diff --git a/.ci/AppImageBuilder.yml b/.ci/AppImageBuilder.yml index 317be2317..22db9f151 100644 --- a/.ci/AppImageBuilder.yml +++ b/.ci/AppImageBuilder.yml @@ -1,26 +1,35 @@ # -# 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. +# 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. +# This file is part of the 86Box distribution. # -# Recipe file for appimage-builder. +# Recipe file for appimage-builder. +# +# build.sh processes conditional comments based on CMakeCache +# options at the end of each line. For example, a line ending in: +# +# # if QT:BOOL=ON +# +# will be removed from the dynamically-generated copy of this +# file if "QT" is not a boolean option set to ON, either through +# a -D definition or the option's default value in CMakeLists. # # -# Authors: RichardG, +# Authors: RichardG, # -# Copyright 2022 RichardG. +# Copyright 2022 RichardG. # version: 1 AppDir: path: ./archive_tmp app_info: - id: !ENV 'net.${project_lower}.${project_lower}' + id: !ENV '${project_id}' name: !ENV '${project}' - icon: !ENV '${project_lower}' + icon: !ENV '${project_icon}' version: !ENV '${project_version}' exec: !ENV 'usr/local/bin/${project}' exec_args: $@ @@ -28,67 +37,60 @@ AppDir: arch: !ENV '${arch_deb}' sources: - sourceline: 'deb http://deb.debian.org/debian bullseye main' - key_url: 'https://ftp-master.debian.org/keys/archive-key-11.asc' + key_url: 'https://keyserver.ubuntu.com/pks/lookup?op=get&search=0x1f89983e0081fde018f3cc9673a4f27b8dd47936' - sourceline: 'deb http://security.debian.org/debian-security bullseye-security main' - key_url: 'https://ftp-master.debian.org/keys/archive-key-11.asc' + key_url: 'https://keyserver.ubuntu.com/pks/lookup?op=get&search=0x1f89983e0081fde018f3cc9673a4f27b8dd47936' - sourceline: 'deb http://deb.debian.org/debian bullseye-updates main' - key_url: 'https://ftp-master.debian.org/keys/archive-key-11-security.asc' + key_url: 'https://keyserver.ubuntu.com/pks/lookup?op=get&search=0xac530d520f2f3269f5e98313a48449044aad5c5d' include: - - libevdev2 - - libfluidsynth2 + - libedit2 # if (CLI:BOOL=ON|QT:BOOL=OFF) + - libevdev2 # if QT:BOOL=ON - libfreetype6 - - libgbm1 - - libgl1 - - libgles2 - - libglvnd0 - - libglx0 + - libgbm1 # if QT:BOOL=ON + - libgl1 # if QT:BOOL=ON + - libgles2 # if QT:BOOL=ON + - libglvnd0 # if QT:BOOL=ON + - libglx0 # if QT:BOOL=ON + - libgomp1 - libgs9 - libpng16-16 - - libqt5core5a - - libqt5gui5 - - libqt5widgets5 + - libqt5core5a # if QT:BOOL=ON + - libqt5gui5 # if QT:BOOL=ON + - libqt5widgets5 # if QT:BOOL=ON + - libsixel1 # if CLI:BOOL=ON - libslirp0 - - libsndio7.0 - - libwayland-client0 - - libx11-6 - - libxcb1 + - libsndio7.0 # if OPENAL:BOOL=ON + - libvdeplug-dev # -dev also pulls in libvdeplug2. -dev is required to get the proper .so symlink to the library + - libx11-6 # if QT:BOOL=ON + - libx11-xcb1 # if QT:BOOL=ON + - libxcb1 # if QT:BOOL=ON + - libxcb-render0 # if QT:BOOL=ON + - libxcb-shape0 # if QT:BOOL=ON + - libxcb-shm0 # if QT:BOOL=ON + - libxcb-xfixes0 # if QT:BOOL=ON + - libxkbcommon-x11-0 # if QT:BOOL=ON + - qtwayland5 # if QT:BOOL=ON - zlib1g files: exclude: - etc - lib/udev - - opt/libc/usr/share - - usr/bin - - usr/include - - usr/lib/*/libasound.so.* - - usr/lib/cmake - - usr/lib/pkgconfig - - usr/sbin - - usr/share/alsa - - usr/share/apport - - usr/share/bug - - usr/share/color - - usr/share/doc - - usr/share/doc-base - - usr/share/fontconfig - - usr/share/fonts - - usr/share/ghostscript - - usr/share/glib-2.0 - - usr/share/info - - usr/share/libinput - - usr/share/libwacom - - usr/share/lintian - - usr/share/locale - - usr/share/man - - usr/share/metainfo - - usr/share/openal - - usr/share/pkgconfig - - usr/share/poppler - - usr/share/readline - - usr/share/rtmidi - - usr/share/sounds - - usr/share/X11 - - usr/share/xml + - usr/[!ls]* # * except lib, local, share + - usr/lib/*/libasound.so.* # using our own ALSA can cause issues, and the API is pretty stable anyway + - usr/lib/*.a # produced by library compilation + - usr/lib/cmake # produced by library compilation + - usr/lib/pkgconfig # produced by library compilation + - usr/s[!h]* # s* except share + - usr/share/[!aim]* # * except applications, icons, metainfo + - usr/share/a[!p]* # a* except applications + - usr/share/ap[!p]* # ap* except applications + - usr/share/app[!l]* # app* except applications + - usr/share/i[!c]* # i* except icons + - usr/share/icons/[!h]* # * except hicolor + - usr/share/icons/h[!i]* # h* except hicolor + - usr/share/m[!e]* # m* except metainfo + - usr/share/metainfo/*.metainfo.xml # metainfo for libraries - var AppImage: arch: !ENV '${arch_appimage}' + file_name: !ENV '${appimage_path}' diff --git a/.ci/Jenkinsfile b/.ci/Jenkinsfile index d1713bb64..a57d3c715 100644 --- a/.ci/Jenkinsfile +++ b/.ci/Jenkinsfile @@ -1,32 +1,37 @@ /* - * 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. + * 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. + * This file is part of the 86Box distribution. * - * Jenkins build pipeline definition. + * Jenkins build pipeline definition. * * * - * Authors: RichardG, + * Authors: RichardG, * - * Copyright 2021 RichardG. + * Copyright 2021-2022 RichardG. */ -def repository = 'https://github.com/86Box/86Box.git' -def commitBrowser = 'https://github.com/86Box/86Box/commit/%s' -def branch = 'master' +/* ['main builds', 'branch builds'] */ +def repository = ['https://github.com/86Box/86Box.git', scm.userRemoteConfigs[0].url] +def commitBrowser = ['https://github.com/86Box/86Box/commit/%s', null] +def branch = ['master', scm.branches[0].name] +def buildType = ['beta', 'alpha'] +def buildBranch = env.JOB_BASE_NAME.contains('-') ? 1 : 0 def osArchs = [ 'Windows': ['32', '64'], - 'Linux': ['x86', 'x86_64', 'arm32', 'arm64'] + 'Linux': ['x86', 'x86_64', 'arm32', 'arm64'], + 'macOS': ['x86_64+x86_64h+arm64'] ] def osFlags = [ - 'Windows': '', - 'Linux': '-D QT=ON' + 'Windows': '-D QT=ON', + 'Linux': '-D QT=ON', + 'macOS': '-D QT=ON' ] def archNames = [ @@ -38,6 +43,12 @@ def archNames = [ 'arm64': 'ARM (64-bit)' ] +def archNamesMac = [ + 'x86_64': 'Intel', + 'arm64': 'Apple Silicon', + 'x86_64+arm64': 'Universal (Intel and Apple Silicon)' +] + def dynarecNames = [ 'ODR': 'Old Recompiler (recommended)', 'NDR': 'New Recompiler (beta)', @@ -50,9 +61,8 @@ def dynarecArchs = [ '64': ['ODR', 'NDR'], 'x86_64': ['ODR', 'NDR'], 'arm32': ['NDR'], - 'ARM32': ['NDR'], 'arm64': ['NDR'], - 'ARM64': ['NDR'] + 'x86_64+arm64': ['ODR', 'NDR'] ] def dynarecFlags = [ @@ -68,8 +78,7 @@ def dynarecSlugs = [ ] def presets = [ - 'Regular', - 'Debug' + 'Regular' ] def presetSlugs = [ @@ -80,58 +89,77 @@ def presetSlugs = [ def presetFlags = [ 'Regular': '-t --preset=regular -D CMAKE_BUILD_TYPE=Release', - 'Debug': '--preset=debug -D CMAKE_BUILD_TYPE=Debug', - 'Dev': '--preset=experimental -D CMAKE_BUILD_TYPE=Debug -D VNC=OFF' + 'Debug': '--preset=debug -D CMAKE_BUILD_TYPE=Debug -D STATIC_BUILD=OFF', + 'Dev': '--preset=experimental -D CMAKE_BUILD_TYPE=Debug -D VNC=OFF -D STATIC_BUILD=OFF' ] -def anyFailure = false - def gitClone(repository, branch) { /* Clean workspace. */ cleanWs() - /* Use stashes to avoid performing multiple clones. */ - if (env.GIT_STASHED != 'true') { - /* Perform clone/checkout. */ - def scmVars = checkout poll: true, - changelog: true, - scm: [$class: 'GitSCM', - branches: [[name: branch]], - userRemoteConfigs: [[url: repository]]] + /* Perform git clone if stashed data isn't available yet, or if + this is not debian.citadel where stash is faster than clone. */ + if (env.GIT_STASHED != 'true' || env.NODE_NAME != 'debian.citadel') { + /* Catch network issues in clone. */ + try { + /* Perform clone/checkout, making sure to set poll and changelog only + once to avoid interference from new commits pushed inbetween clones. */ + def scmVars = checkout(poll: env.GIT_STASHED != 'true', + changelog: env.GIT_STASHED != 'true', + scm: [$class: 'GitSCM', + branches: [[name: branch]], + userRemoteConfigs: [[url: repository]]]) - if (env.GIT_COMMIT == null) { - /* Save the current HEAD commit. */ - env.GIT_COMMIT = scmVars.GIT_COMMIT - } else if (env.GIT_COMMIT != scmVars.GIT_COMMIT) { - /* Checkout the commit read from the polling log. */ - if (isUnix()) - sh "git checkout ${env.GIT_COMMIT} || exit 0" - else - bat "git checkout ${env.GIT_COMMIT} || exit /b 0" + if (env.GIT_COMMIT == null) { + /* Save the current HEAD commit. */ + env.GIT_COMMIT = scmVars.GIT_COMMIT + } else if (env.GIT_COMMIT != scmVars.GIT_COMMIT) { + /* Checkout the commit read from the polling log. */ + if (isUnix()) + sh(returnStatus: true, script: "git checkout ${env.GIT_COMMIT}") + else + bat(returnStatus: true, script: "git checkout ${env.GIT_COMMIT}") + } + println "[-] Using git commit [${env.GIT_COMMIT}]" + + /* Stash data if required, marking it as stashed. */ + if (env.GIT_STASHED != 'true') { + stash(name: 'git', useDefaultExcludes: false) + env.GIT_STASHED = 'true' + } + + /* No need to use stashed data. */ + return; + } catch (e) { + /* If clone fails, use stashed data if available, or re-throw exception otherwise. */ + if (env.GIT_STASHED != 'true') + throw e; } - println "[-] Using git commit [${env.GIT_COMMIT}]" - - /* Stash data and mark it as stashed. */ - stash name: 'git', useDefaultExcludes: false - env.GIT_STASHED = 'true' - } else { - /* Unstash data. */ - unstash name: 'git' } + + /* Unstash data. */ + unstash(name: 'git') } def removeDir(dir) { if (isUnix()) - sh "rm -rf \"$dir\" || exit 0" + return sh(returnStatus: true, script: "rm -rf '$dir'") else - bat "if exist \"$dir\" rd /s /q \"$dir\" & exit /b 0" + return bat(returnStatus: true, script: "rd /s /q \"$dir\"") } def runBuild(args) { if (isUnix()) - sh "chmod u+x \"$WORKSPACE/.ci/build.sh\" && exec \"$WORKSPACE/.ci/build.sh\" $args" + return sh(returnStatus: true, script: "chmod u+x '$WORKSPACE/.ci/build.sh' && exec '$WORKSPACE/.ci/build.sh' $args") else - bat "C:\\msys64\\msys2_shell.cmd -msys2 -defterm -here -no-start -c 'exec \"\$(cygpath -u \\'%WORKSPACE%\\')/.ci/build.sh\" $args'" + return bat(returnStatus: true, script: "C:\\msys64\\msys2_shell.cmd -msys2 -defterm -here -no-start -c 'exec \"\$(cygpath -u \\'%WORKSPACE%\\')/.ci/build.sh\" $args'") +} + +def failStage() { + /* Force this stage to fail. */ + catchError(buildResult: 'FAILURE', stageResult: 'FAILURE') { + def x = 1 / 0 + } } pipeline { @@ -142,24 +170,26 @@ pipeline { } options { - disableConcurrentBuilds() quietPeriod(0) } parameters { string(name: 'BUILD_TYPE', - defaultValue: 'beta', /* !!! CHANGE HERE !!! for build type */ - description: "Build type to pass on to CMake. Should only be changed for one-off builds, otherwise change the default on .ci/Jenkinsfile") + defaultValue: buildType[buildBranch], + description: "Build type to pass on to CMake (on main builds) or feature branch identifier (on branch builds).") } stages { stage('Source Tarball') { agent none + failFast false steps { script { - /* Extract the polled commit from the polling log, so that git checkout can be used - to avoid JENKINS-20518 race conditions caused by two pushes too close together. */ + /* Extract the polled commit from the polling log, so that git checkout + can be used to avoid JENKINS-20518 race conditions caused by the + webhook being triggered more than once in a short period of time. + This is a backup strategy for FilterProxy's webhook queuing. */ node('master') { /* must run on master node to read polling log */ /* Ignore exceptions as this is not really critical. */ try { @@ -178,78 +208,103 @@ pipeline { /* Adding to the above, run a git clone as soon as possible on any node to further avoid race conditions caused by busy node executor delays. */ - node { - /* Run git clone. */ - gitClone(repository, branch) + retry(10) { + node('!Windows') { + /* Run git clone. */ + gitClone(repository[buildBranch], branch[buildBranch]) - /* Clean workspace, in case this is running in a non-build node. */ - cleanWs() + /* Clean workspace, in case this is running in a non-build node. */ + cleanWs() + } + } + + /* Determine build metadata. */ + def buildFlags = "-D \"BUILD_TYPE=$BUILD_TYPE\" -D \"EMU_BUILD=build ${env.BUILD_NUMBER}\" -D \"EMU_BUILD_NUM=${env.BUILD_NUMBER}\"" + def buildSuffix = "-b${env.BUILD_NUMBER}" + if (buildBranch > 0) { + def date = new Date().format("yyyyMMdd") + buildFlags = "-D \"BUILD_TYPE=${buildType[buildBranch]}\" -D \"EMU_BUILD=${env.JOB_BASE_NAME.split('-')[1]} build $date.$BUILD_TYPE\"" + buildSuffix = "-$date-$BUILD_TYPE" } /* Create source tarball. */ - node('Linux') { - try { - /* Run git clone. */ - gitClone(repository, branch) + try { + retry(10) { + node('Linux || macOS') { + /* Run git clone. */ + gitClone(repository[buildBranch], branch[buildBranch]) - /* Switch to temp directory. */ - dir("${env.WORKSPACE_TMP}/output") { - /* Run source tarball creation process. */ - def packageName = "${env.JOB_BASE_NAME}-Source-b${env.BUILD_NUMBER}" - runBuild("-s \"$packageName\"") + /* Switch to temp directory. */ + dir("${env.WORKSPACE_TMP}/output") { + /* Run source tarball creation process. */ + def packageName = "${env.JOB_BASE_NAME}-Source$buildSuffix" + if (runBuild("-s \"$packageName\"") == 0) { + /* Archive resulting artifacts. */ + archiveArtifacts artifacts: "$packageName*" + } else { + /* Fail this stage. */ + failStage() + } + } - /* Archive resulting artifacts. */ - archiveArtifacts artifacts: "$packageName*" - } - - /* Clean up. */ - removeDir("${env.WORKSPACE_TMP}/output") - } catch (e) { - /* Mark that a failure occurred. */ - anyFailure = true - - /* Force this stage to fail. */ - catchError(buildResult: 'SUCCESS', stageResult: 'FAILURE') { - throw e; + /* Clean up. */ + removeDir("${env.WORKSPACE_TMP}/output") } } + } catch (e) { + /* Fail this stage. */ + failStage() } /* Build here to avoid creating a redundant parent stage on the stage view. */ osArchs.each { os, thisOsArchs -> + def combinations = [:] thisOsArchs.each { arch -> - def thisArchDynarecs = dynarecArchs[arch] + def archSlug = arch.replace('+x86_64h', '') /* all instances of arch except the one passed to -b */ + def thisArchDynarecs = dynarecArchs[archSlug.toLowerCase()] if (!thisArchDynarecs) thisArchDynarecs = ['NoDR'] thisArchDynarecs.each { dynarec -> presets.each { preset -> - node(os) { - stage("$os $arch $dynarec $preset") { - try { - /* Run git clone. */ - gitClone(repository, branch) + def combination = "$os $archSlug $dynarec $preset" + combinations[combination] = { + catchError(buildResult: 'FAILURE', stageResult: 'SUCCESS') { + retry(10) { + node(os) { + stage(combination) { + /* Run git clone. */ + gitClone(repository[buildBranch], branch[buildBranch]) - /* Switch to output directory. */ - dir("${env.WORKSPACE_TMP}/output") { - /* Run build process. */ - def packageName = "${env.JOB_BASE_NAME}${dynarecSlugs[dynarec]}${presetSlugs[preset]}-$os-$arch-b${env.BUILD_NUMBER}" - dir("${dynarecNames[dynarec]}/$os - ${archNames[arch]}") { - runBuild("-b \"$packageName\" \"$arch\" ${presetFlags[preset]} ${dynarecFlags[dynarec]} ${osFlags[os]} -D \"BUILD_TYPE=$BUILD_TYPE\" -D \"EMU_BUILD=build ${env.BUILD_NUMBER}\" -D \"EMU_BUILD_NUM=${env.BUILD_NUMBER}\"") + /* Switch to output directory. */ + dir("${env.WORKSPACE_TMP}/output") { + /* Run build process. */ + def packageName = "${env.JOB_BASE_NAME}${dynarecSlugs[dynarec]}${presetSlugs[preset]}-$os-$archSlug$buildSuffix" + def ret = -1 + def archName = archNames[archSlug] + if (os == 'macOS') + archName = archNamesMac[archSlug] + dir(dynarecNames[dynarec]) { + dir("$os - $archName") { + ret = runBuild("-b \"$packageName\" \"$arch\" ${presetFlags[preset]} ${dynarecFlags[dynarec]} ${osFlags[os]} $buildFlags") + if (presets.size() == 1) + writeFile file: '.forcedir', text: '' + } + if ((osArchs.size() == 1) && (thisOsArchs.size() == 1)) + writeFile file: '.forcedir', text: '' + } + + if (ret == 0) { + /* Archive resulting artifacts. */ + archiveArtifacts artifacts: "**/$packageName*, **/.forcedir", defaultExcludes: false + } else { + /* Fail this stage. */ + failStage() + } + } + + /* Clean up. */ + removeDir("${env.WORKSPACE_TMP}/output") } - - /* Archive resulting artifacts. */ - archiveArtifacts artifacts: "**/**/$packageName*" - } - - /* Clean up. */ - removeDir("${env.WORKSPACE_TMP}/output") - } catch (e) { - /* Mark that a failure occurred. */ - anyFailure = true - - /* Force this stage to fail. */ - catchError(buildResult: 'SUCCESS', stageResult: 'FAILURE') { - throw e; } } } @@ -257,6 +312,7 @@ pipeline { } } } + parallel combinations } } } @@ -266,14 +322,8 @@ pipeline { post { always { script { - /* Mark build as failed if any step has failed. */ - if (anyFailure) { - println "[!] Failing build because a build stage failed" - currentBuild.result = 'FAILURE' - } - /* Send out build notifications. */ - if (!env.JOB_BASE_NAME.contains('TestBuildPleaseIgnore')) { + if (commitBrowser[buildBranch]) { try { /* Notify Discord. */ def result = currentBuild.currentResult.toLowerCase() @@ -284,10 +334,10 @@ pipeline { description: "**Status:** ${result}\n\u2060", /* word joiner character forces a blank line */ enableArtifactsList: false, showChangeset: true, - scmWebUrl: commitBrowser + scmWebUrl: commitBrowser[buildBranch] /* Notify IRC, which needs a node for whatever reason. */ - node { + node('citadel || rg || master') { ircNotify() } } catch (e) { diff --git a/.ci/build.sh b/.ci/build.sh old mode 100644 new mode 100755 index 5cd5f3baa..1b1e5825e --- a/.ci/build.sh +++ b/.ci/build.sh @@ -1,18 +1,18 @@ #!/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. +# 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. +# This file is part of the 86Box distribution. # -# Jenkins build script. +# Jenkins build script. # # -# Authors: RichardG, +# Authors: RichardG, # -# Copyright 2021-2022 RichardG. +# Copyright 2021-2023 RichardG. # # @@ -20,30 +20,60 @@ # to produce Jenkins-like builds on your local machine by following these notes: # # - Run build.sh without parameters to see its usage +# - Any boolean CMake definitions (-D ...=ON/OFF) must be ON or OFF to ensure correct behavior # - For Windows (MSYS MinGW) builds: # - Packaging requires 7-Zip on Program Files # - Packaging the Ghostscript DLL requires 32-bit and/or 64-bit Ghostscript on Program Files -# - Packaging the FluidSynth DLL requires it to be at /home/86Box/dll32/libfluidsynth.dll -# and/or /home/86Box/dll64/libfluidsynth64.dll (for 32-bit and 64-bit builds respectively) -# - Packaging the Discord DLL requires wget (MSYS should come with it) +# - Packaging the XAudio2 DLL for FAudio requires it to be at /home/86Box/dll32/xaudio2*.dll +# and/or /home/86Box/dll64/xaudio2*.dll (for 32-bit and 64-bit builds respectively) # - For Linux builds: # - Only Debian and derivatives are supported -# - dpkg and apt-get are called through sudo to manage dependencies +# - dpkg and apt-get are called through sudo to manage dependencies; make sure those +# are configured as NOPASSWD in /etc/sudoers if you're doing unattended builds # - For macOS builds: -# - TBD +# - A standard MacPorts installation is required, with the following macports.conf settings: +# buildfromsource always +# build_arch x86_64 (or arm64) +# universal_archs (blank) +# ui_interactive no +# macosx_deployment_target 10.13 (for x86_64, 10.14 for Qt Vulkan, or 11.0 for arm64) +# - For universal building on Apple Silicon hardware, install native MacPorts on the default +# /opt/local and Intel MacPorts on /opt/intel, then tell build.sh to build for "x86_64+arm64" +# - Qt Vulkan support through MoltenVK requires 10.14 while we target 10.13. We deal with that +# (at least for now) by abusing the x86_64h universal slice to branch Haswell and newer Macs +# into a Vulkan-enabled but 10.14+ binary, with older ones opting for a 10.13-compatible, +# non-Vulkan binary. With this approach, the only machines that miss out on Vulkan despite +# supporting Metal are Ivy Bridge ones as well as GPU-upgraded Mac Pros. For building that +# Vulkan binary, install another Intel MacPorts on /opt/x86_64h, then use the "x86_64h" +# architecture when invoking build.sh (either standalone or as part of an universal build) +# - port and sed are called through sudo to manage dependencies; make sure those are configured +# as NOPASSWD in /etc/sudoers if you're doing unattended builds # # Define common functions. -alias is_windows='[ ! -z "$MSYSTEM" ]' +alias is_windows='[ -n "$MSYSTEM" ]' alias is_mac='uname -s | grep -q Darwin' make_tar() { # Install dependencies. if ! which tar xz > /dev/null 2>&1 then - which apt-get > /dev/null 2>&1 && DEBIAN_FRONTEND=noninteractive sudo apt-get install -y tar xz-utils + if which apt-get > /dev/null 2>&1 + then + sudo apt-get update + DEBIAN_FRONTEND=noninteractive sudo apt-get install -y tar xz-utils + sudo apt-get clean + elif which port > /dev/null 2>&1 + then + sudo port selfupdate + sudo port install gnutar xz + fi fi + # Use MacPorts gnutar (if installed) on macOS. + local tar_cmd=tar + which gnutar > /dev/null 2>&1 && local tar_cmd=gnutar + # Determine the best supported compression type. local compression_flag= local compression_ext= @@ -62,14 +92,14 @@ make_tar() { fi # Make tar verbose if requested. - [ ! -z "$VERBOSE" ] && local compression_flag="$compression_flag -v" + [ -n "$VERBOSE" ] && local compression_flag="$compression_flag -v" # tar is notorious for having many diverging implementations. For instance, # the flags we use to strip UID/GID metadata can be --owner/group (GNU), # --uid/gid (bsdtar) or even none at all (MSYS2 bsdtar). Account for such # flag differences by checking if they're mentioned on the help text. local ownership_flags= - local tar_help=$(tar --help 2>&1) + local tar_help=$("$tar_cmd" --help 2>&1) if echo $tar_help | grep -q -- --owner then local ownership_flags="--owner=0 --group=0" @@ -79,19 +109,33 @@ make_tar() { fi # Run tar. - tar -c $compression_flag -f "$1$compression_ext" $ownership_flags * + "$tar_cmd" -c $compression_flag -f "$1$compression_ext" $ownership_flags * + return $? +} + +cache_dir="$HOME/86box-build-cache" +[ ! -d "$cache_dir" ] && mkdir -p "$cache_dir" +check_buildtag() { + [ -z "$BUILD_TAG" -o "$BUILD_TAG" != "$(cat "$cache_dir/buildtag.$1" 2> /dev/null)" ] + return $? +} +save_buildtag() { + local contents="$BUILD_TAG" + [ -n "$2" ] && local contents="$2" + echo "$contents" > "$cache_dir/buildtag.$1" return $? } # Set common variables. project=86Box -project_lower=86box cwd=$(pwd) # Parse arguments. package_name= arch= tarball_name= +skip_archive=0 +dep_report=0 strip=0 cmake_flags= while [ $# -gt 0 ] @@ -105,6 +149,27 @@ do shift ;; + -n) + shift + skip_archive=1 + ;; + + -p) + shift + + # Check for lddtree and install it if required. + which lddtree > /dev/null || DEBIAN_FRONTEND=noninteractive sudo apt-get -y install pax-utils + + # Default to main binary. + binary="$1" + [ -z "$binary" ] && binary="archive_tmp/usr/local/bin/$project" + + # Run lddtree with AppImage lib directories included in the search path. + LD_LIBRARY_PATH=$(find "$(pwd)/archive_tmp" -type d -name lib -o -name lib64 | while read dir; do find "$dir" -type d; done | tr '\n' ':') \ + lddtree "$binary" + exit $? + ;; + -s) shift tarball_name="$1" @@ -117,29 +182,34 @@ do ;; *) - if echo $1 | grep -q " " - then - cmake_flag="\"$1\"" - else - cmake_flag="$1" - fi - if [ -z "$cmake_flags" ] - then - cmake_flags="$cmake_flag" - else - cmake_flags="$cmake_flags $cmake_flag" - fi - shift + # Consume remaining arguments as CMake flags. + while [ $# -gt 0 ] + do + if echo $1 | grep -q " " + then + cmake_flag="\"$1\"" + else + cmake_flag="$1" + fi + if [ -z "$cmake_flags" ] + then + cmake_flags="$cmake_flag" + else + cmake_flags="$cmake_flags $cmake_flag" + fi + shift + done ;; esac done cmake_flags_extra= # Check if mandatory arguments were specified. -if [ -z "$package_name" -a -z "$tarball_name" ] || [ ! -z "$package_name" -a -z "$arch" ] +if [ -z "$package_name" -a -z "$tarball_name" ] || [ -n "$package_name" -a -z "$arch" ] then echo '[!] Usage: build.sh -b {package_name} {architecture} [-t] [cmake_flags...]' echo ' build.sh -s {source_tarball_name}' + echo 'Dep. tree: build.sh -p [archive_tmp/path/to/binary]' exit 100 fi @@ -147,7 +217,7 @@ fi cd "$(dirname "$0")/.." # Make source tarball if requested. -if [ ! -z "$tarball_name" ] +if [ -n "$tarball_name" ] then echo [-] Making source tarball [$tarball_name] @@ -178,13 +248,18 @@ fi echo [-] Building [$package_name] for [$arch] with flags [$cmake_flags] # Determine CMake toolchain file for this architecture. +toolchain_prefix=flags-gcc +is_mac && toolchain_prefix=llvm-macos case $arch in - 32 | x86) toolchain="flags-gcc-i686";; - 64 | x86_64) toolchain="flags-gcc-x86_64";; - ARM32 | arm32) toolchain="flags-gcc-armv7";; - ARM64 | arm64) toolchain="flags-gcc-aarch64";; - *) toolchain="flags-gcc-$arch";; + 32 | x86) toolchain="$toolchain_prefix-i686";; + 64 | x86_64*) toolchain="$toolchain_prefix-x86_64";; + ARM32 | arm32) toolchain="$toolchain_prefix-armv7";; + ARM64 | arm64) toolchain="$toolchain_prefix-aarch64";; + *) toolchain="$toolchain_prefix-$arch";; esac +[ ! -e "cmake/$toolchain.cmake" ] && toolchain=flags-gcc +toolchain_file="cmake/$toolchain.cmake" +toolchain_file_libs= # Perform platform-specific setup. strip_binary=strip @@ -200,9 +275,10 @@ then # Call build with the correct MSYSTEM. echo [-] Switching to MSYSTEM [$msys] cd "$cwd" - strip_arg= - [ $strip -ne 0 ] && strip_arg="-t " - CHERE_INVOKING=yes MSYSTEM="$msys" bash -lc 'exec "'"$0"'" -b "'"$package_name"'" "'"$arch"'" '"$strip_arg""$cmake_flags" + args= + [ $strip -ne 0 ] && args="-t $args" + [ $skip_archive -ne 0 ] && args="-n $args" + CHERE_INVOKING=yes MSYSTEM="$msys" bash -lc 'exec "'"$0"'" -b "'"$package_name"'" "'"$arch"'" '"$args""$cmake_flags" exit $? fi else @@ -211,12 +287,290 @@ then fi echo [-] Using MSYSTEM [$MSYSTEM] - # Point CMake to the toolchain file. - cmake_flags_extra="$cmake_flags_extra -D \"CMAKE_TOOLCHAIN_FILE=cmake/$toolchain.cmake\"" + # Install dependencies only if we're in a new build and/or architecture. + if check_buildtag "$MSYSTEM" + then + # Update databases and keyring only if we're in a new build. + if check_buildtag pacmansync + then + # Update keyring as well, since the package signing keys sometimes change. + echo [-] Updating package databases and keyring + pacman -Sy --needed --noconfirm msys2-keyring + + # Save build tag to skip pacman sync/keyring later. + save_buildtag pacmansync + else + echo [-] Not updating package databases and keyring again + fi + + # Establish general dependencies. + pkgs="git" + + # Gather installed architecture-specific packages for updating. + # This prevents outdated shared libraries, unmet dependencies + # and potentially other issues caused by the fact pacman doesn't + # update a package's dependencies unless explicitly told to. + pkgs="$pkgs $(pacman -Quq | grep -E "^$MINGW_PACKAGE_PREFIX-")" + + # Establish architecture-specific dependencies. + while read pkg rest + do + pkgs="$pkgs $MINGW_PACKAGE_PREFIX-$(echo "$pkg" | tr -d '\r')" # CR removal required + done < .ci/dependencies_msys.txt + + # Install or update dependencies. + echo [-] Installing dependencies through pacman + if ! pacman -S --needed --noconfirm $pkgs + then + # Install packages individually if installing them all together failed. + for pkg in $pkgs + do + pacman -S --needed --noconfirm "$pkg" + done + fi + + # Clean pacman cache when running under Jenkins to save disk space. + [ "$CI" = "true" ] && rm -rf /var/cache/pacman/pkg + + # 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" + else + echo [-] Not installing dependencies again + fi elif is_mac then # macOS lacks nproc, but sysctl can do the same job. alias nproc='sysctl -n hw.logicalcpu' + + # Handle universal building. + if echo "$arch" | grep -q '+' + then + # Create temporary directory for merging app bundles. + rm -rf archive_tmp_universal + mkdir archive_tmp_universal + + # Build for each architecture. + merge_src= + for arch_universal in $(echo "$arch" | tr '+' ' ') + do + # Run build for the architecture. + args= + [ $strip -ne 0 ] && args="-t $args" + zsh -lc 'exec "'"$0"'" -n -b "universal slice" "'"$arch_universal"'" '"$args""$cmake_flags"' '"$cmake_flags_extra" + status=$? + + if [ $status -eq 0 ] + then + # Move app bundle to the temporary directory. + app_bundle_name="archive_tmp/$(ls archive_tmp | grep '.app$')" + mv "$app_bundle_name" "archive_tmp_universal/$arch_universal.app" + status=$? + + # Merge app bundles. + if [ -z "$merge_src" ] + then + # This is the first bundle, nothing to merge with. + merge_src="$arch_universal" + else + # Merge previous bundle with this one. + merge_dest="$merge_src+$arch_universal" + echo [-] Merging app bundles [$merge_src] and [$arch_universal] into [$merge_dest] + + # Merge directory structures. + (cd "archive_tmp_universal/$merge_src.app" && find . -type d && cd "../../archive_tmp_universal/$arch_universal.app" && find . -type d && cd ../..) | sort > "$cache_dir/universal_listing.txt" + cat "$cache_dir/universal_listing.txt" | uniq | while IFS= read line + do + echo "> Directory: $line" + mkdir -p "archive_tmp_universal/$merge_dest.app/$line" + done + + # Create merged file listing. + (cd "archive_tmp_universal/$merge_src.app" && find . -type f && cd "../../archive_tmp_universal/$arch_universal.app" && find . -type f && cd ../..) | sort > "$cache_dir/universal_listing.txt" + + # Copy files that only exist on one bundle. + cat "$cache_dir/universal_listing.txt" | uniq -u | while IFS= read line + do + if [ -e "archive_tmp_universal/$merge_src.app/$line" ] + then + file_src="$merge_src" + else + file_src="$arch_universal" + fi + echo "> Only on [$file_src]: $line" + cp -p "archive_tmp_universal/$file_src.app/$line" "archive_tmp_universal/$merge_dest.app/$line" + done + + # Copy or lipo files that exist on both bundles. + cat "$cache_dir/universal_listing.txt" | uniq -d | while IFS= read line + do + if cmp -s "archive_tmp_universal/$merge_src.app/$line" "archive_tmp_universal/$arch_universal.app/$line" + then + echo "> Identical: $line" + cp -p "archive_tmp_universal/$merge_src.app/$line" "archive_tmp_universal/$merge_dest.app/$line" + elif lipo -create -output "archive_tmp_universal/$merge_dest.app/$line" "archive_tmp_universal/$merge_src.app/$line" "archive_tmp_universal/$arch_universal.app/$line" 2> /dev/null + then + echo "> Merged: $line" + else + echo "> Copied from [$merge_src]: $line" + cp -p "archive_tmp_universal/$merge_src.app/$line" "archive_tmp_universal/$merge_dest.app/$line" + fi + done + + # Merge symlinks. + (cd "archive_tmp_universal/$merge_src.app" && find . -type l && cd "../../archive_tmp_universal/$arch_universal.app" && find . -type l && cd ../..) | sort > "$cache_dir/universal_listing.txt" + cat "$cache_dir/universal_listing.txt" | uniq | while IFS= read line + do + # Get symlink destinations. + other_link_dest= + if [ -e "archive_tmp_universal/$merge_src.app/$line" ] + then + file_src="$merge_src" + other_link_path="archive_tmp_universal/$arch_universal.app/$line" + if [ -L "$other_link_path" ] + then + other_link_dest="$(readlink "$other_link_path")" + elif [ -e "$other_link_path" ] + then + other_link_dest='[not a symlink]' + fi + else + file_src="$arch_universal" + fi + link_dest="$(readlink "archive_tmp_universal/$file_src.app/$line")" + + # Warn if destinations differ. + if [ -n "$other_link_dest" -a "$link_dest" != "$other_link_dest" ] + then + echo "> Symlink: $line => WARNING: different targets" + echo ">> Using: [$merge_src] $link_dest" + echo ">> Other: [$arch_universal] $other_link_dest" + else + echo "> Symlink: $line => $link_dest" + fi + ln -s "$link_dest" "archive_tmp_universal/$merge_dest.app/$line" + done + + # Merge a subsequent bundle with this one. + merge_src="$merge_dest" + fi + fi + + if [ $status -ne 0 ] + then + echo [!] Aborting universal build: [$arch_universal] failed with status [$status] + exit $status + fi + done + + # Rename final app bundle. + rm -rf archive_tmp + mkdir archive_tmp + mv "archive_tmp_universal/$merge_src.app" "$app_bundle_name" + + # Sign final app bundle. + arch -"$(uname -m)" codesign --force --deep -s - "$app_bundle_name" + + # Create zip. + echo [-] Creating artifact archive + cd archive_tmp + zip --symlinks -r "$cwd/$package_name.zip" . + status=$? + + # Check if the archival succeeded. + if [ $status -ne 0 ] + then + echo [!] Artifact archive creation failed with status [$status] + exit 7 + fi + + # All good. + echo [-] Universal build of [$package_name] for [$arch] with flags [$cmake_flags] successful + exit 0 + fi + + # Switch into the correct architecture if required. + case $arch in + x86_64*) arch_mac="i386"; arch_cmd="x86_64";; + *) arch_mac="$arch"; arch_cmd="$arch";; + esac + if [ "$(arch)" != "$arch" -a "$(arch)" != "$arch_mac" ] + then + # Call build with the correct architecture. + echo [-] Switching to architecture [$arch] + cd "$cwd" + args= + [ $strip -ne 0 ] && args="-t $args" + [ $skip_archive -ne 0 ] && args="-n $args" + arch -"$arch_cmd" zsh -lc 'exec "'"$0"'" -b "'"$package_name"'" "'"$arch"'" '"$args""$cmake_flags" + exit $? + fi + echo [-] Using architecture [$(arch)] + + # Locate the MacPorts prefix. + macports="/opt/local" + [ -e "/opt/$arch/bin/port" ] && macports="/opt/$arch" + [ "$arch" = "x86_64" -a -e "/opt/intel/bin/port" ] && macports="/opt/intel" + export PATH="$macports/bin:$macports/sbin:$macports/libexec/qt5/bin:$PATH" + + # Enable MoltenVK on x86_64h and arm64, but not on x86_64. + # The rationale behind that is explained on the big comment up top. + moltenvk=0 + if [ "$arch" != "x86_64" ] + then + moltenvk=1 + cmake_flags_extra="$cmake_flags_extra -D MOLTENVK=ON -D \"MOLTENVK_INCLUDE_DIR=$macports\"" + fi + + # Install dependencies only if we're in a new build and/or MacPorts prefix. + if check_buildtag "$(basename "$macports")" + then + # Install dependencies. + echo [-] Installing dependencies through MacPorts + sudo "$macports/bin/port" selfupdate + if [ $moltenvk -ne 0 ] + then + # Patch Qt to enable Vulkan support where supported. + qt5_portfile="$macports/var/macports/sources/rsync.macports.org/macports/release/tarballs/ports/aqua/qt5/Portfile" + sudo sed -i -e 's/-no-feature-vulkan/-feature-vulkan/g' "$qt5_portfile" + sudo sed -i -e 's/configure.env-append MAKE=/configure.env-append VULKAN_SDK=${prefix} MAKE=/g' "$qt5_portfile" + fi + while : + do + # Attempt to install dependencies. + sudo "$macports/bin/port" install $(cat .ci/dependencies_macports.txt) 2>&1 | tee macports.log + + # Check for port activation errors. + stuck_dep=$(grep " cannot be built while another version of " macports.log | cut -d" " -f10) + if [ -n "$stuck_dep" ] + then + # Deactivate the stuck dependency and try again. + sudo "$macports/bin/port" -f deactivate "$stuck_dep" + continue + fi + + stuck_dep=$(grep " Please deactivate this port first, or " macports.log | cut -d" " -f5 | tr -d :) + if [ -n "$stuck_dep" ] + then + # Activate the stuck dependency and try again. + sudo "$macports/bin/port" -f activate "$stuck_dep" + continue + fi + + # Stop if no errors were found. + break + done + + # Remove MacPorts error detection log. + rm -f macports.log + + # 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 "$(basename "$macports")" + else + echo [-] Not installing dependencies again + + fi else # Determine Debian architecture. case $arch in @@ -225,96 +579,126 @@ else arm32) arch_deb="armhf";; *) arch_deb="$arch";; esac + grep -q " bullseye " /etc/apt/sources.list || echo [!] WARNING: System not running the expected Debian version # Establish general dependencies. - pkgs="cmake pkg-config git imagemagick wget p7zip-full wayland-protocols tar gzip" + pkgs="cmake ninja-build pkg-config git wget p7zip-full extra-cmake-modules wayland-protocols tar gzip file appstream" if [ "$(dpkg --print-architecture)" = "$arch_deb" ] then pkgs="$pkgs build-essential" else - sudo dpkg --add-architecture $arch_deb + # Add foreign architecture if required. + if ! dpkg --print-foreign-architectures | grep -Fqx "$arch_deb" + then + sudo dpkg --add-architecture "$arch_deb" + + # Force an apt-get update. + save_buildtag aptupdate "arch_$arch_deb" + fi + pkgs="$pkgs crossbuild-essential-$arch_deb" fi # Establish architecture-specific dependencies we don't want listed on the readme... - pkgs="$pkgs linux-libc-dev:$arch_deb extra-cmake-modules:$arch_deb qttools5-dev:$arch_deb qtbase5-private-dev:$arch_deb" + pkgs="$pkgs linux-libc-dev:$arch_deb qttools5-dev:$arch_deb qtbase5-private-dev:$arch_deb" # ...and the ones we do want listed. Non-dev packages fill missing spots on the list. libpkgs="" longest_libpkg=0 - for pkg in libc6-dev libstdc++6 libopenal-dev libfreetype6-dev libx11-dev libsdl2-dev libpng-dev librtmidi-dev qtdeclarative5-dev libwayland-dev libevdev-dev libglib2.0-dev libslirp-dev + for pkg in libc6-dev libstdc++6 libopenal-dev libfreetype6-dev libx11-dev libsdl2-dev libpng-dev librtmidi-dev qtdeclarative5-dev libwayland-dev libevdev-dev libxkbcommon-x11-dev libglib2.0-dev libslirp-dev libfaudio-dev libaudio-dev libjack-jackd2-dev libpipewire-0.3-dev libsamplerate0-dev libsndio-dev libvdeplug-dev libfluidsynth-dev do libpkgs="$libpkgs $pkg:$arch_deb" length=$(echo -n $pkg | sed 's/-dev$//' | sed "s/qtdeclarative/qt/" | wc -c) [ $length -gt $longest_libpkg ] && longest_libpkg=$length done - # Determine GNU toolchain architecture. + # Determine toolchain architecture triplet. case $arch in - x86) arch_gnu="i686-linux-gnu";; - arm32) arch_gnu="arm-linux-gnueabihf";; - arm64) arch_gnu="aarch64-linux-gnu";; - *) arch_gnu="$arch-linux-gnu";; + x86) arch_triplet="i686-linux-gnu";; + arm32) arch_triplet="arm-linux-gnueabihf";; + arm64) arch_triplet="aarch64-linux-gnu";; + *) arch_triplet="$arch-linux-gnu";; esac # Determine library directory name for this architecture. case $arch in x86) libdir="i386-linux-gnu";; - *) libdir="$arch_gnu";; + *) libdir="$arch_triplet";; esac - # Create CMake toolchain file. - cat << EOF > toolchain.cmake + # Create CMake cross toolchain file. + toolchain_file_new="$cache_dir/toolchain.$arch_deb.cmake" + cat << EOF > "$toolchain_file_new" set(CMAKE_SYSTEM_NAME Linux) set(CMAKE_SYSTEM_PROCESSOR $arch) -set(CMAKE_AR $arch_gnu-ar) -set(CMAKE_ASM_COMPILER $arch_gnu-gcc) -set(CMAKE_C_COMPILER $arch_gnu-gcc) -set(CMAKE_CXX_COMPILER $arch_gnu-g++) -set(CMAKE_LINKER $arch_gnu-ld) -set(CMAKE_OBJCOPY $arch_gnu-objcopy) -set(CMAKE_RANLIB $arch_gnu-ranlib) -set(CMAKE_SIZE $arch_gnu-size) -set(CMAKE_STRIP $arch_gnu-strip) +set(CMAKE_AR $arch_triplet-ar) +set(CMAKE_ASM_COMPILER $arch_triplet-gcc) +set(CMAKE_C_COMPILER $arch_triplet-gcc) +set(CMAKE_CXX_COMPILER $arch_triplet-g++) +set(CMAKE_LINKER $arch_triplet-ld) +set(CMAKE_OBJCOPY $arch_triplet-objcopy) +set(CMAKE_RANLIB $arch_triplet-ranlib) +set(CMAKE_SIZE $arch_triplet-size) +set(CMAKE_STRIP $arch_triplet-strip) set(CMAKE_FIND_ROOT_PATH_MODE_PROGRAM NEVER) set(CMAKE_FIND_ROOT_PATH_MODE_LIBRARY ONLY) set(CMAKE_FIND_ROOT_PATH_MODE_INCLUDE ONLY) set(ENV{PKG_CONFIG_PATH} "") -set(ENV{PKG_CONFIG_LIBDIR} "/usr/lib/$libdir/pkgconfig:/usr/share/$libdir/pkgconfig") +set(ENV{PKG_CONFIG_LIBDIR} "/usr/lib/$libdir/pkgconfig:/usr/share/$libdir/pkgconfig:/usr/share/pkgconfig") -include("$(pwd)/cmake/$toolchain.cmake") +include("$(realpath "$toolchain_file")") EOF - cmake_flags_extra="$cmake_flags_extra -D CMAKE_TOOLCHAIN_FILE=toolchain.cmake" - strip_binary="$arch_gnu-strip" + toolchain_file="$toolchain_file_new" + strip_binary="$arch_triplet-strip" - # Install or update dependencies. - echo [-] Installing dependencies through apt - sudo apt-get update - DEBIAN_FRONTEND=noninteractive sudo apt-get -y install $pkgs $libpkgs - sudo apt-get clean + # Create a separate toolchain file for library compilation without including + # our own toolchain files, letting libraries set their own C(XX)FLAGS instead. + # The file is saved on a fixed location, since running CMake again on a library + # we've already built before will *not* update its toolchain file path; therefore, + # we cannot point them to our working directory, which may change across builds. + toolchain_file_libs="$cache_dir/toolchain.$arch_deb.libs.cmake" + grep -Ev "^include\(" "$toolchain_file" > "$toolchain_file_libs" - # Link against the system libslirp instead of compiling ours. - cmake_flags_extra="$cmake_flags_extra -D SLIRP_EXTERNAL=ON" + # Install dependencies only if we're in a new build and/or architecture. + if check_buildtag "$arch_deb" + then + # Install or update dependencies. + echo [-] Installing dependencies through apt + if check_buildtag aptupdate + then + sudo apt-get update + + # Save build tag to skip apt-get update later, unless a new architecture + # is added to dpkg, in which case, this saved tag file gets replaced. + save_buildtag aptupdate + fi + DEBIAN_FRONTEND=noninteractive sudo apt-get -y install $pkgs $libpkgs + sudo apt-get clean + + # 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 "$arch_deb" + else + echo [-] Not installing dependencies again + fi fi +# Point CMake to the toolchain file. +[ -e "$toolchain_file" ] && cmake_flags_extra="$cmake_flags_extra -D \"CMAKE_TOOLCHAIN_FILE=$toolchain_file\"" + # Clean workspace. echo [-] Cleaning workspace -if [ -d "build" ] -then - MAKEFLAGS=-j$(nproc) cmake --build build --target clean 2> /dev/null - rm -rf build -fi -find . \( -name Makefile -o -name CMakeCache.txt -o -name CMakeFiles \) -exec rm -rf "{}" \; 2> /dev/null +rm -rf build # Add ARCH to skip the arch_detect process. case $arch in 32 | x86) cmake_flags_extra="$cmake_flags_extra -D ARCH=i386";; - 64 | x86_64) cmake_flags_extra="$cmake_flags_extra -D ARCH=x86_64";; - ARM32 | arm32) cmake_flags_extra="$cmake_flags_extra -D ARCH=arm";; - ARM64 | arm64) cmake_flags_extra="$cmake_flags_extra -D ARCH=arm64";; + 64 | x86_64*) cmake_flags_extra="$cmake_flags_extra -D ARCH=x86_64";; + ARM32 | arm32) cmake_flags_extra="$cmake_flags_extra -D ARCH=arm -D NEW_DYNAREC=ON";; + ARM64 | arm64) cmake_flags_extra="$cmake_flags_extra -D ARCH=arm64 -D NEW_DYNAREC=ON";; *) cmake_flags_extra="$cmake_flags_extra -D \"ARCH=$arch\"";; esac @@ -324,20 +708,20 @@ if [ "$CI" = "true" ] then # Backup strategy when running under Jenkins. [ -z "$git_hash" ] && git_hash=$(echo $GIT_COMMIT | cut -c 1-8) -elif [ ! -z "$git_hash" ] +elif [ -n "$git_hash" ] then # Append + to denote a dirty tree. git diff --quiet 2> /dev/null || git_hash="$git_hash+" fi -[ ! -z "$git_hash" ] && cmake_flags_extra="$cmake_flags_extra -D \"EMU_GIT_HASH=$git_hash\"" +[ -n "$git_hash" ] && cmake_flags_extra="$cmake_flags_extra -D \"EMU_GIT_HASH=$git_hash\"" # Add copyright year. year=$(date +%Y) -[ ! -z "$year" ] && cmake_flags_extra="$cmake_flags_extra -D \"EMU_COPYRIGHT_YEAR=$year\"" +[ -n "$year" ] && cmake_flags_extra="$cmake_flags_extra -D \"EMU_COPYRIGHT_YEAR=$year\"" # Run CMake. echo [-] Running CMake with flags [$cmake_flags $cmake_flags_extra] -eval cmake -G \"Unix Makefiles\" -B build $cmake_flags $cmake_flags_extra . +eval cmake -G Ninja $cmake_flags $cmake_flags_extra -S . -B build status=$? if [ $status -ne 0 ] then @@ -345,35 +729,57 @@ then exit 3 fi -# Run actual build. -make_flags=-j$(nproc) -echo [-] Running build with make flags [$make_flags] -MAKEFLAGS=$make_flags cmake --build build -status=$? -if [ $status -ne 0 ] +# Run actual build, unless we're running a dry build to precondition a node. +if [ "$BUILD_TAG" != "precondition" ] then - echo [!] Make failed with status [$status] - exit 4 + echo [-] Running build + cmake --build build -j$(nproc) + status=$? + if [ $status -ne 0 ] + then + echo [!] Build failed with status [$status] + exit 4 + fi +else + # Copy dummy binary into place. + echo [-] Preconditioning build node + mkdir -p build/src + if is_windows + then + cp "$(which cp)" "build/src/$project.exe" + elif is_mac + then + : # Special check during app bundle generation. + else + cp "$(which cp)" "build/src/$project" + fi fi -# Download Discord Game SDK from their CDN if necessary. -if [ ! -e "discord_game_sdk.zip" ] +# Download Discord Game SDK from their CDN if we're in a new build. +discord_version="3.2.1" +discord_zip="$cache_dir/discord_game_sdk-$discord_version.zip" +if [ ! -e "$discord_zip" ] then + # Download file. echo [-] Downloading Discord Game SDK - wget -qO discord_game_sdk.zip "https://dl-game-sdk.discordapp.net/2.5.6/discord_game_sdk.zip" + rm -f "$cache_dir/discord_game_sdk"* # remove old versions + wget -qO "$discord_zip" "https://dl-game-sdk.discordapp.net/$discord_version/discord_game_sdk.zip" status=$? if [ $status -ne 0 ] then echo [!] Discord Game SDK download failed with status [$status] - rm -f discord_game_sdk.zip + rm -f "$discord_zip" fi +else + echo [-] Not downloading Discord Game SDK again fi # Determine Discord Game SDK architecture. case $arch in - 32) arch_discord="x86";; - 64) arch_discord="x86_64";; - *) arch_discord="$arch";; + 32) arch_discord="x86";; + 64 | x86_64*) arch_discord="x86_64";; + arm64 | ARM64) arch_discord="aarch64";; + *) arch_discord="$arch";; esac # Create temporary directory for archival. @@ -397,9 +803,6 @@ then sevenzip="$pf/7-Zip/7z.exe" [ "$arch" = "32" -a -d "/c/Program Files (x86)" ] && pf="/c/Program Files (x86)" - # Archive freetype from local MSYS installation. - .ci/static2dll.sh -p freetype2 /$MSYSTEM/lib/libfreetype.a archive_tmp/freetype.dll - # Archive Ghostscript DLL from local official distribution installation. for gs in "$pf"/gs/gs*.*.* do @@ -407,11 +810,11 @@ then done # Archive Discord Game SDK DLL. - "$sevenzip" e -y -o"archive_tmp" discord_game_sdk.zip "lib/$arch_discord/discord_game_sdk.dll" + "$sevenzip" e -y -o"archive_tmp" "$discord_zip" "lib/$arch_discord/discord_game_sdk.dll" [ ! -e "archive_tmp/discord_game_sdk.dll" ] && echo [!] No Discord Game SDK for architecture [$arch_discord] - # Archive other DLLs from local directory. - cp -p "/home/$project/dll$arch/"* archive_tmp/ + # Archive XAudio2 DLL if required. + grep -q "OPENAL:BOOL=ON" build/CMakeCache.txt || cp -p "/home/$project/dll$arch/xaudio2"* archive_tmp/ # Archive executable, while also stripping it if requested. if [ $strip -ne 0 ] @@ -424,60 +827,192 @@ then fi elif is_mac then - # TBD - : + # Archive app bundle with libraries. + cmake_flags_install= + [ $strip -ne 0 ] && cmake_flags_install="$cmake_flags_install --strip" + cmake --install build --prefix "$(pwd)/archive_tmp" $cmake_flags_install + status=$? + + if [ $status -eq 0 ] + then + # Archive Discord Game SDK library. + unzip -j "$discord_zip" "lib/$arch_discord/discord_game_sdk.dylib" -d "archive_tmp/"*".app/Contents/Frameworks" + [ ! -e "archive_tmp/"*".app/Contents/Frameworks/discord_game_sdk.dylib" ] && echo [!] No Discord Game SDK for architecture [$arch_discord] + + # Hack to convert x86_64 binaries to x86_64h when building that architecture. + if [ "$arch" = "x86_64h" ] + then + find archive_tmp -type f | while IFS= read line + do + # Parse and patch a fat header (0xCAFEBABE, big endian) first. + macho_offset=0 + if [ "$(dd if="$line" bs=1 count=4 status=none)" = "$(printf '\xCA\xFE\xBA\xBE')" ] + then + # Get the number of fat architectures. + fat_archs=$(($(dd if="$line" bs=1 skip=4 count=4 status=none | rev | tr -d '\n' | od -An -vtu4))) + + # Go through fat architectures. + fat_offset=8 + for fat_arch in $(seq 1 $fat_archs) + do + # Check CPU type. + if [ "$(dd if="$line" bs=1 skip=$fat_offset count=4 status=none)" = "$(printf '\x01\x00\x00\x07')" ] + then + # Change CPU subtype in the fat header from ALL (0x00000003) to H (0x00000008). + printf '\x00\x00\x00\x08' | dd of="$line" bs=1 seek=$((fat_offset + 4)) count=4 conv=notrunc status=none + + # Save offset for this architecture's Mach-O header. + macho_offset=$(($(dd if="$line" bs=1 skip=$((fat_offset + 8)) count=4 status=none | rev | tr -d '\n' | od -An -vtu4))) + + # Stop looking for the x86_64 slice. + break + fi + + # Move on to the next architecture. + fat_offset=$((fat_offset + 20)) + done + fi + + # Now patch a 64-bit Mach-O header (0xFEEDFACF, little endian), either at + # the beginning or as a sub-header within a fat binary as parsed above. + if [ "$(dd if="$line" bs=1 skip=$macho_offset count=8 status=none)" = "$(printf '\xCF\xFA\xED\xFE\x07\x00\x00\x01')" ] + then + # Change CPU subtype in the Mach-O header from ALL (0x00000003) to H (0x00000008). + printf '\x08\x00\x00\x00' | dd of="$line" bs=1 seek=$((macho_offset + 8)) count=4 conv=notrunc status=none + fi + done + fi + + # Sign app bundle, unless we're in an universal build. + [ $skip_archive -eq 0 ] && codesign --force --deep -s - "archive_tmp/"*".app" + elif [ "$BUILD_TAG" = "precondition" ] + then + # Continue with no app bundle on a dry build. + status=0 + fi else - cwd_root=$(pwd) + cwd_root="$(pwd)" + check_buildtag "libs.$arch_deb" - # Build openal-soft 1.21.1 manually to fix audio issues. This is a temporary - # workaround until a newer version of openal-soft trickles down to Debian repos. - if [ -d "openal-soft-1.21.1" ] + if grep -q "OPENAL:BOOL=ON" build/CMakeCache.txt then - rm -rf openal-soft-1.21.1/build/* + # Build openal-soft 1.23.1 manually to fix audio issues. This is a temporary + # workaround until a newer version of openal-soft trickles down to Debian repos. + prefix="$cache_dir/openal-soft-1.23.1" + if [ ! -d "$prefix" ] + then + rm -rf "$cache_dir/openal-soft-"* # remove old versions + wget -qO - https://github.com/kcat/openal-soft/archive/refs/tags/1.23.1.tar.gz | tar zxf - -C "$cache_dir" || rm -rf "$prefix" + fi + + # Patches to build with the old PipeWire version in Debian. + sed -i -e 's/>=0.3.23//' "$prefix/CMakeLists.txt" + sed -i -e 's/PW_KEY_CONFIG_NAME/"config.name"/g' "$prefix/alc/backends/pipewire.cpp" + + prefix_build="$prefix/build-$arch_deb" + cmake -G Ninja -D "CMAKE_TOOLCHAIN_FILE=$toolchain_file_libs" -D "CMAKE_INSTALL_PREFIX=$cwd_root/archive_tmp/usr" -S "$prefix" -B "$prefix_build" || exit 99 + cmake --build "$prefix_build" -j$(nproc) || exit 99 + cmake --install "$prefix_build" || exit 99 + + # Build SDL2 without sound systems. + sdl_ss=OFF else - wget -qO - https://github.com/kcat/openal-soft/archive/refs/tags/1.21.1.tar.gz | tar zxf - - fi - cd openal-soft-1.21.1/build - [ -e Makefile ] && make clean - cmake -G "Unix Makefiles" -D "CMAKE_TOOLCHAIN_FILE=$cwd_root/toolchain.cmake" -D "CMAKE_INSTALL_PREFIX=$cwd_root/archive_tmp/usr" .. - make -j$(nproc) install || exit 99 - cd "$cwd_root" + # Build FAudio 22.03 manually to remove the dependency on GStreamer. This is a temporary + # workaround until a newer version of FAudio trickles down to Debian repos. + prefix="$cache_dir/FAudio-22.03" + if [ ! -d "$prefix" ] + then + rm -rf "$cache_dir/FAudio-"* # remove old versions + wget -qO - https://github.com/FNA-XNA/FAudio/archive/refs/tags/22.03.tar.gz | tar zxf - -C "$cache_dir" || rm -rf "$prefix" + fi + prefix_build="$prefix/build-$arch_deb" + cmake -G Ninja -D "CMAKE_TOOLCHAIN_FILE=$toolchain_file_libs" -D "CMAKE_INSTALL_PREFIX=$cwd_root/archive_tmp/usr" -S "$prefix" -B "$prefix_build" || exit 99 + cmake --build "$prefix_build" -j$(nproc) || exit 99 + cmake --install "$prefix_build" || exit 99 - # Build rtmidi without JACK support to remove the dependency on libjack. - if [ -d "rtmidi-4.0.0" ] - then - rm -rf rtmidi-4.0.0/CMakeCache.txt rtmidi-4.0.0/CMakeFiles - else - wget -qO - http://www.music.mcgill.ca/~gary/rtmidi/release/rtmidi-4.0.0.tar.gz | tar zxf - + # Build SDL2 with sound systems. + sdl_ss=ON fi - cwd_root=$(pwd) - cd rtmidi-4.0.0 - [ -e Makefile ] && make clean - cmake -G "Unix Makefiles" -D RTMIDI_API_JACK=OFF -D "CMAKE_TOOLCHAIN_FILE=$cwd_root/toolchain.cmake" -D "CMAKE_INSTALL_PREFIX=$cwd_root/archive_tmp/usr" . - make -j$(nproc) install || exit 99 - cd "$cwd_root" - # Build SDL2 for joystick support with most components disabled to remove the dependencies on PulseAudio and libdrm. - if [ ! -d "SDL2-2.0.20" ] + # Build SDL2 with video systems (and dependencies) only if the SDL interface is used. + sdl_ui=OFF + grep -qiE "^QT:BOOL=ON" build/CMakeCache.txt || sdl_ui=ON + + # Build rtmidi without JACK support to remove the dependency on libjack, as + # the Debian libjack is very likely to be incompatible with the system jackd. + prefix="$cache_dir/rtmidi-4.0.0" + if [ ! -d "$prefix" ] then - wget -qO - https://www.libsdl.org/release/SDL2-2.0.20.tar.gz | tar zxf - + rm -rf "$cache_dir/rtmidi-"* # remove old versions + wget -qO - https://github.com/thestk/rtmidi/archive/refs/tags/4.0.0.tar.gz | tar zxf - -C "$cache_dir" || rm -rf "$prefix" fi - rm -rf sdlbuild - mkdir sdlbuild - cd sdlbuild - cmake -G "Unix Makefiles" -D SDL_DISKAUDIO=OFF -D SDL_DIRECTFB_SHARED=OFF -D SDL_OPENGL=OFF -D SDL_OPENGLES=OFF -D SDL_OSS=OFF -D SDL_ALSA=OFF \ - -D SDL_ALSA_SHARED=OFF -D SDL_JACK=OFF -D SDL_JACK_SHARED=OFF -D SDL_ESD=OFF -D SDL_ESD_SHARED=OFF -D SDL_PIPEWIRE=OFF -D SDL_PIPEWIRE_SHARED=OFF \ - -D SDL_PULSEAUDIO=OFF -D SDL_PULSEAUDIO_SHARED=OFF -D SDL_ARTS=OFF -D SDL_ARTS_SHARED=OFF -D SDL_NAS=OFF -D SDL_NAS_SHARED=OFF -D SDL_SNDIO=OFF \ - -D SDL_SNDIO_SHARED=OFF -D SDL_FUSIONSOUND=OFF -D SDL_FUSIONSOUND_SHARED=OFF -D SDL_LIBSAMPLERATE=OFF -D SDL_LIBSAMPLERATE_SHARED=OFF -D SDL_X11=OFF \ - -D SDL_X11_SHARED=OFF -D SDL_WAYLAND=OFF -D SDL_WAYLAND_SHARED=OFF -D SDL_WAYLAND_LIBDECOR=OFF -D SDL_WAYLAND_LIBDECOR_SHARED=OFF \ - -D SDL_WAYLAND_QT_TOUCH=OFF -D SDL_RPI=OFF -D SDL_VIVANTE=OFF -D SDL_VULKAN=OFF -D SDL_KMSDRM=OFF -D SDL_KMSDRM_SHARED=OFF -D SDL_OFFSCREEN=OFF \ - -D SDL_HIDAPI_JOYSTICK=ON -D SDL_VIRTUAL_JOYSTICK=ON -D SDL_SHARED=ON -D SDL_STATIC=OFF -S "$cwd_root/SDL2-2.0.20" \ - -D "CMAKE_TOOLCHAIN_FILE=$cwd_root/toolchain.cmake" -D "CMAKE_INSTALL_PREFIX=$cwd_root/archive_tmp/usr" - make -j$(nproc) install || exit 99 - cd "$cwd_root" + prefix_build="$prefix/build-$arch_deb" + cmake -G Ninja -D RTMIDI_API_JACK=OFF -D "CMAKE_TOOLCHAIN_FILE=$toolchain_file_libs" -D "CMAKE_INSTALL_PREFIX=$cwd_root/archive_tmp/usr" -S "$prefix" -B "$prefix_build" || exit 99 + cmake --build "$prefix_build" -j$(nproc) || exit 99 + cmake --install "$prefix_build" || exit 99 + + # Build FluidSynth without sound systems to remove the dependencies on libjack + # and other sound system libraries. We don't output audio through FluidSynth. + prefix="$cache_dir/fluidsynth-2.3.0" + if [ ! -d "$prefix" ] + then + rm -rf "$cache_dir/fluidsynth-"* # remove old versions + wget -qO - https://github.com/FluidSynth/fluidsynth/archive/refs/tags/v2.3.0.tar.gz | tar zxf - -C "$cache_dir" || rm -rf "$prefix" + fi + prefix_build="$prefix/build-$arch_deb" + cmake -G Ninja -D enable-dbus=OFF -D enable-jack=OFF -D enable-oss=OFF -D enable-sdl2=OFF -D enable-pulseaudio=OFF -D enable-pipewire=OFF -D enable-alsa=OFF \ + -D "CMAKE_TOOLCHAIN_FILE=$toolchain_file_libs" -D "CMAKE_INSTALL_PREFIX=$cwd_root/archive_tmp/usr" \ + -S "$prefix" -B "$prefix_build" || exit 99 + cmake --build "$prefix_build" -j$(nproc) || exit 99 + cmake --install "$prefix_build" || exit 99 + + # Build SDL2 for joystick and FAudio support, with most components + # disabled to remove the dependencies on PulseAudio and libdrm. + prefix="$cache_dir/SDL2-2.0.20" + if [ ! -d "$prefix" ] + then + rm -rf "$cache_dir/SDL2-"* # remove old versions + wget -qO - https://www.libsdl.org/release/SDL2-2.0.20.tar.gz | tar zxf - -C "$cache_dir" || rm -rf "$prefix" + fi + prefix_build="$cache_dir/SDL2-2.0.20-build-$arch_deb" + cmake -G Ninja -D SDL_SHARED=ON -D SDL_STATIC=OFF \ + \ + -D SDL_AUDIO=$sdl_ss -D SDL_DUMMYAUDIO=$sdl_ss -D SDL_DISKAUDIO=OFF -D SDL_OSS=OFF -D SDL_ALSA=$sdl_ss -D SDL_ALSA_SHARED=$sdl_ss \ + -D SDL_JACK=$sdl_ss -D SDL_JACK_SHARED=$sdl_ss -D SDL_ESD=OFF -D SDL_ESD_SHARED=OFF -D SDL_PIPEWIRE=$sdl_ss \ + -D SDL_PIPEWIRE_SHARED=$sdl_ss -D SDL_PULSEAUDIO=$sdl_ss -D SDL_PULSEAUDIO_SHARED=$sdl_ss -D SDL_ARTS=OFF -D SDL_ARTS_SHARED=OFF \ + -D SDL_NAS=$sdl_ss -D SDL_NAS_SHARED=$sdl_ss -D SDL_SNDIO=$sdl_ss -D SDL_SNDIO_SHARED=$sdl_ss -D SDL_FUSIONSOUND=OFF \ + -D SDL_FUSIONSOUND_SHARED=OFF -D SDL_LIBSAMPLERATE=$sdl_ss -D SDL_LIBSAMPLERATE_SHARED=$sdl_ss \ + \ + -D SDL_VIDEO=$sdl_ui -D SDL_X11=$sdl_ui -D SDL_X11_SHARED=$sdl_ui -D SDL_WAYLAND=$sdl_ui -D SDL_WAYLAND_SHARED=$sdl_ui \ + -D SDL_WAYLAND_LIBDECOR=$sdl_ui -D SDL_WAYLAND_LIBDECOR_SHARED=$sdl_ui -D SDL_WAYLAND_QT_TOUCH=OFF -D SDL_RPI=OFF -D SDL_VIVANTE=OFF \ + -D SDL_VULKAN=OFF -D SDL_KMSDRM=$sdl_ui -D SDL_KMSDRM_SHARED=$sdl_ui -D SDL_OFFSCREEN=$sdl_ui -D SDL_RENDER=$sdl_ui \ + \ + -D SDL_JOYSTICK=ON -D SDL_HIDAPI_JOYSTICK=ON -D SDL_VIRTUAL_JOYSTICK=ON \ + \ + -D SDL_ATOMIC=OFF -D SDL_EVENTS=ON -D SDL_HAPTIC=OFF -D SDL_POWER=OFF -D SDL_THREADS=ON -D SDL_TIMERS=ON -D SDL_FILE=OFF \ + -D SDL_LOADSO=ON -D SDL_CPUINFO=ON -D SDL_FILESYSTEM=$sdl_ui -D SDL_DLOPEN=OFF -D SDL_SENSOR=OFF -D SDL_LOCALE=OFF \ + \ + -D "CMAKE_TOOLCHAIN_FILE=$toolchain_file_libs" -D "CMAKE_INSTALL_PREFIX=$cwd_root/archive_tmp/usr" \ + -S "$prefix" -B "$prefix_build" || exit 99 + cmake --build "$prefix_build" -j$(nproc) || exit 99 + cmake --install "$prefix_build" || exit 99 + + # We rely on the host to provide Vulkan libs to sidestep any potential + # dependency issues. While Qt expects libvulkan.so, at least Debian only + # ships libvulkan.so.1 without a symlink, so make our own as a workaround. + # The relative paths prevent appimage-builder from flattening the links. + mkdir -p "archive_tmp/usr/lib/$libdir" + relroot="../../../../../../../../../../../../../../../../../../../../../../../../../../../../.." + ln -s "$relroot/usr/lib/libvulkan.so.1" "archive_tmp/usr/lib/libvulkan.so" + ln -s "$relroot/usr/lib/$libdir/libvulkan.so.1" "archive_tmp/usr/lib/$libdir/libvulkan.so" + + # The FluidSynth packaged by Debian bullseye is ABI incompatible with + # the newer version we compile, despite sharing a major version. Since we + # don't run into the one breaking ABI change they made, just symlink it. + ln -s "$(readlink "archive_tmp/usr/lib/libfluidsynth.so.3")" "archive_tmp/usr/lib/libfluidsynth.so.2" # Archive Discord Game SDK library. - 7z e -y -o"archive_tmp/usr/lib" discord_game_sdk.zip "lib/$arch_discord/discord_game_sdk.so" + 7z e -y -o"archive_tmp/usr/lib" "$discord_zip" "lib/$arch_discord/discord_game_sdk.so" [ ! -e "archive_tmp/usr/lib/discord_game_sdk.so" ] && echo [!] No Discord Game SDK for architecture [$arch_discord] # Archive readme with library package versions. @@ -491,11 +1026,24 @@ else echo $pkg $version >> archive_tmp/README done - # Archive icon, while also shrinking it to 512x512 if necessary. - convert src/win/assets/$project_lower.png -resize '512x512>' icon.png - icon_base="$(identify -format 'archive_tmp/usr/share/icons/%wx%h' icon.png)" - mkdir -p "$icon_base" - mv icon.png "$icon_base/$project_lower.png" + # Archive metadata. + project_id=$(ls src/unix/assets/*.*.xml | head -1 | grep -oP '/\K([^/]+)(?=\.[^\.]+\.[^\.]+$)') + metainfo_base=archive_tmp/usr/share/metainfo + mkdir -p "$metainfo_base" + cp -p "src/unix/assets/$project_id."*".xml" "$metainfo_base/$project_id.appdata.xml" + applications_base=archive_tmp/usr/share/applications + mkdir -p "$applications_base" + cp -p "src/unix/assets/$project_id.desktop" "$applications_base/" + + # Archive icons. + icon_base=archive_tmp/usr/share/icons/hicolor + for icon_size in src/unix/assets/[0-9]*x[0-9]* + do + icon_dir="$icon_base/$(basename "$icon_size")" + mkdir -p "$icon_dir" + cp -rp "$icon_size" "$icon_dir/apps" + done + project_icon=$(find "$icon_base/"[0-9]*x[0-9]*/* -type f -name '*.png' -o -name '*.svg' | head -1 | grep -oP '/\K([^/]+)(?=\.[^\.]+$)') # Archive executable, while also stripping it if requested. mkdir -p archive_tmp/usr/local/bin @@ -516,6 +1064,13 @@ then exit 6 fi +# Stop if artifact archive creation was disabled. +if [ $skip_archive -ne 0 ] +then + echo [-] Skipping artifact archive creation + exit 0 +fi + # Produce artifact archive. echo [-] Creating artifact archive if is_windows @@ -526,8 +1081,10 @@ then status=$? elif is_mac then - # TBD - : + # Create zip. + cd archive_tmp + zip --symlinks -r "$cwd/$package_name.zip" . + status=$? else # Determine AppImage runtime architecture. case $arch in @@ -538,32 +1095,85 @@ else esac # Get version for AppImage metadata. - project_version=$(grep -oP '#define\s+EMU_VERSION\s+"\K([^"]+)' "build/src/include/$project_lower/version.h" 2> /dev/null) + project_version=$(grep -oP '#define\s+EMU_VERSION\s+"\K([^"]+)' "build/src/include/"*"/version.h" 2> /dev/null) [ -z "$project_version" ] && project_version=unknown - build_num=$(grep -oP '#define\s+EMU_BUILD_NUM\s+\K([0-9]+)' "build/src/include/$project_lower/version.h" 2> /dev/null) - [ ! -z "$build_num" -a "$build_num" != "0" ] && project_version="$project_version-b$build_num" + build_num=$(grep -oP '#define\s+EMU_BUILD_NUM\s+\K([0-9]+)' "build/src/include/"*"/version.h" 2> /dev/null) + [ -n "$build_num" -a "$build_num" != "0" ] && project_version="$project_version-b$build_num" + + # Generate modified AppImage metadata to suit build requirements. + cat << EOF > AppImageBuilder-generated.yml +# This file is automatically generated by .ci/build.sh and will be +# overwritten if edited. Please edit .ci/AppImageBuilder.yml instead. +EOF + while IFS= read line + do + # Skip blank or comment lines. + echo "$line" | grep -qE '^(#|$)' && continue + + # Parse "# if OPTION:TYPE=VALUE" CMake condition lines. + condition=$(echo "$line" | grep -oP '# if \K(.+)') + if [ -n "$condition" ] + then + # Skip line if the condition is not matched. + grep -qiE "^$condition" build/CMakeCache.txt || continue + fi + + # Copy line. + echo "$line" >> AppImageBuilder-generated.yml + + # Workaround for appimage-builder issues 272 and 283 (i686 and armhf are also missing) + if [ "$arch_appimage" != "x86_64" -a "$line" = " files:" ] + then + # Some mild arbitrary code execution with a dummy package... + [ ! -d /runtime ] && sudo apt-get -y -o 'DPkg::Post-Invoke::=mkdir -p /runtime; chmod 777 /runtime' install libsixel1 > /dev/null 2>&1 + + echo " include:" >> AppImageBuilder-generated.yml + for loader in "/lib/$libdir/ld-linux"*.so.* + do + for loader_copy in "$loader" "/lib/$(basename "$loader")" + do + if [ ! -e "/runtime/compat$loader_copy" ] + then + mkdir -p "/runtime/compat$(dirname "$loader_copy")" + ln -s "$loader" "/runtime/compat$loader_copy" + fi + echo " - /runtime/compat$loader_copy" >> AppImageBuilder-generated.yml + done + done + fi + done < .ci/AppImageBuilder.yml # Download appimage-builder if necessary. - [ ! -e "appimage-builder.AppImage" ] && wget -qO appimage-builder.AppImage \ - https://github.com/AppImageCrafters/appimage-builder/releases/download/v0.9.2/appimage-builder-0.9.2-35e3eab-x86_64.AppImage - chmod u+x appimage-builder.AppImage + appimage_builder_url="https://github.com/AppImageCrafters/appimage-builder/releases/download/v1.1.0/appimage-builder-1.1.0-$(uname -m).AppImage" + appimage_builder_binary="$cache_dir/$(basename "$appimage_builder_url")" + if [ ! -e "$appimage_builder_binary" ] + then + rm -rf "$cache_dir/"*".AppImage" # remove old versions + wget -qO "$appimage_builder_binary" "$appimage_builder_url" + fi - # Remove any dangling AppImages which may interfere with the renaming process. - rm -rf "$project-"*".AppImage" + # Symlink appimage-builder binary and global cache directory. + rm -rf appimage-builder.AppImage appimage-builder-cache "$project-"*".AppImage" # also remove any dangling AppImages which may interfere with the renaming process + ln -s "$appimage_builder_binary" appimage-builder.AppImage + chmod u+x appimage-builder.AppImage + mkdir -p "$cache_dir/appimage-builder-cache" + ln -s "$cache_dir/appimage-builder-cache" appimage-builder-cache # Run appimage-builder in extract-and-run mode for Docker compatibility. - project="$project" project_lower="$project_lower" project_version="$project_version" arch_deb="$arch_deb" arch_appimage="$arch_appimage" \ - APPIMAGE_EXTRACT_AND_RUN=1 ./appimage-builder.AppImage --recipe .ci/AppImageBuilder.yml - status=$? - - # Rename AppImage to the final name if the build succeeded. - if [ $status -eq 0 ] - then - mv "$project-"*".AppImage" "$cwd/$package_name.AppImage" + # --appdir is a workaround for appimage-builder issue 270 reported by us. + for retry in 1 2 3 4 5 + do + project="$project" project_id="$project_id" project_version="$project_version" project_icon="$project_icon" arch_deb="$arch_deb" \ + arch_appimage="$arch_appimage" appimage_path="$cwd/$package_name.AppImage" APPIMAGE_EXTRACT_AND_RUN=1 ./appimage-builder.AppImage \ + --recipe AppImageBuilder-generated.yml --appdir "$(grep -oP '^\s+path: \K(.+)' AppImageBuilder-generated.yml)" status=$? - fi + [ $status -eq 0 ] && break + [ $status -eq 127 ] && rm -rf /tmp/appimage_extracted_* + done + + # Remove appimage-builder binary on failure, just in case it's corrupted. + [ $status -ne 0 ] && rm -f "$appimage_builder_binary" fi -cd .. # Check if the archival succeeded. if [ $status -ne 0 ] diff --git a/.ci/dependencies_macports.txt b/.ci/dependencies_macports.txt new file mode 100644 index 000000000..5ec71d07c --- /dev/null +++ b/.ci/dependencies_macports.txt @@ -0,0 +1,17 @@ +cmake +pkgconfig +ninja +freetype +libsdl2 +libpng +openal-soft +FAudio +rtmidi +vulkan-headers +MoltenVK +qt5 +wget +fluidsynth +ghostscript +libslirp +vde2 diff --git a/.ci/dependencies_msys.txt b/.ci/dependencies_msys.txt new file mode 100644 index 000000000..22601b643 --- /dev/null +++ b/.ci/dependencies_msys.txt @@ -0,0 +1,14 @@ +ninja +cmake +gcc +pkgconf +openal +freetype +SDL2 +zlib +libpng +rtmidi +libslirp +fluidsynth +qt5-static +qt5-translations diff --git a/.ci/static2dll.sh b/.ci/static2dll.sh deleted file mode 100644 index f6e5b63b9..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/.clang-format b/.clang-format new file mode 100644 index 000000000..c5bb52eed --- /dev/null +++ b/.clang-format @@ -0,0 +1,19 @@ +BasedOnStyle: WebKit +AlignAfterOpenBracket: Align +AlignArrayOfStructures: Left +AlignConsecutiveMacros: AcrossEmptyLines +AlignConsecutiveAssignments: Consecutive +AlignConsecutiveBitFields: AcrossEmptyLines +AlignConsecutiveDeclarations: Consecutive +AlignEscapedNewlines: Left +AlignTrailingComments: true +AlwaysBreakAfterReturnType: TopLevelDefinitions +BreakBeforeTernaryOperators: true +IndentCaseLabels: true +IndentCaseBlocks: true +IndentGotoLabels: false +IndentPPDirectives: AfterHash +IndentExternBlock: NoIndent +PointerAlignment: Right +SpaceAfterCStyleCast: true +SortIncludes: false diff --git a/.editorconfig b/.editorconfig index 047c9d67c..29d9ac0ba 100644 --- a/.editorconfig +++ b/.editorconfig @@ -1,21 +1,21 @@ [*] charset = utf-8 end_of_line = lf -indent_style = tab -indent_size = 8 -tab_width = 8 +indent_style = space +indent_size = 4 +tab_width = 4 # Disabled for now since not all editors support setting a tab_width value different from indent_size # Relevant VSCode extension issue: https://github.com/editorconfig/editorconfig-vscode/issues/190 # [*.rc] # indent_style = space # indent_size = 4 -# tab_width = 8 +# tab_width = 4 # [Makefile.*] # indent_style = space # indent_size = 4 -# tab_width = 8 +# tab_width = 4 [*.manifest] indent_style = space @@ -32,3 +32,7 @@ indent_size = 4 [*.cmake] indent_style = space indent_size = 4 + +[*.json] +indent_style = space +indent_size = 4 diff --git a/.gitattributes b/.gitattributes new file mode 100644 index 000000000..32eb262c9 --- /dev/null +++ b/.gitattributes @@ -0,0 +1,21 @@ +# Set the default behavior, in case people don't have core.autocrlf set. +* text=auto + +# Explicitly declare text files you want to always be normalized and converted +# to native line endings on checkout. +*.c text +*.cc text +*.cpp text +*.h text +*.hpp text +*.rc text + + +# Declare files that will always have CRLF line endings on checkout. +*.sln text eol=crlf + +# Denote all files that are truly binary and should not be modified. +*.ico binary +*.png binary +*.jpg binary +*.dat diff --git a/.github/ISSUE_TEMPLATE/bug_report.md b/.github/ISSUE_TEMPLATE/bug_report.md deleted file mode 100644 index 340d89500..000000000 --- a/.github/ISSUE_TEMPLATE/bug_report.md +++ /dev/null @@ -1,32 +0,0 @@ ---- -name: Bug report -about: Create a report to help us improve -title: '' -labels: bug -assignees: '' - ---- - -**Describe the bug** -A clear and concise description of what the bug is. - -**To Reproduce** -Steps to reproduce the behavior: -1. Go to '...' -2. Click on '....' -3. Scroll down to '....' -4. See error - -**Expected behavior** -A clear and concise description of what you expected to happen. - -**Screenshots** -If applicable, add screenshots to help explain your problem. - -**Desktop (please complete the following information):** - - OS: [e.g. Windows 10] - - 86Box version: [e.g. v3.00 build 3333; saying "Latest from Jenkins" isn't helpful] - - Build information: [i.e. new/old dynarec, architecture and build type] - -**Additional context** -Add any other context about the problem here. If you are using an Optimized build, make sure to try the regular build too before filing a bug report! diff --git a/.github/ISSUE_TEMPLATE/bug_report.yml b/.github/ISSUE_TEMPLATE/bug_report.yml new file mode 100644 index 000000000..cdbc0a56f --- /dev/null +++ b/.github/ISSUE_TEMPLATE/bug_report.yml @@ -0,0 +1,80 @@ +name: Bug Report +description: File a bug report +title: "Title" +labels: ["bug"] +body: + - type: markdown + attributes: + value: | + Thanks for taking the time to fill out this bug report! + - type: textarea + attributes: + label: What happened? + description: Also tell us, what did you expect to happen? + placeholder: Tell us what you see! + validations: + required: true + - type: textarea + attributes: + label: Configuration file + description: Please copy and paste your machine configuration file (`86box.cfg`). This will be automatically formatted into code, so no need for backticks. + render: ini + validations: + required: true + - type: input + attributes: + label: Operating system + description: What is your host operating system? + placeholder: e.g. Windows 10 + validations: + required: true + - type: input + attributes: + label: CPU + description: What is your host CPU? + placeholder: e.g. AMD Ryzen 5 5600G + validations: + required: true + - type: input + attributes: + label: 86Box version + description: What version of 86Box are you running? (Saying "Latest from Jenkins" is not helpful.) + placeholder: e.g. v4.0 build 5000 + validations: + required: true + - type: dropdown + attributes: + label: Build architecture + description: 86Box for what architecture are you using? + options: + - Linux - ARM (32-bit) + - Linux - ARM (64-bit) + - Linux - x64 (64-bit) + - Linux - x86 (32-bit) + - macOS - Universal (Intel and Apple Silicon) + - Windows - x64 (64-bit) + - Windows - x86 (32-bit) + validations: + required: true + - type: checkboxes + attributes: + label: Build type + description: What type of build are you using? + options: + - label: New recompiler + - label: Debug build + - type: dropdown + attributes: + label: Download source + description: Where did you download 86Box from? + options: + - Official website (Jenkins, GitHub) + - Manager auto-update + - I built 86Box myself (please tell us more about your build configuration) + - I got 86Box from a third party repository (please tell us where) + validations: + required: true + - type: textarea + attributes: + label: Additional context + description: Is there anything else you want to tell us? diff --git a/.github/ISSUE_TEMPLATE/config.yml b/.github/ISSUE_TEMPLATE/config.yml index cc1ec7f8e..c03c50764 100644 --- a/.github/ISSUE_TEMPLATE/config.yml +++ b/.github/ISSUE_TEMPLATE/config.yml @@ -1,5 +1,8 @@ blank_issues_enabled: false contact_links: - - name: Question + - name: Machine Request + url: https://github.com/86Box/86Box/issues/3577#issue-comment-box + about: Please submit machine addition requests under this tracking issue. + - name: Feature Request or Question url: https://github.com/86Box/86Box/discussions - about: Please ask and answer questions here. + about: Please submit feature requests and ask questions here. diff --git a/.github/ISSUE_TEMPLATE/feature_request.md b/.github/ISSUE_TEMPLATE/feature_request.md deleted file mode 100644 index 4fe86d5ec..000000000 --- a/.github/ISSUE_TEMPLATE/feature_request.md +++ /dev/null @@ -1,20 +0,0 @@ ---- -name: Feature request -about: Suggest an idea for this project -title: '' -labels: feature -assignees: '' - ---- - -**Is your feature request related to a problem? Please describe.** -A clear and concise description of what the problem is. Ex. I'm always frustrated when [...] - -**Describe the solution you'd like** -A clear and concise description of what you want to happen. - -**Describe alternatives you've considered** -A clear and concise description of any alternative solutions or features you've considered. - -**Additional context** -Add any other context or screenshots about the feature request here. diff --git a/.github/codeql/codeql-config.yml b/.github/codeql/codeql-config.yml new file mode 100644 index 000000000..53e8ec316 --- /dev/null +++ b/.github/codeql/codeql-config.yml @@ -0,0 +1,5 @@ +name: "86Box CodeQL config" + +queries: + - uses: security-extended +# - uses: security-and-quality diff --git a/.github/dependabot.yml b/.github/dependabot.yml new file mode 100644 index 000000000..0d9f70d96 --- /dev/null +++ b/.github/dependabot.yml @@ -0,0 +1,9 @@ +version: 2 + +updates: + + # Maintain dependencies for GitHub Actions + - package-ecosystem: "github-actions" + directory: "/" + schedule: + interval: "weekly" diff --git a/.github/workflows/c-cpp.yml b/.github/workflows/c-cpp.yml index 51e2acbeb..79f350f4f 100644 --- a/.github/workflows/c-cpp.yml +++ b/.github/workflows/c-cpp.yml @@ -1,4 +1,4 @@ -name: MinGW64 Makefile +name: MSYS2 Makefile on: @@ -15,10 +15,10 @@ on: - "!**/CMakeLists.txt" jobs: - build: - name: ${{ matrix.environment.msystem }} Makefile build (DEV_BUILD=${{ matrix.dev-build }}, NEW_DYNAREC=${{ matrix.new-dynarec }}) + msys2: + name: "Windows MSYS2 Makefile (Win32 GUI, ${{ matrix.build.name }}, ${{ matrix.dynarec.name }}, ${{ matrix.environment.msystem }})" - runs-on: windows-latest + runs-on: windows-2022 defaults: run: @@ -27,33 +27,88 @@ jobs: strategy: fail-fast: true matrix: - dev-build: ['y', 'n'] - new-dynarec: ['y', 'n'] + build: +# - name: Regular +# debug: n +# dev: n + - name: Debug + debug: y + dev: n + slug: -Debug + - name: Dev + debug: y + dev: y + slug: -Dev + dynarec: + - name: ODR + new: n + slug: -ODR + - name: NDR + new: y + slug: -NDR environment: +# - msystem: MSYS +# clang: n +# x64: y - msystem: MINGW32 prefix: mingw-w64-i686 + clang: n x64: n - msystem: MINGW64 prefix: mingw-w64-x86_64 + clang: n + x64: y +# - msystem: CLANG32 +# prefix: mingw-w64-clang-i686 +# clang: y +# x64: n +# - msystem: CLANG64 +# prefix: mingw-w64-clang-x86_64 +# clang: y +# x64: y + - msystem: UCRT64 + prefix: mingw-w64-ucrt-x86_64 + clang: n x64: y steps: - - uses: msys2/setup-msys2@v2 - with: - update: true - msystem: ${{ matrix.environment.msystem }} - install: >- - make - ${{ matrix.environment.prefix }}-gcc - ${{ matrix.environment.prefix }}-pkg-config - ${{ matrix.environment.prefix }}-openal - ${{ matrix.environment.prefix }}-freetype - ${{ matrix.environment.prefix }}-SDL2 - ${{ matrix.environment.prefix }}-zlib - ${{ matrix.environment.prefix }}-libpng - ${{ matrix.environment.prefix }}-libvncserver - ${{ matrix.environment.prefix }}-rtmidi - - uses: actions/checkout@v2 - - name: make - run: make -fwin/makefile.mingw -j DEV_BUILD=${{ matrix.dev-build }} NEW_DYNAREC=${{ matrix.new-dynarec }} X64=${{ matrix.environment.x64 }} VNC=n - working-directory: ./src + - name: Prepare MSYS2 environment + uses: msys2/setup-msys2@v2 + with: + release: false + update: true + msystem: ${{ matrix.environment.msystem }} + install: >- + make + pacboy: >- + gcc:p + clang:p + pkg-config:p + freetype:p + SDL2:p + zlib:p + libpng:p + openal:p + rtmidi:p + libslirp:p + fluidsynth:p + libvncserver:p + + - name: Checkout repository + uses: actions/checkout@v4 + + - name: make + run: >- + make -fwin/Makefile.mingw -j + DEV_BUILD=${{ matrix.build.dev }} + DEBUG=${{ matrix.build.debug }} + NEW_DYNAREC=${{ matrix.dynarec.new }} + CLANG=${{ matrix.environment.clang }} + X64=${{ matrix.environment.x64 }} + working-directory: ./src + + - name: Upload artifact + uses: actions/upload-artifact@v3 + with: + name: '86Box${{ matrix.dynarec.slug }}${{ matrix.build.slug }}-Windows-${{ matrix.environment.msystem }}-gha${{ github.run_number }}' + path: src/86Box.exe diff --git a/.github/workflows/cmake.yml b/.github/workflows/cmake.yml index 0c85655c1..bde200b6b 100644 --- a/.github/workflows/cmake.yml +++ b/.github/workflows/cmake.yml @@ -4,28 +4,34 @@ on: push: paths: - - src/** - - "**/CMakeLists.txt" - - "CMakePresets.json" - - .github/workflows/cmake.yml - - vcpkg.json - - "!**/Makefile*" + - src/** + - cmake/** + - "**/CMakeLists.txt" + - "CMakePresets.json" + - .github/workflows/cmake.yml + - vcpkg.json + - "!**/Makefile*" pull_request: paths: - - src/** - - "**/CMakeLists.txt" - - "CMakePresets.json" - - .github/workflows/** - - .github/workflows/cmake.yml - - vcpkg.json - - "!**/Makefile*" + - src/** + - cmake/** + - "**/CMakeLists.txt" + - "CMakePresets.json" + - .github/workflows/** + - .github/workflows/cmake.yml + - vcpkg.json + - "!**/Makefile*" jobs: - msys2: - name: MSYS2 ${{ matrix.build.name }} build (${{ matrix.environment.msystem }}) - runs-on: windows-latest + msys2: + name: "Windows MSYS2 (${{ matrix.ui.name }}, ${{ matrix.build.name }}, ${{ matrix.dynarec.name }}, ${{ matrix.environment.msystem }})" + + runs-on: windows-2022 + + env: + BUILD_WRAPPER_OUT_DIR: build_wrapper_output_directory # Directory where build-wrapper output will be placed defaults: run: @@ -35,304 +41,443 @@ jobs: fail-fast: true matrix: build: - - name: Regular ODR - slug: -ODR - preset: regular - target: install/strip - - name: Debug ODR - slug: -ODR-Debug - preset: debug - target: install - - name: Dev ODR - slug: -ODR-Dev - preset: experimental - target: install - - name: Regular NDR - slug: -NDR - preset: regularndr - target: install/strip - - name: Debug NDR - slug: -NDR-Debug - preset: debugndr - target: install - - name: Dev NDR - slug: -NDR-Dev - preset: experimentalndr - target: install +# - name: Regular +# preset: regular + - name: Debug + preset: debug + slug: -Debug + - name: Dev + preset: experimental + slug: -Dev + dynarec: + - name: ODR + new: off + slug: -ODR + - name: NDR + new: on + slug: -NDR + ui: + - name: Win32 GUI + qt: off + static: on + - name: Qt GUI + qt: on + static: on + slug: -Qt + packages: >- + qt5-static:p +# qt5-base:p +# qt5-tools:p environment: +# - msystem: MSYS +# toolchain: ./cmake/flags-gcc-x86_64.cmake - msystem: MINGW32 prefix: mingw-w64-i686 + toolchain: ./cmake/flags-gcc-i686.cmake - msystem: MINGW64 prefix: mingw-w64-x86_64 - - msystem: UCRT64 - prefix: mingw-w64-ucrt-x86_64 + toolchain: ./cmake/flags-gcc-x86_64.cmake # - msystem: CLANG32 # prefix: mingw-w64-clang-i686 - - msystem: CLANG64 - prefix: mingw-w64-clang-x86_64 +# toolchain: ./cmake/llvm-win32-i686.cmake +# - msystem: CLANG64 +# prefix: mingw-w64-clang-x86_64 +# toolchain: ./cmake/llvm-win32-x86_64.cmake + - msystem: UCRT64 + prefix: mingw-w64-ucrt-x86_64 + toolchain: ./cmake/flags-gcc-x86_64.cmake steps: - - uses: msys2/setup-msys2@v2 - with: - path-type: inherit - update: true - msystem: ${{ matrix.environment.msystem }} - install: >- - ${{ matrix.environment.prefix }}-ninja - ${{ matrix.environment.prefix }}-cc - ${{ matrix.environment.prefix }}-pkg-config - ${{ matrix.environment.prefix }}-openal - ${{ matrix.environment.prefix }}-freetype - ${{ matrix.environment.prefix }}-SDL2 - ${{ matrix.environment.prefix }}-zlib - ${{ matrix.environment.prefix }}-libpng - ${{ matrix.environment.prefix }}-libvncserver - ${{ matrix.environment.prefix }}-rtmidi - - uses: actions/checkout@v2 - - name: Configure CMake - run: >- - cmake -S . -B build - --preset ${{ matrix.build.preset }} - -D CMAKE_INSTALL_PREFIX=./build/artifacts - -D VNC=OFF - - name: Build - run: cmake --build build --target ${{ matrix.build.target }} - - uses: actions/upload-artifact@v2 - with: - name: '86Box${{ matrix.build.slug }}-Windows-${{ matrix.environment.msystem }}-gha${{ github.run_number }}' - path: build/artifacts/** + - name: Prepare MSYS2 environment + uses: msys2/setup-msys2@v2 + with: + release: false + update: true + msystem: ${{ matrix.environment.msystem }} + pacboy: >- + ninja:p + cmake:p + gcc:p + pkgconf:p + freetype:p + SDL2:p + zlib:p + libpng:p + openal:p + rtmidi:p + libslirp:p + fluidsynth:p + libvncserver:p + ${{ matrix.ui.packages }} + + - name: Checkout repository + uses: actions/checkout@v4 + with: + fetch-depth: 0 # Shallow clones should be disabled for a better relevancy of analysis + + - name: Install sonar-scanner and build-wrapper + uses: SonarSource/sonarcloud-github-c-cpp@v2 + + - name: Configure CMake + run: >- + cmake -G Ninja -S . -B build --preset ${{ matrix.build.preset }} + --toolchain ${{ matrix.environment.toolchain }} + -D NEW_DYNAREC=${{ matrix.dynarec.new }} + -D CMAKE_INSTALL_PREFIX=./build/artifacts + -D QT=${{ matrix.ui.qt }} + -D STATIC_BUILD=${{ matrix.ui.static }} + + - name: Build + run: | + .sonar/build-wrapper-win-x86/build-wrapper-win-x86-64.exe --out-dir ${{ env.BUILD_WRAPPER_OUT_DIR }} cmake --build build + + - name: Run sonar-scanner + if: 0 + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + SONAR_TOKEN: ${{ secrets.SONAR_TOKEN }} + run: | + .sonar/sonar-scanner-5.0.1.3006-windows/bin/sonar-scanner.bat --define sonar.cfamily.build-wrapper-output="${{ env.BUILD_WRAPPER_OUT_DIR }}" + + - name: Generate package + run: cmake --install build + + - name: Upload artifact + uses: actions/upload-artifact@v3 + with: + name: '86Box${{ matrix.ui.slug }}${{ matrix.dynarec.slug }}${{ matrix.build.slug }}-Windows-${{ matrix.environment.msystem }}-gha${{ github.run_number }}' + path: build/artifacts/** llvm-windows: - name: "Windows vcpkg/LLVM (${{ matrix.build.name }} ${{ matrix.target.name }})" + name: "Windows vcpkg/LLVM (${{ matrix.ui.name }}, ${{ matrix.build.name }}, ${{ matrix.dynarec.name }}, ${{ matrix.target.name }})" + if: 0 runs-on: windows-2022 env: + BUILD_WRAPPER_OUT_DIR: build_wrapper_output_directory # Directory where build-wrapper output will be placed VCPKG_BINARY_SOURCES: 'clear;nuget,GitHub,readwrite' strategy: fail-fast: true matrix: build: - - name: Regular ODR - slug: -ODR - type: Release - dev-build: off - new-dynarec: off - strip: --strip - - name: Debug ODR - slug: -ODR-Debug - type: Debug - dev-build: off - new-dynarec: off - - name: Dev ODR - slug: -ODR-Dev - type: Debug - dev-build: on - new-dynarec: off - - name: Regular NDR - slug: -NDR - type: Release - strip: --strip - dev-build: off - new-dynarec: on - - name: Debug NDR - slug: -NDR-Debug - type: Debug - dev-build: off - new-dynarec: on - - name: Dev NDR - slug: -NDR-Dev - type: Debug - dev-build: on - new-dynarec: on +# - name: Regular +# preset: regular + - name: Debug + preset: debug + slug: -Debug + - name: Dev + preset: experimental + slug: -Dev + dynarec: + - name: ODR + new: off + slug: -ODR + - name: NDR + new: on + slug: -NDR + ui: + - name: Win32 GUI + qt: off + - name: Qt GUI + qt: on + slug: -Qt target: - - name: x86 - triplet: x86-windows-static - toolchain: cmake/llvm-win32-i686.cmake - vcvars: x64_x86 - - name: x64 - triplet: x64-windows-static - toolchain: cmake/llvm-win32-x86_64.cmake - vcvars: x64 - - name: ARM64 - triplet: arm64-windows-static - toolchain: cmake/llvm-win32-aarch64.cmake - vcvars: x64_arm64 + - name: x86 + triplet: x86-windows-static + toolchain: ./cmake/llvm-win32-i686.cmake + vcvars: x64_x86 + - name: x64 + triplet: x64-windows-static + toolchain: ./cmake/llvm-win32-x86_64.cmake + vcvars: x64 +# - name: ARM +# triplet: arm-windows-static +# toolchain: ./cmake/llvm-win32-arm.cmake +# vcvars: x64_arm + - name: ARM64 + triplet: arm64-windows-static + toolchain: ./cmake/llvm-win32-aarch64.cmake + vcvars: x64_arm64 exclude: - - build: - new-dynarec: off - target: - name: ARM64 + - dynarec: + new: off + target: + name: ARM64 steps: - - uses: actions/checkout@v2 - - name: Download Ninja - run: > - Invoke-WebRequest https://github.com/ninja-build/ninja/releases/download/v1.10.2/ninja-win.zip -OutFile ninja-win.zip && - Expand-Archive ninja-win.zip -DestinationPath . - - name: Setup NuGet Credentials - run: > - & (C:/vcpkg/vcpkg fetch nuget | tail -n 2) - sources add - -source "https://nuget.pkg.github.com/86Box/index.json" - -storepasswordincleartext - -name "GitHub" - -username "86Box" - -password "${{ secrets.GITHUB_TOKEN }}" - - name: vcpkg package restore - if: false - run: vcpkg install freetype libpng openal-soft sdl2 rtmidi --triplet ${{ matrix.target.triplet }} - - name: Configure CMake - run: > - call "C:/Program Files/Microsoft Visual Studio/2022/Enterprise/VC/Auxiliary/Build/vcvarsall.bat" ${{ matrix.target.vcvars }} - - set PATH=C:/Program Files/LLVM/bin;%PATH% + - name: Prepare VS environment + uses: ilammy/msvc-dev-cmd@v1 + with: + arch: ${{ matrix.target.vcvars }} - cmake -S . -B build -G Ninja -D CMAKE_BUILD_TYPE=${{ matrix.build.type }} - -D NEW_DYNAREC=${{ matrix.build.new-dynarec }} - -D CMAKE_TOOLCHAIN_FILE=C:/vcpkg/scripts/buildsystems/vcpkg.cmake - -D VCPKG_CHAINLOAD_TOOLCHAIN_FILE=${{ github.workspace }}/${{ matrix.target.toolchain }} - -D VCPKG_TARGET_TRIPLET=${{ matrix.target.triplet }} - shell: cmd - - name: Build - run: | - call "C:/Program Files/Microsoft Visual Studio/2022/Enterprise/VC/Auxiliary/Build/vcvarsall.bat" ${{ matrix.target.vcvars }} - cmake --build build - shell: cmd - - name: Generate package - run: cmake --install build --prefix ./build/artifacts ${{ matrix.build.strip }} - - uses: actions/upload-artifact@v2 - with: - name: '86Box${{ matrix.build.slug }}-Windows-LLVM-${{ matrix.target.name }}-gha${{ github.run_number }}' - path: build/artifacts/** + - name: Add LLVM to path + run: echo "C:/Program Files/LLVM/bin" >> $env:GITHUB_PATH + + - name: Download Ninja + run: > + Invoke-WebRequest https://github.com/ninja-build/ninja/releases/download/v1.11.1/ninja-win.zip -OutFile ninja-win.zip && + Expand-Archive ninja-win.zip -DestinationPath . + + - name: Setup NuGet Credentials + run: > + & (C:/vcpkg/vcpkg --vcpkg-root "${{ env.VCPKG_ROOT }}" fetch nuget | tail -n 2) + sources add + -source "https://nuget.pkg.github.com/86Box/index.json" + -storepasswordincleartext + -name "GitHub" + -username "86Box" + -password "${{ secrets.GITHUB_TOKEN }}" + + - name: Fix MSVC atomic headers + run: dir "C:/Program Files/Microsoft Visual Studio/2022/*/VC/Tools/MSVC/*/include" -include stdatomic.h -recurse | del + + - name: Checkout repository + uses: actions/checkout@v4 + with: + fetch-depth: 0 # Shallow clones should be disabled for a better relevancy of analysis + + - name: Install sonar-scanner and build-wrapper + uses: SonarSource/sonarcloud-github-c-cpp@v2 + + - name: Configure CMake + run: > + cmake -G Ninja -S . -B build --preset ${{ matrix.build.preset }} + --toolchain C:/vcpkg/scripts/buildsystems/vcpkg.cmake + -D NEW_DYNAREC=${{ matrix.dynarec.new }} -D QT=${{ matrix.ui.qt }} + -D CMAKE_INSTALL_PREFIX=./build/artifacts + -D VCPKG_CHAINLOAD_TOOLCHAIN_FILE=${{ github.workspace }}/${{ matrix.target.toolchain }} + -D VCPKG_TARGET_TRIPLET=${{ matrix.target.triplet }} + -D VCPKG_HOST_TRIPLET=x64-windows + -D VCPKG_USE_HOST_TOOLS=ON + + - name: Fix Qt + if: matrix.ui.qt == 'on' + run: | + $qtTargetsPath = "${{ github.workspace }}/build/vcpkg_installed/${{ matrix.target.triplet }}/share/Qt6/Qt6Targets.cmake" + (Get-Content $qtTargetsPath) -replace "^.*-Zc:__cplusplus;-permissive-.*$","#$&" | Set-Content $qtTargetsPath + + - name: Reconfigure CMake + if: matrix.ui.qt == 'on' + run: | + cmake clean build + + - name: Build + run: | + .sonar/build-wrapper-win-x86/build-wrapper-win-x86-64.exe --out-dir ${{ env.BUILD_WRAPPER_OUT_DIR }} cmake --build build + + - name: Run sonar-scanner + if: 0 + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + SONAR_TOKEN: ${{ secrets.SONAR_TOKEN }} + run: | + .sonar/sonar-scanner-5.0.1.3006-windows/bin/sonar-scanner.bat --define sonar.cfamily.build-wrapper-output="${{ env.BUILD_WRAPPER_OUT_DIR }}" + + - name: Generate package + run: | + cmake --install build + + - name: Upload artifact + uses: actions/upload-artifact@v3 + with: + name: '86Box${{ matrix.ui.slug }}${{ matrix.dynarec.slug }}${{ matrix.build.slug }}-Windows-LLVM-${{ matrix.target.name }}-gha${{ github.run_number }}' + path: build/artifacts/** linux: - name: "Linux GCC 11 (${{ matrix.build.name }} x86_64)" + name: "Linux GCC 11 (${{ matrix.ui.name }}, ${{ matrix.build.name }}, ${{ matrix.dynarec.name }}, x86_64)" - runs-on: ubuntu-latest + runs-on: ubuntu-22.04 + + env: + BUILD_WRAPPER_OUT_DIR: build_wrapper_output_directory # Directory where build-wrapper output will be placed strategy: fail-fast: true matrix: build: - - name: Regular ODR - slug: -ODR - type: Release - dev-build: off - new-dynarec: off - strip: --strip - - name: Debug ODR - slug: -ODR-Debug - type: Debug - dev-build: off - new-dynarec: off - - name: Dev ODR - slug: -ODR-Dev - type: Debug - dev-build: on - new-dynarec: off - - name: Regular NDR - slug: -NDR - type: Release - strip: --strip - dev-build: off - new-dynarec: on - - name: Debug NDR - slug: -NDR-Debug - type: Debug - dev-build: off - new-dynarec: on - - name: Dev NDR - slug: -NDR-Dev - type: Debug - dev-build: on - new-dynarec: on +# - name: Regular +# preset: regular + - name: Debug + preset: debug + slug: -Debug + - name: Dev + preset: experimental + slug: -Dev + dynarec: + - name: ODR + new: off + slug: -ODR + - name: NDR + new: on + slug: -NDR + ui: + - name: SDL GUI + qt: off + static: on + - name: Qt GUI + qt: on + slug: -Qt + packages: >- + qtbase5-dev + qtbase5-private-dev + qttools5-dev + libevdev-dev + libxkbcommon-x11-dev steps: - - uses: actions/checkout@v2 - name: Install dependencies - run: sudo apt update && sudo apt install gcc-11 g++-11 libfreetype-dev libsdl2-dev libpng-dev libopenal-dev libc6-dev librtmidi-dev qtbase5-dev qttools5-dev + run: >- + sudo apt update && sudo apt install + build-essential + ninja-build + libfreetype-dev + libsdl2-dev + libpng-dev + libc6-dev + librtmidi-dev + libopenal-dev + libslirp-dev + libfluidsynth-dev + libvncserver-dev + ${{ matrix.ui.packages }} + + - name: Checkout repository + uses: actions/checkout@v4 + with: + fetch-depth: 0 # Shallow clones should be disabled for a better relevancy of analysis + + - name: Install sonar-scanner and build-wrapper + uses: SonarSource/sonarcloud-github-c-cpp@v2 + - name: Configure CMake run: >- - cmake -S . -B build + cmake -G Ninja -S . -B build --preset ${{ matrix.build.preset }} + --toolchain ./cmake/flags-gcc-x86_64.cmake + -D NEW_DYNAREC=${{ matrix.dynarec.new }} -D CMAKE_INSTALL_PREFIX=./build/artifacts - -D DEV_BRANCH=${{ matrix.build.dev-build }} - -D NEW_DYNAREC=${{ matrix.build.new-dynarec }} - -D QT=ON - -D CMAKE_BUILD_TYPE=${{ matrix.build.type }} - -D CMAKE_C_COMPILER=gcc-11 -D CMAKE_CXX_COMPILER=g++-11 + -D QT=${{ matrix.ui.qt }} + - name: Build - run: cmake --build build + run: | + build-wrapper-linux-x86-64 --out-dir ${{ env.BUILD_WRAPPER_OUT_DIR }} cmake --build build + + - name: Run sonar-scanner +# if: 0 + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + SONAR_TOKEN: ${{ secrets.SONAR_TOKEN }} + run: | + sonar-scanner --define sonar.cfamily.build-wrapper-output="${{ env.BUILD_WRAPPER_OUT_DIR }}" + - name: Generate package - run: cmake --install build --prefix ./build/artifacts ${{ matrix.build.strip }} - - uses: actions/upload-artifact@v2 + run: | + cmake --install build + + - name: Upload artifact + uses: actions/upload-artifact@v3 with: - name: '86Box${{ matrix.build.slug }}-UbuntuFocal-x86_64-gha${{ github.run_number }}' + name: '86Box${{ matrix.ui.slug }}${{ matrix.dynarec.slug }}${{ matrix.build.slug }}-UbuntuJammy-x86_64-gha${{ github.run_number }}' path: build/artifacts/** macos11: - name: "macOS 11 (${{ matrix.build.name }} x86_64)" + name: "macOS 11 (${{ matrix.ui.name }}, ${{ matrix.build.name }}, ${{ matrix.dynarec.name }}, x86_64)" runs-on: macos-11 + env: + BUILD_WRAPPER_OUT_DIR: build_wrapper_output_directory # Directory where build-wrapper output will be placed + strategy: fail-fast: true matrix: build: - - name: Regular ODR - slug: -ODR - type: Release - dev-build: off - new-dynarec: off - strip: --strip - - name: Debug ODR - slug: -ODR-Debug - type: Debug - dev-build: off - new-dynarec: off - - name: Dev ODR - slug: -ODR-Dev - type: Debug - dev-build: on - new-dynarec: off - - name: Regular NDR - slug: -NDR - type: Release - strip: --strip - dev-build: off - new-dynarec: on - - name: Debug NDR - slug: -NDR-Debug - type: Debug - dev-build: off - new-dynarec: on - - name: Dev NDR - slug: -NDR-Dev - type: Debug - dev-build: on - new-dynarec: on +# - name: Regular +# preset: regular + - name: Debug + preset: debug + slug: -Debug + - name: Dev + preset: experimental + slug: -Dev + dynarec: + - name: ODR + new: off + slug: -ODR + - name: NDR + new: on + slug: -NDR + ui: + - name: SDL GUI + qt: off + static: on + src-packages: >- + libsndfile + - name: Qt GUI + qt: on + slug: -Qt + packages: >- + qt@5 + src-packages: >- + libsndfile steps: - - uses: actions/checkout@v2 + - name: Install source dependencies + run: >- + brew reinstall -s + ${{ matrix.ui.src-packages }} + - name: Install dependencies - run: brew install freetype sdl2 libpng openal-soft rtmidi qt@5 + run: >- + brew install + ninja + freetype + sdl2 + libpng + rtmidi + openal-soft + fluidsynth + libvncserver + ${{ matrix.ui.packages }} + + - name: Checkout repository + uses: actions/checkout@v4 + with: + fetch-depth: 0 # Shallow clones should be disabled for a better relevancy of analysis + + - name: Install sonar-scanner and build-wrapper + uses: SonarSource/sonarcloud-github-c-cpp@v2 + - name: Configure CMake run: >- - cmake -S . -B build - --toolchain cmake/flags-gcc-x86_64.cmake - -D DEV_BRANCH=${{ matrix.build.dev-build }} - -D NEW_DYNAREC=${{ matrix.build.new-dynarec }} - -D VNC=OFF - -D CMAKE_BUILD_TYPE=${{ matrix.build.type }} - -D QT=ON - -D Qt5_DIR=/usr/local/Cellar/qt@5/5.15.2_1/lib/cmake/Qt5 - -D Qt5LinguistTools_DIR=/usr/local/Cellar/qt@5/5.15.2_1/lib/cmake/Qt5LinguistTools/ + cmake -G Ninja -S . -B build --preset ${{ matrix.build.preset }} + --toolchain ./cmake/flags-gcc-x86_64.cmake + -D NEW_DYNAREC=${{ matrix.dynarec.new }} + -D CMAKE_INSTALL_PREFIX=./build/artifacts + -D QT=${{ matrix.ui.qt }} + -D Qt5_ROOT=$(brew --prefix qt@5) + -D Qt5LinguistTools_ROOT=$(brew --prefix qt@5) + -D OpenAL_ROOT=$(brew --prefix openal-soft) + - name: Build - run: cmake --build build + run: | + build-wrapper-macosx-x86 --out-dir ${{ env.BUILD_WRAPPER_OUT_DIR }} cmake --build build + + - name: Run sonar-scanner + if: 0 + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + SONAR_TOKEN: ${{ secrets.SONAR_TOKEN }} + run: | + sonar-scanner --define sonar.cfamily.build-wrapper-output="${{ env.BUILD_WRAPPER_OUT_DIR }}" + - name: Generate package - run: cmake --install build --prefix ./build/artifacts ${{ matrix.build.strip }} - - uses: actions/upload-artifact@v2 + run: | + cmake --install build + + - name: Upload artifact + uses: actions/upload-artifact@v3 with: - name: '86Box${{ matrix.build.slug }}-macOS-x86_64-gha${{ github.run_number }}' + name: '86Box${{ matrix.ui.slug }}${{ matrix.dynarec.slug }}${{ matrix.build.slug }}-macOS-x86_64-gha${{ github.run_number }}' path: build/artifacts/** diff --git a/.github/workflows/codeql.yml b/.github/workflows/codeql.yml new file mode 100644 index 000000000..5c23961d5 --- /dev/null +++ b/.github/workflows/codeql.yml @@ -0,0 +1,309 @@ +name: CodeQL + +on: + + push: + paths: + - src/** + - cmake/** + - "**/CMakeLists.txt" + - "CMakePresets.json" + - .github/workflows/codeql.yml + - vcpkg.json + - "!**/Makefile*" + + pull_request: + paths: + - src/** + - cmake/** + - "**/CMakeLists.txt" + - "CMakePresets.json" + - .github/workflows/** + - .github/workflows/codeql.yml + - vcpkg.json + - "!**/Makefile*" + +jobs: + + analyze-msys2: + + name: "Analyze Windows MSYS2 (${{ matrix.ui.name }}, ${{ matrix.build.name }}, ${{ matrix.dynarec.name }}, ${{ matrix.environment.msystem }})" + + runs-on: windows-2022 + + permissions: + actions: read + contents: read + security-events: write + + defaults: + run: + shell: msys2 {0} + + strategy: + fail-fast: true + matrix: + language: [ 'cpp' ] + build: +# - name: Regular +# preset: regular +# - name: Debug +# preset: debug +# slug: -Debug + - name: Dev + preset: experimental + slug: -Dev + dynarec: + - name: ODR + new: off + slug: -ODR + - name: NDR + new: on + slug: -NDR + ui: + - name: Win32 GUI + qt: off + static: on + - name: Qt GUI + qt: on + static: off + slug: -Qt + packages: >- + qt5-base:p + qt5-tools:p + environment: +# - msystem: MSYS +# toolchain: ./cmake/flags-gcc-x86_64.cmake + - msystem: MINGW32 + prefix: mingw-w64-i686 + toolchain: ./cmake/flags-gcc-i686.cmake + - msystem: MINGW64 + prefix: mingw-w64-x86_64 + toolchain: ./cmake/flags-gcc-x86_64.cmake +# - msystem: CLANG32 +# prefix: mingw-w64-clang-i686 +# toolchain: ./cmake/llvm-win32-i686.cmake +# - msystem: CLANG64 +# prefix: mingw-w64-clang-x86_64 +# toolchain: ./cmake/llvm-win32-x86_64.cmake + - msystem: UCRT64 + prefix: mingw-w64-ucrt-x86_64 + toolchain: ./cmake/flags-gcc-x86_64.cmake + + steps: + - name: Prepare MSYS2 environment + uses: msys2/setup-msys2@v2 + with: + release: false + update: true + msystem: ${{ matrix.environment.msystem }} + pacboy: >- + ninja:p + cmake:p + gcc:p + pkgconf:p + freetype:p + SDL2:p + zlib:p + libpng:p + openal:p + rtmidi:p + libslirp:p + fluidsynth:p + libvncserver:p + ${{ matrix.ui.packages }} + + - name: Checkout repository + uses: actions/checkout@v4 + + - name: Initialize CodeQL + uses: github/codeql-action/init@v2 + with: + languages: ${{ matrix.language }} + config-file: ./.github/codeql/codeql-config.yml + + - name: Configure CMake + run: >- + cmake -G Ninja -S . -B build --preset ${{ matrix.build.preset }} + --toolchain ${{ matrix.environment.toolchain }} + -D NEW_DYNAREC=${{ matrix.dynarec.new }} + -D CMAKE_INSTALL_PREFIX=./build/artifacts + -D QT=${{ matrix.ui.qt }} + -D STATIC_BUILD=${{ matrix.ui.static }} + + - name: Build + run: cmake --build build + + + - name: Perform CodeQL Analysis + uses: github/codeql-action/analyze@v2 + with: + category: "/language:${{matrix.language}}" + + analyze-linux: + + name: "Analyze Linux GCC 11 (${{ matrix.ui.name }}, ${{ matrix.build.name }}, ${{ matrix.dynarec.name }}, x86_64)" + + runs-on: ubuntu-22.04 + + permissions: + actions: read + contents: read + security-events: write + + strategy: + fail-fast: true + matrix: + language: [ 'cpp' ] + build: +# - name: Regular +# preset: regular +# - name: Debug +# preset: debug +# slug: -Debug + - name: Dev + preset: experimental + slug: -Dev + dynarec: + - name: ODR + new: off + slug: -ODR + - name: NDR + new: on + slug: -NDR + ui: + - name: SDL GUI + qt: off + - name: Qt GUI + qt: on + slug: -Qt + packages: >- + qtbase5-dev + qtbase5-private-dev + qttools5-dev + libevdev-dev + libxkbcommon-x11-dev + + steps: + - name: Install dependencies + run: >- + sudo apt update && sudo apt install + build-essential + ninja-build + libfreetype-dev + libsdl2-dev + libpng-dev + libc6-dev + librtmidi-dev + libopenal-dev + libslirp-dev + libfluidsynth-dev + libvncserver-dev + ${{ matrix.ui.packages }} + + - name: Checkout repository + uses: actions/checkout@v4 + + - name: Initialize CodeQL + uses: github/codeql-action/init@v2 + with: + languages: ${{ matrix.language }} + config-file: ./.github/codeql/codeql-config.yml + + - name: Configure CMake + run: >- + cmake -G Ninja -S . -B build --preset ${{ matrix.build.preset }} + --toolchain ./cmake/flags-gcc-x86_64.cmake + -D NEW_DYNAREC=${{ matrix.dynarec.new }} + -D CMAKE_INSTALL_PREFIX=./build/artifacts + -D QT=${{ matrix.ui.qt }} + + - name: Build + run: cmake --build build + + - name: Perform CodeQL Analysis + uses: github/codeql-action/analyze@v2 + with: + category: "/language:${{matrix.language}}" + + analyze-macos11: + + name: "Analyze macOS 11 (${{ matrix.ui.name }}, ${{ matrix.build.name }}, ${{ matrix.dynarec.name }}, x86_64)" + + runs-on: macos-11 + + permissions: + actions: read + contents: read + security-events: write + + strategy: + fail-fast: true + matrix: + language: [ 'cpp' ] + build: +# - name: Regular +# preset: regular +# - name: Debug +# preset: debug +# slug: -Debug + - name: Dev + preset: experimental + slug: -Dev + dynarec: + - name: ODR + new: off + slug: -ODR + - name: NDR + new: on + slug: -NDR + ui: + - name: SDL GUI + qt: off + - name: Qt GUI + qt: on + slug: -Qt + packages: >- + qt@5 + + steps: + - name: Install dependencies + run: >- + brew install + ninja + freetype + sdl2 + libpng + rtmidi + openal-soft + fluidsynth + libvncserver + ${{ matrix.ui.packages }} + + - name: Checkout repository + uses: actions/checkout@v4 + + - name: Initialize CodeQL + uses: github/codeql-action/init@v2 + with: + languages: ${{ matrix.language }} + config-file: ./.github/codeql/codeql-config.yml + + - name: Configure CMake + run: >- + cmake -G Ninja -S . -B build --preset ${{ matrix.build.preset }} + --toolchain ./cmake/flags-gcc-x86_64.cmake + -D NEW_DYNAREC=${{ matrix.dynarec.new }} + -D CMAKE_INSTALL_PREFIX=./build/artifacts + -D QT=${{ matrix.ui.qt }} + -D Qt5_ROOT=$(brew --prefix qt@5) + -D Qt5LinguistTools_ROOT=$(brew --prefix qt@5) + -D OpenAL_ROOT=$(brew --prefix openal-soft) + + - name: Build + run: cmake --build build + + - name: Perform CodeQL Analysis + uses: github/codeql-action/analyze@v2 + with: + category: "/language:${{matrix.language}}" diff --git a/.gitignore b/.gitignore index f54d57c5b..48a5950b9 100644 --- a/.gitignore +++ b/.gitignore @@ -1,8 +1,8 @@ # CMake -/CMakeUserPresets.json -/CMakeCache.txt -/build +CMakeUserPresets.json +CMakeCache.txt CMakeFiles +/build Makefile *.a /src/*.exe @@ -26,6 +26,7 @@ Makefile # Build scripts /archive_tmp +/archive_tmp_universal /static2dll.* /VERSION *.zip @@ -33,11 +34,28 @@ Makefile *.tar.* *.AppImage /appimage-builder-cache +/appimage-build +/AppImageBuilder-generated.yml # Visual Studio Code /.vs /.vscode -src/win/RCa04980 +/out + +# Windows resource compiler +RC* # Qt Creator CMakeLists.txt.user + +# Debian builder +/debian/*.log +/debian/*.substvars +/debian/.debhelper +/debian/86box +/debian/debhelper-build-stamp +/debian/files +/obj-*-linux-gnu + +# MacOS Finder stuff +.DS_Store diff --git a/AUTHORS b/AUTHORS index cef4e3773..bea36a263 100644 --- a/AUTHORS +++ b/AUTHORS @@ -1,5 +1,5 @@ -All authors of this emulator are documented in at the top of each file in the source code. - -They own portions of the code, or in cases, the entirety of it. - -resid-fp and slirp folders have their own exceptions. \ No newline at end of file +All authors of this emulator are documented in at the top of each file in the source code. + +They own portions of the code, or in cases, the entirety of it. + +resid-fp and slirp folders have their own exceptions. diff --git a/CMakeLists.txt b/CMakeLists.txt index 56a4d446a..8422792bd 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -10,7 +10,7 @@ # # Authors: David HrdliÄka, # -# Copyright 2020,2021 David HrdliÄka. +# Copyright 2020-2021 David HrdliÄka. # cmake_minimum_required(VERSION 3.16) @@ -18,12 +18,16 @@ cmake_minimum_required(VERSION 3.16) cmake_policy(SET CMP0091 NEW) cmake_policy(SET CMP0079 NEW) -if(QT) +if(HAIKU) + set(OPENAL ON) +endif() + +if(NOT DEFINED QT OR QT) list(APPEND VCPKG_MANIFEST_FEATURES "qt-ui") endif() -if(SLIRP_EXTERNAL) - list(APPEND VCPKG_MANIFEST_FEATURES "slirp") +if(NOT DEFINED OPENAL OR OPENAL) + list(APPEND VCPKG_MANIFEST_FEATURES "openal") endif() if(MUNT_EXTERNAL) @@ -31,7 +35,7 @@ if(MUNT_EXTERNAL) endif() project(86Box - VERSION 3.2 + VERSION 4.0.2 DESCRIPTION "Emulator of x86-based systems" HOMEPAGE_URL "https://86box.net" LANGUAGES C CXX) @@ -57,6 +61,9 @@ if(VCPKG_TOOLCHAIN) set(CMAKE_MSVC_RUNTIME_LIBRARY "MultiThreaded$<$:Debug>DLL") set(STATIC_BUILD OFF) endif() + + # `vcpkg.json` defaults to Qt6 + set(USE_QT6 ON) endif() if(WIN32) @@ -105,7 +112,12 @@ if(WIN32) add_compile_definitions(_WINSOCK_DEPRECATED_NO_WARNINGS) endif() -set(CMAKE_CXX_STANDARD 11) +if(NOT (WIN32 OR APPLE OR CMAKE_SYSTEM_NAME STREQUAL "Linux")) + set(DISCORD OFF) +endif() + +set(CMAKE_C_STANDARD 11) +set(CMAKE_CXX_STANDARD 14) set(CMAKE_FIND_PACKAGE_PREFER_CONFIG ON) # Optional features @@ -115,44 +127,46 @@ set(CMAKE_FIND_PACKAGE_PREFER_CONFIG ON) option(RELEASE "Release build" OFF) option(DYNAREC "Dynamic recompiler" ON) option(OPENAL "OpenAL" ON) +option(RTMIDI "RtMidi" ON) option(FLUIDSYNTH "FluidSynth" ON) option(MUNT "MUNT" ON) +option(VNC "VNC renderer" OFF) option(DINPUT "DirectInput" OFF) option(CPPTHREADS "C++11 threads" ON) option(NEW_DYNAREC "Use the PCem v15 (\"new\") dynamic recompiler" OFF) option(MINITRACE "Enable Chrome tracing using the modified minitrace library" OFF) +option(GDBSTUB "Enable GDB stub server for debugging" OFF) option(DEV_BRANCH "Development branch" OFF) -if(NOT WIN32) -option(QT "QT GUI" ON) -else() -option(QT "QT GUI" OFF) -endif() +option(QT "Qt GUI" ON) +option(DISCORD "Discord Rich Presence support" ON) # Development branch features # # Option Description Def. Condition Otherwise # ------ ----------- ---- --------- --------- cmake_dependent_option(AMD_K5 "AMD K5" ON "DEV_BRANCH" OFF) +cmake_dependent_option(AN430TX "Intel AN430TX" ON "DEV_BRANCH" OFF) cmake_dependent_option(CYRIX_6X86 "Cyrix 6x86" ON "DEV_BRANCH" OFF) +cmake_dependent_option(DESKPRO386 "Compaq Deskpro 386" ON "DEV_BRANCH" OFF) cmake_dependent_option(GUSMAX "Gravis UltraSound MAX" ON "DEV_BRANCH" OFF) cmake_dependent_option(ISAMEM_RAMPAGE "AST Rampage" ON "DEV_BRANCH" OFF) cmake_dependent_option(ISAMEM_IAB "Intel Above Board" ON "DEV_BRANCH" OFF) cmake_dependent_option(ISAMEM_BRAT "BocaRAM/AT" ON "DEV_BRANCH" OFF) cmake_dependent_option(LASERXT "VTech Laser XT" ON "DEV_BRANCH" OFF) cmake_dependent_option(MGA "Matrox Mystique graphics adapters" ON "DEV_BRANCH" OFF) -cmake_dependent_option(NO_SIO "Machines without emulated Super I/O chips" ON "DEV_BRANCH" OFF) cmake_dependent_option(OLIVETTI "Olivetti M290" ON "DEV_BRANCH" OFF) cmake_dependent_option(OPEN_AT "OpenAT" ON "DEV_BRANCH" OFF) -cmake_dependent_option(PAS16 "Pro Audio Spectrum 16" OFF "DEV_BRANCH" OFF) +cmake_dependent_option(PAS16 "Pro Audio Spectrum 16" ON "DEV_BRANCH" OFF) cmake_dependent_option(SIO_DETECT "Super I/O Detection Helper" ON "DEV_BRANCH" OFF) -cmake_dependent_option(TANDY_ISA "Tandy PSG ISA clone boards" ON "DEV_BRANCH" OFF) cmake_dependent_option(VGAWONDER "ATI VGA Wonder (ATI-18800)" ON "DEV_BRANCH" OFF) -cmake_dependent_option(VNC "VNC renderer" OFF "DEV_BRANCH" OFF) cmake_dependent_option(XL24 "ATI VGA Wonder XL24 (ATI-28800-6)" ON "DEV_BRANCH" OFF) # Ditto but for Qt -if (QT) +if(QT) option(USE_QT6 "Use Qt6 instead of Qt5" OFF) + if(APPLE) + option(MOLTENVK "Use MoltenVK libraries for Vulkan support on macOS. Requires a Vulkan-enabled QT." OFF) + endif() endif() # Determine the build type @@ -175,7 +189,7 @@ elseif(BUILD_TYPE_LOWER STREQUAL "alpha") add_compile_definitions(ALPHA_BUILD) endif() -# Variables introduced by richardg867 for versioning stuff +# Versioning variables if(NOT CMAKE_PROJECT_VERSION_PATCH) set(CMAKE_PROJECT_VERSION_PATCH 0) endif() @@ -183,7 +197,7 @@ if(NOT EMU_BUILD_NUM) set(EMU_BUILD_NUM 0) endif() if(NOT EMU_COPYRIGHT_YEAR) - set(EMU_COPYRIGHT_YEAR 2022) + set(EMU_COPYRIGHT_YEAR 2023) endif() add_subdirectory(src) diff --git a/CMakePresets.json b/CMakePresets.json index f85564b19..0dbaf1988 100644 --- a/CMakePresets.json +++ b/CMakePresets.json @@ -1,114 +1,129 @@ { - "version": 3, + "version": 2, "cmakeMinimumRequired": { "major": 3, - "minor": 21, - "patch": 0 + "minor": 20 }, "configurePresets": [ { - "name": "flags-base", + "name": "base", + "binaryDir": "${sourceDir}/build/${presetName}", "cacheVariables": { - "CMAKE_CONFIGURATION_TYPES": "Debug;Release;Optimized" + "CMAKE_INSTALL_PREFIX": "${sourceDir}/build/artifacts", + "CMAKE_EXPORT_COMPILE_COMMANDS": true, + "DEV_BRANCH": "OFF", + "NEW_DYNAREC": "OFF", + "QT": "ON" }, - "hidden": true, - "binaryDir": "build" + "generator": "Ninja", + "hidden": true }, { "name": "regular", - "inherits": [ - "flags-base" - ], - "generator": "Ninja", "cacheVariables": { - "CMAKE_BUILD_TYPE": "Release", - "DEV_BRANCH": "OFF", - "NEW_DYNAREC": "OFF" - } - }, - { - "name": "regularndr", - "inherits": [ - "flags-base" - ], - "generator": "Ninja", - "cacheVariables": { - "CMAKE_BUILD_TYPE": "Release", - "DEV_BRANCH": "OFF", - "NEW_DYNAREC": "ON" - } + "CMAKE_BUILD_TYPE": "Release" + }, + "inherits": "base" }, { "name": "optimized", - "inherits": [ - "flags-base" - ], - "generator": "Ninja", "cacheVariables": { - "CMAKE_BUILD_TYPE": "Optimized", - "DEV_BRANCH": "OFF", - "NEW_DYNAREC": "OFF" - } - }, - { - "name": "optimizedndr", - "inherits": [ - "flags-base" - ], - "generator": "Ninja", - "cacheVariables": { - "CMAKE_BUILD_TYPE": "Optimized", - "DEV_BRANCH": "OFF", - "NEW_DYNAREC": "ON" - } + "CMAKE_BUILD_TYPE": "Optimized" + }, + "inherits": "base" }, { "name": "debug", - "inherits": [ - "flags-base" - ], - "generator": "Ninja", "cacheVariables": { - "CMAKE_BUILD_TYPE": "Debug", - "DEV_BRANCH": "OFF", - "NEW_DYNAREC": "OFF" - } + "CMAKE_BUILD_TYPE": "Debug" + }, + "inherits": "base" }, { - "name": "debugndr", - "inherits": [ - "flags-base" - ], - "generator": "Ninja", + "name": "development", "cacheVariables": { - "CMAKE_BUILD_TYPE": "Debug", - "DEV_BRANCH": "OFF", - "NEW_DYNAREC": "ON" - } + "CMAKE_BUILD_TYPE": "Release", + "DEV_BRANCH": "ON", + "NEW_DYNAREC": "OFF" + }, + "inherits": "base" }, { "name": "experimental", - "inherits": [ - "flags-base" - ], - "generator": "Ninja", - "cacheVariables": { - "CMAKE_BUILD_TYPE": "Debug", - "DEV_BRANCH": "ON", - "NEW_DYNAREC": "OFF" - } - }, - { - "name": "experimentalndr", - "inherits": [ - "flags-base" - ], - "generator": "Ninja", "cacheVariables": { "CMAKE_BUILD_TYPE": "Debug", "DEV_BRANCH": "ON", "NEW_DYNAREC": "ON" - } + }, + "inherits": "base" + }, + { + "name": "llvm-macos-aarch64.cmake", + "displayName": "MacOS clang regular", + "generator": "Ninja", + "binaryDir": "${sourceDir}/out/build/${presetName}", + "cacheVariables": { + "CMAKE_TOOLCHAIN_FILE": "cmake/llvm-macos-aarch64.cmake", + "NEW_DYNAREC": "ON", + "QT": "ON", + "USE_QT6": "OFF", + "Qt5_DIR": "/opt/homebrew/opt/qt@5/lib/cmake/Qt5", + "MOLTENVK_DIR": "/opt/homebrew/opt/molten-vk", + "Qt5LinguistTools_DIR": "/opt/homebrew/opt/qt@5/lib/cmake/Qt5LinguistTools", + "OpenAL_ROOT": "/opt/homebrew/opt/openal-soft" + }, + "inherits": "regular" + }, + { + "name": "llvm-macos-aarch64-debug", + "displayName": "MacOS clang debug", + "generator": "Ninja", + "binaryDir": "${sourceDir}/out/build/${presetName}", + "cacheVariables": { + "CMAKE_TOOLCHAIN_FILE": "cmake/llvm-macos-aarch64.cmake", + "NEW_DYNAREC": "ON", + "QT": "ON", + "USE_QT6": "OFF", + "Qt5_DIR": "/opt/homebrew/opt/qt@5/lib/cmake/Qt5", + "MOLTENVK_DIR": "/opt/homebrew/opt/molten-vk", + "Qt5LinguistTools_DIR": "/opt/homebrew/opt/qt@5/lib/cmake/Qt5LinguistTools", + "OpenAL_ROOT": "/opt/homebrew/opt/openal-soft", + "CMAKE_CXX_FLAGS_DEBUG": "-g -O0 -DENABLE_VDE_LOG", + "CMAKE_C_FLAGS_DEBUG": "-g -O0 -DENABLE_VDE_LOG" + }, + "inherits": "debug" + }, + { + "name": "flags-gcc-aarch64-debug", + "displayName": "Linux ARM 64 - Debug", + "description": "Linux ARM64 - Debug build", + "generator": "Ninja", + "binaryDir": "${sourceDir}/out/build/${presetName}", + "cacheVariables": { + "NEW_DYNAREC": "ON", + "CMAKE_BUILD_TYPE": "Debug", + "CMAKE_TOOLCHAIN_FILE": "cmake/flags-gcc-aarch64.cmake", + "CMAKE_INSTALL_PREFIX": "${sourceDir}/out/install/${presetName}", + "CMAKE_CXX_FLAGS_DEBUG": "-g -O0 -DENABLE_VDE_LOG", + "CMAKE_C_FLAGS_DEBUG": "-g -O0 -DENABLE_VDE_LOG" + }, + "inherits": "debug" + }, + { + "name": "flags-gcc-aarch64-regular", + "displayName": "Linux ARM 64 - Regular", + "description": "Linux ARM64 - Release build", + "generator": "Ninja", + "binaryDir": "${sourceDir}/out/build/${presetName}", + "cacheVariables": { + "NEW_DYNAREC": "ON", + "CMAKE_BUILD_TYPE": "Release", + "CMAKE_TOOLCHAIN_FILE": "cmake/flags-gcc-aarch64.cmake", + "CMAKE_INSTALL_PREFIX": "${sourceDir}/out/install/${presetName}" + }, + "inherits": "regular" } - ] + ], + "buildPresets": [], + "testPresets": [] } diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md new file mode 100644 index 000000000..4f4f32b2e --- /dev/null +++ b/CONTRIBUTING.md @@ -0,0 +1,13 @@ +# Contribution guidelines +The 86Box project welcomes contributions from anyone, as long as some basic guidelines are followed. + +## Emulated hardware +In order to accept new emulated hardware, the following criteria must be met: + +* A ROM must be available and be added to [our ROM repository](https://github.com/86Box/roms) +* Documentation must be available or it must be feasible to reverse engineer with a reasonable amount of time and effort +* It must be feasible to implement with a reasonable amount of time and effort +* It has to fall inside the project's scope + +## Questions +If you're unsure about any aspect of contributing, don't hesitate to get in touch via any of our official communities linked in our [readme](README.md#community) or [GitHub Discussions](https://github.com/86Box/86Box/discussions). diff --git a/README.md b/README.md index 0f48bc59e..370bc940e 100644 --- a/README.md +++ b/README.md @@ -1,55 +1,72 @@ -86Box [![Build Status](http://ci.86box.net/job/86Box/badge/icon)](http://ci.86box.net/job/86Box) +86Box ===== + +[![Build Status](https://ci.86box.net/job/86Box/badge/icon)](https://ci.86box.net/job/86Box/) +[![License](https://img.shields.io/github/license/86Box/86Box)](COPYING) [![Latest release](https://img.shields.io/github/release/86Box/86Box.svg)](https://github.com/86Box/86Box/releases) [![Downloads](https://img.shields.io/github/downloads/86Box/86Box/total.svg)](https://github.com/86Box/86Box/releases) + **86Box** is a low level x86 emulator that runs older operating systems and software designed for IBM PC systems and compatibles from 1981 through fairly recent system designs based on the PCI bus. Features -------- + * Easy to use interface inspired by mainstream hypervisor software -* Low level emulation of 8086-based processors up to the Pentium with focus on accuracy +* Low level emulation of 8086-based processors up to the Mendocino-era Celeron with focus on accuracy * Great range of customizability of virtual machines * Many available systems, such as the very first IBM PC 5150 from 1981, or the more obscure IBM PS/2 line of systems based on the Micro Channel Architecture * Lots of supported peripherals including video adapters, sound cards, network adapters, hard disk controllers, and SCSI adapters * MIDI output to Windows built-in MIDI support, FluidSynth, or emulated Roland synthesizers * Supports running MS-DOS, older Windows versions, OS/2, many Linux distributions, or vintage systems such as BeOS or NEXTSTEP, and applications for these systems -System requirements and recommendations ---------------------------------------- -* Intel Core 2 or AMD Athlon 64 processor -* Windows 7 Service Pack 1, Windows 8.1 or Windows 10 -* 4 GB of RAM +Minimum system requirements and recommendations +----------------------------------------------- -Performance may vary depending on both host and guest configuration. Most emulation logic is executed in a single thread, therefore generally systems with better IPC (instructions per clock) should be able to emulate higher clock speeds. +* Intel Core 2 or AMD Athlon 64 processor or newer +* Windows version: Windows 7 Service Pack 1 or later +* Linux version: Ubuntu 16.04, Debian 9.0 or other distributions from 2016 onwards +* macOS version: macOS High Sierra 10.13 or newer +* 4 GB of RAM or higher + +Performance may vary depending on both host and guest configuration. Most emulation logic is executed in a single thread; therefore, systems with better IPC (instructions per clock) generally should be able to emulate higher clock speeds. It is also recommended to use a manager application with 86Box for easier handling of multiple virtual machines. -* [WinBox for 86Box](https://github.com/86Box/WinBox-for-86Box) by Laci bá' - * The new manager with improved new user experience; installer, automatic updates of emulator files and more. -* [86Box Manager](https://github.com/86Box/86BoxManager) by [daviunic](https://github.com/daviunic) (Overdoze) - * The traditional 86Box manager with simple interface. -However, it is also possible to use 86Box on its own with the `--vmpath`/`-P` command line option. +* [86Box Manager](https://github.com/86Box/86BoxManager) by [Overdoze](https://github.com/daviunic) (Windows only) +* [Linbox-qt5](https://github.com/Dungeonseeker/linbox-qt5) by Dungeonseeker (Linux focused, should work on Windows though untested) +* [MacBox for 86Box](https://github.com/Moonif/MacBox) by [Moonif](https://github.com/Moonif) (MacOS only) + +It is also possible to use 86Box on its own with the `--vmpath`/`-P` command line option. Getting started --------------- + See [our documentation](https://86box.readthedocs.io/en/latest/index.html) for an overview of the emulator's features and user interface. Community --------- + We operate an IRC channel and a Discord server for discussing 86Box, its development and anything related to retro computing. We look forward to hearing from you! [![Visit our IRC channel](https://kiwiirc.com/buttons/irc.ringoflightning.net/86Box.png)](https://kiwiirc.com/client/irc.ringoflightning.net/?nick=86box|?#86Box) [![Visit our Discord server](https://discordapp.com/api/guilds/262614059009048590/embed.png)](https://discord.gg/QXK9XTv) +Contributions +--------- + +We welcome all contributions to the project, as long as the [contribution guidelines](CONTRIBUTING.md) are followed. + Licensing --------- + 86Box is released under the [GNU General Public License, version 2](https://www.gnu.org/licenses/old-licenses/gpl-2.0.html) or later. For more information, see the `COPYING` file in the root of the repository. The emulator can also optionally make use of [munt](https://github.com/munt/munt), [FluidSynth](https://www.fluidsynth.org/), [Ghostscript](https://www.ghostscript.com/) and [Discord Game SDK](https://discord.com/developers/docs/game-sdk/sdk-starter-guide), which are distributed under their respective licenses. Donations --------- + We do not charge you for the emulator but donations are still welcome: -https://paypal.me/86Box. +. You can also support the project on Patreon: -https://www.patreon.com/86box. +. diff --git a/bumpversion.sh b/bumpversion.sh new file mode 100644 index 000000000..4681e72be --- /dev/null +++ b/bumpversion.sh @@ -0,0 +1,77 @@ +#!/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. +# +# Convenience script for changing the emulator's version. +# +# +# Authors: RichardG, +# +# Copyright 2022 RichardG. +# + +# Parse arguments. +newversion="$1" +romversion="$2" + +if [ -z "$(echo "$newversion" | grep '\.')" ] +then + echo '[!] Usage: bumpversion.sh x.y[.z] [romversion]' + exit 1 +fi +shift + +# Extract version components. +newversion_maj=$(echo "$newversion" | cut -d. -f1) +newversion_min=$(echo "$newversion" | cut -d. -f2) +newversion_patch=$(echo "$newversion" | cut -d. -f3) +[ -z "$newversion_patch" ] && newversion_patch=0 + +if [ -z "${romversion}" ]; then + # Get the latest ROM release from the GitHub API. + romversion=$(curl --silent "https://api.github.com/repos/86Box/roms/releases/latest" | + grep '"tag_name":' | + sed -E 's/.*"v([^"]+)".*/\1/') +fi + +# Switch to the repository root directory. +cd "$(dirname "$0")" || exit + +pretty_date() { + # Ensure we get the date in English. + LANG=en_US.UTF-8 date '+%a %b %d %Y' +} + +# Patch files. +patch_file() { + # Stop if the file doesn't exist. + [ ! -e "$1" ] && return + + # Patch file. + if sed -i -r -e "$3" "$1" + then + echo "[-] Patched $2 on $1" + else + echo "[!] Patching $2 on $1 failed" + fi +} +patch_file CMakeLists.txt VERSION 's/^(\s*VERSION ).+/\1'"$newversion"'/' +patch_file vcpkg.json version-string 's/(^\s*"version-string"\s*:\s*")[^"]+/\1'"$newversion"'/' +patch_file src/include_make/*/version.h EMU_VERSION 's/(#\s*define\s+EMU_VERSION\s+")[^"]+/\1'"$newversion"'/' +patch_file src/include_make/*/version.h EMU_VERSION_MAJ 's/(#\s*define\s+EMU_VERSION_MAJ\s+)[0-9]+/\1'"$newversion_maj"'/' +patch_file src/include_make/*/version.h EMU_VERSION_MIN 's/(#\s*define\s+EMU_VERSION_MIN\s+)[0-9]+/\1'"$newversion_min"'/' +patch_file src/include_make/*/version.h EMU_VERSION_PATCH 's/(#\s*define\s+EMU_VERSION_PATCH\s+)[0-9]+/\1'"$newversion_patch"'/' +patch_file src/include_make/*/version.h COPYRIGHT_YEAR 's/(#\s*define\s+COPYRIGHT_YEAR\s+)[0-9]+/\1'"$(date +%Y)"'/' +patch_file src/include_make/*/version.h EMU_DOCS_URL 's/(#\s*define\s+EMU_DOCS_URL\s+"https:\/\/[^\/]+\/en\/v)[^\/]+/\1'"$newversion_maj.$newversion_min"'/' +patch_file src/unix/assets/*.spec Version 's/(Version:\s+)[0-9].+/\1'"$newversion"'/' +patch_file src/unix/assets/*.spec '%global romver' 's/(^%global\ romver\s+)[0-9]{8}/\1'"$romversion"'/' +patch_file src/unix/assets/*.spec 'changelog version' 's/(^[*]\s.*>\s+)[0-9].+/\1'"$newversion"-1'/' +patch_file src/unix/assets/*.spec 'changelog date' 's/(^[*]\s)[a-zA-Z]{3}\s[a-zA-Z]{3}\s[0-9]{2}\s[0-9]{4}/\1'"$(pretty_date)"'/' +patch_file src/unix/assets/*.metainfo.xml release 's/( .+/> '"$(date -R)"'/' +patch_file debian/changelog 'changelog version' 's/86box \(.+\)/86box \('"$newversion"'\)/' diff --git a/cmake/flags-gcc-aarch64.cmake b/cmake/flags-gcc-aarch64.cmake index d1f36af9c..4344e2c81 100644 --- a/cmake/flags-gcc-aarch64.cmake +++ b/cmake/flags-gcc-aarch64.cmake @@ -1,20 +1,20 @@ # -# 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. +# 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. +# This file is part of the 86Box distribution. # -# CMake toolchain file defining GCC compiler flags -# for AArch64 (ARM64) targets. +# CMake toolchain file defining GCC compiler flags +# for AArch64 (ARM64) targets. # -# Authors: David HrdliÄka, +# Authors: David HrdliÄka, # -# Copyright 2021 David HrdliÄka. +# Copyright 2021 David HrdliÄka. # -string(APPEND CMAKE_C_FLAGS_INIT " -march=armv8-a ${CMAKE_C_FLAGS_INIT}") -string(APPEND CMAKE_CXX_FLAGS_INIT " -march=armv8-a ${CMAKE_CXX_FLAGS_INIT}") +string(APPEND CMAKE_C_FLAGS_INIT " -march=armv8-a") +string(APPEND CMAKE_CXX_FLAGS_INIT " -march=armv8-a") -include(${CMAKE_CURRENT_LIST_DIR}/flags-gcc.cmake) \ No newline at end of file +include(${CMAKE_CURRENT_LIST_DIR}/flags-gcc.cmake) diff --git a/cmake/flags-gcc-armv7.cmake b/cmake/flags-gcc-armv7.cmake index bd49fdfce..070e5e52a 100644 --- a/cmake/flags-gcc-armv7.cmake +++ b/cmake/flags-gcc-armv7.cmake @@ -1,20 +1,20 @@ # -# 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. +# 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. +# This file is part of the 86Box distribution. # -# CMake toolchain file defining GCC compiler flags -# for ARMv7 targets. +# CMake toolchain file defining GCC compiler flags +# for ARMv7 targets. # -# Authors: David HrdliÄka, +# Authors: David HrdliÄka, # -# Copyright 2021 David HrdliÄka. +# Copyright 2021 David HrdliÄka. # -string(APPEND CMAKE_C_FLAGS_INIT " -march=armv7-a -mfloat-abi=hard ${CMAKE_C_FLAGS_INIT}") -string(APPEND CMAKE_CXX_FLAGS_INIT " -march=armv7-a -mfloat-abi=hard ${CMAKE_CXX_FLAGS_INIT}") +string(APPEND CMAKE_C_FLAGS_INIT " -march=armv7-a+fp -mfloat-abi=hard") +string(APPEND CMAKE_CXX_FLAGS_INIT " -march=armv7-a+fp -mfloat-abi=hard") -include(${CMAKE_CURRENT_LIST_DIR}/flags-gcc.cmake) \ No newline at end of file +include(${CMAKE_CURRENT_LIST_DIR}/flags-gcc.cmake) diff --git a/cmake/flags-gcc-i686.cmake b/cmake/flags-gcc-i686.cmake index 870fbc5df..3b3d72a16 100644 --- a/cmake/flags-gcc-i686.cmake +++ b/cmake/flags-gcc-i686.cmake @@ -1,20 +1,20 @@ # -# 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. +# 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. +# This file is part of the 86Box distribution. # -# CMake toolchain file defining GCC compiler flags -# for 32-bit x86 targets. +# CMake toolchain file defining GCC compiler flags +# for 32-bit x86 targets. # -# Authors: David HrdliÄka, +# Authors: David HrdliÄka, # -# Copyright 2021 David HrdliÄka. +# Copyright 2021 David HrdliÄka. # -string(APPEND CMAKE_C_FLAGS_INIT " -m32 -march=i686 -msse2 -mfpmath=sse -mstackrealign ${CMAKE_C_FLAGS_INIT}") -string(APPEND CMAKE_CXX_FLAGS_INIT " -m32 -march=i686 -msse2 -mfpmath=sse -mstackrealign ${CMAKE_CXX_FLAGS_INIT}") +string(APPEND CMAKE_C_FLAGS_INIT " -m32 -march=i686 -msse2 -mfpmath=sse -mstackrealign") +string(APPEND CMAKE_CXX_FLAGS_INIT " -m32 -march=i686 -msse2 -mfpmath=sse -mstackrealign") include(${CMAKE_CURRENT_LIST_DIR}/flags-gcc.cmake) diff --git a/cmake/flags-gcc-x86_64.cmake b/cmake/flags-gcc-x86_64.cmake index 9099d8749..47928df42 100644 --- a/cmake/flags-gcc-x86_64.cmake +++ b/cmake/flags-gcc-x86_64.cmake @@ -1,20 +1,20 @@ # -# 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. +# 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. +# This file is part of the 86Box distribution. # -# CMake toolchain file defining GCC compiler flags -# for 64-bit x86 targets. +# CMake toolchain file defining GCC compiler flags +# for 64-bit x86 targets. # -# Authors: David HrdliÄka, +# Authors: David HrdliÄka, # -# Copyright 2021 David HrdliÄka. +# Copyright 2021 David HrdliÄka. # -string(APPEND CMAKE_C_FLAGS_INIT " -m64 -march=x86-64 -msse2 -mfpmath=sse -mstackrealign ${CMAKE_C_FLAGS_INIT}") -string(APPEND CMAKE_CXX_FLAGS_INIT " -m64 -march=x86-64 -msse2 -mfpmath=sse -mstackrealign ${CMAKE_CXX_FLAGS_INIT}") +string(APPEND CMAKE_C_FLAGS_INIT " -m64 -march=x86-64 -msse2 -mfpmath=sse -mstackrealign") +string(APPEND CMAKE_CXX_FLAGS_INIT " -m64 -march=x86-64 -msse2 -mfpmath=sse -mstackrealign") include(${CMAKE_CURRENT_LIST_DIR}/flags-gcc.cmake) diff --git a/cmake/flags-gcc.cmake b/cmake/flags-gcc.cmake index 3339ad063..885353b87 100644 --- a/cmake/flags-gcc.cmake +++ b/cmake/flags-gcc.cmake @@ -1,20 +1,20 @@ # -# 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. +# 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. +# This file is part of the 86Box distribution. # -# CMake toolchain file defining GCC compiler flags. +# CMake toolchain file defining GCC compiler flags. # -# Authors: David HrdliÄka, +# Authors: David HrdliÄka, # -# Copyright 2021 David HrdliÄka. +# Copyright 2021 David HrdliÄka. # # Define our flags -string(APPEND CMAKE_C_FLAGS_INIT " -fomit-frame-pointer -Wall -fno-strict-aliasing") +string(APPEND CMAKE_C_FLAGS_INIT " -fomit-frame-pointer -Wall -fno-strict-aliasing -Werror=implicit-int -Werror=implicit-function-declaration -Werror=int-conversion -Werror=strict-prototypes -Werror=old-style-definition") string(APPEND CMAKE_CXX_FLAGS_INIT " -fomit-frame-pointer -Wall -fno-strict-aliasing") string(APPEND CMAKE_C_FLAGS_RELEASE_INIT " -g0 -O3") string(APPEND CMAKE_CXX_FLAGS_RELEASE_INIT " -g0 -O3") @@ -32,4 +32,4 @@ foreach(LANG C;CXX) set(CMAKE_${LANG}_FLAGS_${CONFIG} "${CMAKE_${LANG}_FLAGS_${CONFIG}_INIT}" CACHE STRING "Flags used by the ${LANG} compiler during ${CONFIG} builds.") mark_as_advanced(CMAKE_${LANG}_FLAGS_${CONFIG}) endforeach() -endforeach() \ No newline at end of file +endforeach() diff --git a/cmake/llvm-macos-aarch64.cmake b/cmake/llvm-macos-aarch64.cmake index da9ccb449..df67ad45b 100644 --- a/cmake/llvm-macos-aarch64.cmake +++ b/cmake/llvm-macos-aarch64.cmake @@ -1,22 +1,22 @@ # -# 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. +# 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. +# This file is part of the 86Box distribution. # -# CMake toolchain file defining Clang compiler flags -# for AArch64 (ARM64)-based Apple Silicon targets. +# CMake toolchain file defining Clang compiler flags +# for AArch64 (ARM64)-based Apple Silicon targets. # -# Authors: David HrdliÄka, -# dob205 +# Authors: David HrdliÄka, +# dob205 # -# Copyright 2021 David HrdliÄka. -# Copyright 2022 dob205. +# Copyright 2021 David HrdliÄka. +# Copyright 2022 dob205. # string(APPEND CMAKE_C_FLAGS_INIT " -march=armv8.5-a+simd") string(APPEND CMAKE_CXX_FLAGS_INIT " -march=armv8.5-a+simd") -include(${CMAKE_CURRENT_LIST_DIR}/flags-gcc.cmake) \ No newline at end of file +include(${CMAKE_CURRENT_LIST_DIR}/flags-gcc.cmake) diff --git a/cmake/llvm-win32-aarch64.cmake b/cmake/llvm-win32-aarch64.cmake index 4aacb248f..015a0dad0 100644 --- a/cmake/llvm-win32-aarch64.cmake +++ b/cmake/llvm-win32-aarch64.cmake @@ -1,16 +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. +# 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. +# This file is part of the 86Box distribution. # -# CMake toolchain file for Clang on Windows builds (ARM64 target). +# CMake toolchain file for Clang on Windows builds (ARM64 target). # -# Authors: David HrdliÄka, +# Authors: David HrdliÄka, # -# Copyright 2021 David HrdliÄka. +# Copyright 2021 David HrdliÄka. # include(${CMAKE_CURRENT_LIST_DIR}/flags-gcc-aarch64.cmake) @@ -27,4 +27,4 @@ set(CMAKE_CXX_COMPILER_TARGET aarch64-pc-windows-msvc) set(CMAKE_SYSTEM_PROCESSOR ARM64) -# TODO: set the vcpkg target triplet perhaps? \ No newline at end of file +# TODO: set the vcpkg target triplet perhaps? diff --git a/cmake/llvm-win32-arm.cmake b/cmake/llvm-win32-arm.cmake new file mode 100644 index 000000000..30c9877d4 --- /dev/null +++ b/cmake/llvm-win32-arm.cmake @@ -0,0 +1,30 @@ +# +# 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 toolchain file for Clang on Windows builds (ARM64 target). +# +# Authors: David HrdliÄka, +# +# Copyright 2021 David HrdliÄka. +# + +include(${CMAKE_CURRENT_LIST_DIR}/flags-gcc-armv7.cmake) + +# Use the GCC-compatible Clang executables in order to use our flags +set(CMAKE_C_COMPILER clang) +set(CMAKE_CXX_COMPILER clang++) + +# `llvm-rc` is barely usable as of LLVM 13, using MS' rc.exe for now +set(CMAKE_RC_COMPILER rc) + +set(CMAKE_C_COMPILER_TARGET arm-pc-windows-msvc) +set(CMAKE_CXX_COMPILER_TARGET arm-pc-windows-msvc) + +set(CMAKE_SYSTEM_PROCESSOR ARM) + +# TODO: set the vcpkg target triplet perhaps? diff --git a/cmake/llvm-win32-i686.cmake b/cmake/llvm-win32-i686.cmake index 8221f8bc2..b69771407 100644 --- a/cmake/llvm-win32-i686.cmake +++ b/cmake/llvm-win32-i686.cmake @@ -1,16 +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. +# 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. +# This file is part of the 86Box distribution. # -# CMake toolchain file for Clang on Windows builds (x86 target). +# CMake toolchain file for Clang on Windows builds (x86 target). # -# Authors: David HrdliÄka, +# Authors: David HrdliÄka, # -# Copyright 2021 David HrdliÄka. +# Copyright 2021 David HrdliÄka. # include(${CMAKE_CURRENT_LIST_DIR}/flags-gcc-i686.cmake) @@ -27,4 +27,4 @@ set(CMAKE_CXX_COMPILER_TARGET i686-pc-windows-msvc) set(CMAKE_SYSTEM_PROCESSOR X86) -# TODO: set the vcpkg target triplet perhaps? \ No newline at end of file +# TODO: set the vcpkg target triplet perhaps? diff --git a/cmake/llvm-win32-x86_64.cmake b/cmake/llvm-win32-x86_64.cmake index 7caeb7836..da0cfd3f2 100644 --- a/cmake/llvm-win32-x86_64.cmake +++ b/cmake/llvm-win32-x86_64.cmake @@ -1,16 +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. +# 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. +# This file is part of the 86Box distribution. # -# CMake toolchain file for Clang on Windows builds (x64/AMD64 target). +# CMake toolchain file for Clang on Windows builds (x64/AMD64 target). # -# Authors: David HrdliÄka, +# Authors: David HrdliÄka, # -# Copyright 2021 David HrdliÄka. +# Copyright 2021 David HrdliÄka. # include(${CMAKE_CURRENT_LIST_DIR}/flags-gcc-x86_64.cmake) @@ -27,4 +27,4 @@ set(CMAKE_CXX_COMPILER_TARGET x86_64-pc-windows-msvc) set(CMAKE_SYSTEM_PROCESSOR AMD64) -# TODO: set the vcpkg target triplet perhaps? \ No newline at end of file +# TODO: set the vcpkg target triplet perhaps? diff --git a/debian/changelog b/debian/changelog new file mode 100644 index 000000000..887066097 --- /dev/null +++ b/debian/changelog @@ -0,0 +1,5 @@ +86box (4.0.2) UNRELEASED; urgency=medium + + * Bump release. + + -- Jasmine Iwanek Mon, 16 Oct 2023 20:24:46 +0200 diff --git a/debian/control b/debian/control new file mode 100644 index 000000000..78a92bf8f --- /dev/null +++ b/debian/control @@ -0,0 +1,29 @@ +Source: 86box +Section: otherosfs +Priority: optional +Maintainer: Mariusz Kurek +Build-Depends: cmake (>= 3.21), + debhelper-compat (= 13), + libevdev-dev, + libfreetype-dev, + libopenal-dev, + libqt5opengl5-dev, + librtmidi-dev, + libsdl2-dev, + libslirp-dev, + ninja-build, + qttools5-dev +Standards-Version: 4.6.0 +Homepage: https://86box.net/ +#Vcs-Browser: https://salsa.debian.org/debian/86box +#Vcs-Git: https://salsa.debian.org/debian/86box.git +Rules-Requires-Root: no + +Package: 86box +Architecture: amd64 armhf arm64 i386 +Depends: ${shlibs:Depends}, + ${misc:Depends}, + sse2-support [i386] +Recommends: libpcap0.8-dev +Description: An emulator for classic IBM PC clones +#TODO: insert long description, indented with spaces diff --git a/debian/copyright b/debian/copyright new file mode 100644 index 000000000..22817edc5 --- /dev/null +++ b/debian/copyright @@ -0,0 +1,38 @@ +Format: https://www.debian.org/doc/packaging-manuals/copyright-format/1.0/ +Upstream-Name: 86box +Source: https://86box.net/ + +Files: * +Copyright: + +License: GPL-2.0+ + +Files: debian/* +Copyright: 2022 Mariusz Kurek +License: GPL-2.0+ + +License: GPL-2.0+ + This package is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + . + This package is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + . + You should have received a copy of the GNU General Public License + along with this program. If not, see + . + On Debian systems, the complete text of the GNU General + Public License version 2 can be found in "/usr/share/common-licenses/GPL-2". + +# Please also look if there are files or directories which have a +# different copyright/license attached and list them here. +# Please avoid picking licenses with terms that are more restrictive than the +# packaged work, as it may make Debian's contributions unacceptable upstream. +# +# If you need, there are some extra license texts available in two places: +# /usr/share/debhelper/dh_make/licenses/ +# /usr/share/common-licenses/ diff --git a/debian/postinst b/debian/postinst new file mode 100644 index 000000000..b3080e419 --- /dev/null +++ b/debian/postinst @@ -0,0 +1,41 @@ +#!/bin/sh +# postinst script for 86box +# +# see: dh_installdeb(1) + +set -e + +# summary of how this script can be called: +# * `configure' +# * `abort-upgrade' +# * `abort-remove' `in-favour' +# +# * `abort-remove' +# * `abort-deconfigure' `in-favour' +# `removing' +# +# for details, see https://www.debian.org/doc/debian-policy/ or +# the debian-policy package + + +case "$1" in + configure) + echo You need ROM files in order to use 86Box. These can be obtained from https://github.com/86Box/roms + echo You can put the roms folder in, for example, /usr/share/86Box/roms or \~/.local/share/86Box/roms + ;; + + abort-upgrade|abort-remove|abort-deconfigure) + ;; + + *) + echo "postinst called with unknown argument \`$1'" >&2 + exit 1 + ;; +esac + +# dh_installdeb will replace this with shell code automatically +# generated by other debhelper scripts. + +#DEBHELPER# + +exit 0 diff --git a/debian/rules b/debian/rules new file mode 100644 index 000000000..7b0605e72 --- /dev/null +++ b/debian/rules @@ -0,0 +1,42 @@ +#!/usr/bin/make -f +# See debhelper(7) (uncomment to enable) +# output every command that modifies files on the build system. +#export DH_VERBOSE = 1 + +ARCH=$(shell dpkg-architecture -qDEB_HOST_ARCH) + +ifeq ($(ARCH), $(filter $(ARCH), amd64 i386)) + NDR=off + ifeq ($(ARCH),amd64) + TOOLCHAIN=cmake/flags-gcc-x86_64.cmake + else + TOOLCHAIN=cmake/flags-gcc-i686.cmake + endif +else + NDR=on + ifeq ($(ARCH),armhf) + TOOLCHAIN=cmake/flags-gcc-armv7.cmake + else + TOOLCHAIN=cmake/flags-gcc-aarch64.cmake + endif +endif + +%: + dh $@ --buildsystem cmake+ninja + +override_dh_auto_configure: + dh_auto_configure --buildsystem cmake+ninja -- --preset regular --toolchain $(TOOLCHAIN) -DNEW_DYNAREC=$(NDR) + +override_dh_auto_test: + +override_dh_auto_install: + dh_auto_install --buildsystem cmake+ninja + for i in 48x48 64x64 72x72 96x96 128x128 192x192 256x256 512x512 ; do \ + install -Dm644 src/unix/assets/$$i/net.86box.86Box.png -t debian/86box/usr/share/icons/hicolor/$$i/apps ; \ + done + mkdir debian/86box/usr/share/applications + sed 's/^Exec.*/Exec=86Box -P .local\/share\/86Box/' "src/unix/assets/net.86box.86Box.desktop" > "debian/86box/usr/share/applications/net.86box.86Box.desktop" + +override_dh_installdocs: + +override_dh_installman: diff --git a/debian/source/format b/debian/source/format new file mode 100644 index 000000000..163aaf8d8 --- /dev/null +++ b/debian/source/format @@ -0,0 +1 @@ +3.0 (quilt) diff --git a/debian/watch b/debian/watch new file mode 100644 index 000000000..6f790c753 --- /dev/null +++ b/debian/watch @@ -0,0 +1,15 @@ +# Example watch control file for uscan +# Rename this file to "watch" and then you can run the "uscan" command +# to check for upstream updates and more. +# See uscan(1) for format + +# Compulsory line, this is a version 4 file +version=4 + +# PGP signature mangle, so foo.tar.gz has foo.tar.gz.sig +#opts="pgpsigurlmangle=s%$%.sig%" + +# GitHub hosted projects +opts="filenamemangle=s%(?:.*?)?v?(\d[\d.]*)\.tar\.gz%-$1.tar.gz%" \ + https://github.com/86Box/86Box/tags \ + (?:.*?/)?v?(\d[\d.]*)\.tar\.gz debian uupdate diff --git a/sonar-project.properties b/sonar-project.properties new file mode 100644 index 000000000..781fad035 --- /dev/null +++ b/sonar-project.properties @@ -0,0 +1,12 @@ +sonar.projectKey=86Box_86Box +sonar.organization=86box + +# This is the name and version displayed in the SonarCloud UI. +#sonar.projectName=86Box +#sonar.projectVersion=1.0 + +# Path is relative to the sonar-project.properties file. Replace "\" by "/" on Windows. +#sonar.sources=. + +# Encoding of the source code. Default is default system encoding +#sonar.sourceEncoding=UTF-8 diff --git a/src/86box.c b/src/86box.c index 9647a8a6e..bf9be5086 100644 --- a/src/86box.c +++ b/src/86box.c @@ -1,29 +1,30 @@ /* - * 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. + * 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. + * This file is part of the 86Box distribution. * - * Main emulator module where most things are controlled. + * Main emulator module where most things are controlled. * + * Authors: Sarah Walker, + * Miran Grca, + * Fred N. van Kempen, * - * - * Authors: Sarah Walker, - * Miran Grca, - * Fred N. van Kempen, - * - * Copyright 2008-2020 Sarah Walker. - * Copyright 2016-2020 Miran Grca. - * Copyright 2017-2020 Fred N. van Kempen. - * Copyright 2021 Laci bá' - * Copyright 2021 dob205 + * Copyright 2008-2020 Sarah Walker. + * Copyright 2016-2020 Miran Grca. + * Copyright 2017-2020 Fred N. van Kempen. + * Copyright 2021 Laci bá' + * Copyright 2021 dob205 + * Copyright 2021 Andreas J. Reichel. + * Copyright 2021-2022 Jasmine Iwanek. */ #include #include #include #include +#include #include #include #include @@ -31,15 +32,15 @@ #include #ifndef _WIN32 -#include +# include +# include #endif #ifdef __APPLE__ -#include -#include -#include "mac/macOSXGlue.h" -#ifdef __aarch64__ -#include -#endif +# include +# include +# ifdef __aarch64__ +# include +# endif #endif #define HAVE_STDARG_H @@ -48,7 +49,7 @@ #include <86box/mem.h> #include "cpu.h" #ifdef USE_DYNAREC -# include "codegen_public.h" +# include "codegen_public.h" #endif #include "x86_ops.h" #include <86box/io.h> @@ -60,7 +61,6 @@ #include <86box/device.h> #include <86box/pit.h> #include <86box/random.h> -#include <86box/timer.h> #include <86box/nvr.h> #include <86box/machine.h> #include <86box/bugger.h> @@ -69,6 +69,7 @@ #include <86box/isartc.h> #include <86box/lpt.h> #include <86box/serial.h> +#include <86box/serial_passthrough.h> #include <86box/keyboard.h> #include <86box/mouse.h> #include <86box/gameport.h> @@ -81,96 +82,125 @@ #include <86box/scsi.h> #include <86box/scsi_device.h> #include <86box/cdrom.h> +#include <86box/cdrom_interface.h> #include <86box/zip.h> #include <86box/mo.h> #include <86box/scsi_disk.h> #include <86box/cdrom_image.h> +#include <86box/thread.h> #include <86box/network.h> #include <86box/sound.h> #include <86box/midi.h> #include <86box/snd_speaker.h> #include <86box/video.h> #include <86box/ui.h> +#include <86box/path.h> #include <86box/plat.h> #include <86box/version.h> +#include <86box/gdbstub.h> +#include <86box/machine_status.h> +#include <86box/apm.h> +#include <86box/acpi.h> +// Disable c99-designator to avoid the warnings about int ng +#ifdef __clang__ +# if __has_warning("-Wunused-but-set-variable") +# pragma clang diagnostic ignored "-Wunused-but-set-variable" +# endif +#endif /* Stuff that used to be globally declared in plat.h but is now extern there and declared here instead. */ -int dopause; /* system is paused */ -atomic_flag doresize; /* screen resize requested */ -volatile int is_quit; /* system exit requested */ -uint64_t timer_freq; -char emu_version[200]; /* version ID string */ +int dopause; /* system is paused */ +atomic_flag doresize; /* screen resize requested */ +volatile int is_quit; /* system exit requested */ +uint64_t timer_freq; +char emu_version[200]; /* version ID string */ #ifdef MTR_ENABLED -int tracing_on = 0; +int tracing_on = 0; #endif /* Commandline options. */ -int dump_on_exit = 0; /* (O) dump regs on exit */ -int do_dump_config = 0; /* (O) dump config on load */ -int start_in_fullscreen = 0; /* (O) start in fullscreen */ +int dump_on_exit = 0; /* (O) dump regs on exit */ +int start_in_fullscreen = 0; /* (O) start in fullscreen */ #ifdef _WIN32 -int force_debug = 0; /* (O) force debug output */ +int force_debug = 0; /* (O) force debug output */ #endif #ifdef USE_WX -int video_fps = RENDER_FPS; /* (O) render speed in fps */ +int video_fps = RENDER_FPS; /* (O) render speed in fps */ #endif -int settings_only = 0; /* (O) show only the settings dialog */ -int confirm_exit_cmdl = 1; /* (O) do not ask for confirmation on quit if set to 0 */ +int settings_only = 0; /* (O) show only the settings dialog */ +int confirm_exit_cmdl = 1; /* (O) do not ask for confirmation on quit if set to 0 */ #ifdef _WIN32 -uint64_t unique_id = 0; -uint64_t source_hwnd = 0; +uint64_t unique_id = 0; +uint64_t source_hwnd = 0; #endif -char rom_path[1024] = { '\0'}; /* (O) full path to ROMs */ -char log_path[1024] = { '\0'}; /* (O) full path of logfile */ -char vm_name[1024] = { '\0'}; /* (O) display name of the VM */ +char rom_path[1024] = { '\0' }; /* (O) full path to ROMs */ +rom_path_t rom_paths = { "", NULL }; /* (O) full paths to ROMs */ +char log_path[1024] = { '\0' }; /* (O) full path of logfile */ +char vm_name[1024] = { '\0' }; /* (O) display name of the VM */ +int do_nothing = 0; +int dump_missing = 0; +int clear_cmos = 0; +#ifdef USE_INSTRUMENT +uint8_t instru_enabled = 0; +uint64_t instru_run_ms = 0; +#endif +int clear_flash = 0; +int auto_paused = 0; /* Configuration values. */ -int window_w; /* (C) window size and */ -int window_h; /* position info */ -int window_x; -int window_y; -int window_remember; -int vid_resize; /* (C) allow resizing */ -int invert_display = 0; /* (C) invert the display */ -int suppress_overscan = 0; /* (C) suppress overscans */ -int scale = 0; /* (C) screen scale factor */ -int dpi_scale = 0; /* (C) DPI scaling of the emulated screen */ -int vid_api = 0; /* (C) video renderer */ -int vid_cga_contrast = 0; /* (C) video */ -int video_fullscreen = 0; /* (C) video */ -int video_fullscreen_scale = 0; /* (C) video */ -int video_fullscreen_first = 0; /* (C) video */ -int enable_overscan = 0; /* (C) video */ -int force_43 = 0; /* (C) video */ -int video_filter_method = 1; /* (C) video */ -int video_vsync = 0; /* (C) video */ -int video_framerate = -1; /* (C) video */ -char video_shader[512] = { '\0' }; /* (C) video */ -int serial_enabled[SERIAL_MAX] = {0,0}; /* (C) enable serial ports */ -int bugger_enabled = 0; /* (C) enable ISAbugger */ -int postcard_enabled = 0; /* (C) enable POST card */ -int isamem_type[ISAMEM_MAX] = { 0,0,0,0 }; /* (C) enable ISA mem cards */ -int isartc_type = 0; /* (C) enable ISA RTC card */ -int gfxcard = 0; /* (C) graphics/video card */ -int sound_is_float = 1; /* (C) sound uses FP values */ -int GAMEBLASTER = 0; /* (C) sound option */ -int GUS = 0; /* (C) sound option */ -int SSI2001 = 0; /* (C) sound option */ -int voodoo_enabled = 0; /* (C) video option */ -uint32_t mem_size = 0; /* (C) memory size (Installed on system board)*/ -uint32_t isa_mem_size = 0; /* (C) memory size (ISA Memory Cards) */ -int cpu_use_dynarec = 0; /* (C) cpu uses/needs Dyna */ -int cpu = 0; /* (C) cpu type */ -int fpu_type = 0; /* (C) fpu type */ -int time_sync = 0; /* (C) enable time sync */ -int confirm_reset = 1; /* (C) enable reset confirmation */ -int confirm_exit = 1; /* (C) enable exit confirmation */ -int confirm_save = 1; /* (C) enable save confirmation */ -int enable_discord = 0; /* (C) enable Discord integration */ -int enable_crashdump = 0; /* (C) enable crash dump */ +int window_remember; +int vid_resize; /* (C) allow resizing */ +int invert_display = 0; /* (C) invert the display */ +int suppress_overscan = 0; /* (C) suppress overscans */ +int scale = 0; /* (C) screen scale factor */ +int dpi_scale = 0; /* (C) DPI scaling of the emulated + screen */ +int vid_api = 0; /* (C) video renderer */ +int vid_cga_contrast = 0; /* (C) video */ +int video_fullscreen = 0; /* (C) video */ +int video_fullscreen_scale = 0; /* (C) video */ +int video_fullscreen_first = 0; /* (C) video */ +int enable_overscan = 0; /* (C) video */ +int force_43 = 0; /* (C) video */ +int video_filter_method = 1; /* (C) video */ +int video_vsync = 0; /* (C) video */ +int video_framerate = -1; /* (C) video */ +char video_shader[512] = { '\0' }; /* (C) video */ +bool serial_passthrough_enabled[SERIAL_MAX] = { 0, 0, 0, 0 }; /* (C) activation and kind of + pass-through for serial ports */ +int bugger_enabled = 0; /* (C) enable ISAbugger */ +int postcard_enabled = 0; /* (C) enable POST card */ +int isamem_type[ISAMEM_MAX] = { 0, 0, 0, 0 }; /* (C) enable ISA mem cards */ +int isartc_type = 0; /* (C) enable ISA RTC card */ +int gfxcard[2] = { 0, 0 }; /* (C) graphics/video card */ +int show_second_monitors = 1; /* (C) show non-primary monitors */ +int sound_is_float = 1; /* (C) sound uses FP values */ +int voodoo_enabled = 0; /* (C) video option */ +int ibm8514_standalone_enabled = 0; /* (C) video option */ +int xga_standalone_enabled = 0; /* (C) video option */ +uint32_t mem_size = 0; /* (C) memory size (Installed on + system board)*/ +uint32_t isa_mem_size = 0; /* (C) memory size (ISA Memory Cards) */ +int cpu_use_dynarec = 0; /* (C) cpu uses/needs Dyna */ +int cpu = 0; /* (C) cpu type */ +int fpu_type = 0; /* (C) fpu type */ +int fpu_softfloat = 0; /* (C) fpu uses softfloat */ +int time_sync = 0; /* (C) enable time sync */ +int confirm_reset = 1; /* (C) enable reset confirmation */ +int confirm_exit = 1; /* (C) enable exit confirmation */ +int confirm_save = 1; /* (C) enable save confirmation */ +int enable_discord = 0; /* (C) enable Discord integration */ +int pit_mode = -1; /* (C) force setting PIT mode */ +int fm_driver = 0; /* (C) select FM sound driver */ +int open_dir_usr_path = 0; /* (C) default file open dialog directory + of usr_path */ +int video_fullscreen_scale_maximized = 0; /* (C) Whether fullscreen scaling settings + also apply when maximized. */ +int do_auto_pause = 0; /* (C) Auto-pause the emulator on focus + loss */ /* Statistics. */ extern int mmuflush; @@ -178,36 +208,40 @@ extern int readlnum; extern int writelnum; /* emulator % */ -int fps; +int fps; int framecount; -extern int CPUID; -extern int output; -int atfullspeed; +extern int CPUID; +extern int output; +int atfullspeed; -char exe_path[2048]; /* path (dir) of executable */ -char usr_path[1024]; /* path (dir) of user data */ -char cfg_path[1024]; /* full path of config file */ -FILE *stdlog = NULL; /* file to log output to */ -int scrnsz_x = SCREEN_RES_X; /* current screen size, X */ -int scrnsz_y = SCREEN_RES_Y; /* current screen size, Y */ -int config_changed; /* config has changed */ -int title_update; -int framecountx = 0; -int hard_reset_pending = 0; +char exe_path[2048]; /* path (dir) of executable */ +char usr_path[1024]; /* path (dir) of user data */ +char cfg_path[1024]; /* full path of config file */ +FILE *stdlog = NULL; /* file to log output to */ +#if 0 +int scrnsz_x = SCREEN_RES_X; /* current screen size, X */ +int scrnsz_y = SCREEN_RES_Y; /* current screen size, Y */ +#endif +int config_changed; /* config has changed */ +int title_update; +int framecountx = 0; +int hard_reset_pending = 0; - -int unscaled_size_x = SCREEN_RES_X; /* current unscaled size X */ -int unscaled_size_y = SCREEN_RES_Y; /* current unscaled size Y */ +#if 0 +int unscaled_size_x = SCREEN_RES_X; /* current unscaled size X */ +int unscaled_size_y = SCREEN_RES_Y; /* current unscaled size Y */ int efscrnsz_y = SCREEN_RES_Y; +#endif +static wchar_t mouse_msg[3][200]; -static wchar_t mouse_msg[3][200]; - +static int do_pause_ack = 0; +static volatile int pause_ack = 0; #ifndef RELEASE_BUILD static char buff[1024]; -static int seen = 0; +static int seen = 0; static int suppr_seen = 1; #endif @@ -226,73 +260,70 @@ pclog_ex(const char *fmt, va_list ap) char temp[1024]; if (strcmp(fmt, "") == 0) - return; + return; if (stdlog == NULL) { - if (log_path[0] != '\0') { - stdlog = plat_fopen(log_path, "w"); - if (stdlog == NULL) - stdlog = stdout; - } else - stdlog = stdout; + if (log_path[0] != '\0') { + stdlog = plat_fopen(log_path, "w"); + if (stdlog == NULL) + stdlog = stdout; + } else + stdlog = stdout; } vsprintf(temp, fmt, ap); - if (suppr_seen && ! strcmp(buff, temp)) - seen++; + if (suppr_seen && !strcmp(buff, temp)) + seen++; else { - if (suppr_seen && seen) - fprintf(stdlog, "*** %d repeats ***\n", seen); - seen = 0; - strcpy(buff, temp); - fprintf(stdlog, "%s", temp); + if (suppr_seen && seen) + fprintf(stdlog, "*** %d repeats ***\n", seen); + seen = 0; + strcpy(buff, temp); + fprintf(stdlog, "%s", temp); } fflush(stdlog); #endif } - void pclog_toggle_suppr(void) { #ifndef RELEASE_BUILD - suppr_seen ^= 1; + suppr_seen ^= 1; #endif } - /* Log something. We only do this in non-release builds. */ void pclog(const char *fmt, ...) { #ifndef RELEASE_BUILD - va_list ap; + va_list ap; - va_start(ap, fmt); - pclog_ex(fmt, ap); - va_end(ap); + va_start(ap, fmt); + pclog_ex(fmt, ap); + va_end(ap); #endif } - /* Log a fatal error, and display a UI message before exiting. */ void fatal(const char *fmt, ...) { - char temp[1024]; + char temp[1024]; va_list ap; - char *sp; + char *sp; va_start(ap, fmt); if (stdlog == NULL) { - if (log_path[0] != '\0') { - stdlog = plat_fopen(log_path, "w"); - if (stdlog == NULL) - stdlog = stdout; - } else - stdlog = stdout; + if (log_path[0] != '\0') { + stdlog = plat_fopen(log_path, "w"); + if (stdlog == NULL) + stdlog = stdout; + } else + stdlog = stdout; } vsprintf(temp, fmt, ap); @@ -309,7 +340,8 @@ fatal(const char *fmt, ...) #endif /* Make sure the message does not have a trailing newline. */ - if ((sp = strchr(temp, '\n')) != NULL) *sp = '\0'; + if ((sp = strchr(temp, '\n')) != NULL) + *sp = '\0'; /* Cleanly terminate all of the emulator's components so as to avoid things like threads getting stuck. */ @@ -322,20 +354,19 @@ fatal(const char *fmt, ...) exit(-1); } - void fatal_ex(const char *fmt, va_list ap) { - char temp[1024]; + char temp[1024]; char *sp; if (stdlog == NULL) { - if (log_path[0] != '\0') { - stdlog = plat_fopen(log_path, "w"); - if (stdlog == NULL) - stdlog = stdout; - } else - stdlog = stdout; + if (log_path[0] != '\0') { + stdlog = plat_fopen(log_path, "w"); + if (stdlog == NULL) + stdlog = stdout; + } else + stdlog = stdout; } vsprintf(temp, fmt, ap); @@ -351,7 +382,8 @@ fatal_ex(const char *fmt, va_list ap) #endif /* Make sure the message does not have a trailing newline. */ - if ((sp = strchr(temp, '\n')) != NULL) *sp = '\0'; + if ((sp = strchr(temp, '\n')) != NULL) + *sp = '\0'; /* Cleanly terminate all of the emulator's components so as to avoid things like threads getting stuck. */ @@ -362,26 +394,48 @@ fatal_ex(const char *fmt, va_list ap) fflush(stdlog); } - #ifdef ENABLE_PC_LOG int pc_do_log = ENABLE_PC_LOG; - static void pc_log(const char *fmt, ...) { - va_list ap; + va_list ap; - if (pc_do_log) { - va_start(ap, fmt); - pclog_ex(fmt, ap); - va_end(ap); - } + if (pc_do_log) { + va_start(ap, fmt); + pclog_ex(fmt, ap); + va_end(ap); + } } #else -#define pc_log(fmt, ...) +# define pc_log(fmt, ...) #endif +static void +delete_nvr_file(uint8_t flash) +{ + char *fn = NULL; + int c; + + /* Set up the NVR file's name. */ + c = strlen(machine_get_internal_name()) + 5; + fn = (char *) malloc(c + 1); + + if (fn == NULL) + fatal("Error allocating memory for the removal of the %s file\n", + flash ? "BIOS flash" : "CMOS"); + + if (flash) + sprintf(fn, "%s.bin", machine_get_internal_name()); + else + sprintf(fn, "%s.nvr", machine_get_internal_name()); + + remove(nvr_path(fn)); + + free(fn); + fn = NULL; +} /* * Perform initial startup of the PC. @@ -393,564 +447,665 @@ pc_log(const char *fmt, ...) int pc_init(int argc, char *argv[]) { - char path[2048], path2[2048]; - char *cfg = NULL, *p; -#if !defined(__APPLE__) && !defined(_WIN32) - char *appimage; + char *ppath = NULL; + char *rpath = NULL; + char *cfg = NULL; + char *p; + char temp[2048]; + char *fn[FDD_NUM] = { NULL }; + char drive = 0; + char *temp2 = NULL; + char *what; + const struct tm *info; + time_t now; + int c; + int lvmp = 0; +#ifdef ENABLE_NG + int ng = 0; #endif - char temp[128]; - struct tm *info; - time_t now; - int c, vmrp = 0; - int ng = 0, lvmp = 0; - uint32_t *uid, *shwnd; - uint32_t lang_init = 0; - - /* Grab the executable's full path. */ - plat_get_exe_name(exe_path, sizeof(exe_path)-1); - p = plat_get_filename(exe_path); - *p = '\0'; - - /* - * Get the current working directory. - * - * This is normally the directory from where the - * program was run. If we have been started via - * a shortcut (desktop icon), however, the CWD - * could have been set to something else. - */ - plat_getcwd(usr_path, sizeof(usr_path) - 1); - plat_getcwd(rom_path, sizeof(rom_path) - 1); - - memset(path, 0x00, sizeof(path)); - memset(path2, 0x00, sizeof(path)); - - for (c=1; c= 16) && !strcmp(&exe_path[c - 16], "/Contents/MacOS/")) { + exe_path[c - 16] = '\0'; + p = path_get_filename(exe_path); + *p = '\0'; + } + if (!strncmp(exe_path, "/private/var/folders/", 21)) { + ui_msgbox_header(MBX_FATAL, L"App Translocation", EMU_NAME_W L" cannot determine the emulated machine's location due to a macOS security feature. Please move the " EMU_NAME_W L" app to another folder (not /Applications), or make a copy of it and open that copy instead."); + return 0; + } #elif !defined(_WIN32) - appimage = getenv("APPIMAGE"); - if (appimage && (appimage[0] != '\0')) { - plat_get_dirname(path2, appimage); - plat_path_slash(path2); - strcat(path2, "roms"); - plat_path_slash(path2); - } + /* Grab the actual path if we are an AppImage. */ + p = getenv("APPIMAGE"); + if (p && (p[0] != '\0')) + path_get_dirname(exe_path, p); #endif - } - if (vmrp && (path2[0] == '\0')) { - strcpy(path2, usr_path); - plat_path_slash(path2); - strcat(path2, "roms"); - plat_path_slash(path2); - } + path_slash(exe_path); - /* - * If the user provided a path for ROMs, use that - * instead of the current working directory. We do - * make sure that if that was a relative path, we - * make it absolute. - */ - if (path2[0] != '\0') { - if (! plat_path_abs(path2)) { - /* - * This looks like a relative path. - * - * Add it to the current working directory - * to convert it (back) to an absolute path. - */ - strcat(rom_path, path2); - } else { - /* - * The user-provided path seems like an - * absolute path, so just use that. - */ - strcpy(rom_path, path2); - } + /* + * Get the current working directory. + * + * This is normally the directory from where the + * program was run. If we have been started via + * a shortcut (desktop icon), however, the CWD + * could have been set to something else. + */ + plat_getcwd(usr_path, sizeof(usr_path) - 1); + plat_getcwd(rom_path, sizeof(rom_path) - 1); - /* If the specified path does not yet exist, - create it. */ - if (! plat_dir_check(rom_path)) - plat_dir_create(rom_path); - } else - rom_path[0] = '\0'; + for (c = 1; c < argc; c++) { + if (argv[c][0] != '-') + break; - /* Grab the name of the configuration file. */ - if (cfg == NULL) - cfg = CONFIG_FILE; + if (!strcasecmp(argv[c], "--help") || !strcasecmp(argv[c], "-?")) { +usage: + for (uint8_t i = 0; i < FDD_NUM; i++) { + if (fn[i] != NULL) { + free(fn[i]); + fn[i] = NULL; + } + } - /* - * If the configuration file name has (part of) - * a pathname, consider that to be part of the - * actual working directory. - * - * This can happen when people load a config - * file using the UI, for example. - */ - p = plat_get_filename(cfg); - if (cfg != p) { - /* - * OK, the configuration file name has a - * path component. Separate the two, and - * add the path component to the cfg path. - */ - *(p-1) = '\0'; + printf("\nUsage: 86box [options] [cfg-file]\n\n"); + printf("Valid options are:\n\n"); + printf("-? or --help - show this information\n"); + printf("-C or --config path - set 'path' to be config file\n"); +#ifdef _WIN32 + printf("-D or --debug - force debug output logging\n"); +#endif +#if 0 + printf("-E or --nographic - forces the old behavior\n"); +#endif + printf("-F or --fullscreen - start in fullscreen mode\n"); + printf("-G or --lang langid - start with specified language (e.g. en-US, or system)\n"); +#ifdef _WIN32 + printf("-H or --hwnd id,hwnd - sends back the main dialog's hwnd\n"); +#endif + printf("-I or --image d:path - load 'path' as floppy image on drive d\n"); +#ifdef USE_INSTRUMENT + printf("-J or --instrument name - set 'name' to be the profiling instrument\n"); +#endif + printf("-K or --keycodes codes - set 'codes' to be the uncapture combination\n"); + printf("-L or --logfile path - set 'path' to be the logfile\n"); + printf("-M or --missing - dump missing machines and video cards\n"); + printf("-N or --noconfirm - do not ask for confirmation on quit\n"); + printf("-P or --vmpath path - set 'path' to be root for vm\n"); + printf("-R or --rompath path - set 'path' to be ROM path\n"); + printf("-S or --settings - show only the settings dialog\n"); + printf("-V or --vmname name - overrides the name of the running VM\n"); + printf("-X or --clear what - clears the 'what' (cmos/flash/both)\n"); + printf("-Y or --donothing - do not show any UI or run the emulation\n"); + printf("-Z or --lastvmpath - the last parameter is VM path rather than config\n"); + printf("\nA config file can be specified. If none is, the default file will be used.\n"); + return 0; + } else if (!strcasecmp(argv[c], "--lastvmpath") || !strcasecmp(argv[c], "-Z")) { + lvmp = 1; +#ifdef _WIN32 + } else if (!strcasecmp(argv[c], "--debug") || !strcasecmp(argv[c], "-D")) { + force_debug = 1; +#endif +#ifdef ENABLE_NG + } else if (!strcasecmp(argv[c], "--nographic") || !strcasecmp(argv[c], "-E")) { + /* Currently does nothing, but if/when we implement a built-in manager, + it's going to force the manager not to run, allowing the old usage + without parameter. */ + ng = 1; +#endif + } else if (!strcasecmp(argv[c], "--fullscreen") || !strcasecmp(argv[c], "-F")) { + start_in_fullscreen = 1; + } else if (!strcasecmp(argv[c], "--logfile") || !strcasecmp(argv[c], "-L")) { + if ((c + 1) == argc) + goto usage; - /* - * If this is an absolute path, keep it, as - * there is probably have a reason to do so. - * Otherwise, assume the pathname given is - * relative to whatever the usr_path is. - */ - if (plat_path_abs(cfg)) - strcpy(usr_path, cfg); - else - strcat(usr_path, cfg); - } + strcpy(log_path, argv[++c]); + } else if (!strcasecmp(argv[c], "--vmpath") || !strcasecmp(argv[c], "-P")) { + if ((c + 1) == argc) + goto usage; - /* Make sure we have a trailing backslash. */ - plat_path_slash(usr_path); - if (rom_path[0] != '\0') - plat_path_slash(rom_path); + ppath = argv[++c]; + } else if (!strcasecmp(argv[c], "--rompath") || !strcasecmp(argv[c], "-R")) { + if ((c + 1) == argc) + goto usage; - /* At this point, we can safely create the full path name. */ - plat_append_filename(cfg_path, usr_path, p); + rpath = argv[++c]; + rom_add_path(rpath); + } else if (!strcasecmp(argv[c], "--config") || !strcasecmp(argv[c], "-C")) { + if ((c + 1) == argc || plat_dir_check(argv[c + 1])) + goto usage; - /* - * Get the current directory's name - * - * At this point usr_path is perfectly initialized. - * If no --vmname parameter specified we'll use the - * working directory name as the VM's name. - */ - if (strlen(vm_name) == 0) { - char ltemp[1024] = { '\0'}; - plat_get_dirname(ltemp, usr_path); - strcpy(vm_name, plat_get_filename(ltemp)); - } + cfg = argv[++c]; + } else if (!strcasecmp(argv[c], "--image") || !strcasecmp(argv[c], "-I")) { + if ((c + 1) == argc) + goto usage; - /* - * This is where we start outputting to the log file, - * if there is one. Create a little info header first. - */ - (void)time(&now); - info = localtime(&now); - strftime(temp, sizeof(temp), "%Y/%m/%d %H:%M:%S", info); - pclog("#\n# %ls v%ls logfile, created %s\n#\n", - EMU_NAME_W, EMU_VERSION_FULL_W, temp); - pclog("# VM: %s\n#\n", vm_name); - pclog("# Emulator path: %s\n", exe_path); - pclog("# Userfiles path: %s\n", usr_path); - if (rom_path[0] != '\0') - pclog("# ROM path: %s\n", rom_path); - else - pclog("# ROM path: %sroms\\\n", exe_path); - pclog("# Configuration file: %s\n#\n\n", cfg_path); - /* - * We are about to read the configuration file, which MAY - * put data into global variables (the hard- and floppy - * disks are an example) so we have to initialize those - * modules before we load the config.. - */ - hdd_init(); - network_init(); - mouse_init(); - cdrom_global_init(); - zip_global_init(); - mo_global_init(); + temp2 = (char *) calloc(2048, 1); + sscanf(argv[++c], "%c:%s", &drive, temp2); + if (drive > 0x40) + drive = (drive & 0x1f) - 1; + else + drive = drive & 0x1f; + if (drive < 0) + drive = 0; + if (drive >= FDD_NUM) + drive = FDD_NUM - 1; + fn[(int) drive] = (char *) calloc(2048, 1); + strcpy(fn[(int) drive], temp2); + pclog("Drive %c: %s\n", drive + 0x41, fn[(int) drive]); + free(temp2); + temp2 = NULL; + } else if (!strcasecmp(argv[c], "--vmname") || !strcasecmp(argv[c], "-V")) { + if ((c + 1) == argc) + goto usage; - /* Load the configuration file. */ - config_load(); - - /* Load the desired language */ - if (lang_init) - lang_id = lang_init; + strcpy(vm_name, argv[++c]); + } else if (!strcasecmp(argv[c], "--settings") || !strcasecmp(argv[c], "-S")) { + settings_only = 1; + } else if (!strcasecmp(argv[c], "--noconfirm") || !strcasecmp(argv[c], "-N")) { + confirm_exit_cmdl = 0; + } else if (!strcasecmp(argv[c], "--missing") || !strcasecmp(argv[c], "-M")) { + dump_missing = 1; + } else if (!strcasecmp(argv[c], "--donothing") || !strcasecmp(argv[c], "-Y")) { + do_nothing = 1; + } else if (!strcasecmp(argv[c], "--keycodes") || !strcasecmp(argv[c], "-K")) { + if ((c + 1) == argc) + goto usage; - /* All good! */ - return(1); + sscanf(argv[++c], "%03hX,%03hX,%03hX,%03hX,%03hX,%03hX", + &key_prefix_1_1, &key_prefix_1_2, &key_prefix_2_1, &key_prefix_2_2, + &key_uncapture_1, &key_uncapture_2); + } else if (!strcasecmp(argv[c], "--clearboth") || !strcasecmp(argv[c], "-X")) { + if ((c + 1) == argc) + goto usage; + + what = argv[++c]; + + if (!strcasecmp(what, "cmos")) + clear_cmos = 1; + else if (!strcasecmp(what, "flash")) + clear_flash = 1; + else if (!strcasecmp(what, "both")) { + clear_cmos = 1; + clear_flash = 1; + } else + goto usage; +#ifdef _WIN32 + } else if (!strcasecmp(argv[c], "--hwnd") || !strcasecmp(argv[c], "-H")) { + + if ((c + 1) == argc) + goto usage; + + uid = (uint32_t *) &unique_id; + shwnd = (uint32_t *) &source_hwnd; + sscanf(argv[++c], "%08X%08X,%08X%08X", uid + 1, uid, shwnd + 1, shwnd); +#endif + } else if (!strcasecmp(argv[c], "--lang") || !strcasecmp(argv[c], "-G")) { + // This function is currently unimplemented for *nix but has placeholders. + + lang_init = plat_language_code(argv[++c]); + if (!lang_init) + printf("\nWarning: Invalid language code, ignoring --lang parameter.\n\n"); + + // The return value of 0 only means that the code is invalid, + // not related to that translation is exists or not for the + // selected language. + } else if (!strcasecmp(argv[c], "--test") || !strcasecmp(argv[c], "-T")) { + /* some (undocumented) test function here.. */ + + /* .. and then exit. */ + return 0; +#ifdef USE_INSTRUMENT + } else if (!strcasecmp(argv[c], "--instrument") || !strcasecmp(argv[c], "-J")) { + if ((c + 1) == argc) + goto usage; + instru_enabled = 1; + sscanf(argv[++c], "%llu", &instru_run_ms); +#endif + } + + /* Uhm... out of options here.. */ + else + goto usage; + } + + /* One argument (config file) allowed. */ + if (c < argc) { + if (lvmp) + ppath = argv[c++]; + else + cfg = argv[c++]; + } + + if (c != argc) + goto usage; + + path_slash(usr_path); + path_slash(rom_path); + + /* + * If the user provided a path for files, use that + * instead of the current working directory. We do + * make sure that if that was a relative path, we + * make it absolute. + */ + if (ppath != NULL) { + if (!path_abs(ppath)) { + /* + * This looks like a relative path. + * + * Add it to the current working directory + * to convert it (back) to an absolute path. + */ + strcat(usr_path, ppath); + } else { + /* + * The user-provided path seems like an + * absolute path, so just use that. + */ + strcpy(usr_path, ppath); + } + + /* If the specified path does not yet exist, + create it. */ + if (!plat_dir_check(usr_path)) + plat_dir_create(usr_path); + } + + // Add the VM-local ROM path. + path_append_filename(temp, usr_path, "roms"); + rom_add_path(temp); + + // Add the standard ROM path in the same directory as the executable. + path_append_filename(temp, exe_path, "roms"); + rom_add_path(temp); + + plat_init_rom_paths(); + + /* + * If the user provided a path for ROMs, use that + * instead of the current working directory. We do + * make sure that if that was a relative path, we + * make it absolute. + */ + if (rpath != NULL) { + if (!path_abs(rpath)) { + /* + * This looks like a relative path. + * + * Add it to the current working directory + * to convert it (back) to an absolute path. + */ + strcat(rom_path, rpath); + } else { + /* + * The user-provided path seems like an + * absolute path, so just use that. + */ + strcpy(rom_path, rpath); + } + + /* If the specified path does not yet exist, + create it. */ + if (!plat_dir_check(rom_path)) + plat_dir_create(rom_path); + } else + rom_path[0] = '\0'; + + /* Grab the name of the configuration file. */ + if (cfg == NULL) + cfg = CONFIG_FILE; + + /* + * If the configuration file name has (part of) + * a pathname, consider that to be part of the + * actual working directory. + * + * This can happen when people load a config + * file using the UI, for example. + */ + p = path_get_filename(cfg); + if (cfg != p) { + /* + * OK, the configuration file name has a + * path component. Separate the two, and + * add the path component to the cfg path. + */ + *(p - 1) = '\0'; + + /* + * If this is an absolute path, keep it, as + * there is probably have a reason to do so. + * Otherwise, assume the pathname given is + * relative to whatever the usr_path is. + */ + if (path_abs(cfg)) + strcpy(usr_path, cfg); + else + strcat(usr_path, cfg); + } + + /* Make sure we have a trailing backslash. */ + path_slash(usr_path); + if (rom_path[0] != '\0') + path_slash(rom_path); + + /* At this point, we can safely create the full path name. */ + path_append_filename(cfg_path, usr_path, p); + + /* + * Get the current directory's name + * + * At this point usr_path is perfectly initialized. + * If no --vmname parameter specified we'll use the + * working directory name as the VM's name. + */ + if (strlen(vm_name) == 0) { + char ltemp[1024] = { '\0' }; + path_get_dirname(ltemp, usr_path); + strcpy(vm_name, path_get_filename(ltemp)); + } + + /* + * This is where we start outputting to the log file, + * if there is one. Create a little info header first. + */ + (void) time(&now); + info = localtime(&now); + strftime(temp, sizeof(temp), "%Y/%m/%d %H:%M:%S", info); + pclog("#\n# %ls v%ls logfile, created %s\n#\n", + EMU_NAME_W, EMU_VERSION_FULL_W, temp); + pclog("# VM: %s\n#\n", vm_name); + pclog("# Emulator path: %s\n", exe_path); + pclog("# Userfiles path: %s\n", usr_path); + for (rom_path_t *rom_path = &rom_paths; rom_path != NULL; rom_path = rom_path->next) { + pclog("# ROM path: %s\n", rom_path->path); + } + + pclog("# Configuration file: %s\n#\n\n", cfg_path); + /* + * We are about to read the configuration file, which MAY + * put data into global variables (the hard- and floppy + * disks are an example) so we have to initialize those + * modules before we load the config.. + */ + hdd_init(); + network_init(); + mouse_init(); + cdrom_global_init(); + zip_global_init(); + mo_global_init(); + + /* Load the configuration file. */ + config_load(); + + /* Clear the CMOS and/or BIOS flash file, if we were started with + the relevant parameter(s). */ + if (clear_cmos) { + delete_nvr_file(0); + clear_cmos = 0; + } + + if (clear_flash) { + delete_nvr_file(1); + clear_flash = 0; + } + + for (uint8_t i = 0; i < FDD_NUM; i++) { + if (fn[i] != NULL) { + if (strlen(fn[i]) <= 511) + strncpy(floppyfns[i], fn[i], 511); + free(fn[i]); + fn[i] = NULL; + } + } + + /* Load the desired language */ + if (lang_init) + lang_id = lang_init; + + gdbstub_init(); + + /* All good! */ + return 1; } - void pc_speed_changed(void) { - if (cpu_s->cpu_type >= CPU_286) - pit_set_clock(cpu_s->rspeed); - else - pit_set_clock(14318184.0); + if (cpu_s->cpu_type >= CPU_286) + pit_set_clock(cpu_s->rspeed); + else + pit_set_clock((uint32_t) 14318184.0); } - void pc_full_speed(void) { - if (! atfullspeed) { - pc_log("Set fullspeed - %i %i\n", is386, AT); - pc_speed_changed(); - } - atfullspeed = 1; + if (!atfullspeed) { + pc_log("Set fullspeed - %i %i\n", is386, is486); + pc_speed_changed(); + } + atfullspeed = 1; } - /* Initialize modules, ran once, after pc_init. */ int pc_init_modules(void) { - int c, m; - wchar_t temp[512]; - char tempc[512]; + int c; + int m; + wchar_t temp[512]; + char tempc[512]; -#ifdef PRINT_MISSING_MACHINES_AND_VIDEO_CARDS - c = m = 0; - while (machine_get_internal_name_ex(c) != NULL) { - m = machine_available(c); - if (!m) - pclog("Missing machine: %s\n", machine_getname_ex(c)); - c++; - } + if (dump_missing) { + dump_missing = 0; - c = m = 0; - while (video_get_internal_name(c) != NULL) { - memset(tempc, 0, sizeof(tempc)); - device_get_name(video_card_getdevice(c), 0, tempc); - if ((c > 1) && !(tempc[0])) - break; - m = video_card_available(c); - if (!m) - pclog("Missing video card: %s\n", tempc); - c++; - } -#endif + c = m = 0; + while (machine_get_internal_name_ex(c) != NULL) { + m = machine_available(c); + if (!m) + pclog("Missing machine: %s\n", machine_getname_ex(c)); + c++; + } - pc_log("Scanning for ROM images:\n"); - c = m = 0; - while (machine_get_internal_name_ex(m) != NULL) { - c += machine_available(m); - m++; - } - if (c == 0) { - /* No usable ROMs found, aborting. */ - return(0); - } - pc_log("A total of %d ROM sets have been loaded.\n", c); + c = m = 0; + while (video_get_internal_name(c) != NULL) { + memset(tempc, 0, sizeof(tempc)); + device_get_name(video_card_getdevice(c), 0, tempc); + if ((c > 1) && !(tempc[0])) + break; + m = video_card_available(c); + if (!m) + pclog("Missing video card: %s\n", tempc); + c++; + } + } - /* Load the ROMs for the selected machine. */ - if (! machine_available(machine)) { - swprintf(temp, sizeof(temp), plat_get_string(IDS_2063), machine_getname()); - c = 0; - machine = -1; - while (machine_get_internal_name_ex(c) != NULL) { - if (machine_available(c)) { - ui_msgbox_header(MBX_INFO, (wchar_t *) IDS_2128, temp); - machine = c; - config_save(); - break; - } - c++; - } - if (machine == -1) { - fatal("No available machines\n"); - exit(-1); - return(0); - } - } + pc_log("Scanning for ROM images:\n"); + c = m = 0; + while (machine_get_internal_name_ex(m) != NULL) { + c += machine_available(m); + m++; + } + if (c == 0) { + /* No usable ROMs found, aborting. */ + return 0; + } + pc_log("A total of %d ROM sets have been loaded.\n", c); - /* Make sure we have a usable video card. */ - if (! video_card_available(gfxcard)) { - memset(tempc, 0, sizeof(tempc)); - device_get_name(video_card_getdevice(gfxcard), 0, tempc); - swprintf(temp, sizeof(temp), plat_get_string(IDS_2064), tempc); - c = 0; - while (video_get_internal_name(c) != NULL) { - gfxcard = -1; - if (video_card_available(c)) { - ui_msgbox_header(MBX_INFO, (wchar_t *) IDS_2128, temp); - gfxcard = c; - config_save(); - break; - } - c++; - } - if (gfxcard == -1) { - fatal("No available video cards\n"); - exit(-1); - return(0); - } - } + /* Load the ROMs for the selected machine. */ + if (!machine_available(machine)) { + swprintf(temp, sizeof_w(temp), plat_get_string(IDS_2063), machine_getname()); + c = 0; + machine = -1; + while (machine_get_internal_name_ex(c) != NULL) { + if (machine_available(c)) { + ui_msgbox_header(MBX_INFO, (wchar_t *) IDS_2129, temp); + machine = c; + config_save(); + break; + } + c++; + } + if (machine == -1) { + fatal("No available machines\n"); + exit(-1); + } + } - atfullspeed = 0; + /* Make sure we have a usable video card. */ + if (!video_card_available(gfxcard[0])) { + memset(tempc, 0, sizeof(tempc)); + device_get_name(video_card_getdevice(gfxcard[0]), 0, tempc); + swprintf(temp, sizeof_w(temp), plat_get_string(IDS_2064), tempc); + c = 0; + while (video_get_internal_name(c) != NULL) { + gfxcard[0] = -1; + if (video_card_available(c)) { + ui_msgbox_header(MBX_INFO, (wchar_t *) IDS_2129, temp); + gfxcard[0] = c; + config_save(); + break; + } + c++; + } + if (gfxcard[0] == -1) { + fatal("No available video cards\n"); + exit(-1); + } + } - random_init(); + if (!video_card_available(gfxcard[1])) { + char tempc[512] = { 0 }; + device_get_name(video_card_getdevice(gfxcard[1]), 0, tempc); + swprintf(temp, sizeof_w(temp), plat_get_string(IDS_2163), tempc); + ui_msgbox_header(MBX_INFO, (wchar_t *) IDS_2129, temp); + gfxcard[1] = 0; + } - mem_init(); + atfullspeed = 0; + + random_init(); + + mem_init(); #ifdef USE_DYNAREC -#if defined(__APPLE__) && defined(__aarch64__) - pthread_jit_write_protect_np(0); -#endif - codegen_init(); -#if defined(__APPLE__) && defined(__aarch64__) - pthread_jit_write_protect_np(1); -#endif +# if defined(__APPLE__) && defined(__aarch64__) + if (__builtin_available(macOS 11.0, *)) { + pthread_jit_write_protect_np(0); + } +# endif + codegen_init(); +# if defined(__APPLE__) && defined(__aarch64__) + if (__builtin_available(macOS 11.0, *)) { + pthread_jit_write_protect_np(1); + } +# endif #endif - keyboard_init(); - joystick_init(); + keyboard_init(); + joystick_init(); - video_init(); + video_init(); - fdd_init(); + fdd_init(); - sound_init(); + sound_init(); - hdc_init(); + hdc_init(); - video_reset_close(); + video_reset_close(); - return(1); + machine_status_init(); + + if (do_nothing) { + do_nothing = 0; + exit(-1); + } + + return 1; } - void pc_send_ca(uint16_t sc) { - keyboard_input(1, 0x1D); /* Ctrl key pressed */ - keyboard_input(1, 0x38); /* Alt key pressed */ - keyboard_input(1, sc); - keyboard_input(0, sc); - keyboard_input(0, 0x38); /* Alt key released */ - keyboard_input(0, 0x1D); /* Ctrl key released */ + keyboard_input(1, 0x1D); /* Ctrl key pressed */ + keyboard_input(1, 0x38); /* Alt key pressed */ + keyboard_input(1, sc); + keyboard_input(0, sc); + keyboard_input(0, 0x38); /* Alt key released */ + keyboard_input(0, 0x1D); /* Ctrl key released */ } - /* Send the machine a Control-Alt-DEL sequence. */ void pc_send_cad(void) { - pc_send_ca(0x153); + pc_send_ca(0x153); } - /* Send the machine a Control-Alt-ESC sequence. */ void pc_send_cae(void) { - pc_send_ca(1); + pc_send_ca(1); } - void pc_reset_hard_close(void) { - ui_sb_set_ready(0); + ui_sb_set_ready(0); - /* Close all the memory mappings. */ - mem_close(); + /* Close all the memory mappings. */ + mem_close(); - network_timer_stop(); + /* Turn off timer processing to avoid potential segmentation faults. */ + timer_close(); - /* Turn off timer processing to avoid potential segmentation faults. */ - timer_close(); + suppress_overscan = 0; - suppress_overscan = 0; + nvr_save(); + nvr_close(); - nvr_save(); - nvr_close(); + mouse_close(); - mouse_close(); + lpt_devices_close(); - lpt_devices_close(); + device_close_all(); - device_close_all(); + scsi_device_close_all(); - scsi_device_close_all(); + midi_out_close(); - midi_close(); + midi_in_close(); - cdrom_close(); + cdrom_close(); - zip_close(); + zip_close(); - mo_close(); + mo_close(); - scsi_disk_close(); + scsi_disk_close(); -#ifdef USE_OPENAL - closeal(); -#endif + closeal(); - video_reset_close(); + video_reset_close(); - cpu_close(); + cpu_close(); + + serial_set_next_inst(0); } - /* * This is basically the spot where we start up the actual machine, * by issuing a 'hard reset' to the entire configuration. Order is @@ -960,382 +1115,476 @@ pc_reset_hard_close(void) void pc_reset_hard_init(void) { - /* - * First, we reset the modules that are not part of - * the actual machine, but which support some of the - * modules that are. - */ + /* + * First, we reset the modules that are not part of + * the actual machine, but which support some of the + * modules that are. + */ - /* Reset the general machine support modules. */ - io_init(); + /* Mark ACPI as unavailable */ + acpi_enabled = 0; - /* Turn on and (re)initialize timer processing. */ - timer_init(); + /* Reset the general machine support modules. */ + io_init(); - device_init(); + /* Turn on and (re)initialize timer processing. */ + timer_init(); - sound_reset(); + device_init(); - scsi_reset(); - scsi_device_init(); + sound_reset(); - /* Initialize the actual machine and its basic modules. */ - machine_init(); + scsi_reset(); + scsi_device_init(); - /* Reset and reconfigure the serial ports. */ - serial_standalone_init(); + /* Initialize the actual machine and its basic modules. */ + machine_init(); - /* Reset and reconfigure the Sound Card layer. */ - sound_card_reset(); + /* Reset some basic devices. */ + speaker_init(); + shadowbios = 0; - /* Reset any ISA RTC cards. */ - isartc_reset(); + /* + * Once the machine has been initialized, all that remains + * should be resetting all devices set up for it, to their + * current configurations ! + * + * For now, we will call their reset functions here, but + * that will be a call to device_reset_all() later ! + */ - fdc_card_init(); + if (joystick_type) + gameport_update_joystick_type(); - fdd_reset(); + /* Reset and reconfigure the Sound Card layer. */ + sound_card_reset(); - /* - * Once the machine has been initialized, all that remains - * should be resetting all devices set up for it, to their - * current configurations ! - * - * For now, we will call their reset functions here, but - * that will be a call to device_reset_all() later ! - */ + /* Initialize parallel devices. */ + /* note: PLIP LPT side has to be initialized before the network side */ + lpt_devices_init(); - /* Reset some basic devices. */ - speaker_init(); - lpt_devices_init(); - shadowbios = 0; + /* Reset and reconfigure the Network Card layer. */ + network_reset(); - /* - * Reset the mouse, this will attach it to any port needed. - */ - mouse_reset(); + /* Reset and reconfigure the serial ports. */ + serial_standalone_init(); + serial_passthrough_init(); - /* Reset the Hard Disk Controller module. */ - hdc_reset(); - /* Reset and reconfigure the SCSI layer. */ - scsi_card_init(); + /* + * Reset the mouse, this will attach it to any port needed. + */ + mouse_reset(); - cdrom_hard_reset(); + /* Reset the Hard Disk Controller module. */ + hdc_reset(); - zip_hard_reset(); + fdc_card_init(); - mo_hard_reset(); + fdd_reset(); - scsi_disk_hard_reset(); + /* Reset the CD-ROM Controller module. */ + cdrom_interface_reset(); - /* Reset and reconfigure the Network Card layer. */ - network_reset(); + /* Reset and reconfigure the SCSI layer. */ + scsi_card_init(); - if (joystick_type) - gameport_update_joystick_type(); + scsi_disk_hard_reset(); - ui_sb_update_panes(); + cdrom_hard_reset(); - if (config_changed) { - config_save(); + mo_hard_reset(); - config_changed = 0; - } else - ui_sb_set_ready(1); + zip_hard_reset(); - /* Needs the status bar... */ - if (bugger_enabled) - device_add(&bugger_device); - if (postcard_enabled) - device_add(&postcard_device); + /* Reset any ISA RTC cards. */ + isartc_reset(); - /* Reset the CPU module. */ - resetx86(); - dma_reset(); - pci_pic_reset(); - cpu_cache_int_enabled = cpu_cache_ext_enabled = 0; + /* Initialize the Voodoo cards here inorder to minmize + the chances of the SCSI controller ending up on the bridge. */ + video_voodoo_init(); - atfullspeed = 0; - pc_full_speed(); + ui_sb_update_panes(); - cycles = 0; + if (config_changed) { + config_save(); + + config_changed = 0; + } else + ui_sb_set_ready(1); + + /* Needs the status bar... */ + if (bugger_enabled) + device_add(&bugger_device); + if (postcard_enabled) + device_add(&postcard_device); + + if (IS_ARCH(machine, MACHINE_BUS_PCI)) { + pci_register_cards(); + device_reset_all(DEVICE_PCI); + } + + /* Reset the CPU module. */ + resetx86(); + dma_reset(); + pci_pic_reset(); + cpu_cache_int_enabled = cpu_cache_ext_enabled = 0; + + atfullspeed = 0; + pc_full_speed(); + + cycles = 0; #ifdef FPU_CYCLES - fpu_cycles = 0; + fpu_cycles = 0; #endif #ifdef USE_DYNAREC - cycles_main = 0; + cycles_main = 0; #endif - update_mouse_msg(); + update_mouse_msg(); + + ui_hard_reset_completed(); } -void update_mouse_msg() +void +update_mouse_msg(void) { - wchar_t wcpufamily[2048], wcpu[2048], wmachine[2048], *wcp; - - mbstowcs(wmachine, machine_getname(), strlen(machine_getname())+1); + wchar_t wcpufamily[2048]; + wchar_t wcpu[2048]; + wchar_t wmachine[2048]; + wchar_t *wcp; - if (!cpu_override) - mbstowcs(wcpufamily, cpu_f->name, strlen(cpu_f->name)+1); - else - swprintf(wcpufamily, sizeof_w(wcpufamily), L"[U] %hs", cpu_f->name); + mbstowcs(wmachine, machine_getname(), strlen(machine_getname()) + 1); - wcp = wcschr(wcpufamily, L'('); - if (wcp) /* remove parentheses */ - *(wcp - 1) = L'\0'; - mbstowcs(wcpu, cpu_s->name, strlen(cpu_s->name)+1); + if (!cpu_override) + mbstowcs(wcpufamily, cpu_f->name, strlen(cpu_f->name) + 1); + else + swprintf(wcpufamily, sizeof_w(wcpufamily), L"[U] %hs", cpu_f->name); + + wcp = wcschr(wcpufamily, L'('); + if (wcp) /* remove parentheses */ + *(wcp - 1) = L'\0'; + mbstowcs(wcpu, cpu_s->name, strlen(cpu_s->name) + 1); #ifdef _WIN32 - swprintf(mouse_msg[0], sizeof_w(mouse_msg[0]), L"%%i%%%% - %ls", - plat_get_string(IDS_2077)); - swprintf(mouse_msg[1], sizeof_w(mouse_msg[1]), L"%%i%%%% - %ls", - (mouse_get_buttons() > 2) ? plat_get_string(IDS_2078) : plat_get_string(IDS_2079)); - wcsncpy(mouse_msg[2], L"%i%%", sizeof_w(mouse_msg[2])); + swprintf(mouse_msg[0], sizeof_w(mouse_msg[0]), L"%%i%%%% - %ls", + plat_get_string(IDS_2077)); + swprintf(mouse_msg[1], sizeof_w(mouse_msg[1]), L"%%i%%%% - %ls", + (mouse_get_buttons() > 2) ? plat_get_string(IDS_2078) : plat_get_string(IDS_2079)); + wcsncpy(mouse_msg[2], L"%i%%", sizeof_w(mouse_msg[2])); #else - swprintf(mouse_msg[0], sizeof_w(mouse_msg[0]), L"%ls v%ls - %%i%%%% - %ls - %ls/%ls - %ls", - EMU_NAME_W, EMU_VERSION_FULL_W, wmachine, wcpufamily, wcpu, - plat_get_string(IDS_2077)); - swprintf(mouse_msg[1], sizeof_w(mouse_msg[1]), L"%ls v%ls - %%i%%%% - %ls - %ls/%ls - %ls", - EMU_NAME_W, EMU_VERSION_FULL_W, wmachine, wcpufamily, wcpu, - (mouse_get_buttons() > 2) ? plat_get_string(IDS_2078) : plat_get_string(IDS_2079)); - swprintf(mouse_msg[2], sizeof_w(mouse_msg[2]), L"%ls v%ls - %%i%%%% - %ls - %ls/%ls", - EMU_NAME_W, EMU_VERSION_FULL_W, wmachine, wcpufamily, wcpu); + swprintf(mouse_msg[0], sizeof_w(mouse_msg[0]), L"%ls v%ls - %%i%%%% - %ls - %ls/%ls - %ls", + EMU_NAME_W, EMU_VERSION_FULL_W, wmachine, wcpufamily, wcpu, + plat_get_string(IDS_2077)); + swprintf(mouse_msg[1], sizeof_w(mouse_msg[1]), L"%ls v%ls - %%i%%%% - %ls - %ls/%ls - %ls", + EMU_NAME_W, EMU_VERSION_FULL_W, wmachine, wcpufamily, wcpu, + (mouse_get_buttons() > 2) ? plat_get_string(IDS_2078) : plat_get_string(IDS_2079)); + swprintf(mouse_msg[2], sizeof_w(mouse_msg[2]), L"%ls v%ls - %%i%%%% - %ls - %ls/%ls", + EMU_NAME_W, EMU_VERSION_FULL_W, wmachine, wcpufamily, wcpu); #endif } void pc_reset_hard(void) { - hard_reset_pending = 1; + hard_reset_pending = 1; } - void -pc_close(thread_t *ptr) +pc_close(UNUSED(thread_t *ptr)) { - int i; + /* Wait a while so things can shut down. */ + plat_delay_ms(200); - /* Wait a while so things can shut down. */ - plat_delay_ms(200); + /* Claim the video blitter. */ + startblit(); - /* Claim the video blitter. */ - startblit(); + /* Terminate the UI thread. */ + is_quit = 1; - /* Terminate the UI thread. */ - is_quit = 1; + nvr_save(); -#if (defined(USE_DYNAREC) && defined(USE_NEW_DYNAREC)) - codegen_close(); -#endif + config_save(); - nvr_save(); + plat_mouse_capture(0); - config_save(); + /* Close all the memory mappings. */ + mem_close(); - plat_mouse_capture(0); + /* Turn off timer processing to avoid potential segmentation faults. */ + timer_close(); - /* Close all the memory mappings. */ - mem_close(); + lpt_devices_close(); - network_timer_stop(); - - /* Turn off timer processing to avoid potential segmentation faults. */ - timer_close(); - - lpt_devices_close(); - - for (i=0; irspeed / 100); - mouse_process(); - joystick_process(); - endblit(); - - /* Done with this frame, update statistics. */ - framecount++; - if (++framecountx >= 100) { - framecountx = 0; - frames = 0; - } - - if (title_update) { - mouse_msg_idx = (mouse_type == MOUSE_TYPE_NONE) ? 2 : !!mouse_capture; - swprintf(temp, sizeof_w(temp), mouse_msg[mouse_msg_idx], fps); -#ifdef __APPLE__ - /* Needed due to modifying the UI on the non-main thread is a big no-no. */ - dispatch_async_f(dispatch_get_main_queue(), wcsdup((const wchar_t *) temp), _ui_window_title); -#else - ui_window_title(temp); + /* Run a block of code. */ + startblit(); + cpu_exec((int32_t) cpu_s->rspeed / 100); + ack_pause(); +#ifdef USE_GDBSTUB /* avoid a KBC FIFO overflow when CPU emulation is stalled */ + if (gdbstub_step == GDBSTUB_EXEC) { #endif - title_update = 0; - } -} + if (!mouse_timed) + mouse_process(); +#ifdef USE_GDBSTUB /* avoid a KBC FIFO overflow when CPU emulation is stalled */ + } +#endif + joystick_process(); + endblit(); + /* Done with this frame, update statistics. */ + framecount++; + if (++framecountx >= 100) { + framecountx = 0; + frames = 0; + } + + if (title_update) { + mouse_msg_idx = ((mouse_type == MOUSE_TYPE_NONE) || (mouse_input_mode >= 1)) ? 2 : !!mouse_capture; + swprintf(temp, sizeof_w(temp), mouse_msg[mouse_msg_idx], fps); +#ifdef __APPLE__ + /* Needed due to modifying the UI on the non-main thread is a big no-no. */ + dispatch_async_f(dispatch_get_main_queue(), wcsdup((const wchar_t *) temp), _ui_window_title); +#else + ui_window_title(temp); +#endif + title_update = 0; + } +} /* Handler for the 1-second timer to refresh the window title. */ void pc_onesec(void) { - fps = framecount; - framecount = 0; + fps = framecount; + framecount = 0; - title_update = 1; + title_update = 1; } - void -set_screen_size(int x, int y) +set_screen_size_monitor(int x, int y, int monitor_index) { - int owsx = scrnsz_x; - int owsy = scrnsz_y; - int temp_overscan_x = overscan_x; - int temp_overscan_y = overscan_y; - double dx, dy, dtx, dty; + int temp_overscan_x = monitors[monitor_index].mon_overscan_x; + int temp_overscan_y = monitors[monitor_index].mon_overscan_y; + double dx; + double dy; + double dtx; + double dty; /* Make sure we keep usable values. */ #if 0 pc_log("SetScreenSize(%d, %d) resize=%d\n", x, y, vid_resize); #endif - if (x < 320) x = 320; - if (y < 200) y = 200; - if (x > 2048) x = 2048; - if (y > 2048) y = 2048; + if (x < 320) + x = 320; + if (y < 200) + y = 200; + if (x > 2048) + x = 2048; + if (y > 2048) + y = 2048; /* Save the new values as "real" (unscaled) resolution. */ - unscaled_size_x = x; - efscrnsz_y = y; + monitors[monitor_index].mon_unscaled_size_x = x; + monitors[monitor_index].mon_efscrnsz_y = y; if (suppress_overscan) - temp_overscan_x = temp_overscan_y = 0; + temp_overscan_x = temp_overscan_y = 0; if (force_43) { - dx = (double)x; - dtx = (double)temp_overscan_x; + dx = (double) x; + dtx = (double) temp_overscan_x; - dy = (double)y; - dty = (double)temp_overscan_y; + dy = (double) y; + dty = (double) temp_overscan_y; - /* Account for possible overscan. */ - if (!(video_is_ega_vga()) && (temp_overscan_y == 16)) { - /* CGA */ - dy = (((dx - dtx) / 4.0) * 3.0) + dty; - } else if (!(video_is_ega_vga()) && (temp_overscan_y < 16)) { - /* MDA/Hercules */ - dy = (x / 4.0) * 3.0; - } else { - if (enable_overscan) { - /* EGA/(S)VGA with overscan */ - dy = (((dx - dtx) / 4.0) * 3.0) + dty; - } else { - /* EGA/(S)VGA without overscan */ - dy = (x / 4.0) * 3.0; - } - } - unscaled_size_y = (int)dy; + /* Account for possible overscan. */ + if (video_get_type_monitor(monitor_index) != VIDEO_FLAG_TYPE_SPECIAL && (temp_overscan_y == 16)) { + /* CGA */ + dy = (((dx - dtx) / 4.0) * 3.0) + dty; + } else if (video_get_type_monitor(monitor_index) != VIDEO_FLAG_TYPE_SPECIAL && (temp_overscan_y < 16)) { + /* MDA/Hercules */ + dy = (x / 4.0) * 3.0; + } else { + if (enable_overscan) { + /* EGA/(S)VGA with overscan */ + dy = (((dx - dtx) / 4.0) * 3.0) + dty; + } else { + /* EGA/(S)VGA without overscan */ + dy = (x / 4.0) * 3.0; + } + } + monitors[monitor_index].mon_unscaled_size_y = (int) dy; } else - unscaled_size_y = efscrnsz_y; + monitors[monitor_index].mon_unscaled_size_y = monitors[monitor_index].mon_efscrnsz_y; - switch(scale) { - case 0: /* 50% */ - scrnsz_x = (unscaled_size_x>>1); - scrnsz_y = (unscaled_size_y>>1); - break; + switch (scale) { + case 0: /* 50% */ + monitors[monitor_index].mon_scrnsz_x = (monitors[monitor_index].mon_unscaled_size_x >> 1); + monitors[monitor_index].mon_scrnsz_y = (monitors[monitor_index].mon_unscaled_size_y >> 1); + break; - case 1: /* 100% */ - scrnsz_x = unscaled_size_x; - scrnsz_y = unscaled_size_y; - break; + case 1: /* 100% */ + monitors[monitor_index].mon_scrnsz_x = monitors[monitor_index].mon_unscaled_size_x; + monitors[monitor_index].mon_scrnsz_y = monitors[monitor_index].mon_unscaled_size_y; + break; - case 2: /* 150% */ - scrnsz_x = ((unscaled_size_x*3)>>1); - scrnsz_y = ((unscaled_size_y*3)>>1); - break; + case 2: /* 150% */ + monitors[monitor_index].mon_scrnsz_x = ((monitors[monitor_index].mon_unscaled_size_x * 3) >> 1); + monitors[monitor_index].mon_scrnsz_y = ((monitors[monitor_index].mon_unscaled_size_y * 3) >> 1); + break; - case 3: /* 200% */ - scrnsz_x = (unscaled_size_x<<1); - scrnsz_y = (unscaled_size_y<<1); - break; + case 3: /* 200% */ + monitors[monitor_index].mon_scrnsz_x = (monitors[monitor_index].mon_unscaled_size_x << 1); + monitors[monitor_index].mon_scrnsz_y = (monitors[monitor_index].mon_unscaled_size_y << 1); + break; + + case 4: /* 300% */ + monitors[monitor_index].mon_scrnsz_x = (monitors[monitor_index].mon_unscaled_size_x * 3); + monitors[monitor_index].mon_scrnsz_y = (monitors[monitor_index].mon_unscaled_size_y * 3); + break; + + case 5: /* 400% */ + monitors[monitor_index].mon_scrnsz_x = (monitors[monitor_index].mon_unscaled_size_x << 2); + monitors[monitor_index].mon_scrnsz_y = (monitors[monitor_index].mon_unscaled_size_y << 2); + break; + + case 6: /* 500% */ + monitors[monitor_index].mon_scrnsz_x = (monitors[monitor_index].mon_unscaled_size_x * 5); + monitors[monitor_index].mon_scrnsz_y = (monitors[monitor_index].mon_unscaled_size_y * 5); + break; + + case 7: /* 600% */ + monitors[monitor_index].mon_scrnsz_x = (monitors[monitor_index].mon_unscaled_size_x * 6); + monitors[monitor_index].mon_scrnsz_y = (monitors[monitor_index].mon_unscaled_size_y * 6); + break; + + case 8: /* 700% */ + monitors[monitor_index].mon_scrnsz_x = (monitors[monitor_index].mon_unscaled_size_x * 7); + monitors[monitor_index].mon_scrnsz_y = (monitors[monitor_index].mon_unscaled_size_y * 7); + break; + + case 9: /* 800% */ + monitors[monitor_index].mon_scrnsz_x = (monitors[monitor_index].mon_unscaled_size_x << 3); + monitors[monitor_index].mon_scrnsz_y = (monitors[monitor_index].mon_unscaled_size_y << 3); + break; + + default: + break; } - /* If the resolution has changed, let the main thread handle it. */ - if ((owsx != scrnsz_x) || (owsy != scrnsz_y)) - atomic_flag_clear(&doresize); + plat_resize_request(monitors[monitor_index].mon_scrnsz_x, monitors[monitor_index].mon_scrnsz_y, monitor_index); } +void +set_screen_size(int x, int y) +{ + set_screen_size_monitor(x, y, monitor_index_global); +} + +void +reset_screen_size_monitor(int monitor_index) +{ + set_screen_size(monitors[monitor_index].mon_unscaled_size_x, monitors[monitor_index].mon_efscrnsz_y); +} void reset_screen_size(void) { - set_screen_size(unscaled_size_x, efscrnsz_y); + for (uint8_t i = 0; i < MONITORS_NUM; i++) + set_screen_size(monitors[i].mon_unscaled_size_x, monitors[i].mon_efscrnsz_y); } - void set_screen_size_natural(void) { - set_screen_size(unscaled_size_x, unscaled_size_y); + for (uint8_t i = 0; i < MONITORS_NUM; i++) + set_screen_size(monitors[i].mon_unscaled_size_x, monitors[i].mon_unscaled_size_y); } - int get_actual_size_x(void) { - return(unscaled_size_x); + return (unscaled_size_x); } - int get_actual_size_y(void) { - return(efscrnsz_y); + return (efscrnsz_y); +} + +void +do_pause(int p) +{ + if (p) + do_pause_ack = p; + dopause = p; + if (p) { + while (!pause_ack) + ; + } + pause_ack = 0; } diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 704024067..bfa582e33 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -1,28 +1,41 @@ # -# 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. +# 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. +# This file is part of the 86Box distribution. # -# CMake build script. +# CMake build script. # -# Authors: David HrdliÄka, -# dob205 +# Authors: David HrdliÄka, +# dob205 # -# Copyright 2020-2022 David HrdliÄka. -# Copyright 2021 dob205. +# Copyright 2020-2022 David HrdliÄka. +# Copyright 2021 dob205. # +if(APPLE) + set(CMAKE_INSTALL_RPATH_USE_LINK_PATH TRUE) +endif() add_executable(86Box 86box.c config.c log.c random.c timer.c io.c acpi.c apm.c - dma.c ddma.c discord.c nmi.c pic.c pit.c port_6x.c port_92.c ppi.c pci.c - mca.c usb.c fifo8.c device.c nvr.c nvr_at.c nvr_ps2.c) + dma.c ddma.c nmi.c pic.c pit.c pit_fast.c port_6x.c port_92.c ppi.c pci.c + mca.c usb.c fifo.c fifo8.c device.c nvr.c nvr_at.c nvr_ps2.c + machine_status.c ini.c) + +if(CMAKE_SYSTEM_NAME MATCHES "Linux") + add_compile_definitions(_FILE_OFFSET_BITS=64 _LARGEFILE_SOURCE=1 _LARGEFILE64_SOURCE=1) +endif() if(CPPTHREADS) target_sources(86Box PRIVATE thread.cpp) endif() +if(GDBSTUB) + add_compile_definitions(USE_GDBSTUB) + target_sources(86Box PRIVATE gdbstub.c) +endif() + if(NEW_DYNAREC) add_compile_definitions(USE_NEW_DYNAREC) endif() @@ -39,15 +52,27 @@ if(DEV_BRANCH) add_compile_definitions(DEV_BRANCH) endif() +if(DISCORD) + add_compile_definitions(DISCORD) + target_sources(86Box PRIVATE discord.c) +endif() + if(VNC) - add_compile_definitions(USE_VNC) - add_library(vnc OBJECT vnc.c vnc_keymap.c) - target_link_libraries(86Box vnc vncserver) - if (WIN32) - target_link_libraries(86Box ws2_32) + find_package(LibVNCServer) + if(LibVNCServer_FOUND) + add_compile_definitions(USE_VNC) + add_library(vnc OBJECT vnc.c vnc_keymap.c) + target_link_libraries(86Box vnc LibVNCServer::vncserver) + if(WIN32) + target_link_libraries(86Box ws2_32) + endif() endif() endif() +if(INSTRUMENT) + add_compile_definitions(USE_INSTRUMENT) +endif() + target_link_libraries(86Box cpu chipset mch dev mem fdd game cdrom zip mo hdd net print scsi sio snd vid voodoo plat ui) @@ -70,39 +95,30 @@ if(APPLE) # Force using the newest library if it's installed by homebrew set(CMAKE_FIND_FRAMEWORK LAST) - # setting our compilation target to macOS 10.15 Catalina if targetting Qt6, macOS 10.13 High Sierra otherwise + # setting our compilation target to macOS 10.15 Catalina if targeting Qt6, + # macOS 10.14 Mojave for vulkan support, 10.13 High Sierra otherwise if (USE_QT6) set(CMAKE_OSX_DEPLOYMENT_TARGET "10.15") else() - set(CMAKE_OSX_DEPLOYMENT_TARGET "10.13") + if(MOLTENVK) + set(CMAKE_OSX_DEPLOYMENT_TARGET "10.14") + else() + set(CMAKE_OSX_DEPLOYMENT_TARGET "10.13") + endif() endif() endif() find_package(Freetype REQUIRED) include_directories(${FREETYPE_INCLUDE_DIRS}) +if(FREETYPE_INCLUDE_DIR_ft2build) + include_directories(${FREETYPE_INCLUDE_DIR_ft2build}) +endif() if(APPLE) # Freetype is dynamically loaded by the emulator, however, we link it # on macOS so it gets copied to the bundle by the installation process target_link_libraries(86Box Freetype::Freetype) endif() -if(OPENAL) - if(VCPKG_TOOLCHAIN) - find_package(OpenAL CONFIG REQUIRED) - elseif(MINGW) - find_package(OpenAL MODULE REQUIRED) - else() - find_package(OpenAL REQUIRED) - endif() - - if(TARGET OpenAL::OpenAL) - target_link_libraries(86Box OpenAL::OpenAL) - else() - include_directories(${OPENAL_INCLUDE_DIR}) - target_link_libraries(86Box ${OPENAL_LIBRARY}) - endif() -endif() - find_package(SDL2 REQUIRED) include_directories(${SDL2_INCLUDE_DIRS}) if(STATIC_BUILD AND TARGET SDL2::SDL2-static) @@ -117,20 +133,6 @@ find_package(PNG REQUIRED) include_directories(${PNG_INCLUDE_DIRS}) target_link_libraries(86Box PNG::PNG) -if(VCPKG_TOOLCHAIN) - # vcpkg includes a config file for rtmidi - find_package(RtMidi REQUIRED) - target_link_libraries(86Box RtMidi::rtmidi) -else() - find_package(PkgConfig REQUIRED) - pkg_check_modules(RTMIDI REQUIRED IMPORTED_TARGET rtmidi) - target_link_libraries(86Box PkgConfig::RTMIDI) - - if(WIN32) - target_link_libraries(PkgConfig::RTMIDI INTERFACE winmm) - endif() -endif() - configure_file(include/86box/version.h.in include/86box/version.h @ONLY) include_directories(${CMAKE_CURRENT_BINARY_DIR}/include) @@ -205,6 +207,7 @@ elseif(WIN32) OPTIONAL) endif() + add_subdirectory(device) add_subdirectory(disk) add_subdirectory(floppy) @@ -218,7 +221,7 @@ add_subdirectory(scsi) add_subdirectory(sound) add_subdirectory(video) if (APPLE) - add_subdirectory(mac) + add_subdirectory(mac) endif() if (QT) diff --git a/src/Makefile.local b/src/Makefile.local index c927037d8..fdb2dcab3 100644 --- a/src/Makefile.local +++ b/src/Makefile.local @@ -1,32 +1,32 @@ # -# 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. +# 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. +# This file is part of the 86Box distribution. # -# Prefix for localizing the general Makefile.mingw for local -# settings, so we can avoid changing the main one for all of -# our local setups. +# Prefix for localizing the general Makefile.mingw for local +# settings, so we can avoid changing the main one for all of +# our local setups. # -# Author: Fred N. van Kempen, +# Authors: Fred N. van Kempen, # ######################################################################### -# Anything here will override defaults in Makefile.MinGW. # +# Anything here will override defaults in Makefile.MinGW. # ######################################################################### # Name of the executable. -#PROG := yourexe +#PROG := 86box.exe # Various compile-time options. # -DROM_TRACE=0xc800 traces ROM access from segment C800 # -DIO_TRACE=0x66 traces I/O on port 0x66 # -DIO_CATCH enables I/O range catch logs -STUFF := +STUFF := # Add feature selections here. # -DANSI_CFG forces the config file to ANSI encoding. @@ -168,32 +168,31 @@ STUFF := # -DENABLE_JOYSTICK_LOG=N sets logging level at N. # -DENABLE_SDL_LOG=N sets logging level at N. # -DENABLE_SETTINGS_LOG=N sets logging level at N. -EXTRAS := +EXTRAS := -AUTODEP := n -CRASHDUMP := n -DEBUG := n -OPTIM := n -X64 := n -RELEASE := n -USB := n -VNC := n -RDP := n -DEV_BUILD := n -DEV_BRANCH := n -CIRRUS := n -NE1000 := n -NV_RIVA := n -OPENAL := y -FLUIDSYNTH := y -MUNT := y -PAS16 := n -DYNAREC := y +AUTODEP := n +DEBUG := n +OPTIM := n +X64 := n +RELEASE := n +USB := n +VNC := n +RDP := n +DEV_BUILD := n +DEV_BRANCH := n +CIRRUS := n +NE1000 := n +NV_RIVA := n +OPENAL := y +FLUIDSYNTH := y +MUNT := y +PAS16 := n +DYNAREC := y ######################################################################### -# Include the master Makefile.MinGW for the rest. # +# Include the master Makefile.MinGW for the rest. # ######################################################################### include win/Makefile.mingw diff --git a/src/acpi.c b/src/acpi.c index af02aa692..d60699f1b 100644 --- a/src/acpi.c +++ b/src/acpi.c @@ -1,18 +1,18 @@ /* - * 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. + * 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. + * This file is part of the 86Box distribution. * - * ACPI emulation. + * ACPI emulation. * * * - * Authors: Miran Grca, + * Authors: Miran Grca, * - * Copyright 2020 Miran Grca. + * Copyright 2020 Miran Grca. */ #include #include @@ -20,6 +20,7 @@ #include #include #include +#include #define HAVE_STDARG_H #include <86box/86box.h> #include "cpu.h" @@ -37,55 +38,110 @@ #include <86box/acpi.h> #include <86box/machine.h> #include <86box/i2c.h> +#include <86box/video.h> +int acpi_rtc_status = 0; +atomic_int acpi_pwrbut_pressed = 0; +int acpi_enabled = 0; -int acpi_rtc_status = 0; +static double cpu_to_acpi; +static int acpi_power_on = 0; #ifdef ENABLE_ACPI_LOG int acpi_do_log = ENABLE_ACPI_LOG; - static void acpi_log(const char *fmt, ...) { va_list ap; if (acpi_do_log) { - va_start(ap, fmt); - pclog_ex(fmt, ap); - va_end(ap); + va_start(ap, fmt); + pclog_ex(fmt, ap); + va_end(ap); } } #else -#define acpi_log(fmt, ...) +# define acpi_log(fmt, ...) #endif +static uint64_t +acpi_clock_get(void) +{ + return tsc * cpu_to_acpi; +} + +static uint32_t +acpi_timer_get(acpi_t *dev) +{ + uint64_t clock = acpi_clock_get(); + if (dev->regs.timer32) + return clock & 0xffffffff; + else + return clock & 0xffffff; +} + +static double +acpi_get_overflow_period(acpi_t *dev) +{ + uint64_t timer = acpi_clock_get(); + uint64_t overflow_time; + + if (dev->regs.timer32) { + overflow_time = (timer + 0x80000000LL) & ~0x7fffffffLL; + } else { + overflow_time = (timer + 0x800000LL) & ~0x7fffffLL; + } + + uint64_t time_to_overflow = overflow_time - timer; + + return ((double) time_to_overflow / (double) ACPI_TIMER_FREQ) * 1000000.0; +} + +static void +acpi_timer_overflow(void *priv) +{ + acpi_t *dev = (acpi_t *) priv; + dev->regs.pmsts |= TMROF_STS; + acpi_update_irq(dev); +} + +static void +acpi_timer_update(acpi_t *dev, bool enable) +{ + if (enable) { + timer_on_auto(&dev->timer, acpi_get_overflow_period(dev)); + } else { + timer_stop(&dev->timer); + } +} void acpi_update_irq(acpi_t *dev) { int sci_level = (dev->regs.pmsts & dev->regs.pmen) & (RTC_EN | PWRBTN_EN | GBL_EN | TMROF_EN); if (dev->vendor == VEN_SMC) - sci_level |= (dev->regs.pmsts & BM_STS); + sci_level |= (dev->regs.pmsts & BM_STS); - if (sci_level) { - if (dev->irq_mode == 1) - pci_set_irq(dev->slot, dev->irq_pin); - else if (dev->irq_mode == 2) - pci_set_mirq(5, dev->mirq_is_level); - else - pci_set_mirq(0xf0 | dev->irq_line, 1); + if ((dev->regs.pmcntrl & 0x01) && sci_level) { + if (dev->irq_mode == 1) + pci_set_irq(dev->slot, dev->irq_pin, &dev->irq_state); + else if (dev->irq_mode == 2) + pci_set_mirq(5, dev->mirq_is_level, &dev->irq_state); + else + picintlevel(1 << dev->irq_line, &dev->irq_state); } else { - if (dev->irq_mode == 1) - pci_clear_irq(dev->slot, dev->irq_pin); - else if (dev->irq_mode == 2) - pci_clear_mirq(5, dev->mirq_is_level); - else - pci_clear_mirq(0xf0 | dev->irq_line, 1); + if (dev->irq_mode == 1) + pci_clear_irq(dev->slot, dev->irq_pin, &dev->irq_state); + else if (dev->irq_mode == 2) + pci_clear_mirq(5, dev->mirq_is_level, &dev->irq_state); + else + picintclevel(1 << dev->irq_line, &dev->irq_state); } -} + acpi_timer_update(dev, (dev->regs.pmen & TMROF_EN) && !(dev->regs.pmsts & TMROF_STS)); +} void acpi_raise_smi(void *priv, int do_smi) @@ -93,841 +149,769 @@ acpi_raise_smi(void *priv, int do_smi) acpi_t *dev = (acpi_t *) priv; if (dev->regs.glbctl & 0x01) { - if ((dev->vendor == VEN_VIA) || (dev->vendor == VEN_VIA_596B)) { - if ((!dev->regs.smi_lock || !dev->regs.smi_active)) { - if (do_smi) - smi_line = 1; - dev->regs.smi_active = 1; - } - } else if ((dev->vendor == VEN_INTEL) || (dev->vendor == VEN_ALI)) { - if (do_smi) - smi_line = 1; - /* Clear bit 16 of GLBCTL. */ - if (dev->vendor == VEN_INTEL) - dev->regs.glbctl &= ~0x00010000; - else - dev->regs.ali_soft_smi = 1; - } else if (dev->vendor == VEN_SMC) { - if (do_smi) - smi_line = 1; - } + if ((dev->vendor == VEN_VIA) || (dev->vendor == VEN_VIA_596B)) { + if (!dev->regs.smi_lock || !dev->regs.smi_active) { + if (do_smi) + smi_raise(); + dev->regs.smi_active = 1; + } + } else if ((dev->vendor == VEN_INTEL) || (dev->vendor == VEN_ALI)) { + if (do_smi) + smi_raise(); + /* Clear bit 16 of GLBCTL. */ + if (dev->vendor == VEN_INTEL) + dev->regs.glbctl &= ~0x00010000; + else + dev->regs.ali_soft_smi = 1; + } else if (dev->vendor == VEN_SMC) { + if (do_smi) + smi_raise(); + } } } - static uint32_t -acpi_reg_read_common_regs(int size, uint16_t addr, void *p) +acpi_reg_read_common_regs(UNUSED(int size), uint16_t addr, void *priv) { - acpi_t *dev = (acpi_t *) p; + acpi_t *dev = (acpi_t *) priv; uint32_t ret = 0x00000000; - int shift16, shift32; + int shift16; + int shift32; addr &= 0x3f; shift16 = (addr & 1) << 3; shift32 = (addr & 3) << 3; switch (addr) { - case 0x00: case 0x01: - /* PMSTS - Power Management Status Register (IO) */ - ret = (dev->regs.pmsts >> shift16) & 0xff; - if (addr == 0x01) - ret |= (acpi_rtc_status << 2); - break; - case 0x02: case 0x03: - /* PMEN - Power Management Resume Enable Register (IO) */ - ret = (dev->regs.pmen >> shift16) & 0xff; - break; - case 0x04: case 0x05: - /* PMCNTRL - Power Management Control Register (IO) */ - ret = (dev->regs.pmcntrl >> shift16) & 0xff; - if (addr == 0x05) - ret = (ret & 0xdf); /* Bit 5 is write-only. */ - break; - case 0x08: case 0x09: case 0x0a: case 0x0b: - /* PMTMR - Power Management Timer Register (IO) */ - ret = (dev->regs.timer_val >> shift32) & 0xff; + case 0x00: + case 0x01: + /* PMSTS - Power Management Status Register (IO) */ + ret = (dev->regs.pmsts >> shift16) & 0xff; + if (addr == 0x01) + ret |= (acpi_rtc_status << 2); + break; + case 0x02: + case 0x03: + /* PMEN - Power Management Resume Enable Register (IO) */ + ret = (dev->regs.pmen >> shift16) & 0xff; + break; + case 0x04: + case 0x05: + /* PMCNTRL - Power Management Control Register (IO) */ + ret = (dev->regs.pmcntrl >> shift16) & 0xff; + if (addr == 0x05) + ret = (ret & 0xdf); /* Bit 5 is write-only. */ + break; + case 0x08: + case 0x09: + case 0x0a: + case 0x0b: + /* PMTMR - Power Management Timer Register (IO) */ + ret = (acpi_timer_get(dev) >> shift32) & 0xff; #ifdef USE_DYNAREC - if (cpu_use_dynarec) - update_tsc(); + if (cpu_use_dynarec) + update_tsc(); #endif - break; + break; + + default: + break; } #ifdef ENABLE_ACPI_LOG if (size != 1) - acpi_log("(%i) ACPI Read (%i) %02X: %02X\n", in_smm, size, addr, ret); + acpi_log("(%i) ACPI Read (%i) %02X: %02X\n", in_smm, size, addr, ret); #endif return ret; } - static uint32_t -acpi_reg_read_ali(int size, uint16_t addr, void *p) +acpi_reg_read_ali(int size, uint16_t addr, void *priv) { - acpi_t *dev = (acpi_t *) p; - uint32_t ret = 0x00000000; - int shift16, shift32; - - addr &= 0x3f; - shift16 = (addr & 1) << 3; - shift32 = (addr & 3) << 3; - - switch(addr) { - case 0x10: case 0x11: case 0x12: case 0x13: - /* PCNTRL - Processor Control Register (IO) */ - ret = (dev->regs.pcntrl >> shift16) & 0xff; - break; - case 0x14: - /* LVL2 - Processor Level 2 Register */ - ret = dev->regs.plvl2; - break; - case 0x15: - /* LVL3 - Processor Level 3 Register */ - ret = dev->regs.plvl3; - break; - case 0x18: case 0x19: - /* GPE0_STS - General Purpose Event0 Status Register */ - ret = (dev->regs.gpsts >> shift16) & 0xff; - break; - case 0x1a: case 0x1b: - /* GPE0_EN - General Purpose Event0 Enable Register */ - ret = (dev->regs.gpen >> shift16) & 0xff; - break; - case 0x1d: case 0x1c: - /* GPE1_STS - General Purpose Event1 Status Register */ - ret = (dev->regs.gpsts1 >> shift16) & 0xff; - break; - case 0x1f: case 0x1e: - /* GPE1_EN - General Purpose Event1 Enable Register */ - ret = (dev->regs.gpen1 >> shift16) & 0xff; - break; - case 0x20 ... 0x27: - /* GPE1_CTL - General Purpose Event1 Control Register */ - ret = (dev->regs.gpcntrl >> shift32) & 0xff; - break; - case 0x30: - /* PM2_CNTRL - Power Management 2 Control Register( */ - ret = dev->regs.pmcntrl; - break; - default: - ret = acpi_reg_read_common_regs(size, addr, p); - break; - } - -#ifdef ENABLE_ACPI_LOG - if (size != 1) - acpi_log("(%i) ACPI Read (%i) %02X: %02X\n", in_smm, size, addr, ret); -#endif - return ret; -} - - -static uint32_t -acpi_reg_read_intel(int size, uint16_t addr, void *p) -{ - acpi_t *dev = (acpi_t *) p; - uint32_t ret = 0x00000000; - int shift16, shift32; + const acpi_t *dev = (acpi_t *) priv; + uint32_t ret = 0x00000000; + int shift16; + int shift32; addr &= 0x3f; shift16 = (addr & 1) << 3; shift32 = (addr & 3) << 3; switch (addr) { - case 0x0c: case 0x0d: - /* GPSTS - General Purpose Status Register (IO) */ - ret = (dev->regs.gpsts >> shift16) & 0xff; - break; - case 0x0e: case 0x0f: - /* GPEN - General Purpose Enable Register (IO) */ - ret = (dev->regs.gpen >> shift16) & 0xff; - break; - case 0x10: case 0x11: case 0x12: case 0x13: - /* PCNTRL - Processor Control Register (IO) */ - ret = (dev->regs.pcntrl >> shift32) & 0xff; - break; - case 0x18: case 0x19: - /* GLBSTS - Global Status Register (IO) */ - ret = (dev->regs.glbsts >> shift16) & 0xff; - if (addr == 0x18) { - ret &= 0x27; - if (dev->regs.gpsts != 0x0000) - ret |= 0x80; - if (dev->regs.pmsts != 0x0000) - ret |= 0x40; - if (dev->regs.devsts != 0x00000000) - ret |= 0x10; - } - break; - case 0x1c: case 0x1d: case 0x1e: case 0x1f: - /* DEVSTS - Device Status Register (IO) */ - ret = (dev->regs.devsts >> shift32) & 0xff; - break; - case 0x20: case 0x21: - /* GLBEN - Global Enable Register (IO) */ - ret = (dev->regs.glben >> shift16) & 0xff; - break; - case 0x28: case 0x29: case 0x2a: case 0x2b: - /* GLBCTL - Global Control Register (IO) */ - ret = (dev->regs.glbctl >> shift32) & 0xff; - break; - case 0x2c: case 0x2d: case 0x2e: case 0x2f: - /* DEVCTL - Device Control Register (IO) */ - ret = (dev->regs.devctl >> shift32) & 0xff; - break; - case 0x30: case 0x31: case 0x32: - /* GPIREG - General Purpose Input Register (IO) */ - if (size == 1) - ret = dev->regs.gpireg[addr & 3]; - break; - case 0x34: case 0x35: case 0x36: case 0x37: - /* GPOREG - General Purpose Output Register (IO) */ - if (size == 1) - ret = dev->regs.gporeg[addr & 3]; - break; - default: - ret = acpi_reg_read_common_regs(size, addr, p); - break; + case 0x10: + case 0x11: + case 0x12: + case 0x13: + /* PCNTRL - Processor Control Register (IO) */ + ret = (dev->regs.pcntrl >> shift16) & 0xff; + break; + case 0x14: + /* LVL2 - Processor Level 2 Register */ + ret = dev->regs.plvl2; + break; + case 0x15: + /* LVL3 - Processor Level 3 Register */ + ret = dev->regs.plvl3; + break; + case 0x18: + case 0x19: + /* GPE0_STS - General Purpose Event0 Status Register */ + ret = (dev->regs.gpsts >> shift16) & 0xff; + break; + case 0x1a: + case 0x1b: + /* GPE0_EN - General Purpose Event0 Enable Register */ + ret = (dev->regs.gpen >> shift16) & 0xff; + break; + case 0x1d: + case 0x1c: + /* GPE1_STS - General Purpose Event1 Status Register */ + ret = (dev->regs.gpsts1 >> shift16) & 0xff; + break; + case 0x1f: + case 0x1e: + /* GPE1_EN - General Purpose Event1 Enable Register */ + ret = (dev->regs.gpen1 >> shift16) & 0xff; + break; + case 0x20 ... 0x27: + /* GPE1_CTL - General Purpose Event1 Control Register */ + ret = (dev->regs.gpcntrl >> shift32) & 0xff; + break; + case 0x30: + /* PM2_CNTRL - Power Management 2 Control Register( */ + ret = dev->regs.pmcntrl; + break; + default: + ret = acpi_reg_read_common_regs(size, addr, priv); + break; } #ifdef ENABLE_ACPI_LOG - // if (size != 1) - // acpi_log("(%i) ACPI Read (%i) %02X: %02X\n", in_smm, size, addr, ret); + if (size != 1) + acpi_log("(%i) ACPI Read (%i) %02X: %02X\n", in_smm, size, addr, ret); #endif return ret; } - static uint32_t -acpi_reg_read_sis(int size, uint16_t addr, void *p) +acpi_reg_read_intel(int size, uint16_t addr, void *priv) { - acpi_t *dev = (acpi_t *) p; - uint32_t ret = 0x00000000; - int shift16, shift32; + const acpi_t *dev = (acpi_t *) priv; + uint32_t ret = 0x00000000; + int shift16; + int shift32; - addr &= 0x2f; + addr &= 0x3f; shift16 = (addr & 1) << 3; shift32 = (addr & 3) << 3; - switch(addr) - { - case 0x0c: - case 0x0d: - case 0x0e: - case 0x0f: - ret = (dev->regs.pcntrl >> shift32) & 0xff; - break; + switch (addr) { + case 0x0c: + case 0x0d: + /* GPSTS - General Purpose Status Register (IO) */ + ret = (dev->regs.gpsts >> shift16) & 0xff; + break; + case 0x0e: + case 0x0f: + /* GPEN - General Purpose Enable Register (IO) */ + ret = (dev->regs.gpen >> shift16) & 0xff; + break; + case 0x10: + case 0x11: + case 0x12: + case 0x13: + /* PCNTRL - Processor Control Register (IO) */ + ret = (dev->regs.pcntrl >> shift32) & 0xff; + break; + case 0x18: + case 0x19: + /* GLBSTS - Global Status Register (IO) */ + ret = (dev->regs.glbsts >> shift16) & 0xff; + if (addr == 0x18) { + ret &= 0x27; + if (dev->regs.gpsts != 0x0000) + ret |= 0x80; + if (dev->regs.pmsts != 0x0000) + ret |= 0x40; + if (dev->regs.devsts != 0x00000000) + ret |= 0x10; + } + break; + case 0x1c: + case 0x1d: + case 0x1e: + case 0x1f: + /* DEVSTS - Device Status Register (IO) */ + ret = (dev->regs.devsts >> shift32) & 0xff; + break; + case 0x20: + case 0x21: + /* GLBEN - Global Enable Register (IO) */ + ret = (dev->regs.glben >> shift16) & 0xff; + break; + case 0x28: + case 0x29: + case 0x2a: + case 0x2b: + /* GLBCTL - Global Control Register (IO) */ + ret = (dev->regs.glbctl >> shift32) & 0xff; + break; + case 0x2c: + case 0x2d: + case 0x2e: + case 0x2f: + /* DEVCTL - Device Control Register (IO) */ + ret = (dev->regs.devctl >> shift32) & 0xff; + break; + case 0x30: + case 0x31: + case 0x32: + /* GPIREG - General Purpose Input Register (IO) */ + if (size == 1) + ret = dev->regs.gpireg[addr & 3]; + break; + case 0x34: + case 0x35: + case 0x36: + case 0x37: + /* GPOREG - General Purpose Output Register (IO) */ + if (size == 1) + ret = dev->regs.gporeg[addr & 3]; + break; + default: + ret = acpi_reg_read_common_regs(size, addr, priv); + break; + } - case 0x12: - ret = dev->regs.p2cntrl; - break; - - case 0x13: - ret = dev->regs.gptimer; - break; - - case 0x14: case 0x15: - ret = (dev->regs.gpsts >> shift16) & 0xff; - break; - - case 0x16: case 0x17: - ret = (dev->regs.gpen >> shift16) & 0xff; - break; - - case 0x18: case 0x19: - ret = (dev->regs.gpcntrl >> shift16) & 0xff; - break; - - case 0x1a: case 0x1b: - ret = (dev->regs.gpen >> shift16) & 0xff; - break; - - case 0x1c: case 0x1d: - ret = (dev->regs.gpmux >> shift16) & 0xff; - break; - - case 0x1e: case 0x1f: - ret = (dev->regs.gplvl >> shift16) & 0xff; - break; - - case 0x20: - ret = dev->regs.smicmd; - break; - - case 0x24: - ret = dev->regs.muxcntrl; - break; - - case 0x25: - ret = dev->regs.auxsts; - break; - - case 0x26: - ret = dev->regs.auxen; - break; - - case 0x2a: - ret = dev->regs.smireg; - break; - - case 0x2b: - ret = dev->regs.acpitst; - break; - - default: - acpi_reg_read_common_regs(size, addr, p); - break; - } #ifdef ENABLE_ACPI_LOG - if (size != 1) - acpi_log("(%i) ACPI Read (%i) %02X: %02X\n", in_smm, size, addr, ret); + // if (size != 1) + // acpi_log("(%i) ACPI Read (%i) %02X: %02X\n", in_smm, size, addr, ret); #endif return ret; } - static uint32_t -acpi_reg_read_via_common(int size, uint16_t addr, void *p) +acpi_reg_read_via_common(int size, uint16_t addr, void *priv) { - acpi_t *dev = (acpi_t *) p; - uint32_t ret = 0x00000000; - int shift16, shift32; + const acpi_t *dev = (acpi_t *) priv; + uint32_t ret = 0x00000000; + int shift16; + int shift32; addr &= 0xff; shift16 = (addr & 1) << 3; shift32 = (addr & 3) << 3; switch (addr) { - case 0x10: case 0x11: case 0x12: case 0x13: - /* PCNTRL - Processor Control Register (IO) */ - ret = (dev->regs.pcntrl >> shift32) & 0xff; - break; - case 0x20: case 0x21: - /* GPSTS - General Purpose Status Register (IO) */ - ret = (dev->regs.gpsts >> shift16) & 0xff; - break; - case 0x22: case 0x23: - /* General Purpose SCI Enable */ - ret = (dev->regs.gpscien >> shift16) & 0xff; - break; - case 0x24: case 0x25: - /* General Purpose SMI Enable */ - ret = (dev->regs.gpsmien >> shift16) & 0xff; - break; - case 0x26: case 0x27: - /* Power Supply Control */ - ret = (dev->regs.pscntrl >> shift16) & 0xff; - break; - case 0x28: case 0x29: - /* GLBSTS - Global Status Register (IO) */ - ret = (dev->regs.glbsts >> shift16) & 0xff; - break; - case 0x2a: case 0x2b: - /* GLBEN - Global Enable Register (IO) */ - ret = (dev->regs.glben >> shift16) & 0xff; - break; - case 0x2c: case 0x2d: - /* GLBCTL - Global Control Register (IO) */ - ret = (dev->regs.glbctl >> shift16) & 0xff; - ret &= ~0x0110; - ret |= (dev->regs.smi_lock ? 0x10 : 0x00); - ret |= (dev->regs.smi_active ? 0x01 : 0x00); - break; - case 0x2f: - /* SMI Command */ - if (size == 1) - ret = dev->regs.smicmd & 0xff; - break; - case 0x30: case 0x31: case 0x32: case 0x33: - /* Primary Activity Detect Status */ - ret = (dev->regs.padsts >> shift32) & 0xff; - break; - case 0x34: case 0x35: case 0x36: case 0x37: - /* Primary Activity Detect Enable */ - ret = (dev->regs.paden >> shift32) & 0xff; - break; - case 0x38: case 0x39: case 0x3a: case 0x3b: - /* GP Timer Reload Enable */ - ret = (dev->regs.gptren >> shift32) & 0xff; - break; - default: - ret = acpi_reg_read_common_regs(size, addr, p); - break; + case 0x10: + case 0x11: + case 0x12: + case 0x13: + /* PCNTRL - Processor Control Register (IO) */ + ret = (dev->regs.pcntrl >> shift32) & 0xff; + break; + case 0x20: + case 0x21: + /* GPSTS - General Purpose Status Register (IO) */ + ret = (dev->regs.gpsts >> shift16) & 0xff; + break; + case 0x22: + case 0x23: + /* General Purpose SCI Enable */ + ret = (dev->regs.gpscien >> shift16) & 0xff; + break; + case 0x24: + case 0x25: + /* General Purpose SMI Enable */ + ret = (dev->regs.gpsmien >> shift16) & 0xff; + break; + case 0x26: + case 0x27: + /* Power Supply Control */ + ret = (dev->regs.pscntrl >> shift16) & 0xff; + break; + case 0x28: + case 0x29: + /* GLBSTS - Global Status Register (IO) */ + ret = (dev->regs.glbsts >> shift16) & 0xff; + break; + case 0x2a: + case 0x2b: + /* GLBEN - Global Enable Register (IO) */ + ret = (dev->regs.glben >> shift16) & 0xff; + break; + case 0x2c: + case 0x2d: + /* GLBCTL - Global Control Register (IO) */ + ret = (dev->regs.glbctl >> shift16) & 0xff; + ret &= ~0x0110; + ret |= (dev->regs.smi_lock ? 0x10 : 0x00); + ret |= (dev->regs.smi_active ? 0x01 : 0x00); + break; + case 0x2f: + /* SMI Command */ + if (size == 1) + ret = dev->regs.smicmd & 0xff; + break; + case 0x30: + case 0x31: + case 0x32: + case 0x33: + /* Primary Activity Detect Status */ + ret = (dev->regs.padsts >> shift32) & 0xff; + break; + case 0x34: + case 0x35: + case 0x36: + case 0x37: + /* Primary Activity Detect Enable */ + ret = (dev->regs.paden >> shift32) & 0xff; + break; + case 0x38: + case 0x39: + case 0x3a: + case 0x3b: + /* GP Timer Reload Enable */ + ret = (dev->regs.gptren >> shift32) & 0xff; + break; + default: + ret = acpi_reg_read_common_regs(size, addr, priv); + break; } #ifdef ENABLE_ACPI_LOG if (size != 1) - acpi_log("(%i) ACPI Read (%i) %02X: %02X\n", in_smm, size, addr, ret); + acpi_log("(%i) ACPI Read (%i) %02X: %02X\n", in_smm, size, addr, ret); #endif return ret; } - static uint32_t -acpi_reg_read_via(int size, uint16_t addr, void *p) +acpi_reg_read_via(int size, uint16_t addr, void *priv) { - acpi_t *dev = (acpi_t *) p; + acpi_t *dev = (acpi_t *) priv; uint32_t ret = 0x00000000; - int shift16; + int shift16; addr &= 0xff; shift16 = (addr & 1) << 3; switch (addr) { - case 0x40: - /* GPIO Direction Control */ - if (size == 1) - ret = dev->regs.gpio_dir & 0xff; - break; - case 0x42: - /* GPIO port Output Value */ - if (size == 1) - ret = dev->regs.gpio_val & 0x13; - break; - case 0x44: - /* GPIO port Input Value */ - if (size == 1) { - ret = dev->regs.extsmi_val & 0xff; + case 0x40: + /* GPIO Direction Control */ + if (size == 1) + ret = dev->regs.gpio_dir & 0xff; + break; + case 0x42: + /* GPIO port Output Value */ + if (size == 1) + ret = dev->regs.gpio_val & 0x13; + break; + case 0x44: + /* GPIO port Input Value */ + if (size == 1) { + ret = dev->regs.extsmi_val & 0xff; - if (dev->i2c) { - ret &= 0xf9; - if (!(dev->regs.gpio_dir & 0x02) && i2c_gpio_get_scl(dev->i2c)) - ret |= 0x02; - if (!(dev->regs.gpio_dir & 0x04) && i2c_gpio_get_sda(dev->i2c)) - ret |= 0x04; - } - } - break; - case 0x46: case 0x47: - /* GPO Port Output Value */ - ret = (dev->regs.gpo_val >> shift16) & 0xff; - break; - case 0x48: case 0x49: - /* GPO Port Input Value */ - ret = (dev->regs.gpi_val >> shift16) & 0xff; - break; - default: - ret = acpi_reg_read_via_common(size, addr, p); - break; + if (dev->i2c) { + ret &= 0xf9; + if (!(dev->regs.gpio_dir & 0x02) && i2c_gpio_get_scl(dev->i2c)) + ret |= 0x02; + if (!(dev->regs.gpio_dir & 0x04) && i2c_gpio_get_sda(dev->i2c)) + ret |= 0x04; + } + } + break; + case 0x46: + case 0x47: + /* GPO Port Output Value */ + ret = (dev->regs.gpo_val >> shift16) & 0xff; + break; + case 0x48: + case 0x49: + /* GPO Port Input Value */ + ret = (dev->regs.gpi_val >> shift16) & 0xff; + break; + default: + ret = acpi_reg_read_via_common(size, addr, priv); + break; } #ifdef ENABLE_ACPI_LOG if (size != 1) - acpi_log("(%i) ACPI Read (%i) %02X: %02X\n", in_smm, size, addr, ret); + acpi_log("(%i) ACPI Read (%i) %02X: %02X\n", in_smm, size, addr, ret); #endif return ret; } - static uint32_t -acpi_reg_read_via_596b(int size, uint16_t addr, void *p) +acpi_reg_read_via_596b(int size, uint16_t addr, void *priv) { - acpi_t *dev = (acpi_t *) p; - uint32_t ret = 0x00000000; - int shift16, shift32; + const acpi_t *dev = (acpi_t *) priv; + uint32_t ret = 0x00000000; + int shift16; + int shift32; addr &= 0x7f; shift16 = (addr & 1) << 3; shift32 = (addr & 3) << 3; switch (addr) { - case 0x40: /* Extended I/O Trap Status (686A/B) */ - ret = dev->regs.extiotrapsts; - break; - case 0x42: /* Extended I/O Trap Enable (686A/B) */ - ret = dev->regs.extiotrapen; - break; - case 0x44: case 0x45: - /* External SMI Input Value */ - ret = (dev->regs.extsmi_val >> shift16) & 0xff; - break; - case 0x48: case 0x49: case 0x4a: case 0x4b: - /* GPI Port Input Value */ - ret = (dev->regs.gpi_val >> shift32) & 0xff; - break; - case 0x4c: case 0x4d: case 0x4e: case 0x4f: - /* GPO Port Output Value */ - ret = (dev->regs.gpo_val >> shift32) & 0xff; - break; - default: - ret = acpi_reg_read_via_common(size, addr, p); - break; + case 0x40: /* Extended I/O Trap Status (686A/B) */ + ret = dev->regs.extiotrapsts; + break; + case 0x42: /* Extended I/O Trap Enable (686A/B) */ + ret = dev->regs.extiotrapen; + break; + case 0x44: + case 0x45: + /* External SMI Input Value */ + ret = (dev->regs.extsmi_val >> shift16) & 0xff; + break; + case 0x48: + case 0x49: + case 0x4a: + case 0x4b: + /* GPI Port Input Value */ + ret = (dev->regs.gpi_val >> shift32) & 0xff; + break; + case 0x4c: + case 0x4d: + case 0x4e: + case 0x4f: + /* GPO Port Output Value */ + ret = (dev->regs.gpo_val >> shift32) & 0xff; + break; + default: + ret = acpi_reg_read_via_common(size, addr, priv); + break; } #ifdef ENABLE_ACPI_LOG if (size != 1) - acpi_log("(%i) ACPI Read (%i) %02X: %02X\n", in_smm, size, addr, ret); + acpi_log("(%i) ACPI Read (%i) %02X: %02X\n", in_smm, size, addr, ret); #endif return ret; } - static uint32_t -acpi_reg_read_smc(int size, uint16_t addr, void *p) +acpi_reg_read_smc(int size, uint16_t addr, void *priv) { uint32_t ret = 0x00000000; addr &= 0x0f; - ret = acpi_reg_read_common_regs(size, addr, p); + ret = acpi_reg_read_common_regs(size, addr, priv); #ifdef ENABLE_ACPI_LOG if (size != 1) - acpi_log("(%i) ACPI Read (%i) %02X: %02X\n", in_smm, size, addr, ret); + acpi_log("(%i) ACPI Read (%i) %02X: %02X\n", in_smm, size, addr, ret); #endif return ret; } - static uint32_t -acpi_aux_reg_read_smc(int size, uint16_t addr, void *p) +acpi_aux_reg_read_smc(UNUSED(int size), uint16_t addr, void *priv) { - acpi_t *dev = (acpi_t *) p; - uint32_t ret = 0x00000000; - int shift16; + const acpi_t *dev = (acpi_t *) priv; + uint32_t ret = 0x00000000; + int shift16; addr &= 0x07; shift16 = (addr & 1) << 3; switch (addr) { - case 0x00: case 0x01: - /* SCI Status Register */ - ret = (dev->regs.pcntrl >> shift16) & 0xff; - break; - case 0x02: case 0x03: - /* SCI Enable Register */ - ret = (dev->regs.gpscien >> shift16) & 0xff; - break; - case 0x04: case 0x05: - /* Miscellaneous Status Register */ - ret = (dev->regs.glbsts >> shift16) & 0xff; - break; - case 0x06: - /* Miscellaneous Enable Register */ - ret = dev->regs.glben & 0xff; - break; - case 0x07: - /* Miscellaneous Control Register */ - ret = dev->regs.glbctl & 0xff; - break; + case 0x00: + case 0x01: + /* SCI Status Register */ + ret = (dev->regs.pcntrl >> shift16) & 0xff; + break; + case 0x02: + case 0x03: + /* SCI Enable Register */ + ret = (dev->regs.gpscien >> shift16) & 0xff; + break; + case 0x04: + case 0x05: + /* Miscellaneous Status Register */ + ret = (dev->regs.glbsts >> shift16) & 0xff; + break; + case 0x06: + /* Miscellaneous Enable Register */ + ret = dev->regs.glben & 0xff; + break; + case 0x07: + /* Miscellaneous Control Register */ + ret = dev->regs.glbctl & 0xff; + break; + + default: + break; } acpi_log("(%i) ACPI Read (%i) %02X: %02X\n", in_smm, size, addr, ret); return ret; } - static void -acpi_reg_write_common_regs(int size, uint16_t addr, uint8_t val, void *p) +acpi_reg_write_common_regs(UNUSED(int size), uint16_t addr, uint8_t val, void *priv) { - acpi_t *dev = (acpi_t *) p; - int shift16, sus_typ; + acpi_t *dev = (acpi_t *) priv; + int shift16; + int sus_typ; + uint8_t old; addr &= 0x3f; #ifdef ENABLE_ACPI_LOG if (size != 1) - acpi_log("(%i) ACPI Write (%i) %02X: %02X\n", in_smm, size, addr, val); + acpi_log("(%i) ACPI Write (%i) %02X: %02X\n", in_smm, size, addr, val); #endif shift16 = (addr & 1) << 3; switch (addr) { - case 0x00: case 0x01: - /* PMSTS - Power Management Status Register (IO) */ - dev->regs.pmsts &= ~((val << shift16) & 0x8d31); - if ((addr == 0x01) && (val & 0x04)) - acpi_rtc_status = 0; - acpi_update_irq(dev); - break; - case 0x02: case 0x03: - /* PMEN - Power Management Resume Enable Register (IO) */ - dev->regs.pmen = ((dev->regs.pmen & ~(0xff << shift16)) | (val << shift16)) & 0x0521; - acpi_update_irq(dev); - break; - case 0x04: case 0x05: - /* PMCNTRL - Power Management Control Register (IO) */ - if ((addr == 0x05) && (val & 0x20)) { - sus_typ = dev->suspend_types[(val >> 2) & 7]; + case 0x00: + case 0x01: + /* PMSTS - Power Management Status Register (IO) */ + dev->regs.pmsts &= ~((val << shift16) & 0x8d31); + if ((addr == 0x01) && (val & 0x04)) + acpi_rtc_status = 0; + acpi_update_irq(dev); + break; + case 0x02: + case 0x03: + /* PMEN - Power Management Resume Enable Register (IO) */ + dev->regs.pmen = ((dev->regs.pmen & ~(0xff << shift16)) | (val << shift16)) & 0x0521; + acpi_update_irq(dev); + break; + case 0x04: + case 0x05: + /* PMCNTRL - Power Management Control Register (IO) */ + old = dev->regs.pmcntrl & 0xff; + if ((addr == 0x05) && (val & 0x20)) { + sus_typ = dev->suspend_types[(val >> 2) & 7]; + acpi_log("ACPI suspend type %d flags %02X\n", (val >> 2) & 7, sus_typ); - if (sus_typ & SUS_POWER_OFF) { - /* Soft power off. */ - plat_power_off(); - return; - } + if (sus_typ & SUS_POWER_OFF) { + /* Soft power off. */ + plat_power_off(); + return; + } - if (sus_typ & SUS_SUSPEND) { - if (sus_typ & SUS_NVR) { - /* Suspend to RAM. */ - nvr_reg_write(0x000f, 0xff, dev->nvr); - } + if (sus_typ & SUS_SUSPEND) { + if (sus_typ & SUS_NVR) { + /* Suspend to RAM. */ + nvr_reg_write(0x000f, 0xff, dev->nvr); + } - if (sus_typ & SUS_RESET_PCI) - device_reset_all_pci(); + if (sus_typ & SUS_RESET_PCI) + device_reset_all(DEVICE_PCI); - if (sus_typ & SUS_RESET_CPU) - cpu_alt_reset = 0; + if (sus_typ & SUS_RESET_CPU) + cpu_alt_reset = 0; - if (sus_typ & SUS_RESET_PCI) { - pci_reset(); - keyboard_at_reset(); + if (sus_typ & SUS_RESET_PCI) { + pci_reset(); - mem_a20_alt = 0; - mem_a20_recalc(); - } + mem_a20_alt = 0; + mem_a20_recalc(); + } - if (sus_typ & (SUS_RESET_CPU | SUS_RESET_CACHE)) - flushmmucache(); + if (sus_typ & (SUS_RESET_CPU | SUS_RESET_CACHE)) + flushmmucache(); - if (sus_typ & SUS_RESET_CPU) - resetx86(); + if (sus_typ & SUS_RESET_CPU) + resetx86(); - /* Since the UI doesn't have a power button at the moment, pause emulation, - then trigger a resume event so that the system resumes after unpausing. */ - plat_pause(1); - timer_set_delay_u64(&dev->resume_timer, 50 * TIMER_USEC); - } - } - dev->regs.pmcntrl = ((dev->regs.pmcntrl & ~(0xff << shift16)) | (val << shift16)) & 0x3f07 /* 0x3c07 */; - break; - } -} + /* Since the UI doesn't have a power button at the moment, pause emulation, + then trigger a resume event so that the system resumes after unpausing. */ + plat_pause(1); + timer_set_delay_u64(&dev->resume_timer, 50 * TIMER_USEC); + } + } + dev->regs.pmcntrl = ((dev->regs.pmcntrl & ~(0xff << shift16)) | (val << shift16)) & 0x3f07 /* 0x3c07 */; + if ((addr == 0x04) && ((old ^ val) & 0x01)) + acpi_update_irq(dev); + break; - -static void -acpi_reg_write_ali(int size, uint16_t addr, uint8_t val, void *p) -{ - acpi_t *dev = (acpi_t *) p; - int shift16, shift32; - - addr &= 0x3f; -#ifdef ENABLE_ACPI_LOG - if (size != 1) - acpi_log("(%i) ACPI Write (%i) %02X: %02X\n", in_smm, size, addr, val); -#endif - shift16 = (addr & 1) << 3; - shift32 = (addr & 3) << 3; - - switch (addr) { - case 0x10: case 0x11: case 0x12: case 0x13: - /* PCNTRL - Processor Control Register (IO) */ - dev->regs.pcntrl = ((dev->regs.pcntrl & ~(0xff << shift32)) | (val << shift32)) & 0x00023e1e; - break; - case 0x14: - /* LVL2 - Processor Level 2 Register */ - dev->regs.plvl2 = val; - break; - case 0x15: - /* LVL3 - Processor Level 3 Register */ - dev->regs.plvl3 = val; - break; - case 0x18: case 0x19: - /* GPE0_STS - General Purpose Event0 Status Register */ - dev->regs.gpsts &= ~((val << shift16) & 0x0d07); - break; - case 0x1a: case 0x1b: - /* GPE0_EN - General Purpose Event0 Enable Register */ - dev->regs.gpen = ((dev->regs.gpen & ~(0xff << shift16)) | (val << shift16)) & 0x0d07; - break; - case 0x1d: case 0x1c: - /* GPE1_STS - General Purpose Event1 Status Register */ - dev->regs.gpsts1 &= ~((val << shift16) & 0x0c01); - break; - case 0x1f: case 0x1e: - /* GPE1_EN - General Purpose Event1 Enable Register */ - dev->regs.gpen1 = ((dev->regs.gpen & ~(0xff << shift16)) | (val << shift16)) & 0x0c01; - break; - case 0x20 ... 0x27: - /* GPE1_CTL - General Purpose Event1 Control Register */ - dev->regs.gpcntrl = ((dev->regs.gpcntrl & ~(0xff << shift32)) | (val << shift32)) & 0x00000001; - break; - case 0x30: - /* PM2_CNTRL - Power Management 2 Control Register( */ - dev->regs.pmcntrl = val & 1; - break; - default: - acpi_reg_write_common_regs(size, addr, val, p); - /* Setting GBL_RLS also sets BIOS_STS and generates SMI. */ - if ((addr == 0x00) && !(dev->regs.pmsts & 0x20)) - dev->regs.gpcntrl &= ~0x0002; - else if ((addr == 0x04) && (dev->regs.pmcntrl & 0x0004)) { - dev->regs.gpsts1 |= 0x01; - if (dev->regs.gpen1 & 0x01) - acpi_raise_smi(dev, 1); - } - } -} - - -static void -acpi_reg_write_intel(int size, uint16_t addr, uint8_t val, void *p) -{ - acpi_t *dev = (acpi_t *) p; - int shift16, shift32; - - addr &= 0x3f; -#ifdef ENABLE_ACPI_LOG - if (size != 1) - acpi_log("(%i) ACPI Write (%i) %02X: %02X\n", in_smm, size, addr, val); -#endif - shift16 = (addr & 1) << 3; - shift32 = (addr & 3) << 3; - - switch (addr) { - case 0x0c: case 0x0d: - /* GPSTS - General Purpose Status Register (IO) */ - dev->regs.gpsts &= ~((val << shift16) & 0x0f81); - break; - case 0x0e: case 0x0f: - /* GPEN - General Purpose Enable Register (IO) */ - dev->regs.gpen = ((dev->regs.gpen & ~(0xff << shift16)) | (val << shift16)) & 0x0f01; - break; - case 0x10: case 0x11: case 0x13: - /* PCNTRL - Processor Control Register (IO) */ - dev->regs.pcntrl = ((dev->regs.pcntrl & ~(0xff << shift32)) | (val << shift32)) & 0x00023e1e; - break; - case 0x12: - /* PCNTRL - Processor Control Register (IO) */ - dev->regs.pcntrl = ((dev->regs.pcntrl & ~(0xfd << shift32)) | (val << shift32)) & 0x00023e1e; - break; - case 0x18: case 0x19: - /* GLBSTS - Global Status Register (IO) */ - dev->regs.glbsts &= ~((val << shift16) & 0x0d27); - break; - case 0x1c: case 0x1d: case 0x1e: case 0x1f: - /* DEVSTS - Device Status Register (IO) */ - dev->regs.devsts &= ~((val << shift32) & 0x3fff0fff); - break; - case 0x20: case 0x21: - /* GLBEN - Global Enable Register (IO) */ - dev->regs.glben = ((dev->regs.glben & ~(0xff << shift16)) | (val << shift16)) & 0x8d1f; - break; - case 0x28: case 0x29: case 0x2a: case 0x2b: - /* GLBCTL - Global Control Register (IO) */ - dev->regs.glbctl = ((dev->regs.glbctl & ~(0xff << shift32)) | (val << shift32)) & 0x0701ff07; - /* Setting BIOS_RLS also sets GBL_STS and generates SMI. */ - if (dev->regs.glbctl & 0x00000002) { - dev->regs.pmsts |= 0x20; - if (dev->regs.pmen & 0x20) - acpi_update_irq(dev); - } - break; - case 0x2c: case 0x2d: case 0x2e: case 0x2f: - /* DEVCTL - Device Control Register (IO) */ - dev->regs.devctl = ((dev->regs.devctl & ~(0xff << shift32)) | (val << shift32)) & 0x0fffffff; - if (dev->trap_update) - dev->trap_update(dev->trap_priv); - break; - case 0x34: case 0x35: case 0x36: case 0x37: - /* GPOREG - General Purpose Output Register (IO) */ - if (size == 1) - dev->regs.gporeg[addr & 3] = val; - break; - default: - acpi_reg_write_common_regs(size, addr, val, p); - /* Setting GBL_RLS also sets BIOS_STS and generates SMI. */ - if ((addr == 0x00) && !(dev->regs.pmsts & 0x20)) - dev->regs.glbctl &= ~0x0002; - else if ((addr == 0x04) && (dev->regs.pmcntrl & 0x0004)) { - dev->regs.glbsts |= 0x01; - if (dev->regs.glben & 0x02) - acpi_raise_smi(dev, 1); - } - break; + default: + break; } } static void -acpi_reg_write_sis(int size, uint16_t addr, uint8_t val, void *p) +acpi_reg_write_ali(int size, uint16_t addr, uint8_t val, void *priv) { - acpi_t *dev = (acpi_t *) p; - int shift16, shift32; + acpi_t *dev = (acpi_t *) priv; + int shift16; + int shift32; - addr &= 0x2f; + addr &= 0x3f; +#ifdef ENABLE_ACPI_LOG + if (size != 1) + acpi_log("(%i) ACPI Write (%i) %02X: %02X\n", in_smm, size, addr, val); +#endif shift16 = (addr & 1) << 3; shift32 = (addr & 3) << 3; -switch(addr) -{ - case 0x0c: - case 0x0d: - case 0x0e: - case 0x0f: - dev->regs.pcntrl = ((dev->regs.pcntrl & ~(0xff << shift32)) | (val << shift32)) & 0x0000007e; - break; - - case 0x12: - dev->regs.p2cntrl = val & 1; - break; - - case 0x13: - dev->regs.gptimer = val; - break; - - case 0x14: case 0x15: - dev->regs.gpsts &= ~((val << shift16) & 0xff9f); - break; - - case 0x16: case 0x17: - dev->regs.gpen = ((dev->regs.gpen & ~(0xff << shift16)) | (val << shift16)) & 0xef1f; - break; - - case 0x18: case 0x19: - dev->regs.gpcntrl &= ~((val << shift16) & 0x07ff); - break; - - case 0x1a: case 0x1b: - dev->regs.gpen = ((dev->regs.gpen & ~(0xff << shift16)) | (val << shift16)) & 0x0187; - break; - - case 0x1c: case 0x1d: - dev->regs.gpmux = ((dev->regs.gpmux & ~(0xff << shift16)) | (val << shift16)) & 0x3f7f; - if(dev->regs.gpmux & 0x0400) - dev->regs.pmsts |= 0x0020; - break; - - case 0x1e: case 0x1f: - dev->regs.gplvl = ((dev->regs.gplvl & ~(0xff << shift16)) | (val << shift16)) & 0x0fb7; - break; - - case 0x20: - dev->regs.smicmd = val; - break; - - case 0x24: - dev->regs.muxcntrl = val & 0xc3; - break; - - case 0x25: - dev->regs.auxsts &= val & 0x1f; - break; - - case 0x26: - dev->regs.auxen = val & 0x3f; - break; - - case 0x2a: - dev->regs.smireg = val; - break; - - case 0x2b: - dev->regs.acpitst = val; - break; - - default: - acpi_reg_write_common_regs(size, addr, val, p); - break; -} - -#ifdef ENABLE_ACPI_LOG - if (size != 1) - acpi_log("(%i) ACPI Write (%i) %02X: %02X\n", in_smm, size, addr, val); -#endif + switch (addr) { + case 0x10: + case 0x11: + case 0x12: + case 0x13: + /* PCNTRL - Processor Control Register (IO) */ + dev->regs.pcntrl = ((dev->regs.pcntrl & ~(0xff << shift32)) | (val << shift32)) & 0x00023e1e; + break; + case 0x14: + /* LVL2 - Processor Level 2 Register */ + dev->regs.plvl2 = val; + break; + case 0x15: + /* LVL3 - Processor Level 3 Register */ + dev->regs.plvl3 = val; + break; + case 0x18: + case 0x19: + /* GPE0_STS - General Purpose Event0 Status Register */ + dev->regs.gpsts &= ~((val << shift16) & 0x0d07); + break; + case 0x1a: + case 0x1b: + /* GPE0_EN - General Purpose Event0 Enable Register */ + dev->regs.gpen = ((dev->regs.gpen & ~(0xff << shift16)) | (val << shift16)) & 0x0d07; + break; + case 0x1d: + case 0x1c: + /* GPE1_STS - General Purpose Event1 Status Register */ + dev->regs.gpsts1 &= ~((val << shift16) & 0x0c01); + break; + case 0x1f: + case 0x1e: + /* GPE1_EN - General Purpose Event1 Enable Register */ + dev->regs.gpen1 = ((dev->regs.gpen & ~(0xff << shift16)) | (val << shift16)) & 0x0c01; + break; + case 0x20 ... 0x27: + /* GPE1_CTL - General Purpose Event1 Control Register */ + dev->regs.gpcntrl = ((dev->regs.gpcntrl & ~(0xff << shift32)) | (val << shift32)) & 0x00000001; + break; + case 0x30: + /* PM2_CNTRL - Power Management 2 Control Register */ + dev->regs.pmcntrl = val & 1; + break; + default: + acpi_reg_write_common_regs(size, addr, val, priv); + /* Setting GBL_RLS also sets BIOS_STS and generates SMI. */ + if ((addr == 0x00) && !(dev->regs.pmsts & 0x20)) + dev->regs.gpcntrl &= ~0x0002; + else if ((addr == 0x04) && (dev->regs.pmcntrl & 0x0004)) { + dev->regs.gpsts1 |= 0x01; + if (dev->regs.gpen1 & 0x01) + acpi_raise_smi(dev, 1); + } + } } static void -acpi_reg_write_via_common(int size, uint16_t addr, uint8_t val, void *p) +acpi_reg_write_intel(int size, uint16_t addr, uint8_t val, void *priv) { - acpi_t *dev = (acpi_t *) p; - int shift16, shift32; + acpi_t *dev = (acpi_t *) priv; + int shift16; + int shift32; + + addr &= 0x3f; +#ifdef ENABLE_ACPI_LOG + if (size != 1) + acpi_log("(%i) ACPI Write (%i) %02X: %02X\n", in_smm, size, addr, val); +#endif + shift16 = (addr & 1) << 3; + shift32 = (addr & 3) << 3; + + switch (addr) { + case 0x0c: + case 0x0d: + /* GPSTS - General Purpose Status Register (IO) */ + dev->regs.gpsts &= ~((val << shift16) & 0x0f81); + break; + case 0x0e: + case 0x0f: + /* GPEN - General Purpose Enable Register (IO) */ + dev->regs.gpen = ((dev->regs.gpen & ~(0xff << shift16)) | (val << shift16)) & 0x0f01; + break; + case 0x10: + case 0x11: + case 0x13: + /* PCNTRL - Processor Control Register (IO) */ + dev->regs.pcntrl = ((dev->regs.pcntrl & ~(0xff << shift32)) | (val << shift32)) & 0x00023e1e; + break; + case 0x12: + /* PCNTRL - Processor Control Register (IO) */ + dev->regs.pcntrl = ((dev->regs.pcntrl & ~(0xfd << shift32)) | (val << shift32)) & 0x00023e1e; + break; + case 0x18: + case 0x19: + /* GLBSTS - Global Status Register (IO) */ + dev->regs.glbsts &= ~((val << shift16) & 0x0d27); + break; + case 0x1c: + case 0x1d: + case 0x1e: + case 0x1f: + /* DEVSTS - Device Status Register (IO) */ + dev->regs.devsts &= ~((val << shift32) & 0x3fff0fff); + break; + case 0x20: + case 0x21: + /* GLBEN - Global Enable Register (IO) */ + dev->regs.glben = ((dev->regs.glben & ~(0xff << shift16)) | (val << shift16)) & 0x8d1f; + break; + case 0x28: + case 0x29: + case 0x2a: + case 0x2b: + /* GLBCTL - Global Control Register (IO) */ + dev->regs.glbctl = ((dev->regs.glbctl & ~(0xff << shift32)) | (val << shift32)) & 0x0701ff07; + /* Setting BIOS_RLS also sets GBL_STS and generates SMI. */ + if (dev->regs.glbctl & 0x00000002) { + dev->regs.pmsts |= 0x20; + if (dev->regs.pmen & 0x20) + acpi_update_irq(dev); + } + break; + case 0x2c: + case 0x2d: + case 0x2e: + case 0x2f: + /* DEVCTL - Device Control Register (IO) */ + dev->regs.devctl = ((dev->regs.devctl & ~(0xff << shift32)) | (val << shift32)) & 0x0fffffff; + if (dev->trap_update) + dev->trap_update(dev->trap_priv); + break; + case 0x34: + case 0x35: + case 0x36: + case 0x37: + /* GPOREG - General Purpose Output Register (IO) */ + if (size == 1) + dev->regs.gporeg[addr & 3] = val; + break; + default: + acpi_reg_write_common_regs(size, addr, val, priv); + /* Setting GBL_RLS also sets BIOS_STS and generates SMI. */ + if ((addr == 0x00) && !(dev->regs.pmsts & 0x20)) + dev->regs.glbctl &= ~0x0002; + else if ((addr == 0x04) && (dev->regs.pmcntrl & 0x0004)) { + dev->regs.glbsts |= 0x01; + if (dev->regs.glben & 0x02) + acpi_raise_smi(dev, 1); + } + break; + } +} + +static void +acpi_reg_write_via_common(int size, uint16_t addr, uint8_t val, void *priv) +{ + acpi_t *dev = (acpi_t *) priv; + int shift16; + int shift32; addr &= 0xff; acpi_log("(%i) ACPI Write (%i) %02X: %02X\n", in_smm, size, addr, val); @@ -935,84 +919,93 @@ acpi_reg_write_via_common(int size, uint16_t addr, uint8_t val, void *p) shift32 = (addr & 3) << 3; switch (addr) { - case 0x10: case 0x11: case 0x12: case 0x13: - /* PCNTRL - Processor Control Register (IO) */ - dev->regs.pcntrl = ((dev->regs.pcntrl & ~(0xff << shift32)) | (val << shift32)) & 0x0000001e; - break; - case 0x20: case 0x21: - /* GPSTS - General Purpose Status Register (IO) */ - dev->regs.gpsts &= ~((val << shift16) & 0x03ff); - break; - case 0x22: case 0x23: - /* General Purpose SCI Enable */ - dev->regs.gpscien = ((dev->regs.gpscien & ~(0xff << shift16)) | (val << shift16)) & 0x03ff; - break; - case 0x24: case 0x25: - /* General Purpose SMI Enable */ - dev->regs.gpsmien = ((dev->regs.gpsmien & ~(0xff << shift16)) | (val << shift16)) & 0x03ff; - break; - case 0x26: case 0x27: - /* Power Supply Control */ - dev->regs.pscntrl = ((dev->regs.pscntrl & ~(0xff << shift16)) | (val << shift16)) & 0x0701; - break; - case 0x2c: - /* GLBCTL - Global Control Register (IO) */ - dev->regs.glbctl = (dev->regs.glbctl & ~0xff) | (val & 0xff); - dev->regs.smi_lock = !!(dev->regs.glbctl & 0x0010); - /* Setting BIOS_RLS also sets GBL_STS and generates SMI. */ - if (dev->regs.glbctl & 0x0002) { - dev->regs.pmsts |= 0x20; - if (dev->regs.pmen & 0x20) - acpi_update_irq(dev); - } - break; - case 0x2d: - /* GLBCTL - Global Control Register (IO) */ - dev->regs.glbctl &= ~((val << 8) & 0x0100); - if (val & 0x01) - dev->regs.smi_active = 0; - break; - case 0x2f: - /* SMI Command */ - if (size == 1) { - dev->regs.smicmd = val & 0xff; - dev->regs.glbsts |= 0x40; - if (dev->regs.glben & 0x40) - acpi_raise_smi(dev, 1); - } - break; - case 0x38: case 0x39: case 0x3a: case 0x3b: - /* GP Timer Reload Enable */ - dev->regs.gptren = ((dev->regs.gptren & ~(0xff << shift32)) | (val << shift32)) & 0x000000d9; - break; - default: - acpi_reg_write_common_regs(size, addr, val, p); - /* Setting GBL_RLS also sets BIOS_STS and generates SMI. */ - if ((addr == 0x00) && !(dev->regs.pmsts & 0x20)) - dev->regs.glbctl &= ~0x0002; - else if ((addr == 0x04) && (dev->regs.pmcntrl & 0x0004)) { - dev->regs.glbsts |= 0x20; - if (dev->regs.glben & 0x20) - acpi_raise_smi(dev, 1); - } - break; + case 0x10: + case 0x11: + case 0x12: + case 0x13: + /* PCNTRL - Processor Control Register (IO) */ + dev->regs.pcntrl = ((dev->regs.pcntrl & ~(0xff << shift32)) | (val << shift32)) & 0x0000001e; + break; + case 0x20: + case 0x21: + /* GPSTS - General Purpose Status Register (IO) */ + dev->regs.gpsts &= ~((val << shift16) & 0x03ff); + break; + case 0x22: + case 0x23: + /* General Purpose SCI Enable */ + dev->regs.gpscien = ((dev->regs.gpscien & ~(0xff << shift16)) | (val << shift16)) & 0x03ff; + break; + case 0x24: + case 0x25: + /* General Purpose SMI Enable */ + dev->regs.gpsmien = ((dev->regs.gpsmien & ~(0xff << shift16)) | (val << shift16)) & 0x03ff; + break; + case 0x26: + case 0x27: + /* Power Supply Control */ + dev->regs.pscntrl = ((dev->regs.pscntrl & ~(0xff << shift16)) | (val << shift16)) & 0x0701; + break; + case 0x2c: + /* GLBCTL - Global Control Register (IO) */ + dev->regs.glbctl = (dev->regs.glbctl & ~0xff) | (val & 0xff); + dev->regs.smi_lock = !!(dev->regs.glbctl & 0x0010); + /* Setting BIOS_RLS also sets GBL_STS and generates SMI. */ + if (dev->regs.glbctl & 0x0002) { + dev->regs.pmsts |= 0x20; + if (dev->regs.pmen & 0x20) + acpi_update_irq(dev); + } + break; + case 0x2d: + /* GLBCTL - Global Control Register (IO) */ + dev->regs.glbctl &= ~((val << 8) & 0x0100); + if (val & 0x01) + dev->regs.smi_active = 0; + break; + case 0x2f: + /* SMI Command */ + if (size == 1) { + dev->regs.smicmd = val & 0xff; + dev->regs.glbsts |= 0x40; + if (dev->regs.glben & 0x40) + acpi_raise_smi(dev, 1); + } + break; + case 0x38: + case 0x39: + case 0x3a: + case 0x3b: + /* GP Timer Reload Enable */ + dev->regs.gptren = ((dev->regs.gptren & ~(0xff << shift32)) | (val << shift32)) & 0x000000d9; + break; + default: + acpi_reg_write_common_regs(size, addr, val, priv); + /* Setting GBL_RLS also sets BIOS_STS and generates SMI. */ + if ((addr == 0x00) && !(dev->regs.pmsts & 0x20)) + dev->regs.glbctl &= ~0x0002; + else if ((addr == 0x04) && (dev->regs.pmcntrl & 0x0004)) { + dev->regs.glbsts |= 0x20; + if (dev->regs.glben & 0x20) + acpi_raise_smi(dev, 1); + } + break; } } - static void acpi_i2c_set(acpi_t *dev) { if (dev->i2c) - i2c_gpio_set(dev->i2c, !(dev->regs.gpio_dir & 0x02) || (dev->regs.gpio_val & 0x02), !(dev->regs.gpio_dir & 0x04) || (dev->regs.gpio_val & 0x04)); + i2c_gpio_set(dev->i2c, !(dev->regs.gpio_dir & 0x02) || (dev->regs.gpio_val & 0x02), !(dev->regs.gpio_dir & 0x04) || (dev->regs.gpio_val & 0x04)); } - static void -acpi_reg_write_via(int size, uint16_t addr, uint8_t val, void *p) +acpi_reg_write_via(int size, uint16_t addr, uint8_t val, void *priv) { - acpi_t *dev = (acpi_t *) p; - int shift16, shift32; + acpi_t *dev = (acpi_t *) priv; + int shift16; + int shift32; addr &= 0xff; acpi_log("(%i) ACPI Write (%i) %02X: %02X\n", in_smm, size, addr, val); @@ -1020,54 +1013,63 @@ acpi_reg_write_via(int size, uint16_t addr, uint8_t val, void *p) shift32 = (addr & 3) << 3; switch (addr) { - case 0x28: case 0x29: - /* GLBSTS - Global Status Register (IO) */ - dev->regs.glbsts &= ~((val << shift16) & 0x007f); - break; - case 0x2a: case 0x2b: - /* GLBEN - Global Enable Register (IO) */ - dev->regs.glben = ((dev->regs.glben & ~(0xff << shift16)) | (val << shift16)) & 0x007f; - break; - case 0x30: case 0x31: case 0x32: case 0x33: - /* Primary Activity Detect Status */ - dev->regs.padsts &= ~((val << shift32) & 0x000000fd); - break; - case 0x34: case 0x35: case 0x36: case 0x37: - /* Primary Activity Detect Enable */ - dev->regs.paden = ((dev->regs.paden & ~(0xff << shift32)) | (val << shift32)) & 0x000000fd; - if (dev->trap_update) - dev->trap_update(dev->trap_priv); - break; - case 0x40: - /* GPIO Direction Control */ - if (size == 1) { - dev->regs.gpio_dir = val & 0x7f; - acpi_i2c_set(dev); - } - break; - case 0x42: - /* GPIO port Output Value */ - if (size == 1) { - dev->regs.gpio_val = val & 0x13; - acpi_i2c_set(dev); - } - break; - case 0x46: case 0x47: - /* GPO Port Output Value */ - dev->regs.gpo_val = ((dev->regs.gpo_val & ~(0xff << shift16)) | (val << shift16)) & 0xffff; - break; - default: - acpi_reg_write_via_common(size, addr, val, p); - break; + case 0x28: + case 0x29: + /* GLBSTS - Global Status Register (IO) */ + dev->regs.glbsts &= ~((val << shift16) & 0x007f); + break; + case 0x2a: + case 0x2b: + /* GLBEN - Global Enable Register (IO) */ + dev->regs.glben = ((dev->regs.glben & ~(0xff << shift16)) | (val << shift16)) & 0x007f; + break; + case 0x30: + case 0x31: + case 0x32: + case 0x33: + /* Primary Activity Detect Status */ + dev->regs.padsts &= ~((val << shift32) & 0x000000fd); + break; + case 0x34: + case 0x35: + case 0x36: + case 0x37: + /* Primary Activity Detect Enable */ + dev->regs.paden = ((dev->regs.paden & ~(0xff << shift32)) | (val << shift32)) & 0x000000fd; + if (dev->trap_update) + dev->trap_update(dev->trap_priv); + break; + case 0x40: + /* GPIO Direction Control */ + if (size == 1) { + dev->regs.gpio_dir = val & 0x7f; + acpi_i2c_set(dev); + } + break; + case 0x42: + /* GPIO port Output Value */ + if (size == 1) { + dev->regs.gpio_val = val & 0x13; + acpi_i2c_set(dev); + } + break; + case 0x46: + case 0x47: + /* GPO Port Output Value */ + dev->regs.gpo_val = ((dev->regs.gpo_val & ~(0xff << shift16)) | (val << shift16)) & 0xffff; + break; + default: + acpi_reg_write_via_common(size, addr, val, priv); + break; } } - static void -acpi_reg_write_via_596b(int size, uint16_t addr, uint8_t val, void *p) +acpi_reg_write_via_596b(int size, uint16_t addr, uint8_t val, void *priv) { - acpi_t *dev = (acpi_t *) p; - int shift16, shift32; + acpi_t *dev = (acpi_t *) priv; + int shift16; + int shift32; addr &= 0x7f; acpi_log("(%i) ACPI Write (%i) %02X: %02X\n", in_smm, size, addr, val); @@ -1075,422 +1077,385 @@ acpi_reg_write_via_596b(int size, uint16_t addr, uint8_t val, void *p) shift32 = (addr & 3) << 3; switch (addr) { - case 0x28: case 0x29: - /* GLBSTS - Global Status Register (IO) */ - dev->regs.glbsts &= ~((val << shift16) & 0xfdff); - break; - case 0x2a: case 0x2b: - /* GLBEN - Global Enable Register (IO) */ - dev->regs.glben = ((dev->regs.glben & ~(0xff << shift16)) | (val << shift16)) & 0xfdff; - break; - case 0x30: case 0x31: case 0x32: case 0x33: - /* Primary Activity Detect Status */ - dev->regs.padsts &= ~((val << shift32) & 0x000007ff); - break; - case 0x34: case 0x35: case 0x36: case 0x37: - /* Primary Activity Detect Enable */ - dev->regs.paden = ((dev->regs.paden & ~(0xff << shift32)) | (val << shift32)) & 0x000007ff; - if (dev->trap_update) - dev->trap_update(dev->trap_priv); - break; - case 0x40: /* Extended I/O Trap Status (686A/B) */ - dev->regs.extiotrapsts &= ~(val & 0x13); - break; - case 0x42: /* Extended I/O Trap Enable (686A/B) */ - dev->regs.extiotrapen = val & 0x13; - break; - case 0x4c: case 0x4d: case 0x4e: case 0x4f: - /* GPO Port Output Value */ - dev->regs.gpo_val = ((dev->regs.gpo_val & ~(0xff << shift32)) | (val << shift32)) & 0x7fffffff; - break; - default: - acpi_reg_write_via_common(size, addr, val, p); - break; + case 0x28: + case 0x29: + /* GLBSTS - Global Status Register (IO) */ + dev->regs.glbsts &= ~((val << shift16) & 0xfdff); + break; + case 0x2a: + case 0x2b: + /* GLBEN - Global Enable Register (IO) */ + dev->regs.glben = ((dev->regs.glben & ~(0xff << shift16)) | (val << shift16)) & 0xfdff; + break; + case 0x30: + case 0x31: + case 0x32: + case 0x33: + /* Primary Activity Detect Status */ + dev->regs.padsts &= ~((val << shift32) & 0x000007ff); + break; + case 0x34: + case 0x35: + case 0x36: + case 0x37: + /* Primary Activity Detect Enable */ + dev->regs.paden = ((dev->regs.paden & ~(0xff << shift32)) | (val << shift32)) & 0x000007ff; + if (dev->trap_update) + dev->trap_update(dev->trap_priv); + break; + case 0x40: /* Extended I/O Trap Status (686A/B) */ + dev->regs.extiotrapsts &= ~(val & 0x13); + break; + case 0x42: /* Extended I/O Trap Enable (686A/B) */ + dev->regs.extiotrapen = val & 0x13; + break; + case 0x4c: + case 0x4d: + case 0x4e: + case 0x4f: + /* GPO Port Output Value */ + dev->regs.gpo_val = ((dev->regs.gpo_val & ~(0xff << shift32)) | (val << shift32)) & 0x7fffffff; + break; + default: + acpi_reg_write_via_common(size, addr, val, priv); + break; } } - static void -acpi_reg_write_smc(int size, uint16_t addr, uint8_t val, void *p) +acpi_reg_write_smc(int size, uint16_t addr, uint8_t val, void *priv) { - acpi_t *dev = (acpi_t *) p; + acpi_t *dev = (acpi_t *) priv; addr &= 0x0f; acpi_log("(%i) ACPI Write (%i) %02X: %02X\n", in_smm, size, addr, val); - acpi_reg_write_common_regs(size, addr, val, p); + acpi_reg_write_common_regs(size, addr, val, priv); /* Setting GBL_RLS also sets BIOS_STS and generates SMI. */ if ((addr == 0x00) && !(dev->regs.pmsts & 0x20)) - dev->regs.glbctl &= ~0x0001; + dev->regs.glbctl &= ~0x0001; else if ((addr == 0x04) && (dev->regs.pmcntrl & 0x0004)) { - dev->regs.glbsts |= 0x01; - if (dev->regs.glben & 0x01) - acpi_raise_smi(dev, 1); + dev->regs.glbsts |= 0x01; + if (dev->regs.glben & 0x01) + acpi_raise_smi(dev, 1); } } - static void -acpi_aux_reg_write_smc(int size, uint16_t addr, uint8_t val, void *p) +acpi_aux_reg_write_smc(UNUSED(int size), uint16_t addr, uint8_t val, void *priv) { - acpi_t *dev = (acpi_t *) p; - int shift16; + acpi_t *dev = (acpi_t *) priv; + int shift16; addr &= 0x07; acpi_log("(%i) ACPI Write (%i) %02X: %02X\n", in_smm, size, addr, val); shift16 = (addr & 1) << 3; switch (addr) { - case 0x00: case 0x01: - /* SCI Status Register */ - dev->regs.gpscists &= ~((val << shift16) & 0x000c); - break; - case 0x02: case 0x03: - /* SCI Enable Register */ - dev->regs.gpscien = ((dev->regs.gpscien & ~(0xff << shift16)) | (val << shift16)) & 0x3fff; - break; - case 0x04: case 0x05: - /* Miscellanous Status Register */ - dev->regs.glbsts &= ~((val << shift16) & 0x001f); - break; - case 0x06: - /* Miscellaneous Enable Register */ - dev->regs.glben = (uint16_t) (val & 0x03); - break; - case 0x07: - /* Miscellaneous Control Register */ - dev->regs.glbctl = (uint16_t) (val & 0x03); - /* Setting BIOS_RLS also sets GBL_STS and generates SMI. */ - if (dev->regs.glbctl & 0x0001) { - dev->regs.pmsts |= 0x20; - if (dev->regs.pmen & 0x20) - acpi_update_irq(dev); - } - if (dev->regs.glbctl & 0x0002) { - dev->regs.pmsts |= 0x10; - if (dev->regs.pmcntrl & 0x02) - acpi_update_irq(dev); - } - break; + case 0x00: + case 0x01: + /* SCI Status Register */ + dev->regs.gpscists &= ~((val << shift16) & 0x000c); + break; + case 0x02: + case 0x03: + /* SCI Enable Register */ + dev->regs.gpscien = ((dev->regs.gpscien & ~(0xff << shift16)) | (val << shift16)) & 0x3fff; + break; + case 0x04: + case 0x05: + /* Miscellanous Status Register */ + dev->regs.glbsts &= ~((val << shift16) & 0x001f); + break; + case 0x06: + /* Miscellaneous Enable Register */ + dev->regs.glben = (uint16_t) (val & 0x03); + break; + case 0x07: + /* Miscellaneous Control Register */ + dev->regs.glbctl = (uint16_t) (val & 0x03); + /* Setting BIOS_RLS also sets GBL_STS and generates SMI. */ + if (dev->regs.glbctl & 0x0001) { + dev->regs.pmsts |= 0x20; + if (dev->regs.pmen & 0x20) + acpi_update_irq(dev); + } + if (dev->regs.glbctl & 0x0002) { + dev->regs.pmsts |= 0x10; + if (dev->regs.pmcntrl & 0x02) + acpi_update_irq(dev); + } + break; + + default: + break; } } - static uint32_t -acpi_reg_read_common(int size, uint16_t addr, void *p) +acpi_reg_read_common(int size, uint16_t addr, void *priv) { - acpi_t *dev = (acpi_t *) p; + const acpi_t *dev = (acpi_t *) priv; uint8_t ret = 0xff; if (dev->vendor == VEN_ALI) - ret = acpi_reg_read_ali(size, addr, p); + ret = acpi_reg_read_ali(size, addr, priv); else if (dev->vendor == VEN_VIA) - ret = acpi_reg_read_via(size, addr, p); + ret = acpi_reg_read_via(size, addr, priv); else if (dev->vendor == VEN_VIA_596B) - ret = acpi_reg_read_via_596b(size, addr, p); + ret = acpi_reg_read_via_596b(size, addr, priv); else if (dev->vendor == VEN_INTEL) - ret = acpi_reg_read_intel(size, addr, p); - else if (dev->vendor == VEN_SIS) - ret = acpi_reg_read_sis(size, addr, p); + ret = acpi_reg_read_intel(size, addr, priv); else if (dev->vendor == VEN_SMC) - ret = acpi_reg_read_smc(size, addr, p); + ret = acpi_reg_read_smc(size, addr, priv); return ret; } - static void -acpi_reg_write_common(int size, uint16_t addr, uint8_t val, void *p) +acpi_reg_write_common(int size, uint16_t addr, uint8_t val, void *priv) { - acpi_t *dev = (acpi_t *) p; + const acpi_t *dev = (acpi_t *) priv; if (dev->vendor == VEN_ALI) - acpi_reg_write_ali(size, addr, val, p); + acpi_reg_write_ali(size, addr, val, priv); else if (dev->vendor == VEN_VIA) - acpi_reg_write_via(size, addr, val, p); + acpi_reg_write_via(size, addr, val, priv); else if (dev->vendor == VEN_VIA_596B) - acpi_reg_write_via_596b(size, addr, val, p); + acpi_reg_write_via_596b(size, addr, val, priv); else if (dev->vendor == VEN_INTEL) - acpi_reg_write_intel(size, addr, val, p); - else if (dev->vendor == VEN_SIS) - acpi_reg_write_sis(size, addr, val, p); + acpi_reg_write_intel(size, addr, val, priv); else if (dev->vendor == VEN_SMC) - acpi_reg_write_smc(size, addr, val, p); + acpi_reg_write_smc(size, addr, val, priv); } - static uint32_t -acpi_aux_reg_read_common(int size, uint16_t addr, void *p) +acpi_aux_reg_read_common(int size, uint16_t addr, void *priv) { - acpi_t *dev = (acpi_t *) p; + const acpi_t *dev = (acpi_t *) priv; uint8_t ret = 0xff; if (dev->vendor == VEN_SMC) - ret = acpi_aux_reg_read_smc(size, addr, p); + ret = acpi_aux_reg_read_smc(size, addr, priv); return ret; } - static void -acpi_aux_reg_write_common(int size, uint16_t addr, uint8_t val, void *p) +acpi_aux_reg_write_common(int size, uint16_t addr, uint8_t val, void *priv) { - acpi_t *dev = (acpi_t *) p; + const acpi_t *dev = (acpi_t *) priv; if (dev->vendor == VEN_SMC) - acpi_aux_reg_write_smc(size, addr, val, p); + acpi_aux_reg_write_smc(size, addr, val, priv); } - static uint32_t -acpi_reg_readl(uint16_t addr, void *p) +acpi_reg_readl(uint16_t addr, void *priv) { uint32_t ret = 0x00000000; - ret = acpi_reg_read_common(4, addr, p); - ret |= (acpi_reg_read_common(4, addr + 1, p) << 8); - ret |= (acpi_reg_read_common(4, addr + 2, p) << 16); - ret |= (acpi_reg_read_common(4, addr + 3, p) << 24); + ret = acpi_reg_read_common(4, addr, priv); + ret |= (acpi_reg_read_common(4, addr + 1, priv) << 8); + ret |= (acpi_reg_read_common(4, addr + 2, priv) << 16); + ret |= (acpi_reg_read_common(4, addr + 3, priv) << 24); acpi_log("ACPI: Read L %08X from %04X\n", ret, addr); return ret; } - static uint16_t -acpi_reg_readw(uint16_t addr, void *p) +acpi_reg_readw(uint16_t addr, void *priv) { uint16_t ret = 0x0000; - ret = acpi_reg_read_common(2, addr, p); - ret |= (acpi_reg_read_common(2, addr + 1, p) << 8); + ret = acpi_reg_read_common(2, addr, priv); + ret |= (acpi_reg_read_common(2, addr + 1, priv) << 8); acpi_log("ACPI: Read W %08X from %04X\n", ret, addr); return ret; } - static uint8_t -acpi_reg_read(uint16_t addr, void *p) +acpi_reg_read(uint16_t addr, void *priv) { uint8_t ret = 0x00; - ret = acpi_reg_read_common(1, addr, p); + ret = acpi_reg_read_common(1, addr, priv); acpi_log("ACPI: Read B %02X from %04X\n", ret, addr); return ret; } - static uint32_t -acpi_aux_reg_readl(uint16_t addr, void *p) +acpi_aux_reg_readl(uint16_t addr, void *priv) { uint32_t ret = 0x00000000; - ret = acpi_aux_reg_read_common(4, addr, p); - ret |= (acpi_aux_reg_read_common(4, addr + 1, p) << 8); - ret |= (acpi_aux_reg_read_common(4, addr + 2, p) << 16); - ret |= (acpi_aux_reg_read_common(4, addr + 3, p) << 24); + ret = acpi_aux_reg_read_common(4, addr, priv); + ret |= (acpi_aux_reg_read_common(4, addr + 1, priv) << 8); + ret |= (acpi_aux_reg_read_common(4, addr + 2, priv) << 16); + ret |= (acpi_aux_reg_read_common(4, addr + 3, priv) << 24); acpi_log("ACPI: Read Aux L %08X from %04X\n", ret, addr); return ret; } - static uint16_t -acpi_aux_reg_readw(uint16_t addr, void *p) +acpi_aux_reg_readw(uint16_t addr, void *priv) { uint16_t ret = 0x0000; - ret = acpi_aux_reg_read_common(2, addr, p); - ret |= (acpi_aux_reg_read_common(2, addr + 1, p) << 8); + ret = acpi_aux_reg_read_common(2, addr, priv); + ret |= (acpi_aux_reg_read_common(2, addr + 1, priv) << 8); acpi_log("ACPI: Read Aux W %04X from %04X\n", ret, addr); return ret; } - static uint8_t -acpi_aux_reg_read(uint16_t addr, void *p) +acpi_aux_reg_read(uint16_t addr, void *priv) { uint8_t ret = 0x00; - ret = acpi_aux_reg_read_common(1, addr, p); + ret = acpi_aux_reg_read_common(1, addr, priv); acpi_log("ACPI: Read Aux B %02X from %04X\n", ret, addr); return ret; } - static void -acpi_reg_writel(uint16_t addr, uint32_t val, void *p) +acpi_reg_writel(uint16_t addr, uint32_t val, void *priv) { acpi_log("ACPI: Write L %08X to %04X\n", val, addr); - acpi_reg_write_common(4, addr, val & 0xff, p); - acpi_reg_write_common(4, addr + 1, (val >> 8) & 0xff, p); - acpi_reg_write_common(4, addr + 2, (val >> 16) & 0xff, p); - acpi_reg_write_common(4, addr + 3, (val >> 24) & 0xff, p); + acpi_reg_write_common(4, addr, val & 0xff, priv); + acpi_reg_write_common(4, addr + 1, (val >> 8) & 0xff, priv); + acpi_reg_write_common(4, addr + 2, (val >> 16) & 0xff, priv); + acpi_reg_write_common(4, addr + 3, (val >> 24) & 0xff, priv); } - static void -acpi_reg_writew(uint16_t addr, uint16_t val, void *p) +acpi_reg_writew(uint16_t addr, uint16_t val, void *priv) { acpi_log("ACPI: Write W %04X to %04X\n", val, addr); - acpi_reg_write_common(2, addr, val & 0xff, p); - acpi_reg_write_common(2, addr + 1, (val >> 8) & 0xff, p); + acpi_reg_write_common(2, addr, val & 0xff, priv); + acpi_reg_write_common(2, addr + 1, (val >> 8) & 0xff, priv); } - static void -acpi_reg_write(uint16_t addr, uint8_t val, void *p) +acpi_reg_write(uint16_t addr, uint8_t val, void *priv) { acpi_log("ACPI: Write B %02X to %04X\n", val, addr); - acpi_reg_write_common(1, addr, val, p); + acpi_reg_write_common(1, addr, val, priv); } - static void -acpi_aux_reg_writel(uint16_t addr, uint32_t val, void *p) +acpi_aux_reg_writel(uint16_t addr, uint32_t val, void *priv) { acpi_log("ACPI: Write Aux L %08X to %04X\n", val, addr); - acpi_aux_reg_write_common(4, addr, val & 0xff, p); - acpi_aux_reg_write_common(4, addr + 1, (val >> 8) & 0xff, p); - acpi_aux_reg_write_common(4, addr + 2, (val >> 16) & 0xff, p); - acpi_aux_reg_write_common(4, addr + 3, (val >> 24) & 0xff, p); + acpi_aux_reg_write_common(4, addr, val & 0xff, priv); + acpi_aux_reg_write_common(4, addr + 1, (val >> 8) & 0xff, priv); + acpi_aux_reg_write_common(4, addr + 2, (val >> 16) & 0xff, priv); + acpi_aux_reg_write_common(4, addr + 3, (val >> 24) & 0xff, priv); } - static void -acpi_aux_reg_writew(uint16_t addr, uint16_t val, void *p) +acpi_aux_reg_writew(uint16_t addr, uint16_t val, void *priv) { acpi_log("ACPI: Write Aux W %04X to %04X\n", val, addr); - acpi_aux_reg_write_common(2, addr, val & 0xff, p); - acpi_aux_reg_write_common(2, addr + 1, (val >> 8) & 0xff, p); + acpi_aux_reg_write_common(2, addr, val & 0xff, priv); + acpi_aux_reg_write_common(2, addr + 1, (val >> 8) & 0xff, priv); } - static void -acpi_aux_reg_write(uint16_t addr, uint8_t val, void *p) +acpi_aux_reg_write(uint16_t addr, uint8_t val, void *priv) { acpi_log("ACPI: Write Aux B %02X to %04X\n", val, addr); - acpi_aux_reg_write_common(1, addr, val, p); + acpi_aux_reg_write_common(1, addr, val, priv); } - void acpi_update_io_mapping(acpi_t *dev, uint32_t base, int chipset_en) { int size; switch (dev->vendor) { - case VEN_ALI: - case VEN_INTEL: - default: - size = 0x040; - break; - case VEN_SIS: - size = 0x030; - break; - case VEN_SMC: - size = 0x010; - break; - case VEN_VIA: - size = 0x100; - break; - case VEN_VIA_596B: - size = 0x080; - break; + default: + case VEN_ALI: + case VEN_INTEL: + size = 0x040; + break; + case VEN_SMC: + size = 0x010; + break; + case VEN_VIA: + size = 0x100; + break; + case VEN_VIA_596B: + size = 0x080; + break; } acpi_log("ACPI: Update I/O %04X to %04X (%sabled)\n", dev->io_base, base, chipset_en ? "en" : "dis"); if (dev->io_base != 0x0000) { - io_removehandler(dev->io_base, size, - acpi_reg_read, acpi_reg_readw, acpi_reg_readl, - acpi_reg_write, acpi_reg_writew, acpi_reg_writel, dev); + io_removehandler(dev->io_base, size, + acpi_reg_read, acpi_reg_readw, acpi_reg_readl, + acpi_reg_write, acpi_reg_writew, acpi_reg_writel, dev); } dev->io_base = base; if (chipset_en && (dev->io_base != 0x0000)) { - io_sethandler(dev->io_base, size, - acpi_reg_read, acpi_reg_readw, acpi_reg_readl, - acpi_reg_write, acpi_reg_writew, acpi_reg_writel, dev); + io_sethandler(dev->io_base, size, + acpi_reg_read, acpi_reg_readw, acpi_reg_readl, + acpi_reg_write, acpi_reg_writew, acpi_reg_writel, dev); } } - void acpi_update_aux_io_mapping(acpi_t *dev, uint32_t base, int chipset_en) { int size; switch (dev->vendor) { - case VEN_SMC: - size = 0x008; - break; - default: - size = 0x000; - break; + case VEN_SMC: + size = 0x008; + break; + default: + size = 0x000; + break; } acpi_log("ACPI: Update Aux I/O %04X to %04X (%sabled)\n", dev->aux_io_base, base, chipset_en ? "en" : "dis"); if (dev->aux_io_base != 0x0000) { - io_removehandler(dev->aux_io_base, size, - acpi_aux_reg_read, acpi_aux_reg_readw, acpi_aux_reg_readl, - acpi_aux_reg_write, acpi_aux_reg_writew, acpi_aux_reg_writel, dev); + io_removehandler(dev->aux_io_base, size, + acpi_aux_reg_read, acpi_aux_reg_readw, acpi_aux_reg_readl, + acpi_aux_reg_write, acpi_aux_reg_writew, acpi_aux_reg_writel, dev); } dev->aux_io_base = base; if (chipset_en && (dev->aux_io_base != 0x0000)) { - io_sethandler(dev->aux_io_base, size, - acpi_aux_reg_read, acpi_aux_reg_readw, acpi_aux_reg_readl, - acpi_aux_reg_write, acpi_aux_reg_writew, acpi_aux_reg_writel, dev); + io_sethandler(dev->aux_io_base, size, + acpi_aux_reg_read, acpi_aux_reg_readw, acpi_aux_reg_readl, + acpi_aux_reg_write, acpi_aux_reg_writew, acpi_aux_reg_writel, dev); } } - -static void -acpi_timer_count(void *priv) -{ - acpi_t *dev = (acpi_t *) priv; - int overflow; - uint32_t old; - - old = dev->regs.timer_val; - dev->regs.timer_val++; - - if (dev->regs.timer32) - overflow = (old ^ dev->regs.timer_val) & 0x80000000; - else { - dev->regs.timer_val &= 0x00ffffff; - overflow = (old ^ dev->regs.timer_val) & 0x00800000; - } - - if (overflow) { - dev->regs.pmsts |= TMROF_EN; - acpi_update_irq(dev); - } - - timer_advance_u64(&dev->timer, ACPICONST); -} - - static void acpi_timer_resume(void *priv) { @@ -1501,10 +1466,9 @@ acpi_timer_resume(void *priv) /* Nasty workaround for ASUS P2B-LS and potentially others, where the PMCNTRL SMI trap handler clears the resume bit before returning control to the OS. */ if (in_smm) - timer_set_delay_u64(&dev->resume_timer, 50 * TIMER_USEC); + timer_set_delay_u64(&dev->resume_timer, 50 * TIMER_USEC); } - void acpi_init_gporeg(acpi_t *dev, uint8_t val0, uint8_t val1, uint8_t val2, uint8_t val3) { @@ -1515,138 +1479,139 @@ acpi_init_gporeg(acpi_t *dev, uint8_t val0, uint8_t val1, uint8_t val2, uint8_t acpi_log("acpi_init_gporeg(): %02X %02X %02X %02X\n", dev->regs.gporeg[0], dev->regs.gporeg[1], dev->regs.gporeg[2], dev->regs.gporeg[3]); } - void acpi_set_timer32(acpi_t *dev, uint8_t timer32) { dev->regs.timer32 = timer32; - - if (!dev->regs.timer32) - dev->regs.timer_val &= 0x00ffffff; } - void acpi_set_slot(acpi_t *dev, int slot) { dev->slot = slot; } - void acpi_set_irq_mode(acpi_t *dev, int irq_mode) { dev->irq_mode = irq_mode; } - void acpi_set_irq_pin(acpi_t *dev, int irq_pin) { dev->irq_pin = irq_pin; } - void acpi_set_irq_line(acpi_t *dev, int irq_line) { dev->irq_line = irq_line; } - void acpi_set_mirq_is_level(acpi_t *dev, int mirq_is_level) { dev->mirq_is_level = mirq_is_level; } - void acpi_set_gpireg2_default(acpi_t *dev, uint8_t gpireg2_default) { dev->gpireg2_default = gpireg2_default; - dev->regs.gpireg[2] = dev->gpireg2_default; + dev->regs.gpireg[2] = dev->gpireg2_default; } - void acpi_set_nvr(acpi_t *dev, nvr_t *nvr) { dev->nvr = nvr; } - void acpi_set_trap_update(acpi_t *dev, void (*update)(void *priv), void *priv) { dev->trap_update = update; - dev->trap_priv = priv; + dev->trap_priv = priv; } - uint8_t acpi_ali_soft_smi_status_read(acpi_t *dev) { return dev->regs.ali_soft_smi = 1; } - void acpi_ali_soft_smi_status_write(acpi_t *dev, uint8_t soft_smi) { dev->regs.ali_soft_smi = soft_smi; } +void +acpi_pwrbtn_timer(void *priv) +{ + acpi_t *dev = (acpi_t *) priv; + + timer_on_auto(&dev->pwrbtn_timer, 16. * 1000.); + if (acpi_pwrbut_pressed) { + acpi_pwrbut_pressed = 0; + if (dev->regs.pmen & PWRBTN_EN) { + dev->regs.pmsts |= PWRBTN_STS; + acpi_update_irq(dev); + } + } +} static void -acpi_apm_out(uint16_t port, uint8_t val, void *p) +acpi_apm_out(uint16_t port, uint8_t val, void *priv) { - acpi_t *dev = (acpi_t *) p; + acpi_t *dev = (acpi_t *) priv; acpi_log("[%04X:%08X] APM write: %04X = %02X (AX = %04X, BX = %04X, CX = %04X)\n", CS, cpu_state.pc, port, val, AX, BX, CX); port &= 0x0001; if (dev->vendor == VEN_ALI) { - if (port == 0x0001) { - acpi_log("ALi SOFT SMI# status set (%i)\n", dev->apm->do_smi); - dev->apm->cmd = val; - // acpi_raise_smi(dev, dev->apm->do_smi); - if (dev->apm->do_smi) - smi_line = 1; - dev->regs.ali_soft_smi = 1; - } else if (port == 0x0003) - dev->apm->stat = val; + if (port == 0x0001) { + acpi_log("ALi SOFT SMI# status set (%i)\n", dev->apm->do_smi); + dev->apm->cmd = val; +#if 0 + acpi_raise_smi(dev, dev->apm->do_smi); +#endif + if (dev->apm->do_smi) + smi_raise(); + dev->regs.ali_soft_smi = 1; + } else if (port == 0x0003) + dev->apm->stat = val; } else { - if (port == 0x0000) { - dev->apm->cmd = val; - if (dev->vendor == VEN_INTEL) - dev->regs.glbsts |= 0x20; - acpi_raise_smi(dev, dev->apm->do_smi); - } else - dev->apm->stat = val; + if (port == 0x0000) { + dev->apm->cmd = val; + if (dev->vendor == VEN_INTEL) + dev->regs.glbsts |= 0x20; + acpi_raise_smi(dev, dev->apm->do_smi); + } else + dev->apm->stat = val; } } - static uint8_t -acpi_apm_in(uint16_t port, void *p) +acpi_apm_in(uint16_t port, void *priv) { - acpi_t *dev = (acpi_t *) p; - uint8_t ret = 0xff; + const acpi_t *dev = (acpi_t *) priv; + uint8_t ret = 0xff; port &= 0x0001; if (dev->vendor == VEN_ALI) { - if (port == 0x0001) - ret = dev->apm->cmd; - else if (port == 0x0003) - ret = dev->apm->stat; + if (port == 0x0001) + ret = dev->apm->cmd; + else if (port == 0x0003) + ret = dev->apm->stat; } else { - if (port == 0x0000) - ret = dev->apm->cmd; - else - ret = dev->apm->stat; + if (port == 0x0000) + ret = dev->apm->cmd; + else + ret = dev->apm->stat; } acpi_log("[%04X:%08X] APM read: %04X = %02X\n", CS, cpu_state.pc, port, ret); @@ -1654,240 +1619,230 @@ acpi_apm_in(uint16_t port, void *p) return ret; } - static void acpi_reset(void *priv) { acpi_t *dev = (acpi_t *) priv; - int i; memset(&dev->regs, 0x00, sizeof(acpi_regs_t)); - dev->regs.gpireg[0] = 0xff; dev->regs.gpireg[1] = 0xff; + dev->regs.gpireg[0] = 0xff; + dev->regs.gpireg[1] = 0xff; /* A-Trend ATC7020BXII: - Bit 3: 80-conductor cable on secondary IDE channel (active low) - Bit 2: 80-conductor cable on primary IDE channel (active low) Gigabyte GA-686BX: - Bit 1: CMOS battery low (active high) */ dev->regs.gpireg[2] = dev->gpireg2_default; - for (i = 0; i < 4; i++) - dev->regs.gporeg[i] = dev->gporeg_default[i]; + for (uint8_t i = 0; i < 4; i++) + dev->regs.gporeg[i] = dev->gporeg_default[i]; if (dev->vendor == VEN_VIA_596B) { - dev->regs.gpo_val = 0x7fffffff; - /* FIC VA-503A: - - Bit 11: ATX power (active high) - - Bit 4: 80-conductor cable on primary IDE channel (active low) - - Bit 3: 80-conductor cable on secondary IDE channel (active low) - - Bit 2: password cleared (active low) - ASUS P3V4X: - - Bit 15: 80-conductor cable on secondary IDE channel (active low) - - Bit 5: 80-conductor cable on primary IDE channel (active low) - BCM GT694VA: - - Bit 19: 80-conductor cable on secondary IDE channel (active low) - - Bit 17: 80-conductor cable on primary IDE channel (active low) - ASUS CUV4X-LS: - - Bit 2: 80-conductor cable on secondary IDE channel (active low) - - Bit 1: 80-conductor cable on primary IDE channel (active low) - Acorp 6VIA90AP: - - Bit 3: 80-conductor cable on secondary IDE channel (active low) - - Bit 1: 80-conductor cable on primary IDE channel (active low) */ - dev->regs.gpi_val = 0xfff57fc1; - if (!strcmp(machine_get_internal_name(), "ficva503a") || !strcmp(machine_get_internal_name(), "6via90ap")) - dev->regs.gpi_val |= 0x00000004; + dev->regs.gpo_val = 0x7fffffff; + /* FIC VA-503A: + - Bit 11: ATX power (active high) + - Bit 4: 80-conductor cable on primary IDE channel (active low) + - Bit 3: 80-conductor cable on secondary IDE channel (active low) + - Bit 2: password cleared (active low) + ASUS P3V4X: + - Bit 15: 80-conductor cable on secondary IDE channel (active low) + - Bit 5: 80-conductor cable on primary IDE channel (active low) + BCM GT694VA: + - Bit 19: 80-conductor cable on secondary IDE channel (active low) + - Bit 17: 80-conductor cable on primary IDE channel (active low) + ASUS CUV4X-LS: + - Bit 2: 80-conductor cable on secondary IDE channel (active low) + - Bit 1: 80-conductor cable on primary IDE channel (active low) + Acorp 6VIA90AP: + - Bit 3: 80-conductor cable on secondary IDE channel (active low) + - Bit 1: 80-conductor cable on primary IDE channel (active low) */ + dev->regs.gpi_val = 0xfff57fc1; + if (!strcmp(machine_get_internal_name(), "ficva503a") || !strcmp(machine_get_internal_name(), "6via90ap")) + dev->regs.gpi_val |= 0x00000004; } - /* Power on always generates a resume event. */ - dev->regs.pmsts |= 0x8000; + if (acpi_power_on) { + /* Power on always generates a resume event. */ + dev->regs.pmsts |= 0x8100; + acpi_power_on = 0; + } acpi_rtc_status = 0; -} + acpi_update_irq(dev); + dev->irq_state = 0; +} static void acpi_speed_changed(void *priv) { - acpi_t *dev = (acpi_t *) priv; + acpi_t *dev = (acpi_t *) priv; + cpu_to_acpi = ACPI_TIMER_FREQ / cpuclock; + bool timer_enabled = timer_is_enabled(&dev->timer); + timer_stop(&dev->timer); - timer_disable(&dev->timer); - timer_set_delay_u64(&dev->timer, ACPICONST); + if (timer_enabled) + timer_on_auto(&dev->timer, acpi_get_overflow_period(dev)); } - static void acpi_close(void *priv) { acpi_t *dev = (acpi_t *) priv; if (dev->i2c) { - if (i2c_smbus == i2c_gpio_get_bus(dev->i2c)) - i2c_smbus = NULL; - i2c_gpio_close(dev->i2c); + if (i2c_smbus == i2c_gpio_get_bus(dev->i2c)) + i2c_smbus = NULL; + i2c_gpio_close(dev->i2c); } - timer_disable(&dev->timer); + timer_stop(&dev->timer); free(dev); } - static void * acpi_init(const device_t *info) { acpi_t *dev; - dev = (acpi_t *)malloc(sizeof(acpi_t)); - if (dev == NULL) return(NULL); + dev = (acpi_t *) malloc(sizeof(acpi_t)); + if (dev == NULL) + return NULL; memset(dev, 0x00, sizeof(acpi_t)); + cpu_to_acpi = ACPI_TIMER_FREQ / cpuclock; dev->vendor = info->local; dev->irq_line = 9; if ((dev->vendor == VEN_INTEL) || (dev->vendor == VEN_ALI)) { - if (dev->vendor == VEN_ALI) - dev->irq_mode = 2; - dev->apm = device_add(&apm_pci_acpi_device); - if (dev->vendor == VEN_ALI) { - acpi_log("Setting I/O handler at port B1\n"); - io_sethandler(0x00b1, 0x0003, acpi_apm_in, NULL, NULL, acpi_apm_out, NULL, NULL, dev); - } else - io_sethandler(0x00b2, 0x0002, acpi_apm_in, NULL, NULL, acpi_apm_out, NULL, NULL, dev); + if (dev->vendor == VEN_ALI) + dev->irq_mode = 2; + dev->apm = device_add(&apm_pci_acpi_device); + if (dev->vendor == VEN_ALI) { + acpi_log("Setting I/O handler at port B1\n"); + io_sethandler(0x00b1, 0x0003, acpi_apm_in, NULL, NULL, acpi_apm_out, NULL, NULL, dev); + } else + io_sethandler(0x00b2, 0x0002, acpi_apm_in, NULL, NULL, acpi_apm_out, NULL, NULL, dev); } else if (dev->vendor == VEN_VIA) { - dev->i2c = i2c_gpio_init("smbus_vt82c586b"); - i2c_smbus = i2c_gpio_get_bus(dev->i2c); + dev->i2c = i2c_gpio_init("smbus_vt82c586b"); + i2c_smbus = i2c_gpio_get_bus(dev->i2c); } switch (dev->vendor) { - case VEN_ALI: - dev->suspend_types[0] = SUS_POWER_OFF; - dev->suspend_types[1] = SUS_POWER_OFF; - dev->suspend_types[2] = SUS_SUSPEND | SUS_NVR | SUS_RESET_CPU | SUS_RESET_PCI; - dev->suspend_types[3] = SUS_SUSPEND; - break; + case VEN_ALI: + dev->suspend_types[0] = SUS_POWER_OFF; + dev->suspend_types[1] = SUS_POWER_OFF; + dev->suspend_types[2] = SUS_SUSPEND | SUS_NVR | SUS_RESET_CPU | SUS_RESET_PCI; + dev->suspend_types[3] = SUS_SUSPEND; + dev->suspend_types[5] = SUS_POWER_OFF; /* undocumented, used for S4/S5 by ASUS P5A ACPI table */ + dev->suspend_types[7] = SUS_POWER_OFF; /* undocumented, used for S5 by Gigabyte GA-5AX ACPI table */ + break; - case VEN_VIA: - dev->suspend_types[0] = SUS_POWER_OFF; - dev->suspend_types[2] = SUS_SUSPEND; - break; + case VEN_VIA: + dev->suspend_types[0] = SUS_POWER_OFF; + dev->suspend_types[2] = SUS_SUSPEND; + break; - case VEN_VIA_596B: - dev->suspend_types[1] = SUS_SUSPEND | SUS_NVR | SUS_RESET_CPU | SUS_RESET_PCI; - dev->suspend_types[2] = SUS_POWER_OFF; - dev->suspend_types[4] = SUS_SUSPEND; - dev->suspend_types[5] = SUS_SUSPEND | SUS_RESET_CPU; - dev->suspend_types[6] = SUS_SUSPEND | SUS_RESET_CPU | SUS_RESET_PCI; - break; + case VEN_VIA_596B: + dev->suspend_types[1] = SUS_SUSPEND | SUS_NVR | SUS_RESET_CPU | SUS_RESET_PCI; + dev->suspend_types[2] = SUS_POWER_OFF; + dev->suspend_types[4] = SUS_SUSPEND; + dev->suspend_types[5] = SUS_SUSPEND | SUS_RESET_CPU; + dev->suspend_types[6] = SUS_SUSPEND | SUS_RESET_CPU | SUS_RESET_PCI; + break; - case VEN_INTEL: - dev->suspend_types[0] = SUS_POWER_OFF; - dev->suspend_types[1] = SUS_SUSPEND | SUS_NVR | SUS_RESET_CPU | SUS_RESET_PCI; - dev->suspend_types[2] = SUS_SUSPEND | SUS_RESET_CPU; - dev->suspend_types[3] = SUS_SUSPEND | SUS_RESET_CACHE; - dev->suspend_types[4] = SUS_SUSPEND; - break; + case VEN_INTEL: + dev->suspend_types[0] = SUS_POWER_OFF; + dev->suspend_types[1] = SUS_SUSPEND | SUS_NVR | SUS_RESET_CPU | SUS_RESET_PCI; + dev->suspend_types[2] = SUS_SUSPEND | SUS_RESET_CPU; + dev->suspend_types[3] = SUS_SUSPEND | SUS_RESET_CACHE; + dev->suspend_types[4] = SUS_SUSPEND; + break; - case VEN_SIS: - dev->suspend_types[0] = SUS_SUSPEND; - dev->suspend_types[4] = SUS_POWER_OFF; - break; + default: + break; } - timer_add(&dev->timer, acpi_timer_count, dev, 0); - timer_set_delay_u64(&dev->timer, ACPICONST); + timer_add(&dev->timer, acpi_timer_overflow, dev, 0); timer_add(&dev->resume_timer, acpi_timer_resume, dev, 0); + timer_add(&dev->pwrbtn_timer, acpi_pwrbtn_timer, dev, 0); + + timer_on_auto(&dev->pwrbtn_timer, 16. * 1000.); acpi_reset(dev); + acpi_enabled = 1; + acpi_power_on = 1; + return dev; } -const device_t acpi_ali_device = -{ - "ALi M7101 ACPI", - "acpi_ali", - DEVICE_PCI, - VEN_ALI, - acpi_init, - acpi_close, - acpi_reset, - { NULL }, - acpi_speed_changed, - NULL, - NULL +const device_t acpi_ali_device = { + .name = "ALi M7101 ACPI", + .internal_name = "acpi_ali", + .flags = DEVICE_PCI, + .local = VEN_ALI, + .init = acpi_init, + .close = acpi_close, + .reset = acpi_reset, + { .available = NULL }, + .speed_changed = acpi_speed_changed, + .force_redraw = NULL, + .config = NULL }; -const device_t acpi_intel_device = -{ - "Intel ACPI", - "acpi_intel", - DEVICE_PCI, - VEN_INTEL, - acpi_init, - acpi_close, - acpi_reset, - { NULL }, - acpi_speed_changed, - NULL, - NULL +const device_t acpi_intel_device = { + .name = "Intel ACPI", + .internal_name = "acpi_intel", + .flags = DEVICE_PCI, + .local = VEN_INTEL, + .init = acpi_init, + .close = acpi_close, + .reset = acpi_reset, + { .available = NULL }, + .speed_changed = acpi_speed_changed, + .force_redraw = NULL, + .config = NULL }; -const device_t acpi_sis_device = -{ - "SiS ACPI", - "acpi_sis", - DEVICE_PCI, - VEN_SIS, - acpi_init, - acpi_close, - acpi_reset, - { NULL }, - acpi_speed_changed, - NULL, - NULL +const device_t acpi_via_device = { + .name = "VIA ACPI", + .internal_name = "acpi_via", + .flags = DEVICE_PCI, + .local = VEN_VIA, + .init = acpi_init, + .close = acpi_close, + .reset = acpi_reset, + { .available = NULL }, + .speed_changed = acpi_speed_changed, + .force_redraw = NULL, + .config = NULL }; -const device_t acpi_via_device = -{ - "VIA ACPI", - "acpi_via", - DEVICE_PCI, - VEN_VIA, - acpi_init, - acpi_close, - acpi_reset, - { NULL }, - acpi_speed_changed, - NULL, - NULL +const device_t acpi_via_596b_device = { + .name = "VIA VT82C596 ACPI", + .internal_name = "acpi_via_596b", + .flags = DEVICE_PCI, + .local = VEN_VIA_596B, + .init = acpi_init, + .close = acpi_close, + .reset = acpi_reset, + { .available = NULL }, + .speed_changed = acpi_speed_changed, + .force_redraw = NULL, + .config = NULL }; - -const device_t acpi_via_596b_device = -{ - "VIA VT82C596 ACPI", - "acpi_via_596b", - DEVICE_PCI, - VEN_VIA_596B, - acpi_init, - acpi_close, - acpi_reset, - { NULL }, - acpi_speed_changed, - NULL, - NULL -}; - - -const device_t acpi_smc_device = -{ - "SMC FDC73C931APM ACPI", - "acpi_smc", - DEVICE_PCI, - VEN_SMC, - acpi_init, - acpi_close, - acpi_reset, - { NULL }, - acpi_speed_changed, - NULL, - NULL +const device_t acpi_smc_device = { + .name = "SMC FDC73C931APM ACPI", + .internal_name = "acpi_smc", + .flags = DEVICE_PCI, + .local = VEN_SMC, + .init = acpi_init, + .close = acpi_close, + .reset = acpi_reset, + { .available = NULL }, + .speed_changed = acpi_speed_changed, + .force_redraw = NULL, + .config = NULL }; diff --git a/src/apm.c b/src/apm.c index 35c9a2a3c..d7ce262a3 100644 --- a/src/apm.c +++ b/src/apm.c @@ -1,18 +1,18 @@ /* - * 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. + * 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. + * This file is part of the 86Box distribution. * - * Advanced Power Management emulation. + * Advanced Power Management emulation. * * * - * Authors: Miran Grca, + * Authors: Miran Grca, * - * Copyright 2019 Miran Grca. + * Copyright 2019 Miran Grca. */ #include #include @@ -27,145 +27,131 @@ #include <86box/io.h> #include <86box/apm.h> - #ifdef ENABLE_APM_LOG int apm_do_log = ENABLE_APM_LOG; - static void apm_log(const char *fmt, ...) { va_list ap; if (apm_do_log) { - va_start(ap, fmt); - pclog_ex(fmt, ap); - va_end(ap); + va_start(ap, fmt); + pclog_ex(fmt, ap); + va_end(ap); } } #else -#define apm_log(fmt, ...) +# define apm_log(fmt, ...) #endif - void apm_set_do_smi(apm_t *dev, uint8_t do_smi) { dev->do_smi = do_smi; } - static void -apm_out(uint16_t port, uint8_t val, void *p) +apm_out(uint16_t port, uint8_t val, void *priv) { - apm_t *dev = (apm_t *) p; + apm_t *dev = (apm_t *) priv; apm_log("[%04X:%08X] APM write: %04X = %02X (BX = %04X, CX = %04X)\n", CS, cpu_state.pc, port, val, BX, CX); port &= 0x0001; if (port == 0x0000) { - dev->cmd = val; - if (dev->do_smi) - smi_line = 1; + dev->cmd = val; + if (dev->do_smi) + smi_raise(); } else - dev->stat = val; + dev->stat = val; } - static uint8_t -apm_in(uint16_t port, void *p) +apm_in(uint16_t port, void *priv) { - apm_t *dev = (apm_t *) p; - uint8_t ret = 0xff; + const apm_t *dev = (apm_t *) priv; + uint8_t ret = 0xff; port &= 0x0001; if (port == 0x0000) - ret = dev->cmd; + ret = dev->cmd; else - ret = dev->stat; + ret = dev->stat; apm_log("[%04X:%08X] APM read: %04X = %02X\n", CS, cpu_state.pc, port, ret); return ret; } - static void -apm_reset(void *p) +apm_reset(void *priv) { - apm_t *dev = (apm_t *)p; + apm_t *dev = (apm_t *) priv; dev->cmd = dev->stat = 0x00; } - static void -apm_close(void *p) +apm_close(void *priv) { - apm_t *dev = (apm_t *)p; + apm_t *dev = (apm_t *) priv; free(dev); } - -static void -*apm_init(const device_t *info) +static void * +apm_init(const device_t *info) { apm_t *dev = (apm_t *) malloc(sizeof(apm_t)); memset(dev, 0, sizeof(apm_t)); if (info->local == 0) - io_sethandler(0x00b2, 0x0002, apm_in, NULL, NULL, apm_out, NULL, NULL, dev); + io_sethandler(0x00b2, 0x0002, apm_in, NULL, NULL, apm_out, NULL, NULL, dev); return dev; } - -const device_t apm_device = -{ - "Advanced Power Management", - "apm", - 0, - 0, - apm_init, - apm_close, - NULL, - { NULL }, - NULL, - NULL, - NULL +const device_t apm_device = { + .name = "Advanced Power Management", + .internal_name = "apm", + .flags = 0, + .local = 0, + .init = apm_init, + .close = apm_close, + .reset = NULL, + { .available = NULL }, + .speed_changed = NULL, + .force_redraw = NULL, + .config = NULL }; - -const device_t apm_pci_device = -{ - "Advanced Power Management (PCI)", - "apm_pci", - DEVICE_PCI, - 0, - apm_init, - apm_close, - apm_reset, - { NULL }, - NULL, - NULL, - NULL +const device_t apm_pci_device = { + .name = "Advanced Power Management (PCI)", + .internal_name = "apm_pci", + .flags = DEVICE_PCI, + .local = 0, + .init = apm_init, + .close = apm_close, + .reset = apm_reset, + { .available = NULL }, + .speed_changed = NULL, + .force_redraw = NULL, + .config = NULL }; - -const device_t apm_pci_acpi_device = -{ - "Advanced Power Management (PCI)", - "apm_pci_acpi", - DEVICE_PCI, - 1, - apm_init, - apm_close, - apm_reset, - { NULL }, - NULL, - NULL, - NULL +const device_t apm_pci_acpi_device = { + .name = "Advanced Power Management (PCI)", + .internal_name = "apm_pci_acpi", + .flags = DEVICE_PCI, + .local = 1, + .init = apm_init, + .close = apm_close, + .reset = apm_reset, + { .available = NULL }, + .speed_changed = NULL, + .force_redraw = NULL, + .config = NULL }; diff --git a/src/arch_detect.c b/src/arch_detect.c index 03d3b61e7..42a7d29bf 100644 --- a/src/arch_detect.c +++ b/src/arch_detect.c @@ -1,27 +1,27 @@ /* - * 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. + * 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. + * This file is part of the 86Box distribution. * - * Configure-time architecture detection for the CMake build. + * Configure-time architecture detection for the CMake build. * * * - * Authors: David HrdliÄka, + * Authors: David HrdliÄka, * - * Copyright 2020-2021 David HrdliÄka. + * Copyright 2020-2021 David HrdliÄka. */ #if defined(__arm__) || defined(__TARGET_ARCH_ARM) - #error ARCH arm +# error ARCH arm #elif defined(__aarch64__) || defined(_M_ARM64) - #error ARCH arm64 +# error ARCH arm64 #elif defined(__i386) || defined(__i386__) || defined(_M_IX86) - #error ARCH i386 +# error ARCH i386 #elif defined(__x86_64) || defined(__x86_64__) || defined(__amd64) || defined(_M_X64) - #error ARCH x86_64 +# error ARCH x86_64 #endif #error ARCH unknown diff --git a/src/cdrom/CMakeLists.txt b/src/cdrom/CMakeLists.txt index eaa50bf2c..201cee7f6 100644 --- a/src/cdrom/CMakeLists.txt +++ b/src/cdrom/CMakeLists.txt @@ -1,16 +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. +# 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. +# This file is part of the 86Box distribution. # -# CMake build script. +# CMake build script. # -# Authors: David HrdliÄka, +# Authors: David HrdliÄka, # -# Copyright 2020,2021 David HrdliÄka. +# Copyright 2020-2021 David HrdliÄka. # -add_library(cdrom OBJECT cdrom.c cdrom_image_backend.c cdrom_image.c) \ No newline at end of file +add_library(cdrom OBJECT cdrom.c cdrom_image_backend.c cdrom_image_viso.c cdrom_image.c cdrom_mitsumi.c) diff --git a/src/cdrom/cdrom.c b/src/cdrom/cdrom.c index c400fa953..22cefb991 100644 --- a/src/cdrom/cdrom.c +++ b/src/cdrom/cdrom.c @@ -1,18 +1,18 @@ /* - * 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. + * 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. + * This file is part of the 86Box distribution. * - * Generic CD-ROM drive core. + * Generic CD-ROM drive core. * * * - * Author: Miran Grca, + * Authors: Miran Grca, * - * Copyright 2018-2021 Miran Grca. + * Copyright 2018-2021 Miran Grca. */ #include #include @@ -23,83 +23,81 @@ #include #define HAVE_STDARG_H #include <86box/86box.h> +#include <86box/device.h> #include <86box/config.h> #include <86box/cdrom.h> #include <86box/cdrom_image.h> +#include <86box/cdrom_interface.h> +#include <86box/cdrom_mitsumi.h> #include <86box/plat.h> +#include <86box/scsi.h> #include <86box/scsi_device.h> #include <86box/sound.h> - /* The addresses sent from the guest are absolute, ie. a LBA of 0 corresponds to a MSF of 00:00:00. Otherwise, the counter displayed by the guest is wrong: there is a seeming 2 seconds in which audio plays but counter does not move, while a data track before audio jumps to 2 seconds before the actual start of the audio while audio still plays. With an absolute conversion, the counter is fine. */ #undef MSFtoLBA -#define MSFtoLBA(m,s,f) ((((m*60)+s)*75)+f) +#define MSFtoLBA(m, s, f) ((((m * 60) + s) * 75) + f) -#define RAW_SECTOR_SIZE 2352 -#define COOKED_SECTOR_SIZE 2048 +#define RAW_SECTOR_SIZE 2352 +#define COOKED_SECTOR_SIZE 2048 -#define MIN_SEEK 2000 -#define MAX_SEEK 333333 +#define MIN_SEEK 2000 +#define MAX_SEEK 333333 -#define CD_BCD(x) (((x) % 10) | (((x) / 10) << 4)) -#define CD_DCB(x) ((((x) & 0xf0) >> 4) * 10 + ((x) & 0x0f)) - -#pragma pack(push,1) +#pragma pack(push, 1) typedef struct { uint8_t user_data[2048], - ecc[288]; + ecc[288]; } m1_data_t; typedef struct { uint8_t sub_header[8], - user_data[2328]; + user_data[2328]; } m2_data_t; typedef union { m1_data_t m1_data; m2_data_t m2_data; - uint8_t raw_data[2336]; + uint8_t raw_data[2336]; } sector_data_t; typedef struct { - uint8_t sync[12]; - uint8_t header[4]; + uint8_t sync[12]; + uint8_t header[4]; sector_data_t data; } sector_raw_data_t; typedef union { sector_raw_data_t sector_data; - uint8_t raw_data[2352]; + uint8_t raw_data[2352]; } sector_t; typedef struct { sector_t sector; - uint8_t c2[296]; - uint8_t subchannel_raw[96]; - uint8_t subchannel_q[16]; - uint8_t subchannel_rw[96]; + uint8_t c2[296]; + uint8_t subchannel_raw[96]; + uint8_t subchannel_q[16]; + uint8_t subchannel_rw[96]; } cdrom_sector_t; typedef union { cdrom_sector_t cdrom_sector; - uint8_t buffer[2856]; + uint8_t buffer[2856]; } sector_buffer_t; #pragma pack(pop) +static int cdrom_sector_size; +static uint8_t raw_buffer[2856]; /* Needs to be the same size as sector_buffer_t in the structs. */ +static uint8_t extra_buffer[296]; -static int cdrom_sector_size; -static uint8_t raw_buffer[2856]; /* Needs to be the same size as sector_buffer_t in the structs. */ -static uint8_t extra_buffer[296]; - - -cdrom_t cdrom[CDROM_NUM]; +cdrom_t cdrom[CDROM_NUM]; +int cdrom_interface_current; #ifdef ENABLE_CDROM_LOG -int cdrom_do_log = ENABLE_CDROM_LOG; - +int cdrom_do_log = ENABLE_CDROM_LOG; void cdrom_log(const char *fmt, ...) @@ -107,24 +105,162 @@ cdrom_log(const char *fmt, ...) va_list ap; if (cdrom_do_log) { - va_start(ap, fmt); - pclog_ex(fmt, ap); - va_end(ap); + va_start(ap, fmt); + pclog_ex(fmt, ap); + va_end(ap); } } #else -#define cdrom_log(fmt, ...) +# define cdrom_log(fmt, ...) #endif +static const device_t cdrom_interface_none_device = { + .name = "None", + .internal_name = "none", + .flags = 0, + .local = 0, + .init = NULL, + .close = NULL, + .reset = NULL, + { .available = NULL }, + .speed_changed = NULL, + .force_redraw = NULL, + .config = NULL +}; + +static const struct { + const device_t *device; +} controllers[] = { + // clang-format off + { &cdrom_interface_none_device }, + { NULL } + // clang-format on +}; + +/* Reset the CD-ROM Interface, whichever one that is. */ +void +cdrom_interface_reset(void) +{ + cdrom_log("CD-ROM Interface: reset(current=%d)\n", + cdrom_interface_current); + + /* If we have a valid controller, add its device. */ + if ((cdrom_interface_current > 0) && controllers[cdrom_interface_current].device) + device_add(controllers[cdrom_interface_current].device); +} + +const char * +cdrom_interface_get_internal_name(int cdinterface) +{ + return device_get_internal_name(controllers[cdinterface].device); +} + +int +cdrom_interface_get_from_internal_name(char *s) +{ + int c = 0; + + while (controllers[c].device != NULL) { + if (!strcmp(controllers[c].device->internal_name, s)) + return c; + c++; + } + + return 0; +} + +const device_t * +cdrom_interface_get_device(int cdinterface) +{ + return (controllers[cdinterface].device); +} + +int +cdrom_interface_has_config(int cdinterface) +{ + const device_t *dev = cdrom_interface_get_device(cdinterface); + + if (dev == NULL) + return 0; + + if (!device_has_config(dev)) + return 0; + + return 1; +} + +int +cdrom_interface_get_flags(int cdinterface) +{ + return (controllers[cdinterface].device->flags); +} + +int +cdrom_interface_available(int cdinterface) +{ + return (device_available(controllers[cdinterface].device)); +} + +char * +cdrom_getname(int type) +{ + return (char *) cdrom_drive_types[type].name; +} + +char * +cdrom_get_internal_name(int type) +{ + return (char *) cdrom_drive_types[type].internal_name; +} + +int +cdrom_get_from_internal_name(char *s) +{ + int c = 0; + + while (strlen(cdrom_drive_types[c].internal_name)) { + if (!strcmp((char *) cdrom_drive_types[c].internal_name, s)) + return c; + c++; + } + + return 0; +} + +void +cdrom_set_type(int model, int type) +{ + cdrom[model].type = type; +} + +int +cdrom_get_type(int model) +{ + return cdrom[model].type; +} + +static __inline int +bin2bcd(int x) +{ + return (x % 10) | ((x / 10) << 4); +} + +static __inline int +bcd2bin(int x) +{ + return (x >> 4) * 10 + (x & 0x0f); +} int cdrom_lba_to_msf_accurate(int lba) { int pos; - int m, s, f; + int m; + int s; + int f; pos = lba + 150; - f = pos % 75; + f = pos % 75; pos -= f; pos /= 75; s = pos % 60; @@ -135,157 +271,207 @@ cdrom_lba_to_msf_accurate(int lba) return ((m << 16) | (s << 8) | f); } - static double cdrom_get_short_seek(cdrom_t *dev) { - switch(dev->cur_speed) { - case 0: - fatal("CD-ROM %i: 0x speed\n", dev->id); - return 0.0; - case 1: - return 240.0; - case 2: - return 160.0; - case 3: - return 150.0; - case 4: case 5: case 6: case 7: case 8: - case 9: case 10: case 11: - return 112.0; - case 12: case 13: case 14: case 15: - return 75.0; - case 16: case 17: case 18: case 19: - return 58.0; - case 20: case 21: case 22: case 23: - case 40: case 41: case 42: case 43: - case 44: case 45: case 46: case 47: - case 48: - return 50.0; - default: - /* 24-32, 52+ */ - return 45.0; + switch (dev->cur_speed) { + case 0: + fatal("CD-ROM %i: 0x speed\n", dev->id); + return 0.0; + case 1: + return 240.0; + case 2: + return 160.0; + case 3: + return 150.0; + case 4: + case 5: + case 6: + case 7: + case 8: + case 9: + case 10: + case 11: + return 112.0; + case 12: + case 13: + case 14: + case 15: + return 75.0; + case 16: + case 17: + case 18: + case 19: + return 58.0; + case 20: + case 21: + case 22: + case 23: + case 40: + case 41: + case 42: + case 43: + case 44: + case 45: + case 46: + case 47: + case 48: + return 50.0; + default: + /* 24-32, 52+ */ + return 45.0; } } - static double cdrom_get_long_seek(cdrom_t *dev) { - switch(dev->cur_speed) { - case 0: - fatal("CD-ROM %i: 0x speed\n", dev->id); - return 0.0; - case 1: - return 1446.0; - case 2: - return 1000.0; - case 3: - return 900.0; - case 4: case 5: case 6: case 7: case 8: - case 9: case 10: case 11: - return 675.0; - case 12: case 13: case 14: case 15: - return 400.0; - case 16: case 17: case 18: case 19: - return 350.0; - case 20: case 21: case 22: case 23: - case 40: case 41: case 42: case 43: - case 44: case 45: case 46: case 47: - case 48: - return 300.0; - default: - /* 24-32, 52+ */ - return 270.0; + switch (dev->cur_speed) { + case 0: + fatal("CD-ROM %i: 0x speed\n", dev->id); + return 0.0; + case 1: + return 1446.0; + case 2: + return 1000.0; + case 3: + return 900.0; + case 4: + case 5: + case 6: + case 7: + case 8: + case 9: + case 10: + case 11: + return 675.0; + case 12: + case 13: + case 14: + case 15: + return 400.0; + case 16: + case 17: + case 18: + case 19: + return 350.0; + case 20: + case 21: + case 22: + case 23: + case 40: + case 41: + case 42: + case 43: + case 44: + case 45: + case 46: + case 47: + case 48: + return 300.0; + default: + /* 24-32, 52+ */ + return 270.0; } } - double cdrom_seek_time(cdrom_t *dev) { uint32_t diff = dev->seek_diff; - double sd = (double) (MAX_SEEK - MIN_SEEK); + double sd = (double) (MAX_SEEK - MIN_SEEK); if (diff < MIN_SEEK) - return 0.0; + return 0.0; if (diff > MAX_SEEK) - diff = MAX_SEEK; + diff = MAX_SEEK; diff -= MIN_SEEK; return cdrom_get_short_seek(dev) + ((cdrom_get_long_seek(dev) * ((double) diff)) / sd); } - void cdrom_stop(cdrom_t *dev) { if (dev->cd_status > CD_STATUS_DATA_ONLY) - dev->cd_status = CD_STATUS_STOPPED; + dev->cd_status = CD_STATUS_STOPPED; } - void -cdrom_seek(cdrom_t *dev, uint32_t pos) +cdrom_seek(cdrom_t *dev, uint32_t pos, uint8_t vendor_type) { + int m; + int s; + int f; + if (!dev) - return; + return; - cdrom_log("CD-ROM %i: Seek to LBA %08X\n", dev->id, pos); + cdrom_log("CD-ROM %i: Seek to LBA %08X, vendor type = %02x.\n", dev->id, pos, vendor_type); - dev->seek_pos = pos; + switch (vendor_type) { + case 0x40: + m = bcd2bin((pos >> 24) & 0xff); + s = bcd2bin((pos >> 16) & 0xff); + f = bcd2bin((pos >> 8) & 0xff); + pos = MSFtoLBA(m, s, f) - 150; + break; + case 0x80: + pos = bcd2bin((pos >> 24) & 0xff); + break; + default: + break; + } + + dev->seek_pos = pos; cdrom_stop(dev); } - int cdrom_is_pre(cdrom_t *dev, uint32_t lba) { if (dev->ops && dev->ops->is_track_pre) - return dev->ops->is_track_pre(dev, lba); + return dev->ops->is_track_pre(dev, lba); return 0; } - int cdrom_audio_callback(cdrom_t *dev, int16_t *output, int len) { int ret = 1; if (!dev->sound_on || (dev->cd_status != CD_STATUS_PLAYING)) { - cdrom_log("CD-ROM %i: Audio callback while not playing\n", dev->id); - if (dev->cd_status == CD_STATUS_PLAYING) - dev->seek_pos += (len >> 11); - memset(output, 0, len * 2); - return 0; + cdrom_log("CD-ROM %i: Audio callback while not playing\n", dev->id); + if (dev->cd_status == CD_STATUS_PLAYING) + dev->seek_pos += (len >> 11); + memset(output, 0, len * 2); + return 0; } while (dev->cd_buflen < len) { - if (dev->seek_pos < dev->cd_end) { - if (dev->ops->read_sector(dev, CD_READ_AUDIO, - (uint8_t *) &(dev->cd_buffer[dev->cd_buflen]), - dev->seek_pos)) { - cdrom_log("CD-ROM %i: Read LBA %08X successful\n", dev->id, dev->seek_pos); - dev->seek_pos++; - dev->cd_buflen += (RAW_SECTOR_SIZE / 2); - ret = 1; - } else { - cdrom_log("CD-ROM %i: Read LBA %08X failed\n", dev->id, dev->seek_pos); - memset(&(dev->cd_buffer[dev->cd_buflen]), - 0x00, (BUF_SIZE - dev->cd_buflen) * 2); - dev->cd_status = CD_STATUS_STOPPED; - dev->cd_buflen = len; - ret = 0; - } - } else { - cdrom_log("CD-ROM %i: Playing completed\n", dev->id); - memset(&dev->cd_buffer[dev->cd_buflen], - 0x00, (BUF_SIZE - dev->cd_buflen) * 2); - dev->cd_status = CD_STATUS_PLAYING_COMPLETED; - dev->cd_buflen = len; - ret = 0; - } + if (dev->seek_pos < dev->cd_end) { + if (dev->ops->read_sector(dev, CD_READ_AUDIO, (uint8_t *) &(dev->cd_buffer[dev->cd_buflen]), + dev->seek_pos)) { + cdrom_log("CD-ROM %i: Read LBA %08X successful\n", dev->id, dev->seek_pos); + dev->seek_pos++; + dev->cd_buflen += (RAW_SECTOR_SIZE / 2); + ret = 1; + } else { + cdrom_log("CD-ROM %i: Read LBA %08X failed\n", dev->id, dev->seek_pos); + memset(&(dev->cd_buffer[dev->cd_buflen]), 0x00, (BUF_SIZE - dev->cd_buflen) * 2); + dev->cd_status = CD_STATUS_STOPPED; + dev->cd_buflen = len; + ret = 0; + } + } else { + cdrom_log("CD-ROM %i: Playing completed\n", dev->id); + memset(&dev->cd_buffer[dev->cd_buflen], 0x00, (BUF_SIZE - dev->cd_buflen) * 2); + dev->cd_status = CD_STATUS_PLAYING_COMPLETED; + dev->cd_buflen = len; + ret = 0; + } } memcpy(output, dev->cd_buffer, len * 2); @@ -296,132 +482,282 @@ cdrom_audio_callback(cdrom_t *dev, int16_t *output, int len) return ret; } +static void +msf_from_bcd(int *m, int *s, int *f) +{ + *m = bcd2bin(*m); + *s = bcd2bin(*s); + *f = bcd2bin(*f); +} + +static void +msf_to_bcd(int *m, int *s, int *f) +{ + *m = bin2bcd(*m); + *s = bin2bcd(*s); + *f = bin2bcd(*f); +} uint8_t cdrom_audio_play(cdrom_t *dev, uint32_t pos, uint32_t len, int ismsf) { track_info_t ti; - int m = 0, s = 0, f = 0; + int m = 0; + int s = 0; + int f = 0; if (dev->cd_status == CD_STATUS_DATA_ONLY) - return 0; + return 0; cdrom_log("CD-ROM %i: Play audio - %08X %08X %i\n", dev->id, pos, len, ismsf); if (ismsf & 0x100) { - /* Track-relative audio play. */ - dev->ops->get_track_info(dev, ismsf & 0xff, 0, &ti); - pos += MSFtoLBA(ti.m, ti.s, ti.f) - 150; - } else if (ismsf == 2) { - dev->ops->get_track_info(dev, pos, 0, &ti); - pos = MSFtoLBA(ti.m, ti.s, ti.f) - 150; - /* We have to end at the *end* of the specified track, - not at the beginning. */ - dev->ops->get_track_info(dev, len, 1, &ti); - len = MSFtoLBA(ti.m, ti.s, ti.f) - 150; + /* Track-relative audio play. */ + dev->ops->get_track_info(dev, ismsf & 0xff, 0, &ti); + pos += MSFtoLBA(ti.m, ti.s, ti.f) - 150; + } else if ((ismsf == 2) || (ismsf == 3)) { + dev->ops->get_track_info(dev, pos, 0, &ti); + pos = MSFtoLBA(ti.m, ti.s, ti.f) - 150; + if (ismsf == 2) { + /* We have to end at the *end* of the specified track, + not at the beginning. */ + dev->ops->get_track_info(dev, len, 1, &ti); + len = MSFtoLBA(ti.m, ti.s, ti.f) - 150; + } } else if (ismsf == 1) { - m = (pos >> 16) & 0xff; - s = (pos >> 8) & 0xff; - f = pos & 0xff; + m = (pos >> 16) & 0xff; + s = (pos >> 8) & 0xff; + f = pos & 0xff; - if (pos == 0xffffff) { - cdrom_log("CD-ROM %i: Playing from current position (MSF)\n", dev->id); - pos = dev->seek_pos; - } else - pos = MSFtoLBA(m, s, f) - 150; + /* NEC CDR-260 speaks BCD. */ + if ((dev->type == CDROM_TYPE_NEC_260_100) || (dev->type == CDROM_TYPE_NEC_260_101)) /*NEC*/ + msf_from_bcd(&m, &s, &f); - m = (len >> 16) & 0xff; - s = (len >> 8) & 0xff; - f = len & 0xff; - len = MSFtoLBA(m, s, f) - 150; + if (pos == 0xffffff) { + cdrom_log("CD-ROM %i: Playing from current position (MSF)\n", dev->id); + pos = dev->seek_pos; + } else + pos = MSFtoLBA(m, s, f) - 150; - cdrom_log("CD-ROM %i: MSF - pos = %08X len = %08X\n", dev->id, pos, len); + m = (len >> 16) & 0xff; + s = (len >> 8) & 0xff; + f = len & 0xff; + + /* NEC CDR-260 speaks BCD. */ + if ((dev->type == CDROM_TYPE_NEC_260_100) || (dev->type == CDROM_TYPE_NEC_260_101)) /*NEC*/ + msf_from_bcd(&m, &s, &f); + + len = MSFtoLBA(m, s, f) - 150; + + cdrom_log("CD-ROM %i: MSF - pos = %08X len = %08X\n", dev->id, pos, len); } else if (ismsf == 0) { - if (pos == 0xffffffff) { - cdrom_log("CD-ROM %i: Playing from current position\n", dev->id); - pos = dev->seek_pos; - } - len += pos; + if (pos == 0xffffffff) { + cdrom_log("CD-ROM %i: Playing from current position\n", dev->id); + pos = dev->seek_pos; + } + len += pos; } /* Do this at this point, since it's at this point that we know the actual LBA position to start playing from. */ if (!(dev->ops->track_type(dev, pos) & CD_TRACK_AUDIO)) { - cdrom_log("CD-ROM %i: LBA %08X not on an audio track\n", dev->id, pos); - cdrom_stop(dev); - return 0; + cdrom_log("CD-ROM %i: LBA %08X not on an audio track\n", dev->id, pos); + cdrom_stop(dev); + return 0; } - dev->seek_pos = pos; - dev->cd_end = len; + dev->seek_pos = pos; + dev->cd_end = len; dev->cd_status = CD_STATUS_PLAYING; dev->cd_buflen = 0; - return 1; } uint8_t cdrom_audio_track_search(cdrom_t *dev, uint32_t pos, int type, uint8_t playbit) { - int m = 0, s = 0, f = 0; - + int m = 0; + int s = 0; + int f = 0; + if (dev->cd_status == CD_STATUS_DATA_ONLY) - return 0; - + return 0; + + cdrom_log("Audio Track Search: MSF = %06x, type = %02x, playbit = %02x\n", pos, type, playbit); switch (type) { - case 0x40: - cdrom_log("Audio Track Search: MSF = %06x, type = %02x\n", pos, type); - m = CD_DCB((pos >> 24) & 0xff); - s = CD_DCB((pos >> 16) & 0xff); - f = CD_DCB((pos >> 8) & 0xff); - pos = MSFtoLBA(m, s, f) - 150; - break; - } - - /* Do this at this point, since it's at this point that we know the - actual LBA position to start playing from. */ - if (!(dev->ops->track_type(dev, pos) & CD_TRACK_AUDIO)) { - cdrom_log("CD-ROM %i: LBA %08X not on an audio track\n", dev->id, pos); - cdrom_stop(dev); - return 0; + case 0x00: + if (pos == 0xffffffff) { + cdrom_log("CD-ROM %i: (type 0) Search from current position\n", dev->id); + pos = dev->seek_pos; + } + dev->seek_pos = pos; + break; + case 0x40: + m = bcd2bin((pos >> 24) & 0xff); + s = bcd2bin((pos >> 16) & 0xff); + f = bcd2bin((pos >> 8) & 0xff); + if (pos == 0xffffffff) { + cdrom_log("CD-ROM %i: (type 1) Search from current position\n", dev->id); + pos = dev->seek_pos; + } else + pos = MSFtoLBA(m, s, f) - 150; + + dev->seek_pos = pos; + break; + case 0x80: + if (pos == 0xffffffff) { + cdrom_log("CD-ROM %i: (type 2) Search from current position\n", dev->id); + pos = dev->seek_pos; + } + dev->seek_pos = (pos >> 24) & 0xff; + break; + default: + break; } - dev->seek_pos = pos; - dev->noplay = !playbit; + /* Unlike standard commands, if there's a data track on an Audio CD (mixed mode) + the playback continues with the audio muted (Toshiba CD-ROM SCSI-2 manual reference). */ + dev->cd_buflen = 0; dev->cd_status = playbit ? CD_STATUS_PLAYING : CD_STATUS_PAUSED; return 1; } -uint8_t -cdrom_toshiba_audio_play(cdrom_t *dev, uint32_t pos, int type) +uint8_t +cdrom_audio_track_search_pioneer(cdrom_t *dev, uint32_t pos, uint8_t playbit) { - int m = 0, s = 0, f = 0; + int m = 0; + int s = 0; + int f = 0; if (dev->cd_status == CD_STATUS_DATA_ONLY) - return 0; + return 0; - if (dev->cd_status == CD_STATUS_STOPPED || dev->cd_status == CD_STATUS_PAUSED) - dev->cd_status = CD_STATUS_PLAYING; + f = bcd2bin((pos >> 24) & 0xff); + s = bcd2bin((pos >> 16) & 0xff); + m = bcd2bin((pos >> 8) & 0xff); + if (pos == 0xffffffff) { + pos = dev->seek_pos; + } else + pos = MSFtoLBA(m, s, f) - 150; + + dev->seek_pos = pos; + + dev->cd_buflen = 0; + dev->cd_status = playbit ? CD_STATUS_PLAYING : CD_STATUS_PAUSED; + return 1; +} + +uint8_t +cdrom_audio_play_pioneer(cdrom_t *dev, uint32_t pos) +{ + int m = 0; + int s = 0; + int f = 0; + + if (dev->cd_status == CD_STATUS_DATA_ONLY) + return 0; + + f = bcd2bin((pos >> 24) & 0xff); + s = bcd2bin((pos >> 16) & 0xff); + m = bcd2bin((pos >> 8) & 0xff); + pos = MSFtoLBA(m, s, f) - 150; + dev->cd_end = pos; + + dev->cd_buflen = 0; + dev->cd_status = CD_STATUS_PLAYING; + return 1; +} + +uint8_t +cdrom_audio_play_toshiba(cdrom_t *dev, uint32_t pos, int type) +{ + int m = 0; + int s = 0; + int f = 0; + + if (dev->cd_status == CD_STATUS_DATA_ONLY) + return 0; /*Preliminary support, revert if too incomplete*/ switch (type) { - case 0x40: - cdrom_log("Toshiba Play Audio: MSF = %06x, type = %02x\n", pos, type); - m = CD_DCB((pos >> 24) & 0xff); - s = CD_DCB((pos >> 16) & 0xff); - f = CD_DCB((pos >> 8) & 0xff); - pos = MSFtoLBA(m, s, f) - 150; - break; + case 0x00: + dev->cd_end = pos; + break; + case 0x40: + m = bcd2bin((pos >> 24) & 0xff); + s = bcd2bin((pos >> 16) & 0xff); + f = bcd2bin((pos >> 8) & 0xff); + pos = MSFtoLBA(m, s, f) - 150; + dev->cd_end = pos; + break; + case 0x80: + dev->cd_end = (pos >> 24) & 0xff; + break; + case 0xc0: + if (pos == 0xffffffff) { + cdrom_log("CD-ROM %i: Playing from current position\n", dev->id); + pos = dev->cd_end; + } + dev->cd_end = pos; + break; + default: + break; } - + + cdrom_log("Toshiba/NEC Play Audio: MSF = %06x, type = %02x, cdstatus = %02x\n", pos, type, dev->cd_status); + + /* Unlike standard commands, if there's a data track on an Audio CD (mixed mode) + the playback continues with the audio muted (Toshiba CD-ROM SCSI-2 manual reference). */ + dev->cd_buflen = 0; + dev->cd_status = CD_STATUS_PLAYING; + return 1; +} + +uint8_t +cdrom_audio_scan(cdrom_t *dev, uint32_t pos, int type) +{ + int m = 0; + int s = 0; + int f = 0; + + if (dev->cd_status == CD_STATUS_DATA_ONLY) + return 0; + + cdrom_log("Audio Scan: MSF = %06x, type = %02x\n", pos, type); + switch (type) { + case 0x00: + if (pos == 0xffffffff) { + cdrom_log("CD-ROM %i: (type 0) Search from current position\n", dev->id); + pos = dev->seek_pos; + } + dev->seek_pos = pos; + break; + case 0x40: + m = bcd2bin((pos >> 24) & 0xff); + s = bcd2bin((pos >> 16) & 0xff); + f = bcd2bin((pos >> 8) & 0xff); + if (pos == 0xffffffff) { + cdrom_log("CD-ROM %i: (type 1) Search from current position\n", dev->id); + pos = dev->seek_pos; + } else + pos = MSFtoLBA(m, s, f) - 150; + + dev->seek_pos = pos; + break; + case 0x80: + dev->seek_pos = (pos >> 24) & 0xff; + break; + default: + break; + } + /* Do this at this point, since it's at this point that we know the actual LBA position to start playing from. */ if (!(dev->ops->track_type(dev, pos) & CD_TRACK_AUDIO)) { - cdrom_log("CD-ROM %i: LBA %08X not on an audio track\n", dev->id, pos); - cdrom_stop(dev); - return 0; - } - - dev->cd_end = pos; + cdrom_log("CD-ROM %i: LBA %08X not on an audio track\n", dev->id, pos); + cdrom_stop(dev); + return 0; + } + dev->cd_buflen = 0; return 1; } @@ -430,65 +766,212 @@ void cdrom_audio_pause_resume(cdrom_t *dev, uint8_t resume) { if ((dev->cd_status == CD_STATUS_PLAYING) || (dev->cd_status == CD_STATUS_PAUSED)) - dev->cd_status = (dev->cd_status & 0xfe) | (resume & 0x01); + dev->cd_status = (dev->cd_status & 0xfe) | (resume & 0x01); } - uint8_t cdrom_get_current_subchannel(cdrom_t *dev, uint8_t *b, int msf) { - uint8_t ret; + uint8_t ret; subchannel_t subc; - int pos = 1; + int pos = 1; + int m; + int s; + int f; + uint32_t dat; dev->ops->get_subchannel(dev, dev->seek_pos, &subc); - cdrom_log("CD-ROM %i: Returned subchannel at %02i:%02i.%02i\n", subc.abs_m, subc.abs_s, subc.abs_f); if (dev->cd_status == CD_STATUS_DATA_ONLY) - ret = 0x15; + ret = 0x15; else { - if (dev->cd_status == CD_STATUS_PLAYING) - ret = 0x11; - else if (dev->cd_status == CD_STATUS_PAUSED) - ret = 0x12; - else - ret = 0x13; + if (dev->cd_status == CD_STATUS_PLAYING) + ret = 0x11; + else if (dev->cd_status == CD_STATUS_PAUSED) + ret = 0x12; + else + ret = 0x13; } - if (b[pos] > 1) - return ret; + cdrom_log("CD-ROM %i: Returned subchannel absolute at %02i:%02i.%02i, relative at %02i:%02i.%02i, ret = %02x, seek pos = %08x, cd_end = %08x.\n", dev->id, subc.abs_m, subc.abs_s, subc.abs_f, subc.rel_m, subc.rel_s, subc.rel_f, ret, dev->seek_pos, dev->cd_end); + + if (b[pos] > 1) { + cdrom_log("B[%i] = %02x, ret = %02x.\n", pos, b[pos], ret); + return ret; + } b[pos++] = subc.attr; b[pos++] = subc.track; b[pos++] = subc.index; if (msf) { - b[pos] = 0; - b[pos + 1] = subc.abs_m; - b[pos + 2] = subc.abs_s; - b[pos + 3] = subc.abs_f; - pos += 4; - b[pos] = 0; - b[pos + 1] = subc.rel_m; - b[pos + 2] = subc.rel_s; - b[pos + 3] = subc.rel_f; - pos += 4; + b[pos] = 0; + + /* NEC CDR-260 speaks BCD. */ + if ((dev->type == CDROM_TYPE_NEC_260_100) || (dev->type == CDROM_TYPE_NEC_260_101)) { /*NEC*/ + m = subc.abs_m; + s = subc.abs_s; + f = subc.abs_f; + msf_to_bcd(&m, &s, &f); + b[pos + 1] = m; + b[pos + 2] = s; + b[pos + 3] = f; + } else { + b[pos + 1] = subc.abs_m; + b[pos + 2] = subc.abs_s; + b[pos + 3] = subc.abs_f; + } + + pos += 4; + + b[pos] = 0; + + /* NEC CDR-260 speaks BCD. */ + if ((dev->type == CDROM_TYPE_NEC_260_100) || (dev->type == CDROM_TYPE_NEC_260_101)) { /*NEC*/ + m = subc.rel_m; + s = subc.rel_s; + f = subc.rel_f; + msf_to_bcd(&m, &s, &f); + b[pos + 1] = m; + b[pos + 2] = s; + b[pos + 3] = f; + } else { + b[pos + 1] = subc.rel_m; + b[pos + 2] = subc.rel_s; + b[pos + 3] = subc.rel_f; + } + + pos += 4; } else { - uint32_t dat = MSFtoLBA(subc.abs_m, subc.abs_s, subc.abs_f) - 150; - b[pos++] = (dat >> 24) & 0xff; - b[pos++] = (dat >> 16) & 0xff; - b[pos++] = (dat >> 8) & 0xff; - b[pos++] = dat & 0xff; - dat = MSFtoLBA(subc.rel_m, subc.rel_s, subc.rel_f); - b[pos++] = (dat >> 24) & 0xff; - b[pos++] = (dat >> 16) & 0xff; - b[pos++] = (dat >> 8) & 0xff; - b[pos++] = dat & 0xff; + dat = MSFtoLBA(subc.abs_m, subc.abs_s, subc.abs_f) - 150; + b[pos++] = (dat >> 24) & 0xff; + b[pos++] = (dat >> 16) & 0xff; + b[pos++] = (dat >> 8) & 0xff; + b[pos++] = dat & 0xff; + dat = MSFtoLBA(subc.rel_m, subc.rel_s, subc.rel_f); + b[pos++] = (dat >> 24) & 0xff; + b[pos++] = (dat >> 16) & 0xff; + b[pos++] = (dat >> 8) & 0xff; + b[pos++] = dat & 0xff; } return ret; } +void +cdrom_get_current_subchannel_sony(cdrom_t *dev, uint8_t *b, int msf) +{ + subchannel_t subc; + uint32_t dat; + + dev->ops->get_subchannel(dev, dev->seek_pos, &subc); + + cdrom_log("CD-ROM %i: Returned subchannel at %02i:%02i.%02i, seek pos = %08x, cd_end = %08x, msf = %x.\n", dev->id, subc.abs_m, subc.abs_s, subc.abs_f, dev->seek_pos, dev->cd_end, msf); + + b[0] = subc.attr; + b[1] = subc.track; + b[2] = subc.index; + + if (msf) { + b[3] = subc.rel_m; + b[4] = subc.rel_s; + b[5] = subc.rel_f; + b[6] = subc.abs_m; + b[7] = subc.abs_s; + b[8] = subc.abs_f; + } else { + dat = MSFtoLBA(subc.rel_m, subc.rel_s, subc.rel_f); + b[3] = (dat >> 16) & 0xff; + b[4] = (dat >> 8) & 0xff; + b[5] = dat & 0xff; + dat = MSFtoLBA(subc.abs_m, subc.abs_s, subc.abs_f) - 150; + b[6] = (dat >> 16) & 0xff; + b[7] = (dat >> 8) & 0xff; + b[8] = dat & 0xff; + } +} + +uint8_t +cdrom_get_audio_status_pioneer(cdrom_t *dev, uint8_t *b) +{ + uint8_t ret; + subchannel_t subc; + + dev->ops->get_subchannel(dev, dev->seek_pos, &subc); + + if (dev->cd_status == CD_STATUS_DATA_ONLY) + ret = 0x05; + else { + if (dev->cd_status == CD_STATUS_PLAYING) + ret = dev->sound_on ? 0x00 : 0x02; + else if (dev->cd_status == CD_STATUS_PAUSED) + ret = 0x01; + else + ret = 0x03; + } + + b[0] = 0; + b[1] = bin2bcd(subc.abs_m); + b[2] = bin2bcd(subc.abs_s); + b[3] = bin2bcd(subc.abs_f); + + return ret; +} + +uint8_t +cdrom_get_audio_status_sony(cdrom_t *dev, uint8_t *b, int msf) +{ + uint8_t ret; + subchannel_t subc; + uint32_t dat; + + dev->ops->get_subchannel(dev, dev->seek_pos, &subc); + + if (dev->cd_status == CD_STATUS_DATA_ONLY) + ret = 0x05; + else { + if (dev->cd_status == CD_STATUS_PLAYING) + ret = dev->sound_on ? 0x00 : 0x02; + else if (dev->cd_status == CD_STATUS_PAUSED) + ret = 0x01; + else + ret = 0x03; + } + + if (msf) { + b[0] = 0; + b[1] = subc.abs_m; + b[2] = subc.abs_s; + b[3] = subc.abs_f; + } else { + dat = MSFtoLBA(subc.abs_m, subc.abs_s, subc.abs_f) - 150; + b[0] = (dat >> 24) & 0xff; + b[1] = (dat >> 16) & 0xff; + b[2] = (dat >> 8) & 0xff; + b[3] = dat & 0xff; + } + + return ret; +} + +void +cdrom_get_current_subcodeq(cdrom_t *dev, uint8_t *b) +{ + subchannel_t subc; + + dev->ops->get_subchannel(dev, dev->seek_pos, &subc); + + b[0] = subc.attr; + b[1] = bin2bcd(subc.track); + b[2] = bin2bcd(subc.index); + b[3] = bin2bcd(subc.rel_m); + b[4] = bin2bcd(subc.rel_s); + b[5] = bin2bcd(subc.rel_f); + b[6] = bin2bcd(subc.abs_m); + b[7] = bin2bcd(subc.abs_s); + b[8] = bin2bcd(subc.abs_f); +} + uint8_t cdrom_get_current_subcodeq_playstatus(cdrom_t *dev, uint8_t *b) { @@ -496,40 +979,38 @@ cdrom_get_current_subcodeq_playstatus(cdrom_t *dev, uint8_t *b) subchannel_t subc; dev->ops->get_subchannel(dev, dev->seek_pos, &subc); - - if (dev->cd_status == CD_STATUS_PLAYING) - ret = 0x00; - else if (dev->cd_status == CD_STATUS_PAUSED) { - if (dev->noplay) - ret = 0x02; - else - ret = 0x01; - } - else - ret = 0x03; + + if ((dev->cd_status == CD_STATUS_DATA_ONLY) || + (dev->cd_status == CD_STATUS_PLAYING_COMPLETED) || + (dev->cd_status == CD_STATUS_STOPPED)) + ret = 0x03; + else + ret = (dev->cd_status == CD_STATUS_PLAYING) ? 0x00 : dev->audio_op; b[0] = subc.attr; - b[1] = CD_BCD(subc.track); - b[2] = CD_BCD(subc.index); - b[3] = CD_BCD(subc.rel_m); - b[4] = CD_BCD(subc.rel_s); - b[5] = CD_BCD(subc.rel_f); - b[6] = CD_BCD(subc.abs_m); - b[7] = CD_BCD(subc.abs_s); - b[8] = CD_BCD(subc.abs_f); - cdrom_log("CD-ROM %i: Returned subcode-q at %02i:%02i.%02i, track=%02x\n", dev->id, b[3], b[4], b[5], b[1]); - + b[1] = bin2bcd(subc.track); + b[2] = bin2bcd(subc.index); + b[3] = bin2bcd(subc.rel_m); + b[4] = bin2bcd(subc.rel_s); + b[5] = bin2bcd(subc.rel_f); + b[6] = bin2bcd(subc.abs_m); + b[7] = bin2bcd(subc.abs_s); + b[8] = bin2bcd(subc.abs_f); return ret; } - static int read_toc_normal(cdrom_t *dev, unsigned char *b, unsigned char start_track, int msf) { track_info_t ti; - int i, len = 4; - int first_track, last_track; - uint32_t temp; + int i; + int len = 4; + int m; + int s; + int f; + int first_track; + int last_track; + uint32_t temp; cdrom_log("read_toc_normal(%08X, %08X, %02X, %i)\n", dev, b, start_track, msf); @@ -546,60 +1027,72 @@ read_toc_normal(cdrom_t *dev, unsigned char *b, unsigned char start_track, int m cdrom_log(" b[3] = %02X\n", b[2]); if (start_track == 0x00) - first_track = 0; + first_track = 0; else { - first_track = -1; - for (i = 0; i <= last_track; i++) { - dev->ops->get_track_info(dev, i + 1, 0, &ti); - if (ti.number >= start_track) { - first_track = i; - break; - } - } + first_track = -1; + for (i = 0; i <= last_track; i++) { + dev->ops->get_track_info(dev, i + 1, 0, &ti); + if (ti.number >= start_track) { + first_track = i; + break; + } + } } cdrom_log(" first_track = %i, last_track = %i\n", first_track, last_track); /* No suitable starting track, return with error. */ if (first_track == -1) { -#ifdef ENABLE_CDROM_LOG - cdrom_log(" [ERROR] No suitable track found\n"); -#endif - return -1; + cdrom_log(" [ERROR] No suitable track found\n"); + return -1; } for (i = first_track; i <= last_track; i++) { - cdrom_log(" tracks(%i) = %02X, %02X, %i:%02i.%02i\n", i, ti.attr, ti.number, ti.m, ti.s, ti.f); - dev->ops->get_track_info(dev, i + 1, 0, &ti); + cdrom_log(" tracks(%i) = %02X, %02X, %i:%02i.%02i\n", i, ti.attr, ti.number, ti.m, ti.s, ti.f); + dev->ops->get_track_info(dev, i + 1, 0, &ti); - b[len++] = 0; /* reserved */ - b[len++] = ti.attr; - b[len++] = ti.number; /* track number */ - b[len++] = 0; /* reserved */ + b[len++] = 0; /* reserved */ + b[len++] = ti.attr; + b[len++] = ti.number; /* track number */ + b[len++] = 0; /* reserved */ - if (msf) { - b[len++] = 0; - b[len++] = ti.m; - b[len++] = ti.s; - b[len++] = ti.f; - } else { - temp = MSFtoLBA(ti.m, ti.s, ti.f) - 150; - b[len++] = temp >> 24; - b[len++] = temp >> 16; - b[len++] = temp >> 8; - b[len++] = temp; - } + if (msf) { + b[len++] = 0; + + /* NEC CDR-260 speaks BCD. */ + if ((dev->type == CDROM_TYPE_NEC_260_100) || (dev->type == CDROM_TYPE_NEC_260_101)) { /*NEC*/ + m = ti.m; + s = ti.s; + f = ti.f; + msf_to_bcd(&m, &s, &f); + b[len++] = m; + b[len++] = s; + b[len++] = f; + } else { + b[len++] = ti.m; + b[len++] = ti.s; + b[len++] = ti.f; + } + } else { + temp = MSFtoLBA(ti.m, ti.s, ti.f) - 150; + b[len++] = temp >> 24; + b[len++] = temp >> 16; + b[len++] = temp >> 8; + b[len++] = temp; + } } return len; } - static int read_toc_session(cdrom_t *dev, unsigned char *b, int msf) { track_info_t ti; - int len = 4; - uint32_t temp; + int len = 4; + int m; + int s; + int f; + uint32_t temp; cdrom_log("read_toc_session(%08X, %08X, %i)\n", dev, b, msf); @@ -613,31 +1106,43 @@ read_toc_session(cdrom_t *dev, unsigned char *b, int msf) b[len++] = 0; /* reserved */ b[len++] = ti.attr; b[len++] = ti.number; /* track number */ - b[len++] = 0; /* reserved */ + b[len++] = 0; /* reserved */ if (msf) { - b[len++] = 0; - b[len++] = ti.m; - b[len++] = ti.s; - b[len++] = ti.f; + b[len++] = 0; + + /* NEC CDR-260 speaks BCD. */ + if ((dev->type == CDROM_TYPE_NEC_260_100) || (dev->type == CDROM_TYPE_NEC_260_101)) { /*NEC*/ + m = ti.m; + s = ti.s; + f = ti.f; + msf_to_bcd(&m, &s, &f); + b[len++] = m; + b[len++] = s; + b[len++] = f; + } else { + b[len++] = ti.m; + b[len++] = ti.s; + b[len++] = ti.f; + } } else { - temp = MSFtoLBA(ti.m, ti.s, ti.f) - 150; - b[len++] = temp >> 24; - b[len++] = temp >> 16; - b[len++] = temp >> 8; - b[len++] = temp; + temp = MSFtoLBA(ti.m, ti.s, ti.f) - 150; + b[len++] = temp >> 24; + b[len++] = temp >> 16; + b[len++] = temp >> 8; + b[len++] = temp; } return len; } - static int read_toc_raw(cdrom_t *dev, unsigned char *b) { track_info_t ti; - int i, len = 4; - int first_track, last_track; + int len = 4; + int first_track; + int last_track; cdrom_log("read_toc_raw(%08X, %08X)\n", dev, b); @@ -646,45 +1151,111 @@ read_toc_raw(cdrom_t *dev, unsigned char *b) /* Bytes 2 and 3 = Number of first and last sessions */ b[2] = b[3] = 1; - for (i = 0; i <= last_track; i++) { - dev->ops->get_track_info(dev, i + 1, 0, &ti); + for (int i = 0; i <= last_track; i++) { + dev->ops->get_track_info(dev, i + 1, 0, &ti); - cdrom_log(" tracks(%i) = %02X, %02X, %i:%02i.%02i\n", i, ti.attr, ti.number, ti.m, ti.s, ti.f); + cdrom_log(" tracks(%i) = %02X, %02X, %i:%02i.%02i\n", i, ti.attr, ti.number, ti.m, ti.s, ti.f); - b[len++] = 1; /* Session number */ - b[len++] = ti.attr; /* Track ADR and Control */ - b[len++] = 0; /* TNO (always 0) */ - b[len++] = ti.number; /* Point (for track points - track number) */ - b[len++] = ti.m; /* M */ - b[len++] = ti.s; /* S */ - b[len++] = ti.f; /* F */ - b[len++] = 0; - b[len++] = 0; - b[len++] = 0; + b[len++] = 1; /* Session number */ + b[len++] = ti.attr; /* Track ADR and Control */ + b[len++] = 0; /* TNO (always 0) */ + b[len++] = ti.number; /* Point (for track points - track number) */ + b[len++] = ti.m; /* M */ + b[len++] = ti.s; /* S */ + b[len++] = ti.f; /* F */ + b[len++] = 0; + b[len++] = 0; + b[len++] = 0; } return len; } +static int +read_toc_sony(cdrom_t *dev, unsigned char *b, unsigned char start_track, int msf) +{ + track_info_t ti; + int i; + int len = 4; + int first_track; + int last_track; + uint32_t temp; + + cdrom_log("read_toc_sony(%08X, %08X, %02X, %i)\n", dev, b, start_track, msf); + + dev->ops->get_tracks(dev, &first_track, &last_track); + + /* Byte 2 = Number of the first track */ + dev->ops->get_track_info(dev, 1, 0, &ti); + b[2] = ti.number; + cdrom_log(" b[2] = %02X\n", b[2]); + + /* Byte 3 = Number of the last track before the lead-out track */ + dev->ops->get_track_info(dev, last_track, 0, &ti); + b[3] = ti.number; + cdrom_log(" b[3] = %02X\n", b[2]); + + if (start_track == 0x00) + first_track = 0; + else { + first_track = -1; + for (i = 0; i <= last_track; i++) { + dev->ops->get_track_info(dev, i + 1, 0, &ti); + if (ti.number >= start_track) { + first_track = i; + break; + } + } + } + cdrom_log(" first_track = %i, last_track = %i\n", first_track, last_track); + + /* No suitable starting track, return with error. */ + if (first_track == -1) { + cdrom_log(" [ERROR] No suitable track found\n"); + return -1; + } + + for (i = first_track; i <= last_track; i++) { + cdrom_log(" tracks(%i) = %02X, %02X, %i:%02i.%02i\n", i, ti.attr, ti.number, ti.m, ti.s, ti.f); + dev->ops->get_track_info(dev, i + 1, 0, &ti); + + b[len++] = ti.number; /* track number */ + b[len++] = ti.attr; + + if (msf) { + b[len++] = 0; + b[len++] = ti.m; + b[len++] = ti.s; + b[len++] = ti.f; + } else { + temp = MSFtoLBA(ti.m, ti.s, ti.f) - 150; + b[len++] = temp >> 24; + b[len++] = temp >> 16; + b[len++] = temp >> 8; + b[len++] = temp; + } + } + return len; +} int cdrom_read_toc(cdrom_t *dev, unsigned char *b, int type, unsigned char start_track, int msf, int max_len) { int len; - switch(type) { - case CD_TOC_NORMAL: - len = read_toc_normal(dev, b, start_track, msf); - break; - case CD_TOC_SESSION: - len = read_toc_session(dev, b, msf); - break; - case CD_TOC_RAW: - len = read_toc_raw(dev, b); - break; - default: - cdrom_log("CD-ROM %i: Unknown TOC read type: %i\n", dev->id, type); - return 0; + switch (type) { + case CD_TOC_NORMAL: + len = read_toc_normal(dev, b, start_track, msf); + break; + case CD_TOC_SESSION: + len = read_toc_session(dev, b, msf); + break; + case CD_TOC_RAW: + len = read_toc_raw(dev, b); + break; + default: + cdrom_log("CD-ROM %i: Unknown TOC read type: %i\n", dev->id, type); + return 0; } len = MIN(len, max_len); @@ -695,115 +1266,231 @@ cdrom_read_toc(cdrom_t *dev, unsigned char *b, int type, unsigned char start_tra return len; } +int +cdrom_read_toc_sony(cdrom_t *dev, unsigned char *b, unsigned char start_track, int msf, int max_len) +{ + int len; -/* A new API call for Mitsumi CD-ROM. */ + len = read_toc_sony(dev, b, start_track, msf); + + len = MIN(len, max_len); + + b[0] = (uint8_t) (((len - 2) >> 8) & 0xff); + b[1] = (uint8_t) ((len - 2) & 0xff); + + return len; +} + +/* New API calls for Mitsumi CD-ROM. */ void cdrom_get_track_buffer(cdrom_t *dev, uint8_t *buf) { track_info_t ti; - int first_track, last_track; + int first_track; + int last_track; if (dev != NULL) { - dev->ops->get_tracks(dev, &first_track, &last_track); - buf[0] = 1; - buf[1] = last_track + 1; - dev->ops->get_track_info(dev, 1, 0, &ti); - buf[2] = ti.m; - buf[3] = ti.s; - buf[4] = ti.f; - dev->ops->get_track_info(dev, last_track + 1, 0, &ti); - buf[5] = ti.m; - buf[6] = ti.s; - buf[7] = ti.f; - buf[8] = 0x00; + dev->ops->get_tracks(dev, &first_track, &last_track); + buf[0] = 1; + buf[1] = last_track + 1; + dev->ops->get_track_info(dev, 1, 0, &ti); + buf[2] = ti.m; + buf[3] = ti.s; + buf[4] = ti.f; + dev->ops->get_track_info(dev, last_track + 1, 0, &ti); + buf[5] = ti.m; + buf[6] = ti.s; + buf[7] = ti.f; + buf[8] = 0x00; } else - memset(buf, 0x00, 9); + memset(buf, 0x00, 9); } - void +cdrom_get_q(cdrom_t *dev, uint8_t *buf, int *curtoctrk, uint8_t mode) +{ + track_info_t ti; + int first_track; + int last_track; + + if (dev != NULL) { + dev->ops->get_tracks(dev, &first_track, &last_track); + dev->ops->get_track_info(dev, *curtoctrk, 0, &ti); + buf[0] = (ti.attr << 4) & 0xf0; + buf[1] = ti.number; + buf[2] = bin2bcd(*curtoctrk + 1); + buf[3] = ti.m; + buf[4] = ti.s; + buf[5] = ti.f; + buf[6] = 0x00; + dev->ops->get_track_info(dev, 1, 0, &ti); + buf[7] = ti.m; + buf[8] = ti.s; + buf[9] = ti.f; + if (*curtoctrk >= (last_track + 1)) + *curtoctrk = 0; + else if (mode) + *curtoctrk = *curtoctrk + 1; + } else + memset(buf, 0x00, 10); +} + +uint8_t +cdrom_mitsumi_audio_play(cdrom_t *dev, uint32_t pos, uint32_t len) +{ + track_info_t ti; + + if (dev->cd_status == CD_STATUS_DATA_ONLY) + return 0; + + cdrom_log("CD-ROM 0: Play Mitsumi audio - %08X %08X\n", pos, len); + dev->ops->get_track_info(dev, pos, 0, &ti); + pos = MSFtoLBA(ti.m, ti.s, ti.f) - 150; + dev->ops->get_track_info(dev, len, 1, &ti); + len = MSFtoLBA(ti.m, ti.s, ti.f) - 150; + + /* Do this at this point, since it's at this point that we know the + actual LBA position to start playing from. */ + if (!(dev->ops->track_type(dev, pos) & CD_TRACK_AUDIO)) { + cdrom_log("CD-ROM %i: LBA %08X not on an audio track\n", dev->id, pos); + cdrom_stop(dev); + return 0; + } + + dev->seek_pos = pos; + dev->cd_end = len; + dev->cd_status = CD_STATUS_PLAYING; + dev->cd_buflen = 0; + + return 1; +} + +uint8_t cdrom_read_disc_info_toc(cdrom_t *dev, unsigned char *b, unsigned char track, int type) { track_info_t ti; - int first_track, last_track; + int first_track; + int last_track; + int m = 0; + int s = 0; + int f = 0; + uint32_t temp; dev->ops->get_tracks(dev, &first_track, &last_track); + cdrom_log("Read DISC Info TOC Type = %d, track = %d, first_track = %d, last_track = %d.\n", type, track, first_track, last_track); switch (type) { - case 0: - b[0] = CD_BCD(first_track); - b[1] = CD_BCD(last_track); - b[2] = 0; - b[3] = 0; - break; - case 1: - dev->ops->get_track_info(dev, 0xAA, 0, &ti); - b[0] = CD_BCD(ti.m); - b[1] = CD_BCD(ti.s); - b[2] = CD_BCD(ti.f); - b[3] = 0; - break; - case 2: - dev->ops->get_track_info(dev, CD_DCB(track), 0, &ti); - b[0] = CD_BCD(ti.m); - b[1] = CD_BCD(ti.s); - b[2] = CD_BCD(ti.f); - b[3] = ti.attr; - cdrom_log("CD-ROM %i: Returned Toshiba disc information at %02i:%02i.%02i, track=%d\n", dev->id, b[0], b[1], b[2], CD_DCB(track)); - break; - case 3: - b[0] = 0x00; /*TODO: correct it further, mark it as CD-Audio/CD-ROM disc for now*/ - b[1] = 0; - b[2] = 0; - b[3] = 0; - break; - } -} + case 0: + b[0] = bin2bcd(first_track); + b[1] = bin2bcd(last_track); + b[2] = 0; + b[3] = 0; + cdrom_log("CD-ROM %i: Returned Toshiba/NEC disc information (type 0) at %02i:%02i\n", dev->id, b[0], b[1]); + break; + case 1: + dev->ops->get_track_info(dev, 0xaa, 0, &ti); + m = ti.m; + s = ti.s; + f = ti.f; + msf_to_bcd(&m, &s, &f); + b[0] = m; + b[1] = s; + b[2] = f; + b[3] = 0; + cdrom_log("CD-ROM %i: Returned Toshiba/NEC disc information (type 1) at %02i:%02i.%02i, track=%d\n", dev->id, b[0], b[1], b[2], bcd2bin(track)); + break; + case 2: + if (track > bin2bcd(last_track)) + return 0; -static int -track_type_is_valid(uint8_t id, int type, int flags, int audio, int mode2) -{ - if (!(flags & 0x70) && (flags & 0xf8)) { /* 0x08/0x80/0x88 are illegal modes */ - cdrom_log("CD-ROM %i: [Any Mode] 0x08/0x80/0x88 are illegal modes\n", id); - return 0; - } + dev->ops->get_track_info(dev, bcd2bin(track), 0, &ti); + m = ti.m; + s = ti.s; + f = ti.f; + msf_to_bcd(&m, &s, &f); + b[0] = m; + b[1] = s; + b[2] = f; + b[3] = ti.attr; + cdrom_log("CD-ROM %i: Returned Toshiba/NEC disc information (type 2) at %02i:%02i.%02i, track=%d, m=%02i,s=%02i,f=%02i, tno=%02x.\n", dev->id, b[0], b[1], b[2], bcd2bin(track), m, s, f, ti.attr); + break; + case 3: /*Undocumented on NEC CD-ROM's, from information based on sr_vendor.c from Android's source code*/ + switch (dev->type) { + case CDROM_TYPE_NEC_25_10a: + case CDROM_TYPE_NEC_38_103: + case CDROM_TYPE_NEC_75_103: + case CDROM_TYPE_NEC_77_106: + case CDROM_TYPE_NEC_211_100: + case CDROM_TYPE_NEC_464_105: + dev->ops->get_track_info(dev, 1, 0, &ti); + b[0x0e] = 0; + temp = MSFtoLBA(ti.m, ti.s, ti.f) - 150; + b[0x0f] = temp >> 24; + b[0x10] = temp >> 16; + b[0x11] = temp >> 8; + b[0x12] = temp; + break; - if ((type != 1) && !audio) { - if ((flags & 0x06) == 0x06) { - cdrom_log("CD-ROM %i: [Any Data Mode] Invalid error flags\n", id); - return 0; - } - - if (((flags & 0x700) == 0x300) || ((flags & 0x700) > 0x400)) { - cdrom_log("CD-ROM %i: [Any Data Mode] Invalid subchannel data flags (%02X)\n", id, flags & 0x700); - return 0; - } - - if ((flags & 0x18) == 0x08) { /* EDC/ECC without user data is an illegal mode */ - cdrom_log("CD-ROM %i: [Any Data Mode] EDC/ECC without user data is an illegal mode\n", id); - return 0; - } - - if (((flags & 0xf0) == 0x90) || ((flags & 0xf0) == 0xc0)) { /* 0x90/0x98/0xC0/0xC8 are illegal modes */ - cdrom_log("CD-ROM %i: [Any Data Mode] 0x90/0x98/0xC0/0xC8 are illegal modes\n", id); - return 0; - } - - if (((type > 3) && (type != 8)) || (mode2 && (mode2 & 0x03))) { - if ((flags & 0xf0) == 0x30) { /* 0x30/0x38 are illegal modes */ - cdrom_log("CD-ROM %i: [Any XA Mode 2] 0x30/0x38 are illegal modes\n", id); - return 0; - } - if (((flags & 0xf0) == 0xb0) || ((flags & 0xf0) == 0xd0)) { /* 0xBx and 0xDx are illegal modes */ - cdrom_log("CD-ROM %i: [Any XA Mode 2] 0xBx and 0xDx are illegal modes\n", id); - return 0; - } - } + default: + dev->ops->get_track_info(dev, 1, 0, &ti); + b[0] = 0; + temp = MSFtoLBA(ti.m, ti.s, ti.f) - 150; + b[1] = temp >> 24; + b[2] = temp >> 16; + b[3] = temp >> 8; + break; + } + break; + default: + break; } return 1; } +static int +track_type_is_valid(UNUSED(uint8_t id), int type, int flags, int audio, int mode2) +{ + if (!(flags & 0x70) && (flags & 0xf8)) { /* 0x08/0x80/0x88 are illegal modes */ + cdrom_log("CD-ROM %i: [Any Mode] 0x08/0x80/0x88 are illegal modes\n", id); + return 0; + } + + if ((type != 1) && !audio) { + if ((flags & 0x06) == 0x06) { + cdrom_log("CD-ROM %i: [Any Data Mode] Invalid error flags\n", id); + return 0; + } + + if (((flags & 0x700) == 0x300) || ((flags & 0x700) > 0x400)) { + cdrom_log("CD-ROM %i: [Any Data Mode] Invalid subchannel data flags (%02X)\n", id, flags & 0x700); + return 0; + } + + if ((flags & 0x18) == 0x08) { /* EDC/ECC without user data is an illegal mode */ + cdrom_log("CD-ROM %i: [Any Data Mode] EDC/ECC without user data is an illegal mode\n", id); + return 0; + } + + if (((flags & 0xf0) == 0x90) || ((flags & 0xf0) == 0xc0)) { /* 0x90/0x98/0xC0/0xC8 are illegal modes */ + cdrom_log("CD-ROM %i: [Any Data Mode] 0x90/0x98/0xC0/0xC8 are illegal modes\n", id); + return 0; + } + + if (((type > 3) && (type != 8)) || (mode2 && (mode2 & 0x03))) { + if ((flags & 0xf0) == 0x30) { /* 0x30/0x38 are illegal modes */ + cdrom_log("CD-ROM %i: [Any XA Mode 2] 0x30/0x38 are illegal modes\n", id); + return 0; + } + if (((flags & 0xf0) == 0xb0) || ((flags & 0xf0) == 0xd0)) { /* 0xBx and 0xDx are illegal modes */ + cdrom_log("CD-ROM %i: [Any XA Mode 2] 0xBx and 0xDx are illegal modes\n", id); + return 0; + } + } + } + + return 1; +} static void read_sector_to_buffer(cdrom_t *dev, uint8_t *rbuf, uint32_t msf, uint32_t lba, int mode2, int len) @@ -827,12 +1514,11 @@ read_sector_to_buffer(cdrom_t *dev, uint8_t *rbuf, uint32_t msf, uint32_t lba, i bb += mode2 ? 12 : 4; bb += len; if (mode2 && ((mode2 & 0x03) == 1)) - memset(bb, 0, 280); + memset(bb, 0, 280); else if (!mode2) - memset(bb, 0, 288); + memset(bb, 0, 288); } - static void read_audio(cdrom_t *dev, uint32_t lba, uint8_t *b) { @@ -843,213 +1529,250 @@ read_audio(cdrom_t *dev, uint32_t lba, uint8_t *b) cdrom_sector_size = 2352; } - static void read_mode1(cdrom_t *dev, int cdrom_sector_flags, uint32_t lba, uint32_t msf, int mode2, uint8_t *b) { if ((dev->cd_status == CD_STATUS_DATA_ONLY) || (dev->ops->sector_size(dev, lba) == 2048)) - read_sector_to_buffer(dev, raw_buffer, msf, lba, mode2, 2048); + read_sector_to_buffer(dev, raw_buffer, msf, lba, mode2, 2048); else - dev->ops->read_sector(dev, CD_READ_RAW, raw_buffer, lba); + dev->ops->read_sector(dev, CD_READ_RAW, raw_buffer, lba); cdrom_sector_size = 0; - if (cdrom_sector_flags & 0x80) { /* Sync */ - cdrom_log("CD-ROM %i: [Mode 1] Sync\n", dev->id); - memcpy(b, raw_buffer, 12); - cdrom_sector_size += 12; - b += 12; + if (cdrom_sector_flags & 0x80) { + /* Sync */ + cdrom_log("CD-ROM %i: [Mode 1] Sync\n", dev->id); + memcpy(b, raw_buffer, 12); + cdrom_sector_size += 12; + b += 12; } - if (cdrom_sector_flags & 0x20) { /* Header */ - cdrom_log("CD-ROM %i: [Mode 1] Header\n", dev->id); - memcpy(b, raw_buffer + 12, 4); - cdrom_sector_size += 4; - b += 4; + if (cdrom_sector_flags & 0x20) { + /* Header */ + cdrom_log("CD-ROM %i: [Mode 1] Header\n", dev->id); + memcpy(b, raw_buffer + 12, 4); + cdrom_sector_size += 4; + b += 4; } - if (cdrom_sector_flags & 0x40) { /* Sub-header */ - if (!(cdrom_sector_flags & 0x10)) { /* No user data */ - cdrom_log("CD-ROM %i: [Mode 1] Sub-header\n", dev->id); - memcpy(b, raw_buffer + 16, 8); - cdrom_sector_size += 8; - b += 8; - } + if (cdrom_sector_flags & 0x40) { + /* Sub-header */ + if (!(cdrom_sector_flags & 0x10)) { + /* No user data */ + cdrom_log("CD-ROM %i: [Mode 1] Sub-header\n", dev->id); + memcpy(b, raw_buffer + 16, 8); + cdrom_sector_size += 8; + b += 8; + } } - if (cdrom_sector_flags & 0x10) { /* User data */ - cdrom_log("CD-ROM %i: [Mode 1] User data\n", dev->id); - memcpy(b, raw_buffer + 16, 2048); - cdrom_sector_size += 2048; - b += 2048; + if (cdrom_sector_flags & 0x10) { + /* User data */ + cdrom_log("CD-ROM %i: [Mode 1] User data\n", dev->id); + memcpy(b, raw_buffer + 16, 2048); + cdrom_sector_size += 2048; + b += 2048; } - if (cdrom_sector_flags & 0x08) { /* EDC/ECC */ - cdrom_log("CD-ROM %i: [Mode 1] EDC/ECC\n", dev->id); - memcpy(b, raw_buffer + 2064, 288); - cdrom_sector_size += 288; - b += 288; + if (cdrom_sector_flags & 0x08) { + /* EDC/ECC */ + cdrom_log("CD-ROM %i: [Mode 1] EDC/ECC\n", dev->id); + memcpy(b, raw_buffer + 2064, 288); + cdrom_sector_size += 288; + b += 288; } } - static void read_mode2_non_xa(cdrom_t *dev, int cdrom_sector_flags, uint32_t lba, uint32_t msf, int mode2, uint8_t *b) { if ((dev->cd_status == CD_STATUS_DATA_ONLY) || (dev->ops->sector_size(dev, lba) == 2336)) - read_sector_to_buffer(dev, raw_buffer, msf, lba, mode2, 2336); + read_sector_to_buffer(dev, raw_buffer, msf, lba, mode2, 2336); else - dev->ops->read_sector(dev, CD_READ_RAW, raw_buffer, lba); + dev->ops->read_sector(dev, CD_READ_RAW, raw_buffer, lba); cdrom_sector_size = 0; - if (cdrom_sector_flags & 0x80) { /* Sync */ - cdrom_log("CD-ROM %i: [Mode 2 Formless] Sync\n", dev->id); - memcpy(b, raw_buffer, 12); - cdrom_sector_size += 12; - b += 12; + if (cdrom_sector_flags & 0x80) { + /* Sync */ + cdrom_log("CD-ROM %i: [Mode 2 Formless] Sync\n", dev->id); + memcpy(b, raw_buffer, 12); + cdrom_sector_size += 12; + b += 12; } - if (cdrom_sector_flags & 0x20) { /* Header */ - cdrom_log("CD-ROM %i: [Mode 2 Formless] Header\n", dev->id); - memcpy(b, raw_buffer + 12, 4); - cdrom_sector_size += 4; - b += 4; + if (cdrom_sector_flags & 0x20) { + /* Header */ + cdrom_log("CD-ROM %i: [Mode 2 Formless] Header\n", dev->id); + memcpy(b, raw_buffer + 12, 4); + cdrom_sector_size += 4; + b += 4; } /* Mode 1 sector, expected type is 1 type. */ - if (cdrom_sector_flags & 0x40) { /* Sub-header */ - cdrom_log("CD-ROM %i: [Mode 2 Formless] Sub-header\n", dev->id); - memcpy(b, raw_buffer + 16, 8); - cdrom_sector_size += 8; - b += 8; + if (cdrom_sector_flags & 0x40) { + /* Sub-header */ + cdrom_log("CD-ROM %i: [Mode 2 Formless] Sub-header\n", dev->id); + memcpy(b, raw_buffer + 16, 8); + cdrom_sector_size += 8; + b += 8; } - if (cdrom_sector_flags & 0x10) { /* User data */ - cdrom_log("CD-ROM %i: [Mode 2 Formless] User data\n", dev->id); - memcpy(b, raw_buffer + 24, 2336); - cdrom_sector_size += 2336; - b += 2336; + if (cdrom_sector_flags & 0x10) { + /* User data */ + cdrom_log("CD-ROM %i: [Mode 2 Formless] User data\n", dev->id); + memcpy(b, raw_buffer + 24, 2336); + cdrom_sector_size += 2336; + b += 2336; } } - static void read_mode2_xa_form1(cdrom_t *dev, int cdrom_sector_flags, uint32_t lba, uint32_t msf, int mode2, uint8_t *b) { if ((dev->cd_status == CD_STATUS_DATA_ONLY) || (dev->ops->sector_size(dev, lba) == 2048)) - read_sector_to_buffer(dev, raw_buffer, msf, lba, mode2, 2048); + read_sector_to_buffer(dev, raw_buffer, msf, lba, mode2, 2048); else - dev->ops->read_sector(dev, CD_READ_RAW, raw_buffer, lba); + dev->ops->read_sector(dev, CD_READ_RAW, raw_buffer, lba); cdrom_sector_size = 0; - if (cdrom_sector_flags & 0x80) { /* Sync */ - cdrom_log("CD-ROM %i: [XA Mode 2 Form 1] Sync\n", dev->id); - memcpy(b, raw_buffer, 12); - cdrom_sector_size += 12; - b += 12; + if (cdrom_sector_flags & 0x80) { + /* Sync */ + cdrom_log("CD-ROM %i: [XA Mode 2 Form 1] Sync\n", dev->id); + memcpy(b, raw_buffer, 12); + cdrom_sector_size += 12; + b += 12; } - if (cdrom_sector_flags & 0x20) { /* Header */ - cdrom_log("CD-ROM %i: [XA Mode 2 Form 1] Header\n", dev->id); - memcpy(b, raw_buffer + 12, 4); - cdrom_sector_size += 4; - b += 4; + if (cdrom_sector_flags & 0x20) { + /* Header */ + cdrom_log("CD-ROM %i: [XA Mode 2 Form 1] Header\n", dev->id); + memcpy(b, raw_buffer + 12, 4); + cdrom_sector_size += 4; + b += 4; } - if (cdrom_sector_flags & 0x40) { /* Sub-header */ - cdrom_log("CD-ROM %i: [XA Mode 2 Form 1] Sub-header\n", dev->id); - memcpy(b, raw_buffer + 16, 8); - cdrom_sector_size += 8; - b += 8; + if (cdrom_sector_flags & 0x40) { + /* Sub-header */ + cdrom_log("CD-ROM %i: [XA Mode 2 Form 1] Sub-header\n", dev->id); + memcpy(b, raw_buffer + 16, 8); + cdrom_sector_size += 8; + b += 8; } - if (cdrom_sector_flags & 0x10) { /* User data */ - cdrom_log("CD-ROM %i: [XA Mode 2 Form 1] User data\n", dev->id); - memcpy(b, raw_buffer + 24, 2048); - cdrom_sector_size += 2048; - b += 2048; + if (cdrom_sector_flags & 0x10) { + /* User data */ + cdrom_log("CD-ROM %i: [XA Mode 2 Form 1] User data\n", dev->id); + memcpy(b, raw_buffer + 24, 2048); + cdrom_sector_size += 2048; + b += 2048; } - if (cdrom_sector_flags & 0x08) { /* EDC/ECC */ - cdrom_log("CD-ROM %i: [XA Mode 2 Form 1] EDC/ECC\n", dev->id); - memcpy(b, raw_buffer + 2072, 280); - cdrom_sector_size += 280; - b += 280; + if (cdrom_sector_flags & 0x08) { + /* EDC/ECC */ + cdrom_log("CD-ROM %i: [XA Mode 2 Form 1] EDC/ECC\n", dev->id); + memcpy(b, raw_buffer + 2072, 280); + cdrom_sector_size += 280; + b += 280; } } - static void read_mode2_xa_form2(cdrom_t *dev, int cdrom_sector_flags, uint32_t lba, uint32_t msf, int mode2, uint8_t *b) { if ((dev->cd_status == CD_STATUS_DATA_ONLY) || (dev->ops->sector_size(dev, lba) == 2324)) - read_sector_to_buffer(dev, raw_buffer, msf, lba, mode2, 2324); + read_sector_to_buffer(dev, raw_buffer, msf, lba, mode2, 2324); else - dev->ops->read_sector(dev, CD_READ_RAW, raw_buffer, lba); + dev->ops->read_sector(dev, CD_READ_RAW, raw_buffer, lba); cdrom_sector_size = 0; - if (cdrom_sector_flags & 0x80) { /* Sync */ - cdrom_log("CD-ROM %i: [XA Mode 2 Form 2] Sync\n", dev->id); - memcpy(b, raw_buffer, 12); - cdrom_sector_size += 12; - b += 12; + if (cdrom_sector_flags & 0x80) { + /* Sync */ + cdrom_log("CD-ROM %i: [XA Mode 2 Form 2] Sync\n", dev->id); + memcpy(b, raw_buffer, 12); + cdrom_sector_size += 12; + b += 12; } - if (cdrom_sector_flags & 0x20) { /* Header */ - cdrom_log("CD-ROM %i: [XA Mode 2 Form 2] Header\n", dev->id); - memcpy(b, raw_buffer + 12, 4); - cdrom_sector_size += 4; - b += 4; + if (cdrom_sector_flags & 0x20) { + /* Header */ + cdrom_log("CD-ROM %i: [XA Mode 2 Form 2] Header\n", dev->id); + memcpy(b, raw_buffer + 12, 4); + cdrom_sector_size += 4; + b += 4; } - if (cdrom_sector_flags & 0x40) { /* Sub-header */ - cdrom_log("CD-ROM %i: [XA Mode 2 Form 2] Sub-header\n", dev->id); - memcpy(b, raw_buffer + 16, 8); - cdrom_sector_size += 8; - b += 8; + if (cdrom_sector_flags & 0x40) { + /* Sub-header */ + cdrom_log("CD-ROM %i: [XA Mode 2 Form 2] Sub-header\n", dev->id); + memcpy(b, raw_buffer + 16, 8); + cdrom_sector_size += 8; + b += 8; } - if (cdrom_sector_flags & 0x10) { /* User data */ - cdrom_log("CD-ROM %i: [XA Mode 2 Form 2] User data\n", dev->id); - memcpy(b, raw_buffer + 24, 2328); - cdrom_sector_size += 2328; - b += 2328; + if (cdrom_sector_flags & 0x10) { + /* User data */ + cdrom_log("CD-ROM %i: [XA Mode 2 Form 2] User data\n", dev->id); + memcpy(b, raw_buffer + 24, 2328); + cdrom_sector_size += 2328; + b += 2328; } } - int cdrom_readsector_raw(cdrom_t *dev, uint8_t *buffer, int sector, int ismsf, int cdrom_sector_type, - int cdrom_sector_flags, int *len) + int cdrom_sector_flags, int *len, uint8_t vendor_type) { - uint8_t *b, *temp_b; - uint32_t msf, lba; - int audio = 0, mode2 = 0; - int m, s, f; + uint8_t *b; + uint8_t *temp_b; + uint32_t msf; + uint32_t lba; + int audio = 0; + int mode2 = 0; + int m; + int s; + int f; if (dev->cd_status == CD_STATUS_EMPTY) - return 0; + return 0; b = temp_b = buffer; *len = 0; if (ismsf) { - m = (sector >> 16) & 0xff; - s = (sector >> 8) & 0xff; - f = sector & 0xff; - lba = MSFtoLBA(m, s, f) - 150; - msf = sector; + m = (sector >> 16) & 0xff; + s = (sector >> 8) & 0xff; + f = sector & 0xff; + lba = MSFtoLBA(m, s, f) - 150; + msf = sector; } else { - lba = sector; - msf = cdrom_lba_to_msf_accurate(sector); + switch (vendor_type) { + case 0x00: + lba = sector; + msf = cdrom_lba_to_msf_accurate(sector); + break; + case 0x40: + m = bcd2bin((sector >> 24) & 0xff); + s = bcd2bin((sector >> 16) & 0xff); + f = bcd2bin((sector >> 8) & 0xff); + lba = MSFtoLBA(m, s, f) - 150; + msf = sector; + break; + case 0x80: + lba = bcd2bin((sector >> 24) & 0xff); + msf = sector; + break; + /* Never used values but the compiler complains. */ + default: + lba = msf = 0; + } } if (dev->ops->track_type) - audio = dev->ops->track_type(dev, lba); + audio = dev->ops->track_type(dev, lba); mode2 = audio & ~CD_TRACK_AUDIO; audio &= CD_TRACK_AUDIO; @@ -1057,106 +1780,107 @@ cdrom_readsector_raw(cdrom_t *dev, uint8_t *buffer, int sector, int ismsf, int c memset(raw_buffer, 0, 2448); memset(extra_buffer, 0, 296); - if ((cdrom_sector_flags & 0xf8) == 0x08) { /* 0x08 is an illegal mode */ - cdrom_log("CD-ROM %i: [Mode 1] 0x08 is an illegal mode\n", dev->id); - return 0; + if ((cdrom_sector_flags & 0xf8) == 0x08) { + /* 0x08 is an illegal mode */ + cdrom_log("CD-ROM %i: [Mode 1] 0x08 is an illegal mode\n", dev->id); + return 0; } if (!track_type_is_valid(dev->id, cdrom_sector_type, cdrom_sector_flags, audio, mode2)) - return 0; + return 0; if ((cdrom_sector_type > 5) && (cdrom_sector_type != 8)) { - cdrom_log("CD-ROM %i: Attempting to read an unrecognized sector type from an image\n", dev->id); - return 0; + cdrom_log("CD-ROM %i: Attempting to read an unrecognized sector type from an image\n", dev->id); + return 0; } else if (cdrom_sector_type == 1) { - if (!audio || (dev->cd_status == CD_STATUS_DATA_ONLY)) { - cdrom_log("CD-ROM %i: [Audio] Attempting to read an audio sector from a data image\n", dev->id); - return 0; - } + if (!audio || (dev->cd_status == CD_STATUS_DATA_ONLY)) { + cdrom_log("CD-ROM %i: [Audio] Attempting to read an audio sector from a data image\n", dev->id); + return 0; + } - read_audio(dev, lba, temp_b); + read_audio(dev, lba, temp_b); } else if (cdrom_sector_type == 2) { - if (audio || mode2) { - cdrom_log("CD-ROM %i: [Mode 1] Attempting to read a sector of another type\n", dev->id); - return 0; - } + if (audio || mode2) { + cdrom_log("CD-ROM %i: [Mode 1] Attempting to read a sector of another type\n", dev->id); + return 0; + } - read_mode1(dev, cdrom_sector_flags, lba, msf, mode2, temp_b); + read_mode1(dev, cdrom_sector_flags, lba, msf, mode2, temp_b); } else if (cdrom_sector_type == 3) { - if (audio || !mode2 || (mode2 & 0x03)) { - cdrom_log("CD-ROM %i: [Mode 2 Formless] Attempting to read a sector of another type\n", dev->id); - return 0; - } + if (audio || !mode2 || (mode2 & 0x03)) { + cdrom_log("CD-ROM %i: [Mode 2 Formless] Attempting to read a sector of another type\n", dev->id); + return 0; + } - read_mode2_non_xa(dev, cdrom_sector_flags, lba, msf, mode2, temp_b); + read_mode2_non_xa(dev, cdrom_sector_flags, lba, msf, mode2, temp_b); } else if (cdrom_sector_type == 4) { - if (audio || !mode2 || ((mode2 & 0x03) != 1)) { - cdrom_log("CD-ROM %i: [XA Mode 2 Form 1] Attempting to read a sector of another type\n", dev->id); - return 0; - } + if (audio || !mode2 || ((mode2 & 0x03) != 1)) { + cdrom_log("CD-ROM %i: [XA Mode 2 Form 1] Attempting to read a sector of another type\n", dev->id); + return 0; + } - read_mode2_xa_form1(dev, cdrom_sector_flags, lba, msf, mode2, temp_b); + read_mode2_xa_form1(dev, cdrom_sector_flags, lba, msf, mode2, temp_b); } else if (cdrom_sector_type == 5) { - if (audio || !mode2 || ((mode2 & 0x03) != 2)) { - cdrom_log("CD-ROM %i: [XA Mode 2 Form 2] Attempting to read a sector of another type\n", dev->id); - return 0; - } + if (audio || !mode2 || ((mode2 & 0x03) != 2)) { + cdrom_log("CD-ROM %i: [XA Mode 2 Form 2] Attempting to read a sector of another type\n", dev->id); + return 0; + } - read_mode2_xa_form2(dev, cdrom_sector_flags, lba, msf, mode2, temp_b); + read_mode2_xa_form2(dev, cdrom_sector_flags, lba, msf, mode2, temp_b); } else if (cdrom_sector_type == 8) { - if (audio) { - cdrom_log("CD-ROM %i: [Any Data] Attempting to read a data sector from an audio track\n", dev->id); - return 0; - } + if (audio) { + cdrom_log("CD-ROM %i: [Any Data] Attempting to read a data sector from an audio track\n", dev->id); + return 0; + } - if (mode2 && ((mode2 & 0x03) == 1)) - read_mode2_xa_form1(dev, cdrom_sector_flags, lba, msf, mode2, temp_b); - else if (!mode2) - read_mode1(dev, cdrom_sector_flags, lba, msf, mode2, temp_b); - else { - cdrom_log("CD-ROM %i: [Any Data] Attempting to read a data sector whose cooked size is not 2048 bytes\n", dev->id); - return 0; - } + if (mode2 && ((mode2 & 0x03) == 1)) + read_mode2_xa_form1(dev, cdrom_sector_flags, lba, msf, mode2, temp_b); + else if (!mode2) + read_mode1(dev, cdrom_sector_flags, lba, msf, mode2, temp_b); + else { + cdrom_log("CD-ROM %i: [Any Data] Attempting to read a data sector whose cooked size is not 2048 bytes\n", dev->id); + return 0; + } } else { - if (mode2) { - if ((mode2 & 0x03) == 0x01) - read_mode2_xa_form1(dev, cdrom_sector_flags, lba, msf, mode2, temp_b); - else if ((mode2 & 0x03) == 0x02) - read_mode2_xa_form2(dev, cdrom_sector_flags, lba, msf, mode2, temp_b); - else - read_mode2_non_xa(dev, cdrom_sector_flags, lba, msf, mode2, temp_b); - } else { - if (audio) - read_audio(dev, lba, temp_b); - else - read_mode1(dev, cdrom_sector_flags, lba, msf, mode2, temp_b); - } + if (mode2) { + if ((mode2 & 0x03) == 0x01) + read_mode2_xa_form1(dev, cdrom_sector_flags, lba, msf, mode2, temp_b); + else if ((mode2 & 0x03) == 0x02) + read_mode2_xa_form2(dev, cdrom_sector_flags, lba, msf, mode2, temp_b); + else + read_mode2_non_xa(dev, cdrom_sector_flags, lba, msf, mode2, temp_b); + } else { + if (audio) + read_audio(dev, lba, temp_b); + else + read_mode1(dev, cdrom_sector_flags, lba, msf, mode2, temp_b); + } } if ((cdrom_sector_flags & 0x06) == 0x02) { - /* Add error flags. */ - cdrom_log("CD-ROM %i: Error flags\n", dev->id); - memcpy(b + cdrom_sector_size, extra_buffer, 294); - cdrom_sector_size += 294; + /* Add error flags. */ + cdrom_log("CD-ROM %i: Error flags\n", dev->id); + memcpy(b + cdrom_sector_size, extra_buffer, 294); + cdrom_sector_size += 294; } else if ((cdrom_sector_flags & 0x06) == 0x04) { - /* Add error flags. */ - cdrom_log("CD-ROM %i: Full error flags\n", dev->id); - memcpy(b + cdrom_sector_size, extra_buffer, 296); - cdrom_sector_size += 296; + /* Add error flags. */ + cdrom_log("CD-ROM %i: Full error flags\n", dev->id); + memcpy(b + cdrom_sector_size, extra_buffer, 296); + cdrom_sector_size += 296; } if ((cdrom_sector_flags & 0x700) == 0x100) { - cdrom_log("CD-ROM %i: Raw subchannel data\n", dev->id); - memcpy(b + cdrom_sector_size, raw_buffer + 2352, 96); - cdrom_sector_size += 96; + cdrom_log("CD-ROM %i: Raw subchannel data\n", dev->id); + memcpy(b + cdrom_sector_size, raw_buffer + 2352, 96); + cdrom_sector_size += 96; } else if ((cdrom_sector_flags & 0x700) == 0x200) { - cdrom_log("CD-ROM %i: Q subchannel data\n", dev->id); - memcpy(b + cdrom_sector_size, raw_buffer + 2352, 16); - cdrom_sector_size += 16; + cdrom_log("CD-ROM %i: Q subchannel data\n", dev->id); + memcpy(b + cdrom_sector_size, raw_buffer + 2352, 16); + cdrom_sector_size += 16; } else if ((cdrom_sector_flags & 0x700) == 0x400) { - cdrom_log("CD-ROM %i: R/W subchannel data\n", dev->id); - memcpy(b + cdrom_sector_size, raw_buffer + 2352, 96); - cdrom_sector_size += 96; + cdrom_log("CD-ROM %i: R/W subchannel data\n", dev->id); + memcpy(b + cdrom_sector_size, raw_buffer + 2352, 96); + cdrom_sector_size += 96; } *len = cdrom_sector_size; @@ -1164,7 +1888,6 @@ cdrom_readsector_raw(cdrom_t *dev, uint8_t *buffer, int sector, int ismsf, int c return 1; } - /* Peform a master init on the entire module. */ void cdrom_global_init(void) @@ -1173,93 +1896,84 @@ cdrom_global_init(void) memset(cdrom, 0x00, sizeof(cdrom)); } - static void cdrom_drive_reset(cdrom_t *dev) { - dev->priv = NULL; - dev->insert = NULL; - dev->close = NULL; - dev->get_volume = NULL; + dev->priv = NULL; + dev->insert = NULL; + dev->close = NULL; + dev->get_volume = NULL; dev->get_channel = NULL; } - void cdrom_hard_reset(void) { cdrom_t *dev; - int i; - for (i = 0; i < CDROM_NUM; i++) { - dev = &cdrom[i]; - if (dev->bus_type) { - cdrom_log("CD-ROM %i: Hard reset\n", i); + for (uint8_t i = 0; i < CDROM_NUM; i++) { + dev = &cdrom[i]; + if (dev->bus_type) { + cdrom_log("CD-ROM %i: Hard reset\n", i); - dev->id = i; + dev->id = i; - cdrom_drive_reset(dev); + cdrom_drive_reset(dev); - switch(dev->bus_type) { - case CDROM_BUS_ATAPI: - case CDROM_BUS_SCSI: - scsi_cdrom_drive_reset(i); - break; + switch (dev->bus_type) { + case CDROM_BUS_ATAPI: + case CDROM_BUS_SCSI: + scsi_cdrom_drive_reset(i); + break; - default: - break; - } + default: + break; + } - dev->cd_status = CD_STATUS_EMPTY; + dev->cd_status = CD_STATUS_EMPTY; - if (dev->host_drive == 200) - cdrom_image_open(dev, dev->image_path); - } + if (dev->host_drive == 200) + cdrom_image_open(dev, dev->image_path); + } } sound_cd_thread_reset(); } - void cdrom_close(void) { cdrom_t *dev; - int i; - for (i = 0; i < CDROM_NUM; i++) { - dev = &cdrom[i]; + for (uint8_t i = 0; i < CDROM_NUM; i++) { + dev = &cdrom[i]; - if (dev->bus_type == CDROM_BUS_SCSI) - memset(&scsi_devices[dev->scsi_device_id], 0x00, sizeof(scsi_device_t)); + if (dev->bus_type == CDROM_BUS_SCSI) + memset(&scsi_devices[dev->scsi_device_id], 0x00, sizeof(scsi_device_t)); - if (dev->close) - dev->close(dev->priv); + if (dev->close) + dev->close(dev->priv); - if (dev->ops && dev->ops->exit) - dev->ops->exit(dev); + if (dev->ops && dev->ops->exit) + dev->ops->exit(dev); - dev->ops = NULL; - dev->priv = NULL; + dev->ops = NULL; + dev->priv = NULL; - cdrom_drive_reset(dev); + cdrom_drive_reset(dev); } } - /* Signal disc change to the emulated machine. */ void cdrom_insert(uint8_t id) { cdrom_t *dev = &cdrom[id]; - if (dev->bus_type) { - if (dev->insert) - dev->insert(dev->priv); - } + if (dev->bus_type && dev->insert) + dev->insert(dev->priv); } - /* The mechanics of ejecting a CD-ROM from a drive. */ void cdrom_eject(uint8_t id) @@ -1268,15 +1982,15 @@ cdrom_eject(uint8_t id) /* This entire block should be in cdrom.c/cdrom_eject(dev*) ... */ if (dev->host_drive == 0) { - /* Switch from empty to empty. Do nothing. */ - return; + /* Switch from empty to empty. Do nothing. */ + return; } if (dev->host_drive == 200) - strcpy(dev->prev_image_path, dev->image_path); + strcpy(dev->prev_image_path, dev->image_path); dev->prev_host_drive = dev->host_drive; - dev->host_drive = 0; + dev->host_drive = 0; dev->ops->exit(dev); dev->ops = NULL; @@ -1289,35 +2003,33 @@ cdrom_eject(uint8_t id) config_save(); } - /* The mechanics of re-loading a CD-ROM drive. */ void cdrom_reload(uint8_t id) { cdrom_t *dev = &cdrom[id]; - if ((dev->host_drive == dev->prev_host_drive) || - (dev->prev_host_drive == 0) || (dev->host_drive != 0)) { - /* Switch from empty to empty. Do nothing. */ - return; + if ((dev->host_drive == dev->prev_host_drive) || (dev->prev_host_drive == 0) || (dev->host_drive != 0)) { + /* Switch from empty to empty. Do nothing. */ + return; } if (dev->ops && dev->ops->exit) - dev->ops->exit(dev); + dev->ops->exit(dev); dev->ops = NULL; memset(dev->image_path, 0, sizeof(dev->image_path)); if (dev->prev_host_drive == 200) { - /* Reload a previous image. */ - strcpy(dev->image_path, dev->prev_image_path); - cdrom_image_open(dev, dev->image_path); + /* Reload a previous image. */ + strcpy(dev->image_path, dev->prev_image_path); + cdrom_image_open(dev, dev->image_path); - cdrom_insert(id); + cdrom_insert(id); - if (strlen(dev->image_path) == 0) - dev->host_drive = 0; - else - dev->host_drive = 200; + if (strlen(dev->image_path) == 0) + dev->host_drive = 0; + else + dev->host_drive = 200; } plat_cdrom_ui_update(id, 1); diff --git a/src/cdrom/cdrom_image.c b/src/cdrom/cdrom_image.c index 91e4992b4..0c7ee03a0 100644 --- a/src/cdrom/cdrom_image.c +++ b/src/cdrom/cdrom_image.c @@ -1,26 +1,23 @@ /* - * 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. + * 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. + * This file is part of the 86Box distribution. * - * CD-ROM image support. + * CD-ROM image support. * * * - * Author: RichardG867, - * Miran Grca, - * bit, + * Authors: RichardG867, + * Miran Grca, + * bit, * - * Copyright 2015-2019 Richardg867. - * Copyright 2015-2019 Miran Grca. - * Copyright 2017-2019 bit. + * Copyright 2015-2019 Richardg867. + * Copyright 2015-2019 Miran Grca. + * Copyright 2017-2019 bit. */ -#define __USE_LARGEFILE64 -#define _LARGEFILE_SOURCE -#define _LARGEFILE64_SOURCE #include #include #include @@ -31,17 +28,16 @@ #define HAVE_STDARG_H #include <86box/86box.h> #include <86box/config.h> +#include <86box/path.h> #include <86box/plat.h> #include <86box/scsi_device.h> #include <86box/cdrom_image_backend.h> #include <86box/cdrom.h> #include <86box/cdrom_image.h> - #ifdef ENABLE_CDROM_IMAGE_LOG int cdrom_image_do_log = ENABLE_CDROM_IMAGE_LOG; - void cdrom_image_log(const char *fmt, ...) { @@ -54,31 +50,28 @@ cdrom_image_log(const char *fmt, ...) } } #else -#define cdrom_image_log(fmt, ...) +# define cdrom_image_log(fmt, ...) #endif - /* The addresses sent from the guest are absolute, ie. a LBA of 0 corresponds to a MSF of 00:00:00. Otherwise, the counter displayed by the guest is wrong: there is a seeming 2 seconds in which audio plays but counter does not move, while a data track before audio jumps to 2 seconds before the actual start of the audio while audio still plays. With an absolute conversion, the counter is fine. */ -#define MSFtoLBA(m,s,f) ((((m * 60) + s) * 75) + f) - +#define MSFtoLBA(m, s, f) ((((m * 60) + s) * 75) + f) static void image_get_tracks(cdrom_t *dev, int *first, int *last) { - cd_img_t *img = (cd_img_t *)dev->image; - TMSF tmsf; + cd_img_t *img = (cd_img_t *) dev->image; + TMSF tmsf; cdi_get_audio_tracks(img, first, last, &tmsf); } - static void image_get_track_info(cdrom_t *dev, uint32_t track, int end, track_info_t *ti) { - cd_img_t *img = (cd_img_t *)dev->image; - TMSF tmsf; + cd_img_t *img = (cd_img_t *) dev->image; + TMSF tmsf; cdi_get_audio_track_info(img, end, track, &ti->number, &tmsf, &ti->attr); @@ -87,15 +80,15 @@ image_get_track_info(cdrom_t *dev, uint32_t track, int end, track_info_t *ti) ti->f = tmsf.fr; } - static void image_get_subchannel(cdrom_t *dev, uint32_t lba, subchannel_t *subc) { - cd_img_t *img = (cd_img_t *)dev->image; - TMSF rel_pos, abs_pos; + cd_img_t *img = (cd_img_t *) dev->image; + TMSF rel_pos; + TMSF abs_pos; cdi_get_audio_sub(img, lba, &subc->attr, &subc->track, &subc->index, - &rel_pos, &abs_pos); + &rel_pos, &abs_pos); subc->abs_m = abs_pos.min; subc->abs_s = abs_pos.sec; @@ -106,143 +99,140 @@ image_get_subchannel(cdrom_t *dev, uint32_t lba, subchannel_t *subc) subc->rel_f = rel_pos.fr; } - static int image_get_capacity(cdrom_t *dev) { - cd_img_t *img = (cd_img_t *)dev->image; - int first_track, last_track; - int number, c; + cd_img_t *img = (cd_img_t *) dev->image; + int first_track; + int last_track; + int number; unsigned char attr; - uint32_t address = 0, lb = 0; + uint32_t address = 0; + uint32_t lb = 0; if (!img) - return 0; + return 0; cdi_get_audio_tracks_lba(img, &first_track, &last_track, &lb); - for (c = 0; c <= last_track; c++) { - cdi_get_audio_track_info_lba(img, 0, c + 1, &number, &address, &attr); - if (address > lb) - lb = address; + for (int c = 0; c <= last_track; c++) { + cdi_get_audio_track_info_lba(img, 0, c + 1, &number, &address, &attr); + if (address > lb) + lb = address; } return lb; } - static int image_is_track_audio(cdrom_t *dev, uint32_t pos, int ismsf) { - cd_img_t *img = (cd_img_t *)dev->image; - uint8_t attr; - TMSF tmsf; - int m, s, f; - int number, track; + cd_img_t *img = (cd_img_t *) dev->image; + uint8_t attr; + TMSF tmsf; + int m; + int s; + int f; + int number; + int track; if (!img || (dev->cd_status == CD_STATUS_DATA_ONLY)) - return 0; + return 0; if (ismsf) { - m = (pos >> 16) & 0xff; - s = (pos >> 8) & 0xff; - f = pos & 0xff; - pos = MSFtoLBA(m, s, f) - 150; + m = (pos >> 16) & 0xff; + s = (pos >> 8) & 0xff; + f = pos & 0xff; + pos = MSFtoLBA(m, s, f) - 150; } /* GetTrack requires LBA. */ track = cdi_get_track(img, pos); if (track == -1) - return 0; + return 0; else { - cdi_get_audio_track_info(img, 0, track, &number, &tmsf, &attr); - return attr == AUDIO_TRACK; + cdi_get_audio_track_info(img, 0, track, &number, &tmsf, &attr); + return attr == AUDIO_TRACK; } } - static int image_is_track_pre(cdrom_t *dev, uint32_t lba) { - cd_img_t *img = (cd_img_t *)dev->image; - int track; + cd_img_t *img = (cd_img_t *) dev->image; + int track; /* GetTrack requires LBA. */ track = cdi_get_track(img, lba); if (track != -1) - return cdi_get_audio_track_pre(img, track); + return cdi_get_audio_track_pre(img, track); return 0; } - -static int +static int image_sector_size(struct cdrom *dev, uint32_t lba) { - cd_img_t *img = (cd_img_t *)dev->image; + cd_img_t *img = (cd_img_t *) dev->image; return cdi_get_sector_size(img, lba); } - static int image_read_sector(struct cdrom *dev, int type, uint8_t *b, uint32_t lba) { - cd_img_t *img = (cd_img_t *)dev->image; + cd_img_t *img = (cd_img_t *) dev->image; switch (type) { - case CD_READ_DATA: - return cdi_read_sector(img, b, 0, lba); - case CD_READ_AUDIO: - return cdi_read_sector(img, b, 1, lba); - case CD_READ_RAW: - if (cdi_get_sector_size(img, lba) == 2352) - return cdi_read_sector(img, b, 1, lba); - else - return cdi_read_sector_sub(img, b, lba); - default: - cdrom_image_log("CD-ROM %i: Unknown CD read type\n", dev->id); - return 0; + case CD_READ_DATA: + return cdi_read_sector(img, b, 0, lba); + case CD_READ_AUDIO: + return cdi_read_sector(img, b, 1, lba); + case CD_READ_RAW: + if (cdi_get_sector_size(img, lba) == 2352) + return cdi_read_sector(img, b, 1, lba); + else + return cdi_read_sector_sub(img, b, lba); + default: + cdrom_image_log("CD-ROM %i: Unknown CD read type\n", dev->id); + return 0; } } - static int image_track_type(cdrom_t *dev, uint32_t lba) { - cd_img_t *img = (cd_img_t *)dev->image; + cd_img_t *img = (cd_img_t *) dev->image; if (img) { - if (image_is_track_audio(dev, lba, 0)) - return CD_TRACK_AUDIO; - else { - if (cdi_is_mode2(img, lba)) - return CD_TRACK_MODE2 | cdi_get_mode2_form(img, lba); - } + if (image_is_track_audio(dev, lba, 0)) + return CD_TRACK_AUDIO; + else { + if (cdi_is_mode2(img, lba)) + return CD_TRACK_MODE2 | cdi_get_mode2_form(img, lba); + } } return 0; } - static void image_exit(cdrom_t *dev) { - cd_img_t *img = (cd_img_t *)dev->image; + cd_img_t *img = (cd_img_t *) dev->image; -cdrom_image_log("CDROM: image_exit(%s)\n", dev->image_path); + cdrom_image_log("CDROM: image_exit(%s)\n", dev->image_path); dev->cd_status = CD_STATUS_EMPTY; if (img) { - cdi_close(img); - dev->image = NULL; + cdi_close(img); + dev->image = NULL; } dev->ops = NULL; } - static const cdrom_ops_t cdrom_image_ops = { image_get_tracks, image_get_track_info, @@ -254,17 +244,16 @@ static const cdrom_ops_t cdrom_image_ops = { image_exit }; - static int image_open_abort(cdrom_t *dev) { cdrom_image_close(dev); - dev->ops = NULL; - dev->host_drive = 0; + dev->ops = NULL; + dev->host_drive = 0; + dev->image_path[0] = 0; return 1; } - int cdrom_image_open(cdrom_t *dev, const char *fn) { @@ -273,30 +262,32 @@ cdrom_image_open(cdrom_t *dev, const char *fn) /* Make sure to not STRCPY if the two are pointing at the same place. */ if (fn != dev->image_path) - strcpy(dev->image_path, fn); + strcpy(dev->image_path, fn); /* Create new instance of the CDROM_Image class. */ img = (cd_img_t *) malloc(sizeof(cd_img_t)); /* This guarantees that if ops is not NULL, then neither is the image pointer. */ - if (!img) - return image_open_abort(dev); + if (!img) + return image_open_abort(dev); memset(img, 0, sizeof(cd_img_t)); dev->image = img; /* Open the image. */ - if (!cdi_set_device(img, fn)) - return image_open_abort(dev); + int i = cdi_set_device(img, fn); + if (!i) + return image_open_abort(dev); /* All good, reset state. */ - if (! strcasecmp(plat_get_extension((char *) fn), "ISO")) - dev->cd_status = CD_STATUS_DATA_ONLY; + if (i >= 2) + dev->cd_status = CD_STATUS_DATA_ONLY; else - dev->cd_status = CD_STATUS_STOPPED; - dev->seek_pos = 0; - dev->cd_buflen = 0; + dev->cd_status = CD_STATUS_STOPPED; + dev->is_dir = (i == 3); + dev->seek_pos = 0; + dev->cd_buflen = 0; dev->cdrom_capacity = image_get_capacity(dev); cdrom_image_log("CD-ROM capacity: %i sectors (%" PRIi64 " bytes)\n", dev->cdrom_capacity, ((uint64_t) dev->cdrom_capacity) << 11ULL); @@ -306,12 +297,11 @@ cdrom_image_open(cdrom_t *dev, const char *fn) return 0; } - void cdrom_image_close(cdrom_t *dev) { cdrom_image_log("CDROM: image_close(%s)\n", dev->image_path); if (dev && dev->ops && dev->ops->exit) - dev->ops->exit(dev); + dev->ops->exit(dev); } diff --git a/src/cdrom/cdrom_image_backend.c b/src/cdrom/cdrom_image_backend.c index ae6e4bb39..151ddfe9f 100644 --- a/src/cdrom/cdrom_image_backend.c +++ b/src/cdrom/cdrom_image_backend.c @@ -1,60 +1,56 @@ /* - * 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. + * 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. + * This file is part of the 86Box distribution. * - * CD-ROM image file handling module, translated to C from - * cdrom_dosbox.cpp. + * CD-ROM image file handling module, translated to C from + * cdrom_dosbox.cpp. * * * - * Authors: Miran Grca, - * Fred N. van Kempen, - * The DOSBox Team, + * Authors: Miran Grca, + * Fred N. van Kempen, + * The DOSBox Team, * - * Copyright 2016-2020 Miran Grca. - * Copyright 2017-2020 Fred N. van Kempen. - * Copyright 2002-2020 The DOSBox Team. + * Copyright 2016-2020 Miran Grca. + * Copyright 2017-2020 Fred N. van Kempen. + * Copyright 2002-2020 The DOSBox Team. */ -#define _LARGEFILE_SOURCE -#define _LARGEFILE64_SOURCE #define __STDC_FORMAT_MACROS -#include -#include -#include -#include -#include -#include #include +#include +#include +#include +#include +#include +#include +#include #ifdef _WIN32 -# include +# include +# include #else -# include +# include #endif -#include #define HAVE_STDARG_H #include <86box/86box.h> +#include <86box/path.h> #include <86box/plat.h> #include <86box/cdrom_image_backend.h> +#define CDROM_BCD(x) (((x) % 10) | (((x) / 10) << 4)) -#define CDROM_BCD(x) (((x) % 10) | (((x) / 10) << 4)) - -#define MAX_LINE_LENGTH 512 -#define MAX_FILENAME_LENGTH 256 -#define CROSS_LEN 512 - - -static char temp_keyword[1024]; +#define MAX_LINE_LENGTH 512 +#define MAX_FILENAME_LENGTH 256 +#define CROSS_LEN 512 +static char temp_keyword[1024]; #ifdef ENABLE_CDROM_IMAGE_BACKEND_LOG int cdrom_image_backend_do_log = ENABLE_CDROM_IMAGE_BACKEND_LOG; - void cdrom_image_backend_log(const char *fmt, ...) { @@ -67,109 +63,117 @@ cdrom_image_backend_log(const char *fmt, ...) } } #else -#define cdrom_image_backend_log(fmt, ...) +# define cdrom_image_backend_log(fmt, ...) #endif - /* Binary file functions. */ static int -bin_read(void *p, uint8_t *buffer, uint64_t seek, size_t count) +bin_read(void *priv, uint8_t *buffer, uint64_t seek, size_t count) { - track_file_t *tf = (track_file_t *) p; + track_file_t *tf = (track_file_t *) priv; cdrom_image_backend_log("CDROM: binary_read(%08lx, pos=%" PRIu64 " count=%lu\n", - tf->file, seek, count); + tf->fp, seek, count); - if (tf->file == NULL) - return 0; + if (tf->fp == NULL) + return 0; - if (fseeko64(tf->file, seek, SEEK_SET) == -1) { + if (fseeko64(tf->fp, seek, SEEK_SET) == -1) { #ifdef ENABLE_CDROM_IMAGE_BACKEND_LOG - cdrom_image_backend_log("CDROM: binary_read failed during seek!\n"); + cdrom_image_backend_log("CDROM: binary_read failed during seek!\n"); #endif - return 0; + return 0; } - if (fread(buffer, count, 1, tf->file) != 1) { + if (fread(buffer, count, 1, tf->fp) != 1) { #ifdef ENABLE_CDROM_IMAGE_BACKEND_LOG - cdrom_image_backend_log("CDROM: binary_read failed during read!\n"); + cdrom_image_backend_log("CDROM: binary_read failed during read!\n"); #endif - return 0; + return 0; } return 1; } - static uint64_t -bin_get_length(void *p) +bin_get_length(void *priv) { - off64_t len; - track_file_t *tf = (track_file_t *) p; + off64_t len; + track_file_t *tf = (track_file_t *) priv; - cdrom_image_backend_log("CDROM: binary_length(%08lx)\n", tf->file); + cdrom_image_backend_log("CDROM: binary_length(%08lx)\n", tf->fp); - if (tf->file == NULL) - return 0; + if (tf->fp == NULL) + return 0; - fseeko64(tf->file, 0, SEEK_END); - len = ftello64(tf->file); - cdrom_image_backend_log("CDROM: binary_length(%08lx) = %" PRIu64 "\n", tf->file, len); + fseeko64(tf->fp, 0, SEEK_END); + len = ftello64(tf->fp); + cdrom_image_backend_log("CDROM: binary_length(%08lx) = %" PRIu64 "\n", tf->fp, len); return len; } - static void -bin_close(void *p) +bin_close(void *priv) { - track_file_t *tf = (track_file_t *) p; + track_file_t *tf = (track_file_t *) priv; if (tf == NULL) - return; + return; - if (tf->file != NULL) { - fclose(tf->file); - tf->file = NULL; + if (tf->fp != NULL) { + fclose(tf->fp); + tf->fp = NULL; } memset(tf->fn, 0x00, sizeof(tf->fn)); - free(p); + free(priv); } - static track_file_t * bin_init(const char *filename, int *error) { track_file_t *tf = (track_file_t *) malloc(sizeof(track_file_t)); + struct stat stats; if (tf == NULL) { - *error = 1; - return NULL; + *error = 1; + return NULL; } memset(tf->fn, 0x00, sizeof(tf->fn)); strncpy(tf->fn, filename, sizeof(tf->fn) - 1); - tf->file = plat_fopen64(tf->fn, "rb"); - cdrom_image_backend_log("CDROM: binary_open(%s) = %08lx\n", tf->fn, tf->file); + tf->fp = plat_fopen64(tf->fn, "rb"); + cdrom_image_backend_log("CDROM: binary_open(%s) = %08lx\n", tf->fn, tf->fp); - *error = (tf->file == NULL); + if (stat(tf->fn, &stats) != 0) { + /* Use a blank structure if stat failed. */ + memset(&stats, 0, sizeof(struct stat)); + } + *error = ((tf->fp == NULL) || ((stats.st_mode & S_IFMT) == S_IFDIR)); /* Set the function pointers. */ if (!*error) { - tf->read = bin_read; - tf->get_length = bin_get_length; - tf->close = bin_close; + tf->read = bin_read; + tf->get_length = bin_get_length; + tf->close = bin_close; } else { - free(tf); - tf = NULL; + /* From the check above, error may still be non-zero if opening a directory. + * The error is set for viso to try and open the directory following this function. + * However, we need to make sure the descriptor is closed. */ + if ((tf->fp != NULL) && ((stats.st_mode & S_IFMT) == S_IFDIR)) { + /* tf is freed by bin_close */ + bin_close(tf); + } else { + free(tf); + } + tf = NULL; } return tf; } - static track_file_t * track_file_init(const char *filename, int *error) { @@ -178,44 +182,41 @@ track_file_init(const char *filename, int *error) return bin_init(filename, error); } - static void track_file_close(track_t *trk) { if (trk == NULL) - return; + return; if (trk->file == NULL) - return; + return; if (trk->file->close == NULL) - return; + return; trk->file->close(trk->file); trk->file = NULL; } - /* Root functions. */ static void cdi_clear_tracks(cd_img_t *cdi) { - int i; - track_file_t *last = NULL; - track_t *cur = NULL; + const track_file_t *last = NULL; + track_t *cur = NULL; if ((cdi->tracks == NULL) || (cdi->tracks_num == 0)) - return; + return; - for (i = 0; i < cdi->tracks_num; i++) { - cur = &cdi->tracks[i]; + for (int i = 0; i < cdi->tracks_num; i++) { + cur = &cdi->tracks[i]; - /* Make sure we do not attempt to close a NULL file. */ - if (cur->file != last) { - last = cur->file; - track_file_close(cur); - } else - cur->file = NULL; + /* Make sure we do not attempt to close a NULL file. */ + if (cur->file != last) { + last = cur->file; + track_file_close(cur); + } else + cur->file = NULL; } /* Now free the array. */ @@ -226,7 +227,6 @@ cdi_clear_tracks(cd_img_t *cdi) cdi->tracks_num = 0; } - void cdi_close(cd_img_t *cdi) { @@ -234,130 +234,129 @@ cdi_close(cd_img_t *cdi) free(cdi); } - int cdi_set_device(cd_img_t *cdi, const char *path) { - if (cdi_load_cue(cdi, path)) - return 1; + int ret; - if (cdi_load_iso(cdi, path)) - return 1; + if ((ret = cdi_load_cue(cdi, path))) + return ret; + + if ((ret = cdi_load_iso(cdi, path))) + return ret; return 0; } - /* TODO: This never returns anything other than 1, should it even be an int? */ int cdi_get_audio_tracks(cd_img_t *cdi, int *st_track, int *end, TMSF *lead_out) { *st_track = 1; - *end = cdi->tracks_num - 1; + *end = cdi->tracks_num - 1; FRAMES_TO_MSF(cdi->tracks[*end].start + 150, &lead_out->min, &lead_out->sec, &lead_out->fr); return 1; } - /* TODO: This never returns anything other than 1, should it even be an int? */ int cdi_get_audio_tracks_lba(cd_img_t *cdi, int *st_track, int *end, uint32_t *lead_out) { *st_track = 1; - *end = cdi->tracks_num - 1; + *end = cdi->tracks_num - 1; *lead_out = cdi->tracks[*end].start; return 1; } - int cdi_get_audio_track_pre(cd_img_t *cdi, int track) { - track_t *trk = &cdi->tracks[track - 1]; + const track_t *trk = &cdi->tracks[track - 1]; if ((track < 1) || (track > cdi->tracks_num)) - return 0; + return 0; return trk->pre; } - /* This replaces both Info and EndInfo, they are specified by a variable. */ int -cdi_get_audio_track_info(cd_img_t *cdi, int end, int track, int *track_num, TMSF *start, uint8_t *attr) +cdi_get_audio_track_info(cd_img_t *cdi, UNUSED(int end), int track, int *track_num, TMSF *start, uint8_t *attr) { - track_t *trk = &cdi->tracks[track - 1]; - int pos = trk->start + 150; + const track_t *trk = &cdi->tracks[track - 1]; + int pos = trk->start + 150; if ((track < 1) || (track > cdi->tracks_num)) - return 0; + return 0; pos = trk->start + 150; FRAMES_TO_MSF(pos, &start->min, &start->sec, &start->fr); *track_num = trk->track_number; - *attr = trk->attr; + *attr = trk->attr; return 1; } - int -cdi_get_audio_track_info_lba(cd_img_t *cdi, int end, int track, int *track_num, uint32_t *start, uint8_t *attr) +cdi_get_audio_track_info_lba(cd_img_t *cdi, UNUSED(int end), int track, int *track_num, uint32_t *start, uint8_t *attr) { - track_t *trk = &cdi->tracks[track - 1]; + const track_t *trk = &cdi->tracks[track - 1]; if ((track < 1) || (track > cdi->tracks_num)) - return 0; + return 0; *start = (uint32_t) trk->start; *track_num = trk->track_number; - *attr = trk->attr; + *attr = trk->attr; return 1; } - int cdi_get_track(cd_img_t *cdi, uint32_t sector) { - int i; - track_t *cur, *next; + const track_t *cur; + const track_t *next; /* There must be at least two tracks - data and lead out. */ if (cdi->tracks_num < 2) - return -1; + return -1; /* This has a problem - the code skips the last track, which is lead out - is that correct? */ - for (i = 0; i < (cdi->tracks_num - 1); i++) { - cur = &cdi->tracks[i]; - next = &cdi->tracks[i + 1]; - if ((cur->start <= sector) && (sector < next->start)) - return cur->number; + for (int i = 0; i < (cdi->tracks_num - 1); i++) { + cur = &cdi->tracks[i]; + next = &cdi->tracks[i + 1]; + + /* Take into account cue sheets that do not start on sector 0. */ + if ((i == 0) && (sector < cur->start)) + return cur->number; + + if ((cur->start <= sector) && (sector < next->start)) + return cur->number; } return -1; } - /* TODO: See if track start is adjusted by 150 or not. */ int cdi_get_audio_sub(cd_img_t *cdi, uint32_t sector, uint8_t *attr, uint8_t *track, uint8_t *index, TMSF *rel_pos, TMSF *abs_pos) { - int cur_track = cdi_get_track(cdi, sector); - track_t *trk; + int cur_track = cdi_get_track(cdi, sector); + const track_t *trk; if (cur_track < 1) - return 0; + return 0; *track = (uint8_t) cur_track; - trk = &cdi->tracks[*track - 1]; - *attr = trk->attr; + trk = &cdi->tracks[*track - 1]; + *attr = trk->attr; *index = 1; FRAMES_TO_MSF(sector + 150, &abs_pos->min, &abs_pos->sec, &abs_pos->fr); @@ -368,86 +367,96 @@ cdi_get_audio_sub(cd_img_t *cdi, uint32_t sector, uint8_t *attr, uint8_t *track, return 1; } - int cdi_read_sector(cd_img_t *cdi, uint8_t *buffer, int raw, uint32_t sector) { - size_t length; - int track = cdi_get_track(cdi, sector) - 1; - uint64_t sect = (uint64_t) sector, seek; + size_t length; + int track = cdi_get_track(cdi, sector) - 1; + uint64_t sect = (uint64_t) sector; + uint64_t seek; track_t *trk; - int track_is_raw, ret; - int raw_size, cooked_size; + int track_is_raw; + int ret; + int raw_size; + int cooked_size; uint64_t offset = 0ULL; - int m = 0, s = 0, f = 0; + int m = 0; + int s = 0; + int f = 0; if (track < 0) - return 0; + return 0; - trk = &cdi->tracks[track]; + trk = &cdi->tracks[track]; track_is_raw = ((trk->sector_size == RAW_SECTOR_SIZE) || (trk->sector_size == 2448)); seek = trk->skip + ((sect - trk->start) * trk->sector_size); if (track_is_raw) - raw_size = trk->sector_size; + raw_size = trk->sector_size; else - raw_size = 2448; + raw_size = 2448; if (trk->mode2 && (trk->form != 1)) { - if (trk->form == 2) - cooked_size = (track_is_raw ? 2328 : trk->sector_size); /* Both 2324 + ECC and 2328 variants are valid. */ - else - cooked_size = 2336; + if (trk->form == 2) + cooked_size = (track_is_raw ? 2328 : trk->sector_size); /* Both 2324 + ECC and 2328 variants are valid. */ + else + cooked_size = 2336; } else - cooked_size = COOKED_SECTOR_SIZE; + cooked_size = COOKED_SECTOR_SIZE; length = (raw ? raw_size : cooked_size); if (trk->mode2 && (trk->form >= 1)) - offset = 24ULL; + offset = 24ULL; else - offset = 16ULL; + offset = 16ULL; if (raw && !track_is_raw) { - memset(buffer, 0x00, 2448); - ret = trk->file->read(trk->file, buffer + offset, seek, length); - if (!ret) - return 0; - /* Construct the rest of the raw sector. */ - memset(buffer + 1, 0xff, 10); - buffer += 12; - FRAMES_TO_MSF(sector + 150, &m, &s, &f); - /* These have to be BCD. */ - buffer[12] = CDROM_BCD(m & 0xff); - buffer[13] = CDROM_BCD(s & 0xff); - buffer[14] = CDROM_BCD(f & 0xff); - buffer[15] = trk->mode2 ? 2 : 1; /* Data, should reflect the actual sector type. */ - return 1; + memset(buffer, 0x00, 2448); + ret = trk->file->read(trk->file, buffer + offset, seek, length); + if (!ret) + return 0; + /* Construct the rest of the raw sector. */ + memset(buffer + 1, 0xff, 10); + buffer += 12; + FRAMES_TO_MSF(sector + 150, &m, &s, &f); + /* These have to be BCD. */ + buffer[12] = CDROM_BCD(m & 0xff); + buffer[13] = CDROM_BCD(s & 0xff); + buffer[14] = CDROM_BCD(f & 0xff); + /* Data, should reflect the actual sector type. */ + buffer[15] = trk->mode2 ? 2 : 1; + return 1; } else if (!raw && track_is_raw) - return trk->file->read(trk->file, buffer, seek + offset, length); - else - return trk->file->read(trk->file, buffer, seek, length); + return trk->file->read(trk->file, buffer, seek + offset, length); + else { + return trk->file->read(trk->file, buffer, seek, length); + } } - int cdi_read_sectors(cd_img_t *cdi, uint8_t *buffer, int raw, uint32_t sector, uint32_t num) { - int sector_size, success = 1; + int sector_size; + int success = 1; uint8_t *buf; - uint32_t buf_len, i; + uint32_t buf_len; - /* TODO: This fails to account for Mode 2. Shouldn't we have a function - to get sector size? */ + /* TODO: This fails to account for Mode 2. Shouldn't we have a function + to get sector size? */ sector_size = raw ? RAW_SECTOR_SIZE : COOKED_SECTOR_SIZE; - buf_len = num * sector_size; - buf = (uint8_t *) malloc(buf_len * sizeof(uint8_t)); + buf_len = num * sector_size; + buf = (uint8_t *) malloc(buf_len * sizeof(uint8_t)); - for (i = 0; i < num; i++) { - success = cdi_read_sector(cdi, &buf[i * sector_size], raw, sector + i); - if (!success) - break; + for (uint32_t i = 0; i < num; i++) { + success = cdi_read_sector(cdi, &buf[i * sector_size], raw, sector + i); + if (!success) + break; + /* Based on the DOSBox patch, but check all 8 bytes and makes sure it's not an + audio track. */ + if (raw && sector < cdi->tracks[0].length && !cdi->tracks[0].mode2 && (cdi->tracks[0].attr != AUDIO_TRACK) && *(uint64_t *) &(buf[i * sector_size + 2068])) + return 0; } memcpy((void *) buffer, buf, buf_len); @@ -457,89 +466,83 @@ cdi_read_sectors(cd_img_t *cdi, uint8_t *buffer, int raw, uint32_t sector, uint3 return success; } - /* TODO: Do CUE+BIN images with a sector size of 2448 even exist? */ int cdi_read_sector_sub(cd_img_t *cdi, uint8_t *buffer, uint32_t sector) { - int track = cdi_get_track(cdi, sector) - 1; + int track = cdi_get_track(cdi, sector) - 1; track_t *trk; - uint64_t s = (uint64_t) sector, seek; + uint64_t s = (uint64_t) sector; + uint64_t seek; if (track < 0) - return 0; + return 0; - trk = &cdi->tracks[track]; + trk = &cdi->tracks[track]; seek = trk->skip + ((s - trk->start) * trk->sector_size); if (trk->sector_size != 2448) - return 0; + return 0; return trk->file->read(trk->file, buffer, seek, 2448); } - int cdi_get_sector_size(cd_img_t *cdi, uint32_t sector) { - int track = cdi_get_track(cdi, sector) - 1; - track_t *trk; + int track = cdi_get_track(cdi, sector) - 1; + const track_t *trk; if (track < 0) - return 0; + return 0; trk = &cdi->tracks[track]; return trk->sector_size; } - int cdi_is_mode2(cd_img_t *cdi, uint32_t sector) { - int track = cdi_get_track(cdi, sector) - 1; - track_t *trk; + int track = cdi_get_track(cdi, sector) - 1; + const track_t *trk; if (track < 0) - return 0; + return 0; trk = &cdi->tracks[track]; return !!(trk->mode2); } - int cdi_get_mode2_form(cd_img_t *cdi, uint32_t sector) { - int track = cdi_get_track(cdi, sector) - 1; - track_t *trk; + int track = cdi_get_track(cdi, sector) - 1; + const track_t *trk; if (track < 0) - return 0; + return 0; trk = &cdi->tracks[track]; return trk->form; } - static int cdi_can_read_pvd(track_file_t *file, uint64_t sector_size, int mode2, int form) { - uint8_t pvd[COOKED_SECTOR_SIZE]; - uint64_t seek = 16ULL * sector_size; /* First VD is located at sector 16. */ + uint8_t pvd[COOKED_SECTOR_SIZE]; + uint64_t seek = 16ULL * sector_size; /* First VD is located at sector 16. */ if ((!mode2 || (form == 0)) && (sector_size == RAW_SECTOR_SIZE)) - seek += 16; + seek += 16; if (mode2 && (form >= 1)) - seek += 24; + seek += 24; file->read(file, pvd, seek, COOKED_SECTOR_SIZE); - return ((pvd[0] == 1 && !strncmp((char*)(&pvd[1]), "CD001", 5) && pvd[6] == 1) || - (pvd[8] == 1 && !strncmp((char*)(&pvd[9]), "CDROM", 5) && pvd[14] == 1)); + return ((pvd[0] == 1 && !strncmp((char *) (&pvd[1]), "CD001", 5) && pvd[6] == 1) || (pvd[8] == 1 && !strncmp((char *) (&pvd[9]), "CDROM", 5) && pvd[14] == 1)); } - /* This reallocates the array and returns the pointer to the last track. */ static void cdi_track_push_back(cd_img_t *cdi, track_t *trk) @@ -547,23 +550,23 @@ cdi_track_push_back(cd_img_t *cdi, track_t *trk) /* This has to be done so situations in which realloc would misbehave can be detected and reported to the user. */ if ((cdi->tracks != NULL) && (cdi->tracks_num == 0)) - fatal("CD-ROM Image: Non-null tracks array at 0 loaded tracks\n"); + fatal("CD-ROM Image: Non-null tracks array at 0 loaded tracks\n"); if ((cdi->tracks == NULL) && (cdi->tracks_num != 0)) - fatal("CD-ROM Image: Null tracks array at non-zero loaded tracks\n"); + fatal("CD-ROM Image: Null tracks array at non-zero loaded tracks\n"); cdi->tracks = realloc(cdi->tracks, (cdi->tracks_num + 1) * sizeof(track_t)); memcpy(&(cdi->tracks[cdi->tracks_num]), trk, sizeof(track_t)); cdi->tracks_num++; } - int cdi_load_iso(cd_img_t *cdi, const char *filename) { - int error; + int error; + int ret = 2; track_t trk; - cdi->tracks = NULL; + cdi->tracks = NULL; cdi->tracks_num = 0; memset(&trk, 0, sizeof(track_t)); @@ -571,33 +574,39 @@ cdi_load_iso(cd_img_t *cdi, const char *filename) /* Data track (shouldn't there be a lead in track?). */ trk.file = bin_init(filename, &error); if (error) { - if ((trk.file != NULL) && (trk.file->close != NULL)) - trk.file->close(trk.file); - return 0; + if ((trk.file != NULL) && (trk.file->close != NULL)) + trk.file->close(trk.file); + ret = 3; + trk.file = viso_init(filename, &error); + if (error) { + if ((trk.file != NULL) && (trk.file->close != NULL)) + trk.file->close(trk.file); + return 0; + } } - trk.number = 1; + trk.number = 1; trk.track_number = 1; - trk.attr = DATA_TRACK; + trk.attr = DATA_TRACK; /* Try to detect ISO type. */ - trk.form = 0; + trk.form = 0; trk.mode2 = 0; /* TODO: Merge the first and last cases since they result in the same thing. */ if (cdi_can_read_pvd(trk.file, RAW_SECTOR_SIZE, 0, 0)) - trk.sector_size = RAW_SECTOR_SIZE; + trk.sector_size = RAW_SECTOR_SIZE; else if (cdi_can_read_pvd(trk.file, 2336, 1, 0)) { - trk.sector_size = 2336; - trk.mode2 = 1; + trk.sector_size = 2336; + trk.mode2 = 1; } else if (cdi_can_read_pvd(trk.file, 2324, 1, 2)) { - trk.sector_size = 2324; - trk.mode2 = 1; - trk.form = 2; + trk.sector_size = 2324; + trk.mode2 = 1; + trk.form = 2; } else if (cdi_can_read_pvd(trk.file, RAW_SECTOR_SIZE, 1, 0)) { - trk.sector_size = RAW_SECTOR_SIZE; - trk.mode2 = 1; + trk.sector_size = RAW_SECTOR_SIZE; + trk.mode2 = 1; } else { - /* We use 2048 mode 1 as the default. */ - trk.sector_size = COOKED_SECTOR_SIZE; + /* We use 2048 mode 1 as the default. */ + trk.sector_size = COOKED_SECTOR_SIZE; } trk.length = trk.file->get_length(trk.file) / trk.sector_size; @@ -605,64 +614,63 @@ cdi_load_iso(cd_img_t *cdi, const char *filename) cdi_track_push_back(cdi, &trk); /* Lead out track. */ - trk.number = 2; + trk.number = 2; trk.track_number = 0xAA; - trk.attr = 0x16; /* Was originally 0x00, but I believe 0x16 is appropriate. */ - trk.start = trk.length; - trk.length = 0; - trk.file = NULL; + trk.attr = 0x16; /* Was originally 0x00, but I believe 0x16 is appropriate. */ + trk.start = trk.length; + trk.length = 0; + trk.file = NULL; cdi_track_push_back(cdi, &trk); - return 1; + return ret; } - static int cdi_cue_get_buffer(char *str, char **line, int up) { - char *s = *line; - char *p = str; - int quote = 0; - int done = 0; - int space = 1; + char *s = *line; + char *p = str; + int quote = 0; + int done = 0; + int space = 1; /* Copy to local buffer until we have end of string or whitespace. */ - while (! done) { - switch(*s) { - case '\0': - if (quote) { - /* Ouch, unterminated string.. */ - return 0; - } - done = 1; - break; + while (!done) { + switch (*s) { + case '\0': + if (quote) { + /* Ouch, unterminated string.. */ + return 0; + } + done = 1; + break; - case '\"': - quote ^= 1; - break; + case '\"': + quote ^= 1; + break; - case ' ': - case '\t': - if (space) - break; + case ' ': + case '\t': + if (space) + break; - if (! quote) { - done = 1; - break; - } - /*FALLTHROUGH*/ + if (!quote) { + done = 1; + break; + } + fallthrough; - default: - if (up && islower((int) *s)) - *p++ = toupper((int) *s); - else - *p++ = *s; - space = 0; - break; - } + default: + if (up && islower((int) *s)) + *p++ = toupper((int) *s); + else + *p++ = *s; + space = 0; + break; + } - if (! done) - s++; + if (!done) + s++; } *p = '\0'; @@ -671,7 +679,6 @@ cdi_cue_get_buffer(char *str, char **line, int up) return 1; } - static int cdi_cue_get_keyword(char **dest, char **line) { @@ -679,394 +686,401 @@ cdi_cue_get_keyword(char **dest, char **line) success = cdi_cue_get_buffer(temp_keyword, line, 1); if (success) - *dest = temp_keyword; + *dest = temp_keyword; return success; } - /* Get a string from the input line, handling quotes properly. */ static uint64_t cdi_cue_get_number(char **line) { - char temp[128]; + char temp[128]; uint64_t num; if (!cdi_cue_get_buffer(temp, line, 0)) - return 0; + return 0; if (sscanf(temp, "%" PRIu64, &num) != 1) - return 0; + return 0; return num; } - static int cdi_cue_get_frame(uint64_t *frames, char **line) { char temp[128]; - int min, sec, fr; - int success; + int min; + int sec; + int fr; + int success; success = cdi_cue_get_buffer(temp, line, 0); - if (! success) return 0; + if (!success) + return 0; success = sscanf(temp, "%d:%d:%d", &min, &sec, &fr) == 3; - if (! success) return 0; + if (!success) + return 0; *frames = MSF_TO_FRAMES(min, sec, fr); return 1; } - static int cdi_cue_get_flags(track_t *cur, char **line) { - char temp[128], temp2[128]; - int success; + char temp[128]; + char temp2[128]; + int success; success = cdi_cue_get_buffer(temp, line, 0); - if (! success) return 0; + if (!success) + return 0; memset(temp2, 0x00, sizeof(temp2)); success = sscanf(temp, "%s", temp2) == 1; - if (! success) return 0; + if (!success) + return 0; cur->pre = (strstr(temp2, "PRE") != NULL); return 1; } - static int cdi_add_track(cd_img_t *cdi, track_t *cur, uint64_t *shift, uint64_t prestart, uint64_t *total_pregap, uint64_t cur_pregap) { /* Frames between index 0 (prestart) and 1 (current track start) must be skipped. */ - uint64_t skip, temp; + uint64_t skip; + uint64_t temp; track_t *prev = NULL; /* Skip *MUST* be calculated even if prestart is 0. */ if (prestart >= 0) { - if (prestart > cur->start) - return 0; - skip = cur->start - prestart; + if (prestart > cur->start) + return 0; + skip = cur->start - prestart; } else - skip = 0ULL; + skip = 0ULL; if ((cdi->tracks != NULL) && (cdi->tracks_num != 0)) - prev = &cdi->tracks[cdi->tracks_num - 1]; + prev = &cdi->tracks[cdi->tracks_num - 1]; else if ((cdi->tracks == NULL) && (cdi->tracks_num != 0)) { - fatal("NULL cdi->tracks with non-zero cdi->tracks_num\n"); - return 0; + fatal("NULL cdi->tracks with non-zero cdi->tracks_num\n"); + return 0; } /* First track (track number must be 1). */ - if (cdi->tracks_num == 0) { - /* I guess this makes sure the structure is not filled with invalid data. */ - if (cur->number != 1) - return 0; - cur->skip = skip * cur->sector_size; - cur->start += cur_pregap; - *total_pregap = cur_pregap; - cdi_track_push_back(cdi, cur); - return 1; + if ((prev == NULL) || (cdi->tracks_num == 0)) { + /* I guess this makes sure the structure is not filled with invalid data. */ + if (cur->number != 1) + return 0; + cur->skip = skip * cur->sector_size; + cur->start += cur_pregap; + *total_pregap = cur_pregap; + cdi_track_push_back(cdi, cur); + return 1; } /* Current track consumes data from the same file as the previous. */ if (prev->file == cur->file) { - cur->start += *shift; - prev->length = cur->start + *total_pregap - prev->start - skip; - cur->skip += prev->skip + (prev->length * prev->sector_size) + (skip * cur->sector_size); - *total_pregap += cur_pregap; - cur->start += *total_pregap; + cur->start += *shift; + prev->length = cur->start + *total_pregap - prev->start - skip; + cur->skip += prev->skip + (prev->length * prev->sector_size) + (skip * cur->sector_size); + *total_pregap += cur_pregap; + cur->start += *total_pregap; } else { - temp = prev->file->get_length(prev->file) - ((uint64_t) prev->skip); - prev->length = temp / ((uint64_t) prev->sector_size); - if ((temp % prev->sector_size) != 0) - prev->length++; /* Padding. */ + temp = prev->file->get_length(prev->file) - (prev->skip); + prev->length = temp / ((uint64_t) prev->sector_size); + if ((temp % prev->sector_size) != 0) + prev->length++; + /* Padding. */ - cur->start += prev->start + prev->length + cur_pregap; - cur->skip = skip * cur->sector_size; - *shift += prev->start + prev->length; - *total_pregap = cur_pregap; + cur->start += prev->start + prev->length + cur_pregap; + cur->skip = skip * cur->sector_size; + *shift += prev->start + prev->length; + *total_pregap = cur_pregap; } /* Error checks. */ if (cur->number <= 1) - return 0; + return 0; if ((prev->number + 1) != cur->number) - return 0; + return 0; if (cur->start < (prev->start + prev->length)) - return 0; + return 0; cdi_track_push_back(cdi, cur); return 1; } - int cdi_load_cue(cd_img_t *cdi, const char *cuefile) { - track_t trk; - char pathname[MAX_FILENAME_LENGTH], filename[MAX_FILENAME_LENGTH]; - char temp[MAX_FILENAME_LENGTH]; - uint64_t shift = 0ULL, prestart = 0ULL; - uint64_t cur_pregap = 0ULL, total_pregap = 0ULL; - uint64_t frame = 0ULL, index; - int i, success; - int error, can_add_track = 0; - FILE *fp; - char buf[MAX_LINE_LENGTH], ansi[MAX_FILENAME_LENGTH]; - char *line, *command; - char *type; + track_t trk; + char pathname[MAX_FILENAME_LENGTH]; + char filename[MAX_FILENAME_LENGTH]; + char temp[MAX_FILENAME_LENGTH]; + uint64_t shift = 0ULL; + uint64_t prestart = 0ULL; + uint64_t cur_pregap = 0ULL; + uint64_t total_pregap = 0ULL; + uint64_t frame = 0ULL; + uint64_t index; + int success; + int error; + int can_add_track = 0; + FILE *fp; + char buf[MAX_LINE_LENGTH]; + char ansi[MAX_FILENAME_LENGTH]; + char *line; + char *command; + char *type; - cdi->tracks = NULL; + cdi->tracks = NULL; cdi->tracks_num = 0; memset(&trk, 0, sizeof(track_t)); /* Get a copy of the filename into pathname, we need it later. */ memset(pathname, 0, MAX_FILENAME_LENGTH * sizeof(char)); - plat_get_dirname(pathname, cuefile); + path_get_dirname(pathname, cuefile); /* Open the file. */ fp = plat_fopen(cuefile, "r"); if (fp == NULL) - return 0; + return 0; success = 0; for (;;) { - line = buf; + line = buf; - /* Read a line from the cuesheet file. */ - if (feof(fp) || fgets(buf, sizeof(buf), fp) == NULL || ferror(fp)) - break; + /* Read a line from the cuesheet file. */ + if (feof(fp) || fgets(buf, sizeof(buf), fp) == NULL || ferror(fp)) + break; - /* Do two iterations to make sure to nuke even if it's \r\n or \n\r, - but do checks to make sure we're not nuking other bytes. */ - for (i = 0; i < 2; i++) { - if (strlen(buf) > 0) { - if (buf[strlen(buf) - 1] == '\n') - buf[strlen(buf) - 1] = '\0'; /* nuke trailing newline */ - else if (buf[strlen(buf) - 1] == '\r') - buf[strlen(buf) - 1] = '\0'; /* nuke trailing newline */ - } - } + /* Do two iterations to make sure to nuke even if it's \r\n or \n\r, + but do checks to make sure we're not nuking other bytes. */ + for (uint8_t i = 0; i < 2; i++) { + if (strlen(buf) > 0) { + if (buf[strlen(buf) - 1] == '\n') + buf[strlen(buf) - 1] = '\0'; + /* nuke trailing newline */ + else if (buf[strlen(buf) - 1] == '\r') + buf[strlen(buf) - 1] = '\0'; + /* nuke trailing newline */ + } + } - success = cdi_cue_get_keyword(&command, &line); + success = cdi_cue_get_keyword(&command, &line); - if (!strcmp(command, "TRACK")) { - if (can_add_track) - success = cdi_add_track(cdi, &trk, &shift, prestart, &total_pregap, cur_pregap); - else - success = 1; - if (!success) - break; + if (!strcmp(command, "TRACK")) { + if (can_add_track) + success = cdi_add_track(cdi, &trk, &shift, prestart, &total_pregap, cur_pregap); + else + success = 1; + if (!success) + break; - trk.start = 0; - trk.skip = 0; - cur_pregap = 0; - prestart = 0; + trk.start = 0; + trk.skip = 0; + cur_pregap = 0; + prestart = 0; - trk.number = cdi_cue_get_number(&line); - trk.track_number = trk.number; - success = cdi_cue_get_keyword(&type, &line); - if (!success) - break; + trk.number = cdi_cue_get_number(&line); + trk.track_number = trk.number; + success = cdi_cue_get_keyword(&type, &line); + if (!success) + break; - trk.form = 0; - trk.mode2 = 0; + trk.form = 0; + trk.mode2 = 0; - trk.pre = 0; + trk.pre = 0; - if (!strcmp(type, "AUDIO")) { - trk.sector_size = RAW_SECTOR_SIZE; - trk.attr = AUDIO_TRACK; - } else if (!strcmp(type, "MODE1/2048")) { - trk.sector_size = COOKED_SECTOR_SIZE; - trk.attr = DATA_TRACK; - } else if (!strcmp(type, "MODE1/2352")) { - trk.sector_size = RAW_SECTOR_SIZE; - trk.attr = DATA_TRACK; - } else if (!strcmp(type, "MODE1/2448")) { - trk.sector_size = 2448; - trk.attr = DATA_TRACK; - } else if (!strcmp(type, "MODE2/2048")) { - trk.form = 1; - trk.sector_size = COOKED_SECTOR_SIZE; - trk.attr = DATA_TRACK; - trk.mode2 = 1; - } else if (!strcmp(type, "MODE2/2324")) { - trk.form = 2; - trk.sector_size = 2324; - trk.attr = DATA_TRACK; - trk.mode2 = 1; - } else if (!strcmp(type, "MODE2/2328")) { - trk.form = 2; - trk.sector_size = 2328; - trk.attr = DATA_TRACK; - trk.mode2 = 1; - } else if (!strcmp(type, "MODE2/2336")) { - trk.sector_size = 2336; - trk.attr = DATA_TRACK; - trk.mode2 = 1; - } else if (!strcmp(type, "MODE2/2352")) { - trk.form = 1; /* Assume this is XA Mode 2 Form 1. */ - trk.sector_size = RAW_SECTOR_SIZE; - trk.attr = DATA_TRACK; - trk.mode2 = 1; - } else if (!strcmp(type, "MODE2/2448")) { - trk.form = 1; /* Assume this is XA Mode 2 Form 1. */ - trk.sector_size = 2448; - trk.attr = DATA_TRACK; - trk.mode2 = 1; - } else if (!strcmp(type, "CDG/2448")) { - trk.sector_size = 2448; - trk.attr = DATA_TRACK; - trk.mode2 = 1; - } else if (!strcmp(type, "CDI/2336")) { - trk.sector_size = 2336; - trk.attr = DATA_TRACK; - trk.mode2 = 1; - } else if (!strcmp(type, "CDI/2352")) { - trk.sector_size = RAW_SECTOR_SIZE; - trk.attr = DATA_TRACK; - trk.mode2 = 1; - } else - success = 0; + if (!strcmp(type, "AUDIO")) { + trk.sector_size = RAW_SECTOR_SIZE; + trk.attr = AUDIO_TRACK; + } else if (!strcmp(type, "MODE1/2048")) { + trk.sector_size = COOKED_SECTOR_SIZE; + trk.attr = DATA_TRACK; + } else if (!strcmp(type, "MODE1/2352")) { + trk.sector_size = RAW_SECTOR_SIZE; + trk.attr = DATA_TRACK; + } else if (!strcmp(type, "MODE1/2448")) { + trk.sector_size = 2448; + trk.attr = DATA_TRACK; + } else if (!strcmp(type, "MODE2/2048")) { + trk.form = 1; + trk.sector_size = COOKED_SECTOR_SIZE; + trk.attr = DATA_TRACK; + trk.mode2 = 1; + } else if (!strcmp(type, "MODE2/2324")) { + trk.form = 2; + trk.sector_size = 2324; + trk.attr = DATA_TRACK; + trk.mode2 = 1; + } else if (!strcmp(type, "MODE2/2328")) { + trk.form = 2; + trk.sector_size = 2328; + trk.attr = DATA_TRACK; + trk.mode2 = 1; + } else if (!strcmp(type, "MODE2/2336")) { + trk.sector_size = 2336; + trk.attr = DATA_TRACK; + trk.mode2 = 1; + } else if (!strcmp(type, "MODE2/2352")) { + /* Assume this is XA Mode 2 Form 1. */ + trk.form = 1; + trk.sector_size = RAW_SECTOR_SIZE; + trk.attr = DATA_TRACK; + trk.mode2 = 1; + } else if (!strcmp(type, "MODE2/2448")) { + /* Assume this is XA Mode 2 Form 1. */ + trk.form = 1; + trk.sector_size = 2448; + trk.attr = DATA_TRACK; + trk.mode2 = 1; + } else if (!strcmp(type, "CDG/2448")) { + trk.sector_size = 2448; + trk.attr = DATA_TRACK; + trk.mode2 = 1; + } else if (!strcmp(type, "CDI/2336")) { + trk.sector_size = 2336; + trk.attr = DATA_TRACK; + trk.mode2 = 1; + } else if (!strcmp(type, "CDI/2352")) { + trk.sector_size = RAW_SECTOR_SIZE; + trk.attr = DATA_TRACK; + trk.mode2 = 1; + } else + success = 0; - can_add_track = 1; - } else if (!strcmp(command, "INDEX")) { - index = cdi_cue_get_number(&line); - success = cdi_cue_get_frame(&frame, &line); + can_add_track = 1; + } else if (!strcmp(command, "INDEX")) { + index = cdi_cue_get_number(&line); + success = cdi_cue_get_frame(&frame, &line); - switch(index) { - case 0: - prestart = frame; - break; + switch (index) { + case 0: + prestart = frame; + break; - case 1: - trk.start = frame; - break; + case 1: + trk.start = frame; + break; - default: - /* ignore other indices */ - break; - } - } else if (!strcmp(command, "FILE")) { - if (can_add_track) - success = cdi_add_track(cdi, &trk, &shift, prestart, &total_pregap, cur_pregap); - else - success = 1; - if (!success) - break; - can_add_track = 0; + default: + /* Ignore other indices. */ + break; + } + } else if (!strcmp(command, "FILE")) { + if (can_add_track) + success = cdi_add_track(cdi, &trk, &shift, prestart, &total_pregap, cur_pregap); + else + success = 1; + if (!success) + break; + can_add_track = 0; - memset(ansi, 0, MAX_FILENAME_LENGTH * sizeof(char)); - memset(filename, 0, MAX_FILENAME_LENGTH * sizeof(char)); + memset(ansi, 0, MAX_FILENAME_LENGTH * sizeof(char)); + memset(filename, 0, MAX_FILENAME_LENGTH * sizeof(char)); - success = cdi_cue_get_buffer(ansi, &line, 0); - if (!success) - break; - success = cdi_cue_get_keyword(&type, &line); - if (!success) - break; + success = cdi_cue_get_buffer(ansi, &line, 0); + if (!success) + break; + success = cdi_cue_get_keyword(&type, &line); + if (!success) + break; - trk.file = NULL; - error = 1; + trk.file = NULL; + error = 1; - if (!strcmp(type, "BINARY")) { - memset(temp, 0, MAX_FILENAME_LENGTH * sizeof(char)); - plat_append_filename(filename, pathname, ansi); - trk.file = track_file_init(filename, &error); - } - if (error) { + if (!strcmp(type, "BINARY")) { + memset(temp, 0, MAX_FILENAME_LENGTH * sizeof(char)); + path_append_filename(filename, pathname, ansi); + trk.file = track_file_init(filename, &error); + } + if (error) { #ifdef ENABLE_CDROM_IMAGE_BACKEND_LOG - cdrom_image_backend_log("CUE: cannot open fille '%s' in cue sheet!\n", - filename); + cdrom_image_backend_log("CUE: cannot open fille '%s' in cue sheet!\n", + filename); #endif - if (trk.file != NULL) { - trk.file->close(trk.file); - trk.file = NULL; - } - success = 0; - } - } else if (!strcmp(command, "PREGAP")) - success = cdi_cue_get_frame(&cur_pregap, &line); - else if (!strcmp(command, "FLAGS")) - success = cdi_cue_get_flags(&trk, &line); - else if (!strcmp(command, "CATALOG") || !strcmp(command, "CDTEXTFILE") || !strcmp(command, "ISRC") || - !strcmp(command, "PERFORMER") || !strcmp(command, "POSTGAP") || !strcmp(command, "REM") || - !strcmp(command, "SONGWRITER") || !strcmp(command, "TITLE") || !strcmp(command, "")) { - /* Ignored commands. */ - success = 1; - } else { + if (trk.file != NULL) { + trk.file->close(trk.file); + trk.file = NULL; + } + success = 0; + } + } else if (!strcmp(command, "PREGAP")) + success = cdi_cue_get_frame(&cur_pregap, &line); + else if (!strcmp(command, "FLAGS")) + success = cdi_cue_get_flags(&trk, &line); + else if (!strcmp(command, "CATALOG") || !strcmp(command, "CDTEXTFILE") || !strcmp(command, "ISRC") || !strcmp(command, "PERFORMER") || !strcmp(command, "POSTGAP") || !strcmp(command, "REM") || !strcmp(command, "SONGWRITER") || !strcmp(command, "TITLE") || !strcmp(command, "")) { + /* Ignored commands. */ + success = 1; + } else { #ifdef ENABLE_CDROM_IMAGE_BACKEND_LOG - cdrom_image_backend_log("CUE: unsupported command '%s' in cue sheet!\n", command); + cdrom_image_backend_log("CUE: unsupported command '%s' in cue sheet!\n", command); #endif - success = 0; - } + success = 0; + } - if (!success) - break; + if (!success) + break; } fclose(fp); if (!success) - return 0; + return 0; /* Add last track. */ if (!cdi_add_track(cdi, &trk, &shift, prestart, &total_pregap, cur_pregap)) - return 0; + return 0; /* Add lead out track. */ trk.number++; trk.track_number = 0xAA; - trk.attr = 0x16; /* Was 0x00 but I believe 0x16 is appropriate. */ - trk.start = 0; - trk.length = 0; - trk.file = NULL; + trk.attr = 0x16; /* Was 0x00 but I believe 0x16 is appropriate. */ + trk.start = 0; + trk.length = 0; + trk.file = NULL; if (!cdi_add_track(cdi, &trk, &shift, 0, &total_pregap, 0)) - return 0; + return 0; return 1; } - int cdi_has_data_track(cd_img_t *cdi) { - int i; - if ((cdi == NULL) || (cdi->tracks == NULL)) - return 0; + return 0; /* Data track has attribute 0x14. */ - for (i = 0; i < cdi->tracks_num; i++) { - if (cdi->tracks[i].attr == DATA_TRACK) - return 1; + for (int i = 0; i < cdi->tracks_num; i++) { + if (cdi->tracks[i].attr == DATA_TRACK) + return 1; } return 0; } - int cdi_has_audio_track(cd_img_t *cdi) { - int i; - if ((cdi == NULL) || (cdi->tracks == NULL)) - return 0; + return 0; /* Audio track has attribute 0x14. */ - for (i = 0; i < cdi->tracks_num; i++) { - if (cdi->tracks[i].attr == AUDIO_TRACK) - return 1; + for (int i = 0; i < cdi->tracks_num; i++) { + if (cdi->tracks[i].attr == AUDIO_TRACK) + return 1; } return 0; diff --git a/src/cdrom/cdrom_image_viso.c b/src/cdrom/cdrom_image_viso.c new file mode 100644 index 000000000..7ed68cd86 --- /dev/null +++ b/src/cdrom/cdrom_image_viso.c @@ -0,0 +1,1576 @@ +/* + * 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. + * + * Virtual ISO CD-ROM image back-end. + * + * + * + * Authors: RichardG + * + * Copyright 2022 RichardG. + */ +#ifndef _LARGEFILE_SOURCE +# define _LARGEFILE_SOURCE +#endif +#ifndef _LARGEFILE64_SOURCE +# define _LARGEFILE64_SOURCE +#endif +#define __STDC_FORMAT_MACROS +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#define HAVE_STDARG_H +#include <86box/86box.h> +#include <86box/bswap.h> +#include <86box/cdrom_image_backend.h> +#include <86box/path.h> +#include <86box/plat.h> +#include <86box/plat_dir.h> +#include <86box/version.h> +#include <86box/timer.h> +#include <86box/nvr.h> + +#ifndef S_ISDIR +# define S_ISDIR(m) (((m) &S_IFMT) == S_IFDIR) +#endif + +#define VISO_SKIP(p, n) \ + { \ + memset(p, 0x00, n); \ + p += n; \ + } +#define VISO_TIME_VALID(t) ((t) > 0) + +/* ISO 9660 defines "both endian" data formats, which + are stored as little endian followed by big endian. */ +#define VISO_LBE_16(p, x) \ + { \ + *((uint16_t *) p) = cpu_to_le16(x); \ + p += 2; \ + *((uint16_t *) p) = cpu_to_be16(x); \ + p += 2; \ + } +#define VISO_LBE_32(p, x) \ + { \ + *((uint32_t *) p) = cpu_to_le32(x); \ + p += 4; \ + *((uint32_t *) p) = cpu_to_be32(x); \ + p += 4; \ + } + +#define VISO_SECTOR_SIZE COOKED_SECTOR_SIZE +#define VISO_OPEN_FILES 32 + +enum { + VISO_CHARSET_D = 0, + VISO_CHARSET_A, + VISO_CHARSET_FN, + VISO_CHARSET_ANY +}; + +enum { + VISO_DIR_CURRENT = 0, + VISO_DIR_CURRENT_ROOT, + VISO_DIR_PARENT, + VISO_DIR_REGULAR, + VISO_DIR_JOLIET +}; + +enum { + VISO_FORMAT_ISO = 1, /* ISO 9660 (High Sierra if not set) */ + VISO_FORMAT_JOLIET = 2, /* Joliet extensions (Microsoft) */ + VISO_FORMAT_RR = 4 /* Rock Ridge extensions (*nix) */ +}; + +typedef struct _viso_entry_ { + union { /* save some memory */ + uint64_t pt_offsets[4]; + FILE *file; + }; + union { + char name_short[13]; + uint64_t dr_offsets[2]; + uint64_t data_offset; + }; + uint16_t pt_idx; + + struct stat stats; + + struct _viso_entry_ *parent, *next, *next_dir, *first_child; + + char *basename, path[]; +} viso_entry_t; + +typedef struct { + uint64_t vol_size_offsets[2]; + uint64_t pt_meta_offsets[2]; + int format; + uint8_t use_version_suffix : 1; + size_t metadata_sectors, all_sectors, entry_map_size, sector_size, file_fifo_pos; + uint8_t *metadata; + + track_file_t tf; + viso_entry_t *root_dir; + viso_entry_t **entry_map; + viso_entry_t *file_fifo[VISO_OPEN_FILES]; +} viso_t; + +static const char rr_eid[] = "RRIP_1991A"; /* identifiers used in ER field for Rock Ridge */ +static const char rr_edesc[] = "THE ROCK RIDGE INTERCHANGE PROTOCOL PROVIDES SUPPORT FOR POSIX FILE SYSTEM SEMANTICS."; +static int8_t tz_offset = 0; + +#ifdef ENABLE_CDROM_IMAGE_VISO_LOG +int cdrom_image_viso_do_log = ENABLE_CDROM_IMAGE_VISO_LOG; + +void +cdrom_image_viso_log(const char *fmt, ...) +{ + va_list ap; + + if (cdrom_image_viso_do_log) { + va_start(ap, fmt); + pclog_ex(fmt, ap); + va_end(ap); + } +} +#else +# define cdrom_image_viso_log(fmt, ...) +#endif + +static size_t +viso_pread(void *ptr, uint64_t offset, size_t size, size_t count, FILE *fp) +{ + uint64_t cur_pos = ftello64(fp); + size_t ret = 0; + if (fseeko64(fp, offset, SEEK_SET) != -1) + ret = fread(ptr, size, count, fp); + fseeko64(fp, cur_pos, SEEK_SET); + return ret; +} + +static size_t +viso_pwrite(const void *ptr, uint64_t offset, size_t size, size_t count, FILE *fp) +{ + uint64_t cur_pos = ftello64(fp); + size_t ret = 0; + if (fseeko64(fp, offset, SEEK_SET) != -1) + ret = fwrite(ptr, size, count, fp); + fseeko64(fp, cur_pos, SEEK_SET); + return ret; +} + +static size_t +viso_convert_utf8(wchar_t *dest, const char *src, ssize_t buf_size) +{ + uint32_t c; + wchar_t *p = dest; + size_t next; + + while (buf_size-- > 0) { + /* Interpret source codepoint. */ + c = *src; + if (!c) { + /* Terminator. */ + *p = 0; + break; + } else if (c & 0x80) { + /* Convert UTF-8 sequence into a codepoint. */ + next = 0; + while (c & 0x40) { + next++; + c <<= 1; + } + c = *src++ & (0x3f >> next); + while ((next-- > 0) && ((*src & 0xc0) == 0x80)) + c = (c << 6) | (*src++ & 0x3f); + + /* Convert codepoints >= U+10000 to UTF-16 surrogate pairs. + This has to be done here because wchar_t on some platforms + (Windows) is not wide enough to store such high codepoints. */ + if (c >= 0x10000) { + if ((c <= 0x10ffff) && (buf_size-- > 0)) { + /* Encode surrogate pair. */ + c -= 0x10000; + *p++ = 0xd800 | (c >> 10); + c = 0xdc00 | (c & 0x3ff); + } else { + /* Codepoint overflow or no room for a pair. */ + c = '?'; + } + } + } else { + /* Pass through sub-UTF-8 codepoints. */ + src++; + } + + /* Write destination codepoint. */ + *p++ = c; + } + + return p - dest; +} + +#define VISO_WRITE_STR_FUNC(func, dst_type, src_type, converter, bounds_chk) \ + static void \ + func(dst_type *dest, const src_type *src, ssize_t buf_size, int charset) \ + { \ + src_type c; \ + while (buf_size-- > 0) { \ + /* Interpret source codepoint. */ \ + c = *src++; \ + switch (c) { \ + case 0x00: \ + /* Terminator, apply space padding. */ \ + while (buf_size-- >= 0) \ + *dest++ = converter(' '); \ + return; \ + \ + case 'A' ... 'Z': \ + case '0' ... '9': \ + case '_': \ + /* Valid on all sets. */ \ + break; \ + \ + case 'a' ... 'z': \ + /* Convert to uppercase on D and A. */ \ + if (charset <= VISO_CHARSET_A) \ + c -= 'a' - 'A'; \ + break; \ + \ + case '!': \ + case '#': \ + case '$': \ + case '%': \ + case '&': \ + case '\'': \ + case '(': \ + case ')': \ + case '-': \ + case '@': \ + case '^': \ + case '`': \ + case '{': \ + case '}': \ + case '~': \ + /* Valid on all sets (non-complying DOS characters). */ \ + break; \ + \ + case ' ': \ + case '"': \ + case '+': \ + case ',': \ + case '.': \ + case '<': \ + case '=': \ + case '>': \ + /* Valid for A and filenames but not for D. */ \ + if (charset < VISO_CHARSET_A) \ + c = '_'; \ + break; \ + \ + case '*': \ + case '/': \ + case ':': \ + case ';': \ + case '?': \ + /* Valid for A but not for filenames or D. */ \ + if ((charset < VISO_CHARSET_A) || (charset == VISO_CHARSET_FN)) \ + c = '_'; \ + break; \ + \ + case 0x01 ... 0x1f: \ + case '\\': \ + /* Not valid for D, A or filenames. */ \ + if (charset <= VISO_CHARSET_FN) \ + c = '_'; \ + break; \ + \ + default: \ + /* Not valid for D or A, but valid for filenames. */ \ + if ((charset < VISO_CHARSET_FN) || (bounds_chk)) \ + c = '_'; \ + break; \ + } \ + \ + /* Write destination codepoint with conversion function applied. */ \ + *dest++ = converter(c); \ + } \ + } +VISO_WRITE_STR_FUNC(viso_write_string, uint8_t, char, , 0) +VISO_WRITE_STR_FUNC(viso_write_wstring, uint16_t, wchar_t, cpu_to_be16, c > 0xffff) + +static int +viso_fill_fn_short(char *data, const viso_entry_t *entry, viso_entry_t **entries) +{ + /* Get name and extension length. */ + const char *ext_pos = strrchr(entry->basename, '.'); + int name_len; + int ext_len; + if (ext_pos) { + name_len = ext_pos - entry->basename; + ext_len = strlen(ext_pos); + } else { + name_len = strlen(entry->basename); + ext_len = 0; + } + + /* Copy name. */ + int name_copy_len = MIN(8, name_len); + viso_write_string((uint8_t *) data, entry->basename, name_copy_len, VISO_CHARSET_D); + data[name_copy_len] = '\0'; + + /* Copy extension to temporary buffer. */ + char ext[5] = { 0 }; + int force_tail = (name_len > 8) || (ext_len == 1); + if (ext_len > 1) { + ext[0] = '.'; + if (ext_len > 4) { + ext_len = 4; + force_tail = 1; + } + viso_write_string((uint8_t *) &ext[1], &ext_pos[1], ext_len - 1, VISO_CHARSET_D); + } + + /* Check if this filename is unique, and add a tail if required, while also adding the extension. */ + char tail[16]; + for (int i = force_tail; i <= 999999; i++) { + /* Add tail to the filename if this is not the first run. */ + int tail_len = -1; + if (i) { + tail_len = sprintf(tail, "~%d", i); + strcpy(&data[MIN(name_copy_len, 8 - tail_len)], tail); + } + + /* Add extension to the filename if present. */ + if (ext[0]) + strcat(data, ext); + + /* Go through files in this directory to make sure this filename is unique. */ + for (size_t j = 0; entries[j] != entry; j++) { + /* Flag and stop if this filename was seen. */ + if (!strcmp(data, entries[j]->name_short)) { + tail_len = 0; + break; + } + } + + /* Stop if this is an unique name. */ + if (tail_len) + return 0; + } + return 1; +} + +static size_t +viso_fill_fn_rr(uint8_t *data, const viso_entry_t *entry, size_t max_len) +{ + /* Trim filename to max_len if needed. */ + size_t len = strlen(entry->basename); + if (len > max_len) { + viso_write_string(data, entry->basename, max_len, VISO_CHARSET_FN); + + /* Relocate extension if the original name exceeds the maximum length. */ + if (!S_ISDIR(entry->stats.st_mode)) { /* do this on files only */ + const char *ext = strrchr(entry->basename, '.'); + if (ext > entry->basename) { + len = strlen(ext); + if (len >= max_len) + len = max_len - 1; /* don't create a dotfile where there isn't one */ + viso_write_string(data + (max_len - len), ext, len, VISO_CHARSET_FN); + } + } + + return max_len; + } else { + viso_write_string(data, entry->basename, len, VISO_CHARSET_FN); + return len; + } +} + +static size_t +viso_fill_fn_joliet(uint8_t *data, const viso_entry_t *entry, size_t max_len) /* note: receives and returns byte sizes */ +{ + /* Decode filename as UTF-8. */ + size_t len = strlen(entry->basename); + wchar_t utf8dec[len + 1]; + len = viso_convert_utf8(utf8dec, entry->basename, len + 1); + + /* Trim decoded filename to max_len if needed. */ + max_len /= 2; + if (len > max_len) { + viso_write_wstring((uint16_t *) data, utf8dec, max_len, VISO_CHARSET_FN); + + /* Relocate extension if the original name exceeds the maximum length. */ + if (!S_ISDIR(entry->stats.st_mode)) { /* do this on files only */ + const wchar_t *ext = wcsrchr(utf8dec, L'.'); + if (ext > utf8dec) { + len = wcslen(ext); + if (len > max_len) + len = max_len; + else if ((len < max_len) && ((((uint16_t *) data)[max_len - len] & be16_to_cpu(0xfc00)) == be16_to_cpu(0xdc00))) + max_len--; /* don't break an UTF-16 pair */ + viso_write_wstring(((uint16_t *) data) + (max_len - len), ext, len, VISO_CHARSET_FN); + } + } + + return max_len * 2; + } else { + viso_write_wstring((uint16_t *) data, utf8dec, len, VISO_CHARSET_FN); + return len * 2; + } +} + +static int +viso_fill_time(uint8_t *data, time_t time, int format, int longform) +{ + uint8_t *p = data; + struct tm *time_s = localtime(&time); + if (!time_s) { + /* localtime will return NULL if the time_t is negative (Windows) + or way too far into 64-bit space (Linux). Fall back to epoch. */ + time_t epoch = 0; + time_s = localtime(&epoch); + if (UNLIKELY(!time_s)) + fatal("VISO: localtime(0) = NULL\n"); + + /* Force year clamping if the timestamp is known to be outside the supported ranges. */ + if (time < (longform ? -62135596800LL : -2208988800LL)) /* 0001-01-01 00:00:00 : 1900-01-01 00:00:00 */ + time_s->tm_year = -1901; + else if (time > (longform ? 253402300799LL : 5869583999LL)) /* 9999-12-31 23:59:59 : 2155-12-31 23:59:59 */ + time_s->tm_year = 8100; + } + + /* Clamp year to the supported ranges, and assume the + OS returns valid numbers in the other struct fields. */ + if (time_s->tm_year < (longform ? -1900 : 0)) { + time_s->tm_year = longform ? -1900 : 0; + time_s->tm_mon = time_s->tm_hour = time_s->tm_min = time_s->tm_sec = 0; + time_s->tm_mday = 1; + } else if (time_s->tm_year > (longform ? 8099 : 255)) { + time_s->tm_year = longform ? 8099 : 255; + time_s->tm_mon = 11; + time_s->tm_mday = 31; + time_s->tm_hour = 23; + time_s->tm_min = time_s->tm_sec = 59; + } + + /* Convert timestamp. */ + if (longform) { + p += sprintf((char *) p, "%04u%02u%02u%02u%02u%02u00", + 1900 + time_s->tm_year, 1 + time_s->tm_mon, time_s->tm_mday, + time_s->tm_hour, time_s->tm_min, time_s->tm_sec); + } else { + *p++ = time_s->tm_year; /* year since 1900 */ + *p++ = 1 + time_s->tm_mon; /* month */ + *p++ = time_s->tm_mday; /* day */ + *p++ = time_s->tm_hour; /* hour */ + *p++ = time_s->tm_min; /* minute */ + *p++ = time_s->tm_sec; /* second */ + } + if (format & VISO_FORMAT_ISO) + *p++ = tz_offset; /* timezone (ISO only) */ + + return p - data; +} + +static int +viso_fill_dir_record(uint8_t *data, viso_entry_t *entry, viso_t *viso, int type) +{ + uint8_t *p = data; + uint8_t *q; + uint8_t *r; + + *p++ = 0; /* size (filled in later) */ + *p++ = 0; /* extended attribute length */ + VISO_SKIP(p, 8); /* sector offset */ + VISO_LBE_32(p, entry->stats.st_size); /* size (filled in later if this is a directory) */ +#ifdef _WIN32 + if (entry->stats.st_mtime < 0) + pclog("VISO: Warning: Windows returned st_mtime %lld on file [%s]\n", (long long) entry->stats.st_mtime, entry->path); +#endif + p += viso_fill_time(p, entry->stats.st_mtime, viso->format, 0); /* time */ + *p++ = S_ISDIR(entry->stats.st_mode) ? 0x02 : 0x00; /* flags */ + + VISO_SKIP(p, 2 + !(viso->format & VISO_FORMAT_ISO)); /* file unit size (reserved on HSF), interleave gap size (HSF/ISO) and skip factor (HSF only) */ + VISO_LBE_16(p, 1); /* volume sequence number */ + + switch (type) { + case VISO_DIR_CURRENT: + case VISO_DIR_CURRENT_ROOT: + case VISO_DIR_PARENT: + *p++ = 1; /* file ID length */ + *p++ = (type == VISO_DIR_PARENT) ? 1 : 0; /* magic value corresponding to . or .. */ + + /* Fill Rock Ridge Extension Record for the root directory's . entry. */ + if ((type == VISO_DIR_CURRENT_ROOT) && (viso->format & VISO_FORMAT_RR)) { + *p++ = 'E'; + *p++ = 'R'; + *p++ = 8 + (sizeof(rr_eid) - 1) + (sizeof(rr_edesc) - 1); /* length */ + *p++ = 1; /* version */ + + *p++ = sizeof(rr_eid) - 1; /* ID length */ + *p++ = sizeof(rr_edesc) - 1; /* description length */ + *p++ = 0; /* source length (source is recommended but won't fit here) */ + *p++ = 1; /* extension version */ + + memcpy(p, rr_eid, sizeof(rr_eid) - 1); /* ID */ + p += sizeof(rr_eid) - 1; + memcpy(p, rr_edesc, sizeof(rr_edesc) - 1); /* description */ + p += sizeof(rr_edesc) - 1; + + goto pad_susp; + } + break; + + case VISO_DIR_REGULAR: + q = p++; /* save file ID length location for later */ + + *q = strlen(entry->name_short); + memcpy(p, entry->name_short, *q); /* file ID */ + p += *q; + if (viso->use_version_suffix && !S_ISDIR(entry->stats.st_mode)) { + *p++ = ';'; /* version suffix for files (ISO only, except for Windows NT SETUPLDR.BIN El Torito hack) */ + *p++ = '1'; + *q += 2; + } + + if (!(*q & 1)) /* padding for even file ID lengths */ + *p++ = 0; + + /* Fill Rock Ridge data. */ + if (viso->format & VISO_FORMAT_RR) { + *p++ = 'R'; /* RR = present Rock Ridge entries (only documented by RRIP revision 1.09!) */ + *p++ = 'R'; + *p++ = 5; /* length */ + *p++ = 1; /* version */ + + q = p++; /* save Rock Ridge flags location for later */ + +#ifndef _WIN32 /* attributes reported by MinGW don't really make sense because it's Windows */ + *q |= 0x01; /* PX = POSIX attributes */ + *p++ = 'P'; + *p++ = 'X'; + *p++ = 36; /* length */ + *p++ = 1; /* version */ + + VISO_LBE_32(p, entry->stats.st_mode); /* mode */ + VISO_LBE_32(p, entry->stats.st_nlink); /* number of links */ + VISO_LBE_32(p, entry->stats.st_uid); /* owner UID */ + VISO_LBE_32(p, entry->stats.st_gid); /* owner GID */ + +# ifndef S_ISCHR +# define S_ISCHR(x) 0 +# endif +# ifndef S_ISBLK +# define S_ISBLK(x) 0 +# endif + if (S_ISCHR(entry->stats.st_mode) || S_ISBLK(entry->stats.st_mode)) { + *q |= 0x02; /* PN = POSIX device */ + *p++ = 'P'; + *p++ = 'N'; + *p++ = 20; /* length */ + *p++ = 1; /* version */ + + uint64_t dev = entry->stats.st_rdev; /* avoid warning if <= 32 bits */ + VISO_LBE_32(p, dev >> 32); /* device number (high 32 bits) */ + VISO_LBE_32(p, dev); /* device number (low 32 bits) */ + } +#endif + int times = +#ifdef st_birthtime + (VISO_TIME_VALID(entry->stats.st_birthtime) << 0) | /* creation (hack: assume the platform remaps st_birthtime at header level) */ +#endif + (VISO_TIME_VALID(entry->stats.st_mtime) << 1) | /* modify */ + (VISO_TIME_VALID(entry->stats.st_atime) << 2) | /* access */ + (VISO_TIME_VALID(entry->stats.st_ctime) << 3); /* attributes */ + if (times) { + *q |= 0x80; /* TF = timestamps */ + *p++ = 'T'; + *p++ = 'F'; + r = p; /* save length location for later */ + *p++ = 2; /* length (added to later) */ + *p++ = 1; /* version */ + + *p++ = times; /* flags */ +#ifdef st_birthtime + if (times & (1 << 0)) + p += viso_fill_time(p, entry->stats.st_birthtime, viso->format, 0); /* creation */ +#endif + if (times & (1 << 1)) + p += viso_fill_time(p, entry->stats.st_mtime, viso->format, 0); /* modify */ + if (times & (1 << 2)) + p += viso_fill_time(p, entry->stats.st_atime, viso->format, 0); /* access */ + if (times & (1 << 3)) + p += viso_fill_time(p, entry->stats.st_ctime, viso->format, 0); /* attributes */ + + *r += p - r; /* add to length */ + } + + *q |= 0x08; /* NM = alternate name */ + *p++ = 'N'; + *p++ = 'M'; + r = p; /* save length location for later */ + *p++ = 2; /* length (added to later) */ + *p++ = 1; /* version */ + + *p++ = 0; /* flags */ + p += viso_fill_fn_rr(p, entry, 254 - (p - data)); /* name */ + + *r += p - r; /* add to length */ +pad_susp: + if ((p - data) & 1) /* padding for odd SUSP section lengths */ + *p++ = 0; + } + break; + + case VISO_DIR_JOLIET: + q = p++; /* save file ID length location for later */ + + *q = viso_fill_fn_joliet(p, entry, 254 - (p - data)); + p += *q; + + if (!(*q & 1)) /* padding for even file ID lengths */ + *p++ = 0; + break; + + default: + break; + } + + if (UNLIKELY((p - data) > 255)) + fatal("VISO: Directory record overflow (%" PRIuPTR ") on entry %08" PRIXPTR "\n", (uintptr_t) (p - data), (uintptr_t) entry); + + data[0] = p - data; /* length */ + return data[0]; +} + +static int +viso_compare_entries(const void *a, const void *b) +{ + return strcmp((*((viso_entry_t **) a))->name_short, (*((viso_entry_t **) b))->name_short); +} + +int +viso_read(void *priv, uint8_t *buffer, uint64_t seek, size_t count) +{ + track_file_t *tf = (track_file_t *) priv; + viso_t *viso = (viso_t *) tf->priv; + + /* Handle reads in a sector by sector basis. */ + while (count > 0) { + /* Determine the current sector, offset and remainder. */ + uint32_t sector = seek / viso->sector_size; + uint32_t sector_offset = seek % viso->sector_size; + uint32_t sector_remain = MIN(count, viso->sector_size - sector_offset); + + /* Handle sector. */ + if (sector < viso->metadata_sectors) { + /* Copy metadata. */ + memcpy(buffer, viso->metadata + seek, sector_remain); + } else { + size_t read = 0; + + /* Get the file entry corresponding to this sector. */ + viso_entry_t *entry = viso->entry_map[sector - viso->metadata_sectors]; + if (entry) { + /* Open file if it's not already open. */ + if (!entry->file) { + /* Close any existing FIFO entry's file. */ + viso_entry_t *other_entry = viso->file_fifo[viso->file_fifo_pos]; + if (other_entry && other_entry->file) { + cdrom_image_viso_log("VISO: Closing [%s]", other_entry->path); + fclose(other_entry->file); + other_entry->file = NULL; + cdrom_image_viso_log("\n"); + } + + /* Open file. */ + cdrom_image_viso_log("VISO: Opening [%s]", entry->path); + if ((entry->file = fopen(entry->path, "rb"))) { + cdrom_image_viso_log("\n"); + + /* Add this entry to the FIFO. */ + viso->file_fifo[viso->file_fifo_pos++] = entry; + viso->file_fifo_pos &= (sizeof(viso->file_fifo) / sizeof(viso->file_fifo[0])) - 1; + } else { + cdrom_image_viso_log(" => failed\n"); + + /* Clear any existing FIFO entry. */ + viso->file_fifo[viso->file_fifo_pos] = NULL; + } + } + + /* Read data. */ + if (entry->file && (fseeko64(entry->file, seek - entry->data_offset, SEEK_SET) != -1)) + read = fread(buffer, 1, sector_remain, entry->file); + } + + /* Fill remainder with 00 bytes if needed. */ + if (read < sector_remain) + memset(buffer + read, 0x00, sector_remain - read); + } + + /* Move on to the next sector. */ + buffer += sector_remain; + seek += sector_remain; + count -= sector_remain; + } + + return 1; +} + +uint64_t +viso_get_length(void *priv) +{ + track_file_t *tf = (track_file_t *) priv; + const viso_t *viso = (viso_t *) tf->priv; + + return ((uint64_t) viso->all_sectors) * viso->sector_size; +} + +void +viso_close(void *priv) +{ + track_file_t *tf = (track_file_t *) priv; + viso_t *viso = (viso_t *) tf->priv; + + if (viso == NULL) + return; + + cdrom_image_viso_log("VISO: close()\n"); + + /* De-allocate everything. */ + if (tf->fp) + fclose(tf->fp); +#ifndef ENABLE_CDROM_IMAGE_VISO_LOG + remove(nvr_path(viso->tf.fn)); +#endif + + viso_entry_t *entry = viso->root_dir; + viso_entry_t *next_entry; + while (entry) { + if (entry->file) + fclose(entry->file); + next_entry = entry->next; + free(entry); + entry = next_entry; + } + + if (viso->metadata) + free(viso->metadata); + if (viso->entry_map) + free(viso->entry_map); + + free(viso); +} + +track_file_t * +viso_init(const char *dirname, int *error) +{ + cdrom_image_viso_log("VISO: init()\n"); + + /* Initialize our data structure. */ + viso_t *viso = (viso_t *) calloc(1, sizeof(viso_t)); + uint8_t *data = NULL; + uint8_t *p; + *error = 1; + if (viso == NULL) + goto end; + viso->sector_size = VISO_SECTOR_SIZE; + viso->format = VISO_FORMAT_ISO | VISO_FORMAT_JOLIET | VISO_FORMAT_RR; + viso->use_version_suffix = (viso->format & VISO_FORMAT_ISO); /* cleared later if required */ + + /* Prepare temporary data buffers. */ + data = calloc(2, viso->sector_size); + if (!data) + goto end; + + /* Open temporary file. */ +#ifdef ENABLE_CDROM_IMAGE_VISO_LOG + strcpy(viso->tf.fn, "viso-debug.iso"); +#else + plat_tempfile(viso->tf.fn, "viso", ".tmp"); +#endif + viso->tf.fp = plat_fopen64(nvr_path(viso->tf.fn), "w+b"); + if (!viso->tf.fp) + goto end; + + /* Set up directory traversal. */ + cdrom_image_viso_log("VISO: Traversing directories:\n"); + viso_entry_t *entry; + viso_entry_t *last_entry; + viso_entry_t *dir; + viso_entry_t *last_dir; + const viso_entry_t *eltorito_dir = NULL; + const viso_entry_t *eltorito_entry = NULL; + struct dirent *readdir_entry; + int len; + int eltorito_others_present = 0; + size_t dir_path_len; + uint64_t eltorito_offset = 0; + uint8_t eltorito_type = 0; + + /* Fill root directory entry. */ + dir_path_len = strlen(dirname); + last_entry = dir = last_dir = viso->root_dir = (viso_entry_t *) calloc(1, sizeof(viso_entry_t) + dir_path_len + 1); + if (!dir) + goto end; + strcpy(dir->path, dirname); + if (stat(dirname, &dir->stats) != 0) { + /* Use a blank structure if stat failed. */ + memset(&dir->stats, 0x00, sizeof(struct stat)); + } + if (!S_ISDIR(dir->stats.st_mode)) /* root is not a directory */ + goto end; + dir->parent = dir; /* for the root's path table and .. entries */ + cdrom_image_viso_log("[%08X] %s => [root]\n", dir, dir->path); + + /* Traverse directories, starting with the root. */ + viso_entry_t **dir_entries = NULL; + size_t dir_entries_len = 0; + while (dir) { + /* Open directory for listing. */ + DIR *dirp = opendir(dir->path); + + /* Iterate through this directory's children to determine the entry array size. */ + size_t children_count = 3; /* include terminator, . and .. */ + if (dirp) { /* create empty directory if opendir failed */ + while ((readdir_entry = readdir(dirp))) { + /* Ignore . and .. pseudo-directories. */ + if ((readdir_entry->d_name[0] == '.') && ((readdir_entry->d_name[1] == '\0') || (*((uint16_t *) &readdir_entry->d_name[1]) == '.'))) + continue; + children_count++; + } + } + + /* Grow array if needed. */ + if (children_count > dir_entries_len) { + viso_entry_t **new_dir_entries = (viso_entry_t **) realloc(dir_entries, children_count * sizeof(viso_entry_t *)); + if (new_dir_entries) { + dir_entries = new_dir_entries; + dir_entries_len = children_count; + } else { + goto next_dir; + } + } + + /* Add . and .. pseudo-directories. */ + dir_path_len = strlen(dir->path); + for (children_count = 0; children_count < 2; children_count++) { + entry = dir_entries[children_count] = (viso_entry_t *) calloc(1, sizeof(viso_entry_t) + 1); + if (!entry) + goto next_dir; + entry->parent = dir; + if (!children_count) + dir->first_child = entry; + + /* Stat the current directory or parent directory. */ + if (stat(children_count ? dir->parent->path : dir->path, &entry->stats) != 0) { + /* Use a blank structure if stat failed. */ + memset(&entry->stats, 0x00, sizeof(struct stat)); + } + + /* Set basename. */ + strcpy(entry->name_short, children_count ? ".." : "."); + + cdrom_image_viso_log("[%08X] %s => %s\n", entry, dir->path, entry->name_short); + } + + /* Iterate through this directory's children again, making the entries. */ + if (dirp) { + rewinddir(dirp); + while ((readdir_entry = readdir(dirp))) { + /* Ignore . and .. pseudo-directories. */ + if ((readdir_entry->d_name[0] == '.') && ((readdir_entry->d_name[1] == '\0') || (*((uint16_t *) &readdir_entry->d_name[1]) == '.'))) + continue; + + /* Add and fill entry. */ + entry = dir_entries[children_count++] = (viso_entry_t *) calloc(1, sizeof(viso_entry_t) + dir_path_len + strlen(readdir_entry->d_name) + 2); + if (!entry) + break; + entry->parent = dir; + strcpy(entry->path, dir->path); + path_slash(&entry->path[dir_path_len]); + entry->basename = &entry->path[dir_path_len + 1]; + strcpy(entry->basename, readdir_entry->d_name); + + /* Stat this child. */ + if (stat(entry->path, &entry->stats) != 0) { + /* Use a blank structure if stat failed. */ + memset(&entry->stats, 0x00, sizeof(struct stat)); + } + + /* Handle file size and El Torito boot code. */ + if (!S_ISDIR(entry->stats.st_mode)) { + /* Clamp file size to 4 GB - 1 byte. */ + if (entry->stats.st_size > ((uint32_t) -1)) + entry->stats.st_size = (uint32_t) -1; + + /* Increase entry map size. */ + viso->entry_map_size += entry->stats.st_size / viso->sector_size; + if (entry->stats.st_size % viso->sector_size) + viso->entry_map_size++; /* round up to the next sector */ + + /* Detect El Torito boot code file and set it accordingly. */ + if (dir == eltorito_dir) { + if (!stricmp(readdir_entry->d_name, "Boot-NoEmul.img")) { + eltorito_type = 0x00; +have_eltorito_entry: + if (eltorito_entry) + eltorito_others_present = 1; /* flag that the boot code directory contains other files */ + eltorito_entry = entry; + } else if (!stricmp(readdir_entry->d_name, "Boot-1.2M.img")) { + eltorito_type = 0x01; + goto have_eltorito_entry; + } else if (!stricmp(readdir_entry->d_name, "Boot-1.44M.img")) { + eltorito_type = 0x02; + goto have_eltorito_entry; + } else if (!stricmp(readdir_entry->d_name, "Boot-2.88M.img")) { + eltorito_type = 0x03; + goto have_eltorito_entry; + } else if (!stricmp(readdir_entry->d_name, "Boot-HardDisk.img")) { + eltorito_type = 0x04; + goto have_eltorito_entry; + } else { + eltorito_others_present = 1; /* flag that the boot code directory contains other files */ + } + } else { + /* Disable version suffixes if this structure appears to contain the Windows NT + El Torito boot code, which is known not to tolerate suffixed file names. */ + if (eltorito_dir && /* El Torito directory present? */ + (eltorito_type == 0x00) && /* El Torito directory not checked yet, or confirmed to contain non-emulation boot code? */ + (dir->parent == viso->root_dir) && /* one subdirectory deep? (I386 for instance) */ + !stricmp(readdir_entry->d_name, "SETUPLDR.BIN")) /* SETUPLDR.BIN present? */ + viso->use_version_suffix = 0; + } + } else if ((dir == viso->root_dir) && !stricmp(readdir_entry->d_name, "[BOOT]")) { + /* Set this as the directory containing El Torito boot code. */ + eltorito_dir = entry; + eltorito_others_present = 0; + } + + /* Set short filename. */ + if (viso_fill_fn_short(entry->name_short, entry, dir_entries)) { + free(entry); + children_count--; + continue; + } + + cdrom_image_viso_log("[%08X] %s => [%-12s] %s\n", entry, dir->path, entry->name_short, entry->basename); + } + } else { + cdrom_image_viso_log("VISO: Failed to enumerate [%s], will be empty\n", dir->path); + } + + /* Add terminator. */ + dir_entries[children_count] = NULL; + + /* Sort directory entries and create the linked list. */ + qsort(&dir_entries[2], children_count - 2, sizeof(viso_entry_t *), viso_compare_entries); + for (size_t i = 0; dir_entries[i]; i++) { + /* Add link. */ + last_entry->next = dir_entries[i]; + last_entry = dir_entries[i]; + + /* If this is a directory, add it to the traversal list. */ + if ((i >= 2) && S_ISDIR(dir_entries[i]->stats.st_mode)) { + last_dir->next_dir = dir_entries[i]; + last_dir = dir_entries[i]; + } + } + +next_dir: + /* Move on to the next directory. */ + if (dirp) + closedir(dirp); + dir = dir->next_dir; + } + if (dir_entries) + free(dir_entries); + + /* Write 16 blank sectors. */ + for (int i = 0; i < 16; i++) + fwrite(data, viso->sector_size, 1, viso->tf.fp); + + /* Get current time for the volume descriptors, and calculate + the timezone offset for descriptors and file times to use. */ + tzset(); + time_t now = time(NULL); + if (viso->format & VISO_FORMAT_ISO) /* timezones are ISO only */ + tz_offset = (now - mktime(gmtime(&now))) / (3600 / 4); + + /* Get root directory basename for the volume ID. */ + const char *basename = path_get_filename(viso->root_dir->path); + if (!basename || (basename[0] == '\0')) + basename = EMU_NAME; + + /* Determine whether or not we're working with 2 volume descriptors + (as well as 2 directory trees and 4 path tables) for Joliet. */ + int max_vd = (viso->format & VISO_FORMAT_JOLIET) ? 1 : 0; + + /* Write volume descriptors. */ + for (int i = 0; i <= max_vd; i++) { + /* Fill volume descriptor. */ + p = data; + if (!(viso->format & VISO_FORMAT_ISO)) + VISO_LBE_32(p, ftello64(viso->tf.fp) / viso->sector_size); /* sector offset (HSF only) */ + *p++ = 1 + i; /* type */ + memcpy(p, (viso->format & VISO_FORMAT_ISO) ? "CD001" : "CDROM", 5); /* standard ID */ + p += 5; + *p++ = 1; /* version */ + *p++ = 0; /* unused */ + + if (i) { + viso_write_wstring((uint16_t *) p, EMU_NAME_W, 16, VISO_CHARSET_A); /* system ID */ + p += 32; + wchar_t wtemp[16]; + viso_convert_utf8(wtemp, basename, 16); + viso_write_wstring((uint16_t *) p, wtemp, 16, VISO_CHARSET_D); /* volume ID */ + p += 32; + } else { + viso_write_string(p, EMU_NAME, 32, VISO_CHARSET_A); /* system ID */ + p += 32; + viso_write_string(p, basename, 32, VISO_CHARSET_D); /* volume ID */ + p += 32; + } + + VISO_SKIP(p, 8); /* unused */ + + viso->vol_size_offsets[i] = ftello64(viso->tf.fp) + (p - data); + VISO_LBE_32(p, 0); /* volume space size (filled in later) */ + + if (i) { + *p++ = 0x25; /* escape sequence (indicates our Joliet names are UCS-2 Level 3) */ + *p++ = 0x2f; + *p++ = 0x45; + VISO_SKIP(p, 32 - 3); /* unused */ + } else { + VISO_SKIP(p, 32); /* unused */ + } + + VISO_LBE_16(p, 1); /* volume set size */ + VISO_LBE_16(p, 1); /* volume sequence number */ + VISO_LBE_16(p, viso->sector_size); /* logical block size */ + + /* Path table metadata is filled in later. */ + viso->pt_meta_offsets[i] = ftello64(viso->tf.fp) + (p - data); + VISO_SKIP(p, 24 + (16 * !(viso->format & VISO_FORMAT_ISO))); /* PT size, LE PT offset, optional LE PT offset (three on HSF), BE PT offset, optional BE PT offset (three on HSF) */ + + viso->root_dir->dr_offsets[i] = ftello64(viso->tf.fp) + (p - data); + p += viso_fill_dir_record(p, viso->root_dir, viso, VISO_DIR_CURRENT); /* root directory */ + + int copyright_abstract_len = (viso->format & VISO_FORMAT_ISO) ? 37 : 32; + if (i) { + viso_write_wstring((uint16_t *) p, L"", 64, VISO_CHARSET_D); /* volume set ID */ + p += 128; + viso_write_wstring((uint16_t *) p, L"", 64, VISO_CHARSET_A); /* publisher ID */ + p += 128; + viso_write_wstring((uint16_t *) p, L"", 64, VISO_CHARSET_A); /* data preparer ID */ + p += 128; + viso_write_wstring((uint16_t *) p, EMU_NAME_W L" " EMU_VERSION_W L" VIRTUAL ISO", 64, VISO_CHARSET_A); /* application ID */ + p += 128; + viso_write_wstring((uint16_t *) p, L"", copyright_abstract_len >> 1, VISO_CHARSET_D); /* copyright file ID */ + p += copyright_abstract_len; + viso_write_wstring((uint16_t *) p, L"", copyright_abstract_len >> 1, VISO_CHARSET_D); /* abstract file ID */ + p += copyright_abstract_len; + if (viso->format & VISO_FORMAT_ISO) { + viso_write_wstring((uint16_t *) p, L"", 18, VISO_CHARSET_D); /* bibliography file ID (ISO only) */ + p += 37; + } + } else { + viso_write_string(p, "", 128, VISO_CHARSET_D); /* volume set ID */ + p += 128; + viso_write_string(p, "", 128, VISO_CHARSET_A); /* publisher ID */ + p += 128; + viso_write_string(p, "", 128, VISO_CHARSET_A); /* data preparer ID */ + p += 128; + viso_write_string(p, EMU_NAME " " EMU_VERSION " VIRTUAL ISO", 128, VISO_CHARSET_A); /* application ID */ + p += 128; + viso_write_string(p, "", copyright_abstract_len, VISO_CHARSET_D); /* copyright file ID */ + p += copyright_abstract_len; + viso_write_string(p, "", copyright_abstract_len, VISO_CHARSET_D); /* abstract file ID */ + p += copyright_abstract_len; + if (viso->format & VISO_FORMAT_ISO) { + viso_write_string(p, "", 37, VISO_CHARSET_D); /* bibliography file ID (ISO only) */ + p += 37; + } + } + + len = viso_fill_time(p, now, viso->format, 1); /* volume created */ + memcpy(p + len, p, len); /* volume modified */ + p += len * 2; + VISO_SKIP(p, len * 2); /* volume expires/effective */ + + *p++ = 1; /* file structure version */ + *p++ = 0; /* unused */ + + /* Blank the rest of the working sector. */ + memset(p, 0x00, viso->sector_size - (p - data)); + + /* Write volume descriptor. */ + fwrite(data, viso->sector_size, 1, viso->tf.fp); + + /* Write El Torito boot descriptor. This is an awkward spot for + that, but the spec requires it to be the second descriptor. */ + if (!i && eltorito_entry) { + cdrom_image_viso_log("VISO: Writing El Torito boot descriptor for entry [%08X]\n", eltorito_entry); + + p = data; + if (!(viso->format & VISO_FORMAT_ISO)) + VISO_LBE_32(p, ftello64(viso->tf.fp) / viso->sector_size); /* sector offset (HSF only) */ + *p++ = 0; /* type */ + memcpy(p, (viso->format & VISO_FORMAT_ISO) ? "CD001" : "CDROM", 5); /* standard ID */ + p += 5; + *p++ = 1; /* version */ + + memcpy(p, "EL TORITO SPECIFICATION", 24); /* identifier */ + p += 24; + VISO_SKIP(p, 40); + + /* Save the boot catalog pointer's offset for later. */ + eltorito_offset = ftello64(viso->tf.fp) + (p - data); + + /* Blank the rest of the working sector. */ + memset(p, 0x00, viso->sector_size - (p - data)); + + /* Write boot descriptor. */ + fwrite(data, viso->sector_size, 1, viso->tf.fp); + } + } + + /* Fill terminator. */ + p = data; + if (!(viso->format & VISO_FORMAT_ISO)) + VISO_LBE_32(p, ftello64(viso->tf.fp) / viso->sector_size); /* sector offset (HSF only) */ + *p++ = 0xff; /* type */ + memcpy(p, (viso->format & VISO_FORMAT_ISO) ? "CD001" : "CDROM", 5); /* standard ID */ + p += 5; + *p++ = 1; /* version */ + + /* Blank the rest of the working sector. */ + memset(p, 0x00, viso->sector_size - (p - data)); + + /* Write terminator. */ + fwrite(data, viso->sector_size, 1, viso->tf.fp); + + /* We start seeing a pattern of padding to even sectors here. + mkisofs does this, presumably for a very good reason... */ + int write = ftello64(viso->tf.fp) % (viso->sector_size * 2); + if (write) { + write = (viso->sector_size * 2) - write; + memset(data, 0x00, write); + fwrite(data, write, 1, viso->tf.fp); + } + + /* Handle El Torito boot catalog. */ + if (eltorito_entry) { + /* Write a pointer to this boot catalog to the boot descriptor. */ + *((uint32_t *) data) = cpu_to_le32(ftello64(viso->tf.fp) / viso->sector_size); + viso_pwrite(data, eltorito_offset, 4, 1, viso->tf.fp); + + /* Fill boot catalog validation entry. */ + p = data; + *p++ = 0x01; /* header ID */ + *p++ = 0x00; /* platform */ + *p++ = 0x00; /* reserved */ + *p++ = 0x00; + VISO_SKIP(p, 24); + strncpy((char *) (p - 24), EMU_NAME, 24); /* ID string */ + *p++ = 0x00; /* checksum */ + *p++ = 0x00; + *p++ = 0x55; /* key bytes */ + *p++ = 0xaa; + + /* Calculate checksum. */ + uint16_t eltorito_checksum = 0; + for (int i = 0; i < (p - data); i += 2) + eltorito_checksum -= le16_to_cpu(*((uint16_t *) &data[i])); + *((uint16_t *) &data[28]) = cpu_to_le16(eltorito_checksum); + + /* Now fill the default boot entry. */ + *p++ = 0x88; /* bootable flag */ + *p++ = eltorito_type; /* boot media type */ + *p++ = 0x00; /* load segment */ + *p++ = 0x00; + *p++ = 0x00; /* system type (is this even relevant?) */ + *p++ = 0x00; /* reserved */ + + /* Save offsets to the boot catalog entry's offset and size fields for later. */ + eltorito_offset = ftello64(viso->tf.fp) + (p - data); + + /* Blank the rest of the working sector. This includes the sector count, + ISO sector offset and 20-byte selection criteria fields at the end. */ + memset(p, 0x00, viso->sector_size - (p - data)); + + /* Write boot catalog. */ + fwrite(data, viso->sector_size, 1, viso->tf.fp); + + /* Pad to the next even sector. */ + write = ftello64(viso->tf.fp) % (viso->sector_size * 2); + if (write) { + write = (viso->sector_size * 2) - write; + memset(data, 0x00, write); + fwrite(data, write, 1, viso->tf.fp); + } + + /* Flag that we shouldn't hide the boot code directory if it contains other files. */ + if (eltorito_others_present) + eltorito_dir = NULL; + } + + /* Write each path table. */ + for (int i = 0; i <= ((max_vd << 1) | 1); i++) { + cdrom_image_viso_log("VISO: Generating path table #%d:\n", i); + + /* Save this path table's start offset. */ + uint64_t pt_start = ftello64(viso->tf.fp); + + /* Write this table's sector offset to the corresponding volume descriptor. */ + uint32_t pt_temp = pt_start / viso->sector_size; + *((uint32_t *) data) = (i & 1) ? cpu_to_be32(pt_temp) : cpu_to_le32(pt_temp); + viso_pwrite(data, viso->pt_meta_offsets[i >> 1] + 8 + (8 * (i & 1)), 4, 1, viso->tf.fp); + + /* Go through directories. */ + dir = viso->root_dir; + uint16_t pt_idx = 1; + while (dir) { + /* Ignore . and .. pseudo-directories, and hide the El Torito + boot code directory if no other files are present in it. */ + if ((dir->name_short[0] == '.' && (dir->name_short[1] == '\0' || (dir->name_short[1] == '.' && dir->name_short[2] == '\0'))) || (dir == eltorito_dir)) { + dir = dir->next_dir; + continue; + } + + cdrom_image_viso_log("[%08X] %s => %s\n", dir, dir->path, ((i & 2) || (dir == viso->root_dir)) ? dir->basename : dir->name_short); + + /* Save this directory's path table index and offset. */ + dir->pt_idx = pt_idx; + dir->pt_offsets[i] = ftello64(viso->tf.fp); + + /* Fill path table entry. */ + p = data; + if (!(viso->format & VISO_FORMAT_ISO)) { + *((uint32_t *) p) = 0; /* extent location (filled in later) */ + p += 4; + *p++ = 0; /* extended attribute length */ + p++; /* skip ID length for now */ + } else { + p++; /* skip ID length for now */ + *p++ = 0; /* extended attribute length */ + dir->pt_offsets[i] += p - data; + *((uint32_t *) p) = 0; /* extent location (filled in later) */ + p += 4; + } + + *((uint16_t *) p) = (i & 1) ? cpu_to_be16(dir->parent->pt_idx) : cpu_to_le16(dir->parent->pt_idx); /* parent directory number */ + p += 2; + + pt_temp = 5 * !(viso->format & VISO_FORMAT_ISO); /* directory ID length at offset 0 for ISO, 5 for HSF */ + if (dir == viso->root_dir) { /* directory ID length then ID for root... */ + data[pt_temp] = 1; + *p = 0x00; + } else if (i & 2) { /* ...or Joliet... */ + data[pt_temp] = viso_fill_fn_joliet(p, dir, 255); + } else { /* ...or short name */ + data[pt_temp] = strlen(dir->name_short); + memcpy(p, dir->name_short, data[pt_temp]); + } + p += data[pt_temp]; + + if ((p - data) & 1) /* padding for odd directory ID lengths */ + *p++ = 0x00; + + /* Write path table entry. */ + fwrite(data, p - data, 1, viso->tf.fp); + + /* Increment path table index and stop if it overflows. */ + if (++pt_idx == 0) + break; + + /* Move on to the next directory. */ + dir = dir->next_dir; + } + + /* Write this table's size to the corresponding volume descriptor. */ + pt_temp = ftello64(viso->tf.fp) - pt_start; + p = data; + VISO_LBE_32(p, pt_temp); + viso_pwrite(data, viso->pt_meta_offsets[i >> 1], 8, 1, viso->tf.fp); + + /* Pad to the next even sector. */ + write = ftello64(viso->tf.fp) % (viso->sector_size * 2); + if (write) { + write = (viso->sector_size * 2) - write; + memset(data, 0x00, write); + fwrite(data, write, 1, viso->tf.fp); + } + } + + /* Write directory records for each type. */ + int dir_type = VISO_DIR_CURRENT_ROOT; + for (int i = 0; i <= max_vd; i++) { + cdrom_image_viso_log("VISO: Generating directory record set #%d:\n", i); + + /* Go through directories. */ + dir = viso->root_dir; + while (dir) { + /* Hide the El Torito boot code directory if no other files are present in it. */ + if (dir == eltorito_dir) { + dir = dir->next_dir; + continue; + } + + /* Pad to the next sector if required. */ + write = ftello64(viso->tf.fp) % viso->sector_size; + if (write) { + write = viso->sector_size - write; + memset(data, 0x00, write); + fwrite(data, write, 1, viso->tf.fp); + } + + /* Save this directory's child record array's start offset. */ + uint64_t dir_start = ftello64(viso->tf.fp); + + /* Write this directory's child record array's sector offset to its record... */ + uint32_t dir_temp = dir_start / viso->sector_size; + p = data; + VISO_LBE_32(p, dir_temp); + viso_pwrite(data, dir->dr_offsets[i] + 2, 8, 1, viso->tf.fp); + + /* ...and to its path table entries. */ + viso_pwrite(data, dir->pt_offsets[i << 1], 4, 1, viso->tf.fp); /* little endian */ + viso_pwrite(data + 4, dir->pt_offsets[(i << 1) | 1], 4, 1, viso->tf.fp); /* big endian */ + + if (i == max_vd) /* overwrite pt_offsets in the union if we no longer need them */ + dir->file = NULL; + + /* Go through entries in this directory. */ + entry = dir->first_child; + while (entry) { + /* Skip the El Torito boot code entry if present, or hide the + boot code directory if no other files are present in it. */ + if ((entry == eltorito_entry) || (entry == eltorito_dir)) + goto next_entry; + + cdrom_image_viso_log("[%08X] %s => %s\n", entry, dir->path, + ((dir_type == VISO_DIR_PARENT) ? ".." : ((dir_type < VISO_DIR_PARENT) ? "." : (i ? entry->basename : entry->name_short)))); + + /* Fill directory record. */ + viso_fill_dir_record(data, entry, viso, dir_type); + + /* Entries cannot cross sector boundaries, so pad to the next sector if needed. */ + write = viso->sector_size - (ftello64(viso->tf.fp) % viso->sector_size); + if (write < data[0]) { + p = data + (viso->sector_size * 2) - write; + memset(p, 0x00, write); + fwrite(p, write, 1, viso->tf.fp); + } + + /* Save this entry's record's offset. This overwrites name_short in the union. */ + entry->dr_offsets[i] = ftello64(viso->tf.fp); + + /* Write data related to the . and .. pseudo-subdirectories, + while advancing the current directory type. */ + if (dir_type < VISO_DIR_PARENT) { + /* Write a self-referential pointer to this entry. */ + p = data + 2; + VISO_LBE_32(p, dir_temp); + + dir_type = VISO_DIR_PARENT; + } else if (dir_type == VISO_DIR_PARENT) { + /* Copy the parent directory's offset and size. The root directory's + parent size is a special, self-referential case handled later. */ + viso_pread(data + 2, dir->parent->dr_offsets[i] + 2, 16, 1, viso->tf.fp); + + dir_type = i ? VISO_DIR_JOLIET : VISO_DIR_REGULAR; + } + + /* Write entry. */ + fwrite(data, data[0], 1, viso->tf.fp); +next_entry: + /* Move on to the next entry, and stop if the end of this directory was reached. */ + entry = entry->next; + if (entry && (entry->parent != dir)) + break; + } + + /* Write this directory's child record array's size to its parent and . records. */ + dir_temp = ftello64(viso->tf.fp) - dir_start; + p = data; + VISO_LBE_32(p, dir_temp); + viso_pwrite(data, dir->dr_offsets[i] + 10, 8, 1, viso->tf.fp); + viso_pwrite(data, dir->first_child->dr_offsets[i] + 10, 8, 1, viso->tf.fp); + if (dir->parent == dir) /* write size to .. on root directory as well */ + viso_pwrite(data, dir->first_child->next->dr_offsets[i] + 10, 8, 1, viso->tf.fp); + + /* Move on to the next directory. */ + dir_type = VISO_DIR_CURRENT; + dir = dir->next_dir; + } + + /* Pad to the next even sector. */ + write = ftello64(viso->tf.fp) % (viso->sector_size * 2); + if (write) { + write = (viso->sector_size * 2) - write; + memset(data, 0x00, write); + fwrite(data, write, 1, viso->tf.fp); + } + } + + /* Allocate entry map for sector->file lookups. */ + size_t orig_sector_size = viso->sector_size; + while (1) { + cdrom_image_viso_log("VISO: Allocating entry map for %d %d-byte sectors\n", viso->entry_map_size, viso->sector_size); + viso->entry_map = (viso_entry_t **) calloc(viso->entry_map_size, sizeof(viso_entry_t *)); + if (viso->entry_map) { + /* Successfully allocated. */ + break; + } else { + /* Blank data buffer for padding if this is the first run. */ + if (orig_sector_size == viso->sector_size) + memset(data, 0x00, orig_sector_size); + + /* If we don't have enough memory, double the sector size. */ + viso->sector_size *= 2; + if (viso->sector_size == 0) /* give up if sectors become too large */ + goto end; + + /* Go through files, recalculating the entry map size. */ + size_t orig_entry_map_size = viso->entry_map_size; + viso->entry_map_size = 0; + entry = viso->root_dir; + while (entry) { + if (!S_ISDIR(entry->stats.st_mode)) { + viso->entry_map_size += entry->stats.st_size / viso->sector_size; + if (entry->stats.st_size % viso->sector_size) + viso->entry_map_size++; /* round up to the next sector */ + } + entry = entry->next; + } + if (viso->entry_map_size == orig_entry_map_size) /* give up if there was no change in map size */ + goto end; + + /* Pad metadata to the new size's next sector. */ + while (ftello64(viso->tf.fp) % viso->sector_size) + fwrite(data, orig_sector_size, 1, viso->tf.fp); + } + } + + /* Start sector counts. */ + viso->metadata_sectors = ftello64(viso->tf.fp) / viso->sector_size; + viso->all_sectors = viso->metadata_sectors; + + /* Go through files, assigning sectors to them. */ + cdrom_image_viso_log("VISO: Assigning sectors to files:\n"); + size_t base_factor = viso->sector_size / orig_sector_size; + viso_entry_t *prev_entry = viso->root_dir; + viso_entry_t **entry_map_p = viso->entry_map; + entry = prev_entry->next; + while (entry) { + /* Skip this entry if it corresponds to a directory. */ + if (S_ISDIR(entry->stats.st_mode)) { + /* Deallocate directory entries to save some memory. */ + prev_entry->next = entry->next; + free(entry); + entry = prev_entry->next; + continue; + } + + /* Write this file's base sector offset to its directory + entries, unless this is the El Torito boot code entry, + in which case, write offset and size to the boot entry. */ + if (entry == eltorito_entry) { + /* Load the entire file if not emulating, or just the first virtual + sector (which usually contains all the boot code) if emulating. */ + if (eltorito_type == 0x00) { /* non-emulation */ + uint32_t boot_size = entry->stats.st_size; + if (boot_size % 512) /* round up */ + boot_size += 512 - (boot_size % 512); + *((uint16_t *) &data[0]) = cpu_to_le16(boot_size / 512); + } else { /* emulation */ + *((uint16_t *) &data[0]) = cpu_to_le16(1); + } + *((uint32_t *) &data[2]) = cpu_to_le32(viso->all_sectors * base_factor); + viso_pwrite(data, eltorito_offset, 6, 1, viso->tf.fp); + } else { + p = data; + VISO_LBE_32(p, viso->all_sectors * base_factor); + for (int i = 0; i <= max_vd; i++) + viso_pwrite(data, entry->dr_offsets[i] + 2, 8, 1, viso->tf.fp); + } + + /* Save this file's base offset. This overwrites dr_offsets in the union. */ + entry->data_offset = ((uint64_t) viso->all_sectors) * viso->sector_size; + + /* Determine how many sectors this file will take. */ + uint32_t size = entry->stats.st_size / viso->sector_size; + if (entry->stats.st_size % viso->sector_size) + size++; /* round up to the next sector */ + cdrom_image_viso_log("[%08X] %s => %" PRIu32 " + %" PRIu32 " sectors\n", entry, entry->path, viso->all_sectors, size); + + /* Allocate sectors to this file. */ + viso->all_sectors += size; + while (size-- > 0) + *entry_map_p++ = entry; + + /* Move on to the next entry. */ + prev_entry = entry; + entry = entry->next; + } + + /* Write final volume size to all volume descriptors. */ + p = data; + VISO_LBE_32(p, viso->all_sectors); + for (int i = 0; i < (sizeof(viso->vol_size_offsets) / sizeof(viso->vol_size_offsets[0])); i++) + viso_pwrite(data, viso->vol_size_offsets[i], 8, 1, viso->tf.fp); + + /* Metadata processing is finished, read it back to memory. */ + cdrom_image_viso_log("VISO: Reading back %d %d-byte sectors of metadata\n", viso->metadata_sectors, viso->sector_size); + viso->metadata = (uint8_t *) calloc(viso->metadata_sectors, viso->sector_size); + if (!viso->metadata) + goto end; + fseeko64(viso->tf.fp, 0, SEEK_SET); + uint64_t metadata_size = viso->metadata_sectors * viso->sector_size; + uint64_t metadata_remain = metadata_size; + while (metadata_remain > 0) + metadata_remain -= fread(viso->metadata + (metadata_size - metadata_remain), 1, MIN(metadata_remain, viso->sector_size), viso->tf.fp); + + /* We no longer need the temporary file; close and delete it. */ + fclose(viso->tf.fp); + viso->tf.fp = NULL; +#ifndef ENABLE_CDROM_IMAGE_VISO_LOG + remove(nvr_path(viso->tf.fn)); +#endif + + /* All good. */ + *error = 0; + +end: + /* Set the function pointers. */ + viso->tf.priv = viso; + if (!*error) { + cdrom_image_viso_log("VISO: Initialized\n"); + viso->tf.read = viso_read; + viso->tf.get_length = viso_get_length; + viso->tf.close = viso_close; + return &viso->tf; + } else { + cdrom_image_viso_log("VISO: Initialization failed\n"); + if (data) + free(data); + viso_close(&viso->tf); + return NULL; + } +} diff --git a/src/cdrom/cdrom_mitsumi.c b/src/cdrom/cdrom_mitsumi.c new file mode 100644 index 000000000..7f4d2645b --- /dev/null +++ b/src/cdrom/cdrom_mitsumi.c @@ -0,0 +1,478 @@ +/* + * 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. + * + * Mitsumi CD-ROM emulation for the ISA bus. + * + * + * + * Authors: Miran Grca, + * + * Copyright 2022 Miran Grca. + */ +#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/pic.h> +#include <86box/dma.h> +#include <86box/cdrom.h> +#include <86box/cdrom_interface.h> +#include <86box/cdrom_mitsumi.h> +#include <86box/plat.h> +#include <86box/sound.h> + +#define MCD_DEFAULT_IOPORT 0x310 +#define MCD_DEFAULT_IRQ 5 +#define MCD_DEFAULT_DMA 5 + +#define RAW_SECTOR_SIZE 2352 +#define COOKED_SECTOR_SIZE 2048 + +enum { + STAT_CMD_CHECK = 0x01, + STAT_PLAY_CDDA = 0x02, + STAT_ERROR = 0x04, + STAT_DISK_CDDA = 0x08, + STAT_SPIN = 0x10, + STAT_CHANGE = 0x20, + STAT_READY = 0x40, + STAT_OPEN = 0x80 +}; +enum { + CMD_GET_INFO = 0x10, + CMD_GET_Q = 0x20, + CMD_GET_STAT = 0x40, + CMD_SET_MODE = 0x50, + CMD_SOFT_RESET = 0x60, + CMD_STOPCDDA = 0x70, + CMD_CONFIG = 0x90, + CMD_SET_VOL = 0xae, + CMD_READ1X = 0xc0, + CMD_READ2X = 0xc1, + CMD_GET_VER = 0xdc, + CMD_STOP = 0xf0, + CMD_EJECT = 0xf6, + CMD_LOCK = 0xfe +}; +enum { + MODE_MUTE = 0x01, + MODE_GET_TOC = 0x04, + MODE_STOP = 0x08, + MODE_ECC = 0x20, + MODE_DATA = 0x40 +}; +enum { + DRV_MODE_STOP, + DRV_MODE_READ, + DRV_MODE_CDDA +}; +enum { + FLAG_NODATA = 2, + FLAG_NOSTAT = 4, + FLAG_UNK = 8, //?? + FLAG_OPEN = 16 +}; +enum { + IRQ_DATAREADY = 1, + IRQ_DATACOMP = 2, + IRQ_ERROR = 4 +}; + +typedef struct mcd_t { + int dma; + int irq; + int change; + int data; + uint8_t stat; + uint8_t buf[RAW_SECTOR_SIZE]; + int buf_count; + int buf_idx; + uint8_t cmdbuf[16]; + int cmdbuf_count; + int cmdrd_count; + int cmdbuf_idx; + uint8_t mode; + uint8_t cmd; + uint8_t conf; + uint8_t enable_irq; + uint8_t enable_dma; + uint16_t dmalen; + uint32_t readmsf; + uint32_t readcount; + int locked; + int drvmode; + int cur_toc_track; + int pos; + int newstat; +} mcd_t; + +/* The addresses sent from the guest are absolute, ie. a LBA of 0 corresponds to a MSF of 00:00:00. Otherwise, the counter displayed by the guest is wrong: + there is a seeming 2 seconds in which audio plays but counter does not move, while a data track before audio jumps to 2 seconds before the actual start + of the audio while audio still plays. With an absolute conversion, the counter is fine. */ +#ifdef MSFtoLBA +#undef MSFtoLBA +#endif +#define MSFtoLBA(m, s, f) ((((m * 60) + s) * 75) + f) + +#define CD_BCD(x) (((x) % 10) | (((x) / 10) << 4)) +#define CD_DCB(x) ((((x) &0xf0) >> 4) * 10 + ((x) &0x0f)) + +#ifdef ENABLE_MITSUMI_CDROM_LOG +int mitsumi_cdrom_do_log = ENABLE_MITSUMI_CDROM_LOG; + +void +mitsumi_cdrom_log(const char *fmt, ...) +{ + va_list ap; + + if (mitsumi_cdrom_do_log) { + va_start(ap, fmt); + pclog_ex(fmt, ap); + va_end(ap); + } +} +#else +# define mitsumi_cdrom_log(fmt, ...) +#endif + +static void +mitsumi_cdrom_reset(mcd_t *dev) +{ + cdrom_t cdrom; + + cdrom.host_drive = 0; + + dev->stat = cdrom.host_drive ? (STAT_READY | STAT_CHANGE) : 0; + dev->cmdrd_count = 0; + dev->cmdbuf_count = 0; + dev->buf_count = 0; + dev->cur_toc_track = 0; + dev->enable_dma = 0; + dev->enable_irq = 0; + dev->conf = 0; + dev->dmalen = COOKED_SECTOR_SIZE; + dev->locked = 0; + dev->change = 1; + dev->newstat = 1; + dev->data = 0; +} + +static int +mitsumi_cdrom_read_sector(mcd_t *dev, int first) +{ + cdrom_t cdrom; + uint8_t status; + int ret; + + if (dev->drvmode == DRV_MODE_CDDA) { + status = cdrom_mitsumi_audio_play(&cdrom, dev->readmsf, dev->readcount); + if (status == 1) + return status; + else + dev->drvmode = DRV_MODE_READ; + } + + if ((dev->enable_irq & IRQ_DATACOMP) && !first) { + picint(1 << dev->irq); + } + if (!dev->readcount) { + dev->data = 0; + return 0; + } + cdrom_stop(&cdrom); + ret = cdrom_readsector_raw(&cdrom, dev->buf, cdrom.seek_pos, 0, 2, 0x10, (int *) &dev->readcount, 0); + if (!ret) + return 0; + if (dev->mode & 0x40) { + dev->buf[12] = CD_BCD((dev->readmsf >> 16) & 0xff); + dev->buf[13] = CD_BCD((dev->readmsf >> 8) & 0xff); + } + dev->readmsf = cdrom_lba_to_msf_accurate(cdrom.seek_pos + 1); + dev->buf_count = dev->dmalen + 1; + dev->buf_idx = 0; + dev->data = 1; + if (dev->enable_dma) { + while (dev->pos < dev->readcount) { + dma_channel_write(dev->dma, dev->buf[dev->pos]); + dev->pos++; + } + dev->pos = 0; + } + dev->readcount--; + if ((dev->enable_irq & IRQ_DATAREADY) && first) + picint(1 << dev->irq); + return 1; +} + +static uint8_t +mitsumi_cdrom_in(uint16_t port, void *priv) +{ + mcd_t *dev = (mcd_t *) priv; + uint8_t ret; + + pclog("Mitsumi CD-ROM IN=%03x\n", port); + switch (port & 1) { + case 0: + if (dev->cmdbuf_count) { + dev->cmdbuf_count--; + return dev->cmdbuf[dev->cmdbuf_idx++]; + } else if (dev->buf_count) { + ret = (dev->buf_idx < RAW_SECTOR_SIZE) ? dev->buf[dev->buf_idx] : 0; + dev->buf_idx++; + dev->buf_count--; + if (!dev->buf_count) + mitsumi_cdrom_read_sector(dev, 0); + + pclog("Read port 0: ret = %02x\n", ret); + return ret; + } + pclog("Read port 0: stat = %02x\n", dev->stat); + return dev->stat; + case 1: + ret = 0; + picintc(1 << dev->irq); + if (!dev->buf_count || !dev->data || dev->enable_dma) + ret |= FLAG_NODATA; + if (!dev->cmdbuf_count || !dev->newstat) + ret |= FLAG_NOSTAT; + pclog("Read port 1: ret = %02x\n", ret | FLAG_UNK); + return ret | FLAG_UNK; + case 2: + break; + default: + break; + } + + return 0xff; +} + +static void +mitsumi_cdrom_out(uint16_t port, uint8_t val, void *priv) +{ + mcd_t *dev = (mcd_t *) priv; + cdrom_t cdrom; + + pclog("Mitsumi CD-ROM OUT=%03x, val=%02x\n", port, val); + switch (port & 1) { + case 0: + if (dev->cmdrd_count) { + dev->cmdrd_count--; + switch (dev->cmd) { + case CMD_SET_MODE: + dev->mode = val; + dev->cmdbuf[1] = 0; + dev->cmdbuf_count = 2; + break; + case CMD_LOCK: + dev->locked = val & 1; + dev->cmdbuf[1] = 0; + dev->cmdbuf[2] = 0; + dev->cmdbuf_count = 3; + break; + case CMD_CONFIG: + switch (dev->cmdrd_count) { + case 0: + switch (dev->conf) { + case 0x01: + dev->dmalen |= val; + break; + case 0x02: + dev->enable_dma = val; + break; + case 0x10: + dev->enable_irq = val; + break; + default: + break; + } + dev->cmdbuf[1] = 0; + dev->cmdbuf_count = 2; + dev->conf = 0; + break; + case 1: + if (dev->conf == 1) { + dev->dmalen = val << 8; + break; + } + dev->conf = val; + if (dev->conf == 1) + dev->cmdrd_count++; + break; + default: + break; + } + break; + case CMD_READ1X: + case CMD_READ2X: + switch (dev->cmdrd_count) { + case 0: + dev->readcount |= val; + mitsumi_cdrom_read_sector(dev, 1); + dev->cmdbuf_count = 1; + dev->cmdbuf[0] = STAT_SPIN | STAT_READY; + break; + case 1: + dev->readcount |= (val << 8); + break; + case 2: + dev->readcount = (val << 16); + break; + case 5: + dev->readmsf = 0; + fallthrough; + case 4: + case 3: + dev->readmsf |= CD_DCB(val) << ((dev->cmdrd_count - 3) << 3); + break; + default: + break; + } + break; + default: + break; + } + if (!dev->cmdrd_count) + dev->stat = cdrom.host_drive ? (STAT_READY | (dev->change ? STAT_CHANGE : 0)) : 0; + return; + } + dev->cmd = val; + dev->cmdbuf_idx = 0; + dev->cmdrd_count = 0; + dev->cmdbuf_count = 1; + dev->cmdbuf[0] = cdrom.host_drive ? (STAT_READY | (dev->change ? STAT_CHANGE : 0)) : 0; + dev->data = 0; + switch (val) { + case CMD_GET_INFO: + if (cdrom.host_drive) { + cdrom_get_track_buffer(&cdrom, &(dev->cmdbuf[1])); + dev->cmdbuf_count = 10; + dev->readcount = 0; + } else { + dev->cmdbuf_count = 1; + dev->cmdbuf[0] = STAT_CMD_CHECK; + } + break; + case CMD_GET_Q: + if (cdrom.host_drive) { + cdrom_get_q(&cdrom, &(dev->cmdbuf[1]), &dev->cur_toc_track, dev->mode & MODE_GET_TOC); + dev->cmdbuf_count = 11; + dev->readcount = 0; + } else { + dev->cmdbuf_count = 1; + dev->cmdbuf[0] = STAT_CMD_CHECK; + } + break; + case CMD_GET_STAT: + dev->change = 0; + break; + case CMD_SET_MODE: + dev->cmdrd_count = 1; + break; + case CMD_STOPCDDA: + case CMD_STOP: + cdrom_stop(&cdrom); + dev->drvmode = DRV_MODE_STOP; + dev->cur_toc_track = 0; + break; + case CMD_CONFIG: + dev->cmdrd_count = 2; + break; + case CMD_READ1X: + case CMD_READ2X: + if (cdrom.host_drive) { + dev->readcount = 0; + dev->drvmode = (val == CMD_READ1X) ? DRV_MODE_CDDA : DRV_MODE_READ; + dev->cmdrd_count = 6; + } else { + dev->cmdbuf_count = 1; + dev->cmdbuf[0] = STAT_CMD_CHECK; + } + break; + case CMD_GET_VER: + dev->cmdbuf[0] = 1; + dev->cmdbuf[1] = 'D'; + dev->cmdbuf[2] = 0; + dev->cmdbuf_count = 3; + break; + case CMD_EJECT: + cdrom_stop(&cdrom); + cdrom_eject(0); + dev->readcount = 0; + break; + case CMD_LOCK: + dev->cmdrd_count = 1; + break; + case CMD_SOFT_RESET: + pclog("Soft Reset\n"); + mitsumi_cdrom_reset(dev); + break; + default: + dev->cmdbuf[0] = dev->stat | STAT_CMD_CHECK; + break; + } + break; + case 1: + mitsumi_cdrom_reset(dev); + break; + case 2: + break; + default: + break; + } +} + +static void * +mitsumi_cdrom_init(UNUSED(const device_t *info)) +{ + mcd_t *dev; + + dev = malloc(sizeof(mcd_t)); + memset(dev, 0x00, sizeof(mcd_t)); + + dev->irq = MCD_DEFAULT_IRQ; + dev->dma = MCD_DEFAULT_DMA; + + io_sethandler(MCD_DEFAULT_IOPORT, 3, + mitsumi_cdrom_in, NULL, NULL, mitsumi_cdrom_out, NULL, NULL, dev); + + mitsumi_cdrom_reset(dev); + + return dev; +} + +static void +mitsumi_cdrom_close(void *priv) +{ + mcd_t *dev = (mcd_t *) priv; + + if (dev) { + free(dev); + dev = NULL; + } +} + +const device_t mitsumi_cdrom_device = { + .name = "Mitsumi CD-ROM interface", + .internal_name = "mcd", + .flags = DEVICE_ISA | DEVICE_AT, + .local = 1, + .init = mitsumi_cdrom_init, + .close = mitsumi_cdrom_close, + .reset = NULL, + { .available = NULL }, + .speed_changed = NULL, + .force_redraw = NULL, + .config = NULL +}; diff --git a/src/chipset/82c100.c b/src/chipset/82c100.c index 76a6590bf..689234ebb 100644 --- a/src/chipset/82c100.c +++ b/src/chipset/82c100.c @@ -1,24 +1,26 @@ /* - * 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. + * 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. + * This file is part of the 86Box distribution. * - * Implementation of Chips&Technology's 82C100 chipset. + * Implementation of Chips&Technology's 82C100 chipset. * * * - * Authors: Miran Grca, + * Authors: Miran Grca, * - * Copyright 2021 Miran Grca. + * Copyright 2021 Miran Grca. */ +#include #include #include #include #include #include +#define HAVE_STDARG_H #include <86box/86box.h> #include <86box/device.h> #include "cpu.h" @@ -26,33 +28,30 @@ #include <86box/io.h> #include <86box/mem.h> #include <86box/nmi.h> +#include <86box/plat_unused.h> #include <86box/port_92.h> #include <86box/rom.h> #include <86box/chipset.h> - -typedef struct -{ - int enabled; - uint32_t virt, phys; +typedef struct ems_page_t { + int enabled; + uint32_t virt; + uint32_t phys; } ems_page_t; - -typedef struct -{ - uint8_t index, access; - uint16_t ems_io_base; - uint32_t ems_window_base; - uint8_t ems_page_regs[4], - regs[256]; - ems_page_t ems_pages[4]; - mem_mapping_t ems_mappings[4]; +typedef struct ct_82c100_t { + uint8_t index; + uint8_t access; + uint16_t ems_io_base; + uint32_t ems_window_base; + uint8_t ems_page_regs[4]; + uint8_t regs[256]; + ems_page_t ems_pages[4]; + mem_mapping_t ems_mappings[4]; } ct_82c100_t; - #ifdef ENABLE_CT_82C100_LOG -int ct_82c100_do_log = ENABLE_CT82C100_LOG; - +int ct_82c100_do_log = ENABLE_CT_82C100_LOG; static void ct_82c100_log(const char *fmt, ...) @@ -60,46 +59,43 @@ ct_82c100_log(const char *fmt, ...) va_list ap; if (ct_82c100_do_log) { - va_start(ap, fmt); - pclog_ex(fmt, ap); - va_end(ap); + va_start(ap, fmt); + pclog_ex(fmt, ap); + va_end(ap); } } #else -#define ct_82c100_log(fmt, ...) +# define ct_82c100_log(fmt, ...) #endif - static void ct_82c100_ems_pages_recalc(ct_82c100_t *dev) { - int i; uint32_t page_base; - for (i = 0; i < 4; i++) { - page_base = dev->ems_window_base + (i << 14); - if ((i == 1) || (i == 2)) - page_base ^= 0xc000; - if (dev->ems_page_regs[i] & 0x80) { - dev->ems_pages[i].virt = page_base; - dev->ems_pages[i].phys = 0xa0000 + (((uint32_t) (dev->ems_page_regs[i] & 0x7f)) << 14); - ct_82c100_log("Enabling EMS page %i: %08X-%08X -> %08X-%08X\n", i, - dev->ems_pages[i].virt, dev->ems_pages[i].virt + 0x00003fff, - dev->ems_pages[i].phys, dev->ems_pages[i].phys + 0x00003fff); - mem_mapping_set_addr(&(dev->ems_mappings[i]), dev->ems_pages[i].virt, 0x4000); - mem_mapping_set_exec(&(dev->ems_mappings[i]), &(ram[dev->ems_pages[i].phys])); - mem_set_mem_state_both(page_base, 0x00004000, MEM_READ_INTERNAL | MEM_WRITE_INTERNAL); - } else { - ct_82c100_log("Disabling EMS page %i\n", i); - mem_mapping_disable(&(dev->ems_mappings[i])); - mem_set_mem_state_both(page_base, 0x00004000, MEM_READ_EXTANY | MEM_WRITE_EXTANY); - } + for (uint8_t i = 0; i < 4; i++) { + page_base = dev->ems_window_base + (i << 14); + if ((i == 1) || (i == 2)) + page_base ^= 0xc000; + if (dev->ems_page_regs[i] & 0x80) { + dev->ems_pages[i].virt = page_base; + dev->ems_pages[i].phys = 0xa0000 + (((uint32_t) (dev->ems_page_regs[i] & 0x7f)) << 14); + ct_82c100_log("Enabling EMS page %i: %08X-%08X -> %08X-%08X\n", i, + dev->ems_pages[i].virt, dev->ems_pages[i].virt + 0x00003fff, + dev->ems_pages[i].phys, dev->ems_pages[i].phys + 0x00003fff); + mem_mapping_set_addr(&(dev->ems_mappings[i]), dev->ems_pages[i].virt, 0x4000); + mem_mapping_set_exec(&(dev->ems_mappings[i]), &(ram[dev->ems_pages[i].phys])); + mem_set_mem_state_both(page_base, 0x00004000, MEM_READ_INTERNAL | MEM_WRITE_INTERNAL); + } else { + ct_82c100_log("Disabling EMS page %i\n", i); + mem_mapping_disable(&(dev->ems_mappings[i])); + mem_set_mem_state_both(page_base, 0x00004000, MEM_READ_EXTANY | MEM_WRITE_EXTANY); + } } flushmmucache_nopc(); } - static void ct_82c100_ems_out(uint16_t port, uint8_t val, void *priv) { @@ -110,36 +106,32 @@ ct_82c100_ems_out(uint16_t port, uint8_t val, void *priv) ct_82c100_ems_pages_recalc(dev); } - static uint8_t ct_82c100_ems_in(uint16_t port, void *priv) { - ct_82c100_t *dev = (ct_82c100_t *) priv; - uint8_t ret = 0xff; + const ct_82c100_t *dev = (ct_82c100_t *) priv; + uint8_t ret = 0xff; ret = dev->ems_page_regs[port >> 14]; return ret; } - static void ct_82c100_ems_update(ct_82c100_t *dev) { - int i; - - for (i = 0; i < 4; i++) { - ct_82c100_log("Disabling EMS I/O handler %i at %04X\n", i, dev->ems_io_base + (i << 14)); - io_handler(0, dev->ems_io_base + (i << 14), 1, - ct_82c100_ems_in, NULL, NULL, ct_82c100_ems_out, NULL, NULL, dev); + for (uint8_t i = 0; i < 4; i++) { + ct_82c100_log("Disabling EMS I/O handler %i at %04X\n", i, dev->ems_io_base + (i << 14)); + io_handler(0, dev->ems_io_base + (i << 14), 1, + ct_82c100_ems_in, NULL, NULL, ct_82c100_ems_out, NULL, NULL, dev); } dev->ems_io_base = 0x0208 + (dev->regs[0x4c] & 0xf0); - for (i = 0; i < 4; i++) { - ct_82c100_log("Enabling EMS I/O handler %i at %04X\n", i, dev->ems_io_base + (i << 14)); - io_handler(1, dev->ems_io_base + (i << 14), 1, - ct_82c100_ems_in, NULL, NULL, ct_82c100_ems_out, NULL, NULL, dev); + for (uint8_t i = 0; i < 4; i++) { + ct_82c100_log("Enabling EMS I/O handler %i at %04X\n", i, dev->ems_io_base + (i << 14)); + io_handler(1, dev->ems_io_base + (i << 14), 1, + ct_82c100_ems_in, NULL, NULL, ct_82c100_ems_out, NULL, NULL, dev); } dev->ems_window_base = 0xc0000 + (((uint32_t) (dev->regs[0x4c] & 0x0f)) << 14); @@ -147,7 +139,6 @@ ct_82c100_ems_update(ct_82c100_t *dev) ct_82c100_ems_pages_recalc(dev); } - static void ct_82c100_reset(void *priv) { @@ -161,7 +152,7 @@ ct_82c100_reset(void *priv) dev->index = dev->access = 0x00; /* INTERNAL CONFIGURATION/CONTROL REGISTERS */ - dev->regs[0x40] = 0x01; /* Defaults to 8086/V30 mode. */ + dev->regs[0x40] = 0x01; /* Defaults to 8086/V30 mode. */ dev->regs[0x43] = 0x30; dev->regs[0x48] = 0x01; @@ -171,188 +162,189 @@ ct_82c100_reset(void *priv) /* ADDITIONAL I/O REGISTERS */ } - static void ct_82c100_out(uint16_t port, uint8_t val, void *priv) { ct_82c100_t *dev = (ct_82c100_t *) priv; if (port == 0x0022) { - dev->index = val; - dev->access = 1; + dev->index = val; + dev->access = 1; } else if (port == 0x0023) { - if (dev->access) { - switch (dev->index) { - /* INTERNAL CONFIGURATION/CONTROL REGISTERS */ - case 0x40: - dev->regs[0x40] = val & 0xc7; - /* TODO: Clock stuff - needs CPU speed change functionality that's - going to be implemented in 86box v4.0. - Bit 0 is 0 for 8088/V20 and 1 for 8086/V30. */ - break; - case 0x41: - dev->regs[0x41] = val & 0xed; - /* TODO: Where is the Software Reset Function that's enabled by - setting bit 6 to 1? */ - break; - case 0x42: - dev->regs[0x42] = val & 0x01; - break; - case 0x43: - dev->regs[0x43] = val; - break; - case 0x44: - dev->regs[0x44] = val; - custom_nmi_vector = (custom_nmi_vector & 0xffffff00) | ((uint32_t) val); - break; - case 0x45: - dev->regs[0x45] = val; - custom_nmi_vector = (custom_nmi_vector & 0xffff00ff) | (((uint32_t) val) << 8); - break; - case 0x46: - dev->regs[0x46] = val; - custom_nmi_vector = (custom_nmi_vector & 0xff00ffff) | (((uint32_t) val) << 16); - break; - case 0x47: - dev->regs[0x47] = val; - custom_nmi_vector = (custom_nmi_vector & 0x00ffffff) | (((uint32_t) val) << 24); - break; - case 0x48: case 0x49: - dev->regs[dev->index] = val; - break; - case 0x4b: - dev->regs[0x4b] = val; - use_custom_nmi_vector = !!(val & 0x40); - break; - case 0x4c: - ct_82c100_log("CS4C: %02X\n", val); - dev->regs[0x4c] = val; - ct_82c100_ems_update(dev); - break; - } - dev->access = 0; - } + if (dev->access) { + switch (dev->index) { + /* INTERNAL CONFIGURATION/CONTROL REGISTERS */ + case 0x40: + dev->regs[0x40] = val & 0xc7; + /* TODO: Clock stuff - needs CPU speed change functionality that's + going to be implemented in 86box v4.0. + Bit 0 is 0 for 8088/V20 and 1 for 8086/V30. */ + break; + case 0x41: + dev->regs[0x41] = val & 0xed; + /* TODO: Where is the Software Reset Function that's enabled by + setting bit 6 to 1? */ + break; + case 0x42: + dev->regs[0x42] = val & 0x01; + break; + case 0x43: + dev->regs[0x43] = val; + break; + case 0x44: + dev->regs[0x44] = val; + custom_nmi_vector = (custom_nmi_vector & 0xffffff00) | ((uint32_t) val); + break; + case 0x45: + dev->regs[0x45] = val; + custom_nmi_vector = (custom_nmi_vector & 0xffff00ff) | (((uint32_t) val) << 8); + break; + case 0x46: + dev->regs[0x46] = val; + custom_nmi_vector = (custom_nmi_vector & 0xff00ffff) | (((uint32_t) val) << 16); + break; + case 0x47: + dev->regs[0x47] = val; + custom_nmi_vector = (custom_nmi_vector & 0x00ffffff) | (((uint32_t) val) << 24); + break; + case 0x48: + case 0x49: + dev->regs[dev->index] = val; + break; + case 0x4b: + dev->regs[0x4b] = val; + use_custom_nmi_vector = !!(val & 0x40); + break; + case 0x4c: + ct_82c100_log("CS4C: %02X\n", val); + dev->regs[0x4c] = val; + ct_82c100_ems_update(dev); + break; + + default: + break; + } + dev->access = 0; + } } else if (port == 0x72) - dev->regs[0x72] = val & 0x7e; + dev->regs[0x72] = val & 0x7e; else if (port == 0x7e) - dev->regs[0x7e] = val; + dev->regs[0x7e] = val; else if (port == 0x7f) { - /* Bit 3 is Software Controlled Reset, asserted if set. Will be - done in the feature/machine_and_kb branch using hardresetx86(). */ - dev->regs[0x7f] = val; - if ((dev->regs[0x41] & 0x40) && (val & 0x08)) { - softresetx86(); - cpu_set_edx(); - ct_82c100_reset(dev); - } + /* Bit 3 is Software Controlled Reset, asserted if set. Will be + done in the feature/machine_and_kb branch using hardresetx86(). */ + dev->regs[0x7f] = val; + if ((dev->regs[0x41] & 0x40) && (val & 0x08)) { + softresetx86(); + cpu_set_edx(); + ct_82c100_reset(dev); + } } } - static uint8_t ct_82c100_in(uint16_t port, void *priv) { ct_82c100_t *dev = (ct_82c100_t *) priv; - uint8_t ret = 0xff; + uint8_t ret = 0xff; if (port == 0x0022) - ret = dev->index; + ret = dev->index; else if (port == 0x0023) { - if (dev->access) { - switch (dev->index) { - /* INTERNAL CONFIGURATION/CONTROL REGISTERS */ - case 0x40 ... 0x49: - case 0x4b: case 0x4c: - ret = dev->regs[dev->index]; - break; - } - dev->access = 0; - } + if (dev->access) { + switch (dev->index) { + /* INTERNAL CONFIGURATION/CONTROL REGISTERS */ + case 0x40 ... 0x49: + case 0x4b: + case 0x4c: + ret = dev->regs[dev->index]; + break; + + default: + break; + } + dev->access = 0; + } } else if (port == 0x72) - ret = dev->regs[0x72]; + ret = dev->regs[0x72]; else if (port == 0x7e) - ret = dev->regs[0x7e]; + ret = dev->regs[0x7e]; else if (port == 0x7f) - ret = dev->regs[0x7f]; + ret = dev->regs[0x7f]; return ret; } - static uint8_t mem_read_emsb(uint32_t addr, void *priv) { - ems_page_t *page = (ems_page_t *)priv; - uint8_t ret = 0xff; + const ems_page_t *page = (ems_page_t *) priv; + uint8_t ret = 0xff; #ifdef ENABLE_CT_82C100_LOG uint32_t old_addr = addr; #endif addr = addr - page->virt + page->phys; - if (addr < ((uint32_t)mem_size << 10)) - ret = ram[addr]; + if (addr < (mem_size << 10)) + ret = ram[addr]; ct_82c100_log("mem_read_emsb(%08X = %08X): %02X\n", old_addr, addr, ret); return ret; } - static uint16_t mem_read_emsw(uint32_t addr, void *priv) { - ems_page_t *page = (ems_page_t *)priv; - uint16_t ret = 0xffff; + const ems_page_t *page = (ems_page_t *) priv; + uint16_t ret = 0xffff; #ifdef ENABLE_CT_82C100_LOG uint32_t old_addr = addr; #endif addr = addr - page->virt + page->phys; - if (addr < ((uint32_t)mem_size << 10)) - ret = *(uint16_t *)&ram[addr]; + if (addr < (mem_size << 10)) + ret = *(uint16_t *) &ram[addr]; ct_82c100_log("mem_read_emsw(%08X = %08X): %04X\n", old_addr, addr, ret); return ret; } - static void mem_write_emsb(uint32_t addr, uint8_t val, void *priv) { - ems_page_t *page = (ems_page_t *)priv; + const ems_page_t *page = (ems_page_t *) priv; #ifdef ENABLE_CT_82C100_LOG uint32_t old_addr = addr; #endif addr = addr - page->virt + page->phys; - if (addr < ((uint32_t)mem_size << 10)) - ram[addr] = val; + if (addr < (mem_size << 10)) + ram[addr] = val; ct_82c100_log("mem_write_emsb(%08X = %08X, %02X)\n", old_addr, addr, val); } - static void mem_write_emsw(uint32_t addr, uint16_t val, void *priv) { - ems_page_t *page = (ems_page_t *)priv; + const ems_page_t *page = (ems_page_t *) priv; #ifdef ENABLE_CT_82C100_LOG uint32_t old_addr = addr; #endif addr = addr - page->virt + page->phys; - if (addr < ((uint32_t)mem_size << 10)) - *(uint16_t *)&ram[addr] = val; + if (addr < (mem_size << 10)) + *(uint16_t *) &ram[addr] = val; ct_82c100_log("mem_write_emsw(%08X = %08X, %04X)\n", old_addr, addr, val); } - static void ct_82c100_close(void *priv) { @@ -361,47 +353,48 @@ ct_82c100_close(void *priv) free(dev); } - static void * -ct_82c100_init(const device_t *info) +ct_82c100_init(UNUSED(const device_t *info)) { ct_82c100_t *dev; - uint32_t i; - dev = (ct_82c100_t *)malloc(sizeof(ct_82c100_t)); + dev = (ct_82c100_t *) malloc(sizeof(ct_82c100_t)); memset(dev, 0x00, sizeof(ct_82c100_t)); ct_82c100_reset(dev); io_sethandler(0x0022, 2, - ct_82c100_in, NULL, NULL, ct_82c100_out, NULL, NULL, dev); + ct_82c100_in, NULL, NULL, ct_82c100_out, NULL, NULL, dev); io_sethandler(0x0072, 1, - ct_82c100_in, NULL, NULL, ct_82c100_out, NULL, NULL, dev); + ct_82c100_in, NULL, NULL, ct_82c100_out, NULL, NULL, dev); io_sethandler(0x007e, 2, - ct_82c100_in, NULL, NULL, ct_82c100_out, NULL, NULL, dev); + ct_82c100_in, NULL, NULL, ct_82c100_out, NULL, NULL, dev); - for (i = 0; i < 4; i++) { - mem_mapping_add(&(dev->ems_mappings[i]), (i + 28) << 14, 0x04000, - mem_read_emsb, mem_read_emsw, NULL, - mem_write_emsb, mem_write_emsw, NULL, - ram + 0xa0000 + (i << 14), MEM_MAPPING_INTERNAL, &dev->ems_pages[i]); - mem_mapping_disable(&(dev->ems_mappings[i])); + for (uint8_t i = 0; i < 4; i++) { + mem_mapping_add(&(dev->ems_mappings[i]), (i + 28) << 14, 0x04000, + mem_read_emsb, mem_read_emsw, NULL, + mem_write_emsb, mem_write_emsw, NULL, + ram + 0xa0000 + (i << 14), MEM_MAPPING_INTERNAL, &dev->ems_pages[i]); + mem_mapping_disable(&(dev->ems_mappings[i])); } mem_mapping_disable(&ram_mid_mapping); device_add(&port_92_device); - return(dev); + return dev; } - const device_t ct_82c100_device = { - "C&T 82C100", - "ct_82c100", - 0, - 0, - ct_82c100_init, ct_82c100_close, ct_82c100_reset, - { NULL }, NULL, NULL, - NULL + .name = "C&T 82C100", + .internal_name = "ct_82c100", + .flags = 0, + .local = 0, + .init = ct_82c100_init, + .close = ct_82c100_close, + .reset = ct_82c100_reset, + { .available = NULL }, + .speed_changed = NULL, + .force_redraw = NULL, + .config = NULL }; diff --git a/src/chipset/CMakeLists.txt b/src/chipset/CMakeLists.txt index 5be4490af..0f3c78c84 100644 --- a/src/chipset/CMakeLists.txt +++ b/src/chipset/CMakeLists.txt @@ -1,26 +1,27 @@ # -# 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. +# 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. +# This file is part of the 86Box distribution. # -# CMake build script. +# CMake build script. # -# Authors: David HrdliÄka, +# Authors: David HrdliÄka, # -# Copyright 2020,2021 David HrdliÄka. +# Copyright 2020-2021 David HrdliÄka. # -add_library(chipset OBJECT 82c100.c acc2168.c cs8230.c ali1429.c ali1489.c ali1531.c ali1541.c ali1543.c - ali1621.c ali6117.c headland.c ims8848.c intel_82335.c contaq_82c59x.c cs4031.c intel_420ex.c - intel_4x0.c intel_i450kx.c intel_sio.c intel_piix.c ../ioapic.c neat.c opti283.c opti291.c opti391.c - opti495.c opti822.c opti895.c opti5x7.c scamp.c scat.c sis_85c310.c sis_85c4xx.c - sis_85c496.c sis_85c50x.c sis_5511.c sis_5571.c via_vt82c49x.c via_vt82c505.c sis_85c310.c - sis_85c4xx.c sis_85c496.c sis_85c50x.c gc100.c stpc.c umc_8886.c umc_hb4.c via_apollo.c - via_pipc.c vl82c480.c wd76c10.c) +add_library(chipset OBJECT 82c100.c acc2168.c cs8230.c ali1429.c ali1435.c ali1489.c + ali1531.c ali1541.c ali1543.c ali1621.c ali6117.c headland.c ims8848.c intel_82335.c + compaq_386.c contaq_82c59x.c cs4031.c intel_420ex.c intel_4x0.c intel_i450kx.c + intel_sio.c intel_piix.c ../ioapic.c neat.c opti283.c opti291.c opti391.c opti495.c + opti602.c opti822.c opti895.c opti5x7.c scamp.c scat.c sis_85c310.c sis_85c4xx.c + sis_85c496.c sis_85c50x.c sis_5511.c sis_5571.c via_vt82c49x.c via_vt82c505.c + sis_85c310.c sis_85c4xx.c sis_85c496.c sis_85c50x.c gc100.c stpc.c umc_8886.c + umc_hb4.c via_apollo.c via_pipc.c vl82c480.c wd76c10.c) if(OLIVETTI) target_sources(chipset PRIVATE olivetti_eva.c) -endif() \ No newline at end of file +endif() diff --git a/src/chipset/acc2168.c b/src/chipset/acc2168.c index ba8331447..9ce29bdff 100644 --- a/src/chipset/acc2168.c +++ b/src/chipset/acc2168.c @@ -1,20 +1,20 @@ /* - * 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. + * 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. + * This file is part of the 86Box distribution. * - * Implementation of the ACC 2046/2168 chipset + * Implementation of the ACC 2046/2168 chipset * * * - * Authors: Sarah Walker, + * Authors: Sarah Walker, * Tiseno100 * - * Copyright 2019 Sarah Walker. - * Copyright 2021 Tiseno100. + * Copyright 2019 Sarah Walker. + * Copyright 2021 Tiseno100. */ #include #include @@ -30,144 +30,145 @@ #include <86box/io.h> #include <86box/mem.h> #include <86box/port_92.h> +#include <86box/plat_unused.h> #include <86box/chipset.h> -#define ENABLED_SHADOW (MEM_READ_INTERNAL | ((dev->regs[0x02] & 0x20) ? MEM_WRITE_DISABLED : MEM_WRITE_INTERNAL)) +#define ENABLED_SHADOW (MEM_READ_INTERNAL | ((dev->regs[0x02] & 0x20) ? MEM_WRITE_DISABLED : MEM_WRITE_INTERNAL)) #define DISABLED_SHADOW (MEM_READ_EXTANY | MEM_WRITE_EXTANY) -#define SHADOW_ADDR ((i <= 1) ? (0xc0000 + (i << 15)) : (0xd0000 + ((i - 2) << 16))) -#define SHADOW_SIZE ((i <= 1) ? 0x8000 : 0x10000) -#define SHADOW_RECALC ((dev->regs[0x02] & (1 << i)) ? ENABLED_SHADOW : DISABLED_SHADOW) +#define SHADOW_ADDR ((i <= 1) ? (0xc0000 + (i << 15)) : (0xd0000 + ((i - 2) << 16))) +#define SHADOW_SIZE ((i <= 1) ? 0x8000 : 0x10000) +#define SHADOW_RECALC ((dev->regs[0x02] & (1 << i)) ? ENABLED_SHADOW : DISABLED_SHADOW) #ifdef ENABLE_ACC2168_LOG int acc2168_do_log = ENABLE_ACC2168_LOG; + static void acc2168_log(const char *fmt, ...) { va_list ap; if (acc2168_do_log) { - va_start(ap, fmt); - pclog_ex(fmt, ap); - va_end(ap); + va_start(ap, fmt); + pclog_ex(fmt, ap); + va_end(ap); } } #else -#define acc2168_log(fmt, ...) +# define acc2168_log(fmt, ...) #endif -typedef struct acc2168_t -{ - uint8_t reg_idx, regs[256]; +typedef struct acc2168_t { + uint8_t reg_idx; + uint8_t regs[256]; } acc2168_t; static void acc2168_shadow_recalc(acc2168_t *dev) { - for (uint32_t i = 0; i < 5; i++) + for (uint8_t i = 0; i < 5; i++) mem_set_mem_state_both(SHADOW_ADDR, SHADOW_SIZE, SHADOW_RECALC); } static void -acc2168_write(uint16_t addr, uint8_t val, void *p) +acc2168_write(uint16_t addr, uint8_t val, void *priv) { - acc2168_t *dev = (acc2168_t *)p; + acc2168_t *dev = (acc2168_t *) priv; - switch (addr) - { - case 0xf2: - dev->reg_idx = val; - break; - case 0xf3: - acc2168_log("ACC2168: dev->regs[%02x] = %02x\n", dev->reg_idx, val); - switch (dev->reg_idx) - { - case 0x00: - dev->regs[dev->reg_idx] = val; + switch (addr) { + case 0xf2: + dev->reg_idx = val; break; + case 0xf3: + acc2168_log("ACC2168: dev->regs[%02x] = %02x\n", dev->reg_idx, val); + switch (dev->reg_idx) { + case 0x00: + dev->regs[dev->reg_idx] = val; + break; - case 0x01: - dev->regs[dev->reg_idx] = val & 0xd3; - cpu_update_waitstates(); + case 0x01: + dev->regs[dev->reg_idx] = val & 0xd3; + cpu_update_waitstates(); + break; + + case 0x02: + dev->regs[dev->reg_idx] = val & 0x7f; + acc2168_shadow_recalc(dev); + break; + + case 0x03: + dev->regs[dev->reg_idx] = val & 0x1f; + break; + + case 0x04: + dev->regs[dev->reg_idx] = val; + cpu_cache_ext_enabled = !!(val & 0x01); + cpu_update_waitstates(); + break; + + case 0x05: + dev->regs[dev->reg_idx] = val & 0xf3; + break; + + case 0x06: + case 0x07: + dev->regs[dev->reg_idx] = val & 0x1f; + break; + + case 0x08: + dev->regs[dev->reg_idx] = val & 0x0f; + break; + + case 0x09: + dev->regs[dev->reg_idx] = val & 0x03; + break; + + case 0x0a: + case 0x0b: + case 0x0c: + case 0x0d: + case 0x0e: + case 0x0f: + case 0x10: + case 0x11: + dev->regs[dev->reg_idx] = val; + break; + + case 0x12: + dev->regs[dev->reg_idx] = val & 0xbb; + break; + + case 0x18: + dev->regs[dev->reg_idx] = val & 0x77; + break; + + case 0x19: + dev->regs[dev->reg_idx] = val & 0xfb; + break; + + case 0x1a: + dev->regs[dev->reg_idx] = val; + cpu_cache_int_enabled = !(val & 0x40); + cpu_update_waitstates(); + break; + + case 0x1b: + dev->regs[dev->reg_idx] = val & 0xef; + break; + + default: /* ACC 2168 has way more registers which we haven't documented */ + dev->regs[dev->reg_idx] = val; + break; + } break; - - case 0x02: - dev->regs[dev->reg_idx] = val & 0x7f; - acc2168_shadow_recalc(dev); + default: break; - - case 0x03: - dev->regs[dev->reg_idx] = val & 0x1f; - break; - - case 0x04: - dev->regs[dev->reg_idx] = val; - cpu_cache_ext_enabled = !!(val & 0x01); - cpu_update_waitstates(); - break; - - case 0x05: - dev->regs[dev->reg_idx] = val & 0xf3; - break; - - case 0x06: - case 0x07: - dev->regs[dev->reg_idx] = val & 0x1f; - break; - - case 0x08: - dev->regs[dev->reg_idx] = val & 0x0f; - break; - - case 0x09: - dev->regs[dev->reg_idx] = val & 0x03; - break; - - case 0x0a: - case 0x0b: - case 0x0c: - case 0x0d: - case 0x0e: - case 0x0f: - case 0x10: - case 0x11: - dev->regs[dev->reg_idx] = val; - break; - - case 0x12: - dev->regs[dev->reg_idx] = val & 0xbb; - break; - - case 0x18: - dev->regs[dev->reg_idx] = val & 0x77; - break; - - case 0x19: - dev->regs[dev->reg_idx] = val & 0xfb; - break; - - case 0x1a: - dev->regs[dev->reg_idx] = val; - cpu_cache_int_enabled = !(val & 0x40); - cpu_update_waitstates(); - break; - - case 0x1b: - dev->regs[dev->reg_idx] = val & 0xef; - break; - - default: /* ACC 2168 has way more registers which we haven't documented */ - dev->regs[dev->reg_idx] = val; - break; - - } - break; } } static uint8_t -acc2168_read(uint16_t addr, void *p) +acc2168_read(uint16_t addr, void *priv) { - acc2168_t *dev = (acc2168_t *)p; + const acc2168_t *dev = (acc2168_t *) priv; return (addr == 0xf3) ? dev->regs[dev->reg_idx] : dev->reg_idx; } @@ -175,15 +176,15 @@ acc2168_read(uint16_t addr, void *p) static void acc2168_close(void *priv) { - acc2168_t *dev = (acc2168_t *)priv; + acc2168_t *dev = (acc2168_t *) priv; free(dev); } static void * -acc2168_init(const device_t *info) +acc2168_init(UNUSED(const device_t *info)) { - acc2168_t *dev = (acc2168_t *)malloc(sizeof(acc2168_t)); + acc2168_t *dev = (acc2168_t *) malloc(sizeof(acc2168_t)); memset(dev, 0, sizeof(acc2168_t)); device_add(&port_92_device); @@ -193,14 +194,15 @@ acc2168_init(const device_t *info) } const device_t acc2168_device = { - "ACC 2046/2168", - "acc2168", - 0, - 0, - acc2168_init, - acc2168_close, - NULL, - {NULL}, - NULL, - NULL, - NULL}; + .name = "ACC 2046/2168", + .internal_name = "acc2168", + .flags = 0, + .local = 0, + .init = acc2168_init, + .close = acc2168_close, + .reset = NULL, + { .available = NULL }, + .speed_changed = NULL, + .force_redraw = NULL, + .config = NULL +}; diff --git a/src/chipset/ali1429.c b/src/chipset/ali1429.c index ccd7e5007..34c3e18c2 100644 --- a/src/chipset/ali1429.c +++ b/src/chipset/ali1429.c @@ -1,21 +1,23 @@ /* - * 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. + * 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. + * This file is part of the 86Box distribution. * - * Implementation of the ALi M1429 chipset. + * Implementation of the ALi M1429 chipset. * - * Note: This chipset has no datasheet, everything were done via - * reverse engineering the BIOS of various machines using it. + * Note: This chipset has no datasheet, everything were done via + * reverse engineering the BIOS of various machines using it. * - * Authors: Tiseno100, - * Miran Grca, * - * Copyright 2020,2021 Tiseno100. - * Copyright 2021,2021 Miran Grca. + * + * Authors: Tiseno100, + * Miran Grca, + * + * Copyright 2020-2021 Tiseno100. + * Copyright 2021 Miran Grca. */ /* @@ -64,15 +66,14 @@ Register 20h: Bits 2-1-0: Bus Clock Speed 0 0 0: 7.1519Mhz (ATCLK2) - 0 0 1: CLK2IN/4 - 0 1 0: CLK2IN/5 - 0 1 1: CLK2IN/6 - 1 0 0: CLK2IN/8 - 1 0 1: CLK2IN/10 - 1 1 0: CLK2IN/12 + 0 0 1: CLK2IN/4 + 0 1 0: CLK2IN/5 + 0 1 1: CLK2IN/6 + 1 0 0: CLK2IN/8 + 1 0 1: CLK2IN/10 + 1 1 0: CLK2IN/12 */ - #include #include #include @@ -94,13 +95,11 @@ #include <86box/smram.h> #include <86box/chipset.h> -#define GREEN dev->is_g /* Is G Variant */ - +#define GREEN dev->is_g /* Is G Variant */ #ifdef ENABLE_ALI1429_LOG int ali1429_do_log = ENABLE_ALI1429_LOG; - static void ali1429_log(const char *fmt, ...) { @@ -113,29 +112,31 @@ ali1429_log(const char *fmt, ...) } } #else -#define ali1429_log(fmt, ...) +# define ali1429_log(fmt, ...) #endif - -typedef struct -{ - uint8_t is_g, index, cfg_locked, reg_57h, - regs[90]; +typedef struct ali_1429_t { + uint8_t is_g; + uint8_t index; + uint8_t cfg_locked; + uint8_t reg_57h; + uint8_t regs[90]; } ali1429_t; - static void ali1429_shadow_recalc(ali1429_t *dev) { - uint32_t base, i, can_write, can_read; + uint32_t base; + uint32_t can_write; + uint32_t can_read; - shadowbios = (dev->regs[0x13] & 0x40) && (dev->regs[0x14] & 0x01); + shadowbios = (dev->regs[0x13] & 0x40) && (dev->regs[0x14] & 0x01); shadowbios_write = (dev->regs[0x13] & 0x40) && (dev->regs[0x14] & 0x02); can_write = (dev->regs[0x14] & 0x02) ? MEM_WRITE_INTERNAL : MEM_WRITE_EXTANY; - can_read = (dev->regs[0x14] & 0x01) ? MEM_READ_INTERNAL : MEM_READ_EXTANY; + can_read = (dev->regs[0x14] & 0x01) ? MEM_READ_INTERNAL : MEM_READ_EXTANY; - for (i = 0; i < 8; i++) { + for (uint8_t i = 0; i < 8; i++) { base = 0xc0000 + (i << 15); if (dev->regs[0x13] & (1 << i)) @@ -147,147 +148,159 @@ ali1429_shadow_recalc(ali1429_t *dev) flushmmucache_nopc(); } - static void ali1429_write(uint16_t addr, uint8_t val, void *priv) { - ali1429_t *dev = (ali1429_t *)priv; + ali1429_t *dev = (ali1429_t *) priv; switch (addr) { - case 0x22: - dev->index = val; - break; + case 0x22: + dev->index = val; + break; - case 0x23: + case 0x23: #ifdef ENABLE_ALI1429_LOG - if (dev->index != 0x03) - ali1429_log("M1429: dev->regs[%02x] = %02x\n", dev->index, val); + if (dev->index != 0x03) + ali1429_log("M1429: dev->regs[%02x] = %02x\n", dev->index, val); #endif - if (dev->index == 0x03) - dev->cfg_locked = !(val == 0xc5); + if (dev->index == 0x03) + dev->cfg_locked = (val != 0xc5); - if (!dev->cfg_locked) { - /* Common M1429 Registers */ - switch (dev->index) { - case 0x10: case 0x11: - dev->regs[dev->index] = val; - break; + if (!dev->cfg_locked) { + ali1429_log("M1429: dev->regs[%02x] = %02x\n", dev->index, val); - case 0x12: - dev->regs[dev->index] = val; - if(val & 4) - mem_remap_top(128); - else - mem_remap_top(0); - break; + /* Common M1429 Registers */ + switch (dev->index) { + case 0x10: + case 0x11: + dev->regs[dev->index] = val; + break; - case 0x13: case 0x14: - dev->regs[dev->index] = val; - ali1429_shadow_recalc(dev); - break; + case 0x12: + dev->regs[dev->index] = val; + if (val & 4) + mem_remap_top(128); + else + mem_remap_top(0); + break; - case 0x15: case 0x16: - case 0x17: - dev->regs[dev->index] = val; - break; + case 0x13: + case 0x14: + dev->regs[dev->index] = val; + ali1429_shadow_recalc(dev); + break; - case 0x18: - dev->regs[dev->index] = (val & 0x8f) | 0x20; - cpu_cache_ext_enabled = !!(val & 2); - cpu_update_waitstates(); - break; + case 0x15: + case 0x16: + case 0x17: + dev->regs[dev->index] = val; + break; - case 0x19: case 0x1a: - case 0x1e: - dev->regs[dev->index] = val; - break; + case 0x18: + dev->regs[dev->index] = (val & 0x8f) | 0x20; + cpu_cache_ext_enabled = !!(val & 2); + cpu_update_waitstates(); + break; - case 0x20: - dev->regs[dev->index] = val; + case 0x19: + case 0x1a: + case 0x1e: + dev->regs[dev->index] = val; + break; - switch(val & 7) { - case 0: case 7: /* Illegal */ - cpu_set_isa_speed(7159091); - break; + case 0x20: + dev->regs[dev->index] = val; - case 1: - cpu_set_isa_speed(cpu_busspeed / 4); - break; + switch (val & 7) { + case 0: + case 7: /* Illegal */ + cpu_set_isa_speed(7159091); + break; - case 2: - cpu_set_isa_speed(cpu_busspeed / 5); - break; + case 1: + cpu_set_isa_speed(cpu_busspeed / 4); + break; - case 3: - cpu_set_isa_speed(cpu_busspeed / 6); - break; + case 2: + cpu_set_isa_speed(cpu_busspeed / 5); + break; - case 4: - cpu_set_isa_speed(cpu_busspeed / 8); - break; + case 3: + cpu_set_isa_speed(cpu_busspeed / 6); + break; - case 5: - cpu_set_isa_speed(cpu_busspeed / 10); - break; + case 4: + cpu_set_isa_speed(cpu_busspeed / 8); + break; - case 6: - cpu_set_isa_speed(cpu_busspeed / 12); - break; - } - break; + case 5: + cpu_set_isa_speed(cpu_busspeed / 10); + break; - case 0x21 ... 0x27: - dev->regs[dev->index] = val; - break; - } + case 6: + cpu_set_isa_speed(cpu_busspeed / 12); + break; + default: + break; + } + break; - /* M1429G Only Registers */ - if (GREEN) { - switch (dev->index) { - case 0x30 ... 0x41: - case 0x43: case 0x45: - case 0x4a: - dev->regs[dev->index] = val; - break; + case 0x21 ... 0x27: + dev->regs[dev->index] = val; + break; + default: + break; + } - case 0x57: - dev->reg_57h = val; - break; - } - } - } - break; + /* M1429G Only Registers */ + if (GREEN) { + switch (dev->index) { + case 0x30 ... 0x41: + case 0x43: + case 0x45: + case 0x4a: + dev->regs[dev->index] = val; + break; + + case 0x57: + dev->reg_57h = val; + break; + default: + break; + } + } + } + break; + default: + break; } } - static uint8_t ali1429_read(uint16_t addr, void *priv) { - ali1429_t *dev = (ali1429_t *)priv; - uint8_t ret = 0xff; + const ali1429_t *dev = (ali1429_t *) priv; + uint8_t ret = 0xff; if ((addr == 0x23) && (dev->index >= 0x10) && (dev->index <= 0x4a)) - ret = dev->regs[dev->index]; + ret = dev->regs[dev->index]; else if ((addr == 0x23) && (dev->index == 0x57)) - ret = dev->reg_57h; + ret = dev->reg_57h; else if (addr == 0x22) - ret = dev->index; + ret = dev->index; return ret; } - static void ali1429_close(void *priv) { - ali1429_t *dev = (ali1429_t *)priv; + ali1429_t *dev = (ali1429_t *) priv; free(dev); } - static void ali1429_defaults(ali1429_t *dev) { @@ -306,28 +319,27 @@ ali1429_defaults(ali1429_t *dev) /* M1429G Default Registers */ if (GREEN) { - dev->regs[0x31] = 0x88; - dev->regs[0x32] = 0xc0; - dev->regs[0x38] = 0xe5; - dev->regs[0x40] = 0xe3; - dev->regs[0x41] = 2; - dev->regs[0x45] = 0x80; + dev->regs[0x31] = 0x88; + dev->regs[0x32] = 0xc0; + dev->regs[0x38] = 0xe5; + dev->regs[0x40] = 0xe3; + dev->regs[0x41] = 2; + dev->regs[0x45] = 0x80; } } - static void * ali1429_init(const device_t *info) { - ali1429_t *dev = (ali1429_t *)malloc(sizeof(ali1429_t)); + ali1429_t *dev = (ali1429_t *) malloc(sizeof(ali1429_t)); memset(dev, 0, sizeof(ali1429_t)); dev->cfg_locked = 1; - GREEN = info->local; + GREEN = info->local; /* M1429 Ports: - 22h Index Port - 23h Data Port + 22h Index Port + 23h Data Port */ io_sethandler(0x0022, 0x0002, ali1429_read, NULL, NULL, ali1429_write, NULL, NULL, dev); @@ -339,21 +351,29 @@ ali1429_init(const device_t *info) } const device_t ali1429_device = { - "ALi M1429", - "ali1429", - 0, - 0, - ali1429_init, ali1429_close, NULL, - { NULL }, NULL, NULL, - NULL + .name = "ALi M1429", + .internal_name = "ali1429", + .flags = 0, + .local = 0, + .init = ali1429_init, + .close = ali1429_close, + .reset = NULL, + { .available = NULL }, + .speed_changed = NULL, + .force_redraw = NULL, + .config = NULL }; const device_t ali1429g_device = { - "ALi M1429G", - "ali1429g", - 0, - 1, - ali1429_init, ali1429_close, NULL, - { NULL }, NULL, NULL, - NULL + .name = "ALi M1429G", + .internal_name = "ali1429g", + .flags = 0, + .local = 1, + .init = ali1429_init, + .close = ali1429_close, + .reset = NULL, + { .available = NULL }, + .speed_changed = NULL, + .force_redraw = NULL, + .config = NULL }; diff --git a/src/chipset/ali1435.c b/src/chipset/ali1435.c new file mode 100644 index 000000000..9476d2b45 --- /dev/null +++ b/src/chipset/ali1435.c @@ -0,0 +1,315 @@ +/* + * 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. + * + * Emulation of ALi M1435 chipset that acts as both the + * southbridge. + * + * + * + * Authors: Miran Grca, + * + * Copyright 2020 Miran Grca. + */ +#include +#include +#include +#include +#include +#include +#define HAVE_STDARG_H +#include <86box/86box.h> +#include <86box/device.h> +#include <86box/io.h> +#include <86box/apm.h> +#include <86box/dma.h> +#include <86box/mem.h> +#include <86box/smram.h> +#include <86box/pci.h> +#include <86box/timer.h> +#include <86box/pic.h> +#include <86box/pit.h> +#include <86box/plat_unused.h> +#include <86box/port_92.h> +#include <86box/hdc_ide.h> +#include <86box/hdc.h> +#include <86box/machine.h> +#include <86box/chipset.h> +#include <86box/spd.h> + +#define MEM_STATE_SHADOW_R 0x01 +#define MEM_STATE_SHADOW_W 0x02 +#define MEM_STATE_SMRAM 0x04 + +typedef struct ali_1435_t { + uint8_t index; + uint8_t cfg_locked; + uint8_t pci_slot; + uint8_t pad; + uint8_t regs[16]; + uint8_t pci_regs[256]; +} ali1435_t; + +#ifdef ENABLE_ALI1435_LOG +int ali1435_do_log = ENABLE_ALI1435_LOG; + +static void +ali1435_log(const char *fmt, ...) +{ + va_list ap; + + if (ali1435_do_log) { + va_start(ap, fmt); + pclog_ex(fmt, ap); + va_end(ap); + } +} +#else +# define ali1435_log(fmt, ...) +#endif + +/* NOTE: We cheat here. The real ALi M1435 uses a level to edge triggered IRQ converter + when the most siginificant bit is set. We work around that by manipulating the + emulated PIC's ELCR register. */ +static void +ali1435_update_irqs(ali1435_t *dev, int set) +{ + uint8_t val; + int reg; + int shift; + int irq; + int irq_map[8] = { -1, 5, 9, 10, 11, 12, 14, 15 }; + pic_t *temp_pic; + + for (uint8_t i = 0; i < 4; i++) { + reg = 0x80 + (i >> 1); + shift = (i & 1) << 2; + val = (dev->pci_regs[reg] >> shift) & 0x0f; + irq = irq_map[val & 0x07]; + if (irq == -1) + continue; + temp_pic = (irq >= 8) ? &pic2 : &pic; + irq &= 7; + if (set && (val & 0x08)) + temp_pic->elcr |= (1 << irq); + else + temp_pic->elcr &= ~(1 << irq); + } +} + +static void +ali1435_pci_write(int func, int addr, uint8_t val, void *priv) +{ + ali1435_t *dev = (ali1435_t *) priv; + int irq; + int irq_map[8] = { -1, 5, 9, 10, 11, 12, 14, 15 }; + + ali1435_log("ali1435_write(%02X, %02X, %02X)\n", func, addr, val); + + if (func > 0) + return; + + if ((addr < 0x04) || (addr == 0x06) || ((addr >= 0x08) && (addr <= 0x0b))) + return; + + if ((addr >= 0x0f) && (addr < 0x30)) + return; + + if ((addr >= 0x34) && (addr < 0x40)) + return; + + switch (addr) { + /* Dummy PCI Config */ + case 0x04: + dev->pci_regs[addr] = (val & 0x7f) | 0x07; + break; + + case 0x05: + dev->pci_regs[addr] = (val & 0x01); + break; + + /* Dummy PCI Status */ + case 0x07: + dev->pci_regs[addr] &= ~(val & 0xb8); + break; + + case 0x80: + case 0x81: + dev->pci_regs[addr] = val; + ali1435_update_irqs(dev, 0); + irq = irq_map[val & 0x07]; + if (irq >= 0) { + ali1435_log("Set IRQ routing: INT %c -> %02X\n", 0x41 + ((addr & 0x01) << 1), irq); + pci_set_irq_routing(PCI_INTA + ((addr & 0x01) << 1), irq); + } else { + ali1435_log("Set IRQ routing: INT %c -> FF\n", 0x41 + ((addr & 0x01) << 1)); + pci_set_irq_routing(PCI_INTA + ((addr & 0x01) << 1), PCI_IRQ_DISABLED); + } + irq = irq_map[(val >> 4) & 0x07]; + if (irq >= 0) { + ali1435_log("Set IRQ routing: INT %c -> %02X\n", 0x42 + ((addr & 0x01) << 1), irq); + pci_set_irq_routing(PCI_INTB + ((addr & 0x01) << 1), irq); + } else { + ali1435_log("Set IRQ routing: INT %c -> FF\n", 0x42 + ((addr & 0x01) << 1)); + pci_set_irq_routing(PCI_INTB + ((addr & 0x01) << 1), PCI_IRQ_DISABLED); + } + ali1435_update_irqs(dev, 1); + break; + + default: + dev->pci_regs[addr] = val; + break; + } +} + +static uint8_t +ali1435_pci_read(int func, int addr, void *priv) +{ + const ali1435_t *dev = (ali1435_t *) priv; + uint8_t ret; + + ret = 0xff; + + if (func == 0) + ret = dev->pci_regs[addr]; + + ali1435_log("ali1435_read(%02X, %02X) = %02X\n", func, addr, ret); + + return ret; +} + +static void +ali1435_write(uint16_t addr, uint8_t val, void *priv) +{ + ali1435_t *dev = (ali1435_t *) priv; + + switch (addr) { + case 0x22: + dev->index = val; + break; + + case 0x23: + if (dev->index == 0x03) + dev->cfg_locked = (val != 0x69); +#ifdef ENABLE_ALI1435_LOG + else + ali1435_log("M1435: dev->regs[%02x] = %02x\n", dev->index, val); +#endif + + if (!dev->cfg_locked) { + switch (dev->index) { + /* PCI Mechanism select? */ + case 0x00: + dev->regs[dev->index] = val; + ali1435_log("PMC = %i\n", val != 0xc8); + pci_key_write(((val & 0xc8) == 0xc8) ? 0xf0 : 0x00); + break; + + /* ???? */ + case 0x06: + dev->regs[dev->index] = val; + break; + + /* ???? */ + case 0x07: + dev->regs[dev->index] = val; + break; + + default: + break; + } + } + break; + default: + break; + } +} + +static uint8_t +ali1435_read(uint16_t addr, void *priv) +{ + const ali1435_t *dev = (ali1435_t *) priv; + uint8_t ret = 0xff; + + if ((addr == 0x23) && (dev->index < 0x10)) + ret = dev->regs[dev->index]; + else if (addr == 0x22) + ret = dev->index; + + return ret; +} + +static void +ali1435_reset(void *priv) +{ + ali1435_t *dev = (ali1435_t *) priv; + + memset(dev->regs, 0, 16); + + dev->regs[0x00] = 0xff; + + dev->cfg_locked = 1; + + memset(dev->pci_regs, 0, 256); + + dev->pci_regs[0x00] = 0x25; + dev->pci_regs[0x01] = 0x10; /*ALi*/ + dev->pci_regs[0x02] = 0x35; + dev->pci_regs[0x03] = 0x14; /*M1435*/ + dev->pci_regs[0x04] = 0x07; + dev->pci_regs[0x07] = 0x04; + dev->pci_regs[0x0b] = 0x06; + + dev->pci_regs[0x80] = 0x80; + dev->pci_regs[0x81] = 0x00; + + pci_set_irq_routing(PCI_INTA, PCI_IRQ_DISABLED); + pci_set_irq_routing(PCI_INTB, PCI_IRQ_DISABLED); + pci_set_irq_routing(PCI_INTC, PCI_IRQ_DISABLED); + pci_set_irq_routing(PCI_INTD, PCI_IRQ_DISABLED); +} + +static void +ali1435_close(void *priv) +{ + ali1435_t *dev = (ali1435_t *) priv; + + free(dev); +} + +static void * +ali1435_init(UNUSED(const device_t *info)) +{ + ali1435_t *dev = (ali1435_t *) malloc(sizeof(ali1435_t)); + memset(dev, 0, sizeof(ali1435_t)); + + dev->cfg_locked = 1; + + /* M1435 Ports: + 22h Index Port + 23h Data Port + */ + io_sethandler(0x0022, 0x0002, ali1435_read, NULL, NULL, ali1435_write, NULL, NULL, dev); + + pci_add_card(PCI_ADD_NORTHBRIDGE, ali1435_pci_read, ali1435_pci_write, dev, &dev->pci_slot); + + ali1435_reset(dev); + + return dev; +} + +const device_t ali1435_device = { + .name = "Intel ALi M1435", + .internal_name = "ali1435", + .flags = DEVICE_PCI, + .local = 0x00, + .init = ali1435_init, + .close = ali1435_close, + .reset = ali1435_reset, + { .available = NULL }, + .speed_changed = NULL, + .force_redraw = NULL, + .config = NULL +}; diff --git a/src/chipset/ali1489.c b/src/chipset/ali1489.c index 1ab245b40..822ab7baf 100644 --- a/src/chipset/ali1489.c +++ b/src/chipset/ali1489.c @@ -1,20 +1,20 @@ /* - * 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. + * 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. + * This file is part of the 86Box distribution. * - * Implementation of the ALi M1489 chipset. + * Implementation of the ALi M1489 chipset. * * * - * Authors: Tiseno100, - * Miran Grca, + * Authors: Tiseno100, + * Miran Grca, * - * Copyright 2020,2021 Tiseno100. - * Copyright 2020,2021 Miran Grca. + * Copyright 2020-2021 Tiseno100. + * Copyright 2020-2021 Miran Grca. */ #include #include @@ -35,83 +35,80 @@ #include <86box/nmi.h> #include <86box/pic.h> #include <86box/pci.h> +#include <86box/plat_unused.h> #include <86box/port_92.h> #include <86box/smram.h> #include <86box/chipset.h> - #define DEFINE_SHADOW_PROCEDURE (((dev->regs[0x14] & 0x10) ? MEM_READ_INTERNAL : MEM_READ_EXTANY) | ((dev->regs[0x14] & 0x20) ? MEM_WRITE_INTERNAL : MEM_WRITE_EXTANY)) -#define DISABLED_SHADOW (MEM_READ_EXTANY | MEM_WRITE_EXTANY) - +#define DISABLED_SHADOW (MEM_READ_EXTANY | MEM_WRITE_EXTANY) #ifdef ENABLE_ALI1489_LOG int ali1489_do_log = ENABLE_ALI1489_LOG; + static void ali1489_log(const char *fmt, ...) { va_list ap; - if (ali1489_do_log) - { + if (ali1489_do_log) { va_start(ap, fmt); pclog_ex(fmt, ap); va_end(ap); } } #else -#define ali1489_log(fmt, ...) +# define ali1489_log(fmt, ...) #endif +typedef struct ali1489_t { + uint8_t index; + uint8_t ide_index; + uint8_t ide_chip_id; + uint8_t pci_slot; + uint8_t regs[256]; + uint8_t pci_conf[256]; + uint8_t ide_regs[256]; -typedef struct -{ - uint8_t index, ide_index, ide_chip_id, pci_slot, - regs[256], pci_conf[256], ide_regs[256]; - - port_92_t * port_92; - smram_t * smram; + port_92_t *port_92; + smram_t *smram; } ali1489_t; - -static void ali1489_ide_handler(ali1489_t *dev); - +static void ali1489_ide_handler(ali1489_t *dev); static void ali1489_shadow_recalc(ali1489_t *dev) { - uint32_t i; - shadowbios = shadowbios_write = 0; - for (i = 0; i < 8; i++) { - if (dev->regs[0x13] & (1 << i)) { - ali1489_log("%06Xh-%06Xh region shadow enabled: read = %i, write = %i\n", - 0xc0000 + (i << 14), 0xc3fff + (i << 14), !!(dev->regs[0x14] & 0x10), !!(dev->regs[0x14] & 0x20)); - mem_set_mem_state_both(0xc0000 + (i << 14), 0x4000, DEFINE_SHADOW_PROCEDURE); - } else { - ali1489_log("%06Xh-%06Xh region shadow disabled\n", 0xc0000 + (i << 14), 0xc3fff + (i << 14)); - mem_set_mem_state_both(0xc0000 + (i << 14), 0x4000, DISABLED_SHADOW); - } + for (uint8_t i = 0; i < 8; i++) { + if (dev->regs[0x13] & (1 << i)) { + ali1489_log("%06Xh-%06Xh region shadow enabled: read = %i, write = %i\n", + 0xc0000 + (i << 14), 0xc3fff + (i << 14), !!(dev->regs[0x14] & 0x10), !!(dev->regs[0x14] & 0x20)); + mem_set_mem_state_both(0xc0000 + (i << 14), 0x4000, DEFINE_SHADOW_PROCEDURE); + } else { + ali1489_log("%06Xh-%06Xh region shadow disabled\n", 0xc0000 + (i << 14), 0xc3fff + (i << 14)); + mem_set_mem_state_both(0xc0000 + (i << 14), 0x4000, DISABLED_SHADOW); + } } - for (i = 0; i < 4; i++) { + for (uint8_t i = 0; i < 4; i++) { if (dev->regs[0x14] & (1 << i)) { - ali1489_log("%06Xh-%06Xh region shadow enabled: read = %i, write = %i\n", - 0xe0000 + (i << 15), 0xe7fff + (i << 15), !!(dev->regs[0x14] & 0x10), !!(dev->regs[0x14] & 0x20)); - mem_set_mem_state_both(0xe0000 + (i << 15), 0x8000, DEFINE_SHADOW_PROCEDURE); - shadowbios |= !!(dev->regs[0x14] & 0x10); - shadowbios_write |= !!(dev->regs[0x14] & 0x20); + ali1489_log("%06Xh-%06Xh region shadow enabled: read = %i, write = %i\n", + 0xe0000 + (i << 15), 0xe7fff + (i << 15), !!(dev->regs[0x14] & 0x10), !!(dev->regs[0x14] & 0x20)); + mem_set_mem_state_both(0xe0000 + (i << 15), 0x8000, DEFINE_SHADOW_PROCEDURE); + shadowbios |= !!(dev->regs[0x14] & 0x10); + shadowbios_write |= !!(dev->regs[0x14] & 0x20); } else { - ali1489_log("%06Xh-%06Xh region shadow disabled\n", 0xe0000 + (i << 15), 0xe7fff + (i << 15)); - mem_set_mem_state_both(0xe0000 + (i << 15), 0x8000, DISABLED_SHADOW); - } + ali1489_log("%06Xh-%06Xh region shadow disabled\n", 0xe0000 + (i << 15), 0xe7fff + (i << 15)); + mem_set_mem_state_both(0xe0000 + (i << 15), 0x8000, DISABLED_SHADOW); + } } flushmmucache_nopc(); } - static void ali1489_smram_recalc(ali1489_t *dev) { @@ -120,27 +117,28 @@ ali1489_smram_recalc(ali1489_t *dev) smram_disable(dev->smram); switch (dev->regs[0x19] & 0x30) { - case 0x10: - smram_enable(dev->smram, 0xa0000, 0xa0000, 0x20000, (dev->regs[0x19] & 0x08), 1); - break; - case 0x20: - smram_enable(dev->smram, 0xe0000, 0xe0000, 0x10000, (dev->regs[0x19] & 0x08), 1); - break; - case 0x30: - if ((dev->regs[0x35] & 0xc0) == 0x80) - smram_enable(dev->smram, 0x68000, 0xa8000, 0x08000, (dev->regs[0x19] & 0x08), 1); - else - smram_enable(dev->smram, 0x38000, 0xa8000, 0x08000, (dev->regs[0x19] & 0x08), 1); - break; + case 0x10: + smram_enable(dev->smram, 0xa0000, 0xa0000, 0x20000, (dev->regs[0x19] & 0x08), 1); + break; + case 0x20: + smram_enable(dev->smram, 0xe0000, 0xe0000, 0x10000, (dev->regs[0x19] & 0x08), 1); + break; + case 0x30: + if ((dev->regs[0x35] & 0xc0) == 0x80) + smram_enable(dev->smram, 0x68000, 0xa8000, 0x08000, (dev->regs[0x19] & 0x08), 1); + else + smram_enable(dev->smram, 0x38000, 0xa8000, 0x08000, (dev->regs[0x19] & 0x08), 1); + break; + default: + break; } if ((dev->regs[0x19] & 0x31) == 0x11) { - /* If SMRAM is enabled and bit 0 is set, code still goes to DRAM. */ - mem_set_mem_state_smram_ex(1, 0xa0000, 0x20000, 0x02); + /* If SMRAM is enabled and bit 0 is set, code still goes to DRAM. */ + mem_set_mem_state_smram_ex(1, 0xa0000, 0x20000, 0x02); } } - static void ali1489_defaults(ali1489_t *dev) { @@ -197,9 +195,9 @@ ali1489_defaults(ali1489_t *dev) picintc(1 << 10); picintc(1 << 15); - nmi = 0; + nmi = 0; smi_line = 0; - in_smm = 0; + in_smm = 0; pci_set_irq_routing(PCI_INTA, PCI_IRQ_DISABLED); pci_set_irq_routing(PCI_INTB, PCI_IRQ_DISABLED); @@ -209,214 +207,222 @@ ali1489_defaults(ali1489_t *dev) ali1489_ide_handler(dev); } - static void ali1489_write(uint16_t addr, uint8_t val, void *priv) { - ali1489_t *dev = (ali1489_t *)priv; - uint8_t old, irq; - const uint8_t irq_array[16] = { 0, 3, 4, 7, 0, 0, 0, 0, 9, 10, 5, 6, 11, 12, 14, 15 }; + ali1489_t *dev = (ali1489_t *) priv; + uint8_t old; + uint8_t irq; + 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: - dev->index = val; - break; - case 0x23: - /* Check if the configuration registers are unlocked */ - if (dev->regs[0x03] == 0xc5) { - switch (dev->index) { - case 0x03: /* Lock Register */ - case 0x10: /* DRAM Configuration Register I */ - case 0x11: /* DRAM Configuration Register II */ - case 0x12: /* ROM Function Register */ - dev->regs[dev->index] = val; - break; + case 0x22: + dev->index = val; + break; + case 0x23: + /* Check if the configuration registers are unlocked */ + if (dev->regs[0x03] == 0xc5) { + switch (dev->index) { + case 0x03: /* Lock Register */ + case 0x10: /* DRAM Configuration Register I */ + case 0x11: /* DRAM Configuration Register II */ + case 0x12: /* ROM Function Register */ + dev->regs[dev->index] = val; + break; - case 0x13: /* Shadow Region Register */ - case 0x14: /* Shadow Control Register */ - if (dev->index == 0x14) - dev->regs[dev->index] = (val & 0xbf); - else - dev->regs[dev->index] = val; + case 0x13: /* Shadow Region Register */ + case 0x14: /* Shadow Control Register */ + if (dev->index == 0x14) + dev->regs[dev->index] = (val & 0xbf); + else + dev->regs[dev->index] = val; - ali1489_shadow_recalc(dev); - ali1489_smram_recalc(dev); - break; + ali1489_shadow_recalc(dev); + ali1489_smram_recalc(dev); + break; - case 0x15: /* Cycle Check Point Control Register */ - dev->regs[dev->index] = (val & 0xf1); - break; + case 0x15: /* Cycle Check Point Control Register */ + dev->regs[dev->index] = (val & 0xf1); + break; - case 0x16: /* Cache Control Register I */ - dev->regs[dev->index] = val; - cpu_cache_int_enabled = (val & 0x01); - cpu_cache_ext_enabled = (val & 0x02); - cpu_update_waitstates(); - break; - case 0x17: /* Cache Control Register II */ - dev->regs[dev->index] = val; - break; + case 0x16: /* Cache Control Register I */ + dev->regs[dev->index] = val; + cpu_cache_int_enabled = (val & 0x01); + cpu_cache_ext_enabled = (val & 0x02); + cpu_update_waitstates(); + break; + case 0x17: /* Cache Control Register II */ + dev->regs[dev->index] = val; + break; - case 0x19: /* SMM Control Register */ - dev->regs[dev->index] = val; - ali1489_smram_recalc(dev); - break; + case 0x19: /* SMM Control Register */ + dev->regs[dev->index] = val; + ali1489_smram_recalc(dev); + break; - case 0x1a: /* EDO DRAM Configuration Register */ - case 0x1b: /* DRAM Timing Control Register */ - dev->regs[dev->index] = val; - break; - case 0x1c: /* Memory Data Buffer Direction Control Register */ - dev->regs[dev->index] = val & 0x1f; - break; + case 0x1a: /* EDO DRAM Configuration Register */ + case 0x1b: /* DRAM Timing Control Register */ + dev->regs[dev->index] = val; + break; + case 0x1c: /* Memory Data Buffer Direction Control Register */ + dev->regs[dev->index] = val & 0x1f; + break; - case 0x1e: /* Linear Wrapped Burst Order Mode Control Register */ - dev->regs[dev->index] = (val & 0x40); - break; + case 0x1e: /* Linear Wrapped Burst Order Mode Control Register */ + dev->regs[dev->index] = (val & 0x40); + break; - case 0x20: /* CPU to PCI Buffer Control Register */ - dev->regs[dev->index] = val; - break; - case 0x21: /* DEVSELJ Check Point Setting Register */ - dev->regs[dev->index] = (val & 0xbb) | 0x04; - break; - case 0x22: /* PCI to CPU W/R Buffer Configuration Register */ - dev->regs[dev->index] = (val & 0xfd); - break; + case 0x20: /* CPU to PCI Buffer Control Register */ + dev->regs[dev->index] = val; + break; + case 0x21: /* DEVSELJ Check Point Setting Register */ + dev->regs[dev->index] = (val & 0xbb) | 0x04; + break; + case 0x22: /* PCI to CPU W/R Buffer Configuration Register */ + dev->regs[dev->index] = (val & 0xfd); + break; - case 0x25: /* GP/MEM Address Definition Register I */ - case 0x26: /* GP/MEM Address Definition Register II */ - case 0x27: /* GP/MEM Address Definition Register III */ - dev->regs[dev->index] = val; - break; - case 0x28: /* PCI Arbiter Control Register */ - dev->regs[dev->index] = val & 0x3f; - break; + case 0x25: /* GP/MEM Address Definition Register I */ + case 0x26: /* GP/MEM Address Definition Register II */ + case 0x27: /* GP/MEM Address Definition Register III */ + dev->regs[dev->index] = val; + break; + case 0x28: /* PCI Arbiter Control Register */ + dev->regs[dev->index] = val & 0x3f; + break; - case 0x29: /* System Clock Register */ - dev->regs[dev->index] = val; + case 0x29: /* System Clock Register */ + dev->regs[dev->index] = val; - port_92_remove(dev->port_92); - if (val & 0x10) - port_92_add(dev->port_92); - break; + port_92_remove(dev->port_92); + if (val & 0x10) + port_92_add(dev->port_92); + break; - case 0x2a: /* I/O Recovery Register */ - dev->regs[dev->index] = val; - break; + case 0x2a: /* I/O Recovery Register */ + dev->regs[dev->index] = val; + break; - case 0x2b: /* Turbo Function Register */ - dev->regs[dev->index] = (val & 0xbf) | 0x40; - break; + case 0x2b: /* Turbo Function Register */ + dev->regs[dev->index] = (val & 0xbf) | 0x40; + break; - case 0x30: /* Power Management Unit Control Register */ - old = dev->regs[dev->index]; - dev->regs[dev->index] = val; + case 0x30: /* Power Management Unit Control Register */ + old = dev->regs[dev->index]; + dev->regs[dev->index] = val; - if (((val & 0x14) == 0x14) && !(old & 0x08) && (val & 0x08)) { - switch (dev->regs[0x35] & 0x30) { - case 0x00: - smi_line = 1; - break; - case 0x10: - nmi = 1; - break; - case 0x20: - picint(1 << 15); - break; - case 0x30: - picint(1 << 10); - break; - } - dev->regs[0x35] |= 0x0e; - } else if (!(val & 0x10)) - dev->regs[0x35] &= ~0x0f; - break; + if (((val & 0x14) == 0x14) && !(old & 0x08) && (val & 0x08)) { + switch (dev->regs[0x35] & 0x30) { + case 0x00: + smi_raise(); + break; + case 0x10: + nmi_raise(); + break; + case 0x20: + picint(1 << 15); + break; + case 0x30: + picint(1 << 10); + break; + default: + break; + } + dev->regs[0x35] |= 0x0e; + } else if (!(val & 0x10)) + dev->regs[0x35] &= ~0x0f; + break; - case 0x31: /* Mode Timer Monitoring Events Selection Register I */ - case 0x32: /* Mode Timer Monitoring Events Selection Register II */ - case 0x33: /* SMI Triggered Events Selection Register I */ - case 0x34: /* SMI Triggered Events Selection Register II */ - dev->regs[dev->index] = val; - break; + case 0x31: /* Mode Timer Monitoring Events Selection Register I */ + case 0x32: /* Mode Timer Monitoring Events Selection Register II */ + case 0x33: /* SMI Triggered Events Selection Register I */ + case 0x34: /* SMI Triggered Events Selection Register II */ + dev->regs[dev->index] = val; + break; - case 0x35: /* SMI Status Register */ - dev->regs[dev->index] = (dev->regs[dev->index] & 0x0f) | (val & 0xf0); - break; + case 0x35: /* SMI Status Register */ + dev->regs[dev->index] = (dev->regs[dev->index] & 0x0f) | (val & 0xf0); + break; - case 0x36: /* IRQ Channel Group Selected Control Register I */ - dev->regs[dev->index] = (val & 0xe5); - break; - case 0x37: /* IRQ Channel Group Selected Control Register II */ - dev->regs[dev->index] = (val & 0xef); - break; + case 0x36: /* IRQ Channel Group Selected Control Register I */ + dev->regs[dev->index] = (val & 0xe5); + break; + case 0x37: /* IRQ Channel Group Selected Control Register II */ + dev->regs[dev->index] = (val & 0xef); + break; - case 0x38: /* DRQ Channel Selected Control Register */ - case 0x39: /* Mode Timer Setting Register */ - case 0x3a: /* Input_device Timer Setting Register */ - case 0x3b: /* GP/MEM Timer Setting Register */ - case 0x3c: /* LED Flash Control Register */ - dev->regs[dev->index] = val; - break; + case 0x38: /* DRQ Channel Selected Control Register */ + case 0x39: /* Mode Timer Setting Register */ + case 0x3a: /* Input_device Timer Setting Register */ + case 0x3b: /* GP/MEM Timer Setting Register */ + case 0x3c: /* LED Flash Control Register */ + dev->regs[dev->index] = val; + break; - case 0x3d: /* Miscellaneous Register I */ - dev->regs[dev->index] = (val & 0x07); - break; + case 0x3d: /* Miscellaneous Register I */ + dev->regs[dev->index] = (val & 0x07); + break; - case 0x40: /* Clock Generator Control Feature Register */ - dev->regs[dev->index] = (val & 0x3f); - break; - case 0x41: /* Power Control Output Register */ - dev->regs[dev->index] = val; - break; + case 0x40: /* Clock Generator Control Feature Register */ + dev->regs[dev->index] = (val & 0x3f); + break; + case 0x41: /* Power Control Output Register */ + dev->regs[dev->index] = val; + break; - case 0x42: /* PCI INTx Routing Table Mapping Register I */ - irq = irq_array[val & 0x0f]; - pci_set_irq_routing(PCI_INTA, (irq != 0) ? irq : PCI_IRQ_DISABLED); - irq = irq_array[(val & 0xf0) >> 4]; - pci_set_irq_routing(PCI_INTB, (irq != 0) ? irq : PCI_IRQ_DISABLED); - break; + case 0x42: /* PCI INTx Routing Table Mapping Register I */ + irq = irq_array[val & 0x0f]; + pci_set_irq_routing(PCI_INTA, (irq != 0) ? irq : PCI_IRQ_DISABLED); + irq = irq_array[(val & 0xf0) >> 4]; + pci_set_irq_routing(PCI_INTB, (irq != 0) ? irq : PCI_IRQ_DISABLED); + break; - case 0x43: /* PCI INTx Routing Table Mapping Register II */ - irq = irq_array[val & 0x0f]; - pci_set_irq_routing(PCI_INTC, (irq != 0) ? irq : PCI_IRQ_DISABLED); - irq = irq_array[(val & 0xf0) >> 4]; - pci_set_irq_routing(PCI_INTD, (irq != 0) ? irq : PCI_IRQ_DISABLED); - break; + case 0x43: /* PCI INTx Routing Table Mapping Register II */ + irq = irq_array[val & 0x0f]; + pci_set_irq_routing(PCI_INTC, (irq != 0) ? irq : PCI_IRQ_DISABLED); + irq = irq_array[(val & 0xf0) >> 4]; + pci_set_irq_routing(PCI_INTD, (irq != 0) ? irq : PCI_IRQ_DISABLED); + break; - case 0x44: /* PCI INTx Sensitivity Register */ - /* TODO: When doing the IRQ and PCI IRQ rewrite, bits 0 to 3 toggle edge/level output. */ - dev->regs[dev->index] = val; - break; - } + case 0x44: /* PCI INTx Sensitivity Register */ + /* TODO: When doing the IRQ and PCI IRQ rewrite, bits 0 to 3 toggle edge/level output. */ + dev->regs[dev->index] = val; + break; + default: + break; + } - if (dev->index != 0x03) { - ali1489_log("M1489: dev->regs[%02x] = %02x\n", dev->index, val); - } - } else if (dev->index == 0x03) - dev->regs[dev->index] = val; + if (dev->index != 0x03) { + ali1489_log("M1489: dev->regs[%02x] = %02x\n", dev->index, val); + } + } else if (dev->index == 0x03) + dev->regs[dev->index] = val; - break; + break; + + default: + break; } } - static uint8_t ali1489_read(uint16_t addr, void *priv) { - uint8_t ret = 0xff; - ali1489_t *dev = (ali1489_t *)priv; + uint8_t ret = 0xff; + const ali1489_t *dev = (ali1489_t *) priv; switch (addr) { - case 0x23: - /* Avoid conflict with Cyrix CPU registers */ - if (((dev->index == 0x20) || (dev->index >= 0xc0)) && cpu_iscyrix) - ret = 0xff; - else if (dev->index == 0x3f) - ret = inb(0x70); - else - ret = dev->regs[dev->index]; - break; + case 0x23: + /* Avoid conflict with Cyrix CPU registers */ + if (((dev->index == 0x20) || (dev->index >= 0xc0)) && cpu_iscyrix) + ret = 0xff; + else if (dev->index == 0x3f) + ret = inb(0x70); + else + ret = dev->regs[dev->index]; + break; + default: + break; } ali1489_log("M1489: dev->regs[%02x] (%02x)\n", dev->index, ret); @@ -424,155 +430,159 @@ ali1489_read(uint16_t addr, void *priv) return ret; } - static void -ali1489_pci_write(int func, int addr, uint8_t val, void *priv) +ali1489_pci_write(UNUSED(int func), int addr, uint8_t val, void *priv) { - ali1489_t *dev = (ali1489_t *)priv; + ali1489_t *dev = (ali1489_t *) priv; ali1489_log("M1489-PCI: dev->pci_conf[%02x] = %02x\n", addr, val); switch (addr) { - /* Dummy PCI Config */ - case 0x04: - dev->pci_conf[0x04] = val & 0x7f; - break; + /* Dummy PCI Config */ + case 0x04: + dev->pci_conf[0x04] = val & 0x7f; + break; - /* Dummy PCI Status */ - case 0x07: - dev->pci_conf[0x07] &= ~(val & 0xb8); - break; + /* Dummy PCI Status */ + case 0x07: + dev->pci_conf[0x07] &= ~(val & 0xb8); + break; + + default: + break; } } - static uint8_t -ali1489_pci_read(int func, int addr, void *priv) +ali1489_pci_read(UNUSED(int func), int addr, void *priv) { - ali1489_t *dev = (ali1489_t *)priv; - uint8_t ret = 0xff; + const ali1489_t *dev = (ali1489_t *) priv; + uint8_t ret = 0xff; ret = dev->pci_conf[addr]; ali1489_log("M1489-PCI: dev->pci_conf[%02x] (%02x)\n", addr, ret); return ret; } - static void ali1489_ide_handler(ali1489_t *dev) { ide_pri_disable(); ide_sec_disable(); if (dev->ide_regs[0x01] & 0x01) { - ide_pri_enable(); - if (!(dev->ide_regs[0x35] & 0x40)) - ide_sec_enable(); + ide_pri_enable(); + if (!(dev->ide_regs[0x35] & 0x40)) + ide_sec_enable(); } } - static void ali1489_ide_write(uint16_t addr, uint8_t val, void *priv) { - ali1489_t *dev = (ali1489_t *)priv; + ali1489_t *dev = (ali1489_t *) priv; - switch (addr) - { - case 0xf4: /* Usually it writes 30h here */ - dev->ide_chip_id = val; - break; + switch (addr) { + case 0xf4: /* Usually it writes 30h here */ + dev->ide_chip_id = val; + break; - case 0xf8: - dev->ide_index = val; - break; + case 0xf8: + dev->ide_index = val; + break; - case 0xfc: - if (dev->ide_chip_id != 0x30) - break; + case 0xfc: + if (dev->ide_chip_id != 0x30) + break; - switch(dev->ide_index) { - case 0x01: /* IDE Configuration Register */ - dev->ide_regs[dev->ide_index] = val & 0x8f; - ali1489_ide_handler(dev); - break; - case 0x02: /* DBA Data Byte Cative Count for IDE-1 */ - case 0x03: /* D0RA Disk 0 Read Active Count for IDE-1 */ - case 0x04: /* D0WA Disk 0 Write Active Count for IDE-1 */ - case 0x05: /* D1RA Disk 1 Read Active Count for IDE-1 */ - case 0x06: /* D1WA Disk 1 Write Active Count for IDE-1 */ - case 0x25: /* DBR Data Byte Recovery Count for IDE-1 */ - case 0x26: /* D0RR Disk 0 Read Byte Recovery Count for IDE-1 */ - case 0x27: /* D0WR Disk 0 Write Byte Recovery Count for IDE-1 */ - case 0x28: /* D1RR Disk 1 Read Byte Recovery Count for IDE-1 */ - case 0x29: /* D1WR Disk 1 Write Byte Recovery Count for IDE-1 */ - case 0x2a: /* DBA Data Byte Cative Count for IDE-2 */ - case 0x2b: /* D0RA Disk 0 Read Active Count for IDE-2 */ - case 0x2c: /* D0WA Disk 0 Write Active Count for IDE-2 */ - case 0x2d: /* D1RA Disk 1 Read Active Count for IDE-2 */ - case 0x2e: /* D1WA Disk 1 Write Active Count for IDE-2 */ - case 0x2f: /* DBR Data Byte Recovery Count for IDE-2 */ - case 0x30: /* D0RR Disk 0 Read Byte Recovery Count for IDE-2 */ - case 0x31: /* D0WR Disk 0 Write Byte Recovery Count for IDE-2 */ - case 0x32: /* D1RR Disk 1 Read Byte Recovery Count for IDE-2 */ - case 0x33: /* D1WR Disk 1 Write Byte Recovery Count for IDE-2 */ - dev->ide_regs[dev->ide_index] = val & 0x1f; - break; - case 0x07: /* Buffer Mode Register 1 */ - dev->ide_regs[dev->ide_index] = val; - break; - case 0x09: /* IDEPE1 IDE Port Enable Register 1 */ - dev->ide_regs[dev->ide_index] = val & 0xc3; - break; - case 0x0a: /* Buffer Mode Register 2 */ - dev->ide_regs[dev->ide_index] = val & 0x4f; - break; - case 0x0b: /* IDE Channel 1 Disk 0 Sector Byte Count Register 1 */ - case 0x0d: /* IDE Channel 1 Disk 1 Sector Byte Count Register 1 */ - case 0x0f: /* IDE Channel 2 Disk 0 Sector Byte Count Register 1 */ - case 0x11: /* IDE Channel 2 Disk 1 Sector Byte Count Register 1 */ - dev->ide_regs[dev->ide_index] = val & 0x03; - break; - case 0x0c: /* IDE Channel 1 Disk 0 Sector Byte Count Register 2 */ - case 0x0e: /* IDE Channel 1 Disk 1 Sector Byte Count Register 2 */ - case 0x10: /* IDE Channel 2 Disk 1 Sector Byte Count Register 2 */ - case 0x12: /* IDE Channel 2 Disk 1 Sector Byte Count Register 2 */ - dev->ide_regs[dev->ide_index] = val & 0x1f; - break; - case 0x35: /* IDEPE3 IDE Port Enable Register 3 */ - dev->ide_regs[dev->ide_index] = val; - ali1489_ide_handler(dev); - break; - } - break; + switch (dev->ide_index) { + case 0x01: /* IDE Configuration Register */ + dev->ide_regs[dev->ide_index] = val & 0x8f; + ali1489_ide_handler(dev); + break; + case 0x02: /* DBA Data Byte Cative Count for IDE-1 */ + case 0x03: /* D0RA Disk 0 Read Active Count for IDE-1 */ + case 0x04: /* D0WA Disk 0 Write Active Count for IDE-1 */ + case 0x05: /* D1RA Disk 1 Read Active Count for IDE-1 */ + case 0x06: /* D1WA Disk 1 Write Active Count for IDE-1 */ + case 0x25: /* DBR Data Byte Recovery Count for IDE-1 */ + case 0x26: /* D0RR Disk 0 Read Byte Recovery Count for IDE-1 */ + case 0x27: /* D0WR Disk 0 Write Byte Recovery Count for IDE-1 */ + case 0x28: /* D1RR Disk 1 Read Byte Recovery Count for IDE-1 */ + case 0x29: /* D1WR Disk 1 Write Byte Recovery Count for IDE-1 */ + case 0x2a: /* DBA Data Byte Cative Count for IDE-2 */ + case 0x2b: /* D0RA Disk 0 Read Active Count for IDE-2 */ + case 0x2c: /* D0WA Disk 0 Write Active Count for IDE-2 */ + case 0x2d: /* D1RA Disk 1 Read Active Count for IDE-2 */ + case 0x2e: /* D1WA Disk 1 Write Active Count for IDE-2 */ + case 0x2f: /* DBR Data Byte Recovery Count for IDE-2 */ + case 0x30: /* D0RR Disk 0 Read Byte Recovery Count for IDE-2 */ + case 0x31: /* D0WR Disk 0 Write Byte Recovery Count for IDE-2 */ + case 0x32: /* D1RR Disk 1 Read Byte Recovery Count for IDE-2 */ + case 0x33: /* D1WR Disk 1 Write Byte Recovery Count for IDE-2 */ + dev->ide_regs[dev->ide_index] = val & 0x1f; + break; + case 0x07: /* Buffer Mode Register 1 */ + dev->ide_regs[dev->ide_index] = val; + break; + case 0x09: /* IDEPE1 IDE Port Enable Register 1 */ + dev->ide_regs[dev->ide_index] = val & 0xc3; + break; + case 0x0a: /* Buffer Mode Register 2 */ + dev->ide_regs[dev->ide_index] = val & 0x4f; + break; + case 0x0b: /* IDE Channel 1 Disk 0 Sector Byte Count Register 1 */ + case 0x0d: /* IDE Channel 1 Disk 1 Sector Byte Count Register 1 */ + case 0x0f: /* IDE Channel 2 Disk 0 Sector Byte Count Register 1 */ + case 0x11: /* IDE Channel 2 Disk 1 Sector Byte Count Register 1 */ + dev->ide_regs[dev->ide_index] = val & 0x03; + break; + case 0x0c: /* IDE Channel 1 Disk 0 Sector Byte Count Register 2 */ + case 0x0e: /* IDE Channel 1 Disk 1 Sector Byte Count Register 2 */ + case 0x10: /* IDE Channel 2 Disk 1 Sector Byte Count Register 2 */ + case 0x12: /* IDE Channel 2 Disk 1 Sector Byte Count Register 2 */ + dev->ide_regs[dev->ide_index] = val & 0x1f; + break; + case 0x35: /* IDEPE3 IDE Port Enable Register 3 */ + dev->ide_regs[dev->ide_index] = val; + ali1489_ide_handler(dev); + break; + + default: + break; + } + break; + + default: + break; } } - static uint8_t ali1489_ide_read(uint16_t addr, void *priv) { - ali1489_t *dev = (ali1489_t *)priv; - uint8_t ret = 0xff; + const ali1489_t *dev = (ali1489_t *) priv; + uint8_t ret = 0xff; - switch (addr) - { - case 0xf4: - ret = dev->ide_chip_id; - break; - case 0xfc: - ret = dev->ide_regs[dev->ide_index]; - ali1489_log("M1489-IDE: dev->regs[%02x] (%02x)\n", dev->ide_index, ret); - break; + switch (addr) { + case 0xf4: + ret = dev->ide_chip_id; + break; + case 0xfc: + ret = dev->ide_regs[dev->ide_index]; + ali1489_log("M1489-IDE: dev->regs[%02x] (%02x)\n", dev->ide_index, ret); + break; + + default: + break; } return ret; } - static void ali1489_reset(void *priv) { - ali1489_t *dev = (ali1489_t *)priv; + ali1489_t *dev = (ali1489_t *) priv; pci_set_irq_routing(PCI_INTA, PCI_IRQ_DISABLED); pci_set_irq_routing(PCI_INTB, PCI_IRQ_DISABLED); @@ -582,21 +592,19 @@ ali1489_reset(void *priv) ali1489_defaults(dev); } - static void ali1489_close(void *priv) { - ali1489_t *dev = (ali1489_t *)priv; + ali1489_t *dev = (ali1489_t *) priv; smram_del(dev->smram); free(dev); } - static void * -ali1489_init(const device_t *info) +ali1489_init(UNUSED(const device_t *info)) { - ali1489_t *dev = (ali1489_t *)malloc(sizeof(ali1489_t)); + ali1489_t *dev = (ali1489_t *) malloc(sizeof(ali1489_t)); memset(dev, 0, sizeof(ali1489_t)); /* M1487/M1489 @@ -614,28 +622,28 @@ ali1489_init(const device_t *info) io_sethandler(0x0fc, 0x0001, ali1489_ide_read, NULL, NULL, ali1489_ide_write, NULL, NULL, dev); /* Dummy M1489 PCI device */ - dev->pci_slot = pci_add_card(PCI_ADD_NORTHBRIDGE, ali1489_pci_read, ali1489_pci_write, dev); + pci_add_card(PCI_ADD_NORTHBRIDGE, ali1489_pci_read, ali1489_pci_write, dev, &dev->pci_slot); device_add(&ide_pci_2ch_device); dev->port_92 = device_add(&port_92_pci_device); - dev->smram = smram_add(); + dev->smram = smram_add(); ali1489_defaults(dev); return dev; } - const device_t ali1489_device = { - "ALi M1489", - "ali1489", - 0, - 0, - ali1489_init, - ali1489_close, - ali1489_reset, - {NULL}, - NULL, - NULL, - NULL}; + .name = "ALi M1489", + .internal_name = "ali1489", + .flags = 0, + .local = 0, + .init = ali1489_init, + .close = ali1489_close, + .reset = ali1489_reset, + { .available = NULL }, + .speed_changed = NULL, + .force_redraw = NULL, + .config = NULL +}; diff --git a/src/chipset/ali1531.c b/src/chipset/ali1531.c index 12f425c36..9eb75f7cd 100644 --- a/src/chipset/ali1531.c +++ b/src/chipset/ali1531.c @@ -1,19 +1,18 @@ /* - * 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. + * 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. + * This file is part of the 86Box distribution. * - * Implementation of the ALi M1531B CPU-to-PCI Bridge. + * Implementation of the ALi M1531B CPU-to-PCI Bridge. * * * - * Authors: Tiseno100, - * - * Copyright 2021 Tiseno100. + * Authors: Tiseno100, * + * Copyright 2021 Tiseno100. */ #include #include @@ -29,283 +28,298 @@ #include <86box/io.h> #include <86box/mem.h> #include <86box/pci.h> +#include <86box/plat_unused.h> #include <86box/smram.h> #include <86box/spd.h> #include <86box/chipset.h> +typedef struct ali1531_t { + uint8_t pci_slot; + uint8_t pad; + uint8_t pad0; + uint8_t pad1; -typedef struct ali1531_t -{ uint8_t pci_conf[256]; smram_t *smram; } ali1531_t; - #ifdef ENABLE_ALI1531_LOG int ali1531_do_log = ENABLE_ALI1531_LOG; + static void ali1531_log(const char *fmt, ...) { va_list ap; - if (ali1531_do_log) - { + if (ali1531_do_log) { va_start(ap, fmt); pclog_ex(fmt, ap); va_end(ap); } } #else -#define ali1531_log(fmt, ...) +# define ali1531_log(fmt, ...) #endif - static void ali1531_smram_recalc(uint8_t val, ali1531_t *dev) { smram_disable_all(); if (val & 1) { - switch (val & 0x0c) { - case 0x00: - ali1531_log("SMRAM: D0000 -> B0000 (%i)\n", val & 2); - smram_enable(dev->smram, 0xd0000, 0xb0000, 0x10000, val & 2, 1); - if (val & 0x10) - mem_set_mem_state_smram_ex(1, 0xd0000, 0x10000, 0x02); - break; - case 0x04: - ali1531_log("SMRAM: A0000 -> A0000 (%i)\n", val & 2); - smram_enable(dev->smram, 0xa0000, 0xa0000, 0x20000, val & 2, 1); - if (val & 0x10) - mem_set_mem_state_smram_ex(1, 0xa0000, 0x20000, 0x02); - break; - case 0x08: - ali1531_log("SMRAM: 30000 -> B0000 (%i)\n", val & 2); - smram_enable(dev->smram, 0x30000, 0xb0000, 0x10000, val & 2, 1); - if (val & 0x10) - mem_set_mem_state_smram_ex(1, 0x30000, 0x10000, 0x02); - break; - } + switch (val & 0x0c) { + case 0x00: + ali1531_log("SMRAM: D0000 -> B0000 (%i)\n", val & 2); + smram_enable(dev->smram, 0xd0000, 0xb0000, 0x10000, val & 2, 1); + if (val & 0x10) + mem_set_mem_state_smram_ex(1, 0xd0000, 0x10000, 0x02); + break; + case 0x04: + ali1531_log("SMRAM: A0000 -> A0000 (%i)\n", val & 2); + smram_enable(dev->smram, 0xa0000, 0xa0000, 0x20000, val & 2, 1); + if (val & 0x10) + mem_set_mem_state_smram_ex(1, 0xa0000, 0x20000, 0x02); + break; + case 0x08: + ali1531_log("SMRAM: 30000 -> B0000 (%i)\n", val & 2); + smram_enable(dev->smram, 0x30000, 0xb0000, 0x10000, val & 2, 1); + if (val & 0x10) + mem_set_mem_state_smram_ex(1, 0x30000, 0x10000, 0x02); + break; + + default: + break; + } } flushmmucache_nopc(); } - static void -ali1531_shadow_recalc(int cur_reg, ali1531_t *dev) +ali1531_shadow_recalc(UNUSED(int cur_reg), ali1531_t *dev) { - int i, bit, r_reg, w_reg; - uint32_t base, flags = 0; + int bit; + int r_reg; + int w_reg; + uint32_t base; + uint32_t flags = 0; shadowbios = shadowbios_write = 0; - for (i = 0; i < 16; i++) { - base = 0x000c0000 + (i << 14); - bit = i & 7; - r_reg = 0x4c + (i >> 3); - w_reg = 0x4e + (i >> 3); + for (uint8_t i = 0; i < 16; i++) { + base = 0x000c0000 + (i << 14); + bit = i & 7; + r_reg = 0x4c + (i >> 3); + w_reg = 0x4e + (i >> 3); - flags = (dev->pci_conf[r_reg] & (1 << bit)) ? MEM_READ_INTERNAL : MEM_READ_EXTANY; - flags |= ((dev->pci_conf[w_reg] & (1 << bit)) ? MEM_WRITE_INTERNAL : MEM_WRITE_EXTANY); + flags = (dev->pci_conf[r_reg] & (1 << bit)) ? MEM_READ_INTERNAL : MEM_READ_EXTANY; + flags |= ((dev->pci_conf[w_reg] & (1 << bit)) ? MEM_WRITE_INTERNAL : MEM_WRITE_EXTANY); - if (base >= 0x000e0000) { - if (dev->pci_conf[r_reg] & (1 << bit)) - shadowbios |= 1; - if (dev->pci_conf[w_reg] & (1 << bit)) - shadowbios_write |= 1; - } + if (base >= 0x000e0000) { + if (dev->pci_conf[r_reg] & (1 << bit)) + shadowbios |= 1; + if (dev->pci_conf[w_reg] & (1 << bit)) + shadowbios_write |= 1; + } - ali1531_log("%08X-%08X shadow: R%c, W%c\n", base, base + 0x00003fff, - (dev->pci_conf[r_reg] & (1 << bit)) ? 'I' : 'E', (dev->pci_conf[w_reg] & (1 << bit)) ? 'I' : 'E'); + ali1531_log("%08X-%08X shadow: R%c, W%c\n", base, base + 0x00003fff, + (dev->pci_conf[r_reg] & (1 << bit)) ? 'I' : 'E', (dev->pci_conf[w_reg] & (1 << bit)) ? 'I' : 'E'); mem_set_mem_state_both(base, 0x00004000, flags); } flushmmucache_nopc(); } - static void -ali1531_write(int func, int addr, uint8_t val, void *priv) +ali1531_write(UNUSED(int func), int addr, uint8_t val, void *priv) { - ali1531_t *dev = (ali1531_t *)priv; + ali1531_t *dev = (ali1531_t *) priv; switch (addr) { - case 0x04: - dev->pci_conf[addr] = val; - break; - case 0x05: - dev->pci_conf[addr] = val & 0x01; - break; + case 0x04: + dev->pci_conf[addr] = val; + break; + case 0x05: + dev->pci_conf[addr] = val & 0x01; + break; - case 0x07: - dev->pci_conf[addr] &= ~(val & 0xf8); - break; + case 0x07: + dev->pci_conf[addr] &= ~(val & 0xf8); + break; - case 0x0d: - dev->pci_conf[addr] = val & 0xf8; - break; + case 0x0d: + dev->pci_conf[addr] = val & 0xf8; + break; - case 0x2c: /* Subsystem Vendor ID */ - case 0x2d: - case 0x2e: - case 0x2f: - if (dev->pci_conf[0x70] & 0x08) - dev->pci_conf[addr] = val; - break; + case 0x2c: /* Subsystem Vendor ID */ + case 0x2d: + case 0x2e: + case 0x2f: + if (dev->pci_conf[0x70] & 0x08) + dev->pci_conf[addr] = val; + break; - case 0x40: - dev->pci_conf[addr] = val & 0xf1; - break; + case 0x40: + dev->pci_conf[addr] = val & 0xf1; + break; - case 0x41: - dev->pci_conf[addr] = (val & 0xd6) | 0x08; - break; + case 0x41: + dev->pci_conf[addr] = (val & 0xd6) | 0x08; + break; - case 0x42: /* L2 Cache */ - dev->pci_conf[addr] = val & 0xf7; - cpu_cache_ext_enabled = !!(val & 1); - cpu_update_waitstates(); - break; + case 0x42: /* L2 Cache */ + dev->pci_conf[addr] = val & 0xf7; + cpu_cache_ext_enabled = !!(val & 1); + cpu_update_waitstates(); + break; - case 0x43: /* L1 Cache */ - dev->pci_conf[addr] = val; - cpu_cache_int_enabled = !!(val & 1); - cpu_update_waitstates(); - break; + case 0x43: /* L1 Cache */ + dev->pci_conf[addr] = val; + cpu_cache_int_enabled = !!(val & 1); + cpu_update_waitstates(); + break; - case 0x44: - dev->pci_conf[addr] = val; - break; - case 0x45: - dev->pci_conf[addr] = val; - break; + case 0x44: + dev->pci_conf[addr] = val; + break; + case 0x45: + dev->pci_conf[addr] = val; + break; - case 0x46: - dev->pci_conf[addr] = val; - break; + case 0x46: + dev->pci_conf[addr] = val; + break; - case 0x47: - dev->pci_conf[addr] = val & 0xfc; + case 0x47: + dev->pci_conf[addr] = val & 0xfc; - if (mem_size > 0xe00000) - mem_set_mem_state_both(0xe00000, 0x100000, (val & 0x20) ? (MEM_READ_EXTANY | MEM_WRITE_EXTANY) : (MEM_READ_INTERNAL | MEM_WRITE_INTERNAL)); + if (mem_size > 0xe00000) + mem_set_mem_state_both(0xe00000, 0x100000, (val & 0x20) ? (MEM_READ_EXTANY | MEM_WRITE_EXTANY) : (MEM_READ_INTERNAL | MEM_WRITE_INTERNAL)); - if (mem_size > 0xf00000) - mem_set_mem_state_both(0xf00000, 0x100000, (val & 0x10) ? (MEM_READ_EXTANY | MEM_WRITE_EXTANY) : (MEM_READ_INTERNAL | MEM_WRITE_INTERNAL)); + if (mem_size > 0xf00000) + mem_set_mem_state_both(0xf00000, 0x100000, (val & 0x10) ? (MEM_READ_EXTANY | MEM_WRITE_EXTANY) : (MEM_READ_INTERNAL | MEM_WRITE_INTERNAL)); - mem_set_mem_state_both(0xa0000, 0x20000, (val & 8) ? (MEM_READ_INTERNAL | MEM_WRITE_INTERNAL) : (MEM_READ_EXTANY | MEM_WRITE_EXTANY)); - mem_set_mem_state_both(0x80000, 0x20000, (val & 4) ? (MEM_READ_EXTANY | MEM_WRITE_EXTANY) : (MEM_READ_INTERNAL | MEM_WRITE_INTERNAL)); + mem_set_mem_state_both(0xa0000, 0x20000, (val & 8) ? (MEM_READ_INTERNAL | MEM_WRITE_INTERNAL) : (MEM_READ_EXTANY | MEM_WRITE_EXTANY)); + mem_set_mem_state_both(0x80000, 0x20000, (val & 4) ? (MEM_READ_EXTANY | MEM_WRITE_EXTANY) : (MEM_READ_INTERNAL | MEM_WRITE_INTERNAL)); - flushmmucache_nopc(); - break; + flushmmucache_nopc(); + break; - case 0x48: /* SMRAM */ - dev->pci_conf[addr] = val; - ali1531_smram_recalc(val, dev); - break; + case 0x48: /* SMRAM */ + dev->pci_conf[addr] = val; + ali1531_smram_recalc(val, dev); + break; - case 0x49: - dev->pci_conf[addr] = val & 0x73; - break; + case 0x49: + dev->pci_conf[addr] = val & 0x73; + break; - case 0x4a: - dev->pci_conf[addr] = val; - break; + case 0x4a: + dev->pci_conf[addr] = val; + break; - case 0x4c ... 0x4f: /* Shadow RAM */ - dev->pci_conf[addr] = val; - ali1531_shadow_recalc(val, dev); - break; + case 0x4c ... 0x4f: /* Shadow RAM */ + dev->pci_conf[addr] = val; + ali1531_shadow_recalc(val, dev); + break; - case 0x50: case 0x51: case 0x52: case 0x54: - case 0x55: case 0x56: - dev->pci_conf[addr] = val; - break; + case 0x50: + case 0x51: + case 0x52: + case 0x54: + case 0x55: + case 0x56: + dev->pci_conf[addr] = val; + break; - case 0x57: /* H2PO */ - dev->pci_conf[addr] = val & 0x60; - /* Find where the Shut-down Special cycle is initiated. */ - // if (!(val & 0x20)) - // outb(0x92, 0x01); - break; + case 0x57: /* H2PO */ + dev->pci_conf[addr] = val & 0x60; + /* Find where the Shut-down Special cycle is initiated. */ +#if 0 + if (!(val & 0x20)) + outb(0x92, 0x01); +#endif + break; - case 0x58: - dev->pci_conf[addr] = val & 0x86; - break; + case 0x58: + dev->pci_conf[addr] = val & 0x86; + break; - case 0x59: case 0x5a: - case 0x5c: - dev->pci_conf[addr] = val; - break; + case 0x59: + case 0x5a: + case 0x5c: + dev->pci_conf[addr] = val; + break; - case 0x5b: - dev->pci_conf[addr] = val & 0x4f; - break; + case 0x5b: + dev->pci_conf[addr] = val & 0x4f; + break; - case 0x5d: - dev->pci_conf[addr] = val & 0x53; - break; + case 0x5d: + dev->pci_conf[addr] = val & 0x53; + break; - case 0x5f: - dev->pci_conf[addr] = val & 0x7f; - break; + case 0x5f: + dev->pci_conf[addr] = val & 0x7f; + break; - case 0x60 ... 0x6f: /* DRB's */ - dev->pci_conf[addr] = val; - spd_write_drbs_interleaved(dev->pci_conf, 0x60, 0x6f, 1); - break; + case 0x60 ... 0x6f: /* DRB's */ + dev->pci_conf[addr] = val; + spd_write_drbs_interleaved(dev->pci_conf, 0x60, 0x6f, 1); + break; - case 0x70: case 0x71: - dev->pci_conf[addr] = val; - break; + case 0x70: + case 0x71: + dev->pci_conf[addr] = val; + break; - case 0x72: - dev->pci_conf[addr] = val & 0x0f; - break; + case 0x72: + dev->pci_conf[addr] = val & 0x0f; + break; - case 0x74: - dev->pci_conf[addr] = val & 0x2b; - break; + case 0x74: + dev->pci_conf[addr] = val & 0x2b; + break; - case 0x76: case 0x77: - dev->pci_conf[addr] = val; - break; + case 0x76: + case 0x77: + dev->pci_conf[addr] = val; + break; - case 0x80: - dev->pci_conf[addr] = val & 0x84; - break; + case 0x80: + dev->pci_conf[addr] = val & 0x84; + break; - case 0x81: - dev->pci_conf[addr] = val & 0x81; - break; + case 0x81: + dev->pci_conf[addr] = val & 0x81; + break; - case 0x83: - dev->pci_conf[addr] = val & 0x10; - break; + case 0x83: + dev->pci_conf[addr] = val & 0x10; + break; + + default: + break; } } - static uint8_t -ali1531_read(int func, int addr, void *priv) +ali1531_read(UNUSED(int func), int addr, void *priv) { - ali1531_t *dev = (ali1531_t *)priv; - uint8_t ret = 0xff; + const ali1531_t *dev = (ali1531_t *) priv; + uint8_t ret = 0xff; ret = dev->pci_conf[addr]; return ret; } - static void ali1531_reset(void *priv) { - ali1531_t *dev = (ali1531_t *)priv; - int i; + ali1531_t *dev = (ali1531_t *) priv; /* Default Registers */ dev->pci_conf[0x00] = 0xb9; @@ -341,33 +355,31 @@ ali1531_reset(void *priv) ali1531_write(0, 0x47, 0x00, dev); ali1531_write(0, 0x48, 0x00, dev); - for (i = 0; i < 4; i++) - ali1531_write(0, 0x4c + i, 0x00, dev); + for (uint8_t i = 0; i < 4; i++) + ali1531_write(0, 0x4c + i, 0x00, dev); - for (i = 0; i < 16; i += 2) { - ali1531_write(0, 0x60 + i, 0x08, dev); - ali1531_write(0, 0x61 + i, 0x40, dev); + for (uint8_t i = 0; i < 16; i += 2) { + ali1531_write(0, 0x60 + i, 0x08, dev); + ali1531_write(0, 0x61 + i, 0x40, dev); } } - static void ali1531_close(void *priv) { - ali1531_t *dev = (ali1531_t *)priv; + ali1531_t *dev = (ali1531_t *) priv; smram_del(dev->smram); free(dev); } - static void * -ali1531_init(const device_t *info) +ali1531_init(UNUSED(const device_t *info)) { - ali1531_t *dev = (ali1531_t *)malloc(sizeof(ali1531_t)); + ali1531_t *dev = (ali1531_t *) malloc(sizeof(ali1531_t)); memset(dev, 0, sizeof(ali1531_t)); - pci_add_card(PCI_ADD_NORTHBRIDGE, ali1531_read, ali1531_write, dev); + pci_add_card(PCI_ADD_NORTHBRIDGE, ali1531_read, ali1531_write, dev, &dev->pci_slot); dev->smram = smram_add(); @@ -376,17 +388,16 @@ ali1531_init(const device_t *info) return dev; } - const device_t ali1531_device = { - "ALi M1531 CPU-to-PCI Bridge", - "ali1531", - DEVICE_PCI, - 0, - ali1531_init, - ali1531_close, - ali1531_reset, - {NULL}, - NULL, - NULL, - NULL + .name = "ALi M1531 CPU-to-PCI Bridge", + .internal_name = "ali1531", + .flags = DEVICE_PCI, + .local = 0, + .init = ali1531_init, + .close = ali1531_close, + .reset = ali1531_reset, + { .available = NULL }, + .speed_changed = NULL, + .force_redraw = NULL, + .config = NULL }; diff --git a/src/chipset/ali1541.c b/src/chipset/ali1541.c index 3f94ec694..d57ef51e7 100644 --- a/src/chipset/ali1541.c +++ b/src/chipset/ali1541.c @@ -1,16 +1,18 @@ /* - * 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. + * 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. + * This file is part of the 86Box distribution. * - * Implementation of the ALi M1541/2 CPU-to-PCI Bridge. + * Implementation of the ALi M1541/2 CPU-to-PCI Bridge. * - * Authors: Miran Grca, * - * Copyright 2021 Miran Grca. + * + * Authors: Miran Grca, + * + * Copyright 2021 Miran Grca. */ #include #include @@ -26,540 +28,555 @@ #include <86box/io.h> #include <86box/mem.h> #include <86box/pci.h> +#include <86box/plat_unused.h> #include <86box/smram.h> #include <86box/spd.h> #include <86box/chipset.h> +typedef struct ali1541_t { + uint8_t pci_slot; + uint8_t pad; + uint8_t pad0; + uint8_t pad1; -typedef struct ali1541_t -{ - uint8_t pci_conf[256]; + uint8_t pci_conf[256]; - smram_t * smram; - void * agp_bridge; + smram_t *smram; + void *agp_bridge; } ali1541_t; - #ifdef ENABLE_ALI1541_LOG int ali1541_do_log = ENABLE_ALI1541_LOG; + static void ali1541_log(const char *fmt, ...) { va_list ap; - if (ali1541_do_log) - { + if (ali1541_do_log) { va_start(ap, fmt); pclog_ex(fmt, ap); va_end(ap); } } #else -#define ali1541_log(fmt, ...) +# define ali1541_log(fmt, ...) #endif - static void ali1541_smram_recalc(uint8_t val, ali1541_t *dev) { smram_disable_all(); if (val & 1) { - switch (val & 0x0c) { - case 0x00: - ali1541_log("SMRAM: D0000 -> B0000 (%i)\n", val & 2); - smram_enable(dev->smram, 0xd0000, 0xb0000, 0x10000, val & 2, 1); - if (val & 0x10) - mem_set_mem_state_smram_ex(1, 0xd0000, 0x10000, 0x02); - break; - case 0x04: - ali1541_log("SMRAM: A0000 -> A0000 (%i)\n", val & 2); - smram_enable(dev->smram, 0xa0000, 0xa0000, 0x20000, val & 2, 1); - if (val & 0x10) - mem_set_mem_state_smram_ex(1, 0xa0000, 0x20000, 0x02); - break; - case 0x08: - ali1541_log("SMRAM: 30000 -> B0000 (%i)\n", val & 2); - smram_enable(dev->smram, 0x30000, 0xb0000, 0x10000, val & 2, 1); - if (val & 0x10) - mem_set_mem_state_smram_ex(1, 0x30000, 0x10000, 0x02); - break; - } + switch (val & 0x0c) { + case 0x00: + ali1541_log("SMRAM: D0000 -> B0000 (%i)\n", val & 2); + smram_enable(dev->smram, 0xd0000, 0xb0000, 0x10000, val & 2, 1); + if (val & 0x10) + mem_set_mem_state_smram_ex(1, 0xd0000, 0x10000, 0x02); + break; + case 0x04: + ali1541_log("SMRAM: A0000 -> A0000 (%i)\n", val & 2); + smram_enable(dev->smram, 0xa0000, 0xa0000, 0x20000, val & 2, 1); + if (val & 0x10) + mem_set_mem_state_smram_ex(1, 0xa0000, 0x20000, 0x02); + break; + case 0x08: + ali1541_log("SMRAM: 30000 -> B0000 (%i)\n", val & 2); + smram_enable(dev->smram, 0x30000, 0xb0000, 0x10000, val & 2, 1); + if (val & 0x10) + mem_set_mem_state_smram_ex(1, 0x30000, 0x10000, 0x02); + break; + default: + break; + } } flushmmucache_nopc(); } - static void -ali1541_shadow_recalc(int cur_reg, ali1541_t *dev) +ali1541_shadow_recalc(UNUSED(int cur_reg), ali1541_t *dev) { - int i, bit, r_reg, w_reg; - uint32_t base, flags = 0; + int bit; + int r_reg; + int w_reg; + uint32_t base; + uint32_t flags = 0; shadowbios = shadowbios_write = 0; - for (i = 0; i < 16; i++) { - base = 0x000c0000 + (i << 14); - bit = i & 7; - r_reg = 0x56 + (i >> 3); - w_reg = 0x58 + (i >> 3); + for (uint8_t i = 0; i < 16; i++) { + base = 0x000c0000 + (i << 14); + bit = i & 7; + r_reg = 0x56 + (i >> 3); + w_reg = 0x58 + (i >> 3); - flags = (dev->pci_conf[r_reg] & (1 << bit)) ? MEM_READ_INTERNAL : MEM_READ_EXTANY; - flags |= ((dev->pci_conf[w_reg] & (1 << bit)) ? MEM_WRITE_INTERNAL : MEM_WRITE_EXTANY); + flags = (dev->pci_conf[r_reg] & (1 << bit)) ? MEM_READ_INTERNAL : MEM_READ_EXTANY; + flags |= ((dev->pci_conf[w_reg] & (1 << bit)) ? MEM_WRITE_INTERNAL : MEM_WRITE_EXTANY); - if (base >= 0x000e0000) { - if (dev->pci_conf[r_reg] & (1 << bit)) - shadowbios |= 1; - if (dev->pci_conf[w_reg] & (1 << bit)) - shadowbios_write |= 1; - } + if (base >= 0x000e0000) { + if (dev->pci_conf[r_reg] & (1 << bit)) + shadowbios |= 1; + if (dev->pci_conf[w_reg] & (1 << bit)) + shadowbios_write |= 1; + } - ali1541_log("%08X-%08X shadow: R%c, W%c\n", base, base + 0x00003fff, - (dev->pci_conf[r_reg] & (1 << bit)) ? 'I' : 'E', (dev->pci_conf[w_reg] & (1 << bit)) ? 'I' : 'E'); + ali1541_log("%08X-%08X shadow: R%c, W%c\n", base, base + 0x00003fff, + (dev->pci_conf[r_reg] & (1 << bit)) ? 'I' : 'E', (dev->pci_conf[w_reg] & (1 << bit)) ? 'I' : 'E'); mem_set_mem_state_both(base, 0x00004000, flags); } flushmmucache_nopc(); } - static void ali1541_mask_bar(ali1541_t *dev) { - uint32_t bar, mask; + uint32_t bar; + uint32_t mask; switch (dev->pci_conf[0xbc] & 0x0f) { - case 0x00: - default: - mask = 0x00000000; - break; - case 0x01: - mask = 0xfff00000; - break; - case 0x02: - mask = 0xffe00000; - break; - case 0x03: - mask = 0xffc00000; - break; - case 0x04: - mask = 0xff800000; - break; - case 0x06: - mask = 0xff000000; - break; - case 0x07: - mask = 0xfe000000; - break; - case 0x08: - mask = 0xfc000000; - break; - case 0x09: - mask = 0xf8000000; - break; - case 0x0a: - mask = 0xf0000000; - break; + default: + case 0x00: + mask = 0x00000000; + break; + case 0x01: + mask = 0xfff00000; + break; + case 0x02: + mask = 0xffe00000; + break; + case 0x03: + mask = 0xffc00000; + break; + case 0x04: + mask = 0xff800000; + break; + case 0x06: + mask = 0xff000000; + break; + case 0x07: + mask = 0xfe000000; + break; + case 0x08: + mask = 0xfc000000; + break; + case 0x09: + mask = 0xf8000000; + break; + case 0x0a: + mask = 0xf0000000; + break; } - bar = ((dev->pci_conf[0x13] << 24) | (dev->pci_conf[0x12] << 16)) & mask; + bar = ((dev->pci_conf[0x13] << 24) | (dev->pci_conf[0x12] << 16)) & mask; dev->pci_conf[0x12] = (bar >> 16) & 0xff; dev->pci_conf[0x13] = (bar >> 24) & 0xff; } - static void -ali1541_write(int func, int addr, uint8_t val, void *priv) +ali1541_write(UNUSED(int func), int addr, uint8_t val, void *priv) { - ali1541_t *dev = (ali1541_t *)priv; + ali1541_t *dev = (ali1541_t *) priv; switch (addr) { - case 0x04: - dev->pci_conf[addr] = val; - break; - case 0x05: - dev->pci_conf[addr] = val & 0x01; - break; - - case 0x07: - dev->pci_conf[addr] &= ~(val & 0xf8); - break; - - case 0x0d: - dev->pci_conf[addr] = val & 0xf8; - break; - - case 0x12: - dev->pci_conf[0x12] = (val & 0xc0); - ali1541_mask_bar(dev); - break; - case 0x13: - dev->pci_conf[0x13] = val; - ali1541_mask_bar(dev); - break; - - case 0x2c: /* Subsystem Vendor ID */ - case 0x2d: - case 0x2e: - case 0x2f: - if (dev->pci_conf[0x90] & 0x01) - dev->pci_conf[addr] = val; - break; - - case 0x34: - if (dev->pci_conf[0x90] & 0x02) - dev->pci_conf[addr] = val; - break; - - case 0x40: - dev->pci_conf[addr] = val & 0x7f; - break; - - case 0x41: - dev->pci_conf[addr] = val & 0x7f; - break; - - case 0x42: /* L2 Cache */ - dev->pci_conf[addr] = val; - cpu_cache_ext_enabled = !!(val & 1); - cpu_update_waitstates(); - break; - - case 0x43: /* PLCTL-Pipe Line Control */ - dev->pci_conf[addr] = val & 0xf7; - break; - - case 0x44: - dev->pci_conf[addr] = val; - break; - case 0x45: - dev->pci_conf[addr] = val; - break; - case 0x46: - dev->pci_conf[addr] = val & 0xf0; - break; - case 0x47: - dev->pci_conf[addr] = val; - break; - - case 0x48: - dev->pci_conf[addr] = val; - break; - case 0x49: - dev->pci_conf[addr] = val; - break; - - case 0x4a: - dev->pci_conf[addr] = val & 0xf8; - break; - - case 0x4b: - dev->pci_conf[addr] = val; - break; - - case 0x4c: - dev->pci_conf[addr] = val; - break; - case 0x4d: - dev->pci_conf[addr] = val; - break; - - case 0x4e: - dev->pci_conf[addr] = val; - break; - case 0x4f: - dev->pci_conf[addr] = val; - break; - - case 0x50: - dev->pci_conf[addr] = val & 0x71; - break; - - case 0x51: - dev->pci_conf[addr] = val; - break; - - case 0x52: - dev->pci_conf[addr] = val; - break; - - case 0x53: - dev->pci_conf[addr] = val; - break; - - case 0x54: - dev->pci_conf[addr] = val & 0x3c; - - if (mem_size > 0xe00000) - mem_set_mem_state_both(0xe00000, 0x100000, (val & 0x20) ? (MEM_READ_EXTANY | MEM_WRITE_EXTANY) : (MEM_READ_INTERNAL | MEM_WRITE_INTERNAL)); - - if (mem_size > 0xf00000) - mem_set_mem_state_both(0xf00000, 0x100000, (val & 0x10) ? (MEM_READ_EXTANY | MEM_WRITE_EXTANY) : (MEM_READ_INTERNAL | MEM_WRITE_INTERNAL)); - - mem_set_mem_state_both(0xa0000, 0x20000, (val & 8) ? (MEM_READ_INTERNAL | MEM_WRITE_INTERNAL) : (MEM_READ_EXTANY | MEM_WRITE_EXTANY)); - mem_set_mem_state_both(0x80000, 0x20000, (val & 4) ? (MEM_READ_EXTANY | MEM_WRITE_EXTANY) : (MEM_READ_INTERNAL | MEM_WRITE_INTERNAL)); - - flushmmucache_nopc(); - break; - - case 0x55: /* SMRAM */ - dev->pci_conf[addr] = val & 0x1f; - ali1541_smram_recalc(val, dev); - break; - - case 0x56 ... 0x59: /* Shadow RAM */ - dev->pci_conf[addr] = val; - ali1541_shadow_recalc(val, dev); - break; - - case 0x5a: case 0x5b: - dev->pci_conf[addr] = val; - break; - - case 0x5c: - dev->pci_conf[addr] = val; - break; - - case 0x5d: - dev->pci_conf[addr] = val & 0x17; - break; - - case 0x5e: - dev->pci_conf[addr] = val; - break; - - case 0x5f: - dev->pci_conf[addr] = val & 0xc1; - break; - - case 0x60 ... 0x6f: /* DRB's */ - dev->pci_conf[addr] = val; - spd_write_drbs_interleaved(dev->pci_conf, 0x60, 0x6f, 1); - break; - - case 0x70: - dev->pci_conf[addr] = val; - break; - - case 0x71: - dev->pci_conf[addr] = val; - break; - - case 0x72: - dev->pci_conf[addr] = val & 0xc7; - break; - - case 0x73: - dev->pci_conf[addr] = val & 0x1f; - break; - - case 0x84: case 0x85: - dev->pci_conf[addr] = val; - break; - - case 0x86: - dev->pci_conf[addr] = val & 0x0f; - break; - - case 0x87: /* H2PO */ - dev->pci_conf[addr] = val; - /* Find where the Shut-down Special cycle is initiated. */ - // if (!(val & 0x20)) - // outb(0x92, 0x01); - break; - - case 0x88: - dev->pci_conf[addr] = val; - break; - - case 0x89: - dev->pci_conf[addr] = val; - break; - - case 0x8a: - dev->pci_conf[addr] = val; - break; - - case 0x8b: - dev->pci_conf[addr] = val & 0x3f; - break; - - case 0x8c: - dev->pci_conf[addr] = val; - break; - - case 0x8d: - dev->pci_conf[addr] = val; - break; - - case 0x8e: - dev->pci_conf[addr] = val; - break; - - case 0x8f: - dev->pci_conf[addr] = val; - break; - - case 0x90: - dev->pci_conf[addr] = val; - pci_bridge_set_ctl(dev->agp_bridge, val); - break; - - case 0x91: - dev->pci_conf[addr] = val; - break; - - case 0xb4: - if (dev->pci_conf[0x90] & 0x01) - dev->pci_conf[addr] = val & 0x03; - break; - case 0xb5: - if (dev->pci_conf[0x90] & 0x01) - dev->pci_conf[addr] = val & 0x02; - break; - case 0xb7: - if (dev->pci_conf[0x90] & 0x01) - dev->pci_conf[addr] = val; - break; - - case 0xb8: - dev->pci_conf[addr] = val & 0x03; - break; - case 0xb9: - dev->pci_conf[addr] = val & 0x03; - break; - case 0xbb: - dev->pci_conf[addr] = val; - break; - - case 0xbc: - dev->pci_conf[addr] = val & 0x0f; - ali1541_mask_bar(dev); - break; - case 0xbd: - dev->pci_conf[addr] = val & 0xf0; - break; - case 0xbe: case 0xbf: - dev->pci_conf[addr] = val; - break; - - case 0xc0: - dev->pci_conf[addr] = val & 0x90; - break; - case 0xc1: case 0xc2: - case 0xc3: - dev->pci_conf[addr] = val; - break; - - case 0xc8: case 0xc9: - dev->pci_conf[addr] = val; - break; - - case 0xd1: - dev->pci_conf[addr] = val & 0xf1; - break; - case 0xd2: case 0xd3: - dev->pci_conf[addr] = val; - break; - - case 0xe0: case 0xe1: - if (dev->pci_conf[0x90] & 0x20) - dev->pci_conf[addr] = val; - break; - case 0xe2: - if (dev->pci_conf[0x90] & 0x20) - dev->pci_conf[addr] = val & 0x3f; - break; - case 0xe3: - if (dev->pci_conf[0x90] & 0x20) - dev->pci_conf[addr] = val & 0xfe; - break; - - case 0xe4: - if (dev->pci_conf[0x90] & 0x20) - dev->pci_conf[addr] = val & 0x03; - break; - case 0xe5: - if (dev->pci_conf[0x90] & 0x20) - dev->pci_conf[addr] = val; - break; - - case 0xe6: - if (dev->pci_conf[0x90] & 0x20) - dev->pci_conf[addr] = val & 0xc0; - break; - - case 0xe7: - if (dev->pci_conf[0x90] & 0x20) - dev->pci_conf[addr] = val; - break; - - case 0xe8: case 0xe9: - if (dev->pci_conf[0x90] & 0x04) - dev->pci_conf[addr] = val; - break; - - case 0xea: - dev->pci_conf[addr] = val & 0xcf; - break; - - case 0xeb: - dev->pci_conf[addr] = val & 0xcf; - break; - - case 0xec: - dev->pci_conf[addr] = val & 0x3f; - break; - - case 0xed: - dev->pci_conf[addr] = val; - break; - - case 0xee: - dev->pci_conf[addr] = val & 0x3e; - break; - case 0xef: - dev->pci_conf[addr] = val; - break; - - case 0xf3: - dev->pci_conf[addr] = val & 0x08; - break; - - case 0xf5: - dev->pci_conf[addr] = val; - break; - - case 0xf6: - dev->pci_conf[addr] = val; - break; - - case 0xf7: - dev->pci_conf[addr] = val & 0x43; - break; + case 0x04: + dev->pci_conf[addr] = val; + break; + case 0x05: + dev->pci_conf[addr] = val & 0x01; + break; + + case 0x07: + dev->pci_conf[addr] &= ~(val & 0xf8); + break; + + case 0x0d: + dev->pci_conf[addr] = val & 0xf8; + break; + + case 0x12: + dev->pci_conf[0x12] = (val & 0xc0); + ali1541_mask_bar(dev); + break; + case 0x13: + dev->pci_conf[0x13] = val; + ali1541_mask_bar(dev); + break; + + case 0x2c: /* Subsystem Vendor ID */ + case 0x2d: + case 0x2e: + case 0x2f: + if (dev->pci_conf[0x90] & 0x01) + dev->pci_conf[addr] = val; + break; + + case 0x34: + if (dev->pci_conf[0x90] & 0x02) + dev->pci_conf[addr] = val; + break; + + case 0x40: + dev->pci_conf[addr] = val & 0x7f; + break; + + case 0x41: + dev->pci_conf[addr] = val & 0x7f; + break; + + case 0x42: /* L2 Cache */ + dev->pci_conf[addr] = val; + cpu_cache_ext_enabled = !!(val & 1); + cpu_update_waitstates(); + break; + + case 0x43: /* PLCTL-Pipe Line Control */ + dev->pci_conf[addr] = val & 0xf7; + break; + + case 0x44: + dev->pci_conf[addr] = val; + break; + case 0x45: + dev->pci_conf[addr] = val; + break; + case 0x46: + dev->pci_conf[addr] = val & 0xf0; + break; + case 0x47: + dev->pci_conf[addr] = val; + break; + + case 0x48: + dev->pci_conf[addr] = val; + break; + case 0x49: + dev->pci_conf[addr] = val; + break; + + case 0x4a: + dev->pci_conf[addr] = val & 0xf8; + break; + + case 0x4b: + dev->pci_conf[addr] = val; + break; + + case 0x4c: + dev->pci_conf[addr] = val; + break; + case 0x4d: + dev->pci_conf[addr] = val; + break; + + case 0x4e: + dev->pci_conf[addr] = val; + break; + case 0x4f: + dev->pci_conf[addr] = val; + break; + + case 0x50: + dev->pci_conf[addr] = val & 0x71; + break; + + case 0x51: + dev->pci_conf[addr] = val; + break; + + case 0x52: + dev->pci_conf[addr] = val; + break; + + case 0x53: + dev->pci_conf[addr] = val; + break; + + case 0x54: + dev->pci_conf[addr] = val & 0x3c; + + if (mem_size > 0xe00000) + mem_set_mem_state_both(0xe00000, 0x100000, (val & 0x20) ? (MEM_READ_EXTANY | MEM_WRITE_EXTANY) : (MEM_READ_INTERNAL | MEM_WRITE_INTERNAL)); + + if (mem_size > 0xf00000) + mem_set_mem_state_both(0xf00000, 0x100000, (val & 0x10) ? (MEM_READ_EXTANY | MEM_WRITE_EXTANY) : (MEM_READ_INTERNAL | MEM_WRITE_INTERNAL)); + + mem_set_mem_state_both(0xa0000, 0x20000, (val & 8) ? (MEM_READ_INTERNAL | MEM_WRITE_INTERNAL) : (MEM_READ_EXTANY | MEM_WRITE_EXTANY)); + mem_set_mem_state_both(0x80000, 0x20000, (val & 4) ? (MEM_READ_EXTANY | MEM_WRITE_EXTANY) : (MEM_READ_INTERNAL | MEM_WRITE_INTERNAL)); + + flushmmucache_nopc(); + break; + + case 0x55: /* SMRAM */ + dev->pci_conf[addr] = val & 0x1f; + ali1541_smram_recalc(val, dev); + break; + + case 0x56 ... 0x59: /* Shadow RAM */ + dev->pci_conf[addr] = val; + ali1541_shadow_recalc(val, dev); + break; + + case 0x5a: + case 0x5b: + dev->pci_conf[addr] = val; + break; + + case 0x5c: + dev->pci_conf[addr] = val; + break; + + case 0x5d: + dev->pci_conf[addr] = val & 0x17; + break; + + case 0x5e: + dev->pci_conf[addr] = val; + break; + + case 0x5f: + dev->pci_conf[addr] = val & 0xc1; + break; + + case 0x60 ... 0x6f: /* DRB's */ + dev->pci_conf[addr] = val; + spd_write_drbs_interleaved(dev->pci_conf, 0x60, 0x6f, 1); + break; + + case 0x70: + dev->pci_conf[addr] = val; + break; + + case 0x71: + dev->pci_conf[addr] = val; + break; + + case 0x72: + dev->pci_conf[addr] = val & 0xc7; + break; + + case 0x73: + dev->pci_conf[addr] = val & 0x1f; + break; + + case 0x84: + case 0x85: + dev->pci_conf[addr] = val; + break; + + case 0x86: + dev->pci_conf[addr] = val & 0x0f; + break; + + case 0x87: /* H2PO */ + dev->pci_conf[addr] = val; + /* Find where the Shut-down Special cycle is initiated. */ +#if 0 + if (!(val & 0x20)) + outb(0x92, 0x01); +#endif + break; + + case 0x88: + dev->pci_conf[addr] = val; + break; + + case 0x89: + dev->pci_conf[addr] = val; + break; + + case 0x8a: + dev->pci_conf[addr] = val; + break; + + case 0x8b: + dev->pci_conf[addr] = val & 0x3f; + break; + + case 0x8c: + dev->pci_conf[addr] = val; + break; + + case 0x8d: + dev->pci_conf[addr] = val; + break; + + case 0x8e: + dev->pci_conf[addr] = val; + break; + + case 0x8f: + dev->pci_conf[addr] = val; + break; + + case 0x90: + dev->pci_conf[addr] = val; + pci_bridge_set_ctl(dev->agp_bridge, val); + break; + + case 0x91: + dev->pci_conf[addr] = val; + break; + + case 0xb4: + if (dev->pci_conf[0x90] & 0x01) + dev->pci_conf[addr] = val & 0x03; + break; + case 0xb5: + if (dev->pci_conf[0x90] & 0x01) + dev->pci_conf[addr] = val & 0x02; + break; + case 0xb7: + if (dev->pci_conf[0x90] & 0x01) + dev->pci_conf[addr] = val; + break; + + case 0xb8: + dev->pci_conf[addr] = val & 0x03; + break; + case 0xb9: + dev->pci_conf[addr] = val & 0x03; + break; + case 0xbb: + dev->pci_conf[addr] = val; + break; + + case 0xbc: + dev->pci_conf[addr] = val & 0x0f; + ali1541_mask_bar(dev); + break; + case 0xbd: + dev->pci_conf[addr] = val & 0xf0; + break; + case 0xbe: + case 0xbf: + dev->pci_conf[addr] = val; + break; + + case 0xc0: + dev->pci_conf[addr] = val & 0x90; + break; + case 0xc1: + case 0xc2: + case 0xc3: + dev->pci_conf[addr] = val; + break; + + case 0xc8: + case 0xc9: + dev->pci_conf[addr] = val; + break; + + case 0xd1: + dev->pci_conf[addr] = val & 0xf1; + break; + case 0xd2: + case 0xd3: + dev->pci_conf[addr] = val; + break; + + case 0xe0: + case 0xe1: + if (dev->pci_conf[0x90] & 0x20) + dev->pci_conf[addr] = val; + break; + case 0xe2: + if (dev->pci_conf[0x90] & 0x20) + dev->pci_conf[addr] = val & 0x3f; + break; + case 0xe3: + if (dev->pci_conf[0x90] & 0x20) + dev->pci_conf[addr] = val & 0xfe; + break; + + case 0xe4: + if (dev->pci_conf[0x90] & 0x20) + dev->pci_conf[addr] = val & 0x03; + break; + case 0xe5: + if (dev->pci_conf[0x90] & 0x20) + dev->pci_conf[addr] = val; + break; + + case 0xe6: + if (dev->pci_conf[0x90] & 0x20) + dev->pci_conf[addr] = val & 0xc0; + break; + + case 0xe7: + if (dev->pci_conf[0x90] & 0x20) + dev->pci_conf[addr] = val; + break; + + case 0xe8: + case 0xe9: + if (dev->pci_conf[0x90] & 0x04) + dev->pci_conf[addr] = val; + break; + + case 0xea: + dev->pci_conf[addr] = val & 0xcf; + break; + + case 0xeb: + dev->pci_conf[addr] = val & 0xcf; + break; + + case 0xec: + dev->pci_conf[addr] = val & 0x3f; + break; + + case 0xed: + dev->pci_conf[addr] = val; + break; + + case 0xee: + dev->pci_conf[addr] = val & 0x3e; + break; + case 0xef: + dev->pci_conf[addr] = val; + break; + + case 0xf3: + dev->pci_conf[addr] = val & 0x08; + break; + + case 0xf5: + dev->pci_conf[addr] = val; + break; + + case 0xf6: + dev->pci_conf[addr] = val; + break; + + case 0xf7: + dev->pci_conf[addr] = val & 0x43; + break; + + default: + break; } } - static uint8_t -ali1541_read(int func, int addr, void *priv) +ali1541_read(UNUSED(int func), int addr, void *priv) { - ali1541_t *dev = (ali1541_t *)priv; - uint8_t ret = 0xff; + const ali1541_t *dev = (ali1541_t *) priv; + uint8_t ret = 0xff; ret = dev->pci_conf[addr]; return ret; } - static void ali1541_reset(void *priv) { - ali1541_t *dev = (ali1541_t *)priv; - int i; + ali1541_t *dev = (ali1541_t *) priv; /* Default Registers */ dev->pci_conf[0x00] = 0xb9; @@ -602,35 +619,34 @@ ali1541_reset(void *priv) ali1541_write(0, 0x54, 0x00, dev); ali1541_write(0, 0x55, 0x00, dev); - for (i = 0; i < 4; i++) - ali1541_write(0, 0x56 + i, 0x00, dev); + for (uint8_t i = 0; i < 4; i++) + ali1541_write(0, 0x56 + i, 0x00, dev); - ali1541_write(0, 0x60 + i, 0x07, dev); - ali1541_write(0, 0x61 + i, 0x40, dev); - for (i = 0; i < 14; i += 2) { - ali1541_write(0, 0x62 + i, 0x00, dev); - ali1541_write(0, 0x63 + i, 0x00, dev); + ali1541_write(0, 0x60, 0x07, dev); + ali1541_write(0, 0x61, 0x40, dev); + + for (uint8_t i = 0; i < 14; i += 2) { + ali1541_write(0, 0x62 + i, 0x00, dev); + ali1541_write(0, 0x63 + i, 0x00, dev); } } - static void ali1541_close(void *priv) { - ali1541_t *dev = (ali1541_t *)priv; + ali1541_t *dev = (ali1541_t *) priv; smram_del(dev->smram); free(dev); } - static void * -ali1541_init(const device_t *info) +ali1541_init(UNUSED(const device_t *info)) { - ali1541_t *dev = (ali1541_t *)malloc(sizeof(ali1541_t)); + ali1541_t *dev = (ali1541_t *) malloc(sizeof(ali1541_t)); memset(dev, 0, sizeof(ali1541_t)); - pci_add_card(PCI_ADD_NORTHBRIDGE, ali1541_read, ali1541_write, dev); + pci_add_card(PCI_ADD_NORTHBRIDGE, ali1541_read, ali1541_write, dev, &dev->pci_slot); dev->smram = smram_add(); @@ -641,17 +657,16 @@ ali1541_init(const device_t *info) return dev; } - const device_t ali1541_device = { - "ALi M1541 CPU-to-PCI Bridge", - "ali1541", - DEVICE_PCI, - 0, - ali1541_init, - ali1541_close, - ali1541_reset, - {NULL}, - NULL, - NULL, - NULL + .name = "ALi M1541 CPU-to-PCI Bridge", + .internal_name = "ali1541", + .flags = DEVICE_PCI, + .local = 0, + .init = ali1541_init, + .close = ali1541_close, + .reset = ali1541_reset, + { .available = NULL }, + .speed_changed = NULL, + .force_redraw = NULL, + .config = NULL }; diff --git a/src/chipset/ali1543.c b/src/chipset/ali1543.c index a454b6a20..4d8dea3ce 100644 --- a/src/chipset/ali1543.c +++ b/src/chipset/ali1543.c @@ -1,19 +1,18 @@ /* - * 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. + * 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. + * This file is part of the 86Box distribution. * - * Implementation of the ALi M1543 Desktop South Bridge. + * Implementation of the ALi M1543 Desktop South Bridge. * * * - * Authors: Tiseno100, - * - * Copyright 2021 Tiseno100. + * Authors: Tiseno100, * + * Copyright 2021 Tiseno100. */ #include #include @@ -30,18 +29,16 @@ #include <86box/apm.h> #include <86box/dma.h> #include <86box/ddma.h> -#include <86box/fdd.h> -#include <86box/fdc.h> #include <86box/hdc_ide.h> #include <86box/hdc_ide_sff8038i.h> #include <86box/keyboard.h> -#include <86box/lpt.h> #include <86box/mem.h> #include <86box/nvr.h> #include <86box/pci.h> #include <86box/pic.h> +#include <86box/plat_unused.h> #include <86box/port_92.h> -#include <86box/serial.h> +#include <86box/sio.h> #include <86box/smbus.h> #include <86box/usb.h> @@ -49,24 +46,30 @@ #include <86box/chipset.h> +typedef struct ali1543_t { + uint8_t mirq_states[8]; + uint8_t pci_conf[256]; + uint8_t pmu_conf[256]; + uint8_t usb_conf[256]; + uint8_t ide_conf[256]; + uint8_t pci_slot; + uint8_t ide_slot; + uint8_t usb_slot; + uint8_t pmu_slot; + uint8_t usb_dev_enable; + uint8_t ide_dev_enable; + uint8_t pmu_dev_enable; + uint8_t type; + int offset; -typedef struct ali1543_t -{ - uint8_t pci_conf[256], pmu_conf[256], usb_conf[256], ide_conf[256], - sio_regs[256], device_regs[8][256], sio_index, in_configuration_mode, - pci_slot, ide_slot, usb_slot, pmu_slot, usb_dev_enable, ide_dev_enable, - pmu_dev_enable, type; - - apm_t * apm; - acpi_t * acpi; - ddma_t * ddma; - fdc_t * fdc_controller; - nvr_t * nvr; - port_92_t * port_92; - serial_t * uart[2]; - sff8038i_t * ide_controller[2]; - smbus_ali7101_t * smbus; - usb_t * usb; + apm_t *apm; + acpi_t *acpi; + ddma_t *ddma; + nvr_t *nvr; + port_92_t *port_92; + sff8038i_t *ide_controller[2]; + smbus_ali7101_t *smbus; + usb_t *usb; } ali1543_t; @@ -80,512 +83,530 @@ typedef struct ali1543_t - Code quality is abysmal and needs lot's of cleanup. */ -int ali1533_irq_routing[16] = { PCI_IRQ_DISABLED, 9, 3, 10, 4, 5, 7, 6, - 1, 11, PCI_IRQ_DISABLED, 12, PCI_IRQ_DISABLED, 14, PCI_IRQ_DISABLED, 15 }; - +int ali1533_irq_routing[16] = { PCI_IRQ_DISABLED, 9, 3, 10, 4, 5, 7, 6, + 1, 11, PCI_IRQ_DISABLED, 12, PCI_IRQ_DISABLED, 14, PCI_IRQ_DISABLED, 15 }; #ifdef ENABLE_ALI1543_LOG int ali1543_do_log = ENABLE_ALI1543_LOG; + static void ali1543_log(const char *fmt, ...) { va_list ap; - if (ali1543_do_log) - { + if (ali1543_do_log) { va_start(ap, fmt); pclog_ex(fmt, ap); va_end(ap); } } #else -#define ali1543_log(fmt, ...) +# define ali1543_log(fmt, ...) #endif - static void -ali1533_ddma_handler(ali1543_t *dev) +ali1533_ddma_handler(UNUSED(ali1543_t *dev)) { /* TODO: Find any documentation that actually explains the ALi southbridge DDMA mapping. */ } +static void ali5229_ide_handler(ali1543_t *dev); +static void ali5229_ide_irq_handler(ali1543_t *dev); -static void ali5229_ide_handler(ali1543_t *dev); -static void ali5229_ide_irq_handler(ali1543_t *dev); - -static void ali5229_write(int func, int addr, uint8_t val, void *priv); - -static void ali7101_write(int func, int addr, uint8_t val, void *priv); -static uint8_t ali7101_read(int func, int addr, void *priv); +static void ali5229_write(int func, int addr, uint8_t val, void *priv); +static void ali7101_write(int func, int addr, uint8_t val, void *priv); +static uint8_t ali7101_read(int func, int addr, void *priv); static void ali1533_write(int func, int addr, uint8_t val, void *priv) { - ali1543_t *dev = (ali1543_t *)priv; - int irq; + ali1543_t *dev = (ali1543_t *) priv; ali1543_log("M1533: dev->pci_conf[%02x] = %02x\n", addr, val); if (func > 0) - return; + return; switch (addr) { - case 0x04: /* Command Register */ - if (dev->type == 1) { - if (dev->pci_conf[0x5f] & 0x08) - dev->pci_conf[0x04] = val & 0x0f; - else - dev->pci_conf[0x04] = val; - } else { - if (!(dev->pci_conf[0x5f] & 0x08)) - dev->pci_conf[0x04] = val; - } - break; - case 0x05: /* Command Register */ - if (!(dev->pci_conf[0x5f] & 0x08)) - dev->pci_conf[0x04] = val & 0x03; - break; + case 0x04: /* Command Register */ + if (dev->type == 1) { + if (dev->pci_conf[0x5f] & 0x08) + dev->pci_conf[0x04] = val & 0x0f; + else + dev->pci_conf[0x04] = val; + } else { + if (!(dev->pci_conf[0x5f] & 0x08)) + dev->pci_conf[0x04] = val; + } + break; + case 0x05: /* Command Register */ + if (!(dev->pci_conf[0x5f] & 0x08)) + dev->pci_conf[0x04] = val & 0x03; + break; - case 0x07: /* Status Byte */ - dev->pci_conf[addr] &= ~(val & 0x30); - break; + case 0x07: /* Status Byte */ + dev->pci_conf[addr] &= ~(val & 0x30); + break; - case 0x2c: /* Subsystem Vendor ID */ - case 0x2d: - case 0x2e: - case 0x2f: - if (!(dev->pci_conf[0x74] & 0x40)) - dev->pci_conf[addr] = val; - break; + case 0x2c: /* Subsystem Vendor ID */ + case 0x2d: + case 0x2e: + case 0x2f: + if (!(dev->pci_conf[0x74] & 0x40)) + dev->pci_conf[addr] = val; + break; - case 0x40: - dev->pci_conf[addr] = val & 0x7f; - break; + case 0x40: + dev->pci_conf[addr] = val & 0x7f; + break; - case 0x41: - /* TODO: Bit 7 selects keyboard controller type: - 0 = AT, 1 = PS/2 */ - keyboard_at_set_mouse_scan((val & 0x40) ? 1 : 0); - dev->pci_conf[addr] = val & 0xbf; - break; + case 0x41: + dev->pci_conf[addr] = val; + break; - case 0x42: /* ISA Bus Speed */ - dev->pci_conf[addr] = val & 0xcf; - switch (val & 7) { - case 0: - cpu_set_isa_speed(7159091); - break; - case 1: case 2: case 3: case 4: - case 5: case 6: - cpu_set_isa_pci_div((val & 7) + 1); - break; - } - break; + case 0x42: /* ISA Bus Speed */ + dev->pci_conf[addr] = val & 0xcf; + switch (val & 7) { + case 0: + cpu_set_isa_speed(7159091); + break; + case 1: + case 2: + case 3: + case 4: + case 5: + case 6: + cpu_set_isa_pci_div((val & 7) + 1); + break; + default: + break; + } + break; - case 0x43: - dev->pci_conf[addr] = val; - if (val & 0x80) - port_92_add(dev->port_92); - else - port_92_remove(dev->port_92); - break; + case 0x43: + dev->pci_conf[addr] = val; + if (val & 0x80) + port_92_add(dev->port_92); + else + port_92_remove(dev->port_92); + break; - /* We're going to cheat a little bit here and use MIRQ's as a substitute for the ALi's INTAJ's, - as they work pretty much the same - specifically, we're going to use MIRQ2 and MIRQ3 for them, - as MIRQ0 and MIRQ1 map to the ALi's MBIRQ0 and MBIRQ1. */ - case 0x44: /* Set IRQ Line for Primary IDE if it's on native mode */ - dev->pci_conf[addr] = val & 0xdf; - soft_reset_pci = !!(val & 0x80); - sff_set_irq_level(dev->ide_controller[0], 0, !(val & 0x10)); - sff_set_irq_level(dev->ide_controller[1], 0, !(val & 0x10)); - ali1543_log("INTAJ = IRQ %i\n", ali1533_irq_routing[val & 0x0f]); - pci_set_mirq_routing(PCI_MIRQ0, ali1533_irq_routing[val & 0x0f]); - pci_set_mirq_routing(PCI_MIRQ2, ali1533_irq_routing[val & 0x0f]); - break; + /* We're going to cheat a little bit here and use MIRQ's as a substitute for the ALi's INTAJ's, + as they work pretty much the same - specifically, we're going to use MIRQ2 and MIRQ3 for them, + as MIRQ0 and MIRQ1 map to the ALi's MBIRQ0 and MBIRQ1. */ + case 0x44: /* Set IRQ Line for Primary IDE if it's on native mode */ + dev->pci_conf[addr] = val & 0xdf; + soft_reset_pci = !!(val & 0x80); + pci_set_mirq_level(PCI_MIRQ2, !(val & 0x10)); + ali1543_log("INTAJ = IRQ %i\n", ali1533_irq_routing[val & 0x0f]); + pci_set_mirq_routing(PCI_MIRQ0, ali1533_irq_routing[val & 0x0f]); + pci_set_mirq_routing(PCI_MIRQ2, ali1533_irq_routing[val & 0x0f]); + break; - /* TODO: Implement a ROMCS# assertion bitmask for I/O ports. */ - case 0x45: /* DDMA Enable */ - dev->pci_conf[addr] = val & 0xcb; - ali1533_ddma_handler(dev); - break; + /* TODO: Implement a ROMCS# assertion bitmask for I/O ports. */ + case 0x45: /* DDMA Enable */ + dev->pci_conf[addr] = val & 0xcb; + ali1533_ddma_handler(dev); + break; - /* TODO: For 0x47, we need a way to obtain the memory state for an address - and toggle ROMCS#. */ - case 0x47: /* BIOS chip select control */ - dev->pci_conf[addr] = val; - break; + /* TODO: For 0x47, we need a way to obtain the memory state for an address + and toggle ROMCS#. */ + case 0x47: /* BIOS chip select control */ + dev->pci_conf[addr] = val; + break; - /* PCI IRQ Routing */ - case 0x48: case 0x49: case 0x4a: case 0x4b: - dev->pci_conf[addr] = val; + /* PCI IRQ Routing */ + case 0x48: + case 0x49: + case 0x4a: + case 0x4b: + dev->pci_conf[addr] = val; - pci_set_irq_routing(((addr & 0x03) << 1) + 2, ali1533_irq_routing[(val >> 4) & 0x0f]); - pci_set_irq_routing(((addr & 0x03) << 1) + 1, ali1533_irq_routing[val & 0x0f]); - break; + pci_set_irq_routing(((addr & 0x03) << 1) + 2, ali1533_irq_routing[(val >> 4) & 0x0f]); + pci_set_irq_routing(((addr & 0x03) << 1) + 1, ali1533_irq_routing[val & 0x0f]); + break; - case 0x4c: /* PCI INT to ISA Level to Edge transfer */ - dev->pci_conf[addr] = val; + case 0x4c: /* PCI INT to ISA Level to Edge transfer */ + dev->pci_conf[addr] = val; - for (irq = 1; irq < 9; irq++) - pci_set_irq_level(irq, !(val & (1 << (irq - 1)))); - break; + for (uint8_t irq = 1; irq < 9; irq++) + pci_set_irq_level(irq, !(val & (1 << (irq - 1)))); + break; - case 0x4d: /* MBIRQ0(SIRQI#), MBIRQ1(SIRQII#) Interrupt to ISA IRQ routing table */ - if (dev->type == 0) { - dev->pci_conf[addr] = val; + case 0x4d: /* MBIRQ0(SIRQI#), MBIRQ1(SIRQII#) Interrupt to ISA IRQ routing table */ + if (dev->type == 0) { + dev->pci_conf[addr] = val; - ali1543_log("SIRQI = IRQ %i; SIRQII = IRQ %i\n", ali1533_irq_routing[(val >> 4) & 0x0f], ali1533_irq_routing[val & 0x0f]); - // pci_set_mirq_routing(PCI_MIRQ0, ali1533_irq_routing[(val >> 4) & 0x0f]); - // pci_set_mirq_routing(PCI_MIRQ1, ali1533_irq_routing[val & 0x0f]); - } - break; + ali1543_log("SIRQI = IRQ %i; SIRQII = IRQ %i\n", ali1533_irq_routing[(val >> 4) & 0x0f], ali1533_irq_routing[val & 0x0f]); +#if 0 + pci_set_mirq_routing(PCI_MIRQ0, ali1533_irq_routing[(val >> 4) & 0x0f]); + pci_set_mirq_routing(PCI_MIRQ1, ali1533_irq_routing[val & 0x0f]); +#endif + } + break; - /* I/O cycle posted-write first port definition */ - case 0x50: - dev->pci_conf[addr] = val; - break; - case 0x51: - dev->pci_conf[addr] = val & 0x8f; - break; + /* I/O cycle posted-write first port definition */ + case 0x50: + dev->pci_conf[addr] = val; + break; + case 0x51: + dev->pci_conf[addr] = val & 0x8f; + break; - /* I/O cycle posted-write second port definition */ - case 0x52: - dev->pci_conf[addr] = val; - break; - case 0x53: - if (dev->type == 1) - dev->pci_conf[addr] = val; - else - dev->pci_conf[addr] = val & 0xcf; - /* This actually enables/disables the USB *device* rather than the interface itself. */ - dev->usb_dev_enable = !(val & 0x40); - break; + /* I/O cycle posted-write second port definition */ + case 0x52: + dev->pci_conf[addr] = val; + break; + case 0x53: + if (dev->type == 1) + dev->pci_conf[addr] = val; + else + dev->pci_conf[addr] = val & 0xcf; + /* This actually enables/disables the USB *device* rather than the interface itself. */ + dev->usb_dev_enable = !(val & 0x40); + if (dev->type == 1) { + nvr_at_index_read_handler(0, 0x0070, dev->nvr); + nvr_at_index_read_handler(0, 0x0072, dev->nvr); + if (val & 0x20) { + nvr_at_index_read_handler(1, 0x0070, dev->nvr); + nvr_at_index_read_handler(1, 0x0072, dev->nvr); + } + } + break; - /* Hardware setting status bits, read-only (register 0x54) */ + /* Hardware setting status bits, read-only (register 0x54) */ - /* Programmable chip select (pin PCSJ) address define */ - case 0x55: case 0x56: - dev->pci_conf[addr] = val; - break; - case 0x57: - if (dev->type == 1) - dev->pci_conf[addr] = val & 0xf0; - else - dev->pci_conf[addr] = val & 0xe0; - break; + /* Programmable chip select (pin PCSJ) address define */ + case 0x55: + case 0x56: + dev->pci_conf[addr] = val; + break; + case 0x57: + if (dev->type == 1) + dev->pci_conf[addr] = val & 0xf0; + else + dev->pci_conf[addr] = val & 0xe0; + break; - /* IDE interface control - TODO: What is IDSEL address? */ - case 0x58: - dev->pci_conf[addr] = val & 0x7f; - ali1543_log("PCI58: %02X\n", val); - dev->ide_dev_enable = !!(val & 0x40); - switch (val & 0x30) { - case 0x00: - dev->ide_slot = 0x10; /* A27 = slot 16 */ - break; - case 0x10: - dev->ide_slot = 0x0f; /* A26 = slot 15 */ - break; - case 0x20: - dev->ide_slot = 0x0e; /* A25 = slot 14 */ - break; - case 0x30: - dev->ide_slot = 0x0d; /* A24 = slot 13 */ - break; - } - ali1543_log("IDE slot = %02X (A%0i)\n", dev->ide_slot/* - 5*/, dev->ide_slot + 11); - ali5229_ide_irq_handler(dev); - break; + /* IDE interface control */ + case 0x58: + dev->pci_conf[addr] = val & 0x7f; + ali1543_log("PCI58: %02X\n", val); + dev->ide_dev_enable = !!(val & 0x40); + switch (val & 0x30) { + case 0x00: + dev->ide_slot = 0x10; /* A27 = slot 16 */ + break; + case 0x10: + dev->ide_slot = 0x0f; /* A26 = slot 15 */ + break; + case 0x20: + dev->ide_slot = 0x0e; /* A25 = slot 14 */ + break; + case 0x30: + dev->ide_slot = 0x0d; /* A24 = slot 13 */ + break; + default: + break; + } + pci_relocate_slot(PCI_CARD_SOUTHBRIDGE_IDE, ((int) dev->ide_slot) + dev->offset); + ali1543_log("IDE slot = %02X (A%0i)\n", ((int) dev->ide_slot) + dev->offset, dev->ide_slot + 11); + ali5229_ide_irq_handler(dev); + break; - /* General Purpose input multiplexed pin(GPI) select */ - case 0x59: - dev->pci_conf[addr] = val & 0x0e; - break; + /* General Purpose input multiplexed pin(GPI) select */ + case 0x59: + dev->pci_conf[addr] = val & 0x0e; + break; - /* General Purpose output multiplexed pin(GPO) select low */ - case 0x5a: - dev->pci_conf[addr] = val & 0x0f; - break; - /* General Purpose output multiplexed pin(GPO) select high */ - case 0x5b: - dev->pci_conf[addr] = val & 0x02; - break; + /* General Purpose output multiplexed pin(GPO) select low */ + case 0x5a: + dev->pci_conf[addr] = val & 0x0f; + break; + /* General Purpose output multiplexed pin(GPO) select high */ + case 0x5b: + dev->pci_conf[addr] = val & 0x02; + break; - case 0x5c: - dev->pci_conf[addr] = val & 0x7f; - break; - case 0x5d: - dev->pci_conf[addr] = val & 0x02; - break; + case 0x5c: + dev->pci_conf[addr] = val & 0x7f; + break; + case 0x5d: + dev->pci_conf[addr] = val & 0x02; + break; - case 0x5e: - if (dev->type == 1) - dev->pci_conf[addr] = val & 0xe1; - else - dev->pci_conf[addr] = val & 0xe0; - break; + case 0x5e: + if (dev->type == 1) + dev->pci_conf[addr] = val & 0xe1; + else + dev->pci_conf[addr] = val & 0xe0; + break; - case 0x5f: - dev->pci_conf[addr] = val; - dev->pmu_dev_enable = !(val & 0x04); - break; + case 0x5f: + dev->pci_conf[addr] = val; + dev->pmu_dev_enable = !(val & 0x04); + break; - case 0x6c: /* Deleted - no idea what it used to do */ - dev->pci_conf[addr] = val; - break; + case 0x6c: /* Deleted - no idea what it used to do */ + dev->pci_conf[addr] = val; + break; - case 0x6d: - dev->pci_conf[addr] = val & 0xbf; - break; + case 0x6d: + dev->pci_conf[addr] = val & 0xbf; + break; - case 0x6e: case 0x70: - dev->pci_conf[addr] = val; - break; + case 0x6e: + case 0x70: + dev->pci_conf[addr] = val; + break; - case 0x71: - dev->pci_conf[addr] = val & 0xef; - break; + case 0x71: + dev->pci_conf[addr] = val & 0xef; + break; - case 0x72: - dev->pci_conf[addr] = val & 0xef; - switch (val & 0x0c) { - case 0x00: - dev->pmu_slot = 0x11; /* A28 = slot 17 */ - break; - case 0x04: - dev->pmu_slot = 0x12; /* A29 = slot 18 */ - break; - case 0x08: - dev->pmu_slot = 0x03; /* A14 = slot 03 */ - break; - case 0x0c: - dev->pmu_slot = 0x04; /* A15 = slot 04 */ - break; - } - ali1543_log("PMU slot = %02X (A%0i)\n", dev->pmu_slot/* - 5*/, dev->pmu_slot + 11); - switch (val & 0x03) { - case 0x00: - dev->usb_slot = 0x14; /* A31 = slot 20 */ - break; - case 0x01: - dev->usb_slot = 0x13; /* A30 = slot 19 */ - break; - case 0x02: - dev->usb_slot = 0x02; /* A13 = slot 02 */ - break; - case 0x03: - dev->usb_slot = 0x01; /* A12 = slot 01 */ - break; - } - ali1543_log("USB slot = %02X (A%0i)\n", dev->usb_slot/* - 5*/, dev->usb_slot + 11); - break; + case 0x72: + dev->pci_conf[addr] = val & 0xef; + switch (val & 0x0c) { + case 0x00: + dev->pmu_slot = 0x11; /* A28 = slot 17 */ + break; + case 0x04: + dev->pmu_slot = 0x12; /* A29 = slot 18 */ + break; + case 0x08: + dev->pmu_slot = 0x03; /* A14 = slot 03 */ + break; + case 0x0c: + dev->pmu_slot = 0x04; /* A15 = slot 04 */ + break; + default: + break; + } + pci_relocate_slot(PCI_CARD_SOUTHBRIDGE_PMU, ((int) dev->pmu_slot) + dev->offset); + ali1543_log("PMU slot = %02X (A%0i)\n", ((int) dev->pmu_slot) + dev->offset, dev->pmu_slot + 11); + switch (val & 0x03) { + case 0x00: + dev->usb_slot = 0x14; /* A31 = slot 20 */ + break; + case 0x01: + dev->usb_slot = 0x13; /* A30 = slot 19 */ + break; + case 0x02: + dev->usb_slot = 0x02; /* A13 = slot 02 */ + break; + case 0x03: + dev->usb_slot = 0x01; /* A12 = slot 01 */ + break; + default: + break; + } + pci_relocate_slot(PCI_CARD_SOUTHBRIDGE_USB, ((int) dev->usb_slot) + dev->offset); + ali1543_log("USB slot = %02X (A%0i)\n", ((int) dev->usb_slot) + dev->offset, dev->usb_slot + 11); + break; - case 0x73: /* DDMA Base Address */ - dev->pci_conf[addr] = val; - ali1533_ddma_handler(dev); - break; + case 0x73: /* DDMA Base Address */ + dev->pci_conf[addr] = val; + ali1533_ddma_handler(dev); + break; - case 0x74: /* USB IRQ Routing - we cheat and use MIRQ4 */ - dev->pci_conf[addr] = val & 0xdf; - /* TODO: MIRQ level/edge control - if bit 4 = 1, it's level */ - pci_set_mirq_routing(PCI_MIRQ4, ali1533_irq_routing[val & 0x0f]); - break; + case 0x74: /* USB IRQ Routing - we cheat and use MIRQ4 */ + dev->pci_conf[addr] = val & 0xdf; + /* TODO: MIRQ level/edge control - if bit 4 = 1, it's level */ + pci_set_mirq_routing(PCI_MIRQ4, ali1533_irq_routing[val & 0x0f]); + break; - case 0x75: /* Set IRQ Line for Secondary IDE if it's on native mode */ - dev->pci_conf[addr] = val & 0x1f; - sff_set_irq_level(dev->ide_controller[0], 1, !(val & 0x10)); - sff_set_irq_level(dev->ide_controller[1], 1, !(val & 0x10)); - ali1543_log("INTBJ = IRQ %i\n", ali1533_irq_routing[val & 0x0f]); - pci_set_mirq_routing(PCI_MIRQ1, ali1533_irq_routing[val & 0x0f]); - pci_set_mirq_routing(PCI_MIRQ3, ali1533_irq_routing[val & 0x0f]); - break; + case 0x75: /* Set IRQ Line for Secondary IDE if it's on native mode */ + dev->pci_conf[addr] = val & 0x1f; + pci_set_mirq_level(PCI_MIRQ3, !(val & 0x10)); + ali1543_log("INTBJ = IRQ %i\n", ali1533_irq_routing[val & 0x0f]); + pci_set_mirq_routing(PCI_MIRQ1, ali1533_irq_routing[val & 0x0f]); + pci_set_mirq_routing(PCI_MIRQ3, ali1533_irq_routing[val & 0x0f]); + break; - case 0x76: /* PMU IRQ Routing - we cheat and use MIRQ5 */ - if (dev->type == 1) - dev->pci_conf[addr] = val & 0x9f; - else - dev->pci_conf[addr] = val & 0x1f; - acpi_set_mirq_is_level(dev->acpi, !!(val & 0x10)); - if ((dev->type == 1) && (val & 0x80)) - pci_set_mirq_routing(PCI_MIRQ5, PCI_IRQ_DISABLED); - else - pci_set_mirq_routing(PCI_MIRQ5, ali1533_irq_routing[val & 0x0f]); - /* TODO: Tell ACPI to use MIRQ5 */ - break; + case 0x76: /* PMU IRQ Routing - we cheat and use MIRQ5 */ + if (dev->type == 1) + dev->pci_conf[addr] = val & 0x9f; + else + dev->pci_conf[addr] = val & 0x1f; + acpi_set_mirq_is_level(dev->acpi, !!(val & 0x10)); + if ((dev->type == 1) && (val & 0x80)) + pci_set_mirq_routing(PCI_MIRQ5, PCI_IRQ_DISABLED); + else + pci_set_mirq_routing(PCI_MIRQ5, ali1533_irq_routing[val & 0x0f]); + /* TODO: Tell ACPI to use MIRQ5 */ + break; - case 0x77: /* SMBus IRQ Routing - we cheat and use MIRQ6 */ - dev->pci_conf[addr] = val & 0x1f; - pci_set_mirq_routing(PCI_MIRQ6, ali1533_irq_routing[val & 0x0f]); - break; + case 0x77: /* SMBus IRQ Routing - we cheat and use MIRQ6 */ + dev->pci_conf[addr] = val & 0x1f; + pci_set_mirq_routing(PCI_MIRQ6, ali1533_irq_routing[val & 0x0f]); + break; - case 0x78: - if (dev->type == 1) { - ali1543_log("PCI78 = %02X\n", val); - dev->pci_conf[addr] = val & 0x33; - } - break; + case 0x78: + if (dev->type == 1) { + ali1543_log("PCI78 = %02X\n", val); + dev->pci_conf[addr] = val & 0x33; + } + break; - case 0x7c ... 0xff: - if ((dev->type == 1) && !dev->pmu_dev_enable) { - dev->pmu_dev_enable = 1; - ali7101_write(func, addr, val, priv); - dev->pmu_dev_enable = 0; - } - break; + case 0x7c ... 0xff: + if ((dev->type == 1) && !dev->pmu_dev_enable) { + dev->pmu_dev_enable = 1; + ali7101_write(func, addr, val, priv); + dev->pmu_dev_enable = 0; + } + break; + + default: + break; } } static uint8_t ali1533_read(int func, int addr, void *priv) { - ali1543_t *dev = (ali1543_t *)priv; - uint8_t ret = 0xff; + ali1543_t *dev = (ali1543_t *) priv; + uint8_t ret = 0xff; if (func == 0) { - if (((dev->pci_conf[0x42] & 0x80) && (addr >= 0x40)) || ((dev->pci_conf[0x5f] & 8) && (addr == 4))) - ret = 0x00; - else { - ret = dev->pci_conf[addr]; - if (addr == 0x41) - ret |= (keyboard_at_get_mouse_scan() << 2); - else if (addr == 0x58) - ret = (ret & 0xbf) | (dev->ide_dev_enable ? 0x40 : 0x00); - else if ((dev->type == 1) && ((addr >= 0x7c) && (addr <= 0xff)) && !dev->pmu_dev_enable) { - dev->pmu_dev_enable = 1; - ret = ali7101_read(func, addr, priv); - dev->pmu_dev_enable = 0; - } - } + if (((dev->pci_conf[0x42] & 0x80) && (addr >= 0x40)) || ((dev->pci_conf[0x5f] & 8) && (addr == 4))) + ret = 0x00; + else { + ret = dev->pci_conf[addr]; + if (addr == 0x58) + ret = (ret & 0xbf) | (dev->ide_dev_enable ? 0x40 : 0x00); + else if ((dev->type == 1) && ((addr >= 0x7c) && (addr <= 0xff)) && !dev->pmu_dev_enable) { + dev->pmu_dev_enable = 1; + ret = ali7101_read(func, addr, priv); + dev->pmu_dev_enable = 0; + } + } } return ret; } - static void ali5229_ide_irq_handler(ali1543_t *dev) { - int ctl = 0, ch = 0; + int ctl = 0; + int ch = 0; int bit = 0; if (dev->ide_conf[0x52] & 0x10) { - ctl ^= 1; - ch ^= 1; - bit ^= 5; + ctl ^= 1; + ch ^= 1; + bit ^= 5; } if (dev->ide_conf[0x09] & (1 ^ bit)) { - /* Primary IDE is native. */ - ali1543_log("Primary IDE IRQ mode: Native, Native\n"); - sff_set_irq_mode(dev->ide_controller[ctl], 0 ^ ch, 4); - sff_set_irq_mode(dev->ide_controller[ctl], 1 ^ ch, 4); + /* Primary IDE is native. */ + ali1543_log("Primary IDE IRQ mode: Native, Native\n"); + sff_set_irq_mode(dev->ide_controller[ctl], IRQ_MODE_ALI_ALADDIN); } else { - /* Primary IDE is legacy. */ - switch (dev->pci_conf[0x58] & 0x03) { - case 0x00: - /* SIRQI, SIRQII */ - ali1543_log("Primary IDE IRQ mode: SIRQI, SIRQII\n"); - sff_set_irq_mode(dev->ide_controller[ctl], 0 ^ ch, 2); - sff_set_irq_mode(dev->ide_controller[ctl], 1 ^ ch, 5); - break; - case 0x01: - /* IRQ14, IRQ15 */ - ali1543_log("Primary IDE IRQ mode: IRQ14, IRQ15\n"); - sff_set_irq_mode(dev->ide_controller[ctl], 0 ^ ch, 0); - sff_set_irq_mode(dev->ide_controller[ctl], 1 ^ ch, 0); - break; - case 0x02: - /* IRQ14, SIRQII */ - ali1543_log("Primary IDE IRQ mode: IRQ14, SIRQII\n"); - sff_set_irq_mode(dev->ide_controller[ctl], 0 ^ ch, 0); - sff_set_irq_mode(dev->ide_controller[ctl], 1 ^ ch, 5); - break; - case 0x03: - /* IRQ14, SIRQI */ - ali1543_log("Primary IDE IRQ mode: IRQ14, SIRQI\n"); - sff_set_irq_mode(dev->ide_controller[ctl], 0 ^ ch, 0); - sff_set_irq_mode(dev->ide_controller[ctl], 1 ^ ch, 2); - break; - } + /* Primary IDE is legacy. */ + switch (dev->pci_conf[0x58] & 0x03) { + case 0x00: + /* SIRQI, SIRQII */ + ali1543_log("Primary IDE IRQ mode: SIRQI, SIRQII\n"); + sff_set_irq_mode(dev->ide_controller[ctl], ctl ? IRQ_MODE_MIRQ_1 : IRQ_MODE_MIRQ_0); + break; + case 0x01: + /* IRQ14, IRQ15 */ + ali1543_log("Primary IDE IRQ mode: IRQ14, IRQ15\n"); + sff_set_irq_mode(dev->ide_controller[ctl], IRQ_MODE_LEGACY); + break; + case 0x02: + /* IRQ14, SIRQII */ + ali1543_log("Primary IDE IRQ mode: IRQ14, SIRQII\n"); + sff_set_irq_mode(dev->ide_controller[ctl], ctl ? IRQ_MODE_MIRQ_1 : IRQ_MODE_LEGACY); + break; + case 0x03: + /* IRQ14, SIRQI */ + ali1543_log("Primary IDE IRQ mode: IRQ14, SIRQI\n"); + sff_set_irq_mode(dev->ide_controller[ctl], ctl ? IRQ_MODE_MIRQ_0 : IRQ_MODE_LEGACY); + break; + + default: + break; + } } ctl ^= 1; if (dev->ide_conf[0x09] & (4 ^ bit)) { - /* Secondary IDE is native. */ - ali1543_log("Secondary IDE IRQ mode: Native, Native\n"); - sff_set_irq_mode(dev->ide_controller[ctl], 0 ^ ch, 4); - sff_set_irq_mode(dev->ide_controller[ctl], 1 ^ ch, 4); + /* Secondary IDE is native. */ + ali1543_log("Secondary IDE IRQ mode: Native, Native\n"); + sff_set_irq_mode(dev->ide_controller[ctl], IRQ_MODE_ALI_ALADDIN); } else { - /* Secondary IDE is legacy. */ - switch (dev->pci_conf[0x58] & 0x03) { - case 0x00: - /* SIRQI, SIRQII */ - ali1543_log("Secondary IDE IRQ mode: SIRQI, SIRQII\n"); - sff_set_irq_mode(dev->ide_controller[ctl], 0 ^ ch, 2); - sff_set_irq_mode(dev->ide_controller[ctl], 1 ^ ch, 5); - break; - case 0x01: - /* IRQ14, IRQ15 */ - ali1543_log("Secondary IDE IRQ mode: IRQ14, IRQ15\n"); - sff_set_irq_mode(dev->ide_controller[ctl], 0 ^ ch, 0); - sff_set_irq_mode(dev->ide_controller[ctl], 1 ^ ch, 0); - break; - case 0x02: - /* IRQ14, SIRQII */ - ali1543_log("Secondary IDE IRQ mode: IRQ14, SIRQII\n"); - sff_set_irq_mode(dev->ide_controller[ctl], 0 ^ ch, 0); - sff_set_irq_mode(dev->ide_controller[ctl], 1 ^ ch, 5); - break; - case 0x03: - /* IRQ14, SIRQI */ - ali1543_log("Secondary IDE IRQ mode: IRQ14, SIRQI\n"); - sff_set_irq_mode(dev->ide_controller[ctl], 0 ^ ch, 0); - sff_set_irq_mode(dev->ide_controller[ctl], 1 ^ ch, 2); - break; - } + /* Secondary IDE is legacy. */ + switch (dev->pci_conf[0x58] & 0x03) { + case 0x00: + /* SIRQI, SIRQII */ + ali1543_log("Secondary IDE IRQ mode: SIRQI, SIRQII\n"); + sff_set_irq_mode(dev->ide_controller[ctl], ctl ? IRQ_MODE_MIRQ_1 : IRQ_MODE_MIRQ_0); + break; + case 0x01: + /* IRQ14, IRQ15 */ + ali1543_log("Secondary IDE IRQ mode: IRQ14, IRQ15\n"); + sff_set_irq_mode(dev->ide_controller[ctl], IRQ_MODE_LEGACY); + break; + case 0x02: + /* IRQ14, SIRQII */ + ali1543_log("Secondary IDE IRQ mode: IRQ14, SIRQII\n"); + sff_set_irq_mode(dev->ide_controller[ctl], ctl ? IRQ_MODE_MIRQ_1 : IRQ_MODE_LEGACY); + break; + case 0x03: + /* IRQ14, SIRQI */ + ali1543_log("Secondary IDE IRQ mode: IRQ14, SIRQI\n"); + sff_set_irq_mode(dev->ide_controller[ctl], ctl ? IRQ_MODE_MIRQ_0 : IRQ_MODE_LEGACY); + break; + + default: + break; + } } } - static void ali5229_ide_handler(ali1543_t *dev) { uint32_t ch = 0; - uint16_t native_base_pri_addr = ((dev->ide_conf[0x11] | dev->ide_conf[0x10] << 8)) & 0xfffe; - uint16_t native_side_pri_addr = ((dev->ide_conf[0x15] | dev->ide_conf[0x14] << 8)) & 0xfffe; - uint16_t native_base_sec_addr = ((dev->ide_conf[0x19] | dev->ide_conf[0x18] << 8)) & 0xfffe; - uint16_t native_side_sec_addr = ((dev->ide_conf[0x1c] | dev->ide_conf[0x1b] << 8)) & 0xfffe; + uint16_t native_base_pri_addr = (dev->ide_conf[0x11] | dev->ide_conf[0x10] << 8) & 0xfffe; + uint16_t native_side_pri_addr = (dev->ide_conf[0x15] | dev->ide_conf[0x14] << 8) & 0xfffe; + uint16_t native_base_sec_addr = (dev->ide_conf[0x19] | dev->ide_conf[0x18] << 8) & 0xfffe; + uint16_t native_side_sec_addr = (dev->ide_conf[0x1c] | dev->ide_conf[0x1b] << 8) & 0xfffe; uint16_t comp_base_pri_addr = 0x01f0; uint16_t comp_side_pri_addr = 0x03f6; uint16_t comp_base_sec_addr = 0x0170; uint16_t comp_side_sec_addr = 0x0376; - uint16_t current_pri_base, current_pri_side, current_sec_base, current_sec_side; + uint16_t current_pri_base; + uint16_t current_pri_side; + uint16_t current_sec_base; + uint16_t current_sec_side; /* Primary Channel Programming */ if (dev->ide_conf[0x52] & 0x10) { - current_pri_base = (!(dev->ide_conf[0x09] & 1)) ? comp_base_sec_addr : native_base_sec_addr; - current_pri_side = (!(dev->ide_conf[0x09] & 1)) ? comp_side_sec_addr : native_side_sec_addr; + current_pri_base = (!(dev->ide_conf[0x09] & 1)) ? comp_base_sec_addr : native_base_sec_addr; + current_pri_side = (!(dev->ide_conf[0x09] & 1)) ? comp_side_sec_addr : native_side_sec_addr; } else { - current_pri_base = (!(dev->ide_conf[0x09] & 1)) ? comp_base_pri_addr : native_base_pri_addr; - current_pri_side = (!(dev->ide_conf[0x09] & 1)) ? comp_side_pri_addr : native_side_pri_addr; + current_pri_base = (!(dev->ide_conf[0x09] & 1)) ? comp_base_pri_addr : native_base_pri_addr; + current_pri_side = (!(dev->ide_conf[0x09] & 1)) ? comp_side_pri_addr : native_side_pri_addr; } /* Secondary Channel Programming */ if (dev->ide_conf[0x52] & 0x10) { - current_sec_base = (!(dev->ide_conf[0x09] & 4)) ? comp_base_pri_addr : native_base_pri_addr; - current_sec_side = (!(dev->ide_conf[0x09] & 4)) ? comp_side_pri_addr : native_side_pri_addr; + current_sec_base = (!(dev->ide_conf[0x09] & 4)) ? comp_base_pri_addr : native_base_pri_addr; + current_sec_side = (!(dev->ide_conf[0x09] & 4)) ? comp_side_pri_addr : native_side_pri_addr; } else { - current_sec_base = (!(dev->ide_conf[0x09] & 4)) ? comp_base_sec_addr : native_base_sec_addr; - current_sec_side = (!(dev->ide_conf[0x09] & 4)) ? comp_side_sec_addr : native_side_sec_addr; + current_sec_base = (!(dev->ide_conf[0x09] & 4)) ? comp_base_sec_addr : native_base_sec_addr; + current_sec_side = (!(dev->ide_conf[0x09] & 4)) ? comp_side_sec_addr : native_side_sec_addr; } if (dev->ide_conf[0x52] & 0x10) - ch ^= 8; + ch ^= 8; ali1543_log("ali5229_ide_handler(): Disabling primary IDE...\n"); ide_pri_disable(); @@ -593,39 +614,38 @@ ali5229_ide_handler(ali1543_t *dev) ide_sec_disable(); if (dev->ide_conf[0x04] & 0x01) { - /* Primary Channel Setup */ - if ((dev->ide_conf[0x09] & 0x20) || (dev->ide_conf[0x4d] & 0x80)) { - ali1543_log("ali5229_ide_handler(): Primary IDE base now %04X...\n", current_pri_base); - ide_set_base(0, current_pri_base); - ali1543_log("ali5229_ide_handler(): Primary IDE side now %04X...\n", current_pri_side); - ide_set_side(0, current_pri_side); + /* Primary Channel Setup */ + if ((dev->ide_conf[0x09] & 0x20) || (dev->ide_conf[0x4d] & 0x80)) { + ali1543_log("ali5229_ide_handler(): Primary IDE base now %04X...\n", current_pri_base); + ide_set_base(0, current_pri_base); + ali1543_log("ali5229_ide_handler(): Primary IDE side now %04X...\n", current_pri_side); + ide_set_side(0, current_pri_side); - ali1543_log("ali5229_ide_handler(): Enabling primary IDE...\n"); - ide_pri_enable(); + ali1543_log("ali5229_ide_handler(): Enabling primary IDE...\n"); + ide_pri_enable(); - sff_bus_master_handler(dev->ide_controller[0], dev->ide_conf[0x04] & 0x01, ((dev->ide_conf[0x20] & 0xf0) | (dev->ide_conf[0x21] << 8)) + (0 ^ ch)); - ali1543_log("M5229 PRI: BASE %04x SIDE %04x\n", current_pri_base, current_pri_side); - } + ali1543_log("M5229 PRI: BASE %04x SIDE %04x\n", current_pri_base, current_pri_side); + } - /* Secondary Channel Setup */ - if ((dev->ide_conf[0x09] & 0x10) || (dev->ide_conf[0x4d] & 0x80)) { - ali1543_log("ali5229_ide_handler(): Secondary IDE base now %04X...\n", current_sec_base); - ide_set_base(1, current_sec_base); - ali1543_log("ali5229_ide_handler(): Secondary IDE side now %04X...\n", current_sec_side); - ide_set_side(1, current_sec_side); + /* Secondary Channel Setup */ + if ((dev->ide_conf[0x09] & 0x10) || (dev->ide_conf[0x4d] & 0x80)) { + ali1543_log("ali5229_ide_handler(): Secondary IDE base now %04X...\n", current_sec_base); + ide_set_base(1, current_sec_base); + ali1543_log("ali5229_ide_handler(): Secondary IDE side now %04X...\n", current_sec_side); + ide_set_side(1, current_sec_side); - ali1543_log("ali5229_ide_handler(): Enabling secondary IDE...\n"); - ide_sec_enable(); + ali1543_log("ali5229_ide_handler(): Enabling secondary IDE...\n"); + ide_sec_enable(); - sff_bus_master_handler(dev->ide_controller[1], dev->ide_conf[0x04] & 0x01, (((dev->ide_conf[0x20] & 0xf0) | (dev->ide_conf[0x21] << 8))) + (8 ^ ch)); - ali1543_log("M5229 SEC: BASE %04x SIDE %04x\n", current_sec_base, current_sec_side); - } - } else { - sff_bus_master_handler(dev->ide_controller[0], dev->ide_conf[0x04] & 0x01, (dev->ide_conf[0x20] & 0xf0) | (dev->ide_conf[0x21] << 8)); - sff_bus_master_handler(dev->ide_controller[1], dev->ide_conf[0x04] & 0x01, ((dev->ide_conf[0x20] & 0xf0) | (dev->ide_conf[0x21] << 8)) + 8); + ali1543_log("M5229 SEC: BASE %04x SIDE %04x\n", current_sec_base, current_sec_side); + } } -} + sff_bus_master_handler(dev->ide_controller[0], dev->ide_conf[0x04] & 0x01, + ((dev->ide_conf[0x20] & 0xf0) | (dev->ide_conf[0x21] << 8)) + (0 ^ ch)); + sff_bus_master_handler(dev->ide_controller[1], dev->ide_conf[0x04] & 0x01, + ((dev->ide_conf[0x20] & 0xf0) | (dev->ide_conf[0x21] << 8)) + (8 ^ ch)); +} static void ali5229_chip_reset(ali1543_t *dev) @@ -663,11 +683,11 @@ ali5229_chip_reset(ali1543_t *dev) dev->ide_conf[0x78] = 0x21; if (dev->type == 1) { - dev->ide_conf[0x08] = 0xc1; - dev->ide_conf[0x43] = 0x00; - dev->ide_conf[0x4b] = 0x4a; - dev->ide_conf[0x4e] = 0xba; - dev->ide_conf[0x4f] = 0x1a; + dev->ide_conf[0x08] = 0xc1; + dev->ide_conf[0x43] = 0x00; + dev->ide_conf[0x4b] = 0x4a; + dev->ide_conf[0x4e] = 0xba; + dev->ide_conf[0x4f] = 0x1a; } ali5229_write(0, 0x04, 0x05, dev); @@ -690,844 +710,770 @@ ali5229_chip_reset(ali1543_t *dev) sff_set_slot(dev->ide_controller[0], dev->ide_slot); sff_set_slot(dev->ide_controller[1], dev->ide_slot); - sff_bus_master_reset(dev->ide_controller[0], (dev->ide_conf[0x20] & 0xf0) | (dev->ide_conf[0x21] << 8)); - sff_bus_master_reset(dev->ide_controller[1], ((dev->ide_conf[0x20] & 0xf0) | (dev->ide_conf[0x21] << 8)) + 8); + sff_bus_master_reset(dev->ide_controller[0]); + sff_bus_master_reset(dev->ide_controller[1]); ali5229_ide_handler(dev); } - static void ali5229_write(int func, int addr, uint8_t val, void *priv) { - ali1543_t *dev = (ali1543_t *)priv; + ali1543_t *dev = (ali1543_t *) priv; ali1543_log("M5229: dev->ide_conf[%02x] = %02x\n", addr, val); if (func > 0) - return; + return; if (!dev->ide_dev_enable) - return; + return; switch (addr) { - case 0x04: /* COM - Command Register */ - ali1543_log("IDE04: %02X\n", val); - dev->ide_conf[addr] = val & 0x45; - ali5229_ide_handler(dev); - break; + case 0x04: /* COM - Command Register */ + ali1543_log("IDE04: %02X\n", val); + dev->ide_conf[addr] = val & 0x45; + ali5229_ide_handler(dev); + break; - case 0x05: - dev->ide_conf[addr] = val & 0x01; - break; + case 0x05: + dev->ide_conf[addr] = val & 0x01; + break; - case 0x07: - dev->ide_conf[addr] &= ~(val & 0xf1); - break; + case 0x07: + dev->ide_conf[addr] &= ~(val & 0xf1); + break; - case 0x09: /* Control */ - ali1543_log("IDE09: %02X\n", val); + case 0x09: /* Control */ + ali1543_log("IDE09: %02X\n", val); - if (dev->type == 1) { - val &= ~(dev->ide_conf[0x43]); - val |= (dev->ide_conf[addr] & dev->ide_conf[0x43]); - } + if (dev->type == 1) { + val &= ~(dev->ide_conf[0x43]); + val |= (dev->ide_conf[addr] & dev->ide_conf[0x43]); + } - if (dev->ide_conf[0x4d] & 0x80) - dev->ide_conf[addr] = (dev->ide_conf[addr] & 0xfa) | (val & 0x05); - else - dev->ide_conf[addr] = (dev->ide_conf[addr] & 0x8a) | (val & 0x75); - ali5229_ide_handler(dev); - ali5229_ide_irq_handler(dev); - break; + if (dev->ide_conf[0x4d] & 0x80) + dev->ide_conf[addr] = (dev->ide_conf[addr] & 0xfa) | (val & 0x05); + else + dev->ide_conf[addr] = (dev->ide_conf[addr] & 0x8a) | (val & 0x75); + ali5229_ide_handler(dev); + ali5229_ide_irq_handler(dev); + break; - /* Primary Base Address */ - case 0x10: case 0x11: case 0x14: case 0x15: - /* FALLTHROUGH */ + /* Primary Base Address */ + case 0x10: + case 0x11: + case 0x14: + case 0x15: + /* FALLTHROUGH */ - /* Secondary Base Address */ - case 0x18: case 0x19: case 0x1c: case 0x1d: - /* FALLTHROUGH */ + /* Secondary Base Address */ + case 0x18: + case 0x19: + case 0x1c: + case 0x1d: + /* FALLTHROUGH */ - /* Bus Mastering Base Address */ - case 0x20: case 0x21: case 0x22: case 0x23: - dev->ide_conf[addr] = val; - ali5229_ide_handler(dev); - break; + /* Bus Mastering Base Address */ + case 0x20: + case 0x21: + /* Datasheet erratum: the PCI BAR's actually have different sizes. */ + if (addr == 0x20) + dev->ide_conf[addr] = (val & 0xe0) | 0x01; + else if ((addr & 0x43) == 0x00) + dev->ide_conf[addr] = (val & 0xf8) | 0x01; + else if ((addr & 0x43) == 0x40) + dev->ide_conf[addr] = (val & 0xfc) | 0x01; + else + dev->ide_conf[addr] = val; + ali5229_ide_handler(dev); + break; - case 0x2c: /* Subsystem Vendor ID */ - case 0x2d: - case 0x2e: - case 0x2f: - if (!(dev->ide_conf[0x53] & 0x80)) - dev->ide_conf[addr] = val; - break; + case 0x2c: /* Subsystem Vendor ID */ + case 0x2d: + case 0x2e: + case 0x2f: + if (!(dev->ide_conf[0x53] & 0x80)) + dev->ide_conf[addr] = val; + break; - case 0x3c: /* Interrupt Line */ - case 0x3d: /* Interrupt Pin */ - dev->ide_conf[addr] = val; - break; + case 0x3c: /* Interrupt Line */ + case 0x3d: /* Interrupt Pin */ + dev->ide_conf[addr] = val; + break; - /* The machines don't touch anything beyond that point so we avoid any programming */ - case 0x43: - if (dev->type == 1) - dev->ide_conf[addr] = val & 0x7f; - break; + /* The machines don't touch anything beyond that point so we avoid any programming */ + case 0x43: + if (dev->type == 1) + dev->ide_conf[addr] = val & 0x7f; + break; - case 0x4b: - if (dev->type == 1) - dev->ide_conf[addr] = val; - break; + case 0x4b: + if (dev->type == 1) + dev->ide_conf[addr] = val; + break; - case 0x4d: - dev->ide_conf[addr] = val & 0x80; - ali5229_ide_handler(dev); - break; + case 0x4d: + dev->ide_conf[addr] = val & 0x80; + ali5229_ide_handler(dev); + break; - case 0x4f: - if (dev->type == 0) - dev->ide_conf[addr] = val & 0x3f; - break; + case 0x4f: + if (dev->type == 0) + dev->ide_conf[addr] = val & 0x3f; + break; - case 0x50: /* Configuration */ - ali1543_log("IDE50: %02X\n", val); - dev->ide_conf[addr] = val & 0x2b; - dev->ide_dev_enable = !!(val & 0x01); - break; + case 0x50: /* Configuration */ + ali1543_log("IDE50: %02X\n", val); + dev->ide_conf[addr] = val & 0x2b; + dev->ide_dev_enable = !!(val & 0x01); + break; - case 0x51: - dev->ide_conf[addr] = val & 0xf7; - if (val & 0x80) - ali5229_chip_reset(dev); - else if (val & 0x40) { - sff_bus_master_reset(dev->ide_controller[0], (dev->ide_conf[0x20] & 0xf0) | (dev->ide_conf[0x21] << 8)); - sff_bus_master_reset(dev->ide_controller[1], ((dev->ide_conf[0x20] & 0xf0) | (dev->ide_conf[0x21] << 8)) + 8); - } - break; + case 0x51: + dev->ide_conf[addr] = val & 0xf7; + if (val & 0x80) + ali5229_chip_reset(dev); + else if (val & 0x40) { + sff_bus_master_reset(dev->ide_controller[0]); + sff_bus_master_reset(dev->ide_controller[1]); + } + break; - case 0x52: /* FCS - Flexible Channel Setting Register */ - dev->ide_conf[addr] = val; - ali5229_ide_handler(dev); - ali5229_ide_irq_handler(dev); - break; + case 0x52: /* FCS - Flexible Channel Setting Register */ + dev->ide_conf[addr] = val; + ali5229_ide_handler(dev); + ali5229_ide_irq_handler(dev); + break; - case 0x53: /* Subsystem Vendor ID */ - dev->ide_conf[addr] = val & 0x8b; - break; + case 0x53: /* Subsystem Vendor ID */ + dev->ide_conf[addr] = val & 0x8b; + break; - case 0x54: /* FIFO threshold of primary channel drive 0 and drive 1 */ - case 0x55: /* FIFO threshold of secondary channel drive 0 and drive 1 */ - case 0x56: /* Ultra DMA /33 setting for Primary drive 0 and drive 1 */ - case 0x57: /* Ultra DMA /33 setting for Secondary drive 0 and drive 1 */ - case 0x78: /* IDE clock's frequency (default value is 33 = 21H) */ - dev->ide_conf[addr] = val; - break; + case 0x54: /* FIFO threshold of primary channel drive 0 and drive 1 */ + case 0x55: /* FIFO threshold of secondary channel drive 0 and drive 1 */ + case 0x56: /* Ultra DMA /33 setting for Primary drive 0 and drive 1 */ + case 0x57: /* Ultra DMA /33 setting for Secondary drive 0 and drive 1 */ + case 0x78: /* IDE clock's frequency (default value is 33 = 21H) */ + dev->ide_conf[addr] = val; + break; - case 0x58: - dev->ide_conf[addr] = val & 3; - break; + case 0x58: + dev->ide_conf[addr] = val & 3; + break; - case 0x59: case 0x5a: - case 0x5b: - dev->ide_conf[addr] = val & 0x7f; - break; + case 0x59: + case 0x5a: + case 0x5b: + dev->ide_conf[addr] = val & 0x7f; + break; - case 0x5c: - dev->ide_conf[addr] = val & 3; - break; + case 0x5c: + dev->ide_conf[addr] = val & 3; + break; - case 0x5d: case 0x5e: - case 0x5f: - dev->ide_conf[addr] = val & 0x7f; - break; + case 0x5d: + case 0x5e: + case 0x5f: + dev->ide_conf[addr] = val & 0x7f; + break; + + default: + break; } } - static uint8_t ali5229_read(int func, int addr, void *priv) { - ali1543_t *dev = (ali1543_t *)priv; - uint8_t ret = 0xff; + const ali1543_t *dev = (ali1543_t *) priv; + uint8_t ret = 0xff; if (dev->ide_dev_enable && (func == 0)) { - ret = dev->ide_conf[addr]; - if ((addr == 0x09) && !(dev->ide_conf[0x50] & 0x02)) - ret &= 0x0f; - else if (addr == 0x50) - ret = (ret & 0xfe) | (dev->ide_dev_enable ? 0x01 : 0x00); - else if (addr == 0x75) - ret = ide_read_ali_75(); - else if (addr == 0x76) - ret = ide_read_ali_76(); + ret = dev->ide_conf[addr]; + if ((addr == 0x09) && !(dev->ide_conf[0x50] & 0x02)) + ret &= 0x0f; + else if (addr == 0x50) + ret = (ret & 0xfe) | (dev->ide_dev_enable ? 0x01 : 0x00); + else if (addr == 0x75) + ret = ide_read_ali_75(); + else if (addr == 0x76) + ret = ide_read_ali_76(); } return ret; } - static void ali5237_write(int func, int addr, uint8_t val, void *priv) { - ali1543_t *dev = (ali1543_t *)priv; + ali1543_t *dev = (ali1543_t *) priv; ali1543_log("M5237: dev->usb_conf[%02x] = %02x\n", addr, val); if (func > 0) - return; + return; if (!dev->usb_dev_enable) - return; + return; switch (addr) { - case 0x04: /* USB Enable */ - dev->usb_conf[addr] = val & 0x5f; - ohci_update_mem_mapping(dev->usb, dev->usb_conf[0x11], dev->usb_conf[0x12], dev->usb_conf[0x13], dev->usb_conf[0x04] & 1); - break; + case 0x04: /* USB Enable */ + dev->usb_conf[addr] = val & 0x5f; + ohci_update_mem_mapping(dev->usb, dev->usb_conf[0x11], dev->usb_conf[0x12], dev->usb_conf[0x13], dev->usb_conf[0x04] & 1); + break; - case 0x05: - dev->usb_conf[addr] = 0x01; - break; + case 0x05: + dev->usb_conf[addr] = 0x01; + break; - case 0x07: - dev->usb_conf[addr] &= ~(val & 0xc9); - break; + case 0x07: + dev->usb_conf[addr] &= ~(val & 0xc9); + break; - case 0x0c: /* Cache Line Size */ - case 0x0d: /* Latency Timer */ - case 0x3c: /* Interrupt Line Register */ + case 0x0c: /* Cache Line Size */ + case 0x0d: /* Latency Timer */ + dev->usb_conf[addr] = val; + break; - case 0x42: /* Test Mode Register */ - dev->usb_conf[addr] = val & 0x10; - break; - case 0x43: - if (dev->type == 1) - dev->usb_conf[addr] = val & 0x04; - break; + case 0x3c: /* Interrupt Line Register */ + dev->usb_conf[addr] = val; + break; - /* USB Base I/O */ - case 0x11: - dev->usb_conf[addr] = val & 0xf0; - ohci_update_mem_mapping(dev->usb, dev->usb_conf[0x11], dev->usb_conf[0x12], dev->usb_conf[0x13], dev->usb_conf[0x04] & 1); - break; - case 0x12: case 0x13: - dev->usb_conf[addr] = val; - ohci_update_mem_mapping(dev->usb, dev->usb_conf[0x11], dev->usb_conf[0x12], dev->usb_conf[0x13], dev->usb_conf[0x04] & 1); - break; + case 0x42: /* Test Mode Register */ + dev->usb_conf[addr] = val & 0x10; + break; + case 0x43: + if (dev->type == 1) + dev->usb_conf[addr] = val & 0x04; + break; - case 0x2c: /* Subsystem Vendor ID */ - case 0x2d: - case 0x2e: - case 0x2f: - if (!(dev->usb_conf[0x42] & 0x10)) - dev->usb_conf[addr] = val; - break; + /* USB Base I/O */ + case 0x11: + dev->usb_conf[addr] = val & 0xf0; + ohci_update_mem_mapping(dev->usb, dev->usb_conf[0x11], dev->usb_conf[0x12], dev->usb_conf[0x13], dev->usb_conf[0x04] & 1); + break; + case 0x12: + case 0x13: + dev->usb_conf[addr] = val; + ohci_update_mem_mapping(dev->usb, dev->usb_conf[0x11], dev->usb_conf[0x12], dev->usb_conf[0x13], dev->usb_conf[0x04] & 1); + break; + + case 0x2c: /* Subsystem Vendor ID */ + case 0x2d: + case 0x2e: + case 0x2f: + if (!(dev->usb_conf[0x42] & 0x10)) + dev->usb_conf[addr] = val; + break; + + default: + break; } } - static uint8_t ali5237_read(int func, int addr, void *priv) { - ali1543_t *dev = (ali1543_t *)priv; - uint8_t ret = 0xff; + const ali1543_t *dev = (ali1543_t *) priv; + uint8_t ret = 0xff; if (dev->usb_dev_enable && (func == 0)) - ret = dev->usb_conf[addr]; + ret = dev->usb_conf[addr]; return ret; } - static void ali7101_write(int func, int addr, uint8_t val, void *priv) { - ali1543_t *dev = (ali1543_t *)priv; + ali1543_t *dev = (ali1543_t *) priv; ali1543_log("M7101: dev->pmu_conf[%02x] = %02x\n", addr, val); if (func > 0) - return; + return; if (!dev->pmu_dev_enable) - return; + return; if ((dev->pmu_conf[0xc9] & 0x01) && (addr >= 0x40) && (addr != 0xc9)) - return; + return; switch (addr) { - case 0x04: /* Enable PMU */ - ali1543_log("PMU04: %02X\n", val); - dev->pmu_conf[addr] = val & 0x01; - if (!(dev->pmu_conf[0x5b] & 0x02)) - acpi_update_io_mapping(dev->acpi, (dev->pmu_conf[0x11] << 8) | (dev->pmu_conf[0x10] & 0xc0), dev->pmu_conf[0x04] & 1); - if (!(dev->pmu_conf[0x5b] & 0x04)) { - if (dev->type == 1) - smbus_ali7101_remap(dev->smbus, (dev->pmu_conf[0x15] << 8) | (dev->pmu_conf[0x14] & 0xc0), (dev->pmu_conf[0xe0] & 1) && (dev->pmu_conf[0x04] & 1)); - else - smbus_ali7101_remap(dev->smbus, (dev->pmu_conf[0x15] << 8) | (dev->pmu_conf[0x14] & 0xe0), (dev->pmu_conf[0xe0] & 1) && (dev->pmu_conf[0x04] & 1)); - } - break; + case 0x04: /* Enable PMU */ + ali1543_log("PMU04: %02X\n", val); + dev->pmu_conf[addr] = val & 0x01; + if (!(dev->pmu_conf[0x5b] & 0x02)) + acpi_update_io_mapping(dev->acpi, (dev->pmu_conf[0x11] << 8) | (dev->pmu_conf[0x10] & 0xc0), dev->pmu_conf[0x04] & 1); + if (!(dev->pmu_conf[0x5b] & 0x04)) { + if (dev->type == 1) + smbus_ali7101_remap(dev->smbus, (dev->pmu_conf[0x15] << 8) | (dev->pmu_conf[0x14] & 0xc0), (dev->pmu_conf[0xe0] & 1) && (dev->pmu_conf[0x04] & 1)); + else + smbus_ali7101_remap(dev->smbus, (dev->pmu_conf[0x15] << 8) | (dev->pmu_conf[0x14] & 0xe0), (dev->pmu_conf[0xe0] & 1) && (dev->pmu_conf[0x04] & 1)); + } + break; - /* PMU Base I/O */ - case 0x10: case 0x11: - if (!(dev->pmu_conf[0x5b] & 0x02)) { - if (addr == 0x10) - dev->pmu_conf[addr] = (val & 0xc0) | 1; - else if (addr == 0x11) - dev->pmu_conf[addr] = val; + /* PMU Base I/O */ + case 0x10: + case 0x11: + if (!(dev->pmu_conf[0x5b] & 0x02)) { + if (addr == 0x10) + dev->pmu_conf[addr] = (val & 0xc0) | 1; + else if (addr == 0x11) + dev->pmu_conf[addr] = val; - ali1543_log("New ACPI base address: %08X\n", (dev->pmu_conf[0x11] << 8) | (dev->pmu_conf[0x10] & 0xc0)); - acpi_update_io_mapping(dev->acpi, (dev->pmu_conf[0x11] << 8) | (dev->pmu_conf[0x10] & 0xc0), dev->pmu_conf[0x04] & 1); - } - break; + ali1543_log("New ACPI base address: %08X\n", (dev->pmu_conf[0x11] << 8) | (dev->pmu_conf[0x10] & 0xc0)); + acpi_update_io_mapping(dev->acpi, (dev->pmu_conf[0x11] << 8) | (dev->pmu_conf[0x10] & 0xc0), dev->pmu_conf[0x04] & 1); + } + break; - /* SMBus Base I/O */ - case 0x14: case 0x15: - if (!(dev->pmu_conf[0x5b] & 0x04)) { - if (addr == 0x14) { - if (dev->type == 1) - dev->pmu_conf[addr] = (val & 0xc0) | 1; - else - dev->pmu_conf[addr] = (val & 0xe0) | 1; - } else if (addr == 0x15) - dev->pmu_conf[addr] = val; + /* SMBus Base I/O */ + case 0x14: + case 0x15: + if (!(dev->pmu_conf[0x5b] & 0x04)) { + if (addr == 0x14) { + if (dev->type == 1) + dev->pmu_conf[addr] = (val & 0xc0) | 1; + else + dev->pmu_conf[addr] = (val & 0xe0) | 1; + } else if (addr == 0x15) + dev->pmu_conf[addr] = val; - if (dev->type == 1) { - ali1543_log("New SMBUS base address: %08X\n", (dev->pmu_conf[0x15] << 8) | (dev->pmu_conf[0x14] & 0xc0)); - smbus_ali7101_remap(dev->smbus, (dev->pmu_conf[0x15] << 8) | (dev->pmu_conf[0x14] & 0xc0), (dev->pmu_conf[0xe0] & 1) && (dev->pmu_conf[0x04] & 1)); - } else { - ali1543_log("New SMBUS base address: %08X\n", (dev->pmu_conf[0x15] << 8) | (dev->pmu_conf[0x14] & 0xe0)); - smbus_ali7101_remap(dev->smbus, (dev->pmu_conf[0x15] << 8) | (dev->pmu_conf[0x14] & 0xe0), (dev->pmu_conf[0xe0] & 1) && (dev->pmu_conf[0x04] & 1)); - } - } - break; + if (dev->type == 1) { + ali1543_log("New SMBUS base address: %08X\n", (dev->pmu_conf[0x15] << 8) | (dev->pmu_conf[0x14] & 0xc0)); + smbus_ali7101_remap(dev->smbus, (dev->pmu_conf[0x15] << 8) | (dev->pmu_conf[0x14] & 0xc0), (dev->pmu_conf[0xe0] & 1) && (dev->pmu_conf[0x04] & 1)); + } else { + ali1543_log("New SMBUS base address: %08X\n", (dev->pmu_conf[0x15] << 8) | (dev->pmu_conf[0x14] & 0xe0)); + smbus_ali7101_remap(dev->smbus, (dev->pmu_conf[0x15] << 8) | (dev->pmu_conf[0x14] & 0xe0), (dev->pmu_conf[0xe0] & 1) && (dev->pmu_conf[0x04] & 1)); + } + } + break; - /* Subsystem Vendor ID */ - case 0x2c: case 0x2d: case 0x2e: case 0x2f: - if (!(dev->pmu_conf[0xd8] & 0x08)) - dev->pmu_conf[addr] = val; - break; + /* Subsystem Vendor ID */ + case 0x2c: + case 0x2d: + case 0x2e: + case 0x2f: + if (!(dev->pmu_conf[0xd8] & 0x08)) + dev->pmu_conf[addr] = val; + break; - case 0x40: - dev->pmu_conf[addr] = val & 0x1f; - pic_set_smi_irq_mask(8, (dev->pmu_conf[0x77] & 0x08) && (dev->pmu_conf[0x40] & 0x03)); - break; - case 0x41: - dev->pmu_conf[addr] = val & 0x10; - ali1543_log("PMU41: %02X\n", val); - apm_set_do_smi(dev->acpi->apm, (dev->pmu_conf[0x77] & 0x08) && (dev->pmu_conf[0x41] & 0x10)); - break; + case 0x40: + dev->pmu_conf[addr] = val & 0x1f; + nvr_smi_enable((dev->pmu_conf[0x77] & 0x08) && (dev->pmu_conf[0x40] & 0x08), dev->nvr); + break; + case 0x41: + dev->pmu_conf[addr] = val & 0x10; + ali1543_log("PMU41: %02X\n", val); + apm_set_do_smi(dev->acpi->apm, (dev->pmu_conf[0x77] & 0x08) && (dev->pmu_conf[0x41] & 0x10)); + break; - /* TODO: Is the status R/W or R/WC? */ - case 0x42: - dev->pmu_conf[addr] &= ~(val & 0x1f); - break; - case 0x43: - dev->pmu_conf[addr] &= ~(val & 0x10); - if (val & 0x10) - acpi_ali_soft_smi_status_write(dev->acpi, 0); - break; + /* TODO: Is the status R/W or R/WC? */ + case 0x42: + dev->pmu_conf[addr] &= ~(val & 0x1f); + if (val & 0x08) + nvr_smi_status_clear(dev->nvr); + break; + case 0x43: + dev->pmu_conf[addr] &= ~(val & 0x10); + if (val & 0x10) + acpi_ali_soft_smi_status_write(dev->acpi, 0); + break; - case 0x44: - dev->pmu_conf[addr] = val; - break; - case 0x45: - dev->pmu_conf[addr] = val & 0x9f; - break; - case 0x46: - dev->pmu_conf[addr] = val & 0x18; - break; + case 0x44: + dev->pmu_conf[addr] = val; + break; + case 0x45: + dev->pmu_conf[addr] = val & 0x9f; + break; + case 0x46: + dev->pmu_conf[addr] = val & 0x18; + break; - /* TODO: Is the status R/W or R/WC? */ - case 0x48: - dev->pmu_conf[addr] &= ~val; - break; - case 0x49: - dev->pmu_conf[addr] &= ~(val & 0x9f); - break; - case 0x4a: - dev->pmu_conf[addr] &= ~(val & 0x38); - break; + /* TODO: Is the status R/W or R/WC? */ + case 0x48: + dev->pmu_conf[addr] &= ~val; + break; + case 0x49: + dev->pmu_conf[addr] &= ~(val & 0x9f); + break; + case 0x4a: + dev->pmu_conf[addr] &= ~(val & 0x38); + break; - case 0x4c: - dev->pmu_conf[addr] = val & 5; - break; - case 0x4d: - dev->pmu_conf[addr] = val & 1; - break; + case 0x4c: + dev->pmu_conf[addr] = val & 5; + break; + case 0x4d: + dev->pmu_conf[addr] = val & 1; + break; - /* TODO: Is the status R/W or R/WC? */ - case 0x4e: - dev->pmu_conf[addr] &= ~(val & 5); - break; - case 0x4f: - dev->pmu_conf[addr] &= ~(val & 1); - break; + /* TODO: Is the status R/W or R/WC? */ + case 0x4e: + dev->pmu_conf[addr] &= ~(val & 5); + break; + case 0x4f: + dev->pmu_conf[addr] &= ~(val & 1); + break; - case 0x50: case 0x51: - if (dev->type == 1) - dev->pmu_conf[addr] = val; - break; + case 0x50: + case 0x51: + if (dev->type == 1) + dev->pmu_conf[addr] = val; + break; - case 0x52: case 0x53: - if (dev->type == 1) - dev->pmu_conf[addr] &= ~val; - break; + case 0x52: + case 0x53: + if (dev->type == 1) + dev->pmu_conf[addr] &= ~val; + break; - case 0x54: /* Standby timer */ - dev->pmu_conf[addr] = val; - break; - case 0x55: /* APM Timer */ - dev->pmu_conf[addr] = val & 0x7f; - break; - case 0x59: /* Global display timer. */ - dev->pmu_conf[addr] = val & 0x1f; - break; + case 0x54: /* Standby timer */ + dev->pmu_conf[addr] = val; + break; + case 0x55: /* APM Timer */ + dev->pmu_conf[addr] = val & 0x7f; + break; + case 0x59: /* Global display timer. */ + dev->pmu_conf[addr] = val & 0x1f; + break; - case 0x5b: /* ACPI/SMB Base I/O Control */ - if (dev->type == 1) - dev->pmu_conf[addr] = val & 0x87; - else - dev->pmu_conf[addr] = val & 0x7f; - break; + case 0x5b: /* ACPI/SMB Base I/O Control */ + if (dev->type == 1) + dev->pmu_conf[addr] = val & 0x87; + else + dev->pmu_conf[addr] = val & 0x7f; + break; - case 0x60: - dev->pmu_conf[addr] = val; - break; - case 0x61: - dev->pmu_conf[addr] = val & 0x13; - break; - case 0x62: - dev->pmu_conf[addr] = val & 0xf1; - break; - case 0x63: - dev->pmu_conf[addr] = val & 0x07; - break; + case 0x60: + dev->pmu_conf[addr] = val; + break; + case 0x61: + dev->pmu_conf[addr] = val & 0x13; + break; + case 0x62: + dev->pmu_conf[addr] = val & 0xf1; + break; + case 0x63: + dev->pmu_conf[addr] = val & 0x07; + break; - case 0x64: - dev->pmu_conf[addr] = val; - break; - case 0x65: - dev->pmu_conf[addr] = val & 0x11; - break; + case 0x64: + dev->pmu_conf[addr] = val; + break; + case 0x65: + dev->pmu_conf[addr] = val & 0x11; + break; - case 0x68: - dev->pmu_conf[addr] = val & 0x07; - break; + case 0x68: + dev->pmu_conf[addr] = val & 0x07; + break; - case 0x6c: case 0x6d: - dev->pmu_conf[addr] = val; - break; - case 0x6e: - dev->pmu_conf[addr] = val & 0xbf; - break; - case 0x6f: - if (dev->type == 1) - dev->pmu_conf[addr] = val & 0x1e; - else - dev->pmu_conf[addr] = val & 0x1f; - break; + case 0x6c: + case 0x6d: + dev->pmu_conf[addr] = val; + break; + case 0x6e: + dev->pmu_conf[addr] = val & 0xbf; + break; + case 0x6f: + if (dev->type == 1) + dev->pmu_conf[addr] = val & 0x1e; + else + dev->pmu_conf[addr] = val & 0x1f; + break; - case 0x70: - dev->pmu_conf[addr] = val; - break; - case 0x71: - dev->pmu_conf[addr] = val & 0x3f; - break; + case 0x70: + dev->pmu_conf[addr] = val; + break; + case 0x71: + dev->pmu_conf[addr] = val & 0x3f; + break; - case 0x72: - dev->pmu_conf[addr] = val & 0x0f; - break; + case 0x72: + dev->pmu_conf[addr] = val & 0x0f; + break; - /* TODO: Is the status R/W or R/WC? */ - case 0x74: - dev->pmu_conf[addr] &= ~(val & 0x33); - break; + /* TODO: Is the status R/W or R/WC? */ + case 0x74: + dev->pmu_conf[addr] &= ~(val & 0x33); + break; - case 0x75: - dev->pmu_conf[addr] = val; - break; + case 0x75: + dev->pmu_conf[addr] = val; + break; - case 0x76: - dev->pmu_conf[addr] = val & 0x7f; - break; + case 0x76: + dev->pmu_conf[addr] = val & 0x7f; + break; - case 0x77: - /* TODO: If bit 1 is clear, then status bit is set even if SMI is disabled. */ - dev->pmu_conf[addr] = val; - pic_set_smi_irq_mask(8, (dev->pmu_conf[0x77] & 0x08) && (dev->pmu_conf[0x40] & 0x03)); - ali1543_log("PMU77: %02X\n", val); - apm_set_do_smi(dev->acpi->apm, (dev->pmu_conf[0x77] & 0x08) && (dev->pmu_conf[0x41] & 0x10)); - break; + case 0x77: + /* TODO: If bit 1 is clear, then status bit is set even if SMI is disabled. */ + dev->pmu_conf[addr] = val; + ali1543_log("PMU77: %02X\n", val); + nvr_smi_enable((dev->pmu_conf[0x77] & 0x08) && (dev->pmu_conf[0x40] & 0x08), dev->nvr); + apm_set_do_smi(dev->acpi->apm, (dev->pmu_conf[0x77] & 0x08) && (dev->pmu_conf[0x41] & 0x10)); + break; - case 0x78: - dev->pmu_conf[addr] = val; - break; - case 0x79: - dev->pmu_conf[addr] = val & 0x0f; - break; + case 0x78: + dev->pmu_conf[addr] = val; + break; + case 0x79: + dev->pmu_conf[addr] = val & 0x0f; + break; - case 0x7a: - if (dev->type == 1) - dev->pmu_conf[addr] = val & 0x07; - else - dev->pmu_conf[addr] = val & 0x02; - break; + case 0x7a: + if (dev->type == 1) + dev->pmu_conf[addr] = val & 0x07; + else + dev->pmu_conf[addr] = val & 0x02; + break; - case 0x7b: - if (dev->type == 1) - dev->pmu_conf[addr] = val; - else - dev->pmu_conf[addr] = val & 0x7f; - break; + case 0x7b: + if (dev->type == 1) + dev->pmu_conf[addr] = val; + else + dev->pmu_conf[addr] = val & 0x7f; + break; - case 0x7c ... 0x7f: - dev->pmu_conf[addr] = val; - break; + case 0x7c ... 0x7f: + dev->pmu_conf[addr] = val; + break; - case 0x81: - dev->pmu_conf[addr] = val & 0xf0; - break; + case 0x81: + dev->pmu_conf[addr] = val & 0xf0; + break; - case 0x82: - if (dev->type == 1) - dev->pmu_conf[addr] = val & 0x01; - break; + case 0x82: + if (dev->type == 1) + dev->pmu_conf[addr] = val & 0x01; + break; - case 0x84 ... 0x87: - if (dev->type == 1) - dev->pmu_conf[addr] = val; - break; - case 0x88 ... 0x8b: - if (dev->type == 1) - dev->pmu_conf[addr] = val; - break; + case 0x84 ... 0x87: + if (dev->type == 1) + dev->pmu_conf[addr] = val; + break; + case 0x88 ... 0x8b: + if (dev->type == 1) + dev->pmu_conf[addr] = val; + break; - case 0x8c: case 0x8d: - dev->pmu_conf[addr] = val & 0x0f; - break; + case 0x8c: + case 0x8d: + dev->pmu_conf[addr] = val & 0x0f; + break; - case 0x90: - if (dev->type == 1) - dev->pmu_conf[addr] = val & 0x0f; - else - dev->pmu_conf[addr] = val & 0x01; - break; + case 0x90: + if (dev->type == 1) + dev->pmu_conf[addr] = val & 0x0f; + else + dev->pmu_conf[addr] = val & 0x01; + break; - case 0x91: - if (dev->type == 1) - dev->pmu_conf[addr] = val & 0x02; - break; + case 0x91: + if (dev->type == 1) + dev->pmu_conf[addr] = val & 0x02; + break; - case 0x94: - dev->pmu_conf[addr] = val & 0xf0; - break; - case 0x95 ... 0x97: - dev->pmu_conf[addr] = val; - break; + case 0x94: + dev->pmu_conf[addr] = val & 0xf0; + break; + case 0x95 ... 0x97: + dev->pmu_conf[addr] = val; + break; - case 0x98: case 0x99: - if (dev->type == 1) - dev->pmu_conf[addr] = val; - break; + case 0x98: + case 0x99: + if (dev->type == 1) + dev->pmu_conf[addr] = val; + break; - case 0xa4: case 0xa5: - dev->pmu_conf[addr] = val; - break; + case 0xa4: + case 0xa5: + dev->pmu_conf[addr] = val; + break; - case 0xb2: - dev->pmu_conf[addr] = val & 0x01; - break; + case 0xb2: + dev->pmu_conf[addr] = val & 0x01; + break; - case 0xb3: - dev->pmu_conf[addr] = val & 0x7f; - break; + case 0xb3: + dev->pmu_conf[addr] = val & 0x7f; + break; - case 0xb4: - dev->pmu_conf[addr] = val & 0x7c; - break; + case 0xb4: + dev->pmu_conf[addr] = val & 0x7c; + break; - case 0xb5: case 0xb7: - dev->pmu_conf[addr] = val & 0x0f; - break; + case 0xb5: + case 0xb7: + dev->pmu_conf[addr] = val & 0x0f; + break; - case 0xb8: case 0xb9: - if (dev->type == 1) - dev->pmu_conf[addr] = val; - break; + case 0xb8: + case 0xb9: + if (dev->type == 1) + dev->pmu_conf[addr] = val; + break; - case 0xbc: - outb(0x70, val); - break; + case 0xbc: + outb(0x70, val); + break; - case 0xbd: - dev->pmu_conf[addr] = val & 0x0f; - acpi_set_timer32(dev->acpi, val & 0x04); - break; + case 0xbd: + dev->pmu_conf[addr] = val & 0x0f; + acpi_set_timer32(dev->acpi, val & 0x04); + break; - case 0xbe: - dev->pmu_conf[addr] = val & 0x03; - break; + case 0xbe: + dev->pmu_conf[addr] = val & 0x03; + break; - /* Continue Further Later */ - /* GPO Registers */ - case 0xc0: - dev->pmu_conf[addr] = val & 0x0f; - acpi_init_gporeg(dev->acpi, dev->pmu_conf[0xc0], dev->pmu_conf[0xc1], dev->pmu_conf[0xc2] | (dev->pmu_conf[0xc3] << 5), 0x00); - break; - case 0xc1: - dev->pmu_conf[addr] = val & 0x12; - acpi_init_gporeg(dev->acpi, dev->pmu_conf[0xc0], dev->pmu_conf[0xc1], dev->pmu_conf[0xc2] | (dev->pmu_conf[0xc3] << 5), 0x00); - break; - case 0xc2: - dev->pmu_conf[addr] = val & 0x1c; - acpi_init_gporeg(dev->acpi, dev->pmu_conf[0xc0], dev->pmu_conf[0xc1], dev->pmu_conf[0xc2] | (dev->pmu_conf[0xc3] << 5), 0x00); - break; - case 0xc3: - dev->pmu_conf[addr] = val & 0x06; - acpi_init_gporeg(dev->acpi, dev->pmu_conf[0xc0], dev->pmu_conf[0xc1], dev->pmu_conf[0xc2] | (dev->pmu_conf[0xc3] << 5), 0x00); - break; + /* Continue Further Later */ + /* GPO Registers */ + case 0xc0: + dev->pmu_conf[addr] = val & 0x0f; + acpi_init_gporeg(dev->acpi, dev->pmu_conf[0xc0], dev->pmu_conf[0xc1], dev->pmu_conf[0xc2] | (dev->pmu_conf[0xc3] << 5), 0x00); + break; + case 0xc1: + dev->pmu_conf[addr] = val & 0x12; + acpi_init_gporeg(dev->acpi, dev->pmu_conf[0xc0], dev->pmu_conf[0xc1], dev->pmu_conf[0xc2] | (dev->pmu_conf[0xc3] << 5), 0x00); + break; + case 0xc2: + dev->pmu_conf[addr] = val & 0x1c; + acpi_init_gporeg(dev->acpi, dev->pmu_conf[0xc0], dev->pmu_conf[0xc1], dev->pmu_conf[0xc2] | (dev->pmu_conf[0xc3] << 5), 0x00); + break; + case 0xc3: + dev->pmu_conf[addr] = val & 0x06; + acpi_init_gporeg(dev->acpi, dev->pmu_conf[0xc0], dev->pmu_conf[0xc1], dev->pmu_conf[0xc2] | (dev->pmu_conf[0xc3] << 5), 0x00); + break; - case 0xc6: - dev->pmu_conf[addr] = val & 0x06; - break; + case 0xc6: + dev->pmu_conf[addr] = val & 0x06; + break; - case 0xc8: case 0xc9: - dev->pmu_conf[addr] = val & 0x01; - break; + case 0xc8: + case 0xc9: + dev->pmu_conf[addr] = val & 0x01; + break; - case 0xca: - /* TODO: Write to this port causes a beep. */ - dev->pmu_conf[addr] = val; - break; + case 0xca: + /* TODO: Write to this port causes a beep. */ + dev->pmu_conf[addr] = val; + break; - case 0xcc: - if (dev->type == 1) - dev->pmu_conf[addr] = val & 0x1f; - break; - case 0xcd: - if (dev->type == 1) - dev->pmu_conf[addr] = val & 0x33; - break; + case 0xcc: + if (dev->type == 1) + dev->pmu_conf[addr] = val & 0x1f; + break; + case 0xcd: + if (dev->type == 1) + dev->pmu_conf[addr] = val & 0x33; + break; - case 0xd4: - dev->pmu_conf[addr] = val & 0x01; - break; + case 0xd4: + dev->pmu_conf[addr] = val & 0x01; + break; - case 0xd8: - dev->pmu_conf[addr] = val & 0xfd; - break; - case 0xd9: - if (dev->type == 1) - dev->pmu_conf[addr] = val & 0x3f; - break; + case 0xd8: + dev->pmu_conf[addr] = val & 0xfd; + break; + case 0xd9: + if (dev->type == 1) + dev->pmu_conf[addr] = val & 0x3f; + break; - case 0xe0: - dev->pmu_conf[addr] = val & 0x03; - if (dev->type == 1) - smbus_ali7101_remap(dev->smbus, (dev->pmu_conf[0x15] << 8) | (dev->pmu_conf[0x14] & 0xc0), (dev->pmu_conf[0xe0] & 1) && (dev->pmu_conf[0x04] & 1) && (!(dev->pci_conf[0x5f] & 4))); - else - smbus_ali7101_remap(dev->smbus, (dev->pmu_conf[0x15] << 8) | (dev->pmu_conf[0x14] & 0xe0), (dev->pmu_conf[0xe0] & 1) && (dev->pmu_conf[0x04] & 1) && (!(dev->pci_conf[0x5f] & 4))); - break; + case 0xe0: + dev->pmu_conf[addr] = val & 0x03; + if (dev->type == 1) + smbus_ali7101_remap(dev->smbus, (dev->pmu_conf[0x15] << 8) | (dev->pmu_conf[0x14] & 0xc0), (dev->pmu_conf[0xe0] & 1) && (dev->pmu_conf[0x04] & 1) && (!(dev->pci_conf[0x5f] & 4))); + else + smbus_ali7101_remap(dev->smbus, (dev->pmu_conf[0x15] << 8) | (dev->pmu_conf[0x14] & 0xe0), (dev->pmu_conf[0xe0] & 1) && (dev->pmu_conf[0x04] & 1) && (!(dev->pci_conf[0x5f] & 4))); + break; - case 0xe1: - dev->pmu_conf[addr] = val; - break; + case 0xe1: + dev->pmu_conf[addr] = val; + break; - case 0xe2: - dev->pmu_conf[addr] = val & 0xf8; - break; + case 0xe2: + dev->pmu_conf[addr] = val & 0xf8; + break; - default: - dev->pmu_conf[addr] = val; - break; + default: + dev->pmu_conf[addr] = val; + break; } } - static uint8_t ali7101_read(int func, int addr, void *priv) { - ali1543_t *dev = (ali1543_t *)priv; - uint8_t ret = 0xff; + ali1543_t *dev = (ali1543_t *) priv; + uint8_t ret = 0xff; if (dev->pmu_dev_enable && (func == 0)) { - if ((dev->pmu_conf[0xc9] & 0x01) && (addr >= 0x40) && (addr != 0xc9)) - return 0xff; + if ((dev->pmu_conf[0xc9] & 0x01) && (addr >= 0x40) && (addr != 0xc9)) + return 0xff; - /* TODO: C4, C5 = GPIREG (masks: 0D, 0E) */ - if (addr == 0x43) - ret = acpi_ali_soft_smi_status_read(dev->acpi) ? 0x10 : 0x00; - else if (addr == 0x7f) - ret = 0x80; - else if (addr == 0xbc) - ret = inb(0x70); - else - ret = dev->pmu_conf[addr]; + /* TODO: C4, C5 = GPIREG (masks: 0D, 0E) */ + switch (addr) { + default: + ret = dev->pmu_conf[addr]; + break; + case 0x42: + ret = (dev->pmu_conf[addr] & 0xf7) | (nvr_smi_status(dev->nvr) ? 0x08 : 0x00); + break; + case 0x43: + ret = acpi_ali_soft_smi_status_read(dev->acpi) ? 0x10 : 0x00; + break; + case 0x7f: + ret = 0x80; + break; + case 0xbc: + ret = inb(0x70); + break; + } - if (dev->pmu_conf[0x77] & 0x10) { - switch (addr) { - case 0x42: - dev->pmu_conf[addr] &= 0xe0; - break; - case 0x43: - dev->pmu_conf[addr] &= 0xef; - acpi_ali_soft_smi_status_write(dev->acpi, 0); - break; + if (dev->pmu_conf[0x77] & 0x10) { + switch (addr) { + case 0x42: + dev->pmu_conf[addr] &= 0xe0; + break; + case 0x43: + dev->pmu_conf[addr] &= 0xef; + acpi_ali_soft_smi_status_write(dev->acpi, 0); + break; - case 0x48: - dev->pmu_conf[addr] = 0x00; - break; - case 0x49: - dev->pmu_conf[addr] &= 0x60; - break; - case 0x4a: - dev->pmu_conf[addr] &= 0xc7; - break; + case 0x48: + dev->pmu_conf[addr] = 0x00; + break; + case 0x49: + dev->pmu_conf[addr] &= 0x60; + break; + case 0x4a: + dev->pmu_conf[addr] &= 0xc7; + break; - case 0x4e: - dev->pmu_conf[addr] &= 0xfa; - break; - case 0x4f: - dev->pmu_conf[addr] &= 0xfe; - break; + case 0x4e: + dev->pmu_conf[addr] &= 0xfa; + break; + case 0x4f: + dev->pmu_conf[addr] &= 0xfe; + break; - case 0x74: - dev->pmu_conf[addr] &= 0xcc; - break; - } - } + case 0x74: + dev->pmu_conf[addr] &= 0xcc; + break; + + default: + break; + } + } } return ret; } - -static void -ali1533_sio_fdc_handler(ali1543_t *dev) -{ - fdc_remove(dev->fdc_controller); - - if (dev->device_regs[0][0x30] & 1) { - ali1543_log("New FDC base address: %04X\n", dev->device_regs[0][0x61] | (dev->device_regs[0][0x60] << 8)); - fdc_set_base(dev->fdc_controller, dev->device_regs[0][0x61] | (dev->device_regs[0][0x60] << 8)); - fdc_set_irq(dev->fdc_controller, dev->device_regs[0][0x70] & 0xf); - fdc_set_dma_ch(dev->fdc_controller, dev->device_regs[0][0x74] & 0x07); - ali1543_log("M1543-SIO FDC: ADDR %04x IRQ %02x DMA %02x\n", dev->device_regs[0][0x61] | (dev->device_regs[0][0x60] << 8), dev->device_regs[0][0x70] & 0xf, dev->device_regs[0][0x74] & 0x07); - } -} - - -static void -ali1533_sio_uart_handler(int num, ali1543_t *dev) -{ - serial_remove(dev->uart[num]); - - if (dev->device_regs[num + 4][0x30] & 1) { - serial_setup(dev->uart[num], dev->device_regs[num + 4][0x61] | (dev->device_regs[num + 4][0x60] << 8), dev->device_regs[num + 4][0x70] & 0xf); - ali1543_log("M1543-SIO UART%d: ADDR %04x IRQ %02x\n", num, dev->device_regs[num + 4][0x61] | (dev->device_regs[num + 4][0x60] << 8), dev->device_regs[num + 4][0x70] & 0xf); - } -} - - -void -ali1533_sio_lpt_handler(ali1543_t *dev) -{ - lpt1_remove(); - - if (dev->device_regs[3][0x30] & 1) { - lpt1_init(dev->device_regs[3][0x61] | (dev->device_regs[3][0x60] << 8)); - lpt1_irq(dev->device_regs[3][0x70] & 0xf); - ali1543_log("M1543-SIO LPT: ADDR %04x IRQ %02x\n", dev->device_regs[3][0x61] | (dev->device_regs[3][0x60] << 8), dev->device_regs[3][0x70] & 0xf); - } -} - - -void -ali1533_sio_ldn(uint16_t ldn, ali1543_t *dev) -{ - /* We don't include all LDN's */ - switch (ldn) { - case 0: /* FDC */ - ali1533_sio_fdc_handler(dev); - break; - case 3: /* LPT */ - ali1533_sio_lpt_handler(dev); - break; - /* UART */ - case 4: case 5: - ali1533_sio_uart_handler(ldn - 4, dev); - break; - } -} - - -static void -ali1533_sio_write(uint16_t addr, uint8_t val, void *priv) -{ - ali1543_t *dev = (ali1543_t *)priv; - - switch (addr) { - case 0x3f0: - dev->sio_index = val; - if (dev->sio_index == 0x51) - dev->in_configuration_mode = 1; - else if ((dev->sio_index == 0x23) && (dev->in_configuration_mode == 1)) - dev->in_configuration_mode = 2; - else if (dev->sio_index == 0xbb) - dev->in_configuration_mode = 0; - break; - - case 0x3f1: - if (dev->in_configuration_mode == 2) { - switch (dev->sio_index) { - case 0x07: - dev->sio_regs[dev->sio_index] = val & 0x7; - break; - - case 0x22: - dev->sio_regs[dev->sio_index] = val & 0x39; - break; - - case 0x23: - dev->sio_regs[dev->sio_index] = val & 0x38; - break; - - default: - if ((dev->sio_index < 0x30) || (dev->sio_index == 0x51) || (dev->sio_index == 0xbb)) - dev->sio_regs[dev->sio_index] = val; - else if (dev->sio_regs[0x07] <= 7) - dev->device_regs[dev->sio_regs[0x07]][dev->sio_index] = val; - break; - } - } - break; - } - - if ((!dev->in_configuration_mode) && (dev->sio_regs[0x07] <= 7) && (addr == 0x03f0)) - ali1533_sio_ldn(dev->sio_regs[0x07], dev); -} - - -static uint8_t -ali1533_sio_read(uint16_t addr, void *priv) -{ - ali1543_t *dev = (ali1543_t *)priv; - uint8_t ret = 0xff; - - if (addr == 0x03f1) { - if (dev->sio_index >= 0x30) - ret = dev->device_regs[dev->sio_regs[0x07]][dev->sio_index]; - else - ret = dev->sio_regs[dev->sio_index]; - } - - return ret; -} - - static void ali1543_reset(void *priv) { - ali1543_t *dev = (ali1543_t *)priv; - int i; + ali1543_t *dev = (ali1543_t *) priv; /* Temporarily enable everything. Register writes will disable the devices. */ dev->ide_dev_enable = 1; @@ -1601,11 +1547,12 @@ ali1543_reset(void *priv) dev->pci_conf[0x04] = 0x0f; dev->pci_conf[0x07] = 0x02; if (dev->type == 1) - dev->pci_conf[0x08] = 0xc0; + dev->pci_conf[0x08] = 0xc0; dev->pci_conf[0x0a] = 0x01; dev->pci_conf[0x0b] = 0x06; - ali1533_write(0, 0x48, 0x00, dev); // Disables all IRQ's + ali1533_write(0, 0x41, 0x00, dev); /* Disables the keyboard and mouse IRQ latch. */ + ali1533_write(0, 0x48, 0x00, dev); /* Disables all IRQ's. */ ali1533_write(0, 0x44, 0x00, dev); ali1533_write(0, 0x4d, 0x00, dev); ali1533_write(0, 0x53, 0x00, dev); @@ -1615,82 +1562,41 @@ ali1543_reset(void *priv) ali1533_write(0, 0x74, 0x00, dev); ali1533_write(0, 0x75, 0x00, dev); ali1533_write(0, 0x76, 0x00, dev); - - /* M1543 Super I/O */ - memset(dev->sio_regs, 0x00, sizeof(dev->sio_regs)); - for (i = 0; i < 8; i++) - memset(dev->device_regs[i], 0x00, sizeof(dev->device_regs[i])); - - dev->device_regs[0][0x60] = 0x03; - dev->device_regs[0][0x61] = 0xf0; - dev->device_regs[0][0x70] = 0x06; - dev->device_regs[0][0x74] = 0x02; - dev->device_regs[0][0xf0] = 0x08; - dev->device_regs[0][0xf2] = 0xff; - - dev->device_regs[3][0x60] = 0x03; - dev->device_regs[3][0x61] = 0x78; - dev->device_regs[3][0x70] = 0x05; - dev->device_regs[3][0x74] = 0x04; - dev->device_regs[3][0xf0] = 0x0c; - dev->device_regs[3][0xf1] = 0x05; - - dev->device_regs[4][0x60] = 0x03; - dev->device_regs[4][0x61] = 0xf8; - dev->device_regs[4][0x70] = 0x04; - dev->device_regs[4][0xf1] = 0x02; - dev->device_regs[4][0xf2] = 0x0c; - - dev->device_regs[5][0x60] = 0x02; - dev->device_regs[5][0x61] = 0xf8; - dev->device_regs[5][0x70] = 0x03; - dev->device_regs[5][0xf1] = 0x02; - dev->device_regs[5][0xf2] = 0x0c; - - dev->device_regs[7][0x70] = 0x01; - - ali1533_sio_fdc_handler(dev); - ali1533_sio_uart_handler(0, dev); - ali1533_sio_uart_handler(1, dev); - ali1533_sio_lpt_handler(dev); + if (dev->type == 1) + ali1533_write(0, 0x78, 0x00, dev); unmask_a20_in_smm = 1; } - static void ali1543_close(void *priv) { - ali1543_t *dev = (ali1543_t *)priv; + ali1543_t *dev = (ali1543_t *) priv; free(dev); } - static void * ali1543_init(const device_t *info) { - ali1543_t *dev = (ali1543_t *)malloc(sizeof(ali1543_t)); + ali1543_t *dev = (ali1543_t *) malloc(sizeof(ali1543_t)); memset(dev, 0, sizeof(ali1543_t)); /* Device 02: M1533 Southbridge */ - dev->pci_slot = pci_add_card(PCI_ADD_SOUTHBRIDGE, ali1533_read, ali1533_write, dev); + pci_add_card(PCI_ADD_SOUTHBRIDGE, ali1533_read, ali1533_write, dev, &dev->pci_slot); /* Device 0B: M5229 IDE Controller*/ - dev->ide_slot = pci_add_card(PCI_ADD_SOUTHBRIDGE, ali5229_read, ali5229_write, dev); + pci_add_card(PCI_ADD_SOUTHBRIDGE_IDE, ali5229_read, ali5229_write, dev, &dev->ide_slot); /* Device 0C: M7101 Power Managment Controller */ - dev->pmu_slot = pci_add_card(PCI_ADD_SOUTHBRIDGE, ali7101_read, ali7101_write, dev); + pci_add_card(PCI_ADD_SOUTHBRIDGE_PMU, ali7101_read, ali7101_write, dev, &dev->pmu_slot); /* Device 0F: M5237 USB */ - dev->usb_slot = pci_add_card(PCI_ADD_SOUTHBRIDGE, ali5237_read, ali5237_write, dev); - - /* Ports 3F0-1h: M1543 Super I/O */ - io_sethandler(0x03f0, 0x0002, ali1533_sio_read, NULL, NULL, ali1533_sio_write, NULL, NULL, dev); + pci_add_card(PCI_ADD_SOUTHBRIDGE_USB, ali5237_read, ali5237_write, dev, &dev->usb_slot); /* ACPI */ dev->acpi = device_add(&acpi_ali_device); - dev->nvr = device_add(&piix4_nvr_device); + dev->nvr = device_add(&piix4_nvr_device); /* DMA */ dma_alias_set(); @@ -1703,9 +1609,6 @@ ali1543_init(const device_t *info) /* DDMA */ dev->ddma = device_add(&ddma_device); - /* Floppy Disk Controller */ - dev->fdc_controller = device_add(&fdc_at_smc_device); - /* IDE Controllers */ dev->ide_controller[0] = device_add_inst(&sff8038i_device, 1); dev->ide_controller[1] = device_add_inst(&sff8038i_device, 2); @@ -1713,20 +1616,17 @@ ali1543_init(const device_t *info) /* Port 92h */ dev->port_92 = device_add(&port_92_pci_device); - /* Serial NS16500 */ - dev->uart[0] = device_add_inst(&ns16550_device, 1); - dev->uart[1] = device_add_inst(&ns16550_device, 2); - /* Standard SMBus */ dev->smbus = device_add(&ali7101_smbus_device); - /* Super I/O Configuration Mechanism */ - dev->in_configuration_mode = 0; - /* USB */ dev->usb = device_add(&usb_device); - dev->type = info->local; + dev->type = info->local & 0xff; + dev->offset = (info->local >> 8) & 0x7f; + if (info->local & 0x8000) + dev->offset = -dev->offset; + ali1543_log("Offset = %i\n", dev->offset); pci_enable_mirq(0); pci_enable_mirq(1); @@ -1736,36 +1636,39 @@ ali1543_init(const device_t *info) pci_enable_mirq(5); pci_enable_mirq(6); + /* Super I/O chip */ + device_add(&ali5123_device); + ali1543_reset(dev); return dev; } - const device_t ali1543_device = { - "ALi M1543 Desktop South Bridge", - "ali1543", - DEVICE_PCI, - 0, - ali1543_init, - ali1543_close, - ali1543_reset, - { NULL }, - NULL, - NULL, - NULL + .name = "ALi M1543 Desktop South Bridge", + .internal_name = "ali1543", + .flags = DEVICE_PCI, + .local = 0x8500, /* -5 slot offset, we can do this because we currently + have no case of M1543 non-C with a different offset */ + .init = ali1543_init, + .close = ali1543_close, + .reset = ali1543_reset, + { .available = NULL }, + .speed_changed = NULL, + .force_redraw = NULL, + .config = NULL }; const device_t ali1543c_device = { - "ALi M1543C Desktop South Bridge", - "ali1543c", - DEVICE_PCI, - 1, - ali1543_init, - ali1543_close, - ali1543_reset, - { NULL }, - NULL, - NULL, - NULL + .name = "ALi M1543C Desktop South Bridge", + .internal_name = "ali1543c", + .flags = DEVICE_PCI, + .local = 1, + .init = ali1543_init, + .close = ali1543_close, + .reset = ali1543_reset, + { .available = NULL }, + .speed_changed = NULL, + .force_redraw = NULL, + .config = NULL }; diff --git a/src/chipset/ali1621.c b/src/chipset/ali1621.c index 65cee2fd6..6194dce19 100644 --- a/src/chipset/ali1621.c +++ b/src/chipset/ali1621.c @@ -1,16 +1,18 @@ /* - * 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. + * 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. + * This file is part of the 86Box distribution. * - * Implementation of the ALi M1621/2 CPU-to-PCI Bridge. + * Implementation of the ALi M1621/2 CPU-to-PCI Bridge. * - * Authors: Miran Grca, * - * Copyright 2021 Miran Grca. + * + * Authors: Miran Grca, + * + * Copyright 2021 Miran Grca. */ #include #include @@ -26,561 +28,575 @@ #include <86box/io.h> #include <86box/mem.h> #include <86box/pci.h> +#include <86box/plat_fallthrough.h> +#include <86box/plat_unused.h> #include <86box/smram.h> #include <86box/spd.h> #include <86box/chipset.h> +typedef struct ali1621_t { + uint8_t pci_slot; + uint8_t pad; + uint8_t pad0; + uint8_t pad1; -typedef struct ali1621_t -{ - uint8_t pci_conf[256]; + uint8_t pci_conf[256]; - smram_t * smram[2]; + smram_t *smram[2]; } ali1621_t; - #ifdef ENABLE_ALI1621_LOG int ali1621_do_log = ENABLE_ALI1621_LOG; + static void ali1621_log(const char *fmt, ...) { va_list ap; - if (ali1621_do_log) - { + if (ali1621_do_log) { va_start(ap, fmt); pclog_ex(fmt, ap); va_end(ap); } } #else -#define ali1621_log(fmt, ...) +# define ali1621_log(fmt, ...) #endif - /* Table translated to a more sensible format: - Read cycles: - SMREN SMM Mode Code Data - 0 X X PCI PCI - 1 0 Close PCI PCI - 1 0 Lock PCI PCI - 1 0 Protect PCI PCI - 1 0 Open DRAM DRAM - 1 1 Open DRAM DRAM - 1 1 Protect DRAM DRAM - 1 1 Close DRAM PCI - 1 1 Lock DRAM PCI + Read cycles: + SMREN SMM Mode Code Data + 0 X X PCI PCI + 1 0 Close PCI PCI + 1 0 Lock PCI PCI + 1 0 Protect PCI PCI + 1 0 Open DRAM DRAM + 1 1 Open DRAM DRAM + 1 1 Protect DRAM DRAM + 1 1 Close DRAM PCI + 1 1 Lock DRAM PCI - Write cycles: - SMWEN SMM Mode Data - 0 X X PCI - 1 0 Close PCI - 1 0 Lock PCI - 1 0 Protect PCI - 1 0 Open DRAM - 1 1 Open DRAM - 1 1 Protect DRAM - 1 1 Close PCI - 1 1 Lock PCI + Write cycles: + SMWEN SMM Mode Data + 0 X X PCI + 1 0 Close PCI + 1 0 Lock PCI + 1 0 Protect PCI + 1 0 Open DRAM + 1 1 Open DRAM + 1 1 Protect DRAM + 1 1 Close PCI + 1 1 Lock PCI - Explanation of the modes based above: - If SM*EN = 0, SMRAM is entirely disabled, otherwise: - If mode is Close or Lock, then SMRAM always goes to PCI outside SMM, - and data to PCI, code to DRAM in SMM; - If mode is Protect, then SMRAM always goes to PCI outside SMM and - DRAM in SMM; - If mode is Open, then SMRAM always goes to DRAM. - Read and write are enabled separately. + Explanation of the modes based above: + If SM*EN = 0, SMRAM is entirely disabled, otherwise: + If mode is Close or Lock, then SMRAM always goes to PCI outside SMM, + and data to PCI, code to DRAM in SMM; + If mode is Protect, then SMRAM always goes to PCI outside SMM and + DRAM in SMM; + If mode is Open, then SMRAM always goes to DRAM. + Read and write are enabled separately. */ static void ali1621_smram_recalc(uint8_t val, ali1621_t *dev) { - uint16_t access_smm = 0x0000, access_normal = 0x0000; + uint16_t access_smm = 0x0000; + uint16_t access_normal = 0x0000; smram_disable_all(); if (val & 0xc0) { - /* SMRAM 0: A0000-BFFFF */ - if (val & 0x80) { - access_smm = ACCESS_SMRAM_X; + /* SMRAM 0: A0000-BFFFF */ + if (val & 0x80) { + access_smm = ACCESS_SMRAM_X; - switch (val & 0x30) { - case 0x10: /* Open. */ - access_normal = ACCESS_SMRAM_RX; - /* FALLTHROUGH */ - case 0x30: /* Protect. */ - access_smm |= ACCESS_SMRAM_R; - break; - } - } + switch (val & 0x30) { + case 0x10: /* Open. */ + access_normal = ACCESS_SMRAM_RX; + fallthrough; + case 0x30: /* Protect. */ + access_smm |= ACCESS_SMRAM_R; + break; + default: + break; + } + } - if (val & 0x40) switch (val & 0x30) { - case 0x10: /* Open. */ - access_normal |= ACCESS_SMRAM_W; - /* FALLTHROUGH */ - case 0x30: /* Protect. */ - access_smm |= ACCESS_SMRAM_W; - break; - } + if (val & 0x40) + switch (val & 0x30) { + case 0x10: /* Open. */ + access_normal |= ACCESS_SMRAM_W; + fallthrough; + case 0x30: /* Protect. */ + access_smm |= ACCESS_SMRAM_W; + break; + default: + break; + } - smram_enable(dev->smram[0], 0xa0000, 0xa0000, 0x20000, ((val & 0x30) == 0x10), (val & 0x30)); + smram_enable(dev->smram[0], 0xa0000, 0xa0000, 0x20000, ((val & 0x30) == 0x10), (val & 0x30)); - mem_set_access(ACCESS_NORMAL, 3, 0xa0000, 0x20000, access_normal); - mem_set_access(ACCESS_SMM, 3, 0xa0000, 0x20000, access_smm); + mem_set_access(ACCESS_NORMAL, 3, 0xa0000, 0x20000, access_normal); + mem_set_access(ACCESS_SMM, 3, 0xa0000, 0x20000, access_smm); } if (val & 0x08) - smram_enable(dev->smram[1], 0x38000, 0xa8000, 0x08000, 0, 1); + smram_enable(dev->smram[1], 0x38000, 0xa8000, 0x08000, 0, 1); flushmmucache_nopc(); } - static void -ali1621_shadow_recalc(int cur_reg, ali1621_t *dev) +ali1621_shadow_recalc(UNUSED(int cur_reg), ali1621_t *dev) { - int i, r_bit, w_bit, reg; - uint32_t base, flags = 0; + int r_bit; + int w_bit; + int reg; + uint32_t base; + uint32_t flags = 0; shadowbios = shadowbios_write = 0; /* C0000-EFFFF */ - for (i = 0; i < 12; i++) { - base = 0x000c0000 + (i << 14); - r_bit = (i << 1) + 4; - reg = 0x84; - if (r_bit > 23) { - r_bit &= 7; - reg += 3; - } else if (r_bit > 15) { - r_bit &= 7; - reg += 2; - } else if (r_bit > 7) { - r_bit &= 7; - reg++; - } - w_bit = r_bit + 1; + for (uint8_t i = 0; i < 12; i++) { + base = 0x000c0000 + (i << 14); + r_bit = (i << 1) + 4; + reg = 0x84; + if (r_bit > 23) { + r_bit &= 7; + reg += 3; + } else if (r_bit > 15) { + r_bit &= 7; + reg += 2; + } else if (r_bit > 7) { + r_bit &= 7; + reg++; + } + w_bit = r_bit + 1; - flags = (dev->pci_conf[reg] & (1 << r_bit)) ? MEM_READ_INTERNAL : MEM_READ_EXTANY; - flags |= ((dev->pci_conf[reg] & (1 << w_bit)) ? MEM_WRITE_INTERNAL : MEM_WRITE_EXTANY); + flags = (dev->pci_conf[reg] & (1 << r_bit)) ? MEM_READ_INTERNAL : MEM_READ_EXTANY; + flags |= ((dev->pci_conf[reg] & (1 << w_bit)) ? MEM_WRITE_INTERNAL : MEM_WRITE_EXTANY); - if (base >= 0x000e0000) { - if (dev->pci_conf[reg] & (1 << r_bit)) - shadowbios |= 1; - if (dev->pci_conf[reg] & (1 << r_bit)) - shadowbios_write |= 1; - } + if (base >= 0x000e0000) { + if (dev->pci_conf[reg] & (1 << r_bit)) + shadowbios |= 1; + if (dev->pci_conf[reg] & (1 << r_bit)) + shadowbios_write |= 1; + } - ali1621_log("%08X-%08X shadow: R%c, W%c\n", base, base + 0x00003fff, - (dev->pci_conf[reg] & (1 << r_bit)) ? 'I' : 'E', (dev->pci_conf[reg] & (1 << w_bit)) ? 'I' : 'E'); + ali1621_log("%08X-%08X shadow: R%c, W%c\n", base, base + 0x00003fff, + (dev->pci_conf[reg] & (1 << r_bit)) ? 'I' : 'E', (dev->pci_conf[reg] & (1 << w_bit)) ? 'I' : 'E'); mem_set_mem_state_both(base, 0x00004000, flags); } /* F0000-FFFFF */ - base = 0x000f0000; + base = 0x000f0000; r_bit = 4; w_bit = 5; - reg = 0x87; + reg = 0x87; flags = (dev->pci_conf[reg] & (1 << r_bit)) ? MEM_READ_INTERNAL : MEM_READ_EXTANY; flags |= ((dev->pci_conf[reg] & (1 << w_bit)) ? MEM_WRITE_INTERNAL : MEM_WRITE_EXTANY); if (dev->pci_conf[reg] & (1 << r_bit)) - shadowbios |= 1; + shadowbios |= 1; if (dev->pci_conf[reg] & (1 << r_bit)) - shadowbios_write |= 1; + shadowbios_write |= 1; ali1621_log("%08X-%08X shadow: R%c, W%c\n", base, base + 0x0000ffff, - (dev->pci_conf[reg] & (1 << r_bit)) ? 'I' : 'E', (dev->pci_conf[reg] & (1 << w_bit)) ? 'I' : 'E'); + (dev->pci_conf[reg] & (1 << r_bit)) ? 'I' : 'E', (dev->pci_conf[reg] & (1 << w_bit)) ? 'I' : 'E'); mem_set_mem_state_both(base, 0x00010000, flags); flushmmucache_nopc(); } - static void ali1621_mask_bar(ali1621_t *dev) { - uint32_t bar, mask; + uint32_t bar; + uint32_t mask; switch (dev->pci_conf[0xbc] & 0x0f) { - case 0x00: - default: - mask = 0x00000000; - break; - case 0x01: - mask = 0xfff00000; - break; - case 0x02: - mask = 0xffe00000; - break; - case 0x03: - mask = 0xffc00000; - break; - case 0x04: - mask = 0xff800000; - break; - case 0x06: - mask = 0xff000000; - break; - case 0x07: - mask = 0xfe000000; - break; - case 0x08: - mask = 0xfc000000; - break; - case 0x09: - mask = 0xf8000000; - break; - case 0x0a: - mask = 0xf0000000; - break; + default: + case 0x00: + mask = 0x00000000; + break; + case 0x01: + mask = 0xfff00000; + break; + case 0x02: + mask = 0xffe00000; + break; + case 0x03: + mask = 0xffc00000; + break; + case 0x04: + mask = 0xff800000; + break; + case 0x06: + mask = 0xff000000; + break; + case 0x07: + mask = 0xfe000000; + break; + case 0x08: + mask = 0xfc000000; + break; + case 0x09: + mask = 0xf8000000; + break; + case 0x0a: + mask = 0xf0000000; + break; } - bar = ((dev->pci_conf[0x13] << 24) | (dev->pci_conf[0x12] << 16)) & mask; + bar = ((dev->pci_conf[0x13] << 24) | (dev->pci_conf[0x12] << 16)) & mask; dev->pci_conf[0x12] = (bar >> 16) & 0xff; dev->pci_conf[0x13] = (bar >> 24) & 0xff; } - static void -ali1621_write(int func, int addr, uint8_t val, void *priv) +ali1621_write(UNUSED(int func), int addr, uint8_t val, void *priv) { - ali1621_t *dev = (ali1621_t *)priv; + ali1621_t *dev = (ali1621_t *) priv; switch (addr) { - case 0x04: - dev->pci_conf[addr] = val & 0x01; - break; - case 0x05: - dev->pci_conf[addr] = val & 0x01; - break; + case 0x04: + dev->pci_conf[addr] = val & 0x01; + break; + case 0x05: + dev->pci_conf[addr] = val & 0x01; + break; - case 0x07: - dev->pci_conf[addr] &= ~(val & 0xf0); - break; + case 0x07: + dev->pci_conf[addr] &= ~(val & 0xf0); + break; - case 0x0d: - dev->pci_conf[addr] = val & 0xf8; - break; + case 0x0d: + dev->pci_conf[addr] = val & 0xf8; + break; - case 0x12: - dev->pci_conf[0x12] = (val & 0xc0); - ali1621_mask_bar(dev); - break; - case 0x13: - dev->pci_conf[0x13] = val; - ali1621_mask_bar(dev); - break; + case 0x12: + dev->pci_conf[0x12] = (val & 0xc0); + ali1621_mask_bar(dev); + break; + case 0x13: + dev->pci_conf[0x13] = val; + ali1621_mask_bar(dev); + break; - case 0x34: - dev->pci_conf[addr] = val; - break; + case 0x34: + dev->pci_conf[addr] = val; + break; - case 0x40: - dev->pci_conf[addr] = val; - break; - case 0x41: - dev->pci_conf[addr] = val; - break; + case 0x40: + dev->pci_conf[addr] = val; + break; + case 0x41: + dev->pci_conf[addr] = val; + break; - case 0x42: - dev->pci_conf[addr] = val; - break; - case 0x43: - dev->pci_conf[addr] = val; - break; + case 0x42: + dev->pci_conf[addr] = val; + break; + case 0x43: + dev->pci_conf[addr] = val; + break; - case 0x44: - dev->pci_conf[addr] = val; - break; - case 0x45: - dev->pci_conf[addr] = val; - break; + case 0x44: + dev->pci_conf[addr] = val; + break; + case 0x45: + dev->pci_conf[addr] = val; + break; - case 0x46: - dev->pci_conf[addr] = val; - break; - case 0x47: - dev->pci_conf[addr] = val; - break; + case 0x46: + dev->pci_conf[addr] = val; + break; + case 0x47: + dev->pci_conf[addr] = val; + break; - case 0x48: - dev->pci_conf[addr] = val; - break; - case 0x49: - dev->pci_conf[addr] = val; - break; + case 0x48: + dev->pci_conf[addr] = val; + break; + case 0x49: + dev->pci_conf[addr] = val; + break; - case 0x4a: - dev->pci_conf[addr] = val; - break; + case 0x4a: + dev->pci_conf[addr] = val; + break; - case 0x4b: - dev->pci_conf[addr] = val & 0x0f; - break; + case 0x4b: + dev->pci_conf[addr] = val & 0x0f; + break; - case 0x4c: - dev->pci_conf[addr] = val; - break; + case 0x4c: + dev->pci_conf[addr] = val; + break; - case 0x4d: - dev->pci_conf[addr] = val; - break; + case 0x4d: + dev->pci_conf[addr] = val; + break; - case 0x4e: - dev->pci_conf[addr] = val; - break; - case 0x4f: - dev->pci_conf[addr] = val; - break; + case 0x4e: + dev->pci_conf[addr] = val; + break; + case 0x4f: + dev->pci_conf[addr] = val; + break; - case 0x50: - dev->pci_conf[addr] = val & 0xef; - break; + case 0x50: + dev->pci_conf[addr] = val & 0xef; + break; - case 0x51: - dev->pci_conf[addr] = val; - break; + case 0x51: + dev->pci_conf[addr] = val; + break; - case 0x52: - dev->pci_conf[addr] = val & 0x9f; - break; + case 0x52: + dev->pci_conf[addr] = val & 0x9f; + break; - case 0x53: - dev->pci_conf[addr] = val; - break; + case 0x53: + dev->pci_conf[addr] = val; + break; - case 0x54: - dev->pci_conf[addr] = val & 0xb4; - break; - case 0x55: - dev->pci_conf[addr] = val & 0x01; - break; + case 0x54: + dev->pci_conf[addr] = val & 0xb4; + break; + case 0x55: + dev->pci_conf[addr] = val & 0x01; + break; - case 0x56: - dev->pci_conf[addr] = val & 0x3f; - break; + case 0x56: + dev->pci_conf[addr] = val & 0x3f; + break; - case 0x57: - dev->pci_conf[addr] = val & 0x08; - break; + case 0x57: + dev->pci_conf[addr] = val & 0x08; + break; - case 0x58: - dev->pci_conf[addr] = val; - break; + case 0x58: + dev->pci_conf[addr] = val; + break; - case 0x59: - dev->pci_conf[addr] = val; - break; + case 0x59: + dev->pci_conf[addr] = val; + break; - case 0x5a: - dev->pci_conf[addr] = val; - break; + case 0x5a: + dev->pci_conf[addr] = val; + break; - case 0x5c: - dev->pci_conf[addr] = val & 0x01; - break; + case 0x5c: + dev->pci_conf[addr] = val & 0x01; + break; - case 0x60: - dev->pci_conf[addr] = val; - break; + case 0x60: + dev->pci_conf[addr] = val; + break; - case 0x61: - dev->pci_conf[addr] = val; - break; + case 0x61: + dev->pci_conf[addr] = val; + break; - case 0x62: - dev->pci_conf[addr] = val; - break; + case 0x62: + dev->pci_conf[addr] = val; + break; - case 0x63: - dev->pci_conf[addr] = val; - break; + case 0x63: + dev->pci_conf[addr] = val; + break; - case 0x64: - dev->pci_conf[addr] = val & 0xb7; - break; - case 0x65: - dev->pci_conf[addr] = val & 0x01; - break; + case 0x64: + dev->pci_conf[addr] = val & 0xb7; + break; + case 0x65: + dev->pci_conf[addr] = val & 0x01; + break; - case 0x66: - dev->pci_conf[addr] &= ~(val & 0x33); - break; + case 0x66: + dev->pci_conf[addr] &= ~(val & 0x33); + break; - case 0x67: - dev->pci_conf[addr] = val; - break; + case 0x67: + dev->pci_conf[addr] = val; + break; - case 0x68: - dev->pci_conf[addr] = val; - break; + case 0x68: + dev->pci_conf[addr] = val; + break; - case 0x69: - dev->pci_conf[addr] = val; - break; + case 0x69: + dev->pci_conf[addr] = val; + break; - case 0x6c ... 0x7b: - /* Bits 22:20 = DRAM Row size: - - 000: 4 MB; - - 001: 8 MB; - - 010: 16 MB; - - 011: 32 MB; - - 100: 64 MB; - - 101: 128 MB; - - 110: 256 MB; - - 111: Reserved. */ - dev->pci_conf[addr] = val; - spd_write_drbs_ali1621(dev->pci_conf, 0x6c, 0x7b); - break; + case 0x6c ... 0x7b: + /* Bits 22:20 = DRAM Row size: + - 000: 4 MB; + - 001: 8 MB; + - 010: 16 MB; + - 011: 32 MB; + - 100: 64 MB; + - 101: 128 MB; + - 110: 256 MB; + - 111: Reserved. */ + dev->pci_conf[addr] = val; + spd_write_drbs_ali1621(dev->pci_conf, 0x6c, 0x7b); + break; - case 0x7c ... 0x7f: - dev->pci_conf[addr] = val; - break; + case 0x7c ... 0x7f: + dev->pci_conf[addr] = val; + break; - case 0x80: - dev->pci_conf[addr] = val; - break; - case 0x81: - dev->pci_conf[addr] = val & 0xdf; - break; + case 0x80: + dev->pci_conf[addr] = val; + break; + case 0x81: + dev->pci_conf[addr] = val & 0xdf; + break; - case 0x82: - dev->pci_conf[addr] = val & 0xf7; - break; + case 0x82: + dev->pci_conf[addr] = val & 0xf7; + break; - case 0x83: - dev->pci_conf[addr] = val & 0xfc; - ali1621_smram_recalc(val & 0xfc, dev); - break; + case 0x83: + dev->pci_conf[addr] = val & 0xfc; + ali1621_smram_recalc(val & 0xfc, dev); + break; - case 0x84 ... 0x87: - if (addr == 0x87) - dev->pci_conf[addr] = val & 0x3f; - else - dev->pci_conf[addr] = val; - ali1621_shadow_recalc(val, dev); - break; + case 0x84 ... 0x87: + if (addr == 0x87) + dev->pci_conf[addr] = val & 0x3f; + else + dev->pci_conf[addr] = val; + ali1621_shadow_recalc(val, dev); + break; - case 0x88: case 0x89: - dev->pci_conf[addr] = val; - break; - case 0x8a: - dev->pci_conf[addr] = val & 0xc5; - break; - case 0x8b: - dev->pci_conf[addr] = val & 0xbf; - break; + case 0x88: + case 0x89: + dev->pci_conf[addr] = val; + break; + case 0x8a: + dev->pci_conf[addr] = val & 0xc5; + break; + case 0x8b: + dev->pci_conf[addr] = val & 0xbf; + break; - case 0x8c ... 0x8f: - dev->pci_conf[addr] = val; - break; + case 0x8c ... 0x8f: + dev->pci_conf[addr] = val; + break; - case 0x90: - dev->pci_conf[addr] = val; - break; - case 0x91: - dev->pci_conf[addr] = val & 0x07; - break; + case 0x90: + dev->pci_conf[addr] = val; + break; + case 0x91: + dev->pci_conf[addr] = val & 0x07; + break; - case 0x94 ... 0x97: - dev->pci_conf[addr] = val; - break; + case 0x94 ... 0x97: + dev->pci_conf[addr] = val; + break; - case 0x98 ... 0x9b: - dev->pci_conf[addr] = val; - break; + case 0x98 ... 0x9b: + dev->pci_conf[addr] = val; + break; - case 0x9c ... 0x9f: - dev->pci_conf[addr] = val; - break; + case 0x9c ... 0x9f: + dev->pci_conf[addr] = val; + break; - case 0xa0: case 0xa1: - dev->pci_conf[addr] = val; - break; + case 0xa0: + case 0xa1: + dev->pci_conf[addr] = val; + break; - case 0xbc: - dev->pci_conf[addr] = val & 0x0f; - ali1621_mask_bar(dev); - break; - case 0xbd: - dev->pci_conf[addr] = val & 0xf0; - break; - case 0xbe: case 0xbf: - dev->pci_conf[addr] = val; - break; + case 0xbc: + dev->pci_conf[addr] = val & 0x0f; + ali1621_mask_bar(dev); + break; + case 0xbd: + dev->pci_conf[addr] = val & 0xf0; + break; + case 0xbe: + case 0xbf: + dev->pci_conf[addr] = val; + break; - case 0xc0: - dev->pci_conf[addr] = val & 0xb1; - break; + case 0xc0: + dev->pci_conf[addr] = val & 0xb1; + break; - case 0xc4 ... 0xc7: - dev->pci_conf[addr] = val; - break; + case 0xc4 ... 0xc7: + dev->pci_conf[addr] = val; + break; - case 0xc8: - dev->pci_conf[addr] = val & 0x8c; - break; - case 0xc9: - dev->pci_conf[addr] = val; - break; - case 0xca: - dev->pci_conf[addr] = val & 0x7f; - break; - case 0xcb: - dev->pci_conf[addr] = val & 0x87; - break; + case 0xc8: + dev->pci_conf[addr] = val & 0x8c; + break; + case 0xc9: + dev->pci_conf[addr] = val; + break; + case 0xca: + dev->pci_conf[addr] = val & 0x7f; + break; + case 0xcb: + dev->pci_conf[addr] = val & 0x87; + break; - case 0xcc ... 0xcf: - dev->pci_conf[addr] = val; - break; + case 0xcc ... 0xcf: + dev->pci_conf[addr] = val; + break; - case 0xd0: - dev->pci_conf[addr] = val & 0x80; - break; - case 0xd2: - dev->pci_conf[addr] = val & 0x40; - break; - case 0xd3: - dev->pci_conf[addr] = val & 0xb0; - break; + case 0xd0: + dev->pci_conf[addr] = val & 0x80; + break; + case 0xd2: + dev->pci_conf[addr] = val & 0x40; + break; + case 0xd3: + dev->pci_conf[addr] = val & 0xb0; + break; - case 0xd4: - dev->pci_conf[addr] = val; - break; - case 0xd5: - dev->pci_conf[addr] = val & 0xef; - break; - case 0xd6: case 0xd7: - dev->pci_conf[addr] = val; - break; + case 0xd4: + dev->pci_conf[addr] = val; + break; + case 0xd5: + dev->pci_conf[addr] = val & 0xef; + break; + case 0xd6: + case 0xd7: + dev->pci_conf[addr] = val; + break; - case 0xf0 ... 0xff: - dev->pci_conf[addr] = val; - break; + case 0xf0 ... 0xff: + dev->pci_conf[addr] = val; + break; + + default: + break; } } - static uint8_t -ali1621_read(int func, int addr, void *priv) +ali1621_read(UNUSED(int func), int addr, void *priv) { - ali1621_t *dev = (ali1621_t *)priv; - uint8_t ret = 0xff; + const ali1621_t *dev = (ali1621_t *) priv; + uint8_t ret = 0xff; ret = dev->pci_conf[addr]; return ret; } - static void ali1621_reset(void *priv) { - ali1621_t *dev = (ali1621_t *)priv; - int i; + ali1621_t *dev = (ali1621_t *) priv; /* Default Registers */ dev->pci_conf[0x00] = 0xb9; @@ -635,15 +651,14 @@ ali1621_reset(void *priv) ali1621_write(0, 0x83, 0x08, dev); - for (i = 0; i < 4; i++) - ali1621_write(0, 0x84 + i, 0x00, dev); + for (uint8_t i = 0; i < 4; i++) + ali1621_write(0, 0x84 + i, 0x00, dev); } - static void ali1621_close(void *priv) { - ali1621_t *dev = (ali1621_t *)priv; + ali1621_t *dev = (ali1621_t *) priv; smram_del(dev->smram[1]); smram_del(dev->smram[0]); @@ -651,14 +666,13 @@ ali1621_close(void *priv) free(dev); } - static void * -ali1621_init(const device_t *info) +ali1621_init(UNUSED(const device_t *info)) { - ali1621_t *dev = (ali1621_t *)malloc(sizeof(ali1621_t)); + ali1621_t *dev = (ali1621_t *) malloc(sizeof(ali1621_t)); memset(dev, 0, sizeof(ali1621_t)); - pci_add_card(PCI_ADD_NORTHBRIDGE, ali1621_read, ali1621_write, dev); + pci_add_card(PCI_ADD_NORTHBRIDGE, ali1621_read, ali1621_write, dev, &dev->pci_slot); dev->smram[0] = smram_add(); dev->smram[1] = smram_add(); @@ -670,17 +684,16 @@ ali1621_init(const device_t *info) return dev; } - const device_t ali1621_device = { - "ALi M1621 CPU-to-PCI Bridge", - "ali1621", - DEVICE_PCI, - 0, - ali1621_init, - ali1621_close, - ali1621_reset, - {NULL}, - NULL, - NULL, - NULL + .name = "ALi M1621 CPU-to-PCI Bridge", + .internal_name = "ali1621", + .flags = DEVICE_PCI, + .local = 0, + .init = ali1621_init, + .close = ali1621_close, + .reset = ali1621_reset, + { .available = NULL }, + .speed_changed = NULL, + .force_redraw = NULL, + .config = NULL }; diff --git a/src/chipset/ali6117.c b/src/chipset/ali6117.c index 52975671a..c7ada4bc6 100644 --- a/src/chipset/ali6117.c +++ b/src/chipset/ali6117.c @@ -1,18 +1,18 @@ /* - * 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. + * 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. + * This file is part of the 86Box distribution. * - * Implementation of the ALi M6117 SoC. + * Implementation of the ALi M6117 SoC. * * * - * Authors: RichardG, + * Authors: RichardG, * - * Copyright 2020 RichardG. + * Copyright 2020 RichardG. */ #include #include @@ -30,22 +30,58 @@ #include <86box/pit.h> #include <86box/device.h> #include <86box/port_92.h> -#include <86box/usb.h> #include <86box/hdc.h> #include <86box/hdc_ide.h> #include <86box/chipset.h> +#include <86box/plat_fallthrough.h> - -typedef struct ali6117_t -{ - uint32_t local; +typedef struct ali6117_t { + uint32_t local; /* Main registers (port 22h/23h) */ - uint8_t unlocked; - uint8_t reg_offset; - uint8_t regs[256]; + uint8_t unlocked; + uint8_t mode; + uint8_t reg_offset; + uint8_t regs[256]; } ali6117_t; +/* Total size, Bank 0 size, Bank 1 size, Bank 2 size, Bank 3 size. */ +static uint32_t ali6117_modes[32][5] = { +// clang-format off + { 1024, 512, 512, 0, 0 }, + { 2048, 512, 512, 512, 512 }, + { 3072, 512, 512, 2048, 0 }, + { 5120, 512, 512, 2048, 2048 }, + { 9216, 512, 512, 8192, 0 }, + { 1024, 1024, 0, 0, 0 }, + { 2048, 1024, 1024, 0, 0 }, + { 4096, 1024, 1024, 2048, 0 }, + { 6144, 1024, 1024, 2048, 2048 }, + { 10240, 1024, 1024, 8192, 0 }, + { 18432, 1024, 1024, 8192, 8192 }, + { 3072, 1024, 2048, 0, 0 }, + { 5120, 1024, 2048, 2048, 0 }, + { 9216, 1024, 8192, 0, 0 }, + { 2048, 2048, 0, 0, 0 }, + { 4096, 2048, 2048, 0, 0 }, + { 6144, 2048, 2048, 2048, 0 }, + { 8192, 2048, 2048, 2048, 2048 }, + { 12288, 2048, 2048, 8192, 0 }, + { 20480, 2048, 2048, 8192, 8192 }, + { 10240, 2048, 8192, 0, 0 }, + { 18432, 2048, 8192, 8192, 0 }, + { 26624, 2048, 8192, 8192, 8192 }, + { 4096, 4096, 0, 0, 0 }, + { 8192, 4096, 4096, 0, 0 }, + { 24576, 4096, 4096, 8192, 8192 }, + { 12288, 4096, 8192, 0, 0 }, + { 8192, 8192, 0, 0, 0 }, + { 16384, 8192, 8192, 0, 0 }, + { 24576, 8192, 8192, 8192, 0 }, + { 32768, 8192, 8192, 8192, 8192 }, + { 65536, 32768, 32768, 0, 0 } +// clang-format on +}; #ifdef ENABLE_ALI6117_LOG int ali6117_do_log = ENABLE_ALI6117_LOG; @@ -56,62 +92,104 @@ ali6117_log(const char *fmt, ...) va_list ap; if (ali6117_do_log) { - va_start(ap, fmt); - pclog_ex(fmt, ap); - va_end(ap); + va_start(ap, fmt); + pclog_ex(fmt, ap); + va_end(ap); } } #else -#define ali6117_log(fmt, ...) +# define ali6117_log(fmt, ...) #endif - static void ali6117_recalcmapping(ali6117_t *dev) { - uint8_t reg, bitpair; - uint32_t base, size; - int state; + uint32_t base; + uint32_t size; + int state; - shadowbios = 0; + shadowbios = 0; shadowbios_write = 0; ali6117_log("ALI6117: Shadowing for A0000-BFFFF (reg 12 bit 1) = %s\n", (dev->regs[0x12] & 0x02) ? "on" : "off"); mem_set_mem_state(0xa0000, 0x20000, (dev->regs[0x12] & 0x02) ? (MEM_WRITE_INTERNAL | MEM_READ_INTERNAL) : (MEM_WRITE_EXTANY | MEM_READ_EXTANY)); - for (reg = 0; reg <= 1; reg++) { - for (bitpair = 0; bitpair <= 3; bitpair++) { - size = 0x8000; - base = 0xc0000 + (size * ((reg * 4) + bitpair)); - ali6117_log("ALI6117: Shadowing for %05X-%05X (reg %02X bp %d wmask %02X rmask %02X) =", base, base + size - 1, 0x14 + reg, bitpair, 1 << ((bitpair * 2) + 1), 1 << (bitpair * 2)); + for (uint8_t reg = 0; reg <= 1; reg++) { + for (uint8_t bitpair = 0; bitpair <= 3; bitpair++) { + size = 0x8000; + base = 0xc0000 + (size * ((reg * 4) + bitpair)); + ali6117_log("ALI6117: Shadowing for %05X-%05X (reg %02X bp %d wmask %02X rmask %02X) =", base, base + size - 1, 0x14 + reg, bitpair, 1 << ((bitpair * 2) + 1), 1 << (bitpair * 2)); - state = 0; - if (dev->regs[0x14 + reg] & (1 << ((bitpair * 2) + 1))) { - ali6117_log(" w on"); - state |= MEM_WRITE_INTERNAL; - if (base >= 0xe0000) - shadowbios_write |= 1; - } else { - ali6117_log(" w off"); - state |= MEM_WRITE_EXTANY; - } - if (dev->regs[0x14 + reg] & (1 << (bitpair * 2))) { - ali6117_log("; r on\n"); - state |= MEM_READ_INTERNAL; - if (base >= 0xe0000) - shadowbios |= 1; - } else { - ali6117_log("; r off\n"); - state |= MEM_READ_EXTANY; - } + state = 0; + if (dev->regs[0x14 + reg] & (1 << ((bitpair * 2) + 1))) { + ali6117_log(" w on"); + state |= MEM_WRITE_INTERNAL; + if (base >= 0xe0000) + shadowbios_write |= 1; + } else { + ali6117_log(" w off"); + state |= MEM_WRITE_EXTANY; + } + if (dev->regs[0x14 + reg] & (1 << (bitpair * 2))) { + ali6117_log("; r on\n"); + state |= MEM_READ_INTERNAL; + if (base >= 0xe0000) + shadowbios |= 1; + } else { + ali6117_log("; r off\n"); + state |= MEM_READ_EXTANY; + } - mem_set_mem_state(base, size, state); - } + mem_set_mem_state(base, size, state); + } } flushmmucache_nopc(); } +static void +ali6117_bank_recalc(ali6117_t *dev) +{ + uint32_t bank; + uint32_t addr; + + for (uint32_t i = 0x00000000; i < (mem_size << 10); i += 4096) { + if ((i >= 0x000a0000) && (i < 0x00100000)) + continue; + + if (!is6117 && (i >= 0x00f00000) && (i < 0x01000000)) + continue; + + if (is6117 && (i >= 0x03f00000) && (i < 0x04000000)) + continue; + + switch (dev->regs[0x10] & 0xf8) { + case 0xe8: + bank = (i >> 12) & 3; + addr = (i & 0xfff) | ((i >> 14) << 12); + ali6117_log("E8 (%08X): Bank %i, address %08X vs. bank size %08X\n", i, bank, addr, ali6117_modes[dev->mode][bank + 1] * 1024); + if (addr < (ali6117_modes[dev->mode][bank + 1] * 1024)) + mem_set_mem_state_both(i, 4096, MEM_READ_INTERNAL | MEM_WRITE_INTERNAL); + else + mem_set_mem_state_both(i, 4096, MEM_READ_EXTANY | MEM_WRITE_EXTANY); + break; + case 0xf8: + bank = (i >> 12) & 1; + addr = (i & 0xfff) | ((i >> 13) << 12); + ali6117_log("F8 (%08X): Bank %i, address %08X vs. bank size %08X\n", i, bank, addr, ali6117_modes[dev->mode][bank + 1] * 1024); + if (addr < (ali6117_modes[dev->mode][bank + 1] * 1024)) + mem_set_mem_state_both(i, 4096, MEM_READ_INTERNAL | MEM_WRITE_INTERNAL); + else + mem_set_mem_state_both(i, 4096, MEM_READ_EXTANY | MEM_WRITE_EXTANY); + break; + default: + mem_set_mem_state_both(i, 4096, MEM_READ_INTERNAL | MEM_WRITE_INTERNAL); + break; + } + } + + flushmmucache(); +} static void ali6117_reg_write(uint16_t addr, uint8_t val, void *priv) @@ -121,184 +199,208 @@ ali6117_reg_write(uint16_t addr, uint8_t val, void *priv) ali6117_log("ALI6117: reg_write(%04X, %02X)\n", addr, val); if (addr == 0x22) - dev->reg_offset = val; + dev->reg_offset = val; else if (dev->reg_offset == 0x13) - dev->unlocked = (val == 0xc5); + dev->unlocked = (val == 0xc5); else if (dev->unlocked) { - ali6117_log("ALI6117: regs[%02X] = %02X\n", dev->reg_offset, val); + ali6117_log("ALI6117: regs[%02X] = %02X\n", dev->reg_offset, val); - if (!(dev->local & 0x08) || (dev->reg_offset < 0x30)) switch (dev->reg_offset) { - case 0x30: case 0x34: case 0x35: case 0x3e: - case 0x3f: case 0x46: case 0x4c: case 0x6a: - case 0x73: - return; /* read-only registers */ + if (!(dev->local & 0x08) || (dev->reg_offset < 0x30)) + switch (dev->reg_offset) { + case 0x30: + case 0x34: + case 0x35: + case 0x3e: + case 0x3f: + case 0x46: + case 0x4c: + case 0x6a: + case 0x73: + return; /* read-only registers */ - case 0x10: - refresh_at_enable = !(val & 0x02) || !!(dev->regs[0x20] & 0x80); - break; + case 0x10: + refresh_at_enable = !(val & 0x02) || !!(dev->regs[0x20] & 0x80); + dev->regs[dev->reg_offset] = val; - case 0x12: - val &= 0xf7; - /* FALL-THROUGH */ + if (dev->local != 0x8) { + if (val & 0x04) + mem_set_mem_state_both(0x00f00000, 0x00100000, MEM_READ_EXTANY | MEM_WRITE_EXTANY); + else + mem_set_mem_state_both(0x00f00000, 0x00100000, MEM_READ_INTERNAL | MEM_WRITE_INTERNAL); - case 0x14: case 0x15: - dev->regs[dev->reg_offset] = val; - ali6117_recalcmapping(dev); - break; + ali6117_bank_recalc(dev); + } + break; - case 0x1e: - val &= 0x07; + case 0x12: + val &= 0xf7; + fallthrough; - switch (val) { - /* Half PIT clock. */ - case 0x0: - cpu_set_isa_speed(7159091); - break; + case 0x14: + case 0x15: + dev->regs[dev->reg_offset] = val; + ali6117_recalcmapping(dev); + break; - /* Divisors on the input clock PCLK2, which is double the CPU clock. */ - case 0x1: - cpu_set_isa_speed(cpu_busspeed / 1.5); - break; + case 0x1e: + val &= 0x07; - case 0x2: - cpu_set_isa_speed(cpu_busspeed / 2); - break; + switch (val) { + /* Half PIT clock. */ + case 0x0: + cpu_set_isa_speed(7159091); + break; - case 0x3: - cpu_set_isa_speed(cpu_busspeed / 2.5); - break; + /* Divisors on the input clock PCLK2, which is double the CPU clock. */ + case 0x1: + cpu_set_isa_speed(cpu_busspeed / 1.5); + break; - case 0x4: - cpu_set_isa_speed(cpu_busspeed / 3); - break; + case 0x2: + cpu_set_isa_speed(cpu_busspeed / 2); + break; - case 0x5: - cpu_set_isa_speed(cpu_busspeed / 4); - break; + case 0x3: + cpu_set_isa_speed(cpu_busspeed / 2.5); + break; - case 0x6: - cpu_set_isa_speed(cpu_busspeed / 5); - break; + case 0x4: + cpu_set_isa_speed(cpu_busspeed / 3); + break; - case 0x7: - cpu_set_isa_speed(cpu_busspeed / 6); - break; - } - break; + case 0x5: + cpu_set_isa_speed(cpu_busspeed / 4); + break; - case 0x20: - val &= 0xbf; - refresh_at_enable = !(dev->regs[0x10] & 0x02) || !!(val & 0x80); - break; + case 0x6: + cpu_set_isa_speed(cpu_busspeed / 5); + break; - case 0x31: - /* TODO: fast gate A20 (bit 0) */ - val &= 0x21; - break; + case 0x7: + cpu_set_isa_speed(cpu_busspeed / 6); + break; - case 0x32: - val &= 0xc1; - break; + default: + break; + } + break; - case 0x33: - val &= 0xfd; - break; + case 0x20: + val &= 0xbf; + refresh_at_enable = !(dev->regs[0x10] & 0x02) || !!(val & 0x80); + break; - case 0x36: - val &= 0xf0; - val |= dev->regs[dev->reg_offset]; - break; + case 0x31: + /* TODO: fast gate A20 (bit 0) */ + val &= 0x21; + break; - case 0x37: - val &= 0xf5; - break; + case 0x32: + val &= 0xc1; + break; - case 0x3c: - val &= 0x8f; - ide_pri_disable(); - ide_set_base(1, (val & 0x01) ? 0x170 : 0x1f0); - ide_set_side(1, (val & 0x01) ? 0x376 : 0x3f6); - ide_pri_enable(); - break; + case 0x33: + val &= 0xfd; + break; - case 0x44: case 0x45: - val &= 0x3f; - break; + case 0x36: + val &= 0xf0; + val |= dev->regs[dev->reg_offset]; + break; - case 0x4a: - val &= 0xfe; - break; + case 0x37: + val &= 0xf5; + break; - case 0x55: - val &= 0x03; - break; + case 0x3c: + val &= 0x8f; + ide_pri_disable(); + ide_set_base(1, (val & 0x01) ? 0x170 : 0x1f0); + ide_set_side(1, (val & 0x01) ? 0x376 : 0x3f6); + ide_pri_enable(); + break; - case 0x56: - val &= 0xc7; - break; + case 0x44: + case 0x45: + val &= 0x3f; + break; - case 0x58: - val &= 0xc3; - break; + case 0x4a: + val &= 0xfe; + break; - case 0x59: - val &= 0x60; - break; + case 0x55: + val &= 0x03; + break; - case 0x5b: - val &= 0x1f; - break; + case 0x56: + val &= 0xc7; + break; - case 0x64: - val &= 0xf7; - break; + case 0x58: + val &= 0xc3; + break; - case 0x66: - val &= 0xe3; - break; + case 0x59: + val &= 0x60; + break; - case 0x67: - val &= 0xdf; - break; + case 0x5b: + val &= 0x1f; + break; - case 0x69: - val &= 0x50; - break; + case 0x64: + val &= 0xf7; + break; - case 0x6b: - val &= 0x7f; - break; + case 0x66: + val &= 0xe3; + break; - case 0x6e: case 0x6f: - val &= 0x03; - break; + case 0x67: + val &= 0xdf; + break; - case 0x71: - val &= 0x1f; - break; - } + case 0x69: + val &= 0x50; + break; - dev->regs[dev->reg_offset] = val; + case 0x6b: + val &= 0x7f; + break; + + case 0x6e: + case 0x6f: + val &= 0x03; + break; + + case 0x71: + val &= 0x1f; + break; + + default: + break; + } + + dev->regs[dev->reg_offset] = val; } } - static uint8_t ali6117_reg_read(uint16_t addr, void *priv) { - ali6117_t *dev = (ali6117_t *) priv; - uint8_t ret; + const ali6117_t *dev = (ali6117_t *) priv; + uint8_t ret; if (addr == 0x22) - ret = dev->reg_offset; + ret = dev->reg_offset; else - ret = dev->regs[dev->reg_offset]; + ret = dev->regs[dev->reg_offset]; ali6117_log("ALI6117: reg_read(%04X) = %02X\n", dev->reg_offset, ret); return ret; } - static void ali6117_reset(void *priv) { @@ -316,18 +418,23 @@ ali6117_reset(void *priv) dev->regs[0x1d] = 0xff; dev->regs[0x20] = 0x80; if (dev->local & 0x08) { - dev->regs[0x30] = 0x08; - dev->regs[0x31] = 0x01; - dev->regs[0x34] = 0x04; /* enable internal RTC */ - dev->regs[0x35] = 0x20; /* enable internal KBC */ - dev->regs[0x36] = dev->local & 0x07; /* M6117D ID */ + dev->regs[0x30] = 0x08; + dev->regs[0x31] = 0x01; + dev->regs[0x34] = 0x04; /* enable internal RTC */ + dev->regs[0x35] = 0x20; /* enable internal KBC */ + dev->regs[0x36] = dev->local & 0x07; /* M6117D ID */ } cpu_set_isa_speed(7159091); refresh_at_enable = 1; -} + if (dev->local != 0x8) { + /* On-board memory 15-16M is enabled by default. */ + mem_set_mem_state_both(0x00f00000, 0x00100000, MEM_READ_INTERNAL | MEM_WRITE_INTERNAL); + ali6117_bank_recalc(dev); + } +} static void ali6117_setup(ali6117_t *dev) @@ -336,10 +443,9 @@ ali6117_setup(ali6117_t *dev) /* Main register interface */ io_sethandler(0x22, 2, - ali6117_reg_read, NULL, NULL, ali6117_reg_write, NULL, NULL, dev); + ali6117_reg_read, NULL, NULL, ali6117_reg_write, NULL, NULL, dev); } - static void ali6117_close(void *priv) { @@ -348,61 +454,66 @@ ali6117_close(void *priv) ali6117_log("ALI6117: close()\n"); io_removehandler(0x22, 2, - ali6117_reg_read, NULL, NULL, ali6117_reg_write, NULL, NULL, dev); + ali6117_reg_read, NULL, NULL, ali6117_reg_write, NULL, NULL, dev); free(dev); } - static void * ali6117_init(const device_t *info) { + int last_match = 0; + ali6117_log("ALI6117: init()\n"); ali6117_t *dev = (ali6117_t *) malloc(sizeof(ali6117_t)); memset(dev, 0, sizeof(ali6117_t)); - + dev->local = info->local; device_add(&ide_isa_device); ali6117_setup(dev); + + for (int8_t i = 31; i >= 0; i--) { + if ((mem_size >= ali6117_modes[i][0]) && (ali6117_modes[i][0] > last_match)) { + last_match = ali6117_modes[i][0]; + dev->mode = i; + } + } + ali6117_reset(dev); if (!(dev->local & 0x08)) - pic_elcr_io_handler(0); + pic_elcr_io_handler(0); return dev; } - -const device_t ali1217_device = -{ - "ALi M1217", - "ali1217", - DEVICE_AT, - 0x8, - ali6117_init, - ali6117_close, - ali6117_reset, - { NULL }, - NULL, - NULL, - NULL +const device_t ali1217_device = { + .name = "ALi M1217", + .internal_name = "ali1217", + .flags = DEVICE_AT, + .local = 0x8, + .init = ali6117_init, + .close = ali6117_close, + .reset = ali6117_reset, + { .available = NULL }, + .speed_changed = NULL, + .force_redraw = NULL, + .config = NULL }; - -const device_t ali6117d_device = -{ - "ALi M6117D", - "ali6117d", - DEVICE_AT, - 0x2, - ali6117_init, - ali6117_close, - ali6117_reset, - { NULL }, - NULL, - NULL, - NULL +const device_t ali6117d_device = { + .name = "ALi M6117D", + .internal_name = "ali6117d", + .flags = DEVICE_AT, + .local = 0x2, + .init = ali6117_init, + .close = ali6117_close, + .reset = ali6117_reset, + { .available = NULL }, + .speed_changed = NULL, + .force_redraw = NULL, + .config = NULL }; diff --git a/src/chipset/compaq_386.c b/src/chipset/compaq_386.c new file mode 100644 index 000000000..7d55bc5a5 --- /dev/null +++ b/src/chipset/compaq_386.c @@ -0,0 +1,761 @@ +/* + * 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 Compaq 386 memory controller. + * + * Authors: Miran Grca, + * + * Copyright 2023 Miran Grca. + */ +#include +#include +#include +#include +#include +#include +#include <86box/86box.h> +#include "cpu.h" +#include <86box/io.h> +#include <86box/timer.h> +#include <86box/pit.h> +#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> +#include <86box/hdc.h> +#include <86box/hdc_ide.h> +#include <86box/machine.h> +#include <86box/video.h> +#include <86box/vid_cga.h> +#include <86box/vid_cga_comp.h> +#include <86box/plat_unused.h> + +#define RAM_DIAG_L_BASE_MEM_640KB 0x00 +#define RAM_DIAG_L_BASE_MEM_INV 0x10 +#define RAM_DIAG_L_BASE_MEM_512KB 0x20 +#define RAM_DIAG_L_BASE_MEM_256KB 0x30 +#define RAM_DIAG_L_BASE_MEM_MASK 0x30 +#define RAM_DIAG_L_PERMA_BITS 0x80 + +#define RAM_DIAG_H_SYS_RAM_4MB 0x01 +#define RAM_DIAG_H_SYS_RAM_1MB 0x02 +#define RAM_DIAG_H_SYS_RAM_NONE 0x03 +#define RAM_DIAG_H_SYS_RAM_MASK 0x03 +#define RAM_DIAG_H_MOD_A_RAM_4MB 0x04 +#define RAM_DIAG_H_MOD_A_RAM_1MB 0x08 +#define RAM_DIAG_H_MOD_A_RAM_NONE 0x0c +#define RAM_DIAG_H_MOD_A_RAM_MASK 0x0c +#define RAM_DIAG_H_MOD_B_RAM_4MB 0x10 +#define RAM_DIAG_H_MOD_B_RAM_1MB 0x20 +#define RAM_DIAG_H_MOD_B_RAM_NONE 0x30 +#define RAM_DIAG_H_MOD_B_RAM_MASK 0x30 +#define RAM_DIAG_H_MOD_C_RAM_4MB 0x40 +#define RAM_DIAG_H_MOD_C_RAM_1MB 0x80 +#define RAM_DIAG_H_MOD_C_RAM_NONE 0xc0 +#define RAM_DIAG_H_MOD_C_RAM_MASK 0xc0 + +#define MEM_STATE_BUS 0x00 +#define MEM_STATE_SYS 0x01 +#define MEM_STATE_SYS_RELOC 0x02 +#define MEM_STATE_MOD_A 0x04 +#define MEM_STATE_MOD_B 0x08 +#define MEM_STATE_MOD_C 0x10 +#define MEM_STATE_MASK (MEM_STATE_SYS | MEM_STATE_MOD_A | MEM_STATE_MOD_B | MEM_STATE_MOD_C) +#define MEM_STATE_WP 0x20 + +typedef struct cpq_ram_t { + uint8_t wp; + + uint32_t phys_base; + uint32_t virt_base; + + mem_mapping_t mapping; +} cpq_ram_t; + +typedef struct cpq_386_t { + uint8_t regs[8]; + + uint8_t old_state[256]; + uint8_t mem_state[256]; + + uint32_t ram_bases[4]; + + uint32_t ram_sizes[4]; + uint32_t ram_map_sizes[4]; + + cpq_ram_t ram[4][64]; + cpq_ram_t high_ram[16]; + + mem_mapping_t regs_mapping; +} cpq_386_t; + +static uint8_t +cpq_read_ram(uint32_t addr, void *priv) +{ + const cpq_ram_t *dev = (cpq_ram_t *) priv; + uint8_t ret = 0xff; + + addr = (addr - dev->virt_base) + dev->phys_base; + + if (addr < (mem_size << 10)) + ret = mem_read_ram(addr, priv); + + return ret; +} + +static uint16_t +cpq_read_ramw(uint32_t addr, void *priv) +{ + const cpq_ram_t *dev = (cpq_ram_t *) priv; + uint16_t ret = 0xffff; + + addr = (addr - dev->virt_base) + dev->phys_base; + + if (addr < (mem_size << 10)) + ret = mem_read_ramw(addr, priv); + + return ret; +} + +static uint32_t +cpq_read_raml(uint32_t addr, void *priv) +{ + const cpq_ram_t *dev = (cpq_ram_t *) priv; + uint32_t ret = 0xffffffff; + + addr = (addr - dev->virt_base) + dev->phys_base; + + if (addr < (mem_size << 10)) + ret = mem_read_raml(addr, priv); + + return ret; +} + +static void +cpq_write_ram(uint32_t addr, uint8_t val, void *priv) +{ + const cpq_ram_t *dev = (cpq_ram_t *) priv; + + addr = (addr - dev->virt_base) + dev->phys_base; + + if (!dev->wp && (addr < (mem_size << 10))) + mem_write_ram(addr, val, priv); +} + +static void +cpq_write_ramw(uint32_t addr, uint16_t val, void *priv) +{ + const cpq_ram_t *dev = (cpq_ram_t *) priv; + + addr = (addr - dev->virt_base) + dev->phys_base; + + if (!dev->wp && (addr < (mem_size << 10))) + mem_write_ramw(addr, val, priv); +} + +static void +cpq_write_raml(uint32_t addr, uint32_t val, void *priv) +{ + const cpq_ram_t *dev = (cpq_ram_t *) priv; + + addr = (addr - dev->virt_base) + dev->phys_base; + + if (!dev->wp && (addr < (mem_size << 10))) + mem_write_raml(addr, val, priv); +} + +static uint8_t +cpq_read_regs(uint32_t addr, void *priv) +{ + const cpq_386_t *dev = (cpq_386_t *) priv; + uint8_t ret = 0xff; + + addr &= 0x00000fff; + + switch (addr) { + case 0x00000000: + case 0x00000001: + /* RAM Diagnostics (Read Only) */ + case 0x00000002: + case 0x00000003: + /* RAM Setup Port (Read/Write) */ + ret = dev->regs[addr]; + break; + + default: + break; + } + + return ret; +} + +static uint16_t +cpq_read_regsw(uint32_t addr, void *priv) +{ + uint16_t ret = 0xffff; + + ret = cpq_read_regs(addr, priv); + ret |= (((uint16_t) cpq_read_regs(addr + 1, priv)) << 8); + + return ret; +} + +static uint32_t +cpq_read_regsl(uint32_t addr, void *priv) +{ + uint32_t ret = 0xffffffff; + + ret = cpq_read_regsw(addr, priv); + ret |= (((uint32_t) cpq_read_regsw(addr + 2, priv)) << 16); + + return ret; +} + +static void +cpq_recalc_state(cpq_386_t *dev, uint8_t i) +{ + uint32_t addr; + + addr = ((uint32_t) i) << 16; + if (dev->mem_state[i] == 0x00) + mem_set_mem_state(addr, 0x00010000, MEM_READ_EXTANY | MEM_WRITE_EXTANY); + else if (dev->mem_state[i] == MEM_STATE_WP) + mem_set_mem_state(addr, 0x00010000, MEM_READ_EXTANY | MEM_WRITE_DISABLED); + else if (dev->mem_state[i] & MEM_STATE_WP) + mem_set_mem_state(addr, 0x00010000, MEM_READ_INTERNAL | MEM_WRITE_DISABLED); + else + mem_set_mem_state(addr, 0x00010000, MEM_READ_INTERNAL | MEM_WRITE_INTERNAL); + + dev->old_state[i] = dev->mem_state[i]; +} + +static void +cpq_recalc_states(cpq_386_t *dev) +{ + /* Recalculate the entire 16 MB space. */ + for (uint16_t i = 0; i < 256; i++) { + if (dev->mem_state[i] != dev->old_state[i]) + cpq_recalc_state(dev, i); + } + + flushmmucache_nopc(); +} + +static void +cpq_recalc_cache(cpq_386_t *dev) +{ + cpu_cache_ext_enabled = (dev->regs[0x00000002] & 0x40); + cpu_update_waitstates(); +} + +static void +cpq_recalc_ram(cpq_386_t *dev) +{ + uint8_t sys_ram = (dev->regs[0x00000001] & RAM_DIAG_H_SYS_RAM_MASK) & 0x01; + uint8_t setup_port = dev->regs[0x00000002] & 0x0f; + uint8_t sys_min_high = sys_ram ? 0xfa : 0xf4; + uint8_t ram_states[4] = { MEM_STATE_SYS, MEM_STATE_MOD_A, + MEM_STATE_MOD_B, MEM_STATE_MOD_C }; + uint8_t ram_bases[4][2][16] = { { { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, + { 0x10, 0x00, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, + 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10 } }, + { { 0x00, 0x00, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, + 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x00, 0x00 }, + { 0x40, 0x00, 0x00, 0x00, 0x00, 0x40, 0x40, 0x40, + 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40 } }, + { { 0x00, 0x00, 0x00, 0x20, 0x20, 0x00, 0x20, 0x20, + 0x50, 0x50, 0x50, 0x50, 0x50, 0x50, 0x00, 0x00 }, + { 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x50, 0x50, + 0x00, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80 } }, + { { 0x00, 0x00, 0x00, 0x00, 0x30, 0x00, 0x00, 0x60, + 0x00, 0x00, 0x90, 0x90, 0x90, 0x90, 0x00, 0x00 }, + { 0xc0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x60, + 0x00, 0x00, 0x90, 0x00, 0x00, 0xc0, 0xc0, 0xc0 } } }; + uint8_t ram_sizes[4][2][16] = { { { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, + { 0x30, 0x00, 0x10, 0x20, 0x30, 0x30, 0x30, 0x30, + 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30 } }, + { { 0x00, 0x00, 0x10, 0x10, 0x10, 0x40, 0x10, 0x10, + 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x00, 0x00 }, + { 0x40, 0x00, 0x00, 0x00, 0x00, 0x10, 0x10, 0x10, + 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40 } }, + { { 0x00, 0x00, 0x00, 0x10, 0x10, 0x00, 0x40, 0x40, + 0x30, 0x40, 0x40, 0x40, 0x40, 0x40, 0x00, 0x00 }, + { 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x10, + 0x00, 0x10, 0x10, 0x30, 0x40, 0x40, 0x40, 0x40 } }, + { { 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x10, + 0x00, 0x00, 0x10, 0x20, 0x30, 0x40, 0x00, 0x00 }, + { 0x3a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, + 0x00, 0x00, 0x10, 0x00, 0x00, 0x10, 0x20, 0x30 } } }; + uint8_t size; + uint8_t start; + uint8_t end; + uint8_t k; + uint32_t virt_base; + cpq_ram_t *cram; + + for (uint16_t i = 0x10; i < sys_min_high; i++) + dev->mem_state[i] &= ~MEM_STATE_MASK; + + for (uint8_t i = 0; i < 4; i++) { + for (uint8_t j = 0; j <= 64; j++) { + if ((i >= 1) || (j >= 0x10)) + mem_mapping_disable(&dev->ram[i][j].mapping); + } + } + + for (uint8_t i = 0; i < 4; i++) { + size = ram_sizes[i][sys_ram][setup_port]; + if (size > 0x00) { + start = ram_bases[i][sys_ram][setup_port]; + end = start + (size - 1); + + virt_base = ((uint32_t) start) << 16; + + for (uint16_t j = start; j <= end; j++) { + k = j - start; + if (i == 0) + k += 0x10; + + cram = &(dev->ram[i][k]); + + dev->mem_state[j] |= ram_states[i]; + + cram->virt_base = ((uint32_t) j) << 16; + cram->phys_base = cram->virt_base - virt_base + dev->ram_bases[i]; + + mem_mapping_set_addr(&cram->mapping, cram->virt_base, 0x00010000); + mem_mapping_set_exec(&cram->mapping, &(ram[cram->phys_base])); + } + } + } + + /* Recalculate the entire 16 MB space. */ + cpq_recalc_states(dev); +} + +static void +cpq_write_regs(uint32_t addr, uint8_t val, void *priv) +{ + cpq_386_t *dev = (cpq_386_t *) priv; + + addr &= 0x00000fff; + + switch (addr) { + case 0x00000000: + case 0x00000001: + /* RAM Relocation (Write Only) */ + dev->regs[addr + 4] = val; + if (addr == 0x00000000) { + dev->mem_state[0x0e] &= ~(MEM_STATE_SYS | MEM_STATE_WP); + dev->mem_state[0x0f] &= ~(MEM_STATE_SYS | MEM_STATE_WP); + dev->mem_state[0xfe] &= ~MEM_STATE_WP; + dev->mem_state[0xff] &= ~MEM_STATE_WP; + if (!(val & 0x01)) { + dev->mem_state[0x0e] |= MEM_STATE_SYS; + dev->mem_state[0x0f] |= MEM_STATE_SYS; + } + if (!(val & 0x02)) { + dev->mem_state[0x0e] |= MEM_STATE_WP; + dev->mem_state[0x0f] |= MEM_STATE_WP; + dev->mem_state[0xfe] |= MEM_STATE_WP; + dev->mem_state[0xff] |= MEM_STATE_WP; + } + cpq_recalc_state(dev, 0x0e); + cpq_recalc_state(dev, 0x0f); + cpq_recalc_state(dev, 0xfe); + cpq_recalc_state(dev, 0xff); + flushmmucache_nopc(); + } + break; + case 0x00000002: + case 0x00000003: + /* RAM Setup Port (Read/Write) */ + dev->regs[addr] = val; + if (addr == 0x00000002) { + cpq_recalc_ram(dev); + cpq_recalc_cache(dev); + } + break; + + default: + break; + } +} + +static void +cpq_write_regsw(uint32_t addr, uint16_t val, void *priv) +{ + cpq_write_regs(addr, val & 0xff, priv); + cpq_write_regs(addr + 1, (val >> 8) & 0xff, priv); +} + +static void +cpq_write_regsl(uint32_t addr, uint32_t val, void *priv) +{ + cpq_write_regsw(addr, val & 0xff, priv); + cpq_write_regsw(addr + 2, (val >> 16) & 0xff, priv); +} + +static void +compaq_ram_init(cpq_ram_t *dev) +{ + mem_mapping_add(&dev->mapping, + 0x00000000, + 0x00010000, + cpq_read_ram, + cpq_read_ramw, + cpq_read_raml, + cpq_write_ram, + cpq_write_ramw, + cpq_write_raml, + NULL, + MEM_MAPPING_INTERNAL, + dev); + + mem_mapping_disable(&dev->mapping); +} + +static void +compaq_ram_diags_parse(cpq_386_t *dev) +{ + uint8_t val = dev->regs[0x00000001]; + uint32_t accum = 0x00100000; + + for (uint8_t i = 0; i < 4; i++) { + dev->ram_bases[i] = accum; + + switch (val & 0x03) { + case RAM_DIAG_H_SYS_RAM_1MB: + dev->ram_sizes[i] = 0x00100000; + break; + case RAM_DIAG_H_SYS_RAM_4MB: + dev->ram_sizes[i] = 0x00400000; + break; + + default: + break; + } + if (i == 0) + dev->ram_sizes[i] -= 0x00100000; + + dev->ram_map_sizes[i] = dev->ram_sizes[i]; + accum += dev->ram_sizes[i]; + + if (accum >= (mem_size << 10)) { + dev->ram_sizes[i] = (mem_size << 10) - dev->ram_bases[i]; + break; + } + + val >>= 2; + } +} + +static void +compaq_recalc_base_ram(cpq_386_t *dev) +{ + uint8_t base_mem = dev->regs[0x00000000] & RAM_DIAG_L_BASE_MEM_MASK; + uint8_t sys_ram = dev->regs[0x00000001] & RAM_DIAG_H_SYS_RAM_MASK; + uint8_t low_start = 0x00; + uint8_t low_end = 0x00; + uint8_t high_start = 0x00; + uint8_t high_end = 0x00; + cpq_ram_t *cram; + + switch (base_mem) { + case RAM_DIAG_L_BASE_MEM_256KB: + switch (sys_ram) { + case RAM_DIAG_H_SYS_RAM_1MB: + low_start = 0x00; + low_end = 0x03; + high_start = 0xf4; + high_end = 0xff; + break; + case RAM_DIAG_H_SYS_RAM_4MB: + low_start = 0x00; + low_end = 0x03; + high_start = 0xfa; + high_end = 0xff; + break; + default: + fatal("Compaq 386 - Invalid configuation: %02X %02X\n", base_mem, sys_ram); + return; + } + break; + case RAM_DIAG_L_BASE_MEM_512KB: + switch (sys_ram) { + case RAM_DIAG_H_SYS_RAM_1MB: + low_start = 0x00; + low_end = 0x07; + high_start = 0xf8; + high_end = 0xff; + break; + case RAM_DIAG_H_SYS_RAM_4MB: + low_start = 0x00; + low_end = 0x07; + high_start = 0xfa; + high_end = 0xff; + break; + default: + fatal("Compaq 386 - Invalid configuation: %02X %02X\n", base_mem, sys_ram); + return; + } + break; + case RAM_DIAG_L_BASE_MEM_640KB: + switch (sys_ram) { + case RAM_DIAG_H_SYS_RAM_1MB: + low_start = 0x00; + low_end = 0x09; + high_start = 0xfa; + high_end = 0xff; + break; + case RAM_DIAG_H_SYS_RAM_4MB: + low_start = 0x00; + low_end = 0x09; + high_start = 0xfa; + high_end = 0xff; + break; + default: + fatal("Compaq 386 - Invalid configuation: %02X %02X\n", base_mem, sys_ram); + return; + } + break; + default: + fatal("Compaq 386 - Invalid configuation: %02X %02X\n", base_mem, sys_ram); + return; + } + + switch (sys_ram) { + case RAM_DIAG_H_SYS_RAM_1MB: + if (mem_size < 1024) + dev->regs[0x00000002] = 0x01; + else if (mem_size == 8192) + dev->regs[0x00000002] = 0x09; + else if (mem_size >= 11264) + dev->regs[0x00000002] = 0x0d; + else + dev->regs[0x00000002] = (mem_size >> 10); + break; + case RAM_DIAG_H_SYS_RAM_4MB: + if (mem_size < 4096) + dev->regs[0x00000002] = 0x04; + else if (mem_size == 11264) + dev->regs[0x00000002] = 0x0c; + else if (mem_size >= 16384) + dev->regs[0x00000002] = 0x00; + else if (mem_size > 13312) + dev->regs[0x00000002] = 0x0d; + else + dev->regs[0x00000002] = (mem_size >> 10); + break; + default: + fatal("Compaq 386 - Invalid configuation: %02X\n", sys_ram); + return; + } + + /* The base 640 kB. */ + for (uint8_t i = low_start; i <= low_end; i++) { + cram = &(dev->ram[0][i]); + + cram->phys_base = cram->virt_base = ((uint32_t) i) << 16; + dev->mem_state[i] |= MEM_STATE_SYS; + + mem_mapping_set_addr(&cram->mapping, cram->virt_base, 0x00010000); + mem_mapping_set_exec(&cram->mapping, &(ram[cram->phys_base])); + + cpq_recalc_state(dev, i); + } + + /* The relocated 128 kB. */ + for (uint8_t i = 0x0e; i <= 0x0f; i++) { + cram = &(dev->ram[0][i]); + + cram->phys_base = cram->virt_base = ((uint32_t) i) << 16; + + mem_mapping_set_addr(&cram->mapping, cram->virt_base, 0x00010000); + mem_mapping_set_exec(&cram->mapping, &(ram[cram->phys_base])); + } + + /* Blocks FA-FF. */ + for (uint16_t i = high_start; i <= high_end; i++) { + cram = &(dev->high_ram[i & 0x0f]); + + cram->phys_base = ((uint32_t) (i & 0x0f)) << 16; + cram->virt_base = ((uint32_t) i) << 16; + dev->mem_state[i] |= MEM_STATE_SYS; + + mem_mapping_set_addr(&cram->mapping, cram->virt_base, 0x00010000); + mem_mapping_set_exec(&cram->mapping, &(ram[cram->phys_base])); + + cpq_recalc_state(dev, i); + } +} + +static void +compaq_386_close(void *priv) +{ + cpq_386_t *dev = (cpq_386_t *) priv; + + free(dev); +} + +static void * +compaq_386_init(UNUSED(const device_t *info)) +{ + cpq_386_t *dev = (cpq_386_t *) calloc(1, sizeof(cpq_386_t)); + + mem_mapping_add(&dev->regs_mapping, + 0x80c00000, + 0x00001000, + cpq_read_regs, + cpq_read_regsw, + cpq_read_regsl, + cpq_write_regs, + cpq_write_regsw, + cpq_write_regsl, + NULL, + MEM_MAPPING_INTERNAL, + dev); + + mem_set_mem_state(0x80c00000, 0x00001000, MEM_READ_INTERNAL | MEM_WRITE_INTERNAL); + + dev->regs[0x00000000] = RAM_DIAG_L_PERMA_BITS; + if (mem_size >= 640) + dev->regs[0x00000000] |= RAM_DIAG_L_BASE_MEM_640KB; + else if (mem_size >= 512) + dev->regs[0x00000000] |= RAM_DIAG_L_BASE_MEM_512KB; + else if (mem_size >= 256) + dev->regs[0x00000000] |= RAM_DIAG_L_BASE_MEM_256KB; + else + dev->regs[0x00000000] |= RAM_DIAG_L_BASE_MEM_INV; + /* Indicate no parity error. */ + dev->regs[0x00000000] |= 0x0f; + + if (mem_size >= 1024) { + switch (mem_size) { + case 1024: + dev->regs[0x00000001] = RAM_DIAG_H_SYS_RAM_4MB | RAM_DIAG_H_MOD_A_RAM_NONE | + RAM_DIAG_H_MOD_B_RAM_NONE | RAM_DIAG_H_MOD_C_RAM_NONE; + break; + case 2048: + dev->regs[0x00000001] = RAM_DIAG_H_SYS_RAM_4MB | RAM_DIAG_H_MOD_A_RAM_NONE | + RAM_DIAG_H_MOD_B_RAM_NONE | RAM_DIAG_H_MOD_C_RAM_NONE; + break; + case 3072: + dev->regs[0x00000001] = RAM_DIAG_H_SYS_RAM_4MB | RAM_DIAG_H_MOD_A_RAM_NONE | + RAM_DIAG_H_MOD_B_RAM_NONE | RAM_DIAG_H_MOD_C_RAM_NONE; + break; + case 4096: + dev->regs[0x00000001] = RAM_DIAG_H_SYS_RAM_4MB | RAM_DIAG_H_MOD_A_RAM_NONE | + RAM_DIAG_H_MOD_B_RAM_NONE | RAM_DIAG_H_MOD_C_RAM_NONE; + break; + case 5120: + dev->regs[0x00000001] = RAM_DIAG_H_SYS_RAM_4MB | RAM_DIAG_H_MOD_A_RAM_1MB | + RAM_DIAG_H_MOD_B_RAM_NONE | RAM_DIAG_H_MOD_C_RAM_NONE; + break; + case 6144: + dev->regs[0x00000001] = RAM_DIAG_H_SYS_RAM_4MB | RAM_DIAG_H_MOD_A_RAM_1MB | + RAM_DIAG_H_MOD_B_RAM_1MB | RAM_DIAG_H_MOD_C_RAM_NONE; + break; + case 7168: + dev->regs[0x00000001] = RAM_DIAG_H_SYS_RAM_4MB | RAM_DIAG_H_MOD_A_RAM_1MB | + RAM_DIAG_H_MOD_B_RAM_1MB | RAM_DIAG_H_MOD_C_RAM_1MB; + break; + case 8192: + dev->regs[0x00000001] = RAM_DIAG_H_SYS_RAM_4MB | RAM_DIAG_H_MOD_A_RAM_4MB | + RAM_DIAG_H_MOD_B_RAM_NONE | RAM_DIAG_H_MOD_C_RAM_NONE; + break; + case 9216: + dev->regs[0x00000001] = RAM_DIAG_H_SYS_RAM_4MB | RAM_DIAG_H_MOD_A_RAM_4MB | + RAM_DIAG_H_MOD_B_RAM_1MB | RAM_DIAG_H_MOD_C_RAM_NONE; + break; + case 10240: + dev->regs[0x00000001] = RAM_DIAG_H_SYS_RAM_4MB | RAM_DIAG_H_MOD_A_RAM_4MB | + RAM_DIAG_H_MOD_B_RAM_1MB | RAM_DIAG_H_MOD_C_RAM_1MB; + break; + case 11264: + case 12288: + dev->regs[0x00000001] = RAM_DIAG_H_SYS_RAM_4MB | RAM_DIAG_H_MOD_A_RAM_4MB | + RAM_DIAG_H_MOD_B_RAM_4MB | RAM_DIAG_H_MOD_C_RAM_NONE; + break; + case 13312: + dev->regs[0x00000001] = RAM_DIAG_H_SYS_RAM_4MB | RAM_DIAG_H_MOD_A_RAM_4MB | + RAM_DIAG_H_MOD_B_RAM_4MB | RAM_DIAG_H_MOD_C_RAM_1MB; + break; + case 14336: + case 15360: + case 16384: + dev->regs[0x00000001] = RAM_DIAG_H_SYS_RAM_4MB | RAM_DIAG_H_MOD_A_RAM_4MB | + RAM_DIAG_H_MOD_B_RAM_4MB | RAM_DIAG_H_MOD_C_RAM_4MB; + break; + + default: + break; + } + } else + dev->regs[0x00000001] = RAM_DIAG_H_SYS_RAM_1MB | RAM_DIAG_H_MOD_A_RAM_NONE | + RAM_DIAG_H_MOD_B_RAM_NONE | RAM_DIAG_H_MOD_C_RAM_NONE; + + dev->regs[0x00000003] = 0xfc; + dev->regs[0x00000004] = dev->regs[0x00000005] = 0xff; + + compaq_ram_diags_parse(dev); + + mem_mapping_disable(&ram_low_mapping); + mem_mapping_disable(&ram_mid_mapping); + mem_mapping_disable(&ram_high_mapping); +#if (!(defined __amd64__ || defined _M_X64 || defined __aarch64__ || defined _M_ARM64)) + /* Should never be the case, but you never know what a user may set. */ + if (mem_size > 1048576) + mem_mapping_disable(&ram_2gb_mapping); +#endif + + /* Initialize in reverse order for memory mapping precedence + reasons. */ + for (int8_t i = 3; i >= 0; i--) { + for (uint8_t j = 0; j < 64; j++) + compaq_ram_init(&(dev->ram[i][j])); + } + + for (uint8_t i = 0; i < 16; i++) + compaq_ram_init(&(dev->high_ram[i])); + + /* First, set the entire 256 MB of space to invalid states. */ + for (uint16_t i = 0; i < 256; i++) + dev->old_state[i] = 0xff; + + /* Then, recalculate the base RAM mappings. */ + compaq_recalc_base_ram(dev); + + /* Enable the external cache. */ + dev->regs[0x00000002] |= 0x40; + cpq_recalc_cache(dev); + + /* Recalculate the rest of the RAM mapping. */ + cpq_recalc_ram(dev); + + return dev; +} + +const device_t compaq_386_device = { + .name = "Compaq 386 Memory Control", + .internal_name = "compaq_386", + .flags = 0, + .local = 0, + .init = compaq_386_init, + .close = compaq_386_close, + .reset = NULL, + { .available = NULL }, + .speed_changed = NULL, + .force_redraw = NULL, + .config = NULL +}; diff --git a/src/chipset/contaq_82c59x.c b/src/chipset/contaq_82c59x.c index 0abab7f02..ec7050b1e 100644 --- a/src/chipset/contaq_82c59x.c +++ b/src/chipset/contaq_82c59x.c @@ -1,18 +1,19 @@ /* - * 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. + * 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. + * This file is part of the 86Box distribution. * - * Implementation of the Contaq/Cypress 82C596(A) and 597 chipsets. + * Implementation of the Contaq/Cypress 82C596(A) and 597 chipsets. * - * Authors: Miran Grca, * - * Copyright 2021 Miran Grca. + * + * Authors: Miran Grca, + * + * Copyright 2021 Miran Grca. */ - #include #include #include @@ -29,7 +30,6 @@ #include <86box/smram.h> #include <86box/chipset.h> - #ifdef ENABLE_CONTAQ_82C59X_LOG int contaq_82c59x_do_log = ENABLE_CONTAQ_82C59X_LOG; @@ -38,274 +38,278 @@ contaq_82c59x_log(const char *fmt, ...) { va_list ap; - if (contaq_82c59x_do_log) - { + if (contaq_82c59x_do_log) { va_start(ap, fmt); pclog_ex(fmt, ap); va_end(ap); } } #else -#define contaq_82c59x_log(fmt, ...) +# define contaq_82c59x_log(fmt, ...) #endif - -typedef struct -{ - uint32_t phys, virt; +typedef struct mem_remapping_t { + uint32_t phys; + uint32_t virt; } mem_remapping_t; +typedef struct contaq_82c59x_t { + uint8_t index; + uint8_t green; + uint8_t smi_status_set; + uint8_t regs[256]; + uint8_t smi_status[2]; -typedef struct -{ - uint8_t index, green, - smi_status_set, - regs[256], smi_status[2]; - - smram_t *smram[2]; + smram_t *smram[2]; } contaq_82c59x_t; - static void contaq_82c59x_isa_speed_recalc(contaq_82c59x_t *dev) { if (dev->regs[0x1c] & 0x02) - cpu_set_isa_speed(7159091); + cpu_set_isa_speed(7159091); else { - /* TODO: ISA clock dividers for 386 and alt. 486. */ - switch (dev->regs[0x10] & 0x03) { - case 0x00: - cpu_set_isa_speed(cpu_busspeed / 4); - break; - case 0x01: - cpu_set_isa_speed(cpu_busspeed / 6); - break; - case 0x02: - cpu_set_isa_speed(cpu_busspeed / 8); - break; - case 0x03: - cpu_set_isa_speed(cpu_busspeed / 5); - break; - } + /* TODO: ISA clock dividers for 386 and alt. 486. */ + switch (dev->regs[0x10] & 0x03) { + case 0x00: + cpu_set_isa_speed(cpu_busspeed / 4); + break; + case 0x01: + cpu_set_isa_speed(cpu_busspeed / 6); + break; + case 0x02: + cpu_set_isa_speed(cpu_busspeed / 8); + break; + case 0x03: + cpu_set_isa_speed(cpu_busspeed / 5); + break; + default: + break; + } } } - static void contaq_82c59x_shadow_recalc(contaq_82c59x_t *dev) { - uint32_t i, base; - uint8_t bit; + uint32_t i; + uint32_t base; + uint8_t bit; shadowbios = shadowbios_write = 0; /* F0000-FFFFF */ if (dev->regs[0x15] & 0x80) { - shadowbios |= 1; - mem_set_mem_state_both(0xf0000, 0x10000, MEM_READ_INTERNAL | MEM_WRITE_EXTANY); + shadowbios |= 1; + mem_set_mem_state_both(0xf0000, 0x10000, MEM_READ_INTERNAL | MEM_WRITE_EXTANY); } else { - shadowbios_write |= 1; - mem_set_mem_state_both(0xf0000, 0x10000, MEM_READ_EXTANY | MEM_WRITE_INTERNAL); + shadowbios_write |= 1; + mem_set_mem_state_both(0xf0000, 0x10000, MEM_READ_EXTANY | MEM_WRITE_INTERNAL); } /* C0000-CFFFF */ if (dev->regs[0x15] & 0x01) - mem_set_mem_state_both(0xc0000, 0x10000, MEM_READ_EXTANY | MEM_WRITE_EXTANY); + mem_set_mem_state_both(0xc0000, 0x10000, MEM_READ_EXTANY | MEM_WRITE_EXTANY); else { - for (i = 0; i < 4; i++) { - base = 0xc0000 + (i << 14); - bit = 1 << (i + 2); - if (dev->regs[0x15] & bit) { - if (dev->regs[0x15] & 0x02) - mem_set_mem_state_both(base, 0x04000, MEM_READ_INTERNAL | MEM_WRITE_EXTERNAL); - else - mem_set_mem_state_both(base, 0x04000, MEM_READ_EXTERNAL | MEM_WRITE_INTERNAL); - } else - mem_set_mem_state_both(base, 0x04000, MEM_READ_EXTERNAL | MEM_WRITE_EXTERNAL); - } + for (i = 0; i < 4; i++) { + base = 0xc0000 + (i << 14); + bit = 1 << (i + 2); + if (dev->regs[0x15] & bit) { + if (dev->regs[0x15] & 0x02) + mem_set_mem_state_both(base, 0x04000, MEM_READ_INTERNAL | MEM_WRITE_EXTERNAL); + else + mem_set_mem_state_both(base, 0x04000, MEM_READ_EXTERNAL | MEM_WRITE_INTERNAL); + } else + mem_set_mem_state_both(base, 0x04000, MEM_READ_EXTERNAL | MEM_WRITE_EXTERNAL); + } } if (dev->green) { - /* D0000-DFFFF */ - if (dev->regs[0x6e] & 0x01) - mem_set_mem_state_both(0xd0000, 0x10000, MEM_READ_EXTANY | MEM_WRITE_EXTANY); - else { - for (i = 0; i < 4; i++) { - base = 0xd0000 + (i << 14); - bit = 1 << (i + 2); - if (dev->regs[0x6e] & bit) { - if (dev->regs[0x6e] & 0x02) - mem_set_mem_state_both(base, 0x04000, MEM_READ_INTERNAL | MEM_WRITE_EXTERNAL); - else - mem_set_mem_state_both(base, 0x04000, MEM_READ_INTERNAL | MEM_WRITE_INTERNAL); - } else - mem_set_mem_state_both(base, 0x04000, MEM_READ_EXTERNAL | MEM_WRITE_EXTERNAL); - } - } + /* D0000-DFFFF */ + if (dev->regs[0x6e] & 0x01) + mem_set_mem_state_both(0xd0000, 0x10000, MEM_READ_EXTANY | MEM_WRITE_EXTANY); + else { + for (i = 0; i < 4; i++) { + base = 0xd0000 + (i << 14); + bit = 1 << (i + 2); + if (dev->regs[0x6e] & bit) { + if (dev->regs[0x6e] & 0x02) + mem_set_mem_state_both(base, 0x04000, MEM_READ_INTERNAL | MEM_WRITE_EXTERNAL); + else + mem_set_mem_state_both(base, 0x04000, MEM_READ_INTERNAL | MEM_WRITE_INTERNAL); + } else + mem_set_mem_state_both(base, 0x04000, MEM_READ_EXTERNAL | MEM_WRITE_EXTERNAL); + } + } - /* E0000-EFFFF */ - if (dev->regs[0x6f] & 0x01) - mem_set_mem_state_both(0xe0000, 0x10000, MEM_READ_EXTANY | MEM_WRITE_EXTANY); - else { - for (i = 0; i < 4; i++) { - base = 0xe0000 + (i << 14); - bit = 1 << (i + 2); - if (dev->regs[0x6f] & bit) { - shadowbios |= 1; - if (dev->regs[0x6f] & 0x02) - mem_set_mem_state_both(base, 0x04000, MEM_READ_INTERNAL | MEM_WRITE_EXTERNAL); - else { - shadowbios_write |= 1; - mem_set_mem_state_both(base, 0x04000, MEM_READ_INTERNAL | MEM_WRITE_INTERNAL); - } - } else - mem_set_mem_state_both(base, 0x04000, MEM_READ_EXTERNAL | MEM_WRITE_EXTERNAL); - } - } + /* E0000-EFFFF */ + if (dev->regs[0x6f] & 0x01) + mem_set_mem_state_both(0xe0000, 0x10000, MEM_READ_EXTANY | MEM_WRITE_EXTANY); + else { + for (i = 0; i < 4; i++) { + base = 0xe0000 + (i << 14); + bit = 1 << (i + 2); + if (dev->regs[0x6f] & bit) { + shadowbios |= 1; + if (dev->regs[0x6f] & 0x02) + mem_set_mem_state_both(base, 0x04000, MEM_READ_INTERNAL | MEM_WRITE_EXTERNAL); + else { + shadowbios_write |= 1; + mem_set_mem_state_both(base, 0x04000, MEM_READ_INTERNAL | MEM_WRITE_INTERNAL); + } + } else + mem_set_mem_state_both(base, 0x04000, MEM_READ_EXTERNAL | MEM_WRITE_EXTERNAL); + } + } } } - static void contaq_82c59x_smram_recalc(contaq_82c59x_t *dev) { smram_disable(dev->smram[1]); if (dev->regs[0x70] & 0x04) - smram_enable(dev->smram[1], 0x00040000, 0x000a0000, 0x00020000, 1, 1); + smram_enable(dev->smram[1], 0x00040000, 0x000a0000, 0x00020000, 1, 1); } - static void contaq_82c59x_write(uint16_t addr, uint8_t val, void *priv) { - contaq_82c59x_t *dev = (contaq_82c59x_t *)priv; + contaq_82c59x_t *dev = (contaq_82c59x_t *) priv; switch (addr) { - case 0x22: - dev->index = val; - break; + case 0x22: + dev->index = val; + break; - case 0x23: - contaq_82c59x_log("Contaq 82C59x: dev->regs[%02x] = %02x\n", dev->index, val); + case 0x23: + contaq_82c59x_log("Contaq 82C59x: dev->regs[%02x] = %02x\n", dev->index, val); - if ((dev->index >= 0x60) && !dev->green) - return; + if ((dev->index >= 0x60) && !dev->green) + return; - switch (dev->index) { - /* Registers common to 82C596(A) and 82C597. */ - case 0x10: - dev->regs[dev->index] = val; - contaq_82c59x_isa_speed_recalc(dev); - break; + switch (dev->index) { + /* Registers common to 82C596(A) and 82C597. */ + case 0x10: + dev->regs[dev->index] = val; + contaq_82c59x_isa_speed_recalc(dev); + break; - case 0x11: - dev->regs[dev->index] = val; - cpu_cache_int_enabled = !!(val & 0x01); - cpu_update_waitstates(); - break; + case 0x11: + dev->regs[dev->index] = val; + cpu_cache_int_enabled = !!(val & 0x01); + cpu_update_waitstates(); + break; - case 0x12: case 0x13: - dev->regs[dev->index] = val; - break; + case 0x12: + case 0x13: + dev->regs[dev->index] = val; + break; - case 0x14: - dev->regs[dev->index] = val; - reset_on_hlt = !!(val & 0x80); - break; + case 0x14: + dev->regs[dev->index] = val; + reset_on_hlt = !!(val & 0x80); + break; - case 0x15: - dev->regs[dev->index] = val; - contaq_82c59x_shadow_recalc(dev); - break; + case 0x15: + dev->regs[dev->index] = val; + contaq_82c59x_shadow_recalc(dev); + break; - case 0x16 ... 0x1b: - dev->regs[dev->index] = val; - break; + case 0x16 ... 0x1b: + dev->regs[dev->index] = val; + break; - case 0x1c: - /* TODO: What's NPRST (generated if bit 3 is set)? */ - dev->regs[dev->index] = val; - contaq_82c59x_isa_speed_recalc(dev); - break; + case 0x1c: + /* TODO: What's NPRST (generated if bit 3 is set)? */ + dev->regs[dev->index] = val; + contaq_82c59x_isa_speed_recalc(dev); + break; - case 0x1d ... 0x1f: - dev->regs[dev->index] = val; - break; + case 0x1d ... 0x1f: + dev->regs[dev->index] = val; + break; - /* Green (82C597-specific) registers. */ - case 0x60 ... 0x63: - dev->regs[dev->index] = val; - break; + /* Green (82C597-specific) registers. */ + case 0x60 ... 0x63: + dev->regs[dev->index] = val; + break; - case 0x64: - dev->regs[dev->index] = val; - if (val & 0x80) { - if (dev->regs[0x65] & 0x80) - smi_line = 1; - dev->smi_status[0] |= 0x10; - } - break; + case 0x64: + dev->regs[dev->index] = val; + if (val & 0x80) { + if (dev->regs[0x65] & 0x80) + smi_raise(); + dev->smi_status[0] |= 0x10; + } + break; - case 0x65 ... 0x69: - dev->regs[dev->index] = val; - break; + case 0x65 ... 0x69: + dev->regs[dev->index] = val; + break; - case 0x6a: - dev->regs[dev->index] = val; - dev->smi_status_set = !!(val & 0x80); - break; + case 0x6a: + dev->regs[dev->index] = val; + dev->smi_status_set = !!(val & 0x80); + break; - case 0x6b ... 0x6d: - dev->regs[dev->index] = val; - break; + case 0x6b ... 0x6d: + dev->regs[dev->index] = val; + break; - case 0x6e: case 0x6f: - dev->regs[dev->index] = val; - contaq_82c59x_shadow_recalc(dev); - break; + case 0x6e: + case 0x6f: + dev->regs[dev->index] = val; + contaq_82c59x_shadow_recalc(dev); + break; - case 0x70: - dev->regs[dev->index] = val; - contaq_82c59x_smram_recalc(dev); - break; + case 0x70: + dev->regs[dev->index] = val; + contaq_82c59x_smram_recalc(dev); + break; - case 0x71 ... 0x79: - dev->regs[dev->index] = val; - break; + case 0x71 ... 0x79: + dev->regs[dev->index] = val; + break; - case 0x7b: case 0x7c: - dev->regs[dev->index] = val; - break; - } - break; + case 0x7b: + case 0x7c: + dev->regs[dev->index] = val; + break; + + default: + break; + } + break; + + default: + break; } } - static uint8_t contaq_82c59x_read(uint16_t addr, void *priv) { - contaq_82c59x_t *dev = (contaq_82c59x_t *)priv; - uint8_t ret = 0xff; + contaq_82c59x_t *dev = (contaq_82c59x_t *) priv; + uint8_t ret = 0xff; if (addr == 0x23) { - if (dev->index == 0x6a) { - ret = dev->smi_status[dev->smi_status_set]; - /* I assume it's cleared on read. */ - dev->smi_status[dev->smi_status_set] = 0x00; - } else - ret = dev->regs[dev->index]; + if (dev->index == 0x6a) { + ret = dev->smi_status[dev->smi_status_set]; + /* I assume it's cleared on read. */ + dev->smi_status[dev->smi_status_set] = 0x00; + } else + ret = dev->regs[dev->index]; } return ret; } - static void contaq_82c59x_close(void *priv) { - contaq_82c59x_t *dev = (contaq_82c59x_t *)priv; + contaq_82c59x_t *dev = (contaq_82c59x_t *) priv; smram_del(dev->smram[1]); smram_del(dev->smram[0]); @@ -313,11 +317,10 @@ contaq_82c59x_close(void *priv) free(dev); } - static void * contaq_82c59x_init(const device_t *info) { - contaq_82c59x_t *dev = (contaq_82c59x_t *)malloc(sizeof(contaq_82c59x_t)); + contaq_82c59x_t *dev = (contaq_82c59x_t *) malloc(sizeof(contaq_82c59x_t)); memset(dev, 0x00, sizeof(contaq_82c59x_t)); dev->green = info->local; @@ -334,44 +337,42 @@ contaq_82c59x_init(const device_t *info) contaq_82c59x_shadow_recalc(dev); if (dev->green) { - /* SMRAM 0: Fixed A0000-BFFFF to A0000-BFFFF DRAM. */ - dev->smram[0] = smram_add(); - smram_enable(dev->smram[0], 0x000a0000, 0x000a0000, 0x00020000, 0, 1); + /* SMRAM 0: Fixed A0000-BFFFF to A0000-BFFFF DRAM. */ + dev->smram[0] = smram_add(); + smram_enable(dev->smram[0], 0x000a0000, 0x000a0000, 0x00020000, 0, 1); - /* SMRAM 1: Optional. */ - dev->smram[1] = smram_add(); - contaq_82c59x_smram_recalc(dev); + /* SMRAM 1: Optional. */ + dev->smram[1] = smram_add(); + contaq_82c59x_smram_recalc(dev); } return dev; } - const device_t contaq_82c596a_device = { - "Contaq 82C596A", - "contaq_82c596a", - 0, - 0, - contaq_82c59x_init, - contaq_82c59x_close, - NULL, - { NULL }, - NULL, - NULL, - NULL + .name = "Contaq 82C596A", + .internal_name = "contaq_82c596a", + .flags = 0, + .local = 0, + .init = contaq_82c59x_init, + .close = contaq_82c59x_close, + .reset = NULL, + { .available = NULL }, + .speed_changed = NULL, + .force_redraw = NULL, + .config = NULL }; - const device_t contaq_82c597_device = { - "Contaq 82C597", - "contaq_82c597", - 0, - 1, - contaq_82c59x_init, - contaq_82c59x_close, - NULL, - { NULL }, - NULL, - NULL, - NULL + .name = "Contaq 82C597", + .internal_name = "contaq_82c597", + .flags = 0, + .local = 1, + .init = contaq_82c59x_init, + .close = contaq_82c59x_close, + .reset = NULL, + { .available = NULL }, + .speed_changed = NULL, + .force_redraw = NULL, + .config = NULL }; diff --git a/src/chipset/cs4031.c b/src/chipset/cs4031.c index 01e3edc18..fb439ec3a 100644 --- a/src/chipset/cs4031.c +++ b/src/chipset/cs4031.c @@ -1,21 +1,19 @@ /* - * 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. + * 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. + * This file is part of the 86Box distribution. * - * Implementation of the Chips & Technologies CS4031 chipset. + * Implementation of the Chips & Technologies CS4031 chipset. * * * - * Authors: Tiseno100 - * - * Copyright 2021 Tiseno100 + * Authors: Tiseno100 * + * Copyright 2021 Tiseno100 */ - #include #include #include @@ -29,124 +27,128 @@ #include <86box/io.h> #include <86box/device.h> #include <86box/mem.h> +#include <86box/plat_unused.h> #include <86box/port_92.h> #include <86box/chipset.h> -typedef struct -{ - uint8_t index, - regs[256]; +typedef struct cs4031_t { + uint8_t index; + uint8_t regs[256]; port_92_t *port_92; } cs4031_t; #ifdef ENABLE_CS4031_LOG int cs4031_do_log = ENABLE_CS4031_LOG; + static void cs4031_log(const char *fmt, ...) { va_list ap; - if (cs4031_do_log) - { + if (cs4031_do_log) { va_start(ap, fmt); pclog_ex(fmt, ap); va_end(ap); } } #else -#define cs4031_log(fmt, ...) +# define cs4031_log(fmt, ...) #endif -static void cs4031_shadow_recalc(cs4031_t *dev) +static void +cs4031_shadow_recalc(cs4031_t *dev) { mem_set_mem_state_both(0xa0000, 0x10000, (dev->regs[0x18] & 0x01) ? (MEM_READ_INTERNAL | MEM_WRITE_INTERNAL) : (MEM_READ_EXTANY | MEM_WRITE_EXTANY)); mem_set_mem_state_both(0xb0000, 0x10000, (dev->regs[0x18] & 0x02) ? (MEM_READ_INTERNAL | MEM_WRITE_INTERNAL) : (MEM_READ_EXTANY | MEM_WRITE_EXTANY)); - for (uint32_t i = 0; i < 7; i++) - { + for (uint32_t i = 0; i < 7; i++) { if (i < 4) mem_set_mem_state_both(0xc0000 + (i << 14), 0x4000, ((dev->regs[0x19] & (1 << i)) ? MEM_READ_INTERNAL : MEM_READ_EXTANY) | ((dev->regs[0x1a] & (1 << i)) ? MEM_WRITE_INTERNAL : MEM_WRITE_EXTANY)); else mem_set_mem_state_both(0xd0000 + ((i - 4) << 16), 0x10000, ((dev->regs[0x19] & (1 << i)) ? MEM_READ_INTERNAL : MEM_READ_EXTANY) | ((dev->regs[0x1a] & (1 << i)) ? MEM_WRITE_INTERNAL : MEM_WRITE_EXTANY)); } - shadowbios = !!(dev->regs[0x19] & 0x40); + shadowbios = !!(dev->regs[0x19] & 0x40); shadowbios_write = !!(dev->regs[0x1a] & 0x40); } static void cs4031_write(uint16_t addr, uint8_t val, void *priv) { - cs4031_t *dev = (cs4031_t *)priv; + cs4031_t *dev = (cs4031_t *) priv; - switch (addr) - { - case 0x22: - dev->index = val; - break; - case 0x23: - cs4031_log("CS4031: dev->regs[%02x] = %02x\n", dev->index, val); - switch (dev->index) - { - case 0x05: - dev->regs[dev->index] = val & 0x3f; + switch (addr) { + case 0x22: + dev->index = val; + break; + case 0x23: + cs4031_log("CS4031: dev->regs[%02x] = %02x\n", dev->index, val); + switch (dev->index) { + case 0x05: + dev->regs[dev->index] = val & 0x3f; + break; + + case 0x06: + dev->regs[dev->index] = val & 0xbc; + break; + + case 0x07: + dev->regs[dev->index] = val & 0x0f; + break; + + case 0x10: + dev->regs[dev->index] = val & 0x3d; + break; + + case 0x11: + dev->regs[dev->index] = val & 0x8d; + break; + + case 0x12: + case 0x13: + dev->regs[dev->index] = val & 0x8d; + break; + + case 0x14: + case 0x15: + case 0x16: + case 0x17: + dev->regs[dev->index] = val & 0x7f; + break; + + case 0x18: + dev->regs[dev->index] = val & 0xf3; + cs4031_shadow_recalc(dev); + break; + + case 0x19: + case 0x1a: + dev->regs[dev->index] = val & 0x7f; + cs4031_shadow_recalc(dev); + break; + + case 0x1b: + dev->regs[dev->index] = val; + break; + + case 0x1c: + dev->regs[dev->index] = val & 0xb3; + port_92_set_features(dev->port_92, val & 0x10, val & 0x20); + break; + + default: + break; + } break; - case 0x06: - dev->regs[dev->index] = val & 0xbc; - break; - - case 0x07: - dev->regs[dev->index] = val & 0x0f; - break; - - case 0x10: - dev->regs[dev->index] = val & 0x3d; - break; - - case 0x11: - dev->regs[dev->index] = val & 0x8d; - break; - - case 0x12: - case 0x13: - dev->regs[dev->index] = val & 0x8d; - break; - - case 0x14: - case 0x15: - case 0x16: - case 0x17: - dev->regs[dev->index] = val & 0x7f; - break; - - case 0x18: - dev->regs[dev->index] = val & 0xf3; - cs4031_shadow_recalc(dev); - break; - - case 0x19: - case 0x1a: - dev->regs[dev->index] = val & 0x7f; - cs4031_shadow_recalc(dev); - break; - - case 0x1b: - dev->regs[dev->index] = val; - break; - - case 0x1c: - dev->regs[dev->index] = val & 0xb3; - port_92_set_features(dev->port_92, val & 0x10, val & 0x20); - break; - } - break; + default: + break; } } static uint8_t cs4031_read(uint16_t addr, void *priv) { - cs4031_t *dev = (cs4031_t *)priv; + const cs4031_t *dev = (cs4031_t *) priv; return (addr == 0x23) ? dev->regs[dev->index] : 0xff; } @@ -154,15 +156,15 @@ cs4031_read(uint16_t addr, void *priv) static void cs4031_close(void *priv) { - cs4031_t *dev = (cs4031_t *)priv; + cs4031_t *dev = (cs4031_t *) priv; free(dev); } static void * -cs4031_init(const device_t *info) +cs4031_init(UNUSED(const device_t *info)) { - cs4031_t *dev = (cs4031_t *)malloc(sizeof(cs4031_t)); + cs4031_t *dev = (cs4031_t *) malloc(sizeof(cs4031_t)); memset(dev, 0, sizeof(cs4031_t)); dev->port_92 = device_add(&port_92_device); @@ -176,14 +178,15 @@ cs4031_init(const device_t *info) } const device_t cs4031_device = { - "Chips & Technogies CS4031", - "cs4031", - 0, - 0, - cs4031_init, - cs4031_close, - NULL, - {NULL}, - NULL, - NULL, - NULL}; + .name = "Chips & Technogies CS4031", + .internal_name = "cs4031", + .flags = 0, + .local = 0, + .init = cs4031_init, + .close = cs4031_close, + .reset = NULL, + { .available = NULL }, + .speed_changed = NULL, + .force_redraw = NULL, + .config = NULL +}; diff --git a/src/chipset/cs8230.c b/src/chipset/cs8230.c index e9e060138..93a7f1bba 100644 --- a/src/chipset/cs8230.c +++ b/src/chipset/cs8230.c @@ -1,18 +1,18 @@ /* - * 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. + * 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. + * This file is part of the 86Box distribution. * - * Emulation of C&T CS8230 ("386/AT") chipset. + * Emulation of C&T CS8230 ("386/AT") chipset. * * * - * Authors: Sarah Walker, + * Authors: Sarah Walker, * - * Copyright 2020 Sarah Walker. + * Copyright 2020 Sarah Walker. */ #include #include @@ -25,144 +25,161 @@ #include <86box/io.h> #include <86box/device.h> #include <86box/mem.h> +#include <86box/plat_unused.h> #include <86box/fdd.h> #include <86box/fdc.h> #include <86box/chipset.h> - -typedef struct -{ - int idx; - uint8_t regs[256]; +typedef struct cs8230_t { + int idx; + uint8_t regs[256]; } cs8230_t; - static void shadow_control(uint32_t addr, uint32_t size, int state) { switch (state) { - case 0x00: - mem_set_mem_state(addr, size, MEM_READ_INTERNAL | MEM_WRITE_INTERNAL); - break; - case 0x01: - mem_set_mem_state(addr, size, MEM_READ_EXTANY | MEM_WRITE_INTERNAL); - break; - case 0x10: - mem_set_mem_state(addr, size, MEM_READ_INTERNAL | MEM_WRITE_EXTANY); - break; - case 0x11: - mem_set_mem_state(addr, size, MEM_READ_EXTANY | MEM_WRITE_EXTANY); - break; + case 0x00: + mem_set_mem_state(addr, size, MEM_READ_INTERNAL | MEM_WRITE_INTERNAL); + break; + case 0x01: + mem_set_mem_state(addr, size, MEM_READ_EXTANY | MEM_WRITE_INTERNAL); + break; + case 0x10: + mem_set_mem_state(addr, size, MEM_READ_INTERNAL | MEM_WRITE_EXTANY); + break; + case 0x11: + mem_set_mem_state(addr, size, MEM_READ_EXTANY | MEM_WRITE_EXTANY); + break; + default: + break; } flushmmucache_nopc(); } - static void rethink_shadow_mappings(cs8230_t *cs8230) { - int c; - - for (c = 0; c < 32; c++) { - /* Addresses 40000-bffff in 16k blocks */ - if (cs8230->regs[0xa + (c >> 3)] & (1 << (c & 7))) - mem_set_mem_state(0x40000 + (c << 14), 0x4000, MEM_READ_EXTERNAL | MEM_WRITE_EXTERNAL); /* I/O channel */ - else - mem_set_mem_state(0x40000 + (c << 14), 0x4000, MEM_READ_INTERNAL | MEM_WRITE_INTERNAL); /* System board */ + for (uint8_t c = 0; c < 32; c++) { + /* Addresses 40000-bffff in 16k blocks */ + if (cs8230->regs[0xa + (c >> 3)] & (1 << (c & 7))) + mem_set_mem_state(0x40000 + (c << 14), 0x4000, MEM_READ_EXTERNAL | MEM_WRITE_EXTERNAL); /* I/O channel */ + else + mem_set_mem_state(0x40000 + (c << 14), 0x4000, MEM_READ_INTERNAL | MEM_WRITE_INTERNAL); /* System board */ } - for (c = 0; c < 16; c++) { - /* Addresses c0000-fffff in 16k blocks. System board ROM can be mapped here */ - if (cs8230->regs[0xe + (c >> 3)] & (1 << (c & 7))) - mem_set_mem_state(0xc0000 + (c << 14), 0x4000, MEM_READ_EXTANY | MEM_WRITE_EXTANY); /* I/O channel */ - else - shadow_control(0xc0000 + (c << 14), 0x4000, (cs8230->regs[9] >> (3 - (c >> 2))) & 0x11); + for (uint8_t c = 0; c < 16; c++) { + /* Addresses c0000-fffff in 16k blocks. System board ROM can be mapped here */ + if (cs8230->regs[0xe + (c >> 3)] & (1 << (c & 7))) + mem_set_mem_state(0xc0000 + (c << 14), 0x4000, MEM_READ_EXTANY | MEM_WRITE_EXTANY); /* I/O channel */ + else + shadow_control(0xc0000 + (c << 14), 0x4000, (cs8230->regs[9] >> (3 - (c >> 2))) & 0x11); } } - static uint8_t -cs8230_read(uint16_t port, void *p) +cs8230_read(uint16_t port, void *priv) { - cs8230_t *cs8230 = (cs8230_t *) p; - uint8_t ret = 0xff; + const cs8230_t *cs8230 = (cs8230_t *) priv; + uint8_t ret = 0xff; if (port & 1) { - switch (cs8230->idx) { - case 0x04: /* 82C301 ID/version */ - ret = cs8230->regs[cs8230->idx] & ~0xe3; - break; + switch (cs8230->idx) { + case 0x04: /* 82C301 ID/version */ + ret = cs8230->regs[cs8230->idx] & ~0xe3; + break; - case 0x08: /* 82C302 ID/Version */ - ret = cs8230->regs[cs8230->idx] & ~0xe0; - break; + case 0x08: /* 82C302 ID/Version */ + ret = cs8230->regs[cs8230->idx] & ~0xe0; + break; - case 0x05: case 0x06: /* 82C301 registers */ - case 0x09: case 0x0a: case 0x0b: case 0x0c: /* 82C302 registers */ - case 0x0d: case 0x0e: case 0x0f: - case 0x10: case 0x11: case 0x12: case 0x13: - case 0x28: case 0x29: case 0x2a: - ret = cs8230->regs[cs8230->idx]; - break; - } + case 0x05: + case 0x06: /* 82C301 registers */ + case 0x09: + case 0x0a: + case 0x0b: + case 0x0c: /* 82C302 registers */ + case 0x0d: + case 0x0e: + case 0x0f: + case 0x10: + case 0x11: + case 0x12: + case 0x13: + case 0x28: + case 0x29: + case 0x2a: + ret = cs8230->regs[cs8230->idx]; + break; + + default: + break; + } } return ret; } - static void -cs8230_write(uint16_t port, uint8_t val, void *p) +cs8230_write(uint16_t port, uint8_t val, void *priv) { - cs8230_t *cs8230 = (cs8230_t *)p; + cs8230_t *cs8230 = (cs8230_t *) priv; if (!(port & 1)) - cs8230->idx = val; + cs8230->idx = val; else { - cs8230->regs[cs8230->idx] = val; - switch (cs8230->idx) { - case 0x09: /* RAM/ROM Configuration in boot area */ - case 0x0a: case 0x0b: case 0x0c: case 0x0d: case 0x0e: case 0x0f: /* Address maps */ - rethink_shadow_mappings(cs8230); - break; - } + cs8230->regs[cs8230->idx] = val; + switch (cs8230->idx) { + case 0x09: /* RAM/ROM Configuration in boot area */ + case 0x0a: + case 0x0b: + case 0x0c: + case 0x0d: + case 0x0e: + case 0x0f: /* Address maps */ + rethink_shadow_mappings(cs8230); + break; + default: + break; + } } } - static void cs8230_close(void *priv) { - cs8230_t *cs8230 = (cs8230_t *)priv; + cs8230_t *cs8230 = (cs8230_t *) priv; free(cs8230); } - -static void -*cs8230_init(const device_t *info) +static void * +cs8230_init(UNUSED(const device_t *info)) { - cs8230_t *cs8230 = (cs8230_t *)malloc(sizeof(cs8230_t)); + cs8230_t *cs8230 = (cs8230_t *) malloc(sizeof(cs8230_t)); memset(cs8230, 0, sizeof(cs8230_t)); io_sethandler(0x0022, 0x0002, cs8230_read, NULL, NULL, cs8230_write, NULL, NULL, cs8230); if (mem_size > 768) { - mem_mapping_set_addr(&ram_mid_mapping, 0xa0000, mem_size > 1024 ? 0x60000 : 0x20000 + (mem_size - 768) * 1024); - mem_mapping_set_exec(&ram_mid_mapping, ram + 0xa0000); + mem_mapping_set_addr(&ram_mid_mapping, 0xa0000, mem_size > 1024 ? 0x60000 : 0x20000 + (mem_size - 768) * 1024); + mem_mapping_set_exec(&ram_mid_mapping, ram + 0xa0000); } return cs8230; } - const device_t cs8230_device = { - "C&T CS8230 (386/AT)", - "cs8230", - 0, - 0, - cs8230_init, cs8230_close, NULL, - { NULL }, NULL, NULL, - NULL + .name = "C&T CS8230 (386/AT)", + .internal_name = "cs8230", + .flags = 0, + .local = 0, + .init = cs8230_init, + .close = cs8230_close, + .reset = NULL, + { .available = NULL }, + .speed_changed = NULL, + .force_redraw = NULL, + .config = NULL }; diff --git a/src/chipset/et6000.c b/src/chipset/et6000.c index 4dd00bdf3..f2cffd7f7 100644 --- a/src/chipset/et6000.c +++ b/src/chipset/et6000.c @@ -1,19 +1,19 @@ /* - * 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. + * 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. + * This file is part of the 86Box distribution. * - * Implementation of the ETEQ Cheetah ET6000 chipset. + * Implementation of the ETEQ Cheetah ET6000 chipset. * - * Authors: Tiseno100 * - * Copyright 2021 Tiseno100 * + * Authors: Tiseno100 + * + * Copyright 2021 Tiseno100 */ - #include #include #include @@ -28,35 +28,37 @@ #include <86box/device.h> #include <86box/mem.h> #include <86box/pit.h> +#include <86box/plat_unused.h> #include <86box/port_92.h> #include <86box/chipset.h> #define INDEX (dev->index - 0x10) -typedef struct -{ - uint8_t index, regs[6]; +typedef struct et6000_t { + uint8_t index; + uint8_t regs[256]; } et6000_t; #ifdef ENABLE_ET6000_LOG int et6000_do_log = ENABLE_ET6000_LOG; + static void et6000_log(const char *fmt, ...) { va_list ap; - if (et6000_do_log) - { + if (et6000_do_log) { va_start(ap, fmt); pclog_ex(fmt, ap); va_end(ap); } } #else -#define et6000_log(fmt, ...) +# define et6000_log(fmt, ...) #endif -static void et6000_shadow_control(int base, int size, int can_read, int can_write) +static void +et6000_shadow_control(int base, int size, int can_read, int can_write) { mem_set_mem_state_both(base, size, (can_read ? MEM_READ_INTERNAL : MEM_READ_EXTANY) | (can_write ? MEM_WRITE_INTERNAL : MEM_WRITE_EXTANY)); flushmmucache_nopc(); @@ -65,57 +67,61 @@ static void et6000_shadow_control(int base, int size, int can_read, int can_writ static void et6000_write(uint16_t addr, uint8_t val, void *priv) { - et6000_t *dev = (et6000_t *)priv; + et6000_t *dev = (et6000_t *) priv; - switch (addr) - { - case 0x22: - dev->index = val; - break; - case 0x23: - switch (INDEX) - { - case 0: /* System Configuration Register */ - dev->regs[INDEX] = val & 0xdf; - et6000_shadow_control(0xa0000, 0x20000, val & 1, val & 1); - refresh_at_enable = !(val & 0x10); + switch (addr) { + case 0x22: + dev->index = val; + break; + case 0x23: + switch (INDEX) { + case 0: /* System Configuration Register */ + dev->regs[INDEX] = val & 0xdf; + et6000_shadow_control(0xa0000, 0x20000, val & 1, val & 1); + refresh_at_enable = !(val & 0x10); + break; + + case 1: /* CACHE Configuration and Non-Cacheable Block Size */ + dev->regs[INDEX] = val & 0xf0; + break; + + case 2: /* Non-Cacheable Block Address Register */ + dev->regs[INDEX] = val & 0xfe; + break; + + case 3: /* DRAM Bank and Type Configuration Register */ + dev->regs[INDEX] = val; + break; + + case 4: /* DRAM Configuration Register */ + dev->regs[INDEX] = val; + et6000_shadow_control(0xc0000, 0x10000, (dev->regs[0x15] & 2) && (val & 0x20), (dev->regs[0x15] & 2) && (val & 0x20) && (dev->regs[0x15] & 1)); + et6000_shadow_control(0xd0000, 0x10000, (dev->regs[0x15] & 8) && (val & 0x20), (dev->regs[0x15] & 8) && (val & 0x20) && (dev->regs[0x15] & 4)); + break; + + case 5: /* Shadow RAM Configuration Register */ + dev->regs[INDEX] = val; + et6000_shadow_control(0xc0000, 0x10000, (val & 2) && (dev->regs[0x14] & 0x20), (val & 2) && (dev->regs[0x14] & 0x20) && (val & 1)); + et6000_shadow_control(0xd0000, 0x10000, (val & 8) && (dev->regs[0x14] & 0x20), (val & 8) && (dev->regs[0x14] & 0x20) && (val & 4)); + et6000_shadow_control(0xe0000, 0x10000, val & 0x20, (val & 0x20) && (val & 0x10)); + et6000_shadow_control(0xf0000, 0x10000, val & 0x40, !(val & 0x40)); + break; + + default: + break; + } + et6000_log("ET6000: dev->regs[%02x] = %02x\n", dev->index, dev->regs[dev->index]); break; - case 1: /* CACHE Configuration and Non-Cacheable Block Size */ - dev->regs[INDEX] = val & 0xf0; + default: break; - - case 2: /* Non-Cacheable Block Address Register */ - dev->regs[INDEX] = val & 0xfe; - break; - - case 3: /* DRAM Bank and Type Configuration Register */ - dev->regs[INDEX] = val; - break; - - case 4: /* DRAM Configuration Register */ - dev->regs[INDEX] = val; - et6000_shadow_control(0xc0000, 0x10000, (dev->regs[0x15] & 2) && (val & 0x20), (dev->regs[0x15] & 2) && (val & 0x20) && (dev->regs[0x15] & 1)); - et6000_shadow_control(0xd0000, 0x10000, (dev->regs[0x15] & 8) && (val & 0x20), (dev->regs[0x15] & 8) && (val & 0x20) && (dev->regs[0x15] & 4)); - break; - - case 5: /* Shadow RAM Configuration Register */ - dev->regs[INDEX] = val; - et6000_shadow_control(0xc0000, 0x10000, (val & 2) && (dev->regs[0x14] & 0x20), (val & 2) && (dev->regs[0x14] & 0x20) && (val & 1)); - et6000_shadow_control(0xd0000, 0x10000, (val & 8) && (dev->regs[0x14] & 0x20), (val & 8) && (dev->regs[0x14] & 0x20) && (val & 4)); - et6000_shadow_control(0xe0000, 0x10000, val & 0x20, (val & 0x20) && (val & 0x10)); - et6000_shadow_control(0xf0000, 0x10000, val & 0x40, !(val & 0x40)); - break; - } - et6000_log("ET6000: dev->regs[%02x] = %02x\n", dev->index, dev->regs[dev->index]); - break; } } static uint8_t et6000_read(uint16_t addr, void *priv) { - et6000_t *dev = (et6000_t *)priv; + const et6000_t *dev = (et6000_t *) priv; return ((addr == 0x23) && (INDEX >= 0) && (INDEX <= 5)) ? dev->regs[INDEX] : 0xff; } @@ -123,15 +129,15 @@ et6000_read(uint16_t addr, void *priv) static void et6000_close(void *priv) { - et6000_t *dev = (et6000_t *)priv; + et6000_t *dev = (et6000_t *) priv; free(dev); } static void * -et6000_init(const device_t *info) +et6000_init(UNUSED(const device_t *info)) { - et6000_t *dev = (et6000_t *)malloc(sizeof(et6000_t)); + et6000_t *dev = (et6000_t *) malloc(sizeof(et6000_t)); memset(dev, 0, sizeof(et6000_t)); /* Port 92h */ @@ -149,14 +155,15 @@ et6000_init(const device_t *info) } const device_t et6000_device = { - "ETEQ Cheetah ET6000", - "et6000", - 0, - 0, - et6000_init, - et6000_close, - NULL, - {NULL}, - NULL, - NULL, - NULL}; + .name = "ETEQ Cheetah ET6000", + .internal_name = "et6000", + .flags = 0, + .local = 0, + .init = et6000_init, + .close = et6000_close, + .reset = NULL, + { .available = NULL }, + .speed_changed = NULL, + .force_redraw = NULL, + .config = NULL +}; diff --git a/src/chipset/gc100.c b/src/chipset/gc100.c index 079f775e5..0b4717903 100644 --- a/src/chipset/gc100.c +++ b/src/chipset/gc100.c @@ -1,19 +1,22 @@ /* - * 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. + * 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. + * This file is part of the 86Box distribution. * - * Implementation of the G2 GC100/GC100A chipset. - * NOTE: As documentation is currently available only for the - * CG100 chipset, the GC100A chipset has been reverese-engineered. - * Thus, its behavior may not be fully accurate. + * Implementation of the G2 GC100/GC100A chipset. * - * Authors: EngiNerd, + * NOTE: As documentation is currently available only for the + * GC100 chipset, the GC100A chipset has been reverese-engineered. + * Thus, its behavior may not be fully accurate. * - * Copyright 2020-2021 EngiNerd. + * + * + * Authors: EngiNerd, + * + * Copyright 2020-2021 EngiNerd. */ #include #include @@ -41,13 +44,10 @@ #include <86box/io.h> #include <86box/video.h> - -typedef struct -{ - uint8_t reg[0x10]; +typedef struct gc100_t { + uint8_t reg[0x10]; } gc100_t; - #ifdef ENABLE_GC100_LOG int gc100_do_log = ENABLE_GC100_LOG; @@ -59,143 +59,144 @@ gc100_log(const char *fmt, ...) if (gc100_do_log) { va_start(ap, fmt); pclog_ex(fmt, ap); - va_end(ap); + va_end(ap); } } #else -#define gc100_log(fmt, ...) +# define gc100_log(fmt, ...) #endif - static uint8_t get_fdd_switch_settings(void) { - int i, fdd_count = 0; - - for (i = 0; i < FDD_NUM; i++) { - if (fdd_get_flags(i)) - fdd_count++; + uint8_t fdd_count = 0; + + for (uint8_t i = 0; i < FDD_NUM; i++) { + if (fdd_get_flags(i)) + fdd_count++; } if (!fdd_count) return 0x00; else - return ((fdd_count - 1) << 6) | 0x01; + return ((fdd_count - 1) << 6) | 0x01; } - static uint8_t get_videomode_switch_settings(void) { if (video_is_mda()) - return 0x30; + return 0x30; else if (video_is_cga()) - return 0x20; /* 0x10 would be 40x25 */ + return 0x20; /* 0x10 would be 40x25 */ else - return 0x00; + return 0x00; } - static void gc100_write(uint16_t port, uint8_t val, void *priv) { - gc100_t *dev = (gc100_t *) priv; + gc100_t *dev = (gc100_t *) priv; uint16_t addr = port & 0xf; dev->reg[addr] = val; switch (addr) { - /* addr 0x2 - * bits 5-7: not used - * bit 4: intenal memory wait states - * bits 2-3: external memory wait states - * bits 0-1: i/o access wait states - */ - case 2: - break; + /* addr 0x2 + * bits 5-7: not used + * bit 4: intenal memory wait states + * bits 2-3: external memory wait states + * bits 0-1: i/o access wait states + */ + case 2: + break; - /* addr 0x3 - * bits 1-7: not used - * bit 0: turbo 0 xt 1 - */ - case 3: - if (val & 1) - cpu_dynamic_switch(0); - else - cpu_dynamic_switch(cpu); - break; - - /* addr 0x5 - * programmable dip-switches - * bits 6-7: floppy drive number - * bits 4-5: video mode - * bits 2-3: memory size - * bit 1: fpu - * bit 0: not used - */ + /* addr 0x3 + * bits 1-7: not used + * bit 0: turbo 0 xt 1 + */ + case 3: + if (val & 1) + cpu_dynamic_switch(0); + else + cpu_dynamic_switch(cpu); + break; - /* addr 0x6 */ + /* addr 0x5 + * programmable dip-switches + * bits 6-7: floppy drive number + * bits 4-5: video mode + * bits 2-3: memory size + * bit 1: fpu + * bit 0: not used + */ - /* addr 0x7 */ + /* addr 0x6 */ + + /* addr 0x7 */ + + default: + break; } gc100_log("GC100: Write %02x at %02x\n", val, port); } - static uint8_t gc100_read(uint16_t port, void *priv) { - gc100_t *dev = (gc100_t *) priv; - uint8_t ret = 0xff; - uint16_t addr = port & 0xf; + const gc100_t *dev = (gc100_t *) priv; + uint8_t ret = 0xff; + uint16_t addr = port & 0xf; ret = dev->reg[addr]; gc100_log("GC100: Read %02x at %02x\n", ret, port); switch (addr) { - /* addr 0x2 - * bits 5-7: not used - * bit 4: intenal memory wait states - * bits 2-3: external memory wait states - * bits 0-1: i/o access wait states - */ - case 0x2: - break; + /* addr 0x2 + * bits 5-7: not used + * bit 4: intenal memory wait states + * bits 2-3: external memory wait states + * bits 0-1: i/o access wait states + */ + case 0x2: + break; - /* addr 0x3 - * bits 1-7: not used - * bit 0: turbo 0 xt 1 - */ - case 0x3: - break; + /* addr 0x3 + * bits 1-7: not used + * bit 0: turbo 0 xt 1 + */ + case 0x3: + break; - /* addr 0x5 - * programmable dip-switches - * bits 6-7: floppy drive number - * bits 4-5: video mode - * bits 2-3: memory size - * bit 1: fpu - * bit 0: not used - */ - case 0x5: - ret = ret & 0x0c; - ret |= get_fdd_switch_settings(); - ret |= get_videomode_switch_settings(); - if (hasfpu) - ret |= 0x02; - break; + /* addr 0x5 + * programmable dip-switches + * bits 6-7: floppy drive number + * bits 4-5: video mode + * bits 2-3: memory size + * bit 1: fpu + * bit 0: not used + */ + case 0x5: + ret = ret & 0x0c; + ret |= get_fdd_switch_settings(); + ret |= get_videomode_switch_settings(); + if (hasfpu) + ret |= 0x02; + break; - /* addr 0x6 */ + /* addr 0x6 */ - /* addr 0x7 */ + /* addr 0x7 */ + + default: + break; } return ret; } - static void gc100_close(void *priv) { @@ -204,7 +205,6 @@ gc100_close(void *priv) free(dev); } - static void * gc100_init(const device_t *info) { @@ -216,37 +216,44 @@ gc100_init(const device_t *info) dev->reg[0x5] = 0x0; dev->reg[0x6] = 0x0; dev->reg[0x7] = 0x0; - + if (info->local) { - /* GC100A */ + /* GC100A */ io_sethandler(0x0c2, 0x02, gc100_read, NULL, NULL, gc100_write, NULL, NULL, dev); io_sethandler(0x0c5, 0x03, gc100_read, NULL, NULL, gc100_write, NULL, NULL, dev); } else { - /* GC100 */ + /* GC100 */ io_sethandler(0x022, 0x02, gc100_read, NULL, NULL, gc100_write, NULL, NULL, dev); io_sethandler(0x025, 0x01, gc100_read, NULL, NULL, gc100_write, NULL, NULL, dev); } - + return dev; } - const device_t gc100_device = { - "G2 GC100", - "gc100", - 0, - 0, - gc100_init, gc100_close, NULL, - { NULL }, NULL, NULL, - NULL + .name = "G2 GC100", + .internal_name = "gc100", + .flags = 0, + .local = 0, + .init = gc100_init, + .close = gc100_close, + .reset = NULL, + { .available = NULL }, + .speed_changed = NULL, + .force_redraw = NULL, + .config = NULL }; const device_t gc100a_device = { - "G2 GC100A", - "gc100a", - 0, - 1, - gc100_init, gc100_close, NULL, - { NULL }, NULL, NULL, - NULL + .name = "G2 GC100A", + .internal_name = "gc100a", + .flags = 0, + .local = 1, + .init = gc100_init, + .close = gc100_close, + .reset = NULL, + { .available = NULL }, + .speed_changed = NULL, + .force_redraw = NULL, + .config = NULL }; diff --git a/src/chipset/headland.c b/src/chipset/headland.c index 8a67df9b1..db5922470 100644 --- a/src/chipset/headland.c +++ b/src/chipset/headland.c @@ -1,24 +1,24 @@ /* - * 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. + * 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. + * This file is part of the 86Box distribution. * - * Implementation of the HEADLAND AT286 chipset. + * Implementation of the HEADLAND AT286 chipset. * * * - * Authors: Sarah Walker, - * Fred N. van Kempen, - * Original by GreatPsycho for PCem. - * Miran Grca, + * Authors: Sarah Walker, + * Fred N. van Kempen, + * Original by GreatPsycho for PCem. + * Miran Grca, * - * Copyright 2010-2019 Sarah Walker. - * Copyright 2017-2019 Fred N. van Kempen. - * Copyright 2017-2019 Miran Grca. - * Copyright 2017-2019 GreatPsycho. + * Copyright 2010-2019 Sarah Walker. + * Copyright 2017-2019 Fred N. van Kempen. + * Copyright 2017-2019 Miran Grca. + * Copyright 2017-2019 GreatPsycho. */ #include #include @@ -34,44 +34,60 @@ #include <86box/device.h> #include <86box/fdd.h> #include <86box/fdc.h> +#include <86box/plat_unused.h> #include <86box/port_92.h> #include <86box/chipset.h> +enum { + HEADLAND_GC103 = 0x00, + HEADLAND_GC113 = 0x10, + HEADLAND_HT18_A = 0x11, + HEADLAND_HT18_B = 0x12, + HEADLAND_HT18_C = 0x18, + HEADLAND_HT21_C_D = 0x31, + HEADLAND_HT21_E = 0x32, +}; -typedef struct { - uint8_t valid, enabled; - uint16_t mr; - uint32_t virt_base; +#define HEADLAND_REV_MASK 0x0F - struct headland_t * headland; +#define HEADLAND_HAS_CRI 0x10 +#define HEADLAND_HAS_SLEEP 0x20 + +typedef struct headland_mr_t { + uint8_t valid; + uint8_t enabled; + uint16_t mr; + uint32_t virt_base; + + struct headland_t *headland; } headland_mr_t; - typedef struct headland_t { - uint8_t revision; + uint8_t revision; + uint8_t has_cri; + uint8_t has_sleep; - uint8_t cri; - uint8_t cr[7]; + uint8_t cri; + uint8_t cr[7]; - uint8_t indx; - uint8_t regs[256]; + uint8_t indx; + uint8_t regs[256]; - uint8_t ems_mar; + uint8_t ems_mar; - headland_mr_t null_mr, - ems_mr[64]; + headland_mr_t null_mr; + headland_mr_t ems_mr[64]; - mem_mapping_t low_mapping; - mem_mapping_t ems_mapping[64]; - mem_mapping_t mid_mapping; - mem_mapping_t high_mapping; - mem_mapping_t shadow_mapping[2]; - mem_mapping_t upper_mapping[24]; + mem_mapping_t low_mapping; + mem_mapping_t ems_mapping[64]; + mem_mapping_t mid_mapping; + mem_mapping_t high_mapping; + mem_mapping_t shadow_mapping[2]; + mem_mapping_t upper_mapping[24]; } headland_t; - /* TODO - Headland chipset's memory address mapping emulation isn't fully implemented yet, - so memory configuration is hardcoded now. */ + so memory configuration is hardcoded now. */ static const int mem_conf_cr0[41] = { 0x00, 0x00, 0x20, 0x40, 0x60, 0xA0, 0x40, 0xE0, 0xA0, 0xC0, 0xE0, 0xE0, 0xC0, 0xE0, 0xE0, 0xE0, @@ -89,23 +105,26 @@ static const int mem_conf_cr1[41] = { 0x40 }; - static uint32_t get_addr(headland_t *dev, uint32_t addr, headland_mr_t *mr) { - uint32_t bank_base[4], bank_shift[4], shift, other_shift, bank; + uint32_t bank_base[4]; + uint32_t bank_shift[4]; + uint32_t shift; + uint32_t other_shift; + uint32_t bank; if ((addr >= 0x0e0000) && (addr <= 0x0fffff)) - return addr; + return addr; else if ((addr >= 0xfe0000) && (addr <= 0xffffff)) - return addr & 0x0fffff; + return addr & 0x0fffff; if (dev->revision == 8) { - shift = (dev->cr[0] & 0x80) ? 21 : ((dev->cr[6] & 0x01) ? 23 : 19); - other_shift = (dev->cr[0] & 0x80) ? ((dev->cr[6] & 0x01) ? 19 : 23) : 21; + shift = (dev->cr[0] & 0x80) ? 21 : ((dev->cr[6] & 0x01) ? 23 : 19); + other_shift = (dev->cr[0] & 0x80) ? ((dev->cr[6] & 0x01) ? 19 : 23) : 21; } else { - shift = (dev->cr[0] & 0x80) ? 21 : 19; - other_shift = (dev->cr[0] & 0x80) ? 21 : 19; + shift = (dev->cr[0] & 0x80) ? 21 : 19; + other_shift = (dev->cr[0] & 0x80) ? 21 : 19; } /* Bank size = 1 << (bank shift + 2) . */ @@ -116,289 +135,286 @@ get_addr(headland_t *dev, uint32_t addr, headland_mr_t *mr) bank_base[2] = bank_base[1] + (1 << shift); if ((dev->revision > 0) && (dev->revision < 8) && (dev->cr[1] & 0x40)) { - bank_shift[2] = bank_shift[3] = other_shift; - bank_base[3] = bank_base[2] + (1 << other_shift); - /* First address after the memory is bank_base[3] + (1 << other_shift) */ + bank_shift[2] = bank_shift[3] = other_shift; + bank_base[3] = bank_base[2] + (1 << other_shift); + /* First address after the memory is bank_base[3] + (1 << other_shift) */ } else { - bank_shift[2] = bank_shift[3] = shift; - bank_base[3] = bank_base[2] + (1 << shift); - /* First address after the memory is bank_base[3] + (1 << shift) */ + bank_shift[2] = bank_shift[3] = shift; + bank_base[3] = bank_base[2] + (1 << shift); + /* First address after the memory is bank_base[3] + (1 << shift) */ } if (mr && mr->valid && (dev->cr[0] & 2) && (mr->mr & 0x200)) { - addr = (addr & 0x3fff) | ((mr->mr & 0x1F) << 14); + addr = (addr & 0x3fff) | ((mr->mr & 0x1F) << 14); - bank = (mr->mr >> 7) & 3; + bank = (mr->mr >> 7) & 3; - if (bank_shift[bank] >= 21) - addr |= (mr->mr & 0x060) << 14; + if (bank_shift[bank] >= 21) + addr |= (mr->mr & 0x060) << 14; - if ((dev->revision == 8) && (bank_shift[bank] == 23)) - addr |= (mr->mr & 0xc00) << 11; + if ((dev->revision == 8) && (bank_shift[bank] == 23)) + addr |= (mr->mr & 0xc00) << 11; - addr |= bank_base[(mr->mr >> 7) & 3]; + addr |= bank_base[(mr->mr >> 7) & 3]; } else if (((mr == NULL) || !mr->valid) && (mem_size >= 1024) && (addr >= 0x100000) && ((dev->cr[0] & 4) == 0)) - addr -= 0x60000; + addr -= 0x60000; return addr; } - static void hl_ems_disable(headland_t *dev, uint8_t mar, uint32_t base_addr, uint8_t indx) { - if (base_addr < ((uint32_t)mem_size << 10)) - mem_mapping_set_exec(&dev->ems_mapping[mar & 0x3f], ram + base_addr); + if (base_addr < (mem_size << 10)) + mem_mapping_set_exec(&dev->ems_mapping[mar & 0x3f], ram + base_addr); else - mem_mapping_set_exec(&dev->ems_mapping[mar & 0x3f], NULL); + mem_mapping_set_exec(&dev->ems_mapping[mar & 0x3f], NULL); mem_mapping_disable(&dev->ems_mapping[mar & 0x3f]); if (indx < 24) { - mem_set_mem_state(base_addr, 0x4000, MEM_READ_INTERNAL | MEM_WRITE_INTERNAL); - mem_mapping_enable(&dev->upper_mapping[indx]); + mem_set_mem_state(base_addr, 0x4000, MEM_READ_INTERNAL | MEM_WRITE_INTERNAL); + mem_mapping_enable(&dev->upper_mapping[indx]); } else - mem_set_mem_state(base_addr, 0x4000, MEM_READ_EXTANY | MEM_WRITE_EXTANY); + mem_set_mem_state(base_addr, 0x4000, MEM_READ_EXTANY | MEM_WRITE_EXTANY); } - static void hl_ems_update(headland_t *dev, uint8_t mar) { - uint32_t base_addr, virt_addr; - uint8_t indx = mar & 0x1f; + uint32_t base_addr; + uint32_t virt_addr; + uint8_t indx = mar & 0x1f; base_addr = (indx + 16) << 14; if (indx >= 24) - base_addr += 0x20000; + base_addr += 0x20000; hl_ems_disable(dev, mar, base_addr, indx); - dev->ems_mr[mar & 0x3f].enabled = 0; + dev->ems_mr[mar & 0x3f].enabled = 0; dev->ems_mr[mar & 0x3f].virt_base = base_addr; if ((dev->cr[0] & 2) && ((dev->cr[0] & 1) == ((mar & 0x20) >> 5)) && (dev->ems_mr[mar & 0x3f].mr & 0x200)) { - mem_set_mem_state(base_addr, 0x4000, MEM_READ_INTERNAL | MEM_WRITE_INTERNAL); - virt_addr = get_addr(dev, base_addr, &dev->ems_mr[mar & 0x3f]); - dev->ems_mr[mar & 0x3f].enabled = 1; - dev->ems_mr[mar & 0x3f].virt_base = virt_addr; - if (indx < 24) - mem_mapping_disable(&dev->upper_mapping[indx]); - if (virt_addr < ((uint32_t)mem_size << 10)) - mem_mapping_set_exec(&dev->ems_mapping[mar & 0x3f], ram + virt_addr); - else - mem_mapping_set_exec(&dev->ems_mapping[mar & 0x3f], NULL); - mem_mapping_enable(&dev->ems_mapping[mar & 0x3f]); + mem_set_mem_state(base_addr, 0x4000, MEM_READ_INTERNAL | MEM_WRITE_INTERNAL); + virt_addr = get_addr(dev, base_addr, &dev->ems_mr[mar & 0x3f]); + dev->ems_mr[mar & 0x3f].enabled = 1; + dev->ems_mr[mar & 0x3f].virt_base = virt_addr; + if (indx < 24) + mem_mapping_disable(&dev->upper_mapping[indx]); + if (virt_addr < (mem_size << 10)) + mem_mapping_set_exec(&dev->ems_mapping[mar & 0x3f], ram + virt_addr); + else + mem_mapping_set_exec(&dev->ems_mapping[mar & 0x3f], NULL); + mem_mapping_enable(&dev->ems_mapping[mar & 0x3f]); } flushmmucache(); } - static void -set_global_EMS_state(headland_t *dev, int state) +set_global_EMS_state(headland_t *dev, UNUSED(int state)) { - int i; - - for (i = 0; i < 32; i++) { - hl_ems_update(dev, i | (((dev->cr[0] & 0x01) << 5) ^ 0x20)); - hl_ems_update(dev, i | ((dev->cr[0] & 0x01) << 5)); - } + for (uint8_t i = 0; i < 32; i++) { + hl_ems_update(dev, i | (((dev->cr[0] & 0x01) << 5) ^ 0x20)); + hl_ems_update(dev, i | ((dev->cr[0] & 0x01) << 5)); + } } - static void memmap_state_default(headland_t *dev, uint8_t ht_romcs) { mem_mapping_disable(&dev->mid_mapping); if (ht_romcs) - mem_set_mem_state(0x0e0000, 0x20000, MEM_READ_ROMCS | MEM_WRITE_ROMCS); + mem_set_mem_state(0x0e0000, 0x20000, MEM_READ_ROMCS | MEM_WRITE_ROMCS); else - mem_set_mem_state(0x0e0000, 0x20000, MEM_READ_EXTERNAL | MEM_WRITE_EXTERNAL); + mem_set_mem_state(0x0e0000, 0x20000, MEM_READ_EXTERNAL | MEM_WRITE_EXTERNAL); mem_set_mem_state(0xfe0000, 0x20000, MEM_READ_ROMCS | MEM_WRITE_ROMCS); mem_mapping_disable(&dev->shadow_mapping[0]); mem_mapping_disable(&dev->shadow_mapping[1]); } - static void memmap_state_update(headland_t *dev) { uint32_t addr; - int i; - uint8_t ht_cr0 = dev->cr[0]; - uint8_t ht_romcs = !(dev->cr[4] & 0x01); + uint8_t ht_cr0 = dev->cr[0]; + uint8_t ht_romcs = !(dev->cr[4] & 0x01); if (dev->revision <= 1) - ht_romcs = 1; + ht_romcs = 1; if (!(dev->cr[0] & 0x04)) - ht_cr0 &= ~0x18; + ht_cr0 &= ~0x18; - for (i = 0; i < 24; i++) { - addr = get_addr(dev, 0x40000 + (i << 14), NULL); - mem_mapping_set_exec(&dev->upper_mapping[i], addr < ((uint32_t)mem_size << 10) ? ram + addr : NULL); + for (uint8_t i = 0; i < 24; i++) { + addr = get_addr(dev, 0x40000 + (i << 14), NULL); + mem_mapping_set_exec(&dev->upper_mapping[i], addr < (mem_size << 10) ? ram + addr : NULL); } memmap_state_default(dev, ht_romcs); if (mem_size > 640) { - if (ht_cr0 & 0x04) { - mem_mapping_set_addr(&dev->mid_mapping, 0xA0000, 0x40000); - mem_mapping_set_exec(&dev->mid_mapping, ram + 0xA0000); - mem_mapping_disable(&dev->mid_mapping); - if (mem_size > 1024) { - mem_set_mem_state((mem_size << 10), 0x60000, MEM_READ_INTERNAL | MEM_WRITE_INTERNAL); - mem_mapping_set_addr(&dev->high_mapping, 0x100000, (mem_size - 1024) << 10); - mem_mapping_set_exec(&dev->high_mapping, ram + 0x100000); - } - } else { - /* 1 MB - 1 MB + 384k: RAM pointing to A0000-FFFFF - 1 MB + 384k: Any ram pointing 1 MB onwards. */ - /* First, do the addresses above 1 MB. */ - mem_mapping_set_addr(&dev->mid_mapping, 0x100000, mem_size > 1024 ? 0x60000 : (mem_size - 640) << 10); - mem_mapping_set_exec(&dev->mid_mapping, ram + 0xA0000); - if (mem_size > 1024) { - /* We have ram above 1 MB, we need to relocate that. */ - mem_set_mem_state((mem_size << 10), 0x60000, MEM_READ_EXTANY | MEM_WRITE_EXTANY); - mem_mapping_set_addr(&dev->high_mapping, 0x160000, (mem_size - 1024) << 10); - mem_mapping_set_exec(&dev->high_mapping, ram + 0x100000); - } - } + if (ht_cr0 & 0x04) { + mem_mapping_set_addr(&dev->mid_mapping, 0xA0000, 0x40000); + mem_mapping_set_exec(&dev->mid_mapping, ram + 0xA0000); + mem_mapping_disable(&dev->mid_mapping); + if (mem_size > 1024) { + mem_set_mem_state((mem_size << 10), 0x60000, MEM_READ_INTERNAL | MEM_WRITE_INTERNAL); + mem_mapping_set_addr(&dev->high_mapping, 0x100000, (mem_size - 1024) << 10); + mem_mapping_set_exec(&dev->high_mapping, ram + 0x100000); + } + } else { + /* 1 MB - 1 MB + 384k: RAM pointing to A0000-FFFFF + 1 MB + 384k: Any ram pointing 1 MB onwards. */ + /* First, do the addresses above 1 MB. */ + mem_mapping_set_addr(&dev->mid_mapping, 0x100000, mem_size > 1024 ? 0x60000 : (mem_size - 640) << 10); + mem_mapping_set_exec(&dev->mid_mapping, ram + 0xA0000); + if (mem_size > 1024) { + /* We have ram above 1 MB, we need to relocate that. */ + mem_set_mem_state((mem_size << 10), 0x60000, MEM_READ_EXTANY | MEM_WRITE_EXTANY); + mem_mapping_set_addr(&dev->high_mapping, 0x160000, (mem_size - 1024) << 10); + mem_mapping_set_exec(&dev->high_mapping, ram + 0x100000); + } + } } switch (ht_cr0) { - case 0x18: - if ((mem_size << 10) > 0xe0000) { - mem_set_mem_state(0x0e0000, 0x20000, MEM_READ_INTERNAL | MEM_WRITE_DISABLED); - mem_set_mem_state(0xfe0000, 0x20000, MEM_READ_INTERNAL | MEM_WRITE_DISABLED); + case 0x18: + if ((mem_size << 10) > 0xe0000) { + mem_set_mem_state(0x0e0000, 0x20000, MEM_READ_INTERNAL | MEM_WRITE_DISABLED); + mem_set_mem_state(0xfe0000, 0x20000, MEM_READ_INTERNAL | MEM_WRITE_DISABLED); - mem_mapping_set_addr(&dev->shadow_mapping[0], 0x0e0000, 0x20000); - mem_mapping_set_exec(&dev->shadow_mapping[0], ram + 0xe0000); - mem_mapping_set_addr(&dev->shadow_mapping[1], 0xfe0000, 0x20000); - mem_mapping_set_exec(&dev->shadow_mapping[1], ram + 0xe0000); - } else { - mem_mapping_disable(&dev->shadow_mapping[0]); - mem_mapping_disable(&dev->shadow_mapping[1]); - } - break; - case 0x10: - if ((mem_size << 10) > 0xf0000) { - mem_set_mem_state(0x0f0000, 0x10000, MEM_READ_INTERNAL | MEM_WRITE_DISABLED); - mem_set_mem_state(0xff0000, 0x10000, MEM_READ_INTERNAL | MEM_WRITE_DISABLED); + mem_mapping_set_addr(&dev->shadow_mapping[0], 0x0e0000, 0x20000); + mem_mapping_set_exec(&dev->shadow_mapping[0], ram + 0xe0000); + mem_mapping_set_addr(&dev->shadow_mapping[1], 0xfe0000, 0x20000); + mem_mapping_set_exec(&dev->shadow_mapping[1], ram + 0xe0000); + } else { + mem_mapping_disable(&dev->shadow_mapping[0]); + mem_mapping_disable(&dev->shadow_mapping[1]); + } + break; + case 0x10: + if ((mem_size << 10) > 0xf0000) { + mem_set_mem_state(0x0f0000, 0x10000, MEM_READ_INTERNAL | MEM_WRITE_DISABLED); + mem_set_mem_state(0xff0000, 0x10000, MEM_READ_INTERNAL | MEM_WRITE_DISABLED); - mem_mapping_set_addr(&dev->shadow_mapping[0], 0x0f0000, 0x10000); - mem_mapping_set_exec(&dev->shadow_mapping[0], ram + 0xf0000); - mem_mapping_set_addr(&dev->shadow_mapping[1], 0xff0000, 0x10000); - mem_mapping_set_exec(&dev->shadow_mapping[1], ram + 0xf0000); - } else { - mem_mapping_disable(&dev->shadow_mapping[0]); - mem_mapping_disable(&dev->shadow_mapping[1]); - } - break; - case 0x08: - if ((mem_size << 10) > 0xe0000) { - mem_set_mem_state(0x0e0000, 0x10000, MEM_READ_INTERNAL | MEM_WRITE_DISABLED); - mem_set_mem_state(0xfe0000, 0x10000, MEM_READ_INTERNAL | MEM_WRITE_DISABLED); + mem_mapping_set_addr(&dev->shadow_mapping[0], 0x0f0000, 0x10000); + mem_mapping_set_exec(&dev->shadow_mapping[0], ram + 0xf0000); + mem_mapping_set_addr(&dev->shadow_mapping[1], 0xff0000, 0x10000); + mem_mapping_set_exec(&dev->shadow_mapping[1], ram + 0xf0000); + } else { + mem_mapping_disable(&dev->shadow_mapping[0]); + mem_mapping_disable(&dev->shadow_mapping[1]); + } + break; + case 0x08: + if ((mem_size << 10) > 0xe0000) { + mem_set_mem_state(0x0e0000, 0x10000, MEM_READ_INTERNAL | MEM_WRITE_DISABLED); + mem_set_mem_state(0xfe0000, 0x10000, MEM_READ_INTERNAL | MEM_WRITE_DISABLED); - mem_mapping_set_addr(&dev->shadow_mapping[0], 0x0e0000, 0x10000); - mem_mapping_set_exec(&dev->shadow_mapping[0], ram + 0xe0000); - mem_mapping_set_addr(&dev->shadow_mapping[1], 0xfe0000, 0x10000); - mem_mapping_set_exec(&dev->shadow_mapping[1], ram + 0xe0000); - } else { - mem_mapping_disable(&dev->shadow_mapping[0]); - mem_mapping_disable(&dev->shadow_mapping[1]); - } - break; - case 0x00: - default: - mem_mapping_disable(&dev->shadow_mapping[0]); - mem_mapping_disable(&dev->shadow_mapping[1]); - break; + mem_mapping_set_addr(&dev->shadow_mapping[0], 0x0e0000, 0x10000); + mem_mapping_set_exec(&dev->shadow_mapping[0], ram + 0xe0000); + mem_mapping_set_addr(&dev->shadow_mapping[1], 0xfe0000, 0x10000); + mem_mapping_set_exec(&dev->shadow_mapping[1], ram + 0xe0000); + } else { + mem_mapping_disable(&dev->shadow_mapping[0]); + mem_mapping_disable(&dev->shadow_mapping[1]); + } + break; + case 0x00: + default: + mem_mapping_disable(&dev->shadow_mapping[0]); + mem_mapping_disable(&dev->shadow_mapping[1]); + break; } set_global_EMS_state(dev, ht_cr0 & 3); } - static void hl_write(uint16_t addr, uint8_t val, void *priv) { - headland_t *dev = (headland_t *)priv; + headland_t *dev = (headland_t *) priv; - switch(addr) { - case 0x01ec: - dev->ems_mr[dev->ems_mar & 0x3f].mr = val | 0xff00; - hl_ems_update(dev, dev->ems_mar & 0x3f); - if (dev->ems_mar & 0x80) - dev->ems_mar++; - break; + switch (addr) { + case 0x01ec: + dev->ems_mr[dev->ems_mar & 0x3f].mr = val | 0xff00; + hl_ems_update(dev, dev->ems_mar & 0x3f); + if (dev->ems_mar & 0x80) + dev->ems_mar++; + break; - case 0x01ed: - if (dev->revision > 0) - dev->cri = val; - break; + case 0x01ed: + if (dev->has_cri) + dev->cri = val; + break; - case 0x01ee: - dev->ems_mar = val; - break; + case 0x01ee: + dev->ems_mar = val; + break; - case 0x01ef: - switch(dev->cri) { - case 0: - dev->cr[0] = (val & 0x1f) | mem_conf_cr0[(mem_size > 640 ? mem_size : mem_size - 128) >> 9]; - memmap_state_update(dev); - break; + case 0x01ef: + switch (dev->cri & 0x07) { + case 0: + dev->cr[0] = (val & 0x1f) | mem_conf_cr0[(mem_size > 640 ? mem_size : mem_size - 128) >> 9]; + memmap_state_update(dev); + break; - case 1: - dev->cr[1] = (val & 0xbf) | mem_conf_cr1[(mem_size > 640 ? mem_size : mem_size - 128) >> 9]; - memmap_state_update(dev); - break; + case 1: + dev->cr[1] = (val & 0xbf) | mem_conf_cr1[(mem_size > 640 ? mem_size : mem_size - 128) >> 9]; + memmap_state_update(dev); + break; - case 2: - case 3: - case 5: - dev->cr[dev->cri] = val; - memmap_state_update(dev); - break; + case 2: + case 3: + dev->cr[dev->cri] = val; + memmap_state_update(dev); + break; - case 4: - dev->cr[4] = (dev->cr[4] & 0xf0) | (val & 0x0f); - memmap_state_update(dev); - break; + case 5: + if (dev->has_sleep) + dev->cr[dev->cri] = val; + else + dev->cr[dev->cri] = val & 0x0f; + memmap_state_update(dev); + break; - case 6: - if (dev->revision == 8) { - dev->cr[dev->cri] = (val & 0xfe) | (mem_size > 8192 ? 1 : 0); - memmap_state_update(dev); - } - break; + case 4: + dev->cr[4] = (dev->cr[4] & 0xf0) | (val & 0x0f); + memmap_state_update(dev); + break; - default: - break; - } - break; + case 6: + if (dev->revision == 8) { + dev->cr[dev->cri] = (val & 0xfe) | (mem_size > 8192 ? 1 : 0); + memmap_state_update(dev); + } + break; - default: - break; + default: + break; + } + break; + + default: + break; } } - static void hl_writew(uint16_t addr, uint16_t val, void *priv) { - headland_t *dev = (headland_t *)priv; + headland_t *dev = (headland_t *) priv; - switch(addr) { - case 0x01ec: - dev->ems_mr[dev->ems_mar & 0x3f].mr = val; - hl_ems_update(dev, dev->ems_mar & 0x3f); - if (dev->ems_mar & 0x80) - dev->ems_mar++; - break; + switch (addr) { + case 0x01ec: + dev->ems_mr[dev->ems_mar & 0x3f].mr = val; + hl_ems_update(dev, dev->ems_mar & 0x3f); + if (dev->ems_mar & 0x80) + dev->ems_mar++; + break; - default: - break; + default: + break; } } - static void hl_writel(uint16_t addr, uint32_t val, void *priv) { @@ -406,81 +422,78 @@ hl_writel(uint16_t addr, uint32_t val, void *priv) hl_writew(addr + 2, val >> 16, priv); } - static uint8_t hl_read(uint16_t addr, void *priv) { - headland_t *dev = (headland_t *)priv; - uint8_t ret = 0xff; + headland_t *dev = (headland_t *) priv; + uint8_t ret = 0xff; - switch(addr) { - case 0x01ec: - ret = (uint8_t)dev->ems_mr[dev->ems_mar & 0x3f].mr; - if (dev->ems_mar & 0x80) - dev->ems_mar++; - break; + switch (addr) { + case 0x01ec: + ret = (uint8_t) dev->ems_mr[dev->ems_mar & 0x3f].mr; + if (dev->ems_mar & 0x80) + dev->ems_mar++; + break; - case 0x01ed: - if (dev->revision > 0) - ret = dev->cri; - break; + case 0x01ed: + if (dev->has_cri) + ret = dev->cri; + break; - case 0x01ee: - ret = dev->ems_mar; - break; + case 0x01ee: + ret = dev->ems_mar; + break; - case 0x01ef: - switch(dev->cri) { - case 0: - ret = (dev->cr[0] & 0x1f) | mem_conf_cr0[(mem_size > 640 ? mem_size : mem_size - 128) >> 9]; - break; + case 0x01ef: + switch (dev->cri & 0x07) { + case 0: + ret = (dev->cr[0] & 0x1f) | mem_conf_cr0[(mem_size > 640 ? mem_size : mem_size - 128) >> 9]; + break; - case 1: - ret = (dev->cr[1] & 0xbf) | mem_conf_cr1[(mem_size > 640 ? mem_size : mem_size - 128) >> 9]; - break; + case 1: + ret = (dev->cr[1] & 0xbf) | mem_conf_cr1[(mem_size > 640 ? mem_size : mem_size - 128) >> 9]; + break; - case 6: - if (dev->revision == 8) - ret = (dev->cr[6] & 0xfe) | (mem_size > 8192 ? 1 : 0); - else - ret = 0; - break; + case 6: + if (dev->revision == 8) + ret = (dev->cr[6] & 0xfe) | (mem_size > 8192 ? 1 : 0); + else + ret = 0; + break; - default: - ret = dev->cr[dev->cri]; - break; - } - break; + default: + ret = dev->cr[dev->cri]; + break; + } + break; - default: - break; + default: + break; } return ret; } - static uint16_t hl_readw(uint16_t addr, void *priv) { - headland_t *dev = (headland_t *)priv; - uint16_t ret = 0xffff; + headland_t *dev = (headland_t *) priv; + uint16_t ret = 0xffff; - switch(addr) { - case 0x01ec: - ret = dev->ems_mr[dev->ems_mar & 0x3f].mr | ((dev->cr[4] & 0x80) ? 0xf000 : 0xfc00); - if (dev->ems_mar & 0x80) - dev->ems_mar++; - break; + switch (addr) { + case 0x01ec: + ret = dev->ems_mr[dev->ems_mar & 0x3f].mr | ((dev->cr[4] & 0x80) ? 0xf000 : 0xfc00); + if (dev->ems_mar & 0x80) + dev->ems_mar++; + break; - default: - break; + default: + break; } return ret; } - static uint32_t hl_readl(uint16_t addr, void *priv) { @@ -492,128 +505,122 @@ hl_readl(uint16_t addr, void *priv) return ret; } - static uint8_t mem_read_b(uint32_t addr, void *priv) { - headland_mr_t *mr = (headland_mr_t *) priv; - headland_t *dev = mr->headland; - uint8_t ret = 0xff; + headland_mr_t *mr = (headland_mr_t *) priv; + headland_t *dev = mr->headland; + uint8_t ret = 0xff; addr = get_addr(dev, addr, mr); - if (addr < ((uint32_t)mem_size << 10)) - ret = ram[addr]; + if (addr < (mem_size << 10)) + ret = ram[addr]; return ret; } - static uint16_t mem_read_w(uint32_t addr, void *priv) { - headland_mr_t *mr = (headland_mr_t *) priv; - headland_t *dev = mr->headland; - uint16_t ret = 0xffff; + headland_mr_t *mr = (headland_mr_t *) priv; + headland_t *dev = mr->headland; + uint16_t ret = 0xffff; addr = get_addr(dev, addr, mr); - if (addr < ((uint32_t)mem_size << 10)) - ret = *(uint16_t *)&ram[addr]; + if (addr < (mem_size << 10)) + ret = *(uint16_t *) &ram[addr]; return ret; } - static uint32_t mem_read_l(uint32_t addr, void *priv) { - headland_mr_t *mr = (headland_mr_t *) priv; - headland_t *dev = mr->headland; - uint32_t ret = 0xffffffff; + headland_mr_t *mr = (headland_mr_t *) priv; + headland_t *dev = mr->headland; + uint32_t ret = 0xffffffff; addr = get_addr(dev, addr, mr); - if (addr < ((uint32_t)mem_size << 10)) - ret = *(uint32_t *)&ram[addr]; + if (addr < (mem_size << 10)) + ret = *(uint32_t *) &ram[addr]; return ret; } - static void mem_write_b(uint32_t addr, uint8_t val, void *priv) { - headland_mr_t *mr = (headland_mr_t *) priv; - headland_t *dev = mr->headland; + headland_mr_t *mr = (headland_mr_t *) priv; + headland_t *dev = mr->headland; addr = get_addr(dev, addr, mr); - if (addr < ((uint32_t)mem_size << 10)) - ram[addr] = val; + if (addr < (mem_size << 10)) + ram[addr] = val; } - static void mem_write_w(uint32_t addr, uint16_t val, void *priv) { - headland_mr_t *mr = (headland_mr_t *) priv; - headland_t *dev = mr->headland; + headland_mr_t *mr = (headland_mr_t *) priv; + headland_t *dev = mr->headland; addr = get_addr(dev, addr, mr); - if (addr < ((uint32_t)mem_size << 10)) - *(uint16_t *)&ram[addr] = val; + if (addr < (mem_size << 10)) + *(uint16_t *) &ram[addr] = val; } - static void mem_write_l(uint32_t addr, uint32_t val, void *priv) { - headland_mr_t *mr = (headland_mr_t *) priv; - headland_t *dev = mr->headland; + headland_mr_t *mr = (headland_mr_t *) priv; + headland_t *dev = mr->headland; addr = get_addr(dev, addr, mr); - if (addr < ((uint32_t)mem_size << 10)) - *(uint32_t *)&ram[addr] = val; + if (addr < (mem_size << 10)) + *(uint32_t *) &ram[addr] = val; } - static void headland_close(void *priv) { - headland_t *dev = (headland_t *)priv; + headland_t *dev = (headland_t *) priv; free(dev); } - static void * headland_init(const device_t *info) { headland_t *dev; - int ht386 = 0; - uint32_t i; + int ht386 = 0; dev = (headland_t *) malloc(sizeof(headland_t)); memset(dev, 0x00, sizeof(headland_t)); - dev->revision = info->local; + dev->has_cri = (info->local & HEADLAND_HAS_CRI); + dev->has_sleep = (info->local & HEADLAND_HAS_SLEEP); + dev->revision = info->local & HEADLAND_REV_MASK; if (dev->revision > 0) - ht386 = 1; + ht386 = 1; + dev->cr[0] = 0x04; dev->cr[4] = dev->revision << 4; - if (ht386) - device_add(&port_92_inv_device); + if (ht386) + device_add(&port_92_inv_device); io_sethandler(0x01ec, 4, - hl_read,hl_readw,hl_readl, hl_write,hl_writew,hl_writel, dev); + hl_read, hl_readw, hl_readl, hl_write, hl_writew, hl_writel, dev); - dev->null_mr.valid = 0; - dev->null_mr.mr = 0xff; + dev->null_mr.valid = 0; + dev->null_mr.mr = 0xff; dev->null_mr.headland = dev; - for (i = 0; i < 64; i++) { - dev->ems_mr[i].valid = 1; - dev->ems_mr[i].mr = 0x00; - dev->ems_mr[i].headland = dev; + for (uint8_t i = 0; i < 64; i++) { + dev->ems_mr[i].valid = 1; + dev->ems_mr[i].mr = 0x00; + dev->ems_mr[i].headland = dev; } /* Turn off mem.c mappings. */ @@ -622,105 +629,162 @@ headland_init(const device_t *info) mem_mapping_disable(&ram_high_mapping); mem_mapping_add(&dev->low_mapping, 0, 0x40000, - mem_read_b, mem_read_w, mem_read_l, - mem_write_b, mem_write_w, mem_write_l, - ram, MEM_MAPPING_INTERNAL, &dev->null_mr); + mem_read_b, mem_read_w, mem_read_l, + mem_write_b, mem_write_w, mem_write_l, + ram, MEM_MAPPING_INTERNAL, &dev->null_mr); if (mem_size > 640) { - mem_mapping_add(&dev->mid_mapping, 0xa0000, 0x40000, - mem_read_b, mem_read_w, mem_read_l, - mem_write_b, mem_write_w, mem_write_l, - ram + 0xa0000, MEM_MAPPING_INTERNAL, &dev->null_mr); - mem_mapping_disable(&dev->mid_mapping); + mem_mapping_add(&dev->mid_mapping, 0xa0000, 0x60000, + mem_read_b, mem_read_w, mem_read_l, + mem_write_b, mem_write_w, mem_write_l, + ram + 0xa0000, MEM_MAPPING_INTERNAL, &dev->null_mr); + mem_mapping_disable(&dev->mid_mapping); } if (mem_size > 1024) { - mem_mapping_add(&dev->high_mapping, 0x100000, ((mem_size-1024)*1024), - mem_read_b, mem_read_w, mem_read_l, - mem_write_b, mem_write_w, mem_write_l, - ram + 0x100000, MEM_MAPPING_INTERNAL, &dev->null_mr); - mem_mapping_enable(&dev->high_mapping); + mem_mapping_add(&dev->high_mapping, 0x100000, ((mem_size - 1024) * 1024), + mem_read_b, mem_read_w, mem_read_l, + mem_write_b, mem_write_w, mem_write_l, + ram + 0x100000, MEM_MAPPING_INTERNAL, &dev->null_mr); + mem_mapping_enable(&dev->high_mapping); } - for (i = 0; i < 24; i++) { - mem_mapping_add(&dev->upper_mapping[i], - 0x40000 + (i << 14), 0x4000, - mem_read_b, mem_read_w, mem_read_l, - mem_write_b, mem_write_w, mem_write_l, - mem_size > (256 + (i << 4)) ? (ram + 0x40000 + (i << 14)) : NULL, - MEM_MAPPING_INTERNAL, &dev->null_mr); - mem_mapping_enable(&dev->upper_mapping[i]); + for (uint8_t i = 0; i < 24; i++) { + mem_mapping_add(&dev->upper_mapping[i], + 0x40000 + (i << 14), 0x4000, + mem_read_b, mem_read_w, mem_read_l, + mem_write_b, mem_write_w, mem_write_l, + mem_size > (256 + (i << 4)) ? (ram + 0x40000 + (i << 14)) : NULL, + MEM_MAPPING_INTERNAL, &dev->null_mr); + mem_mapping_enable(&dev->upper_mapping[i]); } mem_mapping_add(&dev->shadow_mapping[0], - 0xe0000, 0x20000, - mem_read_b, mem_read_w, mem_read_l, - mem_write_b, mem_write_w, mem_write_l, - ((mem_size << 10) > 0xe0000) ? (ram + 0xe0000) : NULL, - MEM_MAPPING_INTERNAL, &dev->null_mr); + 0xe0000, 0x20000, + mem_read_b, mem_read_w, mem_read_l, + mem_write_b, mem_write_w, mem_write_l, + ((mem_size << 10) > 0xe0000) ? (ram + 0xe0000) : NULL, + MEM_MAPPING_INTERNAL, &dev->null_mr); mem_mapping_disable(&dev->shadow_mapping[0]); mem_mapping_add(&dev->shadow_mapping[1], - 0xfe0000, 0x20000, - mem_read_b, mem_read_w, mem_read_l, - mem_write_b, mem_write_w, mem_write_l, - ((mem_size << 10) > 0xe0000) ? (ram + 0xe0000) : NULL, - MEM_MAPPING_INTERNAL, &dev->null_mr); + 0xfe0000, 0x20000, + mem_read_b, mem_read_w, mem_read_l, + mem_write_b, mem_write_w, mem_write_l, + ((mem_size << 10) > 0xe0000) ? (ram + 0xe0000) : NULL, + MEM_MAPPING_INTERNAL, &dev->null_mr); mem_mapping_disable(&dev->shadow_mapping[1]); - for (i = 0; i < 64; i++) { - dev->ems_mr[i].mr = 0x00; - mem_mapping_add(&dev->ems_mapping[i], - ((i & 31) + ((i & 31) >= 24 ? 24 : 16)) << 14, 0x04000, - mem_read_b, mem_read_w, mem_read_l, - mem_write_b, mem_write_w, mem_write_l, - ram + (((i & 31) + ((i & 31) >= 24 ? 24 : 16)) << 14), - MEM_MAPPING_INTERNAL, &dev->ems_mr[i]); - mem_mapping_disable(&dev->ems_mapping[i]); + for (uint8_t i = 0; i < 64; i++) { + dev->ems_mr[i].mr = 0x00; + mem_mapping_add(&dev->ems_mapping[i], + ((i & 31) + ((i & 31) >= 24 ? 24 : 16)) << 14, 0x04000, + mem_read_b, mem_read_w, mem_read_l, + mem_write_b, mem_write_w, mem_write_l, + ram + (((i & 31) + ((i & 31) >= 24 ? 24 : 16)) << 14), + MEM_MAPPING_INTERNAL, &dev->ems_mr[i]); + mem_mapping_disable(&dev->ems_mapping[i]); } memmap_state_update(dev); - return(dev); + return dev; } - const device_t headland_gc10x_device = { - "Headland GC101/102/103", - "headland_gc10x", - 0, - 0, - headland_init, headland_close, NULL, - { NULL }, NULL, NULL, - NULL + .name = "Headland GC101/102/103", + .internal_name = "headland_gc10x", + .flags = 0, + .local = HEADLAND_GC103, + .init = headland_init, + .close = headland_close, + .reset = NULL, + { .available = NULL }, + .speed_changed = NULL, + .force_redraw = NULL, + .config = NULL +}; + +const device_t headland_gc113_device = { + .name = "Headland GC101/102/113", + .internal_name = "headland_gc113", + .flags = 0, + .local = HEADLAND_GC113, + .init = headland_init, + .close = headland_close, + .reset = NULL, + { .available = NULL }, + .speed_changed = NULL, + .force_redraw = NULL, + .config = NULL }; const device_t headland_ht18a_device = { - "Headland HT18 Rev. A", - "headland_ht18a", - 0, - 1, - headland_init, headland_close, NULL, - { NULL }, NULL, NULL, - NULL + .name = "Headland HT18 Rev. A", + .internal_name = "headland_ht18a", + .flags = 0, + .local = HEADLAND_HT18_A, + .init = headland_init, + .close = headland_close, + .reset = NULL, + { .available = NULL }, + .speed_changed = NULL, + .force_redraw = NULL, + .config = NULL }; const device_t headland_ht18b_device = { - "Headland HT18 Rev. B", - "headland_ht18b", - 0, - 2, - headland_init, headland_close, NULL, - { NULL }, NULL, NULL, - NULL + .name = "Headland HT18 Rev. B", + .internal_name = "headland_ht18b", + .flags = 0, + .local = HEADLAND_HT18_B, + .init = headland_init, + .close = headland_close, + .reset = NULL, + { .available = NULL }, + .speed_changed = NULL, + .force_redraw = NULL, + .config = NULL }; const device_t headland_ht18c_device = { - "Headland HT18 Rev. C", - "headland_ht18c", - 0, - 8, - headland_init, headland_close, NULL, - { NULL }, NULL, NULL, - NULL + .name = "Headland HT18 Rev. C", + .internal_name = "headland_ht18c", + .flags = 0, + .local = HEADLAND_HT18_C, + .init = headland_init, + .close = headland_close, + .reset = NULL, + { .available = NULL }, + .speed_changed = NULL, + .force_redraw = NULL, + .config = NULL +}; + +const device_t headland_ht21c_d_device = { + .name = "Headland HT21 Rev. C/D", + .internal_name = "headland_ht21cd", + .flags = 0, + .local = HEADLAND_HT21_C_D, + .init = headland_init, + .close = headland_close, + .reset = NULL, + { .available = NULL }, + .speed_changed = NULL, + .force_redraw = NULL, + .config = NULL +}; + +const device_t headland_ht21e_device = { + .name = "Headland HT21 Rev. E", + .internal_name = "headland_ht21", + .flags = 0, + .local = HEADLAND_HT21_E, + .init = headland_init, + .close = headland_close, + .reset = NULL, + { .available = NULL }, + .speed_changed = NULL, + .force_redraw = NULL, + .config = NULL }; diff --git a/src/chipset/ims8848.c b/src/chipset/ims8848.c index d96c53508..3e86a44e1 100644 --- a/src/chipset/ims8848.c +++ b/src/chipset/ims8848.c @@ -1,20 +1,20 @@ /* - * 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. + * 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. + * This file is part of the 86Box distribution. * - * Implementation of the IMS 8848/8849 chipset. + * Implementation of the IMS 8848/8849 chipset. * * * - * Authors: Miran Grca, - * Tiseno100, + * Authors: Miran Grca, + * Tiseno100, * - * Copyright 2021 Miran Grca. - * Copyright 2021 Tiseno100. + * Copyright 2021 Miran Grca. + * Copyright 2021 Tiseno100. */ #include #include @@ -30,10 +30,11 @@ #include <86box/mem.h> #include <86box/smram.h> #include <86box/pci.h> +#include <86box/pic.h> +#include <86box/plat_unused.h> #include <86box/port_92.h> #include <86box/chipset.h> - /* IMS 884x Configuration Registers @@ -42,158 +43,156 @@ By: Tiseno100, Miran Grca(OBattler) Register 00h: - Bit 3: F0000-FFFFF Shadow Enable - Bit 2: E0000-EFFFF Shadow Enable - Bit 0: ???? + Bit 3: F0000-FFFFF Shadow Enable + Bit 2: E0000-EFFFF Shadow Enable + Bit 0: ???? Register 04h: - Bit 3: Cache Write Hit Wait State - Bit 2: Cache Read Hit Wait State + Bit 3: Cache Write Hit Wait State + Bit 2: Cache Read Hit Wait State Register 06h: - Bit 3: System BIOS Cacheable (1: Yes / 0: No) - Bit 1: Power Management Mode (1: IRQ / 0: SMI#) + Bit 3: System BIOS Cacheable (1: Yes / 0: No) + Bit 1: Power Management Mode (1: IRQ / 0: SMI#) Register 08h: - Bit 2: System BIOS Shadow Write (1: Enable / 0: Disable) - Bit 1: System BIOS Shadow Read? + Bit 2: System BIOS Shadow Write (1: Enable / 0: Disable) + Bit 1: System BIOS Shadow Read? Register 0Dh: - Bit 0: IO 100H-3FFH Idle Detect (1: Enable / 0: Disable) + Bit 0: IO 100H-3FFH Idle Detect (1: Enable / 0: Disable) Register 0Eh: - Bit 7: DMA & Local Bus Idle Detect (1: Enable / 0: Disable) - Bit 6: Floppy Disk Idle Detect (1: Enable / 0: Disable) - Bit 5: IDE Idle Detect (1: Enable / 0: Disable) - Bit 4: Serial Port Idle Detect (1: Enable / 0: Disable) - Bit 3: Parallel Port Idle Detect (1: Enable / 0: Disable) - Bit 2: Keyboard Idle Detect (1: Enable / 0: Disable) - Bit 1: Video Idle Detect (1: Enable / 0: Disable) + Bit 7: DMA & Local Bus Idle Detect (1: Enable / 0: Disable) + Bit 6: Floppy Disk Idle Detect (1: Enable / 0: Disable) + Bit 5: IDE Idle Detect (1: Enable / 0: Disable) + Bit 4: Serial Port Idle Detect (1: Enable / 0: Disable) + Bit 3: Parallel Port Idle Detect (1: Enable / 0: Disable) + Bit 2: Keyboard Idle Detect (1: Enable / 0: Disable) + Bit 1: Video Idle Detect (1: Enable / 0: Disable) Register 12h: - Bits 3-2: Power Saving Timer (00 = 1 MIN, 01 = 3 MIN, 10 = 5 MIN, 11 = 8 MIN) - Bit 1: Base Memory (1: 512KB / 0: 640KB) + Bits 3-2: Power Saving Timer (00 = 1 MIN, 01 = 3 MIN, 10 = 5 MIN, 11 = 8 MIN) + Bit 1: Base Memory (1: 512KB / 0: 640KB) Register 1Ah: - Bit 3: Cache Write Hit W/S For PCI (1: Enabled / 0: Disable) - Bit 2: Cache Read Hit W/S For PCI (1: Enabled / 0: Disable) - Bit 1: VESA Clock Skew (1: 4ns/6ns, 0: No Delay/2ns) + Bit 3: Cache Write Hit W/S For PCI (1: Enabled / 0: Disable) + Bit 2: Cache Read Hit W/S For PCI (1: Enabled / 0: Disable) + Bit 1: VESA Clock Skew (1: 4ns/6ns, 0: No Delay/2ns) Register 1Bh: - Bit 6: Enable SMRAM (always at 30000-4FFFF) in SMM - Bit 5: ???? - Bit 4: Software SMI# - Bit 3: DC000-DFFFF Shadow Enable - Bit 2: D8000-DBFFF Shadow Enable - Bit 1: D4000-D7FFF Shadow Enable - Bit 0: D0000-D3FFF Shadow Enable + Bit 6: Enable SMRAM (always at 30000-4FFFF) in SMM + Bit 5: ???? + Bit 4: Software SMI# + Bit 3: DC000-DFFFF Shadow Enable + Bit 2: D8000-DBFFF Shadow Enable + Bit 1: D4000-D7FFF Shadow Enable + Bit 0: D0000-D3FFF Shadow Enable Register 1Ch: - Bits 7-4: INTA IRQ routing (0 = disabled, 1 to F = IRQ) - Bit 3: CC000-CFFFF Shadow Enable - Bit 2: C8000-CBFFF Shadow Enable - Bit 1: C4000-C7FFF Shadow Enable - Bit 0: C0000-C3FFF Shadow Enable + Bits 7-4: INTA IRQ routing (0 = disabled, 1 to F = IRQ) + Bit 3: CC000-CFFFF Shadow Enable + Bit 2: C8000-CBFFF Shadow Enable + Bit 1: C4000-C7FFF Shadow Enable + Bit 0: C0000-C3FFF Shadow Enable Register 1Dh: - Bits 7-4: INTB IRQ routing (0 = disabled, 1 to F = IRQ) + Bits 7-4: INTB IRQ routing (0 = disabled, 1 to F = IRQ) Register 1Eh: - Bits 7-4: INTC IRQ routing (0 = disabled, 1 to F = IRQ) - Bit 1: C4000-C7FFF Cacheable - Bit 0: C0000-C3FFF Cacheable + Bits 7-4: INTC IRQ routing (0 = disabled, 1 to F = IRQ) + Bit 1: C4000-C7FFF Cacheable + Bit 0: C0000-C3FFF Cacheable Register 21h: - Bits 7-4: INTD IRQ routing (0 = disabled, 1 to F = IRQ) + Bits 7-4: INTD IRQ routing (0 = disabled, 1 to F = IRQ) Register 22h: - Bit 5: Local Bus Master #2 select (0 = VESA, 1 = PCI) - Bit 4: Local Bus Master #1 select (0 = VESA, 1 = PCI) - Bits 1-0: Internal HADS# Delay Always (00 = No Delay, 01 = 1 Clk, 10 = 2 Clks) + Bit 5: Local Bus Master #2 select (0 = VESA, 1 = PCI) + Bit 4: Local Bus Master #1 select (0 = VESA, 1 = PCI) + Bits 1-0: Internal HADS# Delay Always (00 = No Delay, 01 = 1 Clk, 10 = 2 Clks) Register 23h: - Bit 7: Seven Bits Tag (1: Enabled / 0: Disable) - Bit 3: Extend LBRDY#(VL Master) (1: Enabled / 0: Disable) - Bit 2: Sync LRDY#(VL Slave) (1: Enabled / 0: Disable) - Bit 0: HADS# Delay After LB. Cycle (1: Enabled / 0: Disable) + Bit 7: Seven Bits Tag (1: Enabled / 0: Disable) + Bit 3: Extend LBRDY#(VL Master) (1: Enabled / 0: Disable) + Bit 2: Sync LRDY#(VL Slave) (1: Enabled / 0: Disable) + Bit 0: HADS# Delay After LB. Cycle (1: Enabled / 0: Disable) */ -typedef struct -{ - uint8_t idx, access_data, - regs[256], pci_conf[256]; +typedef struct ims8848_t { + uint8_t idx; + uint8_t access_data; + uint8_t pci_slot; + uint8_t pad; - smram_t *smram; + uint8_t regs[256]; + uint8_t pci_conf[256]; + + smram_t *smram; } ims8848_t; - #ifdef ENABLE_IMS8848_LOG int ims8848_do_log = ENABLE_IMS8848_LOG; - static void ims8848_log(const char *fmt, ...) { va_list ap; if (ims8848_do_log) { - va_start(ap, fmt); - pclog_ex(fmt, ap); - va_end(ap); + va_start(ap, fmt); + pclog_ex(fmt, ap); + va_end(ap); } } #else -#define ims8848_log(fmt, ...) +# define ims8848_log(fmt, ...) #endif - /* Shadow write always enabled, 1B and 1C control C000-DFFF read. */ static void ims8848_recalc(ims8848_t *dev) { - int i, state_on; + int state_on; uint32_t base; ims8848_log("SHADOW: 00 = %02X, 08 = %02X, 1B = %02X, 1C = %02X\n", - dev->regs[0x00], dev->regs[0x08], dev->regs[0x1b], dev->regs[0x1c]); + dev->regs[0x00], dev->regs[0x08], dev->regs[0x1b], dev->regs[0x1c]); state_on = MEM_READ_INTERNAL; state_on |= (dev->regs[0x08] & 0x04) ? MEM_WRITE_INTERNAL : MEM_WRITE_EXTANY; - for (i = 0; i < 2; i++) { - base = 0xe0000 + (i << 16); - if (dev->regs[0x00] & (1 << (i + 2))) - mem_set_mem_state_both(base, 0x10000, state_on); - else - mem_set_mem_state_both(base, 0x10000, MEM_READ_EXTANY | MEM_WRITE_INTERNAL); + for (uint8_t i = 0; i < 2; i++) { + base = 0xe0000 + (i << 16); + if (dev->regs[0x00] & (1 << (i + 2))) + mem_set_mem_state_both(base, 0x10000, state_on); + else + mem_set_mem_state_both(base, 0x10000, MEM_READ_EXTANY | MEM_WRITE_INTERNAL); } - for (i = 0; i < 4; i++) { - base = 0xc0000 + (i << 14); - if (dev->regs[0x1c] & (1 << i)) - mem_set_mem_state_both(base, 0x4000, MEM_READ_INTERNAL | MEM_WRITE_INTERNAL); - else - mem_set_mem_state_both(base, 0x4000, MEM_READ_EXTANY | MEM_WRITE_INTERNAL); + for (uint8_t i = 0; i < 4; i++) { + base = 0xc0000 + (i << 14); + if (dev->regs[0x1c] & (1 << i)) + mem_set_mem_state_both(base, 0x4000, MEM_READ_INTERNAL | MEM_WRITE_INTERNAL); + else + mem_set_mem_state_both(base, 0x4000, MEM_READ_EXTANY | MEM_WRITE_INTERNAL); - base = 0xd0000 + (i << 14); - if (dev->regs[0x1b] & (1 << i)) - mem_set_mem_state_both(base, 0x4000, MEM_READ_INTERNAL | MEM_WRITE_INTERNAL); - else - mem_set_mem_state_both(base, 0x4000, MEM_READ_EXTANY | MEM_WRITE_INTERNAL); + base = 0xd0000 + (i << 14); + if (dev->regs[0x1b] & (1 << i)) + mem_set_mem_state_both(base, 0x4000, MEM_READ_INTERNAL | MEM_WRITE_INTERNAL); + else + mem_set_mem_state_both(base, 0x4000, MEM_READ_EXTANY | MEM_WRITE_INTERNAL); } flushmmucache_nopc(); } - static void ims8848_base_memory(ims8848_t *dev) { /* We can use the proper mem_set_access to handle that. */ - mem_set_mem_state_both(0x80000, 0x20000, (dev->regs[0x12] & 2) ? - (MEM_READ_DISABLED | MEM_WRITE_DISABLED) : (MEM_READ_INTERNAL | MEM_WRITE_INTERNAL)); + mem_set_mem_state_both(0x80000, 0x20000, (dev->regs[0x12] & 2) ? (MEM_READ_DISABLED | MEM_WRITE_DISABLED) : (MEM_READ_INTERNAL | MEM_WRITE_INTERNAL)); } - static void ims8848_smram(ims8848_t *dev) { @@ -202,137 +201,148 @@ ims8848_smram(ims8848_t *dev) smram_enable(dev->smram, 0x00030000, 0x00030000, 0x20000, dev->regs[0x1b] & 0x40, 1); } - static void ims8848_write(uint16_t addr, uint8_t val, void *priv) { ims8848_t *dev = (ims8848_t *) priv; - uint8_t old = dev->regs[dev->idx]; + uint8_t old = dev->regs[dev->idx]; switch (addr) { - case 0x22: - ims8848_log("[W] IDX = %02X\n", val); - dev->idx = val; - break; - case 0x23: - ims8848_log("[W] IDX IN = %02X\n", val); - if (((val & 0x0f) == ((dev->idx >> 4) & 0x0f)) && ((val & 0xf0) == ((dev->idx << 4) & 0xf0))) - dev->access_data = 1; - break; - case 0x24: - ims8848_log("[W] [%i] REG %02X = %02X\n", dev->access_data, dev->idx, val); - if (dev->access_data) { - dev->regs[dev->idx] = val; - switch (dev->idx) { - case 0x00: case 0x08: case 0x1b: case 0x1c: - /* Shadow RAM */ - ims8848_recalc(dev); - if (dev->idx == 0x1b) { - ims8848_smram(dev); - if (!(old & 0x10) && (val & 0x10)) - smi_line = 1; - } else if (dev->idx == 0x1c) - pci_set_irq_routing(PCI_INTA, (val >> 4) ? (val >> 4) : PCI_IRQ_DISABLED); - break; + case 0x22: + ims8848_log("[W] IDX = %02X\n", val); + dev->idx = val; + break; + case 0x23: + ims8848_log("[W] IDX IN = %02X\n", val); + if (((val & 0x0f) == ((dev->idx >> 4) & 0x0f)) && ((val & 0xf0) == ((dev->idx << 4) & 0xf0))) + dev->access_data = 1; + break; + case 0x24: + ims8848_log("[W] [%i] REG %02X = %02X\n", dev->access_data, dev->idx, val); + if (dev->access_data) { + dev->regs[dev->idx] = val; + switch (dev->idx) { + case 0x00: + case 0x08: + case 0x1b: + case 0x1c: + /* Shadow RAM */ + ims8848_recalc(dev); + if (dev->idx == 0x1b) { + ims8848_smram(dev); + if (!(old & 0x10) && (val & 0x10)) + smi_raise(); + } else if (dev->idx == 0x1c) + pci_set_irq_routing(PCI_INTA, (val >> 4) ? (val >> 4) : PCI_IRQ_DISABLED); + break; - case 0x1d: case 0x1e: - pci_set_irq_routing(PCI_INTB + (dev->idx - 0x1d), (val >> 4) ? (val >> 4) : PCI_IRQ_DISABLED); - break; - case 0x21: - pci_set_irq_routing(PCI_INTD, (val >> 4) ? (val >> 4) : PCI_IRQ_DISABLED); - break; + case 0x1d: + case 0x1e: + pci_set_irq_routing(PCI_INTB + (dev->idx - 0x1d), (val >> 4) ? (val >> 4) : PCI_IRQ_DISABLED); + break; + case 0x21: + pci_set_irq_routing(PCI_INTD, (val >> 4) ? (val >> 4) : PCI_IRQ_DISABLED); + break; - case 0x12: - /* Base Memory */ - ims8848_base_memory(dev); - break; - } - dev->access_data = 0; - } - break; + case 0x12: + /* Base Memory */ + ims8848_base_memory(dev); + break; + + default: + break; + } + dev->access_data = 0; + } + break; + + default: + break; } } - static uint8_t ims8848_read(uint16_t addr, void *priv) { - uint8_t ret = 0xff; + uint8_t ret = 0xff; ims8848_t *dev = (ims8848_t *) priv; #ifdef ENABLE_IMS8848_LOG uint8_t old_ad = dev->access_data; #endif switch (addr) { - case 0x22: - ims8848_log("[R] IDX = %02X\n", ret); - ret = dev->idx; - break; - case 0x23: - ims8848_log("[R] IDX IN = %02X\n", ret); - ret = (dev->idx >> 4) | (dev->idx << 4); - break; - case 0x24: - if (dev->access_data) { - ret = dev->regs[dev->idx]; - dev->access_data = 0; - } - ims8848_log("[R] [%i] REG %02X = %02X\n", old_ad, dev->idx, ret); - break; + case 0x22: + ims8848_log("[R] IDX = %02X\n", ret); + ret = dev->idx; + break; + case 0x23: + ims8848_log("[R] IDX IN = %02X\n", ret); + ret = (dev->idx >> 4) | (dev->idx << 4); + break; + case 0x24: + if (dev->access_data) { + ret = dev->regs[dev->idx]; + dev->access_data = 0; + } + ims8848_log("[R] [%i] REG %02X = %02X\n", old_ad, dev->idx, ret); + break; + default: + break; } return ret; } - static void ims8849_pci_write(int func, int addr, uint8_t val, void *priv) { - ims8848_t *dev = (ims8848_t *)priv; + ims8848_t *dev = (ims8848_t *) priv; ims8848_log("IMS 884x-PCI: dev->regs[%02x] = %02x POST: %02x\n", addr, val, inb(0x80)); - if (func == 0) switch (addr) { - case 0x04: - dev->pci_conf[addr] = val; - break; + if (func == 0) + switch (addr) { + case 0x04: + dev->pci_conf[addr] = val; + break; - case 0x05: - dev->pci_conf[addr] = val & 3; - break; + case 0x05: + dev->pci_conf[addr] = val & 3; + break; - case 0x07: - dev->pci_conf[addr] &= val & 0xf7; - break; + case 0x07: + dev->pci_conf[addr] &= val & 0xf7; + break; - case 0x0c ... 0x0d: - dev->pci_conf[addr] = val; - break; + case 0x0c ... 0x0d: + dev->pci_conf[addr] = val; + break; - case 0x52 ... 0x55: - dev->pci_conf[addr] = val; - break; - } + case 0x52 ... 0x55: + dev->pci_conf[addr] = val; + break; + + default: + break; + } } - static uint8_t ims8849_pci_read(int func, int addr, void *priv) { - ims8848_t *dev = (ims8848_t *)priv; - uint8_t ret = 0xff; + const ims8848_t *dev = (ims8848_t *) priv; + uint8_t ret = 0xff; if (func == 0) - ret = dev->pci_conf[addr]; + ret = dev->pci_conf[addr]; return ret; } - static void ims8848_reset(void *priv) { - ims8848_t *dev = (ims8848_t *)priv; + ims8848_t *dev = (ims8848_t *) priv; memset(dev->regs, 0x00, sizeof(dev->regs)); memset(dev->pci_conf, 0x00, sizeof(dev->pci_conf)); @@ -347,7 +357,7 @@ ims8848_reset(void *priv) dev->pci_conf[0x0b] = 0x06; - ims8848_recalc(dev); /* Shadow RAM Setup */ + ims8848_recalc(dev); /* Shadow RAM Setup */ ims8848_base_memory(dev); /* Base Memory Setup */ pci_set_irq_routing(PCI_INTA, PCI_IRQ_DISABLED); @@ -358,7 +368,6 @@ ims8848_reset(void *priv) ims8848_smram(dev); } - static void ims8848_close(void *priv) { @@ -369,9 +378,8 @@ ims8848_close(void *priv) free(dev); } - static void * -ims8848_init(const device_t *info) +ims8848_init(UNUSED(const device_t *info)) { ims8848_t *dev = (ims8848_t *) malloc(sizeof(ims8848_t)); memset(dev, 0, sizeof(ims8848_t)); @@ -379,15 +387,15 @@ ims8848_init(const device_t *info) device_add(&port_92_device); /* IMS 8848: - 22h Index - 23h Data Unlock - 24h Data + 22h Index + 23h Data Unlock + 24h Data IMS 8849: - PCI Device 0: IMS 8849 Dummy for compatibility reasons + PCI Device 0: IMS 8849 Dummy for compatibility reasons */ io_sethandler(0x0022, 0x0003, ims8848_read, NULL, NULL, ims8848_write, NULL, NULL, dev); - pci_add_card(PCI_ADD_NORTHBRIDGE, ims8849_pci_read, ims8849_pci_write, dev); + pci_add_card(PCI_ADD_NORTHBRIDGE, ims8849_pci_read, ims8849_pci_write, dev, &dev->pci_slot); dev->smram = smram_add(); smram_set_separate_smram(1); @@ -400,13 +408,16 @@ ims8848_init(const device_t *info) return dev; } - const device_t ims8848_device = { - "IMS 8848/8849", - "ims8848", - 0, - 0, - ims8848_init, ims8848_close, ims8848_reset, - { NULL }, NULL, NULL, - NULL + .name = "IMS 8848/8849", + .internal_name = "ims8848", + .flags = 0, + .local = 0, + .init = ims8848_init, + .close = ims8848_close, + .reset = ims8848_reset, + { .available = NULL }, + .speed_changed = NULL, + .force_redraw = NULL, + .config = NULL }; diff --git a/src/chipset/intel_420ex.c b/src/chipset/intel_420ex.c index aed5a6e6d..34335d53c 100644 --- a/src/chipset/intel_420ex.c +++ b/src/chipset/intel_420ex.c @@ -1,24 +1,30 @@ /* - * 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. + * 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. * - * Emulation of Intel 82420EX chipset that acts as both the - * northbridge and the southbridge. + * This file is part of the 86Box distribution. + * + * Emulation of Intel 82420EX chipset that acts as both the + * northbridge and the southbridge. * * * - * Authors: Miran Grca, + * Authors: Miran Grca, * - * Copyright 2020 Miran Grca. + * Copyright 2020 Miran Grca. */ +#define USE_DRB_HACK +#include #include #include #include #include #include +#define HAVE_STDARG_H #include <86box/86box.h> +#include "cpu.h" #include <86box/device.h> #include <86box/io.h> #include <86box/apm.h> @@ -26,81 +32,86 @@ #include <86box/mem.h> #include <86box/smram.h> #include <86box/pci.h> +#include <86box/pic.h> #include <86box/timer.h> #include <86box/pit.h> +#include <86box/plat_unused.h> #include <86box/port_92.h> #include <86box/hdc_ide.h> #include <86box/hdc.h> #include <86box/machine.h> #include <86box/chipset.h> #include <86box/spd.h> +#ifndef USE_DRB_HACK +#include <86box/row.h> +#endif +#define MEM_STATE_SHADOW_R 0x01 +#define MEM_STATE_SHADOW_W 0x02 +#define MEM_STATE_SMRAM 0x04 -#define MEM_STATE_SHADOW_R 0x01 -#define MEM_STATE_SHADOW_W 0x02 -#define MEM_STATE_SMRAM 0x04 +typedef struct i420ex_t { + uint8_t has_ide; + uint8_t smram_locked; + uint8_t pci_slot; + uint8_t pad; + uint8_t regs[256]; -typedef struct -{ - uint8_t has_ide, smram_locked, - regs[256]; + uint16_t timer_base; + uint16_t timer_latch; - uint16_t timer_base, - timer_latch; + smram_t *smram; - smram_t *smram; + double fast_off_period; - double fast_off_period; + pc_timer_t timer; + pc_timer_t fast_off_timer; - pc_timer_t timer, fast_off_timer; - - apm_t * apm; - port_92_t * port_92; + apm_t *apm; + port_92_t *port_92; } i420ex_t; - #ifdef ENABLE_I420EX_LOG int i420ex_do_log = ENABLE_I420EX_LOG; - static void i420ex_log(const char *fmt, ...) { va_list ap; if (i420ex_do_log) { - va_start(ap, fmt); - pclog_ex(fmt, ap); - va_end(ap); + va_start(ap, fmt); + pclog_ex(fmt, ap); + va_end(ap); } } #else -#define i420ex_log(fmt, ...) +# define i420ex_log(fmt, ...) #endif - static void i420ex_map(uint32_t addr, uint32_t size, int state) { switch (state & 3) { - case 0: - mem_set_mem_state_both(addr, size, MEM_READ_EXTANY | MEM_WRITE_EXTANY); - break; - case 1: - mem_set_mem_state_both(addr, size, MEM_READ_INTERNAL | MEM_WRITE_EXTANY); - break; - case 2: - mem_set_mem_state_both(addr, size, MEM_READ_EXTANY | MEM_WRITE_INTERNAL); - break; - case 3: - mem_set_mem_state_both(addr, size, MEM_READ_INTERNAL | MEM_WRITE_INTERNAL); - break; + case 0: + mem_set_mem_state_both(addr, size, MEM_READ_EXTANY | MEM_WRITE_EXTANY); + break; + case 1: + mem_set_mem_state_both(addr, size, MEM_READ_INTERNAL | MEM_WRITE_EXTANY); + break; + case 2: + mem_set_mem_state_both(addr, size, MEM_READ_EXTANY | MEM_WRITE_INTERNAL); + break; + case 3: + mem_set_mem_state_both(addr, size, MEM_READ_INTERNAL | MEM_WRITE_INTERNAL); + break; + default: + break; } flushmmucache_nopc(); } - static void i420ex_smram_handler_phase0(void) { @@ -108,51 +119,70 @@ i420ex_smram_handler_phase0(void) smram_disable_all(); } - static void i420ex_smram_handler_phase1(i420ex_t *dev) { - uint8_t *regs = (uint8_t *) dev->regs; + const uint8_t *regs = (uint8_t *) dev->regs; - uint32_t host_base = 0x000a0000, ram_base = 0x000a0000; - uint32_t size = 0x00010000; + uint32_t host_base = 0x000a0000; + uint32_t ram_base = 0x000a0000; + uint32_t size = 0x00010000; switch (regs[0x70] & 0x07) { - case 0: case 1: - default: - host_base = ram_base = 0x00000000; - size = 0x00000000; - break; - case 2: - host_base = 0x000a0000; - ram_base = 0x000a0000; - break; - case 3: - host_base = 0x000b0000; - ram_base = 0x000b0000; - break; - case 4: - host_base = 0x000c0000; - ram_base = 0x000a0000; - break; - case 5: - host_base = 0x000d0000; - ram_base = 0x000a0000; - break; - case 6: - host_base = 0x000e0000; - ram_base = 0x000a0000; - break; - case 7: - host_base = 0x000f0000; - ram_base = 0x000a0000; - break; + default: + case 0: + case 1: + host_base = ram_base = 0x00000000; + size = 0x00000000; + break; + case 2: + host_base = 0x000a0000; + ram_base = 0x000a0000; + break; + case 3: + host_base = 0x000b0000; + ram_base = 0x000b0000; + break; + case 4: + host_base = 0x000c0000; + ram_base = 0x000a0000; + break; + case 5: + host_base = 0x000d0000; + ram_base = 0x000a0000; + break; + case 6: + host_base = 0x000e0000; + ram_base = 0x000a0000; + break; + case 7: + host_base = 0x000f0000; + ram_base = 0x000a0000; + break; } smram_enable(dev->smram, host_base, ram_base, size, - (regs[0x70] & 0x70) == 0x40, !(regs[0x70] & 0x20)); + (regs[0x70] & 0x70) == 0x40, !(regs[0x70] & 0x20)); } +#ifndef USE_DRB_HACK +static void +i420ex_drb_recalc(i420ex_t *dev) +{ + uint32_t boundary; + + for (int8_t i = 4; i >= 0; i--) + row_disable(i); + + for (uint8_t i = 0; i <= 4; i++) { + boundary = ((uint32_t) dev->regs[0x60 + i]) & 0xff; + row_set_boundary(i, boundary); + } + + flushmmucache(); +} +#endif + static void i420ex_write(int func, int addr, uint8_t val, void *priv) @@ -160,206 +190,219 @@ i420ex_write(int func, int addr, uint8_t val, void *priv) i420ex_t *dev = (i420ex_t *) priv; if (func > 0) - return; + return; if (((addr >= 0x0f) && (addr < 0x4c)) && (addr != 0x40)) - return; + return; switch (addr) { - case 0x05: - dev->regs[addr] = (val & 0x01); - break; + case 0x05: + dev->regs[addr] = (val & 0x01); + break; - case 0x07: - dev->regs[addr] &= ~(val & 0xf0); - break; + case 0x07: + dev->regs[addr] &= ~(val & 0xf0); + break; - case 0x40: - dev->regs[addr] = (val & 0x7f); - break; - case 0x44: - dev->regs[addr] = (val & 0x07); - break; - case 0x48: - dev->regs[addr] = (val & 0x3f); - if (dev->has_ide) { - ide_pri_disable(); - switch (val & 0x03) { - case 0x01: - ide_set_base(0, 0x01f0); - ide_set_side(0, 0x03f6); - ide_pri_enable(); - break; - case 0x02: - ide_set_base(0, 0x0170); - ide_set_side(0, 0x0376); - ide_pri_enable(); - break; - } - } - break; - case 0x49: case 0x53: - dev->regs[addr] = (val & 0x1f); - break; - case 0x4c: case 0x51: - case 0x57: - case 0x68: case 0x69: - dev->regs[addr] = val; - if (addr == 0x4c) { - dma_alias_remove(); - if (!(val & 0x80)) - dma_alias_set(); - } - break; - case 0x4d: - dev->regs[addr] = (dev->regs[addr] & 0xef) | (val & 0x10); - break; - case 0x4e: - dev->regs[addr] = (val & 0xf7); - break; - case 0x50: - dev->regs[addr] = (val & 0x0f); - break; - case 0x52: - dev->regs[addr] = (val & 0x7f); - break; - case 0x56: - dev->regs[addr] = (val & 0x3e); - break; - case 0x59: /* PAM0 */ - if ((dev->regs[0x59] ^ val) & 0xf0) { - i420ex_map(0xf0000, 0x10000, val >> 4); - shadowbios = (val & 0x10); - } - dev->regs[0x59] = val & 0xf0; - break; - case 0x5a: /* PAM1 */ - if ((dev->regs[0x5a] ^ val) & 0x0f) - i420ex_map(0xc0000, 0x04000, val & 0xf); - if ((dev->regs[0x5a] ^ val) & 0xf0) - i420ex_map(0xc4000, 0x04000, val >> 4); - dev->regs[0x5a] = val; - break; - case 0x5b: /*PAM2 */ - if ((dev->regs[0x5b] ^ val) & 0x0f) - i420ex_map(0xc8000, 0x04000, val & 0xf); - if ((dev->regs[0x5b] ^ val) & 0xf0) - i420ex_map(0xcc000, 0x04000, val >> 4); - dev->regs[0x5b] = val; - break; - case 0x5c: /*PAM3 */ - if ((dev->regs[0x5c] ^ val) & 0x0f) - i420ex_map(0xd0000, 0x04000, val & 0xf); - if ((dev->regs[0x5c] ^ val) & 0xf0) - i420ex_map(0xd4000, 0x04000, val >> 4); - dev->regs[0x5c] = val; - break; - case 0x5d: /* PAM4 */ - if ((dev->regs[0x5d] ^ val) & 0x0f) - i420ex_map(0xd8000, 0x04000, val & 0xf); - if ((dev->regs[0x5d] ^ val) & 0xf0) - i420ex_map(0xdc000, 0x04000, val >> 4); - dev->regs[0x5d] = val; - break; - case 0x5e: /* PAM5 */ - if ((dev->regs[0x5e] ^ val) & 0x0f) - i420ex_map(0xe0000, 0x04000, val & 0xf); - if ((dev->regs[0x5e] ^ val) & 0xf0) - i420ex_map(0xe4000, 0x04000, val >> 4); - dev->regs[0x5e] = val; - break; - case 0x5f: /* PAM6 */ - if ((dev->regs[0x5f] ^ val) & 0x0f) - i420ex_map(0xe8000, 0x04000, val & 0xf); - if ((dev->regs[0x5f] ^ val) & 0xf0) - i420ex_map(0xec000, 0x04000, val >> 4); - dev->regs[0x5f] = val; - break; - case 0x60: case 0x61: case 0x62: case 0x63: case 0x64: - spd_write_drbs(dev->regs, 0x60, 0x64, 1); - break; - case 0x66: case 0x67: - i420ex_log("Set IRQ routing: INT %c -> %02X\n", 0x41 + (addr & 0x01), val); - dev->regs[addr] = val & 0x8f; - if (val & 0x80) - pci_set_irq_routing(PCI_INTA + (addr & 0x01), PCI_IRQ_DISABLED); - else - pci_set_irq_routing(PCI_INTA + (addr & 0x01), val & 0xf); - break; - case 0x70: /* SMRAM */ - i420ex_smram_handler_phase0(); - if (dev->smram_locked) - dev->regs[0x70] = (dev->regs[0x70] & 0xdf) | (val & 0x20); - else { - dev->regs[0x70] = (dev->regs[0x70] & 0x88) | (val & 0x77); - dev->smram_locked = (val & 0x10); - if (dev->smram_locked) - dev->regs[0x70] &= 0xbf; - } - i420ex_smram_handler_phase1(dev); - break; - case 0xa0: - dev->regs[addr] = val & 0x1f; - apm_set_do_smi(dev->apm, !!(val & 0x01) && !!(dev->regs[0xa2] & 0x80)); - switch ((val & 0x18) >> 3) { - case 0x00: - dev->fast_off_period = PCICLK * 32768.0 * 60000.0; - break; - case 0x01: - default: - dev->fast_off_period = 0.0; - break; - case 0x02: - dev->fast_off_period = PCICLK; - break; - case 0x03: - dev->fast_off_period = PCICLK * 32768.0; - break; - } - cpu_fast_off_count = dev->regs[0xa8] + 1; - timer_disable(&dev->fast_off_timer); - if (dev->fast_off_period != 0.0) - timer_on_auto(&dev->fast_off_timer, dev->fast_off_period); - break; - case 0xa2: - dev->regs[addr] = val & 0xff; - apm_set_do_smi(dev->apm, !!(dev->regs[0xa0] & 0x01) && !!(val & 0x80)); - break; - case 0xaa: - dev->regs[addr] &= (val & 0xff); - break; - case 0xac: case 0xae: - dev->regs[addr] = val & 0xff; - break; - case 0xa4: - dev->regs[addr] = val & 0xfb; - cpu_fast_off_flags = (cpu_fast_off_flags & 0xffffff00) | dev->regs[addr]; - break; - case 0xa5: - dev->regs[addr] = val; - cpu_fast_off_flags = (cpu_fast_off_flags & 0xffff00ff) | (dev->regs[addr] << 8); - break; - case 0xa7: - dev->regs[addr] = val & 0xe0; - cpu_fast_off_flags = (cpu_fast_off_flags & 0x00ffffff) | (dev->regs[addr] << 24); - break; - case 0xa8: - dev->regs[addr] = val & 0xff; - cpu_fast_off_val = val; - cpu_fast_off_count = val + 1; - timer_disable(&dev->fast_off_timer); - if (dev->fast_off_period != 0.0) - timer_on_auto(&dev->fast_off_timer, dev->fast_off_period); - break; + case 0x40: + dev->regs[addr] = (val & 0x7f); + break; + case 0x44: + dev->regs[addr] = (val & 0x07); + break; + case 0x48: + dev->regs[addr] = (val & 0x3f); + if (dev->has_ide) { + ide_pri_disable(); + switch (val & 0x03) { + case 0x01: + ide_set_base(0, 0x01f0); + ide_set_side(0, 0x03f6); + ide_pri_enable(); + break; + case 0x02: + ide_set_base(0, 0x0170); + ide_set_side(0, 0x0376); + ide_pri_enable(); + break; + default: + break; + } + } + break; + case 0x49: + case 0x53: + dev->regs[addr] = (val & 0x1f); + break; + case 0x4c: + case 0x51: + case 0x57: + case 0x68: + case 0x69: + dev->regs[addr] = val; + if (addr == 0x4c) { + dma_alias_remove(); + if (!(val & 0x80)) + dma_alias_set(); + } + break; + case 0x4d: + dev->regs[addr] = (dev->regs[addr] & 0xef) | (val & 0x10); + break; + case 0x4e: + dev->regs[addr] = (val & 0xf7); + break; + case 0x50: + dev->regs[addr] = (val & 0x0f); + break; + case 0x52: + dev->regs[addr] = (val & 0x7f); + break; + case 0x56: + dev->regs[addr] = (val & 0x3e); + break; + case 0x59: /* PAM0 */ + if ((dev->regs[0x59] ^ val) & 0xf0) { + i420ex_map(0xf0000, 0x10000, val >> 4); + shadowbios = (val & 0x10); + } + dev->regs[0x59] = val & 0xf0; + break; + case 0x5a: /* PAM1 */ + if ((dev->regs[0x5a] ^ val) & 0x0f) + i420ex_map(0xc0000, 0x04000, val & 0xf); + if ((dev->regs[0x5a] ^ val) & 0xf0) + i420ex_map(0xc4000, 0x04000, val >> 4); + dev->regs[0x5a] = val; + break; + case 0x5b: /*PAM2 */ + if ((dev->regs[0x5b] ^ val) & 0x0f) + i420ex_map(0xc8000, 0x04000, val & 0xf); + if ((dev->regs[0x5b] ^ val) & 0xf0) + i420ex_map(0xcc000, 0x04000, val >> 4); + dev->regs[0x5b] = val; + break; + case 0x5c: /*PAM3 */ + if ((dev->regs[0x5c] ^ val) & 0x0f) + i420ex_map(0xd0000, 0x04000, val & 0xf); + if ((dev->regs[0x5c] ^ val) & 0xf0) + i420ex_map(0xd4000, 0x04000, val >> 4); + dev->regs[0x5c] = val; + break; + case 0x5d: /* PAM4 */ + if ((dev->regs[0x5d] ^ val) & 0x0f) + i420ex_map(0xd8000, 0x04000, val & 0xf); + if ((dev->regs[0x5d] ^ val) & 0xf0) + i420ex_map(0xdc000, 0x04000, val >> 4); + dev->regs[0x5d] = val; + break; + case 0x5e: /* PAM5 */ + if ((dev->regs[0x5e] ^ val) & 0x0f) + i420ex_map(0xe0000, 0x04000, val & 0xf); + if ((dev->regs[0x5e] ^ val) & 0xf0) + i420ex_map(0xe4000, 0x04000, val >> 4); + dev->regs[0x5e] = val; + break; + case 0x5f: /* PAM6 */ + if ((dev->regs[0x5f] ^ val) & 0x0f) + i420ex_map(0xe8000, 0x04000, val & 0xf); + if ((dev->regs[0x5f] ^ val) & 0xf0) + i420ex_map(0xec000, 0x04000, val >> 4); + dev->regs[0x5f] = val; + break; + case 0x60: + case 0x61: + case 0x62: + case 0x63: + case 0x64: +#ifdef USE_DRB_HACK + spd_write_drbs(dev->regs, 0x60, 0x64, 1); +#else + dev->regs[addr] = val; + i420ex_drb_recalc(dev); +#endif + break; + case 0x66: + case 0x67: + i420ex_log("Set IRQ routing: INT %c -> %02X\n", 0x41 + (addr & 0x01), val); + dev->regs[addr] = val & 0x8f; + if (val & 0x80) + pci_set_irq_routing(PCI_INTA + (addr & 0x01), PCI_IRQ_DISABLED); + else + pci_set_irq_routing(PCI_INTA + (addr & 0x01), val & 0xf); + break; + case 0x70: /* SMRAM */ + i420ex_smram_handler_phase0(); + if (dev->smram_locked) + dev->regs[0x70] = (dev->regs[0x70] & 0xdf) | (val & 0x20); + else { + dev->regs[0x70] = (dev->regs[0x70] & 0x88) | (val & 0x77); + dev->smram_locked = (val & 0x10); + if (dev->smram_locked) + dev->regs[0x70] &= 0xbf; + } + i420ex_smram_handler_phase1(dev); + break; + case 0xa0: + dev->regs[addr] = val & 0x1f; + apm_set_do_smi(dev->apm, !!(val & 0x01) && !!(dev->regs[0xa2] & 0x80)); + switch ((val & 0x18) >> 3) { + case 0x00: + dev->fast_off_period = PCICLK * 32768.0 * 60000.0; + break; + case 0x01: + default: + dev->fast_off_period = 0.0; + break; + case 0x02: + dev->fast_off_period = PCICLK; + break; + case 0x03: + dev->fast_off_period = PCICLK * 32768.0; + break; + } + cpu_fast_off_count = cpu_fast_off_val + 1; + cpu_fast_off_period_set(cpu_fast_off_val, dev->fast_off_period); + break; + case 0xa2: + dev->regs[addr] = val & 0xff; + apm_set_do_smi(dev->apm, !!(dev->regs[0xa0] & 0x01) && !!(val & 0x80)); + break; + case 0xaa: + dev->regs[addr] &= (val & 0xff); + break; + case 0xac: + case 0xae: + dev->regs[addr] = val & 0xff; + break; + case 0xa4: + dev->regs[addr] = val & 0xfb; + cpu_fast_off_flags = (cpu_fast_off_flags & 0xffffff00) | dev->regs[addr]; + break; + case 0xa5: + dev->regs[addr] = val; + cpu_fast_off_flags = (cpu_fast_off_flags & 0xffff00ff) | (dev->regs[addr] << 8); + break; + case 0xa7: + dev->regs[addr] = val & 0xe0; + cpu_fast_off_flags = (cpu_fast_off_flags & 0x00ffffff) | (dev->regs[addr] << 24); + break; + case 0xa8: + dev->regs[addr] = val & 0xff; + cpu_fast_off_val = val; + cpu_fast_off_count = val + 1; + cpu_fast_off_period_set(cpu_fast_off_val, dev->fast_off_period); + break; + default: + break; } } - static uint8_t i420ex_read(int func, int addr, void *priv) { - i420ex_t *dev = (i420ex_t *) priv; - uint8_t ret; + const i420ex_t *dev = (i420ex_t *) priv; + uint8_t ret; ret = 0xff; @@ -369,7 +412,6 @@ i420ex_read(int func, int addr, void *priv) return ret; } - static void i420ex_reset_hard(void *priv) { @@ -377,22 +419,25 @@ i420ex_reset_hard(void *priv) memset(dev->regs, 0, 256); - dev->regs[0x00] = 0x86; dev->regs[0x01] = 0x80; /*Intel*/ - dev->regs[0x02] = 0x86; dev->regs[0x03] = 0x04; /*82378IB (I420EX)*/ + dev->regs[0x00] = 0x86; + dev->regs[0x01] = 0x80; /*Intel*/ + dev->regs[0x02] = 0x86; + dev->regs[0x03] = 0x04; /*82378IB (I420EX)*/ dev->regs[0x04] = 0x07; dev->regs[0x07] = 0x02; dev->regs[0x4c] = 0x4d; dev->regs[0x4e] = 0x03; - /* Bits 2:1 of register 50h are 00 is 25 MHz, and 01 if 33 MHz, 10 and 11 are reserved. */ + /* Bits 2:1 of register 50h are 00 is 25 MHz, and 01 if 33 MHz, 10 and 11 are reserved. */ if (cpu_busspeed >= 33333333) - dev->regs[0x50] |= 0x02; + dev->regs[0x50] |= 0x02; dev->regs[0x51] = 0x80; dev->regs[0x60] = dev->regs[0x61] = dev->regs[0x62] = dev->regs[0x63] = dev->regs[0x64] = 0x01; - dev->regs[0x66] = 0x80; dev->regs[0x67] = 0x80; - dev->regs[0x69] = 0x02; - dev->regs[0xa0] = 0x08; - dev->regs[0xa8] = 0x0f; + dev->regs[0x66] = 0x80; + dev->regs[0x67] = 0x80; + dev->regs[0x69] = 0x02; + dev->regs[0xa0] = 0x08; + dev->regs[0xa8] = 0x0f; mem_set_mem_state(0x000a0000, 0x00060000, MEM_READ_EXTANY | MEM_WRITE_EXTANY); mem_set_mem_state_smm(0x000a0000, 0x00060000, MEM_READ_EXTANY | MEM_WRITE_EXTANY); @@ -401,20 +446,18 @@ i420ex_reset_hard(void *priv) pci_set_irq_routing(PCI_INTB, PCI_IRQ_DISABLED); if (dev->has_ide) - ide_pri_disable(); + ide_pri_disable(); } - static void -i420ex_apm_out(uint16_t port, uint8_t val, void *p) +i420ex_apm_out(UNUSED(uint16_t port), UNUSED(uint8_t val), void *priv) { - i420ex_t *dev = (i420ex_t *) p; + i420ex_t *dev = (i420ex_t *) priv; if (dev->apm->do_smi) - dev->regs[0xaa] |= 0x80; + dev->regs[0xaa] |= 0x80; } - static void i420ex_fast_off_count(void *priv) { @@ -422,78 +465,71 @@ i420ex_fast_off_count(void *priv) cpu_fast_off_count--; - if (cpu_fast_off_count == 0) { - smi_line = 1; - dev->regs[0xaa] |= 0x20; - cpu_fast_off_count = dev->regs[0xa8] + 1; - } - - timer_on_auto(&dev->fast_off_timer, dev->fast_off_period); + smi_raise(); + dev->regs[0xaa] |= 0x20; } - static void -i420ex_reset(void *p) +i420ex_reset(void *priv) { - i420ex_t *dev = (i420ex_t *) p; - int i; + i420ex_t *dev = (i420ex_t *) priv; - i420ex_write(0, 0x48, 0x00, p); + i420ex_write(0, 0x48, 0x00, priv); - for (i = 0; i < 7; i++) - i420ex_write(0, 0x59 + i, 0x00, p); + /* Disable the PIC mouse latch. */ + i420ex_write(0, 0x4e, 0x03, priv); - for (i = 0; i <= 4; i++) - i420ex_write(0, 0x60 + i, 0x01, p); + for (uint8_t i = 0; i < 7; i++) + i420ex_write(0, 0x59 + i, 0x00, priv); - dev->regs[0x70] &= 0xef; /* Forcibly unlock the SMRAM register. */ + for (uint8_t i = 0; i <= 4; i++) + dev->regs[0x60 + i] = 0x01; + + dev->regs[0x70] &= 0xef; /* Forcibly unlock the SMRAM register. */ dev->smram_locked = 0; - i420ex_write(0, 0x70, 0x00, p); + i420ex_write(0, 0x70, 0x00, priv); mem_set_mem_state(0x000a0000, 0x00060000, MEM_READ_EXTANY | MEM_WRITE_EXTANY); mem_set_mem_state_smm(0x000a0000, 0x00060000, MEM_READ_EXTANY | MEM_WRITE_EXTANY); - i420ex_write(0, 0xa0, 0x08, p); - i420ex_write(0, 0xa2, 0x00, p); - i420ex_write(0, 0xa4, 0x00, p); - i420ex_write(0, 0xa5, 0x00, p); - i420ex_write(0, 0xa6, 0x00, p); - i420ex_write(0, 0xa7, 0x00, p); - i420ex_write(0, 0xa8, 0x0f, p); + i420ex_write(0, 0xa0, 0x08, priv); + i420ex_write(0, 0xa2, 0x00, priv); + i420ex_write(0, 0xa4, 0x00, priv); + i420ex_write(0, 0xa5, 0x00, priv); + i420ex_write(0, 0xa6, 0x00, priv); + i420ex_write(0, 0xa7, 0x00, priv); + i420ex_write(0, 0xa8, 0x0f, priv); } - static void -i420ex_close(void *p) +i420ex_close(void *priv) { - i420ex_t *dev = (i420ex_t *)p; + i420ex_t *dev = (i420ex_t *) priv; smram_del(dev->smram); free(dev); } - static void i420ex_speed_changed(void *priv) { i420ex_t *dev = (i420ex_t *) priv; - int te; + int te; te = timer_is_enabled(&dev->timer); timer_disable(&dev->timer); if (te) - timer_set_delay_u64(&dev->timer, ((uint64_t) dev->timer_latch) * TIMER_USEC); + timer_set_delay_u64(&dev->timer, ((uint64_t) dev->timer_latch) * TIMER_USEC); - te = timer_is_enabled(&dev->fast_off_timer); + te = timer_is_on(&dev->fast_off_timer); timer_stop(&dev->fast_off_timer); if (te) - timer_on_auto(&dev->fast_off_timer, dev->fast_off_period); + timer_on_auto(&dev->fast_off_timer, dev->fast_off_period); } - static void * i420ex_init(const device_t *info) { @@ -502,7 +538,7 @@ i420ex_init(const device_t *info) dev->smram = smram_add(); - pci_add_card(PCI_ADD_NORTHBRIDGE, i420ex_read, i420ex_write, dev); + pci_add_card(PCI_ADD_NORTHBRIDGE, i420ex_read, i420ex_write, dev, &dev->pci_slot); dev->has_ide = info->local; @@ -510,9 +546,11 @@ i420ex_init(const device_t *info) cpu_fast_off_flags = 0x00000000; - cpu_fast_off_val = dev->regs[0xa8]; + cpu_fast_off_val = dev->regs[0xa8]; cpu_fast_off_count = cpu_fast_off_val + 1; + cpu_register_fast_off_handler(&dev->fast_off_timer); + dev->apm = device_add(&apm_pci_device); /* APM intercept handler to update 82420EX SMI status on APM SMI. */ io_sethandler(0x00b2, 0x0001, NULL, NULL, NULL, i420ex_apm_out, NULL, NULL, dev); @@ -523,39 +561,40 @@ i420ex_init(const device_t *info) device_add(&ide_pci_2ch_device); +#ifndef USE_DRB_HACK + row_device.local = 4 | (1 << 8) | (0x01 << 16) | (8 << 24); + device_add((const device_t *) &row_device); +#endif + i420ex_reset_hard(dev); return dev; } - -const device_t i420ex_device = -{ - "Intel 82420EX", - "i420ex", - DEVICE_PCI, - 0x00, - i420ex_init, - i420ex_close, - i420ex_reset, - { NULL }, - i420ex_speed_changed, - NULL, - NULL +const device_t i420ex_device = { + .name = "Intel 82420EX", + .internal_name = "i420ex", + .flags = DEVICE_PCI, + .local = 0x00, + .init = i420ex_init, + .close = i420ex_close, + .reset = i420ex_reset, + { .available = NULL }, + .speed_changed = i420ex_speed_changed, + .force_redraw = NULL, + .config = NULL }; - -const device_t i420ex_ide_device = -{ - "Intel 82420EX (With IDE)", - "i420ex_ide", - DEVICE_PCI, - 0x01, - i420ex_init, - i420ex_close, - i420ex_reset, - { NULL }, - i420ex_speed_changed, - NULL, - NULL +const device_t i420ex_ide_device = { + .name = "Intel 82420EX (With IDE)", + .internal_name = "i420ex_ide", + .flags = DEVICE_PCI, + .local = 0x01, + .init = i420ex_init, + .close = i420ex_close, + .reset = i420ex_reset, + { .available = NULL }, + .speed_changed = i420ex_speed_changed, + .force_redraw = NULL, + .config = NULL }; diff --git a/src/chipset/intel_4x0.c b/src/chipset/intel_4x0.c index 1f7a29ede..1e4158b94 100644 --- a/src/chipset/intel_4x0.c +++ b/src/chipset/intel_4x0.c @@ -1,24 +1,26 @@ /* - * 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. + * 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. + * This file is part of the 86Box distribution. * - * Implementation of the Intel PCISet chips from 420TX to 440GX. + * Implementation of the Intel PCISet chips from 420TX to 440GX. * * * - * Authors: Miran Grca, + * Authors: Miran Grca, * - * Copyright 2019,2020 Miran Grca. + * Copyright 2019-2020 Miran Grca. */ +#include #include #include #include #include #include +#define HAVE_STDARG_H #include <86box/86box.h> #include "cpu.h" #include <86box/mem.h> @@ -26,14 +28,13 @@ #include <86box/io.h> #include <86box/device.h> #include <86box/pci.h> +#include <86box/plat_unused.h> #include <86box/chipset.h> #include <86box/spd.h> #include <86box/machine.h> -#include <86box/video.h> +#include <86box/agpgart.h> - -enum -{ +enum { INTEL_420TX, INTEL_420ZX, INTEL_430LX, @@ -50,162 +51,161 @@ enum INTEL_440ZX }; -typedef struct -{ - uint8_t pm2_cntrl, - smram_locked, max_drb, - drb_unit, drb_default; - uint8_t regs[256], regs_locked[256]; - uint8_t mem_state[256]; - int type; - smram_t *smram_low, *smram_high; - void *agpgart; - void (*write_drbs)(uint8_t *regs, uint8_t reg_min, uint8_t reg_max, uint8_t drb_unit); +typedef struct i4x0_t { + uint8_t pm2_cntrl; + uint8_t smram_locked; + uint8_t max_drb; + uint8_t drb_unit; + uint8_t drb_default; + uint8_t pci_slot; + uint8_t pad; + uint8_t pad0; + uint8_t regs[256]; + uint8_t regs_locked[256]; + uint8_t mem_state[256]; + int type; + smram_t *smram_low; + smram_t *smram_high; + agpgart_t *agpgart; + void (*write_drbs)(uint8_t *regs, uint8_t reg_min, uint8_t reg_max, uint8_t drb_unit); } i4x0_t; - #ifdef ENABLE_I4X0_LOG int i4x0_do_log = ENABLE_I4X0_LOG; - static void i4x0_log(const char *fmt, ...) { va_list ap; if (i4x0_do_log) { - va_start(ap, fmt); - pclog_ex(fmt, ap); - va_end(ap); + va_start(ap, fmt); + pclog_ex(fmt, ap); + va_end(ap); } } #else -#define i4x0_log(fmt, ...) +# define i4x0_log(fmt, ...) #endif - static void i4x0_map(i4x0_t *dev, uint32_t addr, uint32_t size, int state) { - uint32_t base = addr >> 12; - int states[4] = { MEM_READ_EXTANY | MEM_WRITE_EXTANY, MEM_READ_INTERNAL | MEM_WRITE_EXTANY, - MEM_READ_EXTANY | MEM_WRITE_INTERNAL, MEM_READ_INTERNAL | MEM_WRITE_INTERNAL }; + uint32_t base = addr >> 12; + int states[4] = { MEM_READ_EXTANY | MEM_WRITE_EXTANY, MEM_READ_INTERNAL | MEM_WRITE_EXTANY, + MEM_READ_EXTANY | MEM_WRITE_INTERNAL, MEM_READ_INTERNAL | MEM_WRITE_INTERNAL }; state &= 3; if (dev->mem_state[base] != state) { - mem_set_mem_state_both(addr, size, states[state]); - dev->mem_state[base] = state; - flushmmucache_nopc(); + mem_set_mem_state_both(addr, size, states[state]); + dev->mem_state[base] = state; + flushmmucache_nopc(); } } - static void i4x0_smram_handler_phase0(i4x0_t *dev) { uint32_t tom = (mem_size << 10); - if (((dev->type == INTEL_430TX) || (dev->type >= INTEL_440BX)) && - smram_enabled(dev->smram_high)) { - tom -= (1 << 20); - mem_set_mem_state_smm(tom, (1 << 20), MEM_READ_INTERNAL | MEM_WRITE_INTERNAL); + if (((dev->type == INTEL_430TX) || (dev->type >= INTEL_440BX)) && smram_enabled(dev->smram_high)) { + tom -= (1 << 20); + mem_set_mem_state_smm(tom, (1 << 20), MEM_READ_INTERNAL | MEM_WRITE_INTERNAL); } /* Disable any active mappings. */ smram_disable_all(); } - static void i4x0_smram_handler_phase1(i4x0_t *dev) { - uint8_t *regs = (uint8_t *) dev->regs; - uint32_t tom = (mem_size << 10); - uint8_t *reg = (dev->type >= INTEL_430LX) ? &(regs[0x72]) : &(regs[0x57]); - uint8_t *ext_reg = (dev->type >= INTEL_440BX) ? &(regs[0x73]) : &(regs[0x71]); + const uint8_t *regs = (uint8_t *) dev->regs; + uint32_t tom = (mem_size << 10); + const uint8_t *reg = (dev->type >= INTEL_430LX) ? &(regs[0x72]) : &(regs[0x57]); + const uint8_t *ext_reg = (dev->type >= INTEL_440BX) ? &(regs[0x73]) : &(regs[0x71]); - uint32_t s, base[2] = { 0x000a0000, 0x00000000 }; + uint32_t s; + uint32_t base[2] = { 0x000a0000, 0x00000000 }; uint32_t size[2] = { 0x00010000, 0x00000000 }; if ((dev->type <= INTEL_420ZX) || (dev->type >= INTEL_430FX)) { - /* Set temporary bases and sizes. */ - if (((dev->type == INTEL_430TX) || (dev->type >= INTEL_440BX)) && - (*ext_reg & 0x80)) { - base[0] = 0x100a0000; - size[0] = 0x00060000; - } else if (((dev->type == INTEL_440LX) || (dev->type == INTEL_440EX)) && ((*reg & 0x07) == 0x04)) { - base[0] = 0x000c0000; - size[0] = 0x00010000; - } else { - base[0] = 0x000a0000; - size[0] = 0x00020000; - } + /* Set temporary bases and sizes. */ + if (((dev->type == INTEL_430TX) || (dev->type >= INTEL_440BX)) && (*ext_reg & 0x80)) { + base[0] = 0x100a0000; + size[0] = 0x00060000; + } else if (((dev->type == INTEL_440LX) || (dev->type == INTEL_440EX)) && ((*reg & 0x07) == 0x04)) { + base[0] = 0x000c0000; + size[0] = 0x00010000; + } else { + base[0] = 0x000a0000; + size[0] = 0x00020000; + } - if (*reg & 0x08) - smram_enable(dev->smram_low, base[0], base[0] & 0x000f0000, size[0], - ((*reg & 0x78) == 0x48), (*reg & 0x08)); + if (*reg & 0x08) + smram_enable(dev->smram_low, base[0], base[0] & 0x000f0000, size[0], + ((*reg & 0x78) == 0x48), (*reg & 0x08)); - if ((*reg & 0x28) == 0x28) { - /* If SMRAM is enabled and DCLS is set, then data goes to PCI, but - code still goes to DRAM. */ - mem_set_mem_state_smram_ex(1, base[0], size[0], 0x02); - } + if ((*reg & 0x28) == 0x28) { + /* If SMRAM is enabled and DCLS is set, then data goes to PCI, but + code still goes to DRAM. */ + mem_set_mem_state_smram_ex(1, base[0], size[0], 0x02); + } - /* TSEG mapping. */ - if ((dev->type == INTEL_430TX) || (dev->type >= INTEL_440BX)) { - if ((*reg & 0x08) && (*ext_reg & 0x01)) { - size[1] = (1 << (17 + ((*ext_reg >> 1) & 0x03))); - tom -= size[1]; - base[1] = tom; - } else - base[1] = size[1] = 0x00000000; + /* TSEG mapping. */ + if ((dev->type == INTEL_430TX) || (dev->type >= INTEL_440BX)) { + if ((*reg & 0x08) && (*ext_reg & 0x01)) { + size[1] = (1 << (17 + ((*ext_reg >> 1) & 0x03))); + tom -= size[1]; + base[1] = tom; + } else + base[1] = size[1] = 0x00000000; - if (size[1] != 0x00000000) { - smram_enable(dev->smram_high, base[1] + (1 << 28), base[1], size[1], - 0, 1); + if (size[1] != 0x00000000) { + smram_enable(dev->smram_high, base[1] + (1 << 28), base[1], size[1], + 0, 1); - mem_set_mem_state_smm(base[1], size[1], MEM_READ_EXTANY | MEM_WRITE_EXTANY); - } - } + mem_set_mem_state_smm(base[1], size[1], MEM_READ_EXTANY | MEM_WRITE_EXTANY); + } + } } else { - size[0] = 0x00010000; - switch (*reg & 0x03) { - case 0: - default: - base[0] = (mem_size << 10) - size[0]; - s = 1; - break; - case 1: - base[0] = size[0] = 0x00000000; - s = 1; - break; - case 2: - base[0] = 0x000a0000; - s = 0; - break; - case 3: - base[0] = 0x000b0000; - s = 0; - break; - } + size[0] = 0x00010000; + switch (*reg & 0x03) { + default: + case 0: + base[0] = (mem_size << 10) - size[0]; + s = 1; + break; + case 1: + base[0] = size[0] = 0x00000000; + s = 1; + break; + case 2: + base[0] = 0x000a0000; + s = 0; + break; + case 3: + base[0] = 0x000b0000; + s = 0; + break; + } - if (size[0] != 0x00000000) { - smram_enable(dev->smram_low, base[0], base[0], size[0], - (((*reg & 0x38) == 0x20) || s), 1); + if (size[0] != 0x00000000) { + smram_enable(dev->smram_low, base[0], base[0], size[0], + (((*reg & 0x38) == 0x20) || s), 1); - if (*reg & 0x10) { - /* If SMRAM is enabled and DCLS is set, then data goes to PCI, but - code still goes to DRAM. */ - mem_set_mem_state_smram_ex(1, base[0], size[0], 0x02); - } - } + if (*reg & 0x10) { + /* If SMRAM is enabled and DCLS is set, then data goes to PCI, but + code still goes to DRAM. */ + mem_set_mem_state_smram_ex(1, base[0], size[0], 0x02); + } + } } flushmmucache(); } - static void i4x0_mask_bar(uint8_t *regs, void *agpgart) { @@ -218,1083 +218,1360 @@ i4x0_mask_bar(uint8_t *regs, void *agpgart) regs[0x13] = (bar >> 24) & 0xff; if (!agpgart) - return; + return; /* Map aperture and GART. */ agpgart_set_aperture(agpgart, - bar, - ((uint32_t) (uint8_t) (~regs[0xb4] & 0x3f) + 1) << 22, - !!(regs[0x51] & 0x02)); + bar, + ((uint32_t) (uint8_t) (~regs[0xb4] & 0x3f) + 1) << 22, + !!(regs[0x51] & 0x02)); agpgart_set_gart(agpgart, (regs[0xb9] << 8) | (regs[0xba] << 16) | (regs[0xbb] << 24)); } - static uint8_t -pm2_cntrl_read(uint16_t addr, void *p) +pm2_cntrl_read(UNUSED(uint16_t addr), void *priv) { - i4x0_t *dev = (i4x0_t *) p; + const i4x0_t *dev = (i4x0_t *) priv; return dev->pm2_cntrl & 0x01; } - static void -pm2_cntrl_write(uint16_t addr, uint8_t val, void *p) +pm2_cntrl_write(UNUSED(uint16_t addr), uint8_t val, void *priv) { - i4x0_t *dev = (i4x0_t *) p; + i4x0_t *dev = (i4x0_t *) priv; dev->pm2_cntrl = val & 0x01; } - static void i4x0_write(int func, int addr, uint8_t val, void *priv) { - i4x0_t *dev = (i4x0_t *) priv; - uint8_t *regs = (uint8_t *) dev->regs; + i4x0_t *dev = (i4x0_t *) priv; + uint8_t *regs = (uint8_t *) dev->regs; uint8_t *regs_l = (uint8_t *) dev->regs_locked; - int i; if (func > 0) - return; + return; - if (func == 0) switch (addr) { - case 0x04: /*Command register*/ - switch (dev->type) { - case INTEL_420TX: case INTEL_420ZX: case INTEL_430LX: case INTEL_430NX: - case INTEL_440BX: case INTEL_440GX: case INTEL_440ZX: - default: - regs[0x04] = (regs[0x04] & ~0x42) | (val & 0x42); - break; - case INTEL_430FX: case INTEL_430HX: case INTEL_430VX: case INTEL_430TX: - case INTEL_440FX: - regs[0x04] = (regs[0x04] & ~0x02) | (val & 0x02); - break; - case INTEL_440LX: case INTEL_440EX: - regs[0x04] = val & 0x40; - break; - } - break; - case 0x05: - switch (dev->type) { - case INTEL_420TX: case INTEL_420ZX: case INTEL_430LX: case INTEL_430NX: - case INTEL_430HX: case INTEL_440FX: case INTEL_440BX: case INTEL_440GX: - case INTEL_440ZX: - regs[0x05] = (regs[0x05] & ~0x01) | (val & 0x01); - break; - case INTEL_440LX: case INTEL_440EX: - regs[0x05] = val & 0x01; - break; - } - break; - case 0x07: - switch (dev->type) { - case INTEL_420TX: case INTEL_420ZX: case INTEL_430LX: case INTEL_430NX: - case INTEL_430HX: - default: - regs[0x07] &= ~(val & 0x70); - break; - case INTEL_430FX: case INTEL_430VX: - case INTEL_430TX: - regs[0x07] &= ~(val & 0x30); - break; - case INTEL_440FX: - regs[0x07] &= ~(val & 0xf9); - break; - case INTEL_440LX: case INTEL_440EX: - regs[0x07] &= ~(val & 0xf1); - break; - case INTEL_440BX: case INTEL_440ZX: - case INTEL_440GX: - regs[0x07] &= ~(val & 0xf0); - break; - } - break; - case 0x0d: - switch (dev->type) { - case INTEL_420TX: case INTEL_420ZX: case INTEL_430LX: case INTEL_430NX: - regs[0x0d] = (val & 0xf0); - break; - default: - regs[0x0d] = (val & 0xf8); - break; - } - break; - case 0x0f: - switch (dev->type) { - case INTEL_430FX: case INTEL_430HX: case INTEL_430VX: case INTEL_430TX: - regs[0x0f] = (val & 0x40); - break; - } - break; - case 0x12: - switch (dev->type) { - case INTEL_440LX: case INTEL_440EX: - case INTEL_440BX: case INTEL_440ZX: - case INTEL_440GX: - regs[0x12] = (val & 0xc0); - i4x0_mask_bar(regs, dev->agpgart); - break; - } - break; - case 0x13: - switch (dev->type) { - case INTEL_440LX: case INTEL_440EX: - case INTEL_440BX: case INTEL_440ZX: - case INTEL_440GX: - regs[0x13] = val; - i4x0_mask_bar(regs, dev->agpgart); - break; - } - break; - case 0x2c: case 0x2d: case 0x2e: case 0x2f: - switch (dev->type) { - case INTEL_440BX: case INTEL_440ZX: - case INTEL_440GX: - if (!regs_l[addr]) { - regs[addr] = val; - regs_l[addr] = 1; - } - break; - } - break; + if (func == 0) + switch (addr) { + case 0x04: /*Command register*/ + switch (dev->type) { + default: + case INTEL_420TX: + case INTEL_420ZX: + case INTEL_430LX: + case INTEL_430NX: + case INTEL_440BX: + case INTEL_440GX: + case INTEL_440ZX: + regs[0x04] = (regs[0x04] & ~0x42) | (val & 0x42); + break; + case INTEL_430FX: + case INTEL_430HX: + case INTEL_430VX: + case INTEL_430TX: + case INTEL_440FX: + regs[0x04] = (regs[0x04] & ~0x02) | (val & 0x02); + break; + case INTEL_440LX: + case INTEL_440EX: + regs[0x04] = val & 0x40; + break; + } + break; + case 0x05: + switch (dev->type) { + case INTEL_420TX: + case INTEL_420ZX: + case INTEL_430LX: + case INTEL_430NX: + case INTEL_430HX: + case INTEL_440FX: + case INTEL_440BX: + case INTEL_440GX: + case INTEL_440ZX: + regs[0x05] = (regs[0x05] & ~0x01) | (val & 0x01); + break; + case INTEL_440LX: + case INTEL_440EX: + regs[0x05] = val & 0x01; + break; + default: + break; + } + break; + case 0x07: + switch (dev->type) { + default: + case INTEL_420TX: + case INTEL_420ZX: + case INTEL_430LX: + case INTEL_430NX: + case INTEL_430HX: + regs[0x07] &= ~(val & 0x70); + break; + case INTEL_430FX: + case INTEL_430VX: + case INTEL_430TX: + regs[0x07] &= ~(val & 0x30); + break; + case INTEL_440FX: + regs[0x07] &= ~(val & 0xf9); + break; + case INTEL_440LX: + case INTEL_440EX: + regs[0x07] &= ~(val & 0xf1); + break; + case INTEL_440BX: + case INTEL_440ZX: + case INTEL_440GX: + regs[0x07] &= ~(val & 0xf0); + break; + } + break; + case 0x0d: + switch (dev->type) { + case INTEL_420TX: + case INTEL_420ZX: + case INTEL_430LX: + case INTEL_430NX: + regs[0x0d] = (val & 0xf0); + break; + default: + regs[0x0d] = (val & 0xf8); + break; + } + break; + case 0x0f: + switch (dev->type) { + case INTEL_430FX: + case INTEL_430HX: + case INTEL_430VX: + case INTEL_430TX: + regs[0x0f] = (val & 0x40); + break; + default: + break; + } + break; + case 0x12: + switch (dev->type) { + case INTEL_440LX: + case INTEL_440EX: + case INTEL_440BX: + case INTEL_440ZX: + case INTEL_440GX: + regs[0x12] = (val & 0xc0); + i4x0_mask_bar(regs, dev->agpgart); + break; + default: + break; + } + break; + case 0x13: + switch (dev->type) { + case INTEL_440LX: + case INTEL_440EX: + case INTEL_440BX: + case INTEL_440ZX: + case INTEL_440GX: + regs[0x13] = val; + i4x0_mask_bar(regs, dev->agpgart); + break; + default: + break; + } + break; + case 0x2c: + case 0x2d: + case 0x2e: + case 0x2f: + switch (dev->type) { + case INTEL_440BX: + case INTEL_440ZX: + case INTEL_440GX: + if (!regs_l[addr]) { + regs[addr] = val; + regs_l[addr] = 1; + } + break; + default: + break; + } + break; - case 0x4f: - switch (dev->type) { - case INTEL_430HX: - regs[0x4f] = (val & 0x84); - break; - case INTEL_430VX: - regs[0x4f] = (val & 0x94); - break; - case INTEL_430TX: - regs[0x4f] = (val & 0x80); - break; - } - break; - case 0x50: - switch (dev->type) { - case INTEL_420TX: case INTEL_420ZX: - case INTEL_430LX: default: - regs[0x50] = (val & 0xe5); - break; - case INTEL_430NX: - regs[0x50] = (val & 0xe7); - break; - case INTEL_430FX: - regs[0x50] = (val & 0xef); - break; - case INTEL_430HX: - regs[0x50] = (val & 0xf7); - break; - case INTEL_430VX: case INTEL_430TX: - regs[0x50] = (val & 0x08); - break; - case INTEL_440FX: - regs[0x50] = (val & 0xf4); - break; - case INTEL_440LX: - regs[0x50] = (val & 0x70); - break; - case INTEL_440EX: - regs[0x50] = (val & 0x20); - break; - case INTEL_440BX: - regs[0x50] = (regs[0x50] & 0x14) | (val & 0xeb); - break; - case INTEL_440GX: - regs[0x50] = (regs[0x50] & 0x04) | (val & 0xe8); - break; - case INTEL_440ZX: - regs[0x50] = (regs[0x50] & 0x34) | (val & 0xcb); - break; + case 0x4f: + switch (dev->type) { + case INTEL_430HX: + regs[0x4f] = (val & 0x84); + break; + case INTEL_430VX: + regs[0x4f] = (val & 0x94); + break; + case INTEL_430TX: + regs[0x4f] = (val & 0x80); + break; + default: + break; + } + break; + case 0x50: + switch (dev->type) { + default: + case INTEL_420TX: + case INTEL_420ZX: + case INTEL_430LX: + regs[0x50] = (val & 0xe5); + break; + case INTEL_430NX: + regs[0x50] = (val & 0xe7); + break; + case INTEL_430FX: + regs[0x50] = (val & 0xef); + break; + case INTEL_430HX: + regs[0x50] = (val & 0xf7); + break; + case INTEL_430VX: + case INTEL_430TX: + regs[0x50] = (val & 0x08); + break; + case INTEL_440FX: + regs[0x50] = (val & 0xf4); + break; + case INTEL_440LX: + regs[0x50] = (val & 0x70); + break; + case INTEL_440EX: + regs[0x50] = (val & 0x20); + break; + case INTEL_440BX: + regs[0x50] = (regs[0x50] & 0x14) | (val & 0xeb); + break; + case INTEL_440GX: + regs[0x50] = (regs[0x50] & 0x04) | (val & 0xe8); + break; + case INTEL_440ZX: + regs[0x50] = (regs[0x50] & 0x34) | (val & 0xcb); + break; + } + break; + case 0x51: + switch (dev->type) { + case INTEL_420TX: + case INTEL_420ZX: + case INTEL_430LX: + case INTEL_430NX: + regs[0x51] = (val & 0xc0); + break; + case INTEL_440FX: + regs[0x51] = (val & 0xc3); + break; + case INTEL_440LX: + regs[0x51] = (regs[0x51] & 0x40) | (val & 0x87); + i4x0_mask_bar(regs, dev->agpgart); + break; + case INTEL_440EX: + regs[0x51] = (val & 0x86); + i4x0_mask_bar(regs, dev->agpgart); + break; + case INTEL_440BX: + case INTEL_440ZX: + regs[0x51] = (regs[0x51] & 0x70) | (val & 0x8f); + i4x0_mask_bar(regs, dev->agpgart); + break; + case INTEL_440GX: + regs[0x51] = (regs[0x51] & 0xb0) | (val & 0x4f); + i4x0_mask_bar(regs, dev->agpgart); + break; + default: + break; + } + break; + case 0x52: /* Cache Control Register */ + switch (dev->type) { + default: + case INTEL_420TX: + case INTEL_420ZX: + case INTEL_430LX: + case INTEL_430FX: + case INTEL_430VX: + case INTEL_430TX: + regs[0x52] = (val & 0xfb); + break; + case INTEL_430NX: + case INTEL_430HX: + case INTEL_440FX: + regs[0x52] = val; + break; + case INTEL_440BX: + case INTEL_440ZX: + case INTEL_440GX: + regs[0x52] = val & 0x07; + break; + } + break; + case 0x53: + switch (dev->type) { + case INTEL_420TX: + case INTEL_420ZX: + case INTEL_430LX: + regs[0x53] = val & 0x0b; + break; + case INTEL_430NX: + regs[0x53] = val & 0x0a; + break; + case INTEL_430VX: + case INTEL_430TX: + regs[0x53] = val & 0x3f; + break; + case INTEL_440LX: + case INTEL_440EX: + regs[0x53] = val & 0x60; + break; + case INTEL_440BX: + case INTEL_440GX: + /* Not applicable to 440ZX as that does not support ECC. */ + regs[0x53] = val; + break; + default: + break; + } + break; + case 0x54: + switch (dev->type) { + case INTEL_420TX: + case INTEL_420ZX: + case INTEL_430LX: + case INTEL_430NX: + regs[0x54] = val & 0x07; + break; + case INTEL_430VX: + regs[0x54] = val & 0xd8; + break; + case INTEL_430TX: + regs[0x54] = val & 0xfa; + break; + case INTEL_440FX: + regs[0x54] = val & 0x82; + break; + default: + break; + } + break; + case 0x55: + switch (dev->type) { + case INTEL_420TX: + case INTEL_420ZX: + /* According to the FreeBSD 3.x source code, the 420TX/ZX chipset has + this register. The mask is unknown, so write all bits. */ + regs[0x55] = val; + break; + case INTEL_430VX: + case INTEL_430TX: + regs[0x55] = val & 0x01; + break; + case INTEL_440FX: + case INTEL_440LX: + case INTEL_440EX: + regs[0x55] = val; + break; + default: + break; + } + break; + case 0x56: + switch (dev->type) { + case INTEL_420TX: + case INTEL_420ZX: + /* According to the FreeBSD 3.x source code, the 420TX/ZX chipset has + this register. The mask is unknown, so write all bits. */ + regs[0x56] = val; + break; + case INTEL_430HX: + regs[0x56] = val & 0x1f; + break; + case INTEL_430VX: + regs[0x56] = val & 0x77; + break; + case INTEL_430TX: + regs[0x56] = val & 0x76; + break; + case INTEL_440FX: + case INTEL_440LX: + case INTEL_440EX: + regs[0x56] = val; + break; + default: + break; + } + break; + case 0x57: + switch (dev->type) { + /* On the 420TX and 420ZX, this is the SMRAM space register. */ + case INTEL_420TX: + case INTEL_420ZX: + i4x0_smram_handler_phase0(dev); + if (dev->smram_locked) + regs[0x57] = (regs[0x57] & 0xdf) | (val & 0x20); + else { + regs[0x57] = (regs[0x57] & 0x87) | (val & 0x78); + dev->smram_locked = (val & 0x10); + if (dev->smram_locked) + regs[0x57] &= 0xbf; + } + i4x0_smram_handler_phase1(dev); + break; + case INTEL_430LX: + default: + regs[0x57] = val & 0x3f; + break; + case INTEL_430NX: + regs[0x57] = val; + break; + case INTEL_430FX: + case INTEL_430HX: + case INTEL_430VX: + regs[0x57] = val & 0xcf; + break; + case INTEL_430TX: + regs[0x57] = val & 0xdf; + break; + case INTEL_440FX: + regs[0x57] = val & 0x77; + break; + case INTEL_440LX: + case INTEL_440EX: + regs[0x57] = val & 0x37; + break; + case INTEL_440BX: + case INTEL_440GX: + regs[0x57] = val & 0x3f; + break; + case INTEL_440ZX: + regs[0x57] = val & 0x2f; + break; + } + break; + case 0x58: + switch (dev->type) { + default: + case INTEL_420TX: + case INTEL_420ZX: + case INTEL_430LX: + regs[0x58] = val & 0x01; + break; + case INTEL_430NX: + case INTEL_440BX: + case INTEL_440ZX: + regs[0x58] = val & 0x03; + break; + case INTEL_430FX: + case INTEL_440FX: + regs[0x58] = val & 0x7f; + break; + case INTEL_430HX: + case INTEL_430VX: + case INTEL_440LX: + case INTEL_440EX: + regs[0x58] = val; + break; + case INTEL_430TX: + regs[0x58] = val & 0x7b; + break; + } + break; + case 0x59: /* PAM0 */ + if (dev->type <= INTEL_430NX) { + if ((regs[0x59] ^ val) & 0x0f) + i4x0_map(dev, 0x80000, 0x20000, val & 0x0f); + } + if ((regs[0x59] ^ val) & 0xf0) { + i4x0_map(dev, 0xf0000, 0x10000, val >> 4); + shadowbios = (val & 0x10); + } + if (dev->type > INTEL_430NX) + regs[0x59] = val & 0x70; + else + regs[0x59] = val & 0x77; + break; + case 0x5a: /* PAM1 */ + if ((regs[0x5a] ^ val) & 0x0f) + i4x0_map(dev, 0xc0000, 0x04000, val & 0xf); + if ((regs[0x5a] ^ val) & 0xf0) + i4x0_map(dev, 0xc4000, 0x04000, val >> 4); + regs[0x5a] = val & 0x77; + break; + case 0x5b: /*PAM2 */ + if ((regs[0x5b] ^ val) & 0x0f) + i4x0_map(dev, 0xc8000, 0x04000, val & 0xf); + if ((regs[0x5b] ^ val) & 0xf0) + i4x0_map(dev, 0xcc000, 0x04000, val >> 4); + regs[0x5b] = val & 0x77; + break; + case 0x5c: /*PAM3 */ + if ((regs[0x5c] ^ val) & 0x0f) + i4x0_map(dev, 0xd0000, 0x04000, val & 0xf); + if ((regs[0x5c] ^ val) & 0xf0) + i4x0_map(dev, 0xd4000, 0x04000, val >> 4); + regs[0x5c] = val & 0x77; + break; + case 0x5d: /* PAM4 */ + if ((regs[0x5d] ^ val) & 0x0f) + i4x0_map(dev, 0xd8000, 0x04000, val & 0xf); + if ((regs[0x5d] ^ val) & 0xf0) + i4x0_map(dev, 0xdc000, 0x04000, val >> 4); + regs[0x5d] = val & 0x77; + break; + case 0x5e: /* PAM5 */ + if ((regs[0x5e] ^ val) & 0x0f) + i4x0_map(dev, 0xe0000, 0x04000, val & 0xf); + if ((regs[0x5e] ^ val) & 0xf0) + i4x0_map(dev, 0xe4000, 0x04000, val >> 4); + regs[0x5e] = val & 0x77; + break; + case 0x5f: /* PAM6 */ + if ((regs[0x5f] ^ val) & 0x0f) + i4x0_map(dev, 0xe8000, 0x04000, val & 0xf); + if ((regs[0x5f] ^ val) & 0xf0) + i4x0_map(dev, 0xec000, 0x04000, val >> 4); + regs[0x5f] = val & 0x77; + break; + case 0x60: + case 0x61: + case 0x62: + case 0x63: + case 0x64: + if ((addr & 0x7) <= dev->max_drb) { + dev->write_drbs(regs, 0x60, 0x60 + dev->max_drb, dev->drb_unit); + break; + } + switch (dev->type) { + default: + case INTEL_420TX: + case INTEL_420ZX: + case INTEL_430LX: + case INTEL_430NX: + case INTEL_430HX: + case INTEL_440FX: + case INTEL_440LX: + case INTEL_440EX: + case INTEL_440BX: + case INTEL_440ZX: + case INTEL_440GX: + regs[addr] = val; + break; + case INTEL_430FX: + case INTEL_430VX: + regs[addr] = val & 0x3f; + break; + case INTEL_430TX: + regs[addr] = val & 0x7f; + break; + } + break; + case 0x65: + if ((addr & 0x7) <= dev->max_drb) { + dev->write_drbs(regs, 0x60, 0x60 + dev->max_drb, dev->drb_unit); + break; + } + switch (dev->type) { + case INTEL_420TX: + case INTEL_420ZX: + case INTEL_430LX: + case INTEL_430NX: + case INTEL_430HX: + case INTEL_440FX: + case INTEL_440LX: + case INTEL_440EX: + case INTEL_440GX: + case INTEL_440BX: + case INTEL_440ZX: + regs[addr] = val; + break; + case INTEL_430VX: + regs[addr] = val & 0x3f; + break; + case INTEL_430TX: + regs[addr] = val & 0x7f; + break; + default: + break; + } + break; + case 0x66: + if ((addr & 0x7) <= dev->max_drb) { + dev->write_drbs(regs, 0x60, 0x60 + dev->max_drb, dev->drb_unit); + break; + } + switch (dev->type) { + case INTEL_430NX: + case INTEL_430HX: + case INTEL_440FX: + case INTEL_440LX: + case INTEL_440EX: + case INTEL_440GX: + case INTEL_440BX: + case INTEL_440ZX: + regs[addr] = val; + break; + default: + break; + } + break; + case 0x67: + if ((addr & 0x7) <= dev->max_drb) { + dev->write_drbs(regs, 0x60, 0x60 + dev->max_drb, dev->drb_unit); + break; + } + switch (dev->type) { + case INTEL_430NX: + case INTEL_430HX: + case INTEL_440FX: + case INTEL_440LX: + case INTEL_440EX: + case INTEL_440BX: + case INTEL_440GX: + case INTEL_440ZX: + regs[addr] = val; + break; + case INTEL_430VX: + regs[addr] = val & 0x11; + break; + case INTEL_430TX: + regs[addr] = val & 0xb7; + break; + default: + break; + } + break; + case 0x68: + if (dev->type == INTEL_430NX) { + dev->write_drbs(regs, 0x60, 0x60 + dev->max_drb, dev->drb_unit); + break; + } + switch (dev->type) { + case INTEL_430HX: + case INTEL_430VX: + case INTEL_430TX: + regs[0x68] = val; + break; + case INTEL_430FX: + regs[0x68] = val & 0x1f; + break; + case INTEL_440FX: + case INTEL_440LX: + case INTEL_440EX: + case INTEL_440GX: + regs[0x68] = val & 0xc0; + break; + case INTEL_440BX: + regs[0x68] = (regs[0x68] & 0x38) | (val & 0xc7); + break; + case INTEL_440ZX: + regs[0x68] = (regs[0x68] & 0x3f) | (val & 0xc0); + break; + default: + break; + } + break; + case 0x69: + if (dev->type == INTEL_430NX) { + dev->write_drbs(regs, 0x60, 0x60 + dev->max_drb, dev->drb_unit); + break; + } + switch (dev->type) { + case INTEL_440BX: + case INTEL_440GX: + regs[0x69] = val; + break; + case INTEL_430VX: + regs[0x69] = val & 0x07; + break; + case INTEL_440ZX: + regs[0x69] = val & 0x3f; + break; + default: + break; + } + break; + case 0x6a: + case 0x6b: + if (dev->type == INTEL_430NX) { + dev->write_drbs(regs, 0x60, 0x60 + dev->max_drb, dev->drb_unit); + break; + } + switch (dev->type) { + case INTEL_440BX: + case INTEL_440GX: + regs[addr] = val; + break; + case INTEL_440LX: + case INTEL_440EX: + if (addr == 0x6a) + regs[addr] = val & 0xef; + break; + case INTEL_440ZX: + if (addr == 0x6a) + regs[addr] = val & 0xfc; + else + regs[addr] = val & 0x33; + break; + default: + break; + } + break; + case 0x6c: + case 0x6d: + case 0x6e: + switch (dev->type) { + case INTEL_440LX: + case INTEL_440EX: + case INTEL_440BX: + case INTEL_440GX: + if (addr != 0x6e) + regs[addr] = val; + break; + case INTEL_440ZX: + if (addr == 0x6c) + regs[addr] = val & 0x03; + else if (addr == 0x6d) + regs[addr] = val & 0xcf; + break; + default: + break; + } + break; + case 0x6f: + switch (dev->type) { + case INTEL_440LX: + regs[addr] = val; + break; + case INTEL_440EX: + regs[addr] = val & 0xcf; + break; + default: + break; + } + break; + case 0x70: + switch (dev->type) { + case INTEL_420TX: + case INTEL_420ZX: + case INTEL_430LX: + regs[addr] = val & 0xc7; + break; + case INTEL_430NX: + regs[addr] = val; + break; + case INTEL_430VX: + case INTEL_430TX: + regs[addr] = val & 0xfc; + break; + case INTEL_440FX: + case INTEL_440LX: + case INTEL_440EX: + regs[addr] = val & 0xf8; + break; + default: + break; + } + break; + case 0x71: + switch (dev->type) { + case INTEL_420TX: + case INTEL_420ZX: + case INTEL_430LX: + regs[addr] = val & 0x4d; + break; + case INTEL_430TX: + if (!dev->smram_locked) { + i4x0_smram_handler_phase0(dev); + regs[0x71] = (regs[0x71] & 0x20) | (val & 0xdf); + i4x0_smram_handler_phase1(dev); + } + break; + case INTEL_440EX: + regs[addr] = val; + break; + case INTEL_440FX: + case INTEL_440LX: + regs[addr] = val & 0x1f; + break; + default: + break; + } + break; + case 0x72: /* SMRAM */ + if (dev->type <= INTEL_420ZX) + break; - } - break; - case 0x51: - switch (dev->type) { - case INTEL_420TX: case INTEL_420ZX: case INTEL_430LX: case INTEL_430NX: - regs[0x51] = (val & 0xc0); - break; - case INTEL_440FX: - regs[0x51] = (val & 0xc3); - break; - case INTEL_440LX: - regs[0x51] = (regs[0x51] & 0x40) | (val & 0x87); - i4x0_mask_bar(regs, dev->agpgart); - break; - case INTEL_440EX: - regs[0x51] = (val & 0x86); - i4x0_mask_bar(regs, dev->agpgart); - break; - case INTEL_440BX: case INTEL_440ZX: - regs[0x51] = (regs[0x51] & 0x70) | (val & 0x8f); - i4x0_mask_bar(regs, dev->agpgart); - break; - case INTEL_440GX: - regs[0x51] = (regs[0x51] & 0xb0) | (val & 0x4f); - i4x0_mask_bar(regs, dev->agpgart); - break; - } - break; - case 0x52: /* Cache Control Register */ - switch (dev->type) { - case INTEL_420TX: case INTEL_420ZX: - case INTEL_430LX: case INTEL_430FX: - case INTEL_430VX: case INTEL_430TX: - default: - regs[0x52] = (val & 0xfb); - break; - case INTEL_430NX: case INTEL_430HX: - case INTEL_440FX: - regs[0x52] = val; - break; - case INTEL_440BX: case INTEL_440ZX: - case INTEL_440GX: - regs[0x52] = val & 0x07; - break; - } - break; - case 0x53: - switch (dev->type) { - case INTEL_420TX: case INTEL_420ZX: - case INTEL_430LX: - regs[0x53] = val & 0x0b; - break; - case INTEL_430NX: - regs[0x53] = val & 0x0a; - break; - case INTEL_430VX: case INTEL_430TX: - regs[0x53] = val & 0x3f; - break; - case INTEL_440LX: case INTEL_440EX: - regs[0x53] = val & 0x60; - break; - case INTEL_440BX: case INTEL_440GX: - /* Not applicable to 440ZX as that does not support ECC. */ - regs[0x53] = val; - break; - } - break; - case 0x54: - switch (dev->type) { - case INTEL_420TX: case INTEL_420ZX: - case INTEL_430LX: case INTEL_430NX: - regs[0x54] = val & 0x07; - break; - case INTEL_430VX: - regs[0x54] = val & 0xd8; - break; - case INTEL_430TX: - regs[0x54] = val & 0xfa; - break; - case INTEL_440FX: - regs[0x54] = val & 0x82; - break; - } - break; - case 0x55: - switch (dev->type) { - case INTEL_420TX: case INTEL_420ZX: - /* According to the FreeBSD 3.x source code, the 420TX/ZX chipset has - this register. The mask is unknown, so write all bits. */ - regs[0x55] = val; - break; - case INTEL_430VX: case INTEL_430TX: - regs[0x55] = val & 0x01; - break; - case INTEL_440FX: case INTEL_440LX: - case INTEL_440EX: - regs[0x55] = val; - break; - } - break; - case 0x56: - switch (dev->type) { - case INTEL_420TX: case INTEL_420ZX: - /* According to the FreeBSD 3.x source code, the 420TX/ZX chipset has - this register. The mask is unknown, so write all bits. */ - regs[0x56] = val; - break; - case INTEL_430HX: - regs[0x56] = val & 0x1f; - break; - case INTEL_430VX: - regs[0x56] = val & 0x77; - break; - case INTEL_430TX: - regs[0x56] = val & 0x76; - break; - case INTEL_440FX: - case INTEL_440LX: case INTEL_440EX: - regs[0x56] = val; - break; - } - break; - case 0x57: - switch (dev->type) { - /* On the 420TX and 420ZX, this is the SMRAM space register. */ - case INTEL_420TX: case INTEL_420ZX: - i4x0_smram_handler_phase0(dev); - if (dev->smram_locked) - regs[0x57] = (regs[0x57] & 0xdf) | (val & 0x20); - else { - regs[0x57] = (regs[0x57] & 0x87) | (val & 0x78); - dev->smram_locked = (val & 0x10); - if (dev->smram_locked) - regs[0x57] &= 0xbf; - } - i4x0_smram_handler_phase1(dev); - break; - case INTEL_430LX: default: - regs[0x57] = val & 0x3f; - break; - case INTEL_430NX: - regs[0x57] = val; - break; - case INTEL_430FX: case INTEL_430HX: - case INTEL_430VX: - regs[0x57] = val & 0xcf; - break; - case INTEL_430TX: - regs[0x57] = val & 0xdf; - break; - case INTEL_440FX: - regs[0x57] = val & 0x77; - break; - case INTEL_440LX: case INTEL_440EX: - regs[0x57] = val & 0x37; - break; - case INTEL_440BX: case INTEL_440GX: - regs[0x57] = val & 0x3f; - break; - case INTEL_440ZX: - regs[0x57] = val & 0x2f; - break; - } - break; - case 0x58: - switch (dev->type) { - case INTEL_420TX: case INTEL_420ZX: - case INTEL_430LX: default: - regs[0x58] = val & 0x01; - break; - case INTEL_430NX: - case INTEL_440BX: case INTEL_440ZX: - regs[0x58] = val & 0x03; - break; - case INTEL_430FX: case INTEL_440FX: - regs[0x58] = val & 0x7f; - break; - case INTEL_430HX: case INTEL_430VX: - case INTEL_440LX: case INTEL_440EX: - regs[0x58] = val; - break; - case INTEL_430TX: - regs[0x58] = val & 0x7b; - break; - } - break; - case 0x59: /* PAM0 */ - if (dev->type <= INTEL_430NX) { - if ((regs[0x59] ^ val) & 0x0f) - i4x0_map(dev, 0x80000, 0x20000, val & 0x0f); - } - if ((regs[0x59] ^ val) & 0xf0) { - i4x0_map(dev, 0xf0000, 0x10000, val >> 4); - shadowbios = (val & 0x10); - } - if (dev->type > INTEL_430NX) - regs[0x59] = val & 0x70; - else - regs[0x59] = val & 0x77; - break; - case 0x5a: /* PAM1 */ - if ((regs[0x5a] ^ val) & 0x0f) - i4x0_map(dev, 0xc0000, 0x04000, val & 0xf); - if ((regs[0x5a] ^ val) & 0xf0) - i4x0_map(dev, 0xc4000, 0x04000, val >> 4); - regs[0x5a] = val & 0x77; - break; - case 0x5b: /*PAM2 */ - if ((regs[0x5b] ^ val) & 0x0f) - i4x0_map(dev, 0xc8000, 0x04000, val & 0xf); - if ((regs[0x5b] ^ val) & 0xf0) - i4x0_map(dev, 0xcc000, 0x04000, val >> 4); - regs[0x5b] = val & 0x77; - break; - case 0x5c: /*PAM3 */ - if ((regs[0x5c] ^ val) & 0x0f) - i4x0_map(dev, 0xd0000, 0x04000, val & 0xf); - if ((regs[0x5c] ^ val) & 0xf0) - i4x0_map(dev, 0xd4000, 0x04000, val >> 4); - regs[0x5c] = val & 0x77; - break; - case 0x5d: /* PAM4 */ - if ((regs[0x5d] ^ val) & 0x0f) - i4x0_map(dev, 0xd8000, 0x04000, val & 0xf); - if ((regs[0x5d] ^ val) & 0xf0) - i4x0_map(dev, 0xdc000, 0x04000, val >> 4); - regs[0x5d] = val & 0x77; - break; - case 0x5e: /* PAM5 */ - if ((regs[0x5e] ^ val) & 0x0f) - i4x0_map(dev, 0xe0000, 0x04000, val & 0xf); - if ((regs[0x5e] ^ val) & 0xf0) - i4x0_map(dev, 0xe4000, 0x04000, val >> 4); - regs[0x5e] = val & 0x77; - break; - case 0x5f: /* PAM6 */ - if ((regs[0x5f] ^ val) & 0x0f) - i4x0_map(dev, 0xe8000, 0x04000, val & 0xf); - if ((regs[0x5f] ^ val) & 0xf0) - i4x0_map(dev, 0xec000, 0x04000, val >> 4); - regs[0x5f] = val & 0x77; - break; - case 0x60: case 0x61: case 0x62: case 0x63: case 0x64: - if ((addr & 0x7) <= dev->max_drb) { - dev->write_drbs(regs, 0x60, 0x60 + dev->max_drb, dev->drb_unit); - break; - } - switch (dev->type) { - case INTEL_420TX: case INTEL_420ZX: - case INTEL_430LX: case INTEL_430NX: - case INTEL_430HX: - case INTEL_440FX: - case INTEL_440LX: case INTEL_440EX: - case INTEL_440BX: case INTEL_440ZX: - case INTEL_440GX: - default: - regs[addr] = val; - break; - case INTEL_430FX: case INTEL_430VX: - regs[addr] = val & 0x3f; - break; - case INTEL_430TX: - regs[addr] = val & 0x7f; - break; - } - break; - case 0x65: - if ((addr & 0x7) <= dev->max_drb) { - dev->write_drbs(regs, 0x60, 0x60 + dev->max_drb, dev->drb_unit); - break; - } - switch (dev->type) { - case INTEL_420TX: case INTEL_420ZX: - case INTEL_430LX: case INTEL_430NX: - case INTEL_430HX: - case INTEL_440FX: - case INTEL_440LX: case INTEL_440EX: - case INTEL_440GX: - case INTEL_440BX: case INTEL_440ZX: - regs[addr] = val; - break; - case INTEL_430VX: - regs[addr] = val & 0x3f; - break; - case INTEL_430TX: - regs[addr] = val & 0x7f; - break; - } - break; - case 0x66: - if ((addr & 0x7) <= dev->max_drb) { - dev->write_drbs(regs, 0x60, 0x60 + dev->max_drb, dev->drb_unit); - break; - } - switch (dev->type) { - case INTEL_430NX: case INTEL_430HX: - case INTEL_440FX: case INTEL_440LX: - case INTEL_440EX: case INTEL_440GX: - case INTEL_440BX: case INTEL_440ZX: - regs[addr] = val; - break; - } - break; - case 0x67: - if ((addr & 0x7) <= dev->max_drb) { - dev->write_drbs(regs, 0x60, 0x60 + dev->max_drb, dev->drb_unit); - break; - } - switch (dev->type) { - case INTEL_430NX: case INTEL_430HX: - case INTEL_440FX: - case INTEL_440LX: case INTEL_440EX: - case INTEL_440BX: case INTEL_440GX: - case INTEL_440ZX: - regs[addr] = val; - break; - case INTEL_430VX: - regs[addr] = val & 0x11; - break; - case INTEL_430TX: - regs[addr] = val & 0xb7; - break; - } - break; - case 0x68: - if (dev->type == INTEL_430NX) { - dev->write_drbs(regs, 0x60, 0x60 + dev->max_drb, dev->drb_unit); - break; - } - switch (dev->type) { - case INTEL_430HX: - case INTEL_430VX: case INTEL_430TX: - regs[0x68] = val; - break; - case INTEL_430FX: - regs[0x68] = val & 0x1f; - break; - case INTEL_440FX: - case INTEL_440LX: case INTEL_440EX: - case INTEL_440GX: - regs[0x68] = val & 0xc0; - break; - case INTEL_440BX: - regs[0x68] = (regs[0x68] & 0x38) | (val & 0xc7); - break; - case INTEL_440ZX: - regs[0x68] = (regs[0x68] & 0x3f) | (val & 0xc0); - break; - } - break; - case 0x69: - if (dev->type == INTEL_430NX) { - dev->write_drbs(regs, 0x60, 0x60 + dev->max_drb, dev->drb_unit); - break; - } - switch (dev->type) { - case INTEL_440BX: case INTEL_440GX: - regs[0x69] = val; - break; - case INTEL_430VX: - regs[0x69] = val & 0x07; - break; - case INTEL_440ZX: - regs[0x69] = val & 0x3f; - break; - } - break; - case 0x6a: case 0x6b: - if (dev->type == INTEL_430NX) { - dev->write_drbs(regs, 0x60, 0x60 + dev->max_drb, dev->drb_unit); - break; - } - switch (dev->type) { - case INTEL_440BX: case INTEL_440GX: - regs[addr] = val; - break; - case INTEL_440LX: case INTEL_440EX: - if (addr == 0x6a) - regs[addr] = val & 0xef; - break; - case INTEL_440ZX: - if (addr == 0x6a) - regs[addr] = val & 0xfc; - else - regs[addr] = val & 0x33; - break; - } - break; - case 0x6c: case 0x6d: case 0x6e: - switch (dev->type) { - case INTEL_440LX: case INTEL_440EX: - case INTEL_440BX: case INTEL_440GX: - if (addr != 0x6e) - regs[addr] = val; - break; - case INTEL_440ZX: - if (addr == 0x6c) - regs[addr] = val & 0x03; - else if (addr == 0x6d) - regs[addr] = val & 0xcf; - break; - } - break; - case 0x6f: - switch (dev->type) { - case INTEL_440LX: - regs[addr] = val; - break; - case INTEL_440EX: - regs[addr] = val & 0xcf; - break; - } - break; - case 0x70: - switch (dev->type) { - case INTEL_420TX: case INTEL_420ZX: - case INTEL_430LX: - regs[addr] = val & 0xc7; - break; - case INTEL_430NX: - regs[addr] = val; - break; - case INTEL_430VX: case INTEL_430TX: - regs[addr] = val & 0xfc; - break; - case INTEL_440FX: - case INTEL_440LX: case INTEL_440EX: - regs[addr] = val & 0xf8; - break; - } - break; - case 0x71: - switch (dev->type) { - case INTEL_420TX: case INTEL_420ZX: - case INTEL_430LX: - regs[addr] = val & 0x4d; - break; - case INTEL_430TX: - if (!dev->smram_locked) { - i4x0_smram_handler_phase0(dev); - regs[0x71] = (regs[0x71] & 0x20) | (val & 0xdf); - i4x0_smram_handler_phase1(dev); - } - break; - case INTEL_440EX: - regs[addr] = val; - break; - case INTEL_440FX: case INTEL_440LX: - regs[addr] = val & 0x1f; - break; - } - break; - case 0x72: /* SMRAM */ - if (dev->type <= INTEL_420ZX) - break; + i4x0_smram_handler_phase0(dev); + if (dev->type >= INTEL_430FX) { + if (dev->smram_locked) + regs[0x72] = (regs[0x72] & 0xdf) | (val & 0x20); + else { + if ((dev->type == INTEL_440LX) || (dev->type == INTEL_440EX) || (dev->type == INTEL_440GX)) + regs[0x72] = (val & 0x7f); + else + regs[0x72] = (regs[0x72] & 0x87) | (val & 0x78); + dev->smram_locked = (val & 0x10); + if (dev->smram_locked) + regs[0x72] &= 0xbf; + } + } else { + if (dev->smram_locked) + regs[0x72] = (regs[0x72] & 0xef) | (val & 0x10); + else { + regs[0x72] = (regs[0x72] & 0xc0) | (val & 0x3f); + dev->smram_locked = (val & 0x08); + if (dev->smram_locked) + regs[0x72] &= 0xdf; + } + } + i4x0_smram_handler_phase1(dev); + break; + case 0x73: + switch (dev->type) { + case INTEL_430VX: + regs[0x73] = val & 0x03; + break; + case INTEL_440BX: + case INTEL_440ZX: + case INTEL_440GX: + if (!dev->smram_locked) { + i4x0_smram_handler_phase0(dev); + regs[0x73] = (regs[0x73] & 0x38) | (val & 0xc7); + i4x0_smram_handler_phase1(dev); + } + break; + default: + break; + } + break; + case 0x74: + switch (dev->type) { + case INTEL_430VX: + case INTEL_440BX: + case INTEL_440ZX: + case INTEL_440GX: + regs[0x74] = val; + break; + default: + break; + } + break; + case 0x75: + case 0x76: + case 0x7b: + switch (dev->type) { + case INTEL_440BX: + case INTEL_440ZX: + case INTEL_440GX: + regs[addr] = val; + break; - i4x0_smram_handler_phase0(dev); - if (dev->type >= INTEL_430FX) { - if (dev->smram_locked) - regs[0x72] = (regs[0x72] & 0xdf) | (val & 0x20); - else { - if ((dev->type == INTEL_440LX) || (dev->type == INTEL_440EX) || - (dev->type == INTEL_440GX)) - regs[0x72] = (val & 0x7f); - else - regs[0x72] = (regs[0x72] & 0x87) | (val & 0x78); - dev->smram_locked = (val & 0x10); - if (dev->smram_locked) - regs[0x72] &= 0xbf; - } - } else { - if (dev->smram_locked) - regs[0x72] = (regs[0x72] & 0xef) | (val & 0x10); - else { - regs[0x72] = (regs[0x72] & 0xc0) | (val & 0x3f); - dev->smram_locked = (val & 0x08); - if (dev->smram_locked) - regs[0x72] &= 0xdf; - } - } - i4x0_smram_handler_phase1(dev); - break; - case 0x73: - switch (dev->type) { - case INTEL_430VX: - regs[0x73] = val & 0x03; - break; - case INTEL_440BX: case INTEL_440ZX: - case INTEL_440GX: - if (!dev->smram_locked) { - i4x0_smram_handler_phase0(dev); - regs[0x73] = (regs[0x73] & 0x38) | (val & 0xc7); - i4x0_smram_handler_phase1(dev); - } - break; - } - break; - case 0x74: - switch (dev->type) { - case INTEL_430VX: - case INTEL_440BX: case INTEL_440ZX: - case INTEL_440GX: - regs[0x74] = val; - break; - } - break; - case 0x75: case 0x76: - case 0x7b: - switch (dev->type) { - case INTEL_440BX: case INTEL_440ZX: - case INTEL_440GX: - regs[addr] = val; - } - break; - case 0x77: - switch (dev->type) { - case INTEL_440BX: case INTEL_440ZX: - regs[0x77] = val & 0x03; - } - break; - case 0x78: - switch (dev->type) { - case INTEL_430VX: - regs[0x78] = val & 0xcf; - break; - case INTEL_440BX: case INTEL_440ZX: - regs[0x78] = val & 0x0f; - break; - case INTEL_440GX: - regs[0x78] = val & 0x1f; - break; - } - break; - case 0x79: - switch (dev->type) { - case INTEL_430TX: - regs[0x79] = val & 0x74; - io_removehandler(0x0022, 0x01, pm2_cntrl_read, NULL, NULL, pm2_cntrl_write, NULL, NULL, dev); - if (val & 0x40) - io_sethandler(0x0022, 0x01, pm2_cntrl_read, NULL, NULL, pm2_cntrl_write, NULL, NULL, dev); - break; - case INTEL_440BX: case INTEL_440ZX: - case INTEL_440GX: - regs[0x79] = val; - break; - } - break; - case 0x7a: - switch (dev->type) { - case INTEL_440BX: case INTEL_440ZX: - case INTEL_440GX: - regs[0x7a] = (regs[0x7a] & 0x0a) | (val & 0xf5); - io_removehandler(0x0022, 0x01, pm2_cntrl_read, NULL, NULL, pm2_cntrl_write, NULL, NULL, dev); - if (val & 0x40) - io_sethandler(0x0022, 0x01, pm2_cntrl_read, NULL, NULL, pm2_cntrl_write, NULL, NULL, dev); - break; - } - break; - case 0x7c: - switch (dev->type) { - case INTEL_420TX: case INTEL_420ZX: - case INTEL_430LX: case INTEL_430NX: - regs[0x7c] = val & 0x8f; - break; - case INTEL_440BX: case INTEL_440GX: - case INTEL_440ZX: - regs[0x7c] = val & 0x1f; - break; - } - break; - case 0x7d: - switch (dev->type) { - case INTEL_420TX: case INTEL_420ZX: - case INTEL_430LX: case INTEL_430NX: - regs[0x7d] = val & 0x32; - break; - } - break; - case 0x7e: case 0x7f: - switch (dev->type) { - case INTEL_420TX: case INTEL_420ZX: - case INTEL_430LX: case INTEL_430NX: - regs[addr] = val; - break; - } - break; - case 0x80: - switch (dev->type) { - case INTEL_440BX: case INTEL_440ZX: - case INTEL_440GX: - regs[0x80] &= ~(val & 0x03); - break; - } - break; - case 0x90: - switch (dev->type) { - case INTEL_430HX: - regs[0x90] = val & 0x87; - break; - case INTEL_440FX: - regs[0x90] = val & 0x1b; - break; - case INTEL_440LX: - regs[0x90] = val & 0xfb; - break; - case INTEL_440EX: - regs[0x90] = val & 0xf8; - break; - case INTEL_440BX: case INTEL_440ZX: - case INTEL_440GX: - regs[0x90] = val; - break; - } - break; - case 0x91: - switch (dev->type) { - case INTEL_430HX: case INTEL_440BX: - case INTEL_440FX: case INTEL_440LX: - case INTEL_440GX: - /* Not applicable on 82443EX and 82443ZX. */ - regs[0x91] &= ~(val & 0x11); - break; - } - break; - case 0x92: - switch (dev->type) { - case INTEL_440LX: case INTEL_440EX: - regs[0x92] &= ~(val & 0x07); - break; - case INTEL_440BX: case INTEL_440ZX: - case INTEL_440GX: - regs[0x92] &= ~(val & 0x1f); - break; - } - break; - case 0x93: - switch (dev->type) { - case INTEL_440FX: - regs[0x93] = (val & 0x0f); - trc_write(0x0093, val & 0x06, NULL); - break; - case INTEL_440LX: case INTEL_440EX: - regs[0x93] = (val & 0x0e); - trc_write(0x0093, val & 0x06, NULL); - break; - } - break; - case 0xa7: - switch (dev->type) { - case INTEL_440LX: case INTEL_440EX: - regs[0xa7] = val & 0x1f; - break; - } - break; - case 0xa8: case 0xa9: - switch (dev->type) { - case INTEL_440LX: case INTEL_440EX: - case INTEL_440BX: case INTEL_440ZX: - case INTEL_440GX: - regs[addr] = (val & 0x03); - break; - } - break; - case 0xb0: - switch (dev->type) { - case INTEL_440LX: case INTEL_440EX: - case INTEL_440BX: case INTEL_440ZX: - case INTEL_440GX: - regs[0xb0] = (val & 0x80); - break; - } - break; - case 0xb1: - switch (dev->type) { - case INTEL_440LX: case INTEL_440EX: - regs[0xb1] = (val & 0x22); - break; - case INTEL_440BX: case INTEL_440ZX: - case INTEL_440GX: - regs[0xb1] = (val & 0xa0); - break; - } - break; - case 0xb4: - switch (dev->type) { - case INTEL_440LX: case INTEL_440EX: - case INTEL_440BX: case INTEL_440ZX: - case INTEL_440GX: - regs[0xb4] = (val & 0x3f); - i4x0_mask_bar(regs, dev->agpgart); - break; - } - break; - case 0xb9: - switch (dev->type) { - case INTEL_440LX: case INTEL_440EX: - case INTEL_440BX: case INTEL_440ZX: - case INTEL_440GX: - regs[0xb9] = (val & 0xf0); - i4x0_mask_bar(regs, dev->agpgart); - break; - } - break; + default: + break; + } + break; + case 0x77: + switch (dev->type) { + case INTEL_440BX: + case INTEL_440ZX: + regs[0x77] = val & 0x03; + break; - case 0xba: case 0xbb: - switch (dev->type) { - case INTEL_440LX: case INTEL_440EX: - case INTEL_440BX: case INTEL_440ZX: - case INTEL_440GX: - regs[addr] = val; - i4x0_mask_bar(regs, dev->agpgart); - break; - } - break; + default: + break; + } + break; + case 0x78: + switch (dev->type) { + case INTEL_430VX: + regs[0x78] = val & 0xcf; + break; + case INTEL_440BX: + case INTEL_440ZX: + regs[0x78] = val & 0x0f; + break; + case INTEL_440GX: + regs[0x78] = val & 0x1f; + break; + default: + break; + } + break; + case 0x79: + switch (dev->type) { + case INTEL_430TX: + regs[0x79] = val & 0x74; + io_removehandler(0x0022, 0x01, pm2_cntrl_read, NULL, NULL, pm2_cntrl_write, NULL, NULL, dev); + if (val & 0x40) + io_sethandler(0x0022, 0x01, pm2_cntrl_read, NULL, NULL, pm2_cntrl_write, NULL, NULL, dev); + break; + case INTEL_440BX: + case INTEL_440ZX: + case INTEL_440GX: + regs[0x79] = val; + break; + default: + break; + } + break; + case 0x7a: + switch (dev->type) { + case INTEL_440BX: + case INTEL_440ZX: + case INTEL_440GX: + regs[0x7a] = (regs[0x7a] & 0x0a) | (val & 0xf5); + io_removehandler(0x0022, 0x01, pm2_cntrl_read, NULL, NULL, pm2_cntrl_write, NULL, NULL, dev); + if (val & 0x40) + io_sethandler(0x0022, 0x01, pm2_cntrl_read, NULL, NULL, pm2_cntrl_write, NULL, NULL, dev); + break; + default: + break; + } + break; + case 0x7c: + switch (dev->type) { + case INTEL_420TX: + case INTEL_420ZX: + case INTEL_430LX: + case INTEL_430NX: + regs[0x7c] = val & 0x8f; + break; + case INTEL_440BX: + case INTEL_440GX: + case INTEL_440ZX: + regs[0x7c] = val & 0x1f; + break; + default: + break; + } + break; + case 0x7d: + switch (dev->type) { + case INTEL_420TX: + case INTEL_420ZX: + case INTEL_430LX: + case INTEL_430NX: + regs[0x7d] = val & 0x32; + break; + default: + break; + } + break; + case 0x7e: + case 0x7f: + switch (dev->type) { + case INTEL_420TX: + case INTEL_420ZX: + case INTEL_430LX: + case INTEL_430NX: + regs[addr] = val; + break; + default: + break; + } + break; + case 0x80: + switch (dev->type) { + case INTEL_440BX: + case INTEL_440ZX: + case INTEL_440GX: + regs[0x80] &= ~(val & 0x03); + break; + default: + break; + } + break; + case 0x90: + switch (dev->type) { + case INTEL_430HX: + regs[0x90] = val & 0x87; + break; + case INTEL_440FX: + regs[0x90] = val & 0x1b; + break; + case INTEL_440LX: + regs[0x90] = val & 0xfb; + break; + case INTEL_440EX: + regs[0x90] = val & 0xf8; + break; + case INTEL_440BX: + case INTEL_440ZX: + case INTEL_440GX: + regs[0x90] = val; + break; + default: + break; + } + break; + case 0x91: + switch (dev->type) { + case INTEL_430HX: + case INTEL_440BX: + case INTEL_440FX: + case INTEL_440LX: + case INTEL_440GX: + /* Not applicable on 82443EX and 82443ZX. */ + regs[0x91] &= ~(val & 0x11); + break; + default: + break; + } + break; + case 0x92: + switch (dev->type) { + case INTEL_440LX: + case INTEL_440EX: + regs[0x92] &= ~(val & 0x07); + break; + case INTEL_440BX: + case INTEL_440ZX: + case INTEL_440GX: + regs[0x92] &= ~(val & 0x1f); + break; + default: + break; + } + break; + case 0x93: + switch (dev->type) { + case INTEL_440FX: + regs[0x93] = (val & 0x0f); + pci_write(0x0cf9, val & 0x06, NULL); + break; + case INTEL_440LX: + case INTEL_440EX: + regs[0x93] = (val & 0x0e); + pci_write(0x0cf9, val & 0x06, NULL); + break; + default: + break; + } + break; + case 0xa7: + switch (dev->type) { + case INTEL_440LX: + case INTEL_440EX: + regs[0xa7] = val & 0x1f; + break; + default: + break; + } + break; + case 0xa8: + case 0xa9: + switch (dev->type) { + case INTEL_440LX: + case INTEL_440EX: + case INTEL_440BX: + case INTEL_440ZX: + case INTEL_440GX: + regs[addr] = (val & 0x03); + break; + default: + break; + } + break; + case 0xb0: + switch (dev->type) { + case INTEL_440LX: + case INTEL_440EX: + case INTEL_440BX: + case INTEL_440ZX: + case INTEL_440GX: + regs[0xb0] = (val & 0x80); + break; + default: + break; + } + break; + case 0xb1: + switch (dev->type) { + case INTEL_440LX: + case INTEL_440EX: + regs[0xb1] = (val & 0x22); + break; + case INTEL_440BX: + case INTEL_440ZX: + case INTEL_440GX: + regs[0xb1] = (val & 0xa0); + break; + default: + break; + } + break; + case 0xb4: + switch (dev->type) { + case INTEL_440LX: + case INTEL_440EX: + case INTEL_440BX: + case INTEL_440ZX: + case INTEL_440GX: + regs[0xb4] = (val & 0x3f); + i4x0_mask_bar(regs, dev->agpgart); + break; + default: + break; + } + break; + case 0xb9: + switch (dev->type) { + case INTEL_440LX: + case INTEL_440EX: + case INTEL_440BX: + case INTEL_440ZX: + case INTEL_440GX: + regs[0xb9] = (val & 0xf0); + i4x0_mask_bar(regs, dev->agpgart); + break; + default: + break; + } + break; - case 0xbc: - switch (dev->type) { - case INTEL_440LX: case INTEL_440EX: - regs[addr] = (val & 0xf8); - break; - } - break; + case 0xba: + case 0xbb: + switch (dev->type) { + case INTEL_440LX: + case INTEL_440EX: + case INTEL_440BX: + case INTEL_440ZX: + case INTEL_440GX: + regs[addr] = val; + i4x0_mask_bar(regs, dev->agpgart); + break; + default: + break; + } + break; - case 0xbd: - switch (dev->type) { - case INTEL_440LX: case INTEL_440EX: - regs[addr] = (val & 0xf8); - break; - } - break; + case 0xbc: + switch (dev->type) { + case INTEL_440LX: + case INTEL_440EX: + regs[addr] = (val & 0xf8); + break; + default: + break; + } + break; - case 0xd0: case 0xd1: case 0xd2: case 0xd3: - case 0xd4: case 0xd5: case 0xd6: case 0xd7: - switch (dev->type) { - case INTEL_440BX: case INTEL_440ZX: - case INTEL_440GX: - regs[addr] = val; - break; - } - break; - case 0xca: - switch (dev->type) { - case INTEL_440BX: case INTEL_440GX: - regs[addr] = val; - break; - case INTEL_440ZX: - regs[addr] = val & 0xe7; - break; - } - break; - case 0xcb: - switch (dev->type) { - case INTEL_440BX: case INTEL_440GX: - regs[addr] = val; - break; - case INTEL_440ZX: - regs[addr] = val & 0xa7; - break; - } - break; - case 0xcc: - switch (dev->type) { - case INTEL_440BX: case INTEL_440GX: - regs[0xcc] = (val & 0x7f); - break; - case INTEL_440ZX: - regs[0xcc] = (val & 0x58); - break; - } - break; - case 0xe0: case 0xe1: case 0xe2: case 0xe3: case 0xe4: - case 0xe8: case 0xe9: case 0xea: case 0xeb: case 0xec: - switch (dev->type) { - case INTEL_440BX: case INTEL_440ZX: - case INTEL_440GX: - if (!regs_l[addr]) - regs[addr] = val; - break; - } - break; - case 0xe5: case 0xed: - switch (dev->type) { - case INTEL_440BX: case INTEL_440ZX: - case INTEL_440GX: - if (!regs_l[addr]) - regs[addr] = (val & 0x3f); - break; - } - break; - case 0xe7: - switch (dev->type) { - case INTEL_440BX: case INTEL_440ZX: - case INTEL_440GX: - regs[0xe7] = 0x80; - for (i = 0; i < 16; i++) - regs_l[0xe0 + i] = !!(val & 0x80); - if (!regs_l[0xe7]) { - regs[0xe7] |= (val & 0x7f); - } - break; - } - break; - case 0xf0: - switch (dev->type) { - case INTEL_440BX: case INTEL_440ZX: - case INTEL_440GX: - regs[0xf0] = (val & 0xc0); - break; - } - break; - case 0xf1: - switch (dev->type) { - case INTEL_440BX: case INTEL_440ZX: - case INTEL_440GX: - regs[0xf1] = (val & 0x03); - break; - } - break; - } + case 0xbd: + switch (dev->type) { + case INTEL_440LX: + case INTEL_440EX: + regs[addr] = (val & 0xf8); + break; + default: + break; + } + break; + + case 0xd0: + case 0xd1: + case 0xd2: + case 0xd3: + case 0xd4: + case 0xd5: + case 0xd6: + case 0xd7: + switch (dev->type) { + case INTEL_440BX: + case INTEL_440ZX: + case INTEL_440GX: + regs[addr] = val; + break; + default: + break; + } + break; + case 0xca: + switch (dev->type) { + case INTEL_440BX: + case INTEL_440GX: + regs[addr] = val; + break; + case INTEL_440ZX: + regs[addr] = val & 0xe7; + break; + default: + break; + } + break; + case 0xcb: + switch (dev->type) { + case INTEL_440BX: + case INTEL_440GX: + regs[addr] = val; + break; + case INTEL_440ZX: + regs[addr] = val & 0xa7; + break; + default: + break; + } + break; + case 0xcc: + switch (dev->type) { + case INTEL_440BX: + case INTEL_440GX: + regs[0xcc] = (val & 0x7f); + break; + case INTEL_440ZX: + regs[0xcc] = (val & 0x58); + break; + default: + break; + } + break; + case 0xe0: + case 0xe1: + case 0xe2: + case 0xe3: + case 0xe4: + case 0xe8: + case 0xe9: + case 0xea: + case 0xeb: + case 0xec: + switch (dev->type) { + case INTEL_440BX: + case INTEL_440ZX: + case INTEL_440GX: + if (!regs_l[addr]) + regs[addr] = val; + break; + default: + break; + } + break; + case 0xe5: + case 0xed: + switch (dev->type) { + case INTEL_440BX: + case INTEL_440ZX: + case INTEL_440GX: + if (!regs_l[addr]) + regs[addr] = (val & 0x3f); + break; + default: + break; + } + break; + case 0xe7: + switch (dev->type) { + case INTEL_440BX: + case INTEL_440ZX: + case INTEL_440GX: + regs[0xe7] = 0x80; + for (uint8_t i = 0; i < 16; i++) + regs_l[0xe0 + i] = !!(val & 0x80); + if (!regs_l[0xe7]) { + regs[0xe7] |= (val & 0x7f); + } + break; + default: + break; + } + break; + case 0xf0: + switch (dev->type) { + case INTEL_440BX: + case INTEL_440ZX: + case INTEL_440GX: + regs[0xf0] = (val & 0xc0); + break; + default: + break; + } + break; + case 0xf1: + switch (dev->type) { + case INTEL_440BX: + case INTEL_440ZX: + case INTEL_440GX: + regs[0xf1] = (val & 0x03); + break; + default: + break; + } + break; + + default: + break; + } } - static uint8_t i4x0_read(int func, int addr, void *priv) { - i4x0_t *dev = (i4x0_t *) priv; - uint8_t ret = 0xff; - uint8_t *regs = (uint8_t *) dev->regs; + i4x0_t *dev = (i4x0_t *) priv; + uint8_t ret = 0xff; + const uint8_t *regs = (uint8_t *) dev->regs; if (func == 0) { - ret = regs[addr]; - /* Special behavior for 440FX register 0x93 which is basically TRC in PCI space - with the addition of bits 3 and 0. */ - if ((func == 0) && (addr == 0x93) && - ((dev->type == INTEL_440FX) || (dev->type == INTEL_440LX) || - (dev->type == INTEL_440EX))) - ret = (ret & 0xf9) | (trc_read(0x0093, NULL) & 0x06); + ret = regs[addr]; + /* Special behavior for 440FX register 0x93 which is basically TRC in PCI space + with the addition of bits 3 and 0. */ + if ((func == 0) && (addr == 0x93) && ((dev->type == INTEL_440FX) || (dev->type == INTEL_440LX) || (dev->type == INTEL_440EX))) + ret = (ret & 0xf9) | (pci_read(0x0cf9, NULL) & 0x06); } return ret; } - static void i4x0_reset(void *priv) { - i4x0_t *dev = (i4x0_t *)priv; - int i; + i4x0_t *dev = (i4x0_t *) priv; - if ((dev->type == INTEL_440LX) || (dev->type == INTEL_440BX) || - (dev->type == INTEL_440ZX)) - memset(dev->regs_locked, 0x00, 256 * sizeof(uint8_t)); + if ((dev->type == INTEL_440LX) || (dev->type == INTEL_440BX) || (dev->type == INTEL_440ZX)) + memset(dev->regs_locked, 0x00, 256 * sizeof(uint8_t)); if (dev->type >= INTEL_430FX) - i4x0_write(0, 0x59, 0x00, priv); + i4x0_write(0, 0x59, 0x00, priv); else - i4x0_write(0, 0x59, 0x0f, priv); + i4x0_write(0, 0x59, 0x0f, priv); - for (i = 0; i < 6; i++) - i4x0_write(0, 0x5a + i, 0x00, priv); + for (uint8_t i = 0; i < 6; i++) + i4x0_write(0, 0x5a + i, 0x00, priv); - for (i = 0; i <= dev->max_drb; i++) - i4x0_write(0, 0x60 + i, dev->drb_default, priv); + for (uint8_t i = 0; i <= dev->max_drb; i++) + dev->regs[0x60 + i] = dev->drb_default; + + if (dev->type >= INTEL_430NX) { + for (uint8_t i = 0; i < 4; i++) + dev->regs[0x68 + i] = 0x00; + } if (dev->type >= INTEL_430FX) { - dev->regs[0x72] &= 0xef; /* Forcibly unlock the SMRAM register. */ - i4x0_write(0, 0x72, 0x02, priv); + dev->regs[0x72] &= 0xef; /* Forcibly unlock the SMRAM register. */ + i4x0_write(0, 0x72, 0x02, priv); } else if (dev->type >= INTEL_430LX) { - dev->regs[0x72] &= 0xf7; /* Forcibly unlock the SMRAM register. */ - i4x0_write(0, 0x72, 0x00, priv); + dev->regs[0x72] &= 0xf7; /* Forcibly unlock the SMRAM register. */ + i4x0_write(0, 0x72, 0x00, priv); } else { - dev->regs[0x57] &= 0xef; /* Forcibly unlock the SMRAM register. */ - i4x0_write(0, 0x57, 0x02, priv); + dev->regs[0x57] &= 0xef; /* Forcibly unlock the SMRAM register. */ + i4x0_write(0, 0x57, 0x02, priv); } if ((dev->type == INTEL_430TX) || (dev->type >= INTEL_440BX)) { - i4x0_write(0, (dev->type >= INTEL_440BX) ? 0x73 : 0x71, - (dev->type >= INTEL_440BX) ? 0x38 : 0x00, priv); + i4x0_write(0, (dev->type >= INTEL_440BX) ? 0x73 : 0x71, + (dev->type >= INTEL_440BX) ? 0x38 : 0x00, priv); } } - static void -i4x0_close(void *p) +i4x0_close(void *priv) { - i4x0_t *dev = (i4x0_t *)p; + i4x0_t *dev = (i4x0_t *) priv; smram_del(dev->smram_high); smram_del(dev->smram_low); @@ -1302,303 +1579,326 @@ i4x0_close(void *p) free(dev); } - -static void -*i4x0_init(const device_t *info) +static void * +i4x0_init(const device_t *info) { - i4x0_t *dev = (i4x0_t *) malloc(sizeof(i4x0_t)); + i4x0_t *dev = (i4x0_t *) malloc(sizeof(i4x0_t)); uint8_t *regs; memset(dev, 0, sizeof(i4x0_t)); - dev->smram_low = smram_add(); + dev->smram_low = smram_add(); dev->smram_high = smram_add(); dev->type = info->local & 0xff; regs = (uint8_t *) dev->regs; - regs[0x00] = 0x86; regs[0x01] = 0x80; /*Intel*/ + regs[0x00] = 0x86; + regs[0x01] = 0x80; /*Intel*/ dev->write_drbs = spd_write_drbs; switch (dev->type) { - case INTEL_420TX: - case INTEL_420ZX: - regs[0x02] = 0x83; regs[0x03] = 0x04; /* 82424TX/ZX */ - regs[0x06] = 0x40; - regs[0x08] = (dev->type == INTEL_420ZX) ? 0x01 : 0x00; - regs[0x0d] = 0x20; - /* According to information from FreeBSD 3.x source code: - 0x00 = 486DX, 0x20 = 486SX, 0x40 = 486DX2 or 486DX4, 0x80 = Pentium OverDrive. */ - if (!(hasfpu) && (cpu_multi == 1)) - regs[0x50] = 0x20; - else if (!(hasfpu) && (cpu_multi == 2)) - regs[0x50] = 0x60; /* Guess based on the SX, DX, and DX2 values. */ - else if (hasfpu && (cpu_multi == 1)) - regs[0x50] = 0x00; - else if (hasfpu && (cpu_multi >= 2) && !(cpu_s->cpu_type == CPU_P24T)) - regs[0x50] = 0x40; - else - regs[0x50] = 0x80; /* Pentium OverDrive. */ - /* According to information from FreeBSD 3.x source code: - 00 = 25 MHz, 01 = 33 MHz. */ - if (cpu_busspeed > 25000000) - regs[0x50] |= 0x01; - regs[0x51] = 0x80; - /* According to information from FreeBSD 3.x source code: - 0x00 = None, 0x01 = 64 kB, 0x41 = 128 kB, 0x81 = 256 kB, 0xc1 = 512 kB, - If bit 0 is set, then if bit 2 is also set, the cache is write back, - otherwise it's write through. */ - regs[0x52] = 0xc3; /* 512 kB writeback cache */ - regs[0x57] = 0x31; - regs[0x59] = 0x0f; - regs[0x60] = regs[0x61] = regs[0x62] = regs[0x63] = 0x02; - dev->max_drb = 3; - dev->drb_unit = 4; - dev->drb_default = 0x02; - break; - case INTEL_430LX: - regs[0x02] = 0xa3; regs[0x03] = 0x04; /* 82434LX/NX */ - regs[0x06] = 0x40; - regs[0x08] = 0x03; - regs[0x0d] = 0x20; - regs[0x50] = 0x82; - if (cpu_busspeed <= 60000000) - regs[0x50] |= 0x00; - else if ((cpu_busspeed > 60000000) && (cpu_busspeed <= 66666667)) - regs[0x50] |= 0x01; - regs[0x51] = 0x80; - regs[0x52] = 0xea; /* 512 kB burst cache, set to 0xaa for 256 kB */ - regs[0x59] = 0x0f; - regs[0x60] = regs[0x61] = regs[0x62] = regs[0x63] = 0x02; - dev->max_drb = 5; - dev->drb_unit = 1; - dev->drb_default = 0x02; - break; - case INTEL_430NX: - regs[0x02] = 0xa3; regs[0x03] = 0x04; /* 82434LX/NX */ - regs[0x06] = 0x40; - regs[0x08] = 0x11; - regs[0x0d] = 0x20; - regs[0x50] = 0x80; - if (cpu_busspeed <= 50000000) - regs[0x50] |= 0x01; - else if ((cpu_busspeed > 50000000) && (cpu_busspeed <= 60000000)) - regs[0x50] |= 0x02; - else if ((cpu_busspeed > 60000000) && (cpu_busspeed <= 66666667)) - regs[0x50] |= 0x03; - regs[0x51] = 0x80; - regs[0x52] = 0xea; /* 512 kB burst cache, set to 0xaa for 256 kB */ - regs[0x57] = 0x31; - regs[0x59] = 0x0f; - regs[0x60] = regs[0x61] = regs[0x62] = regs[0x63] = regs[0x64] = regs[0x65] = regs[0x66] = regs[0x67] = 0x02; - dev->max_drb = 7; - dev->drb_unit = 1; - dev->drb_default = 0x02; - dev->write_drbs = spd_write_drbs_with_ext; - break; - case INTEL_430FX: - regs[0x02] = 0x2d; regs[0x03] = 0x12; /* SB82437FX-66 */ - regs[0x08] = (info->local >> 8) & 0xff; - regs[0x52] = 0xb2; /* 512 kB PLB cache, set to 0x42 for 256 kB */ - if (cpu_busspeed <= 50000000) - regs[0x57] |= 0x01; - else if ((cpu_busspeed > 50000000) && (cpu_busspeed <= 60000000)) - regs[0x57] |= 0x02; - else if ((cpu_busspeed > 60000000) && (cpu_busspeed <= 66666667)) - regs[0x57] |= 0x03; - regs[0x60] = regs[0x61] = regs[0x62] = regs[0x63] = regs[0x64] = 0x02; - regs[0x72] = 0x02; - dev->max_drb = 4; - dev->drb_unit = 4; - dev->drb_default = 0x02; - break; - case INTEL_430HX: - regs[0x02] = 0x50; regs[0x03] = 0x12; /* 82439HX */ - regs[0x52] = 0xb2; /* 512 kB PLB cache, set to 0x42 for 256 kB */ - if (cpu_busspeed <= 50000000) - regs[0x57] |= 0x01; - else if ((cpu_busspeed > 50000000) && (cpu_busspeed <= 60000000)) - regs[0x57] |= 0x02; - else if ((cpu_busspeed > 60000000) && (cpu_busspeed <= 66666667)) - regs[0x57] |= 0x03; - regs[0x60] = regs[0x61] = regs[0x62] = regs[0x63] = regs[0x64] = regs[0x65] = regs[0x66] = regs[0x67] = 0x02; - regs[0x72] = 0x02; - dev->max_drb = 7; - dev->drb_unit = 4; - dev->drb_default = 0x02; - break; - case INTEL_430VX: - regs[0x02] = 0x30; regs[0x03] = 0x70; /* 82437VX */ - regs[0x52] = 0xb2; /* 512 kB PLB cache, set to 0x42 for 256 kB */ - regs[0x53] = 0x14; - regs[0x56] = 0x52; - if (cpu_busspeed <= 50000000) - regs[0x57] |= 0x01; - else if ((cpu_busspeed > 50000000) && (cpu_busspeed <= 60000000)) - regs[0x57] |= 0x02; - else if ((cpu_busspeed > 60000000) && (cpu_busspeed <= 66666667)) - regs[0x57] |= 0x03; - regs[0x60] = regs[0x61] = regs[0x62] = regs[0x63] = regs[0x64] = 0x02; - regs[0x67] = 0x11; - regs[0x69] = 0x03; - regs[0x70] = 0x20; - regs[0x72] = 0x02; - regs[0x74] = 0x0e; - regs[0x78] = 0x23; - dev->max_drb = 4; - dev->drb_unit = 4; - dev->drb_default = 0x02; - break; - case INTEL_430TX: - regs[0x02] = 0x00; regs[0x03] = 0x71; /* 82439TX */ - regs[0x08] = 0x01; - regs[0x52] = 0xb2; /* 512 kB PLB cache, set to 0x42 for 256 kB */ - regs[0x53] = 0x14; - regs[0x56] = 0x52; - regs[0x57] = 0x01; - regs[0x60] = regs[0x61] = regs[0x62] = regs[0x63] = regs[0x64] = regs[0x65] = 0x02; - if (cpu_busspeed <= 60000000) - regs[0x67] |= 0x00; - else if ((cpu_busspeed > 60000000) && (cpu_busspeed <= 66666667)) - regs[0x67] |= 0x80; - regs[0x70] = 0x20; - regs[0x72] = 0x02; - dev->max_drb = 5; - dev->drb_unit = 4; - dev->drb_default = 0x02; - break; - case INTEL_440FX: - regs[0x02] = 0x37; regs[0x03] = 0x12; /* 82441FX */ - regs[0x08] = 0x02; - if (cpu_busspeed <= 60000000) - regs[0x51] |= 0x01; - else if ((cpu_busspeed > 60000000) && (cpu_busspeed <= 66666667)) - regs[0x51] |= 0x02; - regs[0x53] = 0x80; - regs[0x57] = 0x01; - regs[0x58] = 0x10; - regs[0x60] = regs[0x61] = regs[0x62] = regs[0x63] = regs[0x64] = regs[0x65] = regs[0x66] = regs[0x67] = 0x02; - regs[0x71] = 0x10; - regs[0x72] = 0x02; - dev->max_drb = 7; - dev->drb_unit = 8; - dev->drb_default = 0x02; - break; - case INTEL_440LX: - regs[0x02] = 0x80; regs[0x03] = 0x71; /* 82443LX */ - regs[0x08] = 0x03; - regs[0x06] = 0x90; - regs[0x10] = 0x08; - regs[0x34] = 0xa0; - if (cpu_busspeed <= 60000000) - regs[0x51] |= 0x40; - else if ((cpu_busspeed > 60000000) && (cpu_busspeed <= 66666667)) - regs[0x51] |= 0x00; - regs[0x53] = 0x83; - regs[0x57] = 0x01; - regs[0x60] = regs[0x61] = regs[0x62] = regs[0x63] = regs[0x64] = regs[0x65] = regs[0x66] = regs[0x67] = 0x01; - regs[0x6c] = regs[0x6d] = regs[0x6e] = regs[0x6f] = 0x55; - regs[0x72] = 0x02; - regs[0xa0] = 0x02; - regs[0xa2] = 0x10; - regs[0xa4] = 0x03; - regs[0xa5] = 0x02; - regs[0xa7] = 0x1f; - dev->max_drb = 7; - dev->drb_unit = 8; - dev->drb_default = 0x01; - break; - case INTEL_440EX: - regs[0x02] = 0x80; regs[0x03] = 0x71; /* 82443EX. Same Vendor ID as 440LX */ - regs[0x08] = 0x03; - regs[0x06] = 0x90; - regs[0x10] = 0x08; - regs[0x34] = 0xa0; - regs[0x51] = 0x80; - regs[0x53] = 0x83; - regs[0x57] = 0x01; - regs[0x60] = regs[0x61] = regs[0x62] = regs[0x63] = regs[0x64] = regs[0x65] = regs[0x66] = regs[0x67] = 0x01; - regs[0x6c] = regs[0x6d] = regs[0x6e] = regs[0x6f] = 0x55; - regs[0x72] = 0x02; - regs[0xa0] = 0x02; - regs[0xa2] = 0x10; - regs[0xa4] = 0x03; - regs[0xa5] = 0x02; - regs[0xa7] = 0x1f; - dev->max_drb = 7; - dev->drb_unit = 8; - dev->drb_default = 0x01; - break; - case INTEL_440BX: case INTEL_440ZX: - regs[0x7a] = (info->local >> 8) & 0xff; + case INTEL_420TX: + case INTEL_420ZX: + regs[0x02] = 0x83; + regs[0x03] = 0x04; /* 82424TX/ZX */ + regs[0x06] = 0x40; + regs[0x08] = (dev->type == INTEL_420ZX) ? 0x01 : 0x00; + regs[0x0d] = 0x20; + /* According to information from FreeBSD 3.x source code: + 0x00 = 486DX, 0x20 = 486SX, 0x40 = 486DX2 or 486DX4, 0x80 = Pentium OverDrive. */ + if (!hasfpu && (cpu_multi == 1)) + regs[0x50] = 0x20; + else if (!hasfpu && (cpu_multi == 2)) + regs[0x50] = 0x60; /* Guess based on the SX, DX, and DX2 values. */ + else if (hasfpu && (cpu_multi == 1)) + regs[0x50] = 0x00; + else if (hasfpu && (cpu_multi >= 2) && !(cpu_s->cpu_type == CPU_P24T)) + regs[0x50] = 0x40; + else + regs[0x50] = 0x80; /* Pentium OverDrive. */ + /* According to information from FreeBSD 3.x source code: + 00 = 25 MHz, 01 = 33 MHz. */ + if (cpu_busspeed > 25000000) + regs[0x50] |= 0x01; + regs[0x51] = 0x80; + /* According to information from FreeBSD 3.x source code: + 0x00 = None, 0x01 = 64 kB, 0x41 = 128 kB, 0x81 = 256 kB, 0xc1 = 512 kB, + If bit 0 is set, then if bit 2 is also set, the cache is write back, + otherwise it's write through. */ + regs[0x52] = 0xc3; /* 512 kB writeback cache */ + regs[0x57] = 0x31; + regs[0x59] = 0x0f; + regs[0x60] = regs[0x61] = regs[0x62] = regs[0x63] = 0x02; + dev->max_drb = 3; + dev->drb_unit = 1; + dev->drb_default = 0x02; + break; + case INTEL_430LX: + regs[0x02] = 0xa3; + regs[0x03] = 0x04; /* 82434LX/NX */ + regs[0x06] = 0x40; + regs[0x08] = 0x03; + regs[0x0d] = 0x20; + regs[0x50] = 0x82; + if (cpu_busspeed <= 60000000) + regs[0x50] |= 0x00; + else if ((cpu_busspeed > 60000000) && (cpu_busspeed <= 66666667)) + regs[0x50] |= 0x01; + regs[0x51] = 0x80; + regs[0x52] = 0xea; /* 512 kB burst cache, set to 0xaa for 256 kB */ + regs[0x59] = 0x0f; + regs[0x60] = regs[0x61] = regs[0x62] = regs[0x63] = 0x02; + dev->max_drb = 5; + dev->drb_unit = 1; + dev->drb_default = 0x02; + break; + case INTEL_430NX: + regs[0x02] = 0xa3; + regs[0x03] = 0x04; /* 82434LX/NX */ + regs[0x06] = 0x40; + regs[0x08] = 0x11; + regs[0x0d] = 0x20; + regs[0x50] = 0x80; + if (cpu_busspeed <= 50000000) + regs[0x50] |= 0x01; + else if ((cpu_busspeed > 50000000) && (cpu_busspeed <= 60000000)) + regs[0x50] |= 0x02; + else if ((cpu_busspeed > 60000000) && (cpu_busspeed <= 66666667)) + regs[0x50] |= 0x03; + regs[0x51] = 0x80; + regs[0x52] = 0xea; /* 512 kB burst cache, set to 0xaa for 256 kB */ + regs[0x57] = 0x31; + regs[0x59] = 0x0f; + regs[0x60] = regs[0x61] = regs[0x62] = regs[0x63] = + regs[0x64] = regs[0x65] = regs[0x66] = regs[0x67] = 0x02; + dev->max_drb = 7; + dev->drb_unit = 1; + dev->drb_default = 0x02; + dev->write_drbs = spd_write_drbs_with_ext; + break; + case INTEL_430FX: + regs[0x02] = 0x2d; + regs[0x03] = 0x12; /* SB82437FX-66 */ + regs[0x08] = (info->local >> 8) & 0xff; + regs[0x52] = 0xb2; /* 512 kB PLB cache, set to 0x42 for 256 kB */ + if (cpu_busspeed <= 50000000) + regs[0x57] |= 0x01; + else if ((cpu_busspeed > 50000000) && (cpu_busspeed <= 60000000)) + regs[0x57] |= 0x02; + else if ((cpu_busspeed > 60000000) && (cpu_busspeed <= 66666667)) + regs[0x57] |= 0x03; + regs[0x60] = regs[0x61] = regs[0x62] = regs[0x63] = regs[0x64] = 0x02; + regs[0x72] = 0x02; + dev->max_drb = 4; + dev->drb_unit = 4; + dev->drb_default = 0x02; + break; + case INTEL_430HX: + regs[0x02] = 0x50; + regs[0x03] = 0x12; /* 82439HX */ + regs[0x52] = 0xb2; /* 512 kB PLB cache, set to 0x42 for 256 kB */ + if (cpu_busspeed <= 50000000) + regs[0x57] |= 0x01; + else if ((cpu_busspeed > 50000000) && (cpu_busspeed <= 60000000)) + regs[0x57] |= 0x02; + else if ((cpu_busspeed > 60000000) && (cpu_busspeed <= 66666667)) + regs[0x57] |= 0x03; + regs[0x60] = regs[0x61] = regs[0x62] = regs[0x63] = + regs[0x64] = regs[0x65] = regs[0x66] = regs[0x67] = 0x02; + regs[0x72] = 0x02; + dev->max_drb = 7; + dev->drb_unit = 4; + dev->drb_default = 0x02; + break; + case INTEL_430VX: + regs[0x02] = 0x30; + regs[0x03] = 0x70; /* 82437VX */ + regs[0x52] = 0xb2; /* 512 kB PLB cache, set to 0x42 for 256 kB */ + regs[0x53] = 0x14; + regs[0x56] = 0x52; + if (cpu_busspeed <= 50000000) + regs[0x57] |= 0x01; + else if ((cpu_busspeed > 50000000) && (cpu_busspeed <= 60000000)) + regs[0x57] |= 0x02; + else if ((cpu_busspeed > 60000000) && (cpu_busspeed <= 66666667)) + regs[0x57] |= 0x03; + regs[0x60] = regs[0x61] = regs[0x62] = regs[0x63] = regs[0x64] = 0x02; + regs[0x67] = 0x11; + regs[0x69] = 0x03; + regs[0x70] = 0x20; + regs[0x72] = 0x02; + regs[0x74] = 0x0e; + regs[0x78] = 0x23; + dev->max_drb = 4; + dev->drb_unit = 4; + dev->drb_default = 0x02; + break; + case INTEL_430TX: + regs[0x02] = 0x00; + regs[0x03] = 0x71; /* 82439TX */ + regs[0x08] = 0x01; + regs[0x52] = 0xb2; /* 512 kB PLB cache, set to 0x42 for 256 kB */ + regs[0x53] = 0x14; + regs[0x56] = 0x52; + regs[0x57] = 0x01; + regs[0x60] = regs[0x61] = regs[0x62] = regs[0x63] = regs[0x64] = regs[0x65] = 0x02; + if (cpu_busspeed <= 60000000) + regs[0x67] |= 0x00; + else if ((cpu_busspeed > 60000000) && (cpu_busspeed <= 66666667)) + regs[0x67] |= 0x80; + regs[0x70] = 0x20; + regs[0x72] = 0x02; + dev->max_drb = 5; + dev->drb_unit = 4; + dev->drb_default = 0x02; + break; + case INTEL_440FX: + regs[0x02] = 0x37; + regs[0x03] = 0x12; /* 82441FX */ + regs[0x08] = 0x02; + if (cpu_busspeed <= 60000000) + regs[0x51] |= 0x01; + else if ((cpu_busspeed > 60000000) && (cpu_busspeed <= 66666667)) + regs[0x51] |= 0x02; + regs[0x53] = 0x80; + regs[0x57] = 0x01; + regs[0x58] = 0x10; + regs[0x60] = regs[0x61] = regs[0x62] = regs[0x63] = + regs[0x64] = regs[0x65] = regs[0x66] = regs[0x67] = 0x02; + regs[0x71] = 0x10; + regs[0x72] = 0x02; + dev->max_drb = 7; + dev->drb_unit = 8; + dev->drb_default = 0x02; + break; + case INTEL_440LX: + regs[0x02] = 0x80; + regs[0x03] = 0x71; /* 82443LX */ + regs[0x08] = 0x03; + regs[0x06] = 0x90; + regs[0x10] = 0x08; + regs[0x34] = 0xa0; + if (cpu_busspeed <= 60000000) + regs[0x51] |= 0x40; + else if ((cpu_busspeed > 60000000) && (cpu_busspeed <= 66666667)) + regs[0x51] |= 0x00; + regs[0x53] = 0x83; + regs[0x57] = 0x01; + regs[0x60] = regs[0x61] = regs[0x62] = regs[0x63] = + regs[0x64] = regs[0x65] = regs[0x66] = regs[0x67] = 0x01; + regs[0x6c] = regs[0x6d] = regs[0x6e] = regs[0x6f] = 0x55; + regs[0x72] = 0x02; + regs[0xa0] = 0x02; + regs[0xa2] = 0x10; + regs[0xa4] = 0x03; + regs[0xa5] = 0x02; + regs[0xa7] = 0x1f; + dev->max_drb = 7; + dev->drb_unit = 8; + dev->drb_default = 0x01; + break; + case INTEL_440EX: + regs[0x02] = 0x80; + regs[0x03] = 0x71; /* 82443EX. Same Vendor ID as 440LX */ + regs[0x08] = 0x03; + regs[0x06] = 0x90; + regs[0x10] = 0x08; + regs[0x34] = 0xa0; + regs[0x51] = 0x80; + regs[0x53] = 0x83; + regs[0x57] = 0x01; + regs[0x60] = regs[0x61] = regs[0x62] = regs[0x63] = + regs[0x64] = regs[0x65] = regs[0x66] = regs[0x67] = 0x01; + regs[0x6c] = regs[0x6d] = regs[0x6e] = regs[0x6f] = 0x55; + regs[0x72] = 0x02; + regs[0xa0] = 0x02; + regs[0xa2] = 0x10; + regs[0xa4] = 0x03; + regs[0xa5] = 0x02; + regs[0xa7] = 0x1f; + dev->max_drb = 7; + dev->drb_unit = 8; + dev->drb_default = 0x01; + break; + case INTEL_440BX: + case INTEL_440ZX: + regs[0x7a] = (info->local >> 8) & 0xff; - regs[0x02] = (regs[0x7a] & 0x02) ? 0x92 : 0x90; regs[0x03] = 0x71; /* 82443BX */ - regs[0x06] = (regs[0x7a] & 0x02) ? 0x00 : 0x10; - regs[0x08] = (regs[0x7a] & 0x02) ? 0x03 : 0x02; - regs[0x10] = 0x08; - regs[0x34] = (regs[0x7a] & 0x02) ? 0x00 : 0xa0; - if (cpu_busspeed <= 66666667) - regs[0x51] |= 0x20; - else if ((cpu_busspeed > 66666667) && (cpu_busspeed <= 100000000)) - regs[0x51] |= 0x00; - regs[0x57] = 0x28; /* 4 DIMMs, SDRAM */ - regs[0x58] = 0x03; - regs[0x60] = regs[0x61] = regs[0x62] = regs[0x63] = regs[0x64] = regs[0x65] = regs[0x66] = regs[0x67] = 0x01; - regs[0x72] = 0x02; - regs[0x73] = 0x38; - regs[0x7b] = 0x38; - regs[0x90] = 0x80; - regs[0xa0] = (regs[0x7a] & 0x02) ? 0x00 : 0x02; - regs[0xa2] = (regs[0x7a] & 0x02) ? 0x00 : 0x10; - regs[0xa4] = 0x03; - regs[0xa5] = 0x02; - regs[0xa7] = 0x1f; - dev->max_drb = 7; - dev->drb_unit = 8; - dev->drb_default = 0x01; - break; - case INTEL_440GX: - regs[0x7a] = (info->local >> 8) & 0xff; + regs[0x02] = (regs[0x7a] & 0x02) ? 0x92 : 0x90; + regs[0x03] = 0x71; /* 82443BX */ + regs[0x06] = (regs[0x7a] & 0x02) ? 0x00 : 0x10; + regs[0x08] = (regs[0x7a] & 0x02) ? 0x03 : 0x02; + regs[0x10] = 0x08; + regs[0x34] = (regs[0x7a] & 0x02) ? 0x00 : 0xa0; + if (cpu_busspeed <= 66666667) + regs[0x51] |= 0x20; + else if ((cpu_busspeed > 66666667) && (cpu_busspeed <= 100000000)) + regs[0x51] |= 0x00; + regs[0x57] = 0x28; /* 4 DIMMs, SDRAM */ + regs[0x58] = 0x03; + regs[0x60] = regs[0x61] = regs[0x62] = regs[0x63] = + regs[0x64] = regs[0x65] = regs[0x66] = regs[0x67] = 0x01; + regs[0x72] = 0x02; + regs[0x73] = 0x38; + regs[0x7b] = 0x38; + regs[0x90] = 0x80; + regs[0xa0] = (regs[0x7a] & 0x02) ? 0x00 : 0x02; + regs[0xa2] = (regs[0x7a] & 0x02) ? 0x00 : 0x10; + regs[0xa4] = 0x03; + regs[0xa5] = 0x02; + regs[0xa7] = 0x1f; + dev->max_drb = 7; + dev->drb_unit = 8; + dev->drb_default = 0x01; + break; + case INTEL_440GX: + regs[0x7a] = (info->local >> 8) & 0xff; - regs[0x02] = (regs[0x7a] & 0x02) ? 0xa2 : 0xa0; regs[0x03] = 0x71; /* 82443GX */ - regs[0x06] = (regs[0x7a] & 0x02) ? 0x00 : 0x10; - regs[0x10] = 0x08; - regs[0x34] = (regs[0x7a] & 0x02) ? 0x00 : 0xa0; - regs[0x57] = 0x28; - regs[0x60] = regs[0x61] = regs[0x62] = regs[0x63] = regs[0x64] = regs[0x65] = regs[0x66] = regs[0x67] = 0x01; - regs[0x72] = 0x02; - regs[0x73] = 0x38; - regs[0x7b] = 0x38; - regs[0x90] = 0x80; - regs[0xa0] = (regs[0x7a] & 0x02) ? 0x00 : 0x02; - regs[0xa2] = (regs[0x7a] & 0x02) ? 0x00 : 0x10; - regs[0xa4] = 0x03; - regs[0xa5] = 0x02; - regs[0xa7] = 0x1f; - dev->max_drb = 7; - dev->drb_unit = 8; - dev->drb_default = 0x01; - break; + regs[0x02] = (regs[0x7a] & 0x02) ? 0xa2 : 0xa0; + regs[0x03] = 0x71; /* 82443GX */ + regs[0x06] = (regs[0x7a] & 0x02) ? 0x00 : 0x10; + regs[0x10] = 0x08; + regs[0x34] = (regs[0x7a] & 0x02) ? 0x00 : 0xa0; + regs[0x57] = 0x28; + regs[0x60] = regs[0x61] = regs[0x62] = regs[0x63] = + regs[0x64] = regs[0x65] = regs[0x66] = regs[0x67] = 0x01; + regs[0x72] = 0x02; + regs[0x73] = 0x38; + regs[0x7b] = 0x38; + regs[0x90] = 0x80; + regs[0xa0] = (regs[0x7a] & 0x02) ? 0x00 : 0x02; + regs[0xa2] = (regs[0x7a] & 0x02) ? 0x00 : 0x10; + regs[0xa4] = 0x03; + regs[0xa5] = 0x02; + regs[0xa7] = 0x1f; + dev->max_drb = 7; + dev->drb_unit = 8; + dev->drb_default = 0x01; + break; + default: + break; } - regs[0x04] = 0x06; regs[0x07] = 0x02; + regs[0x04] = 0x06; + regs[0x07] = 0x02; regs[0x0b] = 0x06; if (dev->type >= INTEL_440FX) { - cpu_cache_ext_enabled = 1; - cpu_update_waitstates(); + cpu_cache_ext_enabled = 1; + cpu_update_waitstates(); } /* Out-of-spec PCI and AGP clocks with overclocked bus. */ if ((dev->type <= INTEL_440FX) && (cpu_busspeed >= 66666666)) - cpu_set_pci_speed(cpu_busspeed / 2); + cpu_set_pci_speed(cpu_busspeed / 2); if ((dev->type >= INTEL_440BX) && (cpu_busspeed >= 100000000)) - cpu_set_agp_speed(cpu_busspeed / 1.5); + cpu_set_agp_speed(cpu_busspeed / 1.5); else if (dev->type >= INTEL_440LX) - cpu_set_agp_speed(cpu_busspeed); + cpu_set_agp_speed(cpu_busspeed); i4x0_write(regs[0x59], 0x59, 0x00, dev); i4x0_write(regs[0x5a], 0x5a, 0x00, dev); @@ -1609,276 +1909,250 @@ static void i4x0_write(regs[0x5f], 0x5f, 0x00, dev); if (dev->type >= INTEL_430FX) - i4x0_write(0, 0x72, 0x02, dev); + i4x0_write(0, 0x72, 0x02, dev); else if (dev->type >= INTEL_430LX) - i4x0_write(0, 0x72, 0x00, dev); + i4x0_write(0, 0x72, 0x00, dev); else - i4x0_write(0, 0x57, 0x02, dev); + i4x0_write(0, 0x57, 0x02, dev); if ((dev->type == INTEL_430TX) || (dev->type >= INTEL_440BX)) { - i4x0_write(0, (dev->type >= INTEL_440BX) ? 0x73 : 0x71, - (dev->type >= INTEL_440BX) ? 0x38 : 0x00, dev); + i4x0_write(0, (dev->type >= INTEL_440BX) ? 0x73 : 0x71, + (dev->type >= INTEL_440BX) ? 0x38 : 0x00, dev); } - pci_add_card(PCI_ADD_NORTHBRIDGE, i4x0_read, i4x0_write, dev); + pci_add_card(PCI_ADD_NORTHBRIDGE, i4x0_read, i4x0_write, dev, &dev->pci_slot); if ((dev->type >= INTEL_440BX) && !(regs[0x7a] & 0x02)) { - device_add((dev->type == INTEL_440GX) ? &i440gx_agp_device : &i440bx_agp_device); - dev->agpgart = device_add(&agpgart_device); - } else if (dev->type >= INTEL_440LX) { - device_add(&i440lx_agp_device); - dev->agpgart = device_add(&agpgart_device); + device_add((dev->type == INTEL_440GX) ? &i440gx_agp_device : &i440bx_agp_device); + dev->agpgart = device_add(&agpgart_device); + } else if ((dev->type == INTEL_440LX) || (dev->type == INTEL_440EX)) { + device_add(&i440lx_agp_device); + dev->agpgart = device_add(&agpgart_device); } return dev; } - -const device_t i420tx_device = -{ - "Intel 82424TX", - "i420tx", - DEVICE_PCI, - INTEL_420TX, - i4x0_init, - i4x0_close, - i4x0_reset, - { NULL }, - NULL, - NULL, - NULL +const device_t i420tx_device = { + .name = "Intel 82424TX", + .internal_name = "i420tx", + .flags = DEVICE_PCI, + .local = INTEL_420TX, + .init = i4x0_init, + .close = i4x0_close, + .reset = i4x0_reset, + { .available = NULL }, + .speed_changed = NULL, + .force_redraw = NULL, + .config = NULL }; - -const device_t i420zx_device = -{ - "Intel 82424ZX", - "i420zx", - DEVICE_PCI, - INTEL_420ZX, - i4x0_init, - i4x0_close, - i4x0_reset, - { NULL }, - NULL, - NULL, - NULL +const device_t i420zx_device = { + .name = "Intel 82424ZX", + .internal_name = "i420zx", + .flags = DEVICE_PCI, + .local = INTEL_420ZX, + .init = i4x0_init, + .close = i4x0_close, + .reset = i4x0_reset, + { .available = NULL }, + .speed_changed = NULL, + .force_redraw = NULL, + .config = NULL }; - -const device_t i430lx_device = -{ - "Intel 82434LX", - "i430lx", - DEVICE_PCI, - INTEL_430LX, - i4x0_init, - i4x0_close, - i4x0_reset, - { NULL }, - NULL, - NULL, - NULL +const device_t i430lx_device = { + .name = "Intel 82434LX", + .internal_name = "i430lx", + .flags = DEVICE_PCI, + .local = INTEL_430LX, + .init = i4x0_init, + .close = i4x0_close, + .reset = i4x0_reset, + { .available = NULL }, + .speed_changed = NULL, + .force_redraw = NULL, + .config = NULL }; - -const device_t i430nx_device = -{ - "Intel 82434NX", - "i430nx", - DEVICE_PCI, - INTEL_430NX, - i4x0_init, - i4x0_close, - i4x0_reset, - { NULL }, - NULL, - NULL, - NULL +const device_t i430nx_device = { + .name = "Intel 82434NX", + .internal_name = "i430nx", + .flags = DEVICE_PCI, + .local = INTEL_430NX, + .init = i4x0_init, + .close = i4x0_close, + .reset = i4x0_reset, + { .available = NULL }, + .speed_changed = NULL, + .force_redraw = NULL, + .config = NULL }; - -const device_t i430fx_device = -{ - "Intel SB82437FX-66", - "i430fx", - DEVICE_PCI, - INTEL_430FX, - i4x0_init, - i4x0_close, - i4x0_reset, - { NULL }, - NULL, - NULL, - NULL +const device_t i430fx_device = { + .name = "Intel SB82437FX-66", + .internal_name = "i430fx", + .flags = DEVICE_PCI, + .local = INTEL_430FX, + .init = i4x0_init, + .close = i4x0_close, + .reset = i4x0_reset, + { .available = NULL }, + .speed_changed = NULL, + .force_redraw = NULL, + .config = NULL }; - -const device_t i430fx_rev02_device = -{ - "Intel SB82437FX-66 (Rev. 02)", - "i430fx_rev02", - DEVICE_PCI, - 0x0200 | INTEL_430FX, - i4x0_init, - i4x0_close, - i4x0_reset, - { NULL }, - NULL, - NULL, - NULL +const device_t i430fx_rev02_device = { + .name = "Intel SB82437FX-66 (Rev. 02)", + .internal_name = "i430fx_rev02", + .flags = DEVICE_PCI, + .local = 0x0200 | INTEL_430FX, + .init = i4x0_init, + .close = i4x0_close, + .reset = i4x0_reset, + { .available = NULL }, + .speed_changed = NULL, + .force_redraw = NULL, + .config = NULL }; - -const device_t i430hx_device = -{ - "Intel 82439HX", - "i430hx", - DEVICE_PCI, - INTEL_430HX, - i4x0_init, - i4x0_close, - i4x0_reset, - { NULL }, - NULL, - NULL, - NULL +const device_t i430hx_device = { + .name = "Intel 82439HX", + .internal_name = "i430hx", + .flags = DEVICE_PCI, + .local = INTEL_430HX, + .init = i4x0_init, + .close = i4x0_close, + .reset = i4x0_reset, + { .available = NULL }, + .speed_changed = NULL, + .force_redraw = NULL, + .config = NULL }; - -const device_t i430vx_device = -{ - "Intel 82437VX", - "i430vx", - DEVICE_PCI, - INTEL_430VX, - i4x0_init, - i4x0_close, - i4x0_reset, - { NULL }, - NULL, - NULL, - NULL +const device_t i430vx_device = { + .name = "Intel 82437VX", + .internal_name = "i430vx", + .flags = DEVICE_PCI, + .local = INTEL_430VX, + .init = i4x0_init, + .close = i4x0_close, + .reset = i4x0_reset, + { .available = NULL }, + .speed_changed = NULL, + .force_redraw = NULL, + .config = NULL }; - -const device_t i430tx_device = -{ - "Intel 82439TX", - "i430tx", - DEVICE_PCI, - INTEL_430TX, - i4x0_init, - i4x0_close, - i4x0_reset, - { NULL }, - NULL, - NULL, - NULL +const device_t i430tx_device = { + .name = "Intel 82439TX", + .internal_name = "i430tx", + .flags = DEVICE_PCI, + .local = INTEL_430TX, + .init = i4x0_init, + .close = i4x0_close, + .reset = i4x0_reset, + { .available = NULL }, + .speed_changed = NULL, + .force_redraw = NULL, + .config = NULL }; - -const device_t i440fx_device = -{ - "Intel 82441FX", - "i440fx", - DEVICE_PCI, - INTEL_440FX, - i4x0_init, - i4x0_close, - i4x0_reset, - { NULL }, - NULL, - NULL, - NULL +const device_t i440fx_device = { + .name = "Intel 82441FX", + .internal_name = "i440fx", + .flags = DEVICE_PCI, + .local = INTEL_440FX, + .init = i4x0_init, + .close = i4x0_close, + .reset = i4x0_reset, + { .available = NULL }, + .speed_changed = NULL, + .force_redraw = NULL, + .config = NULL }; -const device_t i440lx_device = -{ - "Intel 82443LX", - "i440lx", - DEVICE_PCI, - INTEL_440LX, - i4x0_init, - i4x0_close, - i4x0_reset, - { NULL }, - NULL, - NULL, - NULL +const device_t i440lx_device = { + .name = "Intel 82443LX", + .internal_name = "i440lx", + .flags = DEVICE_PCI, + .local = INTEL_440LX, + .init = i4x0_init, + .close = i4x0_close, + .reset = i4x0_reset, + { .available = NULL }, + .speed_changed = NULL, + .force_redraw = NULL, + .config = NULL }; -const device_t i440ex_device = -{ - "Intel 82443EX", - "i440ex", - DEVICE_PCI, - INTEL_440EX, - i4x0_init, - i4x0_close, - i4x0_reset, - { NULL }, - NULL, - NULL, - NULL +const device_t i440ex_device = { + .name = "Intel 82443EX", + .internal_name = "i440ex", + .flags = DEVICE_PCI, + .local = INTEL_440EX, + .init = i4x0_init, + .close = i4x0_close, + .reset = i4x0_reset, + { .available = NULL }, + .speed_changed = NULL, + .force_redraw = NULL, + .config = NULL }; -const device_t i440bx_device = -{ - "Intel 82443BX", - "i440bx", - DEVICE_PCI, - 0x8000 | INTEL_440BX, - i4x0_init, - i4x0_close, - i4x0_reset, - { NULL }, - NULL, - NULL, - NULL +const device_t i440bx_device = { + .name = "Intel 82443BX", + .internal_name = "i440bx", + .flags = DEVICE_PCI, + .local = 0x8000 | INTEL_440BX, + .init = i4x0_init, + .close = i4x0_close, + .reset = i4x0_reset, + { .available = NULL }, + .speed_changed = NULL, + .force_redraw = NULL, + .config = NULL }; -const device_t i440bx_no_agp_device = -{ - "Intel 82443BX", - "i440bx_no_agp", - DEVICE_PCI, - 0x8200 | INTEL_440BX, - i4x0_init, - i4x0_close, - i4x0_reset, - { NULL }, - NULL, - NULL, - NULL +const device_t i440bx_no_agp_device = { + .name = "Intel 82443BX (No AGP)", + .internal_name = "i440bx_no_agp", + .flags = DEVICE_PCI, + .local = 0x8200 | INTEL_440BX, + .init = i4x0_init, + .close = i4x0_close, + .reset = i4x0_reset, + { .available = NULL }, + .speed_changed = NULL, + .force_redraw = NULL, + .config = NULL }; -const device_t i440gx_device = -{ - "Intel 82443GX", - "i440gx", - DEVICE_PCI, - 0x8000 | INTEL_440GX, - i4x0_init, - i4x0_close, - i4x0_reset, - { NULL }, - NULL, - NULL, - NULL +const device_t i440gx_device = { + .name = "Intel 82443GX", + .internal_name = "i440gx", + .flags = DEVICE_PCI, + .local = 0x8000 | INTEL_440GX, + .init = i4x0_init, + .close = i4x0_close, + .reset = i4x0_reset, + { .available = NULL }, + .speed_changed = NULL, + .force_redraw = NULL, + .config = NULL }; -const device_t i440zx_device = -{ - "Intel 82443ZX", - "i440zx", - DEVICE_PCI, - 0x8000 | INTEL_440ZX, - i4x0_init, - i4x0_close, - i4x0_reset, - { NULL }, - NULL, - NULL, - NULL +const device_t i440zx_device = { + .name = "Intel 82443ZX", + .internal_name = "i440zx", + .flags = DEVICE_PCI, + .local = 0x8000 | INTEL_440ZX, + .init = i4x0_init, + .close = i4x0_close, + .reset = i4x0_reset, + { .available = NULL }, + .speed_changed = NULL, + .force_redraw = NULL, + .config = NULL }; diff --git a/src/chipset/intel_82335.c b/src/chipset/intel_82335.c index 6dbe0ea4f..da0cc30f6 100644 --- a/src/chipset/intel_82335.c +++ b/src/chipset/intel_82335.c @@ -1,17 +1,19 @@ /* - * 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. + * 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. + * This file is part of the 86Box distribution. * - * Implementation of the Intel 82335(KU82335) chipset. + * Implementation of the Intel 82335(KU82335) chipset. * - * Copyright 2021 Tiseno100 * + * + * Authors: Tiseno100 + * + * Copyright 2021 Tiseno100. */ - #include #include #include @@ -26,22 +28,23 @@ #include <86box/device.h> #include <86box/mem.h> #include <86box/chipset.h> +#include <86box/plat_unused.h> /* Shadow capabilities */ #define DISABLED_SHADOW (MEM_READ_EXTANY | MEM_WRITE_EXTANY) -#define ENABLED_SHADOW ((LOCK_STATUS) ? RO_SHADOW : RW_SHADOW) -#define RW_SHADOW (MEM_READ_INTERNAL | MEM_WRITE_INTERNAL) -#define RO_SHADOW (MEM_READ_INTERNAL | MEM_WRITE_DISABLED) +#define ENABLED_SHADOW ((LOCK_STATUS) ? RO_SHADOW : RW_SHADOW) +#define RW_SHADOW (MEM_READ_INTERNAL | MEM_WRITE_INTERNAL) +#define RO_SHADOW (MEM_READ_INTERNAL | MEM_WRITE_DISABLED) /* Granularity Register Enable & Recalc */ #define EXTENDED_GRANULARITY_ENABLED (dev->regs[0x2c] & 0x01) -#define GRANULARITY_RECALC ((dev->regs[0x2e] & (1 << (i + 8))) ? ((dev->regs[0x2e] & (1 << i)) ? RO_SHADOW : RW_SHADOW) : DISABLED_SHADOW) +#define GRANULARITY_RECALC ((dev->regs[0x2e] & (1 << (i + 8))) ? ((dev->regs[0x2e] & (1 << i)) ? RO_SHADOW : RW_SHADOW) : DISABLED_SHADOW) /* R/W operator for the Video RAM region */ #define DETERMINE_VIDEO_RAM_WRITE_ACCESS ((dev->regs[0x22] & (0x08 << 8)) ? RW_SHADOW : RO_SHADOW) /* Base System 512/640KB switch */ -#define ENABLE_TOP_128KB (MEM_READ_INTERNAL | MEM_WRITE_INTERNAL) +#define ENABLE_TOP_128KB (MEM_READ_INTERNAL | MEM_WRITE_INTERNAL) #define DISABLE_TOP_128KB (MEM_READ_EXTANY | MEM_WRITE_EXTANY) /* ROM size determination */ @@ -54,91 +57,92 @@ #define DEFINE_RC1_REMAP_SIZE ((dev->regs[0x24] & 0x02) ? 128 : 256) #define DEFINE_RC2_REMAP_SIZE ((dev->regs[0x26] & 0x02) ? 128 : 256) -typedef struct -{ +typedef struct intel_82335_t { + uint16_t regs[256]; - uint16_t regs[256], - - cfg_locked; + uint16_t cfg_locked; } intel_82335_t; #ifdef ENABLE_INTEL_82335_LOG int intel_82335_do_log = ENABLE_INTEL_82335_LOG; + static void intel_82335_log(const char *fmt, ...) { va_list ap; - if (intel_82335_do_log) - { + if (intel_82335_do_log) { va_start(ap, fmt); pclog_ex(fmt, ap); va_end(ap); } } #else -#define intel_82335_log(fmt, ...) +# define intel_82335_log(fmt, ...) #endif static void intel_82335_write(uint16_t addr, uint16_t val, void *priv) { - intel_82335_t *dev = (intel_82335_t *)priv; - uint32_t romsize = 0, base = 0, i = 0, rc1_remap = 0, rc2_remap = 0; + intel_82335_t *dev = (intel_82335_t *) priv; + uint32_t romsize = 0; + uint32_t base = 0; + uint32_t rc1_remap = 0; + uint32_t rc2_remap = 0; dev->regs[addr] = val; - if (!dev->cfg_locked) - { + if (!dev->cfg_locked) { intel_82335_log("Register %02x: Write %04x\n", addr, val); - switch (addr) - { - case 0x22: /* Memory Controller */ + switch (addr) { + case 0x22: /* Memory Controller */ - /* Check if the ROM chips are 256 or 512Kbit (Just for Shadowing sanity) */ - romsize = ROM_SIZE; + /* Check if the ROM chips are 256 or 512Kbit (Just for Shadowing sanity) */ + romsize = ROM_SIZE; - if (!EXTENDED_GRANULARITY_ENABLED) - { - shadowbios = !!(dev->regs[0x22] & 0x01); - shadowbios_write = !!(dev->regs[0x22] & 0x01); + if (!EXTENDED_GRANULARITY_ENABLED) { + shadowbios = !!(dev->regs[0x22] & 0x01); + shadowbios_write = !!(dev->regs[0x22] & 0x01); - /* Base System 512/640KB set */ - mem_set_mem_state_both(0x80000, 0x20000, (dev->regs[0x22] & 0x08) ? ENABLE_TOP_128KB : DISABLE_TOP_128KB); + /* Base System 512/640KB set */ +#if 0 + mem_set_mem_state_both(0x80000, 0x20000, (dev->regs[0x22] & 0x08) ? ENABLE_TOP_128KB : DISABLE_TOP_128KB); +#endif - /* Video RAM shadow*/ - mem_set_mem_state_both(0xa0000, 0x20000, (dev->regs[0x22] & (0x04 << 8)) ? DETERMINE_VIDEO_RAM_WRITE_ACCESS : DISABLED_SHADOW); + /* Video RAM shadow*/ + mem_set_mem_state_both(0xa0000, 0x20000, (dev->regs[0x22] & (0x04 << 8)) ? DETERMINE_VIDEO_RAM_WRITE_ACCESS : DISABLED_SHADOW); - /* Option ROM shadow */ - mem_set_mem_state_both(0xc0000, 0x20000, (dev->regs[0x22] & (0x02 << 8)) ? ENABLED_SHADOW : DISABLED_SHADOW); + /* Option ROM shadow */ + mem_set_mem_state_both(0xc0000, 0x20000, (dev->regs[0x22] & (0x02 << 8)) ? ENABLED_SHADOW : DISABLED_SHADOW); - /* System ROM shadow */ - mem_set_mem_state_both(0xe0000, 0x20000, (dev->regs[0x22] & 0x01) ? ENABLED_SHADOW : DISABLED_SHADOW); - } - break; - - case 0x24: /* Roll Compare (Just top remapping. Not followed according to datasheet!) */ - case 0x26: - rc1_remap = (dev->regs[0x24] & 0x01) ? DEFINE_RC1_REMAP_SIZE : 0; - rc2_remap = (dev->regs[0x26] & 0x01) ? DEFINE_RC2_REMAP_SIZE : 0; - mem_remap_top(rc1_remap + rc2_remap); - break; - - case 0x2e: /* Extended Granularity (Enabled if Bit 0 in Register 2Ch is set) */ - if (EXTENDED_GRANULARITY_ENABLED) - { - for (i = 0; i < 8; i++) - { - base = 0xc0000 + (i << 15); - shadowbios = (dev->regs[0x2e] & (1 << (i + 8))) && (base == romsize); - shadowbios_write = (dev->regs[0x2e] & (1 << i)) && (base == romsize); - mem_set_mem_state_both(base, 0x8000, GRANULARITY_RECALC); + /* System ROM shadow */ + mem_set_mem_state_both(0xe0000, 0x20000, (dev->regs[0x22] & 0x01) ? ENABLED_SHADOW : DISABLED_SHADOW); } break; - } + + case 0x24: /* Roll Compare (Just top remapping. Not followed according to datasheet!) */ + case 0x26: + rc1_remap = (dev->regs[0x24] & 0x01) ? DEFINE_RC1_REMAP_SIZE : 0; + rc2_remap = (dev->regs[0x26] & 0x01) ? DEFINE_RC2_REMAP_SIZE : 0; + mem_remap_top(rc1_remap + rc2_remap); + break; + + case 0x2e: /* Extended Granularity (Enabled if Bit 0 in Register 2Ch is set) */ + if (EXTENDED_GRANULARITY_ENABLED) { + for (uint8_t i = 0; i < 8; i++) { + base = 0xc0000 + (i << 15); + shadowbios = (dev->regs[0x2e] & (1 << (i + 8))) && (base == romsize); + shadowbios_write = (dev->regs[0x2e] & (1 << i)) && (base == romsize); + mem_set_mem_state_both(base, 0x8000, GRANULARITY_RECALC); + } + } + break; + + default: + break; } } @@ -149,7 +153,7 @@ intel_82335_write(uint16_t addr, uint16_t val, void *priv) static uint16_t intel_82335_read(uint16_t addr, void *priv) { - intel_82335_t *dev = (intel_82335_t *)priv; + const intel_82335_t *dev = (intel_82335_t *) priv; intel_82335_log("Register %02x: Read %04x\n", addr, dev->regs[addr]); @@ -159,19 +163,20 @@ intel_82335_read(uint16_t addr, void *priv) static void intel_82335_close(void *priv) { - intel_82335_t *dev = (intel_82335_t *)priv; + intel_82335_t *dev = (intel_82335_t *) priv; free(dev); } static void * -intel_82335_init(const device_t *info) +intel_82335_init(UNUSED(const device_t *info)) { - intel_82335_t *dev = (intel_82335_t *)malloc(sizeof(intel_82335_t)); + intel_82335_t *dev = (intel_82335_t *) malloc(sizeof(intel_82335_t)); memset(dev, 0, sizeof(intel_82335_t)); memset(dev->regs, 0, sizeof(dev->regs)); + dev->regs[0x22] = 0x08; dev->regs[0x28] = 0xf9; dev->cfg_locked = 0; @@ -197,14 +202,15 @@ intel_82335_init(const device_t *info) } const device_t intel_82335_device = { - "Intel 82335", - "intel_82335", - 0, - 0, - intel_82335_init, - intel_82335_close, - NULL, - {NULL}, - NULL, - NULL, - NULL}; + .name = "Intel 82335", + .internal_name = "intel_82335", + .flags = 0, + .local = 0, + .init = intel_82335_init, + .close = intel_82335_close, + .reset = NULL, + { .available = NULL }, + .speed_changed = NULL, + .force_redraw = NULL, + .config = NULL +}; diff --git a/src/chipset/intel_i450kx.c b/src/chipset/intel_i450kx.c index 38b2afc1d..90b807a6d 100644 --- a/src/chipset/intel_i450kx.c +++ b/src/chipset/intel_i450kx.c @@ -1,16 +1,18 @@ /* - * 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. + * 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. + * This file is part of the 86Box distribution. * - * Implementation of the Intel 450KX Mars Chipset. + * Implementation of the Intel 450KX Mars Chipset. * - * Authors: Tiseno100, * - * Copyright 2021 Tiseno100. + * + * Authors: Tiseno100 + * + * Copyright 2021 Tiseno100. */ /* @@ -19,7 +21,6 @@ Due to 86Box limitations we can't manage them seperately thus it is dev branch t i450GX is way more popular of an option but needs more stuff. */ - #include #include #include @@ -34,585 +35,596 @@ i450GX is way more popular of an option but needs more stuff. #include <86box/device.h> #include <86box/mem.h> #include <86box/pci.h> +#include <86box/plat_unused.h> #include <86box/smram.h> #include <86box/spd.h> #include <86box/chipset.h> - #ifdef ENABLE_450KX_LOG int i450kx_do_log = ENABLE_450KX_LOG; + static void i450kx_log(const char *fmt, ...) { va_list ap; - if (i450kx_do_log) - { - va_start(ap, fmt); - pclog_ex(fmt, ap); - va_end(ap); + if (i450kx_do_log) { + va_start(ap, fmt); + pclog_ex(fmt, ap); + va_end(ap); } } #else -#define i450kx_log(fmt, ...) +# define i450kx_log(fmt, ...) #endif - /* TODO: Finish the bus index stuff. */ typedef struct i450kx_t { - smram_t * smram[2]; + smram_t *smram[2]; - uint8_t pb_pci_conf[256], mc_pci_conf[256]; - uint8_t mem_state[2][256]; + uint8_t bus_index; + uint8_t pb_slot; + uint8_t mc_slot; + uint8_t pad; - uint8_t bus_index; + uint8_t pb_pci_conf[256]; + uint8_t mc_pci_conf[256]; + + uint8_t mem_state[2][256]; } i450kx_t; - static void i450kx_map(i450kx_t *dev, int bus, uint32_t addr, uint32_t size, int state) { - uint32_t base = addr >> 12; - int states[4] = { MEM_READ_EXTANY | MEM_WRITE_EXTANY, MEM_READ_INTERNAL | MEM_WRITE_EXTANY, - MEM_READ_EXTANY | MEM_WRITE_INTERNAL, MEM_READ_INTERNAL | MEM_WRITE_INTERNAL }; + uint32_t base = addr >> 12; + int states[4] = { MEM_READ_EXTANY | MEM_WRITE_EXTANY, MEM_READ_INTERNAL | MEM_WRITE_EXTANY, + MEM_READ_EXTANY | MEM_WRITE_INTERNAL, MEM_READ_INTERNAL | MEM_WRITE_INTERNAL }; state &= 3; if (dev->mem_state[bus][base] != state) { - if (bus) - mem_set_mem_state_bus_both(addr, size, states[state]); - else - mem_set_mem_state_cpu_both(addr, size, states[state]); - dev->mem_state[bus][base] = state; - flushmmucache_nopc(); + if (bus) + mem_set_mem_state_bus_both(addr, size, states[state]); + else + mem_set_mem_state_cpu_both(addr, size, states[state]); + dev->mem_state[bus][base] = state; + flushmmucache_nopc(); } } - static void i450kx_smram_recalc(i450kx_t *dev, int bus) { - uint8_t *regs = bus ? dev->pb_pci_conf : dev->mc_pci_conf; - uint32_t addr, size; + const uint8_t *regs = bus ? dev->pb_pci_conf : dev->mc_pci_conf; + uint32_t addr; + uint32_t size; smram_disable(dev->smram[bus]); addr = ((uint32_t) regs[0xb8] << 16) | ((uint32_t) regs[0xb9] << 24); size = (((uint32_t) ((regs[0xbb] >> 4) & 0x0f)) << 16) + 0x00010000; - + if ((addr != 0x00000000) && !!(regs[0x57] & 0x08)) { - if (bus) - smram_enable_ex(dev->smram[bus], addr, addr, size, 0, !!(regs[0x57] & 8), 0, 1); - else - smram_enable_ex(dev->smram[bus], addr, addr, size, !!(regs[0x57] & 8), 0, 1, 0); + if (bus) + smram_enable_ex(dev->smram[bus], addr, addr, size, 0, !!(regs[0x57] & 8), 0, 1); + else + smram_enable_ex(dev->smram[bus], addr, addr, size, !!(regs[0x57] & 8), 0, 1, 0); } flushmmucache(); } - static void i450kx_vid_buf_recalc(i450kx_t *dev, int bus) { - uint8_t *regs = bus ? dev->pb_pci_conf : dev->mc_pci_conf; + const uint8_t *regs = bus ? dev->pb_pci_conf : dev->mc_pci_conf; +#if 0 // int state = (regs[0x58] & 0x02) ? (MEM_READ_EXTANY | MEM_WRITE_EXTANY) : (MEM_READ_DISABLED | MEM_WRITE_DISABLED); +#endif int state = (regs[0x58] & 0x02) ? (MEM_READ_INTERNAL | MEM_WRITE_INTERNAL) : (MEM_READ_EXTANY | MEM_WRITE_EXTANY); if (bus) - mem_set_mem_state_bus_both(0x000a0000, 0x00020000, state); + mem_set_mem_state_bus_both(0x000a0000, 0x00020000, state); else - mem_set_mem_state_cpu_both(0x000a0000, 0x00020000, state); + mem_set_mem_state_cpu_both(0x000a0000, 0x00020000, state); flushmmucache_nopc(); } - static void pb_write(int func, int addr, uint8_t val, void *priv) { - i450kx_t *dev = (i450kx_t *)priv; + i450kx_t *dev = (i450kx_t *) priv; // pclog("i450KX-PB: [W] dev->pb_pci_conf[%02X] = %02X POST: %02X\n", addr, val, inb(0x80)); i450kx_log("i450KX-PB: [W] dev->pb_pci_conf[%02X] = %02X POST: %02X\n", addr, val, inb(0x80)); - if (func == 0) switch (addr) { - case 0x04: - dev->pb_pci_conf[addr] = (dev->pb_pci_conf[addr] & 0x04) | (val & 0x53); - break; - case 0x05: - dev->pb_pci_conf[addr] = val & 0x01; - break; + if (func == 0) + switch (addr) { + case 0x04: + dev->pb_pci_conf[addr] = (dev->pb_pci_conf[addr] & 0x04) | (val & 0x53); + break; + case 0x05: + dev->pb_pci_conf[addr] = val & 0x01; + break; - case 0x07: - dev->pb_pci_conf[addr] &= ~(val & 0xf9); - break; + case 0x07: + dev->pb_pci_conf[addr] &= ~(val & 0xf9); + break; - case 0x0d: - dev->pb_pci_conf[addr] = val; - break; + case 0x0d: + dev->pb_pci_conf[addr] = val; + break; - case 0x0f: - dev->pb_pci_conf[addr] = val & 0xcf; - break; + case 0x0f: + dev->pb_pci_conf[addr] = val & 0xcf; + break; - case 0x40: case 0x41: - dev->pb_pci_conf[addr] = val; - break; - case 0x43: - dev->pb_pci_conf[addr] = val & 0x80; - break; + case 0x40: + case 0x41: + dev->pb_pci_conf[addr] = val; + break; + case 0x43: + dev->pb_pci_conf[addr] = val & 0x80; + break; - case 0x48: - dev->pb_pci_conf[addr] = val & 0x06; - break; + case 0x48: + dev->pb_pci_conf[addr] = val & 0x06; + break; - case 0x4a: case 0x4b: - dev->pb_pci_conf[addr] = val; - // if (addr == 0x4a) - // pci_remap_bus(dev->bus_index, val); - break; + case 0x4a: + case 0x4b: + dev->pb_pci_conf[addr] = val; +#if 0 + if (addr == 0x4a) + pci_remap_bus(dev->bus_index, val); +#endif + break; - case 0x4c: - dev->pb_pci_conf[addr] = (dev->pb_pci_conf[addr] & 0x01) | (val & 0xd8); - break; + case 0x4c: + dev->pb_pci_conf[addr] = (dev->pb_pci_conf[addr] & 0x01) | (val & 0xd8); + break; - case 0x51: - dev->pb_pci_conf[addr] = val; - break; + case 0x51: + dev->pb_pci_conf[addr] = val; + break; - case 0x53: - dev->pb_pci_conf[addr] = val & 0x02; - break; + case 0x53: + dev->pb_pci_conf[addr] = val & 0x02; + break; - case 0x54: - dev->pb_pci_conf[addr] = val & 0x7b; - break; - case 0x55: - dev->pb_pci_conf[addr] = val & 0x03; - break; + case 0x54: + dev->pb_pci_conf[addr] = val & 0x7b; + break; + case 0x55: + dev->pb_pci_conf[addr] = val & 0x03; + break; - case 0x57: - dev->pb_pci_conf[addr] = val & 0x08; - i450kx_smram_recalc(dev, 1); - break; + case 0x57: + dev->pb_pci_conf[addr] = val & 0x08; + i450kx_smram_recalc(dev, 1); + break; - case 0x58: - dev->pb_pci_conf[addr] = val & 0x02; - i450kx_vid_buf_recalc(dev, 1); - break; + case 0x58: + dev->pb_pci_conf[addr] = val & 0x02; + i450kx_vid_buf_recalc(dev, 1); + break; - case 0x59: /* PAM0 */ - if ((dev->pb_pci_conf[0x59] ^ val) & 0x0f) - i450kx_map(dev, 1, 0x80000, 0x20000, val & 0x0f); - if ((dev->pb_pci_conf[0x59] ^ val) & 0xf0) { - i450kx_map(dev, 1, 0xf0000, 0x10000, val >> 4); - shadowbios = (val & 0x10); - } - dev->pb_pci_conf[0x59] = val & 0x33; - break; - case 0x5a: /* PAM1 */ - if ((dev->pb_pci_conf[0x5a] ^ val) & 0x0f) - i450kx_map(dev, 1, 0xc0000, 0x04000, val & 0xf); - if ((dev->pb_pci_conf[0x5a] ^ val) & 0xf0) - i450kx_map(dev, 1, 0xc4000, 0x04000, val >> 4); - dev->pb_pci_conf[0x5a] = val & 0x33; - break; - case 0x5b: /*PAM2 */ - if ((dev->pb_pci_conf[0x5b] ^ val) & 0x0f) - i450kx_map(dev, 1, 0xc8000, 0x04000, val & 0xf); - if ((dev->pb_pci_conf[0x5b] ^ val) & 0xf0) - i450kx_map(dev, 1, 0xcc000, 0x04000, val >> 4); - dev->pb_pci_conf[0x5b] = val & 0x33; - break; - case 0x5c: /*PAM3 */ - if ((dev->pb_pci_conf[0x5c] ^ val) & 0x0f) - i450kx_map(dev, 1, 0xd0000, 0x04000, val & 0xf); - if ((dev->pb_pci_conf[0x5c] ^ val) & 0xf0) - i450kx_map(dev, 1, 0xd4000, 0x04000, val >> 4); - dev->pb_pci_conf[0x5c] = val & 0x33; - break; - case 0x5d: /* PAM4 */ - if ((dev->pb_pci_conf[0x5d] ^ val) & 0x0f) - i450kx_map(dev, 1, 0xd8000, 0x04000, val & 0xf); - if ((dev->pb_pci_conf[0x5d] ^ val) & 0xf0) - i450kx_map(dev, 1, 0xdc000, 0x04000, val >> 4); - dev->pb_pci_conf[0x5d] = val & 0x33; - break; - case 0x5e: /* PAM5 */ - if ((dev->pb_pci_conf[0x5e] ^ val) & 0x0f) - i450kx_map(dev, 1, 0xe0000, 0x04000, val & 0xf); - if ((dev->pb_pci_conf[0x5e] ^ val) & 0xf0) - i450kx_map(dev, 1, 0xe4000, 0x04000, val >> 4); - dev->pb_pci_conf[0x5e] = val & 0x33; - break; - case 0x5f: /* PAM6 */ - if ((dev->pb_pci_conf[0x5f] ^ val) & 0x0f) - i450kx_map(dev, 1, 0xe8000, 0x04000, val & 0xf); - if ((dev->pb_pci_conf[0x5f] ^ val) & 0xf0) - i450kx_map(dev, 1, 0xec000, 0x04000, val >> 4); - dev->pb_pci_conf[0x5f] = val & 0x33; - break; + case 0x59: /* PAM0 */ + if ((dev->pb_pci_conf[0x59] ^ val) & 0x0f) + i450kx_map(dev, 1, 0x80000, 0x20000, val & 0x0f); + if ((dev->pb_pci_conf[0x59] ^ val) & 0xf0) { + i450kx_map(dev, 1, 0xf0000, 0x10000, val >> 4); + shadowbios = (val & 0x10); + } + dev->pb_pci_conf[0x59] = val & 0x33; + break; + case 0x5a: /* PAM1 */ + if ((dev->pb_pci_conf[0x5a] ^ val) & 0x0f) + i450kx_map(dev, 1, 0xc0000, 0x04000, val & 0xf); + if ((dev->pb_pci_conf[0x5a] ^ val) & 0xf0) + i450kx_map(dev, 1, 0xc4000, 0x04000, val >> 4); + dev->pb_pci_conf[0x5a] = val & 0x33; + break; + case 0x5b: /*PAM2 */ + if ((dev->pb_pci_conf[0x5b] ^ val) & 0x0f) + i450kx_map(dev, 1, 0xc8000, 0x04000, val & 0xf); + if ((dev->pb_pci_conf[0x5b] ^ val) & 0xf0) + i450kx_map(dev, 1, 0xcc000, 0x04000, val >> 4); + dev->pb_pci_conf[0x5b] = val & 0x33; + break; + case 0x5c: /*PAM3 */ + if ((dev->pb_pci_conf[0x5c] ^ val) & 0x0f) + i450kx_map(dev, 1, 0xd0000, 0x04000, val & 0xf); + if ((dev->pb_pci_conf[0x5c] ^ val) & 0xf0) + i450kx_map(dev, 1, 0xd4000, 0x04000, val >> 4); + dev->pb_pci_conf[0x5c] = val & 0x33; + break; + case 0x5d: /* PAM4 */ + if ((dev->pb_pci_conf[0x5d] ^ val) & 0x0f) + i450kx_map(dev, 1, 0xd8000, 0x04000, val & 0xf); + if ((dev->pb_pci_conf[0x5d] ^ val) & 0xf0) + i450kx_map(dev, 1, 0xdc000, 0x04000, val >> 4); + dev->pb_pci_conf[0x5d] = val & 0x33; + break; + case 0x5e: /* PAM5 */ + if ((dev->pb_pci_conf[0x5e] ^ val) & 0x0f) + i450kx_map(dev, 1, 0xe0000, 0x04000, val & 0xf); + if ((dev->pb_pci_conf[0x5e] ^ val) & 0xf0) + i450kx_map(dev, 1, 0xe4000, 0x04000, val >> 4); + dev->pb_pci_conf[0x5e] = val & 0x33; + break; + case 0x5f: /* PAM6 */ + if ((dev->pb_pci_conf[0x5f] ^ val) & 0x0f) + i450kx_map(dev, 1, 0xe8000, 0x04000, val & 0xf); + if ((dev->pb_pci_conf[0x5f] ^ val) & 0xf0) + i450kx_map(dev, 1, 0xec000, 0x04000, val >> 4); + dev->pb_pci_conf[0x5f] = val & 0x33; + break; - case 0x70: - dev->pb_pci_conf[addr] = val & 0xf8; - break; + case 0x70: + dev->pb_pci_conf[addr] = val & 0xf8; + break; - case 0x71: - dev->pb_pci_conf[addr] = val & 0x71; - break; + case 0x71: + dev->pb_pci_conf[addr] = val & 0x71; + break; - case 0x78: - dev->pb_pci_conf[addr] = val & 0xf0; - break; - case 0x79: - dev->pb_pci_conf[addr] = val & 0xfc; - break; - case 0x7a: - dev->pb_pci_conf[addr] = val; - break; - case 0x7b: - dev->pb_pci_conf[addr] = val & 0x0f; - break; + case 0x78: + dev->pb_pci_conf[addr] = val & 0xf0; + break; + case 0x79: + dev->pb_pci_conf[addr] = val & 0xfc; + break; + case 0x7a: + dev->pb_pci_conf[addr] = val; + break; + case 0x7b: + dev->pb_pci_conf[addr] = val & 0x0f; + break; - case 0x7c: - dev->pb_pci_conf[addr] = val & 0x9f; - break; - case 0x7d: - dev->pb_pci_conf[addr] = val & 0x1a; - break; - case 0x7e: - dev->pb_pci_conf[addr] = val & 0xf0; - break; - case 0x7f: - dev->pb_pci_conf[addr] = val; - break; + case 0x7c: + dev->pb_pci_conf[addr] = val & 0x9f; + break; + case 0x7d: + dev->pb_pci_conf[addr] = val & 0x1a; + break; + case 0x7e: + dev->pb_pci_conf[addr] = val & 0xf0; + break; + case 0x7f: + dev->pb_pci_conf[addr] = val; + break; - case 0x88: case 0x89: - dev->pb_pci_conf[addr] = val; - break; - case 0x8b: - dev->pb_pci_conf[addr] = val & 0x80; - break; - case 0x8c: case 0x8d: - dev->pb_pci_conf[addr] = val; - break; + case 0x88: + case 0x89: + dev->pb_pci_conf[addr] = val; + break; + case 0x8b: + dev->pb_pci_conf[addr] = val & 0x80; + break; + case 0x8c: + case 0x8d: + dev->pb_pci_conf[addr] = val; + break; - case 0x9c: - dev->pb_pci_conf[addr] = val & 0x01; - break; + case 0x9c: + dev->pb_pci_conf[addr] = val & 0x01; + break; - case 0xa4: - dev->pb_pci_conf[addr] = val & 0xf8; - break; - case 0xa5: case 0xa6: - dev->pb_pci_conf[addr] = val; - break; - case 0xa7: - dev->pb_pci_conf[addr] = val & 0x0f; - break; + case 0xa4: + dev->pb_pci_conf[addr] = val & 0xf8; + break; + case 0xa5: + case 0xa6: + dev->pb_pci_conf[addr] = val; + break; + case 0xa7: + dev->pb_pci_conf[addr] = val & 0x0f; + break; - case 0xb0: - dev->pb_pci_conf[addr] = val & 0xe0; - break; - case 0xb1: - dev->pb_pci_conf[addr] = val & /*0x1a*/ 0x1f; - break; + case 0xb0: + dev->pb_pci_conf[addr] = val & 0xe0; + break; + case 0xb1: + dev->pb_pci_conf[addr] = val & /*0x1a*/ 0x1f; + break; - case 0xb4: - dev->pb_pci_conf[addr] = val & 0xe0; - break; - case 0xb5: - dev->pb_pci_conf[addr] = val & 0x1f; - break; + case 0xb8: + case 0xb9: + dev->pb_pci_conf[addr] = val; + i450kx_smram_recalc(dev, 1); + break; + case 0xbb: + dev->pb_pci_conf[addr] = val & 0xf0; + i450kx_smram_recalc(dev, 1); + break; - case 0xb8: case 0xb9: - dev->pb_pci_conf[addr] = val; - i450kx_smram_recalc(dev, 1); - break; - case 0xbb: - dev->pb_pci_conf[addr] = val & 0xf0; - i450kx_smram_recalc(dev, 1); - break; + case 0xbc: + dev->pb_pci_conf[addr] = val & 0x11; + break; - case 0xbc: - dev->pb_pci_conf[addr] = val & 0x11; - break; + case 0xc0: + dev->pb_pci_conf[addr] = val & 0xdf; + break; + case 0xc1: + dev->pb_pci_conf[addr] = val & 0x3f; + break; - case 0xc0: - dev->pb_pci_conf[addr] = val & 0xdf; - break; - case 0xc1: - dev->pb_pci_conf[addr] = val & 0x3f; - break; + case 0xc4: + dev->pb_pci_conf[addr] &= ~(val & 0x0f); + break; + case 0xc5: + dev->pb_pci_conf[addr] &= ~(val & 0x0a); + break; + case 0xc6: + dev->pb_pci_conf[addr] &= ~(val & 0x1f); + break; - case 0xc4: - dev->pb_pci_conf[addr] &= ~(val & 0x0f); - break; - case 0xc5: - dev->pb_pci_conf[addr] &= ~(val & 0x0a); - break; - case 0xc6: - dev->pb_pci_conf[addr] &= ~(val & 0x1f); - break; + case 0xc8: + dev->pb_pci_conf[addr] = val & 0x1f; + break; - case 0xc8: - dev->pb_pci_conf[addr] = val & 0x1f; - break; + case 0xca: + case 0xcb: + dev->pb_pci_conf[addr] = val; + break; - case 0xca: - case 0xcb: - dev->pb_pci_conf[addr] = val; - break; - } + default: + break; + } } - static uint8_t pb_read(int func, int addr, void *priv) { - i450kx_t *dev = (i450kx_t *)priv; - uint8_t ret = 0xff; + const i450kx_t *dev = (i450kx_t *) priv; + uint8_t ret = 0xff; if (func == 0) - ret = dev->pb_pci_conf[addr]; + ret = dev->pb_pci_conf[addr]; // pclog("i450KX-PB: [R] dev->pb_pci_conf[%02X] = %02X POST: %02X\n", addr, ret, inb(0x80)); return ret; } - /* A way to use spd_write_drbs_interlaved() and convert the output to what we need. */ static void mc_fill_drbs(i450kx_t *dev) { - int i; - spd_write_drbs_interleaved(dev->mc_pci_conf, 0x60, 0x6f, 4); - for (i = 0x60; i <= 0x6f; i++) { - if (i & 0x01) - dev->mc_pci_conf[i] = 0x00; - else - dev->mc_pci_conf[i] &= 0x7f; + for (uint8_t i = 0x60; i <= 0x6f; i++) { + if (i & 0x01) + dev->mc_pci_conf[i] = 0x00; + else + dev->mc_pci_conf[i] &= 0x7f; } } - static void mc_write(int func, int addr, uint8_t val, void *priv) { - i450kx_t *dev = (i450kx_t *)priv; + i450kx_t *dev = (i450kx_t *) priv; // pclog("i450KX-MC: [W] dev->mc_pci_conf[%02X] = %02X POST: %02X\n", addr, val, inb(0x80)); i450kx_log("i450KX-MC: [W] dev->mc_pci_conf[%02X] = %02X POST: %02X\n", addr, val, inb(0x80)); - if (func == 0) switch (addr) { - case 0x4c: - dev->mc_pci_conf[addr] = val & 0xdf; - break; - case 0x4d: - dev->mc_pci_conf[addr] = val & 0xff; - break; + if (func == 0) + switch (addr) { + case 0x4c: + dev->mc_pci_conf[addr] = val & 0xdf; + break; + case 0x4d: + dev->mc_pci_conf[addr] = val & 0xff; + break; - case 0x57: - dev->mc_pci_conf[addr] = val & 0x08; - i450kx_smram_recalc(dev, 0); - break; + case 0x57: + dev->mc_pci_conf[addr] = val & 0x08; + i450kx_smram_recalc(dev, 0); + break; - case 0x58: - dev->mc_pci_conf[addr] = val & 0x02; - i450kx_vid_buf_recalc(dev, 0); - break; + case 0x58: + dev->mc_pci_conf[addr] = val & 0x02; + i450kx_vid_buf_recalc(dev, 0); + break; - case 0x59: /* PAM0 */ - if ((dev->mc_pci_conf[0x59] ^ val) & 0x0f) - i450kx_map(dev, 0, 0x80000, 0x20000, val & 0x0f); - if ((dev->mc_pci_conf[0x59] ^ val) & 0xf0) { - i450kx_map(dev, 0, 0xf0000, 0x10000, val >> 4); - shadowbios = (val & 0x10); - } - dev->mc_pci_conf[0x59] = val & 0x33; - break; - case 0x5a: /* PAM1 */ - if ((dev->mc_pci_conf[0x5a] ^ val) & 0x0f) - i450kx_map(dev, 0, 0xc0000, 0x04000, val & 0xf); - if ((dev->mc_pci_conf[0x5a] ^ val) & 0xf0) - i450kx_map(dev, 0, 0xc4000, 0x04000, val >> 4); - dev->mc_pci_conf[0x5a] = val & 0x33; - break; - case 0x5b: /*PAM2 */ - if ((dev->mc_pci_conf[0x5b] ^ val) & 0x0f) - i450kx_map(dev, 0, 0xc8000, 0x04000, val & 0xf); - if ((dev->mc_pci_conf[0x5b] ^ val) & 0xf0) - i450kx_map(dev, 0, 0xcc000, 0x04000, val >> 4); - dev->mc_pci_conf[0x5b] = val & 0x33; - break; - case 0x5c: /*PAM3 */ - if ((dev->mc_pci_conf[0x5c] ^ val) & 0x0f) - i450kx_map(dev, 0, 0xd0000, 0x04000, val & 0xf); - if ((dev->mc_pci_conf[0x5c] ^ val) & 0xf0) - i450kx_map(dev, 0, 0xd4000, 0x04000, val >> 4); - dev->mc_pci_conf[0x5c] = val & 0x33; - break; - case 0x5d: /* PAM4 */ - if ((dev->mc_pci_conf[0x5d] ^ val) & 0x0f) - i450kx_map(dev, 0, 0xd8000, 0x04000, val & 0xf); - if ((dev->mc_pci_conf[0x5d] ^ val) & 0xf0) - i450kx_map(dev, 0, 0xdc000, 0x04000, val >> 4); - dev->mc_pci_conf[0x5d] = val & 0x33; - break; - case 0x5e: /* PAM5 */ - if ((dev->mc_pci_conf[0x5e] ^ val) & 0x0f) - i450kx_map(dev, 0, 0xe0000, 0x04000, val & 0xf); - if ((dev->mc_pci_conf[0x5e] ^ val) & 0xf0) - i450kx_map(dev, 0, 0xe4000, 0x04000, val >> 4); - dev->mc_pci_conf[0x5e] = val & 0x33; - break; - case 0x5f: /* PAM6 */ - if ((dev->mc_pci_conf[0x5f] ^ val) & 0x0f) - i450kx_map(dev, 0, 0xe8000, 0x04000, val & 0xf); - if ((dev->mc_pci_conf[0x5f] ^ val) & 0xf0) - i450kx_map(dev, 0, 0xec000, 0x04000, val >> 4); - dev->mc_pci_conf[0x5f] = val & 0x33; - break; + case 0x59: /* PAM0 */ + if ((dev->mc_pci_conf[0x59] ^ val) & 0x0f) + i450kx_map(dev, 0, 0x80000, 0x20000, val & 0x0f); + if ((dev->mc_pci_conf[0x59] ^ val) & 0xf0) { + i450kx_map(dev, 0, 0xf0000, 0x10000, val >> 4); + shadowbios = (val & 0x10); + } + dev->mc_pci_conf[0x59] = val & 0x33; + break; + case 0x5a: /* PAM1 */ + if ((dev->mc_pci_conf[0x5a] ^ val) & 0x0f) + i450kx_map(dev, 0, 0xc0000, 0x04000, val & 0xf); + if ((dev->mc_pci_conf[0x5a] ^ val) & 0xf0) + i450kx_map(dev, 0, 0xc4000, 0x04000, val >> 4); + dev->mc_pci_conf[0x5a] = val & 0x33; + break; + case 0x5b: /*PAM2 */ + if ((dev->mc_pci_conf[0x5b] ^ val) & 0x0f) + i450kx_map(dev, 0, 0xc8000, 0x04000, val & 0xf); + if ((dev->mc_pci_conf[0x5b] ^ val) & 0xf0) + i450kx_map(dev, 0, 0xcc000, 0x04000, val >> 4); + dev->mc_pci_conf[0x5b] = val & 0x33; + break; + case 0x5c: /*PAM3 */ + if ((dev->mc_pci_conf[0x5c] ^ val) & 0x0f) + i450kx_map(dev, 0, 0xd0000, 0x04000, val & 0xf); + if ((dev->mc_pci_conf[0x5c] ^ val) & 0xf0) + i450kx_map(dev, 0, 0xd4000, 0x04000, val >> 4); + dev->mc_pci_conf[0x5c] = val & 0x33; + break; + case 0x5d: /* PAM4 */ + if ((dev->mc_pci_conf[0x5d] ^ val) & 0x0f) + i450kx_map(dev, 0, 0xd8000, 0x04000, val & 0xf); + if ((dev->mc_pci_conf[0x5d] ^ val) & 0xf0) + i450kx_map(dev, 0, 0xdc000, 0x04000, val >> 4); + dev->mc_pci_conf[0x5d] = val & 0x33; + break; + case 0x5e: /* PAM5 */ + if ((dev->mc_pci_conf[0x5e] ^ val) & 0x0f) + i450kx_map(dev, 0, 0xe0000, 0x04000, val & 0xf); + if ((dev->mc_pci_conf[0x5e] ^ val) & 0xf0) + i450kx_map(dev, 0, 0xe4000, 0x04000, val >> 4); + dev->mc_pci_conf[0x5e] = val & 0x33; + break; + case 0x5f: /* PAM6 */ + if ((dev->mc_pci_conf[0x5f] ^ val) & 0x0f) + i450kx_map(dev, 0, 0xe8000, 0x04000, val & 0xf); + if ((dev->mc_pci_conf[0x5f] ^ val) & 0xf0) + i450kx_map(dev, 0, 0xec000, 0x04000, val >> 4); + dev->mc_pci_conf[0x5f] = val & 0x33; + break; - case 0x60 ... 0x6f: - dev->mc_pci_conf[addr] = ((addr & 0x0f) & 0x01) ? 0x00 : (val & 0x7f); - mc_fill_drbs(dev); - break; + case 0x60 ... 0x6f: + dev->mc_pci_conf[addr] = ((addr & 0x0f) & 0x01) ? 0x00 : (val & 0x7f); + mc_fill_drbs(dev); + break; - case 0x74 ... 0x77: - dev->mc_pci_conf[addr] = val; - break; + case 0x74 ... 0x77: + dev->mc_pci_conf[addr] = val; + break; - case 0x78: - dev->mc_pci_conf[addr] = val & 0xf0; - break; - case 0x79: - dev->mc_pci_conf[addr] = val & 0xfe; - break; - case 0x7a: - dev->mc_pci_conf[addr] = val; - break; - case 0x7b: - dev->mc_pci_conf[addr] = val & 0x0f; - break; + case 0x78: + dev->mc_pci_conf[addr] = val & 0xf0; + break; + case 0x79: + dev->mc_pci_conf[addr] = val & 0xfe; + break; + case 0x7a: + dev->mc_pci_conf[addr] = val; + break; + case 0x7b: + dev->mc_pci_conf[addr] = val & 0x0f; + break; - case 0x7c: - dev->mc_pci_conf[addr] = val & 0x1f; - break; - case 0x7d: - dev->mc_pci_conf[addr] = val & 0x0c; - break; - case 0x7e: - dev->mc_pci_conf[addr] = val & 0xf0; - break; - case 0x7f: - dev->mc_pci_conf[addr] = val; - break; + case 0x7c: + dev->mc_pci_conf[addr] = val & 0x1f; + break; + case 0x7d: + dev->mc_pci_conf[addr] = val & 0x0c; + break; + case 0x7e: + dev->mc_pci_conf[addr] = val & 0xf0; + break; + case 0x7f: + dev->mc_pci_conf[addr] = val; + break; - case 0x88: case 0x89: - dev->mc_pci_conf[addr] = val; - break; - case 0x8b: - dev->mc_pci_conf[addr] = val & 0x80; - break; + case 0x88: + case 0x89: + dev->mc_pci_conf[addr] = val; + break; + case 0x8b: + dev->mc_pci_conf[addr] = val & 0x80; + break; - case 0x8c: case 0x8d: - dev->mc_pci_conf[addr] = val; - break; + case 0x8c: + case 0x8d: + dev->mc_pci_conf[addr] = val; + break; - case 0xa4: - dev->mc_pci_conf[addr] = val & 0x01; - break; - case 0xa5: - dev->pb_pci_conf[addr] = val & 0xf0; - break; - case 0xa6: - dev->mc_pci_conf[addr] = val; - break; - case 0xa7: - dev->mc_pci_conf[addr] = val & 0x0f; - break; + case 0xa4: + dev->mc_pci_conf[addr] = val & 0x01; + break; + case 0xa5: + dev->pb_pci_conf[addr] = val & 0xf0; + break; + case 0xa6: + dev->mc_pci_conf[addr] = val; + break; + case 0xa7: + dev->mc_pci_conf[addr] = val & 0x0f; + break; - case 0xa8: - dev->mc_pci_conf[addr] = val & 0xfe; - break; - case 0xa9 ... 0xab: - dev->mc_pci_conf[addr] = val; - break; + case 0xa8: + dev->mc_pci_conf[addr] = val & 0xfe; + break; + case 0xa9 ... 0xab: + dev->mc_pci_conf[addr] = val; + break; - case 0xac ... 0xae: - dev->mc_pci_conf[addr] = val; - break; - case 0xaf: - dev->mc_pci_conf[addr] = val & 0x7f; - break; + case 0xac ... 0xae: + dev->mc_pci_conf[addr] = val; + break; + case 0xaf: + dev->mc_pci_conf[addr] = val & 0x7f; + break; - case 0xb8: case 0xb9: - dev->mc_pci_conf[addr] = val; - i450kx_smram_recalc(dev, 0); - break; - case 0xbb: - dev->mc_pci_conf[addr] = val & 0xf0; - i450kx_smram_recalc(dev, 0); - break; + case 0xb8: + case 0xb9: + dev->mc_pci_conf[addr] = val; + i450kx_smram_recalc(dev, 0); + break; + case 0xbb: + dev->mc_pci_conf[addr] = val & 0xf0; + i450kx_smram_recalc(dev, 0); + break; - case 0xbc: - dev->mc_pci_conf[addr] = val & 0x01; - break; + case 0xbc: + dev->mc_pci_conf[addr] = val & 0x01; + break; - case 0xc0: - dev->mc_pci_conf[addr] = val & 0x07; - break; + case 0xc0: + dev->mc_pci_conf[addr] = val & 0x07; + break; - case 0xc2: - dev->mc_pci_conf[addr] &= ~(val & 0x03); - break; + case 0xc2: + dev->mc_pci_conf[addr] &= ~(val & 0x03); + break; - case 0xc4: - dev->mc_pci_conf[addr] = val & 0xbf; - break; - case 0xc5: - dev->mc_pci_conf[addr] = val & 0x03; - break; + case 0xc4: + dev->mc_pci_conf[addr] = val & 0xbf; + break; + case 0xc5: + dev->mc_pci_conf[addr] = val & 0x03; + break; - case 0xc6: - dev->mc_pci_conf[addr] &= ~(val & 0x19); - break; + case 0xc6: + dev->mc_pci_conf[addr] &= ~(val & 0x19); + break; - case 0xc8: - dev->mc_pci_conf[addr] = val & 0x1f; - break; - case 0xca: case 0xcb: - dev->mc_pci_conf[addr] = val; - break; - } + case 0xc8: + dev->mc_pci_conf[addr] = val & 0x1f; + break; + case 0xca: + case 0xcb: + dev->mc_pci_conf[addr] = val; + break; + + default: + break; + } } - static uint8_t mc_read(int func, int addr, void *priv) { - i450kx_t *dev = (i450kx_t *)priv; - uint8_t ret = 0xff; + const i450kx_t *dev = (i450kx_t *) priv; + uint8_t ret = 0xff; if (func == 0) - ret = dev->mc_pci_conf[addr]; + ret = dev->mc_pci_conf[addr]; // pclog("i450KX-MC: [R] dev->mc_pci_conf[%02X] = %02X POST: %02X\n", addr, ret, inb(0x80)); return ret; } - static void i450kx_reset(void *priv) { - i450kx_t *dev = (i450kx_t *)priv; - uint32_t i; + i450kx_t *dev = (i450kx_t *) priv; + uint32_t i; +#if 0 // pclog("i450KX: i450kx_reset()\n"); +#endif /* Defaults PB */ dev->pb_pci_conf[0x00] = 0x86; @@ -670,9 +682,11 @@ i450kx_reset(void *priv) dev->pb_pci_conf[0xa6] = 0xfe; dev->pb_pci_conf[0xa7] = 0x00; /* Note: Do NOT reset these two registers on programmed (TRC) hard reset! */ - // dev->pb_pci_conf[0xb0] = 0x00; - // dev->pb_pci_conf[0xb1] = 0x00; - dev->pb_pci_conf[0xb4] = 0x00; +#if 0 + dev->pb_pci_conf[0xb0] = 0x00; + dev->pb_pci_conf[0xb1] = 0x00; +#endif + dev->pb_pci_conf[0xb4] = 0xff; dev->pb_pci_conf[0xb5] = 0x00; dev->pb_pci_conf[0xb8] = 0x05; dev->pb_pci_conf[0xb9] = 0x00; @@ -692,12 +706,14 @@ i450kx_reset(void *priv) dev->pb_pci_conf[0xca] = 0x00; dev->pb_pci_conf[0xcb] = 0x00; - // pci_remap_bus(dev->bus_index, 0x00); +#if 0 + pci_remap_bus(dev->bus_index, 0x00); +#endif i450kx_smram_recalc(dev, 1); i450kx_vid_buf_recalc(dev, 1); pb_write(0, 0x59, 0x30, dev); for (i = 0x5a; i <= 0x5f; i++) - pb_write(0, i, 0x33, dev); + pb_write(0, i, 0x33, dev); /* Defaults MC */ dev->mc_pci_conf[0x00] = 0x86; @@ -769,30 +785,28 @@ i450kx_reset(void *priv) i450kx_vid_buf_recalc(dev, 0); mc_write(0, 0x59, 0x03, dev); for (i = 0x5a; i <= 0x5f; i++) - mc_write(0, i, 0x00, dev); + mc_write(0, i, 0x00, dev); for (i = 0x60; i <= 0x6f; i++) - dev->mc_pci_conf[i] = 0x01; + dev->mc_pci_conf[i] = 0x01; } - static void i450kx_close(void *priv) { - i450kx_t *dev = (i450kx_t *)priv; + i450kx_t *dev = (i450kx_t *) priv; smram_del(dev->smram[1]); smram_del(dev->smram[0]); free(dev); } - static void * -i450kx_init(const device_t *info) +i450kx_init(UNUSED(const device_t *info)) { - i450kx_t *dev = (i450kx_t *)malloc(sizeof(i450kx_t)); + i450kx_t *dev = (i450kx_t *) malloc(sizeof(i450kx_t)); memset(dev, 0, sizeof(i450kx_t)); - pci_add_card(PCI_ADD_NORTHBRIDGE, pb_read, pb_write, dev); /* Device 19h: Intel 450KX PCI Bridge PB */ - pci_add_card(PCI_ADD_AGPBRIDGE, mc_read, mc_write, dev); /* Device 14h: Intel 450KX Memory Controller MC */ + pci_add_card(PCI_ADD_NORTHBRIDGE, pb_read, pb_write, dev, &dev->pb_slot); /* Device 19h: Intel 450KX PCI Bridge PB */ + pci_add_card(PCI_ADD_NORTHBRIDGE_SEC, mc_read, mc_write, dev, &dev->mc_slot); /* Device 14h: Intel 450KX Memory Controller MC */ dev->smram[0] = smram_add(); dev->smram[1] = smram_add(); @@ -806,17 +820,16 @@ i450kx_init(const device_t *info) return dev; } - const device_t i450kx_device = { - "Intel 450KX (Mars)", - "i450kx", - DEVICE_PCI, - 0, - i450kx_init, - i450kx_close, - i450kx_reset, - { NULL }, - NULL, - NULL, - NULL + .name = "Intel 450KX (Mars)", + .internal_name = "i450kx", + .flags = DEVICE_PCI, + .local = 0, + .init = i450kx_init, + .close = i450kx_close, + .reset = i450kx_reset, + { .available = NULL }, + .speed_changed = NULL, + .force_redraw = NULL, + .config = NULL }; diff --git a/src/chipset/intel_piix.c b/src/chipset/intel_piix.c index 97280b06c..2094eefcf 100644 --- a/src/chipset/intel_piix.c +++ b/src/chipset/intel_piix.c @@ -1,21 +1,21 @@ /* - * 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. + * 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. * - * Emulation of the Intel PIIX, PIIX3, PIIX4, PIIX4E, and SMSC - * SLC90E66 (Victory66) Xcelerators. + * Emulation of the Intel PIIX, PIIX3, PIIX4, PIIX4E, and SMSC + * SLC90E66 (Victory66) Xcelerators. * - * PRD format : - * word 0 - base address - * word 1 - bits 1-15 = byte count, bit 31 = end of transfer + * PRD format : + * word 0 - base address + * word 1 - bits 1-15 = byte count, bit 31 = end of transfer * * * - * Authors: Miran Grca, + * Authors: Miran Grca, * - * Copyright 2016-2020 Miran Grca. + * Copyright 2016-2020 Miran Grca. */ #include #include @@ -40,6 +40,7 @@ #include <86box/pci.h> #include <86box/pic.h> #include <86box/pit.h> +#include <86box/plat.h> #include <86box/port_92.h> #include <86box/scsi_device.h> #include <86box/hdc.h> @@ -50,152 +51,152 @@ #include <86box/smbus.h> #include <86box/chipset.h> - -typedef struct { +typedef struct piix_io_trap_t { struct _piix_ *dev; - void *trap; - uint8_t dev_id; - uint32_t *sts_reg, *en_reg, sts_mask, en_mask; + void *trap; + uint8_t dev_id; + uint32_t *sts_reg, *en_reg, sts_mask, en_mask; } piix_io_trap_t; typedef struct _piix_ { - uint8_t cur_readout_reg, rev, - type, func_shift, - max_func, pci_slot, - no_mirq0, pad, - regs[4][256], - readout_regs[256], board_config[2]; - uint16_t func0_id, nvr_io_base, - acpi_io_base; - double fast_off_period; - sff8038i_t *bm[2]; - smbus_piix4_t * smbus; - apm_t * apm; - nvr_t * nvr; - ddma_t * ddma; - usb_t * usb; - acpi_t * acpi; - piix_io_trap_t io_traps[26]; - port_92_t * port_92; - pc_timer_t fast_off_timer; + uint8_t cur_readout_reg; + uint8_t rev; + uint8_t type; + uint8_t func_shift; + uint8_t max_func; + uint8_t pci_slot; + uint8_t no_mirq0; + uint8_t regs[4][256]; + uint8_t readout_regs[256]; + uint16_t func0_id; + uint16_t nvr_io_base; + uint16_t acpi_io_base; + double fast_off_period; + sff8038i_t *bm[2]; + smbus_piix4_t *smbus; + apm_t *apm; + nvr_t *nvr; + ddma_t *ddma; + usb_t *usb; + acpi_t *acpi; + piix_io_trap_t io_traps[26]; + port_92_t *port_92; + pc_timer_t fast_off_timer; } piix_t; - #ifdef ENABLE_PIIX_LOG int piix_do_log = ENABLE_PIIX_LOG; - static void piix_log(const char *fmt, ...) { va_list ap; if (piix_do_log) { - va_start(ap, fmt); - pclog_ex(fmt, ap); - va_end(ap); + va_start(ap, fmt); + pclog_ex(fmt, ap); + va_end(ap); } } #else -#define piix_log(fmt, ...) +# define piix_log(fmt, ...) #endif - static void smsc_ide_irqs(piix_t *dev) { - int irq_line = 3, irq_mode[2] = { 0, 0 }; + int irq_line = 3; + uint8_t irq_mode[2] = { IRQ_MODE_LEGACY, IRQ_MODE_LEGACY }; if (dev->regs[1][0x09] & 0x01) - irq_mode[0] = (dev->regs[0][0xe1] & 0x01) ? 3 : 1; + irq_mode[0] = (dev->regs[0][0xe1] & 0x01) ? IRQ_MODE_PCI_IRQ_LINE : IRQ_MODE_PCI_IRQ_PIN; if (dev->regs[1][0x09] & 0x04) - irq_mode[1] = (dev->regs[0][0xe1] & 0x01) ? 3 : 1; + irq_mode[1] = (dev->regs[0][0xe1] & 0x01) ? IRQ_MODE_PCI_IRQ_LINE : IRQ_MODE_PCI_IRQ_PIN; switch ((dev->regs[0][0xe1] >> 1) & 0x07) { - case 0x00: - irq_line = 3; - break; - case 0x01: - irq_line = 5; - break; - case 0x02: - irq_line = 7; - break; - case 0x03: - irq_line = 8; - break; - case 0x04: - irq_line = 11; - break; - case 0x05: - irq_line = 12; - break; - case 0x06: - irq_line = 14; - break; - case 0x07: - irq_line = 15; - break; + case 0x00: + irq_line = 3; + break; + case 0x01: + irq_line = 5; + break; + case 0x02: + irq_line = 7; + break; + case 0x03: + irq_line = 8; + break; + case 0x04: + irq_line = 11; + break; + case 0x05: + irq_line = 12; + break; + case 0x06: + irq_line = 14; + break; + case 0x07: + irq_line = 15; + break; + default: + break; } sff_set_irq_line(dev->bm[0], irq_line); - sff_set_irq_mode(dev->bm[0], 0, irq_mode[0]); - sff_set_irq_mode(dev->bm[0], 1, irq_mode[1]); + sff_set_irq_mode(dev->bm[0], irq_mode[0]); sff_set_irq_line(dev->bm[1], irq_line); - sff_set_irq_mode(dev->bm[1], 0, irq_mode[0]); - sff_set_irq_mode(dev->bm[1], 1, irq_mode[1]); + sff_set_irq_mode(dev->bm[1], irq_mode[1]); } - static void piix_ide_handlers(piix_t *dev, int bus) { - uint16_t main, side; + uint16_t main; + uint16_t side; if (bus & 0x01) { - ide_pri_disable(); + ide_pri_disable(); - if (dev->type == 5) { - if (dev->regs[1][0x09] & 0x01) { - main = (dev->regs[1][0x11] << 8) | (dev->regs[1][0x10] & 0xf8); - side = ((dev->regs[1][0x15] << 8) | (dev->regs[1][0x14] & 0xfc)) + 2; - } else { - main = 0x1f0; - side = 0x3f6; - } + if (dev->type == 5) { + if (dev->regs[1][0x09] & 0x01) { + main = (dev->regs[1][0x11] << 8) | (dev->regs[1][0x10] & 0xf8); + side = ((dev->regs[1][0x15] << 8) | (dev->regs[1][0x14] & 0xfc)) + 2; + } else { + main = 0x1f0; + side = 0x3f6; + } - ide_set_base(0, main); - ide_set_side(0, side); - } + ide_set_base(0, main); + ide_set_side(0, side); + } - if ((dev->regs[1][0x04] & 0x01) && (dev->regs[1][0x41] & 0x80)) - ide_pri_enable(); + if ((dev->regs[1][0x04] & 0x01) && (dev->regs[1][0x41] & 0x80)) + ide_pri_enable(); } if (bus & 0x02) { - ide_sec_disable(); + ide_sec_disable(); - if (dev->type == 5) { - if (dev->regs[1][0x09] & 0x04) { - main = (dev->regs[1][0x19] << 8) | (dev->regs[1][0x18] & 0xf8); - side = ((dev->regs[1][0x1d] << 8) | (dev->regs[1][0x1c] & 0xfc)) + 2; - } else { - main = 0x170; - side = 0x376; - } + if (dev->type == 5) { + if (dev->regs[1][0x09] & 0x04) { + main = (dev->regs[1][0x19] << 8) | (dev->regs[1][0x18] & 0xf8); + side = ((dev->regs[1][0x1d] << 8) | (dev->regs[1][0x1c] & 0xfc)) + 2; + } else { + main = 0x170; + side = 0x376; + } - ide_set_base(1, main); - ide_set_side(1, side); - } + ide_set_base(1, main); + ide_set_side(1, side); + } - if ((dev->regs[1][0x04] & 0x01) && (dev->regs[1][0x43] & 0x80)) - ide_sec_enable(); + if ((dev->regs[1][0x04] & 0x01) && (dev->regs[1][0x43] & 0x80)) + ide_sec_enable(); } } - static void piix_ide_bm_handlers(piix_t *dev) { @@ -205,23 +206,20 @@ piix_ide_bm_handlers(piix_t *dev) sff_bus_master_handler(dev->bm[1], (dev->regs[1][0x04] & 1), base + 8); } - static uint8_t -kbc_alias_reg_read(uint16_t addr, void *p) +kbc_alias_reg_read(UNUSED(uint16_t addr), UNUSED(void *priv)) { uint8_t ret = inb(0x61); return ret; } - static void -kbc_alias_reg_write(uint16_t addr, uint8_t val, void *p) +kbc_alias_reg_write(UNUSED(uint16_t addr), uint8_t val, UNUSED(void *priv)) { outb(0x61, val); } - static void kbc_alias_update_io_mapping(piix_t *dev) { @@ -230,109 +228,104 @@ kbc_alias_update_io_mapping(piix_t *dev) io_removehandler(0x0067, 1, kbc_alias_reg_read, NULL, NULL, kbc_alias_reg_write, NULL, NULL, dev); if (dev->regs[0][0x4e] & 0x08) { - io_sethandler(0x0063, 1, kbc_alias_reg_read, NULL, NULL, kbc_alias_reg_write, NULL, NULL, dev); - io_sethandler(0x0065, 1, kbc_alias_reg_read, NULL, NULL, kbc_alias_reg_write, NULL, NULL, dev); - io_sethandler(0x0067, 1, kbc_alias_reg_read, NULL, NULL, kbc_alias_reg_write, NULL, NULL, dev); + io_sethandler(0x0063, 1, kbc_alias_reg_read, NULL, NULL, kbc_alias_reg_write, NULL, NULL, dev); + io_sethandler(0x0065, 1, kbc_alias_reg_read, NULL, NULL, kbc_alias_reg_write, NULL, NULL, dev); + io_sethandler(0x0067, 1, kbc_alias_reg_read, NULL, NULL, kbc_alias_reg_write, NULL, NULL, dev); } } - static void smbus_update_io_mapping(piix_t *dev) { smbus_piix4_remap(dev->smbus, ((uint16_t) (dev->regs[3][0x91] << 8)) | (dev->regs[3][0x90] & 0xf0), (dev->regs[3][PCI_REG_COMMAND] & PCI_COMMAND_IO) && (dev->regs[3][0xd2] & 0x01)); } - static void nvr_update_io_mapping(piix_t *dev) { if (dev->nvr_io_base != 0x0000) { - piix_log("Removing NVR at %04X...\n", dev->nvr_io_base); - nvr_at_handler(0, dev->nvr_io_base, dev->nvr); - nvr_at_handler(0, dev->nvr_io_base + 0x0002, dev->nvr); - nvr_at_handler(0, dev->nvr_io_base + 0x0004, dev->nvr); + piix_log("Removing NVR at %04X...\n", dev->nvr_io_base); + nvr_at_handler(0, dev->nvr_io_base, dev->nvr); + nvr_at_handler(0, dev->nvr_io_base + 0x0002, dev->nvr); + nvr_at_handler(0, dev->nvr_io_base + 0x0004, dev->nvr); } if (dev->type == 5) - dev->nvr_io_base = (dev->regs[0][0xd5] << 8) | (dev->regs[0][0xd4] & 0xf0); + dev->nvr_io_base = (dev->regs[0][0xd5] << 8) | (dev->regs[0][0xd4] & 0xf0); else - dev->nvr_io_base = 0x70; + dev->nvr_io_base = 0x70; piix_log("New NVR I/O base: %04X\n", dev->nvr_io_base); if (dev->regs[0][0xcb] & 0x01) { - piix_log("Adding low NVR at %04X...\n", dev->nvr_io_base); - if (dev->nvr_io_base != 0x0000) { - nvr_at_handler(1, dev->nvr_io_base, dev->nvr); - nvr_at_handler(1, dev->nvr_io_base + 0x0004, dev->nvr); - } + piix_log("Adding low NVR at %04X...\n", dev->nvr_io_base); + if (dev->nvr_io_base != 0x0000) { + nvr_at_handler(1, dev->nvr_io_base, dev->nvr); + nvr_at_handler(1, dev->nvr_io_base + 0x0004, dev->nvr); + } } if (dev->regs[0][0xcb] & 0x04) { - piix_log("Adding high NVR at %04X...\n", dev->nvr_io_base + 0x0002); - if (dev->nvr_io_base != 0x0000) - nvr_at_handler(1, dev->nvr_io_base + 0x0002, dev->nvr); + piix_log("Adding high NVR at %04X...\n", dev->nvr_io_base + 0x0002); + if (dev->nvr_io_base != 0x0000) + nvr_at_handler(1, dev->nvr_io_base + 0x0002, dev->nvr); } } - static void -piix_trap_io(int size, uint16_t addr, uint8_t write, uint8_t val, void *priv) +piix_trap_io(UNUSED(int size), UNUSED(uint16_t addr), UNUSED(uint8_t write), UNUSED(uint8_t val), void *priv) { piix_io_trap_t *trap = (piix_io_trap_t *) priv; if (*(trap->en_reg) & trap->en_mask) { - *(trap->sts_reg) |= trap->sts_mask; - acpi_raise_smi(trap->dev->acpi, 1); + *(trap->sts_reg) |= trap->sts_mask; + acpi_raise_smi(trap->dev->acpi, 1); } } - static void piix_trap_io_ide(int size, uint16_t addr, uint8_t write, uint8_t val, void *priv) { - piix_io_trap_t *trap = (piix_io_trap_t *) priv; + const piix_io_trap_t *trap = (piix_io_trap_t *) priv; /* IDE traps are per drive, not per channel. */ if (ide_drives[trap->dev_id]->selected) - piix_trap_io(size, addr, write, val, priv); + piix_trap_io(size, addr, write, val, priv); } - static void piix_trap_update_devctl(piix_t *dev, uint8_t trap_id, uint8_t dev_id, - uint32_t devctl_mask, uint8_t enable, - uint16_t addr, uint16_t size) + uint32_t devctl_mask, uint8_t enable, + uint16_t addr, uint16_t size) { piix_io_trap_t *trap = &dev->io_traps[trap_id]; - enable = (dev->acpi->regs.devctl & devctl_mask) && enable; + enable = (dev->acpi->regs.devctl & devctl_mask) && enable; /* Set up Device I/O traps dynamically. */ if (enable && !trap->trap) { - trap->dev = dev; - trap->trap = io_trap_add((dev_id <= 3) ? piix_trap_io_ide : piix_trap_io, trap); - trap->dev_id = dev_id; - trap->sts_reg = &dev->acpi->regs.devsts; - trap->sts_mask = 0x00010000 << dev_id; - trap->en_reg = &dev->acpi->regs.devctl; - trap->en_mask = devctl_mask; + trap->dev = dev; + trap->trap = io_trap_add((dev_id <= 3) ? piix_trap_io_ide : piix_trap_io, trap); + trap->dev_id = dev_id; + trap->sts_reg = &dev->acpi->regs.devsts; + trap->sts_mask = 0x00010000 << dev_id; + trap->en_reg = &dev->acpi->regs.devctl; + trap->en_mask = devctl_mask; } #ifdef ENABLE_PIIX_LOG if ((dev_id == 9) || (dev_id == 10) || (dev_id == 12) || (dev_id == 13)) - piix_log("PIIX: Mapping trap device %d to %04X-%04X (enable %d)\n", dev_id, addr, addr + size - 1, enable); + piix_log("PIIX: Mapping trap device %d to %04X-%04X (enable %d)\n", dev_id, addr, addr + size - 1, enable); #endif /* Remap I/O trap. */ io_trap_remap(trap->trap, enable, addr, size); } - static void piix_trap_update(void *priv) { - piix_t *dev = (piix_t *) priv; - uint8_t trap_id = 0, *fregs = dev->regs[3]; - uint16_t temp; + piix_t *dev = (piix_t *) priv; + uint8_t trap_id = 0; + const uint8_t *fregs = dev->regs[3]; + uint16_t temp; piix_trap_update_devctl(dev, trap_id++, 0, 0x00000002, 1, 0x1f0, 8); piix_trap_update_devctl(dev, trap_id++, 0, 0x00000002, 1, 0x3f6, 1); @@ -350,10 +343,18 @@ piix_trap_update(void *priv) piix_trap_update_devctl(dev, trap_id++, 4, 0x00000200, fregs[0x5c] & 0x10, 0x200, 8); piix_trap_update_devctl(dev, trap_id++, 4, 0x00000200, fregs[0x5c] & 0x08, 0x388, 4); switch (fregs[0x5d] & 0x03) { - case 0x00: temp = 0x530; break; - case 0x01: temp = 0x604; break; - case 0x02: temp = 0xe80; break; - default: temp = 0xf40; break; + case 0x00: + temp = 0x530; + break; + case 0x01: + temp = 0x604; + break; + case 0x02: + temp = 0xe80; + break; + default: + temp = 0xf40; + break; } piix_trap_update_devctl(dev, trap_id++, 4, 0x00000200, fregs[0x5c] & 0x80, temp, 8); piix_trap_update_devctl(dev, trap_id++, 4, 0x00000200, fregs[0x5c] & 0x01, 0x300 + (0x10 * ((fregs[0x5c] >> 1) & 0x03)), 4); @@ -362,49 +363,81 @@ piix_trap_update(void *priv) piix_trap_update_devctl(dev, trap_id++, 5, 0x00000800, fregs[0x51] & 0x10, 0x377 + (0x80 * !(fregs[0x63] & 0x10)), 1); switch (fregs[0x67] & 0x07) { - case 0x00: temp = 0x3f8; break; - case 0x01: temp = 0x2f8; break; - case 0x02: temp = 0x220; break; - case 0x03: temp = 0x228; break; - case 0x04: temp = 0x238; break; - case 0x05: temp = 0x2e8; break; - case 0x06: temp = 0x338; break; - default: temp = 0x3e8; break; + case 0x00: + temp = 0x3f8; + break; + case 0x01: + temp = 0x2f8; + break; + case 0x02: + temp = 0x220; + break; + case 0x03: + temp = 0x228; + break; + case 0x04: + temp = 0x238; + break; + case 0x05: + temp = 0x2e8; + break; + case 0x06: + temp = 0x338; + break; + default: + temp = 0x3e8; + break; } piix_trap_update_devctl(dev, trap_id++, 6, 0x00002000, fregs[0x51] & 0x40, temp, 8); switch (fregs[0x67] & 0x70) { - case 0x00: temp = 0x3f8; break; - case 0x10: temp = 0x2f8; break; - case 0x20: temp = 0x220; break; - case 0x30: temp = 0x228; break; - case 0x40: temp = 0x238; break; - case 0x50: temp = 0x2e8; break; - case 0x60: temp = 0x338; break; - default: temp = 0x3e8; break; + case 0x00: + temp = 0x3f8; + break; + case 0x10: + temp = 0x2f8; + break; + case 0x20: + temp = 0x220; + break; + case 0x30: + temp = 0x228; + break; + case 0x40: + temp = 0x238; + break; + case 0x50: + temp = 0x2e8; + break; + case 0x60: + temp = 0x338; + break; + default: + temp = 0x3e8; + break; } piix_trap_update_devctl(dev, trap_id++, 7, 0x00008000, fregs[0x52] & 0x01, temp, 8); switch (fregs[0x63] & 0x06) { - case 0x00: - piix_trap_update_devctl(dev, trap_id++, 8, 0x00020000, fregs[0x52] & 0x04, 0x3bc, 4); - piix_trap_update_devctl(dev, trap_id++, 8, 0x00020000, fregs[0x52] & 0x04, 0x7bc, 3); - break; + case 0x00: + piix_trap_update_devctl(dev, trap_id++, 8, 0x00020000, fregs[0x52] & 0x04, 0x3bc, 4); + piix_trap_update_devctl(dev, trap_id++, 8, 0x00020000, fregs[0x52] & 0x04, 0x7bc, 3); + break; - case 0x02: - piix_trap_update_devctl(dev, trap_id++, 8, 0x00020000, fregs[0x52] & 0x04, 0x378, 8); - piix_trap_update_devctl(dev, trap_id++, 8, 0x00020000, fregs[0x52] & 0x04, 0x778, 3); - break; + case 0x02: + piix_trap_update_devctl(dev, trap_id++, 8, 0x00020000, fregs[0x52] & 0x04, 0x378, 8); + piix_trap_update_devctl(dev, trap_id++, 8, 0x00020000, fregs[0x52] & 0x04, 0x778, 3); + break; - case 0x04: - piix_trap_update_devctl(dev, trap_id++, 8, 0x00020000, fregs[0x52] & 0x04, 0x278, 8); - piix_trap_update_devctl(dev, trap_id++, 8, 0x00020000, fregs[0x52] & 0x04, 0x678, 3); - break; + case 0x04: + piix_trap_update_devctl(dev, trap_id++, 8, 0x00020000, fregs[0x52] & 0x04, 0x278, 8); + piix_trap_update_devctl(dev, trap_id++, 8, 0x00020000, fregs[0x52] & 0x04, 0x678, 3); + break; - default: - piix_trap_update_devctl(dev, trap_id++, 8, 0x00020000, fregs[0x52] & 0x04, 0, 0); - piix_trap_update_devctl(dev, trap_id++, 8, 0x00020000, fregs[0x52] & 0x04, 0, 0); - break; + default: + piix_trap_update_devctl(dev, trap_id++, 8, 0x00020000, fregs[0x52] & 0x04, 0, 0); + piix_trap_update_devctl(dev, trap_id++, 8, 0x00020000, fregs[0x52] & 0x04, 0, 0); + break; } temp = fregs[0x62] & 0x0f; @@ -427,724 +460,768 @@ piix_trap_update(void *priv) /* Programmable memory trap not implemented. */ } - static void piix_write(int func, int addr, uint8_t val, void *priv) { - piix_t *dev = (piix_t *) priv; + piix_t *dev = (piix_t *) priv; uint8_t *fregs; uint16_t base; - int i; /* Return on unsupported function. */ if (dev->max_func > 0) { - if (func > dev->max_func) - return; + if (func > dev->max_func) + return; } else { - if (func > 1) - return; + if (func > 1) + return; } /* Ignore the new IDE BAR's on the Intel chips. */ if ((dev->type < 5) && (func == 1) && (addr >= 0x10) && (addr <= 0x1f)) - return; + return; piix_log("PIIX function %i write: %02X to %02X\n", func, val, addr); fregs = (uint8_t *) dev->regs[func]; - if (func == 0) switch (addr) { - case 0x04: - fregs[0x04] = (val & 0x08) | 0x07; - break; - case 0x05: - if (dev->type > 1) - fregs[0x05] = (val & 0x01); - break; - case 0x07: - if ((val & 0x40) && (dev->type > 1)) - fregs[0x07] &= 0xbf; - if (val & 0x20) - fregs[0x07] &= 0xdf; - if (val & 0x10) - fregs[0x07] &= 0xef; - if (val & 0x08) - fregs[0x07] &= 0xf7; - if (val & 0x04) - fregs[0x07] &= 0xfb; - break; - case 0x4c: - fregs[0x4c] = val; - if (dev->type > 1) - dma_alias_remove(); - else - dma_alias_remove_piix(); - if (!(val & 0x80)) { - if (dev->type > 1) - dma_alias_set(); - else - dma_alias_set_piix(); - } - break; - case 0x4e: - fregs[0x4e] = val; - keyboard_at_set_mouse_scan((val & 0x10) ? 1 : 0); - if (dev->type >= 4) - kbc_alias_update_io_mapping(dev); - break; - case 0x4f: - if (dev->type > 3) - fregs[0x4f] = val & 0x07; - else if (dev->type == 3) - fregs[0x4f] = val & 0x01; - break; - case 0x60: case 0x61: case 0x62: case 0x63: - piix_log("Set IRQ routing: INT %c -> %02X\n", 0x41 + (addr & 0x03), val); - fregs[addr] = val & 0x8f; - if (val & 0x80) - pci_set_irq_routing(PCI_INTA + (addr & 0x03), PCI_IRQ_DISABLED); - else - pci_set_irq_routing(PCI_INTA + (addr & 0x03), val & 0xf); - break; - case 0x64: - if (dev->type > 3) - fregs[0x64] = val; - break; - case 0x65: - if (dev->type > 4) - fregs[0x65] = val; - break; - case 0x66: - if (dev->type > 4) - fregs[0x66] = val & 0x81; - break; - case 0x69: - if (dev->type > 1) - fregs[0x69] = val & 0xfe; - else - fregs[0x69] = val & 0xfa; - break; - case 0x6a: - switch (dev->type) { - case 1: - default: - fregs[0x6a] = (fregs[0x6a] & 0xfb) | (val & 0x04); - fregs[0x0e] = (val & 0x04) ? 0x80 : 0x00; - piix_log("PIIX: Write %02X\n", val); - dev->max_func = 0 + !!(val & 0x04); - break; - case 3: - fregs[0x6a] = val & 0xd1; - piix_log("PIIX3: Write %02X\n", val); - dev->max_func = 1 + !!(val & 0x10); - break; - case 4: - fregs[0x6a] = val & 0x80; - break; - case 5: - /* This case is needed so it doesn't behave the PIIX way on the SMSC. */ - break; - } - break; - case 0x6b: - if ((dev->type > 1) && (dev->type <= 4) && (val & 0x80)) - fregs[0x6b] &= 0x7f; - return; - case 0x70: case 0x71: - if ((dev->type > 1) && (addr == 0x71)) - break; - if (dev->type < 4) { - piix_log("Set MIRQ routing: MIRQ%i -> %02X\n", addr & 0x01, val); - if (dev->type > 1) - fregs[addr] = val & 0xef; - else - fregs[addr] = val & 0xcf; - if (val & 0x80) - pci_set_mirq_routing(PCI_MIRQ0 + (addr & 0x01), PCI_IRQ_DISABLED); - else - pci_set_mirq_routing(PCI_MIRQ0 + (addr & 0x01), val & 0xf); - piix_log("MIRQ%i is %s\n", addr & 0x01, (val & 0x20) ? "disabled" : "enabled"); - } - break; - case 0x76: case 0x77: - if (dev->type > 1) - fregs[addr] = val & 0x87; - else if (dev->type <= 4) - fregs[addr] = val & 0x8f; - break; - case 0x78: case 0x79: - if (dev->type < 4) - fregs[addr] = val; - break; - case 0x80: - if (dev->type > 1) - fregs[addr] = val & 0x7f; - break; - case 0x81: - if (dev->type > 1) - fregs[addr] = val & 0x0f; - break; - case 0x82: - if (dev->type > 3) - fregs[addr] = val & 0x0f; - break; - case 0x90: - if (dev->type > 3) - fregs[addr] = val; - break; - case 0x91: - if (dev->type > 3) - fregs[addr] = val & 0xfc; - break; - case 0x92: case 0x93: case 0x94: case 0x95: - if (dev->type > 3) { - if (addr & 0x01) - fregs[addr] = val & 0xff; - else - fregs[addr] = val & 0xc0; + if (func == 0) + switch (addr) { + case 0x04: + fregs[0x04] = (val & 0x08) | 0x07; + break; + case 0x05: + if (dev->type > 1) + fregs[0x05] = (val & 0x01); + break; + case 0x07: + if ((val & 0x40) && (dev->type > 1)) + fregs[0x07] &= 0xbf; + if (val & 0x20) + fregs[0x07] &= 0xdf; + if (val & 0x10) + fregs[0x07] &= 0xef; + if (val & 0x08) + fregs[0x07] &= 0xf7; + if (val & 0x04) + fregs[0x07] &= 0xfb; + break; + case 0x4c: + fregs[0x4c] = val; + if (dev->type > 1) + dma_alias_remove(); + else + dma_alias_remove_piix(); + if (!(val & 0x80)) { + if (dev->type > 1) + dma_alias_set(); + else + dma_alias_set_piix(); + } + break; + case 0x4e: + fregs[0x4e] = val; + if (dev->type >= 4) + kbc_alias_update_io_mapping(dev); + break; + case 0x4f: + if (dev->type > 3) + fregs[0x4f] = val & 0x07; + else if (dev->type == 3) + fregs[0x4f] = val & 0x01; + break; + case 0x60: + case 0x61: + case 0x62: + case 0x63: + piix_log("Set IRQ routing: INT %c -> %02X\n", 0x41 + (addr & 0x03), val); + fregs[addr] = val & 0x8f; + if (val & 0x80) + pci_set_irq_routing(PCI_INTA + (addr & 0x03), PCI_IRQ_DISABLED); + else + pci_set_irq_routing(PCI_INTA + (addr & 0x03), val & 0xf); + break; + case 0x64: + if (dev->type > 3) + fregs[0x64] = val; + break; + case 0x65: + if (dev->type > 4) + fregs[0x65] = val; + break; + case 0x66: + if (dev->type > 4) + fregs[0x66] = val & 0x81; + break; + case 0x69: + if (dev->type > 1) + fregs[0x69] = val & 0xfe; + else + fregs[0x69] = val & 0xfa; + break; + case 0x6a: + switch (dev->type) { + default: + case 1: + fregs[0x6a] = (fregs[0x6a] & 0xfb) | (val & 0x04); + fregs[0x0e] = (val & 0x04) ? 0x80 : 0x00; + piix_log("PIIX: Write %02X\n", val); + dev->max_func = 0 + !!(val & 0x04); + break; + case 3: + fregs[0x6a] = val & 0xd1; + piix_log("PIIX3: Write %02X\n", val); + dev->max_func = 1 + !!(val & 0x10); + break; + case 4: + fregs[0x6a] = val & 0x80; + break; + case 5: + /* This case is needed so it doesn't behave the PIIX way on the SMSC. */ + break; + } + break; + case 0x6b: + if ((dev->type > 1) && (dev->type <= 4) && (val & 0x80)) + fregs[0x6b] &= 0x7f; + return; + case 0x70: + case 0x71: + if ((dev->type > 1) && (addr == 0x71)) + break; + if (dev->type < 4) { + piix_log("Set MIRQ routing: MIRQ%i -> %02X\n", addr & 0x01, val); + if (dev->type > 1) + fregs[addr] = val & 0xef; + else + fregs[addr] = val & 0xcf; + if (val & 0x80) + pci_set_mirq_routing(PCI_MIRQ0 + (addr & 0x01), PCI_IRQ_DISABLED); + else + pci_set_mirq_routing(PCI_MIRQ0 + (addr & 0x01), val & 0xf); + piix_log("MIRQ%i is %s\n", addr & 0x01, (val & 0x20) ? "disabled" : "enabled"); + } + break; + case 0x76: + case 0x77: + if (dev->type > 1) + fregs[addr] = val & 0x87; + else if (dev->type <= 4) + fregs[addr] = val & 0x8f; + break; + case 0x78: + case 0x79: + if (dev->type < 4) + fregs[addr] = val; + break; + case 0x80: + if (dev->type > 1) + fregs[addr] = val & 0x7f; + break; + case 0x81: + if (dev->type > 1) + fregs[addr] = val & 0x0f; + break; + case 0x82: + if (dev->type > 3) + fregs[addr] = val & 0x0f; + break; + case 0x90: + if (dev->type > 3) + fregs[addr] = val; + break; + case 0x91: + if (dev->type > 3) + fregs[addr] = val & 0xfc; + break; + case 0x92: + case 0x93: + case 0x94: + case 0x95: + if (dev->type > 3) { + if (addr & 0x01) + fregs[addr] = val & 0xff; + else + fregs[addr] = val & 0xc0; - base = fregs[addr | 0x01] << 8; - base |= fregs[addr & 0xfe]; + base = fregs[addr | 0x01] << 8; + base |= fregs[addr & 0xfe]; - for (i = 0; i < 4; i++) - ddma_update_io_mapping(dev->ddma, (addr & 4) + i, fregs[addr & 0xfe] + (i << 4), fregs[addr | 0x01], (base != 0x0000)); - } - break; - case 0xa0: - if (dev->type < 4) { - fregs[addr] = val & 0x1f; - apm_set_do_smi(dev->apm, !!(val & 0x01) && !!(fregs[0xa2] & 0x80)); - switch ((val & 0x18) >> 3) { - case 0x00: - dev->fast_off_period = PCICLK * 32768.0 * 60000.0; - break; - case 0x01: - default: - dev->fast_off_period = 0.0; - break; - case 0x02: - dev->fast_off_period = PCICLK; - break; - case 0x03: - dev->fast_off_period = PCICLK * 32768.0; - break; - } - cpu_fast_off_count = fregs[0xa8] + 1; - timer_disable(&dev->fast_off_timer); - if (dev->fast_off_period != 0.0) - timer_on_auto(&dev->fast_off_timer, dev->fast_off_period); - } - break; - case 0xa2: - if (dev->type < 4) { - fregs[addr] = val & 0xff; - apm_set_do_smi(dev->apm, !!(fregs[0xa0] & 0x01) && !!(val & 0x80)); - } - break; - case 0xac: case 0xae: - if (dev->type < 4) - fregs[addr] = val & 0xff; - break; - case 0xa3: - if (dev->type == 3) - fregs[addr] = val & 0x01; - break; - case 0xa4: - if (dev->type < 4) { - fregs[addr] = val & 0xfb; - cpu_fast_off_flags = (cpu_fast_off_flags & 0xffffff00) | fregs[addr]; - } - break; - case 0xa5: - if (dev->type < 4) { - fregs[addr] = val & 0xff; - cpu_fast_off_flags = (cpu_fast_off_flags & 0xffff00ff) | (fregs[addr] << 8); - } - break; - case 0xa6: - if (dev->type < 4) { - fregs[addr] = val & 0xff; - cpu_fast_off_flags = (cpu_fast_off_flags & 0xff00ffff) | (fregs[addr] << 16); - } - break; - case 0xa7: - if (dev->type == 3) - fregs[addr] = val & 0xef; - else if (dev->type < 3) - fregs[addr] = val; - if (dev->type < 4) - cpu_fast_off_flags = (cpu_fast_off_flags & 0x00ffffff) | (fregs[addr] << 24); - break; - case 0xa8: - if (dev->type < 3) { - fregs[addr] = val & 0xff; - cpu_fast_off_val = val; - cpu_fast_off_count = val + 1; - timer_disable(&dev->fast_off_timer); - if (dev->fast_off_period != 0.0) - timer_on_auto(&dev->fast_off_timer, dev->fast_off_period); - } - break; - case 0xaa: - if (dev->type < 4) - fregs[addr] &= val; - break; - case 0xab: - if (dev->type == 3) - fregs[addr] &= (val & 0x01); - else if (dev->type < 3) - fregs[addr] = val; - break; - case 0xb0: - if (dev->type == 4) - fregs[addr] = (fregs[addr] & 0x8c) | (val & 0x73); - else if (dev->type == 5) - fregs[addr] = val & 0x7f; + for (uint8_t i = 0; i < 4; i++) + ddma_update_io_mapping(dev->ddma, (addr & 4) + i, fregs[addr & 0xfe] + (i << 4), fregs[addr | 0x01], (base != 0x0000)); + } + break; + case 0xa0: + if (dev->type < 4) { + fregs[addr] = val & 0x1f; + apm_set_do_smi(dev->apm, !!(val & 0x01) && !!(fregs[0xa2] & 0x80)); + switch ((val & 0x18) >> 3) { + case 0x00: + dev->fast_off_period = PCICLK * 32768.0 * 60000.0; + break; + case 0x01: + default: + dev->fast_off_period = 0.0; + break; + case 0x02: + dev->fast_off_period = PCICLK; + break; + case 0x03: + dev->fast_off_period = PCICLK * 32768.0; + break; + } + cpu_fast_off_count = cpu_fast_off_val + 1; + cpu_fast_off_period_set(cpu_fast_off_val, dev->fast_off_period); + } + break; + case 0xa2: + if (dev->type < 4) { + fregs[addr] = val & 0xff; + apm_set_do_smi(dev->apm, !!(fregs[0xa0] & 0x01) && !!(val & 0x80)); + } + break; + case 0xac: + case 0xae: + if (dev->type < 4) + fregs[addr] = val & 0xff; + break; + case 0xa3: + if (dev->type == 3) + fregs[addr] = val & 0x01; + break; + case 0xa4: + if (dev->type < 4) { + fregs[addr] = val & 0xfb; + cpu_fast_off_flags = (cpu_fast_off_flags & 0xffffff00) | fregs[addr]; + } + break; + case 0xa5: + if (dev->type < 4) { + fregs[addr] = val & 0xff; + cpu_fast_off_flags = (cpu_fast_off_flags & 0xffff00ff) | (fregs[addr] << 8); + } + break; + case 0xa6: + if (dev->type < 4) { + fregs[addr] = val & 0xff; + cpu_fast_off_flags = (cpu_fast_off_flags & 0xff00ffff) | (fregs[addr] << 16); + } + break; + case 0xa7: + if (dev->type == 3) + fregs[addr] = val & 0xef; + else if (dev->type < 3) + fregs[addr] = val; + if (dev->type < 4) + cpu_fast_off_flags = (cpu_fast_off_flags & 0x00ffffff) | (fregs[addr] << 24); + break; + case 0xa8: + if (dev->type < 3) { + fregs[addr] = val & 0xff; + cpu_fast_off_val = val; + cpu_fast_off_count = val + 1; + cpu_fast_off_period_set(cpu_fast_off_val, dev->fast_off_period); + } + break; + case 0xaa: + if (dev->type < 4) + fregs[addr] &= val; + break; + case 0xab: + if (dev->type == 3) + fregs[addr] &= (val & 0x01); + else if (dev->type < 3) + fregs[addr] = val; + break; + case 0xb0: + if (dev->type == 4) + fregs[addr] = (fregs[addr] & 0x8c) | (val & 0x73); + else if (dev->type == 5) + fregs[addr] = val & 0x7f; - if (dev->type >= 4) - alt_access = !!(val & 0x20); - break; - case 0xb1: - if (dev->type > 3) - fregs[addr] = val & 0xdf; - break; - case 0xb2: - if (dev->type > 3) - fregs[addr] = val; - break; - case 0xb3: - if (dev->type > 3) - fregs[addr] = val & 0xfb; - break; - case 0xcb: - if (dev->type > 3) { - fregs[addr] = val & 0x3d; + if (dev->type >= 4) + alt_access = !!(val & 0x20); + break; + case 0xb1: + if (dev->type > 3) + fregs[addr] = val & 0xdf; + break; + case 0xb2: + if (dev->type > 3) + fregs[addr] = val; + break; + case 0xb3: + if (dev->type > 3) + fregs[addr] = val & 0xfb; + break; + case 0xcb: + if (dev->type > 3) { + fregs[addr] = val & 0x3d; - nvr_update_io_mapping(dev); + nvr_update_io_mapping(dev); - nvr_wp_set(!!(val & 0x08), 0, dev->nvr); - nvr_wp_set(!!(val & 0x10), 1, dev->nvr); - } - break; - case 0xd4: - if ((dev->type > 4) && !(fregs[addr] & 0x01)) { - fregs[addr] = val & 0xf1; - nvr_update_io_mapping(dev); - } - break; - case 0xd5: - if ((dev->type > 4) && !(fregs[0xd4] & 0x01)) { - fregs[addr] = val & 0xff; - nvr_update_io_mapping(dev); - } - break; - case 0xe0: - if (dev->type > 4) - fregs[addr] = val & 0xe7; - break; - case 0xe1: case 0xe4: case 0xe5: case 0xe6: case 0xe7: - case 0xe8: case 0xe9: case 0xea: case 0xeb: - if (dev->type > 4) { - fregs[addr] = val; - if ((dev->type == 5) && (addr == 0xe1)) { - smsc_ide_irqs(dev); - port_92_set_features(dev->port_92, !!(val & 0x40), !!(val & 0x40)); - } - } - break; - } else if (func == 1) switch(addr) { /* IDE */ - case 0x04: - fregs[0x04] = (val & 5); - if (dev->type <= 3) - fregs[0x04] |= 0x02; - piix_ide_handlers(dev, 0x03); - piix_ide_bm_handlers(dev); - break; - case 0x07: - fregs[0x07] &= ~(val & 0x38); - break; - case 0x09: - if (dev->type == 5) { - fregs[0x09] = (fregs[0x09] & 0xfa) | (val & 0x05); - piix_ide_handlers(dev, 0x03); - smsc_ide_irqs(dev); - } - break; - case 0x0d: - fregs[0x0d] = val & 0xf0; - break; - case 0x10: - if (dev->type == 5) { - fregs[0x10] = (val & 0xf8) | 1; - piix_ide_handlers(dev, 0x01); - } - break; - case 0x11: - if (dev->type == 5) { - fregs[0x11] = val; - piix_ide_handlers(dev, 0x01); - } - break; - case 0x14: - if (dev->type == 5) { - fregs[0x14] = (val & 0xfc) | 1; - piix_ide_handlers(dev, 0x01); - } - break; - case 0x15: - if (dev->type == 5) { - fregs[0x15] = val; - piix_ide_handlers(dev, 0x01); - } - break; - case 0x18: - if (dev->type == 5) { - fregs[0x18] = (val & 0xf8) | 1; - piix_ide_handlers(dev, 0x02); - } - break; - case 0x19: - if (dev->type == 5) { - fregs[0x19] = val; - piix_ide_handlers(dev, 0x02); - } - break; - case 0x1c: - if (dev->type == 5) { - fregs[0x1c] = (val & 0xfc) | 1; - piix_ide_handlers(dev, 0x02); - } - break; - case 0x1d: - if (dev->type == 5) { - fregs[0x1d] = val; - piix_ide_handlers(dev, 0x02); - } - break; - case 0x20: - fregs[0x20] = (val & 0xf0) | 1; - piix_ide_bm_handlers(dev); - break; - case 0x21: - fregs[0x21] = val; - piix_ide_bm_handlers(dev); - break; - case 0x3c: - if (dev->type == 5) - fregs[0x3c] = val; - break; - case 0x3d: - if (dev->type == 5) - fregs[0x3d] = val; - break; - case 0x40: case 0x42: - fregs[addr] = val; - break; - case 0x41: case 0x43: - fregs[addr] = val & ((dev->type > 1) ? 0xf3 : 0xb3); - piix_ide_handlers(dev, 1 << !!(addr & 0x02)); - break; - case 0x44: - if (dev->type > 1) - fregs[0x44] = val; - break; - case 0x45: - if (dev->type > 4) - fregs[0x45] = val; - break; - case 0x46: - if (dev->type > 4) - fregs[0x46] = val & 0x03; - break; - case 0x48: - if (dev->type > 3) - fregs[0x48] = val & 0x0f; - break; - case 0x4a: case 0x4b: - if (dev->type > 3) - fregs[addr] = val & 0x33; - break; - case 0x5c: case 0x5d: - if (dev->type > 4) - fregs[addr] = val; - break; - default: - break; - } else if (func == 2) switch(addr) { /* USB */ - case 0x04: - if (dev->type > 4) { - fregs[0x04] = (val & 7); - ohci_update_mem_mapping(dev->usb, fregs[0x11], fregs[0x12], fregs[0x13], fregs[PCI_REG_COMMAND] & PCI_COMMAND_MEM); - } else { - fregs[0x04] = (val & 5); - uhci_update_io_mapping(dev->usb, fregs[0x20] & ~0x1f, fregs[0x21], fregs[PCI_REG_COMMAND] & PCI_COMMAND_IO); - } - break; - case 0x07: - if (dev->type > 4) { - if (val & 0x80) - fregs[0x07] &= 0x7f; - if (val & 0x40) - fregs[0x07] &= 0xbf; - } - if (val & 0x20) - fregs[0x07] &= 0xdf; - if (val & 0x10) - fregs[0x07] &= 0xef; - if (val & 0x08) - fregs[0x07] &= 0xf7; - break; - case 0x0c: - if (dev->type > 4) - fregs[0x0c] = val; - break; - case 0x0d: - if (dev->type < 5) - fregs[0x0d] = val & 0xf0; - break; - case 0x11: - if (dev->type > 4) { - fregs[addr] = val & 0xf0; - ohci_update_mem_mapping(dev->usb, fregs[0x11], fregs[0x12], fregs[0x13], 1 /*fregs[PCI_REG_COMMAND] & PCI_COMMAND_MEM*/); - } - break; - case 0x12: case 0x13: - if (dev->type > 4) { - fregs[addr] = val; - ohci_update_mem_mapping(dev->usb, fregs[0x11], fregs[0x12], fregs[0x13], 1 /*fregs[PCI_REG_COMMAND] & PCI_COMMAND_MEM*/); - } - break; - case 0x20: - if (dev->type < 5) { - fregs[0x20] = (val & 0xe0) | 1; - uhci_update_io_mapping(dev->usb, fregs[0x20] & ~0x1f, fregs[0x21], fregs[PCI_REG_COMMAND] & PCI_COMMAND_IO); - } - break; - case 0x21: - if (dev->type < 5) { - fregs[0x21] = val; - uhci_update_io_mapping(dev->usb, fregs[0x20] & ~0x1f, fregs[0x21], fregs[PCI_REG_COMMAND] & PCI_COMMAND_IO); - } - break; - case 0x3c: - fregs[0x3c] = val; - break; - case 0x3e: case 0x3f: - case 0x40: case 0x41: case 0x43: - if (dev->type > 4) - fregs[addr] = val; - break; - case 0x42: - if (dev->type > 4) - fregs[addr] = val & 0x8f; - break; - case 0x44: case 0x45: - if (dev->type > 4) - fregs[addr] = val & 0x01; - break; - case 0x6a: - if (dev->type <= 4) - fregs[0x6a] = val & 0x01; - break; - case 0xc0: - if (dev->type <= 4) - fregs[0xc0] = (fregs[0xc0] & ~(val & 0xbf)) | (val & 0x20); - break; - case 0xc1: - if (dev->type <= 4) - fregs[0xc1] &= ~val; - break; - case 0xff: - if (dev->type == 4) { - fregs[addr] = val & 0x10; - nvr_read_addr_set(!!(val & 0x10), dev->nvr); - } - break; - } else if (func == 3) switch(addr) { /* Power Management */ - case 0x04: - fregs[0x04] = (val & 0x01); - smbus_update_io_mapping(dev); - apm_set_do_smi(dev->acpi->apm, !!(fregs[0x5b] & 0x02) && !!(val & 0x01)); - break; - case 0x07: - if (val & 0x08) - fregs[0x07] &= 0xf7; - break; + nvr_wp_set(!!(val & 0x08), 0, dev->nvr); + nvr_wp_set(!!(val & 0x10), 1, dev->nvr); + } + break; + case 0xd4: + if ((dev->type > 4) && !(fregs[addr] & 0x01)) { + fregs[addr] = val & 0xf1; + nvr_update_io_mapping(dev); + } + break; + case 0xd5: + if ((dev->type > 4) && !(fregs[0xd4] & 0x01)) { + fregs[addr] = val & 0xff; + nvr_update_io_mapping(dev); + } + break; + case 0xe0: + if (dev->type > 4) + fregs[addr] = val & 0xe7; + break; + case 0xe1: + case 0xe4: + case 0xe5: + case 0xe6: + case 0xe7: + case 0xe8: + case 0xe9: + case 0xea: + case 0xeb: + if (dev->type > 4) { + fregs[addr] = val; + if ((dev->type == 5) && (addr == 0xe1)) { + smsc_ide_irqs(dev); + port_92_set_features(dev->port_92, !!(val & 0x40), !!(val & 0x40)); + } + } + break; + default: + break; + } + else if (func == 1) + switch (addr) { /* IDE */ + case 0x04: + fregs[0x04] = (val & 5); + if (dev->type <= 3) + fregs[0x04] |= 0x02; + piix_ide_handlers(dev, 0x03); + piix_ide_bm_handlers(dev); + break; + case 0x07: + fregs[0x07] &= ~(val & 0x38); + break; + case 0x09: + if (dev->type == 5) { + fregs[0x09] = (fregs[0x09] & 0xfa) | (val & 0x05); + piix_ide_handlers(dev, 0x03); + smsc_ide_irqs(dev); + } + break; + case 0x0d: + fregs[0x0d] = val & 0xf0; + break; + case 0x10: + if (dev->type == 5) { + fregs[0x10] = (val & 0xf8) | 1; + piix_ide_handlers(dev, 0x01); + } + break; + case 0x11: + if (dev->type == 5) { + fregs[0x11] = val; + piix_ide_handlers(dev, 0x01); + } + break; + case 0x14: + if (dev->type == 5) { + fregs[0x14] = (val & 0xfc) | 1; + piix_ide_handlers(dev, 0x01); + } + break; + case 0x15: + if (dev->type == 5) { + fregs[0x15] = val; + piix_ide_handlers(dev, 0x01); + } + break; + case 0x18: + if (dev->type == 5) { + fregs[0x18] = (val & 0xf8) | 1; + piix_ide_handlers(dev, 0x02); + } + break; + case 0x19: + if (dev->type == 5) { + fregs[0x19] = val; + piix_ide_handlers(dev, 0x02); + } + break; + case 0x1c: + if (dev->type == 5) { + fregs[0x1c] = (val & 0xfc) | 1; + piix_ide_handlers(dev, 0x02); + } + break; + case 0x1d: + if (dev->type == 5) { + fregs[0x1d] = val; + piix_ide_handlers(dev, 0x02); + } + break; + case 0x20: + fregs[0x20] = (val & 0xf0) | 1; + piix_ide_bm_handlers(dev); + break; + case 0x21: + fregs[0x21] = val; + piix_ide_bm_handlers(dev); + break; + case 0x3c: + if (dev->type == 5) + fregs[0x3c] = val; + break; + case 0x3d: + if (dev->type == 5) + fregs[0x3d] = val; + break; + case 0x40: + case 0x42: + fregs[addr] = val; + break; + case 0x41: + case 0x43: + fregs[addr] = val & ((dev->type > 1) ? 0xf3 : 0xb3); + piix_ide_handlers(dev, 1 << !!(addr & 0x02)); + break; + case 0x44: + if (dev->type > 1) + fregs[0x44] = val; + break; + case 0x45: + if (dev->type > 4) + fregs[0x45] = val; + break; + case 0x46: + if (dev->type > 4) + fregs[0x46] = val & 0x03; + break; + case 0x48: + if (dev->type > 3) + fregs[0x48] = val & 0x0f; + break; + case 0x4a: + case 0x4b: + if (dev->type > 3) + fregs[addr] = val & 0x33; + break; + case 0x5c: + case 0x5d: + if (dev->type > 4) + fregs[addr] = val; + break; + default: + break; + } + else if (func == 2) + switch (addr) { /* USB */ + case 0x04: + if (dev->type > 4) { + fregs[0x04] = (val & 7); + ohci_update_mem_mapping(dev->usb, fregs[0x11], fregs[0x12], fregs[0x13], fregs[PCI_REG_COMMAND] & PCI_COMMAND_MEM); + } else { + fregs[0x04] = (val & 5); + uhci_update_io_mapping(dev->usb, fregs[0x20] & ~0x1f, fregs[0x21], fregs[PCI_REG_COMMAND] & PCI_COMMAND_IO); + } + break; + case 0x07: + if (dev->type > 4) { + if (val & 0x80) + fregs[0x07] &= 0x7f; + if (val & 0x40) + fregs[0x07] &= 0xbf; + } + if (val & 0x20) + fregs[0x07] &= 0xdf; + if (val & 0x10) + fregs[0x07] &= 0xef; + if (val & 0x08) + fregs[0x07] &= 0xf7; + break; + case 0x0c: + if (dev->type > 4) + fregs[0x0c] = val; + break; + case 0x0d: + if (dev->type < 5) + fregs[0x0d] = val & 0xf0; + break; + case 0x11: + if (dev->type > 4) { + fregs[addr] = val & 0xf0; + ohci_update_mem_mapping(dev->usb, fregs[0x11], fregs[0x12], fregs[0x13], 1 /*fregs[PCI_REG_COMMAND] & PCI_COMMAND_MEM*/); + } + break; + case 0x12: + case 0x13: + if (dev->type > 4) { + fregs[addr] = val; + ohci_update_mem_mapping(dev->usb, fregs[0x11], fregs[0x12], fregs[0x13], 1 /*fregs[PCI_REG_COMMAND] & PCI_COMMAND_MEM*/); + } + break; + case 0x20: + if (dev->type < 5) { + fregs[0x20] = (val & 0xe0) | 1; + uhci_update_io_mapping(dev->usb, fregs[0x20] & ~0x1f, fregs[0x21], fregs[PCI_REG_COMMAND] & PCI_COMMAND_IO); + } + break; + case 0x21: + if (dev->type < 5) { + fregs[0x21] = val; + uhci_update_io_mapping(dev->usb, fregs[0x20] & ~0x1f, fregs[0x21], fregs[PCI_REG_COMMAND] & PCI_COMMAND_IO); + } + break; + case 0x3c: + fregs[0x3c] = val; + break; + case 0x3e: + case 0x3f: + case 0x40: + case 0x41: + case 0x43: + if (dev->type > 4) + fregs[addr] = val; + break; + case 0x42: + if (dev->type > 4) + fregs[addr] = val & 0x8f; + break; + case 0x44: + case 0x45: + if (dev->type > 4) + fregs[addr] = val & 0x01; + break; + case 0x6a: + if (dev->type <= 4) + fregs[0x6a] = val & 0x01; + break; + case 0xc0: + if (dev->type <= 4) + fregs[0xc0] = (fregs[0xc0] & ~(val & 0xbf)) | (val & 0x20); + break; + case 0xc1: + if (dev->type <= 4) + fregs[0xc1] &= ~val; + break; + case 0xff: + if (dev->type == 4) { + fregs[addr] = val & 0x10; + nvr_read_addr_set(!!(val & 0x10), dev->nvr); + } + break; + default: + break; + } + else if (func == 3) + switch (addr) { /* Power Management */ + case 0x04: + fregs[0x04] = (val & 0x01); + smbus_update_io_mapping(dev); + apm_set_do_smi(dev->acpi->apm, !!(fregs[0x5b] & 0x02) && !!(val & 0x01)); + break; + case 0x07: + if (val & 0x08) + fregs[0x07] &= 0xf7; + break; #if 0 - case 0x3c: - fregs[0x3c] = val; - break; + case 0x3c: + fregs[0x3c] = val; + break; #endif - case 0x40: - fregs[0x40] = (val & 0xc0) | 1; - dev->acpi_io_base = (dev->regs[3][0x41] << 8) | (dev->regs[3][0x40] & 0xc0); - acpi_update_io_mapping(dev->acpi, dev->acpi_io_base, (dev->regs[3][0x80] & 0x01)); - break; - case 0x41: - fregs[0x41] = val; - dev->acpi_io_base = (dev->regs[3][0x41] << 8) | (dev->regs[3][0x40] & 0xc0); - acpi_update_io_mapping(dev->acpi, dev->acpi_io_base, (dev->regs[3][0x80] & 0x01)); - break; - case 0x44: case 0x45: case 0x46: case 0x47: - case 0x48: case 0x49: - case 0x4c: case 0x4d: case 0x4e: - case 0x54: case 0x55: case 0x56: case 0x57: - case 0x59: case 0x5a: - case 0x5c: case 0x5d: case 0x5e: case 0x5f: - case 0x60: case 0x61: case 0x62: - case 0x64: case 0x65: - case 0x67: case 0x68: case 0x69: - case 0x6c: case 0x6e: case 0x6f: - case 0x70: case 0x71: - case 0x74: case 0x77: case 0x78: case 0x79: - case 0x7c: case 0x7d: - case 0xd3: case 0xd4: - case 0xd5: - fregs[addr] = val; - if ((addr == 0x5c) || (addr == 0x60) || (addr == 0x61) || (addr == 0x62) || - (addr == 0x64) || (addr == 0x65) || (addr == 0x68) || (addr == 0x69) || - (addr == 0x70) || (addr == 0x71)) - piix_trap_update(dev); - break; - case 0x4a: - fregs[addr] = val & 0x73; - break; - case 0x4b: - fregs[addr] = val & 0x01; - break; - case 0x4f: case 0x80: case 0xd2: - fregs[addr] = val & 0x0f; - if (addr == 0x80) - acpi_update_io_mapping(dev->acpi, dev->acpi_io_base, (dev->regs[3][0x80] & 0x01)); - else if (addr == 0xd2) - smbus_update_io_mapping(dev); - break; - case 0x50: - fregs[addr] = val & 0x3f; - break; - case 0x51: - fregs[addr] = val & 0x58; - piix_trap_update(dev); - break; - case 0x52: - fregs[addr] = val & 0x7f; - piix_trap_update(dev); - break; - case 0x58: - fregs[addr] = val & 0x77; - break; - case 0x5b: - fregs[addr] = val & 0x03; - apm_set_do_smi(dev->acpi->apm, !!(val & 0x02) && !!(fregs[0x04] & 0x01)); - break; - case 0x63: - fregs[addr] = val & 0xf7; - piix_trap_update(dev); - break; - case 0x66: - fregs[addr] = val & 0xef; - piix_trap_update(dev); - break; - case 0x6a: case 0x72: case 0x7a: case 0x7e: - fregs[addr] = val & 0x1f; - if ((addr == 0x6a) || (addr == 0x72)) - piix_trap_update(dev); - break; - case 0x6d: case 0x75: - fregs[addr] = val & 0x80; - break; - case 0x90: - fregs[0x90] = (val & 0xf0) | 1; - smbus_update_io_mapping(dev); - break; - case 0x91: - fregs[0x91] = val; - smbus_update_io_mapping(dev); - break; - } + case 0x40: + fregs[0x40] = (val & 0xc0) | 1; + dev->acpi_io_base = (dev->regs[3][0x41] << 8) | (dev->regs[3][0x40] & 0xc0); + acpi_update_io_mapping(dev->acpi, dev->acpi_io_base, (dev->regs[3][0x80] & 0x01)); + break; + case 0x41: + fregs[0x41] = val; + dev->acpi_io_base = (dev->regs[3][0x41] << 8) | (dev->regs[3][0x40] & 0xc0); + acpi_update_io_mapping(dev->acpi, dev->acpi_io_base, (dev->regs[3][0x80] & 0x01)); + break; + case 0x44: + case 0x45: + case 0x46: + case 0x47: + case 0x48: + case 0x49: + case 0x4c: + case 0x4d: + case 0x4e: + case 0x54: + case 0x55: + case 0x56: + case 0x57: + case 0x59: + case 0x5a: + case 0x5c: + case 0x5d: + case 0x5e: + case 0x5f: + case 0x60: + case 0x61: + case 0x62: + case 0x64: + case 0x65: + case 0x67: + case 0x68: + case 0x69: + case 0x6c: + case 0x6e: + case 0x6f: + case 0x70: + case 0x71: + case 0x74: + case 0x77: + case 0x78: + case 0x79: + case 0x7c: + case 0x7d: + case 0xd3: + case 0xd4: + case 0xd5: + fregs[addr] = val; + if ((addr == 0x5c) || (addr == 0x60) || (addr == 0x61) || (addr == 0x62) || (addr == 0x64) || (addr == 0x65) || (addr == 0x68) || (addr == 0x69) || (addr == 0x70) || (addr == 0x71)) + piix_trap_update(dev); + break; + case 0x4a: + fregs[addr] = val & 0x73; + break; + case 0x4b: + fregs[addr] = val & 0x01; + break; + case 0x4f: + case 0x80: + case 0xd2: + fregs[addr] = val & 0x0f; + if (addr == 0x80) + acpi_update_io_mapping(dev->acpi, dev->acpi_io_base, (dev->regs[3][0x80] & 0x01)); + else if (addr == 0xd2) + smbus_update_io_mapping(dev); + break; + case 0x50: + fregs[addr] = val & 0x3f; + break; + case 0x51: + fregs[addr] = val & 0x58; + piix_trap_update(dev); + break; + case 0x52: + fregs[addr] = val & 0x7f; + piix_trap_update(dev); + break; + case 0x58: + fregs[addr] = val & 0x77; + break; + case 0x5b: + fregs[addr] = val & 0x03; + apm_set_do_smi(dev->acpi->apm, !!(val & 0x02) && !!(fregs[0x04] & 0x01)); + break; + case 0x63: + fregs[addr] = val & 0xf7; + piix_trap_update(dev); + break; + case 0x66: + fregs[addr] = val & 0xef; + piix_trap_update(dev); + break; + case 0x6a: + case 0x72: + case 0x7a: + case 0x7e: + fregs[addr] = val & 0x1f; + if ((addr == 0x6a) || (addr == 0x72)) + piix_trap_update(dev); + break; + case 0x6d: + case 0x75: + fregs[addr] = val & 0x80; + break; + case 0x90: + fregs[0x90] = (val & 0xf0) | 1; + smbus_update_io_mapping(dev); + break; + case 0x91: + fregs[0x91] = val; + smbus_update_io_mapping(dev); + break; + default: + break; + } } - static uint8_t piix_read(int func, int addr, void *priv) { - piix_t *dev = (piix_t *) priv; - uint8_t ret = 0xff, *fregs; + piix_t *dev = (piix_t *) priv; + uint8_t ret = 0xff; + const uint8_t *fregs; if ((dev->type == 3) && (func == 2) && (dev->max_func == 1) && (addr >= 0x40)) - ret = 0x00; + ret = 0x00; /* Return on unsupported function. */ if ((func <= dev->max_func) || ((func == 1) && (dev->max_func == 0))) { - fregs = (uint8_t *) dev->regs[func]; - ret = fregs[addr]; - if ((func == 0) && (addr == 0x4e)) - ret |= keyboard_at_get_mouse_scan(); - else if ((func == 2) && (addr == 0xff)) - ret |= 0xef; + fregs = (uint8_t *) dev->regs[func]; + ret = fregs[addr]; - piix_log("PIIX function %i read: %02X from %02X\n", func, ret, addr); + piix_log("PIIX function %i read: %02X from %02X\n", func, ret, addr); } return ret; } - static void board_write(uint16_t port, uint8_t val, void *priv) { piix_t *dev = (piix_t *) priv; - if (port == 0x0078) - dev->board_config[0] = val; - else if (port == 0x00e0) - dev->cur_readout_reg = val; + if (port == 0x00e0) + dev->cur_readout_reg = val; else if (port == 0x00e1) - dev->readout_regs[dev->cur_readout_reg] = val; + dev->readout_regs[dev->cur_readout_reg] = val; } - static uint8_t board_read(uint16_t port, void *priv) { - piix_t *dev = (piix_t *) priv; - uint8_t ret = 0x64; + const piix_t *dev = (piix_t *) priv; + uint8_t ret = 0x64; - if (port == 0x0078) - ret = dev->board_config[0]; - else if (port == 0x0079) - ret = dev->board_config[1]; - else if (port == 0x00e0) - ret = dev->cur_readout_reg; + if (port == 0x00e0) + ret = dev->cur_readout_reg; else if (port == 0x00e1) - ret = dev->readout_regs[dev->cur_readout_reg]; + ret = dev->readout_regs[dev->cur_readout_reg]; return ret; } - static void piix_reset_hard(piix_t *dev) { - int i; uint8_t *fregs; - uint16_t old_base = (dev->regs[1][0x20] & 0xf0) | (dev->regs[1][0x21] << 8); - - sff_bus_master_reset(dev->bm[0], old_base); - sff_bus_master_reset(dev->bm[1], old_base + 8); + sff_bus_master_reset(dev->bm[0]); + sff_bus_master_reset(dev->bm[1]); if (dev->type >= 4) { - sff_set_slot(dev->bm[0], dev->pci_slot); - sff_set_irq_pin(dev->bm[0], PCI_INTA); - sff_set_irq_line(dev->bm[0], 14); - sff_set_irq_mode(dev->bm[0], 0, 0); - sff_set_irq_mode(dev->bm[0], 1, 0); + sff_set_slot(dev->bm[0], dev->pci_slot); + sff_set_irq_pin(dev->bm[0], PCI_INTA); + sff_set_irq_line(dev->bm[0], 14); + sff_set_irq_mode(dev->bm[0], IRQ_MODE_LEGACY); - sff_set_slot(dev->bm[1], dev->pci_slot); - sff_set_irq_pin(dev->bm[1], PCI_INTA); - sff_set_irq_line(dev->bm[1], 14); - sff_set_irq_mode(dev->bm[1], 0, 0); - sff_set_irq_mode(dev->bm[1], 1, 0); + sff_set_slot(dev->bm[1], dev->pci_slot); + sff_set_irq_pin(dev->bm[1], PCI_INTA); + sff_set_irq_line(dev->bm[1], 14); + sff_set_irq_mode(dev->bm[1], IRQ_MODE_LEGACY); } #ifdef ENABLE_PIIX_LOG @@ -1154,70 +1231,74 @@ piix_reset_hard(piix_t *dev) ide_sec_disable(); if (dev->type > 3) { - nvr_at_handler(0, 0x0072, dev->nvr); - nvr_wp_set(0, 0, dev->nvr); - nvr_wp_set(0, 1, dev->nvr); - nvr_at_handler(1, 0x0074, dev->nvr); - dev->nvr_io_base = 0x0070; + nvr_at_handler(0, 0x0072, dev->nvr); + nvr_wp_set(0, 0, dev->nvr); + nvr_wp_set(0, 1, dev->nvr); + nvr_at_handler(1, 0x0074, dev->nvr); + dev->nvr_io_base = 0x0070; } /* Clear all 4 functions' arrays and set their vendor and device ID's. */ - for (i = 0; i < 4; i++) { - memset(dev->regs[i], 0, 256); - if (dev->type == 5) { - dev->regs[i][0x00] = 0x55; dev->regs[i][0x01] = 0x10; /* SMSC/EFAR */ - if (i == 1) { /* IDE controller is 9130, breaking convention */ - dev->regs[i][0x02] = 0x30; - dev->regs[i][0x03] = 0x91; - } else { - dev->regs[i][0x02] = (dev->func0_id & 0xff) + (i << dev->func_shift); - dev->regs[i][0x03] = (dev->func0_id >> 8); - } - } else { - dev->regs[i][0x00] = 0x86; dev->regs[i][0x01] = 0x80; /* Intel */ - dev->regs[i][0x02] = (dev->func0_id & 0xff) + (i << dev->func_shift); - dev->regs[i][0x03] = (dev->func0_id >> 8); - } + for (uint8_t i = 0; i < 4; i++) { + memset(dev->regs[i], 0, 256); + if (dev->type == 5) { + dev->regs[i][0x00] = 0x55; + dev->regs[i][0x01] = 0x10; /* SMSC/EFAR */ + if (i == 1) { /* IDE controller is 9130, breaking convention */ + dev->regs[i][0x02] = 0x30; + dev->regs[i][0x03] = 0x91; + } else { + dev->regs[i][0x02] = (dev->func0_id & 0xff) + (i << dev->func_shift); + dev->regs[i][0x03] = (dev->func0_id >> 8); + } + } else { + dev->regs[i][0x00] = 0x86; + dev->regs[i][0x01] = 0x80; /* Intel */ + dev->regs[i][0x02] = (dev->func0_id & 0xff) + (i << dev->func_shift); + dev->regs[i][0x03] = (dev->func0_id >> 8); + } } /* Function 0: PCI to ISA Bridge */ fregs = (uint8_t *) dev->regs[0]; piix_log("PIIX Function 0: %02X%02X:%02X%02X\n", fregs[0x01], fregs[0x00], fregs[0x03], fregs[0x02]); fregs[0x04] = 0x07; - fregs[0x06] = 0x80; fregs[0x07] = 0x02; + fregs[0x06] = 0x80; + fregs[0x07] = 0x02; if (dev->type == 4) - fregs[0x08] = (dev->rev & 0x08) ? 0x02 : (dev->rev & 0x07); + fregs[0x08] = (dev->rev & 0x08) ? 0x02 : (dev->rev & 0x07); else - fregs[0x08] = dev->rev; + fregs[0x08] = dev->rev; fregs[0x09] = 0x00; - fregs[0x0a] = 0x01; fregs[0x0b] = 0x06; + fregs[0x0a] = 0x01; + fregs[0x0b] = 0x06; fregs[0x0e] = ((dev->type > 1) || (dev->rev != 2)) ? 0x80 : 0x00; fregs[0x4c] = 0x4d; fregs[0x4e] = 0x03; fregs[0x60] = fregs[0x61] = fregs[0x62] = fregs[0x63] = 0x80; - fregs[0x64] = (dev->type > 3) ? 0x10 : 0x00; - fregs[0x69] = 0x02; + fregs[0x64] = (dev->type > 3) ? 0x10 : 0x00; + fregs[0x69] = 0x02; if ((dev->type == 1) && (dev->rev != 2)) - fregs[0x6a] = 0x04; + fregs[0x6a] = 0x04; else if (dev->type == 3) - fregs[0x6a] = 0x10; + fregs[0x6a] = 0x10; fregs[0x70] = (dev->type < 4) ? 0x80 : 0x00; fregs[0x71] = (dev->type < 3) ? 0x80 : 0x00; if (dev->type <= 4) { - fregs[0x76] = fregs[0x77] = (dev->type > 1) ? 0x04 : 0x0c; + fregs[0x76] = fregs[0x77] = (dev->type > 1) ? 0x04 : 0x0c; } fregs[0x78] = (dev->type < 4) ? 0x02 : 0x00; fregs[0xa0] = (dev->type < 4) ? 0x08 : 0x00; fregs[0xa8] = (dev->type < 4) ? 0x0f : 0x00; if (dev->type > 3) - fregs[0xb0] = (is_pentium) ? 0x00 : 0x04; + fregs[0xb0] = is_pentium ? 0x00 : 0x04; fregs[0xcb] = (dev->type > 3) ? 0x21 : 0x00; if (dev->type > 4) { - fregs[0xd4] = 0x70; - fregs[0xe1] = 0x40; - fregs[0xe6] = 0x12; - fregs[0xe8] = 0x02; - fregs[0xea] = 0x12; + fregs[0xd4] = 0x70; + fregs[0xe1] = 0x40; + fregs[0xe6] = 0x12; + fregs[0xe8] = 0x02; + fregs[0xea] = 0x12; } dev->max_func = 0; @@ -1225,78 +1306,90 @@ piix_reset_hard(piix_t *dev) fregs = (uint8_t *) dev->regs[1]; piix_log("PIIX Function 1: %02X%02X:%02X%02X\n", fregs[0x01], fregs[0x00], fregs[0x03], fregs[0x02]); if (dev->type < 4) - fregs[0x04] = 0x02; - fregs[0x06] = 0x80; fregs[0x07] = 0x02; + fregs[0x04] = 0x02; + fregs[0x06] = 0x80; + fregs[0x07] = 0x02; if (dev->type == 4) - fregs[0x08] = dev->rev & 0x07; + fregs[0x08] = dev->rev & 0x07; else - fregs[0x08] = dev->rev; + fregs[0x08] = dev->rev; if (dev->type == 5) - fregs[0x09] = 0x8a; + fregs[0x09] = 0x8a; else - fregs[0x09] = 0x80; - fregs[0x0a] = 0x01; fregs[0x0b] = 0x01; + fregs[0x09] = 0x80; + fregs[0x0a] = 0x01; + fregs[0x0b] = 0x01; if (dev->type == 5) { - fregs[0x10] = 0xf1; fregs[0x11] = 0x01; - fregs[0x14] = 0xf5; fregs[0x15] = 0x03; - fregs[0x18] = 0x71; fregs[0x19] = 0x01; - fregs[0x1c] = 0x75; fregs[0x1d] = 0x03; + fregs[0x10] = 0xf1; + fregs[0x11] = 0x01; + fregs[0x14] = 0xf5; + fregs[0x15] = 0x03; + fregs[0x18] = 0x71; + fregs[0x19] = 0x01; + fregs[0x1c] = 0x75; + fregs[0x1d] = 0x03; } fregs[0x20] = 0x01; if (dev->type == 5) { - fregs[0x3c] = 0x0e; fregs[0x3d] = 0x01; - fregs[0x45] = 0x55; fregs[0x46] = 0x01; + fregs[0x3c] = 0x0e; + fregs[0x3d] = 0x01; + fregs[0x45] = 0x55; + fregs[0x46] = 0x01; } if ((dev->type == 1) && (dev->rev == 2)) - dev->max_func = 0; /* It starts with IDE disabled, then enables it. */ + dev->max_func = 0; /* It starts with IDE disabled, then enables it. */ else - dev->max_func = 1; + dev->max_func = 1; /* Function 2: USB */ if (dev->type > 1) { - fregs = (uint8_t *) dev->regs[2]; - piix_log("PIIX Function 2: %02X%02X:%02X%02X\n", fregs[0x01], fregs[0x00], fregs[0x03], fregs[0x02]); - fregs[0x06] = 0x80; fregs[0x07] = 0x02; - if (dev->type == 4) - fregs[0x08] = dev->rev & 0x07; - else if (dev->type < 4) - fregs[0x08] = 0x01; - else - fregs[0x08] = 0x02; - if (dev->type > 4) - fregs[0x09] = 0x10; /* SMSC has OHCI rather than UHCI */ - fregs[0x0a] = 0x03; fregs[0x0b] = 0x0c; - if (dev->type < 5) - fregs[0x20] = 0x01; - fregs[0x3d] = 0x04; - if (dev->type > 4) - fregs[0x60] = (dev->type > 3) ? 0x10 : 0x00; - if (dev->type < 5) { - fregs[0x6a] = (dev->type == 3) ? 0x01 : 0x00; - fregs[0xc1] = 0x20; - fregs[0xff] = (dev->type > 3) ? 0x10 : 0x00; - } - dev->max_func = 2; /* It starts with USB disabled, then enables it. */ + fregs = (uint8_t *) dev->regs[2]; + piix_log("PIIX Function 2: %02X%02X:%02X%02X\n", fregs[0x01], fregs[0x00], fregs[0x03], fregs[0x02]); + fregs[0x06] = 0x80; + fregs[0x07] = 0x02; + if (dev->type == 4) + fregs[0x08] = dev->rev & 0x07; + else if (dev->type < 4) + fregs[0x08] = 0x01; + else + fregs[0x08] = 0x02; + if (dev->type > 4) + fregs[0x09] = 0x10; /* SMSC has OHCI rather than UHCI */ + fregs[0x0a] = 0x03; + fregs[0x0b] = 0x0c; + if (dev->type < 5) + fregs[0x20] = 0x01; + fregs[0x3d] = 0x04; + if (dev->type > 4) + fregs[0x60] = (dev->type > 3) ? 0x10 : 0x00; + if (dev->type < 5) { + fregs[0x6a] = (dev->type == 3) ? 0x01 : 0x00; + fregs[0xc1] = 0x20; + fregs[0xff] = (dev->type > 3) ? 0x10 : 0x00; + } + dev->max_func = 2; /* It starts with USB disabled, then enables it. */ } /* Function 3: Power Management */ if (dev->type > 3) { - fregs = (uint8_t *) dev->regs[3]; - piix_log("PIIX Function 3: %02X%02X:%02X%02X\n", fregs[0x01], fregs[0x00], fregs[0x03], fregs[0x02]); - fregs[0x06] = 0x80; fregs[0x07] = 0x02; - if (dev->type > 4) - fregs[0x08] = 0x02; - else - fregs[0x08] = (dev->rev & 0x08) ? 0x02 : 0x01 /*(dev->rev & 0x07)*/; - fregs[0x0a] = 0x80; fregs[0x0b] = 0x06; - /* NOTE: The Specification Update says this should default to 0x00 and be read-only. */ + fregs = (uint8_t *) dev->regs[3]; + piix_log("PIIX Function 3: %02X%02X:%02X%02X\n", fregs[0x01], fregs[0x00], fregs[0x03], fregs[0x02]); + fregs[0x06] = 0x80; + fregs[0x07] = 0x02; + if (dev->type > 4) + fregs[0x08] = 0x02; + else + fregs[0x08] = (dev->rev & 0x08) ? 0x02 : 0x01 /*(dev->rev & 0x07)*/; + fregs[0x0a] = 0x80; + fregs[0x0b] = 0x06; + /* NOTE: The Specification Update says this should default to 0x00 and be read-only. */ #ifdef WRONG_SPEC - if (dev->type == 4) - fregs[0x3d] = 0x01; + if (dev->type == 4) + fregs[0x3d] = 0x01; #endif - fregs[0x40] = 0x01; - fregs[0x90] = 0x01; - dev->max_func = 3; + fregs[0x40] = 0x01; + fregs[0x90] = 0x01; + dev->max_func = 3; } pci_set_irq_routing(PCI_INTA, PCI_IRQ_DISABLED); @@ -1305,231 +1398,217 @@ piix_reset_hard(piix_t *dev) pci_set_irq_routing(PCI_INTD, PCI_IRQ_DISABLED); if (dev->type < 4) - pci_set_mirq_routing(PCI_MIRQ0, PCI_IRQ_DISABLED); + pci_set_mirq_routing(PCI_MIRQ0, PCI_IRQ_DISABLED); if (dev->type < 3) - pci_set_mirq_routing(PCI_MIRQ1, PCI_IRQ_DISABLED); + pci_set_mirq_routing(PCI_MIRQ1, PCI_IRQ_DISABLED); if (dev->type >= 4) - acpi_init_gporeg(dev->acpi, 0xff, 0xbf, 0xff, 0x7f); + acpi_init_gporeg(dev->acpi, 0xff, 0xbf, 0xff, 0x7f); } - static void -piix_apm_out(uint16_t port, uint8_t val, void *p) +piix_apm_out(UNUSED(uint16_t port), UNUSED(uint8_t val), void *priv) { - piix_t *dev = (piix_t *) p; + piix_t *dev = (piix_t *) priv; if (dev->apm->do_smi) { - if (dev->type < 4) - dev->regs[0][0xaa] |= 0x80; + if (dev->type < 4) + dev->regs[0][0xaa] |= 0x80; } } - static void piix_fast_off_count(void *priv) { piix_t *dev = (piix_t *) priv; - cpu_fast_off_count--; - - if (cpu_fast_off_count == 0) { - smi_line = 1; - dev->regs[0][0xaa] |= 0x20; - cpu_fast_off_count = dev->regs[0][0xa8] + 1; - } - - timer_on_auto(&dev->fast_off_timer, dev->fast_off_period); + smi_raise(); + dev->regs[0][0xaa] |= 0x20; } - static void -piix_reset(void *p) +piix_reset(void *priv) { - piix_t *dev = (piix_t *)p; + const piix_t *dev = (piix_t *) priv; if (dev->type > 3) { - piix_write(3, 0x04, 0x00, p); - piix_write(3, 0x5b, 0x00, p); + piix_write(3, 0x04, 0x00, priv); + piix_write(3, 0x5b, 0x00, priv); } else { - piix_write(0, 0xa0, 0x08, p); - piix_write(0, 0xa2, 0x00, p); - piix_write(0, 0xa4, 0x00, p); - piix_write(0, 0xa5, 0x00, p); - piix_write(0, 0xa6, 0x00, p); - piix_write(0, 0xa7, 0x00, p); - piix_write(0, 0xa8, 0x0f, p); + piix_write(0, 0xa0, 0x08, priv); + piix_write(0, 0xa2, 0x00, priv); + piix_write(0, 0xa4, 0x00, priv); + piix_write(0, 0xa5, 0x00, priv); + piix_write(0, 0xa6, 0x00, priv); + piix_write(0, 0xa7, 0x00, priv); + piix_write(0, 0xa8, 0x0f, priv); } + /* Disable the PIC mouse latch. */ + piix_write(0, 0x4e, 0x03, priv); + if (dev->type == 5) - piix_write(0, 0xe1, 0x40, p); - piix_write(1, 0x04, 0x00, p); + piix_write(0, 0xe1, 0x40, priv); + piix_write(1, 0x04, 0x00, priv); if (dev->type == 5) { - piix_write(1, 0x09, 0x8a, p); - piix_write(1, 0x10, 0xf1, p); - piix_write(1, 0x11, 0x01, p); - piix_write(1, 0x14, 0xf5, p); - piix_write(1, 0x15, 0x03, p); - piix_write(1, 0x18, 0x71, p); - piix_write(1, 0x19, 0x01, p); - piix_write(1, 0x1c, 0x75, p); - piix_write(1, 0x1d, 0x03, p); + piix_write(1, 0x09, 0x8a, priv); + piix_write(1, 0x10, 0xf1, priv); + piix_write(1, 0x11, 0x01, priv); + piix_write(1, 0x14, 0xf5, priv); + piix_write(1, 0x15, 0x03, priv); + piix_write(1, 0x18, 0x71, priv); + piix_write(1, 0x19, 0x01, priv); + piix_write(1, 0x1c, 0x75, priv); + piix_write(1, 0x1d, 0x03, priv); } else - piix_write(1, 0x09, 0x80, p); - piix_write(1, 0x20, 0x01, p); - piix_write(1, 0x21, 0x00, p); - piix_write(1, 0x41, 0x00, p); - piix_write(1, 0x43, 0x00, p); + piix_write(1, 0x09, 0x80, priv); + piix_write(1, 0x20, 0x01, priv); + piix_write(1, 0x21, 0x00, priv); + piix_write(1, 0x41, 0x00, priv); + piix_write(1, 0x43, 0x00, priv); ide_pri_disable(); ide_sec_disable(); if (dev->type >= 3) { - piix_write(2, 0x04, 0x00, p); - if (dev->type == 5) { - piix_write(2, 0x10, 0x00, p); - piix_write(2, 0x11, 0x00, p); - piix_write(2, 0x12, 0x00, p); - piix_write(2, 0x13, 0x00, p); - } else { - piix_write(2, 0x20, 0x01, p); - piix_write(2, 0x21, 0x00, p); - piix_write(2, 0x22, 0x00, p); - piix_write(2, 0x23, 0x00, p); - } + piix_write(2, 0x04, 0x00, priv); + if (dev->type == 5) { + piix_write(2, 0x10, 0x00, priv); + piix_write(2, 0x11, 0x00, priv); + piix_write(2, 0x12, 0x00, priv); + piix_write(2, 0x13, 0x00, priv); + } else { + piix_write(2, 0x20, 0x01, priv); + piix_write(2, 0x21, 0x00, priv); + piix_write(2, 0x22, 0x00, priv); + piix_write(2, 0x23, 0x00, priv); + } } if (dev->type >= 4) { - piix_write(0, 0xb0, (is_pentium) ? 0x00 : 0x04, p); - piix_write(3, 0x40, 0x01, p); - piix_write(3, 0x41, 0x00, p); - piix_write(3, 0x5b, 0x00, p); - piix_write(3, 0x80, 0x00, p); - piix_write(3, 0x90, 0x01, p); - piix_write(3, 0x91, 0x00, p); - piix_write(3, 0xd2, 0x00, p); + piix_write(0, 0xb0, is_pentium ? 0x00 : 0x04, priv); + piix_write(3, 0x40, 0x01, priv); + piix_write(3, 0x41, 0x00, priv); + piix_write(3, 0x5b, 0x00, priv); + piix_write(3, 0x80, 0x00, priv); + piix_write(3, 0x90, 0x01, priv); + piix_write(3, 0x91, 0x00, priv); + piix_write(3, 0xd2, 0x00, priv); } - sff_set_irq_mode(dev->bm[0], 0, 0); - sff_set_irq_mode(dev->bm[1], 0, 0); + sff_set_irq_mode(dev->bm[0], IRQ_MODE_LEGACY); - if (dev->no_mirq0 || (dev->type >= 4)) { - sff_set_irq_mode(dev->bm[0], 1, 0); - sff_set_irq_mode(dev->bm[1], 1, 0); - } else { - sff_set_irq_mode(dev->bm[0], 1, 2); - sff_set_irq_mode(dev->bm[1], 1, 2); - } + if (dev->no_mirq0 || (dev->type >= 4)) + sff_set_irq_mode(dev->bm[1], IRQ_MODE_LEGACY); + else + sff_set_irq_mode(dev->bm[1], IRQ_MODE_MIRQ_0); } - static void piix_close(void *priv) { piix_t *dev = (piix_t *) priv; for (int i = 0; i < (sizeof(dev->io_traps) / sizeof(dev->io_traps[0])); i++) - io_trap_remove(dev->io_traps[i].trap); + io_trap_remove(dev->io_traps[i].trap); free(dev); } - static void piix_speed_changed(void *priv) { piix_t *dev = (piix_t *) priv; if (!dev) - return; + return; - int te = timer_is_enabled(&dev->fast_off_timer); + int to = timer_is_on(&dev->fast_off_timer); timer_stop(&dev->fast_off_timer); - if (te) - timer_on_auto(&dev->fast_off_timer, dev->fast_off_period); + if (to) + timer_on_auto(&dev->fast_off_timer, ((double) cpu_fast_off_val + 1) * dev->fast_off_period); } - -static void -*piix_init(const device_t *info) +static void * +piix_init(const device_t *info) { piix_t *dev = (piix_t *) malloc(sizeof(piix_t)); memset(dev, 0, sizeof(piix_t)); dev->type = info->local & 0x0f; /* If (dev->type == 4) and (dev->rev & 0x08), then this is PIIX4E. */ - dev->rev = (info->local >> 4) & 0x0f; + dev->rev = (info->local >> 4) & 0x0f; dev->func_shift = (info->local >> 8) & 0x0f; - dev->no_mirq0 = (info->local >> 12) & 0x0f; - dev->func0_id = info->local >> 16; + dev->no_mirq0 = (info->local >> 12) & 0x0f; + dev->func0_id = info->local >> 16; - dev->pci_slot = pci_add_card(PCI_ADD_SOUTHBRIDGE, piix_read, piix_write, dev); + pci_add_card(PCI_ADD_SOUTHBRIDGE, piix_read, piix_write, dev, &dev->pci_slot); piix_log("PIIX%i: Added to slot: %02X\n", dev->type, dev->pci_slot); piix_log("PIIX%i: Added to slot: %02X\n", dev->type, dev->pci_slot); dev->bm[0] = device_add_inst(&sff8038i_device, 1); dev->bm[1] = device_add_inst(&sff8038i_device, 2); if ((dev->type == 1) && (dev->rev == 2)) { - /* PIIX rev. 02 has faulty bus mastering on real hardware, - so set our devices IDE devices to force ATA-3 (no DMA). */ - ide_board_set_force_ata3(0, 1); - ide_board_set_force_ata3(1, 1); + /* PIIX rev. 02 has faulty bus mastering on real hardware, + so set our devices IDE devices to force ATA-3 (no DMA). */ + ide_board_set_force_ata3(0, 1); + ide_board_set_force_ata3(1, 1); } - sff_set_irq_mode(dev->bm[0], 0, 0); - sff_set_irq_mode(dev->bm[1], 0, 0); + sff_set_irq_mode(dev->bm[0], IRQ_MODE_LEGACY); - if (dev->no_mirq0 || (dev->type >= 4)) { - sff_set_irq_mode(dev->bm[0], 1, 0); - sff_set_irq_mode(dev->bm[1], 1, 0); - } else { - sff_set_irq_mode(dev->bm[0], 1, 2); - sff_set_irq_mode(dev->bm[1], 1, 2); - } + if (dev->no_mirq0 || (dev->type >= 4)) + sff_set_irq_mode(dev->bm[1], IRQ_MODE_LEGACY); + else + sff_set_irq_mode(dev->bm[1], IRQ_MODE_MIRQ_0); if (dev->type >= 3) - dev->usb = device_add(&usb_device); + dev->usb = device_add(&usb_device); if (dev->type > 3) { - dev->nvr = device_add(&piix4_nvr_device); - dev->smbus = device_add(&piix4_smbus_device); + dev->nvr = device_add(&piix4_nvr_device); + dev->smbus = device_add(&piix4_smbus_device); - dev->acpi = device_add(&acpi_intel_device); - acpi_set_slot(dev->acpi, dev->pci_slot); - acpi_set_nvr(dev->acpi, dev->nvr); - acpi_set_gpireg2_default(dev->acpi, (dev->type > 4) ? 0xf1 : 0xdd); - acpi_set_trap_update(dev->acpi, piix_trap_update, dev); + dev->acpi = device_add(&acpi_intel_device); + acpi_set_slot(dev->acpi, dev->pci_slot); + acpi_set_nvr(dev->acpi, dev->nvr); + acpi_set_gpireg2_default(dev->acpi, (dev->type > 4) ? 0xf1 : 0xdd); + acpi_set_trap_update(dev->acpi, piix_trap_update, dev); - dev->ddma = device_add(&ddma_device); + dev->ddma = device_add(&ddma_device); } else - timer_add(&dev->fast_off_timer, piix_fast_off_count, dev, 0); + timer_add(&dev->fast_off_timer, piix_fast_off_count, dev, 0); piix_reset_hard(dev); piix_log("Maximum function: %i\n", dev->max_func); cpu_fast_off_flags = 0x00000000; if (dev->type < 4) { - cpu_fast_off_val = dev->regs[0][0xa8]; - cpu_fast_off_count = cpu_fast_off_val + 1; + cpu_fast_off_val = dev->regs[0][0xa8]; + cpu_fast_off_count = cpu_fast_off_val + 1; + cpu_register_fast_off_handler(&dev->fast_off_timer); } else - cpu_fast_off_val = cpu_fast_off_count = 0; + cpu_fast_off_val = cpu_fast_off_count = 0; /* On PIIX4, PIIX4E, and SMSC, APM is added by the ACPI device. */ if (dev->type < 4) { - dev->apm = device_add(&apm_pci_device); - /* APM intercept handler to update PIIX/PIIX3 and PIIX4/4E/SMSC ACPI SMI status on APM SMI. */ - io_sethandler(0x00b2, 0x0001, NULL, NULL, NULL, piix_apm_out, NULL, NULL, dev); + dev->apm = device_add(&apm_pci_device); + /* APM intercept handler to update PIIX/PIIX3 and PIIX4/4E/SMSC ACPI SMI status on APM SMI. */ + io_sethandler(0x00b2, 0x0001, NULL, NULL, NULL, piix_apm_out, NULL, NULL, dev); } dev->port_92 = device_add(&port_92_pci_device); - cpu_set_isa_pci_div(4); + if (cpu_busspeed > 50000000) + cpu_set_isa_pci_div(4); + else + cpu_set_isa_pci_div(3); dma_alias_set(); if (dev->type < 4) - pci_enable_mirq(0); + pci_enable_mirq(0); if (dev->type < 3) - pci_enable_mirq(1); + pci_enable_mirq(1); dev->readout_regs[0] = 0xff; dev->readout_regs[1] = 0x40; @@ -1537,170 +1616,149 @@ static void /* Port E1 register 01 (TODO: Find how multipliers > 3.0 are defined): - Bit 6: 1 = can boot, 0 = no; - Bit 7, 1 = multiplier (00 = 2.5, 01 = 2.0, 10 = 3.0, 11 = 1.5); - Bit 5, 4 = bus speed (00 = 50 MHz, 01 = 66 MHz, 10 = 60 MHz, 11 = ????): - Bit 7, 5, 4, 1: 0000 = 125 MHz, 0010 = 166 MHz, 0100 = 150 MHz, 0110 = ??? MHz; - 0001 = 100 MHz, 0011 = 133 MHz, 0101 = 120 MHz, 0111 = ??? MHz; - 1000 = 150 MHz, 1010 = 200 MHz, 1100 = 180 MHz, 1110 = ??? MHz; - 1001 = 75 MHz, 1011 = 100 MHz, 1101 = 90 MHz, 1111 = ??? MHz */ + Bit 6: 1 = can boot, 0 = no; + Bit 7, 1 = multiplier (00 = 2.5, 01 = 2.0, 10 = 3.0, 11 = 1.5); + Bit 5, 4 = bus speed (00 = 50 MHz, 01 = 66 MHz, 10 = 60 MHz, 11 = ????): + Bit 7, 5, 4, 1: 0000 = 125 MHz, 0010 = 166 MHz, 0100 = 150 MHz, 0110 = ??? MHz; + 0001 = 100 MHz, 0011 = 133 MHz, 0101 = 120 MHz, 0111 = ??? MHz; + 1000 = 150 MHz, 1010 = 200 MHz, 1100 = 180 MHz, 1110 = ??? MHz; + 1001 = 75 MHz, 1011 = 100 MHz, 1101 = 90 MHz, 1111 = ??? MHz */ if (cpu_busspeed <= 40000000) - dev->readout_regs[1] |= 0x30; + dev->readout_regs[1] |= 0x30; else if ((cpu_busspeed > 40000000) && (cpu_busspeed <= 50000000)) - dev->readout_regs[1] |= 0x00; + dev->readout_regs[1] |= 0x00; else if ((cpu_busspeed > 50000000) && (cpu_busspeed <= 60000000)) - dev->readout_regs[1] |= 0x20; + dev->readout_regs[1] |= 0x20; else if (cpu_busspeed > 60000000) - dev->readout_regs[1] |= 0x10; + dev->readout_regs[1] |= 0x10; if (cpu_dmulti <= 1.5) - dev->readout_regs[1] |= 0x82; + dev->readout_regs[1] |= 0x82; else if ((cpu_dmulti > 1.5) && (cpu_dmulti <= 2.0)) - dev->readout_regs[1] |= 0x02; + dev->readout_regs[1] |= 0x02; else if ((cpu_dmulti > 2.0) && (cpu_dmulti <= 2.5)) - dev->readout_regs[1] |= 0x00; + dev->readout_regs[1] |= 0x00; else if (cpu_dmulti > 2.5) - dev->readout_regs[1] |= 0x80; + dev->readout_regs[1] |= 0x80; - io_sethandler(0x0078, 0x0002, board_read, NULL, NULL, board_write, NULL, NULL, dev); io_sethandler(0x00e0, 0x0002, board_read, NULL, NULL, board_write, NULL, NULL, dev); - dev->board_config[0] = 0xff; - /* Register 0x0079: */ - /* Bit 7: 0 = Clear password, 1 = Keep password. */ - /* Bit 6: 0 = NVRAM cleared by jumper, 1 = NVRAM normal. */ - /* Bit 5: 0 = CMOS Setup disabled, 1 = CMOS Setup enabled. */ - /* Bit 4: External CPU clock (Switch 8). */ - /* Bit 3: External CPU clock (Switch 7). */ - /* 50 MHz: Switch 7 = Off, Switch 8 = Off. */ - /* 60 MHz: Switch 7 = On, Switch 8 = Off. */ - /* 66 MHz: Switch 7 = Off, Switch 8 = On. */ - /* Bit 2: 0 = On-board audio absent, 1 = On-board audio present. */ - /* Bit 1: 0 = Soft-off capable power supply present, 1 = Soft-off capable power supply absent. */ - /* Bit 0: 0 = 1.5x multiplier, 1 = 2x multiplier (Switch 6). */ - /* NOTE: A bit is read as 1 if switch is off, and as 0 if switch is on. */ - dev->board_config[1] = 0xe0; - - if (cpu_busspeed <= 50000000) - dev->board_config[1] |= 0x10; - else if ((cpu_busspeed > 50000000) && (cpu_busspeed <= 60000000)) - dev->board_config[1] |= 0x18; - else if (cpu_busspeed > 60000000) - dev->board_config[1] |= 0x00; - - if (cpu_dmulti <= 1.5) - dev->board_config[1] |= 0x01; - else - dev->board_config[1] |= 0x00; - - // device_add(&i8254_sec_device); +#if 0 + device_add(&i8254_sec_device); +#endif return dev; } - -const device_t piix_device = -{ - "Intel 82371FB (PIIX)", - "piix", - DEVICE_PCI, - 0x122e0101, - piix_init, - piix_close, - piix_reset, - { NULL }, - piix_speed_changed, - NULL, - NULL +const device_t piix_device = { + .name = "Intel 82371FB (PIIX)", + .internal_name = "piix", + .flags = DEVICE_PCI, + .local = 0x122e0101, + .init = piix_init, + .close = piix_close, + .reset = piix_reset, + { .available = NULL }, + .speed_changed = piix_speed_changed, + .force_redraw = NULL, + .config = NULL }; -const device_t piix_rev02_device = -{ - "Intel 82371FB (PIIX) (Faulty BusMastering!!)", - "piix_rev02", - DEVICE_PCI, - 0x122e0121, - piix_init, - piix_close, - piix_reset, - { NULL }, - piix_speed_changed, - NULL, - NULL +const device_t piix_no_mirq_device = { + .name = "Intel 82371FB (PIIX) (No MIRQ)", + .internal_name = "piix_no_mirq", + .flags = DEVICE_PCI, + .local = 0x122e1101, + .init = piix_init, + .close = piix_close, + .reset = piix_reset, + { .available = NULL }, + .speed_changed = piix_speed_changed, + .force_redraw = NULL, + .config = NULL }; -const device_t piix3_device = -{ - "Intel 82371SB (PIIX3)", - "piix3", - DEVICE_PCI, - 0x70000403, - piix_init, - piix_close, - piix_reset, - { NULL }, - piix_speed_changed, - NULL, - NULL +const device_t piix_rev02_device = { + .name = "Intel 82371FB (PIIX) (Faulty BusMastering!!)", + .internal_name = "piix_rev02", + .flags = DEVICE_PCI, + .local = 0x122e0121, + .init = piix_init, + .close = piix_close, + .reset = piix_reset, + { .available = NULL }, + .speed_changed = piix_speed_changed, + .force_redraw = NULL, + .config = NULL }; -const device_t piix3_ioapic_device = -{ - "Intel 82371SB (PIIX3) (Boards with I/O APIC)", - "piix3_ioapic", - DEVICE_PCI, - 0x70001403, - piix_init, - piix_close, - piix_reset, - { NULL }, - piix_speed_changed, - NULL, - NULL +const device_t piix3_device = { + .name = "Intel 82371SB (PIIX3)", + .internal_name = "piix3", + .flags = DEVICE_PCI, + .local = 0x70000403, + .init = piix_init, + .close = piix_close, + .reset = piix_reset, + { .available = NULL }, + .speed_changed = piix_speed_changed, + .force_redraw = NULL, + .config = NULL }; -const device_t piix4_device = -{ - "Intel 82371AB/EB (PIIX4/PIIX4E)", - "piix4", - DEVICE_PCI, - 0x71100004, - piix_init, - piix_close, - piix_reset, - { NULL }, - piix_speed_changed, - NULL, - NULL +const device_t piix3_ioapic_device = { + .name = "Intel 82371SB (PIIX3) (Boards with I/O APIC)", + .internal_name = "piix3_ioapic", + .flags = DEVICE_PCI, + .local = 0x70001403, + .init = piix_init, + .close = piix_close, + .reset = piix_reset, + { .available = NULL }, + .speed_changed = piix_speed_changed, + .force_redraw = NULL, + .config = NULL }; -const device_t piix4e_device = -{ - "Intel 82371EB (PIIX4E)", - "piix4e", - DEVICE_PCI, - 0x71100094, - piix_init, - piix_close, - piix_reset, - { NULL }, - piix_speed_changed, - NULL, - NULL +const device_t piix4_device = { + .name = "Intel 82371AB/EB (PIIX4/PIIX4E)", + .internal_name = "piix4", + .flags = DEVICE_PCI, + .local = 0x71100004, + .init = piix_init, + .close = piix_close, + .reset = piix_reset, + { .available = NULL }, + .speed_changed = piix_speed_changed, + .force_redraw = NULL, + .config = NULL }; -const device_t slc90e66_device = -{ - "SMSC SLC90E66 (Victory66)", - "slc90e66", - DEVICE_PCI, - 0x94600005, - piix_init, - piix_close, - piix_reset, - { NULL }, - piix_speed_changed, - NULL, - NULL +const device_t piix4e_device = { + .name = "Intel 82371EB (PIIX4E)", + .internal_name = "piix4e", + .flags = DEVICE_PCI, + .local = 0x71100094, + .init = piix_init, + .close = piix_close, + .reset = piix_reset, + { .available = NULL }, + .speed_changed = piix_speed_changed, + .force_redraw = NULL, + .config = NULL +}; + +const device_t slc90e66_device = { + .name = "SMSC SLC90E66 (Victory66)", + .internal_name = "slc90e66", + .flags = DEVICE_PCI, + .local = 0x94600005, + .init = piix_init, + .close = piix_close, + .reset = piix_reset, + { .available = NULL }, + .speed_changed = piix_speed_changed, + .force_redraw = NULL, + .config = NULL }; diff --git a/src/chipset/intel_sio.c b/src/chipset/intel_sio.c index df8bb8e61..03a292da8 100644 --- a/src/chipset/intel_sio.c +++ b/src/chipset/intel_sio.c @@ -1,324 +1,335 @@ /* - * 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. + * 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. * - * Emulation of Intel System I/O PCI chip. + * Emulation of Intel System I/O PCI chip. * * * - * Authors: Miran Grca, + * Authors: Miran Grca, * - * Copyright 2016-2018 Miran Grca. + * Copyright 2016-2018 Miran Grca. */ +#include #include #include #include #include #include +#define HAVE_STDARG_H #include <86box/86box.h> +#include "cpu.h" #include <86box/device.h> #include <86box/io.h> #include <86box/apm.h> #include <86box/dma.h> #include <86box/mem.h> #include <86box/pci.h> +#include <86box/pic.h> #include <86box/timer.h> #include <86box/pit.h> #include <86box/port_92.h> #include <86box/machine.h> #include <86box/chipset.h> +#include <86box/plat_unused.h> +typedef struct sio_t { + uint8_t id; + uint8_t pci_slot; + uint8_t pad; + uint8_t pad0; -typedef struct -{ - uint8_t id, - regs[256]; + uint8_t regs[256]; - uint16_t timer_base, - timer_latch; + uint16_t timer_base; + uint16_t timer_latch; - double fast_off_period; + double fast_off_period; - pc_timer_t timer, fast_off_timer; + pc_timer_t timer; + pc_timer_t fast_off_timer; - apm_t * apm; - port_92_t * port_92; + apm_t *apm; + port_92_t *port_92; } sio_t; - #ifdef ENABLE_SIO_LOG int sio_do_log = ENABLE_SIO_LOG; - static void sio_log(const char *fmt, ...) { va_list ap; if (sio_do_log) { - va_start(ap, fmt); - pclog_ex(fmt, ap); - va_end(ap); + va_start(ap, fmt); + pclog_ex(fmt, ap); + va_end(ap); } } #else -#define sio_log(fmt, ...) +# define sio_log(fmt, ...) #endif - static void sio_timer_write(uint16_t addr, uint8_t val, void *priv) { sio_t *dev = (sio_t *) priv; if (!(addr & 0x0002)) { - if (addr & 0x0001) - dev->timer_latch = (dev->timer_latch & 0xff) | (val << 8); - else - dev->timer_latch = (dev->timer_latch & 0xff00) | val; + if (addr & 0x0001) + dev->timer_latch = (dev->timer_latch & 0xff) | (val << 8); + else + dev->timer_latch = (dev->timer_latch & 0xff00) | val; - timer_set_delay_u64(&dev->timer, ((uint64_t) dev->timer_latch) * TIMER_USEC); + timer_set_delay_u64(&dev->timer, ((uint64_t) dev->timer_latch) * TIMER_USEC); } } - static void sio_timer_writew(uint16_t addr, uint16_t val, void *priv) { sio_t *dev = (sio_t *) priv; if (!(addr & 0x0002)) { - dev->timer_latch = val; + dev->timer_latch = val; - timer_set_delay_u64(&dev->timer, ((uint64_t) dev->timer_latch) * TIMER_USEC); + timer_set_delay_u64(&dev->timer, ((uint64_t) dev->timer_latch) * TIMER_USEC); } } - static uint8_t sio_timer_read(uint16_t addr, void *priv) { - sio_t *dev = (sio_t *) priv; + sio_t *dev = (sio_t *) priv; uint16_t sio_timer_latch; - uint8_t ret = 0xff; + uint8_t ret = 0xff; if (!(addr & 0x0002)) { - cycles -= ((int) (PITCONST >> 32)); + cycles -= ((int) (PITCONST >> 32)); - sio_timer_latch = timer_get_remaining_us(&dev->timer); + sio_timer_latch = timer_get_remaining_us(&dev->timer); - if (addr & 0x0001) - ret = sio_timer_latch >> 8; - else - ret = sio_timer_latch & 0xff; + if (addr & 0x0001) + ret = sio_timer_latch >> 8; + else + ret = sio_timer_latch & 0xff; } return ret; } - static uint16_t sio_timer_readw(uint16_t addr, void *priv) { - sio_t *dev = (sio_t *) priv; + sio_t *dev = (sio_t *) priv; uint16_t ret = 0xffff; if (!(addr & 0x0002)) { - cycles -= ((int) (PITCONST >> 32)); + cycles -= ((int) (PITCONST >> 32)); - ret = timer_get_remaining_us(&dev->timer); + ret = timer_get_remaining_us(&dev->timer); } return ret; } - static void sio_write(int func, int addr, uint8_t val, void *priv) { - sio_t *dev = (sio_t *) priv; + sio_t *dev = (sio_t *) priv; uint8_t old; if (func > 0) - return; + return; if (((addr >= 0x0f) && (addr < 0x4c)) && (addr != 0x40)) - return; + return; /* The IB (original) variant of the SIO has no PCI IRQ steering. */ if ((addr >= 0x60) && (addr <= 0x63) && (dev->id < 0x03)) - return; + return; old = dev->regs[addr]; switch (addr) { - case 0x04: /*Command register*/ - if (dev->id == 0x03) - dev->regs[addr] = (dev->regs[addr] & 0xf7) | (val & 0x08); - break; + case 0x04: /*Command register*/ + if (dev->id == 0x03) + dev->regs[addr] = (dev->regs[addr] & 0xf7) | (val & 0x08); + break; - case 0x07: - dev->regs[addr] &= ~(val & 0x38); - break; + case 0x07: + dev->regs[addr] &= ~(val & 0x38); + break; - case 0x40: - if (dev->id == 0x03) { - dev->regs[addr] = (val & 0x7f); + case 0x40: + if (dev->id == 0x03) { + dev->regs[addr] = (val & 0x7f); - if (!((val ^ old) & 0x40)) - return; + if (!((val ^ old) & 0x40)) + return; - dma_alias_remove(); - if (!(val & 0x40)) - dma_alias_set(); - } else - dev->regs[addr] = (val & 0x3f); - break; - case 0x41: case 0x44: - dev->regs[addr] = (val & 0x1f); - break; - case 0x42: - if (dev->id == 0x03) - dev->regs[addr] = val; - else - dev->regs[addr] = (val & 0x77); - break; - case 0x43: - if (dev->id == 0x03) - dev->regs[addr] = (val & 0x01); - break; - case 0x45: case 0x46: - case 0x47: case 0x48: - case 0x49: case 0x4a: - case 0x4b: case 0x4e: - case 0x54: case 0x55: - case 0x56: - dev->regs[addr] = val; - break; - case 0x4c: case 0x4d: - dev->regs[addr] = (val & 0x7f); - break; - case 0x4f: - dev->regs[addr] = val; + dma_alias_remove(); + if (!(val & 0x40)) + dma_alias_set(); + } else + dev->regs[addr] = (val & 0x3f); + break; + case 0x41: + case 0x44: + dev->regs[addr] = (val & 0x1f); + break; + case 0x42: + if (dev->id == 0x03) + dev->regs[addr] = val; + else + dev->regs[addr] = (val & 0x77); + break; + case 0x43: + if (dev->id == 0x03) + dev->regs[addr] = (val & 0x01); + break; + case 0x45: + case 0x46: + case 0x47: + case 0x48: + case 0x49: + case 0x4a: + case 0x4b: + case 0x4e: + case 0x54: + case 0x55: + case 0x56: + dev->regs[addr] = val; + break; + case 0x4c: + dev->regs[addr] = (val & 0x7f); + break; + case 0x4d: + dev->regs[addr] = (val & 0x7f); + break; + case 0x4f: + dev->regs[addr] = val; - if (!((val ^ old) & 0x40)) - return; + if (!((val ^ old) & 0x40)) + return; - port_92_remove(dev->port_92); - if (val & 0x40) - port_92_add(dev->port_92); - break; - case 0x57: - dev->regs[addr] = val; + port_92_remove(dev->port_92); + if (val & 0x40) + port_92_add(dev->port_92); + break; + case 0x57: + dev->regs[addr] = val; - dma_remove_sg(); - dma_set_sg_base(val); - break; - case 0x60: case 0x61: case 0x62: case 0x63: - if (dev->id == 0x03) { - sio_log("Set IRQ routing: INT %c -> %02X\n", 0x41 + (addr & 0x03), val); - dev->regs[addr] = val & 0x8f; - if (val & 0x80) - pci_set_irq_routing(PCI_INTA + (addr & 0x03), PCI_IRQ_DISABLED); - else - pci_set_irq_routing(PCI_INTA + (addr & 0x03), val & 0xf); - } - break; - case 0x80: - case 0x81: - if (addr == 0x80) - dev->regs[addr] = val & 0xfd; - else - dev->regs[addr] = val; + dma_remove_sg(); + dma_set_sg_base(val); + break; + case 0x60: + case 0x61: + case 0x62: + case 0x63: + if (dev->id == 0x03) { + sio_log("Set IRQ routing: INT %c -> %02X\n", 0x41 + (addr & 0x03), val); + dev->regs[addr] = val & 0x8f; + if (val & 0x80) + pci_set_irq_routing(PCI_INTA + (addr & 0x03), PCI_IRQ_DISABLED); + else + pci_set_irq_routing(PCI_INTA + (addr & 0x03), val & 0xf); + } + break; + case 0x80: + case 0x81: + if (addr == 0x80) + dev->regs[addr] = val & 0xfd; + else + dev->regs[addr] = val; - if (dev->timer_base & 0x01) { - io_removehandler(dev->timer_base & 0xfffc, 0x0004, - sio_timer_read, sio_timer_readw, NULL, - sio_timer_write, sio_timer_writew, NULL, dev); - } - dev->timer_base = (dev->regs[0x81] << 8) | (dev->regs[0x80] & 0xfd); - if (dev->timer_base & 0x01) { - io_sethandler(dev->timer_base & 0xfffc, 0x0004, - sio_timer_read, sio_timer_readw, NULL, - sio_timer_write, sio_timer_writew, NULL, dev); - } - break; - case 0xa0: - if (dev->id == 0x03) { - dev->regs[addr] = val & 0x1f; - apm_set_do_smi(dev->apm, !!(val & 0x01) && !!(dev->regs[0xa2] & 0x80)); - switch ((val & 0x18) >> 3) { - case 0x00: - dev->fast_off_period = PCICLK * 32768.0 * 60000.0; - break; - case 0x01: - default: - dev->fast_off_period = 0.0; - break; - case 0x02: - dev->fast_off_period = PCICLK; - break; - case 0x03: - dev->fast_off_period = PCICLK * 32768.0; - break; - } - cpu_fast_off_count = dev->regs[0xa8] + 1; - timer_disable(&dev->fast_off_timer); - if (dev->fast_off_period != 0.0) - timer_on_auto(&dev->fast_off_timer, dev->fast_off_period); - } - break; - case 0xa2: - if (dev->id == 0x03) { - dev->regs[addr] = val & 0xff; - apm_set_do_smi(dev->apm, !!(dev->regs[0xa0] & 0x01) && !!(val & 0x80)); - } - break; - case 0xaa: - if (dev->id == 0x03) - dev->regs[addr] &= (val & 0xff); - break; - case 0xac: case 0xae: - if (dev->id == 0x03) - dev->regs[addr] = val & 0xff; - break; - case 0xa4: - if (dev->id == 0x03) { - dev->regs[addr] = val & 0xfb; - cpu_fast_off_flags = (cpu_fast_off_flags & 0xffffff00) | dev->regs[addr]; - } - break; - case 0xa5: - if (dev->id == 0x03) { - dev->regs[addr] = val & 0xff; - cpu_fast_off_flags = (cpu_fast_off_flags & 0xffff00ff) | (dev->regs[addr] << 8); - } - break; - case 0xa7: - if (dev->id == 0x03) { - dev->regs[addr] = val & 0xa0; - cpu_fast_off_flags = (cpu_fast_off_flags & 0x00ffffff) | (dev->regs[addr] << 24); - } - break; - case 0xa8: - dev->regs[addr] = val & 0xff; - cpu_fast_off_val = val; - cpu_fast_off_count = val + 1; - timer_disable(&dev->fast_off_timer); - if (dev->fast_off_period != 0.0) - timer_on_auto(&dev->fast_off_timer, dev->fast_off_period); - break; + if (dev->timer_base & 0x01) { + io_removehandler(dev->timer_base & 0xfffc, 0x0004, + sio_timer_read, sio_timer_readw, NULL, + sio_timer_write, sio_timer_writew, NULL, dev); + } + dev->timer_base = (dev->regs[0x81] << 8) | (dev->regs[0x80] & 0xfd); + if (dev->timer_base & 0x01) { + io_sethandler(dev->timer_base & 0xfffc, 0x0004, + sio_timer_read, sio_timer_readw, NULL, + sio_timer_write, sio_timer_writew, NULL, dev); + } + break; + case 0xa0: + if (dev->id == 0x03) { + dev->regs[addr] = val & 0x1f; + apm_set_do_smi(dev->apm, !!(val & 0x01) && !!(dev->regs[0xa2] & 0x80)); + switch ((val & 0x18) >> 3) { + case 0x00: + dev->fast_off_period = PCICLK * 32768.0 * 60000.0; + break; + case 0x01: + default: + dev->fast_off_period = 0.0; + break; + case 0x02: + dev->fast_off_period = PCICLK; + break; + case 0x03: + dev->fast_off_period = PCICLK * 32768.0; + break; + } + cpu_fast_off_count = cpu_fast_off_val + 1; + cpu_fast_off_period_set(cpu_fast_off_val, dev->fast_off_period); + } + break; + case 0xa2: + if (dev->id == 0x03) { + dev->regs[addr] = val & 0xff; + apm_set_do_smi(dev->apm, !!(dev->regs[0xa0] & 0x01) && !!(val & 0x80)); + } + break; + case 0xaa: + if (dev->id == 0x03) + dev->regs[addr] &= (val & 0xff); + break; + case 0xac: + case 0xae: + if (dev->id == 0x03) + dev->regs[addr] = val & 0xff; + break; + case 0xa4: + if (dev->id == 0x03) { + dev->regs[addr] = val & 0xfb; + cpu_fast_off_flags = (cpu_fast_off_flags & 0xffffff00) | dev->regs[addr]; + } + break; + case 0xa5: + if (dev->id == 0x03) { + dev->regs[addr] = val & 0xff; + cpu_fast_off_flags = (cpu_fast_off_flags & 0xffff00ff) | (dev->regs[addr] << 8); + } + break; + case 0xa7: + if (dev->id == 0x03) { + dev->regs[addr] = val & 0xa0; + cpu_fast_off_flags = (cpu_fast_off_flags & 0x00ffffff) | (dev->regs[addr] << 24); + } + break; + case 0xa8: + dev->regs[addr] = val & 0xff; + cpu_fast_off_val = val; + cpu_fast_off_count = val + 1; + cpu_fast_off_period_set(cpu_fast_off_val, dev->fast_off_period); + break; + default: + break; } } - static uint8_t sio_read(int func, int addr, void *priv) { - sio_t *dev = (sio_t *) priv; - uint8_t ret; + const sio_t *dev = (sio_t *) priv; + uint8_t ret; ret = 0xff; @@ -328,47 +339,48 @@ sio_read(int func, int addr, void *priv) return ret; } - static void -sio_config_write(uint16_t addr, uint8_t val, void *priv) +sio_config_write(UNUSED(uint16_t addr), UNUSED(uint8_t val), UNUSED(void *priv)) { + // } - static uint8_t -sio_config_read(uint16_t port, void *priv) +sio_config_read(uint16_t port, UNUSED(void *priv)) { uint8_t ret = 0x00; switch (port & 0x000f) { - case 3: - ret = 0xff; - break; - case 5: - ret = 0xd3; + case 3: + ret = 0xff; + break; + case 5: + ret = 0xd3; - switch (cpu_pci_speed) { - case 20000000: - ret |= 0x0c; - break; - case 25000000: - default: - ret |= 0x00; - break; - case 30000000: - ret |= 0x08; - break; - case 33333333: - ret |= 0x04; - break; - } - break; + switch (cpu_pci_speed) { + case 20000000: + ret |= 0x0c; + break; + case 25000000: + default: + ret |= 0x00; + break; + case 30000000: + ret |= 0x08; + break; + case 33333333: + ret |= 0x04; + break; + } + break; + + default: + break; } return ret; } - static void sio_reset_hard(void *priv) { @@ -376,27 +388,37 @@ sio_reset_hard(void *priv) memset(dev->regs, 0, 256); - dev->regs[0x00] = 0x86; dev->regs[0x01] = 0x80; /*Intel*/ - dev->regs[0x02] = 0x84; dev->regs[0x03] = 0x04; /*82378IB (SIO)*/ + dev->regs[0x00] = 0x86; + dev->regs[0x01] = 0x80; /*Intel*/ + dev->regs[0x02] = 0x84; + dev->regs[0x03] = 0x04; /*82378IB (SIO)*/ dev->regs[0x04] = 0x07; dev->regs[0x07] = 0x02; dev->regs[0x08] = dev->id; - dev->regs[0x40] = 0x20; dev->regs[0x41] = 0x00; + dev->regs[0x40] = 0x20; + dev->regs[0x41] = 0x00; dev->regs[0x42] = 0x04; - dev->regs[0x45] = 0x10; dev->regs[0x46] = 0x0f; + dev->regs[0x45] = 0x10; + dev->regs[0x46] = 0x0f; dev->regs[0x48] = 0x01; - dev->regs[0x4a] = 0x10; dev->regs[0x4b] = 0x0f; - dev->regs[0x4c] = 0x56; dev->regs[0x4d] = 0x40; - dev->regs[0x4e] = 0x07; dev->regs[0x4f] = 0x4f; + dev->regs[0x4a] = 0x10; + dev->regs[0x4b] = 0x0f; + dev->regs[0x4c] = 0x56; + dev->regs[0x4d] = 0x40; + dev->regs[0x4e] = 0x07; + dev->regs[0x4f] = 0x4f; dev->regs[0x57] = 0x04; if (dev->id == 0x03) { - dev->regs[0x60] = 0x80; dev->regs[0x61] = 0x80; dev->regs[0x62] = 0x80; dev->regs[0x63] = 0x80; + dev->regs[0x60] = 0x80; + dev->regs[0x61] = 0x80; + dev->regs[0x62] = 0x80; + dev->regs[0x63] = 0x80; } dev->regs[0x80] = 0x78; if (dev->id == 0x03) { - dev->regs[0xa0] = 0x08; - dev->regs[0xa8] = 0x0f; + dev->regs[0xa0] = 0x08; + dev->regs[0xa8] = 0x0f; } pci_set_irq_routing(PCI_INTA, PCI_IRQ_DISABLED); @@ -405,121 +427,113 @@ sio_reset_hard(void *priv) pci_set_irq_routing(PCI_INTD, PCI_IRQ_DISABLED); if (dev->timer_base & 0x0001) { - io_removehandler(dev->timer_base & 0xfffc, 0x0004, - sio_timer_read, sio_timer_readw, NULL, - sio_timer_write, sio_timer_writew, NULL, dev); + io_removehandler(dev->timer_base & 0xfffc, 0x0004, + sio_timer_read, sio_timer_readw, NULL, + sio_timer_write, sio_timer_writew, NULL, dev); } dev->timer_base = 0x0078; } - static void -sio_apm_out(uint16_t port, uint8_t val, void *p) +sio_apm_out(UNUSED(uint16_t port), UNUSED(uint8_t val), void *priv) { - sio_t *dev = (sio_t *) p; + sio_t *dev = (sio_t *) priv; if (dev->apm->do_smi) - dev->regs[0xaa] |= 0x80; + dev->regs[0xaa] |= 0x80; } - static void sio_fast_off_count(void *priv) { sio_t *dev = (sio_t *) priv; - cpu_fast_off_count--; - - if (cpu_fast_off_count == 0) { - smi_line = 1; - dev->regs[0xaa] |= 0x20; - cpu_fast_off_count = dev->regs[0xa8] + 1; - } - - timer_on_auto(&dev->fast_off_timer, dev->fast_off_period); + smi_raise(); + dev->regs[0xaa] |= 0x20; } - static void -sio_reset(void *p) +sio_reset(void *priv) { - sio_t *dev = (sio_t *) p; + const sio_t *dev = (sio_t *) priv; - sio_write(0, 0x57, 0x04, p); + /* Disable the PIC mouse latch. */ + sio_write(0, 0x4d, 0x40, priv); + + sio_write(0, 0x57, 0x04, priv); dma_set_params(1, 0xffffffff); if (dev->id == 0x03) { - sio_write(0, 0xa0, 0x08, p); - sio_write(0, 0xa2, 0x00, p); - sio_write(0, 0xa4, 0x00, p); - sio_write(0, 0xa5, 0x00, p); - sio_write(0, 0xa6, 0x00, p); - sio_write(0, 0xa7, 0x00, p); - sio_write(0, 0xa8, 0x0f, p); + sio_write(0, 0xa0, 0x08, priv); + sio_write(0, 0xa2, 0x00, priv); + sio_write(0, 0xa4, 0x00, priv); + sio_write(0, 0xa5, 0x00, priv); + sio_write(0, 0xa6, 0x00, priv); + sio_write(0, 0xa7, 0x00, priv); + sio_write(0, 0xa8, 0x0f, priv); } } - static void -sio_close(void *p) +sio_close(void *priv) { - sio_t *dev = (sio_t *)p; + sio_t *dev = (sio_t *) priv; free(dev); } - static void sio_speed_changed(void *priv) { sio_t *dev = (sio_t *) priv; - int te; + int te; te = timer_is_enabled(&dev->timer); timer_disable(&dev->timer); if (te) - timer_set_delay_u64(&dev->timer, ((uint64_t) dev->timer_latch) * TIMER_USEC); + timer_set_delay_u64(&dev->timer, ((uint64_t) dev->timer_latch) * TIMER_USEC); if (dev->id == 0x03) { - te = timer_is_enabled(&dev->fast_off_timer); + te = timer_is_on(&dev->fast_off_timer); - timer_stop(&dev->fast_off_timer); - if (te) - timer_on_auto(&dev->fast_off_timer, dev->fast_off_period); + timer_stop(&dev->fast_off_timer); + if (te) + timer_on_auto(&dev->fast_off_timer, dev->fast_off_period); } } - static void * sio_init(const device_t *info) { sio_t *dev = (sio_t *) malloc(sizeof(sio_t)); memset(dev, 0, sizeof(sio_t)); - pci_add_card(PCI_ADD_SOUTHBRIDGE, sio_read, sio_write, dev); + pci_add_card(PCI_ADD_SOUTHBRIDGE, sio_read, sio_write, dev, &dev->pci_slot); dev->id = info->local; if (dev->id == 0x03) - timer_add(&dev->fast_off_timer, sio_fast_off_count, dev, 0); + timer_add(&dev->fast_off_timer, sio_fast_off_count, dev, 0); sio_reset_hard(dev); cpu_fast_off_flags = 0x00000000; if (dev->id == 0x03) { - cpu_fast_off_val = dev->regs[0xa8]; - cpu_fast_off_count = cpu_fast_off_val + 1; + cpu_fast_off_val = dev->regs[0xa8]; + cpu_fast_off_count = cpu_fast_off_val + 1; + + cpu_register_fast_off_handler(&dev->fast_off_timer); } else - cpu_fast_off_val = cpu_fast_off_count = 0; + cpu_fast_off_val = cpu_fast_off_count = 0; if (dev->id == 0x03) { - dev->apm = device_add(&apm_pci_device); - /* APM intercept handler to update 82378ZB SMI status on APM SMI. */ - io_sethandler(0x00b2, 0x0001, NULL, NULL, NULL, sio_apm_out, NULL, NULL, dev); + dev->apm = device_add(&apm_pci_device); + /* APM intercept handler to update 82378ZB SMI status on APM SMI. */ + io_sethandler(0x00b2, 0x0001, NULL, NULL, NULL, sio_apm_out, NULL, NULL, dev); } dev->port_92 = device_add(&port_92_pci_device); @@ -530,48 +544,46 @@ sio_init(const device_t *info) dma_high_page_init(); if (dev->id == 0x03) - dma_alias_set(); + dma_alias_set(); io_sethandler(0x0073, 0x0001, - sio_config_read, NULL, NULL, sio_config_write, NULL, NULL, dev); + sio_config_read, NULL, NULL, sio_config_write, NULL, NULL, dev); io_sethandler(0x0075, 0x0001, - sio_config_read, NULL, NULL, sio_config_write, NULL, NULL, dev); + sio_config_read, NULL, NULL, sio_config_write, NULL, NULL, dev); timer_add(&dev->timer, NULL, NULL, 0); - // device_add(&i8254_sec_device); +#if 0 + device_add(&i8254_sec_device); +#endif return dev; } - -const device_t sio_device = -{ - "Intel 82378IB (SIO)", - "sio", - DEVICE_PCI, - 0x00, - sio_init, - sio_close, - sio_reset, - { NULL }, - sio_speed_changed, - NULL, - NULL +const device_t sio_device = { + .name = "Intel 82378IB (SIO)", + .internal_name = "sio", + .flags = DEVICE_PCI, + .local = 0x00, + .init = sio_init, + .close = sio_close, + .reset = sio_reset, + { .available = NULL }, + .speed_changed = sio_speed_changed, + .force_redraw = NULL, + .config = NULL }; - -const device_t sio_zb_device = -{ - "Intel 82378ZB (SIO)", - "sio_zb", - DEVICE_PCI, - 0x03, - sio_init, - sio_close, - sio_reset, - { NULL }, - sio_speed_changed, - NULL, - NULL +const device_t sio_zb_device = { + .name = "Intel 82378ZB (SIO)", + .internal_name = "sio_zb", + .flags = DEVICE_PCI, + .local = 0x03, + .init = sio_init, + .close = sio_close, + .reset = sio_reset, + { .available = NULL }, + .speed_changed = sio_speed_changed, + .force_redraw = NULL, + .config = NULL }; diff --git a/src/chipset/neat.c b/src/chipset/neat.c index 7badc0de8..a54fc312e 100644 --- a/src/chipset/neat.c +++ b/src/chipset/neat.c @@ -1,295 +1,292 @@ /* - * 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. + * 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. + * This file is part of the 86Box distribution. * - * Emulation of C&T CS8121 ("NEAT") 82C206/211/212/215 chipset. + * Emulation of C&T CS8121 ("NEAT") 82C206/211/212/215 chipset. * - * Note: The datasheet mentions that the chipset supports up to 8MB - * of DRAM. This is intepreted as 'being able to refresh up to - * 8MB of DRAM chips', because it works fine with bus-based - * memory expansion. + * Note: The datasheet mentions that the chipset supports up to 8MB + * of DRAM. This is intepreted as 'being able to refresh up to + * 8MB of DRAM chips', because it works fine with bus-based + * memory expansion. * * * - * Author: Fred N. van Kempen, + * Authors: Fred N. van Kempen, * - * Copyright 2018 Fred N. van Kempen. + * Copyright 2018 Fred N. van Kempen. */ +#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/plat_unused.h> #include <86box/chipset.h> -#define NEAT_DEBUG 0 - - -#define EMS_MAXPAGE 4 -#define EMS_PGSIZE 16384 +#define NEAT_DEBUG 0 +#define EMS_MAXPAGE 4 +#define EMS_PGSIZE 16384 /* CS8221 82C211 controller registers. */ -#define REG_RA0 0x60 /* PROCCLK selector */ -# define RA0_MASK 0x34 /* RR11 X1XR */ -# define RA0_READY 0x01 /* local bus READY timeout */ -# define RA0_RDYNMIEN 0x04 /* local bus READY tmo NMI enable */ -# define RA0_PROCCLK 0x10 /* PROCCLK=BCLK (1) or CLK2IN (0) */ -# define RA0_ALTRST 0x20 /* alternate CPU reset (1) */ -# define RA0_REV 0xc0 /* chip revision ID */ -# define RA0_REV_SH 6 -# define RA0_REV_ID 2 /* faked revision# for 82C211 */ +#define REG_RA0 0x60 /* PROCCLK selector */ +#define RA0_MASK 0x34 /* RR11 X1XR */ +#define RA0_READY 0x01 /* local bus READY timeout */ +#define RA0_RDYNMIEN 0x04 /* local bus READY tmo NMI enable */ +#define RA0_PROCCLK 0x10 /* PROCCLK=BCLK (1) or CLK2IN (0) */ +#define RA0_ALTRST 0x20 /* alternate CPU reset (1) */ +#define RA0_REV 0xc0 /* chip revision ID */ +#define RA0_REV_SH 6 +#define RA0_REV_ID 2 /* faked revision# for 82C211 */ -#define REG_RA1 0x61 /* Command Delay */ -# define RA1_MASK 0xff /* 1111 1111 */ -# define RA1_BUSDLY 0x03 /* AT BUS command delay */ -# define RA1_BUSDLY_SH 0 -# define RA1_BUS8DLY 0x0c /* AT BUS 8bit command delay */ -# define RA1_BUS8DLY_SH 2 -# define RA1_MEMDLY 0x30 /* AT BUS 16bit memory delay */ -# define RA1_MEMDLY_SH 4 -# define RA1_QUICKEN 0x40 /* Quick Mode enable */ -# define RA1_HOLDDLY 0x80 /* Hold Time Delay */ +#define REG_RA1 0x61 /* Command Delay */ +#define RA1_MASK 0xff /* 1111 1111 */ +#define RA1_BUSDLY 0x03 /* AT BUS command delay */ +#define RA1_BUSDLY_SH 0 +#define RA1_BUS8DLY 0x0c /* AT BUS 8bit command delay */ +#define RA1_BUS8DLY_SH 2 +#define RA1_MEMDLY 0x30 /* AT BUS 16bit memory delay */ +#define RA1_MEMDLY_SH 4 +#define RA1_QUICKEN 0x40 /* Quick Mode enable */ +#define RA1_HOLDDLY 0x80 /* Hold Time Delay */ -#define REG_RA2 0x62 /* Wait State / BCLK selector */ -# define RA2_MASK 0x3f /* XX11 1111 */ -# define RA2_BCLK 0x03 /* BCLK select */ -# define RA2_BCLK_SH 0 -# define BCLK_IN2 0 /* BCLK = CLK2IN/2 */ -# define BCLK_IN 1 /* BCLK = CLK2IN */ -# define BCLK_AT 2 /* BCLK = ATCLK */ -# define RA2_AT8WS 0x0c /* AT 8-bit wait states */ -# define RA2_AT8WS_SH 2 -# define AT8WS_2 0 /* 2 wait states */ -# define AT8WS_3 1 /* 3 wait states */ -# define AT8WS_4 2 /* 4 wait states */ -# define AT8WS_5 4 /* 5 wait states */ -# define RA2_ATWS 0x30 /* AT 16-bit wait states */ -# define RA2_ATWS_SH 4 -# define ATWS_2 0 /* 2 wait states */ -# define ATWS_3 1 /* 3 wait states */ -# define ATWS_4 2 /* 4 wait states */ -# define ATWS_5 4 /* 5 wait states */ +#define REG_RA2 0x62 /* Wait State / BCLK selector */ +#define RA2_MASK 0x3f /* XX11 1111 */ +#define RA2_BCLK 0x03 /* BCLK select */ +#define RA2_BCLK_SH 0 +#define BCLK_IN2 0 /* BCLK = CLK2IN/2 */ +#define BCLK_IN 1 /* BCLK = CLK2IN */ +#define BCLK_AT 2 /* BCLK = ATCLK */ +#define RA2_AT8WS 0x0c /* AT 8-bit wait states */ +#define RA2_AT8WS_SH 2 +#define AT8WS_2 0 /* 2 wait states */ +#define AT8WS_3 1 /* 3 wait states */ +#define AT8WS_4 2 /* 4 wait states */ +#define AT8WS_5 4 /* 5 wait states */ +#define RA2_ATWS 0x30 /* AT 16-bit wait states */ +#define RA2_ATWS_SH 4 +#define ATWS_2 0 /* 2 wait states */ +#define ATWS_3 1 /* 3 wait states */ +#define ATWS_4 2 /* 4 wait states */ +#define ATWS_5 4 /* 5 wait states */ /* CS8221 82C212 controller registers. */ -#define REG_RB0 0x64 /* Version ID */ -# define RB0_MASK 0x60 /* R11X XXXX */ -# define RB0_REV 0x60 /* Chip revsion number */ -# define RB0_REV_SH 5 -# define RB0_REV_ID 2 /* faked revision# for 82C212 */ -# define RB0_VERSION 0x80 /* Chip version (0=82C212) */ +#define REG_RB0 0x64 /* Version ID */ +#define RB0_MASK 0x60 /* R11X XXXX */ +#define RB0_REV 0x60 /* Chip revsion number */ +#define RB0_REV_SH 5 +#define RB0_REV_ID 2 /* faked revision# for 82C212 */ +#define RB0_VERSION 0x80 /* Chip version (0=82C212) */ -#define REG_RB1 0x65 /* ROM configuration */ -# define RB1_MASK 0xff /* 1111 1111 */ -# define RB1_ROMF0 0x01 /* ROM F0000 enabled (0) */ -# define RB1_ROME0 0x02 /* ROM E0000 disabled (1) */ -# define RB1_ROMD0 0x04 /* ROM D0000 disabled (1) */ -# define RB1_ROMC0 0x08 /* ROM C0000 disabled (1) */ -# define RB1_SHADOWF0 0x10 /* Shadow F0000 R/W (0) */ -# define RB1_SHADOWE0 0x20 /* Shadow E0000 R/W (0) */ -# define RB1_SHADOWD0 0x40 /* Shadow D0000 R/W (0) */ -# define RB1_SHADOWC0 0x80 /* Shadow C0000 R/W (0) */ +#define REG_RB1 0x65 /* ROM configuration */ +#define RB1_MASK 0xff /* 1111 1111 */ +#define RB1_ROMF0 0x01 /* ROM F0000 enabled (0) */ +#define RB1_ROME0 0x02 /* ROM E0000 disabled (1) */ +#define RB1_ROMD0 0x04 /* ROM D0000 disabled (1) */ +#define RB1_ROMC0 0x08 /* ROM C0000 disabled (1) */ +#define RB1_SHADOWF0 0x10 /* Shadow F0000 R/W (0) */ +#define RB1_SHADOWE0 0x20 /* Shadow E0000 R/W (0) */ +#define RB1_SHADOWD0 0x40 /* Shadow D0000 R/W (0) */ +#define RB1_SHADOWC0 0x80 /* Shadow C0000 R/W (0) */ -#define REG_RB2 0x66 /* Memory Enable 1 */ -# define RB2_MASK 0x80 /* 1XXX XXXX */ -# define RB2_TOP128 0x80 /* top 128K is on sysboard (1) */ +#define REG_RB2 0x66 /* Memory Enable 1 */ +#define RB2_MASK 0x80 /* 1XXX XXXX */ +#define RB2_TOP128 0x80 /* top 128K is on sysboard (1) */ -#define REG_RB3 0x67 /* Memory Enable 2 */ -# define RB3_MASK 0xff /* 1111 1111 */ -# define RB3_SHENB0 0x01 /* enable B0000-B3FFF shadow (1) */ -# define RB3_SHENB4 0x02 /* enable B4000-B7FFF shadow (1) */ -# define RB3_SHENB8 0x04 /* enable B8000-BBFFF shadow (1) */ -# define RB3_SHENBC 0x08 /* enable BC000-BFFFF shadow (1) */ -# define RB3_SHENA0 0x10 /* enable A0000-A3FFF shadow (1) */ -# define RB3_SHENA4 0x20 /* enable A4000-A7FFF shadow (1) */ -# define RB3_SHENA8 0x40 /* enable A8000-ABFFF shadow (1) */ -# define RB3_SHENAC 0x80 /* enable AC000-AFFFF shadow (1) */ +#define REG_RB3 0x67 /* Memory Enable 2 */ +#define RB3_MASK 0xff /* 1111 1111 */ +#define RB3_SHENB0 0x01 /* enable B0000-B3FFF shadow (1) */ +#define RB3_SHENB4 0x02 /* enable B4000-B7FFF shadow (1) */ +#define RB3_SHENB8 0x04 /* enable B8000-BBFFF shadow (1) */ +#define RB3_SHENBC 0x08 /* enable BC000-BFFFF shadow (1) */ +#define RB3_SHENA0 0x10 /* enable A0000-A3FFF shadow (1) */ +#define RB3_SHENA4 0x20 /* enable A4000-A7FFF shadow (1) */ +#define RB3_SHENA8 0x40 /* enable A8000-ABFFF shadow (1) */ +#define RB3_SHENAC 0x80 /* enable AC000-AFFFF shadow (1) */ -#define REG_RB4 0x68 /* Memory Enable 3 */ -# define RB4_MASK 0xff /* 1111 1111 */ -# define RB4_SHENC0 0x01 /* enable C0000-C3FFF shadow (1) */ -# define RB4_SHENC4 0x02 /* enable C4000-C7FFF shadow (1) */ -# define RB4_SHENC8 0x04 /* enable C8000-CBFFF shadow (1) */ -# define RB4_SHENCC 0x08 /* enable CC000-CFFFF shadow (1) */ -# define RB4_SHEND0 0x10 /* enable D0000-D3FFF shadow (1) */ -# define RB4_SHEND4 0x20 /* enable D4000-D7FFF shadow (1) */ -# define RB4_SHEND8 0x40 /* enable D8000-DBFFF shadow (1) */ -# define RB4_SHENDC 0x80 /* enable DC000-DFFFF shadow (1) */ +#define REG_RB4 0x68 /* Memory Enable 3 */ +#define RB4_MASK 0xff /* 1111 1111 */ +#define RB4_SHENC0 0x01 /* enable C0000-C3FFF shadow (1) */ +#define RB4_SHENC4 0x02 /* enable C4000-C7FFF shadow (1) */ +#define RB4_SHENC8 0x04 /* enable C8000-CBFFF shadow (1) */ +#define RB4_SHENCC 0x08 /* enable CC000-CFFFF shadow (1) */ +#define RB4_SHEND0 0x10 /* enable D0000-D3FFF shadow (1) */ +#define RB4_SHEND4 0x20 /* enable D4000-D7FFF shadow (1) */ +#define RB4_SHEND8 0x40 /* enable D8000-DBFFF shadow (1) */ +#define RB4_SHENDC 0x80 /* enable DC000-DFFFF shadow (1) */ -#define REG_RB5 0x69 /* Memory Enable 4 */ -# define RB5_MASK 0xff /* 1111 1111 */ -# define RB5_SHENE0 0x01 /* enable E0000-E3FFF shadow (1) */ -# define RB5_SHENE4 0x02 /* enable E4000-E7FFF shadow (1) */ -# define RB5_SHENE8 0x04 /* enable E8000-EBFFF shadow (1) */ -# define RB5_SHENEC 0x08 /* enable EC000-EFFFF shadow (1) */ -# define RB5_SHENF0 0x10 /* enable F0000-F3FFF shadow (1) */ -# define RB5_SHENF4 0x20 /* enable F4000-F7FFF shadow (1) */ -# define RB5_SHENF8 0x40 /* enable F8000-FBFFF shadow (1) */ -# define RB5_SHENFC 0x80 /* enable FC000-FFFFF shadow (1) */ +#define REG_RB5 0x69 /* Memory Enable 4 */ +#define RB5_MASK 0xff /* 1111 1111 */ +#define RB5_SHENE0 0x01 /* enable E0000-E3FFF shadow (1) */ +#define RB5_SHENE4 0x02 /* enable E4000-E7FFF shadow (1) */ +#define RB5_SHENE8 0x04 /* enable E8000-EBFFF shadow (1) */ +#define RB5_SHENEC 0x08 /* enable EC000-EFFFF shadow (1) */ +#define RB5_SHENF0 0x10 /* enable F0000-F3FFF shadow (1) */ +#define RB5_SHENF4 0x20 /* enable F4000-F7FFF shadow (1) */ +#define RB5_SHENF8 0x40 /* enable F8000-FBFFF shadow (1) */ +#define RB5_SHENFC 0x80 /* enable FC000-FFFFF shadow (1) */ -#define REG_RB6 0x6a /* Bank 0/1 Enable */ -# define RB6_MASK 0xe0 /* 111R RRRR */ -# define RB6_BANKS 0x20 /* #banks used (1=two) */ -# define RB6_RTYPE 0xc0 /* DRAM chip size used */ -# define RTYPE_SH 6 -# define RTYPE_NONE 0 /* Disabled */ -# define RTYPE_MIXED 1 /* 64K/256K mixed (for 640K) */ -# define RTYPE_256K 2 /* 256K (default) */ -# define RTYPE_1M 3 /* 1M */ +#define REG_RB6 0x6a /* Bank 0/1 Enable */ +#define RB6_MASK 0xe0 /* 111R RRRR */ +#define RB6_BANKS 0x20 /* #banks used (1=two) */ +#define RB6_RTYPE 0xc0 /* DRAM chip size used */ +#define RTYPE_SH 6 +#define RTYPE_NONE 0 /* Disabled */ +#define RTYPE_MIXED 1 /* 64K/256K mixed (for 640K) */ +#define RTYPE_256K 2 /* 256K (default) */ +#define RTYPE_1M 3 /* 1M */ -#define REG_RB7 0x6b /* DRAM configuration */ -# define RB7_MASK 0xff /* 1111 1111 */ -# define RB7_ROMWS 0x03 /* ROM access wait states */ -# define RB7_ROMWS_SH 0 -# define ROMWS_0 0 /* 0 wait states */ -# define ROMWS_1 1 /* 1 wait states */ -# define ROMWS_2 2 /* 2 wait states */ -# define ROMWS_3 3 /* 3 wait states (default) */ -# define RB7_EMSWS 0x0c /* EMS access wait states */ -# define RB7_EMSWS_SH 2 -# define EMSWS_0 0 /* 0 wait states */ -# define EMSWS_1 1 /* 1 wait states */ -# define EMSWS_2 2 /* 2 wait states */ -# define EMSWS_3 3 /* 3 wait states (default) */ -# define RB7_EMSEN 0x10 /* enable EMS (1=on) */ -# define RB7_RAMWS 0x20 /* RAM access wait state (1=1ws) */ -# define RB7_UMAREL 0x40 /* relocate 640-1024K to 1M */ -# define RB7_PAGEEN 0x80 /* enable Page/Interleaved mode */ +#define REG_RB7 0x6b /* DRAM configuration */ +#define RB7_MASK 0xff /* 1111 1111 */ +#define RB7_ROMWS 0x03 /* ROM access wait states */ +#define RB7_ROMWS_SH 0 +#define ROMWS_0 0 /* 0 wait states */ +#define ROMWS_1 1 /* 1 wait states */ +#define ROMWS_2 2 /* 2 wait states */ +#define ROMWS_3 3 /* 3 wait states (default) */ +#define RB7_EMSWS 0x0c /* EMS access wait states */ +#define RB7_EMSWS_SH 2 +#define EMSWS_0 0 /* 0 wait states */ +#define EMSWS_1 1 /* 1 wait states */ +#define EMSWS_2 2 /* 2 wait states */ +#define EMSWS_3 3 /* 3 wait states (default) */ +#define RB7_EMSEN 0x10 /* enable EMS (1=on) */ +#define RB7_RAMWS 0x20 /* RAM access wait state (1=1ws) */ +#define RB7_UMAREL 0x40 /* relocate 640-1024K to 1M */ +#define RB7_PAGEEN 0x80 /* enable Page/Interleaved mode */ -#define REG_RB8 0x6c /* Bank 2/3 Enable */ -# define RB8_MASK 0xf0 /* 1111 RRRR */ -# define RB8_4WAY 0x10 /* enable 4-way interleave mode */ -# define RB8_BANKS 0x20 /* enable 2 banks (1) */ -# define RB8_RTYPE 0xc0 /* DRAM chip size used */ -# define RB8_RTYPE_SH 6 +#define REG_RB8 0x6c /* Bank 2/3 Enable */ +#define RB8_MASK 0xf0 /* 1111 RRRR */ +#define RB8_4WAY 0x10 /* enable 4-way interleave mode */ +#define RB8_BANKS 0x20 /* enable 2 banks (1) */ +#define RB8_RTYPE 0xc0 /* DRAM chip size used */ +#define RB8_RTYPE_SH 6 -#define REG_RB9 0x6d /* EMS base address */ -# define RB9_MASK 0xff /* 1111 1111 */ -# define RB9_BASE 0x0f /* I/O base address selection */ -# define RB9_BASE_SH 0 -# define RB9_FRAME 0xf0 /* frame address selection */ -# define RB9_FRAME_SH 4 +#define REG_RB9 0x6d /* EMS base address */ +#define RB9_MASK 0xff /* 1111 1111 */ +#define RB9_BASE 0x0f /* I/O base address selection */ +#define RB9_BASE_SH 0 +#define RB9_FRAME 0xf0 /* frame address selection */ +#define RB9_FRAME_SH 4 -#define REG_RB10 0x6e /* EMS address extension */ -# define RB10_MASK 0xff /* 1111 1111 */ -# define RB10_P3EXT 0x03 /* page 3 extension */ -# define RB10_P3EXT_SH 0 -# define PEXT_0M 0 /* page is at 0-2M */ -# define PEXT_2M 1 /* page is at 2-4M */ -# define PEXT_4M 2 /* page is at 4-6M */ -# define PEXT_6M 3 /* page is at 6-8M */ -# define RB10_P2EXT 0x0c /* page 2 extension */ -# define RB10_P2EXT_SH 2 -# define RB10_P1EXT 0x30 /* page 1 extension */ -# define RB10_P1EXT_SH 4 -# define RB10_P0EXT 0xc0 /* page 0 extension */ -# define RB10_P0EXT_SH 6 +#define REG_RB10 0x6e /* EMS address extension */ +#define RB10_MASK 0xff /* 1111 1111 */ +#define RB10_P3EXT 0x03 /* page 3 extension */ +#define RB10_P3EXT_SH 0 +#define PEXT_0M 0 /* page is at 0-2M */ +#define PEXT_2M 1 /* page is at 2-4M */ +#define PEXT_4M 2 /* page is at 4-6M */ +#define PEXT_6M 3 /* page is at 6-8M */ +#define RB10_P2EXT 0x0c /* page 2 extension */ +#define RB10_P2EXT_SH 2 +#define RB10_P1EXT 0x30 /* page 1 extension */ +#define RB10_P1EXT_SH 4 +#define RB10_P0EXT 0xc0 /* page 0 extension */ +#define RB10_P0EXT_SH 6 -#define REG_RB11 0x6f /* Miscellaneous */ -# define RB11_MASK 0xe6 /* 111R R11R */ -# define RB11_GA20 0x02 /* gate for A20 */ -# define RB11_RASTMO 0x04 /* enable RAS timeout counter */ -# define RB11_EMSLEN 0xe0 /* EMS memory chunk size */ -# define RB11_EMSLEN_SH 5 +#define REG_RB11 0x6f /* Miscellaneous */ +#define RB11_MASK 0xe6 /* 111R R11R */ +#define RB11_GA20 0x02 /* gate for A20 */ +#define RB11_RASTMO 0x04 /* enable RAS timeout counter */ +#define RB11_EMSLEN 0xe0 /* EMS memory chunk size */ +#define RB11_EMSLEN_SH 5 -typedef struct { - int8_t enabled; /* 1=ENABLED */ - char pad; - uint16_t page; /* selected page in EMS block */ - uint32_t start; /* start of EMS in RAM */ - uint8_t *addr; /* start addr in EMS RAM */ - mem_mapping_t mapping; /* mapping entry for page */ +typedef struct emspage_t { + int8_t enabled; /* 1=ENABLED */ + char pad; + uint16_t page; /* selected page in EMS block */ + uint32_t start; /* start of EMS in RAM */ + uint8_t *addr; /* start addr in EMS RAM */ + mem_mapping_t mapping; /* mapping entry for page */ } emspage_t; -typedef struct { - uint8_t regs[128]; /* all the CS8221 registers */ - uint8_t indx; /* programmed index into registers */ +typedef struct neat_t { + uint8_t regs[128]; /* all the CS8221 registers */ + uint8_t indx; /* programmed index into registers */ - char pad; + char pad; - uint16_t ems_base, /* configured base address */ - ems_oldbase; - uint32_t ems_frame, /* configured frame address */ - ems_oldframe; - uint16_t ems_size, /* EMS size in KB */ - ems_pages; /* EMS size in pages */ - emspage_t ems[EMS_MAXPAGE]; /* EMS page registers */ + uint16_t ems_base; /* configured base address */ + uint16_t ems_oldbase; + uint32_t ems_frame; /* configured frame address */ + uint32_t ems_oldframe; + uint16_t ems_size; /* EMS size in KB */ + uint16_t ems_pages; /* EMS size in pages */ + emspage_t ems[EMS_MAXPAGE]; /* EMS page registers */ } neat_t; - #ifdef ENABLE_NEAT_LOG int neat_do_log = ENABLE_NEAT_LOG; - static void neat_log(const char *fmt, ...) { - va_list ap; + va_list ap; - if (neat_do_log) - { - va_start(ap, fmt); - pclog_ex(fmt, ap); - va_end(ap); - } + if (neat_do_log) { + va_start(ap, fmt); + pclog_ex(fmt, ap); + va_end(ap); + } } #else -#define neat_log(fmt, ...) +# define neat_log(fmt, ...) #endif - /* Read one byte from paged RAM. */ static uint8_t ems_readb(uint32_t addr, void *priv) { - neat_t *dev = (neat_t *)priv; + neat_t *dev = (neat_t *) priv; uint8_t ret = 0xff; /* Grab the data. */ - ret = *(uint8_t *)(dev->ems[((addr & 0xffff) >> 14)].addr + (addr & 0x3fff)); + ret = *(uint8_t *) (dev->ems[(addr & 0xffff) >> 14].addr + (addr & 0x3fff)); - return(ret); + return ret; } /* Read one word from paged RAM. */ static uint16_t ems_readw(uint32_t addr, void *priv) { - neat_t *dev = (neat_t *)priv; + neat_t *dev = (neat_t *) priv; uint16_t ret = 0xffff; /* Grab the data. */ - ret = *(uint16_t *)(dev->ems[((addr & 0xffff) >> 14)].addr + (addr & 0x3fff)); + ret = *(uint16_t *) (dev->ems[(addr & 0xffff) >> 14].addr + (addr & 0x3fff)); - return(ret); + return ret; } /* Write one byte to paged RAM. */ static void ems_writeb(uint32_t addr, uint8_t val, void *priv) { - neat_t *dev = (neat_t *)priv; + neat_t *dev = (neat_t *) priv; /* Write the data. */ - *(uint8_t *)(dev->ems[((addr & 0xffff) >> 14)].addr + (addr & 0x3fff)) = val; + *(uint8_t *) (dev->ems[(addr & 0xffff) >> 14].addr + (addr & 0x3fff)) = val; } /* Write one word to paged RAM. */ static void ems_writew(uint32_t addr, uint16_t val, void *priv) { - neat_t *dev = (neat_t *)priv; + neat_t *dev = (neat_t *) priv; /* Write the data. */ - *(uint16_t *)(dev->ems[((addr & 0xffff) >> 14)].addr + (addr & 0x3fff)) = val; + *(uint16_t *) (dev->ems[(addr & 0xffff) >> 14].addr + (addr & 0x3fff)) = val; } /* Re-calculate the active-page physical address. */ @@ -297,36 +294,36 @@ static void ems_recalc(neat_t *dev, emspage_t *ems) { if (ems->page >= dev->ems_pages) { - /* That page does not exist. */ - ems->enabled = 0; + /* That page does not exist. */ + ems->enabled = 0; } /* Pre-calculate the page address in EMS RAM. */ ems->addr = ram + ems->start + (ems->page * EMS_PGSIZE); if (ems->enabled) { - /* Update the EMS RAM address for this page. */ - mem_mapping_set_exec(&ems->mapping, ems->addr); + /* Update the EMS RAM address for this page. */ + mem_mapping_set_exec(&ems->mapping, ems->addr); - /* Enable this page. */ - mem_mapping_enable(&ems->mapping); + /* Enable this page. */ + mem_mapping_enable(&ems->mapping); #if NEAT_DEBUG > 1 - neat_log("NEAT EMS: page %d set to %08lx, %sabled)\n", - ems->page, ems->addr-ram, ems->enabled?"en":"dis"); + neat_log("NEAT EMS: page %d set to %08lx, %sabled)\n", + ems->page, ems->addr - ram, ems->enabled ? "en" : "dis"); #endif } else { - /* Disable this page. */ - mem_mapping_disable(&ems->mapping); + /* Disable this page. */ + mem_mapping_disable(&ems->mapping); } } static void ems_write(uint16_t port, uint8_t val, void *priv) { - neat_t *dev = (neat_t *)priv; + neat_t *dev = (neat_t *) priv; emspage_t *ems; - int vpage; + int vpage; #if NEAT_DEBUG > 1 neat_log("NEAT: ems_write(%04x, %02x)\n", port, val); @@ -334,329 +331,335 @@ ems_write(uint16_t port, uint8_t val, void *priv) /* Get the viewport page number. */ vpage = (port / EMS_PGSIZE); - ems = &dev->ems[vpage]; + ems = &dev->ems[vpage]; - switch(port & 0x000f) { - case 0x0008: - case 0x0009: - ems->enabled = !!(val & 0x80); - ems->page &= 0x0180; /* clear lower bits */ - ems->page |= (val & 0x7f); /* add new bits */ - ems_recalc(dev, ems); - break; + switch (port & 0x000f) { + case 0x0008: + case 0x0009: + ems->enabled = !!(val & 0x80); + ems->page &= 0x0180; /* clear lower bits */ + ems->page |= (val & 0x7f); /* add new bits */ + ems_recalc(dev, ems); + break; + default: + break; } } static uint8_t ems_read(uint16_t port, void *priv) { - neat_t *dev = (neat_t *)priv; - uint8_t ret = 0xff; - int vpage; + const neat_t *dev = (neat_t *) priv; + uint8_t ret = 0xff; + int vpage; /* Get the viewport page number. */ vpage = (port / EMS_PGSIZE); - switch(port & 0x000f) { - case 0x0008: /* page number register */ - ret = dev->ems[vpage].page & 0x7f; - if (dev->ems[vpage].enabled) - ret |= 0x80; - break; + switch (port & 0x000f) { + case 0x0008: /* page number register */ + ret = dev->ems[vpage].page & 0x7f; + if (dev->ems[vpage].enabled) + ret |= 0x80; + break; + default: + break; } #if NEAT_DEBUG > 1 neat_log("NEAT: ems_read(%04x) = %02x\n", port, ret); #endif - return(ret); + return ret; } /* Initialize the EMS module. */ static void ems_init(neat_t *dev, int en) { - int i; + uint8_t j; /* Remove if needed. */ - if (! en) { - if (dev->ems_base > 0) for (i = 0; i < EMS_MAXPAGE; i++) { - /* Disable for now. */ - mem_mapping_disable(&dev->ems[i].mapping); + if (!en) { + if (dev->ems_base > 0) + for (uint8_t i = 0; i < EMS_MAXPAGE; i++) { + /* Disable for now. */ + mem_mapping_disable(&dev->ems[i].mapping); - /* Remove I/O handler. */ - io_removehandler(dev->ems_base + (i * EMS_PGSIZE), 2, - ems_read,NULL,NULL, ems_write,NULL,NULL, dev); - } + /* Remove I/O handler. */ + io_removehandler(dev->ems_base + (i * EMS_PGSIZE), 2, + ems_read, NULL, NULL, ems_write, NULL, NULL, dev); + } #ifdef ENABLE_NEAT_LOG - neat_log("NEAT: EMS disabled\n"); + neat_log("NEAT: EMS disabled\n"); #endif - return; + return; } /* Get configured I/O address. */ - i = (dev->regs[REG_RB9] & RB9_BASE) >> RB9_BASE_SH; - dev->ems_base = 0x0208 + (0x10 * i); + j = (dev->regs[REG_RB9] & RB9_BASE) >> RB9_BASE_SH; + dev->ems_base = 0x0208 + (0x10 * j); /* Get configured frame address. */ - i = (dev->regs[REG_RB9] & RB9_FRAME) >> RB9_FRAME_SH; - dev->ems_frame = 0xC0000 + (EMS_PGSIZE * i); + j = (dev->regs[REG_RB9] & RB9_FRAME) >> RB9_FRAME_SH; + dev->ems_frame = 0xC0000 + (EMS_PGSIZE * j); /* * For each supported page (we can have a maximum of 4), * create, initialize and disable the mappings, and set * up the I/O control handler. */ - for (i = 0; i < EMS_MAXPAGE; i++) { - /* Create and initialize a page mapping. */ - mem_mapping_add(&dev->ems[i].mapping, - dev->ems_frame + (EMS_PGSIZE*i), EMS_PGSIZE, - ems_readb, ems_readw, NULL, - ems_writeb, ems_writew, NULL, - ram, MEM_MAPPING_EXTERNAL, - dev); + for (uint8_t i = 0; i < EMS_MAXPAGE; i++) { + /* Create and initialize a page mapping. */ + mem_mapping_add(&dev->ems[i].mapping, + dev->ems_frame + (EMS_PGSIZE * i), EMS_PGSIZE, + ems_readb, ems_readw, NULL, + ems_writeb, ems_writew, NULL, + ram, MEM_MAPPING_EXTERNAL, + dev); - /* Disable for now. */ - mem_mapping_disable(&dev->ems[i].mapping); + /* Disable for now. */ + mem_mapping_disable(&dev->ems[i].mapping); - /* Set up an I/O port handler. */ - io_sethandler(dev->ems_base + (i * EMS_PGSIZE), 2, - ems_read,NULL,NULL, ems_write,NULL,NULL, dev); + /* Set up an I/O port handler. */ + io_sethandler(dev->ems_base + (i * EMS_PGSIZE), 2, + ems_read, NULL, NULL, ems_write, NULL, NULL, dev); - /* - * TODO: update the 'high_mem' mapping to reflect that we now - * have NN MB less extended memory available.. - */ + /* + * TODO: update the 'high_mem' mapping to reflect that we now + * have NN MB less extended memory available.. + */ } neat_log("NEAT: EMS enabled, I/O=%04xH, Frame=%05XH\n", - dev->ems_base, dev->ems_frame); + dev->ems_base, dev->ems_frame); } static void neat_write(uint16_t port, uint8_t val, void *priv) { - neat_t *dev = (neat_t *)priv; - uint8_t xval, *reg; - int i; + neat_t *dev = (neat_t *) priv; + uint8_t xval; + uint8_t *reg; + int i; #if NEAT_DEBUG > 2 neat_log("NEAT: write(%04x, %02x)\n", port, val); #endif switch (port) { - case 0x22: - dev->indx = val; - break; + case 0x22: + dev->indx = val; + break; - case 0x23: - reg = &dev->regs[dev->indx]; - xval = *reg ^ val; - switch (dev->indx) { - case REG_RA0: - val &= RA0_MASK; - *reg = (*reg & ~RA0_MASK) | val | \ - (RA0_REV_ID << RA0_REV_SH); + case 0x23: + reg = &dev->regs[dev->indx]; + xval = *reg ^ val; + switch (dev->indx) { + case REG_RA0: + val &= RA0_MASK; + *reg = (*reg & ~RA0_MASK) | val | (RA0_REV_ID << RA0_REV_SH); #if NEAT_DEBUG > 1 - neat_log("NEAT: RA0=%02x(%02x)\n", val, *reg); + neat_log("NEAT: RA0=%02x(%02x)\n", val, *reg); #endif - break; + break; - case REG_RA1: - val &= RA1_MASK; - *reg = (*reg & ~RA1_MASK) | val; + case REG_RA1: + val &= RA1_MASK; + *reg = (*reg & ~RA1_MASK) | val; #if NEAT_DEBUG > 1 - neat_log("NEAT: RA1=%02x(%02x)\n", val, *reg); + neat_log("NEAT: RA1=%02x(%02x)\n", val, *reg); #endif - break; + break; - case REG_RA2: - val &= RA2_MASK; - *reg = (*reg & ~RA2_MASK) | val; + case REG_RA2: + val &= RA2_MASK; + *reg = (*reg & ~RA2_MASK) | val; #if NEAT_DEBUG > 1 - neat_log("NEAT: RA2=%02x(%02x)\n", val, *reg); + neat_log("NEAT: RA2=%02x(%02x)\n", val, *reg); #endif - break; + break; - case REG_RB0: - val &= RB0_MASK; - *reg = (*reg & ~RB0_MASK) | val | \ - (RB0_REV_ID << RB0_REV_SH); + case REG_RB0: + val &= RB0_MASK; + *reg = (*reg & ~RB0_MASK) | val | (RB0_REV_ID << RB0_REV_SH); #if NEAT_DEBUG > 1 - neat_log("NEAT: RB0=%02x(%02x)\n", val, *reg); + neat_log("NEAT: RB0=%02x(%02x)\n", val, *reg); #endif - break; + break; - case REG_RB1: - val &= RB1_MASK; - *reg = (*reg & ~RB1_MASK) | val; + case REG_RB1: + val &= RB1_MASK; + *reg = (*reg & ~RB1_MASK) | val; #if NEAT_DEBUG > 1 - neat_log("NEAT: RB1=%02x(%02x)\n", val, *reg); + neat_log("NEAT: RB1=%02x(%02x)\n", val, *reg); #endif - break; + break; - case REG_RB2: - val &= RB2_MASK; - *reg = (*reg & ~RB2_MASK) | val; + case REG_RB2: + val &= RB2_MASK; + *reg = (*reg & ~RB2_MASK) | val; #if NEAT_DEBUG > 1 - neat_log("NEAT: RB2=%02x(%02x)\n", val, *reg); + neat_log("NEAT: RB2=%02x(%02x)\n", val, *reg); #endif - break; + break; - case REG_RB3: - val &= RB3_MASK; - *reg = (*reg & ~RB3_MASK) | val; + case REG_RB3: + val &= RB3_MASK; + *reg = (*reg & ~RB3_MASK) | val; #if NEAT_DEBUG > 1 - neat_log("NEAT: RB3=%02x(%02x)\n", val, *reg); + neat_log("NEAT: RB3=%02x(%02x)\n", val, *reg); #endif - break; + break; - case REG_RB4: - val &= RB4_MASK; - *reg = (*reg & ~RB4_MASK) | val; + case REG_RB4: + val &= RB4_MASK; + *reg = (*reg & ~RB4_MASK) | val; #if NEAT_DEBUG > 1 - neat_log("NEAT: RB4=%02x(%02x)\n", val, *reg); + neat_log("NEAT: RB4=%02x(%02x)\n", val, *reg); #endif - break; + break; - case REG_RB5: - val &= RB5_MASK; - *reg = (*reg & ~RB5_MASK) | val; + case REG_RB5: + val &= RB5_MASK; + *reg = (*reg & ~RB5_MASK) | val; #if NEAT_DEBUG > 1 - neat_log("NEAT: RB5=%02x(%02x)\n", val, *reg); + neat_log("NEAT: RB5=%02x(%02x)\n", val, *reg); #endif - break; + break; - case REG_RB6: - val &= RB6_MASK; - *reg = (*reg & ~RB6_MASK) | val; + case REG_RB6: + val &= RB6_MASK; + *reg = (*reg & ~RB6_MASK) | val; #if NEAT_DEBUG > 1 - neat_log("NEAT: RB6=%02x(%02x)\n", val, *reg); + neat_log("NEAT: RB6=%02x(%02x)\n", val, *reg); #endif - break; + break; - case REG_RB7: - val &= RB7_MASK; - *reg = val; + case REG_RB7: + val &= RB7_MASK; + *reg = val; #if NEAT_DEBUG > 1 - neat_log("NEAT: RB7=%02x(%02x)\n", val, *reg); + neat_log("NEAT: RB7=%02x(%02x)\n", val, *reg); #endif - if (val & RB7_EMSEN) - ems_init(dev, 1); - else if (xval & RB7_EMSEN) - ems_init(dev, 0); + if (val & RB7_EMSEN) + ems_init(dev, 1); + else if (xval & RB7_EMSEN) + ems_init(dev, 0); - if (xval & RB7_UMAREL) { - if (val & RB7_UMAREL) - mem_remap_top(384); - else - mem_remap_top(0); - } - break; + if (xval & RB7_UMAREL) { + if (val & RB7_UMAREL) + mem_remap_top(384); + else + mem_remap_top(0); + } + break; - case REG_RB8: - val &= RB8_MASK; - *reg = (*reg & ~RB8_MASK) | val; + case REG_RB8: + val &= RB8_MASK; + *reg = (*reg & ~RB8_MASK) | val; #if NEAT_DEBUG > 1 - neat_log("NEAT: RB8=%02x(%02x)\n", val, *reg); + neat_log("NEAT: RB8=%02x(%02x)\n", val, *reg); #endif - break; + break; - case REG_RB9: - val &= RB9_MASK; - *reg = (*reg & ~RB9_MASK) | val; + case REG_RB9: + val &= RB9_MASK; + *reg = (*reg & ~RB9_MASK) | val; #if NEAT_DEBUG > 1 - neat_log("NEAT: RB9=%02x(%02x)\n", val, *reg); + neat_log("NEAT: RB9=%02x(%02x)\n", val, *reg); #endif - if (dev->regs[REG_RB7] & RB7_EMSEN) { - ems_init(dev, 0); - ems_init(dev, 1); - } - break; + if (dev->regs[REG_RB7] & RB7_EMSEN) { + ems_init(dev, 0); + ems_init(dev, 1); + } + break; - case REG_RB10: - val &= RB10_MASK; - *reg = (*reg & ~RB10_MASK) | val; + case REG_RB10: + val &= RB10_MASK; + *reg = (*reg & ~RB10_MASK) | val; #if NEAT_DEBUG > 1 - neat_log("NEAT: RB10=%02x(%02x)\n", val, *reg); + neat_log("NEAT: RB10=%02x(%02x)\n", val, *reg); #endif - dev->ems[3].start = ((val & RB10_P3EXT) >> RB10_P3EXT_SH) << 21; - dev->ems[2].start = ((val & RB10_P2EXT) >> RB10_P2EXT_SH) << 21; - dev->ems[1].start = ((val & RB10_P1EXT) >> RB10_P1EXT_SH) << 21; - dev->ems[0].start = ((val & RB10_P0EXT) >> RB10_P0EXT_SH) << 21; - for (i = 0; i < EMS_MAXPAGE; i++) - ems_recalc(dev, &dev->ems[i]); - break; + dev->ems[3].start = ((val & RB10_P3EXT) >> RB10_P3EXT_SH) << 21; + dev->ems[2].start = ((val & RB10_P2EXT) >> RB10_P2EXT_SH) << 21; + dev->ems[1].start = ((val & RB10_P1EXT) >> RB10_P1EXT_SH) << 21; + dev->ems[0].start = ((val & RB10_P0EXT) >> RB10_P0EXT_SH) << 21; + for (i = 0; i < EMS_MAXPAGE; i++) + ems_recalc(dev, &dev->ems[i]); + break; - case REG_RB11: - val &= RB11_MASK; - *reg = (*reg & ~RB11_MASK) | val; + case REG_RB11: + val &= RB11_MASK; + *reg = (*reg & ~RB11_MASK) | val; #if NEAT_DEBUG > 1 - neat_log("NEAT: RB11=%02x(%02x)\n", val, *reg); + neat_log("NEAT: RB11=%02x(%02x)\n", val, *reg); #endif - i = (val & RB11_EMSLEN) >> RB11_EMSLEN_SH; - switch(i) { - case 0: /* "less than 2MB" */ - dev->ems_size = 512; - break; + i = (val & RB11_EMSLEN) >> RB11_EMSLEN_SH; + switch (i) { + case 0: /* "less than 2MB" */ + dev->ems_size = 512; + break; - case 1: /* 1 MB */ - case 2: /* 2 MB */ - case 3: /* 3 MB */ - case 4: /* 4 MB */ - case 5: /* 5 MB */ - case 6: /* 6 MB */ - case 7: /* 7 MB */ - dev->ems_size = i << 10; - break; - } - dev->ems_pages = (dev->ems_size << 10) / EMS_PGSIZE; - if (dev->regs[REG_RB7] & RB7_EMSEN) { - neat_log("NEAT: EMS %iKB (%i pages)\n", - dev->ems_size, dev->ems_pages); - } - break; + case 1: /* 1 MB */ + case 2: /* 2 MB */ + case 3: /* 3 MB */ + case 4: /* 4 MB */ + case 5: /* 5 MB */ + case 6: /* 6 MB */ + case 7: /* 7 MB */ + dev->ems_size = i << 10; + break; + default: + break; + } + dev->ems_pages = (dev->ems_size << 10) / EMS_PGSIZE; + if (dev->regs[REG_RB7] & RB7_EMSEN) { + neat_log("NEAT: EMS %iKB (%i pages)\n", + dev->ems_size, dev->ems_pages); + } + break; - default: - neat_log("NEAT: inv write to reg %02x (%02x)\n", - dev->indx, val); - break; - } - break; + default: + neat_log("NEAT: inv write to reg %02x (%02x)\n", + dev->indx, val); + break; + } + break; + default: + break; } } - static uint8_t neat_read(uint16_t port, void *priv) { - neat_t *dev = (neat_t *)priv; - uint8_t ret = 0xff; + const neat_t *dev = (neat_t *) priv; + uint8_t ret = 0xff; switch (port) { - case 0x22: - ret = dev->indx; - break; + case 0x22: + ret = dev->indx; + break; - case 0x23: - ret = dev->regs[dev->indx]; - break; + case 0x23: + ret = dev->regs[dev->indx]; + break; - default: - break; + default: + break; } #if NEAT_DEBUG > 2 neat_log("NEAT: read(%04x) = %02x\n", port, ret); #endif - return(ret); + return ret; } - static void neat_close(void *priv) { @@ -665,21 +668,20 @@ neat_close(void *priv) free(dev); } - static void * -neat_init(const device_t *info) +neat_init(UNUSED(const device_t *info)) { neat_t *dev; - int i; + uint8_t dram_mode = 0; /* Create an instance. */ - dev = (neat_t *)malloc(sizeof(neat_t)); + dev = (neat_t *) malloc(sizeof(neat_t)); memset(dev, 0x00, sizeof(neat_t)); /* Initialize some of the registers to specific defaults. */ - for (i = REG_RA0; i <= REG_RB11; i++) { - dev->indx = i; - neat_write(0x0023, 0x00, dev); + for (uint8_t i = REG_RA0; i <= REG_RB11; i++) { + dev->indx = i; + neat_write(0x0023, 0x00, dev); } /* @@ -689,148 +691,150 @@ neat_init(const device_t *info) * TODO: We might also want to set 'valid' waitstate * bits, based on our cpu speed. */ - i = 0; - switch(mem_size) { - case 512: /* 512KB */ - /* 256K, 0, 0, 0 */ - dev->regs[REG_RB6] &= ~RB6_BANKS; /* one bank */ - dev->regs[REG_RB6] |= (RTYPE_256K<regs[REG_RB8] &= ~RB8_BANKS; /* one bank */ - dev->regs[REG_RB8] |= (RTYPE_NONE<regs[REG_RB6] &= ~RB6_BANKS; /* one bank */ + dev->regs[REG_RB6] |= (RTYPE_256K << RTYPE_SH); /* 256K */ + dev->regs[REG_RB8] &= ~RB8_BANKS; /* one bank */ + dev->regs[REG_RB8] |= (RTYPE_NONE << RTYPE_SH); /* NONE */ + dram_mode = 2; + break; - case 640: /* 640KB */ - /* 256K, 64K, 0, 0 */ - dev->regs[REG_RB6] |= RB6_BANKS; /* two banks */ - dev->regs[REG_RB6] |= (RTYPE_MIXED<regs[REG_RB8] &= ~RB8_BANKS; /* one bank */ - dev->regs[REG_RB8] |= (RTYPE_NONE<regs[REG_RB6] |= RB6_BANKS; /* two banks */ + dev->regs[REG_RB6] |= (RTYPE_MIXED << RTYPE_SH); /* mixed */ + dev->regs[REG_RB8] &= ~RB8_BANKS; /* one bank */ + dev->regs[REG_RB8] |= (RTYPE_NONE << RTYPE_SH); /* NONE */ + dram_mode = 4; + break; - case 1024: /* 1MB */ - /* 256K, 256K, 0, 0 */ - dev->regs[REG_RB6] |= RB6_BANKS; /* two banks */ - dev->regs[REG_RB6] |= (RTYPE_256K<regs[REG_RB8] &= ~RB8_BANKS; /* one bank */ - dev->regs[REG_RB8] |= (RTYPE_NONE<regs[REG_RB6] |= RB6_BANKS; /* two banks */ + dev->regs[REG_RB6] |= (RTYPE_256K << RTYPE_SH); /* 256K */ + dev->regs[REG_RB8] &= ~RB8_BANKS; /* one bank */ + dev->regs[REG_RB8] |= (RTYPE_NONE << RTYPE_SH); /* NONE */ + dram_mode = 5; + break; - case 1536: /* 1.5MB */ - /* 256K, 256K, 256K, 0 */ - dev->regs[REG_RB6] |= RB6_BANKS; /* two banks */ - dev->regs[REG_RB6] |= (RTYPE_256K<regs[REG_RB8] &= ~RB8_BANKS; /* one bank */ - dev->regs[REG_RB8] |= (RTYPE_256K<regs[REG_RB6] |= RB6_BANKS; /* two banks */ + dev->regs[REG_RB6] |= (RTYPE_256K << RTYPE_SH); /* 256K */ + dev->regs[REG_RB8] &= ~RB8_BANKS; /* one bank */ + dev->regs[REG_RB8] |= (RTYPE_256K << RTYPE_SH); /* 256K */ + dram_mode = 7; + break; - case 1664: /* 1.64MB */ - /* 256K, 64K, 256K, 256K */ - dev->regs[REG_RB6] |= RB6_BANKS; /* two banks */ - dev->regs[REG_RB6] |= (RTYPE_MIXED<regs[REG_RB8] |= RB8_BANKS; /* two banks */ - dev->regs[REG_RB8] |= (RTYPE_256K<regs[REG_RB6] |= RB6_BANKS; /* two banks */ + dev->regs[REG_RB6] |= (RTYPE_MIXED << RTYPE_SH); /* mixed */ + dev->regs[REG_RB8] |= RB8_BANKS; /* two banks */ + dev->regs[REG_RB8] |= (RTYPE_256K << RTYPE_SH); /* 256K */ + dram_mode = 10; + break; - case 2048: /* 2MB */ + case 2048: /* 2MB */ #if 1 - /* 256K, 256K, 256K, 256K */ - dev->regs[REG_RB6] |= RB6_BANKS; /* two banks */ - dev->regs[REG_RB6] |= (RTYPE_256K<regs[REG_RB8] |= RB8_BANKS; /* two banks */ - dev->regs[REG_RB8] |= (RTYPE_256K<regs[REG_RB8] |= RB8_4WAY; /* 4way intl */ - i = 11; + /* 256K, 256K, 256K, 256K */ + dev->regs[REG_RB6] |= RB6_BANKS; /* two banks */ + dev->regs[REG_RB6] |= (RTYPE_256K << RTYPE_SH); /* 256K */ + dev->regs[REG_RB8] |= RB8_BANKS; /* two banks */ + dev->regs[REG_RB8] |= (RTYPE_256K << RTYPE_SH); /* 256K */ + dev->regs[REG_RB8] |= RB8_4WAY; /* 4way intl */ + dram_mode = 11; #else - /* 1M, 0, 0, 0 */ - dev->regs[REG_RB6] &= ~RB6_BANKS; /* one bank */ - dev->regs[REG_RB6] |= (RTYPE_1M<regs[REG_RB8] &= ~RB8_BANKS; /* one bank */ - dev->regs[REG_RB8] |= (RTYPE_NONE<regs[REG_RB6] &= ~RB6_BANKS; /* one bank */ + dev->regs[REG_RB6] |= (RTYPE_1M << RTYPE_SH); /* 1M */ + dev->regs[REG_RB8] &= ~RB8_BANKS; /* one bank */ + dev->regs[REG_RB8] |= (RTYPE_NONE << RTYPE_SH); /* NONE */ + dram_mode = 3; #endif - break; + break; - case 3072: /* 3MB */ - /* 256K, 256K, 1M, 0 */ - dev->regs[REG_RB6] |= RB6_BANKS; /* two banks */ - dev->regs[REG_RB6] |= (RTYPE_256K<regs[REG_RB8] &= ~RB8_BANKS; /* one bank */ - dev->regs[REG_RB8] |= (RTYPE_1M<regs[REG_RB6] |= RB6_BANKS; /* two banks */ + dev->regs[REG_RB6] |= (RTYPE_256K << RTYPE_SH); /* 256K */ + dev->regs[REG_RB8] &= ~RB8_BANKS; /* one bank */ + dev->regs[REG_RB8] |= (RTYPE_1M << RTYPE_SH); /* 1M */ + dram_mode = 8; + break; - case 4096: /* 4MB */ - /* 1M, 1M, 0, 0 */ - dev->regs[REG_RB6] |= RB6_BANKS; /* two banks */ - dev->regs[REG_RB6] |= (RTYPE_1M<regs[REG_RB8] &= ~RB8_BANKS; /* one bank */ - dev->regs[REG_RB8] |= (RTYPE_NONE<regs[REG_RB6] |= RB6_BANKS; /* two banks */ + dev->regs[REG_RB6] |= (RTYPE_1M << RTYPE_SH); /* 1M */ + dev->regs[REG_RB8] &= ~RB8_BANKS; /* one bank */ + dev->regs[REG_RB8] |= (RTYPE_NONE << RTYPE_SH); /* NONE */ + dram_mode = 6; + break; - case 4224: /* 4.64MB */ - /* 256K, 64K, 1M, 1M */ - dev->regs[REG_RB6] |= RB6_BANKS; /* two banks */ - dev->regs[REG_RB6] |= (RTYPE_MIXED<regs[REG_RB8] |= RB8_BANKS; /* two banks */ - dev->regs[REG_RB8] |= (RTYPE_1M<regs[REG_RB6] |= RB6_BANKS; /* two banks */ + dev->regs[REG_RB6] |= (RTYPE_MIXED << RTYPE_SH); /* mixed */ + dev->regs[REG_RB8] |= RB8_BANKS; /* two banks */ + dev->regs[REG_RB8] |= (RTYPE_1M << RTYPE_SH); /* 1M */ + dram_mode = 12; + break; - case 5120: /* 5MB */ - /* 256K, 256K, 1M, 1M */ - dev->regs[REG_RB6] |= RB6_BANKS; /* two banks */ - dev->regs[REG_RB6] |= (RTYPE_256K<regs[REG_RB8] |= RB8_BANKS; /* two banks */ - dev->regs[REG_RB8] |= (RTYPE_1M<regs[REG_RB6] |= RB6_BANKS; /* two banks */ + dev->regs[REG_RB6] |= (RTYPE_256K << RTYPE_SH); /* 256K */ + dev->regs[REG_RB8] |= RB8_BANKS; /* two banks */ + dev->regs[REG_RB8] |= (RTYPE_1M << RTYPE_SH); /* 1M */ + dram_mode = 13; + break; - case 6144: /* 6MB */ - /* 1M, 1M, 1M, 0 */ - dev->regs[REG_RB6] |= RB6_BANKS; /* two banks */ - dev->regs[REG_RB6] |= (RTYPE_1M<regs[REG_RB8] &= ~RB8_BANKS; /* one bank */ - dev->regs[REG_RB8] |= (RTYPE_1M<regs[REG_RB6] |= RB6_BANKS; /* two banks */ + dev->regs[REG_RB6] |= (RTYPE_1M << RTYPE_SH); /* 1M */ + dev->regs[REG_RB8] &= ~RB8_BANKS; /* one bank */ + dev->regs[REG_RB8] |= (RTYPE_1M << RTYPE_SH); /* 1M */ + dram_mode = 9; + break; - case 8192: /* 8MB */ - /* 1M, 1M, 1M, 1M */ - dev->regs[REG_RB6] |= RB6_BANKS; /* two banks */ - dev->regs[REG_RB6] |= (RTYPE_1M<regs[REG_RB8] |= RB8_BANKS; /* two banks */ - dev->regs[REG_RB8] |= (RTYPE_1M<regs[REG_RB8] |= RB8_4WAY; /* 4way intl */ - i = 14; - break; + case 8192: /* 8MB */ + /* 1M, 1M, 1M, 1M */ + dev->regs[REG_RB6] |= RB6_BANKS; /* two banks */ + dev->regs[REG_RB6] |= (RTYPE_1M << RTYPE_SH); /* 1M */ + dev->regs[REG_RB8] |= RB8_BANKS; /* two banks */ + dev->regs[REG_RB8] |= (RTYPE_1M << RTYPE_SH); /* 1M */ + dev->regs[REG_RB8] |= RB8_4WAY; /* 4way intl */ + dram_mode = 14; + break; - default: - neat_log("NEAT: **INVALID DRAM SIZE %iKB !**\n", mem_size); + default: + neat_log("NEAT: **INVALID DRAM SIZE %iKB !**\n", mem_size); } - if (i > 0) { - neat_log("NEAT: using DRAM mode #%i (mem=%iKB)\n", i, mem_size); + if (dram_mode > 0) { + neat_log("NEAT: using DRAM mode #%i (mem=%iKB)\n", i, mem_size); } /* Set up an I/O handler for the chipset. */ io_sethandler(0x0022, 2, - neat_read,NULL,NULL, neat_write,NULL,NULL, dev); + neat_read, NULL, NULL, neat_write, NULL, NULL, dev); return dev; } - const device_t neat_device = { - "C&T CS8121 (NEAT)", - "neat", - 0, - 0, - neat_init, neat_close, NULL, - { NULL }, NULL, NULL, - NULL + .name = "C&T CS8121 (NEAT)", + .internal_name = "neat", + .flags = 0, + .local = 0, + .init = neat_init, + .close = neat_close, + .reset = NULL, + { .available = NULL }, + .speed_changed = NULL, + .force_redraw = NULL, + .config = NULL }; diff --git a/src/chipset/olivetti_eva.c b/src/chipset/olivetti_eva.c index 2858307d4..1f5eacc6c 100644 --- a/src/chipset/olivetti_eva.c +++ b/src/chipset/olivetti_eva.c @@ -1,22 +1,22 @@ /* - * 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. + * 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. + * This file is part of the 86Box distribution. + * + * Implementation of the Olivetti EVA (98/86) Gate Array. + * + * Note: This chipset has no datasheet, everything were done via + * reverse engineering the BIOS of various machines using it. * - * Implementation of the Olivetti EVA (98/86) Gate Array. * - * Note: This chipset has no datasheet, everything were done via - * reverse engineering the BIOS of various machines using it. * * Authors: EngiNerd * - * Copyright 2020-2021 EngiNerd + * Copyright 2020-2021 EngiNerd */ - - #include #include #include @@ -32,16 +32,17 @@ #include <86box/chipset.h> #include <86box/video.h> #include <86box/mem.h> +#include <86box/plat_unused.h> -typedef struct -{ - uint8_t reg_065; - uint8_t reg_067; +typedef struct olivetti_eva_t { + uint8_t reg_065; + uint8_t reg_067; uint8_t reg_069; } olivetti_eva_t; #ifdef ENABLE_OLIVETTI_EVA_LOG int olivetti_eva_do_log = ENABLE_OLIVETTI_EVA_LOG; + static void olivetti_eva_log(const char *fmt, ...) { @@ -50,11 +51,11 @@ olivetti_eva_log(const char *fmt, ...) if (olivetti_eva_do_log) { va_start(ap, fmt); pclog_ex(fmt, ap); - va_end(ap); + va_end(ap); } } #else -#define olivetti_eva_log(fmt, ...) +# define olivetti_eva_log(fmt, ...) #endif static void @@ -73,23 +74,27 @@ olivetti_eva_write(uint16_t addr, uint8_t val, void *priv) case 0x069: dev->reg_069 = val; /* - * Unfortunately, if triggered, the BIOS remapping function fails causing + * Unfortunately, if triggered, the BIOS remapping function fails causing * a fatal error. Therefore, this code section is currently commented. */ - // if (val & 1){ - // /* - // * Set the register to 7 or above for the BIOS to trigger the - // * memory remapping function if shadowing is active. - // */ - // dev->reg_069 = 0x7; - // } - // if (val & 8) { - // /* - // * Activate shadowing for region e0000-fffff - // */ - // mem_remap_top(256); - // mem_set_mem_state_both(0xa0000, 0x60000, MEM_READ_INTERNAL | MEM_WRITE_INTERNAL); - // } +#if 0 + if (val & 1) { + /* + * Set the register to 7 or above for the BIOS to trigger the + * memory remapping function if shadowing is active. + */ + dev->reg_069 = 0x7; + } + if (val & 8) { + /* + * Activate shadowing for region e0000-fffff + */ + mem_remap_top(256); + mem_set_mem_state_both(0xa0000, 0x60000, MEM_READ_INTERNAL | MEM_WRITE_INTERNAL); + } +#endif + break; + default: break; } } @@ -97,8 +102,9 @@ olivetti_eva_write(uint16_t addr, uint8_t val, void *priv) static uint8_t olivetti_eva_read(uint16_t addr, void *priv) { - olivetti_eva_t *dev = (olivetti_eva_t *) priv; - uint8_t ret = 0xff; + const olivetti_eva_t *dev = (olivetti_eva_t *) priv; + uint8_t ret = 0xff; + switch (addr) { case 0x065: ret = dev->reg_065; @@ -110,12 +116,13 @@ olivetti_eva_read(uint16_t addr, void *priv) case 0x069: ret = dev->reg_069; break; + default: + break; } olivetti_eva_log("Olivetti EVA Gate Array: Read %02x at %02x\n", ret, addr); return ret; } - static void olivetti_eva_close(void *priv) { @@ -125,28 +132,28 @@ olivetti_eva_close(void *priv) } static void * -olivetti_eva_init(const device_t *info) +olivetti_eva_init(UNUSED(const device_t *info)) { olivetti_eva_t *dev = (olivetti_eva_t *) malloc(sizeof(olivetti_eva_t)); memset(dev, 0, sizeof(olivetti_eva_t)); - + /* GA98 registers */ dev->reg_065 = 0x00; - + /* RAM page registers: never read, only set */ dev->reg_067 = 0x00; - + /* RAM enable registers */ dev->reg_069 = 0x0; - + io_sethandler(0x0065, 0x0001, olivetti_eva_read, NULL, NULL, olivetti_eva_write, NULL, NULL, dev); io_sethandler(0x0067, 0x0001, olivetti_eva_read, NULL, NULL, olivetti_eva_write, NULL, NULL, dev); io_sethandler(0x0069, 0x0001, olivetti_eva_read, NULL, NULL, olivetti_eva_write, NULL, NULL, dev); - + /* When shadowing is not enabled in BIOS, all upper memory is available as XMS */ mem_remap_top(384); - - /* + + /* * Default settings when NVRAM is cleared activate shadowing. * Thus, to avoid boot errors, remap only 256k from UMB to XMS. * Remove this block once BIOS memory remapping works. @@ -157,11 +164,15 @@ olivetti_eva_init(const device_t *info) } const device_t olivetti_eva_device = { - "Olivetti EVA Gate Array", - "olivetta_eva", - 0, - 0, - olivetti_eva_init, olivetti_eva_close, NULL, - { NULL }, NULL, NULL, - NULL + .name = "Olivetti EVA Gate Array", + .internal_name = "olivetta_eva", + .flags = 0, + .local = 0, + .init = olivetti_eva_init, + .close = olivetti_eva_close, + .reset = NULL, + { .available = NULL }, + .speed_changed = NULL, + .force_redraw = NULL, + .config = NULL }; diff --git a/src/chipset/opti283.c b/src/chipset/opti283.c index d02ea4add..1fa59f2f0 100644 --- a/src/chipset/opti283.c +++ b/src/chipset/opti283.c @@ -1,20 +1,21 @@ /* - * 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. + * 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. + * This file is part of the 86Box distribution. * - * Implementation of the OPTi 82C283 chipset. + * Implementation of the OPTi 82C283 chipset. * - * Authors: Tiseno100, - * Miran Grca, * - * Copyright 2021 Tiseno100. - * Copyright 2021 Miran Grca. + * + * Authors: Tiseno100, + * Miran Grca, + * + * Copyright 2021 Tiseno100. + * Copyright 2021 Miran Grca. */ - #include #include #include @@ -28,9 +29,10 @@ #include <86box/io.h> #include <86box/device.h> #include <86box/mem.h> +#include <86box/plat_fallthrough.h> +#include <86box/plat_unused.h> #include <86box/chipset.h> - #ifdef ENABLE_OPTI283_LOG int opti283_do_log = ENABLE_OPTI283_LOG; @@ -39,241 +41,236 @@ opti283_log(const char *fmt, ...) { va_list ap; - if (opti283_do_log) - { + if (opti283_do_log) { va_start(ap, fmt); pclog_ex(fmt, ap); va_end(ap); } } #else -#define opti283_log(fmt, ...) +# define opti283_log(fmt, ...) #endif - -typedef struct -{ - uint32_t phys, virt; +typedef struct mem_remapping_t { + uint32_t phys; + uint32_t virt; } mem_remapping_t; - -typedef struct -{ - uint8_t index, shadow_high, - regs[256]; - mem_remapping_t mem_remappings[2]; - mem_mapping_t mem_mappings[2]; +typedef struct opti283_t { + uint8_t index; + uint8_t shadow_high; + uint8_t regs[256]; + mem_remapping_t mem_remappings[2]; + mem_mapping_t mem_mappings[2]; } opti283_t; - static uint8_t opti283_read_remapped_ram(uint32_t addr, void *priv) { - mem_remapping_t *dev = (mem_remapping_t *) priv; + const mem_remapping_t *dev = (mem_remapping_t *) priv; return mem_read_ram((addr - dev->virt) + dev->phys, priv); } - static uint16_t opti283_read_remapped_ramw(uint32_t addr, void *priv) { - mem_remapping_t *dev = (mem_remapping_t *) priv; + const mem_remapping_t *dev = (mem_remapping_t *) priv; return mem_read_ramw((addr - dev->virt) + dev->phys, priv); } - static uint32_t opti283_read_remapped_raml(uint32_t addr, void *priv) { - mem_remapping_t *dev = (mem_remapping_t *) priv; + const mem_remapping_t *dev = (mem_remapping_t *) priv; return mem_read_raml((addr - dev->virt) + dev->phys, priv); } - static void opti283_write_remapped_ram(uint32_t addr, uint8_t val, void *priv) { - mem_remapping_t *dev = (mem_remapping_t *) priv; + const mem_remapping_t *dev = (mem_remapping_t *) priv; mem_write_ram((addr - dev->virt) + dev->phys, val, priv); } - static void opti283_write_remapped_ramw(uint32_t addr, uint16_t val, void *priv) { - mem_remapping_t *dev = (mem_remapping_t *) priv; + const mem_remapping_t *dev = (mem_remapping_t *) priv; mem_write_ramw((addr - dev->virt) + dev->phys, val, priv); } - static void opti283_write_remapped_raml(uint32_t addr, uint32_t val, void *priv) { - mem_remapping_t *dev = (mem_remapping_t *) priv; + const mem_remapping_t *dev = (mem_remapping_t *) priv; mem_write_raml((addr - dev->virt) + dev->phys, val, priv); } - static void opti283_shadow_recalc(opti283_t *dev) { - uint32_t i, base; + uint32_t base; uint32_t rbase; - uint8_t sh_enable, sh_mode; - uint8_t rom, sh_copy; + uint8_t sh_enable; + uint8_t sh_mode; + uint8_t rom; + uint8_t sh_copy; shadowbios = shadowbios_write = 0; - dev->shadow_high = 0; + dev->shadow_high = 0; opti283_log("OPTI 283: %02X %02X %02X %02X\n", dev->regs[0x11], dev->regs[0x12], dev->regs[0x13], dev->regs[0x14]); if (dev->regs[0x11] & 0x80) { - mem_set_mem_state_both(0xf0000, 0x10000, MEM_READ_EXTANY | MEM_WRITE_INTERNAL); - opti283_log("OPTI 283: F0000-FFFFF READ_EXTANY, WRITE_INTERNAL\n"); - shadowbios_write = 1; + mem_set_mem_state_both(0xf0000, 0x10000, MEM_READ_EXTANY | MEM_WRITE_INTERNAL); + opti283_log("OPTI 283: F0000-FFFFF READ_EXTANY, WRITE_INTERNAL\n"); + shadowbios_write = 1; } else { - shadowbios = 1; - if (dev->regs[0x14] & 0x80) { - mem_set_mem_state_both(0xf0000, 0x01000, MEM_READ_INTERNAL | MEM_WRITE_INTERNAL); - opti283_log("OPTI 283: F0000-F0FFF READ_INTERNAL, WRITE_INTERNAL\n"); - shadowbios_write = 1; - } else { - mem_set_mem_state_both(0xf0000, 0x01000, MEM_READ_INTERNAL | MEM_WRITE_DISABLED); - opti283_log("OPTI 283: F0000-F0FFF READ_INTERNAL, WRITE_DISABLED\n"); - } + shadowbios = 1; + if (dev->regs[0x14] & 0x80) { + mem_set_mem_state_both(0xf0000, 0x01000, MEM_READ_INTERNAL | MEM_WRITE_INTERNAL); + opti283_log("OPTI 283: F0000-F0FFF READ_INTERNAL, WRITE_INTERNAL\n"); + shadowbios_write = 1; + } else { + mem_set_mem_state_both(0xf0000, 0x01000, MEM_READ_INTERNAL | MEM_WRITE_DISABLED); + opti283_log("OPTI 283: F0000-F0FFF READ_INTERNAL, WRITE_DISABLED\n"); + } - mem_set_mem_state_both(0xf1000, 0x0f000, MEM_READ_INTERNAL | MEM_WRITE_DISABLED); - opti283_log("OPTI 283: F1000-FFFFF READ_INTERNAL, WRITE_DISABLED\n"); + mem_set_mem_state_both(0xf1000, 0x0f000, MEM_READ_INTERNAL | MEM_WRITE_DISABLED); + opti283_log("OPTI 283: F1000-FFFFF READ_INTERNAL, WRITE_DISABLED\n"); } sh_copy = dev->regs[0x11] & 0x08; - for (i = 0; i < 12; i++) { - base = 0xc0000 + (i << 14); - if (i >= 4) - sh_enable = dev->regs[0x12] & (1 << (i - 4)); - else - sh_enable = dev->regs[0x13] & (1 << (i + 4)); - sh_mode = dev->regs[0x11] & (1 << (i >> 2)); - rom = dev->regs[0x11] & (1 << ((i >> 2) + 4)); - opti283_log("OPTI 283: %i/%08X: %i, %i, %i\n", i, base, (i >= 4) ? (1 << (i - 4)) : (1 << (i + 4)), (1 << (i >> 2)), (1 << ((i >> 2) + 4))); + for (uint8_t i = 0; i < 12; i++) { + base = 0xc0000 + (i << 14); + if (i >= 4) + sh_enable = dev->regs[0x12] & (1 << (i - 4)); + else + sh_enable = dev->regs[0x13] & (1 << (i + 4)); + sh_mode = dev->regs[0x11] & (1 << (i >> 2)); + rom = dev->regs[0x11] & (1 << ((i >> 2) + 4)); + opti283_log("OPTI 283: %i/%08X: %i, %i, %i\n", i, base, (i >= 4) ? (1 << (i - 4)) : (1 << (i + 4)), (1 << (i >> 2)), (1 << ((i >> 2) + 4))); - if (sh_enable && rom) { - if (base >= 0x000e0000) - shadowbios |= 1; - if (base >= 0x000d0000) - dev->shadow_high |= 1; + if (sh_enable && rom) { + if (base >= 0x000e0000) + shadowbios |= 1; + if (base >= 0x000d0000) + dev->shadow_high |= 1; - if (sh_mode) { - mem_set_mem_state_both(base, 0x4000, MEM_READ_INTERNAL | MEM_WRITE_DISABLED); - opti283_log("OPTI 283: %08X-%08X READ_INTERNAL, WRITE_DISABLED\n", base, base + 0x3fff); - } else { - if (base >= 0x000e0000) - shadowbios_write |= 1; + if (sh_mode) { + mem_set_mem_state_both(base, 0x4000, MEM_READ_INTERNAL | MEM_WRITE_DISABLED); + opti283_log("OPTI 283: %08X-%08X READ_INTERNAL, WRITE_DISABLED\n", base, base + 0x3fff); + } else { + if (base >= 0x000e0000) + shadowbios_write |= 1; - if (sh_copy) { - mem_set_mem_state_both(base, 0x4000, MEM_READ_INTERNAL | MEM_WRITE_INTERNAL); - opti283_log("OPTI 283: %08X-%08X READ_INTERNAL, WRITE_INTERNAL\n", base, base + 0x3fff); - } else { - mem_set_mem_state_both(base, 0x4000, MEM_READ_INTERNAL | MEM_WRITE_EXTERNAL); - opti283_log("OPTI 283: %08X-%08X READ_INTERNAL, WRITE_EXTERNAL\n", base, base + 0x3fff); - } - } - } else { - if (base >= 0xe0000) { - mem_set_mem_state_both(base, 0x4000, MEM_READ_EXTANY | MEM_WRITE_DISABLED); - opti283_log("OPTI 283: %08X-%08X READ_EXTANY, WRITE_DISABLED\n", base, base + 0x3fff); - } else { - mem_set_mem_state_both(base, 0x4000, MEM_READ_EXTERNAL | MEM_WRITE_DISABLED); - opti283_log("OPTI 283: %08X-%08X READ_EXTERNAL, WRITE_DISABLED\n", base, base + 0x3fff); - } - } + if (sh_copy) { + mem_set_mem_state_both(base, 0x4000, MEM_READ_INTERNAL | MEM_WRITE_INTERNAL); + opti283_log("OPTI 283: %08X-%08X READ_INTERNAL, WRITE_INTERNAL\n", base, base + 0x3fff); + } else { + mem_set_mem_state_both(base, 0x4000, MEM_READ_INTERNAL | MEM_WRITE_EXTERNAL); + opti283_log("OPTI 283: %08X-%08X READ_INTERNAL, WRITE_EXTERNAL\n", base, base + 0x3fff); + } + } + } else { + if (base >= 0xe0000) { + mem_set_mem_state_both(base, 0x4000, MEM_READ_EXTANY | MEM_WRITE_DISABLED); + opti283_log("OPTI 283: %08X-%08X READ_EXTANY, WRITE_DISABLED\n", base, base + 0x3fff); + } else { + mem_set_mem_state_both(base, 0x4000, MEM_READ_EXTERNAL | MEM_WRITE_DISABLED); + opti283_log("OPTI 283: %08X-%08X READ_EXTERNAL, WRITE_DISABLED\n", base, base + 0x3fff); + } + } } rbase = ((uint32_t) (dev->regs[0x13] & 0x0f)) << 20; if (rbase > 0) { - dev->mem_remappings[0].virt = rbase; - mem_mapping_set_addr(&dev->mem_mappings[0], rbase, 0x00020000); + dev->mem_remappings[0].virt = rbase; + mem_mapping_set_addr(&dev->mem_mappings[0], rbase, 0x00020000); - if (!dev->shadow_high) { - rbase += 0x00020000; - dev->mem_remappings[1].virt = rbase; - mem_mapping_set_addr(&dev->mem_mappings[1], rbase , 0x00020000); - } else - mem_mapping_disable(&dev->mem_mappings[1]); + if (!dev->shadow_high) { + rbase += 0x00020000; + dev->mem_remappings[1].virt = rbase; + mem_mapping_set_addr(&dev->mem_mappings[1], rbase, 0x00020000); + } else + mem_mapping_disable(&dev->mem_mappings[1]); } else { - mem_mapping_disable(&dev->mem_mappings[0]); - mem_mapping_disable(&dev->mem_mappings[1]); + mem_mapping_disable(&dev->mem_mappings[0]); + mem_mapping_disable(&dev->mem_mappings[1]); } flushmmucache_nopc(); } - static void opti283_write(uint16_t addr, uint8_t val, void *priv) { - opti283_t *dev = (opti283_t *)priv; + opti283_t *dev = (opti283_t *) priv; switch (addr) { - case 0x22: - dev->index = val; - break; + case 0x22: + dev->index = val; + break; - case 0x24: - opti283_log("OPTi 283: dev->regs[%02x] = %02x\n", dev->index, val); + case 0x24: + opti283_log("OPTi 283: dev->regs[%02x] = %02x\n", dev->index, val); - switch (dev->index) { - case 0x10: - dev->regs[dev->index] = val; - break; + switch (dev->index) { + case 0x10: + dev->regs[dev->index] = val; + break; - case 0x14: - reset_on_hlt = !!(val & 0x40); - /* FALLTHROUGH */ - case 0x11: case 0x12: - case 0x13: - dev->regs[dev->index] = val; - opti283_shadow_recalc(dev); - break; - } - break; + case 0x14: + reset_on_hlt = !!(val & 0x40); + fallthrough; + case 0x11: + case 0x12: + case 0x13: + dev->regs[dev->index] = val; + opti283_shadow_recalc(dev); + break; + + default: + break; + } + break; + + default: + break; } } - static uint8_t opti283_read(uint16_t addr, void *priv) { - opti283_t *dev = (opti283_t *)priv; - uint8_t ret = 0xff; + const opti283_t *dev = (opti283_t *) priv; + uint8_t ret = 0xff; if (addr == 0x24) - ret = dev->regs[dev->index]; + ret = dev->regs[dev->index]; return ret; } - static void opti283_close(void *priv) { - opti283_t *dev = (opti283_t *)priv; + opti283_t *dev = (opti283_t *) priv; free(dev); } - static void * -opti283_init(const device_t *info) +opti283_init(UNUSED(const device_t *info)) { - opti283_t *dev = (opti283_t *)malloc(sizeof(opti283_t)); + opti283_t *dev = (opti283_t *) malloc(sizeof(opti283_t)); memset(dev, 0x00, sizeof(opti283_t)); io_sethandler(0x0022, 0x0001, opti283_read, NULL, NULL, opti283_write, NULL, NULL, dev); @@ -286,14 +283,14 @@ opti283_init(const device_t *info) dev->mem_remappings[1].phys = 0x000d0000; mem_mapping_add(&dev->mem_mappings[0], 0, 0x00020000, - opti283_read_remapped_ram, opti283_read_remapped_ramw, opti283_read_remapped_raml, - opti283_write_remapped_ram, opti283_write_remapped_ramw, opti283_write_remapped_raml, + opti283_read_remapped_ram, opti283_read_remapped_ramw, opti283_read_remapped_raml, + opti283_write_remapped_ram, opti283_write_remapped_ramw, opti283_write_remapped_raml, &ram[dev->mem_remappings[0].phys], MEM_MAPPING_INTERNAL, &dev->mem_remappings[0]); mem_mapping_disable(&dev->mem_mappings[0]); mem_mapping_add(&dev->mem_mappings[1], 0, 0x00020000, - opti283_read_remapped_ram, opti283_read_remapped_ramw, opti283_read_remapped_raml, - opti283_write_remapped_ram, opti283_write_remapped_ramw, opti283_write_remapped_raml, + opti283_read_remapped_ram, opti283_read_remapped_ramw, opti283_read_remapped_raml, + opti283_write_remapped_ram, opti283_write_remapped_ramw, opti283_write_remapped_raml, &ram[dev->mem_remappings[1].phys], MEM_MAPPING_INTERNAL, &dev->mem_remappings[1]); mem_mapping_disable(&dev->mem_mappings[1]); @@ -302,17 +299,16 @@ opti283_init(const device_t *info) return dev; } - const device_t opti283_device = { - "OPTi 82C283", - "opti283", - 0, - 0, - opti283_init, - opti283_close, - NULL, - { NULL }, - NULL, - NULL, - NULL + .name = "OPTi 82C283", + .internal_name = "opti283", + .flags = 0, + .local = 0, + .init = opti283_init, + .close = opti283_close, + .reset = NULL, + { .available = NULL }, + .speed_changed = NULL, + .force_redraw = NULL, + .config = NULL }; diff --git a/src/chipset/opti291.c b/src/chipset/opti291.c index 3105d50d7..6d2256974 100644 --- a/src/chipset/opti291.c +++ b/src/chipset/opti291.c @@ -1,17 +1,19 @@ /* - * 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. + * 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. + * This file is part of the 86Box distribution. * - * Implementation of the OPTi 82C291 chipset. - - * Authors: plant/nerd73, Tiseno100 + * Implementation of the OPTi 82C291 chipset. * - * Copyright 2020 plant/nerd73. - * Copyright 2021 Tiseno100. + * + * + * Authors: plant/nerd73, Tiseno100 + * + * Copyright 2020 plant/nerd73. + * Copyright 2021 Tiseno100. */ #include #include @@ -26,135 +28,141 @@ #include <86box/io.h> #include <86box/device.h> #include <86box/mem.h> +#include <86box/plat_unused.h> #include <86box/port_92.h> #include <86box/chipset.h> #ifdef ENABLE_OPTI291_LOG int opti291_do_log = ENABLE_OPTI291_LOG; + static void opti291_log(const char *fmt, ...) { - va_list ap; + va_list ap; - if (opti291_do_log) - { - va_start(ap, fmt); - pclog_ex(fmt, ap); - va_end(ap); - } + if (opti291_do_log) { + va_start(ap, fmt); + pclog_ex(fmt, ap); + va_end(ap); + } } #else -#define opti291_log(fmt, ...) +# define opti291_log(fmt, ...) #endif -typedef struct -{ - uint8_t index, regs[256]; - port_92_t *port_92; +typedef struct opti291_t { + uint8_t index; + uint8_t regs[256]; + port_92_t *port_92; } opti291_t; -static void opti291_recalc(opti291_t *dev) +static void +opti291_recalc(opti291_t *dev) { - mem_set_mem_state_both(0xf0000, 0x10000, (!(dev->regs[0x23] & 0x40) ? MEM_READ_INTERNAL : MEM_READ_EXTANY) | ((dev->regs[0x27] & 0x80) ? MEM_WRITE_DISABLED : MEM_WRITE_INTERNAL)); + mem_set_mem_state_both(0xf0000, 0x10000, (!(dev->regs[0x23] & 0x40) ? MEM_READ_INTERNAL : MEM_READ_EXTANY) | ((dev->regs[0x27] & 0x80) ? MEM_WRITE_DISABLED : MEM_WRITE_INTERNAL)); - for (uint32_t i = 0; i < 4; i++) - { - mem_set_mem_state_both(0xc0000 + (i << 14), 0x4000, ((dev->regs[0x26] & (1 << (i + 4))) ? MEM_READ_INTERNAL : MEM_READ_EXTANY) | ((dev->regs[0x27] & 0x10) ? MEM_WRITE_DISABLED : ((dev->regs[0x26] & (1 << i)) ? MEM_WRITE_INTERNAL : MEM_WRITE_EXTANY))); - mem_set_mem_state_both(0xd0000 + (i << 14), 0x4000, ((dev->regs[0x25] & (1 << (i + 4))) ? MEM_READ_INTERNAL : MEM_READ_EXTANY) | ((dev->regs[0x27] & 0x20) ? MEM_WRITE_DISABLED : ((dev->regs[0x25] & (1 << i)) ? MEM_WRITE_INTERNAL : MEM_WRITE_EXTANY))); - mem_set_mem_state_both(0xe0000 + (i << 14), 0x4000, ((dev->regs[0x24] & (1 << (i + 4))) ? MEM_READ_INTERNAL : MEM_READ_EXTANY) | ((dev->regs[0x27] & 0x40) ? MEM_WRITE_DISABLED : ((dev->regs[0x24] & (1 << i)) ? MEM_WRITE_INTERNAL : MEM_WRITE_EXTANY))); - } - flushmmucache(); + for (uint32_t i = 0; i < 4; i++) { + mem_set_mem_state_both(0xc0000 + (i << 14), 0x4000, ((dev->regs[0x26] & (1 << (i + 4))) ? MEM_READ_INTERNAL : MEM_READ_EXTANY) | ((dev->regs[0x27] & 0x10) ? MEM_WRITE_DISABLED : ((dev->regs[0x26] & (1 << i)) ? MEM_WRITE_INTERNAL : MEM_WRITE_EXTANY))); + mem_set_mem_state_both(0xd0000 + (i << 14), 0x4000, ((dev->regs[0x25] & (1 << (i + 4))) ? MEM_READ_INTERNAL : MEM_READ_EXTANY) | ((dev->regs[0x27] & 0x20) ? MEM_WRITE_DISABLED : ((dev->regs[0x25] & (1 << i)) ? MEM_WRITE_INTERNAL : MEM_WRITE_EXTANY))); + mem_set_mem_state_both(0xe0000 + (i << 14), 0x4000, ((dev->regs[0x24] & (1 << (i + 4))) ? MEM_READ_INTERNAL : MEM_READ_EXTANY) | ((dev->regs[0x27] & 0x40) ? MEM_WRITE_DISABLED : ((dev->regs[0x24] & (1 << i)) ? MEM_WRITE_INTERNAL : MEM_WRITE_EXTANY))); + } + flushmmucache(); } static void opti291_write(uint16_t addr, uint8_t val, void *priv) { - opti291_t *dev = (opti291_t *)priv; + opti291_t *dev = (opti291_t *) priv; - switch (addr) - { - case 0x22: - dev->index = val; - break; - case 0x24: - opti291_log("OPTi 291: dev->regs[%02x] = %02x\n", dev->index, val); - switch (dev->index) - { - case 0x20: - dev->regs[dev->index] = val & 0x3f; - break; - case 0x21: - dev->regs[dev->index] = val & 0xf3; - break; - case 0x22: - dev->regs[dev->index] = val; - break; - case 0x23: - case 0x24: - case 0x25: - case 0x26: - dev->regs[dev->index] = val; - opti291_recalc(dev); - break; - case 0x27: - case 0x28: - dev->regs[dev->index] = val; - break; - case 0x29: - dev->regs[dev->index] = val & 0x0f; - break; - case 0x2a: - case 0x2b: - case 0x2c: - dev->regs[dev->index] = val; - break; - } - break; - } + switch (addr) { + case 0x22: + dev->index = val; + break; + case 0x24: + opti291_log("OPTi 291: dev->regs[%02x] = %02x\n", dev->index, val); + switch (dev->index) { + case 0x20: + dev->regs[dev->index] = val & 0x3f; + break; + case 0x21: + dev->regs[dev->index] = val & 0xf3; + break; + case 0x22: + dev->regs[dev->index] = val; + break; + case 0x23: + case 0x24: + case 0x25: + case 0x26: + dev->regs[dev->index] = val; + opti291_recalc(dev); + break; + case 0x27: + case 0x28: + dev->regs[dev->index] = val; + break; + case 0x29: + dev->regs[dev->index] = val & 0x0f; + break; + case 0x2a: + case 0x2b: + case 0x2c: + dev->regs[dev->index] = val; + break; + + default: + break; + } + break; + + default: + break; + } } static uint8_t opti291_read(uint16_t addr, void *priv) { - opti291_t *dev = (opti291_t *)priv; + const opti291_t *dev = (opti291_t *) priv; - return (addr == 0x24) ? dev->regs[dev->index] : 0xff; + return (addr == 0x24) ? dev->regs[dev->index] : 0xff; } static void opti291_close(void *priv) { - opti291_t *dev = (opti291_t *)priv; + opti291_t *dev = (opti291_t *) priv; - free(dev); + free(dev); } static void * -opti291_init(const device_t *info) +opti291_init(UNUSED(const device_t *info)) { - opti291_t *dev = (opti291_t *)malloc(sizeof(opti291_t)); - memset(dev, 0, sizeof(opti291_t)); + opti291_t *dev = (opti291_t *) malloc(sizeof(opti291_t)); + memset(dev, 0, sizeof(opti291_t)); - io_sethandler(0x022, 0x0001, opti291_read, NULL, NULL, opti291_write, NULL, NULL, dev); - io_sethandler(0x024, 0x0001, opti291_read, NULL, NULL, opti291_write, NULL, NULL, dev); - dev->regs[0x22] = 0xf0; - dev->regs[0x23] = 0x40; - dev->regs[0x28] = 0x08; - dev->regs[0x29] = 0xa0; - device_add(&port_92_device); - opti291_recalc(dev); + io_sethandler(0x022, 0x0001, opti291_read, NULL, NULL, opti291_write, NULL, NULL, dev); + io_sethandler(0x024, 0x0001, opti291_read, NULL, NULL, opti291_write, NULL, NULL, dev); + dev->regs[0x22] = 0xf0; + dev->regs[0x23] = 0x40; + dev->regs[0x28] = 0x08; + dev->regs[0x29] = 0xa0; + device_add(&port_92_device); + opti291_recalc(dev); - return dev; + return dev; } const device_t opti291_device = { - "OPTi 82C291", - "opti291", - 0, - 0, - opti291_init, - opti291_close, - NULL, - {NULL}, - NULL, - NULL, - NULL}; + .name = "OPTi 82C291", + .internal_name = "opti291", + .flags = 0, + .local = 0, + .init = opti291_init, + .close = opti291_close, + .reset = NULL, + { .available = NULL }, + .speed_changed = NULL, + .force_redraw = NULL, + .config = NULL +}; diff --git a/src/chipset/opti391.c b/src/chipset/opti391.c index fde71fe3e..03cbb2ea7 100644 --- a/src/chipset/opti391.c +++ b/src/chipset/opti391.c @@ -1,18 +1,19 @@ /* - * 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. + * 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. + * This file is part of the 86Box distribution. * - * Implementation of the OPTi 82C391/392 chipset. + * Implementation of the OPTi 82C391/392 chipset. * - * Authors: Miran Grca, * - * Copyright 2021 Miran Grca. + * + * Authors: Miran Grca, + * + * Copyright 2021 Miran Grca. */ - #include #include #include @@ -26,9 +27,9 @@ #include <86box/io.h> #include <86box/device.h> #include <86box/mem.h> +#include <86box/plat_unused.h> #include <86box/chipset.h> - #ifdef ENABLE_OPTI391_LOG int opti391_do_log = ENABLE_OPTI391_LOG; @@ -37,160 +38,167 @@ opti391_log(const char *fmt, ...) { va_list ap; - if (opti391_do_log) - { + if (opti391_do_log) { va_start(ap, fmt); pclog_ex(fmt, ap); va_end(ap); } } #else -#define opti391_log(fmt, ...) +# define opti391_log(fmt, ...) #endif - -typedef struct -{ - uint32_t phys, virt; +typedef struct mem_remapping_t { + uint32_t phys; + uint32_t virt; } mem_remapping_t; - -typedef struct -{ - uint8_t index, regs[256]; +typedef struct opti391_t { + uint8_t index; + uint8_t regs[256]; } opti391_t; - static void opti391_shadow_recalc(opti391_t *dev) { - uint32_t i, base; - uint8_t sh_enable, sh_master; - uint8_t sh_wp, sh_write_internal; + uint32_t base; + uint8_t sh_enable; + uint8_t sh_master; + uint8_t sh_wp; + uint8_t sh_write_internal; shadowbios = shadowbios_write = 0; /* F0000-FFFFF */ sh_enable = !(dev->regs[0x22] & 0x80); if (sh_enable) - mem_set_mem_state_both(0xf0000, 0x10000, MEM_READ_EXTANY | MEM_WRITE_INTERNAL); + mem_set_mem_state_both(0xf0000, 0x10000, MEM_READ_EXTANY | MEM_WRITE_INTERNAL); else - mem_set_mem_state_both(0xf0000, 0x10000, MEM_READ_INTERNAL | MEM_WRITE_DISABLED); + mem_set_mem_state_both(0xf0000, 0x10000, MEM_READ_INTERNAL | MEM_WRITE_DISABLED); sh_write_internal = (dev->regs[0x26] & 0x40); /* D0000-EFFFF */ - for (i = 0; i < 8; i++) { - base = 0xd0000 + (i << 14); - if (base >= 0xe0000) { - sh_master = (dev->regs[0x22] & 0x40); - sh_wp = (dev->regs[0x22] & 0x10); - } else { - sh_master = (dev->regs[0x22] & 0x20); - sh_wp = (dev->regs[0x22] & 0x08); - } - sh_enable = dev->regs[0x23] & (1 << i); + for (uint8_t i = 0; i < 8; i++) { + base = 0xd0000 + (i << 14); + if (base >= 0xe0000) { + sh_master = (dev->regs[0x22] & 0x40); + sh_wp = (dev->regs[0x22] & 0x10); + } else { + sh_master = (dev->regs[0x22] & 0x20); + sh_wp = (dev->regs[0x22] & 0x08); + } + sh_enable = dev->regs[0x23] & (1 << i); - if (sh_master) { - if (sh_enable) { - if (sh_wp) - mem_set_mem_state_both(base, 0x4000, MEM_READ_INTERNAL | MEM_WRITE_DISABLED); - else - mem_set_mem_state_both(base, 0x4000, MEM_READ_INTERNAL | MEM_WRITE_INTERNAL); - } else if (sh_write_internal) - mem_set_mem_state_both(base, 0x4000, MEM_READ_EXTANY | MEM_WRITE_INTERNAL); - else - mem_set_mem_state_both(base, 0x4000, MEM_READ_EXTANY | MEM_WRITE_EXTANY); - } else if (sh_write_internal) - mem_set_mem_state_both(base, 0x4000, MEM_READ_EXTANY | MEM_WRITE_INTERNAL); - else - mem_set_mem_state_both(base, 0x4000, MEM_READ_EXTANY | MEM_WRITE_EXTANY); + if (sh_master) { + if (sh_enable) { + if (sh_wp) + mem_set_mem_state_both(base, 0x4000, MEM_READ_INTERNAL | MEM_WRITE_DISABLED); + else + mem_set_mem_state_both(base, 0x4000, MEM_READ_INTERNAL | MEM_WRITE_INTERNAL); + } else if (sh_write_internal) + mem_set_mem_state_both(base, 0x4000, MEM_READ_EXTANY | MEM_WRITE_INTERNAL); + else + mem_set_mem_state_both(base, 0x4000, MEM_READ_EXTANY | MEM_WRITE_EXTANY); + } else if (sh_write_internal) + mem_set_mem_state_both(base, 0x4000, MEM_READ_EXTANY | MEM_WRITE_INTERNAL); + else + mem_set_mem_state_both(base, 0x4000, MEM_READ_EXTANY | MEM_WRITE_EXTANY); } /* C0000-CFFFF */ sh_master = !(dev->regs[0x26] & 0x10); - sh_wp = (dev->regs[0x26] & 0x20); - for (i = 0; i < 4; i++) { - base = 0xc0000 + (i << 14); - sh_enable = dev->regs[0x26] & (1 << i); + sh_wp = (dev->regs[0x26] & 0x20); + for (uint8_t i = 0; i < 4; i++) { + base = 0xc0000 + (i << 14); + sh_enable = dev->regs[0x26] & (1 << i); - if (sh_master) { - if (sh_enable) { - if (sh_wp) - mem_set_mem_state_both(base, 0x4000, MEM_READ_INTERNAL | MEM_WRITE_DISABLED); - else - mem_set_mem_state_both(base, 0x4000, MEM_READ_INTERNAL | MEM_WRITE_INTERNAL); - } else if (sh_write_internal) - mem_set_mem_state_both(base, 0x4000, MEM_READ_EXTANY | MEM_WRITE_INTERNAL); - else - mem_set_mem_state_both(base, 0x4000, MEM_READ_EXTANY | MEM_WRITE_EXTANY); - } else if (sh_write_internal) - mem_set_mem_state_both(base, 0x4000, MEM_READ_EXTANY | MEM_WRITE_INTERNAL); - else - mem_set_mem_state_both(base, 0x4000, MEM_READ_EXTANY | MEM_WRITE_EXTANY); + if (sh_master) { + if (sh_enable) { + if (sh_wp) + mem_set_mem_state_both(base, 0x4000, MEM_READ_INTERNAL | MEM_WRITE_DISABLED); + else + mem_set_mem_state_both(base, 0x4000, MEM_READ_INTERNAL | MEM_WRITE_INTERNAL); + } else if (sh_write_internal) + mem_set_mem_state_both(base, 0x4000, MEM_READ_EXTANY | MEM_WRITE_INTERNAL); + else + mem_set_mem_state_both(base, 0x4000, MEM_READ_EXTANY | MEM_WRITE_EXTANY); + } else if (sh_write_internal) + mem_set_mem_state_both(base, 0x4000, MEM_READ_EXTANY | MEM_WRITE_INTERNAL); + else + mem_set_mem_state_both(base, 0x4000, MEM_READ_EXTANY | MEM_WRITE_EXTANY); } } - static void opti391_write(uint16_t addr, uint8_t val, void *priv) { - opti391_t *dev = (opti391_t *)priv; + opti391_t *dev = (opti391_t *) priv; switch (addr) { - case 0x22: - dev->index = val; - break; + case 0x22: + dev->index = val; + break; - case 0x24: - opti391_log("OPTi 391: dev->regs[%02x] = %02x\n", dev->index, val); + case 0x24: + opti391_log("OPTi 391: dev->regs[%02x] = %02x\n", dev->index, val); - switch (dev->index) { - case 0x20: - dev->regs[dev->index] = (dev->regs[dev->index] & 0xc0) | (val & 0x3f); - break; + switch (dev->index) { + case 0x20: + dev->regs[dev->index] = (dev->regs[dev->index] & 0xc0) | (val & 0x3f); + break; - case 0x21: case 0x24: case 0x25: case 0x27: - case 0x28: case 0x29: case 0x2a: case 0x2b: - dev->regs[dev->index] = val; - break; + case 0x21: + case 0x24: + case 0x25: + case 0x27: + case 0x28: + case 0x29: + case 0x2a: + case 0x2b: + dev->regs[dev->index] = val; + break; - case 0x22: case 0x23: - case 0x26: - dev->regs[dev->index] = val; - opti391_shadow_recalc(dev); - break; - } - break; + case 0x22: + case 0x23: + case 0x26: + dev->regs[dev->index] = val; + opti391_shadow_recalc(dev); + break; + + default: + break; + } + break; + + default: + break; } } - static uint8_t opti391_read(uint16_t addr, void *priv) { - opti391_t *dev = (opti391_t *)priv; - uint8_t ret = 0xff; + const opti391_t *dev = (opti391_t *) priv; + uint8_t ret = 0xff; if (addr == 0x24) - ret = dev->regs[dev->index]; + ret = dev->regs[dev->index]; return ret; } - static void opti391_close(void *priv) { - opti391_t *dev = (opti391_t *)priv; + opti391_t *dev = (opti391_t *) priv; free(dev); } - static void * -opti391_init(const device_t *info) +opti391_init(UNUSED(const device_t *info)) { - opti391_t *dev = (opti391_t *)malloc(sizeof(opti391_t)); + opti391_t *dev = (opti391_t *) malloc(sizeof(opti391_t)); memset(dev, 0x00, sizeof(opti391_t)); io_sethandler(0x0022, 0x0001, opti391_read, NULL, NULL, opti391_write, NULL, NULL, dev); @@ -211,17 +219,16 @@ opti391_init(const device_t *info) return dev; } - const device_t opti391_device = { - "OPTi 82C391", - "opti391", - 0, - 0, - opti391_init, - opti391_close, - NULL, - { NULL }, - NULL, - NULL, - NULL + .name = "OPTi 82C391", + .internal_name = "opti391", + .flags = 0, + .local = 0, + .init = opti391_init, + .close = opti391_close, + .reset = NULL, + { .available = NULL }, + .speed_changed = NULL, + .force_redraw = NULL, + .config = NULL }; diff --git a/src/chipset/opti495.c b/src/chipset/opti495.c index 605d0fb8d..13bc2a124 100644 --- a/src/chipset/opti495.c +++ b/src/chipset/opti495.c @@ -1,20 +1,20 @@ /* - * 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. + * 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. + * This file is part of the 86Box distribution. * - * Implementation of the OPTi 82C493/82C495 chipset. + * Implementation of the OPTi 82C493/82C495 chipset. * * * - * Authors: Tiseno100, - * Miran Grca, + * Authors: Tiseno100, + * Miran Grca, * - * Copyright 2008-2020 Tiseno100. - * Copyright 2016-2020 Miran Grca. + * Copyright 2008-2020 Tiseno100. + * Copyright 2016-2020 Miran Grca. */ #include #include @@ -31,159 +31,156 @@ #include <86box/port_92.h> #include <86box/chipset.h> - -typedef struct -{ - uint8_t idx, - regs[256], - scratch[2]; +typedef struct opti495_t { + uint8_t idx; + uint8_t regs[256]; + uint8_t scratch[2]; } opti495_t; - #ifdef ENABLE_OPTI495_LOG int opti495_do_log = ENABLE_OPTI495_LOG; - static void opti495_log(const char *fmt, ...) { va_list ap; if (opti495_do_log) { - va_start(ap, fmt); - pclog_ex(fmt, ap); - va_end(ap); + va_start(ap, fmt); + pclog_ex(fmt, ap); + va_end(ap); } } #else -#define opti495_log(fmt, ...) +# define opti495_log(fmt, ...) #endif - static void opti495_recalc(opti495_t *dev) { uint32_t base; - uint32_t i, shflags = 0; + uint32_t shflags = 0; - shadowbios = 0; + shadowbios = 0; shadowbios_write = 0; if (dev->regs[0x22] & 0x80) { - shadowbios = 1; - shadowbios_write = 0; - shflags = MEM_READ_EXTANY | MEM_WRITE_INTERNAL; + shadowbios = 1; + shadowbios_write = 0; + shflags = MEM_READ_EXTANY | MEM_WRITE_INTERNAL; } else { - shadowbios = 0; - shadowbios_write = 1; - shflags = MEM_READ_INTERNAL | MEM_WRITE_DISABLED; + shadowbios = 0; + shadowbios_write = 1; + shflags = MEM_READ_INTERNAL | MEM_WRITE_DISABLED; } mem_set_mem_state_both(0xf0000, 0x10000, shflags); - for (i = 0; i < 8; i++) { - base = 0xd0000 + (i << 14); + for (uint8_t i = 0; i < 8; i++) { + base = 0xd0000 + (i << 14); - if ((dev->regs[0x22] & ((base >= 0xe0000) ? 0x20 : 0x40)) && - (dev->regs[0x23] & (1 << i))) { - shflags = MEM_READ_INTERNAL; - shflags |= (dev->regs[0x22] & ((base >= 0xe0000) ? 0x08 : 0x10)) ? MEM_WRITE_DISABLED : MEM_WRITE_INTERNAL; - } else { - if (dev->regs[0x26] & 0x40) { - shflags = MEM_READ_EXTANY; - shflags |= (dev->regs[0x22] & ((base >= 0xe0000) ? 0x08 : 0x10)) ? MEM_WRITE_DISABLED : MEM_WRITE_INTERNAL; - } else - shflags = MEM_READ_EXTANY | MEM_WRITE_EXTANY; - } + if ((dev->regs[0x22] & ((base >= 0xe0000) ? 0x20 : 0x40)) && (dev->regs[0x23] & (1 << i))) { + shflags = MEM_READ_INTERNAL; + shflags |= (dev->regs[0x22] & ((base >= 0xe0000) ? 0x08 : 0x10)) ? MEM_WRITE_DISABLED : MEM_WRITE_INTERNAL; + } else { + if (dev->regs[0x26] & 0x40) { + shflags = MEM_READ_EXTANY; + shflags |= (dev->regs[0x22] & ((base >= 0xe0000) ? 0x08 : 0x10)) ? MEM_WRITE_DISABLED : MEM_WRITE_INTERNAL; + } else + shflags = MEM_READ_EXTANY | MEM_WRITE_EXTANY; + } - mem_set_mem_state_both(base, 0x4000, shflags); + mem_set_mem_state_both(base, 0x4000, shflags); } - for (i = 0; i < 4; i++) { - base = 0xc0000 + (i << 14); + for (uint8_t i = 0; i < 4; i++) { + base = 0xc0000 + (i << 14); - if ((dev->regs[0x26] & 0x10) && (dev->regs[0x26] & (1 << i))) { - shflags = MEM_READ_INTERNAL; - shflags |= (dev->regs[0x26] & 0x20) ? MEM_WRITE_DISABLED : MEM_WRITE_INTERNAL; - } else { - if (dev->regs[0x26] & 0x40) { - shflags = MEM_READ_EXTANY; - shflags |= (dev->regs[0x26] & 0x20) ? MEM_WRITE_DISABLED : MEM_WRITE_INTERNAL; - } else - shflags = MEM_READ_EXTANY | MEM_WRITE_EXTANY; - } + if ((dev->regs[0x26] & 0x10) && (dev->regs[0x26] & (1 << i))) { + shflags = MEM_READ_INTERNAL; + shflags |= (dev->regs[0x26] & 0x20) ? MEM_WRITE_DISABLED : MEM_WRITE_INTERNAL; + } else { + if (dev->regs[0x26] & 0x40) { + shflags = MEM_READ_EXTANY; + shflags |= (dev->regs[0x26] & 0x20) ? MEM_WRITE_DISABLED : MEM_WRITE_INTERNAL; + } else + shflags = MEM_READ_EXTANY | MEM_WRITE_EXTANY; + } - mem_set_mem_state_both(base, 0x4000, shflags); + mem_set_mem_state_both(base, 0x4000, shflags); } flushmmucache(); } - static void opti495_write(uint16_t addr, uint8_t val, void *priv) { opti495_t *dev = (opti495_t *) priv; switch (addr) { - case 0x22: - opti495_log("[%04X:%08X] [W] dev->idx = %02X\n", CS, cpu_state.pc, val); - dev->idx = val; - break; - case 0x24: - if ((dev->idx >= 0x20) && (dev->idx <= 0x2d)) { - dev->regs[dev->idx] = val; - opti495_log("[%04X:%08X] [W] dev->regs[%04X] = %02X\n", CS, cpu_state.pc, dev->idx, val); + case 0x22: + opti495_log("[%04X:%08X] [W] dev->idx = %02X\n", CS, cpu_state.pc, val); + dev->idx = val; + break; + case 0x24: + if ((dev->idx >= 0x20) && (dev->idx <= 0x2d)) { + dev->regs[dev->idx] = val; + opti495_log("[%04X:%08X] [W] dev->regs[%04X] = %02X\n", CS, cpu_state.pc, dev->idx, val); - switch(dev->idx) { - case 0x21: - cpu_cache_ext_enabled = !!(dev->regs[0x21] & 0x10); - cpu_update_waitstates(); - break; + switch (dev->idx) { + case 0x21: + cpu_cache_ext_enabled = !!(dev->regs[0x21] & 0x10); + cpu_update_waitstates(); + break; - case 0x22: - case 0x23: - case 0x26: - opti495_recalc(dev); - break; - } - } - break; + case 0x22: + case 0x23: + case 0x26: + opti495_recalc(dev); + break; + default: + break; + } + } + break; - case 0xe1: - case 0xe2: - dev->scratch[~addr & 0x01] = val; - break; + case 0xe1: + case 0xe2: + dev->scratch[~addr & 0x01] = val; + break; + default: + break; } } - static uint8_t opti495_read(uint16_t addr, void *priv) { - uint8_t ret = 0xff; - opti495_t *dev = (opti495_t *) priv; + uint8_t ret = 0xff; + const opti495_t *dev = (opti495_t *) priv; switch (addr) { - case 0x22: - opti495_log("[%04X:%08X] [R] dev->idx = %02X\n", CS, cpu_state.pc, ret); - break; - case 0x24: - if ((dev->idx >= 0x20) && (dev->idx <= 0x2d)) { - ret = dev->regs[dev->idx]; - opti495_log("[%04X:%08X] [R] dev->regs[%04X] = %02X\n", CS, cpu_state.pc, dev->idx, ret); - } - break; - case 0xe1: - case 0xe2: - ret = dev->scratch[~addr & 0x01]; - break; + case 0x22: + opti495_log("[%04X:%08X] [R] dev->idx = %02X\n", CS, cpu_state.pc, ret); + break; + case 0x24: + if ((dev->idx >= 0x20) && (dev->idx <= 0x2d)) { + ret = dev->regs[dev->idx]; + opti495_log("[%04X:%08X] [R] dev->regs[%04X] = %02X\n", CS, cpu_state.pc, dev->idx, ret); + } + break; + case 0xe1: + case 0xe2: + ret = dev->scratch[~addr & 0x01]; + break; + default: + break; } return ret; } - static void opti495_close(void *priv) { @@ -192,7 +189,6 @@ opti495_close(void *priv) free(dev); } - static void * opti495_init(const device_t *info) { @@ -207,26 +203,26 @@ opti495_init(const device_t *info) dev->scratch[0] = dev->scratch[1] = 0xff; if (info->local == 1) { - /* 85C495 */ - dev->regs[0x20] = 0x02; - dev->regs[0x21] = 0x20; - dev->regs[0x22] = 0xe4; - dev->regs[0x25] = 0xf0; - dev->regs[0x26] = 0x80; - dev->regs[0x27] = 0xb1; - dev->regs[0x28] = 0x80; - dev->regs[0x29] = 0x10; + /* 85C495 */ + dev->regs[0x20] = 0x02; + dev->regs[0x21] = 0x20; + dev->regs[0x22] = 0xe4; + dev->regs[0x25] = 0xf0; + dev->regs[0x26] = 0x80; + dev->regs[0x27] = 0xb1; + dev->regs[0x28] = 0x80; + dev->regs[0x29] = 0x10; } else { - /* 85C493 */ - dev->regs[0x20] = 0x40; - dev->regs[0x22] = 0x84; - dev->regs[0x24] = 0x87; - dev->regs[0x25] = 0xf1; /* Note: 0xf0 is also valid default. */ - dev->regs[0x27] = 0x91; - dev->regs[0x28] = 0x80; - dev->regs[0x29] = 0x10; - dev->regs[0x2a] = 0x80; - dev->regs[0x2b] = 0x10; + /* 85C493 */ + dev->regs[0x20] = 0x40; + dev->regs[0x22] = 0x84; + dev->regs[0x24] = 0x87; + dev->regs[0x25] = 0xf1; /* Note: 0xf0 is also valid default. */ + dev->regs[0x27] = 0x91; + dev->regs[0x28] = 0x80; + dev->regs[0x29] = 0x10; + dev->regs[0x2a] = 0x80; + dev->regs[0x2b] = 0x10; } opti495_recalc(dev); @@ -236,24 +232,30 @@ opti495_init(const device_t *info) return dev; } - const device_t opti493_device = { - "OPTi 82C493", - "opti493", - 0, - 0, - opti495_init, opti495_close, NULL, - { NULL }, NULL, NULL, - NULL + .name = "OPTi 82C493", + .internal_name = "opti493", + .flags = 0, + .local = 0, + .init = opti495_init, + .close = opti495_close, + .reset = NULL, + { .available = NULL }, + .speed_changed = NULL, + .force_redraw = NULL, + .config = NULL }; - const device_t opti495_device = { - "OPTi 82C495", - "opti495", - 0, - 1, - opti495_init, opti495_close, NULL, - { NULL }, NULL, NULL, - NULL + .name = "OPTi 82C495", + .internal_name = "opti495", + .flags = 0, + .local = 1, + .init = opti495_init, + .close = opti495_close, + .reset = NULL, + { .available = NULL }, + .speed_changed = NULL, + .force_redraw = NULL, + .config = NULL }; diff --git a/src/chipset/opti499.c b/src/chipset/opti499.c index ca9692964..f8b878559 100644 --- a/src/chipset/opti499.c +++ b/src/chipset/opti499.c @@ -1,20 +1,20 @@ /* - * 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. + * 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. + * This file is part of the 86Box distribution. * - * Implementation of the OPTi 82C493/82C499 chipset. + * Implementation of the OPTi 82C493/82C499 chipset. * * * - * Authors: Tiseno100, - * Miran Grca, + * Authors: Tiseno100, + * Miran Grca, * - * Copyright 2008-2020 Tiseno100. - * Copyright 2016-2020 Miran Grca. + * Copyright 2008-2020 Tiseno100. + * Copyright 2016-2020 Miran Grca. */ #include #include @@ -29,174 +29,179 @@ #include <86box/device.h> #include <86box/mem.h> #include <86box/port_92.h> +#include <86box/plat_unused.h> #include <86box/chipset.h> - -typedef struct -{ - uint8_t idx, - regs[256], scratch[2]; +typedef struct opti499_t { + uint8_t idx; + uint8_t regs[256]; + uint8_t scratch[2]; } opti499_t; - #ifdef ENABLE_OPTI499_LOG int opti499_do_log = ENABLE_OPTI499_LOG; - static void opti499_log(const char *fmt, ...) { va_list ap; if (opti499_do_log) { - va_start(ap, fmt); - pclog_ex(fmt, ap); - va_end(ap); + va_start(ap, fmt); + pclog_ex(fmt, ap); + va_end(ap); } } #else -#define opti499_log(fmt, ...) +# define opti499_log(fmt, ...) #endif - static void opti499_recalc(opti499_t *dev) { uint32_t base; - uint32_t i, shflags = 0; + uint32_t shflags = 0; - shadowbios = 0; + shadowbios = 0; shadowbios_write = 0; if (dev->regs[0x22] & 0x80) { - shadowbios = 1; - shadowbios_write = 0; - shflags = MEM_READ_EXTANY | MEM_WRITE_INTERNAL; + shadowbios = 1; + shadowbios_write = 0; + shflags = MEM_READ_EXTANY | MEM_WRITE_INTERNAL; } else { - shadowbios = 0; - shadowbios_write = 1; - shflags = MEM_READ_INTERNAL | MEM_WRITE_DISABLED; + shadowbios = 0; + shadowbios_write = 1; + shflags = MEM_READ_INTERNAL | MEM_WRITE_DISABLED; } mem_set_mem_state_both(0xf0000, 0x10000, shflags); - for (i = 0; i < 8; i++) { - base = 0xd0000 + (i << 14); + for (uint8_t i = 0; i < 8; i++) { + base = 0xd0000 + (i << 14); - if ((dev->regs[0x22] & ((base >= 0xe0000) ? 0x20 : 0x40)) && - (dev->regs[0x23] & (1 << i))) { - shflags = MEM_READ_INTERNAL; - shflags |= (dev->regs[0x22] & ((base >= 0xe0000) ? 0x08 : 0x10)) ? MEM_WRITE_DISABLED : MEM_WRITE_INTERNAL; - } else { - if (dev->regs[0x2d] && (1 << ((i >> 1) + 2))) - shflags = MEM_READ_EXTANY | MEM_WRITE_EXTANY; - else - shflags = MEM_READ_EXTERNAL | MEM_WRITE_EXTERNAL; - } + if ((dev->regs[0x22] & ((base >= 0xe0000) ? 0x20 : 0x40)) && (dev->regs[0x23] & (1 << i))) { + shflags = MEM_READ_INTERNAL; + shflags |= (dev->regs[0x22] & ((base >= 0xe0000) ? 0x08 : 0x10)) ? MEM_WRITE_DISABLED : MEM_WRITE_INTERNAL; + } else { + if (dev->regs[0x2d] && (1 << ((i >> 1) + 2))) + shflags = MEM_READ_EXTANY | MEM_WRITE_EXTANY; + else + shflags = MEM_READ_EXTERNAL | MEM_WRITE_EXTERNAL; + } - mem_set_mem_state_both(base, 0x4000, shflags); + mem_set_mem_state_both(base, 0x4000, shflags); } - for (i = 0; i < 4; i++) { - base = 0xc0000 + (i << 14); + for (uint8_t i = 0; i < 4; i++) { + base = 0xc0000 + (i << 14); - if ((dev->regs[0x26] & 0x10) && (dev->regs[0x26] & (1 << i))) { - shflags = MEM_READ_INTERNAL; - shflags |= (dev->regs[0x26] & 0x20) ? MEM_WRITE_DISABLED : MEM_WRITE_INTERNAL; - } else { - if (dev->regs[0x26] & 0x40) { - if (dev->regs[0x2d] && (1 << (i >> 1))) - shflags = MEM_READ_EXTANY; - else - shflags = MEM_READ_EXTERNAL; - shflags |= (dev->regs[0x26] & 0x20) ? MEM_WRITE_DISABLED : MEM_WRITE_INTERNAL; - } else { - if (dev->regs[0x2d] && (1 << (i >> 1))) - shflags = MEM_READ_EXTANY | MEM_WRITE_EXTANY; - else - shflags = MEM_READ_EXTERNAL | MEM_WRITE_EXTERNAL; - } - } + if ((dev->regs[0x26] & 0x10) && (dev->regs[0x26] & (1 << i))) { + shflags = MEM_READ_INTERNAL; + shflags |= (dev->regs[0x26] & 0x20) ? MEM_WRITE_DISABLED : MEM_WRITE_INTERNAL; + } else { + if (dev->regs[0x26] & 0x40) { + if (dev->regs[0x2d] && (1 << (i >> 1))) + shflags = MEM_READ_EXTANY; + else + shflags = MEM_READ_EXTERNAL; + shflags |= (dev->regs[0x26] & 0x20) ? MEM_WRITE_DISABLED : MEM_WRITE_INTERNAL; + } else { + if (dev->regs[0x2d] && (1 << (i >> 1))) + shflags = MEM_READ_EXTANY | MEM_WRITE_EXTANY; + else + shflags = MEM_READ_EXTERNAL | MEM_WRITE_EXTERNAL; + } + } - mem_set_mem_state_both(base, 0x4000, shflags); + mem_set_mem_state_both(base, 0x4000, shflags); } flushmmucache_nopc(); } - static void opti499_write(uint16_t addr, uint8_t val, void *priv) { opti499_t *dev = (opti499_t *) priv; switch (addr) { - case 0x22: - opti499_log("[%04X:%08X] [W] dev->idx = %02X\n", CS, cpu_state.pc, val); - dev->idx = val; - break; - case 0x24: - if ((dev->idx >= 0x20) && (dev->idx <= 0x2d)) { - if (dev->idx == 0x20) - dev->regs[dev->idx] = (dev->regs[dev->idx] & 0xc0) | (val & 0x3f); - else - dev->regs[dev->idx] = val; - opti499_log("[%04X:%08X] [W] dev->regs[%04X] = %02X\n", CS, cpu_state.pc, dev->idx, val); + case 0x22: + opti499_log("[%04X:%08X] [W] dev->idx = %02X\n", CS, cpu_state.pc, val); + dev->idx = val; + break; + case 0x24: + if ((dev->idx >= 0x20) && (dev->idx <= 0x2d)) { + if (dev->idx == 0x20) + dev->regs[dev->idx] = (dev->regs[dev->idx] & 0xc0) | (val & 0x3f); + else + dev->regs[dev->idx] = val; + opti499_log("[%04X:%08X] [W] dev->regs[%04X] = %02X\n", CS, cpu_state.pc, dev->idx, val); - switch(dev->idx) { - case 0x20: - reset_on_hlt = !(val & 0x02); - break; + switch (dev->idx) { + case 0x20: + reset_on_hlt = !(val & 0x02); + break; - case 0x21: - cpu_cache_ext_enabled = !!(dev->regs[0x21] & 0x10); - cpu_update_waitstates(); - break; + case 0x21: + cpu_cache_ext_enabled = !!(dev->regs[0x21] & 0x10); + cpu_update_waitstates(); + break; - case 0x22: case 0x23: - case 0x26: case 0x2d: - opti499_recalc(dev); - break; - } - } - break; + case 0x22: + case 0x23: + case 0x26: + case 0x2d: + opti499_recalc(dev); + break; - case 0xe1: case 0xe2: - dev->scratch[~addr & 0x01] = val; - break; + default: + break; + } + } + break; + + case 0xe1: + case 0xe2: + dev->scratch[~addr & 0x01] = val; + break; + + default: + break; } } - static uint8_t opti499_read(uint16_t addr, void *priv) { - uint8_t ret = 0xff; + uint8_t ret = 0xff; opti499_t *dev = (opti499_t *) priv; switch (addr) { - case 0x22: - opti499_log("[%04X:%08X] [R] dev->idx = %02X\n", CS, cpu_state.pc, ret); - break; - case 0x24: - if ((dev->idx >= 0x20) && (dev->idx <= 0x2d)) { - if (dev->idx == 0x2d) - ret = dev->regs[dev->idx] & 0xbf; - else - ret = dev->regs[dev->idx]; - opti499_log("[%04X:%08X] [R] dev->regs[%04X] = %02X\n", CS, cpu_state.pc, dev->idx, ret); - } - break; - case 0xe1: - case 0xe2: - ret = dev->scratch[~addr & 0x01]; - break; + case 0x22: + opti499_log("[%04X:%08X] [R] dev->idx = %02X\n", CS, cpu_state.pc, ret); + break; + case 0x24: + if ((dev->idx >= 0x20) && (dev->idx <= 0x2d)) { + if (dev->idx == 0x2d) + ret = dev->regs[dev->idx] & 0xbf; + else + ret = dev->regs[dev->idx]; + opti499_log("[%04X:%08X] [R] dev->regs[%04X] = %02X\n", CS, cpu_state.pc, dev->idx, ret); + } + break; + case 0xe1: + case 0xe2: + ret = dev->scratch[~addr & 0x01]; + break; + + default: + break; } return ret; } - static void opti499_reset(void *priv) { @@ -213,7 +218,7 @@ opti499_reset(void *priv) dev->regs[0x27] = 0xd1; dev->regs[0x28] = dev->regs[0x2a] = 0x80; dev->regs[0x29] = dev->regs[0x2b] = 0x10; - dev->regs[0x2d] = 0x40; + dev->regs[0x2d] = 0x40; reset_on_hlt = 1; @@ -225,7 +230,6 @@ opti499_reset(void *priv) free(dev); } - static void opti499_close(void *priv) { @@ -234,9 +238,8 @@ opti499_close(void *priv) free(dev); } - static void * -opti499_init(const device_t *info) +opti499_init(UNUSED(const device_t *info)) { opti499_t *dev = (opti499_t *) malloc(sizeof(opti499_t)); memset(dev, 0, sizeof(opti499_t)); @@ -253,13 +256,16 @@ opti499_init(const device_t *info) return dev; } - const device_t opti499_device = { - "OPTi 82C499", - "opti499", - 0, - 1, - opti499_init, opti499_close, opti499_reset, - { NULL }, NULL, NULL, - NULL + .name = "OPTi 82C499", + .internal_name = "opti499", + .flags = 0, + .local = 1, + .init = opti499_init, + .close = opti499_close, + .reset = opti499_reset, + { .available = NULL }, + .speed_changed = NULL, + .force_redraw = NULL, + .config = NULL }; diff --git a/src/chipset/opti5x7.c b/src/chipset/opti5x7.c index 483580803..64adacde4 100644 --- a/src/chipset/opti5x7.c +++ b/src/chipset/opti5x7.c @@ -1,20 +1,20 @@ /* - * 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. + * 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. + * This file is part of the 86Box distribution. * - * Implementation of the OPTi 82C546/82C547(Python) & 82C596/82C597(Cobra) chipsets. - - * Authors: plant/nerd73, + * Implementation of the OPTi 82C546/82C547(Python) & 82C596/82C597(Cobra) chipsets. + + * Authors: plant/nerd73, * Miran Grca, * Tiseno100 * - * Copyright 2020 plant/nerd73. - * Copyright 2020 Miran Grca. - * Copyright 2021 Tiseno100. + * Copyright 2020 plant/nerd73. + * Copyright 2020 Miran Grca. + * Copyright 2021 Tiseno100. */ #include #include @@ -32,9 +32,10 @@ #include <86box/port_92.h> #include <86box/chipset.h> -typedef struct -{ - uint8_t idx, regs[16]; +typedef struct opti5x7_t { + uint8_t idx; + uint8_t is_pci; + uint8_t regs[16]; } opti5x7_t; #ifdef ENABLE_OPTI5X7_LOG @@ -45,45 +46,50 @@ opti5x7_log(const char *fmt, ...) { va_list ap; - if (opti5x7_do_log) - { + if (opti5x7_do_log) { va_start(ap, fmt); pclog_ex(fmt, ap); va_end(ap); } } #else -#define opti5x7_log(fmt, ...) +# define opti5x7_log(fmt, ...) #endif static void opti5x7_shadow_map(int cur_reg, opti5x7_t *dev) { -/* -Register 4h: Cxxxx Segment -Register 5h: Dxxxx Segment + /* + Register 4h: Cxxxx Segment + Register 5h: Dxxxx Segment -Bits 7-6: xC000-xFFFF -Bits 5-4: x8000-xBFFF -Bits 3-2: x4000-x7FFF -Bits 0-1: x0000-x3FFF + Bits 7-6: xC000-xFFFF + Bits 5-4: x8000-xBFFF + Bits 3-2: x4000-x7FFF + Bits 0-1: x0000-x3FFF - x-y - 0 0 Read/Write AT bus - 1 0 Read from AT - Write to DRAM - 1 1 Read from DRAM - Write to DRAM - 0 1 Read from DRAM (write protected) -*/ - if (cur_reg == 0x06) - { - mem_set_mem_state_both(0xe0000, 0x10000, ((dev->regs[6] & 1) ? MEM_READ_INTERNAL : MEM_READ_EXTANY) | ((dev->regs[6] & 2) ? MEM_WRITE_INTERNAL : MEM_WRITE_EXTANY)); - mem_set_mem_state_both(0xf0000, 0x10000, ((dev->regs[6] & 4) ? MEM_READ_INTERNAL : MEM_READ_EXTANY) | ((dev->regs[6] & 8) ? MEM_WRITE_INTERNAL : MEM_WRITE_EXTANY)); - } - else - { - for (int i = 0; i < 4; i++) - mem_set_mem_state_both(0xc0000 + ((cur_reg & 1) << 16) + (i << 14), 0x4000, ((dev->regs[cur_reg] & (1 << (2 * i))) ? MEM_READ_INTERNAL : MEM_READ_EXTANY) | ((dev->regs[cur_reg] & (2 << (2 * i))) ? MEM_WRITE_INTERNAL : MEM_WRITE_EXTANY)); + x-y + 0 0 Read/Write AT bus + 1 0 Read from AT - Write to DRAM + 1 1 Read from DRAM - Write to DRAM + 0 1 Read from DRAM (write protected) + */ + if (cur_reg == 0x06) { + if (dev->is_pci) { + mem_set_mem_state_cpu_both(0xe0000, 0x10000, ((dev->regs[6] & 1) ? MEM_READ_INTERNAL : MEM_READ_EXTANY) | ((dev->regs[6] & 2) ? MEM_WRITE_INTERNAL : MEM_WRITE_EXTANY)); + mem_set_mem_state_cpu_both(0xf0000, 0x10000, ((dev->regs[6] & 4) ? MEM_READ_INTERNAL : MEM_READ_EXTANY) | ((dev->regs[6] & 8) ? MEM_WRITE_INTERNAL : MEM_WRITE_EXTANY)); + } else { + mem_set_mem_state_both(0xe0000, 0x10000, ((dev->regs[6] & 1) ? MEM_READ_INTERNAL : MEM_READ_EXTANY) | ((dev->regs[6] & 2) ? MEM_WRITE_INTERNAL : MEM_WRITE_EXTANY)); + mem_set_mem_state_both(0xf0000, 0x10000, ((dev->regs[6] & 4) ? MEM_READ_INTERNAL : MEM_READ_EXTANY) | ((dev->regs[6] & 8) ? MEM_WRITE_INTERNAL : MEM_WRITE_EXTANY)); + } + } else { + for (uint8_t i = 0; i < 4; i++) { + if (dev->is_pci) + mem_set_mem_state_cpu_both(0xc0000 + ((cur_reg & 1) << 16) + (i << 14), 0x4000, ((dev->regs[cur_reg] & (1 << (2 * i))) ? MEM_READ_INTERNAL : MEM_READ_EXTANY) | ((dev->regs[cur_reg] & (2 << (2 * i))) ? MEM_WRITE_INTERNAL : MEM_WRITE_EXTANY)); + else + mem_set_mem_state_both(0xc0000 + ((cur_reg & 1) << 16) + (i << 14), 0x4000, ((dev->regs[cur_reg] & (1 << (2 * i))) ? MEM_READ_INTERNAL : MEM_READ_EXTANY) | ((dev->regs[cur_reg] & (2 << (2 * i))) ? MEM_WRITE_INTERNAL : MEM_WRITE_EXTANY)); + } } flushmmucache_nopc(); @@ -92,63 +98,65 @@ Bits 0-1: x0000-x3FFF static void opti5x7_write(uint16_t addr, uint8_t val, void *priv) { - opti5x7_t *dev = (opti5x7_t *)priv; + opti5x7_t *dev = (opti5x7_t *) priv; - switch (addr) - { - case 0x22: - dev->idx = val; - break; - case 0x24: - switch (dev->idx) - { - case 0x00: /* DRAM Configuration Register #1 */ - dev->regs[dev->idx] = val & 0x7f; + switch (addr) { + case 0x22: + dev->idx = val; break; - case 0x01: /* DRAM Control Register #1 */ - dev->regs[dev->idx] = val; + case 0x24: + switch (dev->idx) { + case 0x00: /* DRAM Configuration Register #1 */ + dev->regs[dev->idx] = val & 0x7f; + break; + case 0x01: /* DRAM Control Register #1 */ + dev->regs[dev->idx] = val; + break; + case 0x02: /* Cache Control Register #1 */ + dev->regs[dev->idx] = val; + cpu_cache_ext_enabled = !!(dev->regs[0x02] & 0x0c); + cpu_update_waitstates(); + break; + case 0x03: /* Cache Control Register #2 */ + dev->regs[dev->idx] = val; + break; + case 0x04: /* Shadow RAM Control Register #1 */ + case 0x05: /* Shadow RAM Control Register #2 */ + case 0x06: /* Shadow RAM Control Register #3 */ + dev->regs[dev->idx] = val; + opti5x7_shadow_map(dev->idx, dev); + break; + case 0x07: /* Tag Test Register */ + case 0x08: /* CPU Cache Control Register #1 */ + case 0x09: /* System Memory Function Register #1 */ + case 0x0a: /* System Memory Address Decode Register #1 */ + case 0x0b: /* System Memory Address Decode Register #2 */ + dev->regs[dev->idx] = val; + break; + case 0x0c: /* Extended DMA Register */ + dev->regs[dev->idx] = val & 0xcf; + break; + case 0x0d: /* ROMCS# Register */ + case 0x0e: /* Local Master Preemption Register */ + case 0x0f: /* Deturbo Control Register #1 */ + case 0x10: /* Cache Write-Hit Control Register */ + case 0x11: /* Master Cycle Control Register */ + dev->regs[dev->idx] = val; + break; + default: + break; + } + opti5x7_log("OPTi 5x7: dev->regs[%02x] = %02x\n", dev->idx, dev->regs[dev->idx]); break; - case 0x02: /* Cache Control Register #1 */ - dev->regs[dev->idx] = val; - cpu_cache_ext_enabled = !!(dev->regs[0x02] & 0x0c); - cpu_update_waitstates(); + default: break; - case 0x03: /* Cache Control Register #2 */ - dev->regs[dev->idx] = val; - break; - case 0x04: /* Shadow RAM Control Register #1 */ - case 0x05: /* Shadow RAM Control Register #2 */ - case 0x06: /* Shadow RAM Control Register #3 */ - dev->regs[dev->idx] = val; - opti5x7_shadow_map(dev->idx, dev); - break; - case 0x07: /* Tag Test Register */ - case 0x08: /* CPU Cache Control Register #1 */ - case 0x09: /* System Memory Function Register #1 */ - case 0x0a: /* System Memory Address Decode Register #1 */ - case 0x0b: /* System Memory Address Decode Register #2 */ - dev->regs[dev->idx] = val; - break; - case 0x0c: /* Extended DMA Register */ - dev->regs[dev->idx] = val & 0xcf; - break; - case 0x0d: /* ROMCS# Register */ - case 0x0e: /* Local Master Preemption Register */ - case 0x0f: /* Deturbo Control Register #1 */ - case 0x10: /* Cache Write-Hit Control Register */ - case 0x11: /* Master Cycle Control Register */ - dev->regs[dev->idx] = val; - break; - } - opti5x7_log("OPTi 5x7: dev->regs[%02x] = %02x\n", dev->idx, dev->regs[dev->idx]); - break; } } static uint8_t opti5x7_read(uint16_t addr, void *priv) { - opti5x7_t *dev = (opti5x7_t *)priv; + const opti5x7_t *dev = (opti5x7_t *) priv; return (addr == 0x24) ? dev->regs[dev->idx] : 0xff; } @@ -156,7 +164,7 @@ opti5x7_read(uint16_t addr, void *priv) static void opti5x7_close(void *priv) { - opti5x7_t *dev = (opti5x7_t *)priv; + opti5x7_t *dev = (opti5x7_t *) priv; free(dev); } @@ -164,9 +172,11 @@ opti5x7_close(void *priv) static void * opti5x7_init(const device_t *info) { - opti5x7_t *dev = (opti5x7_t *)malloc(sizeof(opti5x7_t)); + opti5x7_t *dev = (opti5x7_t *) malloc(sizeof(opti5x7_t)); memset(dev, 0, sizeof(opti5x7_t)); + dev->is_pci = info->local; + io_sethandler(0x0022, 0x0001, opti5x7_read, NULL, NULL, opti5x7_write, NULL, NULL, dev); io_sethandler(0x0024, 0x0001, opti5x7_read, NULL, NULL, opti5x7_write, NULL, NULL, dev); @@ -176,14 +186,29 @@ opti5x7_init(const device_t *info) } const device_t opti5x7_device = { - "OPTi 82C5x6/82C5x7", - "opti5x7", - 0, - 0, - opti5x7_init, - opti5x7_close, - NULL, - {NULL}, - NULL, - NULL, - NULL}; + .name = "OPTi 82C5x6/82C5x7", + .internal_name = "opti5x7", + .flags = 0, + .local = 0, + .init = opti5x7_init, + .close = opti5x7_close, + .reset = NULL, + { .available = NULL }, + .speed_changed = NULL, + .force_redraw = NULL, + .config = NULL +}; + +const device_t opti5x7_pci_device = { + .name = "OPTi 82C5x6/82C5x7 (PCI)", + .internal_name = "opti5x7_pci", + .flags = 0, + .local = 1, + .init = opti5x7_init, + .close = opti5x7_close, + .reset = NULL, + { .available = NULL }, + .speed_changed = NULL, + .force_redraw = NULL, + .config = NULL +}; diff --git a/src/chipset/opti602.c b/src/chipset/opti602.c new file mode 100644 index 000000000..3b5614ff4 --- /dev/null +++ b/src/chipset/opti602.c @@ -0,0 +1,239 @@ +/* + * 86Box A hypervisor and IBM PC system emulator that specializes in + * running old operating systems and software designed for IBM + * PC systems and compatibles from 1981 through fairly recent + * system designs based on the PCI bus. + * + * This file is part of the 86Box distribution. + * + * Implementation of the OPTi 82C601/82C602 Buffer Devices. + * + * Authors: Miran Grca, + * + * Copyright 2023 Miran Grca. + */ +#include +#include +#include +#include +#include +#include +#define HAVE_STDARG_H +#include <86box/86box.h> +#include "cpu.h" +#include <86box/io.h> +#include <86box/device.h> +#include <86box/mem.h> +#include <86box/timer.h> +#include <86box/nvr.h> +#include <86box/smram.h> +#include <86box/port_92.h> +#include <86box/chipset.h> +#include <86box/plat_unused.h> + +typedef struct opti602_t { + uint8_t idx; + + uint8_t regs[256]; + uint8_t gpio[32]; + + uint16_t gpio_base; + + uint16_t gpio_mask; + uint16_t gpio_size; + + nvr_t *nvr; +} opti602_t; + +#ifdef ENABLE_OPTI602_LOG +int opti602_do_log = ENABLE_OPTI602_LOG; + +static void +opti602_log(const char *fmt, ...) +{ + va_list ap; + + if (opti602_do_log) { + va_start(ap, fmt); + pclog_ex(fmt, ap); + va_end(ap); + } +} +#else +# define opti602_log(fmt, ...) +#endif + +static void +opti602_gpio_write(uint16_t addr, uint8_t val, void *priv) +{ + opti602_t *dev = (opti602_t *) priv; + + dev->gpio[addr - dev->gpio_base] = val; +} + +static uint8_t +opti602_gpio_read(uint16_t addr, void *priv) +{ + const opti602_t *dev = (opti602_t *) priv; + uint8_t ret = 0xff; + + ret = dev->gpio[addr - dev->gpio_base]; + + return ret; +} + +static void +opti602_gpio_recalc(opti602_t *dev) +{ + if (dev->gpio_base != 0x0000) + io_removehandler(dev->gpio_base, dev->gpio_size, opti602_gpio_read, NULL, NULL, opti602_gpio_write, NULL, NULL, dev); + + dev->gpio_base = dev->regs[0xf8]; + dev->gpio_base |= (((uint16_t) dev->regs[0xf7]) << 8); + + dev->gpio_size = 1 << ((dev->regs[0xf9] >> 2) & 0x07); + + dev->gpio_mask = ~(dev->gpio_size - 1); + dev->gpio_base &= dev->gpio_mask; + + dev->gpio_mask = ~dev->gpio_mask; + + if (dev->gpio_base != 0x0000) + io_sethandler(dev->gpio_base, dev->gpio_size, opti602_gpio_read, NULL, NULL, opti602_gpio_write, NULL, NULL, dev); +} + +static void +opti602_write(uint16_t addr, uint8_t val, void *priv) +{ + opti602_t *dev = (opti602_t *) priv; + + switch (addr) { + case 0x22: + dev->idx = val; + break; + case 0x24: + if ((dev->idx == 0xea) || ((dev->idx >= 0xf7) && (dev->idx <= 0xfa))) { + dev->regs[dev->idx] = val; + opti602_log("dev->regs[%04x] = %08x\n", dev->idx, val); + + /* TODO: Registers 0x30-0x3F for OPTi 802GP and 898. */ + switch (dev->idx) { + case 0xea: + /* GREEN Power Port */ + break; + + case 0xf7: + case 0xf8: + /* General Purpose Chip Select Registers */ + opti602_gpio_recalc(dev); + break; + + case 0xf9: + /* General Purpose Chip Select Register */ + nvr_bank_set(0, !!(val & 0x20), dev->nvr); + opti602_gpio_recalc(dev); + break; + + case 0xfa: + /* GPM Port */ + break; + + default: + break; + } + } + break; + + default: + break; + } +} + +static uint8_t +opti602_read(uint16_t addr, void *priv) +{ + uint8_t ret = 0xff; + const opti602_t *dev = (opti602_t *) priv; + + switch (addr) { + case 0x24: + if ((dev->idx == 0xea) || ((dev->idx >= 0xf7) && (dev->idx <= 0xfa))) { + ret = dev->regs[dev->idx]; + if ((dev->idx == 0xfa) && (dev->regs[0xf9] & 0x40)) + ret |= dev->regs[0xea]; + } + break; + + default: + break; + } + + return ret; +} + +static void +opti602_reset(void *priv) +{ + opti602_t *dev = (opti602_t *) priv; + + memset(dev->regs, 0x00, 256 * sizeof(uint8_t)); + memset(dev->gpio, 0x00, 32 * sizeof(uint8_t)); + + dev->regs[0xfa] = 0x07; + + dev->gpio[0x01] |= 0xfe; + + nvr_bank_set(0, 0, dev->nvr); + opti602_gpio_recalc(dev); +} + +static void +opti602_close(void *priv) +{ + opti602_t *dev = (opti602_t *) priv; + + free(dev); +} + +static void * +opti602_init(UNUSED(const device_t *info)) +{ + opti602_t *dev = (opti602_t *) calloc(1, sizeof(opti602_t)); + + io_sethandler(0x0022, 0x0001, opti602_read, NULL, NULL, opti602_write, NULL, NULL, dev); + io_sethandler(0x0024, 0x0001, opti602_read, NULL, NULL, opti602_write, NULL, NULL, dev); + + dev->nvr = device_add(&at_mb_nvr_device); + + opti602_reset(dev); + + return dev; +} + +const device_t opti601_device = { + .name = "OPTi 82C601", + .internal_name = "opti601", + .flags = 0, + .local = 0, + .init = opti602_init, + .close = opti602_close, + .reset = opti602_reset, + { .available = NULL }, + .speed_changed = NULL, + .force_redraw = NULL, + .config = NULL +}; + +const device_t opti602_device = { + .name = "OPTi 82C602", + .internal_name = "opti602", + .flags = 0, + .local = 0, + .init = opti602_init, + .close = opti602_close, + .reset = opti602_reset, + { .available = NULL }, + .speed_changed = NULL, + .force_redraw = NULL, + .config = NULL +}; diff --git a/src/chipset/opti822.c b/src/chipset/opti822.c index 42a7c89cd..3e9316f2b 100644 --- a/src/chipset/opti822.c +++ b/src/chipset/opti822.c @@ -1,19 +1,20 @@ /* - * 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. + * 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. + * This file is part of the 86Box distribution. * - * Implementation of the OPTi 82C822 VESA Local Bus to PCI Bridge Interface. + * Implementation of the OPTi 82C822 VESA Local Bus to PCI + * Bridge Interface. * * - * Authors: Tiseno100, * - * Copyright 2021 Tiseno100. + * Authors: Miran Grca, + * + * Copyright 2022 Miran Grca. */ - #include #include #include @@ -22,287 +23,381 @@ #include #define HAVE_STDARG_H #include <86box/86box.h> -#include "cpu.h" -#include <86box/timer.h> -#include <86box/io.h> #include <86box/device.h> - +#include <86box/io.h> +#include <86box/apm.h> +#include <86box/dma.h> #include <86box/mem.h> +#include <86box/smram.h> #include <86box/pci.h> - +#include <86box/timer.h> +#include <86box/pic.h> +#include <86box/pit.h> +#include <86box/plat_unused.h> +#include <86box/port_92.h> +#include <86box/hdc_ide.h> +#include <86box/hdc.h> +#include <86box/machine.h> #include <86box/chipset.h> +#include <86box/spd.h> -/* Shadow RAM */ -#define SYSTEM_READ ((dev->pci_conf[0x44] & 2) ? MEM_READ_INTERNAL : MEM_READ_EXTANY) -#define SYSTEM_WRITE ((dev->pci_conf[0x44] & 1) ? MEM_WRITE_INTERNAL : MEM_WRITE_EXTANY) -#define SHADOW_READ ((dev->pci_conf[cur_reg] & (1 << (4 + i))) ? MEM_READ_INTERNAL : MEM_READ_EXTANY) -#define SHADOW_WRITE ((dev->pci_conf[cur_reg] & (1 << i)) ? MEM_WRITE_INTERNAL : MEM_WRITE_EXTANY) +typedef struct opti822_t { + uint8_t irq_convert; + uint8_t pci_slot; + uint8_t pad; + uint8_t pad0; + uint8_t pci_regs[256]; +} opti822_t; + +// #define ENABLE_OPTI822_LOG 1 #ifdef ENABLE_OPTI822_LOG int opti822_do_log = ENABLE_OPTI822_LOG; + static void opti822_log(const char *fmt, ...) { va_list ap; - if (opti822_do_log) - { + if (opti822_do_log) { va_start(ap, fmt); pclog_ex(fmt, ap); va_end(ap); } } #else -#define opti822_log(fmt, ...) +# define opti822_log(fmt, ...) #endif -typedef struct opti822_t +/* NOTE: We currently cheat and pass all PCI shadow RAM accesses to ISA as well. + This is because we currently do not have separate access mappings for + PCI and ISA at all. */ +static void +opti822_recalc(opti822_t *dev) { - uint8_t pci_conf[256]; -} opti822_t; + int reg; + int bit_r; + int bit_w; + int state; + uint32_t base; -int opti822_irq_routing[7] = {5, 9, 0x0a, 0x0b, 0x0c, 0x0e, 0x0f}; + for (uint8_t i = 0; i < 12; i++) { + base = 0x000c0000 + (i << 14); + reg = 0x44 + ((i >> 2) ^ 3); + bit_w = (i & 3); + bit_r = bit_w + 4; + bit_w = 1 << bit_w; + bit_r = 1 << bit_r; + state = (dev->pci_regs[reg] & bit_w) ? MEM_WRITE_INTERNAL : MEM_WRITE_EXTANY; + state |= (dev->pci_regs[reg] & bit_r) ? MEM_READ_INTERNAL : MEM_READ_EXTANY; + mem_set_mem_state_bus_both(base, 0x00004000, state); + } -void opti822_shadow(int cur_reg, opti822_t *dev) + state = (dev->pci_regs[0x44] & 0x01) ? MEM_WRITE_INTERNAL : MEM_WRITE_EXTANY; + state |= (dev->pci_regs[0x44] & 0x02) ? MEM_READ_INTERNAL : MEM_READ_EXTANY; + mem_set_mem_state_bus_both(0x000f0000, 0x00010000, state); +} + +/* NOTE: We cheat here. The real ALi M1435 uses a level to edge triggered IRQ converter + when the most siginificant bit is set. We work around that by manipulating the + emulated PIC's ELCR register. */ +static void +opti822_update_irqs(opti822_t *dev, int set) { - if (cur_reg == 0x44) - mem_set_mem_state_both(0xf0000, 0x10000, SYSTEM_READ | SYSTEM_WRITE); - else - for (int i = 0; i < 4; i++) - mem_set_mem_state_both(0xe0000 - (((cur_reg & 3) - 1) << 16) + (i << 14), 0x4000, SHADOW_READ | SHADOW_WRITE); + uint8_t val; + int reg; + int shift; + int irq; + int irq_map[8] = { -1, 5, 9, 10, 11, 12, 14, 15 }; + pic_t *temp_pic; - flushmmucache_nopc(); +#if 0 + dev->irq_convert = (dev->pci_regs[0x53] & 0x08); +#endif + dev->irq_convert = 1; + + for (uint8_t i = 0; i < 16; i++) { + reg = 0x88 + (i >> 1); + shift = (i & 1) << 2; + val = (dev->pci_regs[reg] >> shift) & 0x0f; + irq = irq_map[val & 0x07]; + if (irq == -1) + continue; + temp_pic = (irq >= 8) ? &pic2 : &pic; + irq &= 7; + if (dev->irq_convert && set && (val & 0x08)) + temp_pic->elcr |= (1 << irq); + else + temp_pic->elcr &= ~(1 << irq); + } } static void -opti822_write(int func, int addr, uint8_t val, void *priv) +opti822_pci_write(int func, int addr, uint8_t val, void *priv) { + opti822_t *dev = (opti822_t *) priv; + int irq; + int irq_map[8] = { -1, 5, 9, 10, 11, 12, 14, 15 }; + int pin; + int slot; - opti822_t *dev = (opti822_t *)priv; + opti822_log("opti822_write(%02X, %02X, %02X)\n", func, addr, val); - switch (func) - { - case 0x04: /* Command Register */ - dev->pci_conf[addr] = val & 0x40; - break; + if (func > 0) + return; - case 0x05: /* Command Register */ - dev->pci_conf[addr] = val & 1; - break; + switch (addr) { + /* Command Register */ + case 0x04: + dev->pci_regs[addr] = (val & 0x40) | 0x07; + break; - case 0x06: /* Status Register */ - dev->pci_conf[addr] |= val & 0xc0; - break; + /* Status Register */ + case 0x06: + if (!(dev->pci_regs[0x52] & 0x04)) + dev->pci_regs[addr] = (val & 0x80); + break; + case 0x07: + dev->pci_regs[addr] &= ~(val & 0xf9); + break; - case 0x07: /* Status Register */ - dev->pci_conf[addr] = val & 0xa9; - break; + /* Master Latency Timer Register */ + case 0x0d: + dev->pci_regs[addr] = val; + break; - case 0x40: - dev->pci_conf[addr] = val & 0xc0; - break; + case 0x40: + dev->pci_regs[addr] = (val & 0xc0) | 0x01; + break; + case 0x41: + /* TODO: Bit 15th enable the PCI Bridge when 1. */ + dev->pci_regs[addr] = val & 0xcf; + break; - case 0x41: - dev->pci_conf[addr] = val & 0xcf; - break; + case 0x42: + dev->pci_regs[addr] = val & 0xf8; + break; + case 0x43: + dev->pci_regs[addr] = val; + break; - case 0x42: - dev->pci_conf[addr] = val & 0xf8; - break; + case 0x44: + dev->pci_regs[addr] = val & 0xcb; + opti822_recalc(dev); + break; + case 0x45 ... 0x47: + dev->pci_regs[addr] = val; + opti822_recalc(dev); + break; - case 0x43: - dev->pci_conf[addr] = val; - break; + /* Memory hole stuff. */ + case 0x48 ... 0x51: + dev->pci_regs[addr] = val; + break; - case 0x44: /* Shadow RAM */ - case 0x45: - case 0x46: - case 0x47: - dev->pci_conf[addr] = (addr == 0x44) ? (val & 0xcb) : val; - opti822_shadow(addr, dev); - break; + case 0x52: + dev->pci_regs[addr] = val; + break; - case 0x48: - case 0x49: - case 0x4a: - case 0x4b: - case 0x4c: - case 0x4d: - case 0x4e: - case 0x4f: - case 0x50: - case 0x51: - case 0x52: - case 0x53: - case 0x54: - case 0x55: - case 0x56: - case 0x57: - dev->pci_conf[addr] = val; - break; + case 0x53: + dev->pci_regs[addr] = val; + opti822_update_irqs(dev, 0); + opti822_update_irqs(dev, 1); + break; - case 0x58: - dev->pci_conf[addr] = val & 0xfc; - break; + case 0x54 ... 0x57: + dev->pci_regs[addr] = val; + break; - case 0x59: - case 0x5a: - case 0x5b: - case 0x5c: - case 0x5d: - case 0x5e: - case 0x5f: - dev->pci_conf[addr] = val; - break; + case 0x58: + dev->pci_regs[addr] = val & 0xfc; + break; + case 0x59 ... 0x5b: + dev->pci_regs[addr] = val; + break; - case 0x60: - dev->pci_conf[addr] = val & 0xfc; - break; + case 0x5c ... 0x5f: + dev->pci_regs[addr] = val; + break; - case 0x61: - case 0x62: - case 0x63: - case 0x64: - case 0x65: - case 0x66: - case 0x67: - dev->pci_conf[addr] = val; - break; + case 0x60: + dev->pci_regs[addr] = val & 0xfc; + break; + case 0x61 ... 0x63: + dev->pci_regs[addr] = val; + break; - case 0x68: - dev->pci_conf[addr] = val & 0xfc; - break; + case 0x64 ... 0x67: + dev->pci_regs[addr] = val; + break; - case 0x69: - case 0x6a: - case 0x6b: - case 0x6c: - case 0x6d: - case 0x6e: - case 0x6f: - dev->pci_conf[addr] = val; - break; + case 0x68: + dev->pci_regs[addr] = val & 0xfc; + break; + case 0x69 ... 0x6b: + dev->pci_regs[addr] = val; + break; - case 0x70: - dev->pci_conf[addr] = val & 0xfc; - break; + case 0x6c ... 0x6f: + dev->pci_regs[addr] = val; + break; - case 0x71: - case 0x72: - case 0x73: - dev->pci_conf[addr] = val; - break; + case 0x70: + dev->pci_regs[addr] = val & 0xfc; + break; + case 0x71 ... 0x73: + dev->pci_regs[addr] = val; + break; - case 0x74: - dev->pci_conf[addr] = val & 0xfc; - break; + case 0x74: + dev->pci_regs[addr] = val & 0xf8; + break; - case 0x75: - case 0x76: - dev->pci_conf[addr] = val; - break; + /* ROMCS# and NVMCS# stuff. */ + case 0x75: + dev->pci_regs[addr] = val; + break; - case 0x77: - dev->pci_conf[addr] = val & 0xe7; - break; + case 0x76: + dev->pci_regs[addr] = val; + break; - case 0x78: - dev->pci_conf[addr] = val; - break; + case 0x77: + dev->pci_regs[addr] = val; + break; - case 0x79: - dev->pci_conf[addr] = val & 0xfc; - break; + /* Enabling of memory blocks at ISA bus. */ + case 0x78: + dev->pci_regs[addr] = val; + break; + case 0x79: + dev->pci_regs[addr] = val & 0xfc; + break; - case 0x7a: - case 0x7b: - case 0x7c: - case 0x7d: - case 0x7e: - dev->pci_conf[addr] = val; - break; + case 0x7a: + dev->pci_regs[addr] = val; + break; - case 0x7f: - dev->pci_conf[addr] = val & 3; - break; + case 0x7b ... 0x7c: + dev->pci_regs[addr] = val; + break; - case 0x80: - case 0x81: - case 0x82: - case 0x84: - case 0x85: - case 0x86: - dev->pci_conf[addr] = val; - break; + case 0x7d ... 0x7e: + dev->pci_regs[addr] = val; + break; - case 0x88: /* PCI IRQ Routing */ - case 0x89: /* Very hacky implementation. Needs surely a rewrite after */ - case 0x8a: /* a PCI rework happens. */ - case 0x8b: - case 0x8c: - case 0x8d: - case 0x8e: - case 0x8f: - dev->pci_conf[addr] = val; - if (addr % 2) - { - pci_set_irq_routing(PCI_INTB, ((val & 0x0f) != 0) ? opti822_irq_routing[(val & 7) - 1] : PCI_IRQ_DISABLED); - pci_set_irq_routing(PCI_INTA, (((val >> 4) & 0x0f) != 0) ? opti822_irq_routing[((val >> 4) & 7) - 1] : PCI_IRQ_DISABLED); - } - else - { - pci_set_irq_routing(PCI_INTD, ((val & 0x0f) != 0) ? opti822_irq_routing[(val & 7) - 1] : PCI_IRQ_DISABLED); - pci_set_irq_routing(PCI_INTC, (((val >> 4) & 0x0f) != 0) ? opti822_irq_routing[((val >> 4) & 7) - 1] : PCI_IRQ_DISABLED); - } - break; + case 0x7f: + dev->pci_regs[addr] = val & 0x03; + break; + + case 0x80 ... 0x81: + dev->pci_regs[addr] = val; + break; + case 0x82: + dev->pci_regs[addr] = val; + break; + + case 0x84 ... 0x85: + dev->pci_regs[addr] = val; + break; + case 0x86: + dev->pci_regs[addr] = val; + break; + + case 0x88 ... 0x8f: + dev->pci_regs[addr] = val; + opti822_update_irqs(dev, 0); + irq = irq_map[val & 0x07]; + pin = 4 - ((addr & 0x01) << 1); + slot = ((addr & 0x06) >> 1); + if (irq >= 0) { + opti822_log("Set IRQ routing: INT %c%c -> %02X\n", pin + 0x40, slot + 0x31, irq); + pci_set_irq_routing(pin + (slot << 2), irq); + pci_set_irq_level(pin + (slot << 2), !!(val & 0x07)); + } else { + opti822_log("Set IRQ routing: INT %c%c -> FF\n", pin + 0x40, slot + 0x31); + pci_set_irq_routing(pin + (slot << 2), PCI_IRQ_DISABLED); + } + irq = irq_map[(val >> 4) & 0x07]; + pin = 3 - ((addr & 0x01) << 1); + slot = ((addr & 0x06) >> 1); + if (irq >= 0) { + opti822_log("Set IRQ routing: INT %c%c -> %02X\n", pin + 0x40, slot + 0x31, irq); + pci_set_irq_routing(pin + (slot << 2), irq); + pci_set_irq_level(pin + (slot << 2), !!((val >> 4) & 0x07)); + } else { + opti822_log("Set IRQ routing: INT %c%c -> FF\n", pin + 0x40, slot + 0x31); + pci_set_irq_routing(pin + (slot << 2), PCI_IRQ_DISABLED); + } + opti822_update_irqs(dev, 1); + break; + + default: + break; } - - opti822_log("OPTI822: dev->pci_conf[%02x] = %02x\n", addr, dev->pci_conf[addr]); } static uint8_t -opti822_read(int func, int addr, void *priv) +opti822_pci_read(int func, int addr, void *priv) { - opti822_t *dev = (opti822_t *)priv; - return dev->pci_conf[addr]; + const opti822_t *dev = (opti822_t *) priv; + uint8_t ret; + + ret = 0xff; + + if (func == 0) + ret = dev->pci_regs[addr]; + + opti822_log("opti822_read(%02X, %02X) = %02X\n", func, addr, ret); + + return ret; } static void opti822_reset(void *priv) { - opti822_t *dev = (opti822_t *)priv; + opti822_t *dev = (opti822_t *) priv; - dev->pci_conf[0x00] = 0x45; - dev->pci_conf[0x01] = 0x10; - dev->pci_conf[0x02] = 0x22; - dev->pci_conf[0x03] = 0xc8; - dev->pci_conf[0x04] = 7; - dev->pci_conf[0x06] = 0x40; - dev->pci_conf[0x07] = 1; - dev->pci_conf[0x08] = 1; - dev->pci_conf[0x0b] = 6; - dev->pci_conf[0x0d] = 0x20; - dev->pci_conf[0x40] = 1; - dev->pci_conf[0x43] = 0x20; - dev->pci_conf[0x52] = 6; - dev->pci_conf[0x53] = 0x90; + memset(dev->pci_regs, 0, 256); + + dev->pci_regs[0x00] = 0x45; + dev->pci_regs[0x01] = 0x10; /*OPTi*/ + dev->pci_regs[0x02] = 0x22; + dev->pci_regs[0x03] = 0xc8; /*82C822 PCIB*/ + dev->pci_regs[0x04] = 0x07; + dev->pci_regs[0x06] = 0x80; + dev->pci_regs[0x07] = 0x02; + dev->pci_regs[0x08] = 0x01; + dev->pci_regs[0x0b] = 0x06; + dev->pci_regs[0x0d] = 0x20; + + dev->pci_regs[0x40] = 0x01; + dev->pci_regs[0x41] = 0x0c; + dev->pci_regs[0x43] = 0x02; + dev->pci_regs[0x52] = 0x06; + dev->pci_regs[0x53] = 0x90; + + dev->irq_convert = 1 /*0*/; + + for (uint8_t i = 0; i < 16; i++) + pci_set_irq_routing(PCI_INTA + i, PCI_IRQ_DISABLED); } static void opti822_close(void *priv) { - opti822_t *dev = (opti822_t *)priv; + opti822_t *dev = (opti822_t *) priv; free(dev); } static void * -opti822_init(const device_t *info) +opti822_init(UNUSED(const device_t *info)) { - opti822_t *dev = (opti822_t *)malloc(sizeof(opti822_t)); + opti822_t *dev = (opti822_t *) malloc(sizeof(opti822_t)); memset(dev, 0, sizeof(opti822_t)); - pci_add_card(PCI_ADD_NORTHBRIDGE, opti822_read, opti822_write, dev); + pci_add_card(PCI_ADD_NORTHBRIDGE, opti822_pci_read, opti822_pci_write, dev, &dev->pci_slot); opti822_reset(dev); @@ -310,14 +405,15 @@ opti822_init(const device_t *info) } const device_t opti822_device = { - "OPTi 82C822 PCIB", - "opti822", - DEVICE_PCI, - 0, - opti822_init, - opti822_close, - opti822_reset, - {NULL}, - NULL, - NULL, - NULL}; + .name = "OPTi 82C822 PCIB", + .internal_name = "opti822", + .flags = DEVICE_PCI, + .local = 0, + .init = opti822_init, + .close = opti822_close, + .reset = opti822_reset, + { .available = NULL }, + .speed_changed = NULL, + .force_redraw = NULL, + .config = NULL +}; diff --git a/src/chipset/opti895.c b/src/chipset/opti895.c index 14b0080fd..77297ae95 100644 --- a/src/chipset/opti895.c +++ b/src/chipset/opti895.c @@ -1,20 +1,20 @@ /* - * 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. + * 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. + * This file is part of the 86Box distribution. * - * Implementation of the OPTi 82C802G/82C895 chipset. + * Implementation of the OPTi 82C802G/82C895 chipset. * * * - * Authors: Tiseno100, - * Miran Grca, + * Authors: Tiseno100, + * Miran Grca, * - * Copyright 2008-2020 Tiseno100. - * Copyright 2016-2020 Miran Grca. + * Copyright 2008-2020 Tiseno100. + * Copyright 2016-2020 Miran Grca. */ #include #include @@ -32,196 +32,212 @@ #include <86box/port_92.h> #include <86box/chipset.h> +typedef struct opti895_t { + uint8_t idx; + uint8_t forced_green; + uint8_t is_pci; + uint8_t regs[256]; + uint8_t scratch[2]; -typedef struct -{ - uint8_t idx, forced_green, - regs[256], - scratch[2]; - - smram_t *smram; + smram_t *smram; } opti895_t; - -#define ENABLE_OPTI895_LOG 1 #ifdef ENABLE_OPTI895_LOG int opti895_do_log = ENABLE_OPTI895_LOG; - static void opti895_log(const char *fmt, ...) { va_list ap; if (opti895_do_log) { - va_start(ap, fmt); - pclog_ex(fmt, ap); - va_end(ap); + va_start(ap, fmt); + pclog_ex(fmt, ap); + va_end(ap); } } #else -#define opti895_log(fmt, ...) +# define opti895_log(fmt, ...) #endif - static void opti895_recalc(opti895_t *dev) { uint32_t base; - uint32_t i, shflags = 0; + uint32_t shflags = 0; - shadowbios = 0; + shadowbios = 0; shadowbios_write = 0; if (dev->regs[0x22] & 0x80) { - shadowbios = 1; - shadowbios_write = 0; - shflags = MEM_READ_EXTANY | MEM_WRITE_INTERNAL; + shadowbios = 1; + shadowbios_write = 0; + shflags = MEM_READ_EXTANY | MEM_WRITE_INTERNAL; } else { - shadowbios = 0; - shadowbios_write = 1; - shflags = MEM_READ_INTERNAL | MEM_WRITE_DISABLED; + shadowbios = 0; + shadowbios_write = 1; + shflags = MEM_READ_INTERNAL | MEM_WRITE_DISABLED; } - mem_set_mem_state_both(0xf0000, 0x10000, shflags); + if (dev->is_pci) + mem_set_mem_state_cpu_both(0xf0000, 0x10000, shflags); + else + mem_set_mem_state_both(0xf0000, 0x10000, shflags); - for (i = 0; i < 8; i++) { - base = 0xd0000 + (i << 14); + for (uint8_t i = 0; i < 8; i++) { + base = 0xd0000 + (i << 14); - if (dev->regs[0x23] & (1 << i)) { - shflags = MEM_READ_INTERNAL; - shflags |= (dev->regs[0x22] & ((base >= 0xe0000) ? 0x08 : 0x10)) ? MEM_WRITE_DISABLED : MEM_WRITE_INTERNAL; - } else { - shflags = (dev->regs[0x2d] & (1 << ((i >> 1) + 2))) ? MEM_READ_EXTANY : MEM_READ_EXTERNAL; - if (dev->regs[0x26] & 0x40) - shflags |= (dev->regs[0x22] & ((base >= 0xe0000) ? 0x08 : 0x10)) ? MEM_WRITE_DISABLED : MEM_WRITE_INTERNAL; - else { - if (dev->regs[0x26] & 0x80) - shflags |= (dev->regs[0x2d] & (1 << ((i >> 1) + 2))) ? MEM_WRITE_EXTANY : MEM_WRITE_EXTERNAL; - else - shflags |= MEM_WRITE_EXTERNAL; - } - } + if (dev->regs[0x23] & (1 << i)) { + shflags = MEM_READ_INTERNAL; + shflags |= (dev->regs[0x22] & ((base >= 0xe0000) ? 0x08 : 0x10)) ? MEM_WRITE_DISABLED : MEM_WRITE_INTERNAL; + } else { + shflags = (dev->regs[0x2d] & (1 << ((i >> 1) + 2))) ? MEM_READ_EXTANY : MEM_READ_EXTERNAL; + if (dev->regs[0x26] & 0x40) + shflags |= (dev->regs[0x22] & ((base >= 0xe0000) ? 0x08 : 0x10)) ? MEM_WRITE_DISABLED : MEM_WRITE_INTERNAL; + else { + if (dev->regs[0x26] & 0x80) + shflags |= (dev->regs[0x2d] & (1 << ((i >> 1) + 2))) ? MEM_WRITE_EXTANY : MEM_WRITE_EXTERNAL; + else + shflags |= MEM_WRITE_EXTERNAL; + } + } - mem_set_mem_state_both(base, 0x4000, shflags); + if (dev->is_pci) + mem_set_mem_state_cpu_both(base, 0x4000, shflags); + else + mem_set_mem_state_both(base, 0x4000, shflags); } - for (i = 0; i < 4; i++) { - base = 0xc0000 + (i << 14); + for (uint8_t i = 0; i < 4; i++) { + base = 0xc0000 + (i << 14); - if (dev->regs[0x26] & (1 << i)) { - shflags = MEM_READ_INTERNAL; - shflags |= (dev->regs[0x26] & 0x20) ? MEM_WRITE_DISABLED : MEM_WRITE_INTERNAL; - } else { - shflags = (dev->regs[0x2d] & (1 << (i >> 1))) ? MEM_READ_EXTANY : MEM_READ_EXTERNAL; - if (dev->regs[0x26] & 0x40) - shflags |= (dev->regs[0x26] & 0x20) ? MEM_WRITE_DISABLED : MEM_WRITE_INTERNAL; - else { - if (dev->regs[0x26] & 0x80) - shflags |= (dev->regs[0x2d] & (1 << (i >> 1))) ? MEM_WRITE_EXTANY : MEM_WRITE_EXTERNAL; - else - shflags |= MEM_WRITE_EXTERNAL; - } - } + if (dev->regs[0x26] & (1 << i)) { + shflags = MEM_READ_INTERNAL; + shflags |= (dev->regs[0x26] & 0x20) ? MEM_WRITE_DISABLED : MEM_WRITE_INTERNAL; + } else { + shflags = (dev->regs[0x2d] & (1 << (i >> 1))) ? MEM_READ_EXTANY : MEM_READ_EXTERNAL; + if (dev->regs[0x26] & 0x40) + shflags |= (dev->regs[0x26] & 0x20) ? MEM_WRITE_DISABLED : MEM_WRITE_INTERNAL; + else { + if (dev->regs[0x26] & 0x80) + shflags |= (dev->regs[0x2d] & (1 << (i >> 1))) ? MEM_WRITE_EXTANY : MEM_WRITE_EXTERNAL; + else + shflags |= MEM_WRITE_EXTERNAL; + } + } - mem_set_mem_state_both(base, 0x4000, shflags); + if (dev->is_pci) + mem_set_mem_state_cpu_both(base, 0x4000, shflags); + else + mem_set_mem_state_both(base, 0x4000, shflags); } flushmmucache_nopc(); } - static void opti895_write(uint16_t addr, uint8_t val, void *priv) { opti895_t *dev = (opti895_t *) priv; + opti895_log("opti895_write(%04X, %08X)\n", addr, val); + switch (addr) { - case 0x22: - dev->idx = val; - break; - case 0x23: - if (dev->idx == 0x01) { - dev->regs[dev->idx] = val; - opti895_log("dev->regs[%04x] = %08x\n", dev->idx, val); - } - break; - case 0x24: - if (((dev->idx >= 0x20) && (dev->idx <= 0x2f)) || - ((dev->idx >= 0xe0) && (dev->idx <= 0xef))) { - dev->regs[dev->idx] = val; - opti895_log("dev->regs[%04x] = %08x\n", dev->idx, val); + case 0x22: + dev->idx = val; + break; + case 0x23: + if (dev->idx == 0x01) { + dev->regs[dev->idx] = val; + opti895_log("dev->regs[%04x] = %08x\n", dev->idx, val); + } + break; + case 0x24: + if (((dev->idx >= 0x20) && (dev->idx <= 0x2f)) || ((dev->idx >= 0xe0) && (dev->idx <= 0xef))) { + dev->regs[dev->idx] = val; + opti895_log("dev->regs[%04x] = %08x\n", dev->idx, val); - switch(dev->idx) { - case 0x21: - cpu_cache_ext_enabled = !!(dev->regs[0x21] & 0x10); - cpu_update_waitstates(); - break; + /* TODO: Registers 0x30-0x3F for OPTi 802GP and 898. */ + switch (dev->idx) { + case 0x21: + cpu_cache_ext_enabled = !!(dev->regs[0x21] & 0x10); + cpu_update_waitstates(); + break; - case 0x22: - case 0x23: - case 0x26: - case 0x2d: - opti895_recalc(dev); - break; + case 0x22: + case 0x23: + case 0x26: + case 0x2d: + opti895_recalc(dev); + break; - case 0x24: - smram_state_change(dev->smram, 0, !!(val & 0x80)); - break; + case 0x24: + smram_state_change(dev->smram, 0, !!(val & 0x80)); + break; - case 0xe0: - if (!(val & 0x01)) - dev->forced_green = 0; - break; + case 0xe0: + if (!(val & 0x01)) + dev->forced_green = 0; + break; - case 0xe1: - if ((val & 0x08) && (dev->regs[0xe0] & 0x01)) { - smi_line = 1; - dev->forced_green = 1; - break; - } - break; - } - } - break; + case 0xe1: + if ((val & 0x08) && (dev->regs[0xe0] & 0x01)) { + smi_raise(); + dev->forced_green = 1; + break; + } + break; - case 0xe1: - case 0xe2: - dev->scratch[addr - 0xe1] = val; - break; + default: + break; + } + } + break; + + case 0xe1: + case 0xe2: + dev->scratch[addr - 0xe1] = val; + break; + + default: + break; } } - static uint8_t opti895_read(uint16_t addr, void *priv) { - uint8_t ret = 0xff; - opti895_t *dev = (opti895_t *) priv; + uint8_t ret = 0xff; + const opti895_t *dev = (opti895_t *) priv; switch (addr) { - case 0x23: - if (dev->idx == 0x01) - ret = dev->regs[dev->idx]; - break; - case 0x24: - if (((dev->idx >= 0x20) && (dev->idx <= 0x2f)) || - ((dev->idx >= 0xe0) && (dev->idx <= 0xef))) { - ret = dev->regs[dev->idx]; - if (dev->idx == 0xe0) - ret = (ret & 0xf6) | (in_smm ? 0x00 : 0x08) | !!dev->forced_green; - } - break; - case 0xe1: - case 0xe2: - ret = dev->scratch[addr - 0xe1]; - break; + case 0x23: + if (dev->idx == 0x01) + ret = dev->regs[dev->idx]; + break; + case 0x24: + /* TODO: Registers 0x30-0x3F for OPTi 802GP and 898. */ + if (((dev->idx >= 0x20) && (dev->idx <= 0x2f)) || ((dev->idx >= 0xe0) && (dev->idx <= 0xef))) { + ret = dev->regs[dev->idx]; + if (dev->idx == 0xe0) + ret = (ret & 0xf6) | (in_smm ? 0x00 : 0x08) | !!dev->forced_green; + } + break; + + case 0xe1: + case 0xe2: + ret = dev->scratch[addr - 0xe1]; + break; + + default: + break; } + opti895_log("opti895_read(%04X) = %02X\n", addr, ret); + return ret; } - static void opti895_close(void *priv) { @@ -232,7 +248,6 @@ opti895_close(void *priv) free(dev); } - static void * opti895_init(const device_t *info) { @@ -243,6 +258,8 @@ opti895_init(const device_t *info) io_sethandler(0x0022, 0x0003, opti895_read, NULL, NULL, opti895_write, NULL, NULL, dev); + dev->is_pci = info->local; + dev->scratch[0] = dev->scratch[1] = 0xff; dev->regs[0x01] = 0xc0; @@ -273,24 +290,44 @@ opti895_init(const device_t *info) return dev; } - const device_t opti802g_device = { - "OPTi 82C802G", - "opti802g", - 0, - 0, - opti895_init, opti895_close, NULL, - { NULL }, NULL, NULL, - NULL + .name = "OPTi 82C802G", + .internal_name = "opti802g", + .flags = 0, + .local = 0, + .init = opti895_init, + .close = opti895_close, + .reset = NULL, + { .available = NULL }, + .speed_changed = NULL, + .force_redraw = NULL, + .config = NULL }; +const device_t opti802g_pci_device = { + .name = "OPTi 82C802G (PCI)", + .internal_name = "opti802g_pci", + .flags = 0, + .local = 1, + .init = opti895_init, + .close = opti895_close, + .reset = NULL, + { .available = NULL }, + .speed_changed = NULL, + .force_redraw = NULL, + .config = NULL +}; const device_t opti895_device = { - "OPTi 82C895", - "opti895", - 0, - 0, - opti895_init, opti895_close, NULL, - { NULL }, NULL, NULL, - NULL + .name = "OPTi 82C895", + .internal_name = "opti895", + .flags = 0, + .local = 0, + .init = opti895_init, + .close = opti895_close, + .reset = NULL, + { .available = NULL }, + .speed_changed = NULL, + .force_redraw = NULL, + .config = NULL }; diff --git a/src/chipset/scamp.c b/src/chipset/scamp.c index 57b0120b2..122318862 100644 --- a/src/chipset/scamp.c +++ b/src/chipset/scamp.c @@ -1,23 +1,23 @@ /* - * 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. + * 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. + * This file is part of the 86Box distribution. * - * Emulation of VLSI 82C311 ("SCAMP") chipset. + * Emulation of VLSI 82C311 ("SCAMP") chipset. * - * Note: The datasheet mentions that the chipset supports up to 8MB - * of DRAM. This is intepreted as 'being able to refresh up to - * 8MB of DRAM chips', because it works fine with bus-based - * memory expansion. + * Note: The datasheet mentions that the chipset supports up to 8MB + * of DRAM. This is intepreted as 'being able to refresh up to + * 8MB of DRAM chips', because it works fine with bus-based + * memory expansion. * * * - * Authors: Sarah Walker, + * Authors: Sarah Walker, * - * Copyright 2020 Sarah Walker. + * Copyright 2020 Sarah Walker. */ #include #include @@ -31,35 +31,33 @@ #include <86box/io.h> #include <86box/mem.h> #include <86box/nmi.h> +#include <86box/plat_unused.h> #include <86box/port_92.h> #include <86box/chipset.h> +#define CFG_ID 0x00 +#define CFG_SLTPTR 0x02 +#define CFG_RAMMAP 0x03 +#define CFG_EMSEN1 0x0b +#define CFG_EMSEN2 0x0c +#define CFG_ABAXS 0x0e +#define CFG_CAXS 0x0f +#define CFG_DAXS 0x10 +#define CFG_FEAXS 0x11 -#define CFG_ID 0x00 -#define CFG_SLTPTR 0x02 -#define CFG_RAMMAP 0x03 -#define CFG_EMSEN1 0x0b -#define CFG_EMSEN2 0x0c -#define CFG_ABAXS 0x0e -#define CFG_CAXS 0x0f -#define CFG_DAXS 0x10 -#define CFG_FEAXS 0x11 - -#define ID_VL82C311 0xd6 +#define ID_VL82C311 0xd6 #define RAMMAP_REMP386 (1 << 4) #define EMSEN1_EMSMAP (1 << 4) #define EMSEN1_EMSENAB (1 << 7) -#define NR_ELEMS(x) (sizeof(x) / sizeof(x[0])) - +#define NR_ELEMS(x) (sizeof(x) / sizeof(x[0])) /*Commodore SL386SX requires proper memory slot decoding to detect memory size. Therefore we emulate the SCAMP memory address decoding, and therefore are limited to the DRAM combinations supported by the actual chip*/ -enum -{ +enum { BANK_NONE, BANK_256K, BANK_256K_INTERLEAVED, @@ -69,589 +67,597 @@ enum BANK_4M_INTERLEAVED }; - -typedef struct { - void * parent; - int bank; +typedef struct ram_struct_t { + void *parent; + int bank; } ram_struct_t; -typedef struct { - void * parent; - int segment; +typedef struct ems_struct_t { + void *parent; + int segment; } ems_struct_t; -typedef struct { - int cfg_index; - uint8_t cfg_regs[256]; - int cfg_enable, ram_config; +typedef struct scamp_t { + int cfg_index; + uint8_t cfg_regs[256]; + int cfg_enable; + int ram_config; - int ems_index; - int ems_autoinc; - uint16_t ems[0x24]; - mem_mapping_t ems_mappings[20]; /*a0000-effff*/ - uint32_t mappings[20]; + int ems_index; + int ems_autoinc; + uint16_t ems[0x24]; + mem_mapping_t ems_mappings[20]; /*a0000-effff*/ + uint32_t mappings[20]; mem_mapping_t ram_mapping[2]; - ram_struct_t ram_struct[2]; - ems_struct_t ems_struct[20]; + ram_struct_t ram_struct[2]; + ems_struct_t ems_struct[20]; - uint32_t ram_virt_base[2], ram_phys_base[2]; - uint32_t ram_mask[2]; - int row_virt_shift[2], row_phys_shift[2]; - int ram_interleaved[2], ibank_shift[2]; + uint32_t ram_virt_base[2]; + uint32_t ram_phys_base[2]; + uint32_t ram_mask[2]; + int row_virt_shift[2]; + int row_phys_shift[2]; + int ram_interleaved[2]; + int ibank_shift[2]; - port_92_t * port_92; + port_92_t *port_92; } scamp_t; -static const struct -{ - int size_kb; - int rammap; - int bank[2]; -} ram_configs[] = -{ - {512, 0x0, {BANK_256K, BANK_NONE}}, - {1024, 0x1, {BANK_256K_INTERLEAVED, BANK_NONE}}, - {1536, 0x2, {BANK_256K_INTERLEAVED, BANK_256K}}, - {2048, 0x3, {BANK_256K_INTERLEAVED, BANK_256K_INTERLEAVED}}, - {3072, 0xc, {BANK_256K_INTERLEAVED, BANK_1M}}, - {4096, 0x5, {BANK_1M_INTERLEAVED, BANK_NONE}}, - {5120, 0xd, {BANK_256K_INTERLEAVED, BANK_1M_INTERLEAVED}}, - {6144, 0x6, {BANK_1M_INTERLEAVED, BANK_1M}}, - {8192, 0x7, {BANK_1M_INTERLEAVED, BANK_1M_INTERLEAVED}}, - {12288, 0xe, {BANK_1M_INTERLEAVED, BANK_4M}}, - {16384, 0x9, {BANK_4M_INTERLEAVED, BANK_NONE}}, +static const struct { + int size_kb; + int rammap; + int bank[2]; +} ram_configs[] = { + { 512, 0x0, { BANK_256K, BANK_NONE } }, + { 1024, 0x1, { BANK_256K_INTERLEAVED, BANK_NONE } }, + { 1536, 0x2, { BANK_256K_INTERLEAVED, BANK_256K } }, + { 2048, 0x3, { BANK_256K_INTERLEAVED, BANK_256K_INTERLEAVED }}, + { 3072, 0xc, { BANK_256K_INTERLEAVED, BANK_1M } }, + { 4096, 0x5, { BANK_1M_INTERLEAVED, BANK_NONE } }, + { 5120, 0xd, { BANK_256K_INTERLEAVED, BANK_1M_INTERLEAVED } }, + { 6144, 0x6, { BANK_1M_INTERLEAVED, BANK_1M } }, + { 8192, 0x7, { BANK_1M_INTERLEAVED, BANK_1M_INTERLEAVED } }, + { 12288, 0xe, { BANK_1M_INTERLEAVED, BANK_4M } }, + { 16384, 0x9, { BANK_4M_INTERLEAVED, BANK_NONE } }, }; -static const struct -{ - int bank[2]; - int remapped; -} rammap[16] = -{ - {{BANK_256K, BANK_NONE}, 0}, - {{BANK_256K_INTERLEAVED, BANK_NONE}, 0}, - {{BANK_256K_INTERLEAVED, BANK_256K}, 0}, - {{BANK_256K_INTERLEAVED, BANK_256K_INTERLEAVED}, 0}, +static const struct { + int bank[2]; + int remapped; +} rammap[16] = { + { { BANK_256K, BANK_NONE }, 0}, + { { BANK_256K_INTERLEAVED, BANK_NONE }, 0}, + { { BANK_256K_INTERLEAVED, BANK_256K }, 0}, + { { BANK_256K_INTERLEAVED, BANK_256K_INTERLEAVED }, 0}, - {{BANK_1M, BANK_NONE}, 0}, - {{BANK_1M_INTERLEAVED, BANK_NONE}, 0}, - {{BANK_1M_INTERLEAVED, BANK_1M}, 0}, - {{BANK_1M_INTERLEAVED, BANK_1M_INTERLEAVED}, 0}, + { { BANK_1M, BANK_NONE }, 0}, + { { BANK_1M_INTERLEAVED, BANK_NONE }, 0}, + { { BANK_1M_INTERLEAVED, BANK_1M }, 0}, + { { BANK_1M_INTERLEAVED, BANK_1M_INTERLEAVED }, 0}, - {{BANK_4M, BANK_NONE}, 0}, - {{BANK_4M_INTERLEAVED, BANK_NONE}, 0}, - {{BANK_NONE, BANK_4M}, 1}, /*Bank 2 remapped to 0*/ - {{BANK_NONE, BANK_4M_INTERLEAVED}, 1}, /*Banks 2/3 remapped to 0/1*/ + { { BANK_4M, BANK_NONE }, 0}, + { { BANK_4M_INTERLEAVED, BANK_NONE }, 0}, + { { BANK_NONE, BANK_4M }, 1}, /*Bank 2 remapped to 0*/ + { { BANK_NONE, BANK_4M_INTERLEAVED }, 1}, /*Banks 2/3 remapped to 0/1*/ - {{BANK_256K_INTERLEAVED, BANK_1M}, 0}, - {{BANK_256K_INTERLEAVED, BANK_1M_INTERLEAVED}, 0}, - {{BANK_1M_INTERLEAVED, BANK_4M}, 0}, - {{BANK_1M_INTERLEAVED, BANK_4M_INTERLEAVED}, 0}, /*Undocumented - probably wrong!*/ + { { BANK_256K_INTERLEAVED, BANK_1M }, 0}, + { { BANK_256K_INTERLEAVED, BANK_1M_INTERLEAVED }, 0}, + { { BANK_1M_INTERLEAVED, BANK_4M }, 0}, + { { BANK_1M_INTERLEAVED, BANK_4M_INTERLEAVED }, 0}, /*Undocumented - probably wrong!*/ }; - /* The column bits masked when using 256kbit DRAMs in 4Mbit mode aren't contiguous, so we use separate routines for that special case */ -static uint8_t +static uint8_t ram_mirrored_256k_in_4mi_read(uint32_t addr, void *priv) { - ram_struct_t *rs = (ram_struct_t *) priv; - scamp_t *dev = rs->parent; - int bank = rs->bank, byte; - int row, column; + const ram_struct_t *rs = (ram_struct_t *) priv; + const scamp_t *dev = rs->parent; + int bank = rs->bank; + int byte; + int row; + int column; addr -= dev->ram_virt_base[bank]; byte = addr & 1; if (!dev->ram_interleaved[bank]) { - if (addr & 0x400) - return 0xff; + if (addr & 0x400) + return 0xff; - addr = (addr & 0x3ff) | ((addr & ~0x7ff) >> 1); - column = (addr >> 1) & dev->ram_mask[bank]; - row = ((addr & 0xff000) >> 13) | (((addr & 0x200000) >> 22) << 9); + addr = (addr & 0x3ff) | ((addr & ~0x7ff) >> 1); + column = (addr >> 1) & dev->ram_mask[bank]; + row = ((addr & 0xff000) >> 13) | (((addr & 0x200000) >> 22) << 9); - addr = byte | (column << 1) | (row << dev->row_phys_shift[bank]); + addr = byte | (column << 1) | (row << dev->row_phys_shift[bank]); } else { - column = (addr >> 1) & ((dev->ram_mask[bank] << 1) | 1); - row = ((addr & 0x1fe000) >> 13) | (((addr & 0x400000) >> 22) << 9); + column = (addr >> 1) & ((dev->ram_mask[bank] << 1) | 1); + row = ((addr & 0x1fe000) >> 13) | (((addr & 0x400000) >> 22) << 9); - addr = byte | (column << 1) | (row << (dev->row_phys_shift[bank]+1)); + addr = byte | (column << 1) | (row << (dev->row_phys_shift[bank] + 1)); } return ram[addr + dev->ram_phys_base[bank]]; } - -static void +static void ram_mirrored_256k_in_4mi_write(uint32_t addr, uint8_t val, void *priv) { - ram_struct_t *rs = (ram_struct_t *) priv; - scamp_t *dev = rs->parent; - int bank = rs->bank, byte; - int row, column; + const ram_struct_t *rs = (ram_struct_t *) priv; + const scamp_t *dev = rs->parent; + int bank = rs->bank; + int byte; + int row; + int column; addr -= dev->ram_virt_base[bank]; byte = addr & 1; if (!dev->ram_interleaved[bank]) { - if (addr & 0x400) - return; + if (addr & 0x400) + return; - addr = (addr & 0x3ff) | ((addr & ~0x7ff) >> 1); - column = (addr >> 1) & dev->ram_mask[bank]; - row = ((addr & 0xff000) >> 13) | (((addr & 0x200000) >> 22) << 9); + addr = (addr & 0x3ff) | ((addr & ~0x7ff) >> 1); + column = (addr >> 1) & dev->ram_mask[bank]; + row = ((addr & 0xff000) >> 13) | (((addr & 0x200000) >> 22) << 9); - addr = byte | (column << 1) | (row << dev->row_phys_shift[bank]); + addr = byte | (column << 1) | (row << dev->row_phys_shift[bank]); } else { - column = (addr >> 1) & ((dev->ram_mask[bank] << 1) | 1); - row = ((addr & 0x1fe000) >> 13) | (((addr & 0x400000) >> 22) << 9); + column = (addr >> 1) & ((dev->ram_mask[bank] << 1) | 1); + row = ((addr & 0x1fe000) >> 13) | (((addr & 0x400000) >> 22) << 9); - addr = byte | (column << 1) | (row << (dev->row_phys_shift[bank]+1)); + addr = byte | (column << 1) | (row << (dev->row_phys_shift[bank] + 1)); } ram[addr + dev->ram_phys_base[bank]] = val; } - /*Read/write handlers for interleaved memory banks. We must keep CPU and ram array mapping linear, otherwise we won't be able to execute code from interleaved banks*/ -static uint8_t +static uint8_t ram_mirrored_interleaved_read(uint32_t addr, void *priv) { - ram_struct_t *rs = (ram_struct_t *) priv; - scamp_t *dev = rs->parent; - int bank = rs->bank, byte; - int row, column; + const ram_struct_t *rs = (ram_struct_t *) priv; + const scamp_t *dev = rs->parent; + int bank = rs->bank; + int byte; + int row; + int column; addr -= dev->ram_virt_base[bank]; byte = addr & 1; if (!dev->ram_interleaved[bank]) { - if (addr & 0x400) - return 0xff; + if (addr & 0x400) + return 0xff; - addr = (addr & 0x3ff) | ((addr & ~0x7ff) >> 1); - column = (addr >> 1) & dev->ram_mask[bank]; - row = (addr >> dev->row_virt_shift[bank]) & dev->ram_mask[bank]; + addr = (addr & 0x3ff) | ((addr & ~0x7ff) >> 1); + column = (addr >> 1) & dev->ram_mask[bank]; + row = (addr >> dev->row_virt_shift[bank]) & dev->ram_mask[bank]; - addr = byte | (column << 1) | (row << dev->row_phys_shift[bank]); + addr = byte | (column << 1) | (row << dev->row_phys_shift[bank]); } else { - column = (addr >> 1) & ((dev->ram_mask[bank] << 1) | 1); - row = (addr >> (dev->row_virt_shift[bank]+1)) & dev->ram_mask[bank]; + column = (addr >> 1) & ((dev->ram_mask[bank] << 1) | 1); + row = (addr >> (dev->row_virt_shift[bank] + 1)) & dev->ram_mask[bank]; - addr = byte | (column << 1) | (row << (dev->row_phys_shift[bank]+1)); + addr = byte | (column << 1) | (row << (dev->row_phys_shift[bank] + 1)); } return ram[addr + dev->ram_phys_base[bank]]; } - -static void +static void ram_mirrored_interleaved_write(uint32_t addr, uint8_t val, void *priv) { - ram_struct_t *rs = (ram_struct_t *) priv; - scamp_t *dev = rs->parent; - int bank = rs->bank, byte; - int row, column; + const ram_struct_t *rs = (ram_struct_t *) priv; + const scamp_t *dev = rs->parent; + int bank = rs->bank; + int byte; + int row; + int column; addr -= dev->ram_virt_base[bank]; byte = addr & 1; if (!dev->ram_interleaved[bank]) { - if (addr & 0x400) - return; + if (addr & 0x400) + return; - addr = (addr & 0x3ff) | ((addr & ~0x7ff) >> 1); - column = (addr >> 1) & dev->ram_mask[bank]; - row = (addr >> dev->row_virt_shift[bank]) & dev->ram_mask[bank]; + addr = (addr & 0x3ff) | ((addr & ~0x7ff) >> 1); + column = (addr >> 1) & dev->ram_mask[bank]; + row = (addr >> dev->row_virt_shift[bank]) & dev->ram_mask[bank]; - addr = byte | (column << 1) | (row << dev->row_phys_shift[bank]); + addr = byte | (column << 1) | (row << dev->row_phys_shift[bank]); } else { - column = (addr >> 1) & ((dev->ram_mask[bank] << 1) | 1); - row = (addr >> (dev->row_virt_shift[bank]+1)) & dev->ram_mask[bank]; + column = (addr >> 1) & ((dev->ram_mask[bank] << 1) | 1); + row = (addr >> (dev->row_virt_shift[bank] + 1)) & dev->ram_mask[bank]; - addr = byte | (column << 1) | (row << (dev->row_phys_shift[bank]+1)); + addr = byte | (column << 1) | (row << (dev->row_phys_shift[bank] + 1)); } ram[addr + dev->ram_phys_base[bank]] = val; } - -static uint8_t +static uint8_t ram_mirrored_read(uint32_t addr, void *priv) { - ram_struct_t *rs = (ram_struct_t *) priv; - scamp_t *dev = rs->parent; - int bank = rs->bank, byte; - int row, column; + const ram_struct_t *rs = (ram_struct_t *) priv; + const scamp_t *dev = rs->parent; + int bank = rs->bank; + int byte; + int row; + int column; addr -= dev->ram_virt_base[bank]; - byte = addr & 1; + byte = addr & 1; column = (addr >> 1) & dev->ram_mask[bank]; - row = (addr >> dev->row_virt_shift[bank]) & dev->ram_mask[bank]; - addr = byte | (column << 1) | (row << dev->row_phys_shift[bank]); + row = (addr >> dev->row_virt_shift[bank]) & dev->ram_mask[bank]; + addr = byte | (column << 1) | (row << dev->row_phys_shift[bank]); return ram[addr + dev->ram_phys_base[bank]]; } - -static void +static void ram_mirrored_write(uint32_t addr, uint8_t val, void *priv) { - ram_struct_t *rs = (ram_struct_t *) priv; - scamp_t *dev = rs->parent; - int bank = rs->bank, byte; - int row, column; - + const ram_struct_t *rs = (ram_struct_t *) priv; + const scamp_t *dev = rs->parent; + int bank = rs->bank; + int byte; + int row; + int column; + addr -= dev->ram_virt_base[bank]; - byte = addr & 1; + byte = addr & 1; column = (addr >> 1) & dev->ram_mask[bank]; - row = (addr >> dev->row_virt_shift[bank]) & dev->ram_mask[bank]; - addr = byte | (column << 1) | (row << dev->row_phys_shift[bank]); + row = (addr >> dev->row_virt_shift[bank]) & dev->ram_mask[bank]; + addr = byte | (column << 1) | (row << dev->row_phys_shift[bank]); ram[addr + dev->ram_phys_base[bank]] = val; } - -static void +static void recalc_mappings(void *priv) { scamp_t *dev = (scamp_t *) priv; - int c; - uint32_t virt_base = 0, old_virt_base; - uint8_t cur_rammap = dev->cfg_regs[CFG_RAMMAP] & 0xf; - int bank_nr = 0, phys_bank; + uint32_t virt_base = 0; + uint32_t old_virt_base; + uint8_t cur_rammap = dev->cfg_regs[CFG_RAMMAP] & 0xf; + int bank_nr = 0; + int phys_bank; mem_set_mem_state_both((1 << 20), (16256 - 1024) * 1024, MEM_READ_EXTERNAL | MEM_WRITE_EXTERNAL); mem_set_mem_state(0xfe0000, 0x20000, MEM_READ_EXTANY | MEM_WRITE_EXTANY); - for (c = 0; c < 2; c++) - mem_mapping_disable(&dev->ram_mapping[c]); + for (uint8_t c = 0; c < 2; c++) + mem_mapping_disable(&dev->ram_mapping[c]); /* Once the BIOS programs the correct DRAM configuration, switch to regular linear memory mapping */ if (cur_rammap == ram_configs[dev->ram_config].rammap) { - mem_mapping_set_handler(&ram_low_mapping, - mem_read_ram, mem_read_ramw, mem_read_raml, - mem_write_ram, mem_write_ramw, mem_write_raml); - mem_mapping_set_addr(&ram_low_mapping, 0, 0xa0000); - if (mem_size > 1024) - mem_set_mem_state_both((1 << 20), (mem_size - 1024) << 10, MEM_READ_INTERNAL | MEM_WRITE_INTERNAL); - mem_mapping_enable(&ram_high_mapping); - return; + mem_mapping_set_handler(&ram_low_mapping, + mem_read_ram, mem_read_ramw, mem_read_raml, + mem_write_ram, mem_write_ramw, mem_write_raml); + mem_mapping_set_addr(&ram_low_mapping, 0, 0xa0000); + if (mem_size > 1024) + mem_set_mem_state_both((1 << 20), (mem_size - 1024) << 10, MEM_READ_INTERNAL | MEM_WRITE_INTERNAL); + mem_mapping_enable(&ram_high_mapping); + return; } else { - mem_mapping_set_handler(&ram_low_mapping, - ram_mirrored_read, NULL, NULL, - ram_mirrored_write, NULL, NULL); - mem_mapping_disable(&ram_low_mapping); + mem_mapping_set_handler(&ram_low_mapping, + ram_mirrored_read, NULL, NULL, + ram_mirrored_write, NULL, NULL); + mem_mapping_disable(&ram_low_mapping); } if (rammap[cur_rammap].bank[0] == BANK_NONE) - bank_nr = 1; - + bank_nr = 1; + for (; bank_nr < 2; bank_nr++) { - old_virt_base = virt_base; - phys_bank = ram_configs[dev->ram_config].bank[bank_nr]; + old_virt_base = virt_base; + phys_bank = ram_configs[dev->ram_config].bank[bank_nr]; - dev->ram_virt_base[bank_nr] = virt_base; + dev->ram_virt_base[bank_nr] = virt_base; - if (virt_base == 0) { - switch (rammap[cur_rammap].bank[bank_nr]) { - case BANK_NONE: - fatal(" Bank %i is empty!\n }\n}\n", bank_nr); - break; + if (virt_base == 0) { + switch (rammap[cur_rammap].bank[bank_nr]) { + case BANK_NONE: + fatal(" Bank %i is empty!\n }\n}\n", bank_nr); + break; - case BANK_256K: - if (phys_bank != BANK_NONE) { - mem_mapping_set_addr(&ram_low_mapping, 0, 0x80000); - mem_mapping_set_p(&ram_low_mapping, (void *)&dev->ram_struct[bank_nr]); - } - virt_base += (1 << 19); - dev->row_virt_shift[bank_nr] = 10; - break; + case BANK_256K: + if (phys_bank != BANK_NONE) { + mem_mapping_set_addr(&ram_low_mapping, 0, 0x80000); + mem_mapping_set_p(&ram_low_mapping, (void *) &dev->ram_struct[bank_nr]); + } + virt_base += (1 << 19); + dev->row_virt_shift[bank_nr] = 10; + break; - case BANK_256K_INTERLEAVED: - if (phys_bank != BANK_NONE) { - mem_mapping_set_addr(&ram_low_mapping, 0, 0xa0000); - mem_mapping_set_p(&ram_low_mapping, (void *)&dev->ram_struct[bank_nr]); - } - virt_base += (1 << 20); - dev->row_virt_shift[bank_nr] = 10; - break; + case BANK_256K_INTERLEAVED: + if (phys_bank != BANK_NONE) { + mem_mapping_set_addr(&ram_low_mapping, 0, 0xa0000); + mem_mapping_set_p(&ram_low_mapping, (void *) &dev->ram_struct[bank_nr]); + } + virt_base += (1 << 20); + dev->row_virt_shift[bank_nr] = 10; + break; - case BANK_1M: - if (phys_bank != BANK_NONE) { - mem_mapping_set_addr(&ram_low_mapping, 0, 0xa0000); - mem_mapping_set_p(&ram_low_mapping, (void *)&dev->ram_struct[bank_nr]); - mem_mapping_set_addr(&dev->ram_mapping[bank_nr], 0x100000, 0x100000); - mem_mapping_set_exec(&dev->ram_mapping[bank_nr], &ram[dev->ram_phys_base[bank_nr] + 0x100000]); - mem_set_mem_state_both((1 << 20), (1 << 20), MEM_READ_INTERNAL | MEM_WRITE_INTERNAL); - } - virt_base += (1 << 21); - dev->row_virt_shift[bank_nr] = 11; - break; + case BANK_1M: + if (phys_bank != BANK_NONE) { + mem_mapping_set_addr(&ram_low_mapping, 0, 0xa0000); + mem_mapping_set_p(&ram_low_mapping, (void *) &dev->ram_struct[bank_nr]); + mem_mapping_set_addr(&dev->ram_mapping[bank_nr], 0x100000, 0x100000); + mem_mapping_set_exec(&dev->ram_mapping[bank_nr], &ram[dev->ram_phys_base[bank_nr] + 0x100000]); + mem_set_mem_state_both((1 << 20), (1 << 20), MEM_READ_INTERNAL | MEM_WRITE_INTERNAL); + } + virt_base += (1 << 21); + dev->row_virt_shift[bank_nr] = 11; + break; - case BANK_1M_INTERLEAVED: - if (phys_bank != BANK_NONE) { - mem_mapping_set_addr(&ram_low_mapping, 0, 0xa0000); - mem_mapping_set_p(&ram_low_mapping, (void *)&dev->ram_struct[bank_nr]); - mem_mapping_set_addr(&dev->ram_mapping[bank_nr], 0x100000, 0x300000); - mem_mapping_set_exec(&dev->ram_mapping[bank_nr], &ram[dev->ram_phys_base[bank_nr] + 0x100000]); - mem_set_mem_state_both((1 << 20), (3 << 20), MEM_READ_INTERNAL | MEM_WRITE_INTERNAL); - } - virt_base += (1 << 22); - dev->row_virt_shift[bank_nr] = 11; - break; + case BANK_1M_INTERLEAVED: + if (phys_bank != BANK_NONE) { + mem_mapping_set_addr(&ram_low_mapping, 0, 0xa0000); + mem_mapping_set_p(&ram_low_mapping, (void *) &dev->ram_struct[bank_nr]); + mem_mapping_set_addr(&dev->ram_mapping[bank_nr], 0x100000, 0x300000); + mem_mapping_set_exec(&dev->ram_mapping[bank_nr], &ram[dev->ram_phys_base[bank_nr] + 0x100000]); + mem_set_mem_state_both((1 << 20), (3 << 20), MEM_READ_INTERNAL | MEM_WRITE_INTERNAL); + } + virt_base += (1 << 22); + dev->row_virt_shift[bank_nr] = 11; + break; - case BANK_4M: - if (phys_bank != BANK_NONE) { - mem_mapping_set_addr(&ram_low_mapping, 0, 0xa0000); - mem_mapping_set_p(&ram_low_mapping, (void *)&dev->ram_struct[bank_nr]); - mem_mapping_set_addr(&dev->ram_mapping[bank_nr], 0x100000, 0x700000); - mem_mapping_set_exec(&dev->ram_mapping[bank_nr], &ram[dev->ram_phys_base[bank_nr] + 0x100000]); - mem_set_mem_state_both((1 << 20), (7 << 20), MEM_READ_INTERNAL | MEM_WRITE_INTERNAL); - } - virt_base += (1 << 23); - dev->row_virt_shift[bank_nr] = 12; - break; + case BANK_4M: + if (phys_bank != BANK_NONE) { + mem_mapping_set_addr(&ram_low_mapping, 0, 0xa0000); + mem_mapping_set_p(&ram_low_mapping, (void *) &dev->ram_struct[bank_nr]); + mem_mapping_set_addr(&dev->ram_mapping[bank_nr], 0x100000, 0x700000); + mem_mapping_set_exec(&dev->ram_mapping[bank_nr], &ram[dev->ram_phys_base[bank_nr] + 0x100000]); + mem_set_mem_state_both((1 << 20), (7 << 20), MEM_READ_INTERNAL | MEM_WRITE_INTERNAL); + } + virt_base += (1 << 23); + dev->row_virt_shift[bank_nr] = 12; + break; - case BANK_4M_INTERLEAVED: - if (phys_bank != BANK_NONE) { - mem_mapping_set_addr(&ram_low_mapping, 0, 0xa0000); - mem_mapping_set_p(&ram_low_mapping, (void *)&dev->ram_struct[bank_nr]); - mem_mapping_set_addr(&dev->ram_mapping[bank_nr], 0x100000, 0xf00000); - mem_mapping_set_exec(&dev->ram_mapping[bank_nr], &ram[dev->ram_phys_base[bank_nr] + 0x100000]); - mem_set_mem_state_both((1 << 20), (15 << 20), MEM_READ_INTERNAL | MEM_WRITE_INTERNAL); - } - virt_base += (1 << 24); - dev->row_virt_shift[bank_nr] = 12; - break; - } - } else { - switch (rammap[cur_rammap].bank[bank_nr]) { - case BANK_NONE: - break; + case BANK_4M_INTERLEAVED: + if (phys_bank != BANK_NONE) { + mem_mapping_set_addr(&ram_low_mapping, 0, 0xa0000); + mem_mapping_set_p(&ram_low_mapping, (void *) &dev->ram_struct[bank_nr]); + mem_mapping_set_addr(&dev->ram_mapping[bank_nr], 0x100000, 0xf00000); + mem_mapping_set_exec(&dev->ram_mapping[bank_nr], &ram[dev->ram_phys_base[bank_nr] + 0x100000]); + mem_set_mem_state_both((1 << 20), (15 << 20), MEM_READ_INTERNAL | MEM_WRITE_INTERNAL); + } + virt_base += (1 << 24); + dev->row_virt_shift[bank_nr] = 12; + break; - case BANK_256K: - if (phys_bank != BANK_NONE) { - mem_mapping_set_addr(&dev->ram_mapping[bank_nr], virt_base, 0x80000); - mem_mapping_set_exec(&dev->ram_mapping[bank_nr], &ram[dev->ram_phys_base[bank_nr]]); - mem_set_mem_state_both(virt_base, (1 << 19), MEM_READ_INTERNAL | MEM_WRITE_INTERNAL); - } - virt_base += (1 << 19); - dev->row_virt_shift[bank_nr] = 10; - break; + default: + break; + } + } else { + switch (rammap[cur_rammap].bank[bank_nr]) { + case BANK_NONE: + break; - case BANK_256K_INTERLEAVED: - if (phys_bank != BANK_NONE) { - mem_mapping_set_addr(&dev->ram_mapping[bank_nr], virt_base, 0x100000); - mem_mapping_set_exec(&dev->ram_mapping[bank_nr], &ram[dev->ram_phys_base[bank_nr]]); - mem_set_mem_state_both(virt_base, (1 << 20), MEM_READ_INTERNAL | MEM_WRITE_INTERNAL); - } - virt_base += (1 << 20); - dev->row_virt_shift[bank_nr] = 10; - break; + case BANK_256K: + if (phys_bank != BANK_NONE) { + mem_mapping_set_addr(&dev->ram_mapping[bank_nr], virt_base, 0x80000); + mem_mapping_set_exec(&dev->ram_mapping[bank_nr], &ram[dev->ram_phys_base[bank_nr]]); + mem_set_mem_state_both(virt_base, (1 << 19), MEM_READ_INTERNAL | MEM_WRITE_INTERNAL); + } + virt_base += (1 << 19); + dev->row_virt_shift[bank_nr] = 10; + break; - case BANK_1M: - if (phys_bank != BANK_NONE) { - mem_mapping_set_addr(&dev->ram_mapping[bank_nr], virt_base, 0x200000); - mem_mapping_set_exec(&dev->ram_mapping[bank_nr], &ram[dev->ram_phys_base[bank_nr]]); - mem_set_mem_state_both(virt_base, (1 << 21), MEM_READ_INTERNAL | MEM_WRITE_INTERNAL); - } - virt_base += (1 << 21); - dev->row_virt_shift[bank_nr] = 11; - break; + case BANK_256K_INTERLEAVED: + if (phys_bank != BANK_NONE) { + mem_mapping_set_addr(&dev->ram_mapping[bank_nr], virt_base, 0x100000); + mem_mapping_set_exec(&dev->ram_mapping[bank_nr], &ram[dev->ram_phys_base[bank_nr]]); + mem_set_mem_state_both(virt_base, (1 << 20), MEM_READ_INTERNAL | MEM_WRITE_INTERNAL); + } + virt_base += (1 << 20); + dev->row_virt_shift[bank_nr] = 10; + break; - case BANK_1M_INTERLEAVED: - if (phys_bank != BANK_NONE) { - mem_mapping_set_addr(&dev->ram_mapping[bank_nr], virt_base, 0x400000); - mem_mapping_set_exec(&dev->ram_mapping[bank_nr], &ram[dev->ram_phys_base[bank_nr]]); - mem_set_mem_state_both(virt_base, (1 << 22), MEM_READ_INTERNAL | MEM_WRITE_INTERNAL); - } - virt_base += (1 << 22); - dev->row_virt_shift[bank_nr] = 11; - break; + case BANK_1M: + if (phys_bank != BANK_NONE) { + mem_mapping_set_addr(&dev->ram_mapping[bank_nr], virt_base, 0x200000); + mem_mapping_set_exec(&dev->ram_mapping[bank_nr], &ram[dev->ram_phys_base[bank_nr]]); + mem_set_mem_state_both(virt_base, (1 << 21), MEM_READ_INTERNAL | MEM_WRITE_INTERNAL); + } + virt_base += (1 << 21); + dev->row_virt_shift[bank_nr] = 11; + break; - case BANK_4M: - if (phys_bank != BANK_NONE) { - mem_mapping_set_addr(&dev->ram_mapping[bank_nr], virt_base, 0x800000); - mem_mapping_set_exec(&dev->ram_mapping[bank_nr], &ram[dev->ram_phys_base[bank_nr]]); - mem_set_mem_state_both(virt_base, (1 << 23), MEM_READ_INTERNAL | MEM_WRITE_INTERNAL); - } - virt_base += (1 << 23); - dev->row_virt_shift[bank_nr] = 12; - break; + case BANK_1M_INTERLEAVED: + if (phys_bank != BANK_NONE) { + mem_mapping_set_addr(&dev->ram_mapping[bank_nr], virt_base, 0x400000); + mem_mapping_set_exec(&dev->ram_mapping[bank_nr], &ram[dev->ram_phys_base[bank_nr]]); + mem_set_mem_state_both(virt_base, (1 << 22), MEM_READ_INTERNAL | MEM_WRITE_INTERNAL); + } + virt_base += (1 << 22); + dev->row_virt_shift[bank_nr] = 11; + break; - case BANK_4M_INTERLEAVED: - if (phys_bank != BANK_NONE) { - mem_mapping_set_addr(&dev->ram_mapping[bank_nr], virt_base, 0x1000000); - mem_mapping_set_exec(&dev->ram_mapping[bank_nr], &ram[dev->ram_phys_base[bank_nr]]); - mem_set_mem_state_both(virt_base, (1 << 24), MEM_READ_INTERNAL | MEM_WRITE_INTERNAL); - } - virt_base += (1 << 24); - dev->row_virt_shift[bank_nr] = 12; - break; - } - } - switch (rammap[cur_rammap].bank[bank_nr]) { - case BANK_256K: case BANK_1M: case BANK_4M: - mem_mapping_set_handler(&dev->ram_mapping[bank_nr], - ram_mirrored_read, NULL, NULL, - ram_mirrored_write, NULL, NULL); - if (!old_virt_base) - mem_mapping_set_handler(&ram_low_mapping, - ram_mirrored_read, NULL, NULL, - ram_mirrored_write, NULL, NULL); - break; + case BANK_4M: + if (phys_bank != BANK_NONE) { + mem_mapping_set_addr(&dev->ram_mapping[bank_nr], virt_base, 0x800000); + mem_mapping_set_exec(&dev->ram_mapping[bank_nr], &ram[dev->ram_phys_base[bank_nr]]); + mem_set_mem_state_both(virt_base, (1 << 23), MEM_READ_INTERNAL | MEM_WRITE_INTERNAL); + } + virt_base += (1 << 23); + dev->row_virt_shift[bank_nr] = 12; + break; - case BANK_256K_INTERLEAVED: case BANK_1M_INTERLEAVED: - mem_mapping_set_handler(&dev->ram_mapping[bank_nr], - ram_mirrored_interleaved_read, NULL, NULL, - ram_mirrored_interleaved_write, NULL, NULL); - if (!old_virt_base) - mem_mapping_set_handler(&ram_low_mapping, - ram_mirrored_interleaved_read, NULL, NULL, - ram_mirrored_interleaved_write, NULL, NULL); - break; - - case BANK_4M_INTERLEAVED: - if (phys_bank == BANK_256K || phys_bank == BANK_256K_INTERLEAVED) { - mem_mapping_set_handler(&dev->ram_mapping[bank_nr], - ram_mirrored_256k_in_4mi_read, NULL, NULL, - ram_mirrored_256k_in_4mi_write, NULL, NULL); - if (!old_virt_base) - mem_mapping_set_handler(&ram_low_mapping, - ram_mirrored_256k_in_4mi_read, NULL, NULL, - ram_mirrored_256k_in_4mi_write, NULL, NULL); - } else { - mem_mapping_set_handler(&dev->ram_mapping[bank_nr], - ram_mirrored_interleaved_read, NULL, NULL, - ram_mirrored_interleaved_write, NULL, NULL); - if (!old_virt_base) - mem_mapping_set_handler(&ram_low_mapping, - ram_mirrored_interleaved_read, NULL, NULL, - ram_mirrored_interleaved_write, NULL, NULL); - } - break; - } + case BANK_4M_INTERLEAVED: + if (phys_bank != BANK_NONE) { + mem_mapping_set_addr(&dev->ram_mapping[bank_nr], virt_base, 0x1000000); + mem_mapping_set_exec(&dev->ram_mapping[bank_nr], &ram[dev->ram_phys_base[bank_nr]]); + mem_set_mem_state_both(virt_base, (1 << 24), MEM_READ_INTERNAL | MEM_WRITE_INTERNAL); + } + virt_base += (1 << 24); + dev->row_virt_shift[bank_nr] = 12; + break; + + default: + break; + } + } + switch (rammap[cur_rammap].bank[bank_nr]) { + case BANK_256K: + case BANK_1M: + case BANK_4M: + mem_mapping_set_handler(&dev->ram_mapping[bank_nr], + ram_mirrored_read, NULL, NULL, + ram_mirrored_write, NULL, NULL); + if (!old_virt_base) + mem_mapping_set_handler(&ram_low_mapping, + ram_mirrored_read, NULL, NULL, + ram_mirrored_write, NULL, NULL); + break; + + case BANK_256K_INTERLEAVED: + case BANK_1M_INTERLEAVED: + mem_mapping_set_handler(&dev->ram_mapping[bank_nr], + ram_mirrored_interleaved_read, NULL, NULL, + ram_mirrored_interleaved_write, NULL, NULL); + if (!old_virt_base) + mem_mapping_set_handler(&ram_low_mapping, + ram_mirrored_interleaved_read, NULL, NULL, + ram_mirrored_interleaved_write, NULL, NULL); + break; + + case BANK_4M_INTERLEAVED: + if (phys_bank == BANK_256K || phys_bank == BANK_256K_INTERLEAVED) { + mem_mapping_set_handler(&dev->ram_mapping[bank_nr], + ram_mirrored_256k_in_4mi_read, NULL, NULL, + ram_mirrored_256k_in_4mi_write, NULL, NULL); + if (!old_virt_base) + mem_mapping_set_handler(&ram_low_mapping, + ram_mirrored_256k_in_4mi_read, NULL, NULL, + ram_mirrored_256k_in_4mi_write, NULL, NULL); + } else { + mem_mapping_set_handler(&dev->ram_mapping[bank_nr], + ram_mirrored_interleaved_read, NULL, NULL, + ram_mirrored_interleaved_write, NULL, NULL); + if (!old_virt_base) + mem_mapping_set_handler(&ram_low_mapping, + ram_mirrored_interleaved_read, NULL, NULL, + ram_mirrored_interleaved_write, NULL, NULL); + } + break; + + default: + break; + } } } - static void recalc_sltptr(scamp_t *dev) { - uint32_t sltptr = dev->cfg_regs[CFG_SLTPTR] << 16; + uint32_t sltptr = dev->cfg_regs[CFG_SLTPTR] << 16; - if (sltptr >= 0xa0000 && sltptr < 0x100000) - sltptr = 0x100000; - if (sltptr > 0xfe0000) - sltptr = 0xfe0000; + if (sltptr >= 0xa0000 && sltptr < 0x100000) + sltptr = 0x100000; + if (sltptr > 0xfe0000) + sltptr = 0xfe0000; - if (sltptr >= 0xa0000) - { - mem_set_mem_state(0, 0xa0000, MEM_READ_INTERNAL | MEM_WRITE_INTERNAL); - mem_set_mem_state(0x100000, sltptr - 0x100000, MEM_READ_INTERNAL | MEM_WRITE_INTERNAL); - mem_set_mem_state(sltptr, 0x1000000 - sltptr, MEM_READ_EXTANY | MEM_WRITE_EXTANY); - } - else - { - mem_set_mem_state(0, sltptr, MEM_READ_INTERNAL | MEM_WRITE_INTERNAL); - mem_set_mem_state(sltptr, 0xa0000-sltptr, MEM_READ_EXTANY | MEM_WRITE_EXTANY); - mem_set_mem_state(0x100000, 0xf00000, MEM_READ_EXTANY | MEM_WRITE_EXTANY); - } + if (sltptr >= 0xa0000) { + mem_set_mem_state(0, 0xa0000, MEM_READ_INTERNAL | MEM_WRITE_INTERNAL); + mem_set_mem_state(0x100000, sltptr - 0x100000, MEM_READ_INTERNAL | MEM_WRITE_INTERNAL); + mem_set_mem_state(sltptr, 0x1000000 - sltptr, MEM_READ_EXTANY | MEM_WRITE_EXTANY); + } else { + mem_set_mem_state(0, sltptr, MEM_READ_INTERNAL | MEM_WRITE_INTERNAL); + mem_set_mem_state(sltptr, 0xa0000 - sltptr, MEM_READ_EXTANY | MEM_WRITE_EXTANY); + mem_set_mem_state(0x100000, 0xf00000, MEM_READ_EXTANY | MEM_WRITE_EXTANY); + } } static uint8_t scamp_ems_read(uint32_t addr, void *priv) { - ems_struct_t *ems = (ems_struct_t *) priv; - scamp_t *dev = ems->parent; - int segment = ems->segment; + const ems_struct_t *ems = (ems_struct_t *) priv; + const scamp_t *dev = ems->parent; + int segment = ems->segment; - addr = (addr & 0x3fff) | dev->mappings[segment]; - return ram[addr]; + addr = (addr & 0x3fff) | dev->mappings[segment]; + return ram[addr]; } static void scamp_ems_write(uint32_t addr, uint8_t val, void *priv) { - ems_struct_t *ems = (ems_struct_t *) priv; - scamp_t *dev = ems->parent; - int segment = ems->segment; - - addr = (addr & 0x3fff) | dev->mappings[segment]; - ram[addr] = val; + const ems_struct_t *ems = (ems_struct_t *) priv; + const scamp_t *dev = ems->parent; + int segment = ems->segment; + + addr = (addr & 0x3fff) | dev->mappings[segment]; + ram[addr] = val; } static void recalc_ems(scamp_t *dev) -{ - int segment; - const uint32_t ems_base[12] = - { - 0xc0000, 0xc4000, 0xc8000, 0xcc000, - 0xd0000, 0xd4000, 0xd8000, 0xdc000, - 0xe0000, 0xe4000, 0xe8000, 0xec000 - }; - uint32_t new_mappings[20]; - uint16_t ems_enable; +{ + const uint32_t ems_base[12] = { + 0xc0000, 0xc4000, 0xc8000, 0xcc000, + 0xd0000, 0xd4000, 0xd8000, 0xdc000, + 0xe0000, 0xe4000, 0xe8000, 0xec000 + }; + uint32_t new_mappings[20]; + uint16_t ems_enable; - for (segment = 0; segment < 20; segment++) - new_mappings[segment] = 0xa0000 + segment*0x4000; + for (int segment = 0; segment < 20; segment++) + new_mappings[segment] = 0xa0000 + segment * 0x4000; - if (dev->cfg_regs[CFG_EMSEN1] & EMSEN1_EMSENAB) - ems_enable = dev->cfg_regs[CFG_EMSEN2] | ((dev->cfg_regs[CFG_EMSEN1] & 0xf) << 8); - else - ems_enable = 0; + if (dev->cfg_regs[CFG_EMSEN1] & EMSEN1_EMSENAB) + ems_enable = dev->cfg_regs[CFG_EMSEN2] | ((dev->cfg_regs[CFG_EMSEN1] & 0xf) << 8); + else + ems_enable = 0; - for (segment = 0; segment < 12; segment++) - { - if (ems_enable & (1 << segment)) - { - uint32_t phys_addr = dev->ems[segment] << 14; + for (int segment = 0; segment < 12; segment++) { + if (ems_enable & (1 << segment)) { + uint32_t phys_addr = dev->ems[segment] << 14; - /*If physical address is in remapped memory then adjust down to a0000-fffff range*/ - if ((dev->cfg_regs[CFG_RAMMAP] & RAMMAP_REMP386) && phys_addr >= (mem_size * 1024) - && phys_addr < ((mem_size + 384) * 1024)) - phys_addr = (phys_addr - mem_size * 1024) + 0xa0000; - new_mappings[(ems_base[segment] - 0xa0000) >> 14] = phys_addr; - } + /*If physical address is in remapped memory then adjust down to a0000-fffff range*/ + if ((dev->cfg_regs[CFG_RAMMAP] & RAMMAP_REMP386) && phys_addr >= (mem_size * 1024) + && phys_addr < ((mem_size + 384) * 1024)) + phys_addr = (phys_addr - mem_size * 1024) + 0xa0000; + new_mappings[(ems_base[segment] - 0xa0000) >> 14] = phys_addr; } + } - for (segment = 0; segment < 20; segment++) - { - if (new_mappings[segment] != dev->mappings[segment]) - { - dev->mappings[segment] = new_mappings[segment]; - if (new_mappings[segment] < (mem_size * 1024)) - { - mem_mapping_set_exec(&dev->ems_mappings[segment], ram + dev->mappings[segment]); - mem_mapping_enable(&dev->ems_mappings[segment]); - } - else - mem_mapping_disable(&dev->ems_mappings[segment]); - } + for (int segment = 0; segment < 20; segment++) { + if (new_mappings[segment] != dev->mappings[segment]) { + dev->mappings[segment] = new_mappings[segment]; + if (new_mappings[segment] < (mem_size * 1024)) { + mem_mapping_set_exec(&dev->ems_mappings[segment], ram + dev->mappings[segment]); + mem_mapping_enable(&dev->ems_mappings[segment]); + } else + mem_mapping_disable(&dev->ems_mappings[segment]); } + } } -static void +static void shadow_control(uint32_t addr, uint32_t size, int state, int ems_enable) { - if (ems_enable) - mem_set_mem_state(addr, size, MEM_READ_INTERNAL | MEM_WRITE_INTERNAL); - else switch (state) { - case 0: - mem_set_mem_state(addr, size, MEM_READ_EXTANY | MEM_WRITE_EXTANY); - break; - case 1: - mem_set_mem_state(addr, size, MEM_READ_EXTANY | MEM_WRITE_INTERNAL); - break; - case 2: - mem_set_mem_state(addr, size, MEM_READ_INTERNAL | MEM_WRITE_EXTANY); - break; - case 3: - mem_set_mem_state(addr, size, MEM_READ_INTERNAL | MEM_WRITE_INTERNAL); - break; - } + if (ems_enable) + mem_set_mem_state(addr, size, MEM_READ_INTERNAL | MEM_WRITE_INTERNAL); + else + switch (state) { + case 0: + mem_set_mem_state(addr, size, MEM_READ_EXTANY | MEM_WRITE_EXTANY); + break; + case 1: + mem_set_mem_state(addr, size, MEM_READ_EXTANY | MEM_WRITE_INTERNAL); + break; + case 2: + mem_set_mem_state(addr, size, MEM_READ_INTERNAL | MEM_WRITE_EXTANY); + break; + case 3: + mem_set_mem_state(addr, size, MEM_READ_INTERNAL | MEM_WRITE_INTERNAL); + break; + default: + break; + } flushmmucache_nopc(); } @@ -659,170 +665,176 @@ shadow_control(uint32_t addr, uint32_t size, int state, int ems_enable) static void shadow_recalc(scamp_t *dev) { - uint8_t abaxs = (dev->cfg_regs[CFG_RAMMAP] & RAMMAP_REMP386) ? 0 : dev->cfg_regs[CFG_ABAXS]; - uint8_t caxs = (dev->cfg_regs[CFG_RAMMAP] & RAMMAP_REMP386) ? 0 : dev->cfg_regs[CFG_CAXS]; - uint8_t daxs = (dev->cfg_regs[CFG_RAMMAP] & RAMMAP_REMP386) ? 0 : dev->cfg_regs[CFG_DAXS]; - uint8_t feaxs = (dev->cfg_regs[CFG_RAMMAP] & RAMMAP_REMP386) ? 0 : dev->cfg_regs[CFG_FEAXS]; - uint32_t ems_enable; + uint8_t abaxs = (dev->cfg_regs[CFG_RAMMAP] & RAMMAP_REMP386) ? 0 : dev->cfg_regs[CFG_ABAXS]; + uint8_t caxs = (dev->cfg_regs[CFG_RAMMAP] & RAMMAP_REMP386) ? 0 : dev->cfg_regs[CFG_CAXS]; + uint8_t daxs = (dev->cfg_regs[CFG_RAMMAP] & RAMMAP_REMP386) ? 0 : dev->cfg_regs[CFG_DAXS]; + uint8_t feaxs = (dev->cfg_regs[CFG_RAMMAP] & RAMMAP_REMP386) ? 0 : dev->cfg_regs[CFG_FEAXS]; + uint32_t ems_enable; - if (dev->cfg_regs[CFG_EMSEN1] & EMSEN1_EMSENAB) { - if (dev->cfg_regs[CFG_EMSEN1] & EMSEN1_EMSMAP) /*Axxx/Bxxx/Dxxx*/ - ems_enable = (dev->cfg_regs[CFG_EMSEN2] & 0xf) | ((dev->cfg_regs[CFG_EMSEN1] & 0xf) << 4) | ((dev->cfg_regs[CFG_EMSEN2] & 0xf0) << 8); - else /*Cxxx/Dxxx/Exxx*/ - ems_enable = (dev->cfg_regs[CFG_EMSEN2] << 8) | ((dev->cfg_regs[CFG_EMSEN1] & 0xf) << 16); - } else - ems_enable = 0; + if (dev->cfg_regs[CFG_EMSEN1] & EMSEN1_EMSENAB) { + if (dev->cfg_regs[CFG_EMSEN1] & EMSEN1_EMSMAP) /*Axxx/Bxxx/Dxxx*/ + ems_enable = (dev->cfg_regs[CFG_EMSEN2] & 0xf) | ((dev->cfg_regs[CFG_EMSEN1] & 0xf) << 4) | ((dev->cfg_regs[CFG_EMSEN2] & 0xf0) << 8); + else /*Cxxx/Dxxx/Exxx*/ + ems_enable = (dev->cfg_regs[CFG_EMSEN2] << 8) | ((dev->cfg_regs[CFG_EMSEN1] & 0xf) << 16); + } else + ems_enable = 0; - /*Enabling remapping will disable all shadowing*/ - if (dev->cfg_regs[CFG_RAMMAP] & RAMMAP_REMP386) - mem_remap_top(384); + /*Enabling remapping will disable all shadowing*/ + if (dev->cfg_regs[CFG_RAMMAP] & RAMMAP_REMP386) + mem_remap_top(384); - shadow_control(0xa0000, 0x4000, abaxs & 3, ems_enable & 0x00001); - shadow_control(0xa0000, 0x4000, abaxs & 3, ems_enable & 0x00002); - shadow_control(0xa8000, 0x4000, (abaxs >> 2) & 3, ems_enable & 0x00004); - shadow_control(0xa8000, 0x4000, (abaxs >> 2) & 3, ems_enable & 0x00008); + shadow_control(0xa0000, 0x4000, abaxs & 3, ems_enable & 0x00001); + shadow_control(0xa0000, 0x4000, abaxs & 3, ems_enable & 0x00002); + shadow_control(0xa8000, 0x4000, (abaxs >> 2) & 3, ems_enable & 0x00004); + shadow_control(0xa8000, 0x4000, (abaxs >> 2) & 3, ems_enable & 0x00008); - shadow_control(0xb0000, 0x4000, (abaxs >> 4) & 3, ems_enable & 0x00010); - shadow_control(0xb0000, 0x4000, (abaxs >> 4) & 3, ems_enable & 0x00020); - shadow_control(0xb8000, 0x4000, (abaxs >> 6) & 3, ems_enable & 0x00040); - shadow_control(0xb8000, 0x4000, (abaxs >> 6) & 3, ems_enable & 0x00080); + shadow_control(0xb0000, 0x4000, (abaxs >> 4) & 3, ems_enable & 0x00010); + shadow_control(0xb0000, 0x4000, (abaxs >> 4) & 3, ems_enable & 0x00020); + shadow_control(0xb8000, 0x4000, (abaxs >> 6) & 3, ems_enable & 0x00040); + shadow_control(0xb8000, 0x4000, (abaxs >> 6) & 3, ems_enable & 0x00080); - shadow_control(0xc0000, 0x4000, caxs & 3, ems_enable & 0x00100); - shadow_control(0xc4000, 0x4000, (caxs >> 2) & 3, ems_enable & 0x00200); - shadow_control(0xc8000, 0x4000, (caxs >> 4) & 3, ems_enable & 0x00400); - shadow_control(0xcc000, 0x4000, (caxs >> 6) & 3, ems_enable & 0x00800); + shadow_control(0xc0000, 0x4000, caxs & 3, ems_enable & 0x00100); + shadow_control(0xc4000, 0x4000, (caxs >> 2) & 3, ems_enable & 0x00200); + shadow_control(0xc8000, 0x4000, (caxs >> 4) & 3, ems_enable & 0x00400); + shadow_control(0xcc000, 0x4000, (caxs >> 6) & 3, ems_enable & 0x00800); - shadow_control(0xd0000, 0x4000, daxs & 3, ems_enable & 0x01000); - shadow_control(0xd4000, 0x4000, (daxs >> 2) & 3, ems_enable & 0x02000); - shadow_control(0xd8000, 0x4000, (daxs >> 4) & 3, ems_enable & 0x04000); - shadow_control(0xdc000, 0x4000, (daxs >> 6) & 3, ems_enable & 0x08000); + shadow_control(0xd0000, 0x4000, daxs & 3, ems_enable & 0x01000); + shadow_control(0xd4000, 0x4000, (daxs >> 2) & 3, ems_enable & 0x02000); + shadow_control(0xd8000, 0x4000, (daxs >> 4) & 3, ems_enable & 0x04000); + shadow_control(0xdc000, 0x4000, (daxs >> 6) & 3, ems_enable & 0x08000); - shadow_control(0xe0000, 0x4000, feaxs & 3, ems_enable & 0x10000); - shadow_control(0xe4000, 0x4000, feaxs & 3, ems_enable & 0x20000); - shadow_control(0xe8000, 0x4000, (feaxs >> 2) & 3, ems_enable & 0x40000); - shadow_control(0xec000, 0x4000, (feaxs >> 2) & 3, ems_enable & 0x80000); + shadow_control(0xe0000, 0x4000, feaxs & 3, ems_enable & 0x10000); + shadow_control(0xe4000, 0x4000, feaxs & 3, ems_enable & 0x20000); + shadow_control(0xe8000, 0x4000, (feaxs >> 2) & 3, ems_enable & 0x40000); + shadow_control(0xec000, 0x4000, (feaxs >> 2) & 3, ems_enable & 0x80000); - shadow_control(0xf0000, 0x8000, (feaxs >> 4) & 3, 0); - shadow_control(0xf8000, 0x8000, (feaxs >> 6) & 3, 0); + shadow_control(0xf0000, 0x8000, (feaxs >> 4) & 3, 0); + shadow_control(0xf8000, 0x8000, (feaxs >> 6) & 3, 0); } -static void +static void scamp_write(uint16_t addr, uint8_t val, void *priv) { scamp_t *dev = (scamp_t *) priv; switch (addr) { - case 0xe8: - dev->ems_index = val & 0x1f; - dev->ems_autoinc = val & 0x40; - break; + case 0xe8: + dev->ems_index = val & 0x1f; + dev->ems_autoinc = val & 0x40; + break; - case 0xea: - if (dev->ems_index < 0x24) { - dev->ems[dev->ems_index] = (dev->ems[dev->ems_index] & 0x300) | val; - recalc_ems(dev); - } - break; - case 0xeb: - if (dev->ems_index < 0x24) { - dev->ems[dev->ems_index] = (dev->ems[dev->ems_index] & 0x0ff) | ((val & 3) << 8); - recalc_ems(dev); - } - if (dev->ems_autoinc) - dev->ems_index = (dev->ems_index + 1) & 0x3f; - break; - - case 0xec: - if (dev->cfg_enable) - dev->cfg_index = val; - break; + case 0xea: + if (dev->ems_index < 0x24) { + dev->ems[dev->ems_index] = (dev->ems[dev->ems_index] & 0x300) | val; + recalc_ems(dev); + } + break; + case 0xeb: + if (dev->ems_index < 0x24) { + dev->ems[dev->ems_index] = (dev->ems[dev->ems_index] & 0x0ff) | ((val & 3) << 8); + recalc_ems(dev); + } + if (dev->ems_autoinc) + dev->ems_index = (dev->ems_index + 1) & 0x3f; + break; - case 0xed: - if (dev->cfg_enable && (dev->cfg_index >= 0x02) && (dev->cfg_index <= 0x16)) { - dev->cfg_regs[dev->cfg_index] = val; - switch (dev->cfg_index) { - case CFG_SLTPTR: - recalc_sltptr(dev); - break; + case 0xec: + if (dev->cfg_enable) + dev->cfg_index = val; + break; - case CFG_RAMMAP: - recalc_mappings(dev); - mem_mapping_disable(&ram_remapped_mapping); - shadow_recalc(dev); - break; + case 0xed: + if (dev->cfg_enable && (dev->cfg_index >= 0x02) && (dev->cfg_index <= 0x16)) { + dev->cfg_regs[dev->cfg_index] = val; + switch (dev->cfg_index) { + case CFG_SLTPTR: + recalc_sltptr(dev); + break; - case CFG_EMSEN1: - case CFG_EMSEN2: - shadow_recalc(dev); - recalc_ems(dev); - break; + case CFG_RAMMAP: + recalc_mappings(dev); + mem_mapping_disable(&ram_remapped_mapping); + shadow_recalc(dev); + break; - case CFG_ABAXS: - case CFG_CAXS: - case CFG_DAXS: - case CFG_FEAXS: - shadow_recalc(dev); - break; - } - } - break; + case CFG_EMSEN1: + case CFG_EMSEN2: + shadow_recalc(dev); + recalc_ems(dev); + break; - case 0xee: - if (dev->cfg_enable && mem_a20_alt) { - dev->port_92->reg &= 0xfd; - mem_a20_alt = 0; - mem_a20_recalc(); - } - break; + case CFG_ABAXS: + case CFG_CAXS: + case CFG_DAXS: + case CFG_FEAXS: + shadow_recalc(dev); + break; + default: + break; + } + } + break; + + case 0xee: + if (dev->cfg_enable && mem_a20_alt) { + dev->port_92->reg &= 0xfd; + mem_a20_alt = 0; + mem_a20_recalc(); + } + break; + + default: + break; } } - -static uint8_t +static uint8_t scamp_read(uint16_t addr, void *priv) { scamp_t *dev = (scamp_t *) priv; - uint8_t ret = 0xff; + uint8_t ret = 0xff; switch (addr) { - case 0xe8: - ret = dev->ems_index | dev->ems_autoinc; - break; + case 0xe8: + ret = dev->ems_index | dev->ems_autoinc; + break; - case 0xea: - if (dev->ems_index < 0x24) - ret = dev->ems[dev->ems_index] & 0xff; - break; - case 0xeb: - if (dev->ems_index < 0x24) - ret = (dev->ems[dev->ems_index] >> 8) | 0xfc; - if (dev->ems_autoinc) - dev->ems_index = (dev->ems_index + 1) & 0x3f; - break; + case 0xea: + if (dev->ems_index < 0x24) + ret = dev->ems[dev->ems_index] & 0xff; + break; + case 0xeb: + if (dev->ems_index < 0x24) + ret = (dev->ems[dev->ems_index] >> 8) | 0xfc; + if (dev->ems_autoinc) + dev->ems_index = (dev->ems_index + 1) & 0x3f; + break; - case 0xed: - if (dev->cfg_enable && (dev->cfg_index >= 0x00) && (dev->cfg_index <= 0x16)) - ret = (dev->cfg_regs[dev->cfg_index]); - break; + case 0xed: + if (dev->cfg_enable && (dev->cfg_index >= 0x00) && (dev->cfg_index <= 0x16)) + ret = (dev->cfg_regs[dev->cfg_index]); + break; - case 0xee: - if (!mem_a20_alt) { - dev->port_92->reg |= 0x02; - mem_a20_alt = 1; - mem_a20_recalc(); - } - break; + case 0xee: + if (!mem_a20_alt) { + dev->port_92->reg |= 0x02; + mem_a20_alt = 1; + mem_a20_recalc(); + } + break; - case 0xef: - softresetx86(); - cpu_set_edx(); - break; + case 0xef: + softresetx86(); + cpu_set_edx(); + break; + + default: + break; } return ret; } - static void scamp_close(void *priv) { @@ -831,137 +843,141 @@ scamp_close(void *priv) free(dev); } - static void * -scamp_init(const device_t *info) +scamp_init(UNUSED(const device_t *info)) { uint32_t addr; - int c; - scamp_t *dev = (scamp_t *)malloc(sizeof(scamp_t)); + scamp_t *dev = (scamp_t *) malloc(sizeof(scamp_t)); memset(dev, 0x00, sizeof(scamp_t)); - + dev->cfg_regs[CFG_ID] = ID_VL82C311; - dev->cfg_enable = 1; + dev->cfg_enable = 1; io_sethandler(0x00e8, 0x0001, - scamp_read, NULL, NULL, scamp_write, NULL, NULL, dev); + scamp_read, NULL, NULL, scamp_write, NULL, NULL, dev); io_sethandler(0x00ea, 0x0006, - scamp_read, NULL, NULL, scamp_write, NULL, NULL, dev); + scamp_read, NULL, NULL, scamp_write, NULL, NULL, dev); io_sethandler(0x00f4, 0x0002, - scamp_read, NULL, NULL, scamp_write, NULL, NULL, dev); + scamp_read, NULL, NULL, scamp_write, NULL, NULL, dev); io_sethandler(0x00f9, 0x0001, - scamp_read, NULL, NULL, scamp_write, NULL, NULL, dev); + scamp_read, NULL, NULL, scamp_write, NULL, NULL, dev); io_sethandler(0x00fb, 0x0001, - scamp_read, NULL, NULL, scamp_write, NULL, NULL, dev); + scamp_read, NULL, NULL, scamp_write, NULL, NULL, dev); dev->ram_config = 0; /* Find best fit configuration for the requested memory size */ - for (c = 0; c < NR_ELEMS(ram_configs); c++) { - if (mem_size < ram_configs[c].size_kb) - break; + for (uint8_t c = 0; c < NR_ELEMS(ram_configs); c++) { + if (mem_size < ram_configs[c].size_kb) + break; - dev->ram_config = c; + dev->ram_config = c; } mem_mapping_set_p(&ram_low_mapping, (void *) &dev->ram_struct[0]); mem_mapping_set_handler(&ram_low_mapping, - ram_mirrored_read, NULL, NULL, - ram_mirrored_write, NULL, NULL); + ram_mirrored_read, NULL, NULL, + ram_mirrored_write, NULL, NULL); mem_mapping_disable(&ram_high_mapping); - mem_mapping_set_addr(&ram_mid_mapping, 0xf0000, 0x10000); - mem_mapping_set_exec(&ram_mid_mapping, ram+0xf0000); + mem_mapping_set_addr(&ram_mid_mapping, 0xf0000, 0x10000); + mem_mapping_set_exec(&ram_mid_mapping, ram + 0xf0000); addr = 0; - for (c = 0; c < 2; c++) { - dev->ram_struct[c].parent = dev; - dev->ram_struct[c].bank = c; - mem_mapping_add(&dev->ram_mapping[c], 0, 0, - ram_mirrored_read, NULL, NULL, - ram_mirrored_write, NULL, NULL, - &ram[addr], MEM_MAPPING_INTERNAL, (void *) &dev->ram_struct[c]); - mem_mapping_disable(&dev->ram_mapping[c]); + for (uint8_t c = 0; c < 2; c++) { + dev->ram_struct[c].parent = dev; + dev->ram_struct[c].bank = c; + mem_mapping_add(&dev->ram_mapping[c], 0, 0, + ram_mirrored_read, NULL, NULL, + ram_mirrored_write, NULL, NULL, + &ram[addr], MEM_MAPPING_INTERNAL, (void *) &dev->ram_struct[c]); + mem_mapping_disable(&dev->ram_mapping[c]); - dev->ram_phys_base[c] = addr; + dev->ram_phys_base[c] = addr; - switch (ram_configs[dev->ram_config].bank[c]) { - case BANK_NONE: - dev->ram_mask[c] = 0; - dev->ram_interleaved[c] = 0; - break; + switch (ram_configs[dev->ram_config].bank[c]) { + case BANK_NONE: + dev->ram_mask[c] = 0; + dev->ram_interleaved[c] = 0; + break; - case BANK_256K: - addr += (1 << 19); - dev->ram_mask[c] = 0x1ff; - dev->row_phys_shift[c] = 10; - dev->ram_interleaved[c] = 0; - break; + case BANK_256K: + addr += (1 << 19); + dev->ram_mask[c] = 0x1ff; + dev->row_phys_shift[c] = 10; + dev->ram_interleaved[c] = 0; + break; - case BANK_256K_INTERLEAVED: - addr += (1 << 20); - dev->ram_mask[c] = 0x1ff; - dev->row_phys_shift[c] = 10; - dev->ibank_shift[c] = 19; - dev->ram_interleaved[c] = 1; - break; + case BANK_256K_INTERLEAVED: + addr += (1 << 20); + dev->ram_mask[c] = 0x1ff; + dev->row_phys_shift[c] = 10; + dev->ibank_shift[c] = 19; + dev->ram_interleaved[c] = 1; + break; - case BANK_1M: - addr += (1 << 21); - dev->ram_mask[c] = 0x3ff; - dev->row_phys_shift[c] = 11; - dev->ram_interleaved[c] = 0; - break; + case BANK_1M: + addr += (1 << 21); + dev->ram_mask[c] = 0x3ff; + dev->row_phys_shift[c] = 11; + dev->ram_interleaved[c] = 0; + break; - case BANK_1M_INTERLEAVED: - addr += (1 << 22); - dev->ram_mask[c] = 0x3ff; - dev->row_phys_shift[c] = 11; - dev->ibank_shift[c] = 21; - dev->ram_interleaved[c] = 1; - break; + case BANK_1M_INTERLEAVED: + addr += (1 << 22); + dev->ram_mask[c] = 0x3ff; + dev->row_phys_shift[c] = 11; + dev->ibank_shift[c] = 21; + dev->ram_interleaved[c] = 1; + break; - case BANK_4M: - addr += (1 << 23); - dev->ram_mask[c] = 0x7ff; - dev->row_phys_shift[c] = 12; - dev->ram_interleaved[c] = 0; - break; + case BANK_4M: + addr += (1 << 23); + dev->ram_mask[c] = 0x7ff; + dev->row_phys_shift[c] = 12; + dev->ram_interleaved[c] = 0; + break; - case BANK_4M_INTERLEAVED: - addr += (1 << 24); - dev->ram_mask[c] = 0x7ff; - dev->row_phys_shift[c] = 12; - dev->ibank_shift[c] = 23; - dev->ram_interleaved[c] = 1; - break; - } + case BANK_4M_INTERLEAVED: + addr += (1 << 24); + dev->ram_mask[c] = 0x7ff; + dev->row_phys_shift[c] = 12; + dev->ibank_shift[c] = 23; + dev->ram_interleaved[c] = 1; + break; + + default: + break; + } } mem_set_mem_state(0xfe0000, 0x20000, MEM_READ_EXTANY | MEM_WRITE_EXTANY); - for (c = 0; c < 20; c++) { - dev->ems_struct[c].parent = dev; - dev->ems_struct[c].segment = c; - mem_mapping_add(&dev->ems_mappings[c], - 0xa0000 + c*0x4000, 0x4000, - scamp_ems_read, NULL, NULL, - scamp_ems_write, NULL, NULL, - ram + 0xa0000 + c*0x4000, MEM_MAPPING_INTERNAL, (void *)&dev->ems_struct[c]); - dev->mappings[c] = 0xa0000 + c*0x4000; - } + for (uint8_t c = 0; c < 20; c++) { + dev->ems_struct[c].parent = dev; + dev->ems_struct[c].segment = c; + mem_mapping_add(&dev->ems_mappings[c], + 0xa0000 + c * 0x4000, 0x4000, + scamp_ems_read, NULL, NULL, + scamp_ems_write, NULL, NULL, + ram + 0xa0000 + c * 0x4000, MEM_MAPPING_INTERNAL, (void *) &dev->ems_struct[c]); + dev->mappings[c] = 0xa0000 + c * 0x4000; + } dev->port_92 = device_add(&port_92_device); return dev; } - const device_t vlsi_scamp_device = { - "VLSI SCAMP", - "vlsi_scamp", - 0, - 0, - scamp_init, scamp_close, NULL, - { NULL }, NULL, NULL, - NULL + .name = "VLSI SCAMP", + .internal_name = "vlsi_scamp", + .flags = 0, + .local = 0, + .init = scamp_init, + .close = scamp_close, + .reset = NULL, + { .available = NULL }, + .speed_changed = NULL, + .force_redraw = NULL, + .config = NULL }; diff --git a/src/chipset/scat.c b/src/chipset/scat.c index 4a58d2a1f..aa0c5511a 100644 --- a/src/chipset/scat.c +++ b/src/chipset/scat.c @@ -1,22 +1,22 @@ /* - * 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. + * 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. + * This file is part of the 86Box distribution. * - * Implementation of Chips&Technology's SCAT (82C235) chipset. + * Implementation of Chips&Technology's SCAT (82C235) chipset. * - * Re-worked version based on the 82C235 datasheet and errata. + * Re-worked version based on the 82C235 datasheet and errata. * * * - * Authors: Original by GreatPsycho for PCem. - * Fred N. van Kempen, + * Authors: Original by GreatPsycho for PCem. + * Fred N. van Kempen, * - * Copyright 2017-2019 GreatPsycho. - * Copyright 2017-2019 Fred N. van Kempen. + * Copyright 2017-2019 GreatPsycho. + * Copyright 2017-2019 Fred N. van Kempen. */ #include #include @@ -34,21 +34,20 @@ #include <86box/rom.h> #include <86box/chipset.h> - -#define SCAT_DMA_WAIT_STATE_CONTROL 0x01 -#define SCAT_VERSION 0x40 -#define SCAT_CLOCK_CONTROL 0x41 -#define SCAT_PERIPHERAL_CONTROL 0x44 -#define SCAT_MISCELLANEOUS_STATUS 0x45 -#define SCAT_POWER_MANAGEMENT 0x46 -#define SCAT_ROM_ENABLE 0x48 -#define SCAT_RAM_WRITE_PROTECT 0x49 -#define SCAT_SHADOW_RAM_ENABLE_1 0x4A -#define SCAT_SHADOW_RAM_ENABLE_2 0x4B -#define SCAT_SHADOW_RAM_ENABLE_3 0x4C -#define SCAT_DRAM_CONFIGURATION 0x4D -#define SCAT_EXTENDED_BOUNDARY 0x4E -#define SCAT_EMS_CONTROL 0x4F +#define SCAT_DMA_WAIT_STATE_CONTROL 0x01 +#define SCAT_VERSION 0x40 +#define SCAT_CLOCK_CONTROL 0x41 +#define SCAT_PERIPHERAL_CONTROL 0x44 +#define SCAT_MISCELLANEOUS_STATUS 0x45 +#define SCAT_POWER_MANAGEMENT 0x46 +#define SCAT_ROM_ENABLE 0x48 +#define SCAT_RAM_WRITE_PROTECT 0x49 +#define SCAT_SHADOW_RAM_ENABLE_1 0x4A +#define SCAT_SHADOW_RAM_ENABLE_2 0x4B +#define SCAT_SHADOW_RAM_ENABLE_3 0x4C +#define SCAT_DRAM_CONFIGURATION 0x4D +#define SCAT_EXTENDED_BOUNDARY 0x4E +#define SCAT_EMS_CONTROL 0x4F #define SCATSX_LAPTOP_FEATURES 0x60 #define SCATSX_FAST_VIDEO_CONTROL 0x61 @@ -56,47 +55,51 @@ #define SCATSX_HIGH_PERFORMANCE_REFRESH 0x63 #define SCATSX_CAS_TIMING_FOR_DMA 0x64 +typedef struct ems_page_t { + uint8_t valid; + uint8_t pad; -typedef struct { - uint8_t valid, pad; + uint8_t regs_2x8; + uint8_t regs_2x9; - uint8_t regs_2x8; - uint8_t regs_2x9; - - struct scat_t * scat; + struct scat_t *scat; } ems_page_t; typedef struct scat_t { - int type; + int type; - int indx; - uint8_t regs[256]; - uint8_t reg_2xA; + int indx; + uint8_t regs[256]; + uint8_t reg_2xA; - uint32_t xms_bound; + uint32_t xms_bound; - int external_is_RAS; + int external_is_RAS; - ems_page_t null_page, page[32]; + ems_page_t null_page; + ems_page_t page[32]; - mem_mapping_t low_mapping[32]; - mem_mapping_t remap_mapping[6]; - mem_mapping_t efff_mapping[44]; - mem_mapping_t ems_mapping[32]; + mem_mapping_t low_mapping[32]; + mem_mapping_t remap_mapping[6]; + mem_mapping_t efff_mapping[44]; + mem_mapping_t ems_mapping[32]; } scat_t; - static const uint8_t max_map[32] = { +// clang-format off 0, 1, 1, 1, 2, 3, 4, 8, 4, 8, 12, 16, 20, 24, 28, 32, 0, 5, 9, 13, 6, 10, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 +// clang-format om }; static const uint8_t max_map_sx[32] = { - 0, 1, 2, 1, 3, 4, 6, 10, - 5, 9, 13, 4, 8, 12, 16, 14, - 18, 22, 26, 20, 24, 28, 32, 18, - 20, 32, 0, 0, 0, 0, 0, 0 +// clang-format off + 0, 1, 2, 1, 3, 4, 6, 10, + 5, 9, 13, 4, 8, 12, 16, 14, + 18, 22, 26, 20, 24, 28, 32, 18, + 20, 32, 0, 0, 0, 0, 0, 0 +// clang-format om }; static const uint8_t scatsx_external_is_RAS[33] = { 0, 0, 0, 0, 0, 0, 0, 0, @@ -106,1428 +109,1416 @@ static const uint8_t scatsx_external_is_RAS[33] = { 0 }; - -static uint8_t scat_in(uint16_t port, void *priv); -static void scat_out(uint16_t port, uint8_t val, void *priv); - +static uint8_t scat_in(uint16_t port, void *priv); +static void scat_out(uint16_t port, uint8_t val, void *priv); static void shadow_state_update(scat_t *dev) { - int i, val; + int val; - uint32_t base, bit, romcs, shflags = 0; + uint32_t base; + uint32_t bit; + uint32_t romcs; + uint32_t shflags = 0; shadowbios = shadowbios_write = 0; - for (i = 0; i < 24; i++) { - if ((dev->regs[SCAT_DRAM_CONFIGURATION] & 0xf) < 4) - val = 0; - else - val = (dev->regs[SCAT_SHADOW_RAM_ENABLE_1 + (i >> 3)] >> (i & 7)) & 1; + for (uint8_t i = 0; i < 24; i++) { + if ((dev->regs[SCAT_DRAM_CONFIGURATION] & 0xf) < 4) + val = 0; + else + val = (dev->regs[SCAT_SHADOW_RAM_ENABLE_1 + (i >> 3)] >> (i & 7)) & 1; - base = 0xa0000 + (i << 14); - bit = (base - 0xc0000) >> 15; - romcs = 0; + base = 0xa0000 + (i << 14); + bit = (base - 0xc0000) >> 15; + romcs = 0; - if (base >= 0xc0000) - romcs = dev->regs[SCAT_ROM_ENABLE] & (1 << bit); + if (base >= 0xc0000) + romcs = dev->regs[SCAT_ROM_ENABLE] & (1 << bit); - if (base >= 0xe0000) { - shadowbios |= val; - shadowbios_write |= val; - } + if (base >= 0xe0000) { + shadowbios |= val; + shadowbios_write |= val; + } - shflags = val ? MEM_READ_INTERNAL : (romcs ? MEM_READ_EXTANY : MEM_READ_EXTERNAL); - shflags |= (val ? MEM_WRITE_INTERNAL : (romcs ? MEM_WRITE_EXTANY : MEM_WRITE_EXTERNAL)); + shflags = val ? MEM_READ_INTERNAL : (romcs ? MEM_READ_EXTANY : MEM_READ_EXTERNAL); + shflags |= (val ? MEM_WRITE_INTERNAL : (romcs ? MEM_WRITE_EXTANY : MEM_WRITE_EXTERNAL)); - mem_set_mem_state(base, 0x4000, shflags); + mem_set_mem_state(base, 0x4000, shflags); } flushmmucache(); } - static void set_xms_bound(scat_t *dev, uint8_t val) { uint32_t xms_max = ((dev->regs[SCAT_VERSION] & 0xf0) != 0 && ((val & 0x10) != 0)) || (dev->regs[SCAT_VERSION] >= 4) ? 0xfe0000 : 0xfc0000; - int i; switch (val & 0x0f) { - case 1: - dev->xms_bound = 0x100000; - break; + case 1: + dev->xms_bound = 0x100000; + break; - case 2: - dev->xms_bound = 0x140000; - break; + case 2: + dev->xms_bound = 0x140000; + break; - case 3: - dev->xms_bound = 0x180000; - break; + case 3: + dev->xms_bound = 0x180000; + break; - case 4: - dev->xms_bound = 0x200000; - break; + case 4: + dev->xms_bound = 0x200000; + break; - case 5: - dev->xms_bound = 0x300000; - break; + case 5: + dev->xms_bound = 0x300000; + break; - case 6: - dev->xms_bound = 0x400000; - break; + case 6: + dev->xms_bound = 0x400000; + break; - case 7: - dev->xms_bound = ((dev->regs[SCAT_VERSION] & 0xf0) == 0) ? 0x600000 : 0x500000; - break; + case 7: + dev->xms_bound = ((dev->regs[SCAT_VERSION] & 0xf0) == 0) ? 0x600000 : 0x500000; + break; - case 8: - dev->xms_bound = ((dev->regs[SCAT_VERSION] & 0xf0) == 0) ? 0x800000 : 0x700000; - break; + case 8: + dev->xms_bound = ((dev->regs[SCAT_VERSION] & 0xf0) == 0) ? 0x800000 : 0x700000; + break; - case 9: - dev->xms_bound = ((dev->regs[SCAT_VERSION] & 0xf0) == 0) ? 0xa00000 : 0x800000; - break; + case 9: + dev->xms_bound = ((dev->regs[SCAT_VERSION] & 0xf0) == 0) ? 0xa00000 : 0x800000; + break; - case 10: - dev->xms_bound = ((dev->regs[SCAT_VERSION] & 0xf0) == 0) ? 0xc00000 : 0x900000; - break; + case 10: + dev->xms_bound = ((dev->regs[SCAT_VERSION] & 0xf0) == 0) ? 0xc00000 : 0x900000; + break; - case 11: - dev->xms_bound = ((dev->regs[SCAT_VERSION] & 0xf0) == 0) ? 0xe00000 : 0xa00000; - break; + case 11: + dev->xms_bound = ((dev->regs[SCAT_VERSION] & 0xf0) == 0) ? 0xe00000 : 0xa00000; + break; - case 12: - dev->xms_bound = ((dev->regs[SCAT_VERSION] & 0xf0) == 0) ? xms_max : 0xb00000; - break; + case 12: + dev->xms_bound = ((dev->regs[SCAT_VERSION] & 0xf0) == 0) ? xms_max : 0xb00000; + break; - case 13: - dev->xms_bound = ((dev->regs[SCAT_VERSION] & 0xf0) == 0) ? xms_max : 0xc00000; - break; + case 13: + dev->xms_bound = ((dev->regs[SCAT_VERSION] & 0xf0) == 0) ? xms_max : 0xc00000; + break; - case 14: - dev->xms_bound = ((dev->regs[SCAT_VERSION] & 0xf0) == 0) ? xms_max : 0xd00000; - break; + case 14: + dev->xms_bound = ((dev->regs[SCAT_VERSION] & 0xf0) == 0) ? xms_max : 0xd00000; + break; - case 15: - dev->xms_bound = ((dev->regs[SCAT_VERSION] & 0xf0) == 0) ? xms_max : 0xf00000; - break; + case 15: + dev->xms_bound = ((dev->regs[SCAT_VERSION] & 0xf0) == 0) ? xms_max : 0xf00000; + break; - default: - dev->xms_bound = xms_max; - break; + default: + dev->xms_bound = xms_max; + break; } - if ((((dev->regs[SCAT_VERSION] & 0xf0) == 0) && (val & 0x40) == 0 && (dev->regs[SCAT_DRAM_CONFIGURATION] & 0x0f) == 3) || - (((dev->regs[SCAT_VERSION] & 0xf0) != 0) && (dev->regs[SCAT_DRAM_CONFIGURATION] & 0x1f) == 3)) { - if ((val & 0x0f) == 0 || dev->xms_bound > 0x160000) - dev->xms_bound = 0x160000; + if ((((dev->regs[SCAT_VERSION] & 0xf0) == 0) && (val & 0x40) == 0 && (dev->regs[SCAT_DRAM_CONFIGURATION] & 0x0f) == 3) || (((dev->regs[SCAT_VERSION] & 0xf0) != 0) && (dev->regs[SCAT_DRAM_CONFIGURATION] & 0x1f) == 3)) { + if ((val & 0x0f) == 0 || dev->xms_bound > 0x160000) + dev->xms_bound = 0x160000; - if (dev->xms_bound > 0x100000) - mem_set_mem_state(0x100000, dev->xms_bound - 0x100000, - MEM_READ_INTERNAL | MEM_WRITE_INTERNAL); + if (dev->xms_bound > 0x100000) + mem_set_mem_state(0x100000, dev->xms_bound - 0x100000, + MEM_READ_INTERNAL | MEM_WRITE_INTERNAL); - if (dev->xms_bound < 0x160000) - mem_set_mem_state(dev->xms_bound, 0x160000 - dev->xms_bound, - MEM_READ_EXTANY | MEM_WRITE_EXTANY); + if (dev->xms_bound < 0x160000) + mem_set_mem_state(dev->xms_bound, 0x160000 - dev->xms_bound, + MEM_READ_EXTANY | MEM_WRITE_EXTANY); } else { - if (dev->xms_bound > xms_max) - dev->xms_bound = xms_max; + if (dev->xms_bound > xms_max) + dev->xms_bound = xms_max; - if (dev->xms_bound > 0x100000) - mem_set_mem_state(0x100000, dev->xms_bound - 0x100000, - MEM_READ_INTERNAL | MEM_WRITE_INTERNAL); + if (dev->xms_bound > 0x100000) + mem_set_mem_state(0x100000, dev->xms_bound - 0x100000, + MEM_READ_INTERNAL | MEM_WRITE_INTERNAL); - if (dev->xms_bound < ((uint32_t)mem_size << 10)) - mem_set_mem_state(dev->xms_bound, (mem_size << 10) - dev->xms_bound, - MEM_READ_EXTANY | MEM_WRITE_EXTANY); + if (dev->xms_bound < ((uint32_t) mem_size << 10)) + mem_set_mem_state(dev->xms_bound, (mem_size << 10) - dev->xms_bound, + MEM_READ_EXTANY | MEM_WRITE_EXTANY); } mem_mapping_set_addr(&dev->low_mapping[31], 0xf80000, - ((dev->regs[SCAT_VERSION] & 0xf0) != 0 && ((val & 0x10) != 0)) || - (dev->regs[SCAT_VERSION] >= 4) ? 0x60000 : 0x40000); + ((dev->regs[SCAT_VERSION] & 0xf0) != 0 && ((val & 0x10) != 0)) || (dev->regs[SCAT_VERSION] >= 4) ? 0x60000 : 0x40000); if (dev->regs[SCAT_VERSION] & 0xf0) { - for (i = 0; i < 8; i++) { - if (val & 0x10) - mem_mapping_disable(&bios_high_mapping); - else - mem_mapping_enable(&bios_high_mapping); - } + for (uint8_t i = 0; i < 8; i++) { + if (val & 0x10) + mem_mapping_disable(&bios_high_mapping); + else + mem_mapping_enable(&bios_high_mapping); + } } } - static uint32_t get_addr(scat_t *dev, uint32_t addr, ems_page_t *p) { #if 1 - int nbanks_2048k, nbanks_512k; + int nbanks_2048k; + int nbanks_512k; uint32_t addr2; - int nbank; + int nbank; #else uint32_t nbanks_2048k, nbanks_512k, addr2, nbank; #endif if (p && p->valid && (dev->regs[SCAT_EMS_CONTROL] & 0x80) && (p->regs_2x9 & 0x80)) - addr = (addr & 0x3fff) | (((p->regs_2x9 & 3) << 8) | p->regs_2x8) << 14; + addr = (addr & 0x3fff) | (((p->regs_2x9 & 3) << 8) | p->regs_2x8) << 14; if ((dev->regs[SCAT_VERSION] & 0xf0) == 0) { - switch((dev->regs[SCAT_EXTENDED_BOUNDARY] & ((dev->regs[SCAT_VERSION] & 0x0f) > 3 ? 0x40 : 0)) | (dev->regs[SCAT_DRAM_CONFIGURATION] & 0x0f)) { - case 0x41: - nbank = addr >> 19; - if (nbank < 4) - nbank = 1; - else if (nbank == 4) - nbank = 0; - else - nbank -= 3; - break; + switch ((dev->regs[SCAT_EXTENDED_BOUNDARY] & ((dev->regs[SCAT_VERSION] & 0x0f) > 3 ? 0x40 : 0)) | (dev->regs[SCAT_DRAM_CONFIGURATION] & 0x0f)) { + case 0x41: + nbank = addr >> 19; + if (nbank < 4) + nbank = 1; + else if (nbank == 4) + nbank = 0; + else + nbank -= 3; + break; - case 0x42: - nbank = addr >> 19; - if (nbank < 8) - nbank = 1 + (nbank >> 2); - else if (nbank == 8) - nbank = 0; - else - nbank -= 6; - break; + case 0x42: + nbank = addr >> 19; + if (nbank < 8) + nbank = 1 + (nbank >> 2); + else if (nbank == 8) + nbank = 0; + else + nbank -= 6; + break; - case 0x43: - nbank = addr >> 19; - if (nbank < 12) - nbank = 1 + (nbank >> 2); - else if (nbank == 12) - nbank = 0; - else - nbank -= 9; - break; + case 0x43: + nbank = addr >> 19; + if (nbank < 12) + nbank = 1 + (nbank >> 2); + else if (nbank == 12) + nbank = 0; + else + nbank -= 9; + break; - case 0x44: - nbank = addr >> 19; - if (nbank < 4) - nbank = 2; - else if (nbank < 6) - nbank -= 4; - else - nbank -= 3; - break; + case 0x44: + nbank = addr >> 19; + if (nbank < 4) + nbank = 2; + else if (nbank < 6) + nbank -= 4; + else + nbank -= 3; + break; - case 0x45: - nbank = addr >> 19; - if (nbank < 8) - nbank = 2 + (nbank >> 2); - else if (nbank < 10) - nbank -= 8; - else - nbank -= 6; - break; + case 0x45: + nbank = addr >> 19; + if (nbank < 8) + nbank = 2 + (nbank >> 2); + else if (nbank < 10) + nbank -= 8; + else + nbank -= 6; + break; - default: - nbank = addr >> (((dev->regs[SCAT_DRAM_CONFIGURATION] & 0x0f) < 8 && (dev->regs[SCAT_EXTENDED_BOUNDARY] & 0x40) == 0) ? 19 : 21); - break; - } + default: + nbank = addr >> (((dev->regs[SCAT_DRAM_CONFIGURATION] & 0x0f) < 8 && (dev->regs[SCAT_EXTENDED_BOUNDARY] & 0x40) == 0) ? 19 : 21); + break; + } - nbank &= (dev->regs[SCAT_EXTENDED_BOUNDARY] & 0x80) ? 7 : 3; + nbank &= (dev->regs[SCAT_EXTENDED_BOUNDARY] & 0x80) ? 7 : 3; - if ((dev->regs[SCAT_EXTENDED_BOUNDARY] & 0x40) == 0 && - (dev->regs[SCAT_DRAM_CONFIGURATION] & 0x0f) == 3 && - nbank == 2 && (addr & 0x7ffff) < 0x60000 && mem_size > 640) { - nbank = 1; - addr ^= 0x70000; - } + if ((dev->regs[SCAT_EXTENDED_BOUNDARY] & 0x40) == 0 && (dev->regs[SCAT_DRAM_CONFIGURATION] & 0x0f) == 3 && nbank == 2 && (addr & 0x7ffff) < 0x60000 && mem_size > 640) { + nbank = 1; + addr ^= 0x70000; + } - if (dev->external_is_RAS && (dev->regs[SCAT_EXTENDED_BOUNDARY] & 0x80) == 0) { - if (nbank == 3) - nbank = 7; - else - return 0xffffffff; - } else if (!dev->external_is_RAS && dev->regs[SCAT_EXTENDED_BOUNDARY] & 0x80) { - switch(nbank) { - case 7: - nbank = 3; - break; + if (dev->external_is_RAS && (dev->regs[SCAT_EXTENDED_BOUNDARY] & 0x80) == 0) { + if (nbank == 3) + nbank = 7; + else + return 0xffffffff; + } else if (!dev->external_is_RAS && dev->regs[SCAT_EXTENDED_BOUNDARY] & 0x80) { + switch (nbank) { + case 7: + nbank = 3; + break; - /* Note - In the following cases, the chipset accesses multiple memory banks - at the same time, so it's impossible to predict which memory bank - is actually accessed. */ - case 5: - case 1: - nbank = 1; - break; + /* Note - In the following cases, the chipset accesses multiple memory banks + at the same time, so it's impossible to predict which memory bank + is actually accessed. */ + case 5: + case 1: + nbank = 1; + break; - case 3: - nbank = 2; - break; + case 3: + nbank = 2; + break; - default: - nbank = 0; - break; - } - } + default: + nbank = 0; + break; + } + } - if ((dev->regs[SCAT_VERSION] & 0x0f) > 3 && (mem_size > 2048) && (mem_size & 1536)) { - if ((mem_size & 1536) == 512) { - if (nbank == 0) - addr &= 0x7ffff; - else - addr = 0x80000 + ((addr & 0x1fffff) | ((nbank - 1) << 21)); - } else { - if (nbank < 2) - addr = (addr & 0x7ffff) | (nbank << 19); - else - addr = 0x100000 + ((addr & 0x1fffff) | ((nbank - 2) << 21)); - } - } else { - if (mem_size <= ((dev->regs[SCAT_VERSION] & 0x0f) > 3 ? 2048 : 4096) && (((dev->regs[SCAT_DRAM_CONFIGURATION] & 0x0f) < 8) || dev->external_is_RAS)) { - nbanks_2048k = 0; - nbanks_512k = mem_size >> 9; - } else { - nbanks_2048k = mem_size >> 11; - nbanks_512k = (mem_size & 1536) >> 9; - } + if ((dev->regs[SCAT_VERSION] & 0x0f) > 3 && (mem_size > 2048) && (mem_size & 1536)) { + if ((mem_size & 1536) == 512) { + if (nbank == 0) + addr &= 0x7ffff; + else + addr = 0x80000 + ((addr & 0x1fffff) | ((nbank - 1) << 21)); + } else { + if (nbank < 2) + addr = (addr & 0x7ffff) | (nbank << 19); + else + addr = 0x100000 + ((addr & 0x1fffff) | ((nbank - 2) << 21)); + } + } else { + if (mem_size <= ((dev->regs[SCAT_VERSION] & 0x0f) > 3 ? 2048 : 4096) && (((dev->regs[SCAT_DRAM_CONFIGURATION] & 0x0f) < 8) || dev->external_is_RAS)) { + nbanks_2048k = 0; + nbanks_512k = mem_size >> 9; + } else { + nbanks_2048k = mem_size >> 11; + nbanks_512k = (mem_size & 1536) >> 9; + } - if (nbank < nbanks_2048k || (nbanks_2048k > 0 && nbank >= nbanks_2048k + nbanks_512k + ((mem_size & 511) >> 7))) { - addr &= 0x1fffff; - addr |= (nbank << 21); - } else if (nbank < nbanks_2048k + nbanks_512k || nbank >= nbanks_2048k + nbanks_512k + ((mem_size & 511) >> 7)) { - addr &= 0x7ffff; - addr |= (nbanks_2048k << 21) | ((nbank - nbanks_2048k) << 19); - } else { - addr &= 0x1ffff; - addr |= (nbanks_2048k << 21) | (nbanks_512k << 19) | ((nbank - nbanks_2048k - nbanks_512k) << 17); - } - } + if (nbank < nbanks_2048k || (nbanks_2048k > 0 && nbank >= nbanks_2048k + nbanks_512k + ((mem_size & 511) >> 7))) { + addr &= 0x1fffff; + addr |= (nbank << 21); + } else if (nbank < nbanks_2048k + nbanks_512k || nbank >= nbanks_2048k + nbanks_512k + ((mem_size & 511) >> 7)) { + addr &= 0x7ffff; + addr |= (nbanks_2048k << 21) | ((nbank - nbanks_2048k) << 19); + } else { + addr &= 0x1ffff; + addr |= (nbanks_2048k << 21) | (nbanks_512k << 19) | ((nbank - nbanks_2048k - nbanks_512k) << 17); + } + } } else { - switch(dev->regs[SCAT_DRAM_CONFIGURATION] & 0x1f) { - case 0x02: - case 0x04: - nbank = addr >> 19; - if ((nbank & (dev->regs[SCAT_EXTENDED_BOUNDARY] & 0x80 ? 7 : 3)) < 2) { - nbank = (addr >> 10) & 1; - addr2 = addr >> 11; - } else - addr2 = addr >> 10; - break; + switch (dev->regs[SCAT_DRAM_CONFIGURATION] & 0x1f) { + case 0x02: + case 0x04: + nbank = addr >> 19; + if ((nbank & (dev->regs[SCAT_EXTENDED_BOUNDARY] & 0x80 ? 7 : 3)) < 2) { + nbank = (addr >> 10) & 1; + addr2 = addr >> 11; + } else + addr2 = addr >> 10; + break; - case 0x03: - nbank = addr >> 19; - if ((nbank & (dev->regs[SCAT_EXTENDED_BOUNDARY] & 0x80 ? 7 : 3)) < 2) { - nbank = (addr >> 10) & 1; - addr2 = addr >> 11; - } else if ((nbank & (dev->regs[SCAT_EXTENDED_BOUNDARY] & 0x80 ? 7 : 3)) == 2 && (addr & 0x7ffff) < 0x60000) { - addr ^= 0x1f0000; - nbank = (addr >> 10) & 1; - addr2 = addr >> 11; - } else - addr2 = addr >> 10; - break; + case 0x03: + nbank = addr >> 19; + if ((nbank & (dev->regs[SCAT_EXTENDED_BOUNDARY] & 0x80 ? 7 : 3)) < 2) { + nbank = (addr >> 10) & 1; + addr2 = addr >> 11; + } else if ((nbank & (dev->regs[SCAT_EXTENDED_BOUNDARY] & 0x80 ? 7 : 3)) == 2 && (addr & 0x7ffff) < 0x60000) { + addr ^= 0x1f0000; + nbank = (addr >> 10) & 1; + addr2 = addr >> 11; + } else + addr2 = addr >> 10; + break; - case 0x05: - nbank = addr >> 19; - if ((nbank & (dev->regs[SCAT_EXTENDED_BOUNDARY] & 0x80 ? 7 : 3)) < 4) { - nbank = (addr >> 10) & 3; - addr2 = addr >> 12; - } else - addr2 = addr >> 10; - break; + case 0x05: + nbank = addr >> 19; + if ((nbank & (dev->regs[SCAT_EXTENDED_BOUNDARY] & 0x80 ? 7 : 3)) < 4) { + nbank = (addr >> 10) & 3; + addr2 = addr >> 12; + } else + addr2 = addr >> 10; + break; - case 0x06: - nbank = addr >> 19; - if (nbank < 2) { - nbank = (addr >> 10) & 1; - addr2 = addr >> 11; - } else { - nbank = 2 + ((addr - 0x100000) >> 21); - addr2 = (addr - 0x100000) >> 11; - } - break; + case 0x06: + nbank = addr >> 19; + if (nbank < 2) { + nbank = (addr >> 10) & 1; + addr2 = addr >> 11; + } else { + nbank = 2 + ((addr - 0x100000) >> 21); + addr2 = (addr - 0x100000) >> 11; + } + break; - case 0x07: - case 0x0f: - nbank = addr >> 19; - if (nbank < 2) { - nbank = (addr >> 10) & 1; - addr2 = addr >> 11; - } else if (nbank < 10) { - nbank = 2 + (((addr - 0x100000) >> 11) & 1); - addr2 = (addr - 0x100000) >> 12; - } else { - nbank = 4 + ((addr - 0x500000) >> 21); - addr2 = (addr - 0x500000) >> 11; - } - break; + case 0x07: + case 0x0f: + nbank = addr >> 19; + if (nbank < 2) { + nbank = (addr >> 10) & 1; + addr2 = addr >> 11; + } else if (nbank < 10) { + nbank = 2 + (((addr - 0x100000) >> 11) & 1); + addr2 = (addr - 0x100000) >> 12; + } else { + nbank = 4 + ((addr - 0x500000) >> 21); + addr2 = (addr - 0x500000) >> 11; + } + break; - case 0x08: - nbank = addr >> 19; - if (nbank < 4) { - nbank = 1; - addr2 = addr >> 11; - } else if (nbank == 4) { - nbank = 0; - addr2 = addr >> 10; - } else { - nbank -= 3; - addr2 = addr >> 10; - } - break; + case 0x08: + nbank = addr >> 19; + if (nbank < 4) { + nbank = 1; + addr2 = addr >> 11; + } else if (nbank == 4) { + nbank = 0; + addr2 = addr >> 10; + } else { + nbank -= 3; + addr2 = addr >> 10; + } + break; - case 0x09: - nbank = addr >> 19; - if (nbank < 8) { - nbank = 1 + ((addr >> 11) & 1); - addr2 = addr >> 12; - } else if (nbank == 8) { - nbank = 0; - addr2 = addr >> 10; - } else { - nbank -= 6; - addr2 = addr >> 10; - } - break; + case 0x09: + nbank = addr >> 19; + if (nbank < 8) { + nbank = 1 + ((addr >> 11) & 1); + addr2 = addr >> 12; + } else if (nbank == 8) { + nbank = 0; + addr2 = addr >> 10; + } else { + nbank -= 6; + addr2 = addr >> 10; + } + break; - case 0x0a: - nbank = addr >> 19; - if (nbank < 8) { - nbank = 1 + ((addr >> 11) & 1); - addr2 = addr >> 12; - } else if (nbank < 12) { - nbank = 3; - addr2 = addr >> 11; - } else if (nbank == 12) { - nbank = 0; - addr2 = addr >> 10; - } else { - nbank -= 9; - addr2 = addr >> 10; - } - break; + case 0x0a: + nbank = addr >> 19; + if (nbank < 8) { + nbank = 1 + ((addr >> 11) & 1); + addr2 = addr >> 12; + } else if (nbank < 12) { + nbank = 3; + addr2 = addr >> 11; + } else if (nbank == 12) { + nbank = 0; + addr2 = addr >> 10; + } else { + nbank -= 9; + addr2 = addr >> 10; + } + break; - case 0x0b: - nbank = addr >> 21; - addr2 = addr >> 11; - break; + case 0x0b: + nbank = addr >> 21; + addr2 = addr >> 11; + break; - case 0x0c: - case 0x0d: - nbank = addr >> 21; - if ((nbank & (dev->regs[SCAT_EXTENDED_BOUNDARY] & 0x80 ? 7 : 3)) < 2) { - nbank = (addr >> 11) & 1; - addr2 = addr >> 12; - } else - addr2 = addr >> 11; - break; + case 0x0c: + case 0x0d: + nbank = addr >> 21; + if ((nbank & (dev->regs[SCAT_EXTENDED_BOUNDARY] & 0x80 ? 7 : 3)) < 2) { + nbank = (addr >> 11) & 1; + addr2 = addr >> 12; + } else + addr2 = addr >> 11; + break; - case 0x0e: - case 0x13: - nbank = addr >> 21; - if ((nbank & (dev->regs[SCAT_EXTENDED_BOUNDARY] & 0x80 ? 7 : 3)) < 4) { - nbank = (addr >> 11) & 3; - addr2 = addr >> 13; - } else - addr2 = addr >> 11; - break; + case 0x0e: + case 0x13: + nbank = addr >> 21; + if ((nbank & (dev->regs[SCAT_EXTENDED_BOUNDARY] & 0x80 ? 7 : 3)) < 4) { + nbank = (addr >> 11) & 3; + addr2 = addr >> 13; + } else + addr2 = addr >> 11; + break; - case 0x10: - case 0x11: - nbank = addr >> 19; - if (nbank < 2) { - nbank = (addr >> 10) & 1; - addr2 = addr >> 11; - } else if (nbank < 10) { - nbank = 2 + (((addr - 0x100000) >> 11) & 1); - addr2 = (addr - 0x100000) >> 12; - } else if (nbank < 18) { - nbank = 4 + (((addr - 0x500000) >> 11) & 1); - addr2 = (addr - 0x500000) >> 12; - } else { - nbank = 6 + ((addr - 0x900000) >> 21); - addr2 = (addr - 0x900000) >> 11; - } - break; + case 0x10: + case 0x11: + nbank = addr >> 19; + if (nbank < 2) { + nbank = (addr >> 10) & 1; + addr2 = addr >> 11; + } else if (nbank < 10) { + nbank = 2 + (((addr - 0x100000) >> 11) & 1); + addr2 = (addr - 0x100000) >> 12; + } else if (nbank < 18) { + nbank = 4 + (((addr - 0x500000) >> 11) & 1); + addr2 = (addr - 0x500000) >> 12; + } else { + nbank = 6 + ((addr - 0x900000) >> 21); + addr2 = (addr - 0x900000) >> 11; + } + break; - case 0x12: - nbank = addr >> 19; - if (nbank < 2) { - nbank = (addr >> 10) & 1; - addr2 = addr >> 11; - } else if (nbank < 10) { - nbank = 2 + (((addr - 0x100000) >> 11) & 1); - addr2 = (addr - 0x100000) >> 12; - } else { - nbank = 4 + (((addr - 0x500000) >> 11) & 3); - addr2 = (addr - 0x500000) >> 13; - } - break; + case 0x12: + nbank = addr >> 19; + if (nbank < 2) { + nbank = (addr >> 10) & 1; + addr2 = addr >> 11; + } else if (nbank < 10) { + nbank = 2 + (((addr - 0x100000) >> 11) & 1); + addr2 = (addr - 0x100000) >> 12; + } else { + nbank = 4 + (((addr - 0x500000) >> 11) & 3); + addr2 = (addr - 0x500000) >> 13; + } + break; - case 0x14: - case 0x15: - nbank = addr >> 21; - if ((nbank & 7) < 4) { - nbank = (addr >> 11) & 3; - addr2 = addr >> 13; - } else if ((nbank & 7) < 6) { - nbank = 4 + (((addr - 0x800000) >> 11) & 1); - addr2 = (addr - 0x800000) >> 12; - } else { - nbank = 6 + (((addr - 0xc00000) >> 11) & 3); - addr2 = (addr - 0xc00000) >> 13; - } - break; + case 0x14: + case 0x15: + nbank = addr >> 21; + if ((nbank & 7) < 4) { + nbank = (addr >> 11) & 3; + addr2 = addr >> 13; + } else if ((nbank & 7) < 6) { + nbank = 4 + (((addr - 0x800000) >> 11) & 1); + addr2 = (addr - 0x800000) >> 12; + } else { + nbank = 6 + (((addr - 0xc00000) >> 11) & 3); + addr2 = (addr - 0xc00000) >> 13; + } + break; - case 0x16: - nbank = ((addr >> 21) & 4) | ((addr >> 11) & 3); - addr2 = addr >> 13; - break; + case 0x16: + nbank = ((addr >> 21) & 4) | ((addr >> 11) & 3); + addr2 = addr >> 13; + break; - case 0x17: - if (dev->external_is_RAS && (addr & 0x800) == 0) - return 0xffffffff; - nbank = addr >> 19; - if (nbank < 2) { - nbank = (addr >> 10) & 1; - addr2 = addr >> 11; - } else { - nbank = 2 + ((addr - 0x100000) >> 23); - addr2 = (addr - 0x100000) >> 12; - } - break; + case 0x17: + if (dev->external_is_RAS && (addr & 0x800) == 0) + return 0xffffffff; + nbank = addr >> 19; + if (nbank < 2) { + nbank = (addr >> 10) & 1; + addr2 = addr >> 11; + } else { + nbank = 2 + ((addr - 0x100000) >> 23); + addr2 = (addr - 0x100000) >> 12; + } + break; - case 0x18: - if (dev->external_is_RAS && (addr & 0x800) == 0) - return 0xffffffff; - nbank = addr >> 21; - if (nbank < 4) { - nbank = 1; - addr2 = addr >> 12; - } else if (nbank == 4) { - nbank = 0; - addr2 = addr >> 11; - } else { - nbank -= 3; - addr2 = addr >> 11; - } - break; + case 0x18: + if (dev->external_is_RAS && (addr & 0x800) == 0) + return 0xffffffff; + nbank = addr >> 21; + if (nbank < 4) { + nbank = 1; + addr2 = addr >> 12; + } else if (nbank == 4) { + nbank = 0; + addr2 = addr >> 11; + } else { + nbank -= 3; + addr2 = addr >> 11; + } + break; - case 0x19: - if (dev->external_is_RAS && (addr & 0x800) == 0) - return 0xffffffff; - nbank = addr >> 23; - if ((nbank & 3) < 2) { - nbank = (addr >> 12) & 1; - addr2 = addr >> 13; - } else - addr2 = addr >> 12; - break; + case 0x19: + if (dev->external_is_RAS && (addr & 0x800) == 0) + return 0xffffffff; + nbank = addr >> 23; + if ((nbank & 3) < 2) { + nbank = (addr >> 12) & 1; + addr2 = addr >> 13; + } else + addr2 = addr >> 12; + break; - default: - if ((dev->regs[SCAT_DRAM_CONFIGURATION] & 0x1f) < 6) { - nbank = addr >> 19; - addr2 = (addr >> 10) & 0x1ff; - } else if ((dev->regs[SCAT_DRAM_CONFIGURATION] & 0x1f) < 0x17) { - nbank = addr >> 21; - addr2 = (addr >> 11) & 0x3ff; - } else { - nbank = addr >> 23; - addr2 = (addr >> 12) & 0x7ff; - } - break; - } + default: + if ((dev->regs[SCAT_DRAM_CONFIGURATION] & 0x1f) < 6) { + nbank = addr >> 19; + addr2 = (addr >> 10) & 0x1ff; + } else if ((dev->regs[SCAT_DRAM_CONFIGURATION] & 0x1f) < 0x17) { + nbank = addr >> 21; + addr2 = (addr >> 11) & 0x3ff; + } else { + nbank = addr >> 23; + addr2 = (addr >> 12) & 0x7ff; + } + break; + } - nbank &= (dev->regs[SCAT_EXTENDED_BOUNDARY] & 0x80) ? 7 : 3; + nbank &= (dev->regs[SCAT_EXTENDED_BOUNDARY] & 0x80) ? 7 : 3; - if ((dev->regs[SCAT_DRAM_CONFIGURATION] & 0x1f) > 0x16 && nbank == 3) - return 0xffffffff; + if ((dev->regs[SCAT_DRAM_CONFIGURATION] & 0x1f) > 0x16 && nbank == 3) + return 0xffffffff; - if (dev->external_is_RAS && (dev->regs[SCAT_EXTENDED_BOUNDARY] & 0x80) == 0) { - if (nbank == 3) - nbank = 7; - else - return 0xffffffff; - } else if (!dev->external_is_RAS && dev->regs[SCAT_EXTENDED_BOUNDARY] & 0x80) { - switch(nbank) { - case 7: - nbank = 3; - break; + if (dev->external_is_RAS && (dev->regs[SCAT_EXTENDED_BOUNDARY] & 0x80) == 0) { + if (nbank == 3) + nbank = 7; + else + return 0xffffffff; + } else if (!dev->external_is_RAS && dev->regs[SCAT_EXTENDED_BOUNDARY] & 0x80) { + switch (nbank) { + case 7: + nbank = 3; + break; - /* Note - In the following cases, the chipset accesses multiple memory banks - at the same time, so it's impossible to predict which memory bank - is actually accessed. */ - case 5: - case 1: - nbank = 1; - break; + /* Note - In the following cases, the chipset accesses multiple memory banks + at the same time, so it's impossible to predict which memory bank + is actually accessed. */ + case 5: + case 1: + nbank = 1; + break; - case 3: - nbank = 2; - break; + case 3: + nbank = 2; + break; - default: - nbank = 0; - break; - } - } + default: + nbank = 0; + break; + } + } - switch(mem_size & ~511) { - case 1024: - case 1536: - addr &= 0x3ff; - if (nbank < 2) - addr |= (nbank << 10) | ((addr2 & 0x1ff) << 11); - else - addr |= ((addr2 & 0x1ff) << 10) | (nbank << 19); - break; + switch (mem_size & ~511) { + case 1024: + case 1536: + addr &= 0x3ff; + if (nbank < 2) + addr |= (nbank << 10) | ((addr2 & 0x1ff) << 11); + else + addr |= ((addr2 & 0x1ff) << 10) | (nbank << 19); + break; - case 2048: - if ((dev->regs[SCAT_DRAM_CONFIGURATION] & 0x1f) == 5) { - addr &= 0x3ff; - if (nbank < 4) - addr |= (nbank << 10) | ((addr2 & 0x1ff) << 12); - else - addr |= ((addr2 & 0x1ff) << 10) | (nbank << 19); - } else { - addr &= 0x7ff; - addr |= ((addr2 & 0x3ff) << 11) | (nbank << 21); - } - break; + case 2048: + if ((dev->regs[SCAT_DRAM_CONFIGURATION] & 0x1f) == 5) { + addr &= 0x3ff; + if (nbank < 4) + addr |= (nbank << 10) | ((addr2 & 0x1ff) << 12); + else + addr |= ((addr2 & 0x1ff) << 10) | (nbank << 19); + } else { + addr &= 0x7ff; + addr |= ((addr2 & 0x3ff) << 11) | (nbank << 21); + } + break; - case 2560: - if (nbank == 0) - addr = (addr & 0x3ff) | ((addr2 & 0x1ff) << 10); - else { - addr &= 0x7ff; - addr2 &= 0x3ff; - addr = addr + 0x80000 + ((addr2 << 11) | ((nbank - 1) << 21)); - } - break; + case 2560: + if (nbank == 0) + addr = (addr & 0x3ff) | ((addr2 & 0x1ff) << 10); + else { + addr &= 0x7ff; + addr2 &= 0x3ff; + addr = addr + 0x80000 + ((addr2 << 11) | ((nbank - 1) << 21)); + } + break; - case 3072: - if (nbank < 2) - addr = (addr & 0x3ff) | (nbank << 10) | ((addr2 & 0x1ff) << 11); - else - addr = 0x100000 + ((addr & 0x7ff) | ((addr2 & 0x3ff) << 11) | ((nbank - 2) << 21)); - break; + case 3072: + if (nbank < 2) + addr = (addr & 0x3ff) | (nbank << 10) | ((addr2 & 0x1ff) << 11); + else + addr = 0x100000 + ((addr & 0x7ff) | ((addr2 & 0x3ff) << 11) | ((nbank - 2) << 21)); + break; - case 4096: - case 6144: - addr &= 0x7ff; - if (nbank < 2) - addr |= (nbank << 11) | ((addr2 & 0x3ff) << 12); - else - addr |= ((addr2 & 0x3ff) << 11) | (nbank << 21); - break; + case 4096: + case 6144: + addr &= 0x7ff; + if (nbank < 2) + addr |= (nbank << 11) | ((addr2 & 0x3ff) << 12); + else + addr |= ((addr2 & 0x3ff) << 11) | (nbank << 21); + break; - case 4608: - if (((dev->regs[SCAT_DRAM_CONFIGURATION] & 0x1f) >= 8 && (dev->regs[SCAT_DRAM_CONFIGURATION] & 0x1f) <= 0x0a) || ((dev->regs[SCAT_DRAM_CONFIGURATION] & 0x1f) == 0x18)) { - if (nbank == 0) - addr = (addr & 0x3ff) | ((addr2 & 0x1ff) << 10); - else if (nbank < 3) - addr = 0x80000 + ((addr & 0x7ff) | ((nbank - 1) << 11) | ((addr2 & 0x3ff) << 12)); - else - addr = 0x480000 + ((addr & 0x3ff) | ((addr2 & 0x1ff) << 10) | ((nbank - 3) << 19)); - } else if (nbank == 0) - addr = (addr & 0x3ff) | ((addr2 & 0x1ff) << 10); - else { - addr &= 0x7ff; - addr2 &= 0x3ff; - addr = addr + 0x80000 + ((addr2 << 11) | ((nbank - 1) << 21)); - } - break; + case 4608: + if (((dev->regs[SCAT_DRAM_CONFIGURATION] & 0x1f) >= 8 && (dev->regs[SCAT_DRAM_CONFIGURATION] & 0x1f) <= 0x0a) || ((dev->regs[SCAT_DRAM_CONFIGURATION] & 0x1f) == 0x18)) { + if (nbank == 0) + addr = (addr & 0x3ff) | ((addr2 & 0x1ff) << 10); + else if (nbank < 3) + addr = 0x80000 + ((addr & 0x7ff) | ((nbank - 1) << 11) | ((addr2 & 0x3ff) << 12)); + else + addr = 0x480000 + ((addr & 0x3ff) | ((addr2 & 0x1ff) << 10) | ((nbank - 3) << 19)); + } else if (nbank == 0) + addr = (addr & 0x3ff) | ((addr2 & 0x1ff) << 10); + else { + addr &= 0x7ff; + addr2 &= 0x3ff; + addr = addr + 0x80000 + ((addr2 << 11) | ((nbank - 1) << 21)); + } + break; - case 5120: - case 7168: - if (nbank < 2) - addr = (addr & 0x3ff) | (nbank << 10) | ((addr2 & 0x1ff) << 11); - else if (nbank < 4) - addr = 0x100000 + ((addr & 0x7ff) | ((addr2 & 0x3ff) << 12) | ((nbank & 1) << 11)); - else - addr = 0x100000 + ((addr & 0x7ff) | ((addr2 & 0x3ff) << 11) | ((nbank - 2) << 21)); - break; + case 5120: + case 7168: + if (nbank < 2) + addr = (addr & 0x3ff) | (nbank << 10) | ((addr2 & 0x1ff) << 11); + else if (nbank < 4) + addr = 0x100000 + ((addr & 0x7ff) | ((addr2 & 0x3ff) << 12) | ((nbank & 1) << 11)); + else + addr = 0x100000 + ((addr & 0x7ff) | ((addr2 & 0x3ff) << 11) | ((nbank - 2) << 21)); + break; - case 6656: - if (((dev->regs[SCAT_DRAM_CONFIGURATION] & 0x1f) >= 8 && (dev->regs[SCAT_DRAM_CONFIGURATION] & 0x1f) <= 0x0a) || ((dev->regs[SCAT_DRAM_CONFIGURATION] & 0x1f) == 0x18)) { - if (nbank == 0) - addr = (addr & 0x3ff) | ((addr2 & 0x1ff) << 10); - else if (nbank < 3) - addr = 0x80000 + ((addr & 0x7ff) | ((nbank - 1) << 11) | ((addr2 & 0x3ff) << 12)); - else if (nbank == 3) - addr = 0x480000 + ((addr & 0x7ff) | ((addr2 & 0x3ff) << 11)); - else - addr = 0x680000 + ((addr & 0x3ff) | ((addr2 & 0x1ff) << 10) | ((nbank - 4) << 19)); - } else if (nbank == 0) - addr = (addr & 0x3ff) | ((addr2 & 0x1ff) << 10); - else if (nbank == 1) { - addr &= 0x7ff; - addr2 &= 0x3ff; - addr = addr + 0x80000 + (addr2 << 11); - } else { - addr &= 0x7ff; - addr2 &= 0x3ff; - addr = addr + 0x280000 + ((addr2 << 12) | ((nbank & 1) << 11) | (((nbank - 2) & 6) << 21)); - } - break; + case 6656: + if (((dev->regs[SCAT_DRAM_CONFIGURATION] & 0x1f) >= 8 && (dev->regs[SCAT_DRAM_CONFIGURATION] & 0x1f) <= 0x0a) || ((dev->regs[SCAT_DRAM_CONFIGURATION] & 0x1f) == 0x18)) { + if (nbank == 0) + addr = (addr & 0x3ff) | ((addr2 & 0x1ff) << 10); + else if (nbank < 3) + addr = 0x80000 + ((addr & 0x7ff) | ((nbank - 1) << 11) | ((addr2 & 0x3ff) << 12)); + else if (nbank == 3) + addr = 0x480000 + ((addr & 0x7ff) | ((addr2 & 0x3ff) << 11)); + else + addr = 0x680000 + ((addr & 0x3ff) | ((addr2 & 0x1ff) << 10) | ((nbank - 4) << 19)); + } else if (nbank == 0) + addr = (addr & 0x3ff) | ((addr2 & 0x1ff) << 10); + else if (nbank == 1) { + addr &= 0x7ff; + addr2 &= 0x3ff; + addr = addr + 0x80000 + (addr2 << 11); + } else { + addr &= 0x7ff; + addr2 &= 0x3ff; + addr = addr + 0x280000 + ((addr2 << 12) | ((nbank & 1) << 11) | (((nbank - 2) & 6) << 21)); + } + break; - case 8192: - addr &= 0x7ff; - if (nbank < 4) - addr |= (nbank << 11) | ((addr2 & 0x3ff) << 13); - else - addr |= ((addr2 & 0x3ff) << 11) | (nbank << 21); - break; + case 8192: + addr &= 0x7ff; + if (nbank < 4) + addr |= (nbank << 11) | ((addr2 & 0x3ff) << 13); + else + addr |= ((addr2 & 0x3ff) << 11) | (nbank << 21); + break; - case 9216: - if (nbank < 2) - addr = (addr & 0x3ff) | (nbank << 10) | ((addr2 & 0x1ff) << 11); - else if (dev->external_is_RAS) { - if (nbank < 6) - addr = 0x100000 + ((addr & 0x7ff) | ((addr2 & 0x3ff) << 12) | ((nbank & 1) << 11)); - else - addr = 0x100000 + ((addr & 0x7ff) | ((addr2 & 0x3ff) << 11) | ((nbank - 2) << 21)); - } else - addr = 0x100000 + ((addr & 0xfff) | ((addr2 & 0x7ff) << 12) | ((nbank - 2) << 23)); - break; + case 9216: + if (nbank < 2) + addr = (addr & 0x3ff) | (nbank << 10) | ((addr2 & 0x1ff) << 11); + else if (dev->external_is_RAS) { + if (nbank < 6) + addr = 0x100000 + ((addr & 0x7ff) | ((addr2 & 0x3ff) << 12) | ((nbank & 1) << 11)); + else + addr = 0x100000 + ((addr & 0x7ff) | ((addr2 & 0x3ff) << 11) | ((nbank - 2) << 21)); + } else + addr = 0x100000 + ((addr & 0xfff) | ((addr2 & 0x7ff) << 12) | ((nbank - 2) << 23)); + break; - case 10240: - if (dev->external_is_RAS) { - addr &= 0x7ff; - if (nbank < 4) - addr |= (nbank << 11) | ((addr2 & 0x3ff) << 13); - else - addr |= ((addr2 & 0x3ff) << 11) | (nbank << 21); - } else if (nbank == 0) - addr = (addr & 0x7ff) | ((addr2 & 0x3ff) << 11); - else { - addr &= 0xfff; - addr2 &= 0x7ff; - addr = addr + 0x200000 + ((addr2 << 12) | ((nbank - 1) << 23)); - } - break; + case 10240: + if (dev->external_is_RAS) { + addr &= 0x7ff; + if (nbank < 4) + addr |= (nbank << 11) | ((addr2 & 0x3ff) << 13); + else + addr |= ((addr2 & 0x3ff) << 11) | (nbank << 21); + } else if (nbank == 0) + addr = (addr & 0x7ff) | ((addr2 & 0x3ff) << 11); + else { + addr &= 0xfff; + addr2 &= 0x7ff; + addr = addr + 0x200000 + ((addr2 << 12) | ((nbank - 1) << 23)); + } + break; - case 11264: - if (nbank < 2) - addr = (addr & 0x3ff) | (nbank << 10) | ((addr2 & 0x1ff) << 11); - else if (nbank < 6) - addr = 0x100000 + ((addr & 0x7ff) | ((addr2 & 0x3ff) << 12) | ((nbank & 1) << 11)); - else - addr = 0x100000 + ((addr & 0x7ff) | ((addr2 & 0x3ff) << 11) | ((nbank - 2) << 21)); - break; + case 11264: + if (nbank < 2) + addr = (addr & 0x3ff) | (nbank << 10) | ((addr2 & 0x1ff) << 11); + else if (nbank < 6) + addr = 0x100000 + ((addr & 0x7ff) | ((addr2 & 0x3ff) << 12) | ((nbank & 1) << 11)); + else + addr = 0x100000 + ((addr & 0x7ff) | ((addr2 & 0x3ff) << 11) | ((nbank - 2) << 21)); + break; - case 12288: - if (dev->external_is_RAS) { - addr &= 0x7ff; - if (nbank < 4) - addr |= (nbank << 11) | ((addr2 & 0x3ff) << 13); - else if (nbank < 6) - addr |= ((nbank & 1) << 11) | ((addr2 & 0x3ff) << 12) | ((nbank & 4) << 21); - else - addr |= ((addr2 & 0x3ff) << 11) | (nbank << 21); - } else { - if (nbank < 2) - addr = (addr & 0x7ff) | (nbank << 11) | ((addr2 & 0x3ff) << 12); - else - addr = 0x400000 + ((addr & 0xfff) | ((addr2 & 0x7ff) << 12) | ((nbank - 2) << 23)); - } - break; + case 12288: + if (dev->external_is_RAS) { + addr &= 0x7ff; + if (nbank < 4) + addr |= (nbank << 11) | ((addr2 & 0x3ff) << 13); + else if (nbank < 6) + addr |= ((nbank & 1) << 11) | ((addr2 & 0x3ff) << 12) | ((nbank & 4) << 21); + else + addr |= ((addr2 & 0x3ff) << 11) | (nbank << 21); + } else { + if (nbank < 2) + addr = (addr & 0x7ff) | (nbank << 11) | ((addr2 & 0x3ff) << 12); + else + addr = 0x400000 + ((addr & 0xfff) | ((addr2 & 0x7ff) << 12) | ((nbank - 2) << 23)); + } + break; - case 13312: - if (nbank < 2) - addr = (addr & 0x3FF) | (nbank << 10) | ((addr2 & 0x1FF) << 11); - else if (nbank < 4) - addr = 0x100000 + ((addr & 0x7FF) | ((addr2 & 0x3FF) << 12) | ((nbank & 1) << 11)); - else - addr = 0x500000 + ((addr & 0x7FF) | ((addr2 & 0x3FF) << 13) | ((nbank & 3) << 11)); - break; + case 13312: + if (nbank < 2) + addr = (addr & 0x3FF) | (nbank << 10) | ((addr2 & 0x1FF) << 11); + else if (nbank < 4) + addr = 0x100000 + ((addr & 0x7FF) | ((addr2 & 0x3FF) << 12) | ((nbank & 1) << 11)); + else + addr = 0x500000 + ((addr & 0x7FF) | ((addr2 & 0x3FF) << 13) | ((nbank & 3) << 11)); + break; - case 14336: - addr &= 0x7ff; - if (nbank < 4) - addr |= (nbank << 11) | ((addr2 & 0x3ff) << 13); - else if (nbank < 6) - addr |= ((nbank & 1) << 11) | ((addr2 & 0x3ff) << 12) | ((nbank & 4) << 21); - else - addr |= ((addr2 & 0x3ff) << 11) | (nbank << 21); - break; + case 14336: + addr &= 0x7ff; + if (nbank < 4) + addr |= (nbank << 11) | ((addr2 & 0x3ff) << 13); + else if (nbank < 6) + addr |= ((nbank & 1) << 11) | ((addr2 & 0x3ff) << 12) | ((nbank & 4) << 21); + else + addr |= ((addr2 & 0x3ff) << 11) | (nbank << 21); + break; - case 16384: - if (dev->external_is_RAS) { - addr &= 0x7ff; - addr2 &= 0x3ff; - addr |= ((nbank & 3) << 11) | (addr2 << 13) | ((nbank & 4) << 21); - } else { - addr &= 0xfff; - addr2 &= 0x7ff; - if (nbank < 2) - addr |= (addr2 << 13) | (nbank << 12); - else - addr |= (addr2 << 12) | (nbank << 23); - } - break; + case 16384: + if (dev->external_is_RAS) { + addr &= 0x7ff; + addr2 &= 0x3ff; + addr |= ((nbank & 3) << 11) | (addr2 << 13) | ((nbank & 4) << 21); + } else { + addr &= 0xfff; + addr2 &= 0x7ff; + if (nbank < 2) + addr |= (addr2 << 13) | (nbank << 12); + else + addr |= (addr2 << 12) | (nbank << 23); + } + break; - default: - if (mem_size < 2048 || ((mem_size & 1536) == 512) || (mem_size == 2048 && (dev->regs[SCAT_DRAM_CONFIGURATION] & 0x1f) < 6)) { - addr &= 0x3ff; - addr2 &= 0x1ff; - addr |= (addr2 << 10) | (nbank << 19); - } else if (mem_size < 8192 || (dev->regs[SCAT_DRAM_CONFIGURATION] & 0x1f) < 0x17) { - addr &= 0x7ff; - addr2 &= 0x3ff; - addr |= (addr2 << 11) | (nbank << 21); - } else { - addr &= 0xfff; - addr2 &= 0x7ff; - addr |= (addr2 << 12) | (nbank << 23); - } - break; - } + default: + if (mem_size < 2048 || ((mem_size & 1536) == 512) || (mem_size == 2048 && (dev->regs[SCAT_DRAM_CONFIGURATION] & 0x1f) < 6)) { + addr &= 0x3ff; + addr2 &= 0x1ff; + addr |= (addr2 << 10) | (nbank << 19); + } else if (mem_size < 8192 || (dev->regs[SCAT_DRAM_CONFIGURATION] & 0x1f) < 0x17) { + addr &= 0x7ff; + addr2 &= 0x3ff; + addr |= (addr2 << 11) | (nbank << 21); + } else { + addr &= 0xfff; + addr2 &= 0x7ff; + addr |= (addr2 << 12) | (nbank << 23); + } + break; + } } return addr; } - static void set_global_EMS_state(scat_t *dev, int state) { - uint32_t base_addr, virt_addr; - int i, conf; + uint32_t base_addr; + uint32_t virt_addr; + int conf; - for (i = ((dev->regs[SCAT_VERSION] & 0xf0) == 0) ? 0 : 24; i < 32; i++) { - base_addr = (i + 16) << 14; + for (uint32_t i = ((dev->regs[SCAT_VERSION] & 0xf0) == 0) ? 0 : 24; i < 32; i++) { + base_addr = (i + 16) << 14; - if (i >= 24) - base_addr += 0x30000; - if (state && (dev->page[i].regs_2x9 & 0x80)) { - virt_addr = get_addr(dev, base_addr, &dev->page[i]); - if (i < 24) - mem_mapping_disable(&dev->efff_mapping[i]); - else - mem_mapping_disable(&dev->efff_mapping[i + 12]); - mem_mapping_enable(&dev->ems_mapping[i]); + if (i >= 24) + base_addr += 0x30000; + if (state && (dev->page[i].regs_2x9 & 0x80)) { + virt_addr = get_addr(dev, base_addr, &dev->page[i]); + if (i < 24) + mem_mapping_disable(&dev->efff_mapping[i]); + else + mem_mapping_disable(&dev->efff_mapping[i + 12]); + mem_mapping_enable(&dev->ems_mapping[i]); - if (virt_addr < ((uint32_t)mem_size << 10)) - mem_mapping_set_exec(&dev->ems_mapping[i], ram + virt_addr); - else - mem_mapping_set_exec(&dev->ems_mapping[i], NULL); - } else { - mem_mapping_set_exec(&dev->ems_mapping[i], ram + base_addr); - mem_mapping_disable(&dev->ems_mapping[i]); + if (virt_addr < ((uint32_t) mem_size << 10)) + mem_mapping_set_exec(&dev->ems_mapping[i], ram + virt_addr); + else + mem_mapping_set_exec(&dev->ems_mapping[i], NULL); + } else { + mem_mapping_set_exec(&dev->ems_mapping[i], ram + base_addr); + mem_mapping_disable(&dev->ems_mapping[i]); - conf = (dev->regs[SCAT_VERSION] & 0xf0) ? (dev->regs[SCAT_DRAM_CONFIGURATION] & 0x1f) - : (dev->regs[SCAT_DRAM_CONFIGURATION] & 0xf) | - ((dev->regs[SCAT_EXTENDED_BOUNDARY] & 0x40) >> 2); - if (i < 24) { - if (conf > 1 || (conf == 1 && i < 16)) - mem_mapping_enable(&dev->efff_mapping[i]); - else - mem_mapping_disable(&dev->efff_mapping[i]); - } else if (conf > 3 || ((dev->regs[SCAT_VERSION] & 0xf0) != 0 && conf == 2)) - mem_mapping_enable(&dev->efff_mapping[i + 12]); - else - mem_mapping_disable(&dev->efff_mapping[i + 12]); - } + conf = (dev->regs[SCAT_VERSION] & 0xf0) ? (dev->regs[SCAT_DRAM_CONFIGURATION] & 0x1f) + : (dev->regs[SCAT_DRAM_CONFIGURATION] & 0xf) | ((dev->regs[SCAT_EXTENDED_BOUNDARY] & 0x40) >> 2); + if (i < 24) { + if (conf > 1 || (conf == 1 && i < 16)) + mem_mapping_enable(&dev->efff_mapping[i]); + else + mem_mapping_disable(&dev->efff_mapping[i]); + } else if (conf > 3 || ((dev->regs[SCAT_VERSION] & 0xf0) != 0 && conf == 2)) + mem_mapping_enable(&dev->efff_mapping[i + 12]); + else + mem_mapping_disable(&dev->efff_mapping[i + 12]); + } } flushmmucache(); } - static void memmap_state_update(scat_t *dev) { uint32_t addr; - int i; - for (i = (((dev->regs[SCAT_VERSION] & 0xf0) == 0) ? 0 : 16); i < 44; i++) { - addr = get_addr(dev, 0x40000 + (i << 14), &dev->null_page); - mem_mapping_set_exec(&dev->efff_mapping[i], - addr < ((uint32_t)mem_size << 10) ? ram + addr : NULL); + for (uint8_t i = (((dev->regs[SCAT_VERSION] & 0xf0) == 0) ? 0 : 16); i < 44; i++) { + addr = get_addr(dev, 0x40000 + (i << 14), &dev->null_page); + mem_mapping_set_exec(&dev->efff_mapping[i], + addr < ((uint32_t) mem_size << 10) ? ram + addr : NULL); } addr = get_addr(dev, 0, &dev->null_page); mem_mapping_set_exec(&dev->low_mapping[0], - addr < ((uint32_t)mem_size << 10) ? ram + addr : NULL); + addr < ((uint32_t) mem_size << 10) ? ram + addr : NULL); addr = get_addr(dev, 0xf0000, &dev->null_page); mem_mapping_set_exec(&dev->low_mapping[1], - addr < ((uint32_t)mem_size << 10) ? ram + addr : NULL); + addr < ((uint32_t) mem_size << 10) ? ram + addr : NULL); - for (i = 2; i < 32; i++) { - addr = get_addr(dev, i << 19, &dev->null_page); - mem_mapping_set_exec(&dev->low_mapping[i], - addr < ((uint32_t)mem_size << 10) ? ram + addr : NULL); + for (uint8_t i = 2; i < 32; i++) { + addr = get_addr(dev, i << 19, &dev->null_page); + mem_mapping_set_exec(&dev->low_mapping[i], + addr < ((uint32_t) mem_size << 10) ? ram + addr : NULL); } if ((dev->regs[SCAT_VERSION] & 0xf0) == 0) { - for (i = 0; i < max_map[(dev->regs[SCAT_DRAM_CONFIGURATION] & 0x0f) | - ((dev->regs[SCAT_EXTENDED_BOUNDARY] & 0x40) >> 2)]; i++) - mem_mapping_enable(&dev->low_mapping[i]); + uint8_t j = 0; - for (; i < 32; i++) - mem_mapping_disable(&dev->low_mapping[i]); + for (j = 0; j < max_map[(dev->regs[SCAT_DRAM_CONFIGURATION] & 0x0f) | ((dev->regs[SCAT_EXTENDED_BOUNDARY] & 0x40) >> 2)]; j++) + mem_mapping_enable(&dev->low_mapping[j]); - for (i = 24; i < 36; i++) { - if (((dev->regs[SCAT_DRAM_CONFIGURATION] & 0x0f) | (dev->regs[SCAT_EXTENDED_BOUNDARY] & 0x40)) < 4) - mem_mapping_disable(&dev->efff_mapping[i]); - else - mem_mapping_enable(&dev->efff_mapping[i]); - } + for (; j < 32; j++) + mem_mapping_disable(&dev->low_mapping[j]); + + for (j = 24; j < 36; j++) { + if (((dev->regs[SCAT_DRAM_CONFIGURATION] & 0x0f) | (dev->regs[SCAT_EXTENDED_BOUNDARY] & 0x40)) < 4) + mem_mapping_disable(&dev->efff_mapping[j]); + else + mem_mapping_enable(&dev->efff_mapping[j]); + } } else { - for (i = 0; i < max_map_sx[dev->regs[SCAT_DRAM_CONFIGURATION] & 0x1f]; i++) - mem_mapping_enable(&dev->low_mapping[i]); + uint8_t j = 0; + for (j = 0; j < max_map_sx[dev->regs[SCAT_DRAM_CONFIGURATION] & 0x1f]; j++) + mem_mapping_enable(&dev->low_mapping[j]); - for (; i < 32; i++) - mem_mapping_disable(&dev->low_mapping[i]); + for (; j < 32; j++) + mem_mapping_disable(&dev->low_mapping[j]); - for(i = 24; i < 36; i++) { - if ((dev->regs[SCAT_DRAM_CONFIGURATION] & 0x1f) < 2 || (dev->regs[SCAT_DRAM_CONFIGURATION] & 0x1f) == 3) - mem_mapping_disable(&dev->efff_mapping[i]); - else - mem_mapping_enable(&dev->efff_mapping[i]); - } + for (j = 24; j < 36; j++) { + if ((dev->regs[SCAT_DRAM_CONFIGURATION] & 0x1f) < 2 || (dev->regs[SCAT_DRAM_CONFIGURATION] & 0x1f) == 3) + mem_mapping_disable(&dev->efff_mapping[j]); + else + mem_mapping_enable(&dev->efff_mapping[j]); + } } - if ((((dev->regs[SCAT_VERSION] & 0xf0) == 0) && - (dev->regs[SCAT_EXTENDED_BOUNDARY] & 0x40) == 0) || ((dev->regs[SCAT_VERSION] & 0xf0) != 0)) { - if ((((dev->regs[SCAT_VERSION] & 0xf0) == 0) && - (dev->regs[SCAT_DRAM_CONFIGURATION] & 0x0f) == 3) || - (((dev->regs[SCAT_VERSION] & 0xf0) != 0) && (dev->regs[SCAT_DRAM_CONFIGURATION] & 0x1f) == 3)) { - mem_mapping_disable(&dev->low_mapping[2]); + if ((((dev->regs[SCAT_VERSION] & 0xf0) == 0) && (dev->regs[SCAT_EXTENDED_BOUNDARY] & 0x40) == 0) || ((dev->regs[SCAT_VERSION] & 0xf0) != 0)) { + if ((((dev->regs[SCAT_VERSION] & 0xf0) == 0) && (dev->regs[SCAT_DRAM_CONFIGURATION] & 0x0f) == 3) || (((dev->regs[SCAT_VERSION] & 0xf0) != 0) && (dev->regs[SCAT_DRAM_CONFIGURATION] & 0x1f) == 3)) { + mem_mapping_disable(&dev->low_mapping[2]); - for (i = 0; i < 6; i++) { - addr = get_addr(dev, 0x100000 + (i << 16), &dev->null_page); - mem_mapping_set_exec(&dev->remap_mapping[i], - addr < ((uint32_t)mem_size << 10) ? ram + addr : NULL); - mem_mapping_enable(&dev->remap_mapping[i]); - } - } else { - for (i = 0; i < 6; i++) - mem_mapping_disable(&dev->remap_mapping[i]); + for (uint8_t i = 0; i < 6; i++) { + addr = get_addr(dev, 0x100000 + (i << 16), &dev->null_page); + mem_mapping_set_exec(&dev->remap_mapping[i], + addr < ((uint32_t) mem_size << 10) ? ram + addr : NULL); + mem_mapping_enable(&dev->remap_mapping[i]); + } + } else { + for (uint8_t i = 0; i < 6; i++) + mem_mapping_disable(&dev->remap_mapping[i]); - if ((((dev->regs[SCAT_VERSION] & 0xf0) == 0) && - (dev->regs[SCAT_DRAM_CONFIGURATION] & 0x0f) > 4) || - (((dev->regs[SCAT_VERSION] & 0xf0) != 0) && - (dev->regs[SCAT_DRAM_CONFIGURATION] & 0x1f) > 3)) - mem_mapping_enable(&dev->low_mapping[2]); - } + if ((((dev->regs[SCAT_VERSION] & 0xf0) == 0) && (dev->regs[SCAT_DRAM_CONFIGURATION] & 0x0f) > 4) || (((dev->regs[SCAT_VERSION] & 0xf0) != 0) && (dev->regs[SCAT_DRAM_CONFIGURATION] & 0x1f) > 3)) + mem_mapping_enable(&dev->low_mapping[2]); + } } else { - for (i = 0; i < 6; i++) - mem_mapping_disable(&dev->remap_mapping[i]); + for (uint8_t i = 0; i < 6; i++) + mem_mapping_disable(&dev->remap_mapping[i]); - mem_mapping_enable(&dev->low_mapping[2]); + mem_mapping_enable(&dev->low_mapping[2]); } set_global_EMS_state(dev, dev->regs[SCAT_EMS_CONTROL] & 0x80); - flushmmucache_cr3(); + flushmmucache_nopc(); } - static void scat_out(uint16_t port, uint8_t val, void *priv) { - scat_t *dev = (scat_t *)priv; - uint8_t reg_valid = 0, - shadow_update = 0, - map_update = 0, - indx; - uint32_t base_addr, virt_addr; + scat_t *dev = (scat_t *) priv; + uint8_t reg_valid = 0; + uint8_t shadow_update = 0; + uint8_t map_update = 0; + uint8_t indx; + uint32_t base_addr; + uint32_t virt_addr; switch (port) { - case 0x22: - dev->indx = val; - break; + case 0x22: + dev->indx = val; + break; - case 0x23: - switch (dev->indx) { - case SCAT_DMA_WAIT_STATE_CONTROL: - case SCAT_CLOCK_CONTROL: - case SCAT_PERIPHERAL_CONTROL: - reg_valid = 1; - break; + case 0x23: + switch (dev->indx) { + case SCAT_DMA_WAIT_STATE_CONTROL: + case SCAT_CLOCK_CONTROL: + case SCAT_PERIPHERAL_CONTROL: + reg_valid = 1; + break; - case SCAT_EMS_CONTROL: - io_removehandler(0x0208, 0x0003, scat_in, NULL, NULL, scat_out, NULL, NULL, dev); - io_removehandler(0x0218, 0x0003, scat_in, NULL, NULL, scat_out, NULL, NULL, dev); + case SCAT_EMS_CONTROL: + io_removehandler(0x0208, 0x0003, scat_in, NULL, NULL, scat_out, NULL, NULL, dev); + io_removehandler(0x0218, 0x0003, scat_in, NULL, NULL, scat_out, NULL, NULL, dev); - if (val & 0x40) { - if (val & 1) - io_sethandler(0x0218, 3, scat_in, NULL, NULL, scat_out, NULL, NULL, dev); - else - io_sethandler(0x0208, 3, scat_in, NULL, NULL, scat_out, NULL, NULL, dev); - } - set_global_EMS_state(dev, val & 0x80); - reg_valid = 1; - break; + if (val & 0x40) { + if (val & 1) + io_sethandler(0x0218, 3, scat_in, NULL, NULL, scat_out, NULL, NULL, dev); + else + io_sethandler(0x0208, 3, scat_in, NULL, NULL, scat_out, NULL, NULL, dev); + } + set_global_EMS_state(dev, val & 0x80); + reg_valid = 1; + break; - case SCAT_POWER_MANAGEMENT: - /* TODO - Only use AUX parity disable bit for this version. - Other bits should be implemented later. */ - val &= (dev->regs[SCAT_VERSION] & 0xf0) == 0 ? 0x40 : 0x60; - reg_valid = 1; - break; + case SCAT_POWER_MANAGEMENT: + /* TODO - Only use AUX parity disable bit for this version. + Other bits should be implemented later. */ + val &= (dev->regs[SCAT_VERSION] & 0xf0) == 0 ? 0x40 : 0x60; + reg_valid = 1; + break; - case SCAT_DRAM_CONFIGURATION: - map_update = 1; + case SCAT_DRAM_CONFIGURATION: + map_update = 1; - if ((dev->regs[SCAT_VERSION] & 0xf0) == 0) { - cpu_waitstates = (val & 0x70) == 0 ? 1 : 2; - cpu_update_waitstates(); - } + if ((dev->regs[SCAT_VERSION] & 0xf0) == 0) { + cpu_waitstates = (val & 0x70) == 0 ? 1 : 2; + cpu_update_waitstates(); + } - reg_valid = 1; - break; + reg_valid = 1; + break; - case SCAT_EXTENDED_BOUNDARY: - if ((dev->regs[SCAT_VERSION] & 0xf0) == 0) { - if (dev->regs[SCAT_VERSION] < 4) { - val &= 0xbf; - set_xms_bound(dev, val & 0x0f); - } else { - val = (val & 0x7f) | 0x80; - set_xms_bound(dev, val & 0x4f); - } - } else - set_xms_bound(dev, val & 0x1f); + case SCAT_EXTENDED_BOUNDARY: + if ((dev->regs[SCAT_VERSION] & 0xf0) == 0) { + if (dev->regs[SCAT_VERSION] < 4) { + val &= 0xbf; + set_xms_bound(dev, val & 0x0f); + } else { + val = (val & 0x7f) | 0x80; + set_xms_bound(dev, val & 0x4f); + } + } else + set_xms_bound(dev, val & 0x1f); - mem_set_mem_state(0x40000, 0x60000, (val & 0x20) ? MEM_READ_EXTANY | MEM_WRITE_EXTANY : - MEM_READ_INTERNAL | MEM_WRITE_INTERNAL); - if ((val ^ dev->regs[SCAT_EXTENDED_BOUNDARY]) & 0xc0) - map_update = 1; - reg_valid = 1; - break; + mem_set_mem_state(0x40000, 0x60000, (val & 0x20) ? MEM_READ_EXTANY | MEM_WRITE_EXTANY : MEM_READ_INTERNAL | MEM_WRITE_INTERNAL); + if ((val ^ dev->regs[SCAT_EXTENDED_BOUNDARY]) & 0xc0) + map_update = 1; + reg_valid = 1; + break; - case SCAT_ROM_ENABLE: - case SCAT_RAM_WRITE_PROTECT: - case SCAT_SHADOW_RAM_ENABLE_1: - case SCAT_SHADOW_RAM_ENABLE_2: - case SCAT_SHADOW_RAM_ENABLE_3: - reg_valid = 1; - shadow_update = 1; - break; + case SCAT_ROM_ENABLE: + case SCAT_RAM_WRITE_PROTECT: + case SCAT_SHADOW_RAM_ENABLE_1: + case SCAT_SHADOW_RAM_ENABLE_2: + case SCAT_SHADOW_RAM_ENABLE_3: + reg_valid = 1; + shadow_update = 1; + break; - case SCATSX_LAPTOP_FEATURES: - if ((dev->regs[SCAT_VERSION] & 0xf0) != 0) { - val = (val & ~8) | (dev->regs[SCATSX_LAPTOP_FEATURES] & 8); - reg_valid = 1; - } - break; + case SCATSX_LAPTOP_FEATURES: + if ((dev->regs[SCAT_VERSION] & 0xf0) != 0) { + val = (val & ~8) | (dev->regs[SCATSX_LAPTOP_FEATURES] & 8); + reg_valid = 1; + } + break; - case SCATSX_FAST_VIDEO_CONTROL: - case SCATSX_FAST_VIDEORAM_ENABLE: - case SCATSX_HIGH_PERFORMANCE_REFRESH: - case SCATSX_CAS_TIMING_FOR_DMA: - if ((dev->regs[SCAT_VERSION] & 0xf0) != 0) - reg_valid = 1; - break; + case SCATSX_FAST_VIDEO_CONTROL: + case SCATSX_FAST_VIDEORAM_ENABLE: + case SCATSX_HIGH_PERFORMANCE_REFRESH: + case SCATSX_CAS_TIMING_FOR_DMA: + if ((dev->regs[SCAT_VERSION] & 0xf0) != 0) + reg_valid = 1; + break; - default: - break; - } + default: + break; + } - if (reg_valid) - dev->regs[dev->indx] = val; + if (reg_valid) + dev->regs[dev->indx] = val; - if (shadow_update) - shadow_state_update(dev); + if (shadow_update) + shadow_state_update(dev); - if (map_update) - memmap_state_update(dev); - break; + if (map_update) + memmap_state_update(dev); + break; - case 0x208: - case 0x218: - if ((dev->regs[SCAT_EMS_CONTROL] & 0x41) == (0x40 | ((port & 0x10) >> 4))) { - if ((dev->regs[SCAT_VERSION] & 0xf0) == 0) - indx = dev->reg_2xA & 0x1f; - else - indx = ((dev->reg_2xA & 0x40) >> 4) + (dev->reg_2xA & 0x3) + 24; - dev->page[indx].regs_2x8 = val; - base_addr = (indx + 16) << 14; - if (indx >= 24) - base_addr += 0x30000; + case 0x208: + case 0x218: + if ((dev->regs[SCAT_EMS_CONTROL] & 0x41) == (0x40 | ((port & 0x10) >> 4))) { + if ((dev->regs[SCAT_VERSION] & 0xf0) == 0) + indx = dev->reg_2xA & 0x1f; + else + indx = ((dev->reg_2xA & 0x40) >> 4) + (dev->reg_2xA & 0x3) + 24; + dev->page[indx].regs_2x8 = val; + base_addr = (indx + 16) << 14; + if (indx >= 24) + base_addr += 0x30000; - if ((dev->regs[SCAT_EMS_CONTROL] & 0x80) && (dev->page[indx].regs_2x9 & 0x80)) { - virt_addr = get_addr(dev, base_addr, &dev->page[indx]); - if (virt_addr < ((uint32_t)mem_size << 10)) - mem_mapping_set_exec(&dev->ems_mapping[indx], ram + virt_addr); - else - mem_mapping_set_exec(&dev->ems_mapping[indx], NULL); - flushmmucache(); - } - } - break; + if ((dev->regs[SCAT_EMS_CONTROL] & 0x80) && (dev->page[indx].regs_2x9 & 0x80)) { + virt_addr = get_addr(dev, base_addr, &dev->page[indx]); + if (virt_addr < ((uint32_t) mem_size << 10)) + mem_mapping_set_exec(&dev->ems_mapping[indx], ram + virt_addr); + else + mem_mapping_set_exec(&dev->ems_mapping[indx], NULL); + flushmmucache(); + } + } + break; - case 0x209: - case 0x219: - if ((dev->regs[SCAT_EMS_CONTROL] & 0x41) == (0x40 | ((port & 0x10) >> 4))) { - if ((dev->regs[SCAT_VERSION] & 0xf0) == 0) - indx = dev->reg_2xA & 0x1f; - else - indx = ((dev->reg_2xA & 0x40) >> 4) + (dev->reg_2xA & 0x3) + 24; - dev->page[indx].regs_2x9 = val; - base_addr = (indx + 16) << 14; - if (indx >= 24) - base_addr += 0x30000; + case 0x209: + case 0x219: + if ((dev->regs[SCAT_EMS_CONTROL] & 0x41) == (0x40 | ((port & 0x10) >> 4))) { + if ((dev->regs[SCAT_VERSION] & 0xf0) == 0) + indx = dev->reg_2xA & 0x1f; + else + indx = ((dev->reg_2xA & 0x40) >> 4) + (dev->reg_2xA & 0x3) + 24; + dev->page[indx].regs_2x9 = val; + base_addr = (indx + 16) << 14; + if (indx >= 24) + base_addr += 0x30000; - if (dev->regs[SCAT_EMS_CONTROL] & 0x80) { - if (val & 0x80) { - virt_addr = get_addr(dev, base_addr, &dev->page[indx]); - if (indx < 24) - mem_mapping_disable(&dev->efff_mapping[indx]); - else - mem_mapping_disable(&dev->efff_mapping[indx + 12]); - if (virt_addr < ((uint32_t)mem_size << 10)) - mem_mapping_set_exec(&dev->ems_mapping[indx], ram + virt_addr); - else - mem_mapping_set_exec(&dev->ems_mapping[indx], NULL); - mem_mapping_enable(&dev->ems_mapping[indx]); - } else { - mem_mapping_set_exec(&dev->ems_mapping[indx], ram + base_addr); - mem_mapping_disable(&dev->ems_mapping[indx]); - if (indx < 24) - mem_mapping_enable(&dev->efff_mapping[indx]); - else - mem_mapping_enable(&dev->efff_mapping[indx + 12]); - } + if (dev->regs[SCAT_EMS_CONTROL] & 0x80) { + if (val & 0x80) { + virt_addr = get_addr(dev, base_addr, &dev->page[indx]); + if (indx < 24) + mem_mapping_disable(&dev->efff_mapping[indx]); + else + mem_mapping_disable(&dev->efff_mapping[indx + 12]); + if (virt_addr < ((uint32_t) mem_size << 10)) + mem_mapping_set_exec(&dev->ems_mapping[indx], ram + virt_addr); + else + mem_mapping_set_exec(&dev->ems_mapping[indx], NULL); + mem_mapping_enable(&dev->ems_mapping[indx]); + } else { + mem_mapping_set_exec(&dev->ems_mapping[indx], ram + base_addr); + mem_mapping_disable(&dev->ems_mapping[indx]); + if (indx < 24) + mem_mapping_enable(&dev->efff_mapping[indx]); + else + mem_mapping_enable(&dev->efff_mapping[indx + 12]); + } - flushmmucache(); - } + flushmmucache(); + } - if (dev->reg_2xA & 0x80) - dev->reg_2xA = (dev->reg_2xA & 0xe0) | ((dev->reg_2xA + 1) & (((dev->regs[SCAT_VERSION] & 0xf0) == 0) ? 0x1f : 3)); - } - break; + if (dev->reg_2xA & 0x80) + dev->reg_2xA = (dev->reg_2xA & 0xe0) | ((dev->reg_2xA + 1) & (((dev->regs[SCAT_VERSION] & 0xf0) == 0) ? 0x1f : 3)); + } + break; - case 0x20a: - case 0x21a: - if ((dev->regs[SCAT_EMS_CONTROL] & 0x41) == (0x40 | ((port & 0x10) >> 4))) - dev->reg_2xA = ((dev->regs[SCAT_VERSION] & 0xf0) == 0) ? val : val & 0xc3; - break; + case 0x20a: + case 0x21a: + if ((dev->regs[SCAT_EMS_CONTROL] & 0x41) == (0x40 | ((port & 0x10) >> 4))) + dev->reg_2xA = ((dev->regs[SCAT_VERSION] & 0xf0) == 0) ? val : val & 0xc3; + break; + + default: + break; } } - static uint8_t scat_in(uint16_t port, void *priv) { - scat_t *dev = (scat_t *)priv; - uint8_t ret = 0xff, indx; + const scat_t *dev = (scat_t *) priv; + uint8_t ret = 0xff; + uint8_t indx; switch (port) { - case 0x23: - switch (dev->indx) { - case SCAT_MISCELLANEOUS_STATUS: - ret = (dev->regs[dev->indx] & 0x3f) | (~nmi_mask & 0x80) | ((mem_a20_key & 2) << 5); - break; + case 0x23: + switch (dev->indx) { + case SCAT_MISCELLANEOUS_STATUS: + ret = (dev->regs[dev->indx] & 0x3f) | (~nmi_mask & 0x80) | ((mem_a20_key & 2) << 5); + break; - case SCAT_DRAM_CONFIGURATION: - if ((dev->regs[SCAT_VERSION] & 0xf0) == 0) - ret = (dev->regs[dev->indx] & 0x8f) | (cpu_waitstates == 1 ? 0 : 0x10); - else - ret = dev->regs[dev->indx]; - break; + case SCAT_DRAM_CONFIGURATION: + if ((dev->regs[SCAT_VERSION] & 0xf0) == 0) + ret = (dev->regs[dev->indx] & 0x8f) | (cpu_waitstates == 1 ? 0 : 0x10); + else + ret = dev->regs[dev->indx]; + break; - case SCAT_EXTENDED_BOUNDARY: - ret = dev->regs[dev->indx]; - if ((dev->regs[SCAT_VERSION] & 0xf0) == 0) { - if ((dev->regs[SCAT_VERSION] & 0x0f) >= 4) - ret |= 0x80; - else - ret &= 0xaf; - } - break; + case SCAT_EXTENDED_BOUNDARY: + ret = dev->regs[dev->indx]; + if ((dev->regs[SCAT_VERSION] & 0xf0) == 0) { + if ((dev->regs[SCAT_VERSION] & 0x0f) >= 4) + ret |= 0x80; + else + ret &= 0xaf; + } + break; - default: - ret = dev->regs[dev->indx]; - break; - } - break; + default: + ret = dev->regs[dev->indx]; + break; + } + break; - case 0x208: - case 0x218: - if ((dev->regs[SCAT_EMS_CONTROL] & 0x41) == (0x40 | ((port & 0x10) >> 4))) { - if ((dev->regs[SCAT_VERSION] & 0xf0) == 0) - indx = dev->reg_2xA & 0x1f; - else - indx = ((dev->reg_2xA & 0x40) >> 4) + (dev->reg_2xA & 0x3) + 24; - ret = dev->page[indx].regs_2x8; - } - break; + case 0x208: + case 0x218: + if ((dev->regs[SCAT_EMS_CONTROL] & 0x41) == (0x40 | ((port & 0x10) >> 4))) { + if ((dev->regs[SCAT_VERSION] & 0xf0) == 0) + indx = dev->reg_2xA & 0x1f; + else + indx = ((dev->reg_2xA & 0x40) >> 4) + (dev->reg_2xA & 0x3) + 24; + ret = dev->page[indx].regs_2x8; + } + break; - case 0x209: - case 0x219: - if ((dev->regs[SCAT_EMS_CONTROL] & 0x41) == (0x40 | ((port & 0x10) >> 4))) { - if ((dev->regs[SCAT_VERSION] & 0xf0) == 0) - indx = dev->reg_2xA & 0x1f; - else - indx = ((dev->reg_2xA & 0x40) >> 4) + (dev->reg_2xA & 0x3) + 24; - ret = dev->page[indx].regs_2x9; - } - break; + case 0x209: + case 0x219: + if ((dev->regs[SCAT_EMS_CONTROL] & 0x41) == (0x40 | ((port & 0x10) >> 4))) { + if ((dev->regs[SCAT_VERSION] & 0xf0) == 0) + indx = dev->reg_2xA & 0x1f; + else + indx = ((dev->reg_2xA & 0x40) >> 4) + (dev->reg_2xA & 0x3) + 24; + ret = dev->page[indx].regs_2x9; + } + break; - case 0x20a: - case 0x21a: - if ((dev->regs[SCAT_EMS_CONTROL] & 0x41) == (0x40 | ((port & 0x10) >> 4))) - ret = dev->reg_2xA; - break; + case 0x20a: + case 0x21a: + if ((dev->regs[SCAT_EMS_CONTROL] & 0x41) == (0x40 | ((port & 0x10) >> 4))) + ret = dev->reg_2xA; + break; + default: + break; } return ret; } - static uint8_t mem_read_scatb(uint32_t addr, void *priv) { - ems_page_t *page = (ems_page_t *)priv; - scat_t *dev = (scat_t *)page->scat; - uint8_t val = 0xff; + ems_page_t *page = (ems_page_t *) priv; + scat_t *dev = (scat_t *) page->scat; + uint8_t val = 0xff; addr = get_addr(dev, addr, page); - if (addr < ((uint32_t)mem_size << 10)) - val = ram[addr]; + if (addr < ((uint32_t) mem_size << 10)) + val = ram[addr]; return val; } - static uint16_t mem_read_scatw(uint32_t addr, void *priv) { - ems_page_t *page = (ems_page_t *)priv; - scat_t *dev = (scat_t *)page->scat; - uint16_t val = 0xffff; + ems_page_t *page = (ems_page_t *) priv; + scat_t *dev = (scat_t *) page->scat; + uint16_t val = 0xffff; addr = get_addr(dev, addr, page); - if (addr < ((uint32_t)mem_size << 10)) - val = *(uint16_t *)&ram[addr]; + if (addr < ((uint32_t) mem_size << 10)) + val = *(uint16_t *) &ram[addr]; return val; } - static uint32_t mem_read_scatl(uint32_t addr, void *priv) { - ems_page_t *page = (ems_page_t *)priv; - scat_t *dev = (scat_t *)page->scat; - uint32_t val = 0xffffffff; + ems_page_t *page = (ems_page_t *) priv; + scat_t *dev = (scat_t *) page->scat; + uint32_t val = 0xffffffff; addr = get_addr(dev, addr, page); - if (addr < ((uint32_t)mem_size << 10)) - val = *(uint32_t *)&ram[addr]; + if (addr < ((uint32_t) mem_size << 10)) + val = *(uint32_t *) &ram[addr]; return val; } - static void mem_write_scatb(uint32_t addr, uint8_t val, void *priv) { - ems_page_t *page = (ems_page_t *)priv; - scat_t *dev = (scat_t *)page->scat; - uint32_t oldaddr = addr, chkaddr; + ems_page_t *page = (ems_page_t *) priv; + scat_t *dev = (scat_t *) page->scat; + uint32_t oldaddr = addr; + uint32_t chkaddr; - addr = get_addr(dev, addr, page); + addr = get_addr(dev, addr, page); chkaddr = page->valid ? addr : oldaddr; if ((chkaddr >= 0xc0000) && (chkaddr < 0x100000)) { - if (dev->regs[SCAT_RAM_WRITE_PROTECT] & (1 << ((chkaddr - 0xc0000) >> 15))) - return; + if (dev->regs[SCAT_RAM_WRITE_PROTECT] & (1 << ((chkaddr - 0xc0000) >> 15))) + return; } - if (addr < ((uint32_t)mem_size << 10)) - ram[addr] = val; + if (addr < ((uint32_t) mem_size << 10)) + ram[addr] = val; } - static void mem_write_scatw(uint32_t addr, uint16_t val, void *priv) { - ems_page_t *page = (ems_page_t *)priv; - scat_t *dev = (scat_t *)page->scat; - uint32_t oldaddr = addr, chkaddr; + ems_page_t *page = (ems_page_t *) priv; + scat_t *dev = (scat_t *) page->scat; + uint32_t oldaddr = addr; + uint32_t chkaddr; - addr = get_addr(dev, addr, page); + addr = get_addr(dev, addr, page); chkaddr = page->valid ? addr : oldaddr; if ((chkaddr >= 0xc0000) && (chkaddr < 0x100000)) { - if (dev->regs[SCAT_RAM_WRITE_PROTECT] & (1 << ((chkaddr - 0xc0000) >> 15))) - return; + if (dev->regs[SCAT_RAM_WRITE_PROTECT] & (1 << ((chkaddr - 0xc0000) >> 15))) + return; } - if (addr < ((uint32_t)mem_size << 10)) - *(uint16_t *)&ram[addr] = val; + if (addr < ((uint32_t) mem_size << 10)) + *(uint16_t *) &ram[addr] = val; } - static void mem_write_scatl(uint32_t addr, uint32_t val, void *priv) { - ems_page_t *page = (ems_page_t *)priv; - scat_t *dev = (scat_t *)page->scat; - uint32_t oldaddr = addr, chkaddr; + ems_page_t *page = (ems_page_t *) priv; + scat_t *dev = (scat_t *) page->scat; + uint32_t oldaddr = addr; + uint32_t chkaddr; - addr = get_addr(dev, addr, page); + addr = get_addr(dev, addr, page); chkaddr = page->valid ? addr : oldaddr; if ((chkaddr >= 0xc0000) && (chkaddr < 0x100000)) { - if (dev->regs[SCAT_RAM_WRITE_PROTECT] & (1 << ((chkaddr - 0xc0000) >> 15))) - return; + if (dev->regs[SCAT_RAM_WRITE_PROTECT] & (1 << ((chkaddr - 0xc0000) >> 15))) + return; } - if (addr < ((uint32_t)mem_size << 10)) - *(uint32_t *)&ram[addr] = val; + if (addr < ((uint32_t) mem_size << 10)) + *(uint32_t *) &ram[addr] = val; } - static void scat_close(void *priv) { - scat_t *dev = (scat_t *)priv; + scat_t *dev = (scat_t *) priv; free(dev); } - static void * scat_init(const device_t *info) { - scat_t *dev; - uint32_t i, k; - int sx; + scat_t *dev; + uint32_t j; + uint32_t k; + int sx; - dev = (scat_t *)malloc(sizeof(scat_t)); + dev = (scat_t *) malloc(sizeof(scat_t)); memset(dev, 0x00, sizeof(scat_t)); dev->type = info->local; sx = (dev->type == 32) ? 1 : 0; - for (i = 0; i < sizeof(dev->regs); i++) - dev->regs[i] = 0xff; + for (uint32_t i = 0; i < sizeof(dev->regs); i++) + dev->regs[i] = 0xff; if (sx) { - dev->regs[SCAT_VERSION] = 0x13; - dev->regs[SCAT_CLOCK_CONTROL] = 6; - dev->regs[SCAT_PERIPHERAL_CONTROL] = 0; - dev->regs[SCAT_DRAM_CONFIGURATION] = 1; - dev->regs[SCATSX_LAPTOP_FEATURES] = 0; - dev->regs[SCATSX_FAST_VIDEO_CONTROL] = 0; - dev->regs[SCATSX_FAST_VIDEORAM_ENABLE] = 0; - dev->regs[SCATSX_HIGH_PERFORMANCE_REFRESH] = 8; - dev->regs[SCATSX_CAS_TIMING_FOR_DMA] = 3; + dev->regs[SCAT_VERSION] = 0x13; + dev->regs[SCAT_CLOCK_CONTROL] = 6; + dev->regs[SCAT_PERIPHERAL_CONTROL] = 0; + dev->regs[SCAT_DRAM_CONFIGURATION] = 1; + dev->regs[SCATSX_LAPTOP_FEATURES] = 0; + dev->regs[SCATSX_FAST_VIDEO_CONTROL] = 0; + dev->regs[SCATSX_FAST_VIDEORAM_ENABLE] = 0; + dev->regs[SCATSX_HIGH_PERFORMANCE_REFRESH] = 8; + dev->regs[SCATSX_CAS_TIMING_FOR_DMA] = 3; } else { - switch(dev->type) { - case 4: - dev->regs[SCAT_VERSION] = 4; - break; + switch (dev->type) { + case 4: + dev->regs[SCAT_VERSION] = 4; + break; - default: - dev->regs[SCAT_VERSION] = 1; - break; - } - dev->regs[SCAT_CLOCK_CONTROL] = 2; - dev->regs[SCAT_PERIPHERAL_CONTROL] = 0x80; - dev->regs[SCAT_DRAM_CONFIGURATION] = cpu_waitstates == 1 ? 2 : 0x12; + default: + dev->regs[SCAT_VERSION] = 1; + break; + } + dev->regs[SCAT_CLOCK_CONTROL] = 2; + dev->regs[SCAT_PERIPHERAL_CONTROL] = 0x80; + dev->regs[SCAT_DRAM_CONFIGURATION] = cpu_waitstates == 1 ? 2 : 0x12; } dev->regs[SCAT_DMA_WAIT_STATE_CONTROL] = 0; - dev->regs[SCAT_MISCELLANEOUS_STATUS] = 0x37; - dev->regs[SCAT_ROM_ENABLE] = 0xc0; - dev->regs[SCAT_RAM_WRITE_PROTECT] = 0; - dev->regs[SCAT_POWER_MANAGEMENT] = 0; - dev->regs[SCAT_SHADOW_RAM_ENABLE_1] = 0; - dev->regs[SCAT_SHADOW_RAM_ENABLE_2] = 0; - dev->regs[SCAT_SHADOW_RAM_ENABLE_3] = 0; - dev->regs[SCAT_EXTENDED_BOUNDARY] = 0; - dev->regs[SCAT_EMS_CONTROL] = 0; + dev->regs[SCAT_MISCELLANEOUS_STATUS] = 0x37; + dev->regs[SCAT_ROM_ENABLE] = 0xc0; + dev->regs[SCAT_RAM_WRITE_PROTECT] = 0; + dev->regs[SCAT_POWER_MANAGEMENT] = 0; + dev->regs[SCAT_SHADOW_RAM_ENABLE_1] = 0; + dev->regs[SCAT_SHADOW_RAM_ENABLE_2] = 0; + dev->regs[SCAT_SHADOW_RAM_ENABLE_3] = 0; + dev->regs[SCAT_EXTENDED_BOUNDARY] = 0; + dev->regs[SCAT_EMS_CONTROL] = 0; /* Disable all system mappings, we will override them. */ mem_mapping_disable(&ram_low_mapping); - if (! sx) - mem_mapping_disable(&ram_mid_mapping); + if (!sx) + mem_mapping_disable(&ram_mid_mapping); mem_mapping_disable(&ram_high_mapping); - k = (sx) ? 0x80000 : 0x40000; + k = sx ? 0x80000 : 0x40000; - dev->null_page.valid = 0; + dev->null_page.valid = 0; dev->null_page.regs_2x8 = 0xff; dev->null_page.regs_2x9 = 0xff; - dev->null_page.scat = dev; + dev->null_page.scat = dev; mem_mapping_add(&dev->low_mapping[0], 0, k, - mem_read_scatb, mem_read_scatw, mem_read_scatl, - mem_write_scatb, mem_write_scatw, mem_write_scatl, - ram, MEM_MAPPING_INTERNAL, &dev->null_page); + mem_read_scatb, mem_read_scatw, mem_read_scatl, + mem_write_scatb, mem_write_scatw, mem_write_scatl, + ram, MEM_MAPPING_INTERNAL, &dev->null_page); mem_mapping_add(&dev->low_mapping[1], 0xf0000, 0x10000, - mem_read_scatb, mem_read_scatw, mem_read_scatl, - mem_write_scatb, mem_write_scatw, mem_write_scatl, - ram + 0xf0000, MEM_MAPPING_INTERNAL, &dev->null_page); + mem_read_scatb, mem_read_scatw, mem_read_scatl, + mem_write_scatb, mem_write_scatw, mem_write_scatl, + ram + 0xf0000, MEM_MAPPING_INTERNAL, &dev->null_page); - for (i = 2; i < 32; i++) { - mem_mapping_add(&dev->low_mapping[i], (i << 19), 0x80000, - mem_read_scatb, mem_read_scatw, mem_read_scatl, - mem_write_scatb, mem_write_scatw, mem_write_scatl, - ram + (i<<19), MEM_MAPPING_INTERNAL, &dev->null_page); + for (uint8_t i = 2; i < 32; i++) { + mem_mapping_add(&dev->low_mapping[i], (i << 19), 0x80000, + mem_read_scatb, mem_read_scatw, mem_read_scatl, + mem_write_scatb, mem_write_scatw, mem_write_scatl, + ram + (i << 19), MEM_MAPPING_INTERNAL, &dev->null_page); } if (sx) { - i = 16; - k = 0x40000; + j = 16; + k = 0x40000; } else { - i = 0; - k = (dev->regs[SCAT_VERSION] < 4) ? 0x40000 : 0x60000; + j = 0; + k = (dev->regs[SCAT_VERSION] < 4) ? 0x40000 : 0x60000; } mem_mapping_set_addr(&dev->low_mapping[31], 0xf80000, k); - for (; i < 44; i++) { - mem_mapping_add(&dev->efff_mapping[i], 0x40000 + (i << 14), 0x4000, - mem_read_scatb, mem_read_scatw, mem_read_scatl, - mem_write_scatb, mem_write_scatw, mem_write_scatl, - mem_size > (256 + (i << 4)) ? ram + 0x40000 + (i << 14) : NULL, - MEM_MAPPING_INTERNAL, &dev->null_page); + for (; j < 44; j++) { + mem_mapping_add(&dev->efff_mapping[j], 0x40000 + (j << 14), 0x4000, + mem_read_scatb, mem_read_scatw, mem_read_scatl, + mem_write_scatb, mem_write_scatw, mem_write_scatl, + mem_size > (256 + (j << 4)) ? ram + 0x40000 + (j << 14) : NULL, + MEM_MAPPING_INTERNAL, &dev->null_page); - if (sx) - mem_mapping_enable(&dev->efff_mapping[i]); + if (sx) + mem_mapping_enable(&dev->efff_mapping[j]); } if (sx) { - for (i = 24; i < 32; i++) { - dev->page[i].valid = 1; - dev->page[i].regs_2x8 = 0xff; - dev->page[i].regs_2x9 = 0x03; - dev->page[i].scat = dev; - mem_mapping_add(&dev->ems_mapping[i], (i + 28) << 14, 0x04000, - mem_read_scatb, mem_read_scatw, mem_read_scatl, - mem_write_scatb, mem_write_scatw, mem_write_scatl, - ram + ((i + 28) << 14), 0, &dev->page[i]); - mem_mapping_disable(&dev->ems_mapping[i]); - } + for (uint8_t i = 24; i < 32; i++) { + dev->page[i].valid = 1; + dev->page[i].regs_2x8 = 0xff; + dev->page[i].regs_2x9 = 0x03; + dev->page[i].scat = dev; + mem_mapping_add(&dev->ems_mapping[i], (i + 28) << 14, 0x04000, + mem_read_scatb, mem_read_scatw, mem_read_scatl, + mem_write_scatb, mem_write_scatw, mem_write_scatl, + ram + ((i + 28) << 14), 0, &dev->page[i]); + mem_mapping_disable(&dev->ems_mapping[i]); + } } else { - for (i = 0; i < 32; i++) { - dev->page[i].valid = 1; - dev->page[i].regs_2x8 = 0xff; - dev->page[i].regs_2x9 = 0x03; - dev->page[i].scat = dev; - mem_mapping_add(&dev->ems_mapping[i], (i + (i >= 24 ? 28 : 16)) << 14, 0x04000, - mem_read_scatb, mem_read_scatw, mem_read_scatl, - mem_write_scatb, mem_write_scatw, mem_write_scatl, - ram + ((i + (i >= 24 ? 28 : 16)) << 14), - 0, &dev->page[i]); - } + for (uint8_t i = 0; i < 32; i++) { + dev->page[i].valid = 1; + dev->page[i].regs_2x8 = 0xff; + dev->page[i].regs_2x9 = 0x03; + dev->page[i].scat = dev; + mem_mapping_add(&dev->ems_mapping[i], (i + (i >= 24 ? 28 : 16)) << 14, 0x04000, + mem_read_scatb, mem_read_scatw, mem_read_scatl, + mem_write_scatb, mem_write_scatw, mem_write_scatl, + ram + ((i + (i >= 24 ? 28 : 16)) << 14), + 0, &dev->page[i]); + } } - for (i = 0; i < 6; i++) { - mem_mapping_add(&dev->remap_mapping[i], 0x100000 + (i << 16), 0x10000, - mem_read_scatb, mem_read_scatw, mem_read_scatl, - mem_write_scatb, mem_write_scatw, mem_write_scatl, - mem_size >= 1024 ? ram + get_addr(dev, 0x100000 + (i << 16), &dev->null_page) : NULL, - MEM_MAPPING_INTERNAL, &dev->null_page); + for (uint8_t i = 0; i < 6; i++) { + mem_mapping_add(&dev->remap_mapping[i], 0x100000 + (i << 16), 0x10000, + mem_read_scatb, mem_read_scatw, mem_read_scatl, + mem_write_scatb, mem_write_scatw, mem_write_scatl, + mem_size >= 1024 ? ram + get_addr(dev, 0x100000 + (i << 16), &dev->null_page) : NULL, + MEM_MAPPING_INTERNAL, &dev->null_page); } if (sx) { - dev->external_is_RAS = scatsx_external_is_RAS[mem_size >> 9]; + dev->external_is_RAS = scatsx_external_is_RAS[mem_size >> 9]; } else { - dev->external_is_RAS = (dev->regs[SCAT_VERSION] > 3) || (((mem_size & ~2047) >> 11) + ((mem_size & 1536) >> 9) + ((mem_size & 511) >> 7)) > 4; + dev->external_is_RAS = (dev->regs[SCAT_VERSION] > 3) || (((mem_size & ~2047) >> 11) + ((mem_size & 1536) >> 9) + ((mem_size & 511) >> 7)) > 4; } set_xms_bound(dev, 0); @@ -1535,40 +1526,51 @@ scat_init(const device_t *info) shadow_state_update(dev); io_sethandler(0x0022, 2, - scat_in, NULL, NULL, scat_out, NULL, NULL, dev); + scat_in, NULL, NULL, scat_out, NULL, NULL, dev); device_add(&port_92_device); - return(dev); + return dev; } - const device_t scat_device = { - "C&T SCAT (v1)", - "scat", - 0, - 0, - scat_init, scat_close, NULL, - { NULL }, NULL, NULL, - NULL + .name = "C&T SCAT (v1)", + .internal_name = "scat", + .flags = 0, + .local = 0, + .init = scat_init, + .close = scat_close, + .reset = NULL, + { .available = NULL }, + .speed_changed = NULL, + .force_redraw = NULL, + .config = NULL }; const device_t scat_4_device = { - "C&T SCAT (v4)", - "scat_4", - 0, - 4, - scat_init, scat_close, NULL, - { NULL }, NULL, NULL, - NULL + .name = "C&T SCAT (v4)", + .internal_name = "scat_4", + .flags = 0, + .local = 4, + .init = scat_init, + .close = scat_close, + .reset = NULL, + { .available = NULL }, + .speed_changed = NULL, + .force_redraw = NULL, + .config = NULL }; const device_t scat_sx_device = { - "C&T SCATsx", - "scat_sx", - 0, - 32, - scat_init, scat_close, NULL, - { NULL }, NULL, NULL, - NULL + .name = "C&T SCATsx", + .internal_name = "scat_sx", + .flags = 0, + .local = 32, + .init = scat_init, + .close = scat_close, + .reset = NULL, + { .available = NULL }, + .speed_changed = NULL, + .force_redraw = NULL, + .config = NULL }; diff --git a/src/chipset/sis_5511.c b/src/chipset/sis_5511.c index 44e8f98de..f2ee01ebb 100644 --- a/src/chipset/sis_5511.c +++ b/src/chipset/sis_5511.c @@ -1,20 +1,19 @@ /* - * 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. + * 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. + * This file is part of the 86Box distribution. * - * Implementation of the SiS 5511/5512/5513 Pentium PCI/ISA Chipset. + * Implementation of the SiS 5511/5512/5513 Pentium PCI/ISA Chipset. * + * Authors: Miran Grca, + * Tiseno100, * - * - * Authors: Tiseno100, - * - * Copyright 2021 Tiseno100. + * Copyright 2021-2023 Miran Grca. + * Copyright 2021-2023 Tiseno100. */ - #include #include #include @@ -28,81 +27,99 @@ #include <86box/timer.h> #include <86box/mem.h> +#include <86box/nvr.h> #include <86box/hdd.h> #include <86box/hdc.h> #include <86box/hdc_ide.h> #include <86box/hdc_ide_sff8038i.h> #include <86box/pci.h> +#include <86box/pic.h> +#include <86box/pit.h> +#include <86box/pit_fast.h> +#include <86box/plat.h> +#include <86box/plat_unused.h> #include <86box/port_92.h> #include <86box/smram.h> +#include <86box/spd.h> #include <86box/chipset.h> -/* IDE Flags (1 Native / 0 Compatibility)*/ -#define PRIMARY_COMP_NAT_SWITCH (dev->pci_conf_sb[1][9] & 1) -#define SECONDARY_COMP_NAT_SWITCH (dev->pci_conf_sb[1][9] & 4) -#define PRIMARY_NATIVE_BASE (dev->pci_conf_sb[1][0x11] << 8) | (dev->pci_conf_sb[1][0x10] & 0xf8) -#define PRIMARY_NATIVE_SIDE (((dev->pci_conf_sb[1][0x15] << 8) | (dev->pci_conf_sb[1][0x14] & 0xfc)) + 2) -#define SECONDARY_NATIVE_BASE (dev->pci_conf_sb[1][0x19] << 8) | (dev->pci_conf_sb[1][0x18] & 0xf8) -#define SECONDARY_NATIVE_SIDE (((dev->pci_conf_sb[1][0x1d] << 8) | (dev->pci_conf_sb[1][0x1c] & 0xfc)) + 2) -#define BUS_MASTER_BASE ((dev->pci_conf_sb[1][0x20] & 0xf0) | (dev->pci_conf_sb[1][0x21] << 8)) - #ifdef ENABLE_SIS_5511_LOG int sis_5511_do_log = ENABLE_SIS_5511_LOG; + static void sis_5511_log(const char *fmt, ...) { - va_list ap; + va_list ap; - if (sis_5511_do_log) - { - va_start(ap, fmt); - pclog_ex(fmt, ap); - va_end(ap); - } + if (sis_5511_do_log) { + va_start(ap, fmt); + pclog_ex(fmt, ap); + va_end(ap); + } } #else -#define sis_5511_log(fmt, ...) +# define sis_5511_log(fmt, ...) #endif -typedef struct sis_5511_t -{ - uint8_t pci_conf[256], pci_conf_sb[2][256], - index, regs[16]; +typedef struct sis_5511_t { + uint8_t index; + uint8_t nb_slot; + uint8_t sb_slot; + uint8_t pad; - int nb_pci_slot, sb_pci_slot; + uint8_t regs[16]; + uint8_t states[7]; - sff8038i_t *ide_drive[2]; - smram_t *smram; - port_92_t *port_92; + uint8_t slic_regs[4096]; + uint8_t pci_conf[256]; + uint8_t pci_conf_sb[2][256]; + + mem_mapping_t slic_mapping; + + sff8038i_t *bm[2]; + smram_t *smram; + port_92_t *port_92; + void *pit; + nvr_t *nvr; + + uint8_t (*pit_read_reg)(void *priv, uint8_t reg); } sis_5511_t; static void sis_5511_shadow_recalc(sis_5511_t *dev) { - int i, state; + int state; uint32_t base; - for (i = 0x80; i <= 0x86; i++) { - if (i == 0x86) { - state = (dev->pci_conf[i] & 0x80) ? MEM_READ_INTERNAL : MEM_READ_EXTANY; - state |= (dev->pci_conf[i] & 0x20) ? MEM_WRITE_INTERNAL : MEM_WRITE_EXTANY; - mem_set_mem_state_both(0xf0000, 0x10000, state); - pclog("000F0000-000FFFFF\n"); - } else { - base = ((i & 0x07) << 15) + 0xc0000; + for (uint8_t i = 0x80; i <= 0x86; i++) { + if (i == 0x86) { + if ((dev->states[i & 0x0f] ^ dev->pci_conf[i]) & 0xa0) { + state = (dev->pci_conf[i] & 0x80) ? MEM_READ_INTERNAL : MEM_READ_EXTANY; + state |= (dev->pci_conf[i] & 0x20) ? MEM_WRITE_INTERNAL : MEM_WRITE_EXTANY; + mem_set_mem_state_both(0xf0000, 0x10000, state); + sis_5511_log("000F0000-000FFFFF\n"); + } + } else { + base = ((i & 0x07) << 15) + 0xc0000; - state = (dev->pci_conf[i] & 0x80) ? MEM_READ_INTERNAL : MEM_READ_EXTANY; - state |= (dev->pci_conf[i] & 0x20) ? MEM_WRITE_INTERNAL : MEM_WRITE_EXTANY; - mem_set_mem_state_both(base, 0x4000, state); - pclog("%08X-%08X\n", base, base + 0x3fff); + if ((dev->states[i & 0x0f] ^ dev->pci_conf[i]) & 0xa0) { + state = (dev->pci_conf[i] & 0x80) ? MEM_READ_INTERNAL : MEM_READ_EXTANY; + state |= (dev->pci_conf[i] & 0x20) ? MEM_WRITE_INTERNAL : MEM_WRITE_EXTANY; + mem_set_mem_state_both(base, 0x4000, state); + sis_5511_log("%08X-%08X\n", base, base + 0x3fff); + } - state = (dev->pci_conf[i] & 0x08) ? MEM_READ_INTERNAL : MEM_READ_EXTANY; - state |= (dev->pci_conf[i] & 0x02) ? MEM_WRITE_INTERNAL : MEM_WRITE_EXTANY; - mem_set_mem_state_both(base + 0x4000, 0x4000, state); - pclog("%08X-%08X\n", base + 0x4000, base + 0x7fff); - } + if ((dev->states[i & 0x0f] ^ dev->pci_conf[i]) & 0x0a) { + state = (dev->pci_conf[i] & 0x08) ? MEM_READ_INTERNAL : MEM_READ_EXTANY; + state |= (dev->pci_conf[i] & 0x02) ? MEM_WRITE_INTERNAL : MEM_WRITE_EXTANY; + mem_set_mem_state_both(base + 0x4000, 0x4000, state); + sis_5511_log("%08X-%08X\n", base + 0x4000, base + 0x7fff); + } + } + + dev->states[i & 0x0f] = dev->pci_conf[i]; } flushmmucache_nopc(); @@ -114,512 +131,625 @@ sis_5511_smram_recalc(sis_5511_t *dev) smram_disable_all(); switch (dev->pci_conf[0x65] >> 6) { - case 0: - smram_enable(dev->smram, 0x000e0000, 0x000e0000, 0x8000, dev->pci_conf[0x65] & 0x10, 1); - break; - case 1: - smram_enable(dev->smram, 0x000e0000, 0x000a0000, 0x8000, dev->pci_conf[0x65] & 0x10, 1); - break; - case 2: - smram_enable(dev->smram, 0x000e0000, 0x000b0000, 0x8000, dev->pci_conf[0x65] & 0x10, 1); - break; - } + case 0: + smram_enable(dev->smram, 0x000e0000, 0x000e0000, 0x8000, dev->pci_conf[0x65] & 0x10, 1); + break; + case 1: + smram_enable(dev->smram, 0x000e0000, 0x000a0000, 0x8000, dev->pci_conf[0x65] & 0x10, 1); + break; + case 2: + smram_enable(dev->smram, 0x000e0000, 0x000b0000, 0x8000, dev->pci_conf[0x65] & 0x10, 1); + break; - flushmmucache(); + default: + break; + } + + flushmmucache(); } - -void sis_5513_ide_handler(sis_5511_t *dev) -{ - ide_pri_disable(); - ide_sec_disable(); - if (dev->pci_conf_sb[1][4] & 1) - { - if (dev->pci_conf_sb[1][0x4a] & 4) - { - ide_set_base(0, PRIMARY_COMP_NAT_SWITCH ? PRIMARY_NATIVE_BASE : 0x1f0); - ide_set_side(0, PRIMARY_COMP_NAT_SWITCH ? PRIMARY_NATIVE_SIDE : 0x3f6); - ide_pri_enable(); - } - if (dev->pci_conf_sb[1][0x4a] & 2) - { - ide_set_base(1, SECONDARY_COMP_NAT_SWITCH ? SECONDARY_NATIVE_BASE : 0x170); - ide_set_side(1, SECONDARY_COMP_NAT_SWITCH ? SECONDARY_NATIVE_SIDE : 0x376); - ide_sec_enable(); - } - } -} - -void sis_5513_bm_handler(sis_5511_t *dev) -{ - sff_bus_master_handler(dev->ide_drive[0], dev->pci_conf_sb[1][4] & 4, BUS_MASTER_BASE); - sff_bus_master_handler(dev->ide_drive[1], dev->pci_conf_sb[1][4] & 4, BUS_MASTER_BASE + 8); -} - - static void -sis_5511_write(int func, int addr, uint8_t val, void *priv) +sis_5511_write(UNUSED(int func), int addr, uint8_t val, void *priv) { - sis_5511_t *dev = (sis_5511_t *)priv; + sis_5511_t *dev = (sis_5511_t *) priv; + + sis_5511_log("SiS 5511: [W] dev->pci_conf[%02X] = %02X\n", addr, val); + + if (func == 0x00) switch (addr) { + case 0x07: /* Status - High Byte */ + dev->pci_conf[addr] &= 0xb0; + break; + + case 0x50: + dev->pci_conf[addr] = val; + cpu_cache_ext_enabled = !!(val & 0x40); + cpu_update_waitstates(); + break; + + case 0x51: + dev->pci_conf[addr] = val & 0xfe; + break; + + case 0x52: + dev->pci_conf[addr] = val & 0x3f; + break; + + case 0x53: + case 0x54: + dev->pci_conf[addr] = val; + break; + + case 0x55: + dev->pci_conf[addr] = val & 0xf8; + break; + + case 0x56 ... 0x59: + dev->pci_conf[addr] = val; + break; + + case 0x5a: + /* TODO: Fast Gate A20 Emulation and Fast Reset Emulation on the KBC. + The former (bit 7) means the chipset intercepts D1h to 64h and 00h to 60h. + The latter (bit 6) means the chipset intercepts all odd FXh to 64h. + Bit 5 sets fast reset latency. This should be fixed on the other SiS + chipsets as well. */ + dev->pci_conf[addr] = val; + break; + + case 0x5b: + dev->pci_conf[addr] = val & 0xf7; + break; + + case 0x5c: + dev->pci_conf[addr] = val & 0xcf; + break; + + case 0x5d: + dev->pci_conf[addr] = val; + break; + + case 0x5e: + dev->pci_conf[addr] = val & 0xfe; + break; + + case 0x5f: + dev->pci_conf[addr] = val & 0xfe; + break; + + case 0x60: + dev->pci_conf[addr] = val & 0x3e; + if ((dev->pci_conf[0x68] & 1) && (val & 2)) { + smi_raise(); + dev->pci_conf[0x69] |= 1; + } + break; + + case 0x61 ... 0x64: + dev->pci_conf[addr] = val; + break; + + case 0x65: + dev->pci_conf[addr] = val & 0xd0; + sis_5511_smram_recalc(dev); + break; + + case 0x66: + dev->pci_conf[addr] = val & 0x7f; + break; + + case 0x67: + case 0x68: + dev->pci_conf[addr] = val; + break; + + case 0x69: + dev->pci_conf[addr] &= val; + break; + + case 0x6a ... 0x6e: + dev->pci_conf[addr] = val; + break; + + case 0x6f: + dev->pci_conf[addr] = val & 0x3f; + break; + + case 0x70: /* DRAM Bank Register 0-0 */ + case 0x72: /* DRAM Bank Register 0-1 */ + case 0x74: /* DRAM Bank Register 1-0 */ + case 0x76: /* DRAM Bank Register 1-1 */ + case 0x78: /* DRAM Bank Register 2-0 */ + case 0x7a: /* DRAM Bank Register 2-1 */ + case 0x7c: /* DRAM Bank Register 3-0 */ + case 0x7e: /* DRAM Bank Register 3-1 */ + spd_write_drbs(dev->regs, 0x70, 0x7e, 0x82); + break; + + case 0x71: /* DRAM Bank Register 0-0 */ + dev->pci_conf[addr] = val; + break; + + case 0x75: /* DRAM Bank Register 1-0 */ + case 0x79: /* DRAM Bank Register 2-0 */ + case 0x7d: /* DRAM Bank Register 3-0 */ + dev->pci_conf[addr] = val & 0x7f; + break; + + case 0x73: /* DRAM Bank Register 0-1 */ + case 0x77: /* DRAM Bank Register 1-1 */ + case 0x7b: /* DRAM Bank Register 2-1 */ + case 0x7f: /* DRAM Bank Register 3-1 */ + dev->pci_conf[addr] = val & 0x83; + break; + + case 0x80 ... 0x85: + dev->pci_conf[addr] = val & 0xee; + sis_5511_shadow_recalc(dev); + break; + case 0x86: + dev->pci_conf[addr] = val & 0xe8; + sis_5511_shadow_recalc(dev); + break; + + case 0x90 ... 0x93: /* 5512 General Purpose Register Index */ + dev->pci_conf[addr] = val; + break; + + default: + break; + } +} + +static void +sis_5511_slic_write(uint32_t addr, uint8_t val, void *priv) +{ + sis_5511_t *dev = (sis_5511_t *) priv; + + addr &= 0x00000fff; switch (addr) { - case 0x07: /* Status - High Byte */ - dev->pci_conf[addr] &= 0xb0; - break; - - case 0x50: - dev->pci_conf[addr] = val; - cpu_cache_ext_enabled = !!(val & 0x40); - cpu_update_waitstates(); - break; - - case 0x51: - dev->pci_conf[addr] = val & 0xfe; - break; - - case 0x52: - dev->pci_conf[addr] = val & 0x3f; - break; - - case 0x53: case 0x54: - dev->pci_conf[addr] = val; - break; - - case 0x55: - dev->pci_conf[addr] = val & 0xf8; - break; - - case 0x56 ... 0x59: - dev->pci_conf[addr] = val; - break; - - case 0x5a: - /* TODO: Fast Gate A20 Emulation and Fast Reset Emulation on the KBC. - The former (bit 7) means the chipset intercepts D1h to 64h and 00h to 60h. - The latter (bit 6) means the chipset intercepts all odd FXh to 64h. - Bit 5 sets fast reset latency. This should be fixed on the other SiS - chipsets as well. */ - dev->pci_conf[addr] = val; - break; - - case 0x5b: - dev->pci_conf[addr] = val & 0xf7; - break; - - case 0x5c: - dev->pci_conf[addr] = val & 0xcf; - break; - - case 0x5d: - dev->pci_conf[addr] = val; - break; - - case 0x5e: - dev->pci_conf[addr] = val & 0xfe; - break; - - case 0x5f: - dev->pci_conf[addr] = val & 0xfe; - break; - - case 0x60: - dev->pci_conf[addr] = val & 0x3e; - if ((dev->pci_conf[0x68] & 1) && (val & 2)) { - smi_line = 1; - dev->pci_conf[0x69] |= 1; - } - break; - - case 0x61 ... 0x64: - dev->pci_conf[addr] = val; - break; - - case 0x65: - dev->pci_conf[addr] = val & 0xd0; - sis_5511_smram_recalc(dev); - break; - - case 0x66: - dev->pci_conf[addr] = val & 0x7f; - break; - - case 0x67: case 0x68: - dev->pci_conf[addr] = val; - break; - - case 0x69: - dev->pci_conf[addr] &= val; - break; - - case 0x6a ... 0x6e: - dev->pci_conf[addr] = val; - break; - - case 0x6f: - dev->pci_conf[addr] = val & 0x3f; - break; - - case 0x70: /* DRAM Bank Register 0-0 */ - case 0x71: /* DRAM Bank Register 0-0 */ - case 0x72: /* DRAM Bank Register 0-1 */ - dev->pci_conf[addr] = val; - break; - - case 0x73: /* DRAM Bank Register 0-1 */ - dev->pci_conf[addr] = val & 0x83; - break; - - case 0x74: /* DRAM Bank Register 1-0 */ - dev->pci_conf[addr] = val; - break; - - case 0x75: /* DRAM Bank Register 1-0 */ - dev->pci_conf[addr] = val & 0x7f; - break; - - case 0x76: /* DRAM Bank Register 1-1 */ - dev->pci_conf[addr] = val; - break; - - case 0x77: /* DRAM Bank Register 1-1 */ - dev->pci_conf[addr] = val & 0x83; - break; - - case 0x78: /* DRAM Bank Register 2-0 */ - dev->pci_conf[addr] = val; - break; - - case 0x79: /* DRAM Bank Register 2-0 */ - dev->pci_conf[addr] = val & 0x7f; - break; - - case 0x7a: /* DRAM Bank Register 2-1 */ - dev->pci_conf[addr] = val; - break; - - case 0x7b: /* DRAM Bank Register 2-1 */ - dev->pci_conf[addr] = val & 0x83; - break; - - case 0x7c: /* DRAM Bank Register 3-0 */ - dev->pci_conf[addr] = val; - break; - - case 0x7d: /* DRAM Bank Register 3-0 */ - dev->pci_conf[addr] = val & 0x7f; - break; - - case 0x7e: /* DRAM Bank Register 3-1 */ - dev->pci_conf[addr] = val; - break; - - case 0x7f: /* DRAM Bank Register 3-1 */ - dev->pci_conf[addr] = val & 0x83; - break; - - case 0x80: - case 0x81: - case 0x82: - case 0x83: - case 0x84: - case 0x85: - case 0x86: - dev->pci_conf[addr] = val & ((addr == 0x86) ? 0xe8 : 0xee); - sis_5511_shadow_recalc(dev); - break; - - case 0x90: /* 5512 General Purpose Register Index */ - case 0x91: /* 5512 General Purpose Register Index */ - case 0x92: /* 5512 General Purpose Register Index */ - case 0x93: /* 5512 General Purpose Register Index */ - dev->pci_conf[addr] = val; - break; - } - sis_5511_log("SiS 5511: dev->pci_conf[%02x] = %02x POST: %02x\n", addr, dev->pci_conf[addr], inb(0x80)); + case 0x00000000: + case 0x00000008: /* 0x00000008 is a SiS 5512 register. */ + dev->slic_regs[addr] = val; + break; + case 0x00000010: + case 0x00000018: + case 0x00000028: + case 0x00000038: + dev->slic_regs[addr] = val & 0x01; + break; + case 0x00000030: + dev->slic_regs[addr] = val & 0x0f; + mem_mapping_set_addr(&dev->slic_mapping, + (((uint32_t) (val & 0x0f)) << 28) | 0x0fc00000, 0x00001000); + break; + } } static uint8_t -sis_5511_read(int func, int addr, void *priv) +sis_5511_read(UNUSED(int func), int addr, void *priv) { - sis_5511_t *dev = (sis_5511_t *)priv; - sis_5511_log("SiS 5511: dev->pci_conf[%02x] (%02x) POST %02x\n", addr, dev->pci_conf[addr], inb(0x80)); - return dev->pci_conf[addr]; + const sis_5511_t *dev = (sis_5511_t *) priv; + uint8_t ret = 0xff; + + if (func == 0x00) + ret = dev->pci_conf[addr]; + + sis_5511_log("SiS 5511: [R] dev->pci_conf[%02X] = %02X\n", addr, ret); + + return ret; } -void sis_5513_pci_to_isa_write(int addr, uint8_t val, sis_5511_t *dev) +static uint8_t +sis_5511_slic_read(uint32_t addr, void *priv) { - switch (addr) - { - case 0x04: /* Command */ - dev->pci_conf_sb[0][addr] = val & 7; - break; + sis_5511_t *dev = (sis_5511_t *) priv; + uint8_t ret = 0xff; - case 0x07: /* Status */ - dev->pci_conf_sb[0][addr] &= val & 0x36; - break; + addr &= 0x00000fff; - case 0x40: /* BIOS Control Register */ - dev->pci_conf_sb[0][addr] = val & 0x3f; - break; + switch (addr) { + case 0x00000008: /* 0x00000008 is a SiS 5512 register. */ + ret = dev->slic_regs[addr]; + break; + } - case 0x41: /* INTA# Remapping Control Register */ - case 0x42: /* INTB# Remapping Control Register */ - case 0x43: /* INTC# Remapping Control Register */ - case 0x44: /* INTD# Remapping Control Register */ - dev->pci_conf_sb[0][addr] = val & 0x8f; - pci_set_irq_routing(addr & 7, (val & 0x80) ? (val & 0x80) : PCI_IRQ_DISABLED); - break; - - case 0x48: /* ISA Master/DMA Memory Cycle Control Register 1 */ - case 0x49: /* ISA Master/DMA Memory Cycle Control Register 2 */ - case 0x4a: /* ISA Master/DMA Memory Cycle Control Register 3 */ - case 0x4b: /* ISA Master/DMA Memory Cycle Control Register 4 */ - case 0x4c: - case 0x4d: - case 0x4e: - case 0x4f: - case 0x50: - case 0x51: - case 0x52: - case 0x53: - case 0x54: - case 0x55: - case 0x56: - case 0x57: - case 0x58: - case 0x59: - case 0x5a: - case 0x5b: - case 0x5c: - case 0x5d: - case 0x5e: - case 0x5f: - dev->pci_conf_sb[0][addr] = val; - break; - - case 0x60: /* MIRQ0 Remapping Control Register */ - case 0x61: /* MIRQ1 Remapping Control Register */ - dev->pci_conf_sb[0][addr] = val & 0xcf; - pci_set_mirq_routing(addr & 1, (val & 0x80) ? (val & 0x0f) : PCI_IRQ_DISABLED); - break; - - case 0x62: /* On-board Device DMA Control Register */ - dev->pci_conf_sb[0][addr] = val; - break; - - case 0x63: /* IDEIRQ Remapping Control Register */ - dev->pci_conf_sb[0][addr] = val & 0x8f; - if (val & 0x80) - { - sff_set_irq_line(dev->ide_drive[0], (val & 0x80) ? (val & 0x0f) : PCI_IRQ_DISABLED); - sff_set_irq_line(dev->ide_drive[1], (val & 0x80) ? (val & 0x0f) : PCI_IRQ_DISABLED); - } - break; - - case 0x64: /* GPIO0 Control Register */ - dev->pci_conf_sb[0][addr] = val & 0xef; - break; - - case 0x65: - dev->pci_conf_sb[0][addr] = val & 0x80; - break; - - case 0x66: /* GPIO0 Output Mode Control Register */ - case 0x67: /* GPIO0 Output Mode Control Register */ - dev->pci_conf_sb[0][addr] = val; - break; - - case 0x6a: /* GPIO Status Register */ - dev->pci_conf_sb[0][addr] &= val & 0x15; - break; - } + return ret; } -void sis_5513_ide_write(int addr, uint8_t val, sis_5511_t *dev) +void +sis_5513_pci_to_isa_write(int addr, uint8_t val, sis_5511_t *dev) { - switch (addr) - { - case 0x04: /* Command low byte */ - dev->pci_conf_sb[1][addr] = val & 5; - sis_5513_ide_handler(dev); - sis_5513_bm_handler(dev); - break; - case 0x07: /* Status high byte */ - dev->pci_conf_sb[1][addr] &= val & 0x3f; - break; - case 0x09: /* Programming Interface Byte */ - dev->pci_conf_sb[1][addr] = val; - sis_5513_ide_handler(dev); - break; - case 0x0d: /* Latency Timer */ - dev->pci_conf_sb[1][addr] = val; - break; + sis_5511_log("SiS 5513 P2I: [W] dev->pci_conf_sb[0][%02X] = %02X\n", addr, val); - case 0x10: /* Primary Channel Base Address Register */ - case 0x11: /* Primary Channel Base Address Register */ - case 0x12: /* Primary Channel Base Address Register */ - case 0x13: /* Primary Channel Base Address Register */ - case 0x14: /* Primary Channel Base Address Register */ - case 0x15: /* Primary Channel Base Address Register */ - case 0x16: /* Primary Channel Base Address Register */ - case 0x17: /* Primary Channel Base Address Register */ - case 0x18: /* Secondary Channel Base Address Register */ - case 0x19: /* Secondary Channel Base Address Register */ - case 0x1a: /* Secondary Channel Base Address Register */ - case 0x1b: /* Secondary Channel Base Address Register */ - case 0x1c: /* Secondary Channel Base Address Register */ - case 0x1d: /* Secondary Channel Base Address Register */ - case 0x1e: /* Secondary Channel Base Address Register */ - case 0x1f: /* Secondary Channel Base Address Register */ - dev->pci_conf_sb[1][addr] = val; - sis_5513_ide_handler(dev); - break; + switch (addr) { + case 0x04: /* Command */ + dev->pci_conf_sb[0][addr] = val & 0x0f; + break; - case 0x20: /* Bus Master IDE Control Register Base Address */ - case 0x21: /* Bus Master IDE Control Register Base Address */ - case 0x22: /* Bus Master IDE Control Register Base Address */ - case 0x23: /* Bus Master IDE Control Register Base Address */ - dev->pci_conf_sb[1][addr] = val; - sis_5513_bm_handler(dev); - break; + case 0x07: /* Status */ + dev->pci_conf_sb[0][addr] = (dev->pci_conf_sb[0][addr] & 0x06) & ~(val & 0x30); + break; - case 0x30: /* Expansion ROM Base Address */ - case 0x31: /* Expansion ROM Base Address */ - case 0x32: /* Expansion ROM Base Address */ - case 0x33: /* Expansion ROM Base Address */ - dev->pci_conf_sb[1][addr] = val; - break; + case 0x40: /* BIOS Control Register */ + dev->pci_conf_sb[0][addr] = val & 0x3f; + break; - case 0x40: /* IDE Primary Channel/Master Drive Data Recovery Time Control */ - case 0x41: /* IDE Primary Channel/Master Drive DataActive Time Control */ - case 0x42: /* IDE Primary Channel/Slave Drive Data Recovery Time Control */ - case 0x43: /* IDE Primary Channel/Slave Drive Data Active Time Control */ - case 0x44: /* IDE Secondary Channel/Master Drive Data Recovery Time Control */ - case 0x45: /* IDE Secondary Channel/Master Drive Data Active Time Control */ - case 0x46: /* IDE Secondary Channel/Slave Drive Data Recovery Time Control */ - case 0x47: /* IDE Secondary Channel/Slave Drive Data Active Time Control */ - case 0x48: /* IDE Command Recovery Time Control */ - case 0x49: /* IDE Command Active Time Control */ - dev->pci_conf_sb[1][addr] = val; - break; + case 0x41: /* INTA# Remapping Control Register */ + case 0x42: /* INTB# Remapping Control Register */ + case 0x43: /* INTC# Remapping Control Register */ + case 0x44: /* INTD# Remapping Control Register */ + dev->pci_conf_sb[0][addr] = val & 0x8f; + pci_set_irq_routing(addr & 0x07, (val & 0x80) ? PCI_IRQ_DISABLED : (val & 0x0f)); + break; - case 0x4a: /* IDE General Control Register 0 */ - dev->pci_conf_sb[1][addr] = val & 0x9f; - sis_5513_ide_handler(dev); - break; + case 0x48: /* ISA Master/DMA Memory Cycle Control Register 1 */ + case 0x49: /* ISA Master/DMA Memory Cycle Control Register 2 */ + case 0x4a: /* ISA Master/DMA Memory Cycle Control Register 3 */ + case 0x4b: /* ISA Master/DMA Memory Cycle Control Register 4 */ + dev->pci_conf_sb[0][addr] = val; + break; - case 0x4b: /* IDE General Control Register 1 */ - dev->pci_conf_sb[1][addr] = val & 0xef; - break; + case 0x60: /* MIRQ0 Remapping Control Register */ + case 0x61: /* MIRQ1 Remapping Control Register */ + sis_5511_log("Set MIRQ routing: MIRQ%i -> %02X\n", addr & 0x01, val); + dev->pci_conf_sb[0][addr] = val & 0xcf; + if (val & 0x80) + pci_set_mirq_routing(PCI_MIRQ0 + (addr & 0x01), PCI_IRQ_DISABLED); + else + pci_set_mirq_routing(PCI_MIRQ0 + (addr & 0x01), val & 0xf); + break; - case 0x4c: /* Prefetch Count of Primary Channel (Low Byte) */ - case 0x4d: /* Prefetch Count of Primary Channel (High Byte) */ - case 0x4e: /* Prefetch Count of Secondary Channel (Low Byte) */ - case 0x4f: /* Prefetch Count of Secondary Channel (High Byte) */ - dev->pci_conf_sb[1][addr] = val; - break; - } + case 0x62: /* On-board Device DMA Control Register */ + dev->pci_conf_sb[0][addr] = val; + break; + + case 0x63: /* IDEIRQ Remapping Control Register */ + sis_5511_log("Set MIRQ routing: IDEIRQ -> %02X\n", val); + dev->pci_conf_sb[0][addr] = val & 0x8f; + if (val & 0x80) + pci_set_mirq_routing(PCI_MIRQ2, PCI_IRQ_DISABLED); + else + pci_set_mirq_routing(PCI_MIRQ2, val & 0xf); + break; + + case 0x64: /* GPIO0 Control Register */ + dev->pci_conf_sb[0][addr] = val & 0xef; + break; + + case 0x65: + dev->pci_conf_sb[0][addr] = val & 0x80; + break; + + case 0x66: /* GPIO0 Output Mode Control Register */ + case 0x67: /* GPIO0 Output Mode Control Register */ + dev->pci_conf_sb[0][addr] = val; + break; + + case 0x6a: /* GPIO Status Register */ + dev->pci_conf_sb[0][addr] |= (val & 0x10); + dev->pci_conf_sb[0][addr] &= ~(val & 0x01); + break; + + default: + break; + } +} + +static void +sis_5513_ide_irq_handler(sis_5511_t *dev) +{ + if (dev->pci_conf_sb[1][0x09] & 0x01) { + /* Primary IDE is native. */ + sis_5511_log("Primary IDE IRQ mode: Native, Native\n"); + sff_set_irq_mode(dev->bm[0], IRQ_MODE_SIS_551X); + } else { + /* Primary IDE is legacy. */ + sis_5511_log("Primary IDE IRQ mode: IRQ14, IRQ15\n"); + sff_set_irq_mode(dev->bm[0], IRQ_MODE_LEGACY); + } + + if (dev->pci_conf_sb[1][0x09] & 0x04) { + /* Secondary IDE is native. */ + sis_5511_log("Secondary IDE IRQ mode: Native, Native\n"); + sff_set_irq_mode(dev->bm[1], IRQ_MODE_SIS_551X); + } else { + /* Secondary IDE is legacy. */ + sis_5511_log("Secondary IDE IRQ mode: IRQ14, IRQ15\n"); + sff_set_irq_mode(dev->bm[1], IRQ_MODE_LEGACY); + } +} + +static void +sis_5513_ide_handler(sis_5511_t *dev) +{ + uint8_t ide_io_on = dev->pci_conf_sb[1][0x04] & 0x01; + + uint16_t native_base_pri_addr = (dev->pci_conf_sb[1][0x11] | dev->pci_conf_sb[1][0x10] << 8) & 0xfffe; + uint16_t native_side_pri_addr = (dev->pci_conf_sb[1][0x15] | dev->pci_conf_sb[1][0x14] << 8) & 0xfffe; + uint16_t native_base_sec_addr = (dev->pci_conf_sb[1][0x19] | dev->pci_conf_sb[1][0x18] << 8) & 0xfffe; + uint16_t native_side_sec_addr = (dev->pci_conf_sb[1][0x1c] | dev->pci_conf_sb[1][0x1b] << 8) & 0xfffe; + + uint16_t current_pri_base; + uint16_t current_pri_side; + uint16_t current_sec_base; + uint16_t current_sec_side; + + /* Primary Channel Programming */ + current_pri_base = (!(dev->pci_conf_sb[1][0x09] & 1)) ? 0x01f0 : native_base_pri_addr; + current_pri_side = (!(dev->pci_conf_sb[1][0x09] & 1)) ? 0x03f6 : native_side_pri_addr; + + /* Secondary Channel Programming */ + current_sec_base = (!(dev->pci_conf_sb[1][0x09] & 4)) ? 0x0170 : native_base_sec_addr; + current_sec_side = (!(dev->pci_conf_sb[1][0x09] & 4)) ? 0x0376 : native_side_sec_addr; + + sis_5511_log("sis_5513_ide_handler(): Disabling primary IDE...\n"); + ide_pri_disable(); + sis_5511_log("sis_5513_ide_handler(): Disabling secondary IDE...\n"); + ide_sec_disable(); + + if (ide_io_on) { + /* Primary Channel Setup */ + if (dev->pci_conf_sb[1][0x4a] & 0x02) { + sis_5511_log("sis_5513_ide_handler(): Primary IDE base now %04X...\n", current_pri_base); + ide_set_base(0, current_pri_base); + sis_5511_log("sis_5513_ide_handler(): Primary IDE side now %04X...\n", current_pri_side); + ide_set_side(0, current_pri_side); + + sis_5511_log("sis_5513_ide_handler(): Enabling primary IDE...\n"); + ide_pri_enable(); + + sis_5511_log("SiS 5513 PRI: BASE %04x SIDE %04x\n", current_pri_base, current_pri_side); + } + + /* Secondary Channel Setup */ + if (dev->pci_conf_sb[1][0x4a] & 0x04) { + sis_5511_log("sis_5513_ide_handler(): Secondary IDE base now %04X...\n", current_sec_base); + ide_set_base(1, current_sec_base); + sis_5511_log("sis_5513_ide_handler(): Secondary IDE side now %04X...\n", current_sec_side); + ide_set_side(1, current_sec_side); + + sis_5511_log("sis_5513_ide_handler(): Enabling secondary IDE...\n"); + ide_sec_enable(); + + sis_5511_log("SiS 5513: BASE %04x SIDE %04x\n", current_sec_base, current_sec_side); + } + } + + sff_bus_master_handler(dev->bm[0], ide_io_on, + ((dev->pci_conf_sb[1][0x20] & 0xf0) | (dev->pci_conf_sb[1][0x21] << 8)) + 0); + sff_bus_master_handler(dev->bm[1], ide_io_on, + ((dev->pci_conf_sb[1][0x20] & 0xf0) | (dev->pci_conf_sb[1][0x21] << 8)) + 8); +} + +void +sis_5513_ide_write(int addr, uint8_t val, sis_5511_t *dev) +{ + sis_5511_log("SiS 5513 IDE: [W] dev->pci_conf_sb[1][%02X] = %02X\n", addr, val); + + switch (addr) { + case 0x04: /* Command low byte */ + dev->pci_conf_sb[1][addr] = val & 0x05; + sis_5513_ide_handler(dev); + break; + case 0x06: /* Status low byte */ + dev->pci_conf_sb[1][addr] = val & 0x20; + break; + case 0x07: /* Status high byte */ + dev->pci_conf_sb[1][addr] = (dev->pci_conf_sb[1][addr] & 0x06) & ~(val & 0x38); + break; + case 0x09: /* Programming Interface Byte */ + dev->pci_conf_sb[1][addr] = (dev->pci_conf_sb[1][addr] & 0x8a) | (val & 0x05); + sis_5513_ide_irq_handler(dev); + sis_5513_ide_handler(dev); + break; + case 0x0d: /* Latency Timer */ + dev->pci_conf_sb[1][addr] = val; + break; + + /* Primary Base Address */ + case 0x10: + case 0x11: + case 0x14: + case 0x15: + fallthrough; + + /* Secondary Base Address */ + case 0x18: + case 0x19: + case 0x1c: + case 0x1d: + fallthrough; + + /* Bus Mastering Base Address */ + case 0x20: + case 0x21: + if (addr == 0x20) + dev->pci_conf_sb[1][addr] = (val & 0xe0) | 0x01; + else + dev->pci_conf_sb[1][addr] = val; + sis_5513_ide_handler(dev); + break; + + case 0x30: /* Expansion ROM Base Address */ + case 0x31: /* Expansion ROM Base Address */ + case 0x32: /* Expansion ROM Base Address */ + case 0x33: /* Expansion ROM Base Address */ + dev->pci_conf_sb[1][addr] = val; + break; + + case 0x40: /* IDE Primary Channel/Master Drive Data Recovery Time Control */ + case 0x41: /* IDE Primary Channel/Master Drive DataActive Time Control */ + case 0x42: /* IDE Primary Channel/Slave Drive Data Recovery Time Control */ + case 0x43: /* IDE Primary Channel/Slave Drive Data Active Time Control */ + case 0x44: /* IDE Secondary Channel/Master Drive Data Recovery Time Control */ + case 0x45: /* IDE Secondary Channel/Master Drive Data Active Time Control */ + case 0x46: /* IDE Secondary Channel/Slave Drive Data Recovery Time Control */ + case 0x47: /* IDE Secondary Channel/Slave Drive Data Active Time Control */ + case 0x48: /* IDE Command Recovery Time Control */ + case 0x49: /* IDE Command Active Time Control */ + dev->pci_conf_sb[1][addr] = val; + break; + + case 0x4a: /* IDE General Control Register 0 */ + dev->pci_conf_sb[1][addr] = val & 0x9e; + sis_5513_ide_handler(dev); + break; + + case 0x4b: /* IDE General Control Register 1 */ + dev->pci_conf_sb[1][addr] = val & 0xef; + break; + + case 0x4c: /* Prefetch Count of Primary Channel (Low Byte) */ + case 0x4d: /* Prefetch Count of Primary Channel (High Byte) */ + case 0x4e: /* Prefetch Count of Secondary Channel (Low Byte) */ + case 0x4f: /* Prefetch Count of Secondary Channel (High Byte) */ + dev->pci_conf_sb[1][addr] = val; + break; + + default: + break; + } } static void sis_5513_write(int func, int addr, uint8_t val, void *priv) { - sis_5511_t *dev = (sis_5511_t *)priv; - switch (func) - { - case 0: - sis_5513_pci_to_isa_write(addr, val, dev); - break; - case 1: - sis_5513_ide_write(addr, val, dev); - break; - } - sis_5511_log("SiS 5513: dev->pci_conf[%02x][%02x] = %02x POST: %02x\n", func, addr, dev->pci_conf_sb[func][addr], inb(0x80)); + sis_5511_t *dev = (sis_5511_t *) priv; + + switch (func) { + default: + break; + case 0: + sis_5513_pci_to_isa_write(addr, val, dev); + break; + case 1: + sis_5513_ide_write(addr, val, dev); + break; + } } static uint8_t sis_5513_read(int func, int addr, void *priv) { - sis_5511_t *dev = (sis_5511_t *)priv; + const sis_5511_t *dev = (sis_5511_t *) priv; + uint8_t ret = 0xff; - sis_5511_log("SiS 5513: dev->pci_conf[%02x][%02x] = %02x POST %02x\n", func, addr, dev->pci_conf_sb[func][addr], inb(0x80)); - if ((func >= 0) && (func <= 1)) - return dev->pci_conf_sb[func][addr]; - else - return 0xff; + if (func == 0x00) { + switch (addr) { + default: + ret = dev->pci_conf_sb[func][addr]; + break; + case 0x4c ... 0x4f: + ret = pic_read_icw(0, addr & 0x03); + break; + case 0x50 ... 0x53: + ret = pic_read_icw(1, addr & 0x03); + break; + case 0x54 ... 0x55: + ret = pic_read_ocw(0, addr & 0x01); + break; + case 0x56 ... 0x57: + ret = pic_read_ocw(1, addr & 0x01); + break; + case 0x58 ... 0x5f: + ret = dev->pit_read_reg(dev->pit, addr & 0x07); + break; + } + + sis_5511_log("SiS 5513 P2I: [R] dev->pci_conf_sb[0][%02X] = %02X\n", addr, ret); + } else if (func == 0x01) { + ret = dev->pci_conf_sb[func][addr]; + + sis_5511_log("SiS 5513 IDE: [R] dev->pci_conf_sb[1][%02X] = %02X\n", addr, ret); + } + + return ret; } static void sis_5513_isa_write(uint16_t addr, uint8_t val, void *priv) { - sis_5511_t *dev = (sis_5511_t *)priv; + sis_5511_t *dev = (sis_5511_t *) priv; - switch (addr) - { - case 0x22: - dev->index = val - 0x50; - break; - case 0x23: - switch (dev->index) - { - case 0x00: - dev->regs[dev->index] = val & 0xed; - switch (val >> 6) - { - case 0: - cpu_set_isa_speed(7159091); - break; - case 1: - cpu_set_isa_pci_div(4); - break; - case 2: - cpu_set_isa_pci_div(3); - break; - } - break; - case 0x01: - dev->regs[dev->index] = val & 0xf4; - break; - case 0x03: - dev->regs[dev->index] = val & 3; - break; - case 0x04: /* BIOS Register */ - dev->regs[dev->index] = val; - break; - case 0x05: - dev->regs[dev->index] = inb(0x70); - break; - case 0x08: - case 0x09: - case 0x0a: - case 0x0b: - dev->regs[dev->index] = val; - break; - } - sis_5511_log("SiS 5513-ISA: dev->regs[%02x] = %02x POST: %02x\n", dev->index + 0x50, dev->regs[dev->index], inb(0x80)); - break; - } + switch (addr) { + case 0x22: + dev->index = val - 0x50; + break; + case 0x23: + sis_5511_log("SiS 5513 ISA: [W] dev->regs[%02X] = %02X\n", dev->index + 0x50, val); + + switch (dev->index) { + case 0x00: + dev->regs[dev->index] = val & 0xed; + switch (val >> 6) { + case 0: + cpu_set_isa_speed(7159091); + break; + case 1: + cpu_set_isa_pci_div(4); + break; + case 2: + cpu_set_isa_pci_div(3); + break; + + default: + break; + } + nvr_bank_set(0, !!(val & 0x08), dev->nvr); + break; + case 0x01: + dev->regs[dev->index] = val & 0xf4; + break; + case 0x03: + dev->regs[dev->index] = val & 3; + break; + case 0x04: /* BIOS Register */ + dev->regs[dev->index] = val; + break; + case 0x05: + dev->regs[dev->index] = val; + outb(0x70, val); + break; + case 0x08: + case 0x09: + case 0x0a: + case 0x0b: + dev->regs[dev->index] = val; + break; + + default: + break; + } + break; + + default: + break; + } } static uint8_t sis_5513_isa_read(uint16_t addr, void *priv) { - sis_5511_t *dev = (sis_5511_t *)priv; + const sis_5511_t *dev = (sis_5511_t *) priv; + uint8_t ret = 0xff; - if (addr == 0x23) - { - sis_5511_log("SiS 5513-ISA: dev->regs[%02x] (%02x) POST: %02x\n", dev->index + 0x50, dev->regs[dev->index], inb(0x80)); - return dev->regs[dev->index]; - } - else - return 0xff; + if (addr == 0x23) { + if (dev->index == 0x05) + ret = inb(0x70); + else + ret = dev->regs[dev->index]; + + sis_5511_log("SiS 5513 ISA: [R] dev->regs[%02X] = %02X\n", dev->index + 0x50, ret); + } + + return ret; } - static void sis_5511_reset(void *priv) { - sis_5511_t *dev = (sis_5511_t *)priv; + sis_5511_t *dev = (sis_5511_t *) priv; /* SiS 5511 */ dev->pci_conf[0x00] = 0x39; @@ -628,12 +758,12 @@ sis_5511_reset(void *priv) dev->pci_conf[0x03] = 0x55; dev->pci_conf[0x04] = 0x07; dev->pci_conf[0x05] = dev->pci_conf[0x06] = 0x00; - dev->pci_conf[0x07] = 0x02; - dev->pci_conf[0x08] = 0x00; + dev->pci_conf[0x07] = 0x02; + dev->pci_conf[0x08] = 0x00; dev->pci_conf[0x09] = dev->pci_conf[0x0a] = 0x00; - dev->pci_conf[0x0b] = 0x06; + dev->pci_conf[0x0b] = 0x06; dev->pci_conf[0x50] = dev->pci_conf[0x51] = 0x00; - dev->pci_conf[0x52] = 0x20; + dev->pci_conf[0x52] = 0x20; dev->pci_conf[0x53] = dev->pci_conf[0x54] = 0x00; dev->pci_conf[0x55] = dev->pci_conf[0x56] = 0x00; dev->pci_conf[0x57] = dev->pci_conf[0x58] = 0x00; @@ -642,112 +772,191 @@ sis_5511_reset(void *priv) dev->pci_conf[0x5d] = dev->pci_conf[0x5e] = 0x00; dev->pci_conf[0x5f] = dev->pci_conf[0x60] = 0x00; dev->pci_conf[0x61] = dev->pci_conf[0x62] = 0xff; - dev->pci_conf[0x63] = 0xff; + dev->pci_conf[0x63] = 0xff; dev->pci_conf[0x64] = dev->pci_conf[0x65] = 0x00; - dev->pci_conf[0x66] = 0x00; - dev->pci_conf[0x67] = 0xff; + dev->pci_conf[0x66] = 0x00; + dev->pci_conf[0x67] = 0xff; dev->pci_conf[0x68] = dev->pci_conf[0x69] = 0x00; - dev->pci_conf[0x6a] = dev->pci_conf[0x6b] = 0x00; - dev->pci_conf[0x6c] = dev->pci_conf[0x6d] = 0x00; - dev->pci_conf[0x6e] = dev->pci_conf[0x6f] = 0x00; + dev->pci_conf[0x6a] = 0x00; + dev->pci_conf[0x6b] = dev->pci_conf[0x6c] = 0xff; + dev->pci_conf[0x6d] = dev->pci_conf[0x6e] = 0xff; + dev->pci_conf[0x6f] = 0x00; + dev->pci_conf[0x70] = dev->pci_conf[0x72] = 0x04; + dev->pci_conf[0x74] = dev->pci_conf[0x76] = 0x04; + dev->pci_conf[0x78] = dev->pci_conf[0x7a] = 0x04; + dev->pci_conf[0x7c] = dev->pci_conf[0x7e] = 0x04; + dev->pci_conf[0x73] = dev->pci_conf[0x77] = 0x80; + dev->pci_conf[0x7b] = dev->pci_conf[0x7f] = 0x80; + dev->pci_conf[0x80] = dev->pci_conf[0x81] = 0x00; + dev->pci_conf[0x82] = dev->pci_conf[0x83] = 0x00; + dev->pci_conf[0x84] = dev->pci_conf[0x85] = 0x00; + dev->pci_conf[0x86] = 0x00; cpu_cache_ext_enabled = 0; cpu_update_waitstates(); - dev->pci_conf[0x6b] = 0xff; - dev->pci_conf[0x6c] = 0xff; - dev->pci_conf[0x70] = 4; - dev->pci_conf[0x72] = 4; - dev->pci_conf[0x73] = 0x80; - dev->pci_conf[0x74] = 4; - dev->pci_conf[0x76] = 4; - dev->pci_conf[0x77] = 0x80; - dev->pci_conf[0x78] = 4; - dev->pci_conf[0x7a] = 4; - dev->pci_conf[0x7b] = 0x80; - dev->pci_conf[0x7c] = 4; - dev->pci_conf[0x7e] = 4; - dev->pci_conf[0x7f] = 0x80; - dev->pci_conf[0x80] = 0x00; - dev->pci_conf[0x81] = 0x00; - dev->pci_conf[0x82] = 0x00; - dev->pci_conf[0x83] = 0x00; - dev->pci_conf[0x84] = 0x00; - dev->pci_conf[0x85] = 0x00; - dev->pci_conf[0x86] = 0x00; - sis_5511_smram_recalc(dev); - sis_5511_shadow_recalc(dev); + sis_5511_smram_recalc(dev); + sis_5511_shadow_recalc(dev); - /* SiS 5513 */ - dev->pci_conf_sb[0][0x00] = 0x39; - dev->pci_conf_sb[0][0x01] = 0x10; - dev->pci_conf_sb[0][0x02] = 8; - dev->pci_conf_sb[0][0x04] = 7; - dev->pci_conf_sb[0][0x0a] = 1; - dev->pci_conf_sb[0][0x0b] = 6; - dev->pci_conf_sb[0][0x0e] = 0x80; + flushmmucache(); - /* SiS 5513 IDE Controller */ - dev->pci_conf_sb[1][0x00] = 0x39; - dev->pci_conf_sb[1][0x01] = 0x10; - dev->pci_conf_sb[1][0x02] = 0x13; - dev->pci_conf_sb[1][0x03] = 0x55; - dev->pci_conf_sb[1][0x0a] = 1; - dev->pci_conf_sb[1][0x0b] = 1; - dev->pci_conf_sb[1][0x0e] = 0x80; - sff_set_slot(dev->ide_drive[0], dev->sb_pci_slot); - sff_set_slot(dev->ide_drive[1], dev->sb_pci_slot); - sff_bus_master_reset(dev->ide_drive[0], BUS_MASTER_BASE); - sff_bus_master_reset(dev->ide_drive[1], BUS_MASTER_BASE + 8); + memset(dev->slic_regs, 0x00, 4096 * sizeof(uint8_t)); + dev->slic_regs[0x18] = 0x0f; + + mem_mapping_set_addr(&dev->slic_mapping, 0xffc00000, 0x00001000); + + /* SiS 5513 */ + dev->pci_conf_sb[0][0x00] = 0x39; + dev->pci_conf_sb[0][0x01] = 0x10; + dev->pci_conf_sb[0][0x02] = 0x08; + dev->pci_conf_sb[0][0x03] = 0x00; + dev->pci_conf_sb[0][0x04] = 0x07; + dev->pci_conf_sb[0][0x05] = dev->pci_conf_sb[0][0x06] = 0x00; + dev->pci_conf_sb[0][0x07] = 0x02; + dev->pci_conf_sb[0][0x08] = dev->pci_conf_sb[0][0x09] = 0x00; + dev->pci_conf_sb[0][0x0a] = 0x01; + dev->pci_conf_sb[0][0x0b] = 0x06; + dev->pci_conf_sb[0][0x0e] = 0x80; + dev->pci_conf_sb[0][0x40] = 0x00; + dev->pci_conf_sb[0][0x41] = dev->pci_conf_sb[0][0x42] = 0x80; + dev->pci_conf_sb[0][0x43] = dev->pci_conf_sb[0][0x44] = 0x80; + dev->pci_conf_sb[0][0x48] = dev->pci_conf_sb[0][0x49] = 0x80; + dev->pci_conf_sb[0][0x4a] = dev->pci_conf_sb[0][0x4b] = 0x80; + dev->pci_conf_sb[0][0x60] = dev->pci_conf_sb[0][0x51] = 0x80; + dev->pci_conf_sb[0][0x62] = 0x00; + dev->pci_conf_sb[0][0x63] = 0x80; + dev->pci_conf_sb[0][0x64] = 0x00; + dev->pci_conf_sb[0][0x65] = 0x80; + dev->pci_conf_sb[0][0x66] = dev->pci_conf_sb[0][0x67] = 0x00; + dev->pci_conf_sb[0][0x68] = dev->pci_conf_sb[0][0x69] = 0x00; + dev->pci_conf_sb[0][0x6a] = 0x04; + + pci_set_irq_routing(PCI_INTA, PCI_IRQ_DISABLED); + pci_set_irq_routing(PCI_INTB, PCI_IRQ_DISABLED); + pci_set_irq_routing(PCI_INTC, PCI_IRQ_DISABLED); + pci_set_irq_routing(PCI_INTD, PCI_IRQ_DISABLED); + + pci_set_mirq_routing(PCI_MIRQ0, PCI_IRQ_DISABLED); + pci_set_mirq_routing(PCI_MIRQ1, PCI_IRQ_DISABLED); + pci_set_mirq_routing(PCI_MIRQ2, PCI_IRQ_DISABLED); + + dev->regs[0x00] = dev->regs[0x01] = 0x00; + dev->regs[0x03] = dev->regs[0x04] = 0x00; + dev->regs[0x05] = 0x00; + dev->regs[0x08] = dev->regs[0x09] = 0x00; + dev->regs[0x0a] = dev->regs[0x0b] = 0x00; + + cpu_set_isa_speed(7159091); + nvr_bank_set(0, 0, dev->nvr); + + /* SiS 5513 IDE Controller */ + dev->pci_conf_sb[1][0x00] = 0x39; + dev->pci_conf_sb[1][0x01] = 0x10; + dev->pci_conf_sb[1][0x02] = 0x13; + dev->pci_conf_sb[1][0x03] = 0x55; + dev->pci_conf_sb[1][0x04] = dev->pci_conf_sb[1][0x05] = 0x00; + dev->pci_conf_sb[1][0x06] = dev->pci_conf_sb[1][0x07] = 0x00; + dev->pci_conf_sb[1][0x08] = 0x00; + dev->pci_conf_sb[1][0x09] = 0x8a; + dev->pci_conf_sb[1][0x0a] = dev->pci_conf_sb[1][0x0b] = 0x01; + dev->pci_conf_sb[1][0x0c] = dev->pci_conf_sb[1][0x0d] = 0x00; + dev->pci_conf_sb[1][0x0e] = 0x80; + dev->pci_conf_sb[1][0x0f] = 0x00; + dev->pci_conf_sb[1][0x10] = 0xf1; + dev->pci_conf_sb[1][0x11] = 0x01; + dev->pci_conf_sb[1][0x14] = 0xf5; + dev->pci_conf_sb[1][0x15] = 0x03; + dev->pci_conf_sb[1][0x18] = 0x71; + dev->pci_conf_sb[1][0x19] = 0x01; + dev->pci_conf_sb[1][0x1c] = 0x75; + dev->pci_conf_sb[1][0x1d] = 0x03; + dev->pci_conf_sb[1][0x20] = 0x01; + dev->pci_conf_sb[1][0x21] = 0xf0; + dev->pci_conf_sb[1][0x22] = dev->pci_conf_sb[1][0x23] = 0x00; + + sis_5513_ide_irq_handler(dev); + sis_5513_ide_handler(dev); + + sff_bus_master_reset(dev->bm[0]); + sff_bus_master_reset(dev->bm[1]); } static void sis_5511_close(void *priv) { - sis_5511_t *dev = (sis_5511_t *)priv; + sis_5511_t *dev = (sis_5511_t *) priv; - smram_del(dev->smram); - free(dev); + smram_del(dev->smram); + free(dev); } static void * -sis_5511_init(const device_t *info) +sis_5511_init(UNUSED(const device_t *info)) { - sis_5511_t *dev = (sis_5511_t *)malloc(sizeof(sis_5511_t)); - memset(dev, 0, sizeof(sis_5511_t)); + sis_5511_t *dev = (sis_5511_t *) calloc(1, sizeof(sis_5511_t)); + uint8_t pit_is_fast = (((pit_mode == -1) && is486) || (pit_mode == 1)); - dev->nb_pci_slot = pci_add_card(PCI_ADD_NORTHBRIDGE, sis_5511_read, sis_5511_write, dev); /* Device 0: SiS 5511 */ - dev->sb_pci_slot = pci_add_card(PCI_ADD_SOUTHBRIDGE, sis_5513_read, sis_5513_write, dev); /* Device 1: SiS 5513 */ - io_sethandler(0x0022, 0x0002, sis_5513_isa_read, NULL, NULL, sis_5513_isa_write, NULL, NULL, dev); /* Ports 22h-23h: SiS 5513 ISA */ + memset(dev, 0, sizeof(sis_5511_t)); - /* MIRQ */ - pci_enable_mirq(0); - pci_enable_mirq(1); + /* Device 0: SiS 5511 */ + pci_add_card(PCI_ADD_NORTHBRIDGE, sis_5511_read, sis_5511_write, dev, &dev->nb_slot); + /* Device 1: SiS 5513 */ + pci_add_card(PCI_ADD_SOUTHBRIDGE, sis_5513_read, sis_5513_write, dev, &dev->sb_slot); - /* Port 92h */ - dev->port_92 = device_add(&port_92_device); + /* SLiC Memory Mapped Registers */ + mem_mapping_add(&dev->slic_mapping, + 0xffc00000, 0x00001000, + sis_5511_slic_read, + NULL, + NULL, + sis_5511_slic_write, + NULL, + NULL, + NULL, MEM_MAPPING_EXTERNAL, + dev); - /* SFF IDE */ - dev->ide_drive[0] = device_add_inst(&sff8038i_device, 1); - dev->ide_drive[1] = device_add_inst(&sff8038i_device, 2); + /* Ports 22h-23h: SiS 5513 ISA */ + io_sethandler(0x0022, 0x0002, sis_5513_isa_read, NULL, NULL, sis_5513_isa_write, NULL, NULL, dev); - /* SMRAM */ - dev->smram = smram_add(); + /* MIRQ */ + pci_enable_mirq(0); + pci_enable_mirq(1); - sis_5511_reset(dev); + /* IDEIRQ */ + pci_enable_mirq(2); - return dev; + /* Port 92h */ + dev->port_92 = device_add(&port_92_device); + + /* SFF IDE */ + dev->bm[0] = device_add_inst(&sff8038i_device, 1); + dev->bm[1] = device_add_inst(&sff8038i_device, 2); + + /* SMRAM */ + dev->smram = smram_add(); + + /* PIT */ + dev->pit = device_find_first_priv(DEVICE_PIT); + dev->pit_read_reg = pit_is_fast ? pitf_read_reg : pit_read_reg; + + /* NVR */ + dev->nvr = device_add(&at_mb_nvr_device); + + sis_5511_reset(dev); + + return dev; } const device_t sis_5511_device = { - "SiS 5511", - "sis_5511", - DEVICE_PCI, - 0, - sis_5511_init, - sis_5511_close, - sis_5511_reset, - {NULL}, - NULL, - NULL, - NULL}; + .name = "SiS 5511", + .internal_name = "sis_5511", + .flags = DEVICE_PCI, + .local = 0, + .init = sis_5511_init, + .close = sis_5511_close, + .reset = sis_5511_reset, + { .available = NULL }, + .speed_changed = NULL, + .force_redraw = NULL, + .config = NULL +}; diff --git a/src/chipset/sis_5571.c b/src/chipset/sis_5571.c index 4cc99319f..f130ecd8a 100644 --- a/src/chipset/sis_5571.c +++ b/src/chipset/sis_5571.c @@ -1,18 +1,19 @@ /* - * 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. + * 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. + * This file is part of the 86Box distribution. * - * Implementation of the SiS 5571 Chipset. + * Implementation of the SiS 5571 Chipset. * - * Authors: Tiseno100, * - * Copyright 2021 Tiseno100. + * + * Authors: Tiseno100, + * + * Copyright 2021 Tiseno100. */ - #include #include #include @@ -28,6 +29,8 @@ #include <86box/dma.h> #include <86box/mem.h> #include <86box/pci.h> +#include <86box/pic.h> +#include <86box/plat_unused.h> #include <86box/port_92.h> #include <86box/hdc_ide.h> #include <86box/hdc_ide_sff8038i.h> @@ -37,719 +40,733 @@ #include <86box/chipset.h> /* Shadow RAM */ -#define LSB_READ ((dev->pci_conf[0x70 + (cur_reg & 0x07)] & 0x08) ? MEM_READ_INTERNAL : MEM_READ_EXTANY) -#define LSB_WRITE ((dev->pci_conf[0x70 + (cur_reg & 0x07)] & 0x02) ? MEM_WRITE_INTERNAL : MEM_WRITE_EXTANY) -#define MSB_READ ((dev->pci_conf[0x70 + (cur_reg & 0x07)] & 0x80) ? MEM_READ_INTERNAL : MEM_READ_EXTANY) -#define MSB_WRITE ((dev->pci_conf[0x70 + (cur_reg & 0x07)] & 0x20) ? MEM_WRITE_INTERNAL : MEM_WRITE_EXTANY) -#define SYSTEM_READ ((dev->pci_conf[0x76] & 0x80) ? MEM_READ_INTERNAL : MEM_READ_EXTANY) +#define LSB_READ ((dev->pci_conf[0x70 + (cur_reg & 0x07)] & 0x08) ? MEM_READ_INTERNAL : MEM_READ_EXTANY) +#define LSB_WRITE ((dev->pci_conf[0x70 + (cur_reg & 0x07)] & 0x02) ? MEM_WRITE_INTERNAL : MEM_WRITE_EXTANY) +#define MSB_READ ((dev->pci_conf[0x70 + (cur_reg & 0x07)] & 0x80) ? MEM_READ_INTERNAL : MEM_READ_EXTANY) +#define MSB_WRITE ((dev->pci_conf[0x70 + (cur_reg & 0x07)] & 0x20) ? MEM_WRITE_INTERNAL : MEM_WRITE_EXTANY) +#define SYSTEM_READ ((dev->pci_conf[0x76] & 0x80) ? MEM_READ_INTERNAL : MEM_READ_EXTANY) #define SYSTEM_WRITE ((dev->pci_conf[0x76] & 0x20) ? MEM_WRITE_INTERNAL : MEM_WRITE_EXTANY) /* IDE Flags (1 Native / 0 Compatibility)*/ -#define PRIMARY_COMP_NAT_SWITCH (dev->pci_conf_sb[1][9] & 1) +#define PRIMARY_COMP_NAT_SWITCH (dev->pci_conf_sb[1][9] & 1) #define SECONDARY_COMP_NAT_SWITCH (dev->pci_conf_sb[1][9] & 4) -#define PRIMARY_NATIVE_BASE (dev->pci_conf_sb[1][0x11] << 8) | (dev->pci_conf_sb[1][0x10] & 0xf8) -#define PRIMARY_NATIVE_SIDE (((dev->pci_conf_sb[1][0x15] << 8) | (dev->pci_conf_sb[1][0x14] & 0xfc)) + 2) -#define SECONDARY_NATIVE_BASE (dev->pci_conf_sb[1][0x19] << 8) | (dev->pci_conf_sb[1][0x18] & 0xf8) -#define SECONDARY_NATIVE_SIDE (((dev->pci_conf_sb[1][0x1d] << 8) | (dev->pci_conf_sb[1][0x1c] & 0xfc)) + 2) -#define BUS_MASTER_BASE ((dev->pci_conf_sb[1][0x20] & 0xf0) | (dev->pci_conf_sb[1][0x21] << 8)) +#define PRIMARY_NATIVE_BASE (dev->pci_conf_sb[1][0x11] << 8) | (dev->pci_conf_sb[1][0x10] & 0xf8) +#define PRIMARY_NATIVE_SIDE (((dev->pci_conf_sb[1][0x15] << 8) | (dev->pci_conf_sb[1][0x14] & 0xfc)) + 2) +#define SECONDARY_NATIVE_BASE (dev->pci_conf_sb[1][0x19] << 8) | (dev->pci_conf_sb[1][0x18] & 0xf8) +#define SECONDARY_NATIVE_SIDE (((dev->pci_conf_sb[1][0x1d] << 8) | (dev->pci_conf_sb[1][0x1c] & 0xfc)) + 2) +#define BUS_MASTER_BASE ((dev->pci_conf_sb[1][0x20] & 0xf0) | (dev->pci_conf_sb[1][0x21] << 8)) #ifdef ENABLE_SIS_5571_LOG int sis_5571_do_log = ENABLE_SIS_5571_LOG; + static void sis_5571_log(const char *fmt, ...) { - va_list ap; + va_list ap; - if (sis_5571_do_log) - { - va_start(ap, fmt); - pclog_ex(fmt, ap); - va_end(ap); - } + if (sis_5571_do_log) { + va_start(ap, fmt); + pclog_ex(fmt, ap); + va_end(ap); + } } #else -#define sis_5571_log(fmt, ...) +# define sis_5571_log(fmt, ...) #endif -typedef struct sis_5571_t -{ - uint8_t pci_conf[256], pci_conf_sb[3][256]; +typedef struct sis_5571_t { + uint8_t nb_slot; + uint8_t sb_slot; + uint8_t pad; + uint8_t usb_irq_state; - int nb_pci_slot, sb_pci_slot; - - port_92_t *port_92; - sff8038i_t *ide_drive[2]; - smram_t *smram; - usb_t *usb; + uint8_t pci_conf[256]; + uint8_t pci_conf_sb[3][256]; + port_92_t *port_92; + sff8038i_t *ide_drive[2]; + smram_t *smram; + usb_t *usb; } sis_5571_t; static void sis_5571_shadow_recalc(int cur_reg, sis_5571_t *dev) { - if (cur_reg != 0x76) - { - mem_set_mem_state_both(0xc0000 + (0x8000 * (cur_reg & 0x07)), 0x4000, LSB_READ | LSB_WRITE); - mem_set_mem_state_both(0xc4000 + (0x8000 * (cur_reg & 0x07)), 0x4000, MSB_READ | MSB_WRITE); - } - else - mem_set_mem_state_both(0xf0000, 0x10000, SYSTEM_READ | SYSTEM_WRITE); + if (cur_reg != 0x76) { + mem_set_mem_state_both(0xc0000 + (0x8000 * (cur_reg & 0x07)), 0x4000, LSB_READ | LSB_WRITE); + mem_set_mem_state_both(0xc4000 + (0x8000 * (cur_reg & 0x07)), 0x4000, MSB_READ | MSB_WRITE); + } else + mem_set_mem_state_both(0xf0000, 0x10000, SYSTEM_READ | SYSTEM_WRITE); - flushmmucache_nopc(); + flushmmucache_nopc(); } static void sis_5571_smm_recalc(sis_5571_t *dev) { - smram_disable_all(); + smram_disable_all(); - switch ((dev->pci_conf[0xa3] & 0xc0) >> 6) - { - case 0x00: - smram_enable(dev->smram, 0xe0000, 0xe0000, 0x8000, (dev->pci_conf[0xa3] & 0x10), 1); - break; - case 0x01: - smram_enable(dev->smram, 0xe0000, 0xa0000, 0x8000, (dev->pci_conf[0xa3] & 0x10), 1); - break; - case 0x02: - smram_enable(dev->smram, 0xe0000, 0xb0000, 0x8000, (dev->pci_conf[0xa3] & 0x10), 1); - break; - case 0x03: - smram_enable(dev->smram, 0xa0000, 0xa0000, 0x10000, (dev->pci_conf[0xa3] & 0x10), 1); - break; - } + switch ((dev->pci_conf[0xa3] & 0xc0) >> 6) { + case 0x00: + smram_enable(dev->smram, 0xe0000, 0xe0000, 0x8000, (dev->pci_conf[0xa3] & 0x10), 1); + break; + case 0x01: + smram_enable(dev->smram, 0xe0000, 0xa0000, 0x8000, (dev->pci_conf[0xa3] & 0x10), 1); + break; + case 0x02: + smram_enable(dev->smram, 0xe0000, 0xb0000, 0x8000, (dev->pci_conf[0xa3] & 0x10), 1); + break; + case 0x03: + smram_enable(dev->smram, 0xa0000, 0xa0000, 0x10000, (dev->pci_conf[0xa3] & 0x10), 1); + break; - flushmmucache(); + default: + break; + } + + flushmmucache(); } -void sis_5571_ide_handler(sis_5571_t *dev) +void +sis_5571_ide_handler(sis_5571_t *dev) { - ide_pri_disable(); - ide_sec_disable(); - if (dev->pci_conf_sb[1][4] & 1) - { - if (dev->pci_conf_sb[1][0x4a] & 4) - { - ide_set_base(0, PRIMARY_COMP_NAT_SWITCH ? PRIMARY_NATIVE_BASE : 0x1f0); - ide_set_side(0, PRIMARY_COMP_NAT_SWITCH ? PRIMARY_NATIVE_SIDE : 0x3f6); - ide_pri_enable(); - } - if (dev->pci_conf_sb[1][0x4a] & 2) - { - ide_set_base(1, SECONDARY_COMP_NAT_SWITCH ? SECONDARY_NATIVE_BASE : 0x170); - ide_set_side(1, SECONDARY_COMP_NAT_SWITCH ? SECONDARY_NATIVE_SIDE : 0x376); - ide_sec_enable(); - } - } + ide_pri_disable(); + ide_sec_disable(); + if (dev->pci_conf_sb[1][4] & 1) { + if (dev->pci_conf_sb[1][0x4a] & 4) { + ide_set_base(0, PRIMARY_COMP_NAT_SWITCH ? PRIMARY_NATIVE_BASE : 0x1f0); + ide_set_side(0, PRIMARY_COMP_NAT_SWITCH ? PRIMARY_NATIVE_SIDE : 0x3f6); + ide_pri_enable(); + } + if (dev->pci_conf_sb[1][0x4a] & 2) { + ide_set_base(1, SECONDARY_COMP_NAT_SWITCH ? SECONDARY_NATIVE_BASE : 0x170); + ide_set_side(1, SECONDARY_COMP_NAT_SWITCH ? SECONDARY_NATIVE_SIDE : 0x376); + ide_sec_enable(); + } + } } -void sis_5571_bm_handler(sis_5571_t *dev) +void +sis_5571_bm_handler(sis_5571_t *dev) { - sff_bus_master_handler(dev->ide_drive[0], dev->pci_conf_sb[1][4] & 4, BUS_MASTER_BASE); - sff_bus_master_handler(dev->ide_drive[1], dev->pci_conf_sb[1][4] & 4, BUS_MASTER_BASE + 8); + sff_bus_master_handler(dev->ide_drive[0], dev->pci_conf_sb[1][4] & 4, BUS_MASTER_BASE); + sff_bus_master_handler(dev->ide_drive[1], dev->pci_conf_sb[1][4] & 4, BUS_MASTER_BASE + 8); } static void -memory_pci_bridge_write(int func, int addr, uint8_t val, void *priv) +memory_pci_bridge_write(UNUSED(int func), int addr, uint8_t val, void *priv) { - sis_5571_t *dev = (sis_5571_t *)priv; + sis_5571_t *dev = (sis_5571_t *) priv; - switch (addr) - { - case 0x04: /* Command - low byte */ - case 0x05: /* Command - high byte */ - dev->pci_conf[addr] |= val; - break; + switch (addr) { + case 0x04: /* Command - low byte */ + case 0x05: /* Command - high byte */ + dev->pci_conf[addr] |= val; + break; - case 0x06: /* Status - Low Byte */ - dev->pci_conf[addr] &= val; - break; + case 0x06: /* Status - Low Byte */ + dev->pci_conf[addr] &= val; + break; - case 0x07: /* Status - High Byte */ - dev->pci_conf[addr] &= val & 0xbe; - break; + case 0x07: /* Status - High Byte */ + dev->pci_conf[addr] &= val & 0xbe; + break; - case 0x0d: /* Master latency timer */ - dev->pci_conf[addr] = val; - break; + case 0x0d: /* Master latency timer */ + dev->pci_conf[addr] = val; + break; - case 0x50: /* Host Interface and DRAM arbiter */ - dev->pci_conf[addr] = val & 0xec; - break; + case 0x50: /* Host Interface and DRAM arbiter */ + dev->pci_conf[addr] = val & 0xec; + break; - case 0x51: /* CACHE */ - dev->pci_conf[addr] = val; - cpu_cache_ext_enabled = !!(val & 0x40); - cpu_update_waitstates(); - break; + case 0x51: /* CACHE */ + dev->pci_conf[addr] = val; + cpu_cache_ext_enabled = !!(val & 0x40); + cpu_update_waitstates(); + break; - case 0x52: - dev->pci_conf[addr] = val & 0xd0; - break; + case 0x52: + dev->pci_conf[addr] = val & 0xd0; + break; - case 0x53: /* DRAM */ - dev->pci_conf[addr] = val & 0xfe; - break; + case 0x53: /* DRAM */ + dev->pci_conf[addr] = val & 0xfe; + break; - case 0x54: /* FP/EDO */ - dev->pci_conf[addr] = val; - break; + case 0x54: /* FP/EDO */ + dev->pci_conf[addr] = val; + break; - case 0x55: - dev->pci_conf[addr] = val & 0xe0; - break; + case 0x55: + dev->pci_conf[addr] = val & 0xe0; + break; - case 0x56: /* MDLE delay */ - case 0x57: /* SDRAM */ - dev->pci_conf[addr] = val & 0xf8; - break; + case 0x56: /* MDLE delay */ + case 0x57: /* SDRAM */ + dev->pci_conf[addr] = val & 0xf8; + break; - case 0x59: /* Buffer strength and current rating */ - dev->pci_conf[addr] = val; - break; + case 0x59: /* Buffer strength and current rating */ + dev->pci_conf[addr] = val; + break; - case 0x5a: - dev->pci_conf[addr] = val & 0x03; - break; + case 0x5a: + dev->pci_conf[addr] = val & 0x03; + break; - case 0x60: /* Undocumented */ - case 0x61: /* Undocumented */ - case 0x62: /* Undocumented */ - case 0x63: /* Undocumented */ - case 0x64: /* Undocumented */ - case 0x65: /* Undocumented */ - case 0x66: /* Undocumented */ - case 0x67: /* Undocumented */ - case 0x68: /* Undocumented */ - case 0x69: /* Undocumented */ - case 0x6a: /* Undocumented */ - case 0x6b: /* Undocumented */ - dev->pci_conf[addr] = val; - break; + case 0x60: /* Undocumented */ + case 0x61: /* Undocumented */ + case 0x62: /* Undocumented */ + case 0x63: /* Undocumented */ + case 0x64: /* Undocumented */ + case 0x65: /* Undocumented */ + case 0x66: /* Undocumented */ + case 0x67: /* Undocumented */ + case 0x68: /* Undocumented */ + case 0x69: /* Undocumented */ + case 0x6a: /* Undocumented */ + case 0x6b: /* Undocumented */ + dev->pci_conf[addr] = val; + break; - case 0x70: - case 0x71: - case 0x72: - case 0x73: - case 0x74: - case 0x75: - case 0x76: /* Attribute of shadow RAM for BIOS area */ - dev->pci_conf[addr] = val & ((addr != 0x76) ? 0xee : 0xe8); - sis_5571_shadow_recalc(addr, dev); - sis_5571_smm_recalc(dev); - break; + case 0x70: + case 0x71: + case 0x72: + case 0x73: + case 0x74: + case 0x75: + case 0x76: /* Attribute of shadow RAM for BIOS area */ + dev->pci_conf[addr] = val & ((addr != 0x76) ? 0xee : 0xe8); + sis_5571_shadow_recalc(addr, dev); + sis_5571_smm_recalc(dev); + break; - case 0x77: /* Characteristics of non-cacheable area */ - dev->pci_conf[addr] = val & 0x0f; - break; + case 0x77: /* Characteristics of non-cacheable area */ + dev->pci_conf[addr] = val & 0x0f; + break; - case 0x78: /* Allocation of Non-Cacheable area #1 */ - case 0x79: /* NCA1REG2 */ - case 0x7a: /* Allocation of Non-Cacheable area #2 */ - case 0x7b: /* NCA2REG2 */ - dev->pci_conf[addr] = val; - break; + case 0x78: /* Allocation of Non-Cacheable area #1 */ + case 0x79: /* NCA1REG2 */ + case 0x7a: /* Allocation of Non-Cacheable area #2 */ + case 0x7b: /* NCA2REG2 */ + dev->pci_conf[addr] = val; + break; - case 0x80: /* PCI master characteristics */ - dev->pci_conf[addr] = val & 0xfe; - break; + case 0x80: /* PCI master characteristics */ + dev->pci_conf[addr] = val & 0xfe; + break; - case 0x81: - dev->pci_conf[addr] = val & 0xcc; - break; + case 0x81: + dev->pci_conf[addr] = val & 0xcc; + break; - case 0x82: - dev->pci_conf[addr] = val; - break; + case 0x82: + dev->pci_conf[addr] = val; + break; - case 0x83: /* CPU to PCI characteristics */ - dev->pci_conf[addr] = val; - port_92_set_features(dev->port_92, !!(val & 0x40), !!(val & 0x80)); - break; + case 0x83: /* CPU to PCI characteristics */ + dev->pci_conf[addr] = val; + port_92_set_features(dev->port_92, !!(val & 0x40), !!(val & 0x80)); + break; - case 0x84: - case 0x85: - case 0x86: - dev->pci_conf[addr] = val; - break; + case 0x84: + case 0x85: + case 0x86: + dev->pci_conf[addr] = val; + break; - case 0x87: /* Miscellanea */ - dev->pci_conf[addr] = val & 0xf8; - break; + case 0x87: /* Miscellanea */ + dev->pci_conf[addr] = val & 0xf8; + break; - case 0x90: /* PMU control register */ - case 0x91: /* Address trap for green function */ - case 0x92: - dev->pci_conf[addr] = val; - break; + case 0x90: /* PMU control register */ + case 0x91: /* Address trap for green function */ + case 0x92: + dev->pci_conf[addr] = val; + break; - case 0x93: /* STPCLK# and APM SMI control */ - dev->pci_conf[addr] = val; + case 0x93: /* STPCLK# and APM SMI control */ + dev->pci_conf[addr] = val; - if ((dev->pci_conf[0x9b] & 1) && !!(val & 2)) - { - smi_line = 1; - dev->pci_conf[0x9d] |= 1; - } - break; + if ((dev->pci_conf[0x9b] & 1) && !!(val & 2)) { + smi_raise(); + dev->pci_conf[0x9d] |= 1; + } + break; - case 0x94: /* 6x86 and Green function control */ - dev->pci_conf[addr] = val & 0xf8; - break; + case 0x94: /* 6x86 and Green function control */ + dev->pci_conf[addr] = val & 0xf8; + break; - case 0x95: /* Test mode control */ - case 0x96: /* Time slot and Programmable 10-bit I/O port definition */ - dev->pci_conf[addr] = val & 0xfb; - break; + case 0x95: /* Test mode control */ + case 0x96: /* Time slot and Programmable 10-bit I/O port definition */ + dev->pci_conf[addr] = val & 0xfb; + break; - case 0x97: /* programmable 10-bit I/O port address */ - case 0x98: /* Programmable 16-bit I/O port */ - case 0x99: - case 0x9a: - case 0x9b: - case 0x9c: - dev->pci_conf[addr] = val; - break; + case 0x97: /* programmable 10-bit I/O port address */ + case 0x98: /* Programmable 16-bit I/O port */ + case 0x99: + case 0x9a: + case 0x9b: + case 0x9c: + dev->pci_conf[addr] = val; + break; - case 0x9d: - dev->pci_conf[addr] &= val; - break; + case 0x9d: + dev->pci_conf[addr] &= val; + break; - case 0x9e: /* STPCLK# Assertion Timer */ - case 0x9f: /* STPCLK# De-assertion Timer */ - case 0xa0: - case 0xa1: - case 0xa2: - dev->pci_conf[addr] = val; - break; + case 0x9e: /* STPCLK# Assertion Timer */ + case 0x9f: /* STPCLK# De-assertion Timer */ + case 0xa0: + case 0xa1: + case 0xa2: + dev->pci_conf[addr] = val; + break; - case 0xa3: /* SMRAM access control and Power supply control */ - dev->pci_conf[addr] = val & 0xd0; - sis_5571_smm_recalc(dev); - break; - } - sis_5571_log("SiS5571: dev->pci_conf[%02x] = %02x\n", addr, val); + case 0xa3: /* SMRAM access control and Power supply control */ + dev->pci_conf[addr] = val & 0xd0; + sis_5571_smm_recalc(dev); + break; + + default: + break; + } + sis_5571_log("SiS5571: dev->pci_conf[%02x] = %02x\n", addr, val); } static uint8_t -memory_pci_bridge_read(int func, int addr, void *priv) +memory_pci_bridge_read(UNUSED(int func), int addr, void *priv) { - sis_5571_t *dev = (sis_5571_t *)priv; - sis_5571_log("SiS5571: dev->pci_conf[%02x] (%02x)\n", addr, dev->pci_conf[addr]); - return dev->pci_conf[addr]; + const sis_5571_t *dev = (sis_5571_t *) priv; + + sis_5571_log("SiS5571: dev->pci_conf[%02x] (%02x)\n", addr, dev->pci_conf[addr]); + return dev->pci_conf[addr]; } static void pci_isa_bridge_write(int func, int addr, uint8_t val, void *priv) { - sis_5571_t *dev = (sis_5571_t *)priv; - switch (func) - { - case 0: /* Bridge */ - switch (addr) - { - case 0x04: /* Command */ - dev->pci_conf_sb[0][addr] |= val & 0x0f; - break; + sis_5571_t *dev = (sis_5571_t *) priv; + switch (func) { + case 0: /* Bridge */ + switch (addr) { + case 0x04: /* Command */ + dev->pci_conf_sb[0][addr] |= val & 0x0f; + break; - case 0x06: /* Status */ - dev->pci_conf_sb[0][addr] &= val; - break; + case 0x06: /* Status */ + dev->pci_conf_sb[0][addr] &= val; + break; - case 0x40: /* BIOS Control Register */ - dev->pci_conf_sb[0][addr] = val & 0x3f; - break; + case 0x40: /* BIOS Control Register */ + dev->pci_conf_sb[0][addr] = val & 0x3f; + break; - case 0x41: /* INTA# Remapping Control Register */ - case 0x42: /* INTB# Remapping Control Register */ - case 0x43: /* INTC# Remapping Control Register */ - case 0x44: /* INTD# Remapping Control Register */ - dev->pci_conf_sb[0][addr] = val & 0x8f; - pci_set_irq_routing((addr & 0x07), !(val & 0x80) ? (val & 0x0f) : PCI_IRQ_DISABLED); - break; + case 0x41: /* INTA# Remapping Control Register */ + case 0x42: /* INTB# Remapping Control Register */ + case 0x43: /* INTC# Remapping Control Register */ + case 0x44: /* INTD# Remapping Control Register */ + dev->pci_conf_sb[0][addr] = val & 0x8f; + pci_set_irq_routing((addr & 0x07), !(val & 0x80) ? (val & 0x0f) : PCI_IRQ_DISABLED); + break; - case 0x45: - dev->pci_conf_sb[0][addr] = val & 0xec; - switch ((val & 0xc0) >> 6) - { - case 0: - cpu_set_isa_speed(7159091); - break; - case 1: - cpu_set_isa_pci_div(4); - break; - case 2: - cpu_set_isa_pci_div(3); - break; - } - break; + case 0x45: + dev->pci_conf_sb[0][addr] = val & 0xec; + switch ((val & 0xc0) >> 6) { + case 0: + cpu_set_isa_speed(7159091); + break; + case 1: + cpu_set_isa_pci_div(4); + break; + case 2: + cpu_set_isa_pci_div(3); + break; - case 0x46: - dev->pci_conf_sb[0][addr] = val & 0xec; - break; + default: + break; + } + break; - case 0x47: /* DMA Clock and Wait State Control Register */ - dev->pci_conf_sb[0][addr] = val & 0x3e; - break; + case 0x46: + dev->pci_conf_sb[0][addr] = val & 0xec; + break; - case 0x48: /* ISA Master/DMA Memory Cycle Control Register 1 */ - case 0x49: /* ISA Master/DMA Memory Cycle Control Register 2 */ - case 0x4a: /* ISA Master/DMA Memory Cycle Control Register 3 */ - case 0x4b: /* ISA Master/DMA Memory Cycle Control Register 4 */ - dev->pci_conf_sb[0][addr] = val; - break; + case 0x47: /* DMA Clock and Wait State Control Register */ + dev->pci_conf_sb[0][addr] = val & 0x3e; + break; - case 0x4c: - case 0x4d: - case 0x4e: - case 0x4f: - case 0x50: - case 0x51: - case 0x52: - case 0x53: - case 0x54: - case 0x55: - case 0x56: - case 0x57: - case 0x58: - case 0x59: - case 0x5a: - case 0x5b: - case 0x5c: - case 0x5d: - case 0x5e: - dev->pci_conf_sb[0][addr] = val; - break; + case 0x48: /* ISA Master/DMA Memory Cycle Control Register 1 */ + case 0x49: /* ISA Master/DMA Memory Cycle Control Register 2 */ + case 0x4a: /* ISA Master/DMA Memory Cycle Control Register 3 */ + case 0x4b: /* ISA Master/DMA Memory Cycle Control Register 4 */ + dev->pci_conf_sb[0][addr] = val; + break; - case 0x5f: - dev->pci_conf_sb[0][addr] = val & 0x3f; - break; + case 0x4c: + case 0x4d: + case 0x4e: + case 0x4f: + case 0x50: + case 0x51: + case 0x52: + case 0x53: + case 0x54: + case 0x55: + case 0x56: + case 0x57: + case 0x58: + case 0x59: + case 0x5a: + case 0x5b: + case 0x5c: + case 0x5d: + case 0x5e: + dev->pci_conf_sb[0][addr] = val; + break; - case 0x60: - dev->pci_conf_sb[0][addr] = val; - break; + case 0x5f: + dev->pci_conf_sb[0][addr] = val & 0x3f; + break; - case 0x61: /* MIRQ Remapping Control Register */ - dev->pci_conf_sb[0][addr] = val; - pci_set_mirq_routing(PCI_MIRQ0, !(val & 0x80) ? (val & 0x0f) : PCI_IRQ_DISABLED); - break; + case 0x60: + dev->pci_conf_sb[0][addr] = val; + break; - case 0x62: /* On-board Device DMA Control Register */ - dev->pci_conf_sb[0][addr] = val & 0x0f; - dma_set_drq((val & 0x07), 1); - break; + case 0x61: /* MIRQ Remapping Control Register */ + dev->pci_conf_sb[0][addr] = val; + pci_set_mirq_routing(PCI_MIRQ0, !(val & 0x80) ? (val & 0x0f) : PCI_IRQ_DISABLED); + break; - case 0x63: /* IDEIRQ Remapping Control Register */ - dev->pci_conf_sb[0][addr] = val & 0x8f; - if (val & 0x80) - { - sff_set_irq_line(dev->ide_drive[0], val & 0x0f); - sff_set_irq_line(dev->ide_drive[1], val & 0x0f); - } - break; + case 0x62: /* On-board Device DMA Control Register */ + dev->pci_conf_sb[0][addr] = val & 0x0f; + dma_set_drq((val & 0x07), 1); + break; - case 0x64: /* GPIO Control Register */ - dev->pci_conf_sb[0][addr] = val & 0xef; - break; + case 0x63: /* IDEIRQ Remapping Control Register */ + dev->pci_conf_sb[0][addr] = val & 0x8f; + if (val & 0x80) { + sff_set_irq_line(dev->ide_drive[0], val & 0x0f); + sff_set_irq_line(dev->ide_drive[1], val & 0x0f); + } + break; - case 0x65: - dev->pci_conf_sb[0][addr] = val & 0x1b; - break; + case 0x64: /* GPIO Control Register */ + dev->pci_conf_sb[0][addr] = val & 0xef; + break; - case 0x66: /* GPIO Output Mode Control Register */ - case 0x67: /* GPIO Output Mode Control Register */ - dev->pci_conf_sb[0][addr] = val; - break; + case 0x65: + dev->pci_conf_sb[0][addr] = val & 0x1b; + break; - case 0x68: /* USBIRQ Remapping Control Register */ - dev->pci_conf_sb[0][addr] = val & 0x1b; - break; + case 0x66: /* GPIO Output Mode Control Register */ + case 0x67: /* GPIO Output Mode Control Register */ + dev->pci_conf_sb[0][addr] = val; + break; - case 0x69: - dev->pci_conf_sb[0][addr] = val; - break; + case 0x68: /* USBIRQ Remapping Control Register */ + dev->pci_conf_sb[0][addr] = val & 0x1b; + break; - case 0x6a: - dev->pci_conf_sb[0][addr] = val & 0xfc; - break; + case 0x69: + dev->pci_conf_sb[0][addr] = val; + break; - case 0x6b: - dev->pci_conf_sb[0][addr] = val; - break; + case 0x6a: + dev->pci_conf_sb[0][addr] = val & 0xfc; + break; - case 0x6c: - dev->pci_conf_sb[0][addr] = val & 0x03; - break; + case 0x6b: + dev->pci_conf_sb[0][addr] = val; + break; - case 0x6e: /* Software-Controlled Interrupt Request, Channels 7-0 */ - case 0x6f: /* Software-Controlled Interrupt Request, channels 15-8 */ - dev->pci_conf_sb[0][addr] = val; - break; + case 0x6c: + dev->pci_conf_sb[0][addr] = val & 0x03; + break; - case 0x70: - dev->pci_conf_sb[0][addr] = val & 0xde; - break; + case 0x6e: /* Software-Controlled Interrupt Request, Channels 7-0 */ + case 0x6f: /* Software-Controlled Interrupt Request, channels 15-8 */ + dev->pci_conf_sb[0][addr] = val; + break; - case 0x71: /* Type-F DMA Control Register */ - dev->pci_conf_sb[0][addr] = val & 0xfe; - break; + case 0x70: + dev->pci_conf_sb[0][addr] = val & 0xde; + break; - case 0x72: /* SMI Triggered By IRQ/GPIO Control */ - case 0x73: /* SMI Triggered By IRQ/GPIO Control */ - dev->pci_conf_sb[0][addr] = (addr == 0x72) ? val & 0xfe : val; - break; + case 0x71: /* Type-F DMA Control Register */ + dev->pci_conf_sb[0][addr] = val & 0xfe; + break; - case 0x74: /* System Standby Timer Reload, System Standby State Exit And Throttling State Exit Control */ - case 0x75: /* System Standby Timer Reload, System Standby State Exit And Throttling State Exit Control */ - case 0x76: /* Monitor Standby Timer Reload And Monitor Standby State ExitControl */ - case 0x77: /* Monitor Standby Timer Reload And Monitor Standby State ExitControl */ - dev->pci_conf_sb[0][addr] = val; - break; - } - sis_5571_log("SiS5571-SB: dev->pci_conf[%02x] = %02x\n", addr, val); - break; + case 0x72: /* SMI Triggered By IRQ/GPIO Control */ + case 0x73: /* SMI Triggered By IRQ/GPIO Control */ + dev->pci_conf_sb[0][addr] = (addr == 0x72) ? val & 0xfe : val; + break; - case 1: /* IDE Controller */ - switch (addr) - { - case 0x04: /* Command low byte */ - dev->pci_conf_sb[1][addr] = val & 0x05; - sis_5571_ide_handler(dev); - sis_5571_bm_handler(dev); - break; + case 0x74: /* System Standby Timer Reload, System Standby State Exit And Throttling State Exit Control */ + case 0x75: /* System Standby Timer Reload, System Standby State Exit And Throttling State Exit Control */ + case 0x76: /* Monitor Standby Timer Reload And Monitor Standby State ExitControl */ + case 0x77: /* Monitor Standby Timer Reload And Monitor Standby State ExitControl */ + dev->pci_conf_sb[0][addr] = val; + break; - case 0x07: /* Status high byte */ - dev->pci_conf_sb[1][addr] &= val; - break; + default: + break; + } + sis_5571_log("SiS5571-SB: dev->pci_conf[%02x] = %02x\n", addr, val); + break; - case 0x09: /* Programming Interface Byte */ - dev->pci_conf_sb[1][addr] = val & 0xcf; - sis_5571_ide_handler(dev); - break; + case 1: /* IDE Controller */ + switch (addr) { + case 0x04: /* Command low byte */ + dev->pci_conf_sb[1][addr] = val & 0x05; + sis_5571_ide_handler(dev); + sis_5571_bm_handler(dev); + break; - case 0x0d: /* Latency Time */ - case 0x10: /* Primary Channel Base Address Register */ - case 0x11: /* Primary Channel Base Address Register */ - case 0x12: /* Primary Channel Base Address Register */ - case 0x13: /* Primary Channel Base Address Register */ - case 0x14: /* Primary Channel Base Address Register */ - case 0x15: /* Primary Channel Base Address Register */ - case 0x16: /* Primary Channel Base Address Register */ - case 0x17: /* Primary Channel Base Address Register */ - case 0x18: /* Secondary Channel Base Address Register */ - case 0x19: /* Secondary Channel Base Address Register */ - case 0x1a: /* Secondary Channel Base Address Register */ - case 0x1b: /* Secondary Channel Base Address Register */ - case 0x1c: /* Secondary Channel Base Address Register */ - case 0x1d: /* Secondary Channel Base Address Register */ - case 0x1e: /* Secondary Channel Base Address Register */ - case 0x1f: /* Secondary Channel Base Address Register */ - dev->pci_conf_sb[1][addr] = val; - sis_5571_ide_handler(dev); - break; + case 0x07: /* Status high byte */ + dev->pci_conf_sb[1][addr] &= val; + break; - case 0x20: /* Bus Master IDE Control Register Base Address */ - case 0x21: /* Bus Master IDE Control Register Base Address */ - case 0x22: /* Bus Master IDE Control Register Base Address */ - case 0x23: /* Bus Master IDE Control Register Base Address */ - dev->pci_conf_sb[1][addr] = val; - sis_5571_bm_handler(dev); - break; + case 0x09: /* Programming Interface Byte */ + dev->pci_conf_sb[1][addr] = val & 0xcf; + sis_5571_ide_handler(dev); + break; - case 0x30: /* Expansion ROM Base Address */ - case 0x31: /* Expansion ROM Base Address */ - case 0x32: /* Expansion ROM Base Address */ - case 0x33: /* Expansion ROM Base Address */ - case 0x40: /* IDE Primary Channel/Master Drive Data Recovery Time Control */ - case 0x41: /* IDE Primary Channel/Master Drive DataActive Time Control */ - case 0x42: /* IDE Primary Channel/Slave Drive Data Recovery Time Control */ - case 0x43: /* IDE Primary Channel/Slave Drive Data Active Time Control */ - case 0x44: /* IDE Secondary Channel/Master Drive Data Recovery Time Control */ - case 0x45: /* IDE Secondary Channel/Master Drive Data Active Time Control */ - case 0x46: /* IDE Secondary Channel/Slave Drive Data Recovery Time Control */ - case 0x47: /* IDE Secondary Channel/Slave Drive Data Active Time Control */ - case 0x48: /* IDE Command Recovery Time Control */ - case 0x49: /* IDE Command Active Time Control */ - dev->pci_conf_sb[1][addr] = val; - break; + case 0x0d: /* Latency Time */ + case 0x10: /* Primary Channel Base Address Register */ + case 0x11: /* Primary Channel Base Address Register */ + case 0x12: /* Primary Channel Base Address Register */ + case 0x13: /* Primary Channel Base Address Register */ + case 0x14: /* Primary Channel Base Address Register */ + case 0x15: /* Primary Channel Base Address Register */ + case 0x16: /* Primary Channel Base Address Register */ + case 0x17: /* Primary Channel Base Address Register */ + case 0x18: /* Secondary Channel Base Address Register */ + case 0x19: /* Secondary Channel Base Address Register */ + case 0x1a: /* Secondary Channel Base Address Register */ + case 0x1b: /* Secondary Channel Base Address Register */ + case 0x1c: /* Secondary Channel Base Address Register */ + case 0x1d: /* Secondary Channel Base Address Register */ + case 0x1e: /* Secondary Channel Base Address Register */ + case 0x1f: /* Secondary Channel Base Address Register */ + dev->pci_conf_sb[1][addr] = val; + sis_5571_ide_handler(dev); + break; - case 0x4a: /* IDE General Control Register 0 */ - dev->pci_conf_sb[1][addr] = val & 0xaf; - sis_5571_ide_handler(dev); - break; + case 0x20: /* Bus Master IDE Control Register Base Address */ + case 0x21: /* Bus Master IDE Control Register Base Address */ + case 0x22: /* Bus Master IDE Control Register Base Address */ + case 0x23: /* Bus Master IDE Control Register Base Address */ + dev->pci_conf_sb[1][addr] = val; + sis_5571_bm_handler(dev); + break; - case 0x4b: /* IDE General Control register 1 */ - case 0x4c: /* Prefetch Count of Primary Channel (Low Byte) */ - case 0x4d: /* Prefetch Count of Primary Channel (High Byte) */ - case 0x4e: /* Prefetch Count of Secondary Channel (Low Byte) */ - case 0x4f: /* Prefetch Count of Secondary Channel (High Byte) */ - dev->pci_conf_sb[1][addr] = val; - break; - } - sis_5571_log("SiS5571-IDE: dev->pci_conf[%02x] = %02x\n", addr, val); - break; + case 0x30: /* Expansion ROM Base Address */ + case 0x31: /* Expansion ROM Base Address */ + case 0x32: /* Expansion ROM Base Address */ + case 0x33: /* Expansion ROM Base Address */ + case 0x40: /* IDE Primary Channel/Master Drive Data Recovery Time Control */ + case 0x41: /* IDE Primary Channel/Master Drive DataActive Time Control */ + case 0x42: /* IDE Primary Channel/Slave Drive Data Recovery Time Control */ + case 0x43: /* IDE Primary Channel/Slave Drive Data Active Time Control */ + case 0x44: /* IDE Secondary Channel/Master Drive Data Recovery Time Control */ + case 0x45: /* IDE Secondary Channel/Master Drive Data Active Time Control */ + case 0x46: /* IDE Secondary Channel/Slave Drive Data Recovery Time Control */ + case 0x47: /* IDE Secondary Channel/Slave Drive Data Active Time Control */ + case 0x48: /* IDE Command Recovery Time Control */ + case 0x49: /* IDE Command Active Time Control */ + dev->pci_conf_sb[1][addr] = val; + break; - case 2: /* USB Controller */ - switch (addr) - { - case 0x04: /* Command - Low Byte */ - dev->pci_conf_sb[2][addr] = val; - ohci_update_mem_mapping(dev->usb, dev->pci_conf_sb[2][0x11], dev->pci_conf_sb[2][0x12], dev->pci_conf_sb[2][0x13], dev->pci_conf_sb[2][4] & 1); - break; + case 0x4a: /* IDE General Control Register 0 */ + dev->pci_conf_sb[1][addr] = val & 0xaf; + sis_5571_ide_handler(dev); + break; - case 0x05: /* Command - High Byte */ - dev->pci_conf_sb[2][addr] = val & 0x03; - break; + case 0x4b: /* IDE General Control register 1 */ + case 0x4c: /* Prefetch Count of Primary Channel (Low Byte) */ + case 0x4d: /* Prefetch Count of Primary Channel (High Byte) */ + case 0x4e: /* Prefetch Count of Secondary Channel (Low Byte) */ + case 0x4f: /* Prefetch Count of Secondary Channel (High Byte) */ + dev->pci_conf_sb[1][addr] = val; + break; - case 0x06: /* Status - Low Byte */ - dev->pci_conf_sb[2][addr] &= val & 0xc0; - break; + default: + break; + } + sis_5571_log("SiS5571-IDE: dev->pci_conf[%02x] = %02x\n", addr, val); + break; - case 0x07: /* Status - High Byte */ - dev->pci_conf_sb[2][addr] &= val; - break; + case 2: /* USB Controller */ + switch (addr) { + case 0x04: /* Command - Low Byte */ + dev->pci_conf_sb[2][addr] = val; + ohci_update_mem_mapping(dev->usb, dev->pci_conf_sb[2][0x11], dev->pci_conf_sb[2][0x12], dev->pci_conf_sb[2][0x13], dev->pci_conf_sb[2][4] & 1); + break; - case 0x10: /* Memory Space Base Address Register */ - case 0x11: /* Memory Space Base Address Register */ - case 0x12: /* Memory Space Base Address Register */ - case 0x13: /* Memory Space Base Address Register */ - dev->pci_conf_sb[2][addr] = val & ((addr == 0x11) ? 0x0f : 0xff); - ohci_update_mem_mapping(dev->usb, dev->pci_conf_sb[2][0x11], dev->pci_conf_sb[2][0x12], dev->pci_conf_sb[2][0x13], dev->pci_conf_sb[2][4] & 1); - break; + case 0x05: /* Command - High Byte */ + dev->pci_conf_sb[2][addr] = val & 0x03; + break; - case 0x14: /* IO Space Base Address Register */ - case 0x15: /* IO Space Base Address Register */ - case 0x16: /* IO Space Base Address Register */ - case 0x17: /* IO Space Base Address Register */ - case 0x3c: /* Interrupt Line */ - dev->pci_conf_sb[2][addr] = val; - break; - } - sis_5571_log("SiS5571-USB: dev->pci_conf[%02x] = %02x\n", addr, val); - } + case 0x06: /* Status - Low Byte */ + dev->pci_conf_sb[2][addr] &= val & 0xc0; + break; + + case 0x07: /* Status - High Byte */ + dev->pci_conf_sb[2][addr] &= val; + break; + + case 0x10: /* Memory Space Base Address Register */ + case 0x11: /* Memory Space Base Address Register */ + case 0x12: /* Memory Space Base Address Register */ + case 0x13: /* Memory Space Base Address Register */ + dev->pci_conf_sb[2][addr] = val & ((addr == 0x11) ? 0x0f : 0xff); + ohci_update_mem_mapping(dev->usb, dev->pci_conf_sb[2][0x11], dev->pci_conf_sb[2][0x12], dev->pci_conf_sb[2][0x13], dev->pci_conf_sb[2][4] & 1); + break; + + case 0x14: /* IO Space Base Address Register */ + case 0x15: /* IO Space Base Address Register */ + case 0x16: /* IO Space Base Address Register */ + case 0x17: /* IO Space Base Address Register */ + case 0x3c: /* Interrupt Line */ + dev->pci_conf_sb[2][addr] = val; + break; + + default: + break; + } + sis_5571_log("SiS5571-USB: dev->pci_conf[%02x] = %02x\n", addr, val); + break; + + default: + break; + } } static uint8_t pci_isa_bridge_read(int func, int addr, void *priv) { - sis_5571_t *dev = (sis_5571_t *)priv; + const sis_5571_t *dev = (sis_5571_t *) priv; - switch (func) - { - case 0: - sis_5571_log("SiS5571-SB: dev->pci_conf[%02x] (%02x)\n", addr, dev->pci_conf_sb[0][addr]); - return dev->pci_conf_sb[0][addr]; - case 1: - sis_5571_log("SiS5571-IDE: dev->pci_conf[%02x] (%02x)\n", addr, dev->pci_conf_sb[1][addr]); - return dev->pci_conf_sb[1][addr]; - case 2: - sis_5571_log("SiS5571-USB: dev->pci_conf[%02x] (%02x)\n", addr, dev->pci_conf_sb[2][addr]); - return dev->pci_conf_sb[2][addr]; - default: - return 0xff; - } + switch (func) { + case 0: + sis_5571_log("SiS5571-SB: dev->pci_conf[%02x] (%02x)\n", addr, dev->pci_conf_sb[0][addr]); + return dev->pci_conf_sb[0][addr]; + case 1: + sis_5571_log("SiS5571-IDE: dev->pci_conf[%02x] (%02x)\n", addr, dev->pci_conf_sb[1][addr]); + return dev->pci_conf_sb[1][addr]; + case 2: + sis_5571_log("SiS5571-USB: dev->pci_conf[%02x] (%02x)\n", addr, dev->pci_conf_sb[2][addr]); + return dev->pci_conf_sb[2][addr]; + + default: + return 0xff; + } } static void sis_5571_reset(void *priv) { - sis_5571_t *dev = (sis_5571_t *)priv; + sis_5571_t *dev = (sis_5571_t *) priv; - /* Memory/PCI Bridge */ - dev->pci_conf[0x00] = 0x39; - dev->pci_conf[0x01] = 0x10; - dev->pci_conf[0x02] = 0x71; - dev->pci_conf[0x03] = 0x55; - dev->pci_conf[0x04] = 0xfd; - dev->pci_conf[0x0b] = 0x06; - dev->pci_conf[0x9e] = 0xff; - dev->pci_conf[0x9f] = 0xff; - dev->pci_conf[0xa2] = 0xff; + /* Memory/PCI Bridge */ + dev->pci_conf[0x00] = 0x39; + dev->pci_conf[0x01] = 0x10; + dev->pci_conf[0x02] = 0x71; + dev->pci_conf[0x03] = 0x55; + dev->pci_conf[0x04] = 0xfd; + dev->pci_conf[0x0b] = 0x06; + dev->pci_conf[0x9e] = 0xff; + dev->pci_conf[0x9f] = 0xff; + dev->pci_conf[0xa2] = 0xff; - /* PCI to ISA bridge */ - dev->pci_conf_sb[0][0x00] = 0x39; - dev->pci_conf_sb[0][0x01] = 0x10; - dev->pci_conf_sb[0][0x02] = 0x08; - dev->pci_conf_sb[0][0x04] = 0xfd; - dev->pci_conf_sb[0][0x08] = 0x01; - dev->pci_conf_sb[0][0x0a] = 0x01; - dev->pci_conf_sb[0][0x0b] = 0x06; + /* PCI to ISA bridge */ + dev->pci_conf_sb[0][0x00] = 0x39; + dev->pci_conf_sb[0][0x01] = 0x10; + dev->pci_conf_sb[0][0x02] = 0x08; + dev->pci_conf_sb[0][0x04] = 0xfd; + dev->pci_conf_sb[0][0x08] = 0x01; + dev->pci_conf_sb[0][0x0a] = 0x01; + dev->pci_conf_sb[0][0x0b] = 0x06; - /* IDE Controller */ - dev->pci_conf_sb[1][0x00] = 0x39; - dev->pci_conf_sb[1][0x01] = 0x10; - dev->pci_conf_sb[1][0x02] = 0x13; - dev->pci_conf_sb[1][0x03] = 0x55; - dev->pci_conf_sb[1][0x08] = 0xc0; - dev->pci_conf_sb[1][0x0a] = 0x01; - dev->pci_conf_sb[1][0x0b] = 0x01; - dev->pci_conf_sb[1][0x0e] = 0x80; - dev->pci_conf_sb[1][0x4a] = 0x06; - sff_set_slot(dev->ide_drive[0], dev->sb_pci_slot); - sff_set_slot(dev->ide_drive[1], dev->sb_pci_slot); - sff_bus_master_reset(dev->ide_drive[0], BUS_MASTER_BASE); - sff_bus_master_reset(dev->ide_drive[1], BUS_MASTER_BASE + 8); + /* IDE Controller */ + dev->pci_conf_sb[1][0x00] = 0x39; + dev->pci_conf_sb[1][0x01] = 0x10; + dev->pci_conf_sb[1][0x02] = 0x13; + dev->pci_conf_sb[1][0x03] = 0x55; + dev->pci_conf_sb[1][0x08] = 0xc0; + dev->pci_conf_sb[1][0x0a] = 0x01; + dev->pci_conf_sb[1][0x0b] = 0x01; + dev->pci_conf_sb[1][0x0e] = 0x80; + dev->pci_conf_sb[1][0x4a] = 0x06; + sff_set_slot(dev->ide_drive[0], dev->sb_slot); + sff_set_slot(dev->ide_drive[1], dev->sb_slot); + sff_bus_master_reset(dev->ide_drive[0]); + sff_bus_master_reset(dev->ide_drive[1]); - /* USB Controller */ - dev->pci_conf_sb[2][0x00] = 0x39; - dev->pci_conf_sb[2][0x01] = 0x10; - dev->pci_conf_sb[2][0x02] = 0x01; - dev->pci_conf_sb[2][0x03] = 0x70; - dev->pci_conf_sb[2][0x08] = 0xb0; - dev->pci_conf_sb[2][0x09] = 0x10; - dev->pci_conf_sb[2][0x0a] = 0x03; - dev->pci_conf_sb[2][0x0b] = 0xc0; - dev->pci_conf_sb[2][0x0e] = 0x80; - dev->pci_conf_sb[2][0x14] = 0x01; - dev->pci_conf_sb[2][0x3d] = 0x01; + /* USB Controller */ + dev->pci_conf_sb[2][0x00] = 0x39; + dev->pci_conf_sb[2][0x01] = 0x10; + dev->pci_conf_sb[2][0x02] = 0x01; + dev->pci_conf_sb[2][0x03] = 0x70; + dev->pci_conf_sb[2][0x08] = 0xb0; + dev->pci_conf_sb[2][0x09] = 0x10; + dev->pci_conf_sb[2][0x0a] = 0x03; + dev->pci_conf_sb[2][0x0b] = 0xc0; + dev->pci_conf_sb[2][0x0e] = 0x80; + dev->pci_conf_sb[2][0x14] = 0x01; + dev->pci_conf_sb[2][0x3d] = 0x01; } static void sis_5571_close(void *priv) { - sis_5571_t *dev = (sis_5571_t *)priv; + sis_5571_t *dev = (sis_5571_t *) priv; - smram_del(dev->smram); - free(dev); + smram_del(dev->smram); + free(dev); } static void * -sis_5571_init(const device_t *info) +sis_5571_init(UNUSED(const device_t *info)) { - sis_5571_t *dev = (sis_5571_t *)malloc(sizeof(sis_5571_t)); - memset(dev, 0x00, sizeof(sis_5571_t)); + sis_5571_t *dev = (sis_5571_t *) malloc(sizeof(sis_5571_t)); + memset(dev, 0x00, sizeof(sis_5571_t)); - dev->nb_pci_slot = pci_add_card(PCI_ADD_NORTHBRIDGE, memory_pci_bridge_read, memory_pci_bridge_write, dev); - dev->sb_pci_slot = pci_add_card(PCI_ADD_SOUTHBRIDGE, pci_isa_bridge_read, pci_isa_bridge_write, dev); + pci_add_card(PCI_ADD_NORTHBRIDGE, memory_pci_bridge_read, memory_pci_bridge_write, dev, &dev->nb_slot); + pci_add_card(PCI_ADD_SOUTHBRIDGE, pci_isa_bridge_read, pci_isa_bridge_write, dev, &dev->sb_slot); - /* MIRQ */ - pci_enable_mirq(0); + /* MIRQ */ + pci_enable_mirq(0); - /* Port 92 & SMRAM */ - dev->port_92 = device_add(&port_92_pci_device); - dev->smram = smram_add(); + /* Port 92 & SMRAM */ + dev->port_92 = device_add(&port_92_pci_device); + dev->smram = smram_add(); - /* SFF IDE */ - dev->ide_drive[0] = device_add_inst(&sff8038i_device, 1); - dev->ide_drive[1] = device_add_inst(&sff8038i_device, 2); + /* SFF IDE */ + dev->ide_drive[0] = device_add_inst(&sff8038i_device, 1); + dev->ide_drive[1] = device_add_inst(&sff8038i_device, 2); - /* USB */ - dev->usb = device_add(&usb_device); + /* USB */ + dev->usb = device_add(&usb_device); - sis_5571_reset(dev); + sis_5571_reset(dev); - return dev; + return dev; } const device_t sis_5571_device = { - "SiS 5571", - "sis_5571", - DEVICE_PCI, - 0, - sis_5571_init, - sis_5571_close, - sis_5571_reset, - {NULL}, - NULL, - NULL, - NULL}; + .name = "SiS 5571", + .internal_name = "sis_5571", + .flags = DEVICE_PCI, + .local = 0, + .init = sis_5571_init, + .close = sis_5571_close, + .reset = sis_5571_reset, + { .available = NULL }, + .speed_changed = NULL, + .force_redraw = NULL, + .config = NULL +}; diff --git a/src/chipset/sis_85c310.c b/src/chipset/sis_85c310.c index 6e31f8456..296307fe1 100644 --- a/src/chipset/sis_85c310.c +++ b/src/chipset/sis_85c310.c @@ -10,29 +10,29 @@ #include <86box/io.h> #include <86box/device.h> #include <86box/mem.h> +#include <86box/plat_unused.h> #include <86box/chipset.h> - -typedef struct -{ - uint8_t cur_reg, tries, - regs[258]; +typedef struct rabbit_t { + uint8_t cur_reg; + uint8_t tries; + uint8_t regs[258]; } rabbit_t; - static void rabbit_recalcmapping(rabbit_t *dev) { - uint32_t shread, shwrite; + uint32_t shread; + uint32_t shwrite; uint32_t shflags = 0; - shread = !!(dev->regs[0x101] & 0x40); + shread = !!(dev->regs[0x101] & 0x40); shwrite = !!(dev->regs[0x100] & 0x02); shflags = shread ? MEM_READ_INTERNAL : MEM_READ_EXTANY; shflags |= shwrite ? MEM_WRITE_INTERNAL : MEM_WRITE_EXTANY; - shadowbios = !!shread; + shadowbios = !!shread; shadowbios_write = !!shwrite; #ifdef USE_SHADOW_C0000 @@ -42,79 +42,83 @@ rabbit_recalcmapping(rabbit_t *dev) #endif switch (dev->regs[0x100] & 0x09) { - case 0x01: + case 0x01: /* The one BIOS we use seems to use something else to control C0000-DFFFF shadow, no idea what. */ #ifdef USE_SHADOW_C0000 - /* 64K at 0C0000-0CFFFF */ - mem_set_mem_state(0x000c0000, 0x00010000, shflags); - /* FALLTHROUGH */ + /* 64K at 0C0000-0CFFFF */ + mem_set_mem_state(0x000c0000, 0x00010000, shflags); + /* FALLTHROUGH */ #endif - case 0x00: - /* 64K at 0F0000-0FFFFF */ - mem_set_mem_state(0x000f0000, 0x00010000, shflags); - break; + case 0x00: + /* 64K at 0F0000-0FFFFF */ + mem_set_mem_state(0x000f0000, 0x00010000, shflags); + break; - case 0x09: + case 0x09: #ifdef USE_SHADOW_C0000 - /* 128K at 0C0000-0DFFFF */ - mem_set_mem_state(0x000c0000, 0x00020000, shflags); - /* FALLTHROUGH */ + /* 128K at 0C0000-0DFFFF */ + mem_set_mem_state(0x000c0000, 0x00020000, shflags); + /* FALLTHROUGH */ #endif - case 0x08: - /* 128K at 0E0000-0FFFFF */ - mem_set_mem_state(0x000e0000, 0x00020000, shflags); - break; + case 0x08: + /* 128K at 0E0000-0FFFFF */ + mem_set_mem_state(0x000e0000, 0x00020000, shflags); + break; + default: + break; } flushmmucache(); } - static void rabbit_write(uint16_t addr, uint8_t val, void *priv) { rabbit_t *dev = (rabbit_t *) priv; switch (addr) { - case 0x22: - dev->cur_reg = val; - dev->tries = 0; - break; - case 0x23: - if (dev->cur_reg == 0x83) { - if (dev->tries < 0x02) { - dev->regs[dev->tries++ | 0x100] = val; - if (dev->tries == 0x02) - rabbit_recalcmapping(dev); - } - } else - dev->regs[dev->cur_reg] = val; - break; + case 0x22: + dev->cur_reg = val; + dev->tries = 0; + break; + case 0x23: + if (dev->cur_reg == 0x83) { + if (dev->tries < 0x02) { + dev->regs[dev->tries++ | 0x100] = val; + if (dev->tries == 0x02) + rabbit_recalcmapping(dev); + } + } else + dev->regs[dev->cur_reg] = val; + break; + default: + break; } } - static uint8_t rabbit_read(uint16_t addr, void *priv) { - uint8_t ret = 0xff; + uint8_t ret = 0xff; rabbit_t *dev = (rabbit_t *) priv; switch (addr) { - case 0x23: - if (dev->cur_reg == 0x83) { - if (dev->tries < 0x02) - ret = dev->regs[dev->tries++ | 0x100]; - } else - ret = dev->regs[dev->cur_reg]; - break; + case 0x23: + if (dev->cur_reg == 0x83) { + if (dev->tries < 0x02) + ret = dev->regs[dev->tries++ | 0x100]; + } else + ret = dev->regs[dev->cur_reg]; + break; + + default: + break; } return ret; } - static void rabbit_close(void *priv) { @@ -123,9 +127,8 @@ rabbit_close(void *priv) free(dev); } - static void * -rabbit_init(const device_t *info) +rabbit_init(UNUSED(const device_t *info)) { rabbit_t *dev = (rabbit_t *) malloc(sizeof(rabbit_t)); memset(dev, 0, sizeof(rabbit_t)); @@ -135,13 +138,16 @@ rabbit_init(const device_t *info) return dev; } - const device_t rabbit_device = { - "SiS Rabbit", - "rabbit", - 0, - 0, - rabbit_init, rabbit_close, NULL, - { NULL }, NULL, NULL, - NULL -}; \ No newline at end of file + .name = "SiS Rabbit", + .internal_name = "rabbit", + .flags = 0, + .local = 0, + .init = rabbit_init, + .close = rabbit_close, + .reset = NULL, + { .available = NULL }, + .speed_changed = NULL, + .force_redraw = NULL, + .config = NULL +}; diff --git a/src/chipset/sis_85c496.c b/src/chipset/sis_85c496.c index 1c1ddb036..4d1db2d9e 100644 --- a/src/chipset/sis_85c496.c +++ b/src/chipset/sis_85c496.c @@ -1,19 +1,20 @@ /* - * 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. + * 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. + * This file is part of the 86Box distribution. * - * Implementation of the SiS 85c496/85c497 chip. + * Implementation of the SiS 85c496/85c497 chip. * * * - * Authors: Miran Grca, + * Authors: Miran Grca, * - * Copyright 2019,2020 Miran Grca. + * Copyright 2019-2020 Miran Grca. */ +#define USE_DRB_HACK #include #include #include @@ -32,45 +33,53 @@ #include <86box/dma.h> #include <86box/nvr.h> #include <86box/pic.h> +#include <86box/plat_unused.h> #include <86box/port_92.h> #include <86box/hdc_ide.h> #include <86box/machine.h> #include <86box/chipset.h> #include <86box/spd.h> +#ifndef USE_DRB_HACK +#include <86box/row.h> +#endif - -typedef struct sis_85c496_t -{ - uint8_t cur_reg, rmsmiblk_count, - regs[127], - pci_conf[256]; - smram_t *smram; - pc_timer_t rmsmiblk_timer; - port_92_t * port_92; - nvr_t * nvr; +typedef struct sis_85c496_t { + uint8_t cur_reg; + uint8_t rmsmiblk_count; + uint8_t pci_slot; + uint8_t pad; +#ifndef USE_DRB_HACK + uint8_t drb_default; + uint8_t drb_bits; + uint8_t pad0; + uint8_t pad1; +#endif + uint8_t regs[127]; + uint8_t pci_conf[256]; + smram_t *smram; + pc_timer_t rmsmiblk_timer; + port_92_t *port_92; + nvr_t *nvr; } sis_85c496_t; - #ifdef ENABLE_SIS_85C496_LOG int sis_85c496_do_log = ENABLE_SIS_85C496_LOG; - void sis_85c496_log(const char *fmt, ...) { va_list ap; if (sis_85c496_do_log) { - va_start(ap, fmt); - pclog_ex(fmt, ap); - va_end(ap); + va_start(ap, fmt); + pclog_ex(fmt, ap); + va_end(ap); } } #else -#define sis_85c496_log(fmt, ...) +# define sis_85c496_log(fmt, ...) #endif - static void sis_85c497_isa_write(uint16_t port, uint8_t val, void *priv) { @@ -79,75 +88,76 @@ sis_85c497_isa_write(uint16_t port, uint8_t val, void *priv) sis_85c496_log("[%04X:%08X] ISA Write %02X to %04X\n", CS, cpu_state.pc, val, port); if (port == 0x22) - dev->cur_reg = val; - else if (port == 0x23) switch (dev->cur_reg) { - case 0x01: /* Built-in 206 Timing Control */ - dev->regs[dev->cur_reg] = val; - break; - case 0x70: /* ISA Bus Clock Selection */ - dev->regs[dev->cur_reg] = val & 0xc0; - break; - case 0x71: /* ISA Bus Timing Control */ - dev->regs[dev->cur_reg] = val & 0xf6; - break; - case 0x72: case 0x76: /* SMOUT */ - case 0x74: /* BIOS Timer */ - dev->regs[dev->cur_reg] = val; - break; - case 0x73: /* BIOS Timer */ - dev->regs[dev->cur_reg] = val & 0xfd; - break; - case 0x75: /* DMA / Deturbo Control */ - dev->regs[dev->cur_reg] = val & 0xfc; - dma_set_mask((val & 0x80) ? 0xffffffff : 0x00ffffff); - break; - } + dev->cur_reg = val; + else if (port == 0x23) + switch (dev->cur_reg) { + case 0x01: /* Built-in 206 Timing Control */ + dev->regs[dev->cur_reg] = val; + break; + case 0x70: /* ISA Bus Clock Selection */ + dev->regs[dev->cur_reg] = val & 0xc0; + break; + case 0x71: /* ISA Bus Timing Control */ + dev->regs[dev->cur_reg] = val & 0xf6; + break; + case 0x72: + case 0x76: /* SMOUT */ + case 0x74: /* BIOS Timer */ + dev->regs[dev->cur_reg] = val; + break; + case 0x73: /* BIOS Timer */ + dev->regs[dev->cur_reg] = val & 0xfd; + break; + case 0x75: /* DMA / Deturbo Control */ + dev->regs[dev->cur_reg] = val & 0xfc; + dma_set_mask((val & 0x80) ? 0xffffffff : 0x00ffffff); + break; + default: + break; + } } - static uint8_t sis_85c497_isa_read(uint16_t port, void *priv) { - sis_85c496_t *dev = (sis_85c496_t *) priv; - uint8_t ret = 0xff; + const sis_85c496_t *dev = (sis_85c496_t *) priv; + uint8_t ret = 0xff; if (port == 0x23) - ret = dev->regs[dev->cur_reg]; + ret = dev->regs[dev->cur_reg]; else if (port == 0x33) - ret = 0x3c /*random_generate()*/; + ret = 0x3c /*random_generate()*/; sis_85c496_log("[%04X:%08X] ISA Read %02X from %04X\n", CS, cpu_state.pc, ret, port); return ret; } - static void sis_85c496_recalcmapping(sis_85c496_t *dev) { uint32_t base; - uint32_t i, shflags = 0; + uint32_t shflags = 0; - shadowbios = 0; + shadowbios = 0; shadowbios_write = 0; - for (i = 0; i < 8; i++) { - base = 0xc0000 + (i << 15); + for (uint8_t i = 0; i < 8; i++) { + base = 0xc0000 + (i << 15); - if (dev->pci_conf[0x44] & (1 << i)) { - shadowbios |= (base >= 0xe0000) && (dev->pci_conf[0x45] & 0x02); - shadowbios_write |= (base >= 0xe0000) && !(dev->pci_conf[0x45] & 0x01); - shflags = (dev->pci_conf[0x45] & 0x02) ? MEM_READ_INTERNAL : MEM_READ_EXTANY; - shflags |= (dev->pci_conf[0x45] & 0x01) ? MEM_WRITE_EXTANY : MEM_WRITE_INTERNAL; - mem_set_mem_state_both(base, 0x8000, shflags); - } else - mem_set_mem_state_both(base, 0x8000, MEM_READ_EXTANY | MEM_WRITE_EXTANY); + if (dev->pci_conf[0x44] & (1 << i)) { + shadowbios |= (base >= 0xe0000) && (dev->pci_conf[0x45] & 0x02); + shadowbios_write |= (base >= 0xe0000) && !(dev->pci_conf[0x45] & 0x01); + shflags = (dev->pci_conf[0x45] & 0x02) ? MEM_READ_INTERNAL : MEM_READ_EXTANY; + shflags |= (dev->pci_conf[0x45] & 0x01) ? MEM_WRITE_EXTANY : MEM_WRITE_INTERNAL; + mem_set_mem_state_both(base, 0x8000, shflags); + } else + mem_set_mem_state_both(base, 0x8000, MEM_READ_EXTANY | MEM_WRITE_EXTANY); } flushmmucache_nopc(); } - static void sis_85c496_ide_handler(sis_85c496_t *dev) { @@ -160,315 +170,371 @@ sis_85c496_ide_handler(sis_85c496_t *dev) ide_sec_disable(); if (ide_cfg[1] & 0x02) { - ide_set_base(0, 0x0170); - ide_set_side(0, 0x0376); - ide_set_base(1, 0x01f0); - ide_set_side(1, 0x03f6); + ide_set_base(0, 0x0170); + ide_set_side(0, 0x0376); + ide_set_base(1, 0x01f0); + ide_set_side(1, 0x03f6); - if (ide_cfg[1] & 0x01) { - if (!(ide_cfg[0] & 0x40)) - ide_pri_enable(); - if (!(ide_cfg[0] & 0x80)) - ide_sec_enable(); - } + if (ide_cfg[1] & 0x01) { + if (!(ide_cfg[0] & 0x40)) + ide_pri_enable(); + if (!(ide_cfg[0] & 0x80)) + ide_sec_enable(); + } } else { - ide_set_base(0, 0x01f0); - ide_set_side(0, 0x03f6); - ide_set_base(1, 0x0170); - ide_set_side(1, 0x0376); + ide_set_base(0, 0x01f0); + ide_set_side(0, 0x03f6); + ide_set_base(1, 0x0170); + ide_set_side(1, 0x0376); - if (ide_cfg[1] & 0x01) { - if (!(ide_cfg[0] & 0x40)) - ide_sec_enable(); - if (!(ide_cfg[0] & 0x80)) - ide_pri_enable(); - } + if (ide_cfg[1] & 0x01) { + if (!(ide_cfg[0] & 0x40)) + ide_sec_enable(); + if (!(ide_cfg[0] & 0x80)) + ide_pri_enable(); + } } } +#ifndef USE_DRB_HACK +static void +sis_85c496_drb_recalc(sis_85c496_t *dev) +{ + int i; + uint32_t boundary; + + for (i = 7; i >= 0; i--) + row_disable(i); + + for (i = 0; i <= 7; i++) { + boundary = ((uint32_t) dev->pci_conf[0x48 + i]); + row_set_boundary(i, boundary); + } + + flushmmucache(); +} +#endif + /* 00 - 3F = PCI Configuration, 40 - 7F = 85C496, 80 - FF = 85C497 */ static void -sis_85c49x_pci_write(int func, int addr, uint8_t val, void *priv) +sis_85c49x_pci_write(UNUSED(int func), int addr, uint8_t val, void *priv) { sis_85c496_t *dev = (sis_85c496_t *) priv; - uint8_t old, valxor; - uint8_t smm_irq[4] = { 10, 11, 12, 15 }; - uint32_t host_base, ram_base, size; + uint8_t old; + uint8_t valxor; + uint8_t smm_irq[4] = { 10, 11, 12, 15 }; + uint32_t host_base; + uint32_t ram_base; + uint32_t size; - old = dev->pci_conf[addr]; + old = dev->pci_conf[addr]; valxor = (dev->pci_conf[addr]) ^ val; sis_85c496_log("[%04X:%08X] PCI Write %02X to %02X:%02X\n", CS, cpu_state.pc, val, func, addr); switch (addr) { - /* PCI Configuration Header Registers (00h ~ 3Fh) */ - case 0x04: /* PCI Device Command */ - dev->pci_conf[addr] = val & 0x40; - break; - case 0x05: /* PCI Device Command */ - dev->pci_conf[addr] = val & 0x03; - break; - case 0x07: /* Device Status */ - dev->pci_conf[addr] &= ~(val & 0xf1); - break; + /* PCI Configuration Header Registers (00h ~ 3Fh) */ + case 0x04: /* PCI Device Command */ + dev->pci_conf[addr] = val & 0x40; + break; + case 0x05: /* PCI Device Command */ + dev->pci_conf[addr] = val & 0x03; + break; + case 0x07: /* Device Status */ + dev->pci_conf[addr] &= ~(val & 0xf1); + break; - /* 86C496 Specific Registers (40h ~ 7Fh) */ - case 0x40: /* CPU Configuration */ - dev->pci_conf[addr] = val & 0x7f; - break; - case 0x41: /* DRAM Configuration */ - dev->pci_conf[addr] = val; - break; - case 0x42: /* Cache Configure */ - dev->pci_conf[addr] = val; - cpu_cache_ext_enabled = (val & 0x01); - cpu_update_waitstates(); - break; - case 0x43: /* Cache Configure */ - dev->pci_conf[addr] = val & 0x8f; - break; - case 0x44: /* Shadow Configure */ - dev->pci_conf[addr] = val; - if (valxor & 0xff) { - sis_85c496_recalcmapping(dev); - if (((old & 0xf0) == 0xf0) && ((val & 0xf0) == 0x30)) - flushmmucache_nopc(); - else if (((old & 0xf0) == 0xf0) && ((val & 0xf0) == 0x00)) - flushmmucache_nopc(); - else - flushmmucache(); - } - break; - case 0x45: /* Shadow Configure */ - dev->pci_conf[addr] = val & 0x0f; - if (valxor & 0x03) - sis_85c496_recalcmapping(dev); - break; - case 0x46: /* Cacheable Control */ - dev->pci_conf[addr] = val; - break; - case 0x47: /* 85C496 Address Decoder */ - dev->pci_conf[addr] = val & 0x1f; - break; - case 0x48: case 0x49: case 0x4a: case 0x4b: /* DRAM Boundary */ - case 0x4c: case 0x4d: case 0x4e: case 0x4f: - // dev->pci_conf[addr] = val; - spd_write_drbs(dev->pci_conf, 0x48, 0x4f, 1); - break; - case 0x50: case 0x51: /* Exclusive Area 0 Setup */ - dev->pci_conf[addr] = val; - break; - case 0x52: case 0x53: /* Exclusive Area 1 Setup */ - dev->pci_conf[addr] = val; - break; - case 0x54: /* Exclusive Area 2 Setup */ - dev->pci_conf[addr] = val; - break; - case 0x55: /* Exclusive Area 3 Setup */ - dev->pci_conf[addr] = val & 0xf0; - break; - case 0x56: /* PCI / Keyboard Configure */ - dev->pci_conf[addr] = val; - if (valxor & 0x02) { - port_92_remove(dev->port_92); - if (val & 0x02) - port_92_add(dev->port_92); - } - break; - case 0x57: /* Output Pin Configuration */ - dev->pci_conf[addr] = val; - break; - case 0x58: /* Build-in IDE Controller / VESA Bus Configuration */ - dev->pci_conf[addr] = val & 0xd7; - if (valxor & 0xc0) - sis_85c496_ide_handler(dev); - break; - case 0x59: /* Build-in IDE Controller / VESA Bus Configuration */ - dev->pci_conf[addr] = val; - if (valxor & 0x03) - sis_85c496_ide_handler(dev); - break; - case 0x5a: /* SMRAM Remapping Configuration */ - dev->pci_conf[addr] = val & 0xbe; - if (valxor & 0x3e) { - unmask_a20_in_smm = !!(val & 0x20); + /* 86C496 Specific Registers (40h ~ 7Fh) */ + case 0x40: /* CPU Configuration */ + dev->pci_conf[addr] = val & 0x7f; + break; + case 0x41: /* DRAM Configuration */ + dev->pci_conf[addr] = val; + break; + case 0x42: /* Cache Configure */ + dev->pci_conf[addr] = val; + cpu_cache_ext_enabled = (val & 0x01); + cpu_update_waitstates(); + break; + case 0x43: /* Cache Configure */ + dev->pci_conf[addr] = val & 0x8f; + break; + case 0x44: /* Shadow Configure */ + dev->pci_conf[addr] = val; + if (valxor & 0xff) { + sis_85c496_recalcmapping(dev); + if (((old & 0xf0) == 0xf0) && ((val & 0xf0) == 0x30)) + flushmmucache_nopc(); + else if (((old & 0xf0) == 0xf0) && ((val & 0xf0) == 0x00)) + flushmmucache_nopc(); + else + flushmmucache(); + } + break; + case 0x45: /* Shadow Configure */ + dev->pci_conf[addr] = val & 0x0f; + if (valxor & 0x03) + sis_85c496_recalcmapping(dev); + break; + case 0x46: /* Cacheable Control */ + dev->pci_conf[addr] = val; + break; + case 0x47: /* 85C496 Address Decoder */ + dev->pci_conf[addr] = val & 0x1f; + break; + case 0x48: + case 0x49: + case 0x4a: + case 0x4b: /* DRAM Boundary */ + case 0x4c: + case 0x4d: + case 0x4e: + case 0x4f: +#ifdef USE_DRB_HACK + spd_write_drbs(dev->pci_conf, 0x48, 0x4f, 1); +#else + dev->pci_conf[addr] = val; + sis_85c496_drb_recalc(dev); +#endif + break; + case 0x50: + case 0x51: /* Exclusive Area 0 Setup */ + dev->pci_conf[addr] = val; + break; + case 0x52: + case 0x53: /* Exclusive Area 1 Setup */ + dev->pci_conf[addr] = val; + break; + case 0x54: /* Exclusive Area 2 Setup */ + dev->pci_conf[addr] = val; + break; + case 0x55: /* Exclusive Area 3 Setup */ + dev->pci_conf[addr] = val & 0xf0; + break; + case 0x56: /* PCI / Keyboard Configure */ + dev->pci_conf[addr] = val; + if (valxor & 0x02) { + port_92_remove(dev->port_92); + if (val & 0x02) + port_92_add(dev->port_92); + } + break; + case 0x57: /* Output Pin Configuration */ + dev->pci_conf[addr] = val; + break; + case 0x58: /* Build-in IDE Controller / VESA Bus Configuration */ + dev->pci_conf[addr] = val & 0xd7; + if (valxor & 0xc0) + sis_85c496_ide_handler(dev); + break; + case 0x59: /* Build-in IDE Controller / VESA Bus Configuration */ + dev->pci_conf[addr] = val; + if (valxor & 0x03) + sis_85c496_ide_handler(dev); + break; + case 0x5a: /* SMRAM Remapping Configuration */ + dev->pci_conf[addr] = val & 0xbe; + if (valxor & 0x3e) { + unmask_a20_in_smm = !!(val & 0x20); - smram_disable_all(); + smram_disable_all(); - if (val & 0x02) { - host_base = 0x00060000; - ram_base = 0x000a0000; - size = 0x00010000; - switch ((val >> 3) & 0x03) { - case 0x00: - host_base = 0x00060000; - ram_base = 0x000a0000; - break; - case 0x01: - host_base = 0x00060000; - ram_base = 0x000b0000; - break; - case 0x02: - host_base = 0x000e0000; - ram_base = 0x000a0000; - break; - case 0x03: - host_base = 0x000e0000; - ram_base = 0x000b0000; - break; - } + if (val & 0x02) { + host_base = 0x00060000; + ram_base = 0x000a0000; + size = 0x00010000; + switch ((val >> 3) & 0x03) { + case 0x00: + host_base = 0x00060000; + ram_base = 0x000a0000; + break; + case 0x01: + host_base = 0x00060000; + ram_base = 0x000b0000; + break; + case 0x02: + host_base = 0x000e0000; + ram_base = 0x000a0000; + break; + case 0x03: + host_base = 0x000e0000; + ram_base = 0x000b0000; + break; + default: + break; + } - smram_enable(dev->smram, host_base, ram_base, size, - ((val & 0x06) == 0x06), (val & 0x02)); - } - } - break; - case 0x5b: /* Programmable I/O Traps Configure */ - case 0x5c: case 0x5d: /* Programmable I/O Trap 0 Base */ - case 0x5e: case 0x5f: /* Programmable I/O Trap 0 Base */ - case 0x60: case 0x61: /* IDE Controller Channel 0 Configuration */ - case 0x62: case 0x63: /* IDE Controller Channel 1 Configuration */ - case 0x64: case 0x65: /* Exclusive Area 3 Setup */ - case 0x66: /* EDO DRAM Configuration */ - case 0x68: case 0x69: /* Asymmetry DRAM Configuration */ - dev->pci_conf[addr] = val; - break; - case 0x67: /* Miscellaneous Control */ - dev->pci_conf[addr] = val & 0xf9; - if (valxor & 0x60) - port_92_set_features(dev->port_92, !!(val & 0x20), !!(val & 0x40)); - break; + smram_enable(dev->smram, host_base, ram_base, size, + ((val & 0x06) == 0x06), (val & 0x02)); + } + } + break; + case 0x5b: /* Programmable I/O Traps Configure */ + case 0x5c: + case 0x5d: /* Programmable I/O Trap 0 Base */ + case 0x5e: + case 0x5f: /* Programmable I/O Trap 0 Base */ + case 0x60: + case 0x61: /* IDE Controller Channel 0 Configuration */ + case 0x62: + case 0x63: /* IDE Controller Channel 1 Configuration */ + case 0x64: + case 0x65: /* Exclusive Area 3 Setup */ + case 0x66: /* EDO DRAM Configuration */ + case 0x68: + case 0x69: /* Asymmetry DRAM Configuration */ + dev->pci_conf[addr] = val; + break; + case 0x67: /* Miscellaneous Control */ + dev->pci_conf[addr] = val & 0xf9; + if (valxor & 0x60) + port_92_set_features(dev->port_92, !!(val & 0x20), !!(val & 0x40)); + break; - /* 86C497 Specific Registers (80h ~ FFh) */ - case 0x80: /* PMU Configuration */ - case 0x85: /* STPCLK# Event Control */ - case 0x86: case 0x87: /* STPCLK# Deassertion IRQ Selection */ - case 0x89: /* Fast Timer Count */ - case 0x8a: /* Generic Timer Count */ - case 0x8b: /* Slow Timer Count */ - case 0x8e: /* Clock Throttling On Timer Count */ - case 0x8f: /* Clock Throttling Off Timer Count */ - case 0x90: /* Clock Throttling On Timer Reload Condition */ - case 0x92: /* Fast Timer Reload Condition */ - case 0x94: /* Generic Timer Reload Condition */ - case 0x96: /* Slow Timer Reload Condition */ - case 0x98: case 0x99: /* Fast Timer Reload IRQ Selection */ - case 0x9a: case 0x9b: /* Generic Timer Reload IRQ Selection */ - case 0x9c: case 0x9d: /* Slow Timer Reload IRQ Selection */ - case 0xa2: /* SMI Request Status Selection */ - case 0xa4: case 0xa5: /* SMI Request IRQ Selection */ - case 0xa6: case 0xa7: /* Clock Throttlign On Timer Reload IRQ Selection */ - case 0xa8: /* GPIO Control */ - case 0xaa: /* GPIO DeBounce Count */ - case 0xd2: /* Exclusive Area 2 Base Address */ - dev->pci_conf[addr] = val; - break; - case 0x81: /* PMU CPU Type Configuration */ - dev->pci_conf[addr] = val & 0x9f; - break; - case 0x88: /* Timer Control */ - dev->pci_conf[addr] = val & 0x3f; - break; - case 0x8d: /* RMSMIBLK Timer Count */ - dev->pci_conf[addr] = val; - dev->rmsmiblk_count = val; - timer_stop(&dev->rmsmiblk_timer); - if (val >= 0x02) - timer_on_auto(&dev->rmsmiblk_timer, 35.0); - break; - case 0x91: /* Clock Throttling On Timer Reload Condition */ - case 0x93: /* Fast Timer Reload Condition */ - case 0x95: /* Generic Timer Reload Condition */ - dev->pci_conf[addr] = val & 0x03; - break; - case 0x97: /* Slow Timer Reload Condition */ - dev->pci_conf[addr] = val & 0xc3; - break; - case 0x9e: /* Soft-SMI Generation / RMSMIBLK Trigger */ - if (!smi_block && (val & 0x01) && (dev->pci_conf[0x80] & 0x80) && (dev->pci_conf[0xa2] & 0x10)) { - if (dev->pci_conf[0x80] & 0x10) - picint(1 << smm_irq[dev->pci_conf[0x81] & 0x03]); - else - smi_line = 1; - smi_block = 1; - dev->pci_conf[0xa0] |= 0x10; - } - if (val & 0x02) { - timer_stop(&dev->rmsmiblk_timer); - if (dev->rmsmiblk_count >= 0x02) - timer_on_auto(&dev->rmsmiblk_timer, 35.0); - } - break; - case 0xa0: case 0xa1: /* SMI Request Status */ - dev->pci_conf[addr] &= ~val; - break; - case 0xa3: /* SMI Request Status Selection */ - dev->pci_conf[addr] = val & 0x7f; - break; - case 0xa9: /* GPIO SMI Request Status */ - dev->pci_conf[addr] = ~(val & 0x03); - break; - case 0xc0: /* PCI INTA# -to-IRQ Link */ - case 0xc1: /* PCI INTB# -to-IRQ Link */ - case 0xc2: /* PCI INTC# -to-IRQ Link */ - case 0xc3: /* PCI INTD# -to-IRQ Link */ - dev->pci_conf[addr] = val & 0x8f; - if (val & 0x80) - pci_set_irq_routing(PCI_INTA + (addr & 0x03), val & 0xf); - else - pci_set_irq_routing(PCI_INTA + (addr & 0x03), PCI_IRQ_DISABLED); - break; - case 0xc6: /* 85C497 Post / INIT Configuration */ - dev->pci_conf[addr] = val & 0x0f; - break; - case 0xc8: case 0xc9: case 0xca: case 0xcb: /* Mail Box */ - dev->pci_conf[addr] = val; - break; - case 0xd0: /* ISA BIOS Configuration */ - dev->pci_conf[addr] = val & 0xfb; - break; - case 0xd1: /* ISA Address Decoder */ - if (dev->pci_conf[0xd0] & 0x01) - dev->pci_conf[addr] = val; - break; - case 0xd3: /* Exclusive Area 2 Base Address */ - dev->pci_conf[addr] = val & 0xf0; - break; - case 0xd4: /* Miscellaneous Configuration */ - dev->pci_conf[addr] = val & 0x6e; - nvr_bank_set(0, !!(val & 0x40), dev->nvr); - break; + /* 86C497 Specific Registers (80h ~ FFh) */ + case 0x80: /* PMU Configuration */ + case 0x85: /* STPCLK# Event Control */ + case 0x86: + case 0x87: /* STPCLK# Deassertion IRQ Selection */ + case 0x89: /* Fast Timer Count */ + case 0x8a: /* Generic Timer Count */ + case 0x8b: /* Slow Timer Count */ + case 0x8e: /* Clock Throttling On Timer Count */ + case 0x8f: /* Clock Throttling Off Timer Count */ + case 0x90: /* Clock Throttling On Timer Reload Condition */ + case 0x92: /* Fast Timer Reload Condition */ + case 0x94: /* Generic Timer Reload Condition */ + case 0x96: /* Slow Timer Reload Condition */ + case 0x98: + case 0x99: /* Fast Timer Reload IRQ Selection */ + case 0x9a: + case 0x9b: /* Generic Timer Reload IRQ Selection */ + case 0x9c: + case 0x9d: /* Slow Timer Reload IRQ Selection */ + case 0xa2: /* SMI Request Status Selection */ + case 0xa4: + case 0xa5: /* SMI Request IRQ Selection */ + case 0xa6: + case 0xa7: /* Clock Throttlign On Timer Reload IRQ Selection */ + case 0xa8: /* GPIO Control */ + case 0xaa: /* GPIO DeBounce Count */ + case 0xd2: /* Exclusive Area 2 Base Address */ + dev->pci_conf[addr] = val; + break; + case 0x81: /* PMU CPU Type Configuration */ + dev->pci_conf[addr] = val & 0x9f; + break; + case 0x88: /* Timer Control */ + dev->pci_conf[addr] = val & 0x3f; + break; + case 0x8d: /* RMSMIBLK Timer Count */ + dev->pci_conf[addr] = val; + dev->rmsmiblk_count = val; + timer_stop(&dev->rmsmiblk_timer); + if (val >= 0x02) + timer_on_auto(&dev->rmsmiblk_timer, 35.0); + break; + case 0x91: /* Clock Throttling On Timer Reload Condition */ + case 0x93: /* Fast Timer Reload Condition */ + case 0x95: /* Generic Timer Reload Condition */ + dev->pci_conf[addr] = val & 0x03; + break; + case 0x97: /* Slow Timer Reload Condition */ + dev->pci_conf[addr] = val & 0xc3; + break; + case 0x9e: /* Soft-SMI Generation / RMSMIBLK Trigger */ + if (!smi_block && (val & 0x01) && (dev->pci_conf[0x80] & 0x80) && (dev->pci_conf[0xa2] & 0x10)) { + if (dev->pci_conf[0x80] & 0x10) + picint(1 << smm_irq[dev->pci_conf[0x81] & 0x03]); + else + smi_raise(); + smi_block = 1; + dev->pci_conf[0xa0] |= 0x10; + } + if (val & 0x02) { + timer_stop(&dev->rmsmiblk_timer); + if (dev->rmsmiblk_count >= 0x02) + timer_on_auto(&dev->rmsmiblk_timer, 35.0); + } + break; + case 0xa0: + case 0xa1: /* SMI Request Status */ + dev->pci_conf[addr] &= ~val; + break; + case 0xa3: /* SMI Request Status Selection */ + dev->pci_conf[addr] = val & 0x7f; + break; + case 0xa9: /* GPIO SMI Request Status */ + dev->pci_conf[addr] = ~(val & 0x03); + break; + case 0xc0: /* PCI INTA# -to-IRQ Link */ + case 0xc1: /* PCI INTB# -to-IRQ Link */ + case 0xc2: /* PCI INTC# -to-IRQ Link */ + case 0xc3: /* PCI INTD# -to-IRQ Link */ + dev->pci_conf[addr] = val & 0x8f; + if (val & 0x80) + pci_set_irq_routing(PCI_INTA + (addr & 0x03), val & 0xf); + else + pci_set_irq_routing(PCI_INTA + (addr & 0x03), PCI_IRQ_DISABLED); + break; + case 0xc6: /* 85C497 Post / INIT Configuration */ + dev->pci_conf[addr] = val & 0x0f; + break; + case 0xc8: + case 0xc9: + case 0xca: + case 0xcb: /* Mail Box */ + dev->pci_conf[addr] = val; + break; + case 0xd0: /* ISA BIOS Configuration */ + dev->pci_conf[addr] = val & 0xfb; + break; + case 0xd1: /* ISA Address Decoder */ + if (dev->pci_conf[0xd0] & 0x01) + dev->pci_conf[addr] = val; + break; + case 0xd3: /* Exclusive Area 2 Base Address */ + dev->pci_conf[addr] = val & 0xf0; + break; + case 0xd4: /* Miscellaneous Configuration */ + dev->pci_conf[addr] = val & 0x6e; + nvr_bank_set(0, !!(val & 0x40), dev->nvr); + break; + + default: + break; } } - static uint8_t -sis_85c49x_pci_read(int func, int addr, void *priv) +sis_85c49x_pci_read(UNUSED(int func), int addr, void *priv) { - sis_85c496_t *dev = (sis_85c496_t *) priv; - uint8_t ret = dev->pci_conf[addr]; + const sis_85c496_t *dev = (sis_85c496_t *) priv; + uint8_t ret = dev->pci_conf[addr]; switch (addr) { - case 0xa0: - ret &= 0x10; - break; - case 0xa1: - ret = 0x00; - break; - case 0x82: /*Port 22h Mirror*/ - ret = dev->cur_reg; - break; - case 0x83: /*Port 70h Mirror*/ - ret = inb(0x70); - break; + case 0xa0: + ret &= 0x10; + break; + case 0xa1: + ret = 0x00; + break; + case 0x82: /*Port 22h Mirror*/ + ret = dev->cur_reg; + break; + case 0x83: /*Port 70h Mirror*/ + ret = inb(0x70); + break; + + default: + break; } sis_85c496_log("[%04X:%08X] PCI Read %02X from %02X:%02X\n", CS, cpu_state.pc, ret, func, addr); return ret; } - static void sis_85c496_rmsmiblk_count(void *priv) @@ -478,14 +544,13 @@ sis_85c496_rmsmiblk_count(void *priv) dev->rmsmiblk_count--; if (dev->rmsmiblk_count == 1) { - smi_block = 0; - dev->rmsmiblk_count = 0; - timer_stop(&dev->rmsmiblk_timer); + smi_block = 0; + dev->rmsmiblk_count = 0; + timer_stop(&dev->rmsmiblk_timer); } else - timer_on_auto(&dev->rmsmiblk_timer, 35.0); + timer_on_auto(&dev->rmsmiblk_timer, 35.0); } - static void sis_85c497_isa_reset(sis_85c496_t *dev) { @@ -499,21 +564,19 @@ sis_85c497_isa_reset(sis_85c496_t *dev) dma_set_mask(0x00ffffff); io_removehandler(0x0022, 0x0002, - sis_85c497_isa_read, NULL, NULL, sis_85c497_isa_write, NULL, NULL, dev); + sis_85c497_isa_read, NULL, NULL, sis_85c497_isa_write, NULL, NULL, dev); io_removehandler(0x0033, 0x0001, - sis_85c497_isa_read, NULL, NULL, sis_85c497_isa_write, NULL, NULL, dev); + sis_85c497_isa_read, NULL, NULL, sis_85c497_isa_write, NULL, NULL, dev); io_sethandler(0x0022, 0x0002, - sis_85c497_isa_read, NULL, NULL, sis_85c497_isa_write, NULL, NULL, dev); + sis_85c497_isa_read, NULL, NULL, sis_85c497_isa_write, NULL, NULL, dev); io_sethandler(0x0033, 0x0001, - sis_85c497_isa_read, NULL, NULL, sis_85c497_isa_write, NULL, NULL, dev); + sis_85c497_isa_read, NULL, NULL, sis_85c497_isa_write, NULL, NULL, dev); } - static void sis_85c496_reset(void *priv) { sis_85c496_t *dev = (sis_85c496_t *) priv; - int i; sis_85c49x_pci_write(0, 0x44, 0x00, dev); sis_85c49x_pci_write(0, 0x45, 0x00, dev); @@ -522,8 +585,8 @@ sis_85c496_reset(void *priv) sis_85c49x_pci_write(0, 0x5a, 0x00, dev); // sis_85c49x_pci_write(0, 0x5a, 0x06, dev); - for (i = 0; i < 8; i++) - sis_85c49x_pci_write(0, 0x48 + i, 0x00, dev); + for (uint8_t i = 0; i < 8; i++) + dev->pci_conf[0x48 + i] = 0x02; sis_85c49x_pci_write(0, 0x80, 0x00, dev); sis_85c49x_pci_write(0, 0x81, 0x00, dev); @@ -553,20 +616,19 @@ sis_85c496_reset(void *priv) sis_85c497_isa_reset(dev); } - static void -sis_85c496_close(void *p) +sis_85c496_close(void *priv) { - sis_85c496_t *dev = (sis_85c496_t *)p; + sis_85c496_t *dev = (sis_85c496_t *) priv; smram_del(dev->smram); free(dev); } - static void -*sis_85c496_init(const device_t *info) + * + sis_85c496_init(const device_t *info) { sis_85c496_t *dev = malloc(sizeof(sis_85c496_t)); memset(dev, 0x00, sizeof(sis_85c496_t)); @@ -574,26 +636,28 @@ static void dev->smram = smram_add(); /* PCI Configuration Header Registers (00h ~ 3Fh) */ - dev->pci_conf[0x00] = 0x39; /* SiS */ + dev->pci_conf[0x00] = 0x39; /* SiS */ dev->pci_conf[0x01] = 0x10; - dev->pci_conf[0x02] = 0x96; /* 496/497 */ + dev->pci_conf[0x02] = 0x96; /* 496/497 */ dev->pci_conf[0x03] = 0x04; dev->pci_conf[0x04] = 0x07; dev->pci_conf[0x06] = 0x80; dev->pci_conf[0x07] = 0x02; - dev->pci_conf[0x08] = 0x02; /* Device revision */ - dev->pci_conf[0x09] = 0x00; /* Device class (PCI bridge) */ + dev->pci_conf[0x08] = 0x02; /* Device revision */ + dev->pci_conf[0x09] = 0x00; /* Device class (PCI bridge) */ dev->pci_conf[0x0b] = 0x06; /* 86C496 Specific Registers (40h ~ 7Fh) */ /* 86C497 Specific Registers (80h ~ FFh) */ - dev->pci_conf[0xd0] = 0x78; /* ROM at E0000-FFFFF, Flash enable. */ + dev->pci_conf[0xd0] = 0x78; /* ROM at E0000-FFFFF, Flash enable. */ dev->pci_conf[0xd1] = 0xff; - pci_add_card(PCI_ADD_NORTHBRIDGE, sis_85c49x_pci_read, sis_85c49x_pci_write, dev); + pci_add_card(PCI_ADD_NORTHBRIDGE, sis_85c49x_pci_read, sis_85c49x_pci_write, dev, &dev->pci_slot); - // sis_85c497_isa_reset(dev); +#if 0 + sis_85c497_isa_reset(dev); +#endif dev->port_92 = device_add(&port_92_device); port_92_set_period(dev->port_92, 2ULL * TIMER_USEC); @@ -605,47 +669,48 @@ static void ide_sec_disable(); if (info->local) - dev->nvr = device_add(&ami_1994_nvr_device); + dev->nvr = device_add(&ami_1994_nvr_device); else - dev->nvr = device_add(&at_nvr_device); + dev->nvr = device_add(&at_nvr_device); dma_high_page_init(); timer_add(&dev->rmsmiblk_timer, sis_85c496_rmsmiblk_count, dev, 0); +#ifndef USE_DRB_HACK + row_device.local = 7 | (1 << 8) | (0x02 << 16) | (8 << 24); + device_add((const device_t *) &row_device); +#endif + sis_85c496_reset(dev); return dev; } - -const device_t sis_85c496_device = -{ - "SiS 85c496/85c497", - "sis_85c496", - DEVICE_PCI, - 0, - sis_85c496_init, - sis_85c496_close, - sis_85c496_reset, - { NULL }, - NULL, - NULL, - NULL +const device_t sis_85c496_device = { + .name = "SiS 85c496/85c497", + .internal_name = "sis_85c496", + .flags = DEVICE_PCI, + .local = 0, + .init = sis_85c496_init, + .close = sis_85c496_close, + .reset = sis_85c496_reset, + { .available = NULL }, + .speed_changed = NULL, + .force_redraw = NULL, + .config = NULL }; - -const device_t sis_85c496_ls486e_device = -{ - "SiS 85c496/85c497 (Lucky Star LS-486E)", - "sis_85c496_ls486e", - DEVICE_PCI, - 1, - sis_85c496_init, - sis_85c496_close, - sis_85c496_reset, - { NULL }, - NULL, - NULL, - NULL +const device_t sis_85c496_ls486e_device = { + .name = "SiS 85c496/85c497 (Lucky Star LS-486E)", + .internal_name = "sis_85c496_ls486e", + .flags = DEVICE_PCI, + .local = 1, + .init = sis_85c496_init, + .close = sis_85c496_close, + .reset = sis_85c496_reset, + { .available = NULL }, + .speed_changed = NULL, + .force_redraw = NULL, + .config = NULL }; diff --git a/src/chipset/sis_85c4xx.c b/src/chipset/sis_85c4xx.c index c679c1dad..cf4ff42d7 100644 --- a/src/chipset/sis_85c4xx.c +++ b/src/chipset/sis_85c4xx.c @@ -1,17 +1,19 @@ /* - * 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. + * 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. + * This file is part of the 86Box distribution. * - * Emulation of the SiS 85c401/85c402, 85c460, 85c461, and - * 85c407/85c471 chipsets. + * Emulation of the SiS 85c401/85c402, 85c460, 85c461, and + * 85c407/85c471 chipsets. * - * Authors: Miran Grca, * - * Copyright 2019,2020 Miran Grca. + * + * Authors: Miran Grca, + * + * Copyright 2019-2020 Miran Grca. */ #include #include @@ -26,6 +28,7 @@ #include <86box/timer.h> #include <86box/io.h> #include <86box/device.h> +#include <86box/plat_unused.h> #include <86box/port_92.h> #include <86box/mem.h> #include <86box/smram.h> @@ -33,278 +36,315 @@ #include <86box/machine.h> #include <86box/chipset.h> - -typedef struct -{ - uint8_t cur_reg, tries, - reg_base, reg_last, - reg_00, is_471, - regs[39], scratch[2]; - uint32_t mem_state[8]; - smram_t *smram; - port_92_t *port_92; +typedef struct sis_85c4xx_t { + uint8_t cur_reg; + uint8_t tries; + uint8_t reg_base; + uint8_t reg_last; + uint8_t reg_00; + uint8_t is_471; + uint8_t force_flush; + uint8_t shadowed; + uint8_t smram_enabled; + uint8_t pad; + uint8_t regs[39]; + uint8_t scratch[2]; + uint32_t mem_state[8]; + smram_t *smram; + port_92_t *port_92; } sis_85c4xx_t; +static void +sis_85c4xx_recalcremap(sis_85c4xx_t *dev) +{ + if (dev->is_471) { + if ((mem_size > 8192) || (dev->shadowed & 0x3c) || (dev->regs[0x0b] & 0x02)) + mem_remap_top(0); + else + mem_remap_top(-256); + } +} static void sis_85c4xx_recalcmapping(sis_85c4xx_t *dev) { - uint32_t base, n = 0; - uint32_t i, shflags = 0; - uint32_t readext, writeext; - uint8_t romcs = 0xc0, cur_romcs; + uint32_t base; + uint32_t n = 0; + uint32_t shflags = 0; + uint32_t readext; + uint32_t writeext; + uint8_t romcs = 0xc0; + uint8_t cur_romcs; - shadowbios = 0; + dev->shadowed = 0x00; + + shadowbios = 0; shadowbios_write = 0; if (dev->regs[0x03] & 0x40) - romcs |= 0x01; + romcs |= 0x01; if (dev->regs[0x03] & 0x80) - romcs |= 0x30; + romcs |= 0x30; if (dev->regs[0x08] & 0x04) - romcs |= 0x02; + romcs |= 0x02; - for (i = 0; i < 8; i++) { - base = 0xc0000 + (i << 15); - cur_romcs = romcs & (1 << i); - readext = cur_romcs ? MEM_READ_EXTANY : MEM_READ_EXTERNAL; - writeext = cur_romcs ? MEM_WRITE_EXTANY : MEM_WRITE_EXTERNAL; + for (uint8_t i = 0; i < 8; i++) { + base = 0xc0000 + (i << 15); + cur_romcs = romcs & (1 << i); + readext = cur_romcs ? MEM_READ_EXTANY : MEM_READ_EXTERNAL; + writeext = cur_romcs ? MEM_WRITE_EXTANY : MEM_WRITE_EXTERNAL; - if ((i > 5) || (dev->regs[0x02] & (1 << i))) { - shadowbios |= (base >= 0xe0000) && (dev->regs[0x02] & 0x80); - shadowbios_write |= (base >= 0xe0000) && !(dev->regs[0x02] & 0x40); - shflags = (dev->regs[0x02] & 0x80) ? MEM_READ_INTERNAL : readext; - shflags |= (dev->regs[0x02] & 0x40) ? writeext : MEM_WRITE_INTERNAL; - if (dev->mem_state[i] != shflags) { - n++; - mem_set_mem_state(base, 0x8000, shflags); - if ((base >= 0xf0000) && (dev->mem_state[i] & MEM_READ_INTERNAL) && !(shflags & MEM_READ_INTERNAL)) - mem_invalidate_range(base, base + 0x7fff); - dev->mem_state[i] = shflags; - } - } else { - shflags = readext | writeext; - if (dev->mem_state[i] != shflags) { - n++; - mem_set_mem_state(base, 0x8000, shflags); - dev->mem_state[i] = shflags; - } - } + if ((i > 5) || (dev->regs[0x02] & (1 << i))) { + shadowbios |= (base >= 0xe0000) && (dev->regs[0x02] & 0x80); + shadowbios_write |= (base >= 0xe0000) && !(dev->regs[0x02] & 0x40); + shflags = (dev->regs[0x02] & 0x80) ? MEM_READ_INTERNAL : readext; + shflags |= (dev->regs[0x02] & 0x40) ? writeext : MEM_WRITE_INTERNAL; + if (dev->regs[0x02] & 0x80) + dev->shadowed |= (1 << i); + if (!(dev->regs[0x02] & 0x40)) + dev->shadowed |= (1 << i); + if (dev->force_flush || (dev->mem_state[i] != shflags)) { + n++; + mem_set_mem_state_both(base, 0x8000, shflags); + if ((base >= 0xf0000) && (dev->mem_state[i] & MEM_READ_INTERNAL) && !(shflags & MEM_READ_INTERNAL)) + mem_invalidate_range(base, base + 0x7fff); + dev->mem_state[i] = shflags; + } + } else { + shflags = readext | writeext; + if (dev->force_flush || (dev->mem_state[i] != shflags)) { + n++; + mem_set_mem_state_both(base, 0x8000, shflags); + dev->mem_state[i] = shflags; + } + } } - if (n > 0) - flushmmucache_nopc(); + if (dev->force_flush) { + flushmmucache(); + dev->force_flush = 0; + } else if (n > 0) + flushmmucache_nopc(); + + sis_85c4xx_recalcremap(dev); } - static void -sis_85c4xx_sw_smi_out(uint16_t port, uint8_t val, void *priv) +sis_85c4xx_sw_smi_out(UNUSED(uint16_t port), UNUSED(uint8_t val), void *priv) { sis_85c4xx_t *dev = (sis_85c4xx_t *) priv; if (dev->regs[0x18] & 0x02) { - if (dev->regs[0x0b] & 0x10) - smi_line = 1; - else - picint(1 << ((dev->regs[0x0b] & 0x08) ? 15 : 12)); - soft_reset_mask = 1; - dev->regs[0x19] |= 0x02; + if (dev->regs[0x0b] & 0x10) + smi_raise(); + else + picint(1 << ((dev->regs[0x0b] & 0x08) ? 15 : 12)); + soft_reset_mask = 1; + dev->regs[0x19] |= 0x02; } } - static void sis_85c4xx_sw_smi_handler(sis_85c4xx_t *dev) { uint16_t addr; if (!dev->is_471) - return; + return; addr = dev->regs[0x14] | (dev->regs[0x15] << 8); io_handler((dev->regs[0x0b] & 0x80) && (dev->regs[0x18] & 0x02), addr, 0x0001, - NULL, NULL, NULL, sis_85c4xx_sw_smi_out, NULL, NULL, dev); + NULL, NULL, NULL, sis_85c4xx_sw_smi_out, NULL, NULL, dev); } - static void sis_85c4xx_out(uint16_t port, uint8_t val, void *priv) { - sis_85c4xx_t *dev = (sis_85c4xx_t *) priv; - uint8_t rel_reg = dev->cur_reg - dev->reg_base; - uint8_t valxor = 0x00; - uint32_t host_base = 0x000e0000, ram_base = 0x000a0000; + sis_85c4xx_t *dev = (sis_85c4xx_t *) priv; + uint8_t rel_reg = dev->cur_reg - dev->reg_base; + uint8_t valxor = 0x00; + uint32_t host_base = 0x000e0000; + uint32_t ram_base = 0x000a0000; switch (port) { - case 0x22: - dev->cur_reg = val; - break; - case 0x23: - if ((dev->cur_reg >= dev->reg_base) && (dev->cur_reg <= dev->reg_last)) { - valxor = val ^ dev->regs[rel_reg]; - if (rel_reg == 0x19) - dev->regs[rel_reg] &= ~val; - else - dev->regs[rel_reg] = val; + case 0x22: + dev->cur_reg = val; + break; + case 0x23: + if ((dev->cur_reg >= dev->reg_base) && (dev->cur_reg <= dev->reg_last)) { + valxor = val ^ dev->regs[rel_reg]; + if (rel_reg == 0x19) + dev->regs[rel_reg] &= ~val; + else if (rel_reg == 0x00) + dev->regs[rel_reg] = (dev->regs[rel_reg] & 0x1f) | (val & 0xe0); + else + dev->regs[rel_reg] = val; - switch (rel_reg) { - case 0x01: - cpu_cache_ext_enabled = ((val & 0x84) == 0x84); - cpu_update_waitstates(); - break; + switch (rel_reg) { + case 0x01: + cpu_cache_ext_enabled = ((val & 0x84) == 0x84); + cpu_update_waitstates(); + break; - case 0x02: case 0x03: - case 0x08: - if (valxor) - sis_85c4xx_recalcmapping(dev); - break; + case 0x02: + case 0x03: + case 0x08: + if (valxor) + sis_85c4xx_recalcmapping(dev); + break; - case 0x0b: - sis_85c4xx_sw_smi_handler(dev); - if (dev->is_471 && (valxor & 0x02)) { - if (val & 0x02) - mem_remap_top(0); - else - mem_remap_top(256); - } - break; + case 0x0b: + sis_85c4xx_sw_smi_handler(dev); + if (valxor & 0x02) + sis_85c4xx_recalcremap(dev); + break; - case 0x13: - if (dev->is_471 && (valxor & 0xf0)) { - smram_disable(dev->smram); - host_base = (val & 0x80) ? 0x00060000 : 0x000e0000; - switch ((val >> 5) & 0x03) { - case 0x00: - ram_base = 0x000a0000; - break; - case 0x01: - ram_base = 0x000b0000; - break; - case 0x02: - ram_base = (val & 0x80) ? 0x00000000 : 0x000e0000; - break; - default: - ram_base = 0x00000000; - break; - } - if (ram_base != 0x00000000) - smram_enable(dev->smram, host_base, ram_base, 0x00010000, (val & 0x10), 1); - } - break; + case 0x13: + if (dev->is_471 && (valxor & 0xf0)) { + smram_disable(dev->smram); + host_base = (val & 0x80) ? 0x00060000 : 0x000e0000; + switch ((val >> 5) & 0x03) { + case 0x00: + ram_base = 0x000a0000; + break; + case 0x01: + ram_base = 0x000b0000; + break; + case 0x02: + ram_base = (val & 0x80) ? 0x00000000 : 0x000e0000; + break; + default: + ram_base = 0x00000000; + break; + } + dev->smram_enabled = (ram_base != 0x00000000); + if (ram_base != 0x00000000) + smram_enable(dev->smram, host_base, ram_base, 0x00010000, (val & 0x10), 1); + sis_85c4xx_recalcremap(dev); + } + break; - case 0x14: case 0x15: - case 0x18: - sis_85c4xx_sw_smi_handler(dev); - break; + case 0x14: + case 0x15: + case 0x18: + sis_85c4xx_sw_smi_handler(dev); + break; - case 0x1c: - if (dev->is_471) - soft_reset_mask = 0; - break; + case 0x1c: + if (dev->is_471) + soft_reset_mask = 0; + break; - case 0x22: - if (dev->is_471 && (valxor & 0x01)) { - port_92_remove(dev->port_92); - if (val & 0x01) - port_92_add(dev->port_92); - } - break; - } - } else if ((dev->reg_base == 0x60) && (dev->cur_reg == 0x00)) - dev->reg_00 = val; - dev->cur_reg = 0x00; - break; + case 0x22: + if (dev->is_471 && (valxor & 0x01)) { + port_92_remove(dev->port_92); + if (val & 0x01) + port_92_add(dev->port_92); + } + break; + default: + break; + } + } else if ((dev->reg_base == 0x60) && (dev->cur_reg == 0x00)) + dev->reg_00 = val; + dev->cur_reg = 0x00; + break; - case 0xe1: case 0xe2: - dev->scratch[port - 0xe1] = val; - return; + case 0xe1: + case 0xe2: + dev->scratch[port - 0xe1] = val; + return; + default: + break; } } - static uint8_t sis_85c4xx_in(uint16_t port, void *priv) { - sis_85c4xx_t *dev = (sis_85c4xx_t *) priv; - uint8_t rel_reg = dev->cur_reg - dev->reg_base; - uint8_t ret = 0xff; + sis_85c4xx_t *dev = (sis_85c4xx_t *) priv; + uint8_t rel_reg = dev->cur_reg - dev->reg_base; + uint8_t ret = 0xff; switch (port) { - case 0x23: - if (dev->is_471 && (dev->cur_reg == 0x1c)) - ret = inb(0x70); - /* On the SiS 40x, the shadow RAM read and write enable bits are write-only! */ - if ((dev->reg_base == 0x60) && (dev->cur_reg == 0x62)) - ret = dev->regs[rel_reg] & 0x3f; - else if ((dev->cur_reg >= dev->reg_base) && (dev->cur_reg <= dev->reg_last)) - ret = dev->regs[rel_reg]; - else if ((dev->reg_base == 0x60) && (dev->cur_reg == 0x00)) - ret = dev->reg_00; - if (dev->reg_base != 0x60) - dev->cur_reg = 0x00; - break; + case 0x23: + if (dev->is_471 && (dev->cur_reg == 0x1c)) + ret = inb(0x70); + /* On the SiS 40x, the shadow RAM read and write enable bits are write-only! */ + if ((dev->reg_base == 0x60) && (dev->cur_reg == 0x62)) + ret = dev->regs[rel_reg] & 0x3f; + else if ((dev->cur_reg >= dev->reg_base) && (dev->cur_reg <= dev->reg_last)) + ret = dev->regs[rel_reg]; + else if ((dev->reg_base == 0x60) && (dev->cur_reg == 0x00)) + ret = dev->reg_00; + if (dev->reg_base != 0x60) + dev->cur_reg = 0x00; + break; - case 0xe1: case 0xe2: - ret = dev->scratch[port - 0xe1]; + case 0xe1: + case 0xe2: + ret = dev->scratch[port - 0xe1]; + break; + + default: + break; } return ret; } - static void sis_85c4xx_reset(void *priv) { - sis_85c4xx_t *dev = (sis_85c4xx_t *) priv; - int mem_size_mb = mem_size >> 10; + sis_85c4xx_t *dev = (sis_85c4xx_t *) priv; + int mem_size_mb = mem_size >> 10; static uint8_t ram_4xx[64] = { 0x00, 0x00, 0x01, 0x00, 0x02, 0x00, 0x03, 0x00, 0x04, 0x00, 0x05, 0x00, 0x0b, 0x00, 0x00, 0x00, - 0x19, 0x00, 0x06, 0x00, 0x14, 0x00, 0x00, 0x00, 0x15, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x1b, 0x00, 0x00, 0x00, 0x16, 0x00, 0x00, 0x00, 0x17, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x1e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }; + 0x19, 0x00, 0x06, 0x00, 0x14, 0x00, 0x00, 0x00, 0x15, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x1b, 0x00, 0x00, 0x00, 0x16, 0x00, 0x00, 0x00, 0x17, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x1e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }; static uint8_t ram_471[64] = { 0x00, 0x00, 0x01, 0x01, 0x02, 0x20, 0x09, 0x09, 0x04, 0x04, 0x05, 0x05, 0x0b, 0x0b, 0x0b, 0x0b, - 0x13, 0x21, 0x06, 0x06, 0x0d, 0x0d, 0x0d, 0x0d, 0x0e, 0x0e, 0x0e, 0x0e, 0x0e, 0x0e, 0x0e, 0x0e, - 0x1b, 0x1b, 0x1b, 0x1b, 0x0f, 0x0f, 0x0f, 0x0f, 0x17, 0x17, 0x17, 0x17, 0x17, 0x17, 0x17, 0x17, - 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e }; + 0x13, 0x21, 0x06, 0x06, 0x0d, 0x0d, 0x0d, 0x0d, 0x0e, 0x0e, 0x0e, 0x0e, 0x0e, 0x0e, 0x0e, 0x0e, + 0x1b, 0x1b, 0x1b, 0x1b, 0x0f, 0x0f, 0x0f, 0x0f, 0x17, 0x17, 0x17, 0x17, 0x17, 0x17, 0x17, 0x17, + 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e }; memset(dev->regs, 0x00, sizeof(dev->regs)); if (cpu_s->rspeed < 25000000) - dev->regs[0x08] = 0x80; + dev->regs[0x08] = 0x80; if (dev->is_471) { - dev->regs[0x09] = 0x40; - if (mem_size_mb >= 64) { - if ((mem_size_mb >= 65) && (mem_size_mb < 68)) - dev->regs[0x09] |= 0x22; - else - dev->regs[0x09] |= 0x24; - } else - dev->regs[0x09] |= ram_471[mem_size_mb]; + dev->regs[0x09] = 0x40; + if (mem_size_mb >= 64) { + if ((mem_size_mb >= 65) && (mem_size_mb < 68)) + dev->regs[0x09] |= 0x22; + else + dev->regs[0x09] |= 0x24; + } else + dev->regs[0x09] |= ram_471[mem_size_mb]; - dev->regs[0x11] = 0x09; - dev->regs[0x12] = 0xff; - dev->regs[0x1f] = 0x20; /* Video access enabled. */ - dev->regs[0x23] = 0xf0; - dev->regs[0x26] = 0x01; + dev->regs[0x11] = 0x09; + dev->regs[0x12] = 0xff; + dev->regs[0x1f] = 0x20; /* Video access enabled. */ + dev->regs[0x23] = 0xf0; + dev->regs[0x26] = 0x01; - smram_enable(dev->smram, 0x000e0000, 0x000a0000, 0x00010000, 0, 1); + smram_enable(dev->smram, 0x000e0000, 0x000a0000, 0x00010000, 0, 1); - port_92_remove(dev->port_92); + port_92_remove(dev->port_92); - mem_remap_top(256); - soft_reset_mask = 0; + soft_reset_mask = 0; } else { - /* Bits 6 and 7 must be clear on the SiS 40x. */ - if (dev->reg_base == 0x60) - dev->reg_00 = 0x24; + /* Bits 6 and 7 must be clear on the SiS 40x. */ + if (dev->reg_base == 0x60) + dev->reg_00 = 0x24; - if (mem_size_mb == 64) - dev->regs[0x00] = 0x1f; - else if (mem_size_mb < 64) - dev->regs[0x00] = ram_4xx[mem_size_mb]; + if (mem_size_mb == 64) + dev->regs[0x00] = 0x1f; + else if (mem_size_mb < 64) + dev->regs[0x00] = ram_4xx[mem_size_mb]; - dev->regs[0x11] = 0x01; + dev->regs[0x11] = 0x01; } dev->scratch[0] = dev->scratch[1] = 0xff; @@ -312,22 +352,21 @@ sis_85c4xx_reset(void *priv) cpu_cache_ext_enabled = 0; cpu_update_waitstates(); + dev->force_flush = 1; sis_85c4xx_recalcmapping(dev); } - static void sis_85c4xx_close(void *priv) { sis_85c4xx_t *dev = (sis_85c4xx_t *) priv; if (dev->is_471) - smram_del(dev->smram); + smram_del(dev->smram); free(dev); } - static void * sis_85c4xx_init(const device_t *info) { @@ -339,63 +378,78 @@ sis_85c4xx_init(const device_t *info) dev->reg_base = info->local & 0xff; if (dev->is_471) { - dev->reg_last = dev->reg_base + 0x76; + dev->reg_last = dev->reg_base + 0x76; - dev->smram = smram_add(); + dev->smram = smram_add(); - dev->port_92 = device_add(&port_92_device); + dev->port_92 = device_add(&port_92_device); } else - dev->reg_last = dev->reg_base + 0x11; + dev->reg_last = dev->reg_base + 0x11; io_sethandler(0x0022, 0x0002, - sis_85c4xx_in, NULL, NULL, sis_85c4xx_out, NULL, NULL, dev); + sis_85c4xx_in, NULL, NULL, sis_85c4xx_out, NULL, NULL, dev); io_sethandler(0x00e1, 0x0002, - sis_85c4xx_in, NULL, NULL, sis_85c4xx_out, NULL, NULL, dev); + sis_85c4xx_in, NULL, NULL, sis_85c4xx_out, NULL, NULL, dev); sis_85c4xx_reset(dev); return dev; } - const device_t sis_85c401_device = { - "SiS 85c401/85c402", - "sis_85c401", - 0, - 0x060, - sis_85c4xx_init, sis_85c4xx_close, sis_85c4xx_reset, - { NULL }, NULL, NULL, - NULL + .name = "SiS 85c401/85c402", + .internal_name = "sis_85c401", + .flags = 0, + .local = 0x060, + .init = sis_85c4xx_init, + .close = sis_85c4xx_close, + .reset = sis_85c4xx_reset, + { .available = NULL }, + .speed_changed = NULL, + .force_redraw = NULL, + .config = NULL }; const device_t sis_85c460_device = { - "SiS 85c460", - "sis_85c460", - 0, - 0x050, - sis_85c4xx_init, sis_85c4xx_close, sis_85c4xx_reset, - { NULL }, NULL, NULL, - NULL + .name = "SiS 85c460", + .internal_name = "sis_85c460", + .flags = 0, + .local = 0x050, + .init = sis_85c4xx_init, + .close = sis_85c4xx_close, + .reset = sis_85c4xx_reset, + { .available = NULL }, + .speed_changed = NULL, + .force_redraw = NULL, + .config = NULL }; /* TODO: Log to make sure the registers are correct. */ const device_t sis_85c461_device = { - "SiS 85c461", - "sis_85c461", - 0, - 0x050, - sis_85c4xx_init, sis_85c4xx_close, sis_85c4xx_reset, - { NULL }, NULL, NULL, - NULL + .name = "SiS 85c461", + .internal_name = "sis_85c461", + .flags = 0, + .local = 0x050, + .init = sis_85c4xx_init, + .close = sis_85c4xx_close, + .reset = sis_85c4xx_reset, + { .available = NULL }, + .speed_changed = NULL, + .force_redraw = NULL, + .config = NULL }; const device_t sis_85c471_device = { - "SiS 85c407/85c471", - "sis_85c471", - 0, - 0x150, - sis_85c4xx_init, sis_85c4xx_close, sis_85c4xx_reset, - { NULL }, NULL, NULL, - NULL + .name = "SiS 85c407/85c471", + .internal_name = "sis_85c471", + .flags = 0, + .local = 0x150, + .init = sis_85c4xx_init, + .close = sis_85c4xx_close, + .reset = sis_85c4xx_reset, + { .available = NULL }, + .speed_changed = NULL, + .force_redraw = NULL, + .config = NULL }; diff --git a/src/chipset/sis_85c50x.c b/src/chipset/sis_85c50x.c index 5bbe99f1d..7f4aebb7c 100644 --- a/src/chipset/sis_85c50x.c +++ b/src/chipset/sis_85c50x.c @@ -1,20 +1,20 @@ /* - * 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. + * 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. + * This file is part of the 86Box distribution. * - * Implementation of the SiS 85C50x Chipset. + * Implementation of the SiS 85C50x Chipset. * * * - * Authors: Tiseno100, - * Miran Grca, + * Authors: Tiseno100, + * Miran Grca, * - * Copyright 2020,2021 Tiseno100. - * Copyright 2020,2021 Miran Grca. + * Copyright 2020-2021 Tiseno100. + * Copyright 2020-2021 Miran Grca. */ #include #include @@ -29,6 +29,9 @@ #include <86box/timer.h> #include <86box/apm.h> +#include <86box/machine.h> +#include <86box/pic.h> +#include <86box/plat_unused.h> #include <86box/mem.h> #include <86box/smram.h> #include <86box/pci.h> @@ -36,285 +39,337 @@ #include <86box/chipset.h> - #ifdef ENABLE_SIS_85C50X_LOG int sis_85c50x_do_log = ENABLE_SIS_85C50X_LOG; + static void sis_85c50x_log(const char *fmt, ...) { va_list ap; if (sis_85c50x_do_log) { - va_start(ap, fmt); - pclog_ex(fmt, ap); - va_end(ap); + va_start(ap, fmt); + pclog_ex(fmt, ap); + va_end(ap); } } #else -#define sis_85c50x_log(fmt, ...) +# define sis_85c50x_log(fmt, ...) #endif +typedef struct sis_85c50x_t { + uint8_t index; + uint8_t nb_slot; + uint8_t sb_slot; + uint8_t pad; -typedef struct sis_85c50x_t -{ - uint8_t index, - pci_conf[256], pci_conf_sb[256], - regs[256]; + uint8_t pci_conf[256]; + uint8_t pci_conf_sb[256]; + uint8_t regs[256]; - smram_t * smram; - port_92_t * port_92; + smram_t *smram[2]; + port_92_t *port_92; } sis_85c50x_t; - static void sis_85c50x_shadow_recalc(sis_85c50x_t *dev) { - uint32_t base, i, can_read, can_write; + uint32_t base; + uint32_t can_read; + uint32_t can_write; - can_read = (dev->pci_conf[0x53] & 0x40) ? MEM_READ_INTERNAL : MEM_READ_EXTANY; + can_read = (dev->pci_conf[0x53] & 0x40) ? MEM_READ_INTERNAL : MEM_READ_EXTANY; can_write = (dev->pci_conf[0x53] & 0x20) ? MEM_WRITE_EXTANY : MEM_WRITE_INTERNAL; if (!can_read) - can_write = MEM_WRITE_EXTANY; + can_write = MEM_WRITE_EXTANY; mem_set_mem_state_both(0xf0000, 0x10000, can_read | can_write); - shadowbios = 1; + shadowbios = 1; shadowbios_write = 1; - for (i = 0; i < 4; i++) { - base = 0xe0000 + (i << 14); - mem_set_mem_state_both(base, 0x4000, (dev->pci_conf[0x54] & (1 << (7 - i))) ? (can_read | can_write) : (MEM_READ_EXTANY | MEM_WRITE_EXTANY)); - base = 0xd0000 + (i << 14); - mem_set_mem_state_both(base, 0x4000, (dev->pci_conf[0x55] & (1 << (7 - i))) ? (can_read | can_write) : (MEM_READ_EXTANY | MEM_WRITE_EXTANY)); - base = 0xc0000 + (i << 14); - mem_set_mem_state_both(base, 0x4000, (dev->pci_conf[0x56] & (1 << (7 - i))) ? (can_read | can_write) : (MEM_READ_EXTANY | MEM_WRITE_EXTANY)); + for (uint8_t i = 0; i < 4; i++) { + base = 0xe0000 + (i << 14); + mem_set_mem_state_both(base, 0x4000, (dev->pci_conf[0x54] & (1 << (7 - i))) ? (can_read | can_write) : (MEM_READ_EXTANY | MEM_WRITE_EXTANY)); + base = 0xd0000 + (i << 14); + mem_set_mem_state_both(base, 0x4000, (dev->pci_conf[0x55] & (1 << (7 - i))) ? (can_read | can_write) : (MEM_READ_EXTANY | MEM_WRITE_EXTANY)); + base = 0xc0000 + (i << 14); + mem_set_mem_state_both(base, 0x4000, (dev->pci_conf[0x56] & (1 << (7 - i))) ? (can_read | can_write) : (MEM_READ_EXTANY | MEM_WRITE_EXTANY)); } flushmmucache_nopc(); } - static void sis_85c50x_smm_recalc(sis_85c50x_t *dev) { /* NOTE: Naming mismatch - what the datasheet calls "host address" is what we call ram_base. */ - uint32_t ram_base = (dev->pci_conf[0x64] << 20) | - ((dev->pci_conf[0x65] & 0x07) << 28); + uint32_t host_base = (dev->pci_conf[0x64] << 20) | ((dev->pci_conf[0x65] & 0x07) << 28); - smram_disable(dev->smram); + smram_disable_all(); - if ((((dev->pci_conf[0x65] & 0xe0) >> 5) != 0x00) && (ram_base == 0x00000000)) - return; + if ((((dev->pci_conf[0x65] & 0xe0) >> 5) != 0x00) && (host_base == 0x00000000)) + return; switch ((dev->pci_conf[0x65] & 0xe0) >> 5) { - case 0x00: - smram_enable(dev->smram, 0xe0000, 0xe0000, 0x8000, (dev->pci_conf[0x65] & 0x10), 1); - break; - case 0x01: - smram_enable(dev->smram, 0xb0000, ram_base, 0x10000, (dev->pci_conf[0x65] & 0x10), 1); - break; - case 0x02: - smram_enable(dev->smram, 0xa0000, ram_base, 0x10000, (dev->pci_conf[0x65] & 0x10), 1); - break; - case 0x04: - smram_enable(dev->smram, 0xa0000, ram_base, 0x8000, (dev->pci_conf[0x65] & 0x10), 1); - break; - case 0x06: - smram_enable(dev->smram, 0xb0000, ram_base, 0x8000, (dev->pci_conf[0x65] & 0x10), 1); - break; + case 0x00: + sis_85c50x_log("SiS 50x SMRAM: 000E0000-000E7FFF -> 000E0000-000E7FFF\n"); + smram_enable(dev->smram[0], 0xe0000, 0xe0000, 0x8000, (dev->pci_conf[0x65] & 0x10), 1); + break; + case 0x01: + host_base |= 0x000b0000; + sis_85c50x_log("SiS 50x SMRAM: %08X-%08X -> 000B0000-000BFFFF\n", host_base, host_base + 0x10000 - 1); + smram_enable(dev->smram[0], host_base, 0xb0000, 0x10000, (dev->pci_conf[0x65] & 0x10), 1); + smram_enable(dev->smram[1], host_base ^ 0x00100000, 0xb0000, 0x10000, (dev->pci_conf[0x65] & 0x10), 1); + break; + case 0x02: + host_base |= 0x000a0000; + sis_85c50x_log("SiS 50x SMRAM: %08X-%08X -> 000A0000-000AFFFF\n", host_base, host_base + 0x10000 - 1); + smram_enable(dev->smram[0], host_base, 0xa0000, 0x10000, (dev->pci_conf[0x65] & 0x10), 1); + smram_enable(dev->smram[1], host_base ^ 0x00100000, 0xa0000, 0x10000, (dev->pci_conf[0x65] & 0x10), 1); + break; + case 0x04: + host_base |= 0x000a0000; + sis_85c50x_log("SiS 50x SMRAM: %08X-%08X -> 000A0000-000AFFFF\n", host_base, host_base + 0x8000 - 1); + smram_enable(dev->smram[0], host_base, 0xa0000, 0x8000, (dev->pci_conf[0x65] & 0x10), 1); + smram_enable(dev->smram[1], host_base ^ 0x00100000, 0xa0000, 0x8000, (dev->pci_conf[0x65] & 0x10), 1); + break; + case 0x06: + host_base |= 0x000b0000; + sis_85c50x_log("SiS 50x SMRAM: %08X-%08X -> 000B0000-000BFFFF\n", host_base, host_base + 0x8000 - 1); + smram_enable(dev->smram[0], host_base, 0xb0000, 0x8000, (dev->pci_conf[0x65] & 0x10), 1); + smram_enable(dev->smram[1], host_base ^ 0x00100000, 0xa0000, 0x8000, (dev->pci_conf[0x65] & 0x10), 1); + break; + default: + break; } } - static void sis_85c50x_write(int func, int addr, uint8_t val, void *priv) { - sis_85c50x_t *dev = (sis_85c50x_t *)priv; - uint8_t valxor = (val ^ dev->pci_conf[addr]); + sis_85c50x_t *dev = (sis_85c50x_t *) priv; - switch (addr) { - case 0x04: /* Command - low byte */ - dev->pci_conf[addr] = (dev->pci_conf[addr] & 0xb4) | (val & 0x4b); - break; - case 0x07: /* Status - high byte */ - dev->pci_conf[addr] = ((dev->pci_conf[addr] & 0xf9) & ~(val & 0xf8)) | (val & 0x06); - break; - case 0x50: - dev->pci_conf[addr] = val; - break; - case 0x51: /* Cache */ - dev->pci_conf[addr] = val; - cpu_cache_ext_enabled = (val & 0x40); - cpu_update_waitstates(); - break; - case 0x52: - dev->pci_conf[addr] = val; - break; - case 0x53: /* Shadow RAM */ - case 0x54: - case 0x55: - case 0x56: - dev->pci_conf[addr] = val; - sis_85c50x_shadow_recalc(dev); - if (addr == 0x54) - sis_85c50x_smm_recalc(dev); - break; - case 0x57: case 0x58: case 0x59: case 0x5a: - case 0x5c: case 0x5d: case 0x5e: case 0x61: - case 0x62: case 0x63: case 0x67: case 0x68: - case 0x6a: case 0x6b: case 0x6c: case 0x6d: - case 0x6e: case 0x6f: - dev->pci_conf[addr] = val; - break; - case 0x5f: - dev->pci_conf[addr] = val & 0xfe; - break; - case 0x5b: - dev->pci_conf[addr] = val; - if (valxor & 0xc0) - port_92_set_features(dev->port_92, !!(val & 0x40), !!(val & 0x80)); - break; - case 0x60: /* SMI */ - if ((dev->pci_conf[0x68] & 0x01) && !(dev->pci_conf[addr] & 0x02) && (val & 0x02)) { - dev->pci_conf[0x69] |= 0x01; - smi_line = 1; - } - dev->pci_conf[addr] = val & 0x3e; - break; - case 0x64: /* SMRAM */ - case 0x65: - dev->pci_conf[addr] = val; - sis_85c50x_smm_recalc(dev); - break; - case 0x66: - dev->pci_conf[addr] = (val & 0x7f); - break; - case 0x69: - dev->pci_conf[addr] &= ~(val); - break; - } + sis_85c50x_log("85C501: [W] (%02X, %02X) = %02X\n", func, addr, val); - sis_85c50x_log("85C501: dev->pci_conf[%02x] = %02x\n", addr, val); + if (func == 0x00) + switch (addr) { + case 0x04: /* Command - low byte */ + dev->pci_conf[addr] = (dev->pci_conf[addr] & 0xb4) | (val & 0x4b); + break; + case 0x07: /* Status - high byte */ + dev->pci_conf[addr] = ((dev->pci_conf[addr] & 0xf9) & ~(val & 0xf8)) | (val & 0x06); + break; + case 0x50: + dev->pci_conf[addr] = val; + break; + case 0x51: /* Cache */ + dev->pci_conf[addr] = val; + cpu_cache_ext_enabled = (val & 0x40); + cpu_update_waitstates(); + break; + case 0x52: + dev->pci_conf[addr] = val; + break; + case 0x53: /* Shadow RAM */ + case 0x54: + case 0x55: + case 0x56: + dev->pci_conf[addr] = val; + sis_85c50x_shadow_recalc(dev); + if (addr == 0x54) + sis_85c50x_smm_recalc(dev); + break; + case 0x57: + case 0x58: + case 0x59: + case 0x5a: + case 0x5c: + case 0x5d: + case 0x5e: + case 0x61: + case 0x62: + case 0x63: + case 0x67: + case 0x68: + case 0x6a: + case 0x6b: + case 0x6c: + case 0x6d: + case 0x6e: + case 0x6f: + dev->pci_conf[addr] = val; + break; + case 0x5f: + dev->pci_conf[addr] = val & 0xfe; + break; + case 0x5b: + dev->pci_conf[addr] = val; + break; + case 0x60: /* SMI */ + if ((dev->pci_conf[0x68] & 0x01) && !(dev->pci_conf[addr] & 0x02) && (val & 0x02)) { + dev->pci_conf[0x69] |= 0x01; + smi_raise(); + } + dev->pci_conf[addr] = val & 0x3e; + break; + case 0x64: /* SMRAM */ + case 0x65: + dev->pci_conf[addr] = val; + sis_85c50x_smm_recalc(dev); + break; + case 0x66: + dev->pci_conf[addr] = (val & 0x7f); + break; + case 0x69: + dev->pci_conf[addr] &= ~val; + break; + + default: + break; + } } - static uint8_t sis_85c50x_read(int func, int addr, void *priv) { - sis_85c50x_t *dev = (sis_85c50x_t *)priv; + const sis_85c50x_t *dev = (sis_85c50x_t *) priv; + uint8_t ret = 0xff; - sis_85c50x_log("85C501: dev->pci_conf[%02x] (%02x)\n", addr, dev->pci_conf[addr]); + if (func == 0x00) + ret = dev->pci_conf[addr]; - return dev->pci_conf[addr]; -} - - -static void -sis_85c50x_sb_write(int func, int addr, uint8_t val, void *priv) -{ - sis_85c50x_t *dev = (sis_85c50x_t *)priv; - - switch (addr) { - case 0x04: /* Command */ - dev->pci_conf_sb[addr] = val & 0x0f; - break; - case 0x07: /* Status */ - dev->pci_conf_sb[addr] &= ~(val & 0x30); - break; - case 0x40: /* BIOS Control Register */ - dev->pci_conf_sb[addr] = val & 0x3f; - break; - case 0x41: case 0x42: case 0x43: case 0x44: - /* INTA/B/C/D# Remapping Control Register */ - dev->pci_conf_sb[addr] = val & 0x8f; - if (val & 0x80) - pci_set_irq_routing(PCI_INTA + (addr - 0x41), PCI_IRQ_DISABLED); - else - pci_set_irq_routing(PCI_INTA + (addr - 0x41), val & 0xf); - break; - case 0x48: /* ISA Master/DMA Memory Cycle Control Register 1 */ - case 0x49: /* ISA Master/DMA Memory Cycle Control Register 2 */ - case 0x4a: /* ISA Master/DMA Memory Cycle Control Register 3 */ - case 0x4b: /* ISA Master/DMA Memory Cycle Control Register 4 */ - dev->pci_conf_sb[addr] = val; - break; - } - - sis_85c50x_log("85C503: dev->pci_conf_sb[%02x] = %02x\n", addr, val); -} - - -static uint8_t -sis_85c50x_sb_read(int func, int addr, void *priv) -{ - sis_85c50x_t *dev = (sis_85c50x_t *)priv; - sis_85c50x_log("85C503: dev->pci_conf_sb[%02x] (%02x)\n", addr, dev->pci_conf_sb[addr]); - - return dev->pci_conf_sb[addr]; -} - - -static void -sis_85c50x_isa_write(uint16_t addr, uint8_t val, void *priv) -{ - sis_85c50x_t *dev = (sis_85c50x_t *)priv; - - switch (addr) { - case 0x22: - dev->index = val; - break; - - case 0x23: - switch (dev->index) { - case 0x80: - dev->regs[dev->index] = val & 0xe7; - break; - case 0x81: - dev->regs[dev->index] = val & 0xf4; - break; - case 0x84: case 0x88: case 0x9: case 0x8a: - case 0x8b: - dev->regs[dev->index] = val; - break; - case 0x85: - outb(0x70, val); - break; - } - break; - } - - sis_85c50x_log("85C501-ISA: dev->regs[%02x] = %02x\n", addr, val); -} - - -static uint8_t -sis_85c50x_isa_read(uint16_t addr, void *priv) -{ - sis_85c50x_t *dev = (sis_85c50x_t *)priv; - uint8_t ret = 0xff; - - switch (addr) { - case 0x22: - ret = dev->index; - break; - - case 0x23: - if (dev->index == 0x85) - ret = inb(0x70); - else - ret = dev->regs[dev->index]; - break; - } - - sis_85c50x_log("85C501-ISA: dev->regs[%02x] (%02x)\n", dev->index, ret); + sis_85c50x_log("85C501: [R] (%02X, %02X) = %02X\n", func, addr, ret); return ret; } +static void +sis_85c50x_sb_write(int func, int addr, uint8_t val, void *priv) +{ + sis_85c50x_t *dev = (sis_85c50x_t *) priv; + + sis_85c50x_log("85C503: [W] (%02X, %02X) = %02X\n", func, addr, val); + + if (func == 0x00) + switch (addr) { + case 0x04: /* Command */ + dev->pci_conf_sb[addr] = val & 0x0f; + break; + case 0x07: /* Status */ + dev->pci_conf_sb[addr] &= ~(val & 0x30); + break; + case 0x40: /* BIOS Control Register */ + dev->pci_conf_sb[addr] = val & 0x3f; + break; + case 0x41: + case 0x42: + case 0x43: + case 0x44: + /* INTA/B/C/D# Remapping Control Register */ + dev->pci_conf_sb[addr] = val & 0x8f; + if (val & 0x80) + pci_set_irq_routing(PCI_INTA + (addr - 0x41), PCI_IRQ_DISABLED); + else + pci_set_irq_routing(PCI_INTA + (addr - 0x41), val & 0xf); + break; + case 0x48: /* ISA Master/DMA Memory Cycle Control Register 1 */ + case 0x49: /* ISA Master/DMA Memory Cycle Control Register 2 */ + case 0x4a: /* ISA Master/DMA Memory Cycle Control Register 3 */ + case 0x4b: /* ISA Master/DMA Memory Cycle Control Register 4 */ + dev->pci_conf_sb[addr] = val; + break; + + default: + break; + } +} + +static uint8_t +sis_85c50x_sb_read(int func, int addr, void *priv) +{ + const sis_85c50x_t *dev = (sis_85c50x_t *) priv; + uint8_t ret = 0xff; + + if (func == 0x00) + ret = dev->pci_conf_sb[addr]; + + sis_85c50x_log("85C503: [W] (%02X, %02X) = %02X\n", func, addr, ret); + + return ret; +} + +static void +sis_85c50x_isa_write(uint16_t addr, uint8_t val, void *priv) +{ + sis_85c50x_t *dev = (sis_85c50x_t *) priv; + + sis_85c50x_log("85C503 ISA: [W] (%04X) = %02X\n", addr, val); + + switch (addr) { + case 0x22: + dev->index = val; + break; + + case 0x23: + switch (dev->index) { + case 0x80: + dev->regs[dev->index] = val & 0xe7; + break; + case 0x81: + dev->regs[dev->index] = val & 0xf4; + break; + case 0x84: + case 0x88: + case 0x89: + case 0x8a: + case 0x8b: + dev->regs[dev->index] = val; + break; + case 0x85: + outb(0x70, val); + break; + + default: + break; + } + break; + + default: + break; + } +} + +static uint8_t +sis_85c50x_isa_read(uint16_t addr, void *priv) +{ + const sis_85c50x_t *dev = (sis_85c50x_t *) priv; + uint8_t ret = 0xff; + + switch (addr) { + case 0x22: + ret = dev->index; + break; + + case 0x23: + if (dev->index == 0x85) + ret = inb(0x70); + else + ret = dev->regs[dev->index]; + break; + + default: + break; + } + + sis_85c50x_log("85C503 ISA: [R] (%04X) = %02X\n", addr, ret); + + return ret; +} static void sis_85c50x_reset(void *priv) { - sis_85c50x_t *dev = (sis_85c50x_t *)priv; + sis_85c50x_t *dev = (sis_85c50x_t *) priv; /* North Bridge (SiS 85C501/502) */ dev->pci_conf[0x00] = 0x39; @@ -352,37 +407,38 @@ sis_85c50x_reset(void *priv) dev->pci_conf_sb[0x09] = 0x00; dev->pci_conf_sb[0x0a] = 0x01; dev->pci_conf_sb[0x0b] = 0x06; - sis_85c50x_write(0, 0x41, 0x80, dev); - sis_85c50x_write(0, 0x42, 0x80, dev); - sis_85c50x_write(0, 0x43, 0x80, dev); - sis_85c50x_write(0, 0x44, 0x80, dev); + sis_85c50x_sb_write(0, 0x41, 0x80, dev); + sis_85c50x_sb_write(0, 0x42, 0x80, dev); + sis_85c50x_sb_write(0, 0x43, 0x80, dev); + sis_85c50x_sb_write(0, 0x44, 0x80, dev); } - static void sis_85c50x_close(void *priv) { - sis_85c50x_t *dev = (sis_85c50x_t *)priv; + sis_85c50x_t *dev = (sis_85c50x_t *) priv; - smram_del(dev->smram); + smram_del(dev->smram[1]); + smram_del(dev->smram[0]); free(dev); } - static void * -sis_85c50x_init(const device_t *info) +sis_85c50x_init(UNUSED(const device_t *info)) { - sis_85c50x_t *dev = (sis_85c50x_t *)malloc(sizeof(sis_85c50x_t)); + sis_85c50x_t *dev = (sis_85c50x_t *) malloc(sizeof(sis_85c50x_t)); memset(dev, 0x00, sizeof(sis_85c50x_t)); /* 501/502 (Northbridge) */ - pci_add_card(PCI_ADD_NORTHBRIDGE, sis_85c50x_read, sis_85c50x_write, dev); + pci_add_card(PCI_ADD_NORTHBRIDGE, sis_85c50x_read, sis_85c50x_write, dev, &dev->nb_slot); /* 503 (Southbridge) */ - pci_add_card(PCI_ADD_SOUTHBRIDGE, sis_85c50x_sb_read, sis_85c50x_sb_write, dev); + pci_add_card(PCI_ADD_SOUTHBRIDGE, sis_85c50x_sb_read, sis_85c50x_sb_write, dev, &dev->sb_slot); io_sethandler(0x0022, 0x0002, sis_85c50x_isa_read, NULL, NULL, sis_85c50x_isa_write, NULL, NULL, dev); - dev->smram = smram_add(); + dev->smram[0] = smram_add(); + dev->smram[1] = smram_add(); + dev->port_92 = device_add(&port_92_device); sis_85c50x_reset(dev); @@ -390,14 +446,16 @@ sis_85c50x_init(const device_t *info) return dev; } - const device_t sis_85c50x_device = { - "SiS 85C50x", - "sis_85c50x", - DEVICE_PCI, - 0, - sis_85c50x_init, sis_85c50x_close, - sis_85c50x_reset, { NULL }, - NULL, NULL, - NULL + .name = "SiS 85C50x", + .internal_name = "sis_85c50x", + .flags = DEVICE_PCI, + .local = 0, + .init = sis_85c50x_init, + .close = sis_85c50x_close, + .reset = sis_85c50x_reset, + { .available = NULL }, + .speed_changed = NULL, + .force_redraw = NULL, + .config = NULL }; diff --git a/src/chipset/stpc.c b/src/chipset/stpc.c index 6e7067ebc..dbe39ec5c 100644 --- a/src/chipset/stpc.c +++ b/src/chipset/stpc.c @@ -1,18 +1,18 @@ /* - * 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. + * 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. + * This file is part of the 86Box distribution. * - * Implementation of the STMicroelectronics STPC series of SoCs. + * Implementation of the STMicroelectronics STPC series of SoCs. * * * - * Authors: RichardG, + * Authors: RichardG, * - * Copyright 2020 RichardG. + * Copyright 2020 RichardG. */ #include #include @@ -30,6 +30,7 @@ #include <86box/timer.h> #include <86box/pit.h> #include <86box/device.h> +#include <86box/plat_unused.h> #include <86box/port_92.h> #include <86box/usb.h> #include <86box/hdc_ide.h> @@ -38,122 +39,119 @@ #include <86box/lpt.h> #include <86box/chipset.h> +#define STPC_CONSUMER2 0x104a020b +#define STPC_ATLAS 0x104a0210 +#define STPC_ELITE 0x104a021a +#define STPC_CLIENT 0x100e55cc -#define STPC_CONSUMER2 0x104a020b -#define STPC_ATLAS 0x104a0210 -#define STPC_ELITE 0x104a021a -#define STPC_CLIENT 0x100e55cc +typedef struct stpc_t { + uint8_t nb_slot; + uint8_t sb_slot; + uint8_t ide_slot; + uint8_t usb_slot; - -typedef struct stpc_t -{ - uint32_t local; + uint32_t local; /* Main registers (port 22h/23h) */ - uint8_t reg_offset; - uint8_t regs[256]; + uint8_t reg_offset; + uint8_t regs[256]; /* Host bus interface */ - uint16_t host_base; - uint8_t host_offset; - uint8_t host_regs[256]; + uint16_t host_base; + uint8_t host_offset; + uint8_t usb_irq_state; + uint8_t host_regs[256]; /* Local bus */ - uint16_t localbus_base; - uint8_t localbus_offset; - uint8_t localbus_regs[256]; + uint16_t localbus_base; + uint8_t localbus_offset; + uint8_t pad0; + uint8_t localbus_regs[256]; /* PCI devices */ - uint8_t pci_conf[4][256]; - smram_t *smram; - usb_t *usb; - int ide_slot; - sff8038i_t *bm[2]; + uint8_t pci_conf[4][256]; + smram_t *smram; + usb_t *usb; + sff8038i_t *bm[2]; } stpc_t; -typedef struct stpc_serial_t -{ - serial_t *uart[2]; +typedef struct stpc_serial_t { + serial_t *uart[2]; } stpc_serial_t; -typedef struct stpc_lpt_t -{ - uint8_t unlocked; - uint8_t offset; - uint8_t reg1; - uint8_t reg4; +typedef struct stpc_lpt_t { + uint8_t unlocked; + uint8_t offset; + uint8_t reg1; + uint8_t reg4; } stpc_lpt_t; - #ifdef ENABLE_STPC_LOG int stpc_do_log = ENABLE_STPC_LOG; - static void stpc_log(const char *fmt, ...) { va_list ap; if (stpc_do_log) { - va_start(ap, fmt); - pclog_ex(fmt, ap); - va_end(ap); + va_start(ap, fmt); + pclog_ex(fmt, ap); + va_end(ap); } } #else -#define stpc_log(fmt, ...) +# define stpc_log(fmt, ...) #endif - static void stpc_recalcmapping(stpc_t *dev) { - uint8_t reg, bitpair; - uint32_t base, size; - int state; + uint32_t base; + uint32_t size; + int state; - shadowbios = 0; + shadowbios = 0; shadowbios_write = 0; - for (reg = 0; reg <= 3; reg++) { - for (bitpair = 0; bitpair <= ((reg == 3) ? 0 : 3); bitpair++) { - if (reg == 3) { - size = 0x10000; - base = 0xf0000; - } else { - size = 0x4000; - base = 0xc0000 + (size * ((reg * 4) + bitpair)); - } - stpc_log("STPC: Shadowing for %05X-%05X (reg %02X bp %d wmask %02X rmask %02X) =", base, base + size - 1, 0x25 + reg, bitpair, 1 << (bitpair * 2), 1 << ((bitpair * 2) + 1)); + for (uint8_t reg = 0; reg <= 3; reg++) { + for (uint8_t bitpair = 0; bitpair <= ((reg == 3) ? 0 : 3); bitpair++) { + if (reg == 3) { + size = 0x10000; + base = 0xf0000; + } else { + size = 0x4000; + base = 0xc0000 + (size * ((reg * 4) + bitpair)); + } + stpc_log("STPC: Shadowing for %05X-%05X (reg %02X bp %d wmask %02X rmask %02X) =", base, base + size - 1, 0x25 + reg, bitpair, 1 << (bitpair * 2), 1 << ((bitpair * 2) + 1)); - state = 0; - if (dev->regs[0x25 + reg] & (1 << (bitpair * 2))) { - stpc_log(" w on"); - state |= MEM_WRITE_INTERNAL; - if (base >= 0xe0000) - shadowbios_write |= 1; - } else { - stpc_log(" w off"); - state |= MEM_WRITE_EXTANY; - } - if (dev->regs[0x25 + reg] & (1 << ((bitpair * 2) + 1))) { - stpc_log("; r on\n"); - state |= MEM_READ_INTERNAL; - if (base >= 0xe0000) - shadowbios |= 1; - } else { - stpc_log("; r off\n"); - state |= MEM_READ_EXTANY; - } + state = 0; + if (dev->regs[0x25 + reg] & (1 << (bitpair * 2))) { + stpc_log(" w on"); + state |= MEM_WRITE_INTERNAL; + if (base >= 0xe0000) + shadowbios_write |= 1; + } else { + stpc_log(" w off"); + state |= MEM_WRITE_EXTANY; + } + if (dev->regs[0x25 + reg] & (1 << ((bitpair * 2) + 1))) { + stpc_log("; r on\n"); + state |= MEM_READ_INTERNAL; + if (base >= 0xe0000) + shadowbios |= 1; + } else { + stpc_log("; r off\n"); + state |= MEM_READ_EXTANY; + } - mem_set_mem_state(base, size, state); - } + mem_set_mem_state(base, size, state); + } } flushmmucache_nopc(); } - static void stpc_host_write(uint16_t addr, uint8_t val, void *priv) { @@ -162,30 +160,28 @@ stpc_host_write(uint16_t addr, uint8_t val, void *priv) stpc_log("STPC: host_write(%04X, %02X)\n", addr, val); if (addr == dev->host_base) - dev->host_offset = val; + dev->host_offset = val; else if (addr == (dev->host_base + 4)) - dev->host_regs[dev->host_offset] = val; + dev->host_regs[dev->host_offset] = val; } - static uint8_t stpc_host_read(uint16_t addr, void *priv) { - stpc_t *dev = (stpc_t *) priv; - uint8_t ret; + const stpc_t *dev = (stpc_t *) priv; + uint8_t ret; if (addr == dev->host_base) - ret = dev->host_offset; + ret = dev->host_offset; else if (addr == (dev->host_base + 4)) - ret = dev->host_regs[dev->host_offset]; + ret = dev->host_regs[dev->host_offset]; else - ret = 0xff; + ret = 0xff; stpc_log("STPC: host_read(%04X) = %02X\n", addr, ret); return ret; } - static void stpc_localbus_write(uint16_t addr, uint8_t val, void *priv) { @@ -194,30 +190,28 @@ stpc_localbus_write(uint16_t addr, uint8_t val, void *priv) stpc_log("STPC: localbus_write(%04X, %02X)\n", addr, val); if (addr == dev->localbus_base) - dev->localbus_offset = val; + dev->localbus_offset = val; else if (addr == (dev->localbus_base + 4)) - dev->localbus_regs[addr] = val; + dev->localbus_regs[addr] = val; } - static uint8_t stpc_localbus_read(uint16_t addr, void *priv) { - stpc_t *dev = (stpc_t *) priv; - uint8_t ret; + const stpc_t *dev = (stpc_t *) priv; + uint8_t ret; if (addr == dev->localbus_base) - ret = dev->localbus_offset; + ret = dev->localbus_offset; else if (addr == (dev->localbus_base + 4)) - ret = dev->localbus_regs[dev->localbus_offset]; + ret = dev->localbus_regs[dev->localbus_offset]; else - ret = 0xff; + ret = 0xff; stpc_log("STPC: localbus_read(%04X) = %02X\n", addr, ret); return ret; } - static void stpc_nb_write(int func, int addr, uint8_t val, void *priv) { @@ -226,101 +220,113 @@ stpc_nb_write(int func, int addr, uint8_t val, void *priv) stpc_log("STPC: nb_write(%d, %02X, %02X)\n", func, addr, val); if (func > 0) - return; + return; switch (addr) { - case 0x00: case 0x01: case 0x02: case 0x03: - case 0x04: case 0x06: case 0x07: case 0x08: - case 0x09: case 0x0a: case 0x0b: case 0x0e: - case 0x51: case 0x53: case 0x54: - return; + case 0x00: + case 0x01: + case 0x02: + case 0x03: + case 0x04: + case 0x06: + case 0x07: + case 0x08: + case 0x09: + case 0x0a: + case 0x0b: + case 0x0e: + case 0x51: + case 0x53: + case 0x54: + return; - case 0x05: - val &= 0x01; - break; + case 0x05: + val &= 0x01; + break; - case 0x50: - val &= 0x1f; - break; + case 0x50: + val &= 0x1f; + break; - case 0x52: - val &= 0x70; - break; + case 0x52: + val &= 0x70; + break; + + default: + break; } dev->pci_conf[0][addr] = val; } - static uint8_t stpc_nb_read(int func, int addr, void *priv) { - stpc_t *dev = (stpc_t *) priv; - uint8_t ret; + const stpc_t *dev = (stpc_t *) priv; + uint8_t ret; if (func > 0) - ret = 0xff; + ret = 0xff; else - ret = dev->pci_conf[0][addr]; + ret = dev->pci_conf[0][addr]; stpc_log("STPC: nb_read(%d, %02X) = %02X\n", func, addr, ret); return ret; } - static void stpc_ide_handlers(stpc_t *dev, int bus) { - uint16_t main, side; + uint16_t main; + uint16_t side; if (bus & 0x01) { - ide_pri_disable(); + ide_pri_disable(); - if (dev->pci_conf[2][0x09] & 0x01) { - main = (dev->pci_conf[2][0x11] << 8) | (dev->pci_conf[2][0x10] & 0xf8); - side = ((dev->pci_conf[2][0x15] << 8) | (dev->pci_conf[2][0x14] & 0xfc)) + 2; - } else { - main = 0x1f0; - side = 0x3f6; - } + if (dev->pci_conf[2][0x09] & 0x01) { + main = (dev->pci_conf[2][0x11] << 8) | (dev->pci_conf[2][0x10] & 0xf8); + side = ((dev->pci_conf[2][0x15] << 8) | (dev->pci_conf[2][0x14] & 0xfc)) + 2; + } else { + main = 0x1f0; + side = 0x3f6; + } - ide_set_base(0, main); - ide_set_side(0, side); + ide_set_base(0, main); + ide_set_side(0, side); - stpc_log("STPC: IDE primary main %04X side %04X enable ", main, side); - if ((dev->pci_conf[2][0x04] & 0x01) && !(dev->pci_conf[2][0x48] & 0x04)) { - stpc_log("1\n"); - ide_pri_enable(); - } else { - stpc_log("0\n"); - } + stpc_log("STPC: IDE primary main %04X side %04X enable ", main, side); + if ((dev->pci_conf[2][0x04] & 0x01) && !(dev->pci_conf[2][0x48] & 0x04)) { + stpc_log("1\n"); + ide_pri_enable(); + } else { + stpc_log("0\n"); + } } if (bus & 0x02) { - ide_sec_disable(); + ide_sec_disable(); - if (dev->pci_conf[2][0x09] & 0x04) { - main = (dev->pci_conf[2][0x19] << 8) | (dev->pci_conf[2][0x18] & 0xf8); - side = ((dev->pci_conf[2][0x1d] << 8) | (dev->pci_conf[2][0x1c] & 0xfc)) + 2; - } else { - main = 0x170; - side = 0x376; - } + if (dev->pci_conf[2][0x09] & 0x04) { + main = (dev->pci_conf[2][0x19] << 8) | (dev->pci_conf[2][0x18] & 0xf8); + side = ((dev->pci_conf[2][0x1d] << 8) | (dev->pci_conf[2][0x1c] & 0xfc)) + 2; + } else { + main = 0x170; + side = 0x376; + } - ide_set_base(1, main); - ide_set_side(1, side); + ide_set_base(1, main); + ide_set_side(1, side); - stpc_log("STPC: IDE secondary main %04X side %04X enable ", main, side); - if ((dev->pci_conf[2][0x04] & 0x01) && !(dev->pci_conf[2][0x48] & 0x08)) { - stpc_log("1\n"); - ide_sec_enable(); - } else { - stpc_log("0\n"); - } + stpc_log("STPC: IDE secondary main %04X side %04X enable ", main, side); + if ((dev->pci_conf[2][0x04] & 0x01) && !(dev->pci_conf[2][0x48] & 0x08)) { + stpc_log("1\n"); + ide_sec_enable(); + } else { + stpc_log("0\n"); + } } } - static void stpc_ide_bm_handlers(stpc_t *dev) { @@ -330,7 +336,6 @@ stpc_ide_bm_handlers(stpc_t *dev) sff_bus_master_handler(dev->bm[1], dev->pci_conf[2][0x04] & 1, base + 8); } - static void stpc_ide_write(int func, int addr, uint8_t val, void *priv) { @@ -339,168 +344,185 @@ stpc_ide_write(int func, int addr, uint8_t val, void *priv) stpc_log("STPC: ide_write(%d, %02X, %02X)\n", func, addr, val); if (func > 0) - return; + return; switch (addr) { - case 0x04: - dev->pci_conf[2][addr] = (dev->pci_conf[2][addr] & 0xbe) | (val & 0x41); - stpc_ide_handlers(dev, 0x03); - stpc_ide_bm_handlers(dev); - break; + case 0x04: + dev->pci_conf[2][addr] = (dev->pci_conf[2][addr] & 0xbe) | (val & 0x41); + stpc_ide_handlers(dev, 0x03); + stpc_ide_bm_handlers(dev); + break; - case 0x05: - dev->pci_conf[2][addr] = val & 0x01; - break; + case 0x05: + dev->pci_conf[2][addr] = val & 0x01; + break; - case 0x07: - dev->pci_conf[2][addr] &= ~(val & 0x70); - break; + case 0x07: + dev->pci_conf[2][addr] &= ~(val & 0x70); + break; - case 0x09: - dev->pci_conf[2][addr] = (dev->pci_conf[2][addr] & 0x8a) | (val & 0x05); - stpc_ide_handlers(dev, 0x03); - break; + case 0x09: + dev->pci_conf[2][addr] = (dev->pci_conf[2][addr] & 0x8a) | (val & 0x05); + stpc_ide_handlers(dev, 0x03); + break; - case 0x10: - dev->pci_conf[2][addr] = (val & 0xf8) | 1; - stpc_ide_handlers(dev, 0x01); - break; - case 0x11: - dev->pci_conf[2][addr] = val; - stpc_ide_handlers(dev, 0x01); - break; + case 0x10: + dev->pci_conf[2][addr] = (val & 0xf8) | 1; + stpc_ide_handlers(dev, 0x01); + break; + case 0x11: + dev->pci_conf[2][addr] = val; + stpc_ide_handlers(dev, 0x01); + break; - case 0x14: - dev->pci_conf[2][addr] = (val & 0xfc) | 1; - stpc_ide_handlers(dev, 0x01); - break; - case 0x15: - dev->pci_conf[2][addr] = val; - stpc_ide_handlers(dev, 0x01); - break; + case 0x14: + dev->pci_conf[2][addr] = (val & 0xfc) | 1; + stpc_ide_handlers(dev, 0x01); + break; + case 0x15: + dev->pci_conf[2][addr] = val; + stpc_ide_handlers(dev, 0x01); + break; - case 0x18: - dev->pci_conf[2][addr] = (val & 0xf8) | 1; - stpc_ide_handlers(dev, 0x02); - break; - case 0x19: - dev->pci_conf[2][addr] = val; - stpc_ide_handlers(dev, 0x02); - break; + case 0x18: + dev->pci_conf[2][addr] = (val & 0xf8) | 1; + stpc_ide_handlers(dev, 0x02); + break; + case 0x19: + dev->pci_conf[2][addr] = val; + stpc_ide_handlers(dev, 0x02); + break; - case 0x1c: - dev->pci_conf[2][addr] = (val & 0xfc) | 1; - stpc_ide_handlers(dev, 0x02); - break; - case 0x1d: - dev->pci_conf[2][addr] = val; - stpc_ide_handlers(dev, 0x02); - break; + case 0x1c: + dev->pci_conf[2][addr] = (val & 0xfc) | 1; + stpc_ide_handlers(dev, 0x02); + break; + case 0x1d: + dev->pci_conf[2][addr] = val; + stpc_ide_handlers(dev, 0x02); + break; - case 0x20: - dev->pci_conf[2][0x20] = (val & 0xf0) | 1; - stpc_ide_bm_handlers(dev); - break; - case 0x21: - dev->pci_conf[2][0x21] = val; - stpc_ide_bm_handlers(dev); - break; + case 0x20: + dev->pci_conf[2][0x20] = (val & 0xf0) | 1; + stpc_ide_bm_handlers(dev); + break; + case 0x21: + dev->pci_conf[2][0x21] = val; + stpc_ide_bm_handlers(dev); + break; - case 0x3c: - dev->pci_conf[2][addr] = val; - break; + case 0x3c: + dev->pci_conf[2][addr] = val; + break; - case 0x40: case 0x41: case 0x42: case 0x43: - case 0x44: case 0x45: case 0x46: case 0x47: - dev->pci_conf[2][addr] = val; - break; + case 0x40: + case 0x41: + case 0x42: + case 0x43: + case 0x44: + case 0x45: + case 0x46: + case 0x47: + dev->pci_conf[2][addr] = val; + break; - case 0x48: - dev->pci_conf[2][addr] = (val & 0x8c) & ~(val & 0x03); - stpc_ide_handlers(dev, 0x03); - if (val & 0x02) { - sff_bus_master_set_irq(0x01, dev->bm[0]); - sff_bus_master_set_irq(0x01, dev->bm[1]); - } - if (val & 0x01) { - sff_bus_master_set_irq(0x00, dev->bm[0]); - sff_bus_master_set_irq(0x00, dev->bm[1]); - } - break; + case 0x48: + dev->pci_conf[2][addr] = (val & 0x8c) & ~(val & 0x03); + stpc_ide_handlers(dev, 0x03); + if (val & 0x02) { + sff_bus_master_set_irq(0x01, dev->bm[0]); + sff_bus_master_set_irq(0x01, dev->bm[1]); + } + if (val & 0x01) { + sff_bus_master_set_irq(0x00, dev->bm[0]); + sff_bus_master_set_irq(0x00, dev->bm[1]); + } + break; + + default: + break; } } - static uint8_t stpc_ide_read(int func, int addr, void *priv) { - stpc_t *dev = (stpc_t *) priv; - uint8_t ret; + const stpc_t *dev = (stpc_t *) priv; + uint8_t ret; if (func > 0) - ret = 0xff; + ret = 0xff; else { - ret = dev->pci_conf[2][addr]; - if (addr == 0x48) { - ret &= 0xfc; - ret |= !!(dev->bm[0]->status & 0x04); - ret |= (!!(dev->bm[1]->status & 0x04)) << 1; - } + ret = dev->pci_conf[2][addr]; + if (addr == 0x48) { + ret &= 0xfc; + ret |= !!(dev->bm[0]->status & 0x04); + ret |= (!!(dev->bm[1]->status & 0x04)) << 1; + } } stpc_log("STPC: ide_read(%d, %02X) = %02X\n", func, addr, ret); return ret; } - static void stpc_isab_write(int func, int addr, uint8_t val, void *priv) { stpc_t *dev = (stpc_t *) priv; if ((func == 1) && (dev->local != STPC_ATLAS)) { - stpc_ide_write(0, addr, val, priv); - return; + stpc_ide_write(0, addr, val, priv); + return; } stpc_log("STPC: isab_write(%d, %02X, %02X)\n", func, addr, val); if (func > 0) - return; + return; switch (addr) { - case 0x00: case 0x01: case 0x02: case 0x03: - case 0x04: case 0x06: case 0x07: case 0x08: - case 0x09: case 0x0a: case 0x0b: case 0x0e: - return; + case 0x00: + case 0x01: + case 0x02: + case 0x03: + case 0x04: + case 0x06: + case 0x07: + case 0x08: + case 0x09: + case 0x0a: + case 0x0b: + case 0x0e: + return; - case 0x05: - val &= 0x01; - break; + case 0x05: + val &= 0x01; + break; + + default: + break; } dev->pci_conf[1][addr] = val; } - static uint8_t stpc_isab_read(int func, int addr, void *priv) { - stpc_t *dev = (stpc_t *) priv; - uint8_t ret; + const stpc_t *dev = (stpc_t *) priv; + uint8_t ret; if ((func == 1) && (dev->local != STPC_ATLAS)) - ret = stpc_ide_read(0, addr, priv); + ret = stpc_ide_read(0, addr, priv); else if (func > 0) - ret = 0xff; + ret = 0xff; else - ret = dev->pci_conf[1][addr]; + ret = dev->pci_conf[1][addr]; stpc_log("STPC: isab_read(%d, %02X) = %02X\n", func, addr, ret); return ret; } - static void stpc_usb_write(int func, int addr, uint8_t val, void *priv) { @@ -509,112 +531,123 @@ stpc_usb_write(int func, int addr, uint8_t val, void *priv) stpc_log("STPC: usb_write(%d, %02X, %02X)\n", func, addr, val); if (func > 0) - return; + return; switch (addr) { - case 0x00: case 0x01: case 0x02: case 0x03: - case 0x04: case 0x06: case 0x07: case 0x08: - case 0x09: case 0x0a: case 0x0b: case 0x0e: - case 0x10: - return; + case 0x00: + case 0x01: + case 0x02: + case 0x03: + case 0x04: + case 0x06: + case 0x07: + case 0x08: + case 0x09: + case 0x0a: + case 0x0b: + case 0x0e: + case 0x10: + return; - case 0x05: - val &= 0x01; - break; + case 0x05: + val &= 0x01; + break; - case 0x11: - dev->pci_conf[3][addr] = val & 0xf0; - ohci_update_mem_mapping(dev->usb, dev->pci_conf[3][0x11], dev->pci_conf[3][0x12], dev->pci_conf[3][0x13], 1); - break; + case 0x11: + dev->pci_conf[3][addr] = val & 0xf0; + ohci_update_mem_mapping(dev->usb, dev->pci_conf[3][0x11], dev->pci_conf[3][0x12], dev->pci_conf[3][0x13], 1); + break; - case 0x12: case 0x13: - dev->pci_conf[3][addr] = val; - ohci_update_mem_mapping(dev->usb, dev->pci_conf[3][0x11], dev->pci_conf[3][0x12], dev->pci_conf[3][0x13], 1); - break; + case 0x12: + case 0x13: + dev->pci_conf[3][addr] = val; + ohci_update_mem_mapping(dev->usb, dev->pci_conf[3][0x11], dev->pci_conf[3][0x12], dev->pci_conf[3][0x13], 1); + break; + default: + break; } dev->pci_conf[3][addr] = val; } - static uint8_t stpc_usb_read(int func, int addr, void *priv) { - stpc_t *dev = (stpc_t *) priv; - uint8_t ret; + const stpc_t *dev = (stpc_t *) priv; + uint8_t ret; if (func > 0) - ret = 0xff; + ret = 0xff; else - ret = dev->pci_conf[3][addr]; + ret = dev->pci_conf[3][addr]; stpc_log("STPC: usb_read(%d, %02X) = %02X\n", func, addr, ret); return ret; } - static void stpc_remap_host(stpc_t *dev, uint16_t host_base) { stpc_log("STPC: Remapping host bus from %04X to %04X\n", dev->host_base, host_base); io_removehandler(dev->host_base, 5, - stpc_host_read, NULL, NULL, stpc_host_write, NULL, NULL, dev); + stpc_host_read, NULL, NULL, stpc_host_write, NULL, NULL, dev); if (host_base) { - io_sethandler(host_base, 5, - stpc_host_read, NULL, NULL, stpc_host_write, NULL, NULL, dev); + io_sethandler(host_base, 5, + stpc_host_read, NULL, NULL, stpc_host_write, NULL, NULL, dev); } dev->host_base = host_base; } - static void stpc_remap_localbus(stpc_t *dev, uint16_t localbus_base) { stpc_log("STPC: Remapping local bus from %04X to %04X\n", dev->localbus_base, localbus_base); io_removehandler(dev->localbus_base, 5, - stpc_localbus_read, NULL, NULL, stpc_localbus_write, NULL, NULL, dev); + stpc_localbus_read, NULL, NULL, stpc_localbus_write, NULL, NULL, dev); if (localbus_base) { - io_sethandler(localbus_base, 5, - stpc_localbus_read, NULL, NULL, stpc_localbus_write, NULL, NULL, dev); + io_sethandler(localbus_base, 5, + stpc_localbus_read, NULL, NULL, stpc_localbus_write, NULL, NULL, dev); } dev->localbus_base = localbus_base; } - static uint8_t stpc_serial_handlers(uint8_t val) { - stpc_serial_t *dev = device_get_priv(&stpc_serial_device); + const stpc_serial_t *dev = device_get_priv(&stpc_serial_device); + if (!dev) { - stpc_log("STPC: Not remapping UARTs, disabled by strap (raw %02X)\n", val); - return 0; + stpc_log("STPC: Not remapping UARTs, disabled by strap (raw %02X)\n", val); + return 0; } - uint16_t uart0_io = 0x3f8, uart1_io = 0x3f8; - uint8_t uart0_irq = 4, uart1_irq = 3; + uint16_t uart0_io = 0x3f8; + uint16_t uart1_io = 0x3f8; + uint8_t uart0_irq = 4; + uint8_t uart1_irq = 3; if (val & 0x10) - uart1_io &= 0xfeff; + uart1_io &= 0xfeff; if (val & 0x20) - uart1_io &= 0xffef; + uart1_io &= 0xffef; if (val & 0x40) - uart0_io &= 0xfeff; + uart0_io &= 0xfeff; if (val & 0x80) - uart0_io &= 0xffef; + uart0_io &= 0xffef; if (uart0_io == uart1_io) { - /* Apply defaults if both UARTs are set to the same address. */ - stpc_log("STPC: Both UARTs set to %02X, resetting to defaults\n", uart0_io); - uart0_io = 0x3f8; - uart1_io = 0x2f8; + /* Apply defaults if both UARTs are set to the same address. */ + stpc_log("STPC: Both UARTs set to %02X, resetting to defaults\n", uart0_io); + uart0_io = 0x3f8; + uart1_io = 0x2f8; } if (!(uart0_io & 0x100)) { - /* The address for UART0 establishes the IRQs for both ports. */ - uart0_irq = 3; - uart1_irq = 4; + /* The address for UART0 establishes the IRQs for both ports. */ + uart0_irq = 3; + uart1_irq = 4; } stpc_log("STPC: Remapping UART0 to %04X %d and UART1 to %04X %d (raw %02X)\n", uart0_io, uart0_irq, uart1_io, uart1_irq, val); @@ -627,7 +660,6 @@ stpc_serial_handlers(uint8_t val) return 1; } - static void stpc_reg_write(uint16_t addr, uint8_t val, void *priv) { @@ -636,96 +668,104 @@ stpc_reg_write(uint16_t addr, uint8_t val, void *priv) stpc_log("STPC: reg_write(%04X, %02X)\n", addr, val); if (addr == 0x22) { - dev->reg_offset = val; + dev->reg_offset = val; } else { - stpc_log("STPC: regs[%02X] = %02X\n", dev->reg_offset, val); + stpc_log("STPC: regs[%02X] = %02X\n", dev->reg_offset, val); - switch (dev->reg_offset) { - case 0x12: - if (dev->regs[0x10] == 0x07) - stpc_remap_host(dev, (dev->host_base & 0xff00) | val); - else if (dev->regs[0x10] == 0x06) - stpc_remap_localbus(dev, (dev->localbus_base & 0xff00) | val); - break; + switch (dev->reg_offset) { + case 0x12: + if (dev->regs[0x10] == 0x07) + stpc_remap_host(dev, (dev->host_base & 0xff00) | val); + else if (dev->regs[0x10] == 0x06) + stpc_remap_localbus(dev, (dev->localbus_base & 0xff00) | val); + break; - case 0x13: - if (dev->regs[0x10] == 0x07) - stpc_remap_host(dev, (dev->host_base & 0x00ff) | (val << 8)); - else if (dev->regs[0x10] == 0x06) - stpc_remap_localbus(dev, (dev->localbus_base & 0x00ff) | (val << 8)); - break; + case 0x13: + if (dev->regs[0x10] == 0x07) + stpc_remap_host(dev, (dev->host_base & 0x00ff) | (val << 8)); + else if (dev->regs[0x10] == 0x06) + stpc_remap_localbus(dev, (dev->localbus_base & 0x00ff) | (val << 8)); + break; - case 0x21: - val &= 0xfe; - break; + case 0x21: + val &= 0xfe; + break; - case 0x22: - val &= 0x7f; - break; + case 0x22: + val &= 0x7f; + break; - case 0x25: case 0x26: case 0x27: case 0x28: - if (dev->reg_offset == 0x28) { - val &= 0xe3; - smram_state_change(dev->smram, 0, !!(val & 0x80)); - } - dev->regs[dev->reg_offset] = val; - stpc_recalcmapping(dev); - break; + case 0x25: + case 0x26: + case 0x27: + case 0x28: + if (dev->reg_offset == 0x28) { + val &= 0xe3; + smram_state_change(dev->smram, 0, !!(val & 0x80)); + } + dev->regs[dev->reg_offset] = val; + stpc_recalcmapping(dev); + break; - case 0x29: - val &= 0x0f; - break; + case 0x29: + val &= 0x0f; + break; - case 0x36: - val &= 0x3f; - break; + case 0x36: + val &= 0x3f; + break; - case 0x52: case 0x53: case 0x54: case 0x55: - stpc_log("STPC: Set IRQ routing: INT %c -> %d\n", 0x41 + ((dev->reg_offset - 2) & 0x03), (val & 0x80) ? (val & 0xf) : -1); - val &= 0x8f; - pci_set_irq_routing(PCI_INTA + ((dev->reg_offset - 2) & 0x03), (val & 0x80) ? (val & 0xf) : PCI_IRQ_DISABLED); - break; + case 0x52: + case 0x53: + case 0x54: + case 0x55: + stpc_log("STPC: Set IRQ routing: INT %c -> %d\n", 0x41 + ((dev->reg_offset - 2) & 0x03), (val & 0x80) ? (val & 0xf) : -1); + val &= 0x8f; + pci_set_irq_routing(PCI_INTA + ((dev->reg_offset - 2) & 0x03), (val & 0x80) ? (val & 0xf) : PCI_IRQ_DISABLED); + break; - case 0x56: case 0x57: - pic_elcr_write(dev->reg_offset, val, (dev->reg_offset & 1) ? &pic2 : &pic); - if (dev->reg_offset == 0x57) - refresh_at_enable = (val & 0x01); - break; + case 0x56: + case 0x57: + pic_elcr_write(dev->reg_offset, val, (dev->reg_offset & 1) ? &pic2 : &pic); + if (dev->reg_offset == 0x57) + refresh_at_enable = (val & 0x01); + break; - case 0x59: - val &= 0xf1; - stpc_serial_handlers(val); - break; - } + case 0x59: + val &= 0xf1; + stpc_serial_handlers(val); + break; - dev->regs[dev->reg_offset] = val; + default: + break; + } + + dev->regs[dev->reg_offset] = val; } } - static uint8_t stpc_reg_read(uint16_t addr, void *priv) { - stpc_t *dev = (stpc_t *) priv; - uint8_t ret; + const stpc_t *dev = (stpc_t *) priv; + uint8_t ret; if (addr == 0x22) - ret = dev->reg_offset; + ret = dev->reg_offset; else if (dev->reg_offset >= 0xc0) - return 0xff; /* let the CPU code handle Cyrix CPU registers */ + return 0xff; /* let the CPU code handle Cyrix CPU registers */ else if ((dev->reg_offset == 0x56) || (dev->reg_offset == 0x57)) { - /* ELCR registers. */ - ret = pic_elcr_read(dev->reg_offset, (dev->reg_offset & 1) ? &pic2 : &pic); - if (dev->reg_offset == 0x57) - ret |= (dev->regs[dev->reg_offset] & 0x01); + /* ELCR registers. */ + ret = pic_elcr_read(dev->reg_offset, (dev->reg_offset & 1) ? &pic2 : &pic); + if (dev->reg_offset == 0x57) + ret |= (dev->regs[dev->reg_offset] & 0x01); } else - ret = dev->regs[dev->reg_offset]; + ret = dev->regs[dev->reg_offset]; stpc_log("STPC: reg_read(%04X) = %02X\n", dev->reg_offset, ret); return ret; } - static void stpc_reset(void *priv) { @@ -736,12 +776,11 @@ stpc_reset(void *priv) memset(dev->regs, 0, sizeof(dev->regs)); dev->regs[0x7b] = 0xff; if (device_get_priv(&stpc_lpt_device)) - dev->regs[0x4c] |= 0x80; /* LPT strap */ + dev->regs[0x4c] |= 0x80; /* LPT strap */ if (stpc_serial_handlers(0x00)) - dev->regs[0x4c] |= 0x03; /* UART straps */ + dev->regs[0x4c] |= 0x03; /* UART straps */ } - static void stpc_setup(stpc_t *dev) { @@ -749,19 +788,19 @@ stpc_setup(stpc_t *dev) /* Main register interface */ io_sethandler(0x22, 2, - stpc_reg_read, NULL, NULL, stpc_reg_write, NULL, NULL, dev); + stpc_reg_read, NULL, NULL, stpc_reg_write, NULL, NULL, dev); /* Northbridge */ if (dev->local & STPC_CLIENT) { - dev->pci_conf[0][0x00] = 0x0e; - dev->pci_conf[0][0x01] = 0x10; - dev->pci_conf[0][0x02] = 0x64; - dev->pci_conf[0][0x03] = 0x05; + dev->pci_conf[0][0x00] = 0x0e; + dev->pci_conf[0][0x01] = 0x10; + dev->pci_conf[0][0x02] = 0x64; + dev->pci_conf[0][0x03] = 0x05; } else { - dev->pci_conf[0][0x00] = 0x4a; - dev->pci_conf[0][0x01] = 0x10; - dev->pci_conf[0][0x02] = 0x0a; - dev->pci_conf[0][0x03] = 0x02; + dev->pci_conf[0][0x00] = 0x4a; + dev->pci_conf[0][0x01] = 0x10; + dev->pci_conf[0][0x02] = 0x0a; + dev->pci_conf[0][0x03] = 0x02; } dev->pci_conf[0][0x04] = 0x07; @@ -786,8 +825,8 @@ stpc_setup(stpc_t *dev) dev->pci_conf[1][0x0b] = 0x06; /* NOTE: This is an erratum in the STPC Atlas programming manual, the programming manuals for the other - STPC chipsets say 0x80, which is indeed multi-function (as the STPC Atlas programming manual - indicates as well), and Windows 2000 also issues a 0x7B STOP error if it is 0x40. */ + STPC chipsets say 0x80, which is indeed multi-function (as the STPC Atlas programming manual + indicates as well), and Windows 2000 also issues a 0x7B STOP error if it is 0x40. */ dev->pci_conf[1][0x0e] = /*0x40*/ 0x80; /* IDE */ @@ -795,11 +834,11 @@ stpc_setup(stpc_t *dev) dev->pci_conf[2][0x01] = dev->local >> 24; if (dev->local == STPC_ATLAS) { - dev->pci_conf[2][0x02] = 0x28; - dev->pci_conf[2][0x03] = 0x02; + dev->pci_conf[2][0x02] = 0x28; + dev->pci_conf[2][0x03] = 0x02; } else { - dev->pci_conf[2][0x02] = dev->pci_conf[1][0x02]; - dev->pci_conf[2][0x03] = dev->pci_conf[1][0x03]; + dev->pci_conf[2][0x02] = dev->pci_conf[1][0x02]; + dev->pci_conf[2][0x03] = dev->pci_conf[1][0x03]; } dev->pci_conf[2][0x06] = 0x80; @@ -810,8 +849,8 @@ stpc_setup(stpc_t *dev) dev->pci_conf[2][0x0b] = 0x01; /* NOTE: This is an erratum in the STPC Atlas programming manual, the programming manuals for the other - STPC chipsets say 0x80, which is indeed multi-function (as the STPC Atlas programming manual - indicates as well), and Windows 2000 also issues a 0x7B STOP error if it is 0x40. */ + STPC chipsets say 0x80, which is indeed multi-function (as the STPC Atlas programming manual + indicates as well), and Windows 2000 also issues a 0x7B STOP error if it is 0x40. */ dev->pci_conf[2][0x0e] = /*0x40*/ 0x80; dev->pci_conf[2][0x10] = 0x01; @@ -831,22 +870,22 @@ stpc_setup(stpc_t *dev) /* USB */ if (dev->usb) { - dev->pci_conf[3][0x00] = dev->local >> 16; - dev->pci_conf[3][0x01] = dev->local >> 24; - dev->pci_conf[3][0x02] = 0x30; - dev->pci_conf[3][0x03] = 0x02; - - dev->pci_conf[3][0x06] = 0x80; - dev->pci_conf[3][0x07] = 0x02; + dev->pci_conf[3][0x00] = dev->local >> 16; + dev->pci_conf[3][0x01] = dev->local >> 24; + dev->pci_conf[3][0x02] = 0x30; + dev->pci_conf[3][0x03] = 0x02; - dev->pci_conf[3][0x09] = 0x10; - dev->pci_conf[3][0x0a] = 0x03; - dev->pci_conf[3][0x0b] = 0x0c; + dev->pci_conf[3][0x06] = 0x80; + dev->pci_conf[3][0x07] = 0x02; - /* NOTE: This is an erratum in the STPC Atlas programming manual, the programming manuals for the other - STPC chipsets say 0x80, which is indeed multi-function (as the STPC Atlas programming manual - indicates as well), and Windows 2000 also issues a 0x7B STOP error if it is 0x40. */ - dev->pci_conf[3][0x0e] = /*0x40*/ 0x80; + dev->pci_conf[3][0x09] = 0x10; + dev->pci_conf[3][0x0a] = 0x03; + dev->pci_conf[3][0x0b] = 0x0c; + + /* NOTE: This is an erratum in the STPC Atlas programming manual, the programming manuals for the other + STPC chipsets say 0x80, which is indeed multi-function (as the STPC Atlas programming manual + indicates as well), and Windows 2000 also issues a 0x7B STOP error if it is 0x40. */ + dev->pci_conf[3][0x0e] = /*0x40*/ 0x80; } /* PCI setup */ @@ -856,7 +895,6 @@ stpc_setup(stpc_t *dev) pci_set_irq_routing(PCI_INTD, PCI_IRQ_DISABLED); } - static void stpc_close(void *priv) { @@ -869,7 +907,6 @@ stpc_close(void *priv) free(dev); } - static void * stpc_init(const device_t *info) { @@ -877,25 +914,24 @@ stpc_init(const device_t *info) stpc_t *dev = (stpc_t *) malloc(sizeof(stpc_t)); memset(dev, 0, sizeof(stpc_t)); - + dev->local = info->local; - pci_add_card(PCI_ADD_NORTHBRIDGE, stpc_nb_read, stpc_nb_write, dev); - dev->ide_slot = pci_add_card(PCI_ADD_SOUTHBRIDGE, stpc_isab_read, stpc_isab_write, dev); + pci_add_card(PCI_ADD_NORTHBRIDGE, stpc_nb_read, stpc_nb_write, dev, &dev->nb_slot); + pci_add_card(PCI_ADD_SOUTHBRIDGE, stpc_isab_read, stpc_isab_write, dev, &dev->sb_slot); if (dev->local == STPC_ATLAS) { - dev->ide_slot = pci_add_card(PCI_ADD_SOUTHBRIDGE, stpc_ide_read, stpc_ide_write, dev); - dev->usb = device_add(&usb_device); - pci_add_card(PCI_ADD_SOUTHBRIDGE, stpc_usb_read, stpc_usb_write, dev); + pci_add_card(PCI_ADD_SOUTHBRIDGE_IDE, stpc_ide_read, stpc_ide_write, dev, &dev->ide_slot); + + dev->usb = device_add(&usb_device); + pci_add_card(PCI_ADD_SOUTHBRIDGE_USB, stpc_usb_read, stpc_usb_write, dev, &dev->usb_slot); } dev->bm[0] = device_add_inst(&sff8038i_device, 1); dev->bm[1] = device_add_inst(&sff8038i_device, 2); - sff_set_irq_mode(dev->bm[0], 0, 0); - sff_set_irq_mode(dev->bm[0], 1, 0); + sff_set_irq_mode(dev->bm[0], IRQ_MODE_LEGACY); - sff_set_irq_mode(dev->bm[1], 0, 0); - sff_set_irq_mode(dev->bm[1], 1, 0); + sff_set_irq_mode(dev->bm[1], IRQ_MODE_LEGACY); stpc_setup(dev); stpc_reset(dev); @@ -912,7 +948,6 @@ stpc_init(const device_t *info) return dev; } - static void stpc_serial_close(void *priv) { @@ -923,9 +958,8 @@ stpc_serial_close(void *priv) free(dev); } - static void * -stpc_serial_init(const device_t *info) +stpc_serial_init(UNUSED(const device_t *info)) { stpc_log("STPC: serial_init()\n"); @@ -940,45 +974,47 @@ stpc_serial_init(const device_t *info) return dev; } - static void stpc_lpt_handlers(stpc_lpt_t *dev, uint8_t val) { - uint8_t old_addr = (dev->reg1 & 0x03), new_addr = (val & 0x03); + uint8_t old_addr = (dev->reg1 & 0x03); + uint8_t new_addr = (val & 0x03); switch (old_addr) { - case 0x1: - lpt3_remove(); - break; + case 0x1: + lpt3_remove(); + break; - case 0x2: - lpt1_remove(); - break; + case 0x2: + lpt1_remove(); + break; - case 0x3: - lpt2_remove(); - break; + case 0x3: + lpt2_remove(); + break; + default: + break; } switch (new_addr) { - case 0x1: - stpc_log("STPC: Remapping parallel port to LPT3\n"); - lpt3_init(0x3bc); - break; + case 0x1: + stpc_log("STPC: Remapping parallel port to LPT3\n"); + lpt3_init(0x3bc); + break; - case 0x2: - stpc_log("STPC: Remapping parallel port to LPT1\n"); - lpt1_init(0x378); - break; + case 0x2: + stpc_log("STPC: Remapping parallel port to LPT1\n"); + lpt1_init(0x378); + break; - case 0x3: - stpc_log("STPC: Remapping parallel port to LPT2\n"); - lpt2_init(0x278); - break; + case 0x3: + stpc_log("STPC: Remapping parallel port to LPT2\n"); + lpt2_init(0x278); + break; - default: - stpc_log("STPC: Disabling parallel port\n"); - break; + default: + stpc_log("STPC: Disabling parallel port\n"); + break; } dev->reg1 = (val & 0x08); @@ -986,33 +1022,31 @@ stpc_lpt_handlers(stpc_lpt_t *dev, uint8_t val) dev->reg1 |= 0x84; /* reserved bits that default to 1; hardwired? */ } - static void stpc_lpt_write(uint16_t addr, uint8_t val, void *priv) { stpc_lpt_t *dev = (stpc_lpt_t *) priv; if (dev->unlocked < 2) { - /* Cheat a little bit: in reality, any write to any - I/O port is supposed to reset the unlock counter. */ - if ((addr == 0x3f0) && (val == 0x55)) - dev->unlocked++; - else - dev->unlocked = 0; + /* Cheat a little bit: in reality, any write to any + I/O port is supposed to reset the unlock counter. */ + if ((addr == 0x3f0) && (val == 0x55)) + dev->unlocked++; + else + dev->unlocked = 0; } else if (addr == 0x3f0) { - if (val == 0xaa) - dev->unlocked = 0; - else - dev->offset = val; + if (val == 0xaa) + dev->unlocked = 0; + else + dev->offset = val; } else if (dev->offset == 1) { - /* dev->reg1 is set by stpc_lpt_handlers */ - stpc_lpt_handlers(dev, val); + /* dev->reg1 is set by stpc_lpt_handlers */ + stpc_lpt_handlers(dev, val); } else if (dev->offset == 4) { - dev->reg4 = (val & 0x03); + dev->reg4 = (val & 0x03); } } - static void stpc_lpt_reset(void *priv) { @@ -1021,13 +1055,12 @@ stpc_lpt_reset(void *priv) stpc_log("STPC: lpt_reset()\n"); dev->unlocked = 0; - dev->offset = 0x00; - dev->reg1 = 0x9f; - dev->reg4 = 0x00; + dev->offset = 0x00; + dev->reg1 = 0x9f; + dev->reg4 = 0x00; stpc_lpt_handlers(dev, dev->reg1); } - static void stpc_lpt_close(void *priv) { @@ -1038,9 +1071,8 @@ stpc_lpt_close(void *priv) free(dev); } - static void * -stpc_lpt_init(const device_t *info) +stpc_lpt_init(UNUSED(const device_t *info)) { stpc_log("STPC: lpt_init()\n"); @@ -1050,100 +1082,93 @@ stpc_lpt_init(const device_t *info) stpc_lpt_reset(dev); io_sethandler(0x3f0, 2, - NULL, NULL, NULL, stpc_lpt_write, NULL, NULL, dev); + NULL, NULL, NULL, stpc_lpt_write, NULL, NULL, dev); return dev; } - /* STPC SoCs */ -const device_t stpc_client_device = -{ - "STPC Client", - "stpc_client", - DEVICE_PCI, - STPC_CLIENT, - stpc_init, - stpc_close, - stpc_reset, - { NULL }, - NULL, - NULL, - NULL +const device_t stpc_client_device = { + .name = "STPC Client", + .internal_name = "stpc_client", + .flags = DEVICE_PCI, + .local = STPC_CLIENT, + .init = stpc_init, + .close = stpc_close, + .reset = stpc_reset, + { .available = NULL }, + .speed_changed = NULL, + .force_redraw = NULL, + .config = NULL }; -const device_t stpc_consumer2_device = -{ - "STPC Consumer-II", - "stpc_consumer2", - DEVICE_PCI, - STPC_CONSUMER2, - stpc_init, - stpc_close, - stpc_reset, - { NULL }, - NULL, - NULL, - NULL +const device_t stpc_consumer2_device = { + .name = "STPC Consumer-II", + .internal_name = "stpc_consumer2", + .flags = DEVICE_PCI, + .local = STPC_CONSUMER2, + .init = stpc_init, + .close = stpc_close, + .reset = stpc_reset, + { .available = NULL }, + .speed_changed = NULL, + .force_redraw = NULL, + .config = NULL }; -const device_t stpc_elite_device = -{ - "STPC Elite", - "stpc_elite", - DEVICE_PCI, - STPC_ELITE, - stpc_init, - stpc_close, - stpc_reset, - { NULL }, - NULL, - NULL, - NULL +const device_t stpc_elite_device = { + .name = "STPC Elite", + .internal_name = "stpc_elite", + .flags = DEVICE_PCI, + .local = STPC_ELITE, + .init = stpc_init, + .close = stpc_close, + .reset = stpc_reset, + { .available = NULL }, + .speed_changed = NULL, + .force_redraw = NULL, + .config = NULL }; -const device_t stpc_atlas_device = -{ - "STPC Atlas", - "stpc_atlas", - DEVICE_PCI, - STPC_ATLAS, - stpc_init, - stpc_close, - stpc_reset, - { NULL }, - NULL, - NULL, - NULL +const device_t stpc_atlas_device = { + .name = "STPC Atlas", + .internal_name = "stpc_atlas", + .flags = DEVICE_PCI, + .local = STPC_ATLAS, + .init = stpc_init, + .close = stpc_close, + .reset = stpc_reset, + { .available = NULL }, + .speed_changed = NULL, + .force_redraw = NULL, + .config = NULL }; /* Auxiliary devices */ -const device_t stpc_serial_device = -{ - "STPC Serial UARTs", - "stpc_serial", - 0, - 0, - stpc_serial_init, - stpc_serial_close, - NULL, - { NULL }, - NULL, - NULL, - NULL +const device_t stpc_serial_device = { + .name = "STPC Serial UARTs", + .internal_name = "stpc_serial", + .flags = 0, + .local = 0, + .init = stpc_serial_init, + .close = stpc_serial_close, + .reset = NULL, + { .available = NULL }, + .speed_changed = NULL, + .force_redraw = NULL, + .config = NULL }; -const device_t stpc_lpt_device = -{ - "STPC Parallel Port", - "stpc_lpt", - 0, - 0, - stpc_lpt_init, - stpc_lpt_close, - stpc_lpt_reset, - { NULL }, - NULL, - NULL, - NULL +const device_t stpc_lpt_device = { + .name = "STPC Parallel Port", + .internal_name = "stpc_lpt", + .flags = 0, + .local = 0, + .init = stpc_lpt_init, + .close = stpc_lpt_close, + .reset = stpc_lpt_reset, + { .available = NULL }, + .speed_changed = NULL, + .force_redraw = NULL, + .config = NULL }; diff --git a/src/chipset/umc_8886.c b/src/chipset/umc_8886.c index a5206d678..f6a923346 100644 --- a/src/chipset/umc_8886.c +++ b/src/chipset/umc_8886.c @@ -1,24 +1,26 @@ /* - * 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. + * 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. + * This file is part of the 86Box distribution. * - * Implementation of the UMC 8886xx PCI to ISA Bridge . + * Implementation of the UMC 8886xx PCI to ISA Bridge . * - * Note: This chipset has no datasheet, everything were done via - * reverse engineering the BIOS of various machines using it. + * Note: This chipset has no datasheet, everything were done via + * reverse engineering the BIOS of various machines using it. * - * Authors: Tiseno100, - * Miran Grca, * - * Copyright 2021 Tiseno100. - * Copyright 2021 Miran Grca. + * + * Authors: Tiseno100, + * Miran Grca, + * + * Copyright 2021 Tiseno100. + * Copyright 2021 Miran Grca. */ -/* +/* UMC 8886xx Configuration Registers Note: PMU functionality is quite basic. There may be Enable/Disable bits, IRQ/SMI picks and it also @@ -48,16 +50,16 @@ 1 0 PCICLK/2 Function 0 Register A2 - non-software SMI# status register - (documented by Miran Grca): + (documented by Miran Grca): Bit 4: I set, graphics card goes into sleep mode This register is most likely R/WC Function 0 Register A3 (added more details by Miran Grca): Bit 7: Unlock SMM Bit 6: Software SMI trigger (also doubles as software SMI# status register, - cleared by writing a 0 to it - see the handler used by Phoenix BIOS'es): - If Function 0 Register 46 Bit 6 is set, it raises the specified IRQ (15 - or 10) instead. + cleared by writing a 0 to it - see the handler used by Phoenix BIOS'es): + If Function 0 Register 46 Bit 6 is set, it raises the specified IRQ (15 + or 10) instead. Function 0 Register A4: Bit 0: Host to PCI Clock (1: 1 by 1/0: 1 by half) @@ -65,7 +67,6 @@ Function 1 Register 4: (UMC 8886AF/8886BF Only!) Bit 0: Enable Internal IDE */ - #include #include #include @@ -87,52 +88,50 @@ #include <86box/chipset.h> - -#define IDE_BIT 0x01 - +#define IDE_BIT 0x01 #ifdef ENABLE_UMC_8886_LOG int umc_8886_do_log = ENABLE_UMC_8886_LOG; - static void umc_8886_log(const char *fmt, ...) { va_list ap; if (umc_8886_do_log) { - va_start(ap, fmt); - pclog_ex(fmt, ap); - va_end(ap); + va_start(ap, fmt); + pclog_ex(fmt, ap); + va_end(ap); } } #else -#define umc_8886_log(fmt, ...) +# define umc_8886_log(fmt, ...) #endif - /* PCI IRQ Flags */ -#define INTA (PCI_INTA + (2 * !(addr & 1))) -#define INTB (PCI_INTB + (2 * !(addr & 1))) -#define IRQRECALCA (((val & 0xf0) != 0) ? ((val & 0xf0) >> 4) : PCI_IRQ_DISABLED) -#define IRQRECALCB (((val & 0x0f) != 0) ? (val & 0x0f) : PCI_IRQ_DISABLED) +#define INTA (PCI_INTA + (2 * !(addr & 1))) +#define INTB (PCI_INTB + (2 * !(addr & 1))) +#define IRQRECALCA (((val & 0xf0) != 0) ? ((val & 0xf0) >> 4) : PCI_IRQ_DISABLED) +#define IRQRECALCB (((val & 0x0f) != 0) ? (val & 0x0f) : PCI_IRQ_DISABLED) /* Disable Internal IDE Flag needed for the AF or BF Southbridge variant */ -#define HAS_IDE dev->has_ide +#define HAS_IDE dev->has_ide /* Southbridge Revision */ -#define SB_ID dev->sb_id +#define SB_ID dev->sb_id +typedef struct umc_8886_t { + uint8_t max_func; /* Last function number */ + uint8_t pci_slot; + uint8_t pad; + uint8_t pad0; -typedef struct umc_8886_t -{ - uint8_t max_func, /* Last function number */ - pci_conf_sb[2][256]; /* PCI Registers */ - uint16_t sb_id; /* Southbridge Revision */ - int has_ide; /* Check if Southbridge Revision is AF or F */ + uint8_t pci_conf_sb[2][256]; /* PCI Registers */ + + uint16_t sb_id; /* Southbridge Revision */ + int has_ide; /* Check if Southbridge Revision is AF or F */ } umc_8886_t; - static void umc_8886_ide_handler(int status) { @@ -140,164 +139,182 @@ umc_8886_ide_handler(int status) ide_sec_disable(); if (status) { - ide_pri_enable(); - ide_sec_enable(); + ide_pri_enable(); + ide_sec_enable(); } } - static void umc_8886_write(int func, int addr, uint8_t val, void *priv) { - umc_8886_t *dev = (umc_8886_t *)priv; + umc_8886_t *dev = (umc_8886_t *) priv; - if (func <= dev->max_func) switch (func) { - case 0: /* PCI to ISA Bridge */ - umc_8886_log("UM8886: dev->regs[%02x] = %02x POST %02x\n", addr, val, inb(0x80)); + if (func <= dev->max_func) + switch (func) { + case 0: /* PCI to ISA Bridge */ + umc_8886_log("UM8886: dev->regs[%02x] = %02x POST %02x\n", addr, val, inb(0x80)); - switch (addr) { - case 0x04: case 0x05: - dev->pci_conf_sb[func][addr] = val; - break; + switch (addr) { + case 0x04: + case 0x05: + dev->pci_conf_sb[func][addr] = val; + break; - case 0x07: - dev->pci_conf_sb[func][addr] &= ~(val & 0xf9); - break; + case 0x07: + dev->pci_conf_sb[func][addr] &= ~(val & 0xf9); + break; - case 0x0c: case 0x0d: - dev->pci_conf_sb[func][addr] = val; - break; + case 0x0c: + case 0x0d: + dev->pci_conf_sb[func][addr] = val; + break; - case 0x40: case 0x41: - case 0x42: - dev->pci_conf_sb[func][addr] = val; - break; + case 0x40: + case 0x41: + case 0x42: + dev->pci_conf_sb[func][addr] = val; + break; - case 0x43: case 0x44: - dev->pci_conf_sb[func][addr] = val; - pci_set_irq_routing(INTA, IRQRECALCA); - pci_set_irq_routing(INTB, IRQRECALCB); - break; + case 0x43: + case 0x44: + dev->pci_conf_sb[func][addr] = val; + pci_set_irq_routing(INTA, IRQRECALCA); + pci_set_irq_routing(INTB, IRQRECALCB); + break; - case 0x45: - dev->pci_conf_sb[func][addr] = val; - break; + case 0x45: + dev->pci_conf_sb[func][addr] = val; + break; - case 0x46: - /* Bit 6 seems to be the IRQ/SMI# toggle, 1 = IRQ, 0 = SMI#. */ - dev->pci_conf_sb[func][addr] = val; - break; + case 0x46: + /* Bit 6 seems to be the IRQ/SMI# toggle, 1 = IRQ, 0 = SMI#. */ + dev->pci_conf_sb[func][addr] = val; + break; - case 0x47: - dev->pci_conf_sb[func][addr] = val; - break; + case 0x47: + dev->pci_conf_sb[func][addr] = val; + break; - case 0x50: case 0x51: case 0x52: case 0x53: - case 0x54: case 0x55: - dev->pci_conf_sb[func][addr] = val; - break; + case 0x50: + case 0x51: + case 0x52: + case 0x53: + case 0x54: + case 0x55: + dev->pci_conf_sb[func][addr] = val; + break; - case 0x56: - dev->pci_conf_sb[func][addr] = val; + case 0x56: + dev->pci_conf_sb[func][addr] = val; - switch (val & 2) { - case 0: - cpu_set_isa_pci_div(3); - break; - case 1: - cpu_set_isa_pci_div(4); - break; - case 2: - cpu_set_isa_pci_div(2); - break; - } + switch (val & 3) { + case 0: + cpu_set_isa_pci_div(3); + break; + case 1: + cpu_set_isa_pci_div(4); + break; + case 2: + cpu_set_isa_pci_div(2); + break; + default: + break; + } - break; + break; - case 0x57: - case 0x70 ... 0x76: - case 0x80: case 0x81: - case 0x90 ... 0x92: - case 0xa0 ... 0xa1: - dev->pci_conf_sb[func][addr] = val; - break; + case 0x57: + case 0x70 ... 0x76: + case 0x80: + case 0x81: + case 0x90 ... 0x92: + case 0xa0 ... 0xa1: + dev->pci_conf_sb[func][addr] = val; + break; - case 0xa2: - dev->pci_conf_sb[func][addr] &= ~val; - break; + case 0xa2: + dev->pci_conf_sb[func][addr] &= ~val; + break; - case 0xa3: - /* SMI Provocation (Bit 7 Enable SMM + Bit 6 Software SMI) */ - if (((val & 0xc0) == 0xc0) && !(dev->pci_conf_sb[0][0xa3] & 0x40)) { - if (dev->pci_conf_sb[0][0x46] & 0x40) - picint(1 << ((dev->pci_conf_sb[0][0x46] & 0x80) ? 15 : 10)); - else - smi_line = 1; - dev->pci_conf_sb[0][0xa3] |= 0x04; - } + case 0xa3: + /* SMI Provocation (Bit 7 Enable SMM + Bit 6 Software SMI) */ + if (((val & 0xc0) == 0xc0) && !(dev->pci_conf_sb[0][0xa3] & 0x40)) { + if (dev->pci_conf_sb[0][0x46] & 0x40) + picint(1 << ((dev->pci_conf_sb[0][0x46] & 0x80) ? 15 : 10)); + else + smi_raise(); + dev->pci_conf_sb[0][0xa3] |= 0x04; + } - dev->pci_conf_sb[func][addr] = val; - break; + dev->pci_conf_sb[func][addr] = val; + break; - case 0xa4: - dev->pci_conf_sb[func][addr] = val; - cpu_set_pci_speed(cpu_busspeed / ((val & 1) ? 1 : 2)); - break; + case 0xa4: + dev->pci_conf_sb[func][addr] = val; + cpu_set_pci_speed(cpu_busspeed / ((val & 1) ? 1 : 2)); + break; - case 0xa5 ... 0xa8: - dev->pci_conf_sb[func][addr] = val; - break; - } - break; + case 0xa5 ... 0xa8: + dev->pci_conf_sb[func][addr] = val; + break; - case 1: /* IDE Controller */ - umc_8886_log("UM8886-IDE: dev->regs[%02x] = %02x POST: %02x\n", addr, val, inb(0x80)); + default: + break; + } + break; - switch (addr) { - case 0x04: - dev->pci_conf_sb[func][addr] = val; - umc_8886_ide_handler(val & 1); - break; + case 1: /* IDE Controller */ + umc_8886_log("UM8886-IDE: dev->regs[%02x] = %02x POST: %02x\n", addr, val, inb(0x80)); - case 0x07: - dev->pci_conf_sb[func][addr] &= ~(val & 0xf9); - break; + switch (addr) { + case 0x04: + dev->pci_conf_sb[func][addr] = val; + umc_8886_ide_handler(val & 1); + break; - case 0x3c: - case 0x40: case 0x41: - dev->pci_conf_sb[func][addr] = val; - break; - } - break; - } + case 0x07: + dev->pci_conf_sb[func][addr] &= ~(val & 0xf9); + break; + + case 0x3c: + case 0x40: + case 0x41: + dev->pci_conf_sb[func][addr] = val; + break; + + default: + break; + } + break; + default: + break; + } } - static uint8_t umc_8886_read(int func, int addr, void *priv) { - umc_8886_t *dev = (umc_8886_t *)priv; - uint8_t ret = 0xff; + const umc_8886_t *dev = (umc_8886_t *) priv; + uint8_t ret = 0xff; if (func <= dev->max_func) - ret = dev->pci_conf_sb[func][addr]; + ret = dev->pci_conf_sb[func][addr]; return ret; } - static void umc_8886_reset(void *priv) { - umc_8886_t *dev = (umc_8886_t *)priv; + umc_8886_t *dev = (umc_8886_t *) priv; memset(dev->pci_conf_sb[0], 0x00, sizeof(dev->pci_conf_sb[0])); memset(dev->pci_conf_sb[1], 0x00, sizeof(dev->pci_conf_sb[1])); - dev->pci_conf_sb[0][0] = 0x60; /* UMC */ + dev->pci_conf_sb[0][0] = 0x60; /* UMC */ dev->pci_conf_sb[0][1] = 0x10; - dev->pci_conf_sb[0][2] = (SB_ID & 0xff); /* 8886xx */ + dev->pci_conf_sb[0][2] = (SB_ID & 0xff); /* 8886xx */ dev->pci_conf_sb[0][3] = ((SB_ID >> 8) & 0xff); dev->pci_conf_sb[0][4] = 0x0f; @@ -321,51 +338,49 @@ umc_8886_reset(void *priv) dev->pci_conf_sb[0][0xa8] = 0x20; if (HAS_IDE) { - dev->pci_conf_sb[1][0] = 0x60; /* UMC */ - dev->pci_conf_sb[1][1] = 0x10; + dev->pci_conf_sb[1][0] = 0x60; /* UMC */ + dev->pci_conf_sb[1][1] = 0x10; - dev->pci_conf_sb[1][2] = 0x3a; /* 8886BF IDE */ - dev->pci_conf_sb[1][3] = 0x67; + dev->pci_conf_sb[1][2] = 0x3a; /* 8886BF IDE */ + dev->pci_conf_sb[1][3] = 0x67; - dev->pci_conf_sb[1][4] = 1; /* Start with Internal IDE Enabled */ + dev->pci_conf_sb[1][4] = 1; /* Start with Internal IDE Enabled */ - dev->pci_conf_sb[1][8] = 0x10; + dev->pci_conf_sb[1][8] = 0x10; - dev->pci_conf_sb[1][0x09] = 0x0f; - dev->pci_conf_sb[1][0x0a] = dev->pci_conf_sb[1][0x0b] = 1; + dev->pci_conf_sb[1][0x09] = 0x0f; + dev->pci_conf_sb[1][0x0a] = dev->pci_conf_sb[1][0x0b] = 1; - umc_8886_ide_handler(1); + umc_8886_ide_handler(1); } - for (int i = 1; i < 5; i++) /* Disable all IRQ interrupts */ - pci_set_irq_routing(i, PCI_IRQ_DISABLED); + for (uint8_t i = 1; i < 5; i++) /* Disable all IRQ interrupts */ + pci_set_irq_routing(i, PCI_IRQ_DISABLED); cpu_set_isa_pci_div(3); cpu_set_pci_speed(cpu_busspeed / 2); } - static void umc_8886_close(void *priv) { - umc_8886_t *dev = (umc_8886_t *)priv; + umc_8886_t *dev = (umc_8886_t *) priv; free(dev); } - static void * umc_8886_init(const device_t *info) { - umc_8886_t *dev = (umc_8886_t *)malloc(sizeof(umc_8886_t)); + umc_8886_t *dev = (umc_8886_t *) malloc(sizeof(umc_8886_t)); memset(dev, 0, sizeof(umc_8886_t)); dev->has_ide = !!(info->local == 0x886a); - pci_add_card(PCI_ADD_SOUTHBRIDGE, umc_8886_read, umc_8886_write, dev); /* Device 12: UMC 8886xx */ + pci_add_card(PCI_ADD_SOUTHBRIDGE, umc_8886_read, umc_8886_write, dev, &dev->pci_slot); /* Device 12: UMC 8886xx */ /* Add IDE if UM8886AF variant */ if (HAS_IDE) - device_add(&ide_pci_2ch_device); + device_add(&ide_pci_2ch_device); dev->max_func = (HAS_IDE) ? 1 : 0; @@ -377,23 +392,30 @@ umc_8886_init(const device_t *info) return dev; } - const device_t umc_8886f_device = { - "UMC 8886F", - "umc_8886f", - DEVICE_PCI, - 0x8886, - umc_8886_init, umc_8886_close, umc_8886_reset, - { NULL }, NULL, NULL, - NULL + .name = "UMC 8886F", + .internal_name = "umc_8886f", + .flags = DEVICE_PCI, + .local = 0x8886, + .init = umc_8886_init, + .close = umc_8886_close, + .reset = umc_8886_reset, + { .available = NULL }, + .speed_changed = NULL, + .force_redraw = NULL, + .config = NULL }; const device_t umc_8886af_device = { - "UMC 8886AF/8886BF", - "umc_8886af", - DEVICE_PCI, - 0x886a, - umc_8886_init, umc_8886_close, umc_8886_reset, - { NULL }, NULL, NULL, - NULL + .name = "UMC 8886AF/8886BF", + .internal_name = "umc_8886af", + .flags = DEVICE_PCI, + .local = 0x886a, + .init = umc_8886_init, + .close = umc_8886_close, + .reset = umc_8886_reset, + { .available = NULL }, + .speed_changed = NULL, + .force_redraw = NULL, + .config = NULL }; diff --git a/src/chipset/umc_hb4.c b/src/chipset/umc_hb4.c index 8294323ad..d5cce0fca 100644 --- a/src/chipset/umc_hb4.c +++ b/src/chipset/umc_hb4.c @@ -1,24 +1,26 @@ /* - * 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. + * 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. + * This file is part of the 86Box distribution. * - * Implementation of the UMC HB4 "Super Energy Star Green" PCI Chipset. + * Implementation of the UMC HB4 "Super Energy Star Green" PCI Chipset. * - * Note: This chipset has no datasheet, everything were done via - * reverse engineering the BIOS of various machines using it. - * - * Note 2: Additional information were also used from all - * around the web. + * Note: This chipset has no datasheet, everything were done via + * reverse engineering the BIOS of various machines using it. * - * Authors: Tiseno100, - * Miran Grca, + * Note 2: Additional information were also used from all + * around the web. * - * Copyright 2021 Tiseno100. - * Copyright 2021 Miran Grca. + * + * + * Authors: Tiseno100, + * Miran Grca, + * + * Copyright 2021 Tiseno100. + * Copyright 2021 Miran Grca. */ /* @@ -81,11 +83,11 @@ Register 56h & 57h: DRAM Bank 0 Configuration Register 58h & 59h: DRAM Bank 1 Configuration - + Register 60: Bit 5: If set and SMRAM is enabled, data cycles go to PCI and code cycles go to DRAM Bit 0: SMRAM Local Access Enable - if set, SMRAM is also enabled outside SMM - SMRAM appears to always be enabled in SMM, and always set to A0000-BFFFF. + SMRAM appears to always be enabled in SMM, and always set to A0000-BFFFF. */ #include @@ -101,63 +103,47 @@ #include <86box/timer.h> #include <86box/io.h> #include <86box/device.h> - #include <86box/mem.h> #include <86box/pci.h> +#include <86box/plat_unused.h> #include <86box/port_92.h> #include <86box/smram.h> - -#ifdef USE_DYNAREC -# include "codegen_public.h" -#else -#ifdef USE_NEW_DYNAREC -# define PAGE_MASK_SHIFT 6 -#else -# define PAGE_MASK_INDEX_MASK 3 -# define PAGE_MASK_INDEX_SHIFT 10 -# define PAGE_MASK_SHIFT 4 -#endif -# define PAGE_MASK_MASK 63 -#endif #include <86box/chipset.h> - #ifdef ENABLE_HB4_LOG int hb4_do_log = ENABLE_HB4_LOG; - static void hb4_log(const char *fmt, ...) { va_list ap; if (hb4_do_log) { - va_start(ap, fmt); - pclog_ex(fmt, ap); - va_end(ap); + va_start(ap, fmt); + pclog_ex(fmt, ap); + va_end(ap); } } #else -#define hb4_log(fmt, ...) +# define hb4_log(fmt, ...) #endif +typedef struct hb4_t { + uint8_t shadow; + uint8_t shadow_read; + uint8_t shadow_write; + uint8_t pci_slot; -typedef struct hb4_t -{ - uint8_t shadow, - shadow_read, shadow_write, - pci_conf[256]; /* PCI Registers */ - int mem_state[9]; - smram_t *smram[3]; /* SMRAM Handlers */ + uint8_t pci_conf[256]; /* PCI Registers */ + int mem_state[9]; + smram_t *smram[3]; /* SMRAM Handlers */ } hb4_t; - -static int shadow_bios[4] = { (MEM_READ_EXTANY | MEM_WRITE_INTERNAL), (MEM_READ_EXTANY | MEM_WRITE_EXTANY), - (MEM_READ_INTERNAL | MEM_WRITE_INTERNAL), (MEM_READ_INTERNAL | MEM_WRITE_EXTANY) }; -static int shadow_read[2] = { MEM_READ_EXTANY, MEM_READ_INTERNAL }; +static int shadow_bios[4] = { (MEM_READ_EXTANY | MEM_WRITE_INTERNAL), (MEM_READ_EXTANY | MEM_WRITE_EXTANY), + (MEM_READ_INTERNAL | MEM_WRITE_INTERNAL), (MEM_READ_INTERNAL | MEM_WRITE_EXTANY) }; +static int shadow_read[2] = { MEM_READ_EXTANY, MEM_READ_INTERNAL }; static int shadow_write[2] = { MEM_WRITE_INTERNAL, MEM_WRITE_EXTANY }; - int hb4_shadow_bios_high(hb4_t *dev) { @@ -166,17 +152,16 @@ hb4_shadow_bios_high(hb4_t *dev) state = shadow_bios[dev->pci_conf[0x55] >> 6]; if (state != dev->mem_state[8]) { - mem_set_mem_state_both(0xf0000, 0x10000, state); - if ((dev->mem_state[8] & MEM_READ_INTERNAL) && !(state & MEM_READ_INTERNAL)) - mem_invalidate_range(0xf0000, 0xfffff); - dev->mem_state[8] = state; - return 1; + mem_set_mem_state_both(0xf0000, 0x10000, state); + if ((dev->mem_state[8] & MEM_READ_INTERNAL) && !(state & MEM_READ_INTERNAL)) + mem_invalidate_range(0xf0000, 0xfffff); + dev->mem_state[8] = state; + return 1; } return 0; } - int hb4_shadow_bios_low(hb4_t *dev) { @@ -185,54 +170,49 @@ hb4_shadow_bios_low(hb4_t *dev) state = shadow_bios[(dev->pci_conf[0x55] >> 6) & (dev->shadow | 0x01)]; if (state != dev->mem_state[7]) { - mem_set_mem_state_both(0xe0000, 0x10000, state); - dev->mem_state[7] = state; - return 1; + mem_set_mem_state_both(0xe0000, 0x10000, state); + dev->mem_state[7] = state; + return 1; } return 0; } - int hb4_shadow_main(hb4_t *dev) { - int i, state; + int state; int n = 0; - for (i = 0; i < 6; i++) { - state = shadow_read[dev->shadow && ((dev->pci_conf[0x54] >> (i + 2)) & 0x01)] | - shadow_write[(dev->pci_conf[0x55] >> 6) & 0x01]; + for (uint8_t i = 0; i < 6; i++) { + state = shadow_read[dev->shadow && ((dev->pci_conf[0x54] >> (i + 2)) & 0x01)] | shadow_write[(dev->pci_conf[0x55] >> 6) & 0x01]; - if (state != dev->mem_state[i + 1]) { - n++; - mem_set_mem_state_both(0xc8000 + (i << 14), 0x4000, state); - dev->mem_state[i + 1] = state; - } + if (state != dev->mem_state[i + 1]) { + n++; + mem_set_mem_state_both(0xc8000 + (i << 14), 0x4000, state); + dev->mem_state[i + 1] = state; + } } return n; } - int hb4_shadow_video(hb4_t *dev) { int state; - state = shadow_read[dev->shadow && ((dev->pci_conf[0x54] >> 1) & 0x01)] | - shadow_write[(dev->pci_conf[0x55] >> 6) & 0x01]; + state = shadow_read[dev->shadow && ((dev->pci_conf[0x54] >> 1) & 0x01)] | shadow_write[(dev->pci_conf[0x55] >> 6) & 0x01]; if (state != dev->mem_state[0]) { - mem_set_mem_state_both(0xc0000, 0x8000, state); - dev->mem_state[0] = state; - return 1; + mem_set_mem_state_both(0xc0000, 0x8000, state); + dev->mem_state[0] = state; + return 1; } return 0; } - void hb4_shadow(hb4_t *dev) { @@ -245,10 +225,9 @@ hb4_shadow(hb4_t *dev) n += hb4_shadow_video(dev); if (n > 0) - flushmmucache_nopc(); + flushmmucache_nopc(); } - static void hb4_smram(hb4_t *dev) { @@ -265,93 +244,96 @@ hb4_smram(hb4_t *dev) /* Bit 5 seems to set data to go to PCI and code to DRAM. The Samsung SPC7700P-LW uses this. */ if (dev->pci_conf[0x60] & 0x20) { - if (dev->pci_conf[0x60] & 0x01) - mem_set_mem_state_smram_ex(0, 0x000a0000, 0x20000, 0x02); - mem_set_mem_state_smram_ex(1, 0x000a0000, 0x20000, 0x02); + if (dev->pci_conf[0x60] & 0x01) + mem_set_mem_state_smram_ex(0, 0x000a0000, 0x20000, 0x02); + mem_set_mem_state_smram_ex(1, 0x000a0000, 0x20000, 0x02); } } - static void -hb4_write(int func, int addr, uint8_t val, void *priv) +hb4_write(UNUSED(int func), int addr, uint8_t val, void *priv) { - hb4_t *dev = (hb4_t *)priv; + hb4_t *dev = (hb4_t *) priv; hb4_log("UM8881: dev->regs[%02x] = %02x POST: %02x \n", addr, val, inb(0x80)); switch (addr) { - case 0x04: case 0x05: - dev->pci_conf[addr] = val; - break; + case 0x04: + case 0x05: + dev->pci_conf[addr] = val; + break; - case 0x07: - dev->pci_conf[addr] &= ~(val & 0xf9); - break; + case 0x07: + dev->pci_conf[addr] &= ~(val & 0xf9); + break; - case 0x0c: case 0x0d: - dev->pci_conf[addr] = val; - break; + case 0x0c: + case 0x0d: + dev->pci_conf[addr] = val; + break; - case 0x50: - dev->pci_conf[addr] = ((val & 0xf8) | 4); /* Hardcode Cache Size to 512KB */ - cpu_cache_ext_enabled = !!(val & 0x80); /* Fixes freezing issues on the HOT-433A*/ - cpu_update_waitstates(); - break; + case 0x50: + dev->pci_conf[addr] = ((val & 0xf8) | 4); /* Hardcode Cache Size to 512KB */ + cpu_cache_ext_enabled = !!(val & 0x80); /* Fixes freezing issues on the HOT-433A*/ + cpu_update_waitstates(); + break; - case 0x51: case 0x52: - dev->pci_conf[addr] = val; - break; + case 0x51: + case 0x52: + dev->pci_conf[addr] = val; + break; - case 0x53: - dev->pci_conf[addr] = val; - hb4_log("HB53: %02X\n", val); - break; + case 0x53: + dev->pci_conf[addr] = val; + hb4_log("HB53: %02X\n", val); + break; - case 0x55: - dev->shadow_read = (val & 0x80); - dev->shadow_write = (val & 0x40); - dev->pci_conf[addr] = val; - hb4_shadow(dev); - break; - case 0x54: - dev->shadow = (val & 0x01) << 1; - dev->pci_conf[addr] = val; - hb4_shadow(dev); - break; + case 0x55: + dev->shadow_read = (val & 0x80); + dev->shadow_write = (val & 0x40); + dev->pci_conf[addr] = val; + hb4_shadow(dev); + break; + case 0x54: + dev->shadow = (val & 0x01) << 1; + dev->pci_conf[addr] = val; + hb4_shadow(dev); + break; - case 0x56 ... 0x5f: - dev->pci_conf[addr] = val; - break; + case 0x56 ... 0x5f: + dev->pci_conf[addr] = val; + break; - case 0x60: - dev->pci_conf[addr] = val; - hb4_smram(dev); - break; + case 0x60: + dev->pci_conf[addr] = val; + hb4_smram(dev); + break; - case 0x61: - dev->pci_conf[addr] = val; - break; + case 0x61: + dev->pci_conf[addr] = val; + break; + + default: + break; } } - static uint8_t hb4_read(int func, int addr, void *priv) { - hb4_t *dev = (hb4_t *)priv; - uint8_t ret = 0xff; + const hb4_t *dev = (hb4_t *) priv; + uint8_t ret = 0xff; if (func == 0) - ret = dev->pci_conf[addr]; + ret = dev->pci_conf[addr]; return ret; } - static void hb4_reset(void *priv) { - hb4_t *dev = (hb4_t *)priv; + hb4_t *dev = (hb4_t *) priv; memset(dev->pci_conf, 0x00, sizeof(dev->pci_conf)); dev->pci_conf[0] = 0x60; /* UMC */ @@ -385,23 +367,21 @@ hb4_reset(void *priv) memset(dev->mem_state, 0x00, sizeof(dev->mem_state)); } - static void hb4_close(void *priv) { - hb4_t *dev = (hb4_t *)priv; + hb4_t *dev = (hb4_t *) priv; free(dev); } - static void * -hb4_init(const device_t *info) +hb4_init(UNUSED(const device_t *info)) { - hb4_t *dev = (hb4_t *)malloc(sizeof(hb4_t)); + hb4_t *dev = (hb4_t *) malloc(sizeof(hb4_t)); memset(dev, 0, sizeof(hb4_t)); - pci_add_card(PCI_ADD_NORTHBRIDGE, hb4_read, hb4_write, dev); /* Device 10: UMC 8881x */ + pci_add_card(PCI_ADD_NORTHBRIDGE, hb4_read, hb4_write, dev, &dev->pci_slot); /* Device 10: UMC 8881x */ /* Port 92 */ device_add(&port_92_pci_device); @@ -416,13 +396,16 @@ hb4_init(const device_t *info) return dev; } - const device_t umc_hb4_device = { - "UMC HB4(8881F)", - "umc_hb4", - DEVICE_PCI, - 0x886a, - hb4_init, hb4_close, hb4_reset, - { NULL }, NULL, NULL, - NULL + .name = "UMC HB4(8881F)", + .internal_name = "umc_hb4", + .flags = DEVICE_PCI, + .local = 0x886a, + .init = hb4_init, + .close = hb4_close, + .reset = hb4_reset, + { .available = NULL }, + .speed_changed = NULL, + .force_redraw = NULL, + .config = NULL }; diff --git a/src/chipset/via_apollo.c b/src/chipset/via_apollo.c index ea30c14c9..7c1203c3a 100644 --- a/src/chipset/via_apollo.c +++ b/src/chipset/via_apollo.c @@ -1,23 +1,22 @@ /* - * 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. + * 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. + * This file is part of the 86Box distribution. * - * Implementation of the VIA Apollo series of chips. + * Implementation of the VIA Apollo series of chips. * * * - * Authors: Sarah Walker, - * Miran Grca, - * Melissa Goad, - * Tiseno100, + * Authors: Miran Grca, + * RichardG, + * Tiseno100, * - * Copyright 2020 Miran Grca. - * Copyright 2020 Melissa Goad. - * Copyright 2020 Tiseno100. + * Copyright 2020 Miran Grca. + * Copyright 2020 RichardG. + * Copyright 2020 Tiseno100. */ #include #include @@ -33,7 +32,7 @@ #include <86box/pci.h> #include <86box/chipset.h> #include <86box/spd.h> -#include <86box/video.h> +#include <86box/agpgart.h> #define VIA_585 0x05851000 #define VIA_595 0x05950000 @@ -44,50 +43,53 @@ #define VIA_694 0x0691c200 #define VIA_8601 0x86010500 -typedef struct via_apollo_t -{ - uint32_t id; - uint8_t drb_unit; - uint8_t pci_conf[256]; +typedef struct via_apollo_t { + uint8_t drb_unit; + uint8_t pci_slot; + uint8_t pad; + uint8_t pad0; - smram_t *smram; - void *agpgart; + uint8_t pci_conf[256]; + + uint32_t id; + + smram_t *smram; + agpgart_t *agpgart; } via_apollo_t; - static void apollo_map(uint32_t addr, uint32_t size, int state) { switch (state & 3) { - case 0: - mem_set_mem_state_both(addr, size, MEM_READ_EXTANY | MEM_WRITE_EXTANY); - break; - case 1: - mem_set_mem_state_both(addr, size, MEM_READ_EXTANY | MEM_WRITE_INTERNAL); - break; - case 2: - mem_set_mem_state_both(addr, size, MEM_READ_INTERNAL | MEM_WRITE_EXTANY); - break; - case 3: - mem_set_mem_state_both(addr, size, MEM_READ_INTERNAL | MEM_WRITE_INTERNAL); - break; + case 0: + mem_set_mem_state_both(addr, size, MEM_READ_EXTANY | MEM_WRITE_EXTANY); + break; + case 1: + mem_set_mem_state_both(addr, size, MEM_READ_EXTANY | MEM_WRITE_INTERNAL); + break; + case 2: + mem_set_mem_state_both(addr, size, MEM_READ_INTERNAL | MEM_WRITE_EXTANY); + break; + case 3: + mem_set_mem_state_both(addr, size, MEM_READ_INTERNAL | MEM_WRITE_INTERNAL); + break; + default: + break; } flushmmucache_nopc(); } - static void apollo_smram_map(via_apollo_t *dev, int smm, uint32_t host_base, uint32_t size, int is_smram) { if (((is_smram & 0x03) == 0x01) || ((is_smram & 0x03) == 0x02)) - smram_enable(dev->smram, host_base, 0x000a0000, size, 0, 1); + smram_enable(dev->smram, host_base, 0x000a0000, size, 0, 1); mem_set_mem_state_smram_ex(smm, host_base, size, is_smram & 0x03); flushmmucache(); } - static void apollo_agp_map(via_apollo_t *dev) { @@ -96,17 +98,16 @@ apollo_agp_map(via_apollo_t *dev) dev->pci_conf[0x13] &= 0xf0 | (dev->pci_conf[0x84] >> 4); if (!dev->agpgart) - return; + return; /* Map aperture and GART. */ agpgart_set_aperture(dev->agpgart, - (dev->pci_conf[0x12] << 16) | (dev->pci_conf[0x13] << 24), - ((uint32_t) (uint8_t) ~dev->pci_conf[0x84] + 1) << 20, - !!(dev->pci_conf[0x88] & 0x02)); + (dev->pci_conf[0x12] << 16) | (dev->pci_conf[0x13] << 24), + ((uint32_t) (uint8_t) ~dev->pci_conf[0x84] + 1) << 20, + !!(dev->pci_conf[0x88] & 0x02)); agpgart_set_gart(dev->agpgart, (dev->pci_conf[0x89] << 8) | (dev->pci_conf[0x8a] << 16) | (dev->pci_conf[0x8b] << 24)); } - static void via_apollo_setup(via_apollo_t *dev) { @@ -120,9 +121,9 @@ via_apollo_setup(via_apollo_t *dev) dev->pci_conf[0x05] = 0; if ((dev->id >= VIA_585) || (dev->id < VIA_597)) - dev->pci_conf[0x06] = 0xa0; + dev->pci_conf[0x06] = 0xa0; else - dev->pci_conf[0x06] = 0x90; + dev->pci_conf[0x06] = 0x90; dev->pci_conf[0x07] = 0x02; @@ -136,30 +137,30 @@ via_apollo_setup(via_apollo_t *dev) dev->pci_conf[0x0f] = 0; if (dev->id >= VIA_597) { - dev->pci_conf[0x10] = 0x08; - dev->pci_conf[0x34] = 0xa0; + dev->pci_conf[0x10] = 0x08; + dev->pci_conf[0x34] = 0xa0; } if ((dev->id >= VIA_585) || (dev->id < VIA_597)) - dev->pci_conf[0x52] = 0x02; + dev->pci_conf[0x52] = 0x02; else if (dev->id >= VIA_694) - dev->pci_conf[0x52] = (dev->id == VIA_694) ? 0x90 : 0x10; + dev->pci_conf[0x52] = (dev->id == VIA_694) ? 0x90 : 0x10; if (dev->id >= VIA_693A) - dev->pci_conf[0x53] = 0x10; + dev->pci_conf[0x53] = 0x10; if (dev->id == VIA_691) { - dev->pci_conf[0x56] = 0x01; - dev->pci_conf[0x57] = 0x01; + dev->pci_conf[0x56] = 0x01; + dev->pci_conf[0x57] = 0x01; } if (dev->id >= VIA_694) - dev->pci_conf[0x58] = 0x40; + dev->pci_conf[0x58] = 0x40; else if (dev->id >= VIA_585) - dev->pci_conf[0x58] = 0x05; + dev->pci_conf[0x58] = 0x05; if ((dev->id >= VIA_585) || (dev->id < VIA_597)) - dev->pci_conf[0x59] = 0x02; + dev->pci_conf[0x59] = 0x02; dev->pci_conf[0x5a] = 0x01; dev->pci_conf[0x5b] = 0x01; @@ -170,526 +171,536 @@ via_apollo_setup(via_apollo_t *dev) dev->pci_conf[0x64] = ((dev->id >= VIA_585) || (dev->id < VIA_597)) ? 0xab : 0xec; if (dev->id >= VIA_597) { - dev->pci_conf[0x65] = 0xec; - dev->pci_conf[0x66] = 0xec; + dev->pci_conf[0x65] = 0xec; + dev->pci_conf[0x66] = 0xec; } if (dev->id >= VIA_691) - dev->pci_conf[0x67] = 0xec; /* DRAM Timing for Banks 6, 7 */ + dev->pci_conf[0x67] = 0xec; /* DRAM Timing for Banks 6, 7 */ if (dev->id >= VIA_693A) { - if (cpu_busspeed < 95000000) { /* 66 MHz */ - cpu_set_pci_speed(cpu_busspeed / 2); - cpu_set_agp_speed(cpu_busspeed); - dev->pci_conf[0x68] |= 0x00; - } else if (cpu_busspeed < 124000000) { /* 100 MHz */ - cpu_set_pci_speed(cpu_busspeed / 3); - cpu_set_agp_speed(cpu_busspeed / 1.5); - dev->pci_conf[0x68] |= 0x01; - } else { /* 133 MHz */ - cpu_set_pci_speed(cpu_busspeed / 4); - cpu_set_agp_speed(cpu_busspeed / 2); - dev->pci_conf[0x68] |= (dev->id == VIA_8601) ? 0x03 : 0x02; - } + if (cpu_busspeed < 95000000) { /* 66 MHz */ + cpu_set_pci_speed(cpu_busspeed / 2); + cpu_set_agp_speed(cpu_busspeed); + dev->pci_conf[0x68] |= 0x00; + } else if (cpu_busspeed < 124000000) { /* 100 MHz */ + cpu_set_pci_speed(cpu_busspeed / 3); + cpu_set_agp_speed(cpu_busspeed / 1.5); + dev->pci_conf[0x68] |= 0x01; + } else { /* 133 MHz */ + cpu_set_pci_speed(cpu_busspeed / 4); + cpu_set_agp_speed(cpu_busspeed / 2); + dev->pci_conf[0x68] |= (dev->id == VIA_8601) ? 0x03 : 0x02; + } } else if (dev->id >= VIA_598) { - if (cpu_busspeed < ((dev->id >= VIA_691) ? 100000000 : 75000000)) { /* 66 MHz */ - cpu_set_pci_speed(cpu_busspeed / 2); - cpu_set_agp_speed(cpu_busspeed); - dev->pci_conf[0x68] |= 0x00; - } else if (cpu_busspeed < 100000000) { /* 75/83 MHz (not available on 691) */ - cpu_set_pci_speed(cpu_busspeed / 2.5); - cpu_set_agp_speed(cpu_busspeed / 1.25); - dev->pci_conf[0x68] |= 0x03; - } else { /* 100 MHz */ - cpu_set_pci_speed(cpu_busspeed / 3); - cpu_set_agp_speed(cpu_busspeed / 1.5); - dev->pci_conf[0x68] |= 0x01; - } + if (cpu_busspeed < ((dev->id >= VIA_691) ? 100000000 : 75000000)) { /* 66 MHz */ + cpu_set_pci_speed(cpu_busspeed / 2); + cpu_set_agp_speed(cpu_busspeed); + dev->pci_conf[0x68] |= 0x00; + } else if (cpu_busspeed < 100000000) { /* 75/83 MHz (not available on 691) */ + cpu_set_pci_speed(cpu_busspeed / 2.5); + cpu_set_agp_speed(cpu_busspeed / 1.25); + dev->pci_conf[0x68] |= 0x03; + } else { /* 100 MHz */ + cpu_set_pci_speed(cpu_busspeed / 3); + cpu_set_agp_speed(cpu_busspeed / 1.5); + dev->pci_conf[0x68] |= 0x01; + } } dev->pci_conf[0x6b] = 0x01; if (dev->id >= VIA_597) { - dev->pci_conf[0xa0] = 0x02; - dev->pci_conf[0xa2] = 0x10; - dev->pci_conf[0xa4] = 0x03; - dev->pci_conf[0xa5] = 0x02; - dev->pci_conf[0xa7] = 0x07; + dev->pci_conf[0xa0] = 0x02; + dev->pci_conf[0xa2] = 0x10; + dev->pci_conf[0xa4] = 0x03; + dev->pci_conf[0xa5] = 0x02; + dev->pci_conf[0xa7] = 0x07; - if (dev->id == VIA_693A) { - dev->pci_conf[0xac] = 0x08; - dev->pci_conf[0xad] = 0x02; - } + if (dev->id == VIA_693A) { + dev->pci_conf[0xac] = 0x08; + dev->pci_conf[0xad] = 0x02; + } - if (dev->id == VIA_694) { - dev->pci_conf[0xb0] = 0x80; /* The datasheet refers it as 8xh */ - dev->pci_conf[0xb1] = 0x63; - } + if (dev->id == VIA_694) { + dev->pci_conf[0xb0] = 0x80; /* The datasheet refers it as 8xh */ + dev->pci_conf[0xb1] = 0x63; + } } } - static void via_apollo_host_bridge_write(int func, int addr, uint8_t val, void *priv) { via_apollo_t *dev = (via_apollo_t *) priv; if (func) - return; - + return; + /*Read-only addresses*/ - if ((addr < 4) || ((addr > 5) && (addr < 7)) || ((addr >= 8) && (addr < 0xd)) || - ((addr >= 0xe) && (addr != 0x0f) && (addr < 0x12)) || ((addr >= 0x14) && (addr < 0x50)) || - ((addr > 0x7a) && (addr < 0x7e)) || ((addr >= 0x81) && (addr < 0x84)) || - ((addr >= 0x85) && (addr < 0x88)) || ((addr >= 0x8c) && (addr < 0xa8)) || - ((addr >= 0xaa) && (addr < 0xac)) || ((addr > 0xad) && (addr < 0xf0)) || - ((addr >= 0xf8) && (addr < 0xfc))) - return; + if ((addr < 4) || ((addr > 5) && (addr < 7)) || ((addr >= 8) && (addr < 0xd)) || ((addr >= 0xe) && (addr != 0x0f) && (addr < 0x12)) || ((addr >= 0x14) && (addr < 0x50)) || ((addr > 0x7a) && (addr < 0x7e)) || ((addr >= 0x81) && (addr < 0x84)) || ((addr >= 0x85) && (addr < 0x88)) || ((addr >= 0x8c) && (addr < 0xa8)) || ((addr >= 0xaa) && (addr < 0xac)) || ((addr > 0xad) && (addr < 0xf0)) || ((addr >= 0xf8) && (addr < 0xfc))) + return; if (((addr == 0x12) || (addr == 0x13)) && (dev->id < VIA_597)) - return; + return; if (((addr == 0x78) || (addr >= 0xad)) && (dev->id == VIA_597)) - return; + return; if (((addr == 0x67) || ((addr >= 0xf0) && (addr < 0xfc))) && (dev->id < VIA_691)) - return; + return; - switch(addr) { - case 0x04: - dev->pci_conf[0x04] = (dev->pci_conf[0x04] & ~0x40) | (val & 0x40); - break; + switch (addr) { + case 0x04: + dev->pci_conf[0x04] = (dev->pci_conf[0x04] & ~0x40) | (val & 0x40); + break; - case 0x05: - if((dev->id >= VIA_585) || (dev->id < VIA_597)) - dev->pci_conf[0x05] = (dev->pci_conf[0x05] & ~0x03) | (val & 0x03); - else - dev->pci_conf[0x05] = val; - break; - - case 0x07: - dev->pci_conf[0x07] &= ~(val & 0xb0); - break; - case 0x0d: - if(dev->id == VIA_8601) - dev->pci_conf[0x0d] = (dev->pci_conf[0x0d] & ~0x07) | (val & 0x07); - else if(dev->id == VIA_694) - dev->pci_conf[0x0d] = (dev->pci_conf[0x0d] & ~0xf8) | (val & 0xf8); - else - dev->pci_conf[0x0d] = (dev->pci_conf[0x0d] & ~0x07) | (val & 0x07); + case 0x05: + if ((dev->id >= VIA_585) || (dev->id < VIA_597)) + dev->pci_conf[0x05] = (dev->pci_conf[0x05] & ~0x03) | (val & 0x03); + else + dev->pci_conf[0x05] = val; + break; - dev->pci_conf[0x75] = (dev->pci_conf[0x75] & ~0x30) | ((val & 0x06) << 3); - break; + case 0x07: + dev->pci_conf[0x07] &= ~(val & 0xb0); + break; + case 0x0d: + if (dev->id == VIA_8601) + dev->pci_conf[0x0d] = (dev->pci_conf[0x0d] & ~0x07) | (val & 0x07); + else if (dev->id == VIA_694) + dev->pci_conf[0x0d] = (dev->pci_conf[0x0d] & ~0xf8) | (val & 0xf8); + else + dev->pci_conf[0x0d] = (dev->pci_conf[0x0d] & ~0x07) | (val & 0x07); - case 0x0f: - if((dev->id >= VIA_585) || (dev->id < VIA_597)) - dev->pci_conf[0x0f] = (dev->pci_conf[0x0f] & ~0xcf) | (val & 0x0cf); - else - dev->pci_conf[0x0f] = val; - break; - case 0x12: /* Graphics Aperture Base */ - dev->pci_conf[0x12] = (val & 0xf0); - apollo_agp_map(dev); - break; - case 0x13: /* Graphics Aperture Base */ - dev->pci_conf[0x13] = val; - apollo_agp_map(dev); - break; + dev->pci_conf[0x75] = (dev->pci_conf[0x75] & ~0x30) | ((val & 0x06) << 3); + break; - case 0x50: /* Cache Control 1 */ - if (dev->id == VIA_8601) - dev->pci_conf[0x50] = (dev->pci_conf[0x50] & ~0xd3) | (val & 0xd3); - else if (dev->id >= VIA_693A) - dev->pci_conf[0x50] = (dev->pci_conf[0x50] & ~0xd1) | (val & 0xd1); - else if (dev->id == VIA_595) - dev->pci_conf[0x50] = (dev->pci_conf[0x50] & ~0xfb) | (val & 0xfb); - else if ((dev->id == VIA_585) || (dev->id == VIA_691)) - dev->pci_conf[0x50] = val; - else - dev->pci_conf[0x50] = (dev->pci_conf[0x50] & ~0xf8) | (val & 0xf8); - break; - case 0x51: /* Cache Control 2 */ - if (dev->id == VIA_694) - dev->pci_conf[0x51] = (dev->pci_conf[0x51] & ~0xdd) | (val & 0xdd); - else if (dev->id >= VIA_693A) - dev->pci_conf[0x51] = (dev->pci_conf[0x51] & ~0xd9) | (val & 0xd9); - else if (dev->id >= VIA_691) - dev->pci_conf[0x51] = val; - else if ((dev->id >= VIA_585) || (dev->id < VIA_597)) - dev->pci_conf[0x51] = (dev->pci_conf[0x51] & ~0x2b) | (val & 0x2b); - else - dev->pci_conf[0x51] = (dev->pci_conf[0x51] & ~0xeb) | (val & 0xeb); - break; - case 0x52: /* Non_Cacheable Control */ - if (dev->id == VIA_8601) - dev->pci_conf[0x52] = (dev->pci_conf[0x52] & ~0xdf) | (val & 0xdf); - else if (dev->id >= VIA_693A) - dev->pci_conf[0x52] = val; - else if (dev->id == VIA_691) - dev->pci_conf[0x52] = (dev->pci_conf[0x52] & ~0x9f) | (val & 0x9f); - else - dev->pci_conf[0x52] = (dev->pci_conf[0x52] & ~0xf5) | (val & 0xf5); - break; - case 0x53: /* System Performance Control */ - if (dev->id == VIA_8601) - dev->pci_conf[0x53] = (dev->pci_conf[0x53] & ~0xfc) | (val & 0xfc); - else if ((dev->id == VIA_691) || (dev->id == VIA_694)) - dev->pci_conf[0x53] = val; - else if ((dev->id >= VIA_585) || (dev->id < VIA_597) || (dev->id == VIA_693A)) - dev->pci_conf[0x53] = (dev->pci_conf[0x53] & ~0xf8) | (val & 0xf8); - else - dev->pci_conf[0x53] = (dev->pci_conf[0x53] & ~0xf0) | (val & 0xf0); - break; - case 0x54: - if (dev->id == VIA_585) - dev->pci_conf[0x54] = val; - else - dev->pci_conf[0x54] = (dev->pci_conf[0x54] & ~0x07) | (val & 0x07); - break; + case 0x0f: + if ((dev->id >= VIA_585) || (dev->id < VIA_597)) + dev->pci_conf[0x0f] = (dev->pci_conf[0x0f] & ~0xcf) | (val & 0x0cf); + else + dev->pci_conf[0x0f] = val; + break; + case 0x12: /* Graphics Aperture Base */ + dev->pci_conf[0x12] = (val & 0xf0); + apollo_agp_map(dev); + break; + case 0x13: /* Graphics Aperture Base */ + dev->pci_conf[0x13] = val; + apollo_agp_map(dev); + break; - case 0x56: case 0x57: case 0x5a: case 0x5b: case 0x5c: case 0x5d: case 0x5e: case 0x5f: /* DRAM Row Ending Address */ - if ((dev->id >= VIA_691) && (dev->id != VIA_8601)) - spd_write_drbs(dev->pci_conf, 0x5a, 0x56, dev->drb_unit); - else if (addr >= 0x5a) - spd_write_drbs(dev->pci_conf, 0x5a, 0x5f, dev->drb_unit); - break; + case 0x50: /* Cache Control 1 */ + if (dev->id == VIA_8601) + dev->pci_conf[0x50] = (dev->pci_conf[0x50] & ~0xd3) | (val & 0xd3); + else if (dev->id >= VIA_693A) + dev->pci_conf[0x50] = (dev->pci_conf[0x50] & ~0xd1) | (val & 0xd1); + else if (dev->id == VIA_595) + dev->pci_conf[0x50] = (dev->pci_conf[0x50] & ~0xfb) | (val & 0xfb); + else if ((dev->id == VIA_585) || (dev->id == VIA_691)) + dev->pci_conf[0x50] = val; + else + dev->pci_conf[0x50] = (dev->pci_conf[0x50] & ~0xf8) | (val & 0xf8); + break; + case 0x51: /* Cache Control 2 */ + if (dev->id == VIA_694) + dev->pci_conf[0x51] = (dev->pci_conf[0x51] & ~0xdd) | (val & 0xdd); + else if (dev->id >= VIA_693A) + dev->pci_conf[0x51] = (dev->pci_conf[0x51] & ~0xd9) | (val & 0xd9); + else if (dev->id >= VIA_691) + dev->pci_conf[0x51] = val; + else if ((dev->id >= VIA_585) || (dev->id < VIA_597)) + dev->pci_conf[0x51] = (dev->pci_conf[0x51] & ~0x2b) | (val & 0x2b); + else + dev->pci_conf[0x51] = (dev->pci_conf[0x51] & ~0xeb) | (val & 0xeb); + break; + case 0x52: /* Non_Cacheable Control */ + if (dev->id == VIA_8601) + dev->pci_conf[0x52] = (dev->pci_conf[0x52] & ~0xdf) | (val & 0xdf); + else if (dev->id >= VIA_693A) + dev->pci_conf[0x52] = val; + else if (dev->id == VIA_691) + dev->pci_conf[0x52] = (dev->pci_conf[0x52] & ~0x9f) | (val & 0x9f); + else + dev->pci_conf[0x52] = (dev->pci_conf[0x52] & ~0xf5) | (val & 0xf5); + break; + case 0x53: /* System Performance Control */ + if (dev->id == VIA_8601) + dev->pci_conf[0x53] = (dev->pci_conf[0x53] & ~0xfc) | (val & 0xfc); + else if ((dev->id == VIA_691) || (dev->id == VIA_694)) + dev->pci_conf[0x53] = val; + else if ((dev->id >= VIA_585) || (dev->id < VIA_597) || (dev->id == VIA_693A)) + dev->pci_conf[0x53] = (dev->pci_conf[0x53] & ~0xf8) | (val & 0xf8); + else + dev->pci_conf[0x53] = (dev->pci_conf[0x53] & ~0xf0) | (val & 0xf0); + break; + case 0x54: + if (dev->id == VIA_585) + dev->pci_conf[0x54] = val; + else + dev->pci_conf[0x54] = (dev->pci_conf[0x54] & ~0x07) | (val & 0x07); + break; - case 0x58: - if ((dev->id >= VIA_585) || (dev->id < VIA_597) || (dev->id == VIA_597) || ((dev->id >= VIA_693A) || (dev->id < VIA_8601))) - dev->pci_conf[0x58] = (dev->pci_conf[0x58] & ~0xee) | (val & 0xee); - else - dev->pci_conf[0x58] = val; - break; - case 0x59: - if (dev->id >= VIA_693A) - dev->pci_conf[0x59] = (dev->pci_conf[0x59] & ~0xee) | (val & 0xee); - else if (dev->id == VIA_691) - dev->pci_conf[0x59] = val; - else if ((dev->id >= VIA_585) || (dev->id < VIA_597)) - dev->pci_conf[0x59] = (dev->pci_conf[0x59] & ~0xe7) | (val & 0xe7); - else - dev->pci_conf[0x59] = (dev->pci_conf[0x59] & ~0xf0) | (val & 0xf0); - break; + case 0x56: + case 0x57: + case 0x5a: + case 0x5b: + case 0x5c: + case 0x5d: + case 0x5e: + case 0x5f: /* DRAM Row Ending Address */ + if ((dev->id >= VIA_691) && (dev->id != VIA_8601)) + spd_write_drbs(dev->pci_conf, 0x5a, 0x56, dev->drb_unit); + else if (addr >= 0x5a) + spd_write_drbs(dev->pci_conf, 0x5a, 0x5f, dev->drb_unit); + break; - case 0x61: /* Shadow RAM Control 1 */ - apollo_map(0xc0000, 0x04000, val & 0x03); - apollo_map(0xc4000, 0x04000, (val & 0x0c) >> 2); - apollo_map(0xc8000, 0x04000, (val & 0x30) >> 4); - apollo_map(0xcc000, 0x04000, (val & 0xc0) >> 6); + case 0x58: + if ((dev->id >= VIA_585) || (dev->id < VIA_597) || (dev->id == VIA_597) || ((dev->id >= VIA_693A) || (dev->id < VIA_8601))) + dev->pci_conf[0x58] = (dev->pci_conf[0x58] & ~0xee) | (val & 0xee); + else + dev->pci_conf[0x58] = val; + break; + case 0x59: + if (dev->id >= VIA_693A) + dev->pci_conf[0x59] = (dev->pci_conf[0x59] & ~0xee) | (val & 0xee); + else if (dev->id == VIA_691) + dev->pci_conf[0x59] = val; + else if ((dev->id >= VIA_585) || (dev->id < VIA_597)) + dev->pci_conf[0x59] = (dev->pci_conf[0x59] & ~0xe7) | (val & 0xe7); + else + dev->pci_conf[0x59] = (dev->pci_conf[0x59] & ~0xf0) | (val & 0xf0); + break; - dev->pci_conf[0x61] = val; - break; - case 0x62: /* Shadow RAM Control 2 */ - apollo_map(0xd0000, 0x04000, val & 0x03); - apollo_map(0xd4000, 0x04000, (val & 0x0c) >> 2); - apollo_map(0xd8000, 0x04000, (val & 0x30) >> 4); - apollo_map(0xdc000, 0x04000, (val & 0xc0) >> 6); + case 0x61: /* Shadow RAM Control 1 */ + apollo_map(0xc0000, 0x04000, val & 0x03); + apollo_map(0xc4000, 0x04000, (val & 0x0c) >> 2); + apollo_map(0xc8000, 0x04000, (val & 0x30) >> 4); + apollo_map(0xcc000, 0x04000, (val & 0xc0) >> 6); - dev->pci_conf[0x62] = val; - break; - case 0x63: /* Shadow RAM Control 3 */ - shadowbios = 0; - shadowbios_write = 0; + dev->pci_conf[0x61] = val; + break; + case 0x62: /* Shadow RAM Control 2 */ + apollo_map(0xd0000, 0x04000, val & 0x03); + apollo_map(0xd4000, 0x04000, (val & 0x0c) >> 2); + apollo_map(0xd8000, 0x04000, (val & 0x30) >> 4); + apollo_map(0xdc000, 0x04000, (val & 0xc0) >> 6); - apollo_map(0xf0000, 0x10000, (val & 0x30) >> 4); - shadowbios = (((val & 0x30) >> 4) & 0x02); - shadowbios_write = (((val & 0x30) >> 4) & 0x01); + dev->pci_conf[0x62] = val; + break; + case 0x63: /* Shadow RAM Control 3 */ + shadowbios = 0; + shadowbios_write = 0; - apollo_map(0xe0000, 0x10000, (val & 0xc0) >> 6); - shadowbios |= (((val & 0xc0) >> 6) & 0x02); - shadowbios_write |= (((val & 0xc0) >> 6) & 0x01); + apollo_map(0xf0000, 0x10000, (val & 0x30) >> 4); + shadowbios = (((val & 0x30) >> 4) & 0x02); + shadowbios_write = (((val & 0x30) >> 4) & 0x01); - dev->pci_conf[0x63] = val; - smram_disable_all(); - if (dev->id >= VIA_691) switch (val & 0x03) { - case 0x00: - default: - apollo_smram_map(dev, 1, 0x000a0000, 0x00020000, 1); /* SMM: Code DRAM, Data DRAM */ - apollo_smram_map(dev, 0, 0x000a0000, 0x00020000, 0); /* Non-SMM: Code PCI, Data PCI */ - break; - case 0x01: - apollo_smram_map(dev, 1, 0x000a0000, 0x00020000, 1); /* SMM: Code DRAM, Data DRAM */ - apollo_smram_map(dev, 0, 0x000a0000, 0x00020000, 1); /* Non-SMM: Code DRAM, Data DRAM */ - break; - case 0x02: - apollo_smram_map(dev, 1, 0x000a0000, 0x00020000, 3); /* SMM: Code Invalid, Data Invalid */ - apollo_smram_map(dev, 0, 0x000a0000, 0x00020000, 2); /* Non-SMM: Code DRAM, Data PCI */ - break; - case 0x03: - apollo_smram_map(dev, 1, 0x000a0000, 0x00020000, 1); /* SMM: Code DRAM, Data DRAM */ - apollo_smram_map(dev, 0, 0x000a0000, 0x00020000, 3); /* Non-SMM: Code Invalid, Data Invalid */ - break; - } else if (dev->id >= VIA_597) switch (val & 0x03) { - case 0x00: - default: - /* Disable SMI Address Redirection (default) */ - apollo_smram_map(dev, 1, 0x000a0000, 0x00020000, 0); - apollo_smram_map(dev, 0, 0x000a0000, 0x00020000, 0); - break; - case 0x01: - /* Allow access to DRAM Axxxx-Bxxxx for both normal and SMI cycles */ - apollo_smram_map(dev, 1, 0x000a0000, 0x00020000, 1); - apollo_smram_map(dev, 0, 0x000a0000, 0x00020000, 1); - break; - case 0x02: - /* Reserved */ - apollo_smram_map(dev, 1, 0x000a0000, 0x00020000, 3); - if (dev->id == VIA_597) { - /* SMI 3xxxx-4xxxx redirect to Axxxx-Bxxxx. */ - apollo_smram_map(dev, 1, 0x00030000, 0x00020000, 1); - } - apollo_smram_map(dev, 0, 0x000a0000, 0x00020000, 3); - break; - case 0x03: - /* Allow SMI Axxxx-Bxxxx DRAM access */ - apollo_smram_map(dev, 1, 0x000a0000, 0x00020000, 1); - apollo_smram_map(dev, 0, 0x000a0000, 0x00020000, 0); - break; - } else switch(val & 0x03) { - case 0x00: - apollo_smram_map(dev, 1, 0x000a0000, 0x00020000, 0); - apollo_smram_map(dev, 0, 0x000a0000, 0x00020000, 0); - break; - case 0x01: - apollo_smram_map(dev, 1, 0x000a0000, 0x00020000, 1); - apollo_smram_map(dev, 0, 0x000a0000, 0x00020000, 0); - break; - case 0x02: - apollo_smram_map(dev, 1, 0x00030000, 0x00020000, 1); - apollo_smram_map(dev, 0, 0x000a0000, 0x00020000, 3); - break; - case 0x03: - apollo_smram_map(dev, 1, 0x000a0000, 0x00020000, 1); - apollo_smram_map(dev, 0, 0x000a0000, 0x00020000, 1); - apollo_smram_map(dev, 1, 0x000a0000, 0x00020000, 3); - apollo_smram_map(dev, 0, 0x000a0000, 0x00020000, 3); - break; - } - break; - case 0x65: - if (dev->id == VIA_585) - dev->pci_conf[0x65] = (dev->pci_conf[0x65] & ~0xfd) | (val & 0xfd); - else if (dev->id == VIA_595) - dev->pci_conf[0x65] = (dev->pci_conf[0x65] & ~0xf9) | (val & 0xf9); - else - dev->pci_conf[0x65] = val; - break; - case 0x66: - if (dev->id == VIA_585) - dev->pci_conf[0x66] = (dev->pci_conf[0x66] & ~0xaf) | (val & 0xaf); - else if (dev->id == VIA_595) - dev->pci_conf[0x66] = (dev->pci_conf[0x66] & ~0x8f) | (val & 0x8f); - else - dev->pci_conf[0x66] = val; - break; - case 0x68: - if (dev->id != VIA_595) { - if (dev->id == VIA_597) - dev->pci_conf[0x68] = (dev->pci_conf[0x68] & ~0xfe) | (val & 0xfe); - else if ((dev->id == VIA_693A) || (dev->id == VIA_694)) - dev->pci_conf[0x68] = (dev->pci_conf[0x68] & ~0xdc) | (val & 0xdc); - else - dev->pci_conf[0x68] = (dev->pci_conf[0x68] & ~0xfc) | (val & 0xfc); - } - break; - case 0x69: - if ((dev->id != VIA_585) || (dev->id != VIA_595)){ - if ((dev->id == VIA_693A) || (dev->id < VIA_8601)) - dev->pci_conf[0x69] = (dev->pci_conf[0x69] & ~0xfe) | (val & 0xfe); - else - dev->pci_conf[0x69] = val; - } - break; - case 0x6b: - if ((dev->id == VIA_693A) || (dev->id < VIA_8601)) - dev->pci_conf[0x6b] = val; - else if (dev->id == VIA_691) - dev->pci_conf[0x6b] = (dev->pci_conf[0x6b] & ~0xcf) | (val & 0xcf); - else if (dev->id == VIA_595) - dev->pci_conf[0x6b] = (dev->pci_conf[0x6b] & ~0xc0) | (val & 0xc0); - else if (dev->id == VIA_585) - dev->pci_conf[0x6b] = (dev->pci_conf[0x6b] & ~0xc4) | (val & 0xc4); - else - dev->pci_conf[0x6b] = (dev->pci_conf[0x6b] & ~0xc1) | (val & 0xc1); - break; - case 0x6c: - if ((dev->id == VIA_597) || ((dev->id == VIA_693A) || (dev->id < VIA_8601))) - dev->pci_conf[0x6c] = (dev->pci_conf[0x6c] & ~0x1f) | (val & 0x1f); - else if (dev->id == VIA_598) - dev->pci_conf[0x6c] = (dev->pci_conf[0x6c] & ~0x7f) | (val & 0x7f); - else if (dev->id == VIA_585) - dev->pci_conf[0x6c] = (dev->pci_conf[0x6c] & ~0xef) | (val & 0xef); - else - dev->pci_conf[0x6c] = val; - break; - case 0x6d: - if ((dev->id == VIA_597) || (dev->id == VIA_694)) - dev->pci_conf[0x6d] = (dev->pci_conf[0x6d] & ~0x0f) | (val & 0x0f); - else if ((dev->id == VIA_598) || (dev->id == VIA_693A) || (dev->id == VIA_8601)) - dev->pci_conf[0x6d] = (dev->pci_conf[0x6d] & ~0x7f) | (val & 0x7f); - else - dev->pci_conf[0x6d] = val; - break; - case 0x6e: - if((dev->id == VIA_595) || (dev->id == VIA_694)) - dev->pci_conf[0x6e] = val; - else - dev->pci_conf[0x6e] = (dev->pci_conf[0x6e] & ~0xb7) | (val & 0xb7); - break; + apollo_map(0xe0000, 0x10000, (val & 0xc0) >> 6); + shadowbios |= (((val & 0xc0) >> 6) & 0x02); + shadowbios_write |= (((val & 0xc0) >> 6) & 0x01); - case 0x70: - if ((dev->id >= VIA_693A)) - dev->pci_conf[0x70] = (dev->pci_conf[0x70] & ~0xdf) | (val & 0xdf); - else if (dev->id == VIA_597) - dev->pci_conf[0x70] = (dev->pci_conf[0x70] & ~0xf1) | (val & 0xf1); - else if ((dev->id >= VIA_585) || (dev->id < VIA_597)) - dev->pci_conf[0x70] = (dev->pci_conf[0x70] & ~0xe3) | (val & 0xe3); - else - dev->pci_conf[0x70] = val; - break; - case 0x71: - if((dev->id >= VIA_585) || (dev->id == VIA_694)) - dev->pci_conf[0x71] = (dev->pci_conf[0x71] & ~0xdf) | (val & 0xdf); - else - dev->pci_conf[0x71] = val; - break; - case 0x73: - if (dev->id >= VIA_693A) - dev->pci_conf[0x73] = (dev->pci_conf[0x73] & ~0x7f) | (val & 0x7f); - else if ((dev->id >= VIA_585) || (dev->id < VIA_597)) - dev->pci_conf[0x73] = (dev->pci_conf[0x73] & ~0xef) | (val & 0xef); - else - dev->pci_conf[0x73] = val; - break; - case 0x74: - if ((dev->id == VIA_693A) || (dev->id == VIA_8601)) - dev->pci_conf[0x74] = (dev->pci_conf[0x74] & ~0xdf) | (val & 0xdf); - else if (dev->id == VIA_694) - dev->pci_conf[0x74] = (dev->pci_conf[0x74] & ~0x9f) | (val & 0x9f); - else - dev->pci_conf[0x74] = (dev->pci_conf[0x74] & ~0xc0) | (val & 0xc0); - break; - case 0x75: - if (dev->id >= VIA_693A) - dev->pci_conf[0x75] = val; - else - dev->pci_conf[0x75] = (dev->pci_conf[0x75] & ~0xcf) | (val & 0xcf); - break; - case 0x76: - if (dev->id >= VIA_693A) - dev->pci_conf[0x76] = val; - else if ((dev->id >= VIA_585) || (dev->id < VIA_597)) - dev->pci_conf[0x76] = (dev->pci_conf[0x76] & ~0xb0) | (val & 0xb0); - else - dev->pci_conf[0x76] = (dev->pci_conf[0x76] & ~0xf0) | (val & 0xf0); - break; - case 0x77: - if (dev->id < VIA_693A) - dev->pci_conf[0x77] = (dev->pci_conf[0x77] & ~0xc0) | (val & 0xc0); - break; - case 0x78: - dev->pci_conf[0x78] = (dev->pci_conf[0x78] & ~0xd5) | (val & 0xd5); - break; - case 0x79: - dev->pci_conf[0x79] = (dev->pci_conf[0x79] & ~0xfc) | (val & 0xfc); - break; - case 0x7a: - dev->pci_conf[0x7a] = (dev->pci_conf[0x7a] & ~0x89) | (val & 0x89); - break; - case 0x7e: - if ((dev->id != VIA_8601) || (dev->id != VIA_694)) - dev->pci_conf[0x7e] = (dev->pci_conf[0x7e] & ~0x3f) | (val & 0x3f); - break; + dev->pci_conf[0x63] = val; + smram_disable_all(); + if (dev->id >= VIA_691) + switch (val & 0x03) { + default: + case 0x00: + apollo_smram_map(dev, 1, 0x000a0000, 0x00020000, 1); /* SMM: Code DRAM, Data DRAM */ + apollo_smram_map(dev, 0, 0x000a0000, 0x00020000, 0); /* Non-SMM: Code PCI, Data PCI */ + break; + case 0x01: + apollo_smram_map(dev, 1, 0x000a0000, 0x00020000, 1); /* SMM: Code DRAM, Data DRAM */ + apollo_smram_map(dev, 0, 0x000a0000, 0x00020000, 1); /* Non-SMM: Code DRAM, Data DRAM */ + break; + case 0x02: + apollo_smram_map(dev, 1, 0x000a0000, 0x00020000, 3); /* SMM: Code Invalid, Data Invalid */ + apollo_smram_map(dev, 0, 0x000a0000, 0x00020000, 2); /* Non-SMM: Code DRAM, Data PCI */ + break; + case 0x03: + apollo_smram_map(dev, 1, 0x000a0000, 0x00020000, 1); /* SMM: Code DRAM, Data DRAM */ + apollo_smram_map(dev, 0, 0x000a0000, 0x00020000, 3); /* Non-SMM: Code Invalid, Data Invalid */ + break; + } + else if (dev->id >= VIA_597) + switch (val & 0x03) { + default: + case 0x00: + /* Disable SMI Address Redirection (default) */ + apollo_smram_map(dev, 1, 0x000a0000, 0x00020000, 0); + apollo_smram_map(dev, 0, 0x000a0000, 0x00020000, 0); + break; + case 0x01: + /* Allow access to DRAM Axxxx-Bxxxx for both normal and SMI cycles */ + apollo_smram_map(dev, 1, 0x000a0000, 0x00020000, 1); + apollo_smram_map(dev, 0, 0x000a0000, 0x00020000, 1); + break; + case 0x02: + /* Reserved */ + apollo_smram_map(dev, 1, 0x000a0000, 0x00020000, 3); + if (dev->id == VIA_597) { + /* SMI 3xxxx-4xxxx redirect to Axxxx-Bxxxx. */ + apollo_smram_map(dev, 1, 0x00030000, 0x00020000, 1); + } + apollo_smram_map(dev, 0, 0x000a0000, 0x00020000, 3); + break; + case 0x03: + /* Allow SMI Axxxx-Bxxxx DRAM access */ + apollo_smram_map(dev, 1, 0x000a0000, 0x00020000, 1); + apollo_smram_map(dev, 0, 0x000a0000, 0x00020000, 0); + break; + } + else + switch (val & 0x03) { + case 0x00: + apollo_smram_map(dev, 1, 0x000a0000, 0x00020000, 0); + apollo_smram_map(dev, 0, 0x000a0000, 0x00020000, 0); + break; + case 0x01: + apollo_smram_map(dev, 1, 0x000a0000, 0x00020000, 1); + apollo_smram_map(dev, 0, 0x000a0000, 0x00020000, 0); + break; + case 0x02: + apollo_smram_map(dev, 1, 0x00030000, 0x00020000, 1); + apollo_smram_map(dev, 0, 0x000a0000, 0x00020000, 3); + break; + case 0x03: + apollo_smram_map(dev, 1, 0x000a0000, 0x00020000, 1); + apollo_smram_map(dev, 0, 0x000a0000, 0x00020000, 1); + apollo_smram_map(dev, 1, 0x000a0000, 0x00020000, 3); + apollo_smram_map(dev, 0, 0x000a0000, 0x00020000, 3); + break; - case 0x80: - dev->pci_conf[0x80] = (dev->pci_conf[0x80] & ~0x8f) | (val & 0x8f); - break; - case 0x84: - /* The datasheet first mentions 7-0 but then says 3-0 are reserved - - - minimum of 16 MB for the graphics aperture? 8601 datasheet doesn't refer it. */ - if(dev->id >= VIA_693A) - dev->pci_conf[0x84] = val; - else - dev->pci_conf[0x84] = (dev->pci_conf[0x84] & ~0xf0) | (val & 0xf0); - apollo_agp_map(dev); - break; - case 0x88: - if((dev->id == VIA_693A) || (dev->id == VIA_8601)) - dev->pci_conf[0x88] = (dev->pci_conf[0x88] & ~0x06) | (val & 0x06); - else - dev->pci_conf[0x88] = (dev->pci_conf[0x88] & ~0x07) | (val & 0x07); - apollo_agp_map(dev); - break; - case 0x89: - dev->pci_conf[0x89] = val & 0xf0; - apollo_agp_map(dev); - break; - case 0x8a: - case 0x8b: - dev->pci_conf[addr] = val; - apollo_agp_map(dev); - break; + default: + break; + } + break; + case 0x65: + if (dev->id == VIA_585) + dev->pci_conf[0x65] = (dev->pci_conf[0x65] & ~0xfd) | (val & 0xfd); + else if (dev->id == VIA_595) + dev->pci_conf[0x65] = (dev->pci_conf[0x65] & ~0xf9) | (val & 0xf9); + else + dev->pci_conf[0x65] = val; + break; + case 0x66: + if (dev->id == VIA_585) + dev->pci_conf[0x66] = (dev->pci_conf[0x66] & ~0xaf) | (val & 0xaf); + else if (dev->id == VIA_595) + dev->pci_conf[0x66] = (dev->pci_conf[0x66] & ~0x8f) | (val & 0x8f); + else + dev->pci_conf[0x66] = val; + break; + case 0x68: + if (dev->id != VIA_595) { + if (dev->id == VIA_597) + dev->pci_conf[0x68] = (dev->pci_conf[0x68] & ~0xfe) | (val & 0xfe); + else if ((dev->id == VIA_693A) || (dev->id == VIA_694)) + dev->pci_conf[0x68] = (dev->pci_conf[0x68] & ~0xdc) | (val & 0xdc); + else + dev->pci_conf[0x68] = (dev->pci_conf[0x68] & ~0xfc) | (val & 0xfc); + } + break; + case 0x69: + if ((dev->id != VIA_585) || (dev->id != VIA_595)) { + if ((dev->id == VIA_693A) || (dev->id < VIA_8601)) + dev->pci_conf[0x69] = (dev->pci_conf[0x69] & ~0xfe) | (val & 0xfe); + else + dev->pci_conf[0x69] = val; + } + break; + case 0x6b: + if ((dev->id == VIA_693A) || (dev->id < VIA_8601)) + dev->pci_conf[0x6b] = val; + else if (dev->id == VIA_691) + dev->pci_conf[0x6b] = (dev->pci_conf[0x6b] & ~0xcf) | (val & 0xcf); + else if (dev->id == VIA_595) + dev->pci_conf[0x6b] = (dev->pci_conf[0x6b] & ~0xc0) | (val & 0xc0); + else if (dev->id == VIA_585) + dev->pci_conf[0x6b] = (dev->pci_conf[0x6b] & ~0xc4) | (val & 0xc4); + else + dev->pci_conf[0x6b] = (dev->pci_conf[0x6b] & ~0xc1) | (val & 0xc1); + break; + case 0x6c: + if ((dev->id == VIA_597) || ((dev->id == VIA_693A) || (dev->id < VIA_8601))) + dev->pci_conf[0x6c] = (dev->pci_conf[0x6c] & ~0x1f) | (val & 0x1f); + else if (dev->id == VIA_598) + dev->pci_conf[0x6c] = (dev->pci_conf[0x6c] & ~0x7f) | (val & 0x7f); + else if (dev->id == VIA_585) + dev->pci_conf[0x6c] = (dev->pci_conf[0x6c] & ~0xef) | (val & 0xef); + else + dev->pci_conf[0x6c] = val; + break; + case 0x6d: + if ((dev->id == VIA_597) || (dev->id == VIA_694)) + dev->pci_conf[0x6d] = (dev->pci_conf[0x6d] & ~0x0f) | (val & 0x0f); + else if ((dev->id == VIA_598) || (dev->id == VIA_693A) || (dev->id == VIA_8601)) + dev->pci_conf[0x6d] = (dev->pci_conf[0x6d] & ~0x7f) | (val & 0x7f); + else + dev->pci_conf[0x6d] = val; + break; + case 0x6e: + if ((dev->id == VIA_595) || (dev->id == VIA_694)) + dev->pci_conf[0x6e] = val; + else + dev->pci_conf[0x6e] = (dev->pci_conf[0x6e] & ~0xb7) | (val & 0xb7); + break; - case 0xa8: - if(dev->id == VIA_694) - dev->pci_conf[0xa8] = (dev->pci_conf[0xa8] & ~0x33) | (val & 0x33); - else - dev->pci_conf[0xa8] = (dev->pci_conf[0xa8] & ~0x03) | (val & 0x03); - break; - case 0xa9: - dev->pci_conf[0xa9] = (dev->pci_conf[0xa9] & ~0x03) | (val & 0x03); - break; - case 0xac: - if(dev->id == VIA_8601) - dev->pci_conf[0xac] = (dev->pci_conf[0xac] & ~0x7f) | (val & 0x7f); - else - dev->pci_conf[0xac] = (dev->pci_conf[0xac] & ~0x0f) | (val & 0x0f); - break; - case 0xad: - dev->pci_conf[0xac] = (dev->pci_conf[0xac] & ~0x0f) | (val & 0x0f); - break; + case 0x70: + if (dev->id >= VIA_693A) + dev->pci_conf[0x70] = (dev->pci_conf[0x70] & ~0xdf) | (val & 0xdf); + else if (dev->id == VIA_597) + dev->pci_conf[0x70] = (dev->pci_conf[0x70] & ~0xf1) | (val & 0xf1); + else if ((dev->id >= VIA_585) || (dev->id < VIA_597)) + dev->pci_conf[0x70] = (dev->pci_conf[0x70] & ~0xe3) | (val & 0xe3); + else + dev->pci_conf[0x70] = val; + break; + case 0x71: + if ((dev->id >= VIA_585) || (dev->id == VIA_694)) + dev->pci_conf[0x71] = (dev->pci_conf[0x71] & ~0xdf) | (val & 0xdf); + else + dev->pci_conf[0x71] = val; + break; + case 0x73: + if (dev->id >= VIA_693A) + dev->pci_conf[0x73] = (dev->pci_conf[0x73] & ~0x7f) | (val & 0x7f); + else if ((dev->id >= VIA_585) || (dev->id < VIA_597)) + dev->pci_conf[0x73] = (dev->pci_conf[0x73] & ~0xef) | (val & 0xef); + else + dev->pci_conf[0x73] = val; + break; + case 0x74: + if ((dev->id == VIA_693A) || (dev->id == VIA_8601)) + dev->pci_conf[0x74] = (dev->pci_conf[0x74] & ~0xdf) | (val & 0xdf); + else if (dev->id == VIA_694) + dev->pci_conf[0x74] = (dev->pci_conf[0x74] & ~0x9f) | (val & 0x9f); + else + dev->pci_conf[0x74] = (dev->pci_conf[0x74] & ~0xc0) | (val & 0xc0); + break; + case 0x75: + if (dev->id >= VIA_693A) + dev->pci_conf[0x75] = val; + else + dev->pci_conf[0x75] = (dev->pci_conf[0x75] & ~0xcf) | (val & 0xcf); + break; + case 0x76: + if (dev->id >= VIA_693A) + dev->pci_conf[0x76] = val; + else if ((dev->id >= VIA_585) || (dev->id < VIA_597)) + dev->pci_conf[0x76] = (dev->pci_conf[0x76] & ~0xb0) | (val & 0xb0); + else + dev->pci_conf[0x76] = (dev->pci_conf[0x76] & ~0xf0) | (val & 0xf0); + break; + case 0x77: + if (dev->id < VIA_693A) + dev->pci_conf[0x77] = (dev->pci_conf[0x77] & ~0xc0) | (val & 0xc0); + break; + case 0x78: + dev->pci_conf[0x78] = (dev->pci_conf[0x78] & ~0xd5) | (val & 0xd5); + break; + case 0x79: + dev->pci_conf[0x79] = (dev->pci_conf[0x79] & ~0xfc) | (val & 0xfc); + break; + case 0x7a: + dev->pci_conf[0x7a] = (dev->pci_conf[0x7a] & ~0x89) | (val & 0x89); + break; + case 0x7e: + if ((dev->id != VIA_8601) || (dev->id != VIA_694)) + dev->pci_conf[0x7e] = (dev->pci_conf[0x7e] & ~0x3f) | (val & 0x3f); + break; - case 0xfc: - if (dev->id == VIA_8601) - dev->pci_conf[0xfc] = (dev->pci_conf[0xfc] & ~0x03) | (val & 0x03); - else if (dev->id > VIA_597) - dev->pci_conf[0xfc] = (dev->pci_conf[0xfc] & ~0x01) | (val & 0x01); - break; + case 0x80: + dev->pci_conf[0x80] = (dev->pci_conf[0x80] & ~0x8f) | (val & 0x8f); + break; + case 0x84: + /* The datasheet first mentions 7-0 but then says 3-0 are reserved - + - minimum of 16 MB for the graphics aperture? 8601 datasheet doesn't refer it. */ + if (dev->id >= VIA_693A) + dev->pci_conf[0x84] = val; + else + dev->pci_conf[0x84] = (dev->pci_conf[0x84] & ~0xf0) | (val & 0xf0); + apollo_agp_map(dev); + break; + case 0x88: + if ((dev->id == VIA_693A) || (dev->id == VIA_8601)) + dev->pci_conf[0x88] = (dev->pci_conf[0x88] & ~0x06) | (val & 0x06); + else + dev->pci_conf[0x88] = (dev->pci_conf[0x88] & ~0x07) | (val & 0x07); + apollo_agp_map(dev); + break; + case 0x89: + dev->pci_conf[0x89] = val & 0xf0; + apollo_agp_map(dev); + break; + case 0x8a: + case 0x8b: + dev->pci_conf[addr] = val; + apollo_agp_map(dev); + break; - case 0xfd: - if (dev->id == VIA_8601) - dev->pci_conf[0xfd] = (dev->pci_conf[0xfd] & ~0x07) | (val & 0x07); - else - dev->pci_conf[0xfd] = val; - break; + case 0xa8: + if (dev->id == VIA_694) + dev->pci_conf[0xa8] = (dev->pci_conf[0xa8] & ~0x33) | (val & 0x33); + else + dev->pci_conf[0xa8] = (dev->pci_conf[0xa8] & ~0x03) | (val & 0x03); + break; + case 0xa9: + dev->pci_conf[0xa9] = (dev->pci_conf[0xa9] & ~0x03) | (val & 0x03); + break; + case 0xac: + if (dev->id == VIA_8601) + dev->pci_conf[0xac] = (dev->pci_conf[0xac] & ~0x7f) | (val & 0x7f); + else + dev->pci_conf[0xac] = (dev->pci_conf[0xac] & ~0x0f) | (val & 0x0f); + break; + case 0xad: + dev->pci_conf[0xac] = (dev->pci_conf[0xac] & ~0x0f) | (val & 0x0f); + break; - default: - dev->pci_conf[addr] = val; - break; + case 0xfc: + if (dev->id == VIA_8601) + dev->pci_conf[0xfc] = (dev->pci_conf[0xfc] & ~0x03) | (val & 0x03); + else if (dev->id > VIA_597) + dev->pci_conf[0xfc] = (dev->pci_conf[0xfc] & ~0x01) | (val & 0x01); + break; + + case 0xfd: + if (dev->id == VIA_8601) + dev->pci_conf[0xfd] = (dev->pci_conf[0xfd] & ~0x07) | (val & 0x07); + else + dev->pci_conf[0xfd] = val; + break; + + default: + dev->pci_conf[addr] = val; + break; } } - static uint8_t via_apollo_read(int func, int addr, void *priv) { - via_apollo_t *dev = (via_apollo_t *) priv; - uint8_t ret = 0xff; + const via_apollo_t *dev = (via_apollo_t *) priv; + uint8_t ret = 0xff; - switch(func) { + switch (func) { case 0: - ret = dev->pci_conf[addr]; - break; + ret = dev->pci_conf[addr]; + break; + default: + break; } return ret; } - static void via_apollo_write(int func, int addr, uint8_t val, void *priv) { - switch(func) { - case 0: - via_apollo_host_bridge_write(func, addr, val, priv); - break; + switch (func) { + case 0: + via_apollo_host_bridge_write(func, addr, val, priv); + break; + default: + break; } } - static void via_apollo_reset(void *priv) { @@ -698,7 +709,6 @@ via_apollo_reset(void *priv) via_apollo_write(0, 0x63, 0x00, priv); } - static void * via_apollo_init(const device_t *info) { @@ -707,41 +717,44 @@ via_apollo_init(const device_t *info) dev->smram = smram_add(); if (dev->id != VIA_8601) - apollo_smram_map(dev, 1, 0x000a0000, 0x00020000, 1); /* SMM: Code DRAM, Data DRAM */ + apollo_smram_map(dev, 1, 0x000a0000, 0x00020000, 1); /* SMM: Code DRAM, Data DRAM */ - pci_add_card(PCI_ADD_NORTHBRIDGE, via_apollo_read, via_apollo_write, dev); + pci_add_card(PCI_ADD_NORTHBRIDGE, via_apollo_read, via_apollo_write, dev, &dev->pci_slot); dev->id = info->local; switch (dev->id) { - case VIA_597: - device_add(&via_vp3_agp_device); - break; + case VIA_597: + device_add(&via_vp3_agp_device); + break; - case VIA_691: - device_add(&via_apro_agp_device); - break; + case VIA_691: + device_add(&via_apro_agp_device); + break; - case VIA_8601: - device_add(&via_vt8601_agp_device); - break; + case VIA_8601: + device_add(&via_vt8601_agp_device); + break; - case VIA_598: - case VIA_693A: - case VIA_694: - device_add(&via_mvp3_agp_device); - break; + case VIA_598: + case VIA_693A: + case VIA_694: + device_add(&via_mvp3_agp_device); + break; + + default: + break; } if (dev->id >= VIA_597) - dev->agpgart = device_add(&agpgart_device); + dev->agpgart = device_add(&agpgart_device); if ((dev->id >= VIA_694) && (dev->id != VIA_8601)) - dev->drb_unit = 16; + dev->drb_unit = 16; else if (dev->id >= VIA_597) - dev->drb_unit = 8; + dev->drb_unit = 8; else - dev->drb_unit = 4; + dev->drb_unit = 4; via_apollo_setup(dev); via_apollo_reset(dev); @@ -749,7 +762,6 @@ via_apollo_init(const device_t *info) return dev; } - static void via_apollo_close(void *priv) { @@ -760,118 +772,114 @@ via_apollo_close(void *priv) free(dev); } -const device_t via_vpx_device = -{ - "VIA Apollo VPX", - "via_vpx", - DEVICE_PCI, - VIA_585, /*VT82C585*/ - via_apollo_init, - via_apollo_close, - via_apollo_reset, - { NULL }, - NULL, - NULL, - NULL +const device_t via_vpx_device = { + .name = "VIA Apollo VPX", + .internal_name = "via_vpx", + .flags = DEVICE_PCI, + .local = VIA_585, /*VT82C585*/ + .init = via_apollo_init, + .close = via_apollo_close, + .reset = via_apollo_reset, + { .available = NULL }, + .speed_changed = NULL, + .force_redraw = NULL, + .config = NULL }; -const device_t amd640_device = -{ - "AMD 640 System Controller", - "amd640", - DEVICE_PCI, - VIA_595, /*VT82C595*/ - via_apollo_init, - via_apollo_close, - via_apollo_reset, - { NULL }, - NULL, - NULL, - NULL +const device_t amd640_device = { + .name = "AMD 640 System Controller", + .internal_name = "amd640", + .flags = DEVICE_PCI, + .local = VIA_595, /*VT82C595*/ + .init = via_apollo_init, + .close = via_apollo_close, + .reset = via_apollo_reset, + { .available = NULL }, + .speed_changed = NULL, + .force_redraw = NULL, + .config = NULL }; -const device_t via_vp3_device = -{ - "VIA Apollo VP3", - "via_vp3", - DEVICE_PCI, - VIA_597, /*VT82C597*/ - via_apollo_init, - via_apollo_close, - via_apollo_reset, - { NULL }, - NULL, - NULL, - NULL +const device_t via_vp3_device = { + .name = "VIA Apollo VP3", + .internal_name = "via_vp3", + .flags = DEVICE_PCI, + .local = VIA_597, /*VT82C597*/ + .init = via_apollo_init, + .close = via_apollo_close, + .reset = via_apollo_reset, + { .available = NULL }, + .speed_changed = NULL, + .force_redraw = NULL, + .config = NULL }; -const device_t via_mvp3_device = -{ - "VIA Apollo MVP3", - "via_mvp3", - DEVICE_PCI, - VIA_598, /*VT82C598MVP*/ - via_apollo_init, - via_apollo_close, - via_apollo_reset, - { NULL }, - NULL, - NULL, - NULL +const device_t via_mvp3_device = { + .name = "VIA Apollo MVP3", + .internal_name = "via_mvp3", + .flags = DEVICE_PCI, + .local = VIA_598, /*VT82C598MVP*/ + .init = via_apollo_init, + .close = via_apollo_close, + .reset = via_apollo_reset, + { .available = NULL }, + .speed_changed = NULL, + .force_redraw = NULL, + .config = NULL }; const device_t via_apro_device = { - "VIA Apollo Pro", - "via_apro", - DEVICE_PCI, - VIA_691, /*VT82C691*/ - via_apollo_init, - via_apollo_close, - via_apollo_reset, - { NULL }, - NULL, - NULL, - NULL + .name = "VIA Apollo Pro", + .internal_name = "via_apro", + .flags = DEVICE_PCI, + .local = VIA_691, /*VT82C691*/ + .init = via_apollo_init, + .close = via_apollo_close, + .reset = via_apollo_reset, + { .available = NULL }, + .speed_changed = NULL, + .force_redraw = NULL, + .config = NULL }; const device_t via_apro133_device = { - "VIA Apollo Pro133", - "via_apro133", - DEVICE_PCI, - VIA_693A, /*VT82C693A*/ - via_apollo_init, - via_apollo_close, - via_apollo_reset, - { NULL }, - NULL, - NULL, - NULL + .name = "VIA Apollo Pro133", + .internal_name = "via_apro133", + .flags = DEVICE_PCI, + .local = VIA_693A, /*VT82C693A*/ + .init = via_apollo_init, + .close = via_apollo_close, + .reset = via_apollo_reset, + { .available = NULL }, + .speed_changed = NULL, + .force_redraw = NULL, + .config = NULL }; const device_t via_apro133a_device = { - "VIA Apollo Pro133A", - "via_apro_133a", - DEVICE_PCI, - VIA_694, /*VT82C694X*/ - via_apollo_init, - via_apollo_close, - via_apollo_reset, - { NULL }, - NULL, - NULL, - NULL + .name = "VIA Apollo Pro133A", + .internal_name = "via_apro_133a", + .flags = DEVICE_PCI, + .local = VIA_694, /*VT82C694X*/ + .init = via_apollo_init, + .close = via_apollo_close, + .reset = via_apollo_reset, + { .available = NULL }, + .speed_changed = NULL, + .force_redraw = NULL, + .config = NULL }; const device_t via_vt8601_device = { - "VIA Apollo ProMedia", - "via_vt8601", - DEVICE_PCI, - VIA_8601, /*VT8601*/ - via_apollo_init, - via_apollo_close, - via_apollo_reset, - { NULL }, - NULL, - NULL, - NULL + .name = "VIA Apollo ProMedia", + .internal_name = "via_vt8601", + .flags = DEVICE_PCI, + .local = VIA_8601, /*VT8601*/ + .init = via_apollo_init, + .close = via_apollo_close, + .reset = via_apollo_reset, + { .available = NULL }, + .speed_changed = NULL, + .force_redraw = NULL, + .config = NULL }; diff --git a/src/chipset/via_pipc.c b/src/chipset/via_pipc.c index a9da704d8..1f153092b 100644 --- a/src/chipset/via_pipc.c +++ b/src/chipset/via_pipc.c @@ -1,24 +1,21 @@ /* - * 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. + * 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. * - * Emulation of the VIA PIPC southbridges. + * This file is part of the 86Box distribution. + * + * Emulation of the VIA PIPC southbridges. * * * - * Authors: Sarah Walker, - * Miran Grca, - * Melissa Goad, - * RichardG, + * Authors: Miran Grca, + * RichardG, * - * Copyright 2008-2020 Sarah Walker. - * Copyright 2016-2020 Miran Grca. - * Copyright 2020 Melissa Goad. - * Copyright 2020-2021 RichardG. + * Copyright 2016-2020 Miran Grca. + * Copyright 2020-2021 RichardG. */ - #include #include #include @@ -40,6 +37,8 @@ #include <86box/ddma.h> #include <86box/pci.h> #include <86box/pic.h> +#include <86box/plat_fallthrough.h> +#include <86box/plat_unused.h> #include <86box/port_92.h> #include <86box/hdc.h> #include <86box/hdc_ide.h> @@ -58,14 +57,15 @@ /* Most revision numbers (PCI-ISA bridge or otherwise) were lifted from PCI device listings on forums, as VIA's datasheets are not very helpful regarding those. */ -#define VIA_PIPC_586A 0x05862500 -#define VIA_PIPC_586B 0x05864700 -#define VIA_PIPC_596A 0x05960900 -#define VIA_PIPC_596B 0x05962300 -#define VIA_PIPC_686A 0x06861400 -#define VIA_PIPC_686B 0x06864000 -#define VIA_PIPC_8231 0x82311000 +#define VIA_PIPC_586A 0x05862500 +#define VIA_PIPC_586B 0x05864700 +#define VIA_PIPC_596A 0x05960900 +#define VIA_PIPC_596B 0x05962300 +#define VIA_PIPC_686A 0x06861400 +#define VIA_PIPC_686B 0x06864000 +#define VIA_PIPC_8231 0x82311000 +#define VIA_PIPC_FM_EMULATION 1 enum { TRAP_DRQ = 0, @@ -106,95 +106,102 @@ enum { typedef struct { struct _pipc_ *dev; - void *trap; - uint32_t *sts_reg, *en_reg, mask; + void *trap; + uint32_t *sts_reg; + uint32_t *en_reg; + uint32_t mask; } pipc_io_trap_t; typedef struct _pipc_ { - uint32_t local; - uint8_t max_func, max_pcs; + uint8_t max_func; + uint8_t max_pcs; + uint8_t pci_slot; + uint8_t pad; - uint8_t pci_isa_regs[256], - ide_regs[256], - usb_regs[2][256], - power_regs[256], - ac97_regs[2][256], fmnmi_regs[4]; + uint8_t pci_isa_regs[256]; + uint8_t ide_regs[256]; + uint8_t usb_regs[2][256]; + uint8_t power_regs[256]; + uint8_t ac97_regs[2][256]; + uint8_t fmnmi_regs[4]; + uint8_t fmnmi_status; - sff8038i_t *bm[2]; - nvr_t *nvr; - int nvr_enabled, slot; - ddma_t *ddma; + uint32_t local; + + sff8038i_t *bm[2]; + nvr_t *nvr; + int nvr_enabled; + ddma_t *ddma; smbus_piix4_t *smbus; - usb_t *usb[2]; + usb_t *usb[2]; - acpi_t *acpi; + acpi_t *acpi; pipc_io_trap_t io_traps[TRAP_MAX]; - void *gameport, *ac97, *sio, *hwm; - sb_t *sb; - uint16_t midigame_base, sb_base, fmnmi_base; + void *gameport; + void *ac97; + void *sio; + void *hwm; + sb_t *sb; + uint16_t midigame_base; + uint16_t sb_base; + uint16_t fmnmi_base; } pipc_t; - #ifdef ENABLE_PIPC_LOG int pipc_do_log = ENABLE_PIPC_LOG; - static void pipc_log(const char *fmt, ...) { va_list ap; if (pipc_do_log) { - va_start(ap, fmt); - pclog_ex(fmt, ap); - va_end(ap); + va_start(ap, fmt); + pclog_ex(fmt, ap); + va_end(ap); } } #else -#define pipc_log(fmt, ...) +# define pipc_log(fmt, ...) #endif - -static void pipc_sgd_handlers(pipc_t *dev, uint8_t modem); -static void pipc_codec_handlers(pipc_t *dev, uint8_t modem); -static void pipc_sb_handlers(pipc_t *dev, uint8_t modem); -static uint8_t pipc_read(int func, int addr, void *priv); -static void pipc_write(int func, int addr, uint8_t val, void *priv); - +static void pipc_sgd_handlers(pipc_t *dev, uint8_t modem); +static void pipc_codec_handlers(pipc_t *dev, uint8_t modem); +static void pipc_sb_handlers(pipc_t *dev, uint8_t modem); +static uint8_t pipc_read(int func, int addr, void *priv); +static void pipc_write(int func, int addr, uint8_t val, void *priv); static void -pipc_io_trap_pact(int size, uint16_t addr, uint8_t write, uint8_t val, void *priv) +pipc_io_trap_pact(UNUSED(int size), UNUSED(uint16_t addr), UNUSED(uint8_t write), UNUSED(uint8_t val), void *priv) { pipc_io_trap_t *trap = (pipc_io_trap_t *) priv; if (*(trap->en_reg) & trap->mask) { - *(trap->sts_reg) |= trap->mask; - trap->dev->acpi->regs.glbsts |= 0x0001; - if (trap->dev->acpi->regs.glben & 0x0001) - acpi_raise_smi(trap->dev->acpi, 1); + *(trap->sts_reg) |= trap->mask; + trap->dev->acpi->regs.glbsts |= 0x0001; + if (trap->dev->acpi->regs.glben & 0x0001) + acpi_raise_smi(trap->dev->acpi, 1); } } - static void -pipc_io_trap_glb(int size, uint16_t addr, uint8_t write, uint8_t val, void *priv) +pipc_io_trap_glb(UNUSED(int size), UNUSED(uint16_t addr), uint8_t write, UNUSED(uint8_t val), void *priv) { pipc_io_trap_t *trap = (pipc_io_trap_t *) priv; if (*(trap->en_reg) & trap->mask) { - *(trap->sts_reg) |= trap->mask; - if (trap->dev->local >= VIA_PIPC_686A) { - if (write) - trap->dev->acpi->regs.extsmi_val |= 0x1000; - else - trap->dev->acpi->regs.extsmi_val &= ~0x1000; - } - acpi_raise_smi(trap->dev->acpi, 1); + *(trap->sts_reg) |= trap->mask; + if (trap->dev->local >= VIA_PIPC_686A) { + if (write) + trap->dev->acpi->regs.extsmi_val |= 0x1000; + else + trap->dev->acpi->regs.extsmi_val &= ~0x1000; + } + acpi_raise_smi(trap->dev->acpi, 1); } } - static void pipc_reset_hard(void *priv) { @@ -202,11 +209,10 @@ pipc_reset_hard(void *priv) pipc_log("PIPC: reset_hard()\n"); - pipc_t *dev = (pipc_t *) priv; - uint16_t old_base = (dev->ide_regs[0x20] & 0xf0) | (dev->ide_regs[0x21] << 8); + pipc_t *dev = (pipc_t *) priv; - sff_bus_master_reset(dev->bm[0], old_base); - sff_bus_master_reset(dev->bm[1], old_base + 8); + sff_bus_master_reset(dev->bm[0]); + sff_bus_master_reset(dev->bm[1]); memset(dev->pci_isa_regs, 0, 256); memset(dev->ide_regs, 0, 256); @@ -215,7 +221,8 @@ pipc_reset_hard(void *priv) memset(dev->ac97_regs, 0, 512); /* PCI-ISA bridge registers. */ - dev->pci_isa_regs[0x00] = 0x06; dev->pci_isa_regs[0x01] = 0x11; + dev->pci_isa_regs[0x00] = 0x06; + dev->pci_isa_regs[0x01] = 0x11; dev->pci_isa_regs[0x02] = dev->local >> 16; dev->pci_isa_regs[0x03] = dev->local >> 24; dev->pci_isa_regs[0x04] = (dev->local <= VIA_PIPC_586B) ? 0x0f : 0x87; @@ -229,15 +236,16 @@ pipc_reset_hard(void *priv) dev->pci_isa_regs[0x4a] = 0x04; dev->pci_isa_regs[0x4f] = 0x03; - dev->pci_isa_regs[0x50] = (dev->local >= VIA_PIPC_686A) ? 0x0e : 0x24; /* 686A/B default value does not line up with default bits */ + /* 686A/B default value does not line up with default bits */ + dev->pci_isa_regs[0x50] = (dev->local >= VIA_PIPC_686A) ? 0x0e : 0x24; dev->pci_isa_regs[0x59] = 0x04; if (dev->local >= VIA_PIPC_686A) - dev->pci_isa_regs[0x5a] = dev->pci_isa_regs[0x5f] = 0x04; + dev->pci_isa_regs[0x5a] = dev->pci_isa_regs[0x5f] = 0x04; dma_e = 0x00; for (i = 0; i < 8; i++) { - dma[i].ab &= 0xffff000f; - dma[i].ac &= 0xffff000f; + dma[i].ab &= 0xffff000f; + dma[i].ac &= 0xffff000f; } pic_set_shadow(0); @@ -246,229 +254,258 @@ pipc_reset_hard(void *priv) /* IDE registers. */ dev->max_func++; - dev->ide_regs[0x00] = 0x06; dev->ide_regs[0x01] = 0x11; - dev->ide_regs[0x02] = 0x71; dev->ide_regs[0x03] = 0x05; + dev->ide_regs[0x00] = 0x06; + dev->ide_regs[0x01] = 0x11; + dev->ide_regs[0x02] = 0x71; + dev->ide_regs[0x03] = 0x05; dev->ide_regs[0x04] = 0x80; - dev->ide_regs[0x06] = (dev->local == VIA_PIPC_686A) ? 0x90 : 0x80; dev->ide_regs[0x07] = 0x02; + dev->ide_regs[0x06] = (dev->local == VIA_PIPC_686A) ? 0x90 : 0x80; + dev->ide_regs[0x07] = 0x02; dev->ide_regs[0x08] = (dev->local == VIA_PIPC_596B) ? 0x10 : 0x06; /* only 596B has rev 0x10? */ dev->ide_regs[0x09] = 0x85; dev->ide_regs[0x0a] = 0x01; dev->ide_regs[0x0b] = 0x01; - dev->ide_regs[0x10] = 0xf1; dev->ide_regs[0x11] = 0x01; - dev->ide_regs[0x14] = 0xf5; dev->ide_regs[0x15] = 0x03; - dev->ide_regs[0x18] = 0x71; dev->ide_regs[0x19] = 0x01; - dev->ide_regs[0x1c] = 0x75; dev->ide_regs[0x1d] = 0x03; - dev->ide_regs[0x20] = 0x01; dev->ide_regs[0x21] = 0xcc; + dev->ide_regs[0x10] = 0xf1; + dev->ide_regs[0x11] = 0x01; + dev->ide_regs[0x14] = 0xf5; + dev->ide_regs[0x15] = 0x03; + dev->ide_regs[0x18] = 0x71; + dev->ide_regs[0x19] = 0x01; + dev->ide_regs[0x1c] = 0x75; + dev->ide_regs[0x1d] = 0x03; + dev->ide_regs[0x20] = 0x01; + dev->ide_regs[0x21] = 0xcc; if (dev->local >= VIA_PIPC_686A) - dev->ide_regs[0x34] = 0xc0; + dev->ide_regs[0x34] = 0xc0; dev->ide_regs[0x3c] = 0x0e; if (dev->local <= VIA_PIPC_586B) - dev->ide_regs[0x40] = 0x04; + dev->ide_regs[0x40] = 0x04; dev->ide_regs[0x41] = (dev->local == VIA_PIPC_686B) ? 0x06 : 0x02; dev->ide_regs[0x42] = 0x09; dev->ide_regs[0x43] = (dev->local >= VIA_PIPC_686A) ? 0x0a : 0x3a; dev->ide_regs[0x44] = 0x68; if (dev->local == VIA_PIPC_686B) - dev->ide_regs[0x45] = 0x20; + dev->ide_regs[0x45] = 0x20; else if (dev->local >= VIA_PIPC_8231) - dev->ide_regs[0x45] = 0x03; + dev->ide_regs[0x45] = 0x03; dev->ide_regs[0x46] = 0xc0; - dev->ide_regs[0x48] = 0xa8; dev->ide_regs[0x49] = 0xa8; - dev->ide_regs[0x4a] = 0xa8; dev->ide_regs[0x4b] = 0xa8; + dev->ide_regs[0x48] = 0xa8; + dev->ide_regs[0x49] = 0xa8; + dev->ide_regs[0x4a] = 0xa8; + dev->ide_regs[0x4b] = 0xa8; dev->ide_regs[0x4c] = 0xff; if (dev->local != VIA_PIPC_686B) - dev->ide_regs[0x4e] = dev->ide_regs[0x4f] = 0xff; + dev->ide_regs[0x4e] = dev->ide_regs[0x4f] = 0xff; dev->ide_regs[0x50] = dev->ide_regs[0x51] = dev->ide_regs[0x52] = dev->ide_regs[0x53] = ((dev->local == VIA_PIPC_686A) || (dev->local == VIA_PIPC_686B)) ? 0x07 : 0x03; if (dev->local >= VIA_PIPC_596A) - dev->ide_regs[0x54] = ((dev->local == VIA_PIPC_686A) || (dev->local == VIA_PIPC_686B)) ? 0x04 : 0x06; + dev->ide_regs[0x54] = ((dev->local == VIA_PIPC_686A) || (dev->local == VIA_PIPC_686B)) ? 0x04 : 0x06; dev->ide_regs[0x61] = 0x02; dev->ide_regs[0x69] = 0x02; if (dev->local >= VIA_PIPC_686A) { - dev->ide_regs[0xc0] = 0x01; - dev->ide_regs[0xc2] = 0x02; + dev->ide_regs[0xc0] = 0x01; + dev->ide_regs[0xc2] = 0x02; } /* USB registers. */ for (i = 0; i <= (dev->local >= VIA_PIPC_686A); i++) { - dev->max_func++; - dev->usb_regs[i][0x00] = 0x06; dev->usb_regs[i][0x01] = 0x11; - dev->usb_regs[i][0x02] = 0x38; dev->usb_regs[i][0x03] = 0x30; - dev->usb_regs[i][0x04] = 0x00; dev->usb_regs[i][0x05] = 0x00; - dev->usb_regs[i][0x06] = 0x00; dev->usb_regs[i][0x07] = 0x02; - switch (dev->local) { - case VIA_PIPC_586A: - case VIA_PIPC_586B: - case VIA_PIPC_596A: - dev->usb_regs[i][0x08] = 0x02; - break; + dev->max_func++; + dev->usb_regs[i][0x00] = 0x06; + dev->usb_regs[i][0x01] = 0x11; + dev->usb_regs[i][0x02] = 0x38; + dev->usb_regs[i][0x03] = 0x30; + dev->usb_regs[i][0x04] = 0x00; + dev->usb_regs[i][0x05] = 0x00; + dev->usb_regs[i][0x06] = 0x00; + dev->usb_regs[i][0x07] = 0x02; + switch (dev->local) { + case VIA_PIPC_586A: + case VIA_PIPC_586B: + case VIA_PIPC_596A: + dev->usb_regs[i][0x08] = 0x02; + break; - case VIA_PIPC_596B: - dev->usb_regs[i][0x08] = 0x08; - break; + case VIA_PIPC_596B: + dev->usb_regs[i][0x08] = 0x08; + break; - case VIA_PIPC_686A: - dev->usb_regs[i][0x08] = 0x06; - break; + case VIA_PIPC_686A: + dev->usb_regs[i][0x08] = 0x06; + break; - case VIA_PIPC_686B: - dev->usb_regs[i][0x08] = 0x1a; - break; + case VIA_PIPC_686B: + dev->usb_regs[i][0x08] = 0x1a; + break; - case VIA_PIPC_8231: - dev->usb_regs[i][0x08] = 0x1e; - break; - } + case VIA_PIPC_8231: + dev->usb_regs[i][0x08] = 0x1e; + break; + default: + break; + } - dev->usb_regs[i][0x0a] = 0x03; - dev->usb_regs[i][0x0b] = 0x0c; - dev->usb_regs[i][0x0d] = 0x16; - dev->usb_regs[i][0x20] = 0x01; - dev->usb_regs[i][0x21] = 0x03; - if (dev->local == VIA_PIPC_686B) - dev->usb_regs[i][0x34] = 0x80; - dev->usb_regs[i][0x3d] = 0x04; + dev->usb_regs[i][0x0a] = 0x03; + dev->usb_regs[i][0x0b] = 0x0c; + dev->usb_regs[i][0x0d] = 0x16; + dev->usb_regs[i][0x20] = 0x01; + dev->usb_regs[i][0x21] = 0x03; + if (dev->local == VIA_PIPC_686B) + dev->usb_regs[i][0x34] = 0x80; + dev->usb_regs[i][0x3d] = 0x04; - dev->usb_regs[i][0x60] = 0x10; - if (dev->local >= VIA_PIPC_686A) { - dev->usb_regs[i][0x80] = 0x01; - dev->usb_regs[i][0x82] = 0x02; - } - dev->usb_regs[i][0xc1] = 0x20; + dev->usb_regs[i][0x60] = 0x10; + if (dev->local >= VIA_PIPC_686A) { + dev->usb_regs[i][0x80] = 0x01; + dev->usb_regs[i][0x82] = 0x02; + } + dev->usb_regs[i][0xc1] = 0x20; } /* Power management registers. */ if (dev->acpi) { - dev->max_func++; - dev->power_regs[0x00] = 0x06; dev->power_regs[0x01] = 0x11; - if (dev->local >= VIA_PIPC_8231) { - /* The VT8231 preliminary datasheet lists *two* inaccurate - device IDs (3068 and 3057). Real dumps have 8235. */ - dev->power_regs[0x02] = 0x35; dev->power_regs[0x03] = 0x82; - } else { - if (dev->local <= VIA_PIPC_586B) - dev->power_regs[0x02] = 0x40; - else if (dev->local <= VIA_PIPC_596B) - dev->power_regs[0x02] = 0x50; - else - dev->power_regs[0x02] = 0x57; - dev->power_regs[0x03] = 0x30; - } - dev->power_regs[0x04] = 0x00; dev->power_regs[0x05] = 0x00; - dev->power_regs[0x06] = (dev->local == VIA_PIPC_686B) ? 0x90 : 0x80; dev->power_regs[0x07] = 0x02; - switch (dev->local) { - case VIA_PIPC_586B: - case VIA_PIPC_686A: - case VIA_PIPC_8231: - dev->power_regs[0x08] = 0x10; - break; + dev->max_func++; + dev->power_regs[0x00] = 0x06; + dev->power_regs[0x01] = 0x11; + if (dev->local >= VIA_PIPC_8231) { + /* The VT8231 preliminary datasheet lists *two* inaccurate + device IDs (3068 and 3057). Real dumps have 8235. */ + dev->power_regs[0x02] = 0x35; + dev->power_regs[0x03] = 0x82; + } else { + if (dev->local <= VIA_PIPC_586B) + dev->power_regs[0x02] = 0x40; + else if (dev->local <= VIA_PIPC_596B) + dev->power_regs[0x02] = 0x50; + else + dev->power_regs[0x02] = 0x57; + dev->power_regs[0x03] = 0x30; + } + dev->power_regs[0x04] = 0x00; + dev->power_regs[0x05] = 0x00; + dev->power_regs[0x06] = (dev->local == VIA_PIPC_686B) ? 0x90 : 0x80; + dev->power_regs[0x07] = 0x02; + switch (dev->local) { + case VIA_PIPC_586B: + case VIA_PIPC_686A: + case VIA_PIPC_8231: + dev->power_regs[0x08] = 0x10; + break; - case VIA_PIPC_596A: - dev->power_regs[0x08] = 0x20; - break; + case VIA_PIPC_596A: + dev->power_regs[0x08] = 0x20; + break; - case VIA_PIPC_596B: - dev->power_regs[0x08] = 0x30; - break; + case VIA_PIPC_596B: + dev->power_regs[0x08] = 0x30; + break; - case VIA_PIPC_686B: - dev->power_regs[0x08] = 0x40; - break; - } - if (dev->local == VIA_PIPC_686B) - dev->power_regs[0x34] = 0x68; - dev->power_regs[0x40] = 0x20; + case VIA_PIPC_686B: + dev->power_regs[0x08] = 0x40; + break; - dev->power_regs[0x42] = 0x50; - dev->power_regs[0x48] = 0x01; + default: + break; + } + if (dev->local == VIA_PIPC_686B) + dev->power_regs[0x34] = 0x68; + dev->power_regs[0x40] = 0x20; - if (dev->local == VIA_PIPC_686B) { - dev->power_regs[0x68] = 0x01; - dev->power_regs[0x6a] = 0x02; - } + dev->power_regs[0x42] = 0x50; + dev->power_regs[0x48] = 0x01; - if (dev->local >= VIA_PIPC_686A) - dev->power_regs[0x70] = 0x01; + if (dev->local == VIA_PIPC_686B) { + dev->power_regs[0x68] = 0x01; + dev->power_regs[0x6a] = 0x02; + } - if (dev->local == VIA_PIPC_596A) - dev->power_regs[0x80] = 0x01; - else if (dev->local >= VIA_PIPC_596B) - dev->power_regs[0x90] = 0x01; + if (dev->local >= VIA_PIPC_686A) + dev->power_regs[0x70] = 0x01; - /* Set up PCS I/O traps. */ - pipc_io_trap_t *trap; - for (i = 0; i <= dev->max_pcs; i++) { - trap = &dev->io_traps[TRAP_GR0 + i]; - trap->dev = dev; - trap->trap = io_trap_add(pipc_io_trap_glb, trap); - if (i & 2) { - trap->sts_reg = (uint32_t *) &dev->acpi->regs.extiotrapsts; - trap->en_reg = (uint32_t *) &dev->acpi->regs.extiotrapen; - trap->mask = 0x01 << (i & 1); - } else { - trap->sts_reg = &dev->acpi->regs.glbsts; - trap->en_reg = &dev->acpi->regs.glben; - trap->mask = 0x4000 << i; - } - } + if (dev->local == VIA_PIPC_596A) + dev->power_regs[0x80] = 0x01; + else if (dev->local >= VIA_PIPC_596B) + dev->power_regs[0x90] = 0x01; + + /* Set up PCS I/O traps. */ + pipc_io_trap_t *trap; + for (i = 0; i <= dev->max_pcs; i++) { + trap = &dev->io_traps[TRAP_GR0 + i]; + trap->dev = dev; + trap->trap = io_trap_add(pipc_io_trap_glb, trap); + if (i & 2) { + trap->sts_reg = (uint32_t *) &dev->acpi->regs.extiotrapsts; + trap->en_reg = (uint32_t *) &dev->acpi->regs.extiotrapen; + trap->mask = 0x01 << (i & 1); + } else { + trap->sts_reg = &dev->acpi->regs.glbsts; + trap->en_reg = &dev->acpi->regs.glben; + trap->mask = 0x4000 << i; + } + } } /* AC97/MC97 registers. */ if (dev->local >= VIA_PIPC_686A) { - for (i = 0; i <= 1; i++) { - dev->max_func++; - dev->ac97_regs[i][0x00] = 0x06; dev->ac97_regs[i][0x01] = 0x11; - dev->ac97_regs[i][0x02] = 0x58 + (0x10 * i); dev->ac97_regs[i][0x03] = 0x30; - dev->ac97_regs[i][0x06] = 0x10 * (1 - i); dev->ac97_regs[i][0x07] = 0x02; - switch (dev->local) { - case VIA_PIPC_686A: - dev->ac97_regs[i][0x08] = (i == 0) ? 0x12 : 0x01; - break; + for (i = 0; i <= 1; i++) { + dev->max_func++; + dev->ac97_regs[i][0x00] = 0x06; + dev->ac97_regs[i][0x01] = 0x11; + dev->ac97_regs[i][0x02] = 0x58 + (0x10 * i); + dev->ac97_regs[i][0x03] = 0x30; + dev->ac97_regs[i][0x06] = 0x10 * (1 - i); + dev->ac97_regs[i][0x07] = 0x02; + switch (dev->local) { + case VIA_PIPC_686A: + dev->ac97_regs[i][0x08] = (i == 0) ? 0x12 : 0x01; + break; - case VIA_PIPC_686B: - dev->ac97_regs[i][0x08] = (i == 0) ? 0x50 : 0x30; - break; + case VIA_PIPC_686B: + dev->ac97_regs[i][0x08] = (i == 0) ? 0x50 : 0x30; + break; - case VIA_PIPC_8231: - dev->ac97_regs[i][0x08] = (i == 0) ? 0x40 : 0x20; - break; - } + case VIA_PIPC_8231: + dev->ac97_regs[i][0x08] = (i == 0) ? 0x40 : 0x20; + break; - if (i == 0) { - dev->ac97_regs[i][0x0a] = 0x01; - dev->ac97_regs[i][0x0b] = 0x04; - } else { - dev->ac97_regs[i][0x0a] = 0x80; - dev->ac97_regs[i][0x0b] = 0x07; - } + default: + break; + } - dev->ac97_regs[i][0x10] = 0x01; - if (i == 0) { - dev->ac97_regs[i][0x14] = 0x01; - dev->ac97_regs[i][0x18] = 0x01; - } - dev->ac97_regs[i][0x1c] = 0x01; + if (i == 0) { + dev->ac97_regs[i][0x0a] = 0x01; + dev->ac97_regs[i][0x0b] = 0x04; + } else { + dev->ac97_regs[i][0x0a] = 0x80; + dev->ac97_regs[i][0x0b] = 0x07; + } - dev->ac97_regs[i][0x3d] = 0x03; + dev->ac97_regs[i][0x10] = 0x01; + if (i == 0) { + dev->ac97_regs[i][0x14] = 0x01; + dev->ac97_regs[i][0x18] = 0x01; + } + dev->ac97_regs[i][0x1c] = 0x01; - if (i == 0) - dev->ac97_regs[i][0x40] = 0x01; + dev->ac97_regs[i][0x3d] = 0x03; - dev->ac97_regs[i][0x43] = 0x1c; - dev->ac97_regs[i][0x48] = 0x01; - dev->ac97_regs[i][0x4b] = 0x02; + if (i == 0) + dev->ac97_regs[i][0x40] = 0x01; - pipc_sgd_handlers(dev, i); - pipc_codec_handlers(dev, i); - pipc_sb_handlers(dev, i); - } + dev->ac97_regs[i][0x43] = 0x1c; + dev->ac97_regs[i][0x48] = 0x01; + dev->ac97_regs[i][0x4b] = 0x02; + + pipc_sgd_handlers(dev, i); + pipc_codec_handlers(dev, i); + pipc_sb_handlers(dev, i); + } } if (dev->gameport) - gameport_remap(dev->gameport, 0x200); + gameport_remap(dev->gameport, 0x200); pci_set_irq_routing(PCI_INTA, PCI_IRQ_DISABLED); pci_set_irq_routing(PCI_INTB, PCI_IRQ_DISABLED); @@ -476,10 +513,10 @@ pipc_reset_hard(void *priv) pci_set_irq_routing(PCI_INTD, PCI_IRQ_DISABLED); if (dev->local <= VIA_PIPC_586B) { - pci_set_mirq_routing(PCI_MIRQ0, PCI_IRQ_DISABLED); - pci_set_mirq_routing(PCI_MIRQ1, PCI_IRQ_DISABLED); - if (dev->local == VIA_PIPC_586B) - pci_set_mirq_routing(PCI_MIRQ2, PCI_IRQ_DISABLED); + pci_set_mirq_routing(PCI_MIRQ0, PCI_IRQ_DISABLED); + pci_set_mirq_routing(PCI_MIRQ1, PCI_IRQ_DISABLED); + if (dev->local == VIA_PIPC_586B) + pci_set_mirq_routing(PCI_MIRQ2, PCI_IRQ_DISABLED); } ide_pri_disable(); @@ -489,63 +526,59 @@ pipc_reset_hard(void *priv) nvr_via_wp_set(0x00, 0x0d, dev->nvr); } - static void pipc_ide_handlers(pipc_t *dev) { - uint16_t main, side; + uint16_t main; + uint16_t side; ide_pri_disable(); ide_sec_disable(); if (dev->ide_regs[0x09] & 0x01) { - main = (dev->ide_regs[0x11] << 8) | (dev->ide_regs[0x10] & 0xf8); - side = ((dev->ide_regs[0x15] << 8) | (dev->ide_regs[0x14] & 0xfc)) + 2; + main = (dev->ide_regs[0x11] << 8) | (dev->ide_regs[0x10] & 0xf8); + side = ((dev->ide_regs[0x15] << 8) | (dev->ide_regs[0x14] & 0xfc)) + 2; } else { - main = 0x1f0; - side = 0x3f6; + main = 0x1f0; + side = 0x3f6; } ide_set_base(0, main); ide_set_side(0, side); if (dev->ide_regs[0x09] & 0x04) { - main = (dev->ide_regs[0x19] << 8) | (dev->ide_regs[0x18] & 0xf8); - side = ((dev->ide_regs[0x1d] << 8) | (dev->ide_regs[0x1c] & 0xfc)) + 2; + main = (dev->ide_regs[0x19] << 8) | (dev->ide_regs[0x18] & 0xf8); + side = ((dev->ide_regs[0x1d] << 8) | (dev->ide_regs[0x1c] & 0xfc)) + 2; } else { - main = 0x170; - side = 0x376; + main = 0x170; + side = 0x376; } ide_set_base(1, main); ide_set_side(1, side); if (dev->ide_regs[0x04] & PCI_COMMAND_IO) { - if (dev->ide_regs[0x40] & 0x02) - ide_pri_enable(); - if (dev->ide_regs[0x40] & 0x01) - ide_sec_enable(); + if (dev->ide_regs[0x40] & 0x02) + ide_pri_enable(); + if (dev->ide_regs[0x40] & 0x01) + ide_sec_enable(); } } - static void pipc_ide_irqs(pipc_t *dev) { - int irq_mode[2] = { 0, 0 }; + int irq_mode[2] = { IRQ_MODE_LEGACY, IRQ_MODE_LEGACY }; if (dev->ide_regs[0x09] & 0x01) - irq_mode[0] = (dev->ide_regs[0x3d] & 0x01); + irq_mode[0] = (dev->ide_regs[0x3d] & 0x01) ? IRQ_MODE_PCI_IRQ_PIN : IRQ_MODE_LEGACY; if (dev->ide_regs[0x09] & 0x04) - irq_mode[1] = (dev->ide_regs[0x3d] & 0x01); + irq_mode[1] = (dev->ide_regs[0x3d] & 0x01) ? IRQ_MODE_PCI_IRQ_PIN : IRQ_MODE_LEGACY; - sff_set_irq_mode(dev->bm[0], 0, irq_mode[0]); - sff_set_irq_mode(dev->bm[0], 1, irq_mode[1]); + sff_set_irq_mode(dev->bm[0], irq_mode[0]); - sff_set_irq_mode(dev->bm[1], 0, irq_mode[0]); - sff_set_irq_mode(dev->bm[1], 1, irq_mode[1]); + sff_set_irq_mode(dev->bm[1], irq_mode[1]); } - static void pipc_bus_master_handlers(pipc_t *dev) { @@ -555,60 +588,61 @@ pipc_bus_master_handlers(pipc_t *dev) sff_bus_master_handler(dev->bm[1], (dev->ide_regs[0x04] & 1), base + 8); } - static void pipc_pcs_update(pipc_t *dev) { - uint8_t i, io_base_reg, io_mask_reg, io_mask_shift, enable; - uint16_t io_base, io_mask; + uint8_t io_base_reg; + uint8_t io_mask_reg; + uint8_t io_mask_shift; + uint8_t enable; + uint16_t io_base; + uint16_t io_mask; - for (i = 0; i <= dev->max_pcs; i++) { - if (i & 2) { - io_base_reg = 0x8c; - io_mask_reg = 0x8a; - } else { - io_base_reg = 0x78; - io_mask_reg = 0x80; - } - io_base_reg |= (i & 1) << 1; - io_mask_shift = (i & 1) << 2; + for (uint8_t i = 0; i <= dev->max_pcs; i++) { + if (i & 2) { + io_base_reg = 0x8c; + io_mask_reg = 0x8a; + } else { + io_base_reg = 0x78; + io_mask_reg = 0x80; + } + io_base_reg |= (i & 1) << 1; + io_mask_shift = (i & 1) << 2; - if (dev->local <= VIA_PIPC_596B) - enable = dev->pci_isa_regs[0x76] & (0x10 << i); - else - enable = dev->pci_isa_regs[0x8b] & (0x01 << i); + if (dev->local <= VIA_PIPC_596B) + enable = dev->pci_isa_regs[0x76] & (0x10 << i); + else + enable = dev->pci_isa_regs[0x8b] & (0x01 << i); - io_base = dev->pci_isa_regs[io_base_reg] | (dev->pci_isa_regs[io_base_reg | 1] << 8); - io_mask = (dev->pci_isa_regs[io_mask_reg] >> io_mask_shift) & 0x000f; + io_base = dev->pci_isa_regs[io_base_reg] | (dev->pci_isa_regs[io_base_reg | 1] << 8); + io_mask = (dev->pci_isa_regs[io_mask_reg] >> io_mask_shift) & 0x000f; - pipc_log("PIPC: Mapping PCS%d to %04X-%04X (enable %d)\n", i, io_base, io_base + io_mask, enable); - io_trap_remap(dev->io_traps[TRAP_GR0 + i].trap, enable, io_base & ~io_mask, io_mask + 1); + pipc_log("PIPC: Mapping PCS%d to %04X-%04X (enable %d)\n", i, io_base, io_base + io_mask, enable); + io_trap_remap(dev->io_traps[TRAP_GR0 + i].trap, enable, io_base & ~io_mask, io_mask + 1); } } - static void pipc_trap_update_paden(pipc_t *dev, uint8_t trap_id, - uint32_t paden_mask, uint8_t enable, - uint16_t addr, uint16_t size) + uint32_t paden_mask, uint8_t enable, + uint16_t addr, uint16_t size) { pipc_io_trap_t *trap = &dev->io_traps[trap_id]; - enable = (dev->acpi->regs.paden & paden_mask) && enable; + enable = (dev->acpi->regs.paden & paden_mask) && enable; /* Set up Primary Activity Detect I/O traps dynamically. */ if (enable && !trap->trap) { - trap->dev = dev; - trap->trap = io_trap_add(pipc_io_trap_pact, trap); - trap->sts_reg = &dev->acpi->regs.padsts; - trap->en_reg = &dev->acpi->regs.paden; - trap->mask = paden_mask; + trap->dev = dev; + trap->trap = io_trap_add(pipc_io_trap_pact, trap); + trap->sts_reg = &dev->acpi->regs.padsts; + trap->en_reg = &dev->acpi->regs.paden; + trap->mask = paden_mask; } /* Remap I/O trap. */ io_trap_remap(trap->trap, enable, addr, size); } - static void pipc_trap_update_586(void *priv) { @@ -634,12 +668,10 @@ pipc_trap_update_586(void *priv) pipc_trap_update_paden(dev, TRAP_KBC, 0x00000080, 1, 0x60, 1); } - static void pipc_trap_update_596(void *priv) { pipc_t *dev = (pipc_t *) priv; - int i; /* TRAP_DRQ (00000001) and TRAP_PIRQ (00000002) not implemented. */ @@ -670,14 +702,14 @@ pipc_trap_update_596(void *priv) by the Positive Decoding Control registers. I couldn't probe this behavior on hardware. It's better to be safe and cover all of them than to assume Intel-like behavior (one range). */ - for (i = 0; i < 3; i++) { - pipc_trap_update_paden(dev, TRAP_AUD_MIDI_0 + i, - 0x00000400, (dev->local <= VIA_PIPC_596B) || (dev->power_regs[0x40] & 0x01), - 0x300 + (0x10 * i), 4); + for (uint8_t i = 0; i < 3; i++) { + pipc_trap_update_paden(dev, TRAP_AUD_MIDI_0 + i, + 0x00000400, (dev->local <= VIA_PIPC_596B) || (dev->power_regs[0x40] & 0x01), + 0x300 + (0x10 * i), 4); - pipc_trap_update_paden(dev, TRAP_AUD_SB_0 + i, - 0x00000400, (dev->local <= VIA_PIPC_596B) || (dev->power_regs[0x40] & 0x02), - 0x220 + (0x20 * i), 20); + pipc_trap_update_paden(dev, TRAP_AUD_SB_0 + i, + 0x00000400, (dev->local <= VIA_PIPC_596B) || (dev->power_regs[0x40] & 0x02), + 0x220 + (0x20 * i), 20); } pipc_trap_update_paden(dev, TRAP_AUD_GAME, 0x00000400, (dev->local <= VIA_PIPC_596B) || (dev->power_regs[0x40] & 0x04), 0x200, 8); @@ -688,79 +720,74 @@ pipc_trap_update_596(void *priv) pipc_trap_update_paden(dev, TRAP_AUD_WSS_3, 0x00000400, (dev->local <= VIA_PIPC_596B) || (dev->power_regs[0x40] & 0x08), 0xf40, 8); } - static void pipc_sgd_handlers(pipc_t *dev, uint8_t modem) { if (!dev->ac97) - return; + return; if (modem) - ac97_via_remap_modem_sgd(dev->ac97, dev->ac97_regs[1][0x11] << 8, dev->ac97_regs[1][0x04] & PCI_COMMAND_IO); + ac97_via_remap_modem_sgd(dev->ac97, dev->ac97_regs[1][0x11] << 8, dev->ac97_regs[1][0x04] & PCI_COMMAND_IO); else - ac97_via_remap_audio_sgd(dev->ac97, dev->ac97_regs[0][0x11] << 8, dev->ac97_regs[0][0x04] & PCI_COMMAND_IO); + ac97_via_remap_audio_sgd(dev->ac97, dev->ac97_regs[0][0x11] << 8, dev->ac97_regs[0][0x04] & PCI_COMMAND_IO); } - static void pipc_codec_handlers(pipc_t *dev, uint8_t modem) { if (!dev->ac97) - return; + return; if (modem) - ac97_via_remap_modem_codec(dev->ac97, dev->ac97_regs[1][0x1d] << 8, dev->ac97_regs[1][0x04] & PCI_COMMAND_IO); + ac97_via_remap_modem_codec(dev->ac97, dev->ac97_regs[1][0x1d] << 8, dev->ac97_regs[1][0x04] & PCI_COMMAND_IO); else - ac97_via_remap_audio_codec(dev->ac97, dev->ac97_regs[0][0x1d] << 8, dev->ac97_regs[0][0x04] & PCI_COMMAND_IO); + ac97_via_remap_audio_codec(dev->ac97, dev->ac97_regs[0][0x1d] << 8, dev->ac97_regs[0][0x04] & PCI_COMMAND_IO); } - static uint8_t pipc_fmnmi_read(uint16_t addr, void *priv) { - pipc_t *dev = (pipc_t *) priv; - uint8_t ret = dev->fmnmi_regs[addr & 0x03]; + const pipc_t *dev = (pipc_t *) priv; + uint8_t ret = dev->fmnmi_regs[addr & 0x03]; pipc_log("PIPC: fmnmi_read(%02X) = %02X\n", addr & 0x03, ret); #ifdef VIA_PIPC_FM_EMULATION /* Clear NMI/SMI if enabled. */ - if (dev->ac97_regs[0][0x48] & 0x01) { - if (dev->ac97_regs[0][0x48] & 0x04) - smi_line = 0; - else - nmi = 0; + if (dev->ac97_regs[0][0x48] & 0x01) { + if (dev->ac97_regs[0][0x48] & 0x04) + smi_line = 0; + else + nmi = 0; } #endif return ret; } - static void pipc_fmnmi_handlers(pipc_t *dev, uint8_t modem) { if (!dev->ac97 || modem) - return; + return; if (dev->fmnmi_base) - io_removehandler(dev->fmnmi_base, 4, pipc_fmnmi_read, NULL, NULL, NULL, NULL, NULL, dev); + io_removehandler(dev->fmnmi_base, 4, pipc_fmnmi_read, NULL, NULL, NULL, NULL, NULL, dev); dev->fmnmi_base = (dev->ac97_regs[0][0x15] << 8) | (dev->ac97_regs[0][0x14] & 0xfc); if (dev->fmnmi_base && (dev->ac97_regs[0][0x04] & PCI_COMMAND_IO)) - io_sethandler(dev->fmnmi_base, 4, pipc_fmnmi_read, NULL, NULL, NULL, NULL, NULL, dev); + io_sethandler(dev->fmnmi_base, 4, pipc_fmnmi_read, NULL, NULL, NULL, NULL, NULL, dev); } - static uint8_t pipc_fm_read(uint16_t addr, void *priv) { + const pipc_t *dev = (pipc_t *) priv; #ifdef VIA_PIPC_FM_EMULATION - uint8_t ret = 0x00; + uint8_t ret = ((addr & 0x03) == 0x00) ? dev->fmnmi_status : 0x00; #else - pipc_t *dev = (pipc_t *) priv; - uint8_t ret = opl3_read(addr, &dev->sb->opl); + uint8_t ret = dev->sb->opl.read(addr, dev->sb->opl.priv); #endif pipc_log("PIPC: fm_read(%02X) = %02X\n", addr & 0x03, ret); @@ -768,7 +795,6 @@ pipc_fm_read(uint16_t addr, void *priv) return ret; } - static void pipc_fm_write(uint16_t addr, uint8_t val, void *priv) { @@ -780,143 +806,171 @@ pipc_fm_write(uint16_t addr, uint8_t val, void *priv) /* Real 686B only updates the bank ID register when writing to the index port, and only fires NMI/SMI when writing to the data port. */ if (!(addr & 0x01)) { - dev->fmnmi_regs[0x00] = (addr & 0x02) ? 0x02 : 0x01; - dev->fmnmi_regs[0x01] = val; + dev->fmnmi_regs[0x00] = (addr & 0x02) ? 0x02 : 0x01; + dev->fmnmi_regs[0x02] = val; } else { - dev->fmnmi_regs[0x02] = val; + dev->fmnmi_regs[0x01] = val; - /* Fire NMI/SMI if enabled. */ - if (dev->ac97_regs[0][0x48] & 0x01) { - if (dev->ac97_regs[0][0x48] & 0x04) - smi_line = 1; - else - nmi = 1; - } + /* TODO: Probe how real hardware handles OPL timers. This assumed implementation + just sets the relevant interrupt flags as soon as a timer is started. */ + if (!(addr & 0x02) && (dev->fmnmi_regs[0x02] == 0x04)) { + if (val & 0x80) + dev->fmnmi_status = 0x00; + if ((val & 0x41) == 0x01) + dev->fmnmi_status |= 0x40; + if ((val & 0x22) == 0x02) + dev->fmnmi_status |= 0x20; + if (dev->fmnmi_status & 0x60) + dev->fmnmi_status |= 0x80; + } + + /* Fire NMI/SMI if enabled. */ + if (dev->ac97_regs[0][0x48] & 0x01) { + pipc_log("PIPC: Raising %s\n", (dev->ac97_regs[0][0x48] & 0x04) ? "SMI" : "NMI"); + if (dev->ac97_regs[0][0x48] & 0x04) + smi_raise(); + else + nmi_raise(); + } } #else - opl3_write(addr, val, &dev->sb->opl); + dev->sb->opl.write(addr, val, dev->sb->opl.priv); #endif } - static void pipc_sb_handlers(pipc_t *dev, uint8_t modem) { if (!dev->ac97 || modem) - return; + return; sb_dsp_setaddr(&dev->sb->dsp, 0); if (dev->sb_base) { - io_removehandler(dev->sb_base, 4, opl3_read, NULL, NULL, opl3_write, NULL, NULL, &dev->sb->opl); - io_removehandler(dev->sb_base + 8, 2, opl3_read, NULL, NULL, opl3_write, NULL, NULL, &dev->sb->opl); - io_removehandler(dev->sb_base + 4, 2, sb_ct1345_mixer_read, NULL, NULL, sb_ct1345_mixer_write, NULL, NULL, dev->sb); + io_removehandler(dev->sb_base, 4, dev->sb->opl.read, NULL, NULL, dev->sb->opl.write, NULL, NULL, dev->sb->opl.priv); + io_removehandler(dev->sb_base + 8, 2, dev->sb->opl.read, NULL, NULL, dev->sb->opl.write, NULL, NULL, dev->sb->opl.priv); + io_removehandler(dev->sb_base + 4, 2, sb_ct1345_mixer_read, NULL, NULL, sb_ct1345_mixer_write, NULL, NULL, dev->sb); } mpu401_change_addr(dev->sb->mpu, 0); mpu401_setirq(dev->sb->mpu, 0); - io_removehandler(0x388, 4, opl3_read, NULL, NULL, opl3_write, NULL, NULL, &dev->sb->opl); + io_removehandler(0x388, 4, dev->sb->opl.read, NULL, NULL, dev->sb->opl.write, NULL, NULL, dev->sb->opl.priv); if (dev->ac97_regs[0][0x42] & 0x01) { - dev->sb_base = 0x220 + (0x20 * (dev->ac97_regs[0][0x43] & 0x03)); - sb_dsp_setaddr(&dev->sb->dsp, dev->sb_base); - if (dev->ac97_regs[0][0x42] & 0x04) { - io_sethandler(dev->sb_base, 4, opl3_read, NULL, NULL, opl3_write, NULL, NULL, &dev->sb->opl); - io_sethandler(dev->sb_base + 8, 2, opl3_read, NULL, NULL, opl3_write, NULL, NULL, &dev->sb->opl); - } - io_sethandler(dev->sb_base + 4, 2, sb_ct1345_mixer_read, NULL, NULL, sb_ct1345_mixer_write, NULL, NULL, dev->sb); + dev->sb_base = 0x220 + (0x20 * (dev->ac97_regs[0][0x43] & 0x03)); + sb_dsp_setaddr(&dev->sb->dsp, dev->sb_base); + if (dev->ac97_regs[0][0x42] & 0x04) { + io_sethandler(dev->sb_base, 4, dev->sb->opl.read, NULL, NULL, dev->sb->opl.write, NULL, NULL, dev->sb->opl.priv); + io_sethandler(dev->sb_base + 8, 2, dev->sb->opl.read, NULL, NULL, dev->sb->opl.write, NULL, NULL, dev->sb->opl.priv); + } + io_sethandler(dev->sb_base + 4, 2, sb_ct1345_mixer_read, NULL, NULL, sb_ct1345_mixer_write, NULL, NULL, dev->sb); - uint8_t irq = 5 + (2 * ((dev->ac97_regs[0][0x43] >> 6) & 0x03)); - sb_dsp_setirq(&dev->sb->dsp, (irq == 11) ? 10 : irq); + uint8_t irq = 5 + (2 * ((dev->ac97_regs[0][0x43] >> 6) & 0x03)); + sb_dsp_setirq(&dev->sb->dsp, (irq == 11) ? 10 : irq); - sb_dsp_setdma8(&dev->sb->dsp, (dev->ac97_regs[0][0x43] >> 4) & 0x03); + sb_dsp_setdma8(&dev->sb->dsp, (dev->ac97_regs[0][0x43] >> 4) & 0x03); - /* Set up CD audio filter. This might not actually work if VIAUDIO writes to CD volume through AC97. */ - sound_set_cd_audio_filter(sbpro_filter_cd_audio, dev->sb); + /* Set up CD audio filter. This might not actually work if VIAUDIO writes to CD volume through AC97. */ + sound_set_cd_audio_filter(sbpro_filter_cd_audio, dev->sb); } if (dev->ac97_regs[0][0x42] & 0x02) { - /* BAR 2 is a mess. The MPU and game port remapping registers that VIA claims to be there don't - seem to actually exist on a real 686B. Remapping the MPU to BAR 2 itself does work, though. */ - if (dev->ac97_regs[0][0x42] & 0x80) - mpu401_change_addr(dev->sb->mpu, (dev->ac97_regs[0][0x19] << 8) | (dev->ac97_regs[0][0x18] & 0xfc)); - else - mpu401_change_addr(dev->sb->mpu, 0x300 | ((dev->ac97_regs[0][0x43] << 2) & 0x30)); + /* BAR 2 is a mess. The MPU and game port remapping registers that VIA claims to be there don't + seem to actually exist on a real 686B. Remapping the MPU to BAR 2 itself does work, though. */ + if (dev->ac97_regs[0][0x42] & 0x80) + mpu401_change_addr(dev->sb->mpu, (dev->ac97_regs[0][0x19] << 8) | (dev->ac97_regs[0][0x18] & 0xfc)); + else + mpu401_change_addr(dev->sb->mpu, 0x300 | ((dev->ac97_regs[0][0x43] << 2) & 0x30)); if (!(dev->ac97_regs[0][0x42] & 0x40)) - mpu401_setirq(dev->sb->mpu, dev->sb->dsp.sb_irqnum); + mpu401_setirq(dev->sb->mpu, dev->sb->dsp.sb_irqnum); } if (dev->ac97_regs[0][0x42] & 0x04) { - io_sethandler(0x388, 4, pipc_fm_read, NULL, NULL, pipc_fm_write, NULL, NULL, dev); + io_sethandler(0x388, 4, pipc_fm_read, NULL, NULL, pipc_fm_write, NULL, NULL, dev); +#ifndef VIA_PIPC_FM_EMULATION + dev->sb->opl_enabled = 1; + } else { + dev->sb->opl_enabled = 0; +#endif } } +static void +pipc_sb_get_buffer(int32_t *buffer, int len, void *priv) +{ + pipc_t *dev = (pipc_t *) priv; + + /* Poll SB audio only if the legacy block is enabled. */ +#ifdef VIA_PIPC_FM_EMULATION + if (dev->ac97_regs[0][0x42] & 0x01) +#else + if (dev->ac97_regs[0][0x42] & 0x05) +#endif + sb_get_buffer_sbpro(buffer, len, dev->sb); +} static uint8_t pipc_read(int func, int addr, void *priv) { pipc_t *dev = (pipc_t *) priv; uint8_t ret = 0xff; - int c; + int c; uint8_t pm_func = dev->usb[1] ? 4 : 3; if (func > dev->max_func) - return ret; - else if (func == 0) { /* PCI-ISA bridge */ - if ((addr >= 0x60) && (addr <= 0x6f)) { /* DMA shadow registers */ - c = (addr & 0x0e) >> 1; - if (addr & 0x01) - ret = (dma[c].ab & 0x0000ff00) >> 8; - else { - ret = (dma[c].ab & 0x000000f0); - ret |= (!!(dma_e & (1 << c)) << 3); - } - } else - ret = dev->pci_isa_regs[addr]; - } - else if ((func == 1) && !(dev->pci_isa_regs[0x48] & 0x02)) { /* IDE */ - ret = dev->ide_regs[addr]; - if ((addr >= 0x50) && (addr <= 0x53)) { /* UDMA timing registers */ - /* Set or clear bit 5 according to UDMA mode. Documentation is unclear, but a real - 686B does set bit 5 when UDMA is enabled through the method specified in bit 7. */ - c = 0x53 - addr; - if (ret & 0x80) /* bit 7 set = use bit 6 */ - c = ret & 0x40; - else if (ide_drives[c]) /* bit 7 clear = use SET FEATURES mode */ - c = (ide_drives[c]->mdma_mode & 0x300) == 0x300; - else /* no drive here */ - c = 0; - /* 586A/B datasheet claims bit 5 must be clear for UDMA, unlike later models where - it must be set, but the Windows driver doesn't care and always checks if it's set. */ - if (c) - ret |= 0x20; - else - ret &= ~0x20; - } - } - else if ((func < pm_func) && !((func == 2) ? (dev->pci_isa_regs[0x48] & 0x04) : (dev->pci_isa_regs[0x85] & 0x10))) /* USB */ - ret = dev->usb_regs[func - 2][addr]; + return ret; + else if (func == 0) { /* PCI-ISA bridge */ + if ((addr >= 0x60) && (addr <= 0x6f)) { /* DMA shadow registers */ + c = (addr & 0x0e) >> 1; + if (addr & 0x01) + ret = (dma[c].ab & 0x0000ff00) >> 8; + else { + ret = (dma[c].ab & 0x000000f0); + ret |= (!!(dma_e & (1 << c)) << 3); + } + } else + ret = dev->pci_isa_regs[addr]; + } else if ((func == 1) && !(dev->pci_isa_regs[0x48] & 0x02)) { /* IDE */ + ret = dev->ide_regs[addr]; + if ((addr >= 0x50) && (addr <= 0x53)) { /* UDMA timing registers */ + /* Set or clear bit 5 according to UDMA mode. Documentation is unclear, but a real + 686B does set bit 5 when UDMA is enabled through the method specified in bit 7. */ + c = 0x53 - addr; + if (ret & 0x80) /* bit 7 set = use bit 6 */ + c = ret & 0x40; + else if (ide_drives[c]) /* bit 7 clear = use SET FEATURES mode */ + c = (ide_drives[c]->mdma_mode & 0x300) == 0x300; + else /* no drive here */ + c = 0; + /* 586A/B datasheet claims bit 5 must be clear for UDMA, unlike later models where + it must be set, but the Windows driver doesn't care and always checks if it's set. */ + if (c) + ret |= 0x20; + else + ret &= ~0x20; + } + } else if ((func < pm_func) && !((func == 2) ? (dev->pci_isa_regs[0x48] & 0x04) : (dev->pci_isa_regs[0x85] & 0x10))) /* USB */ + ret = dev->usb_regs[func - 2][addr]; else if (func == pm_func) { /* Power */ - ret = dev->power_regs[addr]; - if (addr == 0x42) { - if (dev->nvr->regs[0x0d] & 0x80) - ret |= 0x10; - else - ret &= ~0x10; - } else if ((addr == 0xd2) && (dev->local == VIA_PIPC_686B)) { - /* SMBus clock select bit. */ - if (dev->smbus->clock == 16384) - ret &= ~0x10; - else - ret |= 0x10; - } - } - else if ((func <= (pm_func + 2)) && !(dev->pci_isa_regs[0x85] & ((func == (pm_func + 1)) ? 0x04 : 0x08))) { /* AC97 / MC97 */ - if (addr == 0x40) - ret = ac97_via_read_status(dev->ac97, func - pm_func - 1); - else - ret = dev->ac97_regs[func - pm_func - 1][addr]; + ret = dev->power_regs[addr]; + if (addr == 0x42) { + if (dev->nvr->regs[0x0d] & 0x80) + ret |= 0x10; + else + ret &= ~0x10; + } else if ((addr == 0xd2) && (dev->local == VIA_PIPC_686B)) { + /* SMBus clock select bit. */ + if (dev->smbus->clock == 16384) + ret &= ~0x10; + else + ret |= 0x10; + } + } else if ((func <= (pm_func + 2)) && !(dev->pci_isa_regs[0x85] & ((func == (pm_func + 1)) ? 0x04 : 0x08))) { /* AC97 / MC97 */ + if (addr == 0x40) + ret = ac97_via_read_status(dev->ac97, func - pm_func - 1); + else + ret = dev->ac97_regs[func - pm_func - 1][addr]; } pipc_log("PIPC: read(%d, %02X) = %02X\n", func, addr, ret); @@ -924,614 +978,652 @@ pipc_read(int func, int addr, void *priv) return ret; } - static void nvr_update_io_mapping(pipc_t *dev) { if (dev->nvr_enabled) - nvr_at_handler(0, 0x0074, dev->nvr); + nvr_at_handler(0, 0x0074, dev->nvr); if ((dev->pci_isa_regs[0x5b] & 0x02) || (dev->pci_isa_regs[0x48] & 0x08)) - nvr_at_handler(1, 0x0074, dev->nvr); + nvr_at_handler(1, 0x0074, dev->nvr); } - static void usb_update_io_mapping(pipc_t *dev, int func) { uhci_update_io_mapping(dev->usb[func - 2], dev->usb_regs[func - 2][0x20] & ~0x1f, dev->usb_regs[func - 2][0x21], dev->usb_regs[func - 2][PCI_REG_COMMAND] & PCI_COMMAND_IO); } - static void pipc_ddma_update(pipc_t *dev, int addr) { uint32_t base; if (dev->local >= VIA_PIPC_8231) - return; + return; base = (dev->pci_isa_regs[addr] & 0xf0) | (((uint32_t) dev->pci_isa_regs[addr | 0x01]) << 8); ddma_update_io_mapping(dev->ddma, (addr & 0x0e) >> 1, (dev->pci_isa_regs[addr] & 0xf0), dev->pci_isa_regs[addr | 0x01], (dev->pci_isa_regs[addr] & 0x08) && (base != 0x0000)); } - static void pipc_write(int func, int addr, uint8_t val, void *priv) { pipc_t *dev = (pipc_t *) priv; - int c; + int c; uint8_t pm_func = dev->usb[1] ? 4 : 3; if (func > dev->max_func) - return; + return; pipc_log("PIPC: write(%d, %02X, %02X)\n", func, addr, val); if (func == 0) { /* PCI-ISA bridge */ - /* Read-only addresses. */ - if ((addr < 4) || (addr == 5) || ((addr >= 8) && (addr < 0x40)) || (addr == 0x49) || (addr == 0x4b) || - (addr == 0x53) || ((addr >= 0x5d) && (addr < 0x5f)) || (addr >= 0x90)) - return; + /* Read-only addresses. */ + if ((addr < 4) || (addr == 5) || ((addr >= 8) && (addr < 0x40)) || (addr == 0x49) || (addr == 0x4b) || (addr == 0x53) || ((addr >= 0x5d) && (addr < 0x5f)) || (addr >= 0x90)) + return; - if ((dev->local <= VIA_PIPC_586A) && ((addr >= 0x58) && (addr < 0x80))) - return; + if ((dev->local <= VIA_PIPC_586A) && ((addr >= 0x58) && (addr < 0x80))) + return; - if ((dev->local <= VIA_PIPC_586B) && (addr >= 0x74)) - return; + if ((dev->local <= VIA_PIPC_586B) && (addr >= 0x74)) + return; - if ((dev->local <= VIA_PIPC_596A) && ((addr == 0x51) || (addr == 0x52) || (addr == 0x5f) || (addr == 0x85) || - (addr == 0x86) || ((addr >= 0x8a) && (addr < 0x90)))) - return; + if ((dev->local <= VIA_PIPC_596A) && ((addr == 0x51) || (addr == 0x52) || (addr == 0x5f) || (addr == 0x85) || (addr == 0x86) || ((addr >= 0x8a) && (addr < 0x90)))) + return; - switch (addr) { - case 0x04: - dev->pci_isa_regs[0x04] = (val & 8) | 7; - break; - case 0x07: - dev->pci_isa_regs[0x07] &= ~(val & 0xb0); - break; + switch (addr) { + case 0x04: + dev->pci_isa_regs[0x04] = (val & 8) | 7; + break; + case 0x07: + dev->pci_isa_regs[0x07] &= ~(val & 0xb0); + break; - case 0x42: - dev->pci_isa_regs[0x42] = val & 0xcf; + case 0x42: + dev->pci_isa_regs[0x42] = val & 0xcf; - switch (val & 0xf) { - /* Divisors on the PCI clock. */ - case 0x8: - cpu_set_isa_pci_div(3); - break; + switch (val & 0xf) { + /* Divisors on the PCI clock. */ + case 0x8: + cpu_set_isa_pci_div(3); + break; - case 0x9: - cpu_set_isa_pci_div(2); - break; + case 0x9: + cpu_set_isa_pci_div(2); + break; - /* case 0xa: same as default */ + /* case 0xa: same as default */ - case 0xb: - cpu_set_isa_pci_div(6); - break; + case 0xb: + cpu_set_isa_pci_div(6); + break; - case 0xc: - cpu_set_isa_pci_div(5); - break; + case 0xc: + cpu_set_isa_pci_div(5); + break; - case 0xd: - cpu_set_isa_pci_div(10); - break; + case 0xd: + cpu_set_isa_pci_div(10); + break; - case 0xe: - cpu_set_isa_pci_div(12); - break; + case 0xe: + cpu_set_isa_pci_div(12); + break; - /* Half oscillator clock. */ - case 0xf: - cpu_set_isa_speed(7159091); - break; + /* Half oscillator clock. */ + case 0xf: + cpu_set_isa_speed(7159091); + break; - /* Divisor 4 on the PCI clock whenever bit 3 is clear. */ - default: - cpu_set_isa_pci_div(4); - break; - } + /* Divisor 4 on the PCI clock whenever bit 3 is clear. */ + default: + cpu_set_isa_pci_div(4); + break; + } - break; + break; - case 0x47: - if (val & 0x01) - trc_write(0x0047, (val & 0x80) ? 0x06 : 0x04, NULL); - pic_set_shadow(!!(val & 0x10)); - pic_elcr_io_handler(!!(val & 0x20)); - dev->pci_isa_regs[0x47] = val & 0xfe; - break; - case 0x48: - dev->pci_isa_regs[0x48] = val; - nvr_update_io_mapping(dev); - break; + case 0x44: + dev->pci_isa_regs[0x44] = val; + break; - case 0x50: case 0x51: case 0x52: case 0x85: - dev->pci_isa_regs[addr] = val; - /* Forward Super I/O-related registers to sio_vt82c686.c */ - if (dev->sio) - vt82c686_sio_write(addr, val, dev->sio); - break; + case 0x47: + if (val & 0x01) + pci_write(0x0cf9, (val & 0x80) ? 0x06 : 0x04, NULL); + pic_set_shadow(!!(val & 0x10)); + pic_elcr_io_handler(!!(val & 0x20)); + dev->pci_isa_regs[0x47] = val & 0xfe; + break; + case 0x48: + dev->pci_isa_regs[0x48] = val; + nvr_update_io_mapping(dev); + break; - case 0x54: - pci_set_irq_level(PCI_INTA, !(val & 8)); - pci_set_irq_level(PCI_INTB, !(val & 4)); - pci_set_irq_level(PCI_INTC, !(val & 2)); - pci_set_irq_level(PCI_INTD, !(val & 1)); - dev->pci_isa_regs[0x54] = val & 0x0f; - break; - case 0x55: - pipc_log("PIPC: Steering PIRQ%c to IRQ %d\n", (dev->local >= VIA_PIPC_596A) ? 'A' : 'D', val >> 4); - pci_set_irq_routing((dev->local >= VIA_PIPC_596A) ? PCI_INTA : PCI_INTD, (val & 0xf0) ? (val >> 4) : PCI_IRQ_DISABLED); - if (dev->local <= VIA_PIPC_586B) { - pipc_log("PIPC: Steering MIRQ0 to IRQ %d\n", val & 0x0f); - pci_set_mirq_routing(PCI_MIRQ0, (val & 0x0f) ? (val & 0x0f) : PCI_IRQ_DISABLED); - } - dev->pci_isa_regs[0x55] = val; - break; - case 0x56: - pipc_log("PIPC: Steering PIRQ%c to IRQ %d\n", (dev->local >= VIA_PIPC_596A) ? 'C' : 'A', val >> 4); - pipc_log("PIPC: Steering PIRQB to IRQ %d\n", val & 0x0f); - pci_set_irq_routing((dev->local >= VIA_PIPC_596A) ? PCI_INTC : PCI_INTA, (val & 0xf0) ? (val >> 4) : PCI_IRQ_DISABLED); - pci_set_irq_routing(PCI_INTB, (val & 0x0f) ? (val & 0x0f) : PCI_IRQ_DISABLED); - dev->pci_isa_regs[0x56] = val; - break; - case 0x57: - pipc_log("PIPC: Steering PIRQ%c to IRQ %d\n", (dev->local >= VIA_PIPC_596A) ? 'D' : 'C', val >> 4); - pci_set_irq_routing((dev->local >= VIA_PIPC_596A) ? PCI_INTD : PCI_INTC, (val & 0xf0) ? (val >> 4) : PCI_IRQ_DISABLED); - if (dev->local <= VIA_PIPC_586B) { - pipc_log("PIPC: Steering MIRQ1 to IRQ %d\n", val & 0x0f); - pci_set_mirq_routing(PCI_MIRQ1, (val & 0x0f) ? (val & 0x0f) : PCI_IRQ_DISABLED); - } - dev->pci_isa_regs[0x57] = val; - break; - case 0x58: - if (dev->local == VIA_PIPC_586B) { - pipc_log("PIPC: Steering MIRQ2 to IRQ %d\n", val & 0x0f); - pci_set_mirq_routing(PCI_MIRQ2, (val & 0x0f) ? (val & 0x0f) : PCI_IRQ_DISABLED); - } - dev->pci_isa_regs[0x58] = val; - break; - case 0x5b: - dev->pci_isa_regs[0x5b] = val; - nvr_update_io_mapping(dev); - break; + case 0x50: + case 0x51: + case 0x52: + case 0x85: + dev->pci_isa_regs[addr] = val; + /* Forward Super I/O-related registers to sio_vt82c686.c */ + if (dev->sio) + vt82c686_sio_write(addr, val, dev->sio); + break; - case 0x60: case 0x62: case 0x64: case 0x66: - case 0x6a: case 0x6c: case 0x6e: - dev->pci_isa_regs[addr] = val & 0xf8; - pipc_ddma_update(dev, addr); - break; - case 0x61: case 0x63: case 0x65: case 0x67: - case 0x6b: case 0x6d: case 0x6f: - dev->pci_isa_regs[addr] = val; - pipc_ddma_update(dev, addr & 0xfe); - break; + case 0x54: + pci_set_irq_level(PCI_INTA, !(val & 8)); + pci_set_irq_level(PCI_INTB, !(val & 4)); + pci_set_irq_level(PCI_INTC, !(val & 2)); + pci_set_irq_level(PCI_INTD, !(val & 1)); + dev->pci_isa_regs[0x54] = val & 0x0f; + break; + case 0x55: + pipc_log("PIPC: Steering PIRQ%c to IRQ %d\n", (dev->local >= VIA_PIPC_596A) ? 'A' : 'D', val >> 4); + pci_set_irq_routing((dev->local >= VIA_PIPC_596A) ? PCI_INTA : PCI_INTD, (val & 0xf0) ? (val >> 4) : PCI_IRQ_DISABLED); + if (dev->local <= VIA_PIPC_586B) { + pipc_log("PIPC: Steering MIRQ0 to IRQ %d\n", val & 0x0f); + pci_set_mirq_routing(PCI_MIRQ0, (val & 0x0f) ? (val & 0x0f) : PCI_IRQ_DISABLED); + } + dev->pci_isa_regs[0x55] = val; + break; + case 0x56: + pipc_log("PIPC: Steering PIRQ%c to IRQ %d\n", (dev->local >= VIA_PIPC_596A) ? 'C' : 'A', val >> 4); + pipc_log("PIPC: Steering PIRQB to IRQ %d\n", val & 0x0f); + pci_set_irq_routing((dev->local >= VIA_PIPC_596A) ? PCI_INTC : PCI_INTA, (val & 0xf0) ? (val >> 4) : PCI_IRQ_DISABLED); + pci_set_irq_routing(PCI_INTB, (val & 0x0f) ? (val & 0x0f) : PCI_IRQ_DISABLED); + dev->pci_isa_regs[0x56] = val; + break; + case 0x57: + pipc_log("PIPC: Steering PIRQ%c to IRQ %d\n", (dev->local >= VIA_PIPC_596A) ? 'D' : 'C', val >> 4); + pci_set_irq_routing((dev->local >= VIA_PIPC_596A) ? PCI_INTD : PCI_INTC, (val & 0xf0) ? (val >> 4) : PCI_IRQ_DISABLED); + if (dev->local <= VIA_PIPC_586B) { + pipc_log("PIPC: Steering MIRQ1 to IRQ %d\n", val & 0x0f); + pci_set_mirq_routing(PCI_MIRQ1, (val & 0x0f) ? (val & 0x0f) : PCI_IRQ_DISABLED); + } + dev->pci_isa_regs[0x57] = val; + break; + case 0x58: + if (dev->local == VIA_PIPC_586B) { + pipc_log("PIPC: Steering MIRQ2 to IRQ %d\n", val & 0x0f); + pci_set_mirq_routing(PCI_MIRQ2, (val & 0x0f) ? (val & 0x0f) : PCI_IRQ_DISABLED); + } + dev->pci_isa_regs[0x58] = val; + break; + case 0x5b: + dev->pci_isa_regs[0x5b] = val; + nvr_update_io_mapping(dev); + break; - case 0x70: case 0x71: case 0x72: case 0x73: - dev->pci_isa_regs[(addr - 0x44)] = val; - break; + case 0x60: + case 0x62: + case 0x64: + case 0x66: + case 0x6a: + case 0x6c: + case 0x6e: + dev->pci_isa_regs[addr] = val & 0xf8; + pipc_ddma_update(dev, addr); + break; + case 0x61: + case 0x63: + case 0x65: + case 0x67: + case 0x6b: + case 0x6d: + case 0x6f: + dev->pci_isa_regs[addr] = val; + pipc_ddma_update(dev, addr & 0xfe); + break; - case 0x74: case 0x8b: - case 0x78: case 0x79: case 0x7a: case 0x7b: - case 0x8c: case 0x8d: case 0x8e: case 0x8f: - case 0x80: case 0x8a: - dev->pci_isa_regs[addr] = val; - pipc_pcs_update(dev); - break; + case 0x70: + case 0x71: + case 0x72: + case 0x73: + dev->pci_isa_regs[addr - 0x44] = val; + break; - case 0x77: - if ((dev->local >= VIA_PIPC_686A) && (val & 0x10)) - pclog("PIPC: Warning: Internal I/O APIC enabled.\n"); - nvr_via_wp_set(!!(val & 0x04), 0x32, dev->nvr); - nvr_via_wp_set(!!(val & 0x02), 0x0d, dev->nvr); - break; + case 0x74: + case 0x8b: + case 0x78: + case 0x79: + case 0x7a: + case 0x7b: + case 0x8c: + case 0x8d: + case 0x8e: + case 0x8f: + case 0x80: + case 0x8a: + dev->pci_isa_regs[addr] = val; + pipc_pcs_update(dev); + break; - default: - dev->pci_isa_regs[addr] = val; - break; - } + case 0x77: + if ((dev->local >= VIA_PIPC_686A) && (val & 0x10)) + pclog("PIPC: Warning: Internal I/O APIC enabled.\n"); + nvr_via_wp_set(!!(val & 0x04), 0x32, dev->nvr); + nvr_via_wp_set(!!(val & 0x02), 0x0d, dev->nvr); + break; + + default: + dev->pci_isa_regs[addr] = val; + break; + } } else if (func == 1) { /* IDE */ - /* Read-only addresses. */ - if ((addr < 4) || (addr == 5) || (addr == 8) || ((addr >= 0xa) && (addr < 0x0d)) || - ((addr >= 0x0e) && (addr < 0x10)) || ((addr >= 0x12) && (addr < 0x13)) || - ((addr >= 0x16) && (addr < 0x17)) || ((addr >= 0x1a) && (addr < 0x1b)) || - ((addr >= 0x1e) && (addr < 0x1f)) || ((addr >= 0x22) && (addr < 0x3c)) || - ((addr >= 0x3e) && (addr < 0x40)) || ((addr >= 0x55) && (addr < 0x60)) || - ((addr >= 0x62) && (addr < 0x68)) || ((addr >= 0x6a) && (addr < 0x70)) || - (addr == 0x72) || (addr == 0x73) || (addr == 0x76) || (addr == 0x77) || - (addr == 0x7a) || (addr == 0x7b) || (addr == 0x7e) || (addr == 0x7f) || - ((addr >= 0x84) && (addr < 0x88)) || (addr >= 0x8c)) - return; + /* Read-only addresses. */ + if ((addr < 4) || (addr == 5) || (addr == 8) || ((addr >= 0xa) && (addr < 0x0d)) || ((addr >= 0x0e) && (addr < 0x10)) || ((addr >= 0x12) && (addr < 0x13)) || ((addr >= 0x16) && (addr < 0x17)) || ((addr >= 0x1a) && (addr < 0x1b)) || ((addr >= 0x1e) && (addr < 0x1f)) || ((addr >= 0x22) && (addr < 0x3c)) || ((addr >= 0x3e) && (addr < 0x40)) || ((addr >= 0x55) && (addr < 0x60)) || ((addr >= 0x62) && (addr < 0x68)) || ((addr >= 0x6a) && (addr < 0x70)) || (addr == 0x72) || (addr == 0x73) || (addr == 0x76) || (addr == 0x77) || (addr == 0x7a) || (addr == 0x7b) || (addr == 0x7e) || (addr == 0x7f) || ((addr >= 0x84) && (addr < 0x88)) || (addr >= 0x8c)) + return; - if ((dev->local <= VIA_PIPC_586B) && ((addr == 0x54) || (addr >= 0x70))) - return; + if ((dev->local <= VIA_PIPC_586B) && ((addr == 0x54) || (addr >= 0x70))) + return; - /* Check disable bit. */ - if (dev->pci_isa_regs[0x48] & 0x02) - return; + /* Check disable bit. */ + if (dev->pci_isa_regs[0x48] & 0x02) + return; - switch (addr) { - case 0x04: - dev->ide_regs[0x04] = val & 0x85; - pipc_ide_handlers(dev); - pipc_bus_master_handlers(dev); - break; - case 0x07: - dev->ide_regs[0x07] &= ~(val & 0xf1); - break; + switch (addr) { + case 0x04: + dev->ide_regs[0x04] = val & 0x85; + pipc_ide_handlers(dev); + pipc_bus_master_handlers(dev); + break; + case 0x07: + dev->ide_regs[0x07] &= ~(val & 0xf1); + break; - case 0x09: - dev->ide_regs[0x09] = (val & 0x05) | 0x8a; - pipc_ide_handlers(dev); - pipc_ide_irqs(dev); - break; + case 0x09: + dev->ide_regs[0x09] = (val & 0x05) | 0x8a; + pipc_ide_handlers(dev); + pipc_ide_irqs(dev); + break; - case 0x10: - dev->ide_regs[0x10] = (val & 0xf8) | 1; - pipc_ide_handlers(dev); - break; - case 0x11: - dev->ide_regs[0x11] = val; - pipc_ide_handlers(dev); - break; + case 0x10: + dev->ide_regs[0x10] = (val & 0xf8) | 1; + pipc_ide_handlers(dev); + break; + case 0x11: + dev->ide_regs[0x11] = val; + pipc_ide_handlers(dev); + break; - case 0x14: - dev->ide_regs[0x14] = (val & 0xfc) | 1; - pipc_ide_handlers(dev); - break; - case 0x15: - dev->ide_regs[0x15] = val; - pipc_ide_handlers(dev); - break; + case 0x14: + dev->ide_regs[0x14] = (val & 0xfc) | 1; + pipc_ide_handlers(dev); + break; + case 0x15: + dev->ide_regs[0x15] = val; + pipc_ide_handlers(dev); + break; - case 0x18: - dev->ide_regs[0x18] = (val & 0xf8) | 1; - pipc_ide_handlers(dev); - break; - case 0x19: - dev->ide_regs[0x19] = val; - pipc_ide_handlers(dev); - break; + case 0x18: + dev->ide_regs[0x18] = (val & 0xf8) | 1; + pipc_ide_handlers(dev); + break; + case 0x19: + dev->ide_regs[0x19] = val; + pipc_ide_handlers(dev); + break; - case 0x1c: - dev->ide_regs[0x1c] = (val & 0xfc) | 1; - pipc_ide_handlers(dev); - break; - case 0x1d: - dev->ide_regs[0x1d] = val; - pipc_ide_handlers(dev); - break; + case 0x1c: + dev->ide_regs[0x1c] = (val & 0xfc) | 1; + pipc_ide_handlers(dev); + break; + case 0x1d: + dev->ide_regs[0x1d] = val; + pipc_ide_handlers(dev); + break; - case 0x20: - dev->ide_regs[0x20] = (val & 0xf0) | 1; - pipc_bus_master_handlers(dev); - break; - case 0x21: - dev->ide_regs[0x21] = val; - pipc_bus_master_handlers(dev); - break; + case 0x20: + dev->ide_regs[0x20] = (val & 0xf0) | 1; + pipc_bus_master_handlers(dev); + break; + case 0x21: + dev->ide_regs[0x21] = val; + pipc_bus_master_handlers(dev); + break; - case 0x3d: - dev->ide_regs[0x3d] = val & 0x01; - pipc_ide_irqs(dev); - break; + case 0x3d: + dev->ide_regs[0x3d] = val & 0x01; + pipc_ide_irqs(dev); + break; - case 0x40: - if (dev->local <= VIA_PIPC_586B) - dev->ide_regs[0x40] = (val & 0x03) | 0x04; - else - dev->ide_regs[0x40] = val & 0x0f; - pipc_ide_handlers(dev); - break; + case 0x40: + if (dev->local <= VIA_PIPC_586B) + dev->ide_regs[0x40] = (val & 0x03) | 0x04; + else + dev->ide_regs[0x40] = val & 0x0f; + pipc_ide_handlers(dev); + break; - case 0x41: - if (dev->local <= VIA_PIPC_686A) - dev->ide_regs[0x41] = val; - else if (dev->local == VIA_PIPC_8231) - dev->ide_regs[0x41] = val & 0xf6; - else - dev->ide_regs[0x41] = val & 0xf2; - break; + case 0x41: + if (dev->local <= VIA_PIPC_686A) + dev->ide_regs[0x41] = val; + else if (dev->local == VIA_PIPC_8231) + dev->ide_regs[0x41] = val & 0xf6; + else + dev->ide_regs[0x41] = val & 0xf2; + break; - case 0x43: - if (dev->local <= VIA_PIPC_586A) - dev->ide_regs[0x43] = (val & 0x6f) | 0x10; - else if (dev->local <= VIA_PIPC_586B) - dev->ide_regs[0x43] = (val & 0xef) | 0x10; - else - dev->ide_regs[0x43] = val & 0x0f; - break; + case 0x43: + if (dev->local <= VIA_PIPC_586A) + dev->ide_regs[0x43] = (val & 0x6f) | 0x10; + else if (dev->local <= VIA_PIPC_586B) + dev->ide_regs[0x43] = (val & 0xef) | 0x10; + else + dev->ide_regs[0x43] = val & 0x0f; + break; - case 0x44: - if (dev->local <= VIA_PIPC_586A) - dev->ide_regs[0x44] = val & 0x78; - else if (dev->local <= VIA_PIPC_586B) - dev->ide_regs[0x44] = val & 0x7b; - else if (dev->local <= VIA_PIPC_596B) - dev->ide_regs[0x44] = val & 0x7f; - else if ((dev->local <= VIA_PIPC_686A) || (dev->local == VIA_PIPC_8231)) - dev->ide_regs[0x44] = val & 0x69; - else - dev->ide_regs[0x44] = val & 0x7d; - break; + case 0x44: + if (dev->local <= VIA_PIPC_586A) + dev->ide_regs[0x44] = val & 0x78; + else if (dev->local <= VIA_PIPC_586B) + dev->ide_regs[0x44] = val & 0x7b; + else if (dev->local <= VIA_PIPC_596B) + dev->ide_regs[0x44] = val & 0x7f; + else if ((dev->local <= VIA_PIPC_686A) || (dev->local == VIA_PIPC_8231)) + dev->ide_regs[0x44] = val & 0x69; + else + dev->ide_regs[0x44] = val & 0x7d; + break; - case 0x45: - if (dev->local <= VIA_PIPC_586B) - dev->ide_regs[0x45] = val & 0x40; - else if ((dev->local <= VIA_PIPC_596B) || (dev->local == VIA_PIPC_8231)) - dev->ide_regs[0x45] = val & 0x4f; - else if (dev->local <= VIA_PIPC_686A) - dev->ide_regs[0x45] = val & 0x5f; - else - dev->ide_regs[0x45] = (val & 0x5c) | 0x20; - break; + case 0x45: + if (dev->local <= VIA_PIPC_586B) + dev->ide_regs[0x45] = val & 0x40; + else if ((dev->local <= VIA_PIPC_596B) || (dev->local == VIA_PIPC_8231)) + dev->ide_regs[0x45] = val & 0x4f; + else if (dev->local <= VIA_PIPC_686A) + dev->ide_regs[0x45] = val & 0x5f; + else + dev->ide_regs[0x45] = (val & 0x5c) | 0x20; + break; - case 0x46: - if ((dev->local <= VIA_PIPC_686A) || (dev->local == VIA_PIPC_8231)) - dev->ide_regs[0x46] = val & 0xf3; - else - dev->ide_regs[0x46] = val & 0xc0; - break; + case 0x46: + if ((dev->local <= VIA_PIPC_686A) || (dev->local == VIA_PIPC_8231)) + dev->ide_regs[0x46] = val & 0xf3; + else + dev->ide_regs[0x46] = val & 0xc0; + break; - case 0x50: case 0x51: case 0x52: case 0x53: - if (dev->local <= VIA_PIPC_586B) - dev->ide_regs[addr] = val & 0xc3; - else if (dev->local <= VIA_PIPC_596B) - dev->ide_regs[addr] = val & ((addr & 1) ? 0xc3 : 0xcb); - else if ((dev->local <= VIA_PIPC_686A) || (dev->local == VIA_PIPC_8231)) - dev->ide_regs[addr] = val & ((addr & 1) ? 0xc7 : 0xcf); - else - dev->ide_regs[addr] = val & 0xd7; - break; + case 0x50: + case 0x51: + case 0x52: + case 0x53: + if (dev->local <= VIA_PIPC_586B) + dev->ide_regs[addr] = val & 0xc3; + else if (dev->local <= VIA_PIPC_596B) + dev->ide_regs[addr] = val & ((addr & 1) ? 0xc3 : 0xcb); + else if ((dev->local <= VIA_PIPC_686A) || (dev->local == VIA_PIPC_8231)) + dev->ide_regs[addr] = val & ((addr & 1) ? 0xc7 : 0xcf); + else + dev->ide_regs[addr] = val & 0xd7; + break; - case 0x61: case 0x69: - dev->ide_regs[addr] = val & 0x0f; - break; + case 0x61: + case 0x69: + dev->ide_regs[addr] = val & 0x0f; + break; - default: - dev->ide_regs[addr] = val; - break; - } + default: + dev->ide_regs[addr] = val; + break; + } } else if (func < pm_func) { /* USB */ - /* Read-only addresses. */ - if ((addr < 4) || (addr == 5) || (addr == 6) || ((addr >= 8) && (addr < 0xd)) || - ((addr >= 0xe) && (addr < 0x20)) || ((addr >= 0x22) && (addr < 0x3c)) || - ((addr >= 0x3e) && (addr < 0x40)) || ((addr >= 0x42) && (addr < 0x44)) || - ((addr >= 0x46) && (addr < 0x84)) || ((addr >= 0x85) && (addr < 0xc0)) || (addr >= 0xc2)) - return; + /* Read-only addresses. */ + if ((addr < 4) || (addr == 5) || (addr == 6) || ((addr >= 8) && (addr < 0xd)) || ((addr >= 0xe) && (addr < 0x20)) || ((addr >= 0x22) && (addr < 0x3c)) || ((addr >= 0x3e) && (addr < 0x40)) || ((addr >= 0x42) && (addr < 0x44)) || ((addr >= 0x46) && (addr < 0x84)) || ((addr >= 0x85) && (addr < 0xc0)) || (addr >= 0xc2)) + return; - if ((dev->local <= VIA_PIPC_596B) && (addr == 0x84)) - return; + if ((dev->local <= VIA_PIPC_596B) && (addr == 0x84)) + return; - /* Check disable bits for both controllers. */ - if ((func == 2) ? (dev->pci_isa_regs[0x48] & 0x04) : (dev->pci_isa_regs[0x85] & 0x10)) - return; + /* Check disable bits for both controllers. */ + if ((func == 2) ? (dev->pci_isa_regs[0x48] & 0x04) : (dev->pci_isa_regs[0x85] & 0x10)) + return; - switch (addr) { - case 0x04: - dev->usb_regs[func - 2][0x04] = val & 0x97; - usb_update_io_mapping(dev, func); - break; - case 0x07: - dev->usb_regs[func - 2][0x07] &= ~(val & 0x78); - break; + switch (addr) { + case 0x04: + dev->usb_regs[func - 2][0x04] = val & 0x97; + usb_update_io_mapping(dev, func); + break; + case 0x07: + dev->usb_regs[func - 2][0x07] &= ~(val & 0x78); + break; - case 0x20: - dev->usb_regs[func - 2][0x20] = (val & ~0x1f) | 1; - usb_update_io_mapping(dev, func); - break; - case 0x21: - dev->usb_regs[func - 2][0x21] = val; - usb_update_io_mapping(dev, func); - break; + case 0x20: + dev->usb_regs[func - 2][0x20] = (val & ~0x1f) | 1; + usb_update_io_mapping(dev, func); + break; + case 0x21: + dev->usb_regs[func - 2][0x21] = val; + usb_update_io_mapping(dev, func); + break; - default: - dev->usb_regs[func - 2][addr] = val; - break; - } + default: + dev->usb_regs[func - 2][addr] = val; + break; + } } else if (func == pm_func) { /* Power */ - /* Read-only addresses */ - if ((addr < 0xd) || ((addr >= 0xe) && (addr < 0x40)) || (addr == 0x43) || (addr == 0x4a) || (addr == 0x4b) || - (addr == 0x4e) || (addr == 0x4f) || (addr == 0x56) || (addr == 0x57) || ((addr >= 0x5c) && (addr < 0x61)) || - ((addr >= 0x64) && (addr < 0x70)) || (addr == 0x72) || (addr == 0x73) || ((addr >= 0x75) && (addr < 0x80)) || - (addr == 0x83) || ((addr >= 0x85) && (addr < 0x90)) || ((addr >= 0x92) && (addr < 0xd2)) || (addr >= 0xd7)) - return; + /* Read-only addresses */ + if ((addr < 0xd) || ((addr >= 0xe) && (addr < 0x40)) || (addr == 0x43) || (addr == 0x4a) || (addr == 0x4b) || (addr == 0x4e) || (addr == 0x4f) || (addr == 0x56) || (addr == 0x57) || ((addr >= 0x5c) && (addr < 0x61)) || ((addr >= 0x64) && (addr < 0x70)) || (addr == 0x72) || (addr == 0x73) || ((addr >= 0x75) && (addr < 0x80)) || (addr == 0x83) || ((addr >= 0x85) && (addr < 0x90)) || ((addr >= 0x92) && (addr < 0xd2)) || (addr >= 0xd7)) + return; - if ((dev->local <= VIA_PIPC_586B) && ((addr == 0x48) || (addr == 0x4c) || (addr == 0x4d) || (addr >= 0x54))) - return; + if ((dev->local <= VIA_PIPC_586B) && ((addr == 0x48) || (addr == 0x4c) || (addr == 0x4d) || (addr >= 0x54))) + return; - if ((dev->local <= VIA_PIPC_596B) && ((addr >= 0x64) && (addr < (dev->local == VIA_PIPC_596A ? 0x80 : 0x85)))) - return; + if ((dev->local <= VIA_PIPC_596B) && ((addr >= 0x64) && (addr < (dev->local == VIA_PIPC_596A ? 0x80 : 0x85)))) + return; - switch (addr) { - case 0x41: case 0x48: case 0x49: - if (addr == 0x48) { - if (dev->local >= VIA_PIPC_596A) - val = (val & 0x80) | 0x01; - else - val = 0x01; - } + switch (addr) { + case 0x41: + case 0x48: + case 0x49: + if (addr == 0x48) { + if (dev->local >= VIA_PIPC_596A) + val = (val & 0x80) | 0x01; + else + val = 0x01; + } - dev->power_regs[addr] = val; - c = (dev->power_regs[0x49] << 8); - if (dev->local >= VIA_PIPC_596A) - c |= (dev->power_regs[0x48] & 0x80); - /* Workaround for P3V133 BIOS in 596B mode mapping ACPI to E800 (same as SMBus) instead of E400. */ - if ((dev->local == VIA_PIPC_596B) && (c == ((dev->power_regs[0x91] << 8) | (dev->power_regs[0x90] & 0xf0))) && (dev->power_regs[0xd2] & 0x01)) - c -= 0x400; - acpi_set_timer32(dev->acpi, dev->power_regs[0x41] & 0x08); - acpi_update_io_mapping(dev->acpi, c, dev->power_regs[0x41] & 0x80); - break; + dev->power_regs[addr] = val; + c = (dev->power_regs[0x49] << 8); + if (dev->local >= VIA_PIPC_596A) + c |= (dev->power_regs[0x48] & 0x80); + /* Workaround for P3V133 BIOS in 596B mode mapping ACPI to E800 (same as SMBus) instead of E400. */ + if ((dev->local == VIA_PIPC_596B) && (c == ((dev->power_regs[0x91] << 8) | (dev->power_regs[0x90] & 0xf0))) && (dev->power_regs[0xd2] & 0x01)) + c -= 0x400; + acpi_set_timer32(dev->acpi, dev->power_regs[0x41] & 0x08); + acpi_update_io_mapping(dev->acpi, c, dev->power_regs[0x41] & 0x80); + break; - case 0x42: - dev->power_regs[addr] = (dev->power_regs[addr] & 0xf0) | (val & 0x0f); - acpi_set_irq_line(dev->acpi, dev->power_regs[addr] & 0x0f); - break; + case 0x42: + dev->power_regs[addr] = (dev->power_regs[addr] & 0xf0) | (val & 0x0f); + acpi_set_irq_line(dev->acpi, dev->power_regs[addr] & 0x0f); + break; - case 0x54: - if (dev->local <= VIA_PIPC_596B) - dev->power_regs[addr] = val; /* write-only on 686A+ */ - else - smbus_piix4_setclock(dev->smbus, (val & 0x80) ? 65536 : 16384); /* final clock undocumented on 686A, assume RTC*2 like 686B */ - break; + case 0x54: + if (dev->local <= VIA_PIPC_596B) + dev->power_regs[addr] = val; /* write-only on 686A+ */ + else + smbus_piix4_setclock(dev->smbus, (val & 0x80) ? 65536 : 16384); /* final clock undocumented on 686A, assume RTC*2 like 686B */ + break; - case 0x61: case 0x62: case 0x63: - dev->power_regs[(addr - 0x58)] = val; - break; + case 0x61: + case 0x62: + case 0x63: + dev->power_regs[addr - 0x58] = val; + break; - case 0x70: case 0x71: case 0x74: - dev->power_regs[addr] = val; - /* Forward hardware monitor-related registers to hwm_vt82c686.c */ - if (dev->hwm) - vt82c686_hwm_write(addr, val, dev->hwm); - break; + case 0x70: + case 0x71: + case 0x74: + dev->power_regs[addr] = val; + /* Forward hardware monitor-related registers to hwm_vt82c686.c */ + if (dev->hwm) + vt82c686_hwm_write(addr, val, dev->hwm); + break; - case 0x80: case 0x81: case 0x84: /* 596A has the SMBus I/O base and enable bit here instead. */ - dev->power_regs[addr] = val; - smbus_piix4_remap(dev->smbus, (dev->power_regs[0x81] << 8) | (dev->power_regs[0x80] & 0xf0), dev->power_regs[0x84] & 0x01); - break; + case 0x80: + case 0x81: + case 0x84: /* 596A has the SMBus I/O base and enable bit here instead. */ + dev->power_regs[addr] = val; + smbus_piix4_remap(dev->smbus, (dev->power_regs[0x81] << 8) | (dev->power_regs[0x80] & 0xf0), dev->power_regs[0x84] & 0x01); + break; - case 0xd2: - if (dev->local == VIA_PIPC_686B) - smbus_piix4_setclock(dev->smbus, (val & 0x04) ? 65536 : 16384); - /* fall-through */ + case 0xd2: + if (dev->local == VIA_PIPC_686B) + smbus_piix4_setclock(dev->smbus, (val & 0x04) ? 65536 : 16384); + fallthrough; - case 0x90: case 0x91: - dev->power_regs[addr] = val; - smbus_piix4_remap(dev->smbus, (dev->power_regs[0x91] << 8) | (dev->power_regs[0x90] & 0xf0), dev->power_regs[0xd2] & 0x01); - break; + case 0x90: + case 0x91: + dev->power_regs[addr] = val; + smbus_piix4_remap(dev->smbus, (dev->power_regs[0x91] << 8) | (dev->power_regs[0x90] & 0xf0), dev->power_regs[0xd2] & 0x01); + break; - default: - dev->power_regs[addr] = val; - break; - } + default: + dev->power_regs[addr] = val; + break; + } } else if (func <= pm_func + 2) { /* AC97 / MC97 */ - /* Read-only addresses. */ - if ((addr < 0x4) || ((addr >= 0x6) && (addr < 0x9)) || ((addr >= 0xc) && (addr < 0x11)) || (addr == 0x16) || - (addr == 0x17) || (addr == 0x1a) || (addr == 0x1b) || ((addr >= 0x1e) && (addr < 0x2c)) || - ((addr >= 0x30) && (addr < 0x34)) || ((addr >= 0x35) && (addr < 0x3c)) || ((addr >= 0x3d) && (addr < 0x41)) || - ((addr >= 0x45) && (addr < 0x4a)) || (addr >= 0x4c)) - return; + /* Read-only addresses. */ + if ((addr < 0x4) || ((addr >= 0x6) && (addr < 0x9)) || ((addr >= 0xc) && (addr < 0x11)) || (addr == 0x16) || (addr == 0x17) || (addr == 0x1a) || (addr == 0x1b) || ((addr >= 0x1e) && (addr < 0x2c)) || ((addr >= 0x30) && (addr < 0x34)) || ((addr >= 0x35) && (addr < 0x3c)) || ((addr >= 0x3d) && (addr < 0x41)) || ((addr >= 0x45) && (addr < 0x4a)) || (addr >= 0x4c)) + return; - /* Small shortcut. */ - func = func - pm_func - 1; + /* Small shortcut. */ + func = func - pm_func - 1; - /* Check disable bits and specific read-only addresses for both controllers. */ - if ((func == 0) && (((addr >= 0x09) && (addr < 0xc)) || (addr == 0x44) || (dev->pci_isa_regs[0x85] & 0x04))) - return; + /* Check disable bits and specific read-only addresses for both controllers. */ + if ((func == 0) && (((addr >= 0x09) && (addr < 0xc)) || (addr == 0x44) || (dev->pci_isa_regs[0x85] & 0x04))) + return; - if ((func == 1) && ((addr == 0x14) || (addr == 0x15) || (addr == 0x18) || (addr == 0x19) || (addr == 0x42) || - (addr == 0x43) || (addr == 0x48) || (addr == 0x4a) || (addr == 0x4b) || (dev->pci_isa_regs[0x85] & 0x08))) - return; + if ((func == 1) && ((addr == 0x14) || (addr == 0x15) || (addr == 0x18) || (addr == 0x19) || (addr == 0x42) || (addr == 0x43) || (addr == 0x48) || (addr == 0x4a) || (addr == 0x4b) || (dev->pci_isa_regs[0x85] & 0x08))) + return; - switch (addr) { - case 0x04: - dev->ac97_regs[func][addr] = val; - pipc_sgd_handlers(dev, func); - pipc_codec_handlers(dev, func); - pipc_fmnmi_handlers(dev, func); - break; + switch (addr) { + case 0x04: + dev->ac97_regs[func][addr] = val; + pipc_sgd_handlers(dev, func); + pipc_codec_handlers(dev, func); + pipc_fmnmi_handlers(dev, func); + break; - case 0x09: case 0x0a: case 0x0b: - if (dev->ac97_regs[func][0x44] & 0x20) - dev->ac97_regs[func][addr] = val; - break; + case 0x09: + case 0x0a: + case 0x0b: + if (dev->ac97_regs[func][0x44] & 0x20) + dev->ac97_regs[func][addr] = val; + break; - case 0x10: case 0x11: - dev->ac97_regs[func][addr] = val; - pipc_sgd_handlers(dev, func); - break; + case 0x10: + case 0x11: + dev->ac97_regs[func][addr] = val; + pipc_sgd_handlers(dev, func); + break; - case 0x14: case 0x15: - if (addr == 0x14) - val = (val & 0xfc) | 1; - dev->ac97_regs[func][addr] = val; - pipc_fmnmi_handlers(dev, func); - break; + case 0x14: + case 0x15: + if (addr == 0x14) + val = (val & 0xfc) | 1; + dev->ac97_regs[func][addr] = val; + pipc_fmnmi_handlers(dev, func); + break; - case 0x18: case 0x19: - if (addr == 0x18) - val = (val & 0xfc) | 1; - dev->ac97_regs[func][addr] = val; - pipc_sb_handlers(dev, func); - break; + case 0x18: + case 0x19: + if (addr == 0x18) + val = (val & 0xfc) | 1; + dev->ac97_regs[func][addr] = val; + pipc_sb_handlers(dev, func); + break; - case 0x1c: case 0x1d: - dev->ac97_regs[func][addr] = val; - pipc_codec_handlers(dev, func); - break; + case 0x1c: + case 0x1d: + dev->ac97_regs[func][addr] = val; + pipc_codec_handlers(dev, func); + break; - case 0x2c: case 0x2d: case 0x2e: case 0x2f: - if ((func == 0) && (dev->ac97_regs[func][0x42] & 0x20)) - dev->ac97_regs[func][addr] = val; - break; + case 0x2c: + case 0x2d: + case 0x2e: + case 0x2f: + if ((func == 0) && (dev->ac97_regs[func][0x42] & 0x20)) + dev->ac97_regs[func][addr] = val; + break; - case 0x41: - dev->ac97_regs[func][addr] = val; - ac97_via_write_control(dev->ac97, func, val); - break; + case 0x41: + dev->ac97_regs[func][addr] = val; + ac97_via_write_control(dev->ac97, func, val); + break; - case 0x42: case 0x4a: case 0x4b: - dev->ac97_regs[0][addr] = dev->ac97_regs[1][addr] = val; - gameport_remap(dev->gameport, (dev->ac97_regs[0][0x42] & 0x08) ? ((dev->ac97_regs[0][0x4b] << 8) | (dev->ac97_regs[0][0x4a] & 0xf8)) : 0); - if (addr == 0x42) - pipc_sb_handlers(dev, func); - break; + case 0x42: + case 0x4a: + case 0x4b: + dev->ac97_regs[0][addr] = dev->ac97_regs[1][addr] = val; + gameport_remap(dev->gameport, (dev->ac97_regs[0][0x42] & 0x08) ? ((dev->ac97_regs[0][0x4b] << 8) | (dev->ac97_regs[0][0x4a] & 0xf8)) : 0); + if (addr == 0x42) + pipc_sb_handlers(dev, func); + break; - case 0x43: - dev->ac97_regs[0][addr] = dev->ac97_regs[1][addr] = val; - break; + case 0x43: + dev->ac97_regs[0][addr] = dev->ac97_regs[1][addr] = val; + break; - case 0x44: - dev->ac97_regs[0][addr] = dev->ac97_regs[1][addr] = val & 0xf0; - break; + case 0x44: + dev->ac97_regs[0][addr] = dev->ac97_regs[1][addr] = val & 0xf0; + break; - case 0x45: case 0x48: - dev->ac97_regs[0][addr] = dev->ac97_regs[1][addr] = val & 0x0f; - break; + case 0x45: + case 0x48: + dev->ac97_regs[0][addr] = dev->ac97_regs[1][addr] = val & 0x0f; + break; - default: - dev->ac97_regs[func][addr] = val; - break; - } + default: + dev->ac97_regs[func][addr] = val; + break; + } } } - static void -pipc_reset(void *p) +pipc_reset(void *priv) { - pipc_t *dev = (pipc_t *) p; + pipc_t *dev = (pipc_t *) priv; uint8_t pm_func = dev->usb[1] ? 4 : 3; - pipc_write(pm_func, 0x41, 0x00, p); - pipc_write(pm_func, 0x48, 0x01, p); - pipc_write(pm_func, 0x49, 0x00, p); + pipc_write(pm_func, 0x41, 0x00, priv); + pipc_write(pm_func, 0x48, 0x01, priv); + pipc_write(pm_func, 0x49, 0x00, priv); - pipc_write(1, 0x04, 0x80, p); - pipc_write(1, 0x09, 0x85, p); - pipc_write(1, 0x10, 0xf1, p); - pipc_write(1, 0x11, 0x01, p); - pipc_write(1, 0x14, 0xf5, p); - pipc_write(1, 0x15, 0x03, p); - pipc_write(1, 0x18, 0x71, p); - pipc_write(1, 0x19, 0x01, p); - pipc_write(1, 0x1c, 0x75, p); - pipc_write(1, 0x1d, 0x03, p); - pipc_write(1, 0x20, 0x01, p); - pipc_write(1, 0x21, 0xcc, p); + pipc_write(1, 0x04, 0x80, priv); + pipc_write(1, 0x09, 0x85, priv); + pipc_write(1, 0x10, 0xf1, priv); + pipc_write(1, 0x11, 0x01, priv); + pipc_write(1, 0x14, 0xf5, priv); + pipc_write(1, 0x15, 0x03, priv); + pipc_write(1, 0x18, 0x71, priv); + pipc_write(1, 0x19, 0x01, priv); + pipc_write(1, 0x1c, 0x75, priv); + pipc_write(1, 0x1d, 0x03, priv); + pipc_write(1, 0x20, 0x01, priv); + pipc_write(1, 0x21, 0xcc, priv); if (dev->local <= VIA_PIPC_586B) - pipc_write(1, 0x40, 0x04, p); + pipc_write(1, 0x40, 0x04, priv); else - pipc_write(1, 0x40, 0x00, p); + pipc_write(1, 0x40, 0x00, priv); - pipc_write(0, 0x77, 0x00, p); + if (dev->local < VIA_PIPC_586B) + pipc_write(0, 0x44, 0x00, priv); + + pipc_write(0, 0x77, 0x00, priv); + + sff_set_slot(dev->bm[0], dev->pci_slot); + sff_set_slot(dev->bm[1], dev->pci_slot); + + if (dev->local >= VIA_PIPC_686A) + ac97_via_set_slot(dev->ac97, dev->pci_slot, PCI_INTC); + if (dev->acpi) + acpi_set_slot(dev->acpi, dev->pci_slot); } - static void * pipc_init(const device_t *info) { @@ -1541,52 +1633,44 @@ pipc_init(const device_t *info) pipc_log("PIPC: init()\n"); dev->local = info->local; - dev->slot = pci_add_card(PCI_ADD_SOUTHBRIDGE, pipc_read, pipc_write, dev); + pci_add_card(PCI_ADD_SOUTHBRIDGE, pipc_read, pipc_write, dev, &dev->pci_slot); dev->bm[0] = device_add_inst(&sff8038i_device, 1); - sff_set_slot(dev->bm[0], dev->slot); - sff_set_irq_mode(dev->bm[0], 0, 0); - sff_set_irq_mode(dev->bm[0], 1, 0); + sff_set_irq_mode(dev->bm[0], IRQ_MODE_LEGACY); sff_set_irq_pin(dev->bm[0], PCI_INTA); dev->bm[1] = device_add_inst(&sff8038i_device, 2); - sff_set_slot(dev->bm[1], dev->slot); - sff_set_irq_mode(dev->bm[1], 0, 0); - sff_set_irq_mode(dev->bm[1], 1, 0); + sff_set_irq_mode(dev->bm[1], IRQ_MODE_LEGACY); sff_set_irq_pin(dev->bm[1], PCI_INTA); + if (dev->local == VIA_PIPC_686B) + dev->smbus = device_add(&via_smbus_device); + else if (dev->local >= VIA_PIPC_596A) + dev->smbus = device_add(&piix4_smbus_device); + dev->nvr = device_add(&via_nvr_device); - if (dev->local == VIA_PIPC_686B) - dev->smbus = device_add(&via_smbus_device); - else if (dev->local >= VIA_PIPC_596A) - dev->smbus = device_add(&piix4_smbus_device); - if (dev->local >= VIA_PIPC_596A) { - dev->acpi = device_add(&acpi_via_596b_device); - acpi_set_trap_update(dev->acpi, pipc_trap_update_596, dev); + dev->acpi = device_add(&acpi_via_596b_device); + acpi_set_trap_update(dev->acpi, pipc_trap_update_596, dev); } else if (dev->local >= VIA_PIPC_586B) { - dev->acpi = device_add(&acpi_via_device); - acpi_set_trap_update(dev->acpi, pipc_trap_update_586, dev); + dev->acpi = device_add(&acpi_via_device); + acpi_set_trap_update(dev->acpi, pipc_trap_update_586, dev); } dev->usb[0] = device_add_inst(&usb_device, 1); if (dev->local >= VIA_PIPC_686A) { - dev->usb[1] = device_add_inst(&usb_device, 2); + dev->usb[1] = device_add_inst(&usb_device, 2); - dev->ac97 = device_add(&ac97_via_device); - ac97_via_set_slot(dev->ac97, dev->slot, PCI_INTC); + dev->ac97 = device_add(&ac97_via_device); - dev->sb = device_add(&sb_pro_compat_device); -#ifndef VIA_PIPC_FM_EMULATION - dev->sb->opl_enabled = 1; -#endif - sound_add_handler(sb_get_buffer_sbpro, dev->sb); + dev->sb = device_add_inst(&sb_pro_compat_device, 2); + sound_add_handler(pipc_sb_get_buffer, dev); - dev->gameport = gameport_add(&gameport_sio_device); + dev->gameport = gameport_add(&gameport_sio_device); - dev->sio = device_add(&via_vt82c686_sio_device); - dev->hwm = device_add(&via_vt82c686_hwm_device); + dev->sio = device_add(&via_vt82c686_sio_device); + dev->hwm = device_add(&via_vt82c686_hwm_device); } pipc_reset_hard(dev); @@ -1598,130 +1682,117 @@ pipc_init(const device_t *info) dma_alias_set(); if (dev->local <= VIA_PIPC_586B) { - pci_enable_mirq(0); - pci_enable_mirq(1); - if (dev->local == VIA_PIPC_586B) - pci_enable_mirq(2); + pci_enable_mirq(0); + pci_enable_mirq(1); + if (dev->local == VIA_PIPC_586B) + pci_enable_mirq(2); } if (dev->local < VIA_PIPC_8231) - dev->ddma = device_add(&ddma_device); + dev->ddma = device_add(&ddma_device); if (dev->acpi) { - acpi_set_slot(dev->acpi, dev->slot); - acpi_set_nvr(dev->acpi, dev->nvr); + acpi_set_nvr(dev->acpi, dev->nvr); - acpi_init_gporeg(dev->acpi, 0xff, 0xbf, 0xff, 0x7f); + acpi_init_gporeg(dev->acpi, 0xff, 0xbf, 0xff, 0x7f); } return dev; } - static void -pipc_close(void *p) +pipc_close(void *priv) { - pipc_t *dev = (pipc_t *) p; + pipc_t *dev = (pipc_t *) priv; pipc_log("PIPC: close()\n"); - for (int i = 0; i < TRAP_MAX; i++) - io_trap_remove(dev->io_traps[i].trap); + for (uint8_t i = 0; i < TRAP_MAX; i++) + io_trap_remove(dev->io_traps[i].trap); free(dev); } - -const device_t via_vt82c586b_device = -{ - "VIA VT82C586B", - "via_vt82c586b", - DEVICE_PCI, - VIA_PIPC_586B, - pipc_init, - pipc_close, - pipc_reset, - { NULL }, - NULL, - NULL, - NULL +const device_t via_vt82c586b_device = { + .name = "VIA VT82C586B", + .internal_name = "via_vt82c586b", + .flags = DEVICE_PCI, + .local = VIA_PIPC_586B, + .init = pipc_init, + .close = pipc_close, + .reset = pipc_reset, + { .available = NULL }, + .speed_changed = NULL, + .force_redraw = NULL, + .config = NULL }; -const device_t via_vt82c596a_device = -{ - "VIA VT82C596A", - "via_vt82c596a", - DEVICE_PCI, - VIA_PIPC_596A, - pipc_init, - pipc_close, - pipc_reset, - { NULL }, - NULL, - NULL, - NULL +const device_t via_vt82c596a_device = { + .name = "VIA VT82C596A", + .internal_name = "via_vt82c596a", + .flags = DEVICE_PCI, + .local = VIA_PIPC_596A, + .init = pipc_init, + .close = pipc_close, + .reset = pipc_reset, + { .available = NULL }, + .speed_changed = NULL, + .force_redraw = NULL, + .config = NULL }; - -const device_t via_vt82c596b_device = -{ - "VIA VT82C596B", - "via_vt82c596b", - DEVICE_PCI, - VIA_PIPC_596B, - pipc_init, - pipc_close, - pipc_reset, - { NULL }, - NULL, - NULL, - NULL +const device_t via_vt82c596b_device = { + .name = "VIA VT82C596B", + .internal_name = "via_vt82c596b", + .flags = DEVICE_PCI, + .local = VIA_PIPC_596B, + .init = pipc_init, + .close = pipc_close, + .reset = pipc_reset, + { .available = NULL }, + .speed_changed = NULL, + .force_redraw = NULL, + .config = NULL }; - -const device_t via_vt82c686a_device = -{ - "VIA VT82C686A", - "via_vt82c686a", - DEVICE_PCI, - VIA_PIPC_686A, - pipc_init, - pipc_close, - pipc_reset, - { NULL }, - NULL, - NULL, - NULL +const device_t via_vt82c686a_device = { + .name = "VIA VT82C686A", + .internal_name = "via_vt82c686a", + .flags = DEVICE_PCI, + .local = VIA_PIPC_686A, + .init = pipc_init, + .close = pipc_close, + .reset = pipc_reset, + { .available = NULL }, + .speed_changed = NULL, + .force_redraw = NULL, + .config = NULL }; - -const device_t via_vt82c686b_device = -{ - "VIA VT82C686B", - "via_vt82c686b", - DEVICE_PCI, - VIA_PIPC_686B, - pipc_init, - pipc_close, - pipc_reset, - { NULL }, - NULL, - NULL, - NULL +const device_t via_vt82c686b_device = { + .name = "VIA VT82C686B", + .internal_name = "via_vt82c686b", + .flags = DEVICE_PCI, + .local = VIA_PIPC_686B, + .init = pipc_init, + .close = pipc_close, + .reset = pipc_reset, + { .available = NULL }, + .speed_changed = NULL, + .force_redraw = NULL, + .config = NULL }; - -const device_t via_vt8231_device = -{ - "VIA VT8231", - "via_vt8231", - DEVICE_PCI, - VIA_PIPC_8231, - pipc_init, - pipc_close, - pipc_reset, - { NULL }, - NULL, - NULL, - NULL +const device_t via_vt8231_device = { + .name = "VIA VT8231", + .internal_name = "via_vt8231", + .flags = DEVICE_PCI, + .local = VIA_PIPC_8231, + .init = pipc_init, + .close = pipc_close, + .reset = pipc_reset, + { .available = NULL }, + .speed_changed = NULL, + .force_redraw = NULL, + .config = NULL }; diff --git a/src/chipset/via_vt82c49x.c b/src/chipset/via_vt82c49x.c index bed86068b..de55f7060 100644 --- a/src/chipset/via_vt82c49x.c +++ b/src/chipset/via_vt82c49x.c @@ -1,20 +1,20 @@ /* - * 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. + * 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. + * This file is part of the 86Box distribution. * - * Implementation of the VIA VT82C49X chipset. + * Implementation of the VIA VT82C49X chipset. * * * - * Authors: Tiseno100, - * Miran Grca, + * Authors: Tiseno100, + * Miran Grca, * - * Copyright 2020 Tiseno100. - * Copyright 2020 Miran Grca. + * Copyright 2020 Tiseno100. + * Copyright 2020 Miran Grca. */ #include #include @@ -30,147 +30,151 @@ #include <86box/mem.h> #include <86box/smram.h> #include <86box/pic.h> +#include <86box/timer.h> #include <86box/hdc.h> #include <86box/hdc_ide.h> #include <86box/port_92.h> #include <86box/chipset.h> -typedef struct -{ - uint8_t has_ide, index, - regs[256]; +typedef struct vt82c49x_t { + uint8_t has_ide; + uint8_t index; + uint8_t regs[256]; - smram_t *smram_smm, *smram_low, - *smram_high; + smram_t *smram_smm; + smram_t *smram_low; + smram_t *smram_high; } vt82c49x_t; - #ifdef ENABLE_VT82C49X_LOG int vt82c49x_do_log = ENABLE_VT82C49X_LOG; + static void vt82c49x_log(const char *fmt, ...) { va_list ap; if (vt82c49x_do_log) { - va_start(ap, fmt); - pclog_ex(fmt, ap); - va_end(ap); + va_start(ap, fmt); + pclog_ex(fmt, ap); + va_end(ap); } } #else -#define vt82c49x_log(fmt, ...) +# define vt82c49x_log(fmt, ...) #endif - static void vt82c49x_recalc(vt82c49x_t *dev) { - int i, relocate; - uint8_t reg, bit; - uint32_t base, state; + int relocate; + uint8_t reg; + uint8_t bit; + uint32_t base; + uint32_t state; uint32_t shadow_bitmap = 0x00000000; relocate = (dev->regs[0x33] >> 2) & 0x03; - shadowbios = 0; + shadowbios = 0; shadowbios_write = 0; - for (i = 0; i < 8; i++) { - base = 0xc0000 + (i << 14); - reg = 0x30 + (i >> 2); - bit = (i & 3) << 1; + for (uint8_t i = 0; i < 8; i++) { + base = 0xc0000 + (i << 14); + reg = 0x30 + (i >> 2); + bit = (i & 3) << 1; - if ((base >= 0xc0000) && (base <= 0xc7fff)) { - if (dev->regs[0x40] & 0x80) - state = MEM_WRITE_DISABLED; - else if ((dev->regs[reg]) & (1 << bit)) - state = MEM_WRITE_INTERNAL; - else - state = (dev->regs[0x33] & 0x40) ? MEM_WRITE_ROMCS : MEM_WRITE_EXTERNAL; + if ((base >= 0xc0000) && (base <= 0xc7fff)) { + if (dev->regs[0x40] & 0x80) + state = MEM_WRITE_DISABLED; + else if ((dev->regs[reg]) & (1 << bit)) + state = MEM_WRITE_INTERNAL; + else + state = (dev->regs[0x33] & 0x40) ? MEM_WRITE_ROMCS : MEM_WRITE_EXTERNAL; - if ((dev->regs[reg]) & (1 << (bit + 1))) - state |= MEM_READ_INTERNAL; - else - state |= (dev->regs[0x33] & 0x40) ? MEM_READ_ROMCS : MEM_READ_EXTERNAL; - } if ((base >= 0xc8000) && (base <= 0xcffff)) { - if ((dev->regs[reg]) & (1 << bit)) - state = MEM_WRITE_INTERNAL; - else - state = (dev->regs[0x33] & 0x80) ? MEM_WRITE_ROMCS : MEM_WRITE_EXTERNAL; + if ((dev->regs[reg]) & (1 << (bit + 1))) + state |= MEM_READ_INTERNAL; + else + state |= (dev->regs[0x33] & 0x40) ? MEM_READ_ROMCS : MEM_READ_EXTERNAL; + } + if ((base >= 0xc8000) && (base <= 0xcffff)) { + if ((dev->regs[reg]) & (1 << bit)) + state = MEM_WRITE_INTERNAL; + else + state = (dev->regs[0x33] & 0x80) ? MEM_WRITE_ROMCS : MEM_WRITE_EXTERNAL; - if ((dev->regs[reg]) & (1 << (bit + 1))) - state |= MEM_READ_INTERNAL; - else - state |= (dev->regs[0x33] & 0x80) ? MEM_READ_ROMCS : MEM_READ_EXTERNAL; - } else { - state = ((dev->regs[reg]) & (1 << bit)) ? MEM_WRITE_INTERNAL : MEM_WRITE_EXTANY; - state |= ((dev->regs[reg]) & (1 << (bit + 1))) ? MEM_READ_INTERNAL : MEM_READ_EXTANY; - } + if ((dev->regs[reg]) & (1 << (bit + 1))) + state |= MEM_READ_INTERNAL; + else + state |= (dev->regs[0x33] & 0x80) ? MEM_READ_ROMCS : MEM_READ_EXTERNAL; + } else { + state = ((dev->regs[reg]) & (1 << bit)) ? MEM_WRITE_INTERNAL : MEM_WRITE_EXTANY; + state |= ((dev->regs[reg]) & (1 << (bit + 1))) ? MEM_READ_INTERNAL : MEM_READ_EXTANY; + } - vt82c49x_log("(%02X=%02X, %i) Setting %08X-%08X to: write %sabled, read %sabled\n", - reg, dev->regs[reg], bit, base, base + 0x3fff, - ((dev->regs[reg]) & (1 << bit)) ? "en" : "dis", ((dev->regs[reg]) & (1 << (bit + 1))) ? "en" : "dis"); + vt82c49x_log("(%02X=%02X, %i) Setting %08X-%08X to: write %sabled, read %sabled\n", + reg, dev->regs[reg], bit, base, base + 0x3fff, + ((dev->regs[reg]) & (1 << bit)) ? "en" : "dis", ((dev->regs[reg]) & (1 << (bit + 1))) ? "en" : "dis"); - if ((dev->regs[reg]) & (1 << bit)) - shadow_bitmap |= (1 << i); - if ((dev->regs[reg]) & (1 << (bit + 1))) - shadow_bitmap |= (1 << (i + 16)); + if ((dev->regs[reg]) & (1 << bit)) + shadow_bitmap |= (1 << i); + if ((dev->regs[reg]) & (1 << (bit + 1))) + shadow_bitmap |= (1 << (i + 16)); - mem_set_mem_state_both(base, 0x4000, state); + mem_set_mem_state_both(base, 0x4000, state); } - for (i = 0; i < 4; i++) { - base = 0xe0000 + (i << 15); - bit = 6 - (i & 2); + for (uint8_t i = 0; i < 4; i++) { + base = 0xe0000 + (i << 15); + bit = 6 - (i & 2); - if ((base >= 0xe0000) && (base <= 0xe7fff)) { - if (dev->regs[0x40] & 0x20) - state = MEM_WRITE_DISABLED; - else if ((dev->regs[0x32]) & (1 << bit)) - state = MEM_WRITE_INTERNAL; - else - state = (dev->regs[0x33] & 0x10) ? MEM_WRITE_ROMCS : MEM_WRITE_EXTERNAL; + if ((base >= 0xe0000) && (base <= 0xe7fff)) { + if (dev->regs[0x40] & 0x20) + state = MEM_WRITE_DISABLED; + else if ((dev->regs[0x32]) & (1 << bit)) + state = MEM_WRITE_INTERNAL; + else + state = (dev->regs[0x33] & 0x10) ? MEM_WRITE_ROMCS : MEM_WRITE_EXTERNAL; - if ((dev->regs[0x32]) & (1 << (bit + 1))) - state |= MEM_READ_INTERNAL; - else - state |= (dev->regs[0x33] & 0x10) ? MEM_READ_ROMCS : MEM_READ_EXTERNAL; - } else if ((base >= 0xe8000) && (base <= 0xeffff)) { - if (dev->regs[0x40] & 0x20) - state = MEM_WRITE_DISABLED; - else if ((dev->regs[0x32]) & (1 << bit)) - state = MEM_WRITE_INTERNAL; - else - state = (dev->regs[0x33] & 0x20) ? MEM_WRITE_ROMCS : MEM_WRITE_EXTERNAL; + if ((dev->regs[0x32]) & (1 << (bit + 1))) + state |= MEM_READ_INTERNAL; + else + state |= (dev->regs[0x33] & 0x10) ? MEM_READ_ROMCS : MEM_READ_EXTERNAL; + } else if ((base >= 0xe8000) && (base <= 0xeffff)) { + if (dev->regs[0x40] & 0x20) + state = MEM_WRITE_DISABLED; + else if ((dev->regs[0x32]) & (1 << bit)) + state = MEM_WRITE_INTERNAL; + else + state = (dev->regs[0x33] & 0x20) ? MEM_WRITE_ROMCS : MEM_WRITE_EXTERNAL; - if ((dev->regs[0x32]) & (1 << (bit + 1))) - state |= MEM_READ_INTERNAL; - else - state |= (dev->regs[0x33] & 0x20) ? MEM_READ_ROMCS : MEM_READ_EXTERNAL; - } else { - if (dev->regs[0x40] & 0x40) - state = MEM_WRITE_DISABLED; - else if ((dev->regs[0x32]) & (1 << bit)) - state = ((dev->regs[0x32]) & (1 << bit)) ? MEM_WRITE_INTERNAL : MEM_WRITE_EXTANY; + if ((dev->regs[0x32]) & (1 << (bit + 1))) + state |= MEM_READ_INTERNAL; + else + state |= (dev->regs[0x33] & 0x20) ? MEM_READ_ROMCS : MEM_READ_EXTERNAL; + } else { + if (dev->regs[0x40] & 0x40) + state = MEM_WRITE_DISABLED; + else if ((dev->regs[0x32]) & (1 << bit)) + state = ((dev->regs[0x32]) & (1 << bit)) ? MEM_WRITE_INTERNAL : MEM_WRITE_EXTANY; - state |= ((dev->regs[0x32]) & (1 << (bit + 1))) ? MEM_READ_INTERNAL : MEM_READ_EXTANY; - } + state |= ((dev->regs[0x32]) & (1 << (bit + 1))) ? MEM_READ_INTERNAL : MEM_READ_EXTANY; + } - vt82c49x_log("(32=%02X, %i) Setting %08X-%08X to: write %sabled, read %sabled\n", - dev->regs[0x32], bit, base, base + 0x7fff, - ((dev->regs[0x32]) & (1 << bit)) ? "en" : "dis", ((dev->regs[0x32]) & (1 << (bit + 1))) ? "en" : "dis"); + vt82c49x_log("(32=%02X, %i) Setting %08X-%08X to: write %sabled, read %sabled\n", + dev->regs[0x32], bit, base, base + 0x7fff, + ((dev->regs[0x32]) & (1 << bit)) ? "en" : "dis", ((dev->regs[0x32]) & (1 << (bit + 1))) ? "en" : "dis"); - if ((dev->regs[0x32]) & (1 << bit)) { - shadow_bitmap |= (0xf << ((i << 2) + 8)); - shadowbios_write |= 1; - } - if ((dev->regs[0x32]) & (1 << (bit + 1))) { - shadow_bitmap |= (0xf << ((i << 2) + 24)); - shadowbios |= 1; - } + if ((dev->regs[0x32]) & (1 << bit)) { + shadow_bitmap |= (0xf << ((i << 2) + 8)); + shadowbios_write |= 1; + } + if ((dev->regs[0x32]) & (1 << (bit + 1))) { + shadow_bitmap |= (0xf << ((i << 2) + 24)); + shadowbios |= 1; + } - mem_set_mem_state_both(base, 0x8000, state); + mem_set_mem_state_both(base, 0x8000, state); } vt82c49x_log("Shadow bitmap: %08X\n", shadow_bitmap); @@ -178,145 +182,151 @@ vt82c49x_recalc(vt82c49x_t *dev) mem_remap_top(0); switch (relocate) { - case 0x02: - if (!(shadow_bitmap & 0xfff0fff0)) - mem_remap_top(256); - break; - case 0x03: - if (!shadow_bitmap) - mem_remap_top(384); - break; + case 0x02: + if (!(shadow_bitmap & 0xfff0fff0)) + mem_remap_top(256); + break; + case 0x03: + if (!shadow_bitmap) + mem_remap_top(384); + break; + default: + break; } } - static void vt82c49x_write(uint16_t addr, uint8_t val, void *priv) { vt82c49x_t *dev = (vt82c49x_t *) priv; - uint8_t valxor; + uint8_t valxor; switch (addr) { - case 0xa8: - dev->index = val; - break; + case 0xa8: + dev->index = val; + break; - case 0xa9: - valxor = (val ^ dev->regs[dev->index]); - if (dev->index == 0x55) - dev->regs[dev->index] &= ~val; - else - dev->regs[dev->index] = val; + case 0xa9: + valxor = (val ^ dev->regs[dev->index]); + if (dev->index == 0x55) + dev->regs[dev->index] &= ~val; + else + dev->regs[dev->index] = val; - vt82c49x_log("dev->regs[0x%02x] = %02x\n", dev->index, val); + vt82c49x_log("dev->regs[0x%02x] = %02x\n", dev->index, val); - switch(dev->index) { - /* Wait States */ - case 0x03: - cpu_update_waitstates(); - break; + switch (dev->index) { + /* Wait States */ + case 0x03: + cpu_update_waitstates(); + break; - /* Shadow RAM and top of RAM relocation */ - case 0x30: - case 0x31: - case 0x32: - case 0x33: - case 0x40: - vt82c49x_recalc(dev); - break; + /* Shadow RAM and top of RAM relocation */ + case 0x30: + case 0x31: + case 0x32: + case 0x33: + case 0x40: + vt82c49x_recalc(dev); + break; - /* External Cache Enable(Based on the 486-VC-HD BIOS) */ - case 0x50: - cpu_cache_ext_enabled = (val & 0x84); - break; + /* External Cache Enable(Based on the 486-VC-HD BIOS) */ + case 0x50: + cpu_cache_ext_enabled = (val & 0x84); + break; - /* Software SMI */ - case 0x54: - if ((dev->regs[0x5b] & 0x80) && (valxor & 0x01) && (val & 0x01)) { - if (dev->regs[0x5b] & 0x20) - smi_line = 1; - else - picint(1 << 15); - dev->regs[0x55] = 0x01; - } - break; + /* Software SMI */ + case 0x54: + if ((dev->regs[0x5b] & 0x80) && (valxor & 0x01) && (val & 0x01)) { + if (dev->regs[0x5b] & 0x20) + smi_raise(); + else + picint(1 << 15); + dev->regs[0x55] = 0x01; + } + break; - /* SMRAM */ - case 0x5b: - smram_disable_all(); + /* SMRAM */ + case 0x5b: + smram_disable_all(); - if (val & 0x80) { - smram_enable(dev->smram_smm, (val & 0x40) ? 0x00060000 : 0x00030000, 0x000a0000, 0x00020000, - 0, (val & 0x10)); - smram_enable(dev->smram_high, 0x000a0000, 0x000a0000, 0x00020000, - (val & 0x08), (val & 0x08)); - smram_enable(dev->smram_low, 0x00030000, 0x000a0000, 0x00020000, - (val & 0x02), 0); - } - break; + if (val & 0x80) { + smram_enable(dev->smram_smm, (val & 0x40) ? 0x00060000 : 0x00030000, 0x000a0000, 0x00020000, + 0, (val & 0x10)); + smram_enable(dev->smram_high, 0x000a0000, 0x000a0000, 0x00020000, + (val & 0x08), (val & 0x08)); + smram_enable(dev->smram_low, 0x00030000, 0x000a0000, 0x00020000, + (val & 0x02), 0); + } + break; - /* Edge/Level IRQ Control */ - case 0x62: case 0x63: - if (dev->index == 0x63) - pic_elcr_write(dev->index, val & 0xde, &pic2); - else { - pic_elcr_write(dev->index, val & 0xf8, &pic); - pic_elcr_set_enabled(val & 0x01); - } - break; + /* Edge/Level IRQ Control */ + case 0x62: + case 0x63: + if (dev->index == 0x63) + pic_elcr_write(dev->index, val & 0xde, &pic2); + else { + pic_elcr_write(dev->index, val & 0xf8, &pic); + pic_elcr_set_enabled(val & 0x01); + } + break; - /* Local Bus IDE Controller */ - case 0x71: - if (dev->has_ide) { - ide_pri_disable(); - ide_set_base(0, (val & 0x40) ? 0x170 : 0x1f0); - ide_set_side(0, (val & 0x40) ? 0x376 : 0x3f6); - if (val & 0x01) - ide_pri_enable(); - vt82c49x_log("VT82C496 IDE now %sabled as %sary\n", (val & 0x01) ? "en": "dis", - (val & 0x40) ? "second" : "prim"); - } - break; - } - break; + /* Local Bus IDE Controller */ + case 0x71: + if (dev->has_ide) { + ide_pri_disable(); + ide_set_base(0, (val & 0x40) ? 0x170 : 0x1f0); + ide_set_side(0, (val & 0x40) ? 0x376 : 0x3f6); + if (val & 0x01) + ide_pri_enable(); + vt82c49x_log("VT82C496 IDE now %sabled as %sary\n", (val & 0x01) ? "en" : "dis", + (val & 0x40) ? "second" : "prim"); + } + break; + + default: + break; + } + break; + + default: + break; } } - static uint8_t vt82c49x_read(uint16_t addr, void *priv) { - uint8_t ret = 0xff; - vt82c49x_t *dev = (vt82c49x_t *) priv; + uint8_t ret = 0xff; + const vt82c49x_t *dev = (vt82c49x_t *) priv; switch (addr) { - case 0xa9: - /* Register 64h is jumper readout. */ - if (dev->index == 0x64) - ret = 0xff; - else if (dev->index == 0x63) - ret = pic_elcr_read(dev->index, &pic2) | (dev->regs[dev->index] & 0x01); - else if (dev->index == 0x62) - ret = pic_elcr_read(dev->index, &pic) | (dev->regs[dev->index] & 0x07); - else if (dev->index < 0x80) - ret = dev->regs[dev->index]; - break; + case 0xa9: + /* Register 64h is jumper readout. */ + if (dev->index == 0x64) + ret = 0xff; + else if (dev->index == 0x63) + ret = pic_elcr_read(dev->index, &pic2) | (dev->regs[dev->index] & 0x01); + else if (dev->index == 0x62) + ret = pic_elcr_read(dev->index, &pic) | (dev->regs[dev->index] & 0x07); + else if (dev->index < 0x80) + ret = dev->regs[dev->index]; + break; + + default: + break; } return ret; } - static void vt82c49x_reset(void *priv) { - uint16_t i; - - for (i = 0; i < 256; i++) - vt82c49x_write(i, 0x00, priv); + for (uint16_t i = 0; i < 256; i++) + vt82c49x_write(i, 0x00, priv); } - static void vt82c49x_close(void *priv) { @@ -329,21 +339,20 @@ vt82c49x_close(void *priv) free(dev); } - static void * vt82c49x_init(const device_t *info) { vt82c49x_t *dev = (vt82c49x_t *) malloc(sizeof(vt82c49x_t)); memset(dev, 0x00, sizeof(vt82c49x_t)); - dev->smram_smm = smram_add(); - dev->smram_low = smram_add(); + dev->smram_smm = smram_add(); + dev->smram_low = smram_add(); dev->smram_high = smram_add(); dev->has_ide = info->local & 1; if (dev->has_ide) { - device_add(&ide_vlb_2ch_device); - ide_sec_disable(); + device_add(&ide_vlb_2ch_device); + ide_sec_disable(); } device_add(&port_92_device); @@ -354,50 +363,62 @@ vt82c49x_init(const device_t *info) pic_elcr_set_enabled(1); vt82c49x_recalc(dev); - + return dev; } - const device_t via_vt82c49x_device = { - "VIA VT82C49X", - "via_vt82c49x", - 0, - 0, - vt82c49x_init, vt82c49x_close, NULL, - { NULL }, NULL, NULL, - NULL + .name = "VIA VT82C49X", + .internal_name = "via_vt82c49x", + .flags = 0, + .local = 0, + .init = vt82c49x_init, + .close = vt82c49x_close, + .reset = NULL, + { .available = NULL }, + .speed_changed = NULL, + .force_redraw = NULL, + .config = NULL }; - const device_t via_vt82c49x_pci_device = { - "VIA VT82C49X PCI", - "via_vt82c49x_pci", - DEVICE_PCI, - 0, - vt82c49x_init, vt82c49x_close, vt82c49x_reset, - { NULL }, NULL, NULL, - NULL + .name = "VIA VT82C49X PCI", + .internal_name = "via_vt82c49x_pci", + .flags = DEVICE_PCI, + .local = 0, + .init = vt82c49x_init, + .close = vt82c49x_close, + .reset = vt82c49x_reset, + { .available = NULL }, + .speed_changed = NULL, + .force_redraw = NULL, + .config = NULL }; - const device_t via_vt82c49x_ide_device = { - "VIA VT82C49X (With IDE)", - "via_vt82c49x_ide", - 0, - 1, - vt82c49x_init, vt82c49x_close, NULL, - { NULL }, NULL, NULL, - NULL + .name = "VIA VT82C49X (With IDE)", + .internal_name = "via_vt82c49x_ide", + .flags = 0, + .local = 1, + .init = vt82c49x_init, + .close = vt82c49x_close, + .reset = NULL, + { .available = NULL }, + .speed_changed = NULL, + .force_redraw = NULL, + .config = NULL }; - const device_t via_vt82c49x_pci_ide_device = { - "VIA VT82C49X PCI (With IDE)", - "via_vt82c49x_pci_ide", - DEVICE_PCI, - 1, - vt82c49x_init, vt82c49x_close, vt82c49x_reset, - { NULL }, NULL, NULL, - NULL + .name = "VIA VT82C49X PCI (With IDE)", + .internal_name = "via_vt82c49x_pci_ide", + .flags = DEVICE_PCI, + .local = 1, + .init = vt82c49x_init, + .close = vt82c49x_close, + .reset = vt82c49x_reset, + { .available = NULL }, + .speed_changed = NULL, + .force_redraw = NULL, + .config = NULL }; diff --git a/src/chipset/via_vt82c505.c b/src/chipset/via_vt82c505.c index 6dea85d80..34efbead9 100644 --- a/src/chipset/via_vt82c505.c +++ b/src/chipset/via_vt82c505.c @@ -1,20 +1,20 @@ /* - * 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. + * 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. + * This file is part of the 86Box distribution. * - * Implementation of the VIA VT82C505 VL/PCI Bridge Controller. + * Implementation of the VIA VT82C505 VL/PCI Bridge Controller. * * * - * Authors: Tiseno100, - * Miran Grca, + * Authors: Tiseno100, + * Miran Grca, * - * Copyright 2020 Tiseno100. - * Copyright 2020 Miran Grca. + * Copyright 2020 Tiseno100. + * Copyright 2020 Miran Grca. */ #include #include @@ -26,164 +26,173 @@ #include <86box/io.h> #include <86box/pic.h> #include <86box/pci.h> +#include <86box/plat_unused.h> #include <86box/device.h> #include <86box/chipset.h> +typedef struct vt82c505_t { + uint8_t index; + uint8_t pci_slot; + uint8_t pad; + uint8_t pad0; -typedef struct vt82c505_t -{ - uint8_t index; - uint8_t pci_conf[256]; + uint8_t pci_conf[256]; } vt82c505_t; - static void vt82c505_write(int func, int addr, uint8_t val, void *priv) { - vt82c505_t *dev = (vt82c505_t *) priv; - uint8_t irq; + vt82c505_t *dev = (vt82c505_t *) priv; + uint8_t irq; const uint8_t irq_array[8] = { 0, 5, 9, 10, 11, 14, 15, 0 }; if (func != 0) - return; + return; - switch(addr) { - /* RX00-07h: Mandatory header field */ - case 0x04: - dev->pci_conf[addr] = (dev->pci_conf[addr] & 0xbf) | (val & 0x40); - break; - case 0x07: - dev->pci_conf[addr] &= ~(val & 0x90); - break; + switch (addr) { + /* RX00-07h: Mandatory header field */ + case 0x04: + dev->pci_conf[addr] = (dev->pci_conf[addr] & 0xbf) | (val & 0x40); + break; + case 0x07: + dev->pci_conf[addr] &= ~(val & 0x90); + break; - /* RX80-9F: VT82C505 internal configuration registers */ - case 0x80: - dev->pci_conf[addr] = (dev->pci_conf[addr] & 0x0f) | (val & 0xf0); - break; - case 0x81: case 0x84: case 0x85: case 0x87: - case 0x88: case 0x89: case 0x8a: case 0x8b: - case 0x8c: case 0x8d: case 0x8e: case 0x8f: - case 0x92: case 0x94: - dev->pci_conf[addr] = val; - break; - case 0x82: - dev->pci_conf[addr] = val & 0xdb; - break; - case 0x83: - dev->pci_conf[addr] = val & 0xf9; - break; - case 0x86: - dev->pci_conf[addr] = val & 0xef; - /* Bit 7 switches between the two PCI configuration mechanisms: - 0 = configuration mechanism 1, 1 = configuration mechanism 2 */ - pci_set_pmc(!(val & 0x80)); - break; - case 0x90: - dev->pci_conf[addr] = val; - irq = irq_array[val & 0x07]; - if ((val & 0x08) && (irq != 0)) - pci_set_irq_routing(PCI_INTC, irq); - else - pci_set_irq_routing(PCI_INTC, PCI_IRQ_DISABLED); + /* RX80-9F: VT82C505 internal configuration registers */ + case 0x80: + dev->pci_conf[addr] = (dev->pci_conf[addr] & 0x0f) | (val & 0xf0); + break; + case 0x81: + case 0x84: + case 0x85: + case 0x87: + case 0x88: + case 0x89: + case 0x8a: + case 0x8b: + case 0x8c: + case 0x8d: + case 0x8e: + case 0x8f: + case 0x92: + case 0x94: + dev->pci_conf[addr] = val; + break; + case 0x82: + dev->pci_conf[addr] = val & 0xdb; + break; + case 0x83: + dev->pci_conf[addr] = val & 0xf9; + break; + case 0x86: + dev->pci_conf[addr] = val & 0xef; + /* Bit 7 switches between the two PCI configuration mechanisms: + 0 = configuration mechanism 1, 1 = configuration mechanism 2 */ + pci_set_pmc(!(val & 0x80)); + break; + case 0x90: + dev->pci_conf[addr] = val; + irq = irq_array[val & 0x07]; + if ((val & 0x08) && (irq != 0)) + pci_set_irq_routing(PCI_INTC, irq); + else + pci_set_irq_routing(PCI_INTC, PCI_IRQ_DISABLED); - irq = irq_array[(val & 0x70) >> 4]; - if ((val & 0x80) && (irq != 0)) - pci_set_irq_routing(PCI_INTD, irq); - else - pci_set_irq_routing(PCI_INTD, PCI_IRQ_DISABLED); - break; - case 0x91: - dev->pci_conf[addr] = val; - irq = irq_array[val & 0x07]; - if ((val & 0x08) && (irq != 0)) - pci_set_irq_routing(PCI_INTA, irq); - else - pci_set_irq_routing(PCI_INTA, PCI_IRQ_DISABLED); + irq = irq_array[(val & 0x70) >> 4]; + if ((val & 0x80) && (irq != 0)) + pci_set_irq_routing(PCI_INTD, irq); + else + pci_set_irq_routing(PCI_INTD, PCI_IRQ_DISABLED); + break; + case 0x91: + dev->pci_conf[addr] = val; + irq = irq_array[val & 0x07]; + if ((val & 0x08) && (irq != 0)) + pci_set_irq_routing(PCI_INTA, irq); + else + pci_set_irq_routing(PCI_INTA, PCI_IRQ_DISABLED); - irq = irq_array[(val & 0x70) >> 4]; - if ((val & 0x80) && (irq != 0)) - pci_set_irq_routing(PCI_INTB, irq); - else - pci_set_irq_routing(PCI_INTB, PCI_IRQ_DISABLED); - break; - case 0x93: - dev->pci_conf[addr] = val & 0xe0; - break; + irq = irq_array[(val & 0x70) >> 4]; + if ((val & 0x80) && (irq != 0)) + pci_set_irq_routing(PCI_INTB, irq); + else + pci_set_irq_routing(PCI_INTB, PCI_IRQ_DISABLED); + break; + case 0x93: + dev->pci_conf[addr] = val & 0xe0; + break; + + default: + break; } } - static uint8_t vt82c505_read(int func, int addr, void *priv) { - vt82c505_t *dev = (vt82c505_t *) priv; - uint8_t ret = 0xff; + const vt82c505_t *dev = (vt82c505_t *) priv; + uint8_t ret = 0xff; if (func != 0) - return ret; + return ret; ret = dev->pci_conf[addr]; return ret; } - static void vt82c505_out(uint16_t addr, uint8_t val, void *priv) { vt82c505_t *dev = (vt82c505_t *) priv; if (addr == 0xa8) - dev->index = val; + dev->index = val; else if ((addr == 0xa9) && (dev->index >= 0x80) && (dev->index <= 0x9f)) - vt82c505_write(0, dev->index, val, priv); + vt82c505_write(0, dev->index, val, priv); } - static uint8_t vt82c505_in(uint16_t addr, void *priv) { - vt82c505_t *dev = (vt82c505_t *) priv; - uint8_t ret = 0xff; + const vt82c505_t *dev = (vt82c505_t *) priv; + uint8_t ret = 0xff; if ((addr == 0xa9) && (dev->index >= 0x80) && (dev->index <= 0x9f)) - ret = vt82c505_read(0, dev->index, priv); + ret = vt82c505_read(0, dev->index, priv); return ret; } - static void vt82c505_reset(void *priv) { vt82c505_t *dev = (vt82c505_t *) malloc(sizeof(vt82c505_t)); - int i; dev->pci_conf[0x04] = 0x07; dev->pci_conf[0x07] = 0x00; - for (i = 0x80; i <= 0x9f; i++) { - switch (i) { - case 0x81: - vt82c505_write(0, i, 0x01, priv); - break; - case 0x84: - vt82c505_write(0, i, 0x03, priv); - break; - case 0x93: - vt82c505_write(0, i, 0x40, priv); - break; - default: - vt82c505_write(0, i, 0x00, priv); - break; - } + for (uint8_t i = 0x80; i <= 0x9f; i++) { + switch (i) { + case 0x81: + vt82c505_write(0, i, 0x01, priv); + break; + case 0x84: + vt82c505_write(0, i, 0x03, priv); + break; + case 0x93: + vt82c505_write(0, i, 0x40, priv); + break; + default: + vt82c505_write(0, i, 0x00, priv); + break; + } } pic_reset(); pic_set_pci_flag(1); } - static void vt82c505_close(void *priv) { @@ -192,14 +201,13 @@ vt82c505_close(void *priv) free(dev); } - static void * -vt82c505_init(const device_t *info) +vt82c505_init(UNUSED(const device_t *info)) { vt82c505_t *dev = (vt82c505_t *) malloc(sizeof(vt82c505_t)); memset(dev, 0, sizeof(vt82c505_t)); - pci_add_card(PCI_ADD_NORTHBRIDGE, vt82c505_read, vt82c505_write, dev); + pci_add_card(PCI_ADD_NORTHBRIDGE, vt82c505_read, vt82c505_write, dev, &dev->pci_slot); dev->pci_conf[0x00] = 0x06; dev->pci_conf[0x01] = 0x11; @@ -216,17 +224,16 @@ vt82c505_init(const device_t *info) return dev; } - const device_t via_vt82c505_device = { - "VIA VT82C505", - "via_vt82c505", - DEVICE_PCI, - 0, - vt82c505_init, - vt82c505_close, - vt82c505_reset, - { NULL }, - NULL, - NULL, - NULL + .name = "VIA VT82C505", + .internal_name = "via_vt82c505", + .flags = DEVICE_PCI, + .local = 0, + .init = vt82c505_init, + .close = vt82c505_close, + .reset = vt82c505_reset, + { .available = NULL }, + .speed_changed = NULL, + .force_redraw = NULL, + .config = NULL }; diff --git a/src/chipset/vl82c480.c b/src/chipset/vl82c480.c index 7a0568a6c..00adcc2a4 100644 --- a/src/chipset/vl82c480.c +++ b/src/chipset/vl82c480.c @@ -1,16 +1,18 @@ /* - * 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. + * 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. + * This file is part of the 86Box distribution. * - * Implementation of the VLSI VL82c480 chipset. + * Implementation of the VLSI VL82c480 chipset. * - * Authors: Miran Grca, * - * Copyright 2020 Miran Grca. + * + * Authors: Miran Grca, + * + * Copyright 2020 Miran Grca. */ #include #include @@ -27,149 +29,158 @@ #include <86box/port_92.h> #include <86box/chipset.h> -typedef struct { - uint8_t idx, - regs[256]; +typedef struct vl82c480_t { + uint8_t idx; + uint8_t regs[256]; } vl82c480_t; - static int vl82c480_shflags(uint8_t access) { int ret = MEM_READ_EXTANY | MEM_WRITE_EXTANY; switch (access) { - case 0x00: - default: - ret = MEM_READ_EXTANY | MEM_WRITE_EXTANY; - break; - case 0x01: - ret = MEM_READ_EXTANY | MEM_WRITE_INTERNAL; - break; - case 0x02: - ret = MEM_READ_INTERNAL | MEM_WRITE_EXTANY; - break; - case 0x03: - ret = MEM_READ_INTERNAL | MEM_WRITE_INTERNAL; - break; + default: + case 0x00: + ret = MEM_READ_EXTANY | MEM_WRITE_EXTANY; + break; + case 0x01: + ret = MEM_READ_EXTANY | MEM_WRITE_INTERNAL; + break; + case 0x02: + ret = MEM_READ_INTERNAL | MEM_WRITE_EXTANY; + break; + case 0x03: + ret = MEM_READ_INTERNAL | MEM_WRITE_INTERNAL; + break; } return ret; } - -static void +static void vl82c480_recalc(vl82c480_t *dev) { - int i, j; uint32_t base; - uint8_t access; + uint8_t access; - shadowbios = 0; + shadowbios = 0; shadowbios_write = 0; - for (i = 0; i < 6; i++) { - for (j = 0; j < 8; j += 2) { - base = 0x000a0000 + (i << 16) + (j << 13); - access = (dev->regs[0x0d + i] >> j) & 3; - mem_set_mem_state(base, 0x4000, vl82c480_shflags(access)); - shadowbios |= ((base >= 0xe0000) && (access & 0x02)); - shadowbios_write |= ((base >= 0xe0000) && (access & 0x01)); - } + for (uint8_t i = 0; i < 6; i++) { + for (uint8_t j = 0; j < 8; j += 2) { + base = 0x000a0000 + (i << 16) + (j << 13); + access = (dev->regs[0x0d + i] >> j) & 3; + mem_set_mem_state(base, 0x4000, vl82c480_shflags(access)); + shadowbios |= ((base >= 0xe0000) && (access & 0x02)); + shadowbios_write |= ((base >= 0xe0000) && (access & 0x01)); + } } flushmmucache(); } - static void -vl82c480_write(uint16_t addr, uint8_t val, void *p) +vl82c480_write(uint16_t addr, uint8_t val, void *priv) { - vl82c480_t *dev = (vl82c480_t *)p; + vl82c480_t *dev = (vl82c480_t *) priv; switch (addr) { - case 0xec: - dev->idx = val; - break; + case 0xec: + dev->idx = val; + break; - case 0xed: - if (dev->idx >= 0x01 && dev->idx <= 0x24) { - switch (dev->idx) { - default: - dev->regs[dev->idx] = val; - break; - case 0x04: - if (dev->regs[0x00] == 0x98) - dev->regs[dev->idx] = (dev->regs[dev->idx] & 0x08) | (val & 0xf7); - else - dev->regs[dev->idx] = val; - break; - case 0x05: - dev->regs[dev->idx] = (dev->regs[dev->idx] & 0x10) | (val & 0xef); - break; - case 0x07: - dev->regs[dev->idx] = (dev->regs[dev->idx] & 0x40) | (val & 0xbf); - break; - case 0x0d: case 0x0e: case 0x0f: case 0x10: - case 0x11: case 0x12: - dev->regs[dev->idx] = val; - vl82c480_recalc(dev); - break; - } - } - break; + case 0xed: + if (dev->idx >= 0x01 && dev->idx <= 0x24) { + switch (dev->idx) { + default: + dev->regs[dev->idx] = val; + break; + case 0x04: + if (dev->regs[0x00] == 0x98) + dev->regs[dev->idx] = (dev->regs[dev->idx] & 0x08) | (val & 0xf7); + else + dev->regs[dev->idx] = val; + break; + case 0x05: + dev->regs[dev->idx] = (dev->regs[dev->idx] & 0x10) | (val & 0xef); + break; + case 0x07: + dev->regs[dev->idx] = (dev->regs[dev->idx] & 0x40) | (val & 0xbf); + break; + case 0x0d: + case 0x0e: + case 0x0f: + case 0x10: + case 0x11: + case 0x12: + dev->regs[dev->idx] = val; + vl82c480_recalc(dev); + break; + } + } + break; - case 0xee: - if (mem_a20_alt) - outb(0x92, inb(0x92) & ~2); - break; +/* TODO: This is actually Fast A20 disable. */ +#if 0 + case 0xee: + if (mem_a20_alt) + outb(0x92, inb(0x92) & ~2); + break; +#endif + + default: + break; } } - -static uint8_t -vl82c480_read(uint16_t addr, void *p) +static uint8_t +vl82c480_read(uint16_t addr, void *priv) { - vl82c480_t *dev = (vl82c480_t *)p; - uint8_t ret = 0xff; + const vl82c480_t *dev = (vl82c480_t *) priv; + uint8_t ret = 0xff; switch (addr) { - case 0xec: - ret = dev->idx; - break; + case 0xec: + ret = dev->idx; + break; - case 0xed: - ret = dev->regs[dev->idx]; - break; + case 0xed: + ret = dev->regs[dev->idx]; + break; - case 0xee: - if (!mem_a20_alt) - outb(0x92, inb(0x92) | 2); - break; +/* TODO: This is actually Fast A20 enable. */ +#if 0 + case 0xee: + if (!mem_a20_alt) + outb(0x92, inb(0x92) | 2); + break; +#endif - case 0xef: - softresetx86(); - cpu_set_edx(); - break; + case 0xef: + softresetx86(); + cpu_set_edx(); + break; + + default: + break; } return ret; } - static void -vl82c480_close(void *p) +vl82c480_close(void *priv) { - vl82c480_t *dev = (vl82c480_t *)p; + vl82c480_t *dev = (vl82c480_t *) priv; free(dev); } - static void * vl82c480_init(const device_t *info) { - vl82c480_t *dev = (vl82c480_t *)malloc(sizeof(vl82c480_t)); + vl82c480_t *dev = (vl82c480_t *) malloc(sizeof(vl82c480_t)); memset(dev, 0, sizeof(vl82c480_t)); dev->regs[0x00] = info->local; @@ -178,34 +189,40 @@ vl82c480_init(const device_t *info) dev->regs[0x03] = 0x88; dev->regs[0x06] = 0x1b; if (info->local == 0x98) - dev->regs[0x07] = 0x21; + dev->regs[0x07] = 0x21; dev->regs[0x08] = 0x38; - io_sethandler(0x00ec, 0x0004, vl82c480_read, NULL, NULL, vl82c480_write, NULL, NULL, dev); + io_sethandler(0x00ec, 0x0004, vl82c480_read, NULL, NULL, vl82c480_write, NULL, NULL, dev); device_add(&port_92_device); return dev; } - const device_t vl82c480_device = { - "VLSI VL82c480", - "vl82c480", - 0, - 0x90, - vl82c480_init, vl82c480_close, NULL, - { NULL }, NULL, NULL, - NULL + .name = "VLSI VL82c480", + .internal_name = "vl82c480", + .flags = 0, + .local = 0x90, + .init = vl82c480_init, + .close = vl82c480_close, + .reset = NULL, + { .available = NULL }, + .speed_changed = NULL, + .force_redraw = NULL, + .config = NULL }; - const device_t vl82c486_device = { - "VLSI VL82c486", - "vl82c486", - 0, - 0x98, - vl82c480_init, vl82c480_close, NULL, - { NULL }, NULL, NULL, - NULL + .name = "VLSI VL82c486", + .internal_name = "vl82c486", + .flags = 0, + .local = 0x98, + .init = vl82c480_init, + .close = vl82c480_close, + .reset = NULL, + { .available = NULL }, + .speed_changed = NULL, + .force_redraw = NULL, + .config = NULL }; diff --git a/src/chipset/wd76c10.c b/src/chipset/wd76c10.c index 82e5d57d5..ae4b30228 100644 --- a/src/chipset/wd76c10.c +++ b/src/chipset/wd76c10.c @@ -1,22 +1,22 @@ /* - * 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. + * 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. + * This file is part of the 86Box distribution. * - * Implementation of the Western Digital WD76C10 chipset. + * Implementation of the Western Digital WD76C10 chipset. * - * Note: This chipset has no datasheet, everything were done via - * reverse engineering the BIOS of various machines using it. + * Note: This chipset has no datasheet, everything were done via + * reverse engineering the BIOS of various machines using it. * - * Authors: Tiseno100 * - * Copyright 2021 Tiseno100 * + * Authors: Tiseno100 + * + * Copyright 2021 Tiseno100 */ - #include #include #include @@ -37,134 +37,156 @@ #include <86box/hdc_ide.h> #include <86box/lpt.h> #include <86box/mem.h> +#include <86box/plat_unused.h> #include <86box/port_92.h> #include <86box/serial.h> #include <86box/chipset.h> /* Lock/Unlock Procedures */ -#define LOCK dev->lock +#define LOCK dev->lock #define UNLOCKED !dev->lock -#define ENABLE_WD76C10_LOG 1 - #ifdef ENABLE_WD76C10_LOG int wd76c10_do_log = ENABLE_WD76C10_LOG; + static void wd76c10_log(const char *fmt, ...) { va_list ap; - if (wd76c10_do_log) - { + if (wd76c10_do_log) { va_start(ap, fmt); pclog_ex(fmt, ap); va_end(ap); } } #else -#define wd76c10_log(fmt, ...) +# define wd76c10_log(fmt, ...) #endif -typedef struct -{ - uint16_t lock_reg, oscillator_40mhz, cache_flush, ems_page_reg, - ems_page_reg_pointer, port_shadow, pmc_interrupt, - high_mem_protect_boundry, delay_line, diagnostic, - nmi_status, pmc_input, pmc_timer, - pmc_output, ems_control_low_address_boundry, shadow_ram, - split_addr, bank32staddr, bank10staddr, - non_page_mode_dram_timing, mem_control, - refresh_control, disk_chip_select, prog_chip_sel_addr, - bus_timing_power_down_ctl, clk_control; +typedef struct wd76c10_t { + uint16_t lock_reg; + uint16_t oscillator_40mhz; + uint16_t cache_flush; + uint16_t ems_page_reg; + uint16_t ems_page_reg_pointer; + uint16_t port_shadow; + uint16_t pmc_interrupt; + uint16_t high_mem_protect_boundry; + uint16_t delay_line; + uint16_t diagnostic; + uint16_t nmi_status; + uint16_t pmc_input; + uint16_t pmc_timer; + uint16_t pmc_output; + uint16_t ems_control_low_address_boundry; + uint16_t shadow_ram; + uint16_t split_addr; + uint16_t bank32staddr; + uint16_t bank10staddr; + uint16_t non_page_mode_dram_timing; + uint16_t mem_control; + uint16_t refresh_control; + uint16_t disk_chip_select; + uint16_t prog_chip_sel_addr; + uint16_t bus_timing_power_down_ctl; + uint16_t clk_control; int lock; - fdc_t *fdc_controller; + fdc_t *fdc_controller; mem_mapping_t *mem_mapping; - serial_t *uart[2]; + serial_t *uart[2]; } wd76c10_t; -static void wd76c10_refresh_control(wd76c10_t *dev) +static void +wd76c10_refresh_control(wd76c10_t *dev) { serial_remove(dev->uart[1]); /* Serial B */ - switch ((dev->refresh_control >> 1) & 7) - { - case 1: - serial_setup(dev->uart[1], 0x3f8, 3); - break; - case 2: - serial_setup(dev->uart[1], 0x2f8, 3); - break; - case 3: - serial_setup(dev->uart[1], 0x3e8, 3); - break; - case 4: - serial_setup(dev->uart[1], 0x2e8, 3); - break; + switch ((dev->refresh_control >> 1) & 7) { + case 1: + serial_setup(dev->uart[1], 0x3f8, 3); + break; + case 2: + serial_setup(dev->uart[1], 0x2f8, 3); + break; + case 3: + serial_setup(dev->uart[1], 0x3e8, 3); + break; + case 4: + serial_setup(dev->uart[1], 0x2e8, 3); + break; + default: + break; } serial_remove(dev->uart[0]); /* Serial A */ - switch ((dev->refresh_control >> 5) & 7) - { - case 1: - serial_setup(dev->uart[0], 0x3f8, 4); - break; - case 2: - serial_setup(dev->uart[0], 0x2f8, 4); - break; - case 3: - serial_setup(dev->uart[0], 0x3e8, 4); - break; - case 4: - serial_setup(dev->uart[0], 0x2e8, 4); - break; + switch ((dev->refresh_control >> 5) & 7) { + case 1: + serial_setup(dev->uart[0], 0x3f8, 4); + break; + case 2: + serial_setup(dev->uart[0], 0x2f8, 4); + break; + case 3: + serial_setup(dev->uart[0], 0x3e8, 4); + break; + case 4: + serial_setup(dev->uart[0], 0x2e8, 4); + break; + default: + break; } lpt1_remove(); /* LPT */ - switch ((dev->refresh_control >> 9) & 3) - { - case 1: - lpt1_init(0x3bc); - lpt1_irq(7); - break; - case 2: - lpt1_init(0x378); - lpt1_irq(7); - break; - case 3: - lpt1_init(0x278); - lpt1_irq(7); - break; + switch ((dev->refresh_control >> 9) & 3) { + case 1: + lpt1_init(0x3bc); + lpt1_irq(7); + break; + case 2: + lpt1_init(0x378); + lpt1_irq(7); + break; + case 3: + lpt1_init(0x278); + lpt1_irq(7); + break; + + default: + break; } } -static void wd76c10_split_addr(wd76c10_t *dev) +static void +wd76c10_split_addr(wd76c10_t *dev) { - switch ((dev->split_addr >> 8) & 3) - { - case 1: - if (((dev->shadow_ram >> 8) & 3) == 2) - mem_remap_top(256); - break; - case 2: - if (((dev->shadow_ram >> 8) & 3) == 1) - mem_remap_top(320); - break; - case 3: - if (((dev->shadow_ram >> 8) & 3) == 3) - mem_remap_top(384); - break; + switch ((dev->split_addr >> 8) & 3) { + case 1: + if (((dev->shadow_ram >> 8) & 3) == 2) + mem_remap_top(256); + break; + case 2: + if (((dev->shadow_ram >> 8) & 3) == 1) + mem_remap_top(320); + break; + case 3: + if (((dev->shadow_ram >> 8) & 3) == 3) + mem_remap_top(384); + break; + default: + break; } } -static void wd76c10_disk_chip_select(wd76c10_t *dev) +static void +wd76c10_disk_chip_select(wd76c10_t *dev) { ide_pri_disable(); - if (!(dev->disk_chip_select & 1)) - { + if (!(dev->disk_chip_select & 1)) { ide_set_base(0, !(dev->disk_chip_select & 0x0010) ? 0x1f0 : 0x170); ide_set_side(0, !(dev->disk_chip_select & 0x0010) ? 0x3f6 : 0x376); } @@ -172,275 +194,281 @@ static void wd76c10_disk_chip_select(wd76c10_t *dev) fdc_remove(dev->fdc_controller); if (!(dev->disk_chip_select & 2)) - fdc_set_base(dev->fdc_controller, !(dev->disk_chip_select & 0x0010) ? 0x3f0 : 0x370); + fdc_set_base(dev->fdc_controller, !(dev->disk_chip_select & 0x0010) ? FDC_PRIMARY_ADDR : FDC_SECONDARY_ADDR); } -static void wd76c10_shadow_recalc(wd76c10_t *dev) +static void +wd76c10_shadow_recalc(wd76c10_t *dev) { - switch ((dev->shadow_ram >> 14) & 3) - { - case 0: - mem_set_mem_state_both(0x20000, 0x80000, MEM_READ_INTERNAL | MEM_WRITE_INTERNAL); - break; - case 1: - mem_set_mem_state_both(0x80000, 0x20000, MEM_READ_DISABLED | MEM_WRITE_DISABLED); - break; - case 2: - mem_set_mem_state_both(0x40000, 0x60000, MEM_READ_DISABLED | MEM_WRITE_DISABLED); - break; - case 3: - mem_set_mem_state_both(0x20000, 0x80000, MEM_READ_DISABLED | MEM_WRITE_DISABLED); - break; + switch ((dev->shadow_ram >> 14) & 3) { + case 0: + mem_set_mem_state_both(0x20000, 0x80000, MEM_READ_INTERNAL | MEM_WRITE_INTERNAL); + break; + case 1: + mem_set_mem_state_both(0x80000, 0x20000, MEM_READ_DISABLED | MEM_WRITE_DISABLED); + break; + case 2: + mem_set_mem_state_both(0x40000, 0x60000, MEM_READ_DISABLED | MEM_WRITE_DISABLED); + break; + case 3: + mem_set_mem_state_both(0x20000, 0x80000, MEM_READ_DISABLED | MEM_WRITE_DISABLED); + break; + default: + break; } - switch ((dev->shadow_ram >> 8) & 3) - { - case 0: - mem_set_mem_state_both(0xe0000, 0x20000, MEM_READ_EXTANY | MEM_WRITE_EXTANY); - mem_set_mem_state_both(0xc0000, 0x10000, MEM_READ_EXTANY | MEM_WRITE_EXTANY); - break; - case 1: - mem_set_mem_state_both(0xf0000, 0x10000, MEM_READ_INTERNAL | (!!(dev->shadow_ram & 0x1000) ? MEM_WRITE_DISABLED : MEM_WRITE_INTERNAL)); - break; - case 2: - mem_set_mem_state_both(0xe0000, 0x20000, MEM_READ_INTERNAL | (!!(dev->shadow_ram & 0x1000) ? MEM_WRITE_DISABLED : MEM_WRITE_INTERNAL)); - break; - case 3: - mem_set_mem_state_both(0x20000, 0x80000, MEM_READ_DISABLED | (!!(dev->shadow_ram & 0x1000) ? MEM_WRITE_DISABLED : MEM_WRITE_INTERNAL)); - break; + switch ((dev->shadow_ram >> 8) & 3) { + case 0: + mem_set_mem_state_both(0xe0000, 0x20000, MEM_READ_EXTANY | MEM_WRITE_EXTANY); + mem_set_mem_state_both(0xc0000, 0x10000, MEM_READ_EXTANY | MEM_WRITE_EXTANY); + break; + case 1: + mem_set_mem_state_both(0xf0000, 0x10000, MEM_READ_INTERNAL | (!!(dev->shadow_ram & 0x1000) ? MEM_WRITE_DISABLED : MEM_WRITE_INTERNAL)); + break; + case 2: + mem_set_mem_state_both(0xe0000, 0x20000, MEM_READ_INTERNAL | (!!(dev->shadow_ram & 0x1000) ? MEM_WRITE_DISABLED : MEM_WRITE_INTERNAL)); + break; + case 3: + mem_set_mem_state_both(0x20000, 0x80000, MEM_READ_DISABLED | (!!(dev->shadow_ram & 0x1000) ? MEM_WRITE_DISABLED : MEM_WRITE_INTERNAL)); + break; + default: + break; } } static void wd76c10_write(uint16_t addr, uint16_t val, void *priv) { - wd76c10_t *dev = (wd76c10_t *)priv; + wd76c10_t *dev = (wd76c10_t *) priv; - if (UNLOCKED) - { - switch (addr) - { - case 0x1072: - dev->clk_control = val; - break; + if (UNLOCKED) { + switch (addr) { + case 0x1072: + dev->clk_control = val; + break; - case 0x1872: - dev->bus_timing_power_down_ctl = val; - break; + case 0x1872: + dev->bus_timing_power_down_ctl = val; + break; - case 0x2072: - dev->refresh_control = val; - wd76c10_refresh_control(dev); - break; + case 0x2072: + dev->refresh_control = val; + wd76c10_refresh_control(dev); + break; - case 0x2872: - dev->disk_chip_select = val; - wd76c10_disk_chip_select(dev); - break; + case 0x2872: + dev->disk_chip_select = val; + wd76c10_disk_chip_select(dev); + break; - case 0x3072: - dev->prog_chip_sel_addr = val; - break; + case 0x3072: + dev->prog_chip_sel_addr = val; + break; - case 0x3872: - dev->non_page_mode_dram_timing = val; - break; + case 0x3872: + dev->non_page_mode_dram_timing = val; + break; - case 0x4072: - dev->mem_control = val; - break; + case 0x4072: + dev->mem_control = val; + break; - case 0x4872: - dev->bank10staddr = val; - break; + case 0x4872: + dev->bank10staddr = val; + break; - case 0x5072: - dev->bank32staddr = val; - break; + case 0x5072: + dev->bank32staddr = val; + break; - case 0x5872: - dev->split_addr = val; - wd76c10_split_addr(dev); - break; + case 0x5872: + dev->split_addr = val; + wd76c10_split_addr(dev); + break; - case 0x6072: - dev->shadow_ram = val & 0xffbf; - wd76c10_shadow_recalc(dev); - break; + case 0x6072: + dev->shadow_ram = val & 0xffbf; + wd76c10_shadow_recalc(dev); + break; - case 0x6872: - dev->ems_control_low_address_boundry = val & 0xecff; - break; + case 0x6872: + dev->ems_control_low_address_boundry = val & 0xecff; + break; - case 0x7072: - dev->pmc_output = (val >> 8) & 0x00ff; - break; + case 0x7072: + dev->pmc_output = (val >> 8) & 0x00ff; + break; - case 0x7872: - dev->pmc_output = val & 0xff00; - break; + case 0x7872: + dev->pmc_output = val & 0xff00; + break; - case 0x8072: - dev->pmc_timer = val; - break; + case 0x8072: + dev->pmc_timer = val; + break; - case 0x8872: - dev->pmc_input = val; - break; + case 0x8872: + dev->pmc_input = val; + break; - case 0x9072: - dev->nmi_status = val & 0x00fc; - break; + case 0x9072: + dev->nmi_status = val & 0x00fc; + break; - case 0x9872: - dev->diagnostic = val & 0xfdff; - break; + case 0x9872: + dev->diagnostic = val & 0xfdff; + break; - case 0xa072: - dev->delay_line = val; - break; + case 0xa072: + dev->delay_line = val; + break; - case 0xc872: - dev->pmc_interrupt = val & 0xfcfc; - break; + case 0xc872: + dev->pmc_interrupt = val & 0xfcfc; + break; - case 0xf072: - dev->oscillator_40mhz = 0; - break; + case 0xf072: + dev->oscillator_40mhz = 0; + break; - case 0xf472: - dev->oscillator_40mhz = 1; - break; + case 0xf472: + dev->oscillator_40mhz = 1; + break; - case 0xf872: - dev->cache_flush = val; - flushmmucache(); - break; + case 0xf872: + dev->cache_flush = val; + flushmmucache(); + break; + + default: + break; } wd76c10_log("WD76C10: dev->regs[%04x] = %04x\n", addr, val); } - switch (addr) - { - case 0xe072: - dev->ems_page_reg_pointer = val & 0x003f; - break; + switch (addr) { + case 0xe072: + dev->ems_page_reg_pointer = val & 0x003f; + break; - case 0xe872: - dev->ems_page_reg = val & 0x8fff; - break; + case 0xe872: + dev->ems_page_reg = val & 0x8fff; + break; - case 0xf073: - dev->lock_reg = val & 0x00ff; - LOCK = !(val & 0x00da); - break; + case 0xf073: + dev->lock_reg = val & 0x00ff; + LOCK = !(val & 0x00da); + break; + + default: + break; } } static uint16_t wd76c10_read(uint16_t addr, void *priv) { - wd76c10_t *dev = (wd76c10_t *)priv; + const wd76c10_t *dev = (wd76c10_t *) priv; + wd76c10_log("WD76C10: R dev->regs[%04x]\n", addr); - switch (addr) - { - case 0x1072: - return dev->clk_control; + switch (addr) { + case 0x1072: + return dev->clk_control; - case 0x1872: - return dev->bus_timing_power_down_ctl; + case 0x1872: + return dev->bus_timing_power_down_ctl; - case 0x2072: - return dev->refresh_control; + case 0x2072: + return dev->refresh_control; - case 0x2872: - return dev->disk_chip_select; + case 0x2872: + return dev->disk_chip_select; - case 0x3072: - return dev->prog_chip_sel_addr; + case 0x3072: + return dev->prog_chip_sel_addr; - case 0x3872: - return dev->non_page_mode_dram_timing; + case 0x3872: + return dev->non_page_mode_dram_timing; - case 0x4072: - return dev->mem_control; + case 0x4072: + return dev->mem_control; - case 0x4872: - return dev->bank10staddr; + case 0x4872: + return dev->bank10staddr; - case 0x5072: - return dev->bank32staddr; + case 0x5072: + return dev->bank32staddr; - case 0x5872: - return dev->split_addr; + case 0x5872: + return dev->split_addr; - case 0x6072: - return dev->shadow_ram; + case 0x6072: + return dev->shadow_ram; - case 0x6872: - return dev->ems_control_low_address_boundry; + case 0x6872: + return dev->ems_control_low_address_boundry; - case 0x7072: - return (dev->pmc_output << 8) & 0xff00; + case 0x7072: + return (dev->pmc_output << 8) & 0xff00; - case 0x7872: - return (dev->pmc_output) & 0xff00; + case 0x7872: + return (dev->pmc_output) & 0xff00; - case 0x8072: - return dev->pmc_timer; + case 0x8072: + return dev->pmc_timer; - case 0x8872: - return dev->pmc_input; + case 0x8872: + return dev->pmc_input; - case 0x9072: - return dev->nmi_status; + case 0x9072: + return dev->nmi_status; - case 0x9872: - return dev->diagnostic; + case 0x9872: + return dev->diagnostic; - case 0xa072: - return dev->delay_line; + case 0xa072: + return dev->delay_line; - case 0xb872: - return (inb(0x040b) << 8) | inb(0x04d6); + case 0xb872: + return (inb(0x040b) << 8) | inb(0x04d6); - case 0xc872: - return dev->pmc_interrupt; + case 0xc872: + return dev->pmc_interrupt; - case 0xd072: - return dev->port_shadow; + case 0xd072: + return dev->port_shadow; - case 0xe072: - return dev->ems_page_reg_pointer; + case 0xe072: + return dev->ems_page_reg_pointer; - case 0xe872: - return dev->ems_page_reg; + case 0xe872: + return dev->ems_page_reg; - case 0xfc72: - return 0x0ff0; + case 0xfc72: + return 0x0ff0; - default: - return 0xffff; + default: + return 0xffff; } } static void wd76c10_close(void *priv) { - wd76c10_t *dev = (wd76c10_t *)priv; + wd76c10_t *dev = (wd76c10_t *) priv; free(dev); } static void * -wd76c10_init(const device_t *info) +wd76c10_init(UNUSED(const device_t *info)) { - wd76c10_t *dev = (wd76c10_t *)malloc(sizeof(wd76c10_t)); + wd76c10_t *dev = (wd76c10_t *) malloc(sizeof(wd76c10_t)); memset(dev, 0, sizeof(wd76c10_t)); device_add(&port_92_inv_device); - dev->uart[0] = device_add_inst(&ns16450_device, 1); - dev->uart[1] = device_add_inst(&ns16450_device, 2); + dev->uart[0] = device_add_inst(&ns16450_device, 1); + dev->uart[1] = device_add_inst(&ns16450_device, 2); dev->fdc_controller = device_add(&fdc_at_device); device_add(&ide_isa_device); @@ -538,14 +566,15 @@ wd76c10_init(const device_t *info) } const device_t wd76c10_device = { - "Western Digital WD76C10", - "wd76c10", - 0, - 0, - wd76c10_init, - wd76c10_close, - NULL, - {NULL}, - NULL, - NULL, - NULL}; + .name = "Western Digital WD76C10", + .internal_name = "wd76c10", + .flags = 0, + .local = 0, + .init = wd76c10_init, + .close = wd76c10_close, + .reset = NULL, + { .available = NULL }, + .speed_changed = NULL, + .force_redraw = NULL, + .config = NULL +}; diff --git a/src/codegen/CMakeLists.txt b/src/codegen/CMakeLists.txt index 68b13f24d..3cb9de6ca 100644 --- a/src/codegen/CMakeLists.txt +++ b/src/codegen/CMakeLists.txt @@ -1,16 +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. +# 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. +# This file is part of the 86Box distribution. # -# CMake build script. +# CMake build script. # -# Authors: David HrdliÄka, +# Authors: David HrdliÄka, # -# Copyright 2020,2021 David HrdliÄka. +# Copyright 2020-2021 David HrdliÄka. # if(DYNAREC) @@ -23,9 +23,9 @@ if(DYNAREC) target_sources(dynarec PRIVATE codegen_x86-64.c codegen_accumulate_x86-64.c) else() - message(SEND_ERROR + message(SEND_ERROR "Dynarec is incompatible with target platform ${ARCH}") endif() target_link_libraries(86Box dynarec cgt) -endif() \ No newline at end of file +endif() diff --git a/src/codegen/codegen.c b/src/codegen/codegen.c index f633243ca..79b26015c 100644 --- a/src/codegen/codegen.c +++ b/src/codegen/codegen.c @@ -9,28 +9,32 @@ #include "x86_ops.h" #include "codegen.h" -void (*codegen_timing_start)(); +void (*codegen_timing_start)(void); void (*codegen_timing_prefix)(uint8_t prefix, uint32_t fetchdat); void (*codegen_timing_opcode)(uint8_t opcode, uint32_t fetchdat, int op_32, uint32_t op_pc); -void (*codegen_timing_block_start)(); -void (*codegen_timing_block_end)(); -int (*codegen_timing_jump_cycles)(); +void (*codegen_timing_block_start)(void); +void (*codegen_timing_block_end)(void); +int (*codegen_timing_jump_cycles)(void); -void codegen_timing_set(codegen_timing_t *timing) +void +codegen_timing_set(codegen_timing_t *timing) { - codegen_timing_start = timing->start; - codegen_timing_prefix = timing->prefix; - codegen_timing_opcode = timing->opcode; - codegen_timing_block_start = timing->block_start; - codegen_timing_block_end = timing->block_end; - codegen_timing_jump_cycles = timing->jump_cycles; + codegen_timing_start = timing->start; + codegen_timing_prefix = timing->prefix; + codegen_timing_opcode = timing->opcode; + codegen_timing_block_start = timing->block_start; + codegen_timing_block_end = timing->block_end; + codegen_timing_jump_cycles = timing->jump_cycles; } int codegen_in_recompile; /* This is for compatibility with new x87 code. */ -void codegen_set_rounding_mode(int mode) +void +codegen_set_rounding_mode(int mode) { - /* cpu_state.new_npxc = (cpu_state.old_npxc & ~0xc00) | (cpu_state.npxc & 0xc00); */ - cpu_state.new_npxc = (cpu_state.old_npxc & ~0xc00) | (mode << 10); +#if 0 + cpu_state.new_npxc = (cpu_state.old_npxc & ~0xc00) | (cpu_state.npxc & 0xc00); +#endif + cpu_state.new_npxc = (cpu_state.old_npxc & ~0xc00) | (mode << 10); } diff --git a/src/codegen/codegen.h b/src/codegen/codegen.h index d3898b535..6d30211a6 100644 --- a/src/codegen/codegen.h +++ b/src/codegen/codegen.h @@ -1,20 +1,20 @@ /* - * VARCem Virtual ARchaeological Computer EMulator. - * An emulator of (mostly) x86-based PC systems and devices, - * using the ISA,EISA,VLB,MCA and PCI system buses, roughly - * spanning the era between 1981 and 1995. + * 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 VARCem Project. + * This file is part of the 86Box distribution. * - * Definitions for the code generator. + * Definitions for the code generator. * * * - * Authors: Sarah Walker, - * Miran Grca, + * Authors: Sarah Walker, + * Miran Grca, * - * Copyright 2008-2018 Sarah Walker. - * Copyright 2016-2018 Miran Grca. + * Copyright 2008-2018 Sarah Walker. + * Copyright 2016-2018 Miran Grca. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -41,11 +41,11 @@ #include "x86_ops.h" #ifdef __amd64__ -#include "codegen_x86-64.h" +# include "codegen_x86-64.h" #elif defined i386 || defined __i386 || defined __i386__ || defined _X86_ || defined _M_IX86 || defined _M_X64 -#include "codegen_x86.h" +# include "codegen_x86.h" #else -#error Dynamic recompiler not implemented on your platform +# error Dynamic recompiler not implemented on your platform #endif /*Handling self-modifying code (of which there is a lot on x86) : @@ -56,55 +56,60 @@ added to the page_lookup for this purpose. When in the page_lookup, each write will go through the mem_write_ram*_page() functions and set the dirty mask appropriately. - + Each codeblock also contains a code mask (actually two masks, one for each page the block is/may be in), again with each bit representing 64 bytes. - + Each page has a list of codeblocks present in it. As each codeblock can span up to two pages, two lists are present. - + When a codeblock is about to be executed, the code masks are compared with the dirty masks for the relevant pages. If either intersect, then codegen_check_flush() is called on the affected page(s), and all affected blocks are evicted. - + The 64 byte granularity appears to work reasonably well for most cases, avoiding most unnecessary evictions (eg when code & data are stored in the same page). */ -typedef struct codeblock_t -{ - uint64_t page_mask, page_mask2; - uint64_t *dirty_mask, *dirty_mask2; - uint64_t cmp; - - /*Previous and next pointers, for the codeblock list associated with - each physical page. Two sets of pointers, as a codeblock can be - present in two pages.*/ - struct codeblock_t *prev, *next; - struct codeblock_t *prev_2, *next_2; - - /*Pointers for codeblock tree, used to search for blocks when hash lookup - fails.*/ - struct codeblock_t *parent, *left, *right; - - int pnt; - int ins; +typedef struct codeblock_t { + uint64_t page_mask; + uint64_t page_mask2; + uint64_t *dirty_mask; + uint64_t *dirty_mask2; + uint64_t cmp; - int valid; + /*Previous and next pointers, for the codeblock list associated with + each physical page. Two sets of pointers, as a codeblock can be + present in two pages.*/ + struct codeblock_t *prev; + struct codeblock_t *next; + struct codeblock_t *prev_2; + struct codeblock_t *next_2; - int was_recompiled; - int TOP; + /*Pointers for codeblock tree, used to search for blocks when hash lookup + fails.*/ + struct codeblock_t *parent; + struct codeblock_t *left; + struct codeblock_t *right; - uint32_t pc; - uint32_t _cs; - uint32_t endpc; - uint32_t phys, phys_2; - uint32_t status; - uint32_t flags; + int pnt; + int ins; - uint8_t data[2048]; + int valid; + + int was_recompiled; + int TOP; + + uint32_t pc; + uint32_t _cs; + uint32_t endpc; + uint32_t phys, phys_2; + uint32_t status; + uint32_t flags; + + uint8_t data[2048]; } codeblock_t; /*Code block uses FPU*/ @@ -112,219 +117,193 @@ typedef struct codeblock_t /*Code block is always entered with the same FPU top-of-stack*/ #define CODEBLOCK_STATIC_TOP 2 -static inline codeblock_t *codeblock_tree_find(uint32_t phys, uint32_t _cs) +static inline codeblock_t * +codeblock_tree_find(uint32_t phys, uint32_t _cs) { - codeblock_t *block = pages[phys >> 12].head; - uint64_t a = _cs | ((uint64_t)phys << 32); - - while (block) - { - if (a == block->cmp) - { - if (!((block->status ^ cpu_cur_status) & CPU_STATUS_FLAGS) && - ((block->status & cpu_cur_status & CPU_STATUS_MASK) == (cpu_cur_status & CPU_STATUS_MASK))) - break; - } - if (a < block->cmp) - block = block->left; - else - block = block->right; - } - - return block; -} + codeblock_t *block = pages[phys >> 12].head; + uint64_t a = _cs | ((uint64_t) phys << 32); -static inline void codeblock_tree_add(codeblock_t *new_block) -{ - codeblock_t *block = pages[new_block->phys >> 12].head; - uint64_t a = new_block->_cs | ((uint64_t)new_block->phys << 32); - new_block->cmp = a; - - if (!block) - { - pages[new_block->phys >> 12].head = new_block; - new_block->parent = new_block->left = new_block->right = NULL; + while (block) { + if (a == block->cmp) { + if (!((block->status ^ cpu_cur_status) & CPU_STATUS_FLAGS) && ((block->status & cpu_cur_status & CPU_STATUS_MASK) == (cpu_cur_status & CPU_STATUS_MASK))) + break; } + if (a < block->cmp) + block = block->left; else - { - codeblock_t *old_block = NULL; - - while (block) - { - old_block = block; - if (a < old_block->cmp) - block = block->left; - else - block = block->right; - } - - if (a < old_block->cmp) - old_block->left = new_block; - else - old_block->right = new_block; - - new_block->parent = old_block; - new_block->left = new_block->right = NULL; - } + block = block->right; + } + + return block; } -static inline void codeblock_tree_delete(codeblock_t *block) +static inline void +codeblock_tree_add(codeblock_t *new_block) { - codeblock_t *parent = block->parent; + codeblock_t *block = pages[new_block->phys >> 12].head; + uint64_t a = new_block->_cs | ((uint64_t) new_block->phys << 32); + new_block->cmp = a; - if (!block->left && !block->right) - { - /*Easy case - remove from parent*/ - if (!parent) - pages[block->phys >> 12].head = NULL; - else - { - if (parent->left == block) - parent->left = NULL; - if (parent->right == block) - parent->right = NULL; - } - return; - } - else if (!block->left) - { - /*Only right node*/ - if (!parent) - { - pages[block->phys >> 12].head = block->right; - pages[block->phys >> 12].head->parent = NULL; - } - else - { - if (parent->left == block) - { - parent->left = block->right; - parent->left->parent = parent; - } - if (parent->right == block) - { - parent->right = block->right; - parent->right->parent = parent; - } - } - return; - } - else if (!block->right) - { - /*Only left node*/ - if (!parent) - { - pages[block->phys >> 12].head = block->left; - pages[block->phys >> 12].head->parent = NULL; - } - else - { - if (parent->left == block) - { - parent->left = block->left; - parent->left->parent = parent; - } - if (parent->right == block) - { - parent->right = block->left; - parent->right->parent = parent; - } - } - return; + if (!block) { + pages[new_block->phys >> 12].head = new_block; + new_block->parent = new_block->left = new_block->right = NULL; + } else { + codeblock_t *old_block = NULL; + + while (block) { + old_block = block; + if (a < old_block->cmp) + block = block->left; + else + block = block->right; } + + if (a < old_block->cmp) + old_block->left = new_block; else - { - /*Difficult case - node has two children. Walk right child to find lowest node*/ - codeblock_t *lowest = block->right, *highest; - codeblock_t *old_parent; - - while (lowest->left) - lowest = lowest->left; + old_block->right = new_block; - old_parent = lowest->parent; - - /*Replace deleted node with lowest node*/ - if (!parent) - pages[block->phys >> 12].head = lowest; - else - { - if (parent->left == block) - parent->left = lowest; - if (parent->right == block) - parent->right = lowest; - } - - lowest->parent = parent; - lowest->left = block->left; - if (lowest->left) - lowest->left->parent = lowest; - - old_parent->left = NULL; - - highest = lowest->right; - if (!highest) - { - if (lowest != block->right) - { - lowest->right = block->right; - block->right->parent = lowest; - } - return; - } - - while (highest->right) - highest = highest->right; - - if (block->right && block->right != lowest) - { - highest->right = block->right; - block->right->parent = highest; - } - } + new_block->parent = old_block; + new_block->left = new_block->right = NULL; + } } -#define PAGE_MASK_INDEX_MASK 3 +static inline void +codeblock_tree_delete(codeblock_t *block) +{ + codeblock_t *parent = block->parent; + + if (!block->left && !block->right) { + /*Easy case - remove from parent*/ + if (!parent) + pages[block->phys >> 12].head = NULL; + else { + if (parent->left == block) + parent->left = NULL; + if (parent->right == block) + parent->right = NULL; + } + return; + } else if (!block->left) { + /*Only right node*/ + if (!parent) { + pages[block->phys >> 12].head = block->right; + pages[block->phys >> 12].head->parent = NULL; + } else { + if (parent->left == block) { + parent->left = block->right; + parent->left->parent = parent; + } + if (parent->right == block) { + parent->right = block->right; + parent->right->parent = parent; + } + } + return; + } else if (!block->right) { + /*Only left node*/ + if (!parent) { + pages[block->phys >> 12].head = block->left; + pages[block->phys >> 12].head->parent = NULL; + } else { + if (parent->left == block) { + parent->left = block->left; + parent->left->parent = parent; + } + if (parent->right == block) { + parent->right = block->left; + parent->right->parent = parent; + } + } + return; + } else { + /*Difficult case - node has two children. Walk right child to find lowest node*/ + codeblock_t *lowest = block->right; + codeblock_t *highest; + codeblock_t *old_parent; + + while (lowest->left) + lowest = lowest->left; + + old_parent = lowest->parent; + + /*Replace deleted node with lowest node*/ + if (!parent) + pages[block->phys >> 12].head = lowest; + else { + if (parent->left == block) + parent->left = lowest; + if (parent->right == block) + parent->right = lowest; + } + + lowest->parent = parent; + lowest->left = block->left; + if (lowest->left) + lowest->left->parent = lowest; + + old_parent->left = NULL; + + highest = lowest->right; + if (!highest) { + if (lowest != block->right) { + lowest->right = block->right; + block->right->parent = lowest; + } + return; + } + + while (highest->right) + highest = highest->right; + + if (block->right && block->right != lowest) { + highest->right = block->right; + block->right->parent = highest; + } + } +} + +#define PAGE_MASK_INDEX_MASK 3 #define PAGE_MASK_INDEX_SHIFT 10 -#define PAGE_MASK_MASK 63 -#define PAGE_MASK_SHIFT 4 +#define PAGE_MASK_MASK 63 +#define PAGE_MASK_SHIFT 4 extern codeblock_t *codeblock; extern codeblock_t **codeblock_hash; -void codegen_init(); -void codegen_reset(); -void codegen_block_init(uint32_t phys_addr); -void codegen_block_remove(); -void codegen_block_start_recompile(codeblock_t *block); -void codegen_block_end_recompile(codeblock_t *block); -void codegen_block_end(); -void codegen_generate_call(uint8_t opcode, OpFn op, uint32_t fetchdat, uint32_t new_pc, uint32_t old_pc); -void codegen_generate_seg_restore(); -void codegen_set_op32(); -void codegen_flush(); -void codegen_check_flush(page_t *page, uint64_t mask, uint32_t phys_addr); +extern void codegen_init(void); +extern void codegen_reset(void); +extern void codegen_block_init(uint32_t phys_addr); +extern void codegen_block_remove(void); +extern void codegen_block_start_recompile(codeblock_t *block); +extern void codegen_block_end_recompile(codeblock_t *block); +extern void codegen_block_end(void); +extern void codegen_generate_call(uint8_t opcode, OpFn op, uint32_t fetchdat, uint32_t new_pc, uint32_t old_pc); +extern void codegen_generate_seg_restore(void); +extern void codegen_set_op32(void); +extern void codegen_flush(void); +extern void codegen_check_flush(page_t *page, uint64_t mask, uint32_t phys_addr); -extern int cpu_block_end; +extern int cpu_block_end; extern uint32_t codegen_endpc; extern int codegen_block_cycles; -extern void (*codegen_timing_start)(); +extern void (*codegen_timing_start)(void); extern void (*codegen_timing_prefix)(uint8_t prefix, uint32_t fetchdat); extern void (*codegen_timing_opcode)(uint8_t opcode, uint32_t fetchdat, int op_32, uint32_t op_pc); -extern void (*codegen_timing_block_start)(); -extern void (*codegen_timing_block_end)(); -extern int (*codegen_timing_jump_cycles)(); +extern void (*codegen_timing_block_start)(void); +extern void (*codegen_timing_block_end)(void); +extern int (*codegen_timing_jump_cycles)(void); -typedef struct codegen_timing_t -{ - void (*start)(); - void (*prefix)(uint8_t prefix, uint32_t fetchdat); - void (*opcode)(uint8_t opcode, uint32_t fetchdat, int op_32, uint32_t op_pc); - void (*block_start)(); - void (*block_end)(); - int (*jump_cycles)(); +typedef struct codegen_timing_t { + void (*start)(void); + void (*prefix)(uint8_t prefix, uint32_t fetchdat); + void (*opcode)(uint8_t opcode, uint32_t fetchdat, int op_32, uint32_t op_pc); + void (*block_start)(void); + void (*block_end)(void); + int (*jump_cycles)(void); } codegen_timing_t; extern codegen_timing_t codegen_timing_pentium; @@ -342,53 +321,53 @@ extern int block_pos; #define CPU_BLOCK_END() cpu_block_end = 1 -static inline void addbyte(uint8_t val) +static inline void +addbyte(uint8_t val) { - codeblock[block_current].data[block_pos++] = val; - if (block_pos >= BLOCK_MAX) - { - CPU_BLOCK_END(); - } + codeblock[block_current].data[block_pos++] = val; + if (block_pos >= BLOCK_MAX) { + CPU_BLOCK_END(); + } } -static inline void addword(uint16_t val) +static inline void +addword(uint16_t val) { - uint16_t *p = (uint16_t *) &codeblock[block_current].data[block_pos]; - *p = val; - block_pos += 2; - if (block_pos >= BLOCK_MAX) - { - CPU_BLOCK_END(); - } + uint16_t *p = (uint16_t *) &codeblock[block_current].data[block_pos]; + *p = val; + block_pos += 2; + if (block_pos >= BLOCK_MAX) { + CPU_BLOCK_END(); + } } -static inline void addlong(uint32_t val) +static inline void +addlong(uint32_t val) { - uint32_t *p = (uint32_t *) &codeblock[block_current].data[block_pos]; - *p = val; - block_pos += 4; - if (block_pos >= BLOCK_MAX) - { - CPU_BLOCK_END(); - } + uint32_t *p = (uint32_t *) &codeblock[block_current].data[block_pos]; + *p = val; + block_pos += 4; + if (block_pos >= BLOCK_MAX) { + CPU_BLOCK_END(); + } } -static inline void addquad(uint64_t val) +static inline void +addquad(uint64_t val) { - uint64_t *p = (uint64_t *) &codeblock[block_current].data[block_pos]; - *p = val; - block_pos += 8; - if (block_pos >= BLOCK_MAX) - { - CPU_BLOCK_END(); - } + uint64_t *p = (uint64_t *) &codeblock[block_current].data[block_pos]; + *p = val; + block_pos += 8; + if (block_pos >= BLOCK_MAX) { + CPU_BLOCK_END(); + } } /*Current physical page of block being recompiled. -1 if no recompilation taking place */ extern uint32_t recomp_page; -extern x86seg *op_ea_seg; -extern int op_ssegs; +extern x86seg *op_ea_seg; +extern int op_ssegs; extern uint32_t op_old_pc; /*Set to 1 if flags have been changed in the block being recompiled, and hence diff --git a/src/codegen/codegen_accumulate.h b/src/codegen/codegen_accumulate.h index 5aebf4c77..3e8261748 100644 --- a/src/codegen/codegen_accumulate.h +++ b/src/codegen/codegen_accumulate.h @@ -1,12 +1,11 @@ -enum -{ - ACCREG_cycles = 0, - - ACCREG_COUNT +enum { + ACCREG_cycles = 0, + + ACCREG_COUNT }; struct ir_data_t; void codegen_accumulate(int acc_reg, int delta); void codegen_accumulate_flush(void); -void codegen_accumulate_reset(); +void codegen_accumulate_reset(void); diff --git a/src/codegen/codegen_accumulate_x86-64.c b/src/codegen/codegen_accumulate_x86-64.c index 05a728ae5..6e88487ba 100644 --- a/src/codegen/codegen_accumulate_x86-64.c +++ b/src/codegen/codegen_accumulate_x86-64.c @@ -9,61 +9,61 @@ static struct { - int count; - uintptr_t dest_reg; -} acc_regs[] = -{ - [ACCREG_cycles] = {0, (uintptr_t) &(cycles)}, + int count; + uintptr_t dest_reg; +} acc_regs[] = { + [ACCREG_cycles] = {0, (uintptr_t) & (cycles)}, }; -void codegen_accumulate(int acc_reg, int delta) +void +codegen_accumulate(int acc_reg, int delta) { - acc_regs[acc_reg].count += delta; + acc_regs[acc_reg].count += delta; #ifdef USE_ACYCS - if ((acc_reg == ACCREG_cycles) && (delta != 0)) { - if (delta == -1) { - /* -delta = 1 */ - addbyte(0xff); /*inc dword ptr[&acycs]*/ - addbyte(0x04); - addbyte(0x25); - addlong((uint32_t) (uintptr_t) &(acycs)); - } else if (delta == 1) { - /* -delta = -1 */ - addbyte(0xff); /*dec dword ptr[&acycs]*/ - addbyte(0x0c); - addbyte(0x25); - addlong((uint32_t) (uintptr_t) &(acycs)); - } else { - addbyte(0x81); /*ADD $acc_regs[c].count,acc_regs[c].dest*/ - addbyte(0x04); - addbyte(0x25); - addlong((uint32_t) (uintptr_t) &(acycs)); - addlong(-delta); - } - } + if ((acc_reg == ACCREG_cycles) && (delta != 0)) { + if (delta == -1) { + /* -delta = 1 */ + addbyte(0xff); /*inc dword ptr[&acycs]*/ + addbyte(0x04); + addbyte(0x25); + addlong((uint32_t) (uintptr_t) & (acycs)); + } else if (delta == 1) { + /* -delta = -1 */ + addbyte(0xff); /*dec dword ptr[&acycs]*/ + addbyte(0x0c); + addbyte(0x25); + addlong((uint32_t) (uintptr_t) & (acycs)); + } else { + addbyte(0x81); /*ADD $acc_regs[c].count,acc_regs[c].dest*/ + addbyte(0x04); + addbyte(0x25); + addlong((uint32_t) (uintptr_t) & (acycs)); + addlong(-delta); + } + } #endif } -void codegen_accumulate_flush(void) +void +codegen_accumulate_flush(void) { - if (acc_regs[0].count) { - addbyte(0x55); /*push rbp*/ - addbyte(0x48); /*mov rbp,val*/ - addbyte(0xbd); - addlong((uint32_t) (acc_regs[0].dest_reg & 0xffffffffULL)); - addlong((uint32_t) (acc_regs[0].dest_reg >> 32ULL)); - addbyte(0x81); /* add d,[rbp][0],val */ - addbyte(0x45); - addbyte(0x00); - addlong(acc_regs[0].count); - addbyte(0x5d); /*pop rbp*/ - } + if (acc_regs[0].count) { + /* To reduce the size of the generated code, we take advantage of + the fact that the target offset points to _cycles within cpu_state, + so we can just use our existing infrastracture for variables + relative to cpu_state. */ + addbyte(0x81); /*ADDL $acc_regs[0].count,(_cycles)*/ + addbyte(0x45); + addbyte((uint8_t) cpu_state_offset(_cycles)); + addlong(acc_regs[0].count); + } - acc_regs[0].count = 0; + acc_regs[0].count = 0; } -void codegen_accumulate_reset() +void +codegen_accumulate_reset(void) { - acc_regs[0].count = 0; + acc_regs[0].count = 0; } diff --git a/src/codegen/codegen_accumulate_x86.c b/src/codegen/codegen_accumulate_x86.c index 424cc45ab..8d56c4c14 100644 --- a/src/codegen/codegen_accumulate_x86.c +++ b/src/codegen/codegen_accumulate_x86.c @@ -9,52 +9,58 @@ static struct { - int count; - uintptr_t dest_reg; -} acc_regs[] = -{ - [ACCREG_cycles] = {0, (uintptr_t) &(cycles)} + int count; + uintptr_t dest_reg; +} acc_regs[] = { + [ACCREG_cycles] = {0, (uintptr_t) & (cycles)} }; -void codegen_accumulate(int acc_reg, int delta) +void +codegen_accumulate(int acc_reg, int delta) { - acc_regs[acc_reg].count += delta; + acc_regs[acc_reg].count += delta; #ifdef USE_ACYCS - if ((acc_reg == ACCREG_cycles) && (delta != 0)) { - if (delta == -1) { - /* -delta = 1 */ - addbyte(0xff); /*inc dword ptr[&acycs]*/ - addbyte(0x05); - addlong((uint32_t) (uintptr_t) &(acycs)); - } else if (delta == 1) { - /* -delta = -1 */ - addbyte(0xff); /*dec dword ptr[&acycs]*/ - addbyte(0x0d); - addlong((uint32_t) (uintptr_t) &(acycs)); - } else { - addbyte(0x81); /*ADD $acc_regs[c].count,acc_regs[c].dest*/ - addbyte(0x05); - addlong((uint32_t) (uintptr_t) &(acycs)); - addlong((uintptr_t) -delta); - } - } + if ((acc_reg == ACCREG_cycles) && (delta != 0)) { + if (delta == -1) { + /* -delta = 1 */ + addbyte(0xff); /*inc dword ptr[&acycs]*/ + addbyte(0x05); + addlong((uint32_t) (uintptr_t) & (acycs)); + } else if (delta == 1) { + /* -delta = -1 */ + addbyte(0xff); /*dec dword ptr[&acycs]*/ + addbyte(0x0d); + addlong((uint32_t) (uintptr_t) & (acycs)); + } else { + addbyte(0x81); /*ADD $acc_regs[c].count,acc_regs[c].dest*/ + addbyte(0x05); + addlong((uint32_t) (uintptr_t) & (acycs)); + addlong((uintptr_t) -delta); + } + } #endif } -void codegen_accumulate_flush(void) +void +codegen_accumulate_flush(void) { - if (acc_regs[0].count) { - addbyte(0x81); /*ADD $acc_regs[0].count,acc_regs[0].dest*/ - addbyte(0x05); - addlong((uint32_t) acc_regs[0].dest_reg); - addlong(acc_regs[0].count); - } + if (acc_regs[0].count) { + /* To reduce the size of the generated code, we take advantage of + the fact that the target offset points to _cycles within cpu_state, + so we can just use our existing infrastracture for variables + relative to cpu_state. */ + addbyte(0x81); /*MOVL $acc_regs[0].count,(_cycles)*/ + addbyte(0x45); + addbyte((uint8_t) cpu_state_offset(_cycles)); + addlong(acc_regs[0].count); + } - acc_regs[0].count = 0; + acc_regs[0].count = 0; } -void codegen_accumulate_reset() +void +codegen_accumulate_reset(void) { - acc_regs[0].count = 0; + acc_regs[0].count = 0; } diff --git a/src/codegen/codegen_ops.c b/src/codegen/codegen_ops.c index e398ad16a..a81eef67e 100644 --- a/src/codegen/codegen_ops.c +++ b/src/codegen/codegen_ops.c @@ -5,10 +5,13 @@ #include <86box/86box.h> #include <86box/mem.h> +#include <86box/plat_unused.h> #include "cpu.h" #include "x86.h" #include "x86_ops.h" #include "x86_flags.h" +#include "x86seg_common.h" +#include "x86seg.h" #include "x87.h" #include "386_common.h" #include "cpu.h" @@ -16,9 +19,9 @@ #include "codegen_ops.h" #if defined __amd64__ || defined _M_X64 -#include "codegen_ops_x86-64.h" +# include "codegen_ops_x86-64.h" #elif defined i386 || defined __i386 || defined __i386__ || defined _X86_ || defined _M_IX86 -#include "codegen_ops_x86.h" +# include "codegen_ops_x86.h" #endif #include "codegen_ops_arith.h" @@ -32,10 +35,10 @@ #include "codegen_ops_stack.h" #include "codegen_ops_xchg.h" -RecompOpFn recomp_opcodes[512] = -{ +RecompOpFn recomp_opcodes[512] = { + // clang-format off /*16-bit data*/ -/* 00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f*/ +/* 00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f*/ /*00*/ ropADD_b_rmw, ropADD_w_rmw, ropADD_b_rm, ropADD_w_rm, ropADD_AL_imm, ropADD_AX_imm, ropPUSH_ES_16, ropPOP_ES_16, ropOR_b_rmw, ropOR_w_rmw, ropOR_b_rm, ropOR_w_rm, ropOR_AL_imm, ropOR_AX_imm, ropPUSH_CS_16, NULL, /*10*/ NULL, NULL, NULL, NULL, NULL, NULL, ropPUSH_SS_16, NULL, NULL, NULL, NULL, NULL, NULL, NULL, ropPUSH_DS_16, ropPOP_DS_16, /*20*/ ropAND_b_rmw, ropAND_w_rmw, ropAND_b_rm, ropAND_w_rm, ropAND_AL_imm, ropAND_AX_imm, NULL, NULL, ropSUB_b_rmw, ropSUB_w_rmw, ropSUB_b_rm, ropSUB_w_rm, ropSUB_AL_imm, ropSUB_AX_imm, NULL, NULL, @@ -57,7 +60,7 @@ RecompOpFn recomp_opcodes[512] = /*f0*/ NULL, NULL, NULL, NULL, NULL, NULL, ropF6, ropF7_w, NULL, NULL, ropCLI, ropSTI, ropCLD, ropSTD, ropFE, ropFF_16, /*32-bit data*/ -/* 00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f*/ +/* 00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f*/ /*00*/ ropADD_b_rmw, ropADD_l_rmw, ropADD_b_rm, ropADD_l_rm, ropADD_AL_imm, ropADD_EAX_imm, ropPUSH_ES_32, ropPOP_ES_32, ropOR_b_rmw, ropOR_l_rmw, ropOR_b_rm, ropOR_l_rm, ropOR_AL_imm, ropOR_EAX_imm, ropPUSH_CS_32, NULL, /*10*/ NULL, NULL, NULL, NULL, NULL, NULL, ropPUSH_SS_32, NULL, NULL, NULL, NULL, NULL, NULL, NULL, ropPUSH_DS_32, ropPOP_DS_32, /*20*/ ropAND_b_rmw, ropAND_l_rmw, ropAND_b_rm, ropAND_l_rm, ropAND_AL_imm, ropAND_EAX_imm, NULL, NULL, ropSUB_b_rmw, ropSUB_l_rmw, ropSUB_b_rm, ropSUB_l_rm, ropSUB_AL_imm, ropSUB_EAX_imm, NULL, NULL, @@ -77,12 +80,13 @@ RecompOpFn recomp_opcodes[512] = /*d0*/ ropD0, ropD1_l, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, /*e0*/ NULL, NULL, ropLOOP, ropJCXZ, NULL, NULL, NULL, NULL, ropCALL_r32, ropJMP_r32, NULL, ropJMP_r8, NULL, NULL, NULL, NULL, /*f0*/ NULL, NULL, NULL, NULL, NULL, NULL, ropF6, ropF7_l, NULL, NULL, ropCLI, ropSTI, ropCLD, ropSTD, ropFE, ropFF_32 + // clang-format on }; -RecompOpFn recomp_opcodes_0f[512] = -{ +RecompOpFn recomp_opcodes_0f[512] = { + // clang-format off /*16-bit data*/ -/* 00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f*/ +/* 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, @@ -90,8 +94,8 @@ RecompOpFn recomp_opcodes_0f[512] = /*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, ropEMMS, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, +/*60*/ ropPUNPCKLBW, ropPUNPCKLWD, ropPUNPCKLDQ, ropPACKSSWB, ropPCMPGTB, ropPCMPGTW, ropPCMPGTD, ropPACKUSWB, ropPUNPCKHBW, ropPUNPCKHWD, ropPUNPCKHDQ, ropPACKSSDW, NULL, NULL, ropMOVD_mm_l, ropMOVQ_mm_q, +/*70*/ NULL, ropPSxxW_imm, ropPSxxD_imm, ropPSxxQ_imm, ropPCMPEQB, ropPCMPEQW, ropPCMPEQD, ropEMMS, NULL, NULL, NULL, NULL, NULL, NULL, ropMOVD_l_mm, ropMOVQ_q_mm, /*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, @@ -99,12 +103,12 @@ RecompOpFn recomp_opcodes_0f[512] = /*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, +/*d0*/ NULL, ropPSRLW, ropPSRLD, ropPSRLQ, NULL, ropPMULLW, NULL, NULL, ropPSUBUSB, ropPSUBUSW, NULL, ropPAND, ropPADDUSB, ropPADDUSW, NULL, ropPANDN, +/*e0*/ NULL, ropPSRAW, ropPSRAD, NULL, NULL, ropPMULHW, NULL, NULL, ropPSUBSB, ropPSUBSW, NULL, ropPOR, ropPADDSB, ropPADDSW, NULL, ropPXOR, +/*f0*/ NULL, ropPSLLW, ropPSLLD, ropPSLLQ, NULL, ropPMADDWD, NULL, NULL, ropPSUBB, ropPSUBW, ropPSUBD, NULL, ropPADDB, ropPADDW, ropPADDD, NULL, /*32-bit data*/ -/* 00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f*/ +/* 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, @@ -124,13 +128,61 @@ RecompOpFn recomp_opcodes_0f[512] = /*d0*/ NULL, ropPSRLW, ropPSRLD, ropPSRLQ, NULL, ropPMULLW, NULL, NULL, ropPSUBUSB, ropPSUBUSW, NULL, ropPAND, ropPADDUSB, ropPADDUSW, NULL, ropPANDN, /*e0*/ NULL, ropPSRAW, ropPSRAD, NULL, NULL, ropPMULHW, NULL, NULL, ropPSUBSB, ropPSUBSW, NULL, ropPOR, ropPADDSB, ropPADDSW, NULL, ropPXOR, /*f0*/ NULL, ropPSLLW, ropPSLLD, ropPSLLQ, NULL, ropPMADDWD, NULL, NULL, ropPSUBB, ropPSUBW, ropPSUBD, NULL, ropPADDB, ropPADDW, ropPADDD, NULL, + // clang-format on }; - -RecompOpFn recomp_opcodes_d8[512] = -{ +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 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*/ +/* 00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f*/ /*00*/ ropFADDs, ropFADDs, ropFADDs, ropFADDs, ropFADDs, ropFADDs, ropFADDs, ropFADDs, ropFMULs, ropFMULs, ropFMULs, ropFMULs, ropFMULs, ropFMULs, ropFMULs, ropFMULs, /*10*/ ropFCOMs, ropFCOMs, ropFCOMs, ropFCOMs, ropFCOMs, ropFCOMs, ropFCOMs, ropFCOMs, ropFCOMPs, ropFCOMPs, ropFCOMPs, ropFCOMPs, ropFCOMPs, ropFCOMPs, ropFCOMPs, ropFCOMPs, /*20*/ ropFSUBs, ropFSUBs, ropFSUBs, ropFSUBs, ropFSUBs, ropFSUBs, ropFSUBs, ropFSUBs, ropFSUBRs, ropFSUBRs, ropFSUBRs, ropFSUBRs, ropFSUBRs, ropFSUBRs, ropFSUBRs, ropFSUBRs, @@ -152,7 +204,7 @@ RecompOpFn recomp_opcodes_d8[512] = /*f0*/ ropFDIV, ropFDIV, ropFDIV, ropFDIV, ropFDIV, ropFDIV, ropFDIV, ropFDIV, ropFDIVR, ropFDIVR, ropFDIVR, ropFDIVR, ropFDIVR, ropFDIVR, ropFDIVR, ropFDIVR, /*32-bit data*/ -/* 00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f*/ +/* 00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f*/ /*00*/ ropFADDs, ropFADDs, ropFADDs, ropFADDs, ropFADDs, ropFADDs, ropFADDs, ropFADDs, ropFMULs, ropFMULs, ropFMULs, ropFMULs, ropFMULs, ropFMULs, ropFMULs, ropFMULs, /*10*/ ropFCOMs, ropFCOMs, ropFCOMs, ropFCOMs, ropFCOMs, ropFCOMs, ropFCOMs, ropFCOMs, ropFCOMPs, ropFCOMPs, ropFCOMPs, ropFCOMPs, ropFCOMPs, ropFCOMPs, ropFCOMPs, ropFCOMPs, /*20*/ ropFSUBs, ropFSUBs, ropFSUBs, ropFSUBs, ropFSUBs, ropFSUBs, ropFSUBs, ropFSUBs, ropFSUBRs, ropFSUBRs, ropFSUBRs, ropFSUBRs, ropFSUBRs, ropFSUBRs, ropFSUBRs, ropFSUBRs, @@ -172,12 +224,13 @@ RecompOpFn recomp_opcodes_d8[512] = /*d0*/ ropFCOM, ropFCOM, ropFCOM, ropFCOM, ropFCOM, ropFCOM, ropFCOM, ropFCOM, ropFCOMP, ropFCOMP, ropFCOMP, ropFCOMP, ropFCOMP, ropFCOMP, ropFCOMP, ropFCOMP, /*e0*/ ropFSUB, ropFSUB, ropFSUB, ropFSUB, ropFSUB, ropFSUB, ropFSUB, ropFSUB, ropFSUBR, ropFSUBR, ropFSUBR, ropFSUBR, ropFSUBR, ropFSUBR, ropFSUBR, ropFSUBR, /*f0*/ ropFDIV, ropFDIV, ropFDIV, ropFDIV, ropFDIV, ropFDIV, ropFDIV, ropFDIV, ropFDIVR, ropFDIVR, ropFDIVR, ropFDIVR, ropFDIVR, ropFDIVR, ropFDIVR, ropFDIVR, + // clang-format on }; -RecompOpFn recomp_opcodes_d9[512] = -{ +RecompOpFn recomp_opcodes_d9[512] = { + // clang-format off /*16-bit data*/ -/* 00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f*/ +/* 00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f*/ /*00*/ ropFLDs, ropFLDs, ropFLDs, ropFLDs, ropFLDs, ropFLDs, ropFLDs, ropFLDs, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, /*10*/ ropFSTs, ropFSTs, ropFSTs, ropFSTs, ropFSTs, ropFSTs, ropFSTs, ropFSTs, ropFSTPs, ropFSTPs, ropFSTPs, ropFSTPs, ropFSTPs, ropFSTPs, ropFSTPs, ropFSTPs, /*20*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, ropFLDCW, ropFLDCW, ropFLDCW, ropFLDCW, ropFLDCW, ropFLDCW, ropFLDCW, ropFLDCW, @@ -199,7 +252,7 @@ RecompOpFn recomp_opcodes_d9[512] = /*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 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f*/ /*00*/ ropFLDs, ropFLDs, ropFLDs, ropFLDs, ropFLDs, ropFLDs, ropFLDs, ropFLDs, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, /*10*/ ropFSTs, ropFSTs, ropFSTs, ropFSTs, ropFSTs, ropFSTs, ropFSTs, ropFSTs, ropFSTPs, ropFSTPs, ropFSTPs, ropFSTPs, ropFSTPs, ropFSTPs, ropFSTPs, ropFSTPs, /*20*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, ropFLDCW, ropFLDCW, ropFLDCW, ropFLDCW, ropFLDCW, ropFLDCW, ropFLDCW, ropFLDCW, @@ -219,12 +272,13 @@ RecompOpFn recomp_opcodes_d9[512] = /*d0*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, /*e0*/ ropFCHS, NULL, NULL, NULL, NULL, NULL, NULL, NULL, ropFLD1, ropFLDL2T, ropFLDL2E, ropFLDPI, ropFLDEG2, ropFLDLN2, ropFLDZ, NULL, /*f0*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + // clang-format on }; -RecompOpFn recomp_opcodes_da[512] = -{ +RecompOpFn recomp_opcodes_da[512] = { + // clang-format off /*16-bit data*/ -/* 00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f*/ +/* 00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f*/ /*00*/ ropFADDil, ropFADDil, ropFADDil, ropFADDil, ropFADDil, ropFADDil, ropFADDil, ropFADDil, ropFMULil, ropFMULil, ropFMULil, ropFMULil, ropFMULil, ropFMULil, ropFMULil, ropFMULil, /*10*/ ropFCOMil, ropFCOMil, ropFCOMil, ropFCOMil, ropFCOMil, ropFCOMil, ropFCOMil, ropFCOMil, ropFCOMPil, ropFCOMPil, ropFCOMPil, ropFCOMPil, ropFCOMPil, ropFCOMPil, ropFCOMPil, ropFCOMPil, /*20*/ ropFSUBil, ropFSUBil, ropFSUBil, ropFSUBil, ropFSUBil, ropFSUBil, ropFSUBil, ropFSUBil, ropFSUBRil, ropFSUBRil, ropFSUBRil, ropFSUBRil, ropFSUBRil, ropFSUBRil, ropFSUBRil, ropFSUBRil, @@ -246,7 +300,7 @@ RecompOpFn recomp_opcodes_da[512] = /*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 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f*/ /*00*/ ropFADDil, ropFADDil, ropFADDil, ropFADDil, ropFADDil, ropFADDil, ropFADDil, ropFADDil, ropFMULil, ropFMULil, ropFMULil, ropFMULil, ropFMULil, ropFMULil, ropFMULil, ropFMULil, /*10*/ ropFCOMil, ropFCOMil, ropFCOMil, ropFCOMil, ropFCOMil, ropFCOMil, ropFCOMil, ropFCOMil, ropFCOMPil, ropFCOMPil, ropFCOMPil, ropFCOMPil, ropFCOMPil, ropFCOMPil, ropFCOMPil, ropFCOMPil, /*20*/ ropFSUBil, ropFSUBil, ropFSUBil, ropFSUBil, ropFSUBil, ropFSUBil, ropFSUBil, ropFSUBil, ropFSUBRil, ropFSUBRil, ropFSUBRil, ropFSUBRil, ropFSUBRil, ropFSUBRil, ropFSUBRil, ropFSUBRil, @@ -266,12 +320,13 @@ RecompOpFn recomp_opcodes_da[512] = /*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_db[512] = -{ +RecompOpFn recomp_opcodes_db[512] = { + // clang-format off /*16-bit data*/ -/* 00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f*/ +/* 00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f*/ /*00*/ ropFILDl, ropFILDl, ropFILDl, ropFILDl, ropFILDl, ropFILDl, ropFILDl, ropFILDl, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, /*10*/ ropFISTl, ropFISTl, ropFISTl, ropFISTl, ropFISTl, ropFISTl, ropFISTl, ropFISTl, ropFISTPl, ropFISTPl, ropFISTPl, ropFISTPl, ropFISTPl, ropFISTPl, ropFISTPl, ropFISTPl, /*20*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, @@ -293,7 +348,7 @@ RecompOpFn recomp_opcodes_db[512] = /*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 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f*/ /*80*/ ropFILDl, ropFILDl, ropFILDl, ropFILDl, ropFILDl, ropFILDl, ropFILDl, ropFILDl, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, /*10*/ ropFISTl, ropFISTl, ropFISTl, ropFISTl, ropFISTl, ropFISTl, ropFISTl, ropFISTl, ropFISTPl, ropFISTPl, ropFISTPl, ropFISTPl, ropFISTPl, ropFISTPl, ropFISTPl, ropFISTPl, /*20*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, @@ -313,12 +368,13 @@ RecompOpFn recomp_opcodes_db[512] = /*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_dc[512] = -{ +RecompOpFn recomp_opcodes_dc[512] = { + // clang-format off /*16-bit data*/ -/* 00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f*/ +/* 00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f*/ /*00*/ ropFADDd, ropFADDd, ropFADDd, ropFADDd, ropFADDd, ropFADDd, ropFADDd, ropFADDd, ropFMULd, ropFMULd, ropFMULd, ropFMULd, ropFMULd, ropFMULd, ropFMULd, ropFMULd, /*10*/ ropFCOMd, ropFCOMd, ropFCOMd, ropFCOMd, ropFCOMd, ropFCOMd, ropFCOMd, ropFCOMd, ropFCOMPd, ropFCOMPd, ropFCOMPd, ropFCOMPd, ropFCOMPd, ropFCOMPd, ropFCOMPd, ropFCOMPd, /*20*/ ropFSUBd, ropFSUBd, ropFSUBd, ropFSUBd, ropFSUBd, ropFSUBd, ropFSUBd, ropFSUBd, ropFSUBRd, ropFSUBRd, ropFSUBRd, ropFSUBRd, ropFSUBRd, ropFSUBRd, ropFSUBRd, ropFSUBRd, @@ -340,7 +396,7 @@ RecompOpFn recomp_opcodes_dc[512] = /*f0*/ ropFDIVRr, ropFDIVRr, ropFDIVRr, ropFDIVRr, ropFDIVRr, ropFDIVRr, ropFDIVRr, ropFDIVRr, ropFDIVr, ropFDIVr, ropFDIVr, ropFDIVr, ropFDIVr, ropFDIVr, ropFDIVr, ropFDIVr, /*32-bit data*/ -/* 00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f*/ +/* 00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f*/ /*00*/ ropFADDd, ropFADDd, ropFADDd, ropFADDd, ropFADDd, ropFADDd, ropFADDd, ropFADDd, ropFMULd, ropFMULd, ropFMULd, ropFMULd, ropFMULd, ropFMULd, ropFMULd, ropFMULd, /*10*/ ropFCOMd, ropFCOMd, ropFCOMd, ropFCOMd, ropFCOMd, ropFCOMd, ropFCOMd, ropFCOMd, ropFCOMPd, ropFCOMPd, ropFCOMPd, ropFCOMPd, ropFCOMPd, ropFCOMPd, ropFCOMPd, ropFCOMPd, /*20*/ ropFSUBd, ropFSUBd, ropFSUBd, ropFSUBd, ropFSUBd, ropFSUBd, ropFSUBd, ropFSUBd, ropFSUBRd, ropFSUBRd, ropFSUBRd, ropFSUBRd, ropFSUBRd, ropFSUBRd, ropFSUBRd, ropFSUBRd, @@ -360,12 +416,13 @@ RecompOpFn recomp_opcodes_dc[512] = /*d0*/ ropFCOM, ropFCOM, ropFCOM, ropFCOM, ropFCOM, ropFCOM, ropFCOM, ropFCOM, ropFCOMP, ropFCOMP, ropFCOMP, ropFCOMP, ropFCOMP, ropFCOMP, ropFCOMP, ropFCOMP, /*e0*/ ropFSUBRr, ropFSUBRr, ropFSUBRr, ropFSUBRr, ropFSUBRr, ropFSUBRr, ropFSUBRr, ropFSUBRr, ropFSUBr, ropFSUBr, ropFSUBr, ropFSUBr, ropFSUBr, ropFSUBr, ropFSUBr, ropFSUBr, /*f0*/ ropFDIVRr, ropFDIVRr, ropFDIVRr, ropFDIVRr, ropFDIVRr, ropFDIVRr, ropFDIVRr, ropFDIVRr, ropFDIVr, ropFDIVr, ropFDIVr, ropFDIVr, ropFDIVr, ropFDIVr, ropFDIVr, ropFDIVr, + // clang-format on }; -RecompOpFn recomp_opcodes_dd[512] = -{ +RecompOpFn recomp_opcodes_dd[512] = { + // clang-format off /*16-bit data*/ -/* 00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f*/ +/* 00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f*/ /*00*/ ropFLDd, ropFLDd, ropFLDd, ropFLDd, ropFLDd, ropFLDd, ropFLDd, ropFLDd, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, /*10*/ ropFSTd, ropFSTd, ropFSTd, ropFSTd, ropFSTd, ropFSTd, ropFSTd, ropFSTd, ropFSTPd, ropFSTPd, ropFSTPd, ropFSTPd, ropFSTPd, ropFSTPd, ropFSTPd, ropFSTPd, /*20*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, @@ -387,7 +444,7 @@ RecompOpFn recomp_opcodes_dd[512] = /*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 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f*/ /*00*/ ropFLDd, ropFLDd, ropFLDd, ropFLDd, ropFLDd, ropFLDd, ropFLDd, ropFLDd, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, /*10*/ ropFSTd, ropFSTd, ropFSTd, ropFSTd, ropFSTd, ropFSTd, ropFSTd, ropFSTd, ropFSTPd, ropFSTPd, ropFSTPd, ropFSTPd, ropFSTPd, ropFSTPd, ropFSTPd, ropFSTPd, /*20*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, @@ -407,12 +464,13 @@ RecompOpFn recomp_opcodes_dd[512] = /*d0*/ ropFST, ropFST, ropFST, ropFST, ropFST, ropFST, ropFST, ropFST, ropFSTP, ropFSTP, ropFSTP, ropFSTP, ropFSTP, ropFSTP, ropFSTP, ropFSTP, /*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_de[512] = -{ +RecompOpFn recomp_opcodes_de[512] = { + // clang-format off /*16-bit data*/ -/* 00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f*/ +/* 00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f*/ /*00*/ ropFADDiw, ropFADDiw, ropFADDiw, ropFADDiw, ropFADDiw, ropFADDiw, ropFADDiw, ropFADDiw, ropFMULiw, ropFMULiw, ropFMULiw, ropFMULiw, ropFMULiw, ropFMULiw, ropFMULiw, ropFMULiw, /*10*/ ropFCOMiw, ropFCOMiw, ropFCOMiw, ropFCOMiw, ropFCOMiw, ropFCOMiw, ropFCOMiw, ropFCOMiw, ropFCOMPiw, ropFCOMPiw, ropFCOMPiw, ropFCOMPiw, ropFCOMPiw, ropFCOMPiw, ropFCOMPiw, ropFCOMPiw, /*20*/ ropFSUBiw, ropFSUBiw, ropFSUBiw, ropFSUBiw, ropFSUBiw, ropFSUBiw, ropFSUBiw, ropFSUBiw, ropFSUBRiw, ropFSUBRiw, ropFSUBRiw, ropFSUBRiw, ropFSUBRiw, ropFSUBRiw, ropFSUBRiw, ropFSUBRiw, @@ -434,7 +492,7 @@ RecompOpFn recomp_opcodes_de[512] = /*f0*/ ropFDIVRP, ropFDIVRP, ropFDIVRP, ropFDIVRP, ropFDIVRP, ropFDIVRP, ropFDIVRP, ropFDIVRP, ropFDIVP, ropFDIVP, ropFDIVP, ropFDIVP, ropFDIVP, ropFDIVP, ropFDIVP, ropFDIVP, /*32-bit data*/ -/* 00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f*/ +/* 00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f*/ /*00*/ ropFADDiw, ropFADDiw, ropFADDiw, ropFADDiw, ropFADDiw, ropFADDiw, ropFADDiw, ropFADDiw, ropFMULiw, ropFMULiw, ropFMULiw, ropFMULiw, ropFMULiw, ropFMULiw, ropFMULiw, ropFMULiw, /*10*/ ropFCOMiw, ropFCOMiw, ropFCOMiw, ropFCOMiw, ropFCOMiw, ropFCOMiw, ropFCOMiw, ropFCOMiw, ropFCOMPiw, ropFCOMPiw, ropFCOMPiw, ropFCOMPiw, ropFCOMPiw, ropFCOMPiw, ropFCOMPiw, ropFCOMPiw, /*20*/ ropFSUBiw, ropFSUBiw, ropFSUBiw, ropFSUBiw, ropFSUBiw, ropFSUBiw, ropFSUBiw, ropFSUBiw, ropFSUBRiw, ropFSUBRiw, ropFSUBRiw, ropFSUBRiw, ropFSUBRiw, ropFSUBRiw, ropFSUBRiw, ropFSUBRiw, @@ -454,12 +512,13 @@ RecompOpFn recomp_opcodes_de[512] = /*d0*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, ropFCOMPP, NULL, NULL, NULL, NULL, NULL, NULL, /*e0*/ ropFSUBRP, ropFSUBRP, ropFSUBRP, ropFSUBRP, ropFSUBRP, ropFSUBRP, ropFSUBRP, ropFSUBRP, ropFSUBP, ropFSUBP, ropFSUBP, ropFSUBP, ropFSUBP, ropFSUBP, ropFSUBP, ropFSUBP, /*f0*/ ropFDIVRP, ropFDIVRP, ropFDIVRP, ropFDIVRP, ropFDIVRP, ropFDIVRP, ropFDIVRP, ropFDIVRP, ropFDIVP, ropFDIVP, ropFDIVP, ropFDIVP, ropFDIVP, ropFDIVP, ropFDIVP, ropFDIVP, + // clang-format on }; -RecompOpFn recomp_opcodes_df[512] = -{ +RecompOpFn recomp_opcodes_df[512] = { + // clang-format off /*16-bit data*/ -/* 00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f*/ +/* 00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f*/ /*00*/ ropFILDw, ropFILDw, ropFILDw, ropFILDw, ropFILDw, ropFILDw, ropFILDw, ropFILDw, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, /*10*/ ropFISTw, ropFISTw, ropFISTw, ropFISTw, ropFISTw, ropFISTw, ropFISTw, ropFISTw, ropFISTPw, ropFISTPw, ropFISTPw, ropFISTPw, ropFISTPw, ropFISTPw, ropFISTPw, ropFISTPw, /*20*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, ropFILDq, ropFILDq, ropFILDq, ropFILDq, ropFILDq, ropFILDq, ropFILDq, ropFILDq, @@ -481,7 +540,7 @@ RecompOpFn recomp_opcodes_df[512] = /*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 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f*/ /*00*/ ropFILDw, ropFILDw, ropFILDw, ropFILDw, ropFILDw, ropFILDw, ropFILDw, ropFILDw, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, /*10*/ ropFISTw, ropFISTw, ropFISTw, ropFISTw, ropFISTw, ropFISTw, ropFISTw, ropFISTw, ropFISTPw, ropFISTPw, ropFISTPw, ropFISTPw, ropFISTPw, ropFISTPw, ropFISTPw, ropFISTPw, /*20*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, ropFILDq, ropFILDq, ropFILDq, ropFILDq, ropFILDq, ropFILDq, ropFILDq, ropFILDq, @@ -501,12 +560,13 @@ RecompOpFn recomp_opcodes_df[512] = /*d0*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, /*e0*/ ropFSTSW_AX, 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_REPE[512] = -{ +RecompOpFn recomp_opcodes_REPE[512] = { + // clang-format off /*16-bit data*/ -/* 00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f*/ +/* 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, @@ -528,7 +588,7 @@ RecompOpFn recomp_opcodes_REPE[512] = /*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 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, @@ -548,12 +608,13 @@ RecompOpFn recomp_opcodes_REPE[512] = /*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_REPNE[512] = -{ +RecompOpFn recomp_opcodes_REPNE[512] = { + // clang-format off /*16-bit data*/ -/* 00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f*/ +/* 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, @@ -575,7 +636,7 @@ RecompOpFn recomp_opcodes_REPNE[512] = /*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 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, @@ -595,4 +656,5 @@ RecompOpFn recomp_opcodes_REPNE[512] = /*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 }; diff --git a/src/codegen/codegen_ops.h b/src/codegen/codegen_ops.h index fe54cb9a4..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]; @@ -26,21 +27,21 @@ extern RecompOpFn recomp_opcodes_REPNE[512]; #define REG_EBP 5 #define REG_ESI 6 #define REG_EDI 7 -#define REG_AX 0 -#define REG_CX 1 -#define REG_DX 2 -#define REG_BX 3 -#define REG_SP 4 -#define REG_BP 5 -#define REG_SI 6 -#define REG_DI 7 -#define REG_AL 0 -#define REG_AH 4 -#define REG_CL 1 -#define REG_CH 5 -#define REG_DL 2 -#define REG_DH 6 -#define REG_BL 3 -#define REG_BH 7 +#define REG_AX 0 +#define REG_CX 1 +#define REG_DX 2 +#define REG_BX 3 +#define REG_SP 4 +#define REG_BP 5 +#define REG_SI 6 +#define REG_DI 7 +#define REG_AL 0 +#define REG_AH 4 +#define REG_CL 1 +#define REG_CH 5 +#define REG_DL 2 +#define REG_DH 6 +#define REG_BL 3 +#define REG_BH 7 #endif diff --git a/src/codegen/codegen_ops_arith.h b/src/codegen/codegen_ops_arith.h index e2eb9baef..28ee6d06c 100644 --- a/src/codegen/codegen_ops_arith.h +++ b/src/codegen/codegen_ops_arith.h @@ -1,1032 +1,982 @@ -static uint32_t ropINC_rw(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block) +static uint32_t +ropINC_rw(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block) { - int host_reg; - - CALL_FUNC((uintptr_t)flags_rebuild_c); - - host_reg = LOAD_REG_W(opcode & 7); - - STORE_HOST_REG_ADDR_WL((uintptr_t)&cpu_state.flags_op1, host_reg); - // ADD_HOST_REG_IMM_W(host_reg, 1); - INC_HOST_REG_W(host_reg); - STORE_IMM_ADDR_L((uintptr_t)&cpu_state.flags_op2, 1); - STORE_IMM_ADDR_L((uintptr_t)&cpu_state.flags_op, FLAGS_INC16); - STORE_HOST_REG_ADDR_WL((uintptr_t)&cpu_state.flags_res, host_reg); - STORE_REG_W_RELEASE(host_reg); - - codegen_flags_changed = 1; + int host_reg; - return op_pc; + CALL_FUNC((uintptr_t) flags_rebuild_c); + + host_reg = LOAD_REG_W(opcode & 7); + + STORE_HOST_REG_ADDR_WL((uintptr_t) &cpu_state.flags_op1, host_reg); +#if 0 + ADD_HOST_REG_IMM_W(host_reg, 1); +#endif + INC_HOST_REG_W(host_reg); + STORE_IMM_ADDR_L((uintptr_t) &cpu_state.flags_op2, 1); + STORE_IMM_ADDR_L((uintptr_t) &cpu_state.flags_op, FLAGS_INC16); + STORE_HOST_REG_ADDR_WL((uintptr_t) &cpu_state.flags_res, host_reg); + STORE_REG_W_RELEASE(host_reg); + + codegen_flags_changed = 1; + + return op_pc; } -static uint32_t ropINC_rl(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block) +static uint32_t +ropINC_rl(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block) { - int host_reg; + int host_reg; - CALL_FUNC((uintptr_t)flags_rebuild_c); - - host_reg = LOAD_REG_L(opcode & 7); - - STORE_HOST_REG_ADDR((uintptr_t)&cpu_state.flags_op1, host_reg); - // ADD_HOST_REG_IMM(host_reg, 1); - INC_HOST_REG(host_reg); - STORE_IMM_ADDR_L((uintptr_t)&cpu_state.flags_op2, 1); - STORE_IMM_ADDR_L((uintptr_t)&cpu_state.flags_op, FLAGS_INC32); - STORE_HOST_REG_ADDR((uintptr_t)&cpu_state.flags_res, host_reg); - STORE_REG_L_RELEASE(host_reg); + CALL_FUNC((uintptr_t) flags_rebuild_c); - codegen_flags_changed = 1; + host_reg = LOAD_REG_L(opcode & 7); - return op_pc; + STORE_HOST_REG_ADDR((uintptr_t) &cpu_state.flags_op1, host_reg); +#if 0 + ADD_HOST_REG_IMM(host_reg, 1); +#endif + INC_HOST_REG(host_reg); + STORE_IMM_ADDR_L((uintptr_t) &cpu_state.flags_op2, 1); + STORE_IMM_ADDR_L((uintptr_t) &cpu_state.flags_op, FLAGS_INC32); + STORE_HOST_REG_ADDR((uintptr_t) &cpu_state.flags_res, host_reg); + STORE_REG_L_RELEASE(host_reg); + + codegen_flags_changed = 1; + + return op_pc; } -static uint32_t ropDEC_rw(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block) +static uint32_t +ropDEC_rw(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block) { - int host_reg; - - CALL_FUNC((uintptr_t)flags_rebuild_c); + int host_reg; - host_reg = LOAD_REG_W(opcode & 7); - - STORE_HOST_REG_ADDR_WL((uintptr_t)&cpu_state.flags_op1, host_reg); - // SUB_HOST_REG_IMM_W(host_reg, 1); - DEC_HOST_REG_W(host_reg); - STORE_IMM_ADDR_L((uintptr_t)&cpu_state.flags_op2, 1); - STORE_IMM_ADDR_L((uintptr_t)&cpu_state.flags_op, FLAGS_DEC16); - STORE_HOST_REG_ADDR_WL((uintptr_t)&cpu_state.flags_res, host_reg); - STORE_REG_W_RELEASE(host_reg); + CALL_FUNC((uintptr_t) flags_rebuild_c); - codegen_flags_changed = 1; + host_reg = LOAD_REG_W(opcode & 7); - return op_pc; + STORE_HOST_REG_ADDR_WL((uintptr_t) &cpu_state.flags_op1, host_reg); +#if 0 + SUB_HOST_REG_IMM_W(host_reg, 1); +#endif + DEC_HOST_REG_W(host_reg); + STORE_IMM_ADDR_L((uintptr_t) &cpu_state.flags_op2, 1); + STORE_IMM_ADDR_L((uintptr_t) &cpu_state.flags_op, FLAGS_DEC16); + STORE_HOST_REG_ADDR_WL((uintptr_t) &cpu_state.flags_res, host_reg); + STORE_REG_W_RELEASE(host_reg); + + codegen_flags_changed = 1; + + return op_pc; } -static uint32_t ropDEC_rl(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block) +static uint32_t +ropDEC_rl(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block) { - int host_reg; - - CALL_FUNC((uintptr_t)flags_rebuild_c); + int host_reg; - host_reg = LOAD_REG_L(opcode & 7); - - STORE_HOST_REG_ADDR((uintptr_t)&cpu_state.flags_op1, host_reg); - // SUB_HOST_REG_IMM(host_reg, 1); - DEC_HOST_REG(host_reg); - STORE_IMM_ADDR_L((uintptr_t)&cpu_state.flags_op2, 1); - STORE_IMM_ADDR_L((uintptr_t)&cpu_state.flags_op, FLAGS_DEC32); - STORE_HOST_REG_ADDR((uintptr_t)&cpu_state.flags_res, host_reg); - STORE_REG_L_RELEASE(host_reg); + CALL_FUNC((uintptr_t) flags_rebuild_c); - codegen_flags_changed = 1; + host_reg = LOAD_REG_L(opcode & 7); - return op_pc; + STORE_HOST_REG_ADDR((uintptr_t) &cpu_state.flags_op1, host_reg); +#if 0 + SUB_HOST_REG_IMM(host_reg, 1); +#endif + DEC_HOST_REG(host_reg); + STORE_IMM_ADDR_L((uintptr_t) &cpu_state.flags_op2, 1); + STORE_IMM_ADDR_L((uintptr_t) &cpu_state.flags_op, FLAGS_DEC32); + STORE_HOST_REG_ADDR((uintptr_t) &cpu_state.flags_res, host_reg); + STORE_REG_L_RELEASE(host_reg); + + codegen_flags_changed = 1; + + return op_pc; } -#define ROP_ARITH_RMW(name, op, writeback) \ - static uint32_t rop ## name ## _b_rmw(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block) \ - { \ - int src_reg, dst_reg; \ - x86seg *target_seg; \ - \ - if ((fetchdat & 0xc0) == 0xc0) \ - { \ - dst_reg = LOAD_REG_B(fetchdat & 7); \ - } \ - else \ - { \ - target_seg = FETCH_EA(op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32); \ - STORE_IMM_ADDR_L((uintptr_t)&cpu_state.oldpc, op_old_pc); \ - SAVE_EA(); \ - MEM_CHECK_WRITE(target_seg); \ - dst_reg = MEM_LOAD_ADDR_EA_B_NO_ABRT(target_seg); \ - } \ - STORE_IMM_ADDR_L((uintptr_t)&cpu_state.flags_op, FLAGS_ ## op ## 8); \ - src_reg = LOAD_REG_B((fetchdat >> 3) & 7); \ - STORE_HOST_REG_ADDR_BL((uintptr_t)&cpu_state.flags_op1, dst_reg); \ - STORE_HOST_REG_ADDR_BL((uintptr_t)&cpu_state.flags_op2, src_reg); \ - op ## _HOST_REG_B(dst_reg, src_reg); \ - STORE_HOST_REG_ADDR_BL((uintptr_t)&cpu_state.flags_res, dst_reg); \ - if (writeback) \ - { \ - if ((fetchdat & 0xc0) == 0xc0) \ - STORE_REG_B_RELEASE(dst_reg); \ - else \ - { \ - LOAD_EA(); \ - MEM_STORE_ADDR_EA_B_NO_ABRT(target_seg, dst_reg); \ - } \ - } \ - else \ - RELEASE_REG(dst_reg); \ - RELEASE_REG(src_reg); \ - \ - codegen_flags_changed = 1; \ - return op_pc + 1; \ - } \ - static uint32_t rop ## name ## _w_rmw(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block) \ - { \ - int src_reg, dst_reg; \ - x86seg *target_seg; \ - \ - if ((fetchdat & 0xc0) == 0xc0) \ - { \ - dst_reg = LOAD_REG_W(fetchdat & 7); \ - } \ - else \ - { \ - target_seg = FETCH_EA(op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32); \ - STORE_IMM_ADDR_L((uintptr_t)&cpu_state.oldpc, op_old_pc); \ - SAVE_EA(); \ - MEM_CHECK_WRITE_W(target_seg); \ - dst_reg = MEM_LOAD_ADDR_EA_W_NO_ABRT(target_seg); \ - } \ - STORE_IMM_ADDR_L((uintptr_t)&cpu_state.flags_op, FLAGS_ ## op ## 16); \ - src_reg = LOAD_REG_W((fetchdat >> 3) & 7); \ - STORE_HOST_REG_ADDR_WL((uintptr_t)&cpu_state.flags_op1, dst_reg); \ - STORE_HOST_REG_ADDR_WL((uintptr_t)&cpu_state.flags_op2, src_reg); \ - op ## _HOST_REG_W(dst_reg, src_reg); \ - STORE_HOST_REG_ADDR_WL((uintptr_t)&cpu_state.flags_res, dst_reg); \ - if (writeback) \ - { \ - if ((fetchdat & 0xc0) == 0xc0) \ - STORE_REG_W_RELEASE(dst_reg); \ - else \ - { \ - LOAD_EA(); \ - MEM_STORE_ADDR_EA_W_NO_ABRT(target_seg, dst_reg); \ - } \ - } \ - else \ - RELEASE_REG(dst_reg); \ - RELEASE_REG(src_reg); \ - \ - codegen_flags_changed = 1; \ - return op_pc + 1; \ - } \ - static uint32_t rop ## name ## _l_rmw(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block) \ - { \ - int src_reg, dst_reg; \ - x86seg *target_seg; \ - \ - if ((fetchdat & 0xc0) == 0xc0) \ - { \ - dst_reg = LOAD_REG_L(fetchdat & 7); \ - } \ - else \ - { \ - target_seg = FETCH_EA(op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32); \ - STORE_IMM_ADDR_L((uintptr_t)&cpu_state.oldpc, op_old_pc); \ - SAVE_EA(); \ - MEM_CHECK_WRITE_L(target_seg); \ - dst_reg = MEM_LOAD_ADDR_EA_L_NO_ABRT(target_seg); \ - } \ - STORE_IMM_ADDR_L((uintptr_t)&cpu_state.flags_op, FLAGS_ ## op ## 32); \ - src_reg = LOAD_REG_L((fetchdat >> 3) & 7); \ - STORE_HOST_REG_ADDR((uintptr_t)&cpu_state.flags_op1, dst_reg); \ - STORE_HOST_REG_ADDR((uintptr_t)&cpu_state.flags_op2, src_reg); \ - op ## _HOST_REG_L(dst_reg, src_reg); \ - STORE_HOST_REG_ADDR((uintptr_t)&cpu_state.flags_res, dst_reg); \ - if (writeback) \ - { \ - if ((fetchdat & 0xc0) == 0xc0) \ - STORE_REG_L_RELEASE(dst_reg); \ - else \ - { \ - LOAD_EA(); \ - MEM_STORE_ADDR_EA_L_NO_ABRT(target_seg, dst_reg); \ - } \ - } \ - else \ - RELEASE_REG(dst_reg); \ - RELEASE_REG(src_reg); \ - \ - codegen_flags_changed = 1; \ - return op_pc + 1; \ - } +#define ROP_ARITH_RMW(name, op, writeback) \ + static uint32_t \ + rop##name##_b_rmw(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block) \ + { \ + int src_reg; \ + int dst_reg; \ + x86seg *target_seg; \ + \ + if ((fetchdat & 0xc0) == 0xc0) { \ + dst_reg = LOAD_REG_B(fetchdat & 7); \ + } else { \ + target_seg = FETCH_EA(op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32); \ + STORE_IMM_ADDR_L((uintptr_t) &cpu_state.oldpc, op_old_pc); \ + SAVE_EA(); \ + MEM_CHECK_WRITE(target_seg); \ + dst_reg = MEM_LOAD_ADDR_EA_B_NO_ABRT(target_seg); \ + } \ + STORE_IMM_ADDR_L((uintptr_t) &cpu_state.flags_op, FLAGS_##op##8); \ + src_reg = LOAD_REG_B((fetchdat >> 3) & 7); \ + STORE_HOST_REG_ADDR_BL((uintptr_t) &cpu_state.flags_op1, dst_reg); \ + STORE_HOST_REG_ADDR_BL((uintptr_t) &cpu_state.flags_op2, src_reg); \ + op##_HOST_REG_B(dst_reg, src_reg); \ + STORE_HOST_REG_ADDR_BL((uintptr_t) &cpu_state.flags_res, dst_reg); \ + if (writeback) { \ + if ((fetchdat & 0xc0) == 0xc0) \ + STORE_REG_B_RELEASE(dst_reg); \ + else { \ + LOAD_EA(); \ + MEM_STORE_ADDR_EA_B_NO_ABRT(target_seg, dst_reg); \ + } \ + } else \ + RELEASE_REG(dst_reg); \ + RELEASE_REG(src_reg); \ + \ + codegen_flags_changed = 1; \ + return op_pc + 1; \ + } \ + static uint32_t \ + rop##name##_w_rmw(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block) \ + { \ + int src_reg; \ + int dst_reg; \ + x86seg *target_seg; \ + \ + if ((fetchdat & 0xc0) == 0xc0) { \ + dst_reg = LOAD_REG_W(fetchdat & 7); \ + } else { \ + target_seg = FETCH_EA(op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32); \ + STORE_IMM_ADDR_L((uintptr_t) &cpu_state.oldpc, op_old_pc); \ + SAVE_EA(); \ + MEM_CHECK_WRITE_W(target_seg); \ + dst_reg = MEM_LOAD_ADDR_EA_W_NO_ABRT(target_seg); \ + } \ + STORE_IMM_ADDR_L((uintptr_t) &cpu_state.flags_op, FLAGS_##op##16); \ + src_reg = LOAD_REG_W((fetchdat >> 3) & 7); \ + STORE_HOST_REG_ADDR_WL((uintptr_t) &cpu_state.flags_op1, dst_reg); \ + STORE_HOST_REG_ADDR_WL((uintptr_t) &cpu_state.flags_op2, src_reg); \ + op##_HOST_REG_W(dst_reg, src_reg); \ + STORE_HOST_REG_ADDR_WL((uintptr_t) &cpu_state.flags_res, dst_reg); \ + if (writeback) { \ + if ((fetchdat & 0xc0) == 0xc0) \ + STORE_REG_W_RELEASE(dst_reg); \ + else { \ + LOAD_EA(); \ + MEM_STORE_ADDR_EA_W_NO_ABRT(target_seg, dst_reg); \ + } \ + } else \ + RELEASE_REG(dst_reg); \ + RELEASE_REG(src_reg); \ + \ + codegen_flags_changed = 1; \ + return op_pc + 1; \ + } \ + static uint32_t \ + rop##name##_l_rmw(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block) \ + { \ + int src_reg; \ + int dst_reg; \ + x86seg *target_seg; \ + \ + if ((fetchdat & 0xc0) == 0xc0) { \ + dst_reg = LOAD_REG_L(fetchdat & 7); \ + } else { \ + target_seg = FETCH_EA(op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32); \ + STORE_IMM_ADDR_L((uintptr_t) &cpu_state.oldpc, op_old_pc); \ + SAVE_EA(); \ + MEM_CHECK_WRITE_L(target_seg); \ + dst_reg = MEM_LOAD_ADDR_EA_L_NO_ABRT(target_seg); \ + } \ + STORE_IMM_ADDR_L((uintptr_t) &cpu_state.flags_op, FLAGS_##op##32); \ + src_reg = LOAD_REG_L((fetchdat >> 3) & 7); \ + STORE_HOST_REG_ADDR((uintptr_t) &cpu_state.flags_op1, dst_reg); \ + STORE_HOST_REG_ADDR((uintptr_t) &cpu_state.flags_op2, src_reg); \ + op##_HOST_REG_L(dst_reg, src_reg); \ + STORE_HOST_REG_ADDR((uintptr_t) &cpu_state.flags_res, dst_reg); \ + if (writeback) { \ + if ((fetchdat & 0xc0) == 0xc0) \ + STORE_REG_L_RELEASE(dst_reg); \ + else { \ + LOAD_EA(); \ + MEM_STORE_ADDR_EA_L_NO_ABRT(target_seg, dst_reg); \ + } \ + } else \ + RELEASE_REG(dst_reg); \ + RELEASE_REG(src_reg); \ + \ + codegen_flags_changed = 1; \ + return op_pc + 1; \ + } -#define ROP_ARITH_RM(name, op, writeback) \ - static uint32_t rop ## name ## _b_rm(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block) \ - { \ - int src_reg, dst_reg; \ - \ - if ((fetchdat & 0xc0) == 0xc0) \ - { \ - src_reg = LOAD_REG_B(fetchdat & 7); \ - } \ - else \ - { \ - x86seg *target_seg = FETCH_EA(op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32); \ - STORE_IMM_ADDR_L((uintptr_t)&cpu_state.oldpc, op_old_pc); \ - MEM_LOAD_ADDR_EA_B(target_seg); \ - src_reg = 0; \ - } \ - \ - dst_reg = LOAD_REG_B((fetchdat >> 3) & 7); \ - STORE_IMM_ADDR_L((uintptr_t)&cpu_state.flags_op, FLAGS_ ## op ## 8); \ - STORE_HOST_REG_ADDR_BL((uintptr_t)&cpu_state.flags_op1, dst_reg); \ - STORE_HOST_REG_ADDR_BL((uintptr_t)&cpu_state.flags_op2, src_reg); \ - op ## _HOST_REG_B(dst_reg, src_reg); \ - STORE_HOST_REG_ADDR_BL((uintptr_t)&cpu_state.flags_res, dst_reg); \ - if (writeback) STORE_REG_B_RELEASE(dst_reg); \ - else RELEASE_REG(dst_reg); \ - RELEASE_REG(src_reg); \ - \ - codegen_flags_changed = 1; \ - return op_pc + 1; \ - } \ - static uint32_t rop ## name ## _w_rm(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block) \ - { \ - int src_reg, dst_reg; \ - \ - if ((fetchdat & 0xc0) == 0xc0) \ - { \ - src_reg = LOAD_REG_W(fetchdat & 7); \ - } \ - else \ - { \ - x86seg *target_seg = FETCH_EA(op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32); \ - STORE_IMM_ADDR_L((uintptr_t)&cpu_state.oldpc, op_old_pc); \ - MEM_LOAD_ADDR_EA_W(target_seg); \ - src_reg = 0; \ - } \ - \ - dst_reg = LOAD_REG_W((fetchdat >> 3) & 7); \ - STORE_IMM_ADDR_L((uintptr_t)&cpu_state.flags_op, FLAGS_ ## op ## 16); \ - STORE_HOST_REG_ADDR_WL((uintptr_t)&cpu_state.flags_op1, dst_reg); \ - STORE_HOST_REG_ADDR_WL((uintptr_t)&cpu_state.flags_op2, src_reg); \ - op ## _HOST_REG_W(dst_reg, src_reg); \ - STORE_HOST_REG_ADDR_WL((uintptr_t)&cpu_state.flags_res, dst_reg); \ - if (writeback) STORE_REG_W_RELEASE(dst_reg); \ - else RELEASE_REG(dst_reg); \ - RELEASE_REG(src_reg); \ - \ - codegen_flags_changed = 1; \ - return op_pc + 1; \ - } \ - static uint32_t rop ## name ## _l_rm(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block) \ - { \ - int src_reg, dst_reg; \ - \ - if ((fetchdat & 0xc0) == 0xc0) \ - { \ - src_reg = LOAD_REG_L(fetchdat & 7); \ - } \ - else \ - { \ - x86seg *target_seg = FETCH_EA(op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32); \ - STORE_IMM_ADDR_L((uintptr_t)&cpu_state.oldpc, op_old_pc); \ - MEM_LOAD_ADDR_EA_L(target_seg); \ - src_reg = 0; \ - } \ - \ - dst_reg = LOAD_REG_L((fetchdat >> 3) & 7); \ - STORE_IMM_ADDR_L((uintptr_t)&cpu_state.flags_op, FLAGS_ ## op ## 32); \ - STORE_HOST_REG_ADDR((uintptr_t)&cpu_state.flags_op1, dst_reg); \ - STORE_HOST_REG_ADDR((uintptr_t)&cpu_state.flags_op2, src_reg); \ - op ## _HOST_REG_L(dst_reg, src_reg); \ - STORE_HOST_REG_ADDR((uintptr_t)&cpu_state.flags_res, dst_reg); \ - if (writeback) STORE_REG_L_RELEASE(dst_reg); \ - else RELEASE_REG(dst_reg); \ - RELEASE_REG(src_reg); \ - \ - codegen_flags_changed = 1; \ - return op_pc + 1; \ - } +#define ROP_ARITH_RM(name, op, writeback) \ + static uint32_t \ + rop##name##_b_rm(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block) \ + { \ + int src_reg; \ + int dst_reg; \ + \ + if ((fetchdat & 0xc0) == 0xc0) { \ + src_reg = LOAD_REG_B(fetchdat & 7); \ + } else { \ + x86seg *target_seg = FETCH_EA(op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32); \ + STORE_IMM_ADDR_L((uintptr_t) &cpu_state.oldpc, op_old_pc); \ + MEM_LOAD_ADDR_EA_B(target_seg); \ + src_reg = 0; \ + } \ + \ + dst_reg = LOAD_REG_B((fetchdat >> 3) & 7); \ + STORE_IMM_ADDR_L((uintptr_t) &cpu_state.flags_op, FLAGS_##op##8); \ + STORE_HOST_REG_ADDR_BL((uintptr_t) &cpu_state.flags_op1, dst_reg); \ + STORE_HOST_REG_ADDR_BL((uintptr_t) &cpu_state.flags_op2, src_reg); \ + op##_HOST_REG_B(dst_reg, src_reg); \ + STORE_HOST_REG_ADDR_BL((uintptr_t) &cpu_state.flags_res, dst_reg); \ + if (writeback) \ + STORE_REG_B_RELEASE(dst_reg); \ + else \ + RELEASE_REG(dst_reg); \ + RELEASE_REG(src_reg); \ + \ + codegen_flags_changed = 1; \ + return op_pc + 1; \ + } \ + static uint32_t \ + rop##name##_w_rm(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block) \ + { \ + int src_reg; \ + int dst_reg; \ + \ + if ((fetchdat & 0xc0) == 0xc0) { \ + src_reg = LOAD_REG_W(fetchdat & 7); \ + } else { \ + x86seg *target_seg = FETCH_EA(op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32); \ + STORE_IMM_ADDR_L((uintptr_t) &cpu_state.oldpc, op_old_pc); \ + MEM_LOAD_ADDR_EA_W(target_seg); \ + src_reg = 0; \ + } \ + \ + dst_reg = LOAD_REG_W((fetchdat >> 3) & 7); \ + STORE_IMM_ADDR_L((uintptr_t) &cpu_state.flags_op, FLAGS_##op##16); \ + STORE_HOST_REG_ADDR_WL((uintptr_t) &cpu_state.flags_op1, dst_reg); \ + STORE_HOST_REG_ADDR_WL((uintptr_t) &cpu_state.flags_op2, src_reg); \ + op##_HOST_REG_W(dst_reg, src_reg); \ + STORE_HOST_REG_ADDR_WL((uintptr_t) &cpu_state.flags_res, dst_reg); \ + if (writeback) \ + STORE_REG_W_RELEASE(dst_reg); \ + else \ + RELEASE_REG(dst_reg); \ + RELEASE_REG(src_reg); \ + \ + codegen_flags_changed = 1; \ + return op_pc + 1; \ + } \ + static uint32_t \ + rop##name##_l_rm(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block) \ + { \ + int src_reg; \ + int dst_reg; \ + \ + if ((fetchdat & 0xc0) == 0xc0) { \ + src_reg = LOAD_REG_L(fetchdat & 7); \ + } else { \ + x86seg *target_seg = FETCH_EA(op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32); \ + STORE_IMM_ADDR_L((uintptr_t) &cpu_state.oldpc, op_old_pc); \ + MEM_LOAD_ADDR_EA_L(target_seg); \ + src_reg = 0; \ + } \ + \ + dst_reg = LOAD_REG_L((fetchdat >> 3) & 7); \ + STORE_IMM_ADDR_L((uintptr_t) &cpu_state.flags_op, FLAGS_##op##32); \ + STORE_HOST_REG_ADDR((uintptr_t) &cpu_state.flags_op1, dst_reg); \ + STORE_HOST_REG_ADDR((uintptr_t) &cpu_state.flags_op2, src_reg); \ + op##_HOST_REG_L(dst_reg, src_reg); \ + STORE_HOST_REG_ADDR((uintptr_t) &cpu_state.flags_res, dst_reg); \ + if (writeback) \ + STORE_REG_L_RELEASE(dst_reg); \ + else \ + RELEASE_REG(dst_reg); \ + RELEASE_REG(src_reg); \ + \ + codegen_flags_changed = 1; \ + return op_pc + 1; \ + } ROP_ARITH_RMW(ADD, ADD, 1) ROP_ARITH_RMW(SUB, SUB, 1) ROP_ARITH_RM(ADD, ADD, 1) ROP_ARITH_RM(SUB, SUB, 1) -static uint32_t ropCMP_b_rm(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block) +static uint32_t +ropCMP_b_rm(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block) { - int src_reg, dst_reg; + int src_reg; + int dst_reg; - if ((fetchdat & 0xc0) == 0xc0) - { - src_reg = LOAD_REG_B(fetchdat & 7); - } - else - { - x86seg *target_seg = FETCH_EA(op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32); - STORE_IMM_ADDR_L((uintptr_t)&cpu_state.oldpc, op_old_pc); - MEM_LOAD_ADDR_EA_B(target_seg); - src_reg = 0; - } + if ((fetchdat & 0xc0) == 0xc0) { + src_reg = LOAD_REG_B(fetchdat & 7); + } else { + x86seg *target_seg = FETCH_EA(op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32); + STORE_IMM_ADDR_L((uintptr_t) &cpu_state.oldpc, op_old_pc); + MEM_LOAD_ADDR_EA_B(target_seg); + src_reg = 0; + } - dst_reg = LOAD_REG_B((fetchdat >> 3) & 7); - STORE_IMM_ADDR_L((uintptr_t)&cpu_state.flags_op, FLAGS_SUB8); - STORE_HOST_REG_ADDR_BL((uintptr_t)&cpu_state.flags_op1, dst_reg); - dst_reg = CMP_HOST_REG_B(dst_reg, src_reg); - STORE_HOST_REG_ADDR_BL((uintptr_t)&cpu_state.flags_op2, src_reg); - STORE_HOST_REG_ADDR_BL((uintptr_t)&cpu_state.flags_res, dst_reg); - RELEASE_REG(dst_reg); - RELEASE_REG(src_reg); + dst_reg = LOAD_REG_B((fetchdat >> 3) & 7); + STORE_IMM_ADDR_L((uintptr_t) &cpu_state.flags_op, FLAGS_SUB8); + STORE_HOST_REG_ADDR_BL((uintptr_t) &cpu_state.flags_op1, dst_reg); + dst_reg = CMP_HOST_REG_B(dst_reg, src_reg); + STORE_HOST_REG_ADDR_BL((uintptr_t) &cpu_state.flags_op2, src_reg); + STORE_HOST_REG_ADDR_BL((uintptr_t) &cpu_state.flags_res, dst_reg); + RELEASE_REG(dst_reg); + RELEASE_REG(src_reg); - codegen_flags_changed = 1; - return op_pc + 1; + codegen_flags_changed = 1; + return op_pc + 1; } -static uint32_t ropCMP_w_rm(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block) +static uint32_t +ropCMP_w_rm(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block) { - int src_reg, dst_reg; + int src_reg; + int dst_reg; - if ((fetchdat & 0xc0) == 0xc0) - { - src_reg = LOAD_REG_W(fetchdat & 7); - } - else - { - x86seg *target_seg = FETCH_EA(op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32); - STORE_IMM_ADDR_L((uintptr_t)&cpu_state.oldpc, op_old_pc); - MEM_LOAD_ADDR_EA_W(target_seg); - src_reg = 0; - } + if ((fetchdat & 0xc0) == 0xc0) { + src_reg = LOAD_REG_W(fetchdat & 7); + } else { + x86seg *target_seg = FETCH_EA(op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32); + STORE_IMM_ADDR_L((uintptr_t) &cpu_state.oldpc, op_old_pc); + MEM_LOAD_ADDR_EA_W(target_seg); + src_reg = 0; + } - dst_reg = LOAD_REG_W((fetchdat >> 3) & 7); - STORE_IMM_ADDR_L((uintptr_t)&cpu_state.flags_op, FLAGS_SUB16); - STORE_HOST_REG_ADDR_WL((uintptr_t)&cpu_state.flags_op1, dst_reg); - dst_reg = CMP_HOST_REG_W(dst_reg, src_reg); - STORE_HOST_REG_ADDR_WL((uintptr_t)&cpu_state.flags_op2, src_reg); - STORE_HOST_REG_ADDR_WL((uintptr_t)&cpu_state.flags_res, dst_reg); - RELEASE_REG(dst_reg); - RELEASE_REG(src_reg); + dst_reg = LOAD_REG_W((fetchdat >> 3) & 7); + STORE_IMM_ADDR_L((uintptr_t) &cpu_state.flags_op, FLAGS_SUB16); + STORE_HOST_REG_ADDR_WL((uintptr_t) &cpu_state.flags_op1, dst_reg); + dst_reg = CMP_HOST_REG_W(dst_reg, src_reg); + STORE_HOST_REG_ADDR_WL((uintptr_t) &cpu_state.flags_op2, src_reg); + STORE_HOST_REG_ADDR_WL((uintptr_t) &cpu_state.flags_res, dst_reg); + RELEASE_REG(dst_reg); + RELEASE_REG(src_reg); - codegen_flags_changed = 1; - return op_pc + 1; + codegen_flags_changed = 1; + return op_pc + 1; } -static uint32_t ropCMP_l_rm(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block) +static uint32_t +ropCMP_l_rm(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block) { - int src_reg, dst_reg; + int src_reg; + int dst_reg; - if ((fetchdat & 0xc0) == 0xc0) - { - src_reg = LOAD_REG_L(fetchdat & 7); - } - else - { - x86seg *target_seg = FETCH_EA(op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32); - STORE_IMM_ADDR_L((uintptr_t)&cpu_state.oldpc, op_old_pc); - MEM_LOAD_ADDR_EA_L(target_seg); - src_reg = 0; - } + if ((fetchdat & 0xc0) == 0xc0) { + src_reg = LOAD_REG_L(fetchdat & 7); + } else { + x86seg *target_seg = FETCH_EA(op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32); + STORE_IMM_ADDR_L((uintptr_t) &cpu_state.oldpc, op_old_pc); + MEM_LOAD_ADDR_EA_L(target_seg); + src_reg = 0; + } - dst_reg = LOAD_REG_L((fetchdat >> 3) & 7); - STORE_IMM_ADDR_L((uintptr_t)&cpu_state.flags_op, FLAGS_SUB32); - STORE_HOST_REG_ADDR((uintptr_t)&cpu_state.flags_op1, dst_reg); - dst_reg = CMP_HOST_REG_L(dst_reg, src_reg); - STORE_HOST_REG_ADDR((uintptr_t)&cpu_state.flags_op2, src_reg); - STORE_HOST_REG_ADDR((uintptr_t)&cpu_state.flags_res, dst_reg); - RELEASE_REG(dst_reg); - RELEASE_REG(src_reg); + dst_reg = LOAD_REG_L((fetchdat >> 3) & 7); + STORE_IMM_ADDR_L((uintptr_t) &cpu_state.flags_op, FLAGS_SUB32); + STORE_HOST_REG_ADDR((uintptr_t) &cpu_state.flags_op1, dst_reg); + dst_reg = CMP_HOST_REG_L(dst_reg, src_reg); + STORE_HOST_REG_ADDR((uintptr_t) &cpu_state.flags_op2, src_reg); + STORE_HOST_REG_ADDR((uintptr_t) &cpu_state.flags_res, dst_reg); + RELEASE_REG(dst_reg); + RELEASE_REG(src_reg); - codegen_flags_changed = 1; - return op_pc + 1; + codegen_flags_changed = 1; + return op_pc + 1; } -static uint32_t ropCMP_b_rmw(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block) +static uint32_t +ropCMP_b_rmw(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block) { - int src_reg, dst_reg; + int src_reg; + int dst_reg; - if ((fetchdat & 0xc0) == 0xc0) - { - dst_reg = LOAD_REG_B(fetchdat & 7); + if ((fetchdat & 0xc0) == 0xc0) { + dst_reg = LOAD_REG_B(fetchdat & 7); + } else { + x86seg *target_seg = FETCH_EA(op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32); + STORE_IMM_ADDR_L((uintptr_t) &cpu_state.oldpc, op_old_pc); + MEM_LOAD_ADDR_EA_B(target_seg); + dst_reg = 0; + } + + STORE_IMM_ADDR_L((uintptr_t) &cpu_state.flags_op, FLAGS_SUB8); + src_reg = LOAD_REG_B((fetchdat >> 3) & 7); + STORE_HOST_REG_ADDR_BL((uintptr_t) &cpu_state.flags_op1, dst_reg); + dst_reg = CMP_HOST_REG_B(dst_reg, src_reg); + STORE_HOST_REG_ADDR_BL((uintptr_t) &cpu_state.flags_op2, src_reg); + STORE_HOST_REG_ADDR_BL((uintptr_t) &cpu_state.flags_res, dst_reg); + RELEASE_REG(dst_reg); + RELEASE_REG(src_reg); + + codegen_flags_changed = 1; + return op_pc + 1; +} +static uint32_t +ropCMP_w_rmw(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block) +{ + int src_reg; + int dst_reg; + + if ((fetchdat & 0xc0) == 0xc0) { + dst_reg = LOAD_REG_W(fetchdat & 7); + } else { + x86seg *target_seg = FETCH_EA(op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32); + STORE_IMM_ADDR_L((uintptr_t) &cpu_state.oldpc, op_old_pc); + MEM_LOAD_ADDR_EA_W(target_seg); + dst_reg = 0; + } + + STORE_IMM_ADDR_L((uintptr_t) &cpu_state.flags_op, FLAGS_SUB16); + src_reg = LOAD_REG_W((fetchdat >> 3) & 7); + STORE_HOST_REG_ADDR_WL((uintptr_t) &cpu_state.flags_op1, dst_reg); + dst_reg = CMP_HOST_REG_W(dst_reg, src_reg); + STORE_HOST_REG_ADDR_WL((uintptr_t) &cpu_state.flags_op2, src_reg); + STORE_HOST_REG_ADDR_WL((uintptr_t) &cpu_state.flags_res, dst_reg); + RELEASE_REG(dst_reg); + RELEASE_REG(src_reg); + + codegen_flags_changed = 1; + return op_pc + 1; +} +static uint32_t +ropCMP_l_rmw(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block) +{ + int src_reg; + int dst_reg; + + if ((fetchdat & 0xc0) == 0xc0) { + dst_reg = LOAD_REG_L(fetchdat & 7); + } else { + x86seg *target_seg = FETCH_EA(op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32); + STORE_IMM_ADDR_L((uintptr_t) &cpu_state.oldpc, op_old_pc); + MEM_LOAD_ADDR_EA_L(target_seg); + dst_reg = 0; + } + + STORE_IMM_ADDR_L((uintptr_t) &cpu_state.flags_op, FLAGS_SUB32); + src_reg = LOAD_REG_L((fetchdat >> 3) & 7); + STORE_HOST_REG_ADDR((uintptr_t) &cpu_state.flags_op1, dst_reg); + dst_reg = CMP_HOST_REG_L(dst_reg, src_reg); + STORE_HOST_REG_ADDR((uintptr_t) &cpu_state.flags_op2, src_reg); + STORE_HOST_REG_ADDR((uintptr_t) &cpu_state.flags_res, dst_reg); + RELEASE_REG(dst_reg); + RELEASE_REG(src_reg); + + codegen_flags_changed = 1; + return op_pc + 1; +} + +static uint32_t +ropADD_AL_imm(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block) +{ + int host_reg = LOAD_REG_B(REG_AL); + + STORE_HOST_REG_ADDR_BL((uintptr_t) &cpu_state.flags_op1, host_reg); + ADD_HOST_REG_IMM_B(host_reg, fetchdat & 0xff); + STORE_IMM_ADDR_L((uintptr_t) &cpu_state.flags_op2, fetchdat & 0xff); + STORE_IMM_ADDR_L((uintptr_t) &cpu_state.flags_op, FLAGS_ADD8); + STORE_HOST_REG_ADDR_BL((uintptr_t) &cpu_state.flags_res, host_reg); + STORE_REG_B_RELEASE(host_reg); + + codegen_flags_changed = 1; + return op_pc + 1; +} +static uint32_t +ropADD_AX_imm(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block) +{ + int host_reg = LOAD_REG_W(REG_AX); + + STORE_HOST_REG_ADDR_WL((uintptr_t) &cpu_state.flags_op1, host_reg); + ADD_HOST_REG_IMM_W(host_reg, fetchdat & 0xffff); + STORE_IMM_ADDR_L((uintptr_t) &cpu_state.flags_op2, fetchdat & 0xffff); + STORE_IMM_ADDR_L((uintptr_t) &cpu_state.flags_op, FLAGS_ADD16); + STORE_HOST_REG_ADDR_WL((uintptr_t) &cpu_state.flags_res, host_reg); + STORE_REG_W_RELEASE(host_reg); + + codegen_flags_changed = 1; + return op_pc + 2; +} +static uint32_t +ropADD_EAX_imm(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block) +{ + int host_reg = LOAD_REG_L(REG_EAX); + + STORE_HOST_REG_ADDR((uintptr_t) &cpu_state.flags_op1, host_reg); + fetchdat = fastreadl(cs + op_pc); + ADD_HOST_REG_IMM(host_reg, fetchdat); + STORE_IMM_ADDR_L((uintptr_t) &cpu_state.flags_op2, fetchdat); + STORE_IMM_ADDR_L((uintptr_t) &cpu_state.flags_op, FLAGS_ADD32); + STORE_HOST_REG_ADDR((uintptr_t) &cpu_state.flags_res, host_reg); + STORE_REG_L_RELEASE(host_reg); + + codegen_flags_changed = 1; + return op_pc + 4; +} + +static uint32_t +ropCMP_AL_imm(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block) +{ + int host_reg = LOAD_REG_B(REG_AL); + + STORE_HOST_REG_ADDR_BL((uintptr_t) &cpu_state.flags_op1, host_reg); + host_reg = CMP_HOST_REG_IMM_B(host_reg, fetchdat & 0xff); + STORE_IMM_ADDR_L((uintptr_t) &cpu_state.flags_op2, fetchdat & 0xff); + STORE_IMM_ADDR_L((uintptr_t) &cpu_state.flags_op, FLAGS_SUB8); + STORE_HOST_REG_ADDR_BL((uintptr_t) &cpu_state.flags_res, host_reg); + RELEASE_REG(host_reg); + + codegen_flags_changed = 1; + return op_pc + 1; +} +static uint32_t +ropCMP_AX_imm(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block) +{ + int host_reg = LOAD_REG_W(REG_AX); + + STORE_HOST_REG_ADDR_WL((uintptr_t) &cpu_state.flags_op1, host_reg); + host_reg = CMP_HOST_REG_IMM_W(host_reg, fetchdat & 0xffff); + STORE_IMM_ADDR_L((uintptr_t) &cpu_state.flags_op2, fetchdat & 0xffff); + STORE_IMM_ADDR_L((uintptr_t) &cpu_state.flags_op, FLAGS_SUB16); + STORE_HOST_REG_ADDR_WL((uintptr_t) &cpu_state.flags_res, host_reg); + RELEASE_REG(host_reg); + + codegen_flags_changed = 1; + return op_pc + 2; +} +static uint32_t +ropCMP_EAX_imm(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block) +{ + int host_reg = LOAD_REG_L(REG_EAX); + + STORE_HOST_REG_ADDR((uintptr_t) &cpu_state.flags_op1, host_reg); + fetchdat = fastreadl(cs + op_pc); + host_reg = CMP_HOST_REG_IMM_L(host_reg, fetchdat); + STORE_IMM_ADDR_L((uintptr_t) &cpu_state.flags_op2, fetchdat); + STORE_IMM_ADDR_L((uintptr_t) &cpu_state.flags_op, FLAGS_SUB32); + STORE_HOST_REG_ADDR((uintptr_t) &cpu_state.flags_res, host_reg); + RELEASE_REG(host_reg); + + codegen_flags_changed = 1; + return op_pc + 4; +} + +static uint32_t +ropSUB_AL_imm(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block) +{ + int host_reg = LOAD_REG_B(REG_AL); + + STORE_HOST_REG_ADDR_BL((uintptr_t) &cpu_state.flags_op1, host_reg); + SUB_HOST_REG_IMM_B(host_reg, fetchdat & 0xff); + STORE_IMM_ADDR_L((uintptr_t) &cpu_state.flags_op2, fetchdat & 0xff); + STORE_IMM_ADDR_L((uintptr_t) &cpu_state.flags_op, FLAGS_SUB8); + STORE_HOST_REG_ADDR_BL((uintptr_t) &cpu_state.flags_res, host_reg); + STORE_REG_B_RELEASE(host_reg); + + codegen_flags_changed = 1; + return op_pc + 1; +} +static uint32_t +ropSUB_AX_imm(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block) +{ + int host_reg = LOAD_REG_W(REG_AX); + + STORE_HOST_REG_ADDR_WL((uintptr_t) &cpu_state.flags_op1, host_reg); + SUB_HOST_REG_IMM_W(host_reg, fetchdat & 0xffff); + STORE_IMM_ADDR_L((uintptr_t) &cpu_state.flags_op2, fetchdat & 0xffff); + STORE_IMM_ADDR_L((uintptr_t) &cpu_state.flags_op, FLAGS_SUB16); + STORE_HOST_REG_ADDR_WL((uintptr_t) &cpu_state.flags_res, host_reg); + STORE_REG_W_RELEASE(host_reg); + + codegen_flags_changed = 1; + return op_pc + 2; +} +static uint32_t +ropSUB_EAX_imm(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block) +{ + int host_reg = LOAD_REG_L(REG_EAX); + + STORE_HOST_REG_ADDR((uintptr_t) &cpu_state.flags_op1, host_reg); + fetchdat = fastreadl(cs + op_pc); + SUB_HOST_REG_IMM(host_reg, fetchdat); + STORE_IMM_ADDR_L((uintptr_t) &cpu_state.flags_op2, fetchdat); + STORE_IMM_ADDR_L((uintptr_t) &cpu_state.flags_op, FLAGS_SUB32); + STORE_HOST_REG_ADDR((uintptr_t) &cpu_state.flags_res, host_reg); + STORE_REG_L_RELEASE(host_reg); + + codegen_flags_changed = 1; + return op_pc + 4; +} + +static uint32_t +rop80(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block) +{ + int host_reg; + uint32_t imm; + x86seg *target_seg = NULL; + + if ((fetchdat & 0x30) == 0x10) + return 0; + + if ((fetchdat & 0xc0) != 0xc0) { + target_seg = FETCH_EA(op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32); + STORE_IMM_ADDR_L((uintptr_t) &cpu_state.oldpc, op_old_pc); + if ((fetchdat & 0x38) == 0x38) { + MEM_LOAD_ADDR_EA_B(target_seg); + host_reg = 0; + } else { + SAVE_EA(); + MEM_CHECK_WRITE(target_seg); + host_reg = MEM_LOAD_ADDR_EA_B_NO_ABRT(target_seg); } - else - { - x86seg *target_seg = FETCH_EA(op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32); - STORE_IMM_ADDR_L((uintptr_t)&cpu_state.oldpc, op_old_pc); - MEM_LOAD_ADDR_EA_B(target_seg); - dst_reg = 0; + imm = fastreadb(cs + op_pc + 1); + } else { + host_reg = LOAD_REG_B(fetchdat & 7); + imm = (fetchdat >> 8) & 0xff; + } + + switch (fetchdat & 0x38) { + case 0x00: /*ADD*/ + STORE_HOST_REG_ADDR_BL((uintptr_t) &cpu_state.flags_op1, host_reg); + ADD_HOST_REG_IMM_B(host_reg, imm); + STORE_IMM_ADDR_L((uintptr_t) &cpu_state.flags_op2, imm); + STORE_IMM_ADDR_L((uintptr_t) &cpu_state.flags_op, FLAGS_ADD8); + break; + case 0x08: /*OR*/ + OR_HOST_REG_IMM(host_reg, imm); + STORE_IMM_ADDR_L((uintptr_t) &cpu_state.flags_op, FLAGS_ZN8); + break; + case 0x20: /*AND*/ + AND_HOST_REG_IMM(host_reg, imm | 0xffffff00); + STORE_IMM_ADDR_L((uintptr_t) &cpu_state.flags_op, FLAGS_ZN8); + break; + case 0x28: /*SUB*/ + STORE_HOST_REG_ADDR_BL((uintptr_t) &cpu_state.flags_op1, host_reg); + SUB_HOST_REG_IMM_B(host_reg, imm); + STORE_IMM_ADDR_L((uintptr_t) &cpu_state.flags_op2, imm); + STORE_IMM_ADDR_L((uintptr_t) &cpu_state.flags_op, FLAGS_SUB8); + break; + case 0x30: /*XOR*/ + XOR_HOST_REG_IMM(host_reg, imm); + STORE_IMM_ADDR_L((uintptr_t) &cpu_state.flags_op, FLAGS_ZN8); + break; + case 0x38: /*CMP*/ + STORE_HOST_REG_ADDR_BL((uintptr_t) &cpu_state.flags_op1, host_reg); + host_reg = CMP_HOST_REG_IMM_B(host_reg, imm); + STORE_IMM_ADDR_L((uintptr_t) &cpu_state.flags_op2, imm); + STORE_IMM_ADDR_L((uintptr_t) &cpu_state.flags_op, FLAGS_SUB8); + break; + } + + STORE_HOST_REG_ADDR_BL((uintptr_t) &cpu_state.flags_res, host_reg); + if ((fetchdat & 0x38) != 0x38) { + if ((fetchdat & 0xc0) != 0xc0) { + LOAD_EA(); + MEM_STORE_ADDR_EA_B_NO_ABRT(target_seg, host_reg); + } else { + STORE_REG_B_RELEASE(host_reg); } - - STORE_IMM_ADDR_L((uintptr_t)&cpu_state.flags_op, FLAGS_SUB8); - src_reg = LOAD_REG_B((fetchdat >> 3) & 7); - STORE_HOST_REG_ADDR_BL((uintptr_t)&cpu_state.flags_op1, dst_reg); - dst_reg = CMP_HOST_REG_B(dst_reg, src_reg); - STORE_HOST_REG_ADDR_BL((uintptr_t)&cpu_state.flags_op2, src_reg); - STORE_HOST_REG_ADDR_BL((uintptr_t)&cpu_state.flags_res, dst_reg); - RELEASE_REG(dst_reg); - RELEASE_REG(src_reg); - - codegen_flags_changed = 1; - return op_pc + 1; -} -static uint32_t ropCMP_w_rmw(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block) -{ - int src_reg, dst_reg; - - if ((fetchdat & 0xc0) == 0xc0) - { - dst_reg = LOAD_REG_W(fetchdat & 7); - } - else - { - x86seg *target_seg = FETCH_EA(op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32); - STORE_IMM_ADDR_L((uintptr_t)&cpu_state.oldpc, op_old_pc); - MEM_LOAD_ADDR_EA_W(target_seg); - dst_reg = 0; - } \ - - STORE_IMM_ADDR_L((uintptr_t)&cpu_state.flags_op, FLAGS_SUB16); - src_reg = LOAD_REG_W((fetchdat >> 3) & 7); - STORE_HOST_REG_ADDR_WL((uintptr_t)&cpu_state.flags_op1, dst_reg); - dst_reg = CMP_HOST_REG_W(dst_reg, src_reg); - STORE_HOST_REG_ADDR_WL((uintptr_t)&cpu_state.flags_op2, src_reg); - STORE_HOST_REG_ADDR_WL((uintptr_t)&cpu_state.flags_res, dst_reg); - RELEASE_REG(dst_reg); - RELEASE_REG(src_reg); - - codegen_flags_changed = 1; - return op_pc + 1; -} -static uint32_t ropCMP_l_rmw(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block) -{ - int src_reg, dst_reg; - - if ((fetchdat & 0xc0) == 0xc0) - { - dst_reg = LOAD_REG_L(fetchdat & 7); - } - else - { - x86seg *target_seg = FETCH_EA(op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32); - STORE_IMM_ADDR_L((uintptr_t)&cpu_state.oldpc, op_old_pc); - MEM_LOAD_ADDR_EA_L(target_seg); - dst_reg = 0; - } - - STORE_IMM_ADDR_L((uintptr_t)&cpu_state.flags_op, FLAGS_SUB32); - src_reg = LOAD_REG_L((fetchdat >> 3) & 7); - STORE_HOST_REG_ADDR((uintptr_t)&cpu_state.flags_op1, dst_reg); - dst_reg = CMP_HOST_REG_L(dst_reg, src_reg); - STORE_HOST_REG_ADDR((uintptr_t)&cpu_state.flags_op2, src_reg); - STORE_HOST_REG_ADDR((uintptr_t)&cpu_state.flags_res, dst_reg); - RELEASE_REG(dst_reg); - RELEASE_REG(src_reg); - - codegen_flags_changed = 1; - return op_pc + 1; -} - - -static uint32_t ropADD_AL_imm(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block) -{ - int host_reg = LOAD_REG_B(REG_AL); - - STORE_HOST_REG_ADDR_BL((uintptr_t)&cpu_state.flags_op1, host_reg); - ADD_HOST_REG_IMM_B(host_reg, fetchdat & 0xff); - STORE_IMM_ADDR_L((uintptr_t)&cpu_state.flags_op2, fetchdat & 0xff); - STORE_IMM_ADDR_L((uintptr_t)&cpu_state.flags_op, FLAGS_ADD8); - STORE_HOST_REG_ADDR_BL((uintptr_t)&cpu_state.flags_res, host_reg); - STORE_REG_B_RELEASE(host_reg); - - codegen_flags_changed = 1; - return op_pc + 1; -} -static uint32_t ropADD_AX_imm(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block) -{ - int host_reg = LOAD_REG_W(REG_AX); - - STORE_HOST_REG_ADDR_WL((uintptr_t)&cpu_state.flags_op1, host_reg); - ADD_HOST_REG_IMM_W(host_reg, fetchdat & 0xffff); - STORE_IMM_ADDR_L((uintptr_t)&cpu_state.flags_op2, fetchdat & 0xffff); - STORE_IMM_ADDR_L((uintptr_t)&cpu_state.flags_op, FLAGS_ADD16); - STORE_HOST_REG_ADDR_WL((uintptr_t)&cpu_state.flags_res, host_reg); - STORE_REG_W_RELEASE(host_reg); - - codegen_flags_changed = 1; - return op_pc + 2; -} -static uint32_t ropADD_EAX_imm(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block) -{ - int host_reg = LOAD_REG_L(REG_EAX); - - STORE_HOST_REG_ADDR((uintptr_t)&cpu_state.flags_op1, host_reg); - fetchdat = fastreadl(cs + op_pc); - ADD_HOST_REG_IMM(host_reg, fetchdat); - STORE_IMM_ADDR_L((uintptr_t)&cpu_state.flags_op2, fetchdat); - STORE_IMM_ADDR_L((uintptr_t)&cpu_state.flags_op, FLAGS_ADD32); - STORE_HOST_REG_ADDR((uintptr_t)&cpu_state.flags_res, host_reg); - STORE_REG_L_RELEASE(host_reg); - - codegen_flags_changed = 1; - return op_pc + 4; -} - -static uint32_t ropCMP_AL_imm(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block) -{ - int host_reg = LOAD_REG_B(REG_AL); - - STORE_HOST_REG_ADDR_BL((uintptr_t)&cpu_state.flags_op1, host_reg); - host_reg = CMP_HOST_REG_IMM_B(host_reg, fetchdat & 0xff); - STORE_IMM_ADDR_L((uintptr_t)&cpu_state.flags_op2, fetchdat & 0xff); - STORE_IMM_ADDR_L((uintptr_t)&cpu_state.flags_op, FLAGS_SUB8); - STORE_HOST_REG_ADDR_BL((uintptr_t)&cpu_state.flags_res, host_reg); + } else RELEASE_REG(host_reg); - - codegen_flags_changed = 1; - return op_pc + 1; + + codegen_flags_changed = 1; + return op_pc + 2; } -static uint32_t ropCMP_AX_imm(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block) + +static uint32_t +rop81_w(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block) { - int host_reg = LOAD_REG_W(REG_AX); - - STORE_HOST_REG_ADDR_WL((uintptr_t)&cpu_state.flags_op1, host_reg); - host_reg = CMP_HOST_REG_IMM_W(host_reg, fetchdat & 0xffff); - STORE_IMM_ADDR_L((uintptr_t)&cpu_state.flags_op2, fetchdat & 0xffff); - STORE_IMM_ADDR_L((uintptr_t)&cpu_state.flags_op, FLAGS_SUB16); - STORE_HOST_REG_ADDR_WL((uintptr_t)&cpu_state.flags_res, host_reg); + int host_reg; + uint32_t imm; + x86seg *target_seg = NULL; + + if ((fetchdat & 0x30) == 0x10) + return 0; + + if ((fetchdat & 0xc0) != 0xc0) { + target_seg = FETCH_EA(op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32); + STORE_IMM_ADDR_L((uintptr_t) &cpu_state.oldpc, op_old_pc); + if ((fetchdat & 0x38) == 0x38) { + MEM_LOAD_ADDR_EA_W(target_seg); + host_reg = 0; + } else { + SAVE_EA(); + MEM_CHECK_WRITE_W(target_seg); + host_reg = MEM_LOAD_ADDR_EA_W_NO_ABRT(target_seg); + } + imm = fastreadw(cs + op_pc + 1); + } else { + host_reg = LOAD_REG_W(fetchdat & 7); + imm = (fetchdat >> 8) & 0xffff; + } + + switch (fetchdat & 0x38) { + case 0x00: /*ADD*/ + STORE_HOST_REG_ADDR_WL((uintptr_t) &cpu_state.flags_op1, host_reg); + ADD_HOST_REG_IMM_W(host_reg, imm); + STORE_IMM_ADDR_L((uintptr_t) &cpu_state.flags_op2, imm); + STORE_IMM_ADDR_L((uintptr_t) &cpu_state.flags_op, FLAGS_ADD16); + break; + case 0x08: /*OR*/ + OR_HOST_REG_IMM(host_reg, imm); + STORE_IMM_ADDR_L((uintptr_t) &cpu_state.flags_op, FLAGS_ZN16); + break; + case 0x20: /*AND*/ + AND_HOST_REG_IMM(host_reg, imm | 0xffff0000); + STORE_IMM_ADDR_L((uintptr_t) &cpu_state.flags_op, FLAGS_ZN16); + break; + case 0x28: /*SUB*/ + STORE_HOST_REG_ADDR_WL((uintptr_t) &cpu_state.flags_op1, host_reg); + SUB_HOST_REG_IMM_W(host_reg, imm); + STORE_IMM_ADDR_L((uintptr_t) &cpu_state.flags_op2, imm); + STORE_IMM_ADDR_L((uintptr_t) &cpu_state.flags_op, FLAGS_SUB16); + break; + case 0x30: /*XOR*/ + XOR_HOST_REG_IMM(host_reg, imm); + STORE_IMM_ADDR_L((uintptr_t) &cpu_state.flags_op, FLAGS_ZN16); + break; + case 0x38: /*CMP*/ + STORE_HOST_REG_ADDR_WL((uintptr_t) &cpu_state.flags_op1, host_reg); + host_reg = CMP_HOST_REG_IMM_W(host_reg, imm); + STORE_IMM_ADDR_L((uintptr_t) &cpu_state.flags_op2, imm); + STORE_IMM_ADDR_L((uintptr_t) &cpu_state.flags_op, FLAGS_SUB16); + break; + } + + STORE_HOST_REG_ADDR_WL((uintptr_t) &cpu_state.flags_res, host_reg); + if ((fetchdat & 0x38) != 0x38) { + if ((fetchdat & 0xc0) != 0xc0) { + LOAD_EA(); + MEM_STORE_ADDR_EA_W_NO_ABRT(target_seg, host_reg); + } else { + STORE_REG_W_RELEASE(host_reg); + } + } else RELEASE_REG(host_reg); - - codegen_flags_changed = 1; - return op_pc + 2; -} -static uint32_t ropCMP_EAX_imm(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block) -{ - int host_reg = LOAD_REG_L(REG_EAX); - STORE_HOST_REG_ADDR((uintptr_t)&cpu_state.flags_op1, host_reg); - fetchdat = fastreadl(cs + op_pc); - host_reg = CMP_HOST_REG_IMM_L(host_reg, fetchdat); - STORE_IMM_ADDR_L((uintptr_t)&cpu_state.flags_op2, fetchdat); - STORE_IMM_ADDR_L((uintptr_t)&cpu_state.flags_op, FLAGS_SUB32); - STORE_HOST_REG_ADDR((uintptr_t)&cpu_state.flags_res, host_reg); + codegen_flags_changed = 1; + return op_pc + 3; +} +static uint32_t +rop81_l(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block) +{ + int host_reg; + uint32_t imm; + x86seg *target_seg = NULL; + + if ((fetchdat & 0x30) == 0x10) + return 0; + + if ((fetchdat & 0xc0) != 0xc0) { + target_seg = FETCH_EA(op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32); + STORE_IMM_ADDR_L((uintptr_t) &cpu_state.oldpc, op_old_pc); + if ((fetchdat & 0x38) == 0x38) { + MEM_LOAD_ADDR_EA_L(target_seg); + host_reg = 0; + } else { + SAVE_EA(); + MEM_CHECK_WRITE_L(target_seg); + host_reg = MEM_LOAD_ADDR_EA_L_NO_ABRT(target_seg); + } + } else { + host_reg = LOAD_REG_L(fetchdat & 7); + } + imm = fastreadl(cs + op_pc + 1); + + switch (fetchdat & 0x38) { + case 0x00: /*ADD*/ + STORE_HOST_REG_ADDR((uintptr_t) &cpu_state.flags_op1, host_reg); + ADD_HOST_REG_IMM(host_reg, imm); + STORE_IMM_ADDR_L((uintptr_t) &cpu_state.flags_op2, imm); + STORE_IMM_ADDR_L((uintptr_t) &cpu_state.flags_op, FLAGS_ADD32); + break; + case 0x08: /*OR*/ + OR_HOST_REG_IMM(host_reg, imm); + STORE_IMM_ADDR_L((uintptr_t) &cpu_state.flags_op, FLAGS_ZN32); + break; + case 0x20: /*AND*/ + AND_HOST_REG_IMM(host_reg, imm); + STORE_IMM_ADDR_L((uintptr_t) &cpu_state.flags_op, FLAGS_ZN32); + break; + case 0x28: /*SUB*/ + STORE_HOST_REG_ADDR((uintptr_t) &cpu_state.flags_op1, host_reg); + SUB_HOST_REG_IMM(host_reg, imm); + STORE_IMM_ADDR_L((uintptr_t) &cpu_state.flags_op2, imm); + STORE_IMM_ADDR_L((uintptr_t) &cpu_state.flags_op, FLAGS_SUB32); + break; + case 0x30: /*XOR*/ + XOR_HOST_REG_IMM(host_reg, imm); + STORE_IMM_ADDR_L((uintptr_t) &cpu_state.flags_op, FLAGS_ZN32); + break; + case 0x38: /*CMP*/ + STORE_HOST_REG_ADDR((uintptr_t) &cpu_state.flags_op1, host_reg); + host_reg = CMP_HOST_REG_IMM_L(host_reg, imm); + STORE_IMM_ADDR_L((uintptr_t) &cpu_state.flags_op2, imm); + STORE_IMM_ADDR_L((uintptr_t) &cpu_state.flags_op, FLAGS_SUB32); + break; + } + + STORE_HOST_REG_ADDR((uintptr_t) &cpu_state.flags_res, host_reg); + if ((fetchdat & 0x38) != 0x38) { + if ((fetchdat & 0xc0) != 0xc0) { + LOAD_EA(); + MEM_STORE_ADDR_EA_L_NO_ABRT(target_seg, host_reg); + } else { + STORE_REG_L_RELEASE(host_reg); + } + } else RELEASE_REG(host_reg); - - codegen_flags_changed = 1; - return op_pc + 4; + + codegen_flags_changed = 1; + return op_pc + 5; } -static uint32_t ropSUB_AL_imm(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block) +static uint32_t +rop83_w(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block) { - int host_reg = LOAD_REG_B(REG_AL); + int host_reg; + uint32_t imm; + x86seg *target_seg = NULL; - STORE_HOST_REG_ADDR_BL((uintptr_t)&cpu_state.flags_op1, host_reg); - SUB_HOST_REG_IMM_B(host_reg, fetchdat & 0xff); - STORE_IMM_ADDR_L((uintptr_t)&cpu_state.flags_op2, fetchdat & 0xff); - STORE_IMM_ADDR_L((uintptr_t)&cpu_state.flags_op, FLAGS_SUB8); - STORE_HOST_REG_ADDR_BL((uintptr_t)&cpu_state.flags_res, host_reg); - STORE_REG_B_RELEASE(host_reg); - - codegen_flags_changed = 1; - return op_pc + 1; + if ((fetchdat & 0x30) == 0x10) + return 0; + + if ((fetchdat & 0xc0) != 0xc0) { + target_seg = FETCH_EA(op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32); + STORE_IMM_ADDR_L((uintptr_t) &cpu_state.oldpc, op_old_pc); + if ((fetchdat & 0x38) == 0x38) { + MEM_LOAD_ADDR_EA_W(target_seg); + host_reg = 0; + } else { + SAVE_EA(); + MEM_CHECK_WRITE_W(target_seg); + host_reg = MEM_LOAD_ADDR_EA_W_NO_ABRT(target_seg); + } + imm = fastreadb(cs + op_pc + 1); + } else { + host_reg = LOAD_REG_W(fetchdat & 7); + imm = (fetchdat >> 8) & 0xff; + } + + if (imm & 0x80) + imm |= 0xff80; + + switch (fetchdat & 0x38) { + case 0x00: /*ADD*/ + STORE_HOST_REG_ADDR_WL((uintptr_t) &cpu_state.flags_op1, host_reg); + ADD_HOST_REG_IMM_W(host_reg, imm); + STORE_IMM_ADDR_L((uintptr_t) &cpu_state.flags_op2, imm); + STORE_IMM_ADDR_L((uintptr_t) &cpu_state.flags_op, FLAGS_ADD16); + break; + case 0x08: /*OR*/ + OR_HOST_REG_IMM(host_reg, imm); + STORE_IMM_ADDR_L((uintptr_t) &cpu_state.flags_op, FLAGS_ZN16); + break; + case 0x20: /*AND*/ + AND_HOST_REG_IMM(host_reg, imm | 0xffff0000); + STORE_IMM_ADDR_L((uintptr_t) &cpu_state.flags_op, FLAGS_ZN16); + break; + case 0x28: /*SUB*/ + STORE_HOST_REG_ADDR_WL((uintptr_t) &cpu_state.flags_op1, host_reg); + SUB_HOST_REG_IMM_W(host_reg, imm); + STORE_IMM_ADDR_L((uintptr_t) &cpu_state.flags_op2, imm); + STORE_IMM_ADDR_L((uintptr_t) &cpu_state.flags_op, FLAGS_SUB16); + break; + case 0x30: /*XOR*/ + XOR_HOST_REG_IMM(host_reg, imm); + STORE_IMM_ADDR_L((uintptr_t) &cpu_state.flags_op, FLAGS_ZN16); + break; + case 0x38: /*CMP*/ + STORE_HOST_REG_ADDR_WL((uintptr_t) &cpu_state.flags_op1, host_reg); + host_reg = CMP_HOST_REG_IMM_W(host_reg, imm); + STORE_IMM_ADDR_L((uintptr_t) &cpu_state.flags_op2, imm); + STORE_IMM_ADDR_L((uintptr_t) &cpu_state.flags_op, FLAGS_SUB16); + break; + } + + STORE_HOST_REG_ADDR_WL((uintptr_t) &cpu_state.flags_res, host_reg); + if ((fetchdat & 0x38) != 0x38) { + if ((fetchdat & 0xc0) != 0xc0) { + LOAD_EA(); + MEM_STORE_ADDR_EA_W_NO_ABRT(target_seg, host_reg); + } else { + STORE_REG_W_RELEASE(host_reg); + } + } else + RELEASE_REG(host_reg); + + codegen_flags_changed = 1; + return op_pc + 2; } -static uint32_t ropSUB_AX_imm(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block) +static uint32_t +rop83_l(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block) { - int host_reg = LOAD_REG_W(REG_AX); + int host_reg; + uint32_t imm; + x86seg *target_seg = NULL; - STORE_HOST_REG_ADDR_WL((uintptr_t)&cpu_state.flags_op1, host_reg); - SUB_HOST_REG_IMM_W(host_reg, fetchdat & 0xffff); - STORE_IMM_ADDR_L((uintptr_t)&cpu_state.flags_op2, fetchdat & 0xffff); - STORE_IMM_ADDR_L((uintptr_t)&cpu_state.flags_op, FLAGS_SUB16); - STORE_HOST_REG_ADDR_WL((uintptr_t)&cpu_state.flags_res, host_reg); - STORE_REG_W_RELEASE(host_reg); - - codegen_flags_changed = 1; - return op_pc + 2; -} -static uint32_t ropSUB_EAX_imm(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block) -{ - int host_reg = LOAD_REG_L(REG_EAX); - - STORE_HOST_REG_ADDR((uintptr_t)&cpu_state.flags_op1, host_reg); - fetchdat = fastreadl(cs + op_pc); - SUB_HOST_REG_IMM(host_reg, fetchdat); - STORE_IMM_ADDR_L((uintptr_t)&cpu_state.flags_op2, fetchdat); - STORE_IMM_ADDR_L((uintptr_t)&cpu_state.flags_op, FLAGS_SUB32); - STORE_HOST_REG_ADDR((uintptr_t)&cpu_state.flags_res, host_reg); - STORE_REG_L_RELEASE(host_reg); - - codegen_flags_changed = 1; - return op_pc + 4; -} - -static uint32_t rop80(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block) -{ - int host_reg; - uint32_t imm; - x86seg *target_seg = NULL; - - if ((fetchdat & 0x30) == 0x10) - return 0; - - if ((fetchdat & 0xc0) != 0xc0) - { - target_seg = FETCH_EA(op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32); - STORE_IMM_ADDR_L((uintptr_t)&cpu_state.oldpc, op_old_pc); - if ((fetchdat & 0x38) == 0x38) - { - MEM_LOAD_ADDR_EA_B(target_seg); - host_reg = 0; - } - else - { - SAVE_EA(); - MEM_CHECK_WRITE(target_seg); - host_reg = MEM_LOAD_ADDR_EA_B_NO_ABRT(target_seg); - } - imm = fastreadb(cs + op_pc + 1); - } - else - { - host_reg = LOAD_REG_B(fetchdat & 7); - imm = (fetchdat >> 8) & 0xff; - } - - switch (fetchdat & 0x38) - { - case 0x00: /*ADD*/ - STORE_HOST_REG_ADDR_BL((uintptr_t)&cpu_state.flags_op1, host_reg); - ADD_HOST_REG_IMM_B(host_reg, imm); - STORE_IMM_ADDR_L((uintptr_t)&cpu_state.flags_op2, imm); - STORE_IMM_ADDR_L((uintptr_t)&cpu_state.flags_op, FLAGS_ADD8); - break; - case 0x08: /*OR*/ - OR_HOST_REG_IMM(host_reg, imm); - STORE_IMM_ADDR_L((uintptr_t)&cpu_state.flags_op, FLAGS_ZN8); - break; - case 0x20: /*AND*/ - AND_HOST_REG_IMM(host_reg, imm | 0xffffff00); - STORE_IMM_ADDR_L((uintptr_t)&cpu_state.flags_op, FLAGS_ZN8); - break; - case 0x28: /*SUB*/ - STORE_HOST_REG_ADDR_BL((uintptr_t)&cpu_state.flags_op1, host_reg); - SUB_HOST_REG_IMM_B(host_reg, imm); - STORE_IMM_ADDR_L((uintptr_t)&cpu_state.flags_op2, imm); - STORE_IMM_ADDR_L((uintptr_t)&cpu_state.flags_op, FLAGS_SUB8); - break; - case 0x30: /*XOR*/ - XOR_HOST_REG_IMM(host_reg, imm); - STORE_IMM_ADDR_L((uintptr_t)&cpu_state.flags_op, FLAGS_ZN8); - break; - case 0x38: /*CMP*/ - STORE_HOST_REG_ADDR_BL((uintptr_t)&cpu_state.flags_op1, host_reg); - host_reg = CMP_HOST_REG_IMM_B(host_reg, imm); - STORE_IMM_ADDR_L((uintptr_t)&cpu_state.flags_op2, imm); - STORE_IMM_ADDR_L((uintptr_t)&cpu_state.flags_op, FLAGS_SUB8); - break; - } - - STORE_HOST_REG_ADDR_BL((uintptr_t)&cpu_state.flags_res, host_reg); - if ((fetchdat & 0x38) != 0x38) - { - if ((fetchdat & 0xc0) != 0xc0) - { - LOAD_EA(); - MEM_STORE_ADDR_EA_B_NO_ABRT(target_seg, host_reg); - } - else - { - STORE_REG_B_RELEASE(host_reg); - } - } - else - RELEASE_REG(host_reg); - - codegen_flags_changed = 1; - return op_pc + 2; -} - -static uint32_t rop81_w(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block) -{ - int host_reg; - uint32_t imm; - x86seg *target_seg = NULL; - - if ((fetchdat & 0x30) == 0x10) - return 0; - - if ((fetchdat & 0xc0) != 0xc0) - { - target_seg = FETCH_EA(op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32); - STORE_IMM_ADDR_L((uintptr_t)&cpu_state.oldpc, op_old_pc); - if ((fetchdat & 0x38) == 0x38) - { - MEM_LOAD_ADDR_EA_W(target_seg); - host_reg = 0; - } - else - { - SAVE_EA(); - MEM_CHECK_WRITE_W(target_seg); - host_reg = MEM_LOAD_ADDR_EA_W_NO_ABRT(target_seg); - } - imm = fastreadw(cs + op_pc + 1); - } - else - { - host_reg = LOAD_REG_W(fetchdat & 7); - imm = (fetchdat >> 8) & 0xffff; - } - - switch (fetchdat & 0x38) - { - case 0x00: /*ADD*/ - STORE_HOST_REG_ADDR_WL((uintptr_t)&cpu_state.flags_op1, host_reg); - ADD_HOST_REG_IMM_W(host_reg, imm); - STORE_IMM_ADDR_L((uintptr_t)&cpu_state.flags_op2, imm); - STORE_IMM_ADDR_L((uintptr_t)&cpu_state.flags_op, FLAGS_ADD16); - break; - case 0x08: /*OR*/ - OR_HOST_REG_IMM(host_reg, imm); - STORE_IMM_ADDR_L((uintptr_t)&cpu_state.flags_op, FLAGS_ZN16); - break; - case 0x20: /*AND*/ - AND_HOST_REG_IMM(host_reg, imm | 0xffff0000); - STORE_IMM_ADDR_L((uintptr_t)&cpu_state.flags_op, FLAGS_ZN16); - break; - case 0x28: /*SUB*/ - STORE_HOST_REG_ADDR_WL((uintptr_t)&cpu_state.flags_op1, host_reg); - SUB_HOST_REG_IMM_W(host_reg, imm); - STORE_IMM_ADDR_L((uintptr_t)&cpu_state.flags_op2, imm); - STORE_IMM_ADDR_L((uintptr_t)&cpu_state.flags_op, FLAGS_SUB16); - break; - case 0x30: /*XOR*/ - XOR_HOST_REG_IMM(host_reg, imm); - STORE_IMM_ADDR_L((uintptr_t)&cpu_state.flags_op, FLAGS_ZN16); - break; - case 0x38: /*CMP*/ - STORE_HOST_REG_ADDR_WL((uintptr_t)&cpu_state.flags_op1, host_reg); - host_reg = CMP_HOST_REG_IMM_W(host_reg, imm); - STORE_IMM_ADDR_L((uintptr_t)&cpu_state.flags_op2, imm); - STORE_IMM_ADDR_L((uintptr_t)&cpu_state.flags_op, FLAGS_SUB16); - break; - } - - STORE_HOST_REG_ADDR_WL((uintptr_t)&cpu_state.flags_res, host_reg); - if ((fetchdat & 0x38) != 0x38) - { - if ((fetchdat & 0xc0) != 0xc0) - { - LOAD_EA(); - MEM_STORE_ADDR_EA_W_NO_ABRT(target_seg, host_reg); - } - else - { - STORE_REG_W_RELEASE(host_reg); - } - } - else - RELEASE_REG(host_reg); - - codegen_flags_changed = 1; - return op_pc + 3; -} -static uint32_t rop81_l(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block) -{ - int host_reg; - uint32_t imm; - x86seg *target_seg = NULL; - - if ((fetchdat & 0x30) == 0x10) - return 0; - - if ((fetchdat & 0xc0) != 0xc0) - { - target_seg = FETCH_EA(op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32); - STORE_IMM_ADDR_L((uintptr_t)&cpu_state.oldpc, op_old_pc); - if ((fetchdat & 0x38) == 0x38) - { - MEM_LOAD_ADDR_EA_L(target_seg); - host_reg = 0; - } - else - { - SAVE_EA(); - MEM_CHECK_WRITE(target_seg); - host_reg = MEM_LOAD_ADDR_EA_L_NO_ABRT(target_seg); - } - } - else - { - host_reg = LOAD_REG_L(fetchdat & 7); - } - imm = fastreadl(cs + op_pc + 1); - - switch (fetchdat & 0x38) - { - case 0x00: /*ADD*/ - STORE_HOST_REG_ADDR((uintptr_t)&cpu_state.flags_op1, host_reg); - ADD_HOST_REG_IMM(host_reg, imm); - STORE_IMM_ADDR_L((uintptr_t)&cpu_state.flags_op2, imm); - STORE_IMM_ADDR_L((uintptr_t)&cpu_state.flags_op, FLAGS_ADD32); - break; - case 0x08: /*OR*/ - OR_HOST_REG_IMM(host_reg, imm); - STORE_IMM_ADDR_L((uintptr_t)&cpu_state.flags_op, FLAGS_ZN32); - break; - case 0x20: /*AND*/ - AND_HOST_REG_IMM(host_reg, imm); - STORE_IMM_ADDR_L((uintptr_t)&cpu_state.flags_op, FLAGS_ZN32); - break; - case 0x28: /*SUB*/ - STORE_HOST_REG_ADDR((uintptr_t)&cpu_state.flags_op1, host_reg); - SUB_HOST_REG_IMM(host_reg, imm); - STORE_IMM_ADDR_L((uintptr_t)&cpu_state.flags_op2, imm); - STORE_IMM_ADDR_L((uintptr_t)&cpu_state.flags_op, FLAGS_SUB32); - break; - case 0x30: /*XOR*/ - XOR_HOST_REG_IMM(host_reg, imm); - STORE_IMM_ADDR_L((uintptr_t)&cpu_state.flags_op, FLAGS_ZN32); - break; - case 0x38: /*CMP*/ - STORE_HOST_REG_ADDR((uintptr_t)&cpu_state.flags_op1, host_reg); - host_reg = CMP_HOST_REG_IMM_L(host_reg, imm); - STORE_IMM_ADDR_L((uintptr_t)&cpu_state.flags_op2, imm); - STORE_IMM_ADDR_L((uintptr_t)&cpu_state.flags_op, FLAGS_SUB32); - break; - } - - STORE_HOST_REG_ADDR((uintptr_t)&cpu_state.flags_res, host_reg); - if ((fetchdat & 0x38) != 0x38) - { - if ((fetchdat & 0xc0) != 0xc0) - { - LOAD_EA(); - MEM_STORE_ADDR_EA_L_NO_ABRT(target_seg, host_reg); - } - else - { - STORE_REG_L_RELEASE(host_reg); - } - } - else - RELEASE_REG(host_reg); - - codegen_flags_changed = 1; - return op_pc + 5; -} - -static uint32_t rop83_w(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block) -{ - int host_reg; - uint32_t imm; - x86seg *target_seg = NULL; - - if ((fetchdat & 0x30) == 0x10) - return 0; - - if ((fetchdat & 0xc0) != 0xc0) - { - target_seg = FETCH_EA(op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32); - STORE_IMM_ADDR_L((uintptr_t)&cpu_state.oldpc, op_old_pc); - if ((fetchdat & 0x38) == 0x38) - { - MEM_LOAD_ADDR_EA_W(target_seg); - host_reg = 0; - } - else - { - SAVE_EA(); - MEM_CHECK_WRITE_W(target_seg); - host_reg = MEM_LOAD_ADDR_EA_W_NO_ABRT(target_seg); - } - imm = fastreadb(cs + op_pc + 1); - } - else - { - host_reg = LOAD_REG_W(fetchdat & 7); - imm = (fetchdat >> 8) & 0xff; - } - - if (imm & 0x80) - imm |= 0xff80; - - switch (fetchdat & 0x38) - { - case 0x00: /*ADD*/ - STORE_HOST_REG_ADDR_WL((uintptr_t)&cpu_state.flags_op1, host_reg); - ADD_HOST_REG_IMM_W(host_reg, imm); - STORE_IMM_ADDR_L((uintptr_t)&cpu_state.flags_op2, imm); - STORE_IMM_ADDR_L((uintptr_t)&cpu_state.flags_op, FLAGS_ADD16); - break; - case 0x08: /*OR*/ - OR_HOST_REG_IMM(host_reg, imm); - STORE_IMM_ADDR_L((uintptr_t)&cpu_state.flags_op, FLAGS_ZN16); - break; - case 0x20: /*AND*/ - AND_HOST_REG_IMM(host_reg, imm | 0xffff0000); - STORE_IMM_ADDR_L((uintptr_t)&cpu_state.flags_op, FLAGS_ZN16); - break; - case 0x28: /*SUB*/ - STORE_HOST_REG_ADDR_WL((uintptr_t)&cpu_state.flags_op1, host_reg); - SUB_HOST_REG_IMM_W(host_reg, imm); - STORE_IMM_ADDR_L((uintptr_t)&cpu_state.flags_op2, imm); - STORE_IMM_ADDR_L((uintptr_t)&cpu_state.flags_op, FLAGS_SUB16); - break; - case 0x30: /*XOR*/ - XOR_HOST_REG_IMM(host_reg, imm); - STORE_IMM_ADDR_L((uintptr_t)&cpu_state.flags_op, FLAGS_ZN16); - break; - case 0x38: /*CMP*/ - STORE_HOST_REG_ADDR_WL((uintptr_t)&cpu_state.flags_op1, host_reg); - host_reg = CMP_HOST_REG_IMM_W(host_reg, imm); - STORE_IMM_ADDR_L((uintptr_t)&cpu_state.flags_op2, imm); - STORE_IMM_ADDR_L((uintptr_t)&cpu_state.flags_op, FLAGS_SUB16); - break; - } - - STORE_HOST_REG_ADDR_WL((uintptr_t)&cpu_state.flags_res, host_reg); - if ((fetchdat & 0x38) != 0x38) - { - if ((fetchdat & 0xc0) != 0xc0) - { - LOAD_EA(); - MEM_STORE_ADDR_EA_W_NO_ABRT(target_seg, host_reg); - } - else - { - STORE_REG_W_RELEASE(host_reg); - } - } - else - RELEASE_REG(host_reg); - - codegen_flags_changed = 1; - return op_pc + 2; -} -static uint32_t rop83_l(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block) -{ - int host_reg; - uint32_t imm; - x86seg *target_seg = NULL; - - if ((fetchdat & 0x30) == 0x10) - return 0; - - if ((fetchdat & 0xc0) != 0xc0) - { - target_seg = FETCH_EA(op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32); - STORE_IMM_ADDR_L((uintptr_t)&cpu_state.oldpc, op_old_pc); - if ((fetchdat & 0x38) == 0x38) - { - MEM_LOAD_ADDR_EA_L(target_seg); - host_reg = 0; - } - else - { - SAVE_EA(); - MEM_CHECK_WRITE_L(target_seg); - host_reg = MEM_LOAD_ADDR_EA_L_NO_ABRT(target_seg); - } - imm = fastreadb(cs + op_pc + 1); - } - else - { - host_reg = LOAD_REG_L(fetchdat & 7); - imm = (fetchdat >> 8) & 0xff; - } - - if (imm & 0x80) - imm |= 0xffffff80; - - switch (fetchdat & 0x38) - { - case 0x00: /*ADD*/ - STORE_HOST_REG_ADDR((uintptr_t)&cpu_state.flags_op1, host_reg); - ADD_HOST_REG_IMM(host_reg, imm); - STORE_IMM_ADDR_L((uintptr_t)&cpu_state.flags_op2, imm); - STORE_IMM_ADDR_L((uintptr_t)&cpu_state.flags_op, FLAGS_ADD32); - break; - case 0x08: /*OR*/ - OR_HOST_REG_IMM(host_reg, imm); - STORE_IMM_ADDR_L((uintptr_t)&cpu_state.flags_op, FLAGS_ZN32); - break; - case 0x20: /*AND*/ - AND_HOST_REG_IMM(host_reg, imm); - STORE_IMM_ADDR_L((uintptr_t)&cpu_state.flags_op, FLAGS_ZN32); - break; - case 0x28: /*SUB*/ - STORE_HOST_REG_ADDR((uintptr_t)&cpu_state.flags_op1, host_reg); - SUB_HOST_REG_IMM(host_reg, imm); - STORE_IMM_ADDR_L((uintptr_t)&cpu_state.flags_op2, imm); - STORE_IMM_ADDR_L((uintptr_t)&cpu_state.flags_op, FLAGS_SUB32); - break; - case 0x30: /*XOR*/ - XOR_HOST_REG_IMM(host_reg, imm); - STORE_IMM_ADDR_L((uintptr_t)&cpu_state.flags_op, FLAGS_ZN32); - break; - case 0x38: /*CMP*/ - STORE_HOST_REG_ADDR((uintptr_t)&cpu_state.flags_op1, host_reg); - host_reg = CMP_HOST_REG_IMM_L(host_reg, imm); - STORE_IMM_ADDR_L((uintptr_t)&cpu_state.flags_op2, imm); - STORE_IMM_ADDR_L((uintptr_t)&cpu_state.flags_op, FLAGS_SUB32); - break; - } - - STORE_HOST_REG_ADDR((uintptr_t)&cpu_state.flags_res, host_reg); - if ((fetchdat & 0x38) != 0x38) - { - if ((fetchdat & 0xc0) != 0xc0) - { - LOAD_EA(); - MEM_STORE_ADDR_EA_L_NO_ABRT(target_seg, host_reg); - } - else - { - STORE_REG_L_RELEASE(host_reg); - } - } - else - RELEASE_REG(host_reg); - - codegen_flags_changed = 1; - return op_pc + 2; + if ((fetchdat & 0x30) == 0x10) + return 0; + + if ((fetchdat & 0xc0) != 0xc0) { + target_seg = FETCH_EA(op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32); + STORE_IMM_ADDR_L((uintptr_t) &cpu_state.oldpc, op_old_pc); + if ((fetchdat & 0x38) == 0x38) { + MEM_LOAD_ADDR_EA_L(target_seg); + host_reg = 0; + } else { + SAVE_EA(); + MEM_CHECK_WRITE_L(target_seg); + host_reg = MEM_LOAD_ADDR_EA_L_NO_ABRT(target_seg); + } + imm = fastreadb(cs + op_pc + 1); + } else { + host_reg = LOAD_REG_L(fetchdat & 7); + imm = (fetchdat >> 8) & 0xff; + } + + if (imm & 0x80) + imm |= 0xffffff80; + + switch (fetchdat & 0x38) { + case 0x00: /*ADD*/ + STORE_HOST_REG_ADDR((uintptr_t) &cpu_state.flags_op1, host_reg); + ADD_HOST_REG_IMM(host_reg, imm); + STORE_IMM_ADDR_L((uintptr_t) &cpu_state.flags_op2, imm); + STORE_IMM_ADDR_L((uintptr_t) &cpu_state.flags_op, FLAGS_ADD32); + break; + case 0x08: /*OR*/ + OR_HOST_REG_IMM(host_reg, imm); + STORE_IMM_ADDR_L((uintptr_t) &cpu_state.flags_op, FLAGS_ZN32); + break; + case 0x20: /*AND*/ + AND_HOST_REG_IMM(host_reg, imm); + STORE_IMM_ADDR_L((uintptr_t) &cpu_state.flags_op, FLAGS_ZN32); + break; + case 0x28: /*SUB*/ + STORE_HOST_REG_ADDR((uintptr_t) &cpu_state.flags_op1, host_reg); + SUB_HOST_REG_IMM(host_reg, imm); + STORE_IMM_ADDR_L((uintptr_t) &cpu_state.flags_op2, imm); + STORE_IMM_ADDR_L((uintptr_t) &cpu_state.flags_op, FLAGS_SUB32); + break; + case 0x30: /*XOR*/ + XOR_HOST_REG_IMM(host_reg, imm); + STORE_IMM_ADDR_L((uintptr_t) &cpu_state.flags_op, FLAGS_ZN32); + break; + case 0x38: /*CMP*/ + STORE_HOST_REG_ADDR((uintptr_t) &cpu_state.flags_op1, host_reg); + host_reg = CMP_HOST_REG_IMM_L(host_reg, imm); + STORE_IMM_ADDR_L((uintptr_t) &cpu_state.flags_op2, imm); + STORE_IMM_ADDR_L((uintptr_t) &cpu_state.flags_op, FLAGS_SUB32); + break; + } + + STORE_HOST_REG_ADDR((uintptr_t) &cpu_state.flags_res, host_reg); + if ((fetchdat & 0x38) != 0x38) { + if ((fetchdat & 0xc0) != 0xc0) { + LOAD_EA(); + MEM_STORE_ADDR_EA_L_NO_ABRT(target_seg, host_reg); + } else { + STORE_REG_L_RELEASE(host_reg); + } + } else + RELEASE_REG(host_reg); + + codegen_flags_changed = 1; + return op_pc + 2; } diff --git a/src/codegen/codegen_ops_fpu.h b/src/codegen/codegen_ops_fpu.h index b15d41bff..1021cc742 100644 --- a/src/codegen/codegen_ops_fpu.h +++ b/src/codegen/codegen_ops_fpu.h @@ -1,645 +1,697 @@ -static uint32_t ropFXCH(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block) +static uint32_t +ropFXCH(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block) { - FP_ENTER(); + FP_ENTER(); - FP_FXCH(opcode & 7); - - return op_pc; + FP_FXCH(opcode & 7); + + return op_pc; } -static uint32_t ropFLD(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block) +static uint32_t +ropFLD(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block) { - FP_ENTER(); + FP_ENTER(); - FP_FLD(opcode & 7); - - return op_pc; + FP_FLD(opcode & 7); + + return op_pc; } -static uint32_t ropFST(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block) +static uint32_t +ropFST(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block) { - FP_ENTER(); + FP_ENTER(); - FP_FST(opcode & 7); - - return op_pc; + FP_FST(opcode & 7); + + return op_pc; } -static uint32_t ropFSTP(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block) +static uint32_t +ropFSTP(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block) { - FP_ENTER(); + FP_ENTER(); - FP_FST(opcode & 7); - FP_POP(); - - return op_pc; + FP_FST(opcode & 7); + FP_POP(); + + return op_pc; } - -static uint32_t ropFLDs(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block) +static uint32_t +ropFLDs(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block) { - x86seg *target_seg; - - FP_ENTER(); - op_pc--; - target_seg = FETCH_EA(op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32); + x86seg *target_seg; - STORE_IMM_ADDR_L((uintptr_t)&cpu_state.oldpc, op_old_pc); - - CHECK_SEG_READ(target_seg); - MEM_LOAD_ADDR_EA_L(target_seg); + FP_ENTER(); + op_pc--; + target_seg = FETCH_EA(op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32); - FP_LOAD_S(); + STORE_IMM_ADDR_L((uintptr_t) &cpu_state.oldpc, op_old_pc); - return op_pc + 1; + CHECK_SEG_READ(target_seg); + MEM_LOAD_ADDR_EA_L(target_seg); + + FP_LOAD_S(); + + return op_pc + 1; } -static uint32_t ropFLDd(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block) +static uint32_t +ropFLDd(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block) { - x86seg *target_seg; - - FP_ENTER(); - op_pc--; - target_seg = FETCH_EA(op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32); + x86seg *target_seg; - STORE_IMM_ADDR_L((uintptr_t)&cpu_state.oldpc, op_old_pc); - - CHECK_SEG_READ(target_seg); - MEM_LOAD_ADDR_EA_Q(target_seg); + FP_ENTER(); + op_pc--; + target_seg = FETCH_EA(op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32); - FP_LOAD_D(); + STORE_IMM_ADDR_L((uintptr_t) &cpu_state.oldpc, op_old_pc); - return op_pc + 1; + CHECK_SEG_READ(target_seg); + MEM_LOAD_ADDR_EA_Q(target_seg); + + FP_LOAD_D(); + + return op_pc + 1; } -static uint32_t ropFILDw(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block) +static uint32_t +ropFILDw(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block) { - x86seg *target_seg; - - FP_ENTER(); - op_pc--; - target_seg = FETCH_EA(op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32); + x86seg *target_seg; - STORE_IMM_ADDR_L((uintptr_t)&cpu_state.oldpc, op_old_pc); - - CHECK_SEG_READ(target_seg); - MEM_LOAD_ADDR_EA_W(target_seg); + FP_ENTER(); + op_pc--; + target_seg = FETCH_EA(op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32); - FP_LOAD_IW(); + STORE_IMM_ADDR_L((uintptr_t) &cpu_state.oldpc, op_old_pc); - return op_pc + 1; + CHECK_SEG_READ(target_seg); + MEM_LOAD_ADDR_EA_W(target_seg); + + FP_LOAD_IW(); + + return op_pc + 1; } -static uint32_t ropFILDl(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block) +static uint32_t +ropFILDl(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block) { - x86seg *target_seg; - - FP_ENTER(); - op_pc--; - target_seg = FETCH_EA(op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32); + x86seg *target_seg; - STORE_IMM_ADDR_L((uintptr_t)&cpu_state.oldpc, op_old_pc); - - CHECK_SEG_READ(target_seg); - MEM_LOAD_ADDR_EA_L(target_seg); + FP_ENTER(); + op_pc--; + target_seg = FETCH_EA(op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32); - FP_LOAD_IL(); + STORE_IMM_ADDR_L((uintptr_t) &cpu_state.oldpc, op_old_pc); - return op_pc + 1; + CHECK_SEG_READ(target_seg); + MEM_LOAD_ADDR_EA_L(target_seg); + + FP_LOAD_IL(); + + return op_pc + 1; } -static uint32_t ropFILDq(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block) +static uint32_t +ropFILDq(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block) { - x86seg *target_seg; - - FP_ENTER(); - op_pc--; - target_seg = FETCH_EA(op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32); + x86seg *target_seg; - STORE_IMM_ADDR_L((uintptr_t)&cpu_state.oldpc, op_old_pc); - - CHECK_SEG_READ(target_seg); - MEM_LOAD_ADDR_EA_Q(target_seg); + FP_ENTER(); + op_pc--; + target_seg = FETCH_EA(op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32); - FP_LOAD_IQ(); + STORE_IMM_ADDR_L((uintptr_t) &cpu_state.oldpc, op_old_pc); - codegen_fpu_loaded_iq[(cpu_state.TOP - 1) & 7] = 1; - - return op_pc + 1; + CHECK_SEG_READ(target_seg); + MEM_LOAD_ADDR_EA_Q(target_seg); + + FP_LOAD_IQ(); + + codegen_fpu_loaded_iq[(cpu_state.TOP - 1) & 7] = 1; + + return op_pc + 1; } -static uint32_t ropFSTs(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block) +static uint32_t +ropFSTs(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block) { - x86seg *target_seg; - int host_reg; - - FP_ENTER(); - op_pc--; - target_seg = FETCH_EA(op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32); + x86seg *target_seg; + int host_reg; - host_reg = FP_LOAD_REG(0); + FP_ENTER(); + op_pc--; + target_seg = FETCH_EA(op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32); - STORE_IMM_ADDR_L((uintptr_t)&cpu_state.oldpc, op_old_pc); + host_reg = FP_LOAD_REG(0); - CHECK_SEG_WRITE(target_seg); - - MEM_STORE_ADDR_EA_L(target_seg, host_reg); + STORE_IMM_ADDR_L((uintptr_t) &cpu_state.oldpc, op_old_pc); - return op_pc + 1; + CHECK_SEG_WRITE(target_seg); + + MEM_STORE_ADDR_EA_L(target_seg, host_reg); + + return op_pc + 1; } -static uint32_t ropFSTd(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block) +static uint32_t +ropFSTd(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block) { - x86seg *target_seg; - int host_reg1, host_reg2 = 0; - - FP_ENTER(); - op_pc--; - target_seg = FETCH_EA(op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32); + x86seg *target_seg; + int host_reg1; + int host_reg2 = 0; - FP_LOAD_REG_D(0, &host_reg1, &host_reg2); + FP_ENTER(); + op_pc--; + target_seg = FETCH_EA(op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32); - STORE_IMM_ADDR_L((uintptr_t)&cpu_state.oldpc, op_old_pc); + FP_LOAD_REG_D(0, &host_reg1, &host_reg2); - CHECK_SEG_WRITE(target_seg); - CHECK_SEG_LIMITS(target_seg, 7); - - MEM_STORE_ADDR_EA_Q(target_seg, host_reg1, host_reg2); + STORE_IMM_ADDR_L((uintptr_t) &cpu_state.oldpc, op_old_pc); - return op_pc + 1; + CHECK_SEG_WRITE(target_seg); + CHECK_SEG_LIMITS(target_seg, 7); + + MEM_STORE_ADDR_EA_Q(target_seg, host_reg1, host_reg2); + + return op_pc + 1; } -static uint32_t ropFSTPs(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block) +static uint32_t +ropFSTPs(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block) { - uint32_t new_pc = ropFSTs(opcode, fetchdat, op_32, op_pc, block); - - FP_POP(); - - return new_pc; + uint32_t new_pc = ropFSTs(opcode, fetchdat, op_32, op_pc, block); + + FP_POP(); + + return new_pc; } -static uint32_t ropFSTPd(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block) +static uint32_t +ropFSTPd(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block) { - uint32_t new_pc = ropFSTd(opcode, fetchdat, op_32, op_pc, block); - - FP_POP(); - - return new_pc; + uint32_t new_pc = ropFSTd(opcode, fetchdat, op_32, op_pc, block); + + FP_POP(); + + return new_pc; } -#define ropFarith(name, size, load, op) \ -static uint32_t ropF ## name ## size(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block) \ -{ \ - x86seg *target_seg; \ - \ - FP_ENTER(); \ - op_pc--; \ - target_seg = FETCH_EA(op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32); \ - \ - STORE_IMM_ADDR_L((uintptr_t)&cpu_state.oldpc, op_old_pc); \ - \ - CHECK_SEG_READ(target_seg); \ - load(target_seg); \ - \ - op(FPU_ ## name); \ - \ - return op_pc + 1; \ -} +#define ropFarith(name, size, load, op) \ + static uint32_t \ + ropF##name##size(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block) \ + { \ + x86seg *target_seg; \ + \ + FP_ENTER(); \ + op_pc--; \ + target_seg = FETCH_EA(op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32); \ + \ + STORE_IMM_ADDR_L((uintptr_t) &cpu_state.oldpc, op_old_pc); \ + \ + CHECK_SEG_READ(target_seg); \ + load(target_seg); \ + \ + op(FPU_##name); \ + \ + return op_pc + 1; \ + } -ropFarith(ADD, s, MEM_LOAD_ADDR_EA_L, FP_OP_S); -ropFarith(DIV, s, MEM_LOAD_ADDR_EA_L, FP_OP_S); +ropFarith(ADD, s, MEM_LOAD_ADDR_EA_L, FP_OP_S); +ropFarith(DIV, s, MEM_LOAD_ADDR_EA_L, FP_OP_S); ropFarith(DIVR, s, MEM_LOAD_ADDR_EA_L, FP_OP_S); -ropFarith(MUL, s, MEM_LOAD_ADDR_EA_L, FP_OP_S); -ropFarith(SUB, s, MEM_LOAD_ADDR_EA_L, FP_OP_S); +ropFarith(MUL, s, MEM_LOAD_ADDR_EA_L, FP_OP_S); +ropFarith(SUB, s, MEM_LOAD_ADDR_EA_L, FP_OP_S); ropFarith(SUBR, s, MEM_LOAD_ADDR_EA_L, FP_OP_S); -ropFarith(ADD, d, MEM_LOAD_ADDR_EA_Q, FP_OP_D); -ropFarith(DIV, d, MEM_LOAD_ADDR_EA_Q, FP_OP_D); +ropFarith(ADD, d, MEM_LOAD_ADDR_EA_Q, FP_OP_D); +ropFarith(DIV, d, MEM_LOAD_ADDR_EA_Q, FP_OP_D); ropFarith(DIVR, d, MEM_LOAD_ADDR_EA_Q, FP_OP_D); -ropFarith(MUL, d, MEM_LOAD_ADDR_EA_Q, FP_OP_D); -ropFarith(SUB, d, MEM_LOAD_ADDR_EA_Q, FP_OP_D); +ropFarith(MUL, d, MEM_LOAD_ADDR_EA_Q, FP_OP_D); +ropFarith(SUB, d, MEM_LOAD_ADDR_EA_Q, FP_OP_D); ropFarith(SUBR, d, MEM_LOAD_ADDR_EA_Q, FP_OP_D); -ropFarith(ADD, iw, MEM_LOAD_ADDR_EA_W, FP_OP_IW); -ropFarith(DIV, iw, MEM_LOAD_ADDR_EA_W, FP_OP_IW); +ropFarith(ADD, iw, MEM_LOAD_ADDR_EA_W, FP_OP_IW); +ropFarith(DIV, iw, MEM_LOAD_ADDR_EA_W, FP_OP_IW); ropFarith(DIVR, iw, MEM_LOAD_ADDR_EA_W, FP_OP_IW); -ropFarith(MUL, iw, MEM_LOAD_ADDR_EA_W, FP_OP_IW); -ropFarith(SUB, iw, MEM_LOAD_ADDR_EA_W, FP_OP_IW); +ropFarith(MUL, iw, MEM_LOAD_ADDR_EA_W, FP_OP_IW); +ropFarith(SUB, iw, MEM_LOAD_ADDR_EA_W, FP_OP_IW); ropFarith(SUBR, iw, MEM_LOAD_ADDR_EA_W, FP_OP_IW); -ropFarith(ADD, il, MEM_LOAD_ADDR_EA_L, FP_OP_IL); -ropFarith(DIV, il, MEM_LOAD_ADDR_EA_L, FP_OP_IL); +ropFarith(ADD, il, MEM_LOAD_ADDR_EA_L, FP_OP_IL); +ropFarith(DIV, il, MEM_LOAD_ADDR_EA_L, FP_OP_IL); ropFarith(DIVR, il, MEM_LOAD_ADDR_EA_L, FP_OP_IL); -ropFarith(MUL, il, MEM_LOAD_ADDR_EA_L, FP_OP_IL); -ropFarith(SUB, il, MEM_LOAD_ADDR_EA_L, FP_OP_IL); +ropFarith(MUL, il, MEM_LOAD_ADDR_EA_L, FP_OP_IL); +ropFarith(SUB, il, MEM_LOAD_ADDR_EA_L, FP_OP_IL); ropFarith(SUBR, il, MEM_LOAD_ADDR_EA_L, FP_OP_IL); -#define ropFcompare(name, size, load, op) \ -static uint32_t ropF ## name ## size(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block) \ -{ \ - x86seg *target_seg; \ - \ - FP_ENTER(); \ - op_pc--; \ - target_seg = FETCH_EA(op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32); \ - \ - STORE_IMM_ADDR_L((uintptr_t)&cpu_state.oldpc, op_old_pc); \ - \ - CHECK_SEG_READ(target_seg); \ - load(target_seg); \ - \ - op(); \ - \ - return op_pc + 1; \ -} \ -static uint32_t ropF ## name ## P ## size(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block) \ -{ \ - uint32_t new_pc = ropF ## name ## size(opcode, fetchdat, op_32, op_pc, block); \ - \ - FP_POP(); \ - \ - return new_pc; \ -} +#define ropFcompare(name, size, load, op) \ + static uint32_t \ + ropF##name##size(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block) \ + { \ + x86seg *target_seg; \ + \ + FP_ENTER(); \ + op_pc--; \ + target_seg = FETCH_EA(op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32); \ + \ + STORE_IMM_ADDR_L((uintptr_t) &cpu_state.oldpc, op_old_pc); \ + \ + CHECK_SEG_READ(target_seg); \ + load(target_seg); \ + \ + op(); \ + \ + return op_pc + 1; \ + } \ + static uint32_t ropF##name##P##size(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block) \ + { \ + uint32_t new_pc = ropF##name##size(opcode, fetchdat, op_32, op_pc, block); \ + \ + FP_POP(); \ + \ + return new_pc; \ + } ropFcompare(COM, s, MEM_LOAD_ADDR_EA_L, FP_COMPARE_S); ropFcompare(COM, d, MEM_LOAD_ADDR_EA_Q, FP_COMPARE_D); ropFcompare(COM, iw, MEM_LOAD_ADDR_EA_W, FP_COMPARE_IW); ropFcompare(COM, il, MEM_LOAD_ADDR_EA_L, FP_COMPARE_IL); -/*static uint32_t ropFADDs(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block) +#if 0 +static uint32_t +ropFADDs(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block) { - x86seg *target_seg; - - FP_ENTER(); - op_pc--; - target_seg = FETCH_EA(op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32); + x86seg *target_seg; - STORE_IMM_ADDR_L((uintptr_t)&cpu_state.oldpc, op_old_pc); - - CHECK_SEG_READ(target_seg); - MEM_LOAD_ADDR_EA_L(target_seg); + FP_ENTER(); + op_pc--; + target_seg = FETCH_EA(op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32); - FP_OP_S(FPU_ADD); + STORE_IMM_ADDR_L((uintptr_t)&cpu_state.oldpc, op_old_pc); - return op_pc + 1; + CHECK_SEG_READ(target_seg); + MEM_LOAD_ADDR_EA_L(target_seg); + + FP_OP_S(FPU_ADD); + + return op_pc + 1; } -static uint32_t ropFDIVs(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block) +static uint32_t +ropFDIVs(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block) { - x86seg *target_seg; - - FP_ENTER(); - op_pc--; - target_seg = FETCH_EA(op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32); + x86seg *target_seg; - STORE_IMM_ADDR_L((uintptr_t)&cpu_state.oldpc, op_old_pc); - - CHECK_SEG_READ(target_seg); - MEM_LOAD_ADDR_EA_L(target_seg); + FP_ENTER(); + op_pc--; + target_seg = FETCH_EA(op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32); - FP_OP_S(FPU_DIV); + STORE_IMM_ADDR_L((uintptr_t)&cpu_state.oldpc, op_old_pc); - return op_pc + 1; + CHECK_SEG_READ(target_seg); + MEM_LOAD_ADDR_EA_L(target_seg); + + FP_OP_S(FPU_DIV); + + return op_pc + 1; } -static uint32_t ropFMULs(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block) +static uint32_t +ropFMULs(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block) { - x86seg *target_seg; - - FP_ENTER(); - op_pc--; - target_seg = FETCH_EA(op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32); + x86seg *target_seg; - STORE_IMM_ADDR_L((uintptr_t)&cpu_state.oldpc, op_old_pc); - - CHECK_SEG_READ(target_seg); - MEM_LOAD_ADDR_EA_L(target_seg); + FP_ENTER(); + op_pc--; + target_seg = FETCH_EA(op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32); - FP_OP_S(FPU_MUL); + STORE_IMM_ADDR_L((uintptr_t)&cpu_state.oldpc, op_old_pc); - return op_pc + 1; + CHECK_SEG_READ(target_seg); + MEM_LOAD_ADDR_EA_L(target_seg); + + FP_OP_S(FPU_MUL); + + return op_pc + 1; } -static uint32_t ropFSUBs(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block) +static uint32_t +ropFSUBs(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block) { - x86seg *target_seg; - - FP_ENTER(); - op_pc--; - target_seg = FETCH_EA(op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32); + x86seg *target_seg; - STORE_IMM_ADDR_L((uintptr_t)&cpu_state.oldpc, op_old_pc); - - CHECK_SEG_READ(target_seg); - MEM_LOAD_ADDR_EA_L(target_seg); + FP_ENTER(); + op_pc--; + target_seg = FETCH_EA(op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32); - FP_OP_S(FPU_SUB); + STORE_IMM_ADDR_L((uintptr_t)&cpu_state.oldpc, op_old_pc); - return op_pc + 1; -}*/ + CHECK_SEG_READ(target_seg); + MEM_LOAD_ADDR_EA_L(target_seg); + FP_OP_S(FPU_SUB); -static uint32_t ropFADD(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block) -{ - FP_ENTER(); - FP_OP_REG(FPU_ADD, 0, opcode & 7); - - return op_pc; + return op_pc + 1; } -static uint32_t ropFCOM(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block) +#endif + +static uint32_t +ropFADD(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block) { - FP_ENTER(); - FP_COMPARE_REG(0, opcode & 7); - - return op_pc; + FP_ENTER(); + FP_OP_REG(FPU_ADD, 0, opcode & 7); + + return op_pc; } -static uint32_t ropFDIV(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block) +static uint32_t +ropFCOM(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block) { - FP_ENTER(); - FP_OP_REG(FPU_DIV, 0, opcode & 7); - - return op_pc; + FP_ENTER(); + FP_COMPARE_REG(0, opcode & 7); + + return op_pc; } -static uint32_t ropFDIVR(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block) +static uint32_t +ropFDIV(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block) { - FP_ENTER(); - FP_OP_REG(FPU_DIVR, 0, opcode & 7); - - return op_pc; + FP_ENTER(); + FP_OP_REG(FPU_DIV, 0, opcode & 7); + + return op_pc; } -static uint32_t ropFMUL(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block) +static uint32_t +ropFDIVR(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block) { - FP_ENTER(); - FP_OP_REG(FPU_MUL, 0, opcode & 7); - - return op_pc; + FP_ENTER(); + FP_OP_REG(FPU_DIVR, 0, opcode & 7); + + return op_pc; } -static uint32_t ropFSUB(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block) +static uint32_t +ropFMUL(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block) { - FP_ENTER(); - FP_OP_REG(FPU_SUB, 0, opcode & 7); - - return op_pc; + FP_ENTER(); + FP_OP_REG(FPU_MUL, 0, opcode & 7); + + return op_pc; } -static uint32_t ropFSUBR(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block) +static uint32_t +ropFSUB(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block) { - FP_ENTER(); - FP_OP_REG(FPU_SUBR, 0, opcode & 7); - - return op_pc; + FP_ENTER(); + FP_OP_REG(FPU_SUB, 0, opcode & 7); + + return op_pc; +} +static uint32_t +ropFSUBR(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block) +{ + FP_ENTER(); + FP_OP_REG(FPU_SUBR, 0, opcode & 7); + + return op_pc; } -static uint32_t ropFADDr(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block) +static uint32_t +ropFADDr(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block) { - FP_ENTER(); - FP_OP_REG(FPU_ADD, opcode & 7, 0); - - return op_pc; + FP_ENTER(); + FP_OP_REG(FPU_ADD, opcode & 7, 0); + + return op_pc; } -static uint32_t ropFDIVr(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block) +static uint32_t +ropFDIVr(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block) { - FP_ENTER(); - FP_OP_REG(FPU_DIV, opcode & 7, 0); - - return op_pc; + FP_ENTER(); + FP_OP_REG(FPU_DIV, opcode & 7, 0); + + return op_pc; } -static uint32_t ropFDIVRr(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block) +static uint32_t +ropFDIVRr(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block) { - FP_ENTER(); - FP_OP_REG(FPU_DIVR, opcode & 7, 0); - - return op_pc; + FP_ENTER(); + FP_OP_REG(FPU_DIVR, opcode & 7, 0); + + return op_pc; } -static uint32_t ropFMULr(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block) +static uint32_t +ropFMULr(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block) { - FP_ENTER(); - FP_OP_REG(FPU_MUL, opcode & 7, 0); - - return op_pc; + FP_ENTER(); + FP_OP_REG(FPU_MUL, opcode & 7, 0); + + return op_pc; } -static uint32_t ropFSUBr(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block) +static uint32_t +ropFSUBr(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block) { - FP_ENTER(); - FP_OP_REG(FPU_SUB, opcode & 7, 0); - - return op_pc; + FP_ENTER(); + FP_OP_REG(FPU_SUB, opcode & 7, 0); + + return op_pc; } -static uint32_t ropFSUBRr(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block) +static uint32_t +ropFSUBRr(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block) { - FP_ENTER(); - FP_OP_REG(FPU_SUBR, opcode & 7, 0); - - return op_pc; + FP_ENTER(); + FP_OP_REG(FPU_SUBR, opcode & 7, 0); + + return op_pc; } -static uint32_t ropFADDP(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block) +static uint32_t +ropFADDP(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block) { - FP_ENTER(); - FP_OP_REG(FPU_ADD, opcode & 7, 0); - FP_POP(); - - return op_pc; + FP_ENTER(); + FP_OP_REG(FPU_ADD, opcode & 7, 0); + FP_POP(); + + return op_pc; } -static uint32_t ropFCOMP(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block) +static uint32_t +ropFCOMP(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block) { - FP_ENTER(); - FP_COMPARE_REG(0, opcode & 7); - FP_POP(); - - return op_pc; + FP_ENTER(); + FP_COMPARE_REG(0, opcode & 7); + FP_POP(); + + return op_pc; } -static uint32_t ropFDIVP(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block) +static uint32_t +ropFDIVP(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block) { - FP_ENTER(); - FP_OP_REG(FPU_DIV, opcode & 7, 0); - FP_POP(); - - return op_pc; + FP_ENTER(); + FP_OP_REG(FPU_DIV, opcode & 7, 0); + FP_POP(); + + return op_pc; } -static uint32_t ropFDIVRP(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block) +static uint32_t +ropFDIVRP(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block) { - FP_ENTER(); - FP_OP_REG(FPU_DIVR, opcode & 7, 0); - FP_POP(); - - return op_pc; + FP_ENTER(); + FP_OP_REG(FPU_DIVR, opcode & 7, 0); + FP_POP(); + + return op_pc; } -static uint32_t ropFMULP(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block) +static uint32_t +ropFMULP(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block) { - FP_ENTER(); - FP_OP_REG(FPU_MUL, opcode & 7, 0); - FP_POP(); - - return op_pc; + FP_ENTER(); + FP_OP_REG(FPU_MUL, opcode & 7, 0); + FP_POP(); + + return op_pc; } -static uint32_t ropFSUBP(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block) +static uint32_t +ropFSUBP(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block) { - FP_ENTER(); - FP_OP_REG(FPU_SUB, opcode & 7, 0); - FP_POP(); - - return op_pc; + FP_ENTER(); + FP_OP_REG(FPU_SUB, opcode & 7, 0); + FP_POP(); + + return op_pc; } -static uint32_t ropFSUBRP(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block) +static uint32_t +ropFSUBRP(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block) { - FP_ENTER(); - FP_OP_REG(FPU_SUBR, opcode & 7, 0); - FP_POP(); - - return op_pc; + FP_ENTER(); + FP_OP_REG(FPU_SUBR, opcode & 7, 0); + FP_POP(); + + return op_pc; } -static uint32_t ropFCOMPP(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block) +static uint32_t +ropFCOMPP(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block) { - FP_ENTER(); - FP_COMPARE_REG(0, 1); - FP_POP2(); - - return op_pc; + FP_ENTER(); + FP_COMPARE_REG(0, 1); + FP_POP2(); + + return op_pc; } -static uint32_t ropFSTSW_AX(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block) +static uint32_t +ropFSTSW_AX(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block) { - int host_reg; - - FP_ENTER(); - host_reg = LOAD_VAR_W((uintptr_t)&cpu_state.npxs); - STORE_REG_TARGET_W_RELEASE(host_reg, REG_AX); - - return op_pc; + int host_reg; + + FP_ENTER(); + host_reg = LOAD_VAR_W((uintptr_t) &cpu_state.npxs); + STORE_REG_TARGET_W_RELEASE(host_reg, REG_AX); + + return op_pc; } - -static uint32_t ropFISTw(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block) +static uint32_t +ropFISTw(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block) { - x86seg *target_seg; - int host_reg; + x86seg *target_seg; + int host_reg; - FP_ENTER(); - op_pc--; - target_seg = FETCH_EA(op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32); + FP_ENTER(); + op_pc--; + target_seg = FETCH_EA(op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32); - host_reg = FP_LOAD_REG_INT_W(0); + host_reg = FP_LOAD_REG_INT_W(0); - STORE_IMM_ADDR_L((uintptr_t)&cpu_state.oldpc, op_old_pc); + STORE_IMM_ADDR_L((uintptr_t) &cpu_state.oldpc, op_old_pc); - CHECK_SEG_WRITE(target_seg); - - MEM_STORE_ADDR_EA_W(target_seg, host_reg); + CHECK_SEG_WRITE(target_seg); - return op_pc + 1; + MEM_STORE_ADDR_EA_W(target_seg, host_reg); + + return op_pc + 1; } -static uint32_t ropFISTl(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block) +static uint32_t +ropFISTl(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block) { - x86seg *target_seg; - int host_reg; + x86seg *target_seg; + int host_reg; - FP_ENTER(); - op_pc--; - target_seg = FETCH_EA(op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32); + FP_ENTER(); + op_pc--; + target_seg = FETCH_EA(op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32); - host_reg = FP_LOAD_REG_INT(0); + host_reg = FP_LOAD_REG_INT(0); - STORE_IMM_ADDR_L((uintptr_t)&cpu_state.oldpc, op_old_pc); + STORE_IMM_ADDR_L((uintptr_t) &cpu_state.oldpc, op_old_pc); - CHECK_SEG_WRITE(target_seg); - - MEM_STORE_ADDR_EA_L(target_seg, host_reg); + CHECK_SEG_WRITE(target_seg); - return op_pc + 1; + MEM_STORE_ADDR_EA_L(target_seg, host_reg); + + return op_pc + 1; } -static uint32_t ropFISTPw(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block) +static uint32_t +ropFISTPw(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block) { - uint32_t new_pc = ropFISTw(opcode, fetchdat, op_32, op_pc, block); - - FP_POP(); - - return new_pc; + uint32_t new_pc = ropFISTw(opcode, fetchdat, op_32, op_pc, block); + + FP_POP(); + + return new_pc; } -static uint32_t ropFISTPl(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block) +static uint32_t +ropFISTPl(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block) { - uint32_t new_pc = ropFISTl(opcode, fetchdat, op_32, op_pc, block); - - FP_POP(); - - return new_pc; + uint32_t new_pc = ropFISTl(opcode, fetchdat, op_32, op_pc, block); + + FP_POP(); + + return new_pc; } -static uint32_t ropFISTPq(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block) +static uint32_t +ropFISTPq(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block) { - x86seg *target_seg; - int host_reg1, host_reg2; + x86seg *target_seg; + int host_reg1; + int host_reg2; - FP_ENTER(); - op_pc--; - target_seg = FETCH_EA(op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32); + FP_ENTER(); + op_pc--; + target_seg = FETCH_EA(op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32); - FP_LOAD_REG_INT_Q(0, &host_reg1, &host_reg2); + FP_LOAD_REG_INT_Q(0, &host_reg1, &host_reg2); - STORE_IMM_ADDR_L((uintptr_t)&cpu_state.oldpc, op_old_pc); + STORE_IMM_ADDR_L((uintptr_t) &cpu_state.oldpc, op_old_pc); - CHECK_SEG_WRITE(target_seg); - - MEM_STORE_ADDR_EA_Q(target_seg, host_reg1, host_reg2); + CHECK_SEG_WRITE(target_seg); - FP_POP(); - - return op_pc + 1; + MEM_STORE_ADDR_EA_Q(target_seg, host_reg1, host_reg2); + + FP_POP(); + + return op_pc + 1; } - -static uint32_t ropFLDCW(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block) +static uint32_t +ropFLDCW(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block) { - x86seg *target_seg; + x86seg *target_seg; - FP_ENTER(); - op_pc--; - target_seg = FETCH_EA(op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32); + FP_ENTER(); + op_pc--; + target_seg = FETCH_EA(op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32); - CHECK_SEG_READ(target_seg); - - MEM_LOAD_ADDR_EA_W(target_seg); - STORE_HOST_REG_ADDR_W((uintptr_t)&cpu_state.npxc, 0); - UPDATE_NPXC(0); - - return op_pc + 1; + CHECK_SEG_READ(target_seg); + + MEM_LOAD_ADDR_EA_W(target_seg); + STORE_HOST_REG_ADDR_W((uintptr_t) &cpu_state.npxc, 0); + UPDATE_NPXC(0); + + return op_pc + 1; } -static uint32_t ropFSTCW(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block) +static uint32_t +ropFSTCW(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block) { - int host_reg; - x86seg *target_seg; + int host_reg; + x86seg *target_seg; - FP_ENTER(); - op_pc--; - target_seg = FETCH_EA(op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32); + FP_ENTER(); + op_pc--; + target_seg = FETCH_EA(op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32); - CHECK_SEG_WRITE(target_seg); + CHECK_SEG_WRITE(target_seg); - host_reg = LOAD_VAR_W((uintptr_t)&cpu_state.npxc); - MEM_STORE_ADDR_EA_W(target_seg, host_reg); - - return op_pc + 1; + host_reg = LOAD_VAR_W((uintptr_t) &cpu_state.npxc); + MEM_STORE_ADDR_EA_W(target_seg, host_reg); + + return op_pc + 1; } - -static uint32_t ropFCHS(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block) +static uint32_t +ropFCHS(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block) { - FP_ENTER(); - FP_FCHS(); - - return op_pc; + FP_ENTER(); + FP_FCHS(); + + return op_pc; } -#define opFLDimm(name, v) \ - static uint32_t ropFLD ## name(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block) \ - { \ - static double fp_imm = v; \ - \ - FP_ENTER(); \ - FP_LOAD_IMM_Q(*(uint64_t *)&fp_imm); \ - \ - return op_pc; \ - } +#define opFLDimm(name, v) \ + static uint32_t \ + ropFLD##name(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block) \ + { \ + static double fp_imm = v; \ + \ + FP_ENTER(); \ + FP_LOAD_IMM_Q(*(uint64_t *) &fp_imm); \ + \ + return op_pc; \ + } +// clang-format off opFLDimm(1, 1.0) opFLDimm(L2T, 3.3219280948873623) opFLDimm(L2E, 1.4426950408889634); opFLDimm(PI, 3.141592653589793); opFLDimm(EG2, 0.3010299956639812); opFLDimm(Z, 0.0) +// clang-format on -static uint32_t ropFLDLN2(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block) +static uint32_t +ropFLDLN2(UNUSED(uint8_t opcode), uint32_t fetchdat, UNUSED(uint32_t op_32), uint32_t op_pc, UNUSED(codeblock_t *block)) { - FP_ENTER(); - FP_LOAD_IMM_Q(0x3fe62e42fefa39f0ull); + FP_ENTER(); + FP_LOAD_IMM_Q(0x3fe62e42fefa39f0ULL); - return op_pc; + return op_pc; } diff --git a/src/codegen/codegen_ops_jump.h b/src/codegen/codegen_ops_jump.h index 0ad293744..da16ce03e 100644 --- a/src/codegen/codegen_ops_jump.h +++ b/src/codegen/codegen_ops_jump.h @@ -1,257 +1,261 @@ -static uint32_t ropJMP_r8(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block) +static uint32_t +ropJMP_r8(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block) { - uint32_t offset = fetchdat & 0xff; + uint32_t offset = fetchdat & 0xff; - if (offset & 0x80) - offset |= 0xffffff00; + if (offset & 0x80) + offset |= 0xffffff00; - STORE_IMM_ADDR_L((uintptr_t)&cpu_state.pc, op_pc+1+offset); - - return -1; + STORE_IMM_ADDR_L((uintptr_t) &cpu_state.pc, op_pc + 1 + offset); + + return -1; } -static uint32_t ropJMP_r16(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block) +static uint32_t +ropJMP_r16(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block) { - uint16_t offset = fetchdat & 0xffff; + uint16_t offset = fetchdat & 0xffff; - STORE_IMM_ADDR_L((uintptr_t)&cpu_state.pc, (op_pc+2+offset) & 0xffff); - - return -1; + STORE_IMM_ADDR_L((uintptr_t) &cpu_state.pc, (op_pc + 2 + offset) & 0xffff); + + return -1; } -static uint32_t ropJMP_r32(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block) +static uint32_t +ropJMP_r32(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block) { - uint32_t offset = fastreadl(cs + op_pc); + uint32_t offset = fastreadl(cs + op_pc); - STORE_IMM_ADDR_L((uintptr_t)&cpu_state.pc, op_pc+4+offset); - - return -1; + STORE_IMM_ADDR_L((uintptr_t) &cpu_state.pc, op_pc + 4 + offset); + + return -1; } - -static uint32_t ropJCXZ(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block) +static uint32_t +ropJCXZ(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block) { - uint32_t offset = fetchdat & 0xff; + uint32_t offset = fetchdat & 0xff; - if (offset & 0x80) - offset |= 0xffffff00; + if (offset & 0x80) + offset |= 0xffffff00; - if (op_32 & 0x200) - { - int host_reg = LOAD_REG_L(REG_ECX); - TEST_ZERO_JUMP_L(host_reg, op_pc+1+offset, 0); - } - else - { - int host_reg = LOAD_REG_W(REG_CX); - TEST_ZERO_JUMP_W(host_reg, op_pc+1+offset, 0); - } - - return op_pc+1; + if (op_32 & 0x200) { + int host_reg = LOAD_REG_L(REG_ECX); + TEST_ZERO_JUMP_L(host_reg, op_pc + 1 + offset, 0); + } else { + int host_reg = LOAD_REG_W(REG_CX); + TEST_ZERO_JUMP_W(host_reg, op_pc + 1 + offset, 0); + } + + return op_pc + 1; } -static uint32_t ropLOOP(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block) +static uint32_t +ropLOOP(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block) { - uint32_t offset = fetchdat & 0xff; + uint32_t offset = fetchdat & 0xff; - if (offset & 0x80) - offset |= 0xffffff00; - - if (op_32 & 0x200) - { - int host_reg = LOAD_REG_L(REG_ECX); - SUB_HOST_REG_IMM(host_reg, 1); - STORE_REG_L_RELEASE(host_reg); - TEST_NONZERO_JUMP_L(host_reg, op_pc+1+offset, 0); - } - else - { - int host_reg = LOAD_REG_W(REG_CX); - SUB_HOST_REG_IMM(host_reg, 1); - STORE_REG_W_RELEASE(host_reg); - TEST_NONZERO_JUMP_W(host_reg, op_pc+1+offset, 0); - } - - return op_pc+1; + if (offset & 0x80) + offset |= 0xffffff00; + + if (op_32 & 0x200) { + int host_reg = LOAD_REG_L(REG_ECX); + SUB_HOST_REG_IMM(host_reg, 1); + STORE_REG_L_RELEASE(host_reg); + TEST_NONZERO_JUMP_L(host_reg, op_pc + 1 + offset, 0); + } else { + int host_reg = LOAD_REG_W(REG_CX); + SUB_HOST_REG_IMM(host_reg, 1); + STORE_REG_W_RELEASE(host_reg); + TEST_NONZERO_JUMP_W(host_reg, op_pc + 1 + offset, 0); + } + + return op_pc + 1; } -static void BRANCH_COND_B(int pc_offset, uint32_t op_pc, uint32_t offset, int not) +static void +BRANCH_COND_B(int pc_offset, uint32_t op_pc, uint32_t offset, int not ) { - CALL_FUNC((uintptr_t)CF_SET); - if (not) - TEST_ZERO_JUMP_L(0, op_pc+pc_offset+offset, timing_bt); - else - TEST_NONZERO_JUMP_L(0, op_pc+pc_offset+offset, timing_bt); + CALL_FUNC((uintptr_t) CF_SET); + if (not ) + TEST_ZERO_JUMP_L(0, op_pc + pc_offset + offset, timing_bt); + else + TEST_NONZERO_JUMP_L(0, op_pc + pc_offset + offset, timing_bt); } -static void BRANCH_COND_E(int pc_offset, uint32_t op_pc, uint32_t offset, int not) +static void +BRANCH_COND_E(int pc_offset, uint32_t op_pc, uint32_t offset, int not ) { - int host_reg; - - switch (codegen_flags_changed ? cpu_state.flags_op : FLAGS_UNKNOWN) - { - case FLAGS_ZN8: - case FLAGS_ZN16: - case FLAGS_ZN32: - case FLAGS_ADD8: - case FLAGS_ADD16: - case FLAGS_ADD32: - case FLAGS_SUB8: - case FLAGS_SUB16: - case FLAGS_SUB32: - case FLAGS_SHL8: - case FLAGS_SHL16: - case FLAGS_SHL32: - case FLAGS_SHR8: - case FLAGS_SHR16: - case FLAGS_SHR32: - case FLAGS_SAR8: - case FLAGS_SAR16: - case FLAGS_SAR32: - case FLAGS_INC8: - case FLAGS_INC16: - case FLAGS_INC32: - case FLAGS_DEC8: - case FLAGS_DEC16: - case FLAGS_DEC32: - host_reg = LOAD_VAR_L((uintptr_t)&cpu_state.flags_res); - if (not) - TEST_NONZERO_JUMP_L(host_reg, op_pc+pc_offset+offset, timing_bt); - else - TEST_ZERO_JUMP_L(host_reg, op_pc+pc_offset+offset, timing_bt); - break; - - case FLAGS_UNKNOWN: - CALL_FUNC((uintptr_t)ZF_SET); - if (not) - TEST_ZERO_JUMP_L(0, op_pc+pc_offset+offset, timing_bt); - else - TEST_NONZERO_JUMP_L(0, op_pc+pc_offset+offset, timing_bt); - break; - } + int host_reg; + + switch (codegen_flags_changed ? cpu_state.flags_op : FLAGS_UNKNOWN) { + case FLAGS_ZN8: + case FLAGS_ZN16: + case FLAGS_ZN32: + case FLAGS_ADD8: + case FLAGS_ADD16: + case FLAGS_ADD32: + case FLAGS_SUB8: + case FLAGS_SUB16: + case FLAGS_SUB32: + case FLAGS_SHL8: + case FLAGS_SHL16: + case FLAGS_SHL32: + case FLAGS_SHR8: + case FLAGS_SHR16: + case FLAGS_SHR32: + case FLAGS_SAR8: + case FLAGS_SAR16: + case FLAGS_SAR32: + case FLAGS_INC8: + case FLAGS_INC16: + case FLAGS_INC32: + case FLAGS_DEC8: + case FLAGS_DEC16: + case FLAGS_DEC32: + host_reg = LOAD_VAR_L((uintptr_t) &cpu_state.flags_res); + if (not ) + TEST_NONZERO_JUMP_L(host_reg, op_pc + pc_offset + offset, timing_bt); + else + TEST_ZERO_JUMP_L(host_reg, op_pc + pc_offset + offset, timing_bt); + break; + + case FLAGS_UNKNOWN: + CALL_FUNC((uintptr_t) ZF_SET); + if (not ) + TEST_ZERO_JUMP_L(0, op_pc + pc_offset + offset, timing_bt); + else + TEST_NONZERO_JUMP_L(0, op_pc + pc_offset + offset, timing_bt); + break; + } } -static void BRANCH_COND_O(int pc_offset, uint32_t op_pc, uint32_t offset, int not) +static void +BRANCH_COND_O(int pc_offset, uint32_t op_pc, uint32_t offset, int not ) { - CALL_FUNC((uintptr_t)VF_SET); - if (not) - TEST_ZERO_JUMP_L(0, op_pc+pc_offset+offset, timing_bt); - else - TEST_NONZERO_JUMP_L(0, op_pc+pc_offset+offset, timing_bt); + CALL_FUNC((uintptr_t) VF_SET); + if (not ) + TEST_ZERO_JUMP_L(0, op_pc + pc_offset + offset, timing_bt); + else + TEST_NONZERO_JUMP_L(0, op_pc + pc_offset + offset, timing_bt); } -static void BRANCH_COND_P(int pc_offset, uint32_t op_pc, uint32_t offset, int not) +static void +BRANCH_COND_P(int pc_offset, uint32_t op_pc, uint32_t offset, int not ) { - CALL_FUNC((uintptr_t)PF_SET); - if (not) - TEST_ZERO_JUMP_L(0, op_pc+pc_offset+offset, timing_bt); - else - TEST_NONZERO_JUMP_L(0, op_pc+pc_offset+offset, timing_bt); + CALL_FUNC((uintptr_t) PF_SET); + if (not ) + TEST_ZERO_JUMP_L(0, op_pc + pc_offset + offset, timing_bt); + else + TEST_NONZERO_JUMP_L(0, op_pc + pc_offset + offset, timing_bt); } -static void BRANCH_COND_S(int pc_offset, uint32_t op_pc, uint32_t offset, int not) +static void +BRANCH_COND_S(int pc_offset, uint32_t op_pc, uint32_t offset, int not ) { - int host_reg; - - switch (codegen_flags_changed ? cpu_state.flags_op : FLAGS_UNKNOWN) - { - case FLAGS_ZN8: - case FLAGS_ADD8: - case FLAGS_SUB8: - case FLAGS_SHL8: - case FLAGS_SHR8: - case FLAGS_SAR8: - case FLAGS_INC8: - case FLAGS_DEC8: - host_reg = LOAD_VAR_L((uintptr_t)&cpu_state.flags_res); - AND_HOST_REG_IMM(host_reg, 0x80); - if (not) - TEST_ZERO_JUMP_L(host_reg, op_pc+pc_offset+offset, timing_bt); - else - TEST_NONZERO_JUMP_L(host_reg, op_pc+pc_offset+offset, timing_bt); - break; + int host_reg; - case FLAGS_ZN16: - case FLAGS_ADD16: - case FLAGS_SUB16: - case FLAGS_SHL16: - case FLAGS_SHR16: - case FLAGS_SAR16: - case FLAGS_INC16: - case FLAGS_DEC16: - host_reg = LOAD_VAR_L((uintptr_t)&cpu_state.flags_res); - AND_HOST_REG_IMM(host_reg, 0x8000); - if (not) - TEST_ZERO_JUMP_L(host_reg, op_pc+pc_offset+offset, timing_bt); - else - TEST_NONZERO_JUMP_L(host_reg, op_pc+pc_offset+offset, timing_bt); - break; - - case FLAGS_ZN32: - case FLAGS_ADD32: - case FLAGS_SUB32: - case FLAGS_SHL32: - case FLAGS_SHR32: - case FLAGS_SAR32: - case FLAGS_INC32: - case FLAGS_DEC32: - host_reg = LOAD_VAR_L((uintptr_t)&cpu_state.flags_res); - AND_HOST_REG_IMM(host_reg, 0x80000000); - if (not) - TEST_ZERO_JUMP_L(host_reg, op_pc+pc_offset+offset, timing_bt); - else - TEST_NONZERO_JUMP_L(host_reg, op_pc+pc_offset+offset, timing_bt); - break; - - case FLAGS_UNKNOWN: - CALL_FUNC((uintptr_t)NF_SET); - if (not) - TEST_ZERO_JUMP_L(0, op_pc+pc_offset+offset, timing_bt); - else - TEST_NONZERO_JUMP_L(0, op_pc+pc_offset+offset, timing_bt); - break; - } + switch (codegen_flags_changed ? cpu_state.flags_op : FLAGS_UNKNOWN) { + case FLAGS_ZN8: + case FLAGS_ADD8: + case FLAGS_SUB8: + case FLAGS_SHL8: + case FLAGS_SHR8: + case FLAGS_SAR8: + case FLAGS_INC8: + case FLAGS_DEC8: + host_reg = LOAD_VAR_L((uintptr_t) &cpu_state.flags_res); + AND_HOST_REG_IMM(host_reg, 0x80); + if (not ) + TEST_ZERO_JUMP_L(host_reg, op_pc + pc_offset + offset, timing_bt); + else + TEST_NONZERO_JUMP_L(host_reg, op_pc + pc_offset + offset, timing_bt); + break; + + case FLAGS_ZN16: + case FLAGS_ADD16: + case FLAGS_SUB16: + case FLAGS_SHL16: + case FLAGS_SHR16: + case FLAGS_SAR16: + case FLAGS_INC16: + case FLAGS_DEC16: + host_reg = LOAD_VAR_L((uintptr_t) &cpu_state.flags_res); + AND_HOST_REG_IMM(host_reg, 0x8000); + if (not ) + TEST_ZERO_JUMP_L(host_reg, op_pc + pc_offset + offset, timing_bt); + else + TEST_NONZERO_JUMP_L(host_reg, op_pc + pc_offset + offset, timing_bt); + break; + + case FLAGS_ZN32: + case FLAGS_ADD32: + case FLAGS_SUB32: + case FLAGS_SHL32: + case FLAGS_SHR32: + case FLAGS_SAR32: + case FLAGS_INC32: + case FLAGS_DEC32: + host_reg = LOAD_VAR_L((uintptr_t) &cpu_state.flags_res); + AND_HOST_REG_IMM(host_reg, 0x80000000); + if (not ) + TEST_ZERO_JUMP_L(host_reg, op_pc + pc_offset + offset, timing_bt); + else + TEST_NONZERO_JUMP_L(host_reg, op_pc + pc_offset + offset, timing_bt); + break; + + case FLAGS_UNKNOWN: + CALL_FUNC((uintptr_t) NF_SET); + if (not ) + TEST_ZERO_JUMP_L(0, op_pc + pc_offset + offset, timing_bt); + else + TEST_NONZERO_JUMP_L(0, op_pc + pc_offset + offset, timing_bt); + break; + } } +#define ropBRANCH(name, func, not ) \ + static uint32_t \ + rop##name(uint8_t opcode, uint32_t fetchdat, \ + uint32_t op_32, uint32_t op_pc, \ + codeblock_t *block) \ + { \ + uint32_t offset = fetchdat & 0xff; \ + \ + if (offset & 0x80) \ + offset |= 0xffffff00; \ + \ + func(1, op_pc, offset, not ); \ + \ + return op_pc + 1; \ + } \ + static uint32_t \ + rop##name##_w(uint8_t opcode, \ + uint32_t fetchdat, uint32_t op_32, \ + uint32_t op_pc, codeblock_t *block) \ + { \ + uint32_t offset = fetchdat & 0xffff; \ + \ + if (offset & 0x8000) \ + offset |= 0xffff0000; \ + \ + func(2, op_pc, offset, not ); \ + \ + return op_pc + 2; \ + } \ + static uint32_t \ + rop##name##_l(uint8_t opcode, \ + uint32_t fetchdat, uint32_t op_32, \ + uint32_t op_pc, codeblock_t *block) \ + { \ + uint32_t offset = fastreadl(cs + op_pc); \ + \ + func(4, op_pc, offset, not ); \ + \ + return op_pc + 4; \ + } -#define ropBRANCH(name, func, not) \ -static uint32_t rop ## name(uint8_t opcode, uint32_t fetchdat, \ - uint32_t op_32, uint32_t op_pc, \ - codeblock_t *block) \ -{ \ - uint32_t offset = fetchdat & 0xff; \ - \ - if (offset & 0x80) \ - offset |= 0xffffff00; \ - \ - func(1, op_pc, offset, not); \ - \ - return op_pc+1; \ -} \ -static uint32_t rop ## name ## _w(uint8_t opcode, \ - uint32_t fetchdat, uint32_t op_32, \ - uint32_t op_pc, codeblock_t *block) \ -{ \ - uint32_t offset = fetchdat & 0xffff; \ - \ - if (offset & 0x8000) \ - offset |= 0xffff0000; \ - \ - func(2, op_pc, offset, not); \ - \ - return op_pc+2; \ -} \ -static uint32_t rop ## name ## _l(uint8_t opcode, \ - uint32_t fetchdat, uint32_t op_32, \ - uint32_t op_pc, codeblock_t *block) \ -{ \ - uint32_t offset = fastreadl(cs + op_pc); \ - \ - func(4, op_pc, offset, not); \ - \ - return op_pc+4; \ -} - +// clang-format off ropBRANCH(JB, BRANCH_COND_B, 0) ropBRANCH(JNB, BRANCH_COND_B, 1) ropBRANCH(JE, BRANCH_COND_E, 0) @@ -268,3 +272,4 @@ ropBRANCH(JLE, BRANCH_COND_LE, 0) ropBRANCH(JNLE, BRANCH_COND_LE, 1) ropBRANCH(JBE, BRANCH_COND_BE, 0) ropBRANCH(JNBE, BRANCH_COND_BE, 1) +// clang-format on diff --git a/src/codegen/codegen_ops_logic.h b/src/codegen/codegen_ops_logic.h index c0ffa641a..9f23723e2 100644 --- a/src/codegen/codegen_ops_logic.h +++ b/src/codegen/codegen_ops_logic.h @@ -1,564 +1,555 @@ -#define ROP_LOGIC(name, op, writeback) \ - static uint32_t rop ## name ## _b_rmw(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block) \ - { \ - int src_reg, dst_reg; \ - x86seg *target_seg; \ - \ - if ((fetchdat & 0xc0) == 0xc0) \ - { \ - dst_reg = LOAD_REG_B(fetchdat & 7); \ - } \ - else \ - { \ - target_seg = FETCH_EA(op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32); \ - STORE_IMM_ADDR_L((uintptr_t)&cpu_state.oldpc, op_old_pc); \ - SAVE_EA(); \ - MEM_CHECK_WRITE(target_seg); \ - dst_reg = MEM_LOAD_ADDR_EA_B_NO_ABRT(target_seg); \ - } \ - STORE_IMM_ADDR_L((uintptr_t)&cpu_state.flags_op, FLAGS_ZN8); \ - src_reg = LOAD_REG_B((fetchdat >> 3) & 7); \ - op ## _HOST_REG_B(dst_reg, src_reg); \ - STORE_HOST_REG_ADDR_BL((uintptr_t)&cpu_state.flags_res, dst_reg); \ - if (writeback) \ - { \ - if ((fetchdat & 0xc0) == 0xc0) \ - STORE_REG_B_RELEASE(dst_reg); \ - else \ - { \ - LOAD_EA(); \ - MEM_STORE_ADDR_EA_B_NO_ABRT(target_seg, dst_reg); \ - } \ - } \ - else \ - RELEASE_REG(dst_reg); \ - RELEASE_REG(src_reg); \ - \ - return op_pc + 1; \ - } \ - static uint32_t rop ## name ## _w_rmw(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block) \ - { \ - int src_reg, dst_reg; \ - x86seg *target_seg; \ - \ - if ((fetchdat & 0xc0) == 0xc0) \ - { \ - dst_reg = LOAD_REG_W(fetchdat & 7); \ - } \ - else \ - { \ - target_seg = FETCH_EA(op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32); \ - STORE_IMM_ADDR_L((uintptr_t)&cpu_state.oldpc, op_old_pc); \ - SAVE_EA(); \ - MEM_CHECK_WRITE_W(target_seg); \ - dst_reg = MEM_LOAD_ADDR_EA_W_NO_ABRT(target_seg); \ - } \ - STORE_IMM_ADDR_L((uintptr_t)&cpu_state.flags_op, FLAGS_ZN16); \ - src_reg = LOAD_REG_W((fetchdat >> 3) & 7); \ - op ## _HOST_REG_W(dst_reg, src_reg); \ - STORE_HOST_REG_ADDR_WL((uintptr_t)&cpu_state.flags_res, dst_reg); \ - if (writeback) \ - { \ - if ((fetchdat & 0xc0) == 0xc0) \ - STORE_REG_W_RELEASE(dst_reg); \ - else \ - { \ - LOAD_EA(); \ - MEM_STORE_ADDR_EA_W_NO_ABRT(target_seg, dst_reg); \ - } \ - } \ - else \ - RELEASE_REG(dst_reg); \ - RELEASE_REG(src_reg); \ - \ - return op_pc + 1; \ - } \ - static uint32_t rop ## name ## _l_rmw(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block) \ - { \ - int src_reg, dst_reg; \ - x86seg *target_seg; \ - \ - if ((fetchdat & 0xc0) == 0xc0) \ - { \ - dst_reg = LOAD_REG_L(fetchdat & 7); \ - } \ - else \ - { \ - target_seg = FETCH_EA(op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32); \ - STORE_IMM_ADDR_L((uintptr_t)&cpu_state.oldpc, op_old_pc); \ - SAVE_EA(); \ - MEM_CHECK_WRITE_L(target_seg); \ - dst_reg = MEM_LOAD_ADDR_EA_L_NO_ABRT(target_seg); \ - } \ - STORE_IMM_ADDR_L((uintptr_t)&cpu_state.flags_op, FLAGS_ZN32); \ - src_reg = LOAD_REG_L((fetchdat >> 3) & 7); \ - op ## _HOST_REG_L(dst_reg, src_reg); \ - STORE_HOST_REG_ADDR((uintptr_t)&cpu_state.flags_res, dst_reg); \ - if (writeback) \ - { \ - if ((fetchdat & 0xc0) == 0xc0) \ - STORE_REG_L_RELEASE(dst_reg); \ - else \ - { \ - LOAD_EA(); \ - MEM_STORE_ADDR_EA_L_NO_ABRT(target_seg, dst_reg); \ - } \ - } \ - else \ - RELEASE_REG(dst_reg); \ - RELEASE_REG(src_reg); \ - \ - return op_pc + 1; \ - } \ - static uint32_t rop ## name ## _b_rm(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block) \ - { \ - int src_reg, dst_reg; \ - \ - if ((fetchdat & 0xc0) == 0xc0) \ - { \ - src_reg = LOAD_REG_B(fetchdat & 7); \ - } \ - else \ - { \ - x86seg *target_seg = FETCH_EA(op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32); \ - STORE_IMM_ADDR_L((uintptr_t)&cpu_state.oldpc, op_old_pc); \ - MEM_LOAD_ADDR_EA_B(target_seg); \ - src_reg = 0; \ - } \ - \ - dst_reg = LOAD_REG_B((fetchdat >> 3) & 7); \ - STORE_IMM_ADDR_L((uintptr_t)&cpu_state.flags_op, FLAGS_ZN8); \ - op ## _HOST_REG_B(dst_reg, src_reg); \ - STORE_HOST_REG_ADDR_BL((uintptr_t)&cpu_state.flags_res, dst_reg); \ - if (writeback) STORE_REG_B_RELEASE(dst_reg); \ - else RELEASE_REG(dst_reg); \ - RELEASE_REG(src_reg); \ - \ - return op_pc + 1; \ - } \ - static uint32_t rop ## name ## _w_rm(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block) \ - { \ - int src_reg, dst_reg; \ - \ - if ((fetchdat & 0xc0) == 0xc0) \ - { \ - src_reg = LOAD_REG_W(fetchdat & 7); \ - } \ - else \ - { \ - x86seg *target_seg = FETCH_EA(op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32); \ - STORE_IMM_ADDR_L((uintptr_t)&cpu_state.oldpc, op_old_pc); \ - MEM_LOAD_ADDR_EA_W(target_seg); \ - src_reg = 0; \ - } \ - \ - dst_reg = LOAD_REG_W((fetchdat >> 3) & 7); \ - STORE_IMM_ADDR_L((uintptr_t)&cpu_state.flags_op, FLAGS_ZN16); \ - op ## _HOST_REG_W(dst_reg, src_reg); \ - STORE_HOST_REG_ADDR_WL((uintptr_t)&cpu_state.flags_res, dst_reg); \ - if (writeback) STORE_REG_W_RELEASE(dst_reg); \ - else RELEASE_REG(dst_reg); \ - RELEASE_REG(src_reg); \ - \ - return op_pc + 1; \ - } \ - static uint32_t rop ## name ## _l_rm(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block) \ - { \ - int src_reg, dst_reg; \ - \ - if ((fetchdat & 0xc0) == 0xc0) \ - { \ - src_reg = LOAD_REG_L(fetchdat & 7); \ - } \ - else \ - { \ - x86seg *target_seg = FETCH_EA(op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32); \ - STORE_IMM_ADDR_L((uintptr_t)&cpu_state.oldpc, op_old_pc); \ - MEM_LOAD_ADDR_EA_L(target_seg); \ - src_reg = 0; \ - } \ - \ - dst_reg = LOAD_REG_L((fetchdat >> 3) & 7); \ - STORE_IMM_ADDR_L((uintptr_t)&cpu_state.flags_op, FLAGS_ZN32); \ - op ## _HOST_REG_L(dst_reg, src_reg); \ - STORE_HOST_REG_ADDR((uintptr_t)&cpu_state.flags_res, dst_reg); \ - if (writeback) STORE_REG_L_RELEASE(dst_reg); \ - else RELEASE_REG(dst_reg); \ - RELEASE_REG(src_reg); \ - \ - return op_pc + 1; \ - } +#define ROP_LOGIC(name, op, writeback) \ + static uint32_t \ + rop##name##_b_rmw(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block) \ + { \ + int src_reg; \ + int dst_reg; \ + x86seg *target_seg; \ + \ + if ((fetchdat & 0xc0) == 0xc0) { \ + dst_reg = LOAD_REG_B(fetchdat & 7); \ + } else { \ + target_seg = FETCH_EA(op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32); \ + STORE_IMM_ADDR_L((uintptr_t) &cpu_state.oldpc, op_old_pc); \ + SAVE_EA(); \ + MEM_CHECK_WRITE(target_seg); \ + dst_reg = MEM_LOAD_ADDR_EA_B_NO_ABRT(target_seg); \ + } \ + STORE_IMM_ADDR_L((uintptr_t) &cpu_state.flags_op, FLAGS_ZN8); \ + src_reg = LOAD_REG_B((fetchdat >> 3) & 7); \ + op##_HOST_REG_B(dst_reg, src_reg); \ + STORE_HOST_REG_ADDR_BL((uintptr_t) &cpu_state.flags_res, dst_reg); \ + if (writeback) { \ + if ((fetchdat & 0xc0) == 0xc0) \ + STORE_REG_B_RELEASE(dst_reg); \ + else { \ + LOAD_EA(); \ + MEM_STORE_ADDR_EA_B_NO_ABRT(target_seg, dst_reg); \ + } \ + } else \ + RELEASE_REG(dst_reg); \ + RELEASE_REG(src_reg); \ + \ + return op_pc + 1; \ + } \ + static uint32_t \ + rop##name##_w_rmw(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block) \ + { \ + int src_reg; \ + int dst_reg; \ + x86seg *target_seg; \ + \ + if ((fetchdat & 0xc0) == 0xc0) { \ + dst_reg = LOAD_REG_W(fetchdat & 7); \ + } else { \ + target_seg = FETCH_EA(op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32); \ + STORE_IMM_ADDR_L((uintptr_t) &cpu_state.oldpc, op_old_pc); \ + SAVE_EA(); \ + MEM_CHECK_WRITE_W(target_seg); \ + dst_reg = MEM_LOAD_ADDR_EA_W_NO_ABRT(target_seg); \ + } \ + STORE_IMM_ADDR_L((uintptr_t) &cpu_state.flags_op, FLAGS_ZN16); \ + src_reg = LOAD_REG_W((fetchdat >> 3) & 7); \ + op##_HOST_REG_W(dst_reg, src_reg); \ + STORE_HOST_REG_ADDR_WL((uintptr_t) &cpu_state.flags_res, dst_reg); \ + if (writeback) { \ + if ((fetchdat & 0xc0) == 0xc0) \ + STORE_REG_W_RELEASE(dst_reg); \ + else { \ + LOAD_EA(); \ + MEM_STORE_ADDR_EA_W_NO_ABRT(target_seg, dst_reg); \ + } \ + } else \ + RELEASE_REG(dst_reg); \ + RELEASE_REG(src_reg); \ + \ + return op_pc + 1; \ + } \ + static uint32_t \ + rop##name##_l_rmw(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block) \ + { \ + int src_reg; \ + int dst_reg; \ + x86seg *target_seg; \ + \ + if ((fetchdat & 0xc0) == 0xc0) { \ + dst_reg = LOAD_REG_L(fetchdat & 7); \ + } else { \ + target_seg = FETCH_EA(op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32); \ + STORE_IMM_ADDR_L((uintptr_t) &cpu_state.oldpc, op_old_pc); \ + SAVE_EA(); \ + MEM_CHECK_WRITE_L(target_seg); \ + dst_reg = MEM_LOAD_ADDR_EA_L_NO_ABRT(target_seg); \ + } \ + STORE_IMM_ADDR_L((uintptr_t) &cpu_state.flags_op, FLAGS_ZN32); \ + src_reg = LOAD_REG_L((fetchdat >> 3) & 7); \ + op##_HOST_REG_L(dst_reg, src_reg); \ + STORE_HOST_REG_ADDR((uintptr_t) &cpu_state.flags_res, dst_reg); \ + if (writeback) { \ + if ((fetchdat & 0xc0) == 0xc0) \ + STORE_REG_L_RELEASE(dst_reg); \ + else { \ + LOAD_EA(); \ + MEM_STORE_ADDR_EA_L_NO_ABRT(target_seg, dst_reg); \ + } \ + } else \ + RELEASE_REG(dst_reg); \ + RELEASE_REG(src_reg); \ + \ + return op_pc + 1; \ + } \ + static uint32_t \ + rop##name##_b_rm(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block) \ + { \ + int src_reg; \ + int dst_reg; \ + \ + if ((fetchdat & 0xc0) == 0xc0) { \ + src_reg = LOAD_REG_B(fetchdat & 7); \ + } else { \ + x86seg *target_seg = FETCH_EA(op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32); \ + STORE_IMM_ADDR_L((uintptr_t) &cpu_state.oldpc, op_old_pc); \ + MEM_LOAD_ADDR_EA_B(target_seg); \ + src_reg = 0; \ + } \ + \ + dst_reg = LOAD_REG_B((fetchdat >> 3) & 7); \ + STORE_IMM_ADDR_L((uintptr_t) &cpu_state.flags_op, FLAGS_ZN8); \ + op##_HOST_REG_B(dst_reg, src_reg); \ + STORE_HOST_REG_ADDR_BL((uintptr_t) &cpu_state.flags_res, dst_reg); \ + if (writeback) \ + STORE_REG_B_RELEASE(dst_reg); \ + else \ + RELEASE_REG(dst_reg); \ + RELEASE_REG(src_reg); \ + \ + return op_pc + 1; \ + } \ + static uint32_t \ + rop##name##_w_rm(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block) \ + { \ + int src_reg; \ + int dst_reg; \ + \ + if ((fetchdat & 0xc0) == 0xc0) { \ + src_reg = LOAD_REG_W(fetchdat & 7); \ + } else { \ + x86seg *target_seg = FETCH_EA(op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32); \ + STORE_IMM_ADDR_L((uintptr_t) &cpu_state.oldpc, op_old_pc); \ + MEM_LOAD_ADDR_EA_W(target_seg); \ + src_reg = 0; \ + } \ + \ + dst_reg = LOAD_REG_W((fetchdat >> 3) & 7); \ + STORE_IMM_ADDR_L((uintptr_t) &cpu_state.flags_op, FLAGS_ZN16); \ + op##_HOST_REG_W(dst_reg, src_reg); \ + STORE_HOST_REG_ADDR_WL((uintptr_t) &cpu_state.flags_res, dst_reg); \ + if (writeback) \ + STORE_REG_W_RELEASE(dst_reg); \ + else \ + RELEASE_REG(dst_reg); \ + RELEASE_REG(src_reg); \ + \ + return op_pc + 1; \ + } \ + static uint32_t \ + rop##name##_l_rm(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block) \ + { \ + int src_reg; \ + int dst_reg; \ + \ + if ((fetchdat & 0xc0) == 0xc0) { \ + src_reg = LOAD_REG_L(fetchdat & 7); \ + } else { \ + x86seg *target_seg = FETCH_EA(op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32); \ + STORE_IMM_ADDR_L((uintptr_t) &cpu_state.oldpc, op_old_pc); \ + MEM_LOAD_ADDR_EA_L(target_seg); \ + src_reg = 0; \ + } \ + \ + dst_reg = LOAD_REG_L((fetchdat >> 3) & 7); \ + STORE_IMM_ADDR_L((uintptr_t) &cpu_state.flags_op, FLAGS_ZN32); \ + op##_HOST_REG_L(dst_reg, src_reg); \ + STORE_HOST_REG_ADDR((uintptr_t) &cpu_state.flags_res, dst_reg); \ + if (writeback) \ + STORE_REG_L_RELEASE(dst_reg); \ + else \ + RELEASE_REG(dst_reg); \ + RELEASE_REG(src_reg); \ + \ + return op_pc + 1; \ + } ROP_LOGIC(AND, AND, 1) ROP_LOGIC(OR, OR, 1) ROP_LOGIC(XOR, XOR, 1) -static uint32_t ropTEST_b_rm(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block) +static uint32_t +ropTEST_b_rm(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block) { - int src_reg, dst_reg; + int src_reg; + int dst_reg; - if ((fetchdat & 0xc0) == 0xc0) - { - src_reg = LOAD_REG_B(fetchdat & 7); - } - else - { - x86seg *target_seg = FETCH_EA(op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32); - STORE_IMM_ADDR_L((uintptr_t)&cpu_state.oldpc, op_old_pc); + if ((fetchdat & 0xc0) == 0xc0) { + src_reg = LOAD_REG_B(fetchdat & 7); + } else { + x86seg *target_seg = FETCH_EA(op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32); + STORE_IMM_ADDR_L((uintptr_t) &cpu_state.oldpc, op_old_pc); + MEM_LOAD_ADDR_EA_B(target_seg); + src_reg = 0; + } + + dst_reg = LOAD_REG_B((fetchdat >> 3) & 7); + STORE_IMM_ADDR_L((uintptr_t) &cpu_state.flags_op, FLAGS_ZN8); + dst_reg = TEST_HOST_REG_B(dst_reg, src_reg); + STORE_HOST_REG_ADDR_BL((uintptr_t) &cpu_state.flags_res, dst_reg); + RELEASE_REG(dst_reg); + RELEASE_REG(src_reg); + + return op_pc + 1; +} +static uint32_t +ropTEST_w_rm(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block) +{ + int src_reg; + int dst_reg; + + if ((fetchdat & 0xc0) == 0xc0) { + src_reg = LOAD_REG_W(fetchdat & 7); + } else { + x86seg *target_seg = FETCH_EA(op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32); + STORE_IMM_ADDR_L((uintptr_t) &cpu_state.oldpc, op_old_pc); + MEM_LOAD_ADDR_EA_W(target_seg); + src_reg = 0; + } + + dst_reg = LOAD_REG_W((fetchdat >> 3) & 7); + STORE_IMM_ADDR_L((uintptr_t) &cpu_state.flags_op, FLAGS_ZN16); + dst_reg = TEST_HOST_REG_W(dst_reg, src_reg); + STORE_HOST_REG_ADDR_WL((uintptr_t) &cpu_state.flags_res, dst_reg); + RELEASE_REG(dst_reg); + RELEASE_REG(src_reg); + + return op_pc + 1; +} +static uint32_t +ropTEST_l_rm(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block) +{ + int src_reg; + int dst_reg; + + if ((fetchdat & 0xc0) == 0xc0) { + src_reg = LOAD_REG_L(fetchdat & 7); + } else { + x86seg *target_seg = FETCH_EA(op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32); + STORE_IMM_ADDR_L((uintptr_t) &cpu_state.oldpc, op_old_pc); + MEM_LOAD_ADDR_EA_L(target_seg); + src_reg = 0; + } + + dst_reg = LOAD_REG_L((fetchdat >> 3) & 7); + STORE_IMM_ADDR_L((uintptr_t) &cpu_state.flags_op, FLAGS_ZN32); + dst_reg = TEST_HOST_REG_L(dst_reg, src_reg); + STORE_HOST_REG_ADDR((uintptr_t) &cpu_state.flags_res, dst_reg); + RELEASE_REG(dst_reg); + RELEASE_REG(src_reg); + + return op_pc + 1; +} + +static uint32_t +ropAND_AL_imm(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block) +{ + int host_reg = LOAD_REG_B(REG_AL); + + AND_HOST_REG_IMM(host_reg, (fetchdat & 0xff) | 0xffffff00); + STORE_IMM_ADDR_L((uintptr_t) &cpu_state.flags_op, FLAGS_ZN8); + STORE_HOST_REG_ADDR_BL((uintptr_t) &cpu_state.flags_res, host_reg); + STORE_REG_B_RELEASE(host_reg); + + return op_pc + 1; +} +static uint32_t +ropAND_AX_imm(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block) +{ + int host_reg = LOAD_REG_W(REG_AX); + + AND_HOST_REG_IMM(host_reg, (fetchdat & 0xffff) | 0xffff0000); + STORE_IMM_ADDR_L((uintptr_t) &cpu_state.flags_op, FLAGS_ZN16); + STORE_HOST_REG_ADDR_WL((uintptr_t) &cpu_state.flags_res, host_reg); + STORE_REG_W_RELEASE(host_reg); + + return op_pc + 2; +} +static uint32_t +ropAND_EAX_imm(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block) +{ + int host_reg = LOAD_REG_L(REG_EAX); + + fetchdat = fastreadl(cs + op_pc); + AND_HOST_REG_IMM(host_reg, fetchdat); + STORE_IMM_ADDR_L((uintptr_t) &cpu_state.flags_op, FLAGS_ZN32); + STORE_HOST_REG_ADDR((uintptr_t) &cpu_state.flags_res, host_reg); + STORE_REG_L_RELEASE(host_reg); + + return op_pc + 4; +} + +static uint32_t +ropOR_AL_imm(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block) +{ + int host_reg = LOAD_REG_B(REG_AL); + + OR_HOST_REG_IMM(host_reg, fetchdat & 0xff); + STORE_IMM_ADDR_L((uintptr_t) &cpu_state.flags_op, FLAGS_ZN8); + STORE_HOST_REG_ADDR_BL((uintptr_t) &cpu_state.flags_res, host_reg); + STORE_REG_B_RELEASE(host_reg); + + return op_pc + 1; +} +static uint32_t +ropOR_AX_imm(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block) +{ + int host_reg = LOAD_REG_W(REG_AX); + + OR_HOST_REG_IMM(host_reg, fetchdat & 0xffff); + STORE_IMM_ADDR_L((uintptr_t) &cpu_state.flags_op, FLAGS_ZN16); + STORE_HOST_REG_ADDR_WL((uintptr_t) &cpu_state.flags_res, host_reg); + STORE_REG_W_RELEASE(host_reg); + + return op_pc + 2; +} +static uint32_t +ropOR_EAX_imm(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block) +{ + int host_reg = LOAD_REG_L(REG_EAX); + + fetchdat = fastreadl(cs + op_pc); + OR_HOST_REG_IMM(host_reg, fetchdat); + STORE_IMM_ADDR_L((uintptr_t) &cpu_state.flags_op, FLAGS_ZN32); + STORE_HOST_REG_ADDR((uintptr_t) &cpu_state.flags_res, host_reg); + STORE_REG_L_RELEASE(host_reg); + + return op_pc + 4; +} + +static uint32_t +ropTEST_AL_imm(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block) +{ + int host_reg = LOAD_REG_B(REG_AL); + + host_reg = TEST_HOST_REG_IMM(host_reg, fetchdat & 0xff); + STORE_IMM_ADDR_L((uintptr_t) &cpu_state.flags_op, FLAGS_ZN8); + STORE_HOST_REG_ADDR((uintptr_t) &cpu_state.flags_res, host_reg); + RELEASE_REG(host_reg); + + return op_pc + 1; +} +static uint32_t +ropTEST_AX_imm(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block) +{ + int host_reg = LOAD_REG_W(REG_AX); + + host_reg = TEST_HOST_REG_IMM(host_reg, fetchdat & 0xffff); + STORE_IMM_ADDR_L((uintptr_t) &cpu_state.flags_op, FLAGS_ZN16); + STORE_HOST_REG_ADDR((uintptr_t) &cpu_state.flags_res, host_reg); + RELEASE_REG(host_reg); + + return op_pc + 2; +} +static uint32_t +ropTEST_EAX_imm(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block) +{ + int host_reg = LOAD_REG_L(REG_EAX); + + fetchdat = fastreadl(cs + op_pc); + host_reg = TEST_HOST_REG_IMM(host_reg, fetchdat); + STORE_IMM_ADDR_L((uintptr_t) &cpu_state.flags_op, FLAGS_ZN32); + STORE_HOST_REG_ADDR((uintptr_t) &cpu_state.flags_res, host_reg); + RELEASE_REG(host_reg); + + return op_pc + 4; +} + +static uint32_t +ropXOR_AL_imm(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block) +{ + int host_reg = LOAD_REG_B(REG_AL); + + XOR_HOST_REG_IMM(host_reg, fetchdat & 0xff); + STORE_IMM_ADDR_L((uintptr_t) &cpu_state.flags_op, FLAGS_ZN8); + STORE_HOST_REG_ADDR_BL((uintptr_t) &cpu_state.flags_res, host_reg); + STORE_REG_B_RELEASE(host_reg); + + return op_pc + 1; +} +static uint32_t +ropXOR_AX_imm(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block) +{ + int host_reg = LOAD_REG_W(REG_AX); + + XOR_HOST_REG_IMM(host_reg, fetchdat & 0xffff); + STORE_IMM_ADDR_L((uintptr_t) &cpu_state.flags_op, FLAGS_ZN16); + STORE_HOST_REG_ADDR_WL((uintptr_t) &cpu_state.flags_res, host_reg); + STORE_REG_W_RELEASE(host_reg); + + return op_pc + 2; +} +static uint32_t +ropXOR_EAX_imm(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block) +{ + int host_reg = LOAD_REG_L(REG_EAX); + + fetchdat = fastreadl(cs + op_pc); + XOR_HOST_REG_IMM(host_reg, fetchdat); + STORE_IMM_ADDR_L((uintptr_t) &cpu_state.flags_op, FLAGS_ZN32); + STORE_HOST_REG_ADDR((uintptr_t) &cpu_state.flags_res, host_reg); + STORE_REG_L_RELEASE(host_reg); + + return op_pc + 4; +} + +static uint32_t +ropF6(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block) +{ + x86seg *target_seg; + int host_reg; + uint8_t imm; + + switch (fetchdat & 0x38) { + case 0x00: /*TEST b,#8*/ + if ((fetchdat & 0xc0) == 0xc0) { + host_reg = LOAD_REG_B(fetchdat & 7); + imm = (fetchdat >> 8) & 0xff; + } else { + target_seg = FETCH_EA(op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32); + imm = fastreadb(cs + op_pc + 1); + STORE_IMM_ADDR_L((uintptr_t) &cpu_state.oldpc, op_old_pc); MEM_LOAD_ADDR_EA_B(target_seg); - src_reg = 0; - } + host_reg = 0; + } + STORE_IMM_ADDR_L((uintptr_t) &cpu_state.flags_op, FLAGS_ZN8); + host_reg = TEST_HOST_REG_IMM(host_reg, imm); + STORE_HOST_REG_ADDR_BL((uintptr_t) &cpu_state.flags_res, host_reg); + RELEASE_REG(host_reg); + return op_pc + 2; - dst_reg = LOAD_REG_B((fetchdat >> 3) & 7); - STORE_IMM_ADDR_L((uintptr_t)&cpu_state.flags_op, FLAGS_ZN8); - dst_reg = TEST_HOST_REG_B(dst_reg, src_reg); - STORE_HOST_REG_ADDR_BL((uintptr_t)&cpu_state.flags_res, dst_reg); - RELEASE_REG(dst_reg); - RELEASE_REG(src_reg); + case 0x10: /*NOT b*/ + if ((fetchdat & 0xc0) != 0xc0) + return 0; + host_reg = LOAD_REG_B(fetchdat & 7); + XOR_HOST_REG_IMM(host_reg, 0xff); + STORE_REG_B_RELEASE(host_reg); + return op_pc + 1; - return op_pc + 1; + case 0x18: /*NEG b*/ + if ((fetchdat & 0xc0) != 0xc0) + return 0; + STORE_IMM_ADDR_L((uintptr_t) &cpu_state.flags_op, FLAGS_SUB8); + host_reg = LOAD_REG_B(fetchdat & 7); + STORE_HOST_REG_ADDR_BL((uintptr_t) &cpu_state.flags_op2, host_reg); + NEG_HOST_REG_B(host_reg); + STORE_IMM_ADDR_L((uintptr_t) &cpu_state.flags_op1, 0); + STORE_REG_B_RELEASE(host_reg); + STORE_HOST_REG_ADDR_BL((uintptr_t) &cpu_state.flags_res, host_reg); + return op_pc + 1; + } + + return 0; } -static uint32_t ropTEST_w_rm(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block) +static uint32_t +ropF7_w(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block) { - int src_reg, dst_reg; + x86seg *target_seg; + int host_reg; + uint16_t imm; - if ((fetchdat & 0xc0) == 0xc0) - { - src_reg = LOAD_REG_W(fetchdat & 7); - } - else - { - x86seg *target_seg = FETCH_EA(op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32); - STORE_IMM_ADDR_L((uintptr_t)&cpu_state.oldpc, op_old_pc); + switch (fetchdat & 0x38) { + case 0x00: /*TEST w,#*/ + if ((fetchdat & 0xc0) == 0xc0) { + host_reg = LOAD_REG_W(fetchdat & 7); + imm = (fetchdat >> 8) & 0xffff; + } else { + target_seg = FETCH_EA(op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32); + imm = fastreadw(cs + op_pc + 1); + STORE_IMM_ADDR_L((uintptr_t) &cpu_state.oldpc, op_old_pc); MEM_LOAD_ADDR_EA_W(target_seg); - src_reg = 0; - } + host_reg = 0; + } + STORE_IMM_ADDR_L((uintptr_t) &cpu_state.flags_op, FLAGS_ZN16); + host_reg = TEST_HOST_REG_IMM(host_reg, imm); + STORE_HOST_REG_ADDR_WL((uintptr_t) &cpu_state.flags_res, host_reg); + RELEASE_REG(host_reg); + return op_pc + 3; - dst_reg = LOAD_REG_W((fetchdat >> 3) & 7); - STORE_IMM_ADDR_L((uintptr_t)&cpu_state.flags_op, FLAGS_ZN16); - dst_reg = TEST_HOST_REG_W(dst_reg, src_reg); - STORE_HOST_REG_ADDR_WL((uintptr_t)&cpu_state.flags_res, dst_reg); - RELEASE_REG(dst_reg); - RELEASE_REG(src_reg); + case 0x10: /*NOT w*/ + if ((fetchdat & 0xc0) != 0xc0) + return 0; + host_reg = LOAD_REG_W(fetchdat & 7); + XOR_HOST_REG_IMM(host_reg, 0xffff); + STORE_REG_W_RELEASE(host_reg); + return op_pc + 1; - return op_pc + 1; + case 0x18: /*NEG w*/ + if ((fetchdat & 0xc0) != 0xc0) + return 0; + STORE_IMM_ADDR_L((uintptr_t) &cpu_state.flags_op, FLAGS_SUB16); + host_reg = LOAD_REG_W(fetchdat & 7); + STORE_HOST_REG_ADDR_WL((uintptr_t) &cpu_state.flags_op2, host_reg); + NEG_HOST_REG_W(host_reg); + STORE_IMM_ADDR_L((uintptr_t) &cpu_state.flags_op1, 0); + STORE_REG_W_RELEASE(host_reg); + STORE_HOST_REG_ADDR_WL((uintptr_t) &cpu_state.flags_res, host_reg); + return op_pc + 1; + } + + return 0; } -static uint32_t ropTEST_l_rm(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block) +static uint32_t +ropF7_l(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block) { - int src_reg, dst_reg; + x86seg *target_seg; + int host_reg; + uint32_t imm; - if ((fetchdat & 0xc0) == 0xc0) - { - src_reg = LOAD_REG_L(fetchdat & 7); - } - else - { - x86seg *target_seg = FETCH_EA(op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32); - STORE_IMM_ADDR_L((uintptr_t)&cpu_state.oldpc, op_old_pc); + switch (fetchdat & 0x38) { + case 0x00: /*TEST l,#*/ + if ((fetchdat & 0xc0) == 0xc0) { + host_reg = LOAD_REG_L(fetchdat & 7); + imm = fastreadl(cs + op_pc + 1); + } else { + target_seg = FETCH_EA(op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32); + imm = fastreadl(cs + op_pc + 1); + STORE_IMM_ADDR_L((uintptr_t) &cpu_state.oldpc, op_old_pc); MEM_LOAD_ADDR_EA_L(target_seg); - src_reg = 0; - } + host_reg = 0; + } + STORE_IMM_ADDR_L((uintptr_t) &cpu_state.flags_op, FLAGS_ZN32); + host_reg = TEST_HOST_REG_IMM(host_reg, imm); + STORE_HOST_REG_ADDR((uintptr_t) &cpu_state.flags_res, host_reg); + RELEASE_REG(host_reg); + return op_pc + 5; - dst_reg = LOAD_REG_L((fetchdat >> 3) & 7); - STORE_IMM_ADDR_L((uintptr_t)&cpu_state.flags_op, FLAGS_ZN32); - dst_reg = TEST_HOST_REG_L(dst_reg, src_reg); - STORE_HOST_REG_ADDR((uintptr_t)&cpu_state.flags_res, dst_reg); - RELEASE_REG(dst_reg); - RELEASE_REG(src_reg); + case 0x10: /*NOT l*/ + if ((fetchdat & 0xc0) != 0xc0) + return 0; + host_reg = LOAD_REG_L(fetchdat & 7); + XOR_HOST_REG_IMM(host_reg, 0xffffffff); + STORE_REG_L_RELEASE(host_reg); + return op_pc + 1; - return op_pc + 1; -} - -static uint32_t ropAND_AL_imm(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block) -{ - int host_reg = LOAD_REG_B(REG_AL); - - AND_HOST_REG_IMM(host_reg, (fetchdat & 0xff) | 0xffffff00); - STORE_IMM_ADDR_L((uintptr_t)&cpu_state.flags_op, FLAGS_ZN8); - STORE_HOST_REG_ADDR_BL((uintptr_t)&cpu_state.flags_res, host_reg); - STORE_REG_B_RELEASE(host_reg); - - return op_pc + 1; -} -static uint32_t ropAND_AX_imm(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block) -{ - int host_reg = LOAD_REG_W(REG_AX); - - AND_HOST_REG_IMM(host_reg, (fetchdat & 0xffff) | 0xffff0000); - STORE_IMM_ADDR_L((uintptr_t)&cpu_state.flags_op, FLAGS_ZN16); - STORE_HOST_REG_ADDR_WL((uintptr_t)&cpu_state.flags_res, host_reg); - STORE_REG_W_RELEASE(host_reg); - - return op_pc + 2; -} -static uint32_t ropAND_EAX_imm(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block) -{ - int host_reg = LOAD_REG_L(REG_EAX); - - fetchdat = fastreadl(cs + op_pc); - AND_HOST_REG_IMM(host_reg, fetchdat); - STORE_IMM_ADDR_L((uintptr_t)&cpu_state.flags_op, FLAGS_ZN32); - STORE_HOST_REG_ADDR((uintptr_t)&cpu_state.flags_res, host_reg); - STORE_REG_L_RELEASE(host_reg); - - return op_pc + 4; -} - -static uint32_t ropOR_AL_imm(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block) -{ - int host_reg = LOAD_REG_B(REG_AL); - - OR_HOST_REG_IMM(host_reg, fetchdat & 0xff); - STORE_IMM_ADDR_L((uintptr_t)&cpu_state.flags_op, FLAGS_ZN8); - STORE_HOST_REG_ADDR_BL((uintptr_t)&cpu_state.flags_res, host_reg); - STORE_REG_B_RELEASE(host_reg); - - return op_pc + 1; -} -static uint32_t ropOR_AX_imm(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block) -{ - int host_reg = LOAD_REG_W(REG_AX); - - OR_HOST_REG_IMM(host_reg, fetchdat & 0xffff); - STORE_IMM_ADDR_L((uintptr_t)&cpu_state.flags_op, FLAGS_ZN16); - STORE_HOST_REG_ADDR_WL((uintptr_t)&cpu_state.flags_res, host_reg); - STORE_REG_W_RELEASE(host_reg); - - return op_pc + 2; -} -static uint32_t ropOR_EAX_imm(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block) -{ - int host_reg = LOAD_REG_L(REG_EAX); - - fetchdat = fastreadl(cs + op_pc); - OR_HOST_REG_IMM(host_reg, fetchdat); - STORE_IMM_ADDR_L((uintptr_t)&cpu_state.flags_op, FLAGS_ZN32); - STORE_HOST_REG_ADDR((uintptr_t)&cpu_state.flags_res, host_reg); - STORE_REG_L_RELEASE(host_reg); - - return op_pc + 4; -} - -static uint32_t ropTEST_AL_imm(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block) -{ - int host_reg = LOAD_REG_B(REG_AL); - - host_reg = TEST_HOST_REG_IMM(host_reg, fetchdat & 0xff); - STORE_IMM_ADDR_L((uintptr_t)&cpu_state.flags_op, FLAGS_ZN8); - STORE_HOST_REG_ADDR((uintptr_t)&cpu_state.flags_res, host_reg); - RELEASE_REG(host_reg); - - return op_pc + 1; -} -static uint32_t ropTEST_AX_imm(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block) -{ - int host_reg = LOAD_REG_W(REG_AX); - - host_reg = TEST_HOST_REG_IMM(host_reg, fetchdat & 0xffff); - STORE_IMM_ADDR_L((uintptr_t)&cpu_state.flags_op, FLAGS_ZN16); - STORE_HOST_REG_ADDR((uintptr_t)&cpu_state.flags_res, host_reg); - RELEASE_REG(host_reg); - - return op_pc + 2; -} -static uint32_t ropTEST_EAX_imm(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block) -{ - int host_reg = LOAD_REG_L(REG_EAX); - - fetchdat = fastreadl(cs + op_pc); - host_reg = TEST_HOST_REG_IMM(host_reg, fetchdat); - STORE_IMM_ADDR_L((uintptr_t)&cpu_state.flags_op, FLAGS_ZN32); - STORE_HOST_REG_ADDR((uintptr_t)&cpu_state.flags_res, host_reg); - RELEASE_REG(host_reg); - - return op_pc + 4; -} - -static uint32_t ropXOR_AL_imm(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block) -{ - int host_reg = LOAD_REG_B(REG_AL); - - XOR_HOST_REG_IMM(host_reg, fetchdat & 0xff); - STORE_IMM_ADDR_L((uintptr_t)&cpu_state.flags_op, FLAGS_ZN8); - STORE_HOST_REG_ADDR_BL((uintptr_t)&cpu_state.flags_res, host_reg); - STORE_REG_B_RELEASE(host_reg); - - return op_pc + 1; -} -static uint32_t ropXOR_AX_imm(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block) -{ - int host_reg = LOAD_REG_W(REG_AX); - - XOR_HOST_REG_IMM(host_reg, fetchdat & 0xffff); - STORE_IMM_ADDR_L((uintptr_t)&cpu_state.flags_op, FLAGS_ZN16); - STORE_HOST_REG_ADDR_WL((uintptr_t)&cpu_state.flags_res, host_reg); - STORE_REG_W_RELEASE(host_reg); - - return op_pc + 2; -} -static uint32_t ropXOR_EAX_imm(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block) -{ - int host_reg = LOAD_REG_L(REG_EAX); - - fetchdat = fastreadl(cs + op_pc); - XOR_HOST_REG_IMM(host_reg, fetchdat); - STORE_IMM_ADDR_L((uintptr_t)&cpu_state.flags_op, FLAGS_ZN32); - STORE_HOST_REG_ADDR((uintptr_t)&cpu_state.flags_res, host_reg); - STORE_REG_L_RELEASE(host_reg); - - return op_pc + 4; -} - -static uint32_t ropF6(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block) -{ - x86seg *target_seg; - int host_reg; - uint8_t imm; - - switch (fetchdat & 0x38) - { - case 0x00: /*TEST b,#8*/ - if ((fetchdat & 0xc0) == 0xc0) - { - host_reg = LOAD_REG_B(fetchdat & 7); - imm = (fetchdat >> 8) & 0xff; - } - else - { - target_seg = FETCH_EA(op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32); - imm = fastreadb(cs + op_pc + 1); - STORE_IMM_ADDR_L((uintptr_t)&cpu_state.oldpc, op_old_pc); - MEM_LOAD_ADDR_EA_B(target_seg); - host_reg = 0; - } - STORE_IMM_ADDR_L((uintptr_t)&cpu_state.flags_op, FLAGS_ZN8); - host_reg = TEST_HOST_REG_IMM(host_reg, imm); - STORE_HOST_REG_ADDR_BL((uintptr_t)&cpu_state.flags_res, host_reg); - RELEASE_REG(host_reg); - return op_pc + 2; - - case 0x10: /*NOT b*/ - if ((fetchdat & 0xc0) != 0xc0) - return 0; - host_reg = LOAD_REG_B(fetchdat & 7); - XOR_HOST_REG_IMM(host_reg, 0xff); - STORE_REG_B_RELEASE(host_reg); - return op_pc + 1; - - case 0x18: /*NEG b*/ - if ((fetchdat & 0xc0) != 0xc0) - return 0; - STORE_IMM_ADDR_L((uintptr_t)&cpu_state.flags_op, FLAGS_SUB8); - host_reg = LOAD_REG_B(fetchdat & 7); - STORE_HOST_REG_ADDR_BL((uintptr_t)&cpu_state.flags_op2, host_reg); - NEG_HOST_REG_B(host_reg); - STORE_IMM_ADDR_L((uintptr_t)&cpu_state.flags_op1, 0); - STORE_REG_B_RELEASE(host_reg); - STORE_HOST_REG_ADDR_BL((uintptr_t)&cpu_state.flags_res, host_reg); - return op_pc + 1; - } - - return 0; -} -static uint32_t ropF7_w(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block) -{ - x86seg *target_seg; - int host_reg; - uint16_t imm; - - switch (fetchdat & 0x38) - { - case 0x00: /*TEST w,#*/ - if ((fetchdat & 0xc0) == 0xc0) - { - host_reg = LOAD_REG_W(fetchdat & 7); - imm = (fetchdat >> 8) & 0xffff; - } - else - { - target_seg = FETCH_EA(op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32); - imm = fastreadw(cs + op_pc + 1); - STORE_IMM_ADDR_L((uintptr_t)&cpu_state.oldpc, op_old_pc); - MEM_LOAD_ADDR_EA_W(target_seg); - host_reg = 0; - } - STORE_IMM_ADDR_L((uintptr_t)&cpu_state.flags_op, FLAGS_ZN16); - host_reg = TEST_HOST_REG_IMM(host_reg, imm); - STORE_HOST_REG_ADDR_WL((uintptr_t)&cpu_state.flags_res, host_reg); - RELEASE_REG(host_reg); - return op_pc + 3; - - case 0x10: /*NOT w*/ - if ((fetchdat & 0xc0) != 0xc0) - return 0; - host_reg = LOAD_REG_W(fetchdat & 7); - XOR_HOST_REG_IMM(host_reg, 0xffff); - STORE_REG_W_RELEASE(host_reg); - return op_pc + 1; - - case 0x18: /*NEG w*/ - if ((fetchdat & 0xc0) != 0xc0) - return 0; - STORE_IMM_ADDR_L((uintptr_t)&cpu_state.flags_op, FLAGS_SUB16); - host_reg = LOAD_REG_W(fetchdat & 7); - STORE_HOST_REG_ADDR_WL((uintptr_t)&cpu_state.flags_op2, host_reg); - NEG_HOST_REG_W(host_reg); - STORE_IMM_ADDR_L((uintptr_t)&cpu_state.flags_op1, 0); - STORE_REG_W_RELEASE(host_reg); - STORE_HOST_REG_ADDR_WL((uintptr_t)&cpu_state.flags_res, host_reg); - return op_pc + 1; - } - - return 0; -} -static uint32_t ropF7_l(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block) -{ - x86seg *target_seg; - int host_reg; - uint32_t imm; - - switch (fetchdat & 0x38) - { - case 0x00: /*TEST l,#*/ - if ((fetchdat & 0xc0) == 0xc0) - { - host_reg = LOAD_REG_L(fetchdat & 7); - imm = fastreadl(cs + op_pc + 1); - } - else - { - target_seg = FETCH_EA(op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32); - imm = fastreadl(cs + op_pc + 1); - STORE_IMM_ADDR_L((uintptr_t)&cpu_state.oldpc, op_old_pc); - MEM_LOAD_ADDR_EA_L(target_seg); - host_reg = 0; - } - STORE_IMM_ADDR_L((uintptr_t)&cpu_state.flags_op, FLAGS_ZN32); - host_reg = TEST_HOST_REG_IMM(host_reg, imm); - STORE_HOST_REG_ADDR((uintptr_t)&cpu_state.flags_res, host_reg); - RELEASE_REG(host_reg); - return op_pc + 5; - - case 0x10: /*NOT l*/ - if ((fetchdat & 0xc0) != 0xc0) - return 0; - host_reg = LOAD_REG_L(fetchdat & 7); - XOR_HOST_REG_IMM(host_reg, 0xffffffff); - STORE_REG_L_RELEASE(host_reg); - return op_pc + 1; - - case 0x18: /*NEG l*/ - if ((fetchdat & 0xc0) != 0xc0) - return 0; - STORE_IMM_ADDR_L((uintptr_t)&cpu_state.flags_op, FLAGS_SUB32); - host_reg = LOAD_REG_L(fetchdat & 7); - STORE_HOST_REG_ADDR((uintptr_t)&cpu_state.flags_op2, host_reg); - NEG_HOST_REG_L(host_reg); - STORE_IMM_ADDR_L((uintptr_t)&cpu_state.flags_op1, 0); - STORE_REG_L_RELEASE(host_reg); - STORE_HOST_REG_ADDR((uintptr_t)&cpu_state.flags_res, host_reg); - return op_pc + 1; - } - - return 0; + case 0x18: /*NEG l*/ + if ((fetchdat & 0xc0) != 0xc0) + return 0; + STORE_IMM_ADDR_L((uintptr_t) &cpu_state.flags_op, FLAGS_SUB32); + host_reg = LOAD_REG_L(fetchdat & 7); + STORE_HOST_REG_ADDR((uintptr_t) &cpu_state.flags_op2, host_reg); + NEG_HOST_REG_L(host_reg); + STORE_IMM_ADDR_L((uintptr_t) &cpu_state.flags_op1, 0); + STORE_REG_L_RELEASE(host_reg); + STORE_HOST_REG_ADDR((uintptr_t) &cpu_state.flags_res, host_reg); + return op_pc + 1; + } + + return 0; } diff --git a/src/codegen/codegen_ops_misc.h b/src/codegen/codegen_ops_misc.h index bcafccfdb..61854ab37 100644 --- a/src/codegen/codegen_ops_misc.h +++ b/src/codegen/codegen_ops_misc.h @@ -1,272 +1,263 @@ -static uint32_t ropNOP(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block) +static uint32_t +ropNOP(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block) { - return op_pc; + return op_pc; } -static uint32_t ropCLD(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block) +static uint32_t +ropCLD(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block) { - CLEAR_BITS((uintptr_t)&cpu_state.flags, D_FLAG); - return op_pc; + CLEAR_BITS((uintptr_t) &cpu_state.flags, D_FLAG); + return op_pc; } -static uint32_t ropSTD(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block) +static uint32_t +ropSTD(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block) { - SET_BITS((uintptr_t)&cpu_state.flags, D_FLAG); - return op_pc; + SET_BITS((uintptr_t) &cpu_state.flags, D_FLAG); + return op_pc; } -static uint32_t ropCLI(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block) +static uint32_t +ropCLI(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block) { - if (!IOPLp && (cr4 & (CR4_VME | CR4_PVI))) - return 0; - CLEAR_BITS((uintptr_t)&cpu_state.flags, I_FLAG); + if (!IOPLp && (cr4 & (CR4_VME | CR4_PVI))) + return 0; + CLEAR_BITS((uintptr_t) &cpu_state.flags, I_FLAG); #ifdef CHECK_INT - CLEAR_BITS((uintptr_t)&pic_pending, 0xffffffff); + CLEAR_BITS((uintptr_t) &pic_pending, 0xffffffff); #endif - return op_pc; + return op_pc; } -static uint32_t ropSTI(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block) +static uint32_t +ropSTI(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block) { - if (!IOPLp && (cr4 & (CR4_VME | CR4_PVI))) - return 0; - SET_BITS((uintptr_t)&cpu_state.flags, I_FLAG); - return op_pc; + if (!IOPLp && (cr4 & (CR4_VME | CR4_PVI))) + return 0; + SET_BITS((uintptr_t) &cpu_state.flags, I_FLAG); + return op_pc; } -static uint32_t ropFE(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block) +static uint32_t +ropFE(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block) { - x86seg *target_seg = NULL; - int host_reg; + x86seg *target_seg = NULL; + int host_reg; - if ((fetchdat & 0x30) != 0x00) - return 0; + if ((fetchdat & 0x30) != 0x00) + return 0; - CALL_FUNC((uintptr_t)flags_rebuild_c); - - if ((fetchdat & 0xc0) == 0xc0) - host_reg = LOAD_REG_B(fetchdat & 7); - else - { - target_seg = FETCH_EA(op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32); - STORE_IMM_ADDR_L((uintptr_t)&cpu_state.oldpc, op_old_pc); + CALL_FUNC((uintptr_t) flags_rebuild_c); - SAVE_EA(); - MEM_CHECK_WRITE(target_seg); - host_reg = MEM_LOAD_ADDR_EA_B_NO_ABRT(target_seg); - } - - switch (fetchdat & 0x38) - { - case 0x00: /*INC*/ - STORE_HOST_REG_ADDR_BL((uintptr_t)&cpu_state.flags_op1, host_reg); - ADD_HOST_REG_IMM_B(host_reg, 1); - STORE_IMM_ADDR_L((uintptr_t)&cpu_state.flags_op2, 1); - STORE_IMM_ADDR_L((uintptr_t)&cpu_state.flags_op, FLAGS_INC8); - STORE_HOST_REG_ADDR_BL((uintptr_t)&cpu_state.flags_res, host_reg); - break; - case 0x08: /*DEC*/ - STORE_HOST_REG_ADDR_BL((uintptr_t)&cpu_state.flags_op1, host_reg); - SUB_HOST_REG_IMM_B(host_reg, 1); - STORE_IMM_ADDR_L((uintptr_t)&cpu_state.flags_op2, 1); - STORE_IMM_ADDR_L((uintptr_t)&cpu_state.flags_op, FLAGS_DEC8); - STORE_HOST_REG_ADDR_BL((uintptr_t)&cpu_state.flags_res, host_reg); - break; - } + if ((fetchdat & 0xc0) == 0xc0) + host_reg = LOAD_REG_B(fetchdat & 7); + else { + target_seg = FETCH_EA(op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32); + STORE_IMM_ADDR_L((uintptr_t) &cpu_state.oldpc, op_old_pc); - if ((fetchdat & 0xc0) == 0xc0) - STORE_REG_B_RELEASE(host_reg); - else - { - LOAD_EA(); - MEM_STORE_ADDR_EA_B_NO_ABRT(target_seg, host_reg); - } - codegen_flags_changed = 1; - - return op_pc + 1; + SAVE_EA(); + MEM_CHECK_WRITE(target_seg); + host_reg = MEM_LOAD_ADDR_EA_B_NO_ABRT(target_seg); + } + + switch (fetchdat & 0x38) { + case 0x00: /*INC*/ + STORE_HOST_REG_ADDR_BL((uintptr_t) &cpu_state.flags_op1, host_reg); + ADD_HOST_REG_IMM_B(host_reg, 1); + STORE_IMM_ADDR_L((uintptr_t) &cpu_state.flags_op2, 1); + STORE_IMM_ADDR_L((uintptr_t) &cpu_state.flags_op, FLAGS_INC8); + STORE_HOST_REG_ADDR_BL((uintptr_t) &cpu_state.flags_res, host_reg); + break; + case 0x08: /*DEC*/ + STORE_HOST_REG_ADDR_BL((uintptr_t) &cpu_state.flags_op1, host_reg); + SUB_HOST_REG_IMM_B(host_reg, 1); + STORE_IMM_ADDR_L((uintptr_t) &cpu_state.flags_op2, 1); + STORE_IMM_ADDR_L((uintptr_t) &cpu_state.flags_op, FLAGS_DEC8); + STORE_HOST_REG_ADDR_BL((uintptr_t) &cpu_state.flags_res, host_reg); + break; + } + + if ((fetchdat & 0xc0) == 0xc0) + STORE_REG_B_RELEASE(host_reg); + else { + LOAD_EA(); + MEM_STORE_ADDR_EA_B_NO_ABRT(target_seg, host_reg); + } + codegen_flags_changed = 1; + + return op_pc + 1; } static uint32_t codegen_temp; -static uint32_t ropFF_16(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block) +static uint32_t +ropFF_16(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block) { - x86seg *target_seg = NULL; - int host_reg; - - if ((fetchdat & 0x30) != 0x00 && (fetchdat & 0x08)) - return 0; + x86seg *target_seg = NULL; + int host_reg; - if ((fetchdat & 0x30) == 0x00) - CALL_FUNC((uintptr_t)flags_rebuild_c); - - if ((fetchdat & 0xc0) == 0xc0) - host_reg = LOAD_REG_W(fetchdat & 7); - else - { - target_seg = FETCH_EA(op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32); - STORE_IMM_ADDR_L((uintptr_t)&cpu_state.oldpc, op_old_pc); - - if ((fetchdat & 0x30) != 0x00) - { - MEM_LOAD_ADDR_EA_W(target_seg); - host_reg = 0; - } - else - { - SAVE_EA(); - MEM_CHECK_WRITE_W(target_seg); - host_reg = MEM_LOAD_ADDR_EA_W_NO_ABRT(target_seg); - } - } - - switch (fetchdat & 0x38) - { - case 0x00: /*INC*/ - STORE_HOST_REG_ADDR_WL((uintptr_t)&cpu_state.flags_op1, host_reg); - ADD_HOST_REG_IMM_W(host_reg, 1); - STORE_IMM_ADDR_L((uintptr_t)&cpu_state.flags_op2, 1); - STORE_IMM_ADDR_L((uintptr_t)&cpu_state.flags_op, FLAGS_INC16); - STORE_HOST_REG_ADDR_WL((uintptr_t)&cpu_state.flags_res, host_reg); - if ((fetchdat & 0xc0) == 0xc0) - STORE_REG_W_RELEASE(host_reg); - else - { - LOAD_EA(); - MEM_STORE_ADDR_EA_W_NO_ABRT(target_seg, host_reg); - } - codegen_flags_changed = 1; - return op_pc + 1; - case 0x08: /*DEC*/ - STORE_HOST_REG_ADDR_WL((uintptr_t)&cpu_state.flags_op1, host_reg); - SUB_HOST_REG_IMM_W(host_reg, 1); - STORE_IMM_ADDR_L((uintptr_t)&cpu_state.flags_op2, 1); - STORE_IMM_ADDR_L((uintptr_t)&cpu_state.flags_op, FLAGS_DEC16); - STORE_HOST_REG_ADDR_WL((uintptr_t)&cpu_state.flags_res, host_reg); - if ((fetchdat & 0xc0) == 0xc0) - STORE_REG_W_RELEASE(host_reg); - else - { - LOAD_EA(); - MEM_STORE_ADDR_EA_W_NO_ABRT(target_seg, host_reg); - } - codegen_flags_changed = 1; - return op_pc + 1; - - case 0x10: /*CALL*/ - STORE_HOST_REG_ADDR_W((uintptr_t)&codegen_temp, host_reg); - RELEASE_REG(host_reg); - - STORE_IMM_ADDR_L((uintptr_t)&cpu_state.oldpc, op_old_pc); - LOAD_STACK_TO_EA(-2); - host_reg = LOAD_REG_IMM(op_pc + 1); - MEM_STORE_ADDR_EA_W(&cpu_state.seg_ss, host_reg); - SP_MODIFY(-2); - - host_reg = LOAD_VAR_W((uintptr_t)&codegen_temp); - STORE_HOST_REG_ADDR_W((uintptr_t)&cpu_state.pc, host_reg); - return -1; - - case 0x20: /*JMP*/ - STORE_HOST_REG_ADDR((uintptr_t)&cpu_state.pc, host_reg); - return -1; - - case 0x30: /*PUSH*/ - if (!host_reg) - host_reg = LOAD_HOST_REG(host_reg); - STORE_IMM_ADDR_L((uintptr_t)&cpu_state.oldpc, op_old_pc); - LOAD_STACK_TO_EA(-2); - MEM_STORE_ADDR_EA_W(&cpu_state.seg_ss, host_reg); - SP_MODIFY(-2); - return op_pc + 1; - } + if ((fetchdat & 0x30) != 0x00 && (fetchdat & 0x08)) return 0; + + if ((fetchdat & 0x30) == 0x00) + CALL_FUNC((uintptr_t) flags_rebuild_c); + + if ((fetchdat & 0xc0) == 0xc0) + host_reg = LOAD_REG_W(fetchdat & 7); + else { + target_seg = FETCH_EA(op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32); + STORE_IMM_ADDR_L((uintptr_t) &cpu_state.oldpc, op_old_pc); + + if ((fetchdat & 0x30) != 0x00) { + MEM_LOAD_ADDR_EA_W(target_seg); + host_reg = 0; + } else { + SAVE_EA(); + MEM_CHECK_WRITE_W(target_seg); + host_reg = MEM_LOAD_ADDR_EA_W_NO_ABRT(target_seg); + } + } + + switch (fetchdat & 0x38) { + case 0x00: /*INC*/ + STORE_HOST_REG_ADDR_WL((uintptr_t) &cpu_state.flags_op1, host_reg); + ADD_HOST_REG_IMM_W(host_reg, 1); + STORE_IMM_ADDR_L((uintptr_t) &cpu_state.flags_op2, 1); + STORE_IMM_ADDR_L((uintptr_t) &cpu_state.flags_op, FLAGS_INC16); + STORE_HOST_REG_ADDR_WL((uintptr_t) &cpu_state.flags_res, host_reg); + if ((fetchdat & 0xc0) == 0xc0) + STORE_REG_W_RELEASE(host_reg); + else { + LOAD_EA(); + MEM_STORE_ADDR_EA_W_NO_ABRT(target_seg, host_reg); + } + codegen_flags_changed = 1; + return op_pc + 1; + case 0x08: /*DEC*/ + STORE_HOST_REG_ADDR_WL((uintptr_t) &cpu_state.flags_op1, host_reg); + SUB_HOST_REG_IMM_W(host_reg, 1); + STORE_IMM_ADDR_L((uintptr_t) &cpu_state.flags_op2, 1); + STORE_IMM_ADDR_L((uintptr_t) &cpu_state.flags_op, FLAGS_DEC16); + STORE_HOST_REG_ADDR_WL((uintptr_t) &cpu_state.flags_res, host_reg); + if ((fetchdat & 0xc0) == 0xc0) + STORE_REG_W_RELEASE(host_reg); + else { + LOAD_EA(); + MEM_STORE_ADDR_EA_W_NO_ABRT(target_seg, host_reg); + } + codegen_flags_changed = 1; + return op_pc + 1; + + case 0x10: /*CALL*/ + STORE_HOST_REG_ADDR_W((uintptr_t) &codegen_temp, host_reg); + RELEASE_REG(host_reg); + + STORE_IMM_ADDR_L((uintptr_t) &cpu_state.oldpc, op_old_pc); + LOAD_STACK_TO_EA(-2); + host_reg = LOAD_REG_IMM(op_pc + 1); + MEM_STORE_ADDR_EA_W(&cpu_state.seg_ss, host_reg); + SP_MODIFY(-2); + + host_reg = LOAD_VAR_W((uintptr_t) &codegen_temp); + STORE_HOST_REG_ADDR_W((uintptr_t) &cpu_state.pc, host_reg); + return -1; + + case 0x20: /*JMP*/ + STORE_HOST_REG_ADDR((uintptr_t) &cpu_state.pc, host_reg); + return -1; + + case 0x30: /*PUSH*/ + if (!host_reg) + host_reg = LOAD_HOST_REG(host_reg); + STORE_IMM_ADDR_L((uintptr_t) &cpu_state.oldpc, op_old_pc); + LOAD_STACK_TO_EA(-2); + MEM_STORE_ADDR_EA_W(&cpu_state.seg_ss, host_reg); + SP_MODIFY(-2); + return op_pc + 1; + } + return 0; } -static uint32_t ropFF_32(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block) +static uint32_t +ropFF_32(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block) { - x86seg *target_seg = NULL; - int host_reg; - - if ((fetchdat & 0x30) != 0x00 && (fetchdat & 0x08)) - return 0; + x86seg *target_seg = NULL; + int host_reg; - if ((fetchdat & 0x30) == 0x00) - CALL_FUNC((uintptr_t)flags_rebuild_c); - - if ((fetchdat & 0xc0) == 0xc0) - host_reg = LOAD_REG_L(fetchdat & 7); - else - { - target_seg = FETCH_EA(op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32); - STORE_IMM_ADDR_L((uintptr_t)&cpu_state.oldpc, op_old_pc); - - if ((fetchdat & 0x30) != 0x00) - { - MEM_LOAD_ADDR_EA_L(target_seg); - host_reg = 0; - } - else - { - SAVE_EA(); - MEM_CHECK_WRITE_L(target_seg); - host_reg = MEM_LOAD_ADDR_EA_L_NO_ABRT(target_seg); - } - } - - switch (fetchdat & 0x38) - { - case 0x00: /*INC*/ - STORE_HOST_REG_ADDR((uintptr_t)&cpu_state.flags_op1, host_reg); - ADD_HOST_REG_IMM(host_reg, 1); - STORE_IMM_ADDR_L((uintptr_t)&cpu_state.flags_op2, 1); - STORE_IMM_ADDR_L((uintptr_t)&cpu_state.flags_op, FLAGS_INC32); - STORE_HOST_REG_ADDR((uintptr_t)&cpu_state.flags_res, host_reg); - if ((fetchdat & 0xc0) == 0xc0) - STORE_REG_L_RELEASE(host_reg); - else - { - LOAD_EA(); - MEM_STORE_ADDR_EA_L_NO_ABRT(target_seg, host_reg); - } - codegen_flags_changed = 1; - return op_pc + 1; - case 0x08: /*DEC*/ - STORE_HOST_REG_ADDR((uintptr_t)&cpu_state.flags_op1, host_reg); - SUB_HOST_REG_IMM(host_reg, 1); - STORE_IMM_ADDR_L((uintptr_t)&cpu_state.flags_op2, 1); - STORE_IMM_ADDR_L((uintptr_t)&cpu_state.flags_op, FLAGS_DEC32); - STORE_HOST_REG_ADDR((uintptr_t)&cpu_state.flags_res, host_reg); - if ((fetchdat & 0xc0) == 0xc0) - STORE_REG_L_RELEASE(host_reg); - else - { - LOAD_EA(); - MEM_STORE_ADDR_EA_L_NO_ABRT(target_seg, host_reg); - } - codegen_flags_changed = 1; - return op_pc + 1; - - case 0x10: /*CALL*/ - STORE_HOST_REG_ADDR((uintptr_t)&codegen_temp, host_reg); - RELEASE_REG(host_reg); - - STORE_IMM_ADDR_L((uintptr_t)&cpu_state.oldpc, op_old_pc); - LOAD_STACK_TO_EA(-4); - host_reg = LOAD_REG_IMM(op_pc + 1); - MEM_STORE_ADDR_EA_L(&cpu_state.seg_ss, host_reg); - SP_MODIFY(-4); - - host_reg = LOAD_VAR_L((uintptr_t)&codegen_temp); - STORE_HOST_REG_ADDR((uintptr_t)&cpu_state.pc, host_reg); - return -1; - - case 0x20: /*JMP*/ - STORE_HOST_REG_ADDR((uintptr_t)&cpu_state.pc, host_reg); - return -1; - - case 0x30: /*PUSH*/ - if (!host_reg) - host_reg = LOAD_HOST_REG(host_reg); - STORE_IMM_ADDR_L((uintptr_t)&cpu_state.oldpc, op_old_pc); - LOAD_STACK_TO_EA(-4); - MEM_STORE_ADDR_EA_L(&cpu_state.seg_ss, host_reg); - SP_MODIFY(-4); - return op_pc + 1; - } + if ((fetchdat & 0x30) != 0x00 && (fetchdat & 0x08)) return 0; + + if ((fetchdat & 0x30) == 0x00) + CALL_FUNC((uintptr_t) flags_rebuild_c); + + if ((fetchdat & 0xc0) == 0xc0) + host_reg = LOAD_REG_L(fetchdat & 7); + else { + target_seg = FETCH_EA(op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32); + STORE_IMM_ADDR_L((uintptr_t) &cpu_state.oldpc, op_old_pc); + + if ((fetchdat & 0x30) != 0x00) { + MEM_LOAD_ADDR_EA_L(target_seg); + host_reg = 0; + } else { + SAVE_EA(); + MEM_CHECK_WRITE_L(target_seg); + host_reg = MEM_LOAD_ADDR_EA_L_NO_ABRT(target_seg); + } + } + + switch (fetchdat & 0x38) { + case 0x00: /*INC*/ + STORE_HOST_REG_ADDR((uintptr_t) &cpu_state.flags_op1, host_reg); + ADD_HOST_REG_IMM(host_reg, 1); + STORE_IMM_ADDR_L((uintptr_t) &cpu_state.flags_op2, 1); + STORE_IMM_ADDR_L((uintptr_t) &cpu_state.flags_op, FLAGS_INC32); + STORE_HOST_REG_ADDR((uintptr_t) &cpu_state.flags_res, host_reg); + if ((fetchdat & 0xc0) == 0xc0) + STORE_REG_L_RELEASE(host_reg); + else { + LOAD_EA(); + MEM_STORE_ADDR_EA_L_NO_ABRT(target_seg, host_reg); + } + codegen_flags_changed = 1; + return op_pc + 1; + case 0x08: /*DEC*/ + STORE_HOST_REG_ADDR((uintptr_t) &cpu_state.flags_op1, host_reg); + SUB_HOST_REG_IMM(host_reg, 1); + STORE_IMM_ADDR_L((uintptr_t) &cpu_state.flags_op2, 1); + STORE_IMM_ADDR_L((uintptr_t) &cpu_state.flags_op, FLAGS_DEC32); + STORE_HOST_REG_ADDR((uintptr_t) &cpu_state.flags_res, host_reg); + if ((fetchdat & 0xc0) == 0xc0) + STORE_REG_L_RELEASE(host_reg); + else { + LOAD_EA(); + MEM_STORE_ADDR_EA_L_NO_ABRT(target_seg, host_reg); + } + codegen_flags_changed = 1; + return op_pc + 1; + + case 0x10: /*CALL*/ + STORE_HOST_REG_ADDR((uintptr_t) &codegen_temp, host_reg); + RELEASE_REG(host_reg); + + STORE_IMM_ADDR_L((uintptr_t) &cpu_state.oldpc, op_old_pc); + LOAD_STACK_TO_EA(-4); + host_reg = LOAD_REG_IMM(op_pc + 1); + MEM_STORE_ADDR_EA_L(&cpu_state.seg_ss, host_reg); + SP_MODIFY(-4); + + host_reg = LOAD_VAR_L((uintptr_t) &codegen_temp); + STORE_HOST_REG_ADDR((uintptr_t) &cpu_state.pc, host_reg); + return -1; + + case 0x20: /*JMP*/ + STORE_HOST_REG_ADDR((uintptr_t) &cpu_state.pc, host_reg); + return -1; + + case 0x30: /*PUSH*/ + if (!host_reg) + host_reg = LOAD_HOST_REG(host_reg); + STORE_IMM_ADDR_L((uintptr_t) &cpu_state.oldpc, op_old_pc); + LOAD_STACK_TO_EA(-4); + MEM_STORE_ADDR_EA_L(&cpu_state.seg_ss, host_reg); + SP_MODIFY(-4); + return op_pc + 1; + } + return 0; } diff --git a/src/codegen/codegen_ops_mmx.h b/src/codegen/codegen_ops_mmx.h index b669567fd..4c5a92c8f 100644 --- a/src/codegen/codegen_ops_mmx.h +++ b/src/codegen/codegen_ops_mmx.h @@ -1,277 +1,272 @@ -static uint32_t ropMOVQ_q_mm(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block) +static uint32_t +ropMOVQ_q_mm(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block) { - int host_reg1, host_reg2 = 0; + int host_reg1; + int host_reg2 = 0; - MMX_ENTER(); - - LOAD_MMX_Q((fetchdat >> 3) & 7, &host_reg1, &host_reg2); - - if ((fetchdat & 0xc0) == 0xc0) - { - STORE_MMX_Q(fetchdat & 7, host_reg1, host_reg2); - } - else - { - x86seg *target_seg = FETCH_EA(op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32); + MMX_ENTER(); - STORE_IMM_ADDR_L((uintptr_t)&cpu_state.oldpc, op_old_pc); - - CHECK_SEG_WRITE(target_seg); - CHECK_SEG_LIMITS(target_seg, 7); - - MEM_STORE_ADDR_EA_Q(target_seg, host_reg1, host_reg2); - } + LOAD_MMX_Q((fetchdat >> 3) & 7, &host_reg1, &host_reg2); - return op_pc + 1; + if ((fetchdat & 0xc0) == 0xc0) { + STORE_MMX_Q(fetchdat & 7, host_reg1, host_reg2); + } else { + x86seg *target_seg = FETCH_EA(op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32); + + STORE_IMM_ADDR_L((uintptr_t) &cpu_state.oldpc, op_old_pc); + + CHECK_SEG_WRITE(target_seg); + CHECK_SEG_LIMITS(target_seg, 7); + + MEM_STORE_ADDR_EA_Q(target_seg, host_reg1, host_reg2); + } + + return op_pc + 1; } -static uint32_t ropMOVQ_mm_q(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block) +static uint32_t +ropMOVQ_mm_q(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block) { - MMX_ENTER(); - - if ((fetchdat & 0xc0) == 0xc0) - { - int host_reg1, host_reg2; - - LOAD_MMX_Q(fetchdat & 7, &host_reg1, &host_reg2); - STORE_MMX_Q((fetchdat >> 3) & 7, host_reg1, host_reg2); - } - else - { - x86seg *target_seg = FETCH_EA(op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32); + MMX_ENTER(); - STORE_IMM_ADDR_L((uintptr_t)&cpu_state.oldpc, op_old_pc); + if ((fetchdat & 0xc0) == 0xc0) { + int host_reg1; + int host_reg2; - CHECK_SEG_READ(target_seg); + LOAD_MMX_Q(fetchdat & 7, &host_reg1, &host_reg2); + STORE_MMX_Q((fetchdat >> 3) & 7, host_reg1, host_reg2); + } else { + x86seg *target_seg = FETCH_EA(op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32); - MEM_LOAD_ADDR_EA_Q(target_seg); - STORE_MMX_Q((fetchdat >> 3) & 7, LOAD_Q_REG_1, LOAD_Q_REG_2); - } + STORE_IMM_ADDR_L((uintptr_t) &cpu_state.oldpc, op_old_pc); - return op_pc + 1; + CHECK_SEG_READ(target_seg); + + MEM_LOAD_ADDR_EA_Q(target_seg); + STORE_MMX_Q((fetchdat >> 3) & 7, LOAD_Q_REG_1, LOAD_Q_REG_2); + } + + return op_pc + 1; } -static uint32_t ropMOVD_l_mm(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block) +static uint32_t +ropMOVD_l_mm(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block) { - int host_reg; + int host_reg; - MMX_ENTER(); - - host_reg = LOAD_MMX_D((fetchdat >> 3) & 7); - - if ((fetchdat & 0xc0) == 0xc0) - { - STORE_REG_TARGET_L_RELEASE(host_reg, fetchdat & 7); - } - else - { - x86seg *target_seg = FETCH_EA(op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32); + MMX_ENTER(); - STORE_IMM_ADDR_L((uintptr_t)&cpu_state.oldpc, op_old_pc); - - CHECK_SEG_WRITE(target_seg); - CHECK_SEG_LIMITS(target_seg, 3); - - MEM_STORE_ADDR_EA_L(target_seg, host_reg); - } + host_reg = LOAD_MMX_D((fetchdat >> 3) & 7); - return op_pc + 1; + if ((fetchdat & 0xc0) == 0xc0) { + STORE_REG_TARGET_L_RELEASE(host_reg, fetchdat & 7); + } else { + x86seg *target_seg = FETCH_EA(op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32); + + STORE_IMM_ADDR_L((uintptr_t) &cpu_state.oldpc, op_old_pc); + + CHECK_SEG_WRITE(target_seg); + CHECK_SEG_LIMITS(target_seg, 3); + + MEM_STORE_ADDR_EA_L(target_seg, host_reg); + } + + return op_pc + 1; } -static uint32_t ropMOVD_mm_l(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block) +static uint32_t +ropMOVD_mm_l(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block) { - MMX_ENTER(); - - if ((fetchdat & 0xc0) == 0xc0) - { - int host_reg = LOAD_REG_L(fetchdat & 7); - STORE_MMX_LQ((fetchdat >> 3) & 7, host_reg); - } - else - { - x86seg *target_seg = FETCH_EA(op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32); + MMX_ENTER(); - STORE_IMM_ADDR_L((uintptr_t)&cpu_state.oldpc, op_old_pc); + if ((fetchdat & 0xc0) == 0xc0) { + int host_reg = LOAD_REG_L(fetchdat & 7); + STORE_MMX_LQ((fetchdat >> 3) & 7, host_reg); + } else { + x86seg *target_seg = FETCH_EA(op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32); - CHECK_SEG_READ(target_seg); + STORE_IMM_ADDR_L((uintptr_t) &cpu_state.oldpc, op_old_pc); - MEM_LOAD_ADDR_EA_L(target_seg); - STORE_MMX_LQ((fetchdat >> 3) & 7, 0); - } + CHECK_SEG_READ(target_seg); - return op_pc + 1; + MEM_LOAD_ADDR_EA_L(target_seg); + STORE_MMX_LQ((fetchdat >> 3) & 7, 0); + } + + return op_pc + 1; } -#define MMX_OP(name, func) \ -static uint32_t name(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block) \ -{ \ - int src_reg1, src_reg2; \ - int xmm_src, xmm_dst; \ - \ - MMX_ENTER(); \ - \ - if ((fetchdat & 0xc0) == 0xc0) \ - { \ - xmm_src = LOAD_MMX_Q_MMX(fetchdat & 7); \ - } \ - else \ - { \ - x86seg *target_seg = FETCH_EA(op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32); \ - \ - STORE_IMM_ADDR_L((uintptr_t)&cpu_state.oldpc, op_old_pc); \ - \ - CHECK_SEG_READ(target_seg); \ - \ - MEM_LOAD_ADDR_EA_Q(target_seg); \ - src_reg1 = LOAD_Q_REG_1; \ - src_reg2 = LOAD_Q_REG_2; \ - xmm_src = LOAD_INT_TO_MMX(src_reg1, src_reg2); \ - } \ - xmm_dst = LOAD_MMX_Q_MMX((fetchdat >> 3) & 7); \ - func(xmm_dst, xmm_src); \ - STORE_MMX_Q_MMX((fetchdat >> 3) & 7, xmm_dst); \ - \ - return op_pc + 1; \ -} +#define MMX_OP(name, func) \ + static uint32_t \ + name(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block) \ + { \ + int src_reg1; \ + int src_reg2; \ + int xmm_src; \ + int xmm_dst; \ + \ + MMX_ENTER(); \ + \ + if ((fetchdat & 0xc0) == 0xc0) { \ + xmm_src = LOAD_MMX_Q_MMX(fetchdat & 7); \ + } else { \ + x86seg *target_seg = FETCH_EA(op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32); \ + \ + STORE_IMM_ADDR_L((uintptr_t) &cpu_state.oldpc, op_old_pc); \ + \ + CHECK_SEG_READ(target_seg); \ + \ + MEM_LOAD_ADDR_EA_Q(target_seg); \ + src_reg1 = LOAD_Q_REG_1; \ + src_reg2 = LOAD_Q_REG_2; \ + xmm_src = LOAD_INT_TO_MMX(src_reg1, src_reg2); \ + } \ + xmm_dst = LOAD_MMX_Q_MMX((fetchdat >> 3) & 7); \ + func(xmm_dst, xmm_src); \ + STORE_MMX_Q_MMX((fetchdat >> 3) & 7, xmm_dst); \ + \ + return op_pc + 1; \ + } -MMX_OP(ropPAND, MMX_AND) +MMX_OP(ropPAND, MMX_AND) MMX_OP(ropPANDN, MMX_ANDN) -MMX_OP(ropPOR, MMX_OR) -MMX_OP(ropPXOR, MMX_XOR) +MMX_OP(ropPOR, MMX_OR) +MMX_OP(ropPXOR, MMX_XOR) -MMX_OP(ropPADDB, MMX_ADDB) -MMX_OP(ropPADDW, MMX_ADDW) -MMX_OP(ropPADDD, MMX_ADDD) -MMX_OP(ropPADDSB, MMX_ADDSB) -MMX_OP(ropPADDSW, MMX_ADDSW) -MMX_OP(ropPADDUSB, MMX_ADDUSB) -MMX_OP(ropPADDUSW, MMX_ADDUSW) +MMX_OP(ropPADDB, MMX_ADDB) +MMX_OP(ropPADDW, MMX_ADDW) +MMX_OP(ropPADDD, MMX_ADDD) +MMX_OP(ropPADDSB, MMX_ADDSB) +MMX_OP(ropPADDSW, MMX_ADDSW) +MMX_OP(ropPADDUSB, MMX_ADDUSB) +MMX_OP(ropPADDUSW, MMX_ADDUSW) -MMX_OP(ropPSUBB, MMX_SUBB) -MMX_OP(ropPSUBW, MMX_SUBW) -MMX_OP(ropPSUBD, MMX_SUBD) -MMX_OP(ropPSUBSB, MMX_SUBSB) -MMX_OP(ropPSUBSW, MMX_SUBSW) -MMX_OP(ropPSUBUSB, MMX_SUBUSB) -MMX_OP(ropPSUBUSW, MMX_SUBUSW) +MMX_OP(ropPSUBB, MMX_SUBB) +MMX_OP(ropPSUBW, MMX_SUBW) +MMX_OP(ropPSUBD, MMX_SUBD) +MMX_OP(ropPSUBSB, MMX_SUBSB) +MMX_OP(ropPSUBSW, MMX_SUBSW) +MMX_OP(ropPSUBUSB, MMX_SUBUSB) +MMX_OP(ropPSUBUSW, MMX_SUBUSW) MMX_OP(ropPUNPCKLBW, MMX_PUNPCKLBW); MMX_OP(ropPUNPCKLWD, MMX_PUNPCKLWD); MMX_OP(ropPUNPCKLDQ, MMX_PUNPCKLDQ); -MMX_OP(ropPACKSSWB, MMX_PACKSSWB); -MMX_OP(ropPCMPGTB, MMX_PCMPGTB); -MMX_OP(ropPCMPGTW, MMX_PCMPGTW); -MMX_OP(ropPCMPGTD, MMX_PCMPGTD); -MMX_OP(ropPACKUSWB, MMX_PACKUSWB); +MMX_OP(ropPACKSSWB, MMX_PACKSSWB); +MMX_OP(ropPCMPGTB, MMX_PCMPGTB); +MMX_OP(ropPCMPGTW, MMX_PCMPGTW); +MMX_OP(ropPCMPGTD, MMX_PCMPGTD); +MMX_OP(ropPACKUSWB, MMX_PACKUSWB); MMX_OP(ropPUNPCKHBW, MMX_PUNPCKHBW); MMX_OP(ropPUNPCKHWD, MMX_PUNPCKHWD); MMX_OP(ropPUNPCKHDQ, MMX_PUNPCKHDQ); -MMX_OP(ropPACKSSDW, MMX_PACKSSDW); +MMX_OP(ropPACKSSDW, MMX_PACKSSDW); -MMX_OP(ropPCMPEQB, MMX_PCMPEQB); -MMX_OP(ropPCMPEQW, MMX_PCMPEQW); -MMX_OP(ropPCMPEQD, MMX_PCMPEQD); +MMX_OP(ropPCMPEQB, MMX_PCMPEQB); +MMX_OP(ropPCMPEQW, MMX_PCMPEQW); +MMX_OP(ropPCMPEQD, MMX_PCMPEQD); -MMX_OP(ropPSRLW, MMX_PSRLW) -MMX_OP(ropPSRLD, MMX_PSRLD) -MMX_OP(ropPSRLQ, MMX_PSRLQ) -MMX_OP(ropPSRAW, MMX_PSRAW) -MMX_OP(ropPSRAD, MMX_PSRAD) -MMX_OP(ropPSLLW, MMX_PSLLW) -MMX_OP(ropPSLLD, MMX_PSLLD) -MMX_OP(ropPSLLQ, MMX_PSLLQ) +MMX_OP(ropPSRLW, MMX_PSRLW) +MMX_OP(ropPSRLD, MMX_PSRLD) +MMX_OP(ropPSRLQ, MMX_PSRLQ) +MMX_OP(ropPSRAW, MMX_PSRAW) +MMX_OP(ropPSRAD, MMX_PSRAD) +MMX_OP(ropPSLLW, MMX_PSLLW) +MMX_OP(ropPSLLD, MMX_PSLLD) +MMX_OP(ropPSLLQ, MMX_PSLLQ) -MMX_OP(ropPMULLW, MMX_PMULLW); -MMX_OP(ropPMULHW, MMX_PMULHW); -MMX_OP(ropPMADDWD, MMX_PMADDWD); +MMX_OP(ropPMULLW, MMX_PMULLW); +MMX_OP(ropPMULHW, MMX_PMULHW); +MMX_OP(ropPMADDWD, MMX_PMADDWD); -static uint32_t ropPSxxW_imm(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block) +static uint32_t +ropPSxxW_imm(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block) { - int xmm_dst; + int xmm_dst; - if ((fetchdat & 0xc0) != 0xc0) - return 0; - if ((fetchdat & 0x08) || !(fetchdat & 0x30)) - return 0; - - MMX_ENTER(); - - xmm_dst = LOAD_MMX_Q_MMX(fetchdat & 7); - switch (fetchdat & 0x38) - { - case 0x10: /*PSRLW*/ - MMX_PSRLW_imm(xmm_dst, (fetchdat >> 8) & 0xff); - break; - case 0x20: /*PSRAW*/ - MMX_PSRAW_imm(xmm_dst, (fetchdat >> 8) & 0xff); - break; - case 0x30: /*PSLLW*/ - MMX_PSLLW_imm(xmm_dst, (fetchdat >> 8) & 0xff); - break; - } - STORE_MMX_Q_MMX(fetchdat & 7, xmm_dst); - - return op_pc + 2; -} -static uint32_t ropPSxxD_imm(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block) -{ - int xmm_dst; - - if ((fetchdat & 0xc0) != 0xc0) - return 0; - if ((fetchdat & 0x08) || !(fetchdat & 0x30)) - return 0; - - MMX_ENTER(); - - xmm_dst = LOAD_MMX_Q_MMX(fetchdat & 7); - switch (fetchdat & 0x38) - { - case 0x10: /*PSRLD*/ - MMX_PSRLD_imm(xmm_dst, (fetchdat >> 8) & 0xff); - break; - case 0x20: /*PSRAD*/ - MMX_PSRAD_imm(xmm_dst, (fetchdat >> 8) & 0xff); - break; - case 0x30: /*PSLLD*/ - MMX_PSLLD_imm(xmm_dst, (fetchdat >> 8) & 0xff); - break; - } - STORE_MMX_Q_MMX(fetchdat & 7, xmm_dst); - - return op_pc + 2; -} -static uint32_t ropPSxxQ_imm(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block) -{ - int xmm_dst; - - if ((fetchdat & 0xc0) != 0xc0) - return 0; - if ((fetchdat & 0x08) || !(fetchdat & 0x30)) - return 0; - - MMX_ENTER(); - - xmm_dst = LOAD_MMX_Q_MMX(fetchdat & 7); - switch (fetchdat & 0x38) - { - case 0x10: /*PSRLQ*/ - MMX_PSRLQ_imm(xmm_dst, (fetchdat >> 8) & 0xff); - break; - case 0x20: /*PSRAQ*/ - MMX_PSRAQ_imm(xmm_dst, (fetchdat >> 8) & 0xff); - break; - case 0x30: /*PSLLQ*/ - MMX_PSLLQ_imm(xmm_dst, (fetchdat >> 8) & 0xff); - break; - } - STORE_MMX_Q_MMX(fetchdat & 7, xmm_dst); - - return op_pc + 2; -} - -static uint32_t ropEMMS(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block) -{ - codegen_mmx_entered = 0; - + if ((fetchdat & 0xc0) != 0xc0) return 0; + if ((fetchdat & 0x08) || !(fetchdat & 0x30)) + return 0; + + MMX_ENTER(); + + xmm_dst = LOAD_MMX_Q_MMX(fetchdat & 7); + switch (fetchdat & 0x38) { + case 0x10: /*PSRLW*/ + MMX_PSRLW_imm(xmm_dst, (fetchdat >> 8) & 0xff); + break; + case 0x20: /*PSRAW*/ + MMX_PSRAW_imm(xmm_dst, (fetchdat >> 8) & 0xff); + break; + case 0x30: /*PSLLW*/ + MMX_PSLLW_imm(xmm_dst, (fetchdat >> 8) & 0xff); + break; + } + STORE_MMX_Q_MMX(fetchdat & 7, xmm_dst); + + return op_pc + 2; +} +static uint32_t +ropPSxxD_imm(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block) +{ + int xmm_dst; + + if ((fetchdat & 0xc0) != 0xc0) + return 0; + if ((fetchdat & 0x08) || !(fetchdat & 0x30)) + return 0; + + MMX_ENTER(); + + xmm_dst = LOAD_MMX_Q_MMX(fetchdat & 7); + switch (fetchdat & 0x38) { + case 0x10: /*PSRLD*/ + MMX_PSRLD_imm(xmm_dst, (fetchdat >> 8) & 0xff); + break; + case 0x20: /*PSRAD*/ + MMX_PSRAD_imm(xmm_dst, (fetchdat >> 8) & 0xff); + break; + case 0x30: /*PSLLD*/ + MMX_PSLLD_imm(xmm_dst, (fetchdat >> 8) & 0xff); + break; + } + STORE_MMX_Q_MMX(fetchdat & 7, xmm_dst); + + return op_pc + 2; +} +static uint32_t +ropPSxxQ_imm(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block) +{ + int xmm_dst; + + if ((fetchdat & 0xc0) != 0xc0) + return 0; + if ((fetchdat & 0x08) || !(fetchdat & 0x30)) + return 0; + + MMX_ENTER(); + + xmm_dst = LOAD_MMX_Q_MMX(fetchdat & 7); + switch (fetchdat & 0x38) { + case 0x10: /*PSRLQ*/ + MMX_PSRLQ_imm(xmm_dst, (fetchdat >> 8) & 0xff); + break; + case 0x20: /*PSRAQ*/ + MMX_PSRAQ_imm(xmm_dst, (fetchdat >> 8) & 0xff); + break; + case 0x30: /*PSLLQ*/ + MMX_PSLLQ_imm(xmm_dst, (fetchdat >> 8) & 0xff); + break; + } + STORE_MMX_Q_MMX(fetchdat & 7, xmm_dst); + + return op_pc + 2; +} + +static uint32_t +ropEMMS(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block) +{ + codegen_mmx_entered = 0; + + return 0; } diff --git a/src/codegen/codegen_ops_mov.h b/src/codegen/codegen_ops_mov.h index fc4ec1637..04c4bf2bc 100644 --- a/src/codegen/codegen_ops_mov.h +++ b/src/codegen/codegen_ops_mov.h @@ -1,656 +1,625 @@ -static uint32_t ropMOV_rb_imm(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block) +static uint32_t +ropMOV_rb_imm(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block) { - STORE_IMM_REG_B(opcode & 7, fetchdat & 0xff); - - return op_pc + 1; -} -static uint32_t ropMOV_rw_imm(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block) -{ - STORE_IMM_REG_W(opcode & 7, fetchdat & 0xffff); + STORE_IMM_REG_B(opcode & 7, fetchdat & 0xff); - return op_pc + 2; + return op_pc + 1; } -static uint32_t ropMOV_rl_imm(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block) +static uint32_t +ropMOV_rw_imm(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block) { - fetchdat = fastreadl(cs + op_pc); + STORE_IMM_REG_W(opcode & 7, fetchdat & 0xffff); - STORE_IMM_REG_L(opcode & 7, fetchdat); - - return op_pc + 4; + return op_pc + 2; +} +static uint32_t +ropMOV_rl_imm(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block) +{ + fetchdat = fastreadl(cs + op_pc); + + STORE_IMM_REG_L(opcode & 7, fetchdat); + + return op_pc + 4; } - -static uint32_t ropMOV_b_r(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block) +static uint32_t +ropMOV_b_r(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block) { - int host_reg = LOAD_REG_B((fetchdat >> 3) & 7); - - if ((fetchdat & 0xc0) == 0xc0) - { - STORE_REG_TARGET_B_RELEASE(host_reg, fetchdat & 7); - } - else - { - x86seg *target_seg = FETCH_EA(op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32); + int host_reg = LOAD_REG_B((fetchdat >> 3) & 7); - STORE_IMM_ADDR_L((uintptr_t)&cpu_state.oldpc, op_old_pc); - - CHECK_SEG_WRITE(target_seg); - CHECK_SEG_LIMITS(target_seg, 0); + if ((fetchdat & 0xc0) == 0xc0) { + STORE_REG_TARGET_B_RELEASE(host_reg, fetchdat & 7); + } else { + x86seg *target_seg = FETCH_EA(op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32); - MEM_STORE_ADDR_EA_B(target_seg, host_reg); - RELEASE_REG(host_reg); - } - - return op_pc + 1; -} -static uint32_t ropMOV_w_r(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block) -{ - int host_reg = LOAD_REG_W((fetchdat >> 3) & 7); - - if ((fetchdat & 0xc0) == 0xc0) - { - STORE_REG_TARGET_W_RELEASE(host_reg, fetchdat & 7); - } - else - { - x86seg *target_seg = FETCH_EA(op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32); + STORE_IMM_ADDR_L((uintptr_t) &cpu_state.oldpc, op_old_pc); - STORE_IMM_ADDR_L((uintptr_t)&cpu_state.oldpc, op_old_pc); - - CHECK_SEG_WRITE(target_seg); - CHECK_SEG_LIMITS(target_seg, 1); + CHECK_SEG_WRITE(target_seg); + CHECK_SEG_LIMITS(target_seg, 0); - MEM_STORE_ADDR_EA_W(target_seg, host_reg); - RELEASE_REG(host_reg); - } - - return op_pc + 1; -} - -static uint32_t ropMOV_l_r(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block) -{ - int host_reg; - - host_reg = LOAD_REG_L((fetchdat >> 3) & 7); - - if ((fetchdat & 0xc0) == 0xc0) - { - STORE_REG_TARGET_L_RELEASE(host_reg, fetchdat & 7); - } - else - { - x86seg *target_seg = FETCH_EA(op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32); - - STORE_IMM_ADDR_L((uintptr_t)&cpu_state.oldpc, op_old_pc); - - CHECK_SEG_WRITE(target_seg); - CHECK_SEG_LIMITS(target_seg, 3); - - MEM_STORE_ADDR_EA_L(target_seg, host_reg); - RELEASE_REG(host_reg); - - } - - return op_pc + 1; -} - -static uint32_t ropMOV_r_b(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block) -{ - if ((fetchdat & 0xc0) == 0xc0) - { - int host_reg = LOAD_REG_B(fetchdat & 7); - STORE_REG_TARGET_B_RELEASE(host_reg, (fetchdat >> 3) & 7); - } - else - { - x86seg *target_seg = FETCH_EA(op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32); - - STORE_IMM_ADDR_L((uintptr_t)&cpu_state.oldpc, op_old_pc); - - CHECK_SEG_READ(target_seg); - - MEM_LOAD_ADDR_EA_B(target_seg); - STORE_REG_TARGET_B_RELEASE(0, (fetchdat >> 3) & 7); - } - - return op_pc + 1; -} -static uint32_t ropMOV_r_w(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block) -{ - if ((fetchdat & 0xc0) == 0xc0) - { - int host_reg = LOAD_REG_W(fetchdat & 7); - STORE_REG_TARGET_W_RELEASE(host_reg, (fetchdat >> 3) & 7); - } - else - { - x86seg *target_seg = FETCH_EA(op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32); - - STORE_IMM_ADDR_L((uintptr_t)&cpu_state.oldpc, op_old_pc); - - CHECK_SEG_READ(target_seg); - - MEM_LOAD_ADDR_EA_W(target_seg); - STORE_REG_TARGET_W_RELEASE(0, (fetchdat >> 3) & 7); - } - - return op_pc + 1; -} -static uint32_t ropMOV_r_l(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block) -{ - if ((fetchdat & 0xc0) == 0xc0) - { - int host_reg = LOAD_REG_L(fetchdat & 7); - STORE_REG_TARGET_L_RELEASE(host_reg, (fetchdat >> 3) & 7); - } - else - { - x86seg *target_seg = FETCH_EA(op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32); - - STORE_IMM_ADDR_L((uintptr_t)&cpu_state.oldpc, op_old_pc); - - CHECK_SEG_READ(target_seg); - - MEM_LOAD_ADDR_EA_L(target_seg); - STORE_REG_TARGET_L_RELEASE(0, (fetchdat >> 3) & 7); - } - - return op_pc + 1; -} - -static uint32_t ropMOV_b_imm(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block) -{ - if ((fetchdat & 0xc0) == 0xc0) - { - STORE_IMM_REG_B(fetchdat & 7, (fetchdat >> 8) & 0xff); - } - else - { - x86seg *target_seg = FETCH_EA(op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32); - uint32_t imm = fastreadb(cs + op_pc + 1); - int host_reg = LOAD_REG_IMM(imm); - - STORE_IMM_ADDR_L((uintptr_t)&cpu_state.oldpc, op_old_pc); - CHECK_SEG_WRITE(target_seg); - - MEM_STORE_ADDR_EA_B(target_seg, host_reg); - RELEASE_REG(host_reg); - } - - return op_pc + 2; -} -static uint32_t ropMOV_w_imm(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block) -{ - if ((fetchdat & 0xc0) == 0xc0) - { - STORE_IMM_REG_W(fetchdat & 7, (fetchdat >> 8) & 0xffff); - } - else - { - x86seg *target_seg = FETCH_EA(op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32); - uint32_t imm = fastreadw(cs + op_pc + 1); - int host_reg = LOAD_REG_IMM(imm); - - STORE_IMM_ADDR_L((uintptr_t)&cpu_state.oldpc, op_old_pc); - CHECK_SEG_WRITE(target_seg); - - MEM_STORE_ADDR_EA_W(target_seg, host_reg); - RELEASE_REG(host_reg); - } - - return op_pc + 3; -} -static uint32_t ropMOV_l_imm(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block) -{ - if ((fetchdat & 0xc0) == 0xc0) - { - uint32_t imm = fastreadl(cs + op_pc + 1); - - STORE_IMM_REG_L(fetchdat & 7, imm); - } - else - { - x86seg *target_seg = FETCH_EA(op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32); - uint32_t imm = fastreadl(cs + op_pc + 1); - int host_reg = LOAD_REG_IMM(imm); - - STORE_IMM_ADDR_L((uintptr_t)&cpu_state.oldpc, op_old_pc); - CHECK_SEG_WRITE(target_seg); - - MEM_STORE_ADDR_EA_L(target_seg, host_reg); - RELEASE_REG(host_reg); - } - - return op_pc + 5; -} - - -static uint32_t ropMOV_AL_a(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block) -{ - uint32_t addr; - - if (op_32 & 0x200) - addr = fastreadl(cs + op_pc); - else - addr = fastreadw(cs + op_pc); - - CHECK_SEG_READ(op_ea_seg); - STORE_IMM_ADDR_L((uintptr_t)&cpu_state.oldpc, op_old_pc); - - MEM_LOAD_ADDR_IMM_B(op_ea_seg, addr); - STORE_REG_TARGET_B_RELEASE(0, REG_AL); - - return op_pc + ((op_32 & 0x200) ? 4 : 2); -} -static uint32_t ropMOV_AX_a(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block) -{ - uint32_t addr; - - if (op_32 & 0x200) - addr = fastreadl(cs + op_pc); - else - addr = fastreadw(cs + op_pc); - - CHECK_SEG_READ(op_ea_seg); - STORE_IMM_ADDR_L((uintptr_t)&cpu_state.oldpc, op_old_pc); - - MEM_LOAD_ADDR_IMM_W(op_ea_seg, addr); - STORE_REG_TARGET_W_RELEASE(0, REG_AX); - - return op_pc + ((op_32 & 0x200) ? 4 : 2); -} -static uint32_t ropMOV_EAX_a(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block) -{ - uint32_t addr; - - if (op_32 & 0x200) - addr = fastreadl(cs + op_pc); - else - addr = fastreadw(cs + op_pc); - - CHECK_SEG_READ(op_ea_seg); - STORE_IMM_ADDR_L((uintptr_t)&cpu_state.oldpc, op_old_pc); - - MEM_LOAD_ADDR_IMM_L(op_ea_seg, addr); - STORE_REG_TARGET_L_RELEASE(0, REG_EAX); - - return op_pc + ((op_32 & 0x200) ? 4 : 2); -} - -static uint32_t ropMOV_a_AL(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block) -{ - uint32_t addr; - int host_reg; - - if (op_32 & 0x200) - addr = fastreadl(cs + op_pc); - else - addr = fastreadw(cs + op_pc); - - CHECK_SEG_WRITE(op_ea_seg); - STORE_IMM_ADDR_L((uintptr_t)&cpu_state.oldpc, op_old_pc); - - host_reg = LOAD_REG_B(REG_AL); - - MEM_STORE_ADDR_IMM_B(op_ea_seg, addr, host_reg); + MEM_STORE_ADDR_EA_B(target_seg, host_reg); RELEASE_REG(host_reg); - - return op_pc + ((op_32 & 0x200) ? 4 : 2); + } + + return op_pc + 1; } -static uint32_t ropMOV_a_AX(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block) +static uint32_t +ropMOV_w_r(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block) { - uint32_t addr; - int host_reg; + int host_reg = LOAD_REG_W((fetchdat >> 3) & 7); - if (op_32 & 0x200) - addr = fastreadl(cs + op_pc); - else - addr = fastreadw(cs + op_pc); + if ((fetchdat & 0xc0) == 0xc0) { + STORE_REG_TARGET_W_RELEASE(host_reg, fetchdat & 7); + } else { + x86seg *target_seg = FETCH_EA(op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32); - CHECK_SEG_WRITE(op_ea_seg); - STORE_IMM_ADDR_L((uintptr_t)&cpu_state.oldpc, op_old_pc); - - host_reg = LOAD_REG_W(REG_AX); + STORE_IMM_ADDR_L((uintptr_t) &cpu_state.oldpc, op_old_pc); - MEM_STORE_ADDR_IMM_W(op_ea_seg, addr, host_reg); + CHECK_SEG_WRITE(target_seg); + CHECK_SEG_LIMITS(target_seg, 1); + + MEM_STORE_ADDR_EA_W(target_seg, host_reg); RELEASE_REG(host_reg); - - return op_pc + ((op_32 & 0x200) ? 4 : 2); + } + + return op_pc + 1; } -static uint32_t ropMOV_a_EAX(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block) + +static uint32_t +ropMOV_l_r(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block) { - uint32_t addr; - int host_reg; + int host_reg; - if (op_32 & 0x200) - addr = fastreadl(cs + op_pc); - else - addr = fastreadw(cs + op_pc); + host_reg = LOAD_REG_L((fetchdat >> 3) & 7); - CHECK_SEG_WRITE(op_ea_seg); - STORE_IMM_ADDR_L((uintptr_t)&cpu_state.oldpc, op_old_pc); - - host_reg = LOAD_REG_L(REG_EAX); + if ((fetchdat & 0xc0) == 0xc0) { + STORE_REG_TARGET_L_RELEASE(host_reg, fetchdat & 7); + } else { + x86seg *target_seg = FETCH_EA(op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32); - MEM_STORE_ADDR_IMM_L(op_ea_seg, addr, host_reg); + STORE_IMM_ADDR_L((uintptr_t) &cpu_state.oldpc, op_old_pc); + + CHECK_SEG_WRITE(target_seg); + CHECK_SEG_LIMITS(target_seg, 3); + + MEM_STORE_ADDR_EA_L(target_seg, host_reg); RELEASE_REG(host_reg); - - return op_pc + ((op_32 & 0x200) ? 4 : 2); + } + + return op_pc + 1; } -static uint32_t ropLEA_w(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block) +static uint32_t +ropMOV_r_b(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block) { - int dest_reg = (fetchdat >> 3) & 7; - - if ((fetchdat & 0xc0) == 0xc0) - return 0; - - FETCH_EA(op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32); - - STORE_REG_TARGET_W_RELEASE(0, dest_reg); + if ((fetchdat & 0xc0) == 0xc0) { + int host_reg = LOAD_REG_B(fetchdat & 7); + STORE_REG_TARGET_B_RELEASE(host_reg, (fetchdat >> 3) & 7); + } else { + x86seg *target_seg = FETCH_EA(op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32); - return op_pc + 1; + STORE_IMM_ADDR_L((uintptr_t) &cpu_state.oldpc, op_old_pc); + + CHECK_SEG_READ(target_seg); + + MEM_LOAD_ADDR_EA_B(target_seg); + STORE_REG_TARGET_B_RELEASE(0, (fetchdat >> 3) & 7); + } + + return op_pc + 1; } -static uint32_t ropLEA_l(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block) +static uint32_t +ropMOV_r_w(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block) { - int dest_reg = (fetchdat >> 3) & 7; - - if ((fetchdat & 0xc0) == 0xc0) - return 0; - - FETCH_EA(op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32); - - STORE_REG_TARGET_L_RELEASE(0, dest_reg); + if ((fetchdat & 0xc0) == 0xc0) { + int host_reg = LOAD_REG_W(fetchdat & 7); + STORE_REG_TARGET_W_RELEASE(host_reg, (fetchdat >> 3) & 7); + } else { + x86seg *target_seg = FETCH_EA(op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32); - return op_pc + 1; + STORE_IMM_ADDR_L((uintptr_t) &cpu_state.oldpc, op_old_pc); + + CHECK_SEG_READ(target_seg); + + MEM_LOAD_ADDR_EA_W(target_seg); + STORE_REG_TARGET_W_RELEASE(0, (fetchdat >> 3) & 7); + } + + return op_pc + 1; +} +static uint32_t +ropMOV_r_l(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block) +{ + if ((fetchdat & 0xc0) == 0xc0) { + int host_reg = LOAD_REG_L(fetchdat & 7); + STORE_REG_TARGET_L_RELEASE(host_reg, (fetchdat >> 3) & 7); + } else { + x86seg *target_seg = FETCH_EA(op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32); + + STORE_IMM_ADDR_L((uintptr_t) &cpu_state.oldpc, op_old_pc); + + CHECK_SEG_READ(target_seg); + + MEM_LOAD_ADDR_EA_L(target_seg); + STORE_REG_TARGET_L_RELEASE(0, (fetchdat >> 3) & 7); + } + + return op_pc + 1; } -static uint32_t ropMOVZX_w_b(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block) +static uint32_t +ropMOV_b_imm(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block) { - if ((fetchdat & 0xc0) == 0xc0) - { - int host_reg = LOAD_REG_B(fetchdat & 7); - host_reg = ZERO_EXTEND_W_B(host_reg); - STORE_REG_TARGET_W_RELEASE(host_reg, (fetchdat >> 3) & 7); - } + if ((fetchdat & 0xc0) == 0xc0) { + STORE_IMM_REG_B(fetchdat & 7, (fetchdat >> 8) & 0xff); + } else { + x86seg *target_seg = FETCH_EA(op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32); + uint32_t imm = fastreadb(cs + op_pc + 1); + int host_reg = LOAD_REG_IMM(imm); + + STORE_IMM_ADDR_L((uintptr_t) &cpu_state.oldpc, op_old_pc); + CHECK_SEG_WRITE(target_seg); + + MEM_STORE_ADDR_EA_B(target_seg, host_reg); + RELEASE_REG(host_reg); + } + + return op_pc + 2; +} +static uint32_t +ropMOV_w_imm(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block) +{ + if ((fetchdat & 0xc0) == 0xc0) { + STORE_IMM_REG_W(fetchdat & 7, (fetchdat >> 8) & 0xffff); + } else { + x86seg *target_seg = FETCH_EA(op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32); + uint32_t imm = fastreadw(cs + op_pc + 1); + int host_reg = LOAD_REG_IMM(imm); + + STORE_IMM_ADDR_L((uintptr_t) &cpu_state.oldpc, op_old_pc); + CHECK_SEG_WRITE(target_seg); + + MEM_STORE_ADDR_EA_W(target_seg, host_reg); + RELEASE_REG(host_reg); + } + + return op_pc + 3; +} +static uint32_t +ropMOV_l_imm(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block) +{ + if ((fetchdat & 0xc0) == 0xc0) { + uint32_t imm = fastreadl(cs + op_pc + 1); + + STORE_IMM_REG_L(fetchdat & 7, imm); + } else { + x86seg *target_seg = FETCH_EA(op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32); + uint32_t imm = fastreadl(cs + op_pc + 1); + int host_reg = LOAD_REG_IMM(imm); + + STORE_IMM_ADDR_L((uintptr_t) &cpu_state.oldpc, op_old_pc); + CHECK_SEG_WRITE(target_seg); + + MEM_STORE_ADDR_EA_L(target_seg, host_reg); + RELEASE_REG(host_reg); + } + + return op_pc + 5; +} + +static uint32_t +ropMOV_AL_a(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block) +{ + uint32_t addr; + + if (op_32 & 0x200) + addr = fastreadl(cs + op_pc); + else + addr = fastreadw(cs + op_pc); + + CHECK_SEG_READ(op_ea_seg); + STORE_IMM_ADDR_L((uintptr_t) &cpu_state.oldpc, op_old_pc); + + MEM_LOAD_ADDR_IMM_B(op_ea_seg, addr); + STORE_REG_TARGET_B_RELEASE(0, REG_AL); + + return op_pc + ((op_32 & 0x200) ? 4 : 2); +} +static uint32_t +ropMOV_AX_a(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block) +{ + uint32_t addr; + + if (op_32 & 0x200) + addr = fastreadl(cs + op_pc); + else + addr = fastreadw(cs + op_pc); + + CHECK_SEG_READ(op_ea_seg); + STORE_IMM_ADDR_L((uintptr_t) &cpu_state.oldpc, op_old_pc); + + MEM_LOAD_ADDR_IMM_W(op_ea_seg, addr); + STORE_REG_TARGET_W_RELEASE(0, REG_AX); + + return op_pc + ((op_32 & 0x200) ? 4 : 2); +} +static uint32_t +ropMOV_EAX_a(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block) +{ + uint32_t addr; + + if (op_32 & 0x200) + addr = fastreadl(cs + op_pc); + else + addr = fastreadw(cs + op_pc); + + CHECK_SEG_READ(op_ea_seg); + STORE_IMM_ADDR_L((uintptr_t) &cpu_state.oldpc, op_old_pc); + + MEM_LOAD_ADDR_IMM_L(op_ea_seg, addr); + STORE_REG_TARGET_L_RELEASE(0, REG_EAX); + + return op_pc + ((op_32 & 0x200) ? 4 : 2); +} + +static uint32_t +ropMOV_a_AL(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block) +{ + uint32_t addr; + int host_reg; + + if (op_32 & 0x200) + addr = fastreadl(cs + op_pc); + else + addr = fastreadw(cs + op_pc); + + CHECK_SEG_WRITE(op_ea_seg); + STORE_IMM_ADDR_L((uintptr_t) &cpu_state.oldpc, op_old_pc); + + host_reg = LOAD_REG_B(REG_AL); + + MEM_STORE_ADDR_IMM_B(op_ea_seg, addr, host_reg); + RELEASE_REG(host_reg); + + return op_pc + ((op_32 & 0x200) ? 4 : 2); +} +static uint32_t +ropMOV_a_AX(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block) +{ + uint32_t addr; + int host_reg; + + if (op_32 & 0x200) + addr = fastreadl(cs + op_pc); + else + addr = fastreadw(cs + op_pc); + + CHECK_SEG_WRITE(op_ea_seg); + STORE_IMM_ADDR_L((uintptr_t) &cpu_state.oldpc, op_old_pc); + + host_reg = LOAD_REG_W(REG_AX); + + MEM_STORE_ADDR_IMM_W(op_ea_seg, addr, host_reg); + RELEASE_REG(host_reg); + + return op_pc + ((op_32 & 0x200) ? 4 : 2); +} +static uint32_t +ropMOV_a_EAX(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block) +{ + uint32_t addr; + int host_reg; + + if (op_32 & 0x200) + addr = fastreadl(cs + op_pc); + else + addr = fastreadw(cs + op_pc); + + CHECK_SEG_WRITE(op_ea_seg); + STORE_IMM_ADDR_L((uintptr_t) &cpu_state.oldpc, op_old_pc); + + host_reg = LOAD_REG_L(REG_EAX); + + MEM_STORE_ADDR_IMM_L(op_ea_seg, addr, host_reg); + RELEASE_REG(host_reg); + + return op_pc + ((op_32 & 0x200) ? 4 : 2); +} + +static uint32_t +ropLEA_w(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block) +{ + int dest_reg = (fetchdat >> 3) & 7; + + if ((fetchdat & 0xc0) == 0xc0) + return 0; + + FETCH_EA(op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32); + + STORE_REG_TARGET_W_RELEASE(0, dest_reg); + + return op_pc + 1; +} +static uint32_t +ropLEA_l(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block) +{ + int dest_reg = (fetchdat >> 3) & 7; + + if ((fetchdat & 0xc0) == 0xc0) + return 0; + + FETCH_EA(op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32); + + STORE_REG_TARGET_L_RELEASE(0, dest_reg); + + return op_pc + 1; +} + +static uint32_t +ropMOVZX_w_b(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block) +{ + if ((fetchdat & 0xc0) == 0xc0) { + int host_reg = LOAD_REG_B(fetchdat & 7); + host_reg = ZERO_EXTEND_W_B(host_reg); + STORE_REG_TARGET_W_RELEASE(host_reg, (fetchdat >> 3) & 7); + } else { + x86seg *target_seg = FETCH_EA(op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32); + + STORE_IMM_ADDR_L((uintptr_t) &cpu_state.oldpc, op_old_pc); + + CHECK_SEG_READ(target_seg); + + MEM_LOAD_ADDR_EA_B(target_seg); + ZERO_EXTEND_W_B(0); + STORE_REG_TARGET_W_RELEASE(0, (fetchdat >> 3) & 7); + } + + return op_pc + 1; +} +static uint32_t +ropMOVZX_l_b(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block) +{ + if ((fetchdat & 0xc0) == 0xc0) { + int host_reg = LOAD_REG_B(fetchdat & 7); + host_reg = ZERO_EXTEND_L_B(host_reg); + STORE_REG_TARGET_L_RELEASE(host_reg, (fetchdat >> 3) & 7); + } else { + x86seg *target_seg = FETCH_EA(op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32); + + STORE_IMM_ADDR_L((uintptr_t) &cpu_state.oldpc, op_old_pc); + + CHECK_SEG_READ(target_seg); + + MEM_LOAD_ADDR_EA_B(target_seg); + ZERO_EXTEND_L_B(0); + STORE_REG_TARGET_L_RELEASE(0, (fetchdat >> 3) & 7); + } + + return op_pc + 1; +} +static uint32_t +ropMOVZX_l_w(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block) +{ + if ((fetchdat & 0xc0) == 0xc0) { + int host_reg = LOAD_REG_W(fetchdat & 7); + host_reg = ZERO_EXTEND_L_W(host_reg); + STORE_REG_TARGET_L_RELEASE(host_reg, (fetchdat >> 3) & 7); + } else { + x86seg *target_seg = FETCH_EA(op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32); + + STORE_IMM_ADDR_L((uintptr_t) &cpu_state.oldpc, op_old_pc); + + CHECK_SEG_READ(target_seg); + + MEM_LOAD_ADDR_EA_W(target_seg); + ZERO_EXTEND_L_W(0); + STORE_REG_TARGET_L_RELEASE(0, (fetchdat >> 3) & 7); + } + + return op_pc + 1; +} + +static uint32_t +ropMOVSX_w_b(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block) +{ + if ((fetchdat & 0xc0) == 0xc0) { + int host_reg = LOAD_REG_B(fetchdat & 7); + host_reg = SIGN_EXTEND_W_B(host_reg); + STORE_REG_TARGET_W_RELEASE(host_reg, (fetchdat >> 3) & 7); + } else { + x86seg *target_seg = FETCH_EA(op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32); + + STORE_IMM_ADDR_L((uintptr_t) &cpu_state.oldpc, op_old_pc); + + CHECK_SEG_READ(target_seg); + + MEM_LOAD_ADDR_EA_B(target_seg); + SIGN_EXTEND_W_B(0); + STORE_REG_TARGET_W_RELEASE(0, (fetchdat >> 3) & 7); + } + + return op_pc + 1; +} +static uint32_t +ropMOVSX_l_b(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block) +{ + if ((fetchdat & 0xc0) == 0xc0) { + int host_reg = LOAD_REG_B(fetchdat & 7); + host_reg = SIGN_EXTEND_L_B(host_reg); + STORE_REG_TARGET_L_RELEASE(host_reg, (fetchdat >> 3) & 7); + } else { + x86seg *target_seg = FETCH_EA(op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32); + + STORE_IMM_ADDR_L((uintptr_t) &cpu_state.oldpc, op_old_pc); + + CHECK_SEG_READ(target_seg); + + MEM_LOAD_ADDR_EA_B(target_seg); + SIGN_EXTEND_L_B(0); + STORE_REG_TARGET_L_RELEASE(0, (fetchdat >> 3) & 7); + } + + return op_pc + 1; +} +static uint32_t +ropMOVSX_l_w(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block) +{ + if ((fetchdat & 0xc0) == 0xc0) { + int host_reg = LOAD_REG_W(fetchdat & 7); + host_reg = SIGN_EXTEND_L_W(host_reg); + STORE_REG_TARGET_L_RELEASE(host_reg, (fetchdat >> 3) & 7); + } else { + x86seg *target_seg = FETCH_EA(op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32); + + STORE_IMM_ADDR_L((uintptr_t) &cpu_state.oldpc, op_old_pc); + + CHECK_SEG_READ(target_seg); + + MEM_LOAD_ADDR_EA_W(target_seg); + SIGN_EXTEND_L_W(0); + STORE_REG_TARGET_L_RELEASE(0, (fetchdat >> 3) & 7); + } + + return op_pc + 1; +} + +static uint32_t +ropMOV_w_seg(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block) +{ + int host_reg; + + switch (fetchdat & 0x38) { + case 0x00: /*ES*/ + host_reg = LOAD_VAR_WL((uintptr_t) &ES); + break; + case 0x08: /*CS*/ + host_reg = LOAD_VAR_WL((uintptr_t) &CS); + break; + case 0x18: /*DS*/ + host_reg = LOAD_VAR_WL((uintptr_t) &DS); + break; + case 0x10: /*SS*/ + host_reg = LOAD_VAR_WL((uintptr_t) &SS); + break; + case 0x20: /*FS*/ + host_reg = LOAD_VAR_WL((uintptr_t) &FS); + break; + case 0x28: /*GS*/ + host_reg = LOAD_VAR_WL((uintptr_t) &GS); + break; + default: + return 0; + } + + if ((fetchdat & 0xc0) == 0xc0) { + if (op_32 & 0x100) + STORE_REG_TARGET_L_RELEASE(host_reg, fetchdat & 7); else - { - x86seg *target_seg = FETCH_EA(op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32); + STORE_REG_TARGET_W_RELEASE(host_reg, fetchdat & 7); + } else { + x86seg *target_seg = FETCH_EA(op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32); - STORE_IMM_ADDR_L((uintptr_t)&cpu_state.oldpc, op_old_pc); - - CHECK_SEG_READ(target_seg); + STORE_IMM_ADDR_L((uintptr_t) &cpu_state.oldpc, op_old_pc); - MEM_LOAD_ADDR_EA_B(target_seg); - ZERO_EXTEND_W_B(0); - STORE_REG_TARGET_W_RELEASE(0, (fetchdat >> 3) & 7); - } - - return op_pc + 1; + CHECK_SEG_WRITE(target_seg); + CHECK_SEG_LIMITS(target_seg, 1); + + MEM_STORE_ADDR_EA_W(target_seg, host_reg); + RELEASE_REG(host_reg); + } + + return op_pc + 1; } -static uint32_t ropMOVZX_l_b(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block) +static uint32_t +ropMOV_seg_w(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block) { - if ((fetchdat & 0xc0) == 0xc0) - { - int host_reg = LOAD_REG_B(fetchdat & 7); - host_reg = ZERO_EXTEND_L_B(host_reg); - STORE_REG_TARGET_L_RELEASE(host_reg, (fetchdat >> 3) & 7); - } - else - { - x86seg *target_seg = FETCH_EA(op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32); + int host_reg; - STORE_IMM_ADDR_L((uintptr_t)&cpu_state.oldpc, op_old_pc); - - CHECK_SEG_READ(target_seg); + switch (fetchdat & 0x38) { + case 0x00: /*ES*/ + case 0x18: /*DS*/ + case 0x20: /*FS*/ + case 0x28: /*GS*/ + break; + case 0x10: /*SS*/ + default: + return 0; + } - MEM_LOAD_ADDR_EA_B(target_seg); - ZERO_EXTEND_L_B(0); - STORE_REG_TARGET_L_RELEASE(0, (fetchdat >> 3) & 7); - } - - return op_pc + 1; -} -static uint32_t ropMOVZX_l_w(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block) -{ - if ((fetchdat & 0xc0) == 0xc0) - { - int host_reg = LOAD_REG_W(fetchdat & 7); - host_reg = ZERO_EXTEND_L_W(host_reg); - STORE_REG_TARGET_L_RELEASE(host_reg, (fetchdat >> 3) & 7); - } - else - { - x86seg *target_seg = FETCH_EA(op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32); + STORE_IMM_ADDR_L((uintptr_t) &cpu_state.oldpc, op_old_pc); - STORE_IMM_ADDR_L((uintptr_t)&cpu_state.oldpc, op_old_pc); - - CHECK_SEG_READ(target_seg); + if ((fetchdat & 0xc0) == 0xc0) + host_reg = LOAD_REG_W(fetchdat & 7); + else { + x86seg *target_seg = FETCH_EA(op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32); - MEM_LOAD_ADDR_EA_W(target_seg); - ZERO_EXTEND_L_W(0); - STORE_REG_TARGET_L_RELEASE(0, (fetchdat >> 3) & 7); - } - - return op_pc + 1; + CHECK_SEG_READ(target_seg); + MEM_LOAD_ADDR_EA_W(target_seg); + + host_reg = 0; + } + + switch (fetchdat & 0x38) { + case 0x00: /*ES*/ + LOAD_SEG(host_reg, &cpu_state.seg_es); + break; + case 0x18: /*DS*/ + LOAD_SEG(host_reg, &cpu_state.seg_ds); + break; + case 0x20: /*FS*/ + LOAD_SEG(host_reg, &cpu_state.seg_fs); + break; + case 0x28: /*GS*/ + LOAD_SEG(host_reg, &cpu_state.seg_gs); + break; + } + + return op_pc + 1; } -static uint32_t ropMOVSX_w_b(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block) -{ - if ((fetchdat & 0xc0) == 0xc0) - { - int host_reg = LOAD_REG_B(fetchdat & 7); - host_reg = SIGN_EXTEND_W_B(host_reg); - STORE_REG_TARGET_W_RELEASE(host_reg, (fetchdat >> 3) & 7); - } - else - { - x86seg *target_seg = FETCH_EA(op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32); - - STORE_IMM_ADDR_L((uintptr_t)&cpu_state.oldpc, op_old_pc); - - CHECK_SEG_READ(target_seg); - - MEM_LOAD_ADDR_EA_B(target_seg); - SIGN_EXTEND_W_B(0); - STORE_REG_TARGET_W_RELEASE(0, (fetchdat >> 3) & 7); - } - - return op_pc + 1; -} -static uint32_t ropMOVSX_l_b(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block) -{ - if ((fetchdat & 0xc0) == 0xc0) - { - int host_reg = LOAD_REG_B(fetchdat & 7); - host_reg = SIGN_EXTEND_L_B(host_reg); - STORE_REG_TARGET_L_RELEASE(host_reg, (fetchdat >> 3) & 7); - } - else - { - x86seg *target_seg = FETCH_EA(op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32); - - STORE_IMM_ADDR_L((uintptr_t)&cpu_state.oldpc, op_old_pc); - - CHECK_SEG_READ(target_seg); - - MEM_LOAD_ADDR_EA_B(target_seg); - SIGN_EXTEND_L_B(0); - STORE_REG_TARGET_L_RELEASE(0, (fetchdat >> 3) & 7); - } - - return op_pc + 1; -} -static uint32_t ropMOVSX_l_w(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block) -{ - if ((fetchdat & 0xc0) == 0xc0) - { - int host_reg = LOAD_REG_W(fetchdat & 7); - host_reg = SIGN_EXTEND_L_W(host_reg); - STORE_REG_TARGET_L_RELEASE(host_reg, (fetchdat >> 3) & 7); - } - else - { - x86seg *target_seg = FETCH_EA(op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32); - - STORE_IMM_ADDR_L((uintptr_t)&cpu_state.oldpc, op_old_pc); - - CHECK_SEG_READ(target_seg); - - MEM_LOAD_ADDR_EA_W(target_seg); - SIGN_EXTEND_L_W(0); - STORE_REG_TARGET_L_RELEASE(0, (fetchdat >> 3) & 7); - } - - return op_pc + 1; -} - -static uint32_t ropMOV_w_seg(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block) -{ - int host_reg; - - switch (fetchdat & 0x38) - { - case 0x00: /*ES*/ - host_reg = LOAD_VAR_WL((uintptr_t)&ES); - break; - case 0x08: /*CS*/ - host_reg = LOAD_VAR_WL((uintptr_t)&CS); - break; - case 0x18: /*DS*/ - host_reg = LOAD_VAR_WL((uintptr_t)&DS); - break; - case 0x10: /*SS*/ - host_reg = LOAD_VAR_WL((uintptr_t)&SS); - break; - case 0x20: /*FS*/ - host_reg = LOAD_VAR_WL((uintptr_t)&FS); - break; - case 0x28: /*GS*/ - host_reg = LOAD_VAR_WL((uintptr_t)&GS); - break; - default: - return 0; - } - - if ((fetchdat & 0xc0) == 0xc0) - { - if (op_32 & 0x100) - STORE_REG_TARGET_L_RELEASE(host_reg, fetchdat & 7); - else - STORE_REG_TARGET_W_RELEASE(host_reg, fetchdat & 7); - } - else - { - x86seg *target_seg = FETCH_EA(op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32); - - STORE_IMM_ADDR_L((uintptr_t)&cpu_state.oldpc, op_old_pc); - - CHECK_SEG_WRITE(target_seg); - CHECK_SEG_LIMITS(target_seg, 1); - - MEM_STORE_ADDR_EA_W(target_seg, host_reg); - RELEASE_REG(host_reg); - } - - return op_pc + 1; -} -static uint32_t ropMOV_seg_w(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block) -{ - int host_reg; - - switch (fetchdat & 0x38) - { - case 0x00: /*ES*/ - case 0x18: /*DS*/ - case 0x20: /*FS*/ - case 0x28: /*GS*/ - break; - case 0x10: /*SS*/ - default: - return 0; - } - - STORE_IMM_ADDR_L((uintptr_t)&cpu_state.oldpc, op_old_pc); - - if ((fetchdat & 0xc0) == 0xc0) - host_reg = LOAD_REG_W(fetchdat & 7); - else - { - x86seg *target_seg = FETCH_EA(op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32); - - CHECK_SEG_READ(target_seg); - MEM_LOAD_ADDR_EA_W(target_seg); - - host_reg = 0; - } - - switch (fetchdat & 0x38) - { - case 0x00: /*ES*/ - LOAD_SEG(host_reg, &cpu_state.seg_es); - break; - case 0x18: /*DS*/ - LOAD_SEG(host_reg, &cpu_state.seg_ds); - break; - case 0x20: /*FS*/ - LOAD_SEG(host_reg, &cpu_state.seg_fs); - break; - case 0x28: /*GS*/ - LOAD_SEG(host_reg, &cpu_state.seg_gs); - break; - } - - return op_pc + 1; -} - -#define ropLseg(seg, rseg) \ -static uint32_t ropL ## seg(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block) \ -{ \ - int dest_reg = (fetchdat >> 3) & 7; \ - x86seg *target_seg; \ - \ - if ((fetchdat & 0xc0) == 0xc0) \ - return 0; \ - \ - STORE_IMM_ADDR_L((uintptr_t)&cpu_state.oldpc, op_old_pc); \ - target_seg = FETCH_EA(op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32); \ - SAVE_EA(); \ - \ - if (op_32 & 0x100) \ - { \ - MEM_LOAD_ADDR_EA_L(target_seg); \ - STORE_HOST_REG_ADDR((uintptr_t)&codegen_temp, 0); \ - LOAD_EA(); \ - MEM_LOAD_ADDR_EA_W_OFFSET(target_seg, 4); \ - } \ - else \ - { \ - MEM_LOAD_ADDR_EA_W(target_seg); \ - STORE_HOST_REG_ADDR_W((uintptr_t)&codegen_temp, 0); \ - LOAD_EA(); \ - MEM_LOAD_ADDR_EA_W_OFFSET(target_seg, 2); \ - } \ - LOAD_SEG(0, &rseg); \ - if (op_32 & 0x100) \ - { \ - \ - int host_reg = LOAD_VAR_L((uintptr_t)&codegen_temp); \ - STORE_REG_TARGET_L_RELEASE(host_reg, dest_reg); \ - } \ - else \ - { \ - int host_reg = LOAD_VAR_W((uintptr_t)&codegen_temp); \ - STORE_REG_TARGET_W_RELEASE(host_reg, dest_reg); \ - } \ - \ - if (&rseg == &cpu_state.seg_ss) \ - CPU_BLOCK_END(); /*Instruction might change stack size, so end block here*/ \ - return op_pc + 1; \ -} +#define ropLseg(seg, rseg) \ + static uint32_t ropL##seg(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block) \ + { \ + int dest_reg = (fetchdat >> 3) & 7; \ + x86seg *target_seg; \ + \ + if ((fetchdat & 0xc0) == 0xc0) \ + return 0; \ + \ + STORE_IMM_ADDR_L((uintptr_t) &cpu_state.oldpc, op_old_pc); \ + target_seg = FETCH_EA(op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32); \ + SAVE_EA(); \ + \ + if (op_32 & 0x100) { \ + MEM_LOAD_ADDR_EA_L(target_seg); \ + STORE_HOST_REG_ADDR((uintptr_t) &codegen_temp, 0); \ + LOAD_EA(); \ + MEM_LOAD_ADDR_EA_W_OFFSET(target_seg, 4); \ + } else { \ + MEM_LOAD_ADDR_EA_W(target_seg); \ + STORE_HOST_REG_ADDR_W((uintptr_t) &codegen_temp, 0); \ + LOAD_EA(); \ + MEM_LOAD_ADDR_EA_W_OFFSET(target_seg, 2); \ + } \ + LOAD_SEG(0, &rseg); \ + if (op_32 & 0x100) { \ + \ + int host_reg = LOAD_VAR_L((uintptr_t) &codegen_temp); \ + STORE_REG_TARGET_L_RELEASE(host_reg, dest_reg); \ + } else { \ + int host_reg = LOAD_VAR_W((uintptr_t) &codegen_temp); \ + STORE_REG_TARGET_W_RELEASE(host_reg, dest_reg); \ + } \ + \ + if (&rseg == &cpu_state.seg_ss) \ + CPU_BLOCK_END(); /*Instruction might change stack size, so end block here*/ \ + return op_pc + 1; \ + } +// clang-format off ropLseg(DS, cpu_state.seg_ds) ropLseg(ES, cpu_state.seg_es) ropLseg(FS, cpu_state.seg_fs) ropLseg(GS, cpu_state.seg_gs) ropLseg(SS, cpu_state.seg_ss) +// clang-format on diff --git a/src/codegen/codegen_ops_shift.h b/src/codegen/codegen_ops_shift.h index b67c34544..d750bfcad 100644 --- a/src/codegen/codegen_ops_shift.h +++ b/src/codegen/codegen_ops_shift.h @@ -1,125 +1,129 @@ -#define SHIFT(size, size2, res_store, immediate) \ - if ((fetchdat & 0xc0) == 0xc0) \ - { \ - reg = LOAD_REG_ ## size(fetchdat & 7); \ - if (immediate) count = (fetchdat >> 8) & 0x1f; \ - } \ - else \ - { \ - target_seg = FETCH_EA(op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32); \ - STORE_IMM_ADDR_L((uintptr_t)&cpu_state.oldpc, op_old_pc); \ - SAVE_EA(); \ - MEM_CHECK_WRITE_ ## size(target_seg); \ - reg = MEM_LOAD_ADDR_EA_ ## size ## _NO_ABRT(target_seg); \ - if (immediate) count = fastreadb(cs + op_pc + 1) & 0x1f; \ - } \ - STORE_IMM_ADDR_L((uintptr_t)&cpu_state.flags_op2, count); \ - \ - res_store((uintptr_t)&cpu_state.flags_op1, reg); \ - \ - switch (fetchdat & 0x38) \ - { \ - case 0x20: case 0x30: /*SHL*/ \ - SHL_ ## size ## _IMM(reg, count); \ - STORE_IMM_ADDR_L((uintptr_t)&cpu_state.flags_op, FLAGS_SHL ## size2); \ - break; \ - \ - case 0x28: /*SHR*/ \ - SHR_ ## size ## _IMM(reg, count); \ - STORE_IMM_ADDR_L((uintptr_t)&cpu_state.flags_op, FLAGS_SHR ## size2); \ - break; \ - \ - case 0x38: /*SAR*/ \ - SAR_ ## size ## _IMM(reg, count); \ - STORE_IMM_ADDR_L((uintptr_t)&cpu_state.flags_op, FLAGS_SAR ## size2); \ - break; \ - } \ - \ - res_store((uintptr_t)&cpu_state.flags_res, reg); \ - if ((fetchdat & 0xc0) == 0xc0) \ - STORE_REG_ ## size ## _RELEASE(reg); \ - else \ - { \ - LOAD_EA(); \ - MEM_STORE_ADDR_EA_ ## size ## _NO_ABRT(target_seg, reg); \ - } +#define SHIFT(size, size2, res_store, immediate) \ + if ((fetchdat & 0xc0) == 0xc0) { \ + reg = LOAD_REG_##size(fetchdat & 7); \ + if (immediate) \ + count = (fetchdat >> 8) & 0x1f; \ + } else { \ + target_seg = FETCH_EA(op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32); \ + STORE_IMM_ADDR_L((uintptr_t) &cpu_state.oldpc, op_old_pc); \ + SAVE_EA(); \ + MEM_CHECK_WRITE_##size(target_seg); \ + reg = MEM_LOAD_ADDR_EA_##size##_NO_ABRT(target_seg); \ + if (immediate) \ + count = fastreadb(cs + op_pc + 1) & 0x1f; \ + } \ + STORE_IMM_ADDR_L((uintptr_t) &cpu_state.flags_op2, count); \ + \ + res_store((uintptr_t) &cpu_state.flags_op1, reg); \ + \ + switch (fetchdat & 0x38) { \ + case 0x20: \ + case 0x30: /*SHL*/ \ + SHL_##size##_IMM(reg, count); \ + STORE_IMM_ADDR_L((uintptr_t) &cpu_state.flags_op, FLAGS_SHL##size2); \ + break; \ + \ + case 0x28: /*SHR*/ \ + SHR_##size##_IMM(reg, count); \ + STORE_IMM_ADDR_L((uintptr_t) &cpu_state.flags_op, FLAGS_SHR##size2); \ + break; \ + \ + case 0x38: /*SAR*/ \ + SAR_##size##_IMM(reg, count); \ + STORE_IMM_ADDR_L((uintptr_t) &cpu_state.flags_op, FLAGS_SAR##size2); \ + break; \ + } \ + \ + res_store((uintptr_t) &cpu_state.flags_res, reg); \ + if ((fetchdat & 0xc0) == 0xc0) \ + STORE_REG_##size##_RELEASE(reg); \ + else { \ + LOAD_EA(); \ + MEM_STORE_ADDR_EA_##size##_NO_ABRT(target_seg, reg); \ + } -static uint32_t ropC0(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block) +static uint32_t +ropC0(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block) { - x86seg *target_seg = NULL; - int count; - int reg; + x86seg *target_seg = NULL; + int count; + int reg; - if ((fetchdat & 0x38) < 0x20) - return 0; + if ((fetchdat & 0x38) < 0x20) + return 0; - SHIFT(B, 8, STORE_HOST_REG_ADDR_BL, 1); + SHIFT(B, 8, STORE_HOST_REG_ADDR_BL, 1); - return op_pc + 2; + return op_pc + 2; } -static uint32_t ropC1_w(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block) +static uint32_t +ropC1_w(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block) { - x86seg *target_seg = NULL; - int count; - int reg; + x86seg *target_seg = NULL; + int count; + int reg; - if ((fetchdat & 0x38) < 0x20) - return 0; + if ((fetchdat & 0x38) < 0x20) + return 0; - SHIFT(W, 16, STORE_HOST_REG_ADDR_WL, 1); - - return op_pc + 2; + SHIFT(W, 16, STORE_HOST_REG_ADDR_WL, 1); + + return op_pc + 2; } -static uint32_t ropC1_l(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block) +static uint32_t +ropC1_l(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block) { - x86seg *target_seg = NULL; - int count; - int reg; + x86seg *target_seg = NULL; + int count; + int reg; - if ((fetchdat & 0x38) < 0x20) - return 0; + if ((fetchdat & 0x38) < 0x20) + return 0; - SHIFT(L, 32, STORE_HOST_REG_ADDR, 1); - - return op_pc + 2; + SHIFT(L, 32, STORE_HOST_REG_ADDR, 1); + + return op_pc + 2; } -static uint32_t ropD0(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block) +static uint32_t +ropD0(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block) { - x86seg *target_seg = NULL; - int count = 1; - int reg; + x86seg *target_seg = NULL; + int count = 1; + int reg; - if ((fetchdat & 0x38) < 0x20) - return 0; + if ((fetchdat & 0x38) < 0x20) + return 0; - SHIFT(B, 8, STORE_HOST_REG_ADDR_BL, 0); + SHIFT(B, 8, STORE_HOST_REG_ADDR_BL, 0); - return op_pc + 1; + return op_pc + 1; } -static uint32_t ropD1_w(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block) +static uint32_t +ropD1_w(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block) { - x86seg *target_seg = NULL; - int count = 1; - int reg; + x86seg *target_seg = NULL; + int count = 1; + int reg; - if ((fetchdat & 0x38) < 0x20) - return 0; + if ((fetchdat & 0x38) < 0x20) + return 0; - SHIFT(W, 16, STORE_HOST_REG_ADDR_WL, 0); - - return op_pc + 1; + SHIFT(W, 16, STORE_HOST_REG_ADDR_WL, 0); + + return op_pc + 1; } -static uint32_t ropD1_l(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block) +static uint32_t +ropD1_l(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block) { - x86seg *target_seg = NULL; - int count = 1; - int reg; + x86seg *target_seg = NULL; + int count = 1; + int reg; - if ((fetchdat & 0x38) < 0x20) - return 0; + if ((fetchdat & 0x38) < 0x20) + return 0; - SHIFT(L, 32, STORE_HOST_REG_ADDR, 0); - - return op_pc + 1; + SHIFT(L, 32, STORE_HOST_REG_ADDR, 0); + + return op_pc + 1; } diff --git a/src/codegen/codegen_ops_stack.h b/src/codegen/codegen_ops_stack.h index 288be2c6c..342ddedd4 100644 --- a/src/codegen/codegen_ops_stack.h +++ b/src/codegen/codegen_ops_stack.h @@ -1,238 +1,256 @@ -static uint32_t ropPUSH_16(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block) +static uint32_t +ropPUSH_16(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block) { - int host_reg; + int host_reg; - STORE_IMM_ADDR_L((uintptr_t)&cpu_state.oldpc, op_old_pc); - LOAD_STACK_TO_EA(-2); - host_reg = LOAD_REG_W(opcode & 7); - MEM_STORE_ADDR_EA_W(&cpu_state.seg_ss, host_reg); - SP_MODIFY(-2); - - return op_pc; + STORE_IMM_ADDR_L((uintptr_t) &cpu_state.oldpc, op_old_pc); + LOAD_STACK_TO_EA(-2); + host_reg = LOAD_REG_W(opcode & 7); + MEM_STORE_ADDR_EA_W(&cpu_state.seg_ss, host_reg); + SP_MODIFY(-2); + + return op_pc; } -static uint32_t ropPUSH_32(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block) +static uint32_t +ropPUSH_32(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block) { - int host_reg; + int host_reg; - STORE_IMM_ADDR_L((uintptr_t)&cpu_state.oldpc, op_old_pc); - LOAD_STACK_TO_EA(-4); - host_reg = LOAD_REG_L(opcode & 7); - MEM_STORE_ADDR_EA_L(&cpu_state.seg_ss, host_reg); - SP_MODIFY(-4); + STORE_IMM_ADDR_L((uintptr_t) &cpu_state.oldpc, op_old_pc); + LOAD_STACK_TO_EA(-4); + host_reg = LOAD_REG_L(opcode & 7); + MEM_STORE_ADDR_EA_L(&cpu_state.seg_ss, host_reg); + SP_MODIFY(-4); - return op_pc; + return op_pc; } -static uint32_t ropPUSH_imm_16(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block) +static uint32_t +ropPUSH_imm_16(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block) { - uint16_t imm = fetchdat & 0xffff; - int host_reg; + uint16_t imm = fetchdat & 0xffff; + int host_reg; - STORE_IMM_ADDR_L((uintptr_t)&cpu_state.oldpc, op_old_pc); - LOAD_STACK_TO_EA(-2); - host_reg = LOAD_REG_IMM(imm); - MEM_STORE_ADDR_EA_W(&cpu_state.seg_ss, host_reg); - SP_MODIFY(-2); - - return op_pc+2; + STORE_IMM_ADDR_L((uintptr_t) &cpu_state.oldpc, op_old_pc); + LOAD_STACK_TO_EA(-2); + host_reg = LOAD_REG_IMM(imm); + MEM_STORE_ADDR_EA_W(&cpu_state.seg_ss, host_reg); + SP_MODIFY(-2); + + return op_pc + 2; } -static uint32_t ropPUSH_imm_32(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block) +static uint32_t +ropPUSH_imm_32(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block) { - uint32_t imm = fastreadl(cs + op_pc); - int host_reg; + uint32_t imm = fastreadl(cs + op_pc); + int host_reg; - STORE_IMM_ADDR_L((uintptr_t)&cpu_state.oldpc, op_old_pc); - LOAD_STACK_TO_EA(-4); - host_reg = LOAD_REG_IMM(imm); - MEM_STORE_ADDR_EA_L(&cpu_state.seg_ss, host_reg); - SP_MODIFY(-4); - - return op_pc+4; + STORE_IMM_ADDR_L((uintptr_t) &cpu_state.oldpc, op_old_pc); + LOAD_STACK_TO_EA(-4); + host_reg = LOAD_REG_IMM(imm); + MEM_STORE_ADDR_EA_L(&cpu_state.seg_ss, host_reg); + SP_MODIFY(-4); + + return op_pc + 4; } -static uint32_t ropPUSH_imm_b16(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block) +static uint32_t +ropPUSH_imm_b16(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block) { - uint16_t imm = fetchdat & 0xff; - int host_reg; + uint16_t imm = fetchdat & 0xff; + int host_reg; - if (imm & 0x80) - imm |= 0xff00; + if (imm & 0x80) + imm |= 0xff00; - STORE_IMM_ADDR_L((uintptr_t)&cpu_state.oldpc, op_old_pc); - LOAD_STACK_TO_EA(-2); - host_reg = LOAD_REG_IMM(imm); - MEM_STORE_ADDR_EA_W(&cpu_state.seg_ss, host_reg); - SP_MODIFY(-2); - - return op_pc+1; + STORE_IMM_ADDR_L((uintptr_t) &cpu_state.oldpc, op_old_pc); + LOAD_STACK_TO_EA(-2); + host_reg = LOAD_REG_IMM(imm); + MEM_STORE_ADDR_EA_W(&cpu_state.seg_ss, host_reg); + SP_MODIFY(-2); + + return op_pc + 1; } -static uint32_t ropPUSH_imm_b32(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block) +static uint32_t +ropPUSH_imm_b32(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block) { - uint32_t imm = fetchdat & 0xff; - int host_reg; + uint32_t imm = fetchdat & 0xff; + int host_reg; - if (imm & 0x80) - imm |= 0xffffff00; + if (imm & 0x80) + imm |= 0xffffff00; - STORE_IMM_ADDR_L((uintptr_t)&cpu_state.oldpc, op_old_pc); - LOAD_STACK_TO_EA(-4); - host_reg = LOAD_REG_IMM(imm); - MEM_STORE_ADDR_EA_L(&cpu_state.seg_ss, host_reg); - SP_MODIFY(-4); - - return op_pc+1; + STORE_IMM_ADDR_L((uintptr_t) &cpu_state.oldpc, op_old_pc); + LOAD_STACK_TO_EA(-4); + host_reg = LOAD_REG_IMM(imm); + MEM_STORE_ADDR_EA_L(&cpu_state.seg_ss, host_reg); + SP_MODIFY(-4); + + return op_pc + 1; } -static uint32_t ropPOP_16(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block) +static uint32_t +ropPOP_16(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block) { - STORE_IMM_ADDR_L((uintptr_t)&cpu_state.oldpc, op_old_pc); - LOAD_STACK_TO_EA(0); - MEM_LOAD_ADDR_EA_W(&cpu_state.seg_ss); - SP_MODIFY(2); - STORE_REG_TARGET_W_RELEASE(0, opcode & 7); - - return op_pc; + STORE_IMM_ADDR_L((uintptr_t) &cpu_state.oldpc, op_old_pc); + LOAD_STACK_TO_EA(0); + MEM_LOAD_ADDR_EA_W(&cpu_state.seg_ss); + SP_MODIFY(2); + STORE_REG_TARGET_W_RELEASE(0, opcode & 7); + + return op_pc; } -static uint32_t ropPOP_32(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block) +static uint32_t +ropPOP_32(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block) { - STORE_IMM_ADDR_L((uintptr_t)&cpu_state.oldpc, op_old_pc); - LOAD_STACK_TO_EA(0); - MEM_LOAD_ADDR_EA_L(&cpu_state.seg_ss); - SP_MODIFY(4); - STORE_REG_TARGET_L_RELEASE(0, opcode & 7); - - return op_pc; + STORE_IMM_ADDR_L((uintptr_t) &cpu_state.oldpc, op_old_pc); + LOAD_STACK_TO_EA(0); + MEM_LOAD_ADDR_EA_L(&cpu_state.seg_ss); + SP_MODIFY(4); + STORE_REG_TARGET_L_RELEASE(0, opcode & 7); + + return op_pc; } -static uint32_t ropRET_16(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block) +static uint32_t +ropRET_16(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block) { - STORE_IMM_ADDR_L((uintptr_t)&cpu_state.oldpc, op_old_pc); - LOAD_STACK_TO_EA(0); - MEM_LOAD_ADDR_EA_W(&cpu_state.seg_ss); - STORE_HOST_REG_ADDR((uintptr_t)&cpu_state.pc, 0); - SP_MODIFY(2); - - return -1; + STORE_IMM_ADDR_L((uintptr_t) &cpu_state.oldpc, op_old_pc); + LOAD_STACK_TO_EA(0); + MEM_LOAD_ADDR_EA_W(&cpu_state.seg_ss); + STORE_HOST_REG_ADDR((uintptr_t) &cpu_state.pc, 0); + SP_MODIFY(2); + + return -1; } -static uint32_t ropRET_32(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block) +static uint32_t +ropRET_32(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block) { - STORE_IMM_ADDR_L((uintptr_t)&cpu_state.oldpc, op_old_pc); - LOAD_STACK_TO_EA(0); - MEM_LOAD_ADDR_EA_L(&cpu_state.seg_ss); - STORE_HOST_REG_ADDR((uintptr_t)&cpu_state.pc, 0); - SP_MODIFY(4); - - return -1; + STORE_IMM_ADDR_L((uintptr_t) &cpu_state.oldpc, op_old_pc); + LOAD_STACK_TO_EA(0); + MEM_LOAD_ADDR_EA_L(&cpu_state.seg_ss); + STORE_HOST_REG_ADDR((uintptr_t) &cpu_state.pc, 0); + SP_MODIFY(4); + + return -1; } -static uint32_t ropRET_imm_16(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block) +static uint32_t +ropRET_imm_16(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block) { - uint16_t offset = fetchdat & 0xffff; + uint16_t offset = fetchdat & 0xffff; - STORE_IMM_ADDR_L((uintptr_t)&cpu_state.oldpc, op_old_pc); - LOAD_STACK_TO_EA(0); - MEM_LOAD_ADDR_EA_W(&cpu_state.seg_ss); - STORE_HOST_REG_ADDR((uintptr_t)&cpu_state.pc, 0); - SP_MODIFY(2+offset); - - return -1; + STORE_IMM_ADDR_L((uintptr_t) &cpu_state.oldpc, op_old_pc); + LOAD_STACK_TO_EA(0); + MEM_LOAD_ADDR_EA_W(&cpu_state.seg_ss); + STORE_HOST_REG_ADDR((uintptr_t) &cpu_state.pc, 0); + SP_MODIFY(2 + offset); + + return -1; } -static uint32_t ropRET_imm_32(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block) +static uint32_t +ropRET_imm_32(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block) { - uint16_t offset = fetchdat & 0xffff; + uint16_t offset = fetchdat & 0xffff; - STORE_IMM_ADDR_L((uintptr_t)&cpu_state.oldpc, op_old_pc); - LOAD_STACK_TO_EA(0); - MEM_LOAD_ADDR_EA_L(&cpu_state.seg_ss); - STORE_HOST_REG_ADDR((uintptr_t)&cpu_state.pc, 0); - SP_MODIFY(4+offset); - - return -1; + STORE_IMM_ADDR_L((uintptr_t) &cpu_state.oldpc, op_old_pc); + LOAD_STACK_TO_EA(0); + MEM_LOAD_ADDR_EA_L(&cpu_state.seg_ss); + STORE_HOST_REG_ADDR((uintptr_t) &cpu_state.pc, 0); + SP_MODIFY(4 + offset); + + return -1; } -static uint32_t ropCALL_r16(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block) +static uint32_t +ropCALL_r16(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block) { - uint16_t offset = fetchdat & 0xffff; - int host_reg; + uint16_t offset = fetchdat & 0xffff; + int host_reg; - STORE_IMM_ADDR_L((uintptr_t)&cpu_state.oldpc, op_old_pc); - LOAD_STACK_TO_EA(-2); - host_reg = LOAD_REG_IMM(op_pc+2); - MEM_STORE_ADDR_EA_W(&cpu_state.seg_ss, host_reg); - SP_MODIFY(-2); - STORE_IMM_ADDR_L((uintptr_t)&cpu_state.pc, (op_pc+2+offset) & 0xffff); - - return -1; + STORE_IMM_ADDR_L((uintptr_t) &cpu_state.oldpc, op_old_pc); + LOAD_STACK_TO_EA(-2); + host_reg = LOAD_REG_IMM(op_pc + 2); + MEM_STORE_ADDR_EA_W(&cpu_state.seg_ss, host_reg); + SP_MODIFY(-2); + STORE_IMM_ADDR_L((uintptr_t) &cpu_state.pc, (op_pc + 2 + offset) & 0xffff); + + return -1; } -static uint32_t ropCALL_r32(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block) +static uint32_t +ropCALL_r32(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block) { - uint32_t offset = fastreadl(cs + op_pc); - int host_reg; + uint32_t offset = fastreadl(cs + op_pc); + int host_reg; - STORE_IMM_ADDR_L((uintptr_t)&cpu_state.oldpc, op_old_pc); - LOAD_STACK_TO_EA(-4); - host_reg = LOAD_REG_IMM(op_pc+4); - MEM_STORE_ADDR_EA_L(&cpu_state.seg_ss, host_reg); - SP_MODIFY(-4); - STORE_IMM_ADDR_L((uintptr_t)&cpu_state.pc, op_pc+4+offset); - - return -1; + STORE_IMM_ADDR_L((uintptr_t) &cpu_state.oldpc, op_old_pc); + LOAD_STACK_TO_EA(-4); + host_reg = LOAD_REG_IMM(op_pc + 4); + MEM_STORE_ADDR_EA_L(&cpu_state.seg_ss, host_reg); + SP_MODIFY(-4); + STORE_IMM_ADDR_L((uintptr_t) &cpu_state.pc, op_pc + 4 + offset); + + return -1; } -static uint32_t ropLEAVE_16(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block) +static uint32_t +ropLEAVE_16(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block) { - int host_reg; + int host_reg; - STORE_IMM_ADDR_L((uintptr_t)&cpu_state.oldpc, op_old_pc); - LOAD_EBP_TO_EA(0); - MEM_LOAD_ADDR_EA_W(&cpu_state.seg_ss); - host_reg = LOAD_REG_W(REG_BP); /*SP = BP + 2*/ - ADD_HOST_REG_IMM_W(host_reg, 2); - STORE_REG_TARGET_W_RELEASE(host_reg, REG_SP); - STORE_REG_TARGET_W_RELEASE(0, REG_BP); /*BP = POP_W()*/ + STORE_IMM_ADDR_L((uintptr_t) &cpu_state.oldpc, op_old_pc); + LOAD_EBP_TO_EA(0); + MEM_LOAD_ADDR_EA_W(&cpu_state.seg_ss); + host_reg = LOAD_REG_W(REG_BP); /*SP = BP + 2*/ + ADD_HOST_REG_IMM_W(host_reg, 2); + STORE_REG_TARGET_W_RELEASE(host_reg, REG_SP); + STORE_REG_TARGET_W_RELEASE(0, REG_BP); /*BP = POP_W()*/ - return op_pc; + return op_pc; } -static uint32_t ropLEAVE_32(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block) +static uint32_t +ropLEAVE_32(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block) { - int host_reg; + int host_reg; - STORE_IMM_ADDR_L((uintptr_t)&cpu_state.oldpc, op_old_pc); - LOAD_EBP_TO_EA(0); - MEM_LOAD_ADDR_EA_L(&cpu_state.seg_ss); - host_reg = LOAD_REG_L(REG_EBP); /*ESP = EBP + 4*/ - ADD_HOST_REG_IMM(host_reg, 4); - STORE_REG_TARGET_L_RELEASE(host_reg, REG_ESP); - STORE_REG_TARGET_L_RELEASE(0, REG_EBP); /*EBP = POP_L()*/ - - return op_pc; + STORE_IMM_ADDR_L((uintptr_t) &cpu_state.oldpc, op_old_pc); + LOAD_EBP_TO_EA(0); + MEM_LOAD_ADDR_EA_L(&cpu_state.seg_ss); + host_reg = LOAD_REG_L(REG_EBP); /*ESP = EBP + 4*/ + ADD_HOST_REG_IMM(host_reg, 4); + STORE_REG_TARGET_L_RELEASE(host_reg, REG_ESP); + STORE_REG_TARGET_L_RELEASE(0, REG_EBP); /*EBP = POP_L()*/ + + return op_pc; } -#define ROP_PUSH_SEG(seg) \ -static uint32_t ropPUSH_ ## seg ## _16(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block) \ -{ \ - int host_reg; \ - \ - STORE_IMM_ADDR_L((uintptr_t)&cpu_state.oldpc, op_old_pc); \ - LOAD_STACK_TO_EA(-2); \ - host_reg = LOAD_VAR_W((uintptr_t)&seg); \ - MEM_STORE_ADDR_EA_W(&cpu_state.seg_ss, host_reg); \ - SP_MODIFY(-2); \ - \ - return op_pc; \ -} \ -static uint32_t ropPUSH_ ## seg ## _32(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block) \ -{ \ - int host_reg; \ - \ - STORE_IMM_ADDR_L((uintptr_t)&cpu_state.oldpc, op_old_pc); \ - LOAD_STACK_TO_EA(-4); \ - host_reg = LOAD_VAR_W((uintptr_t)&seg); \ - MEM_STORE_ADDR_EA_L(&cpu_state.seg_ss, host_reg); \ - SP_MODIFY(-4); \ - \ - return op_pc; \ -} +#define ROP_PUSH_SEG(seg) \ + static uint32_t \ + ropPUSH_##seg##_16(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block) \ + { \ + int host_reg; \ + \ + STORE_IMM_ADDR_L((uintptr_t) &cpu_state.oldpc, op_old_pc); \ + LOAD_STACK_TO_EA(-2); \ + host_reg = LOAD_VAR_W((uintptr_t) &seg); \ + MEM_STORE_ADDR_EA_W(&cpu_state.seg_ss, host_reg); \ + SP_MODIFY(-2); \ + \ + return op_pc; \ + } \ + static uint32_t \ + ropPUSH_##seg##_32(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block) \ + { \ + int host_reg; \ + \ + STORE_IMM_ADDR_L((uintptr_t) &cpu_state.oldpc, op_old_pc); \ + LOAD_STACK_TO_EA(-4); \ + host_reg = LOAD_VAR_W((uintptr_t) &seg); \ + MEM_STORE_ADDR_EA_L(&cpu_state.seg_ss, host_reg); \ + SP_MODIFY(-4); \ + \ + return op_pc; \ + } ROP_PUSH_SEG(CS) ROP_PUSH_SEG(DS) @@ -241,27 +259,29 @@ ROP_PUSH_SEG(FS) ROP_PUSH_SEG(GS) ROP_PUSH_SEG(SS) -#define ROP_POP_SEG(seg, rseg) \ -static uint32_t ropPOP_ ## seg ## _16(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block) \ -{ \ - STORE_IMM_ADDR_L((uintptr_t)&cpu_state.oldpc, op_old_pc); \ - LOAD_STACK_TO_EA(0); \ - MEM_LOAD_ADDR_EA_W(&cpu_state.seg_ss); \ - LOAD_SEG(0, &rseg); \ - SP_MODIFY(2); \ - \ - return op_pc; \ -} \ -static uint32_t ropPOP_ ## seg ## _32(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block) \ -{ \ - STORE_IMM_ADDR_L((uintptr_t)&cpu_state.oldpc, op_old_pc); \ - LOAD_STACK_TO_EA(0); \ - MEM_LOAD_ADDR_EA_W(&cpu_state.seg_ss); \ - LOAD_SEG(0, &rseg); \ - SP_MODIFY(4); \ - \ - return op_pc; \ -} +#define ROP_POP_SEG(seg, rseg) \ + static uint32_t \ + ropPOP_##seg##_16(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block) \ + { \ + STORE_IMM_ADDR_L((uintptr_t) &cpu_state.oldpc, op_old_pc); \ + LOAD_STACK_TO_EA(0); \ + MEM_LOAD_ADDR_EA_W(&cpu_state.seg_ss); \ + LOAD_SEG(0, &rseg); \ + SP_MODIFY(2); \ + \ + return op_pc; \ + } \ + static uint32_t \ + ropPOP_##seg##_32(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block) \ + { \ + STORE_IMM_ADDR_L((uintptr_t) &cpu_state.oldpc, op_old_pc); \ + LOAD_STACK_TO_EA(0); \ + MEM_LOAD_ADDR_EA_W(&cpu_state.seg_ss); \ + LOAD_SEG(0, &rseg); \ + SP_MODIFY(4); \ + \ + return op_pc; \ + } ROP_POP_SEG(DS, cpu_state.seg_ds) ROP_POP_SEG(ES, cpu_state.seg_es) diff --git a/src/codegen/codegen_ops_x86-64.h b/src/codegen/codegen_ops_x86-64.h index 9f3f844a4..bc6293c0b 100644 --- a/src/codegen/codegen_ops_x86-64.h +++ b/src/codegen/codegen_ops_x86-64.h @@ -4,4519 +4,4154 @@ #include #define HOST_REG_XMM_START 0 -#define HOST_REG_XMM_END 7 +#define HOST_REG_XMM_END 7 -#define IS_32_ADDR(x) !(((uintptr_t)x) & 0xffffffff00000000) +#define IS_32_ADDR(x) !(((uintptr_t) x) & 0xffffffff00000000) -static inline int find_host_xmm_reg() +static __inline int +find_host_xmm_reg(void) { - int c; - for (c = HOST_REG_XMM_START; c < HOST_REG_XMM_END; c++) - { - if (host_reg_xmm_mapping[c] == -1) - break; - } - - if (c == HOST_REG_XMM_END) - fatal("Out of host XMM regs!\n"); - return c; + int c; + for (c = HOST_REG_XMM_START; c < HOST_REG_XMM_END; c++) { + if (host_reg_xmm_mapping[c] == -1) + break; + } + + if (c == HOST_REG_XMM_END) + fatal("Out of host XMM regs!\n"); + return c; } -static inline void call(codeblock_t *block, uintptr_t func) +static __inline void +call(codeblock_t *block, uintptr_t func) { - uintptr_t diff = func - (uintptr_t)&block->data[block_pos + 5]; + intptr_t diff = (intptr_t) (func - (uintptr_t) &block->data[block_pos + 5]); - codegen_reg_loaded[0] = codegen_reg_loaded[1] = codegen_reg_loaded[2] = codegen_reg_loaded[3] = 0; - codegen_reg_loaded[4] = codegen_reg_loaded[5] = codegen_reg_loaded[6] = codegen_reg_loaded[7] = 0; + codegen_reg_loaded[0] = codegen_reg_loaded[1] = codegen_reg_loaded[2] = codegen_reg_loaded[3] = 0; + codegen_reg_loaded[4] = codegen_reg_loaded[5] = codegen_reg_loaded[6] = codegen_reg_loaded[7] = 0; - if (diff >= -0x80000000ULL && diff < 0x7fffffffULL) - { - addbyte(0xE8); /*CALL*/ - addlong((uint32_t)diff); - } - else - { - addbyte(0x48); /*MOV RAX, func*/ - addbyte(0xb8); - addquad(func); - addbyte(0xff); /*CALL RAX*/ - addbyte(0xd0); - } + if (diff >= -0x80000000LL && diff < 0x7fffffffLL) { + addbyte(0xE8); /*CALL*/ + addlong((uint32_t) diff); + } else { + addbyte(0x48); /*MOV RAX, func*/ + addbyte(0xb8); + addquad(func); + addbyte(0xff); /*CALL RAX*/ + addbyte(0xd0); + } } -static inline void call_long(uintptr_t func) +static __inline void +call_long(uintptr_t func) { - codegen_reg_loaded[0] = codegen_reg_loaded[1] = codegen_reg_loaded[2] = codegen_reg_loaded[3] = 0; - codegen_reg_loaded[4] = codegen_reg_loaded[5] = codegen_reg_loaded[6] = codegen_reg_loaded[7] = 0; + codegen_reg_loaded[0] = codegen_reg_loaded[1] = codegen_reg_loaded[2] = codegen_reg_loaded[3] = 0; + codegen_reg_loaded[4] = codegen_reg_loaded[5] = codegen_reg_loaded[6] = codegen_reg_loaded[7] = 0; - addbyte(0x48); /*MOV RAX, func*/ - addbyte(0xb8); - addquad(func); - addbyte(0xff); /*CALL RAX*/ - addbyte(0xd0); + addbyte(0x48); /*MOV RAX, func*/ + addbyte(0xb8); + addquad(func); + addbyte(0xff); /*CALL RAX*/ + addbyte(0xd0); } -static inline void load_param_1_32(codeblock_t *block, uint32_t param) +static __inline void +load_param_1_32(codeblock_t *block, uint32_t param) { #if _WIN64 - addbyte(0xb9); /*MOVL $fetchdat,%ecx*/ + addbyte(0xb9); /*MOVL $fetchdat,%ecx*/ #else - addbyte(0xbf); /*MOVL $fetchdat,%edi*/ + addbyte(0xbf); /*MOVL $fetchdat,%edi*/ #endif - addlong(param); + addlong(param); } -static inline void load_param_1_reg_32(int reg) +static __inline void +load_param_1_reg_32(int reg) { #if _WIN64 - if (reg & 8) - addbyte(0x44); - addbyte(0x89); /*MOV ECX, EAX*/ - addbyte(0xc0 | REG_ECX | (reg << 3)); + if (reg & 8) + addbyte(0x44); + addbyte(0x89); /*MOV ECX, EAX*/ + addbyte(0xc0 | REG_ECX | (reg << 3)); #else - if (reg & 8) - addbyte(0x44); - addbyte(0x89); /*MOV EDI, EAX*/ - addbyte(0xc0 | REG_EDI | (reg << 3)); + if (reg & 8) + addbyte(0x44); + addbyte(0x89); /*MOV EDI, EAX*/ + addbyte(0xc0 | REG_EDI | (reg << 3)); #endif } #if 0 -static inline void load_param_1_64(codeblock_t *block, uint64_t param) +static __inline void load_param_1_64(codeblock_t *block, uint64_t param) { - addbyte(0x48); -#if _WIN64 + addbyte(0x48); +# if _WIN64 addbyte(0xb9); /*MOVL $fetchdat,%ecx*/ -#else +# else addbyte(0xbf); /*MOVL $fetchdat,%edi*/ -#endif +# endif addquad(param); } #endif -static inline void load_param_2_32(codeblock_t *block, uint32_t param) +static __inline void +load_param_2_32(codeblock_t *block, uint32_t param) { #if _WIN64 - addbyte(0xba); /*MOVL $fetchdat,%edx*/ + addbyte(0xba); /*MOVL $fetchdat,%edx*/ #else - addbyte(0xbe); /*MOVL $fetchdat,%esi*/ + addbyte(0xbe); /*MOVL $fetchdat,%esi*/ #endif - addlong(param); + addlong(param); } -static inline void load_param_2_reg_32(int reg) +static __inline void +load_param_2_reg_32(int reg) { #if _WIN64 - if (reg & 8) - addbyte(0x44); - addbyte(0x89); /*MOV EDX, EAX*/ + if (reg & 8) + addbyte(0x44); + addbyte(0x89); /*MOV EDX, EAX*/ + addbyte(0xc0 | REG_EDX | (reg << 3)); +#else + if (reg & 8) + addbyte(0x44); + addbyte(0x89); /*MOV ESI, EAX*/ + addbyte(0xc0 | REG_ESI | (reg << 3)); +#endif +} +static __inline void +load_param_2_64(codeblock_t *block, uint64_t param) +{ + addbyte(0x48); +#if _WIN64 + addbyte(0xba); /*MOVL $fetchdat,%edx*/ +#else + addbyte(0xbe); /*MOVL $fetchdat,%esi*/ +#endif + addquad(param); +} +static __inline void +load_param_2_reg_64(int reg) +{ + if (reg & 8) { +#if _WIN64 + addbyte(0x4c); /*MOVL EDX,reg*/ + addbyte(0x89); + addbyte(0xc0 | REG_EDX | ((reg & 7) << 3)); +#else + addbyte(0x4c); /*MOVL ESI,reg*/ + addbyte(0x89); + addbyte(0xc0 | REG_ESI | ((reg & 7) << 3)); +#endif + } else { +#if _WIN64 + addbyte(0x48); /*MOVL EDX,reg*/ + addbyte(0x89); + addbyte(0xc0 | REG_EDX | ((reg & 7) << 3)); +#else + addbyte(0x48); /*MOVL ESI,reg*/ + addbyte(0x89); + addbyte(0xc0 | REG_ESI | ((reg & 7) << 3)); +#endif + } +} + +static __inline void +load_param_3_reg_32(int reg) +{ + if (reg & 8) { +#if _WIN64 + addbyte(0x45); /*MOVL R8,reg*/ + addbyte(0x89); + addbyte(0xc0 | ((reg & 7) << 3)); +#else + addbyte(0x44); /*MOV EDX, reg*/ + addbyte(0x89); addbyte(0xc0 | REG_EDX | (reg << 3)); -#else - if (reg & 8) - addbyte(0x44); - addbyte(0x89); /*MOV ESI, EAX*/ - addbyte(0xc0 | REG_ESI | (reg << 3)); #endif -} -static inline void load_param_2_64(codeblock_t *block, uint64_t param) -{ - addbyte(0x48); + } else { #if _WIN64 - addbyte(0xba); /*MOVL $fetchdat,%edx*/ + addbyte(0x41); /*MOVL R8,reg*/ + addbyte(0x89); + addbyte(0xc0 | ((reg & 7) << 3)); #else - addbyte(0xbe); /*MOVL $fetchdat,%esi*/ + addbyte(0x90); + addbyte(0x89); /*MOV EDX, reg*/ + addbyte(0xc0 | REG_EDX | (reg << 3)); #endif - addquad(param); + } } -static inline void load_param_2_reg_64(int reg) +static __inline void +load_param_3_reg_64(int reg) { - if (reg & 8) - { + if (reg & 8) { #if _WIN64 - addbyte(0x4c); /*MOVL EDX,reg*/ - addbyte(0x89); - addbyte(0xc0 | REG_EDX | ((reg & 7) << 3)); + addbyte(0x4d); /*MOVL R8,reg*/ + addbyte(0x89); + addbyte(0xc0 | ((reg & 7) << 3)); #else - addbyte(0x4c); /*MOVL ESI,reg*/ - addbyte(0x89); - addbyte(0xc0 | REG_ESI | ((reg & 7) << 3)); + addbyte(0x4c); /*MOVL EDX,reg*/ + addbyte(0x89); + addbyte(0xc0 | REG_EDX | ((reg & 7) << 3)); #endif - } - else - { + } else { #if _WIN64 - addbyte(0x48); /*MOVL EDX,reg*/ - addbyte(0x89); - addbyte(0xc0 | REG_EDX | ((reg & 7) << 3)); + addbyte(0x49); /*MOVL R8,reg*/ + addbyte(0x89); + addbyte(0xc0 | ((reg & 7) << 3)); #else - addbyte(0x48); /*MOVL ESI,reg*/ - addbyte(0x89); - addbyte(0xc0 | REG_ESI | ((reg & 7) << 3)); + addbyte(0x48); /*MOVL EDX,reg*/ + addbyte(0x89); + addbyte(0xc0 | REG_EDX | ((reg & 7) << 3)); #endif + } +} + +static __inline void +CALL_FUNC(uintptr_t func) +{ + codegen_reg_loaded[0] = codegen_reg_loaded[1] = codegen_reg_loaded[2] = codegen_reg_loaded[3] = 0; + codegen_reg_loaded[4] = codegen_reg_loaded[5] = codegen_reg_loaded[6] = codegen_reg_loaded[7] = 0; + + addbyte(0x48); /*MOV RAX, func*/ + addbyte(0xb8); + addquad(func); + addbyte(0xff); /*CALL RAX*/ + addbyte(0xd0); +} + +static __inline void +RELEASE_REG(UNUSED(int host_reg)) +{ + // +} + +static __inline int +LOAD_REG_B(int reg) +{ + int host_reg = reg & 3; + + if (!codegen_reg_loaded[reg & 3]) { + addbyte(0x44); /*MOVZX W[reg],host_reg*/ + addbyte(0x8b); + addbyte(0x45 | (host_reg << 3)); + addbyte(cpu_state_offset(regs[host_reg & 3].b)); + } + + codegen_reg_loaded[reg & 3] = 1; + + if (reg & 4) + return host_reg | 0x18; + + return host_reg | 8; +} +static __inline int +LOAD_REG_W(int reg) +{ + int host_reg = reg; + + if (!codegen_reg_loaded[reg & 7]) { + addbyte(0x44); /*MOVZX W[reg],host_reg*/ + addbyte(0x8b); + addbyte(0x45 | (host_reg << 3)); + addbyte(cpu_state_offset(regs[reg & 7].w)); + } + + codegen_reg_loaded[reg & 7] = 1; + + return host_reg | 8; +} +static __inline int +LOAD_REG_L(int reg) +{ + int host_reg = reg; + + if (!codegen_reg_loaded[reg & 7]) { + addbyte(0x44); /*MOVZX W[reg],host_reg*/ + addbyte(0x8b); + addbyte(0x45 | (host_reg << 3)); + addbyte(cpu_state_offset(regs[reg & 7].l)); + } + + codegen_reg_loaded[reg & 7] = 1; + + return host_reg | 8; +} + +static __inline int +LOAD_REG_IMM(uint32_t imm) +{ + int host_reg = REG_EBX; + + addbyte(0xb8 | REG_EBX); /*MOVL EBX, imm*/ + addlong(imm); + + return host_reg; +} + +static __inline void +STORE_REG_TARGET_B_RELEASE(int host_reg, int guest_reg) +{ + int dest_reg = LOAD_REG_L(guest_reg & 3) & 7; + + if (guest_reg & 4) { + if (host_reg & 8) { + addbyte(0x66); /*MOV AX, host_reg*/ + addbyte(0x44); + addbyte(0x89); + addbyte(0xc0 | ((host_reg & 3) << 3)); + } else if (host_reg & 3) { + addbyte(0x66); /*MOV AX, host_reg*/ + addbyte(0x89); + addbyte(0xc0 | ((host_reg & 3) << 3)); } -} - -static inline void load_param_3_reg_32(int reg) -{ - if (reg & 8) - { -#if _WIN64 - addbyte(0x45); /*MOVL R8,reg*/ - addbyte(0x89); - addbyte(0xc0 | ((reg & 7) << 3)); -#else - addbyte(0x44); /*MOV EDX, reg*/ - addbyte(0x89); - addbyte(0xc0 | REG_EDX | (reg << 3)); -#endif + if (host_reg & 0x10) { + addbyte(0x66); /*AND AX, 0xff00*/ + addbyte(0x25); + addword(0xff00); + } else { + addbyte(0x66); /*SHL AX, 8*/ + addbyte(0xc1); + addbyte(0xe0); + addbyte(0x08); } - else - { -#if _WIN64 - addbyte(0x41); /*MOVL R8,reg*/ - addbyte(0x89); - addbyte(0xc0 | ((reg & 7) << 3)); -#else - addbyte(0x90); - addbyte(0x89); /*MOV EDX, reg*/ - addbyte(0xc0 | REG_EDX | (reg << 3)); -#endif - } -} -static inline void load_param_3_reg_64(int reg) -{ - if (reg & 8) - { -#if _WIN64 - addbyte(0x4d); /*MOVL R8,reg*/ - addbyte(0x89); - addbyte(0xc0 | ((reg & 7) << 3)); -#else - addbyte(0x4c); /*MOVL EDX,reg*/ - addbyte(0x89); - addbyte(0xc0 | REG_EDX | ((reg & 7) << 3)); -#endif - } - else - { -#if _WIN64 - addbyte(0x49); /*MOVL R8,reg*/ - addbyte(0x89); - addbyte(0xc0 | ((reg & 7) << 3)); -#else - addbyte(0x48); /*MOVL EDX,reg*/ - addbyte(0x89); - addbyte(0xc0 | REG_EDX | ((reg & 7) << 3)); -#endif - } -} - -static inline void CALL_FUNC(uintptr_t func) -{ - codegen_reg_loaded[0] = codegen_reg_loaded[1] = codegen_reg_loaded[2] = codegen_reg_loaded[3] = 0; - codegen_reg_loaded[4] = codegen_reg_loaded[5] = codegen_reg_loaded[6] = codegen_reg_loaded[7] = 0; - - addbyte(0x48); /*MOV RAX, func*/ - addbyte(0xb8); - addquad(func); - addbyte(0xff); /*CALL RAX*/ - addbyte(0xd0); -} - -static inline void RELEASE_REG(int host_reg) -{ -} - -static inline int LOAD_REG_B(int reg) -{ - int host_reg = reg & 3; - - if (!codegen_reg_loaded[reg & 3]) - { - addbyte(0x44); /*MOVZX W[reg],host_reg*/ - addbyte(0x8b); - addbyte(0x45 | (host_reg << 3)); - addbyte(cpu_state_offset(regs[host_reg & 3].b)); - } - - codegen_reg_loaded[reg & 3] = 1; - - if (reg & 4) - return host_reg | 0x18; - - return host_reg | 8; -} -static inline int LOAD_REG_W(int reg) -{ - int host_reg = reg; - - if (!codegen_reg_loaded[reg & 7]) - { - addbyte(0x44); /*MOVZX W[reg],host_reg*/ - addbyte(0x8b); - addbyte(0x45 | (host_reg << 3)); - addbyte(cpu_state_offset(regs[reg & 7].w)); - } - - codegen_reg_loaded[reg & 7] = 1; - - return host_reg | 8; -} -static inline int LOAD_REG_L(int reg) -{ - int host_reg = reg; - - if (!codegen_reg_loaded[reg & 7]) - { - addbyte(0x44); /*MOVZX W[reg],host_reg*/ - addbyte(0x8b); - addbyte(0x45 | (host_reg << 3)); - addbyte(cpu_state_offset(regs[reg & 7].l)); - } - - codegen_reg_loaded[reg & 7] = 1; - - return host_reg | 8; -} - -static inline int LOAD_REG_IMM(uint32_t imm) -{ - int host_reg = REG_EBX; - - addbyte(0xb8 | REG_EBX); /*MOVL EBX, imm*/ - addlong(imm); - - return host_reg; -} - -static inline void STORE_REG_TARGET_B_RELEASE(int host_reg, int guest_reg) -{ - int dest_reg = LOAD_REG_L(guest_reg & 3) & 7; - - if (guest_reg & 4) - { - if (host_reg & 8) - { - addbyte(0x66); /*MOV AX, host_reg*/ - addbyte(0x44); - addbyte(0x89); - addbyte(0xc0 | ((host_reg & 3) << 3)); - } - else if (host_reg & 3) - { - addbyte(0x66); /*MOV AX, host_reg*/ - addbyte(0x89); - addbyte(0xc0 | ((host_reg & 3) << 3)); - } - if (host_reg & 0x10) - { - addbyte(0x66); /*AND AX, 0xff00*/ - addbyte(0x25); - addword(0xff00); - } - else - { - addbyte(0x66); /*SHL AX, 8*/ - addbyte(0xc1); - addbyte(0xe0); - addbyte(0x08); - } - addbyte(0x66); /*AND dest_reg, 0x00ff*/ - addbyte(0x41); - addbyte(0x81); - addbyte(0xe0 | dest_reg); - addword(0x00ff); - addbyte(0x66); /*OR dest_reg, AX*/ - addbyte(0x41); - addbyte(0x09); - addbyte(0xc0 | dest_reg); - addbyte(0x66); /*MOVW regs[guest_reg].w, dest_reg*/ + addbyte(0x66); /*AND dest_reg, 0x00ff*/ + addbyte(0x41); + addbyte(0x81); + addbyte(0xe0 | dest_reg); + addword(0x00ff); + addbyte(0x66); /*OR dest_reg, AX*/ + addbyte(0x41); + addbyte(0x09); + addbyte(0xc0 | dest_reg); + addbyte(0x66); /*MOVW regs[guest_reg].w, dest_reg*/ + addbyte(0x44); + addbyte(0x89); + addbyte(0x45 | (dest_reg << 3)); + addbyte(cpu_state_offset(regs[guest_reg & 3].w)); + } else { + if (host_reg & 8) { + if (host_reg & 0x10) { + addbyte(0x66); /*MOV AX, host_reg*/ addbyte(0x44); addbyte(0x89); - addbyte(0x45 | (dest_reg << 3)); - addbyte(cpu_state_offset(regs[guest_reg & 3].w)); - } - else - { - if (host_reg & 8) - { - if (host_reg & 0x10) - { - addbyte(0x66); /*MOV AX, host_reg*/ - addbyte(0x44); - addbyte(0x89); - addbyte(0xc0 | ((host_reg & 3) << 3)); - addbyte(0x88); /*MOV AL, AH*/ - addbyte(0xe0); - addbyte(0x41); /*MOV dest_reg, AL*/ - addbyte(0x88); - addbyte(0xc0 | (dest_reg & 7)); - addbyte(0x88); /*MOVB regs[reg].b, AH*/ - addbyte(0x65); - addbyte(cpu_state_offset(regs[guest_reg & 3].b)); - } - else - { - addbyte(0x45); /*MOVB dest_reg, host_reg*/ - addbyte(0x88); - addbyte(0xc0 | (dest_reg & 7) | ((host_reg & 7) << 3)); - addbyte(0x44); /*MOVB regs[guest_reg].b, host_reg*/ - addbyte(0x88); - addbyte(0x45 | ((host_reg & 3) << 3)); - addbyte(cpu_state_offset(regs[guest_reg & 3].b)); - } - } - else - { - if (host_reg & 0x10) - { - addbyte(0xc1); /*SHR host_reg, 8*/ - addbyte(0xe8 | (host_reg & 7)); - addbyte(8); - } - addbyte(0x41); /*MOVB dest_reg, host_reg*/ - addbyte(0x88); - addbyte(0xc0 | (dest_reg & 7) | ((host_reg & 7) << 3)); - addbyte(0x88); /*MOVB regs[guest_reg].b, host_reg*/ - addbyte(0x45 | ((host_reg & 3) << 3)); - addbyte(cpu_state_offset(regs[guest_reg & 3].b)); - } - } -} -static inline void STORE_REG_TARGET_W_RELEASE(int host_reg, int guest_reg) -{ - int dest_reg = LOAD_REG_L(guest_reg & 7) & 7; - - if (host_reg & 8) - { - addbyte(0x66); /*MOVW guest_reg, host_reg*/ - addbyte(0x45); - addbyte(0x89); - addbyte(0xc0 | dest_reg | ((host_reg & 7) << 3)); - addbyte(0x66); /*MOVW regs[guest_reg].w, host_reg*/ - addbyte(0x44); - addbyte(0x89); - addbyte(0x45 | ((host_reg & 7) << 3)); - addbyte(cpu_state_offset(regs[guest_reg & 7].w)); - } - else - { - addbyte(0x66); /*MOVW guest_reg, host_reg*/ - addbyte(0x41); - addbyte(0x89); - addbyte(0xc0 | dest_reg | (host_reg << 3)); - addbyte(0x66); /*MOVW regs[guest_reg].w, host_reg*/ - addbyte(0x89); - addbyte(0x45 | (host_reg << 3)); - addbyte(cpu_state_offset(regs[guest_reg & 7].w)); - } -} -static inline void STORE_REG_TARGET_L_RELEASE(int host_reg, int guest_reg) -{ - if (host_reg & 8) - { - addbyte(0x45); /*MOVL guest_reg, host_reg*/ - addbyte(0x89); - addbyte(0xc0 | guest_reg | (host_reg << 3)); - addbyte(0x44); /*MOVL regs[guest_reg].l, host_reg*/ - addbyte(0x89); - addbyte(0x45 | (host_reg << 3)); - addbyte(cpu_state_offset(regs[guest_reg & 7].l)); - } - else - { - addbyte(0x41); /*MOVL guest_reg, host_reg*/ - addbyte(0x89); - addbyte(0xc0 | guest_reg | (host_reg << 3)); - addbyte(0x89); /*MOVL regs[guest_reg].l, host_reg*/ - addbyte(0x45 | (host_reg << 3)); - addbyte(cpu_state_offset(regs[guest_reg & 7].l)); - } -} - -static inline void STORE_REG_B_RELEASE(int host_reg) -{ - if (host_reg & 0x10) - { - addbyte(0x66); /*MOVW [reg],host_reg*/ - addbyte(0x44); - addbyte(0x89); - addbyte(0x45 | ((host_reg & 7) << 3)); - addbyte(cpu_state_offset(regs[host_reg & 7].w)); - } - else - { - addbyte(0x44); /*MOVB [reg],host_reg*/ + addbyte(0xc0 | ((host_reg & 3) << 3)); + addbyte(0x88); /*MOV AL, AH*/ + addbyte(0xe0); + addbyte(0x41); /*MOV dest_reg, AL*/ addbyte(0x88); - addbyte(0x45 | ((host_reg & 7) << 3)); - addbyte(cpu_state_offset(regs[host_reg & 7].b)); + addbyte(0xc0 | (dest_reg & 7)); + addbyte(0x88); /*MOVB regs[reg].b, AH*/ + addbyte(0x65); + addbyte(cpu_state_offset(regs[guest_reg & 3].b)); + } else { + addbyte(0x45); /*MOVB dest_reg, host_reg*/ + addbyte(0x88); + addbyte(0xc0 | (dest_reg & 7) | ((host_reg & 7) << 3)); + addbyte(0x44); /*MOVB regs[guest_reg].b, host_reg*/ + addbyte(0x88); + addbyte(0x45 | ((host_reg & 3) << 3)); + addbyte(cpu_state_offset(regs[guest_reg & 3].b)); + } + } else { + if (host_reg & 0x10) { + addbyte(0xc1); /*SHR host_reg, 8*/ + addbyte(0xe8 | (host_reg & 7)); + addbyte(8); + } + addbyte(0x41); /*MOVB dest_reg, host_reg*/ + addbyte(0x88); + addbyte(0xc0 | (dest_reg & 7) | ((host_reg & 7) << 3)); + addbyte(0x88); /*MOVB regs[guest_reg].b, host_reg*/ + addbyte(0x45 | ((host_reg & 3) << 3)); + addbyte(cpu_state_offset(regs[guest_reg & 3].b)); } + } } -static inline void STORE_REG_W_RELEASE(int host_reg) +static __inline void +STORE_REG_TARGET_W_RELEASE(int host_reg, int guest_reg) { + int dest_reg = LOAD_REG_L(guest_reg & 7) & 7; + + if (host_reg & 8) { + addbyte(0x66); /*MOVW guest_reg, host_reg*/ + addbyte(0x45); + addbyte(0x89); + addbyte(0xc0 | dest_reg | ((host_reg & 7) << 3)); + addbyte(0x66); /*MOVW regs[guest_reg].w, host_reg*/ + addbyte(0x44); + addbyte(0x89); + addbyte(0x45 | ((host_reg & 7) << 3)); + addbyte(cpu_state_offset(regs[guest_reg & 7].w)); + } else { + addbyte(0x66); /*MOVW guest_reg, host_reg*/ + addbyte(0x41); + addbyte(0x89); + addbyte(0xc0 | dest_reg | (host_reg << 3)); + addbyte(0x66); /*MOVW regs[guest_reg].w, host_reg*/ + addbyte(0x89); + addbyte(0x45 | (host_reg << 3)); + addbyte(cpu_state_offset(regs[guest_reg & 7].w)); + } +} +static __inline void +STORE_REG_TARGET_L_RELEASE(int host_reg, int guest_reg) +{ + if (host_reg & 8) { + addbyte(0x45); /*MOVL guest_reg, host_reg*/ + addbyte(0x89); + addbyte(0xc0 | guest_reg | (host_reg << 3)); + addbyte(0x44); /*MOVL regs[guest_reg].l, host_reg*/ + addbyte(0x89); + addbyte(0x45 | (host_reg << 3)); + addbyte(cpu_state_offset(regs[guest_reg & 7].l)); + } else { + addbyte(0x41); /*MOVL guest_reg, host_reg*/ + addbyte(0x89); + addbyte(0xc0 | guest_reg | (host_reg << 3)); + addbyte(0x89); /*MOVL regs[guest_reg].l, host_reg*/ + addbyte(0x45 | (host_reg << 3)); + addbyte(cpu_state_offset(regs[guest_reg & 7].l)); + } +} + +static __inline void +STORE_REG_B_RELEASE(int host_reg) +{ + if (host_reg & 0x10) { addbyte(0x66); /*MOVW [reg],host_reg*/ addbyte(0x44); addbyte(0x89); addbyte(0x45 | ((host_reg & 7) << 3)); addbyte(cpu_state_offset(regs[host_reg & 7].w)); -} -static inline void STORE_REG_L_RELEASE(int host_reg) -{ - addbyte(0x44); /*MOVL [reg],host_reg*/ - addbyte(0x89); + } else { + addbyte(0x44); /*MOVB [reg],host_reg*/ + addbyte(0x88); addbyte(0x45 | ((host_reg & 7) << 3)); - addbyte(cpu_state_offset(regs[host_reg & 7].l)); + addbyte(cpu_state_offset(regs[host_reg & 7].b)); + } +} +static __inline void +STORE_REG_W_RELEASE(int host_reg) +{ + addbyte(0x66); /*MOVW [reg],host_reg*/ + addbyte(0x44); + addbyte(0x89); + addbyte(0x45 | ((host_reg & 7) << 3)); + addbyte(cpu_state_offset(regs[host_reg & 7].w)); +} +static __inline void +STORE_REG_L_RELEASE(int host_reg) +{ + addbyte(0x44); /*MOVL [reg],host_reg*/ + addbyte(0x89); + addbyte(0x45 | ((host_reg & 7) << 3)); + addbyte(cpu_state_offset(regs[host_reg & 7].l)); } -static inline void STORE_IMM_REG_B(int reg, uint8_t val) +static __inline void +STORE_IMM_REG_B(int reg, uint8_t val) { - if (reg & 4) - { - int host_reg = LOAD_REG_W(reg & 3) & 7; - addbyte(0x66); /*AND host_reg, 0x00ff*/ - addbyte(0x41); - addbyte(0x81); - addbyte(0xe0 | host_reg); - addword(0x00ff); - addbyte(0x66); /*OR host_reg, val << 8*/ - addbyte(0x41); - addbyte(0x81); - addbyte(0xc8 | host_reg); - addword(val << 8); - addbyte(0x66); /*MOVW host_reg, regs[host_reg].w*/ - addbyte(0x44); - addbyte(0x89); - addbyte(0x45 | (host_reg << 3)); - addbyte(cpu_state_offset(regs[reg & 3].w)); - } - else - { - addbyte(0x41); /*MOVB reg, imm*/ - addbyte(0xb0 | reg); - addbyte(val); - addbyte(0x44); /*MOVB reg, regs[reg].b*/ - addbyte(0x88); - addbyte(0x45 | (reg << 3)); - addbyte(cpu_state_offset(regs[reg & 7].b)); - } -} -static inline void STORE_IMM_REG_W(int reg, uint16_t val) -{ - addbyte(0x66); /*MOVW reg, imm*/ + if (reg & 4) { + int host_reg = LOAD_REG_W(reg & 3) & 7; + addbyte(0x66); /*AND host_reg, 0x00ff*/ addbyte(0x41); - addbyte(0xb8 | reg); - addword(val); - addbyte(0x66); /*MOVW reg, regs[reg].w*/ + addbyte(0x81); + addbyte(0xe0 | host_reg); + addword(0x00ff); + addbyte(0x66); /*OR host_reg, val << 8*/ + addbyte(0x41); + addbyte(0x81); + addbyte(0xc8 | host_reg); + addword(val << 8); + addbyte(0x66); /*MOVW host_reg, regs[host_reg].w*/ addbyte(0x44); addbyte(0x89); + addbyte(0x45 | (host_reg << 3)); + addbyte(cpu_state_offset(regs[reg & 3].w)); + } else { + addbyte(0x41); /*MOVB reg, imm*/ + addbyte(0xb0 | reg); + addbyte(val); + addbyte(0x44); /*MOVB reg, regs[reg].b*/ + addbyte(0x88); addbyte(0x45 | (reg << 3)); - addbyte(cpu_state_offset(regs[reg & 7].w)); + addbyte(cpu_state_offset(regs[reg & 7].b)); + } } -static inline void STORE_IMM_REG_L(int reg, uint32_t val) +static __inline void +STORE_IMM_REG_W(int reg, uint16_t val) { - addbyte(0x41); /*MOVL reg, imm*/ - addbyte(0xb8 | reg); + addbyte(0x66); /*MOVW reg, imm*/ + addbyte(0x41); + addbyte(0xb8 | reg); + addword(val); + addbyte(0x66); /*MOVW reg, regs[reg].w*/ + addbyte(0x44); + addbyte(0x89); + addbyte(0x45 | (reg << 3)); + addbyte(cpu_state_offset(regs[reg & 7].w)); +} +static __inline void +STORE_IMM_REG_L(int reg, uint32_t val) +{ + addbyte(0x41); /*MOVL reg, imm*/ + addbyte(0xb8 | reg); + addlong(val); + addbyte(0x44); /*MOVL reg, regs[reg].l*/ + addbyte(0x89); + addbyte(0x45 | (reg << 3)); + addbyte(cpu_state_offset(regs[reg & 7].l)); +} + +static __inline void +STORE_IMM_ADDR_L(uintptr_t addr, uint32_t val) +{ + if (addr >= (uintptr_t) &cpu_state && addr < ((uintptr_t) &cpu_state) + 0x100) { + addbyte(0xC7); /*MOVL [addr],val*/ + addbyte(0x45); + addbyte(addr - (uintptr_t) &cpu_state - 128); addlong(val); - addbyte(0x44); /*MOVL reg, regs[reg].l*/ - addbyte(0x89); - addbyte(0x45 | (reg << 3)); - addbyte(cpu_state_offset(regs[reg & 7].l)); + } else if (addr < 0x100000000) { + addbyte(0xC7); /*MOVL [addr],val*/ + addbyte(0x04); + addbyte(0x25); + addlong(addr); + addlong(val); + } else { + addbyte(0x48); /*MOV ESI, &addr*/ + addbyte(0xb8 | REG_ESI); + addquad(addr); + addbyte(0xc7); /*MOVL [ESI], val*/ + addbyte(0x00 | REG_ESI); + addlong(val); + } } -static inline void STORE_IMM_ADDR_L(uintptr_t addr, uint32_t val) +static x86seg * +FETCH_EA_16(x86seg *op_ea_seg, uint32_t fetchdat, int op_ssegs, uint32_t *op_pc) { - if (addr >= (uintptr_t)&cpu_state && addr < ((uintptr_t)&cpu_state)+0x100) - { - addbyte(0xC7); /*MOVL [addr],val*/ - addbyte(0x45); - addbyte(addr - (uintptr_t)&cpu_state - 128); - addlong(val); + int mod = (fetchdat >> 6) & 3; + int rm = fetchdat & 7; + + if (!mod && rm == 6) { + addbyte(0xb8); /*MOVL EAX, imm*/ + addlong((fetchdat >> 8) & 0xffff); + (*op_pc) += 2; + } else { + int base_reg = 0; + int index_reg = 0; + + switch (rm) { + case 0: + case 1: + case 7: + base_reg = LOAD_REG_W(REG_BX); + break; + case 2: + case 3: + case 6: + base_reg = LOAD_REG_W(REG_BP); + break; + case 4: + base_reg = LOAD_REG_W(REG_SI); + break; + case 5: + base_reg = LOAD_REG_W(REG_DI); + break; } - else if (addr < 0x100000000) - { - addbyte(0xC7); /*MOVL [addr],val*/ - addbyte(0x04); - addbyte(0x25); - addlong(addr); - addlong(val); + if (!(rm & 4)) { + if (rm & 1) + index_reg = LOAD_REG_W(REG_DI); + else + index_reg = LOAD_REG_W(REG_SI); } - else - { - addbyte(0x48); /*MOV ESI, &addr*/ - addbyte(0xb8 | REG_ESI); - addquad(addr); - addbyte(0xc7); /*MOVL [ESI], val*/ - addbyte(0x00 | REG_ESI); - addlong(val); - } -} + base_reg &= 7; + index_reg &= 7; - - - -static x86seg *FETCH_EA_16(x86seg *op_ea_seg, uint32_t fetchdat, int op_ssegs, uint32_t *op_pc) -{ - int mod = (fetchdat >> 6) & 3; - int rm = fetchdat & 7; - - if (!mod && rm == 6) - { - addbyte(0xb8); /*MOVL EAX, imm*/ - addlong((fetchdat >> 8) & 0xffff); - (*op_pc) += 2; - } - else - { - int base_reg = 0, index_reg = 0; - - switch (rm) - { - case 0: case 1: case 7: - base_reg = LOAD_REG_W(REG_BX); - break; - case 2: case 3: case 6: - base_reg = LOAD_REG_W(REG_BP); - break; - case 4: - base_reg = LOAD_REG_W(REG_SI); - break; - case 5: - base_reg = LOAD_REG_W(REG_DI); - break; + switch (mod) { + case 0: + if (rm & 4) { + addbyte(0x41); /*MOVZX EAX, base_reg*/ + addbyte(0x0f); + addbyte(0xb7); + addbyte(0xc0 | base_reg); + } else { + addbyte(0x67); /*LEA EAX, base_reg+index_reg*/ + addbyte(0x43); + addbyte(0x8d); + if (base_reg == 5) { + addbyte(0x44); + addbyte(base_reg | (index_reg << 3)); + addbyte(0); + } else { + addbyte(0x04); + addbyte(base_reg | (index_reg << 3)); + } } - if (!(rm & 4)) - { - if (rm & 1) - index_reg = LOAD_REG_W(REG_DI); - else - index_reg = LOAD_REG_W(REG_SI); + break; + case 1: + if (rm & 4) { + addbyte(0x67); /*LEA EAX, base_reg+imm8*/ + addbyte(0x41); + addbyte(0x8d); + addbyte(0x40 | base_reg); + addbyte((fetchdat >> 8) & 0xff); + } else { + addbyte(0x67); /*LEA EAX, base_reg+index_reg+imm8*/ + addbyte(0x43); + addbyte(0x8d); + addbyte(0x44); + addbyte(base_reg | (index_reg << 3)); + addbyte((fetchdat >> 8) & 0xff); } - base_reg &= 7; - index_reg &= 7; - - switch (mod) - { - case 0: - if (rm & 4) - { - addbyte(0x41); /*MOVZX EAX, base_reg*/ - addbyte(0x0f); - addbyte(0xb7); - addbyte(0xc0 | base_reg); - } - else - { - addbyte(0x67); /*LEA EAX, base_reg+index_reg*/ - addbyte(0x43); - addbyte(0x8d); - if (base_reg == 5) - { - addbyte(0x44); - addbyte(base_reg | (index_reg << 3)); - addbyte(0); - } - else - { - addbyte(0x04); - addbyte(base_reg | (index_reg << 3)); - } - } - break; - case 1: - if (rm & 4) - { - addbyte(0x67); /*LEA EAX, base_reg+imm8*/ - addbyte(0x41); - addbyte(0x8d); - addbyte(0x40 | base_reg); - addbyte((fetchdat >> 8) & 0xff); - } - else - { - addbyte(0x67); /*LEA EAX, base_reg+index_reg+imm8*/ - addbyte(0x43); - addbyte(0x8d); - addbyte(0x44); - addbyte(base_reg | (index_reg << 3)); - addbyte((fetchdat >> 8) & 0xff); - } - (*op_pc)++; - break; - case 2: - if (rm & 4) - { - addbyte(0x67); /*LEA EAX, base_reg+imm8*/ - addbyte(0x41); - addbyte(0x8d); - addbyte(0x80 | base_reg); - addlong((fetchdat >> 8) & 0xffff); - } - else - { - addbyte(0x67); /*LEA EAX, base_reg+index_reg+imm16*/ - addbyte(0x43); - addbyte(0x8d); - addbyte(0x84); - addbyte(base_reg | (index_reg << 3)); - addlong((fetchdat >> 8) & 0xffff); - } - (*op_pc) += 2; - break; - - } - if (mod || !(rm & 4)) - { - addbyte(0x25); /*ANDL $0xffff, %eax*/ - addlong(0xffff); - } - - if (mod1seg[rm] == &ss && !op_ssegs) - op_ea_seg = &cpu_state.seg_ss; - } - return op_ea_seg; -} -static x86seg *FETCH_EA_32(x86seg *op_ea_seg, uint32_t fetchdat, int op_ssegs, uint32_t *op_pc, int stack_offset) -{ - int mod = (fetchdat >> 6) & 3; - int rm = fetchdat & 7; - uint32_t new_eaaddr; - - if (rm == 4) - { - uint8_t sib = fetchdat >> 8; - int base_reg = -1, index_reg = -1; - (*op_pc)++; - - if (mod || (sib & 7) != 5) - base_reg = LOAD_REG_L(sib & 7) & 7; - - if (((sib >> 3) & 7) != 4) - index_reg = LOAD_REG_L((sib >> 3) & 7) & 7; - - if (index_reg == -1) - { - switch (mod) - { - case 0: - if ((sib & 7) == 5) - { - new_eaaddr = fastreadl(cs + (*op_pc) + 1); - addbyte(0xb8); /*MOV EAX, imm32*/ - addlong(new_eaaddr); - (*op_pc) += 4; - } - else - { - addbyte(0x44); /*MOV EAX, base_reg*/ - addbyte(0x89); - addbyte(0xc0 | (base_reg << 3)); - } - break; - case 1: - addbyte(0x67); /*LEA EAX, imm8+base_reg*/ - addbyte(0x41); - addbyte(0x8d); - if (base_reg == 4) - { - addbyte(0x44); - addbyte(0x24); - } - else - { - addbyte(0x40 | base_reg); - } - addbyte((fetchdat >> 16) & 0xff); - (*op_pc)++; - break; - case 2: - new_eaaddr = fastreadl(cs + (*op_pc) + 1); - addbyte(0x67); /*LEA EAX, imm32+base_reg*/ - addbyte(0x41); - addbyte(0x8d); - if (base_reg == 4) - { - addbyte(0x84); - addbyte(0x24); - } - else - { - addbyte(0x80 | base_reg); - } - addlong(new_eaaddr); - (*op_pc) += 4; - break; - } + break; + case 2: + if (rm & 4) { + addbyte(0x67); /*LEA EAX, base_reg+imm8*/ + addbyte(0x41); + addbyte(0x8d); + addbyte(0x80 | base_reg); + addlong((fetchdat >> 8) & 0xffff); + } else { + addbyte(0x67); /*LEA EAX, base_reg+index_reg+imm16*/ + addbyte(0x43); + addbyte(0x8d); + addbyte(0x84); + addbyte(base_reg | (index_reg << 3)); + addlong((fetchdat >> 8) & 0xffff); } - else - { - switch (mod) - { - case 0: - if ((sib & 7) == 5) - { - new_eaaddr = fastreadl(cs + (*op_pc) + 1); - if (sib >> 6) - { - addbyte(0x67); /*LEA EAX, imm32+index_reg*scale*/ - addbyte(0x42); - addbyte(0x8d); - addbyte(0x04); - addbyte(0x05 | (sib & 0xc0) | (index_reg << 3)); - addlong(new_eaaddr); - } - else - { - addbyte(0x67); /*LEA EAX, imm32+index_reg*/ - addbyte(0x41); - addbyte(0x8d); - addbyte(0x80 | index_reg); - addlong(new_eaaddr); - } - (*op_pc) += 4; - } - else - { - addbyte(0x67); /*LEA EAX, base_reg+index_reg*scale*/ - addbyte(0x43); - addbyte(0x8d); - if (base_reg == 5) - { - addbyte(0x44); - addbyte(base_reg | (index_reg << 3) | (sib & 0xc0)); - addbyte(0); - } - else - { - addbyte(0x04); - addbyte(base_reg | (index_reg << 3) | (sib & 0xc0)); - } - } - break; - case 1: - addbyte(0x67); /*LEA EAX, imm8+base_reg+index_reg*scale*/ - addbyte(0x43); - addbyte(0x8d); - addbyte(0x44); - addbyte(base_reg | (index_reg << 3) | (sib & 0xc0)); - addbyte((fetchdat >> 16) & 0xff); - (*op_pc)++; - break; - case 2: - new_eaaddr = fastreadl(cs + (*op_pc) + 1); - addbyte(0x67); /*LEA EAX, imm32+base_reg+index_reg*scale*/ - addbyte(0x43); - addbyte(0x8d); - addbyte(0x84); - addbyte(base_reg | (index_reg << 3) | (sib & 0xc0)); - addlong(new_eaaddr); - (*op_pc) += 4; - break; - } - } - if (stack_offset && (sib & 7) == 4 && (mod || (sib & 7) != 5)) /*ESP*/ - { - addbyte(0x05); - addlong(stack_offset); - } - if (((sib & 7) == 4 || (mod && (sib & 7) == 5)) && !op_ssegs) - op_ea_seg = &cpu_state.seg_ss; + (*op_pc) += 2; + break; + } + if (mod || !(rm & 4)) { + addbyte(0x25); /*ANDL $0xffff, %eax*/ + addlong(0xffff); } - else - { - int base_reg; - if (!mod && rm == 5) - { + if (mod1seg[rm] == &ss && !op_ssegs) + op_ea_seg = &cpu_state.seg_ss; + } + return op_ea_seg; +} +static x86seg * +FETCH_EA_32(x86seg *op_ea_seg, uint32_t fetchdat, int op_ssegs, uint32_t *op_pc, int stack_offset) +{ + int mod = (fetchdat >> 6) & 3; + int rm = fetchdat & 7; + uint32_t new_eaaddr; + + if (rm == 4) { + uint8_t sib = fetchdat >> 8; + int base_reg = -1; + int index_reg = -1; + + (*op_pc)++; + + if (mod || (sib & 7) != 5) + base_reg = LOAD_REG_L(sib & 7) & 7; + + if (((sib >> 3) & 7) != 4) + index_reg = LOAD_REG_L((sib >> 3) & 7) & 7; + + if (index_reg == -1) { + switch (mod) { + case 0: + if ((sib & 7) == 5) { new_eaaddr = fastreadl(cs + (*op_pc) + 1); - addbyte(0xb8); /*MOVL EAX, new_eaaddr*/ + addbyte(0xb8); /*MOV EAX, imm32*/ addlong(new_eaaddr); (*op_pc) += 4; - return op_ea_seg; - } - base_reg = LOAD_REG_L(rm) & 7; - if (mod) - { - if (rm == 5 && !op_ssegs) - op_ea_seg = &cpu_state.seg_ss; - if (mod == 1) - { - addbyte(0x67); /*LEA EAX, base_reg+imm8*/ - addbyte(0x41); - addbyte(0x8d); - addbyte(0x40 | base_reg); - addbyte((fetchdat >> 8) & 0xff); - (*op_pc)++; - } - else - { - new_eaaddr = fastreadl(cs + (*op_pc) + 1); - addbyte(0x67); /*LEA EAX, base_reg+imm32*/ - addbyte(0x41); - addbyte(0x8d); - addbyte(0x80 | base_reg); - addlong(new_eaaddr); - (*op_pc) += 4; - } - } - else - { + } else { addbyte(0x44); /*MOV EAX, base_reg*/ addbyte(0x89); addbyte(0xc0 | (base_reg << 3)); - } + } + break; + case 1: + addbyte(0x67); /*LEA EAX, imm8+base_reg*/ + addbyte(0x41); + addbyte(0x8d); + if (base_reg == 4) { + addbyte(0x44); + addbyte(0x24); + } else { + addbyte(0x40 | base_reg); + } + addbyte((fetchdat >> 16) & 0xff); + (*op_pc)++; + break; + case 2: + new_eaaddr = fastreadl(cs + (*op_pc) + 1); + addbyte(0x67); /*LEA EAX, imm32+base_reg*/ + addbyte(0x41); + addbyte(0x8d); + if (base_reg == 4) { + addbyte(0x84); + addbyte(0x24); + } else { + addbyte(0x80 | base_reg); + } + addlong(new_eaaddr); + (*op_pc) += 4; + break; + } + } else { + switch (mod) { + case 0: + if ((sib & 7) == 5) { + new_eaaddr = fastreadl(cs + (*op_pc) + 1); + if (sib >> 6) { + addbyte(0x67); /*LEA EAX, imm32+index_reg*scale*/ + addbyte(0x42); + addbyte(0x8d); + addbyte(0x04); + addbyte(0x05 | (sib & 0xc0) | (index_reg << 3)); + addlong(new_eaaddr); + } else { + addbyte(0x67); /*LEA EAX, imm32+index_reg*/ + addbyte(0x41); + addbyte(0x8d); + addbyte(0x80 | index_reg); + addlong(new_eaaddr); + } + (*op_pc) += 4; + } else { + addbyte(0x67); /*LEA EAX, base_reg+index_reg*scale*/ + addbyte(0x43); + addbyte(0x8d); + if (base_reg == 5) { + addbyte(0x44); + addbyte(base_reg | (index_reg << 3) | (sib & 0xc0)); + addbyte(0); + } else { + addbyte(0x04); + addbyte(base_reg | (index_reg << 3) | (sib & 0xc0)); + } + } + break; + case 1: + addbyte(0x67); /*LEA EAX, imm8+base_reg+index_reg*scale*/ + addbyte(0x43); + addbyte(0x8d); + addbyte(0x44); + addbyte(base_reg | (index_reg << 3) | (sib & 0xc0)); + addbyte((fetchdat >> 16) & 0xff); + (*op_pc)++; + break; + case 2: + new_eaaddr = fastreadl(cs + (*op_pc) + 1); + addbyte(0x67); /*LEA EAX, imm32+base_reg+index_reg*scale*/ + addbyte(0x43); + addbyte(0x8d); + addbyte(0x84); + addbyte(base_reg | (index_reg << 3) | (sib & 0xc0)); + addlong(new_eaaddr); + (*op_pc) += 4; + break; + } } - return op_ea_seg; -} + if (stack_offset && (sib & 7) == 4 && (mod || (sib & 7) != 5)) /*ESP*/ + { + addbyte(0x05); + addlong(stack_offset); + } + if (((sib & 7) == 4 || (mod && (sib & 7) == 5)) && !op_ssegs) + op_ea_seg = &cpu_state.seg_ss; + } else { + int base_reg; -static inline x86seg *FETCH_EA(x86seg *op_ea_seg, uint32_t fetchdat, int op_ssegs, uint32_t *op_pc, uint32_t op_32) -{ - if (op_32 & 0x200) - return FETCH_EA_32(op_ea_seg, fetchdat, op_ssegs, op_pc, 0); - return FETCH_EA_16(op_ea_seg, fetchdat, op_ssegs, op_pc); -} - - - -static inline void CHECK_SEG_READ(x86seg *seg) -{ - /*Segments always valid in real/V86 mode*/ - if (!(cr0 & 1) || (cpu_state.eflags & VM_FLAG)) - return; - /*CS and SS must always be valid*/ - if (seg == &cpu_state.seg_cs || seg == &cpu_state.seg_ss) - return; - if (seg->checked) - return; - if (seg == &cpu_state.seg_ds && codegen_flat_ds && !(cpu_cur_status & CPU_STATUS_NOTFLATDS)) - return; - - if (IS_32_ADDR(&seg->base)) - { - addbyte(0x83); /*CMP seg->base, -1*/ - addbyte(0x3c); - addbyte(0x25); - addlong((uint32_t)(uintptr_t)&seg->base); - addbyte(-1); + if (!mod && rm == 5) { + new_eaaddr = fastreadl(cs + (*op_pc) + 1); + addbyte(0xb8); /*MOVL EAX, new_eaaddr*/ + addlong(new_eaaddr); + (*op_pc) += 4; + return op_ea_seg; } - else - { - addbyte(0x48); /*MOV RSI, &addr*/ - addbyte(0xb8 | REG_ESI); - addquad((uint64_t)&seg->base); - addbyte(0x83); /*CMP RSI, -1*/ - addbyte(0xe8 | REG_ESI); - addbyte(0xff); - } - addbyte(0x0f); /*JE GPF_BLOCK_OFFSET*/ - addbyte(0x84); - addlong(BLOCK_GPF_OFFSET - (block_pos + 4)); - - seg->checked = 1; -} -static inline void CHECK_SEG_WRITE(x86seg *seg) -{ - /*Segments always valid in real/V86 mode*/ - if (!(cr0 & 1) || (cpu_state.eflags & VM_FLAG)) - return; - /*CS and SS must always be valid*/ - if (seg == &cpu_state.seg_cs || seg == &cpu_state.seg_ss) - return; - if (seg->checked) - return; - if (seg == &cpu_state.seg_ds && codegen_flat_ds && !(cpu_cur_status & CPU_STATUS_NOTFLATDS)) - return; - - if (IS_32_ADDR(&seg->base)) - { - addbyte(0x83); /*CMP seg->base, -1*/ - addbyte(0x3c); - addbyte(0x25); - addlong((uint32_t)(uintptr_t)&seg->base); - addbyte(-1); - } - else - { - addbyte(0x48); /*MOV RSI, &addr*/ - addbyte(0xb8 | REG_ESI); - addquad((uint64_t)&seg->base); - addbyte(0x83); /*CMP RSI, -1*/ - addbyte(0xe8 | REG_ESI); - addbyte(0xff); - } - addbyte(0x0f); /*JE GPF_BLOCK_OFFSET*/ - addbyte(0x84); - addlong(BLOCK_GPF_OFFSET - (block_pos + 4)); - - seg->checked = 1; -} -static inline void CHECK_SEG_LIMITS(x86seg *seg, int end_offset) -{ - if ((seg == &cpu_state.seg_ds && codegen_flat_ds && !(cpu_cur_status & CPU_STATUS_NOTFLATDS)) || (seg == &cpu_state.seg_ss && codegen_flat_ss && !(cpu_cur_status & CPU_STATUS_NOTFLATSS))) - return; - - if (IS_32_ADDR(&seg->base)) - { - addbyte(0xb8 | REG_ESI); /*MOV ESI, &addr*/ - addlong((uint32_t)(uintptr_t)seg); - } - else - { - addbyte(0x48); /*MOV RSI, &addr*/ - addbyte(0xb8 | REG_ESI); - addquad((uint64_t)seg); - } - addbyte(0x3b); /*CMP EAX, seg->limit_low*/ - addbyte(0x46); - addbyte((uintptr_t)&seg->limit_low - (uintptr_t)seg); - addbyte(0x0f); /*JB BLOCK_GPF_OFFSET*/ - addbyte(0x82); - addlong(BLOCK_GPF_OFFSET - (block_pos + 4)); - if (end_offset) - { - addbyte(0x83); /*ADD EAX, end_offset*/ - addbyte(0xc0); - addbyte(end_offset); - addbyte(0x3b); /*CMP EAX, seg->limit_high*/ - addbyte(0x46); - addbyte((uintptr_t)&seg->limit_high - (uintptr_t)seg); - addbyte(0x0f); /*JNBE BLOCK_GPF_OFFSET*/ - addbyte(0x87); - addlong(BLOCK_GPF_OFFSET - (block_pos + 4)); - addbyte(0x83); /*SUB EAX, end_offset*/ - addbyte(0xe8); - addbyte(end_offset); - } -} - -static inline void MEM_LOAD_ADDR_EA_B(x86seg *seg) -{ - if ((seg == &cpu_state.seg_ds && codegen_flat_ds && !(cpu_cur_status & CPU_STATUS_NOTFLATDS)) || (seg == &cpu_state.seg_ss && codegen_flat_ss && !(cpu_cur_status & CPU_STATUS_NOTFLATSS))) - { - addbyte(0x31); /*XOR ECX, ECX*/ - addbyte(0xc9); - } - else if (IS_32_ADDR(&seg->base)) - { - addbyte(0x8b); /*MOVL ECX, seg->base*/ - addbyte(0x0c); - addbyte(0x25); - addlong((uint32_t)(uintptr_t)&seg->base); - } - else - { - addbyte(0x48); /*MOV RSI, &seg->base*/ - addbyte(0xb8 | REG_ESI); - addquad((uint64_t)&seg->base); - addbyte(0x8b); /*MOV ECX, [RSI]*/ - addbyte(0x0e); - } - addbyte(0x67); /*LEA ESI, (EAX,ECX)*/ - addbyte(0x8d); - addbyte(0x34); - addbyte(0x08); - addbyte(0x89); /*MOV EDI, ESI*/ - addbyte(0xf7); - addbyte(0xc1); /*SHR ESI, 12*/ - addbyte(0xe8 | REG_ESI); - addbyte(12); - if (IS_32_ADDR(readlookup2)) - { - addbyte(0x67); /*MOV RSI, readlookup2[ESI*8]*/ - addbyte(0x48); - addbyte(0x8b); - addbyte(0x34); - addbyte(0xf5); - addlong((uint32_t)(uintptr_t)readlookup2); - } - else - { - addbyte(0x48); /*MOV RDX, readlookup2*/ - addbyte(0xb8 | REG_EDX); - addquad((uint64_t)readlookup2); - addbyte(0x48); /*MOV RSI, [RDX+RSI*8]*/ - addbyte(0x8b); - addbyte(0x34); - addbyte(0xf2); - } - addbyte(0x83); /*CMP ESI, -1*/ - addbyte(0xf8 | REG_ESI); - addbyte(-1); - addbyte(0x74); /*JE slowpath*/ - addbyte(3+2); - addbyte(0x8b); /*MOV AL,[RDI+RSI]*/ - addbyte(0x04); - addbyte(REG_EDI | (REG_ESI << 3)); - addbyte(0xeb); /*JMP done*/ - addbyte(2+2+12+4+6); - /*slowpath:*/ - addbyte(0x01); /*ADD ECX,EAX*/ - addbyte(0xc1); - load_param_1_reg_32(REG_ECX); - call_long((uintptr_t)readmembl); - addbyte(0x80); /*CMP abrt, 0*/ - addbyte(0x7d); - addbyte((uint8_t)cpu_state_offset(abrt)); - addbyte(0); - addbyte(0x0f); /*JNE end*/ - addbyte(0x85); - addlong(BLOCK_EXIT_OFFSET - (block_pos + 4)); - /*done:*/ -} -static inline void MEM_LOAD_ADDR_EA_W(x86seg *seg) -{ - if ((seg == &cpu_state.seg_ds && codegen_flat_ds && !(cpu_cur_status & CPU_STATUS_NOTFLATDS)) || (seg == &cpu_state.seg_ss && codegen_flat_ss && !(cpu_cur_status & CPU_STATUS_NOTFLATSS))) - { - addbyte(0x31); /*XOR ECX, ECX*/ - addbyte(0xc9); - } - else if (IS_32_ADDR(&seg->base)) - { - addbyte(0x8b); /*MOVL ECX, seg->base*/ - addbyte(0x0c); - addbyte(0x25); - addlong((uint32_t)(uintptr_t)&seg->base); - } - else - { - addbyte(0x48); /*MOV RSI, &seg->base*/ - addbyte(0xb8 | REG_ESI); - addquad((uint64_t)&seg->base); - addbyte(0x8b); /*MOV ECX, [RSI]*/ - addbyte(0x0e); - } - addbyte(0x67); /*LEA ESI, (EAX,ECX)*/ - addbyte(0x8d); - addbyte(0x34); - addbyte(0x08); - addbyte(0x89); /*MOV EDI, ESI*/ - addbyte(0xf7); - addbyte(0xc1); /*SHR ESI, 12*/ - addbyte(0xe8 | REG_ESI); - addbyte(12); - addbyte(0xf7); /*TEST EDI, 1*/ - addbyte(0xc7); - addlong(1); - if (IS_32_ADDR(readlookup2)) - { - addbyte(0x67); /*MOV RSI, readlookup2[ESI*8]*/ - addbyte(0x48); - addbyte(0x8b); - addbyte(0x34); - addbyte(0xf5); - addlong((uint32_t)(uintptr_t)readlookup2); - } - else - { - addbyte(0x48); /*MOV RDX, readlookup2*/ - addbyte(0xb8 | REG_EDX); - addquad((uint64_t)readlookup2); - addbyte(0x48); /*MOV RSI, [RDX+RSI*8]*/ - addbyte(0x8b); - addbyte(0x34); - addbyte(0xf2); - } - addbyte(0x75); /*JNE slowpath*/ - addbyte(3+2+4+2); - addbyte(0x83); /*CMP ESI, -1*/ - addbyte(0xf8 | REG_ESI); - addbyte(-1); - addbyte(0x74); /*JE slowpath*/ - addbyte(4+2); - addbyte(0x66); /*MOV AX,[RDI+RSI]*/ - addbyte(0x8b); - addbyte(0x04); - addbyte(REG_EDI | (REG_ESI << 3)); - addbyte(0xeb); /*JMP done*/ - addbyte(2+2+12+4+6); - /*slowpath:*/ - addbyte(0x01); /*ADD ECX,EAX*/ - addbyte(0xc1); - load_param_1_reg_32(REG_ECX); - call_long((uintptr_t)readmemwl); - addbyte(0x80); /*CMP abrt, 0*/ - addbyte(0x7d); - addbyte((uint8_t)cpu_state_offset(abrt)); - addbyte(0); - addbyte(0x0f); /*JNE end*/ - addbyte(0x85); - addlong(BLOCK_EXIT_OFFSET - (block_pos + 4)); - /*done:*/ -} -static inline void MEM_LOAD_ADDR_EA_W_OFFSET(x86seg *seg, int offset) -{ - addbyte(0x83); /*ADD EAX, offset*/ - addbyte(0xc0); - addbyte(offset); - MEM_LOAD_ADDR_EA_W(seg); -} -static inline void MEM_LOAD_ADDR_EA_L(x86seg *seg) -{ - if ((seg == &cpu_state.seg_ds && codegen_flat_ds && !(cpu_cur_status & CPU_STATUS_NOTFLATDS)) || (seg == &cpu_state.seg_ss && codegen_flat_ss && !(cpu_cur_status & CPU_STATUS_NOTFLATSS))) - { - addbyte(0x31); /*XOR ECX, ECX*/ - addbyte(0xc9); - } - else if (IS_32_ADDR(&seg->base)) - { - addbyte(0x8b); /*MOVL ECX, seg->base*/ - addbyte(0x0c); - addbyte(0x25); - addlong((uint32_t)(uintptr_t)&seg->base); - } - else - { - addbyte(0x48); /*MOV RSI, &seg->base*/ - addbyte(0xb8 | REG_ESI); - addquad((uint64_t)&seg->base); - addbyte(0x8b); /*MOV ECX, [RSI]*/ - addbyte(0x0e); - } - addbyte(0x67); /*LEA ESI, (EAX,ECX)*/ - addbyte(0x8d); - addbyte(0x34); - addbyte(0x08); - addbyte(0x89); /*MOV EDI, ESI*/ - addbyte(0xf7); - addbyte(0xc1); /*SHR ESI, 12*/ - addbyte(0xe8 | REG_ESI); - addbyte(12); - addbyte(0xf7); /*TEST EDI, 3*/ - addbyte(0xc7); - addlong(3); - if (IS_32_ADDR(readlookup2)) - { - addbyte(0x67); /*MOV RSI, readlookup2[ESI*8]*/ - addbyte(0x48); - addbyte(0x8b); - addbyte(0x34); - addbyte(0xf5); - addlong((uint32_t)(uintptr_t)readlookup2); - } - else - { - addbyte(0x48); /*MOV RDX, readlookup2*/ - addbyte(0xb8 | REG_EDX); - addquad((uint64_t)readlookup2); - addbyte(0x48); /*MOV RSI, [RDX+RSI*8]*/ - addbyte(0x8b); - addbyte(0x34); - addbyte(0xf2); - } - addbyte(0x75); /*JNE slowpath*/ - addbyte(3+2+3+2); - addbyte(0x83); /*CMP ESI, -1*/ - addbyte(0xf8 | REG_ESI); - addbyte(-1); - addbyte(0x74); /*JE slowpath*/ - addbyte(3+2); - addbyte(0x8b); /*MOV EAX,[RDI+RSI]*/ - addbyte(0x04); - addbyte(REG_EDI | (REG_ESI << 3)); - addbyte(0xeb); /*JMP done*/ - addbyte(2+2+12+4+6); - /*slowpath:*/ - addbyte(0x01); /*ADD ECX,EAX*/ - addbyte(0xc1); - load_param_1_reg_32(REG_ECX); - call_long((uintptr_t)readmemll); - addbyte(0x80); /*CMP abrt, 0*/ - addbyte(0x7d); - addbyte((uint8_t)cpu_state_offset(abrt)); - addbyte(0); - addbyte(0x0f); /*JNE end*/ - addbyte(0x85); - addlong(BLOCK_EXIT_OFFSET - (block_pos + 4)); - /*done:*/ -} -static inline void MEM_LOAD_ADDR_EA_Q(x86seg *seg) -{ - if ((seg == &cpu_state.seg_ds && codegen_flat_ds && !(cpu_cur_status & CPU_STATUS_NOTFLATDS)) || (seg == &cpu_state.seg_ss && codegen_flat_ss && !(cpu_cur_status & CPU_STATUS_NOTFLATSS))) - { - addbyte(0x31); /*XOR ECX, ECX*/ - addbyte(0xc9); - } - else if (IS_32_ADDR(&seg->base)) - { - addbyte(0x8b); /*MOVL ECX, seg->base*/ - addbyte(0x0c); - addbyte(0x25); - addlong((uint32_t)(uintptr_t)&seg->base); - } - else - { - addbyte(0x48); /*MOV RSI, &seg->base*/ - addbyte(0xb8 | REG_ESI); - addquad((uint64_t)&seg->base); - addbyte(0x8b); /*MOV ECX, [RSI]*/ - addbyte(0x0e); - } - addbyte(0x67); /*LEA ESI, (EAX,ECX)*/ - addbyte(0x8d); - addbyte(0x34); - addbyte(0x08); - addbyte(0x89); /*MOV EDI, ESI*/ - addbyte(0xf7); - addbyte(0xc1); /*SHR ESI, 12*/ - addbyte(0xe8 | REG_ESI); - addbyte(12); - addbyte(0xf7); /*TEST EDI, 7*/ - addbyte(0xc7); - addlong(7); - if (IS_32_ADDR(readlookup2)) - { - addbyte(0x67); /*MOV RSI, readlookup2[ESI*8]*/ - addbyte(0x48); - addbyte(0x8b); - addbyte(0x34); - addbyte(0xf5); - addlong((uint32_t)(uintptr_t)readlookup2); - } - else - { - addbyte(0x48); /*MOV RDX, readlookup2*/ - addbyte(0xb8 | REG_EDX); - addquad((uint64_t)readlookup2); - addbyte(0x48); /*MOV RSI, [RDX+RSI*8]*/ - addbyte(0x8b); - addbyte(0x34); - addbyte(0xf2); - } - addbyte(0x75); /*JNE slowpath*/ - addbyte(3+2+4+2); - addbyte(0x83); /*CMP ESI, -1*/ - addbyte(0xf8 | REG_ESI); - addbyte(-1); - addbyte(0x74); /*JE slowpath*/ - addbyte(4+2); - addbyte(0x48); /*MOV RAX,[RDI+RSI]*/ - addbyte(0x8b); - addbyte(0x04); - addbyte(REG_EDI | (REG_ESI << 3)); - addbyte(0xeb); /*JMP done*/ - addbyte(2+2+12+4+6); - /*slowpath:*/ - addbyte(0x01); /*ADD ECX,EAX*/ - addbyte(0xc1); - load_param_1_reg_32(REG_ECX); - call_long((uintptr_t)readmemql); - addbyte(0x80); /*CMP abrt, 0*/ - addbyte(0x7d); - addbyte((uint8_t)cpu_state_offset(abrt)); - addbyte(0); - addbyte(0x0f); /*JNE end*/ - addbyte(0x85); - addlong(BLOCK_EXIT_OFFSET - (block_pos + 4)); - /*done:*/ -} - -static inline void MEM_LOAD_ADDR_IMM_B(x86seg *seg, uint32_t addr) -{ - addbyte(0xb8); /*MOV EAX, addr*/ - addlong(addr); - MEM_LOAD_ADDR_EA_B(seg); -} -static inline void MEM_LOAD_ADDR_IMM_W(x86seg *seg, uint32_t addr) -{ - addbyte(0xb8); /*MOV EAX, addr*/ - addlong(addr); - MEM_LOAD_ADDR_EA_W(seg); -} -static inline void MEM_LOAD_ADDR_IMM_L(x86seg *seg, uint32_t addr) -{ - addbyte(0xb8); /*MOV EAX, addr*/ - addlong(addr); - MEM_LOAD_ADDR_EA_L(seg); -} - -static inline void MEM_STORE_ADDR_EA_B(x86seg *seg, int host_reg) -{ - if (host_reg & 0x10) - { - /*Handle high byte of register*/ - if (host_reg & 8) - { - addbyte(0x45); /*MOVL R8, host_reg*/ - addbyte(0x89); - addbyte(0xc0 | ((host_reg & 7) << 3)); - } - else - { - addbyte(0x41); /*MOVL R8, host_reg*/ - addbyte(0x89); - addbyte(0xc0 | ((host_reg & 7) << 3)); - } - addbyte(0x66); /*SHR R8, 8*/ + base_reg = LOAD_REG_L(rm) & 7; + if (mod) { + if (rm == 5 && !op_ssegs) + op_ea_seg = &cpu_state.seg_ss; + if (mod == 1) { + addbyte(0x67); /*LEA EAX, base_reg+imm8*/ addbyte(0x41); - addbyte(0xc1); - addbyte(0xe8); - addbyte(8); - host_reg = 8; + addbyte(0x8d); + addbyte(0x40 | base_reg); + addbyte((fetchdat >> 8) & 0xff); + (*op_pc)++; + } else { + new_eaaddr = fastreadl(cs + (*op_pc) + 1); + addbyte(0x67); /*LEA EAX, base_reg+imm32*/ + addbyte(0x41); + addbyte(0x8d); + addbyte(0x80 | base_reg); + addlong(new_eaaddr); + (*op_pc) += 4; + } + } else { + addbyte(0x44); /*MOV EAX, base_reg*/ + addbyte(0x89); + addbyte(0xc0 | (base_reg << 3)); } - if ((seg == &cpu_state.seg_ds && codegen_flat_ds && !(cpu_cur_status & CPU_STATUS_NOTFLATDS)) || (seg == &cpu_state.seg_ss && codegen_flat_ss && !(cpu_cur_status & CPU_STATUS_NOTFLATSS))) - { - addbyte(0x31); /*XOR ECX, ECX*/ - addbyte(0xc9); - } - else if (IS_32_ADDR(&seg->base)) - { - addbyte(0x8b); /*MOVL ECX, seg->base*/ - addbyte(0x0c); - addbyte(0x25); - addlong((uint32_t)(uintptr_t)&seg->base); - } - else - { - addbyte(0x48); /*MOV RSI, &seg->base*/ - addbyte(0xb8 | REG_ESI); - addquad((uint64_t)&seg->base); - addbyte(0x8b); /*MOV ECX, [RSI]*/ - addbyte(0x0e); - } - addbyte(0x67); /*LEA ESI, (EAX,ECX)*/ - addbyte(0x8d); - addbyte(0x34); - addbyte(0x08); - addbyte(0x89); /*MOV EDI, ESI*/ - addbyte(0xf7); - addbyte(0xc1); /*SHR ESI, 12*/ - addbyte(0xe8 | REG_ESI); - addbyte(12); - if (IS_32_ADDR(writelookup2)) - { - addbyte(0x67); /*MOV RSI, writelookup2[ESI*8]*/ - addbyte(0x48); - addbyte(0x8b); - addbyte(0x34); - addbyte(0xf5); - addlong((uint32_t)(uintptr_t)writelookup2); - } - else - { - addbyte(0x48); /*MOV RDX, writelookup2*/ - addbyte(0xb8 | REG_EDX); - addquad((uint64_t)writelookup2); - addbyte(0x48); /*MOV RSI, [RDX+RSI*8]*/ - addbyte(0x8b); - addbyte(0x34); - addbyte(0xf2); - } - addbyte(0x83); /*CMP ESI, -1*/ - addbyte(0xf8 | REG_ESI); - addbyte(-1); - addbyte(0x74); /*JE slowpath*/ - addbyte(((host_reg & 8) ? 4:3)+2); - if (host_reg & 8) - { - addbyte(0x44); /*MOV [RDI+RSI],host_reg*/ - addbyte(0x88); - addbyte(0x04 | ((host_reg & 7) << 3)); - addbyte(REG_EDI | (REG_ESI << 3)); - } - else - { - addbyte(0x88); /*MOV [RDI+RSI],host_reg*/ - addbyte(0x04 | (host_reg << 3)); - addbyte(REG_EDI | (REG_ESI << 3)); - } - addbyte(0xeb); /*JMP done*/ - if (host_reg & 8) { - addbyte(2+2+3+12+4+6); - } else { - addbyte(2+2+2+12+4+6); - } - /*slowpath:*/ - addbyte(0x01); /*ADD ECX,EAX*/ - addbyte(0xc1); - load_param_1_reg_32(REG_ECX); - load_param_2_reg_32(host_reg); - call_long((uintptr_t)writemembl); - addbyte(0x80); /*CMP abrt, 0*/ - addbyte(0x7d); - addbyte((uint8_t)cpu_state_offset(abrt)); - addbyte(0); - addbyte(0x0f); /*JNE end*/ - addbyte(0x85); - addlong(BLOCK_EXIT_OFFSET - (block_pos + 4)); - /*done:*/ -} -static inline void MEM_STORE_ADDR_EA_W(x86seg *seg, int host_reg) -{ - if ((seg == &cpu_state.seg_ds && codegen_flat_ds && !(cpu_cur_status & CPU_STATUS_NOTFLATDS)) || (seg == &cpu_state.seg_ss && codegen_flat_ss && !(cpu_cur_status & CPU_STATUS_NOTFLATSS))) - { - addbyte(0x31); /*XOR ECX, ECX*/ - addbyte(0xc9); - } - else if (IS_32_ADDR(&seg->base)) - { - addbyte(0x8b); /*MOVL ECX, seg->base*/ - addbyte(0x0c); - addbyte(0x25); - addlong((uint32_t)(uintptr_t)&seg->base); - } - else - { - addbyte(0x48); /*MOV RSI, &seg->base*/ - addbyte(0xb8 | REG_ESI); - addquad((uint64_t)&seg->base); - addbyte(0x8b); /*MOV ECX, [RSI]*/ - addbyte(0x0e); - } - addbyte(0x67); /*LEA ESI, (EAX,ECX)*/ - addbyte(0x8d); - addbyte(0x34); - addbyte(0x08); - addbyte(0x89); /*MOV EDI, ESI*/ - addbyte(0xf7); - addbyte(0xc1); /*SHR ESI, 12*/ - addbyte(0xe8 | REG_ESI); - addbyte(12); - addbyte(0xf7); /*TEST EDI, 1*/ - addbyte(0xc7); - addlong(1); - if (IS_32_ADDR(writelookup2)) - { - addbyte(0x67); /*MOV RSI, writelookup2[ESI*8]*/ - addbyte(0x48); - addbyte(0x8b); - addbyte(0x34); - addbyte(0xf5); - addlong((uint32_t)(uintptr_t)writelookup2); - } - else - { - addbyte(0x48); /*MOV RDX, writelookup2*/ - addbyte(0xb8 | REG_EDX); - addquad((uint64_t)writelookup2); - addbyte(0x48); /*MOV RSI, [RDX+RSI*8]*/ - addbyte(0x8b); - addbyte(0x34); - addbyte(0xf2); - } - addbyte(0x75); /*JNE slowpath*/ - addbyte(3+2+((host_reg & 8) ? 5:4)+2); - addbyte(0x83); /*CMP ESI, -1*/ - addbyte(0xf8 | REG_ESI); - addbyte(-1); - addbyte(0x74); /*JE slowpath*/ - addbyte(((host_reg & 8) ? 5:4)+2); - if (host_reg & 8) - { - addbyte(0x66); /*MOV [RDI+RSI],host_reg*/ - addbyte(0x44); - addbyte(0x89); - addbyte(0x04 | ((host_reg & 7) << 3)); - addbyte(REG_EDI | (REG_ESI << 3)); - } - else - { - addbyte(0x66); /*MOV [RDI+RSI],host_reg*/ - addbyte(0x89); - addbyte(0x04 | (host_reg << 3)); - addbyte(REG_EDI | (REG_ESI << 3)); - } - addbyte(0xeb); /*JMP done*/ - if (host_reg & 8) { - addbyte(2+2+3+12+4+6); - } else { - addbyte(2+2+2+12+4+6); - } - /*slowpath:*/ - addbyte(0x01); /*ADD ECX,EAX*/ - addbyte(0xc1); - load_param_1_reg_32(REG_ECX); - load_param_2_reg_32(host_reg); - call_long((uintptr_t)writememwl); - addbyte(0x80); /*CMP abrt, 0*/ - addbyte(0x7d); - addbyte((uint8_t)cpu_state_offset(abrt)); - addbyte(0); - addbyte(0x0f); /*JNE end*/ - addbyte(0x85); - addlong(BLOCK_EXIT_OFFSET - (block_pos + 4)); - /*done:*/ -} -static inline void MEM_STORE_ADDR_EA_L(x86seg *seg, int host_reg) -{ - if ((seg == &cpu_state.seg_ds && codegen_flat_ds && !(cpu_cur_status & CPU_STATUS_NOTFLATDS)) || (seg == &cpu_state.seg_ss && codegen_flat_ss && !(cpu_cur_status & CPU_STATUS_NOTFLATSS))) - { - addbyte(0x31); /*XOR ECX, ECX*/ - addbyte(0xc9); - } - else if (IS_32_ADDR(&seg->base)) - { - addbyte(0x8b); /*MOVL ECX, seg->base*/ - addbyte(0x0c); - addbyte(0x25); - addlong((uint32_t)(uintptr_t)&seg->base); - } - else - { - addbyte(0x48); /*MOV RSI, &seg->base*/ - addbyte(0xb8 | REG_ESI); - addquad((uint64_t)&seg->base); - addbyte(0x8b); /*MOV ECX, [RSI]*/ - addbyte(0x0e); - } - addbyte(0x67); /*LEA ESI, (EAX,ECX)*/ - addbyte(0x8d); - addbyte(0x34); - addbyte(0x08); - addbyte(0x89); /*MOV EDI, ESI*/ - addbyte(0xf7); - addbyte(0xc1); /*SHR ESI, 12*/ - addbyte(0xe8 | REG_ESI); - addbyte(12); - addbyte(0xf7); /*TEST EDI, 3*/ - addbyte(0xc7); - addlong(3); - if (IS_32_ADDR(writelookup2)) - { - addbyte(0x67); /*MOV RSI, writelookup2[ESI*8]*/ - addbyte(0x48); - addbyte(0x8b); - addbyte(0x34); - addbyte(0xf5); - addlong((uint32_t)(uintptr_t)writelookup2); - } - else - { - addbyte(0x48); /*MOV RDX, writelookup2*/ - addbyte(0xb8 | REG_EDX); - addquad((uint64_t)writelookup2); - addbyte(0x48); /*MOV RSI, [RDX+RSI*8]*/ - addbyte(0x8b); - addbyte(0x34); - addbyte(0xf2); - } - addbyte(0x75); /*JNE slowpath*/ - addbyte(3+2+((host_reg & 8) ? 4:3)+2); - addbyte(0x83); /*CMP ESI, -1*/ - addbyte(0xf8 | REG_ESI); - addbyte(-1); - addbyte(0x74); /*JE slowpath*/ - addbyte(((host_reg & 8) ? 4:3)+2); - if (host_reg & 8) - { - addbyte(0x44); /*MOV -3[RDI+RSI],host_reg*/ - addbyte(0x89); - addbyte(0x04 | ((host_reg & 7) << 3)); - addbyte(REG_EDI | (REG_ESI << 3)); - } - else - { - addbyte(0x89); /*MOV -3[RDI+RSI],host_reg*/ - addbyte(0x04 | (host_reg << 3)); - addbyte(REG_EDI | (REG_ESI << 3)); - } - addbyte(0xeb); /*JMP done*/ - if (host_reg & 8) { - addbyte(2+2+3+12+4+6); - } else { - addbyte(2+2+2+12+4+6); - } - /*slowpath:*/ - addbyte(0x01); /*ADD ECX,EAX*/ - addbyte(0xc1); - load_param_1_reg_32(REG_ECX); - load_param_2_reg_32(host_reg); - call_long((uintptr_t)writememll); - addbyte(0x80); /*CMP abrt, 0*/ - addbyte(0x7d); - addbyte((uint8_t)cpu_state_offset(abrt)); - addbyte(0); - addbyte(0x0f); /*JNE end*/ - addbyte(0x85); - addlong(BLOCK_EXIT_OFFSET - (block_pos + 4)); - /*done:*/ -} -static inline void MEM_STORE_ADDR_EA_Q(x86seg *seg, int host_reg, int host_reg2) -{ - if ((seg == &cpu_state.seg_ds && codegen_flat_ds && !(cpu_cur_status & CPU_STATUS_NOTFLATDS)) || (seg == &cpu_state.seg_ss && codegen_flat_ss && !(cpu_cur_status & CPU_STATUS_NOTFLATSS))) - { - addbyte(0x31); /*XOR ECX, ECX*/ - addbyte(0xc9); - } - else if (IS_32_ADDR(&seg->base)) - { - addbyte(0x8b); /*MOVL ECX, seg->base*/ - addbyte(0x0c); - addbyte(0x25); - addlong((uint32_t)(uintptr_t)&seg->base); - } - else - { - addbyte(0x48); /*MOV RSI, &seg->base*/ - addbyte(0xb8 | REG_ESI); - addquad((uint64_t)&seg->base); - addbyte(0x8b); /*MOV ECX, [RSI]*/ - addbyte(0x0e); - } - addbyte(0x67); /*LEA ESI, (EAX,ECX)*/ - addbyte(0x8d); - addbyte(0x34); - addbyte(0x08); - addbyte(0x89); /*MOV EDI, ESI*/ - addbyte(0xf7); - addbyte(0xc1); /*SHR ESI, 12*/ - addbyte(0xe8 | REG_ESI); - addbyte(12); - addbyte(0xf7); /*TEST EDI, 7*/ - addbyte(0xc7); - addlong(7); - if (IS_32_ADDR(writelookup2)) - { - addbyte(0x67); /*MOV RSI, writelookup2[ESI*8]*/ - addbyte(0x48); - addbyte(0x8b); - addbyte(0x34); - addbyte(0xf5); - addlong((uint32_t)(uintptr_t)writelookup2); - } - else - { - addbyte(0x48); /*MOV RDX, writelookup2*/ - addbyte(0xb8 | REG_EDX); - addquad((uint64_t)writelookup2); - addbyte(0x48); /*MOV RSI, [RDX+RSI*8]*/ - addbyte(0x8b); - addbyte(0x34); - addbyte(0xf2); - } - addbyte(0x75); /*JNE slowpath*/ - addbyte(3+2+4+2); - addbyte(0x83); /*CMP ESI, -1*/ - addbyte(0xf8 | REG_ESI); - addbyte(-1); - addbyte(0x74); /*JE slowpath*/ - addbyte(4+2); - if (host_reg & 8) - { - addbyte(0x4c); /*MOV [RDI+RSI],host_reg*/ - addbyte(0x89); - addbyte(0x04 | ((host_reg & 7) << 3)); - addbyte(REG_EDI | (REG_ESI << 3)); - } - else - { - addbyte(0x48); /*MOV [RDI+RSI],host_reg*/ - addbyte(0x89); - addbyte(0x04 | (host_reg << 3)); - addbyte(REG_EDI | (REG_ESI << 3)); - } - addbyte(0xeb); /*JMP done*/ - addbyte(2+2+3+12+4+6); - /*slowpath:*/ - addbyte(0x01); /*ADD ECX,EAX*/ - addbyte(0xc1); - load_param_1_reg_32(REG_ECX); - load_param_2_reg_64(host_reg); - call_long((uintptr_t)writememql); - addbyte(0x80); /*CMP abrt, 0*/ - addbyte(0x7d); - addbyte((uint8_t)cpu_state_offset(abrt)); - addbyte(0); - addbyte(0x0f); /*JNE end*/ - addbyte(0x85); - addlong(BLOCK_EXIT_OFFSET - (block_pos + 4)); - /*done:*/ + } + return op_ea_seg; } -static inline void MEM_STORE_ADDR_IMM_B(x86seg *seg, uint32_t addr, int host_reg) +static __inline x86seg * +FETCH_EA(x86seg *op_ea_seg, uint32_t fetchdat, int op_ssegs, uint32_t *op_pc, uint32_t op_32) { - addbyte(0xb8); /*MOV EAX, addr*/ - addlong(addr); - MEM_STORE_ADDR_EA_B(seg, host_reg); -} -static inline void MEM_STORE_ADDR_IMM_W(x86seg *seg, uint32_t addr, int host_reg) -{ - addbyte(0xb8); /*MOV EAX, addr*/ - addlong(addr); - MEM_STORE_ADDR_EA_W(seg, host_reg); -} -static inline void MEM_STORE_ADDR_IMM_L(x86seg *seg, uint32_t addr, int host_reg) -{ - addbyte(0xb8); /*MOV EAX, addr*/ - addlong(addr); - MEM_STORE_ADDR_EA_L(seg, host_reg); + if (op_32 & 0x200) + return FETCH_EA_32(op_ea_seg, fetchdat, op_ssegs, op_pc, 0); + return FETCH_EA_16(op_ea_seg, fetchdat, op_ssegs, op_pc); } -static inline void STORE_HOST_REG_ADDR_BL(uintptr_t addr, int host_reg) +static __inline void +CHECK_SEG_READ(x86seg *seg) { - int temp_reg = REG_ECX; - - if (host_reg_mapping[REG_ECX] != -1) - temp_reg = REG_EBX; - - if (host_reg & 0x10) - { - if (host_reg & 8) - addbyte(0x41); - addbyte(0x0f); /*MOVZX temp_reg, host_reg*/ - addbyte(0xb7); - addbyte(0xc0 | (temp_reg << 3) | (host_reg & 7)); - addbyte(0xc1); /*SHR temp_reg, 8*/ - addbyte(0xe8 | temp_reg); - addbyte(8); - } - else - { - if (host_reg & 8) - addbyte(0x41); - addbyte(0x0f); /*MOVZX temp_reg, host_reg*/ - addbyte(0xb6); - addbyte(0xc0 | (temp_reg << 3) | (host_reg & 7)); - } - if (addr >= (uintptr_t)&cpu_state && addr < ((uintptr_t)&cpu_state)+0x100) - { - addbyte(0x89); /*MOV addr, temp_reg*/ - addbyte(0x45 | (temp_reg << 3)); - addbyte((uint32_t)addr - (uint32_t)(uintptr_t)&cpu_state - 128); - } - else if (IS_32_ADDR(addr)) - { - addbyte(0x89); /*MOV addr, temp_reg*/ - addbyte(0x04 | (temp_reg << 3)); - addbyte(0x25); - addlong(addr); - } - else - { - addbyte(0x48); /*MOV RSI, addr*/ - addbyte(0xb8 | REG_ESI); - addquad((uint64_t)addr); - addbyte(0x89); /*MOV [RSI], temp_reg*/ - addbyte(0x06 | (temp_reg << 3)); - } + /*Segments always valid in real/V86 mode*/ + if (!(cr0 & 1) || (cpu_state.eflags & VM_FLAG)) + return; + /*CS and SS must always be valid*/ + if (seg == &cpu_state.seg_cs || seg == &cpu_state.seg_ss) + return; + if (seg->checked) + return; + if (seg == &cpu_state.seg_ds && codegen_flat_ds && !(cpu_cur_status & CPU_STATUS_NOTFLATDS)) + return; + + if (IS_32_ADDR(&seg->base)) { + addbyte(0x83); /*CMP seg->base, -1*/ + addbyte(0x3c); + addbyte(0x25); + addlong((uint32_t) (uintptr_t) &seg->base); + addbyte(-1); + } else { + addbyte(0x48); /*MOV RSI, &addr*/ + addbyte(0xb8 | REG_ESI); + addquad((uint64_t) &seg->base); + addbyte(0x83); /*CMP RSI, -1*/ + addbyte(0xe8 | REG_ESI); + addbyte(0xff); + } + addbyte(0x0f); /*JE GPF_BLOCK_OFFSET*/ + addbyte(0x84); + addlong(BLOCK_GPF_OFFSET - (block_pos + 4)); + + seg->checked = 1; } -static inline void STORE_HOST_REG_ADDR_WL(uintptr_t addr, int host_reg) +static __inline void +CHECK_SEG_WRITE(x86seg *seg) { - int temp_reg = REG_ECX; - - if (host_reg_mapping[REG_ECX] != -1) - temp_reg = REG_EBX; - + /*Segments always valid in real/V86 mode*/ + if (!(cr0 & 1) || (cpu_state.eflags & VM_FLAG)) + return; + /*CS and SS must always be valid*/ + if (seg == &cpu_state.seg_cs || seg == &cpu_state.seg_ss) + return; + if (seg->checked) + return; + if (seg == &cpu_state.seg_ds && codegen_flat_ds && !(cpu_cur_status & CPU_STATUS_NOTFLATDS)) + return; + + if (IS_32_ADDR(&seg->base)) { + addbyte(0x83); /*CMP seg->base, -1*/ + addbyte(0x3c); + addbyte(0x25); + addlong((uint32_t) (uintptr_t) &seg->base); + addbyte(-1); + } else { + addbyte(0x48); /*MOV RSI, &addr*/ + addbyte(0xb8 | REG_ESI); + addquad((uint64_t) &seg->base); + addbyte(0x83); /*CMP RSI, -1*/ + addbyte(0xe8 | REG_ESI); + addbyte(0xff); + } + addbyte(0x0f); /*JE GPF_BLOCK_OFFSET*/ + addbyte(0x84); + addlong(BLOCK_GPF_OFFSET - (block_pos + 4)); + + seg->checked = 1; +} +static __inline void +CHECK_SEG_LIMITS(x86seg *seg, int end_offset) +{ + if ((seg == &cpu_state.seg_ds && codegen_flat_ds && !(cpu_cur_status & CPU_STATUS_NOTFLATDS)) || (seg == &cpu_state.seg_ss && codegen_flat_ss && !(cpu_cur_status & CPU_STATUS_NOTFLATSS))) + return; + + if (IS_32_ADDR(&seg->base)) { + addbyte(0xb8 | REG_ESI); /*MOV ESI, &addr*/ + addlong((uint32_t) (uintptr_t) seg); + } else { + addbyte(0x48); /*MOV RSI, &addr*/ + addbyte(0xb8 | REG_ESI); + addquad((uint64_t) seg); + } + addbyte(0x3b); /*CMP EAX, seg->limit_low*/ + addbyte(0x46); + addbyte((uintptr_t) &seg->limit_low - (uintptr_t) seg); + addbyte(0x0f); /*JB BLOCK_GPF_OFFSET*/ + addbyte(0x82); + addlong(BLOCK_GPF_OFFSET - (block_pos + 4)); + if (end_offset) { + addbyte(0x83); /*ADD EAX, end_offset*/ + addbyte(0xc0); + addbyte(end_offset); + addbyte(0x3b); /*CMP EAX, seg->limit_high*/ + addbyte(0x46); + addbyte((uintptr_t) &seg->limit_high - (uintptr_t) seg); + addbyte(0x0f); /*JNBE BLOCK_GPF_OFFSET*/ + addbyte(0x87); + addlong(BLOCK_GPF_OFFSET - (block_pos + 4)); + addbyte(0x83); /*SUB EAX, end_offset*/ + addbyte(0xe8); + addbyte(end_offset); + } +} + +static __inline void +MEM_LOAD_ADDR_EA_B(x86seg *seg) +{ + if ((seg == &cpu_state.seg_ds && codegen_flat_ds && !(cpu_cur_status & CPU_STATUS_NOTFLATDS)) || (seg == &cpu_state.seg_ss && codegen_flat_ss && !(cpu_cur_status & CPU_STATUS_NOTFLATSS))) { + addbyte(0x31); /*XOR ECX, ECX*/ + addbyte(0xc9); + } else if (IS_32_ADDR(&seg->base)) { + addbyte(0x8b); /*MOVL ECX, seg->base*/ + addbyte(0x0c); + addbyte(0x25); + addlong((uint32_t) (uintptr_t) &seg->base); + } else { + addbyte(0x48); /*MOV RSI, &seg->base*/ + addbyte(0xb8 | REG_ESI); + addquad((uint64_t) &seg->base); + addbyte(0x8b); /*MOV ECX, [RSI]*/ + addbyte(0x0e); + } + addbyte(0x67); /*LEA ESI, (EAX,ECX)*/ + addbyte(0x8d); + addbyte(0x34); + addbyte(0x08); + addbyte(0x89); /*MOV EDI, ESI*/ + addbyte(0xf7); + addbyte(0xc1); /*SHR ESI, 12*/ + addbyte(0xe8 | REG_ESI); + addbyte(12); + if (IS_32_ADDR(readlookup2)) { + addbyte(0x67); /*MOV RSI, readlookup2[ESI*8]*/ + addbyte(0x48); + addbyte(0x8b); + addbyte(0x34); + addbyte(0xf5); + addlong((uint32_t) (uintptr_t) readlookup2); + } else { + addbyte(0x48); /*MOV RDX, readlookup2*/ + addbyte(0xb8 | REG_EDX); + addquad((uint64_t) readlookup2); + addbyte(0x48); /*MOV RSI, [RDX+RSI*8]*/ + addbyte(0x8b); + addbyte(0x34); + addbyte(0xf2); + } + addbyte(0x83); /*CMP ESI, -1*/ + addbyte(0xf8 | REG_ESI); + addbyte(-1); + addbyte(0x74); /*JE slowpath*/ + addbyte(3 + 2); + addbyte(0x8b); /*MOV AL,[RDI+RSI]*/ + addbyte(0x04); + addbyte(REG_EDI | (REG_ESI << 3)); + addbyte(0xeb); /*JMP done*/ + addbyte(2 + 2 + 12 + 4 + 6); + /*slowpath:*/ + addbyte(0x01); /*ADD ECX,EAX*/ + addbyte(0xc1); + load_param_1_reg_32(REG_ECX); + call_long((uintptr_t) readmembl); + addbyte(0x80); /*CMP abrt, 0*/ + addbyte(0x7d); + addbyte((uint8_t) cpu_state_offset(abrt)); + addbyte(0); + addbyte(0x0f); /*JNE end*/ + addbyte(0x85); + addlong(BLOCK_EXIT_OFFSET - (block_pos + 4)); + /*done:*/ +} +static __inline void +MEM_LOAD_ADDR_EA_W(x86seg *seg) +{ + if ((seg == &cpu_state.seg_ds && codegen_flat_ds && !(cpu_cur_status & CPU_STATUS_NOTFLATDS)) || (seg == &cpu_state.seg_ss && codegen_flat_ss && !(cpu_cur_status & CPU_STATUS_NOTFLATSS))) { + addbyte(0x31); /*XOR ECX, ECX*/ + addbyte(0xc9); + } else if (IS_32_ADDR(&seg->base)) { + addbyte(0x8b); /*MOVL ECX, seg->base*/ + addbyte(0x0c); + addbyte(0x25); + addlong((uint32_t) (uintptr_t) &seg->base); + } else { + addbyte(0x48); /*MOV RSI, &seg->base*/ + addbyte(0xb8 | REG_ESI); + addquad((uint64_t) &seg->base); + addbyte(0x8b); /*MOV ECX, [RSI]*/ + addbyte(0x0e); + } + addbyte(0x67); /*LEA ESI, (EAX,ECX)*/ + addbyte(0x8d); + addbyte(0x34); + addbyte(0x08); + addbyte(0x89); /*MOV EDI, ESI*/ + addbyte(0xf7); + addbyte(0xc1); /*SHR ESI, 12*/ + addbyte(0xe8 | REG_ESI); + addbyte(12); + addbyte(0xf7); /*TEST EDI, 1*/ + addbyte(0xc7); + addlong(1); + if (IS_32_ADDR(readlookup2)) { + addbyte(0x67); /*MOV RSI, readlookup2[ESI*8]*/ + addbyte(0x48); + addbyte(0x8b); + addbyte(0x34); + addbyte(0xf5); + addlong((uint32_t) (uintptr_t) readlookup2); + } else { + addbyte(0x48); /*MOV RDX, readlookup2*/ + addbyte(0xb8 | REG_EDX); + addquad((uint64_t) readlookup2); + addbyte(0x48); /*MOV RSI, [RDX+RSI*8]*/ + addbyte(0x8b); + addbyte(0x34); + addbyte(0xf2); + } + addbyte(0x75); /*JNE slowpath*/ + addbyte(3 + 2 + 4 + 2); + addbyte(0x83); /*CMP ESI, -1*/ + addbyte(0xf8 | REG_ESI); + addbyte(-1); + addbyte(0x74); /*JE slowpath*/ + addbyte(4 + 2); + addbyte(0x66); /*MOV AX,[RDI+RSI]*/ + addbyte(0x8b); + addbyte(0x04); + addbyte(REG_EDI | (REG_ESI << 3)); + addbyte(0xeb); /*JMP done*/ + addbyte(2 + 2 + 12 + 4 + 6); + /*slowpath:*/ + addbyte(0x01); /*ADD ECX,EAX*/ + addbyte(0xc1); + load_param_1_reg_32(REG_ECX); + call_long((uintptr_t) readmemwl); + addbyte(0x80); /*CMP abrt, 0*/ + addbyte(0x7d); + addbyte((uint8_t) cpu_state_offset(abrt)); + addbyte(0); + addbyte(0x0f); /*JNE end*/ + addbyte(0x85); + addlong(BLOCK_EXIT_OFFSET - (block_pos + 4)); + /*done:*/ +} +static __inline void +MEM_LOAD_ADDR_EA_W_OFFSET(x86seg *seg, int offset) +{ + addbyte(0x83); /*ADD EAX, offset*/ + addbyte(0xc0); + addbyte(offset); + MEM_LOAD_ADDR_EA_W(seg); +} +static __inline void +MEM_LOAD_ADDR_EA_L(x86seg *seg) +{ + if ((seg == &cpu_state.seg_ds && codegen_flat_ds && !(cpu_cur_status & CPU_STATUS_NOTFLATDS)) || (seg == &cpu_state.seg_ss && codegen_flat_ss && !(cpu_cur_status & CPU_STATUS_NOTFLATSS))) { + addbyte(0x31); /*XOR ECX, ECX*/ + addbyte(0xc9); + } else if (IS_32_ADDR(&seg->base)) { + addbyte(0x8b); /*MOVL ECX, seg->base*/ + addbyte(0x0c); + addbyte(0x25); + addlong((uint32_t) (uintptr_t) &seg->base); + } else { + addbyte(0x48); /*MOV RSI, &seg->base*/ + addbyte(0xb8 | REG_ESI); + addquad((uint64_t) &seg->base); + addbyte(0x8b); /*MOV ECX, [RSI]*/ + addbyte(0x0e); + } + addbyte(0x67); /*LEA ESI, (EAX,ECX)*/ + addbyte(0x8d); + addbyte(0x34); + addbyte(0x08); + addbyte(0x89); /*MOV EDI, ESI*/ + addbyte(0xf7); + addbyte(0xc1); /*SHR ESI, 12*/ + addbyte(0xe8 | REG_ESI); + addbyte(12); + addbyte(0xf7); /*TEST EDI, 3*/ + addbyte(0xc7); + addlong(3); + if (IS_32_ADDR(readlookup2)) { + addbyte(0x67); /*MOV RSI, readlookup2[ESI*8]*/ + addbyte(0x48); + addbyte(0x8b); + addbyte(0x34); + addbyte(0xf5); + addlong((uint32_t) (uintptr_t) readlookup2); + } else { + addbyte(0x48); /*MOV RDX, readlookup2*/ + addbyte(0xb8 | REG_EDX); + addquad((uint64_t) readlookup2); + addbyte(0x48); /*MOV RSI, [RDX+RSI*8]*/ + addbyte(0x8b); + addbyte(0x34); + addbyte(0xf2); + } + addbyte(0x75); /*JNE slowpath*/ + addbyte(3 + 2 + 3 + 2); + addbyte(0x83); /*CMP ESI, -1*/ + addbyte(0xf8 | REG_ESI); + addbyte(-1); + addbyte(0x74); /*JE slowpath*/ + addbyte(3 + 2); + addbyte(0x8b); /*MOV EAX,[RDI+RSI]*/ + addbyte(0x04); + addbyte(REG_EDI | (REG_ESI << 3)); + addbyte(0xeb); /*JMP done*/ + addbyte(2 + 2 + 12 + 4 + 6); + /*slowpath:*/ + addbyte(0x01); /*ADD ECX,EAX*/ + addbyte(0xc1); + load_param_1_reg_32(REG_ECX); + call_long((uintptr_t) readmemll); + addbyte(0x80); /*CMP abrt, 0*/ + addbyte(0x7d); + addbyte((uint8_t) cpu_state_offset(abrt)); + addbyte(0); + addbyte(0x0f); /*JNE end*/ + addbyte(0x85); + addlong(BLOCK_EXIT_OFFSET - (block_pos + 4)); + /*done:*/ +} +static __inline void +MEM_LOAD_ADDR_EA_Q(x86seg *seg) +{ + if ((seg == &cpu_state.seg_ds && codegen_flat_ds && !(cpu_cur_status & CPU_STATUS_NOTFLATDS)) || (seg == &cpu_state.seg_ss && codegen_flat_ss && !(cpu_cur_status & CPU_STATUS_NOTFLATSS))) { + addbyte(0x31); /*XOR ECX, ECX*/ + addbyte(0xc9); + } else if (IS_32_ADDR(&seg->base)) { + addbyte(0x8b); /*MOVL ECX, seg->base*/ + addbyte(0x0c); + addbyte(0x25); + addlong((uint32_t) (uintptr_t) &seg->base); + } else { + addbyte(0x48); /*MOV RSI, &seg->base*/ + addbyte(0xb8 | REG_ESI); + addquad((uint64_t) &seg->base); + addbyte(0x8b); /*MOV ECX, [RSI]*/ + addbyte(0x0e); + } + addbyte(0x67); /*LEA ESI, (EAX,ECX)*/ + addbyte(0x8d); + addbyte(0x34); + addbyte(0x08); + addbyte(0x89); /*MOV EDI, ESI*/ + addbyte(0xf7); + addbyte(0xc1); /*SHR ESI, 12*/ + addbyte(0xe8 | REG_ESI); + addbyte(12); + addbyte(0xf7); /*TEST EDI, 7*/ + addbyte(0xc7); + addlong(7); + if (IS_32_ADDR(readlookup2)) { + addbyte(0x67); /*MOV RSI, readlookup2[ESI*8]*/ + addbyte(0x48); + addbyte(0x8b); + addbyte(0x34); + addbyte(0xf5); + addlong((uint32_t) (uintptr_t) readlookup2); + } else { + addbyte(0x48); /*MOV RDX, readlookup2*/ + addbyte(0xb8 | REG_EDX); + addquad((uint64_t) readlookup2); + addbyte(0x48); /*MOV RSI, [RDX+RSI*8]*/ + addbyte(0x8b); + addbyte(0x34); + addbyte(0xf2); + } + addbyte(0x75); /*JNE slowpath*/ + addbyte(3 + 2 + 4 + 2); + addbyte(0x83); /*CMP ESI, -1*/ + addbyte(0xf8 | REG_ESI); + addbyte(-1); + addbyte(0x74); /*JE slowpath*/ + addbyte(4 + 2); + addbyte(0x48); /*MOV RAX,[RDI+RSI]*/ + addbyte(0x8b); + addbyte(0x04); + addbyte(REG_EDI | (REG_ESI << 3)); + addbyte(0xeb); /*JMP done*/ + addbyte(2 + 2 + 12 + 4 + 6); + /*slowpath:*/ + addbyte(0x01); /*ADD ECX,EAX*/ + addbyte(0xc1); + load_param_1_reg_32(REG_ECX); + call_long((uintptr_t) readmemql); + addbyte(0x80); /*CMP abrt, 0*/ + addbyte(0x7d); + addbyte((uint8_t) cpu_state_offset(abrt)); + addbyte(0); + addbyte(0x0f); /*JNE end*/ + addbyte(0x85); + addlong(BLOCK_EXIT_OFFSET - (block_pos + 4)); + /*done:*/ +} + +static __inline void +MEM_LOAD_ADDR_IMM_B(x86seg *seg, uint32_t addr) +{ + addbyte(0xb8); /*MOV EAX, addr*/ + addlong(addr); + MEM_LOAD_ADDR_EA_B(seg); +} +static __inline void +MEM_LOAD_ADDR_IMM_W(x86seg *seg, uint32_t addr) +{ + addbyte(0xb8); /*MOV EAX, addr*/ + addlong(addr); + MEM_LOAD_ADDR_EA_W(seg); +} +static __inline void +MEM_LOAD_ADDR_IMM_L(x86seg *seg, uint32_t addr) +{ + addbyte(0xb8); /*MOV EAX, addr*/ + addlong(addr); + MEM_LOAD_ADDR_EA_L(seg); +} + +static __inline void +MEM_STORE_ADDR_EA_B(x86seg *seg, int host_reg) +{ + if (host_reg & 0x10) { + /*Handle high byte of register*/ + if (host_reg & 8) { + addbyte(0x45); /*MOVL R8, host_reg*/ + addbyte(0x89); + addbyte(0xc0 | ((host_reg & 7) << 3)); + } else { + addbyte(0x41); /*MOVL R8, host_reg*/ + addbyte(0x89); + addbyte(0xc0 | ((host_reg & 7) << 3)); + } + addbyte(0x66); /*SHR R8, 8*/ + addbyte(0x41); + addbyte(0xc1); + addbyte(0xe8); + addbyte(8); + host_reg = 8; + } + if ((seg == &cpu_state.seg_ds && codegen_flat_ds && !(cpu_cur_status & CPU_STATUS_NOTFLATDS)) || (seg == &cpu_state.seg_ss && codegen_flat_ss && !(cpu_cur_status & CPU_STATUS_NOTFLATSS))) { + addbyte(0x31); /*XOR ECX, ECX*/ + addbyte(0xc9); + } else if (IS_32_ADDR(&seg->base)) { + addbyte(0x8b); /*MOVL ECX, seg->base*/ + addbyte(0x0c); + addbyte(0x25); + addlong((uint32_t) (uintptr_t) &seg->base); + } else { + addbyte(0x48); /*MOV RSI, &seg->base*/ + addbyte(0xb8 | REG_ESI); + addquad((uint64_t) &seg->base); + addbyte(0x8b); /*MOV ECX, [RSI]*/ + addbyte(0x0e); + } + addbyte(0x67); /*LEA ESI, (EAX,ECX)*/ + addbyte(0x8d); + addbyte(0x34); + addbyte(0x08); + addbyte(0x89); /*MOV EDI, ESI*/ + addbyte(0xf7); + addbyte(0xc1); /*SHR ESI, 12*/ + addbyte(0xe8 | REG_ESI); + addbyte(12); + if (IS_32_ADDR(writelookup2)) { + addbyte(0x67); /*MOV RSI, writelookup2[ESI*8]*/ + addbyte(0x48); + addbyte(0x8b); + addbyte(0x34); + addbyte(0xf5); + addlong((uint32_t) (uintptr_t) writelookup2); + } else { + addbyte(0x48); /*MOV RDX, writelookup2*/ + addbyte(0xb8 | REG_EDX); + addquad((uint64_t) writelookup2); + addbyte(0x48); /*MOV RSI, [RDX+RSI*8]*/ + addbyte(0x8b); + addbyte(0x34); + addbyte(0xf2); + } + addbyte(0x83); /*CMP ESI, -1*/ + addbyte(0xf8 | REG_ESI); + addbyte(-1); + addbyte(0x74); /*JE slowpath*/ + addbyte(((host_reg & 8) ? 4 : 3) + 2); + if (host_reg & 8) { + addbyte(0x44); /*MOV [RDI+RSI],host_reg*/ + addbyte(0x88); + addbyte(0x04 | ((host_reg & 7) << 3)); + addbyte(REG_EDI | (REG_ESI << 3)); + } else { + addbyte(0x88); /*MOV [RDI+RSI],host_reg*/ + addbyte(0x04 | (host_reg << 3)); + addbyte(REG_EDI | (REG_ESI << 3)); + } + addbyte(0xeb); /*JMP done*/ + if (host_reg & 8) { + addbyte(2 + 2 + 3 + 12 + 4 + 6); + } else { + addbyte(2 + 2 + 2 + 12 + 4 + 6); + } + /*slowpath:*/ + addbyte(0x01); /*ADD ECX,EAX*/ + addbyte(0xc1); + load_param_1_reg_32(REG_ECX); + load_param_2_reg_32(host_reg); + call_long((uintptr_t) writemembl); + addbyte(0x80); /*CMP abrt, 0*/ + addbyte(0x7d); + addbyte((uint8_t) cpu_state_offset(abrt)); + addbyte(0); + addbyte(0x0f); /*JNE end*/ + addbyte(0x85); + addlong(BLOCK_EXIT_OFFSET - (block_pos + 4)); + /*done:*/ +} +static __inline void +MEM_STORE_ADDR_EA_W(x86seg *seg, int host_reg) +{ + if ((seg == &cpu_state.seg_ds && codegen_flat_ds && !(cpu_cur_status & CPU_STATUS_NOTFLATDS)) || (seg == &cpu_state.seg_ss && codegen_flat_ss && !(cpu_cur_status & CPU_STATUS_NOTFLATSS))) { + addbyte(0x31); /*XOR ECX, ECX*/ + addbyte(0xc9); + } else if (IS_32_ADDR(&seg->base)) { + addbyte(0x8b); /*MOVL ECX, seg->base*/ + addbyte(0x0c); + addbyte(0x25); + addlong((uint32_t) (uintptr_t) &seg->base); + } else { + addbyte(0x48); /*MOV RSI, &seg->base*/ + addbyte(0xb8 | REG_ESI); + addquad((uint64_t) &seg->base); + addbyte(0x8b); /*MOV ECX, [RSI]*/ + addbyte(0x0e); + } + addbyte(0x67); /*LEA ESI, (EAX,ECX)*/ + addbyte(0x8d); + addbyte(0x34); + addbyte(0x08); + addbyte(0x89); /*MOV EDI, ESI*/ + addbyte(0xf7); + addbyte(0xc1); /*SHR ESI, 12*/ + addbyte(0xe8 | REG_ESI); + addbyte(12); + addbyte(0xf7); /*TEST EDI, 1*/ + addbyte(0xc7); + addlong(1); + if (IS_32_ADDR(writelookup2)) { + addbyte(0x67); /*MOV RSI, writelookup2[ESI*8]*/ + addbyte(0x48); + addbyte(0x8b); + addbyte(0x34); + addbyte(0xf5); + addlong((uint32_t) (uintptr_t) writelookup2); + } else { + addbyte(0x48); /*MOV RDX, writelookup2*/ + addbyte(0xb8 | REG_EDX); + addquad((uint64_t) writelookup2); + addbyte(0x48); /*MOV RSI, [RDX+RSI*8]*/ + addbyte(0x8b); + addbyte(0x34); + addbyte(0xf2); + } + addbyte(0x75); /*JNE slowpath*/ + addbyte(3 + 2 + ((host_reg & 8) ? 5 : 4) + 2); + addbyte(0x83); /*CMP ESI, -1*/ + addbyte(0xf8 | REG_ESI); + addbyte(-1); + addbyte(0x74); /*JE slowpath*/ + addbyte(((host_reg & 8) ? 5 : 4) + 2); + if (host_reg & 8) { + addbyte(0x66); /*MOV [RDI+RSI],host_reg*/ + addbyte(0x44); + addbyte(0x89); + addbyte(0x04 | ((host_reg & 7) << 3)); + addbyte(REG_EDI | (REG_ESI << 3)); + } else { + addbyte(0x66); /*MOV [RDI+RSI],host_reg*/ + addbyte(0x89); + addbyte(0x04 | (host_reg << 3)); + addbyte(REG_EDI | (REG_ESI << 3)); + } + addbyte(0xeb); /*JMP done*/ + if (host_reg & 8) { + addbyte(2 + 2 + 3 + 12 + 4 + 6); + } else { + addbyte(2 + 2 + 2 + 12 + 4 + 6); + } + /*slowpath:*/ + addbyte(0x01); /*ADD ECX,EAX*/ + addbyte(0xc1); + load_param_1_reg_32(REG_ECX); + load_param_2_reg_32(host_reg); + call_long((uintptr_t) writememwl); + addbyte(0x80); /*CMP abrt, 0*/ + addbyte(0x7d); + addbyte((uint8_t) cpu_state_offset(abrt)); + addbyte(0); + addbyte(0x0f); /*JNE end*/ + addbyte(0x85); + addlong(BLOCK_EXIT_OFFSET - (block_pos + 4)); + /*done:*/ +} +static __inline void +MEM_STORE_ADDR_EA_L(x86seg *seg, int host_reg) +{ + if ((seg == &cpu_state.seg_ds && codegen_flat_ds && !(cpu_cur_status & CPU_STATUS_NOTFLATDS)) || (seg == &cpu_state.seg_ss && codegen_flat_ss && !(cpu_cur_status & CPU_STATUS_NOTFLATSS))) { + addbyte(0x31); /*XOR ECX, ECX*/ + addbyte(0xc9); + } else if (IS_32_ADDR(&seg->base)) { + addbyte(0x8b); /*MOVL ECX, seg->base*/ + addbyte(0x0c); + addbyte(0x25); + addlong((uint32_t) (uintptr_t) &seg->base); + } else { + addbyte(0x48); /*MOV RSI, &seg->base*/ + addbyte(0xb8 | REG_ESI); + addquad((uint64_t) &seg->base); + addbyte(0x8b); /*MOV ECX, [RSI]*/ + addbyte(0x0e); + } + addbyte(0x67); /*LEA ESI, (EAX,ECX)*/ + addbyte(0x8d); + addbyte(0x34); + addbyte(0x08); + addbyte(0x89); /*MOV EDI, ESI*/ + addbyte(0xf7); + addbyte(0xc1); /*SHR ESI, 12*/ + addbyte(0xe8 | REG_ESI); + addbyte(12); + addbyte(0xf7); /*TEST EDI, 3*/ + addbyte(0xc7); + addlong(3); + if (IS_32_ADDR(writelookup2)) { + addbyte(0x67); /*MOV RSI, writelookup2[ESI*8]*/ + addbyte(0x48); + addbyte(0x8b); + addbyte(0x34); + addbyte(0xf5); + addlong((uint32_t) (uintptr_t) writelookup2); + } else { + addbyte(0x48); /*MOV RDX, writelookup2*/ + addbyte(0xb8 | REG_EDX); + addquad((uint64_t) writelookup2); + addbyte(0x48); /*MOV RSI, [RDX+RSI*8]*/ + addbyte(0x8b); + addbyte(0x34); + addbyte(0xf2); + } + addbyte(0x75); /*JNE slowpath*/ + addbyte(3 + 2 + ((host_reg & 8) ? 4 : 3) + 2); + addbyte(0x83); /*CMP ESI, -1*/ + addbyte(0xf8 | REG_ESI); + addbyte(-1); + addbyte(0x74); /*JE slowpath*/ + addbyte(((host_reg & 8) ? 4 : 3) + 2); + if (host_reg & 8) { + addbyte(0x44); /*MOV -3[RDI+RSI],host_reg*/ + addbyte(0x89); + addbyte(0x04 | ((host_reg & 7) << 3)); + addbyte(REG_EDI | (REG_ESI << 3)); + } else { + addbyte(0x89); /*MOV -3[RDI+RSI],host_reg*/ + addbyte(0x04 | (host_reg << 3)); + addbyte(REG_EDI | (REG_ESI << 3)); + } + addbyte(0xeb); /*JMP done*/ + if (host_reg & 8) { + addbyte(2 + 2 + 3 + 12 + 4 + 6); + } else { + addbyte(2 + 2 + 2 + 12 + 4 + 6); + } + /*slowpath:*/ + addbyte(0x01); /*ADD ECX,EAX*/ + addbyte(0xc1); + load_param_1_reg_32(REG_ECX); + load_param_2_reg_32(host_reg); + call_long((uintptr_t) writememll); + addbyte(0x80); /*CMP abrt, 0*/ + addbyte(0x7d); + addbyte((uint8_t) cpu_state_offset(abrt)); + addbyte(0); + addbyte(0x0f); /*JNE end*/ + addbyte(0x85); + addlong(BLOCK_EXIT_OFFSET - (block_pos + 4)); + /*done:*/ +} +static __inline void +MEM_STORE_ADDR_EA_Q(x86seg *seg, int host_reg, int host_reg2) +{ + if ((seg == &cpu_state.seg_ds && codegen_flat_ds && !(cpu_cur_status & CPU_STATUS_NOTFLATDS)) || (seg == &cpu_state.seg_ss && codegen_flat_ss && !(cpu_cur_status & CPU_STATUS_NOTFLATSS))) { + addbyte(0x31); /*XOR ECX, ECX*/ + addbyte(0xc9); + } else if (IS_32_ADDR(&seg->base)) { + addbyte(0x8b); /*MOVL ECX, seg->base*/ + addbyte(0x0c); + addbyte(0x25); + addlong((uint32_t) (uintptr_t) &seg->base); + } else { + addbyte(0x48); /*MOV RSI, &seg->base*/ + addbyte(0xb8 | REG_ESI); + addquad((uint64_t) &seg->base); + addbyte(0x8b); /*MOV ECX, [RSI]*/ + addbyte(0x0e); + } + addbyte(0x67); /*LEA ESI, (EAX,ECX)*/ + addbyte(0x8d); + addbyte(0x34); + addbyte(0x08); + addbyte(0x89); /*MOV EDI, ESI*/ + addbyte(0xf7); + addbyte(0xc1); /*SHR ESI, 12*/ + addbyte(0xe8 | REG_ESI); + addbyte(12); + addbyte(0xf7); /*TEST EDI, 7*/ + addbyte(0xc7); + addlong(7); + if (IS_32_ADDR(writelookup2)) { + addbyte(0x67); /*MOV RSI, writelookup2[ESI*8]*/ + addbyte(0x48); + addbyte(0x8b); + addbyte(0x34); + addbyte(0xf5); + addlong((uint32_t) (uintptr_t) writelookup2); + } else { + addbyte(0x48); /*MOV RDX, writelookup2*/ + addbyte(0xb8 | REG_EDX); + addquad((uint64_t) writelookup2); + addbyte(0x48); /*MOV RSI, [RDX+RSI*8]*/ + addbyte(0x8b); + addbyte(0x34); + addbyte(0xf2); + } + addbyte(0x75); /*JNE slowpath*/ + addbyte(3 + 2 + 4 + 2); + addbyte(0x83); /*CMP ESI, -1*/ + addbyte(0xf8 | REG_ESI); + addbyte(-1); + addbyte(0x74); /*JE slowpath*/ + addbyte(4 + 2); + if (host_reg & 8) { + addbyte(0x4c); /*MOV [RDI+RSI],host_reg*/ + addbyte(0x89); + addbyte(0x04 | ((host_reg & 7) << 3)); + addbyte(REG_EDI | (REG_ESI << 3)); + } else { + addbyte(0x48); /*MOV [RDI+RSI],host_reg*/ + addbyte(0x89); + addbyte(0x04 | (host_reg << 3)); + addbyte(REG_EDI | (REG_ESI << 3)); + } + addbyte(0xeb); /*JMP done*/ + addbyte(2 + 2 + 3 + 12 + 4 + 6); + /*slowpath:*/ + addbyte(0x01); /*ADD ECX,EAX*/ + addbyte(0xc1); + load_param_1_reg_32(REG_ECX); + load_param_2_reg_64(host_reg); + call_long((uintptr_t) writememql); + addbyte(0x80); /*CMP abrt, 0*/ + addbyte(0x7d); + addbyte((uint8_t) cpu_state_offset(abrt)); + addbyte(0); + addbyte(0x0f); /*JNE end*/ + addbyte(0x85); + addlong(BLOCK_EXIT_OFFSET - (block_pos + 4)); + /*done:*/ +} + +static __inline void +MEM_STORE_ADDR_IMM_B(x86seg *seg, uint32_t addr, int host_reg) +{ + addbyte(0xb8); /*MOV EAX, addr*/ + addlong(addr); + MEM_STORE_ADDR_EA_B(seg, host_reg); +} +static __inline void +MEM_STORE_ADDR_IMM_W(x86seg *seg, uint32_t addr, int host_reg) +{ + addbyte(0xb8); /*MOV EAX, addr*/ + addlong(addr); + MEM_STORE_ADDR_EA_W(seg, host_reg); +} +static __inline void +MEM_STORE_ADDR_IMM_L(x86seg *seg, uint32_t addr, int host_reg) +{ + addbyte(0xb8); /*MOV EAX, addr*/ + addlong(addr); + MEM_STORE_ADDR_EA_L(seg, host_reg); +} + +static __inline void +STORE_HOST_REG_ADDR_BL(uintptr_t addr, int host_reg) +{ + int temp_reg = REG_ECX; + + if (host_reg_mapping[REG_ECX] != -1) + temp_reg = REG_EBX; + + if (host_reg & 0x10) { if (host_reg & 8) - addbyte(0x41); + addbyte(0x41); addbyte(0x0f); /*MOVZX temp_reg, host_reg*/ addbyte(0xb7); addbyte(0xc0 | (temp_reg << 3) | (host_reg & 7)); - if (addr >= (uintptr_t)&cpu_state && addr < ((uintptr_t)&cpu_state)+0x100) - { - addbyte(0x89); /*MOV addr, temp_reg*/ - addbyte(0x45 | (temp_reg << 3)); - addbyte((uint32_t)addr - (uint32_t)(uintptr_t)&cpu_state - 128); - } - else if (IS_32_ADDR(addr)) - { - addbyte(0x89); /*MOV addr, temp_reg*/ - addbyte(0x04 | (temp_reg << 3)); - addbyte(0x25); - addlong(addr); - } - else - { - addbyte(0x48); /*MOV RSI, addr*/ - addbyte(0xb8 | REG_ESI); - addquad((uint64_t)addr); - addbyte(0x89); /*MOV [RSI], temp_reg*/ - addbyte(0x06 | (temp_reg << 3)); - } -} -static inline void STORE_HOST_REG_ADDR_W(uintptr_t addr, int host_reg) -{ - if (addr >= (uintptr_t)&cpu_state && addr < ((uintptr_t)&cpu_state)+0x100) - { - addbyte(0x66); /*MOVW [addr],host_reg*/ - if (host_reg & 8) - addbyte(0x44); - addbyte(0x89); - addbyte(0x45 | ((host_reg & 7) << 3)); - addbyte((uint32_t)addr - (uint32_t)(uintptr_t)&cpu_state - 128); - } - else if (IS_32_ADDR(addr)) - { - addbyte(0x66); - if (host_reg & 8) - addbyte(0x44); - addbyte(0x89); /*MOVW addr,host_reg*/ - addbyte(0x04 | ((host_reg & 7) << 3)); - addbyte(0x25); - addlong(addr); - } - else - { - addbyte(0x48); /*MOV RSI, addr*/ - addbyte(0xb8 | REG_ESI); - addquad((uint64_t)addr); - - addbyte(0x66); - if (host_reg & 8) - addbyte(0x44); - addbyte(0x89); /*MOVW [RSI],host_reg*/ - addbyte(0x06 | ((host_reg & 7) << 3)); - } -} -static inline void STORE_HOST_REG_ADDR(uintptr_t addr, int host_reg) -{ - if (addr >= (uintptr_t)&cpu_state && addr < ((uintptr_t)&cpu_state)+0x100) - { - if (host_reg & 8) - addbyte(0x44); - addbyte(0x89); /*MOVL [addr],host_reg*/ - addbyte(0x45 | ((host_reg & 7) << 3)); - addbyte((uint32_t)addr - (uint32_t)(uintptr_t)&cpu_state - 128); - } - else if (IS_32_ADDR(addr)) - { - if (host_reg & 8) - addbyte(0x44); - addbyte(0x89); /*MOVL addr,host_reg*/ - addbyte(0x04 | ((host_reg & 7) << 3)); - addbyte(0x25); - addlong(addr); - } - else - { - addbyte(0x48); /*MOV RSI, addr*/ - addbyte(0xb8 | REG_ESI); - addquad((uint64_t)addr); - - if (host_reg & 8) - addbyte(0x44); - addbyte(0x89); /*MOVL [RSI],host_reg*/ - addbyte(0x06 | ((host_reg & 7) << 3)); - } -} - -static inline void AND_HOST_REG_B(int dst_reg, int src_reg) -{ - if (dst_reg & src_reg & 8) - { - if (dst_reg & 0x10) - { - addbyte(0x66); /*MOVW AX, src_reg*/ - addbyte(0x44); - addbyte(0x89); - addbyte(0xc0 | ((src_reg & 7) << 3)); - if (!(src_reg & 0x10)) - { - addbyte(0x66); /*SHL AX, 8*/ - addbyte(0xc1); - addbyte(0xe0); - addbyte(8); - } - addbyte(0x66); /*OR AX, 0x00ff*/ - addbyte(0x0d); - addword(0xff); - addbyte(0x66); /*ANDW dst_reg, AX*/ - addbyte(0x41); - addbyte(0x21); - addbyte(0xc0 | (dst_reg & 7)); - } - else if (src_reg & 0x10) - { - addbyte(0x66); /*MOVW AX, src_reg*/ - addbyte(0x44); - addbyte(0x89); - addbyte(0xc0 | ((src_reg & 7) << 3)); - addbyte(0x66); /*SHR AX, 8*/ - addbyte(0xc1); - addbyte(0xe8); - addbyte(8); - addbyte(0x41); /*ANDB dst_reg, AL*/ - addbyte(0x20); - addbyte(0xc0 | (dst_reg & 7)); - } - else - { - addbyte(0x45); /*ANDB dst_reg, src_reg*/ - addbyte(0x20); - addbyte(0xc0 | (dst_reg & 7) | ((src_reg & 7) << 3)); - } - } - else if (dst_reg & 8) - { - if (dst_reg & 0x10) - { - addbyte(0x66); /*SHL src_reg, 8*/ - addbyte(0xc1); - addbyte(0xe0 | src_reg); - addbyte(0x08); - addbyte(0x66); /*OR src_reg, 0xff*/ - addbyte(0x81); - addbyte(0xc8 | src_reg); - addword(0xff); - addbyte(0x66); /*ANDW dst_reg, src_reg*/ - addbyte(0x41); - addbyte(0x21); - addbyte(0xc0 | (dst_reg & 7) | ((src_reg & 7) << 3)); - } - else - { - addbyte(0x41); /*ANDB dst_reg, src_reg*/ - addbyte(0x20); - addbyte(0xc0 | (dst_reg & 7) | ((src_reg & 7) << 3)); - } - } - else if (src_reg & 8) - { - if (dst_reg & 0x10) - { - addbyte(0xc1); /*SHR dst_reg, 8*/ - addbyte(0xe8 | (dst_reg & 7)); - addbyte(8); - } - if (src_reg & 0x10) - { - addbyte(0x41); /*MOVZX EBX, src_reg*/ - addbyte(0x0f); - addbyte(0xb7); - addbyte(0xd8 | (src_reg & 7)); - addbyte(0xc1); /*SHR EBX, 8*/ - addbyte(0xeb); - addbyte(8); - addbyte(0x20); /*ANDB dst_reg, EBX*/ - addbyte(0xd8 | (dst_reg & 7)); - } - else - { - addbyte(0x44); /*ANDB dst_reg, src_reg*/ - addbyte(0x20); - addbyte(0xc0 | (dst_reg & 7) | ((src_reg & 7) << 3)); - } - } - else - { - if (dst_reg & 0x10) - { - addbyte(0xc1); /*SHR dst_reg, 8*/ - addbyte(0xe8 | (dst_reg & 7)); - addbyte(8); - } - if (src_reg & 0x10) - { - addbyte(0x0f); /*MOVZX EBX, src_reg*/ - addbyte(0xb7); - addbyte(0xd8 | (src_reg & 7)); - addbyte(0xc1); /*SHR EBX, 8*/ - addbyte(0xeb); - addbyte(8); - addbyte(0x20); /*ANDB dst_reg, EBX*/ - addbyte(0xd8 | (dst_reg & 7)); - } - else - { - addbyte(0x20); /*ANDB dst_reg, src_reg*/ - addbyte(0xc0 | (dst_reg & 7) | ((src_reg & 7) << 3)); - } - } -} -static inline void AND_HOST_REG_W(int dst_reg, int src_reg) -{ - if (dst_reg & src_reg & 8) - { - addbyte(0x66); /*ANDW dst_reg, src_reg*/ - addbyte(0x45); - addbyte(0x21); - addbyte(0xc0 | (dst_reg & 7) | ((src_reg & 7) << 3)); - } - else if (dst_reg & 8) - { - addbyte(0x66); /*ANDW dst_reg, src_reg*/ - addbyte(0x41); - addbyte(0x21); - addbyte(0xc0 | (dst_reg & 7) | ((src_reg & 7) << 3)); - } - else if (src_reg & 8) - { - addbyte(0x66); /*ANDW dst_reg, src_reg*/ - addbyte(0x44); - addbyte(0x21); - addbyte(0xc0 | (dst_reg & 7) | ((src_reg & 7) << 3)); - } - else - { - addbyte(0x66); /*ANDW dst_reg, src_reg*/ - addbyte(0x21); - addbyte(0xc0 | (dst_reg & 7) | ((src_reg & 7) << 3)); - } -} -static inline void AND_HOST_REG_L(int dst_reg, int src_reg) -{ - if (dst_reg & src_reg & 8) - { - addbyte(0x45); /*ANDL dst_reg, src_reg*/ - addbyte(0x21); - addbyte(0xc0 | (dst_reg & 7) | ((src_reg & 7) << 3)); - } - else if (dst_reg & 8) - { - addbyte(0x41); /*ANDL dst_reg, src_reg*/ - addbyte(0x21); - addbyte(0xc0 | (dst_reg & 7) | ((src_reg & 7) << 3)); - } - else if (src_reg & 8) - { - addbyte(0x44); /*ANDL dst_reg, src_reg*/ - addbyte(0x21); - addbyte(0xc0 | (dst_reg & 7) | ((src_reg & 7) << 3)); - } - else - { - addbyte(0x21); /*ANDL dst_reg, src_reg*/ - addbyte(0xc0 | (dst_reg & 7) | ((src_reg & 7) << 3)); - } -} -static inline void AND_HOST_REG_IMM(int host_reg, uint32_t imm) -{ - if (host_reg & 0x10) - { - addbyte(0x66); /*ANDW host_reg, imm<<8*/ - if (host_reg & 8) - addbyte(0x41); - addbyte(0x81); - addbyte(0xe0 | (host_reg & 7)); - addword((imm << 8) | 0xff); - } - else - { - if (host_reg & 8) - addbyte(0x41); - addbyte(0x81); /*ANDL host_reg, imm*/ - addbyte(0xe0 | (host_reg & 7)); - addlong(imm); - } -} - -static inline int TEST_HOST_REG_B(int dst_reg, int src_reg) -{ - if (dst_reg & 8) - { - addbyte(0x44); /*MOV EDX, dst_reg*/ - addbyte(0x89); - addbyte(0xc0 | ((dst_reg & 7) << 3) | REG_EDX); - - dst_reg = (dst_reg & 0x10) | REG_EDX; - } - - AND_HOST_REG_B(dst_reg, src_reg); - - return dst_reg & ~0x10; -} -static inline int TEST_HOST_REG_W(int dst_reg, int src_reg) -{ - if (dst_reg & 8) - { - addbyte(0x44); /*MOV EDX, dst_reg*/ - addbyte(0x89); - addbyte(0xc0 | ((dst_reg & 7) << 3) | REG_EDX); - - dst_reg = REG_EDX; - } - - AND_HOST_REG_W(dst_reg, src_reg); - - return dst_reg; -} -static inline int TEST_HOST_REG_L(int dst_reg, int src_reg) -{ - if (dst_reg & 8) - { - addbyte(0x44); /*MOV EDX, dst_reg*/ - addbyte(0x89); - addbyte(0xc0 | ((dst_reg & 7) << 3) | REG_EDX); - - dst_reg = REG_EDX; - } - - AND_HOST_REG_L(dst_reg, src_reg); - - return dst_reg; -} -static inline int TEST_HOST_REG_IMM(int host_reg, uint32_t imm) -{ + addbyte(0xc1); /*SHR temp_reg, 8*/ + addbyte(0xe8 | temp_reg); + addbyte(8); + } else { if (host_reg & 8) - { - addbyte(0x44); /*MOV EDX, host_reg*/ - addbyte(0x89); - addbyte(0xc0 | REG_EDX | ((host_reg & 7) << 3)); - host_reg = REG_EDX | (host_reg & 0x10); - } - if (host_reg & 0x10) - { - addbyte(0x66); /*ANDW host_reg, imm<<8*/ - addbyte(0x81); - addbyte(0xe0 | (host_reg & 7)); - addword((imm << 8) | 0xff); - } - else - { - addbyte(0x81); /*ANDL host_reg, imm*/ - addbyte(0xe0 | (host_reg & 7)); - addlong(imm); - } - - return host_reg; + addbyte(0x41); + addbyte(0x0f); /*MOVZX temp_reg, host_reg*/ + addbyte(0xb6); + addbyte(0xc0 | (temp_reg << 3) | (host_reg & 7)); + } + if (addr >= (uintptr_t) &cpu_state && addr < ((uintptr_t) &cpu_state) + 0x100) { + addbyte(0x89); /*MOV addr, temp_reg*/ + addbyte(0x45 | (temp_reg << 3)); + addbyte((uint32_t) addr - (uint32_t) (uintptr_t) &cpu_state - 128); + } else if (IS_32_ADDR(addr)) { + addbyte(0x89); /*MOV addr, temp_reg*/ + addbyte(0x04 | (temp_reg << 3)); + addbyte(0x25); + addlong(addr); + } else { + addbyte(0x48); /*MOV RSI, addr*/ + addbyte(0xb8 | REG_ESI); + addquad((uint64_t) addr); + addbyte(0x89); /*MOV [RSI], temp_reg*/ + addbyte(0x06 | (temp_reg << 3)); + } +} +static __inline void +STORE_HOST_REG_ADDR_WL(uintptr_t addr, int host_reg) +{ + int temp_reg = REG_ECX; + + if (host_reg_mapping[REG_ECX] != -1) + temp_reg = REG_EBX; + + if (host_reg & 8) + addbyte(0x41); + addbyte(0x0f); /*MOVZX temp_reg, host_reg*/ + addbyte(0xb7); + addbyte(0xc0 | (temp_reg << 3) | (host_reg & 7)); + if (addr >= (uintptr_t) &cpu_state && addr < ((uintptr_t) &cpu_state) + 0x100) { + addbyte(0x89); /*MOV addr, temp_reg*/ + addbyte(0x45 | (temp_reg << 3)); + addbyte((uint32_t) addr - (uint32_t) (uintptr_t) &cpu_state - 128); + } else if (IS_32_ADDR(addr)) { + addbyte(0x89); /*MOV addr, temp_reg*/ + addbyte(0x04 | (temp_reg << 3)); + addbyte(0x25); + addlong(addr); + } else { + addbyte(0x48); /*MOV RSI, addr*/ + addbyte(0xb8 | REG_ESI); + addquad((uint64_t) addr); + addbyte(0x89); /*MOV [RSI], temp_reg*/ + addbyte(0x06 | (temp_reg << 3)); + } +} +static __inline void +STORE_HOST_REG_ADDR_W(uintptr_t addr, int host_reg) +{ + if (addr >= (uintptr_t) &cpu_state && addr < ((uintptr_t) &cpu_state) + 0x100) { + addbyte(0x66); /*MOVW [addr],host_reg*/ + if (host_reg & 8) + addbyte(0x44); + addbyte(0x89); + addbyte(0x45 | ((host_reg & 7) << 3)); + addbyte((uint32_t) addr - (uint32_t) (uintptr_t) &cpu_state - 128); + } else if (IS_32_ADDR(addr)) { + addbyte(0x66); + if (host_reg & 8) + addbyte(0x44); + addbyte(0x89); /*MOVW addr,host_reg*/ + addbyte(0x04 | ((host_reg & 7) << 3)); + addbyte(0x25); + addlong(addr); + } else { + addbyte(0x48); /*MOV RSI, addr*/ + addbyte(0xb8 | REG_ESI); + addquad((uint64_t) addr); + + addbyte(0x66); + if (host_reg & 8) + addbyte(0x44); + addbyte(0x89); /*MOVW [RSI],host_reg*/ + addbyte(0x06 | ((host_reg & 7) << 3)); + } +} +static __inline void +STORE_HOST_REG_ADDR(uintptr_t addr, int host_reg) +{ + if (addr >= (uintptr_t) &cpu_state && addr < ((uintptr_t) &cpu_state) + 0x100) { + if (host_reg & 8) + addbyte(0x44); + addbyte(0x89); /*MOVL [addr],host_reg*/ + addbyte(0x45 | ((host_reg & 7) << 3)); + addbyte((uint32_t) addr - (uint32_t) (uintptr_t) &cpu_state - 128); + } else if (IS_32_ADDR(addr)) { + if (host_reg & 8) + addbyte(0x44); + addbyte(0x89); /*MOVL addr,host_reg*/ + addbyte(0x04 | ((host_reg & 7) << 3)); + addbyte(0x25); + addlong(addr); + } else { + addbyte(0x48); /*MOV RSI, addr*/ + addbyte(0xb8 | REG_ESI); + addquad((uint64_t) addr); + + if (host_reg & 8) + addbyte(0x44); + addbyte(0x89); /*MOVL [RSI],host_reg*/ + addbyte(0x06 | ((host_reg & 7) << 3)); + } } -static inline void OR_HOST_REG_B(int dst_reg, int src_reg) +static __inline void +AND_HOST_REG_B(int dst_reg, int src_reg) { - if (dst_reg & src_reg & 8) - { - if (dst_reg & 0x10) - { - addbyte(0x66); /*MOVW AX, src_reg*/ - addbyte(0x44); - addbyte(0x89); - addbyte(0xc0 | ((src_reg & 7) << 3)); - if (!(src_reg & 0x10)) - { - addbyte(0x66); /*SHL AX, 8*/ - addbyte(0xc1); - addbyte(0xe0); - addbyte(8); - } - else - { - addbyte(0x66); /*AND AX, 0xff00*/ - addbyte(0x25); - addword(0xff00); - } - addbyte(0x66); /*ORW dst_reg, AX*/ - addbyte(0x41); - addbyte(0x09); - addbyte(0xc0 | (dst_reg & 7)); - } - else if (src_reg & 0x10) - { - addbyte(0x66); /*MOVW AX, src_reg*/ - addbyte(0x44); - addbyte(0x89); - addbyte(0xc0 | ((src_reg & 7) << 3)); - addbyte(0x66); /*SHR AX, 8*/ - addbyte(0xc1); - addbyte(0xe8); - addbyte(8); - addbyte(0x41); /*ORB dst_reg, AL*/ - addbyte(0x08); - addbyte(0xc0 | (dst_reg & 7)); - } - else - { - addbyte(0x45); /*ORB dst_reg, src_reg*/ - addbyte(0x08); - addbyte(0xc0 | (dst_reg & 7) | ((src_reg & 7) << 3)); - } + if (dst_reg & src_reg & 8) { + if (dst_reg & 0x10) { + addbyte(0x66); /*MOVW AX, src_reg*/ + addbyte(0x44); + addbyte(0x89); + addbyte(0xc0 | ((src_reg & 7) << 3)); + if (!(src_reg & 0x10)) { + addbyte(0x66); /*SHL AX, 8*/ + addbyte(0xc1); + addbyte(0xe0); + addbyte(8); + } + addbyte(0x66); /*OR AX, 0x00ff*/ + addbyte(0x0d); + addword(0xff); + addbyte(0x66); /*ANDW dst_reg, AX*/ + addbyte(0x41); + addbyte(0x21); + addbyte(0xc0 | (dst_reg & 7)); + } else if (src_reg & 0x10) { + addbyte(0x66); /*MOVW AX, src_reg*/ + addbyte(0x44); + addbyte(0x89); + addbyte(0xc0 | ((src_reg & 7) << 3)); + addbyte(0x66); /*SHR AX, 8*/ + addbyte(0xc1); + addbyte(0xe8); + addbyte(8); + addbyte(0x41); /*ANDB dst_reg, AL*/ + addbyte(0x20); + addbyte(0xc0 | (dst_reg & 7)); + } else { + addbyte(0x45); /*ANDB dst_reg, src_reg*/ + addbyte(0x20); + addbyte(0xc0 | (dst_reg & 7) | ((src_reg & 7) << 3)); } - else if (dst_reg & 8) - { - if (dst_reg & 0x10) - { - addbyte(0x66); /*SHL src_reg, 8*/ - addbyte(0xc1); - addbyte(0xe0 | src_reg); - addbyte(0x08); - addbyte(0x66); /*ORW dst_reg, src_reg*/ - addbyte(0x41); - addbyte(0x09); - addbyte(0xc0 | (dst_reg & 7) | ((src_reg & 7) << 3)); - } - else - { - addbyte(0x41); /*ORB dst_reg, src_reg*/ - addbyte(0x08); - addbyte(0xc0 | (dst_reg & 7) | ((src_reg & 7) << 3)); - } + } else if (dst_reg & 8) { + if (dst_reg & 0x10) { + addbyte(0x66); /*SHL src_reg, 8*/ + addbyte(0xc1); + addbyte(0xe0 | src_reg); + addbyte(0x08); + addbyte(0x66); /*OR src_reg, 0xff*/ + addbyte(0x81); + addbyte(0xc8 | src_reg); + addword(0xff); + addbyte(0x66); /*ANDW dst_reg, src_reg*/ + addbyte(0x41); + addbyte(0x21); + addbyte(0xc0 | (dst_reg & 7) | ((src_reg & 7) << 3)); + } else { + addbyte(0x41); /*ANDB dst_reg, src_reg*/ + addbyte(0x20); + addbyte(0xc0 | (dst_reg & 7) | ((src_reg & 7) << 3)); } - else if (src_reg & 8) - { - if (dst_reg & 0x10) - { - addbyte(0xc1); /*SHR dst_reg, 8*/ - addbyte(0xe8 | (dst_reg & 7)); - addbyte(8); - } - if (src_reg & 0x10) - { - addbyte(0x41); /*MOVZX EBX, src_reg*/ - addbyte(0x0f); - addbyte(0xb7); - addbyte(0xd8 | (src_reg & 7)); - addbyte(0xc1); /*SHR EBX, 8*/ - addbyte(0xeb); - addbyte(8); - addbyte(0x08); /*ORB dst_reg, EBX*/ - addbyte(0xd8 | (dst_reg & 7)); - } - else - { - addbyte(0x44); /*ORB dst_reg, src_reg*/ - addbyte(0x08); - addbyte(0xc0 | (dst_reg & 7) | ((src_reg & 7) << 3)); - } + } else if (src_reg & 8) { + if (dst_reg & 0x10) { + addbyte(0xc1); /*SHR dst_reg, 8*/ + addbyte(0xe8 | (dst_reg & 7)); + addbyte(8); } - else - { - if (dst_reg & 0x10) - { - addbyte(0xc1); /*SHR dst_reg, 8*/ - addbyte(0xe8 | (dst_reg & 7)); - addbyte(8); - } - if (src_reg & 0x10) - { - addbyte(0x0f); /*MOVZX EBX, src_reg*/ - addbyte(0xb7); - addbyte(0xd8 | (src_reg & 7)); - addbyte(0xc1); /*SHR EBX, 8*/ - addbyte(0xeb); - addbyte(8); - addbyte(0x08); /*ORB dst_reg, EBX*/ - addbyte(0xd8 | (dst_reg & 7)); - } - else - { - addbyte(0x08); /*ORB dst_reg, src_reg*/ - addbyte(0xc0 | (dst_reg & 7) | ((src_reg & 7) << 3)); - } + if (src_reg & 0x10) { + addbyte(0x41); /*MOVZX EBX, src_reg*/ + addbyte(0x0f); + addbyte(0xb7); + addbyte(0xd8 | (src_reg & 7)); + addbyte(0xc1); /*SHR EBX, 8*/ + addbyte(0xeb); + addbyte(8); + addbyte(0x20); /*ANDB dst_reg, EBX*/ + addbyte(0xd8 | (dst_reg & 7)); + } else { + addbyte(0x44); /*ANDB dst_reg, src_reg*/ + addbyte(0x20); + addbyte(0xc0 | (dst_reg & 7) | ((src_reg & 7) << 3)); } + } else { + if (dst_reg & 0x10) { + addbyte(0xc1); /*SHR dst_reg, 8*/ + addbyte(0xe8 | (dst_reg & 7)); + addbyte(8); + } + if (src_reg & 0x10) { + addbyte(0x0f); /*MOVZX EBX, src_reg*/ + addbyte(0xb7); + addbyte(0xd8 | (src_reg & 7)); + addbyte(0xc1); /*SHR EBX, 8*/ + addbyte(0xeb); + addbyte(8); + addbyte(0x20); /*ANDB dst_reg, EBX*/ + addbyte(0xd8 | (dst_reg & 7)); + } else { + addbyte(0x20); /*ANDB dst_reg, src_reg*/ + addbyte(0xc0 | (dst_reg & 7) | ((src_reg & 7) << 3)); + } + } } -static inline void OR_HOST_REG_W(int dst_reg, int src_reg) +static __inline void +AND_HOST_REG_W(int dst_reg, int src_reg) { - if (dst_reg & src_reg & 8) - { - addbyte(0x66); /*ORW dst_reg, src_reg*/ - addbyte(0x45); - addbyte(0x09); - addbyte(0xc0 | (dst_reg & 7) | ((src_reg & 7) << 3)); - } - else if (dst_reg & 8) - { - addbyte(0x66); /*ORW dst_reg, src_reg*/ - addbyte(0x41); - addbyte(0x09); - addbyte(0xc0 | (dst_reg & 7) | ((src_reg & 7) << 3)); - } - else if (src_reg & 8) - { - addbyte(0x66); /*ORW dst_reg, src_reg*/ - addbyte(0x44); - addbyte(0x09); - addbyte(0xc0 | (dst_reg & 7) | ((src_reg & 7) << 3)); - } - else - { - addbyte(0x66); /*ORW dst_reg, src_reg*/ - addbyte(0x09); - addbyte(0xc0 | (dst_reg & 7) | ((src_reg & 7) << 3)); - } + if (dst_reg & src_reg & 8) { + addbyte(0x66); /*ANDW dst_reg, src_reg*/ + addbyte(0x45); + addbyte(0x21); + addbyte(0xc0 | (dst_reg & 7) | ((src_reg & 7) << 3)); + } else if (dst_reg & 8) { + addbyte(0x66); /*ANDW dst_reg, src_reg*/ + addbyte(0x41); + addbyte(0x21); + addbyte(0xc0 | (dst_reg & 7) | ((src_reg & 7) << 3)); + } else if (src_reg & 8) { + addbyte(0x66); /*ANDW dst_reg, src_reg*/ + addbyte(0x44); + addbyte(0x21); + addbyte(0xc0 | (dst_reg & 7) | ((src_reg & 7) << 3)); + } else { + addbyte(0x66); /*ANDW dst_reg, src_reg*/ + addbyte(0x21); + addbyte(0xc0 | (dst_reg & 7) | ((src_reg & 7) << 3)); + } } -static inline void OR_HOST_REG_L(int dst_reg, int src_reg) +static __inline void +AND_HOST_REG_L(int dst_reg, int src_reg) { - if (dst_reg & src_reg & 8) - { - addbyte(0x45); /*ORL dst_reg, src_reg*/ - addbyte(0x09); - addbyte(0xc0 | (dst_reg & 7) | ((src_reg & 7) << 3)); - } - else if (dst_reg & 8) - { - addbyte(0x41); /*ORL dst_reg, src_reg*/ - addbyte(0x09); - addbyte(0xc0 | (dst_reg & 7) | ((src_reg & 7) << 3)); - } - else if (src_reg & 8) - { - addbyte(0x44); /*ORL dst_reg, src_reg*/ - addbyte(0x09); - addbyte(0xc0 | (dst_reg & 7) | ((src_reg & 7) << 3)); - } - else - { - addbyte(0x09); /*ORW dst_reg, src_reg*/ - addbyte(0xc0 | (dst_reg & 7) | ((src_reg & 7) << 3)); - } + if (dst_reg & src_reg & 8) { + addbyte(0x45); /*ANDL dst_reg, src_reg*/ + addbyte(0x21); + addbyte(0xc0 | (dst_reg & 7) | ((src_reg & 7) << 3)); + } else if (dst_reg & 8) { + addbyte(0x41); /*ANDL dst_reg, src_reg*/ + addbyte(0x21); + addbyte(0xc0 | (dst_reg & 7) | ((src_reg & 7) << 3)); + } else if (src_reg & 8) { + addbyte(0x44); /*ANDL dst_reg, src_reg*/ + addbyte(0x21); + addbyte(0xc0 | (dst_reg & 7) | ((src_reg & 7) << 3)); + } else { + addbyte(0x21); /*ANDL dst_reg, src_reg*/ + addbyte(0xc0 | (dst_reg & 7) | ((src_reg & 7) << 3)); + } } -static inline void OR_HOST_REG_IMM(int host_reg, uint32_t imm) +static __inline void +AND_HOST_REG_IMM(int host_reg, uint32_t imm) { - if (host_reg & 0x10) - { - addbyte(0x66); /*ORW host_reg, imm<<8*/ - addbyte(0x41); - addbyte(0x81); - addbyte(0xc8 | (host_reg & 7)); - addword(imm << 8); - } - else if (host_reg & 8) - { - addbyte(0x41); /*ORL host_reg, imm*/ - addbyte(0x81); - addbyte(0xc8 | (host_reg & 7)); - addlong(imm); - } - else - { - addbyte(0x81); /*ORL host_reg, imm*/ - addbyte(0xc8 | (host_reg & 7)); - addlong(imm); - } + if (host_reg & 0x10) { + addbyte(0x66); /*ANDW host_reg, imm<<8*/ + if (host_reg & 8) + addbyte(0x41); + addbyte(0x81); + addbyte(0xe0 | (host_reg & 7)); + addword((imm << 8) | 0xff); + } else { + if (host_reg & 8) + addbyte(0x41); + addbyte(0x81); /*ANDL host_reg, imm*/ + addbyte(0xe0 | (host_reg & 7)); + addlong(imm); + } } -static inline void XOR_HOST_REG_B(int dst_reg, int src_reg) +static __inline int +TEST_HOST_REG_B(int dst_reg, int src_reg) { - if (dst_reg & src_reg & 8) - { - if (dst_reg & 0x10) - { - addbyte(0x66); /*MOVW AX, src_reg*/ - addbyte(0x44); - addbyte(0x89); - addbyte(0xc0 | ((src_reg & 7) << 3)); - if (!(src_reg & 0x10)) - { - addbyte(0x66); /*SHL AX, 8*/ - addbyte(0xc1); - addbyte(0xe0); - addbyte(8); - } - else - { - addbyte(0x66); /*AND AX, 0xff00*/ - addbyte(0x25); - addword(0xff00); - } - addbyte(0x66); /*XORW dst_reg, AX*/ - addbyte(0x41); - addbyte(0x31); - addbyte(0xc0 | (dst_reg & 7)); - } - else if (src_reg & 0x10) - { - addbyte(0x66); /*MOVW AX, src_reg*/ - addbyte(0x44); - addbyte(0x89); - addbyte(0xc0 | ((src_reg & 7) << 3)); - addbyte(0x66); /*SHR AX, 8*/ - addbyte(0xc1); - addbyte(0xe8); - addbyte(8); - addbyte(0x41); /*XORB dst_reg, AL*/ - addbyte(0x30); - addbyte(0xc0 | (dst_reg & 7)); - } - else - { - addbyte(0x45); /*XORB dst_reg, src_reg*/ - addbyte(0x30); - addbyte(0xc0 | (dst_reg & 7) | ((src_reg & 7) << 3)); - } - } - else if (dst_reg & 8) - { - if (dst_reg & 0x10) - { - addbyte(0x66); /*SHL src_reg, 8*/ - addbyte(0xc1); - addbyte(0xe0 | src_reg); - addbyte(0x08); - addbyte(0x66); /*XORW dst_reg, src_reg*/ - addbyte(0x41); - addbyte(0x31); - addbyte(0xc0 | (dst_reg & 7) | ((src_reg & 7) << 3)); - } - else - { - addbyte(0x41); /*XORB dst_reg, src_reg*/ - addbyte(0x30); - addbyte(0xc0 | (dst_reg & 7) | ((src_reg & 7) << 3)); - } - } - else if (src_reg & 8) - { - if (dst_reg & 0x10) - { - addbyte(0xc1); /*SHR dst_reg, 8*/ - addbyte(0xe8 | (dst_reg & 7)); - addbyte(8); - } - if (src_reg & 0x10) - { - addbyte(0x41); /*MOVZX EBX, src_reg*/ - addbyte(0x0f); - addbyte(0xb7); - addbyte(0xd8 | (src_reg & 7)); - addbyte(0xc1); /*SHR EBX, 8*/ - addbyte(0xeb); - addbyte(8); - addbyte(0x30); /*XORB dst_reg, EBX*/ - addbyte(0xd8 | (dst_reg & 7)); - } - else - { - addbyte(0x44); /*XORB dst_reg, src_reg*/ - addbyte(0x30); - addbyte(0xc0 | (dst_reg & 7) | ((src_reg & 7) << 3)); - } - } - else - { - if (dst_reg & 0x10) - { - addbyte(0xc1); /*SHR dst_reg, 8*/ - addbyte(0xe8 | (dst_reg & 7)); - addbyte(8); - } - if (src_reg & 0x10) - { - addbyte(0x0f); /*MOVZX EBX, src_reg*/ - addbyte(0xb7); - addbyte(0xd8 | (src_reg & 7)); - addbyte(0xc1); /*SHR EBX, 8*/ - addbyte(0xeb); - addbyte(8); - addbyte(0x30); /*XORB dst_reg, EBX*/ - addbyte(0xd8 | (dst_reg & 7)); - } - else - { - addbyte(0x30); /*XORB dst_reg, src_reg*/ - addbyte(0xc0 | (dst_reg & 7) | ((src_reg & 7) << 3)); - } - } + if (dst_reg & 8) { + addbyte(0x44); /*MOV EDX, dst_reg*/ + addbyte(0x89); + addbyte(0xc0 | ((dst_reg & 7) << 3) | REG_EDX); + + dst_reg = (dst_reg & 0x10) | REG_EDX; + } + + AND_HOST_REG_B(dst_reg, src_reg); + + return dst_reg & ~0x10; } -static inline void XOR_HOST_REG_W(int dst_reg, int src_reg) +static __inline int +TEST_HOST_REG_W(int dst_reg, int src_reg) { - if (dst_reg & src_reg & 8) - { - addbyte(0x66); /*XORW dst_reg, src_reg*/ - addbyte(0x45); - addbyte(0x31); - addbyte(0xc0 | (dst_reg & 7) | ((src_reg & 7) << 3)); - } - else if (dst_reg & 8) - { - addbyte(0x66); /*XORW dst_reg, src_reg*/ - addbyte(0x41); - addbyte(0x31); - addbyte(0xc0 | (dst_reg & 7) | ((src_reg & 7) << 3)); - } - else if (src_reg & 8) - { - addbyte(0x66); /*XORW dst_reg, src_reg*/ - addbyte(0x44); - addbyte(0x31); - addbyte(0xc0 | (dst_reg & 7) | ((src_reg & 7) << 3)); - } - else - { - addbyte(0x66); /*XORW dst_reg, src_reg*/ - addbyte(0x31); - addbyte(0xc0 | (dst_reg & 7) | ((src_reg & 7) << 3)); - } + if (dst_reg & 8) { + addbyte(0x44); /*MOV EDX, dst_reg*/ + addbyte(0x89); + addbyte(0xc0 | ((dst_reg & 7) << 3) | REG_EDX); + + dst_reg = REG_EDX; + } + + AND_HOST_REG_W(dst_reg, src_reg); + + return dst_reg; } -static inline void XOR_HOST_REG_L(int dst_reg, int src_reg) +static __inline int +TEST_HOST_REG_L(int dst_reg, int src_reg) { - if (dst_reg & src_reg & 8) - { - addbyte(0x45); /*XORL dst_reg, src_reg*/ - addbyte(0x31); - addbyte(0xc0 | (dst_reg & 7) | ((src_reg & 7) << 3)); - } - else if (dst_reg & 8) - { - addbyte(0x41); /*XORL dst_reg, src_reg*/ - addbyte(0x31); - addbyte(0xc0 | (dst_reg & 7) | ((src_reg & 7) << 3)); - } - else if (src_reg & 8) - { - addbyte(0x44); /*XORW dst_reg, src_reg*/ - addbyte(0x31); - addbyte(0xc0 | (dst_reg & 7) | ((src_reg & 7) << 3)); - } - else - { - addbyte(0x31); /*XORW dst_reg, src_reg*/ - addbyte(0xc0 | (dst_reg & 7) | ((src_reg & 7) << 3)); - } + if (dst_reg & 8) { + addbyte(0x44); /*MOV EDX, dst_reg*/ + addbyte(0x89); + addbyte(0xc0 | ((dst_reg & 7) << 3) | REG_EDX); + + dst_reg = REG_EDX; + } + + AND_HOST_REG_L(dst_reg, src_reg); + + return dst_reg; } -static inline void XOR_HOST_REG_IMM(int host_reg, uint32_t imm) +static __inline int +TEST_HOST_REG_IMM(int host_reg, uint32_t imm) { - if (host_reg & 0x10) - { - addbyte(0x66); /*ORW host_reg, imm<<8*/ - addbyte(0x41); - addbyte(0x81); - addbyte(0xf0 | (host_reg & 7)); - addword(imm << 8); - } - else if (host_reg & 8) - { - addbyte(0x41); /*ORL host_reg, imm*/ - addbyte(0x81); - addbyte(0xf0 | (host_reg & 7)); - addlong(imm); - } - else - { - addbyte(0x81); /*ORL host_reg, imm*/ - addbyte(0xf0 | (host_reg & 7)); - addlong(imm); - } + if (host_reg & 8) { + addbyte(0x44); /*MOV EDX, host_reg*/ + addbyte(0x89); + addbyte(0xc0 | REG_EDX | ((host_reg & 7) << 3)); + host_reg = REG_EDX | (host_reg & 0x10); + } + if (host_reg & 0x10) { + addbyte(0x66); /*ANDW host_reg, imm<<8*/ + addbyte(0x81); + addbyte(0xe0 | (host_reg & 7)); + addword((imm << 8) | 0xff); + } else { + addbyte(0x81); /*ANDL host_reg, imm*/ + addbyte(0xe0 | (host_reg & 7)); + addlong(imm); + } + + return host_reg; } -static inline void ADD_HOST_REG_B(int dst_reg, int src_reg) +static __inline void +OR_HOST_REG_B(int dst_reg, int src_reg) { - if (dst_reg & src_reg & 8) - { - if (dst_reg & 0x10) - { - addbyte(0x66); /*MOVW AX, src_reg*/ - addbyte(0x44); - addbyte(0x89); - addbyte(0xc0 | ((src_reg & 7) << 3)); - if (!(src_reg & 0x10)) - { - addbyte(0x66); /*SHL AX, 8*/ - addbyte(0xc1); - addbyte(0xe0); - addbyte(8); - } - else - { - addbyte(0x66); /*AND AX, 0xff00*/ - addbyte(0x25); - addword(0xff00); - } - addbyte(0x66); /*ADDW dst_reg, AX*/ - addbyte(0x41); - addbyte(0x01); - addbyte(0xc0 | (dst_reg & 7)); - } - else if (src_reg & 0x10) - { - addbyte(0x66); /*MOVW AX, src_reg*/ - addbyte(0x44); - addbyte(0x89); - addbyte(0xc0 | ((src_reg & 7) << 3)); - addbyte(0x66); /*SHR AX, 8*/ - addbyte(0xc1); - addbyte(0xe8); - addbyte(8); - addbyte(0x41); /*ADDB dst_reg, AL*/ - addbyte(0x00); - addbyte(0xc0 | (dst_reg & 7)); - } - else - { - addbyte(0x45); /*ADDB dst_reg, src_reg*/ - addbyte(0x00); - addbyte(0xc0 | (dst_reg & 7) | ((src_reg & 7) << 3)); - } + if (dst_reg & src_reg & 8) { + if (dst_reg & 0x10) { + addbyte(0x66); /*MOVW AX, src_reg*/ + addbyte(0x44); + addbyte(0x89); + addbyte(0xc0 | ((src_reg & 7) << 3)); + if (!(src_reg & 0x10)) { + addbyte(0x66); /*SHL AX, 8*/ + addbyte(0xc1); + addbyte(0xe0); + addbyte(8); + } else { + addbyte(0x66); /*AND AX, 0xff00*/ + addbyte(0x25); + addword(0xff00); + } + addbyte(0x66); /*ORW dst_reg, AX*/ + addbyte(0x41); + addbyte(0x09); + addbyte(0xc0 | (dst_reg & 7)); + } else if (src_reg & 0x10) { + addbyte(0x66); /*MOVW AX, src_reg*/ + addbyte(0x44); + addbyte(0x89); + addbyte(0xc0 | ((src_reg & 7) << 3)); + addbyte(0x66); /*SHR AX, 8*/ + addbyte(0xc1); + addbyte(0xe8); + addbyte(8); + addbyte(0x41); /*ORB dst_reg, AL*/ + addbyte(0x08); + addbyte(0xc0 | (dst_reg & 7)); + } else { + addbyte(0x45); /*ORB dst_reg, src_reg*/ + addbyte(0x08); + addbyte(0xc0 | (dst_reg & 7) | ((src_reg & 7) << 3)); } - else if (dst_reg & 8) - { - if (dst_reg & 0x10) - { - addbyte(0x66); /*SHL src_reg, 8*/ - addbyte(0xc1); - addbyte(0xe0 | src_reg); - addbyte(0x08); - addbyte(0x66); /*ADDW dst_reg, src_reg*/ - addbyte(0x41); - addbyte(0x01); - addbyte(0xc0 | (dst_reg & 7) | ((src_reg & 7) << 3)); - } - else - { - addbyte(0x41); /*ADDB dst_reg, src_reg*/ - addbyte(0x00); - addbyte(0xc0 | (dst_reg & 7) | ((src_reg & 7) << 3)); - } + } else if (dst_reg & 8) { + if (dst_reg & 0x10) { + addbyte(0x66); /*SHL src_reg, 8*/ + addbyte(0xc1); + addbyte(0xe0 | src_reg); + addbyte(0x08); + addbyte(0x66); /*ORW dst_reg, src_reg*/ + addbyte(0x41); + addbyte(0x09); + addbyte(0xc0 | (dst_reg & 7) | ((src_reg & 7) << 3)); + } else { + addbyte(0x41); /*ORB dst_reg, src_reg*/ + addbyte(0x08); + addbyte(0xc0 | (dst_reg & 7) | ((src_reg & 7) << 3)); } - else if (src_reg & 8) - { - if (src_reg & 0x10) - { - addbyte(0x66); /*MOVW AX, src_reg*/ - addbyte(0x44); - addbyte(0x89); - addbyte(0xc0 | ((src_reg & 7) << 3)); - addbyte(0x66); /*SHR AX, 8*/ - addbyte(0xc1); - addbyte(0xe8); - addbyte(8); - addbyte(0x00); /*ADDB dst_reg, AL*/ - addbyte(0xc0 | (dst_reg & 7)); - } - else - { - addbyte(0x44); /*ADDB dst_reg, src_reg*/ - addbyte(0x00); - addbyte(0xc0 | (dst_reg & 7) | ((src_reg & 7) << 3)); - } + } else if (src_reg & 8) { + if (dst_reg & 0x10) { + addbyte(0xc1); /*SHR dst_reg, 8*/ + addbyte(0xe8 | (dst_reg & 7)); + addbyte(8); } - else - fatal("!(dst_reg & src_reg & 8)\n"); + if (src_reg & 0x10) { + addbyte(0x41); /*MOVZX EBX, src_reg*/ + addbyte(0x0f); + addbyte(0xb7); + addbyte(0xd8 | (src_reg & 7)); + addbyte(0xc1); /*SHR EBX, 8*/ + addbyte(0xeb); + addbyte(8); + addbyte(0x08); /*ORB dst_reg, EBX*/ + addbyte(0xd8 | (dst_reg & 7)); + } else { + addbyte(0x44); /*ORB dst_reg, src_reg*/ + addbyte(0x08); + addbyte(0xc0 | (dst_reg & 7) | ((src_reg & 7) << 3)); + } + } else { + if (dst_reg & 0x10) { + addbyte(0xc1); /*SHR dst_reg, 8*/ + addbyte(0xe8 | (dst_reg & 7)); + addbyte(8); + } + if (src_reg & 0x10) { + addbyte(0x0f); /*MOVZX EBX, src_reg*/ + addbyte(0xb7); + addbyte(0xd8 | (src_reg & 7)); + addbyte(0xc1); /*SHR EBX, 8*/ + addbyte(0xeb); + addbyte(8); + addbyte(0x08); /*ORB dst_reg, EBX*/ + addbyte(0xd8 | (dst_reg & 7)); + } else { + addbyte(0x08); /*ORB dst_reg, src_reg*/ + addbyte(0xc0 | (dst_reg & 7) | ((src_reg & 7) << 3)); + } + } } -static inline void ADD_HOST_REG_W(int dst_reg, int src_reg) +static __inline void +OR_HOST_REG_W(int dst_reg, int src_reg) { - if (dst_reg & src_reg & 8) - { - addbyte(0x66); /*ADDW dst_reg, src_reg*/ - addbyte(0x45); - addbyte(0x01); - addbyte(0xc0 | (dst_reg & 7) | ((src_reg & 7) << 3)); - } - else if (dst_reg & 8) - { - addbyte(0x66); /*ADDW dst_reg, src_reg*/ - addbyte(0x41); - addbyte(0x01); - addbyte(0xc0 | (dst_reg & 7) | ((src_reg & 7) << 3)); - } - else if (src_reg & 8) - { - addbyte(0x66); /*ADDW dst_reg, src_reg*/ - addbyte(0x44); - addbyte(0x01); - addbyte(0xc0 | (dst_reg & 7) | ((src_reg & 7) << 3)); - } - else - fatal("!(dst_reg & src_reg & 8)\n"); + if (dst_reg & src_reg & 8) { + addbyte(0x66); /*ORW dst_reg, src_reg*/ + addbyte(0x45); + addbyte(0x09); + addbyte(0xc0 | (dst_reg & 7) | ((src_reg & 7) << 3)); + } else if (dst_reg & 8) { + addbyte(0x66); /*ORW dst_reg, src_reg*/ + addbyte(0x41); + addbyte(0x09); + addbyte(0xc0 | (dst_reg & 7) | ((src_reg & 7) << 3)); + } else if (src_reg & 8) { + addbyte(0x66); /*ORW dst_reg, src_reg*/ + addbyte(0x44); + addbyte(0x09); + addbyte(0xc0 | (dst_reg & 7) | ((src_reg & 7) << 3)); + } else { + addbyte(0x66); /*ORW dst_reg, src_reg*/ + addbyte(0x09); + addbyte(0xc0 | (dst_reg & 7) | ((src_reg & 7) << 3)); + } } -static inline void ADD_HOST_REG_L(int dst_reg, int src_reg) +static __inline void +OR_HOST_REG_L(int dst_reg, int src_reg) { - if (dst_reg & src_reg & 8) - { - addbyte(0x45); /*ADDL dst_reg, src_reg*/ - addbyte(0x01); - addbyte(0xc0 | (dst_reg & 7) | ((src_reg & 7) << 3)); - } - else if (dst_reg & 8) - { - addbyte(0x41); /*ADDL dst_reg, src_reg*/ - addbyte(0x01); - addbyte(0xc0 | (dst_reg & 7) | ((src_reg & 7) << 3)); - } - else if (src_reg & 8) - { - addbyte(0x44); /*ADDL dst_reg, src_reg*/ - addbyte(0x01); - addbyte(0xc0 | (dst_reg & 7) | ((src_reg & 7) << 3)); - } - else - fatal("!(dst_reg & src_reg & 8)\n"); + if (dst_reg & src_reg & 8) { + addbyte(0x45); /*ORL dst_reg, src_reg*/ + addbyte(0x09); + addbyte(0xc0 | (dst_reg & 7) | ((src_reg & 7) << 3)); + } else if (dst_reg & 8) { + addbyte(0x41); /*ORL dst_reg, src_reg*/ + addbyte(0x09); + addbyte(0xc0 | (dst_reg & 7) | ((src_reg & 7) << 3)); + } else if (src_reg & 8) { + addbyte(0x44); /*ORL dst_reg, src_reg*/ + addbyte(0x09); + addbyte(0xc0 | (dst_reg & 7) | ((src_reg & 7) << 3)); + } else { + addbyte(0x09); /*ORW dst_reg, src_reg*/ + addbyte(0xc0 | (dst_reg & 7) | ((src_reg & 7) << 3)); + } +} +static __inline void +OR_HOST_REG_IMM(int host_reg, uint32_t imm) +{ + if (host_reg & 0x10) { + addbyte(0x66); /*ORW host_reg, imm<<8*/ + addbyte(0x41); + addbyte(0x81); + addbyte(0xc8 | (host_reg & 7)); + addword(imm << 8); + } else if (host_reg & 8) { + addbyte(0x41); /*ORL host_reg, imm*/ + addbyte(0x81); + addbyte(0xc8 | (host_reg & 7)); + addlong(imm); + } else { + addbyte(0x81); /*ORL host_reg, imm*/ + addbyte(0xc8 | (host_reg & 7)); + addlong(imm); + } } -static inline void SUB_HOST_REG_B(int dst_reg, int src_reg) +static __inline void +XOR_HOST_REG_B(int dst_reg, int src_reg) { - if (dst_reg & src_reg & 8) - { - if (dst_reg & 0x10) - { - addbyte(0x66); /*MOVW AX, src_reg*/ - addbyte(0x44); - addbyte(0x89); - addbyte(0xc0 | ((src_reg & 7) << 3)); - if (!(src_reg & 0x10)) - { - addbyte(0x66); /*SHL AX, 8*/ - addbyte(0xc1); - addbyte(0xe0); - addbyte(8); - } - else - { - addbyte(0x66); /*AND AX, 0xff00*/ - addbyte(0x25); - addword(0xff00); - } - addbyte(0x66); /*SUBW dst_reg, AX*/ - addbyte(0x41); - addbyte(0x29); - addbyte(0xc0 | (dst_reg & 7)); - } - else if (src_reg & 0x10) - { - addbyte(0x66); /*MOVW AX, src_reg*/ - addbyte(0x44); - addbyte(0x89); - addbyte(0xc0 | ((src_reg & 7) << 3)); - addbyte(0x66); /*SHR AX, 8*/ - addbyte(0xc1); - addbyte(0xe8); - addbyte(8); - addbyte(0x41); /*SUBB dst_reg, AL*/ - addbyte(0x28); - addbyte(0xc0 | (dst_reg & 7)); - } - else - { - addbyte(0x45); /*SUBB dst_reg, src_reg*/ - addbyte(0x28); - addbyte(0xc0 | (dst_reg & 7) | ((src_reg & 7) << 3)); - } + if (dst_reg & src_reg & 8) { + if (dst_reg & 0x10) { + addbyte(0x66); /*MOVW AX, src_reg*/ + addbyte(0x44); + addbyte(0x89); + addbyte(0xc0 | ((src_reg & 7) << 3)); + if (!(src_reg & 0x10)) { + addbyte(0x66); /*SHL AX, 8*/ + addbyte(0xc1); + addbyte(0xe0); + addbyte(8); + } else { + addbyte(0x66); /*AND AX, 0xff00*/ + addbyte(0x25); + addword(0xff00); + } + addbyte(0x66); /*XORW dst_reg, AX*/ + addbyte(0x41); + addbyte(0x31); + addbyte(0xc0 | (dst_reg & 7)); + } else if (src_reg & 0x10) { + addbyte(0x66); /*MOVW AX, src_reg*/ + addbyte(0x44); + addbyte(0x89); + addbyte(0xc0 | ((src_reg & 7) << 3)); + addbyte(0x66); /*SHR AX, 8*/ + addbyte(0xc1); + addbyte(0xe8); + addbyte(8); + addbyte(0x41); /*XORB dst_reg, AL*/ + addbyte(0x30); + addbyte(0xc0 | (dst_reg & 7)); + } else { + addbyte(0x45); /*XORB dst_reg, src_reg*/ + addbyte(0x30); + addbyte(0xc0 | (dst_reg & 7) | ((src_reg & 7) << 3)); } - else if (dst_reg & 8) - { - if (dst_reg & 0x10) - { - addbyte(0x66); /*SHL src_reg, 8*/ - addbyte(0xc1); - addbyte(0xe0 | src_reg); - addbyte(0x08); - addbyte(0x66); /*SUBW dst_reg, src_reg*/ - addbyte(0x41); - addbyte(0x29); - addbyte(0xc0 | (dst_reg & 7) | ((src_reg & 7) << 3)); - } - else - { - addbyte(0x41); /*SUBB dst_reg, src_reg*/ - addbyte(0x28); - addbyte(0xc0 | (dst_reg & 7) | ((src_reg & 7) << 3)); - } + } else if (dst_reg & 8) { + if (dst_reg & 0x10) { + addbyte(0x66); /*SHL src_reg, 8*/ + addbyte(0xc1); + addbyte(0xe0 | src_reg); + addbyte(0x08); + addbyte(0x66); /*XORW dst_reg, src_reg*/ + addbyte(0x41); + addbyte(0x31); + addbyte(0xc0 | (dst_reg & 7) | ((src_reg & 7) << 3)); + } else { + addbyte(0x41); /*XORB dst_reg, src_reg*/ + addbyte(0x30); + addbyte(0xc0 | (dst_reg & 7) | ((src_reg & 7) << 3)); } - else if (src_reg & 8) - { - if (dst_reg & 0x10) - { - addbyte(0xc1); /*SHR dst_reg, 8*/ - addbyte(0xe8 | (dst_reg & 7)); - addbyte(8); - } - if (src_reg & 0x10) - { - addbyte(0x41); /*MOVZX EBX, src_reg*/ - addbyte(0x0f); - addbyte(0xb7); - addbyte(0xd8 | (src_reg & 7)); - addbyte(0xc1); /*SHR EBX, 8*/ - addbyte(0xeb); - addbyte(8); - addbyte(0x28); /*SUBB dst_reg, EBX*/ - addbyte(0xd8 | (dst_reg & 7)); - } - else - { - addbyte(0x44); /*SUBB dst_reg, src_reg*/ - addbyte(0x28); - addbyte(0xc0 | (dst_reg & 7) | ((src_reg & 7) << 3)); - } + } else if (src_reg & 8) { + if (dst_reg & 0x10) { + addbyte(0xc1); /*SHR dst_reg, 8*/ + addbyte(0xe8 | (dst_reg & 7)); + addbyte(8); } - else - { - if (dst_reg & 0x10) - { - addbyte(0xc1); /*SHR dst_reg, 8*/ - addbyte(0xe8 | (dst_reg & 7)); - addbyte(8); - } - if (src_reg & 0x10) - { - addbyte(0x0f); /*MOVZX EBX, src_reg*/ - addbyte(0xb7); - addbyte(0xd8 | (src_reg & 7)); - addbyte(0xc1); /*SHR EBX, 8*/ - addbyte(0xeb); - addbyte(8); - addbyte(0x28); /*SUBB dst_reg, EBX*/ - addbyte(0xd8 | (dst_reg & 7)); - } - else - { - addbyte(0x28); /*SUBB dst_reg, src_reg*/ - addbyte(0xc0 | (dst_reg & 7) | ((src_reg & 7) << 3)); - } + if (src_reg & 0x10) { + addbyte(0x41); /*MOVZX EBX, src_reg*/ + addbyte(0x0f); + addbyte(0xb7); + addbyte(0xd8 | (src_reg & 7)); + addbyte(0xc1); /*SHR EBX, 8*/ + addbyte(0xeb); + addbyte(8); + addbyte(0x30); /*XORB dst_reg, EBX*/ + addbyte(0xd8 | (dst_reg & 7)); + } else { + addbyte(0x44); /*XORB dst_reg, src_reg*/ + addbyte(0x30); + addbyte(0xc0 | (dst_reg & 7) | ((src_reg & 7) << 3)); } + } else { + if (dst_reg & 0x10) { + addbyte(0xc1); /*SHR dst_reg, 8*/ + addbyte(0xe8 | (dst_reg & 7)); + addbyte(8); + } + if (src_reg & 0x10) { + addbyte(0x0f); /*MOVZX EBX, src_reg*/ + addbyte(0xb7); + addbyte(0xd8 | (src_reg & 7)); + addbyte(0xc1); /*SHR EBX, 8*/ + addbyte(0xeb); + addbyte(8); + addbyte(0x30); /*XORB dst_reg, EBX*/ + addbyte(0xd8 | (dst_reg & 7)); + } else { + addbyte(0x30); /*XORB dst_reg, src_reg*/ + addbyte(0xc0 | (dst_reg & 7) | ((src_reg & 7) << 3)); + } + } } -static inline void SUB_HOST_REG_W(int dst_reg, int src_reg) +static __inline void +XOR_HOST_REG_W(int dst_reg, int src_reg) { - if (dst_reg & src_reg & 8) - { - addbyte(0x66); /*SUBW dst_reg, src_reg*/ - addbyte(0x45); - addbyte(0x29); - addbyte(0xc0 | (dst_reg & 7) | ((src_reg & 7) << 3)); - } - else if (dst_reg & 8) - { - addbyte(0x66); /*SUBW dst_reg, src_reg*/ - addbyte(0x41); - addbyte(0x29); - addbyte(0xc0 | (dst_reg & 7) | ((src_reg & 7) << 3)); - } - else if (src_reg & 8) - { - addbyte(0x66); /*SUBW dst_reg, src_reg*/ - addbyte(0x44); - addbyte(0x29); - addbyte(0xc0 | (dst_reg & 7) | ((src_reg & 7) << 3)); - } - else - { - addbyte(0x66); /*SUBW dst_reg, src_reg*/ - addbyte(0x29); - addbyte(0xc0 | (dst_reg & 7) | ((src_reg & 7) << 3)); - } + if (dst_reg & src_reg & 8) { + addbyte(0x66); /*XORW dst_reg, src_reg*/ + addbyte(0x45); + addbyte(0x31); + addbyte(0xc0 | (dst_reg & 7) | ((src_reg & 7) << 3)); + } else if (dst_reg & 8) { + addbyte(0x66); /*XORW dst_reg, src_reg*/ + addbyte(0x41); + addbyte(0x31); + addbyte(0xc0 | (dst_reg & 7) | ((src_reg & 7) << 3)); + } else if (src_reg & 8) { + addbyte(0x66); /*XORW dst_reg, src_reg*/ + addbyte(0x44); + addbyte(0x31); + addbyte(0xc0 | (dst_reg & 7) | ((src_reg & 7) << 3)); + } else { + addbyte(0x66); /*XORW dst_reg, src_reg*/ + addbyte(0x31); + addbyte(0xc0 | (dst_reg & 7) | ((src_reg & 7) << 3)); + } } -static inline void SUB_HOST_REG_L(int dst_reg, int src_reg) +static __inline void +XOR_HOST_REG_L(int dst_reg, int src_reg) { - if (dst_reg & src_reg & 8) - { - addbyte(0x45); /*SUBL dst_reg, src_reg*/ - addbyte(0x29); - addbyte(0xc0 | (dst_reg & 7) | ((src_reg & 7) << 3)); - } - else if (dst_reg & 8) - { - addbyte(0x41); /*SUBL dst_reg, src_reg*/ - addbyte(0x29); - addbyte(0xc0 | (dst_reg & 7) | ((src_reg & 7) << 3)); - } - else if (src_reg & 8) - { - addbyte(0x44); /*SUBL dst_reg, src_reg*/ - addbyte(0x29); - addbyte(0xc0 | (dst_reg & 7) | ((src_reg & 7) << 3)); - } - else - { - addbyte(0x29); /*SUBL dst_reg, src_reg*/ - addbyte(0xc0 | (dst_reg & 7) | ((src_reg & 7) << 3)); - } + if (dst_reg & src_reg & 8) { + addbyte(0x45); /*XORL dst_reg, src_reg*/ + addbyte(0x31); + addbyte(0xc0 | (dst_reg & 7) | ((src_reg & 7) << 3)); + } else if (dst_reg & 8) { + addbyte(0x41); /*XORL dst_reg, src_reg*/ + addbyte(0x31); + addbyte(0xc0 | (dst_reg & 7) | ((src_reg & 7) << 3)); + } else if (src_reg & 8) { + addbyte(0x44); /*XORW dst_reg, src_reg*/ + addbyte(0x31); + addbyte(0xc0 | (dst_reg & 7) | ((src_reg & 7) << 3)); + } else { + addbyte(0x31); /*XORW dst_reg, src_reg*/ + addbyte(0xc0 | (dst_reg & 7) | ((src_reg & 7) << 3)); + } +} +static __inline void +XOR_HOST_REG_IMM(int host_reg, uint32_t imm) +{ + if (host_reg & 0x10) { + addbyte(0x66); /*ORW host_reg, imm<<8*/ + addbyte(0x41); + addbyte(0x81); + addbyte(0xf0 | (host_reg & 7)); + addword(imm << 8); + } else if (host_reg & 8) { + addbyte(0x41); /*ORL host_reg, imm*/ + addbyte(0x81); + addbyte(0xf0 | (host_reg & 7)); + addlong(imm); + } else { + addbyte(0x81); /*ORL host_reg, imm*/ + addbyte(0xf0 | (host_reg & 7)); + addlong(imm); + } } -static inline int CMP_HOST_REG_B(int dst_reg, int src_reg) +static __inline void +ADD_HOST_REG_B(int dst_reg, int src_reg) { - if (dst_reg & 8) - { - addbyte(0x44); /*MOV EDX, dst_reg*/ - addbyte(0x89); - addbyte(0xc0 | ((dst_reg & 7) << 3) | REG_EDX); - - dst_reg = (dst_reg & 0x10) | REG_EDX; + if (dst_reg & src_reg & 8) { + if (dst_reg & 0x10) { + addbyte(0x66); /*MOVW AX, src_reg*/ + addbyte(0x44); + addbyte(0x89); + addbyte(0xc0 | ((src_reg & 7) << 3)); + if (!(src_reg & 0x10)) { + addbyte(0x66); /*SHL AX, 8*/ + addbyte(0xc1); + addbyte(0xe0); + addbyte(8); + } else { + addbyte(0x66); /*AND AX, 0xff00*/ + addbyte(0x25); + addword(0xff00); + } + addbyte(0x66); /*ADDW dst_reg, AX*/ + addbyte(0x41); + addbyte(0x01); + addbyte(0xc0 | (dst_reg & 7)); + } else if (src_reg & 0x10) { + addbyte(0x66); /*MOVW AX, src_reg*/ + addbyte(0x44); + addbyte(0x89); + addbyte(0xc0 | ((src_reg & 7) << 3)); + addbyte(0x66); /*SHR AX, 8*/ + addbyte(0xc1); + addbyte(0xe8); + addbyte(8); + addbyte(0x41); /*ADDB dst_reg, AL*/ + addbyte(0x00); + addbyte(0xc0 | (dst_reg & 7)); + } else { + addbyte(0x45); /*ADDB dst_reg, src_reg*/ + addbyte(0x00); + addbyte(0xc0 | (dst_reg & 7) | ((src_reg & 7) << 3)); } - - SUB_HOST_REG_B(dst_reg, src_reg); - - return dst_reg & ~0x10; + } else if (dst_reg & 8) { + if (dst_reg & 0x10) { + addbyte(0x66); /*SHL src_reg, 8*/ + addbyte(0xc1); + addbyte(0xe0 | src_reg); + addbyte(0x08); + addbyte(0x66); /*ADDW dst_reg, src_reg*/ + addbyte(0x41); + addbyte(0x01); + addbyte(0xc0 | (dst_reg & 7) | ((src_reg & 7) << 3)); + } else { + addbyte(0x41); /*ADDB dst_reg, src_reg*/ + addbyte(0x00); + addbyte(0xc0 | (dst_reg & 7) | ((src_reg & 7) << 3)); + } + } else if (src_reg & 8) { + if (src_reg & 0x10) { + addbyte(0x66); /*MOVW AX, src_reg*/ + addbyte(0x44); + addbyte(0x89); + addbyte(0xc0 | ((src_reg & 7) << 3)); + addbyte(0x66); /*SHR AX, 8*/ + addbyte(0xc1); + addbyte(0xe8); + addbyte(8); + addbyte(0x00); /*ADDB dst_reg, AL*/ + addbyte(0xc0 | (dst_reg & 7)); + } else { + addbyte(0x44); /*ADDB dst_reg, src_reg*/ + addbyte(0x00); + addbyte(0xc0 | (dst_reg & 7) | ((src_reg & 7) << 3)); + } + } else + fatal("!(dst_reg & src_reg & 8)\n"); } -static inline int CMP_HOST_REG_W(int dst_reg, int src_reg) +static __inline void +ADD_HOST_REG_W(int dst_reg, int src_reg) { - if (dst_reg & 8) - { - addbyte(0x44); /*MOV EDX, dst_reg*/ - addbyte(0x89); - addbyte(0xc0 | ((dst_reg & 7) << 3) | REG_EDX); - - dst_reg = REG_EDX; - } - - SUB_HOST_REG_W(dst_reg, src_reg); - - return dst_reg; + if (dst_reg & src_reg & 8) { + addbyte(0x66); /*ADDW dst_reg, src_reg*/ + addbyte(0x45); + addbyte(0x01); + addbyte(0xc0 | (dst_reg & 7) | ((src_reg & 7) << 3)); + } else if (dst_reg & 8) { + addbyte(0x66); /*ADDW dst_reg, src_reg*/ + addbyte(0x41); + addbyte(0x01); + addbyte(0xc0 | (dst_reg & 7) | ((src_reg & 7) << 3)); + } else if (src_reg & 8) { + addbyte(0x66); /*ADDW dst_reg, src_reg*/ + addbyte(0x44); + addbyte(0x01); + addbyte(0xc0 | (dst_reg & 7) | ((src_reg & 7) << 3)); + } else + fatal("!(dst_reg & src_reg & 8)\n"); } -static inline int CMP_HOST_REG_L(int dst_reg, int src_reg) +static __inline void +ADD_HOST_REG_L(int dst_reg, int src_reg) { - if (dst_reg & 8) - { - addbyte(0x44); /*MOV EDX, dst_reg*/ - addbyte(0x89); - addbyte(0xc0 | ((dst_reg & 7) << 3) | REG_EDX); - - dst_reg = REG_EDX; - } - - SUB_HOST_REG_L(dst_reg, src_reg); - - return dst_reg; + if (dst_reg & src_reg & 8) { + addbyte(0x45); /*ADDL dst_reg, src_reg*/ + addbyte(0x01); + addbyte(0xc0 | (dst_reg & 7) | ((src_reg & 7) << 3)); + } else if (dst_reg & 8) { + addbyte(0x41); /*ADDL dst_reg, src_reg*/ + addbyte(0x01); + addbyte(0xc0 | (dst_reg & 7) | ((src_reg & 7) << 3)); + } else if (src_reg & 8) { + addbyte(0x44); /*ADDL dst_reg, src_reg*/ + addbyte(0x01); + addbyte(0xc0 | (dst_reg & 7) | ((src_reg & 7) << 3)); + } else + fatal("!(dst_reg & src_reg & 8)\n"); } -static inline void ADD_HOST_REG_IMM_B(int host_reg, uint8_t imm) +static __inline void +SUB_HOST_REG_B(int dst_reg, int src_reg) { - if (host_reg & 0x10) - { - addbyte(0x66); /*ADDW host_reg, imm*/ - if (host_reg & 8) - addbyte(0x41); - addbyte(0x81); - addbyte(0xC0 | (host_reg & 7)); - addword(imm << 8); + if (dst_reg & src_reg & 8) { + if (dst_reg & 0x10) { + addbyte(0x66); /*MOVW AX, src_reg*/ + addbyte(0x44); + addbyte(0x89); + addbyte(0xc0 | ((src_reg & 7) << 3)); + if (!(src_reg & 0x10)) { + addbyte(0x66); /*SHL AX, 8*/ + addbyte(0xc1); + addbyte(0xe0); + addbyte(8); + } else { + addbyte(0x66); /*AND AX, 0xff00*/ + addbyte(0x25); + addword(0xff00); + } + addbyte(0x66); /*SUBW dst_reg, AX*/ + addbyte(0x41); + addbyte(0x29); + addbyte(0xc0 | (dst_reg & 7)); + } else if (src_reg & 0x10) { + addbyte(0x66); /*MOVW AX, src_reg*/ + addbyte(0x44); + addbyte(0x89); + addbyte(0xc0 | ((src_reg & 7) << 3)); + addbyte(0x66); /*SHR AX, 8*/ + addbyte(0xc1); + addbyte(0xe8); + addbyte(8); + addbyte(0x41); /*SUBB dst_reg, AL*/ + addbyte(0x28); + addbyte(0xc0 | (dst_reg & 7)); + } else { + addbyte(0x45); /*SUBB dst_reg, src_reg*/ + addbyte(0x28); + addbyte(0xc0 | (dst_reg & 7) | ((src_reg & 7) << 3)); } - else - { - if (host_reg & 8) - addbyte(0x41); - addbyte(0x80); /*ADDB host_reg, imm*/ - addbyte(0xC0 | (host_reg & 7)); - addbyte(imm); + } else if (dst_reg & 8) { + if (dst_reg & 0x10) { + addbyte(0x66); /*SHL src_reg, 8*/ + addbyte(0xc1); + addbyte(0xe0 | src_reg); + addbyte(0x08); + addbyte(0x66); /*SUBW dst_reg, src_reg*/ + addbyte(0x41); + addbyte(0x29); + addbyte(0xc0 | (dst_reg & 7) | ((src_reg & 7) << 3)); + } else { + addbyte(0x41); /*SUBB dst_reg, src_reg*/ + addbyte(0x28); + addbyte(0xc0 | (dst_reg & 7) | ((src_reg & 7) << 3)); } + } else if (src_reg & 8) { + if (dst_reg & 0x10) { + addbyte(0xc1); /*SHR dst_reg, 8*/ + addbyte(0xe8 | (dst_reg & 7)); + addbyte(8); + } + if (src_reg & 0x10) { + addbyte(0x41); /*MOVZX EBX, src_reg*/ + addbyte(0x0f); + addbyte(0xb7); + addbyte(0xd8 | (src_reg & 7)); + addbyte(0xc1); /*SHR EBX, 8*/ + addbyte(0xeb); + addbyte(8); + addbyte(0x28); /*SUBB dst_reg, EBX*/ + addbyte(0xd8 | (dst_reg & 7)); + } else { + addbyte(0x44); /*SUBB dst_reg, src_reg*/ + addbyte(0x28); + addbyte(0xc0 | (dst_reg & 7) | ((src_reg & 7) << 3)); + } + } else { + if (dst_reg & 0x10) { + addbyte(0xc1); /*SHR dst_reg, 8*/ + addbyte(0xe8 | (dst_reg & 7)); + addbyte(8); + } + if (src_reg & 0x10) { + addbyte(0x0f); /*MOVZX EBX, src_reg*/ + addbyte(0xb7); + addbyte(0xd8 | (src_reg & 7)); + addbyte(0xc1); /*SHR EBX, 8*/ + addbyte(0xeb); + addbyte(8); + addbyte(0x28); /*SUBB dst_reg, EBX*/ + addbyte(0xd8 | (dst_reg & 7)); + } else { + addbyte(0x28); /*SUBB dst_reg, src_reg*/ + addbyte(0xc0 | (dst_reg & 7) | ((src_reg & 7) << 3)); + } + } } -static inline void ADD_HOST_REG_IMM_W(int host_reg, uint16_t imm) +static __inline void +SUB_HOST_REG_W(int dst_reg, int src_reg) { + if (dst_reg & src_reg & 8) { + addbyte(0x66); /*SUBW dst_reg, src_reg*/ + addbyte(0x45); + addbyte(0x29); + addbyte(0xc0 | (dst_reg & 7) | ((src_reg & 7) << 3)); + } else if (dst_reg & 8) { + addbyte(0x66); /*SUBW dst_reg, src_reg*/ + addbyte(0x41); + addbyte(0x29); + addbyte(0xc0 | (dst_reg & 7) | ((src_reg & 7) << 3)); + } else if (src_reg & 8) { + addbyte(0x66); /*SUBW dst_reg, src_reg*/ + addbyte(0x44); + addbyte(0x29); + addbyte(0xc0 | (dst_reg & 7) | ((src_reg & 7) << 3)); + } else { + addbyte(0x66); /*SUBW dst_reg, src_reg*/ + addbyte(0x29); + addbyte(0xc0 | (dst_reg & 7) | ((src_reg & 7) << 3)); + } +} +static __inline void +SUB_HOST_REG_L(int dst_reg, int src_reg) +{ + if (dst_reg & src_reg & 8) { + addbyte(0x45); /*SUBL dst_reg, src_reg*/ + addbyte(0x29); + addbyte(0xc0 | (dst_reg & 7) | ((src_reg & 7) << 3)); + } else if (dst_reg & 8) { + addbyte(0x41); /*SUBL dst_reg, src_reg*/ + addbyte(0x29); + addbyte(0xc0 | (dst_reg & 7) | ((src_reg & 7) << 3)); + } else if (src_reg & 8) { + addbyte(0x44); /*SUBL dst_reg, src_reg*/ + addbyte(0x29); + addbyte(0xc0 | (dst_reg & 7) | ((src_reg & 7) << 3)); + } else { + addbyte(0x29); /*SUBL dst_reg, src_reg*/ + addbyte(0xc0 | (dst_reg & 7) | ((src_reg & 7) << 3)); + } +} + +static __inline int +CMP_HOST_REG_B(int dst_reg, int src_reg) +{ + if (dst_reg & 8) { + addbyte(0x44); /*MOV EDX, dst_reg*/ + addbyte(0x89); + addbyte(0xc0 | ((dst_reg & 7) << 3) | REG_EDX); + + dst_reg = (dst_reg & 0x10) | REG_EDX; + } + + SUB_HOST_REG_B(dst_reg, src_reg); + + return dst_reg & ~0x10; +} +static __inline int +CMP_HOST_REG_W(int dst_reg, int src_reg) +{ + if (dst_reg & 8) { + addbyte(0x44); /*MOV EDX, dst_reg*/ + addbyte(0x89); + addbyte(0xc0 | ((dst_reg & 7) << 3) | REG_EDX); + + dst_reg = REG_EDX; + } + + SUB_HOST_REG_W(dst_reg, src_reg); + + return dst_reg; +} +static __inline int +CMP_HOST_REG_L(int dst_reg, int src_reg) +{ + if (dst_reg & 8) { + addbyte(0x44); /*MOV EDX, dst_reg*/ + addbyte(0x89); + addbyte(0xc0 | ((dst_reg & 7) << 3) | REG_EDX); + + dst_reg = REG_EDX; + } + + SUB_HOST_REG_L(dst_reg, src_reg); + + return dst_reg; +} + +static __inline void +ADD_HOST_REG_IMM_B(int host_reg, uint8_t imm) +{ + if (host_reg & 0x10) { addbyte(0x66); /*ADDW host_reg, imm*/ if (host_reg & 8) - addbyte(0x41); + addbyte(0x41); addbyte(0x81); addbyte(0xC0 | (host_reg & 7)); - addword(imm); -} -static inline void ADD_HOST_REG_IMM(int host_reg, uint32_t imm) -{ + addword(imm << 8); + } else { if (host_reg & 8) - addbyte(0x41); - addbyte(0x81); /*ADDL host_reg, imm*/ + addbyte(0x41); + addbyte(0x80); /*ADDB host_reg, imm*/ addbyte(0xC0 | (host_reg & 7)); - addlong(imm); + addbyte(imm); + } +} +static __inline void +ADD_HOST_REG_IMM_W(int host_reg, uint16_t imm) +{ + addbyte(0x66); /*ADDW host_reg, imm*/ + if (host_reg & 8) + addbyte(0x41); + addbyte(0x81); + addbyte(0xC0 | (host_reg & 7)); + addword(imm); +} +static __inline void +ADD_HOST_REG_IMM(int host_reg, uint32_t imm) +{ + if (host_reg & 8) + addbyte(0x41); + addbyte(0x81); /*ADDL host_reg, imm*/ + addbyte(0xC0 | (host_reg & 7)); + addlong(imm); } -static inline void SUB_HOST_REG_IMM_B(int host_reg, uint8_t imm) -{ - if (host_reg & 0x10) - { - addbyte(0x66); /*SUBW host_reg, imm*/ - if (host_reg & 8) - addbyte(0x41); - addbyte(0x81); - addbyte(0xE8 | (host_reg & 7)); - addword(imm << 8); - } - else - { - if (host_reg & 8) - addbyte(0x41); - addbyte(0x80); /*SUBB host_reg, imm*/ - addbyte(0xE8 | (host_reg & 7)); - addbyte(imm); - } -} -static inline void SUB_HOST_REG_IMM_W(int host_reg, uint16_t imm) +static __inline void +SUB_HOST_REG_IMM_B(int host_reg, uint8_t imm) { + if (host_reg & 0x10) { addbyte(0x66); /*SUBW host_reg, imm*/ if (host_reg & 8) - addbyte(0x41); + addbyte(0x41); addbyte(0x81); addbyte(0xE8 | (host_reg & 7)); - addword(imm); -} -static inline void SUB_HOST_REG_IMM(int host_reg, uint32_t imm) -{ + addword(imm << 8); + } else { if (host_reg & 8) - addbyte(0x41); - addbyte(0x81); /*SUBL host_reg, imm*/ + addbyte(0x41); + addbyte(0x80); /*SUBB host_reg, imm*/ addbyte(0xE8 | (host_reg & 7)); - addlong(imm); + addbyte(imm); + } +} +static __inline void +SUB_HOST_REG_IMM_W(int host_reg, uint16_t imm) +{ + addbyte(0x66); /*SUBW host_reg, imm*/ + if (host_reg & 8) + addbyte(0x41); + addbyte(0x81); + addbyte(0xE8 | (host_reg & 7)); + addword(imm); +} +static __inline void +SUB_HOST_REG_IMM(int host_reg, uint32_t imm) +{ + if (host_reg & 8) + addbyte(0x41); + addbyte(0x81); /*SUBL host_reg, imm*/ + addbyte(0xE8 | (host_reg & 7)); + addlong(imm); } -static inline void INC_HOST_REG_W(int host_reg) +static __inline void +INC_HOST_REG_W(int host_reg) { - addbyte(0x66); /*INCW host_reg*/ - if (host_reg & 8) - addbyte(0x41); - addbyte(0xff); - addbyte(0xc0 | (host_reg & 7)); + addbyte(0x66); /*INCW host_reg*/ + if (host_reg & 8) + addbyte(0x41); + addbyte(0xff); + addbyte(0xc0 | (host_reg & 7)); } -static inline void INC_HOST_REG(int host_reg) +static __inline void +INC_HOST_REG(int host_reg) { - if (host_reg & 8) - addbyte(0x41); - addbyte(0xff); /*INCL host_reg*/ - addbyte(0xc0 | (host_reg & 7)); + if (host_reg & 8) + addbyte(0x41); + addbyte(0xff); /*INCL host_reg*/ + addbyte(0xc0 | (host_reg & 7)); } -static inline void DEC_HOST_REG_W(int host_reg) +static __inline void +DEC_HOST_REG_W(int host_reg) { - addbyte(0x66); /*DECW host_reg*/ - if (host_reg & 8) - addbyte(0x41); - addbyte(0xff); - addbyte(0xc8 | (host_reg & 7)); + addbyte(0x66); /*DECW host_reg*/ + if (host_reg & 8) + addbyte(0x41); + addbyte(0xff); + addbyte(0xc8 | (host_reg & 7)); } -static inline void DEC_HOST_REG(int host_reg) +static __inline void +DEC_HOST_REG(int host_reg) { - if (host_reg & 8) - addbyte(0x41); - addbyte(0xff); /*DECL host_reg*/ - addbyte(0xc8 | (host_reg & 7)); + if (host_reg & 8) + addbyte(0x41); + addbyte(0xff); /*DECL host_reg*/ + addbyte(0xc8 | (host_reg & 7)); } -static inline int CMP_HOST_REG_IMM_B(int host_reg, uint8_t imm) +static __inline int +CMP_HOST_REG_IMM_B(int host_reg, uint8_t imm) { - if (host_reg & 8) - { - addbyte(0x44); /*MOV EDX, dst_reg*/ - addbyte(0x89); - addbyte(0xc0 | ((host_reg & 7) << 3) | REG_EDX); - - host_reg = (host_reg & 0x10) | REG_EDX; - } - - SUB_HOST_REG_IMM_B(host_reg, imm); - - return host_reg; -} -static inline int CMP_HOST_REG_IMM_W(int host_reg, uint16_t imm) -{ - if (host_reg & 8) - { - addbyte(0x44); /*MOV EDX, dst_reg*/ - addbyte(0x89); - addbyte(0xc0 | ((host_reg & 7) << 3) | REG_EDX); - - host_reg = REG_EDX; - } - - SUB_HOST_REG_IMM_W(host_reg, imm); - - return host_reg; -} -static inline int CMP_HOST_REG_IMM_L(int host_reg, uint32_t imm) -{ - if (host_reg & 8) - { - addbyte(0x44); /*MOV EDX, dst_reg*/ - addbyte(0x89); - addbyte(0xc0 | ((host_reg & 7) << 3) | REG_EDX); - - host_reg = REG_EDX; - } - - SUB_HOST_REG_IMM(host_reg, imm); - - return host_reg; -} - -static inline void LOAD_STACK_TO_EA(int off) -{ - if (stack32) - { - addbyte(0x8b); /*MOVL EAX,[ESP]*/ - addbyte(0x45 | (REG_EAX << 3)); - addbyte((uint8_t)cpu_state_offset(regs[REG_ESP].l)); - if (off) - { - addbyte(0x83); /*ADD EAX, off*/ - addbyte(0xc0 | (0 << 3) | REG_EAX); - addbyte(off); - } - } - else - { - addbyte(0x0f); /*MOVZX EAX,W[ESP]*/ - addbyte(0xb7); - addbyte(0x45 | (REG_EAX << 3)); - addbyte((uint8_t)cpu_state_offset(regs[REG_ESP].w)); - if (off) - { - addbyte(0x66); /*ADD AX, off*/ - addbyte(0x05); - addword(off); - } - } -} -static inline void LOAD_EBP_TO_EA(int off) -{ - if (stack32) - { - addbyte(0x8b); /*MOVL EAX,[EBP]*/ - addbyte(0x45 | (REG_EAX << 3)); - addbyte((uint8_t)cpu_state_offset(regs[REG_EBP].l)); - if (off) - { - addbyte(0x83); /*ADD EAX, off*/ - addbyte(0xc0 | (0 << 3) | REG_EAX); - addbyte(off); - } - } - else - { - addbyte(0x0f); /*MOVZX EAX,W[EBP]*/ - addbyte(0xb7); - addbyte(0x45 | (REG_EAX << 3)); - addbyte((uint8_t)cpu_state_offset(regs[REG_BP].l)); - if (off) - { - addbyte(0x66); /*ADD AX, off*/ - addbyte(0x05); - addword(off); - } - } -} - -static inline void SP_MODIFY(int off) -{ - if (stack32) - { - if (off < 0x80) - { - addbyte(0x83); /*ADD [ESP], off*/ - addbyte(0x45); - addbyte((uint8_t)cpu_state_offset(regs[REG_ESP].l)); - addbyte(off); - } - else - { - addbyte(0x81); /*ADD [ESP], off*/ - addbyte(0x45); - addbyte((uint8_t)cpu_state_offset(regs[REG_ESP].l)); - addlong(off); - } - } - else - { - if (off < 0x80) - { - addbyte(0x66); /*ADD [SP], off*/ - addbyte(0x83); - addbyte(0x45); - addbyte((uint8_t)cpu_state_offset(regs[REG_ESP].w)); - addbyte(off); - } - else - { - addbyte(0x66); /*ADD [SP], off*/ - addbyte(0x81); - addbyte(0x45); - addbyte((uint8_t)cpu_state_offset(regs[REG_ESP].w)); - addword(off); - } - } -} - -static inline void TEST_ZERO_JUMP_W(int host_reg, uint32_t new_pc, int taken_cycles) -{ - addbyte(0x66); /*CMPW host_reg, 0*/ - if (host_reg & 8) - addbyte(0x41); - addbyte(0x83); - addbyte(0xc0 | 0x38 | (host_reg & 7)); - addbyte(0); - addbyte(0x75); /*JNZ +*/ - addbyte(7+5+(taken_cycles ? 4 : 0)); - addbyte(0xC7); /*MOVL [pc], new_pc*/ - addbyte(0x45); - addbyte((uint8_t)cpu_state_offset(pc)); - addlong(new_pc); - if (taken_cycles) - { - addbyte(0x83); /*SUB $codegen_block_cycles, cyclcs*/ - addbyte(0x6d); - addbyte((uint8_t)cpu_state_offset(_cycles)); - addbyte(taken_cycles); - } - addbyte(0xe9); /*JMP end*/ - addlong(BLOCK_EXIT_OFFSET - (block_pos + 4)); -} -static inline void TEST_ZERO_JUMP_L(int host_reg, uint32_t new_pc, int taken_cycles) -{ - if (host_reg & 8) - addbyte(0x41); - addbyte(0x83); /*CMPW host_reg, 0*/ - addbyte(0xc0 | 0x38 | (host_reg & 7)); - addbyte(0); - addbyte(0x75); /*JNZ +*/ - addbyte(7+5+(taken_cycles ? 4 : 0)); - addbyte(0xC7); /*MOVL [pc], new_pc*/ - addbyte(0x45); - addbyte((uint8_t)cpu_state_offset(pc)); - addlong(new_pc); - if (taken_cycles) - { - addbyte(0x83); /*SUB $codegen_block_cycles, cyclcs*/ - addbyte(0x6d); - addbyte((uint8_t)cpu_state_offset(_cycles)); - addbyte(taken_cycles); - } - addbyte(0xe9); /*JMP end*/ - addlong(BLOCK_EXIT_OFFSET - (block_pos + 4)); -} - -static inline void TEST_NONZERO_JUMP_W(int host_reg, uint32_t new_pc, int taken_cycles) -{ - addbyte(0x66); /*CMPW host_reg, 0*/ - if (host_reg & 8) - addbyte(0x41); - addbyte(0x83); - addbyte(0xc0 | 0x38 | (host_reg & 7)); - addbyte(0); - addbyte(0x74); /*JZ +*/ - addbyte(7+5+(taken_cycles ? 4 : 0)); - addbyte(0xC7); /*MOVL [pc], new_pc*/ - addbyte(0x45); - addbyte((uint8_t)cpu_state_offset(pc)); - addlong(new_pc); - if (taken_cycles) - { - addbyte(0x83); /*SUB $codegen_block_cycles, cyclcs*/ - addbyte(0x6d); - addbyte((uint8_t)cpu_state_offset(_cycles)); - addbyte(taken_cycles); - } - addbyte(0xe9); /*JMP end*/ - addlong(BLOCK_EXIT_OFFSET - (block_pos + 4)); -} -static inline void TEST_NONZERO_JUMP_L(int host_reg, uint32_t new_pc, int taken_cycles) -{ - if (host_reg & 8) - addbyte(0x41); - addbyte(0x83); /*CMPW host_reg, 0*/ - addbyte(0xc0 | 0x38 | (host_reg & 7)); - addbyte(0); - addbyte(0x74); /*JZ +*/ - addbyte(7+5+(taken_cycles ? 4 : 0)); - addbyte(0xC7); /*MOVL [pc], new_pc*/ - addbyte(0x45); - addbyte((uint8_t)cpu_state_offset(pc)); - addlong(new_pc); - if (taken_cycles) - { - addbyte(0x83); /*SUB $codegen_block_cycles, cyclcs*/ - addbyte(0x6d); - addbyte((uint8_t)cpu_state_offset(_cycles)); - addbyte(taken_cycles); - } - addbyte(0xe9); /*JMP end*/ - addlong(BLOCK_EXIT_OFFSET - (block_pos + 4)); -} - -static inline void BRANCH_COND_BE(int pc_offset, uint32_t op_pc, uint32_t offset, int not) -{ - uint8_t *jump1; - - if (codegen_flags_changed && cpu_state.flags_op != FLAGS_UNKNOWN) - { - addbyte(0x83); /*CMP flags_res, 0*/ - addbyte(0x7d); - addbyte((uint8_t)cpu_state_offset(flags_res)); - addbyte(0); - addbyte(0x74); /*JZ +*/ - } - else - { - CALL_FUNC((uintptr_t)ZF_SET); - addbyte(0x85); /*TEST EAX,EAX*/ - addbyte(0xc0); - addbyte(0x75); /*JNZ +*/ - } - jump1 = &codeblock[block_current].data[block_pos]; - addbyte(0); - CALL_FUNC((uintptr_t)CF_SET); - addbyte(0x85); /*TEST EAX,EAX*/ - addbyte(0xc0); - if (not) - addbyte(0x75); /*JNZ +*/ - else - addbyte(0x74); /*JZ +*/ - addbyte(7+5+(timing_bt ? 4 : 0)); - - if (!not) - *jump1 = (uintptr_t)&codeblock[block_current].data[block_pos] - (uintptr_t)jump1 - 1; - addbyte(0xC7); /*MOVL [pc], new_pc*/ - addbyte(0x45); - addbyte((uint8_t)cpu_state_offset(pc)); - addlong(op_pc+pc_offset+offset); - if (timing_bt) - { - addbyte(0x83); /*SUB $codegen_block_cycles, cyclcs*/ - addbyte(0x6d); - addbyte((uint8_t)cpu_state_offset(_cycles)); - addbyte(timing_bt); - } - addbyte(0xe9); /*JMP end*/ - addlong(BLOCK_EXIT_OFFSET - (block_pos + 4)); - if (not) - *jump1 = (uintptr_t)&codeblock[block_current].data[block_pos] - (uintptr_t)jump1 - 1; -} - -static inline void BRANCH_COND_L(int pc_offset, uint32_t op_pc, uint32_t offset, int not) -{ - CALL_FUNC((uintptr_t)NF_SET); - addbyte(0x85); /*TEST EAX,EAX*/ - addbyte(0xc0); - addbyte(0x0f); /*SETNE BL*/ - addbyte(0x95); - addbyte(0xc3); - CALL_FUNC((uintptr_t)VF_SET); - addbyte(0x85); /*TEST EAX,EAX*/ - addbyte(0xc0); - addbyte(0x0f); /*SETNE AL*/ - addbyte(0x95); - addbyte(0xc0); - addbyte(0x38); /*CMP AL, BL*/ - addbyte(0xd8); - if (not) - addbyte(0x75); /*JNZ +*/ - else - addbyte(0x74); /*JZ +*/ - addbyte(7+5+(timing_bt ? 4 : 0)); - addbyte(0xC7); /*MOVL [pc], new_pc*/ - addbyte(0x45); - addbyte((uint8_t)cpu_state_offset(pc)); - addlong(op_pc+pc_offset+offset); - if (timing_bt) - { - addbyte(0x83); /*SUB $codegen_block_cycles, cyclcs*/ - addbyte(0x6d); - addbyte((uint8_t)cpu_state_offset(_cycles)); - addbyte(timing_bt); - } - addbyte(0xe9); /*JMP end*/ - addlong(BLOCK_EXIT_OFFSET - (block_pos + 4)); -} - -static inline void BRANCH_COND_LE(int pc_offset, uint32_t op_pc, uint32_t offset, int not) -{ - uint8_t *jump1; - if (codegen_flags_changed && cpu_state.flags_op != FLAGS_UNKNOWN) - { - addbyte(0x83); /*CMP flags_res, 0*/ - addbyte(0x7d); - addbyte((uint8_t)cpu_state_offset(flags_res)); - addbyte(0); - addbyte(0x74); /*JZ +*/ - } - else - { - CALL_FUNC((uintptr_t)ZF_SET); - addbyte(0x85); /*TEST EAX,EAX*/ - addbyte(0xc0); - addbyte(0x75); /*JNZ +*/ - } - jump1 = &codeblock[block_current].data[block_pos]; - addbyte(0); - CALL_FUNC((uintptr_t)NF_SET); - addbyte(0x85); /*TEST EAX,EAX*/ - addbyte(0xc0); - addbyte(0x0f); /*SETNE BL*/ - addbyte(0x95); - addbyte(0xc3); - CALL_FUNC((uintptr_t)VF_SET); - addbyte(0x85); /*TEST EAX,EAX*/ - addbyte(0xc0); - addbyte(0x0f); /*SETNE AL*/ - addbyte(0x95); - addbyte(0xc0); - addbyte(0x38); /*CMP AL, BL*/ - addbyte(0xd8); - if (not) - addbyte(0x75); /*JNZ +*/ - else - addbyte(0x74); /*JZ +*/ - addbyte(7+5+(timing_bt ? 4 : 0)); - if (!not) - *jump1 = (uintptr_t)&codeblock[block_current].data[block_pos] - (uintptr_t)jump1 - 1; - addbyte(0xC7); /*MOVL [pc], new_pc*/ - addbyte(0x45); - addbyte((uint8_t)cpu_state_offset(pc)); - addlong(op_pc+pc_offset+offset); - if (timing_bt) - { - addbyte(0x83); /*SUB $codegen_block_cycles, cyclcs*/ - addbyte(0x6d); - addbyte((uint8_t)cpu_state_offset(_cycles)); - addbyte(timing_bt); - } - addbyte(0xe9); /*JMP end*/ - addlong(BLOCK_EXIT_OFFSET - (block_pos + 4)); - if (not) - *jump1 = (uintptr_t)&codeblock[block_current].data[block_pos] - (uintptr_t)jump1 - 1; -} - -static inline int LOAD_VAR_W(uintptr_t addr) -{ - int host_reg = REG_EBX; - - if (addr >= (uintptr_t)&cpu_state && addr < ((uintptr_t)&cpu_state)+0x100) - { - addbyte(0x0f); /*MOVZX host_reg, offset[cpu_state]*/ - addbyte(0xb7); - addbyte(0x45 | (host_reg << 3)); - addbyte(addr - (uintptr_t)&cpu_state - 128); - } - else if (IS_32_ADDR(addr)) - { - addbyte(0x0f); /*MOVZX host_reg,[reg]*/ - addbyte(0xb7); - addbyte(0x04 | (host_reg << 3)); - addbyte(0x25); - addlong((uint32_t)addr); - } - else - { - addbyte(0x48); /*MOV host_reg, &addr*/ - addbyte(0xb8 | host_reg); - addquad(addr); - addbyte(0x0f); /*MOVZX host_reg, [host_reg]*/ - addbyte(0xb7); - addbyte(host_reg | (host_reg << 3)); - } - - return host_reg; -} -static inline int LOAD_VAR_WL(uintptr_t addr) -{ - return LOAD_VAR_W(addr); -} -static inline int LOAD_VAR_L(uintptr_t addr) -{ - int host_reg = REG_EBX; - - if (addr >= (uintptr_t)&cpu_state && addr < ((uintptr_t)&cpu_state)+0x100) - { - addbyte(0x8b); /*MOVL host_reg, offset[cpu_state]*/ - addbyte(0x45 | (host_reg << 3)); - addbyte(addr - (uintptr_t)&cpu_state - 128); - } - else if (IS_32_ADDR(addr)) - { - addbyte(0x8b); /*MOVL host_reg,[reg]*/ - addbyte(0x04 | (host_reg << 3)); - addbyte(0x25); - addlong((uint32_t)addr); - } - else - { - addbyte(0x48); /*MOV host_reg, &addr*/ - addbyte(0xb8 | host_reg); - addquad(addr); - addbyte(0x8b); /*MOVL host_reg, [host_reg]*/ - addbyte(host_reg | (host_reg << 3)); - } - - return host_reg; -} - -static inline int COPY_REG(int src_reg) -{ - if (src_reg & 8) - addbyte(0x44); + if (host_reg & 8) { + addbyte(0x44); /*MOV EDX, dst_reg*/ addbyte(0x89); - addbyte(0xc0 | REG_ECX | ((src_reg & 7) << 3)); - - return REG_ECX | (src_reg & 0x10); -} + addbyte(0xc0 | ((host_reg & 7) << 3) | REG_EDX); -static inline int LOAD_HOST_REG(int host_reg) + host_reg = (host_reg & 0x10) | REG_EDX; + } + + SUB_HOST_REG_IMM_B(host_reg, imm); + + return host_reg; +} +static __inline int +CMP_HOST_REG_IMM_W(int host_reg, uint16_t imm) { - if (host_reg & 8) - addbyte(0x44); + if (host_reg & 8) { + addbyte(0x44); /*MOV EDX, dst_reg*/ addbyte(0x89); - addbyte(0xc0 | REG_EBX | ((host_reg & 7) << 3)); - - return REG_EBX | (host_reg & 0x10); + addbyte(0xc0 | ((host_reg & 7) << 3) | REG_EDX); + + host_reg = REG_EDX; + } + + SUB_HOST_REG_IMM_W(host_reg, imm); + + return host_reg; +} +static __inline int +CMP_HOST_REG_IMM_L(int host_reg, uint32_t imm) +{ + if (host_reg & 8) { + addbyte(0x44); /*MOV EDX, dst_reg*/ + addbyte(0x89); + addbyte(0xc0 | ((host_reg & 7) << 3) | REG_EDX); + + host_reg = REG_EDX; + } + + SUB_HOST_REG_IMM(host_reg, imm); + + return host_reg; } -static inline int ZERO_EXTEND_W_B(int reg) +static __inline void +LOAD_STACK_TO_EA(int off) { - if (reg & 0x10) - { - addbyte(0x44); /*MOV EAX, reg*/ - addbyte(0x89); - addbyte(0xc0 | (reg << 3)); - addbyte(0x0f); /*MOVZX EAX, AH*/ - addbyte(0xb6); - addbyte(0xc4); - - return REG_EAX; + if (stack32) { + addbyte(0x8b); /*MOVL EAX,[ESP]*/ + addbyte(0x45 | (REG_EAX << 3)); + addbyte((uint8_t) cpu_state_offset(regs[REG_ESP].l)); + if (off) { + addbyte(0x83); /*ADD EAX, off*/ + addbyte(0xc0 | (0 << 3) | REG_EAX); + addbyte(off); } - - if (reg & 8) - addbyte(0x41); - addbyte(0x0f); /*MOVZX regl, regb*/ - addbyte(0xb6); - addbyte(0xc0 | (reg & 7)); - - return REG_EAX; -} -static inline int ZERO_EXTEND_L_B(int reg) -{ - if (reg & 0x10) - { - addbyte(0x44); /*MOV EAX, reg*/ - addbyte(0x89); - addbyte(0xc0 | (reg << 3)); - addbyte(0x0f); /*MOVZX EAX, AH*/ - addbyte(0xb6); - addbyte(0xc4); - - return REG_EAX; - } - - if (reg & 8) - addbyte(0x41); - addbyte(0x0f); /*MOVZX regl, regb*/ - addbyte(0xb6); - addbyte(0xc0 | (reg & 7)); - - return REG_EAX; -} -static inline int ZERO_EXTEND_L_W(int reg) -{ - if (reg & 8) - addbyte(0x41); - addbyte(0x0f); /*MOVZX regl, regw*/ + } else { + addbyte(0x0f); /*MOVZX EAX,W[ESP]*/ addbyte(0xb7); - addbyte(0xc0 | (reg & 7)); - - return REG_EAX; + addbyte(0x45 | (REG_EAX << 3)); + addbyte((uint8_t) cpu_state_offset(regs[REG_ESP].w)); + if (off) { + addbyte(0x66); /*ADD AX, off*/ + addbyte(0x05); + addword(off); + } + } +} +static __inline void +LOAD_EBP_TO_EA(int off) +{ + if (stack32) { + addbyte(0x8b); /*MOVL EAX,[EBP]*/ + addbyte(0x45 | (REG_EAX << 3)); + addbyte((uint8_t) cpu_state_offset(regs[REG_EBP].l)); + if (off) { + addbyte(0x83); /*ADD EAX, off*/ + addbyte(0xc0 | (0 << 3) | REG_EAX); + addbyte(off); + } + } else { + addbyte(0x0f); /*MOVZX EAX,W[EBP]*/ + addbyte(0xb7); + addbyte(0x45 | (REG_EAX << 3)); + addbyte((uint8_t) cpu_state_offset(regs[REG_BP].l)); + if (off) { + addbyte(0x66); /*ADD AX, off*/ + addbyte(0x05); + addword(off); + } + } } -static inline int SIGN_EXTEND_W_B(int reg) +static __inline void +SP_MODIFY(int off) { - if (reg & 0x10) - { - addbyte(0x44); /*MOV EAX, reg*/ - addbyte(0x89); - addbyte(0xc0 | (reg << 3)); - addbyte(0x0f); /*MOVSX EAX, AH*/ - addbyte(0xbe); - addbyte(0xc4); - - return REG_EAX; + if (stack32) { + if (off < 0x80) { + addbyte(0x83); /*ADD [ESP], off*/ + addbyte(0x45); + addbyte((uint8_t) cpu_state_offset(regs[REG_ESP].l)); + addbyte(off); + } else { + addbyte(0x81); /*ADD [ESP], off*/ + addbyte(0x45); + addbyte((uint8_t) cpu_state_offset(regs[REG_ESP].l)); + addlong(off); } - - if (reg & 8) - addbyte(0x41); - addbyte(0x0f); /*MOVSX regl, regb*/ - addbyte(0xbe); - addbyte(0xc0 | (reg & 7)); - - return REG_EAX; -} -static inline int SIGN_EXTEND_L_B(int reg) -{ - if (reg & 0x10) - { - addbyte(0x44); /*MOV EAX, reg*/ - addbyte(0x89); - addbyte(0xc0 | (reg << 3)); - addbyte(0x0f); /*MOVSX EAX, AH*/ - addbyte(0xbe); - addbyte(0xc4); - - return REG_EAX; + } else { + if (off < 0x80) { + addbyte(0x66); /*ADD [SP], off*/ + addbyte(0x83); + addbyte(0x45); + addbyte((uint8_t) cpu_state_offset(regs[REG_ESP].w)); + addbyte(off); + } else { + addbyte(0x66); /*ADD [SP], off*/ + addbyte(0x81); + addbyte(0x45); + addbyte((uint8_t) cpu_state_offset(regs[REG_ESP].w)); + addword(off); } - - if (reg & 8) - addbyte(0x41); - addbyte(0x0f); /*MOVSX regl, regb*/ - addbyte(0xbe); - addbyte(0xc0 | (reg & 7)); - - return REG_EAX; -} -static inline int SIGN_EXTEND_L_W(int reg) -{ - if (reg & 8) - addbyte(0x41); - addbyte(0x0f); /*MOVSX regl, regw*/ - addbyte(0xbf); - addbyte(0xc0 | (reg & 7)); - - return REG_EAX; + } } -static inline void SHL_B_IMM(int reg, int count) +static __inline void +TEST_ZERO_JUMP_W(int host_reg, uint32_t new_pc, int taken_cycles) { - if (reg & 0x10) - { - addbyte(0x44); /*MOV EAX, reg*/ - addbyte(0x89); - addbyte(0xc0 | REG_EAX | ((reg & 7) << 3)); - addbyte(0xc0); /*SHL AH, count*/ - addbyte(0xe0 | REG_AH); - addbyte(count); - addbyte(0x41); /*MOV reg, EAX*/ - addbyte(0x89); - addbyte(0xc0 | (REG_EAX << 3) | (reg & 7)); - } - else - { - if (reg & 8) - addbyte(0x41); - addbyte(0xc0); /*SHL reg, count*/ - addbyte(0xc0 | (reg & 7) | 0x20); - addbyte(count); - } + addbyte(0x66); /*CMPW host_reg, 0*/ + if (host_reg & 8) + addbyte(0x41); + addbyte(0x83); + addbyte(0xc0 | 0x38 | (host_reg & 7)); + addbyte(0); + addbyte(0x75); /*JNZ +*/ + addbyte(7 + 5 + (taken_cycles ? 4 : 0)); + addbyte(0xC7); /*MOVL [pc], new_pc*/ + addbyte(0x45); + addbyte((uint8_t) cpu_state_offset(pc)); + addlong(new_pc); + if (taken_cycles) { + addbyte(0x83); /*SUB $codegen_block_cycles, cyclcs*/ + addbyte(0x6d); + addbyte((uint8_t) cpu_state_offset(_cycles)); + addbyte(taken_cycles); + } + addbyte(0xe9); /*JMP end*/ + addlong(BLOCK_EXIT_OFFSET - (block_pos + 4)); } -static inline void SHL_W_IMM(int reg, int count) +static __inline void +TEST_ZERO_JUMP_L(int host_reg, uint32_t new_pc, int taken_cycles) { - addbyte(0x66); /*SHL reg, count*/ - if (reg & 8) - addbyte(0x41); - addbyte(0xc1); - addbyte(0xc0 | (reg & 7) | 0x20); - addbyte(count); -} -static inline void SHL_L_IMM(int reg, int count) -{ - if (reg & 8) - addbyte(0x41); - addbyte(0xc1); /*SHL reg, count*/ - addbyte(0xc0 | (reg & 7) | 0x20); - addbyte(count); -} -static inline void SHR_B_IMM(int reg, int count) -{ - if (reg & 0x10) - { - addbyte(0x44); /*MOV EAX, reg*/ - addbyte(0x89); - addbyte(0xc0 | REG_EAX | ((reg & 7) << 3)); - addbyte(0xc0); /*SHR AH, count*/ - addbyte(0xe8 | REG_AH); - addbyte(count); - addbyte(0x41); /*MOV reg, EAX*/ - addbyte(0x89); - addbyte(0xc0 | (REG_EAX << 3) | (reg & 7)); - } - else - { - if (reg & 8) - addbyte(0x41); - addbyte(0xc0); /*SHR reg, count*/ - addbyte(0xc0 | (reg & 7) | 0x28); - addbyte(count); - } -} -static inline void SHR_W_IMM(int reg, int count) -{ - addbyte(0x66); /*SHR reg, count*/ - if (reg & 8) - addbyte(0x41); - addbyte(0xc1); - addbyte(0xc0 | (reg & 7) | 0x28); - addbyte(count); -} -static inline void SHR_L_IMM(int reg, int count) -{ - if (reg & 8) - addbyte(0x41); - addbyte(0xc1); /*SHR reg, count*/ - addbyte(0xc0 | (reg & 7) | 0x28); - addbyte(count); -} -static inline void SAR_B_IMM(int reg, int count) -{ - if (reg & 0x10) - { - addbyte(0x44); /*MOV EAX, reg*/ - addbyte(0x89); - addbyte(0xc0 | REG_EAX | ((reg & 7) << 3)); - addbyte(0xc0); /*SAR AH, count*/ - addbyte(0xf8 | REG_AH); - addbyte(count); - addbyte(0x41); /*MOV reg, EAX*/ - addbyte(0x89); - addbyte(0xc0 | (REG_EAX << 3) | (reg & 7)); - } - else - { - if (reg & 8) - addbyte(0x41); - addbyte(0xc0); /*SAR reg, count*/ - addbyte(0xc0 | (reg & 7) | 0x38); - addbyte(count); - } -} -static inline void SAR_W_IMM(int reg, int count) -{ - addbyte(0x66); /*SAR reg, count*/ - if (reg & 8) - addbyte(0x41); - addbyte(0xc1); - addbyte(0xc0 | (reg & 7) | 0x38); - addbyte(count); -} -static inline void SAR_L_IMM(int reg, int count) -{ - if (reg & 8) - addbyte(0x41); - addbyte(0xc1); /*SAR reg, count*/ - addbyte(0xc0 | (reg & 7) | 0x38); - addbyte(count); + if (host_reg & 8) + addbyte(0x41); + addbyte(0x83); /*CMPW host_reg, 0*/ + addbyte(0xc0 | 0x38 | (host_reg & 7)); + addbyte(0); + addbyte(0x75); /*JNZ +*/ + addbyte(7 + 5 + (taken_cycles ? 4 : 0)); + addbyte(0xC7); /*MOVL [pc], new_pc*/ + addbyte(0x45); + addbyte((uint8_t) cpu_state_offset(pc)); + addlong(new_pc); + if (taken_cycles) { + addbyte(0x83); /*SUB $codegen_block_cycles, cyclcs*/ + addbyte(0x6d); + addbyte((uint8_t) cpu_state_offset(_cycles)); + addbyte(taken_cycles); + } + addbyte(0xe9); /*JMP end*/ + addlong(BLOCK_EXIT_OFFSET - (block_pos + 4)); } -static inline void NEG_HOST_REG_B(int reg) +static __inline void +TEST_NONZERO_JUMP_W(int host_reg, uint32_t new_pc, int taken_cycles) { - if (reg & 0x10) - { - if (reg & 8) - addbyte(0x44); - addbyte(0x89); /*MOV BX, reg*/ - addbyte(0xc3 | ((reg & 7) << 3)); - addbyte(0xf6); /*NEG BH*/ - addbyte(0xdf); - if (reg & 8) - addbyte(0x41); - addbyte(0x89); /*MOV reg, BX*/ - addbyte(0xd8 | (reg & 7)); - } - else - { - if (reg & 8) - addbyte(0x41); - addbyte(0xf6); - addbyte(0xd8 | (reg & 7)); - } + addbyte(0x66); /*CMPW host_reg, 0*/ + if (host_reg & 8) + addbyte(0x41); + addbyte(0x83); + addbyte(0xc0 | 0x38 | (host_reg & 7)); + addbyte(0); + addbyte(0x74); /*JZ +*/ + addbyte(7 + 5 + (taken_cycles ? 4 : 0)); + addbyte(0xC7); /*MOVL [pc], new_pc*/ + addbyte(0x45); + addbyte((uint8_t) cpu_state_offset(pc)); + addlong(new_pc); + if (taken_cycles) { + addbyte(0x83); /*SUB $codegen_block_cycles, cyclcs*/ + addbyte(0x6d); + addbyte((uint8_t) cpu_state_offset(_cycles)); + addbyte(taken_cycles); + } + addbyte(0xe9); /*JMP end*/ + addlong(BLOCK_EXIT_OFFSET - (block_pos + 4)); } -static inline void NEG_HOST_REG_W(int reg) +static __inline void +TEST_NONZERO_JUMP_L(int host_reg, uint32_t new_pc, int taken_cycles) { - addbyte(0x66); - if (reg & 8) - addbyte(0x41); - addbyte(0xf7); - addbyte(0xd8 | (reg & 7)); + if (host_reg & 8) + addbyte(0x41); + addbyte(0x83); /*CMPW host_reg, 0*/ + addbyte(0xc0 | 0x38 | (host_reg & 7)); + addbyte(0); + addbyte(0x74); /*JZ +*/ + addbyte(7 + 5 + (taken_cycles ? 4 : 0)); + addbyte(0xC7); /*MOVL [pc], new_pc*/ + addbyte(0x45); + addbyte((uint8_t) cpu_state_offset(pc)); + addlong(new_pc); + if (taken_cycles) { + addbyte(0x83); /*SUB $codegen_block_cycles, cyclcs*/ + addbyte(0x6d); + addbyte((uint8_t) cpu_state_offset(_cycles)); + addbyte(taken_cycles); + } + addbyte(0xe9); /*JMP end*/ + addlong(BLOCK_EXIT_OFFSET - (block_pos + 4)); } -static inline void NEG_HOST_REG_L(int reg) -{ - if (reg & 8) - addbyte(0x41); - addbyte(0xf7); - addbyte(0xd8 | (reg & 7)); -} - -static inline void FP_ENTER() +static __inline void +BRANCH_COND_BE(int pc_offset, uint32_t op_pc, uint32_t offset, int not ) { - if (codegen_fpu_entered) - return; - if (IS_32_ADDR(&cr0)) - { - addbyte(0xf6); /*TEST cr0, 0xc*/ - addbyte(0x04); - addbyte(0x25); - addlong((uintptr_t)&cr0); - addbyte(0x0c); - } - else - { - addbyte(0x48); /*MOV RAX, &cr0*/ - addbyte(0xb8 | REG_EAX); - addquad((uint64_t)&cr0); - addbyte(0xf6); /*TEST [RAX], 0xc*/ - addbyte(0 | (REG_EAX << 3)); - addbyte(0x0c); - } + uint8_t *jump1; + + if (codegen_flags_changed && cpu_state.flags_op != FLAGS_UNKNOWN) { + addbyte(0x83); /*CMP flags_res, 0*/ + addbyte(0x7d); + addbyte((uint8_t) cpu_state_offset(flags_res)); + addbyte(0); addbyte(0x74); /*JZ +*/ - addbyte(7+5+12+5); - addbyte(0xC7); /*MOVL [oldpc],op_old_pc*/ - addbyte(0x45); - addbyte((uint8_t)cpu_state_offset(oldpc)); - addlong(op_old_pc); - load_param_1_32(&codeblock[block_current], 7); - CALL_FUNC((uintptr_t)x86_int); - addbyte(0xe9); /*JMP end*/ - addlong(BLOCK_EXIT_OFFSET - (block_pos + 4)); - - codegen_fpu_entered = 1; + } else { + CALL_FUNC((uintptr_t) ZF_SET); + addbyte(0x85); /*TEST EAX,EAX*/ + addbyte(0xc0); + addbyte(0x75); /*JNZ +*/ + } + jump1 = &codeblock[block_current].data[block_pos]; + addbyte(0); + CALL_FUNC((uintptr_t) CF_SET); + addbyte(0x85); /*TEST EAX,EAX*/ + addbyte(0xc0); + if (not ) + addbyte(0x75); /*JNZ +*/ + else + addbyte(0x74); /*JZ +*/ + addbyte(7 + 5 + (timing_bt ? 4 : 0)); + + if (!not ) + *jump1 = (uintptr_t) &codeblock[block_current].data[block_pos] - (uintptr_t) jump1 - 1; + addbyte(0xC7); /*MOVL [pc], new_pc*/ + addbyte(0x45); + addbyte((uint8_t) cpu_state_offset(pc)); + addlong(op_pc + pc_offset + offset); + if (timing_bt) { + addbyte(0x83); /*SUB $codegen_block_cycles, cyclcs*/ + addbyte(0x6d); + addbyte((uint8_t) cpu_state_offset(_cycles)); + addbyte(timing_bt); + } + addbyte(0xe9); /*JMP end*/ + addlong(BLOCK_EXIT_OFFSET - (block_pos + 4)); + if (not ) + *jump1 = (uintptr_t) &codeblock[block_current].data[block_pos] - (uintptr_t) jump1 - 1; } -static inline void FP_FXCH(int reg) +static __inline void +BRANCH_COND_L(int pc_offset, uint32_t op_pc, uint32_t offset, int not ) { - addbyte(0x8b); /*MOV EAX, [TOP]*/ - addbyte(0x45); - addbyte((uint8_t)cpu_state_offset(TOP)); - addbyte(0x89); /*MOV EBX, EAX*/ - addbyte(0xc3); + CALL_FUNC((uintptr_t) NF_SET); + addbyte(0x85); /*TEST EAX,EAX*/ + addbyte(0xc0); + addbyte(0x0f); /*SETNE BL*/ + addbyte(0x95); + addbyte(0xc3); + CALL_FUNC((uintptr_t) VF_SET); + addbyte(0x85); /*TEST EAX,EAX*/ + addbyte(0xc0); + addbyte(0x0f); /*SETNE AL*/ + addbyte(0x95); + addbyte(0xc0); + addbyte(0x38); /*CMP AL, BL*/ + addbyte(0xd8); + if (not ) + addbyte(0x75); /*JNZ +*/ + else + addbyte(0x74); /*JZ +*/ + addbyte(7 + 5 + (timing_bt ? 4 : 0)); + addbyte(0xC7); /*MOVL [pc], new_pc*/ + addbyte(0x45); + addbyte((uint8_t) cpu_state_offset(pc)); + addlong(op_pc + pc_offset + offset); + if (timing_bt) { + addbyte(0x83); /*SUB $codegen_block_cycles, cyclcs*/ + addbyte(0x6d); + addbyte((uint8_t) cpu_state_offset(_cycles)); + addbyte(timing_bt); + } + addbyte(0xe9); /*JMP end*/ + addlong(BLOCK_EXIT_OFFSET - (block_pos + 4)); +} + +static __inline void +BRANCH_COND_LE(int pc_offset, uint32_t op_pc, uint32_t offset, int not ) +{ + uint8_t *jump1; + if (codegen_flags_changed && cpu_state.flags_op != FLAGS_UNKNOWN) { + addbyte(0x83); /*CMP flags_res, 0*/ + addbyte(0x7d); + addbyte((uint8_t) cpu_state_offset(flags_res)); + addbyte(0); + addbyte(0x74); /*JZ +*/ + } else { + CALL_FUNC((uintptr_t) ZF_SET); + addbyte(0x85); /*TEST EAX,EAX*/ + addbyte(0xc0); + addbyte(0x75); /*JNZ +*/ + } + jump1 = &codeblock[block_current].data[block_pos]; + addbyte(0); + CALL_FUNC((uintptr_t) NF_SET); + addbyte(0x85); /*TEST EAX,EAX*/ + addbyte(0xc0); + addbyte(0x0f); /*SETNE BL*/ + addbyte(0x95); + addbyte(0xc3); + CALL_FUNC((uintptr_t) VF_SET); + addbyte(0x85); /*TEST EAX,EAX*/ + addbyte(0xc0); + addbyte(0x0f); /*SETNE AL*/ + addbyte(0x95); + addbyte(0xc0); + addbyte(0x38); /*CMP AL, BL*/ + addbyte(0xd8); + if (not ) + addbyte(0x75); /*JNZ +*/ + else + addbyte(0x74); /*JZ +*/ + addbyte(7 + 5 + (timing_bt ? 4 : 0)); + if (!not ) + *jump1 = (uintptr_t) &codeblock[block_current].data[block_pos] - (uintptr_t) jump1 - 1; + addbyte(0xC7); /*MOVL [pc], new_pc*/ + addbyte(0x45); + addbyte((uint8_t) cpu_state_offset(pc)); + addlong(op_pc + pc_offset + offset); + if (timing_bt) { + addbyte(0x83); /*SUB $codegen_block_cycles, cyclcs*/ + addbyte(0x6d); + addbyte((uint8_t) cpu_state_offset(_cycles)); + addbyte(timing_bt); + } + addbyte(0xe9); /*JMP end*/ + addlong(BLOCK_EXIT_OFFSET - (block_pos + 4)); + if (not ) + *jump1 = (uintptr_t) &codeblock[block_current].data[block_pos] - (uintptr_t) jump1 - 1; +} + +static __inline int +LOAD_VAR_W(uintptr_t addr) +{ + int host_reg = REG_EBX; + + if (addr >= (uintptr_t) &cpu_state && addr < ((uintptr_t) &cpu_state) + 0x100) { + addbyte(0x0f); /*MOVZX host_reg, offset[cpu_state]*/ + addbyte(0xb7); + addbyte(0x45 | (host_reg << 3)); + addbyte(addr - (uintptr_t) &cpu_state - 128); + } else if (IS_32_ADDR(addr)) { + addbyte(0x0f); /*MOVZX host_reg,[reg]*/ + addbyte(0xb7); + addbyte(0x04 | (host_reg << 3)); + addbyte(0x25); + addlong((uint32_t) addr); + } else { + addbyte(0x48); /*MOV host_reg, &addr*/ + addbyte(0xb8 | host_reg); + addquad(addr); + addbyte(0x0f); /*MOVZX host_reg, [host_reg]*/ + addbyte(0xb7); + addbyte(host_reg | (host_reg << 3)); + } + + return host_reg; +} +static __inline int +LOAD_VAR_WL(uintptr_t addr) +{ + return LOAD_VAR_W(addr); +} +static __inline int +LOAD_VAR_L(uintptr_t addr) +{ + int host_reg = REG_EBX; + + if (addr >= (uintptr_t) &cpu_state && addr < ((uintptr_t) &cpu_state) + 0x100) { + addbyte(0x8b); /*MOVL host_reg, offset[cpu_state]*/ + addbyte(0x45 | (host_reg << 3)); + addbyte(addr - (uintptr_t) &cpu_state - 128); + } else if (IS_32_ADDR(addr)) { + addbyte(0x8b); /*MOVL host_reg,[reg]*/ + addbyte(0x04 | (host_reg << 3)); + addbyte(0x25); + addlong((uint32_t) addr); + } else { + addbyte(0x48); /*MOV host_reg, &addr*/ + addbyte(0xb8 | host_reg); + addquad(addr); + addbyte(0x8b); /*MOVL host_reg, [host_reg]*/ + addbyte(host_reg | (host_reg << 3)); + } + + return host_reg; +} + +static __inline int +COPY_REG(int src_reg) +{ + if (src_reg & 8) + addbyte(0x44); + addbyte(0x89); + addbyte(0xc0 | REG_ECX | ((src_reg & 7) << 3)); + + return REG_ECX | (src_reg & 0x10); +} + +static __inline int +LOAD_HOST_REG(int host_reg) +{ + if (host_reg & 8) + addbyte(0x44); + addbyte(0x89); + addbyte(0xc0 | REG_EBX | ((host_reg & 7) << 3)); + + return REG_EBX | (host_reg & 0x10); +} + +static __inline int +ZERO_EXTEND_W_B(int reg) +{ + if (reg & 0x10) { + addbyte(0x44); /*MOV EAX, reg*/ + addbyte(0x89); + addbyte(0xc0 | (reg << 3)); + addbyte(0x0f); /*MOVZX EAX, AH*/ + addbyte(0xb6); + addbyte(0xc4); + + return REG_EAX; + } + + if (reg & 8) + addbyte(0x41); + addbyte(0x0f); /*MOVZX regl, regb*/ + addbyte(0xb6); + addbyte(0xc0 | (reg & 7)); + + return REG_EAX; +} +static __inline int +ZERO_EXTEND_L_B(int reg) +{ + if (reg & 0x10) { + addbyte(0x44); /*MOV EAX, reg*/ + addbyte(0x89); + addbyte(0xc0 | (reg << 3)); + addbyte(0x0f); /*MOVZX EAX, AH*/ + addbyte(0xb6); + addbyte(0xc4); + + return REG_EAX; + } + + if (reg & 8) + addbyte(0x41); + addbyte(0x0f); /*MOVZX regl, regb*/ + addbyte(0xb6); + addbyte(0xc0 | (reg & 7)); + + return REG_EAX; +} +static __inline int +ZERO_EXTEND_L_W(int reg) +{ + if (reg & 8) + addbyte(0x41); + addbyte(0x0f); /*MOVZX regl, regw*/ + addbyte(0xb7); + addbyte(0xc0 | (reg & 7)); + + return REG_EAX; +} + +static __inline int +SIGN_EXTEND_W_B(int reg) +{ + if (reg & 0x10) { + addbyte(0x44); /*MOV EAX, reg*/ + addbyte(0x89); + addbyte(0xc0 | (reg << 3)); + addbyte(0x0f); /*MOVSX EAX, AH*/ + addbyte(0xbe); + addbyte(0xc4); + + return REG_EAX; + } + + if (reg & 8) + addbyte(0x41); + addbyte(0x0f); /*MOVSX regl, regb*/ + addbyte(0xbe); + addbyte(0xc0 | (reg & 7)); + + return REG_EAX; +} +static __inline int +SIGN_EXTEND_L_B(int reg) +{ + if (reg & 0x10) { + addbyte(0x44); /*MOV EAX, reg*/ + addbyte(0x89); + addbyte(0xc0 | (reg << 3)); + addbyte(0x0f); /*MOVSX EAX, AH*/ + addbyte(0xbe); + addbyte(0xc4); + + return REG_EAX; + } + + if (reg & 8) + addbyte(0x41); + addbyte(0x0f); /*MOVSX regl, regb*/ + addbyte(0xbe); + addbyte(0xc0 | (reg & 7)); + + return REG_EAX; +} +static __inline int +SIGN_EXTEND_L_W(int reg) +{ + if (reg & 8) + addbyte(0x41); + addbyte(0x0f); /*MOVSX regl, regw*/ + addbyte(0xbf); + addbyte(0xc0 | (reg & 7)); + + return REG_EAX; +} + +static __inline void +SHL_B_IMM(int reg, int count) +{ + if (reg & 0x10) { + addbyte(0x44); /*MOV EAX, reg*/ + addbyte(0x89); + addbyte(0xc0 | REG_EAX | ((reg & 7) << 3)); + addbyte(0xc0); /*SHL AH, count*/ + addbyte(0xe0 | REG_AH); + addbyte(count); + addbyte(0x41); /*MOV reg, EAX*/ + addbyte(0x89); + addbyte(0xc0 | (REG_EAX << 3) | (reg & 7)); + } else { + if (reg & 8) + addbyte(0x41); + addbyte(0xc0); /*SHL reg, count*/ + addbyte(0xc0 | (reg & 7) | 0x20); + addbyte(count); + } +} +static __inline void +SHL_W_IMM(int reg, int count) +{ + addbyte(0x66); /*SHL reg, count*/ + if (reg & 8) + addbyte(0x41); + addbyte(0xc1); + addbyte(0xc0 | (reg & 7) | 0x20); + addbyte(count); +} +static __inline void +SHL_L_IMM(int reg, int count) +{ + if (reg & 8) + addbyte(0x41); + addbyte(0xc1); /*SHL reg, count*/ + addbyte(0xc0 | (reg & 7) | 0x20); + addbyte(count); +} +static __inline void +SHR_B_IMM(int reg, int count) +{ + if (reg & 0x10) { + addbyte(0x44); /*MOV EAX, reg*/ + addbyte(0x89); + addbyte(0xc0 | REG_EAX | ((reg & 7) << 3)); + addbyte(0xc0); /*SHR AH, count*/ + addbyte(0xe8 | REG_AH); + addbyte(count); + addbyte(0x41); /*MOV reg, EAX*/ + addbyte(0x89); + addbyte(0xc0 | (REG_EAX << 3) | (reg & 7)); + } else { + if (reg & 8) + addbyte(0x41); + addbyte(0xc0); /*SHR reg, count*/ + addbyte(0xc0 | (reg & 7) | 0x28); + addbyte(count); + } +} +static __inline void +SHR_W_IMM(int reg, int count) +{ + addbyte(0x66); /*SHR reg, count*/ + if (reg & 8) + addbyte(0x41); + addbyte(0xc1); + addbyte(0xc0 | (reg & 7) | 0x28); + addbyte(count); +} +static __inline void +SHR_L_IMM(int reg, int count) +{ + if (reg & 8) + addbyte(0x41); + addbyte(0xc1); /*SHR reg, count*/ + addbyte(0xc0 | (reg & 7) | 0x28); + addbyte(count); +} +static __inline void +SAR_B_IMM(int reg, int count) +{ + if (reg & 0x10) { + addbyte(0x44); /*MOV EAX, reg*/ + addbyte(0x89); + addbyte(0xc0 | REG_EAX | ((reg & 7) << 3)); + addbyte(0xc0); /*SAR AH, count*/ + addbyte(0xf8 | REG_AH); + addbyte(count); + addbyte(0x41); /*MOV reg, EAX*/ + addbyte(0x89); + addbyte(0xc0 | (REG_EAX << 3) | (reg & 7)); + } else { + if (reg & 8) + addbyte(0x41); + addbyte(0xc0); /*SAR reg, count*/ + addbyte(0xc0 | (reg & 7) | 0x38); + addbyte(count); + } +} +static __inline void +SAR_W_IMM(int reg, int count) +{ + addbyte(0x66); /*SAR reg, count*/ + if (reg & 8) + addbyte(0x41); + addbyte(0xc1); + addbyte(0xc0 | (reg & 7) | 0x38); + addbyte(count); +} +static __inline void +SAR_L_IMM(int reg, int count) +{ + if (reg & 8) + addbyte(0x41); + addbyte(0xc1); /*SAR reg, count*/ + addbyte(0xc0 | (reg & 7) | 0x38); + addbyte(count); +} + +static __inline void +NEG_HOST_REG_B(int reg) +{ + if (reg & 0x10) { + if (reg & 8) + addbyte(0x44); + addbyte(0x89); /*MOV BX, reg*/ + addbyte(0xc3 | ((reg & 7) << 3)); + addbyte(0xf6); /*NEG BH*/ + addbyte(0xdf); + if (reg & 8) + addbyte(0x41); + addbyte(0x89); /*MOV reg, BX*/ + addbyte(0xd8 | (reg & 7)); + } else { + if (reg & 8) + addbyte(0x41); + addbyte(0xf6); + addbyte(0xd8 | (reg & 7)); + } +} +static __inline void +NEG_HOST_REG_W(int reg) +{ + addbyte(0x66); + if (reg & 8) + addbyte(0x41); + addbyte(0xf7); + addbyte(0xd8 | (reg & 7)); +} +static __inline void +NEG_HOST_REG_L(int reg) +{ + if (reg & 8) + addbyte(0x41); + addbyte(0xf7); + addbyte(0xd8 | (reg & 7)); +} + +static __inline void +FP_ENTER(void) +{ + if (codegen_fpu_entered) + return; + if (IS_32_ADDR(&cr0)) { + addbyte(0xf6); /*TEST cr0, 0xc*/ + addbyte(0x04); + addbyte(0x25); + addlong((uintptr_t) &cr0); + addbyte(0x0c); + } else { + addbyte(0x48); /*MOV RAX, &cr0*/ + addbyte(0xb8 | REG_EAX); + addquad((uint64_t) &cr0); + addbyte(0xf6); /*TEST [RAX], 0xc*/ + addbyte(0 | (REG_EAX << 3)); + addbyte(0x0c); + } + addbyte(0x74); /*JZ +*/ + addbyte(7 + 5 + 12 + 5); + addbyte(0xC7); /*MOVL [oldpc],op_old_pc*/ + addbyte(0x45); + addbyte((uint8_t) cpu_state_offset(oldpc)); + addlong(op_old_pc); + load_param_1_32(&codeblock[block_current], 7); + CALL_FUNC((uintptr_t) x86_int); + addbyte(0xe9); /*JMP end*/ + addlong(BLOCK_EXIT_OFFSET - (block_pos + 4)); + + codegen_fpu_entered = 1; +} + +static __inline void +FP_FXCH(int reg) +{ + addbyte(0x8b); /*MOV EAX, [TOP]*/ + addbyte(0x45); + addbyte((uint8_t) cpu_state_offset(TOP)); + addbyte(0x89); /*MOV EBX, EAX*/ + addbyte(0xc3); + addbyte(0x83); /*ADD EAX, reg*/ + addbyte(0xc0); + addbyte(reg); + + addbyte(0x48); /*MOV RDX, ST[RBX*8]*/ + addbyte(0x8b); + addbyte(0x54); + addbyte(0xdd); + addbyte((uint8_t) cpu_state_offset(ST)); + addbyte(0x83); /*AND EAX, 7*/ + addbyte(0xe0); + addbyte(0x07); + addbyte(0x48); /*MOV RCX, ST[RAX*8]*/ + addbyte(0x8b); + addbyte(0x4c); + addbyte(0xc5); + addbyte((uint8_t) cpu_state_offset(ST)); + addbyte(0x48); /*MOV ST[RAX*8], RDX*/ + addbyte(0x89); + addbyte(0x54); + addbyte(0xc5); + addbyte((uint8_t) cpu_state_offset(ST)); + addbyte(0x48); /*MOV ST[RBX*8], RCX*/ + addbyte(0x89); + addbyte(0x4c); + addbyte(0xdd); + addbyte((uint8_t) cpu_state_offset(ST)); + + addbyte(0x8a); /*MOV CL, tag[EAX]*/ + addbyte(0x4c); + addbyte(0x05); + addbyte((uint8_t) cpu_state_offset(tag)); + addbyte(0x8a); /*MOV DL, tag[EBX]*/ + addbyte(0x54); + addbyte(0x1d); + addbyte((uint8_t) cpu_state_offset(tag)); + addbyte(0x88); /*MOV tag[EBX], CL*/ + addbyte(0x4c); + addbyte(0x1d); + addbyte((uint8_t) cpu_state_offset(tag)); + addbyte(0x88); /*MOV tag[EAX], DL*/ + addbyte(0x54); + addbyte(0x05); + addbyte((uint8_t) cpu_state_offset(tag)); + + addbyte(0x48); /*MOV RDX, MM[RBX*8]*/ + addbyte(0x8b); + addbyte(0x54); + addbyte(0xdd); + addbyte((uint8_t) cpu_state_offset(MM)); + addbyte(0x48); /*MOV RCX, MM[RAX*8]*/ + addbyte(0x8b); + addbyte(0x4c); + addbyte(0xc5); + addbyte((uint8_t) cpu_state_offset(MM)); + addbyte(0x48); /*MOV MM[RAX*8], RDX*/ + addbyte(0x89); + addbyte(0x54); + addbyte(0xc5); + addbyte((uint8_t) cpu_state_offset(MM)); + addbyte(0x48); /*MOV MM[RBX*8], RCX*/ + addbyte(0x89); + addbyte(0x4c); + addbyte(0xdd); + addbyte((uint8_t) cpu_state_offset(MM)); +} + +static __inline void +FP_FLD(int reg) +{ + addbyte(0x8b); /*MOV EAX, [TOP]*/ + addbyte(0x45); + addbyte((uint8_t) cpu_state_offset(TOP)); + addbyte(0x89); /*MOV EBX, EAX*/ + addbyte(0xc3); + if (reg) { addbyte(0x83); /*ADD EAX, reg*/ addbyte(0xc0); addbyte(reg); - - addbyte(0x48); /*MOV RDX, ST[RBX*8]*/ - addbyte(0x8b); - addbyte(0x54); - addbyte(0xdd); - addbyte((uint8_t)cpu_state_offset(ST)); + addbyte(0x83); /*SUB EBX, 1*/ + addbyte(0xeb); + addbyte(0x01); addbyte(0x83); /*AND EAX, 7*/ addbyte(0xe0); addbyte(0x07); - addbyte(0x48); /*MOV RCX, ST[RAX*8]*/ - addbyte(0x8b); - addbyte(0x4c); - addbyte(0xc5); - addbyte((uint8_t)cpu_state_offset(ST)); - addbyte(0x48); /*MOV ST[RAX*8], RDX*/ - addbyte(0x89); - addbyte(0x54); - addbyte(0xc5); - addbyte((uint8_t)cpu_state_offset(ST)); - addbyte(0x48); /*MOV ST[RBX*8], RCX*/ - addbyte(0x89); - addbyte(0x4c); - addbyte(0xdd); - addbyte((uint8_t)cpu_state_offset(ST)); - - addbyte(0x8a); /*MOV CL, tag[EAX]*/ - addbyte(0x4c); - addbyte(0x05); - addbyte((uint8_t)cpu_state_offset(tag)); - addbyte(0x8a); /*MOV DL, tag[EBX]*/ - addbyte(0x54); - addbyte(0x1d); - addbyte((uint8_t)cpu_state_offset(tag)); - addbyte(0x88); /*MOV tag[EBX], CL*/ - addbyte(0x4c); - addbyte(0x1d); - addbyte((uint8_t)cpu_state_offset(tag)); - addbyte(0x88); /*MOV tag[EAX], DL*/ - addbyte(0x54); - addbyte(0x05); - addbyte((uint8_t)cpu_state_offset(tag)); + } else { + addbyte(0x83); /*SUB EBX, 1*/ + addbyte(0xeb); + addbyte(0x01); + } - addbyte(0x48); /*MOV RDX, MM[RBX*8]*/ - addbyte(0x8b); - addbyte(0x54); - addbyte(0xdd); - addbyte((uint8_t)cpu_state_offset(MM)); - addbyte(0x48); /*MOV RCX, MM[RAX*8]*/ - addbyte(0x8b); - addbyte(0x4c); - addbyte(0xc5); - addbyte((uint8_t)cpu_state_offset(MM)); - addbyte(0x48); /*MOV MM[RAX*8], RDX*/ - addbyte(0x89); - addbyte(0x54); - addbyte(0xc5); - addbyte((uint8_t)cpu_state_offset(MM)); - addbyte(0x48); /*MOV MM[RBX*8], RCX*/ - addbyte(0x89); - addbyte(0x4c); - addbyte(0xdd); - addbyte((uint8_t)cpu_state_offset(MM)); + addbyte(0x48); /*MOV RCX, ST[EAX*8]*/ + addbyte(0x8b); + addbyte(0x4c); + addbyte(0xc5); + addbyte((uint8_t) cpu_state_offset(ST)); + addbyte(0x83); /*AND EBX, 7*/ + addbyte(0xe3); + addbyte(0x07); + addbyte(0x48); /*MOV RDX, ST_i64[EAX*8]*/ + addbyte(0x8b); + addbyte(0x54); + addbyte(0xc5); + addbyte((uint8_t) cpu_state_offset(MM)); + addbyte(0x8a); /*MOV AL, [tag+EAX]*/ + addbyte(0x44); + addbyte(0x05); + addbyte((uint8_t) cpu_state_offset(tag)); + addbyte(0x48); /*MOV ST[EBX*8], RCX*/ + addbyte(0x89); + addbyte(0x4c); + addbyte(0xdd); + addbyte((uint8_t) cpu_state_offset(ST)); + addbyte(0x48); /*MOV ST_i64[EBX*8], RDX*/ + addbyte(0x89); + addbyte(0x54); + addbyte(0xdd); + addbyte((uint8_t) cpu_state_offset(MM)); + addbyte(0x88); /*MOV [tag+EBX], AL*/ + addbyte(0x44); + addbyte(0x1d); + addbyte((uint8_t) cpu_state_offset(tag)); + + addbyte(0x89); /*MOV [TOP], EBX*/ + addbyte(0x5d); + addbyte((uint8_t) cpu_state_offset(TOP)); } - - -static inline void FP_FLD(int reg) +static __inline void +FP_FST(int reg) { - addbyte(0x8b); /*MOV EAX, [TOP]*/ - addbyte(0x45); - addbyte((uint8_t)cpu_state_offset(TOP)); - addbyte(0x89); /*MOV EBX, EAX*/ - addbyte(0xc3); - if (reg) - { - addbyte(0x83); /*ADD EAX, reg*/ - addbyte(0xc0); - addbyte(reg); - addbyte(0x83); /*SUB EBX, 1*/ - addbyte(0xeb); - addbyte(0x01); - addbyte(0x83); /*AND EAX, 7*/ - addbyte(0xe0); - addbyte(0x07); - } - else - { - addbyte(0x83); /*SUB EBX, 1*/ - addbyte(0xeb); - addbyte(0x01); - } + addbyte(0x8b); /*MOV EAX, [TOP]*/ + addbyte(0x45); + addbyte((uint8_t) cpu_state_offset(TOP)); + addbyte(0x48); /*MOV RCX, ST[EAX*8]*/ + addbyte(0x8b); + addbyte(0x4c); + addbyte(0xc5); + addbyte((uint8_t) cpu_state_offset(ST)); + addbyte(0x8a); /*MOV BL, [tag+EAX]*/ + addbyte(0x5c); + addbyte(0x05); + addbyte((uint8_t) cpu_state_offset(tag)); - addbyte(0x48); /*MOV RCX, ST[EAX*8]*/ - addbyte(0x8b); - addbyte(0x4c); - addbyte(0xc5); - addbyte((uint8_t)cpu_state_offset(ST)); - addbyte(0x83); /*AND EBX, 7*/ - addbyte(0xe3); + if (reg) { + addbyte(0x83); /*ADD EAX, reg*/ + addbyte(0xc0); + addbyte(reg); + addbyte(0x83); /*AND EAX, 7*/ + addbyte(0xe0); addbyte(0x07); - addbyte(0x48); /*MOV RDX, ST_i64[EAX*8]*/ - addbyte(0x8b); - addbyte(0x54); - addbyte(0xc5); - addbyte((uint8_t)cpu_state_offset(MM)); - addbyte(0x8a); /*MOV AL, [tag+EAX]*/ - addbyte(0x44); - addbyte(0x05); - addbyte((uint8_t)cpu_state_offset(tag)); - addbyte(0x48); /*MOV ST[EBX*8], RCX*/ - addbyte(0x89); - addbyte(0x4c); - addbyte(0xdd); - addbyte((uint8_t)cpu_state_offset(ST)); - addbyte(0x48); /*MOV ST_i64[EBX*8], RDX*/ - addbyte(0x89); - addbyte(0x54); - addbyte(0xdd); - addbyte((uint8_t)cpu_state_offset(MM)); - addbyte(0x88); /*MOV [tag+EBX], AL*/ - addbyte(0x44); - addbyte(0x1d); - addbyte((uint8_t)cpu_state_offset(tag)); + } - addbyte(0x89); /*MOV [TOP], EBX*/ - addbyte(0x5d); - addbyte((uint8_t)cpu_state_offset(TOP)); + addbyte(0x48); /*MOV ST[EAX*8], RCX*/ + addbyte(0x89); + addbyte(0x4c); + addbyte(0xc5); + addbyte((uint8_t) cpu_state_offset(ST)); + addbyte(0x88); /*MOV [tag+EAX], BL*/ + addbyte(0x5c); + addbyte(0x05); + addbyte((uint8_t) cpu_state_offset(tag)); } -static inline void FP_FST(int reg) +static __inline void +FP_POP(void) { - addbyte(0x8b); /*MOV EAX, [TOP]*/ - addbyte(0x45); - addbyte((uint8_t)cpu_state_offset(TOP)); - addbyte(0x48); /*MOV RCX, ST[EAX*8]*/ - addbyte(0x8b); - addbyte(0x4c); - addbyte(0xc5); - addbyte((uint8_t)cpu_state_offset(ST)); - addbyte(0x8a); /*MOV BL, [tag+EAX]*/ - addbyte(0x5c); - addbyte(0x05); - addbyte((uint8_t)cpu_state_offset(tag)); - - if (reg) - { - addbyte(0x83); /*ADD EAX, reg*/ - addbyte(0xc0); - addbyte(reg); - addbyte(0x83); /*AND EAX, 7*/ - addbyte(0xe0); - addbyte(0x07); - } - - addbyte(0x48); /*MOV ST[EAX*8], RCX*/ - addbyte(0x89); - addbyte(0x4c); - addbyte(0xc5); - addbyte((uint8_t)cpu_state_offset(ST)); - addbyte(0x88); /*MOV [tag+EAX], BL*/ - addbyte(0x5c); - addbyte(0x05); - addbyte((uint8_t)cpu_state_offset(tag)); + addbyte(0x8b); /*MOV EAX, [TOP]*/ + addbyte(0x45); + addbyte((uint8_t) cpu_state_offset(TOP)); + addbyte(0xc6); /*MOVB tag[EAX], 3*/ + addbyte(0x44); + addbyte(0x05); + addbyte((uint8_t) cpu_state_offset(tag)); + addbyte(3); + addbyte(0x83); /*ADD AL, 1*/ + addbyte(0xc0); + addbyte(1); + addbyte(0x83); /*AND AL, 7*/ + addbyte(0xe0); + addbyte(7); + addbyte(0x89); /*MOV [TOP], EAX*/ + addbyte(0x45); + addbyte((uint8_t) cpu_state_offset(TOP)); +} +static __inline void +FP_POP2(void) +{ + addbyte(0x8b); /*MOV EAX, [TOP]*/ + addbyte(0x45); + addbyte((uint8_t) cpu_state_offset(TOP)); + addbyte(0xc6); /*MOVB tag[EAX], 3*/ + addbyte(0x44); + addbyte(0x05); + addbyte((uint8_t) cpu_state_offset(tag)); + addbyte(3); + addbyte(0x83); /*ADD AL, 2*/ + addbyte(0xc0); + addbyte(2); + addbyte(0x83); /*AND AL, 7*/ + addbyte(0xe0); + addbyte(7); + addbyte(0x89); /*MOV [TOP], EAX*/ + addbyte(0x45); + addbyte((uint8_t) cpu_state_offset(TOP)); } -static inline void FP_POP() +static __inline void +FP_LOAD_S(void) { - addbyte(0x8b); /*MOV EAX, [TOP]*/ - addbyte(0x45); - addbyte((uint8_t)cpu_state_offset(TOP)); - addbyte(0xc6); /*MOVB tag[EAX], 3*/ - addbyte(0x44); - addbyte(0x05); - addbyte((uint8_t)cpu_state_offset(tag)); - addbyte(3); - addbyte(0x83); /*ADD AL, 1*/ + addbyte(0x8b); /*MOV EBX, TOP*/ + addbyte(0x5d); + addbyte((uint8_t) cpu_state_offset(TOP)); + addbyte(0x66); /*MOVD XMM0, EAX*/ + addbyte(0x0f); + addbyte(0x6e); + addbyte(0xc0); + addbyte(0x83); /*SUB EBX, 1*/ + addbyte(0xeb); + addbyte(0x01); + addbyte(0xf3); /*CVTSS2SD XMM0, XMM0*/ + addbyte(0x0f); + addbyte(0x5a); + addbyte(0xc0); + addbyte(0x83); /*AND EBX, 7*/ + addbyte(0xe3); + addbyte(7); + addbyte(0x85); /*TEST EAX, EAX*/ + addbyte(0xc0); + addbyte(0x89); /*MOV TOP, EBX*/ + addbyte(0x5d); + addbyte((uint8_t) cpu_state_offset(TOP)); + addbyte(0x66); /*MOVQ [ST+EBX*8], XMM0*/ + addbyte(0x0f); + addbyte(0xd6); + addbyte(0x44); + addbyte(0xdd); + addbyte((uint8_t) cpu_state_offset(ST)); + addbyte(0x0f); /*SETE [tag+EBX]*/ + addbyte(0x94); + addbyte(0x44); + addbyte(0x1d); + addbyte((uint8_t) cpu_state_offset(tag)); +} +static __inline void +FP_LOAD_D(void) +{ + addbyte(0x8b); /*MOV EBX, TOP*/ + addbyte(0x5d); + addbyte((uint8_t) cpu_state_offset(TOP)); + addbyte(0x83); /*SUB EBX, 1*/ + addbyte(0xeb); + addbyte(0x01); + addbyte(0x83); /*AND EBX, 7*/ + addbyte(0xe3); + addbyte(7); + addbyte(0x48); /*TEST RAX, RAX*/ + addbyte(0x85); + addbyte(0xc0); + addbyte(0x89); /*MOV TOP, EBX*/ + addbyte(0x5d); + addbyte((uint8_t) cpu_state_offset(TOP)); + addbyte(0x48); /*MOVQ [ST+EBX*8], RAX*/ + addbyte(0x89); + addbyte(0x44); + addbyte(0xdd); + addbyte((uint8_t) cpu_state_offset(ST)); + addbyte(0x0f); /*SETE [tag+EBX]*/ + addbyte(0x94); + addbyte(0x44); + addbyte(0x1d); + addbyte((uint8_t) cpu_state_offset(tag)); +} + +static __inline void +FP_LOAD_IW(void) +{ + addbyte(0x8b); /*MOV EBX, TOP*/ + addbyte(0x5d); + addbyte((uint8_t) cpu_state_offset(TOP)); + addbyte(0x0f); /*MOVSX EAX, AX*/ + addbyte(0xbf); + addbyte(0xc0); + addbyte(0x83); /*SUB EBX, 1*/ + addbyte(0xeb); + addbyte(0x01); + addbyte(0xf2); /*CVTSI2SD XMM0, EAX*/ + addbyte(0x0f); + addbyte(0x2a); + addbyte(0xc0); + addbyte(0x83); /*AND EBX, 7*/ + addbyte(0xe3); + addbyte(7); + addbyte(0x85); /*TEST EAX, EAX*/ + addbyte(0xc0); + addbyte(0x89); /*MOV TOP, EBX*/ + addbyte(0x5d); + addbyte((uint8_t) cpu_state_offset(TOP)); + addbyte(0x66); /*MOVQ [ST+EBX*8], XMM0*/ + addbyte(0x0f); + addbyte(0xd6); + addbyte(0x44); + addbyte(0xdd); + addbyte((uint8_t) cpu_state_offset(ST)); + addbyte(0x0f); /*SETE [tag+EBX]*/ + addbyte(0x94); + addbyte(0x44); + addbyte(0x1d); + addbyte((uint8_t) cpu_state_offset(tag)); +} +static __inline void +FP_LOAD_IL(void) +{ + addbyte(0x8b); /*MOV EBX, TOP*/ + addbyte(0x5d); + addbyte((uint8_t) cpu_state_offset(TOP)); + addbyte(0x83); /*SUB EBX, 1*/ + addbyte(0xeb); + addbyte(0x01); + addbyte(0xf2); /*CVTSI2SD XMM0, EAX*/ + addbyte(0x0f); + addbyte(0x2a); + addbyte(0xc0); + addbyte(0x83); /*AND EBX, 7*/ + addbyte(0xe3); + addbyte(7); + addbyte(0x85); /*TEST EAX, EAX*/ + addbyte(0xc0); + addbyte(0x89); /*MOV TOP, EBX*/ + addbyte(0x5d); + addbyte((uint8_t) cpu_state_offset(TOP)); + addbyte(0x66); /*MOVQ [ST+EBX*8], XMM0*/ + addbyte(0x0f); + addbyte(0xd6); + addbyte(0x44); + addbyte(0xdd); + addbyte((uint8_t) cpu_state_offset(ST)); + addbyte(0x0f); /*SETE [tag+EBX]*/ + addbyte(0x94); + addbyte(0x44); + addbyte(0x1d); + addbyte((uint8_t) cpu_state_offset(tag)); +} +static __inline void +FP_LOAD_IQ(void) +{ + addbyte(0x8b); /*MOV EBX, TOP*/ + addbyte(0x5d); + addbyte((uint8_t) cpu_state_offset(TOP)); + addbyte(0x83); /*SUB EBX, 1*/ + addbyte(0xeb); + addbyte(0x01); + addbyte(0xf2); /*CVTSI2SDQ XMM0, RAX*/ + addbyte(0x48); + addbyte(0x0f); + addbyte(0x2a); + addbyte(0xc0); + addbyte(0x83); /*AND EBX, 7*/ + addbyte(0xe3); + addbyte(7); + addbyte(0x48); /*TEST RAX, RAX*/ + addbyte(0x85); + addbyte(0xc0); + addbyte(0x48); /*MOV [ST_i64+EBX*8], RAX*/ + addbyte(0x89); + addbyte(0x44); + addbyte(0xdd); + addbyte((uint8_t) cpu_state_offset(MM)); + addbyte(0x89); /*MOV TOP, EBX*/ + addbyte(0x5d); + addbyte((uint8_t) cpu_state_offset(TOP)); + addbyte(0x0f); /*SETE AL*/ + addbyte(0x94); + addbyte(0xc0); + addbyte(0x66); /*MOVQ [ST+EBX*8], XMM0*/ + addbyte(0x0f); + addbyte(0xd6); + addbyte(0x44); + addbyte(0xdd); + addbyte((uint8_t) cpu_state_offset(ST)); + addbyte(0x0c); /*OR AL, TAG_UINT64*/ + addbyte(TAG_UINT64); + addbyte(0x88); /*MOV [tag+EBX], AL*/ + addbyte(0x44); + addbyte(0x1d); + addbyte((uint8_t) cpu_state_offset(tag)); +} + +static __inline void +FP_LOAD_IMM_Q(uint64_t v) +{ + addbyte(0x8b); /*MOV EBX, TOP*/ + addbyte(0x5d); + addbyte((uint8_t) cpu_state_offset(TOP)); + addbyte(0x83); /*SUB EBX, 1*/ + addbyte(0xeb); + addbyte(0x01); + addbyte(0x83); /*AND EBX, 7*/ + addbyte(0xe3); + addbyte(7); + addbyte(0xc7); /*MOV ST[EBP+EBX*8], v*/ + addbyte(0x44); + addbyte(0xdd); + addbyte((uint8_t) cpu_state_offset(ST)); + addlong(v & 0xffffffff); + addbyte(0xc7); /*MOV ST[EBP+EBX*8]+4, v*/ + addbyte(0x44); + addbyte(0xdd); + addbyte((uint8_t) cpu_state_offset(ST) + 4); + addlong(v >> 32); + addbyte(0x89); /*MOV TOP, EBX*/ + addbyte(0x5d); + addbyte((uint8_t) cpu_state_offset(TOP)); + addbyte(0xc6); /*MOV [tag+EBX], (v ? 0 : 1)*/ + addbyte(0x44); + addbyte(0x1d); + addbyte((uint8_t) cpu_state_offset(tag)); + addbyte(v ? 0 : 1); +} + +static __inline void +FP_FCHS(void) +{ + addbyte(0x8b); /*MOV EAX, TOP*/ + addbyte(0x45); + addbyte((uint8_t) cpu_state_offset(TOP)); + addbyte(0xf2); /*SUBSD XMM0, XMM0*/ + addbyte(0x0f); + addbyte(0x5c); + addbyte(0xc0); + addbyte(0xf2); /*SUBSD XMM0, ST[EAX*8]*/ + addbyte(0x0f); + addbyte(0x5c); + addbyte(0x44); + addbyte(0xc5); + addbyte((uint8_t) cpu_state_offset(ST)); + addbyte(0x80); /*AND tag[EAX], ~TAG_UINT64*/ + addbyte(0x64); + addbyte(0x05); + addbyte((uint8_t) cpu_state_offset(tag[0])); + addbyte(TAG_NOT_UINT64); + addbyte(0xf2); /*MOVSD ST[EAX*8], XMM0*/ + addbyte(0x0f); + addbyte(0x11); + addbyte(0x44); + addbyte(0xc5); + addbyte((uint8_t) cpu_state_offset(ST)); +} + +static __inline int +FP_LOAD_REG(int reg) +{ + addbyte(0x8b); /*MOV EBX, TOP*/ + addbyte(0x5d); + addbyte((uint8_t) cpu_state_offset(TOP)); + if (reg) { + addbyte(0x83); /*ADD EBX, reg*/ + addbyte(0xc0 | REG_EBX); + addbyte(reg); + addbyte(0x83); /*AND EBX, 7*/ + addbyte(0xe0 | REG_EBX); + addbyte(0x07); + } + addbyte(0xf3); /*MOVQ XMM0, ST[EBX*8]*/ + addbyte(0x0f); + addbyte(0x7e); + addbyte(0x44); + addbyte(0xdd); + addbyte((uint8_t) cpu_state_offset(ST)); + addbyte(0xf2); /*CVTSD2SS XMM0, XMM0*/ + addbyte(0x0f); + addbyte(0x5a); + addbyte(0xc0); + addbyte(0x66); /*MOVD EBX, XMM0*/ + addbyte(0x0f); + addbyte(0x7e); + addbyte(0xc0 | REG_EBX); + + return REG_EBX; +} +static __inline void +FP_LOAD_REG_D(int reg, int *host_reg1, int *host_reg2) +{ + addbyte(0x8b); /*MOV EBX, TOP*/ + addbyte(0x5d); + addbyte((uint8_t) cpu_state_offset(TOP)); + if (reg) { + addbyte(0x83); /*ADD EBX, reg*/ + addbyte(0xc0 | REG_EBX); + addbyte(reg); + addbyte(0x83); /*AND EBX, 7*/ + addbyte(0xe0 | REG_EBX); + addbyte(0x07); + } + addbyte(0x48); /*MOV RBX, ST[EBX*8]*/ + addbyte(0x8b); + addbyte(0x5c); + addbyte(0xdd); + addbyte((uint8_t) cpu_state_offset(ST)); + + *host_reg1 = REG_EBX; +} +static __inline int64_t +x87_fround16_64(double b) +{ + int16_t a; + int16_t c; + + switch ((cpu_state.npxc >> 10) & 3) { + case 0: /*Nearest*/ + a = (int16_t) floor(b); + c = (int16_t) floor(b + 1.0); + if ((b - a) < (c - b)) + return (int64_t) a; + else if ((b - a) > (c - b)) + return (int64_t) c; + else + return (a & 1) ? c : a; + case 1: /*Down*/ + return (int64_t) ((int16_t) floor(b)); + case 2: /*Up*/ + return (int64_t) ((int16_t) ceil(b)); + case 3: /*Chop*/ + return (int64_t) ((int16_t) b); + } + + return 0; +} +static __inline int64_t +x87_fround32_64(double b) +{ + int32_t a; + int32_t c; + + switch ((cpu_state.npxc >> 10) & 3) { + case 0: /*Nearest*/ + a = (int32_t) floor(b); + c = (int32_t) floor(b + 1.0); + if ((b - a) < (c - b)) + return (int64_t) a; + else if ((b - a) > (c - b)) + return (int64_t) c; + else + return (a & 1) ? c : a; + case 1: /*Down*/ + return (int64_t) ((int32_t) floor(b)); + case 2: /*Up*/ + return (int64_t) ((int32_t) ceil(b)); + case 3: /*Chop*/ + return (int64_t) ((int32_t) b); + } + + return 0; +} +static __inline int64_t +x87_fround(double b) +{ + int64_t a; + int64_t c; + + switch ((cpu_state.npxc >> 10) & 3) { + case 0: /*Nearest*/ + a = (int64_t) floor(b); + c = (int64_t) floor(b + 1.0); + if ((b - a) < (c - b)) + return a; + else if ((b - a) > (c - b)) + return c; + else + return (a & 1) ? c : a; + case 1: /*Down*/ + return (int64_t) floor(b); + case 2: /*Up*/ + return (int64_t) ceil(b); + case 3: /*Chop*/ + return (int64_t) b; + } + + return 0; +} +static __inline int +FP_LOAD_REG_INT_W(int reg) +{ + addbyte(0x89); /*MOV EBX, EAX*/ + addbyte(0xc3); + + addbyte(0x8b); /*MOV EAX, [TOP]*/ + addbyte(0x45); + addbyte((uint8_t) cpu_state_offset(TOP)); + if (reg) { + addbyte(0x83); /*ADD EAX, reg*/ addbyte(0xc0); - addbyte(1); - addbyte(0x83); /*AND AL, 7*/ + addbyte(reg); + addbyte(0x83); /*AND EAX, 7*/ addbyte(0xe0); addbyte(7); - addbyte(0x89); /*MOV [TOP], EAX*/ - addbyte(0x45); - addbyte((uint8_t)cpu_state_offset(TOP)); + } + addbyte(0xf3); /*MOVQ XMM0, ST[EAX*8]*/ + addbyte(0x0f); + addbyte(0x7e); + addbyte(0x44); + addbyte(0xc5); + addbyte((uint8_t) cpu_state_offset(ST)); + + CALL_FUNC((uintptr_t) x87_fround16_64); + + addbyte(0x93); /*XCHG EBX, EAX*/ + + return REG_EBX; } -static inline void FP_POP2() +static __inline int +FP_LOAD_REG_INT(int reg) { - addbyte(0x8b); /*MOV EAX, [TOP]*/ - addbyte(0x45); - addbyte((uint8_t)cpu_state_offset(TOP)); - addbyte(0xc6); /*MOVB tag[EAX], 3*/ - addbyte(0x44); - addbyte(0x05); - addbyte((uint8_t)cpu_state_offset(tag)); - addbyte(3); - addbyte(0x83); /*ADD AL, 2*/ + addbyte(0x89); /*MOV EBX, EAX*/ + addbyte(0xc3); + + addbyte(0x8b); /*MOV EAX, [TOP]*/ + addbyte(0x45); + addbyte((uint8_t) cpu_state_offset(TOP)); + if (reg) { + addbyte(0x83); /*ADD EAX, reg*/ addbyte(0xc0); - addbyte(2); - addbyte(0x83); /*AND AL, 7*/ + addbyte(reg); + addbyte(0x83); /*AND EAX, 7*/ addbyte(0xe0); addbyte(7); - addbyte(0x89); /*MOV [TOP], EAX*/ - addbyte(0x45); - addbyte((uint8_t)cpu_state_offset(TOP)); -} + } + addbyte(0xf3); /*MOVQ XMM0, ST[EAX*8]*/ + addbyte(0x0f); + addbyte(0x7e); + addbyte(0x44); + addbyte(0xc5); + addbyte((uint8_t) cpu_state_offset(ST)); -static inline void FP_LOAD_S() + CALL_FUNC((uintptr_t) x87_fround32_64); + + addbyte(0x93); /*XCHG EBX, EAX*/ + + return REG_EBX; +} +static __inline void +FP_LOAD_REG_INT_Q(int reg, int *host_reg1, int *host_reg2) { - addbyte(0x8b); /*MOV EBX, TOP*/ - addbyte(0x5d); - addbyte((uint8_t)cpu_state_offset(TOP)); - addbyte(0x66); /*MOVD XMM0, EAX*/ - addbyte(0x0f); - addbyte(0x6e); + addbyte(0x89); /*MOV EBX, EAX*/ + addbyte(0xc3); + + addbyte(0x8b); /*MOV EAX, [TOP]*/ + addbyte(0x45); + addbyte((uint8_t) cpu_state_offset(TOP)); + if (reg) { + addbyte(0x83); /*ADD EAX, reg*/ addbyte(0xc0); - addbyte(0x83); /*SUB EBX, 1*/ - addbyte(0xeb); - addbyte(0x01); - addbyte(0xf3); /*CVTSS2SD XMM0, XMM0*/ - addbyte(0x0f); - addbyte(0x5a); - addbyte(0xc0); - addbyte(0x83); /*AND EBX, 7*/ - addbyte(0xe3); + addbyte(reg); + addbyte(0x83); /*AND EAX, 7*/ + addbyte(0xe0); addbyte(7); - addbyte(0x85); /*TEST EAX, EAX*/ - addbyte(0xc0); - addbyte(0x89); /*MOV TOP, EBX*/ - addbyte(0x5d); - addbyte((uint8_t)cpu_state_offset(TOP)); - addbyte(0x66); /*MOVQ [ST+EBX*8], XMM0*/ - addbyte(0x0f); - addbyte(0xd6); - addbyte(0x44); - addbyte(0xdd); - addbyte((uint8_t)cpu_state_offset(ST)); - addbyte(0x0f); /*SETE [tag+EBX]*/ - addbyte(0x94); - addbyte(0x44); - addbyte(0x1d); - addbyte((uint8_t)cpu_state_offset(tag)); -} -static inline void FP_LOAD_D() -{ - addbyte(0x8b); /*MOV EBX, TOP*/ - addbyte(0x5d); - addbyte((uint8_t)cpu_state_offset(TOP)); - addbyte(0x83); /*SUB EBX, 1*/ - addbyte(0xeb); - addbyte(0x01); - addbyte(0x83); /*AND EBX, 7*/ - addbyte(0xe3); - addbyte(7); - addbyte(0x48); /*TEST RAX, RAX*/ - addbyte(0x85); - addbyte(0xc0); - addbyte(0x89); /*MOV TOP, EBX*/ - addbyte(0x5d); - addbyte((uint8_t)cpu_state_offset(TOP)); - addbyte(0x48); /*MOVQ [ST+EBX*8], RAX*/ - addbyte(0x89); - addbyte(0x44); - addbyte(0xdd); - addbyte((uint8_t)cpu_state_offset(ST)); - addbyte(0x0f); /*SETE [tag+EBX]*/ - addbyte(0x94); - addbyte(0x44); - addbyte(0x1d); - addbyte((uint8_t)cpu_state_offset(tag)); -} - -static inline void FP_LOAD_IW() -{ - addbyte(0x8b); /*MOV EBX, TOP*/ - addbyte(0x5d); - addbyte((uint8_t)cpu_state_offset(TOP)); - addbyte(0x0f); /*MOVSX EAX, AX*/ - addbyte(0xbf); - addbyte(0xc0); - addbyte(0x83); /*SUB EBX, 1*/ - addbyte(0xeb); - addbyte(0x01); - addbyte(0xf2); /*CVTSI2SD XMM0, EAX*/ - addbyte(0x0f); - addbyte(0x2a); - addbyte(0xc0); - addbyte(0x83); /*AND EBX, 7*/ - addbyte(0xe3); - addbyte(7); - addbyte(0x85); /*TEST EAX, EAX*/ - addbyte(0xc0); - addbyte(0x89); /*MOV TOP, EBX*/ - addbyte(0x5d); - addbyte((uint8_t)cpu_state_offset(TOP)); - addbyte(0x66); /*MOVQ [ST+EBX*8], XMM0*/ - addbyte(0x0f); - addbyte(0xd6); - addbyte(0x44); - addbyte(0xdd); - addbyte((uint8_t)cpu_state_offset(ST)); - addbyte(0x0f); /*SETE [tag+EBX]*/ - addbyte(0x94); - addbyte(0x44); - addbyte(0x1d); - addbyte((uint8_t)cpu_state_offset(tag)); -} -static inline void FP_LOAD_IL() -{ - addbyte(0x8b); /*MOV EBX, TOP*/ - addbyte(0x5d); - addbyte((uint8_t)cpu_state_offset(TOP)); - addbyte(0x83); /*SUB EBX, 1*/ - addbyte(0xeb); - addbyte(0x01); - addbyte(0xf2); /*CVTSI2SD XMM0, EAX*/ - addbyte(0x0f); - addbyte(0x2a); - addbyte(0xc0); - addbyte(0x83); /*AND EBX, 7*/ - addbyte(0xe3); - addbyte(7); - addbyte(0x85); /*TEST EAX, EAX*/ - addbyte(0xc0); - addbyte(0x89); /*MOV TOP, EBX*/ - addbyte(0x5d); - addbyte((uint8_t)cpu_state_offset(TOP)); - addbyte(0x66); /*MOVQ [ST+EBX*8], XMM0*/ - addbyte(0x0f); - addbyte(0xd6); - addbyte(0x44); - addbyte(0xdd); - addbyte((uint8_t)cpu_state_offset(ST)); - addbyte(0x0f); /*SETE [tag+EBX]*/ - addbyte(0x94); - addbyte(0x44); - addbyte(0x1d); - addbyte((uint8_t)cpu_state_offset(tag)); -} -static inline void FP_LOAD_IQ() -{ - addbyte(0x8b); /*MOV EBX, TOP*/ - addbyte(0x5d); - addbyte((uint8_t)cpu_state_offset(TOP)); - addbyte(0x83); /*SUB EBX, 1*/ - addbyte(0xeb); - addbyte(0x01); - addbyte(0xf2); /*CVTSI2SDQ XMM0, RAX*/ - addbyte(0x48); - addbyte(0x0f); - addbyte(0x2a); - addbyte(0xc0); - addbyte(0x83); /*AND EBX, 7*/ - addbyte(0xe3); - addbyte(7); - addbyte(0x48); /*TEST RAX, RAX*/ - addbyte(0x85); - addbyte(0xc0); - addbyte(0x48); /*MOV [ST_i64+EBX*8], RAX*/ - addbyte(0x89); - addbyte(0x44); - addbyte(0xdd); - addbyte((uint8_t)cpu_state_offset(MM)); - addbyte(0x89); /*MOV TOP, EBX*/ - addbyte(0x5d); - addbyte((uint8_t)cpu_state_offset(TOP)); - addbyte(0x0f); /*SETE AL*/ - addbyte(0x94); - addbyte(0xc0); - addbyte(0x66); /*MOVQ [ST+EBX*8], XMM0*/ - addbyte(0x0f); - addbyte(0xd6); - addbyte(0x44); - addbyte(0xdd); - addbyte((uint8_t)cpu_state_offset(ST)); - addbyte(0x0c); /*OR AL, TAG_UINT64*/ - addbyte(TAG_UINT64); - addbyte(0x88); /*MOV [tag+EBX], AL*/ - addbyte(0x44); - addbyte(0x1d); - addbyte((uint8_t)cpu_state_offset(tag)); -} - -static inline void FP_LOAD_IMM_Q(uint64_t v) -{ - addbyte(0x8b); /*MOV EBX, TOP*/ - addbyte(0x5d); - addbyte((uint8_t)cpu_state_offset(TOP)); - addbyte(0x83); /*SUB EBX, 1*/ - addbyte(0xeb); - addbyte(0x01); - addbyte(0x83); /*AND EBX, 7*/ - addbyte(0xe3); - addbyte(7); - addbyte(0xc7); /*MOV ST[EBP+EBX*8], v*/ - addbyte(0x44); - addbyte(0xdd); - addbyte((uint8_t)cpu_state_offset(ST)); - addlong(v & 0xffffffff); - addbyte(0xc7); /*MOV ST[EBP+EBX*8]+4, v*/ - addbyte(0x44); - addbyte(0xdd); - addbyte((uint8_t)cpu_state_offset(ST) + 4); - addlong(v >> 32); - addbyte(0x89); /*MOV TOP, EBX*/ - addbyte(0x5d); - addbyte((uint8_t)cpu_state_offset(TOP)); - addbyte(0xc6); /*MOV [tag+EBX], (v ? 0 : 1)*/ - addbyte(0x44); - addbyte(0x1d); - addbyte((uint8_t)cpu_state_offset(tag)); - addbyte(v ? 0 : 1); -} - -static inline void FP_FCHS() -{ - addbyte(0x8b); /*MOV EAX, TOP*/ - addbyte(0x45); - addbyte((uint8_t)cpu_state_offset(TOP)); - addbyte(0xf2); /*SUBSD XMM0, XMM0*/ - addbyte(0x0f); - addbyte(0x5c); - addbyte(0xc0); - addbyte(0xf2); /*SUBSD XMM0, ST[EAX*8]*/ - addbyte(0x0f); - addbyte(0x5c); - addbyte(0x44); - addbyte(0xc5); - addbyte((uint8_t)cpu_state_offset(ST)); - addbyte(0x80); /*AND tag[EAX], ~TAG_UINT64*/ - addbyte(0x64); - addbyte(0x05); - addbyte((uint8_t)cpu_state_offset(tag[0])); - addbyte(TAG_NOT_UINT64); - addbyte(0xf2); /*MOVSD ST[EAX*8], XMM0*/ - addbyte(0x0f); - addbyte(0x11); - addbyte(0x44); - addbyte(0xc5); - addbyte((uint8_t)cpu_state_offset(ST)); -} - -static inline int FP_LOAD_REG(int reg) -{ - addbyte(0x8b); /*MOV EBX, TOP*/ - addbyte(0x5d); - addbyte((uint8_t)cpu_state_offset(TOP)); - if (reg) - { - addbyte(0x83); /*ADD EBX, reg*/ - addbyte(0xc0 | REG_EBX); - addbyte(reg); - addbyte(0x83); /*AND EBX, 7*/ - addbyte(0xe0 | REG_EBX); - addbyte(0x07); - } - addbyte(0xf3); /*MOVQ XMM0, ST[EBX*8]*/ - addbyte(0x0f); - addbyte(0x7e); - addbyte(0x44); - addbyte(0xdd); - addbyte((uint8_t)cpu_state_offset(ST)); - addbyte(0xf2); /*CVTSD2SS XMM0, XMM0*/ - addbyte(0x0f); - addbyte(0x5a); - addbyte(0xc0); - addbyte(0x66); /*MOVD EBX, XMM0*/ - addbyte(0x0f); - addbyte(0x7e); - addbyte(0xc0 | REG_EBX); - - return REG_EBX; -} -static inline void FP_LOAD_REG_D(int reg, int *host_reg1, int *host_reg2) -{ - addbyte(0x8b); /*MOV EBX, TOP*/ - addbyte(0x5d); - addbyte((uint8_t)cpu_state_offset(TOP)); - if (reg) - { - addbyte(0x83); /*ADD EBX, reg*/ - addbyte(0xc0 | REG_EBX); - addbyte(reg); - addbyte(0x83); /*AND EBX, 7*/ - addbyte(0xe0 | REG_EBX); - addbyte(0x07); - } - addbyte(0x48); /*MOV RBX, ST[EBX*8]*/ - addbyte(0x8b); - addbyte(0x5c); - addbyte(0xdd); - addbyte((uint8_t)cpu_state_offset(ST)); - - *host_reg1 = REG_EBX; -} -static inline int64_t x87_fround16_64(double b) -{ - int16_t a, c; - - switch ((cpu_state.npxc >> 10) & 3) - { - case 0: /*Nearest*/ - a = (int16_t)floor(b); - c = (int16_t)floor(b + 1.0); - if ((b - a) < (c - b)) - return (int64_t) a; - else if ((b - a) > (c - b)) - return (int64_t) c; - else - return (a & 1) ? c : a; - case 1: /*Down*/ - return (int64_t)((int16_t)floor(b)); - case 2: /*Up*/ - return (int64_t)((int16_t)ceil(b)); - case 3: /*Chop*/ - return (int64_t)((int16_t)b); - } - - return 0; -} -static inline int64_t x87_fround32_64(double b) -{ - int32_t a, c; - - switch ((cpu_state.npxc >> 10) & 3) - { - case 0: /*Nearest*/ - a = (int32_t)floor(b); - c = (int32_t)floor(b + 1.0); - if ((b - a) < (c - b)) - return (int64_t) a; - else if ((b - a) > (c - b)) - return (int64_t) c; - else - return (a & 1) ? c : a; - case 1: /*Down*/ - return (int64_t)((int32_t)floor(b)); - case 2: /*Up*/ - return (int64_t)((int32_t)ceil(b)); - case 3: /*Chop*/ - return (int64_t)((int32_t)b); - } - - return 0; -} -static inline int64_t x87_fround(double b) -{ - int64_t a, c; - - switch ((cpu_state.npxc >> 10) & 3) - { - case 0: /*Nearest*/ - a = (int64_t)floor(b); - c = (int64_t)floor(b + 1.0); - if ((b - a) < (c - b)) - return a; - else if ((b - a) > (c - b)) - return c; - else - return (a & 1) ? c : a; - case 1: /*Down*/ - return (int64_t)floor(b); - case 2: /*Up*/ - return (int64_t)ceil(b); - case 3: /*Chop*/ - return (int64_t)b; - } - - return 0; -} -static inline int FP_LOAD_REG_INT_W(int reg) -{ - addbyte(0x89); /*MOV EBX, EAX*/ - addbyte(0xc3); - - addbyte(0x8b); /*MOV EAX, [TOP]*/ - addbyte(0x45); - addbyte((uint8_t)cpu_state_offset(TOP)); - if (reg) - { - addbyte(0x83); /*ADD EAX, reg*/ - addbyte(0xc0); - addbyte(reg); - addbyte(0x83); /*AND EAX, 7*/ - addbyte(0xe0); - addbyte(7); - } - addbyte(0xf3); /*MOVQ XMM0, ST[EAX*8]*/ - addbyte(0x0f); - addbyte(0x7e); - addbyte(0x44); - addbyte(0xc5); - addbyte((uint8_t)cpu_state_offset(ST)); - - CALL_FUNC((uintptr_t)x87_fround16_64); - - addbyte(0x93); /*XCHG EBX, EAX*/ - - return REG_EBX; -} -static inline int FP_LOAD_REG_INT(int reg) -{ - addbyte(0x89); /*MOV EBX, EAX*/ - addbyte(0xc3); - - addbyte(0x8b); /*MOV EAX, [TOP]*/ - addbyte(0x45); - addbyte((uint8_t)cpu_state_offset(TOP)); - if (reg) - { - addbyte(0x83); /*ADD EAX, reg*/ - addbyte(0xc0); - addbyte(reg); - addbyte(0x83); /*AND EAX, 7*/ - addbyte(0xe0); - addbyte(7); - } - addbyte(0xf3); /*MOVQ XMM0, ST[EAX*8]*/ - addbyte(0x0f); - addbyte(0x7e); - addbyte(0x44); - addbyte(0xc5); - addbyte((uint8_t)cpu_state_offset(ST)); - - CALL_FUNC((uintptr_t)x87_fround32_64); - - addbyte(0x93); /*XCHG EBX, EAX*/ - - return REG_EBX; -} -static inline void FP_LOAD_REG_INT_Q(int reg, int *host_reg1, int *host_reg2) -{ - addbyte(0x89); /*MOV EBX, EAX*/ - addbyte(0xc3); - - addbyte(0x8b); /*MOV EAX, [TOP]*/ - addbyte(0x45); - addbyte((uint8_t)cpu_state_offset(TOP)); - if (reg) - { - addbyte(0x83); /*ADD EAX, reg*/ - addbyte(0xc0); - addbyte(reg); - addbyte(0x83); /*AND EAX, 7*/ - addbyte(0xe0); - addbyte(7); - } - - if (codegen_fpu_loaded_iq[cpu_state.TOP] && (cpu_state.tag[cpu_state.TOP] & TAG_UINT64)) - { - /*If we know the register was loaded with FILDq in this block and - has not been modified, then we can skip most of the conversion - and just load the 64-bit integer representation directly */ - addbyte(0x48); /*MOV RAX, [ST_i64+EAX*8]*/ - addbyte(0x8b); - addbyte(0x44); - addbyte(0xc5); - addbyte((uint8_t)cpu_state_offset(MM)); - - addbyte(0x48); /*XCHG RBX, RAX*/ - addbyte(0x93); - - *host_reg1 = REG_EBX; - - return; - } - - addbyte(0xf6); /*TEST TAG[EAX], TAG_UINT64*/ - addbyte(0x44); - addbyte(0x05); - addbyte((uint8_t)cpu_state_offset(tag)); - addbyte(TAG_UINT64); - - addbyte(0x74); /*JZ +*/ - addbyte(5+2); + } + if (codegen_fpu_loaded_iq[cpu_state.TOP] && (cpu_state.tag[cpu_state.TOP] & TAG_UINT64)) { + /*If we know the register was loaded with FILDq in this block and + has not been modified, then we can skip most of the conversion + and just load the 64-bit integer representation directly */ addbyte(0x48); /*MOV RAX, [ST_i64+EAX*8]*/ addbyte(0x8b); addbyte(0x44); addbyte(0xc5); - addbyte((uint8_t)cpu_state_offset(MM)); - - addbyte(0xeb); /*JMP done*/ - addbyte(6+12); + addbyte((uint8_t) cpu_state_offset(MM)); - addbyte(0xf3); /*MOVQ XMM0, ST[EAX*8]*/ - addbyte(0x0f); - addbyte(0x7e); - addbyte(0x44); - addbyte(0xc5); - addbyte((uint8_t)cpu_state_offset(ST)); - - CALL_FUNC((uintptr_t)x87_fround); - addbyte(0x48); /*XCHG RBX, RAX*/ addbyte(0x93); - + *host_reg1 = REG_EBX; + + return; + } + + addbyte(0xf6); /*TEST TAG[EAX], TAG_UINT64*/ + addbyte(0x44); + addbyte(0x05); + addbyte((uint8_t) cpu_state_offset(tag)); + addbyte(TAG_UINT64); + + addbyte(0x74); /*JZ +*/ + addbyte(5 + 2); + + addbyte(0x48); /*MOV RAX, [ST_i64+EAX*8]*/ + addbyte(0x8b); + addbyte(0x44); + addbyte(0xc5); + addbyte((uint8_t) cpu_state_offset(MM)); + + addbyte(0xeb); /*JMP done*/ + addbyte(6 + 12); + + addbyte(0xf3); /*MOVQ XMM0, ST[EAX*8]*/ + addbyte(0x0f); + addbyte(0x7e); + addbyte(0x44); + addbyte(0xc5); + addbyte((uint8_t) cpu_state_offset(ST)); + + CALL_FUNC((uintptr_t) x87_fround); + + addbyte(0x48); /*XCHG RBX, RAX*/ + addbyte(0x93); + + *host_reg1 = REG_EBX; } #define FPU_ADD 0 @@ -4526,1793 +4161,1705 @@ static inline void FP_LOAD_REG_INT_Q(int reg, int *host_reg1, int *host_reg2) #define FPU_SUB 2 #define FPU_SUBR 3 -static inline void FP_OP_REG(int op, int dst, int src) +static __inline void +FP_OP_REG(int op, int dst, int src) { - addbyte(0x8b); /*MOV EAX, [TOP]*/ - addbyte(0x45); - addbyte((uint8_t)cpu_state_offset(TOP)); - addbyte(0x89); /*MOV EBX, EAX*/ - addbyte(0xc3); - if (dst) - { - addbyte(0x83); /*ADD EAX, reg*/ - addbyte(0xc0); - addbyte(dst); - addbyte(0x83); /*AND EAX, 7*/ - addbyte(0xe0); - addbyte(0x07); - } - if (src) - { - addbyte(0x83); /*ADD EBX, reg*/ - addbyte(0xc0 | REG_EBX); - addbyte(src); - addbyte(0x83); /*AND EBX, 7*/ - addbyte(0xe0 | REG_EBX); - addbyte(0x07); - } - addbyte(0x80); /*AND tag[EAX], ~TAG_UINT64*/ - addbyte(0x64); - addbyte(0x05); - addbyte((uint8_t)cpu_state_offset(tag)); - addbyte(TAG_NOT_UINT64); - if (op == FPU_DIVR || op == FPU_SUBR) - { - addbyte(0xf3); /*MOVQ XMM0, ST[RBX*8]*/ - addbyte(0x0f); - addbyte(0x7e); - addbyte(0x44); - addbyte(0xdd); - addbyte((uint8_t)cpu_state_offset(ST)); - } - else - { - addbyte(0xf3); /*MOVQ XMM0, ST[RAX*8]*/ - addbyte(0x0f); - addbyte(0x7e); - addbyte(0x44); - addbyte(0xc5); - addbyte((uint8_t)cpu_state_offset(ST)); - } - switch (op) - { - case FPU_ADD: - addbyte(0xf2); /*ADDSD XMM0, ST[RBX*8]*/ - addbyte(0x0f); - addbyte(0x58); - addbyte(0x44); - addbyte(0xdd); - addbyte((uint8_t)cpu_state_offset(ST)); - break; - case FPU_DIV: - addbyte(0xf2); /*DIVSD XMM0, ST[RBX*8]*/ - addbyte(0x0f); - addbyte(0x5e); - addbyte(0x44); - addbyte(0xdd); - addbyte((uint8_t)cpu_state_offset(ST)); - break; - case FPU_DIVR: - addbyte(0xf2); /*DIVSD XMM0, ST[RAX*8]*/ - addbyte(0x0f); - addbyte(0x5e); - addbyte(0x44); - addbyte(0xc5); - addbyte((uint8_t)cpu_state_offset(ST)); - break; - case FPU_MUL: - addbyte(0xf2); /*MULSD XMM0, ST[RBX*8]*/ - addbyte(0x0f); - addbyte(0x59); - addbyte(0x44); - addbyte(0xdd); - addbyte((uint8_t)cpu_state_offset(ST)); - break; - case FPU_SUB: - addbyte(0xf2); /*SUBSD XMM0, ST[RBX*8]*/ - addbyte(0x0f); - addbyte(0x5c); - addbyte(0x44); - addbyte(0xdd); - addbyte((uint8_t)cpu_state_offset(ST)); - break; - case FPU_SUBR: - addbyte(0xf2); /*SUBSD XMM0, ST[RAX*8]*/ - addbyte(0x0f); - addbyte(0x5c); - addbyte(0x44); - addbyte(0xc5); - addbyte((uint8_t)cpu_state_offset(ST)); - break; - } - addbyte(0x66); /*MOVQ [RSI+RAX*8], XMM0*/ + addbyte(0x8b); /*MOV EAX, [TOP]*/ + addbyte(0x45); + addbyte((uint8_t) cpu_state_offset(TOP)); + addbyte(0x89); /*MOV EBX, EAX*/ + addbyte(0xc3); + if (dst) { + addbyte(0x83); /*ADD EAX, reg*/ + addbyte(0xc0); + addbyte(dst); + addbyte(0x83); /*AND EAX, 7*/ + addbyte(0xe0); + addbyte(0x07); + } + if (src) { + addbyte(0x83); /*ADD EBX, reg*/ + addbyte(0xc0 | REG_EBX); + addbyte(src); + addbyte(0x83); /*AND EBX, 7*/ + addbyte(0xe0 | REG_EBX); + addbyte(0x07); + } + addbyte(0x80); /*AND tag[EAX], ~TAG_UINT64*/ + addbyte(0x64); + addbyte(0x05); + addbyte((uint8_t) cpu_state_offset(tag)); + addbyte(TAG_NOT_UINT64); + if (op == FPU_DIVR || op == FPU_SUBR) { + addbyte(0xf3); /*MOVQ XMM0, ST[RBX*8]*/ + addbyte(0x0f); + addbyte(0x7e); + addbyte(0x44); + addbyte(0xdd); + addbyte((uint8_t) cpu_state_offset(ST)); + } else { + addbyte(0xf3); /*MOVQ XMM0, ST[RAX*8]*/ + addbyte(0x0f); + addbyte(0x7e); + addbyte(0x44); + addbyte(0xc5); + addbyte((uint8_t) cpu_state_offset(ST)); + } + switch (op) { + case FPU_ADD: + addbyte(0xf2); /*ADDSD XMM0, ST[RBX*8]*/ + addbyte(0x0f); + addbyte(0x58); + addbyte(0x44); + addbyte(0xdd); + addbyte((uint8_t) cpu_state_offset(ST)); + break; + case FPU_DIV: + addbyte(0xf2); /*DIVSD XMM0, ST[RBX*8]*/ + addbyte(0x0f); + addbyte(0x5e); + addbyte(0x44); + addbyte(0xdd); + addbyte((uint8_t) cpu_state_offset(ST)); + break; + case FPU_DIVR: + addbyte(0xf2); /*DIVSD XMM0, ST[RAX*8]*/ + addbyte(0x0f); + addbyte(0x5e); + addbyte(0x44); + addbyte(0xc5); + addbyte((uint8_t) cpu_state_offset(ST)); + break; + case FPU_MUL: + addbyte(0xf2); /*MULSD XMM0, ST[RBX*8]*/ + addbyte(0x0f); + addbyte(0x59); + addbyte(0x44); + addbyte(0xdd); + addbyte((uint8_t) cpu_state_offset(ST)); + break; + case FPU_SUB: + addbyte(0xf2); /*SUBSD XMM0, ST[RBX*8]*/ + addbyte(0x0f); + addbyte(0x5c); + addbyte(0x44); + addbyte(0xdd); + addbyte((uint8_t) cpu_state_offset(ST)); + break; + case FPU_SUBR: + addbyte(0xf2); /*SUBSD XMM0, ST[RAX*8]*/ + addbyte(0x0f); + addbyte(0x5c); + addbyte(0x44); + addbyte(0xc5); + addbyte((uint8_t) cpu_state_offset(ST)); + break; + } + addbyte(0x66); /*MOVQ [RSI+RAX*8], XMM0*/ + addbyte(0x0f); + addbyte(0xd6); + addbyte(0x44); + addbyte(0xc5); + addbyte((uint8_t) cpu_state_offset(ST)); +} + +static __inline void +FP_OP_MEM(int op) +{ + addbyte(0x8b); /*MOV EAX, [TOP]*/ + addbyte(0x45); + addbyte((uint8_t) cpu_state_offset(TOP)); + addbyte(0xf3); /*MOVQ XMM0, ST[RAX*8]*/ + addbyte(0x0f); + addbyte(0x7e); + addbyte(0x44); + addbyte(0xc5); + addbyte((uint8_t) cpu_state_offset(ST)); + addbyte(0x80); /*AND tag[EAX], ~TAG_UINT64*/ + addbyte(0x64); + addbyte(0x05); + addbyte((uint8_t) cpu_state_offset(tag)); + addbyte(TAG_NOT_UINT64); + + switch (op) { + case FPU_ADD: + addbyte(0xf2); /*ADDSD XMM0, XMM1*/ + addbyte(0x0f); + addbyte(0x58); + addbyte(0xc1); + break; + case FPU_DIV: + addbyte(0xf2); /*DIVSD XMM0, XMM1*/ + addbyte(0x0f); + addbyte(0x5e); + addbyte(0xc1); + break; + case FPU_DIVR: + addbyte(0xf2); /*DIVSD XMM1, XMM0*/ + addbyte(0x0f); + addbyte(0x5e); + addbyte(0xc8); + break; + case FPU_MUL: + addbyte(0xf2); /*MULSD XMM0, XMM1*/ + addbyte(0x0f); + addbyte(0x59); + addbyte(0xc1); + break; + case FPU_SUB: + addbyte(0xf2); /*SUBSD XMM0, XMM1*/ + addbyte(0x0f); + addbyte(0x5c); + addbyte(0xc1); + break; + case FPU_SUBR: + addbyte(0xf2); /*SUBSD XMM1, XMM0*/ + addbyte(0x0f); + addbyte(0x5c); + addbyte(0xc8); + break; + } + if (op == FPU_DIVR || op == FPU_SUBR) { + addbyte(0x66); /*MOVQ ST[RAX*8], XMM1*/ + addbyte(0x0f); + addbyte(0xd6); + addbyte(0x4c); + addbyte(0xc5); + addbyte((uint8_t) cpu_state_offset(ST)); + } else { + addbyte(0x66); /*MOVQ ST[RAX*8], XMM0*/ addbyte(0x0f); addbyte(0xd6); addbyte(0x44); addbyte(0xc5); - addbyte((uint8_t)cpu_state_offset(ST)); + addbyte((uint8_t) cpu_state_offset(ST)); + } } -static inline void FP_OP_MEM(int op) +static __inline void +FP_OP_S(int op) { - addbyte(0x8b); /*MOV EAX, [TOP]*/ - addbyte(0x45); - addbyte((uint8_t)cpu_state_offset(TOP)); - addbyte(0xf3); /*MOVQ XMM0, ST[RAX*8]*/ - addbyte(0x0f); - addbyte(0x7e); + addbyte(0x66); /*MOVD XMM1, EAX*/ + addbyte(0x0f); + addbyte(0x6e); + addbyte(0xc8); + addbyte(0xf3); /*CVTSS2SD XMM1, XMM1*/ + addbyte(0x0f); + addbyte(0x5a); + addbyte(0xc9); + FP_OP_MEM(op); +} +static __inline void +FP_OP_D(int op) +{ + addbyte(0x66); /*MOVQ XMM1, RAX*/ + addbyte(0x48); + addbyte(0x0f); + addbyte(0x6e); + addbyte(0xc8); + if (((cpu_state.npxc >> 10) & 3) && op == FPU_ADD) { + addbyte(0x0f); /*STMXCSR [ESP+8]*/ + addbyte(0xae); + addbyte(0x5c); + addbyte(0x24); + addbyte(0x08); + addbyte(0x8b); /*MOV EAX, [ESP+8]*/ addbyte(0x44); - addbyte(0xc5); - addbyte((uint8_t)cpu_state_offset(ST)); - addbyte(0x80); /*AND tag[EAX], ~TAG_UINT64*/ - addbyte(0x64); - addbyte(0x05); - addbyte((uint8_t)cpu_state_offset(tag)); - addbyte(TAG_NOT_UINT64); - - switch (op) - { - case FPU_ADD: - addbyte(0xf2); /*ADDSD XMM0, XMM1*/ - addbyte(0x0f); - addbyte(0x58); - addbyte(0xc1); - break; - case FPU_DIV: - addbyte(0xf2); /*DIVSD XMM0, XMM1*/ - addbyte(0x0f); - addbyte(0x5e); - addbyte(0xc1); - break; - case FPU_DIVR: - addbyte(0xf2); /*DIVSD XMM1, XMM0*/ - addbyte(0x0f); - addbyte(0x5e); - addbyte(0xc8); - break; - case FPU_MUL: - addbyte(0xf2); /*MULSD XMM0, XMM1*/ - addbyte(0x0f); - addbyte(0x59); - addbyte(0xc1); - break; - case FPU_SUB: - addbyte(0xf2); /*SUBSD XMM0, XMM1*/ - addbyte(0x0f); - addbyte(0x5c); - addbyte(0xc1); - break; - case FPU_SUBR: - addbyte(0xf2); /*SUBSD XMM1, XMM0*/ - addbyte(0x0f); - addbyte(0x5c); - addbyte(0xc8); - break; - } - if (op == FPU_DIVR || op == FPU_SUBR) - { - addbyte(0x66); /*MOVQ ST[RAX*8], XMM1*/ - addbyte(0x0f); - addbyte(0xd6); - addbyte(0x4c); - addbyte(0xc5); - addbyte((uint8_t)cpu_state_offset(ST)); - } - else - { - addbyte(0x66); /*MOVQ ST[RAX*8], XMM0*/ - addbyte(0x0f); - addbyte(0xd6); - addbyte(0x44); - addbyte(0xc5); - addbyte((uint8_t)cpu_state_offset(ST)); - } + addbyte(0x24); + addbyte(0x08); + addbyte(0x25); /*AND EAX, ~(3 << 13)*/ + addlong(~(3 << 10)); + addbyte(0x0d); /*OR EAX, (npxc & (3 << 10)) << 3*/ + addlong((cpu_state.npxc & (3 << 10)) << 3); + addbyte(0x89); /*MOV [RSP+12], EAX*/ + addbyte(0x44); + addbyte(0x24); + addbyte(0x0c); + addbyte(0x0f); /*LDMXCSR [RSP+12]*/ + addbyte(0xae); + addbyte(0x54); + addbyte(0x24); + addbyte(0x0c); + } + FP_OP_MEM(op); + if (((cpu_state.npxc >> 10) & 3) && op == FPU_ADD) { + addbyte(0x0f); /*LDMXCSR [RSP+8]*/ + addbyte(0xae); + addbyte(0x54); + addbyte(0x24); + addbyte(0x08); + } +} +static __inline void +FP_OP_IW(int op) +{ + addbyte(0x0f); /*MOVSX EAX, AX*/ + addbyte(0xbf); + addbyte(0xc0); + addbyte(0xf2); /*CVTSI2SD XMM1, EAX*/ + addbyte(0x0f); + addbyte(0x2a); + addbyte(0xc8); + FP_OP_MEM(op); +} +static __inline void +FP_OP_IL(int op) +{ + addbyte(0xf2); /*CVTSI2SD XMM1, EAX*/ + addbyte(0x0f); + addbyte(0x2a); + addbyte(0xc8); + FP_OP_MEM(op); } -static inline void FP_OP_S(int op) +static __inline void +FP_COMPARE_REG(int dst, int src) { - addbyte(0x66); /*MOVD XMM1, EAX*/ - addbyte(0x0f); - addbyte(0x6e); - addbyte(0xc8); - addbyte(0xf3); /*CVTSS2SD XMM1, XMM1*/ - addbyte(0x0f); - addbyte(0x5a); - addbyte(0xc9); - FP_OP_MEM(op); -} -static inline void FP_OP_D(int op) -{ - addbyte(0x66); /*MOVQ XMM1, RAX*/ - addbyte(0x48); - addbyte(0x0f); - addbyte(0x6e); - addbyte(0xc8); - if (((cpu_state.npxc >> 10) & 3) && op == FPU_ADD) - { - addbyte(0x0f); /*STMXCSR [ESP+8]*/ - addbyte(0xae); - addbyte(0x5c); - addbyte(0x24); - addbyte(0x08); - addbyte(0x8b); /*MOV EAX, [ESP+8]*/ - addbyte(0x44); - addbyte(0x24); - addbyte(0x08); - addbyte(0x25); /*AND EAX, ~(3 << 13)*/ - addlong(~(3 << 10)); - addbyte(0x0d); /*OR EAX, (npxc & (3 << 10)) << 3*/ - addlong((cpu_state.npxc & (3 << 10)) << 3); - addbyte(0x89); /*MOV [RSP+12], EAX*/ - addbyte(0x44); - addbyte(0x24); - addbyte(0x0c); - addbyte(0x0f); /*LDMXCSR [RSP+12]*/ - addbyte(0xae); - addbyte(0x54); - addbyte(0x24); - addbyte(0x0c); - } - FP_OP_MEM(op); - if (((cpu_state.npxc >> 10) & 3) && op == FPU_ADD) - { - addbyte(0x0f); /*LDMXCSR [RSP+8]*/ - addbyte(0xae); - addbyte(0x54); - addbyte(0x24); - addbyte(0x08); - } -} -static inline void FP_OP_IW(int op) -{ - addbyte(0x0f); /*MOVSX EAX, AX*/ - addbyte(0xbf); + addbyte(0x8b); /*MOV EAX, [TOP]*/ + addbyte(0x45); + addbyte((uint8_t) cpu_state_offset(TOP)); + addbyte(0x89); /*MOV EBX, EAX*/ + addbyte(0xc3); + if (src || dst) { + addbyte(0x83); /*ADD EAX, 1*/ addbyte(0xc0); - addbyte(0xf2); /*CVTSI2SD XMM1, EAX*/ - addbyte(0x0f); - addbyte(0x2a); - addbyte(0xc8); - FP_OP_MEM(op); -} -static inline void FP_OP_IL(int op) -{ - addbyte(0xf2); /*CVTSI2SD XMM1, EAX*/ - addbyte(0x0f); - addbyte(0x2a); - addbyte(0xc8); - FP_OP_MEM(op); -} + addbyte(src ? src : dst); + addbyte(0x83); /*AND EAX, 7*/ + addbyte(0xe0); + addbyte(7); + } -static inline void FP_COMPARE_REG(int dst, int src) -{ - addbyte(0x8b); /*MOV EAX, [TOP]*/ - addbyte(0x45); - addbyte((uint8_t)cpu_state_offset(TOP)); - addbyte(0x89); /*MOV EBX, EAX*/ - addbyte(0xc3); - if (src || dst) - { - addbyte(0x83); /*ADD EAX, 1*/ - addbyte(0xc0); - addbyte(src ? src : dst); - addbyte(0x83); /*AND EAX, 7*/ - addbyte(0xe0); - addbyte(7); - } + addbyte(0x8a); /*MOV CL, [npxs+1]*/ + addbyte(0x4d); + addbyte((uint8_t) cpu_state_offset(npxs) + 1); + addbyte(0x80); /*AND CL, ~(C0|C2|C3)*/ + addbyte(0xe1); + addbyte((~(C0 | C2 | C3)) >> 8); - addbyte(0x8a); /*MOV CL, [npxs+1]*/ - addbyte(0x4d); - addbyte((uint8_t)cpu_state_offset(npxs) + 1); - addbyte(0x80); /*AND CL, ~(C0|C2|C3)*/ - addbyte(0xe1); - addbyte((~(C0|C2|C3)) >> 8); - - if (src) - { - addbyte(0xf3); /*MOVQ XMM0, ST[RBX*8]*/ - addbyte(0x0f); - addbyte(0x7e); - addbyte(0x44); - addbyte(0xdd); - addbyte((uint8_t)cpu_state_offset(ST)); - addbyte(0x66); /*COMISD XMM0, ST[RAX*8]*/ - addbyte(0x0f); - addbyte(0x2f); - addbyte(0x44); - addbyte(0xc5); - addbyte((uint8_t)cpu_state_offset(ST)); - } - else - { - addbyte(0xf3); /*MOVQ XMM0, ST[RAX*8]*/ - addbyte(0x0f); - addbyte(0x7e); - addbyte(0x44); - addbyte(0xc5); - addbyte((uint8_t)cpu_state_offset(ST)); - addbyte(0x66); /*COMISD XMM0, ST[RBX*8]*/ - addbyte(0x0f); - addbyte(0x2f); - addbyte(0x44); - addbyte(0xdd); - addbyte((uint8_t)cpu_state_offset(ST)); - } - - addbyte(0x9f); /*LAHF*/ - addbyte(0x80); /*AND AH, (C0|C2|C3)*/ - addbyte(0xe4); - addbyte((C0|C2|C3) >> 8); - addbyte(0x08); /*OR CL, AH*/ - addbyte(0xe1); - addbyte(0x88); /*MOV [npxs+1], CL*/ - addbyte(0x4d); - addbyte((uint8_t)cpu_state_offset(npxs) + 1); -} - -static inline void FP_COMPARE_MEM() -{ - addbyte(0x8b); /*MOV EAX, [TOP]*/ - addbyte(0x45); - addbyte((uint8_t)cpu_state_offset(TOP)); - - addbyte(0x8a); /*MOV CL, [npxs+1]*/ - addbyte(0x4d); - addbyte((uint8_t)cpu_state_offset(npxs) + 1); - addbyte(0xf3); /*MOVQ XMM0, ST[RAX*8]*/ + if (src) { + addbyte(0xf3); /*MOVQ XMM0, ST[RBX*8]*/ addbyte(0x0f); addbyte(0x7e); addbyte(0x44); - addbyte(0xc5); - addbyte((uint8_t)cpu_state_offset(ST)); - addbyte(0x80); /*AND CL, ~(C0|C2|C3)*/ - addbyte(0xe1); - addbyte((~(C0|C2|C3)) >> 8); - addbyte(0x66); /*COMISD XMM0, XMM1*/ + addbyte(0xdd); + addbyte((uint8_t) cpu_state_offset(ST)); + addbyte(0x66); /*COMISD XMM0, ST[RAX*8]*/ addbyte(0x0f); addbyte(0x2f); - addbyte(0xc1); - addbyte(0x9f); /*LAHF*/ - addbyte(0x80); /*AND AH, (C0|C2|C3)*/ - addbyte(0xe4); - addbyte((C0|C2|C3) >> 8); - addbyte(0x08); /*OR CL, AH*/ - addbyte(0xe1); - addbyte(0x88); /*MOV [npxs+1], CL*/ - addbyte(0x4d); - addbyte((uint8_t)cpu_state_offset(npxs) + 1); -} -static inline void FP_COMPARE_S() -{ - addbyte(0x66); /*MOVD XMM1, EAX*/ + addbyte(0x44); + addbyte(0xc5); + addbyte((uint8_t) cpu_state_offset(ST)); + } else { + addbyte(0xf3); /*MOVQ XMM0, ST[RAX*8]*/ addbyte(0x0f); - addbyte(0x6e); - addbyte(0xc8); - addbyte(0xf3); /*CVTSS2SD XMM1, XMM1*/ + addbyte(0x7e); + addbyte(0x44); + addbyte(0xc5); + addbyte((uint8_t) cpu_state_offset(ST)); + addbyte(0x66); /*COMISD XMM0, ST[RBX*8]*/ addbyte(0x0f); - addbyte(0x5a); - addbyte(0xc9); - FP_COMPARE_MEM(); -} -static inline void FP_COMPARE_D() -{ - addbyte(0x66); /*MOVQ XMM1, RAX*/ - addbyte(0x48); - addbyte(0x0f); - addbyte(0x6e); - addbyte(0xc8); - FP_COMPARE_MEM(); -} -static inline void FP_COMPARE_IW() -{ - addbyte(0x0f); /*MOVSX EAX, AX*/ - addbyte(0xbf); - addbyte(0xc0); - addbyte(0xf2); /*CVTSI2SD XMM1, EAX*/ - addbyte(0x0f); - addbyte(0x2a); - addbyte(0xc8); - FP_COMPARE_MEM(); -} -static inline void FP_COMPARE_IL() -{ - addbyte(0xf2); /*CVTSI2SD XMM1, EAX*/ - addbyte(0x0f); - addbyte(0x2a); - addbyte(0xc8); - FP_COMPARE_MEM(); + addbyte(0x2f); + addbyte(0x44); + addbyte(0xdd); + addbyte((uint8_t) cpu_state_offset(ST)); + } + + addbyte(0x9f); /*LAHF*/ + addbyte(0x80); /*AND AH, (C0|C2|C3)*/ + addbyte(0xe4); + addbyte((C0 | C2 | C3) >> 8); + addbyte(0x08); /*OR CL, AH*/ + addbyte(0xe1); + addbyte(0x88); /*MOV [npxs+1], CL*/ + addbyte(0x4d); + addbyte((uint8_t) cpu_state_offset(npxs) + 1); } -static inline void UPDATE_NPXC(int reg) +static __inline void +FP_COMPARE_MEM(void) { + addbyte(0x8b); /*MOV EAX, [TOP]*/ + addbyte(0x45); + addbyte((uint8_t) cpu_state_offset(TOP)); + + addbyte(0x8a); /*MOV CL, [npxs+1]*/ + addbyte(0x4d); + addbyte((uint8_t) cpu_state_offset(npxs) + 1); + addbyte(0xf3); /*MOVQ XMM0, ST[RAX*8]*/ + addbyte(0x0f); + addbyte(0x7e); + addbyte(0x44); + addbyte(0xc5); + addbyte((uint8_t) cpu_state_offset(ST)); + addbyte(0x80); /*AND CL, ~(C0|C2|C3)*/ + addbyte(0xe1); + addbyte((~(C0 | C2 | C3)) >> 8); + addbyte(0x66); /*COMISD XMM0, XMM1*/ + addbyte(0x0f); + addbyte(0x2f); + addbyte(0xc1); + addbyte(0x9f); /*LAHF*/ + addbyte(0x80); /*AND AH, (C0|C2|C3)*/ + addbyte(0xe4); + addbyte((C0 | C2 | C3) >> 8); + addbyte(0x08); /*OR CL, AH*/ + addbyte(0xe1); + addbyte(0x88); /*MOV [npxs+1], CL*/ + addbyte(0x4d); + addbyte((uint8_t) cpu_state_offset(npxs) + 1); +} +static __inline void +FP_COMPARE_S(void) +{ + addbyte(0x66); /*MOVD XMM1, EAX*/ + addbyte(0x0f); + addbyte(0x6e); + addbyte(0xc8); + addbyte(0xf3); /*CVTSS2SD XMM1, XMM1*/ + addbyte(0x0f); + addbyte(0x5a); + addbyte(0xc9); + FP_COMPARE_MEM(); +} +static __inline void +FP_COMPARE_D(void) +{ + addbyte(0x66); /*MOVQ XMM1, RAX*/ + addbyte(0x48); + addbyte(0x0f); + addbyte(0x6e); + addbyte(0xc8); + FP_COMPARE_MEM(); +} +static __inline void +FP_COMPARE_IW(void) +{ + addbyte(0x0f); /*MOVSX EAX, AX*/ + addbyte(0xbf); + addbyte(0xc0); + addbyte(0xf2); /*CVTSI2SD XMM1, EAX*/ + addbyte(0x0f); + addbyte(0x2a); + addbyte(0xc8); + FP_COMPARE_MEM(); +} +static __inline void +FP_COMPARE_IL(void) +{ + addbyte(0xf2); /*CVTSI2SD XMM1, EAX*/ + addbyte(0x0f); + addbyte(0x2a); + addbyte(0xc8); + FP_COMPARE_MEM(); } -static inline void SET_BITS(uintptr_t addr, uint32_t val) +static __inline void +UPDATE_NPXC(UNUSED(int reg)) { - if (IS_32_ADDR(addr)) - { - if (val & ~0xff) - { - addbyte(0x81); /*OR [addr], val*/ - addbyte(0x0c); - addbyte(0x25); - addlong(addr); - addlong(val); - } - else - { - addbyte(0x80); /*OR [addr], val*/ - addbyte(0x0c); - addbyte(0x25); - addlong(addr); - addbyte(val); - } - } - else - { - addbyte(0x48); /*MOV RAX, &addr*/ - addbyte(0xb8 | REG_EAX); - addquad(addr); - if (val & ~0xff) - { - addbyte(0x81); /*OR [RAX], val*/ - addbyte(0x08); - addlong(val); - } - else - { - addbyte(0x80); /*OR [RAX], val*/ - addbyte(0x08); - addbyte(val); - } - } + // } -static inline void CLEAR_BITS(uintptr_t addr, uint32_t val) +static __inline void +SET_BITS(uintptr_t addr, uint32_t val) { - if (IS_32_ADDR(addr)) - { - if (val & ~0xff) - { - addbyte(0x81); /*AND [addr], val*/ - addbyte(0x24); - addbyte(0x25); - addlong(addr); - addlong(~val); - } - else - { - addbyte(0x80); /*AND [addr], val*/ - addbyte(0x24); - addbyte(0x25); - addlong(addr); - addbyte(~val); - } + if (IS_32_ADDR(addr)) { + if (val & ~0xff) { + addbyte(0x81); /*OR [addr], val*/ + addbyte(0x0c); + addbyte(0x25); + addlong(addr); + addlong(val); + } else { + addbyte(0x80); /*OR [addr], val*/ + addbyte(0x0c); + addbyte(0x25); + addlong(addr); + addbyte(val); } - else - { - addbyte(0x48); /*MOV RAX, &addr*/ - addbyte(0xb8 | REG_EAX); - addquad(addr); - if (val & ~0xff) - { - addbyte(0x81); /*AND [RAX], val*/ - addbyte(0x20); - addlong(~val); - } - else - { - addbyte(0x80); /*AND [RAX], val*/ - addbyte(0x20); - addbyte(~val); - } + } else { + addbyte(0x48); /*MOV RAX, &addr*/ + addbyte(0xb8 | REG_EAX); + addquad(addr); + if (val & ~0xff) { + addbyte(0x81); /*OR [RAX], val*/ + addbyte(0x08); + addlong(val); + } else { + addbyte(0x80); /*OR [RAX], val*/ + addbyte(0x08); + addbyte(val); } + } +} + +static __inline void +CLEAR_BITS(uintptr_t addr, uint32_t val) +{ + if (IS_32_ADDR(addr)) { + if (val & ~0xff) { + addbyte(0x81); /*AND [addr], val*/ + addbyte(0x24); + addbyte(0x25); + addlong(addr); + addlong(~val); + } else { + addbyte(0x80); /*AND [addr], val*/ + addbyte(0x24); + addbyte(0x25); + addlong(addr); + addbyte(~val); + } + } else { + addbyte(0x48); /*MOV RAX, &addr*/ + addbyte(0xb8 | REG_EAX); + addquad(addr); + if (val & ~0xff) { + addbyte(0x81); /*AND [RAX], val*/ + addbyte(0x20); + addlong(~val); + } else { + addbyte(0x80); /*AND [RAX], val*/ + addbyte(0x20); + addbyte(~val); + } + } } #define LOAD_Q_REG_1 REG_EAX #define LOAD_Q_REG_2 REG_EDX -static inline void MMX_ENTER() +static __inline void +MMX_ENTER(void) { - if (codegen_mmx_entered) - return; - - if (IS_32_ADDR(&cr0)) - { - addbyte(0xf6); /*TEST cr0, 0xc*/ - addbyte(0x04); - addbyte(0x25); - addlong((uintptr_t)&cr0); - addbyte(0x0c); - } - else - { - addbyte(0x48); /*MOV RAX, &cr0*/ - addbyte(0xb8 | REG_EAX); - addquad((uint64_t)&cr0); - addbyte(0xf6); /*TEST [RAX], 0xc*/ - addbyte(0 | (REG_EAX << 3)); - addbyte(0x0c); - } - addbyte(0x74); /*JZ +*/ - addbyte(7+5+12+5); - addbyte(0xC7); /*MOVL [oldpc],op_old_pc*/ - addbyte(0x45); - addbyte((uint8_t)cpu_state_offset(oldpc)); - addlong(op_old_pc); - load_param_1_32(&codeblock[block_current], 7); - CALL_FUNC((uintptr_t)x86_int); - addbyte(0xe9); /*JMP end*/ - addlong(BLOCK_EXIT_OFFSET - (block_pos + 4)); + if (codegen_mmx_entered) + return; - - addbyte(0x31); /*XOR EAX, EAX*/ - addbyte(0xc0); - addbyte(0xc6); /*MOV ISMMX, 1*/ - addbyte(0x45); - addbyte((uint8_t)cpu_state_offset(ismmx)); - addbyte(1); - addbyte(0x89); /*MOV TOP, EAX*/ - addbyte(0x45); - addbyte((uint8_t)cpu_state_offset(TOP)); - addbyte(0x89); /*MOV tag, EAX*/ - addbyte(0x45); - addbyte((uint8_t)cpu_state_offset(tag[0])); - addbyte(0x89); /*MOV tag+4, EAX*/ - addbyte(0x45); - addbyte((uint8_t)cpu_state_offset(tag[4])); + if (IS_32_ADDR(&cr0)) { + addbyte(0xf6); /*TEST cr0, 0xc*/ + addbyte(0x04); + addbyte(0x25); + addlong((uintptr_t) &cr0); + addbyte(0x0c); + } else { + addbyte(0x48); /*MOV RAX, &cr0*/ + addbyte(0xb8 | REG_EAX); + addquad((uint64_t) &cr0); + addbyte(0xf6); /*TEST [RAX], 0xc*/ + addbyte(0 | (REG_EAX << 3)); + addbyte(0x0c); + } + addbyte(0x74); /*JZ +*/ + addbyte(7 + 5 + 12 + 5); + addbyte(0xC7); /*MOVL [oldpc],op_old_pc*/ + addbyte(0x45); + addbyte((uint8_t) cpu_state_offset(oldpc)); + addlong(op_old_pc); + load_param_1_32(&codeblock[block_current], 7); + CALL_FUNC((uintptr_t) x86_int); + addbyte(0xe9); /*JMP end*/ + addlong(BLOCK_EXIT_OFFSET - (block_pos + 4)); - codegen_mmx_entered = 1; + addbyte(0x31); /*XOR EAX, EAX*/ + addbyte(0xc0); + addbyte(0xc6); /*MOV ISMMX, 1*/ + addbyte(0x45); + addbyte((uint8_t) cpu_state_offset(ismmx)); + addbyte(1); + addbyte(0x89); /*MOV TOP, EAX*/ + addbyte(0x45); + addbyte((uint8_t) cpu_state_offset(TOP)); + addbyte(0x89); /*MOV tag, EAX*/ + addbyte(0x45); + addbyte((uint8_t) cpu_state_offset(tag[0])); + addbyte(0x89); /*MOV tag+4, EAX*/ + addbyte(0x45); + addbyte((uint8_t) cpu_state_offset(tag[4])); + + codegen_mmx_entered = 1; } extern int mmx_ebx_ecx_loaded; -static inline int LOAD_MMX_D(int guest_reg) +static __inline int +LOAD_MMX_D(int guest_reg) { - int host_reg = REG_EBX; + int host_reg = REG_EBX; - addbyte(0x8b); /*MOV EBX, reg*/ - addbyte(0x44 | (host_reg << 3)); - addbyte(0x25); - addbyte((uint8_t)cpu_state_offset(MM[guest_reg].l[0])); - - return host_reg; + addbyte(0x8b); /*MOV EBX, reg*/ + addbyte(0x44 | (host_reg << 3)); + addbyte(0x25); + addbyte((uint8_t) cpu_state_offset(MM[guest_reg].l[0])); + + return host_reg; } -static inline void LOAD_MMX_Q(int guest_reg, int *host_reg1, int *host_reg2) +static __inline void +LOAD_MMX_Q(int guest_reg, int *host_reg1, int *host_reg2) { - int host_reg = REG_EBX; + int host_reg = REG_EBX; - if (host_reg & 8) - addbyte(0x4c); - else - addbyte(0x48); - addbyte(0x8b); /*MOV RBX, reg*/ - addbyte(0x44 | ((host_reg & 7) << 3)); - addbyte(0x25); - addbyte((uint8_t)cpu_state_offset(MM[guest_reg].q)); - - *host_reg1 = host_reg; + if (host_reg & 8) + addbyte(0x4c); + else + addbyte(0x48); + addbyte(0x8b); /*MOV RBX, reg*/ + addbyte(0x44 | ((host_reg & 7) << 3)); + addbyte(0x25); + addbyte((uint8_t) cpu_state_offset(MM[guest_reg].q)); + + *host_reg1 = host_reg; } -static inline int LOAD_MMX_Q_MMX(int guest_reg) +static __inline int +LOAD_MMX_Q_MMX(int guest_reg) { - int dst_reg = find_host_xmm_reg(); - host_reg_xmm_mapping[dst_reg] = 100; + int dst_reg = find_host_xmm_reg(); + host_reg_xmm_mapping[dst_reg] = 100; - addbyte(0xf3); /*MOV XMMx, reg*/ - addbyte(0x0f); - addbyte(0x7e); - addbyte(0x44 | ((dst_reg & 7) << 3)); - addbyte(0x25); - addbyte((uint8_t)cpu_state_offset(MM[guest_reg].q)); - - return dst_reg; + addbyte(0xf3); /*MOV XMMx, reg*/ + addbyte(0x0f); + addbyte(0x7e); + addbyte(0x44 | ((dst_reg & 7) << 3)); + addbyte(0x25); + addbyte((uint8_t) cpu_state_offset(MM[guest_reg].q)); + + return dst_reg; } -static inline int LOAD_INT_TO_MMX(int src_reg1, int src_reg2) +static __inline int +LOAD_INT_TO_MMX(int src_reg1, int src_reg2) { - int dst_reg = find_host_xmm_reg(); - host_reg_xmm_mapping[dst_reg] = 100; - - addbyte(0x66); /*MOVQ host_reg, src_reg1*/ - if (src_reg1 & 8) - addbyte(0x49); - else - addbyte(0x48); - addbyte(0x0f); - addbyte(0x6e); - addbyte(0xc0 | (dst_reg << 3) | (src_reg1 & 7)); - - return dst_reg; + int dst_reg = find_host_xmm_reg(); + host_reg_xmm_mapping[dst_reg] = 100; + + addbyte(0x66); /*MOVQ host_reg, src_reg1*/ + if (src_reg1 & 8) + addbyte(0x49); + else + addbyte(0x48); + addbyte(0x0f); + addbyte(0x6e); + addbyte(0xc0 | (dst_reg << 3) | (src_reg1 & 7)); + + return dst_reg; } -static inline void STORE_MMX_LQ(int guest_reg, int host_reg1) +static __inline void +STORE_MMX_LQ(int guest_reg, int host_reg1) { - addbyte(0xC7); /*MOVL [reg],0*/ + addbyte(0xC7); /*MOVL [reg],0*/ + addbyte(0x44); + addbyte(0x25); + addbyte((uint8_t) cpu_state_offset(MM[guest_reg].l[1])); + addlong(0); + if (host_reg1 & 8) addbyte(0x44); - addbyte(0x25); - addbyte((uint8_t)cpu_state_offset(MM[guest_reg].l[1])); - addlong(0); - if (host_reg1 & 8) - addbyte(0x44); - addbyte(0x89); /*MOVL [reg],host_reg*/ - addbyte(0x44 | ((host_reg1 & 7) << 3)); - addbyte(0x25); - addbyte((uint8_t)cpu_state_offset(MM[guest_reg].l[0])); + addbyte(0x89); /*MOVL [reg],host_reg*/ + addbyte(0x44 | ((host_reg1 & 7) << 3)); + addbyte(0x25); + addbyte((uint8_t) cpu_state_offset(MM[guest_reg].l[0])); } -static inline void STORE_MMX_Q(int guest_reg, int host_reg1, int host_reg2) +static __inline void +STORE_MMX_Q(int guest_reg, int host_reg1, int host_reg2) { - if (host_reg1 & 8) - addbyte(0x4c); - else - addbyte(0x48); - addbyte(0x89); /*MOV [reg],host_reg*/ - addbyte(0x44 | ((host_reg1 & 7) << 3)); - addbyte(0x25); - addbyte((uint8_t)cpu_state_offset(MM[guest_reg].l[0])); + if (host_reg1 & 8) + addbyte(0x4c); + else + addbyte(0x48); + addbyte(0x89); /*MOV [reg],host_reg*/ + addbyte(0x44 | ((host_reg1 & 7) << 3)); + addbyte(0x25); + addbyte((uint8_t) cpu_state_offset(MM[guest_reg].l[0])); } -static inline void STORE_MMX_Q_MMX(int guest_reg, int host_reg) +static __inline void +STORE_MMX_Q_MMX(int guest_reg, int host_reg) { - addbyte(0x66); /*MOVQ [guest_reg],host_reg*/ - addbyte(0x0f); - addbyte(0xd6); - addbyte(0x44 | (host_reg << 3)); - addbyte(0x25); - addbyte((uint8_t)cpu_state_offset(MM[guest_reg].q)); + addbyte(0x66); /*MOVQ [guest_reg],host_reg*/ + addbyte(0x0f); + addbyte(0xd6); + addbyte(0x44 | (host_reg << 3)); + addbyte(0x25); + addbyte((uint8_t) cpu_state_offset(MM[guest_reg].q)); } -#define MMX_x86_OP(name, opcode) \ -static inline void MMX_ ## name(int dst_reg, int src_reg) \ -{ \ - addbyte(0x66); /*op dst_reg, src_reg*/ \ - addbyte(0x0f); \ - addbyte(opcode); \ - addbyte(0xc0 | (dst_reg << 3) | src_reg); \ -} +#define MMX_x86_OP(name, opcode) \ + static __inline void \ + MMX_##name(int dst_reg, int src_reg) \ + { \ + addbyte(0x66); /*op dst_reg, src_reg*/ \ + addbyte(0x0f); \ + addbyte(opcode); \ + addbyte(0xc0 | (dst_reg << 3) | src_reg); \ + } -MMX_x86_OP(AND, 0xdb) -MMX_x86_OP(ANDN, 0xdf) -MMX_x86_OP(OR, 0xeb) -MMX_x86_OP(XOR, 0xef) +MMX_x86_OP(AND, 0xdb) + MMX_x86_OP(ANDN, 0xdf) + MMX_x86_OP(OR, 0xeb) + MMX_x86_OP(XOR, 0xef) -MMX_x86_OP(ADDB, 0xfc) -MMX_x86_OP(ADDW, 0xfd) -MMX_x86_OP(ADDD, 0xfe) -MMX_x86_OP(ADDSB, 0xec) -MMX_x86_OP(ADDSW, 0xed) -MMX_x86_OP(ADDUSB, 0xdc) -MMX_x86_OP(ADDUSW, 0xdd) + MMX_x86_OP(ADDB, 0xfc) + MMX_x86_OP(ADDW, 0xfd) + MMX_x86_OP(ADDD, 0xfe) + MMX_x86_OP(ADDSB, 0xec) + MMX_x86_OP(ADDSW, 0xed) + MMX_x86_OP(ADDUSB, 0xdc) + MMX_x86_OP(ADDUSW, 0xdd) -MMX_x86_OP(SUBB, 0xf8) -MMX_x86_OP(SUBW, 0xf9) -MMX_x86_OP(SUBD, 0xfa) -MMX_x86_OP(SUBSB, 0xe8) -MMX_x86_OP(SUBSW, 0xe9) -MMX_x86_OP(SUBUSB, 0xd8) -MMX_x86_OP(SUBUSW, 0xd9) + MMX_x86_OP(SUBB, 0xf8) + MMX_x86_OP(SUBW, 0xf9) + MMX_x86_OP(SUBD, 0xfa) + MMX_x86_OP(SUBSB, 0xe8) + MMX_x86_OP(SUBSW, 0xe9) + MMX_x86_OP(SUBUSB, 0xd8) + MMX_x86_OP(SUBUSW, 0xd9) -MMX_x86_OP(PUNPCKLBW, 0x60); + MMX_x86_OP(PUNPCKLBW, 0x60); MMX_x86_OP(PUNPCKLWD, 0x61); MMX_x86_OP(PUNPCKLDQ, 0x62); -MMX_x86_OP(PCMPGTB, 0x64); -MMX_x86_OP(PCMPGTW, 0x65); -MMX_x86_OP(PCMPGTD, 0x66); +MMX_x86_OP(PCMPGTB, 0x64); +MMX_x86_OP(PCMPGTW, 0x65); +MMX_x86_OP(PCMPGTD, 0x66); -MMX_x86_OP(PCMPEQB, 0x74); -MMX_x86_OP(PCMPEQW, 0x75); -MMX_x86_OP(PCMPEQD, 0x76); +MMX_x86_OP(PCMPEQB, 0x74); +MMX_x86_OP(PCMPEQW, 0x75); +MMX_x86_OP(PCMPEQD, 0x76); -MMX_x86_OP(PSRLW, 0xd1); -MMX_x86_OP(PSRLD, 0xd2); -MMX_x86_OP(PSRLQ, 0xd3); -MMX_x86_OP(PSRAW, 0xe1); -MMX_x86_OP(PSRAD, 0xe2); -MMX_x86_OP(PSLLW, 0xf1); -MMX_x86_OP(PSLLD, 0xf2); -MMX_x86_OP(PSLLQ, 0xf3); +MMX_x86_OP(PSRLW, 0xd1); +MMX_x86_OP(PSRLD, 0xd2); +MMX_x86_OP(PSRLQ, 0xd3); +MMX_x86_OP(PSRAW, 0xe1); +MMX_x86_OP(PSRAD, 0xe2); +MMX_x86_OP(PSLLW, 0xf1); +MMX_x86_OP(PSLLD, 0xf2); +MMX_x86_OP(PSLLQ, 0xf3); -MMX_x86_OP(PMULLW, 0xd5); -MMX_x86_OP(PMULHW, 0xe5); +MMX_x86_OP(PMULLW, 0xd5); +MMX_x86_OP(PMULHW, 0xe5); MMX_x86_OP(PMADDWD, 0xf5); -static inline void MMX_PACKSSWB(int dst_reg, int src_reg) +static __inline void +MMX_PACKSSWB(int dst_reg, int src_reg) { - addbyte(0x66); /*PACKSSWB dst_reg, src_reg*/ - addbyte(0x0f); - addbyte(0x63); - addbyte(0xc0 | (dst_reg << 3) | src_reg); - addbyte(0x66); /*PSHUFD dst_reg, dst_reg*/ - addbyte(0x0f); - addbyte(0x70); - addbyte(0xc0 | (dst_reg << 3) | dst_reg); - addbyte(0x08); + addbyte(0x66); /*PACKSSWB dst_reg, src_reg*/ + addbyte(0x0f); + addbyte(0x63); + addbyte(0xc0 | (dst_reg << 3) | src_reg); + addbyte(0x66); /*PSHUFD dst_reg, dst_reg*/ + addbyte(0x0f); + addbyte(0x70); + addbyte(0xc0 | (dst_reg << 3) | dst_reg); + addbyte(0x08); } -static inline void MMX_PACKUSWB(int dst_reg, int src_reg) +static __inline void +MMX_PACKUSWB(int dst_reg, int src_reg) { - addbyte(0x66); /*PACKUSWB dst_reg, src_reg*/ - addbyte(0x0f); - addbyte(0x67); - addbyte(0xc0 | (dst_reg << 3) | src_reg); - addbyte(0x66); /*PSHUFD dst_reg, dst_reg*/ - addbyte(0x0f); - addbyte(0x70); - addbyte(0xc0 | (dst_reg << 3) | dst_reg); - addbyte(0x08); + addbyte(0x66); /*PACKUSWB dst_reg, src_reg*/ + addbyte(0x0f); + addbyte(0x67); + addbyte(0xc0 | (dst_reg << 3) | src_reg); + addbyte(0x66); /*PSHUFD dst_reg, dst_reg*/ + addbyte(0x0f); + addbyte(0x70); + addbyte(0xc0 | (dst_reg << 3) | dst_reg); + addbyte(0x08); } -static inline void MMX_PACKSSDW(int dst_reg, int src_reg) +static __inline void +MMX_PACKSSDW(int dst_reg, int src_reg) { - addbyte(0x66); /*PACKSSDW dst_reg, src_reg*/ - addbyte(0x0f); - addbyte(0x6b); - addbyte(0xc0 | (dst_reg << 3) | src_reg); - addbyte(0x66); /*PSHUFD dst_reg, dst_reg*/ - addbyte(0x0f); - addbyte(0x70); - addbyte(0xc0 | (dst_reg << 3) | dst_reg); - addbyte(0x08); + addbyte(0x66); /*PACKSSDW dst_reg, src_reg*/ + addbyte(0x0f); + addbyte(0x6b); + addbyte(0xc0 | (dst_reg << 3) | src_reg); + addbyte(0x66); /*PSHUFD dst_reg, dst_reg*/ + addbyte(0x0f); + addbyte(0x70); + addbyte(0xc0 | (dst_reg << 3) | dst_reg); + addbyte(0x08); } -static inline void MMX_PUNPCKHBW(int dst_reg, int src_reg) +static __inline void +MMX_PUNPCKHBW(int dst_reg, int src_reg) { - addbyte(0x66); /*PUNPCKLBW dst_reg, src_reg*/ - addbyte(0x0f); - addbyte(0x60); - addbyte(0xc0 | (dst_reg << 3) | src_reg); - addbyte(0x66); /*PSHUFD dst_reg, dst_reg*/ - addbyte(0x0f); - addbyte(0x70); - addbyte(0xc0 | (dst_reg << 3) | dst_reg); - addbyte(0x0e); + addbyte(0x66); /*PUNPCKLBW dst_reg, src_reg*/ + addbyte(0x0f); + addbyte(0x60); + addbyte(0xc0 | (dst_reg << 3) | src_reg); + addbyte(0x66); /*PSHUFD dst_reg, dst_reg*/ + addbyte(0x0f); + addbyte(0x70); + addbyte(0xc0 | (dst_reg << 3) | dst_reg); + addbyte(0x0e); } -static inline void MMX_PUNPCKHWD(int dst_reg, int src_reg) +static __inline void +MMX_PUNPCKHWD(int dst_reg, int src_reg) { - addbyte(0x66); /*PUNPCKLWD dst_reg, src_reg*/ - addbyte(0x0f); - addbyte(0x61); - addbyte(0xc0 | (dst_reg << 3) | src_reg); - addbyte(0x66); /*PSHUFD dst_reg, dst_reg*/ - addbyte(0x0f); - addbyte(0x70); - addbyte(0xc0 | (dst_reg << 3) | dst_reg); - addbyte(0x0e); + addbyte(0x66); /*PUNPCKLWD dst_reg, src_reg*/ + addbyte(0x0f); + addbyte(0x61); + addbyte(0xc0 | (dst_reg << 3) | src_reg); + addbyte(0x66); /*PSHUFD dst_reg, dst_reg*/ + addbyte(0x0f); + addbyte(0x70); + addbyte(0xc0 | (dst_reg << 3) | dst_reg); + addbyte(0x0e); } -static inline void MMX_PUNPCKHDQ(int dst_reg, int src_reg) +static __inline void +MMX_PUNPCKHDQ(int dst_reg, int src_reg) { - addbyte(0x66); /*PUNPCKLDQ dst_reg, src_reg*/ - addbyte(0x0f); - addbyte(0x62); - addbyte(0xc0 | (dst_reg << 3) | src_reg); - addbyte(0x66); /*PSHUFD dst_reg, dst_reg*/ - addbyte(0x0f); - addbyte(0x70); - addbyte(0xc0 | (dst_reg << 3) | dst_reg); - addbyte(0x0e); + addbyte(0x66); /*PUNPCKLDQ dst_reg, src_reg*/ + addbyte(0x0f); + addbyte(0x62); + addbyte(0xc0 | (dst_reg << 3) | src_reg); + addbyte(0x66); /*PSHUFD dst_reg, dst_reg*/ + addbyte(0x0f); + addbyte(0x70); + addbyte(0xc0 | (dst_reg << 3) | dst_reg); + addbyte(0x0e); } -static inline void MMX_PSRLW_imm(int dst_reg, int amount) +static __inline void +MMX_PSRLW_imm(int dst_reg, int amount) { - addbyte(0x66); /*PSRLW dst_reg, amount*/ - addbyte(0x0f); - addbyte(0x71); - addbyte(0xc0 | dst_reg | 0x10); - addbyte(amount); + addbyte(0x66); /*PSRLW dst_reg, amount*/ + addbyte(0x0f); + addbyte(0x71); + addbyte(0xc0 | dst_reg | 0x10); + addbyte(amount); } -static inline void MMX_PSRAW_imm(int dst_reg, int amount) +static __inline void +MMX_PSRAW_imm(int dst_reg, int amount) { - addbyte(0x66); /*PSRAW dst_reg, amount*/ - addbyte(0x0f); - addbyte(0x71); - addbyte(0xc0 | dst_reg | 0x20); - addbyte(amount); + addbyte(0x66); /*PSRAW dst_reg, amount*/ + addbyte(0x0f); + addbyte(0x71); + addbyte(0xc0 | dst_reg | 0x20); + addbyte(amount); } -static inline void MMX_PSLLW_imm(int dst_reg, int amount) +static __inline void +MMX_PSLLW_imm(int dst_reg, int amount) { - addbyte(0x66); /*PSLLW dst_reg, amount*/ - addbyte(0x0f); - addbyte(0x71); - addbyte(0xc0 | dst_reg | 0x30); - addbyte(amount); + addbyte(0x66); /*PSLLW dst_reg, amount*/ + addbyte(0x0f); + addbyte(0x71); + addbyte(0xc0 | dst_reg | 0x30); + addbyte(amount); } -static inline void MMX_PSRLD_imm(int dst_reg, int amount) +static __inline void +MMX_PSRLD_imm(int dst_reg, int amount) { - addbyte(0x66); /*PSRLD dst_reg, amount*/ - addbyte(0x0f); - addbyte(0x72); - addbyte(0xc0 | dst_reg | 0x10); - addbyte(amount); + addbyte(0x66); /*PSRLD dst_reg, amount*/ + addbyte(0x0f); + addbyte(0x72); + addbyte(0xc0 | dst_reg | 0x10); + addbyte(amount); } -static inline void MMX_PSRAD_imm(int dst_reg, int amount) +static __inline void +MMX_PSRAD_imm(int dst_reg, int amount) { - addbyte(0x66); /*PSRAD dst_reg, amount*/ - addbyte(0x0f); - addbyte(0x72); - addbyte(0xc0 | dst_reg | 0x20); - addbyte(amount); + addbyte(0x66); /*PSRAD dst_reg, amount*/ + addbyte(0x0f); + addbyte(0x72); + addbyte(0xc0 | dst_reg | 0x20); + addbyte(amount); } -static inline void MMX_PSLLD_imm(int dst_reg, int amount) +static __inline void +MMX_PSLLD_imm(int dst_reg, int amount) { - addbyte(0x66); /*PSLLD dst_reg, amount*/ - addbyte(0x0f); - addbyte(0x72); - addbyte(0xc0 | dst_reg | 0x30); - addbyte(amount); + addbyte(0x66); /*PSLLD dst_reg, amount*/ + addbyte(0x0f); + addbyte(0x72); + addbyte(0xc0 | dst_reg | 0x30); + addbyte(amount); } -static inline void MMX_PSRLQ_imm(int dst_reg, int amount) +static __inline void +MMX_PSRLQ_imm(int dst_reg, int amount) { - addbyte(0x66); /*PSRLQ dst_reg, amount*/ - addbyte(0x0f); - addbyte(0x73); - addbyte(0xc0 | dst_reg | 0x10); - addbyte(amount); + addbyte(0x66); /*PSRLQ dst_reg, amount*/ + addbyte(0x0f); + addbyte(0x73); + addbyte(0xc0 | dst_reg | 0x10); + addbyte(amount); } -static inline void MMX_PSRAQ_imm(int dst_reg, int amount) +static __inline void +MMX_PSRAQ_imm(int dst_reg, int amount) { - addbyte(0x66); /*PSRAQ dst_reg, amount*/ - addbyte(0x0f); - addbyte(0x73); - addbyte(0xc0 | dst_reg | 0x20); - addbyte(amount); + addbyte(0x66); /*PSRAQ dst_reg, amount*/ + addbyte(0x0f); + addbyte(0x73); + addbyte(0xc0 | dst_reg | 0x20); + addbyte(amount); } -static inline void MMX_PSLLQ_imm(int dst_reg, int amount) +static __inline void +MMX_PSLLQ_imm(int dst_reg, int amount) { - addbyte(0x66); /*PSLLQ dst_reg, amount*/ - addbyte(0x0f); - addbyte(0x73); - addbyte(0xc0 | dst_reg | 0x30); - addbyte(amount); + addbyte(0x66); /*PSLLQ dst_reg, amount*/ + addbyte(0x0f); + addbyte(0x73); + addbyte(0xc0 | dst_reg | 0x30); + addbyte(amount); } - -static inline void SAVE_EA() +static __inline void +SAVE_EA(void) { - addbyte(0x89); /*MOV [ESP+0x24], EAX*/ - addbyte(0x44); - addbyte(0x24); - addbyte(0x24); + addbyte(0x89); /*MOV [ESP+0x24], EAX*/ + addbyte(0x44); + addbyte(0x24); + addbyte(0x24); } -static inline void LOAD_EA() +static __inline void +LOAD_EA(void) { - addbyte(0x8b); /*MOV EAX, [ESP+0x24]*/ - addbyte(0x44); - addbyte(0x24); - addbyte(0x24); + addbyte(0x8b); /*MOV EAX, [ESP+0x24]*/ + addbyte(0x44); + addbyte(0x24); + addbyte(0x24); } #define MEM_CHECK_WRITE_B MEM_CHECK_WRITE -static inline void MEM_CHECK_WRITE(x86seg *seg) +static __inline void +MEM_CHECK_WRITE(x86seg *seg) { - uint8_t *jump1, *jump2, *jump3 = NULL; - - CHECK_SEG_WRITE(seg); + uint8_t *jump1 = NULL; + uint8_t *jump2 = NULL; + uint8_t *jump3 = NULL; - if ((seg == &cpu_state.seg_ds && codegen_flat_ds && !(cpu_cur_status & CPU_STATUS_NOTFLATDS)) || (seg == &cpu_state.seg_ss && codegen_flat_ss && !(cpu_cur_status & CPU_STATUS_NOTFLATSS))) - { - addbyte(0x31); /*XOR ESI, ESI*/ - addbyte(0xf6); - } - else if (IS_32_ADDR(&seg->base)) - { - addbyte(0x8b); /*MOV ESI, seg->base*/ - addbyte(0x34); - addbyte(0x25); - addlong((uint32_t)(uintptr_t)&seg->base); - } - else - { - addbyte(0x48); /*MOV RSI, &addr*/ - addbyte(0xb8 | REG_ESI); - addquad((uint64_t)&seg->base); - addbyte(0x8b); /*MOV ESI, [RSI]*/ - addbyte(0x36); - } + CHECK_SEG_WRITE(seg); - - /*seg = ESI, addr = EAX*/ - - if (IS_32_ADDR(&cr0)) - { - addbyte(0x83); /*CMP cr0, 0*/ - addbyte(0x3c); - addbyte(0x25); - addlong((uint32_t)(uintptr_t)&cr0); - addbyte(0); - } - else - { - addbyte(0x48); /*MOV RDI, &cr0*/ - addbyte(0xbf); - addquad((uint64_t)&cr0); - addbyte(0x83); /*CMPL [RDI], 0*/ - addbyte(0x3f); - addbyte(0); - } - addbyte(0x67); /*LEA EDI, [EAX+ESI]*/ - addbyte(0x8d); - addbyte(0x3c); - addbyte(0x30); - addbyte(0x79); /*JNS +*/ - jump1 = &codeblock[block_current].data[block_pos]; - addbyte(0); - addbyte(0xc1); /*SHR EDI, 12*/ - addbyte(0xef); - addbyte(12); - if (!(seg == &cpu_state.seg_ds && codegen_flat_ds && !(cpu_cur_status & CPU_STATUS_NOTFLATDS)) && !(seg == &cpu_state.seg_ss && codegen_flat_ss && !(cpu_cur_status & CPU_STATUS_NOTFLATSS))) - { - addbyte(0x83); /*CMP ESI, -1*/ - addbyte(0xfe); - addbyte(-1); - addbyte(0x74); /*JE slowpath*/ - jump3 = &codeblock[block_current].data[block_pos]; - addbyte(0); - } - if (IS_32_ADDR(writelookup2)) - { - addbyte(0x83); /*CMP writelookup2[RDI*8],-1*/ - addbyte(0x3c); - addbyte(0xfd); - addlong((uint32_t)(uintptr_t)writelookup2); - addbyte(-1); - } - else - { - addbyte(0x48); /*MOV RCX, writelookup2*/ - addbyte(0xb9); - addquad((uint64_t)writelookup2); - addbyte(0x83); /*CMP [RCX+RDI*8], -1*/ - addbyte(0x3c); - addbyte(0xf9); - addbyte(-1); - } - addbyte(0x75); /*JNE +*/ - jump2 = &codeblock[block_current].data[block_pos]; - addbyte(0); - - if (!(seg == &cpu_state.seg_ds && codegen_flat_ds && !(cpu_cur_status & CPU_STATUS_NOTFLATDS)) && !(seg == &cpu_state.seg_ss && codegen_flat_ss && !(cpu_cur_status & CPU_STATUS_NOTFLATSS))) - *jump3 = (uintptr_t)&codeblock[block_current].data[block_pos] - (uintptr_t)jump3 - 1; - /*slowpath:*/ - addbyte(0x67); /*LEA EDI, [EAX+ESI]*/ - addbyte(0x8d); - addbyte(0x3c); - addbyte(0x30); - - - load_param_1_reg_32(REG_EDI); - load_param_2_32(&codeblock[block_current], 1); - - call(&codeblock[block_current], (uintptr_t)mmutranslatereal32); - addbyte(0x80); /*CMP abrt, 0*/ - addbyte(0x7d); - addbyte((uint8_t)cpu_state_offset(abrt)); - addbyte(0); - addbyte(0x0f); /*JNE mem_abrt_rout*/ - addbyte(0x85); - addlong((uintptr_t)&codeblock[block_current].data[BLOCK_EXIT_OFFSET] - ((uintptr_t)(&codeblock[block_current].data[block_pos]) + 4)); - *jump1 = (uintptr_t)&codeblock[block_current].data[block_pos] - (uintptr_t)jump1 - 1; - *jump2 = (uintptr_t)&codeblock[block_current].data[block_pos] - (uintptr_t)jump2 - 1; - - LOAD_EA(); -} - -static inline void MEM_CHECK_WRITE_W(x86seg *seg) -{ - uint8_t *jump1, *jump2, *jump3, *jump4 = NULL; - int jump_pos; - - CHECK_SEG_WRITE(seg); - - if ((seg == &cpu_state.seg_ds && codegen_flat_ds && !(cpu_cur_status & CPU_STATUS_NOTFLATDS)) || (seg == &cpu_state.seg_ss && codegen_flat_ss && !(cpu_cur_status & CPU_STATUS_NOTFLATSS))) - { - addbyte(0x31); /*XOR ESI, ESI*/ - addbyte(0xf6); - } - else if (IS_32_ADDR(&seg->base)) - { - addbyte(0x8b); /*MOV ESI, seg->base*/ - addbyte(0x34); - addbyte(0x25); - addlong((uint32_t)(uintptr_t)&seg->base); - } - else - { - addbyte(0x48); /*MOV RSI, &addr*/ - addbyte(0xb8 | REG_ESI); - addquad((uint64_t)&seg->base); - addbyte(0x8b); /*MOV ESI, [RSI]*/ - addbyte(0x36); - } - - - /*seg = ESI, addr = EAX*/ - - if (IS_32_ADDR(&cr0)) - { - addbyte(0x83); /*CMP cr0, 0*/ - addbyte(0x3c); - addbyte(0x25); - addlong((uint32_t)(uintptr_t)&cr0); - addbyte(0); - } - else - { - addbyte(0x48); /*MOV RDI, &cr0*/ - addbyte(0xbf); - addquad((uint64_t)&cr0); - addbyte(0x83); /*CMPL [RDI], 0*/ - addbyte(0x3f); - addbyte(0); - } - addbyte(0x67); /*LEA EDI, [EAX+ESI]*/ - addbyte(0x8d); - addbyte(0x3c); - addbyte(0x30); - addbyte(0x79); /*JNS +*/ - jump1 = &codeblock[block_current].data[block_pos]; - addbyte(0); - if (!(seg == &cpu_state.seg_ds && codegen_flat_ds && !(cpu_cur_status & CPU_STATUS_NOTFLATDS)) && !(seg == &cpu_state.seg_ss && codegen_flat_ss && !(cpu_cur_status & CPU_STATUS_NOTFLATSS))) - { - addbyte(0x83); /*CMP ESI, -1*/ - addbyte(0xfe); - addbyte(-1); - } - addbyte(0x8d); /*LEA ESI, 1[EDI]*/ - addbyte(0x77); - addbyte(0x01); - if (!(seg == &cpu_state.seg_ds && codegen_flat_ds && !(cpu_cur_status & CPU_STATUS_NOTFLATDS)) && !(seg == &cpu_state.seg_ss && codegen_flat_ss && !(cpu_cur_status & CPU_STATUS_NOTFLATSS))) - { - addbyte(0x74); /*JE slowpath*/ - jump4 = &codeblock[block_current].data[block_pos]; - addbyte(0); - } - addbyte(0x89); /*MOV EBX, EDI*/ - addbyte(0xfb); - addbyte(0xc1); /*SHR EDI, 12*/ - addbyte(0xef); - addbyte(12); - addbyte(0xc1); /*SHR ESI, 12*/ - addbyte(0xee); - addbyte(12); - if (IS_32_ADDR(writelookup2)) - { - addbyte(0x83); /*CMP writelookup2[RDI*8],-1*/ - addbyte(0x3c); - addbyte(0xfd); - addlong((uint32_t)(uintptr_t)writelookup2); - addbyte(-1); - } - else - { - addbyte(0x48); /*MOV RAX, writelookup2*/ - addbyte(0xb8); - addquad((uint64_t)writelookup2); - addbyte(0x83); /*CMP [RAX+RDI*8], -1*/ - addbyte(0x3c); - addbyte(0xf8); - addbyte(-1); - } - addbyte(0x74); /*JE +*/ - jump2 = &codeblock[block_current].data[block_pos]; - addbyte(0); - if (IS_32_ADDR(writelookup2)) - { - addbyte(0x83); /*CMP writelookup2[RSI*8],-1*/ - addbyte(0x3c); - addbyte(0xf5); - addlong((uint32_t)(uintptr_t)writelookup2); - addbyte(-1); - } - else - { - addbyte(0x83); /*CMP [RAX+RSI*8], -1*/ - addbyte(0x3c); - addbyte(0xf0); - addbyte(-1); - } - addbyte(0x75); /*JNE +*/ - jump3 = &codeblock[block_current].data[block_pos]; - addbyte(0); - - /*slowpath:*/ - *jump2 = (uintptr_t)&codeblock[block_current].data[block_pos] - (uintptr_t)jump2 - 1; - if (!(seg == &cpu_state.seg_ds && codegen_flat_ds && !(cpu_cur_status & CPU_STATUS_NOTFLATDS)) && !(seg == &cpu_state.seg_ss && codegen_flat_ss && !(cpu_cur_status & CPU_STATUS_NOTFLATSS))) - *jump4 = (uintptr_t)&codeblock[block_current].data[block_pos] - (uintptr_t)jump4 - 1; - jump_pos = block_pos; - load_param_1_reg_32(REG_EBX); - load_param_2_32(&codeblock[block_current], 1); - call(&codeblock[block_current], (uintptr_t)mmutranslatereal32); - addbyte(0x83); /*ADD EBX, 1*/ - addbyte(0xc3); - addbyte(1); - addbyte(0x80); /*CMP abrt, 0*/ - addbyte(0x7d); - addbyte((uint8_t)cpu_state_offset(abrt)); - addbyte(0); - addbyte(0x0f); /*JNE mem_abrt_rout*/ - addbyte(0x85); - addlong((uintptr_t)&codeblock[block_current].data[BLOCK_EXIT_OFFSET] - ((uintptr_t)(&codeblock[block_current].data[block_pos]) + 4)); - /*If bits 0-11 of the address are now 0 then this crosses a page, so loop back*/ - addbyte(0xf7); /*TEST $fff, EBX*/ - addbyte(0xc3); - addlong(0xfff); - addbyte(0x74); /*JNE slowpath*/ - addbyte(jump_pos - block_pos - 1); - - *jump1 = (uintptr_t)&codeblock[block_current].data[block_pos] - (uintptr_t)jump1 - 1; - *jump3 = (uintptr_t)&codeblock[block_current].data[block_pos] - (uintptr_t)jump3 - 1; - - LOAD_EA(); -} - -static inline void MEM_CHECK_WRITE_L(x86seg *seg) -{ - uint8_t *jump1, *jump2, *jump3, *jump4 = NULL; - int jump_pos; - - CHECK_SEG_WRITE(seg); - - if ((seg == &cpu_state.seg_ds && codegen_flat_ds && !(cpu_cur_status & CPU_STATUS_NOTFLATDS)) || (seg == &cpu_state.seg_ss && codegen_flat_ss && !(cpu_cur_status & CPU_STATUS_NOTFLATSS))) - { - addbyte(0x31); /*XOR ESI, ESI*/ - addbyte(0xf6); - } - else if (IS_32_ADDR(&seg->base)) - { - addbyte(0x8b); /*MOV ESI, seg->base*/ - addbyte(0x34); - addbyte(0x25); - addlong((uint32_t)(uintptr_t)&seg->base); - } - else - { - addbyte(0x48); /*MOV RSI, &addr*/ - addbyte(0xb8 | REG_ESI); - addquad((uint64_t)&seg->base); - addbyte(0x8b); /*MOV ESI, [RSI]*/ - addbyte(0x36); - } - - - /*seg = ESI, addr = EAX*/ - - if (IS_32_ADDR(&cr0)) - { - addbyte(0x83); /*CMP cr0, 0*/ - addbyte(0x3c); - addbyte(0x25); - addlong((uint32_t)(uintptr_t)&cr0); - addbyte(0); - } - else - { - addbyte(0x48); /*MOV RDI, &cr0*/ - addbyte(0xbf); - addquad((uint64_t)&cr0); - addbyte(0x83); /*CMPL [RDI], 0*/ - addbyte(0x3f); - addbyte(0); - } - addbyte(0x67); /*LEA EDI, [EAX+ESI]*/ - addbyte(0x8d); - addbyte(0x3c); - addbyte(0x30); - addbyte(0x79); /*JNS +*/ - jump1 = &codeblock[block_current].data[block_pos]; - addbyte(0); - if (!(seg == &cpu_state.seg_ds && codegen_flat_ds && !(cpu_cur_status & CPU_STATUS_NOTFLATDS)) && !(seg == &cpu_state.seg_ss && codegen_flat_ss && !(cpu_cur_status & CPU_STATUS_NOTFLATSS))) - { - addbyte(0x83); /*CMP ESI, -1*/ - addbyte(0xfe); - addbyte(-1); - } - addbyte(0x8d); /*LEA ESI, 3[EDI]*/ - addbyte(0x77); - addbyte(0x03); - if (!(seg == &cpu_state.seg_ds && codegen_flat_ds && !(cpu_cur_status & CPU_STATUS_NOTFLATDS)) && !(seg == &cpu_state.seg_ss && codegen_flat_ss && !(cpu_cur_status & CPU_STATUS_NOTFLATSS))) - { - addbyte(0x74); /*JE slowpath*/ - jump4 = &codeblock[block_current].data[block_pos]; - addbyte(0); - } - addbyte(0x89); /*MOV EBX, EDI*/ - addbyte(0xfb); - addbyte(0xc1); /*SHR EDI, 12*/ - addbyte(0xef); - addbyte(12); - addbyte(0xc1); /*SHR ESI, 12*/ - addbyte(0xee); - addbyte(12); - if (IS_32_ADDR(writelookup2)) - { - addbyte(0x83); /*CMP writelookup2[RDI*8],-1*/ - addbyte(0x3c); - addbyte(0xfd); - addlong((uint32_t)(uintptr_t)writelookup2); - addbyte(-1); - } - else - { - addbyte(0x48); /*MOV RAX, writelookup2*/ - addbyte(0xb8); - addquad((uint64_t)writelookup2); - addbyte(0x83); /*CMP [RAX+RDI*8], -1*/ - addbyte(0x3c); - addbyte(0xf8); - addbyte(-1); - } - addbyte(0x74); /*JE slowpath*/ - jump2 = &codeblock[block_current].data[block_pos]; - addbyte(0); - if (IS_32_ADDR(writelookup2)) - { - addbyte(0x83); /*CMP writelookup2[RSI*8],-1*/ - addbyte(0x3c); - addbyte(0xf5); - addlong((uint32_t)(uintptr_t)writelookup2); - addbyte(-1); - } - else - { - addbyte(0x83); /*CMP [RAX+RSI*8], -1*/ - addbyte(0x3c); - addbyte(0xf0); - addbyte(-1); - } - addbyte(0x75); /*JNE +*/ - jump3 = &codeblock[block_current].data[block_pos]; - addbyte(0); - - /*slowpath:*/ - *jump2 = (uintptr_t)&codeblock[block_current].data[block_pos] - (uintptr_t)jump2 - 1; - if (!(seg == &cpu_state.seg_ds && codegen_flat_ds && !(cpu_cur_status & CPU_STATUS_NOTFLATDS)) && !(seg == &cpu_state.seg_ss && codegen_flat_ss && !(cpu_cur_status & CPU_STATUS_NOTFLATSS))) - *jump4 = (uintptr_t)&codeblock[block_current].data[block_pos] - (uintptr_t)jump4 - 1; - jump_pos = block_pos; - load_param_1_reg_32(REG_EBX); - load_param_2_32(&codeblock[block_current], 1); - call(&codeblock[block_current], (uintptr_t)mmutranslatereal32); - addbyte(0x83); /*ADD EBX, 3*/ - addbyte(0xc3); - addbyte(3); - addbyte(0x80); /*CMP abrt, 0*/ - addbyte(0x7d); - addbyte((uint8_t)cpu_state_offset(abrt)); - addbyte(0); - addbyte(0x0f); /*JNE mem_abrt_rout*/ - addbyte(0x85); - addlong((uintptr_t)&codeblock[block_current].data[BLOCK_EXIT_OFFSET] - ((uintptr_t)(&codeblock[block_current].data[block_pos]) + 4)); - /*If bits 0-11 of the address are now 0 then this crosses a page, so loop back*/ - addbyte(0xf7); /*TEST $ffc, EBX*/ - addbyte(0xc3); - addlong(0xffc); - addbyte(0x74); /*JE slowpath*/ - addbyte(jump_pos - block_pos - 1); - - *jump1 = (uintptr_t)&codeblock[block_current].data[block_pos] - (uintptr_t)jump1 - 1; - *jump3 = (uintptr_t)&codeblock[block_current].data[block_pos] - (uintptr_t)jump3 - 1; - - LOAD_EA(); -} - -static inline int MEM_LOAD_ADDR_EA_B_NO_ABRT(x86seg *seg) -{ - if ((seg == &cpu_state.seg_ds && codegen_flat_ds && !(cpu_cur_status & CPU_STATUS_NOTFLATDS)) || (seg == &cpu_state.seg_ss && codegen_flat_ss && !(cpu_cur_status & CPU_STATUS_NOTFLATSS))) - { - addbyte(0x31); /*XOR ECX, ECX*/ - addbyte(0xc9); - } - else if (IS_32_ADDR(&seg->base)) - { - addbyte(0x8b); /*MOVL ECX, seg->base*/ - addbyte(0x0c); - addbyte(0x25); - addlong((uint32_t)(uintptr_t)&seg->base); - } - else - { - addbyte(0x48); /*MOV RSI, &seg->base*/ - addbyte(0xb8 | REG_ESI); - addquad((uint64_t)&seg->base); - addbyte(0x8b); /*MOV ECX, [RSI]*/ - addbyte(0x0e); - } - addbyte(0x67); /*LEA ESI, (EAX,ECX)*/ - addbyte(0x8d); + if ((seg == &cpu_state.seg_ds && codegen_flat_ds && !(cpu_cur_status & CPU_STATUS_NOTFLATDS)) || (seg == &cpu_state.seg_ss && codegen_flat_ss && !(cpu_cur_status & CPU_STATUS_NOTFLATSS))) { + addbyte(0x31); /*XOR ESI, ESI*/ + addbyte(0xf6); + } else if (IS_32_ADDR(&seg->base)) { + addbyte(0x8b); /*MOV ESI, seg->base*/ addbyte(0x34); - addbyte(0x08); - addbyte(0x89); /*MOV EDI, ESI*/ - addbyte(0xf7); - addbyte(0xc1); /*SHR ESI, 12*/ - addbyte(0xe8 | REG_ESI); - addbyte(12); - if (IS_32_ADDR(readlookup2)) - { - addbyte(0x67); /*MOV RSI, readlookup2[ESI*8]*/ - addbyte(0x48); - addbyte(0x8b); - addbyte(0x34); - addbyte(0xf5); - addlong((uint32_t)(uintptr_t)readlookup2); - } - else - { - addbyte(0x48); /*MOV RDX, readlookup2*/ - addbyte(0xb8 | REG_EDX); - addquad((uint64_t)readlookup2); - addbyte(0x48); /*MOV RSI, [RDX+RSI*8]*/ - addbyte(0x8b); - addbyte(0x34); - addbyte(0xf2); - } + addbyte(0x25); + addlong((uint32_t) (uintptr_t) &seg->base); + } else { + addbyte(0x48); /*MOV RSI, &addr*/ + addbyte(0xb8 | REG_ESI); + addquad((uint64_t) &seg->base); + addbyte(0x8b); /*MOV ESI, [RSI]*/ + addbyte(0x36); + } + + /*seg = ESI, addr = EAX*/ + + if (IS_32_ADDR(&cr0)) { + addbyte(0x83); /*CMP cr0, 0*/ + addbyte(0x3c); + addbyte(0x25); + addlong((uint32_t) (uintptr_t) &cr0); + addbyte(0); + } else { + addbyte(0x48); /*MOV RDI, &cr0*/ + addbyte(0xbf); + addquad((uint64_t) &cr0); + addbyte(0x83); /*CMPL [RDI], 0*/ + addbyte(0x3f); + addbyte(0); + } + addbyte(0x67); /*LEA EDI, [EAX+ESI]*/ + addbyte(0x8d); + addbyte(0x3c); + addbyte(0x30); + addbyte(0x79); /*JNS +*/ + jump1 = &codeblock[block_current].data[block_pos]; + addbyte(0); + addbyte(0xc1); /*SHR EDI, 12*/ + addbyte(0xef); + addbyte(12); + if (!(seg == &cpu_state.seg_ds && codegen_flat_ds && !(cpu_cur_status & CPU_STATUS_NOTFLATDS)) && !(seg == &cpu_state.seg_ss && codegen_flat_ss && !(cpu_cur_status & CPU_STATUS_NOTFLATSS))) { addbyte(0x83); /*CMP ESI, -1*/ - addbyte(0xf8 | REG_ESI); + addbyte(0xfe); addbyte(-1); addbyte(0x74); /*JE slowpath*/ - addbyte(3+2); - addbyte(0x8b); /*MOV AL,[RDI+RSI]*/ - addbyte(0x04); - addbyte(REG_EDI | (REG_ESI << 3)); - addbyte(0xeb); /*JMP done*/ - addbyte(2+2+12); - /*slowpath:*/ - addbyte(0x01); /*ADD ECX,EAX*/ - addbyte(0xc1); - load_param_1_reg_32(REG_ECX); - call_long((uintptr_t)readmembl); - addbyte(0x89); /*MOV ECX, EAX*/ - addbyte(0xc1); - /*done:*/ - - host_reg_mapping[REG_ECX] = 8; - - return REG_ECX; -} -static inline int MEM_LOAD_ADDR_EA_W_NO_ABRT(x86seg *seg) -{ - if ((seg == &cpu_state.seg_ds && codegen_flat_ds && !(cpu_cur_status & CPU_STATUS_NOTFLATDS)) || (seg == &cpu_state.seg_ss && codegen_flat_ss && !(cpu_cur_status & CPU_STATUS_NOTFLATSS))) - { - addbyte(0x31); /*XOR ECX, ECX*/ - addbyte(0xc9); - } - else if (IS_32_ADDR(&seg->base)) - { - addbyte(0x8b); /*MOVL ECX, seg->base*/ - addbyte(0x0c); - addbyte(0x25); - addlong((uint32_t)(uintptr_t)&seg->base); - } - else - { - addbyte(0x48); /*MOV RSI, &seg->base*/ - addbyte(0xb8 | REG_ESI); - addquad((uint64_t)&seg->base); - addbyte(0x8b); /*MOV ECX, [RSI]*/ - addbyte(0x0e); - } - addbyte(0x67); /*LEA ESI, (EAX,ECX)*/ - addbyte(0x8d); - addbyte(0x34); - addbyte(0x08); - addbyte(0x89); /*MOV EDI, ESI*/ - addbyte(0xf7); - addbyte(0xc1); /*SHR ESI, 12*/ - addbyte(0xe8 | REG_ESI); - addbyte(12); - addbyte(0xf7); /*TEST EDI, 1*/ - addbyte(0xc7); - addlong(1); - if (IS_32_ADDR(readlookup2)) - { - addbyte(0x67); /*MOV RSI, readlookup2[ESI*8]*/ - addbyte(0x48); - addbyte(0x8b); - addbyte(0x34); - addbyte(0xf5); - addlong((uint32_t)(uintptr_t)readlookup2); - } - else - { - addbyte(0x48); /*MOV RDX, readlookup2*/ - addbyte(0xb8 | REG_EDX); - addquad((uint64_t)readlookup2); - addbyte(0x48); /*MOV RSI, [RDX+RSI*8]*/ - addbyte(0x8b); - addbyte(0x34); - addbyte(0xf2); - } - addbyte(0x75); /*JNE slowpath*/ - addbyte(3+2+4+2); - addbyte(0x83); /*CMP ESI, -1*/ - addbyte(0xf8 | REG_ESI); + jump3 = &codeblock[block_current].data[block_pos]; + addbyte(0); + } + if (IS_32_ADDR(writelookup2)) { + addbyte(0x83); /*CMP writelookup2[RDI*8],-1*/ + addbyte(0x3c); + addbyte(0xfd); + addlong((uint32_t) (uintptr_t) writelookup2); addbyte(-1); + } else { + addbyte(0x48); /*MOV RCX, writelookup2*/ + addbyte(0xb9); + addquad((uint64_t) writelookup2); + addbyte(0x83); /*CMP [RCX+RDI*8], -1*/ + addbyte(0x3c); + addbyte(0xf9); + addbyte(-1); + } + addbyte(0x75); /*JNE +*/ + jump2 = &codeblock[block_current].data[block_pos]; + addbyte(0); + + if (!(seg == &cpu_state.seg_ds && codegen_flat_ds && !(cpu_cur_status & CPU_STATUS_NOTFLATDS)) && !(seg == &cpu_state.seg_ss && codegen_flat_ss && !(cpu_cur_status & CPU_STATUS_NOTFLATSS))) + *jump3 = (uintptr_t) &codeblock[block_current].data[block_pos] - (uintptr_t) jump3 - 1; + /*slowpath:*/ + addbyte(0x67); /*LEA EDI, [EAX+ESI]*/ + addbyte(0x8d); + addbyte(0x3c); + addbyte(0x30); + + load_param_1_reg_32(REG_EDI); + load_param_2_32(&codeblock[block_current], 1); + + call(&codeblock[block_current], (uintptr_t) mmutranslatereal32); + addbyte(0x80); /*CMP abrt, 0*/ + addbyte(0x7d); + addbyte((uint8_t) cpu_state_offset(abrt)); + addbyte(0); + addbyte(0x0f); /*JNE mem_abrt_rout*/ + addbyte(0x85); + addlong((uintptr_t) &codeblock[block_current].data[BLOCK_EXIT_OFFSET] - ((uintptr_t) (&codeblock[block_current].data[block_pos]) + 4)); + *jump1 = (uintptr_t) &codeblock[block_current].data[block_pos] - (uintptr_t) jump1 - 1; + *jump2 = (uintptr_t) &codeblock[block_current].data[block_pos] - (uintptr_t) jump2 - 1; + + LOAD_EA(); +} + +static __inline void +MEM_CHECK_WRITE_W(x86seg *seg) +{ + uint8_t *jump1 = NULL; + uint8_t *jump2 = NULL; + uint8_t *jump3 = NULL; + uint8_t *jump4 = NULL; + int jump_pos; + + CHECK_SEG_WRITE(seg); + + if ((seg == &cpu_state.seg_ds && codegen_flat_ds && !(cpu_cur_status & CPU_STATUS_NOTFLATDS)) || (seg == &cpu_state.seg_ss && codegen_flat_ss && !(cpu_cur_status & CPU_STATUS_NOTFLATSS))) { + addbyte(0x31); /*XOR ESI, ESI*/ + addbyte(0xf6); + } else if (IS_32_ADDR(&seg->base)) { + addbyte(0x8b); /*MOV ESI, seg->base*/ + addbyte(0x34); + addbyte(0x25); + addlong((uint32_t) (uintptr_t) &seg->base); + } else { + addbyte(0x48); /*MOV RSI, &addr*/ + addbyte(0xb8 | REG_ESI); + addquad((uint64_t) &seg->base); + addbyte(0x8b); /*MOV ESI, [RSI]*/ + addbyte(0x36); + } + + /*seg = ESI, addr = EAX*/ + + if (IS_32_ADDR(&cr0)) { + addbyte(0x83); /*CMP cr0, 0*/ + addbyte(0x3c); + addbyte(0x25); + addlong((uint32_t) (uintptr_t) &cr0); + addbyte(0); + } else { + addbyte(0x48); /*MOV RDI, &cr0*/ + addbyte(0xbf); + addquad((uint64_t) &cr0); + addbyte(0x83); /*CMPL [RDI], 0*/ + addbyte(0x3f); + addbyte(0); + } + addbyte(0x67); /*LEA EDI, [EAX+ESI]*/ + addbyte(0x8d); + addbyte(0x3c); + addbyte(0x30); + addbyte(0x79); /*JNS +*/ + jump1 = &codeblock[block_current].data[block_pos]; + addbyte(0); + if (!(seg == &cpu_state.seg_ds && codegen_flat_ds && !(cpu_cur_status & CPU_STATUS_NOTFLATDS)) && !(seg == &cpu_state.seg_ss && codegen_flat_ss && !(cpu_cur_status & CPU_STATUS_NOTFLATSS))) { + addbyte(0x83); /*CMP ESI, -1*/ + addbyte(0xfe); + addbyte(-1); + } + addbyte(0x8d); /*LEA ESI, 1[EDI]*/ + addbyte(0x77); + addbyte(0x01); + if (!(seg == &cpu_state.seg_ds && codegen_flat_ds && !(cpu_cur_status & CPU_STATUS_NOTFLATDS)) && !(seg == &cpu_state.seg_ss && codegen_flat_ss && !(cpu_cur_status & CPU_STATUS_NOTFLATSS))) { addbyte(0x74); /*JE slowpath*/ - addbyte(4+2); - addbyte(0x66); /*MOV AX,[RDI+RSI]*/ + jump4 = &codeblock[block_current].data[block_pos]; + addbyte(0); + } + addbyte(0x89); /*MOV EBX, EDI*/ + addbyte(0xfb); + addbyte(0xc1); /*SHR EDI, 12*/ + addbyte(0xef); + addbyte(12); + addbyte(0xc1); /*SHR ESI, 12*/ + addbyte(0xee); + addbyte(12); + if (IS_32_ADDR(writelookup2)) { + addbyte(0x83); /*CMP writelookup2[RDI*8],-1*/ + addbyte(0x3c); + addbyte(0xfd); + addlong((uint32_t) (uintptr_t) writelookup2); + addbyte(-1); + } else { + addbyte(0x48); /*MOV RAX, writelookup2*/ + addbyte(0xb8); + addquad((uint64_t) writelookup2); + addbyte(0x83); /*CMP [RAX+RDI*8], -1*/ + addbyte(0x3c); + addbyte(0xf8); + addbyte(-1); + } + addbyte(0x74); /*JE +*/ + jump2 = &codeblock[block_current].data[block_pos]; + addbyte(0); + if (IS_32_ADDR(writelookup2)) { + addbyte(0x83); /*CMP writelookup2[RSI*8],-1*/ + addbyte(0x3c); + addbyte(0xf5); + addlong((uint32_t) (uintptr_t) writelookup2); + addbyte(-1); + } else { + addbyte(0x83); /*CMP [RAX+RSI*8], -1*/ + addbyte(0x3c); + addbyte(0xf0); + addbyte(-1); + } + addbyte(0x75); /*JNE +*/ + jump3 = &codeblock[block_current].data[block_pos]; + addbyte(0); + + /*slowpath:*/ + *jump2 = (uintptr_t) &codeblock[block_current].data[block_pos] - (uintptr_t) jump2 - 1; + if (!(seg == &cpu_state.seg_ds && codegen_flat_ds && !(cpu_cur_status & CPU_STATUS_NOTFLATDS)) && !(seg == &cpu_state.seg_ss && codegen_flat_ss && !(cpu_cur_status & CPU_STATUS_NOTFLATSS))) + *jump4 = (uintptr_t) &codeblock[block_current].data[block_pos] - (uintptr_t) jump4 - 1; + jump_pos = block_pos; + load_param_1_reg_32(REG_EBX); + load_param_2_32(&codeblock[block_current], 1); + call(&codeblock[block_current], (uintptr_t) mmutranslatereal32); + addbyte(0x83); /*ADD EBX, 1*/ + addbyte(0xc3); + addbyte(1); + addbyte(0x80); /*CMP abrt, 0*/ + addbyte(0x7d); + addbyte((uint8_t) cpu_state_offset(abrt)); + addbyte(0); + addbyte(0x0f); /*JNE mem_abrt_rout*/ + addbyte(0x85); + addlong((uintptr_t) &codeblock[block_current].data[BLOCK_EXIT_OFFSET] - ((uintptr_t) (&codeblock[block_current].data[block_pos]) + 4)); + /*If bits 0-11 of the address are now 0 then this crosses a page, so loop back*/ + addbyte(0xf7); /*TEST $fff, EBX*/ + addbyte(0xc3); + addlong(0xfff); + addbyte(0x74); /*JNE slowpath*/ + addbyte(jump_pos - block_pos - 1); + + *jump1 = (uintptr_t) &codeblock[block_current].data[block_pos] - (uintptr_t) jump1 - 1; + *jump3 = (uintptr_t) &codeblock[block_current].data[block_pos] - (uintptr_t) jump3 - 1; + + LOAD_EA(); +} + +static __inline void +MEM_CHECK_WRITE_L(x86seg *seg) +{ + uint8_t *jump1 = NULL; + uint8_t *jump2 = NULL; + uint8_t *jump3 = NULL; + uint8_t *jump4 = NULL; + int jump_pos; + + CHECK_SEG_WRITE(seg); + + if ((seg == &cpu_state.seg_ds && codegen_flat_ds && !(cpu_cur_status & CPU_STATUS_NOTFLATDS)) || (seg == &cpu_state.seg_ss && codegen_flat_ss && !(cpu_cur_status & CPU_STATUS_NOTFLATSS))) { + addbyte(0x31); /*XOR ESI, ESI*/ + addbyte(0xf6); + } else if (IS_32_ADDR(&seg->base)) { + addbyte(0x8b); /*MOV ESI, seg->base*/ + addbyte(0x34); + addbyte(0x25); + addlong((uint32_t) (uintptr_t) &seg->base); + } else { + addbyte(0x48); /*MOV RSI, &addr*/ + addbyte(0xb8 | REG_ESI); + addquad((uint64_t) &seg->base); + addbyte(0x8b); /*MOV ESI, [RSI]*/ + addbyte(0x36); + } + + /*seg = ESI, addr = EAX*/ + + if (IS_32_ADDR(&cr0)) { + addbyte(0x83); /*CMP cr0, 0*/ + addbyte(0x3c); + addbyte(0x25); + addlong((uint32_t) (uintptr_t) &cr0); + addbyte(0); + } else { + addbyte(0x48); /*MOV RDI, &cr0*/ + addbyte(0xbf); + addquad((uint64_t) &cr0); + addbyte(0x83); /*CMPL [RDI], 0*/ + addbyte(0x3f); + addbyte(0); + } + addbyte(0x67); /*LEA EDI, [EAX+ESI]*/ + addbyte(0x8d); + addbyte(0x3c); + addbyte(0x30); + addbyte(0x79); /*JNS +*/ + jump1 = &codeblock[block_current].data[block_pos]; + addbyte(0); + if (!(seg == &cpu_state.seg_ds && codegen_flat_ds && !(cpu_cur_status & CPU_STATUS_NOTFLATDS)) && !(seg == &cpu_state.seg_ss && codegen_flat_ss && !(cpu_cur_status & CPU_STATUS_NOTFLATSS))) { + addbyte(0x83); /*CMP ESI, -1*/ + addbyte(0xfe); + addbyte(-1); + } + addbyte(0x8d); /*LEA ESI, 3[EDI]*/ + addbyte(0x77); + addbyte(0x03); + if (!(seg == &cpu_state.seg_ds && codegen_flat_ds && !(cpu_cur_status & CPU_STATUS_NOTFLATDS)) && !(seg == &cpu_state.seg_ss && codegen_flat_ss && !(cpu_cur_status & CPU_STATUS_NOTFLATSS))) { + addbyte(0x74); /*JE slowpath*/ + jump4 = &codeblock[block_current].data[block_pos]; + addbyte(0); + } + addbyte(0x89); /*MOV EBX, EDI*/ + addbyte(0xfb); + addbyte(0xc1); /*SHR EDI, 12*/ + addbyte(0xef); + addbyte(12); + addbyte(0xc1); /*SHR ESI, 12*/ + addbyte(0xee); + addbyte(12); + if (IS_32_ADDR(writelookup2)) { + addbyte(0x83); /*CMP writelookup2[RDI*8],-1*/ + addbyte(0x3c); + addbyte(0xfd); + addlong((uint32_t) (uintptr_t) writelookup2); + addbyte(-1); + } else { + addbyte(0x48); /*MOV RAX, writelookup2*/ + addbyte(0xb8); + addquad((uint64_t) writelookup2); + addbyte(0x83); /*CMP [RAX+RDI*8], -1*/ + addbyte(0x3c); + addbyte(0xf8); + addbyte(-1); + } + addbyte(0x74); /*JE slowpath*/ + jump2 = &codeblock[block_current].data[block_pos]; + addbyte(0); + if (IS_32_ADDR(writelookup2)) { + addbyte(0x83); /*CMP writelookup2[RSI*8],-1*/ + addbyte(0x3c); + addbyte(0xf5); + addlong((uint32_t) (uintptr_t) writelookup2); + addbyte(-1); + } else { + addbyte(0x83); /*CMP [RAX+RSI*8], -1*/ + addbyte(0x3c); + addbyte(0xf0); + addbyte(-1); + } + addbyte(0x75); /*JNE +*/ + jump3 = &codeblock[block_current].data[block_pos]; + addbyte(0); + + /*slowpath:*/ + *jump2 = (uintptr_t) &codeblock[block_current].data[block_pos] - (uintptr_t) jump2 - 1; + if (!(seg == &cpu_state.seg_ds && codegen_flat_ds && !(cpu_cur_status & CPU_STATUS_NOTFLATDS)) && !(seg == &cpu_state.seg_ss && codegen_flat_ss && !(cpu_cur_status & CPU_STATUS_NOTFLATSS))) + *jump4 = (uintptr_t) &codeblock[block_current].data[block_pos] - (uintptr_t) jump4 - 1; + jump_pos = block_pos; + load_param_1_reg_32(REG_EBX); + load_param_2_32(&codeblock[block_current], 1); + call(&codeblock[block_current], (uintptr_t) mmutranslatereal32); + addbyte(0x83); /*ADD EBX, 3*/ + addbyte(0xc3); + addbyte(3); + addbyte(0x80); /*CMP abrt, 0*/ + addbyte(0x7d); + addbyte((uint8_t) cpu_state_offset(abrt)); + addbyte(0); + addbyte(0x0f); /*JNE mem_abrt_rout*/ + addbyte(0x85); + addlong((uintptr_t) &codeblock[block_current].data[BLOCK_EXIT_OFFSET] - ((uintptr_t) (&codeblock[block_current].data[block_pos]) + 4)); + /*If bits 0-11 of the address are now 0 then this crosses a page, so loop back*/ + addbyte(0xf7); /*TEST $ffc, EBX*/ + addbyte(0xc3); + addlong(0xffc); + addbyte(0x74); /*JE slowpath*/ + addbyte(jump_pos - block_pos - 1); + + *jump1 = (uintptr_t) &codeblock[block_current].data[block_pos] - (uintptr_t) jump1 - 1; + *jump3 = (uintptr_t) &codeblock[block_current].data[block_pos] - (uintptr_t) jump3 - 1; + + LOAD_EA(); +} + +static __inline int +MEM_LOAD_ADDR_EA_B_NO_ABRT(x86seg *seg) +{ + if ((seg == &cpu_state.seg_ds && codegen_flat_ds && !(cpu_cur_status & CPU_STATUS_NOTFLATDS)) || (seg == &cpu_state.seg_ss && codegen_flat_ss && !(cpu_cur_status & CPU_STATUS_NOTFLATSS))) { + addbyte(0x31); /*XOR ECX, ECX*/ + addbyte(0xc9); + } else if (IS_32_ADDR(&seg->base)) { + addbyte(0x8b); /*MOVL ECX, seg->base*/ + addbyte(0x0c); + addbyte(0x25); + addlong((uint32_t) (uintptr_t) &seg->base); + } else { + addbyte(0x48); /*MOV RSI, &seg->base*/ + addbyte(0xb8 | REG_ESI); + addquad((uint64_t) &seg->base); + addbyte(0x8b); /*MOV ECX, [RSI]*/ + addbyte(0x0e); + } + addbyte(0x67); /*LEA ESI, (EAX,ECX)*/ + addbyte(0x8d); + addbyte(0x34); + addbyte(0x08); + addbyte(0x89); /*MOV EDI, ESI*/ + addbyte(0xf7); + addbyte(0xc1); /*SHR ESI, 12*/ + addbyte(0xe8 | REG_ESI); + addbyte(12); + if (IS_32_ADDR(readlookup2)) { + addbyte(0x67); /*MOV RSI, readlookup2[ESI*8]*/ + addbyte(0x48); addbyte(0x8b); - addbyte(0x04); + addbyte(0x34); + addbyte(0xf5); + addlong((uint32_t) (uintptr_t) readlookup2); + } else { + addbyte(0x48); /*MOV RDX, readlookup2*/ + addbyte(0xb8 | REG_EDX); + addquad((uint64_t) readlookup2); + addbyte(0x48); /*MOV RSI, [RDX+RSI*8]*/ + addbyte(0x8b); + addbyte(0x34); + addbyte(0xf2); + } + addbyte(0x83); /*CMP ESI, -1*/ + addbyte(0xf8 | REG_ESI); + addbyte(-1); + addbyte(0x74); /*JE slowpath*/ + addbyte(3 + 2); + addbyte(0x8b); /*MOV AL,[RDI+RSI]*/ + addbyte(0x04); + addbyte(REG_EDI | (REG_ESI << 3)); + addbyte(0xeb); /*JMP done*/ + addbyte(2 + 2 + 12); + /*slowpath:*/ + addbyte(0x01); /*ADD ECX,EAX*/ + addbyte(0xc1); + load_param_1_reg_32(REG_ECX); + call_long((uintptr_t) readmembl); + addbyte(0x89); /*MOV ECX, EAX*/ + addbyte(0xc1); + /*done:*/ + + host_reg_mapping[REG_ECX] = 8; + + return REG_ECX; +} +static __inline int +MEM_LOAD_ADDR_EA_W_NO_ABRT(x86seg *seg) +{ + if ((seg == &cpu_state.seg_ds && codegen_flat_ds && !(cpu_cur_status & CPU_STATUS_NOTFLATDS)) || (seg == &cpu_state.seg_ss && codegen_flat_ss && !(cpu_cur_status & CPU_STATUS_NOTFLATSS))) { + addbyte(0x31); /*XOR ECX, ECX*/ + addbyte(0xc9); + } else if (IS_32_ADDR(&seg->base)) { + addbyte(0x8b); /*MOVL ECX, seg->base*/ + addbyte(0x0c); + addbyte(0x25); + addlong((uint32_t) (uintptr_t) &seg->base); + } else { + addbyte(0x48); /*MOV RSI, &seg->base*/ + addbyte(0xb8 | REG_ESI); + addquad((uint64_t) &seg->base); + addbyte(0x8b); /*MOV ECX, [RSI]*/ + addbyte(0x0e); + } + addbyte(0x67); /*LEA ESI, (EAX,ECX)*/ + addbyte(0x8d); + addbyte(0x34); + addbyte(0x08); + addbyte(0x89); /*MOV EDI, ESI*/ + addbyte(0xf7); + addbyte(0xc1); /*SHR ESI, 12*/ + addbyte(0xe8 | REG_ESI); + addbyte(12); + addbyte(0xf7); /*TEST EDI, 1*/ + addbyte(0xc7); + addlong(1); + if (IS_32_ADDR(readlookup2)) { + addbyte(0x67); /*MOV RSI, readlookup2[ESI*8]*/ + addbyte(0x48); + addbyte(0x8b); + addbyte(0x34); + addbyte(0xf5); + addlong((uint32_t) (uintptr_t) readlookup2); + } else { + addbyte(0x48); /*MOV RDX, readlookup2*/ + addbyte(0xb8 | REG_EDX); + addquad((uint64_t) readlookup2); + addbyte(0x48); /*MOV RSI, [RDX+RSI*8]*/ + addbyte(0x8b); + addbyte(0x34); + addbyte(0xf2); + } + addbyte(0x75); /*JNE slowpath*/ + addbyte(3 + 2 + 4 + 2); + addbyte(0x83); /*CMP ESI, -1*/ + addbyte(0xf8 | REG_ESI); + addbyte(-1); + addbyte(0x74); /*JE slowpath*/ + addbyte(4 + 2); + addbyte(0x66); /*MOV AX,[RDI+RSI]*/ + addbyte(0x8b); + addbyte(0x04); + addbyte(REG_EDI | (REG_ESI << 3)); + addbyte(0xeb); /*JMP done*/ + addbyte(2 + 2 + 12); + /*slowpath:*/ + addbyte(0x01); /*ADD ECX,EAX*/ + addbyte(0xc1); + load_param_1_reg_32(REG_ECX); + call_long((uintptr_t) readmemwl); + addbyte(0x89); /*MOV ECX, EAX*/ + addbyte(0xc1); + /*done:*/ + + host_reg_mapping[REG_ECX] = 8; + + return REG_ECX; +} +static __inline int +MEM_LOAD_ADDR_EA_L_NO_ABRT(x86seg *seg) +{ + if ((seg == &cpu_state.seg_ds && codegen_flat_ds && !(cpu_cur_status & CPU_STATUS_NOTFLATDS)) || (seg == &cpu_state.seg_ss && codegen_flat_ss && !(cpu_cur_status & CPU_STATUS_NOTFLATSS))) { + addbyte(0x31); /*XOR ECX, ECX*/ + addbyte(0xc9); + } else if (IS_32_ADDR(&seg->base)) { + addbyte(0x8b); /*MOVL ECX, seg->base*/ + addbyte(0x0c); + addbyte(0x25); + addlong((uint32_t) (uintptr_t) &seg->base); + } else { + addbyte(0x48); /*MOV RSI, &seg->base*/ + addbyte(0xb8 | REG_ESI); + addquad((uint64_t) &seg->base); + addbyte(0x8b); /*MOV ECX, [RSI]*/ + addbyte(0x0e); + } + addbyte(0x67); /*LEA ESI, (EAX,ECX)*/ + addbyte(0x8d); + addbyte(0x34); + addbyte(0x08); + addbyte(0x89); /*MOV EDI, ESI*/ + addbyte(0xf7); + addbyte(0xc1); /*SHR ESI, 12*/ + addbyte(0xe8 | REG_ESI); + addbyte(12); + addbyte(0xf7); /*TEST EDI, 3*/ + addbyte(0xc7); + addlong(3); + if (IS_32_ADDR(readlookup2)) { + addbyte(0x67); /*MOV RSI, readlookup2[ESI*8]*/ + addbyte(0x48); + addbyte(0x8b); + addbyte(0x34); + addbyte(0xf5); + addlong((uint32_t) (uintptr_t) readlookup2); + } else { + addbyte(0x48); /*MOV RDX, readlookup2*/ + addbyte(0xb8 | REG_EDX); + addquad((uint64_t) readlookup2); + addbyte(0x48); /*MOV RSI, [RDX+RSI*8]*/ + addbyte(0x8b); + addbyte(0x34); + addbyte(0xf2); + } + addbyte(0x75); /*JNE slowpath*/ + addbyte(3 + 2 + 3 + 2); + addbyte(0x83); /*CMP ESI, -1*/ + addbyte(0xf8 | REG_ESI); + addbyte(-1); + addbyte(0x74); /*JE slowpath*/ + addbyte(3 + 2); + addbyte(0x8b); /*MOV EAX,[RDI+RSI]*/ + addbyte(0x04); + addbyte(REG_EDI | (REG_ESI << 3)); + addbyte(0xeb); /*JMP done*/ + addbyte(2 + 2 + 12); + /*slowpath:*/ + addbyte(0x01); /*ADD ECX,EAX*/ + addbyte(0xc1); + load_param_1_reg_32(REG_ECX); + call_long((uintptr_t) readmemll); + addbyte(0x89); /*MOV ECX, EAX*/ + addbyte(0xc1); + /*done:*/ + + host_reg_mapping[REG_ECX] = 8; + + return REG_ECX; +} + +static __inline void +MEM_STORE_ADDR_EA_B_NO_ABRT(x86seg *seg, int host_reg) +{ + if (host_reg & 0x10) { + /*Handle high byte of register*/ + if (host_reg & 8) { + addbyte(0x45); /*MOVL R8, host_reg*/ + addbyte(0x89); + addbyte(0xc0 | ((host_reg & 7) << 3)); + } else { + addbyte(0x41); /*MOVL R8, host_reg*/ + addbyte(0x89); + addbyte(0xc0 | ((host_reg & 7) << 3)); + } + addbyte(0x66); /*SHR R8, 8*/ + addbyte(0x41); + addbyte(0xc1); + addbyte(0xe8); + addbyte(8); + host_reg = 8; + } + if ((seg == &cpu_state.seg_ds && codegen_flat_ds && !(cpu_cur_status & CPU_STATUS_NOTFLATDS)) || (seg == &cpu_state.seg_ss && codegen_flat_ss && !(cpu_cur_status & CPU_STATUS_NOTFLATSS))) { + addbyte(0x31); /*XOR EBX, EBX*/ + addbyte(0xdb); + } else if (IS_32_ADDR(&seg->base)) { + addbyte(0x8b); /*MOVL EBX, seg->base*/ + addbyte(0x1c); + addbyte(0x25); + addlong((uint32_t) (uintptr_t) &seg->base); + } else { + addbyte(0x48); /*MOV RSI, &seg->base*/ + addbyte(0xb8 | REG_ESI); + addquad((uint64_t) &seg->base); + addbyte(0x8b); /*MOV EBX, [RSI]*/ + addbyte(0x1e); + } + addbyte(0x67); /*LEA ESI, (EAX,EBX)*/ + addbyte(0x8d); + addbyte(0x34); + addbyte(0x18); + addbyte(0x89); /*MOV EDI, ESI*/ + addbyte(0xf7); + addbyte(0xc1); /*SHR ESI, 12*/ + addbyte(0xe8 | REG_ESI); + addbyte(12); + if (IS_32_ADDR(writelookup2)) { + addbyte(0x67); /*MOV RSI, writelookup2[ESI*8]*/ + addbyte(0x48); + addbyte(0x8b); + addbyte(0x34); + addbyte(0xf5); + addlong((uint32_t) (uintptr_t) writelookup2); + } else { + addbyte(0x48); /*MOV RDX, writelookup2*/ + addbyte(0xb8 | REG_EDX); + addquad((uint64_t) writelookup2); + addbyte(0x48); /*MOV RSI, [RDX+RSI*8]*/ + addbyte(0x8b); + addbyte(0x34); + addbyte(0xf2); + } + addbyte(0x83); /*CMP ESI, -1*/ + addbyte(0xf8 | REG_ESI); + addbyte(-1); + addbyte(0x74); /*JE slowpath*/ + addbyte(((host_reg & 8) ? 4 : 3) + 2); + if (host_reg & 8) { + addbyte(0x44); /*MOV [RDI+RSI],host_reg*/ + addbyte(0x88); + addbyte(0x04 | ((host_reg & 7) << 3)); addbyte(REG_EDI | (REG_ESI << 3)); - addbyte(0xeb); /*JMP done*/ - addbyte(2+2+12); - /*slowpath:*/ - addbyte(0x01); /*ADD ECX,EAX*/ - addbyte(0xc1); - load_param_1_reg_32(REG_ECX); - call_long((uintptr_t)readmemwl); - addbyte(0x89); /*MOV ECX, EAX*/ - addbyte(0xc1); - /*done:*/ - - host_reg_mapping[REG_ECX] = 8; - - return REG_ECX; -} -static inline int MEM_LOAD_ADDR_EA_L_NO_ABRT(x86seg *seg) -{ - if ((seg == &cpu_state.seg_ds && codegen_flat_ds && !(cpu_cur_status & CPU_STATUS_NOTFLATDS)) || (seg == &cpu_state.seg_ss && codegen_flat_ss && !(cpu_cur_status & CPU_STATUS_NOTFLATSS))) - { - addbyte(0x31); /*XOR ECX, ECX*/ - addbyte(0xc9); - } - else if (IS_32_ADDR(&seg->base)) - { - addbyte(0x8b); /*MOVL ECX, seg->base*/ - addbyte(0x0c); - addbyte(0x25); - addlong((uint32_t)(uintptr_t)&seg->base); - } - else - { - addbyte(0x48); /*MOV RSI, &seg->base*/ - addbyte(0xb8 | REG_ESI); - addquad((uint64_t)&seg->base); - addbyte(0x8b); /*MOV ECX, [RSI]*/ - addbyte(0x0e); - } - addbyte(0x67); /*LEA ESI, (EAX,ECX)*/ - addbyte(0x8d); - addbyte(0x34); - addbyte(0x08); - addbyte(0x89); /*MOV EDI, ESI*/ - addbyte(0xf7); - addbyte(0xc1); /*SHR ESI, 12*/ - addbyte(0xe8 | REG_ESI); - addbyte(12); - addbyte(0xf7); /*TEST EDI, 3*/ - addbyte(0xc7); - addlong(3); - if (IS_32_ADDR(readlookup2)) - { - addbyte(0x67); /*MOV RSI, readlookup2[ESI*8]*/ - addbyte(0x48); - addbyte(0x8b); - addbyte(0x34); - addbyte(0xf5); - addlong((uint32_t)(uintptr_t)readlookup2); - } - else - { - addbyte(0x48); /*MOV RDX, readlookup2*/ - addbyte(0xb8 | REG_EDX); - addquad((uint64_t)readlookup2); - addbyte(0x48); /*MOV RSI, [RDX+RSI*8]*/ - addbyte(0x8b); - addbyte(0x34); - addbyte(0xf2); - } - addbyte(0x75); /*JNE slowpath*/ - addbyte(3+2+3+2); - addbyte(0x83); /*CMP ESI, -1*/ - addbyte(0xf8 | REG_ESI); - addbyte(-1); - addbyte(0x74); /*JE slowpath*/ - addbyte(3+2); - addbyte(0x8b); /*MOV EAX,[RDI+RSI]*/ - addbyte(0x04); + } else { + addbyte(0x88); /*MOV [RDI+RSI],host_reg*/ + addbyte(0x04 | (host_reg << 3)); addbyte(REG_EDI | (REG_ESI << 3)); - addbyte(0xeb); /*JMP done*/ - addbyte(2+2+12); - /*slowpath:*/ - addbyte(0x01); /*ADD ECX,EAX*/ - addbyte(0xc1); - load_param_1_reg_32(REG_ECX); - call_long((uintptr_t)readmemll); - addbyte(0x89); /*MOV ECX, EAX*/ - addbyte(0xc1); - /*done:*/ - - host_reg_mapping[REG_ECX] = 8; - - return REG_ECX; + } + addbyte(0xeb); /*JMP done*/ + if (host_reg & 8) { + addbyte(2 + 2 + 3 + 12); + } else { + addbyte(2 + 2 + 2 + 12); + } + /*slowpath:*/ + load_param_2_reg_32(host_reg); + addbyte(0x01); /*ADD EBX,EAX*/ + addbyte(0xc3); + load_param_1_reg_32(REG_EBX); + call_long((uintptr_t) writemembl); + /*done:*/ +} +static __inline void +MEM_STORE_ADDR_EA_W_NO_ABRT(x86seg *seg, int host_reg) +{ + if ((seg == &cpu_state.seg_ds && codegen_flat_ds && !(cpu_cur_status & CPU_STATUS_NOTFLATDS)) || (seg == &cpu_state.seg_ss && codegen_flat_ss && !(cpu_cur_status & CPU_STATUS_NOTFLATSS))) { + addbyte(0x31); /*XOR EBX, EBX*/ + addbyte(0xdb); + } else if (IS_32_ADDR(&seg->base)) { + addbyte(0x8b); /*MOVL EBX, seg->base*/ + addbyte(0x1c); + addbyte(0x25); + addlong((uint32_t) (uintptr_t) &seg->base); + } else { + addbyte(0x48); /*MOV RSI, &seg->base*/ + addbyte(0xb8 | REG_ESI); + addquad((uint64_t) &seg->base); + addbyte(0x8b); /*MOV EBX, [RSI]*/ + addbyte(0x1e); + } + addbyte(0x67); /*LEA ESI, (EAX,EBX)*/ + addbyte(0x8d); + addbyte(0x34); + addbyte(0x18); + addbyte(0x89); /*MOV EDI, ESI*/ + addbyte(0xf7); + addbyte(0xc1); /*SHR ESI, 12*/ + addbyte(0xe8 | REG_ESI); + addbyte(12); + addbyte(0xf7); /*TEST EDI, 1*/ + addbyte(0xc7); + addlong(1); + if (IS_32_ADDR(writelookup2)) { + addbyte(0x67); /*MOV RSI, writelookup2[ESI*8]*/ + addbyte(0x48); + addbyte(0x8b); + addbyte(0x34); + addbyte(0xf5); + addlong((uint32_t) (uintptr_t) writelookup2); + } else { + addbyte(0x48); /*MOV RDX, writelookup2*/ + addbyte(0xb8 | REG_EDX); + addquad((uint64_t) writelookup2); + addbyte(0x48); /*MOV RSI, [RDX+RSI*8]*/ + addbyte(0x8b); + addbyte(0x34); + addbyte(0xf2); + } + addbyte(0x75); /*JNE slowpath*/ + addbyte(3 + 2 + ((host_reg & 8) ? 5 : 4) + 2); + addbyte(0x83); /*CMP ESI, -1*/ + addbyte(0xf8 | REG_ESI); + addbyte(-1); + addbyte(0x74); /*JE slowpath*/ + addbyte(((host_reg & 8) ? 5 : 4) + 2); + if (host_reg & 8) { + addbyte(0x66); /*MOV [RDI+RSI],host_reg*/ + addbyte(0x44); + addbyte(0x89); + addbyte(0x04 | ((host_reg & 7) << 3)); + addbyte(REG_EDI | (REG_ESI << 3)); + } else { + addbyte(0x66); /*MOV [RDI+RSI],host_reg*/ + addbyte(0x89); + addbyte(0x04 | (host_reg << 3)); + addbyte(REG_EDI | (REG_ESI << 3)); + } + addbyte(0xeb); /*JMP done*/ + if (host_reg & 8) { + addbyte(2 + 2 + 3 + 12); + } else { + addbyte(2 + 2 + 2 + 12); + } + /*slowpath:*/ + load_param_2_reg_32(host_reg); + addbyte(0x01); /*ADD EBX,EAX*/ + addbyte(0xc3); + load_param_1_reg_32(REG_EBX); + call_long((uintptr_t) writememwl); + /*done:*/ +} +static __inline void +MEM_STORE_ADDR_EA_L_NO_ABRT(x86seg *seg, int host_reg) +{ + if ((seg == &cpu_state.seg_ds && codegen_flat_ds && !(cpu_cur_status & CPU_STATUS_NOTFLATDS)) || (seg == &cpu_state.seg_ss && codegen_flat_ss && !(cpu_cur_status & CPU_STATUS_NOTFLATSS))) { + addbyte(0x31); /*XOR EBX, EBX*/ + addbyte(0xdb); + } else if (IS_32_ADDR(&seg->base)) { + addbyte(0x8b); /*MOVL EBX, seg->base*/ + addbyte(0x1c); + addbyte(0x25); + addlong((uint32_t) (uintptr_t) &seg->base); + } else { + addbyte(0x48); /*MOV RSI, &seg->base*/ + addbyte(0xb8 | REG_ESI); + addquad((uint64_t) &seg->base); + addbyte(0x8b); /*MOV EBX, [RSI]*/ + addbyte(0x1e); + } + addbyte(0x67); /*LEA ESI, (EAX,EBX)*/ + addbyte(0x8d); + addbyte(0x34); + addbyte(0x18); + addbyte(0x89); /*MOV EDI, ESI*/ + addbyte(0xf7); + addbyte(0xc1); /*SHR ESI, 12*/ + addbyte(0xe8 | REG_ESI); + addbyte(12); + addbyte(0xf7); /*TEST EDI, 3*/ + addbyte(0xc7); + addlong(3); + if (IS_32_ADDR(writelookup2)) { + addbyte(0x67); /*MOV RSI, writelookup2[ESI*8]*/ + addbyte(0x48); + addbyte(0x8b); + addbyte(0x34); + addbyte(0xf5); + addlong((uint32_t) (uintptr_t) writelookup2); + } else { + addbyte(0x48); /*MOV RDX, writelookup2*/ + addbyte(0xb8 | REG_EDX); + addquad((uint64_t) writelookup2); + addbyte(0x48); /*MOV RSI, [RDX+RSI*8]*/ + addbyte(0x8b); + addbyte(0x34); + addbyte(0xf2); + } + addbyte(0x75); /*JNE slowpath*/ + addbyte(3 + 2 + ((host_reg & 8) ? 4 : 3) + 2); + addbyte(0x83); /*CMP ESI, -1*/ + addbyte(0xf8 | REG_ESI); + addbyte(-1); + addbyte(0x74); /*JE slowpath*/ + addbyte(((host_reg & 8) ? 4 : 3) + 2); + if (host_reg & 8) { + addbyte(0x44); /*MOV [RDI+RSI],host_reg*/ + addbyte(0x89); + addbyte(0x04 | ((host_reg & 7) << 3)); + addbyte(REG_EDI | (REG_ESI << 3)); + } else { + addbyte(0x89); /*MOV [RDI+RSI],host_reg*/ + addbyte(0x04 | (host_reg << 3)); + addbyte(REG_EDI | (REG_ESI << 3)); + } + addbyte(0xeb); /*JMP done*/ + if (host_reg & 8) { + addbyte(2 + 2 + 3 + 12); + } else { + addbyte(2 + 2 + 2 + 12); + } + /*slowpath:*/ + load_param_2_reg_32(host_reg); + addbyte(0x01); /*ADD EBX,EAX*/ + addbyte(0xc3); + load_param_1_reg_32(REG_EBX); + call_long((uintptr_t) writememll); + /*done:*/ } -static inline void MEM_STORE_ADDR_EA_B_NO_ABRT(x86seg *seg, int host_reg) +static __inline void +LOAD_SEG(int host_reg, void *seg) { - if (host_reg & 0x10) - { - /*Handle high byte of register*/ - if (host_reg & 8) - { - addbyte(0x45); /*MOVL R8, host_reg*/ - addbyte(0x89); - addbyte(0xc0 | ((host_reg & 7) << 3)); - } - else - { - addbyte(0x41); /*MOVL R8, host_reg*/ - addbyte(0x89); - addbyte(0xc0 | ((host_reg & 7) << 3)); - } - addbyte(0x66); /*SHR R8, 8*/ - addbyte(0x41); - addbyte(0xc1); - addbyte(0xe8); - addbyte(8); - host_reg = 8; - } - if ((seg == &cpu_state.seg_ds && codegen_flat_ds && !(cpu_cur_status & CPU_STATUS_NOTFLATDS)) || (seg == &cpu_state.seg_ss && codegen_flat_ss && !(cpu_cur_status & CPU_STATUS_NOTFLATSS))) - { - addbyte(0x31); /*XOR EBX, EBX*/ - addbyte(0xdb); - } - else if (IS_32_ADDR(&seg->base)) - { - addbyte(0x8b); /*MOVL EBX, seg->base*/ - addbyte(0x1c); - addbyte(0x25); - addlong((uint32_t)(uintptr_t)&seg->base); - } - else - { - addbyte(0x48); /*MOV RSI, &seg->base*/ - addbyte(0xb8 | REG_ESI); - addquad((uint64_t)&seg->base); - addbyte(0x8b); /*MOV EBX, [RSI]*/ - addbyte(0x1e); - } - addbyte(0x67); /*LEA ESI, (EAX,EBX)*/ - addbyte(0x8d); - addbyte(0x34); - addbyte(0x18); - addbyte(0x89); /*MOV EDI, ESI*/ - addbyte(0xf7); - addbyte(0xc1); /*SHR ESI, 12*/ - addbyte(0xe8 | REG_ESI); - addbyte(12); - if (IS_32_ADDR(writelookup2)) - { - addbyte(0x67); /*MOV RSI, writelookup2[ESI*8]*/ - addbyte(0x48); - addbyte(0x8b); - addbyte(0x34); - addbyte(0xf5); - addlong((uint32_t)(uintptr_t)writelookup2); - } - else - { - addbyte(0x48); /*MOV RDX, writelookup2*/ - addbyte(0xb8 | REG_EDX); - addquad((uint64_t)writelookup2); - addbyte(0x48); /*MOV RSI, [RDX+RSI*8]*/ - addbyte(0x8b); - addbyte(0x34); - addbyte(0xf2); - } - addbyte(0x83); /*CMP ESI, -1*/ - addbyte(0xf8 | REG_ESI); - addbyte(-1); - addbyte(0x74); /*JE slowpath*/ - addbyte(((host_reg & 8) ? 4:3)+2); - if (host_reg & 8) - { - addbyte(0x44); /*MOV [RDI+RSI],host_reg*/ - addbyte(0x88); - addbyte(0x04 | ((host_reg & 7) << 3)); - addbyte(REG_EDI | (REG_ESI << 3)); - } - else - { - addbyte(0x88); /*MOV [RDI+RSI],host_reg*/ - addbyte(0x04 | (host_reg << 3)); - addbyte(REG_EDI | (REG_ESI << 3)); - } - addbyte(0xeb); /*JMP done*/ - if (host_reg & 8) { - addbyte(2+2+3+12); - } else { - addbyte(2+2+2+12); - } - /*slowpath:*/ - load_param_2_reg_32(host_reg); - addbyte(0x01); /*ADD EBX,EAX*/ - addbyte(0xc3); - load_param_1_reg_32(REG_EBX); - call_long((uintptr_t)writemembl); - /*done:*/ -} -static inline void MEM_STORE_ADDR_EA_W_NO_ABRT(x86seg *seg, int host_reg) -{ - if ((seg == &cpu_state.seg_ds && codegen_flat_ds && !(cpu_cur_status & CPU_STATUS_NOTFLATDS)) || (seg == &cpu_state.seg_ss && codegen_flat_ss && !(cpu_cur_status & CPU_STATUS_NOTFLATSS))) - { - addbyte(0x31); /*XOR EBX, EBX*/ - addbyte(0xdb); - } - else if (IS_32_ADDR(&seg->base)) - { - addbyte(0x8b); /*MOVL EBX, seg->base*/ - addbyte(0x1c); - addbyte(0x25); - addlong((uint32_t)(uintptr_t)&seg->base); - } - else - { - addbyte(0x48); /*MOV RSI, &seg->base*/ - addbyte(0xb8 | REG_ESI); - addquad((uint64_t)&seg->base); - addbyte(0x8b); /*MOV EBX, [RSI]*/ - addbyte(0x1e); - } - addbyte(0x67); /*LEA ESI, (EAX,EBX)*/ - addbyte(0x8d); - addbyte(0x34); - addbyte(0x18); - addbyte(0x89); /*MOV EDI, ESI*/ - addbyte(0xf7); - addbyte(0xc1); /*SHR ESI, 12*/ - addbyte(0xe8 | REG_ESI); - addbyte(12); - addbyte(0xf7); /*TEST EDI, 1*/ - addbyte(0xc7); - addlong(1); - if (IS_32_ADDR(writelookup2)) - { - addbyte(0x67); /*MOV RSI, writelookup2[ESI*8]*/ - addbyte(0x48); - addbyte(0x8b); - addbyte(0x34); - addbyte(0xf5); - addlong((uint32_t)(uintptr_t)writelookup2); - } - else - { - addbyte(0x48); /*MOV RDX, writelookup2*/ - addbyte(0xb8 | REG_EDX); - addquad((uint64_t)writelookup2); - addbyte(0x48); /*MOV RSI, [RDX+RSI*8]*/ - addbyte(0x8b); - addbyte(0x34); - addbyte(0xf2); - } - addbyte(0x75); /*JNE slowpath*/ - addbyte(3+2+((host_reg & 8) ? 5:4)+2); - addbyte(0x83); /*CMP ESI, -1*/ - addbyte(0xf8 | REG_ESI); - addbyte(-1); - addbyte(0x74); /*JE slowpath*/ - addbyte(((host_reg & 8) ? 5:4)+2); - if (host_reg & 8) - { - addbyte(0x66); /*MOV [RDI+RSI],host_reg*/ - addbyte(0x44); - addbyte(0x89); - addbyte(0x04 | ((host_reg & 7) << 3)); - addbyte(REG_EDI | (REG_ESI << 3)); - } - else - { - addbyte(0x66); /*MOV [RDI+RSI],host_reg*/ - addbyte(0x89); - addbyte(0x04 | (host_reg << 3)); - addbyte(REG_EDI | (REG_ESI << 3)); - } - addbyte(0xeb); /*JMP done*/ - if (host_reg & 8) { - addbyte(2+2+3+12); - } else { - addbyte(2+2+2+12); - } - /*slowpath:*/ - load_param_2_reg_32(host_reg); - addbyte(0x01); /*ADD EBX,EAX*/ - addbyte(0xc3); - load_param_1_reg_32(REG_EBX); - call_long((uintptr_t)writememwl); - /*done:*/ -} -static inline void MEM_STORE_ADDR_EA_L_NO_ABRT(x86seg *seg, int host_reg) -{ - if ((seg == &cpu_state.seg_ds && codegen_flat_ds && !(cpu_cur_status & CPU_STATUS_NOTFLATDS)) || (seg == &cpu_state.seg_ss && codegen_flat_ss && !(cpu_cur_status & CPU_STATUS_NOTFLATSS))) - { - addbyte(0x31); /*XOR EBX, EBX*/ - addbyte(0xdb); - } - else if (IS_32_ADDR(&seg->base)) - { - addbyte(0x8b); /*MOVL EBX, seg->base*/ - addbyte(0x1c); - addbyte(0x25); - addlong((uint32_t)(uintptr_t)&seg->base); - } - else - { - addbyte(0x48); /*MOV RSI, &seg->base*/ - addbyte(0xb8 | REG_ESI); - addquad((uint64_t)&seg->base); - addbyte(0x8b); /*MOV EBX, [RSI]*/ - addbyte(0x1e); - } - addbyte(0x67); /*LEA ESI, (EAX,EBX)*/ - addbyte(0x8d); - addbyte(0x34); - addbyte(0x18); - addbyte(0x89); /*MOV EDI, ESI*/ - addbyte(0xf7); - addbyte(0xc1); /*SHR ESI, 12*/ - addbyte(0xe8 | REG_ESI); - addbyte(12); - addbyte(0xf7); /*TEST EDI, 3*/ - addbyte(0xc7); - addlong(3); - if (IS_32_ADDR(writelookup2)) - { - addbyte(0x67); /*MOV RSI, writelookup2[ESI*8]*/ - addbyte(0x48); - addbyte(0x8b); - addbyte(0x34); - addbyte(0xf5); - addlong((uint32_t)(uintptr_t)writelookup2); - } - else - { - addbyte(0x48); /*MOV RDX, writelookup2*/ - addbyte(0xb8 | REG_EDX); - addquad((uint64_t)writelookup2); - addbyte(0x48); /*MOV RSI, [RDX+RSI*8]*/ - addbyte(0x8b); - addbyte(0x34); - addbyte(0xf2); - } - addbyte(0x75); /*JNE slowpath*/ - addbyte(3+2+((host_reg & 8) ? 4:3)+2); - addbyte(0x83); /*CMP ESI, -1*/ - addbyte(0xf8 | REG_ESI); - addbyte(-1); - addbyte(0x74); /*JE slowpath*/ - addbyte(((host_reg & 8) ? 4:3)+2); - if (host_reg & 8) - { - addbyte(0x44); /*MOV [RDI+RSI],host_reg*/ - addbyte(0x89); - addbyte(0x04 | ((host_reg & 7) << 3)); - addbyte(REG_EDI | (REG_ESI << 3)); - } - else - { - addbyte(0x89); /*MOV [RDI+RSI],host_reg*/ - addbyte(0x04 | (host_reg << 3)); - addbyte(REG_EDI | (REG_ESI << 3)); - } - addbyte(0xeb); /*JMP done*/ - if (host_reg & 8) { - addbyte(2+2+3+12); - } else { - addbyte(2+2+2+12); - } - /*slowpath:*/ - load_param_2_reg_32(host_reg); - addbyte(0x01); /*ADD EBX,EAX*/ - addbyte(0xc3); - load_param_1_reg_32(REG_EBX); - call_long((uintptr_t)writememll); - /*done:*/ -} - -static inline void LOAD_SEG(int host_reg, void *seg) -{ - load_param_2_64(&codeblock[block_current], (uint64_t)seg); - load_param_1_reg_32(host_reg); - CALL_FUNC((uintptr_t)loadseg); - addbyte(0x80); /*CMP abrt, 0*/ - addbyte(0x7d); - addbyte((uint8_t)cpu_state_offset(abrt)); - addbyte(0); - addbyte(0x0f); /*JNE end*/ - addbyte(0x85); - addlong(BLOCK_EXIT_OFFSET - (block_pos + 4)); + load_param_2_64(&codeblock[block_current], (uint64_t) seg); + load_param_1_reg_32(host_reg); + CALL_FUNC((uintptr_t) loadseg); + addbyte(0x80); /*CMP abrt, 0*/ + addbyte(0x7d); + addbyte((uint8_t) cpu_state_offset(abrt)); + addbyte(0); + addbyte(0x0f); /*JNE end*/ + addbyte(0x85); + addlong(BLOCK_EXIT_OFFSET - (block_pos + 4)); } diff --git a/src/codegen/codegen_ops_x86.h b/src/codegen/codegen_ops_x86.h index c4a9cbd47..410ce8e17 100644 --- a/src/codegen/codegen_ops_x86.h +++ b/src/codegen/codegen_ops_x86.h @@ -4,46 +4,46 @@ ESI, EDI - work registers EBP - points at emulated register array */ -#define HOST_REG_START 1 -#define HOST_REG_END 4 +#define HOST_REG_START 1 +#define HOST_REG_END 4 #define HOST_REG_XMM_START 0 -#define HOST_REG_XMM_END 7 -static inline int find_host_reg() +#define HOST_REG_XMM_END 7 +static __inline int +find_host_reg(void) { - int c; - for (c = HOST_REG_START; c < HOST_REG_END; c++) - { - if (host_reg_mapping[c] == -1) - break; - } - - if (c == NR_HOST_REGS) - fatal("Out of host regs!\n"); - return c; + int c; + for (c = HOST_REG_START; c < HOST_REG_END; c++) { + if (host_reg_mapping[c] == -1) + break; + } + + if (c == NR_HOST_REGS) + fatal("Out of host regs!\n"); + return c; } -static inline int find_host_xmm_reg() +static __inline int +find_host_xmm_reg(void) { - int c; - for (c = HOST_REG_XMM_START; c < HOST_REG_XMM_END; c++) - { - if (host_reg_xmm_mapping[c] == -1) - break; - } - - if (c == HOST_REG_XMM_END) - fatal("Out of host XMM regs!\n"); - return c; + int c; + for (c = HOST_REG_XMM_START; c < HOST_REG_XMM_END; c++) { + if (host_reg_xmm_mapping[c] == -1) + break; + } + + if (c == HOST_REG_XMM_END) + fatal("Out of host XMM regs!\n"); + return c; } #if 0 -static inline void STORE_IMM_ADDR_B(uintptr_t addr, uint8_t val) +static __inline void STORE_IMM_ADDR_B(uintptr_t addr, uint8_t val) { addbyte(0xC6); /*MOVB [addr],val*/ addbyte(0x05); addlong(addr); addbyte(val); } -static inline void STORE_IMM_ADDR_W(uintptr_t addr, uint16_t val) +static __inline void STORE_IMM_ADDR_W(uintptr_t addr, uint16_t val) { addbyte(0x66); /*MOVW [addr],val*/ addbyte(0xC7); @@ -52,2637 +52,2572 @@ static inline void STORE_IMM_ADDR_W(uintptr_t addr, uint16_t val) addword(val); } #endif -static inline void STORE_IMM_ADDR_L(uintptr_t addr, uint32_t val) -{ - if (addr >= (uintptr_t)&cpu_state && addr < ((uintptr_t)&cpu_state)+0x100) - { - addbyte(0xC7); /*MOVL [addr],val*/ - addbyte(0x45); - addbyte(addr - (uint32_t)&cpu_state - 128); - addlong(val); - } - else - { - addbyte(0xC7); /*MOVL [addr],val*/ - addbyte(0x05); - addlong(addr); - addlong(val); - } -} - -static inline void STORE_IMM_REG_B(int reg, uint8_t val) -{ - addbyte(0xC6); /*MOVB [addr],val*/ - addbyte(0x45); - if (reg & 4) - addbyte((uint8_t)cpu_state_offset(regs[reg & 3].b.h)); - else - addbyte((uint8_t)cpu_state_offset(regs[reg & 3].b.l)); - addbyte(val); -} -static inline void STORE_IMM_REG_W(int reg, uint16_t val) -{ - addbyte(0x66); /*MOVW [addr],val*/ - addbyte(0xC7); - addbyte(0x45); - addbyte((uint8_t)cpu_state_offset(regs[reg & 7].w)); - addword(val); -} -static inline void STORE_IMM_REG_L(int reg, uint32_t val) +static __inline void +STORE_IMM_ADDR_L(uintptr_t addr, uint32_t val) { + if (addr >= (uintptr_t) &cpu_state && addr < ((uintptr_t) &cpu_state) + 0x100) { addbyte(0xC7); /*MOVL [addr],val*/ addbyte(0x45); - addbyte((uint8_t)cpu_state_offset(regs[reg & 7].l)); + addbyte(addr - (uint32_t) &cpu_state - 128); addlong(val); + } else { + addbyte(0xC7); /*MOVL [addr],val*/ + addbyte(0x05); + addlong(addr); + addlong(val); + } } -static inline int LOAD_REG_B(int reg) +static __inline void +STORE_IMM_REG_B(int reg, uint8_t val) { - int host_reg = find_host_reg(); - host_reg_mapping[host_reg] = reg; - - addbyte(0x0f); /*MOVZX B[reg],host_reg*/ - addbyte(0xb6); - addbyte(0x45 | (host_reg << 3)); - if (reg & 4) - addbyte((uint8_t)cpu_state_offset(regs[reg & 3].b.h)); - else - addbyte((uint8_t)cpu_state_offset(regs[reg & 3].b.l)); - - return host_reg; + addbyte(0xC6); /*MOVB [addr],val*/ + addbyte(0x45); + if (reg & 4) + addbyte((uint8_t) cpu_state_offset(regs[reg & 3].b.h)); + else + addbyte((uint8_t) cpu_state_offset(regs[reg & 3].b.l)); + addbyte(val); } -static inline int LOAD_REG_W(int reg) +static __inline void +STORE_IMM_REG_W(int reg, uint16_t val) { - int host_reg = find_host_reg(); - host_reg_mapping[host_reg] = reg; - - addbyte(0x0f); /*MOVZX W[reg],host_reg*/ - addbyte(0xb7); - addbyte(0x45 | (host_reg << 3)); - addbyte((uint8_t)cpu_state_offset(regs[reg & 7].w)); - - return host_reg; + addbyte(0x66); /*MOVW [addr],val*/ + addbyte(0xC7); + addbyte(0x45); + addbyte((uint8_t) cpu_state_offset(regs[reg & 7].w)); + addword(val); } -static inline int LOAD_REG_L(int reg) +static __inline void +STORE_IMM_REG_L(int reg, uint32_t val) { - int host_reg = find_host_reg(); - host_reg_mapping[host_reg] = reg; - - addbyte(0x8b); /*MOVL host_reg,[reg]*/ - addbyte(0x45 | (host_reg << 3)); - addbyte((uint8_t)cpu_state_offset(regs[reg & 7].l)); - - return host_reg; + addbyte(0xC7); /*MOVL [addr],val*/ + addbyte(0x45); + addbyte((uint8_t) cpu_state_offset(regs[reg & 7].l)); + addlong(val); } -static inline int LOAD_VAR_W(uintptr_t addr) +static __inline int +LOAD_REG_B(int reg) { - int host_reg = find_host_reg(); - host_reg_mapping[host_reg] = 0; + int host_reg = find_host_reg(); + host_reg_mapping[host_reg] = reg; - addbyte(0x66); /*MOVL host_reg,[reg]*/ - addbyte(0x8b); - addbyte(0x05 | (host_reg << 3)); - addlong((uint32_t)addr); + addbyte(0x0f); /*MOVZX B[reg],host_reg*/ + addbyte(0xb6); + addbyte(0x45 | (host_reg << 3)); + if (reg & 4) + addbyte((uint8_t) cpu_state_offset(regs[reg & 3].b.h)); + else + addbyte((uint8_t) cpu_state_offset(regs[reg & 3].b.l)); - return host_reg; + return host_reg; } -static inline int LOAD_VAR_WL(uintptr_t addr) +static __inline int +LOAD_REG_W(int reg) { - int host_reg = find_host_reg(); - host_reg_mapping[host_reg] = 0; - - addbyte(0x0f); /*MOVZX host_reg, [addr]*/ - addbyte(0xb7); - addbyte(0x05 | (host_reg << 3)); - addlong((uint32_t)addr); - - return host_reg; + int host_reg = find_host_reg(); + host_reg_mapping[host_reg] = reg; + + addbyte(0x0f); /*MOVZX W[reg],host_reg*/ + addbyte(0xb7); + addbyte(0x45 | (host_reg << 3)); + addbyte((uint8_t) cpu_state_offset(regs[reg & 7].w)); + + return host_reg; } -static inline int LOAD_VAR_L(uintptr_t addr) +static __inline int +LOAD_REG_L(int reg) { - int host_reg = find_host_reg(); - host_reg_mapping[host_reg] = 0; + int host_reg = find_host_reg(); + host_reg_mapping[host_reg] = reg; - addbyte(0x8b); /*MOVL host_reg,[reg]*/ - addbyte(0x05 | (host_reg << 3)); - addlong((uint32_t)addr); + addbyte(0x8b); /*MOVL host_reg,[reg]*/ + addbyte(0x45 | (host_reg << 3)); + addbyte((uint8_t) cpu_state_offset(regs[reg & 7].l)); - return host_reg; + return host_reg; } -static inline int LOAD_REG_IMM(uint32_t imm) +static __inline int +LOAD_VAR_W(uintptr_t addr) { - int host_reg = find_host_reg(); - host_reg_mapping[host_reg] = 0; - - addbyte(0xc7); /*MOVL host_reg, imm*/ - addbyte(0xc0 | host_reg); - addlong(imm); - - return host_reg; + int host_reg = find_host_reg(); + host_reg_mapping[host_reg] = 0; + + addbyte(0x66); /*MOVL host_reg,[reg]*/ + addbyte(0x8b); + addbyte(0x05 | (host_reg << 3)); + addlong((uint32_t) addr); + + return host_reg; +} +static __inline int +LOAD_VAR_WL(uintptr_t addr) +{ + int host_reg = find_host_reg(); + host_reg_mapping[host_reg] = 0; + + addbyte(0x0f); /*MOVZX host_reg, [addr]*/ + addbyte(0xb7); + addbyte(0x05 | (host_reg << 3)); + addlong((uint32_t) addr); + + return host_reg; +} +static __inline int +LOAD_VAR_L(uintptr_t addr) +{ + int host_reg = find_host_reg(); + host_reg_mapping[host_reg] = 0; + + addbyte(0x8b); /*MOVL host_reg,[reg]*/ + addbyte(0x05 | (host_reg << 3)); + addlong((uint32_t) addr); + + return host_reg; } -static inline int LOAD_HOST_REG(int host_reg) +static __inline int +LOAD_REG_IMM(uint32_t imm) { - int new_host_reg = find_host_reg(); - host_reg_mapping[new_host_reg] = 0; - - addbyte(0x89); /*MOV new_host_reg, host_reg*/ - addbyte(0xc0 | (host_reg << 3) | new_host_reg); - - return new_host_reg; + int host_reg = find_host_reg(); + host_reg_mapping[host_reg] = 0; + + addbyte(0xc7); /*MOVL host_reg, imm*/ + addbyte(0xc0 | host_reg); + addlong(imm); + + return host_reg; } -static inline void STORE_REG_B_RELEASE(int host_reg) +static __inline int +LOAD_HOST_REG(int host_reg) { - addbyte(0x88); /*MOVB [reg],host_reg*/ - addbyte(0x45 | (host_reg << 3)); - if (host_reg_mapping[host_reg] & 4) - addbyte((uint8_t)cpu_state_offset(regs[host_reg_mapping[host_reg] & 3].b.h)); - else - addbyte((uint8_t)cpu_state_offset(regs[host_reg_mapping[host_reg] & 3].b.l)); - host_reg_mapping[host_reg] = -1; + int new_host_reg = find_host_reg(); + host_reg_mapping[new_host_reg] = 0; + + addbyte(0x89); /*MOV new_host_reg, host_reg*/ + addbyte(0xc0 | (host_reg << 3) | new_host_reg); + + return new_host_reg; } -static inline void STORE_REG_W_RELEASE(int host_reg) + +static __inline void +STORE_REG_B_RELEASE(int host_reg) { - addbyte(0x66); /*MOVW [reg],host_reg*/ + addbyte(0x88); /*MOVB [reg],host_reg*/ + addbyte(0x45 | (host_reg << 3)); + if (host_reg_mapping[host_reg] & 4) + addbyte((uint8_t) cpu_state_offset(regs[host_reg_mapping[host_reg] & 3].b.h)); + else + addbyte((uint8_t) cpu_state_offset(regs[host_reg_mapping[host_reg] & 3].b.l)); + host_reg_mapping[host_reg] = -1; +} +static __inline void +STORE_REG_W_RELEASE(int host_reg) +{ + addbyte(0x66); /*MOVW [reg],host_reg*/ + addbyte(0x89); + addbyte(0x45 | (host_reg << 3)); + addbyte((uint8_t) cpu_state_offset(regs[host_reg_mapping[host_reg]].w)); + host_reg_mapping[host_reg] = -1; +} +static __inline void +STORE_REG_L_RELEASE(int host_reg) +{ + addbyte(0x89); /*MOVL [reg],host_reg*/ + addbyte(0x45 | (host_reg << 3)); + addbyte((uint8_t) cpu_state_offset(regs[host_reg_mapping[host_reg]].l)); + host_reg_mapping[host_reg] = -1; +} + +static __inline void +STORE_REG_TARGET_B_RELEASE(int host_reg, int guest_reg) +{ + addbyte(0x88); /*MOVB [guest_reg],host_reg*/ + addbyte(0x45 | (host_reg << 3)); + if (guest_reg & 4) + addbyte((uint8_t) cpu_state_offset(regs[guest_reg & 3].b.h)); + else + addbyte((uint8_t) cpu_state_offset(regs[guest_reg & 3].b.l)); + host_reg_mapping[host_reg] = -1; +} +static __inline void +STORE_REG_TARGET_W_RELEASE(int host_reg, int guest_reg) +{ + addbyte(0x66); /*MOVW [guest_reg],host_reg*/ + addbyte(0x89); + addbyte(0x45 | (host_reg << 3)); + addbyte((uint8_t) cpu_state_offset(regs[guest_reg & 7].w)); + host_reg_mapping[host_reg] = -1; +} +static __inline void +STORE_REG_TARGET_L_RELEASE(int host_reg, int guest_reg) +{ + addbyte(0x89); /*MOVL [guest_reg],host_reg*/ + addbyte(0x45 | (host_reg << 3)); + addbyte((uint8_t) cpu_state_offset(regs[guest_reg & 7].l)); + host_reg_mapping[host_reg] = -1; +} + +static __inline void +RELEASE_REG(int host_reg) +{ + host_reg_mapping[host_reg] = -1; +} + +static __inline void +STORE_HOST_REG_ADDR_W(uintptr_t addr, int host_reg) +{ + if (addr >= (uintptr_t) &cpu_state && addr < ((uintptr_t) &cpu_state) + 0x100) { + addbyte(0x66); /*MOVW [addr],host_reg*/ addbyte(0x89); addbyte(0x45 | (host_reg << 3)); - addbyte((uint8_t)cpu_state_offset(regs[host_reg_mapping[host_reg]].w)); - host_reg_mapping[host_reg] = -1; + addbyte((uint32_t) addr - (uint32_t) &cpu_state - 128); + } else { + addbyte(0x66); /*MOVL [reg],host_reg*/ + addbyte(0x89); + addbyte(0x05 | (host_reg << 3)); + addlong(addr); + } } -static inline void STORE_REG_L_RELEASE(int host_reg) +static __inline void +STORE_HOST_REG_ADDR(uintptr_t addr, int host_reg) { + if (addr >= (uintptr_t) &cpu_state && addr < ((uintptr_t) &cpu_state) + 0x100) { + addbyte(0x89); /*MOVL [addr],host_reg*/ + addbyte(0x45 | (host_reg << 3)); + addbyte((uint32_t) addr - (uint32_t) &cpu_state - 128); + } else { addbyte(0x89); /*MOVL [reg],host_reg*/ - addbyte(0x45 | (host_reg << 3)); - addbyte((uint8_t)cpu_state_offset(regs[host_reg_mapping[host_reg]].l)); - host_reg_mapping[host_reg] = -1; -} - -static inline void STORE_REG_TARGET_B_RELEASE(int host_reg, int guest_reg) -{ - addbyte(0x88); /*MOVB [guest_reg],host_reg*/ - addbyte(0x45 | (host_reg << 3)); - if (guest_reg & 4) - addbyte((uint8_t)cpu_state_offset(regs[guest_reg & 3].b.h)); - else - addbyte((uint8_t)cpu_state_offset(regs[guest_reg & 3].b.l)); - host_reg_mapping[host_reg] = -1; -} -static inline void STORE_REG_TARGET_W_RELEASE(int host_reg, int guest_reg) -{ - addbyte(0x66); /*MOVW [guest_reg],host_reg*/ - addbyte(0x89); - addbyte(0x45 | (host_reg << 3)); - addbyte((uint8_t)cpu_state_offset(regs[guest_reg & 7].w)); - host_reg_mapping[host_reg] = -1; -} -static inline void STORE_REG_TARGET_L_RELEASE(int host_reg, int guest_reg) -{ - addbyte(0x89); /*MOVL [guest_reg],host_reg*/ - addbyte(0x45 | (host_reg << 3)); - addbyte((uint8_t)cpu_state_offset(regs[guest_reg & 7].l)); - host_reg_mapping[host_reg] = -1; -} - -static inline void RELEASE_REG(int host_reg) -{ - host_reg_mapping[host_reg] = -1; -} - -static inline void STORE_HOST_REG_ADDR_W(uintptr_t addr, int host_reg) -{ - if (addr >= (uintptr_t)&cpu_state && addr < ((uintptr_t)&cpu_state)+0x100) - { - addbyte(0x66); /*MOVW [addr],host_reg*/ - addbyte(0x89); - addbyte(0x45 | (host_reg << 3)); - addbyte((uint32_t)addr - (uint32_t)&cpu_state - 128); - } - else - { - addbyte(0x66); /*MOVL [reg],host_reg*/ - addbyte(0x89); - addbyte(0x05 | (host_reg << 3)); - addlong(addr); - } -} -static inline void STORE_HOST_REG_ADDR(uintptr_t addr, int host_reg) -{ - if (addr >= (uintptr_t)&cpu_state && addr < ((uintptr_t)&cpu_state)+0x100) - { - addbyte(0x89); /*MOVL [addr],host_reg*/ - addbyte(0x45 | (host_reg << 3)); - addbyte((uint32_t)addr - (uint32_t)&cpu_state - 128); - } - else - { - addbyte(0x89); /*MOVL [reg],host_reg*/ - addbyte(0x05 | (host_reg << 3)); - addlong(addr); - } + addbyte(0x05 | (host_reg << 3)); + addlong(addr); + } } #define STORE_HOST_REG_ADDR_BL STORE_HOST_REG_ADDR #define STORE_HOST_REG_ADDR_WL STORE_HOST_REG_ADDR -static inline void ADD_HOST_REG_B(int dst_reg, int src_reg) +static __inline void +ADD_HOST_REG_B(int dst_reg, int src_reg) { - addbyte(0x00); /*ADDB dst_reg, src_reg*/ - addbyte(0xc0 | dst_reg | (src_reg << 3)); + addbyte(0x00); /*ADDB dst_reg, src_reg*/ + addbyte(0xc0 | dst_reg | (src_reg << 3)); } -static inline void ADD_HOST_REG_W(int dst_reg, int src_reg) +static __inline void +ADD_HOST_REG_W(int dst_reg, int src_reg) { - addbyte(0x66); /*ADDW dst_reg, src_reg*/ - addbyte(0x01); - addbyte(0xc0 | dst_reg | (src_reg << 3)); + addbyte(0x66); /*ADDW dst_reg, src_reg*/ + addbyte(0x01); + addbyte(0xc0 | dst_reg | (src_reg << 3)); } -static inline void ADD_HOST_REG_L(int dst_reg, int src_reg) +static __inline void +ADD_HOST_REG_L(int dst_reg, int src_reg) { - addbyte(0x01); /*ADDL dst_reg, src_reg*/ - addbyte(0xc0 | dst_reg | (src_reg << 3)); + addbyte(0x01); /*ADDL dst_reg, src_reg*/ + addbyte(0xc0 | dst_reg | (src_reg << 3)); } -static inline void ADD_HOST_REG_IMM_B(int host_reg, uint8_t imm) +static __inline void +ADD_HOST_REG_IMM_B(int host_reg, uint8_t imm) { - addbyte(0x80); /*ADDB host_reg, imm*/ + addbyte(0x80); /*ADDB host_reg, imm*/ + addbyte(0xC0 | host_reg); + addbyte(imm); +} +static __inline void +ADD_HOST_REG_IMM_W(int host_reg, uint16_t imm) +{ + if (imm < 0x80 || imm >= 0xff80) { + addbyte(0x66); /*ADDW host_reg, imm*/ + addbyte(0x83); addbyte(0xC0 | host_reg); - addbyte(imm); + addbyte(imm & 0xff); + } else { + addbyte(0x66); /*ADDW host_reg, imm*/ + addbyte(0x81); + addbyte(0xC0 | host_reg); + addword(imm); + } } -static inline void ADD_HOST_REG_IMM_W(int host_reg, uint16_t imm) +static __inline void +ADD_HOST_REG_IMM(int host_reg, uint32_t imm) { - if (imm < 0x80 || imm >= 0xff80) - { - addbyte(0x66); /*ADDW host_reg, imm*/ - addbyte(0x83); - addbyte(0xC0 | host_reg); - addbyte(imm & 0xff); - } - else - { - addbyte(0x66); /*ADDW host_reg, imm*/ - addbyte(0x81); - addbyte(0xC0 | host_reg); - addword(imm); - } -} -static inline void ADD_HOST_REG_IMM(int host_reg, uint32_t imm) -{ - if (imm < 0x80 || imm >= 0xffffff80) - { - addbyte(0x83); /*ADDL host_reg, imm*/ - addbyte(0xC0 | host_reg); - addbyte(imm & 0xff); - } - else - { - addbyte(0x81); /*ADDL host_reg, imm*/ - addbyte(0xC0 | host_reg); - addlong(imm); - } + if (imm < 0x80 || imm >= 0xffffff80) { + addbyte(0x83); /*ADDL host_reg, imm*/ + addbyte(0xC0 | host_reg); + addbyte(imm & 0xff); + } else { + addbyte(0x81); /*ADDL host_reg, imm*/ + addbyte(0xC0 | host_reg); + addlong(imm); + } } #define AND_HOST_REG_B AND_HOST_REG_L #define AND_HOST_REG_W AND_HOST_REG_L -static inline void AND_HOST_REG_L(int dst_reg, int src_reg) +static __inline void +AND_HOST_REG_L(int dst_reg, int src_reg) { - addbyte(0x21); /*ANDL dst_reg, src_reg*/ - addbyte(0xc0 | dst_reg | (src_reg << 3)); + addbyte(0x21); /*ANDL dst_reg, src_reg*/ + addbyte(0xc0 | dst_reg | (src_reg << 3)); } -static inline void AND_HOST_REG_IMM(int host_reg, uint32_t imm) +static __inline void +AND_HOST_REG_IMM(int host_reg, uint32_t imm) { - if (imm < 0x80 || imm >= 0xffffff80) - { - addbyte(0x83); /*ANDL host_reg, imm*/ - addbyte(0xE0 | host_reg); - addbyte(imm & 0xff); - } - else - { - addbyte(0x81); /*ANDL host_reg, imm*/ - addbyte(0xE0 | host_reg); - addlong(imm); - } + if (imm < 0x80 || imm >= 0xffffff80) { + addbyte(0x83); /*ANDL host_reg, imm*/ + addbyte(0xE0 | host_reg); + addbyte(imm & 0xff); + } else { + addbyte(0x81); /*ANDL host_reg, imm*/ + addbyte(0xE0 | host_reg); + addlong(imm); + } } -static inline int TEST_HOST_REG_B(int dst_reg, int src_reg) +static __inline int +TEST_HOST_REG_B(int dst_reg, int src_reg) { - AND_HOST_REG_B(dst_reg, src_reg); - - return dst_reg; + AND_HOST_REG_B(dst_reg, src_reg); + + return dst_reg; } -static inline int TEST_HOST_REG_W(int dst_reg, int src_reg) +static __inline int +TEST_HOST_REG_W(int dst_reg, int src_reg) { - AND_HOST_REG_W(dst_reg, src_reg); - - return dst_reg; + AND_HOST_REG_W(dst_reg, src_reg); + + return dst_reg; } -static inline int TEST_HOST_REG_L(int dst_reg, int src_reg) +static __inline int +TEST_HOST_REG_L(int dst_reg, int src_reg) { - AND_HOST_REG_L(dst_reg, src_reg); - - return dst_reg; + AND_HOST_REG_L(dst_reg, src_reg); + + return dst_reg; } -static inline int TEST_HOST_REG_IMM(int host_reg, uint32_t imm) +static __inline int +TEST_HOST_REG_IMM(int host_reg, uint32_t imm) { - AND_HOST_REG_IMM(host_reg, imm); - - return host_reg; + AND_HOST_REG_IMM(host_reg, imm); + + return host_reg; } #define OR_HOST_REG_B OR_HOST_REG_L #define OR_HOST_REG_W OR_HOST_REG_L -static inline void OR_HOST_REG_L(int dst_reg, int src_reg) +static __inline void +OR_HOST_REG_L(int dst_reg, int src_reg) { - addbyte(0x09); /*ORL dst_reg, src_reg*/ - addbyte(0xc0 | dst_reg | (src_reg << 3)); + addbyte(0x09); /*ORL dst_reg, src_reg*/ + addbyte(0xc0 | dst_reg | (src_reg << 3)); } -static inline void OR_HOST_REG_IMM(int host_reg, uint32_t imm) +static __inline void +OR_HOST_REG_IMM(int host_reg, uint32_t imm) { - if (imm < 0x80 || imm >= 0xffffff80) - { - addbyte(0x83); /*ORL host_reg, imm*/ - addbyte(0xC8 | host_reg); - addbyte(imm & 0xff); - } - else - { - addbyte(0x81); /*ORL host_reg, imm*/ - addbyte(0xC8 | host_reg); - addlong(imm); - } + if (imm < 0x80 || imm >= 0xffffff80) { + addbyte(0x83); /*ORL host_reg, imm*/ + addbyte(0xC8 | host_reg); + addbyte(imm & 0xff); + } else { + addbyte(0x81); /*ORL host_reg, imm*/ + addbyte(0xC8 | host_reg); + addlong(imm); + } } -static inline void NEG_HOST_REG_B(int reg) +static __inline void +NEG_HOST_REG_B(int reg) { - addbyte(0xf6); - addbyte(0xd8 | reg); + addbyte(0xf6); + addbyte(0xd8 | reg); } -static inline void NEG_HOST_REG_W(int reg) +static __inline void +NEG_HOST_REG_W(int reg) { - addbyte(0x66); - addbyte(0xf7); - addbyte(0xd8 | reg); + addbyte(0x66); + addbyte(0xf7); + addbyte(0xd8 | reg); } -static inline void NEG_HOST_REG_L(int reg) +static __inline void +NEG_HOST_REG_L(int reg) { - addbyte(0xf7); - addbyte(0xd8 | reg); + addbyte(0xf7); + addbyte(0xd8 | reg); } -static inline void SUB_HOST_REG_B(int dst_reg, int src_reg) +static __inline void +SUB_HOST_REG_B(int dst_reg, int src_reg) { - addbyte(0x28); /*SUBB dst_reg, src_reg*/ - addbyte(0xc0 | dst_reg | (src_reg << 3)); + addbyte(0x28); /*SUBB dst_reg, src_reg*/ + addbyte(0xc0 | dst_reg | (src_reg << 3)); } -static inline void SUB_HOST_REG_W(int dst_reg, int src_reg) +static __inline void +SUB_HOST_REG_W(int dst_reg, int src_reg) { - addbyte(0x66); /*SUBW dst_reg, src_reg*/ - addbyte(0x29); - addbyte(0xc0 | dst_reg | (src_reg << 3)); + addbyte(0x66); /*SUBW dst_reg, src_reg*/ + addbyte(0x29); + addbyte(0xc0 | dst_reg | (src_reg << 3)); } -static inline void SUB_HOST_REG_L(int dst_reg, int src_reg) +static __inline void +SUB_HOST_REG_L(int dst_reg, int src_reg) { - addbyte(0x29); /*SUBL dst_reg, src_reg*/ - addbyte(0xc0 | dst_reg | (src_reg << 3)); + addbyte(0x29); /*SUBL dst_reg, src_reg*/ + addbyte(0xc0 | dst_reg | (src_reg << 3)); } -static inline void SUB_HOST_REG_IMM_B(int host_reg, uint8_t imm) +static __inline void +SUB_HOST_REG_IMM_B(int host_reg, uint8_t imm) { - addbyte(0x80); /*SUBB host_reg, imm*/ + addbyte(0x80); /*SUBB host_reg, imm*/ + addbyte(0xE8 | host_reg); + addbyte(imm); +} +static __inline void +SUB_HOST_REG_IMM_W(int host_reg, uint16_t imm) +{ + if (imm < 0x80 || imm >= 0xff80) { + addbyte(0x66); /*SUBW host_reg, imm*/ + addbyte(0x83); + addbyte(0xE8 | host_reg); + addbyte(imm & 0xff); + } else { + addbyte(0x66); /*SUBW host_reg, imm*/ + addbyte(0x81); + addbyte(0xE8 | host_reg); + addword(imm); + } +} +static __inline void +SUB_HOST_REG_IMM(int host_reg, uint32_t imm) +{ + if (imm < 0x80 || imm >= 0xffffff80) { + addbyte(0x83); /*SUBL host_reg, imm*/ addbyte(0xE8 | host_reg); addbyte(imm); -} -static inline void SUB_HOST_REG_IMM_W(int host_reg, uint16_t imm) -{ - if (imm < 0x80 || imm >= 0xff80) - { - addbyte(0x66); /*SUBW host_reg, imm*/ - addbyte(0x83); - addbyte(0xE8 | host_reg); - addbyte(imm & 0xff); - } - else - { - addbyte(0x66); /*SUBW host_reg, imm*/ - addbyte(0x81); - addbyte(0xE8 | host_reg); - addword(imm); - } -} -static inline void SUB_HOST_REG_IMM(int host_reg, uint32_t imm) -{ - if (imm < 0x80 || imm >= 0xffffff80) - { - addbyte(0x83); /*SUBL host_reg, imm*/ - addbyte(0xE8 | host_reg); - addbyte(imm); - } - else - { - addbyte(0x81); /*SUBL host_reg, imm*/ - addbyte(0xE8 | host_reg); - addlong(imm); - } + } else { + addbyte(0x81); /*SUBL host_reg, imm*/ + addbyte(0xE8 | host_reg); + addlong(imm); + } } -static inline void INC_HOST_REG_W(int host_reg) +static __inline void +INC_HOST_REG_W(int host_reg) { - addbyte(0x66); /*INCW host_reg*/ - addbyte(0x40 | host_reg); + addbyte(0x66); /*INCW host_reg*/ + addbyte(0x40 | host_reg); } -static inline void INC_HOST_REG(int host_reg) +static __inline void +INC_HOST_REG(int host_reg) { - addbyte(0x40 | host_reg); /*DECL host_reg*/ + addbyte(0x40 | host_reg); /*DECL host_reg*/ } -static inline void DEC_HOST_REG_W(int host_reg) +static __inline void +DEC_HOST_REG_W(int host_reg) { - addbyte(0x66); /*DECW host_reg*/ - addbyte(0x48 | host_reg); + addbyte(0x66); /*DECW host_reg*/ + addbyte(0x48 | host_reg); } -static inline void DEC_HOST_REG(int host_reg) +static __inline void +DEC_HOST_REG(int host_reg) { - addbyte(0x48 | host_reg); /*DECL host_reg*/ + addbyte(0x48 | host_reg); /*DECL host_reg*/ } -static inline int CMP_HOST_REG_B(int dst_reg, int src_reg) +static __inline int +CMP_HOST_REG_B(int dst_reg, int src_reg) { - SUB_HOST_REG_B(dst_reg, src_reg); - - return dst_reg; + SUB_HOST_REG_B(dst_reg, src_reg); + + return dst_reg; } -static inline int CMP_HOST_REG_W(int dst_reg, int src_reg) +static __inline int +CMP_HOST_REG_W(int dst_reg, int src_reg) { - SUB_HOST_REG_W(dst_reg, src_reg); - - return dst_reg; + SUB_HOST_REG_W(dst_reg, src_reg); + + return dst_reg; } -static inline int CMP_HOST_REG_L(int dst_reg, int src_reg) +static __inline int +CMP_HOST_REG_L(int dst_reg, int src_reg) { - SUB_HOST_REG_L(dst_reg, src_reg); - - return dst_reg; + SUB_HOST_REG_L(dst_reg, src_reg); + + return dst_reg; } -static inline int CMP_HOST_REG_IMM_B(int host_reg, uint8_t imm) +static __inline int +CMP_HOST_REG_IMM_B(int host_reg, uint8_t imm) { - SUB_HOST_REG_IMM_B(host_reg, imm); - - return host_reg; + SUB_HOST_REG_IMM_B(host_reg, imm); + + return host_reg; } -static inline int CMP_HOST_REG_IMM_W(int host_reg, uint16_t imm) +static __inline int +CMP_HOST_REG_IMM_W(int host_reg, uint16_t imm) { - SUB_HOST_REG_IMM_W(host_reg, imm); - - return host_reg; + SUB_HOST_REG_IMM_W(host_reg, imm); + + return host_reg; } -static inline int CMP_HOST_REG_IMM_L(int host_reg, uint32_t imm) +static __inline int +CMP_HOST_REG_IMM_L(int host_reg, uint32_t imm) { - SUB_HOST_REG_IMM(host_reg, imm); - - return host_reg; + SUB_HOST_REG_IMM(host_reg, imm); + + return host_reg; } #define XOR_HOST_REG_B XOR_HOST_REG_L #define XOR_HOST_REG_W XOR_HOST_REG_L -static inline void XOR_HOST_REG_L(int dst_reg, int src_reg) +static __inline void +XOR_HOST_REG_L(int dst_reg, int src_reg) { - addbyte(0x31); /*XORL dst_reg, src_reg*/ - addbyte(0xc0 | dst_reg | (src_reg << 3)); + addbyte(0x31); /*XORL dst_reg, src_reg*/ + addbyte(0xc0 | dst_reg | (src_reg << 3)); } -static inline void XOR_HOST_REG_IMM(int host_reg, uint32_t imm) +static __inline void +XOR_HOST_REG_IMM(int host_reg, uint32_t imm) { - if (imm < 0x80 || imm >= 0xffffff80) - { - addbyte(0x83); /*XORL host_reg, imm*/ - addbyte(0xF0 | host_reg); - addbyte(imm & 0xff); - } - else - { - addbyte(0x81); /*XORL host_reg, imm*/ - addbyte(0xF0 | host_reg); - addlong(imm); - } + if (imm < 0x80 || imm >= 0xffffff80) { + addbyte(0x83); /*XORL host_reg, imm*/ + addbyte(0xF0 | host_reg); + addbyte(imm & 0xff); + } else { + addbyte(0x81); /*XORL host_reg, imm*/ + addbyte(0xF0 | host_reg); + addlong(imm); + } } -static inline void CALL_FUNC(uintptr_t dest) +static __inline void +CALL_FUNC(uintptr_t dest) { - addbyte(0xE8); /*CALL*/ - addlong(((uintptr_t)dest - (uintptr_t)(&codeblock[block_current].data[block_pos + 4]))); + addbyte(0xE8); /*CALL*/ + addlong(((uintptr_t) dest - (uintptr_t) (&codeblock[block_current].data[block_pos + 4]))); } -static inline void SHL_B_IMM(int reg, int count) +static __inline void +SHL_B_IMM(int reg, int count) { - addbyte(0xc0); /*SHL reg, count*/ - addbyte(0xc0 | reg | 0x20); - addbyte(count); + addbyte(0xc0); /*SHL reg, count*/ + addbyte(0xc0 | reg | 0x20); + addbyte(count); } -static inline void SHL_W_IMM(int reg, int count) +static __inline void +SHL_W_IMM(int reg, int count) { - addbyte(0x66); /*SHL reg, count*/ - addbyte(0xc1); - addbyte(0xc0 | reg | 0x20); - addbyte(count); + addbyte(0x66); /*SHL reg, count*/ + addbyte(0xc1); + addbyte(0xc0 | reg | 0x20); + addbyte(count); } -static inline void SHL_L_IMM(int reg, int count) +static __inline void +SHL_L_IMM(int reg, int count) { - addbyte(0xc1); /*SHL reg, count*/ - addbyte(0xc0 | reg | 0x20); - addbyte(count); + addbyte(0xc1); /*SHL reg, count*/ + addbyte(0xc0 | reg | 0x20); + addbyte(count); } -static inline void SHR_B_IMM(int reg, int count) +static __inline void +SHR_B_IMM(int reg, int count) { - addbyte(0xc0); /*SHR reg, count*/ - addbyte(0xc0 | reg | 0x28); - addbyte(count); + addbyte(0xc0); /*SHR reg, count*/ + addbyte(0xc0 | reg | 0x28); + addbyte(count); } -static inline void SHR_W_IMM(int reg, int count) +static __inline void +SHR_W_IMM(int reg, int count) { - addbyte(0x66); /*SHR reg, count*/ - addbyte(0xc1); - addbyte(0xc0 | reg | 0x28); - addbyte(count); + addbyte(0x66); /*SHR reg, count*/ + addbyte(0xc1); + addbyte(0xc0 | reg | 0x28); + addbyte(count); } -static inline void SHR_L_IMM(int reg, int count) +static __inline void +SHR_L_IMM(int reg, int count) { - addbyte(0xc1); /*SHR reg, count*/ - addbyte(0xc0 | reg | 0x28); - addbyte(count); + addbyte(0xc1); /*SHR reg, count*/ + addbyte(0xc0 | reg | 0x28); + addbyte(count); } -static inline void SAR_B_IMM(int reg, int count) +static __inline void +SAR_B_IMM(int reg, int count) { - addbyte(0xc0); /*SAR reg, count*/ - addbyte(0xc0 | reg | 0x38); - addbyte(count); + addbyte(0xc0); /*SAR reg, count*/ + addbyte(0xc0 | reg | 0x38); + addbyte(count); } -static inline void SAR_W_IMM(int reg, int count) +static __inline void +SAR_W_IMM(int reg, int count) { - addbyte(0x66); /*SAR reg, count*/ - addbyte(0xc1); - addbyte(0xc0 | reg | 0x38); - addbyte(count); + addbyte(0x66); /*SAR reg, count*/ + addbyte(0xc1); + addbyte(0xc0 | reg | 0x38); + addbyte(count); } -static inline void SAR_L_IMM(int reg, int count) +static __inline void +SAR_L_IMM(int reg, int count) { - addbyte(0xc1); /*SAR reg, count*/ - addbyte(0xc0 | reg | 0x38); - addbyte(count); + addbyte(0xc1); /*SAR reg, count*/ + addbyte(0xc0 | reg | 0x38); + addbyte(count); } - -static inline void CHECK_SEG_READ(x86seg *seg) +static __inline void +CHECK_SEG_READ(x86seg *seg) { - /*Segments always valid in real/V86 mode*/ - if (!(cr0 & 1) || (cpu_state.eflags & VM_FLAG)) - return; - /*CS and SS must always be valid*/ - if (seg == &cpu_state.seg_cs || seg == &cpu_state.seg_ss) - return; - if (seg->checked) - return; - if (seg == &cpu_state.seg_ds && codegen_flat_ds && !(cpu_cur_status & CPU_STATUS_NOTFLATDS)) - return; + /*Segments always valid in real/V86 mode*/ + if (!(cr0 & 1) || (cpu_state.eflags & VM_FLAG)) + return; + /*CS and SS must always be valid*/ + if (seg == &cpu_state.seg_cs || seg == &cpu_state.seg_ss) + return; + if (seg->checked) + return; + if (seg == &cpu_state.seg_ds && codegen_flat_ds && !(cpu_cur_status & CPU_STATUS_NOTFLATDS)) + return; - addbyte(0x83); /*CMP seg->base, -1*/ - addbyte(0x05|0x38); - addlong((uint32_t)&seg->base); - addbyte(-1); - addbyte(0x0f); - addbyte(0x84); /*JE BLOCK_GPF_OFFSET*/ - addlong(BLOCK_GPF_OFFSET - (block_pos + 4)); - - seg->checked = 1; + addbyte(0x83); /*CMP seg->base, -1*/ + addbyte(0x05 | 0x38); + addlong((uint32_t) &seg->base); + addbyte(-1); + addbyte(0x0f); + addbyte(0x84); /*JE BLOCK_GPF_OFFSET*/ + addlong(BLOCK_GPF_OFFSET - (block_pos + 4)); + + seg->checked = 1; } -static inline void CHECK_SEG_WRITE(x86seg *seg) +static __inline void +CHECK_SEG_WRITE(x86seg *seg) { - /*Segments always valid in real/V86 mode*/ - if (!(cr0 & 1) || (cpu_state.eflags & VM_FLAG)) - return; - /*CS and SS must always be valid*/ - if (seg == &cpu_state.seg_cs || seg == &cpu_state.seg_ss) - return; - if (seg->checked) - return; - if (seg == &cpu_state.seg_ds && codegen_flat_ds && !(cpu_cur_status & CPU_STATUS_NOTFLATDS)) - return; - - addbyte(0x83); /*CMP seg->base, -1*/ - addbyte(0x05|0x38); - addlong((uint32_t)&seg->base); - addbyte(-1); - addbyte(0x0f); - addbyte(0x84); /*JE BLOCK_GPF_OFFSET*/ - addlong(BLOCK_GPF_OFFSET - (block_pos + 4)); + /*Segments always valid in real/V86 mode*/ + if (!(cr0 & 1) || (cpu_state.eflags & VM_FLAG)) + return; + /*CS and SS must always be valid*/ + if (seg == &cpu_state.seg_cs || seg == &cpu_state.seg_ss) + return; + if (seg->checked) + return; + if (seg == &cpu_state.seg_ds && codegen_flat_ds && !(cpu_cur_status & CPU_STATUS_NOTFLATDS)) + return; - seg->checked = 1; + addbyte(0x83); /*CMP seg->base, -1*/ + addbyte(0x05 | 0x38); + addlong((uint32_t) &seg->base); + addbyte(-1); + addbyte(0x0f); + addbyte(0x84); /*JE BLOCK_GPF_OFFSET*/ + addlong(BLOCK_GPF_OFFSET - (block_pos + 4)); + + seg->checked = 1; } -static inline void CHECK_SEG_LIMITS(x86seg *seg, int end_offset) +static __inline void +CHECK_SEG_LIMITS(x86seg *seg, int end_offset) { - if ((seg == &cpu_state.seg_ds && codegen_flat_ds && !(cpu_cur_status & CPU_STATUS_NOTFLATDS)) || (seg == &cpu_state.seg_ss && codegen_flat_ss && !(cpu_cur_status & CPU_STATUS_NOTFLATSS))) - return; + if ((seg == &cpu_state.seg_ds && codegen_flat_ds && !(cpu_cur_status & CPU_STATUS_NOTFLATDS)) || (seg == &cpu_state.seg_ss && codegen_flat_ss && !(cpu_cur_status & CPU_STATUS_NOTFLATSS))) + return; - addbyte(0x3b); /*CMP EAX, seg->limit_low*/ - addbyte(0x05); - addlong((uint32_t)&seg->limit_low); - addbyte(0x0f); /*JB BLOCK_GPF_OFFSET*/ - addbyte(0x82); - addlong(BLOCK_GPF_OFFSET - (block_pos + 4)); - if (end_offset) - { - addbyte(0x83); /*ADD EAX, end_offset*/ - addbyte(0xc0); - addbyte(end_offset); - addbyte(0x3b); /*CMP EAX, seg->limit_high*/ - addbyte(0x05); - addlong((uint32_t)&seg->limit_high); - addbyte(0x0f); /*JNBE BLOCK_GPF_OFFSET*/ - addbyte(0x87); - addlong(BLOCK_GPF_OFFSET - (block_pos + 4)); - addbyte(0x83); /*SUB EAX, end_offset*/ - addbyte(0xe8); - addbyte(end_offset); - } -} - -static inline void MEM_LOAD_ADDR_EA_B(x86seg *seg) -{ - if ((seg == &cpu_state.seg_ds && codegen_flat_ds && !(cpu_cur_status & CPU_STATUS_NOTFLATDS)) || (seg == &cpu_state.seg_ss && codegen_flat_ss && !(cpu_cur_status & CPU_STATUS_NOTFLATSS))) - { - addbyte(0x31); /*XOR EDX, EDX*/ - addbyte(0xd2); - } - else - { - addbyte(0x8b); /*MOVL EDX, seg->base*/ - addbyte(0x05 | (REG_EDX << 3)); - addlong((uint32_t)&seg->base); - } - addbyte(0xe8); /*CALL mem_load_addr_ea_b*/ - addlong(mem_load_addr_ea_b - (uint32_t)(&codeblock[block_current].data[block_pos + 4])); - - host_reg_mapping[0] = 8; -} -static inline int MEM_LOAD_ADDR_EA_B_NO_ABRT(x86seg *seg) -{ - if ((seg == &cpu_state.seg_ds && codegen_flat_ds && !(cpu_cur_status & CPU_STATUS_NOTFLATDS)) || (seg == &cpu_state.seg_ss && codegen_flat_ss && !(cpu_cur_status & CPU_STATUS_NOTFLATSS))) - { - addbyte(0x31); /*XOR EDX, EDX*/ - addbyte(0xd2); - } - else - { - addbyte(0x8b); /*MOVL EDX, seg->base*/ - addbyte(0x05 | (REG_EDX << 3)); - addlong((uint32_t)&seg->base); - } - addbyte(0xe8); /*CALL mem_load_addr_ea_b_no_abrt*/ - addlong(mem_load_addr_ea_b_no_abrt - (uint32_t)(&codeblock[block_current].data[block_pos + 4])); - - host_reg_mapping[REG_ECX] = 8; - - return REG_ECX; -} -static inline void MEM_LOAD_ADDR_EA_W(x86seg *seg) -{ - if ((seg == &cpu_state.seg_ds && codegen_flat_ds && !(cpu_cur_status & CPU_STATUS_NOTFLATDS)) || (seg == &cpu_state.seg_ss && codegen_flat_ss && !(cpu_cur_status & CPU_STATUS_NOTFLATSS))) - { - addbyte(0x31); /*XOR EDX, EDX*/ - addbyte(0xd2); - } - else - { - addbyte(0x8b); /*MOVL EDX, seg->base*/ - addbyte(0x05 | (REG_EDX << 3)); - addlong((uint32_t)&seg->base); - } - addbyte(0xe8); /*CALL mem_load_addr_ea_w*/ - addlong(mem_load_addr_ea_w - (uint32_t)(&codeblock[block_current].data[block_pos + 4])); - - host_reg_mapping[0] = 8; -} -static inline void MEM_LOAD_ADDR_EA_W_OFFSET(x86seg *seg, int offset) -{ - if ((seg == &cpu_state.seg_ds && codegen_flat_ds && !(cpu_cur_status & CPU_STATUS_NOTFLATDS)) || (seg == &cpu_state.seg_ss && codegen_flat_ss && !(cpu_cur_status & CPU_STATUS_NOTFLATSS))) - { - addbyte(0x31); /*XOR EDX, EDX*/ - addbyte(0xd2); - } - else - { - addbyte(0x8b); /*MOVL EDX, seg->base*/ - addbyte(0x05 | (REG_EDX << 3)); - addlong((uint32_t)&seg->base); - } - addbyte(0x83); /*ADD EAX, offset*/ + addbyte(0x3b); /*CMP EAX, seg->limit_low*/ + addbyte(0x05); + addlong((uint32_t) &seg->limit_low); + addbyte(0x0f); /*JB BLOCK_GPF_OFFSET*/ + addbyte(0x82); + addlong(BLOCK_GPF_OFFSET - (block_pos + 4)); + if (end_offset) { + addbyte(0x83); /*ADD EAX, end_offset*/ addbyte(0xc0); - addbyte(offset); - addbyte(0xe8); /*CALL mem_load_addr_ea_w*/ - addlong(mem_load_addr_ea_w - (uint32_t)(&codeblock[block_current].data[block_pos + 4])); - - host_reg_mapping[0] = 8; -} -static inline int MEM_LOAD_ADDR_EA_W_NO_ABRT(x86seg *seg) -{ - if ((seg == &cpu_state.seg_ds && codegen_flat_ds && !(cpu_cur_status & CPU_STATUS_NOTFLATDS)) || (seg == &cpu_state.seg_ss && codegen_flat_ss && !(cpu_cur_status & CPU_STATUS_NOTFLATSS))) - { - addbyte(0x31); /*XOR EDX, EDX*/ - addbyte(0xd2); - } - else - { - addbyte(0x8b); /*MOVL EDX, seg->base*/ - addbyte(0x05 | (REG_EDX << 3)); - addlong((uint32_t)&seg->base); - } - addbyte(0xe8); /*CALL mem_load_addr_ea_w_no_abrt*/ - addlong(mem_load_addr_ea_w_no_abrt - (uint32_t)(&codeblock[block_current].data[block_pos + 4])); - - host_reg_mapping[REG_ECX] = 8; - - return REG_ECX; -} -static inline void MEM_LOAD_ADDR_EA_L(x86seg *seg) -{ - if ((seg == &cpu_state.seg_ds && codegen_flat_ds && !(cpu_cur_status & CPU_STATUS_NOTFLATDS)) || (seg == &cpu_state.seg_ss && codegen_flat_ss && !(cpu_cur_status & CPU_STATUS_NOTFLATSS))) - { - addbyte(0x31); /*XOR EDX, EDX*/ - addbyte(0xd2); - } - else - { - addbyte(0x8b); /*MOVL EDX, seg->base*/ - addbyte(0x05 | (REG_EDX << 3)); - addlong((uint32_t)&seg->base); - } - addbyte(0xe8); /*CALL mem_load_addr_ea_l*/ - addlong(mem_load_addr_ea_l - (uint32_t)(&codeblock[block_current].data[block_pos + 4])); - - - host_reg_mapping[0] = 8; -} -static inline int MEM_LOAD_ADDR_EA_L_NO_ABRT(x86seg *seg) -{ - if ((seg == &cpu_state.seg_ds && codegen_flat_ds && !(cpu_cur_status & CPU_STATUS_NOTFLATDS)) || (seg == &cpu_state.seg_ss && codegen_flat_ss && !(cpu_cur_status & CPU_STATUS_NOTFLATSS))) - { - addbyte(0x31); /*XOR EDX, EDX*/ - addbyte(0xd2); - } - else - { - addbyte(0x8b); /*MOVL EDX, seg->base*/ - addbyte(0x05 | (REG_EDX << 3)); - addlong((uint32_t)&seg->base); - } - addbyte(0xe8); /*CALL mem_load_addr_ea_l_no_abrt*/ - addlong(mem_load_addr_ea_l_no_abrt - (uint32_t)(&codeblock[block_current].data[block_pos + 4])); - - host_reg_mapping[REG_ECX] = 8; - - return REG_ECX; + addbyte(end_offset); + addbyte(0x3b); /*CMP EAX, seg->limit_high*/ + addbyte(0x05); + addlong((uint32_t) &seg->limit_high); + addbyte(0x0f); /*JNBE BLOCK_GPF_OFFSET*/ + addbyte(0x87); + addlong(BLOCK_GPF_OFFSET - (block_pos + 4)); + addbyte(0x83); /*SUB EAX, end_offset*/ + addbyte(0xe8); + addbyte(end_offset); + } } -static inline void MEM_LOAD_ADDR_EA_Q(x86seg *seg) +static __inline void +MEM_LOAD_ADDR_EA_B(x86seg *seg) { - if ((seg == &cpu_state.seg_ds && codegen_flat_ds && !(cpu_cur_status & CPU_STATUS_NOTFLATDS)) || (seg == &cpu_state.seg_ss && codegen_flat_ss && !(cpu_cur_status & CPU_STATUS_NOTFLATSS))) - { - addbyte(0x31); /*XOR EDX, EDX*/ - addbyte(0xd2); - } - else - { - addbyte(0x8b); /*MOVL EDX, seg->base*/ - addbyte(0x05 | (REG_EDX << 3)); - addlong((uint32_t)&seg->base); - } - addbyte(0xe8); /*CALL mem_load_addr_ea_q*/ - addlong(mem_load_addr_ea_q - (uint32_t)(&codeblock[block_current].data[block_pos + 4])); + if ((seg == &cpu_state.seg_ds && codegen_flat_ds && !(cpu_cur_status & CPU_STATUS_NOTFLATDS)) || (seg == &cpu_state.seg_ss && codegen_flat_ss && !(cpu_cur_status & CPU_STATUS_NOTFLATSS))) { + addbyte(0x31); /*XOR EDX, EDX*/ + addbyte(0xd2); + } else { + addbyte(0x8b); /*MOVL EDX, seg->base*/ + addbyte(0x05 | (REG_EDX << 3)); + addlong((uint32_t) &seg->base); + } + addbyte(0xe8); /*CALL mem_load_addr_ea_b*/ + addlong(mem_load_addr_ea_b - (uint32_t) (&codeblock[block_current].data[block_pos + 4])); - host_reg_mapping[0] = 8; + host_reg_mapping[0] = 8; +} +static __inline int +MEM_LOAD_ADDR_EA_B_NO_ABRT(x86seg *seg) +{ + if ((seg == &cpu_state.seg_ds && codegen_flat_ds && !(cpu_cur_status & CPU_STATUS_NOTFLATDS)) || (seg == &cpu_state.seg_ss && codegen_flat_ss && !(cpu_cur_status & CPU_STATUS_NOTFLATSS))) { + addbyte(0x31); /*XOR EDX, EDX*/ + addbyte(0xd2); + } else { + addbyte(0x8b); /*MOVL EDX, seg->base*/ + addbyte(0x05 | (REG_EDX << 3)); + addlong((uint32_t) &seg->base); + } + addbyte(0xe8); /*CALL mem_load_addr_ea_b_no_abrt*/ + addlong(mem_load_addr_ea_b_no_abrt - (uint32_t) (&codeblock[block_current].data[block_pos + 4])); + + host_reg_mapping[REG_ECX] = 8; + + return REG_ECX; +} +static __inline void +MEM_LOAD_ADDR_EA_W(x86seg *seg) +{ + if ((seg == &cpu_state.seg_ds && codegen_flat_ds && !(cpu_cur_status & CPU_STATUS_NOTFLATDS)) || (seg == &cpu_state.seg_ss && codegen_flat_ss && !(cpu_cur_status & CPU_STATUS_NOTFLATSS))) { + addbyte(0x31); /*XOR EDX, EDX*/ + addbyte(0xd2); + } else { + addbyte(0x8b); /*MOVL EDX, seg->base*/ + addbyte(0x05 | (REG_EDX << 3)); + addlong((uint32_t) &seg->base); + } + addbyte(0xe8); /*CALL mem_load_addr_ea_w*/ + addlong(mem_load_addr_ea_w - (uint32_t) (&codeblock[block_current].data[block_pos + 4])); + + host_reg_mapping[0] = 8; +} +static __inline void +MEM_LOAD_ADDR_EA_W_OFFSET(x86seg *seg, int offset) +{ + if ((seg == &cpu_state.seg_ds && codegen_flat_ds && !(cpu_cur_status & CPU_STATUS_NOTFLATDS)) || (seg == &cpu_state.seg_ss && codegen_flat_ss && !(cpu_cur_status & CPU_STATUS_NOTFLATSS))) { + addbyte(0x31); /*XOR EDX, EDX*/ + addbyte(0xd2); + } else { + addbyte(0x8b); /*MOVL EDX, seg->base*/ + addbyte(0x05 | (REG_EDX << 3)); + addlong((uint32_t) &seg->base); + } + addbyte(0x83); /*ADD EAX, offset*/ + addbyte(0xc0); + addbyte(offset); + addbyte(0xe8); /*CALL mem_load_addr_ea_w*/ + addlong(mem_load_addr_ea_w - (uint32_t) (&codeblock[block_current].data[block_pos + 4])); + + host_reg_mapping[0] = 8; +} +static __inline int +MEM_LOAD_ADDR_EA_W_NO_ABRT(x86seg *seg) +{ + if ((seg == &cpu_state.seg_ds && codegen_flat_ds && !(cpu_cur_status & CPU_STATUS_NOTFLATDS)) || (seg == &cpu_state.seg_ss && codegen_flat_ss && !(cpu_cur_status & CPU_STATUS_NOTFLATSS))) { + addbyte(0x31); /*XOR EDX, EDX*/ + addbyte(0xd2); + } else { + addbyte(0x8b); /*MOVL EDX, seg->base*/ + addbyte(0x05 | (REG_EDX << 3)); + addlong((uint32_t) &seg->base); + } + addbyte(0xe8); /*CALL mem_load_addr_ea_w_no_abrt*/ + addlong(mem_load_addr_ea_w_no_abrt - (uint32_t) (&codeblock[block_current].data[block_pos + 4])); + + host_reg_mapping[REG_ECX] = 8; + + return REG_ECX; +} +static __inline void +MEM_LOAD_ADDR_EA_L(x86seg *seg) +{ + if ((seg == &cpu_state.seg_ds && codegen_flat_ds && !(cpu_cur_status & CPU_STATUS_NOTFLATDS)) || (seg == &cpu_state.seg_ss && codegen_flat_ss && !(cpu_cur_status & CPU_STATUS_NOTFLATSS))) { + addbyte(0x31); /*XOR EDX, EDX*/ + addbyte(0xd2); + } else { + addbyte(0x8b); /*MOVL EDX, seg->base*/ + addbyte(0x05 | (REG_EDX << 3)); + addlong((uint32_t) &seg->base); + } + addbyte(0xe8); /*CALL mem_load_addr_ea_l*/ + addlong(mem_load_addr_ea_l - (uint32_t) (&codeblock[block_current].data[block_pos + 4])); + + host_reg_mapping[0] = 8; +} +static __inline int +MEM_LOAD_ADDR_EA_L_NO_ABRT(x86seg *seg) +{ + if ((seg == &cpu_state.seg_ds && codegen_flat_ds && !(cpu_cur_status & CPU_STATUS_NOTFLATDS)) || (seg == &cpu_state.seg_ss && codegen_flat_ss && !(cpu_cur_status & CPU_STATUS_NOTFLATSS))) { + addbyte(0x31); /*XOR EDX, EDX*/ + addbyte(0xd2); + } else { + addbyte(0x8b); /*MOVL EDX, seg->base*/ + addbyte(0x05 | (REG_EDX << 3)); + addlong((uint32_t) &seg->base); + } + addbyte(0xe8); /*CALL mem_load_addr_ea_l_no_abrt*/ + addlong(mem_load_addr_ea_l_no_abrt - (uint32_t) (&codeblock[block_current].data[block_pos + 4])); + + host_reg_mapping[REG_ECX] = 8; + + return REG_ECX; } -static inline void MEM_LOAD_ADDR_IMM_B(x86seg *seg, uint32_t addr) +static __inline void +MEM_LOAD_ADDR_EA_Q(x86seg *seg) { - addbyte(0xb8); /*MOV EAX, addr*/ - addlong(addr); - MEM_LOAD_ADDR_EA_B(seg); -} -static inline void MEM_LOAD_ADDR_IMM_W(x86seg *seg, uint32_t addr) -{ - addbyte(0xb8); /*MOV EAX, addr*/ - addlong(addr); - MEM_LOAD_ADDR_EA_W(seg); -} -static inline void MEM_LOAD_ADDR_IMM_L(x86seg *seg, uint32_t addr) -{ - addbyte(0xb8); /*MOV EAX, addr*/ - addlong(addr); - MEM_LOAD_ADDR_EA_L(seg); + if ((seg == &cpu_state.seg_ds && codegen_flat_ds && !(cpu_cur_status & CPU_STATUS_NOTFLATDS)) || (seg == &cpu_state.seg_ss && codegen_flat_ss && !(cpu_cur_status & CPU_STATUS_NOTFLATSS))) { + addbyte(0x31); /*XOR EDX, EDX*/ + addbyte(0xd2); + } else { + addbyte(0x8b); /*MOVL EDX, seg->base*/ + addbyte(0x05 | (REG_EDX << 3)); + addlong((uint32_t) &seg->base); + } + addbyte(0xe8); /*CALL mem_load_addr_ea_q*/ + addlong(mem_load_addr_ea_q - (uint32_t) (&codeblock[block_current].data[block_pos + 4])); + + host_reg_mapping[0] = 8; } -static inline void MEM_STORE_ADDR_EA_B(x86seg *seg, int host_reg) +static __inline void +MEM_LOAD_ADDR_IMM_B(x86seg *seg, uint32_t addr) { - if ((seg == &cpu_state.seg_ds && codegen_flat_ds && !(cpu_cur_status & CPU_STATUS_NOTFLATDS)) || (seg == &cpu_state.seg_ss && codegen_flat_ss && !(cpu_cur_status & CPU_STATUS_NOTFLATSS))) - { - addbyte(0x31); /*XOR ESI, ESI*/ - addbyte(0xf6); - } - else - { - addbyte(0x8b); /*MOVL ESI, seg->base*/ - addbyte(0x05 | (REG_ESI << 3)); - addlong((uint32_t)&seg->base); - } - if (host_reg != REG_ECX) - { - addbyte(0x89); /*MOV ECX, host_reg*/ - addbyte(0xc0 | REG_ECX | (host_reg << 3)); - } - addbyte(0xe8); /*CALL mem_store_addr_ea_b*/ - addlong(mem_store_addr_ea_b - (uint32_t)(&codeblock[block_current].data[block_pos + 4])); + addbyte(0xb8); /*MOV EAX, addr*/ + addlong(addr); + MEM_LOAD_ADDR_EA_B(seg); } -static inline void MEM_STORE_ADDR_EA_B_NO_ABRT(x86seg *seg, int host_reg) +static __inline void +MEM_LOAD_ADDR_IMM_W(x86seg *seg, uint32_t addr) { - if ((seg == &cpu_state.seg_ds && codegen_flat_ds && !(cpu_cur_status & CPU_STATUS_NOTFLATDS)) || (seg == &cpu_state.seg_ss && codegen_flat_ss && !(cpu_cur_status & CPU_STATUS_NOTFLATSS))) - { - addbyte(0x31); /*XOR ESI, ESI*/ - addbyte(0xf6); - } - else - { - addbyte(0x8b); /*MOVL ESI, seg->base*/ - addbyte(0x05 | (REG_ESI << 3)); - addlong((uint32_t)&seg->base); - } - if (host_reg != REG_ECX) - { - addbyte(0x89); /*MOV ECX, host_reg*/ - addbyte(0xc0 | REG_ECX | (host_reg << 3)); - } - addbyte(0xe8); /*CALL mem_store_addr_ea_b_no_abrt*/ - addlong(mem_store_addr_ea_b_no_abrt - (uint32_t)(&codeblock[block_current].data[block_pos + 4])); + addbyte(0xb8); /*MOV EAX, addr*/ + addlong(addr); + MEM_LOAD_ADDR_EA_W(seg); } -static inline void MEM_STORE_ADDR_EA_W(x86seg *seg, int host_reg) +static __inline void +MEM_LOAD_ADDR_IMM_L(x86seg *seg, uint32_t addr) { - if ((seg == &cpu_state.seg_ds && codegen_flat_ds && !(cpu_cur_status & CPU_STATUS_NOTFLATDS)) || (seg == &cpu_state.seg_ss && codegen_flat_ss && !(cpu_cur_status & CPU_STATUS_NOTFLATSS))) - { - addbyte(0x31); /*XOR ESI, ESI*/ - addbyte(0xf6); - } - else - { - addbyte(0x8b); /*MOVL ESI, seg->base*/ - addbyte(0x05 | (REG_ESI << 3)); - addlong((uint32_t)&seg->base); - } - if (host_reg != REG_ECX) - { - addbyte(0x89); /*MOV ECX, host_reg*/ - addbyte(0xc0 | REG_ECX | (host_reg << 3)); - } - addbyte(0xe8); /*CALL mem_store_addr_ea_w*/ - addlong(mem_store_addr_ea_w - (uint32_t)(&codeblock[block_current].data[block_pos + 4])); -} -static inline void MEM_STORE_ADDR_EA_W_NO_ABRT(x86seg *seg, int host_reg) -{ - if ((seg == &cpu_state.seg_ds && codegen_flat_ds && !(cpu_cur_status & CPU_STATUS_NOTFLATDS)) || (seg == &cpu_state.seg_ss && codegen_flat_ss && !(cpu_cur_status & CPU_STATUS_NOTFLATSS))) - { - addbyte(0x31); /*XOR ESI, ESI*/ - addbyte(0xf6); - } - else - { - addbyte(0x8b); /*MOVL ESI, seg->base*/ - addbyte(0x05 | (REG_ESI << 3)); - addlong((uint32_t)&seg->base); - } - if (host_reg != REG_ECX) - { - addbyte(0x89); /*MOV ECX, host_reg*/ - addbyte(0xc0 | REG_ECX | (host_reg << 3)); - } - addbyte(0xe8); /*CALL mem_store_addr_ea_w_no_abrt*/ - addlong(mem_store_addr_ea_w_no_abrt - (uint32_t)(&codeblock[block_current].data[block_pos + 4])); -} -static inline void MEM_STORE_ADDR_EA_L(x86seg *seg, int host_reg) -{ - if ((seg == &cpu_state.seg_ds && codegen_flat_ds && !(cpu_cur_status & CPU_STATUS_NOTFLATDS)) || (seg == &cpu_state.seg_ss && codegen_flat_ss && !(cpu_cur_status & CPU_STATUS_NOTFLATSS))) - { - addbyte(0x31); /*XOR ESI, ESI*/ - addbyte(0xf6); - } - else - { - addbyte(0x8b); /*MOVL ESI, seg->base*/ - addbyte(0x05 | (REG_ESI << 3)); - addlong((uint32_t)&seg->base); - } - if (host_reg != REG_ECX) - { - addbyte(0x89); /*MOV ECX, host_reg*/ - addbyte(0xc0 | REG_ECX | (host_reg << 3)); - } - addbyte(0xe8); /*CALL mem_store_addr_ea_l*/ - addlong(mem_store_addr_ea_l - (uint32_t)(&codeblock[block_current].data[block_pos + 4])); -} -static inline void MEM_STORE_ADDR_EA_L_NO_ABRT(x86seg *seg, int host_reg) -{ - if ((seg == &cpu_state.seg_ds && codegen_flat_ds && !(cpu_cur_status & CPU_STATUS_NOTFLATDS)) || (seg == &cpu_state.seg_ss && codegen_flat_ss && !(cpu_cur_status & CPU_STATUS_NOTFLATSS))) - { - addbyte(0x31); /*XOR ESI, ESI*/ - addbyte(0xf6); - } - else - { - addbyte(0x8b); /*MOVL ESI, seg->base*/ - addbyte(0x05 | (REG_ESI << 3)); - addlong((uint32_t)&seg->base); - } - if (host_reg != REG_ECX) - { - addbyte(0x89); /*MOV ECX, host_reg*/ - addbyte(0xc0 | REG_ECX | (host_reg << 3)); - } - addbyte(0xe8); /*CALL mem_store_addr_ea_l_no_abrt*/ - addlong(mem_store_addr_ea_l_no_abrt - (uint32_t)(&codeblock[block_current].data[block_pos + 4])); -} -static inline void MEM_STORE_ADDR_EA_Q(x86seg *seg, int host_reg, int host_reg2) -{ - if (host_reg != REG_EBX) - { - addbyte(0x89); /*MOV EBX, host_reg*/ - addbyte(0xc0 | REG_EBX | (host_reg << 3)); - } - if (host_reg2 != REG_ECX) - { - addbyte(0x89); /*MOV ECX, host_reg2*/ - addbyte(0xc0 | REG_ECX | (host_reg2 << 3)); - } - if ((seg == &cpu_state.seg_ds && codegen_flat_ds && !(cpu_cur_status & CPU_STATUS_NOTFLATDS)) || (seg == &cpu_state.seg_ss && codegen_flat_ss && !(cpu_cur_status & CPU_STATUS_NOTFLATSS))) - { - addbyte(0x31); /*XOR ESI, ESI*/ - addbyte(0xf6); - } - else - { - addbyte(0x8b); /*MOVL ESI, seg->base*/ - addbyte(0x05 | (REG_ESI << 3)); - addlong((uint32_t)&seg->base); - } - addbyte(0xe8); /*CALL mem_store_addr_ea_q*/ - addlong(mem_store_addr_ea_q - (uint32_t)(&codeblock[block_current].data[block_pos + 4])); + addbyte(0xb8); /*MOV EAX, addr*/ + addlong(addr); + MEM_LOAD_ADDR_EA_L(seg); } -static inline void MEM_STORE_ADDR_IMM_B(x86seg *seg, uint32_t addr, int host_reg) +static __inline void +MEM_STORE_ADDR_EA_B(x86seg *seg, int host_reg) { - addbyte(0xb8); /*MOV EAX, addr*/ - addlong(addr); - MEM_STORE_ADDR_EA_B(seg, host_reg); + if ((seg == &cpu_state.seg_ds && codegen_flat_ds && !(cpu_cur_status & CPU_STATUS_NOTFLATDS)) || (seg == &cpu_state.seg_ss && codegen_flat_ss && !(cpu_cur_status & CPU_STATUS_NOTFLATSS))) { + addbyte(0x31); /*XOR ESI, ESI*/ + addbyte(0xf6); + } else { + addbyte(0x8b); /*MOVL ESI, seg->base*/ + addbyte(0x05 | (REG_ESI << 3)); + addlong((uint32_t) &seg->base); + } + if (host_reg != REG_ECX) { + addbyte(0x89); /*MOV ECX, host_reg*/ + addbyte(0xc0 | REG_ECX | (host_reg << 3)); + } + addbyte(0xe8); /*CALL mem_store_addr_ea_b*/ + addlong(mem_store_addr_ea_b - (uint32_t) (&codeblock[block_current].data[block_pos + 4])); } -static inline void MEM_STORE_ADDR_IMM_L(x86seg *seg, uint32_t addr, int host_reg) +static __inline void +MEM_STORE_ADDR_EA_B_NO_ABRT(x86seg *seg, int host_reg) { - addbyte(0xb8); /*MOV EAX, addr*/ - addlong(addr); - MEM_STORE_ADDR_EA_L(seg, host_reg); + if ((seg == &cpu_state.seg_ds && codegen_flat_ds && !(cpu_cur_status & CPU_STATUS_NOTFLATDS)) || (seg == &cpu_state.seg_ss && codegen_flat_ss && !(cpu_cur_status & CPU_STATUS_NOTFLATSS))) { + addbyte(0x31); /*XOR ESI, ESI*/ + addbyte(0xf6); + } else { + addbyte(0x8b); /*MOVL ESI, seg->base*/ + addbyte(0x05 | (REG_ESI << 3)); + addlong((uint32_t) &seg->base); + } + if (host_reg != REG_ECX) { + addbyte(0x89); /*MOV ECX, host_reg*/ + addbyte(0xc0 | REG_ECX | (host_reg << 3)); + } + addbyte(0xe8); /*CALL mem_store_addr_ea_b_no_abrt*/ + addlong(mem_store_addr_ea_b_no_abrt - (uint32_t) (&codeblock[block_current].data[block_pos + 4])); } -static inline void MEM_STORE_ADDR_IMM_W(x86seg *seg, uint32_t addr, int host_reg) +static __inline void +MEM_STORE_ADDR_EA_W(x86seg *seg, int host_reg) { - addbyte(0xb8); /*MOV EAX, addr*/ - addlong(addr); - MEM_STORE_ADDR_EA_W(seg, host_reg); + if ((seg == &cpu_state.seg_ds && codegen_flat_ds && !(cpu_cur_status & CPU_STATUS_NOTFLATDS)) || (seg == &cpu_state.seg_ss && codegen_flat_ss && !(cpu_cur_status & CPU_STATUS_NOTFLATSS))) { + addbyte(0x31); /*XOR ESI, ESI*/ + addbyte(0xf6); + } else { + addbyte(0x8b); /*MOVL ESI, seg->base*/ + addbyte(0x05 | (REG_ESI << 3)); + addlong((uint32_t) &seg->base); + } + if (host_reg != REG_ECX) { + addbyte(0x89); /*MOV ECX, host_reg*/ + addbyte(0xc0 | REG_ECX | (host_reg << 3)); + } + addbyte(0xe8); /*CALL mem_store_addr_ea_w*/ + addlong(mem_store_addr_ea_w - (uint32_t) (&codeblock[block_current].data[block_pos + 4])); +} +static __inline void +MEM_STORE_ADDR_EA_W_NO_ABRT(x86seg *seg, int host_reg) +{ + if ((seg == &cpu_state.seg_ds && codegen_flat_ds && !(cpu_cur_status & CPU_STATUS_NOTFLATDS)) || (seg == &cpu_state.seg_ss && codegen_flat_ss && !(cpu_cur_status & CPU_STATUS_NOTFLATSS))) { + addbyte(0x31); /*XOR ESI, ESI*/ + addbyte(0xf6); + } else { + addbyte(0x8b); /*MOVL ESI, seg->base*/ + addbyte(0x05 | (REG_ESI << 3)); + addlong((uint32_t) &seg->base); + } + if (host_reg != REG_ECX) { + addbyte(0x89); /*MOV ECX, host_reg*/ + addbyte(0xc0 | REG_ECX | (host_reg << 3)); + } + addbyte(0xe8); /*CALL mem_store_addr_ea_w_no_abrt*/ + addlong(mem_store_addr_ea_w_no_abrt - (uint32_t) (&codeblock[block_current].data[block_pos + 4])); +} +static __inline void +MEM_STORE_ADDR_EA_L(x86seg *seg, int host_reg) +{ + if ((seg == &cpu_state.seg_ds && codegen_flat_ds && !(cpu_cur_status & CPU_STATUS_NOTFLATDS)) || (seg == &cpu_state.seg_ss && codegen_flat_ss && !(cpu_cur_status & CPU_STATUS_NOTFLATSS))) { + addbyte(0x31); /*XOR ESI, ESI*/ + addbyte(0xf6); + } else { + addbyte(0x8b); /*MOVL ESI, seg->base*/ + addbyte(0x05 | (REG_ESI << 3)); + addlong((uint32_t) &seg->base); + } + if (host_reg != REG_ECX) { + addbyte(0x89); /*MOV ECX, host_reg*/ + addbyte(0xc0 | REG_ECX | (host_reg << 3)); + } + addbyte(0xe8); /*CALL mem_store_addr_ea_l*/ + addlong(mem_store_addr_ea_l - (uint32_t) (&codeblock[block_current].data[block_pos + 4])); +} +static __inline void +MEM_STORE_ADDR_EA_L_NO_ABRT(x86seg *seg, int host_reg) +{ + if ((seg == &cpu_state.seg_ds && codegen_flat_ds && !(cpu_cur_status & CPU_STATUS_NOTFLATDS)) || (seg == &cpu_state.seg_ss && codegen_flat_ss && !(cpu_cur_status & CPU_STATUS_NOTFLATSS))) { + addbyte(0x31); /*XOR ESI, ESI*/ + addbyte(0xf6); + } else { + addbyte(0x8b); /*MOVL ESI, seg->base*/ + addbyte(0x05 | (REG_ESI << 3)); + addlong((uint32_t) &seg->base); + } + if (host_reg != REG_ECX) { + addbyte(0x89); /*MOV ECX, host_reg*/ + addbyte(0xc0 | REG_ECX | (host_reg << 3)); + } + addbyte(0xe8); /*CALL mem_store_addr_ea_l_no_abrt*/ + addlong(mem_store_addr_ea_l_no_abrt - (uint32_t) (&codeblock[block_current].data[block_pos + 4])); +} +static __inline void +MEM_STORE_ADDR_EA_Q(x86seg *seg, int host_reg, int host_reg2) +{ + if (host_reg != REG_EBX) { + addbyte(0x89); /*MOV EBX, host_reg*/ + addbyte(0xc0 | REG_EBX | (host_reg << 3)); + } + if (host_reg2 != REG_ECX) { + addbyte(0x89); /*MOV ECX, host_reg2*/ + addbyte(0xc0 | REG_ECX | (host_reg2 << 3)); + } + if ((seg == &cpu_state.seg_ds && codegen_flat_ds && !(cpu_cur_status & CPU_STATUS_NOTFLATDS)) || (seg == &cpu_state.seg_ss && codegen_flat_ss && !(cpu_cur_status & CPU_STATUS_NOTFLATSS))) { + addbyte(0x31); /*XOR ESI, ESI*/ + addbyte(0xf6); + } else { + addbyte(0x8b); /*MOVL ESI, seg->base*/ + addbyte(0x05 | (REG_ESI << 3)); + addlong((uint32_t) &seg->base); + } + addbyte(0xe8); /*CALL mem_store_addr_ea_q*/ + addlong(mem_store_addr_ea_q - (uint32_t) (&codeblock[block_current].data[block_pos + 4])); } - -static inline x86seg *FETCH_EA_16(x86seg *op_ea_seg, uint32_t fetchdat, int op_ssegs, uint32_t *op_pc) +static __inline void +MEM_STORE_ADDR_IMM_B(x86seg *seg, uint32_t addr, int host_reg) { - int mod = (fetchdat >> 6) & 3; - int rm = fetchdat & 7; - if (!mod && rm == 6) - { + addbyte(0xb8); /*MOV EAX, addr*/ + addlong(addr); + MEM_STORE_ADDR_EA_B(seg, host_reg); +} +static __inline void +MEM_STORE_ADDR_IMM_L(x86seg *seg, uint32_t addr, int host_reg) +{ + addbyte(0xb8); /*MOV EAX, addr*/ + addlong(addr); + MEM_STORE_ADDR_EA_L(seg, host_reg); +} +static __inline void +MEM_STORE_ADDR_IMM_W(x86seg *seg, uint32_t addr, int host_reg) +{ + addbyte(0xb8); /*MOV EAX, addr*/ + addlong(addr); + MEM_STORE_ADDR_EA_W(seg, host_reg); +} + +static __inline x86seg * +FETCH_EA_16(x86seg *op_ea_seg, uint32_t fetchdat, int op_ssegs, uint32_t *op_pc) +{ + int mod = (fetchdat >> 6) & 3; + int rm = fetchdat & 7; + if (!mod && rm == 6) { + addbyte(0xb8); /*MOVL EAX, imm16*/ + addlong((fetchdat >> 8) & 0xffff); + (*op_pc) += 2; + } else { + switch (mod) { + case 0: + addbyte(0xa1); /*MOVL EAX, *mod1add[0][rm]*/ + addlong((uint32_t) mod1add[0][rm]); + if (mod1add[1][rm] != &zero) { + addbyte(0x03); /*ADDL EAX, *mod1add[1][rm]*/ + addbyte(0x05); + addlong((uint32_t) mod1add[1][rm]); + } + break; + case 1: + addbyte(0xa1); /*MOVL EAX, *mod1add[0][rm]*/ + addlong((uint32_t) mod1add[0][rm]); + addbyte(0x83); /*ADDL EAX, imm8*/ + addbyte(0xc0 | REG_EAX); + addbyte((int8_t) (rmdat >> 8)); + if (mod1add[1][rm] != &zero) { + addbyte(0x03); /*ADDL EAX, *mod1add[1][rm]*/ + addbyte(0x05); + addlong((uint32_t) mod1add[1][rm]); + } + (*op_pc)++; + break; + case 2: addbyte(0xb8); /*MOVL EAX, imm16*/ addlong((fetchdat >> 8) & 0xffff); + addbyte(0x03); /*ADDL EAX, *mod1add[0][rm]*/ + addbyte(0x05); + addlong((uint32_t) mod1add[0][rm]); + if (mod1add[1][rm] != &zero) { + addbyte(0x03); /*ADDL EAX, *mod1add[1][rm]*/ + addbyte(0x05); + addlong((uint32_t) mod1add[1][rm]); + } (*op_pc) += 2; + break; } - else - { - switch (mod) - { - case 0: - addbyte(0xa1); /*MOVL EAX, *mod1add[0][rm]*/ - addlong((uint32_t)mod1add[0][rm]); - if (mod1add[1][rm] != &zero) - { - addbyte(0x03); /*ADDL EAX, *mod1add[1][rm]*/ - addbyte(0x05); - addlong((uint32_t)mod1add[1][rm]); - } - break; - case 1: - addbyte(0xa1); /*MOVL EAX, *mod1add[0][rm]*/ - addlong((uint32_t)mod1add[0][rm]); - addbyte(0x83); /*ADDL EAX, imm8*/ - addbyte(0xc0 | REG_EAX); - addbyte((int8_t)(rmdat >> 8)); - if (mod1add[1][rm] != &zero) - { - addbyte(0x03); /*ADDL EAX, *mod1add[1][rm]*/ - addbyte(0x05); - addlong((uint32_t)mod1add[1][rm]); - } - (*op_pc)++; - break; - case 2: - addbyte(0xb8); /*MOVL EAX, imm16*/ - addlong((fetchdat >> 8) & 0xffff); - addbyte(0x03); /*ADDL EAX, *mod1add[0][rm]*/ - addbyte(0x05); - addlong((uint32_t)mod1add[0][rm]); - if (mod1add[1][rm] != &zero) - { - addbyte(0x03); /*ADDL EAX, *mod1add[1][rm]*/ - addbyte(0x05); - addlong((uint32_t)mod1add[1][rm]); - } - (*op_pc) += 2; - break; - } - addbyte(0x25); /*ANDL EAX, 0xffff*/ - addlong(0xffff); + addbyte(0x25); /*ANDL EAX, 0xffff*/ + addlong(0xffff); - if (mod1seg[rm] == &ss && !op_ssegs) - op_ea_seg = &cpu_state.seg_ss; - } - return op_ea_seg; + if (mod1seg[rm] == &ss && !op_ssegs) + op_ea_seg = &cpu_state.seg_ss; + } + return op_ea_seg; } -static inline x86seg *FETCH_EA_32(x86seg *op_ea_seg, uint32_t fetchdat, int op_ssegs, uint32_t *op_pc, int stack_offset) +static __inline x86seg * +FETCH_EA_32(x86seg *op_ea_seg, uint32_t fetchdat, int op_ssegs, uint32_t *op_pc, int stack_offset) { - uint32_t new_eaaddr; - int mod = (fetchdat >> 6) & 3; - int rm = fetchdat & 7; + uint32_t new_eaaddr; + int mod = (fetchdat >> 6) & 3; + int rm = fetchdat & 7; - if (rm == 4) - { - uint8_t sib = fetchdat >> 8; + if (rm == 4) { + uint8_t sib = fetchdat >> 8; + (*op_pc)++; + + switch (mod) { + case 0: + if ((sib & 7) == 5) { + new_eaaddr = fastreadl(cs + (*op_pc) + 1); + addbyte(0xb8); /*MOVL EAX, imm32*/ + addlong(new_eaaddr); + (*op_pc) += 4; + } else { + addbyte(0x8b); /*MOVL EAX, regs[sib&7].l*/ + addbyte(0x45); + addbyte((uint8_t) cpu_state_offset(regs[sib & 7].l)); + } + break; + case 1: + addbyte(0x8b); /*MOVL EAX, regs[sib&7].l*/ + addbyte(0x45); + addbyte((uint8_t) cpu_state_offset(regs[sib & 7].l)); + addbyte(0x83); /*ADDL EAX, imm8*/ + addbyte(0xc0 | REG_EAX); + addbyte((int8_t) (rmdat >> 16)); (*op_pc)++; - - switch (mod) - { - case 0: - if ((sib & 7) == 5) - { - new_eaaddr = fastreadl(cs + (*op_pc) + 1); - addbyte(0xb8); /*MOVL EAX, imm32*/ - addlong(new_eaaddr); - (*op_pc) += 4; - } - else - { - addbyte(0x8b); /*MOVL EAX, regs[sib&7].l*/ - addbyte(0x45); - addbyte((uint8_t)cpu_state_offset(regs[sib & 7].l)); - } - break; - case 1: - addbyte(0x8b); /*MOVL EAX, regs[sib&7].l*/ - addbyte(0x45); - addbyte((uint8_t)cpu_state_offset(regs[sib & 7].l)); - addbyte(0x83); /*ADDL EAX, imm8*/ - addbyte(0xc0 | REG_EAX); - addbyte((int8_t)(rmdat >> 16)); - (*op_pc)++; - break; - case 2: - new_eaaddr = fastreadl(cs + (*op_pc) + 1); - addbyte(0xb8); /*MOVL EAX, new_eaaddr*/ - addlong(new_eaaddr); - addbyte(0x03); /*ADDL EAX, regs[sib&7].l*/ - addbyte(0x45); - addbyte((uint8_t)cpu_state_offset(regs[sib & 7].l)); - (*op_pc) += 4; - break; - } - if (stack_offset && (sib & 7) == 4 && (mod || (sib & 7) != 5)) /*ESP*/ - { - if (stack_offset < 0x80 || stack_offset >= 0xffffff80) - { - addbyte(0x83); - addbyte(0xc0 | REG_EAX); - addbyte(stack_offset); - } - else - { - addbyte(0x05); /*ADDL EAX, stack_offset*/ - addlong(stack_offset); - } - } - if (((sib & 7) == 4 || (mod && (sib & 7) == 5)) && !op_ssegs) - op_ea_seg = &cpu_state.seg_ss; - if (((sib >> 3) & 7) != 4) - { - switch (sib >> 6) - { - case 0: - addbyte(0x03); /*ADDL EAX, regs[sib&7].l*/ - addbyte(0x45); - addbyte((uint8_t)cpu_state_offset(regs[(sib >> 3) & 7].l)); - break; - case 1: - addbyte(0x8B); addbyte(0x45 | (REG_EDI << 3)); addbyte((uint8_t)cpu_state_offset(regs[(sib >> 3) & 7].l)); /*MOVL EDI, reg*/ - addbyte(0x01); addbyte(0xc0 | REG_EAX | (REG_EDI << 3)); /*ADDL EAX, EDI*/ - addbyte(0x01); addbyte(0xc0 | REG_EAX | (REG_EDI << 3)); /*ADDL EAX, EDI*/ - break; - case 2: - addbyte(0x8B); addbyte(0x45 | (REG_EDI << 3)); addbyte((uint8_t)cpu_state_offset(regs[(sib >> 3) & 7].l)); /*MOVL EDI, reg*/ - addbyte(0xC1); addbyte(0xE0 | REG_EDI); addbyte(2); /*SHL EDI, 2*/ - addbyte(0x01); addbyte(0xc0 | REG_EAX | (REG_EDI << 3)); /*ADDL EAX, EDI*/ - break; - case 3: - addbyte(0x8B); addbyte(0x45 | (REG_EDI << 3)); addbyte((uint8_t)cpu_state_offset(regs[(sib >> 3) & 7].l)); /*MOVL EDI reg*/ - addbyte(0xC1); addbyte(0xE0 | REG_EDI); addbyte(3); /*SHL EDI, 3*/ - addbyte(0x01); addbyte(0xc0 | REG_EAX | (REG_EDI << 3)); /*ADDL EAX, EDI*/ - break; - } - } - } - else - { - if (!mod && rm == 5) - { - new_eaaddr = fastreadl(cs + (*op_pc) + 1); - addbyte(0xb8); /*MOVL EAX, imm32*/ - addlong(new_eaaddr); - (*op_pc) += 4; - return op_ea_seg; - } - addbyte(0x8b); /*MOVL EAX, regs[rm].l*/ - addbyte(0x45); - addbyte((uint8_t)cpu_state_offset(regs[rm].l)); - cpu_state.eaaddr = cpu_state.regs[rm].l; - if (mod) - { - if (rm == 5 && !op_ssegs) - op_ea_seg = &cpu_state.seg_ss; - if (mod == 1) - { - addbyte(0x83); /*ADD EAX, imm8*/ - addbyte(0xc0 | REG_EAX); - addbyte((int8_t)(fetchdat >> 8)); - (*op_pc)++; - } - else - { - new_eaaddr = fastreadl(cs + (*op_pc) + 1); - addbyte(0x05); /*ADD EAX, imm32*/ - addlong(new_eaaddr); - (*op_pc) += 4; - } - } - } - return op_ea_seg; -} - -static inline x86seg *FETCH_EA(x86seg *op_ea_seg, uint32_t fetchdat, int op_ssegs, uint32_t *op_pc, uint32_t op_32) -{ - if (op_32 & 0x200) - return FETCH_EA_32(op_ea_seg, fetchdat, op_ssegs, op_pc, 0); - return FETCH_EA_16(op_ea_seg, fetchdat, op_ssegs, op_pc); -} - - -static inline void LOAD_STACK_TO_EA(int off) -{ - if (stack32) - { - addbyte(0x8b); /*MOVL EAX,[ESP]*/ - addbyte(0x45 | (REG_EAX << 3)); - addbyte((uint8_t)cpu_state_offset(regs[REG_ESP].l)); - if (off) - { - addbyte(0x83); /*ADD EAX, off*/ - addbyte(0xc0 | (0 << 3) | REG_EAX); - addbyte(off); - } - } - else - { - addbyte(0x0f); /*MOVZX EAX,W[ESP]*/ - addbyte(0xb7); - addbyte(0x45 | (REG_EAX << 3)); - addbyte((uint8_t)cpu_state_offset(regs[REG_ESP].w)); - if (off) - { - addbyte(0x66); /*ADD AX, off*/ - addbyte(0x05); - addword(off); - } - } -} - -static inline void LOAD_EBP_TO_EA(int off) -{ - if (stack32) - { - addbyte(0x8b); /*MOVL EAX,[EBP]*/ - addbyte(0x45 | (REG_EAX << 3)); - addbyte((uint8_t)cpu_state_offset(regs[REG_EBP].l)); - if (off) - { - addbyte(0x83); /*ADD EAX, off*/ - addbyte(0xc0 | (0 << 3) | REG_EAX); - addbyte(off); - } - } - else - { - addbyte(0x0f); /*MOVZX EAX,W[EBP]*/ - addbyte(0xb7); - addbyte(0x45 | (REG_EAX << 3)); - addbyte((uint8_t)cpu_state_offset(regs[REG_EBP].w)); - if (off) - { - addbyte(0x66); /*ADD AX, off*/ - addbyte(0x05); - addword(off); - } - } -} - -static inline void SP_MODIFY(int off) -{ - if (stack32) - { - if (off < 0x80) - { - addbyte(0x83); /*ADD [ESP], off*/ - addbyte(0x45); - addbyte((uint8_t)cpu_state_offset(regs[REG_ESP].l)); - addbyte(off); - } - else - { - addbyte(0x81); /*ADD [ESP], off*/ - addbyte(0x45); - addbyte((uint8_t)cpu_state_offset(regs[REG_ESP].l)); - addlong(off); - } - } - else - { - if (off < 0x80) - { - addbyte(0x66); /*ADD [SP], off*/ - addbyte(0x83); - addbyte(0x45); - addbyte((uint8_t)cpu_state_offset(regs[REG_ESP].w)); - addbyte(off); - } - else - { - addbyte(0x66); /*ADD [SP], off*/ - addbyte(0x81); - addbyte(0x45); - addbyte((uint8_t)cpu_state_offset(regs[REG_ESP].w)); - addword(off); - } - } -} - - -static inline void TEST_ZERO_JUMP_W(int host_reg, uint32_t new_pc, int taken_cycles) -{ - addbyte(0x66); /*CMPW host_reg, 0*/ - addbyte(0x83); - addbyte(0xc0 | 0x38 | host_reg); - addbyte(0); - addbyte(0x75); /*JNZ +*/ - addbyte(7+5+(taken_cycles ? 4 : 0)); - addbyte(0xC7); /*MOVL [pc], new_pc*/ - addbyte(0x45); - addbyte((uint8_t)cpu_state_offset(pc)); - addlong(new_pc); - if (taken_cycles) - { - addbyte(0x83); /*SUB $codegen_block_cycles, cyclcs*/ - addbyte(0x6d); - addbyte((uint8_t)cpu_state_offset(_cycles)); - addbyte(taken_cycles); - } - addbyte(0xe9); /*JMP end*/ - addlong(BLOCK_EXIT_OFFSET - (block_pos + 4)); -} -static inline void TEST_ZERO_JUMP_L(int host_reg, uint32_t new_pc, int taken_cycles) -{ - addbyte(0x83); /*CMPW host_reg, 0*/ - addbyte(0xc0 | 0x38 | host_reg); - addbyte(0); - addbyte(0x75); /*JNZ +*/ - addbyte(7+5+(taken_cycles ? 4 : 0)); - addbyte(0xC7); /*MOVL [pc], new_pc*/ - addbyte(0x45); - addbyte((uint8_t)cpu_state_offset(pc)); - addlong(new_pc); - if (taken_cycles) - { - addbyte(0x83); /*SUB $codegen_block_cycles, cyclcs*/ - addbyte(0x6d); - addbyte((uint8_t)cpu_state_offset(_cycles)); - addbyte(taken_cycles); - } - addbyte(0xe9); /*JMP end*/ - addlong(BLOCK_EXIT_OFFSET - (block_pos + 4)); -} - -static inline void TEST_NONZERO_JUMP_W(int host_reg, uint32_t new_pc, int taken_cycles) -{ - addbyte(0x66); /*CMPW host_reg, 0*/ - addbyte(0x83); - addbyte(0xc0 | 0x38 | host_reg); - addbyte(0); - addbyte(0x74); /*JZ +*/ - addbyte(7+5+(taken_cycles ? 4 : 0)); - addbyte(0xC7); /*MOVL [pc], new_pc*/ - addbyte(0x45); - addbyte((uint8_t)cpu_state_offset(pc)); - addlong(new_pc); - if (taken_cycles) - { - addbyte(0x83); /*SUB $codegen_block_cycles, cyclcs*/ - addbyte(0x6d); - addbyte((uint8_t)cpu_state_offset(_cycles)); - addbyte(taken_cycles); - } - addbyte(0xe9); /*JMP end*/ - addlong(BLOCK_EXIT_OFFSET - (block_pos + 4)); -} -static inline void TEST_NONZERO_JUMP_L(int host_reg, uint32_t new_pc, int taken_cycles) -{ - addbyte(0x83); /*CMPW host_reg, 0*/ - addbyte(0xc0 | 0x38 | host_reg); - addbyte(0); - addbyte(0x74); /*JZ +*/ - addbyte(7+5+(taken_cycles ? 4 : 0)); - addbyte(0xC7); /*MOVL [pc], new_pc*/ - addbyte(0x45); - addbyte((uint8_t)cpu_state_offset(pc)); - addlong(new_pc); - if (taken_cycles) - { - addbyte(0x83); /*SUB $codegen_block_cycles, cyclcs*/ - addbyte(0x6d); - addbyte((uint8_t)cpu_state_offset(_cycles)); - addbyte(taken_cycles); - } - addbyte(0xe9); /*JMP end*/ - addlong(BLOCK_EXIT_OFFSET - (block_pos + 4)); -} - -static inline void BRANCH_COND_BE(int pc_offset, uint32_t op_pc, uint32_t offset, int not) -{ - switch (codegen_flags_changed ? cpu_state.flags_op : FLAGS_UNKNOWN) - { - case FLAGS_SUB8: - addbyte(0x8a); /*MOV AL, flags_op1*/ - addbyte(0x45); - addbyte((uint8_t)cpu_state_offset(flags_op1)); - addbyte(0x3a); /*CMP AL, flags_op2*/ - addbyte(0x45); - addbyte((uint8_t)cpu_state_offset(flags_op2)); - if (not) - addbyte(0x76); /*JBE*/ - else - addbyte(0x77); /*JNBE*/ break; - case FLAGS_SUB16: - addbyte(0x66); /*MOV AX, flags_op1*/ - addbyte(0x8b); + case 2: + new_eaaddr = fastreadl(cs + (*op_pc) + 1); + addbyte(0xb8); /*MOVL EAX, new_eaaddr*/ + addlong(new_eaaddr); + addbyte(0x03); /*ADDL EAX, regs[sib&7].l*/ addbyte(0x45); - addbyte((uint8_t)cpu_state_offset(flags_op1)); - addbyte(0x66); /*CMP AX, flags_op2*/ - addbyte(0x3b); - addbyte(0x45); - addbyte((uint8_t)cpu_state_offset(flags_op2)); - if (not) - addbyte(0x76); /*JBE*/ - else - addbyte(0x77); /*JNBE*/ + addbyte((uint8_t) cpu_state_offset(regs[sib & 7].l)); + (*op_pc) += 4; break; - case FLAGS_SUB32: - addbyte(0x8b); /*MOV EAX, flags_op1*/ - addbyte(0x45); - addbyte((uint8_t)cpu_state_offset(flags_op1)); - addbyte(0x3b); /*CMP EAX, flags_op2*/ - addbyte(0x45); - addbyte((uint8_t)cpu_state_offset(flags_op2)); - if (not) - addbyte(0x76); /*JBE*/ - else - addbyte(0x77); /*JNBE*/ - break; - - default: - if (codegen_flags_changed && cpu_state.flags_op != FLAGS_UNKNOWN) - { - addbyte(0x83); /*CMP flags_res, 0*/ - addbyte(0x7d); - addbyte((uint8_t)cpu_state_offset(flags_res)); - addbyte(0); - addbyte(0x74); /*JZ +*/ - } - else - { - CALL_FUNC((uintptr_t)ZF_SET); - addbyte(0x85); /*TEST EAX,EAX*/ - addbyte(0xc0); - addbyte(0x75); /*JNZ +*/ - } - if (not) - addbyte(5+2+2+7+5+(timing_bt ? 4 : 0)); - else - addbyte(5+2+2); - CALL_FUNC((uintptr_t)CF_SET); + } + if (stack_offset && (sib & 7) == 4 && (mod || (sib & 7) != 5)) /*ESP*/ + { + if (stack_offset < 0x80 || stack_offset >= 0xffffff80) { + addbyte(0x83); + addbyte(0xc0 | REG_EAX); + addbyte(stack_offset); + } else { + addbyte(0x05); /*ADDL EAX, stack_offset*/ + addlong(stack_offset); + } + } + if (((sib & 7) == 4 || (mod && (sib & 7) == 5)) && !op_ssegs) + op_ea_seg = &cpu_state.seg_ss; + if (((sib >> 3) & 7) != 4) { + switch (sib >> 6) { + case 0: + addbyte(0x03); /*ADDL EAX, regs[sib&7].l*/ + addbyte(0x45); + addbyte((uint8_t) cpu_state_offset(regs[(sib >> 3) & 7].l)); + break; + case 1: + addbyte(0x8B); + addbyte(0x45 | (REG_EDI << 3)); + addbyte((uint8_t) cpu_state_offset(regs[(sib >> 3) & 7].l)); /*MOVL EDI, reg*/ + addbyte(0x01); + addbyte(0xc0 | REG_EAX | (REG_EDI << 3)); /*ADDL EAX, EDI*/ + addbyte(0x01); + addbyte(0xc0 | REG_EAX | (REG_EDI << 3)); /*ADDL EAX, EDI*/ + break; + case 2: + addbyte(0x8B); + addbyte(0x45 | (REG_EDI << 3)); + addbyte((uint8_t) cpu_state_offset(regs[(sib >> 3) & 7].l)); /*MOVL EDI, reg*/ + addbyte(0xC1); + addbyte(0xE0 | REG_EDI); + addbyte(2); /*SHL EDI, 2*/ + addbyte(0x01); + addbyte(0xc0 | REG_EAX | (REG_EDI << 3)); /*ADDL EAX, EDI*/ + break; + case 3: + addbyte(0x8B); + addbyte(0x45 | (REG_EDI << 3)); + addbyte((uint8_t) cpu_state_offset(regs[(sib >> 3) & 7].l)); /*MOVL EDI reg*/ + addbyte(0xC1); + addbyte(0xE0 | REG_EDI); + addbyte(3); /*SHL EDI, 3*/ + addbyte(0x01); + addbyte(0xc0 | REG_EAX | (REG_EDI << 3)); /*ADDL EAX, EDI*/ + break; + } + } + } else { + if (!mod && rm == 5) { + new_eaaddr = fastreadl(cs + (*op_pc) + 1); + addbyte(0xb8); /*MOVL EAX, imm32*/ + addlong(new_eaaddr); + (*op_pc) += 4; + return op_ea_seg; + } + addbyte(0x8b); /*MOVL EAX, regs[rm].l*/ + addbyte(0x45); + addbyte((uint8_t) cpu_state_offset(regs[rm].l)); + cpu_state.eaaddr = cpu_state.regs[rm].l; + if (mod) { + if (rm == 5 && !op_ssegs) + op_ea_seg = &cpu_state.seg_ss; + if (mod == 1) { + addbyte(0x83); /*ADD EAX, imm8*/ + addbyte(0xc0 | REG_EAX); + addbyte((int8_t) (fetchdat >> 8)); + (*op_pc)++; + } else { + new_eaaddr = fastreadl(cs + (*op_pc) + 1); + addbyte(0x05); /*ADD EAX, imm32*/ + addlong(new_eaaddr); + (*op_pc) += 4; + } + } + } + return op_ea_seg; +} + +static __inline x86seg * +FETCH_EA(x86seg *op_ea_seg, uint32_t fetchdat, int op_ssegs, uint32_t *op_pc, uint32_t op_32) +{ + if (op_32 & 0x200) + return FETCH_EA_32(op_ea_seg, fetchdat, op_ssegs, op_pc, 0); + return FETCH_EA_16(op_ea_seg, fetchdat, op_ssegs, op_pc); +} + +static __inline void +LOAD_STACK_TO_EA(int off) +{ + if (stack32) { + addbyte(0x8b); /*MOVL EAX,[ESP]*/ + addbyte(0x45 | (REG_EAX << 3)); + addbyte((uint8_t) cpu_state_offset(regs[REG_ESP].l)); + if (off) { + addbyte(0x83); /*ADD EAX, off*/ + addbyte(0xc0 | (0 << 3) | REG_EAX); + addbyte(off); + } + } else { + addbyte(0x0f); /*MOVZX EAX,W[ESP]*/ + addbyte(0xb7); + addbyte(0x45 | (REG_EAX << 3)); + addbyte((uint8_t) cpu_state_offset(regs[REG_ESP].w)); + if (off) { + addbyte(0x66); /*ADD AX, off*/ + addbyte(0x05); + addword(off); + } + } +} + +static __inline void +LOAD_EBP_TO_EA(int off) +{ + if (stack32) { + addbyte(0x8b); /*MOVL EAX,[EBP]*/ + addbyte(0x45 | (REG_EAX << 3)); + addbyte((uint8_t) cpu_state_offset(regs[REG_EBP].l)); + if (off) { + addbyte(0x83); /*ADD EAX, off*/ + addbyte(0xc0 | (0 << 3) | REG_EAX); + addbyte(off); + } + } else { + addbyte(0x0f); /*MOVZX EAX,W[EBP]*/ + addbyte(0xb7); + addbyte(0x45 | (REG_EAX << 3)); + addbyte((uint8_t) cpu_state_offset(regs[REG_EBP].w)); + if (off) { + addbyte(0x66); /*ADD AX, off*/ + addbyte(0x05); + addword(off); + } + } +} + +static __inline void +SP_MODIFY(int off) +{ + if (stack32) { + if (off < 0x80) { + addbyte(0x83); /*ADD [ESP], off*/ + addbyte(0x45); + addbyte((uint8_t) cpu_state_offset(regs[REG_ESP].l)); + addbyte(off); + } else { + addbyte(0x81); /*ADD [ESP], off*/ + addbyte(0x45); + addbyte((uint8_t) cpu_state_offset(regs[REG_ESP].l)); + addlong(off); + } + } else { + if (off < 0x80) { + addbyte(0x66); /*ADD [SP], off*/ + addbyte(0x83); + addbyte(0x45); + addbyte((uint8_t) cpu_state_offset(regs[REG_ESP].w)); + addbyte(off); + } else { + addbyte(0x66); /*ADD [SP], off*/ + addbyte(0x81); + addbyte(0x45); + addbyte((uint8_t) cpu_state_offset(regs[REG_ESP].w)); + addword(off); + } + } +} + +static __inline void +TEST_ZERO_JUMP_W(int host_reg, uint32_t new_pc, int taken_cycles) +{ + addbyte(0x66); /*CMPW host_reg, 0*/ + addbyte(0x83); + addbyte(0xc0 | 0x38 | host_reg); + addbyte(0); + addbyte(0x75); /*JNZ +*/ + addbyte(7 + 5 + (taken_cycles ? 4 : 0)); + addbyte(0xC7); /*MOVL [pc], new_pc*/ + addbyte(0x45); + addbyte((uint8_t) cpu_state_offset(pc)); + addlong(new_pc); + if (taken_cycles) { + addbyte(0x83); /*SUB $codegen_block_cycles, cyclcs*/ + addbyte(0x6d); + addbyte((uint8_t) cpu_state_offset(_cycles)); + addbyte(taken_cycles); + } + addbyte(0xe9); /*JMP end*/ + addlong(BLOCK_EXIT_OFFSET - (block_pos + 4)); +} +static __inline void +TEST_ZERO_JUMP_L(int host_reg, uint32_t new_pc, int taken_cycles) +{ + addbyte(0x83); /*CMPW host_reg, 0*/ + addbyte(0xc0 | 0x38 | host_reg); + addbyte(0); + addbyte(0x75); /*JNZ +*/ + addbyte(7 + 5 + (taken_cycles ? 4 : 0)); + addbyte(0xC7); /*MOVL [pc], new_pc*/ + addbyte(0x45); + addbyte((uint8_t) cpu_state_offset(pc)); + addlong(new_pc); + if (taken_cycles) { + addbyte(0x83); /*SUB $codegen_block_cycles, cyclcs*/ + addbyte(0x6d); + addbyte((uint8_t) cpu_state_offset(_cycles)); + addbyte(taken_cycles); + } + addbyte(0xe9); /*JMP end*/ + addlong(BLOCK_EXIT_OFFSET - (block_pos + 4)); +} + +static __inline void +TEST_NONZERO_JUMP_W(int host_reg, uint32_t new_pc, int taken_cycles) +{ + addbyte(0x66); /*CMPW host_reg, 0*/ + addbyte(0x83); + addbyte(0xc0 | 0x38 | host_reg); + addbyte(0); + addbyte(0x74); /*JZ +*/ + addbyte(7 + 5 + (taken_cycles ? 4 : 0)); + addbyte(0xC7); /*MOVL [pc], new_pc*/ + addbyte(0x45); + addbyte((uint8_t) cpu_state_offset(pc)); + addlong(new_pc); + if (taken_cycles) { + addbyte(0x83); /*SUB $codegen_block_cycles, cyclcs*/ + addbyte(0x6d); + addbyte((uint8_t) cpu_state_offset(_cycles)); + addbyte(taken_cycles); + } + addbyte(0xe9); /*JMP end*/ + addlong(BLOCK_EXIT_OFFSET - (block_pos + 4)); +} +static __inline void +TEST_NONZERO_JUMP_L(int host_reg, uint32_t new_pc, int taken_cycles) +{ + addbyte(0x83); /*CMPW host_reg, 0*/ + addbyte(0xc0 | 0x38 | host_reg); + addbyte(0); + addbyte(0x74); /*JZ +*/ + addbyte(7 + 5 + (taken_cycles ? 4 : 0)); + addbyte(0xC7); /*MOVL [pc], new_pc*/ + addbyte(0x45); + addbyte((uint8_t) cpu_state_offset(pc)); + addlong(new_pc); + if (taken_cycles) { + addbyte(0x83); /*SUB $codegen_block_cycles, cyclcs*/ + addbyte(0x6d); + addbyte((uint8_t) cpu_state_offset(_cycles)); + addbyte(taken_cycles); + } + addbyte(0xe9); /*JMP end*/ + addlong(BLOCK_EXIT_OFFSET - (block_pos + 4)); +} + +static __inline void +BRANCH_COND_BE(int pc_offset, uint32_t op_pc, uint32_t offset, int not ) +{ + switch (codegen_flags_changed ? cpu_state.flags_op : FLAGS_UNKNOWN) { + case FLAGS_SUB8: + addbyte(0x8a); /*MOV AL, flags_op1*/ + addbyte(0x45); + addbyte((uint8_t) cpu_state_offset(flags_op1)); + addbyte(0x3a); /*CMP AL, flags_op2*/ + addbyte(0x45); + addbyte((uint8_t) cpu_state_offset(flags_op2)); + if (not ) + addbyte(0x76); /*JBE*/ + else + addbyte(0x77); /*JNBE*/ + break; + case FLAGS_SUB16: + addbyte(0x66); /*MOV AX, flags_op1*/ + addbyte(0x8b); + addbyte(0x45); + addbyte((uint8_t) cpu_state_offset(flags_op1)); + addbyte(0x66); /*CMP AX, flags_op2*/ + addbyte(0x3b); + addbyte(0x45); + addbyte((uint8_t) cpu_state_offset(flags_op2)); + if (not ) + addbyte(0x76); /*JBE*/ + else + addbyte(0x77); /*JNBE*/ + break; + case FLAGS_SUB32: + addbyte(0x8b); /*MOV EAX, flags_op1*/ + addbyte(0x45); + addbyte((uint8_t) cpu_state_offset(flags_op1)); + addbyte(0x3b); /*CMP EAX, flags_op2*/ + addbyte(0x45); + addbyte((uint8_t) cpu_state_offset(flags_op2)); + if (not ) + addbyte(0x76); /*JBE*/ + else + addbyte(0x77); /*JNBE*/ + break; + + default: + if (codegen_flags_changed && cpu_state.flags_op != FLAGS_UNKNOWN) { + addbyte(0x83); /*CMP flags_res, 0*/ + addbyte(0x7d); + addbyte((uint8_t) cpu_state_offset(flags_res)); + addbyte(0); + addbyte(0x74); /*JZ +*/ + } else { + CALL_FUNC((uintptr_t) ZF_SET); addbyte(0x85); /*TEST EAX,EAX*/ addbyte(0xc0); - if (not) - addbyte(0x75); /*JNZ +*/ - else - addbyte(0x74); /*JZ +*/ - break; - } - addbyte(7+5+(timing_bt ? 4 : 0)); - addbyte(0xC7); /*MOVL [pc], new_pc*/ - addbyte(0x45); - addbyte((uint8_t)cpu_state_offset(pc)); - addlong(op_pc+pc_offset+offset); - if (timing_bt) - { - addbyte(0x83); /*SUB $codegen_block_cycles, cyclcs*/ - addbyte(0x6d); - addbyte((uint8_t)cpu_state_offset(_cycles)); - addbyte(timing_bt); - } - addbyte(0xe9); /*JMP end*/ - addlong(BLOCK_EXIT_OFFSET - (block_pos + 4)); + addbyte(0x75); /*JNZ +*/ + } + if (not ) + addbyte(5 + 2 + 2 + 7 + 5 + (timing_bt ? 4 : 0)); + else + addbyte(5 + 2 + 2); + CALL_FUNC((uintptr_t) CF_SET); + addbyte(0x85); /*TEST EAX,EAX*/ + addbyte(0xc0); + if (not ) + addbyte(0x75); /*JNZ +*/ + else + addbyte(0x74); /*JZ +*/ + break; + } + addbyte(7 + 5 + (timing_bt ? 4 : 0)); + addbyte(0xC7); /*MOVL [pc], new_pc*/ + addbyte(0x45); + addbyte((uint8_t) cpu_state_offset(pc)); + addlong(op_pc + pc_offset + offset); + if (timing_bt) { + addbyte(0x83); /*SUB $codegen_block_cycles, cyclcs*/ + addbyte(0x6d); + addbyte((uint8_t) cpu_state_offset(_cycles)); + addbyte(timing_bt); + } + addbyte(0xe9); /*JMP end*/ + addlong(BLOCK_EXIT_OFFSET - (block_pos + 4)); } -static inline void BRANCH_COND_L(int pc_offset, uint32_t op_pc, uint32_t offset, int not) +static __inline void +BRANCH_COND_L(int pc_offset, uint32_t op_pc, uint32_t offset, int not ) { - switch (codegen_flags_changed ? cpu_state.flags_op : FLAGS_UNKNOWN) - { - case FLAGS_SUB8: - addbyte(0x8a); /*MOV AL, flags_op1*/ - addbyte(0x45); - addbyte((uint8_t)cpu_state_offset(flags_op1)); - addbyte(0x3a); /*CMP AL, flags_op2*/ - addbyte(0x45); - addbyte((uint8_t)cpu_state_offset(flags_op2)); - if (not) - addbyte(0x7c); /*JL*/ - else - addbyte(0x7d); /*JNL*/ - break; - case FLAGS_SUB16: - addbyte(0x66); /*MOV AX, flags_op1*/ - addbyte(0x8b); - addbyte(0x45); - addbyte((uint8_t)cpu_state_offset(flags_op1)); - addbyte(0x66); /*CMP AX, flags_op2*/ - addbyte(0x3b); - addbyte(0x45); - addbyte((uint8_t)cpu_state_offset(flags_op2)); - if (not) - addbyte(0x7c); /*JL*/ - else - addbyte(0x7d); /*JNL*/ - break; - case FLAGS_SUB32: - addbyte(0x8b); /*MOV EAX, flags_op1*/ - addbyte(0x45); - addbyte((uint8_t)cpu_state_offset(flags_op1)); - addbyte(0x3b); /*CMP EAX, flags_op2*/ - addbyte(0x45); - addbyte((uint8_t)cpu_state_offset(flags_op2)); - if (not) - addbyte(0x7c); /*JL*/ - else - addbyte(0x7d); /*JNL*/ - break; + switch (codegen_flags_changed ? cpu_state.flags_op : FLAGS_UNKNOWN) { + case FLAGS_SUB8: + addbyte(0x8a); /*MOV AL, flags_op1*/ + addbyte(0x45); + addbyte((uint8_t) cpu_state_offset(flags_op1)); + addbyte(0x3a); /*CMP AL, flags_op2*/ + addbyte(0x45); + addbyte((uint8_t) cpu_state_offset(flags_op2)); + if (not ) + addbyte(0x7c); /*JL*/ + else + addbyte(0x7d); /*JNL*/ + break; + case FLAGS_SUB16: + addbyte(0x66); /*MOV AX, flags_op1*/ + addbyte(0x8b); + addbyte(0x45); + addbyte((uint8_t) cpu_state_offset(flags_op1)); + addbyte(0x66); /*CMP AX, flags_op2*/ + addbyte(0x3b); + addbyte(0x45); + addbyte((uint8_t) cpu_state_offset(flags_op2)); + if (not ) + addbyte(0x7c); /*JL*/ + else + addbyte(0x7d); /*JNL*/ + break; + case FLAGS_SUB32: + addbyte(0x8b); /*MOV EAX, flags_op1*/ + addbyte(0x45); + addbyte((uint8_t) cpu_state_offset(flags_op1)); + addbyte(0x3b); /*CMP EAX, flags_op2*/ + addbyte(0x45); + addbyte((uint8_t) cpu_state_offset(flags_op2)); + if (not ) + addbyte(0x7c); /*JL*/ + else + addbyte(0x7d); /*JNL*/ + break; - default: - CALL_FUNC((uintptr_t)NF_SET); - addbyte(0x85); /*TEST EAX,EAX*/ - addbyte(0xc0); - addbyte(0x0f); /*SETNE BL*/ - addbyte(0x95); - addbyte(0xc3); - CALL_FUNC((uintptr_t)VF_SET); - addbyte(0x85); /*TEST EAX,EAX*/ - addbyte(0xc0); - addbyte(0x0f); /*SETNE AL*/ - addbyte(0x95); - addbyte(0xc0); - addbyte(0x38); /*CMP AL, BL*/ - addbyte(0xd8); - if (not) - addbyte(0x75); /*JNZ +*/ - else - addbyte(0x74); /*JZ +*/ - break; - } - addbyte(7+5+(timing_bt ? 4 : 0)); - addbyte(0xC7); /*MOVL [pc], new_pc*/ - addbyte(0x45); - addbyte((uint8_t)cpu_state_offset(pc)); - addlong(op_pc+pc_offset+offset); - if (timing_bt) - { - addbyte(0x83); /*SUB $codegen_block_cycles, cyclcs*/ - addbyte(0x6d); - addbyte((uint8_t)cpu_state_offset(_cycles)); - addbyte(timing_bt); - } - addbyte(0xe9); /*JMP end*/ - addlong(BLOCK_EXIT_OFFSET - (block_pos + 4)); + default: + CALL_FUNC((uintptr_t) NF_SET); + addbyte(0x85); /*TEST EAX,EAX*/ + addbyte(0xc0); + addbyte(0x0f); /*SETNE BL*/ + addbyte(0x95); + addbyte(0xc3); + CALL_FUNC((uintptr_t) VF_SET); + addbyte(0x85); /*TEST EAX,EAX*/ + addbyte(0xc0); + addbyte(0x0f); /*SETNE AL*/ + addbyte(0x95); + addbyte(0xc0); + addbyte(0x38); /*CMP AL, BL*/ + addbyte(0xd8); + if (not ) + addbyte(0x75); /*JNZ +*/ + else + addbyte(0x74); /*JZ +*/ + break; + } + addbyte(7 + 5 + (timing_bt ? 4 : 0)); + addbyte(0xC7); /*MOVL [pc], new_pc*/ + addbyte(0x45); + addbyte((uint8_t) cpu_state_offset(pc)); + addlong(op_pc + pc_offset + offset); + if (timing_bt) { + addbyte(0x83); /*SUB $codegen_block_cycles, cyclcs*/ + addbyte(0x6d); + addbyte((uint8_t) cpu_state_offset(_cycles)); + addbyte(timing_bt); + } + addbyte(0xe9); /*JMP end*/ + addlong(BLOCK_EXIT_OFFSET - (block_pos + 4)); } -static inline void BRANCH_COND_LE(int pc_offset, uint32_t op_pc, uint32_t offset, int not) +static __inline void +BRANCH_COND_LE(int pc_offset, uint32_t op_pc, uint32_t offset, int not ) { - switch (codegen_flags_changed ? cpu_state.flags_op : FLAGS_UNKNOWN) - { - case FLAGS_SUB8: - addbyte(0x8a); /*MOV AL, flags_op1*/ - addbyte(0x45); - addbyte((uint8_t)cpu_state_offset(flags_op1)); - addbyte(0x3a); /*CMP AL, flags_op2*/ - addbyte(0x45); - addbyte((uint8_t)cpu_state_offset(flags_op2)); - if (not) - addbyte(0x7e); /*JLE*/ - else - addbyte(0x7f); /*JNLE*/ - break; - case FLAGS_SUB16: - addbyte(0x66); /*MOV AX, flags_op1*/ - addbyte(0x8b); - addbyte(0x45); - addbyte((uint8_t)cpu_state_offset(flags_op1)); - addbyte(0x66); /*CMP AX, flags_op2*/ - addbyte(0x3b); - addbyte(0x45); - addbyte((uint8_t)cpu_state_offset(flags_op2)); - if (not) - addbyte(0x7e); /*JLE*/ - else - addbyte(0x7f); /*JNLE*/ - break; - case FLAGS_SUB32: - addbyte(0x8b); /*MOV EAX, flags_op1*/ - addbyte(0x45); - addbyte((uint8_t)cpu_state_offset(flags_op1)); - addbyte(0x3b); /*CMP EAX, flags_op2*/ - addbyte(0x45); - addbyte((uint8_t)cpu_state_offset(flags_op2)); - if (not) - addbyte(0x7e); /*JLE*/ - else - addbyte(0x7f); /*JNLE*/ - break; + switch (codegen_flags_changed ? cpu_state.flags_op : FLAGS_UNKNOWN) { + case FLAGS_SUB8: + addbyte(0x8a); /*MOV AL, flags_op1*/ + addbyte(0x45); + addbyte((uint8_t) cpu_state_offset(flags_op1)); + addbyte(0x3a); /*CMP AL, flags_op2*/ + addbyte(0x45); + addbyte((uint8_t) cpu_state_offset(flags_op2)); + if (not ) + addbyte(0x7e); /*JLE*/ + else + addbyte(0x7f); /*JNLE*/ + break; + case FLAGS_SUB16: + addbyte(0x66); /*MOV AX, flags_op1*/ + addbyte(0x8b); + addbyte(0x45); + addbyte((uint8_t) cpu_state_offset(flags_op1)); + addbyte(0x66); /*CMP AX, flags_op2*/ + addbyte(0x3b); + addbyte(0x45); + addbyte((uint8_t) cpu_state_offset(flags_op2)); + if (not ) + addbyte(0x7e); /*JLE*/ + else + addbyte(0x7f); /*JNLE*/ + break; + case FLAGS_SUB32: + addbyte(0x8b); /*MOV EAX, flags_op1*/ + addbyte(0x45); + addbyte((uint8_t) cpu_state_offset(flags_op1)); + addbyte(0x3b); /*CMP EAX, flags_op2*/ + addbyte(0x45); + addbyte((uint8_t) cpu_state_offset(flags_op2)); + if (not ) + addbyte(0x7e); /*JLE*/ + else + addbyte(0x7f); /*JNLE*/ + break; - default: - if (codegen_flags_changed && cpu_state.flags_op != FLAGS_UNKNOWN) - { - addbyte(0x83); /*CMP flags_res, 0*/ - addbyte(0x7d); - addbyte((uint8_t)cpu_state_offset(flags_res)); - addbyte(0); - addbyte(0x74); /*JZ +*/ - } - else - { - CALL_FUNC((uintptr_t)ZF_SET); - addbyte(0x85); /*TEST EAX,EAX*/ - addbyte(0xc0); - addbyte(0x75); /*JNZ +*/ - } - if (not) - addbyte(5+2+3+5+2+3+2+2+7+5+(timing_bt ? 4 : 0)); - else - addbyte(5+2+3+5+2+3+2+2); - - CALL_FUNC((uintptr_t)NF_SET); + default: + if (codegen_flags_changed && cpu_state.flags_op != FLAGS_UNKNOWN) { + addbyte(0x83); /*CMP flags_res, 0*/ + addbyte(0x7d); + addbyte((uint8_t) cpu_state_offset(flags_res)); + addbyte(0); + addbyte(0x74); /*JZ +*/ + } else { + CALL_FUNC((uintptr_t) ZF_SET); addbyte(0x85); /*TEST EAX,EAX*/ addbyte(0xc0); - addbyte(0x0f); /*SETNE BL*/ - addbyte(0x95); - addbyte(0xc3); - CALL_FUNC((uintptr_t)VF_SET); - addbyte(0x85); /*TEST EAX,EAX*/ - addbyte(0xc0); - addbyte(0x0f); /*SETNE AL*/ - addbyte(0x95); - addbyte(0xc0); - addbyte(0x38); /*CMP AL, BL*/ - addbyte(0xd8); - if (not) - addbyte(0x75); /*JNZ +*/ - else - addbyte(0x74); /*JZ +*/ - break; - } - addbyte(7+5+(timing_bt ? 4 : 0)); - addbyte(0xC7); /*MOVL [pc], new_pc*/ - addbyte(0x45); - addbyte((uint8_t)cpu_state_offset(pc)); - addlong(op_pc+pc_offset+offset); - if (timing_bt) - { - addbyte(0x83); /*SUB $codegen_block_cycles, cyclcs*/ - addbyte(0x6d); - addbyte((uint8_t)cpu_state_offset(_cycles)); - addbyte(timing_bt); - } - addbyte(0xe9); /*JMP end*/ - addlong(BLOCK_EXIT_OFFSET - (block_pos + 4)); + addbyte(0x75); /*JNZ +*/ + } + if (not ) + addbyte(5 + 2 + 3 + 5 + 2 + 3 + 2 + 2 + 7 + 5 + (timing_bt ? 4 : 0)); + else + addbyte(5 + 2 + 3 + 5 + 2 + 3 + 2 + 2); + + CALL_FUNC((uintptr_t) NF_SET); + addbyte(0x85); /*TEST EAX,EAX*/ + addbyte(0xc0); + addbyte(0x0f); /*SETNE BL*/ + addbyte(0x95); + addbyte(0xc3); + CALL_FUNC((uintptr_t) VF_SET); + addbyte(0x85); /*TEST EAX,EAX*/ + addbyte(0xc0); + addbyte(0x0f); /*SETNE AL*/ + addbyte(0x95); + addbyte(0xc0); + addbyte(0x38); /*CMP AL, BL*/ + addbyte(0xd8); + if (not ) + addbyte(0x75); /*JNZ +*/ + else + addbyte(0x74); /*JZ +*/ + break; + } + addbyte(7 + 5 + (timing_bt ? 4 : 0)); + addbyte(0xC7); /*MOVL [pc], new_pc*/ + addbyte(0x45); + addbyte((uint8_t) cpu_state_offset(pc)); + addlong(op_pc + pc_offset + offset); + if (timing_bt) { + addbyte(0x83); /*SUB $codegen_block_cycles, cyclcs*/ + addbyte(0x6d); + addbyte((uint8_t) cpu_state_offset(_cycles)); + addbyte(timing_bt); + } + addbyte(0xe9); /*JMP end*/ + addlong(BLOCK_EXIT_OFFSET - (block_pos + 4)); } - -static inline void FP_ENTER() +static __inline void +FP_ENTER(void) { - if (codegen_fpu_entered) - return; - - addbyte(0xf6); /*TEST cr0, 0xc*/ + if (codegen_fpu_entered) + return; + + addbyte(0xf6); /*TEST cr0, 0xc*/ + addbyte(0x05); + addlong((uintptr_t) &cr0); + addbyte(0xc); + addbyte(0x74); /*JZ +*/ + addbyte(7 + 7 + 5 + 5); + addbyte(0xC7); /*MOVL [oldpc],op_old_pc*/ + addbyte(0x45); + addbyte((uint8_t) cpu_state_offset(oldpc)); + addlong(op_old_pc); + addbyte(0xc7); /*MOV [ESP], 7*/ + addbyte(0x04); + addbyte(0x24); + addlong(7); + addbyte(0xe8); /*CALL x86_int*/ + addlong((uint32_t) x86_int - (uint32_t) (&codeblock[block_current].data[block_pos + 4])); + addbyte(0xe9); /*JMP end*/ + addlong(BLOCK_EXIT_OFFSET - (block_pos + 4)); + + codegen_fpu_entered = 1; +} + +static __inline void +FP_FLD(int reg) +{ + if (codeblock[block_current].flags & CODEBLOCK_STATIC_TOP) { + addbyte(0xf3); /*MOVQ XMM0, ST[reg][EBP]*/ + addbyte(0x0f); + addbyte(0x7e); + addbyte(0x45); + addbyte((uint8_t) cpu_state_offset(ST[(cpu_state.TOP + reg) & 7])); + addbyte(0xc6); /*MOVB TOP[EBP], (TOP-1) & 7*/ + addbyte(0x45); + addbyte((uint8_t) cpu_state_offset(TOP)); + addbyte((cpu_state.TOP - 1) & 7); + addbyte(0xf3); /*MOVQ XMM1, MM[reg][EBP]*/ + addbyte(0x0f); + addbyte(0x7e); + addbyte(0x4d); + addbyte((uint8_t) cpu_state_offset(MM[(cpu_state.TOP + reg) & 7].q)); + addbyte(0x66); /*MOVQ ST[-1][EBP], XMM0*/ + addbyte(0x0f); + addbyte(0xd6); + addbyte(0x45); + addbyte((uint8_t) cpu_state_offset(ST[(cpu_state.TOP - 1) & 7])); + addbyte(0x8a); /*MOV AL, tag[reg][EBP]*/ + addbyte(0x45); + addbyte((uint8_t) cpu_state_offset(tag[(cpu_state.TOP + reg) & 7])); + addbyte(0x66); /*MOVQ MM[-1][EBP], XMM1*/ + addbyte(0x0f); + addbyte(0xd6); + addbyte(0x4d); + addbyte((uint8_t) cpu_state_offset(MM[(cpu_state.TOP - 1) & 7].q)); + addbyte(0x88); /*MOV tag[-1][EBP], AL*/ + addbyte(0x45); + addbyte((uint8_t) cpu_state_offset(tag[(cpu_state.TOP - 1) & 7])); + } else { + addbyte(0x8b); /*MOV EAX, [TOP]*/ + addbyte(0x45); + addbyte((uint8_t) cpu_state_offset(TOP)); + addbyte(0x89); /*MOV EBX, EAX*/ + addbyte(0xc3); + if (reg) { + addbyte(0x83); /*ADD EAX, reg*/ + addbyte(0xc0); + addbyte(reg); + addbyte(0x83); /*SUB EBX, 1*/ + addbyte(0xeb); + addbyte(0x01); + addbyte(0x83); /*AND EAX, 7*/ + addbyte(0xe0); + addbyte(0x07); + } else { + addbyte(0x83); /*SUB EBX, 1*/ + addbyte(0xeb); + addbyte(0x01); + } + + addbyte(0xdd); /*FLD [ST+EAX*8]*/ + addbyte(0x44); + addbyte(0xc5); + addbyte((uint8_t) cpu_state_offset(ST)); + addbyte(0x83); /*AND EBX, 7*/ + addbyte(0xe3); + addbyte(0x07); + addbyte(0x8b); /*MOV EDX, [ST_i64+EAX]*/ + addbyte(0x54); + addbyte(0xc5); + addbyte((uint8_t) cpu_state_offset(MM)); + addbyte(0x8b); /*MOV ECX, [ST_i64+4+EAX]*/ + addbyte(0x4c); + addbyte(0xc5); + addbyte((uint8_t) cpu_state_offset(MM) + 4); + addbyte(0x8a); /*MOV AL, [tag+EAX]*/ + addbyte(0x44); addbyte(0x05); - addlong((uintptr_t)&cr0); - addbyte(0xc); - addbyte(0x74); /*JZ +*/ - addbyte(7+7+5+5); - addbyte(0xC7); /*MOVL [oldpc],op_old_pc*/ - addbyte(0x45); - addbyte((uint8_t)cpu_state_offset(oldpc)); - addlong(op_old_pc); - addbyte(0xc7); /*MOV [ESP], 7*/ - addbyte(0x04); - addbyte(0x24); - addlong(7); - addbyte(0xe8); /*CALL x86_int*/ - addlong((uint32_t)x86_int - (uint32_t)(&codeblock[block_current].data[block_pos + 4])); - addbyte(0xe9); /*JMP end*/ - addlong(BLOCK_EXIT_OFFSET - (block_pos + 4)); - - codegen_fpu_entered = 1; -} - -static inline void FP_FLD(int reg) -{ - if (codeblock[block_current].flags & CODEBLOCK_STATIC_TOP) - { - addbyte(0xf3); /*MOVQ XMM0, ST[reg][EBP]*/ - addbyte(0x0f); - addbyte(0x7e); - addbyte(0x45); - addbyte((uint8_t)cpu_state_offset(ST[(cpu_state.TOP + reg) & 7])); - addbyte(0xc6); /*MOVB TOP[EBP], (TOP-1) & 7*/ - addbyte(0x45); - addbyte((uint8_t)cpu_state_offset(TOP)); - addbyte((cpu_state.TOP - 1) & 7); - addbyte(0xf3); /*MOVQ XMM1, MM[reg][EBP]*/ - addbyte(0x0f); - addbyte(0x7e); - addbyte(0x4d); - addbyte((uint8_t)cpu_state_offset(MM[(cpu_state.TOP + reg) & 7].q)); - addbyte(0x66); /*MOVQ ST[-1][EBP], XMM0*/ - addbyte(0x0f); - addbyte(0xd6); - addbyte(0x45); - addbyte((uint8_t)cpu_state_offset(ST[(cpu_state.TOP - 1) & 7])); - addbyte(0x8a); /*MOV AL, tag[reg][EBP]*/ - addbyte(0x45); - addbyte((uint8_t)cpu_state_offset(tag[(cpu_state.TOP + reg) & 7])); - addbyte(0x66); /*MOVQ MM[-1][EBP], XMM1*/ - addbyte(0x0f); - addbyte(0xd6); - addbyte(0x4d); - addbyte((uint8_t)cpu_state_offset(MM[(cpu_state.TOP - 1) & 7].q)); - addbyte(0x88); /*MOV tag[-1][EBP], AL*/ - addbyte(0x45); - addbyte((uint8_t)cpu_state_offset(tag[(cpu_state.TOP - 1) & 7])); - } - else - { - addbyte(0x8b); /*MOV EAX, [TOP]*/ - addbyte(0x45); - addbyte((uint8_t)cpu_state_offset(TOP)); - addbyte(0x89); /*MOV EBX, EAX*/ - addbyte(0xc3); - if (reg) - { - addbyte(0x83); /*ADD EAX, reg*/ - addbyte(0xc0); - addbyte(reg); - addbyte(0x83); /*SUB EBX, 1*/ - addbyte(0xeb); - addbyte(0x01); - addbyte(0x83); /*AND EAX, 7*/ - addbyte(0xe0); - addbyte(0x07); - } - else - { - addbyte(0x83); /*SUB EBX, 1*/ - addbyte(0xeb); - addbyte(0x01); - } - - addbyte(0xdd); /*FLD [ST+EAX*8]*/ - addbyte(0x44); - addbyte(0xc5); - addbyte((uint8_t)cpu_state_offset(ST)); - addbyte(0x83); /*AND EBX, 7*/ - addbyte(0xe3); - addbyte(0x07); - addbyte(0x8b); /*MOV EDX, [ST_i64+EAX]*/ - addbyte(0x54); - addbyte(0xc5); - addbyte((uint8_t)cpu_state_offset(MM)); - addbyte(0x8b); /*MOV ECX, [ST_i64+4+EAX]*/ - addbyte(0x4c); - addbyte(0xc5); - addbyte((uint8_t)cpu_state_offset(MM)+4); - addbyte(0x8a); /*MOV AL, [tag+EAX]*/ - addbyte(0x44); - addbyte(0x05); - addbyte((uint8_t)cpu_state_offset(tag[0])); - addbyte(0xdd); /*FSTP [ST+EBX*8]*/ - addbyte(0x5c); - addbyte(0xdd); - addbyte((uint8_t)cpu_state_offset(ST)); - addbyte(0x88); /*MOV [tag+EBX], AL*/ - addbyte(0x44); - addbyte(0x1d); - addbyte((uint8_t)cpu_state_offset(tag[0])); - addbyte(0x89); /*MOV [ST_i64+EBX], EDX*/ - addbyte(0x54); - addbyte(0xdd); - addbyte((uint8_t)cpu_state_offset(MM)); - addbyte(0x89); /*MOV [ST_i64+EBX+4], ECX*/ - addbyte(0x4c); - addbyte(0xdd); - addbyte((uint8_t)cpu_state_offset(MM)+4); - - addbyte(0x89); /*MOV [TOP], EBX*/ - addbyte(0x5d); - addbyte((uint8_t)cpu_state_offset(TOP)); - } -} - -static inline void FP_FST(int reg) -{ - if (codeblock[block_current].flags & CODEBLOCK_STATIC_TOP) - { - addbyte(0xf3); /*MOVQ XMM0, ST[0][EBP]*/ - addbyte(0x0f); - addbyte(0x7e); - addbyte(0x45); - addbyte((uint8_t)cpu_state_offset(ST[cpu_state.TOP])); - addbyte(0x8a); /*MOV AL, tag[0][EBP]*/ - addbyte(0x45); - addbyte((uint8_t)cpu_state_offset(tag[cpu_state.TOP])); - addbyte(0x66); /*MOVQ ST[reg][EBP], XMM0*/ - addbyte(0x0f); - addbyte(0xd6); - addbyte(0x45); - addbyte((uint8_t)cpu_state_offset(ST[(cpu_state.TOP + reg) & 7])); - addbyte(0x88); /*MOV tag[reg][EBP], AL*/ - addbyte(0x45); - addbyte((uint8_t)cpu_state_offset(tag[(cpu_state.TOP + reg) & 7])); - } - else - { - addbyte(0x8b); /*MOV EAX, [TOP]*/ - addbyte(0x45); - addbyte((uint8_t)cpu_state_offset(TOP)); - addbyte(0xdd); /*FLD [ST+EAX*8]*/ - addbyte(0x44); - addbyte(0xc5); - addbyte((uint8_t)cpu_state_offset(ST)); - addbyte(0x8a); /*MOV BL, [tag+EAX]*/ - addbyte(0x5c); - addbyte(0x05); - addbyte((uint8_t)cpu_state_offset(tag[0])); - - if (reg) - { - addbyte(0x83); /*ADD EAX, reg*/ - addbyte(0xc0); - addbyte(reg); - addbyte(0x83); /*AND EAX, 7*/ - addbyte(0xe0); - addbyte(0x07); - } - - addbyte(0xdd); /*FSTP [ST+EAX*8]*/ - addbyte(0x5c); - addbyte(0xc5); - addbyte((uint8_t)cpu_state_offset(ST)); - addbyte(0x88); /*MOV [tag+EAX], BL*/ - addbyte(0x5c); - addbyte(0x05); - addbyte((uint8_t)cpu_state_offset(tag[0])); - } -} - -static inline void FP_FXCH(int reg) -{ - if (codeblock[block_current].flags & CODEBLOCK_STATIC_TOP) - { - addbyte(0xf3); /*MOVQ XMM0, ST[0][EBP]*/ - addbyte(0x0f); - addbyte(0x7e); - addbyte(0x45); - addbyte((uint8_t)cpu_state_offset(ST[cpu_state.TOP])); - addbyte(0xf3); /*MOVQ XMM1, ST[reg][EBP]*/ - addbyte(0x0f); - addbyte(0x7e); - addbyte(0x4d); - addbyte((uint8_t)cpu_state_offset(ST[(cpu_state.TOP + reg) & 7])); - addbyte(0x66); /*MOVQ ST[reg][EBP], XMM0*/ - addbyte(0x0f); - addbyte(0xd6); - addbyte(0x45); - addbyte((uint8_t)cpu_state_offset(ST[(cpu_state.TOP + reg) & 7])); - addbyte(0xf3); /*MOVQ XMM2, MM[0][EBP]*/ - addbyte(0x0f); - addbyte(0x7e); - addbyte(0x55); - addbyte((uint8_t)cpu_state_offset(MM[cpu_state.TOP].q)); - addbyte(0x66); /*MOVQ ST[0][EBP], XMM1*/ - addbyte(0x0f); - addbyte(0xd6); - addbyte(0x4d); - addbyte((uint8_t)cpu_state_offset(ST[cpu_state.TOP])); - addbyte(0xf3); /*MOVQ XMM3, MM[reg][EBP]*/ - addbyte(0x0f); - addbyte(0x7e); - addbyte(0x5d); - addbyte((uint8_t)cpu_state_offset(MM[(cpu_state.TOP + reg) & 7].q)); - addbyte(0x66); /*MOVQ MM[reg][EBP], XMM2*/ - addbyte(0x0f); - addbyte(0xd6); - addbyte(0x55); - addbyte((uint8_t)cpu_state_offset(MM[(cpu_state.TOP + reg) & 7].q)); - addbyte(0x8a); /*MOV AL, tag[0][EBP]*/ - addbyte(0x45); - addbyte((uint8_t)cpu_state_offset(tag[cpu_state.TOP])); - addbyte(0x66); /*MOVQ MM[0][EBP], XMM3*/ - addbyte(0x0f); - addbyte(0xd6); - addbyte(0x5d); - addbyte((uint8_t)cpu_state_offset(MM[cpu_state.TOP].q)); - addbyte(0x8a); /*MOV AH, tag[reg][EBP]*/ - addbyte(0x65); - addbyte((uint8_t)cpu_state_offset(tag[(cpu_state.TOP + reg) & 7])); - addbyte(0x88); /*MOV tag[reg][EBP], AL*/ - addbyte(0x45); - addbyte((uint8_t)cpu_state_offset(tag[(cpu_state.TOP + reg) & 7])); - addbyte(0x88); /*MOV tag[0][EBP], AH*/ - addbyte(0x65); - addbyte((uint8_t)cpu_state_offset(tag[cpu_state.TOP])); - } - else - { - addbyte(0x8b); /*MOV EAX, [TOP]*/ - addbyte(0x45); - addbyte((uint8_t)cpu_state_offset(TOP)); - addbyte(0x89); /*MOV EBX, EAX*/ - addbyte(0xc3); - addbyte(0x83); /*ADD EAX, reg*/ - addbyte(0xc0); - addbyte(reg); - - addbyte(0xdd); /*FLD [ST+EBX*8]*/ - addbyte(0x44); - addbyte(0xdd); - addbyte((uint8_t)cpu_state_offset(ST)); - addbyte(0x83); /*AND EAX, 7*/ - addbyte(0xe0); - addbyte(0x07); - addbyte(0xdd); /*FLD [ST+EAX*8]*/ - addbyte(0x44); - addbyte(0xc5); - addbyte((uint8_t)cpu_state_offset(ST)); - addbyte(0xdd); /*FSTP [ST+EBX*8]*/ - addbyte(0x5c); - addbyte(0xdd); - addbyte((uint8_t)cpu_state_offset(ST)); - addbyte(0xdd); /*FSTP [ST+EAX*8]*/ - addbyte(0x5c); - addbyte(0xc5); - addbyte((uint8_t)cpu_state_offset(ST)); - addbyte(0x8a); /*MOV CL, tag[EAX]*/ - addbyte(0x4c); - addbyte(0x05); - addbyte((uint8_t)cpu_state_offset(tag[0])); - addbyte(0x8a); /*MOV DL, tag[EBX]*/ - addbyte(0x54); - addbyte(0x1d); - addbyte((uint8_t)cpu_state_offset(tag[0])); - addbyte(0x88); /*MOV tag[EBX], CL*/ - addbyte(0x4c); - addbyte(0x1d); - addbyte((uint8_t)cpu_state_offset(tag[0])); - addbyte(0x88); /*MOV tag[EAX], DL*/ - addbyte(0x54); - addbyte(0x05); - addbyte((uint8_t)cpu_state_offset(tag[0])); - addbyte(0xbe); /*MOVL ESI, ST_int64*/ - addlong((uintptr_t)cpu_state.MM); - addbyte(0x8b); /*MOV ECX, ST_int64[EAX*8]*/ - addbyte(0x0c); - addbyte(0xc6); - addbyte(0x8b); /*MOV EDX, ST_int64[EBX*8]*/ - addbyte(0x14); - addbyte(0xde); - addbyte(0x89); /*MOV ST_int64[EBX*8], ECX*/ - addbyte(0x0c); - addbyte(0xde); - addbyte(0x89); /*MOV ST_int64[EAX*8], EDX*/ - addbyte(0x14); - addbyte(0xc6); - addbyte(0x8b); /*MOV ECX, ST_int64[EAX*8]+4*/ - addbyte(0x4c); - addbyte(0xc6); - addbyte(0x04); - addbyte(0x8b); /*MOV EDX, ST_int64[EBX*8]+4*/ - addbyte(0x54); - addbyte(0xde); - addbyte(0x04); - addbyte(0x89); /*MOV ST_int64[EBX*8]+4, ECX*/ - addbyte(0x4c); - addbyte(0xde); - addbyte(0x04); - addbyte(0x89); /*MOV ST_int64[EAX*8]+4, EDX*/ - addbyte(0x54); - addbyte(0xc6); - addbyte(0x04); - } -} - - -static inline void FP_LOAD_S() -{ - if (codeblock[block_current].flags & CODEBLOCK_STATIC_TOP) - { - addbyte(0x89); /*MOV [ESP], EAX*/ - addbyte(0x04); - addbyte(0x24); - addbyte(0x85); /*TEST EAX, EAX*/ - addbyte(0xc0); - addbyte(0xd9); /*FLD [ESP]*/ - addbyte(0x04); - addbyte(0x24); - addbyte(0xc6); /*MOVB TOP[EBP], (TOP-1) & 7*/ - addbyte(0x45); - addbyte((uint8_t)cpu_state_offset(TOP)); - addbyte((cpu_state.TOP - 1) & 7); - addbyte(0x0f); /*SETE tag[reg][EBP]*/ - addbyte(0x94); - addbyte(0x45); - addbyte((uint8_t)cpu_state_offset(tag[(cpu_state.TOP - 1) & 7])); - addbyte(0xdd); /*FSTP ST[reg][EBP]*/ - addbyte(0x5d); - addbyte((uint8_t)cpu_state_offset(ST[(cpu_state.TOP - 1) & 7])); - } - else - { - addbyte(0x8b); /*MOV EBX, TOP*/ - addbyte(0x5d); - addbyte((uint8_t)cpu_state_offset(TOP)); - addbyte(0x89); /*MOV [ESP], EAX*/ - addbyte(0x04); - addbyte(0x24); - addbyte(0x83); /*SUB EBX, 1*/ - addbyte(0xeb); - addbyte(1); - addbyte(0xd9); /*FLD [ESP]*/ - addbyte(0x04); - addbyte(0x24); - addbyte(0x83); /*AND EBX, 7*/ - addbyte(0xe3); - addbyte(7); - addbyte(0x85); /*TEST EAX, EAX*/ - addbyte(0xc0); - addbyte(0x89); /*MOV TOP, EBX*/ - addbyte(0x5d); - addbyte((uint8_t)cpu_state_offset(TOP)); - addbyte(0xdd); /*FSTP [ST+EBX*8]*/ - addbyte(0x5c); - addbyte(0xdd); - addbyte((uint8_t)cpu_state_offset(ST)); - addbyte(0x0f); /*SETE [tag+EBX]*/ - addbyte(0x94); - addbyte(0x44); - addbyte(0x1d); - addbyte((uint8_t)cpu_state_offset(tag[0])); - } -} -static inline void FP_LOAD_D() -{ - if (codeblock[block_current].flags & CODEBLOCK_STATIC_TOP) - { - addbyte(0x89); /*MOV ST[reg][EBP], EAX*/ - addbyte(0x45); - addbyte((uint8_t)cpu_state_offset(ST[(cpu_state.TOP - 1) & 7])); - addbyte(0x09); /*OR EAX, EDX*/ - addbyte(0xd0); - addbyte(0x89); /*MOV ST[reg][EBP]+4, EDX*/ - addbyte(0x55); - addbyte((uint8_t)cpu_state_offset(ST[(cpu_state.TOP - 1) & 7]) + 4); - addbyte(0xc6); /*MOVB TOP[EBP], (TOP-1) & 7*/ - addbyte(0x45); - addbyte((uint8_t)cpu_state_offset(TOP)); - addbyte((cpu_state.TOP - 1) & 7); - addbyte(0x0f); /*SETE tag[reg][EBP]*/ - addbyte(0x94); - addbyte(0x45); - addbyte((uint8_t)cpu_state_offset(tag[(cpu_state.TOP - 1) & 7])); - } - else - { - addbyte(0x8b); /*MOV EBX, TOP*/ - addbyte(0x5d); - addbyte((uint8_t)cpu_state_offset(TOP)); - addbyte(0x89); /*MOV [ESP], EAX*/ - addbyte(0x04); - addbyte(0x24); - addbyte(0x89); /*MOV [ESP+4], EDX*/ - addbyte(0x54); - addbyte(0x24); - addbyte(0x04); - addbyte(0x83); /*SUB EBX, 1*/ - addbyte(0xeb); - addbyte(1); - addbyte(0x09); /*OR EAX, EDX*/ - addbyte(0xd0); - addbyte(0xdd); /*FLD [ESP]*/ - addbyte(0x04); - addbyte(0x24); - addbyte(0x83); /*AND EBX, 7*/ - addbyte(0xe3); - addbyte(7); - addbyte(0x83); /*CMP EAX, 0*/ - addbyte(0xf8); - addbyte(0); - addbyte(0x89); /*MOV TOP, EBX*/ - addbyte(0x5d); - addbyte((uint8_t)cpu_state_offset(TOP)); - addbyte(0xdd); /*FSTP [ST+EBX*8]*/ - addbyte(0x5c); - addbyte(0xdd); - addbyte((uint8_t)cpu_state_offset(ST)); - addbyte(0x0f); /*SETE [tag+EBX]*/ - addbyte(0x94); - addbyte(0x44); - addbyte(0x1d); - addbyte((uint8_t)cpu_state_offset(tag[0])); - } -} -static inline void FP_LOAD_IW() -{ - if (codeblock[block_current].flags & CODEBLOCK_STATIC_TOP) - { - addbyte(0x66); /*MOV [ESP], AX*/ - addbyte(0x89); - addbyte(0x04); - addbyte(0x24); - addbyte(0x66); /*TEST AX, AX*/ - addbyte(0x85); - addbyte(0xc0); - addbyte(0xdf); /*FILDw [ESP]*/ - addbyte(0x04); - addbyte(0x24); - addbyte(0xc6); /*MOVB TOP[EBP], (TOP-1) & 7*/ - addbyte(0x45); - addbyte((uint8_t)cpu_state_offset(TOP)); - addbyte((cpu_state.TOP - 1) & 7); - addbyte(0x0f); /*SETE tag[reg][EBP]*/ - addbyte(0x94); - addbyte(0x45); - addbyte((uint8_t)cpu_state_offset(tag[(cpu_state.TOP - 1) & 7])); - addbyte(0xdd); /*FSTP ST[reg][EBP]*/ - addbyte(0x5d); - addbyte((uint8_t)cpu_state_offset(ST[(cpu_state.TOP - 1) & 7])); - } - else - { - addbyte(0x8b); /*MOV EBX, TOP*/ - addbyte(0x5d); - addbyte((uint8_t)cpu_state_offset(TOP)); - addbyte(0x89); /*MOV [ESP], EAX*/ - addbyte(0x04); - addbyte(0x24); - addbyte(0x83); /*SUB EBX, 1*/ - addbyte(0xeb); - addbyte(1); - addbyte(0xdf); /*FILDw [ESP]*/ - addbyte(0x04); - addbyte(0x24); - addbyte(0x83); /*AND EBX, 7*/ - addbyte(0xe3); - addbyte(7); - addbyte(0x83); /*CMP EAX, 0*/ - addbyte(0xf8); - addbyte(0); - addbyte(0x89); /*MOV TOP, EBX*/ - addbyte(0x5d); - addbyte((uint8_t)cpu_state_offset(TOP)); - addbyte(0xdd); /*FSTP [ST+EBX*8]*/ - addbyte(0x5c); - addbyte(0xdd); - addbyte((uint8_t)cpu_state_offset(ST)); - addbyte(0x0f); /*SETE [tag+EBX]*/ - addbyte(0x94); - addbyte(0x44); - addbyte(0x1d); - addbyte((uint8_t)cpu_state_offset(tag[0])); - } -} -static inline void FP_LOAD_IL() -{ - if (codeblock[block_current].flags & CODEBLOCK_STATIC_TOP) - { - addbyte(0x89); /*MOV [ESP], EAX*/ - addbyte(0x04); - addbyte(0x24); - addbyte(0x85); /*TEST EAX, EAX*/ - addbyte(0xc0); - addbyte(0xdb); /*FILDl [ESP]*/ - addbyte(0x04); - addbyte(0x24); - addbyte(0xc6); /*MOVB TOP[EBP], (TOP-1) & 7*/ - addbyte(0x45); - addbyte((uint8_t)cpu_state_offset(TOP)); - addbyte((cpu_state.TOP - 1) & 7); - addbyte(0x0f); /*SETE tag[reg][EBP]*/ - addbyte(0x94); - addbyte(0x45); - addbyte((uint8_t)cpu_state_offset(tag[(cpu_state.TOP - 1) & 7])); - addbyte(0xdd); /*FSTP ST[reg][EBP]*/ - addbyte(0x5d); - addbyte((uint8_t)cpu_state_offset(ST[(cpu_state.TOP - 1) & 7])); - } - else - { - addbyte(0x8b); /*MOV EBX, TOP*/ - addbyte(0x5d); - addbyte((uint8_t)cpu_state_offset(TOP)); - addbyte(0x89); /*MOV [ESP], EAX*/ - addbyte(0x04); - addbyte(0x24); - addbyte(0x83); /*SUB EBX, 1*/ - addbyte(0xeb); - addbyte(1); - addbyte(0xdb); /*FILDl [ESP]*/ - addbyte(0x04); - addbyte(0x24); - addbyte(0x83); /*AND EBX, 7*/ - addbyte(0xe3); - addbyte(7); - addbyte(0x83); /*CMP EAX, 0*/ - addbyte(0xf8); - addbyte(0); - addbyte(0x89); /*MOV TOP, EBX*/ - addbyte(0x5d); - addbyte((uint8_t)cpu_state_offset(TOP)); - addbyte(0xdd); /*FSTP [ST+EBX*8]*/ - addbyte(0x5c); - addbyte(0xdd); - addbyte((uint8_t)cpu_state_offset(ST)); - addbyte(0x0f); /*SETE [tag+EBX]*/ - addbyte(0x94); - addbyte(0x44); - addbyte(0x1d); - addbyte((uint8_t)cpu_state_offset(tag[0])); - } -} -static inline void FP_LOAD_IQ() -{ - if (codeblock[block_current].flags & CODEBLOCK_STATIC_TOP) - { - addbyte(0x89); /*MOV MM[reg][EBP], EAX*/ - addbyte(0x45); - addbyte((uint8_t)cpu_state_offset(MM[(cpu_state.TOP - 1) & 7].q)); - addbyte(0x09); /*OR EAX, EDX*/ - addbyte(0xd0); - addbyte(0x89); /*MOV MM[reg][EBP]+4, EDX*/ - addbyte(0x55); - addbyte((uint8_t)cpu_state_offset(MM[(cpu_state.TOP - 1) & 7].q) + 4); - addbyte(0x0f); /*SETE AL*/ - addbyte(0x94); - addbyte(0xc0); - addbyte(0xdf); /*FILDq MM[reg][EBP]*/ - addbyte(0x6d); - addbyte((uint8_t)cpu_state_offset(MM[(cpu_state.TOP - 1) & 7].q)); - addbyte(0x0c); /*OR AL, TAG_UINT64*/ - addbyte(TAG_UINT64); - addbyte(0xc6); /*MOVB TOP[EBP], (TOP-1) & 7*/ - addbyte(0x45); - addbyte((uint8_t)cpu_state_offset(TOP)); - addbyte((cpu_state.TOP - 1) & 7); - addbyte(0x88); /*MOV tag[reg][EBP], AL*/ - addbyte(0x45); - addbyte((uint8_t)cpu_state_offset(tag[(cpu_state.TOP - 1) & 7])); - addbyte(0xdd); /*FSTP ST[reg][EBP]*/ - addbyte(0x5d); - addbyte((uint8_t)cpu_state_offset(ST[(cpu_state.TOP - 1) & 7])); - } - else - { - addbyte(0x8b); /*MOV EBX, TOP*/ - addbyte(0x5d); - addbyte((uint8_t)cpu_state_offset(TOP)); - addbyte(0x83); /*SUB EBX, 1*/ - addbyte(0xeb); - addbyte(1); - addbyte(0x83); /*AND EBX, 7*/ - addbyte(0xe3); - addbyte(7); - addbyte(0x89); /*MOV [ST_i64+EBX*8], EAX*/ - addbyte(0x44); - addbyte(0xdd); - addbyte((uint8_t)cpu_state_offset(MM)); - addbyte(0x09); /*OR EAX, EDX*/ - addbyte(0xd0); - addbyte(0x89); /*MOV [ST_i64+4+EBX*8], EDX*/ - addbyte(0x54); - addbyte(0xdd); - addbyte((uint8_t)cpu_state_offset(MM)+4); - addbyte(0x83); /*CMP EAX, 0*/ - addbyte(0xf8); - addbyte(0); - addbyte(0xdf); /*FILDl [ST_i64+EBX*8]*/ - addbyte(0x6c); - addbyte(0xdd); - addbyte((uint8_t)cpu_state_offset(MM)); - addbyte(0x0f); /*SETE AL*/ - addbyte(0x94); - addbyte(0xc0); - addbyte(0xdd); /*FSTP [ST+EBX*8]*/ - addbyte(0x5c); - addbyte(0xdd); - addbyte((uint8_t)cpu_state_offset(ST)); - addbyte(0x0c); /*OR AL, TAG_UINT64*/ - addbyte(TAG_UINT64); - addbyte(0x89); /*MOV TOP, EBX*/ - addbyte(0x5d); - addbyte((uint8_t)cpu_state_offset(TOP)); - addbyte(0x88); /*MOV [tag+EBX], AL*/ - addbyte(0x44); - addbyte(0x1d); - addbyte((uint8_t)cpu_state_offset(tag[0])); - } -} - -static inline void FP_LOAD_IMM_Q(uint64_t v) -{ - if (codeblock[block_current].flags & CODEBLOCK_STATIC_TOP) - { - addbyte(0xc7); /*MOV ST[reg][EBP], v*/ - addbyte(0x45); - addbyte((uint8_t)cpu_state_offset(ST[(cpu_state.TOP - 1) & 7])); - addlong(v & 0xffffffff); - addbyte(0xc7); /*MOV ST[reg][EBP]+4, v*/ - addbyte(0x45); - addbyte((uint8_t)cpu_state_offset(ST[(cpu_state.TOP - 1) & 7]) + 4); - addlong(v >> 32); - addbyte(0xc6); /*MOVB TOP[EBP], (TOP-1) & 7*/ - addbyte(0x45); - addbyte((uint8_t)cpu_state_offset(TOP)); - addbyte((cpu_state.TOP - 1) & 7); - addbyte(0xc6); /*MOVB tag[reg][EBP], 1:0*/ - addbyte(0x45); - addbyte((uint8_t)cpu_state_offset(tag[(cpu_state.TOP - 1) & 7])); - addbyte(v ? 0 : 1); - } - else - { - addbyte(0x8b); /*MOV EBX, TOP*/ - addbyte(0x5d); - addbyte((uint8_t)cpu_state_offset(TOP)); - addbyte(0x83); /*SUB EBX, 1*/ - addbyte(0xeb); - addbyte(1); - addbyte(0x83); /*AND EBX, 7*/ - addbyte(0xe3); - addbyte(7); - addbyte(0xc7); /*MOV ST[EBP+EBX*8], v*/ - addbyte(0x44); - addbyte(0xdd); - addbyte((uint8_t)cpu_state_offset(ST)); - addlong(v & 0xffffffff); - addbyte(0xc7); /*MOV ST[EBP+EBX*8]+4, v*/ - addbyte(0x44); - addbyte(0xdd); - addbyte((uint8_t)cpu_state_offset(ST) + 4); - addlong(v >> 32); - addbyte(0xc6); /*MOVB tag[reg][EBP], 1:0*/ - addbyte(0x44); - addbyte(0x1d); - addbyte((uint8_t)cpu_state_offset(tag[0])); - addbyte(v ? 0 : 1); - addbyte(0x89); /*MOV TOP, EBX*/ - addbyte(0x5d); - addbyte((uint8_t)cpu_state_offset(TOP)); - } -} - -static inline int FP_LOAD_REG(int reg) -{ - if (codeblock[block_current].flags & CODEBLOCK_STATIC_TOP) - { - addbyte(0xdd); /*FLD ST[reg][EBP]*/ - addbyte(0x45); - addbyte((uint8_t)cpu_state_offset(ST[(cpu_state.TOP + reg) & 7])); - } - else - { - addbyte(0x8b); /*MOV EBX, TOP*/ - addbyte(0x5d); - addbyte((uint8_t)cpu_state_offset(TOP)); - if (reg) - { - addbyte(0x83); /*ADD EBX, reg*/ - addbyte(0xc3); - addbyte(reg); - addbyte(0x83); /*AND EBX, 7*/ - addbyte(0xe3); - addbyte(7); - } - addbyte(0xdd); /*FLD ST[EBX*8]*/ - addbyte(0x44); - addbyte(0xdd); - addbyte((uint8_t)cpu_state_offset(ST)); - } - addbyte(0xd9); /*FSTP [ESP]*/ - addbyte(0x1c); - addbyte(0x24); - addbyte(0x8b); /*MOV EAX, [ESP]*/ - addbyte(0x04 | (REG_EBX << 3)); - addbyte(0x24); - - return REG_EBX; -} - -static inline void FP_LOAD_REG_D(int reg, int *host_reg1, int *host_reg2) -{ - if (codeblock[block_current].flags & CODEBLOCK_STATIC_TOP) - { - addbyte(0xdd); /*FLD ST[reg][EBP]*/ - addbyte(0x45); - addbyte((uint8_t)cpu_state_offset(ST[(cpu_state.TOP + reg) & 7])); - } - else - { - addbyte(0x8b); /*MOV EBX, TOP*/ - addbyte(0x5d); - addbyte((uint8_t)cpu_state_offset(TOP)); - if (reg) - { - addbyte(0x83); /*ADD EBX, reg*/ - addbyte(0xc3); - addbyte(reg); - addbyte(0x83); /*AND EBX, 7*/ - addbyte(0xe3); - addbyte(7); - } - addbyte(0xdd); /*FLD ST[EBX*8]*/ - addbyte(0x44); - addbyte(0xdd); - addbyte((uint8_t)cpu_state_offset(ST)); - } - addbyte(0xdd); /*FSTP [ESP]*/ - addbyte(0x1c); - addbyte(0x24); - addbyte(0x8b); /*MOV EBX, [ESP]*/ - addbyte(0x04 | (REG_EBX << 3)); - addbyte(0x24); - addbyte(0x8b); /*MOV ECX, [ESP+4]*/ - addbyte(0x44 | (REG_ECX << 3)); - addbyte(0x24); - addbyte(0x04); - - *host_reg1 = REG_EBX; - *host_reg2 = REG_ECX; -} - -static inline int FP_LOAD_REG_INT_W(int reg) -{ - addbyte(0x8b); /*MOV EBX, TOP*/ - addbyte(0x5d); - addbyte((uint8_t)cpu_state_offset(TOP)); - if (reg) - { - addbyte(0x83); /*ADD EBX, reg*/ - addbyte(0xc3); - addbyte(reg); - addbyte(0x83); /*AND EBX, 7*/ - addbyte(0xe3); - addbyte(7); - } - addbyte(0xdd); /*FLD ST[EBX*8]*/ - addbyte(0x44); + addbyte((uint8_t) cpu_state_offset(tag[0])); + addbyte(0xdd); /*FSTP [ST+EBX*8]*/ + addbyte(0x5c); addbyte(0xdd); - addbyte((uint8_t)cpu_state_offset(ST)); - - addbyte(0xd9); /*FLDCW cpu_state.new_npxc*/ - addbyte(0x6d); - addbyte((uint8_t)cpu_state_offset(new_npxc)); - addbyte(0xdb); /*FISTP [ESP]*/ - addbyte(0x1c); - addbyte(0x24); - addbyte(0xd9); /*FLDCW cpu_state.old_npxc*/ - addbyte(0x6d); - addbyte((uint8_t)cpu_state_offset(old_npxc)); - addbyte(0x8b); /*MOV EBX, [ESP]*/ - addbyte(0x1c); - addbyte(0x24); - - return REG_EBX; -} -static inline int FP_LOAD_REG_INT(int reg) -{ - addbyte(0x8b); /*MOV EBX, TOP*/ - addbyte(0x5d); - addbyte((uint8_t)cpu_state_offset(TOP)); - if (reg) - { - addbyte(0x83); /*ADD EBX, reg*/ - addbyte(0xc3); - addbyte(reg); - addbyte(0x83); /*AND EBX, 7*/ - addbyte(0xe3); - addbyte(7); - } - addbyte(0xdd); /*FLD ST[EBX*8]*/ - addbyte(0x44); - addbyte(0xdd); - addbyte((uint8_t)cpu_state_offset(ST)); - - addbyte(0xd9); /*FLDCW cpu_state.new_npxc*/ - addbyte(0x6d); - addbyte((uint8_t)cpu_state_offset(new_npxc)); - addbyte(0xdb); /*FISTP [ESP]*/ - addbyte(0x1c); - addbyte(0x24); - addbyte(0xd9); /*FLDCW cpu_state.old_npxc*/ - addbyte(0x6d); - addbyte((uint8_t)cpu_state_offset(old_npxc)); - addbyte(0x8b); /*MOV EBX, [ESP]*/ - addbyte(0x1c); - addbyte(0x24); - - return REG_EBX; -} -static inline void FP_LOAD_REG_INT_Q(int reg, int *host_reg1, int *host_reg2) -{ - addbyte(0x8b); /*MOV EBX, TOP*/ - addbyte(0x5d); - addbyte((uint8_t)cpu_state_offset(TOP)); - if (reg) - { - addbyte(0x83); /*ADD EBX, reg*/ - addbyte(0xc3); - addbyte(reg); - addbyte(0x83); /*AND EBX, 7*/ - addbyte(0xe3); - addbyte(7); - } - if (codegen_fpu_loaded_iq[cpu_state.TOP] && (cpu_state.tag[cpu_state.TOP] & TAG_UINT64)) - { - /*If we know the register was loaded with FILDq in this block and - has not been modified, then we can skip most of the conversion - and just load the 64-bit integer representation directly */ - addbyte(0x8b); /*MOV ECX, [ST_i64+EBX*8]*/ - addbyte(0x4c); - addbyte(0xdd); - addbyte((uint8_t)cpu_state_offset(MM)+4); - addbyte(0x8b); /*MOV EBX, [ST_i64+EBX*8]*/ - addbyte(0x5c); - addbyte(0xdd); - addbyte((uint8_t)cpu_state_offset(MM)); - - return; - } - - addbyte(0xf6); /*TEST TAG[EBX], TAG_UINT64*/ + addbyte((uint8_t) cpu_state_offset(ST)); + addbyte(0x88); /*MOV [tag+EBX], AL*/ addbyte(0x44); addbyte(0x1d); - addbyte((uint8_t)cpu_state_offset(tag[0])); - addbyte(TAG_UINT64); - addbyte(0x74); /*JZ +*/ - addbyte(4+4+2); + addbyte((uint8_t) cpu_state_offset(tag[0])); + addbyte(0x89); /*MOV [ST_i64+EBX], EDX*/ + addbyte(0x54); + addbyte(0xdd); + addbyte((uint8_t) cpu_state_offset(MM)); + addbyte(0x89); /*MOV [ST_i64+EBX+4], ECX*/ + addbyte(0x4c); + addbyte(0xdd); + addbyte((uint8_t) cpu_state_offset(MM) + 4); + addbyte(0x89); /*MOV [TOP], EBX*/ + addbyte(0x5d); + addbyte((uint8_t) cpu_state_offset(TOP)); + } +} + +static __inline void +FP_FST(int reg) +{ + if (codeblock[block_current].flags & CODEBLOCK_STATIC_TOP) { + addbyte(0xf3); /*MOVQ XMM0, ST[0][EBP]*/ + addbyte(0x0f); + addbyte(0x7e); + addbyte(0x45); + addbyte((uint8_t) cpu_state_offset(ST[cpu_state.TOP])); + addbyte(0x8a); /*MOV AL, tag[0][EBP]*/ + addbyte(0x45); + addbyte((uint8_t) cpu_state_offset(tag[cpu_state.TOP])); + addbyte(0x66); /*MOVQ ST[reg][EBP], XMM0*/ + addbyte(0x0f); + addbyte(0xd6); + addbyte(0x45); + addbyte((uint8_t) cpu_state_offset(ST[(cpu_state.TOP + reg) & 7])); + addbyte(0x88); /*MOV tag[reg][EBP], AL*/ + addbyte(0x45); + addbyte((uint8_t) cpu_state_offset(tag[(cpu_state.TOP + reg) & 7])); + } else { + addbyte(0x8b); /*MOV EAX, [TOP]*/ + addbyte(0x45); + addbyte((uint8_t) cpu_state_offset(TOP)); + addbyte(0xdd); /*FLD [ST+EAX*8]*/ + addbyte(0x44); + addbyte(0xc5); + addbyte((uint8_t) cpu_state_offset(ST)); + addbyte(0x8a); /*MOV BL, [tag+EAX]*/ + addbyte(0x5c); + addbyte(0x05); + addbyte((uint8_t) cpu_state_offset(tag[0])); + + if (reg) { + addbyte(0x83); /*ADD EAX, reg*/ + addbyte(0xc0); + addbyte(reg); + addbyte(0x83); /*AND EAX, 7*/ + addbyte(0xe0); + addbyte(0x07); + } + + addbyte(0xdd); /*FSTP [ST+EAX*8]*/ + addbyte(0x5c); + addbyte(0xc5); + addbyte((uint8_t) cpu_state_offset(ST)); + addbyte(0x88); /*MOV [tag+EAX], BL*/ + addbyte(0x5c); + addbyte(0x05); + addbyte((uint8_t) cpu_state_offset(tag[0])); + } +} + +static __inline void +FP_FXCH(int reg) +{ + if (codeblock[block_current].flags & CODEBLOCK_STATIC_TOP) { + addbyte(0xf3); /*MOVQ XMM0, ST[0][EBP]*/ + addbyte(0x0f); + addbyte(0x7e); + addbyte(0x45); + addbyte((uint8_t) cpu_state_offset(ST[cpu_state.TOP])); + addbyte(0xf3); /*MOVQ XMM1, ST[reg][EBP]*/ + addbyte(0x0f); + addbyte(0x7e); + addbyte(0x4d); + addbyte((uint8_t) cpu_state_offset(ST[(cpu_state.TOP + reg) & 7])); + addbyte(0x66); /*MOVQ ST[reg][EBP], XMM0*/ + addbyte(0x0f); + addbyte(0xd6); + addbyte(0x45); + addbyte((uint8_t) cpu_state_offset(ST[(cpu_state.TOP + reg) & 7])); + addbyte(0xf3); /*MOVQ XMM2, MM[0][EBP]*/ + addbyte(0x0f); + addbyte(0x7e); + addbyte(0x55); + addbyte((uint8_t) cpu_state_offset(MM[cpu_state.TOP].q)); + addbyte(0x66); /*MOVQ ST[0][EBP], XMM1*/ + addbyte(0x0f); + addbyte(0xd6); + addbyte(0x4d); + addbyte((uint8_t) cpu_state_offset(ST[cpu_state.TOP])); + addbyte(0xf3); /*MOVQ XMM3, MM[reg][EBP]*/ + addbyte(0x0f); + addbyte(0x7e); + addbyte(0x5d); + addbyte((uint8_t) cpu_state_offset(MM[(cpu_state.TOP + reg) & 7].q)); + addbyte(0x66); /*MOVQ MM[reg][EBP], XMM2*/ + addbyte(0x0f); + addbyte(0xd6); + addbyte(0x55); + addbyte((uint8_t) cpu_state_offset(MM[(cpu_state.TOP + reg) & 7].q)); + addbyte(0x8a); /*MOV AL, tag[0][EBP]*/ + addbyte(0x45); + addbyte((uint8_t) cpu_state_offset(tag[cpu_state.TOP])); + addbyte(0x66); /*MOVQ MM[0][EBP], XMM3*/ + addbyte(0x0f); + addbyte(0xd6); + addbyte(0x5d); + addbyte((uint8_t) cpu_state_offset(MM[cpu_state.TOP].q)); + addbyte(0x8a); /*MOV AH, tag[reg][EBP]*/ + addbyte(0x65); + addbyte((uint8_t) cpu_state_offset(tag[(cpu_state.TOP + reg) & 7])); + addbyte(0x88); /*MOV tag[reg][EBP], AL*/ + addbyte(0x45); + addbyte((uint8_t) cpu_state_offset(tag[(cpu_state.TOP + reg) & 7])); + addbyte(0x88); /*MOV tag[0][EBP], AH*/ + addbyte(0x65); + addbyte((uint8_t) cpu_state_offset(tag[cpu_state.TOP])); + } else { + addbyte(0x8b); /*MOV EAX, [TOP]*/ + addbyte(0x45); + addbyte((uint8_t) cpu_state_offset(TOP)); + addbyte(0x89); /*MOV EBX, EAX*/ + addbyte(0xc3); + addbyte(0x83); /*ADD EAX, reg*/ + addbyte(0xc0); + addbyte(reg); + + addbyte(0xdd); /*FLD [ST+EBX*8]*/ + addbyte(0x44); + addbyte(0xdd); + addbyte((uint8_t) cpu_state_offset(ST)); + addbyte(0x83); /*AND EAX, 7*/ + addbyte(0xe0); + addbyte(0x07); + addbyte(0xdd); /*FLD [ST+EAX*8]*/ + addbyte(0x44); + addbyte(0xc5); + addbyte((uint8_t) cpu_state_offset(ST)); + addbyte(0xdd); /*FSTP [ST+EBX*8]*/ + addbyte(0x5c); + addbyte(0xdd); + addbyte((uint8_t) cpu_state_offset(ST)); + addbyte(0xdd); /*FSTP [ST+EAX*8]*/ + addbyte(0x5c); + addbyte(0xc5); + addbyte((uint8_t) cpu_state_offset(ST)); + addbyte(0x8a); /*MOV CL, tag[EAX]*/ + addbyte(0x4c); + addbyte(0x05); + addbyte((uint8_t) cpu_state_offset(tag[0])); + addbyte(0x8a); /*MOV DL, tag[EBX]*/ + addbyte(0x54); + addbyte(0x1d); + addbyte((uint8_t) cpu_state_offset(tag[0])); + addbyte(0x88); /*MOV tag[EBX], CL*/ + addbyte(0x4c); + addbyte(0x1d); + addbyte((uint8_t) cpu_state_offset(tag[0])); + addbyte(0x88); /*MOV tag[EAX], DL*/ + addbyte(0x54); + addbyte(0x05); + addbyte((uint8_t) cpu_state_offset(tag[0])); + addbyte(0xbe); /*MOVL ESI, ST_int64*/ + addlong((uintptr_t) cpu_state.MM); + addbyte(0x8b); /*MOV ECX, ST_int64[EAX*8]*/ + addbyte(0x0c); + addbyte(0xc6); + addbyte(0x8b); /*MOV EDX, ST_int64[EBX*8]*/ + addbyte(0x14); + addbyte(0xde); + addbyte(0x89); /*MOV ST_int64[EBX*8], ECX*/ + addbyte(0x0c); + addbyte(0xde); + addbyte(0x89); /*MOV ST_int64[EAX*8], EDX*/ + addbyte(0x14); + addbyte(0xc6); + addbyte(0x8b); /*MOV ECX, ST_int64[EAX*8]+4*/ + addbyte(0x4c); + addbyte(0xc6); + addbyte(0x04); + addbyte(0x8b); /*MOV EDX, ST_int64[EBX*8]+4*/ + addbyte(0x54); + addbyte(0xde); + addbyte(0x04); + addbyte(0x89); /*MOV ST_int64[EBX*8]+4, ECX*/ + addbyte(0x4c); + addbyte(0xde); + addbyte(0x04); + addbyte(0x89); /*MOV ST_int64[EAX*8]+4, EDX*/ + addbyte(0x54); + addbyte(0xc6); + addbyte(0x04); + } +} + +static __inline void +FP_LOAD_S(void) +{ + if (codeblock[block_current].flags & CODEBLOCK_STATIC_TOP) { + addbyte(0x89); /*MOV [ESP], EAX*/ + addbyte(0x04); + addbyte(0x24); + addbyte(0x85); /*TEST EAX, EAX*/ + addbyte(0xc0); + addbyte(0xd9); /*FLD [ESP]*/ + addbyte(0x04); + addbyte(0x24); + addbyte(0xc6); /*MOVB TOP[EBP], (TOP-1) & 7*/ + addbyte(0x45); + addbyte((uint8_t) cpu_state_offset(TOP)); + addbyte((cpu_state.TOP - 1) & 7); + addbyte(0x0f); /*SETE tag[reg][EBP]*/ + addbyte(0x94); + addbyte(0x45); + addbyte((uint8_t) cpu_state_offset(tag[(cpu_state.TOP - 1) & 7])); + addbyte(0xdd); /*FSTP ST[reg][EBP]*/ + addbyte(0x5d); + addbyte((uint8_t) cpu_state_offset(ST[(cpu_state.TOP - 1) & 7])); + } else { + addbyte(0x8b); /*MOV EBX, TOP*/ + addbyte(0x5d); + addbyte((uint8_t) cpu_state_offset(TOP)); + addbyte(0x89); /*MOV [ESP], EAX*/ + addbyte(0x04); + addbyte(0x24); + addbyte(0x83); /*SUB EBX, 1*/ + addbyte(0xeb); + addbyte(1); + addbyte(0xd9); /*FLD [ESP]*/ + addbyte(0x04); + addbyte(0x24); + addbyte(0x83); /*AND EBX, 7*/ + addbyte(0xe3); + addbyte(7); + addbyte(0x85); /*TEST EAX, EAX*/ + addbyte(0xc0); + addbyte(0x89); /*MOV TOP, EBX*/ + addbyte(0x5d); + addbyte((uint8_t) cpu_state_offset(TOP)); + addbyte(0xdd); /*FSTP [ST+EBX*8]*/ + addbyte(0x5c); + addbyte(0xdd); + addbyte((uint8_t) cpu_state_offset(ST)); + addbyte(0x0f); /*SETE [tag+EBX]*/ + addbyte(0x94); + addbyte(0x44); + addbyte(0x1d); + addbyte((uint8_t) cpu_state_offset(tag[0])); + } +} +static __inline void +FP_LOAD_D(void) +{ + if (codeblock[block_current].flags & CODEBLOCK_STATIC_TOP) { + addbyte(0x89); /*MOV ST[reg][EBP], EAX*/ + addbyte(0x45); + addbyte((uint8_t) cpu_state_offset(ST[(cpu_state.TOP - 1) & 7])); + addbyte(0x09); /*OR EAX, EDX*/ + addbyte(0xd0); + addbyte(0x89); /*MOV ST[reg][EBP]+4, EDX*/ + addbyte(0x55); + addbyte((uint8_t) cpu_state_offset(ST[(cpu_state.TOP - 1) & 7]) + 4); + addbyte(0xc6); /*MOVB TOP[EBP], (TOP-1) & 7*/ + addbyte(0x45); + addbyte((uint8_t) cpu_state_offset(TOP)); + addbyte((cpu_state.TOP - 1) & 7); + addbyte(0x0f); /*SETE tag[reg][EBP]*/ + addbyte(0x94); + addbyte(0x45); + addbyte((uint8_t) cpu_state_offset(tag[(cpu_state.TOP - 1) & 7])); + } else { + addbyte(0x8b); /*MOV EBX, TOP*/ + addbyte(0x5d); + addbyte((uint8_t) cpu_state_offset(TOP)); + addbyte(0x89); /*MOV [ESP], EAX*/ + addbyte(0x04); + addbyte(0x24); + addbyte(0x89); /*MOV [ESP+4], EDX*/ + addbyte(0x54); + addbyte(0x24); + addbyte(0x04); + addbyte(0x83); /*SUB EBX, 1*/ + addbyte(0xeb); + addbyte(1); + addbyte(0x09); /*OR EAX, EDX*/ + addbyte(0xd0); + addbyte(0xdd); /*FLD [ESP]*/ + addbyte(0x04); + addbyte(0x24); + addbyte(0x83); /*AND EBX, 7*/ + addbyte(0xe3); + addbyte(7); + addbyte(0x83); /*CMP EAX, 0*/ + addbyte(0xf8); + addbyte(0); + addbyte(0x89); /*MOV TOP, EBX*/ + addbyte(0x5d); + addbyte((uint8_t) cpu_state_offset(TOP)); + addbyte(0xdd); /*FSTP [ST+EBX*8]*/ + addbyte(0x5c); + addbyte(0xdd); + addbyte((uint8_t) cpu_state_offset(ST)); + addbyte(0x0f); /*SETE [tag+EBX]*/ + addbyte(0x94); + addbyte(0x44); + addbyte(0x1d); + addbyte((uint8_t) cpu_state_offset(tag[0])); + } +} +static __inline void +FP_LOAD_IW(void) +{ + if (codeblock[block_current].flags & CODEBLOCK_STATIC_TOP) { + addbyte(0x66); /*MOV [ESP], AX*/ + addbyte(0x89); + addbyte(0x04); + addbyte(0x24); + addbyte(0x66); /*TEST AX, AX*/ + addbyte(0x85); + addbyte(0xc0); + addbyte(0xdf); /*FILDw [ESP]*/ + addbyte(0x04); + addbyte(0x24); + addbyte(0xc6); /*MOVB TOP[EBP], (TOP-1) & 7*/ + addbyte(0x45); + addbyte((uint8_t) cpu_state_offset(TOP)); + addbyte((cpu_state.TOP - 1) & 7); + addbyte(0x0f); /*SETE tag[reg][EBP]*/ + addbyte(0x94); + addbyte(0x45); + addbyte((uint8_t) cpu_state_offset(tag[(cpu_state.TOP - 1) & 7])); + addbyte(0xdd); /*FSTP ST[reg][EBP]*/ + addbyte(0x5d); + addbyte((uint8_t) cpu_state_offset(ST[(cpu_state.TOP - 1) & 7])); + } else { + addbyte(0x8b); /*MOV EBX, TOP*/ + addbyte(0x5d); + addbyte((uint8_t) cpu_state_offset(TOP)); + addbyte(0x89); /*MOV [ESP], EAX*/ + addbyte(0x04); + addbyte(0x24); + addbyte(0x83); /*SUB EBX, 1*/ + addbyte(0xeb); + addbyte(1); + addbyte(0xdf); /*FILDw [ESP]*/ + addbyte(0x04); + addbyte(0x24); + addbyte(0x83); /*AND EBX, 7*/ + addbyte(0xe3); + addbyte(7); + addbyte(0x83); /*CMP EAX, 0*/ + addbyte(0xf8); + addbyte(0); + addbyte(0x89); /*MOV TOP, EBX*/ + addbyte(0x5d); + addbyte((uint8_t) cpu_state_offset(TOP)); + addbyte(0xdd); /*FSTP [ST+EBX*8]*/ + addbyte(0x5c); + addbyte(0xdd); + addbyte((uint8_t) cpu_state_offset(ST)); + addbyte(0x0f); /*SETE [tag+EBX]*/ + addbyte(0x94); + addbyte(0x44); + addbyte(0x1d); + addbyte((uint8_t) cpu_state_offset(tag[0])); + } +} +static __inline void +FP_LOAD_IL(void) +{ + if (codeblock[block_current].flags & CODEBLOCK_STATIC_TOP) { + addbyte(0x89); /*MOV [ESP], EAX*/ + addbyte(0x04); + addbyte(0x24); + addbyte(0x85); /*TEST EAX, EAX*/ + addbyte(0xc0); + addbyte(0xdb); /*FILDl [ESP]*/ + addbyte(0x04); + addbyte(0x24); + addbyte(0xc6); /*MOVB TOP[EBP], (TOP-1) & 7*/ + addbyte(0x45); + addbyte((uint8_t) cpu_state_offset(TOP)); + addbyte((cpu_state.TOP - 1) & 7); + addbyte(0x0f); /*SETE tag[reg][EBP]*/ + addbyte(0x94); + addbyte(0x45); + addbyte((uint8_t) cpu_state_offset(tag[(cpu_state.TOP - 1) & 7])); + addbyte(0xdd); /*FSTP ST[reg][EBP]*/ + addbyte(0x5d); + addbyte((uint8_t) cpu_state_offset(ST[(cpu_state.TOP - 1) & 7])); + } else { + addbyte(0x8b); /*MOV EBX, TOP*/ + addbyte(0x5d); + addbyte((uint8_t) cpu_state_offset(TOP)); + addbyte(0x89); /*MOV [ESP], EAX*/ + addbyte(0x04); + addbyte(0x24); + addbyte(0x83); /*SUB EBX, 1*/ + addbyte(0xeb); + addbyte(1); + addbyte(0xdb); /*FILDl [ESP]*/ + addbyte(0x04); + addbyte(0x24); + addbyte(0x83); /*AND EBX, 7*/ + addbyte(0xe3); + addbyte(7); + addbyte(0x83); /*CMP EAX, 0*/ + addbyte(0xf8); + addbyte(0); + addbyte(0x89); /*MOV TOP, EBX*/ + addbyte(0x5d); + addbyte((uint8_t) cpu_state_offset(TOP)); + addbyte(0xdd); /*FSTP [ST+EBX*8]*/ + addbyte(0x5c); + addbyte(0xdd); + addbyte((uint8_t) cpu_state_offset(ST)); + addbyte(0x0f); /*SETE [tag+EBX]*/ + addbyte(0x94); + addbyte(0x44); + addbyte(0x1d); + addbyte((uint8_t) cpu_state_offset(tag[0])); + } +} +static __inline void +FP_LOAD_IQ(void) +{ + if (codeblock[block_current].flags & CODEBLOCK_STATIC_TOP) { + addbyte(0x89); /*MOV MM[reg][EBP], EAX*/ + addbyte(0x45); + addbyte((uint8_t) cpu_state_offset(MM[(cpu_state.TOP - 1) & 7].q)); + addbyte(0x09); /*OR EAX, EDX*/ + addbyte(0xd0); + addbyte(0x89); /*MOV MM[reg][EBP]+4, EDX*/ + addbyte(0x55); + addbyte((uint8_t) cpu_state_offset(MM[(cpu_state.TOP - 1) & 7].q) + 4); + addbyte(0x0f); /*SETE AL*/ + addbyte(0x94); + addbyte(0xc0); + addbyte(0xdf); /*FILDq MM[reg][EBP]*/ + addbyte(0x6d); + addbyte((uint8_t) cpu_state_offset(MM[(cpu_state.TOP - 1) & 7].q)); + addbyte(0x0c); /*OR AL, TAG_UINT64*/ + addbyte(TAG_UINT64); + addbyte(0xc6); /*MOVB TOP[EBP], (TOP-1) & 7*/ + addbyte(0x45); + addbyte((uint8_t) cpu_state_offset(TOP)); + addbyte((cpu_state.TOP - 1) & 7); + addbyte(0x88); /*MOV tag[reg][EBP], AL*/ + addbyte(0x45); + addbyte((uint8_t) cpu_state_offset(tag[(cpu_state.TOP - 1) & 7])); + addbyte(0xdd); /*FSTP ST[reg][EBP]*/ + addbyte(0x5d); + addbyte((uint8_t) cpu_state_offset(ST[(cpu_state.TOP - 1) & 7])); + } else { + addbyte(0x8b); /*MOV EBX, TOP*/ + addbyte(0x5d); + addbyte((uint8_t) cpu_state_offset(TOP)); + addbyte(0x83); /*SUB EBX, 1*/ + addbyte(0xeb); + addbyte(1); + addbyte(0x83); /*AND EBX, 7*/ + addbyte(0xe3); + addbyte(7); + addbyte(0x89); /*MOV [ST_i64+EBX*8], EAX*/ + addbyte(0x44); + addbyte(0xdd); + addbyte((uint8_t) cpu_state_offset(MM)); + addbyte(0x09); /*OR EAX, EDX*/ + addbyte(0xd0); + addbyte(0x89); /*MOV [ST_i64+4+EBX*8], EDX*/ + addbyte(0x54); + addbyte(0xdd); + addbyte((uint8_t) cpu_state_offset(MM) + 4); + addbyte(0x83); /*CMP EAX, 0*/ + addbyte(0xf8); + addbyte(0); + addbyte(0xdf); /*FILDl [ST_i64+EBX*8]*/ + addbyte(0x6c); + addbyte(0xdd); + addbyte((uint8_t) cpu_state_offset(MM)); + addbyte(0x0f); /*SETE AL*/ + addbyte(0x94); + addbyte(0xc0); + addbyte(0xdd); /*FSTP [ST+EBX*8]*/ + addbyte(0x5c); + addbyte(0xdd); + addbyte((uint8_t) cpu_state_offset(ST)); + addbyte(0x0c); /*OR AL, TAG_UINT64*/ + addbyte(TAG_UINT64); + addbyte(0x89); /*MOV TOP, EBX*/ + addbyte(0x5d); + addbyte((uint8_t) cpu_state_offset(TOP)); + addbyte(0x88); /*MOV [tag+EBX], AL*/ + addbyte(0x44); + addbyte(0x1d); + addbyte((uint8_t) cpu_state_offset(tag[0])); + } +} + +static __inline void +FP_LOAD_IMM_Q(uint64_t v) +{ + if (codeblock[block_current].flags & CODEBLOCK_STATIC_TOP) { + addbyte(0xc7); /*MOV ST[reg][EBP], v*/ + addbyte(0x45); + addbyte((uint8_t) cpu_state_offset(ST[(cpu_state.TOP - 1) & 7])); + addlong(v & 0xffffffff); + addbyte(0xc7); /*MOV ST[reg][EBP]+4, v*/ + addbyte(0x45); + addbyte((uint8_t) cpu_state_offset(ST[(cpu_state.TOP - 1) & 7]) + 4); + addlong(v >> 32); + addbyte(0xc6); /*MOVB TOP[EBP], (TOP-1) & 7*/ + addbyte(0x45); + addbyte((uint8_t) cpu_state_offset(TOP)); + addbyte((cpu_state.TOP - 1) & 7); + addbyte(0xc6); /*MOVB tag[reg][EBP], 1:0*/ + addbyte(0x45); + addbyte((uint8_t) cpu_state_offset(tag[(cpu_state.TOP - 1) & 7])); + addbyte(v ? 0 : 1); + } else { + addbyte(0x8b); /*MOV EBX, TOP*/ + addbyte(0x5d); + addbyte((uint8_t) cpu_state_offset(TOP)); + addbyte(0x83); /*SUB EBX, 1*/ + addbyte(0xeb); + addbyte(1); + addbyte(0x83); /*AND EBX, 7*/ + addbyte(0xe3); + addbyte(7); + addbyte(0xc7); /*MOV ST[EBP+EBX*8], v*/ + addbyte(0x44); + addbyte(0xdd); + addbyte((uint8_t) cpu_state_offset(ST)); + addlong(v & 0xffffffff); + addbyte(0xc7); /*MOV ST[EBP+EBX*8]+4, v*/ + addbyte(0x44); + addbyte(0xdd); + addbyte((uint8_t) cpu_state_offset(ST) + 4); + addlong(v >> 32); + addbyte(0xc6); /*MOVB tag[reg][EBP], 1:0*/ + addbyte(0x44); + addbyte(0x1d); + addbyte((uint8_t) cpu_state_offset(tag[0])); + addbyte(v ? 0 : 1); + addbyte(0x89); /*MOV TOP, EBX*/ + addbyte(0x5d); + addbyte((uint8_t) cpu_state_offset(TOP)); + } +} + +static __inline int +FP_LOAD_REG(int reg) +{ + if (codeblock[block_current].flags & CODEBLOCK_STATIC_TOP) { + addbyte(0xdd); /*FLD ST[reg][EBP]*/ + addbyte(0x45); + addbyte((uint8_t) cpu_state_offset(ST[(cpu_state.TOP + reg) & 7])); + } else { + addbyte(0x8b); /*MOV EBX, TOP*/ + addbyte(0x5d); + addbyte((uint8_t) cpu_state_offset(TOP)); + if (reg) { + addbyte(0x83); /*ADD EBX, reg*/ + addbyte(0xc3); + addbyte(reg); + addbyte(0x83); /*AND EBX, 7*/ + addbyte(0xe3); + addbyte(7); + } + addbyte(0xdd); /*FLD ST[EBX*8]*/ + addbyte(0x44); + addbyte(0xdd); + addbyte((uint8_t) cpu_state_offset(ST)); + } + addbyte(0xd9); /*FSTP [ESP]*/ + addbyte(0x1c); + addbyte(0x24); + addbyte(0x8b); /*MOV EAX, [ESP]*/ + addbyte(0x04 | (REG_EBX << 3)); + addbyte(0x24); + + return REG_EBX; +} + +static __inline void +FP_LOAD_REG_D(int reg, int *host_reg1, int *host_reg2) +{ + if (codeblock[block_current].flags & CODEBLOCK_STATIC_TOP) { + addbyte(0xdd); /*FLD ST[reg][EBP]*/ + addbyte(0x45); + addbyte((uint8_t) cpu_state_offset(ST[(cpu_state.TOP + reg) & 7])); + } else { + addbyte(0x8b); /*MOV EBX, TOP*/ + addbyte(0x5d); + addbyte((uint8_t) cpu_state_offset(TOP)); + if (reg) { + addbyte(0x83); /*ADD EBX, reg*/ + addbyte(0xc3); + addbyte(reg); + addbyte(0x83); /*AND EBX, 7*/ + addbyte(0xe3); + addbyte(7); + } + addbyte(0xdd); /*FLD ST[EBX*8]*/ + addbyte(0x44); + addbyte(0xdd); + addbyte((uint8_t) cpu_state_offset(ST)); + } + addbyte(0xdd); /*FSTP [ESP]*/ + addbyte(0x1c); + addbyte(0x24); + addbyte(0x8b); /*MOV EBX, [ESP]*/ + addbyte(0x04 | (REG_EBX << 3)); + addbyte(0x24); + addbyte(0x8b); /*MOV ECX, [ESP+4]*/ + addbyte(0x44 | (REG_ECX << 3)); + addbyte(0x24); + addbyte(0x04); + + *host_reg1 = REG_EBX; + *host_reg2 = REG_ECX; +} + +static __inline int +FP_LOAD_REG_INT_W(int reg) +{ + addbyte(0x8b); /*MOV EBX, TOP*/ + addbyte(0x5d); + addbyte((uint8_t) cpu_state_offset(TOP)); + if (reg) { + addbyte(0x83); /*ADD EBX, reg*/ + addbyte(0xc3); + addbyte(reg); + addbyte(0x83); /*AND EBX, 7*/ + addbyte(0xe3); + addbyte(7); + } + addbyte(0xdd); /*FLD ST[EBX*8]*/ + addbyte(0x44); + addbyte(0xdd); + addbyte((uint8_t) cpu_state_offset(ST)); + + addbyte(0xd9); /*FLDCW cpu_state.new_npxc*/ + addbyte(0x6d); + addbyte((uint8_t) cpu_state_offset(new_npxc)); + addbyte(0xdb); /*FISTP [ESP]*/ + addbyte(0x1c); + addbyte(0x24); + addbyte(0xd9); /*FLDCW cpu_state.old_npxc*/ + addbyte(0x6d); + addbyte((uint8_t) cpu_state_offset(old_npxc)); + addbyte(0x8b); /*MOV EBX, [ESP]*/ + addbyte(0x1c); + addbyte(0x24); + + return REG_EBX; +} +static __inline int +FP_LOAD_REG_INT(int reg) +{ + addbyte(0x8b); /*MOV EBX, TOP*/ + addbyte(0x5d); + addbyte((uint8_t) cpu_state_offset(TOP)); + if (reg) { + addbyte(0x83); /*ADD EBX, reg*/ + addbyte(0xc3); + addbyte(reg); + addbyte(0x83); /*AND EBX, 7*/ + addbyte(0xe3); + addbyte(7); + } + addbyte(0xdd); /*FLD ST[EBX*8]*/ + addbyte(0x44); + addbyte(0xdd); + addbyte((uint8_t) cpu_state_offset(ST)); + + addbyte(0xd9); /*FLDCW cpu_state.new_npxc*/ + addbyte(0x6d); + addbyte((uint8_t) cpu_state_offset(new_npxc)); + addbyte(0xdb); /*FISTP [ESP]*/ + addbyte(0x1c); + addbyte(0x24); + addbyte(0xd9); /*FLDCW cpu_state.old_npxc*/ + addbyte(0x6d); + addbyte((uint8_t) cpu_state_offset(old_npxc)); + addbyte(0x8b); /*MOV EBX, [ESP]*/ + addbyte(0x1c); + addbyte(0x24); + + return REG_EBX; +} +static __inline void +FP_LOAD_REG_INT_Q(int reg, int *host_reg1, int *host_reg2) +{ + addbyte(0x8b); /*MOV EBX, TOP*/ + addbyte(0x5d); + addbyte((uint8_t) cpu_state_offset(TOP)); + if (reg) { + addbyte(0x83); /*ADD EBX, reg*/ + addbyte(0xc3); + addbyte(reg); + addbyte(0x83); /*AND EBX, 7*/ + addbyte(0xe3); + addbyte(7); + } + if (codegen_fpu_loaded_iq[cpu_state.TOP] && (cpu_state.tag[cpu_state.TOP] & TAG_UINT64)) { + /*If we know the register was loaded with FILDq in this block and + has not been modified, then we can skip most of the conversion + and just load the 64-bit integer representation directly */ addbyte(0x8b); /*MOV ECX, [ST_i64+EBX*8]*/ addbyte(0x4c); addbyte(0xdd); - addbyte((uint8_t)cpu_state_offset(MM)+4); + addbyte((uint8_t) cpu_state_offset(MM) + 4); addbyte(0x8b); /*MOV EBX, [ST_i64+EBX*8]*/ addbyte(0x5c); addbyte(0xdd); - addbyte((uint8_t)cpu_state_offset(MM)); - - addbyte(0xeb); /*JMP done*/ - addbyte(4+3+3+3+3+4); - - addbyte(0xdd); /*FLD ST[EBX*8]*/ + addbyte((uint8_t) cpu_state_offset(MM)); + + return; + } + + addbyte(0xf6); /*TEST TAG[EBX], TAG_UINT64*/ + addbyte(0x44); + addbyte(0x1d); + addbyte((uint8_t) cpu_state_offset(tag[0])); + addbyte(TAG_UINT64); + addbyte(0x74); /*JZ +*/ + addbyte(4 + 4 + 2); + + addbyte(0x8b); /*MOV ECX, [ST_i64+EBX*8]*/ + addbyte(0x4c); + addbyte(0xdd); + addbyte((uint8_t) cpu_state_offset(MM) + 4); + addbyte(0x8b); /*MOV EBX, [ST_i64+EBX*8]*/ + addbyte(0x5c); + addbyte(0xdd); + addbyte((uint8_t) cpu_state_offset(MM)); + + addbyte(0xeb); /*JMP done*/ + addbyte(4 + 3 + 3 + 3 + 3 + 4); + + addbyte(0xdd); /*FLD ST[EBX*8]*/ + addbyte(0x44); + addbyte(0xdd); + addbyte((uint8_t) cpu_state_offset(ST)); + + addbyte(0xd9); /*FLDCW cpu_state.new_npxc*/ + addbyte(0x6d); + addbyte((uint8_t) cpu_state_offset(new_npxc)); + addbyte(0xdf); /*FISTPQ [ESP]*/ + addbyte(0x3c); + addbyte(0x24); + addbyte(0xd9); /*FLDCW cpu_state.old_npxc*/ + addbyte(0x6d); + addbyte((uint8_t) cpu_state_offset(old_npxc)); + addbyte(0x8b); /*MOV EBX, [ESP]*/ + addbyte(0x1c); + addbyte(0x24); + addbyte(0x8b); /*MOV ECX, 4[ESP]*/ + addbyte(0x4c); + addbyte(0x24); + addbyte(4); + + *host_reg1 = REG_EBX; + *host_reg2 = REG_ECX; +} + +static __inline void +FP_POP(void) +{ + if (codeblock[block_current].flags & CODEBLOCK_STATIC_TOP) { + addbyte(0xc6); /*MOVB tag[0][EBP], 3*/ + addbyte(0x45); + addbyte((uint8_t) cpu_state_offset(tag[cpu_state.TOP])); + addbyte(3); + addbyte(0xc6); /*MOVB TOP[EBP], (TOP-1) & 7*/ + addbyte(0x45); + addbyte((uint8_t) cpu_state_offset(TOP)); + addbyte((cpu_state.TOP + 1) & 7); + } else { + addbyte(0x8b); /*MOV EAX, TOP*/ + addbyte(0x45); + addbyte((uint8_t) cpu_state_offset(TOP)); + addbyte(0xc6); /*MOVB tag[EAX], 3*/ addbyte(0x44); - addbyte(0xdd); - addbyte((uint8_t)cpu_state_offset(ST)); - - addbyte(0xd9); /*FLDCW cpu_state.new_npxc*/ - addbyte(0x6d); - addbyte((uint8_t)cpu_state_offset(new_npxc)); - addbyte(0xdf); /*FISTPQ [ESP]*/ - addbyte(0x3c); - addbyte(0x24); - addbyte(0xd9); /*FLDCW cpu_state.old_npxc*/ - addbyte(0x6d); - addbyte((uint8_t)cpu_state_offset(old_npxc)); - addbyte(0x8b); /*MOV EBX, [ESP]*/ - addbyte(0x1c); - addbyte(0x24); - addbyte(0x8b); /*MOV ECX, 4[ESP]*/ - addbyte(0x4c); - addbyte(0x24); - addbyte(4); - - *host_reg1 = REG_EBX; - *host_reg2 = REG_ECX; + addbyte(0x05); + addbyte((uint8_t) cpu_state_offset(tag[0])); + addbyte(3); + addbyte(0x04); /*ADD AL, 1*/ + addbyte(1); + addbyte(0x24); /*AND AL, 7*/ + addbyte(7); + addbyte(0x88); /*MOV TOP, AL*/ + addbyte(0x45); + addbyte((uint8_t) cpu_state_offset(TOP)); + } } - -static inline void FP_POP() +static __inline void +FP_POP2(void) { - if (codeblock[block_current].flags & CODEBLOCK_STATIC_TOP) - { - addbyte(0xc6); /*MOVB tag[0][EBP], 3*/ - addbyte(0x45); - addbyte((uint8_t)cpu_state_offset(tag[cpu_state.TOP])); - addbyte(3); - addbyte(0xc6); /*MOVB TOP[EBP], (TOP-1) & 7*/ - addbyte(0x45); - addbyte((uint8_t)cpu_state_offset(TOP)); - addbyte((cpu_state.TOP + 1) & 7); - } - else - { - addbyte(0x8b); /*MOV EAX, TOP*/ - addbyte(0x45); - addbyte((uint8_t)cpu_state_offset(TOP)); - addbyte(0xc6); /*MOVB tag[EAX], 3*/ - addbyte(0x44); - addbyte(0x05); - addbyte((uint8_t)cpu_state_offset(tag[0])); - addbyte(3); - addbyte(0x04); /*ADD AL, 1*/ - addbyte(1); - addbyte(0x24); /*AND AL, 7*/ - addbyte(7); - addbyte(0x88); /*MOV TOP, AL*/ - addbyte(0x45); - addbyte((uint8_t)cpu_state_offset(TOP)); - } -} -static inline void FP_POP2() -{ - if (codeblock[block_current].flags & CODEBLOCK_STATIC_TOP) - { - addbyte(0xc6); /*MOVB tag[0][EBP], 3*/ - addbyte(0x45); - addbyte((uint8_t)cpu_state_offset(tag[cpu_state.TOP])); - addbyte(3); - addbyte(0xc6); /*MOVB tag[1][EBP], 3*/ - addbyte(0x45); - addbyte((uint8_t)cpu_state_offset(tag[(cpu_state.TOP+1)&7])); - addbyte(3); - addbyte(0xc6); /*MOVB TOP[EBP], (TOP+2) & 7*/ - addbyte(0x45); - addbyte((uint8_t)cpu_state_offset(TOP)); - addbyte((cpu_state.TOP + 2) & 7); - } - else - { - addbyte(0x8b); /*MOV EAX, TOP*/ - addbyte(0x45); - addbyte((uint8_t)cpu_state_offset(TOP)); - addbyte(0xc6); /*MOVB tag[EAX], 3*/ - addbyte(0x44); - addbyte(0x05); - addbyte((uint8_t)cpu_state_offset(tag[0])); - addbyte(3); - addbyte(0x04); /*ADD AL, 2*/ - addbyte(2); - addbyte(0x24); /*AND AL, 7*/ - addbyte(7); - addbyte(0x88); /*MOV TOP, AL*/ - addbyte(0x45); - addbyte((uint8_t)cpu_state_offset(TOP)); - } + if (codeblock[block_current].flags & CODEBLOCK_STATIC_TOP) { + addbyte(0xc6); /*MOVB tag[0][EBP], 3*/ + addbyte(0x45); + addbyte((uint8_t) cpu_state_offset(tag[cpu_state.TOP])); + addbyte(3); + addbyte(0xc6); /*MOVB tag[1][EBP], 3*/ + addbyte(0x45); + addbyte((uint8_t) cpu_state_offset(tag[(cpu_state.TOP + 1) & 7])); + addbyte(3); + addbyte(0xc6); /*MOVB TOP[EBP], (TOP+2) & 7*/ + addbyte(0x45); + addbyte((uint8_t) cpu_state_offset(TOP)); + addbyte((cpu_state.TOP + 2) & 7); + } else { + addbyte(0x8b); /*MOV EAX, TOP*/ + addbyte(0x45); + addbyte((uint8_t) cpu_state_offset(TOP)); + addbyte(0xc6); /*MOVB tag[EAX], 3*/ + addbyte(0x44); + addbyte(0x05); + addbyte((uint8_t) cpu_state_offset(tag[0])); + addbyte(3); + addbyte(0x04); /*ADD AL, 2*/ + addbyte(2); + addbyte(0x24); /*AND AL, 7*/ + addbyte(7); + addbyte(0x88); /*MOV TOP, AL*/ + addbyte(0x45); + addbyte((uint8_t) cpu_state_offset(TOP)); + } } #define FPU_ADD 0x00 @@ -2692,229 +2627,217 @@ static inline void FP_POP2() #define FPU_SUB 0x20 #define FPU_SUBR 0x28 -static inline void FP_OP_S(int op) +static __inline void +FP_OP_S(int op) { - if (codeblock[block_current].flags & CODEBLOCK_STATIC_TOP) - { - addbyte(0x89); /*MOV [ESP], EAX*/ - addbyte(0x04); - addbyte(0x24); - addbyte(0xdd); /*FLD ST[dst][EBP]*/ - addbyte(0x45); - addbyte((uint8_t)cpu_state_offset(ST[cpu_state.TOP])); - addbyte(0x80); /*AND tag[dst][EBP], ~TAG_UINT64*/ - addbyte(0x65); - addbyte((uint8_t)cpu_state_offset(tag[cpu_state.TOP])); - addbyte(TAG_NOT_UINT64); - addbyte(0xd8); /*FADD [ESP]*/ - addbyte(0x04 | op); - addbyte(0x24); - addbyte(0xdd); /*FSTP ST[dst][EBP]*/ - addbyte(0x5d); - addbyte((uint8_t)cpu_state_offset(ST[cpu_state.TOP])); - } - else - { - addbyte(0x8b); /*MOV EBX, TOP*/ - addbyte(0x5d); - addbyte((uint8_t)cpu_state_offset(TOP)); - addbyte(0x89); /*MOV [ESP], EAX*/ - addbyte(0x04); - addbyte(0x24); - addbyte(0xdd); /*FLD ST[EBX*8]*/ - addbyte(0x44); - addbyte(0xdd); - addbyte((uint8_t)cpu_state_offset(ST)); - addbyte(0x80); /*AND tag[EBX], ~TAG_UINT64*/ - addbyte(0x64); - addbyte(0x1d); - addbyte((uint8_t)cpu_state_offset(tag[0])); - addbyte(TAG_NOT_UINT64); - addbyte(0xd8); /*FADD [ESP]*/ - addbyte(0x04 | op); - addbyte(0x24); - addbyte(0xdd); /*FSTP [ST+EBX*8]*/ - addbyte(0x5c); - addbyte(0xdd); - addbyte((uint8_t)cpu_state_offset(ST)); - } + if (codeblock[block_current].flags & CODEBLOCK_STATIC_TOP) { + addbyte(0x89); /*MOV [ESP], EAX*/ + addbyte(0x04); + addbyte(0x24); + addbyte(0xdd); /*FLD ST[dst][EBP]*/ + addbyte(0x45); + addbyte((uint8_t) cpu_state_offset(ST[cpu_state.TOP])); + addbyte(0x80); /*AND tag[dst][EBP], ~TAG_UINT64*/ + addbyte(0x65); + addbyte((uint8_t) cpu_state_offset(tag[cpu_state.TOP])); + addbyte(TAG_NOT_UINT64); + addbyte(0xd8); /*FADD [ESP]*/ + addbyte(0x04 | op); + addbyte(0x24); + addbyte(0xdd); /*FSTP ST[dst][EBP]*/ + addbyte(0x5d); + addbyte((uint8_t) cpu_state_offset(ST[cpu_state.TOP])); + } else { + addbyte(0x8b); /*MOV EBX, TOP*/ + addbyte(0x5d); + addbyte((uint8_t) cpu_state_offset(TOP)); + addbyte(0x89); /*MOV [ESP], EAX*/ + addbyte(0x04); + addbyte(0x24); + addbyte(0xdd); /*FLD ST[EBX*8]*/ + addbyte(0x44); + addbyte(0xdd); + addbyte((uint8_t) cpu_state_offset(ST)); + addbyte(0x80); /*AND tag[EBX], ~TAG_UINT64*/ + addbyte(0x64); + addbyte(0x1d); + addbyte((uint8_t) cpu_state_offset(tag[0])); + addbyte(TAG_NOT_UINT64); + addbyte(0xd8); /*FADD [ESP]*/ + addbyte(0x04 | op); + addbyte(0x24); + addbyte(0xdd); /*FSTP [ST+EBX*8]*/ + addbyte(0x5c); + addbyte(0xdd); + addbyte((uint8_t) cpu_state_offset(ST)); + } } -static inline void FP_OP_D(int op) +static __inline void +FP_OP_D(int op) { - if (codeblock[block_current].flags & CODEBLOCK_STATIC_TOP) - { - addbyte(0x89); /*MOV [ESP], EAX*/ - addbyte(0x04); - addbyte(0x24); - addbyte(0x89); /*MOV [ESP+4], EDX*/ - addbyte(0x54); - addbyte(0x24); - addbyte(0x04); - if (((cpu_state.npxc >> 10) & 3) && op == FPU_ADD) - { - addbyte(0xd9); /*FLDCW cpu_state.new_npxc*/ - addbyte(0x6d); - addbyte((uint8_t)cpu_state_offset(new_npxc)); - } - addbyte(0xdd); /*FLD ST[dst][EBP]*/ - addbyte(0x45); - addbyte((uint8_t)cpu_state_offset(ST[cpu_state.TOP])); - addbyte(0x80); /*AND tag[dst][EBP], ~TAG_UINT64*/ - addbyte(0x65); - addbyte((uint8_t)cpu_state_offset(tag[cpu_state.TOP])); - addbyte(TAG_NOT_UINT64); - addbyte(0xdc); /*FADD [ESP]*/ - addbyte(0x04 | op); - addbyte(0x24); - addbyte(0xdd); /*FSTP ST[dst][EBP]*/ - addbyte(0x5d); - addbyte((uint8_t)cpu_state_offset(ST[cpu_state.TOP])); - if (((cpu_state.npxc >> 10) & 3) && op == FPU_ADD) - { - addbyte(0xd9); /*FLDCW cpu_state.old_npxc*/ - addbyte(0x6d); - addbyte((uint8_t)cpu_state_offset(old_npxc)); - } + if (codeblock[block_current].flags & CODEBLOCK_STATIC_TOP) { + addbyte(0x89); /*MOV [ESP], EAX*/ + addbyte(0x04); + addbyte(0x24); + addbyte(0x89); /*MOV [ESP+4], EDX*/ + addbyte(0x54); + addbyte(0x24); + addbyte(0x04); + if (((cpu_state.npxc >> 10) & 3) && op == FPU_ADD) { + addbyte(0xd9); /*FLDCW cpu_state.new_npxc*/ + addbyte(0x6d); + addbyte((uint8_t) cpu_state_offset(new_npxc)); } - else - { - addbyte(0x8b); /*MOV EBX, TOP*/ - addbyte(0x5d); - addbyte((uint8_t)cpu_state_offset(TOP)); - addbyte(0x89); /*MOV [ESP], EAX*/ - addbyte(0x04); - addbyte(0x24); - if (((cpu_state.npxc >> 10) & 3) && op == FPU_ADD) - { - addbyte(0xd9); /*FLDCW cpu_state.new_npxc*/ - addbyte(0x6d); - addbyte((uint8_t)cpu_state_offset(new_npxc)); - } - addbyte(0x89); /*MOV [ESP+4], EDX*/ - addbyte(0x54); - addbyte(0x24); - addbyte(0x04); - addbyte(0xdd); /*FLD ST[EBX*8]*/ - addbyte(0x44); - addbyte(0xdd); - addbyte((uint8_t)cpu_state_offset(ST)); - addbyte(0x80); /*AND tag[EBX], ~TAG_UINT64*/ - addbyte(0x64); - addbyte(0x1d); - addbyte((uint8_t)cpu_state_offset(tag[0])); - addbyte(TAG_NOT_UINT64); - addbyte(0xdc); /*FADD [ESP]*/ - addbyte(0x04 | op); - addbyte(0x24); - addbyte(0xdd); /*FSTP [ST+EBX*8]*/ - addbyte(0x5c); - addbyte(0xdd); - addbyte((uint8_t)cpu_state_offset(ST)); - if (((cpu_state.npxc >> 10) & 3) && op == FPU_ADD) - { - addbyte(0xd9); /*FLDCW cpu_state.old_npxc*/ - addbyte(0x6d); - addbyte((uint8_t)cpu_state_offset(old_npxc)); - } - } + addbyte(0xdd); /*FLD ST[dst][EBP]*/ + addbyte(0x45); + addbyte((uint8_t) cpu_state_offset(ST[cpu_state.TOP])); + addbyte(0x80); /*AND tag[dst][EBP], ~TAG_UINT64*/ + addbyte(0x65); + addbyte((uint8_t) cpu_state_offset(tag[cpu_state.TOP])); + addbyte(TAG_NOT_UINT64); + addbyte(0xdc); /*FADD [ESP]*/ + addbyte(0x04 | op); + addbyte(0x24); + addbyte(0xdd); /*FSTP ST[dst][EBP]*/ + addbyte(0x5d); + addbyte((uint8_t) cpu_state_offset(ST[cpu_state.TOP])); + if (((cpu_state.npxc >> 10) & 3) && op == FPU_ADD) { + addbyte(0xd9); /*FLDCW cpu_state.old_npxc*/ + addbyte(0x6d); + addbyte((uint8_t) cpu_state_offset(old_npxc)); + } + } else { + addbyte(0x8b); /*MOV EBX, TOP*/ + addbyte(0x5d); + addbyte((uint8_t) cpu_state_offset(TOP)); + addbyte(0x89); /*MOV [ESP], EAX*/ + addbyte(0x04); + addbyte(0x24); + if (((cpu_state.npxc >> 10) & 3) && op == FPU_ADD) { + addbyte(0xd9); /*FLDCW cpu_state.new_npxc*/ + addbyte(0x6d); + addbyte((uint8_t) cpu_state_offset(new_npxc)); + } + addbyte(0x89); /*MOV [ESP+4], EDX*/ + addbyte(0x54); + addbyte(0x24); + addbyte(0x04); + addbyte(0xdd); /*FLD ST[EBX*8]*/ + addbyte(0x44); + addbyte(0xdd); + addbyte((uint8_t) cpu_state_offset(ST)); + addbyte(0x80); /*AND tag[EBX], ~TAG_UINT64*/ + addbyte(0x64); + addbyte(0x1d); + addbyte((uint8_t) cpu_state_offset(tag[0])); + addbyte(TAG_NOT_UINT64); + addbyte(0xdc); /*FADD [ESP]*/ + addbyte(0x04 | op); + addbyte(0x24); + addbyte(0xdd); /*FSTP [ST+EBX*8]*/ + addbyte(0x5c); + addbyte(0xdd); + addbyte((uint8_t) cpu_state_offset(ST)); + if (((cpu_state.npxc >> 10) & 3) && op == FPU_ADD) { + addbyte(0xd9); /*FLDCW cpu_state.old_npxc*/ + addbyte(0x6d); + addbyte((uint8_t) cpu_state_offset(old_npxc)); + } + } } -static inline void FP_OP_IW(int op) +static __inline void +FP_OP_IW(int op) { - if (codeblock[block_current].flags & CODEBLOCK_STATIC_TOP) - { - addbyte(0x66); /*MOV [ESP], AX*/ - addbyte(0x89); - addbyte(0x04); - addbyte(0x24); - addbyte(0xdd); /*FLD ST[0][EBP]*/ - addbyte(0x45); - addbyte((uint8_t)cpu_state_offset(ST[cpu_state.TOP])); - addbyte(0x80); /*AND tag[0][EBP], ~TAG_UINT64*/ - addbyte(0x65); - addbyte((uint8_t)cpu_state_offset(tag[cpu_state.TOP])); - addbyte(TAG_NOT_UINT64); - addbyte(0xde); /*FADD [ESP]*/ - addbyte(0x04 | op); - addbyte(0x24); - addbyte(0xdd); /*FSTP ST[0][EBP]*/ - addbyte(0x5d); - addbyte((uint8_t)cpu_state_offset(ST[cpu_state.TOP])); - } - else - { - addbyte(0x8b); /*MOV EBX, TOP*/ - addbyte(0x5d); - addbyte((uint8_t)cpu_state_offset(TOP)); - addbyte(0x89); /*MOV [ESP], EAX*/ - addbyte(0x04); - addbyte(0x24); - addbyte(0xdd); /*FLD ST[EBX*8]*/ - addbyte(0x44); - addbyte(0xdd); - addbyte((uint8_t)cpu_state_offset(ST)); - addbyte(0x80); /*AND tag[EBX], ~TAG_UINT64*/ - addbyte(0x64); - addbyte(0x1d); - addbyte((uint8_t)cpu_state_offset(tag[0])); - addbyte(TAG_NOT_UINT64); - addbyte(0xde); /*FADD [ESP]*/ - addbyte(0x04 | op); - addbyte(0x24); - addbyte(0xdd); /*FSTP [ST+EBX*8]*/ - addbyte(0x5c); - addbyte(0xdd); - addbyte((uint8_t)cpu_state_offset(ST)); - } + if (codeblock[block_current].flags & CODEBLOCK_STATIC_TOP) { + addbyte(0x66); /*MOV [ESP], AX*/ + addbyte(0x89); + addbyte(0x04); + addbyte(0x24); + addbyte(0xdd); /*FLD ST[0][EBP]*/ + addbyte(0x45); + addbyte((uint8_t) cpu_state_offset(ST[cpu_state.TOP])); + addbyte(0x80); /*AND tag[0][EBP], ~TAG_UINT64*/ + addbyte(0x65); + addbyte((uint8_t) cpu_state_offset(tag[cpu_state.TOP])); + addbyte(TAG_NOT_UINT64); + addbyte(0xde); /*FADD [ESP]*/ + addbyte(0x04 | op); + addbyte(0x24); + addbyte(0xdd); /*FSTP ST[0][EBP]*/ + addbyte(0x5d); + addbyte((uint8_t) cpu_state_offset(ST[cpu_state.TOP])); + } else { + addbyte(0x8b); /*MOV EBX, TOP*/ + addbyte(0x5d); + addbyte((uint8_t) cpu_state_offset(TOP)); + addbyte(0x89); /*MOV [ESP], EAX*/ + addbyte(0x04); + addbyte(0x24); + addbyte(0xdd); /*FLD ST[EBX*8]*/ + addbyte(0x44); + addbyte(0xdd); + addbyte((uint8_t) cpu_state_offset(ST)); + addbyte(0x80); /*AND tag[EBX], ~TAG_UINT64*/ + addbyte(0x64); + addbyte(0x1d); + addbyte((uint8_t) cpu_state_offset(tag[0])); + addbyte(TAG_NOT_UINT64); + addbyte(0xde); /*FADD [ESP]*/ + addbyte(0x04 | op); + addbyte(0x24); + addbyte(0xdd); /*FSTP [ST+EBX*8]*/ + addbyte(0x5c); + addbyte(0xdd); + addbyte((uint8_t) cpu_state_offset(ST)); + } } -static inline void FP_OP_IL(int op) +static __inline void +FP_OP_IL(int op) { - if (codeblock[block_current].flags & CODEBLOCK_STATIC_TOP) - { - addbyte(0x89); /*MOV [ESP], EAX*/ - addbyte(0x04); - addbyte(0x24); - addbyte(0xdd); /*FLD ST[0][EBP]*/ - addbyte(0x45); - addbyte((uint8_t)cpu_state_offset(ST[cpu_state.TOP])); - addbyte(0x80); /*AND tag[0][EBP], ~TAG_UINT64*/ - addbyte(0x65); - addbyte((uint8_t)cpu_state_offset(tag[cpu_state.TOP])); - addbyte(TAG_NOT_UINT64); - addbyte(0xda); /*FADD [ESP]*/ - addbyte(0x04 | op); - addbyte(0x24); - addbyte(0xdd); /*FSTP ST[0][EBP]*/ - addbyte(0x5d); - addbyte((uint8_t)cpu_state_offset(ST[cpu_state.TOP])); - } - else - { - addbyte(0x8b); /*MOV EBX, TOP*/ - addbyte(0x5d); - addbyte((uint8_t)cpu_state_offset(TOP)); - addbyte(0x89); /*MOV [ESP], EAX*/ - addbyte(0x04); - addbyte(0x24); - addbyte(0xdd); /*FLD ST[EBX*8]*/ - addbyte(0x44); - addbyte(0xdd); - addbyte((uint8_t)cpu_state_offset(ST)); - addbyte(0x80); /*AND tag[EBX], ~TAG_UINT64*/ - addbyte(0x64); - addbyte(0x1d); - addbyte((uint8_t)cpu_state_offset(tag[0])); - addbyte(TAG_NOT_UINT64); - addbyte(0xda); /*FADD [ESP]*/ - addbyte(0x04 | op); - addbyte(0x24); - addbyte(0xdd); /*FSTP [ST+EBX*8]*/ - addbyte(0x5c); - addbyte(0xdd); - addbyte((uint8_t)cpu_state_offset(ST)); - } + if (codeblock[block_current].flags & CODEBLOCK_STATIC_TOP) { + addbyte(0x89); /*MOV [ESP], EAX*/ + addbyte(0x04); + addbyte(0x24); + addbyte(0xdd); /*FLD ST[0][EBP]*/ + addbyte(0x45); + addbyte((uint8_t) cpu_state_offset(ST[cpu_state.TOP])); + addbyte(0x80); /*AND tag[0][EBP], ~TAG_UINT64*/ + addbyte(0x65); + addbyte((uint8_t) cpu_state_offset(tag[cpu_state.TOP])); + addbyte(TAG_NOT_UINT64); + addbyte(0xda); /*FADD [ESP]*/ + addbyte(0x04 | op); + addbyte(0x24); + addbyte(0xdd); /*FSTP ST[0][EBP]*/ + addbyte(0x5d); + addbyte((uint8_t) cpu_state_offset(ST[cpu_state.TOP])); + } else { + addbyte(0x8b); /*MOV EBX, TOP*/ + addbyte(0x5d); + addbyte((uint8_t) cpu_state_offset(TOP)); + addbyte(0x89); /*MOV [ESP], EAX*/ + addbyte(0x04); + addbyte(0x24); + addbyte(0xdd); /*FLD ST[EBX*8]*/ + addbyte(0x44); + addbyte(0xdd); + addbyte((uint8_t) cpu_state_offset(ST)); + addbyte(0x80); /*AND tag[EBX], ~TAG_UINT64*/ + addbyte(0x64); + addbyte(0x1d); + addbyte((uint8_t) cpu_state_offset(tag[0])); + addbyte(TAG_NOT_UINT64); + addbyte(0xda); /*FADD [ESP]*/ + addbyte(0x04 | op); + addbyte(0x24); + addbyte(0xdd); /*FSTP [ST+EBX*8]*/ + addbyte(0x5c); + addbyte(0xdd); + addbyte((uint8_t) cpu_state_offset(ST)); + } } #if 0 -static inline void FP_OP_IQ(int op) +static __inline void FP_OP_IQ(int op) { if (codeblock[block_current].flags & CODEBLOCK_STATIC_TOP) { @@ -2971,1037 +2894,1035 @@ static inline void FP_OP_IQ(int op) } #endif -static inline void FP_COMPARE_S() +static __inline void +FP_COMPARE_S(void) { - if (codeblock[block_current].flags & CODEBLOCK_STATIC_TOP) - { - addbyte(0x89); /*MOV [ESP], EAX*/ - addbyte(0x04); - addbyte(0x24); - addbyte(0xdd); /*FLD ST[0][EBP]*/ - addbyte(0x45); - addbyte((uint8_t)cpu_state_offset(ST[cpu_state.TOP])); - addbyte(0x8a); /*MOV BL, [npxs+1]*/ - addbyte(0x5d); - addbyte((uint8_t)cpu_state_offset(npxs) + 1); - addbyte(0xdb); /*FCLEX*/ - addbyte(0xe2); - addbyte(0x80); /*AND BL, ~(C0|C2|C3)*/ - addbyte(0xe3); - addbyte((~(C0|C2|C3)) >> 8); - addbyte(0xd8); /*FCOMP [ESP]*/ - addbyte(0x04 | 0x18); - addbyte(0x24); - addbyte(0xdf); /*FSTSW AX*/ - addbyte(0xe0); - addbyte(0x80); /*AND AH, (C0|C2|C3)*/ - addbyte(0xe4); - addbyte((C0|C2|C3) >> 8); - addbyte(0x08); /*OR BL, AH*/ - addbyte(0xe3); - addbyte(0x88); /*MOV [npxs+1], BL*/ - addbyte(0x5d); - addbyte((uint8_t)cpu_state_offset(npxs) + 1); - } - else - { - addbyte(0x8b); /*MOV EBX, TOP*/ - addbyte(0x5d); - addbyte((uint8_t)cpu_state_offset(TOP)); - addbyte(0x89); /*MOV [ESP], EAX*/ - addbyte(0x04); - addbyte(0x24); - addbyte(0xdd); /*FLD ST[EBX*8]*/ - addbyte(0x44); - addbyte(0xdd); - addbyte((uint8_t)cpu_state_offset(ST)); - addbyte(0x8a); /*MOV BL, [npxs+1]*/ - addbyte(0x5d); - addbyte((uint8_t)cpu_state_offset(npxs) + 1); - addbyte(0xdb); /*FCLEX*/ - addbyte(0xe2); - addbyte(0x80); /*AND BL, ~(C0|C2|C3)*/ - addbyte(0xe3); - addbyte((~(C0|C2|C3)) >> 8); - addbyte(0xd8); /*FCOMP [ESP]*/ - addbyte(0x04 | 0x18); - addbyte(0x24); - addbyte(0xdf); /*FSTSW AX*/ - addbyte(0xe0); - addbyte(0x80); /*AND AH, (C0|C2|C3)*/ - addbyte(0xe4); - addbyte((C0|C2|C3) >> 8); - addbyte(0x08); /*OR BL, AH*/ - addbyte(0xe3); - addbyte(0x88); /*MOV [npxs+1], BL*/ - addbyte(0x5d); - addbyte((uint8_t)cpu_state_offset(npxs) + 1); - } + if (codeblock[block_current].flags & CODEBLOCK_STATIC_TOP) { + addbyte(0x89); /*MOV [ESP], EAX*/ + addbyte(0x04); + addbyte(0x24); + addbyte(0xdd); /*FLD ST[0][EBP]*/ + addbyte(0x45); + addbyte((uint8_t) cpu_state_offset(ST[cpu_state.TOP])); + addbyte(0x8a); /*MOV BL, [npxs+1]*/ + addbyte(0x5d); + addbyte((uint8_t) cpu_state_offset(npxs) + 1); + addbyte(0xdb); /*FCLEX*/ + addbyte(0xe2); + addbyte(0x80); /*AND BL, ~(C0|C2|C3)*/ + addbyte(0xe3); + addbyte((~(C0 | C2 | C3)) >> 8); + addbyte(0xd8); /*FCOMP [ESP]*/ + addbyte(0x04 | 0x18); + addbyte(0x24); + addbyte(0xdf); /*FSTSW AX*/ + addbyte(0xe0); + addbyte(0x80); /*AND AH, (C0|C2|C3)*/ + addbyte(0xe4); + addbyte((C0 | C2 | C3) >> 8); + addbyte(0x08); /*OR BL, AH*/ + addbyte(0xe3); + addbyte(0x88); /*MOV [npxs+1], BL*/ + addbyte(0x5d); + addbyte((uint8_t) cpu_state_offset(npxs) + 1); + } else { + addbyte(0x8b); /*MOV EBX, TOP*/ + addbyte(0x5d); + addbyte((uint8_t) cpu_state_offset(TOP)); + addbyte(0x89); /*MOV [ESP], EAX*/ + addbyte(0x04); + addbyte(0x24); + addbyte(0xdd); /*FLD ST[EBX*8]*/ + addbyte(0x44); + addbyte(0xdd); + addbyte((uint8_t) cpu_state_offset(ST)); + addbyte(0x8a); /*MOV BL, [npxs+1]*/ + addbyte(0x5d); + addbyte((uint8_t) cpu_state_offset(npxs) + 1); + addbyte(0xdb); /*FCLEX*/ + addbyte(0xe2); + addbyte(0x80); /*AND BL, ~(C0|C2|C3)*/ + addbyte(0xe3); + addbyte((~(C0 | C2 | C3)) >> 8); + addbyte(0xd8); /*FCOMP [ESP]*/ + addbyte(0x04 | 0x18); + addbyte(0x24); + addbyte(0xdf); /*FSTSW AX*/ + addbyte(0xe0); + addbyte(0x80); /*AND AH, (C0|C2|C3)*/ + addbyte(0xe4); + addbyte((C0 | C2 | C3) >> 8); + addbyte(0x08); /*OR BL, AH*/ + addbyte(0xe3); + addbyte(0x88); /*MOV [npxs+1], BL*/ + addbyte(0x5d); + addbyte((uint8_t) cpu_state_offset(npxs) + 1); + } } -static inline void FP_COMPARE_D() +static __inline void +FP_COMPARE_D(void) { - if (codeblock[block_current].flags & CODEBLOCK_STATIC_TOP) - { - addbyte(0x89); /*MOV [ESP], EAX*/ - addbyte(0x04); - addbyte(0x24); - addbyte(0x89); /*MOV [ESP+4], EDX*/ - addbyte(0x54); - addbyte(0x24); - addbyte(0x04); - addbyte(0xdd); /*FLD ST[0][EBP]*/ - addbyte(0x45); - addbyte((uint8_t)cpu_state_offset(ST[cpu_state.TOP])); - addbyte(0x8a); /*MOV BL, [npxs+1]*/ - addbyte(0x5d); - addbyte((uint8_t)cpu_state_offset(npxs) + 1); - addbyte(0xdb); /*FCLEX*/ - addbyte(0xe2); - addbyte(0x80); /*AND BL, ~(C0|C2|C3)*/ - addbyte(0xe3); - addbyte((~(C0|C2|C3)) >> 8); - addbyte(0xdc); /*FCOMP [ESP]*/ - addbyte(0x04 | 0x18); - addbyte(0x24); - addbyte(0xdf); /*FSTSW AX*/ - addbyte(0xe0); - addbyte(0x80); /*AND AH, (C0|C2|C3)*/ - addbyte(0xe4); - addbyte((C0|C2|C3) >> 8); - addbyte(0x08); /*OR BL, AH*/ - addbyte(0xe3); - addbyte(0x88); /*MOV [npxs+1], BL*/ - addbyte(0x5d); - addbyte((uint8_t)cpu_state_offset(npxs) + 1); - } - else - { - addbyte(0x8b); /*MOV EBX, TOP*/ - addbyte(0x5d); - addbyte((uint8_t)cpu_state_offset(TOP)); - addbyte(0x89); /*MOV [ESP], EAX*/ - addbyte(0x04); - addbyte(0x24); - addbyte(0x89); /*MOV [ESP+4], EDX*/ - addbyte(0x54); - addbyte(0x24); - addbyte(0x04); - addbyte(0xdd); /*FLD ST[EBX*8]*/ - addbyte(0x44); - addbyte(0xdd); - addbyte((uint8_t)cpu_state_offset(ST)); - addbyte(0x8a); /*MOV BL, [npxs+1]*/ - addbyte(0x5d); - addbyte((uint8_t)cpu_state_offset(npxs) + 1); - addbyte(0xdb); /*FCLEX*/ - addbyte(0xe2); - addbyte(0x80); /*AND BL, ~(C0|C2|C3)*/ - addbyte(0xe3); - addbyte((~(C0|C2|C3)) >> 8); - addbyte(0xdc); /*FCOMP [ESP]*/ - addbyte(0x04 | 0x18); - addbyte(0x24); - addbyte(0xdf); /*FSTSW AX*/ - addbyte(0xe0); - addbyte(0x80); /*AND AH, (C0|C2|C3)*/ - addbyte(0xe4); - addbyte((C0|C2|C3) >> 8); - addbyte(0x08); /*OR BL, AH*/ - addbyte(0xe3); - addbyte(0x88); /*MOV [npxs+1], BL*/ - addbyte(0x5d); - addbyte((uint8_t)cpu_state_offset(npxs) + 1); - } + if (codeblock[block_current].flags & CODEBLOCK_STATIC_TOP) { + addbyte(0x89); /*MOV [ESP], EAX*/ + addbyte(0x04); + addbyte(0x24); + addbyte(0x89); /*MOV [ESP+4], EDX*/ + addbyte(0x54); + addbyte(0x24); + addbyte(0x04); + addbyte(0xdd); /*FLD ST[0][EBP]*/ + addbyte(0x45); + addbyte((uint8_t) cpu_state_offset(ST[cpu_state.TOP])); + addbyte(0x8a); /*MOV BL, [npxs+1]*/ + addbyte(0x5d); + addbyte((uint8_t) cpu_state_offset(npxs) + 1); + addbyte(0xdb); /*FCLEX*/ + addbyte(0xe2); + addbyte(0x80); /*AND BL, ~(C0|C2|C3)*/ + addbyte(0xe3); + addbyte((~(C0 | C2 | C3)) >> 8); + addbyte(0xdc); /*FCOMP [ESP]*/ + addbyte(0x04 | 0x18); + addbyte(0x24); + addbyte(0xdf); /*FSTSW AX*/ + addbyte(0xe0); + addbyte(0x80); /*AND AH, (C0|C2|C3)*/ + addbyte(0xe4); + addbyte((C0 | C2 | C3) >> 8); + addbyte(0x08); /*OR BL, AH*/ + addbyte(0xe3); + addbyte(0x88); /*MOV [npxs+1], BL*/ + addbyte(0x5d); + addbyte((uint8_t) cpu_state_offset(npxs) + 1); + } else { + addbyte(0x8b); /*MOV EBX, TOP*/ + addbyte(0x5d); + addbyte((uint8_t) cpu_state_offset(TOP)); + addbyte(0x89); /*MOV [ESP], EAX*/ + addbyte(0x04); + addbyte(0x24); + addbyte(0x89); /*MOV [ESP+4], EDX*/ + addbyte(0x54); + addbyte(0x24); + addbyte(0x04); + addbyte(0xdd); /*FLD ST[EBX*8]*/ + addbyte(0x44); + addbyte(0xdd); + addbyte((uint8_t) cpu_state_offset(ST)); + addbyte(0x8a); /*MOV BL, [npxs+1]*/ + addbyte(0x5d); + addbyte((uint8_t) cpu_state_offset(npxs) + 1); + addbyte(0xdb); /*FCLEX*/ + addbyte(0xe2); + addbyte(0x80); /*AND BL, ~(C0|C2|C3)*/ + addbyte(0xe3); + addbyte((~(C0 | C2 | C3)) >> 8); + addbyte(0xdc); /*FCOMP [ESP]*/ + addbyte(0x04 | 0x18); + addbyte(0x24); + addbyte(0xdf); /*FSTSW AX*/ + addbyte(0xe0); + addbyte(0x80); /*AND AH, (C0|C2|C3)*/ + addbyte(0xe4); + addbyte((C0 | C2 | C3) >> 8); + addbyte(0x08); /*OR BL, AH*/ + addbyte(0xe3); + addbyte(0x88); /*MOV [npxs+1], BL*/ + addbyte(0x5d); + addbyte((uint8_t) cpu_state_offset(npxs) + 1); + } } -static inline void FP_COMPARE_IW() +static __inline void +FP_COMPARE_IW(void) { - if (codeblock[block_current].flags & CODEBLOCK_STATIC_TOP) - { - addbyte(0x66); /*MOV [ESP], AX*/ - addbyte(0x89); - addbyte(0x04); - addbyte(0x24); - addbyte(0xdd); /*FLD ST[0][EBP]*/ - addbyte(0x45); - addbyte((uint8_t)cpu_state_offset(ST[cpu_state.TOP])); - addbyte(0x8a); /*MOV BL, [npxs+1]*/ - addbyte(0x5d); - addbyte((uint8_t)cpu_state_offset(npxs) + 1); - addbyte(0xdb); /*FCLEX*/ - addbyte(0xe2); - addbyte(0x80); /*AND BL, ~(C0|C2|C3)*/ - addbyte(0xe3); - addbyte((~(C0|C2|C3)) >> 8); - addbyte(0xde); /*FCOMP [ESP]*/ - addbyte(0x04 | 0x18); - addbyte(0x24); - addbyte(0xdf); /*FSTSW AX*/ - addbyte(0xe0); - addbyte(0x80); /*AND AH, (C0|C2|C3)*/ - addbyte(0xe4); - addbyte((C0|C2|C3) >> 8); - addbyte(0x08); /*OR BL, AH*/ - addbyte(0xe3); - addbyte(0x88); /*MOV [npxs+1], BL*/ - addbyte(0x5d); - addbyte((uint8_t)cpu_state_offset(npxs) + 1); - } - else - { - addbyte(0x8b); /*MOV EBX, TOP*/ - addbyte(0x5d); - addbyte((uint8_t)cpu_state_offset(TOP)); - addbyte(0x89); /*MOV [ESP], EAX*/ - addbyte(0x04); - addbyte(0x24); - addbyte(0xdd); /*FLD ST[EBX*8]*/ - addbyte(0x44); - addbyte(0xdd); - addbyte((uint8_t)cpu_state_offset(ST)); - addbyte(0x8a); /*MOV BL, [npxs+1]*/ - addbyte(0x5d); - addbyte((uint8_t)cpu_state_offset(npxs) + 1); - addbyte(0xdb); /*FCLEX*/ - addbyte(0xe2); - addbyte(0x80); /*AND BL, ~(C0|C2|C3)*/ - addbyte(0xe3); - addbyte((~(C0|C2|C3)) >> 8); - addbyte(0xde); /*FCOMP [ESP]*/ - addbyte(0x04 | 0x18); - addbyte(0x24); - addbyte(0xdf); /*FSTSW AX*/ - addbyte(0xe0); - addbyte(0x80); /*AND AH, (C0|C2|C3)*/ - addbyte(0xe4); - addbyte((C0|C2|C3) >> 8); - addbyte(0x08); /*OR BL, AH*/ - addbyte(0xe3); - addbyte(0x88); /*MOV [npxs+1], BL*/ - addbyte(0x5d); - addbyte((uint8_t)cpu_state_offset(npxs) + 1); - } + if (codeblock[block_current].flags & CODEBLOCK_STATIC_TOP) { + addbyte(0x66); /*MOV [ESP], AX*/ + addbyte(0x89); + addbyte(0x04); + addbyte(0x24); + addbyte(0xdd); /*FLD ST[0][EBP]*/ + addbyte(0x45); + addbyte((uint8_t) cpu_state_offset(ST[cpu_state.TOP])); + addbyte(0x8a); /*MOV BL, [npxs+1]*/ + addbyte(0x5d); + addbyte((uint8_t) cpu_state_offset(npxs) + 1); + addbyte(0xdb); /*FCLEX*/ + addbyte(0xe2); + addbyte(0x80); /*AND BL, ~(C0|C2|C3)*/ + addbyte(0xe3); + addbyte((~(C0 | C2 | C3)) >> 8); + addbyte(0xde); /*FCOMP [ESP]*/ + addbyte(0x04 | 0x18); + addbyte(0x24); + addbyte(0xdf); /*FSTSW AX*/ + addbyte(0xe0); + addbyte(0x80); /*AND AH, (C0|C2|C3)*/ + addbyte(0xe4); + addbyte((C0 | C2 | C3) >> 8); + addbyte(0x08); /*OR BL, AH*/ + addbyte(0xe3); + addbyte(0x88); /*MOV [npxs+1], BL*/ + addbyte(0x5d); + addbyte((uint8_t) cpu_state_offset(npxs) + 1); + } else { + addbyte(0x8b); /*MOV EBX, TOP*/ + addbyte(0x5d); + addbyte((uint8_t) cpu_state_offset(TOP)); + addbyte(0x89); /*MOV [ESP], EAX*/ + addbyte(0x04); + addbyte(0x24); + addbyte(0xdd); /*FLD ST[EBX*8]*/ + addbyte(0x44); + addbyte(0xdd); + addbyte((uint8_t) cpu_state_offset(ST)); + addbyte(0x8a); /*MOV BL, [npxs+1]*/ + addbyte(0x5d); + addbyte((uint8_t) cpu_state_offset(npxs) + 1); + addbyte(0xdb); /*FCLEX*/ + addbyte(0xe2); + addbyte(0x80); /*AND BL, ~(C0|C2|C3)*/ + addbyte(0xe3); + addbyte((~(C0 | C2 | C3)) >> 8); + addbyte(0xde); /*FCOMP [ESP]*/ + addbyte(0x04 | 0x18); + addbyte(0x24); + addbyte(0xdf); /*FSTSW AX*/ + addbyte(0xe0); + addbyte(0x80); /*AND AH, (C0|C2|C3)*/ + addbyte(0xe4); + addbyte((C0 | C2 | C3) >> 8); + addbyte(0x08); /*OR BL, AH*/ + addbyte(0xe3); + addbyte(0x88); /*MOV [npxs+1], BL*/ + addbyte(0x5d); + addbyte((uint8_t) cpu_state_offset(npxs) + 1); + } } -static inline void FP_COMPARE_IL() +static __inline void +FP_COMPARE_IL(void) { - if (codeblock[block_current].flags & CODEBLOCK_STATIC_TOP) - { - addbyte(0x89); /*MOV [ESP], EAX*/ - addbyte(0x04); - addbyte(0x24); - addbyte(0xdd); /*FLD ST[0][EBP]*/ - addbyte(0x45); - addbyte((uint8_t)cpu_state_offset(ST[cpu_state.TOP])); - addbyte(0x8a); /*MOV BL, [npxs+1]*/ - addbyte(0x5d); - addbyte((uint8_t)cpu_state_offset(npxs) + 1); - addbyte(0xdb); /*FCLEX*/ - addbyte(0xe2); - addbyte(0x80); /*AND BL, ~(C0|C2|C3)*/ - addbyte(0xe3); - addbyte((~(C0|C2|C3)) >> 8); - addbyte(0xda); /*FCOMP [ESP]*/ - addbyte(0x04 | 0x18); - addbyte(0x24); - addbyte(0xdf); /*FSTSW AX*/ - addbyte(0xe0); - addbyte(0x80); /*AND AH, (C0|C2|C3)*/ - addbyte(0xe4); - addbyte((C0|C2|C3) >> 8); - addbyte(0x08); /*OR BL, AH*/ - addbyte(0xe3); - addbyte(0x88); /*MOV [npxs+1], BL*/ - addbyte(0x5d); - addbyte((uint8_t)cpu_state_offset(npxs) + 1); - } - else - { - addbyte(0x8b); /*MOV EBX, TOP*/ - addbyte(0x5d); - addbyte((uint8_t)cpu_state_offset(TOP)); - addbyte(0x89); /*MOV [ESP], EAX*/ - addbyte(0x04); - addbyte(0x24); - addbyte(0xdd); /*FLD ST[EBX*8]*/ - addbyte(0x44); - addbyte(0xdd); - addbyte((uint8_t)cpu_state_offset(ST)); - addbyte(0x8a); /*MOV BL, [npxs+1]*/ - addbyte(0x5d); - addbyte((uint8_t)cpu_state_offset(npxs) + 1); - addbyte(0xdb); /*FCLEX*/ - addbyte(0xe2); - addbyte(0x80); /*AND BL, ~(C0|C2|C3)*/ - addbyte(0xe3); - addbyte((~(C0|C2|C3)) >> 8); - addbyte(0xda); /*FCOMP [ESP]*/ - addbyte(0x04 | 0x18); - addbyte(0x24); - addbyte(0xdf); /*FSTSW AX*/ - addbyte(0xe0); - addbyte(0x80); /*AND AH, (C0|C2|C3)*/ - addbyte(0xe4); - addbyte((C0|C2|C3) >> 8); - addbyte(0x08); /*OR BL, AH*/ - addbyte(0xe3); - addbyte(0x88); /*MOV [npxs+1], BL*/ - addbyte(0x5d); - addbyte((uint8_t)cpu_state_offset(npxs) + 1); - } + if (codeblock[block_current].flags & CODEBLOCK_STATIC_TOP) { + addbyte(0x89); /*MOV [ESP], EAX*/ + addbyte(0x04); + addbyte(0x24); + addbyte(0xdd); /*FLD ST[0][EBP]*/ + addbyte(0x45); + addbyte((uint8_t) cpu_state_offset(ST[cpu_state.TOP])); + addbyte(0x8a); /*MOV BL, [npxs+1]*/ + addbyte(0x5d); + addbyte((uint8_t) cpu_state_offset(npxs) + 1); + addbyte(0xdb); /*FCLEX*/ + addbyte(0xe2); + addbyte(0x80); /*AND BL, ~(C0|C2|C3)*/ + addbyte(0xe3); + addbyte((~(C0 | C2 | C3)) >> 8); + addbyte(0xda); /*FCOMP [ESP]*/ + addbyte(0x04 | 0x18); + addbyte(0x24); + addbyte(0xdf); /*FSTSW AX*/ + addbyte(0xe0); + addbyte(0x80); /*AND AH, (C0|C2|C3)*/ + addbyte(0xe4); + addbyte((C0 | C2 | C3) >> 8); + addbyte(0x08); /*OR BL, AH*/ + addbyte(0xe3); + addbyte(0x88); /*MOV [npxs+1], BL*/ + addbyte(0x5d); + addbyte((uint8_t) cpu_state_offset(npxs) + 1); + } else { + addbyte(0x8b); /*MOV EBX, TOP*/ + addbyte(0x5d); + addbyte((uint8_t) cpu_state_offset(TOP)); + addbyte(0x89); /*MOV [ESP], EAX*/ + addbyte(0x04); + addbyte(0x24); + addbyte(0xdd); /*FLD ST[EBX*8]*/ + addbyte(0x44); + addbyte(0xdd); + addbyte((uint8_t) cpu_state_offset(ST)); + addbyte(0x8a); /*MOV BL, [npxs+1]*/ + addbyte(0x5d); + addbyte((uint8_t) cpu_state_offset(npxs) + 1); + addbyte(0xdb); /*FCLEX*/ + addbyte(0xe2); + addbyte(0x80); /*AND BL, ~(C0|C2|C3)*/ + addbyte(0xe3); + addbyte((~(C0 | C2 | C3)) >> 8); + addbyte(0xda); /*FCOMP [ESP]*/ + addbyte(0x04 | 0x18); + addbyte(0x24); + addbyte(0xdf); /*FSTSW AX*/ + addbyte(0xe0); + addbyte(0x80); /*AND AH, (C0|C2|C3)*/ + addbyte(0xe4); + addbyte((C0 | C2 | C3) >> 8); + addbyte(0x08); /*OR BL, AH*/ + addbyte(0xe3); + addbyte(0x88); /*MOV [npxs+1], BL*/ + addbyte(0x5d); + addbyte((uint8_t) cpu_state_offset(npxs) + 1); + } } -static inline void FP_OP_REG(int op, int dst, int src) +static __inline void +FP_OP_REG(int op, int dst, int src) { - if (codeblock[block_current].flags & CODEBLOCK_STATIC_TOP) - { - addbyte(0xdd); /*FLD ST[dst][EBP]*/ - addbyte(0x45); - addbyte((uint8_t)cpu_state_offset(ST[(cpu_state.TOP + dst) & 7])); - addbyte(0xdc); /*FADD ST[src][EBP]*/ - addbyte(0x45 | op); - addbyte((uint8_t)cpu_state_offset(ST[(cpu_state.TOP + src) & 7])); - addbyte(0x80); /*AND tag[dst][EBP], ~TAG_UINT64*/ - addbyte(0x65); - addbyte((uint8_t)cpu_state_offset(tag[(cpu_state.TOP + dst) & 7])); - addbyte(TAG_NOT_UINT64); - addbyte(0xdd); /*FSTP ST[dst][EBP]*/ - addbyte(0x5d); - addbyte((uint8_t)cpu_state_offset(ST[(cpu_state.TOP + dst) & 7])); - } - else - { - addbyte(0x8b); /*MOV EAX, TOP*/ - addbyte(0x45); - addbyte((uint8_t)cpu_state_offset(TOP)); - addbyte(0x89); /*MOV EBX, EAX*/ - addbyte(0xc3); - if (src || dst) - { - addbyte(0x83); /*ADD EAX, 1*/ - addbyte(0xc0); - addbyte(src ? src : dst); - addbyte(0x83); /*AND EAX, 7*/ - addbyte(0xe0); - addbyte(7); - } - - if (src) - { - addbyte(0xdd); /*FLD ST[EBX*8]*/ - addbyte(0x44); - addbyte(0xdd); - addbyte((uint8_t)cpu_state_offset(ST)); - addbyte(0x80); /*AND tag[EBX], ~TAG_UINT64*/ - addbyte(0x64); - addbyte(0x1d); - addbyte((uint8_t)cpu_state_offset(tag[0])); - addbyte(TAG_NOT_UINT64); - addbyte(0xdc); /*FADD ST[EAX*8]*/ - addbyte(0x44 | op); - addbyte(0xc5); - addbyte((uint8_t)cpu_state_offset(ST)); - addbyte(0xdd); /*FSTP ST[EBX*8]*/ - addbyte(0x5c); - addbyte(0xdd); - addbyte((uint8_t)cpu_state_offset(ST)); - } - else - { - addbyte(0xdd); /*FLD [ESI+EAX*8]*/ - addbyte(0x44); - addbyte(0xc5); - addbyte((uint8_t)cpu_state_offset(ST)); - addbyte(0x80); /*AND tag[EAX], ~TAG_UINT64*/ - addbyte(0x64); - addbyte(0x05); - addbyte((uint8_t)cpu_state_offset(tag[0])); - addbyte(TAG_NOT_UINT64); - addbyte(0xdc); /*FADD ST[EBX*8]*/ - addbyte(0x44 | op); - addbyte(0xdd); - addbyte((uint8_t)cpu_state_offset(ST)); - addbyte(0xdd); /*FSTP ST[EAX*8]*/ - addbyte(0x5c); - addbyte(0xc5); - addbyte((uint8_t)cpu_state_offset(ST)); - } - } -} - -static inline void FP_COMPARE_REG(int dst, int src) -{ - if (codeblock[block_current].flags & CODEBLOCK_STATIC_TOP) - { - addbyte(0x8a); /*MOV CL, [npxs+1]*/ - addbyte(0x4d); - addbyte((uint8_t)cpu_state_offset(npxs) + 1); - addbyte(0xdb); /*FCLEX*/ - addbyte(0xe2); - addbyte(0xdd); /*FLD ST[dst][EBP]*/ - addbyte(0x45); - addbyte((uint8_t)cpu_state_offset(ST[(cpu_state.TOP + dst) & 7])); - addbyte(0x80); /*AND CL, ~(C0|C2|C3)*/ - addbyte(0xe1); - addbyte((~(C0|C2|C3)) >> 8); - addbyte(0xdc); /*FCOMP ST[src][EBP]*/ - addbyte(0x5d); - addbyte((uint8_t)cpu_state_offset(ST[(cpu_state.TOP + src) & 7])); - addbyte(0xdf); /*FSTSW AX*/ - addbyte(0xe0); - addbyte(0x80); /*AND AH, (C0|C2|C3)*/ - addbyte(0xe4); - addbyte((C0|C2|C3) >> 8); - addbyte(0x08); /*OR CL, AH*/ - addbyte(0xe1); - addbyte(0x88); /*MOV [npxs+1], CL*/ - addbyte(0x4d); - addbyte((uint8_t)cpu_state_offset(npxs) + 1); - } - else - { - addbyte(0x8b); /*MOV EAX, TOP*/ - addbyte(0x45); - addbyte((uint8_t)cpu_state_offset(TOP)); - addbyte(0x89); /*MOV EBX, EAX*/ - addbyte(0xc3); - if (src || dst) - { - addbyte(0x83); /*ADD EAX, 1*/ - addbyte(0xc0); - addbyte(src ? src : dst); - addbyte(0x83); /*AND EAX, 7*/ - addbyte(0xe0); - addbyte(7); - } - - addbyte(0x8a); /*MOV CL, [npxs+1]*/ - addbyte(0x4d); - addbyte((uint8_t)cpu_state_offset(npxs) + 1); - addbyte(0xdb); /*FCLEX*/ - addbyte(0xe2); - addbyte(0x80); /*AND CL, ~(C0|C2|C3)*/ - addbyte(0xe1); - addbyte((~(C0|C2|C3)) >> 8); - - if (src) - { - addbyte(0xdd); /*FLD ST[EBX*8]*/ - addbyte(0x44); - addbyte(0xdd); - addbyte((uint8_t)cpu_state_offset(ST)); - addbyte(0xdc); /*FCOMP ST[EAX*8]*/ - addbyte(0x44 | 0x18); - addbyte(0xc5); - addbyte((uint8_t)cpu_state_offset(ST)); - } - else - { - addbyte(0xdd); /*FLD [ESI+EAX*8]*/ - addbyte(0x44); - addbyte(0xc5); - addbyte((uint8_t)cpu_state_offset(ST)); - addbyte(0xdc); /*FCOMP ST[EBX*8]*/ - addbyte(0x44 | 0x18); - addbyte(0xdd); - addbyte((uint8_t)cpu_state_offset(ST)); - } - - addbyte(0xdf); /*FSTSW AX*/ - addbyte(0xe0); - addbyte(0x80); /*AND AH, (C0|C2|C3)*/ - addbyte(0xe4); - addbyte((C0|C2|C3) >> 8); - addbyte(0x08); /*OR CL, AH*/ - addbyte(0xe1); - addbyte(0x88); /*MOV [npxs+1], CL*/ - addbyte(0x4d); - addbyte((uint8_t)cpu_state_offset(npxs) + 1); - } -} - -static inline void FP_FCHS() -{ - if (codeblock[block_current].flags & CODEBLOCK_STATIC_TOP) - { - addbyte(0xdd); /*FLD ST[0][EBP]*/ - addbyte(0x45); - addbyte((uint8_t)cpu_state_offset(ST[cpu_state.TOP])); - addbyte(0xd9); /*FCHS*/ - addbyte(0xe0); - addbyte(0x80); /*AND tag[dst][EBP], ~TAG_UINT64*/ - addbyte(0x65); - addbyte((uint8_t)cpu_state_offset(tag[cpu_state.TOP])); - addbyte(TAG_NOT_UINT64); - addbyte(0xdd); /*FSTP ST[dst][EBP]*/ - addbyte(0x5d); - addbyte((uint8_t)cpu_state_offset(ST[cpu_state.TOP])); - } - else - { - addbyte(0x8b); /*MOV EAX, TOP*/ - addbyte(0x45); - addbyte((uint8_t)cpu_state_offset(TOP)); - - addbyte(0xdd); /*FLD [ESI+EAX*8]*/ - addbyte(0x44); - addbyte(0xc5); - addbyte((uint8_t)cpu_state_offset(ST)); - addbyte(0x80); /*AND tag[EAX], ~TAG_UINT64*/ - addbyte(0x64); - addbyte(0x05); - addbyte((uint8_t)cpu_state_offset(tag[0])); - addbyte(TAG_NOT_UINT64); - addbyte(0xd9); /*FCHS*/ - addbyte(0xe0); - addbyte(0xdd); /*FSTP ST[EAX*8]*/ - addbyte(0x5c); - addbyte(0xc5); - addbyte((uint8_t)cpu_state_offset(ST)); - } -} - -static inline void UPDATE_NPXC(int reg) -{ - addbyte(0x66); /*AND cpu_state.new_npxc, ~0xc00*/ - addbyte(0x81); + if (codeblock[block_current].flags & CODEBLOCK_STATIC_TOP) { + addbyte(0xdd); /*FLD ST[dst][EBP]*/ + addbyte(0x45); + addbyte((uint8_t) cpu_state_offset(ST[(cpu_state.TOP + dst) & 7])); + addbyte(0xdc); /*FADD ST[src][EBP]*/ + addbyte(0x45 | op); + addbyte((uint8_t) cpu_state_offset(ST[(cpu_state.TOP + src) & 7])); + addbyte(0x80); /*AND tag[dst][EBP], ~TAG_UINT64*/ addbyte(0x65); - addbyte((uint8_t)cpu_state_offset(new_npxc)); - addword(~0xc00); - if (reg) - { - addbyte(0x66); /*AND reg, 0xc00*/ - addbyte(0x81); - addbyte(0xe0 | reg); - addword(0xc00); + addbyte((uint8_t) cpu_state_offset(tag[(cpu_state.TOP + dst) & 7])); + addbyte(TAG_NOT_UINT64); + addbyte(0xdd); /*FSTP ST[dst][EBP]*/ + addbyte(0x5d); + addbyte((uint8_t) cpu_state_offset(ST[(cpu_state.TOP + dst) & 7])); + } else { + addbyte(0x8b); /*MOV EAX, TOP*/ + addbyte(0x45); + addbyte((uint8_t) cpu_state_offset(TOP)); + addbyte(0x89); /*MOV EBX, EAX*/ + addbyte(0xc3); + if (src || dst) { + addbyte(0x83); /*ADD EAX, 1*/ + addbyte(0xc0); + addbyte(src ? src : dst); + addbyte(0x83); /*AND EAX, 7*/ + addbyte(0xe0); + addbyte(7); } - else - { - addbyte(0x66); /*AND AX, 0xc00*/ - addbyte(0x25); - addword(0xc00); + + if (src) { + addbyte(0xdd); /*FLD ST[EBX*8]*/ + addbyte(0x44); + addbyte(0xdd); + addbyte((uint8_t) cpu_state_offset(ST)); + addbyte(0x80); /*AND tag[EBX], ~TAG_UINT64*/ + addbyte(0x64); + addbyte(0x1d); + addbyte((uint8_t) cpu_state_offset(tag[0])); + addbyte(TAG_NOT_UINT64); + addbyte(0xdc); /*FADD ST[EAX*8]*/ + addbyte(0x44 | op); + addbyte(0xc5); + addbyte((uint8_t) cpu_state_offset(ST)); + addbyte(0xdd); /*FSTP ST[EBX*8]*/ + addbyte(0x5c); + addbyte(0xdd); + addbyte((uint8_t) cpu_state_offset(ST)); + } else { + addbyte(0xdd); /*FLD [ESI+EAX*8]*/ + addbyte(0x44); + addbyte(0xc5); + addbyte((uint8_t) cpu_state_offset(ST)); + addbyte(0x80); /*AND tag[EAX], ~TAG_UINT64*/ + addbyte(0x64); + addbyte(0x05); + addbyte((uint8_t) cpu_state_offset(tag[0])); + addbyte(TAG_NOT_UINT64); + addbyte(0xdc); /*FADD ST[EBX*8]*/ + addbyte(0x44 | op); + addbyte(0xdd); + addbyte((uint8_t) cpu_state_offset(ST)); + addbyte(0xdd); /*FSTP ST[EAX*8]*/ + addbyte(0x5c); + addbyte(0xc5); + addbyte((uint8_t) cpu_state_offset(ST)); } - addbyte(0x66); /*OR cpu_state.new_npxc, reg*/ - addbyte(0x09); - addbyte(0x45 | (reg << 3)); - addbyte((uint8_t)cpu_state_offset(new_npxc)); + } } -static inline int ZERO_EXTEND_W_B(int reg) +static __inline void +FP_COMPARE_REG(int dst, int src) { - addbyte(0x0f); /*MOVZX regl, regb*/ - addbyte(0xb6); - addbyte(0xc0 | reg | (reg << 3)); - return reg; -} -static inline int ZERO_EXTEND_L_B(int reg) -{ - addbyte(0x0f); /*MOVZX regl, regb*/ - addbyte(0xb6); - addbyte(0xc0 | reg | (reg << 3)); - return reg; -} -static inline int ZERO_EXTEND_L_W(int reg) -{ - addbyte(0x0f); /*MOVZX regl, regw*/ - addbyte(0xb7); - addbyte(0xc0 | reg | (reg << 3)); - return reg; + if (codeblock[block_current].flags & CODEBLOCK_STATIC_TOP) { + addbyte(0x8a); /*MOV CL, [npxs+1]*/ + addbyte(0x4d); + addbyte((uint8_t) cpu_state_offset(npxs) + 1); + addbyte(0xdb); /*FCLEX*/ + addbyte(0xe2); + addbyte(0xdd); /*FLD ST[dst][EBP]*/ + addbyte(0x45); + addbyte((uint8_t) cpu_state_offset(ST[(cpu_state.TOP + dst) & 7])); + addbyte(0x80); /*AND CL, ~(C0|C2|C3)*/ + addbyte(0xe1); + addbyte((~(C0 | C2 | C3)) >> 8); + addbyte(0xdc); /*FCOMP ST[src][EBP]*/ + addbyte(0x5d); + addbyte((uint8_t) cpu_state_offset(ST[(cpu_state.TOP + src) & 7])); + addbyte(0xdf); /*FSTSW AX*/ + addbyte(0xe0); + addbyte(0x80); /*AND AH, (C0|C2|C3)*/ + addbyte(0xe4); + addbyte((C0 | C2 | C3) >> 8); + addbyte(0x08); /*OR CL, AH*/ + addbyte(0xe1); + addbyte(0x88); /*MOV [npxs+1], CL*/ + addbyte(0x4d); + addbyte((uint8_t) cpu_state_offset(npxs) + 1); + } else { + addbyte(0x8b); /*MOV EAX, TOP*/ + addbyte(0x45); + addbyte((uint8_t) cpu_state_offset(TOP)); + addbyte(0x89); /*MOV EBX, EAX*/ + addbyte(0xc3); + if (src || dst) { + addbyte(0x83); /*ADD EAX, 1*/ + addbyte(0xc0); + addbyte(src ? src : dst); + addbyte(0x83); /*AND EAX, 7*/ + addbyte(0xe0); + addbyte(7); + } + + addbyte(0x8a); /*MOV CL, [npxs+1]*/ + addbyte(0x4d); + addbyte((uint8_t) cpu_state_offset(npxs) + 1); + addbyte(0xdb); /*FCLEX*/ + addbyte(0xe2); + addbyte(0x80); /*AND CL, ~(C0|C2|C3)*/ + addbyte(0xe1); + addbyte((~(C0 | C2 | C3)) >> 8); + + if (src) { + addbyte(0xdd); /*FLD ST[EBX*8]*/ + addbyte(0x44); + addbyte(0xdd); + addbyte((uint8_t) cpu_state_offset(ST)); + addbyte(0xdc); /*FCOMP ST[EAX*8]*/ + addbyte(0x44 | 0x18); + addbyte(0xc5); + addbyte((uint8_t) cpu_state_offset(ST)); + } else { + addbyte(0xdd); /*FLD [ESI+EAX*8]*/ + addbyte(0x44); + addbyte(0xc5); + addbyte((uint8_t) cpu_state_offset(ST)); + addbyte(0xdc); /*FCOMP ST[EBX*8]*/ + addbyte(0x44 | 0x18); + addbyte(0xdd); + addbyte((uint8_t) cpu_state_offset(ST)); + } + + addbyte(0xdf); /*FSTSW AX*/ + addbyte(0xe0); + addbyte(0x80); /*AND AH, (C0|C2|C3)*/ + addbyte(0xe4); + addbyte((C0 | C2 | C3) >> 8); + addbyte(0x08); /*OR CL, AH*/ + addbyte(0xe1); + addbyte(0x88); /*MOV [npxs+1], CL*/ + addbyte(0x4d); + addbyte((uint8_t) cpu_state_offset(npxs) + 1); + } } -static inline int SIGN_EXTEND_W_B(int reg) +static __inline void +FP_FCHS(void) { - addbyte(0x0f); /*MOVSX regl, regb*/ - addbyte(0xbe); - addbyte(0xc0 | reg | (reg << 3)); - return reg; -} -static inline int SIGN_EXTEND_L_B(int reg) -{ - addbyte(0x0f); /*MOVSX regl, regb*/ - addbyte(0xbe); - addbyte(0xc0 | reg | (reg << 3)); - return reg; -} -static inline int SIGN_EXTEND_L_W(int reg) -{ - addbyte(0x0f); /*MOVSX regl, regw*/ - addbyte(0xbf); - addbyte(0xc0 | reg | (reg << 3)); - return reg; + if (codeblock[block_current].flags & CODEBLOCK_STATIC_TOP) { + addbyte(0xdd); /*FLD ST[0][EBP]*/ + addbyte(0x45); + addbyte((uint8_t) cpu_state_offset(ST[cpu_state.TOP])); + addbyte(0xd9); /*FCHS*/ + addbyte(0xe0); + addbyte(0x80); /*AND tag[dst][EBP], ~TAG_UINT64*/ + addbyte(0x65); + addbyte((uint8_t) cpu_state_offset(tag[cpu_state.TOP])); + addbyte(TAG_NOT_UINT64); + addbyte(0xdd); /*FSTP ST[dst][EBP]*/ + addbyte(0x5d); + addbyte((uint8_t) cpu_state_offset(ST[cpu_state.TOP])); + } else { + addbyte(0x8b); /*MOV EAX, TOP*/ + addbyte(0x45); + addbyte((uint8_t) cpu_state_offset(TOP)); + + addbyte(0xdd); /*FLD [ESI+EAX*8]*/ + addbyte(0x44); + addbyte(0xc5); + addbyte((uint8_t) cpu_state_offset(ST)); + addbyte(0x80); /*AND tag[EAX], ~TAG_UINT64*/ + addbyte(0x64); + addbyte(0x05); + addbyte((uint8_t) cpu_state_offset(tag[0])); + addbyte(TAG_NOT_UINT64); + addbyte(0xd9); /*FCHS*/ + addbyte(0xe0); + addbyte(0xdd); /*FSTP ST[EAX*8]*/ + addbyte(0x5c); + addbyte(0xc5); + addbyte((uint8_t) cpu_state_offset(ST)); + } } -static inline int COPY_REG(int src_reg) +static __inline void +UPDATE_NPXC(int reg) { - return src_reg; + addbyte(0x66); /*AND cpu_state.new_npxc, ~0xc00*/ + addbyte(0x81); + addbyte(0x65); + addbyte((uint8_t) cpu_state_offset(new_npxc)); + addword(~0xc00); + if (reg) { + addbyte(0x66); /*AND reg, 0xc00*/ + addbyte(0x81); + addbyte(0xe0 | reg); + addword(0xc00); + } else { + addbyte(0x66); /*AND AX, 0xc00*/ + addbyte(0x25); + addword(0xc00); + } + addbyte(0x66); /*OR cpu_state.new_npxc, reg*/ + addbyte(0x09); + addbyte(0x45 | (reg << 3)); + addbyte((uint8_t) cpu_state_offset(new_npxc)); } -static inline void SET_BITS(uintptr_t addr, uint32_t val) +static __inline int +ZERO_EXTEND_W_B(int reg) { - if (val & ~0xff) - { - addbyte(0x81); - addbyte(0x0d); - addlong(addr); - addlong(val); - } - else - { - addbyte(0x80); - addbyte(0x0d); - addlong(addr); - addbyte(val); - } + addbyte(0x0f); /*MOVZX regl, regb*/ + addbyte(0xb6); + addbyte(0xc0 | reg | (reg << 3)); + return reg; } -static inline void CLEAR_BITS(uintptr_t addr, uint32_t val) +static __inline int +ZERO_EXTEND_L_B(int reg) { - if (val & ~0xff) - { - addbyte(0x81); - addbyte(0x25); - addlong(addr); - addlong(~val); - } - else - { - addbyte(0x80); - addbyte(0x25); - addlong(addr); - addbyte(~val); - } + addbyte(0x0f); /*MOVZX regl, regb*/ + addbyte(0xb6); + addbyte(0xc0 | reg | (reg << 3)); + return reg; +} +static __inline int +ZERO_EXTEND_L_W(int reg) +{ + addbyte(0x0f); /*MOVZX regl, regw*/ + addbyte(0xb7); + addbyte(0xc0 | reg | (reg << 3)); + return reg; +} + +static __inline int +SIGN_EXTEND_W_B(int reg) +{ + addbyte(0x0f); /*MOVSX regl, regb*/ + addbyte(0xbe); + addbyte(0xc0 | reg | (reg << 3)); + return reg; +} +static __inline int +SIGN_EXTEND_L_B(int reg) +{ + addbyte(0x0f); /*MOVSX regl, regb*/ + addbyte(0xbe); + addbyte(0xc0 | reg | (reg << 3)); + return reg; +} +static __inline int +SIGN_EXTEND_L_W(int reg) +{ + addbyte(0x0f); /*MOVSX regl, regw*/ + addbyte(0xbf); + addbyte(0xc0 | reg | (reg << 3)); + return reg; +} + +static __inline int +COPY_REG(int src_reg) +{ + return src_reg; +} + +static __inline void +SET_BITS(uintptr_t addr, uint32_t val) +{ + if (val & ~0xff) { + addbyte(0x81); + addbyte(0x0d); + addlong(addr); + addlong(val); + } else { + addbyte(0x80); + addbyte(0x0d); + addlong(addr); + addbyte(val); + } +} +static __inline void +CLEAR_BITS(uintptr_t addr, uint32_t val) +{ + if (val & ~0xff) { + addbyte(0x81); + addbyte(0x25); + addlong(addr); + addlong(~val); + } else { + addbyte(0x80); + addbyte(0x25); + addlong(addr); + addbyte(~val); + } } #define LOAD_Q_REG_1 REG_EAX #define LOAD_Q_REG_2 REG_EDX -static inline void MMX_ENTER() +static __inline void +MMX_ENTER(void) { - if (codegen_mmx_entered) - return; - - addbyte(0xf6); /*TEST cr0, 0xc*/ - addbyte(0x05); - addlong((uintptr_t)&cr0); - addbyte(0xc); - addbyte(0x74); /*JZ +*/ - addbyte(7+7+5+5); - addbyte(0xC7); /*MOVL [oldpc],op_old_pc*/ - addbyte(0x45); - addbyte((uint8_t)cpu_state_offset(oldpc)); - addlong(op_old_pc); - addbyte(0xc7); /*MOV [ESP], 7*/ - addbyte(0x04); - addbyte(0x24); - addlong(7); - addbyte(0xe8); /*CALL x86_int*/ - addlong((uint32_t)x86_int - (uint32_t)(&codeblock[block_current].data[block_pos + 4])); - addbyte(0xe9); /*JMP end*/ - addlong(BLOCK_EXIT_OFFSET - (block_pos + 4)); - - addbyte(0x31); /*XOR EAX, EAX*/ - addbyte(0xc0); - addbyte(0xc6); /*MOV ISMMX, 1*/ - addbyte(0x45); - addbyte((uint8_t)cpu_state_offset(ismmx)); - addbyte(1); - addbyte(0x89); /*MOV TOP, EAX*/ - addbyte(0x45); - addbyte((uint8_t)cpu_state_offset(TOP)); - addbyte(0x89); /*MOV tag, EAX*/ - addbyte(0x45); - addbyte((uint8_t)cpu_state_offset(tag[0])); - addbyte(0x89); /*MOV tag+4, EAX*/ - addbyte(0x45); - addbyte((uint8_t)cpu_state_offset(tag[4])); + if (codegen_mmx_entered) + return; - codegen_mmx_entered = 1; + addbyte(0xf6); /*TEST cr0, 0xc*/ + addbyte(0x05); + addlong((uintptr_t) &cr0); + addbyte(0xc); + addbyte(0x74); /*JZ +*/ + addbyte(7 + 7 + 5 + 5); + addbyte(0xC7); /*MOVL [oldpc],op_old_pc*/ + addbyte(0x45); + addbyte((uint8_t) cpu_state_offset(oldpc)); + addlong(op_old_pc); + addbyte(0xc7); /*MOV [ESP], 7*/ + addbyte(0x04); + addbyte(0x24); + addlong(7); + addbyte(0xe8); /*CALL x86_int*/ + addlong((uint32_t) x86_int - (uint32_t) (&codeblock[block_current].data[block_pos + 4])); + addbyte(0xe9); /*JMP end*/ + addlong(BLOCK_EXIT_OFFSET - (block_pos + 4)); + + addbyte(0x31); /*XOR EAX, EAX*/ + addbyte(0xc0); + addbyte(0xc6); /*MOV ISMMX, 1*/ + addbyte(0x45); + addbyte((uint8_t) cpu_state_offset(ismmx)); + addbyte(1); + addbyte(0x89); /*MOV TOP, EAX*/ + addbyte(0x45); + addbyte((uint8_t) cpu_state_offset(TOP)); + addbyte(0x89); /*MOV tag, EAX*/ + addbyte(0x45); + addbyte((uint8_t) cpu_state_offset(tag[0])); + addbyte(0x89); /*MOV tag+4, EAX*/ + addbyte(0x45); + addbyte((uint8_t) cpu_state_offset(tag[4])); + + codegen_mmx_entered = 1; } extern int mmx_ebx_ecx_loaded; -static inline int LOAD_MMX_D(int guest_reg) +static __inline int +LOAD_MMX_D(int guest_reg) { - int host_reg = find_host_reg(); - host_reg_mapping[host_reg] = 100; + int host_reg = find_host_reg(); + host_reg_mapping[host_reg] = 100; - addbyte(0x8b); /*MOV EBX, reg*/ - addbyte(0x45 | (host_reg << 3)); - addbyte((uint8_t)cpu_state_offset(MM[guest_reg].l[0])); - - return host_reg; + addbyte(0x8b); /*MOV EBX, reg*/ + addbyte(0x45 | (host_reg << 3)); + addbyte((uint8_t) cpu_state_offset(MM[guest_reg].l[0])); + + return host_reg; } -static inline void LOAD_MMX_Q(int guest_reg, int *host_reg1, int *host_reg2) +static __inline void +LOAD_MMX_Q(int guest_reg, int *host_reg1, int *host_reg2) { - if (!mmx_ebx_ecx_loaded) - { - *host_reg1 = REG_EBX; - *host_reg2 = REG_ECX; - mmx_ebx_ecx_loaded = 1; - } - else - { - *host_reg1 = REG_EAX; - *host_reg2 = REG_EDX; - } + if (!mmx_ebx_ecx_loaded) { + *host_reg1 = REG_EBX; + *host_reg2 = REG_ECX; + mmx_ebx_ecx_loaded = 1; + } else { + *host_reg1 = REG_EAX; + *host_reg2 = REG_EDX; + } - addbyte(0x8b); /*MOV EBX, reg*/ - addbyte(0x45 | ((*host_reg1) << 3)); - addbyte((uint8_t)cpu_state_offset(MM[guest_reg].l[0])); - addbyte(0x8b); /*MOV ECX, reg+4*/ - addbyte(0x45 | ((*host_reg2) << 3)); - addbyte((uint8_t)cpu_state_offset(MM[guest_reg].l[1])); + addbyte(0x8b); /*MOV EBX, reg*/ + addbyte(0x45 | ((*host_reg1) << 3)); + addbyte((uint8_t) cpu_state_offset(MM[guest_reg].l[0])); + addbyte(0x8b); /*MOV ECX, reg+4*/ + addbyte(0x45 | ((*host_reg2) << 3)); + addbyte((uint8_t) cpu_state_offset(MM[guest_reg].l[1])); } -static inline int LOAD_MMX_Q_MMX(int guest_reg) +static __inline int +LOAD_MMX_Q_MMX(int guest_reg) { - int dst_reg = find_host_xmm_reg(); - host_reg_xmm_mapping[dst_reg] = guest_reg; + int dst_reg = find_host_xmm_reg(); + host_reg_xmm_mapping[dst_reg] = guest_reg; - addbyte(0xf3); /*MOVQ dst_reg,[reg]*/ - addbyte(0x0f); - addbyte(0x7e); - addbyte(0x45 | (dst_reg << 3)); - addbyte((uint8_t)cpu_state_offset(MM[guest_reg].q)); - - return dst_reg; + addbyte(0xf3); /*MOVQ dst_reg,[reg]*/ + addbyte(0x0f); + addbyte(0x7e); + addbyte(0x45 | (dst_reg << 3)); + addbyte((uint8_t) cpu_state_offset(MM[guest_reg].q)); + + return dst_reg; } -static inline int LOAD_INT_TO_MMX(int src_reg1, int src_reg2) +static __inline int +LOAD_INT_TO_MMX(int src_reg1, int src_reg2) { - int dst_reg = find_host_xmm_reg(); - host_reg_xmm_mapping[dst_reg] = 100; - - addbyte(0x66); /*MOVD dst_reg, src_reg1*/ - addbyte(0x0f); - addbyte(0x6e); - addbyte(0xc0 | (dst_reg << 3) | src_reg1); - addbyte(0x66); /*MOVD XMM7, src_reg2*/ - addbyte(0x0f); - addbyte(0x6e); - addbyte(0xc0 | (7 << 3) | src_reg2); - addbyte(0x66); /*PUNPCKLDQ dst_reg, XMM7*/ - addbyte(0x0f); - addbyte(0x62); - addbyte(0xc0 | 7 | (dst_reg << 3)); - - return dst_reg; + int dst_reg = find_host_xmm_reg(); + host_reg_xmm_mapping[dst_reg] = 100; + + addbyte(0x66); /*MOVD dst_reg, src_reg1*/ + addbyte(0x0f); + addbyte(0x6e); + addbyte(0xc0 | (dst_reg << 3) | src_reg1); + addbyte(0x66); /*MOVD XMM7, src_reg2*/ + addbyte(0x0f); + addbyte(0x6e); + addbyte(0xc0 | (7 << 3) | src_reg2); + addbyte(0x66); /*PUNPCKLDQ dst_reg, XMM7*/ + addbyte(0x0f); + addbyte(0x62); + addbyte(0xc0 | 7 | (dst_reg << 3)); + + return dst_reg; } -static inline void STORE_MMX_LQ(int guest_reg, int host_reg1) +static __inline void +STORE_MMX_LQ(int guest_reg, int host_reg1) { - addbyte(0xC7); /*MOVL [reg],0*/ - addbyte(0x45); - addbyte((uint8_t)cpu_state_offset(MM[guest_reg].l[1])); - addlong(0); - addbyte(0x89); /*MOVL [reg],host_reg*/ - addbyte(0x45 | (host_reg1 << 3)); - addbyte((uint8_t)cpu_state_offset(MM[guest_reg].l[0])); + addbyte(0xC7); /*MOVL [reg],0*/ + addbyte(0x45); + addbyte((uint8_t) cpu_state_offset(MM[guest_reg].l[1])); + addlong(0); + addbyte(0x89); /*MOVL [reg],host_reg*/ + addbyte(0x45 | (host_reg1 << 3)); + addbyte((uint8_t) cpu_state_offset(MM[guest_reg].l[0])); } -static inline void STORE_MMX_Q(int guest_reg, int host_reg1, int host_reg2) +static __inline void +STORE_MMX_Q(int guest_reg, int host_reg1, int host_reg2) { - addbyte(0x89); /*MOVL [reg],host_reg*/ - addbyte(0x45 | (host_reg1 << 3)); - addbyte((uint8_t)cpu_state_offset(MM[guest_reg].l[0])); - addbyte(0x89); /*MOVL [reg],host_reg*/ - addbyte(0x45 | (host_reg2 << 3)); - addbyte((uint8_t)cpu_state_offset(MM[guest_reg].l[1])); + addbyte(0x89); /*MOVL [reg],host_reg*/ + addbyte(0x45 | (host_reg1 << 3)); + addbyte((uint8_t) cpu_state_offset(MM[guest_reg].l[0])); + addbyte(0x89); /*MOVL [reg],host_reg*/ + addbyte(0x45 | (host_reg2 << 3)); + addbyte((uint8_t) cpu_state_offset(MM[guest_reg].l[1])); } -static inline void STORE_MMX_Q_MMX(int guest_reg, int host_reg) +static __inline void +STORE_MMX_Q_MMX(int guest_reg, int host_reg) { - addbyte(0x66); /*MOVQ [guest_reg],host_reg*/ - addbyte(0x0f); - addbyte(0xd6); - addbyte(0x45 | (host_reg << 3)); - addbyte((uint8_t)cpu_state_offset(MM[guest_reg].q)); + addbyte(0x66); /*MOVQ [guest_reg],host_reg*/ + addbyte(0x0f); + addbyte(0xd6); + addbyte(0x45 | (host_reg << 3)); + addbyte((uint8_t) cpu_state_offset(MM[guest_reg].q)); } -#define MMX_x86_OP(name, opcode) \ -static inline void MMX_ ## name(int dst_reg, int src_reg) \ -{ \ - addbyte(0x66); /*op dst_reg, src_reg*/ \ - addbyte(0x0f); \ - addbyte(opcode); \ - addbyte(0xc0 | (dst_reg << 3) | src_reg); \ -} +#define MMX_x86_OP(name, opcode) \ + static \ + __inline void MMX_##name(int dst_reg, int src_reg) \ + { \ + addbyte(0x66); /*op dst_reg, src_reg*/ \ + addbyte(0x0f); \ + addbyte(opcode); \ + addbyte(0xc0 | (dst_reg << 3) | src_reg); \ + } -MMX_x86_OP(AND, 0xdb) +// clang-format off +MMX_x86_OP(AND, 0xdb) MMX_x86_OP(ANDN, 0xdf) -MMX_x86_OP(OR, 0xeb) -MMX_x86_OP(XOR, 0xef) +MMX_x86_OP(OR, 0xeb) +MMX_x86_OP(XOR, 0xef) -MMX_x86_OP(ADDB, 0xfc) -MMX_x86_OP(ADDW, 0xfd) -MMX_x86_OP(ADDD, 0xfe) -MMX_x86_OP(ADDSB, 0xec) -MMX_x86_OP(ADDSW, 0xed) +MMX_x86_OP(ADDB, 0xfc) +MMX_x86_OP(ADDW, 0xfd) +MMX_x86_OP(ADDD, 0xfe) +MMX_x86_OP(ADDSB, 0xec) +MMX_x86_OP(ADDSW, 0xed) MMX_x86_OP(ADDUSB, 0xdc) MMX_x86_OP(ADDUSW, 0xdd) -MMX_x86_OP(SUBB, 0xf8) -MMX_x86_OP(SUBW, 0xf9) -MMX_x86_OP(SUBD, 0xfa) -MMX_x86_OP(SUBSB, 0xe8) -MMX_x86_OP(SUBSW, 0xe9) +MMX_x86_OP(SUBB, 0xf8) +MMX_x86_OP(SUBW, 0xf9) +MMX_x86_OP(SUBD, 0xfa) +MMX_x86_OP(SUBSB, 0xe8) +MMX_x86_OP(SUBSW, 0xe9) MMX_x86_OP(SUBUSB, 0xd8) MMX_x86_OP(SUBUSW, 0xd9) MMX_x86_OP(PUNPCKLBW, 0x60); MMX_x86_OP(PUNPCKLWD, 0x61); MMX_x86_OP(PUNPCKLDQ, 0x62); -MMX_x86_OP(PCMPGTB, 0x64); -MMX_x86_OP(PCMPGTW, 0x65); -MMX_x86_OP(PCMPGTD, 0x66); +MMX_x86_OP(PCMPGTB, 0x64); +MMX_x86_OP(PCMPGTW, 0x65); +MMX_x86_OP(PCMPGTD, 0x66); -MMX_x86_OP(PCMPEQB, 0x74); -MMX_x86_OP(PCMPEQW, 0x75); -MMX_x86_OP(PCMPEQD, 0x76); +MMX_x86_OP(PCMPEQB, 0x74); +MMX_x86_OP(PCMPEQW, 0x75); +MMX_x86_OP(PCMPEQD, 0x76); -MMX_x86_OP(PSRLW, 0xd1); -MMX_x86_OP(PSRLD, 0xd2); -MMX_x86_OP(PSRLQ, 0xd3); -MMX_x86_OP(PSRAW, 0xe1); -MMX_x86_OP(PSRAD, 0xe2); -MMX_x86_OP(PSLLW, 0xf1); -MMX_x86_OP(PSLLD, 0xf2); -MMX_x86_OP(PSLLQ, 0xf3); +MMX_x86_OP(PSRLW, 0xd1); +MMX_x86_OP(PSRLD, 0xd2); +MMX_x86_OP(PSRLQ, 0xd3); +MMX_x86_OP(PSRAW, 0xe1); +MMX_x86_OP(PSRAD, 0xe2); +MMX_x86_OP(PSLLW, 0xf1); +MMX_x86_OP(PSLLD, 0xf2); +MMX_x86_OP(PSLLQ, 0xf3); -MMX_x86_OP(PMULLW, 0xd5); -MMX_x86_OP(PMULHW, 0xe5); +MMX_x86_OP(PMULLW, 0xd5); +MMX_x86_OP(PMULHW, 0xe5); MMX_x86_OP(PMADDWD, 0xf5); +// clang-format on -static inline void MMX_PACKSSWB(int dst_reg, int src_reg) +static __inline void +MMX_PACKSSWB(int dst_reg, int src_reg) { - addbyte(0x66); /*PACKSSWB dst_reg, src_reg*/ - addbyte(0x0f); - addbyte(0x63); - addbyte(0xc0 | (dst_reg << 3) | src_reg); - addbyte(0x66); /*PSHUFD dst_reg, dst_reg*/ - addbyte(0x0f); - addbyte(0x70); - addbyte(0xc0 | (dst_reg << 3) | dst_reg); - addbyte(0x08); + addbyte(0x66); /*PACKSSWB dst_reg, src_reg*/ + addbyte(0x0f); + addbyte(0x63); + addbyte(0xc0 | (dst_reg << 3) | src_reg); + addbyte(0x66); /*PSHUFD dst_reg, dst_reg*/ + addbyte(0x0f); + addbyte(0x70); + addbyte(0xc0 | (dst_reg << 3) | dst_reg); + addbyte(0x08); } -static inline void MMX_PACKUSWB(int dst_reg, int src_reg) +static __inline void +MMX_PACKUSWB(int dst_reg, int src_reg) { - addbyte(0x66); /*PACKUSWB dst_reg, src_reg*/ - addbyte(0x0f); - addbyte(0x67); - addbyte(0xc0 | (dst_reg << 3) | src_reg); - addbyte(0x66); /*PSHUFD dst_reg, dst_reg*/ - addbyte(0x0f); - addbyte(0x70); - addbyte(0xc0 | (dst_reg << 3) | dst_reg); - addbyte(0x08); + addbyte(0x66); /*PACKUSWB dst_reg, src_reg*/ + addbyte(0x0f); + addbyte(0x67); + addbyte(0xc0 | (dst_reg << 3) | src_reg); + addbyte(0x66); /*PSHUFD dst_reg, dst_reg*/ + addbyte(0x0f); + addbyte(0x70); + addbyte(0xc0 | (dst_reg << 3) | dst_reg); + addbyte(0x08); } -static inline void MMX_PACKSSDW(int dst_reg, int src_reg) +static __inline void +MMX_PACKSSDW(int dst_reg, int src_reg) { - addbyte(0x66); /*PACKSSDW dst_reg, src_reg*/ - addbyte(0x0f); - addbyte(0x6b); - addbyte(0xc0 | (dst_reg << 3) | src_reg); - addbyte(0x66); /*PSHUFD dst_reg, dst_reg*/ - addbyte(0x0f); - addbyte(0x70); - addbyte(0xc0 | (dst_reg << 3) | dst_reg); - addbyte(0x08); + addbyte(0x66); /*PACKSSDW dst_reg, src_reg*/ + addbyte(0x0f); + addbyte(0x6b); + addbyte(0xc0 | (dst_reg << 3) | src_reg); + addbyte(0x66); /*PSHUFD dst_reg, dst_reg*/ + addbyte(0x0f); + addbyte(0x70); + addbyte(0xc0 | (dst_reg << 3) | dst_reg); + addbyte(0x08); } -static inline void MMX_PUNPCKHBW(int dst_reg, int src_reg) +static __inline void +MMX_PUNPCKHBW(int dst_reg, int src_reg) { - addbyte(0x66); /*PUNPCKLBW dst_reg, src_reg*/ - addbyte(0x0f); - addbyte(0x60); - addbyte(0xc0 | (dst_reg << 3) | src_reg); - addbyte(0x66); /*PSHUFD dst_reg, dst_reg*/ - addbyte(0x0f); - addbyte(0x70); - addbyte(0xc0 | (dst_reg << 3) | dst_reg); - addbyte(0x0e); + addbyte(0x66); /*PUNPCKLBW dst_reg, src_reg*/ + addbyte(0x0f); + addbyte(0x60); + addbyte(0xc0 | (dst_reg << 3) | src_reg); + addbyte(0x66); /*PSHUFD dst_reg, dst_reg*/ + addbyte(0x0f); + addbyte(0x70); + addbyte(0xc0 | (dst_reg << 3) | dst_reg); + addbyte(0x0e); } -static inline void MMX_PUNPCKHWD(int dst_reg, int src_reg) +static __inline void +MMX_PUNPCKHWD(int dst_reg, int src_reg) { - addbyte(0x66); /*PUNPCKLWD dst_reg, src_reg*/ - addbyte(0x0f); - addbyte(0x61); - addbyte(0xc0 | (dst_reg << 3) | src_reg); - addbyte(0x66); /*PSHUFD dst_reg, dst_reg*/ - addbyte(0x0f); - addbyte(0x70); - addbyte(0xc0 | (dst_reg << 3) | dst_reg); - addbyte(0x0e); + addbyte(0x66); /*PUNPCKLWD dst_reg, src_reg*/ + addbyte(0x0f); + addbyte(0x61); + addbyte(0xc0 | (dst_reg << 3) | src_reg); + addbyte(0x66); /*PSHUFD dst_reg, dst_reg*/ + addbyte(0x0f); + addbyte(0x70); + addbyte(0xc0 | (dst_reg << 3) | dst_reg); + addbyte(0x0e); } -static inline void MMX_PUNPCKHDQ(int dst_reg, int src_reg) +static __inline void +MMX_PUNPCKHDQ(int dst_reg, int src_reg) { - addbyte(0x66); /*PUNPCKLDQ dst_reg, src_reg*/ - addbyte(0x0f); - addbyte(0x62); - addbyte(0xc0 | (dst_reg << 3) | src_reg); - addbyte(0x66); /*PSHUFD dst_reg, dst_reg*/ - addbyte(0x0f); - addbyte(0x70); - addbyte(0xc0 | (dst_reg << 3) | dst_reg); - addbyte(0x0e); + addbyte(0x66); /*PUNPCKLDQ dst_reg, src_reg*/ + addbyte(0x0f); + addbyte(0x62); + addbyte(0xc0 | (dst_reg << 3) | src_reg); + addbyte(0x66); /*PSHUFD dst_reg, dst_reg*/ + addbyte(0x0f); + addbyte(0x70); + addbyte(0xc0 | (dst_reg << 3) | dst_reg); + addbyte(0x0e); } -static inline void MMX_PSRLW_imm(int dst_reg, int amount) +static __inline void +MMX_PSRLW_imm(int dst_reg, int amount) { - addbyte(0x66); /*PSRLW dst_reg, amount*/ - addbyte(0x0f); - addbyte(0x71); - addbyte(0xc0 | dst_reg | 0x10); - addbyte(amount); + addbyte(0x66); /*PSRLW dst_reg, amount*/ + addbyte(0x0f); + addbyte(0x71); + addbyte(0xc0 | dst_reg | 0x10); + addbyte(amount); } -static inline void MMX_PSRAW_imm(int dst_reg, int amount) +static __inline void +MMX_PSRAW_imm(int dst_reg, int amount) { - addbyte(0x66); /*PSRAW dst_reg, amount*/ - addbyte(0x0f); - addbyte(0x71); - addbyte(0xc0 | dst_reg | 0x20); - addbyte(amount); + addbyte(0x66); /*PSRAW dst_reg, amount*/ + addbyte(0x0f); + addbyte(0x71); + addbyte(0xc0 | dst_reg | 0x20); + addbyte(amount); } -static inline void MMX_PSLLW_imm(int dst_reg, int amount) +static __inline void +MMX_PSLLW_imm(int dst_reg, int amount) { - addbyte(0x66); /*PSLLW dst_reg, amount*/ - addbyte(0x0f); - addbyte(0x71); - addbyte(0xc0 | dst_reg | 0x30); - addbyte(amount); + addbyte(0x66); /*PSLLW dst_reg, amount*/ + addbyte(0x0f); + addbyte(0x71); + addbyte(0xc0 | dst_reg | 0x30); + addbyte(amount); } -static inline void MMX_PSRLD_imm(int dst_reg, int amount) +static __inline void +MMX_PSRLD_imm(int dst_reg, int amount) { - addbyte(0x66); /*PSRLD dst_reg, amount*/ - addbyte(0x0f); - addbyte(0x72); - addbyte(0xc0 | dst_reg | 0x10); - addbyte(amount); + addbyte(0x66); /*PSRLD dst_reg, amount*/ + addbyte(0x0f); + addbyte(0x72); + addbyte(0xc0 | dst_reg | 0x10); + addbyte(amount); } -static inline void MMX_PSRAD_imm(int dst_reg, int amount) +static __inline void +MMX_PSRAD_imm(int dst_reg, int amount) { - addbyte(0x66); /*PSRAD dst_reg, amount*/ - addbyte(0x0f); - addbyte(0x72); - addbyte(0xc0 | dst_reg | 0x20); - addbyte(amount); + addbyte(0x66); /*PSRAD dst_reg, amount*/ + addbyte(0x0f); + addbyte(0x72); + addbyte(0xc0 | dst_reg | 0x20); + addbyte(amount); } -static inline void MMX_PSLLD_imm(int dst_reg, int amount) +static __inline void +MMX_PSLLD_imm(int dst_reg, int amount) { - addbyte(0x66); /*PSLLD dst_reg, amount*/ - addbyte(0x0f); - addbyte(0x72); - addbyte(0xc0 | dst_reg | 0x30); - addbyte(amount); + addbyte(0x66); /*PSLLD dst_reg, amount*/ + addbyte(0x0f); + addbyte(0x72); + addbyte(0xc0 | dst_reg | 0x30); + addbyte(amount); } -static inline void MMX_PSRLQ_imm(int dst_reg, int amount) +static __inline void +MMX_PSRLQ_imm(int dst_reg, int amount) { - addbyte(0x66); /*PSRLQ dst_reg, amount*/ - addbyte(0x0f); - addbyte(0x73); - addbyte(0xc0 | dst_reg | 0x10); - addbyte(amount); + addbyte(0x66); /*PSRLQ dst_reg, amount*/ + addbyte(0x0f); + addbyte(0x73); + addbyte(0xc0 | dst_reg | 0x10); + addbyte(amount); } -static inline void MMX_PSRAQ_imm(int dst_reg, int amount) +static __inline void +MMX_PSRAQ_imm(int dst_reg, int amount) { - addbyte(0x66); /*PSRAQ dst_reg, amount*/ - addbyte(0x0f); - addbyte(0x73); - addbyte(0xc0 | dst_reg | 0x20); - addbyte(amount); + addbyte(0x66); /*PSRAQ dst_reg, amount*/ + addbyte(0x0f); + addbyte(0x73); + addbyte(0xc0 | dst_reg | 0x20); + addbyte(amount); } -static inline void MMX_PSLLQ_imm(int dst_reg, int amount) +static __inline void +MMX_PSLLQ_imm(int dst_reg, int amount) { - addbyte(0x66); /*PSLLQ dst_reg, amount*/ - addbyte(0x0f); - addbyte(0x73); - addbyte(0xc0 | dst_reg | 0x30); - addbyte(amount); + addbyte(0x66); /*PSLLQ dst_reg, amount*/ + addbyte(0x0f); + addbyte(0x73); + addbyte(0xc0 | dst_reg | 0x30); + addbyte(amount); } - -static inline void SAVE_EA() +static __inline void +SAVE_EA(void) { - addbyte(0x89); /*MOV [ESP+12], EAX*/ - addbyte(0x44); - addbyte(0x24); - addbyte(12); + addbyte(0x89); /*MOV [ESP+12], EAX*/ + addbyte(0x44); + addbyte(0x24); + addbyte(12); } -static inline void LOAD_EA() +static __inline void +LOAD_EA(void) { - addbyte(0x8b); /*MOV EAX, [ESP+12]*/ - addbyte(0x44); - addbyte(0x24); - addbyte(12); + addbyte(0x8b); /*MOV EAX, [ESP+12]*/ + addbyte(0x44); + addbyte(0x24); + addbyte(12); } #define MEM_CHECK_WRITE_B MEM_CHECK_WRITE -static inline void MEM_CHECK_WRITE(x86seg *seg) +static __inline void +MEM_CHECK_WRITE(x86seg *seg) { - CHECK_SEG_WRITE(seg); - if ((seg == &cpu_state.seg_ds && codegen_flat_ds && !(cpu_cur_status & CPU_STATUS_NOTFLATDS)) || (seg == &cpu_state.seg_ss && codegen_flat_ss && !(cpu_cur_status & CPU_STATUS_NOTFLATSS))) - { - addbyte(0x31); /*XOR ESI, ESI*/ - addbyte(0xf6); - } - else - { - addbyte(0x8b); /*MOVL ESI, seg->base*/ - addbyte(0x05 | (REG_ESI << 3)); - addlong((uint32_t)&seg->base); - } - addbyte(0xe8); /*CALL mem_check_write*/ - addlong(mem_check_write - (uint32_t)(&codeblock[block_current].data[block_pos + 4])); - LOAD_EA(); + CHECK_SEG_WRITE(seg); + if ((seg == &cpu_state.seg_ds && codegen_flat_ds && !(cpu_cur_status & CPU_STATUS_NOTFLATDS)) || (seg == &cpu_state.seg_ss && codegen_flat_ss && !(cpu_cur_status & CPU_STATUS_NOTFLATSS))) { + addbyte(0x31); /*XOR ESI, ESI*/ + addbyte(0xf6); + } else { + addbyte(0x8b); /*MOVL ESI, seg->base*/ + addbyte(0x05 | (REG_ESI << 3)); + addlong((uint32_t) &seg->base); + } + addbyte(0xe8); /*CALL mem_check_write*/ + addlong(mem_check_write - (uint32_t) (&codeblock[block_current].data[block_pos + 4])); + LOAD_EA(); } -static inline void MEM_CHECK_WRITE_W(x86seg *seg) +static __inline void +MEM_CHECK_WRITE_W(x86seg *seg) { - CHECK_SEG_WRITE(seg); - if ((seg == &cpu_state.seg_ds && codegen_flat_ds && !(cpu_cur_status & CPU_STATUS_NOTFLATDS)) || (seg == &cpu_state.seg_ss && codegen_flat_ss && !(cpu_cur_status & CPU_STATUS_NOTFLATSS))) - { - addbyte(0x31); /*XOR ESI, ESI*/ - addbyte(0xf6); - } - else - { - addbyte(0x8b); /*MOVL ESI, seg->base*/ - addbyte(0x05 | (REG_ESI << 3)); - addlong((uint32_t)&seg->base); - } - addbyte(0xe8); /*CALL mem_check_write_w*/ - addlong(mem_check_write_w - (uint32_t)(&codeblock[block_current].data[block_pos + 4])); - LOAD_EA(); + CHECK_SEG_WRITE(seg); + if ((seg == &cpu_state.seg_ds && codegen_flat_ds && !(cpu_cur_status & CPU_STATUS_NOTFLATDS)) || (seg == &cpu_state.seg_ss && codegen_flat_ss && !(cpu_cur_status & CPU_STATUS_NOTFLATSS))) { + addbyte(0x31); /*XOR ESI, ESI*/ + addbyte(0xf6); + } else { + addbyte(0x8b); /*MOVL ESI, seg->base*/ + addbyte(0x05 | (REG_ESI << 3)); + addlong((uint32_t) &seg->base); + } + addbyte(0xe8); /*CALL mem_check_write_w*/ + addlong(mem_check_write_w - (uint32_t) (&codeblock[block_current].data[block_pos + 4])); + LOAD_EA(); } -static inline void MEM_CHECK_WRITE_L(x86seg *seg) +static __inline void +MEM_CHECK_WRITE_L(x86seg *seg) { - CHECK_SEG_WRITE(seg); - if ((seg == &cpu_state.seg_ds && codegen_flat_ds && !(cpu_cur_status & CPU_STATUS_NOTFLATDS)) || (seg == &cpu_state.seg_ss && codegen_flat_ss && !(cpu_cur_status & CPU_STATUS_NOTFLATSS))) - { - addbyte(0x31); /*XOR ESI, ESI*/ - addbyte(0xf6); - } - else - { - addbyte(0x8b); /*MOVL ESI, seg->base*/ - addbyte(0x05 | (REG_ESI << 3)); - addlong((uint32_t)&seg->base); - } - addbyte(0xe8); /*CALL mem_check_write_l*/ - addlong(mem_check_write_l - (uint32_t)(&codeblock[block_current].data[block_pos + 4])); - LOAD_EA(); + CHECK_SEG_WRITE(seg); + if ((seg == &cpu_state.seg_ds && codegen_flat_ds && !(cpu_cur_status & CPU_STATUS_NOTFLATDS)) || (seg == &cpu_state.seg_ss && codegen_flat_ss && !(cpu_cur_status & CPU_STATUS_NOTFLATSS))) { + addbyte(0x31); /*XOR ESI, ESI*/ + addbyte(0xf6); + } else { + addbyte(0x8b); /*MOVL ESI, seg->base*/ + addbyte(0x05 | (REG_ESI << 3)); + addlong((uint32_t) &seg->base); + } + addbyte(0xe8); /*CALL mem_check_write_l*/ + addlong(mem_check_write_l - (uint32_t) (&codeblock[block_current].data[block_pos + 4])); + LOAD_EA(); } -static inline void LOAD_SEG(int host_reg, void *seg) +static __inline void +LOAD_SEG(int host_reg, void *seg) { - addbyte(0xc7); /*MOV [ESP+4], seg*/ - addbyte(0x44); - addbyte(0x24); - addbyte(4); - addlong((uint32_t)seg); - addbyte(0x89); /*MOV [ESP], host_reg*/ - addbyte(0x04 | (host_reg << 3)); - addbyte(0x24); - CALL_FUNC((uintptr_t)loadseg); - addbyte(0x80); /*CMP abrt, 0*/ - addbyte(0x7d); - addbyte((uint8_t)cpu_state_offset(abrt)); - addbyte(0); - addbyte(0x0f); /*JNE end*/ - addbyte(0x85); - addlong(BLOCK_EXIT_OFFSET - (block_pos + 4)); + addbyte(0xc7); /*MOV [ESP+4], seg*/ + addbyte(0x44); + addbyte(0x24); + addbyte(4); + addlong((uint32_t) seg); + addbyte(0x89); /*MOV [ESP], host_reg*/ + addbyte(0x04 | (host_reg << 3)); + addbyte(0x24); + CALL_FUNC((uintptr_t) loadseg); + addbyte(0x80); /*CMP abrt, 0*/ + addbyte(0x7d); + addbyte((uint8_t) cpu_state_offset(abrt)); + addbyte(0); + addbyte(0x0f); /*JNE end*/ + addbyte(0x85); + addlong(BLOCK_EXIT_OFFSET - (block_pos + 4)); } diff --git a/src/codegen/codegen_ops_xchg.h b/src/codegen/codegen_ops_xchg.h index 76cb9e437..28a558078 100644 --- a/src/codegen/codegen_ops_xchg.h +++ b/src/codegen/codegen_ops_xchg.h @@ -1,16 +1,17 @@ -#define OP_XCHG_AX_(reg) \ - static uint32_t ropXCHG_AX_ ## reg(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block) \ - { \ - int ax_reg, host_reg, temp_reg; \ - \ - ax_reg = LOAD_REG_W(REG_AX); \ - host_reg = LOAD_REG_W(REG_ ## reg); \ - temp_reg = COPY_REG(host_reg); \ - STORE_REG_TARGET_W_RELEASE(ax_reg, REG_ ## reg); \ - STORE_REG_TARGET_W_RELEASE(temp_reg, REG_AX); \ - \ - return op_pc; \ - } +#define OP_XCHG_AX_(reg) \ + static uint32_t \ + ropXCHG_AX_##reg(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block) \ + { \ + int ax_reg, host_reg, temp_reg; \ + \ + ax_reg = LOAD_REG_W(REG_AX); \ + host_reg = LOAD_REG_W(REG_##reg); \ + temp_reg = COPY_REG(host_reg); \ + STORE_REG_TARGET_W_RELEASE(ax_reg, REG_##reg); \ + STORE_REG_TARGET_W_RELEASE(temp_reg, REG_AX); \ + \ + return op_pc; \ + } OP_XCHG_AX_(BX) OP_XCHG_AX_(CX) @@ -20,19 +21,20 @@ OP_XCHG_AX_(DI) OP_XCHG_AX_(SP) OP_XCHG_AX_(BP) -#define OP_XCHG_EAX_(reg) \ - static uint32_t ropXCHG_EAX_ ## reg(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block) \ - { \ - int eax_reg, host_reg, temp_reg; \ - \ - eax_reg = LOAD_REG_L(REG_EAX); \ - host_reg = LOAD_REG_L(REG_ ## reg); \ - temp_reg = COPY_REG(host_reg); \ - STORE_REG_TARGET_L_RELEASE(eax_reg, REG_ ## reg); \ - STORE_REG_TARGET_L_RELEASE(temp_reg, REG_EAX); \ - \ - return op_pc; \ - } +#define OP_XCHG_EAX_(reg) \ + static uint32_t \ + ropXCHG_EAX_##reg(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block) \ + { \ + int eax_reg, host_reg, temp_reg; \ + \ + eax_reg = LOAD_REG_L(REG_EAX); \ + host_reg = LOAD_REG_L(REG_##reg); \ + temp_reg = COPY_REG(host_reg); \ + STORE_REG_TARGET_L_RELEASE(eax_reg, REG_##reg); \ + STORE_REG_TARGET_L_RELEASE(temp_reg, REG_EAX); \ + \ + return op_pc; \ + } OP_XCHG_EAX_(EBX) OP_XCHG_EAX_(ECX) @@ -42,48 +44,57 @@ OP_XCHG_EAX_(EDI) OP_XCHG_EAX_(ESP) OP_XCHG_EAX_(EBP) -static uint32_t ropXCHG_b(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block) +static uint32_t +ropXCHG_b(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block) { - int src_reg, dst_reg, temp_reg; + int src_reg; + int dst_reg; + int temp_reg; - if ((fetchdat & 0xc0) != 0xc0) - return 0; + if ((fetchdat & 0xc0) != 0xc0) + return 0; - dst_reg = LOAD_REG_B(fetchdat & 7); - src_reg = LOAD_REG_B((fetchdat >> 3) & 7); - temp_reg = COPY_REG(src_reg); - STORE_REG_TARGET_B_RELEASE(dst_reg, (fetchdat >> 3) & 7); - STORE_REG_TARGET_B_RELEASE(temp_reg, fetchdat & 7); - - return op_pc + 1; + dst_reg = LOAD_REG_B(fetchdat & 7); + src_reg = LOAD_REG_B((fetchdat >> 3) & 7); + temp_reg = COPY_REG(src_reg); + STORE_REG_TARGET_B_RELEASE(dst_reg, (fetchdat >> 3) & 7); + STORE_REG_TARGET_B_RELEASE(temp_reg, fetchdat & 7); + + return op_pc + 1; } -static uint32_t ropXCHG_w(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block) +static uint32_t +ropXCHG_w(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block) { - int src_reg, dst_reg, temp_reg; + int src_reg; + int dst_reg; + int temp_reg; - if ((fetchdat & 0xc0) != 0xc0) - return 0; + if ((fetchdat & 0xc0) != 0xc0) + return 0; - dst_reg = LOAD_REG_W(fetchdat & 7); - src_reg = LOAD_REG_W((fetchdat >> 3) & 7); - temp_reg = COPY_REG(src_reg); - STORE_REG_TARGET_W_RELEASE(dst_reg, (fetchdat >> 3) & 7); - STORE_REG_TARGET_W_RELEASE(temp_reg, fetchdat & 7); - - return op_pc + 1; + dst_reg = LOAD_REG_W(fetchdat & 7); + src_reg = LOAD_REG_W((fetchdat >> 3) & 7); + temp_reg = COPY_REG(src_reg); + STORE_REG_TARGET_W_RELEASE(dst_reg, (fetchdat >> 3) & 7); + STORE_REG_TARGET_W_RELEASE(temp_reg, fetchdat & 7); + + return op_pc + 1; } -static uint32_t ropXCHG_l(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block) +static uint32_t +ropXCHG_l(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block) { - int src_reg, dst_reg, temp_reg; + int src_reg; + int dst_reg; + int temp_reg; - if ((fetchdat & 0xc0) != 0xc0) - return 0; + if ((fetchdat & 0xc0) != 0xc0) + return 0; - dst_reg = LOAD_REG_L(fetchdat & 7); - src_reg = LOAD_REG_L((fetchdat >> 3) & 7); - temp_reg = COPY_REG(src_reg); - STORE_REG_TARGET_L_RELEASE(dst_reg, (fetchdat >> 3) & 7); - STORE_REG_TARGET_L_RELEASE(temp_reg, fetchdat & 7); - - return op_pc + 1; + dst_reg = LOAD_REG_L(fetchdat & 7); + src_reg = LOAD_REG_L((fetchdat >> 3) & 7); + temp_reg = COPY_REG(src_reg); + STORE_REG_TARGET_L_RELEASE(dst_reg, (fetchdat >> 3) & 7); + STORE_REG_TARGET_L_RELEASE(temp_reg, fetchdat & 7); + + return op_pc + 1; } diff --git a/src/codegen/codegen_x86-64.c b/src/codegen/codegen_x86-64.c index ff1e1c682..421f20026 100644 --- a/src/codegen/codegen_x86-64.c +++ b/src/codegen/codegen_x86-64.c @@ -1,1185 +1,1121 @@ #if defined __amd64__ || defined _M_X64 -#include -#include -#include -#include -#include -#define HAVE_STDARG_H -#include <86box/86box.h> -#include "cpu.h" -#include "x86.h" -#include "x86_flags.h" -#include "x86_ops.h" -#include "x87.h" -#include <86box/mem.h> +# include +# include +# include +# include +# include +# define HAVE_STDARG_H +# include <86box/86box.h> +# include "cpu.h" +# include "x86.h" +# include "x86_flags.h" +# include "x86_ops.h" +# include "x86seg_common.h" +# include "x86seg.h" +# include "x87.h" +# include <86box/mem.h> +# include <86box/plat_unused.h> -#include "386_common.h" +# include "386_common.h" -#include "codegen.h" -#include "codegen_accumulate.h" -#include "codegen_ops.h" -#include "codegen_ops_x86-64.h" +# include "codegen.h" +# include "codegen_accumulate.h" +# include "codegen_ops.h" +# include "codegen_ops_x86-64.h" -#if defined(__unix__) || defined(__APPLE__) -#include -#include -#endif -#if _WIN64 -#include -#endif +# if defined(__unix__) || defined(__APPLE__) || defined(__HAIKU__) +# include +# include +# endif +# if _WIN64 +# include +# endif -int codegen_flat_ds, codegen_flat_ss; -int codegen_flags_changed = 0; -int codegen_fpu_entered = 0; -int codegen_fpu_loaded_iq[8]; -int codegen_reg_loaded[8]; -x86seg *op_ea_seg; -int op_ssegs; +int codegen_flat_ds; +int codegen_flat_ss; +int codegen_flags_changed = 0; +int codegen_fpu_entered = 0; +int codegen_fpu_loaded_iq[8]; +int codegen_reg_loaded[8]; +x86seg *op_ea_seg; +int op_ssegs; uint32_t op_old_pc; uint32_t recomp_page = -1; -int host_reg_mapping[NR_HOST_REGS]; -int host_reg_xmm_mapping[NR_HOST_XMM_REGS]; -codeblock_t *codeblock; +int host_reg_mapping[NR_HOST_REGS]; +int host_reg_xmm_mapping[NR_HOST_XMM_REGS]; +codeblock_t *codeblock; codeblock_t **codeblock_hash; -int codegen_mmx_entered = 0; +int codegen_mmx_entered = 0; -int block_current = 0; +int block_current = 0; static int block_num; -int block_pos; +int block_pos; uint32_t codegen_endpc; -int codegen_block_cycles; +int codegen_block_cycles; static int codegen_block_ins; static int codegen_block_full_ins; static uint32_t last_op32; -static x86seg *last_ea_seg; -static int last_ssegs; +static x86seg *last_ea_seg; +static int last_ssegs; -void codegen_init() +void +codegen_init(void) { - int c; - -#if _WIN64 - codeblock = VirtualAlloc(NULL, BLOCK_SIZE * sizeof(codeblock_t), MEM_COMMIT, PAGE_EXECUTE_READWRITE); -#elif defined(__unix__) || defined(__APPLE__) - codeblock = mmap(NULL, BLOCK_SIZE * sizeof(codeblock_t), PROT_READ | PROT_WRITE | PROT_EXEC, MAP_ANON | MAP_PRIVATE, -1, 0); -#else - codeblock = malloc(BLOCK_SIZE * sizeof(codeblock_t)); -#endif - codeblock_hash = malloc(HASH_SIZE * sizeof(codeblock_t *)); +# if _WIN64 + codeblock = VirtualAlloc(NULL, BLOCK_SIZE * sizeof(codeblock_t), MEM_COMMIT, PAGE_EXECUTE_READWRITE); +# elif defined(__unix__) || defined(__APPLE__) || defined(__HAIKU__) + codeblock = mmap(NULL, BLOCK_SIZE * sizeof(codeblock_t), PROT_READ | PROT_WRITE | PROT_EXEC, MAP_ANON | MAP_PRIVATE, -1, 0); +# else + codeblock = malloc(BLOCK_SIZE * sizeof(codeblock_t)); +# endif + codeblock_hash = malloc(HASH_SIZE * sizeof(codeblock_t *)); - memset(codeblock, 0, BLOCK_SIZE * sizeof(codeblock_t)); - memset(codeblock_hash, 0, HASH_SIZE * sizeof(codeblock_t *)); + memset(codeblock, 0, BLOCK_SIZE * sizeof(codeblock_t)); + memset(codeblock_hash, 0, HASH_SIZE * sizeof(codeblock_t *)); - for (c = 0; c < BLOCK_SIZE; c++) - codeblock[c].valid = 0; + for (int c = 0; c < BLOCK_SIZE; c++) + codeblock[c].valid = 0; } -void codegen_reset() +void +codegen_reset(void) { - int c; - - memset(codeblock, 0, BLOCK_SIZE * sizeof(codeblock_t)); - memset(codeblock_hash, 0, HASH_SIZE * sizeof(codeblock_t *)); - mem_reset_page_blocks(); + memset(codeblock, 0, BLOCK_SIZE * sizeof(codeblock_t)); + memset(codeblock_hash, 0, HASH_SIZE * sizeof(codeblock_t *)); + mem_reset_page_blocks(); - for (c = 0; c < BLOCK_SIZE; c++) - codeblock[c].valid = 0; + for (int c = 0; c < BLOCK_SIZE; c++) + codeblock[c].valid = 0; } -void dump_block() +void +dump_block(void) { + // } -static void add_to_block_list(codeblock_t *block) +static void +add_to_block_list(codeblock_t *block) { - codeblock_t *block_prev = pages[block->phys >> 12].block[(block->phys >> 10) & 3]; + codeblock_t *block_prev = pages[block->phys >> 12].block[(block->phys >> 10) & 3]; - if (!block->page_mask) - fatal("add_to_block_list - mask = 0\n"); + if (!block->page_mask) + fatal("add_to_block_list - mask = 0\n"); - if (block_prev) - { - block->next = block_prev; - block_prev->prev = block; - pages[block->phys >> 12].block[(block->phys >> 10) & 3] = block; - } - else - { - block->next = NULL; - pages[block->phys >> 12].block[(block->phys >> 10) & 3] = block; - } + if (block_prev) { + block->next = block_prev; + block_prev->prev = block; + pages[block->phys >> 12].block[(block->phys >> 10) & 3] = block; + } else { + block->next = NULL; + pages[block->phys >> 12].block[(block->phys >> 10) & 3] = block; + } - if (block->next) - { - if (block->next->valid == 0) - fatal("block->next->valid=0 %p %p %x %x\n", (void *)block->next, (void *)codeblock, block_current, block_pos); - } - - if (block->page_mask2) - { - block_prev = pages[block->phys_2 >> 12].block_2[(block->phys_2 >> 10) & 3]; + if (block->next) { + if (block->next->valid == 0) + fatal("block->next->valid=0 %p %p %x %x\n", (void *) block->next, (void *) codeblock, block_current, block_pos); + } - if (block_prev) - { - block->next_2 = block_prev; - block_prev->prev_2 = block; - pages[block->phys_2 >> 12].block_2[(block->phys_2 >> 10) & 3] = block; - } - else - { - block->next_2 = NULL; - pages[block->phys_2 >> 12].block_2[(block->phys_2 >> 10) & 3] = block; - } + if (block->page_mask2) { + block_prev = pages[block->phys_2 >> 12].block_2[(block->phys_2 >> 10) & 3]; + + if (block_prev) { + block->next_2 = block_prev; + block_prev->prev_2 = block; + pages[block->phys_2 >> 12].block_2[(block->phys_2 >> 10) & 3] = block; + } else { + block->next_2 = NULL; + pages[block->phys_2 >> 12].block_2[(block->phys_2 >> 10) & 3] = block; } + } } -static void remove_from_block_list(codeblock_t *block, uint32_t pc) -{ - if (!block->page_mask) - return; - - if (block->prev) - { - block->prev->next = block->next; - if (block->next) - block->next->prev = block->prev; - } - else - { - pages[block->phys >> 12].block[(block->phys >> 10) & 3] = block->next; - if (block->next) - block->next->prev = NULL; - else - mem_flush_write_page(block->phys, 0); - } - if (!block->page_mask2) - { - if (block->prev_2 || block->next_2) - fatal("Invalid block_2\n"); - return; - } - - if (block->prev_2) - { - block->prev_2->next_2 = block->next_2; - if (block->next_2) - block->next_2->prev_2 = block->prev_2; - } - else - { - pages[block->phys_2 >> 12].block_2[(block->phys_2 >> 10) & 3] = block->next_2; - if (block->next_2) - block->next_2->prev_2 = NULL; - else - mem_flush_write_page(block->phys_2, 0); - } -} - -static void delete_block(codeblock_t *block) -{ - uint32_t old_pc = block->pc; - - if (block == codeblock_hash[HASH(block->phys)]) - codeblock_hash[HASH(block->phys)] = NULL; - - if (block->valid == 0) - fatal("Deleting deleted block\n"); - block->valid = 0; - - codeblock_tree_delete(block); - remove_from_block_list(block, old_pc); -} - -void codegen_check_flush(page_t *page, uint64_t mask, uint32_t phys_addr) -{ - struct codeblock_t *block = page->block[(phys_addr >> 10) & 3]; - - while (block) - { - if (mask & block->page_mask) - { - delete_block(block); - } - if (block == block->next) - fatal("Broken 1\n"); - block = block->next; - } - - block = page->block_2[(phys_addr >> 10) & 3]; - - while (block) - { - if (mask & block->page_mask2) - { - delete_block(block); - } - if (block == block->next_2) - fatal("Broken 2\n"); - block = block->next_2; - } -} - -void codegen_block_init(uint32_t phys_addr) -{ - codeblock_t *block; - page_t *page = &pages[phys_addr >> 12]; - - if (!page->block[(phys_addr >> 10) & 3]) - mem_flush_write_page(phys_addr, cs+cpu_state.pc); - - block_current = (block_current + 1) & BLOCK_MASK; - block = &codeblock[block_current]; - - if (block->valid != 0) - { - delete_block(block); - } - block_num = HASH(phys_addr); - codeblock_hash[block_num] = &codeblock[block_current]; - - block->valid = 1; - block->ins = 0; - block->pc = cs + cpu_state.pc; - block->_cs = cs; - block->pnt = block_current; - block->phys = phys_addr; - block->dirty_mask = &page->dirty_mask[(phys_addr >> PAGE_MASK_INDEX_SHIFT) & PAGE_MASK_INDEX_MASK]; - block->dirty_mask2 = NULL; - block->next = block->prev = NULL; - block->next_2 = block->prev_2 = NULL; - block->page_mask = 0; - block->flags = 0; - block->status = cpu_cur_status; - - block->was_recompiled = 0; - - recomp_page = block->phys & ~0xfff; - - codeblock_tree_add(block); -} - -void codegen_block_start_recompile(codeblock_t *block) -{ - page_t *page = &pages[block->phys >> 12]; - - if (!page->block[(block->phys >> 10) & 3]) - mem_flush_write_page(block->phys, cs+cpu_state.pc); - - block_num = HASH(block->phys); - block_current = block->pnt; - - if (block->pc != cs + cpu_state.pc || block->was_recompiled) - fatal("Recompile to used block!\n"); - - block->status = cpu_cur_status; - - block_pos = BLOCK_GPF_OFFSET; -#ifdef OLD_GPF -#if _WIN64 - addbyte(0x48); /*XOR RCX, RCX*/ - addbyte(0x31); - addbyte(0xc9); - addbyte(0x31); /*XOR EDX, EDX*/ - addbyte(0xd2); -#else - addbyte(0x48); /*XOR RDI, RDI*/ - addbyte(0x31); - addbyte(0xff); - addbyte(0x31); /*XOR ESI, ESI*/ - addbyte(0xf6); -#endif - call(block, (uintptr_t)x86gpf); - while (block_pos < BLOCK_EXIT_OFFSET) - addbyte(0x90); /*NOP*/ -#else - addbyte(0xc6); /* mov byte ptr[&(cpu_state.abrt)],ABRT_GPF */ - addbyte(0x05); - addlong((uint32_t) (uintptr_t) &(cpu_state.abrt)); - addbyte(ABRT_GPF); - addbyte(0x31); /* xor eax,eax */ - addbyte(0xc0); - addbyte(0x67); /* mov [&(abrt_error)],eax */ - addbyte(0xa3); - addlong((uint32_t) (uintptr_t) &(abrt_error)); -#endif - block_pos = BLOCK_EXIT_OFFSET; /*Exit code*/ - addbyte(0x48); /*ADDL $40,%rsp*/ - addbyte(0x83); - addbyte(0xC4); - addbyte(0x28); - addbyte(0x41); /*POP R15*/ - addbyte(0x5f); - addbyte(0x41); /*POP R14*/ - addbyte(0x5e); - addbyte(0x41); /*POP R13*/ - addbyte(0x5d); - addbyte(0x41); /*POP R12*/ - addbyte(0x5c); - addbyte(0x5f); /*POP RDI*/ - addbyte(0x5e); /*POP RSI*/ - addbyte(0x5d); /*POP RBP*/ - addbyte(0x5b); /*POP RDX*/ - addbyte(0xC3); /*RET*/ - cpu_block_end = 0; - block_pos = 0; /*Entry code*/ - addbyte(0x53); /*PUSH RBX*/ - addbyte(0x55); /*PUSH RBP*/ - addbyte(0x56); /*PUSH RSI*/ - addbyte(0x57); /*PUSH RDI*/ - addbyte(0x41); /*PUSH R12*/ - addbyte(0x54); - addbyte(0x41); /*PUSH R13*/ - addbyte(0x55); - addbyte(0x41); /*PUSH R14*/ - addbyte(0x56); - addbyte(0x41); /*PUSH R15*/ - addbyte(0x57); - addbyte(0x48); /*SUBL $40,%rsp*/ - addbyte(0x83); - addbyte(0xEC); - addbyte(0x28); - addbyte(0x48); /*MOVL RBP, &cpu_state*/ - addbyte(0xBD); - addquad(((uintptr_t)&cpu_state) + 128); - - last_op32 = -1; - last_ea_seg = NULL; - last_ssegs = -1; - - codegen_block_cycles = 0; - codegen_timing_block_start(); - - codegen_block_ins = 0; - codegen_block_full_ins = 0; - - recomp_page = block->phys & ~0xfff; - - codegen_flags_changed = 0; - codegen_fpu_entered = 0; - codegen_mmx_entered = 0; - - codegen_fpu_loaded_iq[0] = codegen_fpu_loaded_iq[1] = codegen_fpu_loaded_iq[2] = codegen_fpu_loaded_iq[3] = - codegen_fpu_loaded_iq[4] = codegen_fpu_loaded_iq[5] = codegen_fpu_loaded_iq[6] = codegen_fpu_loaded_iq[7] = 0; - - cpu_state.seg_ds.checked = cpu_state.seg_es.checked = cpu_state.seg_fs.checked = cpu_state.seg_gs.checked = (cr0 & 1) ? 0 : 1; - - codegen_reg_loaded[0] = codegen_reg_loaded[1] = codegen_reg_loaded[2] = codegen_reg_loaded[3] = - codegen_reg_loaded[4] = codegen_reg_loaded[5] = codegen_reg_loaded[6] = codegen_reg_loaded[7] = 0; - - block->was_recompiled = 1; - - codegen_flat_ds = !(cpu_cur_status & CPU_STATUS_NOTFLATDS); - codegen_flat_ss = !(cpu_cur_status & CPU_STATUS_NOTFLATSS); -} - -void codegen_block_remove() -{ - codeblock_t *block = &codeblock[block_current]; - - delete_block(block); - - recomp_page = -1; -} - -void codegen_block_generate_end_mask() -{ - codeblock_t *block = &codeblock[block_current]; - uint32_t start_pc; - uint32_t end_pc; - - block->endpc = codegen_endpc; - - block->page_mask = 0; - start_pc = (block->pc & 0x3ff) & ~15; - if ((block->pc ^ block->endpc) & ~0x3ff) - end_pc = 0x3ff & ~15; - else - end_pc = (block->endpc & 0x3ff) & ~15; - if (end_pc < start_pc) - end_pc = 0x3ff; - start_pc >>= PAGE_MASK_SHIFT; - end_pc >>= PAGE_MASK_SHIFT; - - for (; start_pc <= end_pc; start_pc++) - block->page_mask |= ((uint64_t)1 << start_pc); - - pages[block->phys >> 12].code_present_mask[(block->phys >> 10) & 3] |= block->page_mask; - - block->phys_2 = -1; - block->page_mask2 = 0; - block->next_2 = block->prev_2 = NULL; - if ((block->pc ^ block->endpc) & ~0x3ff) - { - block->phys_2 = get_phys_noabrt(block->endpc); - if (block->phys_2 != -1) - { - page_t *page_2 = &pages[block->phys_2 >> 12]; - - start_pc = 0; - end_pc = (block->endpc & 0x3ff) >> PAGE_MASK_SHIFT; - for (; start_pc <= end_pc; start_pc++) - block->page_mask2 |= ((uint64_t)1 << start_pc); - page_2->code_present_mask[(block->phys_2 >> 10) & 3] |= block->page_mask2; - - if (!pages[block->phys_2 >> 12].block_2[(block->phys_2 >> 10) & 3]) - mem_flush_write_page(block->phys_2, block->endpc); - - if (!block->page_mask2) - fatal("!page_mask2\n"); - if (block->next_2) - { - if (block->next_2->valid == 0) - fatal("block->next_2->valid=0 %p\n", (void *)block->next_2); - } - - block->dirty_mask2 = &page_2->dirty_mask[(block->phys_2 >> PAGE_MASK_INDEX_SHIFT) & PAGE_MASK_INDEX_MASK]; - } - } - - recomp_page = -1; -} - -void codegen_block_end() -{ - codeblock_t *block = &codeblock[block_current]; - - codegen_block_generate_end_mask(); - add_to_block_list(block); -} - -void codegen_block_end_recompile(codeblock_t *block) -{ - codegen_timing_block_end(); - codegen_accumulate(ACCREG_cycles, -codegen_block_cycles); - - codegen_accumulate_flush(); - - addbyte(0x48); /*ADDL $40,%rsp*/ - addbyte(0x83); - addbyte(0xC4); - addbyte(0x28); - addbyte(0x41); /*POP R15*/ - addbyte(0x5f); - addbyte(0x41); /*POP R14*/ - addbyte(0x5e); - addbyte(0x41); /*POP R13*/ - addbyte(0x5d); - addbyte(0x41); /*POP R12*/ - addbyte(0x5c); - addbyte(0x5f); /*POP RDI*/ - addbyte(0x5e); /*POP RSI*/ - addbyte(0x5d); /*POP RBP*/ - addbyte(0x5b); /*POP RDX*/ - addbyte(0xC3); /*RET*/ - - if (block_pos > BLOCK_GPF_OFFSET) - fatal("Over limit!\n"); - - remove_from_block_list(block, block->pc); - block->next = block->prev = NULL; - block->next_2 = block->prev_2 = NULL; - codegen_block_generate_end_mask(); - add_to_block_list(block); -} - -void codegen_flush() +static void +remove_from_block_list(codeblock_t *block, uint32_t pc) { + if (!block->page_mask) return; -} -static int opcode_modrm[256] = -{ - 1, 1, 1, 1, 0, 0, 0, 0, 1, 1, 1, 1, 0, 0, 0, 0, /*00*/ - 1, 1, 1, 1, 0, 0, 0, 0, 1, 1, 1, 1, 0, 0, 0, 0, /*10*/ - 1, 1, 1, 1, 0, 0, 0, 0, 1, 1, 1, 1, 0, 0, 0, 0, /*20*/ - 1, 1, 1, 1, 0, 0, 0, 0, 1, 1, 1, 1, 0, 0, 0, 0, /*30*/ - - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /*40*/ - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /*50*/ - 0, 0, 1, 1, 0, 0, 0, 0, 0, 1, 0, 1, 0, 0, 0, 0, /*60*/ - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /*70*/ - - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /*80*/ - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /*90*/ - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /*a0*/ - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /*b0*/ - - 1, 1, 0, 0, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, /*c0*/ - 1, 1, 1, 1, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, /*d0*/ - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /*e0*/ - 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 1, 1, /*f0*/ -}; -int opcode_0f_modrm[256] = -{ - 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, /*00*/ - 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, /*10*/ - 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /*20*/ - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, /*30*/ - - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /*40*/ - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /*50*/ - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 1, 1, /*60*/ - 0, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 1, 1, /*70*/ - - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /*80*/ - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /*90*/ - 0, 0, 0, 1, 1, 1, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, /*a0*/ - 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 1, 1, 1, 1, 1, 1, /*b0*/ - - 1, 1, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, /*c0*/ - 0, 1, 1, 1, 0, 1, 0, 0, 1, 1, 0, 1, 1, 1, 0, 1, /*d0*/ - 0, 1, 1, 0, 0, 1, 0, 0, 1, 1, 0, 1, 1, 1, 0, 1, /*e0*/ - 0, 1, 1, 1, 0, 1, 0, 0, 1, 1, 1, 0, 1, 1, 1, 0 /*f0*/ -}; - -void codegen_debug() -{ -} - -static x86seg *codegen_generate_ea_16_long(x86seg *op_ea_seg, uint32_t fetchdat, int op_ssegs, uint32_t *op_pc) -{ - if (!cpu_mod && cpu_rm == 6) - { - addbyte(0xC7); /*MOVL $0,(ssegs)*/ - addbyte(0x45); - addbyte((uint8_t)cpu_state_offset(eaaddr)); - addlong((fetchdat >> 8) & 0xffff); - (*op_pc) += 2; - } + if (block->prev) { + block->prev->next = block->next; + if (block->next) + block->next->prev = block->prev; + } else { + pages[block->phys >> 12].block[(block->phys >> 10) & 3] = block->next; + if (block->next) + block->next->prev = NULL; else - { - int base_reg = 0, index_reg = 0; - - switch (cpu_rm) - { - case 0: case 1: case 7: - base_reg = LOAD_REG_W(REG_BX); - break; - case 2: case 3: case 6: - base_reg = LOAD_REG_W(REG_BP); - break; - case 4: - base_reg = LOAD_REG_W(REG_SI); - break; - case 5: - base_reg = LOAD_REG_W(REG_DI); - break; - } - if (!(cpu_rm & 4)) - { - if (cpu_rm & 1) - index_reg = LOAD_REG_W(REG_DI); - else - index_reg = LOAD_REG_W(REG_SI); - } - base_reg &= 7; - index_reg &= 7; - - switch (cpu_mod) - { - case 0: - if (cpu_rm & 4) - { - addbyte(0x41); /*MOVZX EAX, base_reg*/ - addbyte(0x0f); - addbyte(0xb7); - addbyte(0xc0 | base_reg); - } - else - { - addbyte(0x67); /*LEA EAX, base_reg+index_reg*/ - addbyte(0x43); - addbyte(0x8d); - if (base_reg == 5) - { - addbyte(0x44); - addbyte(base_reg | (index_reg << 3)); - addbyte(0); - } - else - { - addbyte(0x04); - addbyte(base_reg | (index_reg << 3)); - } - } - break; - case 1: - if (cpu_rm & 4) - { - addbyte(0x67); /*LEA EAX, base_reg+imm8*/ - addbyte(0x41); - addbyte(0x8d); - addbyte(0x40 | base_reg); - addbyte((fetchdat >> 8) & 0xff); - } - else - { - addbyte(0x67); /*LEA EAX, base_reg+index_reg+imm8*/ - addbyte(0x43); - addbyte(0x8d); - addbyte(0x44); - addbyte(base_reg | (index_reg << 3)); - addbyte((fetchdat >> 8) & 0xff); - } - (*op_pc)++; - break; - case 2: - if (cpu_rm & 4) - { - addbyte(0x67); /*LEA EAX, base_reg+imm8*/ - addbyte(0x41); - addbyte(0x8d); - addbyte(0x80 | base_reg); - addlong((fetchdat >> 8) & 0xffff); - } - else - { - addbyte(0x67); /*LEA EAX, base_reg+index_reg+imm16*/ - addbyte(0x43); - addbyte(0x8d); - addbyte(0x84); - addbyte(base_reg | (index_reg << 3)); - addlong((fetchdat >> 8) & 0xffff); - } - (*op_pc) += 2; - break; - - } - if (cpu_mod || !(cpu_rm & 4)) - { - addbyte(0x25); /*ANDL $0xffff, %eax*/ - addlong(0xffff); - } - addbyte(0x89); /*MOV eaaddr, EAX*/ - addbyte(0x45); - addbyte((uint8_t)cpu_state_offset(eaaddr)); + mem_flush_write_page(block->phys, 0); + } + if (!block->page_mask2) { + if (block->prev_2 || block->next_2) + fatal("Invalid block_2\n"); + return; + } - if (mod1seg[cpu_rm] == &ss && !op_ssegs) - op_ea_seg = &cpu_state.seg_ss; - } - return op_ea_seg; + if (block->prev_2) { + block->prev_2->next_2 = block->next_2; + if (block->next_2) + block->next_2->prev_2 = block->prev_2; + } else { + pages[block->phys_2 >> 12].block_2[(block->phys_2 >> 10) & 3] = block->next_2; + if (block->next_2) + block->next_2->prev_2 = NULL; + else + mem_flush_write_page(block->phys_2, 0); + } } -//#if 0 -static x86seg *codegen_generate_ea_32_long(x86seg *op_ea_seg, uint32_t fetchdat, int op_ssegs, uint32_t *op_pc, int stack_offset) + +static void +delete_block(codeblock_t *block) { - uint32_t new_eaaddr; + uint32_t old_pc = block->pc; - if (cpu_rm == 4) - { - uint8_t sib = fetchdat >> 8; - int base_reg = -1, index_reg = -1; + if (block == codeblock_hash[HASH(block->phys)]) + codeblock_hash[HASH(block->phys)] = NULL; + if (block->valid == 0) + fatal("Deleting deleted block\n"); + block->valid = 0; + + codeblock_tree_delete(block); + remove_from_block_list(block, old_pc); +} + +void +codegen_check_flush(page_t *page, uint64_t mask, uint32_t phys_addr) +{ + struct codeblock_t *block = page->block[(phys_addr >> 10) & 3]; + + while (block) { + if (mask & block->page_mask) { + delete_block(block); + } + if (block == block->next) + fatal("Broken 1\n"); + block = block->next; + } + + block = page->block_2[(phys_addr >> 10) & 3]; + + while (block) { + if (mask & block->page_mask2) { + delete_block(block); + } + if (block == block->next_2) + fatal("Broken 2\n"); + block = block->next_2; + } +} + +void +codegen_block_init(uint32_t phys_addr) +{ + codeblock_t *block; + page_t *page = &pages[phys_addr >> 12]; + + if (!page->block[(phys_addr >> 10) & 3]) + mem_flush_write_page(phys_addr, cs + cpu_state.pc); + + block_current = (block_current + 1) & BLOCK_MASK; + block = &codeblock[block_current]; + + if (block->valid != 0) { + delete_block(block); + } + block_num = HASH(phys_addr); + codeblock_hash[block_num] = &codeblock[block_current]; + + block->valid = 1; + block->ins = 0; + block->pc = cs + cpu_state.pc; + block->_cs = cs; + block->pnt = block_current; + block->phys = phys_addr; + block->dirty_mask = &page->dirty_mask[(phys_addr >> PAGE_MASK_INDEX_SHIFT) & PAGE_MASK_INDEX_MASK]; + block->dirty_mask2 = NULL; + block->next = block->prev = NULL; + block->next_2 = block->prev_2 = NULL; + block->page_mask = 0; + block->flags = 0; + block->status = cpu_cur_status; + + block->was_recompiled = 0; + + recomp_page = block->phys & ~0xfff; + + codeblock_tree_add(block); +} + +void +codegen_block_start_recompile(codeblock_t *block) +{ + page_t *page = &pages[block->phys >> 12]; + uintptr_t rip_rel; + + if (!page->block[(block->phys >> 10) & 3]) + mem_flush_write_page(block->phys, cs + cpu_state.pc); + + block_num = HASH(block->phys); + block_current = block->pnt; + + if (block->pc != cs + cpu_state.pc || block->was_recompiled) + fatal("Recompile to used block!\n"); + + block->status = cpu_cur_status; + + block_pos = BLOCK_GPF_OFFSET; +# ifdef OLD_GPF +# if _WIN64 + addbyte(0x48); /*XOR RCX, RCX*/ + addbyte(0x31); + addbyte(0xc9); + addbyte(0x31); /*XOR EDX, EDX*/ + addbyte(0xd2); +# else + addbyte(0x48); /*XOR RDI, RDI*/ + addbyte(0x31); + addbyte(0xff); + addbyte(0x31); /*XOR ESI, ESI*/ + addbyte(0xf6); +# endif + call(block, (uintptr_t) x86gpf); + while (block_pos < BLOCK_EXIT_OFFSET) + addbyte(0x90); /*NOP*/ +# else + addbyte(0xC6); /*MOVB ABRT_GPF,(abrt)*/ + addbyte(0x45); + addbyte((uint8_t) cpu_state_offset(abrt)); + addbyte(ABRT_GPF); + addbyte(0x31); /* xor eax,eax */ + addbyte(0xc0); + addbyte(0x89); /*MOVB eax,(abrt_error)*/ + addbyte(0x85); + rip_rel = ((uintptr_t) &cpu_state) + 128; + rip_rel = ((uintptr_t) & (abrt_error)) - rip_rel; + addlong((uint32_t) rip_rel); +# endif + block_pos = BLOCK_EXIT_OFFSET; /*Exit code*/ + addbyte(0x48); /*ADDL $40,%rsp*/ + addbyte(0x83); + addbyte(0xC4); + addbyte(0x28); + addbyte(0x41); /*POP R15*/ + addbyte(0x5f); + addbyte(0x41); /*POP R14*/ + addbyte(0x5e); + addbyte(0x41); /*POP R13*/ + addbyte(0x5d); + addbyte(0x41); /*POP R12*/ + addbyte(0x5c); + addbyte(0x5f); /*POP RDI*/ + addbyte(0x5e); /*POP RSI*/ + addbyte(0x5d); /*POP RBP*/ + addbyte(0x5b); /*POP RDX*/ + addbyte(0xC3); /*RET*/ + cpu_block_end = 0; + block_pos = 0; /*Entry code*/ + addbyte(0x53); /*PUSH RBX*/ + addbyte(0x55); /*PUSH RBP*/ + addbyte(0x56); /*PUSH RSI*/ + addbyte(0x57); /*PUSH RDI*/ + addbyte(0x41); /*PUSH R12*/ + addbyte(0x54); + addbyte(0x41); /*PUSH R13*/ + addbyte(0x55); + addbyte(0x41); /*PUSH R14*/ + addbyte(0x56); + addbyte(0x41); /*PUSH R15*/ + addbyte(0x57); + addbyte(0x48); /*SUBL $40,%rsp*/ + addbyte(0x83); + addbyte(0xEC); + addbyte(0x28); + addbyte(0x48); /*MOVL RBP, &cpu_state*/ + addbyte(0xBD); + addquad(((uintptr_t) &cpu_state) + 128); + + last_op32 = -1; + last_ea_seg = NULL; + last_ssegs = -1; + + codegen_block_cycles = 0; + codegen_timing_block_start(); + + codegen_block_ins = 0; + codegen_block_full_ins = 0; + + recomp_page = block->phys & ~0xfff; + + codegen_flags_changed = 0; + codegen_fpu_entered = 0; + codegen_mmx_entered = 0; + + codegen_fpu_loaded_iq[0] = codegen_fpu_loaded_iq[1] = codegen_fpu_loaded_iq[2] = codegen_fpu_loaded_iq[3] = codegen_fpu_loaded_iq[4] = codegen_fpu_loaded_iq[5] = codegen_fpu_loaded_iq[6] = codegen_fpu_loaded_iq[7] = 0; + + cpu_state.seg_ds.checked = cpu_state.seg_es.checked = cpu_state.seg_fs.checked = cpu_state.seg_gs.checked = (cr0 & 1) ? 0 : 1; + + codegen_reg_loaded[0] = codegen_reg_loaded[1] = codegen_reg_loaded[2] = codegen_reg_loaded[3] = codegen_reg_loaded[4] = codegen_reg_loaded[5] = codegen_reg_loaded[6] = codegen_reg_loaded[7] = 0; + + block->was_recompiled = 1; + + codegen_flat_ds = !(cpu_cur_status & CPU_STATUS_NOTFLATDS); + codegen_flat_ss = !(cpu_cur_status & CPU_STATUS_NOTFLATSS); +} + +void +codegen_block_remove(void) +{ + codeblock_t *block = &codeblock[block_current]; + + delete_block(block); + + recomp_page = -1; +} + +void +codegen_block_generate_end_mask(void) +{ + codeblock_t *block = &codeblock[block_current]; + uint32_t start_pc; + uint32_t end_pc; + + block->endpc = codegen_endpc; + + block->page_mask = 0; + start_pc = (block->pc & 0x3ff) & ~15; + if ((block->pc ^ block->endpc) & ~0x3ff) + end_pc = 0x3ff & ~15; + else + end_pc = (block->endpc & 0x3ff) & ~15; + if (end_pc < start_pc) + end_pc = 0x3ff; + start_pc >>= PAGE_MASK_SHIFT; + end_pc >>= PAGE_MASK_SHIFT; + + for (; start_pc <= end_pc; start_pc++) + block->page_mask |= ((uint64_t) 1 << start_pc); + + pages[block->phys >> 12].code_present_mask[(block->phys >> 10) & 3] |= block->page_mask; + + block->phys_2 = -1; + block->page_mask2 = 0; + block->next_2 = block->prev_2 = NULL; + if ((block->pc ^ block->endpc) & ~0x3ff) { + block->phys_2 = get_phys_noabrt(block->endpc); + if (block->phys_2 != -1) { + page_t *page_2 = &pages[block->phys_2 >> 12]; + + start_pc = 0; + end_pc = (block->endpc & 0x3ff) >> PAGE_MASK_SHIFT; + for (; start_pc <= end_pc; start_pc++) + block->page_mask2 |= ((uint64_t) 1 << start_pc); + page_2->code_present_mask[(block->phys_2 >> 10) & 3] |= block->page_mask2; + + if (!pages[block->phys_2 >> 12].block_2[(block->phys_2 >> 10) & 3]) + mem_flush_write_page(block->phys_2, block->endpc); + + if (!block->page_mask2) + fatal("!page_mask2\n"); + if (block->next_2) { + if (block->next_2->valid == 0) + fatal("block->next_2->valid=0 %p\n", (void *) block->next_2); + } + + block->dirty_mask2 = &page_2->dirty_mask[(block->phys_2 >> PAGE_MASK_INDEX_SHIFT) & PAGE_MASK_INDEX_MASK]; + } + } + + recomp_page = -1; +} + +void +codegen_block_end(void) +{ + codeblock_t *block = &codeblock[block_current]; + + codegen_block_generate_end_mask(); + add_to_block_list(block); +} + +void +codegen_block_end_recompile(codeblock_t *block) +{ + codegen_timing_block_end(); + codegen_accumulate(ACCREG_cycles, -codegen_block_cycles); + + codegen_accumulate_flush(); + + addbyte(0x48); /*ADDL $40,%rsp*/ + addbyte(0x83); + addbyte(0xC4); + addbyte(0x28); + addbyte(0x41); /*POP R15*/ + addbyte(0x5f); + addbyte(0x41); /*POP R14*/ + addbyte(0x5e); + addbyte(0x41); /*POP R13*/ + addbyte(0x5d); + addbyte(0x41); /*POP R12*/ + addbyte(0x5c); + addbyte(0x5f); /*POP RDI*/ + addbyte(0x5e); /*POP RSI*/ + addbyte(0x5d); /*POP RBP*/ + addbyte(0x5b); /*POP RDX*/ + addbyte(0xC3); /*RET*/ + + if (block_pos > BLOCK_GPF_OFFSET) + fatal("Over limit!\n"); + + remove_from_block_list(block, block->pc); + block->next = block->prev = NULL; + block->next_2 = block->prev_2 = NULL; + codegen_block_generate_end_mask(); + add_to_block_list(block); +} + +void +codegen_flush(void) +{ + return; +} + +// clang-format off +static int opcode_modrm[256] = { + 1, 1, 1, 1, 0, 0, 0, 0, 1, 1, 1, 1, 0, 0, 0, 0, /*00*/ + 1, 1, 1, 1, 0, 0, 0, 0, 1, 1, 1, 1, 0, 0, 0, 0, /*10*/ + 1, 1, 1, 1, 0, 0, 0, 0, 1, 1, 1, 1, 0, 0, 0, 0, /*20*/ + 1, 1, 1, 1, 0, 0, 0, 0, 1, 1, 1, 1, 0, 0, 0, 0, /*30*/ + + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /*40*/ + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /*50*/ + 0, 0, 1, 1, 0, 0, 0, 0, 0, 1, 0, 1, 0, 0, 0, 0, /*60*/ + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /*70*/ + + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /*80*/ + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /*90*/ + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /*a0*/ + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /*b0*/ + + 1, 1, 0, 0, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, /*c0*/ + 1, 1, 1, 1, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, /*d0*/ + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /*e0*/ + 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 1, 1, /*f0*/ +}; + +int opcode_0f_modrm[256] = { + 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, /*00*/ + 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, /*10*/ + 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /*20*/ + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, /*30*/ + + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /*40*/ + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /*50*/ + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 1, 1, /*60*/ + 0, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 1, 1, /*70*/ + + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /*80*/ + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /*90*/ + 0, 0, 0, 1, 1, 1, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, /*a0*/ + 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 1, 1, 1, 1, 1, 1, /*b0*/ + + 1, 1, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, /*c0*/ + 0, 1, 1, 1, 0, 1, 0, 0, 1, 1, 0, 1, 1, 1, 0, 1, /*d0*/ + 0, 1, 1, 0, 0, 1, 0, 0, 1, 1, 0, 1, 1, 1, 0, 1, /*e0*/ + 0, 1, 1, 1, 0, 1, 0, 0, 1, 1, 1, 0, 1, 1, 1, 0 /*f0*/ +}; +// clang-format off + +void +codegen_debug(void) +{ + // +} + +static x86seg * +codegen_generate_ea_16_long(x86seg *op_ea_seg, uint32_t fetchdat, int op_ssegs, uint32_t *op_pc) +{ + if (!cpu_mod && cpu_rm == 6) { + addbyte(0xC7); /*MOVL $0,(ssegs)*/ + addbyte(0x45); + addbyte((uint8_t) cpu_state_offset(eaaddr)); + addlong((fetchdat >> 8) & 0xffff); + (*op_pc) += 2; + } else { + int base_reg = 0, index_reg = 0; + + switch (cpu_rm) { + case 0: + case 1: + case 7: + base_reg = LOAD_REG_W(REG_BX); + break; + case 2: + case 3: + case 6: + base_reg = LOAD_REG_W(REG_BP); + break; + case 4: + base_reg = LOAD_REG_W(REG_SI); + break; + case 5: + base_reg = LOAD_REG_W(REG_DI); + break; + } + if (!(cpu_rm & 4)) { + if (cpu_rm & 1) + index_reg = LOAD_REG_W(REG_DI); + else + index_reg = LOAD_REG_W(REG_SI); + } + base_reg &= 7; + index_reg &= 7; + + switch (cpu_mod) { + case 0: + if (cpu_rm & 4) { + addbyte(0x41); /*MOVZX EAX, base_reg*/ + addbyte(0x0f); + addbyte(0xb7); + addbyte(0xc0 | base_reg); + } else { + addbyte(0x67); /*LEA EAX, base_reg+index_reg*/ + addbyte(0x43); + addbyte(0x8d); + if (base_reg == 5) { + addbyte(0x44); + addbyte(base_reg | (index_reg << 3)); + addbyte(0); + } else { + addbyte(0x04); + addbyte(base_reg | (index_reg << 3)); + } + } + break; + case 1: + if (cpu_rm & 4) { + addbyte(0x67); /*LEA EAX, base_reg+imm8*/ + addbyte(0x41); + addbyte(0x8d); + addbyte(0x40 | base_reg); + addbyte((fetchdat >> 8) & 0xff); + } else { + addbyte(0x67); /*LEA EAX, base_reg+index_reg+imm8*/ + addbyte(0x43); + addbyte(0x8d); + addbyte(0x44); + addbyte(base_reg | (index_reg << 3)); + addbyte((fetchdat >> 8) & 0xff); + } (*op_pc)++; - - if (cpu_mod || (sib & 7) != 5) - base_reg = LOAD_REG_L(sib & 7) & 7; - - if (((sib >> 3) & 7) != 4) - index_reg = LOAD_REG_L((sib >> 3) & 7) & 7; - - if (index_reg == -1) - { - switch (cpu_mod) - { - case 0: - if ((sib & 7) == 5) - { - new_eaaddr = fastreadl(cs + (*op_pc) + 1); - addbyte(0xb8); /*MOV EAX, imm32*/ - addlong(new_eaaddr); - (*op_pc) += 4; - } - else - { - addbyte(0x44); /*MOV EAX, base_reg*/ - addbyte(0x89); - addbyte(0xc0 | (base_reg << 3)); - } - break; - case 1: - addbyte(0x67); /*LEA EAX, imm8+base_reg*/ - addbyte(0x41); - addbyte(0x8d); - if (base_reg == 4) - { - addbyte(0x44); - addbyte(0x24); - } - else - { - addbyte(0x40 | base_reg); - } - addbyte((fetchdat >> 16) & 0xff); - (*op_pc)++; - break; - case 2: - new_eaaddr = fastreadl(cs + (*op_pc) + 1); - addbyte(0x67); /*LEA EAX, imm32+base_reg*/ - addbyte(0x41); - addbyte(0x8d); - if (base_reg == 4) - { - addbyte(0x84); - addbyte(0x24); - } - else - { - addbyte(0x80 | base_reg); - } - addlong(new_eaaddr); - (*op_pc) += 4; - break; - } + break; + case 2: + if (cpu_rm & 4) { + addbyte(0x67); /*LEA EAX, base_reg+imm8*/ + addbyte(0x41); + addbyte(0x8d); + addbyte(0x80 | base_reg); + addlong((fetchdat >> 8) & 0xffff); + } else { + addbyte(0x67); /*LEA EAX, base_reg+index_reg+imm16*/ + addbyte(0x43); + addbyte(0x8d); + addbyte(0x84); + addbyte(base_reg | (index_reg << 3)); + addlong((fetchdat >> 8) & 0xffff); } - else - { - switch (cpu_mod) - { - case 0: - if ((sib & 7) == 5) - { - new_eaaddr = fastreadl(cs + (*op_pc) + 1); - if (sib >> 6) - { - addbyte(0x67); /*LEA EAX, imm32+index_reg*scale*/ - addbyte(0x42); - addbyte(0x8d); - addbyte(0x04); - addbyte(0x05 | (sib & 0xc0) | (index_reg << 3)); - addlong(new_eaaddr); - } - else - { - addbyte(0x67); /*LEA EAX, imm32+index_reg*/ - addbyte(0x41); - addbyte(0x8d); - addbyte(0x80 | index_reg); - addlong(new_eaaddr); - } - (*op_pc) += 4; - } - else - { - addbyte(0x67); /*LEA EAX, base_reg+index_reg*scale*/ - addbyte(0x43); - addbyte(0x8d); - if (base_reg == 5) - { - addbyte(0x44); - addbyte(base_reg | (index_reg << 3) | (sib & 0xc0)); - addbyte(0); - } - else - { - addbyte(0x04); - addbyte(base_reg | (index_reg << 3) | (sib & 0xc0)); - } - } - break; - case 1: - addbyte(0x67); /*LEA EAX, imm8+base_reg+index_reg*scale*/ - addbyte(0x43); - addbyte(0x8d); - addbyte(0x44); - addbyte(base_reg | (index_reg << 3) | (sib & 0xc0)); - addbyte((fetchdat >> 16) & 0xff); - (*op_pc)++; - break; - case 2: - new_eaaddr = fastreadl(cs + (*op_pc) + 1); - addbyte(0x67); /*LEA EAX, imm32+base_reg+index_reg*scale*/ - addbyte(0x43); - addbyte(0x8d); - addbyte(0x84); - addbyte(base_reg | (index_reg << 3) | (sib & 0xc0)); - addlong(new_eaaddr); - (*op_pc) += 4; - break; - } - } - if (stack_offset && (sib & 7) == 4 && (cpu_mod || (sib & 7) != 5)) /*ESP*/ - { - addbyte(0x05); - addlong(stack_offset); - } - if (((sib & 7) == 4 || (cpu_mod && (sib & 7) == 5)) && !op_ssegs) - op_ea_seg = &cpu_state.seg_ss; - - addbyte(0x89); /*MOV eaaddr, EAX*/ - addbyte(0x45); - addbyte((uint8_t)cpu_state_offset(eaaddr)); + (*op_pc) += 2; + break; } - else - { - int base_reg; + if (cpu_mod || !(cpu_rm & 4)) { + addbyte(0x25); /*ANDL $0xffff, %eax*/ + addlong(0xffff); + } + addbyte(0x89); /*MOV eaaddr, EAX*/ + addbyte(0x45); + addbyte((uint8_t) cpu_state_offset(eaaddr)); - if (!cpu_mod && cpu_rm == 5) - { + if (mod1seg[cpu_rm] == &ss && !op_ssegs) + op_ea_seg = &cpu_state.seg_ss; + } + return op_ea_seg; +} +// #if 0 +static x86seg * +codegen_generate_ea_32_long(x86seg *op_ea_seg, uint32_t fetchdat, int op_ssegs, uint32_t *op_pc, int stack_offset) +{ + uint32_t new_eaaddr; + + if (cpu_rm == 4) { + uint8_t sib = fetchdat >> 8; + int base_reg = -1, index_reg = -1; + + (*op_pc)++; + + if (cpu_mod || (sib & 7) != 5) + base_reg = LOAD_REG_L(sib & 7) & 7; + + if (((sib >> 3) & 7) != 4) + index_reg = LOAD_REG_L((sib >> 3) & 7) & 7; + + if (index_reg == -1) { + switch (cpu_mod) { + case 0: + if ((sib & 7) == 5) { new_eaaddr = fastreadl(cs + (*op_pc) + 1); - addbyte(0xC7); /*MOVL $new_eaaddr,(eaaddr)*/ - addbyte(0x45); - addbyte((uint8_t)cpu_state_offset(eaaddr)); + addbyte(0xb8); /*MOV EAX, imm32*/ addlong(new_eaaddr); (*op_pc) += 4; - return op_ea_seg; - } - base_reg = LOAD_REG_L(cpu_rm) & 7; - if (cpu_mod) - { - if (cpu_rm == 5 && !op_ssegs) - op_ea_seg = &cpu_state.seg_ss; - if (cpu_mod == 1) - { - addbyte(0x67); /*LEA EAX, base_reg+imm8*/ - addbyte(0x41); - addbyte(0x8d); - addbyte(0x40 | base_reg); - addbyte((fetchdat >> 8) & 0xff); - (*op_pc)++; - } - else - { - new_eaaddr = fastreadl(cs + (*op_pc) + 1); - addbyte(0x67); /*LEA EAX, base_reg+imm32*/ - addbyte(0x41); - addbyte(0x8d); - addbyte(0x80 | base_reg); - addlong(new_eaaddr); - (*op_pc) += 4; - } - addbyte(0x89); /*MOV eaaddr, EAX*/ - addbyte(0x45); - addbyte((uint8_t)cpu_state_offset(eaaddr)); - } - else - { - addbyte(0x44); /*MOV eaaddr, base_reg*/ + } else { + addbyte(0x44); /*MOV EAX, base_reg*/ addbyte(0x89); - addbyte(0x45 | (base_reg << 3)); - addbyte((uint8_t)cpu_state_offset(eaaddr)); - } + addbyte(0xc0 | (base_reg << 3)); + } + break; + case 1: + addbyte(0x67); /*LEA EAX, imm8+base_reg*/ + addbyte(0x41); + addbyte(0x8d); + if (base_reg == 4) { + addbyte(0x44); + addbyte(0x24); + } else { + addbyte(0x40 | base_reg); + } + addbyte((fetchdat >> 16) & 0xff); + (*op_pc)++; + break; + case 2: + new_eaaddr = fastreadl(cs + (*op_pc) + 1); + addbyte(0x67); /*LEA EAX, imm32+base_reg*/ + addbyte(0x41); + addbyte(0x8d); + if (base_reg == 4) { + addbyte(0x84); + addbyte(0x24); + } else { + addbyte(0x80 | base_reg); + } + addlong(new_eaaddr); + (*op_pc) += 4; + break; + } + } else { + switch (cpu_mod) { + case 0: + if ((sib & 7) == 5) { + new_eaaddr = fastreadl(cs + (*op_pc) + 1); + if (sib >> 6) { + addbyte(0x67); /*LEA EAX, imm32+index_reg*scale*/ + addbyte(0x42); + addbyte(0x8d); + addbyte(0x04); + addbyte(0x05 | (sib & 0xc0) | (index_reg << 3)); + addlong(new_eaaddr); + } else { + addbyte(0x67); /*LEA EAX, imm32+index_reg*/ + addbyte(0x41); + addbyte(0x8d); + addbyte(0x80 | index_reg); + addlong(new_eaaddr); + } + (*op_pc) += 4; + } else { + addbyte(0x67); /*LEA EAX, base_reg+index_reg*scale*/ + addbyte(0x43); + addbyte(0x8d); + if (base_reg == 5) { + addbyte(0x44); + addbyte(base_reg | (index_reg << 3) | (sib & 0xc0)); + addbyte(0); + } else { + addbyte(0x04); + addbyte(base_reg | (index_reg << 3) | (sib & 0xc0)); + } + } + break; + case 1: + addbyte(0x67); /*LEA EAX, imm8+base_reg+index_reg*scale*/ + addbyte(0x43); + addbyte(0x8d); + addbyte(0x44); + addbyte(base_reg | (index_reg << 3) | (sib & 0xc0)); + addbyte((fetchdat >> 16) & 0xff); + (*op_pc)++; + break; + case 2: + new_eaaddr = fastreadl(cs + (*op_pc) + 1); + addbyte(0x67); /*LEA EAX, imm32+base_reg+index_reg*scale*/ + addbyte(0x43); + addbyte(0x8d); + addbyte(0x84); + addbyte(base_reg | (index_reg << 3) | (sib & 0xc0)); + addlong(new_eaaddr); + (*op_pc) += 4; + break; + } } - return op_ea_seg; + if (stack_offset && (sib & 7) == 4 && (cpu_mod || (sib & 7) != 5)) /*ESP*/ + { + addbyte(0x05); + addlong(stack_offset); + } + if (((sib & 7) == 4 || (cpu_mod && (sib & 7) == 5)) && !op_ssegs) + op_ea_seg = &cpu_state.seg_ss; + + addbyte(0x89); /*MOV eaaddr, EAX*/ + addbyte(0x45); + addbyte((uint8_t) cpu_state_offset(eaaddr)); + } else { + int base_reg; + + if (!cpu_mod && cpu_rm == 5) { + new_eaaddr = fastreadl(cs + (*op_pc) + 1); + addbyte(0xC7); /*MOVL $new_eaaddr,(eaaddr)*/ + addbyte(0x45); + addbyte((uint8_t) cpu_state_offset(eaaddr)); + addlong(new_eaaddr); + (*op_pc) += 4; + return op_ea_seg; + } + base_reg = LOAD_REG_L(cpu_rm) & 7; + if (cpu_mod) { + if (cpu_rm == 5 && !op_ssegs) + op_ea_seg = &cpu_state.seg_ss; + if (cpu_mod == 1) { + addbyte(0x67); /*LEA EAX, base_reg+imm8*/ + addbyte(0x41); + addbyte(0x8d); + addbyte(0x40 | base_reg); + addbyte((fetchdat >> 8) & 0xff); + (*op_pc)++; + } else { + new_eaaddr = fastreadl(cs + (*op_pc) + 1); + addbyte(0x67); /*LEA EAX, base_reg+imm32*/ + addbyte(0x41); + addbyte(0x8d); + addbyte(0x80 | base_reg); + addlong(new_eaaddr); + (*op_pc) += 4; + } + addbyte(0x89); /*MOV eaaddr, EAX*/ + addbyte(0x45); + addbyte((uint8_t) cpu_state_offset(eaaddr)); + } else { + addbyte(0x44); /*MOV eaaddr, base_reg*/ + addbyte(0x89); + addbyte(0x45 | (base_reg << 3)); + addbyte((uint8_t) cpu_state_offset(eaaddr)); + } + } + return op_ea_seg; } -//#endif -void codegen_generate_call(uint8_t opcode, OpFn op, uint32_t fetchdat, uint32_t new_pc, uint32_t old_pc) +// #endif +void +codegen_generate_call(uint8_t opcode, OpFn op, uint32_t fetchdat, uint32_t new_pc, uint32_t old_pc) { - codeblock_t *block = &codeblock[block_current]; - uint32_t op_32 = use32; - uint32_t op_pc = new_pc; - const OpFn *op_table = (OpFn *) x86_dynarec_opcodes; - RecompOpFn *recomp_op_table = recomp_opcodes; - int opcode_shift = 0; - int opcode_mask = 0x3ff; - int over = 0; - int pc_off = 0; - int test_modrm = 1; - int c; - - op_ea_seg = &cpu_state.seg_ds; - op_ssegs = 0; - op_old_pc = old_pc; - - for (c = 0; c < NR_HOST_REGS; c++) - host_reg_mapping[c] = -1; - for (c = 0; c < NR_HOST_XMM_REGS; c++) - host_reg_xmm_mapping[c] = -1; - - codegen_timing_start(); + codeblock_t *block = &codeblock[block_current]; + uint32_t op_32 = use32; + uint32_t op_pc = new_pc; + const OpFn *op_table = (OpFn *) x86_dynarec_opcodes; + RecompOpFn *recomp_op_table = recomp_opcodes; + int opcode_shift = 0; + int opcode_mask = 0x3ff; + int over = 0; + int pc_off = 0; + int test_modrm = 1; + int c; - while (!over) - { - switch (opcode) - { - case 0x0f: - op_table = x86_dynarec_opcodes_0f; - recomp_op_table = recomp_opcodes_0f; - over = 1; - break; - - case 0x26: /*ES:*/ - op_ea_seg = &cpu_state.seg_es; - op_ssegs = 1; - break; - case 0x2e: /*CS:*/ - op_ea_seg = &cpu_state.seg_cs; - op_ssegs = 1; - break; - case 0x36: /*SS:*/ - op_ea_seg = &cpu_state.seg_ss; - op_ssegs = 1; - break; - case 0x3e: /*DS:*/ - op_ea_seg = &cpu_state.seg_ds; - op_ssegs = 1; - break; - case 0x64: /*FS:*/ - op_ea_seg = &cpu_state.seg_fs; - op_ssegs = 1; - break; - case 0x65: /*GS:*/ - op_ea_seg = &cpu_state.seg_gs; - op_ssegs = 1; - break; - - case 0x66: /*Data size select*/ - op_32 = ((use32 & 0x100) ^ 0x100) | (op_32 & 0x200); - break; - case 0x67: /*Address size select*/ - op_32 = ((use32 & 0x200) ^ 0x200) | (op_32 & 0x100); - break; - - case 0xd8: - op_table = (op_32 & 0x200) ? x86_dynarec_opcodes_d8_a32 : x86_dynarec_opcodes_d8_a16; - recomp_op_table = recomp_opcodes_d8; - opcode_shift = 3; - opcode_mask = 0x1f; - over = 1; - pc_off = -1; - test_modrm = 0; - block->flags |= CODEBLOCK_HAS_FPU; - break; - case 0xd9: - op_table = (op_32 & 0x200) ? x86_dynarec_opcodes_d9_a32 : x86_dynarec_opcodes_d9_a16; - recomp_op_table = recomp_opcodes_d9; - opcode_mask = 0xff; - over = 1; - pc_off = -1; - test_modrm = 0; - block->flags |= CODEBLOCK_HAS_FPU; - break; - case 0xda: - op_table = (op_32 & 0x200) ? x86_dynarec_opcodes_da_a32 : x86_dynarec_opcodes_da_a16; - recomp_op_table = recomp_opcodes_da; - opcode_mask = 0xff; - over = 1; - pc_off = -1; - test_modrm = 0; - block->flags |= CODEBLOCK_HAS_FPU; - break; - case 0xdb: - op_table = (op_32 & 0x200) ? x86_dynarec_opcodes_db_a32 : x86_dynarec_opcodes_db_a16; - recomp_op_table = recomp_opcodes_db; - opcode_mask = 0xff; - over = 1; - pc_off = -1; - test_modrm = 0; - block->flags |= CODEBLOCK_HAS_FPU; - break; - case 0xdc: - op_table = (op_32 & 0x200) ? x86_dynarec_opcodes_dc_a32 : x86_dynarec_opcodes_dc_a16; - recomp_op_table = recomp_opcodes_dc; - opcode_shift = 3; - opcode_mask = 0x1f; - over = 1; - pc_off = -1; - test_modrm = 0; - block->flags |= CODEBLOCK_HAS_FPU; - break; - case 0xdd: - op_table = (op_32 & 0x200) ? x86_dynarec_opcodes_dd_a32 : x86_dynarec_opcodes_dd_a16; - recomp_op_table = recomp_opcodes_dd; - opcode_mask = 0xff; - over = 1; - pc_off = -1; - test_modrm = 0; - block->flags |= CODEBLOCK_HAS_FPU; - break; - case 0xde: - op_table = (op_32 & 0x200) ? x86_dynarec_opcodes_de_a32 : x86_dynarec_opcodes_de_a16; - recomp_op_table = recomp_opcodes_de; - opcode_mask = 0xff; - over = 1; - pc_off = -1; - test_modrm = 0; - block->flags |= CODEBLOCK_HAS_FPU; - break; - case 0xdf: - op_table = (op_32 & 0x200) ? x86_dynarec_opcodes_df_a32 : x86_dynarec_opcodes_df_a16; - recomp_op_table = recomp_opcodes_df; - opcode_mask = 0xff; - over = 1; - pc_off = -1; - test_modrm = 0; - block->flags |= CODEBLOCK_HAS_FPU; - break; - - case 0xf0: /*LOCK*/ - break; + op_ea_seg = &cpu_state.seg_ds; + op_ssegs = 0; + op_old_pc = old_pc; - case 0xf2: /*REPNE*/ - op_table = x86_dynarec_opcodes_REPNE; - recomp_op_table = recomp_opcodes_REPNE; - break; - case 0xf3: /*REPE*/ - op_table = x86_dynarec_opcodes_REPE; - recomp_op_table = recomp_opcodes_REPE; - break; + for (c = 0; c < NR_HOST_REGS; c++) + host_reg_mapping[c] = -1; + for (c = 0; c < NR_HOST_XMM_REGS; c++) + host_reg_xmm_mapping[c] = -1; - default: - goto generate_call; - } - fetchdat = fastreadl(cs + op_pc); - codegen_timing_prefix(opcode, fetchdat); - if (cpu_state.abrt) - return; - opcode = fetchdat & 0xff; - if (!pc_off) - fetchdat >>= 8; - op_pc++; + codegen_timing_start(); + + while (!over) { + switch (opcode) { + case 0x0f: + op_table = x86_dynarec_opcodes_0f; + recomp_op_table = fpu_softfloat ? recomp_opcodes_0f_no_mmx : recomp_opcodes_0f; + over = 1; + break; + + case 0x26: /*ES:*/ + op_ea_seg = &cpu_state.seg_es; + op_ssegs = 1; + break; + case 0x2e: /*CS:*/ + op_ea_seg = &cpu_state.seg_cs; + op_ssegs = 1; + break; + case 0x36: /*SS:*/ + op_ea_seg = &cpu_state.seg_ss; + op_ssegs = 1; + break; + case 0x3e: /*DS:*/ + op_ea_seg = &cpu_state.seg_ds; + op_ssegs = 1; + break; + case 0x64: /*FS:*/ + op_ea_seg = &cpu_state.seg_fs; + op_ssegs = 1; + break; + case 0x65: /*GS:*/ + op_ea_seg = &cpu_state.seg_gs; + op_ssegs = 1; + break; + + case 0x66: /*Data size select*/ + op_32 = ((use32 & 0x100) ^ 0x100) | (op_32 & 0x200); + break; + case 0x67: /*Address size select*/ + op_32 = ((use32 & 0x200) ^ 0x200) | (op_32 & 0x100); + break; + + case 0xd8: + op_table = (op_32 & 0x200) ? x86_dynarec_opcodes_d8_a32 : x86_dynarec_opcodes_d8_a16; + recomp_op_table = fpu_softfloat ? NULL : recomp_opcodes_d8; + opcode_shift = 3; + opcode_mask = 0x1f; + over = 1; + pc_off = -1; + test_modrm = 0; + block->flags |= CODEBLOCK_HAS_FPU; + break; + case 0xd9: + op_table = (op_32 & 0x200) ? x86_dynarec_opcodes_d9_a32 : x86_dynarec_opcodes_d9_a16; + recomp_op_table = fpu_softfloat ? NULL : recomp_opcodes_d9; + opcode_mask = 0xff; + over = 1; + pc_off = -1; + test_modrm = 0; + block->flags |= CODEBLOCK_HAS_FPU; + break; + case 0xda: + op_table = (op_32 & 0x200) ? x86_dynarec_opcodes_da_a32 : x86_dynarec_opcodes_da_a16; + recomp_op_table = fpu_softfloat ? NULL : recomp_opcodes_da; + opcode_mask = 0xff; + over = 1; + pc_off = -1; + test_modrm = 0; + block->flags |= CODEBLOCK_HAS_FPU; + break; + case 0xdb: + op_table = (op_32 & 0x200) ? x86_dynarec_opcodes_db_a32 : x86_dynarec_opcodes_db_a16; + recomp_op_table = fpu_softfloat ? NULL : recomp_opcodes_db; + opcode_mask = 0xff; + over = 1; + pc_off = -1; + test_modrm = 0; + block->flags |= CODEBLOCK_HAS_FPU; + break; + case 0xdc: + op_table = (op_32 & 0x200) ? x86_dynarec_opcodes_dc_a32 : x86_dynarec_opcodes_dc_a16; + recomp_op_table = fpu_softfloat ? NULL : recomp_opcodes_dc; + opcode_shift = 3; + opcode_mask = 0x1f; + over = 1; + pc_off = -1; + test_modrm = 0; + block->flags |= CODEBLOCK_HAS_FPU; + break; + case 0xdd: + op_table = (op_32 & 0x200) ? x86_dynarec_opcodes_dd_a32 : x86_dynarec_opcodes_dd_a16; + recomp_op_table = fpu_softfloat ? NULL : recomp_opcodes_dd; + opcode_mask = 0xff; + over = 1; + pc_off = -1; + test_modrm = 0; + block->flags |= CODEBLOCK_HAS_FPU; + break; + case 0xde: + op_table = (op_32 & 0x200) ? x86_dynarec_opcodes_de_a32 : x86_dynarec_opcodes_de_a16; + recomp_op_table = fpu_softfloat ? NULL : recomp_opcodes_de; + opcode_mask = 0xff; + over = 1; + pc_off = -1; + test_modrm = 0; + block->flags |= CODEBLOCK_HAS_FPU; + break; + case 0xdf: + op_table = (op_32 & 0x200) ? x86_dynarec_opcodes_df_a32 : x86_dynarec_opcodes_df_a16; + recomp_op_table = fpu_softfloat ? NULL : recomp_opcodes_df; + opcode_mask = 0xff; + over = 1; + pc_off = -1; + test_modrm = 0; + block->flags |= CODEBLOCK_HAS_FPU; + break; + + case 0xf0: /*LOCK*/ + break; + + case 0xf2: /*REPNE*/ + op_table = x86_dynarec_opcodes_REPNE; + recomp_op_table = recomp_opcodes_REPNE; + break; + case 0xf3: /*REPE*/ + op_table = x86_dynarec_opcodes_REPE; + recomp_op_table = recomp_opcodes_REPE; + break; + + default: + goto generate_call; } - + fetchdat = fastreadl(cs + op_pc); + codegen_timing_prefix(opcode, fetchdat); + if (cpu_state.abrt) + return; + opcode = fetchdat & 0xff; + if (!pc_off) + fetchdat >>= 8; + op_pc++; + } + generate_call: - codegen_timing_opcode(opcode, fetchdat, op_32, op_pc); + codegen_timing_opcode(opcode, fetchdat, op_32, op_pc); - codegen_accumulate(ACCREG_cycles, -codegen_block_cycles); - codegen_block_cycles = 0; - - if ((op_table == x86_dynarec_opcodes && - ((opcode & 0xf0) == 0x70 || (opcode & 0xfc) == 0xe0 || opcode == 0xc2 || - (opcode & 0xfe) == 0xca || (opcode & 0xfc) == 0xcc || (opcode & 0xfc) == 0xe8 || - (opcode == 0xff && ((fetchdat & 0x38) >= 0x10 && (fetchdat & 0x38) < 0x30)))) || - (op_table == x86_dynarec_opcodes_0f && ((opcode & 0xf0) == 0x80))) - { - /*On some CPUs (eg K6), a jump/branch instruction may be able to pair with - subsequent instructions, so no cycles may have been deducted for it yet. - To prevent having zero cycle blocks (eg with a jump instruction pointing - to itself), apply the cycles that would be taken if this jump is taken, - then reverse it for subsequent instructions if the jump is not taken*/ - int jump_cycles = 0; + codegen_accumulate(ACCREG_cycles, -codegen_block_cycles); + codegen_block_cycles = 0; - if (codegen_timing_jump_cycles != NULL) - jump_cycles = codegen_timing_jump_cycles(); + if ((op_table == x86_dynarec_opcodes && ((opcode & 0xf0) == 0x70 || (opcode & 0xfc) == 0xe0 || opcode == 0xc2 || (opcode & 0xfe) == 0xca || (opcode & 0xfc) == 0xcc || (opcode & 0xfc) == 0xe8 || (opcode == 0xff && ((fetchdat & 0x38) >= 0x10 && (fetchdat & 0x38) < 0x30)))) || (op_table == x86_dynarec_opcodes_0f && ((opcode & 0xf0) == 0x80))) { + /*On some CPUs (eg K6), a jump/branch instruction may be able to pair with + subsequent instructions, so no cycles may have been deducted for it yet. + To prevent having zero cycle blocks (eg with a jump instruction pointing + to itself), apply the cycles that would be taken if this jump is taken, + then reverse it for subsequent instructions if the jump is not taken*/ + int jump_cycles = 0; - if (jump_cycles) - codegen_accumulate(ACCREG_cycles, -jump_cycles); - codegen_accumulate_flush(); - if (jump_cycles) - codegen_accumulate(ACCREG_cycles, jump_cycles); - } - - if ((op_table == x86_dynarec_opcodes_REPNE || op_table == x86_dynarec_opcodes_REPE) && !op_table[opcode | op_32]) - { - op_table = x86_dynarec_opcodes; - recomp_op_table = recomp_opcodes; - } - - if (recomp_op_table && recomp_op_table[(opcode | op_32) & 0x1ff]) - { - uint32_t new_pc = recomp_op_table[(opcode | op_32) & 0x1ff](opcode, fetchdat, op_32, op_pc, block); - if (new_pc) - { - if (new_pc != -1) - STORE_IMM_ADDR_L((uintptr_t)&cpu_state.pc, new_pc); - - codegen_block_ins++; - block->ins++; - codegen_block_full_ins++; - codegen_endpc = (cs + cpu_state.pc) + 8; - -#ifdef CHECK_INT - /* Check for interrupts. */ - addbyte(0xf6); /* test byte ptr[&pic_pending],1 */ - addbyte(0x04); - addbyte(0x25); - addlong((uint32_t) (uintptr_t) &pic_pending); - addbyte(0x01); - addbyte(0x0F); addbyte(0x85); /*JNZ 0*/ - addlong((uint32_t)(uintptr_t)&block->data[BLOCK_EXIT_OFFSET] - (uint32_t)(uintptr_t)(&block->data[block_pos + 4])); -#endif - - return; - } - } - - op = op_table[((opcode >> opcode_shift) | op_32) & opcode_mask]; - if (op_ssegs != last_ssegs) - { - last_ssegs = op_ssegs; - addbyte(0xC6); /*MOVB $0,(ssegs)*/ - addbyte(0x45); - addbyte((uint8_t)cpu_state_offset(ssegs)); - addbyte(op_ssegs); - } - if ((!test_modrm || - (op_table == x86_dynarec_opcodes && opcode_modrm[opcode]) || - (op_table == x86_dynarec_opcodes_0f && opcode_0f_modrm[opcode]))/* && !(op_32 & 0x200)*/) - { - int stack_offset = 0; - - if (op_table == x86_dynarec_opcodes && opcode == 0x8f) /*POP*/ - stack_offset = (op_32 & 0x100) ? 4 : 2; - - cpu_mod = (fetchdat >> 6) & 3; - cpu_reg = (fetchdat >> 3) & 7; - cpu_rm = fetchdat & 7; - - addbyte(0xC7); /*MOVL $rm | mod | reg,(rm_mod_reg_data)*/ - addbyte(0x45); - addbyte((uint8_t)cpu_state_offset(rm_data.rm_mod_reg_data)); - addlong(cpu_rm | (cpu_mod << 8) | (cpu_reg << 16)); - - op_pc += pc_off; - if (cpu_mod != 3 && !(op_32 & 0x200)) - op_ea_seg = codegen_generate_ea_16_long(op_ea_seg, fetchdat, op_ssegs, &op_pc); - if (cpu_mod != 3 && (op_32 & 0x200)) - op_ea_seg = codegen_generate_ea_32_long(op_ea_seg, fetchdat, op_ssegs, &op_pc, stack_offset); - op_pc -= pc_off; - } - if (op_ea_seg != last_ea_seg) - { - addbyte(0xC7); /*MOVL $&_ds,(ea_seg)*/ - addbyte(0x45); - addbyte((uint8_t)cpu_state_offset(ea_seg)); - addlong((uint32_t)(uintptr_t)op_ea_seg); - } + if (codegen_timing_jump_cycles != NULL) + jump_cycles = codegen_timing_jump_cycles(); + if (jump_cycles) + codegen_accumulate(ACCREG_cycles, -jump_cycles); codegen_accumulate_flush(); + if (jump_cycles) + codegen_accumulate(ACCREG_cycles, jump_cycles); + } - addbyte(0xC7); /*MOVL [pc],new_pc*/ - addbyte(0x45); - addbyte((uint8_t)cpu_state_offset(pc)); - addlong(op_pc + pc_off); - addbyte(0xC7); /*MOVL $old_pc,(oldpc)*/ - addbyte(0x45); - addbyte((uint8_t)cpu_state_offset(oldpc)); - addlong(old_pc); - if (op_32 != last_op32) - { - last_op32 = op_32; - addbyte(0xC7); /*MOVL $use32,(op32)*/ - addbyte(0x45); - addbyte((uint8_t)cpu_state_offset(op32)); - addlong(op_32); + if ((op_table == x86_dynarec_opcodes_REPNE || op_table == x86_dynarec_opcodes_REPE) && !op_table[opcode | op_32]) { + op_table = x86_dynarec_opcodes; + recomp_op_table = recomp_opcodes; + } + + if (recomp_op_table && recomp_op_table[(opcode | op_32) & 0x1ff]) { + uint32_t new_pc = recomp_op_table[(opcode | op_32) & 0x1ff](opcode, fetchdat, op_32, op_pc, block); + if (new_pc) { + if (new_pc != -1) + STORE_IMM_ADDR_L((uintptr_t) &cpu_state.pc, new_pc); + + codegen_block_ins++; + block->ins++; + codegen_block_full_ins++; + codegen_endpc = (cs + cpu_state.pc) + 8; + +# ifdef CHECK_INT + /* Check for interrupts. */ + addbyte(0xf6); /* test byte ptr[&pic_pending],1 */ + addbyte(0x04); + addbyte(0x25); + addlong((uint32_t) (uintptr_t) &pic_pending); + addbyte(0x01); + addbyte(0x0F); + addbyte(0x85); /*JNZ 0*/ + addlong((uint32_t) (uintptr_t) &block->data[BLOCK_EXIT_OFFSET] - (uint32_t) (uintptr_t) (&block->data[block_pos + 4])); +# endif + + return; } + } - load_param_1_32(block, fetchdat); - call(block, (uintptr_t)op); + op = op_table[((opcode >> opcode_shift) | op_32) & opcode_mask]; + if (op_ssegs != last_ssegs) { + last_ssegs = op_ssegs; + addbyte(0xC6); /*MOVB $0,(ssegs)*/ + addbyte(0x45); + addbyte((uint8_t) cpu_state_offset(ssegs)); + addbyte(op_ssegs); + } + if ((!test_modrm || (op_table == x86_dynarec_opcodes && opcode_modrm[opcode]) || (op_table == x86_dynarec_opcodes_0f && opcode_0f_modrm[opcode])) /* && !(op_32 & 0x200)*/) { + int stack_offset = 0; - codegen_block_ins++; - - block->ins++; + if (op_table == x86_dynarec_opcodes && opcode == 0x8f) /*POP*/ + stack_offset = (op_32 & 0x100) ? 4 : 2; -#ifdef CHECK_INT - /* Check for interrupts. */ - addbyte(0x0a); /* or al,byte ptr[&pic_pending] */ - addbyte(0x04); - addbyte(0x25); - addlong((uint32_t) (uintptr_t) &pic_pending); -#endif + cpu_mod = (fetchdat >> 6) & 3; + cpu_reg = (fetchdat >> 3) & 7; + cpu_rm = fetchdat & 7; - addbyte(0x85); /*OR %eax, %eax*/ - addbyte(0xc0); - addbyte(0x0F); addbyte(0x85); /*JNZ 0*/ - addlong((uint32_t)(uintptr_t)&block->data[BLOCK_EXIT_OFFSET] - (uint32_t)(uintptr_t)(&block->data[block_pos + 4])); + addbyte(0xC7); /*MOVL $rm | mod | reg,(rm_mod_reg_data)*/ + addbyte(0x45); + addbyte((uint8_t) cpu_state_offset(rm_data.rm_mod_reg_data)); + addlong(cpu_rm | (cpu_mod << 8) | (cpu_reg << 16)); - codegen_endpc = (cs + cpu_state.pc) + 8; + op_pc += pc_off; + if (cpu_mod != 3 && !(op_32 & 0x200)) + op_ea_seg = codegen_generate_ea_16_long(op_ea_seg, fetchdat, op_ssegs, &op_pc); + if (cpu_mod != 3 && (op_32 & 0x200)) + op_ea_seg = codegen_generate_ea_32_long(op_ea_seg, fetchdat, op_ssegs, &op_pc, stack_offset); + op_pc -= pc_off; + } + if (op_ea_seg != last_ea_seg) { + addbyte(0xC7); /*MOVL $&_ds,(ea_seg)*/ + addbyte(0x45); + addbyte((uint8_t) cpu_state_offset(ea_seg)); + addlong((uint32_t) (uintptr_t) op_ea_seg); + } + + codegen_accumulate_flush(); + + addbyte(0xC7); /*MOVL [pc],new_pc*/ + addbyte(0x45); + addbyte((uint8_t) cpu_state_offset(pc)); + addlong(op_pc + pc_off); + addbyte(0xC7); /*MOVL $old_pc,(oldpc)*/ + addbyte(0x45); + addbyte((uint8_t) cpu_state_offset(oldpc)); + addlong(old_pc); + if (op_32 != last_op32) { + last_op32 = op_32; + addbyte(0xC7); /*MOVL $use32,(op32)*/ + addbyte(0x45); + addbyte((uint8_t) cpu_state_offset(op32)); + addlong(op_32); + } + + load_param_1_32(block, fetchdat); + call(block, (uintptr_t) op); + + codegen_block_ins++; + + block->ins++; + +# ifdef CHECK_INT + /* Check for interrupts. */ + addbyte(0x0a); /* or al,byte ptr[&pic_pending] */ + addbyte(0x04); + addbyte(0x25); + addlong((uint32_t) (uintptr_t) &pic_pending); +# endif + + addbyte(0x85); /*OR %eax, %eax*/ + addbyte(0xc0); + addbyte(0x0F); + addbyte(0x85); /*JNZ 0*/ + addlong((uint32_t) (uintptr_t) &block->data[BLOCK_EXIT_OFFSET] - (uint32_t) (uintptr_t) (&block->data[block_pos + 4])); + + codegen_endpc = (cs + cpu_state.pc) + 8; } #endif diff --git a/src/codegen/codegen_x86-64.h b/src/codegen/codegen_x86-64.h index 529be99ae..91c10a9ee 100644 --- a/src/codegen/codegen_x86-64.h +++ b/src/codegen/codegen_x86-64.h @@ -1,24 +1,23 @@ -#define BLOCK_SIZE 0x4000 -#define BLOCK_MASK 0x3fff -#define BLOCK_START 0 +#define BLOCK_SIZE 0x4000 +#define BLOCK_MASK 0x3fff +#define BLOCK_START 0 -#define HASH_SIZE 0x20000 -#define HASH_MASK 0x1ffff +#define HASH_SIZE 0x20000 +#define HASH_MASK 0x1ffff -#define HASH(l) ((l) & 0x1ffff) +#define HASH(l) ((l) &0x1ffff) #define BLOCK_EXIT_OFFSET 0x7e0 #ifdef OLD_GPF -#define BLOCK_GPF_OFFSET (BLOCK_EXIT_OFFSET - 20) +# define BLOCK_GPF_OFFSET (BLOCK_EXIT_OFFSET - 20) #else -#define BLOCK_GPF_OFFSET (BLOCK_EXIT_OFFSET - 15) +# define BLOCK_GPF_OFFSET (BLOCK_EXIT_OFFSET - 12) #endif #define BLOCK_MAX 1620 -enum -{ - OP_RET = 0xc3 +enum { + OP_RET = 0xc3 }; #define NR_HOST_REGS 4 diff --git a/src/codegen/codegen_x86.c b/src/codegen/codegen_x86.c index b4ba9bc9f..456f93ae9 100644 --- a/src/codegen/codegen_x86.c +++ b/src/codegen/codegen_x86.c @@ -1,22 +1,22 @@ /* - * VARCem Virtual ARchaeological Computer EMulator. - * An emulator of (mostly) x86-based PC systems and devices, - * using the ISA,EISA,VLB,MCA and PCI system buses, roughly - * spanning the era between 1981 and 1995. + * 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 VARCem Project. + * This file is part of the 86Box distribution. * - * Dynamic Recompiler for Intel 32-bit systems. + * Dynamic Recompiler for Intel 32-bit systems. * * * - * Authors: Fred N. van Kempen, - * Sarah Walker, - * Miran Grca, + * Authors: Fred N. van Kempen, + * Sarah Walker, + * Miran Grca, * - * Copyright 2018 Fred N. van Kempen. - * Copyright 2008-2018 Sarah Walker. - * Copyright 2016-2018 Miran Grca. + * Copyright 2018 Fred N. van Kempen. + * Copyright 2008-2018 Sarah Walker. + * Copyright 2016-2018 Miran Grca. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -38,2139 +38,2134 @@ */ #if defined i386 || defined __i386 || defined __i386__ || defined _X86_ || defined _M_IX86 -#include -#include -#include -#include -#include -#include <86box/86box.h> -#include "cpu.h" -#include <86box/mem.h> -#include "x86.h" -#include "x86_flags.h" -#include "x86_ops.h" -#include "x87.h" +# include +# include +# include +# include +# include +# include <86box/86box.h> +# include "cpu.h" +# include <86box/mem.h> +# include "x86.h" +# include "x86_flags.h" +# include "x86_ops.h" +# include "x86seg_common.h" +# include "x86seg.h" +# include "x87.h" /*ex*/ -#include <86box/nmi.h> -#include <86box/pic.h> +# include <86box/nmi.h> +# include <86box/pic.h> -#include "386_common.h" +# include "386_common.h" -#include "codegen.h" -#include "codegen_accumulate.h" -#include "codegen_ops.h" -#include "codegen_ops_x86.h" +# include "codegen.h" +# include "codegen_accumulate.h" +# include "codegen_ops.h" +# include "codegen_ops_x86.h" -#ifdef __unix__ -#include -#include -#endif -#if defined _WIN32 -#include -#endif +# ifdef __unix__ +# include +# include +# endif +# if defined _WIN32 +# include +# endif -int codegen_flat_ds, codegen_flat_ss; -int mmx_ebx_ecx_loaded; -int codegen_flags_changed = 0; -int codegen_fpu_entered = 0; -int codegen_mmx_entered = 0; -int codegen_fpu_loaded_iq[8]; -x86seg *op_ea_seg; -int op_ssegs; +int codegen_flat_ds; +int codegen_flat_ss; +int mmx_ebx_ecx_loaded; +int codegen_flags_changed = 0; +int codegen_fpu_entered = 0; +int codegen_mmx_entered = 0; +int codegen_fpu_loaded_iq[8]; +x86seg *op_ea_seg; +int op_ssegs; uint32_t op_old_pc; uint32_t recomp_page = -1; -int host_reg_mapping[NR_HOST_REGS]; -int host_reg_xmm_mapping[NR_HOST_XMM_REGS]; -codeblock_t *codeblock; +int host_reg_mapping[NR_HOST_REGS]; +int host_reg_xmm_mapping[NR_HOST_XMM_REGS]; +codeblock_t *codeblock; codeblock_t **codeblock_hash; - -int block_current = 0; +int block_current = 0; static int block_num; -int block_pos; +int block_pos; uint32_t codegen_endpc; -int codegen_block_cycles; +int codegen_block_cycles; static int codegen_block_ins; static int codegen_block_full_ins; static uint32_t last_op32; -static x86seg *last_ea_seg; -static int last_ssegs; +static x86seg *last_ea_seg; +static int last_ssegs; static uint32_t mem_abrt_rout; -uint32_t mem_load_addr_ea_b; -uint32_t mem_load_addr_ea_w; -uint32_t mem_load_addr_ea_l; -uint32_t mem_load_addr_ea_q; -uint32_t mem_store_addr_ea_b; -uint32_t mem_store_addr_ea_w; -uint32_t mem_store_addr_ea_l; -uint32_t mem_store_addr_ea_q; -uint32_t mem_load_addr_ea_b_no_abrt; -uint32_t mem_store_addr_ea_b_no_abrt; -uint32_t mem_load_addr_ea_w_no_abrt; -uint32_t mem_store_addr_ea_w_no_abrt; -uint32_t mem_load_addr_ea_l_no_abrt; -uint32_t mem_store_addr_ea_l_no_abrt; -uint32_t mem_check_write; -uint32_t mem_check_write_w; -uint32_t mem_check_write_l; +uint32_t mem_load_addr_ea_b; +uint32_t mem_load_addr_ea_w; +uint32_t mem_load_addr_ea_l; +uint32_t mem_load_addr_ea_q; +uint32_t mem_store_addr_ea_b; +uint32_t mem_store_addr_ea_w; +uint32_t mem_store_addr_ea_l; +uint32_t mem_store_addr_ea_q; +uint32_t mem_load_addr_ea_b_no_abrt; +uint32_t mem_store_addr_ea_b_no_abrt; +uint32_t mem_load_addr_ea_w_no_abrt; +uint32_t mem_store_addr_ea_w_no_abrt; +uint32_t mem_load_addr_ea_l_no_abrt; +uint32_t mem_store_addr_ea_l_no_abrt; +uint32_t mem_check_write; +uint32_t mem_check_write_w; +uint32_t mem_check_write_l; -static uint32_t gen_MEM_LOAD_ADDR_EA_B() +static uint32_t +gen_MEM_LOAD_ADDR_EA_B(void) { - uint32_t addr = (uint32_t)&codeblock[block_current].data[block_pos]; + uint32_t addr = (uint32_t) &codeblock[block_current].data[block_pos]; - addbyte(0x89); /*MOV ESI, EDX*/ - addbyte(0xd6); - addbyte(0x01); /*ADDL EDX, EAX*/ - addbyte(0xc2); - addbyte(0x89); /*MOV EDI, EDX*/ - addbyte(0xd7); - addbyte(0xc1); /*SHR EDX, 12*/ - addbyte(0xea); - addbyte(12); - addbyte(0x8b); /*MOV EDX, readlookup2[EDX*4]*/ - addbyte(0x14); - addbyte(0x95); - addlong((uint32_t)readlookup2); - addbyte(0x83); /*CMP EDX, -1*/ - addbyte(0xfa); - addbyte(-1); - addbyte(0x74); /*JE slowpath*/ - addbyte(4+1); - addbyte(0x0f); /*MOVZX EAX, B[EDX+EDI]*/ - addbyte(0xb6); - addbyte(0x04); - addbyte(0x3a); - addbyte(0xc3); /*RET*/ + addbyte(0x89); /*MOV ESI, EDX*/ + addbyte(0xd6); + addbyte(0x01); /*ADDL EDX, EAX*/ + addbyte(0xc2); + addbyte(0x89); /*MOV EDI, EDX*/ + addbyte(0xd7); + addbyte(0xc1); /*SHR EDX, 12*/ + addbyte(0xea); + addbyte(12); + addbyte(0x8b); /*MOV EDX, readlookup2[EDX*4]*/ + addbyte(0x14); + addbyte(0x95); + addlong((uint32_t) readlookup2); + addbyte(0x83); /*CMP EDX, -1*/ + addbyte(0xfa); + addbyte(-1); + addbyte(0x74); /*JE slowpath*/ + addbyte(4 + 1); + addbyte(0x0f); /*MOVZX EAX, B[EDX+EDI]*/ + addbyte(0xb6); + addbyte(0x04); + addbyte(0x3a); + addbyte(0xc3); /*RET*/ - addbyte(0x01); /*slowpath: ADD ESI,EAX*/ - addbyte(0xc6); - addbyte(0x56); /*PUSH ESI*/ - addbyte(0xe8); /*CALL readmembl*/ - addlong((uint32_t)readmembl - (uint32_t)(&codeblock[block_current].data[block_pos + 4])); - addbyte(0x83); /*ADD ESP, 4*/ - addbyte(0xc4); - addbyte(4); - addbyte(0x80); /*CMP abrt, 0*/ - addbyte(0x7d); - addbyte((uint8_t)cpu_state_offset(abrt)); - addbyte(0); - addbyte(0x0f); /*MOVZX EAX, AL*/ - addbyte(0xb6); - addbyte(0xc0); - addbyte(0x0f); /*JNE mem_abrt_rout*/ - addbyte(0x85); - addlong(mem_abrt_rout - ((uint32_t)(&codeblock[block_current].data[block_pos]) + 4)); - addbyte(0xc3); /*RET*/ - - return addr; + addbyte(0x01); /*slowpath: ADD ESI,EAX*/ + addbyte(0xc6); + addbyte(0x56); /*PUSH ESI*/ + addbyte(0xe8); /*CALL readmembl*/ + addlong((uint32_t) readmembl - (uint32_t) (&codeblock[block_current].data[block_pos + 4])); + addbyte(0x83); /*ADD ESP, 4*/ + addbyte(0xc4); + addbyte(4); + addbyte(0x80); /*CMP abrt, 0*/ + addbyte(0x7d); + addbyte((uint8_t) cpu_state_offset(abrt)); + addbyte(0); + addbyte(0x0f); /*MOVZX EAX, AL*/ + addbyte(0xb6); + addbyte(0xc0); + addbyte(0x0f); /*JNE mem_abrt_rout*/ + addbyte(0x85); + addlong(mem_abrt_rout - ((uint32_t) (&codeblock[block_current].data[block_pos]) + 4)); + addbyte(0xc3); /*RET*/ + + return addr; } -static uint32_t gen_MEM_LOAD_ADDR_EA_W() +static uint32_t +gen_MEM_LOAD_ADDR_EA_W(void) { - uint32_t addr = (uint32_t)&codeblock[block_current].data[block_pos]; + uint32_t addr = (uint32_t) &codeblock[block_current].data[block_pos]; - addbyte(0x89); /*MOV ESI, EDX*/ - addbyte(0xd6); - addbyte(0x01); /*ADDL EDX, EAX*/ - addbyte(0xc2); - addbyte(0x89); /*MOV EDI, EDX*/ - addbyte(0xd7); - addbyte(0xc1); /*SHR EDX, 12*/ - addbyte(0xea); - addbyte(12); - addbyte(0xf7); /*TEST EDI, 1*/ - addbyte(0xc7); - addlong(1); - addbyte(0x8b); /*MOV EDX, readlookup2[EDX*4]*/ - addbyte(0x14); - addbyte(0x95); - addlong((uint32_t)readlookup2); - addbyte(0x75); /*JNE slowpath*/ - addbyte(3+2+4+1); - addbyte(0x83); /*CMP EDX, -1*/ - addbyte(0xfa); - addbyte(-1); - addbyte(0x74); /*JE slowpath*/ - addbyte(4+1); - addbyte(0x0f); /*MOVZX EAX, [EDX+EDI]W*/ - addbyte(0xb7); - addbyte(0x04); - addbyte(0x3a); - addbyte(0xc3); /*RET*/ + addbyte(0x89); /*MOV ESI, EDX*/ + addbyte(0xd6); + addbyte(0x01); /*ADDL EDX, EAX*/ + addbyte(0xc2); + addbyte(0x89); /*MOV EDI, EDX*/ + addbyte(0xd7); + addbyte(0xc1); /*SHR EDX, 12*/ + addbyte(0xea); + addbyte(12); + addbyte(0xf7); /*TEST EDI, 1*/ + addbyte(0xc7); + addlong(1); + addbyte(0x8b); /*MOV EDX, readlookup2[EDX*4]*/ + addbyte(0x14); + addbyte(0x95); + addlong((uint32_t) readlookup2); + addbyte(0x75); /*JNE slowpath*/ + addbyte(3 + 2 + 4 + 1); + addbyte(0x83); /*CMP EDX, -1*/ + addbyte(0xfa); + addbyte(-1); + addbyte(0x74); /*JE slowpath*/ + addbyte(4 + 1); + addbyte(0x0f); /*MOVZX EAX, [EDX+EDI]W*/ + addbyte(0xb7); + addbyte(0x04); + addbyte(0x3a); + addbyte(0xc3); /*RET*/ - addbyte(0x01); /*slowpath: ADD ESI,EAX*/ - addbyte(0xc6); - addbyte(0x56); /*PUSH ESI*/ - addbyte(0xe8); /*CALL readmemwl*/ - addlong((uint32_t)readmemwl - (uint32_t)(&codeblock[block_current].data[block_pos + 4])); - addbyte(0x83); /*ADD ESP, 4*/ - addbyte(0xc4); - addbyte(4); - addbyte(0x80); /*CMP abrt, 0*/ - addbyte(0x7d); - addbyte((uint8_t)cpu_state_offset(abrt)); - addbyte(0); - addbyte(0x0f); /*MOVZX EAX, AX*/ - addbyte(0xb7); - addbyte(0xc0); - addbyte(0x0f); /*JNE mem_abrt_rout*/ - addbyte(0x85); - addlong(mem_abrt_rout - ((uint32_t)(&codeblock[block_current].data[block_pos]) + 4)); - addbyte(0xc3); /*RET*/ - - return addr; + addbyte(0x01); /*slowpath: ADD ESI,EAX*/ + addbyte(0xc6); + addbyte(0x56); /*PUSH ESI*/ + addbyte(0xe8); /*CALL readmemwl*/ + addlong((uint32_t) readmemwl - (uint32_t) (&codeblock[block_current].data[block_pos + 4])); + addbyte(0x83); /*ADD ESP, 4*/ + addbyte(0xc4); + addbyte(4); + addbyte(0x80); /*CMP abrt, 0*/ + addbyte(0x7d); + addbyte((uint8_t) cpu_state_offset(abrt)); + addbyte(0); + addbyte(0x0f); /*MOVZX EAX, AX*/ + addbyte(0xb7); + addbyte(0xc0); + addbyte(0x0f); /*JNE mem_abrt_rout*/ + addbyte(0x85); + addlong(mem_abrt_rout - ((uint32_t) (&codeblock[block_current].data[block_pos]) + 4)); + addbyte(0xc3); /*RET*/ + + return addr; } -static uint32_t gen_MEM_LOAD_ADDR_EA_L() +static uint32_t +gen_MEM_LOAD_ADDR_EA_L(void) { - uint32_t addr = (uint32_t)&codeblock[block_current].data[block_pos]; + uint32_t addr = (uint32_t) &codeblock[block_current].data[block_pos]; - addbyte(0x89); /*MOV ESI, EDX*/ - addbyte(0xd6); - addbyte(0x01); /*ADDL EDX, EAX*/ - addbyte(0xc2); - addbyte(0x89); /*MOV EDI, EDX*/ - addbyte(0xd7); - addbyte(0xc1); /*SHR EDX, 12*/ - addbyte(0xea); - addbyte(12); - addbyte(0xf7); /*TEST EDI, 3*/ - addbyte(0xc7); - addlong(3); - addbyte(0x8b); /*MOV EDX, readlookup2[EDX*4]*/ - addbyte(0x14); - addbyte(0x95); - addlong((uint32_t)readlookup2); - addbyte(0x75); /*JNE slowpath*/ - addbyte(3+2+3+1); - addbyte(0x83); /*CMP EDX, -1*/ - addbyte(0xfa); - addbyte(-1); - addbyte(0x74); /*JE slowpath*/ - addbyte(3+1); - addbyte(0x8b); /*MOV EAX, [EDX+EDI]*/ - addbyte(0x04); - addbyte(0x3a); - addbyte(0xc3); /*RET*/ + addbyte(0x89); /*MOV ESI, EDX*/ + addbyte(0xd6); + addbyte(0x01); /*ADDL EDX, EAX*/ + addbyte(0xc2); + addbyte(0x89); /*MOV EDI, EDX*/ + addbyte(0xd7); + addbyte(0xc1); /*SHR EDX, 12*/ + addbyte(0xea); + addbyte(12); + addbyte(0xf7); /*TEST EDI, 3*/ + addbyte(0xc7); + addlong(3); + addbyte(0x8b); /*MOV EDX, readlookup2[EDX*4]*/ + addbyte(0x14); + addbyte(0x95); + addlong((uint32_t) readlookup2); + addbyte(0x75); /*JNE slowpath*/ + addbyte(3 + 2 + 3 + 1); + addbyte(0x83); /*CMP EDX, -1*/ + addbyte(0xfa); + addbyte(-1); + addbyte(0x74); /*JE slowpath*/ + addbyte(3 + 1); + addbyte(0x8b); /*MOV EAX, [EDX+EDI]*/ + addbyte(0x04); + addbyte(0x3a); + addbyte(0xc3); /*RET*/ - addbyte(0x01); /*slowpath: ADD ESI,EAX*/ - addbyte(0xc6); - addbyte(0x56); /*PUSH ESI*/ - addbyte(0xe8); /*CALL readmemll*/ - addlong((uint32_t)readmemll - (uint32_t)(&codeblock[block_current].data[block_pos + 4])); - addbyte(0x83); /*ADD ESP, 4*/ - addbyte(0xc4); - addbyte(4); - addbyte(0x80); /*CMP abrt, 0*/ - addbyte(0x7d); - addbyte((uint8_t)cpu_state_offset(abrt)); - addbyte(0); - addbyte(0x0f); /*JNE mem_abrt_rout*/ - addbyte(0x85); - addlong(mem_abrt_rout - ((uint32_t)(&codeblock[block_current].data[block_pos]) + 4)); - addbyte(0xc3); /*RET*/ - - return addr; + addbyte(0x01); /*slowpath: ADD ESI,EAX*/ + addbyte(0xc6); + addbyte(0x56); /*PUSH ESI*/ + addbyte(0xe8); /*CALL readmemll*/ + addlong((uint32_t) readmemll - (uint32_t) (&codeblock[block_current].data[block_pos + 4])); + addbyte(0x83); /*ADD ESP, 4*/ + addbyte(0xc4); + addbyte(4); + addbyte(0x80); /*CMP abrt, 0*/ + addbyte(0x7d); + addbyte((uint8_t) cpu_state_offset(abrt)); + addbyte(0); + addbyte(0x0f); /*JNE mem_abrt_rout*/ + addbyte(0x85); + addlong(mem_abrt_rout - ((uint32_t) (&codeblock[block_current].data[block_pos]) + 4)); + addbyte(0xc3); /*RET*/ + + return addr; } -static uint32_t gen_MEM_LOAD_ADDR_EA_Q() +static uint32_t +gen_MEM_LOAD_ADDR_EA_Q(void) { - uint32_t addr = (uint32_t)&codeblock[block_current].data[block_pos]; - - addbyte(0x89); /*MOV ESI, EDX*/ - addbyte(0xd6); - addbyte(0x01); /*ADDL EDX, EAX*/ - addbyte(0xc2); - addbyte(0x89); /*MOV EDI, EDX*/ - addbyte(0xd7); - addbyte(0xc1); /*SHR EDX, 12*/ - addbyte(0xea); - addbyte(12); - addbyte(0xf7); /*TEST EDI, 7*/ - addbyte(0xc7); - addlong(7); - addbyte(0x8b); /*MOV EDX, readlookup2[EDX*4]*/ - addbyte(0x14); - addbyte(0x95); - addlong((uint32_t)readlookup2); - addbyte(0x75); /*JNE slowpath*/ - addbyte(3+2+3+4+1); - addbyte(0x83); /*CMP EDX, -1*/ - addbyte(0xfa); - addbyte(-1); - addbyte(0x74); /*JE slowpath*/ - addbyte(3+4+1); - addbyte(0x8b); /*MOV EAX, [EDX+EDI]*/ - addbyte(0x04); - addbyte(0x3a); - addbyte(0x8b); /*MOV EDX, [EDX+EDI+4]*/ - addbyte(0x54); - addbyte(0x3a); - addbyte(4); - addbyte(0xc3); /*RET*/ + uint32_t addr = (uint32_t) &codeblock[block_current].data[block_pos]; - addbyte(0x01); /*slowpath: ADD ESI,EAX*/ - addbyte(0xc6); - addbyte(0x56); /*PUSH ESI*/ - addbyte(0xe8); /*CALL readmemql*/ - addlong((uint32_t)readmemql - (uint32_t)(&codeblock[block_current].data[block_pos + 4])); - addbyte(0x83); /*ADD ESP, 4*/ - addbyte(0xc4); - addbyte(4); - addbyte(0x80); /*CMP abrt, 0*/ - addbyte(0x7d); - addbyte((uint8_t)cpu_state_offset(abrt)); - addbyte(0); - addbyte(0x0f); /*JNE mem_abrt_rout*/ - addbyte(0x85); - addlong(mem_abrt_rout - ((uint32_t)(&codeblock[block_current].data[block_pos]) + 4)); - addbyte(0xc3); /*RET*/ - - return addr; + addbyte(0x89); /*MOV ESI, EDX*/ + addbyte(0xd6); + addbyte(0x01); /*ADDL EDX, EAX*/ + addbyte(0xc2); + addbyte(0x89); /*MOV EDI, EDX*/ + addbyte(0xd7); + addbyte(0xc1); /*SHR EDX, 12*/ + addbyte(0xea); + addbyte(12); + addbyte(0xf7); /*TEST EDI, 7*/ + addbyte(0xc7); + addlong(7); + addbyte(0x8b); /*MOV EDX, readlookup2[EDX*4]*/ + addbyte(0x14); + addbyte(0x95); + addlong((uint32_t) readlookup2); + addbyte(0x75); /*JNE slowpath*/ + addbyte(3 + 2 + 3 + 4 + 1); + addbyte(0x83); /*CMP EDX, -1*/ + addbyte(0xfa); + addbyte(-1); + addbyte(0x74); /*JE slowpath*/ + addbyte(3 + 4 + 1); + addbyte(0x8b); /*MOV EAX, [EDX+EDI]*/ + addbyte(0x04); + addbyte(0x3a); + addbyte(0x8b); /*MOV EDX, [EDX+EDI+4]*/ + addbyte(0x54); + addbyte(0x3a); + addbyte(4); + addbyte(0xc3); /*RET*/ + + addbyte(0x01); /*slowpath: ADD ESI,EAX*/ + addbyte(0xc6); + addbyte(0x56); /*PUSH ESI*/ + addbyte(0xe8); /*CALL readmemql*/ + addlong((uint32_t) readmemql - (uint32_t) (&codeblock[block_current].data[block_pos + 4])); + addbyte(0x83); /*ADD ESP, 4*/ + addbyte(0xc4); + addbyte(4); + addbyte(0x80); /*CMP abrt, 0*/ + addbyte(0x7d); + addbyte((uint8_t) cpu_state_offset(abrt)); + addbyte(0); + addbyte(0x0f); /*JNE mem_abrt_rout*/ + addbyte(0x85); + addlong(mem_abrt_rout - ((uint32_t) (&codeblock[block_current].data[block_pos]) + 4)); + addbyte(0xc3); /*RET*/ + + return addr; } -static uint32_t gen_MEM_STORE_ADDR_EA_B() +static uint32_t +gen_MEM_STORE_ADDR_EA_B(void) { - uint32_t addr = (uint32_t)&codeblock[block_current].data[block_pos]; - - /*dat = ECX, seg = ESI, addr = EAX*/ - addbyte(0x89); /*MOV EBX, ESI*/ - addbyte(0xf3); - addbyte(0x01); /*ADDL ESI, EAX*/ - addbyte(0xc0 | (REG_EAX << 3) | REG_ESI); - addbyte(0x89); /*MOV EDI, ESI*/ - addbyte(0xc0 | (REG_ESI << 3) | REG_EDI); - addbyte(0xc1); /*SHR ESI, 12*/ - addbyte(0xe8 | REG_ESI); - addbyte(12); - addbyte(0x8b); /*MOV ESI, readlookup2[ESI*4]*/ - addbyte(0x04 | (REG_ESI << 3)); - addbyte(0x85 | (REG_ESI << 3)); - addlong((uint32_t)writelookup2); - addbyte(0x83); /*CMP ESI, -1*/ - addbyte(0xf8 | REG_ESI); - addbyte(-1); - addbyte(0x74); /*JE slowpath*/ - addbyte(3+1); - addbyte(0x88); /*MOV [EDI+ESI],CL*/ - addbyte(0x04 | (REG_ECX << 3)); - addbyte(REG_EDI | (REG_ESI << 3)); - addbyte(0xc3); /*RET*/ + uint32_t addr = (uint32_t) &codeblock[block_current].data[block_pos]; - addbyte(0x51); /*slowpath: PUSH ECX*/ - addbyte(0x01); /*ADD EBX,EAX*/ - addbyte(0xC3); - addbyte(0x53); /*PUSH EBX*/ - addbyte(0xe8); /*CALL writemembl*/ - addlong((uint32_t)writemembl - (uint32_t)(&codeblock[block_current].data[block_pos + 4])); - addbyte(0x83); /*ADD ESP, 8*/ - addbyte(0xc4); - addbyte(8); - addbyte(0x80); /*CMP abrt, 0*/ - addbyte(0x7d); - addbyte((uint8_t)cpu_state_offset(abrt)); - addbyte(0); - addbyte(0x0f); /*JNE mem_abrt_rout*/ - addbyte(0x85); - addlong(mem_abrt_rout - ((uint32_t)(&codeblock[block_current].data[block_pos]) + 4)); - addbyte(0xc3); /*RET*/ + /*dat = ECX, seg = ESI, addr = EAX*/ + addbyte(0x89); /*MOV EBX, ESI*/ + addbyte(0xf3); + addbyte(0x01); /*ADDL ESI, EAX*/ + addbyte(0xc0 | (REG_EAX << 3) | REG_ESI); + addbyte(0x89); /*MOV EDI, ESI*/ + addbyte(0xc0 | (REG_ESI << 3) | REG_EDI); + addbyte(0xc1); /*SHR ESI, 12*/ + addbyte(0xe8 | REG_ESI); + addbyte(12); + addbyte(0x8b); /*MOV ESI, readlookup2[ESI*4]*/ + addbyte(0x04 | (REG_ESI << 3)); + addbyte(0x85 | (REG_ESI << 3)); + addlong((uint32_t) writelookup2); + addbyte(0x83); /*CMP ESI, -1*/ + addbyte(0xf8 | REG_ESI); + addbyte(-1); + addbyte(0x74); /*JE slowpath*/ + addbyte(3 + 1); + addbyte(0x88); /*MOV [EDI+ESI],CL*/ + addbyte(0x04 | (REG_ECX << 3)); + addbyte(REG_EDI | (REG_ESI << 3)); + addbyte(0xc3); /*RET*/ - return addr; + addbyte(0x51); /*slowpath: PUSH ECX*/ + addbyte(0x01); /*ADD EBX,EAX*/ + addbyte(0xC3); + addbyte(0x53); /*PUSH EBX*/ + addbyte(0xe8); /*CALL writemembl*/ + addlong((uint32_t) writemembl - (uint32_t) (&codeblock[block_current].data[block_pos + 4])); + addbyte(0x83); /*ADD ESP, 8*/ + addbyte(0xc4); + addbyte(8); + addbyte(0x80); /*CMP abrt, 0*/ + addbyte(0x7d); + addbyte((uint8_t) cpu_state_offset(abrt)); + addbyte(0); + addbyte(0x0f); /*JNE mem_abrt_rout*/ + addbyte(0x85); + addlong(mem_abrt_rout - ((uint32_t) (&codeblock[block_current].data[block_pos]) + 4)); + addbyte(0xc3); /*RET*/ + + return addr; } -static uint32_t gen_MEM_STORE_ADDR_EA_W() +static uint32_t +gen_MEM_STORE_ADDR_EA_W(void) { - uint32_t addr = (uint32_t)&codeblock[block_current].data[block_pos]; - - /*dat = ECX, seg = ESI, addr = EAX*/ - addbyte(0x89); /*MOV EBX, ESI*/ - addbyte(0xf3); - addbyte(0x01); /*ADDL ESI, EAX*/ - addbyte(0xc0 | (REG_EAX << 3) | REG_ESI); - addbyte(0x89); /*MOV EDI, ESI*/ - addbyte(0xf7); - addbyte(0xc1); /*SHR ESI, 12*/ - addbyte(0xe8 | REG_ESI); - addbyte(12); - addbyte(0xf7); /*TEST EDI, 1*/ - addbyte(0xc7); - addlong(1); - addbyte(0x8b); /*MOV ESI, readlookup2[ESI*4]*/ - addbyte(0x04 | (REG_ESI << 3)); - addbyte(0x85 | (REG_ESI << 3)); - addlong((uint32_t)writelookup2); - addbyte(0x75); /*JNE slowpath*/ - addbyte(3+2+4+1); - addbyte(0x83); /*CMP ESI, -1*/ - addbyte(0xf8 | REG_ESI); - addbyte(-1); - addbyte(0x74); /*JE slowpath*/ - addbyte(4+1); - addbyte(0x66); /*MOV [EDI+ESI],CX*/ - addbyte(0x89); - addbyte(0x04 | (REG_CX << 3)); - addbyte(REG_EDI | (REG_ESI << 3)); - addbyte(0xc3); /*RET*/ + uint32_t addr = (uint32_t) &codeblock[block_current].data[block_pos]; - addbyte(0x51); /*slowpath: PUSH ECX*/ - addbyte(0x01); /*ADD EBX,EAX*/ - addbyte(0xC3); - addbyte(0x53); /*PUSH EBX*/ - addbyte(0xe8); /*CALL writememwl*/ - addlong((uint32_t)writememwl - (uint32_t)(&codeblock[block_current].data[block_pos + 4])); - addbyte(0x83); /*ADD ESP, 8*/ - addbyte(0xc4); - addbyte(8); - addbyte(0x80); /*CMP abrt, 0*/ - addbyte(0x7d); - addbyte((uint8_t)cpu_state_offset(abrt)); - addbyte(0); - addbyte(0x0f); /*JNE mem_abrt_rout*/ - addbyte(0x85); - addlong(mem_abrt_rout - ((uint32_t)(&codeblock[block_current].data[block_pos]) + 4)); - addbyte(0xc3); /*RET*/ + /*dat = ECX, seg = ESI, addr = EAX*/ + addbyte(0x89); /*MOV EBX, ESI*/ + addbyte(0xf3); + addbyte(0x01); /*ADDL ESI, EAX*/ + addbyte(0xc0 | (REG_EAX << 3) | REG_ESI); + addbyte(0x89); /*MOV EDI, ESI*/ + addbyte(0xf7); + addbyte(0xc1); /*SHR ESI, 12*/ + addbyte(0xe8 | REG_ESI); + addbyte(12); + addbyte(0xf7); /*TEST EDI, 1*/ + addbyte(0xc7); + addlong(1); + addbyte(0x8b); /*MOV ESI, readlookup2[ESI*4]*/ + addbyte(0x04 | (REG_ESI << 3)); + addbyte(0x85 | (REG_ESI << 3)); + addlong((uint32_t) writelookup2); + addbyte(0x75); /*JNE slowpath*/ + addbyte(3 + 2 + 4 + 1); + addbyte(0x83); /*CMP ESI, -1*/ + addbyte(0xf8 | REG_ESI); + addbyte(-1); + addbyte(0x74); /*JE slowpath*/ + addbyte(4 + 1); + addbyte(0x66); /*MOV [EDI+ESI],CX*/ + addbyte(0x89); + addbyte(0x04 | (REG_CX << 3)); + addbyte(REG_EDI | (REG_ESI << 3)); + addbyte(0xc3); /*RET*/ - return addr; + addbyte(0x51); /*slowpath: PUSH ECX*/ + addbyte(0x01); /*ADD EBX,EAX*/ + addbyte(0xC3); + addbyte(0x53); /*PUSH EBX*/ + addbyte(0xe8); /*CALL writememwl*/ + addlong((uint32_t) writememwl - (uint32_t) (&codeblock[block_current].data[block_pos + 4])); + addbyte(0x83); /*ADD ESP, 8*/ + addbyte(0xc4); + addbyte(8); + addbyte(0x80); /*CMP abrt, 0*/ + addbyte(0x7d); + addbyte((uint8_t) cpu_state_offset(abrt)); + addbyte(0); + addbyte(0x0f); /*JNE mem_abrt_rout*/ + addbyte(0x85); + addlong(mem_abrt_rout - ((uint32_t) (&codeblock[block_current].data[block_pos]) + 4)); + addbyte(0xc3); /*RET*/ + + return addr; } -static uint32_t gen_MEM_STORE_ADDR_EA_L() +static uint32_t +gen_MEM_STORE_ADDR_EA_L(void) { - uint32_t addr = (uint32_t)&codeblock[block_current].data[block_pos]; - - /*dat = ECX, seg = ESI, addr = EAX*/ - addbyte(0x89); /*MOV EBX, ESI*/ - addbyte(0xf3); - addbyte(0x01); /*ADDL ESI, EAX*/ - addbyte(0xc0 | (REG_EAX << 3) | REG_ESI); - addbyte(0x89); /*MOV EDI, ESI*/ - addbyte(0xf7); - addbyte(0xc1); /*SHR ESI, 12*/ - addbyte(0xe8 | REG_ESI); - addbyte(12); - addbyte(0xf7); /*TEST EDI, 3*/ - addbyte(0xc7); - addlong(3); - addbyte(0x8b); /*MOV ESI, readlookup2[ESI*4]*/ - addbyte(0x04 | (REG_ESI << 3)); - addbyte(0x85 | (REG_ESI << 3)); - addlong((uint32_t)writelookup2); - addbyte(0x75); /*JNE slowpath*/ - addbyte(3+2+3+1); - addbyte(0x83); /*CMP ESI, -1*/ - addbyte(0xf8 | REG_ESI); - addbyte(-1); - addbyte(0x74); /*JE slowpath*/ - addbyte(3+1); - addbyte(0x89); /*MOV [EDI+ESI],ECX*/ - addbyte(0x04 | (REG_ECX << 3)); - addbyte(REG_EDI | (REG_ESI << 3)); - addbyte(0xc3); /*RET*/ + uint32_t addr = (uint32_t) &codeblock[block_current].data[block_pos]; - addbyte(0x51); /*slowpath: PUSH ECX*/ - addbyte(0x01); /*ADD EBX,EAX*/ - addbyte(0xC3); - addbyte(0x53); /*PUSH EBX*/ - addbyte(0xe8); /*CALL writememll*/ - addlong((uint32_t)writememll - (uint32_t)(&codeblock[block_current].data[block_pos + 4])); - addbyte(0x83); /*ADD ESP, 8*/ - addbyte(0xc4); - addbyte(8); - addbyte(0x80); /*CMP abrt, 0*/ - addbyte(0x7d); - addbyte((uint8_t)cpu_state_offset(abrt)); - addbyte(0); - addbyte(0x0f); /*JNE mem_abrt_rout*/ - addbyte(0x85); - addlong(mem_abrt_rout - ((uint32_t)(&codeblock[block_current].data[block_pos]) + 4)); - addbyte(0xc3); /*RET*/ + /*dat = ECX, seg = ESI, addr = EAX*/ + addbyte(0x89); /*MOV EBX, ESI*/ + addbyte(0xf3); + addbyte(0x01); /*ADDL ESI, EAX*/ + addbyte(0xc0 | (REG_EAX << 3) | REG_ESI); + addbyte(0x89); /*MOV EDI, ESI*/ + addbyte(0xf7); + addbyte(0xc1); /*SHR ESI, 12*/ + addbyte(0xe8 | REG_ESI); + addbyte(12); + addbyte(0xf7); /*TEST EDI, 3*/ + addbyte(0xc7); + addlong(3); + addbyte(0x8b); /*MOV ESI, readlookup2[ESI*4]*/ + addbyte(0x04 | (REG_ESI << 3)); + addbyte(0x85 | (REG_ESI << 3)); + addlong((uint32_t) writelookup2); + addbyte(0x75); /*JNE slowpath*/ + addbyte(3 + 2 + 3 + 1); + addbyte(0x83); /*CMP ESI, -1*/ + addbyte(0xf8 | REG_ESI); + addbyte(-1); + addbyte(0x74); /*JE slowpath*/ + addbyte(3 + 1); + addbyte(0x89); /*MOV [EDI+ESI],ECX*/ + addbyte(0x04 | (REG_ECX << 3)); + addbyte(REG_EDI | (REG_ESI << 3)); + addbyte(0xc3); /*RET*/ - return addr; + addbyte(0x51); /*slowpath: PUSH ECX*/ + addbyte(0x01); /*ADD EBX,EAX*/ + addbyte(0xC3); + addbyte(0x53); /*PUSH EBX*/ + addbyte(0xe8); /*CALL writememll*/ + addlong((uint32_t) writememll - (uint32_t) (&codeblock[block_current].data[block_pos + 4])); + addbyte(0x83); /*ADD ESP, 8*/ + addbyte(0xc4); + addbyte(8); + addbyte(0x80); /*CMP abrt, 0*/ + addbyte(0x7d); + addbyte((uint8_t) cpu_state_offset(abrt)); + addbyte(0); + addbyte(0x0f); /*JNE mem_abrt_rout*/ + addbyte(0x85); + addlong(mem_abrt_rout - ((uint32_t) (&codeblock[block_current].data[block_pos]) + 4)); + addbyte(0xc3); /*RET*/ + + return addr; } -static uint32_t gen_MEM_STORE_ADDR_EA_Q() +static uint32_t +gen_MEM_STORE_ADDR_EA_Q(void) { - uint32_t addr = (uint32_t)&codeblock[block_current].data[block_pos]; - - /*dat = EBX/ECX, seg = ESI, addr = EAX*/ - addbyte(0x89); /*MOV EDX, ESI*/ - addbyte(0xf2); - addbyte(0x01); /*ADDL ESI, EAX*/ - addbyte(0xc0 | (REG_EAX << 3) | REG_ESI); - addbyte(0x89); /*MOV EDI, ESI*/ - addbyte(0xf7); - addbyte(0xc1); /*SHR ESI, 12*/ - addbyte(0xe8 | REG_ESI); - addbyte(12); - addbyte(0xf7); /*TEST EDI, 7*/ - addbyte(0xc7); - addlong(7); - addbyte(0x8b); /*MOV ESI, readlookup2[ESI*4]*/ - addbyte(0x04 | (REG_ESI << 3)); - addbyte(0x85 | (REG_ESI << 3)); - addlong((uint32_t)writelookup2); - addbyte(0x75); /*JNE slowpath*/ - addbyte(3+2+3+4+1); - addbyte(0x83); /*CMP ESI, -1*/ - addbyte(0xf8 | REG_ESI); - addbyte(-1); - addbyte(0x74); /*JE slowpath*/ - addbyte(3+4+1); - addbyte(0x89); /*MOV [EDI+ESI],EBX*/ - addbyte(0x04 | (REG_EBX << 3)); - addbyte(REG_EDI | (REG_ESI << 3)); - addbyte(0x89); /*MOV 4[EDI+ESI],EBX*/ - addbyte(0x44 | (REG_ECX << 3)); - addbyte(REG_EDI | (REG_ESI << 3)); - addbyte(4); - addbyte(0xc3); /*RET*/ + uint32_t addr = (uint32_t) &codeblock[block_current].data[block_pos]; - addbyte(0x51); /*slowpath: PUSH ECX*/ - addbyte(0x53); /*PUSH EBX*/ - addbyte(0x01); /*ADD EDX,EAX*/ - addbyte(0xC2); - addbyte(0x52); /*PUSH EDX*/ - addbyte(0xe8); /*CALL writememql*/ - addlong((uint32_t)writememql - (uint32_t)(&codeblock[block_current].data[block_pos + 4])); - addbyte(0x83); /*ADD ESP, 12*/ - addbyte(0xc4); - addbyte(12); - addbyte(0x80); /*CMP abrt, 0*/ - addbyte(0x7d); - addbyte((uint8_t)cpu_state_offset(abrt)); - addbyte(0); - addbyte(0x0f); /*JNE mem_abrt_rout*/ - addbyte(0x85); - addlong(mem_abrt_rout - ((uint32_t)(&codeblock[block_current].data[block_pos]) + 4)); - addbyte(0xc3); /*RET*/ + /*dat = EBX/ECX, seg = ESI, addr = EAX*/ + addbyte(0x89); /*MOV EDX, ESI*/ + addbyte(0xf2); + addbyte(0x01); /*ADDL ESI, EAX*/ + addbyte(0xc0 | (REG_EAX << 3) | REG_ESI); + addbyte(0x89); /*MOV EDI, ESI*/ + addbyte(0xf7); + addbyte(0xc1); /*SHR ESI, 12*/ + addbyte(0xe8 | REG_ESI); + addbyte(12); + addbyte(0xf7); /*TEST EDI, 7*/ + addbyte(0xc7); + addlong(7); + addbyte(0x8b); /*MOV ESI, readlookup2[ESI*4]*/ + addbyte(0x04 | (REG_ESI << 3)); + addbyte(0x85 | (REG_ESI << 3)); + addlong((uint32_t) writelookup2); + addbyte(0x75); /*JNE slowpath*/ + addbyte(3 + 2 + 3 + 4 + 1); + addbyte(0x83); /*CMP ESI, -1*/ + addbyte(0xf8 | REG_ESI); + addbyte(-1); + addbyte(0x74); /*JE slowpath*/ + addbyte(3 + 4 + 1); + addbyte(0x89); /*MOV [EDI+ESI],EBX*/ + addbyte(0x04 | (REG_EBX << 3)); + addbyte(REG_EDI | (REG_ESI << 3)); + addbyte(0x89); /*MOV 4[EDI+ESI],EBX*/ + addbyte(0x44 | (REG_ECX << 3)); + addbyte(REG_EDI | (REG_ESI << 3)); + addbyte(4); + addbyte(0xc3); /*RET*/ - return addr; + addbyte(0x51); /*slowpath: PUSH ECX*/ + addbyte(0x53); /*PUSH EBX*/ + addbyte(0x01); /*ADD EDX,EAX*/ + addbyte(0xC2); + addbyte(0x52); /*PUSH EDX*/ + addbyte(0xe8); /*CALL writememql*/ + addlong((uint32_t) writememql - (uint32_t) (&codeblock[block_current].data[block_pos + 4])); + addbyte(0x83); /*ADD ESP, 12*/ + addbyte(0xc4); + addbyte(12); + addbyte(0x80); /*CMP abrt, 0*/ + addbyte(0x7d); + addbyte((uint8_t) cpu_state_offset(abrt)); + addbyte(0); + addbyte(0x0f); /*JNE mem_abrt_rout*/ + addbyte(0x85); + addlong(mem_abrt_rout - ((uint32_t) (&codeblock[block_current].data[block_pos]) + 4)); + addbyte(0xc3); /*RET*/ + + return addr; } -#ifndef RELEASE_BUILD +# ifndef RELEASE_BUILD static char gen_MEM_LOAD_ADDR_EA_B_NO_ABRT_err[] = "gen_MEM_LOAD_ADDR_EA_B_NO_ABRT aborted\n"; -#endif -static uint32_t gen_MEM_LOAD_ADDR_EA_B_NO_ABRT() +# endif +static uint32_t +gen_MEM_LOAD_ADDR_EA_B_NO_ABRT(void) { - uint32_t addr = (uint32_t)&codeblock[block_current].data[block_pos]; + uint32_t addr = (uint32_t) &codeblock[block_current].data[block_pos]; - addbyte(0x89); /*MOV ESI, EDX*/ - addbyte(0xd6); - addbyte(0x01); /*ADDL EDX, EAX*/ - addbyte(0xc2); - addbyte(0x89); /*MOV EDI, EDX*/ - addbyte(0xd7); - addbyte(0xc1); /*SHR EDX, 12*/ - addbyte(0xea); - addbyte(12); - addbyte(0x8b); /*MOV EDX, readlookup2[EDX*4]*/ - addbyte(0x14); - addbyte(0x95); - addlong((uint32_t)readlookup2); - addbyte(0x83); /*CMP EDX, -1*/ - addbyte(0xfa); - addbyte(-1); - addbyte(0x74); /*JE slowpath*/ - addbyte(4+1); - addbyte(0x0f); /*MOVZX ECX, B[EDX+EDI]*/ - addbyte(0xb6); - addbyte(0x0c); - addbyte(0x3a); - addbyte(0xc3); /*RET*/ + addbyte(0x89); /*MOV ESI, EDX*/ + addbyte(0xd6); + addbyte(0x01); /*ADDL EDX, EAX*/ + addbyte(0xc2); + addbyte(0x89); /*MOV EDI, EDX*/ + addbyte(0xd7); + addbyte(0xc1); /*SHR EDX, 12*/ + addbyte(0xea); + addbyte(12); + addbyte(0x8b); /*MOV EDX, readlookup2[EDX*4]*/ + addbyte(0x14); + addbyte(0x95); + addlong((uint32_t) readlookup2); + addbyte(0x83); /*CMP EDX, -1*/ + addbyte(0xfa); + addbyte(-1); + addbyte(0x74); /*JE slowpath*/ + addbyte(4 + 1); + addbyte(0x0f); /*MOVZX ECX, B[EDX+EDI]*/ + addbyte(0xb6); + addbyte(0x0c); + addbyte(0x3a); + addbyte(0xc3); /*RET*/ - addbyte(0x01); /*slowpath: ADD ESI,EAX*/ - addbyte(0xc6); - addbyte(0x56); /*PUSH ESI*/ - addbyte(0xe8); /*CALL readmembl*/ - addlong((uint32_t)readmembl - (uint32_t)(&codeblock[block_current].data[block_pos + 4])); - addbyte(0x83); /*ADD ESP, 4*/ - addbyte(0xc4); - addbyte(4); -#ifndef RELEASE_BUILD - addbyte(0x80); /*CMP abrt, 0*/ - addbyte(0x7d); - addbyte((uint8_t)cpu_state_offset(abrt)); - addbyte(0); -#endif - addbyte(0x0f); /*MOVZX ECX, AL*/ - addbyte(0xb6); - addbyte(0xc8); -#ifndef RELEASE_BUILD - addbyte(0x75); /*JNE mem_abrt_rout*/ - addbyte(1); -#endif - addbyte(0xc3); /*RET*/ -#ifndef RELEASE_BUILD - addbyte(0xc7); /*MOV [ESP], gen_MEM_LOAD_ADDR_EA_B_NO_ABRT_err*/ - addbyte(0x04); - addbyte(0x24); - addlong((uint32_t)gen_MEM_LOAD_ADDR_EA_B_NO_ABRT_err); - addbyte(0xe8); /*CALL fatal*/ - addlong((uint32_t)fatal - (uint32_t)(&codeblock[block_current].data[block_pos + 4])); - /*Should not return!*/ -#endif - return addr; + addbyte(0x01); /*slowpath: ADD ESI,EAX*/ + addbyte(0xc6); + addbyte(0x56); /*PUSH ESI*/ + addbyte(0xe8); /*CALL readmembl*/ + addlong((uint32_t) readmembl - (uint32_t) (&codeblock[block_current].data[block_pos + 4])); + addbyte(0x83); /*ADD ESP, 4*/ + addbyte(0xc4); + addbyte(4); +# ifndef RELEASE_BUILD + addbyte(0x80); /*CMP abrt, 0*/ + addbyte(0x7d); + addbyte((uint8_t) cpu_state_offset(abrt)); + addbyte(0); +# endif + addbyte(0x0f); /*MOVZX ECX, AL*/ + addbyte(0xb6); + addbyte(0xc8); +# ifndef RELEASE_BUILD + addbyte(0x75); /*JNE mem_abrt_rout*/ + addbyte(1); +# endif + addbyte(0xc3); /*RET*/ +# ifndef RELEASE_BUILD + addbyte(0xc7); /*MOV [ESP], gen_MEM_LOAD_ADDR_EA_B_NO_ABRT_err*/ + addbyte(0x04); + addbyte(0x24); + addlong((uint32_t) gen_MEM_LOAD_ADDR_EA_B_NO_ABRT_err); + addbyte(0xe8); /*CALL fatal*/ + addlong((uint32_t) fatal - (uint32_t) (&codeblock[block_current].data[block_pos + 4])); + /*Should not return!*/ +# endif + return addr; } -#ifndef RELEASE_BUILD +# ifndef RELEASE_BUILD static char gen_MEM_LOAD_ADDR_EA_W_NO_ABRT_err[] = "gen_MEM_LOAD_ADDR_EA_W_NO_ABRT aborted\n"; -#endif -static uint32_t gen_MEM_LOAD_ADDR_EA_W_NO_ABRT() +# endif +static uint32_t +gen_MEM_LOAD_ADDR_EA_W_NO_ABRT(void) { - uint32_t addr = (uint32_t)&codeblock[block_current].data[block_pos]; + uint32_t addr = (uint32_t) &codeblock[block_current].data[block_pos]; - addbyte(0x89); /*MOV ESI, EDX*/ - addbyte(0xd6); - addbyte(0x01); /*ADDL EDX, EAX*/ - addbyte(0xc2); - addbyte(0x89); /*MOV EDI, EDX*/ - addbyte(0xd7); - addbyte(0xc1); /*SHR EDX, 12*/ - addbyte(0xea); - addbyte(12); - addbyte(0xf7); /*TEST EDI, 1*/ - addbyte(0xc7); - addlong(1); - addbyte(0x8b); /*MOV EDX, readlookup2[EDX*4]*/ - addbyte(0x14); - addbyte(0x95); - addlong((uint32_t)readlookup2); - addbyte(0x75); /*JNE slowpath*/ - addbyte(3+2+4+1); - addbyte(0x83); /*CMP EDX, -1*/ - addbyte(0xfa); - addbyte(-1); - addbyte(0x74); /*JE slowpath*/ - addbyte(4+1); - addbyte(0x0f); /*MOVZX ECX, [EDX+EDI]W*/ - addbyte(0xb7); - addbyte(0x0c); - addbyte(0x3a); - addbyte(0xc3); /*RET*/ + addbyte(0x89); /*MOV ESI, EDX*/ + addbyte(0xd6); + addbyte(0x01); /*ADDL EDX, EAX*/ + addbyte(0xc2); + addbyte(0x89); /*MOV EDI, EDX*/ + addbyte(0xd7); + addbyte(0xc1); /*SHR EDX, 12*/ + addbyte(0xea); + addbyte(12); + addbyte(0xf7); /*TEST EDI, 1*/ + addbyte(0xc7); + addlong(1); + addbyte(0x8b); /*MOV EDX, readlookup2[EDX*4]*/ + addbyte(0x14); + addbyte(0x95); + addlong((uint32_t) readlookup2); + addbyte(0x75); /*JNE slowpath*/ + addbyte(3 + 2 + 4 + 1); + addbyte(0x83); /*CMP EDX, -1*/ + addbyte(0xfa); + addbyte(-1); + addbyte(0x74); /*JE slowpath*/ + addbyte(4 + 1); + addbyte(0x0f); /*MOVZX ECX, [EDX+EDI]W*/ + addbyte(0xb7); + addbyte(0x0c); + addbyte(0x3a); + addbyte(0xc3); /*RET*/ - addbyte(0x01); /*slowpath: ADD ESI,EAX*/ - addbyte(0xc6); - addbyte(0x56); /*PUSH ESI*/ - addbyte(0xe8); /*CALL readmemwl*/ - addlong((uint32_t)readmemwl - (uint32_t)(&codeblock[block_current].data[block_pos + 4])); - addbyte(0x83); /*ADD ESP, 4*/ - addbyte(0xc4); - addbyte(4); -#ifndef RELEASE_BUILD - addbyte(0x80); /*CMP abrt, 0*/ - addbyte(0x7d); - addbyte((uint8_t)cpu_state_offset(abrt)); - addbyte(0); -#endif - addbyte(0x0f); /*MOVZX ECX, AX*/ - addbyte(0xb7); - addbyte(0xc8); -#ifndef RELEASE_BUILD - addbyte(0x75); /*JNE mem_abrt_rout*/ - addbyte(1); -#endif - addbyte(0xc3); /*RET*/ -#ifndef RELEASE_BUILD - addbyte(0xc7); /*MOV [ESP], gen_MEM_LOAD_ADDR_EA_W_NO_ABRT_err*/ - addbyte(0x04); - addbyte(0x24); - addlong((uint32_t)gen_MEM_LOAD_ADDR_EA_W_NO_ABRT_err); - addbyte(0xe8); /*CALL fatal*/ - addlong((uint32_t)fatal - (uint32_t)(&codeblock[block_current].data[block_pos + 4])); - /*Should not return!*/ -#endif - return addr; + addbyte(0x01); /*slowpath: ADD ESI,EAX*/ + addbyte(0xc6); + addbyte(0x56); /*PUSH ESI*/ + addbyte(0xe8); /*CALL readmemwl*/ + addlong((uint32_t) readmemwl - (uint32_t) (&codeblock[block_current].data[block_pos + 4])); + addbyte(0x83); /*ADD ESP, 4*/ + addbyte(0xc4); + addbyte(4); +# ifndef RELEASE_BUILD + addbyte(0x80); /*CMP abrt, 0*/ + addbyte(0x7d); + addbyte((uint8_t) cpu_state_offset(abrt)); + addbyte(0); +# endif + addbyte(0x0f); /*MOVZX ECX, AX*/ + addbyte(0xb7); + addbyte(0xc8); +# ifndef RELEASE_BUILD + addbyte(0x75); /*JNE mem_abrt_rout*/ + addbyte(1); +# endif + addbyte(0xc3); /*RET*/ +# ifndef RELEASE_BUILD + addbyte(0xc7); /*MOV [ESP], gen_MEM_LOAD_ADDR_EA_W_NO_ABRT_err*/ + addbyte(0x04); + addbyte(0x24); + addlong((uint32_t) gen_MEM_LOAD_ADDR_EA_W_NO_ABRT_err); + addbyte(0xe8); /*CALL fatal*/ + addlong((uint32_t) fatal - (uint32_t) (&codeblock[block_current].data[block_pos + 4])); + /*Should not return!*/ +# endif + return addr; } -#ifndef RELEASE_BUILD +# ifndef RELEASE_BUILD static char gen_MEM_LOAD_ADDR_EA_L_NO_ABRT_err[] = "gen_MEM_LOAD_ADDR_EA_L_NO_ABRT aborted\n"; -#endif -static uint32_t gen_MEM_LOAD_ADDR_EA_L_NO_ABRT() +# endif +static uint32_t +gen_MEM_LOAD_ADDR_EA_L_NO_ABRT(void) { - uint32_t addr = (uint32_t)&codeblock[block_current].data[block_pos]; + uint32_t addr = (uint32_t) &codeblock[block_current].data[block_pos]; - addbyte(0x89); /*MOV ESI, EDX*/ - addbyte(0xd6); - addbyte(0x01); /*ADDL EDX, EAX*/ - addbyte(0xc2); - addbyte(0x89); /*MOV EDI, EDX*/ - addbyte(0xd7); - addbyte(0xc1); /*SHR EDX, 12*/ - addbyte(0xea); - addbyte(12); - addbyte(0xf7); /*TEST EDI, 3*/ - addbyte(0xc7); - addlong(3); - addbyte(0x8b); /*MOV EDX, readlookup2[EDX*4]*/ - addbyte(0x14); - addbyte(0x95); - addlong((uint32_t)readlookup2); - addbyte(0x75); /*JE slowpath*/ - addbyte(3+2+3+1); - addbyte(0x83); /*CMP EDX, -1*/ - addbyte(0xfa); - addbyte(-1); - addbyte(0x74); /*JE slowpath*/ - addbyte(3+1); - addbyte(0x8b); /*MOV ECX, [EDX+EDI]*/ - addbyte(0x0c); - addbyte(0x3a); - addbyte(0xc3); /*RET*/ + addbyte(0x89); /*MOV ESI, EDX*/ + addbyte(0xd6); + addbyte(0x01); /*ADDL EDX, EAX*/ + addbyte(0xc2); + addbyte(0x89); /*MOV EDI, EDX*/ + addbyte(0xd7); + addbyte(0xc1); /*SHR EDX, 12*/ + addbyte(0xea); + addbyte(12); + addbyte(0xf7); /*TEST EDI, 3*/ + addbyte(0xc7); + addlong(3); + addbyte(0x8b); /*MOV EDX, readlookup2[EDX*4]*/ + addbyte(0x14); + addbyte(0x95); + addlong((uint32_t) readlookup2); + addbyte(0x75); /*JE slowpath*/ + addbyte(3 + 2 + 3 + 1); + addbyte(0x83); /*CMP EDX, -1*/ + addbyte(0xfa); + addbyte(-1); + addbyte(0x74); /*JE slowpath*/ + addbyte(3 + 1); + addbyte(0x8b); /*MOV ECX, [EDX+EDI]*/ + addbyte(0x0c); + addbyte(0x3a); + addbyte(0xc3); /*RET*/ - addbyte(0x01); /*slowpath: ADD ESI,EAX*/ - addbyte(0xc6); - addbyte(0x56); /*PUSH ESI*/ - addbyte(0xe8); /*CALL readmemll*/ - addlong((uint32_t)readmemll - (uint32_t)(&codeblock[block_current].data[block_pos + 4])); - addbyte(0x83); /*ADD ESP, 4*/ - addbyte(0xc4); - addbyte(4); - addbyte(0x89); /*MOV ECX, EAX*/ - addbyte(0xc1); -#ifndef RELEASE_BUILD - addbyte(0x80); /*CMP abrt, 0*/ - addbyte(0x7d); - addbyte((uint8_t)cpu_state_offset(abrt)); - addbyte(0); - addbyte(0x75); /*JNE mem_abrt_rout*/ - addbyte(1); -#endif - addbyte(0xc3); /*RET*/ -#ifndef RELEASE_BUILD - addbyte(0x83); /*SUBL 4,%esp*/ - addbyte(0xEC); - addbyte(4); - addbyte(0xc7); /*MOV [ESP], gen_MEM_LOAD_ADDR_EA_L_NO_ABRT_err*/ - addbyte(0x04); - addbyte(0x24); - addlong((uint32_t)gen_MEM_LOAD_ADDR_EA_L_NO_ABRT_err); - addbyte(0xe8); /*CALL fatal*/ - addlong((uint32_t)fatal - (uint32_t)(&codeblock[block_current].data[block_pos + 4])); - /*Should not return!*/ -#endif - return addr; + addbyte(0x01); /*slowpath: ADD ESI,EAX*/ + addbyte(0xc6); + addbyte(0x56); /*PUSH ESI*/ + addbyte(0xe8); /*CALL readmemll*/ + addlong((uint32_t) readmemll - (uint32_t) (&codeblock[block_current].data[block_pos + 4])); + addbyte(0x83); /*ADD ESP, 4*/ + addbyte(0xc4); + addbyte(4); + addbyte(0x89); /*MOV ECX, EAX*/ + addbyte(0xc1); +# ifndef RELEASE_BUILD + addbyte(0x80); /*CMP abrt, 0*/ + addbyte(0x7d); + addbyte((uint8_t) cpu_state_offset(abrt)); + addbyte(0); + addbyte(0x75); /*JNE mem_abrt_rout*/ + addbyte(1); +# endif + addbyte(0xc3); /*RET*/ +# ifndef RELEASE_BUILD + addbyte(0x83); /*SUBL 4,%esp*/ + addbyte(0xEC); + addbyte(4); + addbyte(0xc7); /*MOV [ESP], gen_MEM_LOAD_ADDR_EA_L_NO_ABRT_err*/ + addbyte(0x04); + addbyte(0x24); + addlong((uint32_t) gen_MEM_LOAD_ADDR_EA_L_NO_ABRT_err); + addbyte(0xe8); /*CALL fatal*/ + addlong((uint32_t) fatal - (uint32_t) (&codeblock[block_current].data[block_pos + 4])); + /*Should not return!*/ +# endif + return addr; } -#ifndef RELEASE_BUILD +# ifndef RELEASE_BUILD static char gen_MEM_STORE_ADDR_EA_B_NO_ABRT_err[] = "gen_MEM_STORE_ADDR_EA_B_NO_ABRT aborted\n"; -#endif -static uint32_t gen_MEM_STORE_ADDR_EA_B_NO_ABRT() +# endif +static uint32_t +gen_MEM_STORE_ADDR_EA_B_NO_ABRT(void) { - uint32_t addr = (uint32_t)&codeblock[block_current].data[block_pos]; - - /*dat = ECX, seg = ESI, addr = EAX*/ - addbyte(0x89); /*MOV EBX, ESI*/ - addbyte(0xf3); - addbyte(0x01); /*ADDL ESI, EAX*/ - addbyte(0xc0 | (REG_EAX << 3) | REG_ESI); - addbyte(0x89); /*MOV EDI, ESI*/ - addbyte(0xc0 | (REG_ESI << 3) | REG_EDI); - addbyte(0xc1); /*SHR ESI, 12*/ - addbyte(0xe8 | REG_ESI); - addbyte(12); - addbyte(0x8b); /*MOV ESI, readlookup2[ESI*4]*/ - addbyte(0x04 | (REG_ESI << 3)); - addbyte(0x85 | (REG_ESI << 3)); - addlong((uint32_t)writelookup2); - addbyte(0x83); /*CMP ESI, -1*/ - addbyte(0xf8 | REG_ESI); - addbyte(-1); - addbyte(0x74); /*JE slowpath*/ - addbyte(3+1); - addbyte(0x88); /*MOV [EDI+ESI],CL*/ - addbyte(0x04 | (REG_ECX << 3)); - addbyte(REG_EDI | (REG_ESI << 3)); - addbyte(0xc3); /*RET*/ + uint32_t addr = (uint32_t) &codeblock[block_current].data[block_pos]; - addbyte(0x51); /*slowpath: PUSH ECX*/ - addbyte(0x01); /*ADD EBX,EAX*/ - addbyte(0xc3); - addbyte(0x53); /*PUSH EBX*/ - addbyte(0xe8); /*CALL writemembl*/ - addlong((uint32_t)writemembl - (uint32_t)(&codeblock[block_current].data[block_pos + 4])); - addbyte(0x83); /*ADD ESP, 8*/ - addbyte(0xc4); - addbyte(8); -#ifndef RELEASE_BUILD - addbyte(0x80); /*CMP abrt, 0*/ - addbyte(0x7d); - addbyte((uint8_t)cpu_state_offset(abrt)); - addbyte(0); - addbyte(0x75); /*JNE mem_abrt_rout*/ - addbyte(1); -#endif - addbyte(0xc3); /*RET*/ -#ifndef RELEASE_BUILD - addbyte(0xc7); /*MOV [ESP], gen_MEM_STORE_ADDR_EA_B_NO_ABRT_err*/ - addbyte(0x04); - addbyte(0x24); - addlong((uint32_t)gen_MEM_STORE_ADDR_EA_B_NO_ABRT_err); - addbyte(0xe8); /*CALL fatal*/ - addlong((uint32_t)fatal - (uint32_t)(&codeblock[block_current].data[block_pos + 4])); - /*Should not return!*/ -#endif - return addr; + /*dat = ECX, seg = ESI, addr = EAX*/ + addbyte(0x89); /*MOV EBX, ESI*/ + addbyte(0xf3); + addbyte(0x01); /*ADDL ESI, EAX*/ + addbyte(0xc0 | (REG_EAX << 3) | REG_ESI); + addbyte(0x89); /*MOV EDI, ESI*/ + addbyte(0xc0 | (REG_ESI << 3) | REG_EDI); + addbyte(0xc1); /*SHR ESI, 12*/ + addbyte(0xe8 | REG_ESI); + addbyte(12); + addbyte(0x8b); /*MOV ESI, readlookup2[ESI*4]*/ + addbyte(0x04 | (REG_ESI << 3)); + addbyte(0x85 | (REG_ESI << 3)); + addlong((uint32_t) writelookup2); + addbyte(0x83); /*CMP ESI, -1*/ + addbyte(0xf8 | REG_ESI); + addbyte(-1); + addbyte(0x74); /*JE slowpath*/ + addbyte(3 + 1); + addbyte(0x88); /*MOV [EDI+ESI],CL*/ + addbyte(0x04 | (REG_ECX << 3)); + addbyte(REG_EDI | (REG_ESI << 3)); + addbyte(0xc3); /*RET*/ + + addbyte(0x51); /*slowpath: PUSH ECX*/ + addbyte(0x01); /*ADD EBX,EAX*/ + addbyte(0xc3); + addbyte(0x53); /*PUSH EBX*/ + addbyte(0xe8); /*CALL writemembl*/ + addlong((uint32_t) writemembl - (uint32_t) (&codeblock[block_current].data[block_pos + 4])); + addbyte(0x83); /*ADD ESP, 8*/ + addbyte(0xc4); + addbyte(8); +# ifndef RELEASE_BUILD + addbyte(0x80); /*CMP abrt, 0*/ + addbyte(0x7d); + addbyte((uint8_t) cpu_state_offset(abrt)); + addbyte(0); + addbyte(0x75); /*JNE mem_abrt_rout*/ + addbyte(1); +# endif + addbyte(0xc3); /*RET*/ +# ifndef RELEASE_BUILD + addbyte(0xc7); /*MOV [ESP], gen_MEM_STORE_ADDR_EA_B_NO_ABRT_err*/ + addbyte(0x04); + addbyte(0x24); + addlong((uint32_t) gen_MEM_STORE_ADDR_EA_B_NO_ABRT_err); + addbyte(0xe8); /*CALL fatal*/ + addlong((uint32_t) fatal - (uint32_t) (&codeblock[block_current].data[block_pos + 4])); + /*Should not return!*/ +# endif + return addr; } -#ifndef RELEASE_BUILD +# ifndef RELEASE_BUILD static char gen_MEM_STORE_ADDR_EA_W_NO_ABRT_err[] = "gen_MEM_STORE_ADDR_EA_W_NO_ABRT aborted\n"; -#endif -static uint32_t gen_MEM_STORE_ADDR_EA_W_NO_ABRT() +# endif +static uint32_t +gen_MEM_STORE_ADDR_EA_W_NO_ABRT(void) { - uint32_t addr = (uint32_t)&codeblock[block_current].data[block_pos]; - - /*dat = ECX, seg = ESI, addr = EAX*/ - addbyte(0x89); /*MOV EBX, ESI*/ - addbyte(0xf3); - addbyte(0x01); /*ADDL ESI, EAX*/ - addbyte(0xc0 | (REG_EAX << 3) | REG_ESI); - addbyte(0x89); /*MOV EDI, ESI*/ - addbyte(0xf7); - addbyte(0xc1); /*SHR ESI, 12*/ - addbyte(0xe8 | REG_ESI); - addbyte(12); - addbyte(0xf7); /*TEST EDI, 1*/ - addbyte(0xc7); - addlong(1); - addbyte(0x8b); /*MOV ESI, readlookup2[ESI*4]*/ - addbyte(0x04 | (REG_ESI << 3)); - addbyte(0x85 | (REG_ESI << 3)); - addlong((uint32_t)writelookup2); - addbyte(0x75); /*JNE slowpath*/ - addbyte(3+2+4+1); - addbyte(0x83); /*CMP ESI, -1*/ - addbyte(0xf8 | REG_ESI); - addbyte(-1); - addbyte(0x74); /*JE slowpath*/ - addbyte(4+1); - addbyte(0x66); /*MOV [EDI+ESI],CX*/ - addbyte(0x89); - addbyte(0x04 | (REG_CX << 3)); - addbyte(REG_EDI | (REG_ESI << 3)); - addbyte(0xc3); /*RET*/ + uint32_t addr = (uint32_t) &codeblock[block_current].data[block_pos]; - addbyte(0x51); /*slowpath: PUSH ECX*/ - addbyte(0x01); /*ADD EBX,EAX*/ - addbyte(0xC3); - addbyte(0x53); /*PUSH EBX*/ - addbyte(0xe8); /*CALL writememwl*/ - addlong((uint32_t)writememwl - (uint32_t)(&codeblock[block_current].data[block_pos + 4])); - addbyte(0x83); /*ADD ESP, 8*/ - addbyte(0xc4); - addbyte(8); -#ifndef RELEASE_BUILD - addbyte(0x80); /*CMP abrt, 0*/ - addbyte(0x7d); - addbyte((uint8_t)cpu_state_offset(abrt)); - addbyte(0); - addbyte(0x75); /*JNE mem_abrt_rout*/ - addbyte(1); -#endif - addbyte(0xc3); /*RET*/ -#ifndef RELEASE_BUILD - addbyte(0xc7); /*MOV [ESP], gen_MEM_STORE_ADDR_EA_W_NO_ABRT_err*/ - addbyte(0x04); - addbyte(0x24); - addlong((uint32_t)gen_MEM_STORE_ADDR_EA_W_NO_ABRT_err); - addbyte(0xe8); /*CALL fatal*/ - addlong((uint32_t)fatal - (uint32_t)(&codeblock[block_current].data[block_pos + 4])); - /*Should not return!*/ -#endif - return addr; + /*dat = ECX, seg = ESI, addr = EAX*/ + addbyte(0x89); /*MOV EBX, ESI*/ + addbyte(0xf3); + addbyte(0x01); /*ADDL ESI, EAX*/ + addbyte(0xc0 | (REG_EAX << 3) | REG_ESI); + addbyte(0x89); /*MOV EDI, ESI*/ + addbyte(0xf7); + addbyte(0xc1); /*SHR ESI, 12*/ + addbyte(0xe8 | REG_ESI); + addbyte(12); + addbyte(0xf7); /*TEST EDI, 1*/ + addbyte(0xc7); + addlong(1); + addbyte(0x8b); /*MOV ESI, readlookup2[ESI*4]*/ + addbyte(0x04 | (REG_ESI << 3)); + addbyte(0x85 | (REG_ESI << 3)); + addlong((uint32_t) writelookup2); + addbyte(0x75); /*JNE slowpath*/ + addbyte(3 + 2 + 4 + 1); + addbyte(0x83); /*CMP ESI, -1*/ + addbyte(0xf8 | REG_ESI); + addbyte(-1); + addbyte(0x74); /*JE slowpath*/ + addbyte(4 + 1); + addbyte(0x66); /*MOV [EDI+ESI],CX*/ + addbyte(0x89); + addbyte(0x04 | (REG_CX << 3)); + addbyte(REG_EDI | (REG_ESI << 3)); + addbyte(0xc3); /*RET*/ + + addbyte(0x51); /*slowpath: PUSH ECX*/ + addbyte(0x01); /*ADD EBX,EAX*/ + addbyte(0xC3); + addbyte(0x53); /*PUSH EBX*/ + addbyte(0xe8); /*CALL writememwl*/ + addlong((uint32_t) writememwl - (uint32_t) (&codeblock[block_current].data[block_pos + 4])); + addbyte(0x83); /*ADD ESP, 8*/ + addbyte(0xc4); + addbyte(8); +# ifndef RELEASE_BUILD + addbyte(0x80); /*CMP abrt, 0*/ + addbyte(0x7d); + addbyte((uint8_t) cpu_state_offset(abrt)); + addbyte(0); + addbyte(0x75); /*JNE mem_abrt_rout*/ + addbyte(1); +# endif + addbyte(0xc3); /*RET*/ +# ifndef RELEASE_BUILD + addbyte(0xc7); /*MOV [ESP], gen_MEM_STORE_ADDR_EA_W_NO_ABRT_err*/ + addbyte(0x04); + addbyte(0x24); + addlong((uint32_t) gen_MEM_STORE_ADDR_EA_W_NO_ABRT_err); + addbyte(0xe8); /*CALL fatal*/ + addlong((uint32_t) fatal - (uint32_t) (&codeblock[block_current].data[block_pos + 4])); + /*Should not return!*/ +# endif + return addr; } -#ifndef RELEASE_BUILD +# ifndef RELEASE_BUILD static char gen_MEM_STORE_ADDR_EA_L_NO_ABRT_err[] = "gen_MEM_STORE_ADDR_EA_L_NO_ABRT aborted\n"; -#endif -static uint32_t gen_MEM_STORE_ADDR_EA_L_NO_ABRT() +# endif +static uint32_t +gen_MEM_STORE_ADDR_EA_L_NO_ABRT(void) { - uint32_t addr = (uint32_t)&codeblock[block_current].data[block_pos]; - - /*dat = ECX, seg = ESI, addr = EAX*/ - addbyte(0x89); /*MOV EBX, ESI*/ - addbyte(0xf3); - addbyte(0x01); /*ADDL ESI, EAX*/ - addbyte(0xc0 | (REG_EAX << 3) | REG_ESI); - addbyte(0x89); /*MOV EDI, ESI*/ - addbyte(0xf7); - addbyte(0xc1); /*SHR ESI, 12*/ - addbyte(0xe8 | REG_ESI); - addbyte(12); - addbyte(0xf7); /*TEST EDI, 3*/ - addbyte(0xc7); - addlong(3); - addbyte(0x8b); /*MOV ESI, readlookup2[ESI*4]*/ - addbyte(0x04 | (REG_ESI << 3)); - addbyte(0x85 | (REG_ESI << 3)); - addlong((uint32_t)writelookup2); - addbyte(0x75); /*JNE slowpath*/ - addbyte(3+2+3+1); - addbyte(0x83); /*CMP ESI, -1*/ - addbyte(0xf8 | REG_ESI); - addbyte(-1); - addbyte(0x74); /*JE slowpath*/ - addbyte(3+1); - addbyte(0x89); /*MOV [EDI+ESI],ECX*/ - addbyte(0x04 | (REG_ECX << 3)); - addbyte(REG_EDI | (REG_ESI << 3)); - addbyte(0xc3); /*RET*/ + uint32_t addr = (uint32_t) &codeblock[block_current].data[block_pos]; - addbyte(0x51); /*slowpath: PUSH ECX*/ - addbyte(0x01); /*ADD EBX,EAX*/ - addbyte(0xC3); - addbyte(0x53); /*PUSH EBX*/ - addbyte(0xe8); /*CALL writememll*/ - addlong((uint32_t)writememll - (uint32_t)(&codeblock[block_current].data[block_pos + 4])); - addbyte(0x83); /*ADD ESP, 8*/ - addbyte(0xc4); - addbyte(8); -#ifndef RELEASE_BUILD - addbyte(0x80); /*CMP abrt, 0*/ - addbyte(0x7d); - addbyte((uint8_t)cpu_state_offset(abrt)); - addbyte(0); - addbyte(0x75); /*JNE mem_abrt_rout*/ - addbyte(1); -#endif - addbyte(0xc3); /*RET*/ -#ifndef RELEASE_BUILD - addbyte(0xc7); /*MOV [ESP], gen_MEM_STORE_ADDR_EA_L_NO_ABRT_err*/ - addbyte(0x04); - addbyte(0x24); - addlong((uint32_t)gen_MEM_STORE_ADDR_EA_L_NO_ABRT_err); - addbyte(0xe8); /*CALL fatal*/ - addlong((uint32_t)fatal - (uint32_t)(&codeblock[block_current].data[block_pos + 4])); - /*Should not return!*/ -#endif - return addr; + /*dat = ECX, seg = ESI, addr = EAX*/ + addbyte(0x89); /*MOV EBX, ESI*/ + addbyte(0xf3); + addbyte(0x01); /*ADDL ESI, EAX*/ + addbyte(0xc0 | (REG_EAX << 3) | REG_ESI); + addbyte(0x89); /*MOV EDI, ESI*/ + addbyte(0xf7); + addbyte(0xc1); /*SHR ESI, 12*/ + addbyte(0xe8 | REG_ESI); + addbyte(12); + addbyte(0xf7); /*TEST EDI, 3*/ + addbyte(0xc7); + addlong(3); + addbyte(0x8b); /*MOV ESI, readlookup2[ESI*4]*/ + addbyte(0x04 | (REG_ESI << 3)); + addbyte(0x85 | (REG_ESI << 3)); + addlong((uint32_t) writelookup2); + addbyte(0x75); /*JNE slowpath*/ + addbyte(3 + 2 + 3 + 1); + addbyte(0x83); /*CMP ESI, -1*/ + addbyte(0xf8 | REG_ESI); + addbyte(-1); + addbyte(0x74); /*JE slowpath*/ + addbyte(3 + 1); + addbyte(0x89); /*MOV [EDI+ESI],ECX*/ + addbyte(0x04 | (REG_ECX << 3)); + addbyte(REG_EDI | (REG_ESI << 3)); + addbyte(0xc3); /*RET*/ + + addbyte(0x51); /*slowpath: PUSH ECX*/ + addbyte(0x01); /*ADD EBX,EAX*/ + addbyte(0xC3); + addbyte(0x53); /*PUSH EBX*/ + addbyte(0xe8); /*CALL writememll*/ + addlong((uint32_t) writememll - (uint32_t) (&codeblock[block_current].data[block_pos + 4])); + addbyte(0x83); /*ADD ESP, 8*/ + addbyte(0xc4); + addbyte(8); +# ifndef RELEASE_BUILD + addbyte(0x80); /*CMP abrt, 0*/ + addbyte(0x7d); + addbyte((uint8_t) cpu_state_offset(abrt)); + addbyte(0); + addbyte(0x75); /*JNE mem_abrt_rout*/ + addbyte(1); +# endif + addbyte(0xc3); /*RET*/ +# ifndef RELEASE_BUILD + addbyte(0xc7); /*MOV [ESP], gen_MEM_STORE_ADDR_EA_L_NO_ABRT_err*/ + addbyte(0x04); + addbyte(0x24); + addlong((uint32_t) gen_MEM_STORE_ADDR_EA_L_NO_ABRT_err); + addbyte(0xe8); /*CALL fatal*/ + addlong((uint32_t) fatal - (uint32_t) (&codeblock[block_current].data[block_pos + 4])); + /*Should not return!*/ +# endif + return addr; } -static uint32_t gen_MEM_CHECK_WRITE() +static uint32_t +gen_MEM_CHECK_WRITE(void) { - uint32_t addr = (uint32_t)&codeblock[block_current].data[block_pos]; - - /*seg = ESI, addr = EAX*/ - - addbyte(0x8d); /*LEA EDI, [EAX+ESI]*/ - addbyte(0x3c); - addbyte(0x30); - addbyte(0x83); /*CMP cr0, 0*/ - addbyte(0x3d); - addlong((uint32_t)&cr0); - addbyte(0); - addbyte(0x78); /*JS +*/ - addbyte(1); - addbyte(0xc3); /*RET*/ - addbyte(0xc1); /*SHR EDI, 12*/ - addbyte(0xef); - addbyte(12); - addbyte(0x83); /*CMP ESI, -1*/ - addbyte(0xfe); - addbyte(-1); - addbyte(0x74); /*JE slowpath*/ - addbyte(11); - addbyte(0x83); /*CMP writelookup2[EDI*4],-1*/ - addbyte(0x3c); - addbyte(0xbd); - addlong((uint32_t)writelookup2); - addbyte(-1); - addbyte(0x74); /*JE +*/ - addbyte(1); - addbyte(0xc3); /*RET*/ - - /*slowpath:*/ - addbyte(0x8d); /*LEA EDI, [EAX+ESI]*/ - addbyte(0x3c); - addbyte(0x30); - addbyte(0x6a); /*PUSH 1*/ - addbyte(1); - addbyte(0x57); /*PUSH EDI*/ - addbyte(0xe8); /*CALL mmutranslatereal32*/ - addlong((uint32_t)mmutranslatereal32 - (uint32_t)(&codeblock[block_current].data[block_pos + 4])); - addbyte(0x83); /*ADD ESP, 8*/ - addbyte(0xc4); - addbyte(8); - addbyte(0x80); /*CMP abrt, 0*/ - addbyte(0x7d); - addbyte((uint8_t)cpu_state_offset(abrt)); - addbyte(0); - addbyte(0x0f); /*JNE mem_abrt_rout*/ - addbyte(0x85); - addlong(mem_abrt_rout - ((uint32_t)(&codeblock[block_current].data[block_pos]) + 4)); - addbyte(0xc3); /*RET*/ + uint32_t addr = (uint32_t) &codeblock[block_current].data[block_pos]; - return addr; + /*seg = ESI, addr = EAX*/ + + addbyte(0x8d); /*LEA EDI, [EAX+ESI]*/ + addbyte(0x3c); + addbyte(0x30); + addbyte(0x83); /*CMP cr0, 0*/ + addbyte(0x3d); + addlong((uint32_t) &cr0); + addbyte(0); + addbyte(0x78); /*JS +*/ + addbyte(1); + addbyte(0xc3); /*RET*/ + addbyte(0xc1); /*SHR EDI, 12*/ + addbyte(0xef); + addbyte(12); + addbyte(0x83); /*CMP ESI, -1*/ + addbyte(0xfe); + addbyte(-1); + addbyte(0x74); /*JE slowpath*/ + addbyte(11); + addbyte(0x83); /*CMP writelookup2[EDI*4],-1*/ + addbyte(0x3c); + addbyte(0xbd); + addlong((uint32_t) writelookup2); + addbyte(-1); + addbyte(0x74); /*JE +*/ + addbyte(1); + addbyte(0xc3); /*RET*/ + + /*slowpath:*/ + addbyte(0x8d); /*LEA EDI, [EAX+ESI]*/ + addbyte(0x3c); + addbyte(0x30); + addbyte(0x6a); /*PUSH 1*/ + addbyte(1); + addbyte(0x57); /*PUSH EDI*/ + addbyte(0xe8); /*CALL mmutranslatereal32*/ + addlong((uint32_t) mmutranslatereal32 - (uint32_t) (&codeblock[block_current].data[block_pos + 4])); + addbyte(0x83); /*ADD ESP, 8*/ + addbyte(0xc4); + addbyte(8); + addbyte(0x80); /*CMP abrt, 0*/ + addbyte(0x7d); + addbyte((uint8_t) cpu_state_offset(abrt)); + addbyte(0); + addbyte(0x0f); /*JNE mem_abrt_rout*/ + addbyte(0x85); + addlong(mem_abrt_rout - ((uint32_t) (&codeblock[block_current].data[block_pos]) + 4)); + addbyte(0xc3); /*RET*/ + + return addr; } -static uint32_t gen_MEM_CHECK_WRITE_W() +static uint32_t +gen_MEM_CHECK_WRITE_W(void) { - uint32_t addr = (uint32_t)&codeblock[block_current].data[block_pos]; - - /*seg = ESI, addr = EAX*/ - - addbyte(0x8d); /*LEA EDI, [EAX+ESI]*/ - addbyte(0x3c); - addbyte(0x30); - addbyte(0x83); /*CMP cr0, 0*/ - addbyte(0x3d); - addlong((uint32_t)&cr0); - addbyte(0); - addbyte(0x78); /*JS +*/ - addbyte(1); - addbyte(0xc3); /*RET*/ - addbyte(0x83); /*CMP ESI, -1*/ - addbyte(0xfe); - addbyte(-1); - addbyte(0x8d); /*LEA ESI, 1[EDI]*/ - addbyte(0x77); - addbyte(0x01); - addbyte(0x74); /*JE slowpath*/ - addbyte(11); - addbyte(0x89); /*MOV EAX, EDI*/ - addbyte(0xf8); - addbyte(0xc1); /*SHR EDI, 12*/ - addbyte(0xef); - addbyte(12); - addbyte(0xc1); /*SHR ESI, 12*/ - addbyte(0xee); - addbyte(12); - addbyte(0x83); /*CMP writelookup2[EDI*4],-1*/ - addbyte(0x3c); - addbyte(0xbd); - addlong((uint32_t)writelookup2); - addbyte(-1); - addbyte(0x74); /*JE +*/ - addbyte(11); - addbyte(0x83); /*CMP writelookup2[ESI*4],-1*/ - addbyte(0x3c); - addbyte(0xb5); - addlong((uint32_t)writelookup2); - addbyte(-1); - addbyte(0x74); /*JE +*/ - addbyte(1); - addbyte(0xc3); /*RET*/ - - /*slowpath:*/ - addbyte(0x89); /*MOV EDI, EAX*/ - addbyte(0xc7); - /*slowpath_lp:*/ - addbyte(0x6a); /*PUSH 1*/ - addbyte(1); - addbyte(0x57); /*PUSH EDI*/ - addbyte(0xe8); /*CALL mmutranslatereal32*/ - addlong((uint32_t)mmutranslatereal32 - (uint32_t)(&codeblock[block_current].data[block_pos + 4])); - addbyte(0x5f); /*POP EDI*/ - addbyte(0x83); /*ADD ESP, 4*/ - addbyte(0xc4); - addbyte(4); - addbyte(0x83); /*ADD EDI, 1*/ - addbyte(0xc7); - addbyte(1); - addbyte(0x80); /*CMP abrt, 0*/ - addbyte(0x7d); - addbyte((uint8_t)cpu_state_offset(abrt)); - addbyte(0); - addbyte(0x0f); /*JNE mem_abrt_rout*/ - addbyte(0x85); - addlong(mem_abrt_rout - ((uint32_t)(&codeblock[block_current].data[block_pos]) + 4)); - /*If bits 0-11 of the address are now 0 then this crosses a page, so loop back*/ - addbyte(0xf7); /*TEST $fff, EDI*/ - addbyte(0xc7); - addlong(0xfff); - addbyte(0x74); /*JE slowpath_lp*/ - addbyte(-33); - addbyte(0xc3); /*RET*/ + uint32_t addr = (uint32_t) &codeblock[block_current].data[block_pos]; - return addr; + /*seg = ESI, addr = EAX*/ + + addbyte(0x8d); /*LEA EDI, [EAX+ESI]*/ + addbyte(0x3c); + addbyte(0x30); + addbyte(0x83); /*CMP cr0, 0*/ + addbyte(0x3d); + addlong((uint32_t) &cr0); + addbyte(0); + addbyte(0x78); /*JS +*/ + addbyte(1); + addbyte(0xc3); /*RET*/ + addbyte(0x83); /*CMP ESI, -1*/ + addbyte(0xfe); + addbyte(-1); + addbyte(0x8d); /*LEA ESI, 1[EDI]*/ + addbyte(0x77); + addbyte(0x01); + addbyte(0x74); /*JE slowpath*/ + addbyte(11); + addbyte(0x89); /*MOV EAX, EDI*/ + addbyte(0xf8); + addbyte(0xc1); /*SHR EDI, 12*/ + addbyte(0xef); + addbyte(12); + addbyte(0xc1); /*SHR ESI, 12*/ + addbyte(0xee); + addbyte(12); + addbyte(0x83); /*CMP writelookup2[EDI*4],-1*/ + addbyte(0x3c); + addbyte(0xbd); + addlong((uint32_t) writelookup2); + addbyte(-1); + addbyte(0x74); /*JE +*/ + addbyte(11); + addbyte(0x83); /*CMP writelookup2[ESI*4],-1*/ + addbyte(0x3c); + addbyte(0xb5); + addlong((uint32_t) writelookup2); + addbyte(-1); + addbyte(0x74); /*JE +*/ + addbyte(1); + addbyte(0xc3); /*RET*/ + + /*slowpath:*/ + addbyte(0x89); /*MOV EDI, EAX*/ + addbyte(0xc7); + /*slowpath_lp:*/ + addbyte(0x6a); /*PUSH 1*/ + addbyte(1); + addbyte(0x57); /*PUSH EDI*/ + addbyte(0xe8); /*CALL mmutranslatereal32*/ + addlong((uint32_t) mmutranslatereal32 - (uint32_t) (&codeblock[block_current].data[block_pos + 4])); + addbyte(0x5f); /*POP EDI*/ + addbyte(0x83); /*ADD ESP, 4*/ + addbyte(0xc4); + addbyte(4); + addbyte(0x83); /*ADD EDI, 1*/ + addbyte(0xc7); + addbyte(1); + addbyte(0x80); /*CMP abrt, 0*/ + addbyte(0x7d); + addbyte((uint8_t) cpu_state_offset(abrt)); + addbyte(0); + addbyte(0x0f); /*JNE mem_abrt_rout*/ + addbyte(0x85); + addlong(mem_abrt_rout - ((uint32_t) (&codeblock[block_current].data[block_pos]) + 4)); + /*If bits 0-11 of the address are now 0 then this crosses a page, so loop back*/ + addbyte(0xf7); /*TEST $fff, EDI*/ + addbyte(0xc7); + addlong(0xfff); + addbyte(0x74); /*JE slowpath_lp*/ + addbyte(-33); + addbyte(0xc3); /*RET*/ + + return addr; } -static uint32_t gen_MEM_CHECK_WRITE_L() +static uint32_t +gen_MEM_CHECK_WRITE_L(void) { - uint32_t addr = (uint32_t)&codeblock[block_current].data[block_pos]; - - /*seg = ESI, addr = EAX*/ - - addbyte(0x8d); /*LEA EDI, [EAX+ESI]*/ - addbyte(0x3c); - addbyte(0x30); - addbyte(0x83); /*CMP cr0, 0*/ - addbyte(0x3d); - addlong((uint32_t)&cr0); - addbyte(0); - addbyte(0x78); /*JS +*/ - addbyte(1); - addbyte(0xc3); /*RET*/ - addbyte(0x83); /*CMP ESI, -1*/ - addbyte(0xfe); - addbyte(-1); - addbyte(0x8d); /*LEA ESI, 3[EDI]*/ - addbyte(0x77); - addbyte(0x03); - addbyte(0x74); /*JE slowpath*/ - addbyte(11); - addbyte(0x89); /*MOV EAX, EDI*/ - addbyte(0xf8); - addbyte(0xc1); /*SHR EDI, 12*/ - addbyte(0xef); - addbyte(12); - addbyte(0xc1); /*SHR ESI, 12*/ - addbyte(0xee); - addbyte(12); - addbyte(0x83); /*CMP writelookup2[EDI*4],-1*/ - addbyte(0x3c); - addbyte(0xbd); - addlong((uint32_t)writelookup2); - addbyte(-1); - addbyte(0x74); /*JE +*/ - addbyte(11); - addbyte(0x83); /*CMP writelookup2[ESI*4],-1*/ - addbyte(0x3c); - addbyte(0xb5); - addlong((uint32_t)writelookup2); - addbyte(-1); - addbyte(0x74); /*JE +*/ - addbyte(1); - addbyte(0xc3); /*RET*/ - - /*slowpath:*/ - addbyte(0x89); /*MOV EDI, EAX*/ - addbyte(0xc7); - /*slowpath_lp:*/ - addbyte(0x6a); /*PUSH 1*/ - addbyte(1); - addbyte(0x57); /*PUSH EDI*/ - addbyte(0xe8); /*CALL mmutranslatereal32*/ - addlong((uint32_t)mmutranslatereal32 - (uint32_t)(&codeblock[block_current].data[block_pos + 4])); - addbyte(0x5f); /*POP EDI*/ - addbyte(0x83); /*ADD ESP, 4*/ - addbyte(0xc4); - addbyte(4); - addbyte(0x83); /*ADD EDI, 3*/ - addbyte(0xc7); - addbyte(3); - addbyte(0x80); /*CMP abrt, 0*/ - addbyte(0x7d); - addbyte((uint8_t)cpu_state_offset(abrt)); - addbyte(0); - addbyte(0x0f); /*JNE mem_abrt_rout*/ - addbyte(0x85); - addlong(mem_abrt_rout - ((uint32_t)(&codeblock[block_current].data[block_pos]) + 4)); - /*If bits 2-11 of the address are now 0 then this crosses a page, so loop back*/ - addbyte(0xf7); /*TEST EDI, FFC*/ - addbyte(0xc7); - addlong(0xffc); - addbyte(0x74); /*JE slowpath_lp*/ - addbyte(-33); - addbyte(0xc3); /*RET*/ + uint32_t addr = (uint32_t) &codeblock[block_current].data[block_pos]; - return addr; + /*seg = ESI, addr = EAX*/ + + addbyte(0x8d); /*LEA EDI, [EAX+ESI]*/ + addbyte(0x3c); + addbyte(0x30); + addbyte(0x83); /*CMP cr0, 0*/ + addbyte(0x3d); + addlong((uint32_t) &cr0); + addbyte(0); + addbyte(0x78); /*JS +*/ + addbyte(1); + addbyte(0xc3); /*RET*/ + addbyte(0x83); /*CMP ESI, -1*/ + addbyte(0xfe); + addbyte(-1); + addbyte(0x8d); /*LEA ESI, 3[EDI]*/ + addbyte(0x77); + addbyte(0x03); + addbyte(0x74); /*JE slowpath*/ + addbyte(11); + addbyte(0x89); /*MOV EAX, EDI*/ + addbyte(0xf8); + addbyte(0xc1); /*SHR EDI, 12*/ + addbyte(0xef); + addbyte(12); + addbyte(0xc1); /*SHR ESI, 12*/ + addbyte(0xee); + addbyte(12); + addbyte(0x83); /*CMP writelookup2[EDI*4],-1*/ + addbyte(0x3c); + addbyte(0xbd); + addlong((uint32_t) writelookup2); + addbyte(-1); + addbyte(0x74); /*JE +*/ + addbyte(11); + addbyte(0x83); /*CMP writelookup2[ESI*4],-1*/ + addbyte(0x3c); + addbyte(0xb5); + addlong((uint32_t) writelookup2); + addbyte(-1); + addbyte(0x74); /*JE +*/ + addbyte(1); + addbyte(0xc3); /*RET*/ + + /*slowpath:*/ + addbyte(0x89); /*MOV EDI, EAX*/ + addbyte(0xc7); + /*slowpath_lp:*/ + addbyte(0x6a); /*PUSH 1*/ + addbyte(1); + addbyte(0x57); /*PUSH EDI*/ + addbyte(0xe8); /*CALL mmutranslatereal32*/ + addlong((uint32_t) mmutranslatereal32 - (uint32_t) (&codeblock[block_current].data[block_pos + 4])); + addbyte(0x5f); /*POP EDI*/ + addbyte(0x83); /*ADD ESP, 4*/ + addbyte(0xc4); + addbyte(4); + addbyte(0x83); /*ADD EDI, 3*/ + addbyte(0xc7); + addbyte(3); + addbyte(0x80); /*CMP abrt, 0*/ + addbyte(0x7d); + addbyte((uint8_t) cpu_state_offset(abrt)); + addbyte(0); + addbyte(0x0f); /*JNE mem_abrt_rout*/ + addbyte(0x85); + addlong(mem_abrt_rout - ((uint32_t) (&codeblock[block_current].data[block_pos]) + 4)); + /*If bits 2-11 of the address are now 0 then this crosses a page, so loop back*/ + addbyte(0xf7); /*TEST EDI, FFC*/ + addbyte(0xc7); + addlong(0xffc); + addbyte(0x74); /*JE slowpath_lp*/ + addbyte(-33); + addbyte(0xc3); /*RET*/ + + return addr; } -void codegen_init() +void +codegen_init(void) { -#ifdef _WIN32 - codeblock = VirtualAlloc(NULL, (BLOCK_SIZE+1) * sizeof(codeblock_t), MEM_COMMIT, PAGE_EXECUTE_READWRITE); -#elif defined __unix__ - codeblock = mmap(NULL, (BLOCK_SIZE+1) * sizeof(codeblock_t), PROT_READ | PROT_WRITE | PROT_EXEC, MAP_ANON | MAP_PRIVATE, 0, 0); -#else - codeblock = malloc((BLOCK_SIZE+1) * sizeof(codeblock_t)); -#endif - codeblock_hash = malloc(HASH_SIZE * sizeof(codeblock_t *)); +# ifdef _WIN32 + codeblock = VirtualAlloc(NULL, (BLOCK_SIZE + 1) * sizeof(codeblock_t), MEM_COMMIT, PAGE_EXECUTE_READWRITE); +# elif defined __unix__ + codeblock = mmap(NULL, (BLOCK_SIZE + 1) * sizeof(codeblock_t), PROT_READ | PROT_WRITE | PROT_EXEC, MAP_ANON | MAP_PRIVATE, 0, 0); +# else + codeblock = malloc((BLOCK_SIZE + 1) * sizeof(codeblock_t)); +# endif + codeblock_hash = malloc(HASH_SIZE * sizeof(codeblock_t *)); - memset(codeblock, 0, (BLOCK_SIZE+1) * sizeof(codeblock_t)); - memset(codeblock_hash, 0, HASH_SIZE * sizeof(codeblock_t *)); + memset(codeblock, 0, (BLOCK_SIZE + 1) * sizeof(codeblock_t)); + memset(codeblock_hash, 0, HASH_SIZE * sizeof(codeblock_t *)); - block_current = BLOCK_SIZE; - block_pos = 0; - mem_abrt_rout = (uint32_t)&codeblock[block_current].data[block_pos]; - addbyte(0x83); /*ADDL $16+4,%esp*/ - addbyte(0xC4); - addbyte(0x10+4); - addbyte(0x5f); /*POP EDI*/ - addbyte(0x5e); /*POP ESI*/ - addbyte(0x5d); /*POP EBP*/ - addbyte(0x5b); /*POP EDX*/ - addbyte(0xC3); /*RET*/ - block_pos = (block_pos + 15) & ~15; - mem_load_addr_ea_l = (uint32_t)gen_MEM_LOAD_ADDR_EA_L(); - block_pos = (block_pos + 15) & ~15; - mem_load_addr_ea_w = (uint32_t)gen_MEM_LOAD_ADDR_EA_W(); - block_pos = (block_pos + 15) & ~15; - mem_load_addr_ea_b = (uint32_t)gen_MEM_LOAD_ADDR_EA_B(); - block_pos = (block_pos + 15) & ~15; - mem_load_addr_ea_q = (uint32_t)gen_MEM_LOAD_ADDR_EA_Q(); - block_pos = (block_pos + 15) & ~15; - mem_store_addr_ea_l = (uint32_t)gen_MEM_STORE_ADDR_EA_L(); - block_pos = (block_pos + 15) & ~15; - mem_store_addr_ea_w = (uint32_t)gen_MEM_STORE_ADDR_EA_W(); - block_pos = (block_pos + 15) & ~15; - mem_store_addr_ea_b = (uint32_t)gen_MEM_STORE_ADDR_EA_B(); - block_pos = (block_pos + 15) & ~15; - mem_store_addr_ea_q = (uint32_t)gen_MEM_STORE_ADDR_EA_Q(); - block_pos = (block_pos + 15) & ~15; - mem_load_addr_ea_b_no_abrt = (uint32_t)gen_MEM_LOAD_ADDR_EA_B_NO_ABRT(); - block_pos = (block_pos + 15) & ~15; - mem_store_addr_ea_b_no_abrt = (uint32_t)gen_MEM_STORE_ADDR_EA_B_NO_ABRT(); - block_pos = (block_pos + 15) & ~15; - mem_load_addr_ea_w_no_abrt = (uint32_t)gen_MEM_LOAD_ADDR_EA_W_NO_ABRT(); - block_pos = (block_pos + 15) & ~15; - mem_store_addr_ea_w_no_abrt = (uint32_t)gen_MEM_STORE_ADDR_EA_W_NO_ABRT(); - block_pos = (block_pos + 15) & ~15; - mem_load_addr_ea_l_no_abrt = (uint32_t)gen_MEM_LOAD_ADDR_EA_L_NO_ABRT(); - block_pos = (block_pos + 15) & ~15; - mem_store_addr_ea_l_no_abrt = (uint32_t)gen_MEM_STORE_ADDR_EA_L_NO_ABRT(); - block_pos = (block_pos + 15) & ~15; - mem_check_write = (uint32_t)gen_MEM_CHECK_WRITE(); - block_pos = (block_pos + 15) & ~15; - mem_check_write_w = (uint32_t)gen_MEM_CHECK_WRITE_W(); - block_pos = (block_pos + 15) & ~15; - mem_check_write_l = (uint32_t)gen_MEM_CHECK_WRITE_L(); - -#ifndef _MSC_VER - asm( - "fstcw %0\n" - : "=m" (cpu_state.old_npxc) - ); -#else - __asm - { - fstcw cpu_state.old_npxc + block_current = BLOCK_SIZE; + block_pos = 0; + mem_abrt_rout = (uint32_t) &codeblock[block_current].data[block_pos]; + addbyte(0x83); /*ADDL $16+4,%esp*/ + addbyte(0xC4); + addbyte(0x10 + 4); + addbyte(0x5f); /*POP EDI*/ + addbyte(0x5e); /*POP ESI*/ + addbyte(0x5d); /*POP EBP*/ + addbyte(0x5b); /*POP EDX*/ + addbyte(0xC3); /*RET*/ + block_pos = (block_pos + 15) & ~15; + mem_load_addr_ea_l = (uint32_t) gen_MEM_LOAD_ADDR_EA_L(); + block_pos = (block_pos + 15) & ~15; + mem_load_addr_ea_w = (uint32_t) gen_MEM_LOAD_ADDR_EA_W(); + block_pos = (block_pos + 15) & ~15; + mem_load_addr_ea_b = (uint32_t) gen_MEM_LOAD_ADDR_EA_B(); + block_pos = (block_pos + 15) & ~15; + mem_load_addr_ea_q = (uint32_t) gen_MEM_LOAD_ADDR_EA_Q(); + block_pos = (block_pos + 15) & ~15; + mem_store_addr_ea_l = (uint32_t) gen_MEM_STORE_ADDR_EA_L(); + block_pos = (block_pos + 15) & ~15; + mem_store_addr_ea_w = (uint32_t) gen_MEM_STORE_ADDR_EA_W(); + block_pos = (block_pos + 15) & ~15; + mem_store_addr_ea_b = (uint32_t) gen_MEM_STORE_ADDR_EA_B(); + block_pos = (block_pos + 15) & ~15; + mem_store_addr_ea_q = (uint32_t) gen_MEM_STORE_ADDR_EA_Q(); + block_pos = (block_pos + 15) & ~15; + mem_load_addr_ea_b_no_abrt = (uint32_t) gen_MEM_LOAD_ADDR_EA_B_NO_ABRT(); + block_pos = (block_pos + 15) & ~15; + mem_store_addr_ea_b_no_abrt = (uint32_t) gen_MEM_STORE_ADDR_EA_B_NO_ABRT(); + block_pos = (block_pos + 15) & ~15; + mem_load_addr_ea_w_no_abrt = (uint32_t) gen_MEM_LOAD_ADDR_EA_W_NO_ABRT(); + block_pos = (block_pos + 15) & ~15; + mem_store_addr_ea_w_no_abrt = (uint32_t) gen_MEM_STORE_ADDR_EA_W_NO_ABRT(); + block_pos = (block_pos + 15) & ~15; + mem_load_addr_ea_l_no_abrt = (uint32_t) gen_MEM_LOAD_ADDR_EA_L_NO_ABRT(); + block_pos = (block_pos + 15) & ~15; + mem_store_addr_ea_l_no_abrt = (uint32_t) gen_MEM_STORE_ADDR_EA_L_NO_ABRT(); + block_pos = (block_pos + 15) & ~15; + mem_check_write = (uint32_t) gen_MEM_CHECK_WRITE(); + block_pos = (block_pos + 15) & ~15; + mem_check_write_w = (uint32_t) gen_MEM_CHECK_WRITE_W(); + block_pos = (block_pos + 15) & ~15; + mem_check_write_l = (uint32_t) gen_MEM_CHECK_WRITE_L(); + +# ifndef _MSC_VER + asm( + "fstcw %0\n" + : "=m"(cpu_state.old_npxc)); +# else + __asm + { + fstcw cpu_state.old_npxc + } +# endif +} + +void +codegen_reset(void) +{ + memset(codeblock, 0, BLOCK_SIZE * sizeof(codeblock_t)); + memset(codeblock_hash, 0, HASH_SIZE * sizeof(codeblock_t *)); + mem_reset_page_blocks(); +} + +void +dump_block(void) +{ +} + +static void +add_to_block_list(codeblock_t *block) +{ + codeblock_t *block_prev = pages[block->phys >> 12].block[(block->phys >> 10) & 3]; + + if (!block->page_mask) + fatal("add_to_block_list - mask = 0\n"); + + if (block_prev) { + block->next = block_prev; + block_prev->prev = block; + pages[block->phys >> 12].block[(block->phys >> 10) & 3] = block; + } else { + block->next = NULL; + pages[block->phys >> 12].block[(block->phys >> 10) & 3] = block; + } + + if (block->next) { + if (!block->next->valid) + fatal("block->next->valid=0 %p %p %x %x\n", (void *) block->next, (void *) codeblock, block_current, block_pos); + } + + if (block->page_mask2) { + block_prev = pages[block->phys_2 >> 12].block_2[(block->phys_2 >> 10) & 3]; + + if (block_prev) { + block->next_2 = block_prev; + block_prev->prev_2 = block; + pages[block->phys_2 >> 12].block_2[(block->phys_2 >> 10) & 3] = block; + } else { + block->next_2 = NULL; + pages[block->phys_2 >> 12].block_2[(block->phys_2 >> 10) & 3] = block; } -#endif + } } -void codegen_reset() -{ - memset(codeblock, 0, BLOCK_SIZE * sizeof(codeblock_t)); - memset(codeblock_hash, 0, HASH_SIZE * sizeof(codeblock_t *)); - mem_reset_page_blocks(); -} - -void dump_block() -{ -} - -static void add_to_block_list(codeblock_t *block) -{ - codeblock_t *block_prev = pages[block->phys >> 12].block[(block->phys >> 10) & 3]; - - if (!block->page_mask) - fatal("add_to_block_list - mask = 0\n"); - - if (block_prev) - { - block->next = block_prev; - block_prev->prev = block; - pages[block->phys >> 12].block[(block->phys >> 10) & 3] = block; - } - else - { - block->next = NULL; - pages[block->phys >> 12].block[(block->phys >> 10) & 3] = block; - } - - if (block->next) - { - if (!block->next->valid) - fatal("block->next->valid=0 %p %p %x %x\n", (void *)block->next, (void *)codeblock, block_current, block_pos); - } - - if (block->page_mask2) - { - block_prev = pages[block->phys_2 >> 12].block_2[(block->phys_2 >> 10) & 3]; - - if (block_prev) - { - block->next_2 = block_prev; - block_prev->prev_2 = block; - pages[block->phys_2 >> 12].block_2[(block->phys_2 >> 10) & 3] = block; - } - else - { - block->next_2 = NULL; - pages[block->phys_2 >> 12].block_2[(block->phys_2 >> 10) & 3] = block; - } - } -} - -static void remove_from_block_list(codeblock_t *block, uint32_t pc) -{ - if (!block->page_mask) - return; - - if (block->prev) - { - block->prev->next = block->next; - if (block->next) - block->next->prev = block->prev; - } - else - { - pages[block->phys >> 12].block[(block->phys >> 10) & 3] = block->next; - if (block->next) - block->next->prev = NULL; - else - mem_flush_write_page(block->phys, 0); - } - if (!block->page_mask2) - { - if (block->prev_2 || block->next_2) - fatal("Invalid block_2\n"); - return; - } - - if (block->prev_2) - { - block->prev_2->next_2 = block->next_2; - if (block->next_2) - block->next_2->prev_2 = block->prev_2; - } - else - { - pages[block->phys_2 >> 12].block_2[(block->phys_2 >> 10) & 3] = block->next_2; - if (block->next_2) - block->next_2->prev_2 = NULL; - else - mem_flush_write_page(block->phys_2, 0); - } -} - -static void delete_block(codeblock_t *block) -{ - uint32_t old_pc = block->pc; - - if (block == codeblock_hash[HASH(block->phys)]) - codeblock_hash[HASH(block->phys)] = NULL; - - if (!block->valid) - fatal("Deleting deleted block\n"); - block->valid = 0; - - codeblock_tree_delete(block); - remove_from_block_list(block, old_pc); -} - -void codegen_check_flush(page_t *page, uint64_t mask, uint32_t phys_addr) -{ - struct codeblock_t *block = page->block[(phys_addr >> 10) & 3]; - - while (block) - { - if (mask & block->page_mask) - { - delete_block(block); - } - if (block == block->next) - fatal("Broken 1\n"); - block = block->next; - } - - block = page->block_2[(phys_addr >> 10) & 3]; - - while (block) - { - if (mask & block->page_mask2) - { - delete_block(block); - } - if (block == block->next_2) - fatal("Broken 2\n"); - block = block->next_2; - } -} - -void codegen_block_init(uint32_t phys_addr) -{ - codeblock_t *block; - page_t *page = &pages[phys_addr >> 12]; - - if (!page->block[(phys_addr >> 10) & 3]) - mem_flush_write_page(phys_addr, cs+cpu_state.pc); - - block_current = (block_current + 1) & BLOCK_MASK; - block = &codeblock[block_current]; - - if (block->valid != 0) - { - delete_block(block); - } - block_num = HASH(phys_addr); - codeblock_hash[block_num] = &codeblock[block_current]; - - block->valid = 1; - block->ins = 0; - block->pc = cs + cpu_state.pc; - block->_cs = cs; - block->pnt = block_current; - block->phys = phys_addr; - block->dirty_mask = &page->dirty_mask[(phys_addr >> PAGE_MASK_INDEX_SHIFT) & PAGE_MASK_INDEX_MASK]; - block->dirty_mask2 = NULL; - block->next = block->prev = NULL; - block->next_2 = block->prev_2 = NULL; - block->page_mask = 0; - block->flags = CODEBLOCK_STATIC_TOP; - block->status = cpu_cur_status; - - block->was_recompiled = 0; - - recomp_page = block->phys & ~0xfff; - - codeblock_tree_add(block); -} - -void codegen_block_start_recompile(codeblock_t *block) -{ - page_t *page = &pages[block->phys >> 12]; - - if (!page->block[(block->phys >> 10) & 3]) - mem_flush_write_page(block->phys, cs+cpu_state.pc); - - block_num = HASH(block->phys); - block_current = block->pnt; - - if (block->pc != cs + cpu_state.pc || block->was_recompiled) - fatal("Recompile to used block!\n"); - - block->status = cpu_cur_status; - - block_pos = BLOCK_GPF_OFFSET; -#ifdef OLD_GPF - addbyte(0xc7); /*MOV [ESP],0*/ - addbyte(0x04); - addbyte(0x24); - addlong(0); - addbyte(0xc7); /*MOV [ESP+4],0*/ - addbyte(0x44); - addbyte(0x24); - addbyte(0x04); - addlong(0); - addbyte(0xe8); /*CALL x86gpf*/ - addlong((uint32_t)x86gpf - (uint32_t)(&codeblock[block_current].data[block_pos + 4])); -#else - addbyte(0xc6); /* mov byte ptr[&(cpu_state.abrt)],ABRT_GPF */ - addbyte(0x05); - addlong((uint32_t) (uintptr_t) &(cpu_state.abrt)); - addbyte(ABRT_GPF); - addbyte(0x31); /* xor eax,eax */ - addbyte(0xc0); - addbyte(0xa3); /* mov [&(abrt_error)],eax */ - addlong((uint32_t) (uintptr_t) &(abrt_error)); -#endif - block_pos = BLOCK_EXIT_OFFSET; /*Exit code*/ - addbyte(0x83); /*ADDL $16,%esp*/ - addbyte(0xC4); - addbyte(0x10); - addbyte(0x5f); /*POP EDI*/ - addbyte(0x5e); /*POP ESI*/ - addbyte(0x5d); /*POP EBP*/ - addbyte(0x5b); /*POP EDX*/ - addbyte(0xC3); /*RET*/ - cpu_block_end = 0; - block_pos = 0; /*Entry code*/ - addbyte(0x53); /*PUSH EBX*/ - addbyte(0x55); /*PUSH EBP*/ - addbyte(0x56); /*PUSH ESI*/ - addbyte(0x57); /*PUSH EDI*/ - addbyte(0x83); /*SUBL $16,%esp*/ - addbyte(0xEC); - addbyte(0x10); - addbyte(0xBD); /*MOVL EBP, &cpu_state*/ - addlong(((uintptr_t)&cpu_state) + 128); - - last_op32 = -1; - last_ea_seg = NULL; - last_ssegs = -1; - - codegen_block_cycles = 0; - codegen_timing_block_start(); - - codegen_block_ins = 0; - codegen_block_full_ins = 0; - - recomp_page = block->phys & ~0xfff; - - codegen_flags_changed = 0; - codegen_fpu_entered = 0; - codegen_mmx_entered = 0; - - codegen_fpu_loaded_iq[0] = codegen_fpu_loaded_iq[1] = codegen_fpu_loaded_iq[2] = codegen_fpu_loaded_iq[3] = - codegen_fpu_loaded_iq[4] = codegen_fpu_loaded_iq[5] = codegen_fpu_loaded_iq[6] = codegen_fpu_loaded_iq[7] = 0; - - cpu_state.seg_ds.checked = cpu_state.seg_es.checked = cpu_state.seg_fs.checked = cpu_state.seg_gs.checked = (cr0 & 1) ? 0 : 1; - - block->TOP = cpu_state.TOP & 7; - block->was_recompiled = 1; - - codegen_flat_ds = !(cpu_cur_status & CPU_STATUS_NOTFLATDS); - codegen_flat_ss = !(cpu_cur_status & CPU_STATUS_NOTFLATSS); - - codegen_accumulate_reset(); -} - -void codegen_block_remove() -{ - codeblock_t *block = &codeblock[block_current]; - - delete_block(block); - - recomp_page = -1; -} - -void codegen_block_generate_end_mask() -{ - codeblock_t *block = &codeblock[block_current]; - uint32_t start_pc; - uint32_t end_pc; - - block->endpc = codegen_endpc; - - block->page_mask = 0; - start_pc = (block->pc & 0x3ff) & ~15; - if ((block->pc ^ block->endpc) & ~0x3ff) - end_pc = 0x3ff & ~15; - else - end_pc = (block->endpc & 0x3ff) & ~15; - if (end_pc < start_pc) - end_pc = 0x3ff; - start_pc >>= PAGE_MASK_SHIFT; - end_pc >>= PAGE_MASK_SHIFT; - - for (; start_pc <= end_pc; start_pc++) - { - block->page_mask |= ((uint64_t)1 << start_pc); - } - - pages[block->phys >> 12].code_present_mask[(block->phys >> 10) & 3] |= block->page_mask; - - block->phys_2 = -1; - block->page_mask2 = 0; - block->next_2 = block->prev_2 = NULL; - if ((block->pc ^ block->endpc) & ~0x3ff) - { - block->phys_2 = get_phys_noabrt(block->endpc); - if (block->phys_2 != -1) - { - page_t *page_2 = &pages[block->phys_2 >> 12]; - - start_pc = 0; - end_pc = (block->endpc & 0x3ff) >> PAGE_MASK_SHIFT; - for (; start_pc <= end_pc; start_pc++) - block->page_mask2 |= ((uint64_t)1 << start_pc); - page_2->code_present_mask[(block->phys_2 >> 10) & 3] |= block->page_mask2; - - if (!pages[block->phys_2 >> 12].block_2[(block->phys_2 >> 10) & 3]) - mem_flush_write_page(block->phys_2, block->endpc); - - if (!block->page_mask2) - fatal("!page_mask2\n"); - if (block->next_2) - { - if (!block->next_2->valid) - fatal("block->next_2->valid=0 %p\n", (void *)block->next_2); - } - - block->dirty_mask2 = &page_2->dirty_mask[(block->phys_2 >> PAGE_MASK_INDEX_SHIFT) & PAGE_MASK_INDEX_MASK]; - } - } - - recomp_page = -1; -} - -void codegen_block_end() -{ - codeblock_t *block = &codeblock[block_current]; - - codegen_block_generate_end_mask(); - add_to_block_list(block); -} - -void codegen_block_end_recompile(codeblock_t *block) -{ - codegen_timing_block_end(); - codegen_accumulate(ACCREG_cycles, -codegen_block_cycles); - - codegen_accumulate_flush(); - - addbyte(0x83); /*ADDL $16,%esp*/ - addbyte(0xC4); - addbyte(0x10); - addbyte(0x5f); /*POP EDI*/ - addbyte(0x5e); /*POP ESI*/ - addbyte(0x5d); /*POP EBP*/ - addbyte(0x5b); /*POP EDX*/ - addbyte(0xC3); /*RET*/ - - if (block_pos > BLOCK_GPF_OFFSET) - fatal("Over limit!\n"); - - remove_from_block_list(block, block->pc); - block->next = block->prev = NULL; - block->next_2 = block->prev_2 = NULL; - codegen_block_generate_end_mask(); - add_to_block_list(block); - - if (!(block->flags & CODEBLOCK_HAS_FPU)) - block->flags &= ~CODEBLOCK_STATIC_TOP; -} - -void codegen_flush() +static void +remove_from_block_list(codeblock_t *block, uint32_t pc) { + if (!block->page_mask) return; -} -static int opcode_modrm[256] = -{ - 1, 1, 1, 1, 0, 0, 0, 0, 1, 1, 1, 1, 0, 0, 0, 0, /*00*/ - 1, 1, 1, 1, 0, 0, 0, 0, 1, 1, 1, 1, 0, 0, 0, 0, /*10*/ - 1, 1, 1, 1, 0, 0, 0, 0, 1, 1, 1, 1, 0, 0, 0, 0, /*20*/ - 1, 1, 1, 1, 0, 0, 0, 0, 1, 1, 1, 1, 0, 0, 0, 0, /*30*/ - - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /*40*/ - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /*50*/ - 0, 0, 1, 1, 0, 0, 0, 0, 0, 1, 0, 1, 0, 0, 0, 0, /*60*/ - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /*70*/ - - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /*80*/ - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /*90*/ - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /*a0*/ - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /*b0*/ - - 1, 1, 0, 0, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, /*c0*/ - 1, 1, 1, 1, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, /*d0*/ - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /*e0*/ - 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 1, 1, /*f0*/ -}; -int opcode_0f_modrm[256] = -{ - 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, /*00*/ - 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, /*10*/ - 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /*20*/ - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, /*30*/ - - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /*40*/ - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /*50*/ - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 1, 1, /*60*/ - 0, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 1, 1, /*70*/ - - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /*80*/ - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /*90*/ - 0, 0, 0, 1, 1, 1, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, /*a0*/ - 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 1, 1, 1, 1, 1, 1, /*b0*/ - - 1, 1, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, /*c0*/ - 0, 1, 1, 1, 0, 1, 0, 0, 1, 1, 0, 1, 1, 1, 0, 1, /*d0*/ - 0, 1, 1, 0, 0, 1, 0, 0, 1, 1, 0, 1, 1, 1, 0, 1, /*e0*/ - 0, 1, 1, 1, 0, 1, 0, 0, 1, 1, 1, 0, 1, 1, 1, 0 /*f0*/ -}; - -void codegen_debug() -{ -} - -static x86seg *codegen_generate_ea_16_long(x86seg *op_ea_seg, uint32_t fetchdat, int op_ssegs, uint32_t *op_pc) -{ - if (!cpu_mod && cpu_rm == 6) - { - addbyte(0xC7); /*MOVL $0,(ssegs)*/ - addbyte(0x45); - addbyte((uint8_t)cpu_state_offset(eaaddr)); - addlong((fetchdat >> 8) & 0xffff); - (*op_pc) += 2; - } + if (block->prev) { + block->prev->next = block->next; + if (block->next) + block->next->prev = block->prev; + } else { + pages[block->phys >> 12].block[(block->phys >> 10) & 3] = block->next; + if (block->next) + block->next->prev = NULL; else - { - switch (cpu_mod) - { - case 0: - addbyte(0xa1); /*MOVL *mod1add[0][cpu_rm], %eax*/ - addlong((uint32_t)mod1add[0][cpu_rm]); - addbyte(0x03); /*ADDL *mod1add[1][cpu_rm], %eax*/ - addbyte(0x05); - addlong((uint32_t)mod1add[1][cpu_rm]); - break; - case 1: - addbyte(0xb8); /*MOVL ,%eax*/ - addlong((uint32_t)(int8_t)(rmdat >> 8)); - addbyte(0x03); /*ADDL *mod1add[0][cpu_rm], %eax*/ - addbyte(0x05); - addlong((uint32_t)mod1add[0][cpu_rm]); - addbyte(0x03); /*ADDL *mod1add[1][cpu_rm], %eax*/ - addbyte(0x05); - addlong((uint32_t)mod1add[1][cpu_rm]); - (*op_pc)++; - break; - case 2: - addbyte(0xb8); /*MOVL ,%eax*/ - addlong((fetchdat >> 8) & 0xffff); - addbyte(0x03); /*ADDL *mod1add[0][cpu_rm], %eax*/ - addbyte(0x05); - addlong((uint32_t)mod1add[0][cpu_rm]); - addbyte(0x03); /*ADDL *mod1add[1][cpu_rm], %eax*/ - addbyte(0x05); - addlong((uint32_t)mod1add[1][cpu_rm]); - (*op_pc) += 2; - break; - } - addbyte(0x25); /*ANDL $0xffff, %eax*/ - addlong(0xffff); - addbyte(0xa3); - addlong((uint32_t)&cpu_state.eaaddr); + mem_flush_write_page(block->phys, 0); + } + if (!block->page_mask2) { + if (block->prev_2 || block->next_2) + fatal("Invalid block_2\n"); + return; + } - if (mod1seg[cpu_rm] == &ss && !op_ssegs) - op_ea_seg = &cpu_state.seg_ss; - } - return op_ea_seg; + if (block->prev_2) { + block->prev_2->next_2 = block->next_2; + if (block->next_2) + block->next_2->prev_2 = block->prev_2; + } else { + pages[block->phys_2 >> 12].block_2[(block->phys_2 >> 10) & 3] = block->next_2; + if (block->next_2) + block->next_2->prev_2 = NULL; + else + mem_flush_write_page(block->phys_2, 0); + } } -static x86seg *codegen_generate_ea_32_long(x86seg *op_ea_seg, uint32_t fetchdat, int op_ssegs, uint32_t *op_pc, int stack_offset) +static void +delete_block(codeblock_t *block) { - uint32_t new_eaaddr; + uint32_t old_pc = block->pc; - if (cpu_rm == 4) - { - uint8_t sib = fetchdat >> 8; + if (block == codeblock_hash[HASH(block->phys)]) + codeblock_hash[HASH(block->phys)] = NULL; + + if (!block->valid) + fatal("Deleting deleted block\n"); + block->valid = 0; + + codeblock_tree_delete(block); + remove_from_block_list(block, old_pc); +} + +void +codegen_check_flush(page_t *page, uint64_t mask, uint32_t phys_addr) +{ + struct codeblock_t *block = page->block[(phys_addr >> 10) & 3]; + + while (block) { + if (mask & block->page_mask) { + delete_block(block); + } + if (block == block->next) + fatal("Broken 1\n"); + block = block->next; + } + + block = page->block_2[(phys_addr >> 10) & 3]; + + while (block) { + if (mask & block->page_mask2) { + delete_block(block); + } + if (block == block->next_2) + fatal("Broken 2\n"); + block = block->next_2; + } +} + +void +codegen_block_init(uint32_t phys_addr) +{ + codeblock_t *block; + page_t *page = &pages[phys_addr >> 12]; + + if (!page->block[(phys_addr >> 10) & 3]) + mem_flush_write_page(phys_addr, cs + cpu_state.pc); + + block_current = (block_current + 1) & BLOCK_MASK; + block = &codeblock[block_current]; + + if (block->valid != 0) { + delete_block(block); + } + block_num = HASH(phys_addr); + codeblock_hash[block_num] = &codeblock[block_current]; + + block->valid = 1; + block->ins = 0; + block->pc = cs + cpu_state.pc; + block->_cs = cs; + block->pnt = block_current; + block->phys = phys_addr; + block->dirty_mask = &page->dirty_mask[(phys_addr >> PAGE_MASK_INDEX_SHIFT) & PAGE_MASK_INDEX_MASK]; + block->dirty_mask2 = NULL; + block->next = block->prev = NULL; + block->next_2 = block->prev_2 = NULL; + block->page_mask = 0; + block->flags = CODEBLOCK_STATIC_TOP; + block->status = cpu_cur_status; + + block->was_recompiled = 0; + + recomp_page = block->phys & ~0xfff; + + codeblock_tree_add(block); +} + +void +codegen_block_start_recompile(codeblock_t *block) +{ + page_t *page = &pages[block->phys >> 12]; + + if (!page->block[(block->phys >> 10) & 3]) + mem_flush_write_page(block->phys, cs + cpu_state.pc); + + block_num = HASH(block->phys); + block_current = block->pnt; + + if (block->pc != cs + cpu_state.pc || block->was_recompiled) + fatal("Recompile to used block!\n"); + + block->status = cpu_cur_status; + + block_pos = BLOCK_GPF_OFFSET; +# ifdef OLD_GPF + addbyte(0xc7); /*MOV [ESP],0*/ + addbyte(0x04); + addbyte(0x24); + addlong(0); + addbyte(0xc7); /*MOV [ESP+4],0*/ + addbyte(0x44); + addbyte(0x24); + addbyte(0x04); + addlong(0); + addbyte(0xe8); /*CALL x86gpf*/ + addlong((uint32_t) x86gpf - (uint32_t) (&codeblock[block_current].data[block_pos + 4])); +# else + addbyte(0xc6); /* mov byte ptr[&(cpu_state.abrt)],ABRT_GPF */ + addbyte(0x05); + addlong((uint32_t) (uintptr_t) & (cpu_state.abrt)); + addbyte(ABRT_GPF); + addbyte(0x31); /* xor eax,eax */ + addbyte(0xc0); + addbyte(0xa3); /* mov [&(abrt_error)],eax */ + addlong((uint32_t) (uintptr_t) & (abrt_error)); +# endif + block_pos = BLOCK_EXIT_OFFSET; /*Exit code*/ + addbyte(0x83); /*ADDL $16,%esp*/ + addbyte(0xC4); + addbyte(0x10); + addbyte(0x5f); /*POP EDI*/ + addbyte(0x5e); /*POP ESI*/ + addbyte(0x5d); /*POP EBP*/ + addbyte(0x5b); /*POP EDX*/ + addbyte(0xC3); /*RET*/ + cpu_block_end = 0; + block_pos = 0; /*Entry code*/ + addbyte(0x53); /*PUSH EBX*/ + addbyte(0x55); /*PUSH EBP*/ + addbyte(0x56); /*PUSH ESI*/ + addbyte(0x57); /*PUSH EDI*/ + addbyte(0x83); /*SUBL $16,%esp*/ + addbyte(0xEC); + addbyte(0x10); + addbyte(0xBD); /*MOVL EBP, &cpu_state*/ + addlong(((uintptr_t) &cpu_state) + 128); + + last_op32 = -1; + last_ea_seg = NULL; + last_ssegs = -1; + + codegen_block_cycles = 0; + codegen_timing_block_start(); + + codegen_block_ins = 0; + codegen_block_full_ins = 0; + + recomp_page = block->phys & ~0xfff; + + codegen_flags_changed = 0; + codegen_fpu_entered = 0; + codegen_mmx_entered = 0; + + codegen_fpu_loaded_iq[0] = codegen_fpu_loaded_iq[1] = codegen_fpu_loaded_iq[2] = codegen_fpu_loaded_iq[3] = codegen_fpu_loaded_iq[4] = codegen_fpu_loaded_iq[5] = codegen_fpu_loaded_iq[6] = codegen_fpu_loaded_iq[7] = 0; + + cpu_state.seg_ds.checked = cpu_state.seg_es.checked = cpu_state.seg_fs.checked = cpu_state.seg_gs.checked = (cr0 & 1) ? 0 : 1; + + block->TOP = cpu_state.TOP & 7; + block->was_recompiled = 1; + + codegen_flat_ds = !(cpu_cur_status & CPU_STATUS_NOTFLATDS); + codegen_flat_ss = !(cpu_cur_status & CPU_STATUS_NOTFLATSS); + + codegen_accumulate_reset(); +} + +void +codegen_block_remove(void) +{ + codeblock_t *block = &codeblock[block_current]; + + delete_block(block); + + recomp_page = -1; +} + +void +codegen_block_generate_end_mask(void) +{ + codeblock_t *block = &codeblock[block_current]; + uint32_t start_pc; + uint32_t end_pc; + + block->endpc = codegen_endpc; + + block->page_mask = 0; + start_pc = (block->pc & 0x3ff) & ~15; + if ((block->pc ^ block->endpc) & ~0x3ff) + end_pc = 0x3ff & ~15; + else + end_pc = (block->endpc & 0x3ff) & ~15; + if (end_pc < start_pc) + end_pc = 0x3ff; + start_pc >>= PAGE_MASK_SHIFT; + end_pc >>= PAGE_MASK_SHIFT; + + for (; start_pc <= end_pc; start_pc++) { + block->page_mask |= ((uint64_t) 1 << start_pc); + } + + pages[block->phys >> 12].code_present_mask[(block->phys >> 10) & 3] |= block->page_mask; + + block->phys_2 = -1; + block->page_mask2 = 0; + block->next_2 = block->prev_2 = NULL; + if ((block->pc ^ block->endpc) & ~0x3ff) { + block->phys_2 = get_phys_noabrt(block->endpc); + if (block->phys_2 != -1) { + page_t *page_2 = &pages[block->phys_2 >> 12]; + + start_pc = 0; + end_pc = (block->endpc & 0x3ff) >> PAGE_MASK_SHIFT; + for (; start_pc <= end_pc; start_pc++) + block->page_mask2 |= ((uint64_t) 1 << start_pc); + page_2->code_present_mask[(block->phys_2 >> 10) & 3] |= block->page_mask2; + + if (!pages[block->phys_2 >> 12].block_2[(block->phys_2 >> 10) & 3]) + mem_flush_write_page(block->phys_2, block->endpc); + + if (!block->page_mask2) + fatal("!page_mask2\n"); + if (block->next_2) { + if (!block->next_2->valid) + fatal("block->next_2->valid=0 %p\n", (void *) block->next_2); + } + + block->dirty_mask2 = &page_2->dirty_mask[(block->phys_2 >> PAGE_MASK_INDEX_SHIFT) & PAGE_MASK_INDEX_MASK]; + } + } + + recomp_page = -1; +} + +void +codegen_block_end(void) +{ + codeblock_t *block = &codeblock[block_current]; + + codegen_block_generate_end_mask(); + add_to_block_list(block); +} + +void +codegen_block_end_recompile(codeblock_t *block) +{ + codegen_timing_block_end(); + codegen_accumulate(ACCREG_cycles, -codegen_block_cycles); + + codegen_accumulate_flush(); + + addbyte(0x83); /*ADDL $16,%esp*/ + addbyte(0xC4); + addbyte(0x10); + addbyte(0x5f); /*POP EDI*/ + addbyte(0x5e); /*POP ESI*/ + addbyte(0x5d); /*POP EBP*/ + addbyte(0x5b); /*POP EDX*/ + addbyte(0xC3); /*RET*/ + + if (block_pos > BLOCK_GPF_OFFSET) + fatal("Over limit!\n"); + + remove_from_block_list(block, block->pc); + block->next = block->prev = NULL; + block->next_2 = block->prev_2 = NULL; + codegen_block_generate_end_mask(); + add_to_block_list(block); + + if (!(block->flags & CODEBLOCK_HAS_FPU)) + block->flags &= ~CODEBLOCK_STATIC_TOP; +} + +void +codegen_flush(void) +{ + return; +} + +// clang-format off +static int opcode_modrm[256] = { + 1, 1, 1, 1, 0, 0, 0, 0, 1, 1, 1, 1, 0, 0, 0, 0, /*00*/ + 1, 1, 1, 1, 0, 0, 0, 0, 1, 1, 1, 1, 0, 0, 0, 0, /*10*/ + 1, 1, 1, 1, 0, 0, 0, 0, 1, 1, 1, 1, 0, 0, 0, 0, /*20*/ + 1, 1, 1, 1, 0, 0, 0, 0, 1, 1, 1, 1, 0, 0, 0, 0, /*30*/ + + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /*40*/ + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /*50*/ + 0, 0, 1, 1, 0, 0, 0, 0, 0, 1, 0, 1, 0, 0, 0, 0, /*60*/ + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /*70*/ + + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /*80*/ + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /*90*/ + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /*a0*/ + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /*b0*/ + + 1, 1, 0, 0, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, /*c0*/ + 1, 1, 1, 1, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, /*d0*/ + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /*e0*/ + 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 1, 1, /*f0*/ +}; + +int opcode_0f_modrm[256] = { + 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, /*00*/ + 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, /*10*/ + 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /*20*/ + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, /*30*/ + + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /*40*/ + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /*50*/ + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 1, 1, /*60*/ + 0, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 1, 1, /*70*/ + + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /*80*/ + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /*90*/ + 0, 0, 0, 1, 1, 1, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, /*a0*/ + 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 1, 1, 1, 1, 1, 1, /*b0*/ + + 1, 1, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, /*c0*/ + 0, 1, 1, 1, 0, 1, 0, 0, 1, 1, 0, 1, 1, 1, 0, 1, /*d0*/ + 0, 1, 1, 0, 0, 1, 0, 0, 1, 1, 0, 1, 1, 1, 0, 1, /*e0*/ + 0, 1, 1, 1, 0, 1, 0, 0, 1, 1, 1, 0, 1, 1, 1, 0 /*f0*/ +}; +// clang-format on + +void +codegen_debug(void) +{ + // +} + +static x86seg * +codegen_generate_ea_16_long(x86seg *op_ea_seg, uint32_t fetchdat, int op_ssegs, uint32_t *op_pc) +{ + if (!cpu_mod && cpu_rm == 6) { + addbyte(0xC7); /*MOVL $0,(ssegs)*/ + addbyte(0x45); + addbyte((uint8_t) cpu_state_offset(eaaddr)); + addlong((fetchdat >> 8) & 0xffff); + (*op_pc) += 2; + } else { + switch (cpu_mod) { + case 0: + addbyte(0xa1); /*MOVL *mod1add[0][cpu_rm], %eax*/ + addlong((uint32_t) mod1add[0][cpu_rm]); + addbyte(0x03); /*ADDL *mod1add[1][cpu_rm], %eax*/ + addbyte(0x05); + addlong((uint32_t) mod1add[1][cpu_rm]); + break; + case 1: + addbyte(0xb8); /*MOVL ,%eax*/ + addlong((uint32_t) (int8_t) (rmdat >> 8)); + addbyte(0x03); /*ADDL *mod1add[0][cpu_rm], %eax*/ + addbyte(0x05); + addlong((uint32_t) mod1add[0][cpu_rm]); + addbyte(0x03); /*ADDL *mod1add[1][cpu_rm], %eax*/ + addbyte(0x05); + addlong((uint32_t) mod1add[1][cpu_rm]); (*op_pc)++; - - switch (cpu_mod) - { - case 0: - if ((sib & 7) == 5) - { - new_eaaddr = fastreadl(cs + (*op_pc) + 1); - addbyte(0xb8); /*MOVL ,%eax*/ - addlong(new_eaaddr); - (*op_pc) += 4; - } - else - { - addbyte(0x8b); /*MOVL regs[sib&7].l, %eax*/ - addbyte(0x45); - addbyte((uint8_t)cpu_state_offset(regs[sib & 7].l)); - } - break; - case 1: - new_eaaddr = (uint32_t)(int8_t)((fetchdat >> 16) & 0xff); - addbyte(0xb8); /*MOVL new_eaaddr, %eax*/ - addlong(new_eaaddr); - addbyte(0x03); /*ADDL regs[sib&7].l, %eax*/ - addbyte(0x45); - addbyte((uint8_t)cpu_state_offset(regs[sib & 7].l)); - (*op_pc)++; - break; - case 2: - new_eaaddr = fastreadl(cs + (*op_pc) + 1); - addbyte(0xb8); /*MOVL new_eaaddr, %eax*/ - addlong(new_eaaddr); - addbyte(0x03); /*ADDL regs[sib&7].l, %eax*/ - addbyte(0x45); - addbyte((uint8_t)cpu_state_offset(regs[sib & 7].l)); - (*op_pc) += 4; - break; - } - if (stack_offset && (sib & 7) == 4 && (cpu_mod || (sib & 7) != 5)) /*ESP*/ - { - addbyte(0x05); - addlong(stack_offset); - } - if (((sib & 7) == 4 || (cpu_mod && (sib & 7) == 5)) && !op_ssegs) - op_ea_seg = &cpu_state.seg_ss; - if (((sib >> 3) & 7) != 4) - { - switch (sib >> 6) - { - case 0: - addbyte(0x03); /*ADDL regs[sib&7].l, %eax*/ - addbyte(0x45); - addbyte((uint8_t)cpu_state_offset(regs[(sib >> 3) & 7].l)); - break; - case 1: - addbyte(0x8B); addbyte(0x5D); addbyte((uint8_t)cpu_state_offset(regs[(sib >> 3) & 7].l)); /*MOVL armregs[RD],%ebx*/ - addbyte(0x01); addbyte(0xD8); /*ADDL %ebx,%eax*/ - addbyte(0x01); addbyte(0xD8); /*ADDL %ebx,%eax*/ - break; - case 2: - addbyte(0x8B); addbyte(0x5D); addbyte((uint8_t)cpu_state_offset(regs[(sib >> 3) & 7].l)); /*MOVL armregs[RD],%ebx*/ - addbyte(0xC1); addbyte(0xE3); addbyte(2); /*SHL $2,%ebx*/ - addbyte(0x01); addbyte(0xD8); /*ADDL %ebx,%eax*/ - break; - case 3: - addbyte(0x8B); addbyte(0x5D); addbyte((uint8_t)cpu_state_offset(regs[(sib >> 3) & 7].l)); /*MOVL armregs[RD],%ebx*/ - addbyte(0xC1); addbyte(0xE3); addbyte(3); /*SHL $2,%ebx*/ - addbyte(0x01); addbyte(0xD8); /*ADDL %ebx,%eax*/ - break; - } - } - addbyte(0xa3); - addlong((uint32_t)&cpu_state.eaaddr); + break; + case 2: + addbyte(0xb8); /*MOVL ,%eax*/ + addlong((fetchdat >> 8) & 0xffff); + addbyte(0x03); /*ADDL *mod1add[0][cpu_rm], %eax*/ + addbyte(0x05); + addlong((uint32_t) mod1add[0][cpu_rm]); + addbyte(0x03); /*ADDL *mod1add[1][cpu_rm], %eax*/ + addbyte(0x05); + addlong((uint32_t) mod1add[1][cpu_rm]); + (*op_pc) += 2; + break; } - else - { - if (!cpu_mod && cpu_rm == 5) - { - new_eaaddr = fastreadl(cs + (*op_pc) + 1); - addbyte(0xC7); /*MOVL $new_eaaddr,(eaaddr)*/ - addbyte(0x45); - addbyte((uint8_t)cpu_state_offset(eaaddr)); - addlong(new_eaaddr); - (*op_pc) += 4; - return op_ea_seg; - } - addbyte(0x8b); /*MOVL regs[sib&7].l, %eax*/ - addbyte(0x45); - addbyte((uint8_t)cpu_state_offset(regs[cpu_rm].l)); - cpu_state.eaaddr = cpu_state.regs[cpu_rm].l; - if (cpu_mod) - { - if (cpu_rm == 5 && !op_ssegs) - op_ea_seg = &cpu_state.seg_ss; - if (cpu_mod == 1) - { - addbyte(0x05); - addlong((uint32_t)(int8_t)(fetchdat >> 8)); - (*op_pc)++; - } - else - { - new_eaaddr = fastreadl(cs + (*op_pc) + 1); - addbyte(0x05); - addlong(new_eaaddr); - (*op_pc) += 4; - } - } - addbyte(0xa3); - addlong((uint32_t)&cpu_state.eaaddr); - } - return op_ea_seg; + addbyte(0x25); /*ANDL $0xffff, %eax*/ + addlong(0xffff); + addbyte(0xa3); + addlong((uint32_t) &cpu_state.eaaddr); + + if (mod1seg[cpu_rm] == &ss && !op_ssegs) + op_ea_seg = &cpu_state.seg_ss; + } + return op_ea_seg; } -void codegen_generate_call(uint8_t opcode, OpFn op, uint32_t fetchdat, uint32_t new_pc, uint32_t old_pc) +static x86seg * +codegen_generate_ea_32_long(x86seg *op_ea_seg, uint32_t fetchdat, int op_ssegs, uint32_t *op_pc, int stack_offset) { - codeblock_t *block = &codeblock[block_current]; - uint32_t op_32 = use32; - uint32_t op_pc = new_pc; - const OpFn *op_table = x86_dynarec_opcodes; - RecompOpFn *recomp_op_table = recomp_opcodes; - int opcode_shift = 0; - int opcode_mask = 0x3ff; - int over = 0; - int pc_off = 0; - int test_modrm = 1; - int c; + uint32_t new_eaaddr; - op_ea_seg = &cpu_state.seg_ds; - op_ssegs = 0; - op_old_pc = old_pc; - - for (c = 0; c < NR_HOST_REGS; c++) - host_reg_mapping[c] = -1; - mmx_ebx_ecx_loaded = 0; - for (c = 0; c < NR_HOST_XMM_REGS; c++) - host_reg_xmm_mapping[c] = -1; - - codegen_timing_start(); + if (cpu_rm == 4) { + uint8_t sib = fetchdat >> 8; + (*op_pc)++; - while (!over) - { - switch (opcode) - { - case 0x0f: - op_table = x86_dynarec_opcodes_0f; - recomp_op_table = recomp_opcodes_0f; - over = 1; - break; - - case 0x26: /*ES:*/ - op_ea_seg = &cpu_state.seg_es; - op_ssegs = 1; - break; - case 0x2e: /*CS:*/ - op_ea_seg = &cpu_state.seg_cs; - op_ssegs = 1; - break; - case 0x36: /*SS:*/ - op_ea_seg = &cpu_state.seg_ss; - op_ssegs = 1; - break; - case 0x3e: /*DS:*/ - op_ea_seg = &cpu_state.seg_ds; - op_ssegs = 1; - break; - case 0x64: /*FS:*/ - op_ea_seg = &cpu_state.seg_fs; - op_ssegs = 1; - break; - case 0x65: /*GS:*/ - op_ea_seg = &cpu_state.seg_gs; - op_ssegs = 1; - break; - - case 0x66: /*Data size select*/ - op_32 = ((use32 & 0x100) ^ 0x100) | (op_32 & 0x200); - break; - case 0x67: /*Address size select*/ - op_32 = ((use32 & 0x200) ^ 0x200) | (op_32 & 0x100); - break; - - case 0xd8: - op_table = (op_32 & 0x200) ? x86_dynarec_opcodes_d8_a32 : x86_dynarec_opcodes_d8_a16; - recomp_op_table = recomp_opcodes_d8; - opcode_shift = 3; - opcode_mask = 0x1f; - over = 1; - pc_off = -1; - test_modrm = 0; - block->flags |= CODEBLOCK_HAS_FPU; - break; - case 0xd9: - op_table = (op_32 & 0x200) ? x86_dynarec_opcodes_d9_a32 : x86_dynarec_opcodes_d9_a16; - recomp_op_table = recomp_opcodes_d9; - opcode_mask = 0xff; - over = 1; - pc_off = -1; - test_modrm = 0; - block->flags |= CODEBLOCK_HAS_FPU; - break; - case 0xda: - op_table = (op_32 & 0x200) ? x86_dynarec_opcodes_da_a32 : x86_dynarec_opcodes_da_a16; - recomp_op_table = recomp_opcodes_da; - opcode_mask = 0xff; - over = 1; - pc_off = -1; - test_modrm = 0; - block->flags |= CODEBLOCK_HAS_FPU; - break; - case 0xdb: - op_table = (op_32 & 0x200) ? x86_dynarec_opcodes_db_a32 : x86_dynarec_opcodes_db_a16; - recomp_op_table = recomp_opcodes_db; - opcode_mask = 0xff; - over = 1; - pc_off = -1; - test_modrm = 0; - block->flags |= CODEBLOCK_HAS_FPU; - break; - case 0xdc: - op_table = (op_32 & 0x200) ? x86_dynarec_opcodes_dc_a32 : x86_dynarec_opcodes_dc_a16; - recomp_op_table = recomp_opcodes_dc; - opcode_shift = 3; - opcode_mask = 0x1f; - over = 1; - pc_off = -1; - test_modrm = 0; - block->flags |= CODEBLOCK_HAS_FPU; - break; - case 0xdd: - op_table = (op_32 & 0x200) ? x86_dynarec_opcodes_dd_a32 : x86_dynarec_opcodes_dd_a16; - recomp_op_table = recomp_opcodes_dd; - opcode_mask = 0xff; - over = 1; - pc_off = -1; - test_modrm = 0; - block->flags |= CODEBLOCK_HAS_FPU; - break; - case 0xde: - op_table = (op_32 & 0x200) ? x86_dynarec_opcodes_de_a32 : x86_dynarec_opcodes_de_a16; - recomp_op_table = recomp_opcodes_de; - opcode_mask = 0xff; - over = 1; - pc_off = -1; - test_modrm = 0; - block->flags |= CODEBLOCK_HAS_FPU; - break; - case 0xdf: - op_table = (op_32 & 0x200) ? x86_dynarec_opcodes_df_a32 : x86_dynarec_opcodes_df_a16; - recomp_op_table = recomp_opcodes_df; - opcode_mask = 0xff; - over = 1; - pc_off = -1; - test_modrm = 0; - block->flags |= CODEBLOCK_HAS_FPU; - break; - - case 0xf0: /*LOCK*/ - break; - - case 0xf2: /*REPNE*/ - op_table = x86_dynarec_opcodes_REPNE; - recomp_op_table = recomp_opcodes_REPNE; - break; - case 0xf3: /*REPE*/ - op_table = x86_dynarec_opcodes_REPE; - recomp_op_table = recomp_opcodes_REPE; - break; - - default: - goto generate_call; + switch (cpu_mod) { + case 0: + if ((sib & 7) == 5) { + new_eaaddr = fastreadl(cs + (*op_pc) + 1); + addbyte(0xb8); /*MOVL ,%eax*/ + addlong(new_eaaddr); + (*op_pc) += 4; + } else { + addbyte(0x8b); /*MOVL regs[sib&7].l, %eax*/ + addbyte(0x45); + addbyte((uint8_t) cpu_state_offset(regs[sib & 7].l)); } - fetchdat = fastreadl(cs + op_pc); - codegen_timing_prefix(opcode, fetchdat); - if (cpu_state.abrt) - return; - opcode = fetchdat & 0xff; - if (!pc_off) - fetchdat >>= 8; - - op_pc++; + break; + case 1: + new_eaaddr = (uint32_t) (int8_t) ((fetchdat >> 16) & 0xff); + addbyte(0xb8); /*MOVL new_eaaddr, %eax*/ + addlong(new_eaaddr); + addbyte(0x03); /*ADDL regs[sib&7].l, %eax*/ + addbyte(0x45); + addbyte((uint8_t) cpu_state_offset(regs[sib & 7].l)); + (*op_pc)++; + break; + case 2: + new_eaaddr = fastreadl(cs + (*op_pc) + 1); + addbyte(0xb8); /*MOVL new_eaaddr, %eax*/ + addlong(new_eaaddr); + addbyte(0x03); /*ADDL regs[sib&7].l, %eax*/ + addbyte(0x45); + addbyte((uint8_t) cpu_state_offset(regs[sib & 7].l)); + (*op_pc) += 4; + break; } - + if (stack_offset && (sib & 7) == 4 && (cpu_mod || (sib & 7) != 5)) /*ESP*/ + { + addbyte(0x05); + addlong(stack_offset); + } + if (((sib & 7) == 4 || (cpu_mod && (sib & 7) == 5)) && !op_ssegs) + op_ea_seg = &cpu_state.seg_ss; + if (((sib >> 3) & 7) != 4) { + switch (sib >> 6) { + case 0: + addbyte(0x03); /*ADDL regs[sib&7].l, %eax*/ + addbyte(0x45); + addbyte((uint8_t) cpu_state_offset(regs[(sib >> 3) & 7].l)); + break; + case 1: + addbyte(0x8B); + addbyte(0x5D); + addbyte((uint8_t) cpu_state_offset(regs[(sib >> 3) & 7].l)); /*MOVL armregs[RD],%ebx*/ + addbyte(0x01); + addbyte(0xD8); /*ADDL %ebx,%eax*/ + addbyte(0x01); + addbyte(0xD8); /*ADDL %ebx,%eax*/ + break; + case 2: + addbyte(0x8B); + addbyte(0x5D); + addbyte((uint8_t) cpu_state_offset(regs[(sib >> 3) & 7].l)); /*MOVL armregs[RD],%ebx*/ + addbyte(0xC1); + addbyte(0xE3); + addbyte(2); /*SHL $2,%ebx*/ + addbyte(0x01); + addbyte(0xD8); /*ADDL %ebx,%eax*/ + break; + case 3: + addbyte(0x8B); + addbyte(0x5D); + addbyte((uint8_t) cpu_state_offset(regs[(sib >> 3) & 7].l)); /*MOVL armregs[RD],%ebx*/ + addbyte(0xC1); + addbyte(0xE3); + addbyte(3); /*SHL $2,%ebx*/ + addbyte(0x01); + addbyte(0xD8); /*ADDL %ebx,%eax*/ + break; + } + } + addbyte(0xa3); + addlong((uint32_t) &cpu_state.eaaddr); + } else { + if (!cpu_mod && cpu_rm == 5) { + new_eaaddr = fastreadl(cs + (*op_pc) + 1); + addbyte(0xC7); /*MOVL $new_eaaddr,(eaaddr)*/ + addbyte(0x45); + addbyte((uint8_t) cpu_state_offset(eaaddr)); + addlong(new_eaaddr); + (*op_pc) += 4; + return op_ea_seg; + } + addbyte(0x8b); /*MOVL regs[sib&7].l, %eax*/ + addbyte(0x45); + addbyte((uint8_t) cpu_state_offset(regs[cpu_rm].l)); + cpu_state.eaaddr = cpu_state.regs[cpu_rm].l; + if (cpu_mod) { + if (cpu_rm == 5 && !op_ssegs) + op_ea_seg = &cpu_state.seg_ss; + if (cpu_mod == 1) { + addbyte(0x05); + addlong((uint32_t) (int8_t) (fetchdat >> 8)); + (*op_pc)++; + } else { + new_eaaddr = fastreadl(cs + (*op_pc) + 1); + addbyte(0x05); + addlong(new_eaaddr); + (*op_pc) += 4; + } + } + addbyte(0xa3); + addlong((uint32_t) &cpu_state.eaaddr); + } + return op_ea_seg; +} + +void +codegen_generate_call(uint8_t opcode, OpFn op, uint32_t fetchdat, uint32_t new_pc, uint32_t old_pc) +{ + codeblock_t *block = &codeblock[block_current]; + uint32_t op_32 = use32; + uint32_t op_pc = new_pc; + const OpFn *op_table = x86_dynarec_opcodes; + RecompOpFn *recomp_op_table = recomp_opcodes; + int opcode_shift = 0; + int opcode_mask = 0x3ff; + int over = 0; + int pc_off = 0; + int test_modrm = 1; + int c; + + op_ea_seg = &cpu_state.seg_ds; + op_ssegs = 0; + op_old_pc = old_pc; + + for (c = 0; c < NR_HOST_REGS; c++) + host_reg_mapping[c] = -1; + mmx_ebx_ecx_loaded = 0; + for (c = 0; c < NR_HOST_XMM_REGS; c++) + host_reg_xmm_mapping[c] = -1; + + codegen_timing_start(); + + while (!over) { + switch (opcode) { + case 0x0f: + op_table = x86_dynarec_opcodes_0f; + recomp_op_table = fpu_softfloat ? recomp_opcodes_0f_no_mmx : recomp_opcodes_0f; + over = 1; + break; + + case 0x26: /*ES:*/ + op_ea_seg = &cpu_state.seg_es; + op_ssegs = 1; + break; + case 0x2e: /*CS:*/ + op_ea_seg = &cpu_state.seg_cs; + op_ssegs = 1; + break; + case 0x36: /*SS:*/ + op_ea_seg = &cpu_state.seg_ss; + op_ssegs = 1; + break; + case 0x3e: /*DS:*/ + op_ea_seg = &cpu_state.seg_ds; + op_ssegs = 1; + break; + case 0x64: /*FS:*/ + op_ea_seg = &cpu_state.seg_fs; + op_ssegs = 1; + break; + case 0x65: /*GS:*/ + op_ea_seg = &cpu_state.seg_gs; + op_ssegs = 1; + break; + + case 0x66: /*Data size select*/ + op_32 = ((use32 & 0x100) ^ 0x100) | (op_32 & 0x200); + break; + case 0x67: /*Address size select*/ + op_32 = ((use32 & 0x200) ^ 0x200) | (op_32 & 0x100); + break; + + case 0xd8: + op_table = (op_32 & 0x200) ? x86_dynarec_opcodes_d8_a32 : x86_dynarec_opcodes_d8_a16; + recomp_op_table = fpu_softfloat ? NULL : recomp_opcodes_d8; + opcode_shift = 3; + opcode_mask = 0x1f; + over = 1; + pc_off = -1; + test_modrm = 0; + block->flags |= CODEBLOCK_HAS_FPU; + break; + case 0xd9: + op_table = (op_32 & 0x200) ? x86_dynarec_opcodes_d9_a32 : x86_dynarec_opcodes_d9_a16; + recomp_op_table = fpu_softfloat ? NULL : recomp_opcodes_d9; + opcode_mask = 0xff; + over = 1; + pc_off = -1; + test_modrm = 0; + block->flags |= CODEBLOCK_HAS_FPU; + break; + case 0xda: + op_table = (op_32 & 0x200) ? x86_dynarec_opcodes_da_a32 : x86_dynarec_opcodes_da_a16; + recomp_op_table = fpu_softfloat ? NULL : recomp_opcodes_da; + opcode_mask = 0xff; + over = 1; + pc_off = -1; + test_modrm = 0; + block->flags |= CODEBLOCK_HAS_FPU; + break; + case 0xdb: + op_table = (op_32 & 0x200) ? x86_dynarec_opcodes_db_a32 : x86_dynarec_opcodes_db_a16; + recomp_op_table = fpu_softfloat ? NULL : recomp_opcodes_db; + opcode_mask = 0xff; + over = 1; + pc_off = -1; + test_modrm = 0; + block->flags |= CODEBLOCK_HAS_FPU; + break; + case 0xdc: + op_table = (op_32 & 0x200) ? x86_dynarec_opcodes_dc_a32 : x86_dynarec_opcodes_dc_a16; + recomp_op_table = fpu_softfloat ? NULL : recomp_opcodes_dc; + opcode_shift = 3; + opcode_mask = 0x1f; + over = 1; + pc_off = -1; + test_modrm = 0; + block->flags |= CODEBLOCK_HAS_FPU; + break; + case 0xdd: + op_table = (op_32 & 0x200) ? x86_dynarec_opcodes_dd_a32 : x86_dynarec_opcodes_dd_a16; + recomp_op_table = fpu_softfloat ? NULL : recomp_opcodes_dd; + opcode_mask = 0xff; + over = 1; + pc_off = -1; + test_modrm = 0; + block->flags |= CODEBLOCK_HAS_FPU; + break; + case 0xde: + op_table = (op_32 & 0x200) ? x86_dynarec_opcodes_de_a32 : x86_dynarec_opcodes_de_a16; + recomp_op_table = fpu_softfloat ? NULL : recomp_opcodes_de; + opcode_mask = 0xff; + over = 1; + pc_off = -1; + test_modrm = 0; + block->flags |= CODEBLOCK_HAS_FPU; + break; + case 0xdf: + op_table = (op_32 & 0x200) ? x86_dynarec_opcodes_df_a32 : x86_dynarec_opcodes_df_a16; + recomp_op_table = fpu_softfloat ? NULL : recomp_opcodes_df; + opcode_mask = 0xff; + over = 1; + pc_off = -1; + test_modrm = 0; + block->flags |= CODEBLOCK_HAS_FPU; + break; + + case 0xf0: /*LOCK*/ + break; + + case 0xf2: /*REPNE*/ + op_table = x86_dynarec_opcodes_REPNE; + recomp_op_table = recomp_opcodes_REPNE; + break; + case 0xf3: /*REPE*/ + op_table = x86_dynarec_opcodes_REPE; + recomp_op_table = recomp_opcodes_REPE; + break; + + default: + goto generate_call; + } + fetchdat = fastreadl(cs + op_pc); + codegen_timing_prefix(opcode, fetchdat); + if (cpu_state.abrt) + return; + opcode = fetchdat & 0xff; + if (!pc_off) + fetchdat >>= 8; + + op_pc++; + } + generate_call: - codegen_timing_opcode(opcode, fetchdat, op_32, op_pc); + codegen_timing_opcode(opcode, fetchdat, op_32, op_pc); - codegen_accumulate(ACCREG_cycles, -codegen_block_cycles); - codegen_block_cycles = 0; + codegen_accumulate(ACCREG_cycles, -codegen_block_cycles); + codegen_block_cycles = 0; - if ((op_table == x86_dynarec_opcodes && - ((opcode & 0xf0) == 0x70 || (opcode & 0xfc) == 0xe0 || opcode == 0xc2 || - (opcode & 0xfe) == 0xca || (opcode & 0xfc) == 0xcc || (opcode & 0xfc) == 0xe8 || - (opcode == 0xff && ((fetchdat & 0x38) >= 0x10 && (fetchdat & 0x38) < 0x30)))) || - (op_table == x86_dynarec_opcodes_0f && ((opcode & 0xf0) == 0x80))) - { - /*On some CPUs (eg K6), a jump/branch instruction may be able to pair with - subsequent instructions, so no cycles may have been deducted for it yet. - To prevent having zero cycle blocks (eg with a jump instruction pointing - to itself), apply the cycles that would be taken if this jump is taken, - then reverse it for subsequent instructions if the jump is not taken*/ - int jump_cycles = 0; + if ((op_table == x86_dynarec_opcodes && ((opcode & 0xf0) == 0x70 || (opcode & 0xfc) == 0xe0 || opcode == 0xc2 || (opcode & 0xfe) == 0xca || (opcode & 0xfc) == 0xcc || (opcode & 0xfc) == 0xe8 || (opcode == 0xff && ((fetchdat & 0x38) >= 0x10 && (fetchdat & 0x38) < 0x30)))) || (op_table == x86_dynarec_opcodes_0f && ((opcode & 0xf0) == 0x80))) { + /*On some CPUs (eg K6), a jump/branch instruction may be able to pair with + subsequent instructions, so no cycles may have been deducted for it yet. + To prevent having zero cycle blocks (eg with a jump instruction pointing + to itself), apply the cycles that would be taken if this jump is taken, + then reverse it for subsequent instructions if the jump is not taken*/ + int jump_cycles = 0; - if (codegen_timing_jump_cycles != NULL) - jump_cycles = codegen_timing_jump_cycles(); - - if (jump_cycles) - codegen_accumulate(ACCREG_cycles, -jump_cycles); - codegen_accumulate_flush(); - if (jump_cycles) - codegen_accumulate(ACCREG_cycles, jump_cycles); - } - - if ((op_table == x86_dynarec_opcodes_REPNE || op_table == x86_dynarec_opcodes_REPE) && !op_table[opcode | op_32]) - { - op_table = x86_dynarec_opcodes; - recomp_op_table = recomp_opcodes; - } - - if (recomp_op_table && recomp_op_table[(opcode | op_32) & 0x1ff]) - { - uint32_t new_pc = recomp_op_table[(opcode | op_32) & 0x1ff](opcode, fetchdat, op_32, op_pc, block); - if (new_pc) - { - if (new_pc != -1) - STORE_IMM_ADDR_L((uintptr_t)&cpu_state.pc, new_pc); - - codegen_block_ins++; - block->ins++; - codegen_block_full_ins++; - codegen_endpc = (cs + cpu_state.pc) + 8; - -#ifdef CHECK_INT - /* Check for interrupts. */ - addbyte(0xf6); /* test byte ptr[&pic_pending],1 */ - addbyte(0x05); - addlong((uint32_t) (uintptr_t) &pic_pending); - addbyte(0x01); - addbyte(0x0F); addbyte(0x85); /*JNZ 0*/ - addlong((uint32_t)&block->data[BLOCK_EXIT_OFFSET] - (uint32_t)(&block->data[block_pos + 4])); -#endif - - return; - } - } - - op = op_table[((opcode >> opcode_shift) | op_32) & opcode_mask]; - if (op_ssegs != last_ssegs) - { - last_ssegs = op_ssegs; - - addbyte(0xC6); /*MOVB [ssegs],op_ssegs*/ - addbyte(0x45); - addbyte((uint8_t)cpu_state_offset(ssegs)); - addbyte(op_pc + pc_off); - } - - if (!test_modrm || - (op_table == x86_dynarec_opcodes && opcode_modrm[opcode]) || - (op_table == x86_dynarec_opcodes_0f && opcode_0f_modrm[opcode])) - { - int stack_offset = 0; - - if (op_table == x86_dynarec_opcodes && opcode == 0x8f) /*POP*/ - stack_offset = (op_32 & 0x100) ? 4 : 2; - - cpu_mod = (fetchdat >> 6) & 3; - cpu_reg = (fetchdat >> 3) & 7; - cpu_rm = fetchdat & 7; - - addbyte(0xC7); /*MOVL $rm | mod | reg,(rm_mod_reg_data)*/ - addbyte(0x45); - addbyte((uint8_t)cpu_state_offset(rm_data.rm_mod_reg_data)); - addlong(cpu_rm | (cpu_mod << 8) | (cpu_reg << 16)); - - op_pc += pc_off; - if (cpu_mod != 3 && !(op_32 & 0x200)) - op_ea_seg = codegen_generate_ea_16_long(op_ea_seg, fetchdat, op_ssegs, &op_pc); - if (cpu_mod != 3 && (op_32 & 0x200)) - op_ea_seg = codegen_generate_ea_32_long(op_ea_seg, fetchdat, op_ssegs, &op_pc, stack_offset); - op_pc -= pc_off; - } - - if (op_ea_seg != last_ea_seg) - { - last_ea_seg = op_ea_seg; - addbyte(0xC7); /*MOVL $&cpu_state.seg_ds,(ea_seg)*/ - addbyte(0x45); - addbyte((uint8_t)cpu_state_offset(ea_seg)); - addlong((uint32_t)op_ea_seg); - } + if (codegen_timing_jump_cycles != NULL) + jump_cycles = codegen_timing_jump_cycles(); + if (jump_cycles) + codegen_accumulate(ACCREG_cycles, -jump_cycles); codegen_accumulate_flush(); + if (jump_cycles) + codegen_accumulate(ACCREG_cycles, jump_cycles); + } - addbyte(0xC7); /*MOVL pc,new_pc*/ - addbyte(0x45); - addbyte((uint8_t)cpu_state_offset(pc)); - addlong(op_pc + pc_off); + if ((op_table == x86_dynarec_opcodes_REPNE || op_table == x86_dynarec_opcodes_REPE) && !op_table[opcode | op_32]) { + op_table = x86_dynarec_opcodes; + recomp_op_table = recomp_opcodes; + } - addbyte(0xC7); /*MOVL $old_pc,(oldpc)*/ - addbyte(0x45); - addbyte((uint8_t)cpu_state_offset(oldpc)); - addlong(old_pc); + if (recomp_op_table && recomp_op_table[(opcode | op_32) & 0x1ff]) { + uint32_t new_pc = recomp_op_table[(opcode | op_32) & 0x1ff](opcode, fetchdat, op_32, op_pc, block); + if (new_pc) { + if (new_pc != -1) + STORE_IMM_ADDR_L((uintptr_t) &cpu_state.pc, new_pc); - if (op_32 != last_op32) - { - last_op32 = op_32; - addbyte(0xC7); /*MOVL $use32,(op32)*/ - addbyte(0x45); - addbyte((uint8_t)cpu_state_offset(op32)); - addlong(op_32); + codegen_block_ins++; + block->ins++; + codegen_block_full_ins++; + codegen_endpc = (cs + cpu_state.pc) + 8; + +# ifdef CHECK_INT + /* Check for interrupts. */ + addbyte(0xf6); /* test byte ptr[&pic_pending],1 */ + addbyte(0x05); + addlong((uint32_t) (uintptr_t) &pic_pending); + addbyte(0x01); + addbyte(0x0F); + addbyte(0x85); /*JNZ 0*/ + addlong((uint32_t) &block->data[BLOCK_EXIT_OFFSET] - (uint32_t) (&block->data[block_pos + 4])); +# endif + + return; } + } - addbyte(0xC7); /*MOVL $fetchdat,(%esp)*/ - addbyte(0x04); - addbyte(0x24); - addlong(fetchdat); - - addbyte(0xE8); /*CALL*/ - addlong(((uint8_t *)op - (uint8_t *)(&block->data[block_pos + 4]))); + op = op_table[((opcode >> opcode_shift) | op_32) & opcode_mask]; + if (op_ssegs != last_ssegs) { + last_ssegs = op_ssegs; - codegen_block_ins++; - - block->ins++; + addbyte(0xC6); /*MOVB [ssegs],op_ssegs*/ + addbyte(0x45); + addbyte((uint8_t) cpu_state_offset(ssegs)); + addbyte(op_pc + pc_off); + } -#ifdef CHECK_INT - /* Check for interrupts. */ - addbyte(0x0a); /* or al,byte ptr[&pic_pending] */ - addbyte(0x05); - addlong((uint32_t) (uintptr_t) &pic_pending); -#endif + if (!test_modrm || (op_table == x86_dynarec_opcodes && opcode_modrm[opcode]) || (op_table == x86_dynarec_opcodes_0f && opcode_0f_modrm[opcode])) { + int stack_offset = 0; - addbyte(0x09); /*OR %eax, %eax*/ - addbyte(0xc0); - addbyte(0x0F); addbyte(0x85); /*JNZ 0*/ - addlong((uint32_t)&block->data[BLOCK_EXIT_OFFSET] - (uint32_t)(&block->data[block_pos + 4])); + if (op_table == x86_dynarec_opcodes && opcode == 0x8f) /*POP*/ + stack_offset = (op_32 & 0x100) ? 4 : 2; - codegen_endpc = (cs + cpu_state.pc) + 8; + cpu_mod = (fetchdat >> 6) & 3; + cpu_reg = (fetchdat >> 3) & 7; + cpu_rm = fetchdat & 7; + + addbyte(0xC7); /*MOVL $rm | mod | reg,(rm_mod_reg_data)*/ + addbyte(0x45); + addbyte((uint8_t) cpu_state_offset(rm_data.rm_mod_reg_data)); + addlong(cpu_rm | (cpu_mod << 8) | (cpu_reg << 16)); + + op_pc += pc_off; + if (cpu_mod != 3 && !(op_32 & 0x200)) + op_ea_seg = codegen_generate_ea_16_long(op_ea_seg, fetchdat, op_ssegs, &op_pc); + if (cpu_mod != 3 && (op_32 & 0x200)) + op_ea_seg = codegen_generate_ea_32_long(op_ea_seg, fetchdat, op_ssegs, &op_pc, stack_offset); + op_pc -= pc_off; + } + + if (op_ea_seg != last_ea_seg) { + last_ea_seg = op_ea_seg; + addbyte(0xC7); /*MOVL $&cpu_state.seg_ds,(ea_seg)*/ + addbyte(0x45); + addbyte((uint8_t) cpu_state_offset(ea_seg)); + addlong((uint32_t) op_ea_seg); + } + + codegen_accumulate_flush(); + + addbyte(0xC7); /*MOVL pc,new_pc*/ + addbyte(0x45); + addbyte((uint8_t) cpu_state_offset(pc)); + addlong(op_pc + pc_off); + + addbyte(0xC7); /*MOVL $old_pc,(oldpc)*/ + addbyte(0x45); + addbyte((uint8_t) cpu_state_offset(oldpc)); + addlong(old_pc); + + if (op_32 != last_op32) { + last_op32 = op_32; + addbyte(0xC7); /*MOVL $use32,(op32)*/ + addbyte(0x45); + addbyte((uint8_t) cpu_state_offset(op32)); + addlong(op_32); + } + + addbyte(0xC7); /*MOVL $fetchdat,(%esp)*/ + addbyte(0x04); + addbyte(0x24); + addlong(fetchdat); + + addbyte(0xE8); /*CALL*/ + addlong(((uint8_t *) op - (uint8_t *) (&block->data[block_pos + 4]))); + + codegen_block_ins++; + + block->ins++; + +# ifdef CHECK_INT + /* Check for interrupts. */ + addbyte(0x0a); /* or al,byte ptr[&pic_pending] */ + addbyte(0x05); + addlong((uint32_t) (uintptr_t) &pic_pending); +# endif + + addbyte(0x09); /*OR %eax, %eax*/ + addbyte(0xc0); + addbyte(0x0F); + addbyte(0x85); /*JNZ 0*/ + addlong((uint32_t) &block->data[BLOCK_EXIT_OFFSET] - (uint32_t) (&block->data[block_pos + 4])); + + codegen_endpc = (cs + cpu_state.pc) + 8; } #endif diff --git a/src/codegen/codegen_x86.h b/src/codegen/codegen_x86.h index 369614329..d6842eec1 100644 --- a/src/codegen/codegen_x86.h +++ b/src/codegen/codegen_x86.h @@ -1,24 +1,23 @@ -#define BLOCK_SIZE 0x4000 -#define BLOCK_MASK 0x3fff -#define BLOCK_START 0 +#define BLOCK_SIZE 0x4000 +#define BLOCK_MASK 0x3fff +#define BLOCK_START 0 -#define HASH_SIZE 0x20000 -#define HASH_MASK 0x1ffff +#define HASH_SIZE 0x20000 +#define HASH_MASK 0x1ffff -#define HASH(l) ((l) & 0x1ffff) +#define HASH(l) ((l) &0x1ffff) #define BLOCK_EXIT_OFFSET 0x7f0 #ifdef OLD_GPF -#define BLOCK_GPF_OFFSET (BLOCK_EXIT_OFFSET - 20) +# define BLOCK_GPF_OFFSET (BLOCK_EXIT_OFFSET - 20) #else -#define BLOCK_GPF_OFFSET (BLOCK_EXIT_OFFSET - 14) +# define BLOCK_GPF_OFFSET (BLOCK_EXIT_OFFSET - 14) #endif #define BLOCK_MAX 1720 -enum -{ - OP_RET = 0xc3 +enum { + OP_RET = 0xc3 }; #define NR_HOST_REGS 4 diff --git a/src/codegen_new/CMakeLists.txt b/src/codegen_new/CMakeLists.txt index 54f3b3c6b..038f1edd1 100644 --- a/src/codegen_new/CMakeLists.txt +++ b/src/codegen_new/CMakeLists.txt @@ -1,16 +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. +# 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. +# This file is part of the 86Box distribution. # -# CMake build script. +# CMake build script. # -# Authors: David HrdliÄka, +# Authors: David HrdliÄka, # -# Copyright 2020,2021 David HrdliÄka. +# Copyright 2020-2021 David HrdliÄka. # if(DYNAREC) @@ -43,9 +43,9 @@ if(DYNAREC) target_sources(dynarec PRIVATE codegen_backend_arm.c codegen_backend_arm_ops.c codegen_backend_arm_uops.c) else() - message(SEND_ERROR + message(SEND_ERROR "Dynarec is incompatible with target platform ${ARCH}") endif() target_link_libraries(86Box dynarec cgt) -endif() \ No newline at end of file +endif() diff --git a/src/codegen_new/codegen.c b/src/codegen_new/codegen.c index aa0791b3e..a3f4ede8f 100644 --- a/src/codegen_new/codegen.c +++ b/src/codegen_new/codegen.c @@ -2,10 +2,13 @@ #include <86box/86box.h> #include "cpu.h" #include <86box/mem.h> +#include <86box/plat_unused.h> #include "x86_ops.h" #include "codegen.h" #include "x86.h" +#include "x86seg_common.h" +#include "x86seg.h" #include "386_common.h" @@ -20,759 +23,730 @@ static struct { - uint32_t pc; - int op_ssegs; - x86seg *op_ea_seg; - uint32_t op_32; - int first_uop; - int TOP; + uint32_t pc; + int op_ssegs; + x86seg *op_ea_seg; + uint32_t op_32; + int first_uop; + int TOP; } codegen_instructions[MAX_INSTRUCTION_COUNT]; -int codegen_get_instruction_uop(codeblock_t *block, uint32_t pc, int *first_instruction, int *TOP) +int +codegen_get_instruction_uop(codeblock_t *block, uint32_t pc, int *first_instruction, int *TOP) { - int c; - - for (c = 0; c <= block->ins; c++) - { - if (codegen_instructions[c].pc == pc) - { - *first_instruction = c; - *TOP = codegen_instructions[c].TOP; - return codegen_instructions[c].first_uop; - } + for (uint8_t c = 0; c <= block->ins; c++) { + if (codegen_instructions[c].pc == pc) { + *first_instruction = c; + *TOP = codegen_instructions[c].TOP; + return codegen_instructions[c].first_uop; } - - *first_instruction = block->ins; - return -1; + } + + *first_instruction = block->ins; + return -1; } -void codegen_set_loop_start(ir_data_t *ir, int first_instruction) +void +codegen_set_loop_start(ir_data_t *ir, int first_instruction) { - uop_MOV_IMM(ir, IREG_op32, codegen_instructions[first_instruction].op_32); - uop_MOV_PTR(ir, IREG_ea_seg, (void *)codegen_instructions[first_instruction].op_ea_seg); - uop_MOV_IMM(ir, IREG_ssegs, codegen_instructions[first_instruction].op_ssegs); + uop_MOV_IMM(ir, IREG_op32, codegen_instructions[first_instruction].op_32); + uop_MOV_PTR(ir, IREG_ea_seg, (void *) codegen_instructions[first_instruction].op_ea_seg); + uop_MOV_IMM(ir, IREG_ssegs, codegen_instructions[first_instruction].op_ssegs); } int has_ea; codeblock_t *codeblock; -uint16_t *codeblock_hash; +uint16_t *codeblock_hash; -void (*codegen_timing_start)(); +void (*codegen_timing_start)(void); void (*codegen_timing_prefix)(uint8_t prefix, uint32_t fetchdat); void (*codegen_timing_opcode)(uint8_t opcode, uint32_t fetchdat, int op_32, uint32_t op_pc); -void (*codegen_timing_block_start)(); -void (*codegen_timing_block_end)(); -int (*codegen_timing_jump_cycles)(); +void (*codegen_timing_block_start)(void); +void (*codegen_timing_block_end)(void); +int (*codegen_timing_jump_cycles)(void); -void codegen_timing_set(codegen_timing_t *timing) +void +codegen_timing_set(codegen_timing_t *timing) { - codegen_timing_start = timing->start; - codegen_timing_prefix = timing->prefix; - codegen_timing_opcode = timing->opcode; - codegen_timing_block_start = timing->block_start; - codegen_timing_block_end = timing->block_end; - codegen_timing_jump_cycles = timing->jump_cycles; + codegen_timing_start = timing->start; + codegen_timing_prefix = timing->prefix; + codegen_timing_opcode = timing->opcode; + codegen_timing_block_start = timing->block_start; + codegen_timing_block_end = timing->block_end; + codegen_timing_jump_cycles = timing->jump_cycles; } int codegen_in_recompile; -static int last_op_ssegs; -static x86seg *last_op_ea_seg; +static int last_op_ssegs; +static x86seg *last_op_ea_seg; static uint32_t last_op_32; -void codegen_generate_reset() +void +codegen_generate_reset(void) { - last_op_ssegs = -1; - last_op_ea_seg = NULL; - last_op_32 = -1; - has_ea = 0; + last_op_ssegs = -1; + last_op_ea_seg = NULL; + last_op_32 = -1; + has_ea = 0; } -void codegen_check_seg_read(codeblock_t *block, ir_data_t *ir, x86seg *seg) +void +codegen_check_seg_read(UNUSED(codeblock_t *block), ir_data_t *ir, x86seg *seg) { - /*Segments always valid in real/V86 mode*/ - if (!(cr0 & 1) || (cpu_state.eflags & VM_FLAG)) - return; - /*CS and SS must always be valid*/ - if (seg == &cpu_state.seg_cs || seg == &cpu_state.seg_ss) - return; - if (seg->checked) - return; - if (seg == &cpu_state.seg_ds && codegen_flat_ds && !(cpu_cur_status & CPU_STATUS_NOTFLATDS)) - return; + /*Segments always valid in real/V86 mode*/ + if (!(cr0 & 1) || (cpu_state.eflags & VM_FLAG)) + return; + /*CS and SS must always be valid*/ + if (seg == &cpu_state.seg_cs || seg == &cpu_state.seg_ss) + return; + if (seg->checked) + return; + if (seg == &cpu_state.seg_ds && codegen_flat_ds && !(cpu_cur_status & CPU_STATUS_NOTFLATDS)) + return; - uop_CMP_IMM_JZ(ir, ireg_seg_base(seg), (uint32_t)-1, codegen_gpf_rout); + uop_CMP_IMM_JZ(ir, ireg_seg_base(seg), (uint32_t) -1, codegen_gpf_rout); - seg->checked = 1; + seg->checked = 1; } -void codegen_check_seg_write(codeblock_t *block, ir_data_t *ir, x86seg *seg) +void +codegen_check_seg_write(UNUSED(codeblock_t *block), ir_data_t *ir, x86seg *seg) { - /*Segments always valid in real/V86 mode*/ - if (!(cr0 & 1) || (cpu_state.eflags & VM_FLAG)) - return; - /*CS and SS must always be valid*/ - if (seg == &cpu_state.seg_cs || seg == &cpu_state.seg_ss) - return; - if (seg->checked) - return; - if (seg == &cpu_state.seg_ds && codegen_flat_ds && !(cpu_cur_status & CPU_STATUS_NOTFLATDS)) - return; + /*Segments always valid in real/V86 mode*/ + if (!(cr0 & 1) || (cpu_state.eflags & VM_FLAG)) + return; + /*CS and SS must always be valid*/ + if (seg == &cpu_state.seg_cs || seg == &cpu_state.seg_ss) + return; + if (seg->checked) + return; + if (seg == &cpu_state.seg_ds && codegen_flat_ds && !(cpu_cur_status & CPU_STATUS_NOTFLATDS)) + return; - uop_CMP_IMM_JZ(ir, ireg_seg_base(seg), (uint32_t)-1, codegen_gpf_rout); + uop_CMP_IMM_JZ(ir, ireg_seg_base(seg), (uint32_t) -1, codegen_gpf_rout); - seg->checked = 1; + seg->checked = 1; } -static x86seg *codegen_generate_ea_16_long(ir_data_t *ir, x86seg *op_ea_seg, uint32_t fetchdat, int op_ssegs, uint32_t *op_pc) +static x86seg * +codegen_generate_ea_16_long(ir_data_t *ir, x86seg *op_ea_seg, uint32_t fetchdat, int op_ssegs, uint32_t *op_pc) { - uint32_t old_pc = (*op_pc) + 1; - if (!cpu_mod && cpu_rm == 6) - { - uint16_t addr = (fetchdat >> 8) & 0xffff; - uop_MOV_IMM(ir, IREG_eaaddr, addr); - (*op_pc) += 2; + uint32_t old_pc = (*op_pc) + 1; + if (!cpu_mod && cpu_rm == 6) { + uint16_t addr = (fetchdat >> 8) & 0xffff; + uop_MOV_IMM(ir, IREG_eaaddr, addr); + (*op_pc) += 2; + } else { + int base_reg; + int index_reg; + int offset; + + switch (cpu_rm & 7) { + default: + case 0: + case 1: + case 7: + base_reg = IREG_EBX; + break; + case 2: + case 3: + case 6: + base_reg = IREG_EBP; + break; + case 4: + base_reg = IREG_ESI; + break; + case 5: + base_reg = IREG_EDI; + break; } - else - { - int base_reg, index_reg, offset; + uop_MOV(ir, IREG_eaaddr, base_reg); - switch (cpu_rm & 7) - { - case 0: case 1: case 7: default: - base_reg = IREG_EBX; - break; - case 2: case 3: case 6: - base_reg = IREG_EBP; - break; - case 4: - base_reg = IREG_ESI; - break; - case 5: - base_reg = IREG_EDI; - break; - } - uop_MOV(ir, IREG_eaaddr, base_reg); + if (!(cpu_rm & 4)) { + if (!(cpu_rm & 1)) + index_reg = IREG_ESI; + else + index_reg = IREG_EDI; - if (!(cpu_rm & 4)) - { - if (!(cpu_rm & 1)) - index_reg = IREG_ESI; - else - index_reg = IREG_EDI; - - uop_ADD(ir, IREG_eaaddr, IREG_eaaddr, index_reg); - } - - switch (cpu_mod) - { - case 1: - offset = (int)(int8_t)((fetchdat >> 8) & 0xff); - uop_ADD_IMM(ir, IREG_eaaddr, IREG_eaaddr, offset); - (*op_pc)++; - break; - case 2: - offset = (fetchdat >> 8) & 0xffff; - uop_ADD_IMM(ir, IREG_eaaddr, IREG_eaaddr, offset); - (*op_pc) += 2; - break; - } - - uop_AND_IMM(ir, IREG_eaaddr, IREG_eaaddr, 0xffff); - - if (mod1seg[cpu_rm] == &ss && !op_ssegs) - { - op_ea_seg = &cpu_state.seg_ss; - } + uop_ADD(ir, IREG_eaaddr, IREG_eaaddr, index_reg); } - - codegen_mark_code_present(ir->block, cs+old_pc, ((*op_pc)+1)-old_pc); - return op_ea_seg; -} -static x86seg *codegen_generate_ea_32_long(ir_data_t *ir, x86seg *op_ea_seg, uint32_t fetchdat, int op_ssegs, uint32_t *op_pc, int stack_offset) -{ - codeblock_t *block = ir->block; - uint32_t old_pc = (*op_pc) + 1; - uint32_t new_eaaddr; - int extra_bytes = 0; - - if (cpu_rm == 4) - { - uint8_t sib = fetchdat >> 8; + switch (cpu_mod) { + case 1: + offset = (int) (int8_t) ((fetchdat >> 8) & 0xff); + uop_ADD_IMM(ir, IREG_eaaddr, IREG_eaaddr, offset); (*op_pc)++; + break; + case 2: + offset = (fetchdat >> 8) & 0xffff; + uop_ADD_IMM(ir, IREG_eaaddr, IREG_eaaddr, offset); + (*op_pc) += 2; + break; - switch (cpu_mod) - { - case 0: - if ((sib & 7) == 5) - { - if (block->flags & CODEBLOCK_NO_IMMEDIATES) - { - LOAD_IMMEDIATE_FROM_RAM_32(block, ir, IREG_eaaddr, cs + (*op_pc) + 1); - extra_bytes = 1; - } - else - { - new_eaaddr = fastreadl(cs + (*op_pc) + 1); - uop_MOV_IMM(ir, IREG_eaaddr, new_eaaddr); - extra_bytes = 5; - } - (*op_pc) += 4; - } - else - { - uop_MOV(ir, IREG_eaaddr, sib & 7); - extra_bytes = 1; - } - break; - case 1: - new_eaaddr = (uint32_t)(int8_t)((fetchdat >> 16) & 0xff); + default: + break; + } + + uop_AND_IMM(ir, IREG_eaaddr, IREG_eaaddr, 0xffff); + + if (mod1seg[cpu_rm] == &ss && !op_ssegs) { + op_ea_seg = &cpu_state.seg_ss; + } + } + + codegen_mark_code_present(ir->block, cs + old_pc, ((*op_pc) + 1) - old_pc); + return op_ea_seg; +} + +static x86seg * +codegen_generate_ea_32_long(ir_data_t *ir, x86seg *op_ea_seg, uint32_t fetchdat, int op_ssegs, uint32_t *op_pc, int stack_offset) +{ + codeblock_t *block = ir->block; + uint32_t old_pc = (*op_pc) + 1; + uint32_t new_eaaddr; + int extra_bytes = 0; + + if (cpu_rm == 4) { + uint8_t sib = fetchdat >> 8; + (*op_pc)++; + + switch (cpu_mod) { + case 0: + if ((sib & 7) == 5) { + if (block->flags & CODEBLOCK_NO_IMMEDIATES) { + LOAD_IMMEDIATE_FROM_RAM_32(block, ir, IREG_eaaddr, cs + (*op_pc) + 1); + extra_bytes = 1; + } else { + new_eaaddr = fastreadl(cs + (*op_pc) + 1); uop_MOV_IMM(ir, IREG_eaaddr, new_eaaddr); - uop_ADD(ir, IREG_eaaddr, IREG_eaaddr, sib & 7); - (*op_pc)++; - extra_bytes = 2; - break; - case 2: - if (block->flags & CODEBLOCK_NO_IMMEDIATES) - { - LOAD_IMMEDIATE_FROM_RAM_32(block, ir, IREG_eaaddr, cs + (*op_pc) + 1); - extra_bytes = 1; - } - else - { - new_eaaddr = fastreadl(cs + (*op_pc) + 1); - uop_MOV_IMM(ir, IREG_eaaddr, new_eaaddr); - extra_bytes = 5; - } - (*op_pc) += 4; - uop_ADD(ir, IREG_eaaddr, IREG_eaaddr, sib & 7); - break; + extra_bytes = 5; + } + (*op_pc) += 4; + } else { + uop_MOV(ir, IREG_eaaddr, sib & 7); + extra_bytes = 1; } - if (stack_offset && (sib & 7) == 4 && (cpu_mod || (sib & 7) != 5)) /*ESP*/ - { - uop_ADD_IMM(ir, IREG_eaaddr, IREG_eaaddr, stack_offset); -// addbyte(0x05); -// addlong(stack_offset); + break; + case 1: + new_eaaddr = (uint32_t) (int8_t) ((fetchdat >> 16) & 0xff); + uop_MOV_IMM(ir, IREG_eaaddr, new_eaaddr); + uop_ADD(ir, IREG_eaaddr, IREG_eaaddr, sib & 7); + (*op_pc)++; + extra_bytes = 2; + break; + case 2: + if (block->flags & CODEBLOCK_NO_IMMEDIATES) { + LOAD_IMMEDIATE_FROM_RAM_32(block, ir, IREG_eaaddr, cs + (*op_pc) + 1); + extra_bytes = 1; + } else { + new_eaaddr = fastreadl(cs + (*op_pc) + 1); + uop_MOV_IMM(ir, IREG_eaaddr, new_eaaddr); + extra_bytes = 5; } - if (((sib & 7) == 4 || (cpu_mod && (sib & 7) == 5)) && !op_ssegs) - op_ea_seg = &cpu_state.seg_ss; - if (((sib >> 3) & 7) != 4) - { - switch (sib >> 6) - { - case 0: - uop_ADD(ir, IREG_eaaddr, IREG_eaaddr, (sib >> 3) & 7); - break; - case 1: - uop_ADD_LSHIFT(ir, IREG_eaaddr, IREG_eaaddr, (sib >> 3) & 7, 1); - break; - case 2: - uop_ADD_LSHIFT(ir, IREG_eaaddr, IREG_eaaddr, (sib >> 3) & 7, 2); - break; - case 3: - uop_ADD_LSHIFT(ir, IREG_eaaddr, IREG_eaaddr, (sib >> 3) & 7, 3); - break; - } - } - } - else - { - if (!cpu_mod && cpu_rm == 5) - { - if (block->flags & CODEBLOCK_NO_IMMEDIATES) - { - LOAD_IMMEDIATE_FROM_RAM_32(block, ir, IREG_eaaddr, cs + (*op_pc) + 1); - } - else - { - new_eaaddr = fastreadl(cs + (*op_pc) + 1); - uop_MOV_IMM(ir, IREG_eaaddr, new_eaaddr); - extra_bytes = 4; - } - - (*op_pc) += 4; - } - else - { - uop_MOV(ir, IREG_eaaddr, cpu_rm); - if (cpu_mod) - { - if (cpu_rm == 5 && !op_ssegs) - op_ea_seg = &cpu_state.seg_ss; - if (cpu_mod == 1) - { - uop_ADD_IMM(ir, IREG_eaaddr, IREG_eaaddr, (uint32_t)(int8_t)(fetchdat >> 8)); - (*op_pc)++; - extra_bytes = 1; - } - else - { - if (block->flags & CODEBLOCK_NO_IMMEDIATES) - { - LOAD_IMMEDIATE_FROM_RAM_32(block, ir, IREG_temp0, cs + (*op_pc) + 1); - uop_ADD(ir, IREG_eaaddr, IREG_eaaddr, IREG_temp0); - } - else - { - new_eaaddr = fastreadl(cs + (*op_pc) + 1); - uop_ADD_IMM(ir, IREG_eaaddr, IREG_eaaddr, new_eaaddr); - extra_bytes = 4; - } - (*op_pc) += 4; - } - } - } - } + (*op_pc) += 4; + uop_ADD(ir, IREG_eaaddr, IREG_eaaddr, sib & 7); + break; - if (extra_bytes) - codegen_mark_code_present(ir->block, cs+old_pc, extra_bytes); - - return op_ea_seg; + default: + break; + } + if (stack_offset && (sib & 7) == 4 && (cpu_mod || (sib & 7) != 5)) { /*ESP*/ + uop_ADD_IMM(ir, IREG_eaaddr, IREG_eaaddr, stack_offset); +#if 0 + addbyte(0x05); + addlong(stack_offset); +#endif + } + if (((sib & 7) == 4 || (cpu_mod && (sib & 7) == 5)) && !op_ssegs) + op_ea_seg = &cpu_state.seg_ss; + if (((sib >> 3) & 7) != 4) { + switch (sib >> 6) { + case 0: + uop_ADD(ir, IREG_eaaddr, IREG_eaaddr, (sib >> 3) & 7); + break; + case 1: + uop_ADD_LSHIFT(ir, IREG_eaaddr, IREG_eaaddr, (sib >> 3) & 7, 1); + break; + case 2: + uop_ADD_LSHIFT(ir, IREG_eaaddr, IREG_eaaddr, (sib >> 3) & 7, 2); + break; + case 3: + uop_ADD_LSHIFT(ir, IREG_eaaddr, IREG_eaaddr, (sib >> 3) & 7, 3); + break; + + default: + break; + } + } + } else { + if (!cpu_mod && cpu_rm == 5) { + if (block->flags & CODEBLOCK_NO_IMMEDIATES) { + LOAD_IMMEDIATE_FROM_RAM_32(block, ir, IREG_eaaddr, cs + (*op_pc) + 1); + } else { + new_eaaddr = fastreadl(cs + (*op_pc) + 1); + uop_MOV_IMM(ir, IREG_eaaddr, new_eaaddr); + extra_bytes = 4; + } + + (*op_pc) += 4; + } else { + uop_MOV(ir, IREG_eaaddr, cpu_rm); + if (cpu_mod) { + if (cpu_rm == 5 && !op_ssegs) + op_ea_seg = &cpu_state.seg_ss; + if (cpu_mod == 1) { + uop_ADD_IMM(ir, IREG_eaaddr, IREG_eaaddr, (uint32_t) (int8_t) (fetchdat >> 8)); + (*op_pc)++; + extra_bytes = 1; + } else { + if (block->flags & CODEBLOCK_NO_IMMEDIATES) { + LOAD_IMMEDIATE_FROM_RAM_32(block, ir, IREG_temp0, cs + (*op_pc) + 1); + uop_ADD(ir, IREG_eaaddr, IREG_eaaddr, IREG_temp0); + } else { + new_eaaddr = fastreadl(cs + (*op_pc) + 1); + uop_ADD_IMM(ir, IREG_eaaddr, IREG_eaaddr, new_eaaddr); + extra_bytes = 4; + } + (*op_pc) += 4; + } + } + } + } + + if (extra_bytes) + codegen_mark_code_present(ir->block, cs + old_pc, extra_bytes); + + return op_ea_seg; } -x86seg *codegen_generate_ea(ir_data_t *ir, x86seg *op_ea_seg, uint32_t fetchdat, int op_ssegs, uint32_t *op_pc, uint32_t op_32, int stack_offset) +x86seg * +codegen_generate_ea(ir_data_t *ir, x86seg *op_ea_seg, uint32_t fetchdat, int op_ssegs, uint32_t *op_pc, uint32_t op_32, int stack_offset) { - cpu_mod = (fetchdat >> 6) & 3; - cpu_reg = (fetchdat >> 3) & 7; - cpu_rm = fetchdat & 7; + cpu_mod = (fetchdat >> 6) & 3; + cpu_reg = (fetchdat >> 3) & 7; + cpu_rm = fetchdat & 7; - if ((fetchdat & 0xc0) == 0xc0) - return NULL; - if (op_32 & 0x200) - return codegen_generate_ea_32_long(ir, op_ea_seg, fetchdat, op_ssegs, op_pc, stack_offset); + if ((fetchdat & 0xc0) == 0xc0) + return NULL; + if (op_32 & 0x200) + return codegen_generate_ea_32_long(ir, op_ea_seg, fetchdat, op_ssegs, op_pc, stack_offset); - return codegen_generate_ea_16_long(ir, op_ea_seg, fetchdat, op_ssegs, op_pc); + return codegen_generate_ea_16_long(ir, op_ea_seg, fetchdat, op_ssegs, op_pc); } -static uint8_t opcode_modrm[256] = -{ - 1, 1, 1, 1, 0, 0, 0, 0, 1, 1, 1, 1, 0, 0, 0, 0, /*00*/ - 1, 1, 1, 1, 0, 0, 0, 0, 1, 1, 1, 1, 0, 0, 0, 0, /*10*/ - 1, 1, 1, 1, 0, 0, 0, 0, 1, 1, 1, 1, 0, 0, 0, 0, /*20*/ - 1, 1, 1, 1, 0, 0, 0, 0, 1, 1, 1, 1, 0, 0, 0, 0, /*30*/ +// clang-format off +static uint8_t opcode_modrm[256] = { + 1, 1, 1, 1, 0, 0, 0, 0, 1, 1, 1, 1, 0, 0, 0, 0, /*00*/ + 1, 1, 1, 1, 0, 0, 0, 0, 1, 1, 1, 1, 0, 0, 0, 0, /*10*/ + 1, 1, 1, 1, 0, 0, 0, 0, 1, 1, 1, 1, 0, 0, 0, 0, /*20*/ + 1, 1, 1, 1, 0, 0, 0, 0, 1, 1, 1, 1, 0, 0, 0, 0, /*30*/ - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /*40*/ - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /*50*/ - 0, 0, 1, 1, 0, 0, 0, 0, 0, 1, 0, 1, 0, 0, 0, 0, /*60*/ - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /*70*/ + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /*40*/ + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /*50*/ + 0, 0, 1, 1, 0, 0, 0, 0, 0, 1, 0, 1, 0, 0, 0, 0, /*60*/ + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /*70*/ - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /*80*/ - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /*90*/ - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /*a0*/ - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /*b0*/ + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /*80*/ + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /*90*/ + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /*a0*/ + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /*b0*/ - 1, 1, 0, 0, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, /*c0*/ - 1, 1, 1, 1, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, /*d0*/ - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /*e0*/ - 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 1, 1, /*f0*/ -}; -static uint8_t opcode_0f_modrm[256] = -{ - 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, /*00*/ - 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, /*10*/ - 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /*20*/ - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, /*30*/ - - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /*40*/ - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /*50*/ - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 1, 1, /*60*/ - 0, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 1, 1, /*70*/ - - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /*80*/ - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /*90*/ - 0, 0, 0, 1, 1, 1, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, /*a0*/ - 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 1, 1, 1, 1, 1, 1, /*b0*/ - - 1, 1, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, /*c0*/ - 0, 1, 1, 1, 0, 1, 0, 0, 1, 1, 0, 1, 1, 1, 0, 1, /*d0*/ - 0, 1, 1, 0, 0, 1, 0, 0, 1, 1, 0, 1, 1, 1, 0, 1, /*e0*/ - 0, 1, 1, 1, 0, 1, 0, 0, 1, 1, 1, 0, 1, 1, 1, 0 /*f0*/ + 1, 1, 0, 0, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, /*c0*/ + 1, 1, 1, 1, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, /*d0*/ + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /*e0*/ + 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 1, 1, /*f0*/ }; -void codegen_generate_call(uint8_t opcode, OpFn op, uint32_t fetchdat, uint32_t new_pc, uint32_t old_pc) +static uint8_t opcode_0f_modrm[256] = { + 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, /*00*/ + 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, /*10*/ + 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /*20*/ + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, /*30*/ + + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /*40*/ + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /*50*/ + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 1, 1, /*60*/ + 0, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 1, 1, /*70*/ + + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /*80*/ + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /*90*/ + 0, 0, 0, 1, 1, 1, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, /*a0*/ + 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 1, 1, 1, 1, 1, 1, /*b0*/ + + 1, 1, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, /*c0*/ + 0, 1, 1, 1, 0, 1, 0, 0, 1, 1, 0, 1, 1, 1, 0, 1, /*d0*/ + 0, 1, 1, 0, 0, 1, 0, 0, 1, 1, 0, 1, 1, 1, 0, 1, /*e0*/ + 0, 1, 1, 1, 0, 1, 0, 0, 1, 1, 1, 0, 1, 1, 1, 0 /*f0*/ +}; +// clang-format on + +void +codegen_generate_call(uint8_t opcode, OpFn op, uint32_t fetchdat, uint32_t new_pc, uint32_t old_pc) { - codeblock_t *block = &codeblock[block_current]; - ir_data_t *ir = codegen_get_ir_data(); - uint32_t op_pc = new_pc; - OpFn *op_table = (OpFn *) x86_dynarec_opcodes; - RecompOpFn *recomp_op_table = recomp_opcodes; - int opcode_shift = 0; - int opcode_mask = 0x3ff; - uint32_t recomp_opcode_mask = 0x1ff; - uint32_t op_32 = use32; - int over = 0; - int test_modrm = 1; - int pc_off = 0; - uint32_t next_pc = 0; + codeblock_t *block = &codeblock[block_current]; + ir_data_t *ir = codegen_get_ir_data(); + uint32_t op_pc = new_pc; + const OpFn *op_table = x86_dynarec_opcodes; + RecompOpFn *recomp_op_table = recomp_opcodes; + int opcode_shift = 0; + int opcode_mask = 0x3ff; + uint32_t recomp_opcode_mask = 0x1ff; + uint32_t op_32 = use32; + int over = 0; + int test_modrm = 1; + int pc_off = 0; + uint32_t next_pc = 0; #ifdef DEBUG_EXTRA - uint8_t last_prefix = 0; + uint8_t last_prefix = 0; #endif - op_ea_seg = &cpu_state.seg_ds; - op_ssegs = 0; + op_ea_seg = &cpu_state.seg_ds; + op_ssegs = 0; - codegen_timing_start(); + codegen_timing_start(); - while (!over) - { - switch (opcode) - { - case 0x0f: + while (!over) { + switch (opcode) { + case 0x0f: #ifdef DEBUG_EXTRA - last_prefix = 0x0f; + last_prefix = 0x0f; #endif - op_table = (OpFn *) x86_dynarec_opcodes_0f; - recomp_op_table = recomp_opcodes_0f; - over = 1; - break; + op_table = x86_dynarec_opcodes_0f; + recomp_op_table = fpu_softfloat ? recomp_opcodes_0f_no_mmx : recomp_opcodes_0f; + over = 1; + break; - case 0x26: /*ES:*/ - op_ea_seg = &cpu_state.seg_es; - op_ssegs = 1; - break; - case 0x2e: /*CS:*/ - op_ea_seg = &cpu_state.seg_cs; - op_ssegs = 1; - break; - case 0x36: /*SS:*/ - op_ea_seg = &cpu_state.seg_ss; - op_ssegs = 1; - break; - case 0x3e: /*DS:*/ - op_ea_seg = &cpu_state.seg_ds; - op_ssegs = 1; - break; - case 0x64: /*FS:*/ - op_ea_seg = &cpu_state.seg_fs; - op_ssegs = 1; - break; - case 0x65: /*GS:*/ - op_ea_seg = &cpu_state.seg_gs; - op_ssegs = 1; - break; + case 0x26: /*ES:*/ + op_ea_seg = &cpu_state.seg_es; + op_ssegs = 1; + break; + case 0x2e: /*CS:*/ + op_ea_seg = &cpu_state.seg_cs; + op_ssegs = 1; + break; + case 0x36: /*SS:*/ + op_ea_seg = &cpu_state.seg_ss; + op_ssegs = 1; + break; + case 0x3e: /*DS:*/ + op_ea_seg = &cpu_state.seg_ds; + op_ssegs = 1; + break; + case 0x64: /*FS:*/ + op_ea_seg = &cpu_state.seg_fs; + op_ssegs = 1; + break; + case 0x65: /*GS:*/ + op_ea_seg = &cpu_state.seg_gs; + op_ssegs = 1; + break; - case 0x66: /*Data size select*/ - op_32 = ((use32 & 0x100) ^ 0x100) | (op_32 & 0x200); - break; - case 0x67: /*Address size select*/ - op_32 = ((use32 & 0x200) ^ 0x200) | (op_32 & 0x100); - break; + case 0x66: /*Data size select*/ + op_32 = ((use32 & 0x100) ^ 0x100) | (op_32 & 0x200); + break; + case 0x67: /*Address size select*/ + op_32 = ((use32 & 0x200) ^ 0x200) | (op_32 & 0x100); + break; - case 0xd8: + case 0xd8: #ifdef DEBUG_EXTRA - last_prefix = 0xd8; + last_prefix = 0xd8; #endif - op_table = (op_32 & 0x200) ? (OpFn *) x86_dynarec_opcodes_d8_a32 : (OpFn *) x86_dynarec_opcodes_d8_a16; - recomp_op_table = recomp_opcodes_d8; - opcode_shift = 3; - opcode_mask = 0x1f; - over = 1; - pc_off = -1; - test_modrm = 0; - block->flags |= CODEBLOCK_HAS_FPU; - break; - case 0xd9: + op_table = (op_32 & 0x200) ? x86_dynarec_opcodes_d8_a32 : x86_dynarec_opcodes_d8_a16; + recomp_op_table = fpu_softfloat ? NULL : recomp_opcodes_d8; + opcode_shift = 3; + opcode_mask = 0x1f; + over = 1; + pc_off = -1; + test_modrm = 0; + block->flags |= CODEBLOCK_HAS_FPU; + break; + case 0xd9: #ifdef DEBUG_EXTRA - last_prefix = 0xd9; + last_prefix = 0xd9; #endif - op_table = (op_32 & 0x200) ? (OpFn *) x86_dynarec_opcodes_d9_a32 : (OpFn *) x86_dynarec_opcodes_d9_a16; - recomp_op_table = recomp_opcodes_d9; - opcode_mask = 0xff; - over = 1; - pc_off = -1; - test_modrm = 0; - block->flags |= CODEBLOCK_HAS_FPU; - break; - case 0xda: + op_table = (op_32 & 0x200) ? x86_dynarec_opcodes_d9_a32 : x86_dynarec_opcodes_d9_a16; + recomp_op_table = fpu_softfloat ? NULL : recomp_opcodes_d9; + opcode_mask = 0xff; + over = 1; + pc_off = -1; + test_modrm = 0; + block->flags |= CODEBLOCK_HAS_FPU; + break; + case 0xda: #ifdef DEBUG_EXTRA - last_prefix = 0xda; + last_prefix = 0xda; #endif - op_table = (op_32 & 0x200) ? (OpFn *) x86_dynarec_opcodes_da_a32 : (OpFn *) x86_dynarec_opcodes_da_a16; - recomp_op_table = recomp_opcodes_da; - opcode_mask = 0xff; - over = 1; - pc_off = -1; - test_modrm = 0; - block->flags |= CODEBLOCK_HAS_FPU; - break; - case 0xdb: + op_table = (op_32 & 0x200) ? x86_dynarec_opcodes_da_a32 : x86_dynarec_opcodes_da_a16; + recomp_op_table = fpu_softfloat ? NULL : recomp_opcodes_da; + opcode_mask = 0xff; + over = 1; + pc_off = -1; + test_modrm = 0; + block->flags |= CODEBLOCK_HAS_FPU; + break; + case 0xdb: #ifdef DEBUG_EXTRA - last_prefix = 0xdb; + last_prefix = 0xdb; #endif - op_table = (op_32 & 0x200) ? (OpFn *) x86_dynarec_opcodes_db_a32 : (OpFn *) x86_dynarec_opcodes_db_a16; - recomp_op_table = recomp_opcodes_db; - opcode_mask = 0xff; - over = 1; - pc_off = -1; - test_modrm = 0; - block->flags |= CODEBLOCK_HAS_FPU; - break; - case 0xdc: + op_table = (op_32 & 0x200) ? x86_dynarec_opcodes_db_a32 : x86_dynarec_opcodes_db_a16; + recomp_op_table = fpu_softfloat ? NULL : recomp_opcodes_db; + opcode_mask = 0xff; + over = 1; + pc_off = -1; + test_modrm = 0; + block->flags |= CODEBLOCK_HAS_FPU; + break; + case 0xdc: #ifdef DEBUG_EXTRA - last_prefix = 0xdc; + last_prefix = 0xdc; #endif - op_table = (op_32 & 0x200) ? (OpFn *) x86_dynarec_opcodes_dc_a32 : (OpFn *) x86_dynarec_opcodes_dc_a16; - recomp_op_table = recomp_opcodes_dc; - opcode_shift = 3; - opcode_mask = 0x1f; - over = 1; - pc_off = -1; - test_modrm = 0; - block->flags |= CODEBLOCK_HAS_FPU; - break; - case 0xdd: + op_table = (op_32 & 0x200) ? x86_dynarec_opcodes_dc_a32 : x86_dynarec_opcodes_dc_a16; + recomp_op_table = fpu_softfloat ? NULL : recomp_opcodes_dc; + opcode_shift = 3; + opcode_mask = 0x1f; + over = 1; + pc_off = -1; + test_modrm = 0; + block->flags |= CODEBLOCK_HAS_FPU; + break; + case 0xdd: #ifdef DEBUG_EXTRA - last_prefix = 0xdd; + last_prefix = 0xdd; #endif - op_table = (op_32 & 0x200) ? (OpFn *) x86_dynarec_opcodes_dd_a32 : (OpFn *) x86_dynarec_opcodes_dd_a16; - recomp_op_table = recomp_opcodes_dd; - opcode_mask = 0xff; - over = 1; - pc_off = -1; - test_modrm = 0; - block->flags |= CODEBLOCK_HAS_FPU; - break; - case 0xde: + op_table = (op_32 & 0x200) ? x86_dynarec_opcodes_dd_a32 : x86_dynarec_opcodes_dd_a16; + recomp_op_table = fpu_softfloat ? NULL : recomp_opcodes_dd; + opcode_mask = 0xff; + over = 1; + pc_off = -1; + test_modrm = 0; + block->flags |= CODEBLOCK_HAS_FPU; + break; + case 0xde: #ifdef DEBUG_EXTRA - last_prefix = 0xde; + last_prefix = 0xde; #endif - op_table = (op_32 & 0x200) ? (OpFn *) x86_dynarec_opcodes_de_a32 : (OpFn *) x86_dynarec_opcodes_de_a16; - recomp_op_table = recomp_opcodes_de; - opcode_mask = 0xff; - over = 1; - pc_off = -1; - test_modrm = 0; - block->flags |= CODEBLOCK_HAS_FPU; - break; - case 0xdf: + op_table = (op_32 & 0x200) ? x86_dynarec_opcodes_de_a32 : x86_dynarec_opcodes_de_a16; + recomp_op_table = fpu_softfloat ? NULL : recomp_opcodes_de; + opcode_mask = 0xff; + over = 1; + pc_off = -1; + test_modrm = 0; + block->flags |= CODEBLOCK_HAS_FPU; + break; + case 0xdf: #ifdef DEBUG_EXTRA - last_prefix = 0xdf; + last_prefix = 0xdf; #endif - op_table = (op_32 & 0x200) ? (OpFn *) x86_dynarec_opcodes_df_a32 : (OpFn *) x86_dynarec_opcodes_df_a16; - recomp_op_table = recomp_opcodes_df; - opcode_mask = 0xff; - over = 1; - pc_off = -1; - test_modrm = 0; - block->flags |= CODEBLOCK_HAS_FPU; - break; + op_table = (op_32 & 0x200) ? x86_dynarec_opcodes_df_a32 : x86_dynarec_opcodes_df_a16; + recomp_op_table = fpu_softfloat ? NULL : recomp_opcodes_df; + opcode_mask = 0xff; + over = 1; + pc_off = -1; + test_modrm = 0; + block->flags |= CODEBLOCK_HAS_FPU; + break; - case 0xf0: /*LOCK*/ - break; + case 0xf0: /*LOCK*/ + break; - case 0xf2: /*REPNE*/ + case 0xf2: /*REPNE*/ #ifdef DEBUG_EXTRA - last_prefix = 0xf2; + last_prefix = 0xf2; #endif - op_table = (OpFn *) x86_dynarec_opcodes_REPNE; - recomp_op_table = NULL;//recomp_opcodes_REPNE; - break; - case 0xf3: /*REPE*/ + op_table = x86_dynarec_opcodes_REPNE; + recomp_op_table = NULL; // recomp_opcodes_REPNE; + break; + case 0xf3: /*REPE*/ #ifdef DEBUG_EXTRA - last_prefix = 0xf3; + last_prefix = 0xf3; #endif - op_table = (OpFn *) x86_dynarec_opcodes_REPE; - recomp_op_table = NULL;//recomp_opcodes_REPE; - break; + op_table = x86_dynarec_opcodes_REPE; + recomp_op_table = NULL; // recomp_opcodes_REPE; + break; - default: - goto generate_call; - } - fetchdat = fastreadl(cs + op_pc); - codegen_timing_prefix(opcode, fetchdat); - if (cpu_state.abrt) - return; - opcode = fetchdat & 0xff; - if (!pc_off) - fetchdat >>= 8; - - op_pc++; + default: + goto generate_call; } + fetchdat = fastreadl(cs + op_pc); + codegen_timing_prefix(opcode, fetchdat); + if (cpu_state.abrt) + return; + opcode = fetchdat & 0xff; + if (!pc_off) + fetchdat >>= 8; + + op_pc++; + } generate_call: - codegen_instructions[block->ins].pc = cpu_state.oldpc; - codegen_instructions[block->ins].op_ssegs = last_op_ssegs; - codegen_instructions[block->ins].op_ea_seg = last_op_ea_seg; - codegen_instructions[block->ins].op_32 = last_op_32; - codegen_instructions[block->ins].TOP = cpu_state.TOP; - codegen_instructions[block->ins].first_uop = ir->wr_pos; + codegen_instructions[block->ins].pc = cpu_state.oldpc; + codegen_instructions[block->ins].op_ssegs = last_op_ssegs; + codegen_instructions[block->ins].op_ea_seg = last_op_ea_seg; + codegen_instructions[block->ins].op_32 = last_op_32; + codegen_instructions[block->ins].TOP = cpu_state.TOP; + codegen_instructions[block->ins].first_uop = ir->wr_pos; - codegen_timing_opcode(opcode, fetchdat, op_32, op_pc); + codegen_timing_opcode(opcode, fetchdat, op_32, op_pc); - codegen_accumulate(ir, ACCREG_cycles, -codegen_block_cycles); - codegen_block_cycles = 0; + codegen_accumulate(ir, ACCREG_cycles, -codegen_block_cycles); + codegen_block_cycles = 0; - if ((op_table == x86_dynarec_opcodes && - ((opcode & 0xf0) == 0x70 || (opcode & 0xfc) == 0xe0 || opcode == 0xc2 || - (opcode & 0xfe) == 0xca || (opcode & 0xfc) == 0xcc || (opcode & 0xfc) == 0xe8 || - (opcode == 0xff && ((fetchdat & 0x38) >= 0x10 && (fetchdat & 0x38) < 0x30)))) || - (op_table == x86_dynarec_opcodes_0f && ((opcode & 0xf0) == 0x80))) - { - /*On some CPUs (eg K6), a jump/branch instruction may be able to pair with - subsequent instructions, so no cycles may have been deducted for it yet. - To prevent having zero cycle blocks (eg with a jump instruction pointing - to itself), apply the cycles that would be taken if this jump is taken, - then reverse it for subsequent instructions if the jump is not taken*/ - int jump_cycles = 0; + if ((op_table == x86_dynarec_opcodes && ((opcode & 0xf0) == 0x70 || (opcode & 0xfc) == 0xe0 || opcode == 0xc2 || (opcode & 0xfe) == 0xca || (opcode & 0xfc) == 0xcc || (opcode & 0xfc) == 0xe8 || (opcode == 0xff && ((fetchdat & 0x38) >= 0x10 && (fetchdat & 0x38) < 0x30)))) || (op_table == x86_dynarec_opcodes_0f && ((opcode & 0xf0) == 0x80))) { + /*On some CPUs (eg K6), a jump/branch instruction may be able to pair with + subsequent instructions, so no cycles may have been deducted for it yet. + To prevent having zero cycle blocks (eg with a jump instruction pointing + to itself), apply the cycles that would be taken if this jump is taken, + then reverse it for subsequent instructions if the jump is not taken*/ + int jump_cycles = 0; - if (codegen_timing_jump_cycles) - codegen_timing_jump_cycles(); - - if (jump_cycles) - codegen_accumulate(ir, ACCREG_cycles, -jump_cycles); - codegen_accumulate_flush(ir); - if (jump_cycles) - codegen_accumulate(ir, ACCREG_cycles, jump_cycles); + if (codegen_timing_jump_cycles) + codegen_timing_jump_cycles(); + + if (jump_cycles) + codegen_accumulate(ir, ACCREG_cycles, -jump_cycles); + codegen_accumulate_flush(ir); + if (jump_cycles) + codegen_accumulate(ir, ACCREG_cycles, jump_cycles); + } + + if (op_table == x86_dynarec_opcodes_0f && opcode == 0x0f) { + /*3DNow opcodes are stored after ModR/M, SIB and any offset*/ + uint8_t modrm = fetchdat & 0xff; + uint8_t sib = (fetchdat >> 8) & 0xff; + uint32_t opcode_pc = op_pc + 1; + uint8_t opcode_3dnow; + + if ((modrm & 0xc0) != 0xc0) { + if (op_32 & 0x200) { + if ((modrm & 7) == 4) { + /* Has SIB*/ + opcode_pc++; + if ((modrm & 0xc0) == 0x40) + opcode_pc++; + else if ((modrm & 0xc0) == 0x80) + opcode_pc += 4; + else if ((sib & 0x07) == 0x05) + opcode_pc += 4; + } else { + if ((modrm & 0xc0) == 0x40) + opcode_pc++; + else if ((modrm & 0xc0) == 0x80) + opcode_pc += 4; + else if ((modrm & 0xc7) == 0x05) + opcode_pc += 4; + } + } else { + if ((modrm & 0xc0) == 0x40) + opcode_pc++; + else if ((modrm & 0xc0) == 0x80) + opcode_pc += 2; + else if ((modrm & 0xc7) == 0x06) + opcode_pc += 2; + } } - if (op_table == x86_dynarec_opcodes_0f && opcode == 0x0f) - { - /*3DNow opcodes are stored after ModR/M, SIB and any offset*/ - uint8_t modrm = fetchdat & 0xff; - uint8_t sib = (fetchdat >> 8) & 0xff; - uint32_t opcode_pc = op_pc + 1; - uint8_t opcode_3dnow; + opcode_3dnow = fastreadb(cs + opcode_pc); + if (!fpu_softfloat && recomp_opcodes_3DNOW[opcode_3dnow]) { + next_pc = opcode_pc + 1; - if ((modrm & 0xc0) != 0xc0) - { - if (op_32 & 0x200) - { - if ((modrm & 7) == 4) - { - /* Has SIB*/ - opcode_pc++; - if ((modrm & 0xc0) == 0x40) - opcode_pc++; - else if ((modrm & 0xc0) == 0x80) - opcode_pc += 4; - else if ((sib & 0x07) == 0x05) - opcode_pc += 4; - } - else - { - if ((modrm & 0xc0) == 0x40) - opcode_pc++; - else if ((modrm & 0xc0) == 0x80) - opcode_pc += 4; - else if ((modrm & 0xc7) == 0x05) - opcode_pc += 4; - } - } - else - { - if ((modrm & 0xc0) == 0x40) - opcode_pc++; - else if ((modrm & 0xc0) == 0x80) - opcode_pc += 2; - else if ((modrm & 0xc7) == 0x06) - opcode_pc += 2; - } - } - - opcode_3dnow = fastreadb(cs + opcode_pc); - if (recomp_opcodes_3DNOW[opcode_3dnow]) - { - next_pc = opcode_pc + 1; - - op_table = (OpFn *) x86_dynarec_opcodes_3DNOW; - recomp_op_table = recomp_opcodes_3DNOW; - opcode = opcode_3dnow; - recomp_opcode_mask = 0xff; - opcode_mask = 0xff; - } + op_table = x86_dynarec_opcodes_3DNOW; + recomp_op_table = fpu_softfloat ? NULL : recomp_opcodes_3DNOW; + opcode = opcode_3dnow; + recomp_opcode_mask = 0xff; + opcode_mask = 0xff; } - codegen_mark_code_present(block, cs+old_pc, (op_pc - old_pc) - pc_off); - /* It is apparently a prefixed instruction. */ - // if ((recomp_op_table == recomp_opcodes) && (opcode == 0x48)) - // goto codegen_skip; + } + codegen_mark_code_present(block, cs + old_pc, (op_pc - old_pc) - pc_off); + /* It is apparently a prefixed instruction. */ +#if 0 + if ((recomp_op_table == recomp_opcodes) && (opcode == 0x48)) + goto codegen_skip; +#endif - if (recomp_op_table && recomp_op_table[(opcode | op_32) & recomp_opcode_mask]) - { - uint32_t new_pc = recomp_op_table[(opcode | op_32) & recomp_opcode_mask](block, ir, opcode, fetchdat, op_32, op_pc); - if (new_pc) - { - if (new_pc != -1) - uop_MOV_IMM(ir, IREG_pc, new_pc); + if (recomp_op_table && recomp_op_table[(opcode | op_32) & recomp_opcode_mask]) { + uint32_t new_pc = recomp_op_table[(opcode | op_32) & recomp_opcode_mask](block, ir, opcode, fetchdat, op_32, op_pc); + if (new_pc) { + if (new_pc != -1) + uop_MOV_IMM(ir, IREG_pc, new_pc); - codegen_endpc = (cs + cpu_state.pc) + 8; + codegen_endpc = (cs + cpu_state.pc) + 8; - block->ins++; + block->ins++; - if (block->ins >= MAX_INSTRUCTION_COUNT) - CPU_BLOCK_END(); + if (block->ins >= MAX_INSTRUCTION_COUNT) + CPU_BLOCK_END(); - return; - } + return; } + } -// codegen_skip: - if ((op_table == x86_dynarec_opcodes_REPNE || op_table == x86_dynarec_opcodes_REPE) && !op_table[opcode | op_32]) - { - op_table = (OpFn *) x86_dynarec_opcodes; - recomp_op_table = recomp_opcodes; + // codegen_skip: + if ((op_table == x86_dynarec_opcodes_REPNE || op_table == x86_dynarec_opcodes_REPE) && !op_table[opcode | op_32]) { + op_table = x86_dynarec_opcodes; + recomp_op_table = recomp_opcodes; + } + + op = op_table[((opcode >> opcode_shift) | op_32) & opcode_mask]; + + if (!test_modrm || (op_table == x86_dynarec_opcodes && opcode_modrm[opcode]) || (op_table == x86_dynarec_opcodes_0f && opcode_0f_modrm[opcode]) || (op_table == x86_dynarec_opcodes_3DNOW)) { + int stack_offset = 0; + + if (op_table == x86_dynarec_opcodes && opcode == 0x8f) /*POP*/ + stack_offset = (op_32 & 0x100) ? 4 : 2; + + cpu_mod = (fetchdat >> 6) & 3; + cpu_reg = (fetchdat >> 3) & 7; + cpu_rm = fetchdat & 7; + + uop_MOV_IMM(ir, IREG_rm_mod_reg, cpu_rm | (cpu_mod << 8) | (cpu_reg << 16)); + + op_pc += pc_off; + if (cpu_mod != 3 && !(op_32 & 0x200)) { + op_ea_seg = codegen_generate_ea_16_long(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc); } - - op = op_table[((opcode >> opcode_shift) | op_32) & opcode_mask]; - - if (!test_modrm || - (op_table == x86_dynarec_opcodes && opcode_modrm[opcode]) || - (op_table == x86_dynarec_opcodes_0f && opcode_0f_modrm[opcode]) || - (op_table == x86_dynarec_opcodes_3DNOW)) - { - int stack_offset = 0; - - if (op_table == x86_dynarec_opcodes && opcode == 0x8f) /*POP*/ - stack_offset = (op_32 & 0x100) ? 4 : 2; - - cpu_mod = (fetchdat >> 6) & 3; - cpu_reg = (fetchdat >> 3) & 7; - cpu_rm = fetchdat & 7; - - uop_MOV_IMM(ir, IREG_rm_mod_reg, cpu_rm | (cpu_mod << 8) | (cpu_reg << 16)); - - op_pc += pc_off; - if (cpu_mod != 3 && !(op_32 & 0x200)) - { - op_ea_seg = codegen_generate_ea_16_long(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc); - } - if (cpu_mod != 3 && (op_32 & 0x200)) - { - op_ea_seg = codegen_generate_ea_32_long(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, stack_offset); - } - op_pc -= pc_off; + if (cpu_mod != 3 && (op_32 & 0x200)) { + op_ea_seg = codegen_generate_ea_32_long(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, stack_offset); } + op_pc -= pc_off; + } #ifdef DEBUG_EXTRA - uop_LOG_INSTR(ir, opcode | (last_prefix << 8)); + uop_LOG_INSTR(ir, opcode | (last_prefix << 8)); #endif - codegen_accumulate_flush(ir); - if (op_table == x86_dynarec_opcodes_3DNOW) - uop_MOV_IMM(ir, IREG_pc, next_pc); - else - uop_MOV_IMM(ir, IREG_pc, op_pc+pc_off); - uop_MOV_IMM(ir, IREG_oldpc, old_pc); - if (op_32 != last_op_32) - uop_MOV_IMM(ir, IREG_op32, op_32); - if (op_ea_seg != last_op_ea_seg) - uop_MOV_PTR(ir, IREG_ea_seg, (void *)op_ea_seg); - if (op_ssegs != last_op_ssegs) - uop_MOV_IMM(ir, IREG_ssegs, op_ssegs); - uop_LOAD_FUNC_ARG_IMM(ir, 0, fetchdat); - uop_CALL_INSTRUCTION_FUNC(ir, op); - codegen_mark_code_present(block, cs+cpu_state.pc, 8); + codegen_accumulate_flush(ir); + if (op_table == x86_dynarec_opcodes_3DNOW) + uop_MOV_IMM(ir, IREG_pc, next_pc); + else + uop_MOV_IMM(ir, IREG_pc, op_pc + pc_off); + uop_MOV_IMM(ir, IREG_oldpc, old_pc); + if (op_32 != last_op_32) + uop_MOV_IMM(ir, IREG_op32, op_32); + if (op_ea_seg != last_op_ea_seg) + uop_MOV_PTR(ir, IREG_ea_seg, (void *) op_ea_seg); + if (op_ssegs != last_op_ssegs) + uop_MOV_IMM(ir, IREG_ssegs, op_ssegs); + uop_LOAD_FUNC_ARG_IMM(ir, 0, fetchdat); + uop_CALL_INSTRUCTION_FUNC(ir, op); + codegen_flags_changed = 0; + codegen_mark_code_present(block, cs + cpu_state.pc, 8); - last_op_32 = op_32; - last_op_ea_seg = op_ea_seg; - last_op_ssegs = op_ssegs; - //codegen_block_ins++; - - block->ins++; + last_op_32 = op_32; + last_op_ea_seg = op_ea_seg; + last_op_ssegs = op_ssegs; +#if 0 + codegen_block_ins++; +#endif - if (block->ins >= MAX_INSTRUCTION_COUNT) - CPU_BLOCK_END(); + block->ins++; - codegen_endpc = (cs + cpu_state.pc) + 8; - -// if (has_ea) -// fatal("Has EA\n"); + if (block->ins >= MAX_INSTRUCTION_COUNT) + CPU_BLOCK_END(); + + codegen_endpc = (cs + cpu_state.pc) + 8; + +#if 0 + if (has_ea) + fatal("Has EA\n"); +#endif } diff --git a/src/codegen_new/codegen.h b/src/codegen_new/codegen.h index 8dd5222e7..deeeb899c 100644 --- a/src/codegen_new/codegen.h +++ b/src/codegen_new/codegen.h @@ -13,51 +13,50 @@ added to the page_lookup for this purpose. When in the page_lookup, each write will go through the mem_write_ram*_page() functions and set the dirty mask appropriately. - + Each codeblock also contains a code mask (actually two masks, one for each page the block is/may be in), again with each bit representing 64 bytes. - + Each page has a list of codeblocks present in it. As each codeblock can span up to two pages, two lists are present. - + When a codeblock is about to be executed, the code masks are compared with the dirty masks for the relevant pages. If either intersect, then codegen_check_flush() is called on the affected page(s), and all affected blocks are evicted. - + The 64 byte granularity appears to work reasonably well for most cases, avoiding most unnecessary evictions (eg when code & data are stored in the same page). */ -typedef struct codeblock_t -{ - uint32_t pc; - uint32_t _cs; - uint32_t phys, phys_2; - uint16_t status; - uint16_t flags; - uint8_t ins; - uint8_t TOP; +typedef struct codeblock_t { + uint32_t pc; + uint32_t _cs; + uint32_t phys, phys_2; + uint16_t status; + uint16_t flags; + uint8_t ins; + uint8_t TOP; - /*Pointers for codeblock tree, used to search for blocks when hash lookup - fails.*/ - uint16_t parent, left, right; + /*Pointers for codeblock tree, used to search for blocks when hash lookup + fails.*/ + uint16_t parent, left, right; - uint8_t *data; - - uint64_t page_mask, page_mask2; - uint64_t *dirty_mask, *dirty_mask2; + uint8_t *data; - /*Previous and next pointers, for the codeblock list associated with - each physical page. Two sets of pointers, as a codeblock can be - present in two pages.*/ - uint16_t prev, next; - uint16_t prev_2, next_2; + uint64_t page_mask, page_mask2; + uint64_t *dirty_mask, *dirty_mask2; - /*First mem_block_t used by this block. Any subsequent mem_block_ts - will be in the list starting at head_mem_block->next.*/ - struct mem_block_t *head_mem_block; + /*Previous and next pointers, for the codeblock list associated with + each physical page. Two sets of pointers, as a codeblock can be + present in two pages.*/ + uint16_t prev, next; + uint16_t prev_2, next_2; + + /*First mem_block_t used by this block. Any subsequent mem_block_ts + will be in the list starting at head_mem_block->next.*/ + struct mem_block_t *head_mem_block; } codeblock_t; extern codeblock_t *codeblock; @@ -83,262 +82,237 @@ extern uint8_t *block_write_data; /*Code block is not inlining immediate parameters, parameters must be fetched from memory*/ #define CODEBLOCK_NO_IMMEDIATES 0x80 -#define BLOCK_PC_INVALID 0xffffffff +#define BLOCK_PC_INVALID 0xffffffff -#define BLOCK_INVALID 0 +#define BLOCK_INVALID 0 -static inline int get_block_nr(codeblock_t *block) +static inline int +get_block_nr(codeblock_t *block) { - return ((uintptr_t)block - (uintptr_t)codeblock) / sizeof(codeblock_t); + return ((uintptr_t) block - (uintptr_t) codeblock) / sizeof(codeblock_t); } -static inline codeblock_t *codeblock_tree_find(uint32_t phys, uint32_t _cs) +static inline codeblock_t * +codeblock_tree_find(uint32_t phys, uint32_t _cs) { - codeblock_t *block; - uint64_t a = _cs | ((uint64_t)phys << 32); - - if (!pages[phys >> 12].head) - return NULL; - - block = &codeblock[pages[phys >> 12].head]; - while (block) - { - uint64_t block_cmp = block->_cs | ((uint64_t)block->phys << 32); - if (a == block_cmp) - { - if (!((block->status ^ cpu_cur_status) & CPU_STATUS_FLAGS) && - ((block->status & cpu_cur_status & CPU_STATUS_MASK) == (cpu_cur_status & CPU_STATUS_MASK))) - break; - } - if (a < block_cmp) - block = block->left ? &codeblock[block->left] : NULL; - else - block = block->right ? &codeblock[block->right] : NULL; - } - - return block; -} + codeblock_t *block; + uint64_t a = _cs | ((uint64_t) phys << 32); -static inline void codeblock_tree_add(codeblock_t *new_block) -{ - codeblock_t *block = &codeblock[pages[new_block->phys >> 12].head]; - uint64_t a = new_block->_cs | ((uint64_t)new_block->phys << 32); + if (!pages[phys >> 12].head) + return NULL; - if (!pages[new_block->phys >> 12].head) - { - pages[new_block->phys >> 12].head = get_block_nr(new_block); - new_block->parent = new_block->left = new_block->right = BLOCK_INVALID; + block = &codeblock[pages[phys >> 12].head]; + while (block) { + uint64_t block_cmp = block->_cs | ((uint64_t) block->phys << 32); + if (a == block_cmp) { + if (!((block->status ^ cpu_cur_status) & CPU_STATUS_FLAGS) && ((block->status & cpu_cur_status & CPU_STATUS_MASK) == (cpu_cur_status & CPU_STATUS_MASK))) + break; } + if (a < block_cmp) + block = block->left ? &codeblock[block->left] : NULL; else - { - codeblock_t *old_block = NULL; - uint64_t old_block_cmp = 0; - - while (block) - { - old_block = block; - old_block_cmp = old_block->_cs | ((uint64_t)old_block->phys << 32); - - if (a < old_block_cmp) - block = block->left ? &codeblock[block->left] : NULL; - else - block = block->right ? &codeblock[block->right] : NULL; - } - - if (a < old_block_cmp) - old_block->left = get_block_nr(new_block); - else - old_block->right = get_block_nr(new_block); - - new_block->parent = get_block_nr(old_block); - new_block->left = new_block->right = BLOCK_INVALID; - } + block = block->right ? &codeblock[block->right] : NULL; + } + + return block; } -static inline void codeblock_tree_delete(codeblock_t *block) +static inline void +codeblock_tree_add(codeblock_t *new_block) { - uint16_t parent_nr = block->parent; - codeblock_t *parent; + codeblock_t *block = &codeblock[pages[new_block->phys >> 12].head]; + uint64_t a = new_block->_cs | ((uint64_t) new_block->phys << 32); - if (block->parent) - parent = &codeblock[block->parent]; - else - parent = NULL; + if (!pages[new_block->phys >> 12].head) { + pages[new_block->phys >> 12].head = get_block_nr(new_block); + new_block->parent = new_block->left = new_block->right = BLOCK_INVALID; + } else { + codeblock_t *old_block = NULL; + uint64_t old_block_cmp = 0; - if (!block->left && !block->right) - { - /*Easy case - remove from parent*/ - if (!parent) - pages[block->phys >> 12].head = BLOCK_INVALID; - else - { - uint16_t block_nr = get_block_nr(block); - - if (parent->left == block_nr) - parent->left = BLOCK_INVALID; - if (parent->right == block_nr) - parent->right = BLOCK_INVALID; - } - return; + while (block) { + old_block = block; + old_block_cmp = old_block->_cs | ((uint64_t) old_block->phys << 32); + + if (a < old_block_cmp) + block = block->left ? &codeblock[block->left] : NULL; + else + block = block->right ? &codeblock[block->right] : NULL; } - else if (!block->left) - { - /*Only right node*/ - if (!parent_nr) - { - pages[block->phys >> 12].head = block->right; - codeblock[pages[block->phys >> 12].head].parent = BLOCK_INVALID; - } - else - { - uint16_t block_nr = get_block_nr(block); - if (parent->left == block_nr) - { - parent->left = block->right; - codeblock[parent->left].parent = parent_nr; - } - if (parent->right == block_nr) - { - parent->right = block->right; - codeblock[parent->right].parent = parent_nr; - } - } - return; - } - else if (!block->right) - { - /*Only left node*/ - if (!parent_nr) - { - pages[block->phys >> 12].head = block->left; - codeblock[pages[block->phys >> 12].head].parent = BLOCK_INVALID; - } - else - { - uint16_t block_nr = get_block_nr(block); + if (old_block != NULL) { + if (a < old_block_cmp) + old_block->left = get_block_nr(new_block); + else + old_block->right = get_block_nr(new_block); - if (parent->left == block_nr) - { - parent->left = block->left; - codeblock[parent->left].parent = parent_nr; - } - if (parent->right == block_nr) - { - parent->right = block->left; - codeblock[parent->right].parent = parent_nr; - } - } - return; - } - else - { - /*Difficult case - node has two children. Walk right child to find lowest node*/ - codeblock_t *lowest = &codeblock[block->right], *highest; - codeblock_t *old_parent; - uint16_t lowest_nr; - - while (lowest->left) - lowest = &codeblock[lowest->left]; - lowest_nr = get_block_nr(lowest); - - old_parent = &codeblock[lowest->parent]; + new_block->parent = get_block_nr(old_block); + } else + new_block->parent = BLOCK_INVALID; - /*Replace deleted node with lowest node*/ - if (!parent_nr) - pages[block->phys >> 12].head = lowest_nr; - else - { - uint16_t block_nr = get_block_nr(block); - - if (parent->left == block_nr) - parent->left = lowest_nr; - if (parent->right == block_nr) - parent->right = lowest_nr; - } - - lowest->parent = parent_nr; - lowest->left = block->left; - if (lowest->left) - codeblock[lowest->left].parent = lowest_nr; - - old_parent->left = BLOCK_INVALID; - - highest = &codeblock[lowest->right]; - if (!lowest->right) - { - if (lowest_nr != block->right) - { - lowest->right = block->right; - codeblock[block->right].parent = lowest_nr; - } - return; - } - - while (highest->right) - highest = &codeblock[highest->right]; - - if (block->right && block->right != lowest_nr) - { - highest->right = block->right; - codeblock[block->right].parent = get_block_nr(highest); - } - } + new_block->left = new_block->right = BLOCK_INVALID; + } } -#define PAGE_MASK_MASK 63 +static inline void +codeblock_tree_delete(codeblock_t *block) +{ + uint16_t parent_nr = block->parent; + codeblock_t *parent; + + if (block->parent) + parent = &codeblock[block->parent]; + else + parent = NULL; + + if (!block->left && !block->right) { + /*Easy case - remove from parent*/ + if (!parent) + pages[block->phys >> 12].head = BLOCK_INVALID; + else { + uint16_t block_nr = get_block_nr(block); + + if (parent->left == block_nr) + parent->left = BLOCK_INVALID; + if (parent->right == block_nr) + parent->right = BLOCK_INVALID; + } + return; + } else if (!block->left) { + /*Only right node*/ + if (!parent_nr) { + pages[block->phys >> 12].head = block->right; + codeblock[pages[block->phys >> 12].head].parent = BLOCK_INVALID; + } else { + uint16_t block_nr = get_block_nr(block); + + if (parent->left == block_nr) { + parent->left = block->right; + codeblock[parent->left].parent = parent_nr; + } + if (parent->right == block_nr) { + parent->right = block->right; + codeblock[parent->right].parent = parent_nr; + } + } + return; + } else if (!block->right) { + /*Only left node*/ + if (!parent_nr) { + pages[block->phys >> 12].head = block->left; + codeblock[pages[block->phys >> 12].head].parent = BLOCK_INVALID; + } else { + uint16_t block_nr = get_block_nr(block); + + if (parent->left == block_nr) { + parent->left = block->left; + codeblock[parent->left].parent = parent_nr; + } + if (parent->right == block_nr) { + parent->right = block->left; + codeblock[parent->right].parent = parent_nr; + } + } + return; + } else { + /*Difficult case - node has two children. Walk right child to find lowest node*/ + codeblock_t *lowest = &codeblock[block->right]; + codeblock_t *highest; + codeblock_t *old_parent; + uint16_t lowest_nr; + + while (lowest->left) + lowest = &codeblock[lowest->left]; + lowest_nr = get_block_nr(lowest); + + old_parent = &codeblock[lowest->parent]; + + /*Replace deleted node with lowest node*/ + if (!parent_nr) + pages[block->phys >> 12].head = lowest_nr; + else { + uint16_t block_nr = get_block_nr(block); + + if (parent->left == block_nr) + parent->left = lowest_nr; + if (parent->right == block_nr) + parent->right = lowest_nr; + } + + lowest->parent = parent_nr; + lowest->left = block->left; + if (lowest->left) + codeblock[lowest->left].parent = lowest_nr; + + old_parent->left = BLOCK_INVALID; + + highest = &codeblock[lowest->right]; + if (!lowest->right) { + if (lowest_nr != block->right) { + lowest->right = block->right; + codeblock[block->right].parent = lowest_nr; + } + return; + } + + while (highest->right) + highest = &codeblock[highest->right]; + + if (block->right && block->right != lowest_nr) { + highest->right = block->right; + codeblock[block->right].parent = get_block_nr(highest); + } + } +} + +#define PAGE_MASK_MASK 63 #define PAGE_MASK_SHIFT 6 void codegen_mark_code_present_multibyte(codeblock_t *block, uint32_t start_pc, int len); -static inline void codegen_mark_code_present(codeblock_t *block, uint32_t start_pc, int len) +static inline void +codegen_mark_code_present(codeblock_t *block, uint32_t start_pc, int len) { - if (len == 1) - { - if (block->flags & CODEBLOCK_BYTE_MASK) - { - if (!((start_pc ^ block->pc) & ~0x3f)) /*Starts in second page*/ - block->page_mask |= ((uint64_t)1 << (start_pc & PAGE_MASK_MASK)); - else - block->page_mask2 |= ((uint64_t)1 << (start_pc & PAGE_MASK_MASK)); - } - else - { - if (!((start_pc ^ block->pc) & ~0xfff)) /*Starts in second page*/ - block->page_mask |= ((uint64_t)1 << ((start_pc >> PAGE_MASK_SHIFT) & PAGE_MASK_MASK)); - else - block->page_mask2 |= ((uint64_t)1 << ((start_pc >> PAGE_MASK_SHIFT) & PAGE_MASK_MASK)); - } + if (len == 1) { + if (block->flags & CODEBLOCK_BYTE_MASK) { + if (!((start_pc ^ block->pc) & ~0x3f)) /*Starts in second page*/ + block->page_mask |= ((uint64_t) 1 << (start_pc & PAGE_MASK_MASK)); + else + block->page_mask2 |= ((uint64_t) 1 << (start_pc & PAGE_MASK_MASK)); + } else { + if (!((start_pc ^ block->pc) & ~0xfff)) /*Starts in second page*/ + block->page_mask |= ((uint64_t) 1 << ((start_pc >> PAGE_MASK_SHIFT) & PAGE_MASK_MASK)); + else + block->page_mask2 |= ((uint64_t) 1 << ((start_pc >> PAGE_MASK_SHIFT) & PAGE_MASK_MASK)); } - else - codegen_mark_code_present_multibyte(block, start_pc, len); + } else + codegen_mark_code_present_multibyte(block, start_pc, len); } -void codegen_init(); -void codegen_close(); -void codegen_reset(); -void codegen_block_init(uint32_t phys_addr); -void codegen_block_remove(); -void codegen_block_start_recompile(codeblock_t *block); -void codegen_block_end_recompile(codeblock_t *block); -void codegen_block_end(); -void codegen_delete_block(codeblock_t *block); -void codegen_generate_call(uint8_t opcode, OpFn op, uint32_t fetchdat, uint32_t new_pc, uint32_t old_pc); -void codegen_generate_seg_restore(); -void codegen_set_op32(); -void codegen_flush(); -void codegen_check_flush(struct page_t *page, uint64_t mask, uint32_t phys_addr); +extern void codegen_init(void); +extern void codegen_reset(void); +extern void codegen_block_init(uint32_t phys_addr); +extern void codegen_block_remove(void); +extern void codegen_block_start_recompile(codeblock_t *block); +extern void codegen_block_end_recompile(codeblock_t *block); +extern void codegen_block_end(void); +extern void codegen_delete_block(codeblock_t *block); +extern void codegen_generate_call(uint8_t opcode, OpFn op, uint32_t fetchdat, uint32_t new_pc, uint32_t old_pc); +extern void codegen_generate_seg_restore(void); +extern void codegen_set_op32(void); +extern void codegen_flush(void); +extern void codegen_check_flush(struct page_t *page, uint64_t mask, uint32_t phys_addr); struct ir_data_t; -x86seg *codegen_generate_ea(struct ir_data_t *ir, x86seg *op_ea_seg, uint32_t fetchdat, int op_ssegs, uint32_t *op_pc, uint32_t op_32, int stack_offset); -void codegen_check_seg_read(codeblock_t *block, struct ir_data_t *ir, x86seg *seg); -void codegen_check_seg_write(codeblock_t *block, struct ir_data_t *ir, x86seg *seg); +x86seg *codegen_generate_ea(struct ir_data_t *ir, x86seg *op_ea_seg, uint32_t fetchdat, int op_ssegs, uint32_t *op_pc, uint32_t op_32, int stack_offset); +extern void codegen_check_seg_read(codeblock_t *block, struct ir_data_t *ir, x86seg *seg); +extern void codegen_check_seg_write(codeblock_t *block, struct ir_data_t *ir, x86seg *seg); -int codegen_purge_purgable_list(); +extern int codegen_purge_purgable_list(void); /*Delete a random code block to free memory. This is obviously quite expensive, and will only be called when the allocator is out of memory*/ -void codegen_delete_random_block(int required_mem_block); +extern void codegen_delete_random_block(int required_mem_block); -extern int cpu_block_end; +extern int cpu_block_end; extern uint32_t codegen_endpc; extern int cpu_reps; @@ -346,21 +320,20 @@ extern int cpu_notreps; extern int codegen_block_cycles; -extern void (*codegen_timing_start)(); +extern void (*codegen_timing_start)(void); extern void (*codegen_timing_prefix)(uint8_t prefix, uint32_t fetchdat); extern void (*codegen_timing_opcode)(uint8_t opcode, uint32_t fetchdat, int op_32, uint32_t op_pc); -extern void (*codegen_timing_block_start)(); -extern void (*codegen_timing_block_end)(); -extern int (*codegen_timing_jump_cycles)(); +extern void (*codegen_timing_block_start)(void); +extern void (*codegen_timing_block_end)(void); +extern int (*codegen_timing_jump_cycles)(void); -typedef struct codegen_timing_t -{ - void (*start)(); - void (*prefix)(uint8_t prefix, uint32_t fetchdat); - void (*opcode)(uint8_t opcode, uint32_t fetchdat, int op_32, uint32_t op_pc); - void (*block_start)(); - void (*block_end)(); - int (*jump_cycles)(); +typedef struct codegen_timing_t { + void (*start)(void); + void (*prefix)(uint8_t prefix, uint32_t fetchdat); + void (*opcode)(uint8_t opcode, uint32_t fetchdat, int op_32, uint32_t op_pc); + void (*block_start)(void); + void (*block_end)(void); + int (*jump_cycles)(void); } codegen_timing_t; extern codegen_timing_t codegen_timing_pentium; @@ -371,7 +344,6 @@ extern codegen_timing_t codegen_timing_winchip2; extern codegen_timing_t codegen_timing_k6; extern codegen_timing_t codegen_timing_p6; - void codegen_timing_set(codegen_timing_t *timing); extern int block_current; @@ -382,8 +354,8 @@ extern int block_pos; /*Current physical page of block being recompiled. -1 if no recompilation taking place */ extern uint32_t recomp_page; -extern x86seg *op_ea_seg; -extern int op_ssegs; +extern x86seg *op_ea_seg; +extern int op_ssegs; extern uint32_t op_old_pc; /*Set to 1 if flags have been changed in the block being recompiled, and hence @@ -398,13 +370,13 @@ extern int codegen_reg_loaded[8]; extern int codegen_in_recompile; -void codegen_generate_reset(); +void codegen_generate_reset(void); -int codegen_get_instruction_uop(codeblock_t *block, uint32_t pc, int *first_instruction, int *TOP); +int codegen_get_instruction_uop(codeblock_t *block, uint32_t pc, int *first_instruction, int *TOP); void codegen_set_loop_start(struct ir_data_t *ir, int first_instruction); #ifdef DEBUG_EXTRA -extern uint32_t instr_counts[256*256]; +extern uint32_t instr_counts[256 * 256]; #endif #endif diff --git a/src/codegen_new/codegen_accumulate.c b/src/codegen_new/codegen_accumulate.c index f15776b74..29b05ad77 100644 --- a/src/codegen_new/codegen_accumulate.c +++ b/src/codegen_new/codegen_accumulate.c @@ -2,6 +2,7 @@ #include <86box/86box.h> #include "cpu.h" #include <86box/mem.h> +#include <86box/plat_unused.h> #include "codegen.h" #include "codegen_accumulate.h" @@ -9,34 +10,36 @@ static struct { - int count; - int dest_reg; -} acc_regs[] = -{ - [ACCREG_cycles] = {0, IREG_cycles} + int count; + int dest_reg; +} acc_regs[] = { + [ACCREG_cycles] = {0, IREG_cycles} }; -void codegen_accumulate(ir_data_t *ir, int acc_reg, int delta) +void +codegen_accumulate(UNUSED(ir_data_t *ir), int acc_reg, int delta) { - acc_regs[acc_reg].count += delta; + acc_regs[acc_reg].count += delta; #ifdef USE_ACYCS - if ((acc_reg == ACCREG_cycles) && (delta != 0)) { - uop_ADD_IMM(ir, IREG_acycs, IREG_acycs, -delta); - } + if ((acc_reg == ACCREG_cycles) && (delta != 0)) { + uop_ADD_IMM(ir, IREG_acycs, IREG_acycs, -delta); + } #endif } -void codegen_accumulate_flush(ir_data_t *ir) +void +codegen_accumulate_flush(ir_data_t *ir) { - if (acc_regs[0].count) { - uop_ADD_IMM(ir, acc_regs[0].dest_reg, acc_regs[0].dest_reg, acc_regs[0].count); - } + if (acc_regs[0].count) { + uop_ADD_IMM(ir, acc_regs[0].dest_reg, acc_regs[0].dest_reg, acc_regs[0].count); + } - acc_regs[0].count = 0; + acc_regs[0].count = 0; } -void codegen_accumulate_reset() +void +codegen_accumulate_reset(void) { - acc_regs[0].count = 0; + acc_regs[0].count = 0; } diff --git a/src/codegen_new/codegen_accumulate.h b/src/codegen_new/codegen_accumulate.h index a9ce2e871..5744c6362 100644 --- a/src/codegen_new/codegen_accumulate.h +++ b/src/codegen_new/codegen_accumulate.h @@ -1,12 +1,11 @@ -enum -{ - ACCREG_cycles = 0, - - ACCREG_COUNT +enum { + ACCREG_cycles = 0, + + ACCREG_COUNT }; struct ir_data_t; void codegen_accumulate(struct ir_data_t *ir, int acc_reg, int delta); void codegen_accumulate_flush(struct ir_data_t *ir); -void codegen_accumulate_reset(); +void codegen_accumulate_reset(void); diff --git a/src/codegen_new/codegen_allocator.c b/src/codegen_new/codegen_allocator.c index 7b8b04323..90e619d70 100644 --- a/src/codegen_new/codegen_allocator.c +++ b/src/codegen_new/codegen_allocator.c @@ -1,10 +1,10 @@ -#if defined(__linux__) || defined(__APPLE__) -#include -#include -#include +#if defined(__unix__) || defined(__APPLE__) || defined(__HAIKU__) +# include +# include +# include #endif #if defined WIN32 || defined _WIN32 || defined _WIN32 -#include +# include #endif #include @@ -13,122 +13,119 @@ #include <86box/86box.h> #include "cpu.h" #include <86box/mem.h> +#include <86box/plat_unused.h> #include "codegen.h" #include "codegen_allocator.h" -typedef struct mem_block_t -{ - uint32_t offset; /*Offset into mem_block_alloc*/ - uint32_t next; - uint16_t code_block; +typedef struct mem_block_t { + uint32_t offset; /*Offset into mem_block_alloc*/ + uint32_t next; + uint16_t code_block; } mem_block_t; static mem_block_t mem_blocks[MEM_BLOCK_NR]; -static uint32_t mem_block_free_list; -static uint8_t *mem_block_alloc = NULL; +static uint32_t mem_block_free_list; +static uint8_t *mem_block_alloc = NULL; int codegen_allocator_usage = 0; -void codegen_allocator_init() +void +codegen_allocator_init(void) { - int c; - #if defined WIN32 || defined _WIN32 || defined _WIN32 - mem_block_alloc = VirtualAlloc(NULL, MEM_BLOCK_NR * MEM_BLOCK_SIZE, MEM_COMMIT, PAGE_EXECUTE_READWRITE); - /* TODO: check deployment target: older Intel-based versions of macOS don't play - nice with MAP_JIT. */ + mem_block_alloc = VirtualAlloc(NULL, MEM_BLOCK_NR * MEM_BLOCK_SIZE, MEM_COMMIT, PAGE_EXECUTE_READWRITE); + /* TODO: check deployment target: older Intel-based versions of macOS don't play + nice with MAP_JIT. */ #elif defined(__APPLE__) && defined(MAP_JIT) - mem_block_alloc = mmap(0, MEM_BLOCK_NR * MEM_BLOCK_SIZE, PROT_READ|PROT_WRITE|PROT_EXEC, MAP_ANON|MAP_PRIVATE|MAP_JIT, -1, 0); + mem_block_alloc = mmap(0, MEM_BLOCK_NR * MEM_BLOCK_SIZE, PROT_READ | PROT_WRITE | PROT_EXEC, MAP_ANON | MAP_PRIVATE | MAP_JIT, -1, 0); #else - mem_block_alloc = mmap(0, MEM_BLOCK_NR * MEM_BLOCK_SIZE, PROT_READ|PROT_WRITE|PROT_EXEC, MAP_ANON|MAP_PRIVATE, -1, 0); + mem_block_alloc = mmap(0, MEM_BLOCK_NR * MEM_BLOCK_SIZE, PROT_READ | PROT_WRITE | PROT_EXEC, MAP_ANON | MAP_PRIVATE, -1, 0); #endif - for (c = 0; c < MEM_BLOCK_NR; c++) - { - mem_blocks[c].offset = c * MEM_BLOCK_SIZE; - mem_blocks[c].code_block = BLOCK_INVALID; - if (c < MEM_BLOCK_NR-1) - mem_blocks[c].next = c+2; - else - mem_blocks[c].next = 0; - } - mem_block_free_list = 1; -} - -mem_block_t *codegen_allocator_allocate(mem_block_t *parent, int code_block) -{ - mem_block_t *block; - uint32_t block_nr; - - while (!mem_block_free_list) - { - /*Pick a random memory block and free the owning code block*/ - block_nr = rand() & MEM_BLOCK_MASK; - block = &mem_blocks[block_nr]; - - if (block->code_block && block->code_block != code_block) - codegen_delete_block(&codeblock[block->code_block]); - } - - /*Remove from free list*/ - block_nr = mem_block_free_list; - block = &mem_blocks[block_nr-1]; - mem_block_free_list = block->next; - - block->code_block = code_block; - if (parent) - { - /*Add to parent list*/ - block->next = parent->next; - parent->next = block_nr; - } + for (uint32_t c = 0; c < MEM_BLOCK_NR; c++) { + mem_blocks[c].offset = c * MEM_BLOCK_SIZE; + mem_blocks[c].code_block = BLOCK_INVALID; + if (c < MEM_BLOCK_NR - 1) + mem_blocks[c].next = c + 2; else - block->next = 0; - - codegen_allocator_usage++; - return block; + mem_blocks[c].next = 0; + } + mem_block_free_list = 1; } -void codegen_allocator_free(mem_block_t *block) + +mem_block_t * +codegen_allocator_allocate(mem_block_t *parent, int code_block) { - int block_nr = (((uintptr_t)block - (uintptr_t)mem_blocks) / sizeof(mem_block_t)) + 1; + mem_block_t *block; + uint32_t block_nr; - while (1) - { - int next_block_nr = block->next; - codegen_allocator_usage--; - - block->next = mem_block_free_list; - block->code_block = BLOCK_INVALID; - mem_block_free_list = block_nr; - block_nr = next_block_nr; - - if (block_nr) - block = &mem_blocks[block_nr - 1]; - else - break; - } + while (!mem_block_free_list) { + /*Pick a random memory block and free the owning code block*/ + block_nr = rand() & MEM_BLOCK_MASK; + block = &mem_blocks[block_nr]; + + if (block->code_block && block->code_block != code_block) + codegen_delete_block(&codeblock[block->code_block]); + } + + /*Remove from free list*/ + block_nr = mem_block_free_list; + block = &mem_blocks[block_nr - 1]; + mem_block_free_list = block->next; + + block->code_block = code_block; + if (parent) { + /*Add to parent list*/ + block->next = parent->next; + parent->next = block_nr; + } else + block->next = 0; + + codegen_allocator_usage++; + return block; } - -uint8_t *codeblock_allocator_get_ptr(mem_block_t *block) +void +codegen_allocator_free(mem_block_t *block) { - return &mem_block_alloc[block->offset]; + int block_nr = (((uintptr_t) block - (uintptr_t) mem_blocks) / sizeof(mem_block_t)) + 1; + + while (1) { + int next_block_nr = block->next; + codegen_allocator_usage--; + + block->next = mem_block_free_list; + block->code_block = BLOCK_INVALID; + mem_block_free_list = block_nr; + block_nr = next_block_nr; + + if (block_nr) + block = &mem_blocks[block_nr - 1]; + else + break; + } } -void codegen_allocator_clean_blocks(struct mem_block_t *block) +uint8_t * +codeblock_allocator_get_ptr(mem_block_t *block) +{ + return &mem_block_alloc[block->offset]; +} + +void +codegen_allocator_clean_blocks(UNUSED(struct mem_block_t *block)) { #if defined __ARM_EABI__ || defined _ARM_ || defined __aarch64__ || defined _M_ARM || defined _M_ARM64 - while (1) - { -#ifndef _MSC_VER - __clear_cache(&mem_block_alloc[block->offset], &mem_block_alloc[block->offset + MEM_BLOCK_SIZE]); -#else - FlushInstructionCache(GetCurrentProcess(), &mem_block_alloc[block->offset], MEM_BLOCK_SIZE); -#endif - if (block->next) - block = &mem_blocks[block->next - 1]; - else - break; - } + while (1) { +# ifndef _MSC_VER + __clear_cache(&mem_block_alloc[block->offset], &mem_block_alloc[block->offset + MEM_BLOCK_SIZE]); +# else + FlushInstructionCache(GetCurrentProcess(), &mem_block_alloc[block->offset], MEM_BLOCK_SIZE); +# endif + if (block->next) + block = &mem_blocks[block->next - 1]; + else + break; + } #endif } diff --git a/src/codegen_new/codegen_allocator.h b/src/codegen_new/codegen_allocator.h index 6cd42258b..21d4dbb0c 100644 --- a/src/codegen_new/codegen_allocator.h +++ b/src/codegen_new/codegen_allocator.h @@ -4,25 +4,25 @@ /*The allocator handles all allocation of executable memory. Since the two-pass recompiler design makes applying hard limits to codeblock size difficult, the allocator allows memory to be provided as and when required. - + The allocator provides a block size of a little under 1 kB (slightly lower to limit cache aliasing). Each generated codeblock is allocated one block by default, and will allocate additional block(s) once the existing memory is sorted. Blocks are chained together by jump instructions. - + Due to the chaining, the total memory size is limited by the range of a jump instruction. ARMv7 is restricted to +/- 32 MB, ARMv8 to +/- 128 MB, x86 to +/- 2GB. As a result, total memory size is limited to 32 MB on ARMv7*/ #if defined __ARM_EABI__ || defined _ARM_ || defined _M_ARM -#define MEM_BLOCK_NR 32768 +# define MEM_BLOCK_NR 32768 #else -#define MEM_BLOCK_NR 131072 +# define MEM_BLOCK_NR 131072 #endif -#define MEM_BLOCK_MASK (MEM_BLOCK_NR-1) +#define MEM_BLOCK_MASK (MEM_BLOCK_NR - 1) #define MEM_BLOCK_SIZE 0x3c0 -void codegen_allocator_init(); +void codegen_allocator_init(void); /*Allocate a mem_block_t, and the associated backing memory. If parent is non-NULL, then the new block will be added to the list in parent->next*/ diff --git a/src/codegen_new/codegen_backend.h b/src/codegen_new/codegen_backend.h index 56884c84b..901b5e9d9 100644 --- a/src/codegen_new/codegen_backend.h +++ b/src/codegen_new/codegen_backend.h @@ -2,25 +2,25 @@ #define _CODEGEN_BACKEND_H_ #if defined __amd64__ || defined _M_X64 -#include "codegen_backend_x86-64.h" +# include "codegen_backend_x86-64.h" #elif defined i386 || defined __i386 || defined __i386__ || defined _X86_ || defined _M_IX86 -#include "codegen_backend_x86.h" +# include "codegen_backend_x86.h" #elif defined __ARM_EABI__ || defined _ARM_ || defined _M_ARM -#include "codegen_backend_arm.h" +# include "codegen_backend_arm.h" #elif defined __aarch64__ || defined _M_ARM64 -#include "codegen_backend_arm64.h" +# include "codegen_backend_arm64.h" #else -#error Dynamic recompiler not implemented on your platform +# error Dynamic recompiler not implemented on your platform #endif -void codegen_backend_init(); +void codegen_backend_init(void); void codegen_backend_prologue(codeblock_t *block); void codegen_backend_epilogue(codeblock_t *block); struct ir_data_t; struct uop_t; -struct ir_data_t *codegen_get_ir_data(); +struct ir_data_t *codegen_get_ir_data(void); typedef int (*uOpFn)(codeblock_t *codeblock, struct uop_t *uop); @@ -29,10 +29,9 @@ extern const uOpFn uop_handlers[]; /*Register will not be preserved across function calls*/ #define HOST_REG_FLAG_VOLATILE (1 << 0) -typedef struct host_reg_def_t -{ - int reg; - int flags; +typedef struct host_reg_def_t { + int reg; + int flags; } host_reg_def_t; extern host_reg_def_t codegen_host_reg_list[CODEGEN_HOST_REGS]; diff --git a/src/codegen_new/codegen_backend_arm.c b/src/codegen_new/codegen_backend_arm.c index f423f72d8..b1e904096 100644 --- a/src/codegen_new/codegen_backend_arm.c +++ b/src/codegen_new/codegen_backend_arm.c @@ -1,27 +1,30 @@ #if defined __ARM_EABI__ || defined _ARM_ || defined _M_ARM -#include -#include -#include <86box/86box.h> -#include "cpu.h" -#include <86box/mem.h> +# include +# include +# include <86box/86box.h> +# include "cpu.h" +# include <86box/mem.h> -#include "codegen.h" -#include "codegen_allocator.h" -#include "codegen_backend.h" -#include "codegen_backend_arm_defs.h" -#include "codegen_backend_arm_ops.h" -#include "codegen_reg.h" -#include "x86.h" -#include "x87.h" +# include "codegen.h" +# include "codegen_allocator.h" +# include "codegen_backend.h" +# include "codegen_backend_arm_defs.h" +# include "codegen_backend_arm_ops.h" +# include "codegen_reg.h" +# include "x86.h" +# include "x86seg_common.h" +# include "x86seg.h" +# include "x87.h" -#if defined(__linux__) || defined(__APPLE__) -#include -#include -#endif -#if defined WIN32 || defined _WIN32 || defined _WIN32 -#include -#endif +# if defined(__linux__) || defined(__APPLE__) +# include +# include +# endif +# if defined WIN32 || defined _WIN32 || defined _WIN32 +# include +# endif +# include void *codegen_mem_load_byte; void *codegen_mem_load_word; @@ -42,329 +45,328 @@ void *codegen_fp_round; void *codegen_gpf_rout; void *codegen_exit_rout; -host_reg_def_t codegen_host_reg_list[CODEGEN_HOST_REGS] = -{ - {REG_R4, 0}, - {REG_R5, 0}, - {REG_R6, 0}, - {REG_R7, 0}, - {REG_R8, 0}, - {REG_R9, 0}, - {REG_R11, 0} +host_reg_def_t codegen_host_reg_list[CODEGEN_HOST_REGS] = { + { REG_R4, 0}, + { REG_R5, 0}, + { REG_R6, 0}, + { REG_R7, 0}, + { REG_R8, 0}, + { REG_R9, 0}, + { REG_R11, 0} }; -host_reg_def_t codegen_host_fp_reg_list[CODEGEN_HOST_FP_REGS] = -{ - {REG_D8, 0}, - {REG_D9, 0}, - {REG_D10, 0}, - {REG_D11, 0}, - {REG_D12, 0}, - {REG_D13, 0}, - {REG_D14, 0}, - {REG_D15, 0} +host_reg_def_t codegen_host_fp_reg_list[CODEGEN_HOST_FP_REGS] = { + { REG_D8, 0}, + { REG_D9, 0}, + { REG_D10, 0}, + { REG_D11, 0}, + { REG_D12, 0}, + { REG_D13, 0}, + { REG_D14, 0}, + { REG_D15, 0} }; -static void build_load_routine(codeblock_t *block, int size, int is_float) +static void +build_load_routine(codeblock_t *block, int size, int is_float) { - uint32_t *branch_offset; - uint32_t *misaligned_offset; + uint32_t *branch_offset; + uint32_t *misaligned_offset; - /*In - R0 = address - Out - R0 = data, R1 = abrt*/ - /*MOV R1, R0, LSR #12 - MOV R2, #readlookup2 - LDR R1, [R2, R1, LSL #2] - CMP R1, #-1 - BNE + - LDRB R0, [R1, R0] - MOV R1, #0 - MOV PC, LR - * STR LR, [SP, -4]! - BL readmembl - LDRB R1, cpu_state.abrt - LDR PC, [SP], #4 - */ - codegen_alloc(block, 80); - host_arm_MOV_REG_LSR(block, REG_R1, REG_R0, 12); - host_arm_MOV_IMM(block, REG_R2, (uint32_t)readlookup2); - host_arm_LDR_REG_LSL(block, REG_R1, REG_R2, REG_R1, 2); - if (size != 1) - { - host_arm_TST_IMM(block, REG_R0, size-1); - misaligned_offset = host_arm_BNE_(block); - } - host_arm_CMP_IMM(block, REG_R1, -1); - branch_offset = host_arm_BEQ_(block); - if (size == 1 && !is_float) - host_arm_LDRB_REG(block, REG_R0, REG_R1, REG_R0); - else if (size == 2 && !is_float) - host_arm_LDRH_REG(block, REG_R0, REG_R1, REG_R0); - else if (size == 4 && !is_float) - host_arm_LDR_REG(block, REG_R0, REG_R1, REG_R0); - else if (size == 4 && is_float) - { - host_arm_ADD_REG(block, REG_R0, REG_R0, REG_R1); - host_arm_VLDR_S(block, REG_D_TEMP, REG_R0, 0); - } - else if (size == 8) - { - host_arm_ADD_REG(block, REG_R0, REG_R0, REG_R1); - host_arm_VLDR_D(block, REG_D_TEMP, REG_R0, 0); - } - host_arm_MOV_IMM(block, REG_R1, 0); - host_arm_MOV_REG(block, REG_PC, REG_LR); + /*In - R0 = address + Out - R0 = data, R1 = abrt*/ + /*MOV R1, R0, LSR #12 + MOV R2, #readlookup2 + LDR R1, [R2, R1, LSL #2] + CMP R1, #-1 + BNE + + LDRB R0, [R1, R0] + MOV R1, #0 + MOV PC, LR + * STR LR, [SP, -4]! + BL readmembl + LDRB R1, cpu_state.abrt + LDR PC, [SP], #4 + */ + codegen_alloc(block, 80); + host_arm_MOV_REG_LSR(block, REG_R1, REG_R0, 12); + host_arm_MOV_IMM(block, REG_R2, (uint32_t) readlookup2); + host_arm_LDR_REG_LSL(block, REG_R1, REG_R2, REG_R1, 2); + if (size != 1) { + host_arm_TST_IMM(block, REG_R0, size - 1); + misaligned_offset = host_arm_BNE_(block); + } + host_arm_CMP_IMM(block, REG_R1, -1); + branch_offset = host_arm_BEQ_(block); + if (size == 1 && !is_float) + host_arm_LDRB_REG(block, REG_R0, REG_R1, REG_R0); + else if (size == 2 && !is_float) + host_arm_LDRH_REG(block, REG_R0, REG_R1, REG_R0); + else if (size == 4 && !is_float) + host_arm_LDR_REG(block, REG_R0, REG_R1, REG_R0); + else if (size == 4 && is_float) { + host_arm_ADD_REG(block, REG_R0, REG_R0, REG_R1); + host_arm_VLDR_S(block, REG_D_TEMP, REG_R0, 0); + } else if (size == 8) { + host_arm_ADD_REG(block, REG_R0, REG_R0, REG_R1); + host_arm_VLDR_D(block, REG_D_TEMP, REG_R0, 0); + } + host_arm_MOV_IMM(block, REG_R1, 0); + host_arm_MOV_REG(block, REG_PC, REG_LR); - *branch_offset |= ((((uintptr_t)&block_write_data[block_pos] - (uintptr_t)branch_offset) - 8) & 0x3fffffc) >> 2; - if (size != 1) - *misaligned_offset |= ((((uintptr_t)&block_write_data[block_pos] - (uintptr_t)misaligned_offset) - 8) & 0x3fffffc) >> 2; - host_arm_STR_IMM_WB(block, REG_LR, REG_HOST_SP, -4); - if (size == 1) - host_arm_BL(block, (uintptr_t)readmembl); - else if (size == 2) - host_arm_BL(block, (uintptr_t)readmemwl); - else if (size == 4) - host_arm_BL(block, (uintptr_t)readmemll); - else if (size == 8) - host_arm_BL(block, (uintptr_t)readmemql); - else - fatal("build_load_routine - unknown size %i\n", size); - if (size == 4 && is_float) - host_arm_VMOV_S_32(block, REG_D_TEMP, REG_R0); - else if (size == 8) - host_arm_VMOV_D_64(block, REG_D_TEMP, REG_R0, REG_R1); - host_arm_LDRB_ABS(block, REG_R1, &cpu_state.abrt); - host_arm_LDR_IMM_POST(block, REG_PC, REG_HOST_SP, 4); + *branch_offset |= ((((uintptr_t) &block_write_data[block_pos] - (uintptr_t) branch_offset) - 8) & 0x3fffffc) >> 2; + if (size != 1) + *misaligned_offset |= ((((uintptr_t) &block_write_data[block_pos] - (uintptr_t) misaligned_offset) - 8) & 0x3fffffc) >> 2; + host_arm_STR_IMM_WB(block, REG_LR, REG_HOST_SP, -4); + if (size == 1) + host_arm_BL(block, (uintptr_t) readmembl); + else if (size == 2) + host_arm_BL(block, (uintptr_t) readmemwl); + else if (size == 4) + host_arm_BL(block, (uintptr_t) readmemll); + else if (size == 8) + host_arm_BL(block, (uintptr_t) readmemql); + else + fatal("build_load_routine - unknown size %i\n", size); + if (size == 4 && is_float) + host_arm_VMOV_S_32(block, REG_D_TEMP, REG_R0); + else if (size == 8) + host_arm_VMOV_D_64(block, REG_D_TEMP, REG_R0, REG_R1); + host_arm_LDRB_ABS(block, REG_R1, &cpu_state.abrt); + host_arm_LDR_IMM_POST(block, REG_PC, REG_HOST_SP, 4); } -static void build_store_routine(codeblock_t *block, int size, int is_float) +static void +build_store_routine(codeblock_t *block, int size, int is_float) { - uint32_t *branch_offset; - uint32_t *misaligned_offset; + uint32_t *branch_offset; + uint32_t *misaligned_offset; - /*In - R0 = address - Out - R0 = data, R1 = abrt*/ - /*MOV R1, R0, LSR #12 - MOV R2, #readlookup2 - LDR R1, [R2, R1, LSL #2] - CMP R1, #-1 - BNE + - LDRB R0, [R1, R0] - MOV R1, #0 - MOV PC, LR - * STR LR, [SP, -4]! - BL readmembl - LDRB R1, cpu_state.abrt - LDR PC, [SP], #4 - */ - codegen_alloc(block, 80); - host_arm_MOV_REG_LSR(block, REG_R2, REG_R0, 12); - host_arm_MOV_IMM(block, REG_R3, (uint32_t)writelookup2); - host_arm_LDR_REG_LSL(block, REG_R2, REG_R3, REG_R2, 2); - if (size != 1) - { - host_arm_TST_IMM(block, REG_R0, size-1); - misaligned_offset = host_arm_BNE_(block); - } - host_arm_CMP_IMM(block, REG_R2, -1); - branch_offset = host_arm_BEQ_(block); - if (size == 1 && !is_float) - host_arm_STRB_REG(block, REG_R1, REG_R2, REG_R0); - else if (size == 2 && !is_float) - host_arm_STRH_REG(block, REG_R1, REG_R2, REG_R0); - else if (size == 4 && !is_float) - host_arm_STR_REG(block, REG_R1, REG_R2, REG_R0); - else if (size == 4 && is_float) - { - host_arm_ADD_REG(block, REG_R0, REG_R0, REG_R2); - host_arm_VSTR_S(block, REG_D_TEMP, REG_R0, 0); - } - else if (size == 8) - { - host_arm_ADD_REG(block, REG_R0, REG_R0, REG_R2); - host_arm_VSTR_D(block, REG_D_TEMP, REG_R0, 0); - } - host_arm_MOV_IMM(block, REG_R1, 0); - host_arm_MOV_REG(block, REG_PC, REG_LR); + /*In - R0 = address + Out - R0 = data, R1 = abrt*/ + /*MOV R1, R0, LSR #12 + MOV R2, #readlookup2 + LDR R1, [R2, R1, LSL #2] + CMP R1, #-1 + BNE + + LDRB R0, [R1, R0] + MOV R1, #0 + MOV PC, LR + * STR LR, [SP, -4]! + BL readmembl + LDRB R1, cpu_state.abrt + LDR PC, [SP], #4 + */ + codegen_alloc(block, 80); + host_arm_MOV_REG_LSR(block, REG_R2, REG_R0, 12); + host_arm_MOV_IMM(block, REG_R3, (uint32_t) writelookup2); + host_arm_LDR_REG_LSL(block, REG_R2, REG_R3, REG_R2, 2); + if (size != 1) { + host_arm_TST_IMM(block, REG_R0, size - 1); + misaligned_offset = host_arm_BNE_(block); + } + host_arm_CMP_IMM(block, REG_R2, -1); + branch_offset = host_arm_BEQ_(block); + if (size == 1 && !is_float) + host_arm_STRB_REG(block, REG_R1, REG_R2, REG_R0); + else if (size == 2 && !is_float) + host_arm_STRH_REG(block, REG_R1, REG_R2, REG_R0); + else if (size == 4 && !is_float) + host_arm_STR_REG(block, REG_R1, REG_R2, REG_R0); + else if (size == 4 && is_float) { + host_arm_ADD_REG(block, REG_R0, REG_R0, REG_R2); + host_arm_VSTR_S(block, REG_D_TEMP, REG_R0, 0); + } else if (size == 8) { + host_arm_ADD_REG(block, REG_R0, REG_R0, REG_R2); + host_arm_VSTR_D(block, REG_D_TEMP, REG_R0, 0); + } + host_arm_MOV_IMM(block, REG_R1, 0); + host_arm_MOV_REG(block, REG_PC, REG_LR); - *branch_offset |= ((((uintptr_t)&block_write_data[block_pos] - (uintptr_t)branch_offset) - 8) & 0x3fffffc) >> 2; - if (size != 1) - *misaligned_offset |= ((((uintptr_t)&block_write_data[block_pos] - (uintptr_t)misaligned_offset) - 8) & 0x3fffffc) >> 2; - host_arm_STR_IMM_WB(block, REG_LR, REG_HOST_SP, -4); - if (size == 4 && is_float) - host_arm_VMOV_32_S(block, REG_R1, REG_D_TEMP); - else if (size == 8) - host_arm_VMOV_64_D(block, REG_R2, REG_R3, REG_D_TEMP); - if (size == 1) - host_arm_BL(block, (uintptr_t)writemembl); - else if (size == 2) - host_arm_BL(block, (uintptr_t)writememwl); - else if (size == 4) - host_arm_BL(block, (uintptr_t)writememll); - else if (size == 8) - host_arm_BL_r1(block, (uintptr_t)writememql); - else - fatal("build_store_routine - unknown size %i\n", size); - host_arm_LDRB_ABS(block, REG_R1, &cpu_state.abrt); - host_arm_LDR_IMM_POST(block, REG_PC, REG_HOST_SP, 4); + *branch_offset |= ((((uintptr_t) &block_write_data[block_pos] - (uintptr_t) branch_offset) - 8) & 0x3fffffc) >> 2; + if (size != 1) + *misaligned_offset |= ((((uintptr_t) &block_write_data[block_pos] - (uintptr_t) misaligned_offset) - 8) & 0x3fffffc) >> 2; + host_arm_STR_IMM_WB(block, REG_LR, REG_HOST_SP, -4); + if (size == 4 && is_float) + host_arm_VMOV_32_S(block, REG_R1, REG_D_TEMP); + else if (size == 8) + host_arm_VMOV_64_D(block, REG_R2, REG_R3, REG_D_TEMP); + if (size == 1) + host_arm_BL(block, (uintptr_t) writemembl); + else if (size == 2) + host_arm_BL(block, (uintptr_t) writememwl); + else if (size == 4) + host_arm_BL(block, (uintptr_t) writememll); + else if (size == 8) + host_arm_BL_r1(block, (uintptr_t) writememql); + else + fatal("build_store_routine - unknown size %i\n", size); + host_arm_LDRB_ABS(block, REG_R1, &cpu_state.abrt); + host_arm_LDR_IMM_POST(block, REG_PC, REG_HOST_SP, 4); } -static void build_loadstore_routines(codeblock_t *block) +static void +build_loadstore_routines(codeblock_t *block) { - codegen_mem_load_byte = &block_write_data[block_pos]; - build_load_routine(block, 1, 0); - codegen_mem_load_word = &block_write_data[block_pos]; - build_load_routine(block, 2, 0); - codegen_mem_load_long = &block_write_data[block_pos]; - build_load_routine(block, 4, 0); - codegen_mem_load_quad = &block_write_data[block_pos]; - build_load_routine(block, 8, 0); - codegen_mem_load_single = &block_write_data[block_pos]; - build_load_routine(block, 4, 1); - codegen_mem_load_double = &block_write_data[block_pos]; - build_load_routine(block, 8, 1); + codegen_mem_load_byte = &block_write_data[block_pos]; + build_load_routine(block, 1, 0); + codegen_mem_load_word = &block_write_data[block_pos]; + build_load_routine(block, 2, 0); + codegen_mem_load_long = &block_write_data[block_pos]; + build_load_routine(block, 4, 0); + codegen_mem_load_quad = &block_write_data[block_pos]; + build_load_routine(block, 8, 0); + codegen_mem_load_single = &block_write_data[block_pos]; + build_load_routine(block, 4, 1); + codegen_mem_load_double = &block_write_data[block_pos]; + build_load_routine(block, 8, 1); - codegen_mem_store_byte = &block_write_data[block_pos]; - build_store_routine(block, 1, 0); - codegen_mem_store_word = &block_write_data[block_pos]; - build_store_routine(block, 2, 0); - codegen_mem_store_long = &block_write_data[block_pos]; - build_store_routine(block, 4, 0); - codegen_mem_store_quad = &block_write_data[block_pos]; - build_store_routine(block, 8, 0); - codegen_mem_store_single = &block_write_data[block_pos]; - build_store_routine(block, 4, 1); - codegen_mem_store_double = &block_write_data[block_pos]; - build_store_routine(block, 8, 1); + codegen_mem_store_byte = &block_write_data[block_pos]; + build_store_routine(block, 1, 0); + codegen_mem_store_word = &block_write_data[block_pos]; + build_store_routine(block, 2, 0); + codegen_mem_store_long = &block_write_data[block_pos]; + build_store_routine(block, 4, 0); + codegen_mem_store_quad = &block_write_data[block_pos]; + build_store_routine(block, 8, 0); + codegen_mem_store_single = &block_write_data[block_pos]; + build_store_routine(block, 4, 1); + codegen_mem_store_double = &block_write_data[block_pos]; + build_store_routine(block, 8, 1); } /*VFP has a specific round-to-zero instruction, and the default rounding mode is nearest. For round up/down, temporarily change the rounding mode in FPCSR*/ -#define FPCSR_ROUNDING_MASK (3 << 22) -#define FPCSR_ROUNDING_UP (1 << 22) -#define FPCSR_ROUNDING_DOWN (2 << 22) +# define FPCSR_ROUNDING_MASK (3 << 22) +# define FPCSR_ROUNDING_UP (1 << 22) +# define FPCSR_ROUNDING_DOWN (2 << 22) -static void build_fp_round_routine(codeblock_t *block) +static void +build_fp_round_routine(codeblock_t *block) { - uint32_t *jump_table; + uint32_t *jump_table; - codegen_alloc(block, 80); + codegen_alloc(block, 80); - host_arm_MOV_REG(block, REG_TEMP2, REG_LR); - host_arm_MOV_REG(block, REG_LR, REG_TEMP2); - host_arm_LDR_IMM(block, REG_TEMP, REG_CPUSTATE, (uintptr_t)&cpu_state.new_fp_control - (uintptr_t)&cpu_state); - host_arm_LDR_REG(block, REG_PC, REG_PC, REG_TEMP); - host_arm_NOP(block); + host_arm_MOV_REG(block, REG_TEMP2, REG_LR); + host_arm_MOV_REG(block, REG_LR, REG_TEMP2); + host_arm_LDR_IMM(block, REG_TEMP, REG_CPUSTATE, (uintptr_t) &cpu_state.new_fp_control - (uintptr_t) &cpu_state); + host_arm_LDR_REG(block, REG_PC, REG_PC, REG_TEMP); + host_arm_NOP(block); - jump_table = (uint32_t *)&block_write_data[block_pos]; - host_arm_NOP(block); - host_arm_NOP(block); - host_arm_NOP(block); - host_arm_NOP(block); + jump_table = (uint32_t *) &block_write_data[block_pos]; + host_arm_NOP(block); + host_arm_NOP(block); + host_arm_NOP(block); + host_arm_NOP(block); - jump_table[X87_ROUNDING_NEAREST] = (uint64_t)(uintptr_t)&block_write_data[block_pos]; //tie even - host_arm_VCVTR_IS_D(block, REG_D_TEMP, REG_D_TEMP); - host_arm_MOV_REG(block, REG_PC, REG_LR); + jump_table[X87_ROUNDING_NEAREST] = (uint64_t) (uintptr_t) &block_write_data[block_pos]; // tie even + host_arm_VCVTR_IS_D(block, REG_D_TEMP, REG_D_TEMP); + host_arm_MOV_REG(block, REG_PC, REG_LR); - jump_table[X87_ROUNDING_UP] = (uint64_t)(uintptr_t)&block_write_data[block_pos]; //pos inf - host_arm_LDR_IMM(block, REG_TEMP, REG_CPUSTATE, (uintptr_t)&cpu_state.old_fp_control - (uintptr_t)&cpu_state); - host_arm_BIC_IMM(block, REG_TEMP2, REG_TEMP, FPCSR_ROUNDING_MASK); - host_arm_ORR_IMM(block, REG_TEMP2, REG_TEMP2, FPCSR_ROUNDING_UP); - host_arm_VMSR_FPSCR(block, REG_TEMP2); - host_arm_VCVTR_IS_D(block, REG_D_TEMP, REG_D_TEMP); - host_arm_VMSR_FPSCR(block, REG_TEMP); - host_arm_MOV_REG(block, REG_PC, REG_LR); + jump_table[X87_ROUNDING_UP] = (uint64_t) (uintptr_t) &block_write_data[block_pos]; // pos inf + host_arm_LDR_IMM(block, REG_TEMP, REG_CPUSTATE, (uintptr_t) &cpu_state.old_fp_control - (uintptr_t) &cpu_state); + host_arm_BIC_IMM(block, REG_TEMP2, REG_TEMP, FPCSR_ROUNDING_MASK); + host_arm_ORR_IMM(block, REG_TEMP2, REG_TEMP2, FPCSR_ROUNDING_UP); + host_arm_VMSR_FPSCR(block, REG_TEMP2); + host_arm_VCVTR_IS_D(block, REG_D_TEMP, REG_D_TEMP); + host_arm_VMSR_FPSCR(block, REG_TEMP); + host_arm_MOV_REG(block, REG_PC, REG_LR); - jump_table[X87_ROUNDING_DOWN] = (uint64_t)(uintptr_t)&block_write_data[block_pos]; //neg inf - host_arm_LDR_IMM(block, REG_TEMP, REG_CPUSTATE, (uintptr_t)&cpu_state.old_fp_control - (uintptr_t)&cpu_state); - host_arm_BIC_IMM(block, REG_TEMP2, REG_TEMP, FPCSR_ROUNDING_MASK); - host_arm_ORR_IMM(block, REG_TEMP2, REG_TEMP, FPCSR_ROUNDING_DOWN); - host_arm_VMSR_FPSCR(block, REG_TEMP2); - host_arm_VCVTR_IS_D(block, REG_D_TEMP, REG_D_TEMP); - host_arm_VMSR_FPSCR(block, REG_TEMP); - host_arm_MOV_REG(block, REG_PC, REG_LR); - - jump_table[X87_ROUNDING_CHOP] = (uint64_t)(uintptr_t)&block_write_data[block_pos]; //zero - host_arm_VCVT_IS_D(block, REG_D_TEMP, REG_D_TEMP); - host_arm_MOV_REG(block, REG_PC, REG_LR); + jump_table[X87_ROUNDING_DOWN] = (uint64_t) (uintptr_t) &block_write_data[block_pos]; // neg inf + host_arm_LDR_IMM(block, REG_TEMP, REG_CPUSTATE, (uintptr_t) &cpu_state.old_fp_control - (uintptr_t) &cpu_state); + host_arm_BIC_IMM(block, REG_TEMP2, REG_TEMP, FPCSR_ROUNDING_MASK); + host_arm_ORR_IMM(block, REG_TEMP2, REG_TEMP, FPCSR_ROUNDING_DOWN); + host_arm_VMSR_FPSCR(block, REG_TEMP2); + host_arm_VCVTR_IS_D(block, REG_D_TEMP, REG_D_TEMP); + host_arm_VMSR_FPSCR(block, REG_TEMP); + host_arm_MOV_REG(block, REG_PC, REG_LR); + + jump_table[X87_ROUNDING_CHOP] = (uint64_t) (uintptr_t) &block_write_data[block_pos]; // zero + host_arm_VCVT_IS_D(block, REG_D_TEMP, REG_D_TEMP); + host_arm_MOV_REG(block, REG_PC, REG_LR); } -void codegen_backend_init() +void +codegen_backend_init(void) { - codeblock_t *block; - int c; + codeblock_t *block; - codeblock = malloc(BLOCK_SIZE * sizeof(codeblock_t)); - codeblock_hash = malloc(HASH_SIZE * sizeof(codeblock_t *)); + codeblock = malloc(BLOCK_SIZE * sizeof(codeblock_t)); + codeblock_hash = malloc(HASH_SIZE * sizeof(codeblock_t *)); - memset(codeblock, 0, BLOCK_SIZE * sizeof(codeblock_t)); - memset(codeblock_hash, 0, HASH_SIZE * sizeof(codeblock_t *)); + memset(codeblock, 0, BLOCK_SIZE * sizeof(codeblock_t)); + memset(codeblock_hash, 0, HASH_SIZE * sizeof(codeblock_t *)); - for (c = 0; c < BLOCK_SIZE; c++) - codeblock[c].pc = BLOCK_PC_INVALID; + for (int c = 0; c < BLOCK_SIZE; c++) + codeblock[c].pc = BLOCK_PC_INVALID; - block_current = 0; - block_pos = 0; - block = &codeblock[block_current]; - block->head_mem_block = codegen_allocator_allocate(NULL, block_current); - block->data = codeblock_allocator_get_ptr(block->head_mem_block); - block_write_data = block->data; - build_loadstore_routines(&codeblock[block_current]); -printf("block_pos=%i\n", block_pos); + block_current = 0; + block_pos = 0; + block = &codeblock[block_current]; + block->head_mem_block = codegen_allocator_allocate(NULL, block_current); + block->data = codeblock_allocator_get_ptr(block->head_mem_block); + block_write_data = block->data; + build_loadstore_routines(&codeblock[block_current]); +# if 0 + pclog("block_pos=%i\n", block_pos); +# endif - codegen_fp_round = &block_write_data[block_pos]; - build_fp_round_routine(&codeblock[block_current]); + codegen_fp_round = &block_write_data[block_pos]; + build_fp_round_routine(&codeblock[block_current]); - codegen_alloc(block, 80); - codegen_gpf_rout = &block_write_data[block_pos]; - host_arm_MOV_IMM(block, REG_R0, 0); - host_arm_MOV_IMM(block, REG_R1, 0); - host_arm_call(block, x86gpf); + codegen_alloc(block, 80); + codegen_gpf_rout = &block_write_data[block_pos]; + host_arm_MOV_IMM(block, REG_R0, 0); + host_arm_MOV_IMM(block, REG_R1, 0); + host_arm_call(block, x86gpf); - codegen_exit_rout = &block_write_data[block_pos]; - host_arm_ADD_IMM(block, REG_HOST_SP, REG_HOST_SP, 0x40); - host_arm_LDMIA_WB(block, REG_HOST_SP, REG_MASK_LOCAL | REG_MASK_PC); + codegen_exit_rout = &block_write_data[block_pos]; + host_arm_ADD_IMM(block, REG_HOST_SP, REG_HOST_SP, 0x40); + host_arm_LDMIA_WB(block, REG_HOST_SP, REG_MASK_LOCAL | REG_MASK_PC); - block_write_data = NULL; -//fatal("block_pos=%i\n", block_pos); - asm("vmrs %0, fpscr\n" - : "=r" (cpu_state.old_fp_control) - ); - if ((cpu_state.old_fp_control >> 22) & 3) - fatal("VFP not in nearest rounding mode\n"); + block_write_data = NULL; +# if 0 + fatal("block_pos=%i\n", block_pos); +# endif + asm("vmrs %0, fpscr\n" + : "=r"(cpu_state.old_fp_control)); + if ((cpu_state.old_fp_control >> 22) & 3) + fatal("VFP not in nearest rounding mode\n"); } -void codegen_set_rounding_mode(int mode) +void +codegen_set_rounding_mode(int mode) { - if (mode < 0 || mode > 3) - fatal("codegen_set_rounding_mode - invalid mode\n"); - cpu_state.new_fp_control = mode << 2; + if (mode < 0 || mode > 3) + fatal("codegen_set_rounding_mode - invalid mode\n"); + cpu_state.new_fp_control = mode << 2; } /*R10 - cpu_state*/ -void codegen_backend_prologue(codeblock_t *block) +void +codegen_backend_prologue(codeblock_t *block) { - block_pos = BLOCK_START; + block_pos = BLOCK_START; - /*Entry code*/ + /*Entry code*/ - host_arm_STMDB_WB(block, REG_HOST_SP, REG_MASK_LOCAL | REG_MASK_LR); - host_arm_SUB_IMM(block, REG_HOST_SP, REG_HOST_SP, 0x40); - host_arm_MOV_IMM(block, REG_CPUSTATE, (uint32_t)&cpu_state); - if (block->flags & CODEBLOCK_HAS_FPU) - { - host_arm_LDR_IMM(block, REG_TEMP, REG_CPUSTATE, (uintptr_t)&cpu_state.TOP - (uintptr_t)&cpu_state); - host_arm_SUB_IMM(block, REG_TEMP, REG_TEMP, block->TOP); - host_arm_STR_IMM(block, REG_TEMP, REG_HOST_SP, IREG_TOP_diff_stack_offset); - } + host_arm_STMDB_WB(block, REG_HOST_SP, REG_MASK_LOCAL | REG_MASK_LR); + host_arm_SUB_IMM(block, REG_HOST_SP, REG_HOST_SP, 0x40); + host_arm_MOV_IMM(block, REG_CPUSTATE, (uint32_t) &cpu_state); + if (block->flags & CODEBLOCK_HAS_FPU) { + host_arm_LDR_IMM(block, REG_TEMP, REG_CPUSTATE, (uintptr_t) &cpu_state.TOP - (uintptr_t) &cpu_state); + host_arm_SUB_IMM(block, REG_TEMP, REG_TEMP, block->TOP); + host_arm_STR_IMM(block, REG_TEMP, REG_HOST_SP, IREG_TOP_diff_stack_offset); + } } -void codegen_backend_epilogue(codeblock_t *block) +void +codegen_backend_epilogue(codeblock_t *block) { - host_arm_ADD_IMM(block, REG_HOST_SP, REG_HOST_SP, 0x40); - host_arm_LDMIA_WB(block, REG_HOST_SP, REG_MASK_LOCAL | REG_MASK_PC); + host_arm_ADD_IMM(block, REG_HOST_SP, REG_HOST_SP, 0x40); + host_arm_LDMIA_WB(block, REG_HOST_SP, REG_MASK_LOCAL | REG_MASK_PC); - codegen_allocator_clean_blocks(block->head_mem_block); + codegen_allocator_clean_blocks(block->head_mem_block); } #endif diff --git a/src/codegen_new/codegen_backend_arm.h b/src/codegen_new/codegen_backend_arm.h index 87dc2d8a0..a3e236d4e 100644 --- a/src/codegen_new/codegen_backend_arm.h +++ b/src/codegen_new/codegen_backend_arm.h @@ -1,15 +1,15 @@ #include "codegen_backend_arm_defs.h" -#define BLOCK_SIZE 0x4000 -#define BLOCK_MASK 0x3fff +#define BLOCK_SIZE 0x4000 +#define BLOCK_MASK 0x3fff #define BLOCK_START 0 -#define HASH_SIZE 0x20000 -#define HASH_MASK 0x1ffff +#define HASH_SIZE 0x20000 +#define HASH_MASK 0x1ffff -#define HASH(l) ((l) & 0x1ffff) +#define HASH(l) ((l) &0x1ffff) -#define BLOCK_MAX 0x3c0 +#define BLOCK_MAX 0x3c0 void host_arm_ADD_IMM(codeblock_t *block, int dst_reg, int src_reg, uint32_t imm); void host_arm_LDMIA_WB(codeblock_t *block, int addr_reg, uint32_t reg_mask); @@ -21,4 +21,4 @@ void host_arm_SUB_IMM(codeblock_t *block, int dst_reg, int src_reg, uint32_t imm void host_arm_call(codeblock_t *block, void *dst_addr); void host_arm_nop(codeblock_t *block); -void codegen_alloc(codeblock_t *block, int size); \ No newline at end of file +void codegen_alloc(codeblock_t *block, int size); diff --git a/src/codegen_new/codegen_backend_arm64.c b/src/codegen_new/codegen_backend_arm64.c index 2ccdab3a2..1eb94a909 100644 --- a/src/codegen_new/codegen_backend_arm64.c +++ b/src/codegen_new/codegen_backend_arm64.c @@ -1,28 +1,30 @@ #if defined __aarch64__ || defined _M_ARM64 -#include -#include -#include <86box/86box.h> -#include "cpu.h" -#include <86box/mem.h> +# include +# include +# include <86box/86box.h> +# include "cpu.h" +# include <86box/mem.h> -#include "codegen.h" -#include "codegen_allocator.h" -#include "codegen_backend.h" -#include "codegen_backend_arm64_defs.h" -#include "codegen_backend_arm64_ops.h" -#include "codegen_reg.h" -#include "x86.h" -#include "x87.h" +# include "codegen.h" +# include "codegen_allocator.h" +# include "codegen_backend.h" +# include "codegen_backend_arm64_defs.h" +# include "codegen_backend_arm64_ops.h" +# include "codegen_reg.h" +# include "x86.h" +# include "x86seg_common.h" +# include "x86seg.h" +# include "x87.h" -#if defined(__linux__) || defined(__APPLE__) -#include -#include -#endif -#if defined WIN32 || defined _WIN32 || defined _WIN32 -#include -#endif -#include +# if defined(__linux__) || defined(__APPLE__) +# include +# include +# endif +# if defined WIN32 || defined _WIN32 || defined _WIN32 +# include +# endif +# include void *codegen_mem_load_byte; void *codegen_mem_load_word; @@ -44,342 +46,334 @@ void *codegen_fp_round_quad; void *codegen_gpf_rout; void *codegen_exit_rout; -host_reg_def_t codegen_host_reg_list[CODEGEN_HOST_REGS] = -{ - {REG_X19, 0}, - {REG_X20, 0}, - {REG_X21, 0}, - {REG_X22, 0}, - {REG_X23, 0}, - {REG_X24, 0}, - {REG_X25, 0}, - {REG_X26, 0}, - {REG_X27, 0}, - {REG_X28, 0} +host_reg_def_t codegen_host_reg_list[CODEGEN_HOST_REGS] = { + { REG_X19, 0}, + { REG_X20, 0}, + { REG_X21, 0}, + { REG_X22, 0}, + { REG_X23, 0}, + { REG_X24, 0}, + { REG_X25, 0}, + { REG_X26, 0}, + { REG_X27, 0}, + { REG_X28, 0} }; -host_reg_def_t codegen_host_fp_reg_list[CODEGEN_HOST_FP_REGS] = -{ - {REG_V8, 0}, - {REG_V9, 0}, - {REG_V10, 0}, - {REG_V11, 0}, - {REG_V12, 0}, - {REG_V13, 0}, - {REG_V14, 0}, - {REG_V15, 0} +host_reg_def_t codegen_host_fp_reg_list[CODEGEN_HOST_FP_REGS] = { + { REG_V8, 0}, + { REG_V9, 0}, + { REG_V10, 0}, + { REG_V11, 0}, + { REG_V12, 0}, + { REG_V13, 0}, + { REG_V14, 0}, + { REG_V15, 0} }; -static void build_load_routine(codeblock_t *block, int size, int is_float) +static void +build_load_routine(codeblock_t *block, int size, int is_float) { - uint32_t *branch_offset; - uint32_t *misaligned_offset; - int offset; + uint32_t *branch_offset; + uint32_t *misaligned_offset; - /*In - W0 = address - Out - W0 = data, W1 = abrt*/ - /*MOV W1, W0, LSR #12 - MOV X2, #readlookup2 - LDR X1, [X2, X1, LSL #3] - CMP X1, #-1 - BEQ + - LDRB W0, [X1, X0] - MOV W1, #0 - RET - * STP X29, X30, [SP, #-16] - BL readmembl - LDRB R1, cpu_state.abrt - LDP X29, X30, [SP, #-16] - RET - */ - codegen_alloc(block, 80); - host_arm64_MOV_REG_LSR(block, REG_W1, REG_W0, 12); - host_arm64_MOVX_IMM(block, REG_X2, (uint64_t)readlookup2); - host_arm64_LDRX_REG_LSL3(block, REG_X1, REG_X2, REG_X1); - if (size != 1) - { - host_arm64_TST_IMM(block, REG_W0, size-1); - misaligned_offset = host_arm64_BNE_(block); - } - host_arm64_CMPX_IMM(block, REG_X1, -1); - branch_offset = host_arm64_BEQ_(block); - if (size == 1 && !is_float) - host_arm64_LDRB_REG(block, REG_W0, REG_W1, REG_W0); - else if (size == 2 && !is_float) - host_arm64_LDRH_REG(block, REG_W0, REG_W1, REG_W0); - else if (size == 4 && !is_float) - host_arm64_LDR_REG(block, REG_W0, REG_W1, REG_W0); - else if (size == 4 && is_float) - host_arm64_LDR_REG_F32(block, REG_V_TEMP, REG_W1, REG_W0); - else if (size == 8) - host_arm64_LDR_REG_F64(block, REG_V_TEMP, REG_W1, REG_W0); - host_arm64_MOVZ_IMM(block, REG_W1, 0); - host_arm64_RET(block, REG_X30); + /*In - W0 = address + Out - W0 = data, W1 = abrt*/ + /*MOV W1, W0, LSR #12 + MOV X2, #readlookup2 + LDR X1, [X2, X1, LSL #3] + CMP X1, #-1 + BEQ + + LDRB W0, [X1, X0] + MOV W1, #0 + RET + * STP X29, X30, [SP, #-16] + BL readmembl + LDRB R1, cpu_state.abrt + LDP X29, X30, [SP, #-16] + RET + */ + codegen_alloc(block, 80); + host_arm64_MOV_REG_LSR(block, REG_W1, REG_W0, 12); + host_arm64_MOVX_IMM(block, REG_X2, (uint64_t) readlookup2); + host_arm64_LDRX_REG_LSL3(block, REG_X1, REG_X2, REG_X1); + if (size != 1) { + host_arm64_TST_IMM(block, REG_W0, size - 1); + misaligned_offset = host_arm64_BNE_(block); + } + host_arm64_CMPX_IMM(block, REG_X1, -1); + branch_offset = host_arm64_BEQ_(block); + if (size == 1 && !is_float) + host_arm64_LDRB_REG(block, REG_W0, REG_W1, REG_W0); + else if (size == 2 && !is_float) + host_arm64_LDRH_REG(block, REG_W0, REG_W1, REG_W0); + else if (size == 4 && !is_float) + host_arm64_LDR_REG(block, REG_W0, REG_W1, REG_W0); + else if (size == 4 && is_float) + host_arm64_LDR_REG_F32(block, REG_V_TEMP, REG_W1, REG_W0); + else if (size == 8) + host_arm64_LDR_REG_F64(block, REG_V_TEMP, REG_W1, REG_W0); + host_arm64_MOVZ_IMM(block, REG_W1, 0); + host_arm64_RET(block, REG_X30); - host_arm64_branch_set_offset(branch_offset, &block_write_data[block_pos]); - if (size != 1) - host_arm64_branch_set_offset(misaligned_offset, &block_write_data[block_pos]); - host_arm64_STP_PREIDX_X(block, REG_X29, REG_X30, REG_XSP, -16); - if (size == 1) - host_arm64_call(block, (void *)readmembl); - else if (size == 2) - host_arm64_call(block, (void *)readmemwl); - else if (size == 4) - host_arm64_call(block, (void *)readmemll); - else if (size == 8) - host_arm64_call(block, (void *)readmemql); - else - fatal("build_load_routine - unknown size %i\n", size); - codegen_direct_read_8(block, REG_W1, &cpu_state.abrt); - if (size == 4 && is_float) - host_arm64_FMOV_S_W(block, REG_V_TEMP, REG_W0); - else if (size == 8) - host_arm64_FMOV_D_Q(block, REG_V_TEMP, REG_X0); - host_arm64_LDP_POSTIDX_X(block, REG_X29, REG_X30, REG_XSP, 16); - host_arm64_RET(block, REG_X30); + host_arm64_branch_set_offset(branch_offset, &block_write_data[block_pos]); + if (size != 1) + host_arm64_branch_set_offset(misaligned_offset, &block_write_data[block_pos]); + host_arm64_STP_PREIDX_X(block, REG_X29, REG_X30, REG_XSP, -16); + if (size == 1) + host_arm64_call(block, (void *) readmembl); + else if (size == 2) + host_arm64_call(block, (void *) readmemwl); + else if (size == 4) + host_arm64_call(block, (void *) readmemll); + else if (size == 8) + host_arm64_call(block, (void *) readmemql); + else + fatal("build_load_routine - unknown size %i\n", size); + codegen_direct_read_8(block, REG_W1, &cpu_state.abrt); + if (size == 4 && is_float) + host_arm64_FMOV_S_W(block, REG_V_TEMP, REG_W0); + else if (size == 8) + host_arm64_FMOV_D_Q(block, REG_V_TEMP, REG_X0); + host_arm64_LDP_POSTIDX_X(block, REG_X29, REG_X30, REG_XSP, 16); + host_arm64_RET(block, REG_X30); } -static void build_store_routine(codeblock_t *block, int size, int is_float) +static void +build_store_routine(codeblock_t *block, int size, int is_float) { - uint32_t *branch_offset; - uint32_t *misaligned_offset; - int offset; + uint32_t *branch_offset; + uint32_t *misaligned_offset; - /*In - R0 = address, R1 = data - Out - R1 = abrt*/ - /*MOV W2, W0, LSR #12 - MOV X3, #writelookup2 - LDR X2, [X3, X2, LSL #3] - CMP X2, #-1 - BEQ + - STRB W1, [X2, X0] - MOV W1, #0 - RET - * STP X29, X30, [SP, #-16] - BL writemembl - LDRB R1, cpu_state.abrt - LDP X29, X30, [SP, #-16] - RET - */ - codegen_alloc(block, 80); - host_arm64_MOV_REG_LSR(block, REG_W2, REG_W0, 12); - host_arm64_MOVX_IMM(block, REG_X3, (uint64_t)writelookup2); - host_arm64_LDRX_REG_LSL3(block, REG_X2, REG_X3, REG_X2); - if (size != 1) - { - host_arm64_TST_IMM(block, REG_W0, size-1); - misaligned_offset = host_arm64_BNE_(block); - } - host_arm64_CMPX_IMM(block, REG_X2, -1); - branch_offset = host_arm64_BEQ_(block); - if (size == 1 && !is_float) - host_arm64_STRB_REG(block, REG_X1, REG_X2, REG_X0); - else if (size == 2 && !is_float) - host_arm64_STRH_REG(block, REG_X1, REG_X2, REG_X0); - else if (size == 4 && !is_float) - host_arm64_STR_REG(block, REG_X1, REG_X2, REG_X0); - else if (size == 4 && is_float) - host_arm64_STR_REG_F32(block, REG_V_TEMP, REG_X2, REG_X0); - else if (size == 8) - host_arm64_STR_REG_F64(block, REG_V_TEMP, REG_X2, REG_X0); - host_arm64_MOVZ_IMM(block, REG_X1, 0); - host_arm64_RET(block, REG_X30); + /*In - R0 = address, R1 = data + Out - R1 = abrt*/ + /*MOV W2, W0, LSR #12 + MOV X3, #writelookup2 + LDR X2, [X3, X2, LSL #3] + CMP X2, #-1 + BEQ + + STRB W1, [X2, X0] + MOV W1, #0 + RET + * STP X29, X30, [SP, #-16] + BL writemembl + LDRB R1, cpu_state.abrt + LDP X29, X30, [SP, #-16] + RET + */ + codegen_alloc(block, 80); + host_arm64_MOV_REG_LSR(block, REG_W2, REG_W0, 12); + host_arm64_MOVX_IMM(block, REG_X3, (uint64_t) writelookup2); + host_arm64_LDRX_REG_LSL3(block, REG_X2, REG_X3, REG_X2); + if (size != 1) { + host_arm64_TST_IMM(block, REG_W0, size - 1); + misaligned_offset = host_arm64_BNE_(block); + } + host_arm64_CMPX_IMM(block, REG_X2, -1); + branch_offset = host_arm64_BEQ_(block); + if (size == 1 && !is_float) + host_arm64_STRB_REG(block, REG_X1, REG_X2, REG_X0); + else if (size == 2 && !is_float) + host_arm64_STRH_REG(block, REG_X1, REG_X2, REG_X0); + else if (size == 4 && !is_float) + host_arm64_STR_REG(block, REG_X1, REG_X2, REG_X0); + else if (size == 4 && is_float) + host_arm64_STR_REG_F32(block, REG_V_TEMP, REG_X2, REG_X0); + else if (size == 8) + host_arm64_STR_REG_F64(block, REG_V_TEMP, REG_X2, REG_X0); + host_arm64_MOVZ_IMM(block, REG_X1, 0); + host_arm64_RET(block, REG_X30); - host_arm64_branch_set_offset(branch_offset, &block_write_data[block_pos]); - if (size != 1) - host_arm64_branch_set_offset(misaligned_offset, &block_write_data[block_pos]); - host_arm64_STP_PREIDX_X(block, REG_X29, REG_X30, REG_XSP, -16); - if (size == 4 && is_float) - host_arm64_FMOV_W_S(block, REG_W1, REG_V_TEMP); - else if (size == 8) - host_arm64_FMOV_Q_D(block, REG_X1, REG_V_TEMP); - if (size == 1) - host_arm64_call(block, (void *)writemembl); - else if (size == 2) - host_arm64_call(block, (void *)writememwl); - else if (size == 4) - host_arm64_call(block, (void *)writememll); - else if (size == 8) - host_arm64_call(block, (void *)writememql); - else - fatal("build_store_routine - unknown size %i\n", size); - codegen_direct_read_8(block, REG_W1, &cpu_state.abrt); - host_arm64_LDP_POSTIDX_X(block, REG_X29, REG_X30, REG_XSP, 16); - host_arm64_RET(block, REG_X30); + host_arm64_branch_set_offset(branch_offset, &block_write_data[block_pos]); + if (size != 1) + host_arm64_branch_set_offset(misaligned_offset, &block_write_data[block_pos]); + host_arm64_STP_PREIDX_X(block, REG_X29, REG_X30, REG_XSP, -16); + if (size == 4 && is_float) + host_arm64_FMOV_W_S(block, REG_W1, REG_V_TEMP); + else if (size == 8) + host_arm64_FMOV_Q_D(block, REG_X1, REG_V_TEMP); + if (size == 1) + host_arm64_call(block, (void *) writemembl); + else if (size == 2) + host_arm64_call(block, (void *) writememwl); + else if (size == 4) + host_arm64_call(block, (void *) writememll); + else if (size == 8) + host_arm64_call(block, (void *) writememql); + else + fatal("build_store_routine - unknown size %i\n", size); + codegen_direct_read_8(block, REG_W1, &cpu_state.abrt); + host_arm64_LDP_POSTIDX_X(block, REG_X29, REG_X30, REG_XSP, 16); + host_arm64_RET(block, REG_X30); } -static void build_loadstore_routines(codeblock_t *block) +static void +build_loadstore_routines(codeblock_t *block) { - codegen_mem_load_byte = &block_write_data[block_pos]; - build_load_routine(block, 1, 0); - codegen_mem_load_word = &block_write_data[block_pos]; - build_load_routine(block, 2, 0); - codegen_mem_load_long = &block_write_data[block_pos]; - build_load_routine(block, 4, 0); - codegen_mem_load_quad = &block_write_data[block_pos]; - build_load_routine(block, 8, 0); - codegen_mem_load_single = &block_write_data[block_pos]; - build_load_routine(block, 4, 1); - codegen_mem_load_double = &block_write_data[block_pos]; - build_load_routine(block, 8, 1); + codegen_mem_load_byte = &block_write_data[block_pos]; + build_load_routine(block, 1, 0); + codegen_mem_load_word = &block_write_data[block_pos]; + build_load_routine(block, 2, 0); + codegen_mem_load_long = &block_write_data[block_pos]; + build_load_routine(block, 4, 0); + codegen_mem_load_quad = &block_write_data[block_pos]; + build_load_routine(block, 8, 0); + codegen_mem_load_single = &block_write_data[block_pos]; + build_load_routine(block, 4, 1); + codegen_mem_load_double = &block_write_data[block_pos]; + build_load_routine(block, 8, 1); - codegen_mem_store_byte = &block_write_data[block_pos]; - build_store_routine(block, 1, 0); - codegen_mem_store_word = &block_write_data[block_pos]; - build_store_routine(block, 2, 0); - codegen_mem_store_long = &block_write_data[block_pos]; - build_store_routine(block, 4, 0); - codegen_mem_store_quad = &block_write_data[block_pos]; - build_store_routine(block, 8, 0); - codegen_mem_store_single = &block_write_data[block_pos]; - build_store_routine(block, 4, 1); - codegen_mem_store_double = &block_write_data[block_pos]; - build_store_routine(block, 8, 1); + codegen_mem_store_byte = &block_write_data[block_pos]; + build_store_routine(block, 1, 0); + codegen_mem_store_word = &block_write_data[block_pos]; + build_store_routine(block, 2, 0); + codegen_mem_store_long = &block_write_data[block_pos]; + build_store_routine(block, 4, 0); + codegen_mem_store_quad = &block_write_data[block_pos]; + build_store_routine(block, 8, 0); + codegen_mem_store_single = &block_write_data[block_pos]; + build_store_routine(block, 4, 1); + codegen_mem_store_double = &block_write_data[block_pos]; + build_store_routine(block, 8, 1); } -static void build_fp_round_routine(codeblock_t *block, int is_quad) +static void +build_fp_round_routine(codeblock_t *block, int is_quad) { - uint64_t *jump_table; + uint64_t *jump_table; - codegen_alloc(block, 80); - host_arm64_LDR_IMM_W(block, REG_TEMP, REG_CPUSTATE, (uintptr_t)&cpu_state.new_fp_control - (uintptr_t)&cpu_state); - host_arm64_ADR(block, REG_TEMP2, 12); - host_arm64_LDR_REG_X(block, REG_TEMP2, REG_TEMP2, REG_TEMP); - host_arm64_BR(block, REG_TEMP2); + codegen_alloc(block, 80); + host_arm64_LDR_IMM_W(block, REG_TEMP, REG_CPUSTATE, (uintptr_t) &cpu_state.new_fp_control - (uintptr_t) &cpu_state); + host_arm64_ADR(block, REG_TEMP2, 12); + host_arm64_LDR_REG_X(block, REG_TEMP2, REG_TEMP2, REG_TEMP); + host_arm64_BR(block, REG_TEMP2); - jump_table = (uint64_t *)&block_write_data[block_pos]; - block_pos += 4*8; + jump_table = (uint64_t *) &block_write_data[block_pos]; + block_pos += 4 * 8; - jump_table[X87_ROUNDING_NEAREST] = (uint64_t)(uintptr_t)&block_write_data[block_pos]; //tie even - if (is_quad) - host_arm64_FCVTNS_X_D(block, REG_TEMP, REG_V_TEMP); - else - host_arm64_FCVTNS_W_D(block, REG_TEMP, REG_V_TEMP); - host_arm64_RET(block, REG_X30); + jump_table[X87_ROUNDING_NEAREST] = (uint64_t) (uintptr_t) &block_write_data[block_pos]; // tie even + if (is_quad) + host_arm64_FCVTNS_X_D(block, REG_TEMP, REG_V_TEMP); + else + host_arm64_FCVTNS_W_D(block, REG_TEMP, REG_V_TEMP); + host_arm64_RET(block, REG_X30); - jump_table[X87_ROUNDING_UP] = (uint64_t)(uintptr_t)&block_write_data[block_pos]; //pos inf - if (is_quad) - host_arm64_FCVTPS_X_D(block, REG_TEMP, REG_V_TEMP); - else - host_arm64_FCVTPS_W_D(block, REG_TEMP, REG_V_TEMP); - host_arm64_RET(block, REG_X30); + jump_table[X87_ROUNDING_UP] = (uint64_t) (uintptr_t) &block_write_data[block_pos]; // pos inf + if (is_quad) + host_arm64_FCVTPS_X_D(block, REG_TEMP, REG_V_TEMP); + else + host_arm64_FCVTPS_W_D(block, REG_TEMP, REG_V_TEMP); + host_arm64_RET(block, REG_X30); - jump_table[X87_ROUNDING_DOWN] = (uint64_t)(uintptr_t)&block_write_data[block_pos]; //neg inf - if (is_quad) - host_arm64_FCVTMS_X_D(block, REG_TEMP, REG_V_TEMP); - else - host_arm64_FCVTMS_W_D(block, REG_TEMP, REG_V_TEMP); - host_arm64_RET(block, REG_X30); - - jump_table[X87_ROUNDING_CHOP] = (uint64_t)(uintptr_t)&block_write_data[block_pos]; //zero - if (is_quad) - host_arm64_FCVTZS_X_D(block, REG_TEMP, REG_V_TEMP); - else - host_arm64_FCVTZS_W_D(block, REG_TEMP, REG_V_TEMP); - host_arm64_RET(block, REG_X30); + jump_table[X87_ROUNDING_DOWN] = (uint64_t) (uintptr_t) &block_write_data[block_pos]; // neg inf + if (is_quad) + host_arm64_FCVTMS_X_D(block, REG_TEMP, REG_V_TEMP); + else + host_arm64_FCVTMS_W_D(block, REG_TEMP, REG_V_TEMP); + host_arm64_RET(block, REG_X30); + + jump_table[X87_ROUNDING_CHOP] = (uint64_t) (uintptr_t) &block_write_data[block_pos]; // zero + if (is_quad) + host_arm64_FCVTZS_X_D(block, REG_TEMP, REG_V_TEMP); + else + host_arm64_FCVTZS_W_D(block, REG_TEMP, REG_V_TEMP); + host_arm64_RET(block, REG_X30); } -void codegen_backend_init() +void +codegen_backend_init(void) { - codeblock_t *block; - int c; -#if defined(__linux__) || defined(__APPLE__) - void *start; - size_t len; - long pagesize = sysconf(_SC_PAGESIZE); - long pagemask = ~(pagesize - 1); -#endif + codeblock_t *block; - codeblock = malloc(BLOCK_SIZE * sizeof(codeblock_t)); - codeblock_hash = malloc(HASH_SIZE * sizeof(codeblock_t *)); + codeblock = malloc(BLOCK_SIZE * sizeof(codeblock_t)); + codeblock_hash = malloc(HASH_SIZE * sizeof(codeblock_t *)); - memset(codeblock, 0, BLOCK_SIZE * sizeof(codeblock_t)); - memset(codeblock_hash, 0, HASH_SIZE * sizeof(codeblock_t *)); + memset(codeblock, 0, BLOCK_SIZE * sizeof(codeblock_t)); + memset(codeblock_hash, 0, HASH_SIZE * sizeof(codeblock_t *)); - for (c = 0; c < BLOCK_SIZE; c++) - { - codeblock[c].pc = BLOCK_PC_INVALID; - } + for (int c = 0; c < BLOCK_SIZE; c++) { + codeblock[c].pc = BLOCK_PC_INVALID; + } - block_current = 0; - block_pos = 0; - block = &codeblock[block_current]; - block->head_mem_block = codegen_allocator_allocate(NULL, block_current); - block->data = codeblock_allocator_get_ptr(block->head_mem_block); - block_write_data = block->data; - build_loadstore_routines(block); + block_current = 0; + block_pos = 0; + block = &codeblock[block_current]; + block->head_mem_block = codegen_allocator_allocate(NULL, block_current); + block->data = codeblock_allocator_get_ptr(block->head_mem_block); + block_write_data = block->data; + build_loadstore_routines(block); - codegen_fp_round = &block_write_data[block_pos]; - build_fp_round_routine(block, 0); - codegen_fp_round_quad = &block_write_data[block_pos]; - build_fp_round_routine(block, 1); + codegen_fp_round = &block_write_data[block_pos]; + build_fp_round_routine(block, 0); + codegen_fp_round_quad = &block_write_data[block_pos]; + build_fp_round_routine(block, 1); - codegen_alloc(block, 80); - codegen_gpf_rout = &block_write_data[block_pos]; - host_arm64_mov_imm(block, REG_ARG0, 0); - host_arm64_mov_imm(block, REG_ARG1, 0); - host_arm64_call(block, (void *)x86gpf); + codegen_alloc(block, 80); + codegen_gpf_rout = &block_write_data[block_pos]; + host_arm64_mov_imm(block, REG_ARG0, 0); + host_arm64_mov_imm(block, REG_ARG1, 0); + host_arm64_call(block, (void *) x86gpf); - codegen_exit_rout = &block_write_data[block_pos]; - host_arm64_LDP_POSTIDX_X(block, REG_X19, REG_X20, REG_XSP, 64); - host_arm64_LDP_POSTIDX_X(block, REG_X21, REG_X22, REG_XSP, 16); - host_arm64_LDP_POSTIDX_X(block, REG_X23, REG_X24, REG_XSP, 16); - host_arm64_LDP_POSTIDX_X(block, REG_X25, REG_X26, REG_XSP, 16); - host_arm64_LDP_POSTIDX_X(block, REG_X27, REG_X28, REG_XSP, 16); - host_arm64_LDP_POSTIDX_X(block, REG_X29, REG_X30, REG_XSP, 16); - host_arm64_RET(block, REG_X30); + codegen_exit_rout = &block_write_data[block_pos]; + host_arm64_LDP_POSTIDX_X(block, REG_X19, REG_X20, REG_XSP, 64); + host_arm64_LDP_POSTIDX_X(block, REG_X21, REG_X22, REG_XSP, 16); + host_arm64_LDP_POSTIDX_X(block, REG_X23, REG_X24, REG_XSP, 16); + host_arm64_LDP_POSTIDX_X(block, REG_X25, REG_X26, REG_XSP, 16); + host_arm64_LDP_POSTIDX_X(block, REG_X27, REG_X28, REG_XSP, 16); + host_arm64_LDP_POSTIDX_X(block, REG_X29, REG_X30, REG_XSP, 16); + host_arm64_RET(block, REG_X30); - block_write_data = NULL; + block_write_data = NULL; - codegen_allocator_clean_blocks(block->head_mem_block); + codegen_allocator_clean_blocks(block->head_mem_block); - asm("mrs %0, fpcr\n" - : "=r" (cpu_state.old_fp_control) - ); + asm("mrs %0, fpcr\n" + : "=r"(cpu_state.old_fp_control)); } -void codegen_set_rounding_mode(int mode) +void +codegen_set_rounding_mode(int mode) { - if (mode < 0 || mode > 3) - fatal("codegen_set_rounding_mode - invalid mode\n"); - cpu_state.new_fp_control = mode << 3; + if (mode < 0 || mode > 3) + fatal("codegen_set_rounding_mode - invalid mode\n"); + cpu_state.new_fp_control = mode << 3; } /*R10 - cpu_state*/ -void codegen_backend_prologue(codeblock_t *block) +void +codegen_backend_prologue(codeblock_t *block) { - block_pos = BLOCK_START; + block_pos = BLOCK_START; - /*Entry code*/ + /*Entry code*/ - host_arm64_STP_PREIDX_X(block, REG_X29, REG_X30, REG_XSP, -16); - host_arm64_STP_PREIDX_X(block, REG_X27, REG_X28, REG_XSP, -16); - host_arm64_STP_PREIDX_X(block, REG_X25, REG_X26, REG_XSP, -16); - host_arm64_STP_PREIDX_X(block, REG_X23, REG_X24, REG_XSP, -16); - host_arm64_STP_PREIDX_X(block, REG_X21, REG_X22, REG_XSP, -16); - host_arm64_STP_PREIDX_X(block, REG_X19, REG_X20, REG_XSP, -64); + host_arm64_STP_PREIDX_X(block, REG_X29, REG_X30, REG_XSP, -16); + host_arm64_STP_PREIDX_X(block, REG_X27, REG_X28, REG_XSP, -16); + host_arm64_STP_PREIDX_X(block, REG_X25, REG_X26, REG_XSP, -16); + host_arm64_STP_PREIDX_X(block, REG_X23, REG_X24, REG_XSP, -16); + host_arm64_STP_PREIDX_X(block, REG_X21, REG_X22, REG_XSP, -16); + host_arm64_STP_PREIDX_X(block, REG_X19, REG_X20, REG_XSP, -64); - host_arm64_MOVX_IMM(block, REG_CPUSTATE, (uint64_t)&cpu_state); + host_arm64_MOVX_IMM(block, REG_CPUSTATE, (uint64_t) &cpu_state); - if (block->flags & CODEBLOCK_HAS_FPU) - { - host_arm64_LDR_IMM_W(block, REG_TEMP, REG_CPUSTATE, (uintptr_t)&cpu_state.TOP - (uintptr_t)&cpu_state); - host_arm64_SUB_IMM(block, REG_TEMP, REG_TEMP, block->TOP); - host_arm64_STR_IMM_W(block, REG_TEMP, REG_XSP, IREG_TOP_diff_stack_offset); - } + if (block->flags & CODEBLOCK_HAS_FPU) { + host_arm64_LDR_IMM_W(block, REG_TEMP, REG_CPUSTATE, (uintptr_t) &cpu_state.TOP - (uintptr_t) &cpu_state); + host_arm64_SUB_IMM(block, REG_TEMP, REG_TEMP, block->TOP); + host_arm64_STR_IMM_W(block, REG_TEMP, REG_XSP, IREG_TOP_diff_stack_offset); + } } -void codegen_backend_epilogue(codeblock_t *block) +void +codegen_backend_epilogue(codeblock_t *block) { - host_arm64_LDP_POSTIDX_X(block, REG_X19, REG_X20, REG_XSP, 64); - host_arm64_LDP_POSTIDX_X(block, REG_X21, REG_X22, REG_XSP, 16); - host_arm64_LDP_POSTIDX_X(block, REG_X23, REG_X24, REG_XSP, 16); - host_arm64_LDP_POSTIDX_X(block, REG_X25, REG_X26, REG_XSP, 16); - host_arm64_LDP_POSTIDX_X(block, REG_X27, REG_X28, REG_XSP, 16); - host_arm64_LDP_POSTIDX_X(block, REG_X29, REG_X30, REG_XSP, 16); - host_arm64_RET(block, REG_X30); + host_arm64_LDP_POSTIDX_X(block, REG_X19, REG_X20, REG_XSP, 64); + host_arm64_LDP_POSTIDX_X(block, REG_X21, REG_X22, REG_XSP, 16); + host_arm64_LDP_POSTIDX_X(block, REG_X23, REG_X24, REG_XSP, 16); + host_arm64_LDP_POSTIDX_X(block, REG_X25, REG_X26, REG_XSP, 16); + host_arm64_LDP_POSTIDX_X(block, REG_X27, REG_X28, REG_XSP, 16); + host_arm64_LDP_POSTIDX_X(block, REG_X29, REG_X30, REG_XSP, 16); + host_arm64_RET(block, REG_X30); - codegen_allocator_clean_blocks(block->head_mem_block); + codegen_allocator_clean_blocks(block->head_mem_block); } #endif diff --git a/src/codegen_new/codegen_backend_arm64.h b/src/codegen_new/codegen_backend_arm64.h index b4888d38e..bf3084f58 100644 --- a/src/codegen_new/codegen_backend_arm64.h +++ b/src/codegen_new/codegen_backend_arm64.h @@ -1,16 +1,15 @@ #include "codegen_backend_arm64_defs.h" -#define BLOCK_SIZE 0x4000 -#define BLOCK_MASK 0x3fff +#define BLOCK_SIZE 0x4000 +#define BLOCK_MASK 0x3fff #define BLOCK_START 0 -#define HASH_SIZE 0x20000 -#define HASH_MASK 0x1ffff +#define HASH_SIZE 0x20000 +#define HASH_MASK 0x1ffff -#define HASH(l) ((l) & 0x1ffff) - -#define BLOCK_MAX 0x3c0 +#define HASH(l) ((l) &0x1ffff) +#define BLOCK_MAX 0x3c0 void host_arm64_BLR(codeblock_t *block, int addr_reg); void host_arm64_CBNZ(codeblock_t *block, int reg, uintptr_t dest); @@ -28,4 +27,4 @@ void host_arm64_STRB_IMM_W(codeblock_t *block, int dest_reg, int base_reg, int o void host_arm64_call(codeblock_t *block, void *dst_addr); void host_arm64_mov_imm(codeblock_t *block, int reg, uint32_t imm_data); -uint32_t host_arm64_find_imm(uint32_t data); \ No newline at end of file +uint32_t host_arm64_find_imm(uint32_t data); diff --git a/src/codegen_new/codegen_backend_arm64_defs.h b/src/codegen_new/codegen_backend_arm64_defs.h index dabfe8ae8..c36f1c4a2 100644 --- a/src/codegen_new/codegen_backend_arm64_defs.h +++ b/src/codegen_new/codegen_backend_arm64_defs.h @@ -1,117 +1,117 @@ -#define REG_W0 0 -#define REG_W1 1 -#define REG_W2 2 -#define REG_W3 3 -#define REG_W4 4 -#define REG_W5 5 -#define REG_W6 6 -#define REG_W7 7 -#define REG_W8 8 -#define REG_W9 9 -#define REG_W10 10 -#define REG_W11 11 -#define REG_W12 12 -#define REG_W13 13 -#define REG_W14 14 -#define REG_W15 15 -#define REG_W16 16 -#define REG_W17 17 -#define REG_W18 18 -#define REG_W19 19 -#define REG_W20 20 -#define REG_W21 21 -#define REG_W22 22 -#define REG_W23 23 -#define REG_W24 24 -#define REG_W25 25 -#define REG_W26 26 -#define REG_W27 27 -#define REG_W28 28 -#define REG_W29 29 -#define REG_W30 30 -#define REG_WZR 31 +#define REG_W0 0 +#define REG_W1 1 +#define REG_W2 2 +#define REG_W3 3 +#define REG_W4 4 +#define REG_W5 5 +#define REG_W6 6 +#define REG_W7 7 +#define REG_W8 8 +#define REG_W9 9 +#define REG_W10 10 +#define REG_W11 11 +#define REG_W12 12 +#define REG_W13 13 +#define REG_W14 14 +#define REG_W15 15 +#define REG_W16 16 +#define REG_W17 17 +#define REG_W18 18 +#define REG_W19 19 +#define REG_W20 20 +#define REG_W21 21 +#define REG_W22 22 +#define REG_W23 23 +#define REG_W24 24 +#define REG_W25 25 +#define REG_W26 26 +#define REG_W27 27 +#define REG_W28 28 +#define REG_W29 29 +#define REG_W30 30 +#define REG_WZR 31 -#define REG_X0 0 -#define REG_X1 1 -#define REG_X2 2 -#define REG_X3 3 -#define REG_X4 4 -#define REG_X5 5 -#define REG_X6 6 -#define REG_X7 7 -#define REG_X8 8 -#define REG_X9 9 -#define REG_X10 10 -#define REG_X11 11 -#define REG_X12 12 -#define REG_X13 13 -#define REG_X14 14 -#define REG_X15 15 -#define REG_X16 16 -#define REG_X17 17 -#define REG_X18 18 -#define REG_X19 19 -#define REG_X20 20 -#define REG_X21 21 -#define REG_X22 22 -#define REG_X23 23 -#define REG_X24 24 -#define REG_X25 25 -#define REG_X26 26 -#define REG_X27 27 -#define REG_X28 28 -#define REG_X29 29 -#define REG_X30 30 -#define REG_XZR 31 +#define REG_X0 0 +#define REG_X1 1 +#define REG_X2 2 +#define REG_X3 3 +#define REG_X4 4 +#define REG_X5 5 +#define REG_X6 6 +#define REG_X7 7 +#define REG_X8 8 +#define REG_X9 9 +#define REG_X10 10 +#define REG_X11 11 +#define REG_X12 12 +#define REG_X13 13 +#define REG_X14 14 +#define REG_X15 15 +#define REG_X16 16 +#define REG_X17 17 +#define REG_X18 18 +#define REG_X19 19 +#define REG_X20 20 +#define REG_X21 21 +#define REG_X22 22 +#define REG_X23 23 +#define REG_X24 24 +#define REG_X25 25 +#define REG_X26 26 +#define REG_X27 27 +#define REG_X28 28 +#define REG_X29 29 +#define REG_X30 30 +#define REG_XZR 31 -#define REG_V0 0 -#define REG_V1 1 -#define REG_V2 2 -#define REG_V3 3 -#define REG_V4 4 -#define REG_V5 5 -#define REG_V6 6 -#define REG_V7 7 -#define REG_V8 8 -#define REG_V9 9 -#define REG_V10 10 -#define REG_V11 11 -#define REG_V12 12 -#define REG_V13 13 -#define REG_V14 14 -#define REG_V15 15 -#define REG_V16 16 -#define REG_V17 17 -#define REG_V18 18 -#define REG_V19 19 -#define REG_V20 20 -#define REG_V21 21 -#define REG_V22 22 -#define REG_V23 23 -#define REG_V24 24 -#define REG_V25 25 -#define REG_V26 26 -#define REG_V27 27 -#define REG_V28 28 -#define REG_V29 29 -#define REG_V30 30 -#define REG_V31 31 +#define REG_V0 0 +#define REG_V1 1 +#define REG_V2 2 +#define REG_V3 3 +#define REG_V4 4 +#define REG_V5 5 +#define REG_V6 6 +#define REG_V7 7 +#define REG_V8 8 +#define REG_V9 9 +#define REG_V10 10 +#define REG_V11 11 +#define REG_V12 12 +#define REG_V13 13 +#define REG_V14 14 +#define REG_V15 15 +#define REG_V16 16 +#define REG_V17 17 +#define REG_V18 18 +#define REG_V19 19 +#define REG_V20 20 +#define REG_V21 21 +#define REG_V22 22 +#define REG_V23 23 +#define REG_V24 24 +#define REG_V25 25 +#define REG_V26 26 +#define REG_V27 27 +#define REG_V28 28 +#define REG_V29 29 +#define REG_V30 30 +#define REG_V31 31 -#define REG_XSP 31 +#define REG_XSP 31 -#define REG_ARG0 REG_X0 -#define REG_ARG1 REG_X1 -#define REG_ARG2 REG_X2 -#define REG_ARG3 REG_X3 +#define REG_ARG0 REG_X0 +#define REG_ARG1 REG_X1 +#define REG_ARG2 REG_X2 +#define REG_ARG3 REG_X3 -#define REG_CPUSTATE REG_X29 +#define REG_CPUSTATE REG_X29 -#define REG_TEMP REG_X7 -#define REG_TEMP2 REG_X6 +#define REG_TEMP REG_X7 +#define REG_TEMP2 REG_X6 -#define REG_V_TEMP REG_V0 +#define REG_V_TEMP REG_V0 -#define CODEGEN_HOST_REGS 10 +#define CODEGEN_HOST_REGS 10 #define CODEGEN_HOST_FP_REGS 8 extern void *codegen_mem_load_byte; @@ -132,4 +132,4 @@ extern void *codegen_fp_round; extern void *codegen_fp_round_quad; extern void *codegen_gpf_rout; -extern void *codegen_exit_rout; \ No newline at end of file +extern void *codegen_exit_rout; diff --git a/src/codegen_new/codegen_backend_arm64_imm.c b/src/codegen_new/codegen_backend_arm64_imm.c index 0362b71d6..88d28aee0 100644 --- a/src/codegen_new/codegen_backend_arm64_imm.c +++ b/src/codegen_new/codegen_backend_arm64_imm.c @@ -5,1326 +5,1326 @@ All valid values are in the table below, which we perform a binary search over*/ #define IMM_NR 1302 -static uint32_t imm_table[][2] = -{ - {0x800, 0x00000001}, - {0xfc0, 0x00000002}, - {0x801, 0x00000003}, - {0xf80, 0x00000004}, - {0xfc1, 0x00000006}, - {0x802, 0x00000007}, - {0xf40, 0x00000008}, - {0xf81, 0x0000000c}, - {0xfc2, 0x0000000e}, - {0x803, 0x0000000f}, - {0xf00, 0x00000010}, - {0xf41, 0x00000018}, - {0xf82, 0x0000001c}, - {0xfc3, 0x0000001e}, - {0x804, 0x0000001f}, - {0xec0, 0x00000020}, - {0xf01, 0x00000030}, - {0xf42, 0x00000038}, - {0xf83, 0x0000003c}, - {0xfc4, 0x0000003e}, - {0x805, 0x0000003f}, - {0xe80, 0x00000040}, - {0xec1, 0x00000060}, - {0xf02, 0x00000070}, - {0xf43, 0x00000078}, - {0xf84, 0x0000007c}, - {0xfc5, 0x0000007e}, - {0x806, 0x0000007f}, - {0xe40, 0x00000080}, - {0xe81, 0x000000c0}, - {0xec2, 0x000000e0}, - {0xf03, 0x000000f0}, - {0xf44, 0x000000f8}, - {0xf85, 0x000000fc}, - {0xfc6, 0x000000fe}, - {0x807, 0x000000ff}, - {0xe00, 0x00000100}, - {0xe41, 0x00000180}, - {0xe82, 0x000001c0}, - {0xec3, 0x000001e0}, - {0xf04, 0x000001f0}, - {0xf45, 0x000001f8}, - {0xf86, 0x000001fc}, - {0xfc7, 0x000001fe}, - {0x808, 0x000001ff}, - {0xdc0, 0x00000200}, - {0xe01, 0x00000300}, - {0xe42, 0x00000380}, - {0xe83, 0x000003c0}, - {0xec4, 0x000003e0}, - {0xf05, 0x000003f0}, - {0xf46, 0x000003f8}, - {0xf87, 0x000003fc}, - {0xfc8, 0x000003fe}, - {0x809, 0x000003ff}, - {0xd80, 0x00000400}, - {0xdc1, 0x00000600}, - {0xe02, 0x00000700}, - {0xe43, 0x00000780}, - {0xe84, 0x000007c0}, - {0xec5, 0x000007e0}, - {0xf06, 0x000007f0}, - {0xf47, 0x000007f8}, - {0xf88, 0x000007fc}, - {0xfc9, 0x000007fe}, - {0x80a, 0x000007ff}, - {0xd40, 0x00000800}, - {0xd81, 0x00000c00}, - {0xdc2, 0x00000e00}, - {0xe03, 0x00000f00}, - {0xe44, 0x00000f80}, - {0xe85, 0x00000fc0}, - {0xec6, 0x00000fe0}, - {0xf07, 0x00000ff0}, - {0xf48, 0x00000ff8}, - {0xf89, 0x00000ffc}, - {0xfca, 0x00000ffe}, - {0x80b, 0x00000fff}, - {0xd00, 0x00001000}, - {0xd41, 0x00001800}, - {0xd82, 0x00001c00}, - {0xdc3, 0x00001e00}, - {0xe04, 0x00001f00}, - {0xe45, 0x00001f80}, - {0xe86, 0x00001fc0}, - {0xec7, 0x00001fe0}, - {0xf08, 0x00001ff0}, - {0xf49, 0x00001ff8}, - {0xf8a, 0x00001ffc}, - {0xfcb, 0x00001ffe}, - {0x80c, 0x00001fff}, - {0xcc0, 0x00002000}, - {0xd01, 0x00003000}, - {0xd42, 0x00003800}, - {0xd83, 0x00003c00}, - {0xdc4, 0x00003e00}, - {0xe05, 0x00003f00}, - {0xe46, 0x00003f80}, - {0xe87, 0x00003fc0}, - {0xec8, 0x00003fe0}, - {0xf09, 0x00003ff0}, - {0xf4a, 0x00003ff8}, - {0xf8b, 0x00003ffc}, - {0xfcc, 0x00003ffe}, - {0x80d, 0x00003fff}, - {0xc80, 0x00004000}, - {0xcc1, 0x00006000}, - {0xd02, 0x00007000}, - {0xd43, 0x00007800}, - {0xd84, 0x00007c00}, - {0xdc5, 0x00007e00}, - {0xe06, 0x00007f00}, - {0xe47, 0x00007f80}, - {0xe88, 0x00007fc0}, - {0xec9, 0x00007fe0}, - {0xf0a, 0x00007ff0}, - {0xf4b, 0x00007ff8}, - {0xf8c, 0x00007ffc}, - {0xfcd, 0x00007ffe}, - {0x80e, 0x00007fff}, - {0xc40, 0x00008000}, - {0xc81, 0x0000c000}, - {0xcc2, 0x0000e000}, - {0xd03, 0x0000f000}, - {0xd44, 0x0000f800}, - {0xd85, 0x0000fc00}, - {0xdc6, 0x0000fe00}, - {0xe07, 0x0000ff00}, - {0xe48, 0x0000ff80}, - {0xe89, 0x0000ffc0}, - {0xeca, 0x0000ffe0}, - {0xf0b, 0x0000fff0}, - {0xf4c, 0x0000fff8}, - {0xf8d, 0x0000fffc}, - {0xfce, 0x0000fffe}, - {0x80f, 0x0000ffff}, - {0xc00, 0x00010000}, - {0xc20, 0x00010001}, - {0xc41, 0x00018000}, - {0xc82, 0x0001c000}, - {0xcc3, 0x0001e000}, - {0xd04, 0x0001f000}, - {0xd45, 0x0001f800}, - {0xd86, 0x0001fc00}, - {0xdc7, 0x0001fe00}, - {0xe08, 0x0001ff00}, - {0xe49, 0x0001ff80}, - {0xe8a, 0x0001ffc0}, - {0xecb, 0x0001ffe0}, - {0xf0c, 0x0001fff0}, - {0xf4d, 0x0001fff8}, - {0xf8e, 0x0001fffc}, - {0xfcf, 0x0001fffe}, - {0x810, 0x0001ffff}, - {0xbc0, 0x00020000}, - {0xfe0, 0x00020002}, - {0xc01, 0x00030000}, - {0xc21, 0x00030003}, - {0xc42, 0x00038000}, - {0xc83, 0x0003c000}, - {0xcc4, 0x0003e000}, - {0xd05, 0x0003f000}, - {0xd46, 0x0003f800}, - {0xd87, 0x0003fc00}, - {0xdc8, 0x0003fe00}, - {0xe09, 0x0003ff00}, - {0xe4a, 0x0003ff80}, - {0xe8b, 0x0003ffc0}, - {0xecc, 0x0003ffe0}, - {0xf0d, 0x0003fff0}, - {0xf4e, 0x0003fff8}, - {0xf8f, 0x0003fffc}, - {0xfd0, 0x0003fffe}, - {0x811, 0x0003ffff}, - {0xb80, 0x00040000}, - {0xfa0, 0x00040004}, - {0xbc1, 0x00060000}, - {0xfe1, 0x00060006}, - {0xc02, 0x00070000}, - {0xc22, 0x00070007}, - {0xc43, 0x00078000}, - {0xc84, 0x0007c000}, - {0xcc5, 0x0007e000}, - {0xd06, 0x0007f000}, - {0xd47, 0x0007f800}, - {0xd88, 0x0007fc00}, - {0xdc9, 0x0007fe00}, - {0xe0a, 0x0007ff00}, - {0xe4b, 0x0007ff80}, - {0xe8c, 0x0007ffc0}, - {0xecd, 0x0007ffe0}, - {0xf0e, 0x0007fff0}, - {0xf4f, 0x0007fff8}, - {0xf90, 0x0007fffc}, - {0xfd1, 0x0007fffe}, - {0x812, 0x0007ffff}, - {0xb40, 0x00080000}, - {0xf60, 0x00080008}, - {0xb81, 0x000c0000}, - {0xfa1, 0x000c000c}, - {0xbc2, 0x000e0000}, - {0xfe2, 0x000e000e}, - {0xc03, 0x000f0000}, - {0xc23, 0x000f000f}, - {0xc44, 0x000f8000}, - {0xc85, 0x000fc000}, - {0xcc6, 0x000fe000}, - {0xd07, 0x000ff000}, - {0xd48, 0x000ff800}, - {0xd89, 0x000ffc00}, - {0xdca, 0x000ffe00}, - {0xe0b, 0x000fff00}, - {0xe4c, 0x000fff80}, - {0xe8d, 0x000fffc0}, - {0xece, 0x000fffe0}, - {0xf0f, 0x000ffff0}, - {0xf50, 0x000ffff8}, - {0xf91, 0x000ffffc}, - {0xfd2, 0x000ffffe}, - {0x813, 0x000fffff}, - {0xb00, 0x00100000}, - {0xf20, 0x00100010}, - {0xb41, 0x00180000}, - {0xf61, 0x00180018}, - {0xb82, 0x001c0000}, - {0xfa2, 0x001c001c}, - {0xbc3, 0x001e0000}, - {0xfe3, 0x001e001e}, - {0xc04, 0x001f0000}, - {0xc24, 0x001f001f}, - {0xc45, 0x001f8000}, - {0xc86, 0x001fc000}, - {0xcc7, 0x001fe000}, - {0xd08, 0x001ff000}, - {0xd49, 0x001ff800}, - {0xd8a, 0x001ffc00}, - {0xdcb, 0x001ffe00}, - {0xe0c, 0x001fff00}, - {0xe4d, 0x001fff80}, - {0xe8e, 0x001fffc0}, - {0xecf, 0x001fffe0}, - {0xf10, 0x001ffff0}, - {0xf51, 0x001ffff8}, - {0xf92, 0x001ffffc}, - {0xfd3, 0x001ffffe}, - {0x814, 0x001fffff}, - {0xac0, 0x00200000}, - {0xee0, 0x00200020}, - {0xb01, 0x00300000}, - {0xf21, 0x00300030}, - {0xb42, 0x00380000}, - {0xf62, 0x00380038}, - {0xb83, 0x003c0000}, - {0xfa3, 0x003c003c}, - {0xbc4, 0x003e0000}, - {0xfe4, 0x003e003e}, - {0xc05, 0x003f0000}, - {0xc25, 0x003f003f}, - {0xc46, 0x003f8000}, - {0xc87, 0x003fc000}, - {0xcc8, 0x003fe000}, - {0xd09, 0x003ff000}, - {0xd4a, 0x003ff800}, - {0xd8b, 0x003ffc00}, - {0xdcc, 0x003ffe00}, - {0xe0d, 0x003fff00}, - {0xe4e, 0x003fff80}, - {0xe8f, 0x003fffc0}, - {0xed0, 0x003fffe0}, - {0xf11, 0x003ffff0}, - {0xf52, 0x003ffff8}, - {0xf93, 0x003ffffc}, - {0xfd4, 0x003ffffe}, - {0x815, 0x003fffff}, - {0xa80, 0x00400000}, - {0xea0, 0x00400040}, - {0xac1, 0x00600000}, - {0xee1, 0x00600060}, - {0xb02, 0x00700000}, - {0xf22, 0x00700070}, - {0xb43, 0x00780000}, - {0xf63, 0x00780078}, - {0xb84, 0x007c0000}, - {0xfa4, 0x007c007c}, - {0xbc5, 0x007e0000}, - {0xfe5, 0x007e007e}, - {0xc06, 0x007f0000}, - {0xc26, 0x007f007f}, - {0xc47, 0x007f8000}, - {0xc88, 0x007fc000}, - {0xcc9, 0x007fe000}, - {0xd0a, 0x007ff000}, - {0xd4b, 0x007ff800}, - {0xd8c, 0x007ffc00}, - {0xdcd, 0x007ffe00}, - {0xe0e, 0x007fff00}, - {0xe4f, 0x007fff80}, - {0xe90, 0x007fffc0}, - {0xed1, 0x007fffe0}, - {0xf12, 0x007ffff0}, - {0xf53, 0x007ffff8}, - {0xf94, 0x007ffffc}, - {0xfd5, 0x007ffffe}, - {0x816, 0x007fffff}, - {0xa40, 0x00800000}, - {0xe60, 0x00800080}, - {0xa81, 0x00c00000}, - {0xea1, 0x00c000c0}, - {0xac2, 0x00e00000}, - {0xee2, 0x00e000e0}, - {0xb03, 0x00f00000}, - {0xf23, 0x00f000f0}, - {0xb44, 0x00f80000}, - {0xf64, 0x00f800f8}, - {0xb85, 0x00fc0000}, - {0xfa5, 0x00fc00fc}, - {0xbc6, 0x00fe0000}, - {0xfe6, 0x00fe00fe}, - {0xc07, 0x00ff0000}, - {0xc27, 0x00ff00ff}, - {0xc48, 0x00ff8000}, - {0xc89, 0x00ffc000}, - {0xcca, 0x00ffe000}, - {0xd0b, 0x00fff000}, - {0xd4c, 0x00fff800}, - {0xd8d, 0x00fffc00}, - {0xdce, 0x00fffe00}, - {0xe0f, 0x00ffff00}, - {0xe50, 0x00ffff80}, - {0xe91, 0x00ffffc0}, - {0xed2, 0x00ffffe0}, - {0xf13, 0x00fffff0}, - {0xf54, 0x00fffff8}, - {0xf95, 0x00fffffc}, - {0xfd6, 0x00fffffe}, - {0x817, 0x00ffffff}, - {0xa00, 0x01000000}, - {0xe20, 0x01000100}, - {0xe30, 0x01010101}, - {0xa41, 0x01800000}, - {0xe61, 0x01800180}, - {0xa82, 0x01c00000}, - {0xea2, 0x01c001c0}, - {0xac3, 0x01e00000}, - {0xee3, 0x01e001e0}, - {0xb04, 0x01f00000}, - {0xf24, 0x01f001f0}, - {0xb45, 0x01f80000}, - {0xf65, 0x01f801f8}, - {0xb86, 0x01fc0000}, - {0xfa6, 0x01fc01fc}, - {0xbc7, 0x01fe0000}, - {0xfe7, 0x01fe01fe}, - {0xc08, 0x01ff0000}, - {0xc28, 0x01ff01ff}, - {0xc49, 0x01ff8000}, - {0xc8a, 0x01ffc000}, - {0xccb, 0x01ffe000}, - {0xd0c, 0x01fff000}, - {0xd4d, 0x01fff800}, - {0xd8e, 0x01fffc00}, - {0xdcf, 0x01fffe00}, - {0xe10, 0x01ffff00}, - {0xe51, 0x01ffff80}, - {0xe92, 0x01ffffc0}, - {0xed3, 0x01ffffe0}, - {0xf14, 0x01fffff0}, - {0xf55, 0x01fffff8}, - {0xf96, 0x01fffffc}, - {0xfd7, 0x01fffffe}, - {0x818, 0x01ffffff}, - {0x9c0, 0x02000000}, - {0xde0, 0x02000200}, - {0xff0, 0x02020202}, - {0xa01, 0x03000000}, - {0xe21, 0x03000300}, - {0xe31, 0x03030303}, - {0xa42, 0x03800000}, - {0xe62, 0x03800380}, - {0xa83, 0x03c00000}, - {0xea3, 0x03c003c0}, - {0xac4, 0x03e00000}, - {0xee4, 0x03e003e0}, - {0xb05, 0x03f00000}, - {0xf25, 0x03f003f0}, - {0xb46, 0x03f80000}, - {0xf66, 0x03f803f8}, - {0xb87, 0x03fc0000}, - {0xfa7, 0x03fc03fc}, - {0xbc8, 0x03fe0000}, - {0xfe8, 0x03fe03fe}, - {0xc09, 0x03ff0000}, - {0xc29, 0x03ff03ff}, - {0xc4a, 0x03ff8000}, - {0xc8b, 0x03ffc000}, - {0xccc, 0x03ffe000}, - {0xd0d, 0x03fff000}, - {0xd4e, 0x03fff800}, - {0xd8f, 0x03fffc00}, - {0xdd0, 0x03fffe00}, - {0xe11, 0x03ffff00}, - {0xe52, 0x03ffff80}, - {0xe93, 0x03ffffc0}, - {0xed4, 0x03ffffe0}, - {0xf15, 0x03fffff0}, - {0xf56, 0x03fffff8}, - {0xf97, 0x03fffffc}, - {0xfd8, 0x03fffffe}, - {0x819, 0x03ffffff}, - {0x980, 0x04000000}, - {0xda0, 0x04000400}, - {0xfb0, 0x04040404}, - {0x9c1, 0x06000000}, - {0xde1, 0x06000600}, - {0xff1, 0x06060606}, - {0xa02, 0x07000000}, - {0xe22, 0x07000700}, - {0xe32, 0x07070707}, - {0xa43, 0x07800000}, - {0xe63, 0x07800780}, - {0xa84, 0x07c00000}, - {0xea4, 0x07c007c0}, - {0xac5, 0x07e00000}, - {0xee5, 0x07e007e0}, - {0xb06, 0x07f00000}, - {0xf26, 0x07f007f0}, - {0xb47, 0x07f80000}, - {0xf67, 0x07f807f8}, - {0xb88, 0x07fc0000}, - {0xfa8, 0x07fc07fc}, - {0xbc9, 0x07fe0000}, - {0xfe9, 0x07fe07fe}, - {0xc0a, 0x07ff0000}, - {0xc2a, 0x07ff07ff}, - {0xc4b, 0x07ff8000}, - {0xc8c, 0x07ffc000}, - {0xccd, 0x07ffe000}, - {0xd0e, 0x07fff000}, - {0xd4f, 0x07fff800}, - {0xd90, 0x07fffc00}, - {0xdd1, 0x07fffe00}, - {0xe12, 0x07ffff00}, - {0xe53, 0x07ffff80}, - {0xe94, 0x07ffffc0}, - {0xed5, 0x07ffffe0}, - {0xf16, 0x07fffff0}, - {0xf57, 0x07fffff8}, - {0xf98, 0x07fffffc}, - {0xfd9, 0x07fffffe}, - {0x81a, 0x07ffffff}, - {0x940, 0x08000000}, - {0xd60, 0x08000800}, - {0xf70, 0x08080808}, - {0x981, 0x0c000000}, - {0xda1, 0x0c000c00}, - {0xfb1, 0x0c0c0c0c}, - {0x9c2, 0x0e000000}, - {0xde2, 0x0e000e00}, - {0xff2, 0x0e0e0e0e}, - {0xa03, 0x0f000000}, - {0xe23, 0x0f000f00}, - {0xe33, 0x0f0f0f0f}, - {0xa44, 0x0f800000}, - {0xe64, 0x0f800f80}, - {0xa85, 0x0fc00000}, - {0xea5, 0x0fc00fc0}, - {0xac6, 0x0fe00000}, - {0xee6, 0x0fe00fe0}, - {0xb07, 0x0ff00000}, - {0xf27, 0x0ff00ff0}, - {0xb48, 0x0ff80000}, - {0xf68, 0x0ff80ff8}, - {0xb89, 0x0ffc0000}, - {0xfa9, 0x0ffc0ffc}, - {0xbca, 0x0ffe0000}, - {0xfea, 0x0ffe0ffe}, - {0xc0b, 0x0fff0000}, - {0xc2b, 0x0fff0fff}, - {0xc4c, 0x0fff8000}, - {0xc8d, 0x0fffc000}, - {0xcce, 0x0fffe000}, - {0xd0f, 0x0ffff000}, - {0xd50, 0x0ffff800}, - {0xd91, 0x0ffffc00}, - {0xdd2, 0x0ffffe00}, - {0xe13, 0x0fffff00}, - {0xe54, 0x0fffff80}, - {0xe95, 0x0fffffc0}, - {0xed6, 0x0fffffe0}, - {0xf17, 0x0ffffff0}, - {0xf58, 0x0ffffff8}, - {0xf99, 0x0ffffffc}, - {0xfda, 0x0ffffffe}, - {0x81b, 0x0fffffff}, - {0x900, 0x10000000}, - {0xd20, 0x10001000}, - {0xf30, 0x10101010}, - {0xf38, 0x11111111}, - {0x941, 0x18000000}, - {0xd61, 0x18001800}, - {0xf71, 0x18181818}, - {0x982, 0x1c000000}, - {0xda2, 0x1c001c00}, - {0xfb2, 0x1c1c1c1c}, - {0x9c3, 0x1e000000}, - {0xde3, 0x1e001e00}, - {0xff3, 0x1e1e1e1e}, - {0xa04, 0x1f000000}, - {0xe24, 0x1f001f00}, - {0xe34, 0x1f1f1f1f}, - {0xa45, 0x1f800000}, - {0xe65, 0x1f801f80}, - {0xa86, 0x1fc00000}, - {0xea6, 0x1fc01fc0}, - {0xac7, 0x1fe00000}, - {0xee7, 0x1fe01fe0}, - {0xb08, 0x1ff00000}, - {0xf28, 0x1ff01ff0}, - {0xb49, 0x1ff80000}, - {0xf69, 0x1ff81ff8}, - {0xb8a, 0x1ffc0000}, - {0xfaa, 0x1ffc1ffc}, - {0xbcb, 0x1ffe0000}, - {0xfeb, 0x1ffe1ffe}, - {0xc0c, 0x1fff0000}, - {0xc2c, 0x1fff1fff}, - {0xc4d, 0x1fff8000}, - {0xc8e, 0x1fffc000}, - {0xccf, 0x1fffe000}, - {0xd10, 0x1ffff000}, - {0xd51, 0x1ffff800}, - {0xd92, 0x1ffffc00}, - {0xdd3, 0x1ffffe00}, - {0xe14, 0x1fffff00}, - {0xe55, 0x1fffff80}, - {0xe96, 0x1fffffc0}, - {0xed7, 0x1fffffe0}, - {0xf18, 0x1ffffff0}, - {0xf59, 0x1ffffff8}, - {0xf9a, 0x1ffffffc}, - {0xfdb, 0x1ffffffe}, - {0x81c, 0x1fffffff}, - {0x8c0, 0x20000000}, - {0xce0, 0x20002000}, - {0xef0, 0x20202020}, - {0xff8, 0x22222222}, - {0x901, 0x30000000}, - {0xd21, 0x30003000}, - {0xf31, 0x30303030}, - {0xf39, 0x33333333}, - {0x942, 0x38000000}, - {0xd62, 0x38003800}, - {0xf72, 0x38383838}, - {0x983, 0x3c000000}, - {0xda3, 0x3c003c00}, - {0xfb3, 0x3c3c3c3c}, - {0x9c4, 0x3e000000}, - {0xde4, 0x3e003e00}, - {0xff4, 0x3e3e3e3e}, - {0xa05, 0x3f000000}, - {0xe25, 0x3f003f00}, - {0xe35, 0x3f3f3f3f}, - {0xa46, 0x3f800000}, - {0xe66, 0x3f803f80}, - {0xa87, 0x3fc00000}, - {0xea7, 0x3fc03fc0}, - {0xac8, 0x3fe00000}, - {0xee8, 0x3fe03fe0}, - {0xb09, 0x3ff00000}, - {0xf29, 0x3ff03ff0}, - {0xb4a, 0x3ff80000}, - {0xf6a, 0x3ff83ff8}, - {0xb8b, 0x3ffc0000}, - {0xfab, 0x3ffc3ffc}, - {0xbcc, 0x3ffe0000}, - {0xfec, 0x3ffe3ffe}, - {0xc0d, 0x3fff0000}, - {0xc2d, 0x3fff3fff}, - {0xc4e, 0x3fff8000}, - {0xc8f, 0x3fffc000}, - {0xcd0, 0x3fffe000}, - {0xd11, 0x3ffff000}, - {0xd52, 0x3ffff800}, - {0xd93, 0x3ffffc00}, - {0xdd4, 0x3ffffe00}, - {0xe15, 0x3fffff00}, - {0xe56, 0x3fffff80}, - {0xe97, 0x3fffffc0}, - {0xed8, 0x3fffffe0}, - {0xf19, 0x3ffffff0}, - {0xf5a, 0x3ffffff8}, - {0xf9b, 0x3ffffffc}, - {0xfdc, 0x3ffffffe}, - {0x81d, 0x3fffffff}, - {0x880, 0x40000000}, - {0xca0, 0x40004000}, - {0xeb0, 0x40404040}, - {0xfb8, 0x44444444}, - {0xfbc, 0x55555555}, - {0x8c1, 0x60000000}, - {0xce1, 0x60006000}, - {0xef1, 0x60606060}, - {0xff9, 0x66666666}, - {0x902, 0x70000000}, - {0xd22, 0x70007000}, - {0xf32, 0x70707070}, - {0xf3a, 0x77777777}, - {0x943, 0x78000000}, - {0xd63, 0x78007800}, - {0xf73, 0x78787878}, - {0x984, 0x7c000000}, - {0xda4, 0x7c007c00}, - {0xfb4, 0x7c7c7c7c}, - {0x9c5, 0x7e000000}, - {0xde5, 0x7e007e00}, - {0xff5, 0x7e7e7e7e}, - {0xa06, 0x7f000000}, - {0xe26, 0x7f007f00}, - {0xe36, 0x7f7f7f7f}, - {0xa47, 0x7f800000}, - {0xe67, 0x7f807f80}, - {0xa88, 0x7fc00000}, - {0xea8, 0x7fc07fc0}, - {0xac9, 0x7fe00000}, - {0xee9, 0x7fe07fe0}, - {0xb0a, 0x7ff00000}, - {0xf2a, 0x7ff07ff0}, - {0xb4b, 0x7ff80000}, - {0xf6b, 0x7ff87ff8}, - {0xb8c, 0x7ffc0000}, - {0xfac, 0x7ffc7ffc}, - {0xbcd, 0x7ffe0000}, - {0xfed, 0x7ffe7ffe}, - {0xc0e, 0x7fff0000}, - {0xc2e, 0x7fff7fff}, - {0xc4f, 0x7fff8000}, - {0xc90, 0x7fffc000}, - {0xcd1, 0x7fffe000}, - {0xd12, 0x7ffff000}, - {0xd53, 0x7ffff800}, - {0xd94, 0x7ffffc00}, - {0xdd5, 0x7ffffe00}, - {0xe16, 0x7fffff00}, - {0xe57, 0x7fffff80}, - {0xe98, 0x7fffffc0}, - {0xed9, 0x7fffffe0}, - {0xf1a, 0x7ffffff0}, - {0xf5b, 0x7ffffff8}, - {0xf9c, 0x7ffffffc}, - {0xfdd, 0x7ffffffe}, - {0x81e, 0x7fffffff}, - {0x840, 0x80000000}, - {0x841, 0x80000001}, - {0x842, 0x80000003}, - {0x843, 0x80000007}, - {0x844, 0x8000000f}, - {0x845, 0x8000001f}, - {0x846, 0x8000003f}, - {0x847, 0x8000007f}, - {0x848, 0x800000ff}, - {0x849, 0x800001ff}, - {0x84a, 0x800003ff}, - {0x84b, 0x800007ff}, - {0x84c, 0x80000fff}, - {0x84d, 0x80001fff}, - {0x84e, 0x80003fff}, - {0x84f, 0x80007fff}, - {0xc60, 0x80008000}, - {0x850, 0x8000ffff}, - {0xc61, 0x80018001}, - {0x851, 0x8001ffff}, - {0xc62, 0x80038003}, - {0x852, 0x8003ffff}, - {0xc63, 0x80078007}, - {0x853, 0x8007ffff}, - {0xc64, 0x800f800f}, - {0x854, 0x800fffff}, - {0xc65, 0x801f801f}, - {0x855, 0x801fffff}, - {0xc66, 0x803f803f}, - {0x856, 0x803fffff}, - {0xc67, 0x807f807f}, - {0x857, 0x807fffff}, - {0xe70, 0x80808080}, - {0xc68, 0x80ff80ff}, - {0x858, 0x80ffffff}, - {0xe71, 0x81818181}, - {0xc69, 0x81ff81ff}, - {0x859, 0x81ffffff}, - {0xe72, 0x83838383}, - {0xc6a, 0x83ff83ff}, - {0x85a, 0x83ffffff}, - {0xe73, 0x87878787}, - {0xc6b, 0x87ff87ff}, - {0x85b, 0x87ffffff}, - {0xf78, 0x88888888}, - {0xe74, 0x8f8f8f8f}, - {0xc6c, 0x8fff8fff}, - {0x85c, 0x8fffffff}, - {0xf79, 0x99999999}, - {0xe75, 0x9f9f9f9f}, - {0xc6d, 0x9fff9fff}, - {0x85d, 0x9fffffff}, - {0xffc, 0xaaaaaaaa}, - {0xf7a, 0xbbbbbbbb}, - {0xe76, 0xbfbfbfbf}, - {0xc6e, 0xbfffbfff}, - {0x85e, 0xbfffffff}, - {0x881, 0xc0000000}, - {0x882, 0xc0000001}, - {0x883, 0xc0000003}, - {0x884, 0xc0000007}, - {0x885, 0xc000000f}, - {0x886, 0xc000001f}, - {0x887, 0xc000003f}, - {0x888, 0xc000007f}, - {0x889, 0xc00000ff}, - {0x88a, 0xc00001ff}, - {0x88b, 0xc00003ff}, - {0x88c, 0xc00007ff}, - {0x88d, 0xc0000fff}, - {0x88e, 0xc0001fff}, - {0x88f, 0xc0003fff}, - {0x890, 0xc0007fff}, - {0xca1, 0xc000c000}, - {0x891, 0xc000ffff}, - {0xca2, 0xc001c001}, - {0x892, 0xc001ffff}, - {0xca3, 0xc003c003}, - {0x893, 0xc003ffff}, - {0xca4, 0xc007c007}, - {0x894, 0xc007ffff}, - {0xca5, 0xc00fc00f}, - {0x895, 0xc00fffff}, - {0xca6, 0xc01fc01f}, - {0x896, 0xc01fffff}, - {0xca7, 0xc03fc03f}, - {0x897, 0xc03fffff}, - {0xca8, 0xc07fc07f}, - {0x898, 0xc07fffff}, - {0xeb1, 0xc0c0c0c0}, - {0xca9, 0xc0ffc0ff}, - {0x899, 0xc0ffffff}, - {0xeb2, 0xc1c1c1c1}, - {0xcaa, 0xc1ffc1ff}, - {0x89a, 0xc1ffffff}, - {0xeb3, 0xc3c3c3c3}, - {0xcab, 0xc3ffc3ff}, - {0x89b, 0xc3ffffff}, - {0xeb4, 0xc7c7c7c7}, - {0xcac, 0xc7ffc7ff}, - {0x89c, 0xc7ffffff}, - {0xfb9, 0xcccccccc}, - {0xeb5, 0xcfcfcfcf}, - {0xcad, 0xcfffcfff}, - {0x89d, 0xcfffffff}, - {0xfba, 0xdddddddd}, - {0xeb6, 0xdfdfdfdf}, - {0xcae, 0xdfffdfff}, - {0x89e, 0xdfffffff}, - {0x8c2, 0xe0000000}, - {0x8c3, 0xe0000001}, - {0x8c4, 0xe0000003}, - {0x8c5, 0xe0000007}, - {0x8c6, 0xe000000f}, - {0x8c7, 0xe000001f}, - {0x8c8, 0xe000003f}, - {0x8c9, 0xe000007f}, - {0x8ca, 0xe00000ff}, - {0x8cb, 0xe00001ff}, - {0x8cc, 0xe00003ff}, - {0x8cd, 0xe00007ff}, - {0x8ce, 0xe0000fff}, - {0x8cf, 0xe0001fff}, - {0x8d0, 0xe0003fff}, - {0x8d1, 0xe0007fff}, - {0xce2, 0xe000e000}, - {0x8d2, 0xe000ffff}, - {0xce3, 0xe001e001}, - {0x8d3, 0xe001ffff}, - {0xce4, 0xe003e003}, - {0x8d4, 0xe003ffff}, - {0xce5, 0xe007e007}, - {0x8d5, 0xe007ffff}, - {0xce6, 0xe00fe00f}, - {0x8d6, 0xe00fffff}, - {0xce7, 0xe01fe01f}, - {0x8d7, 0xe01fffff}, - {0xce8, 0xe03fe03f}, - {0x8d8, 0xe03fffff}, - {0xce9, 0xe07fe07f}, - {0x8d9, 0xe07fffff}, - {0xef2, 0xe0e0e0e0}, - {0xcea, 0xe0ffe0ff}, - {0x8da, 0xe0ffffff}, - {0xef3, 0xe1e1e1e1}, - {0xceb, 0xe1ffe1ff}, - {0x8db, 0xe1ffffff}, - {0xef4, 0xe3e3e3e3}, - {0xcec, 0xe3ffe3ff}, - {0x8dc, 0xe3ffffff}, - {0xef5, 0xe7e7e7e7}, - {0xced, 0xe7ffe7ff}, - {0x8dd, 0xe7ffffff}, - {0xffa, 0xeeeeeeee}, - {0xef6, 0xefefefef}, - {0xcee, 0xefffefff}, - {0x8de, 0xefffffff}, - {0x903, 0xf0000000}, - {0x904, 0xf0000001}, - {0x905, 0xf0000003}, - {0x906, 0xf0000007}, - {0x907, 0xf000000f}, - {0x908, 0xf000001f}, - {0x909, 0xf000003f}, - {0x90a, 0xf000007f}, - {0x90b, 0xf00000ff}, - {0x90c, 0xf00001ff}, - {0x90d, 0xf00003ff}, - {0x90e, 0xf00007ff}, - {0x90f, 0xf0000fff}, - {0x910, 0xf0001fff}, - {0x911, 0xf0003fff}, - {0x912, 0xf0007fff}, - {0xd23, 0xf000f000}, - {0x913, 0xf000ffff}, - {0xd24, 0xf001f001}, - {0x914, 0xf001ffff}, - {0xd25, 0xf003f003}, - {0x915, 0xf003ffff}, - {0xd26, 0xf007f007}, - {0x916, 0xf007ffff}, - {0xd27, 0xf00ff00f}, - {0x917, 0xf00fffff}, - {0xd28, 0xf01ff01f}, - {0x918, 0xf01fffff}, - {0xd29, 0xf03ff03f}, - {0x919, 0xf03fffff}, - {0xd2a, 0xf07ff07f}, - {0x91a, 0xf07fffff}, - {0xf33, 0xf0f0f0f0}, - {0xd2b, 0xf0fff0ff}, - {0x91b, 0xf0ffffff}, - {0xf34, 0xf1f1f1f1}, - {0xd2c, 0xf1fff1ff}, - {0x91c, 0xf1ffffff}, - {0xf35, 0xf3f3f3f3}, - {0xd2d, 0xf3fff3ff}, - {0x91d, 0xf3ffffff}, - {0xf36, 0xf7f7f7f7}, - {0xd2e, 0xf7fff7ff}, - {0x91e, 0xf7ffffff}, - {0x944, 0xf8000000}, - {0x945, 0xf8000001}, - {0x946, 0xf8000003}, - {0x947, 0xf8000007}, - {0x948, 0xf800000f}, - {0x949, 0xf800001f}, - {0x94a, 0xf800003f}, - {0x94b, 0xf800007f}, - {0x94c, 0xf80000ff}, - {0x94d, 0xf80001ff}, - {0x94e, 0xf80003ff}, - {0x94f, 0xf80007ff}, - {0x950, 0xf8000fff}, - {0x951, 0xf8001fff}, - {0x952, 0xf8003fff}, - {0x953, 0xf8007fff}, - {0xd64, 0xf800f800}, - {0x954, 0xf800ffff}, - {0xd65, 0xf801f801}, - {0x955, 0xf801ffff}, - {0xd66, 0xf803f803}, - {0x956, 0xf803ffff}, - {0xd67, 0xf807f807}, - {0x957, 0xf807ffff}, - {0xd68, 0xf80ff80f}, - {0x958, 0xf80fffff}, - {0xd69, 0xf81ff81f}, - {0x959, 0xf81fffff}, - {0xd6a, 0xf83ff83f}, - {0x95a, 0xf83fffff}, - {0xd6b, 0xf87ff87f}, - {0x95b, 0xf87fffff}, - {0xf74, 0xf8f8f8f8}, - {0xd6c, 0xf8fff8ff}, - {0x95c, 0xf8ffffff}, - {0xf75, 0xf9f9f9f9}, - {0xd6d, 0xf9fff9ff}, - {0x95d, 0xf9ffffff}, - {0xf76, 0xfbfbfbfb}, - {0xd6e, 0xfbfffbff}, - {0x95e, 0xfbffffff}, - {0x985, 0xfc000000}, - {0x986, 0xfc000001}, - {0x987, 0xfc000003}, - {0x988, 0xfc000007}, - {0x989, 0xfc00000f}, - {0x98a, 0xfc00001f}, - {0x98b, 0xfc00003f}, - {0x98c, 0xfc00007f}, - {0x98d, 0xfc0000ff}, - {0x98e, 0xfc0001ff}, - {0x98f, 0xfc0003ff}, - {0x990, 0xfc0007ff}, - {0x991, 0xfc000fff}, - {0x992, 0xfc001fff}, - {0x993, 0xfc003fff}, - {0x994, 0xfc007fff}, - {0xda5, 0xfc00fc00}, - {0x995, 0xfc00ffff}, - {0xda6, 0xfc01fc01}, - {0x996, 0xfc01ffff}, - {0xda7, 0xfc03fc03}, - {0x997, 0xfc03ffff}, - {0xda8, 0xfc07fc07}, - {0x998, 0xfc07ffff}, - {0xda9, 0xfc0ffc0f}, - {0x999, 0xfc0fffff}, - {0xdaa, 0xfc1ffc1f}, - {0x99a, 0xfc1fffff}, - {0xdab, 0xfc3ffc3f}, - {0x99b, 0xfc3fffff}, - {0xdac, 0xfc7ffc7f}, - {0x99c, 0xfc7fffff}, - {0xfb5, 0xfcfcfcfc}, - {0xdad, 0xfcfffcff}, - {0x99d, 0xfcffffff}, - {0xfb6, 0xfdfdfdfd}, - {0xdae, 0xfdfffdff}, - {0x99e, 0xfdffffff}, - {0x9c6, 0xfe000000}, - {0x9c7, 0xfe000001}, - {0x9c8, 0xfe000003}, - {0x9c9, 0xfe000007}, - {0x9ca, 0xfe00000f}, - {0x9cb, 0xfe00001f}, - {0x9cc, 0xfe00003f}, - {0x9cd, 0xfe00007f}, - {0x9ce, 0xfe0000ff}, - {0x9cf, 0xfe0001ff}, - {0x9d0, 0xfe0003ff}, - {0x9d1, 0xfe0007ff}, - {0x9d2, 0xfe000fff}, - {0x9d3, 0xfe001fff}, - {0x9d4, 0xfe003fff}, - {0x9d5, 0xfe007fff}, - {0xde6, 0xfe00fe00}, - {0x9d6, 0xfe00ffff}, - {0xde7, 0xfe01fe01}, - {0x9d7, 0xfe01ffff}, - {0xde8, 0xfe03fe03}, - {0x9d8, 0xfe03ffff}, - {0xde9, 0xfe07fe07}, - {0x9d9, 0xfe07ffff}, - {0xdea, 0xfe0ffe0f}, - {0x9da, 0xfe0fffff}, - {0xdeb, 0xfe1ffe1f}, - {0x9db, 0xfe1fffff}, - {0xdec, 0xfe3ffe3f}, - {0x9dc, 0xfe3fffff}, - {0xded, 0xfe7ffe7f}, - {0x9dd, 0xfe7fffff}, - {0xff6, 0xfefefefe}, - {0xdee, 0xfefffeff}, - {0x9de, 0xfeffffff}, - {0xa07, 0xff000000}, - {0xa08, 0xff000001}, - {0xa09, 0xff000003}, - {0xa0a, 0xff000007}, - {0xa0b, 0xff00000f}, - {0xa0c, 0xff00001f}, - {0xa0d, 0xff00003f}, - {0xa0e, 0xff00007f}, - {0xa0f, 0xff0000ff}, - {0xa10, 0xff0001ff}, - {0xa11, 0xff0003ff}, - {0xa12, 0xff0007ff}, - {0xa13, 0xff000fff}, - {0xa14, 0xff001fff}, - {0xa15, 0xff003fff}, - {0xa16, 0xff007fff}, - {0xe27, 0xff00ff00}, - {0xa17, 0xff00ffff}, - {0xe28, 0xff01ff01}, - {0xa18, 0xff01ffff}, - {0xe29, 0xff03ff03}, - {0xa19, 0xff03ffff}, - {0xe2a, 0xff07ff07}, - {0xa1a, 0xff07ffff}, - {0xe2b, 0xff0fff0f}, - {0xa1b, 0xff0fffff}, - {0xe2c, 0xff1fff1f}, - {0xa1c, 0xff1fffff}, - {0xe2d, 0xff3fff3f}, - {0xa1d, 0xff3fffff}, - {0xe2e, 0xff7fff7f}, - {0xa1e, 0xff7fffff}, - {0xa48, 0xff800000}, - {0xa49, 0xff800001}, - {0xa4a, 0xff800003}, - {0xa4b, 0xff800007}, - {0xa4c, 0xff80000f}, - {0xa4d, 0xff80001f}, - {0xa4e, 0xff80003f}, - {0xa4f, 0xff80007f}, - {0xa50, 0xff8000ff}, - {0xa51, 0xff8001ff}, - {0xa52, 0xff8003ff}, - {0xa53, 0xff8007ff}, - {0xa54, 0xff800fff}, - {0xa55, 0xff801fff}, - {0xa56, 0xff803fff}, - {0xa57, 0xff807fff}, - {0xe68, 0xff80ff80}, - {0xa58, 0xff80ffff}, - {0xe69, 0xff81ff81}, - {0xa59, 0xff81ffff}, - {0xe6a, 0xff83ff83}, - {0xa5a, 0xff83ffff}, - {0xe6b, 0xff87ff87}, - {0xa5b, 0xff87ffff}, - {0xe6c, 0xff8fff8f}, - {0xa5c, 0xff8fffff}, - {0xe6d, 0xff9fff9f}, - {0xa5d, 0xff9fffff}, - {0xe6e, 0xffbfffbf}, - {0xa5e, 0xffbfffff}, - {0xa89, 0xffc00000}, - {0xa8a, 0xffc00001}, - {0xa8b, 0xffc00003}, - {0xa8c, 0xffc00007}, - {0xa8d, 0xffc0000f}, - {0xa8e, 0xffc0001f}, - {0xa8f, 0xffc0003f}, - {0xa90, 0xffc0007f}, - {0xa91, 0xffc000ff}, - {0xa92, 0xffc001ff}, - {0xa93, 0xffc003ff}, - {0xa94, 0xffc007ff}, - {0xa95, 0xffc00fff}, - {0xa96, 0xffc01fff}, - {0xa97, 0xffc03fff}, - {0xa98, 0xffc07fff}, - {0xea9, 0xffc0ffc0}, - {0xa99, 0xffc0ffff}, - {0xeaa, 0xffc1ffc1}, - {0xa9a, 0xffc1ffff}, - {0xeab, 0xffc3ffc3}, - {0xa9b, 0xffc3ffff}, - {0xeac, 0xffc7ffc7}, - {0xa9c, 0xffc7ffff}, - {0xead, 0xffcfffcf}, - {0xa9d, 0xffcfffff}, - {0xeae, 0xffdfffdf}, - {0xa9e, 0xffdfffff}, - {0xaca, 0xffe00000}, - {0xacb, 0xffe00001}, - {0xacc, 0xffe00003}, - {0xacd, 0xffe00007}, - {0xace, 0xffe0000f}, - {0xacf, 0xffe0001f}, - {0xad0, 0xffe0003f}, - {0xad1, 0xffe0007f}, - {0xad2, 0xffe000ff}, - {0xad3, 0xffe001ff}, - {0xad4, 0xffe003ff}, - {0xad5, 0xffe007ff}, - {0xad6, 0xffe00fff}, - {0xad7, 0xffe01fff}, - {0xad8, 0xffe03fff}, - {0xad9, 0xffe07fff}, - {0xeea, 0xffe0ffe0}, - {0xada, 0xffe0ffff}, - {0xeeb, 0xffe1ffe1}, - {0xadb, 0xffe1ffff}, - {0xeec, 0xffe3ffe3}, - {0xadc, 0xffe3ffff}, - {0xeed, 0xffe7ffe7}, - {0xadd, 0xffe7ffff}, - {0xeee, 0xffefffef}, - {0xade, 0xffefffff}, - {0xb0b, 0xfff00000}, - {0xb0c, 0xfff00001}, - {0xb0d, 0xfff00003}, - {0xb0e, 0xfff00007}, - {0xb0f, 0xfff0000f}, - {0xb10, 0xfff0001f}, - {0xb11, 0xfff0003f}, - {0xb12, 0xfff0007f}, - {0xb13, 0xfff000ff}, - {0xb14, 0xfff001ff}, - {0xb15, 0xfff003ff}, - {0xb16, 0xfff007ff}, - {0xb17, 0xfff00fff}, - {0xb18, 0xfff01fff}, - {0xb19, 0xfff03fff}, - {0xb1a, 0xfff07fff}, - {0xf2b, 0xfff0fff0}, - {0xb1b, 0xfff0ffff}, - {0xf2c, 0xfff1fff1}, - {0xb1c, 0xfff1ffff}, - {0xf2d, 0xfff3fff3}, - {0xb1d, 0xfff3ffff}, - {0xf2e, 0xfff7fff7}, - {0xb1e, 0xfff7ffff}, - {0xb4c, 0xfff80000}, - {0xb4d, 0xfff80001}, - {0xb4e, 0xfff80003}, - {0xb4f, 0xfff80007}, - {0xb50, 0xfff8000f}, - {0xb51, 0xfff8001f}, - {0xb52, 0xfff8003f}, - {0xb53, 0xfff8007f}, - {0xb54, 0xfff800ff}, - {0xb55, 0xfff801ff}, - {0xb56, 0xfff803ff}, - {0xb57, 0xfff807ff}, - {0xb58, 0xfff80fff}, - {0xb59, 0xfff81fff}, - {0xb5a, 0xfff83fff}, - {0xb5b, 0xfff87fff}, - {0xf6c, 0xfff8fff8}, - {0xb5c, 0xfff8ffff}, - {0xf6d, 0xfff9fff9}, - {0xb5d, 0xfff9ffff}, - {0xf6e, 0xfffbfffb}, - {0xb5e, 0xfffbffff}, - {0xb8d, 0xfffc0000}, - {0xb8e, 0xfffc0001}, - {0xb8f, 0xfffc0003}, - {0xb90, 0xfffc0007}, - {0xb91, 0xfffc000f}, - {0xb92, 0xfffc001f}, - {0xb93, 0xfffc003f}, - {0xb94, 0xfffc007f}, - {0xb95, 0xfffc00ff}, - {0xb96, 0xfffc01ff}, - {0xb97, 0xfffc03ff}, - {0xb98, 0xfffc07ff}, - {0xb99, 0xfffc0fff}, - {0xb9a, 0xfffc1fff}, - {0xb9b, 0xfffc3fff}, - {0xb9c, 0xfffc7fff}, - {0xfad, 0xfffcfffc}, - {0xb9d, 0xfffcffff}, - {0xfae, 0xfffdfffd}, - {0xb9e, 0xfffdffff}, - {0xbce, 0xfffe0000}, - {0xbcf, 0xfffe0001}, - {0xbd0, 0xfffe0003}, - {0xbd1, 0xfffe0007}, - {0xbd2, 0xfffe000f}, - {0xbd3, 0xfffe001f}, - {0xbd4, 0xfffe003f}, - {0xbd5, 0xfffe007f}, - {0xbd6, 0xfffe00ff}, - {0xbd7, 0xfffe01ff}, - {0xbd8, 0xfffe03ff}, - {0xbd9, 0xfffe07ff}, - {0xbda, 0xfffe0fff}, - {0xbdb, 0xfffe1fff}, - {0xbdc, 0xfffe3fff}, - {0xbdd, 0xfffe7fff}, - {0xfee, 0xfffefffe}, - {0xbde, 0xfffeffff}, - {0xc0f, 0xffff0000}, - {0xc10, 0xffff0001}, - {0xc11, 0xffff0003}, - {0xc12, 0xffff0007}, - {0xc13, 0xffff000f}, - {0xc14, 0xffff001f}, - {0xc15, 0xffff003f}, - {0xc16, 0xffff007f}, - {0xc17, 0xffff00ff}, - {0xc18, 0xffff01ff}, - {0xc19, 0xffff03ff}, - {0xc1a, 0xffff07ff}, - {0xc1b, 0xffff0fff}, - {0xc1c, 0xffff1fff}, - {0xc1d, 0xffff3fff}, - {0xc1e, 0xffff7fff}, - {0xc50, 0xffff8000}, - {0xc51, 0xffff8001}, - {0xc52, 0xffff8003}, - {0xc53, 0xffff8007}, - {0xc54, 0xffff800f}, - {0xc55, 0xffff801f}, - {0xc56, 0xffff803f}, - {0xc57, 0xffff807f}, - {0xc58, 0xffff80ff}, - {0xc59, 0xffff81ff}, - {0xc5a, 0xffff83ff}, - {0xc5b, 0xffff87ff}, - {0xc5c, 0xffff8fff}, - {0xc5d, 0xffff9fff}, - {0xc5e, 0xffffbfff}, - {0xc91, 0xffffc000}, - {0xc92, 0xffffc001}, - {0xc93, 0xffffc003}, - {0xc94, 0xffffc007}, - {0xc95, 0xffffc00f}, - {0xc96, 0xffffc01f}, - {0xc97, 0xffffc03f}, - {0xc98, 0xffffc07f}, - {0xc99, 0xffffc0ff}, - {0xc9a, 0xffffc1ff}, - {0xc9b, 0xffffc3ff}, - {0xc9c, 0xffffc7ff}, - {0xc9d, 0xffffcfff}, - {0xc9e, 0xffffdfff}, - {0xcd2, 0xffffe000}, - {0xcd3, 0xffffe001}, - {0xcd4, 0xffffe003}, - {0xcd5, 0xffffe007}, - {0xcd6, 0xffffe00f}, - {0xcd7, 0xffffe01f}, - {0xcd8, 0xffffe03f}, - {0xcd9, 0xffffe07f}, - {0xcda, 0xffffe0ff}, - {0xcdb, 0xffffe1ff}, - {0xcdc, 0xffffe3ff}, - {0xcdd, 0xffffe7ff}, - {0xcde, 0xffffefff}, - {0xd13, 0xfffff000}, - {0xd14, 0xfffff001}, - {0xd15, 0xfffff003}, - {0xd16, 0xfffff007}, - {0xd17, 0xfffff00f}, - {0xd18, 0xfffff01f}, - {0xd19, 0xfffff03f}, - {0xd1a, 0xfffff07f}, - {0xd1b, 0xfffff0ff}, - {0xd1c, 0xfffff1ff}, - {0xd1d, 0xfffff3ff}, - {0xd1e, 0xfffff7ff}, - {0xd54, 0xfffff800}, - {0xd55, 0xfffff801}, - {0xd56, 0xfffff803}, - {0xd57, 0xfffff807}, - {0xd58, 0xfffff80f}, - {0xd59, 0xfffff81f}, - {0xd5a, 0xfffff83f}, - {0xd5b, 0xfffff87f}, - {0xd5c, 0xfffff8ff}, - {0xd5d, 0xfffff9ff}, - {0xd5e, 0xfffffbff}, - {0xd95, 0xfffffc00}, - {0xd96, 0xfffffc01}, - {0xd97, 0xfffffc03}, - {0xd98, 0xfffffc07}, - {0xd99, 0xfffffc0f}, - {0xd9a, 0xfffffc1f}, - {0xd9b, 0xfffffc3f}, - {0xd9c, 0xfffffc7f}, - {0xd9d, 0xfffffcff}, - {0xd9e, 0xfffffdff}, - {0xdd6, 0xfffffe00}, - {0xdd7, 0xfffffe01}, - {0xdd8, 0xfffffe03}, - {0xdd9, 0xfffffe07}, - {0xdda, 0xfffffe0f}, - {0xddb, 0xfffffe1f}, - {0xddc, 0xfffffe3f}, - {0xddd, 0xfffffe7f}, - {0xdde, 0xfffffeff}, - {0xe17, 0xffffff00}, - {0xe18, 0xffffff01}, - {0xe19, 0xffffff03}, - {0xe1a, 0xffffff07}, - {0xe1b, 0xffffff0f}, - {0xe1c, 0xffffff1f}, - {0xe1d, 0xffffff3f}, - {0xe1e, 0xffffff7f}, - {0xe58, 0xffffff80}, - {0xe59, 0xffffff81}, - {0xe5a, 0xffffff83}, - {0xe5b, 0xffffff87}, - {0xe5c, 0xffffff8f}, - {0xe5d, 0xffffff9f}, - {0xe5e, 0xffffffbf}, - {0xe99, 0xffffffc0}, - {0xe9a, 0xffffffc1}, - {0xe9b, 0xffffffc3}, - {0xe9c, 0xffffffc7}, - {0xe9d, 0xffffffcf}, - {0xe9e, 0xffffffdf}, - {0xeda, 0xffffffe0}, - {0xedb, 0xffffffe1}, - {0xedc, 0xffffffe3}, - {0xedd, 0xffffffe7}, - {0xede, 0xffffffef}, - {0xf1b, 0xfffffff0}, - {0xf1c, 0xfffffff1}, - {0xf1d, 0xfffffff3}, - {0xf1e, 0xfffffff7}, - {0xf5c, 0xfffffff8}, - {0xf5d, 0xfffffff9}, - {0xf5e, 0xfffffffb}, - {0xf9d, 0xfffffffc}, - {0xf9e, 0xfffffffd}, - {0xfde, 0xfffffffe}, +static uint32_t imm_table[][2] = { + { 0x800, 0x00000001}, + { 0xfc0, 0x00000002}, + { 0x801, 0x00000003}, + { 0xf80, 0x00000004}, + { 0xfc1, 0x00000006}, + { 0x802, 0x00000007}, + { 0xf40, 0x00000008}, + { 0xf81, 0x0000000c}, + { 0xfc2, 0x0000000e}, + { 0x803, 0x0000000f}, + { 0xf00, 0x00000010}, + { 0xf41, 0x00000018}, + { 0xf82, 0x0000001c}, + { 0xfc3, 0x0000001e}, + { 0x804, 0x0000001f}, + { 0xec0, 0x00000020}, + { 0xf01, 0x00000030}, + { 0xf42, 0x00000038}, + { 0xf83, 0x0000003c}, + { 0xfc4, 0x0000003e}, + { 0x805, 0x0000003f}, + { 0xe80, 0x00000040}, + { 0xec1, 0x00000060}, + { 0xf02, 0x00000070}, + { 0xf43, 0x00000078}, + { 0xf84, 0x0000007c}, + { 0xfc5, 0x0000007e}, + { 0x806, 0x0000007f}, + { 0xe40, 0x00000080}, + { 0xe81, 0x000000c0}, + { 0xec2, 0x000000e0}, + { 0xf03, 0x000000f0}, + { 0xf44, 0x000000f8}, + { 0xf85, 0x000000fc}, + { 0xfc6, 0x000000fe}, + { 0x807, 0x000000ff}, + { 0xe00, 0x00000100}, + { 0xe41, 0x00000180}, + { 0xe82, 0x000001c0}, + { 0xec3, 0x000001e0}, + { 0xf04, 0x000001f0}, + { 0xf45, 0x000001f8}, + { 0xf86, 0x000001fc}, + { 0xfc7, 0x000001fe}, + { 0x808, 0x000001ff}, + { 0xdc0, 0x00000200}, + { 0xe01, 0x00000300}, + { 0xe42, 0x00000380}, + { 0xe83, 0x000003c0}, + { 0xec4, 0x000003e0}, + { 0xf05, 0x000003f0}, + { 0xf46, 0x000003f8}, + { 0xf87, 0x000003fc}, + { 0xfc8, 0x000003fe}, + { 0x809, 0x000003ff}, + { 0xd80, 0x00000400}, + { 0xdc1, 0x00000600}, + { 0xe02, 0x00000700}, + { 0xe43, 0x00000780}, + { 0xe84, 0x000007c0}, + { 0xec5, 0x000007e0}, + { 0xf06, 0x000007f0}, + { 0xf47, 0x000007f8}, + { 0xf88, 0x000007fc}, + { 0xfc9, 0x000007fe}, + { 0x80a, 0x000007ff}, + { 0xd40, 0x00000800}, + { 0xd81, 0x00000c00}, + { 0xdc2, 0x00000e00}, + { 0xe03, 0x00000f00}, + { 0xe44, 0x00000f80}, + { 0xe85, 0x00000fc0}, + { 0xec6, 0x00000fe0}, + { 0xf07, 0x00000ff0}, + { 0xf48, 0x00000ff8}, + { 0xf89, 0x00000ffc}, + { 0xfca, 0x00000ffe}, + { 0x80b, 0x00000fff}, + { 0xd00, 0x00001000}, + { 0xd41, 0x00001800}, + { 0xd82, 0x00001c00}, + { 0xdc3, 0x00001e00}, + { 0xe04, 0x00001f00}, + { 0xe45, 0x00001f80}, + { 0xe86, 0x00001fc0}, + { 0xec7, 0x00001fe0}, + { 0xf08, 0x00001ff0}, + { 0xf49, 0x00001ff8}, + { 0xf8a, 0x00001ffc}, + { 0xfcb, 0x00001ffe}, + { 0x80c, 0x00001fff}, + { 0xcc0, 0x00002000}, + { 0xd01, 0x00003000}, + { 0xd42, 0x00003800}, + { 0xd83, 0x00003c00}, + { 0xdc4, 0x00003e00}, + { 0xe05, 0x00003f00}, + { 0xe46, 0x00003f80}, + { 0xe87, 0x00003fc0}, + { 0xec8, 0x00003fe0}, + { 0xf09, 0x00003ff0}, + { 0xf4a, 0x00003ff8}, + { 0xf8b, 0x00003ffc}, + { 0xfcc, 0x00003ffe}, + { 0x80d, 0x00003fff}, + { 0xc80, 0x00004000}, + { 0xcc1, 0x00006000}, + { 0xd02, 0x00007000}, + { 0xd43, 0x00007800}, + { 0xd84, 0x00007c00}, + { 0xdc5, 0x00007e00}, + { 0xe06, 0x00007f00}, + { 0xe47, 0x00007f80}, + { 0xe88, 0x00007fc0}, + { 0xec9, 0x00007fe0}, + { 0xf0a, 0x00007ff0}, + { 0xf4b, 0x00007ff8}, + { 0xf8c, 0x00007ffc}, + { 0xfcd, 0x00007ffe}, + { 0x80e, 0x00007fff}, + { 0xc40, 0x00008000}, + { 0xc81, 0x0000c000}, + { 0xcc2, 0x0000e000}, + { 0xd03, 0x0000f000}, + { 0xd44, 0x0000f800}, + { 0xd85, 0x0000fc00}, + { 0xdc6, 0x0000fe00}, + { 0xe07, 0x0000ff00}, + { 0xe48, 0x0000ff80}, + { 0xe89, 0x0000ffc0}, + { 0xeca, 0x0000ffe0}, + { 0xf0b, 0x0000fff0}, + { 0xf4c, 0x0000fff8}, + { 0xf8d, 0x0000fffc}, + { 0xfce, 0x0000fffe}, + { 0x80f, 0x0000ffff}, + { 0xc00, 0x00010000}, + { 0xc20, 0x00010001}, + { 0xc41, 0x00018000}, + { 0xc82, 0x0001c000}, + { 0xcc3, 0x0001e000}, + { 0xd04, 0x0001f000}, + { 0xd45, 0x0001f800}, + { 0xd86, 0x0001fc00}, + { 0xdc7, 0x0001fe00}, + { 0xe08, 0x0001ff00}, + { 0xe49, 0x0001ff80}, + { 0xe8a, 0x0001ffc0}, + { 0xecb, 0x0001ffe0}, + { 0xf0c, 0x0001fff0}, + { 0xf4d, 0x0001fff8}, + { 0xf8e, 0x0001fffc}, + { 0xfcf, 0x0001fffe}, + { 0x810, 0x0001ffff}, + { 0xbc0, 0x00020000}, + { 0xfe0, 0x00020002}, + { 0xc01, 0x00030000}, + { 0xc21, 0x00030003}, + { 0xc42, 0x00038000}, + { 0xc83, 0x0003c000}, + { 0xcc4, 0x0003e000}, + { 0xd05, 0x0003f000}, + { 0xd46, 0x0003f800}, + { 0xd87, 0x0003fc00}, + { 0xdc8, 0x0003fe00}, + { 0xe09, 0x0003ff00}, + { 0xe4a, 0x0003ff80}, + { 0xe8b, 0x0003ffc0}, + { 0xecc, 0x0003ffe0}, + { 0xf0d, 0x0003fff0}, + { 0xf4e, 0x0003fff8}, + { 0xf8f, 0x0003fffc}, + { 0xfd0, 0x0003fffe}, + { 0x811, 0x0003ffff}, + { 0xb80, 0x00040000}, + { 0xfa0, 0x00040004}, + { 0xbc1, 0x00060000}, + { 0xfe1, 0x00060006}, + { 0xc02, 0x00070000}, + { 0xc22, 0x00070007}, + { 0xc43, 0x00078000}, + { 0xc84, 0x0007c000}, + { 0xcc5, 0x0007e000}, + { 0xd06, 0x0007f000}, + { 0xd47, 0x0007f800}, + { 0xd88, 0x0007fc00}, + { 0xdc9, 0x0007fe00}, + { 0xe0a, 0x0007ff00}, + { 0xe4b, 0x0007ff80}, + { 0xe8c, 0x0007ffc0}, + { 0xecd, 0x0007ffe0}, + { 0xf0e, 0x0007fff0}, + { 0xf4f, 0x0007fff8}, + { 0xf90, 0x0007fffc}, + { 0xfd1, 0x0007fffe}, + { 0x812, 0x0007ffff}, + { 0xb40, 0x00080000}, + { 0xf60, 0x00080008}, + { 0xb81, 0x000c0000}, + { 0xfa1, 0x000c000c}, + { 0xbc2, 0x000e0000}, + { 0xfe2, 0x000e000e}, + { 0xc03, 0x000f0000}, + { 0xc23, 0x000f000f}, + { 0xc44, 0x000f8000}, + { 0xc85, 0x000fc000}, + { 0xcc6, 0x000fe000}, + { 0xd07, 0x000ff000}, + { 0xd48, 0x000ff800}, + { 0xd89, 0x000ffc00}, + { 0xdca, 0x000ffe00}, + { 0xe0b, 0x000fff00}, + { 0xe4c, 0x000fff80}, + { 0xe8d, 0x000fffc0}, + { 0xece, 0x000fffe0}, + { 0xf0f, 0x000ffff0}, + { 0xf50, 0x000ffff8}, + { 0xf91, 0x000ffffc}, + { 0xfd2, 0x000ffffe}, + { 0x813, 0x000fffff}, + { 0xb00, 0x00100000}, + { 0xf20, 0x00100010}, + { 0xb41, 0x00180000}, + { 0xf61, 0x00180018}, + { 0xb82, 0x001c0000}, + { 0xfa2, 0x001c001c}, + { 0xbc3, 0x001e0000}, + { 0xfe3, 0x001e001e}, + { 0xc04, 0x001f0000}, + { 0xc24, 0x001f001f}, + { 0xc45, 0x001f8000}, + { 0xc86, 0x001fc000}, + { 0xcc7, 0x001fe000}, + { 0xd08, 0x001ff000}, + { 0xd49, 0x001ff800}, + { 0xd8a, 0x001ffc00}, + { 0xdcb, 0x001ffe00}, + { 0xe0c, 0x001fff00}, + { 0xe4d, 0x001fff80}, + { 0xe8e, 0x001fffc0}, + { 0xecf, 0x001fffe0}, + { 0xf10, 0x001ffff0}, + { 0xf51, 0x001ffff8}, + { 0xf92, 0x001ffffc}, + { 0xfd3, 0x001ffffe}, + { 0x814, 0x001fffff}, + { 0xac0, 0x00200000}, + { 0xee0, 0x00200020}, + { 0xb01, 0x00300000}, + { 0xf21, 0x00300030}, + { 0xb42, 0x00380000}, + { 0xf62, 0x00380038}, + { 0xb83, 0x003c0000}, + { 0xfa3, 0x003c003c}, + { 0xbc4, 0x003e0000}, + { 0xfe4, 0x003e003e}, + { 0xc05, 0x003f0000}, + { 0xc25, 0x003f003f}, + { 0xc46, 0x003f8000}, + { 0xc87, 0x003fc000}, + { 0xcc8, 0x003fe000}, + { 0xd09, 0x003ff000}, + { 0xd4a, 0x003ff800}, + { 0xd8b, 0x003ffc00}, + { 0xdcc, 0x003ffe00}, + { 0xe0d, 0x003fff00}, + { 0xe4e, 0x003fff80}, + { 0xe8f, 0x003fffc0}, + { 0xed0, 0x003fffe0}, + { 0xf11, 0x003ffff0}, + { 0xf52, 0x003ffff8}, + { 0xf93, 0x003ffffc}, + { 0xfd4, 0x003ffffe}, + { 0x815, 0x003fffff}, + { 0xa80, 0x00400000}, + { 0xea0, 0x00400040}, + { 0xac1, 0x00600000}, + { 0xee1, 0x00600060}, + { 0xb02, 0x00700000}, + { 0xf22, 0x00700070}, + { 0xb43, 0x00780000}, + { 0xf63, 0x00780078}, + { 0xb84, 0x007c0000}, + { 0xfa4, 0x007c007c}, + { 0xbc5, 0x007e0000}, + { 0xfe5, 0x007e007e}, + { 0xc06, 0x007f0000}, + { 0xc26, 0x007f007f}, + { 0xc47, 0x007f8000}, + { 0xc88, 0x007fc000}, + { 0xcc9, 0x007fe000}, + { 0xd0a, 0x007ff000}, + { 0xd4b, 0x007ff800}, + { 0xd8c, 0x007ffc00}, + { 0xdcd, 0x007ffe00}, + { 0xe0e, 0x007fff00}, + { 0xe4f, 0x007fff80}, + { 0xe90, 0x007fffc0}, + { 0xed1, 0x007fffe0}, + { 0xf12, 0x007ffff0}, + { 0xf53, 0x007ffff8}, + { 0xf94, 0x007ffffc}, + { 0xfd5, 0x007ffffe}, + { 0x816, 0x007fffff}, + { 0xa40, 0x00800000}, + { 0xe60, 0x00800080}, + { 0xa81, 0x00c00000}, + { 0xea1, 0x00c000c0}, + { 0xac2, 0x00e00000}, + { 0xee2, 0x00e000e0}, + { 0xb03, 0x00f00000}, + { 0xf23, 0x00f000f0}, + { 0xb44, 0x00f80000}, + { 0xf64, 0x00f800f8}, + { 0xb85, 0x00fc0000}, + { 0xfa5, 0x00fc00fc}, + { 0xbc6, 0x00fe0000}, + { 0xfe6, 0x00fe00fe}, + { 0xc07, 0x00ff0000}, + { 0xc27, 0x00ff00ff}, + { 0xc48, 0x00ff8000}, + { 0xc89, 0x00ffc000}, + { 0xcca, 0x00ffe000}, + { 0xd0b, 0x00fff000}, + { 0xd4c, 0x00fff800}, + { 0xd8d, 0x00fffc00}, + { 0xdce, 0x00fffe00}, + { 0xe0f, 0x00ffff00}, + { 0xe50, 0x00ffff80}, + { 0xe91, 0x00ffffc0}, + { 0xed2, 0x00ffffe0}, + { 0xf13, 0x00fffff0}, + { 0xf54, 0x00fffff8}, + { 0xf95, 0x00fffffc}, + { 0xfd6, 0x00fffffe}, + { 0x817, 0x00ffffff}, + { 0xa00, 0x01000000}, + { 0xe20, 0x01000100}, + { 0xe30, 0x01010101}, + { 0xa41, 0x01800000}, + { 0xe61, 0x01800180}, + { 0xa82, 0x01c00000}, + { 0xea2, 0x01c001c0}, + { 0xac3, 0x01e00000}, + { 0xee3, 0x01e001e0}, + { 0xb04, 0x01f00000}, + { 0xf24, 0x01f001f0}, + { 0xb45, 0x01f80000}, + { 0xf65, 0x01f801f8}, + { 0xb86, 0x01fc0000}, + { 0xfa6, 0x01fc01fc}, + { 0xbc7, 0x01fe0000}, + { 0xfe7, 0x01fe01fe}, + { 0xc08, 0x01ff0000}, + { 0xc28, 0x01ff01ff}, + { 0xc49, 0x01ff8000}, + { 0xc8a, 0x01ffc000}, + { 0xccb, 0x01ffe000}, + { 0xd0c, 0x01fff000}, + { 0xd4d, 0x01fff800}, + { 0xd8e, 0x01fffc00}, + { 0xdcf, 0x01fffe00}, + { 0xe10, 0x01ffff00}, + { 0xe51, 0x01ffff80}, + { 0xe92, 0x01ffffc0}, + { 0xed3, 0x01ffffe0}, + { 0xf14, 0x01fffff0}, + { 0xf55, 0x01fffff8}, + { 0xf96, 0x01fffffc}, + { 0xfd7, 0x01fffffe}, + { 0x818, 0x01ffffff}, + { 0x9c0, 0x02000000}, + { 0xde0, 0x02000200}, + { 0xff0, 0x02020202}, + { 0xa01, 0x03000000}, + { 0xe21, 0x03000300}, + { 0xe31, 0x03030303}, + { 0xa42, 0x03800000}, + { 0xe62, 0x03800380}, + { 0xa83, 0x03c00000}, + { 0xea3, 0x03c003c0}, + { 0xac4, 0x03e00000}, + { 0xee4, 0x03e003e0}, + { 0xb05, 0x03f00000}, + { 0xf25, 0x03f003f0}, + { 0xb46, 0x03f80000}, + { 0xf66, 0x03f803f8}, + { 0xb87, 0x03fc0000}, + { 0xfa7, 0x03fc03fc}, + { 0xbc8, 0x03fe0000}, + { 0xfe8, 0x03fe03fe}, + { 0xc09, 0x03ff0000}, + { 0xc29, 0x03ff03ff}, + { 0xc4a, 0x03ff8000}, + { 0xc8b, 0x03ffc000}, + { 0xccc, 0x03ffe000}, + { 0xd0d, 0x03fff000}, + { 0xd4e, 0x03fff800}, + { 0xd8f, 0x03fffc00}, + { 0xdd0, 0x03fffe00}, + { 0xe11, 0x03ffff00}, + { 0xe52, 0x03ffff80}, + { 0xe93, 0x03ffffc0}, + { 0xed4, 0x03ffffe0}, + { 0xf15, 0x03fffff0}, + { 0xf56, 0x03fffff8}, + { 0xf97, 0x03fffffc}, + { 0xfd8, 0x03fffffe}, + { 0x819, 0x03ffffff}, + { 0x980, 0x04000000}, + { 0xda0, 0x04000400}, + { 0xfb0, 0x04040404}, + { 0x9c1, 0x06000000}, + { 0xde1, 0x06000600}, + { 0xff1, 0x06060606}, + { 0xa02, 0x07000000}, + { 0xe22, 0x07000700}, + { 0xe32, 0x07070707}, + { 0xa43, 0x07800000}, + { 0xe63, 0x07800780}, + { 0xa84, 0x07c00000}, + { 0xea4, 0x07c007c0}, + { 0xac5, 0x07e00000}, + { 0xee5, 0x07e007e0}, + { 0xb06, 0x07f00000}, + { 0xf26, 0x07f007f0}, + { 0xb47, 0x07f80000}, + { 0xf67, 0x07f807f8}, + { 0xb88, 0x07fc0000}, + { 0xfa8, 0x07fc07fc}, + { 0xbc9, 0x07fe0000}, + { 0xfe9, 0x07fe07fe}, + { 0xc0a, 0x07ff0000}, + { 0xc2a, 0x07ff07ff}, + { 0xc4b, 0x07ff8000}, + { 0xc8c, 0x07ffc000}, + { 0xccd, 0x07ffe000}, + { 0xd0e, 0x07fff000}, + { 0xd4f, 0x07fff800}, + { 0xd90, 0x07fffc00}, + { 0xdd1, 0x07fffe00}, + { 0xe12, 0x07ffff00}, + { 0xe53, 0x07ffff80}, + { 0xe94, 0x07ffffc0}, + { 0xed5, 0x07ffffe0}, + { 0xf16, 0x07fffff0}, + { 0xf57, 0x07fffff8}, + { 0xf98, 0x07fffffc}, + { 0xfd9, 0x07fffffe}, + { 0x81a, 0x07ffffff}, + { 0x940, 0x08000000}, + { 0xd60, 0x08000800}, + { 0xf70, 0x08080808}, + { 0x981, 0x0c000000}, + { 0xda1, 0x0c000c00}, + { 0xfb1, 0x0c0c0c0c}, + { 0x9c2, 0x0e000000}, + { 0xde2, 0x0e000e00}, + { 0xff2, 0x0e0e0e0e}, + { 0xa03, 0x0f000000}, + { 0xe23, 0x0f000f00}, + { 0xe33, 0x0f0f0f0f}, + { 0xa44, 0x0f800000}, + { 0xe64, 0x0f800f80}, + { 0xa85, 0x0fc00000}, + { 0xea5, 0x0fc00fc0}, + { 0xac6, 0x0fe00000}, + { 0xee6, 0x0fe00fe0}, + { 0xb07, 0x0ff00000}, + { 0xf27, 0x0ff00ff0}, + { 0xb48, 0x0ff80000}, + { 0xf68, 0x0ff80ff8}, + { 0xb89, 0x0ffc0000}, + { 0xfa9, 0x0ffc0ffc}, + { 0xbca, 0x0ffe0000}, + { 0xfea, 0x0ffe0ffe}, + { 0xc0b, 0x0fff0000}, + { 0xc2b, 0x0fff0fff}, + { 0xc4c, 0x0fff8000}, + { 0xc8d, 0x0fffc000}, + { 0xcce, 0x0fffe000}, + { 0xd0f, 0x0ffff000}, + { 0xd50, 0x0ffff800}, + { 0xd91, 0x0ffffc00}, + { 0xdd2, 0x0ffffe00}, + { 0xe13, 0x0fffff00}, + { 0xe54, 0x0fffff80}, + { 0xe95, 0x0fffffc0}, + { 0xed6, 0x0fffffe0}, + { 0xf17, 0x0ffffff0}, + { 0xf58, 0x0ffffff8}, + { 0xf99, 0x0ffffffc}, + { 0xfda, 0x0ffffffe}, + { 0x81b, 0x0fffffff}, + { 0x900, 0x10000000}, + { 0xd20, 0x10001000}, + { 0xf30, 0x10101010}, + { 0xf38, 0x11111111}, + { 0x941, 0x18000000}, + { 0xd61, 0x18001800}, + { 0xf71, 0x18181818}, + { 0x982, 0x1c000000}, + { 0xda2, 0x1c001c00}, + { 0xfb2, 0x1c1c1c1c}, + { 0x9c3, 0x1e000000}, + { 0xde3, 0x1e001e00}, + { 0xff3, 0x1e1e1e1e}, + { 0xa04, 0x1f000000}, + { 0xe24, 0x1f001f00}, + { 0xe34, 0x1f1f1f1f}, + { 0xa45, 0x1f800000}, + { 0xe65, 0x1f801f80}, + { 0xa86, 0x1fc00000}, + { 0xea6, 0x1fc01fc0}, + { 0xac7, 0x1fe00000}, + { 0xee7, 0x1fe01fe0}, + { 0xb08, 0x1ff00000}, + { 0xf28, 0x1ff01ff0}, + { 0xb49, 0x1ff80000}, + { 0xf69, 0x1ff81ff8}, + { 0xb8a, 0x1ffc0000}, + { 0xfaa, 0x1ffc1ffc}, + { 0xbcb, 0x1ffe0000}, + { 0xfeb, 0x1ffe1ffe}, + { 0xc0c, 0x1fff0000}, + { 0xc2c, 0x1fff1fff}, + { 0xc4d, 0x1fff8000}, + { 0xc8e, 0x1fffc000}, + { 0xccf, 0x1fffe000}, + { 0xd10, 0x1ffff000}, + { 0xd51, 0x1ffff800}, + { 0xd92, 0x1ffffc00}, + { 0xdd3, 0x1ffffe00}, + { 0xe14, 0x1fffff00}, + { 0xe55, 0x1fffff80}, + { 0xe96, 0x1fffffc0}, + { 0xed7, 0x1fffffe0}, + { 0xf18, 0x1ffffff0}, + { 0xf59, 0x1ffffff8}, + { 0xf9a, 0x1ffffffc}, + { 0xfdb, 0x1ffffffe}, + { 0x81c, 0x1fffffff}, + { 0x8c0, 0x20000000}, + { 0xce0, 0x20002000}, + { 0xef0, 0x20202020}, + { 0xff8, 0x22222222}, + { 0x901, 0x30000000}, + { 0xd21, 0x30003000}, + { 0xf31, 0x30303030}, + { 0xf39, 0x33333333}, + { 0x942, 0x38000000}, + { 0xd62, 0x38003800}, + { 0xf72, 0x38383838}, + { 0x983, 0x3c000000}, + { 0xda3, 0x3c003c00}, + { 0xfb3, 0x3c3c3c3c}, + { 0x9c4, 0x3e000000}, + { 0xde4, 0x3e003e00}, + { 0xff4, 0x3e3e3e3e}, + { 0xa05, 0x3f000000}, + { 0xe25, 0x3f003f00}, + { 0xe35, 0x3f3f3f3f}, + { 0xa46, 0x3f800000}, + { 0xe66, 0x3f803f80}, + { 0xa87, 0x3fc00000}, + { 0xea7, 0x3fc03fc0}, + { 0xac8, 0x3fe00000}, + { 0xee8, 0x3fe03fe0}, + { 0xb09, 0x3ff00000}, + { 0xf29, 0x3ff03ff0}, + { 0xb4a, 0x3ff80000}, + { 0xf6a, 0x3ff83ff8}, + { 0xb8b, 0x3ffc0000}, + { 0xfab, 0x3ffc3ffc}, + { 0xbcc, 0x3ffe0000}, + { 0xfec, 0x3ffe3ffe}, + { 0xc0d, 0x3fff0000}, + { 0xc2d, 0x3fff3fff}, + { 0xc4e, 0x3fff8000}, + { 0xc8f, 0x3fffc000}, + { 0xcd0, 0x3fffe000}, + { 0xd11, 0x3ffff000}, + { 0xd52, 0x3ffff800}, + { 0xd93, 0x3ffffc00}, + { 0xdd4, 0x3ffffe00}, + { 0xe15, 0x3fffff00}, + { 0xe56, 0x3fffff80}, + { 0xe97, 0x3fffffc0}, + { 0xed8, 0x3fffffe0}, + { 0xf19, 0x3ffffff0}, + { 0xf5a, 0x3ffffff8}, + { 0xf9b, 0x3ffffffc}, + { 0xfdc, 0x3ffffffe}, + { 0x81d, 0x3fffffff}, + { 0x880, 0x40000000}, + { 0xca0, 0x40004000}, + { 0xeb0, 0x40404040}, + { 0xfb8, 0x44444444}, + { 0xfbc, 0x55555555}, + { 0x8c1, 0x60000000}, + { 0xce1, 0x60006000}, + { 0xef1, 0x60606060}, + { 0xff9, 0x66666666}, + { 0x902, 0x70000000}, + { 0xd22, 0x70007000}, + { 0xf32, 0x70707070}, + { 0xf3a, 0x77777777}, + { 0x943, 0x78000000}, + { 0xd63, 0x78007800}, + { 0xf73, 0x78787878}, + { 0x984, 0x7c000000}, + { 0xda4, 0x7c007c00}, + { 0xfb4, 0x7c7c7c7c}, + { 0x9c5, 0x7e000000}, + { 0xde5, 0x7e007e00}, + { 0xff5, 0x7e7e7e7e}, + { 0xa06, 0x7f000000}, + { 0xe26, 0x7f007f00}, + { 0xe36, 0x7f7f7f7f}, + { 0xa47, 0x7f800000}, + { 0xe67, 0x7f807f80}, + { 0xa88, 0x7fc00000}, + { 0xea8, 0x7fc07fc0}, + { 0xac9, 0x7fe00000}, + { 0xee9, 0x7fe07fe0}, + { 0xb0a, 0x7ff00000}, + { 0xf2a, 0x7ff07ff0}, + { 0xb4b, 0x7ff80000}, + { 0xf6b, 0x7ff87ff8}, + { 0xb8c, 0x7ffc0000}, + { 0xfac, 0x7ffc7ffc}, + { 0xbcd, 0x7ffe0000}, + { 0xfed, 0x7ffe7ffe}, + { 0xc0e, 0x7fff0000}, + { 0xc2e, 0x7fff7fff}, + { 0xc4f, 0x7fff8000}, + { 0xc90, 0x7fffc000}, + { 0xcd1, 0x7fffe000}, + { 0xd12, 0x7ffff000}, + { 0xd53, 0x7ffff800}, + { 0xd94, 0x7ffffc00}, + { 0xdd5, 0x7ffffe00}, + { 0xe16, 0x7fffff00}, + { 0xe57, 0x7fffff80}, + { 0xe98, 0x7fffffc0}, + { 0xed9, 0x7fffffe0}, + { 0xf1a, 0x7ffffff0}, + { 0xf5b, 0x7ffffff8}, + { 0xf9c, 0x7ffffffc}, + { 0xfdd, 0x7ffffffe}, + { 0x81e, 0x7fffffff}, + { 0x840, 0x80000000}, + { 0x841, 0x80000001}, + { 0x842, 0x80000003}, + { 0x843, 0x80000007}, + { 0x844, 0x8000000f}, + { 0x845, 0x8000001f}, + { 0x846, 0x8000003f}, + { 0x847, 0x8000007f}, + { 0x848, 0x800000ff}, + { 0x849, 0x800001ff}, + { 0x84a, 0x800003ff}, + { 0x84b, 0x800007ff}, + { 0x84c, 0x80000fff}, + { 0x84d, 0x80001fff}, + { 0x84e, 0x80003fff}, + { 0x84f, 0x80007fff}, + { 0xc60, 0x80008000}, + { 0x850, 0x8000ffff}, + { 0xc61, 0x80018001}, + { 0x851, 0x8001ffff}, + { 0xc62, 0x80038003}, + { 0x852, 0x8003ffff}, + { 0xc63, 0x80078007}, + { 0x853, 0x8007ffff}, + { 0xc64, 0x800f800f}, + { 0x854, 0x800fffff}, + { 0xc65, 0x801f801f}, + { 0x855, 0x801fffff}, + { 0xc66, 0x803f803f}, + { 0x856, 0x803fffff}, + { 0xc67, 0x807f807f}, + { 0x857, 0x807fffff}, + { 0xe70, 0x80808080}, + { 0xc68, 0x80ff80ff}, + { 0x858, 0x80ffffff}, + { 0xe71, 0x81818181}, + { 0xc69, 0x81ff81ff}, + { 0x859, 0x81ffffff}, + { 0xe72, 0x83838383}, + { 0xc6a, 0x83ff83ff}, + { 0x85a, 0x83ffffff}, + { 0xe73, 0x87878787}, + { 0xc6b, 0x87ff87ff}, + { 0x85b, 0x87ffffff}, + { 0xf78, 0x88888888}, + { 0xe74, 0x8f8f8f8f}, + { 0xc6c, 0x8fff8fff}, + { 0x85c, 0x8fffffff}, + { 0xf79, 0x99999999}, + { 0xe75, 0x9f9f9f9f}, + { 0xc6d, 0x9fff9fff}, + { 0x85d, 0x9fffffff}, + { 0xffc, 0xaaaaaaaa}, + { 0xf7a, 0xbbbbbbbb}, + { 0xe76, 0xbfbfbfbf}, + { 0xc6e, 0xbfffbfff}, + { 0x85e, 0xbfffffff}, + { 0x881, 0xc0000000}, + { 0x882, 0xc0000001}, + { 0x883, 0xc0000003}, + { 0x884, 0xc0000007}, + { 0x885, 0xc000000f}, + { 0x886, 0xc000001f}, + { 0x887, 0xc000003f}, + { 0x888, 0xc000007f}, + { 0x889, 0xc00000ff}, + { 0x88a, 0xc00001ff}, + { 0x88b, 0xc00003ff}, + { 0x88c, 0xc00007ff}, + { 0x88d, 0xc0000fff}, + { 0x88e, 0xc0001fff}, + { 0x88f, 0xc0003fff}, + { 0x890, 0xc0007fff}, + { 0xca1, 0xc000c000}, + { 0x891, 0xc000ffff}, + { 0xca2, 0xc001c001}, + { 0x892, 0xc001ffff}, + { 0xca3, 0xc003c003}, + { 0x893, 0xc003ffff}, + { 0xca4, 0xc007c007}, + { 0x894, 0xc007ffff}, + { 0xca5, 0xc00fc00f}, + { 0x895, 0xc00fffff}, + { 0xca6, 0xc01fc01f}, + { 0x896, 0xc01fffff}, + { 0xca7, 0xc03fc03f}, + { 0x897, 0xc03fffff}, + { 0xca8, 0xc07fc07f}, + { 0x898, 0xc07fffff}, + { 0xeb1, 0xc0c0c0c0}, + { 0xca9, 0xc0ffc0ff}, + { 0x899, 0xc0ffffff}, + { 0xeb2, 0xc1c1c1c1}, + { 0xcaa, 0xc1ffc1ff}, + { 0x89a, 0xc1ffffff}, + { 0xeb3, 0xc3c3c3c3}, + { 0xcab, 0xc3ffc3ff}, + { 0x89b, 0xc3ffffff}, + { 0xeb4, 0xc7c7c7c7}, + { 0xcac, 0xc7ffc7ff}, + { 0x89c, 0xc7ffffff}, + { 0xfb9, 0xcccccccc}, + { 0xeb5, 0xcfcfcfcf}, + { 0xcad, 0xcfffcfff}, + { 0x89d, 0xcfffffff}, + { 0xfba, 0xdddddddd}, + { 0xeb6, 0xdfdfdfdf}, + { 0xcae, 0xdfffdfff}, + { 0x89e, 0xdfffffff}, + { 0x8c2, 0xe0000000}, + { 0x8c3, 0xe0000001}, + { 0x8c4, 0xe0000003}, + { 0x8c5, 0xe0000007}, + { 0x8c6, 0xe000000f}, + { 0x8c7, 0xe000001f}, + { 0x8c8, 0xe000003f}, + { 0x8c9, 0xe000007f}, + { 0x8ca, 0xe00000ff}, + { 0x8cb, 0xe00001ff}, + { 0x8cc, 0xe00003ff}, + { 0x8cd, 0xe00007ff}, + { 0x8ce, 0xe0000fff}, + { 0x8cf, 0xe0001fff}, + { 0x8d0, 0xe0003fff}, + { 0x8d1, 0xe0007fff}, + { 0xce2, 0xe000e000}, + { 0x8d2, 0xe000ffff}, + { 0xce3, 0xe001e001}, + { 0x8d3, 0xe001ffff}, + { 0xce4, 0xe003e003}, + { 0x8d4, 0xe003ffff}, + { 0xce5, 0xe007e007}, + { 0x8d5, 0xe007ffff}, + { 0xce6, 0xe00fe00f}, + { 0x8d6, 0xe00fffff}, + { 0xce7, 0xe01fe01f}, + { 0x8d7, 0xe01fffff}, + { 0xce8, 0xe03fe03f}, + { 0x8d8, 0xe03fffff}, + { 0xce9, 0xe07fe07f}, + { 0x8d9, 0xe07fffff}, + { 0xef2, 0xe0e0e0e0}, + { 0xcea, 0xe0ffe0ff}, + { 0x8da, 0xe0ffffff}, + { 0xef3, 0xe1e1e1e1}, + { 0xceb, 0xe1ffe1ff}, + { 0x8db, 0xe1ffffff}, + { 0xef4, 0xe3e3e3e3}, + { 0xcec, 0xe3ffe3ff}, + { 0x8dc, 0xe3ffffff}, + { 0xef5, 0xe7e7e7e7}, + { 0xced, 0xe7ffe7ff}, + { 0x8dd, 0xe7ffffff}, + { 0xffa, 0xeeeeeeee}, + { 0xef6, 0xefefefef}, + { 0xcee, 0xefffefff}, + { 0x8de, 0xefffffff}, + { 0x903, 0xf0000000}, + { 0x904, 0xf0000001}, + { 0x905, 0xf0000003}, + { 0x906, 0xf0000007}, + { 0x907, 0xf000000f}, + { 0x908, 0xf000001f}, + { 0x909, 0xf000003f}, + { 0x90a, 0xf000007f}, + { 0x90b, 0xf00000ff}, + { 0x90c, 0xf00001ff}, + { 0x90d, 0xf00003ff}, + { 0x90e, 0xf00007ff}, + { 0x90f, 0xf0000fff}, + { 0x910, 0xf0001fff}, + { 0x911, 0xf0003fff}, + { 0x912, 0xf0007fff}, + { 0xd23, 0xf000f000}, + { 0x913, 0xf000ffff}, + { 0xd24, 0xf001f001}, + { 0x914, 0xf001ffff}, + { 0xd25, 0xf003f003}, + { 0x915, 0xf003ffff}, + { 0xd26, 0xf007f007}, + { 0x916, 0xf007ffff}, + { 0xd27, 0xf00ff00f}, + { 0x917, 0xf00fffff}, + { 0xd28, 0xf01ff01f}, + { 0x918, 0xf01fffff}, + { 0xd29, 0xf03ff03f}, + { 0x919, 0xf03fffff}, + { 0xd2a, 0xf07ff07f}, + { 0x91a, 0xf07fffff}, + { 0xf33, 0xf0f0f0f0}, + { 0xd2b, 0xf0fff0ff}, + { 0x91b, 0xf0ffffff}, + { 0xf34, 0xf1f1f1f1}, + { 0xd2c, 0xf1fff1ff}, + { 0x91c, 0xf1ffffff}, + { 0xf35, 0xf3f3f3f3}, + { 0xd2d, 0xf3fff3ff}, + { 0x91d, 0xf3ffffff}, + { 0xf36, 0xf7f7f7f7}, + { 0xd2e, 0xf7fff7ff}, + { 0x91e, 0xf7ffffff}, + { 0x944, 0xf8000000}, + { 0x945, 0xf8000001}, + { 0x946, 0xf8000003}, + { 0x947, 0xf8000007}, + { 0x948, 0xf800000f}, + { 0x949, 0xf800001f}, + { 0x94a, 0xf800003f}, + { 0x94b, 0xf800007f}, + { 0x94c, 0xf80000ff}, + { 0x94d, 0xf80001ff}, + { 0x94e, 0xf80003ff}, + { 0x94f, 0xf80007ff}, + { 0x950, 0xf8000fff}, + { 0x951, 0xf8001fff}, + { 0x952, 0xf8003fff}, + { 0x953, 0xf8007fff}, + { 0xd64, 0xf800f800}, + { 0x954, 0xf800ffff}, + { 0xd65, 0xf801f801}, + { 0x955, 0xf801ffff}, + { 0xd66, 0xf803f803}, + { 0x956, 0xf803ffff}, + { 0xd67, 0xf807f807}, + { 0x957, 0xf807ffff}, + { 0xd68, 0xf80ff80f}, + { 0x958, 0xf80fffff}, + { 0xd69, 0xf81ff81f}, + { 0x959, 0xf81fffff}, + { 0xd6a, 0xf83ff83f}, + { 0x95a, 0xf83fffff}, + { 0xd6b, 0xf87ff87f}, + { 0x95b, 0xf87fffff}, + { 0xf74, 0xf8f8f8f8}, + { 0xd6c, 0xf8fff8ff}, + { 0x95c, 0xf8ffffff}, + { 0xf75, 0xf9f9f9f9}, + { 0xd6d, 0xf9fff9ff}, + { 0x95d, 0xf9ffffff}, + { 0xf76, 0xfbfbfbfb}, + { 0xd6e, 0xfbfffbff}, + { 0x95e, 0xfbffffff}, + { 0x985, 0xfc000000}, + { 0x986, 0xfc000001}, + { 0x987, 0xfc000003}, + { 0x988, 0xfc000007}, + { 0x989, 0xfc00000f}, + { 0x98a, 0xfc00001f}, + { 0x98b, 0xfc00003f}, + { 0x98c, 0xfc00007f}, + { 0x98d, 0xfc0000ff}, + { 0x98e, 0xfc0001ff}, + { 0x98f, 0xfc0003ff}, + { 0x990, 0xfc0007ff}, + { 0x991, 0xfc000fff}, + { 0x992, 0xfc001fff}, + { 0x993, 0xfc003fff}, + { 0x994, 0xfc007fff}, + { 0xda5, 0xfc00fc00}, + { 0x995, 0xfc00ffff}, + { 0xda6, 0xfc01fc01}, + { 0x996, 0xfc01ffff}, + { 0xda7, 0xfc03fc03}, + { 0x997, 0xfc03ffff}, + { 0xda8, 0xfc07fc07}, + { 0x998, 0xfc07ffff}, + { 0xda9, 0xfc0ffc0f}, + { 0x999, 0xfc0fffff}, + { 0xdaa, 0xfc1ffc1f}, + { 0x99a, 0xfc1fffff}, + { 0xdab, 0xfc3ffc3f}, + { 0x99b, 0xfc3fffff}, + { 0xdac, 0xfc7ffc7f}, + { 0x99c, 0xfc7fffff}, + { 0xfb5, 0xfcfcfcfc}, + { 0xdad, 0xfcfffcff}, + { 0x99d, 0xfcffffff}, + { 0xfb6, 0xfdfdfdfd}, + { 0xdae, 0xfdfffdff}, + { 0x99e, 0xfdffffff}, + { 0x9c6, 0xfe000000}, + { 0x9c7, 0xfe000001}, + { 0x9c8, 0xfe000003}, + { 0x9c9, 0xfe000007}, + { 0x9ca, 0xfe00000f}, + { 0x9cb, 0xfe00001f}, + { 0x9cc, 0xfe00003f}, + { 0x9cd, 0xfe00007f}, + { 0x9ce, 0xfe0000ff}, + { 0x9cf, 0xfe0001ff}, + { 0x9d0, 0xfe0003ff}, + { 0x9d1, 0xfe0007ff}, + { 0x9d2, 0xfe000fff}, + { 0x9d3, 0xfe001fff}, + { 0x9d4, 0xfe003fff}, + { 0x9d5, 0xfe007fff}, + { 0xde6, 0xfe00fe00}, + { 0x9d6, 0xfe00ffff}, + { 0xde7, 0xfe01fe01}, + { 0x9d7, 0xfe01ffff}, + { 0xde8, 0xfe03fe03}, + { 0x9d8, 0xfe03ffff}, + { 0xde9, 0xfe07fe07}, + { 0x9d9, 0xfe07ffff}, + { 0xdea, 0xfe0ffe0f}, + { 0x9da, 0xfe0fffff}, + { 0xdeb, 0xfe1ffe1f}, + { 0x9db, 0xfe1fffff}, + { 0xdec, 0xfe3ffe3f}, + { 0x9dc, 0xfe3fffff}, + { 0xded, 0xfe7ffe7f}, + { 0x9dd, 0xfe7fffff}, + { 0xff6, 0xfefefefe}, + { 0xdee, 0xfefffeff}, + { 0x9de, 0xfeffffff}, + { 0xa07, 0xff000000}, + { 0xa08, 0xff000001}, + { 0xa09, 0xff000003}, + { 0xa0a, 0xff000007}, + { 0xa0b, 0xff00000f}, + { 0xa0c, 0xff00001f}, + { 0xa0d, 0xff00003f}, + { 0xa0e, 0xff00007f}, + { 0xa0f, 0xff0000ff}, + { 0xa10, 0xff0001ff}, + { 0xa11, 0xff0003ff}, + { 0xa12, 0xff0007ff}, + { 0xa13, 0xff000fff}, + { 0xa14, 0xff001fff}, + { 0xa15, 0xff003fff}, + { 0xa16, 0xff007fff}, + { 0xe27, 0xff00ff00}, + { 0xa17, 0xff00ffff}, + { 0xe28, 0xff01ff01}, + { 0xa18, 0xff01ffff}, + { 0xe29, 0xff03ff03}, + { 0xa19, 0xff03ffff}, + { 0xe2a, 0xff07ff07}, + { 0xa1a, 0xff07ffff}, + { 0xe2b, 0xff0fff0f}, + { 0xa1b, 0xff0fffff}, + { 0xe2c, 0xff1fff1f}, + { 0xa1c, 0xff1fffff}, + { 0xe2d, 0xff3fff3f}, + { 0xa1d, 0xff3fffff}, + { 0xe2e, 0xff7fff7f}, + { 0xa1e, 0xff7fffff}, + { 0xa48, 0xff800000}, + { 0xa49, 0xff800001}, + { 0xa4a, 0xff800003}, + { 0xa4b, 0xff800007}, + { 0xa4c, 0xff80000f}, + { 0xa4d, 0xff80001f}, + { 0xa4e, 0xff80003f}, + { 0xa4f, 0xff80007f}, + { 0xa50, 0xff8000ff}, + { 0xa51, 0xff8001ff}, + { 0xa52, 0xff8003ff}, + { 0xa53, 0xff8007ff}, + { 0xa54, 0xff800fff}, + { 0xa55, 0xff801fff}, + { 0xa56, 0xff803fff}, + { 0xa57, 0xff807fff}, + { 0xe68, 0xff80ff80}, + { 0xa58, 0xff80ffff}, + { 0xe69, 0xff81ff81}, + { 0xa59, 0xff81ffff}, + { 0xe6a, 0xff83ff83}, + { 0xa5a, 0xff83ffff}, + { 0xe6b, 0xff87ff87}, + { 0xa5b, 0xff87ffff}, + { 0xe6c, 0xff8fff8f}, + { 0xa5c, 0xff8fffff}, + { 0xe6d, 0xff9fff9f}, + { 0xa5d, 0xff9fffff}, + { 0xe6e, 0xffbfffbf}, + { 0xa5e, 0xffbfffff}, + { 0xa89, 0xffc00000}, + { 0xa8a, 0xffc00001}, + { 0xa8b, 0xffc00003}, + { 0xa8c, 0xffc00007}, + { 0xa8d, 0xffc0000f}, + { 0xa8e, 0xffc0001f}, + { 0xa8f, 0xffc0003f}, + { 0xa90, 0xffc0007f}, + { 0xa91, 0xffc000ff}, + { 0xa92, 0xffc001ff}, + { 0xa93, 0xffc003ff}, + { 0xa94, 0xffc007ff}, + { 0xa95, 0xffc00fff}, + { 0xa96, 0xffc01fff}, + { 0xa97, 0xffc03fff}, + { 0xa98, 0xffc07fff}, + { 0xea9, 0xffc0ffc0}, + { 0xa99, 0xffc0ffff}, + { 0xeaa, 0xffc1ffc1}, + { 0xa9a, 0xffc1ffff}, + { 0xeab, 0xffc3ffc3}, + { 0xa9b, 0xffc3ffff}, + { 0xeac, 0xffc7ffc7}, + { 0xa9c, 0xffc7ffff}, + { 0xead, 0xffcfffcf}, + { 0xa9d, 0xffcfffff}, + { 0xeae, 0xffdfffdf}, + { 0xa9e, 0xffdfffff}, + { 0xaca, 0xffe00000}, + { 0xacb, 0xffe00001}, + { 0xacc, 0xffe00003}, + { 0xacd, 0xffe00007}, + { 0xace, 0xffe0000f}, + { 0xacf, 0xffe0001f}, + { 0xad0, 0xffe0003f}, + { 0xad1, 0xffe0007f}, + { 0xad2, 0xffe000ff}, + { 0xad3, 0xffe001ff}, + { 0xad4, 0xffe003ff}, + { 0xad5, 0xffe007ff}, + { 0xad6, 0xffe00fff}, + { 0xad7, 0xffe01fff}, + { 0xad8, 0xffe03fff}, + { 0xad9, 0xffe07fff}, + { 0xeea, 0xffe0ffe0}, + { 0xada, 0xffe0ffff}, + { 0xeeb, 0xffe1ffe1}, + { 0xadb, 0xffe1ffff}, + { 0xeec, 0xffe3ffe3}, + { 0xadc, 0xffe3ffff}, + { 0xeed, 0xffe7ffe7}, + { 0xadd, 0xffe7ffff}, + { 0xeee, 0xffefffef}, + { 0xade, 0xffefffff}, + { 0xb0b, 0xfff00000}, + { 0xb0c, 0xfff00001}, + { 0xb0d, 0xfff00003}, + { 0xb0e, 0xfff00007}, + { 0xb0f, 0xfff0000f}, + { 0xb10, 0xfff0001f}, + { 0xb11, 0xfff0003f}, + { 0xb12, 0xfff0007f}, + { 0xb13, 0xfff000ff}, + { 0xb14, 0xfff001ff}, + { 0xb15, 0xfff003ff}, + { 0xb16, 0xfff007ff}, + { 0xb17, 0xfff00fff}, + { 0xb18, 0xfff01fff}, + { 0xb19, 0xfff03fff}, + { 0xb1a, 0xfff07fff}, + { 0xf2b, 0xfff0fff0}, + { 0xb1b, 0xfff0ffff}, + { 0xf2c, 0xfff1fff1}, + { 0xb1c, 0xfff1ffff}, + { 0xf2d, 0xfff3fff3}, + { 0xb1d, 0xfff3ffff}, + { 0xf2e, 0xfff7fff7}, + { 0xb1e, 0xfff7ffff}, + { 0xb4c, 0xfff80000}, + { 0xb4d, 0xfff80001}, + { 0xb4e, 0xfff80003}, + { 0xb4f, 0xfff80007}, + { 0xb50, 0xfff8000f}, + { 0xb51, 0xfff8001f}, + { 0xb52, 0xfff8003f}, + { 0xb53, 0xfff8007f}, + { 0xb54, 0xfff800ff}, + { 0xb55, 0xfff801ff}, + { 0xb56, 0xfff803ff}, + { 0xb57, 0xfff807ff}, + { 0xb58, 0xfff80fff}, + { 0xb59, 0xfff81fff}, + { 0xb5a, 0xfff83fff}, + { 0xb5b, 0xfff87fff}, + { 0xf6c, 0xfff8fff8}, + { 0xb5c, 0xfff8ffff}, + { 0xf6d, 0xfff9fff9}, + { 0xb5d, 0xfff9ffff}, + { 0xf6e, 0xfffbfffb}, + { 0xb5e, 0xfffbffff}, + { 0xb8d, 0xfffc0000}, + { 0xb8e, 0xfffc0001}, + { 0xb8f, 0xfffc0003}, + { 0xb90, 0xfffc0007}, + { 0xb91, 0xfffc000f}, + { 0xb92, 0xfffc001f}, + { 0xb93, 0xfffc003f}, + { 0xb94, 0xfffc007f}, + { 0xb95, 0xfffc00ff}, + { 0xb96, 0xfffc01ff}, + { 0xb97, 0xfffc03ff}, + { 0xb98, 0xfffc07ff}, + { 0xb99, 0xfffc0fff}, + { 0xb9a, 0xfffc1fff}, + { 0xb9b, 0xfffc3fff}, + { 0xb9c, 0xfffc7fff}, + { 0xfad, 0xfffcfffc}, + { 0xb9d, 0xfffcffff}, + { 0xfae, 0xfffdfffd}, + { 0xb9e, 0xfffdffff}, + { 0xbce, 0xfffe0000}, + { 0xbcf, 0xfffe0001}, + { 0xbd0, 0xfffe0003}, + { 0xbd1, 0xfffe0007}, + { 0xbd2, 0xfffe000f}, + { 0xbd3, 0xfffe001f}, + { 0xbd4, 0xfffe003f}, + { 0xbd5, 0xfffe007f}, + { 0xbd6, 0xfffe00ff}, + { 0xbd7, 0xfffe01ff}, + { 0xbd8, 0xfffe03ff}, + { 0xbd9, 0xfffe07ff}, + { 0xbda, 0xfffe0fff}, + { 0xbdb, 0xfffe1fff}, + { 0xbdc, 0xfffe3fff}, + { 0xbdd, 0xfffe7fff}, + { 0xfee, 0xfffefffe}, + { 0xbde, 0xfffeffff}, + { 0xc0f, 0xffff0000}, + { 0xc10, 0xffff0001}, + { 0xc11, 0xffff0003}, + { 0xc12, 0xffff0007}, + { 0xc13, 0xffff000f}, + { 0xc14, 0xffff001f}, + { 0xc15, 0xffff003f}, + { 0xc16, 0xffff007f}, + { 0xc17, 0xffff00ff}, + { 0xc18, 0xffff01ff}, + { 0xc19, 0xffff03ff}, + { 0xc1a, 0xffff07ff}, + { 0xc1b, 0xffff0fff}, + { 0xc1c, 0xffff1fff}, + { 0xc1d, 0xffff3fff}, + { 0xc1e, 0xffff7fff}, + { 0xc50, 0xffff8000}, + { 0xc51, 0xffff8001}, + { 0xc52, 0xffff8003}, + { 0xc53, 0xffff8007}, + { 0xc54, 0xffff800f}, + { 0xc55, 0xffff801f}, + { 0xc56, 0xffff803f}, + { 0xc57, 0xffff807f}, + { 0xc58, 0xffff80ff}, + { 0xc59, 0xffff81ff}, + { 0xc5a, 0xffff83ff}, + { 0xc5b, 0xffff87ff}, + { 0xc5c, 0xffff8fff}, + { 0xc5d, 0xffff9fff}, + { 0xc5e, 0xffffbfff}, + { 0xc91, 0xffffc000}, + { 0xc92, 0xffffc001}, + { 0xc93, 0xffffc003}, + { 0xc94, 0xffffc007}, + { 0xc95, 0xffffc00f}, + { 0xc96, 0xffffc01f}, + { 0xc97, 0xffffc03f}, + { 0xc98, 0xffffc07f}, + { 0xc99, 0xffffc0ff}, + { 0xc9a, 0xffffc1ff}, + { 0xc9b, 0xffffc3ff}, + { 0xc9c, 0xffffc7ff}, + { 0xc9d, 0xffffcfff}, + { 0xc9e, 0xffffdfff}, + { 0xcd2, 0xffffe000}, + { 0xcd3, 0xffffe001}, + { 0xcd4, 0xffffe003}, + { 0xcd5, 0xffffe007}, + { 0xcd6, 0xffffe00f}, + { 0xcd7, 0xffffe01f}, + { 0xcd8, 0xffffe03f}, + { 0xcd9, 0xffffe07f}, + { 0xcda, 0xffffe0ff}, + { 0xcdb, 0xffffe1ff}, + { 0xcdc, 0xffffe3ff}, + { 0xcdd, 0xffffe7ff}, + { 0xcde, 0xffffefff}, + { 0xd13, 0xfffff000}, + { 0xd14, 0xfffff001}, + { 0xd15, 0xfffff003}, + { 0xd16, 0xfffff007}, + { 0xd17, 0xfffff00f}, + { 0xd18, 0xfffff01f}, + { 0xd19, 0xfffff03f}, + { 0xd1a, 0xfffff07f}, + { 0xd1b, 0xfffff0ff}, + { 0xd1c, 0xfffff1ff}, + { 0xd1d, 0xfffff3ff}, + { 0xd1e, 0xfffff7ff}, + { 0xd54, 0xfffff800}, + { 0xd55, 0xfffff801}, + { 0xd56, 0xfffff803}, + { 0xd57, 0xfffff807}, + { 0xd58, 0xfffff80f}, + { 0xd59, 0xfffff81f}, + { 0xd5a, 0xfffff83f}, + { 0xd5b, 0xfffff87f}, + { 0xd5c, 0xfffff8ff}, + { 0xd5d, 0xfffff9ff}, + { 0xd5e, 0xfffffbff}, + { 0xd95, 0xfffffc00}, + { 0xd96, 0xfffffc01}, + { 0xd97, 0xfffffc03}, + { 0xd98, 0xfffffc07}, + { 0xd99, 0xfffffc0f}, + { 0xd9a, 0xfffffc1f}, + { 0xd9b, 0xfffffc3f}, + { 0xd9c, 0xfffffc7f}, + { 0xd9d, 0xfffffcff}, + { 0xd9e, 0xfffffdff}, + { 0xdd6, 0xfffffe00}, + { 0xdd7, 0xfffffe01}, + { 0xdd8, 0xfffffe03}, + { 0xdd9, 0xfffffe07}, + { 0xdda, 0xfffffe0f}, + { 0xddb, 0xfffffe1f}, + { 0xddc, 0xfffffe3f}, + { 0xddd, 0xfffffe7f}, + { 0xdde, 0xfffffeff}, + { 0xe17, 0xffffff00}, + { 0xe18, 0xffffff01}, + { 0xe19, 0xffffff03}, + { 0xe1a, 0xffffff07}, + { 0xe1b, 0xffffff0f}, + { 0xe1c, 0xffffff1f}, + { 0xe1d, 0xffffff3f}, + { 0xe1e, 0xffffff7f}, + { 0xe58, 0xffffff80}, + { 0xe59, 0xffffff81}, + { 0xe5a, 0xffffff83}, + { 0xe5b, 0xffffff87}, + { 0xe5c, 0xffffff8f}, + { 0xe5d, 0xffffff9f}, + { 0xe5e, 0xffffffbf}, + { 0xe99, 0xffffffc0}, + { 0xe9a, 0xffffffc1}, + { 0xe9b, 0xffffffc3}, + { 0xe9c, 0xffffffc7}, + { 0xe9d, 0xffffffcf}, + { 0xe9e, 0xffffffdf}, + { 0xeda, 0xffffffe0}, + { 0xedb, 0xffffffe1}, + { 0xedc, 0xffffffe3}, + { 0xedd, 0xffffffe7}, + { 0xede, 0xffffffef}, + { 0xf1b, 0xfffffff0}, + { 0xf1c, 0xfffffff1}, + { 0xf1d, 0xfffffff3}, + { 0xf1e, 0xfffffff7}, + { 0xf5c, 0xfffffff8}, + { 0xf5d, 0xfffffff9}, + { 0xf5e, 0xfffffffb}, + { 0xf9d, 0xfffffffc}, + { 0xf9e, 0xfffffffd}, + { 0xfde, 0xfffffffe}, }; -uint32_t host_arm64_find_imm(uint32_t data) +uint32_t +host_arm64_find_imm(uint32_t data) { - int l = 0, r = IMM_NR - 1; + int l = 0; + int r = IMM_NR - 1; - while (l <= r) - { - int m = (l + r) >> 1; + while (l <= r) { + int m = (l + r) >> 1; - if (imm_table[m][1] < data) - l = m+1; - else if (imm_table[m][1] > data) - r = m-1; - else - return imm_table[m][0]; - } - return 0; + if (imm_table[m][1] < data) + l = m + 1; + else if (imm_table[m][1] > data) + r = m - 1; + else + return imm_table[m][0]; + } + return 0; } diff --git a/src/codegen_new/codegen_backend_arm64_ops.c b/src/codegen_new/codegen_backend_arm64_ops.c index a33062299..915cae93d 100644 --- a/src/codegen_new/codegen_backend_arm64_ops.c +++ b/src/codegen_new/codegen_backend_arm64_ops.c @@ -1,1386 +1,1518 @@ #if defined __aarch64__ || defined _M_ARM64 -#include -#include <86box/86box.h> -#include "cpu.h" -#include <86box/mem.h> +# include +# include +# include <86box/86box.h> +# include "cpu.h" +# include <86box/mem.h> +# include <86box/plat_unused.h> -#include "codegen.h" -#include "codegen_allocator.h" -#include "codegen_backend.h" -#include "codegen_backend_arm64_defs.h" -#include "codegen_backend_arm64_ops.h" +# include "codegen.h" +# include "codegen_allocator.h" +# include "codegen_backend.h" +# include "codegen_backend_arm64_defs.h" +# include "codegen_backend_arm64_ops.h" +# define Rt(x) (x) +# define Rd(x) (x) +# define Rn(x) ((x) << 5) +# define Rt2(x) ((x) << 10) +# define Rm(x) ((x) << 16) -#define Rt(x) (x) -#define Rd(x) (x) -#define Rn(x) ((x) << 5) -#define Rt2(x) ((x) << 10) -#define Rm(x) ((x) << 16) +# define shift_imm6(x) ((x) << 10) -#define shift_imm6(x) ((x) << 10) +# define DATA_OFFSET_UP (1 << 23) +# define DATA_OFFSET_DOWN (0 << 23) -#define DATA_OFFSET_UP (1 << 23) -#define DATA_OFFSET_DOWN (0 << 23) +# define COND_EQ (0x0) +# define COND_NE (0x1) +# define COND_CS (0x2) +# define COND_CC (0x3) +# define COND_MI (0x4) +# define COND_PL (0x5) +# define COND_VS (0x6) +# define COND_VC (0x7) +# define COND_HI (0x8) +# define COND_LS (0x9) +# define COND_GE (0xa) +# define COND_LT (0xb) +# define COND_GT (0xc) +# define COND_LE (0xd) -#define COND_EQ (0x0) -#define COND_NE (0x1) -#define COND_CS (0x2) -#define COND_CC (0x3) -#define COND_MI (0x4) -#define COND_PL (0x5) -#define COND_VS (0x6) -#define COND_VC (0x7) -#define COND_HI (0x8) -#define COND_LS (0x9) -#define COND_GE (0xa) -#define COND_LT (0xb) -#define COND_GT (0xc) -#define COND_LE (0xd) +# define CSEL_COND(cond) ((cond) << 12) -#define CSEL_COND(cond) ((cond) << 12) +# define OPCODE_SHIFT 24 +# define OPCODE_ADD_IMM (0x11 << OPCODE_SHIFT) +# define OPCODE_ADDX_IMM (0x91 << OPCODE_SHIFT) +# define OPCODE_ADR (0x10 << OPCODE_SHIFT) +# define OPCODE_B (0x14 << OPCODE_SHIFT) +# define OPCODE_BCOND (0x54 << OPCODE_SHIFT) +# define OPCODE_CBNZ (0xb5 << OPCODE_SHIFT) +# define OPCODE_CBZ (0xb4 << OPCODE_SHIFT) +# define OPCODE_CMN_IMM (0x31 << OPCODE_SHIFT) +# define OPCODE_CMNX_IMM (0xb1 << OPCODE_SHIFT) +# define OPCODE_CMP_IMM (0x71 << OPCODE_SHIFT) +# define OPCODE_CMPX_IMM (0xf1 << OPCODE_SHIFT) +# define OPCODE_SUB_IMM (0x51 << OPCODE_SHIFT) +# define OPCODE_SUBX_IMM (0xd1 << OPCODE_SHIFT) +# define OPCODE_TBNZ (0x37 << OPCODE_SHIFT) +# define OPCODE_TBZ (0x36 << OPCODE_SHIFT) -#define OPCODE_SHIFT 24 -#define OPCODE_ADD_IMM (0x11 << OPCODE_SHIFT) -#define OPCODE_ADDX_IMM (0x91 << OPCODE_SHIFT) -#define OPCODE_ADR (0x10 << OPCODE_SHIFT) -#define OPCODE_B (0x14 << OPCODE_SHIFT) -#define OPCODE_BCOND (0x54 << OPCODE_SHIFT) -#define OPCODE_CBNZ (0xb5 << OPCODE_SHIFT) -#define OPCODE_CBZ (0xb4 << OPCODE_SHIFT) -#define OPCODE_CMN_IMM (0x31 << OPCODE_SHIFT) -#define OPCODE_CMNX_IMM (0xb1 << OPCODE_SHIFT) -#define OPCODE_CMP_IMM (0x71 << OPCODE_SHIFT) -#define OPCODE_CMPX_IMM (0xf1 << OPCODE_SHIFT) -#define OPCODE_SUB_IMM (0x51 << OPCODE_SHIFT) -#define OPCODE_SUBX_IMM (0xd1 << OPCODE_SHIFT) -#define OPCODE_TBNZ (0x37 << OPCODE_SHIFT) -#define OPCODE_TBZ (0x36 << OPCODE_SHIFT) +# define OPCODE_AND_IMM (0x024 << 23) +# define OPCODE_ANDS_IMM (0x0e4 << 23) +# define OPCODE_EOR_IMM (0x0a4 << 23) +# define OPCODE_MOVK_W (0x0e5 << 23) +# define OPCODE_MOVK_X (0x1e5 << 23) +# define OPCODE_MOVZ_W (0x0a5 << 23) +# define OPCODE_MOVZ_X (0x1a5 << 23) +# define OPCODE_ORR_IMM (0x064 << 23) -#define OPCODE_AND_IMM (0x024 << 23) -#define OPCODE_ANDS_IMM (0x0e4 << 23) -#define OPCODE_EOR_IMM (0x0a4 << 23) -#define OPCODE_MOVK_W (0x0e5 << 23) -#define OPCODE_MOVK_X (0x1e5 << 23) -#define OPCODE_MOVZ_W (0x0a5 << 23) -#define OPCODE_MOVZ_X (0x1a5 << 23) -#define OPCODE_ORR_IMM (0x064 << 23) +# define OPCODE_BFI (0x0cc << 22) +# define OPCODE_LDR_IMM_W (0x2e5 << 22) +# define OPCODE_LDR_IMM_X (0x3e5 << 22) +# define OPCODE_LDR_IMM_F64 (0x3f5 << 22) +# define OPCODE_LDRB_IMM_W (0x0e5 << 22) +# define OPCODE_LDRH_IMM (0x1e5 << 22) +# define OPCODE_LDP_POSTIDX_X (0x2a3 << 22) +# define OPCODE_SBFX (0x04c << 22) +# define OPCODE_STP_PREIDX_X (0x2a6 << 22) +# define OPCODE_STR_IMM_W (0x2e4 << 22) +# define OPCODE_STR_IMM_Q (0x3e4 << 22) +# define OPCODE_STR_IMM_F64 (0x3f4 << 22) +# define OPCODE_STRB_IMM (0x0e4 << 22) +# define OPCODE_STRH_IMM (0x1e4 << 22) +# define OPCODE_UBFX (0x14c << 22) -#define OPCODE_BFI (0x0cc << 22) -#define OPCODE_LDR_IMM_W (0x2e5 << 22) -#define OPCODE_LDR_IMM_X (0x3e5 << 22) -#define OPCODE_LDR_IMM_F64 (0x3f5 << 22) -#define OPCODE_LDRB_IMM_W (0x0e5 << 22) -#define OPCODE_LDRH_IMM (0x1e5 << 22) -#define OPCODE_LDP_POSTIDX_X (0x2a3 << 22) -#define OPCODE_SBFX (0x04c << 22) -#define OPCODE_STP_PREIDX_X (0x2a6 << 22) -#define OPCODE_STR_IMM_W (0x2e4 << 22) -#define OPCODE_STR_IMM_Q (0x3e4 << 22) -#define OPCODE_STR_IMM_F64 (0x3f4 << 22) -#define OPCODE_STRB_IMM (0x0e4 << 22) -#define OPCODE_STRH_IMM (0x1e4 << 22) -#define OPCODE_UBFX (0x14c << 22) +# define OPCODE_ADD_LSL (0x058 << 21) +# define OPCODE_ADD_LSR (0x05a << 21) +# define OPCODE_ADDX_LSL (0x458 << 21) +# define OPCODE_AND_ASR (0x054 << 21) +# define OPCODE_AND_LSL (0x050 << 21) +# define OPCODE_AND_ROR (0x056 << 21) +# define OPCODE_ANDS_LSL (0x350 << 21) +# define OPCODE_CMP_LSL (0x358 << 21) +# define OPCODE_CSEL (0x0d4 << 21) +# define OPCODE_EOR_LSL (0x250 << 21) +# define OPCODE_ORR_ASR (0x154 << 21) +# define OPCODE_ORR_LSL (0x150 << 21) +# define OPCODE_ORR_LSR (0x152 << 21) +# define OPCODE_ORR_ROR (0x156 << 21) +# define OPCODE_ORRX_LSL (0x550 << 21) +# define OPCODE_SUB_LSL (0x258 << 21) +# define OPCODE_SUB_LSR (0x25a << 21) +# define OPCODE_SUBX_LSL (0x658 << 21) -#define OPCODE_ADD_LSL (0x058 << 21) -#define OPCODE_ADD_LSR (0x05a << 21) -#define OPCODE_ADDX_LSL (0x458 << 21) -#define OPCODE_AND_ASR (0x054 << 21) -#define OPCODE_AND_LSL (0x050 << 21) -#define OPCODE_AND_ROR (0x056 << 21) -#define OPCODE_ANDS_LSL (0x350 << 21) -#define OPCODE_CMP_LSL (0x358 << 21) -#define OPCODE_CSEL (0x0d4 << 21) -#define OPCODE_EOR_LSL (0x250 << 21) -#define OPCODE_ORR_ASR (0x154 << 21) -#define OPCODE_ORR_LSL (0x150 << 21) -#define OPCODE_ORR_LSR (0x152 << 21) -#define OPCODE_ORR_ROR (0x156 << 21) -#define OPCODE_ORRX_LSL (0x550 << 21) -#define OPCODE_SUB_LSL (0x258 << 21) -#define OPCODE_SUB_LSR (0x25a << 21) -#define OPCODE_SUBX_LSL (0x658 << 21) +# define OPCODE_ADD_V8B (0x0e208400) +# define OPCODE_ADD_V4H (0x0e608400) +# define OPCODE_ADD_V2S (0x0ea08400) +# define OPCODE_ADDP_V4S (0x4ea0bc00) +# define OPCODE_AND_V (0x0e201c00) +# define OPCODE_ASR (0x1ac02800) +# define OPCODE_BIC_V (0x0e601c00) +# define OPCODE_BLR (0xd63f0000) +# define OPCODE_BR (0xd61f0000) +# define OPCODE_CMEQ_V8B (0x2e208c00) +# define OPCODE_CMEQ_V4H (0x2e608c00) +# define OPCODE_CMEQ_V2S (0x2ea08c00) +# define OPCODE_CMGT_V8B (0x0e203400) +# define OPCODE_CMGT_V4H (0x0e603400) +# define OPCODE_CMGT_V2S (0x0ea03400) +# define OPCODE_DUP_V2S (0x0e040400) +# define OPCODE_EOR_V (0x2e201c00) +# define OPCODE_FABS_D (0x1e60c000) +# define OPCODE_FADD_D (0x1e602800) +# define OPCODE_FADD_V2S (0x0e20d400) +# define OPCODE_FCMEQ_V2S (0x0e20e400) +# define OPCODE_FCMGE_V2S (0x2e20e400) +# define OPCODE_FCMGT_V2S (0x2ea0e400) +# define OPCODE_FCMP_D (0x1e602000) +# define OPCODE_FCVT_D_S (0x1e22c000) +# define OPCODE_FCVT_S_D (0x1e624000) +# define OPCODE_FCVTMS_W_D (0x1e700000) +# define OPCODE_FCVTMS_X_D (0x9e700000) +# define OPCODE_FCVTNS_W_D (0x1e600000) +# define OPCODE_FCVTNS_X_D (0x9e600000) +# define OPCODE_FCVTPS_W_D (0x1e680000) +# define OPCODE_FCVTPS_X_D (0x9e680000) +# define OPCODE_FCVTZS_W_D (0x1e780000) +# define OPCODE_FCVTZS_X_D (0x9e780000) +# define OPCODE_FCVTZS_V2S (0x0ea1b800) +# define OPCODE_FDIV_D (0x1e601800) +# define OPCODE_FDIV_S (0x1e201800) +# define OPCODE_FMAX_V2S (0x0e20f400) +# define OPCODE_FMIN_V2S (0x0ea0f400) +# define OPCODE_FMOV_D_D (0x1e604000) +# define OPCODE_FMOV_D_Q (0x9e670000) +# define OPCODE_FMOV_Q_D (0x9e660000) +# define OPCODE_FMOV_S_W (0x1e270000) +# define OPCODE_FMOV_W_S (0x1e260000) +# define OPCODE_FMOV_S_ONE (0x1e2e1000) +# define OPCODE_FMUL_D (0x1e600800) +# define OPCODE_FMUL_V2S (0x2e20dc00) +# define OPCODE_FNEG_D (0x1e614000) +# define OPCODE_FRINTX_D (0x1e674000) +# define OPCODE_FSQRT_D (0x1e61c000) +# define OPCODE_FSQRT_S (0x1e21c000) +# define OPCODE_FSUB_D (0x1e603800) +# define OPCODE_FSUB_V2S (0x0ea0d400) +# define OPCODE_LDR_REG (0xb8606800) +# define OPCODE_LDRX_REG (0xf8606800) +# define OPCODE_LDRB_REG (0x38606800) +# define OPCODE_LDRH_REG (0x78606800) +# define OPCODE_LDRX_REG_LSL3 (0xf8607800) +# define OPCODE_LDR_REG_F32 (0xbc606800) +# define OPCODE_LDR_REG_F64 (0xfc606800) +# define OPCODE_LDR_REG_F64_S (0xfc607800) +# define OPCODE_LSL (0x1ac02000) +# define OPCODE_LSR (0x1ac02400) +# define OPCODE_MSR_FPCR (0xd51b4400) +# define OPCODE_MUL_V4H (0x0e609c00) +# define OPCODE_NOP (0xd503201f) +# define OPCODE_ORR_V (0x0ea01c00) +# define OPCODE_RET (0xd65f0000) +# define OPCODE_ROR (0x1ac02c00) +# define OPCODE_SADDLP_V2S_4H (0x0e602800) +# define OPCODE_SCVTF_D_Q (0x9e620000) +# define OPCODE_SCVTF_D_W (0x1e620000) +# define OPCODE_SCVTF_V2S (0x0e21d800) +# define OPCODE_SQADD_V8B (0x0e200c00) +# define OPCODE_SQADD_V4H (0x0e600c00) +# define OPCODE_SQSUB_V8B (0x0e202c00) +# define OPCODE_SQSUB_V4H (0x0e602c00) +# define OPCODE_SQXTN_V8B_8H (0x0e214800) +# define OPCODE_SQXTN_V4H_4S (0x0e614800) +# define OPCODE_SHL_VD (0x0f005400) +# define OPCODE_SHL_VQ (0x4f005400) +# define OPCODE_SHRN (0x0f008400) +# define OPCODE_SMULL_V4S_4H (0x0e60c000) +# define OPCODE_SSHR_VD (0x0f000400) +# define OPCODE_SSHR_VQ (0x4f000400) +# define OPCODE_STR_REG (0xb8206800) +# define OPCODE_STRB_REG (0x38206800) +# define OPCODE_STRH_REG (0x78206800) +# define OPCODE_STR_REG_F32 (0xbc206800) +# define OPCODE_STR_REG_F64 (0xfc206800) +# define OPCODE_STR_REG_F64_S (0xfc207800) +# define OPCODE_SUB_V8B (0x2e208400) +# define OPCODE_SUB_V4H (0x2e608400) +# define OPCODE_SUB_V2S (0x2ea08400) +# define OPCODE_UQADD_V8B (0x2e200c00) +# define OPCODE_UQADD_V4H (0x2e600c00) +# define OPCODE_UQSUB_V8B (0x2e202c00) +# define OPCODE_UQSUB_V4H (0x2e602c00) +# define OPCODE_UQXTN_V8B_8H (0x2e214800) +# define OPCODE_UQXTN_V4H_4S (0x2e614800) +# define OPCODE_USHR_VD (0x2f000400) +# define OPCODE_USHR_VQ (0x6f000400) +# define OPCODE_ZIP1_V8B (0x0e003800) +# define OPCODE_ZIP1_V4H (0x0e403800) +# define OPCODE_ZIP1_V2S (0x0e803800) +# define OPCODE_ZIP2_V8B (0x0e007800) +# define OPCODE_ZIP2_V4H (0x0e407800) +# define OPCODE_ZIP2_V2S (0x0e807800) -#define OPCODE_ADD_V8B (0x0e208400) -#define OPCODE_ADD_V4H (0x0e608400) -#define OPCODE_ADD_V2S (0x0ea08400) -#define OPCODE_ADDP_V4S (0x4ea0bc00) -#define OPCODE_AND_V (0x0e201c00) -#define OPCODE_ASR (0x1ac02800) -#define OPCODE_BIC_V (0x0e601c00) -#define OPCODE_BLR (0xd63f0000) -#define OPCODE_BR (0xd61f0000) -#define OPCODE_CMEQ_V8B (0x2e208c00) -#define OPCODE_CMEQ_V4H (0x2e608c00) -#define OPCODE_CMEQ_V2S (0x2ea08c00) -#define OPCODE_CMGT_V8B (0x0e203400) -#define OPCODE_CMGT_V4H (0x0e603400) -#define OPCODE_CMGT_V2S (0x0ea03400) -#define OPCODE_DUP_V2S (0x0e040400) -#define OPCODE_EOR_V (0x2e201c00) -#define OPCODE_FABS_D (0x1e60c000) -#define OPCODE_FADD_D (0x1e602800) -#define OPCODE_FADD_V2S (0x0e20d400) -#define OPCODE_FCMEQ_V2S (0x0e20e400) -#define OPCODE_FCMGE_V2S (0x2e20e400) -#define OPCODE_FCMGT_V2S (0x2ea0e400) -#define OPCODE_FCMP_D (0x1e602000) -#define OPCODE_FCVT_D_S (0x1e22c000) -#define OPCODE_FCVT_S_D (0x1e624000) -#define OPCODE_FCVTMS_W_D (0x1e700000) -#define OPCODE_FCVTMS_X_D (0x9e700000) -#define OPCODE_FCVTNS_W_D (0x1e600000) -#define OPCODE_FCVTNS_X_D (0x9e600000) -#define OPCODE_FCVTPS_W_D (0x1e680000) -#define OPCODE_FCVTPS_X_D (0x9e680000) -#define OPCODE_FCVTZS_W_D (0x1e780000) -#define OPCODE_FCVTZS_X_D (0x9e780000) -#define OPCODE_FCVTZS_V2S (0x0ea1b800) -#define OPCODE_FDIV_D (0x1e601800) -#define OPCODE_FDIV_S (0x1e201800) -#define OPCODE_FMAX_V2S (0x0e20f400) -#define OPCODE_FMIN_V2S (0x0ea0f400) -#define OPCODE_FMOV_D_D (0x1e604000) -#define OPCODE_FMOV_D_Q (0x9e670000) -#define OPCODE_FMOV_Q_D (0x9e660000) -#define OPCODE_FMOV_S_W (0x1e270000) -#define OPCODE_FMOV_W_S (0x1e260000) -#define OPCODE_FMOV_S_ONE (0x1e2e1000) -#define OPCODE_FMUL_D (0x1e600800) -#define OPCODE_FMUL_V2S (0x2e20dc00) -#define OPCODE_FNEG_D (0x1e614000) -#define OPCODE_FRINTX_D (0x1e674000) -#define OPCODE_FSQRT_D (0x1e61c000) -#define OPCODE_FSQRT_S (0x1e21c000) -#define OPCODE_FSUB_D (0x1e603800) -#define OPCODE_FSUB_V2S (0x0ea0d400) -#define OPCODE_LDR_REG (0xb8606800) -#define OPCODE_LDRX_REG (0xf8606800) -#define OPCODE_LDRB_REG (0x38606800) -#define OPCODE_LDRH_REG (0x78606800) -#define OPCODE_LDRX_REG_LSL3 (0xf8607800) -#define OPCODE_LDR_REG_F32 (0xbc606800) -#define OPCODE_LDR_REG_F64 (0xfc606800) -#define OPCODE_LDR_REG_F64_S (0xfc607800) -#define OPCODE_LSL (0x1ac02000) -#define OPCODE_LSR (0x1ac02400) -#define OPCODE_MSR_FPCR (0xd51b4400) -#define OPCODE_MUL_V4H (0x0e609c00) -#define OPCODE_NOP (0xd503201f) -#define OPCODE_ORR_V (0x0ea01c00) -#define OPCODE_RET (0xd65f0000) -#define OPCODE_ROR (0x1ac02c00) -#define OPCODE_SADDLP_V2S_4H (0x0e602800) -#define OPCODE_SCVTF_D_Q (0x9e620000) -#define OPCODE_SCVTF_D_W (0x1e620000) -#define OPCODE_SCVTF_V2S (0x0e21d800) -#define OPCODE_SQADD_V8B (0x0e200c00) -#define OPCODE_SQADD_V4H (0x0e600c00) -#define OPCODE_SQSUB_V8B (0x0e202c00) -#define OPCODE_SQSUB_V4H (0x0e602c00) -#define OPCODE_SQXTN_V8B_8H (0x0e214800) -#define OPCODE_SQXTN_V4H_4S (0x0e614800) -#define OPCODE_SHL_VD (0x0f005400) -#define OPCODE_SHL_VQ (0x4f005400) -#define OPCODE_SHRN (0x0f008400) -#define OPCODE_SMULL_V4S_4H (0x0e60c000) -#define OPCODE_SSHR_VD (0x0f000400) -#define OPCODE_SSHR_VQ (0x4f000400) -#define OPCODE_STR_REG (0xb8206800) -#define OPCODE_STRB_REG (0x38206800) -#define OPCODE_STRH_REG (0x78206800) -#define OPCODE_STR_REG_F32 (0xbc206800) -#define OPCODE_STR_REG_F64 (0xfc206800) -#define OPCODE_STR_REG_F64_S (0xfc207800) -#define OPCODE_SUB_V8B (0x2e208400) -#define OPCODE_SUB_V4H (0x2e608400) -#define OPCODE_SUB_V2S (0x2ea08400) -#define OPCODE_UQADD_V8B (0x2e200c00) -#define OPCODE_UQADD_V4H (0x2e600c00) -#define OPCODE_UQSUB_V8B (0x2e202c00) -#define OPCODE_UQSUB_V4H (0x2e602c00) -#define OPCODE_UQXTN_V8B_8H (0x2e214800) -#define OPCODE_UQXTN_V4H_4S (0x2e614800) -#define OPCODE_USHR_VD (0x2f000400) -#define OPCODE_USHR_VQ (0x6f000400) -#define OPCODE_ZIP1_V8B (0x0e003800) -#define OPCODE_ZIP1_V4H (0x0e403800) -#define OPCODE_ZIP1_V2S (0x0e803800) -#define OPCODE_ZIP2_V8B (0x0e007800) -#define OPCODE_ZIP2_V4H (0x0e407800) -#define OPCODE_ZIP2_V2S (0x0e807800) +# define DATPROC_SHIFT(sh) (sh << 10) +# define DATPROC_IMM_SHIFT(sh) (sh << 22) +# define MOV_WIDE_HW(hw) (hw << 21) -#define DATPROC_SHIFT(sh) (sh << 10) -#define DATPROC_IMM_SHIFT(sh) (sh << 22) -#define MOV_WIDE_HW(hw) (hw << 21) +# define IMM7_X(imm_data) (((imm_data >> 3) & 0x7f) << 15) +# define IMM12(imm_data) ((imm_data) << 10) +# define IMM16(imm_data) ((imm_data) << 5) -#define IMM7_X(imm_data) (((imm_data >> 3) & 0x7f) << 15) -#define IMM12(imm_data) ((imm_data) << 10) -#define IMM16(imm_data) ((imm_data) << 5) +# define IMMN(immn) ((immn) << 22) +# define IMMR(immr) ((immr) << 16) +# define IMMS(imms) ((imms) << 10) -#define IMMN(immn) ((immn) << 22) -#define IMMR(immr) ((immr) << 16) -#define IMMS(imms) ((imms) << 10) +# define IMM_LOGICAL(imm) ((imm) << 10) -#define IMM_LOGICAL(imm) ((imm) << 10) +# define BIT_TBxZ(bit) ((((bit) &0x1f) << 19) | (((bit) &0x20) ? (1 << 31) : 0)) -#define BIT_TBxZ(bit) ((((bit) & 0x1f) << 19) | (((bit) & 0x20) ? (1 << 31) : 0)) +# define OFFSET14(offset) (((offset >> 2) << 5) & 0x0007ffe0) +# define OFFSET19(offset) (((offset >> 2) << 5) & 0x00ffffe0) +# define OFFSET20(offset) (((offset & 3) << 29) | ((((offset) &0x1fffff) >> 2) << 5)) +# define OFFSET26(offset) ((offset >> 2) & 0x03ffffff) -#define OFFSET14(offset) (((offset >> 2) << 5) & 0x0007ffe0) -#define OFFSET19(offset) (((offset >> 2) << 5) & 0x00ffffe0) -#define OFFSET20(offset) (((offset & 3) << 29) | ((((offset) & 0x1fffff) >> 2) << 5)) -#define OFFSET26(offset) ((offset >> 2) & 0x03ffffff) +# define OFFSET12_B(offset) (offset << 10) +# define OFFSET12_H(offset) ((offset >> 1) << 10) +# define OFFSET12_W(offset) ((offset >> 2) << 10) +# define OFFSET12_Q(offset) ((offset >> 3) << 10) -#define OFFSET12_B(offset) (offset << 10) -#define OFFSET12_H(offset) ((offset >> 1) << 10) -#define OFFSET12_W(offset) ((offset >> 2) << 10) -#define OFFSET12_Q(offset) ((offset >> 3) << 10) +# define SHIFT_IMM_V4H(shift) (((shift) | 0x10) << 16) +# define SHIFT_IMM_V2S(shift) (((shift) | 0x20) << 16) +# define SHIFT_IMM_V2D(shift) (((shift) | 0x40) << 16) -#define SHIFT_IMM_V4H(shift) (((shift) | 0x10) << 16) -#define SHIFT_IMM_V2S(shift) (((shift) | 0x20) << 16) -#define SHIFT_IMM_V2D(shift) (((shift) | 0x40) << 16) +# define SHRN_SHIFT_IMM_V4S(shift) (((shift) | 0x10) << 16) -#define SHRN_SHIFT_IMM_V4S(shift) (((shift) | 0x10) << 16) - -#define DUP_ELEMENT(element) ((element) << 19) +# define DUP_ELEMENT(element) ((element) << 19) /*Returns true if offset fits into 19 bits*/ -static int offset_is_19bit(int offset) +static int +offset_is_19bit(int offset) { - if (offset >= (1 << (18+2))) - return 0; - if (offset < -(1 << (18+2))) - return 0; - return 1; + if (offset >= (1 << (18 + 2))) + return 0; + if (offset < -(1 << (18 + 2))) + return 0; + return 1; } /*Returns true if offset fits into 26 bits*/ -static int offset_is_26bit(int offset) +static int +offset_is_26bit(int offset) { - if (offset >= (1 << (25+2))) - return 0; - if (offset < -(1 << (25+2))) - return 0; - return 1; + if (offset >= (1 << (25 + 2))) + return 0; + if (offset < -(1 << (25 + 2))) + return 0; + return 1; } -static inline int imm_is_imm16(uint32_t imm_data) +static inline int +imm_is_imm16(uint32_t imm_data) { - if (!(imm_data & 0xffff0000) || !(imm_data & 0x0000ffff)) - return 1; - return 0; -} -static inline int imm_is_imm12(uint32_t imm_data) -{ - if (!(imm_data & 0xfffff000) || !(imm_data & 0xff000fff)) - return 1; - return 0; + if (!(imm_data & 0xffff0000) || !(imm_data & 0x0000ffff)) + return 1; + return 0; } static void codegen_allocate_new_block(codeblock_t *block); -static inline void codegen_addlong(codeblock_t *block, uint32_t val) +static inline void +codegen_addlong(codeblock_t *block, uint32_t val) { - if (block_pos >= (BLOCK_MAX-4)) - codegen_allocate_new_block(block); - *(uint32_t *)&block_write_data[block_pos] = val; - block_pos += 4; + if (block_pos >= (BLOCK_MAX - 4)) + codegen_allocate_new_block(block); + *(uint32_t *) &block_write_data[block_pos] = val; + block_pos += 4; } -static void codegen_allocate_new_block(codeblock_t *block) +static void +codegen_allocate_new_block(codeblock_t *block) { - /*Current block is full. Allocate a new block*/ - struct mem_block_t *new_block = codegen_allocator_allocate(block->head_mem_block, get_block_nr(block)); - uint8_t *new_ptr = codeblock_allocator_get_ptr(new_block); - uint32_t offset = (uintptr_t)new_ptr - (uintptr_t)&block_write_data[block_pos]; + /*Current block is full. Allocate a new block*/ + struct mem_block_t *new_block = codegen_allocator_allocate(block->head_mem_block, get_block_nr(block)); + uint8_t *new_ptr = codeblock_allocator_get_ptr(new_block); + uint32_t offset = (uintptr_t) new_ptr - (uintptr_t) &block_write_data[block_pos]; - if (!offset_is_26bit(offset)) - fatal("codegen_allocate_new_block - offset out of range %x\n", offset); - /*Add a jump instruction to the new block*/ - *(uint32_t *)&block_write_data[block_pos] = OPCODE_B | OFFSET26(offset); + if (!offset_is_26bit(offset)) + fatal("codegen_allocate_new_block - offset out of range %x\n", offset); + /*Add a jump instruction to the new block*/ + *(uint32_t *) &block_write_data[block_pos] = OPCODE_B | OFFSET26(offset); - /*Set write address to start of new block*/ - block_pos = 0; - block_write_data = new_ptr; + /*Set write address to start of new block*/ + block_pos = 0; + block_write_data = new_ptr; } -void codegen_alloc(codeblock_t *block, int size) +void +codegen_alloc(codeblock_t *block, int size) { - if (block_pos >= (BLOCK_MAX-size)) - codegen_allocate_new_block(block); + if (block_pos >= (BLOCK_MAX - size)) + codegen_allocate_new_block(block); } -void host_arm64_ADD_IMM(codeblock_t *block, int dst_reg, int src_n_reg, uint32_t imm_data) +void +host_arm64_ADD_IMM(codeblock_t *block, int dst_reg, int src_n_reg, uint32_t imm_data) { - if (!imm_data) - host_arm64_MOV_REG(block, dst_reg, src_n_reg, 0); - else if ((int32_t)imm_data < 0 && imm_data != 0x80000000) - { - host_arm64_SUB_IMM(block, dst_reg, src_n_reg, -(int32_t)imm_data); - } - else if (!(imm_data & 0xff000000)) - { - if (imm_data & 0xfff) - { - codegen_addlong(block, OPCODE_ADD_IMM | Rd(dst_reg) | Rn(src_n_reg) | IMM12(imm_data & 0xfff) | DATPROC_IMM_SHIFT(0)); - if (imm_data & 0xfff000) - codegen_addlong(block, OPCODE_ADD_IMM | Rd(dst_reg) | Rn(dst_reg) | IMM12((imm_data >> 12) & 0xfff) | DATPROC_IMM_SHIFT(1)); - } - else if (imm_data & 0xfff000) - codegen_addlong(block, OPCODE_ADD_IMM | Rd(dst_reg) | Rn(src_n_reg) | IMM12((imm_data >> 12) & 0xfff) | DATPROC_IMM_SHIFT(1)); - } - else - { - host_arm64_MOVZ_IMM(block, REG_W16, imm_data & 0xffff); - host_arm64_MOVK_IMM(block, REG_W16, imm_data & 0xffff0000); - codegen_addlong(block, OPCODE_ADD_LSL | Rd(dst_reg) | Rn(src_n_reg) | Rm(REG_W16) | DATPROC_SHIFT(0)); - } + if (!imm_data) + host_arm64_MOV_REG(block, dst_reg, src_n_reg, 0); + else if ((int32_t) imm_data < 0 && imm_data != 0x80000000) { + host_arm64_SUB_IMM(block, dst_reg, src_n_reg, -(int32_t) imm_data); + } else if (!(imm_data & 0xff000000)) { + if (imm_data & 0xfff) { + codegen_addlong(block, OPCODE_ADD_IMM | Rd(dst_reg) | Rn(src_n_reg) | IMM12(imm_data & 0xfff) | DATPROC_IMM_SHIFT(0)); + if (imm_data & 0xfff000) + codegen_addlong(block, OPCODE_ADD_IMM | Rd(dst_reg) | Rn(dst_reg) | IMM12((imm_data >> 12) & 0xfff) | DATPROC_IMM_SHIFT(1)); + } else if (imm_data & 0xfff000) + codegen_addlong(block, OPCODE_ADD_IMM | Rd(dst_reg) | Rn(src_n_reg) | IMM12((imm_data >> 12) & 0xfff) | DATPROC_IMM_SHIFT(1)); + } else { + host_arm64_MOVZ_IMM(block, REG_W16, imm_data & 0xffff); + host_arm64_MOVK_IMM(block, REG_W16, imm_data & 0xffff0000); + codegen_addlong(block, OPCODE_ADD_LSL | Rd(dst_reg) | Rn(src_n_reg) | Rm(REG_W16) | DATPROC_SHIFT(0)); + } } -void host_arm64_ADDX_IMM(codeblock_t *block, int dst_reg, int src_n_reg, uint64_t imm_data) +void +host_arm64_ADDX_IMM(codeblock_t *block, int dst_reg, int src_n_reg, uint64_t imm_data) { - if (!(imm_data & ~0xffffffull)) - { - if (imm_data & 0xfff) - { - codegen_addlong(block, OPCODE_ADDX_IMM | Rd(dst_reg) | Rn(src_n_reg) | IMM12(imm_data & 0xfff) | DATPROC_IMM_SHIFT(0)); - if (imm_data & 0xfff000) - codegen_addlong(block, OPCODE_ADDX_IMM | Rd(dst_reg) | Rn(dst_reg) | IMM12((imm_data >> 12) & 0xfff) | DATPROC_IMM_SHIFT(1)); - } - else if (imm_data & 0xfff000) - codegen_addlong(block, OPCODE_ADDX_IMM | Rd(dst_reg) | Rn(src_n_reg) | IMM12((imm_data >> 12) & 0xfff) | DATPROC_IMM_SHIFT(1)); - } - else - fatal("ADD_IMM_X %016llx\n", imm_data); + if (!(imm_data & ~0xffffffull)) { + if (imm_data & 0xfff) { + codegen_addlong(block, OPCODE_ADDX_IMM | Rd(dst_reg) | Rn(src_n_reg) | IMM12(imm_data & 0xfff) | DATPROC_IMM_SHIFT(0)); + if (imm_data & 0xfff000) + codegen_addlong(block, OPCODE_ADDX_IMM | Rd(dst_reg) | Rn(dst_reg) | IMM12((imm_data >> 12) & 0xfff) | DATPROC_IMM_SHIFT(1)); + } else if (imm_data & 0xfff000) + codegen_addlong(block, OPCODE_ADDX_IMM | Rd(dst_reg) | Rn(src_n_reg) | IMM12((imm_data >> 12) & 0xfff) | DATPROC_IMM_SHIFT(1)); + } else + fatal("ADD_IMM_X %016" PRIu64 "\n", imm_data); } -void host_arm64_ADD_REG(codeblock_t *block, int dst_reg, int src_n_reg, int src_m_reg, int shift) +void +host_arm64_ADD_REG(codeblock_t *block, int dst_reg, int src_n_reg, int src_m_reg, int shift) { - codegen_addlong(block, OPCODE_ADD_LSL | Rd(dst_reg) | Rn(src_n_reg) | Rm(src_m_reg) | DATPROC_SHIFT(shift)); + codegen_addlong(block, OPCODE_ADD_LSL | Rd(dst_reg) | Rn(src_n_reg) | Rm(src_m_reg) | DATPROC_SHIFT(shift)); } -void host_arm64_ADD_REG_LSR(codeblock_t *block, int dst_reg, int src_n_reg, int src_m_reg, int shift) +void +host_arm64_ADD_REG_LSR(codeblock_t *block, int dst_reg, int src_n_reg, int src_m_reg, int shift) { - codegen_addlong(block, OPCODE_ADD_LSR | Rd(dst_reg) | Rn(src_n_reg) | Rm(src_m_reg) | DATPROC_SHIFT(shift)); + codegen_addlong(block, OPCODE_ADD_LSR | Rd(dst_reg) | Rn(src_n_reg) | Rm(src_m_reg) | DATPROC_SHIFT(shift)); } -void host_arm64_ADD_V8B(codeblock_t *block, int dst_reg, int src_n_reg, int src_m_reg) +void +host_arm64_ADD_V8B(codeblock_t *block, int dst_reg, int src_n_reg, int src_m_reg) { - codegen_addlong(block, OPCODE_ADD_V8B | Rd(dst_reg) | Rn(src_n_reg) | Rm(src_m_reg)); + codegen_addlong(block, OPCODE_ADD_V8B | Rd(dst_reg) | Rn(src_n_reg) | Rm(src_m_reg)); } -void host_arm64_ADD_V4H(codeblock_t *block, int dst_reg, int src_n_reg, int src_m_reg) +void +host_arm64_ADD_V4H(codeblock_t *block, int dst_reg, int src_n_reg, int src_m_reg) { - codegen_addlong(block, OPCODE_ADD_V4H | Rd(dst_reg) | Rn(src_n_reg) | Rm(src_m_reg)); + codegen_addlong(block, OPCODE_ADD_V4H | Rd(dst_reg) | Rn(src_n_reg) | Rm(src_m_reg)); } -void host_arm64_ADD_V2S(codeblock_t *block, int dst_reg, int src_n_reg, int src_m_reg) +void +host_arm64_ADD_V2S(codeblock_t *block, int dst_reg, int src_n_reg, int src_m_reg) { - codegen_addlong(block, OPCODE_ADD_V2S | Rd(dst_reg) | Rn(src_n_reg) | Rm(src_m_reg)); + codegen_addlong(block, OPCODE_ADD_V2S | Rd(dst_reg) | Rn(src_n_reg) | Rm(src_m_reg)); } -void host_arm64_ADDP_V4S(codeblock_t *block, int dst_reg, int src_n_reg, int src_m_reg) +void +host_arm64_ADDP_V4S(codeblock_t *block, int dst_reg, int src_n_reg, int src_m_reg) { - codegen_addlong(block, OPCODE_ADDP_V4S | Rd(dst_reg) | Rn(src_n_reg) | Rm(src_m_reg)); + codegen_addlong(block, OPCODE_ADDP_V4S | Rd(dst_reg) | Rn(src_n_reg) | Rm(src_m_reg)); } -void host_arm64_ADR(codeblock_t *block, int dst_reg, int offset) +void +host_arm64_ADR(codeblock_t *block, int dst_reg, int offset) { - codegen_addlong(block, OPCODE_ADR | Rd(dst_reg) | OFFSET20(offset)); + codegen_addlong(block, OPCODE_ADR | Rd(dst_reg) | OFFSET20(offset)); } -void host_arm64_AND_IMM(codeblock_t *block, int dst_reg, int src_n_reg, uint32_t imm_data) +void +host_arm64_AND_IMM(codeblock_t *block, int dst_reg, int src_n_reg, uint32_t imm_data) { - uint32_t imm_encoding = host_arm64_find_imm(imm_data); + uint32_t imm_encoding = host_arm64_find_imm(imm_data); - if (imm_encoding) - { - codegen_addlong(block, OPCODE_AND_IMM | Rd(dst_reg) | Rn(src_n_reg) | IMM_LOGICAL(imm_encoding)); - } - else - { - host_arm64_mov_imm(block, REG_W16, imm_data); - codegen_addlong(block, OPCODE_AND_LSL | Rd(dst_reg) | Rn(src_n_reg) | Rm(REG_W16) | DATPROC_SHIFT(0)); - } + if (imm_encoding) { + codegen_addlong(block, OPCODE_AND_IMM | Rd(dst_reg) | Rn(src_n_reg) | IMM_LOGICAL(imm_encoding)); + } else { + host_arm64_mov_imm(block, REG_W16, imm_data); + codegen_addlong(block, OPCODE_AND_LSL | Rd(dst_reg) | Rn(src_n_reg) | Rm(REG_W16) | DATPROC_SHIFT(0)); + } } -void host_arm64_AND_REG(codeblock_t *block, int dst_reg, int src_n_reg, int src_m_reg, int shift) +void +host_arm64_AND_REG(codeblock_t *block, int dst_reg, int src_n_reg, int src_m_reg, int shift) { - codegen_addlong(block, OPCODE_AND_LSL | Rd(dst_reg) | Rn(src_n_reg) | Rm(src_m_reg) | DATPROC_SHIFT(shift)); + codegen_addlong(block, OPCODE_AND_LSL | Rd(dst_reg) | Rn(src_n_reg) | Rm(src_m_reg) | DATPROC_SHIFT(shift)); } -void host_arm64_AND_REG_ASR(codeblock_t *block, int dst_reg, int src_n_reg, int src_m_reg, int shift) +void +host_arm64_AND_REG_ASR(codeblock_t *block, int dst_reg, int src_n_reg, int src_m_reg, int shift) { - codegen_addlong(block, OPCODE_AND_ASR | Rd(dst_reg) | Rn(src_n_reg) | Rm(src_m_reg) | DATPROC_SHIFT(shift)); + codegen_addlong(block, OPCODE_AND_ASR | Rd(dst_reg) | Rn(src_n_reg) | Rm(src_m_reg) | DATPROC_SHIFT(shift)); } -void host_arm64_AND_REG_ROR(codeblock_t *block, int dst_reg, int src_n_reg, int src_m_reg, int shift) +void +host_arm64_AND_REG_ROR(codeblock_t *block, int dst_reg, int src_n_reg, int src_m_reg, int shift) { - codegen_addlong(block, OPCODE_AND_ROR | Rd(dst_reg) | Rn(src_n_reg) | Rm(src_m_reg) | DATPROC_SHIFT(shift)); + codegen_addlong(block, OPCODE_AND_ROR | Rd(dst_reg) | Rn(src_n_reg) | Rm(src_m_reg) | DATPROC_SHIFT(shift)); } -void host_arm64_AND_REG_V(codeblock_t *block, int dst_reg, int src_n_reg, int src_m_reg) +void +host_arm64_AND_REG_V(codeblock_t *block, int dst_reg, int src_n_reg, int src_m_reg) { - codegen_addlong(block, OPCODE_AND_V | Rd(dst_reg) | Rn(src_n_reg) | Rm(src_m_reg)); + codegen_addlong(block, OPCODE_AND_V | Rd(dst_reg) | Rn(src_n_reg) | Rm(src_m_reg)); } -void host_arm64_ANDS_IMM(codeblock_t *block, int dst_reg, int src_n_reg, uint32_t imm_data) +void +host_arm64_ANDS_IMM(codeblock_t *block, int dst_reg, int src_n_reg, uint32_t imm_data) { - uint32_t imm_encoding = host_arm64_find_imm(imm_data); + uint32_t imm_encoding = host_arm64_find_imm(imm_data); - if (imm_encoding) - { - codegen_addlong(block, OPCODE_ANDS_IMM | Rd(dst_reg) | Rn(src_n_reg) | IMM_LOGICAL(imm_encoding)); - } - else - { - host_arm64_mov_imm(block, REG_W16, imm_data); - codegen_addlong(block, OPCODE_ANDS_LSL | Rd(dst_reg) | Rn(src_n_reg) | Rm(REG_W16) | DATPROC_SHIFT(0)); - } + if (imm_encoding) { + codegen_addlong(block, OPCODE_ANDS_IMM | Rd(dst_reg) | Rn(src_n_reg) | IMM_LOGICAL(imm_encoding)); + } else { + host_arm64_mov_imm(block, REG_W16, imm_data); + codegen_addlong(block, OPCODE_ANDS_LSL | Rd(dst_reg) | Rn(src_n_reg) | Rm(REG_W16) | DATPROC_SHIFT(0)); + } } -void host_arm64_ASR(codeblock_t *block, int dst_reg, int src_n_reg, int shift_reg) +void +host_arm64_ASR(codeblock_t *block, int dst_reg, int src_n_reg, int shift_reg) { - codegen_addlong(block, OPCODE_ASR | Rd(dst_reg) | Rn(src_n_reg) | Rm(shift_reg)); + codegen_addlong(block, OPCODE_ASR | Rd(dst_reg) | Rn(src_n_reg) | Rm(shift_reg)); } -void host_arm64_B(codeblock_t *block, void *dest) +void +host_arm64_B(codeblock_t *block, void *dest) { - int offset; + int offset; - codegen_alloc(block, 4); - offset = (uintptr_t)dest - (uintptr_t)&block_write_data[block_pos]; + codegen_alloc(block, 4); + offset = (uintptr_t) dest - (uintptr_t) &block_write_data[block_pos]; - if (!offset_is_26bit(offset)) - fatal("host_arm64_B - offset out of range %x\n", offset); - codegen_addlong(block, OPCODE_B | OFFSET26(offset)); + if (!offset_is_26bit(offset)) + fatal("host_arm64_B - offset out of range %x\n", offset); + codegen_addlong(block, OPCODE_B | OFFSET26(offset)); } -void host_arm64_BFI(codeblock_t *block, int dst_reg, int src_reg, int lsb, int width) +void +host_arm64_BFI(codeblock_t *block, int dst_reg, int src_reg, int lsb, int width) { - codegen_addlong(block, OPCODE_BFI | Rd(dst_reg) | Rn(src_reg) | IMMN(0) | IMMR((32 - lsb) & 31) | IMMS((width-1) & 31)); + codegen_addlong(block, OPCODE_BFI | Rd(dst_reg) | Rn(src_reg) | IMMN(0) | IMMR((32 - lsb) & 31) | IMMS((width - 1) & 31)); } -void host_arm64_BLR(codeblock_t *block, int addr_reg) +void +host_arm64_BLR(codeblock_t *block, int addr_reg) { - codegen_addlong(block, OPCODE_BLR | Rn(addr_reg)); + codegen_addlong(block, OPCODE_BLR | Rn(addr_reg)); } -uint32_t *host_arm64_BCC_(codeblock_t *block) +uint32_t * +host_arm64_BCC_(codeblock_t *block) { - codegen_alloc(block, 12); - codegen_addlong(block, OPCODE_BCOND | COND_CS | OFFSET19(8)); - codegen_addlong(block, OPCODE_B); - return (uint32_t *)&block_write_data[block_pos-4]; + codegen_alloc(block, 12); + codegen_addlong(block, OPCODE_BCOND | COND_CS | OFFSET19(8)); + codegen_addlong(block, OPCODE_B); + return (uint32_t *) &block_write_data[block_pos - 4]; } -uint32_t *host_arm64_BCS_(codeblock_t *block) +uint32_t * +host_arm64_BCS_(codeblock_t *block) { - codegen_alloc(block, 12); - codegen_addlong(block, OPCODE_BCOND | COND_CC | OFFSET19(8)); - codegen_addlong(block, OPCODE_B); - return (uint32_t *)&block_write_data[block_pos-4]; + codegen_alloc(block, 12); + codegen_addlong(block, OPCODE_BCOND | COND_CC | OFFSET19(8)); + codegen_addlong(block, OPCODE_B); + return (uint32_t *) &block_write_data[block_pos - 4]; } -uint32_t *host_arm64_BEQ_(codeblock_t *block) +uint32_t * +host_arm64_BEQ_(codeblock_t *block) { - codegen_alloc(block, 12); - codegen_addlong(block, OPCODE_BCOND | COND_NE | OFFSET19(8)); - codegen_addlong(block, OPCODE_B); - return (uint32_t *)&block_write_data[block_pos-4]; + codegen_alloc(block, 12); + codegen_addlong(block, OPCODE_BCOND | COND_NE | OFFSET19(8)); + codegen_addlong(block, OPCODE_B); + return (uint32_t *) &block_write_data[block_pos - 4]; } -uint32_t *host_arm64_BGE_(codeblock_t *block) +uint32_t * +host_arm64_BGE_(codeblock_t *block) { - codegen_alloc(block, 12); - codegen_addlong(block, OPCODE_BCOND | COND_LT | OFFSET19(8)); - codegen_addlong(block, OPCODE_B); - return (uint32_t *)&block_write_data[block_pos-4]; + codegen_alloc(block, 12); + codegen_addlong(block, OPCODE_BCOND | COND_LT | OFFSET19(8)); + codegen_addlong(block, OPCODE_B); + return (uint32_t *) &block_write_data[block_pos - 4]; } -uint32_t *host_arm64_BGT_(codeblock_t *block) +uint32_t * +host_arm64_BGT_(codeblock_t *block) { - codegen_alloc(block, 12); - codegen_addlong(block, OPCODE_BCOND | COND_LE | OFFSET19(8)); - codegen_addlong(block, OPCODE_B); - return (uint32_t *)&block_write_data[block_pos-4]; + codegen_alloc(block, 12); + codegen_addlong(block, OPCODE_BCOND | COND_LE | OFFSET19(8)); + codegen_addlong(block, OPCODE_B); + return (uint32_t *) &block_write_data[block_pos - 4]; } -uint32_t *host_arm64_BHI_(codeblock_t *block) +uint32_t * +host_arm64_BHI_(codeblock_t *block) { - codegen_alloc(block, 12); - codegen_addlong(block, OPCODE_BCOND | COND_LS | OFFSET19(8)); - codegen_addlong(block, OPCODE_B); - return (uint32_t *)&block_write_data[block_pos-4]; + codegen_alloc(block, 12); + codegen_addlong(block, OPCODE_BCOND | COND_LS | OFFSET19(8)); + codegen_addlong(block, OPCODE_B); + return (uint32_t *) &block_write_data[block_pos - 4]; } -uint32_t *host_arm64_BLE_(codeblock_t *block) +uint32_t * +host_arm64_BLE_(codeblock_t *block) { - codegen_alloc(block, 12); - codegen_addlong(block, OPCODE_BCOND | COND_GT | OFFSET19(8)); - codegen_addlong(block, OPCODE_B); - return (uint32_t *)&block_write_data[block_pos-4]; + codegen_alloc(block, 12); + codegen_addlong(block, OPCODE_BCOND | COND_GT | OFFSET19(8)); + codegen_addlong(block, OPCODE_B); + return (uint32_t *) &block_write_data[block_pos - 4]; } -uint32_t *host_arm64_BLS_(codeblock_t *block) +uint32_t * +host_arm64_BLS_(codeblock_t *block) { - codegen_alloc(block, 12); - codegen_addlong(block, OPCODE_BCOND | COND_HI | OFFSET19(8)); - codegen_addlong(block, OPCODE_B); - return (uint32_t *)&block_write_data[block_pos-4]; + codegen_alloc(block, 12); + codegen_addlong(block, OPCODE_BCOND | COND_HI | OFFSET19(8)); + codegen_addlong(block, OPCODE_B); + return (uint32_t *) &block_write_data[block_pos - 4]; } -uint32_t *host_arm64_BLT_(codeblock_t *block) +uint32_t * +host_arm64_BLT_(codeblock_t *block) { - codegen_alloc(block, 12); - codegen_addlong(block, OPCODE_BCOND | COND_GE | OFFSET19(8)); - codegen_addlong(block, OPCODE_B); - return (uint32_t *)&block_write_data[block_pos-4]; + codegen_alloc(block, 12); + codegen_addlong(block, OPCODE_BCOND | COND_GE | OFFSET19(8)); + codegen_addlong(block, OPCODE_B); + return (uint32_t *) &block_write_data[block_pos - 4]; } -uint32_t *host_arm64_BMI_(codeblock_t *block) +uint32_t * +host_arm64_BMI_(codeblock_t *block) { - codegen_alloc(block, 12); - codegen_addlong(block, OPCODE_BCOND | COND_PL | OFFSET19(8)); - codegen_addlong(block, OPCODE_B); - return (uint32_t *)&block_write_data[block_pos-4]; + codegen_alloc(block, 12); + codegen_addlong(block, OPCODE_BCOND | COND_PL | OFFSET19(8)); + codegen_addlong(block, OPCODE_B); + return (uint32_t *) &block_write_data[block_pos - 4]; } -uint32_t *host_arm64_BNE_(codeblock_t *block) +uint32_t * +host_arm64_BNE_(codeblock_t *block) { - codegen_alloc(block, 12); - codegen_addlong(block, OPCODE_BCOND | COND_EQ | OFFSET19(8)); - codegen_addlong(block, OPCODE_B); - return (uint32_t *)&block_write_data[block_pos-4]; + codegen_alloc(block, 12); + codegen_addlong(block, OPCODE_BCOND | COND_EQ | OFFSET19(8)); + codegen_addlong(block, OPCODE_B); + return (uint32_t *) &block_write_data[block_pos - 4]; } -uint32_t *host_arm64_BPL_(codeblock_t *block) +uint32_t * +host_arm64_BPL_(codeblock_t *block) { - codegen_alloc(block, 12); - codegen_addlong(block, OPCODE_BCOND | COND_MI | OFFSET19(8)); - codegen_addlong(block, OPCODE_B); - return (uint32_t *)&block_write_data[block_pos-4]; + codegen_alloc(block, 12); + codegen_addlong(block, OPCODE_BCOND | COND_MI | OFFSET19(8)); + codegen_addlong(block, OPCODE_B); + return (uint32_t *) &block_write_data[block_pos - 4]; } -uint32_t *host_arm64_BVC_(codeblock_t *block) +uint32_t * +host_arm64_BVC_(codeblock_t *block) { - codegen_alloc(block, 12); - codegen_addlong(block, OPCODE_BCOND | COND_VS | OFFSET19(8)); - codegen_addlong(block, OPCODE_B); - return (uint32_t *)&block_write_data[block_pos-4]; + codegen_alloc(block, 12); + codegen_addlong(block, OPCODE_BCOND | COND_VS | OFFSET19(8)); + codegen_addlong(block, OPCODE_B); + return (uint32_t *) &block_write_data[block_pos - 4]; } -uint32_t *host_arm64_BVS_(codeblock_t *block) +uint32_t * +host_arm64_BVS_(codeblock_t *block) { - codegen_alloc(block, 12); - codegen_addlong(block, OPCODE_BCOND | COND_VC | OFFSET19(8)); - codegen_addlong(block, OPCODE_B); - return (uint32_t *)&block_write_data[block_pos-4]; + codegen_alloc(block, 12); + codegen_addlong(block, OPCODE_BCOND | COND_VC | OFFSET19(8)); + codegen_addlong(block, OPCODE_B); + return (uint32_t *) &block_write_data[block_pos - 4]; } -void host_arm64_branch_set_offset(uint32_t *opcode, void *dest) +void +host_arm64_branch_set_offset(uint32_t *opcode, void *dest) { - int offset = (uintptr_t)dest - (uintptr_t)opcode; - *opcode |= OFFSET26(offset); + int offset = (uintptr_t) dest - (uintptr_t) opcode; + *opcode |= OFFSET26(offset); } -void host_arm64_BR(codeblock_t *block, int addr_reg) +void +host_arm64_BR(codeblock_t *block, int addr_reg) { - codegen_addlong(block, OPCODE_BR | Rn(addr_reg)); + codegen_addlong(block, OPCODE_BR | Rn(addr_reg)); } -void host_arm64_BEQ(codeblock_t *block, void *dest) +void +host_arm64_BEQ(codeblock_t *block, void *dest) { - uint32_t *opcode = host_arm64_BEQ_(block); - host_arm64_branch_set_offset(opcode, dest); + uint32_t *opcode = host_arm64_BEQ_(block); + host_arm64_branch_set_offset(opcode, dest); } -void host_arm64_BIC_REG_V(codeblock_t *block, int dst_reg, int src_n_reg, int src_m_reg) +void +host_arm64_BIC_REG_V(codeblock_t *block, int dst_reg, int src_n_reg, int src_m_reg) { - codegen_addlong(block, OPCODE_BIC_V | Rd(dst_reg) | Rn(src_n_reg) | Rm(src_m_reg)); + codegen_addlong(block, OPCODE_BIC_V | Rd(dst_reg) | Rn(src_n_reg) | Rm(src_m_reg)); } -void host_arm64_CBNZ(codeblock_t *block, int reg, uintptr_t dest) +void +host_arm64_CBNZ(codeblock_t *block, int reg, uintptr_t dest) { - int offset; + int offset; - codegen_alloc(block, 4); - offset = dest - (uintptr_t)&block_write_data[block_pos]; - if (offset_is_19bit(offset)) - { - codegen_addlong(block, OPCODE_CBNZ | OFFSET19(offset) | Rt(reg)); - } - else - { - codegen_alloc(block, 12); - codegen_addlong(block, OPCODE_CBZ | OFFSET19(8) | Rt(reg)); - offset = (uintptr_t)dest - (uintptr_t)&block_write_data[block_pos]; - codegen_addlong(block, OPCODE_B | OFFSET26(offset)); - } + codegen_alloc(block, 4); + offset = dest - (uintptr_t) &block_write_data[block_pos]; + if (offset_is_19bit(offset)) { + codegen_addlong(block, OPCODE_CBNZ | OFFSET19(offset) | Rt(reg)); + } else { + codegen_alloc(block, 12); + codegen_addlong(block, OPCODE_CBZ | OFFSET19(8) | Rt(reg)); + offset = (uintptr_t) dest - (uintptr_t) &block_write_data[block_pos]; + codegen_addlong(block, OPCODE_B | OFFSET26(offset)); + } } -void host_arm64_CMEQ_V8B(codeblock_t *block, int dst_reg, int src_n_reg, int src_m_reg) +void +host_arm64_CMEQ_V8B(codeblock_t *block, int dst_reg, int src_n_reg, int src_m_reg) { - codegen_addlong(block, OPCODE_CMEQ_V8B | Rd(dst_reg) | Rn(src_n_reg) | Rm(src_m_reg)); + codegen_addlong(block, OPCODE_CMEQ_V8B | Rd(dst_reg) | Rn(src_n_reg) | Rm(src_m_reg)); } -void host_arm64_CMEQ_V4H(codeblock_t *block, int dst_reg, int src_n_reg, int src_m_reg) +void +host_arm64_CMEQ_V4H(codeblock_t *block, int dst_reg, int src_n_reg, int src_m_reg) { - codegen_addlong(block, OPCODE_CMEQ_V4H | Rd(dst_reg) | Rn(src_n_reg) | Rm(src_m_reg)); + codegen_addlong(block, OPCODE_CMEQ_V4H | Rd(dst_reg) | Rn(src_n_reg) | Rm(src_m_reg)); } -void host_arm64_CMEQ_V2S(codeblock_t *block, int dst_reg, int src_n_reg, int src_m_reg) +void +host_arm64_CMEQ_V2S(codeblock_t *block, int dst_reg, int src_n_reg, int src_m_reg) { - codegen_addlong(block, OPCODE_CMEQ_V2S | Rd(dst_reg) | Rn(src_n_reg) | Rm(src_m_reg)); + codegen_addlong(block, OPCODE_CMEQ_V2S | Rd(dst_reg) | Rn(src_n_reg) | Rm(src_m_reg)); } -void host_arm64_CMGT_V8B(codeblock_t *block, int dst_reg, int src_n_reg, int src_m_reg) +void +host_arm64_CMGT_V8B(codeblock_t *block, int dst_reg, int src_n_reg, int src_m_reg) { - codegen_addlong(block, OPCODE_CMGT_V8B | Rd(dst_reg) | Rn(src_n_reg) | Rm(src_m_reg)); + codegen_addlong(block, OPCODE_CMGT_V8B | Rd(dst_reg) | Rn(src_n_reg) | Rm(src_m_reg)); } -void host_arm64_CMGT_V4H(codeblock_t *block, int dst_reg, int src_n_reg, int src_m_reg) +void +host_arm64_CMGT_V4H(codeblock_t *block, int dst_reg, int src_n_reg, int src_m_reg) { - codegen_addlong(block, OPCODE_CMGT_V4H | Rd(dst_reg) | Rn(src_n_reg) | Rm(src_m_reg)); + codegen_addlong(block, OPCODE_CMGT_V4H | Rd(dst_reg) | Rn(src_n_reg) | Rm(src_m_reg)); } -void host_arm64_CMGT_V2S(codeblock_t *block, int dst_reg, int src_n_reg, int src_m_reg) +void +host_arm64_CMGT_V2S(codeblock_t *block, int dst_reg, int src_n_reg, int src_m_reg) { - codegen_addlong(block, OPCODE_CMGT_V2S | Rd(dst_reg) | Rn(src_n_reg) | Rm(src_m_reg)); + codegen_addlong(block, OPCODE_CMGT_V2S | Rd(dst_reg) | Rn(src_n_reg) | Rm(src_m_reg)); } -void host_arm64_CMN_IMM(codeblock_t *block, int src_n_reg, uint32_t imm_data) +void +host_arm64_CMN_IMM(codeblock_t *block, int src_n_reg, uint32_t imm_data) { - if ((int32_t)imm_data < 0 && imm_data != (1ull << 31)) - { - host_arm64_CMP_IMM(block, src_n_reg, -(int32_t)imm_data); - } - else if (!(imm_data & 0xfffff000)) - { - codegen_addlong(block, OPCODE_CMN_IMM | Rd(REG_WZR) | Rn(src_n_reg) | IMM12(imm_data & 0xfff) | DATPROC_IMM_SHIFT(0)); - } - else - fatal("CMN_IMM %08x\n", imm_data); + if ((int32_t) imm_data < 0 && imm_data != (1ull << 31)) { + host_arm64_CMP_IMM(block, src_n_reg, -(int32_t) imm_data); + } else if (!(imm_data & 0xfffff000)) { + codegen_addlong(block, OPCODE_CMN_IMM | Rd(REG_WZR) | Rn(src_n_reg) | IMM12(imm_data & 0xfff) | DATPROC_IMM_SHIFT(0)); + } else + fatal("CMN_IMM %08x\n", imm_data); } -void host_arm64_CMNX_IMM(codeblock_t *block, int src_n_reg, uint64_t imm_data) +void +host_arm64_CMNX_IMM(codeblock_t *block, int src_n_reg, uint64_t imm_data) { - if ((int64_t)imm_data < 0 && imm_data != (1ull << 63)) - { - host_arm64_CMPX_IMM(block, src_n_reg, -(int64_t)imm_data); - } - else if (!(imm_data & 0xfffffffffffff000ull)) - { - codegen_addlong(block, OPCODE_CMNX_IMM | Rd(REG_XZR) | Rn(src_n_reg) | IMM12(imm_data & 0xfff) | DATPROC_IMM_SHIFT(0)); - } - else - fatal("CMNX_IMM %08x\n", imm_data); + if ((int64_t) imm_data < 0 && imm_data != (1ull << 63)) { + host_arm64_CMPX_IMM(block, src_n_reg, -(int64_t) imm_data); + } else if (!(imm_data & 0xfffffffffffff000ull)) { + codegen_addlong(block, OPCODE_CMNX_IMM | Rd(REG_XZR) | Rn(src_n_reg) | IMM12(imm_data & 0xfff) | DATPROC_IMM_SHIFT(0)); + } else + fatal("CMNX_IMM %016" PRIx64 "\n", imm_data); } -void host_arm64_CMP_IMM(codeblock_t *block, int src_n_reg, uint32_t imm_data) +void +host_arm64_CMP_IMM(codeblock_t *block, int src_n_reg, uint32_t imm_data) { - if ((int32_t)imm_data < 0 && imm_data != (1ull << 31)) - { - host_arm64_CMN_IMM(block, src_n_reg, -(int32_t)imm_data); - } - else if (!(imm_data & 0xfffff000)) - { - codegen_addlong(block, OPCODE_CMP_IMM | Rd(REG_WZR) | Rn(src_n_reg) | IMM12(imm_data & 0xfff) | DATPROC_IMM_SHIFT(0)); - } - else - fatal("CMP_IMM %08x\n", imm_data); + if ((int32_t) imm_data < 0 && imm_data != (1ull << 31)) { + host_arm64_CMN_IMM(block, src_n_reg, -(int32_t) imm_data); + } else if (!(imm_data & 0xfffff000)) { + codegen_addlong(block, OPCODE_CMP_IMM | Rd(REG_WZR) | Rn(src_n_reg) | IMM12(imm_data & 0xfff) | DATPROC_IMM_SHIFT(0)); + } else + fatal("CMP_IMM %08x\n", imm_data); } -void host_arm64_CMPX_IMM(codeblock_t *block, int src_n_reg, uint64_t imm_data) +void +host_arm64_CMPX_IMM(codeblock_t *block, int src_n_reg, uint64_t imm_data) { - if ((int64_t)imm_data < 0 && imm_data != (1ull << 63)) - { - host_arm64_CMNX_IMM(block, src_n_reg, -(int64_t)imm_data); - } - else if (!(imm_data & 0xfffffffffffff000ull)) - { - codegen_addlong(block, OPCODE_CMPX_IMM | Rd(REG_XZR) | Rn(src_n_reg) | IMM12(imm_data & 0xfff) | DATPROC_IMM_SHIFT(0)); - } - else - fatal("CMPX_IMM %08x\n", imm_data); + if ((int64_t) imm_data < 0 && imm_data != (1ull << 63)) { + host_arm64_CMNX_IMM(block, src_n_reg, -(int64_t) imm_data); + } else if (!(imm_data & 0xfffffffffffff000ull)) { + codegen_addlong(block, OPCODE_CMPX_IMM | Rd(REG_XZR) | Rn(src_n_reg) | IMM12(imm_data & 0xfff) | DATPROC_IMM_SHIFT(0)); + } else + fatal("CMPX_IMM %08" PRIu64 "\n", imm_data); } -void host_arm64_CMP_REG_LSL(codeblock_t *block, int src_n_reg, int src_m_reg, int shift) +void +host_arm64_CMP_REG_LSL(codeblock_t *block, int src_n_reg, int src_m_reg, int shift) { - codegen_addlong(block, OPCODE_CMP_LSL | Rd(0x1f) | Rn(src_n_reg) | Rm(src_m_reg) | DATPROC_SHIFT(shift)); + codegen_addlong(block, OPCODE_CMP_LSL | Rd(0x1f) | Rn(src_n_reg) | Rm(src_m_reg) | DATPROC_SHIFT(shift)); } -void host_arm64_CSEL_CC(codeblock_t *block, int dst_reg, int src_n_reg, int src_m_reg) +void +host_arm64_CSEL_CC(codeblock_t *block, int dst_reg, int src_n_reg, int src_m_reg) { - codegen_addlong(block, OPCODE_CSEL | CSEL_COND(COND_CC) | Rd(dst_reg) | Rn(src_n_reg) | Rm(src_m_reg)); + codegen_addlong(block, OPCODE_CSEL | CSEL_COND(COND_CC) | Rd(dst_reg) | Rn(src_n_reg) | Rm(src_m_reg)); } -void host_arm64_CSEL_EQ(codeblock_t *block, int dst_reg, int src_n_reg, int src_m_reg) +void +host_arm64_CSEL_EQ(codeblock_t *block, int dst_reg, int src_n_reg, int src_m_reg) { - codegen_addlong(block, OPCODE_CSEL | CSEL_COND(COND_EQ) | Rd(dst_reg) | Rn(src_n_reg) | Rm(src_m_reg)); + codegen_addlong(block, OPCODE_CSEL | CSEL_COND(COND_EQ) | Rd(dst_reg) | Rn(src_n_reg) | Rm(src_m_reg)); } -void host_arm64_CSEL_VS(codeblock_t *block, int dst_reg, int src_n_reg, int src_m_reg) +void +host_arm64_CSEL_VS(codeblock_t *block, int dst_reg, int src_n_reg, int src_m_reg) { - codegen_addlong(block, OPCODE_CSEL | CSEL_COND(COND_VS) | Rd(dst_reg) | Rn(src_n_reg) | Rm(src_m_reg)); + codegen_addlong(block, OPCODE_CSEL | CSEL_COND(COND_VS) | Rd(dst_reg) | Rn(src_n_reg) | Rm(src_m_reg)); } -void host_arm64_DUP_V2S(codeblock_t *block, int dst_reg, int src_n_reg, int element) +void +host_arm64_DUP_V2S(codeblock_t *block, int dst_reg, int src_n_reg, int element) { - codegen_addlong(block, OPCODE_DUP_V2S | Rd(dst_reg) | Rn(src_n_reg) | DUP_ELEMENT(element)); + codegen_addlong(block, OPCODE_DUP_V2S | Rd(dst_reg) | Rn(src_n_reg) | DUP_ELEMENT(element)); } -void host_arm64_EOR_IMM(codeblock_t *block, int dst_reg, int src_n_reg, uint32_t imm_data) +void +host_arm64_EOR_IMM(codeblock_t *block, int dst_reg, int src_n_reg, uint32_t imm_data) { - uint32_t imm_encoding = host_arm64_find_imm(imm_data); + uint32_t imm_encoding = host_arm64_find_imm(imm_data); - if (imm_encoding) - { - codegen_addlong(block, OPCODE_EOR_IMM | Rd(dst_reg) | Rn(src_n_reg) | IMM_LOGICAL(imm_encoding)); - } - else - { - host_arm64_mov_imm(block, REG_W16, imm_data); - codegen_addlong(block, OPCODE_EOR_LSL | Rd(dst_reg) | Rn(src_n_reg) | Rm(REG_W16) | DATPROC_SHIFT(0)); - } + if (imm_encoding) { + codegen_addlong(block, OPCODE_EOR_IMM | Rd(dst_reg) | Rn(src_n_reg) | IMM_LOGICAL(imm_encoding)); + } else { + host_arm64_mov_imm(block, REG_W16, imm_data); + codegen_addlong(block, OPCODE_EOR_LSL | Rd(dst_reg) | Rn(src_n_reg) | Rm(REG_W16) | DATPROC_SHIFT(0)); + } } -void host_arm64_EOR_REG(codeblock_t *block, int dst_reg, int src_n_reg, int src_m_reg, int shift) +void +host_arm64_EOR_REG(codeblock_t *block, int dst_reg, int src_n_reg, int src_m_reg, int shift) { - codegen_addlong(block, OPCODE_EOR_LSL | Rd(dst_reg) | Rn(src_n_reg) | Rm(src_m_reg) | DATPROC_SHIFT(shift)); + codegen_addlong(block, OPCODE_EOR_LSL | Rd(dst_reg) | Rn(src_n_reg) | Rm(src_m_reg) | DATPROC_SHIFT(shift)); } -void host_arm64_EOR_REG_V(codeblock_t *block, int dst_reg, int src_n_reg, int src_m_reg) +void +host_arm64_EOR_REG_V(codeblock_t *block, int dst_reg, int src_n_reg, int src_m_reg) { - codegen_addlong(block, OPCODE_EOR_V | Rd(dst_reg) | Rn(src_n_reg) | Rm(src_m_reg)); + codegen_addlong(block, OPCODE_EOR_V | Rd(dst_reg) | Rn(src_n_reg) | Rm(src_m_reg)); } -void host_arm64_FABS_D(codeblock_t *block, int dst_reg, int src_reg) +void +host_arm64_FABS_D(codeblock_t *block, int dst_reg, int src_reg) { - codegen_addlong(block, OPCODE_FABS_D | Rd(dst_reg) | Rn(src_reg)); + codegen_addlong(block, OPCODE_FABS_D | Rd(dst_reg) | Rn(src_reg)); } -void host_arm64_FADD_D(codeblock_t *block, int dst_reg, int src_n_reg, int src_m_reg) +void +host_arm64_FADD_D(codeblock_t *block, int dst_reg, int src_n_reg, int src_m_reg) { - codegen_addlong(block, OPCODE_FADD_D | Rd(dst_reg) | Rn(src_n_reg) | Rm(src_m_reg)); + codegen_addlong(block, OPCODE_FADD_D | Rd(dst_reg) | Rn(src_n_reg) | Rm(src_m_reg)); } -void host_arm64_FADD_V2S(codeblock_t *block, int dst_reg, int src_n_reg, int src_m_reg) +void +host_arm64_FADD_V2S(codeblock_t *block, int dst_reg, int src_n_reg, int src_m_reg) { - codegen_addlong(block, OPCODE_FADD_V2S | Rd(dst_reg) | Rn(src_n_reg) | Rm(src_m_reg)); + codegen_addlong(block, OPCODE_FADD_V2S | Rd(dst_reg) | Rn(src_n_reg) | Rm(src_m_reg)); } -void host_arm64_FCMEQ_V2S(codeblock_t *block, int dst_reg, int src_n_reg, int src_m_reg) +void +host_arm64_FCMEQ_V2S(codeblock_t *block, int dst_reg, int src_n_reg, int src_m_reg) { - codegen_addlong(block, OPCODE_FCMEQ_V2S | Rd(dst_reg) | Rn(src_n_reg) | Rm(src_m_reg)); + codegen_addlong(block, OPCODE_FCMEQ_V2S | Rd(dst_reg) | Rn(src_n_reg) | Rm(src_m_reg)); } -void host_arm64_FCMGE_V2S(codeblock_t *block, int dst_reg, int src_n_reg, int src_m_reg) +void +host_arm64_FCMGE_V2S(codeblock_t *block, int dst_reg, int src_n_reg, int src_m_reg) { - codegen_addlong(block, OPCODE_FCMGE_V2S | Rd(dst_reg) | Rn(src_n_reg) | Rm(src_m_reg)); + codegen_addlong(block, OPCODE_FCMGE_V2S | Rd(dst_reg) | Rn(src_n_reg) | Rm(src_m_reg)); } -void host_arm64_FCMGT_V2S(codeblock_t *block, int dst_reg, int src_n_reg, int src_m_reg) +void +host_arm64_FCMGT_V2S(codeblock_t *block, int dst_reg, int src_n_reg, int src_m_reg) { - codegen_addlong(block, OPCODE_FCMGT_V2S | Rd(dst_reg) | Rn(src_n_reg) | Rm(src_m_reg)); + codegen_addlong(block, OPCODE_FCMGT_V2S | Rd(dst_reg) | Rn(src_n_reg) | Rm(src_m_reg)); } -void host_arm64_FCMP_D(codeblock_t *block, int src_n_reg, int src_m_reg) +void +host_arm64_FCMP_D(codeblock_t *block, int src_n_reg, int src_m_reg) { - codegen_addlong(block, OPCODE_FCMP_D | Rn(src_n_reg) | Rm(src_m_reg)); + codegen_addlong(block, OPCODE_FCMP_D | Rn(src_n_reg) | Rm(src_m_reg)); } -void host_arm64_FCVT_D_S(codeblock_t *block, int dst_reg, int src_reg) +void +host_arm64_FCVT_D_S(codeblock_t *block, int dst_reg, int src_reg) { - codegen_addlong(block, OPCODE_FCVT_D_S | Rd(dst_reg) | Rn(src_reg)); + codegen_addlong(block, OPCODE_FCVT_D_S | Rd(dst_reg) | Rn(src_reg)); } -void host_arm64_FCVT_S_D(codeblock_t *block, int dst_reg, int src_reg) +void +host_arm64_FCVT_S_D(codeblock_t *block, int dst_reg, int src_reg) { - codegen_addlong(block, OPCODE_FCVT_S_D | Rd(dst_reg) | Rn(src_reg)); + codegen_addlong(block, OPCODE_FCVT_S_D | Rd(dst_reg) | Rn(src_reg)); } -void host_arm64_FCVTMS_W_D(codeblock_t *block, int dst_reg, int src_reg) +void +host_arm64_FCVTMS_W_D(codeblock_t *block, int dst_reg, int src_reg) { - codegen_addlong(block, OPCODE_FCVTMS_W_D | Rd(dst_reg) | Rn(src_reg)); + codegen_addlong(block, OPCODE_FCVTMS_W_D | Rd(dst_reg) | Rn(src_reg)); } -void host_arm64_FCVTMS_X_D(codeblock_t *block, int dst_reg, int src_reg) +void +host_arm64_FCVTMS_X_D(codeblock_t *block, int dst_reg, int src_reg) { - codegen_addlong(block, OPCODE_FCVTMS_X_D | Rd(dst_reg) | Rn(src_reg)); + codegen_addlong(block, OPCODE_FCVTMS_X_D | Rd(dst_reg) | Rn(src_reg)); } -void host_arm64_FCVTNS_W_D(codeblock_t *block, int dst_reg, int src_reg) +void +host_arm64_FCVTNS_W_D(codeblock_t *block, int dst_reg, int src_reg) { - codegen_addlong(block, OPCODE_FCVTNS_W_D | Rd(dst_reg) | Rn(src_reg)); + codegen_addlong(block, OPCODE_FCVTNS_W_D | Rd(dst_reg) | Rn(src_reg)); } -void host_arm64_FCVTNS_X_D(codeblock_t *block, int dst_reg, int src_reg) +void +host_arm64_FCVTNS_X_D(codeblock_t *block, int dst_reg, int src_reg) { - codegen_addlong(block, OPCODE_FCVTNS_X_D | Rd(dst_reg) | Rn(src_reg)); + codegen_addlong(block, OPCODE_FCVTNS_X_D | Rd(dst_reg) | Rn(src_reg)); } -void host_arm64_FCVTPS_W_D(codeblock_t *block, int dst_reg, int src_reg) +void +host_arm64_FCVTPS_W_D(codeblock_t *block, int dst_reg, int src_reg) { - codegen_addlong(block, OPCODE_FCVTPS_W_D | Rd(dst_reg) | Rn(src_reg)); + codegen_addlong(block, OPCODE_FCVTPS_W_D | Rd(dst_reg) | Rn(src_reg)); } -void host_arm64_FCVTPS_X_D(codeblock_t *block, int dst_reg, int src_reg) +void +host_arm64_FCVTPS_X_D(codeblock_t *block, int dst_reg, int src_reg) { - codegen_addlong(block, OPCODE_FCVTPS_X_D | Rd(dst_reg) | Rn(src_reg)); + codegen_addlong(block, OPCODE_FCVTPS_X_D | Rd(dst_reg) | Rn(src_reg)); } -void host_arm64_FCVTZS_W_D(codeblock_t *block, int dst_reg, int src_reg) +void +host_arm64_FCVTZS_W_D(codeblock_t *block, int dst_reg, int src_reg) { - codegen_addlong(block, OPCODE_FCVTZS_W_D | Rd(dst_reg) | Rn(src_reg)); + codegen_addlong(block, OPCODE_FCVTZS_W_D | Rd(dst_reg) | Rn(src_reg)); } -void host_arm64_FCVTZS_X_D(codeblock_t *block, int dst_reg, int src_reg) +void +host_arm64_FCVTZS_X_D(codeblock_t *block, int dst_reg, int src_reg) { - codegen_addlong(block, OPCODE_FCVTZS_X_D | Rd(dst_reg) | Rn(src_reg)); + codegen_addlong(block, OPCODE_FCVTZS_X_D | Rd(dst_reg) | Rn(src_reg)); } -void host_arm64_FCVTZS_V2S(codeblock_t *block, int dst_reg, int src_reg) +void +host_arm64_FCVTZS_V2S(codeblock_t *block, int dst_reg, int src_reg) { - codegen_addlong(block, OPCODE_FCVTZS_V2S | Rd(dst_reg) | Rn(src_reg)); + codegen_addlong(block, OPCODE_FCVTZS_V2S | Rd(dst_reg) | Rn(src_reg)); } -void host_arm64_FDIV_D(codeblock_t *block, int dst_reg, int src_n_reg, int src_m_reg) +void +host_arm64_FDIV_D(codeblock_t *block, int dst_reg, int src_n_reg, int src_m_reg) { - codegen_addlong(block, OPCODE_FDIV_D | Rd(dst_reg) | Rn(src_n_reg) | Rm(src_m_reg)); + codegen_addlong(block, OPCODE_FDIV_D | Rd(dst_reg) | Rn(src_n_reg) | Rm(src_m_reg)); } -void host_arm64_FDIV_S(codeblock_t *block, int dst_reg, int src_n_reg, int src_m_reg) +void +host_arm64_FDIV_S(codeblock_t *block, int dst_reg, int src_n_reg, int src_m_reg) { - codegen_addlong(block, OPCODE_FDIV_S | Rd(dst_reg) | Rn(src_n_reg) | Rm(src_m_reg)); + codegen_addlong(block, OPCODE_FDIV_S | Rd(dst_reg) | Rn(src_n_reg) | Rm(src_m_reg)); } -void host_arm64_FMAX_V2S(codeblock_t *block, int dst_reg, int src_n_reg, int src_m_reg) +void +host_arm64_FMAX_V2S(codeblock_t *block, int dst_reg, int src_n_reg, int src_m_reg) { - codegen_addlong(block, OPCODE_FMAX_V2S | Rd(dst_reg) | Rn(src_n_reg) | Rm(src_m_reg)); + codegen_addlong(block, OPCODE_FMAX_V2S | Rd(dst_reg) | Rn(src_n_reg) | Rm(src_m_reg)); } -void host_arm64_FMIN_V2S(codeblock_t *block, int dst_reg, int src_n_reg, int src_m_reg) +void +host_arm64_FMIN_V2S(codeblock_t *block, int dst_reg, int src_n_reg, int src_m_reg) { - codegen_addlong(block, OPCODE_FMIN_V2S | Rd(dst_reg) | Rn(src_n_reg) | Rm(src_m_reg)); + codegen_addlong(block, OPCODE_FMIN_V2S | Rd(dst_reg) | Rn(src_n_reg) | Rm(src_m_reg)); } -void host_arm64_FMUL_D(codeblock_t *block, int dst_reg, int src_n_reg, int src_m_reg) +void +host_arm64_FMUL_D(codeblock_t *block, int dst_reg, int src_n_reg, int src_m_reg) { - codegen_addlong(block, OPCODE_FMUL_D | Rd(dst_reg) | Rn(src_n_reg) | Rm(src_m_reg)); + codegen_addlong(block, OPCODE_FMUL_D | Rd(dst_reg) | Rn(src_n_reg) | Rm(src_m_reg)); } -void host_arm64_FMUL_V2S(codeblock_t *block, int dst_reg, int src_n_reg, int src_m_reg) +void +host_arm64_FMUL_V2S(codeblock_t *block, int dst_reg, int src_n_reg, int src_m_reg) { - codegen_addlong(block, OPCODE_FMUL_V2S | Rd(dst_reg) | Rn(src_n_reg) | Rm(src_m_reg)); + codegen_addlong(block, OPCODE_FMUL_V2S | Rd(dst_reg) | Rn(src_n_reg) | Rm(src_m_reg)); } -void host_arm64_FSUB_D(codeblock_t *block, int dst_reg, int src_n_reg, int src_m_reg) +void +host_arm64_FSUB_D(codeblock_t *block, int dst_reg, int src_n_reg, int src_m_reg) { - codegen_addlong(block, OPCODE_FSUB_D | Rd(dst_reg) | Rn(src_n_reg) | Rm(src_m_reg)); + codegen_addlong(block, OPCODE_FSUB_D | Rd(dst_reg) | Rn(src_n_reg) | Rm(src_m_reg)); } -void host_arm64_FSUB_V2S(codeblock_t *block, int dst_reg, int src_n_reg, int src_m_reg) +void +host_arm64_FSUB_V2S(codeblock_t *block, int dst_reg, int src_n_reg, int src_m_reg) { - codegen_addlong(block, OPCODE_FSUB_V2S | Rd(dst_reg) | Rn(src_n_reg) | Rm(src_m_reg)); + codegen_addlong(block, OPCODE_FSUB_V2S | Rd(dst_reg) | Rn(src_n_reg) | Rm(src_m_reg)); } -void host_arm64_FMOV_D_D(codeblock_t *block, int dst_reg, int src_reg) +void +host_arm64_FMOV_D_D(codeblock_t *block, int dst_reg, int src_reg) { - codegen_addlong(block, OPCODE_FMOV_D_D | Rd(dst_reg) | Rn(src_reg)); + codegen_addlong(block, OPCODE_FMOV_D_D | Rd(dst_reg) | Rn(src_reg)); } -void host_arm64_FMOV_D_Q(codeblock_t *block, int dst_reg, int src_reg) +void +host_arm64_FMOV_D_Q(codeblock_t *block, int dst_reg, int src_reg) { - codegen_addlong(block, OPCODE_FMOV_D_Q | Rd(dst_reg) | Rn(src_reg)); + codegen_addlong(block, OPCODE_FMOV_D_Q | Rd(dst_reg) | Rn(src_reg)); } -void host_arm64_FMOV_Q_D(codeblock_t *block, int dst_reg, int src_reg) +void +host_arm64_FMOV_Q_D(codeblock_t *block, int dst_reg, int src_reg) { - codegen_addlong(block, OPCODE_FMOV_Q_D | Rd(dst_reg) | Rn(src_reg)); + codegen_addlong(block, OPCODE_FMOV_Q_D | Rd(dst_reg) | Rn(src_reg)); } -void host_arm64_FMOV_S_W(codeblock_t *block, int dst_reg, int src_reg) +void +host_arm64_FMOV_S_W(codeblock_t *block, int dst_reg, int src_reg) { - codegen_addlong(block, OPCODE_FMOV_S_W | Rd(dst_reg) | Rn(src_reg)); + codegen_addlong(block, OPCODE_FMOV_S_W | Rd(dst_reg) | Rn(src_reg)); } -void host_arm64_FMOV_W_S(codeblock_t *block, int dst_reg, int src_reg) +void +host_arm64_FMOV_W_S(codeblock_t *block, int dst_reg, int src_reg) { - codegen_addlong(block, OPCODE_FMOV_W_S | Rd(dst_reg) | Rn(src_reg)); + codegen_addlong(block, OPCODE_FMOV_W_S | Rd(dst_reg) | Rn(src_reg)); } -void host_arm64_FMOV_S_ONE(codeblock_t *block, int dst_reg) +void +host_arm64_FMOV_S_ONE(codeblock_t *block, int dst_reg) { - codegen_addlong(block, OPCODE_FMOV_S_ONE | Rd(dst_reg)); + codegen_addlong(block, OPCODE_FMOV_S_ONE | Rd(dst_reg)); } -void host_arm64_FNEG_D(codeblock_t *block, int dst_reg, int src_reg) +void +host_arm64_FNEG_D(codeblock_t *block, int dst_reg, int src_reg) { - codegen_addlong(block, OPCODE_FNEG_D | Rd(dst_reg) | Rn(src_reg)); + codegen_addlong(block, OPCODE_FNEG_D | Rd(dst_reg) | Rn(src_reg)); } -void host_arm64_FRINTX_D(codeblock_t *block, int dst_reg, int src_reg) +void +host_arm64_FRINTX_D(codeblock_t *block, int dst_reg, int src_reg) { - codegen_addlong(block, OPCODE_FRINTX_D | Rd(dst_reg) | Rn(src_reg)); + codegen_addlong(block, OPCODE_FRINTX_D | Rd(dst_reg) | Rn(src_reg)); } -void host_arm64_FSQRT_D(codeblock_t *block, int dst_reg, int src_reg) +void +host_arm64_FSQRT_D(codeblock_t *block, int dst_reg, int src_reg) { - codegen_addlong(block, OPCODE_FSQRT_D | Rd(dst_reg) | Rn(src_reg)); + codegen_addlong(block, OPCODE_FSQRT_D | Rd(dst_reg) | Rn(src_reg)); } -void host_arm64_FSQRT_S(codeblock_t *block, int dst_reg, int src_reg) +void +host_arm64_FSQRT_S(codeblock_t *block, int dst_reg, int src_reg) { - codegen_addlong(block, OPCODE_FSQRT_S | Rd(dst_reg) | Rn(src_reg)); + codegen_addlong(block, OPCODE_FSQRT_S | Rd(dst_reg) | Rn(src_reg)); } -void host_arm64_LDP_POSTIDX_X(codeblock_t *block, int src_reg1, int src_reg2, int base_reg, int offset) +void +host_arm64_LDP_POSTIDX_X(codeblock_t *block, int src_reg1, int src_reg2, int base_reg, int offset) { - if (!in_range7_x(offset)) - fatal("host_arm64_LDP_POSTIDX out of range7 %i\n", offset); - codegen_addlong(block, OPCODE_LDP_POSTIDX_X | IMM7_X(offset) | Rn(base_reg) | Rt(src_reg1) | Rt2(src_reg2)); + if (!in_range7_x(offset)) + fatal("host_arm64_LDP_POSTIDX out of range7 %i\n", offset); + codegen_addlong(block, OPCODE_LDP_POSTIDX_X | IMM7_X(offset) | Rn(base_reg) | Rt(src_reg1) | Rt2(src_reg2)); } -void host_arm64_LDR_IMM_W(codeblock_t *block, int dest_reg, int base_reg, int offset) +void +host_arm64_LDR_IMM_W(codeblock_t *block, int dest_reg, int base_reg, int offset) { - if (!in_range12_w(offset)) - fatal("host_arm64_LDR_IMM_W out of range12 %i\n", offset); - codegen_addlong(block, OPCODE_LDR_IMM_W | OFFSET12_W(offset) | Rn(base_reg) | Rt(dest_reg)); + if (!in_range12_w(offset)) + fatal("host_arm64_LDR_IMM_W out of range12 %i\n", offset); + codegen_addlong(block, OPCODE_LDR_IMM_W | OFFSET12_W(offset) | Rn(base_reg) | Rt(dest_reg)); } -void host_arm64_LDR_IMM_X(codeblock_t *block, int dest_reg, int base_reg, int offset) +void +host_arm64_LDR_IMM_X(codeblock_t *block, int dest_reg, int base_reg, int offset) { - if (!in_range12_q(offset)) - fatal("host_arm64_LDR_IMM_X out of range12 %i\n", offset); - codegen_addlong(block, OPCODE_LDR_IMM_X | OFFSET12_Q(offset) | Rn(base_reg) | Rt(dest_reg)); + if (!in_range12_q(offset)) + fatal("host_arm64_LDR_IMM_X out of range12 %i\n", offset); + codegen_addlong(block, OPCODE_LDR_IMM_X | OFFSET12_Q(offset) | Rn(base_reg) | Rt(dest_reg)); } -void host_arm64_LDR_REG(codeblock_t *block, int dest_reg, int base_reg, int offset_reg) +void +host_arm64_LDR_REG(codeblock_t *block, int dest_reg, int base_reg, int offset_reg) { - codegen_addlong(block, OPCODE_LDR_REG | Rn(base_reg) | Rm(offset_reg) | Rt(dest_reg)); + codegen_addlong(block, OPCODE_LDR_REG | Rn(base_reg) | Rm(offset_reg) | Rt(dest_reg)); } -void host_arm64_LDR_REG_X(codeblock_t *block, int dest_reg, int base_reg, int offset_reg) +void +host_arm64_LDR_REG_X(codeblock_t *block, int dest_reg, int base_reg, int offset_reg) { - codegen_addlong(block, OPCODE_LDRX_REG | Rn(base_reg) | Rm(offset_reg) | Rt(dest_reg)); + codegen_addlong(block, OPCODE_LDRX_REG | Rn(base_reg) | Rm(offset_reg) | Rt(dest_reg)); } -void host_arm64_LDR_REG_F32(codeblock_t *block, int dest_reg, int base_reg, int offset_reg) +void +host_arm64_LDR_REG_F32(codeblock_t *block, int dest_reg, int base_reg, int offset_reg) { - codegen_addlong(block, OPCODE_LDR_REG_F32 | Rn(base_reg) | Rm(offset_reg) | Rt(dest_reg)); + codegen_addlong(block, OPCODE_LDR_REG_F32 | Rn(base_reg) | Rm(offset_reg) | Rt(dest_reg)); } -void host_arm64_LDR_IMM_F64(codeblock_t *block, int dest_reg, int base_reg, int offset) +void +host_arm64_LDR_IMM_F64(codeblock_t *block, int dest_reg, int base_reg, int offset) { - codegen_addlong(block, OPCODE_LDR_IMM_F64 | OFFSET12_Q(offset) | Rn(base_reg) | Rt(dest_reg)); + codegen_addlong(block, OPCODE_LDR_IMM_F64 | OFFSET12_Q(offset) | Rn(base_reg) | Rt(dest_reg)); } -void host_arm64_LDR_REG_F64(codeblock_t *block, int dest_reg, int base_reg, int offset_reg) +void +host_arm64_LDR_REG_F64(codeblock_t *block, int dest_reg, int base_reg, int offset_reg) { - codegen_addlong(block, OPCODE_LDR_REG_F64 | Rn(base_reg) | Rm(offset_reg) | Rt(dest_reg)); + codegen_addlong(block, OPCODE_LDR_REG_F64 | Rn(base_reg) | Rm(offset_reg) | Rt(dest_reg)); } -void host_arm64_LDR_REG_F64_S(codeblock_t *block, int dest_reg, int base_reg, int offset_reg) +void +host_arm64_LDR_REG_F64_S(codeblock_t *block, int dest_reg, int base_reg, int offset_reg) { - codegen_addlong(block, OPCODE_LDR_REG_F64_S | Rn(base_reg) | Rm(offset_reg) | Rt(dest_reg)); + codegen_addlong(block, OPCODE_LDR_REG_F64_S | Rn(base_reg) | Rm(offset_reg) | Rt(dest_reg)); } -void host_arm64_LDRB_IMM_W(codeblock_t *block, int dest_reg, int base_reg, int offset) +void +host_arm64_LDRB_IMM_W(codeblock_t *block, int dest_reg, int base_reg, int offset) { - if (!in_range12_b(offset)) - fatal("host_arm64_LDRB_IMM_W out of range12 %i\n", offset); - codegen_addlong(block, OPCODE_LDRB_IMM_W | OFFSET12_B(offset) | Rn(base_reg) | Rt(dest_reg)); + if (!in_range12_b(offset)) + fatal("host_arm64_LDRB_IMM_W out of range12 %i\n", offset); + codegen_addlong(block, OPCODE_LDRB_IMM_W | OFFSET12_B(offset) | Rn(base_reg) | Rt(dest_reg)); } -void host_arm64_LDRB_REG(codeblock_t *block, int dest_reg, int base_reg, int offset_reg) +void +host_arm64_LDRB_REG(codeblock_t *block, int dest_reg, int base_reg, int offset_reg) { - codegen_addlong(block, OPCODE_LDRB_REG | Rn(base_reg) | Rm(offset_reg) | Rt(dest_reg)); + codegen_addlong(block, OPCODE_LDRB_REG | Rn(base_reg) | Rm(offset_reg) | Rt(dest_reg)); } -void host_arm64_LDRH_IMM(codeblock_t *block, int dest_reg, int base_reg, int offset) +void +host_arm64_LDRH_IMM(codeblock_t *block, int dest_reg, int base_reg, int offset) { - if (!in_range12_h(offset)) - fatal("host_arm64_LDRH_IMM out of range12 %i\n", offset); - codegen_addlong(block, OPCODE_LDRH_IMM | OFFSET12_H(offset) | Rn(base_reg) | Rt(dest_reg)); + if (!in_range12_h(offset)) + fatal("host_arm64_LDRH_IMM out of range12 %i\n", offset); + codegen_addlong(block, OPCODE_LDRH_IMM | OFFSET12_H(offset) | Rn(base_reg) | Rt(dest_reg)); } -void host_arm64_LDRH_REG(codeblock_t *block, int dest_reg, int base_reg, int offset_reg) +void +host_arm64_LDRH_REG(codeblock_t *block, int dest_reg, int base_reg, int offset_reg) { - codegen_addlong(block, OPCODE_LDRH_REG | Rn(base_reg) | Rm(offset_reg) | Rt(dest_reg)); + codegen_addlong(block, OPCODE_LDRH_REG | Rn(base_reg) | Rm(offset_reg) | Rt(dest_reg)); } -void host_arm64_LDRX_REG_LSL3(codeblock_t *block, int dest_reg, int base_reg, int offset_reg) +void +host_arm64_LDRX_REG_LSL3(codeblock_t *block, int dest_reg, int base_reg, int offset_reg) { - codegen_addlong(block, OPCODE_LDRX_REG_LSL3 | Rn(base_reg) | Rm(offset_reg) | Rt(dest_reg)); + codegen_addlong(block, OPCODE_LDRX_REG_LSL3 | Rn(base_reg) | Rm(offset_reg) | Rt(dest_reg)); } -void host_arm64_LSL(codeblock_t *block, int dst_reg, int src_n_reg, int shift_reg) +void +host_arm64_LSL(codeblock_t *block, int dst_reg, int src_n_reg, int shift_reg) { - codegen_addlong(block, OPCODE_LSL | Rd(dst_reg) | Rn(src_n_reg) | Rm(shift_reg)); + codegen_addlong(block, OPCODE_LSL | Rd(dst_reg) | Rn(src_n_reg) | Rm(shift_reg)); } -void host_arm64_LSR(codeblock_t *block, int dst_reg, int src_n_reg, int shift_reg) +void +host_arm64_LSR(codeblock_t *block, int dst_reg, int src_n_reg, int shift_reg) { - codegen_addlong(block, OPCODE_LSR | Rd(dst_reg) | Rn(src_n_reg) | Rm(shift_reg)); + codegen_addlong(block, OPCODE_LSR | Rd(dst_reg) | Rn(src_n_reg) | Rm(shift_reg)); } -void host_arm64_MOV_REG_ASR(codeblock_t *block, int dst_reg, int src_m_reg, int shift) +void +host_arm64_MOV_REG_ASR(codeblock_t *block, int dst_reg, int src_m_reg, int shift) { - codegen_addlong(block, OPCODE_ORR_ASR | Rd(dst_reg) | Rn(REG_WZR) | Rm(src_m_reg) | DATPROC_SHIFT(shift)); + codegen_addlong(block, OPCODE_ORR_ASR | Rd(dst_reg) | Rn(REG_WZR) | Rm(src_m_reg) | DATPROC_SHIFT(shift)); } -void host_arm64_MOV_REG(codeblock_t *block, int dst_reg, int src_m_reg, int shift) +void +host_arm64_MOV_REG(codeblock_t *block, int dst_reg, int src_m_reg, int shift) { - if (dst_reg != src_m_reg || shift) - codegen_addlong(block, OPCODE_ORR_LSL | Rd(dst_reg) | Rn(REG_WZR) | Rm(src_m_reg) | DATPROC_SHIFT(shift)); + if (dst_reg != src_m_reg || shift) + codegen_addlong(block, OPCODE_ORR_LSL | Rd(dst_reg) | Rn(REG_WZR) | Rm(src_m_reg) | DATPROC_SHIFT(shift)); } -void host_arm64_MOV_REG_LSR(codeblock_t *block, int dst_reg, int src_m_reg, int shift) +void +host_arm64_MOV_REG_LSR(codeblock_t *block, int dst_reg, int src_m_reg, int shift) { - codegen_addlong(block, OPCODE_ORR_LSR | Rd(dst_reg) | Rn(REG_WZR) | Rm(src_m_reg) | DATPROC_SHIFT(shift)); + codegen_addlong(block, OPCODE_ORR_LSR | Rd(dst_reg) | Rn(REG_WZR) | Rm(src_m_reg) | DATPROC_SHIFT(shift)); } -void host_arm64_MOV_REG_ROR(codeblock_t *block, int dst_reg, int src_m_reg, int shift) +void +host_arm64_MOV_REG_ROR(codeblock_t *block, int dst_reg, int src_m_reg, int shift) { - codegen_addlong(block, OPCODE_ORR_ROR | Rd(dst_reg) | Rn(REG_WZR) | Rm(src_m_reg) | DATPROC_SHIFT(shift)); + codegen_addlong(block, OPCODE_ORR_ROR | Rd(dst_reg) | Rn(REG_WZR) | Rm(src_m_reg) | DATPROC_SHIFT(shift)); } -void host_arm64_MOVX_IMM(codeblock_t *block, int reg, uint64_t imm_data) +void +host_arm64_MOVX_IMM(codeblock_t *block, int reg, uint64_t imm_data) { - codegen_addlong(block, OPCODE_MOVZ_X | MOV_WIDE_HW(0) | IMM16(imm_data & 0xffff) | Rd(reg)); - if ((imm_data >> 16) & 0xffff) - codegen_addlong(block, OPCODE_MOVK_X | MOV_WIDE_HW(1) | IMM16((imm_data >> 16) & 0xffff) | Rd(reg)); - if ((imm_data >> 32) & 0xffff) - codegen_addlong(block, OPCODE_MOVK_X | MOV_WIDE_HW(2) | IMM16((imm_data >> 32) & 0xffff) | Rd(reg)); - if ((imm_data >> 48) & 0xffff) - codegen_addlong(block, OPCODE_MOVK_X | MOV_WIDE_HW(3) | IMM16((imm_data >> 48) & 0xffff) | Rd(reg)); + codegen_addlong(block, OPCODE_MOVZ_X | MOV_WIDE_HW(0) | IMM16(imm_data & 0xffff) | Rd(reg)); + if ((imm_data >> 16) & 0xffff) + codegen_addlong(block, OPCODE_MOVK_X | MOV_WIDE_HW(1) | IMM16((imm_data >> 16) & 0xffff) | Rd(reg)); + if ((imm_data >> 32) & 0xffff) + codegen_addlong(block, OPCODE_MOVK_X | MOV_WIDE_HW(2) | IMM16((imm_data >> 32) & 0xffff) | Rd(reg)); + if ((imm_data >> 48) & 0xffff) + codegen_addlong(block, OPCODE_MOVK_X | MOV_WIDE_HW(3) | IMM16((imm_data >> 48) & 0xffff) | Rd(reg)); } -void host_arm64_MOVX_REG(codeblock_t *block, int dst_reg, int src_m_reg, int shift) +void +host_arm64_MOVX_REG(codeblock_t *block, int dst_reg, int src_m_reg, int shift) { - if (dst_reg != src_m_reg) - codegen_addlong(block, OPCODE_ORRX_LSL | Rd(dst_reg) | Rn(REG_XZR) | Rm(src_m_reg) | DATPROC_SHIFT(shift)); + if (dst_reg != src_m_reg) + codegen_addlong(block, OPCODE_ORRX_LSL | Rd(dst_reg) | Rn(REG_XZR) | Rm(src_m_reg) | DATPROC_SHIFT(shift)); } -void host_arm64_MOVZ_IMM(codeblock_t *block, int reg, uint32_t imm_data) +void +host_arm64_MOVZ_IMM(codeblock_t *block, int reg, uint32_t imm_data) { - int hw; + int hw; - if (!imm_is_imm16(imm_data)) - fatal("MOVZ_IMM - imm not representable %08x\n", imm_data); + if (!imm_is_imm16(imm_data)) + fatal("MOVZ_IMM - imm not representable %08x\n", imm_data); - hw = (imm_data & 0xffff0000) ? 1 : 0; - if (hw) - imm_data >>= 16; + hw = (imm_data & 0xffff0000) ? 1 : 0; + if (hw) + imm_data >>= 16; - codegen_addlong(block, OPCODE_MOVZ_W | MOV_WIDE_HW(hw) | IMM16(imm_data) | Rd(reg)); + codegen_addlong(block, OPCODE_MOVZ_W | MOV_WIDE_HW(hw) | IMM16(imm_data) | Rd(reg)); } -void host_arm64_MOVK_IMM(codeblock_t *block, int reg, uint32_t imm_data) +void +host_arm64_MOVK_IMM(codeblock_t *block, int reg, uint32_t imm_data) { - int hw; + int hw; - if (!imm_is_imm16(imm_data)) - fatal("MOVK_IMM - imm not representable %08x\n", imm_data); + if (!imm_is_imm16(imm_data)) + fatal("MOVK_IMM - imm not representable %08x\n", imm_data); - hw = (imm_data & 0xffff0000) ? 1 : 0; - if (hw) - imm_data >>= 16; + hw = (imm_data & 0xffff0000) ? 1 : 0; + if (hw) + imm_data >>= 16; - codegen_addlong(block, OPCODE_MOVK_W | MOV_WIDE_HW(hw) | IMM16(imm_data) | Rd(reg)); + codegen_addlong(block, OPCODE_MOVK_W | MOV_WIDE_HW(hw) | IMM16(imm_data) | Rd(reg)); } -void host_arm64_MSR_FPCR(codeblock_t *block, int src_reg) +void +host_arm64_MSR_FPCR(codeblock_t *block, int src_reg) { - codegen_addlong(block, OPCODE_MSR_FPCR | Rd(src_reg)); + codegen_addlong(block, OPCODE_MSR_FPCR | Rd(src_reg)); } -void host_arm64_MUL_V4H(codeblock_t *block, int dst_reg, int src_n_reg, int src_m_reg) +void +host_arm64_MUL_V4H(codeblock_t *block, int dst_reg, int src_n_reg, int src_m_reg) { - codegen_addlong(block, OPCODE_MUL_V4H | Rd(dst_reg) | Rn(src_n_reg) | Rm(src_m_reg)); + codegen_addlong(block, OPCODE_MUL_V4H | Rd(dst_reg) | Rn(src_n_reg) | Rm(src_m_reg)); } -void host_arm64_NOP(codeblock_t *block) +void +host_arm64_NOP(codeblock_t *block) { - codegen_addlong(block, OPCODE_NOP); + codegen_addlong(block, OPCODE_NOP); } -void host_arm64_ORR_IMM(codeblock_t *block, int dst_reg, int src_n_reg, uint32_t imm_data) +void +host_arm64_ORR_IMM(codeblock_t *block, int dst_reg, int src_n_reg, uint32_t imm_data) { - uint32_t imm_encoding = host_arm64_find_imm(imm_data); + uint32_t imm_encoding = host_arm64_find_imm(imm_data); - if (imm_encoding) - { - codegen_addlong(block, OPCODE_ORR_IMM | Rd(dst_reg) | Rn(src_n_reg) | IMM_LOGICAL(imm_encoding)); - } - else - { - host_arm64_mov_imm(block, REG_W16, imm_data); - codegen_addlong(block, OPCODE_ORR_LSL | Rd(dst_reg) | Rn(src_n_reg) | Rm(REG_W16) | DATPROC_SHIFT(0)); - } + if (imm_encoding) { + codegen_addlong(block, OPCODE_ORR_IMM | Rd(dst_reg) | Rn(src_n_reg) | IMM_LOGICAL(imm_encoding)); + } else { + host_arm64_mov_imm(block, REG_W16, imm_data); + codegen_addlong(block, OPCODE_ORR_LSL | Rd(dst_reg) | Rn(src_n_reg) | Rm(REG_W16) | DATPROC_SHIFT(0)); + } } -void host_arm64_ORR_REG(codeblock_t *block, int dst_reg, int src_n_reg, int src_m_reg, int shift) +void +host_arm64_ORR_REG(codeblock_t *block, int dst_reg, int src_n_reg, int src_m_reg, int shift) { - codegen_addlong(block, OPCODE_ORR_LSL | Rd(dst_reg) | Rn(src_n_reg) | Rm(src_m_reg) | DATPROC_SHIFT(shift)); + codegen_addlong(block, OPCODE_ORR_LSL | Rd(dst_reg) | Rn(src_n_reg) | Rm(src_m_reg) | DATPROC_SHIFT(shift)); } -void host_arm64_ORR_REG_V(codeblock_t *block, int dst_reg, int src_n_reg, int src_m_reg) +void +host_arm64_ORR_REG_V(codeblock_t *block, int dst_reg, int src_n_reg, int src_m_reg) { - codegen_addlong(block, OPCODE_ORR_V | Rd(dst_reg) | Rn(src_n_reg) | Rm(src_m_reg)); + codegen_addlong(block, OPCODE_ORR_V | Rd(dst_reg) | Rn(src_n_reg) | Rm(src_m_reg)); } -void host_arm64_RET(codeblock_t *block, int reg) +void +host_arm64_RET(codeblock_t *block, int reg) { - codegen_addlong(block, OPCODE_RET | Rn(reg)); + codegen_addlong(block, OPCODE_RET | Rn(reg)); } -void host_arm64_ROR(codeblock_t *block, int dst_reg, int src_n_reg, int shift_reg) +void +host_arm64_ROR(codeblock_t *block, int dst_reg, int src_n_reg, int shift_reg) { - codegen_addlong(block, OPCODE_ROR | Rd(dst_reg) | Rn(src_n_reg) | Rm(shift_reg)); + codegen_addlong(block, OPCODE_ROR | Rd(dst_reg) | Rn(src_n_reg) | Rm(shift_reg)); } -void host_arm64_SADDLP_V2S_4H(codeblock_t *block, int dst_reg, int src_n_reg) +void +host_arm64_SADDLP_V2S_4H(codeblock_t *block, int dst_reg, int src_n_reg) { - codegen_addlong(block, OPCODE_SADDLP_V2S_4H | Rd(dst_reg) | Rn(src_n_reg)); + codegen_addlong(block, OPCODE_SADDLP_V2S_4H | Rd(dst_reg) | Rn(src_n_reg)); } -void host_arm64_SBFX(codeblock_t *block, int dst_reg, int src_reg, int lsb, int width) +void +host_arm64_SBFX(codeblock_t *block, int dst_reg, int src_reg, int lsb, int width) { - codegen_addlong(block, OPCODE_SBFX | Rd(dst_reg) | Rn(src_reg) | IMMN(0) | IMMR(lsb) | IMMS((lsb+width-1) & 31)); + codegen_addlong(block, OPCODE_SBFX | Rd(dst_reg) | Rn(src_reg) | IMMN(0) | IMMR(lsb) | IMMS((lsb + width - 1) & 31)); } -void host_arm64_SCVTF_D_Q(codeblock_t *block, int dst_reg, int src_reg) +void +host_arm64_SCVTF_D_Q(codeblock_t *block, int dst_reg, int src_reg) { - codegen_addlong(block, OPCODE_SCVTF_D_Q | Rd(dst_reg) | Rn(src_reg)); + codegen_addlong(block, OPCODE_SCVTF_D_Q | Rd(dst_reg) | Rn(src_reg)); } -void host_arm64_SCVTF_D_W(codeblock_t *block, int dst_reg, int src_reg) +void +host_arm64_SCVTF_D_W(codeblock_t *block, int dst_reg, int src_reg) { - codegen_addlong(block, OPCODE_SCVTF_D_W | Rd(dst_reg) | Rn(src_reg)); + codegen_addlong(block, OPCODE_SCVTF_D_W | Rd(dst_reg) | Rn(src_reg)); } -void host_arm64_SCVTF_V2S(codeblock_t *block, int dst_reg, int src_reg) +void +host_arm64_SCVTF_V2S(codeblock_t *block, int dst_reg, int src_reg) { - codegen_addlong(block, OPCODE_SCVTF_V2S | Rd(dst_reg) | Rn(src_reg)); + codegen_addlong(block, OPCODE_SCVTF_V2S | Rd(dst_reg) | Rn(src_reg)); } -void host_arm64_SHRN_V4H_4S(codeblock_t *block, int dst_reg, int src_n_reg, int shift) +void +host_arm64_SHRN_V4H_4S(codeblock_t *block, int dst_reg, int src_n_reg, int shift) { - if (shift > 16) - fatal("host_arm64_SHRN_V4H_4S : shift > 16\n"); - codegen_addlong(block, OPCODE_SHRN | Rd(dst_reg) | Rn(src_n_reg) | SHRN_SHIFT_IMM_V4S(16-shift)); + if (shift > 16) + fatal("host_arm64_SHRN_V4H_4S : shift > 16\n"); + codegen_addlong(block, OPCODE_SHRN | Rd(dst_reg) | Rn(src_n_reg) | SHRN_SHIFT_IMM_V4S(16 - shift)); } -void host_arm64_SMULL_V4S_4H(codeblock_t *block, int dst_reg, int src_n_reg, int src_m_reg) +void +host_arm64_SMULL_V4S_4H(codeblock_t *block, int dst_reg, int src_n_reg, int src_m_reg) { - codegen_addlong(block, OPCODE_SMULL_V4S_4H | Rd(dst_reg) | Rn(src_n_reg) | Rm(src_m_reg)); + codegen_addlong(block, OPCODE_SMULL_V4S_4H | Rd(dst_reg) | Rn(src_n_reg) | Rm(src_m_reg)); } -void host_arm64_SQADD_V8B(codeblock_t *block, int dst_reg, int src_n_reg, int src_m_reg) +void +host_arm64_SQADD_V8B(codeblock_t *block, int dst_reg, int src_n_reg, int src_m_reg) { - codegen_addlong(block, OPCODE_SQADD_V8B | Rd(dst_reg) | Rn(src_n_reg) | Rm(src_m_reg)); + codegen_addlong(block, OPCODE_SQADD_V8B | Rd(dst_reg) | Rn(src_n_reg) | Rm(src_m_reg)); } -void host_arm64_SQADD_V4H(codeblock_t *block, int dst_reg, int src_n_reg, int src_m_reg) +void +host_arm64_SQADD_V4H(codeblock_t *block, int dst_reg, int src_n_reg, int src_m_reg) { - codegen_addlong(block, OPCODE_SQADD_V4H | Rd(dst_reg) | Rn(src_n_reg) | Rm(src_m_reg)); + codegen_addlong(block, OPCODE_SQADD_V4H | Rd(dst_reg) | Rn(src_n_reg) | Rm(src_m_reg)); } -void host_arm64_SQSUB_V8B(codeblock_t *block, int dst_reg, int src_n_reg, int src_m_reg) +void +host_arm64_SQSUB_V8B(codeblock_t *block, int dst_reg, int src_n_reg, int src_m_reg) { - codegen_addlong(block, OPCODE_SQSUB_V8B | Rd(dst_reg) | Rn(src_n_reg) | Rm(src_m_reg)); + codegen_addlong(block, OPCODE_SQSUB_V8B | Rd(dst_reg) | Rn(src_n_reg) | Rm(src_m_reg)); } -void host_arm64_SQSUB_V4H(codeblock_t *block, int dst_reg, int src_n_reg, int src_m_reg) +void +host_arm64_SQSUB_V4H(codeblock_t *block, int dst_reg, int src_n_reg, int src_m_reg) { - codegen_addlong(block, OPCODE_SQSUB_V4H | Rd(dst_reg) | Rn(src_n_reg) | Rm(src_m_reg)); + codegen_addlong(block, OPCODE_SQSUB_V4H | Rd(dst_reg) | Rn(src_n_reg) | Rm(src_m_reg)); } -void host_arm64_SQXTN_V8B_8H(codeblock_t *block, int dst_reg, int src_reg) +void +host_arm64_SQXTN_V8B_8H(codeblock_t *block, int dst_reg, int src_reg) { - codegen_addlong(block, OPCODE_SQXTN_V8B_8H | Rd(dst_reg) | Rn(src_reg)); + codegen_addlong(block, OPCODE_SQXTN_V8B_8H | Rd(dst_reg) | Rn(src_reg)); } -void host_arm64_SQXTN_V4H_4S(codeblock_t *block, int dst_reg, int src_reg) +void +host_arm64_SQXTN_V4H_4S(codeblock_t *block, int dst_reg, int src_reg) { - codegen_addlong(block, OPCODE_SQXTN_V4H_4S | Rd(dst_reg) | Rn(src_reg)); + codegen_addlong(block, OPCODE_SQXTN_V4H_4S | Rd(dst_reg) | Rn(src_reg)); } -void host_arm64_SHL_V4H(codeblock_t *block, int dst_reg, int src_n_reg, int shift) +void +host_arm64_SHL_V4H(codeblock_t *block, int dst_reg, int src_n_reg, int shift) { - codegen_addlong(block, OPCODE_SHL_VD | Rd(dst_reg) | Rn(src_n_reg) | SHIFT_IMM_V4H(shift)); + codegen_addlong(block, OPCODE_SHL_VD | Rd(dst_reg) | Rn(src_n_reg) | SHIFT_IMM_V4H(shift)); } -void host_arm64_SHL_V2S(codeblock_t *block, int dst_reg, int src_n_reg, int shift) +void +host_arm64_SHL_V2S(codeblock_t *block, int dst_reg, int src_n_reg, int shift) { - codegen_addlong(block, OPCODE_SHL_VD | Rd(dst_reg) | Rn(src_n_reg) | SHIFT_IMM_V2S(shift)); + codegen_addlong(block, OPCODE_SHL_VD | Rd(dst_reg) | Rn(src_n_reg) | SHIFT_IMM_V2S(shift)); } -void host_arm64_SHL_V2D(codeblock_t *block, int dst_reg, int src_n_reg, int shift) +void +host_arm64_SHL_V2D(codeblock_t *block, int dst_reg, int src_n_reg, int shift) { - codegen_addlong(block, OPCODE_SHL_VQ | Rd(dst_reg) | Rn(src_n_reg) | SHIFT_IMM_V2D(shift)); + codegen_addlong(block, OPCODE_SHL_VQ | Rd(dst_reg) | Rn(src_n_reg) | SHIFT_IMM_V2D(shift)); } -void host_arm64_SSHR_V4H(codeblock_t *block, int dst_reg, int src_n_reg, int shift) +void +host_arm64_SSHR_V4H(codeblock_t *block, int dst_reg, int src_n_reg, int shift) { - if (shift > 16) - fatal("host_arm_USHR_V4H : shift > 16\n"); - codegen_addlong(block, OPCODE_SSHR_VD | Rd(dst_reg) | Rn(src_n_reg) | SHIFT_IMM_V4H(16-shift)); + if (shift > 16) + fatal("host_arm_USHR_V4H : shift > 16\n"); + codegen_addlong(block, OPCODE_SSHR_VD | Rd(dst_reg) | Rn(src_n_reg) | SHIFT_IMM_V4H(16 - shift)); } -void host_arm64_SSHR_V2S(codeblock_t *block, int dst_reg, int src_n_reg, int shift) +void +host_arm64_SSHR_V2S(codeblock_t *block, int dst_reg, int src_n_reg, int shift) { - if (shift > 32) - fatal("host_arm_SSHR_V2S : shift > 32\n"); - codegen_addlong(block, OPCODE_SSHR_VD | Rd(dst_reg) | Rn(src_n_reg) | SHIFT_IMM_V2S(32-shift)); + if (shift > 32) + fatal("host_arm_SSHR_V2S : shift > 32\n"); + codegen_addlong(block, OPCODE_SSHR_VD | Rd(dst_reg) | Rn(src_n_reg) | SHIFT_IMM_V2S(32 - shift)); } -void host_arm64_SSHR_V2D(codeblock_t *block, int dst_reg, int src_n_reg, int shift) +void +host_arm64_SSHR_V2D(codeblock_t *block, int dst_reg, int src_n_reg, int shift) { - if (shift > 64) - fatal("host_arm_SSHR_V2D : shift > 64\n"); - codegen_addlong(block, OPCODE_SSHR_VQ | Rd(dst_reg) | Rn(src_n_reg) | SHIFT_IMM_V2D(64-shift)); + if (shift > 64) + fatal("host_arm_SSHR_V2D : shift > 64\n"); + codegen_addlong(block, OPCODE_SSHR_VQ | Rd(dst_reg) | Rn(src_n_reg) | SHIFT_IMM_V2D(64 - shift)); } -void host_arm64_STP_PREIDX_X(codeblock_t *block, int src_reg1, int src_reg2, int base_reg, int offset) +void +host_arm64_STP_PREIDX_X(codeblock_t *block, int src_reg1, int src_reg2, int base_reg, int offset) { - if (!in_range7_x(offset)) - fatal("host_arm64_STP_PREIDX out of range7 %i\n", offset); - codegen_addlong(block, OPCODE_STP_PREIDX_X | IMM7_X(offset) | Rn(base_reg) | Rt(src_reg1) | Rt2(src_reg2)); + if (!in_range7_x(offset)) + fatal("host_arm64_STP_PREIDX out of range7 %i\n", offset); + codegen_addlong(block, OPCODE_STP_PREIDX_X | IMM7_X(offset) | Rn(base_reg) | Rt(src_reg1) | Rt2(src_reg2)); } -void host_arm64_STR_IMM_W(codeblock_t *block, int dest_reg, int base_reg, int offset) +void +host_arm64_STR_IMM_W(codeblock_t *block, int dest_reg, int base_reg, int offset) { - if (!in_range12_w(offset)) - fatal("host_arm64_STR_IMM_W out of range12 %i\n", offset); - codegen_addlong(block, OPCODE_STR_IMM_W | OFFSET12_W(offset) | Rn(base_reg) | Rt(dest_reg)); + if (!in_range12_w(offset)) + fatal("host_arm64_STR_IMM_W out of range12 %i\n", offset); + codegen_addlong(block, OPCODE_STR_IMM_W | OFFSET12_W(offset) | Rn(base_reg) | Rt(dest_reg)); } -void host_arm64_STR_IMM_Q(codeblock_t *block, int dest_reg, int base_reg, int offset) +void +host_arm64_STR_IMM_Q(codeblock_t *block, int dest_reg, int base_reg, int offset) { - if (!in_range12_q(offset)) - fatal("host_arm64_STR_IMM_W out of range12 %i\n", offset); - codegen_addlong(block, OPCODE_STR_IMM_Q | OFFSET12_Q(offset) | Rn(base_reg) | Rt(dest_reg)); + if (!in_range12_q(offset)) + fatal("host_arm64_STR_IMM_W out of range12 %i\n", offset); + codegen_addlong(block, OPCODE_STR_IMM_Q | OFFSET12_Q(offset) | Rn(base_reg) | Rt(dest_reg)); } -void host_arm64_STR_REG(codeblock_t *block, int src_reg, int base_reg, int offset_reg) +void +host_arm64_STR_REG(codeblock_t *block, int src_reg, int base_reg, int offset_reg) { - codegen_addlong(block, OPCODE_STR_REG | Rn(base_reg) | Rm(offset_reg) | Rt(src_reg)); + codegen_addlong(block, OPCODE_STR_REG | Rn(base_reg) | Rm(offset_reg) | Rt(src_reg)); } -void host_arm64_STR_REG_F32(codeblock_t *block, int src_reg, int base_reg, int offset_reg) +void +host_arm64_STR_REG_F32(codeblock_t *block, int src_reg, int base_reg, int offset_reg) { - codegen_addlong(block, OPCODE_STR_REG_F32 | Rn(base_reg) | Rm(offset_reg) | Rt(src_reg)); + codegen_addlong(block, OPCODE_STR_REG_F32 | Rn(base_reg) | Rm(offset_reg) | Rt(src_reg)); } -void host_arm64_STR_IMM_F64(codeblock_t *block, int src_reg, int base_reg, int offset) +void +host_arm64_STR_IMM_F64(codeblock_t *block, int src_reg, int base_reg, int offset) { - codegen_addlong(block, OPCODE_STR_IMM_F64 | OFFSET12_Q(offset) | Rn(base_reg) | Rt(src_reg)); + codegen_addlong(block, OPCODE_STR_IMM_F64 | OFFSET12_Q(offset) | Rn(base_reg) | Rt(src_reg)); } -void host_arm64_STR_REG_F64(codeblock_t *block, int src_reg, int base_reg, int offset_reg) +void +host_arm64_STR_REG_F64(codeblock_t *block, int src_reg, int base_reg, int offset_reg) { - codegen_addlong(block, OPCODE_STR_REG_F64 | Rn(base_reg) | Rm(offset_reg) | Rt(src_reg)); + codegen_addlong(block, OPCODE_STR_REG_F64 | Rn(base_reg) | Rm(offset_reg) | Rt(src_reg)); } -void host_arm64_STR_REG_F64_S(codeblock_t *block, int src_reg, int base_reg, int offset_reg) +void +host_arm64_STR_REG_F64_S(codeblock_t *block, int src_reg, int base_reg, int offset_reg) { - codegen_addlong(block, OPCODE_STR_REG_F64_S | Rn(base_reg) | Rm(offset_reg) | Rt(src_reg)); + codegen_addlong(block, OPCODE_STR_REG_F64_S | Rn(base_reg) | Rm(offset_reg) | Rt(src_reg)); } -void host_arm64_STRB_IMM(codeblock_t *block, int dest_reg, int base_reg, int offset) +void +host_arm64_STRB_IMM(codeblock_t *block, int dest_reg, int base_reg, int offset) { - if (!in_range12_b(offset)) - fatal("host_arm64_STRB_IMM out of range12 %i\n", offset); - codegen_addlong(block, OPCODE_STRB_IMM | OFFSET12_B(offset) | Rn(base_reg) | Rt(dest_reg)); + if (!in_range12_b(offset)) + fatal("host_arm64_STRB_IMM out of range12 %i\n", offset); + codegen_addlong(block, OPCODE_STRB_IMM | OFFSET12_B(offset) | Rn(base_reg) | Rt(dest_reg)); } -void host_arm64_STRB_REG(codeblock_t *block, int src_reg, int base_reg, int offset_reg) +void +host_arm64_STRB_REG(codeblock_t *block, int src_reg, int base_reg, int offset_reg) { - codegen_addlong(block, OPCODE_STRB_REG | Rn(base_reg) | Rm(offset_reg) | Rt(src_reg)); + codegen_addlong(block, OPCODE_STRB_REG | Rn(base_reg) | Rm(offset_reg) | Rt(src_reg)); } -void host_arm64_STRH_IMM(codeblock_t *block, int dest_reg, int base_reg, int offset) +void +host_arm64_STRH_IMM(codeblock_t *block, int dest_reg, int base_reg, int offset) { - if (!in_range12_h(offset)) - fatal("host_arm64_STRH_IMM out of range12 %i\n", offset); - codegen_addlong(block, OPCODE_STRH_IMM | OFFSET12_H(offset) | Rn(base_reg) | Rt(dest_reg)); + if (!in_range12_h(offset)) + fatal("host_arm64_STRH_IMM out of range12 %i\n", offset); + codegen_addlong(block, OPCODE_STRH_IMM | OFFSET12_H(offset) | Rn(base_reg) | Rt(dest_reg)); } -void host_arm64_STRH_REG(codeblock_t *block, int src_reg, int base_reg, int offset_reg) +void +host_arm64_STRH_REG(codeblock_t *block, int src_reg, int base_reg, int offset_reg) { - codegen_addlong(block, OPCODE_STRH_REG | Rn(base_reg) | Rm(offset_reg) | Rt(src_reg)); + codegen_addlong(block, OPCODE_STRH_REG | Rn(base_reg) | Rm(offset_reg) | Rt(src_reg)); } -void host_arm64_SUB_IMM(codeblock_t *block, int dst_reg, int src_n_reg, uint32_t imm_data) +void +host_arm64_SUB_IMM(codeblock_t *block, int dst_reg, int src_n_reg, uint32_t imm_data) { - if (!imm_data) - host_arm64_MOV_REG(block, dst_reg, src_n_reg, 0); - else if ((int32_t)imm_data < 0 && imm_data != 0x80000000) - { - host_arm64_ADD_IMM(block, dst_reg, src_n_reg, -(int32_t)imm_data); - } - else if (!(imm_data & 0xff000000)) - { - if (imm_data & 0xfff) - { - codegen_addlong(block, OPCODE_SUB_IMM | Rd(dst_reg) | Rn(src_n_reg) | IMM12(imm_data & 0xfff) | DATPROC_IMM_SHIFT(0)); - if (imm_data & 0xfff000) - codegen_addlong(block, OPCODE_SUB_IMM | Rd(dst_reg) | Rn(dst_reg) | IMM12((imm_data >> 12) & 0xfff) | DATPROC_IMM_SHIFT(1)); - } - else if (imm_data & 0xfff000) - codegen_addlong(block, OPCODE_SUB_IMM | Rd(dst_reg) | Rn(src_n_reg) | IMM12((imm_data >> 12) & 0xfff) | DATPROC_IMM_SHIFT(1)); - } - else - { - host_arm64_MOVZ_IMM(block, REG_W16, imm_data & 0xffff); - host_arm64_MOVK_IMM(block, REG_W16, imm_data & 0xffff0000); - codegen_addlong(block, OPCODE_SUB_LSL | Rd(dst_reg) | Rn(src_n_reg) | Rm(REG_W16) | DATPROC_SHIFT(0)); - } + if (!imm_data) + host_arm64_MOV_REG(block, dst_reg, src_n_reg, 0); + else if ((int32_t) imm_data < 0 && imm_data != 0x80000000) { + host_arm64_ADD_IMM(block, dst_reg, src_n_reg, -(int32_t) imm_data); + } else if (!(imm_data & 0xff000000)) { + if (imm_data & 0xfff) { + codegen_addlong(block, OPCODE_SUB_IMM | Rd(dst_reg) | Rn(src_n_reg) | IMM12(imm_data & 0xfff) | DATPROC_IMM_SHIFT(0)); + if (imm_data & 0xfff000) + codegen_addlong(block, OPCODE_SUB_IMM | Rd(dst_reg) | Rn(dst_reg) | IMM12((imm_data >> 12) & 0xfff) | DATPROC_IMM_SHIFT(1)); + } else if (imm_data & 0xfff000) + codegen_addlong(block, OPCODE_SUB_IMM | Rd(dst_reg) | Rn(src_n_reg) | IMM12((imm_data >> 12) & 0xfff) | DATPROC_IMM_SHIFT(1)); + } else { + host_arm64_MOVZ_IMM(block, REG_W16, imm_data & 0xffff); + host_arm64_MOVK_IMM(block, REG_W16, imm_data & 0xffff0000); + codegen_addlong(block, OPCODE_SUB_LSL | Rd(dst_reg) | Rn(src_n_reg) | Rm(REG_W16) | DATPROC_SHIFT(0)); + } } -void host_arm64_SUB_REG(codeblock_t *block, int dst_reg, int src_n_reg, int src_m_reg, int shift) +void +host_arm64_SUB_REG(codeblock_t *block, int dst_reg, int src_n_reg, int src_m_reg, int shift) { - codegen_addlong(block, OPCODE_SUB_LSL | Rd(dst_reg) | Rn(src_n_reg) | Rm(src_m_reg) | DATPROC_SHIFT(shift)); + codegen_addlong(block, OPCODE_SUB_LSL | Rd(dst_reg) | Rn(src_n_reg) | Rm(src_m_reg) | DATPROC_SHIFT(shift)); } -void host_arm64_SUB_REG_LSR(codeblock_t *block, int dst_reg, int src_n_reg, int src_m_reg, int shift) +void +host_arm64_SUB_REG_LSR(codeblock_t *block, int dst_reg, int src_n_reg, int src_m_reg, int shift) { - codegen_addlong(block, OPCODE_SUB_LSR | Rd(dst_reg) | Rn(src_n_reg) | Rm(src_m_reg) | DATPROC_SHIFT(shift)); + codegen_addlong(block, OPCODE_SUB_LSR | Rd(dst_reg) | Rn(src_n_reg) | Rm(src_m_reg) | DATPROC_SHIFT(shift)); } -void host_arm64_SUB_V8B(codeblock_t *block, int dst_reg, int src_n_reg, int src_m_reg) +void +host_arm64_SUB_V8B(codeblock_t *block, int dst_reg, int src_n_reg, int src_m_reg) { - codegen_addlong(block, OPCODE_SUB_V8B | Rd(dst_reg) | Rn(src_n_reg) | Rm(src_m_reg)); + codegen_addlong(block, OPCODE_SUB_V8B | Rd(dst_reg) | Rn(src_n_reg) | Rm(src_m_reg)); } -void host_arm64_SUB_V4H(codeblock_t *block, int dst_reg, int src_n_reg, int src_m_reg) +void +host_arm64_SUB_V4H(codeblock_t *block, int dst_reg, int src_n_reg, int src_m_reg) { - codegen_addlong(block, OPCODE_SUB_V4H | Rd(dst_reg) | Rn(src_n_reg) | Rm(src_m_reg)); + codegen_addlong(block, OPCODE_SUB_V4H | Rd(dst_reg) | Rn(src_n_reg) | Rm(src_m_reg)); } -void host_arm64_SUB_V2S(codeblock_t *block, int dst_reg, int src_n_reg, int src_m_reg) +void +host_arm64_SUB_V2S(codeblock_t *block, int dst_reg, int src_n_reg, int src_m_reg) { - codegen_addlong(block, OPCODE_SUB_V2S | Rd(dst_reg) | Rn(src_n_reg) | Rm(src_m_reg)); + codegen_addlong(block, OPCODE_SUB_V2S | Rd(dst_reg) | Rn(src_n_reg) | Rm(src_m_reg)); } -uint32_t *host_arm64_TBNZ(codeblock_t *block, int reg, int bit) +uint32_t * +host_arm64_TBNZ(codeblock_t *block, int reg, int bit) { - codegen_alloc(block, 12); - codegen_addlong(block, OPCODE_TBZ | Rt(reg) | BIT_TBxZ(bit) | OFFSET14(8)); - codegen_addlong(block, OPCODE_B); - return (uint32_t *)&block_write_data[block_pos-4]; + codegen_alloc(block, 12); + codegen_addlong(block, OPCODE_TBZ | Rt(reg) | BIT_TBxZ(bit) | OFFSET14(8)); + codegen_addlong(block, OPCODE_B); + return (uint32_t *) &block_write_data[block_pos - 4]; } -void host_arm64_UBFX(codeblock_t *block, int dst_reg, int src_reg, int lsb, int width) +void +host_arm64_UBFX(codeblock_t *block, int dst_reg, int src_reg, int lsb, int width) { - codegen_addlong(block, OPCODE_UBFX | Rd(dst_reg) | Rn(src_reg) | IMMN(0) | IMMR(lsb) | IMMS((lsb+width-1) & 31)); + codegen_addlong(block, OPCODE_UBFX | Rd(dst_reg) | Rn(src_reg) | IMMN(0) | IMMR(lsb) | IMMS((lsb + width - 1) & 31)); } -void host_arm64_UQADD_V8B(codeblock_t *block, int dst_reg, int src_n_reg, int src_m_reg) +void +host_arm64_UQADD_V8B(codeblock_t *block, int dst_reg, int src_n_reg, int src_m_reg) { - codegen_addlong(block, OPCODE_UQADD_V8B | Rd(dst_reg) | Rn(src_n_reg) | Rm(src_m_reg)); + codegen_addlong(block, OPCODE_UQADD_V8B | Rd(dst_reg) | Rn(src_n_reg) | Rm(src_m_reg)); } -void host_arm64_UQADD_V4H(codeblock_t *block, int dst_reg, int src_n_reg, int src_m_reg) +void +host_arm64_UQADD_V4H(codeblock_t *block, int dst_reg, int src_n_reg, int src_m_reg) { - codegen_addlong(block, OPCODE_UQADD_V4H | Rd(dst_reg) | Rn(src_n_reg) | Rm(src_m_reg)); + codegen_addlong(block, OPCODE_UQADD_V4H | Rd(dst_reg) | Rn(src_n_reg) | Rm(src_m_reg)); } -void host_arm64_UQSUB_V8B(codeblock_t *block, int dst_reg, int src_n_reg, int src_m_reg) +void +host_arm64_UQSUB_V8B(codeblock_t *block, int dst_reg, int src_n_reg, int src_m_reg) { - codegen_addlong(block, OPCODE_UQSUB_V8B | Rd(dst_reg) | Rn(src_n_reg) | Rm(src_m_reg)); + codegen_addlong(block, OPCODE_UQSUB_V8B | Rd(dst_reg) | Rn(src_n_reg) | Rm(src_m_reg)); } -void host_arm64_UQSUB_V4H(codeblock_t *block, int dst_reg, int src_n_reg, int src_m_reg) +void +host_arm64_UQSUB_V4H(codeblock_t *block, int dst_reg, int src_n_reg, int src_m_reg) { - codegen_addlong(block, OPCODE_UQSUB_V4H | Rd(dst_reg) | Rn(src_n_reg) | Rm(src_m_reg)); + codegen_addlong(block, OPCODE_UQSUB_V4H | Rd(dst_reg) | Rn(src_n_reg) | Rm(src_m_reg)); } -void host_arm64_UQXTN_V8B_8H(codeblock_t *block, int dst_reg, int src_reg) +void +host_arm64_UQXTN_V8B_8H(codeblock_t *block, int dst_reg, int src_reg) { - codegen_addlong(block, OPCODE_UQXTN_V8B_8H | Rd(dst_reg) | Rn(src_reg)); + codegen_addlong(block, OPCODE_UQXTN_V8B_8H | Rd(dst_reg) | Rn(src_reg)); } -void host_arm64_UQXTN_V4H_4S(codeblock_t *block, int dst_reg, int src_reg) +void +host_arm64_UQXTN_V4H_4S(codeblock_t *block, int dst_reg, int src_reg) { - codegen_addlong(block, OPCODE_UQXTN_V4H_4S | Rd(dst_reg) | Rn(src_reg)); + codegen_addlong(block, OPCODE_UQXTN_V4H_4S | Rd(dst_reg) | Rn(src_reg)); } -void host_arm64_USHR_V4H(codeblock_t *block, int dst_reg, int src_n_reg, int shift) +void +host_arm64_USHR_V4H(codeblock_t *block, int dst_reg, int src_n_reg, int shift) { - if (shift > 16) - fatal("host_arm_USHR_V4H : shift > 16\n"); - codegen_addlong(block, OPCODE_USHR_VD | Rd(dst_reg) | Rn(src_n_reg) | SHIFT_IMM_V4H(16-shift)); + if (shift > 16) + fatal("host_arm_USHR_V4H : shift > 16\n"); + codegen_addlong(block, OPCODE_USHR_VD | Rd(dst_reg) | Rn(src_n_reg) | SHIFT_IMM_V4H(16 - shift)); } -void host_arm64_USHR_V2S(codeblock_t *block, int dst_reg, int src_n_reg, int shift) +void +host_arm64_USHR_V2S(codeblock_t *block, int dst_reg, int src_n_reg, int shift) { - if (shift > 32) - fatal("host_arm_USHR_V4S : shift > 32\n"); - codegen_addlong(block, OPCODE_USHR_VD | Rd(dst_reg) | Rn(src_n_reg) | SHIFT_IMM_V2S(32-shift)); + if (shift > 32) + fatal("host_arm_USHR_V4S : shift > 32\n"); + codegen_addlong(block, OPCODE_USHR_VD | Rd(dst_reg) | Rn(src_n_reg) | SHIFT_IMM_V2S(32 - shift)); } -void host_arm64_USHR_V2D(codeblock_t *block, int dst_reg, int src_n_reg, int shift) +void +host_arm64_USHR_V2D(codeblock_t *block, int dst_reg, int src_n_reg, int shift) { - if (shift > 64) - fatal("host_arm_USHR_V2D : shift > 64\n"); - codegen_addlong(block, OPCODE_USHR_VQ | Rd(dst_reg) | Rn(src_n_reg) | SHIFT_IMM_V2D(64-shift)); + if (shift > 64) + fatal("host_arm_USHR_V2D : shift > 64\n"); + codegen_addlong(block, OPCODE_USHR_VQ | Rd(dst_reg) | Rn(src_n_reg) | SHIFT_IMM_V2D(64 - shift)); } -void host_arm64_ZIP1_V8B(codeblock_t *block, int dst_reg, int src_n_reg, int src_m_reg) +void +host_arm64_ZIP1_V8B(codeblock_t *block, int dst_reg, int src_n_reg, int src_m_reg) { - codegen_addlong(block, OPCODE_ZIP1_V8B | Rd(dst_reg) | Rn(src_n_reg) | Rm(src_m_reg)); + codegen_addlong(block, OPCODE_ZIP1_V8B | Rd(dst_reg) | Rn(src_n_reg) | Rm(src_m_reg)); } -void host_arm64_ZIP1_V4H(codeblock_t *block, int dst_reg, int src_n_reg, int src_m_reg) +void +host_arm64_ZIP1_V4H(codeblock_t *block, int dst_reg, int src_n_reg, int src_m_reg) { - codegen_addlong(block, OPCODE_ZIP1_V4H | Rd(dst_reg) | Rn(src_n_reg) | Rm(src_m_reg)); + codegen_addlong(block, OPCODE_ZIP1_V4H | Rd(dst_reg) | Rn(src_n_reg) | Rm(src_m_reg)); } -void host_arm64_ZIP1_V2S(codeblock_t *block, int dst_reg, int src_n_reg, int src_m_reg) +void +host_arm64_ZIP1_V2S(codeblock_t *block, int dst_reg, int src_n_reg, int src_m_reg) { - codegen_addlong(block, OPCODE_ZIP1_V2S | Rd(dst_reg) | Rn(src_n_reg) | Rm(src_m_reg)); + codegen_addlong(block, OPCODE_ZIP1_V2S | Rd(dst_reg) | Rn(src_n_reg) | Rm(src_m_reg)); } -void host_arm64_ZIP2_V8B(codeblock_t *block, int dst_reg, int src_n_reg, int src_m_reg) +void +host_arm64_ZIP2_V8B(codeblock_t *block, int dst_reg, int src_n_reg, int src_m_reg) { - codegen_addlong(block, OPCODE_ZIP2_V8B | Rd(dst_reg) | Rn(src_n_reg) | Rm(src_m_reg)); + codegen_addlong(block, OPCODE_ZIP2_V8B | Rd(dst_reg) | Rn(src_n_reg) | Rm(src_m_reg)); } -void host_arm64_ZIP2_V4H(codeblock_t *block, int dst_reg, int src_n_reg, int src_m_reg) +void +host_arm64_ZIP2_V4H(codeblock_t *block, int dst_reg, int src_n_reg, int src_m_reg) { - codegen_addlong(block, OPCODE_ZIP2_V4H | Rd(dst_reg) | Rn(src_n_reg) | Rm(src_m_reg)); + codegen_addlong(block, OPCODE_ZIP2_V4H | Rd(dst_reg) | Rn(src_n_reg) | Rm(src_m_reg)); } -void host_arm64_ZIP2_V2S(codeblock_t *block, int dst_reg, int src_n_reg, int src_m_reg) +void +host_arm64_ZIP2_V2S(codeblock_t *block, int dst_reg, int src_n_reg, int src_m_reg) { - codegen_addlong(block, OPCODE_ZIP2_V2S | Rd(dst_reg) | Rn(src_n_reg) | Rm(src_m_reg)); + codegen_addlong(block, OPCODE_ZIP2_V2S | Rd(dst_reg) | Rn(src_n_reg) | Rm(src_m_reg)); } -void host_arm64_call(codeblock_t *block, void *dst_addr) +void +host_arm64_call(codeblock_t *block, void *dst_addr) { - host_arm64_MOVX_IMM(block, REG_X16, (uint64_t)dst_addr); - host_arm64_BLR(block, REG_X16); + host_arm64_MOVX_IMM(block, REG_X16, (uint64_t) dst_addr); + host_arm64_BLR(block, REG_X16); } -void host_arm64_jump(codeblock_t *block, uintptr_t dst_addr) +void +host_arm64_jump(codeblock_t *block, uintptr_t dst_addr) { - host_arm64_MOVX_IMM(block, REG_X16, (uint64_t)dst_addr); - host_arm64_BR(block, REG_X16); + host_arm64_MOVX_IMM(block, REG_X16, (uint64_t) dst_addr); + host_arm64_BR(block, REG_X16); } -void host_arm64_mov_imm(codeblock_t *block, int reg, uint32_t imm_data) +void +host_arm64_mov_imm(codeblock_t *block, int reg, uint32_t imm_data) { - if (imm_is_imm16(imm_data)) - host_arm64_MOVZ_IMM(block, reg, imm_data); - else - { - host_arm64_MOVZ_IMM(block, reg, imm_data & 0xffff); - host_arm64_MOVK_IMM(block, reg, imm_data & 0xffff0000); - } + if (imm_is_imm16(imm_data)) + host_arm64_MOVZ_IMM(block, reg, imm_data); + else { + host_arm64_MOVZ_IMM(block, reg, imm_data & 0xffff); + host_arm64_MOVK_IMM(block, reg, imm_data & 0xffff0000); + } } #endif diff --git a/src/codegen_new/codegen_backend_arm64_ops.h b/src/codegen_new/codegen_backend_arm64_ops.h index 2a514edbe..df751b4aa 100644 --- a/src/codegen_new/codegen_backend_arm64_ops.h +++ b/src/codegen_new/codegen_backend_arm64_ops.h @@ -251,14 +251,12 @@ void host_arm64_call(codeblock_t *block, void *dst_addr); void host_arm64_jump(codeblock_t *block, uintptr_t dst_addr); void host_arm64_mov_imm(codeblock_t *block, int reg, uint32_t imm_data); - -#define in_range7_x(offset) (((offset) >= -0x200) && ((offset) < (0x200)) && !((offset) & 7)) +#define in_range7_x(offset) (((offset) >= -0x200) && ((offset) < (0x200)) && !((offset) &7)) #define in_range12_b(offset) (((offset) >= 0) && ((offset) < 0x1000)) -#define in_range12_h(offset) (((offset) >= 0) && ((offset) < 0x2000) && !((offset) & 1)) -#define in_range12_w(offset) (((offset) >= 0) && ((offset) < 0x4000) && !((offset) & 3)) -#define in_range12_q(offset) (((offset) >= 0) && ((offset) < 0x8000) && !((offset) & 7)) - +#define in_range12_h(offset) (((offset) >= 0) && ((offset) < 0x2000) && !((offset) &1)) +#define in_range12_w(offset) (((offset) >= 0) && ((offset) < 0x4000) && !((offset) &3)) +#define in_range12_q(offset) (((offset) >= 0) && ((offset) < 0x8000) && !((offset) &7)) void codegen_direct_read_8(codeblock_t *block, int host_reg, void *p); -void codegen_alloc(codeblock_t *block, int size); \ No newline at end of file +void codegen_alloc(codeblock_t *block, int size); diff --git a/src/codegen_new/codegen_backend_arm64_uops.c b/src/codegen_new/codegen_backend_arm64_uops.c index 7e26cdcf1..7514e1f0c 100644 --- a/src/codegen_new/codegen_backend_arm64_uops.c +++ b/src/codegen_new/codegen_backend_arm64_uops.c @@ -1,3372 +1,3579 @@ #if defined __aarch64__ || defined _M_ARM64 -#include -#include <86box/86box.h> -#include "cpu.h" -#include <86box/mem.h> +# include +# include <86box/86box.h> +# include "cpu.h" +# include <86box/mem.h> +# include <86box/plat_unused.h> -#include "x86.h" -#include "x87.h" -#include "386_common.h" -#include "codegen.h" -#include "codegen_backend.h" -#include "codegen_backend_arm64_defs.h" -#include "codegen_backend_arm64_ops.h" -#include "codegen_ir_defs.h" +# include "x86.h" +# include "x86seg_common.h" +# include "x86seg.h" +# include "x87.h" +# include "386_common.h" +# include "codegen.h" +# include "codegen_backend.h" +# include "codegen_backend_arm64_defs.h" +# include "codegen_backend_arm64_ops.h" +# include "codegen_ir_defs.h" -#define OFFSET19(offset) (((offset >> 2) << 5) & 0x00ffffe0) +# define OFFSET19(offset) (((offset >> 2) << 5) & 0x00ffffe0) -#define HOST_REG_GET(reg) (IREG_GET_REG(reg) & 0x1f) +# define HOST_REG_GET(reg) (IREG_GET_REG(reg) & 0x1f) -#define REG_IS_L(size) (size == IREG_SIZE_L) -#define REG_IS_W(size) (size == IREG_SIZE_W) -#define REG_IS_B(size) (size == IREG_SIZE_B) -#define REG_IS_BH(size) (size == IREG_SIZE_BH) -#define REG_IS_D(size) (size == IREG_SIZE_D) -#define REG_IS_Q(size) (size == IREG_SIZE_Q) +# define REG_IS_L(size) (size == IREG_SIZE_L) +# define REG_IS_W(size) (size == IREG_SIZE_W) +# define REG_IS_B(size) (size == IREG_SIZE_B) +# define REG_IS_BH(size) (size == IREG_SIZE_BH) +# define REG_IS_D(size) (size == IREG_SIZE_D) +# define REG_IS_Q(size) (size == IREG_SIZE_Q) -static int codegen_ADD(codeblock_t *block, uop_t *uop) +static int +codegen_ADD(codeblock_t *block, uop_t *uop) { - int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg_a = HOST_REG_GET(uop->src_reg_a_real), src_reg_b = HOST_REG_GET(uop->src_reg_b_real); - int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size_a = IREG_GET_SIZE(uop->src_reg_a_real), src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); + int dest_reg = HOST_REG_GET(uop->dest_reg_a_real); + int src_reg_a = HOST_REG_GET(uop->src_reg_a_real); + int src_reg_b = HOST_REG_GET(uop->src_reg_b_real); + int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real); + int src_size_a = IREG_GET_SIZE(uop->src_reg_a_real); + int src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); - if (REG_IS_L(dest_size) && REG_IS_L(src_size_a) && REG_IS_L(src_size_b)) - { - host_arm64_ADD_REG(block, dest_reg, src_reg_a, src_reg_b, 0); - } - else if (REG_IS_W(dest_size) && REG_IS_W(src_size_a) && REG_IS_W(src_size_b)) - { - host_arm64_ADD_REG(block, REG_TEMP, src_reg_a, src_reg_b, 0); - host_arm64_BFI(block, dest_reg, REG_TEMP, 0, 16); - } - else if (REG_IS_B(dest_size) && REG_IS_B(src_size_a) && REG_IS_B(src_size_b)) - { - host_arm64_ADD_REG(block, REG_TEMP, src_reg_a, src_reg_b, 0); - host_arm64_BFI(block, dest_reg, REG_TEMP, 0, 8); - } - else if (REG_IS_B(dest_size) && REG_IS_B(src_size_a) && REG_IS_BH(src_size_b)) - { - host_arm64_ADD_REG_LSR(block, REG_TEMP, src_reg_a, src_reg_b, 8); - host_arm64_BFI(block, dest_reg, REG_TEMP, 0, 8); - } - else if (REG_IS_BH(dest_size) && REG_IS_BH(src_size_a) && REG_IS_B(src_size_b)) - { - host_arm64_ADD_REG_LSR(block, REG_TEMP, src_reg_b, src_reg_a, 8); - host_arm64_BFI(block, dest_reg, REG_TEMP, 8, 8); - } - else if (REG_IS_BH(dest_size) && REG_IS_BH(src_size_a) && REG_IS_BH(src_size_b)) - { - host_arm64_AND_IMM(block, REG_TEMP, src_reg_a, 0x0000ff00); - host_arm64_ADD_REG(block, REG_TEMP, REG_TEMP, src_reg_b, 0); - host_arm64_MOV_REG_LSR(block, REG_TEMP, REG_TEMP, 8); - host_arm64_BFI(block, dest_reg, REG_TEMP, 8, 8); - } - else - fatal("ADD %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real); + if (REG_IS_L(dest_size) && REG_IS_L(src_size_a) && REG_IS_L(src_size_b)) { + host_arm64_ADD_REG(block, dest_reg, src_reg_a, src_reg_b, 0); + } else if (REG_IS_W(dest_size) && REG_IS_W(src_size_a) && REG_IS_W(src_size_b)) { + host_arm64_ADD_REG(block, REG_TEMP, src_reg_a, src_reg_b, 0); + host_arm64_BFI(block, dest_reg, REG_TEMP, 0, 16); + } else if (REG_IS_B(dest_size) && REG_IS_B(src_size_a) && REG_IS_B(src_size_b)) { + host_arm64_ADD_REG(block, REG_TEMP, src_reg_a, src_reg_b, 0); + host_arm64_BFI(block, dest_reg, REG_TEMP, 0, 8); + } else if (REG_IS_B(dest_size) && REG_IS_B(src_size_a) && REG_IS_BH(src_size_b)) { + host_arm64_ADD_REG_LSR(block, REG_TEMP, src_reg_a, src_reg_b, 8); + host_arm64_BFI(block, dest_reg, REG_TEMP, 0, 8); + } else if (REG_IS_BH(dest_size) && REG_IS_BH(src_size_a) && REG_IS_B(src_size_b)) { + host_arm64_ADD_REG_LSR(block, REG_TEMP, src_reg_b, src_reg_a, 8); + host_arm64_BFI(block, dest_reg, REG_TEMP, 8, 8); + } else if (REG_IS_BH(dest_size) && REG_IS_BH(src_size_a) && REG_IS_BH(src_size_b)) { + host_arm64_AND_IMM(block, REG_TEMP, src_reg_a, 0x0000ff00); + host_arm64_ADD_REG(block, REG_TEMP, REG_TEMP, src_reg_b, 0); + host_arm64_MOV_REG_LSR(block, REG_TEMP, REG_TEMP, 8); + host_arm64_BFI(block, dest_reg, REG_TEMP, 8, 8); + } else + fatal("ADD %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real); - return 0; + return 0; } -static int codegen_ADD_IMM(codeblock_t *block, uop_t *uop) +static int +codegen_ADD_IMM(codeblock_t *block, uop_t *uop) { - int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg = HOST_REG_GET(uop->src_reg_a_real); - int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size = IREG_GET_SIZE(uop->src_reg_a_real); + int dest_reg = HOST_REG_GET(uop->dest_reg_a_real); + int src_reg = HOST_REG_GET(uop->src_reg_a_real); + int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real); + int src_size = IREG_GET_SIZE(uop->src_reg_a_real); - if (REG_IS_L(dest_size) && REG_IS_L(src_size)) - { - host_arm64_ADD_IMM(block, dest_reg, src_reg, uop->imm_data); - } - else if (REG_IS_W(dest_size) && REG_IS_W(src_size)) - { - host_arm64_ADD_IMM(block, REG_TEMP, src_reg, uop->imm_data); - host_arm64_BFI(block, dest_reg, REG_TEMP, 0, 16); - } - else if (REG_IS_B(dest_size) && REG_IS_B(src_size)) - { - host_arm64_ADD_IMM(block, REG_TEMP, src_reg, uop->imm_data); - host_arm64_BFI(block, dest_reg, REG_TEMP, 0, 8); - } - else if (REG_IS_BH(dest_size) && REG_IS_BH(src_size)) - { - host_arm64_ADD_IMM(block, REG_TEMP, src_reg, uop->imm_data << 8); - host_arm64_MOV_REG_LSR(block, REG_TEMP, REG_TEMP, 8); - host_arm64_BFI(block, dest_reg, REG_TEMP, 8, 8); - } - else - fatal("ADD_IMM %x %x\n", uop->dest_reg_a_real, uop->src_reg_a_real); + if (REG_IS_L(dest_size) && REG_IS_L(src_size)) { + host_arm64_ADD_IMM(block, dest_reg, src_reg, uop->imm_data); + } else if (REG_IS_W(dest_size) && REG_IS_W(src_size)) { + host_arm64_ADD_IMM(block, REG_TEMP, src_reg, uop->imm_data); + host_arm64_BFI(block, dest_reg, REG_TEMP, 0, 16); + } else if (REG_IS_B(dest_size) && REG_IS_B(src_size)) { + host_arm64_ADD_IMM(block, REG_TEMP, src_reg, uop->imm_data); + host_arm64_BFI(block, dest_reg, REG_TEMP, 0, 8); + } else if (REG_IS_BH(dest_size) && REG_IS_BH(src_size)) { + host_arm64_ADD_IMM(block, REG_TEMP, src_reg, uop->imm_data << 8); + host_arm64_MOV_REG_LSR(block, REG_TEMP, REG_TEMP, 8); + host_arm64_BFI(block, dest_reg, REG_TEMP, 8, 8); + } else + fatal("ADD_IMM %x %x\n", uop->dest_reg_a_real, uop->src_reg_a_real); - return 0; + return 0; } -static int codegen_ADD_LSHIFT(codeblock_t *block, uop_t *uop) +static int +codegen_ADD_LSHIFT(codeblock_t *block, uop_t *uop) { - host_arm64_ADD_REG(block, uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real, uop->imm_data); - return 0; + host_arm64_ADD_REG(block, uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real, uop->imm_data); + return 0; } -static int codegen_AND(codeblock_t *block, uop_t *uop) +static int +codegen_AND(codeblock_t *block, uop_t *uop) { - int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg_a = HOST_REG_GET(uop->src_reg_a_real), src_reg_b = HOST_REG_GET(uop->src_reg_b_real); - int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size_a = IREG_GET_SIZE(uop->src_reg_a_real), src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); + int dest_reg = HOST_REG_GET(uop->dest_reg_a_real); + int src_reg_a = HOST_REG_GET(uop->src_reg_a_real); + int src_reg_b = HOST_REG_GET(uop->src_reg_b_real); + int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real); + int src_size_a = IREG_GET_SIZE(uop->src_reg_a_real); + int src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); - if (REG_IS_Q(dest_size) && REG_IS_Q(src_size_a) && REG_IS_Q(src_size_b)) - { - host_arm64_AND_REG_V(block, dest_reg, src_reg_a, src_reg_b); - } - else if (REG_IS_L(dest_size) && REG_IS_L(src_size_a) && REG_IS_L(src_size_b)) - { - host_arm64_AND_REG(block, dest_reg, src_reg_a, src_reg_b, 0); - } - else if (REG_IS_W(dest_size) && REG_IS_W(src_size_a) && REG_IS_W(src_size_b) && dest_reg == src_reg_a) - { - host_arm64_ORR_IMM(block, REG_TEMP, src_reg_b, 0xffff0000); - host_arm64_AND_REG(block, dest_reg, src_reg_a, REG_TEMP, 0); - } - else if (REG_IS_B(dest_size) && REG_IS_B(src_size_a) && REG_IS_B(src_size_b) && dest_reg == src_reg_a) - { - host_arm64_ORR_IMM(block, REG_TEMP, src_reg_b, 0xffffff00); - host_arm64_AND_REG(block, dest_reg, src_reg_a, REG_TEMP, 0); - } - else if (REG_IS_B(dest_size) && REG_IS_B(src_size_a) && REG_IS_BH(src_size_b) && dest_reg == src_reg_a) - { - host_arm64_ORR_IMM(block, REG_TEMP, src_reg_b, 0xffff00ff); - host_arm64_AND_REG_ASR(block, dest_reg, src_reg_a, REG_TEMP, 8); - } - else if (REG_IS_BH(dest_size) && REG_IS_BH(src_size_a) && REG_IS_B(src_size_b) && dest_reg == src_reg_a) - { - host_arm64_ORR_IMM(block, REG_TEMP, src_reg_b, 0xffffff00); - host_arm64_AND_REG_ROR(block, dest_reg, src_reg_a, REG_TEMP, 24); - } - else if (REG_IS_BH(dest_size) && REG_IS_BH(src_size_a) && REG_IS_BH(src_size_b) && dest_reg == src_reg_a) - { - host_arm64_ORR_IMM(block, REG_TEMP, src_reg_b, 0xffff00ff); - host_arm64_AND_REG(block, dest_reg, src_reg_a, REG_TEMP, 0); - } - else if (REG_IS_W(dest_size) && REG_IS_W(src_size_a) && REG_IS_W(src_size_b)) - { - host_arm64_AND_REG(block, REG_TEMP, src_reg_a, src_reg_b, 0); - host_arm64_BFI(block, dest_reg, REG_TEMP, 0, 16); - } - else if (REG_IS_B(dest_size) && REG_IS_B(src_size_a) && REG_IS_B(src_size_b)) - { - host_arm64_AND_REG(block, REG_TEMP, src_reg_a, src_reg_b, 0); - host_arm64_BFI(block, dest_reg, REG_TEMP, 0, 8); - } - else if (REG_IS_B(dest_size) && REG_IS_B(src_size_a) && REG_IS_BH(src_size_b)) - { - host_arm64_ORR_IMM(block, REG_TEMP, src_reg_b, 0xffff00ff); - host_arm64_AND_REG_ROR(block, REG_TEMP, src_reg_a, REG_TEMP, 8); - host_arm64_BFI(block, dest_reg, REG_TEMP, 0, 8); - } - else if (REG_IS_B(dest_size) && REG_IS_BH(src_size_a) && REG_IS_B(src_size_b)) - { - host_arm64_ORR_IMM(block, REG_TEMP, src_reg_a, 0xffff00ff); - host_arm64_AND_REG_ROR(block, REG_TEMP, src_reg_b, REG_TEMP, 8); - host_arm64_BFI(block, dest_reg, REG_TEMP, 0, 8); - } - else if (REG_IS_B(dest_size) && REG_IS_BH(src_size_a) && REG_IS_BH(src_size_b)) - { - host_arm64_AND_REG(block, REG_TEMP, src_reg_a, src_reg_b, 0); - host_arm64_MOV_REG_LSR(block, REG_TEMP, REG_TEMP, 8); - host_arm64_BFI(block, dest_reg, REG_TEMP, 0, 8); - } - else - fatal("AND %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real); + if (REG_IS_Q(dest_size) && REG_IS_Q(src_size_a) && REG_IS_Q(src_size_b)) { + host_arm64_AND_REG_V(block, dest_reg, src_reg_a, src_reg_b); + } else if (REG_IS_L(dest_size) && REG_IS_L(src_size_a) && REG_IS_L(src_size_b)) { + host_arm64_AND_REG(block, dest_reg, src_reg_a, src_reg_b, 0); + } else if (REG_IS_W(dest_size) && REG_IS_W(src_size_a) && REG_IS_W(src_size_b) && dest_reg == src_reg_a) { + host_arm64_ORR_IMM(block, REG_TEMP, src_reg_b, 0xffff0000); + host_arm64_AND_REG(block, dest_reg, src_reg_a, REG_TEMP, 0); + } else if (REG_IS_B(dest_size) && REG_IS_B(src_size_a) && REG_IS_B(src_size_b) && dest_reg == src_reg_a) { + host_arm64_ORR_IMM(block, REG_TEMP, src_reg_b, 0xffffff00); + host_arm64_AND_REG(block, dest_reg, src_reg_a, REG_TEMP, 0); + } else if (REG_IS_B(dest_size) && REG_IS_B(src_size_a) && REG_IS_BH(src_size_b) && dest_reg == src_reg_a) { + host_arm64_ORR_IMM(block, REG_TEMP, src_reg_b, 0xffff00ff); + host_arm64_AND_REG_ASR(block, dest_reg, src_reg_a, REG_TEMP, 8); + } else if (REG_IS_BH(dest_size) && REG_IS_BH(src_size_a) && REG_IS_B(src_size_b) && dest_reg == src_reg_a) { + host_arm64_ORR_IMM(block, REG_TEMP, src_reg_b, 0xffffff00); + host_arm64_AND_REG_ROR(block, dest_reg, src_reg_a, REG_TEMP, 24); + } else if (REG_IS_BH(dest_size) && REG_IS_BH(src_size_a) && REG_IS_BH(src_size_b) && dest_reg == src_reg_a) { + host_arm64_ORR_IMM(block, REG_TEMP, src_reg_b, 0xffff00ff); + host_arm64_AND_REG(block, dest_reg, src_reg_a, REG_TEMP, 0); + } else if (REG_IS_W(dest_size) && REG_IS_W(src_size_a) && REG_IS_W(src_size_b)) { + host_arm64_AND_REG(block, REG_TEMP, src_reg_a, src_reg_b, 0); + host_arm64_BFI(block, dest_reg, REG_TEMP, 0, 16); + } else if (REG_IS_B(dest_size) && REG_IS_B(src_size_a) && REG_IS_B(src_size_b)) { + host_arm64_AND_REG(block, REG_TEMP, src_reg_a, src_reg_b, 0); + host_arm64_BFI(block, dest_reg, REG_TEMP, 0, 8); + } else if (REG_IS_B(dest_size) && REG_IS_B(src_size_a) && REG_IS_BH(src_size_b)) { + host_arm64_ORR_IMM(block, REG_TEMP, src_reg_b, 0xffff00ff); + host_arm64_AND_REG_ROR(block, REG_TEMP, src_reg_a, REG_TEMP, 8); + host_arm64_BFI(block, dest_reg, REG_TEMP, 0, 8); + } else if (REG_IS_B(dest_size) && REG_IS_BH(src_size_a) && REG_IS_B(src_size_b)) { + host_arm64_ORR_IMM(block, REG_TEMP, src_reg_a, 0xffff00ff); + host_arm64_AND_REG_ROR(block, REG_TEMP, src_reg_b, REG_TEMP, 8); + host_arm64_BFI(block, dest_reg, REG_TEMP, 0, 8); + } else if (REG_IS_B(dest_size) && REG_IS_BH(src_size_a) && REG_IS_BH(src_size_b)) { + host_arm64_AND_REG(block, REG_TEMP, src_reg_a, src_reg_b, 0); + host_arm64_MOV_REG_LSR(block, REG_TEMP, REG_TEMP, 8); + host_arm64_BFI(block, dest_reg, REG_TEMP, 0, 8); + } else + fatal("AND %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real); - return 0; + return 0; } -static int codegen_AND_IMM(codeblock_t *block, uop_t *uop) +static int +codegen_AND_IMM(codeblock_t *block, uop_t *uop) { - int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg = HOST_REG_GET(uop->src_reg_a_real); - int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size = IREG_GET_SIZE(uop->src_reg_a_real); + int dest_reg = HOST_REG_GET(uop->dest_reg_a_real); + int src_reg = HOST_REG_GET(uop->src_reg_a_real); + int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real); + int src_size = IREG_GET_SIZE(uop->src_reg_a_real); - if (REG_IS_L(dest_size) && REG_IS_L(src_size)) - { - host_arm64_AND_IMM(block, dest_reg, src_reg, uop->imm_data); - } - else if (REG_IS_W(dest_size) && REG_IS_W(src_size)) - { - host_arm64_AND_IMM(block, dest_reg, src_reg, uop->imm_data | 0xffff0000); - } - else if (REG_IS_B(dest_size) && REG_IS_B(src_size)) - { - host_arm64_AND_IMM(block, dest_reg, src_reg, uop->imm_data | 0xffffff00); - } - else if (REG_IS_B(dest_size) && REG_IS_BH(src_size)) - { - host_arm64_MOV_REG_LSR(block, REG_TEMP, src_reg, 8); - host_arm64_AND_IMM(block, REG_TEMP, REG_TEMP, uop->imm_data); - host_arm64_BFI(block, dest_reg, REG_TEMP, 0, 8); - } - else if (REG_IS_BH(dest_size) && REG_IS_BH(src_size)) - { - host_arm64_AND_IMM(block, dest_reg, src_reg, (uop->imm_data << 8) | 0xffff00ff); - } - else - fatal("AND_IMM %x %x\n", uop->dest_reg_a_real, uop->src_reg_a_real); + if (REG_IS_L(dest_size) && REG_IS_L(src_size)) { + host_arm64_AND_IMM(block, dest_reg, src_reg, uop->imm_data); + } else if (REG_IS_W(dest_size) && REG_IS_W(src_size)) { + host_arm64_AND_IMM(block, dest_reg, src_reg, uop->imm_data | 0xffff0000); + } else if (REG_IS_B(dest_size) && REG_IS_B(src_size)) { + host_arm64_AND_IMM(block, dest_reg, src_reg, uop->imm_data | 0xffffff00); + } else if (REG_IS_B(dest_size) && REG_IS_BH(src_size)) { + host_arm64_MOV_REG_LSR(block, REG_TEMP, src_reg, 8); + host_arm64_AND_IMM(block, REG_TEMP, REG_TEMP, uop->imm_data); + host_arm64_BFI(block, dest_reg, REG_TEMP, 0, 8); + } else if (REG_IS_BH(dest_size) && REG_IS_BH(src_size)) { + host_arm64_AND_IMM(block, dest_reg, src_reg, (uop->imm_data << 8) | 0xffff00ff); + } else + fatal("AND_IMM %x %x\n", uop->dest_reg_a_real, uop->src_reg_a_real); - return 0; + return 0; } -static int codegen_ANDN(codeblock_t *block, uop_t *uop) +static int +codegen_ANDN(codeblock_t *block, uop_t *uop) { - int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg_a = HOST_REG_GET(uop->src_reg_a_real), src_reg_b = HOST_REG_GET(uop->src_reg_b_real); - int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size_a = IREG_GET_SIZE(uop->src_reg_a_real), src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); + int dest_reg = HOST_REG_GET(uop->dest_reg_a_real); + int src_reg_a = HOST_REG_GET(uop->src_reg_a_real); + int src_reg_b = HOST_REG_GET(uop->src_reg_b_real); + int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real); + int src_size_a = IREG_GET_SIZE(uop->src_reg_a_real); + int src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); - if (REG_IS_Q(dest_size) && REG_IS_Q(src_size_a) && REG_IS_Q(src_size_b)) - { - host_arm64_BIC_REG_V(block, dest_reg, src_reg_b, src_reg_a); - } - else - fatal("ANDN %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real); + if (REG_IS_Q(dest_size) && REG_IS_Q(src_size_a) && REG_IS_Q(src_size_b)) { + host_arm64_BIC_REG_V(block, dest_reg, src_reg_b, src_reg_a); + } else + fatal("ANDN %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real); - return 0; + return 0; } -static int codegen_CALL_FUNC(codeblock_t *block, uop_t *uop) +static int +codegen_CALL_FUNC(codeblock_t *block, uop_t *uop) { - host_arm64_call(block, uop->p); + host_arm64_call(block, uop->p); - return 0; + return 0; } -static int codegen_CALL_FUNC_RESULT(codeblock_t *block, uop_t *uop) +static int +codegen_CALL_FUNC_RESULT(codeblock_t *block, uop_t *uop) { - int dest_reg = HOST_REG_GET(uop->dest_reg_a_real); - int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real); + int dest_reg = HOST_REG_GET(uop->dest_reg_a_real); + int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real); - if (!REG_IS_L(dest_size)) - fatal("CALL_FUNC_RESULT %02x\n", uop->dest_reg_a_real); - host_arm64_call(block, uop->p); - host_arm64_MOV_REG(block, dest_reg, REG_W0, 0); + if (!REG_IS_L(dest_size)) + fatal("CALL_FUNC_RESULT %02x\n", uop->dest_reg_a_real); + host_arm64_call(block, uop->p); + host_arm64_MOV_REG(block, dest_reg, REG_W0, 0); - return 0; + return 0; } -static int codegen_CALL_INSTRUCTION_FUNC(codeblock_t *block, uop_t *uop) +static int +codegen_CALL_INSTRUCTION_FUNC(codeblock_t *block, uop_t *uop) { - host_arm64_call(block, uop->p); - host_arm64_CBNZ(block, REG_X0, (uintptr_t)codegen_exit_rout); + host_arm64_call(block, uop->p); + host_arm64_CBNZ(block, REG_X0, (uintptr_t) codegen_exit_rout); - return 0; + return 0; } -static int codegen_CMP_IMM_JZ(codeblock_t *block, uop_t *uop) +static int +codegen_CMP_IMM_JZ(codeblock_t *block, uop_t *uop) { - int src_reg = HOST_REG_GET(uop->src_reg_a_real); - int src_size = IREG_GET_SIZE(uop->src_reg_a_real); + int src_reg = HOST_REG_GET(uop->src_reg_a_real); + int src_size = IREG_GET_SIZE(uop->src_reg_a_real); - if (REG_IS_L(src_size)) - { - host_arm64_CMP_IMM(block, src_reg, uop->imm_data); - } - else - fatal("CMP_IMM_JZ %02x\n", uop->src_reg_a_real); - host_arm64_BEQ(block, uop->p); + if (REG_IS_L(src_size)) { + host_arm64_CMP_IMM(block, src_reg, uop->imm_data); + } else + fatal("CMP_IMM_JZ %02x\n", uop->src_reg_a_real); + host_arm64_BEQ(block, uop->p); - return 0; + return 0; } -static int codegen_CMP_IMM_JNZ_DEST(codeblock_t *block, uop_t *uop) +static int +codegen_CMP_IMM_JNZ_DEST(codeblock_t *block, uop_t *uop) { - int src_reg = HOST_REG_GET(uop->src_reg_a_real); - int src_size = IREG_GET_SIZE(uop->src_reg_a_real); + int src_reg = HOST_REG_GET(uop->src_reg_a_real); + int src_size = IREG_GET_SIZE(uop->src_reg_a_real); - if (REG_IS_L(src_size)) - { - host_arm64_CMP_IMM(block, src_reg, uop->imm_data); - } - else if (REG_IS_W(src_size)) - { - host_arm64_AND_IMM(block, REG_TEMP, src_reg, 0xffff); - host_arm64_CMP_IMM(block, REG_TEMP, uop->imm_data); - } - else - fatal("CMP_IMM_JNZ_DEST %02x\n", uop->src_reg_a_real); + if (REG_IS_L(src_size)) { + host_arm64_CMP_IMM(block, src_reg, uop->imm_data); + } else if (REG_IS_W(src_size)) { + host_arm64_AND_IMM(block, REG_TEMP, src_reg, 0xffff); + host_arm64_CMP_IMM(block, REG_TEMP, uop->imm_data); + } else + fatal("CMP_IMM_JNZ_DEST %02x\n", uop->src_reg_a_real); - uop->p = host_arm64_BNE_(block); + uop->p = host_arm64_BNE_(block); - return 0; + return 0; } -static int codegen_CMP_IMM_JZ_DEST(codeblock_t *block, uop_t *uop) +static int +codegen_CMP_IMM_JZ_DEST(codeblock_t *block, uop_t *uop) { - int src_reg = HOST_REG_GET(uop->src_reg_a_real); - int src_size = IREG_GET_SIZE(uop->src_reg_a_real); + int src_reg = HOST_REG_GET(uop->src_reg_a_real); + int src_size = IREG_GET_SIZE(uop->src_reg_a_real); - if (REG_IS_L(src_size)) - { - host_arm64_CMP_IMM(block, src_reg, uop->imm_data); - } - else if (REG_IS_W(src_size)) - { - host_arm64_AND_IMM(block, REG_TEMP, src_reg, 0xffff); - host_arm64_CMP_IMM(block, REG_TEMP, uop->imm_data); - } - else - fatal("CMP_IMM_JZ_DEST %02x\n", uop->src_reg_a_real); + if (REG_IS_L(src_size)) { + host_arm64_CMP_IMM(block, src_reg, uop->imm_data); + } else if (REG_IS_W(src_size)) { + host_arm64_AND_IMM(block, REG_TEMP, src_reg, 0xffff); + host_arm64_CMP_IMM(block, REG_TEMP, uop->imm_data); + } else + fatal("CMP_IMM_JZ_DEST %02x\n", uop->src_reg_a_real); - uop->p = host_arm64_BEQ_(block); + uop->p = host_arm64_BEQ_(block); - return 0; + return 0; } -static int codegen_CMP_JB(codeblock_t *block, uop_t *uop) +static int +codegen_CMP_JB(codeblock_t *block, uop_t *uop) { - int src_reg_a = HOST_REG_GET(uop->src_reg_a_real), src_reg_b = HOST_REG_GET(uop->src_reg_b_real); - int src_size_a = IREG_GET_SIZE(uop->src_reg_a_real), src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); - uint32_t *jump_p; + int src_reg_a = HOST_REG_GET(uop->src_reg_a_real); + int src_reg_b = HOST_REG_GET(uop->src_reg_b_real); + int src_size_a = IREG_GET_SIZE(uop->src_reg_a_real); + int src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); + uint32_t *jump_p; - if (REG_IS_L(src_size_a) && REG_IS_L(src_size_b)) - { - host_arm64_CMP_REG(block, src_reg_a, src_reg_b); - } - else - fatal("CMP_JB %02x\n", uop->src_reg_a_real); + if (REG_IS_L(src_size_a) && REG_IS_L(src_size_b)) { + host_arm64_CMP_REG(block, src_reg_a, src_reg_b); + } else + fatal("CMP_JB %02x\n", uop->src_reg_a_real); - jump_p = host_arm64_BCC_(block); - host_arm64_branch_set_offset(jump_p, uop->p); + jump_p = host_arm64_BCC_(block); + host_arm64_branch_set_offset(jump_p, uop->p); - return 0; + return 0; } -static int codegen_CMP_JNBE(codeblock_t *block, uop_t *uop) +static int +codegen_CMP_JNBE(codeblock_t *block, uop_t *uop) { - int src_reg_a = HOST_REG_GET(uop->src_reg_a_real), src_reg_b = HOST_REG_GET(uop->src_reg_b_real); - int src_size_a = IREG_GET_SIZE(uop->src_reg_a_real), src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); - uint32_t *jump_p; + int src_reg_a = HOST_REG_GET(uop->src_reg_a_real); + int src_reg_b = HOST_REG_GET(uop->src_reg_b_real); + int src_size_a = IREG_GET_SIZE(uop->src_reg_a_real); + int src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); + uint32_t *jump_p; - if (REG_IS_L(src_size_a) && REG_IS_L(src_size_b)) - { - host_arm64_CMP_REG(block, src_reg_a, src_reg_b); - } - else - fatal("CMP_JNBE %02x\n", uop->src_reg_a_real); + if (REG_IS_L(src_size_a) && REG_IS_L(src_size_b)) { + host_arm64_CMP_REG(block, src_reg_a, src_reg_b); + } else + fatal("CMP_JNBE %02x\n", uop->src_reg_a_real); - jump_p = host_arm64_BHI_(block); - host_arm64_branch_set_offset(jump_p, uop->p); + jump_p = host_arm64_BHI_(block); + host_arm64_branch_set_offset(jump_p, uop->p); - return 0; + return 0; } -static int codegen_CMP_JNB_DEST(codeblock_t *block, uop_t *uop) +static int +codegen_CMP_JNB_DEST(codeblock_t *block, uop_t *uop) { - int src_reg_a = HOST_REG_GET(uop->src_reg_a_real), src_reg_b = HOST_REG_GET(uop->src_reg_b_real); - int src_size_a = IREG_GET_SIZE(uop->src_reg_a_real), src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); + int src_reg_a = HOST_REG_GET(uop->src_reg_a_real); + int src_reg_b = HOST_REG_GET(uop->src_reg_b_real); + int src_size_a = IREG_GET_SIZE(uop->src_reg_a_real); + int src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); - if (REG_IS_L(src_size_a) && REG_IS_L(src_size_b)) - { - host_arm64_CMP_REG(block, src_reg_a, src_reg_b); - } - else if (REG_IS_W(src_size_a) && REG_IS_W(src_size_b)) - { - host_arm64_MOV_REG(block, REG_TEMP, src_reg_a, 16); - host_arm64_CMP_REG_LSL(block, REG_TEMP, src_reg_b, 16); - } - else if (REG_IS_B(src_size_a) && REG_IS_B(src_size_b)) - { - host_arm64_MOV_REG(block, REG_TEMP, src_reg_a, 24); - host_arm64_CMP_REG_LSL(block, REG_TEMP, src_reg_b, 24); - } - else - fatal("CMP_JNB_DEST %02x\n", uop->src_reg_a_real); + if (REG_IS_L(src_size_a) && REG_IS_L(src_size_b)) { + host_arm64_CMP_REG(block, src_reg_a, src_reg_b); + } else if (REG_IS_W(src_size_a) && REG_IS_W(src_size_b)) { + host_arm64_MOV_REG(block, REG_TEMP, src_reg_a, 16); + host_arm64_CMP_REG_LSL(block, REG_TEMP, src_reg_b, 16); + } else if (REG_IS_B(src_size_a) && REG_IS_B(src_size_b)) { + host_arm64_MOV_REG(block, REG_TEMP, src_reg_a, 24); + host_arm64_CMP_REG_LSL(block, REG_TEMP, src_reg_b, 24); + } else + fatal("CMP_JNB_DEST %02x\n", uop->src_reg_a_real); - uop->p = host_arm64_BCS_(block); + uop->p = host_arm64_BCS_(block); - return 0; + return 0; } -static int codegen_CMP_JNBE_DEST(codeblock_t *block, uop_t *uop) +static int +codegen_CMP_JNBE_DEST(codeblock_t *block, uop_t *uop) { - int src_reg_a = HOST_REG_GET(uop->src_reg_a_real), src_reg_b = HOST_REG_GET(uop->src_reg_b_real); - int src_size_a = IREG_GET_SIZE(uop->src_reg_a_real), src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); + int src_reg_a = HOST_REG_GET(uop->src_reg_a_real); + int src_reg_b = HOST_REG_GET(uop->src_reg_b_real); + int src_size_a = IREG_GET_SIZE(uop->src_reg_a_real); + int src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); - if (REG_IS_L(src_size_a) && REG_IS_L(src_size_b)) - { - host_arm64_CMP_REG(block, src_reg_a, src_reg_b); - } - else if (REG_IS_W(src_size_a) && REG_IS_W(src_size_b)) - { - host_arm64_MOV_REG(block, REG_TEMP, src_reg_a, 16); - host_arm64_CMP_REG_LSL(block, REG_TEMP, src_reg_b, 16); - } - else if (REG_IS_B(src_size_a) && REG_IS_B(src_size_b)) - { - host_arm64_MOV_REG(block, REG_TEMP, src_reg_a, 24); - host_arm64_CMP_REG_LSL(block, REG_TEMP, src_reg_b, 24); - } - else - fatal("CMP_JNBE_DEST %02x\n", uop->src_reg_a_real); + if (REG_IS_L(src_size_a) && REG_IS_L(src_size_b)) { + host_arm64_CMP_REG(block, src_reg_a, src_reg_b); + } else if (REG_IS_W(src_size_a) && REG_IS_W(src_size_b)) { + host_arm64_MOV_REG(block, REG_TEMP, src_reg_a, 16); + host_arm64_CMP_REG_LSL(block, REG_TEMP, src_reg_b, 16); + } else if (REG_IS_B(src_size_a) && REG_IS_B(src_size_b)) { + host_arm64_MOV_REG(block, REG_TEMP, src_reg_a, 24); + host_arm64_CMP_REG_LSL(block, REG_TEMP, src_reg_b, 24); + } else + fatal("CMP_JNBE_DEST %02x\n", uop->src_reg_a_real); - uop->p = host_arm64_BHI_(block); + uop->p = host_arm64_BHI_(block); - return 0; + return 0; } -static int codegen_CMP_JNL_DEST(codeblock_t *block, uop_t *uop) +static int +codegen_CMP_JNL_DEST(codeblock_t *block, uop_t *uop) { - int src_reg_a = HOST_REG_GET(uop->src_reg_a_real), src_reg_b = HOST_REG_GET(uop->src_reg_b_real); - int src_size_a = IREG_GET_SIZE(uop->src_reg_a_real), src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); + int src_reg_a = HOST_REG_GET(uop->src_reg_a_real); + int src_reg_b = HOST_REG_GET(uop->src_reg_b_real); + int src_size_a = IREG_GET_SIZE(uop->src_reg_a_real); + int src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); - if (REG_IS_L(src_size_a) && REG_IS_L(src_size_b)) - { - host_arm64_CMP_REG(block, src_reg_a, src_reg_b); - } - else if (REG_IS_W(src_size_a) && REG_IS_W(src_size_b)) - { - host_arm64_MOV_REG(block, REG_TEMP, src_reg_a, 16); - host_arm64_CMP_REG_LSL(block, REG_TEMP, src_reg_b, 16); - } - else if (REG_IS_B(src_size_a) && REG_IS_B(src_size_b)) - { - host_arm64_MOV_REG(block, REG_TEMP, src_reg_a, 24); - host_arm64_CMP_REG_LSL(block, REG_TEMP, src_reg_b, 24); - } - else - fatal("CMP_JNL_DEST %02x\n", uop->src_reg_a_real); + if (REG_IS_L(src_size_a) && REG_IS_L(src_size_b)) { + host_arm64_CMP_REG(block, src_reg_a, src_reg_b); + } else if (REG_IS_W(src_size_a) && REG_IS_W(src_size_b)) { + host_arm64_MOV_REG(block, REG_TEMP, src_reg_a, 16); + host_arm64_CMP_REG_LSL(block, REG_TEMP, src_reg_b, 16); + } else if (REG_IS_B(src_size_a) && REG_IS_B(src_size_b)) { + host_arm64_MOV_REG(block, REG_TEMP, src_reg_a, 24); + host_arm64_CMP_REG_LSL(block, REG_TEMP, src_reg_b, 24); + } else + fatal("CMP_JNL_DEST %02x\n", uop->src_reg_a_real); - uop->p = host_arm64_BGE_(block); + uop->p = host_arm64_BGE_(block); - return 0; + return 0; } -static int codegen_CMP_JNLE_DEST(codeblock_t *block, uop_t *uop) +static int +codegen_CMP_JNLE_DEST(codeblock_t *block, uop_t *uop) { - int src_reg_a = HOST_REG_GET(uop->src_reg_a_real), src_reg_b = HOST_REG_GET(uop->src_reg_b_real); - int src_size_a = IREG_GET_SIZE(uop->src_reg_a_real), src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); + int src_reg_a = HOST_REG_GET(uop->src_reg_a_real); + int src_reg_b = HOST_REG_GET(uop->src_reg_b_real); + int src_size_a = IREG_GET_SIZE(uop->src_reg_a_real); + int src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); - if (REG_IS_L(src_size_a) && REG_IS_L(src_size_b)) - { - host_arm64_CMP_REG(block, src_reg_a, src_reg_b); - } - else if (REG_IS_W(src_size_a) && REG_IS_W(src_size_b)) - { - host_arm64_MOV_REG(block, REG_TEMP, src_reg_a, 16); - host_arm64_CMP_REG_LSL(block, REG_TEMP, src_reg_b, 16); - } - else if (REG_IS_B(src_size_a) && REG_IS_B(src_size_b)) - { - host_arm64_MOV_REG(block, REG_TEMP, src_reg_a, 24); - host_arm64_CMP_REG_LSL(block, REG_TEMP, src_reg_b, 24); - } - else - fatal("CMP_JNLE_DEST %02x\n", uop->src_reg_a_real); + if (REG_IS_L(src_size_a) && REG_IS_L(src_size_b)) { + host_arm64_CMP_REG(block, src_reg_a, src_reg_b); + } else if (REG_IS_W(src_size_a) && REG_IS_W(src_size_b)) { + host_arm64_MOV_REG(block, REG_TEMP, src_reg_a, 16); + host_arm64_CMP_REG_LSL(block, REG_TEMP, src_reg_b, 16); + } else if (REG_IS_B(src_size_a) && REG_IS_B(src_size_b)) { + host_arm64_MOV_REG(block, REG_TEMP, src_reg_a, 24); + host_arm64_CMP_REG_LSL(block, REG_TEMP, src_reg_b, 24); + } else + fatal("CMP_JNLE_DEST %02x\n", uop->src_reg_a_real); - uop->p = host_arm64_BGT_(block); + uop->p = host_arm64_BGT_(block); - return 0; + return 0; } -static int codegen_CMP_JNO_DEST(codeblock_t *block, uop_t *uop) +static int +codegen_CMP_JNO_DEST(codeblock_t *block, uop_t *uop) { - int src_reg_a = HOST_REG_GET(uop->src_reg_a_real), src_reg_b = HOST_REG_GET(uop->src_reg_b_real); - int src_size_a = IREG_GET_SIZE(uop->src_reg_a_real), src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); + int src_reg_a = HOST_REG_GET(uop->src_reg_a_real); + int src_reg_b = HOST_REG_GET(uop->src_reg_b_real); + int src_size_a = IREG_GET_SIZE(uop->src_reg_a_real); + int src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); - if (REG_IS_L(src_size_a) && REG_IS_L(src_size_b)) - { - host_arm64_CMP_REG(block, src_reg_a, src_reg_b); - } - else if (REG_IS_W(src_size_a) && REG_IS_W(src_size_b)) - { - host_arm64_MOV_REG(block, REG_TEMP, src_reg_a, 16); - host_arm64_CMP_REG_LSL(block, REG_TEMP, src_reg_b, 16); - } - else if (REG_IS_B(src_size_a) && REG_IS_B(src_size_b)) - { - host_arm64_MOV_REG(block, REG_TEMP, src_reg_a, 24); - host_arm64_CMP_REG_LSL(block, REG_TEMP, src_reg_b, 24); - } - else - fatal("CMP_JNO_DEST %02x\n", uop->src_reg_a_real); + if (REG_IS_L(src_size_a) && REG_IS_L(src_size_b)) { + host_arm64_CMP_REG(block, src_reg_a, src_reg_b); + } else if (REG_IS_W(src_size_a) && REG_IS_W(src_size_b)) { + host_arm64_MOV_REG(block, REG_TEMP, src_reg_a, 16); + host_arm64_CMP_REG_LSL(block, REG_TEMP, src_reg_b, 16); + } else if (REG_IS_B(src_size_a) && REG_IS_B(src_size_b)) { + host_arm64_MOV_REG(block, REG_TEMP, src_reg_a, 24); + host_arm64_CMP_REG_LSL(block, REG_TEMP, src_reg_b, 24); + } else + fatal("CMP_JNO_DEST %02x\n", uop->src_reg_a_real); - uop->p = host_arm64_BVC_(block); + uop->p = host_arm64_BVC_(block); - return 0; + return 0; } -static int codegen_CMP_JNZ_DEST(codeblock_t *block, uop_t *uop) +static int +codegen_CMP_JNZ_DEST(codeblock_t *block, uop_t *uop) { - int src_reg_a = HOST_REG_GET(uop->src_reg_a_real), src_reg_b = HOST_REG_GET(uop->src_reg_b_real); - int src_size_a = IREG_GET_SIZE(uop->src_reg_a_real), src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); + int src_reg_a = HOST_REG_GET(uop->src_reg_a_real); + int src_reg_b = HOST_REG_GET(uop->src_reg_b_real); + int src_size_a = IREG_GET_SIZE(uop->src_reg_a_real); + int src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); - if (REG_IS_L(src_size_a) && REG_IS_L(src_size_b)) - { - host_arm64_CMP_REG(block, src_reg_a, src_reg_b); - } - else if (REG_IS_W(src_size_a) && REG_IS_W(src_size_b)) - { - host_arm64_MOV_REG(block, REG_TEMP, src_reg_a, 16); - host_arm64_CMP_REG_LSL(block, REG_TEMP, src_reg_b, 16); - } - else if (REG_IS_B(src_size_a) && REG_IS_B(src_size_b)) - { - host_arm64_MOV_REG(block, REG_TEMP, src_reg_a, 24); - host_arm64_CMP_REG_LSL(block, REG_TEMP, src_reg_b, 24); - } - else - fatal("CMP_JNZ_DEST %02x\n", uop->src_reg_a_real); + if (REG_IS_L(src_size_a) && REG_IS_L(src_size_b)) { + host_arm64_CMP_REG(block, src_reg_a, src_reg_b); + } else if (REG_IS_W(src_size_a) && REG_IS_W(src_size_b)) { + host_arm64_MOV_REG(block, REG_TEMP, src_reg_a, 16); + host_arm64_CMP_REG_LSL(block, REG_TEMP, src_reg_b, 16); + } else if (REG_IS_B(src_size_a) && REG_IS_B(src_size_b)) { + host_arm64_MOV_REG(block, REG_TEMP, src_reg_a, 24); + host_arm64_CMP_REG_LSL(block, REG_TEMP, src_reg_b, 24); + } else + fatal("CMP_JNZ_DEST %02x\n", uop->src_reg_a_real); - uop->p = host_arm64_BNE_(block); + uop->p = host_arm64_BNE_(block); - return 0; + return 0; } -static int codegen_CMP_JB_DEST(codeblock_t *block, uop_t *uop) +static int +codegen_CMP_JB_DEST(codeblock_t *block, uop_t *uop) { - int src_reg_a = HOST_REG_GET(uop->src_reg_a_real), src_reg_b = HOST_REG_GET(uop->src_reg_b_real); - int src_size_a = IREG_GET_SIZE(uop->src_reg_a_real), src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); + int src_reg_a = HOST_REG_GET(uop->src_reg_a_real); + int src_reg_b = HOST_REG_GET(uop->src_reg_b_real); + int src_size_a = IREG_GET_SIZE(uop->src_reg_a_real); + int src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); - if (REG_IS_L(src_size_a) && REG_IS_L(src_size_b)) - { - host_arm64_CMP_REG(block, src_reg_a, src_reg_b); - } - else if (REG_IS_W(src_size_a) && REG_IS_W(src_size_b)) - { - host_arm64_MOV_REG(block, REG_TEMP, src_reg_a, 16); - host_arm64_CMP_REG_LSL(block, REG_TEMP, src_reg_b, 16); - } - else if (REG_IS_B(src_size_a) && REG_IS_B(src_size_b)) - { - host_arm64_MOV_REG(block, REG_TEMP, src_reg_a, 24); - host_arm64_CMP_REG_LSL(block, REG_TEMP, src_reg_b, 24); - } - else - fatal("CMP_JB_DEST %02x\n", uop->src_reg_a_real); + if (REG_IS_L(src_size_a) && REG_IS_L(src_size_b)) { + host_arm64_CMP_REG(block, src_reg_a, src_reg_b); + } else if (REG_IS_W(src_size_a) && REG_IS_W(src_size_b)) { + host_arm64_MOV_REG(block, REG_TEMP, src_reg_a, 16); + host_arm64_CMP_REG_LSL(block, REG_TEMP, src_reg_b, 16); + } else if (REG_IS_B(src_size_a) && REG_IS_B(src_size_b)) { + host_arm64_MOV_REG(block, REG_TEMP, src_reg_a, 24); + host_arm64_CMP_REG_LSL(block, REG_TEMP, src_reg_b, 24); + } else + fatal("CMP_JB_DEST %02x\n", uop->src_reg_a_real); - uop->p = host_arm64_BCC_(block); + uop->p = host_arm64_BCC_(block); - return 0; + return 0; } -static int codegen_CMP_JBE_DEST(codeblock_t *block, uop_t *uop) +static int +codegen_CMP_JBE_DEST(codeblock_t *block, uop_t *uop) { - int src_reg_a = HOST_REG_GET(uop->src_reg_a_real), src_reg_b = HOST_REG_GET(uop->src_reg_b_real); - int src_size_a = IREG_GET_SIZE(uop->src_reg_a_real), src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); + int src_reg_a = HOST_REG_GET(uop->src_reg_a_real); + int src_reg_b = HOST_REG_GET(uop->src_reg_b_real); + int src_size_a = IREG_GET_SIZE(uop->src_reg_a_real); + int src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); - if (REG_IS_L(src_size_a) && REG_IS_L(src_size_b)) - { - host_arm64_CMP_REG(block, src_reg_a, src_reg_b); - } - else if (REG_IS_W(src_size_a) && REG_IS_W(src_size_b)) - { - host_arm64_MOV_REG(block, REG_TEMP, src_reg_a, 16); - host_arm64_CMP_REG_LSL(block, REG_TEMP, src_reg_b, 16); - } - else if (REG_IS_B(src_size_a) && REG_IS_B(src_size_b)) - { - host_arm64_MOV_REG(block, REG_TEMP, src_reg_a, 24); - host_arm64_CMP_REG_LSL(block, REG_TEMP, src_reg_b, 24); - } - else - fatal("CMP_JBE_DEST %02x\n", uop->src_reg_a_real); + if (REG_IS_L(src_size_a) && REG_IS_L(src_size_b)) { + host_arm64_CMP_REG(block, src_reg_a, src_reg_b); + } else if (REG_IS_W(src_size_a) && REG_IS_W(src_size_b)) { + host_arm64_MOV_REG(block, REG_TEMP, src_reg_a, 16); + host_arm64_CMP_REG_LSL(block, REG_TEMP, src_reg_b, 16); + } else if (REG_IS_B(src_size_a) && REG_IS_B(src_size_b)) { + host_arm64_MOV_REG(block, REG_TEMP, src_reg_a, 24); + host_arm64_CMP_REG_LSL(block, REG_TEMP, src_reg_b, 24); + } else + fatal("CMP_JBE_DEST %02x\n", uop->src_reg_a_real); - uop->p = host_arm64_BLS_(block); + uop->p = host_arm64_BLS_(block); - return 0; + return 0; } -static int codegen_CMP_JL_DEST(codeblock_t *block, uop_t *uop) +static int +codegen_CMP_JL_DEST(codeblock_t *block, uop_t *uop) { - int src_reg_a = HOST_REG_GET(uop->src_reg_a_real), src_reg_b = HOST_REG_GET(uop->src_reg_b_real); - int src_size_a = IREG_GET_SIZE(uop->src_reg_a_real), src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); + int src_reg_a = HOST_REG_GET(uop->src_reg_a_real); + int src_reg_b = HOST_REG_GET(uop->src_reg_b_real); + int src_size_a = IREG_GET_SIZE(uop->src_reg_a_real); + int src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); - if (REG_IS_L(src_size_a) && REG_IS_L(src_size_b)) - { - host_arm64_CMP_REG(block, src_reg_a, src_reg_b); - } - else if (REG_IS_W(src_size_a) && REG_IS_W(src_size_b)) - { - host_arm64_MOV_REG(block, REG_TEMP, src_reg_a, 16); - host_arm64_CMP_REG_LSL(block, REG_TEMP, src_reg_b, 16); - } - else if (REG_IS_B(src_size_a) && REG_IS_B(src_size_b)) - { - host_arm64_MOV_REG(block, REG_TEMP, src_reg_a, 24); - host_arm64_CMP_REG_LSL(block, REG_TEMP, src_reg_b, 24); - } - else - fatal("CMP_JL_DEST %02x\n", uop->src_reg_a_real); + if (REG_IS_L(src_size_a) && REG_IS_L(src_size_b)) { + host_arm64_CMP_REG(block, src_reg_a, src_reg_b); + } else if (REG_IS_W(src_size_a) && REG_IS_W(src_size_b)) { + host_arm64_MOV_REG(block, REG_TEMP, src_reg_a, 16); + host_arm64_CMP_REG_LSL(block, REG_TEMP, src_reg_b, 16); + } else if (REG_IS_B(src_size_a) && REG_IS_B(src_size_b)) { + host_arm64_MOV_REG(block, REG_TEMP, src_reg_a, 24); + host_arm64_CMP_REG_LSL(block, REG_TEMP, src_reg_b, 24); + } else + fatal("CMP_JL_DEST %02x\n", uop->src_reg_a_real); - uop->p = host_arm64_BLT_(block); + uop->p = host_arm64_BLT_(block); - return 0; + return 0; } -static int codegen_CMP_JLE_DEST(codeblock_t *block, uop_t *uop) +static int +codegen_CMP_JLE_DEST(codeblock_t *block, uop_t *uop) { - int src_reg_a = HOST_REG_GET(uop->src_reg_a_real), src_reg_b = HOST_REG_GET(uop->src_reg_b_real); - int src_size_a = IREG_GET_SIZE(uop->src_reg_a_real), src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); + int src_reg_a = HOST_REG_GET(uop->src_reg_a_real); + int src_reg_b = HOST_REG_GET(uop->src_reg_b_real); + int src_size_a = IREG_GET_SIZE(uop->src_reg_a_real); + int src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); - if (REG_IS_L(src_size_a) && REG_IS_L(src_size_b)) - { - host_arm64_CMP_REG(block, src_reg_a, src_reg_b); - } - else if (REG_IS_W(src_size_a) && REG_IS_W(src_size_b)) - { - host_arm64_MOV_REG(block, REG_TEMP, src_reg_a, 16); - host_arm64_CMP_REG_LSL(block, REG_TEMP, src_reg_b, 16); - } - else if (REG_IS_B(src_size_a) && REG_IS_B(src_size_b)) - { - host_arm64_MOV_REG(block, REG_TEMP, src_reg_a, 24); - host_arm64_CMP_REG_LSL(block, REG_TEMP, src_reg_b, 24); - } - else - fatal("CMP_JLE_DEST %02x\n", uop->src_reg_a_real); + if (REG_IS_L(src_size_a) && REG_IS_L(src_size_b)) { + host_arm64_CMP_REG(block, src_reg_a, src_reg_b); + } else if (REG_IS_W(src_size_a) && REG_IS_W(src_size_b)) { + host_arm64_MOV_REG(block, REG_TEMP, src_reg_a, 16); + host_arm64_CMP_REG_LSL(block, REG_TEMP, src_reg_b, 16); + } else if (REG_IS_B(src_size_a) && REG_IS_B(src_size_b)) { + host_arm64_MOV_REG(block, REG_TEMP, src_reg_a, 24); + host_arm64_CMP_REG_LSL(block, REG_TEMP, src_reg_b, 24); + } else + fatal("CMP_JLE_DEST %02x\n", uop->src_reg_a_real); - uop->p = host_arm64_BLE_(block); + uop->p = host_arm64_BLE_(block); - return 0; + return 0; } -static int codegen_CMP_JO_DEST(codeblock_t *block, uop_t *uop) +static int +codegen_CMP_JO_DEST(codeblock_t *block, uop_t *uop) { - int src_reg_a = HOST_REG_GET(uop->src_reg_a_real), src_reg_b = HOST_REG_GET(uop->src_reg_b_real); - int src_size_a = IREG_GET_SIZE(uop->src_reg_a_real), src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); + int src_reg_a = HOST_REG_GET(uop->src_reg_a_real); + int src_reg_b = HOST_REG_GET(uop->src_reg_b_real); + int src_size_a = IREG_GET_SIZE(uop->src_reg_a_real); + int src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); - if (REG_IS_L(src_size_a) && REG_IS_L(src_size_b)) - { - host_arm64_CMP_REG(block, src_reg_a, src_reg_b); - } - else if (REG_IS_W(src_size_a) && REG_IS_W(src_size_b)) - { - host_arm64_MOV_REG(block, REG_TEMP, src_reg_a, 16); - host_arm64_CMP_REG_LSL(block, REG_TEMP, src_reg_b, 16); - } - else if (REG_IS_B(src_size_a) && REG_IS_B(src_size_b)) - { - host_arm64_MOV_REG(block, REG_TEMP, src_reg_a, 24); - host_arm64_CMP_REG_LSL(block, REG_TEMP, src_reg_b, 24); - } - else - fatal("CMP_JO_DEST %02x\n", uop->src_reg_a_real); + if (REG_IS_L(src_size_a) && REG_IS_L(src_size_b)) { + host_arm64_CMP_REG(block, src_reg_a, src_reg_b); + } else if (REG_IS_W(src_size_a) && REG_IS_W(src_size_b)) { + host_arm64_MOV_REG(block, REG_TEMP, src_reg_a, 16); + host_arm64_CMP_REG_LSL(block, REG_TEMP, src_reg_b, 16); + } else if (REG_IS_B(src_size_a) && REG_IS_B(src_size_b)) { + host_arm64_MOV_REG(block, REG_TEMP, src_reg_a, 24); + host_arm64_CMP_REG_LSL(block, REG_TEMP, src_reg_b, 24); + } else + fatal("CMP_JO_DEST %02x\n", uop->src_reg_a_real); - uop->p = host_arm64_BVS_(block); + uop->p = host_arm64_BVS_(block); - return 0; + return 0; } -static int codegen_CMP_JZ_DEST(codeblock_t *block, uop_t *uop) +static int +codegen_CMP_JZ_DEST(codeblock_t *block, uop_t *uop) { - int src_reg_a = HOST_REG_GET(uop->src_reg_a_real), src_reg_b = HOST_REG_GET(uop->src_reg_b_real); - int src_size_a = IREG_GET_SIZE(uop->src_reg_a_real), src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); + int src_reg_a = HOST_REG_GET(uop->src_reg_a_real); + int src_reg_b = HOST_REG_GET(uop->src_reg_b_real); + int src_size_a = IREG_GET_SIZE(uop->src_reg_a_real); + int src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); - if (REG_IS_L(src_size_a) && REG_IS_L(src_size_b)) - { - host_arm64_CMP_REG(block, src_reg_a, src_reg_b); - } - else if (REG_IS_W(src_size_a) && REG_IS_W(src_size_b)) - { - host_arm64_MOV_REG(block, REG_TEMP, src_reg_a, 16); - host_arm64_CMP_REG_LSL(block, REG_TEMP, src_reg_b, 16); - } - else if (REG_IS_B(src_size_a) && REG_IS_B(src_size_b)) - { - host_arm64_MOV_REG(block, REG_TEMP, src_reg_a, 24); - host_arm64_CMP_REG_LSL(block, REG_TEMP, src_reg_b, 24); - } - else - fatal("CMP_JZ_DEST %02x\n", uop->src_reg_a_real); + if (REG_IS_L(src_size_a) && REG_IS_L(src_size_b)) { + host_arm64_CMP_REG(block, src_reg_a, src_reg_b); + } else if (REG_IS_W(src_size_a) && REG_IS_W(src_size_b)) { + host_arm64_MOV_REG(block, REG_TEMP, src_reg_a, 16); + host_arm64_CMP_REG_LSL(block, REG_TEMP, src_reg_b, 16); + } else if (REG_IS_B(src_size_a) && REG_IS_B(src_size_b)) { + host_arm64_MOV_REG(block, REG_TEMP, src_reg_a, 24); + host_arm64_CMP_REG_LSL(block, REG_TEMP, src_reg_b, 24); + } else + fatal("CMP_JZ_DEST %02x\n", uop->src_reg_a_real); - uop->p = host_arm64_BEQ_(block); + uop->p = host_arm64_BEQ_(block); - return 0; + return 0; } -static int codegen_FABS(codeblock_t *block, uop_t *uop) +static int +codegen_FABS(codeblock_t *block, uop_t *uop) { - int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg_a = HOST_REG_GET(uop->src_reg_a_real); - int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size_a = IREG_GET_SIZE(uop->src_reg_a_real); + int dest_reg = HOST_REG_GET(uop->dest_reg_a_real); + int src_reg_a = HOST_REG_GET(uop->src_reg_a_real); + int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real); + int src_size_a = IREG_GET_SIZE(uop->src_reg_a_real); - if (REG_IS_D(dest_size) && REG_IS_D(src_size_a)) - { - host_arm64_FABS_D(block, dest_reg, src_reg_a); - } - else - fatal("codegen_FABS %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real); + if (REG_IS_D(dest_size) && REG_IS_D(src_size_a)) { + host_arm64_FABS_D(block, dest_reg, src_reg_a); + } else + fatal("codegen_FABS %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real); - return 0; + return 0; } -static int codegen_FCHS(codeblock_t *block, uop_t *uop) +static int +codegen_FCHS(codeblock_t *block, uop_t *uop) { - int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg_a = HOST_REG_GET(uop->src_reg_a_real); - int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size_a = IREG_GET_SIZE(uop->src_reg_a_real); + int dest_reg = HOST_REG_GET(uop->dest_reg_a_real); + int src_reg_a = HOST_REG_GET(uop->src_reg_a_real); + int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real); + int src_size_a = IREG_GET_SIZE(uop->src_reg_a_real); - if (REG_IS_D(dest_size) && REG_IS_D(src_size_a)) - { - host_arm64_FNEG_D(block, dest_reg, src_reg_a); - } - else - fatal("codegen_FCHS %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real); + if (REG_IS_D(dest_size) && REG_IS_D(src_size_a)) { + host_arm64_FNEG_D(block, dest_reg, src_reg_a); + } else + fatal("codegen_FCHS %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real); - return 0; + return 0; } -static int codegen_FSQRT(codeblock_t *block, uop_t *uop) +static int +codegen_FSQRT(codeblock_t *block, uop_t *uop) { - int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg_a = HOST_REG_GET(uop->src_reg_a_real); - int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size_a = IREG_GET_SIZE(uop->src_reg_a_real); + int dest_reg = HOST_REG_GET(uop->dest_reg_a_real); + int src_reg_a = HOST_REG_GET(uop->src_reg_a_real); + int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real); + int src_size_a = IREG_GET_SIZE(uop->src_reg_a_real); - if (REG_IS_D(dest_size) && REG_IS_D(src_size_a)) - { - host_arm64_FSQRT_D(block, dest_reg, src_reg_a); - } - else - fatal("codegen_FSQRT %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real); + if (REG_IS_D(dest_size) && REG_IS_D(src_size_a)) { + host_arm64_FSQRT_D(block, dest_reg, src_reg_a); + } else + fatal("codegen_FSQRT %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real); - return 0; + return 0; } -static int codegen_FTST(codeblock_t *block, uop_t *uop) +static int +codegen_FTST(codeblock_t *block, uop_t *uop) { - int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg_a = HOST_REG_GET(uop->src_reg_a_real); - int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size_a = IREG_GET_SIZE(uop->src_reg_a_real); + int dest_reg = HOST_REG_GET(uop->dest_reg_a_real); + int src_reg_a = HOST_REG_GET(uop->src_reg_a_real); + int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real); + int src_size_a = IREG_GET_SIZE(uop->src_reg_a_real); - if (REG_IS_W(dest_size) && REG_IS_D(src_size_a)) - { - host_arm64_FSUB_D(block, REG_V_TEMP, REG_V_TEMP, REG_V_TEMP); - host_arm64_MOVZ_IMM(block, dest_reg, 0); - host_arm64_FCMP_D(block, src_reg_a, REG_V_TEMP); - host_arm64_ORR_IMM(block, REG_TEMP, dest_reg, C3); - host_arm64_ORR_IMM(block, REG_TEMP2, dest_reg, C0); - host_arm64_CSEL_EQ(block, dest_reg, REG_TEMP, dest_reg); - host_arm64_ORR_IMM(block, REG_TEMP, dest_reg, C0|C2|C3); - host_arm64_CSEL_CC(block, dest_reg, REG_TEMP2, dest_reg); - host_arm64_CSEL_VS(block, dest_reg, REG_TEMP, dest_reg); - } - else - fatal("codegen_FTST %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real); + if (REG_IS_W(dest_size) && REG_IS_D(src_size_a)) { + host_arm64_FSUB_D(block, REG_V_TEMP, REG_V_TEMP, REG_V_TEMP); + host_arm64_MOVZ_IMM(block, dest_reg, 0); + host_arm64_FCMP_D(block, src_reg_a, REG_V_TEMP); + host_arm64_ORR_IMM(block, REG_TEMP, dest_reg, C3); + host_arm64_ORR_IMM(block, REG_TEMP2, dest_reg, C0); + host_arm64_CSEL_EQ(block, dest_reg, REG_TEMP, dest_reg); + host_arm64_ORR_IMM(block, REG_TEMP, dest_reg, C0 | C2 | C3); + host_arm64_CSEL_CC(block, dest_reg, REG_TEMP2, dest_reg); + host_arm64_CSEL_VS(block, dest_reg, REG_TEMP, dest_reg); + } else + fatal("codegen_FTST %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real); - return 0; + return 0; } -static int codegen_FADD(codeblock_t *block, uop_t *uop) +static int +codegen_FADD(codeblock_t *block, uop_t *uop) { - int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg_a = HOST_REG_GET(uop->src_reg_a_real), src_reg_b = HOST_REG_GET(uop->src_reg_b_real); - int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size_a = IREG_GET_SIZE(uop->src_reg_a_real), src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); + int dest_reg = HOST_REG_GET(uop->dest_reg_a_real); + int src_reg_a = HOST_REG_GET(uop->src_reg_a_real); + int src_reg_b = HOST_REG_GET(uop->src_reg_b_real); + int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real); + int src_size_a = IREG_GET_SIZE(uop->src_reg_a_real); + int src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); - if (REG_IS_D(dest_size) && REG_IS_D(src_size_a) && REG_IS_D(src_size_b)) - { - host_arm64_FADD_D(block, dest_reg, src_reg_a, src_reg_b); - } - else - fatal("codegen_FADD %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real); + if (REG_IS_D(dest_size) && REG_IS_D(src_size_a) && REG_IS_D(src_size_b)) { + host_arm64_FADD_D(block, dest_reg, src_reg_a, src_reg_b); + } else + fatal("codegen_FADD %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real); - return 0; + return 0; } -static int codegen_FCOM(codeblock_t *block, uop_t *uop) +static int +codegen_FCOM(codeblock_t *block, uop_t *uop) { - int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg_a = HOST_REG_GET(uop->src_reg_a_real), src_reg_b = HOST_REG_GET(uop->src_reg_b_real); - int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size_a = IREG_GET_SIZE(uop->src_reg_a_real), src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); + int dest_reg = HOST_REG_GET(uop->dest_reg_a_real); + int src_reg_a = HOST_REG_GET(uop->src_reg_a_real); + int src_reg_b = HOST_REG_GET(uop->src_reg_b_real); + int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real); + int src_size_a = IREG_GET_SIZE(uop->src_reg_a_real); + int src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); - if (REG_IS_W(dest_size) && REG_IS_D(src_size_a) && REG_IS_D(src_size_b)) - { - host_arm64_MOVZ_IMM(block, dest_reg, 0); - host_arm64_FCMP_D(block, src_reg_a, src_reg_b); - host_arm64_ORR_IMM(block, REG_TEMP, dest_reg, C3); - host_arm64_ORR_IMM(block, REG_TEMP2, dest_reg, C0); - host_arm64_CSEL_EQ(block, dest_reg, REG_TEMP, dest_reg); - host_arm64_ORR_IMM(block, REG_TEMP, dest_reg, C0|C2|C3); - host_arm64_CSEL_CC(block, dest_reg, REG_TEMP2, dest_reg); - host_arm64_CSEL_VS(block, dest_reg, REG_TEMP, dest_reg); - } - else - fatal("codegen_FCOM %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real); + if (REG_IS_W(dest_size) && REG_IS_D(src_size_a) && REG_IS_D(src_size_b)) { + host_arm64_MOVZ_IMM(block, dest_reg, 0); + host_arm64_FCMP_D(block, src_reg_a, src_reg_b); + host_arm64_ORR_IMM(block, REG_TEMP, dest_reg, C3); + host_arm64_ORR_IMM(block, REG_TEMP2, dest_reg, C0); + host_arm64_CSEL_EQ(block, dest_reg, REG_TEMP, dest_reg); + host_arm64_ORR_IMM(block, REG_TEMP, dest_reg, C0 | C2 | C3); + host_arm64_CSEL_CC(block, dest_reg, REG_TEMP2, dest_reg); + host_arm64_CSEL_VS(block, dest_reg, REG_TEMP, dest_reg); + } else + fatal("codegen_FCOM %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real); - return 0; + return 0; } -static int codegen_FDIV(codeblock_t *block, uop_t *uop) +static int +codegen_FDIV(codeblock_t *block, uop_t *uop) { - int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg_a = HOST_REG_GET(uop->src_reg_a_real), src_reg_b = HOST_REG_GET(uop->src_reg_b_real); - int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size_a = IREG_GET_SIZE(uop->src_reg_a_real), src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); + int dest_reg = HOST_REG_GET(uop->dest_reg_a_real); + int src_reg_a = HOST_REG_GET(uop->src_reg_a_real); + int src_reg_b = HOST_REG_GET(uop->src_reg_b_real); + int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real); + int src_size_a = IREG_GET_SIZE(uop->src_reg_a_real); + int src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); - if (REG_IS_D(dest_size) && REG_IS_D(src_size_a) && REG_IS_D(src_size_b)) - { - host_arm64_FDIV_D(block, dest_reg, src_reg_a, src_reg_b); - } - else - fatal("codegen_FDIV %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real); + if (REG_IS_D(dest_size) && REG_IS_D(src_size_a) && REG_IS_D(src_size_b)) { + host_arm64_FDIV_D(block, dest_reg, src_reg_a, src_reg_b); + } else + fatal("codegen_FDIV %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real); - return 0; + return 0; } -static int codegen_FMUL(codeblock_t *block, uop_t *uop) +static int +codegen_FMUL(codeblock_t *block, uop_t *uop) { - int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg_a = HOST_REG_GET(uop->src_reg_a_real), src_reg_b = HOST_REG_GET(uop->src_reg_b_real); - int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size_a = IREG_GET_SIZE(uop->src_reg_a_real), src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); + int dest_reg = HOST_REG_GET(uop->dest_reg_a_real); + int src_reg_a = HOST_REG_GET(uop->src_reg_a_real); + int src_reg_b = HOST_REG_GET(uop->src_reg_b_real); + int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real); + int src_size_a = IREG_GET_SIZE(uop->src_reg_a_real); + int src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); - if (REG_IS_D(dest_size) && REG_IS_D(src_size_a) && REG_IS_D(src_size_b)) - { - host_arm64_FMUL_D(block, dest_reg, src_reg_a, src_reg_b); - } - else - fatal("codegen_FMUL %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real); + if (REG_IS_D(dest_size) && REG_IS_D(src_size_a) && REG_IS_D(src_size_b)) { + host_arm64_FMUL_D(block, dest_reg, src_reg_a, src_reg_b); + } else + fatal("codegen_FMUL %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real); - return 0; + return 0; } -static int codegen_FSUB(codeblock_t *block, uop_t *uop) +static int +codegen_FSUB(codeblock_t *block, uop_t *uop) { - int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg_a = HOST_REG_GET(uop->src_reg_a_real), src_reg_b = HOST_REG_GET(uop->src_reg_b_real); - int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size_a = IREG_GET_SIZE(uop->src_reg_a_real), src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); + int dest_reg = HOST_REG_GET(uop->dest_reg_a_real); + int src_reg_a = HOST_REG_GET(uop->src_reg_a_real); + int src_reg_b = HOST_REG_GET(uop->src_reg_b_real); + int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real); + int src_size_a = IREG_GET_SIZE(uop->src_reg_a_real); + int src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); - if (REG_IS_D(dest_size) && REG_IS_D(src_size_a) && REG_IS_D(src_size_b)) - { - host_arm64_FSUB_D(block, dest_reg, src_reg_a, src_reg_b); - } - else - fatal("codegen_FSUB %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real); + if (REG_IS_D(dest_size) && REG_IS_D(src_size_a) && REG_IS_D(src_size_b)) { + host_arm64_FSUB_D(block, dest_reg, src_reg_a, src_reg_b); + } else + fatal("codegen_FSUB %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real); - return 0; + return 0; } -static int codegen_FP_ENTER(codeblock_t *block, uop_t *uop) +static int +codegen_FP_ENTER(codeblock_t *block, uop_t *uop) { - uint32_t *branch_ptr; + uint32_t *branch_ptr; - if (!in_range12_w((uintptr_t)&cr0 - (uintptr_t)&cpu_state)) - fatal("codegen_FP_ENTER - out of range\n"); + if (!in_range12_w((uintptr_t) &cr0 - (uintptr_t) &cpu_state)) + fatal("codegen_FP_ENTER - out of range\n"); - host_arm64_LDR_IMM_W(block, REG_TEMP, REG_CPUSTATE, (uintptr_t)&cr0 - (uintptr_t)&cpu_state); - host_arm64_TST_IMM(block, REG_TEMP, 0xc); - branch_ptr = host_arm64_BEQ_(block); + host_arm64_LDR_IMM_W(block, REG_TEMP, REG_CPUSTATE, (uintptr_t) &cr0 - (uintptr_t) &cpu_state); + host_arm64_TST_IMM(block, REG_TEMP, 0xc); + branch_ptr = host_arm64_BEQ_(block); - host_arm64_mov_imm(block, REG_TEMP, uop->imm_data); - host_arm64_STR_IMM_W(block, REG_TEMP, REG_CPUSTATE, (uintptr_t)&cpu_state.oldpc - (uintptr_t)&cpu_state); - host_arm64_mov_imm(block, REG_ARG0, 7); - host_arm64_call(block, x86_int); - host_arm64_B(block, codegen_exit_rout); + host_arm64_mov_imm(block, REG_TEMP, uop->imm_data); + host_arm64_STR_IMM_W(block, REG_TEMP, REG_CPUSTATE, (uintptr_t) &cpu_state.oldpc - (uintptr_t) &cpu_state); + host_arm64_mov_imm(block, REG_ARG0, 7); + host_arm64_call(block, x86_int); + host_arm64_B(block, codegen_exit_rout); - host_arm64_branch_set_offset(branch_ptr, &block_write_data[block_pos]); + host_arm64_branch_set_offset(branch_ptr, &block_write_data[block_pos]); - return 0; + return 0; } -static int codegen_MMX_ENTER(codeblock_t *block, uop_t *uop) +static int +codegen_MMX_ENTER(codeblock_t *block, uop_t *uop) { - uint32_t *branch_ptr; + uint32_t *branch_ptr; - if (!in_range12_w((uintptr_t)&cr0 - (uintptr_t)&cpu_state)) - fatal("codegen_MMX_ENTER - out of range\n"); + if (!in_range12_w((uintptr_t) &cr0 - (uintptr_t) &cpu_state)) + fatal("codegen_MMX_ENTER - out of range\n"); - host_arm64_LDR_IMM_W(block, REG_TEMP, REG_CPUSTATE, (uintptr_t)&cr0 - (uintptr_t)&cpu_state); - host_arm64_TST_IMM(block, REG_TEMP, 0xc); - branch_ptr = host_arm64_BEQ_(block); + host_arm64_LDR_IMM_W(block, REG_TEMP, REG_CPUSTATE, (uintptr_t) &cr0 - (uintptr_t) &cpu_state); + host_arm64_TST_IMM(block, REG_TEMP, 0xc); + branch_ptr = host_arm64_BEQ_(block); - host_arm64_mov_imm(block, REG_TEMP, uop->imm_data); - host_arm64_STR_IMM_W(block, REG_TEMP, REG_CPUSTATE, (uintptr_t)&cpu_state.oldpc - (uintptr_t)&cpu_state); - host_arm64_mov_imm(block, REG_ARG0, 7); - host_arm64_call(block, x86_int); - host_arm64_B(block, codegen_exit_rout); + host_arm64_mov_imm(block, REG_TEMP, uop->imm_data); + host_arm64_STR_IMM_W(block, REG_TEMP, REG_CPUSTATE, (uintptr_t) &cpu_state.oldpc - (uintptr_t) &cpu_state); + host_arm64_mov_imm(block, REG_ARG0, 7); + host_arm64_call(block, x86_int); + host_arm64_B(block, codegen_exit_rout); - host_arm64_branch_set_offset(branch_ptr, &block->data[block_pos]); + host_arm64_branch_set_offset(branch_ptr, &block->data[block_pos]); - host_arm64_mov_imm(block, REG_TEMP, 0x01010101); - host_arm64_STR_IMM_W(block, REG_TEMP, REG_CPUSTATE, (uintptr_t)&cpu_state.tag[0] - (uintptr_t)&cpu_state); - host_arm64_STR_IMM_W(block, REG_TEMP, REG_CPUSTATE, (uintptr_t)&cpu_state.tag[4] - (uintptr_t)&cpu_state); - host_arm64_STR_IMM_W(block, REG_WZR, REG_CPUSTATE, (uintptr_t)&cpu_state.TOP - (uintptr_t)&cpu_state); - host_arm64_STRB_IMM(block, REG_WZR, REG_CPUSTATE, (uintptr_t)&cpu_state.ismmx - (uintptr_t)&cpu_state); + host_arm64_mov_imm(block, REG_TEMP, 0x01010101); + host_arm64_STR_IMM_W(block, REG_TEMP, REG_CPUSTATE, (uintptr_t) &cpu_state.tag[0] - (uintptr_t) &cpu_state); + host_arm64_STR_IMM_W(block, REG_TEMP, REG_CPUSTATE, (uintptr_t) &cpu_state.tag[4] - (uintptr_t) &cpu_state); + host_arm64_STR_IMM_W(block, REG_WZR, REG_CPUSTATE, (uintptr_t) &cpu_state.TOP - (uintptr_t) &cpu_state); + host_arm64_STRB_IMM(block, REG_WZR, REG_CPUSTATE, (uintptr_t) &cpu_state.ismmx - (uintptr_t) &cpu_state); - return 0; + return 0; } -static int codegen_JMP(codeblock_t *block, uop_t *uop) +static int +codegen_JMP(codeblock_t *block, uop_t *uop) { - host_arm64_jump(block, (uintptr_t)uop->p); + host_arm64_jump(block, (uintptr_t) uop->p); - return 0; + return 0; } -static int codegen_LOAD_FUNC_ARG0(codeblock_t *block, uop_t *uop) +static int +codegen_LOAD_FUNC_ARG0(codeblock_t *block, uop_t *uop) { - int src_reg = HOST_REG_GET(uop->src_reg_a_real); - int src_size = IREG_GET_SIZE(uop->src_reg_a_real); + int src_reg = HOST_REG_GET(uop->src_reg_a_real); + int src_size = IREG_GET_SIZE(uop->src_reg_a_real); - if (REG_IS_W(src_size)) - { - host_arm64_AND_IMM(block, REG_ARG0, src_reg, 0xffff); - } - else - fatal("codegen_LOAD_FUNC_ARG0 %02x\n", uop->src_reg_a_real); + if (REG_IS_W(src_size)) { + host_arm64_AND_IMM(block, REG_ARG0, src_reg, 0xffff); + } else + fatal("codegen_LOAD_FUNC_ARG0 %02x\n", uop->src_reg_a_real); - return 0; + return 0; } -static int codegen_LOAD_FUNC_ARG1(codeblock_t *block, uop_t *uop) +static int +codegen_LOAD_FUNC_ARG1(codeblock_t *block, uop_t *uop) { - fatal("codegen_LOAD_FUNC_ARG1 %02x\n", uop->src_reg_a_real); - return 0; + fatal("codegen_LOAD_FUNC_ARG1 %02x\n", uop->src_reg_a_real); + return 0; } -static int codegen_LOAD_FUNC_ARG2(codeblock_t *block, uop_t *uop) +static int +codegen_LOAD_FUNC_ARG2(codeblock_t *block, uop_t *uop) { - fatal("codegen_LOAD_FUNC_ARG2 %02x\n", uop->src_reg_a_real); - return 0; + fatal("codegen_LOAD_FUNC_ARG2 %02x\n", uop->src_reg_a_real); + return 0; } -static int codegen_LOAD_FUNC_ARG3(codeblock_t *block, uop_t *uop) +static int +codegen_LOAD_FUNC_ARG3(codeblock_t *block, uop_t *uop) { - fatal("codegen_LOAD_FUNC_ARG3 %02x\n", uop->src_reg_a_real); - return 0; + fatal("codegen_LOAD_FUNC_ARG3 %02x\n", uop->src_reg_a_real); + return 0; } -static int codegen_LOAD_FUNC_ARG0_IMM(codeblock_t *block, uop_t *uop) +static int +codegen_LOAD_FUNC_ARG0_IMM(codeblock_t *block, uop_t *uop) { - host_arm64_mov_imm(block, REG_ARG0, uop->imm_data); + host_arm64_mov_imm(block, REG_ARG0, uop->imm_data); - return 0; + return 0; } -static int codegen_LOAD_FUNC_ARG1_IMM(codeblock_t *block, uop_t *uop) +static int +codegen_LOAD_FUNC_ARG1_IMM(codeblock_t *block, uop_t *uop) { - host_arm64_mov_imm(block, REG_ARG1, uop->imm_data); + host_arm64_mov_imm(block, REG_ARG1, uop->imm_data); - return 0; + return 0; } -static int codegen_LOAD_FUNC_ARG2_IMM(codeblock_t *block, uop_t *uop) +static int +codegen_LOAD_FUNC_ARG2_IMM(codeblock_t *block, uop_t *uop) { - host_arm64_mov_imm(block, REG_ARG2, uop->imm_data); + host_arm64_mov_imm(block, REG_ARG2, uop->imm_data); - return 0; + return 0; } -static int codegen_LOAD_FUNC_ARG3_IMM(codeblock_t *block, uop_t *uop) +static int +codegen_LOAD_FUNC_ARG3_IMM(codeblock_t *block, uop_t *uop) { - host_arm64_mov_imm(block, REG_ARG3, uop->imm_data); + host_arm64_mov_imm(block, REG_ARG3, uop->imm_data); - return 0; + return 0; } -static int codegen_LOAD_SEG(codeblock_t *block, uop_t *uop) +static int +codegen_LOAD_SEG(codeblock_t *block, uop_t *uop) { - int src_reg = HOST_REG_GET(uop->src_reg_a_real); - int src_size = IREG_GET_SIZE(uop->src_reg_a_real); + int src_reg = HOST_REG_GET(uop->src_reg_a_real); + int src_size = IREG_GET_SIZE(uop->src_reg_a_real); - if (!REG_IS_W(src_size)) - fatal("LOAD_SEG %02x %p\n", uop->src_reg_a_real, uop->p); + if (!REG_IS_W(src_size)) + fatal("LOAD_SEG %02x %p\n", uop->src_reg_a_real, uop->p); - host_arm64_MOVX_IMM(block, REG_ARG1, (uint64_t)uop->p); - host_arm64_AND_IMM(block, REG_ARG0, src_reg, 0xffff); - host_arm64_call(block, (void *)loadseg); - host_arm64_CBNZ(block, REG_X0, (uintptr_t)codegen_exit_rout); + host_arm64_MOVX_IMM(block, REG_ARG1, (uint64_t) uop->p); + host_arm64_AND_IMM(block, REG_ARG0, src_reg, 0xffff); + host_arm64_call(block, (void *) loadseg); + host_arm64_CBNZ(block, REG_X0, (uintptr_t) codegen_exit_rout); - return 0; + return 0; } -static int codegen_MEM_LOAD_ABS(codeblock_t *block, uop_t *uop) +static int +codegen_MEM_LOAD_ABS(codeblock_t *block, uop_t *uop) { - int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), seg_reg = HOST_REG_GET(uop->src_reg_a_real); - int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real); + int dest_reg = HOST_REG_GET(uop->dest_reg_a_real); + int seg_reg = HOST_REG_GET(uop->src_reg_a_real); + int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real); - host_arm64_ADD_IMM(block, REG_X0, seg_reg, uop->imm_data); - if (REG_IS_B(dest_size) || REG_IS_BH(dest_size)) - { - host_arm64_call(block, codegen_mem_load_byte); - } - else if (REG_IS_W(dest_size)) - { - host_arm64_call(block, codegen_mem_load_word); - } - else if (REG_IS_L(dest_size)) - { - host_arm64_call(block, codegen_mem_load_long); - } - else - fatal("MEM_LOAD_ABS - %02x\n", uop->dest_reg_a_real); - host_arm64_CBNZ(block, REG_X1, (uintptr_t)codegen_exit_rout); - if (REG_IS_B(dest_size)) - { - host_arm64_BFI(block, dest_reg, REG_X0, 0, 8); - } - else if (REG_IS_BH(dest_size)) - { - host_arm64_BFI(block, dest_reg, REG_X0, 8, 8); - } - else if (REG_IS_W(dest_size)) - { - host_arm64_BFI(block, dest_reg, REG_X0, 0, 16); - } - else if (REG_IS_L(dest_size)) - { - host_arm64_MOV_REG(block, dest_reg, REG_X0, 0); - } + host_arm64_ADD_IMM(block, REG_X0, seg_reg, uop->imm_data); + if (REG_IS_B(dest_size) || REG_IS_BH(dest_size)) { + host_arm64_call(block, codegen_mem_load_byte); + } else if (REG_IS_W(dest_size)) { + host_arm64_call(block, codegen_mem_load_word); + } else if (REG_IS_L(dest_size)) { + host_arm64_call(block, codegen_mem_load_long); + } else + fatal("MEM_LOAD_ABS - %02x\n", uop->dest_reg_a_real); + host_arm64_CBNZ(block, REG_X1, (uintptr_t) codegen_exit_rout); + if (REG_IS_B(dest_size)) { + host_arm64_BFI(block, dest_reg, REG_X0, 0, 8); + } else if (REG_IS_BH(dest_size)) { + host_arm64_BFI(block, dest_reg, REG_X0, 8, 8); + } else if (REG_IS_W(dest_size)) { + host_arm64_BFI(block, dest_reg, REG_X0, 0, 16); + } else if (REG_IS_L(dest_size)) { + host_arm64_MOV_REG(block, dest_reg, REG_X0, 0); + } - return 0; + return 0; } -static int codegen_MEM_LOAD_REG(codeblock_t *block, uop_t *uop) +static int +codegen_MEM_LOAD_REG(codeblock_t *block, uop_t *uop) { - int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), seg_reg = HOST_REG_GET(uop->src_reg_a_real), addr_reg = HOST_REG_GET(uop->src_reg_b_real); - int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real); + int dest_reg = HOST_REG_GET(uop->dest_reg_a_real); + int seg_reg = HOST_REG_GET(uop->src_reg_a_real); + int addr_reg = HOST_REG_GET(uop->src_reg_b_real); + int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real); - host_arm64_ADD_REG(block, REG_X0, seg_reg, addr_reg, 0); - if (uop->imm_data) - host_arm64_ADD_IMM(block, REG_X0, REG_X0, uop->imm_data); - if (REG_IS_B(dest_size) || REG_IS_BH(dest_size)) - { - host_arm64_call(block, codegen_mem_load_byte); - } - else if (REG_IS_W(dest_size)) - { - host_arm64_call(block, codegen_mem_load_word); - } - else if (REG_IS_L(dest_size)) - { - host_arm64_call(block, codegen_mem_load_long); - } - else if (REG_IS_Q(dest_size)) - { - host_arm64_call(block, codegen_mem_load_quad); - } - else - fatal("MEM_LOAD_REG - %02x\n", uop->dest_reg_a_real); - host_arm64_CBNZ(block, REG_X1, (uintptr_t)codegen_exit_rout); - if (REG_IS_B(dest_size)) - { - host_arm64_BFI(block, dest_reg, REG_X0, 0, 8); - } - else if (REG_IS_BH(dest_size)) - { - host_arm64_BFI(block, dest_reg, REG_X0, 8, 8); - } - else if (REG_IS_W(dest_size)) - { - host_arm64_BFI(block, dest_reg, REG_X0, 0, 16); - } - else if (REG_IS_L(dest_size)) - { - host_arm64_MOV_REG(block, dest_reg, REG_X0, 0); - } - else if (REG_IS_Q(dest_size)) - { - host_arm64_FMOV_D_D(block, dest_reg, REG_V_TEMP); - } + host_arm64_ADD_REG(block, REG_X0, seg_reg, addr_reg, 0); + if (uop->imm_data) + host_arm64_ADD_IMM(block, REG_X0, REG_X0, uop->imm_data); + if (REG_IS_B(dest_size) || REG_IS_BH(dest_size)) { + host_arm64_call(block, codegen_mem_load_byte); + } else if (REG_IS_W(dest_size)) { + host_arm64_call(block, codegen_mem_load_word); + } else if (REG_IS_L(dest_size)) { + host_arm64_call(block, codegen_mem_load_long); + } else if (REG_IS_Q(dest_size)) { + host_arm64_call(block, codegen_mem_load_quad); + } else + fatal("MEM_LOAD_REG - %02x\n", uop->dest_reg_a_real); + host_arm64_CBNZ(block, REG_X1, (uintptr_t) codegen_exit_rout); + if (REG_IS_B(dest_size)) { + host_arm64_BFI(block, dest_reg, REG_X0, 0, 8); + } else if (REG_IS_BH(dest_size)) { + host_arm64_BFI(block, dest_reg, REG_X0, 8, 8); + } else if (REG_IS_W(dest_size)) { + host_arm64_BFI(block, dest_reg, REG_X0, 0, 16); + } else if (REG_IS_L(dest_size)) { + host_arm64_MOV_REG(block, dest_reg, REG_X0, 0); + } else if (REG_IS_Q(dest_size)) { + host_arm64_FMOV_D_D(block, dest_reg, REG_V_TEMP); + } - return 0; + return 0; } -static int codegen_MEM_LOAD_DOUBLE(codeblock_t *block, uop_t *uop) +static int +codegen_MEM_LOAD_DOUBLE(codeblock_t *block, uop_t *uop) { - int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), seg_reg = HOST_REG_GET(uop->src_reg_a_real), addr_reg = HOST_REG_GET(uop->src_reg_b_real); - int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real); + int dest_reg = HOST_REG_GET(uop->dest_reg_a_real); + int seg_reg = HOST_REG_GET(uop->src_reg_a_real); + int addr_reg = HOST_REG_GET(uop->src_reg_b_real); + int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real); - if (!REG_IS_D(dest_size)) - fatal("MEM_LOAD_DOUBLE - %02x\n", uop->dest_reg_a_real); + if (!REG_IS_D(dest_size)) + fatal("MEM_LOAD_DOUBLE - %02x\n", uop->dest_reg_a_real); - host_arm64_ADD_REG(block, REG_X0, seg_reg, addr_reg, 0); - if (uop->imm_data) - host_arm64_ADD_IMM(block, REG_X0, REG_X0, uop->imm_data); - host_arm64_call(block, codegen_mem_load_double); - host_arm64_CBNZ(block, REG_X1, (uintptr_t)codegen_exit_rout); - host_arm64_FMOV_D_D(block, dest_reg, REG_V_TEMP); + host_arm64_ADD_REG(block, REG_X0, seg_reg, addr_reg, 0); + if (uop->imm_data) + host_arm64_ADD_IMM(block, REG_X0, REG_X0, uop->imm_data); + host_arm64_call(block, codegen_mem_load_double); + host_arm64_CBNZ(block, REG_X1, (uintptr_t) codegen_exit_rout); + host_arm64_FMOV_D_D(block, dest_reg, REG_V_TEMP); - return 0; + return 0; } -static int codegen_MEM_LOAD_SINGLE(codeblock_t *block, uop_t *uop) +static int +codegen_MEM_LOAD_SINGLE(codeblock_t *block, uop_t *uop) { - int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), seg_reg = HOST_REG_GET(uop->src_reg_a_real), addr_reg = HOST_REG_GET(uop->src_reg_b_real); - int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real); + int dest_reg = HOST_REG_GET(uop->dest_reg_a_real); + int seg_reg = HOST_REG_GET(uop->src_reg_a_real); + int addr_reg = HOST_REG_GET(uop->src_reg_b_real); + int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real); - if (!REG_IS_D(dest_size)) - fatal("MEM_LOAD_DOUBLE - %02x\n", uop->dest_reg_a_real); + if (!REG_IS_D(dest_size)) + fatal("MEM_LOAD_DOUBLE - %02x\n", uop->dest_reg_a_real); - host_arm64_ADD_REG(block, REG_X0, seg_reg, addr_reg, 0); - if (uop->imm_data) - host_arm64_ADD_IMM(block, REG_X0, REG_X0, uop->imm_data); - host_arm64_call(block, codegen_mem_load_single); - host_arm64_CBNZ(block, REG_X1, (uintptr_t)codegen_exit_rout); - host_arm64_FCVT_D_S(block, dest_reg, REG_V_TEMP); + host_arm64_ADD_REG(block, REG_X0, seg_reg, addr_reg, 0); + if (uop->imm_data) + host_arm64_ADD_IMM(block, REG_X0, REG_X0, uop->imm_data); + host_arm64_call(block, codegen_mem_load_single); + host_arm64_CBNZ(block, REG_X1, (uintptr_t) codegen_exit_rout); + host_arm64_FCVT_D_S(block, dest_reg, REG_V_TEMP); - return 0; + return 0; } -static int codegen_MEM_STORE_ABS(codeblock_t *block, uop_t *uop) +static int +codegen_MEM_STORE_ABS(codeblock_t *block, uop_t *uop) { - int seg_reg = HOST_REG_GET(uop->src_reg_a_real), src_reg = HOST_REG_GET(uop->src_reg_b_real); - int src_size = IREG_GET_SIZE(uop->src_reg_b_real); + int seg_reg = HOST_REG_GET(uop->src_reg_a_real); + int src_reg = HOST_REG_GET(uop->src_reg_b_real); + int src_size = IREG_GET_SIZE(uop->src_reg_b_real); - host_arm64_ADD_IMM(block, REG_W0, seg_reg, uop->imm_data); - if (REG_IS_B(src_size)) - { - host_arm64_AND_IMM(block, REG_W1, src_reg, 0xff); - host_arm64_call(block, codegen_mem_store_byte); - } - else if (REG_IS_BH(src_size)) - { - host_arm64_UBFX(block, REG_W1, src_reg, 8, 8); - host_arm64_call(block, codegen_mem_store_byte); - } - else if (REG_IS_W(src_size)) - { - host_arm64_AND_IMM(block, REG_W1, src_reg, 0xffff); - host_arm64_call(block, codegen_mem_store_word); - } - else if (REG_IS_L(src_size)) - { - host_arm64_MOV_REG(block, REG_W1, src_reg, 0); - host_arm64_call(block, codegen_mem_store_long); - } - else - fatal("MEM_STORE_ABS - %02x\n", uop->dest_reg_a_real); - host_arm64_CBNZ(block, REG_X1, (uintptr_t)codegen_exit_rout); - - return 0; -} -static int codegen_MEM_STORE_REG(codeblock_t *block, uop_t *uop) -{ - int seg_reg = HOST_REG_GET(uop->src_reg_a_real), addr_reg = HOST_REG_GET(uop->src_reg_b_real), src_reg = HOST_REG_GET(uop->src_reg_c_real); - int src_size = IREG_GET_SIZE(uop->src_reg_c_real); - - host_arm64_ADD_REG(block, REG_W0, seg_reg, addr_reg, 0); - if (uop->imm_data) - host_arm64_ADD_IMM(block, REG_X0, REG_X0, uop->imm_data); - if (REG_IS_B(src_size)) - { - host_arm64_AND_IMM(block, REG_W1, src_reg, 0xff); - host_arm64_call(block, codegen_mem_store_byte); - } - else if (REG_IS_BH(src_size)) - { - host_arm64_UBFX(block, REG_W1, src_reg, 8, 8); - host_arm64_call(block, codegen_mem_store_byte); - } - else if (REG_IS_W(src_size)) - { - host_arm64_AND_IMM(block, REG_W1, src_reg, 0xffff); - host_arm64_call(block, codegen_mem_store_word); - } - else if (REG_IS_L(src_size)) - { - host_arm64_MOV_REG(block, REG_W1, src_reg, 0); - host_arm64_call(block, codegen_mem_store_long); - } - else if (REG_IS_Q(src_size)) - { - host_arm64_FMOV_D_D(block, REG_V_TEMP, src_reg); - host_arm64_call(block, codegen_mem_store_quad); - } - else - fatal("MEM_STORE_REG - %02x\n", uop->src_reg_c_real); - host_arm64_CBNZ(block, REG_X1, (uintptr_t)codegen_exit_rout); - - return 0; -} - -static int codegen_MEM_STORE_IMM_8(codeblock_t *block, uop_t *uop) -{ - int seg_reg = HOST_REG_GET(uop->src_reg_a_real), addr_reg = HOST_REG_GET(uop->src_reg_b_real); - - host_arm64_ADD_REG(block, REG_W0, seg_reg, addr_reg, 0); - host_arm64_mov_imm(block, REG_W1, uop->imm_data); + host_arm64_ADD_IMM(block, REG_W0, seg_reg, uop->imm_data); + if (REG_IS_B(src_size)) { + host_arm64_AND_IMM(block, REG_W1, src_reg, 0xff); host_arm64_call(block, codegen_mem_store_byte); - host_arm64_CBNZ(block, REG_X1, (uintptr_t)codegen_exit_rout); - - return 0; -} -static int codegen_MEM_STORE_IMM_16(codeblock_t *block, uop_t *uop) -{ - int seg_reg = HOST_REG_GET(uop->src_reg_a_real), addr_reg = HOST_REG_GET(uop->src_reg_b_real); - - host_arm64_ADD_REG(block, REG_W0, seg_reg, addr_reg, 0); - host_arm64_mov_imm(block, REG_W1, uop->imm_data); + } else if (REG_IS_BH(src_size)) { + host_arm64_UBFX(block, REG_W1, src_reg, 8, 8); + host_arm64_call(block, codegen_mem_store_byte); + } else if (REG_IS_W(src_size)) { + host_arm64_AND_IMM(block, REG_W1, src_reg, 0xffff); host_arm64_call(block, codegen_mem_store_word); - host_arm64_CBNZ(block, REG_X1, (uintptr_t)codegen_exit_rout); - - return 0; -} -static int codegen_MEM_STORE_IMM_32(codeblock_t *block, uop_t *uop) -{ - int seg_reg = HOST_REG_GET(uop->src_reg_a_real), addr_reg = HOST_REG_GET(uop->src_reg_b_real); - - host_arm64_ADD_REG(block, REG_W0, seg_reg, addr_reg, 0); - host_arm64_mov_imm(block, REG_W1, uop->imm_data); + } else if (REG_IS_L(src_size)) { + host_arm64_MOV_REG(block, REG_W1, src_reg, 0); host_arm64_call(block, codegen_mem_store_long); - host_arm64_CBNZ(block, REG_X1, (uintptr_t)codegen_exit_rout); + } else + fatal("MEM_STORE_ABS - %02x\n", uop->dest_reg_a_real); + host_arm64_CBNZ(block, REG_X1, (uintptr_t) codegen_exit_rout); - return 0; + return 0; +} +static int +codegen_MEM_STORE_REG(codeblock_t *block, uop_t *uop) +{ + int seg_reg = HOST_REG_GET(uop->src_reg_a_real); + int addr_reg = HOST_REG_GET(uop->src_reg_b_real); + int src_reg = HOST_REG_GET(uop->src_reg_c_real); + int src_size = IREG_GET_SIZE(uop->src_reg_c_real); + + host_arm64_ADD_REG(block, REG_W0, seg_reg, addr_reg, 0); + if (uop->imm_data) + host_arm64_ADD_IMM(block, REG_X0, REG_X0, uop->imm_data); + if (REG_IS_B(src_size)) { + host_arm64_AND_IMM(block, REG_W1, src_reg, 0xff); + host_arm64_call(block, codegen_mem_store_byte); + } else if (REG_IS_BH(src_size)) { + host_arm64_UBFX(block, REG_W1, src_reg, 8, 8); + host_arm64_call(block, codegen_mem_store_byte); + } else if (REG_IS_W(src_size)) { + host_arm64_AND_IMM(block, REG_W1, src_reg, 0xffff); + host_arm64_call(block, codegen_mem_store_word); + } else if (REG_IS_L(src_size)) { + host_arm64_MOV_REG(block, REG_W1, src_reg, 0); + host_arm64_call(block, codegen_mem_store_long); + } else if (REG_IS_Q(src_size)) { + host_arm64_FMOV_D_D(block, REG_V_TEMP, src_reg); + host_arm64_call(block, codegen_mem_store_quad); + } else + fatal("MEM_STORE_REG - %02x\n", uop->src_reg_c_real); + host_arm64_CBNZ(block, REG_X1, (uintptr_t) codegen_exit_rout); + + return 0; } -static int codegen_MEM_STORE_SINGLE(codeblock_t *block, uop_t *uop) +static int +codegen_MEM_STORE_IMM_8(codeblock_t *block, uop_t *uop) { - int seg_reg = HOST_REG_GET(uop->src_reg_a_real), addr_reg = HOST_REG_GET(uop->src_reg_b_real), src_reg = HOST_REG_GET(uop->src_reg_c_real); - int src_size = IREG_GET_SIZE(uop->src_reg_c_real); + int seg_reg = HOST_REG_GET(uop->src_reg_a_real); + int addr_reg = HOST_REG_GET(uop->src_reg_b_real); - if (!REG_IS_D(src_size)) - fatal("MEM_STORE_REG - %02x\n", uop->dest_reg_a_real); + host_arm64_ADD_REG(block, REG_W0, seg_reg, addr_reg, 0); + host_arm64_mov_imm(block, REG_W1, uop->imm_data); + host_arm64_call(block, codegen_mem_store_byte); + host_arm64_CBNZ(block, REG_X1, (uintptr_t) codegen_exit_rout); - host_arm64_ADD_REG(block, REG_W0, seg_reg, addr_reg, 0); - if (uop->imm_data) - host_arm64_ADD_IMM(block, REG_X0, REG_X0, uop->imm_data); - host_arm64_FCVT_S_D(block, REG_V_TEMP, src_reg); - host_arm64_call(block, codegen_mem_store_single); - host_arm64_CBNZ(block, REG_X1, (uintptr_t)codegen_exit_rout); - - return 0; + return 0; } -static int codegen_MEM_STORE_DOUBLE(codeblock_t *block, uop_t *uop) +static int +codegen_MEM_STORE_IMM_16(codeblock_t *block, uop_t *uop) { - int seg_reg = HOST_REG_GET(uop->src_reg_a_real), addr_reg = HOST_REG_GET(uop->src_reg_b_real), src_reg = HOST_REG_GET(uop->src_reg_c_real); - int src_size = IREG_GET_SIZE(uop->src_reg_c_real); + int seg_reg = HOST_REG_GET(uop->src_reg_a_real); + int addr_reg = HOST_REG_GET(uop->src_reg_b_real); - if (!REG_IS_D(src_size)) - fatal("MEM_STORE_REG - %02x\n", uop->dest_reg_a_real); + host_arm64_ADD_REG(block, REG_W0, seg_reg, addr_reg, 0); + host_arm64_mov_imm(block, REG_W1, uop->imm_data); + host_arm64_call(block, codegen_mem_store_word); + host_arm64_CBNZ(block, REG_X1, (uintptr_t) codegen_exit_rout); - host_arm64_ADD_REG(block, REG_W0, seg_reg, addr_reg, 0); - if (uop->imm_data) - host_arm64_ADD_IMM(block, REG_X0, REG_X0, uop->imm_data); - host_arm64_FMOV_D_D(block, REG_V_TEMP, src_reg); - host_arm64_call(block, codegen_mem_store_double); - host_arm64_CBNZ(block, REG_X1, (uintptr_t)codegen_exit_rout); + return 0; +} +static int +codegen_MEM_STORE_IMM_32(codeblock_t *block, uop_t *uop) +{ + int seg_reg = HOST_REG_GET(uop->src_reg_a_real); + int addr_reg = HOST_REG_GET(uop->src_reg_b_real); - return 0; + host_arm64_ADD_REG(block, REG_W0, seg_reg, addr_reg, 0); + host_arm64_mov_imm(block, REG_W1, uop->imm_data); + host_arm64_call(block, codegen_mem_store_long); + host_arm64_CBNZ(block, REG_X1, (uintptr_t) codegen_exit_rout); + + return 0; } -static int codegen_MOV(codeblock_t *block, uop_t *uop) +static int +codegen_MEM_STORE_SINGLE(codeblock_t *block, uop_t *uop) { - int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg = HOST_REG_GET(uop->src_reg_a_real); - int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size = IREG_GET_SIZE(uop->src_reg_a_real); + int seg_reg = HOST_REG_GET(uop->src_reg_a_real); + int addr_reg = HOST_REG_GET(uop->src_reg_b_real); + int src_reg = HOST_REG_GET(uop->src_reg_c_real); + int src_size = IREG_GET_SIZE(uop->src_reg_c_real); - if (REG_IS_L(dest_size) && REG_IS_L(src_size)) - { - host_arm64_MOV_REG(block, dest_reg, src_reg, 0); - } - else if (REG_IS_W(dest_size) && REG_IS_W(src_size)) - { - host_arm64_BFI(block, dest_reg, src_reg, 0, 16); - } - else if (REG_IS_B(dest_size) && REG_IS_B(src_size)) - { - host_arm64_BFI(block, dest_reg, src_reg, 0, 8); - } - else if (REG_IS_B(dest_size) && REG_IS_BH(src_size)) - { - host_arm64_MOV_REG_LSR(block, REG_TEMP, src_reg, 8); - host_arm64_BFI(block, dest_reg, REG_TEMP, 0, 8); - } - else if (REG_IS_BH(dest_size) && REG_IS_B(src_size)) - { - host_arm64_BFI(block, dest_reg, src_reg, 8, 8); - } - else if (REG_IS_BH(dest_size) && REG_IS_BH(src_size)) - { - host_arm64_MOV_REG_LSR(block, REG_TEMP, src_reg, 8); - host_arm64_BFI(block, dest_reg, REG_TEMP, 8, 8); - } - else if (REG_IS_D(dest_size) && REG_IS_D(src_size)) - { - host_arm64_FMOV_D_D(block, dest_reg, src_reg); - } - else if (REG_IS_Q(dest_size) && REG_IS_Q(src_size)) - { - host_arm64_FMOV_D_D(block, dest_reg, src_reg); - } - else - fatal("MOV %x %x\n", uop->dest_reg_a_real, uop->src_reg_a_real); + if (!REG_IS_D(src_size)) + fatal("MEM_STORE_REG - %02x\n", uop->dest_reg_a_real); - return 0; + host_arm64_ADD_REG(block, REG_W0, seg_reg, addr_reg, 0); + if (uop->imm_data) + host_arm64_ADD_IMM(block, REG_X0, REG_X0, uop->imm_data); + host_arm64_FCVT_S_D(block, REG_V_TEMP, src_reg); + host_arm64_call(block, codegen_mem_store_single); + host_arm64_CBNZ(block, REG_X1, (uintptr_t) codegen_exit_rout); + + return 0; } -static int codegen_MOV_IMM(codeblock_t *block, uop_t *uop) +static int +codegen_MEM_STORE_DOUBLE(codeblock_t *block, uop_t *uop) { - int dest_reg = HOST_REG_GET(uop->dest_reg_a_real); - int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real); + int seg_reg = HOST_REG_GET(uop->src_reg_a_real); + int addr_reg = HOST_REG_GET(uop->src_reg_b_real); + int src_reg = HOST_REG_GET(uop->src_reg_c_real); + int src_size = IREG_GET_SIZE(uop->src_reg_c_real); - if (REG_IS_L(dest_size)) - { - host_arm64_mov_imm(block, dest_reg, uop->imm_data); - } - else if (REG_IS_W(dest_size)) - { - host_arm64_MOVK_IMM(block, dest_reg, uop->imm_data & 0xffff); - } - else if (REG_IS_B(dest_size)) - { - host_arm64_MOVZ_IMM(block, REG_TEMP, uop->imm_data & 0xff); - host_arm64_BFI(block, dest_reg, REG_TEMP, 0, 8); - } - else if (REG_IS_BH(dest_size)) - { - host_arm64_MOVZ_IMM(block, REG_TEMP, uop->imm_data & 0xff); - host_arm64_BFI(block, dest_reg, REG_TEMP, 8, 8); - } - else - fatal("MOV_IMM %x\n", uop->dest_reg_a_real); + if (!REG_IS_D(src_size)) + fatal("MEM_STORE_REG - %02x\n", uop->dest_reg_a_real); - return 0; -} -static int codegen_MOV_PTR(codeblock_t *block, uop_t *uop) -{ - host_arm64_MOVX_IMM(block, uop->dest_reg_a_real, (uint64_t)uop->p); + host_arm64_ADD_REG(block, REG_W0, seg_reg, addr_reg, 0); + if (uop->imm_data) + host_arm64_ADD_IMM(block, REG_X0, REG_X0, uop->imm_data); + host_arm64_FMOV_D_D(block, REG_V_TEMP, src_reg); + host_arm64_call(block, codegen_mem_store_double); + host_arm64_CBNZ(block, REG_X1, (uintptr_t) codegen_exit_rout); - return 0; + return 0; } -static int codegen_MOVSX(codeblock_t *block, uop_t *uop) +static int +codegen_MOV(codeblock_t *block, uop_t *uop) { - int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg = HOST_REG_GET(uop->src_reg_a_real); - int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size = IREG_GET_SIZE(uop->src_reg_a_real); + int dest_reg = HOST_REG_GET(uop->dest_reg_a_real); + int src_reg = HOST_REG_GET(uop->src_reg_a_real); + int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real); + int src_size = IREG_GET_SIZE(uop->src_reg_a_real); - if (REG_IS_L(dest_size) && REG_IS_B(src_size)) - { - host_arm64_SBFX(block, dest_reg, src_reg, 0, 8); - } - else if (REG_IS_L(dest_size) && REG_IS_BH(src_size)) - { - host_arm64_SBFX(block, dest_reg, src_reg, 8, 8); - } - else if (REG_IS_L(dest_size) && REG_IS_W(src_size)) - { - host_arm64_SBFX(block, dest_reg, src_reg, 0, 16); - } - else if (REG_IS_W(dest_size) && REG_IS_B(src_size)) - { - host_arm64_SBFX(block, REG_TEMP, src_reg, 0, 8); - host_arm64_BFI(block, dest_reg, REG_TEMP, 0, 16); - } - else if (REG_IS_W(dest_size) && REG_IS_BH(src_size)) - { - host_arm64_SBFX(block, REG_TEMP, src_reg, 8, 8); - host_arm64_BFI(block, dest_reg, REG_TEMP, 0, 16); - } - else - fatal("MOVSX %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real); + if (REG_IS_L(dest_size) && REG_IS_L(src_size)) { + host_arm64_MOV_REG(block, dest_reg, src_reg, 0); + } else if (REG_IS_W(dest_size) && REG_IS_W(src_size)) { + host_arm64_BFI(block, dest_reg, src_reg, 0, 16); + } else if (REG_IS_B(dest_size) && REG_IS_B(src_size)) { + host_arm64_BFI(block, dest_reg, src_reg, 0, 8); + } else if (REG_IS_B(dest_size) && REG_IS_BH(src_size)) { + host_arm64_MOV_REG_LSR(block, REG_TEMP, src_reg, 8); + host_arm64_BFI(block, dest_reg, REG_TEMP, 0, 8); + } else if (REG_IS_BH(dest_size) && REG_IS_B(src_size)) { + host_arm64_BFI(block, dest_reg, src_reg, 8, 8); + } else if (REG_IS_BH(dest_size) && REG_IS_BH(src_size)) { + host_arm64_MOV_REG_LSR(block, REG_TEMP, src_reg, 8); + host_arm64_BFI(block, dest_reg, REG_TEMP, 8, 8); + } else if (REG_IS_D(dest_size) && REG_IS_D(src_size)) { + host_arm64_FMOV_D_D(block, dest_reg, src_reg); + } else if (REG_IS_Q(dest_size) && REG_IS_Q(src_size)) { + host_arm64_FMOV_D_D(block, dest_reg, src_reg); + } else + fatal("MOV %x %x\n", uop->dest_reg_a_real, uop->src_reg_a_real); - return 0; + return 0; } -static int codegen_MOVZX(codeblock_t *block, uop_t *uop) +static int +codegen_MOV_IMM(codeblock_t *block, uop_t *uop) { - int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg = HOST_REG_GET(uop->src_reg_a_real); - int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size = IREG_GET_SIZE(uop->src_reg_a_real); + int dest_reg = HOST_REG_GET(uop->dest_reg_a_real); + int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real); - if (REG_IS_Q(dest_size) && REG_IS_L(src_size)) - { - host_arm64_FMOV_D_Q(block, dest_reg, src_reg); - } - else if (REG_IS_L(dest_size) && REG_IS_Q(src_size)) - { - host_arm64_FMOV_W_S(block, dest_reg, src_reg); - } - else if (REG_IS_L(dest_size) && REG_IS_B(src_size)) - { - host_arm64_AND_IMM(block, dest_reg, src_reg, 0xff); - } - else if (REG_IS_L(dest_size) && REG_IS_BH(src_size)) - { - host_arm64_UBFX(block, dest_reg, src_reg, 8, 8); - } - else if (REG_IS_L(dest_size) && REG_IS_W(src_size)) - { - host_arm64_AND_IMM(block, dest_reg, src_reg, 0xffff); - } - else if (REG_IS_W(dest_size) && REG_IS_B(src_size)) - { - host_arm64_AND_IMM(block, REG_TEMP, src_reg, 0xff); - host_arm64_BFI(block, dest_reg, REG_TEMP, 0, 16); - } - else if (REG_IS_W(dest_size) && REG_IS_BH(src_size)) - { - host_arm64_UBFX(block, REG_TEMP, src_reg, 8, 8); - host_arm64_BFI(block, dest_reg, REG_TEMP, 0, 16); - } - else - fatal("MOVZX %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real); + if (REG_IS_L(dest_size)) { + host_arm64_mov_imm(block, dest_reg, uop->imm_data); + } else if (REG_IS_W(dest_size)) { + host_arm64_MOVK_IMM(block, dest_reg, uop->imm_data & 0xffff); + } else if (REG_IS_B(dest_size)) { + host_arm64_MOVZ_IMM(block, REG_TEMP, uop->imm_data & 0xff); + host_arm64_BFI(block, dest_reg, REG_TEMP, 0, 8); + } else if (REG_IS_BH(dest_size)) { + host_arm64_MOVZ_IMM(block, REG_TEMP, uop->imm_data & 0xff); + host_arm64_BFI(block, dest_reg, REG_TEMP, 8, 8); + } else + fatal("MOV_IMM %x\n", uop->dest_reg_a_real); - return 0; + return 0; +} +static int +codegen_MOV_PTR(codeblock_t *block, uop_t *uop) +{ + host_arm64_MOVX_IMM(block, uop->dest_reg_a_real, (uint64_t) uop->p); + + return 0; } -static int codegen_MOV_DOUBLE_INT(codeblock_t *block, uop_t *uop) +static int +codegen_MOVSX(codeblock_t *block, uop_t *uop) { - int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg = HOST_REG_GET(uop->src_reg_a_real); - int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size = IREG_GET_SIZE(uop->src_reg_a_real); + int dest_reg = HOST_REG_GET(uop->dest_reg_a_real); + int src_reg = HOST_REG_GET(uop->src_reg_a_real); + int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real); + int src_size = IREG_GET_SIZE(uop->src_reg_a_real); - if (REG_IS_D(dest_size) && REG_IS_L(src_size)) - { - host_arm64_SCVTF_D_W(block, dest_reg, src_reg); - } - else if (REG_IS_D(dest_size) && REG_IS_W(src_size)) - { - host_arm64_SBFX(block, REG_TEMP, src_reg, 0, 16); - host_arm64_SCVTF_D_W(block, dest_reg, REG_TEMP); - } - else if (REG_IS_D(dest_size) && REG_IS_Q(src_size)) - { - host_arm64_FMOV_Q_D(block, REG_TEMP, src_reg); - host_arm64_SCVTF_D_Q(block, dest_reg, REG_TEMP); - } + if (REG_IS_L(dest_size) && REG_IS_B(src_size)) { + host_arm64_SBFX(block, dest_reg, src_reg, 0, 8); + } else if (REG_IS_L(dest_size) && REG_IS_BH(src_size)) { + host_arm64_SBFX(block, dest_reg, src_reg, 8, 8); + } else if (REG_IS_L(dest_size) && REG_IS_W(src_size)) { + host_arm64_SBFX(block, dest_reg, src_reg, 0, 16); + } else if (REG_IS_W(dest_size) && REG_IS_B(src_size)) { + host_arm64_SBFX(block, REG_TEMP, src_reg, 0, 8); + host_arm64_BFI(block, dest_reg, REG_TEMP, 0, 16); + } else if (REG_IS_W(dest_size) && REG_IS_BH(src_size)) { + host_arm64_SBFX(block, REG_TEMP, src_reg, 8, 8); + host_arm64_BFI(block, dest_reg, REG_TEMP, 0, 16); + } else + fatal("MOVSX %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real); + + return 0; +} +static int +codegen_MOVZX(codeblock_t *block, uop_t *uop) +{ + int dest_reg = HOST_REG_GET(uop->dest_reg_a_real); + int src_reg = HOST_REG_GET(uop->src_reg_a_real); + int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real); + int src_size = IREG_GET_SIZE(uop->src_reg_a_real); + + if (REG_IS_Q(dest_size) && REG_IS_L(src_size)) { + host_arm64_FMOV_D_Q(block, dest_reg, src_reg); + } else if (REG_IS_L(dest_size) && REG_IS_Q(src_size)) { + host_arm64_FMOV_W_S(block, dest_reg, src_reg); + } else if (REG_IS_L(dest_size) && REG_IS_B(src_size)) { + host_arm64_AND_IMM(block, dest_reg, src_reg, 0xff); + } else if (REG_IS_L(dest_size) && REG_IS_BH(src_size)) { + host_arm64_UBFX(block, dest_reg, src_reg, 8, 8); + } else if (REG_IS_L(dest_size) && REG_IS_W(src_size)) { + host_arm64_AND_IMM(block, dest_reg, src_reg, 0xffff); + } else if (REG_IS_W(dest_size) && REG_IS_B(src_size)) { + host_arm64_AND_IMM(block, REG_TEMP, src_reg, 0xff); + host_arm64_BFI(block, dest_reg, REG_TEMP, 0, 16); + } else if (REG_IS_W(dest_size) && REG_IS_BH(src_size)) { + host_arm64_UBFX(block, REG_TEMP, src_reg, 8, 8); + host_arm64_BFI(block, dest_reg, REG_TEMP, 0, 16); + } else + fatal("MOVZX %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real); + + return 0; +} + +static int +codegen_MOV_DOUBLE_INT(codeblock_t *block, uop_t *uop) +{ + int dest_reg = HOST_REG_GET(uop->dest_reg_a_real); + int src_reg = HOST_REG_GET(uop->src_reg_a_real); + int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real); + int src_size = IREG_GET_SIZE(uop->src_reg_a_real); + + if (REG_IS_D(dest_size) && REG_IS_L(src_size)) { + host_arm64_SCVTF_D_W(block, dest_reg, src_reg); + } else if (REG_IS_D(dest_size) && REG_IS_W(src_size)) { + host_arm64_SBFX(block, REG_TEMP, src_reg, 0, 16); + host_arm64_SCVTF_D_W(block, dest_reg, REG_TEMP); + } else if (REG_IS_D(dest_size) && REG_IS_Q(src_size)) { + host_arm64_FMOV_Q_D(block, REG_TEMP, src_reg); + host_arm64_SCVTF_D_Q(block, dest_reg, REG_TEMP); + } else + fatal("MOV_DOUBLE_INT %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real); + + return 0; +} +static int +codegen_MOV_INT_DOUBLE(codeblock_t *block, uop_t *uop) +{ + int dest_reg = HOST_REG_GET(uop->dest_reg_a_real); + int src_reg = HOST_REG_GET(uop->src_reg_a_real); + int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real); + int src_size = IREG_GET_SIZE(uop->src_reg_a_real); + + if (REG_IS_L(dest_size) && REG_IS_D(src_size)) { + host_arm64_FMOV_D_D(block, REG_V_TEMP, src_reg); + host_arm64_call(block, codegen_fp_round); + host_arm64_MOV_REG(block, dest_reg, REG_TEMP, 0); + } else if (REG_IS_W(dest_size) && REG_IS_D(src_size)) { + host_arm64_FMOV_D_D(block, REG_V_TEMP, src_reg); + host_arm64_call(block, codegen_fp_round); + host_arm64_BFI(block, dest_reg, REG_TEMP, 0, 16); + } else + fatal("MOV_INT_DOUBLE %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real); + + return 0; +} +static int +codegen_MOV_INT_DOUBLE_64(codeblock_t *block, uop_t *uop) +{ + int dest_reg = HOST_REG_GET(uop->dest_reg_a_real); + int src_reg = HOST_REG_GET(uop->src_reg_a_real); + int src_64_reg = HOST_REG_GET(uop->src_reg_b_real); + int tag_reg = HOST_REG_GET(uop->src_reg_c_real); + int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real); + int src_size = IREG_GET_SIZE(uop->src_reg_a_real); + int src_64_size = IREG_GET_SIZE(uop->src_reg_b_real); + + if (REG_IS_Q(dest_size) && REG_IS_D(src_size) && REG_IS_Q(src_64_size)) { + uint32_t *branch_offset; + + /*If TAG_UINT64 is set then the source is MM[]. Otherwise it is a double in ST()*/ + host_arm64_FMOV_D_D(block, dest_reg, src_64_reg); + branch_offset = host_arm64_TBNZ(block, tag_reg, 7); + + host_arm64_FMOV_D_D(block, REG_V_TEMP, src_reg); + host_arm64_call(block, codegen_fp_round_quad); + host_arm64_FMOV_D_Q(block, dest_reg, REG_TEMP); + + host_arm64_branch_set_offset(branch_offset, &block_write_data[block_pos]); + } else + fatal("MOV_INT_DOUBLE_64 %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real); + + return 0; +} +static int +codegen_MOV_REG_PTR(codeblock_t *block, uop_t *uop) +{ + int dest_reg = HOST_REG_GET(uop->dest_reg_a_real); + int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real); + + host_arm64_MOVX_IMM(block, REG_TEMP, (uint64_t) uop->p); + if (REG_IS_L(dest_size)) { + host_arm64_LDR_IMM_W(block, dest_reg, REG_TEMP, 0); + } else + fatal("MOV_REG_PTR %02x\n", uop->dest_reg_a_real); + + return 0; +} +static int +codegen_MOVZX_REG_PTR_8(codeblock_t *block, uop_t *uop) +{ + int dest_reg = HOST_REG_GET(uop->dest_reg_a_real); + int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real); + + host_arm64_MOVX_IMM(block, REG_TEMP, (uint64_t) uop->p); + if (REG_IS_L(dest_size)) { + host_arm64_LDRB_IMM_W(block, dest_reg, REG_TEMP, 0); + } else if (REG_IS_W(dest_size)) { + host_arm64_LDRB_IMM_W(block, REG_TEMP, REG_TEMP, 0); + host_arm64_BFI(block, dest_reg, REG_TEMP, 0, 16); + } else if (REG_IS_B(dest_size)) { + host_arm64_LDRB_IMM_W(block, REG_TEMP, REG_TEMP, 0); + host_arm64_BFI(block, dest_reg, REG_TEMP, 0, 8); + } else + fatal("MOVZX_REG_PTR_8 %02x\n", uop->dest_reg_a_real); + + return 0; +} +static int +codegen_MOVZX_REG_PTR_16(codeblock_t *block, uop_t *uop) +{ + int dest_reg = HOST_REG_GET(uop->dest_reg_a_real); + int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real); + + host_arm64_MOVX_IMM(block, REG_TEMP, (uint64_t) uop->p); + if (REG_IS_L(dest_size)) { + host_arm64_LDRH_IMM(block, dest_reg, REG_TEMP, 0); + } else if (REG_IS_W(dest_size)) { + host_arm64_LDRH_IMM(block, REG_TEMP, REG_TEMP, 0); + host_arm64_BFI(block, dest_reg, REG_TEMP, 0, 16); + } else + fatal("MOVZX_REG_PTR_16 %02x\n", uop->dest_reg_a_real); + + return 0; +} + +static int +codegen_NOP(codeblock_t *block, uop_t *uop) +{ + return 0; +} + +static int +codegen_OR(codeblock_t *block, uop_t *uop) +{ + int dest_reg = HOST_REG_GET(uop->dest_reg_a_real); + int src_reg_a = HOST_REG_GET(uop->src_reg_a_real); + int src_reg_b = HOST_REG_GET(uop->src_reg_b_real); + int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real); + int src_size_a = IREG_GET_SIZE(uop->src_reg_a_real); + int src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); + + if (REG_IS_Q(dest_size) && REG_IS_Q(src_size_a) && REG_IS_Q(src_size_b)) { + host_arm64_ORR_REG_V(block, dest_reg, src_reg_a, src_reg_b); + } else if (REG_IS_L(dest_size) && REG_IS_L(src_size_a) && REG_IS_L(src_size_b)) { + host_arm64_ORR_REG(block, dest_reg, src_reg_a, src_reg_b, 0); + } else if (REG_IS_W(dest_size) && REG_IS_W(src_size_a) && REG_IS_W(src_size_b)) { + host_arm64_ORR_REG(block, REG_TEMP, src_reg_a, src_reg_b, 0); + host_arm64_BFI(block, dest_reg, REG_TEMP, 0, 16); + } else if (REG_IS_B(dest_size) && REG_IS_B(src_size_a) && REG_IS_B(src_size_b) && dest_reg == src_reg_a) { + host_arm64_AND_IMM(block, REG_TEMP, src_reg_b, 0xff); + host_arm64_ORR_REG(block, dest_reg, src_reg_a, REG_TEMP, 0); + } else if (REG_IS_B(dest_size) && REG_IS_B(src_size_a) && REG_IS_BH(src_size_b) && dest_reg == src_reg_a) { + host_arm64_UBFX(block, REG_TEMP, src_reg_b, 8, 8); + host_arm64_ORR_REG(block, dest_reg, src_reg_a, REG_TEMP, 0); + } else if (REG_IS_BH(dest_size) && REG_IS_BH(src_size_a) && REG_IS_B(src_size_b) && dest_reg == src_reg_a) { + host_arm64_AND_IMM(block, REG_TEMP, src_reg_b, 0xff); + host_arm64_ORR_REG(block, dest_reg, src_reg_a, REG_TEMP, 8); + } else if (REG_IS_BH(dest_size) && REG_IS_BH(src_size_a) && REG_IS_BH(src_size_b) && dest_reg == src_reg_a) { + host_arm64_UBFX(block, REG_TEMP, src_reg_b, 8, 8); + host_arm64_ORR_REG(block, dest_reg, src_reg_a, REG_TEMP, 8); + } else + fatal("OR %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real); + + return 0; +} +static int +codegen_OR_IMM(codeblock_t *block, uop_t *uop) +{ + int dest_reg = HOST_REG_GET(uop->dest_reg_a_real); + int src_reg = HOST_REG_GET(uop->src_reg_a_real); + int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real); + int src_size = IREG_GET_SIZE(uop->src_reg_a_real); + + if (REG_IS_L(dest_size) && REG_IS_L(src_size)) { + host_arm64_ORR_IMM(block, dest_reg, src_reg, uop->imm_data); + } else if (REG_IS_W(dest_size) && REG_IS_W(src_size) && dest_reg == src_reg) { + host_arm64_ORR_IMM(block, dest_reg, src_reg, uop->imm_data); + } else if (REG_IS_B(dest_size) && REG_IS_B(src_size) && dest_reg == src_reg) { + host_arm64_ORR_IMM(block, dest_reg, src_reg, uop->imm_data); + } else if (REG_IS_BH(dest_size) && REG_IS_BH(src_size) && dest_reg == src_reg) { + host_arm64_ORR_IMM(block, dest_reg, src_reg, uop->imm_data << 8); + } else + fatal("OR_IMM %x %x\n", uop->dest_reg_a_real, uop->src_reg_a_real); + + return 0; +} + +static int +codegen_PACKSSWB(codeblock_t *block, uop_t *uop) +{ + int dest_reg = HOST_REG_GET(uop->dest_reg_a_real); + int src_reg_b = HOST_REG_GET(uop->src_reg_b_real); + int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real); + int src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); + + if (REG_IS_Q(dest_size) && REG_IS_Q(src_size_b) && uop->dest_reg_a_real == uop->src_reg_a_real) { + host_arm64_SQXTN_V8B_8H(block, REG_V_TEMP, src_reg_b); + host_arm64_SQXTN_V8B_8H(block, dest_reg, dest_reg); + host_arm64_ZIP1_V2S(block, dest_reg, dest_reg, REG_V_TEMP); + } else + fatal("PACKSSWB %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real); + + return 0; +} +static int +codegen_PACKSSDW(codeblock_t *block, uop_t *uop) +{ + int dest_reg = HOST_REG_GET(uop->dest_reg_a_real); + int src_reg_b = HOST_REG_GET(uop->src_reg_b_real); + int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real); + int src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); + + if (REG_IS_Q(dest_size) && REG_IS_Q(src_size_b) && uop->dest_reg_a_real == uop->src_reg_a_real) { + host_arm64_SQXTN_V4H_4S(block, REG_V_TEMP, src_reg_b); + host_arm64_SQXTN_V4H_4S(block, dest_reg, dest_reg); + host_arm64_ZIP1_V2S(block, dest_reg, dest_reg, REG_V_TEMP); + } else + fatal("PACKSSDW %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real); + + return 0; +} +static int +codegen_PACKUSWB(codeblock_t *block, uop_t *uop) +{ + int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg_b = HOST_REG_GET(uop->src_reg_b_real); + int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); + + if (REG_IS_Q(dest_size) && REG_IS_Q(src_size_b) && uop->dest_reg_a_real == uop->src_reg_a_real) { + host_arm64_UQXTN_V8B_8H(block, REG_V_TEMP, src_reg_b); + host_arm64_UQXTN_V8B_8H(block, dest_reg, dest_reg); + host_arm64_ZIP1_V2S(block, dest_reg, dest_reg, REG_V_TEMP); + } else + fatal("PACKUSWB %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real); + + return 0; +} + +static int +codegen_PADDB(codeblock_t *block, uop_t *uop) +{ + int dest_reg = HOST_REG_GET(uop->dest_reg_a_real); + int src_reg_a = HOST_REG_GET(uop->src_reg_a_real); + int src_reg_b = HOST_REG_GET(uop->src_reg_b_real); + int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real); + int src_size_a = IREG_GET_SIZE(uop->src_reg_a_real); + int src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); + + if (REG_IS_Q(dest_size) && REG_IS_Q(src_size_a) && REG_IS_Q(src_size_b)) { + host_arm64_ADD_V8B(block, dest_reg, src_reg_a, src_reg_b); + } else + fatal("PADDB %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real); + + return 0; +} +static int +codegen_PADDW(codeblock_t *block, uop_t *uop) +{ + int dest_reg = HOST_REG_GET(uop->dest_reg_a_real); + int src_reg_a = HOST_REG_GET(uop->src_reg_a_real); + int src_reg_b = HOST_REG_GET(uop->src_reg_b_real); + int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real); + int src_size_a = IREG_GET_SIZE(uop->src_reg_a_real); + int src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); + + if (REG_IS_Q(dest_size) && REG_IS_Q(src_size_a) && REG_IS_Q(src_size_b)) { + host_arm64_ADD_V4H(block, dest_reg, src_reg_a, src_reg_b); + } else + fatal("PADDW %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real); + + return 0; +} +static int +codegen_PADDD(codeblock_t *block, uop_t *uop) +{ + int dest_reg = HOST_REG_GET(uop->dest_reg_a_real); + int src_reg_a = HOST_REG_GET(uop->src_reg_a_real); + int src_reg_b = HOST_REG_GET(uop->src_reg_b_real); + int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real); + int src_size_a = IREG_GET_SIZE(uop->src_reg_a_real); + int src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); + + if (REG_IS_Q(dest_size) && REG_IS_Q(src_size_a) && REG_IS_Q(src_size_b)) { + host_arm64_ADD_V2S(block, dest_reg, src_reg_a, src_reg_b); + } else + fatal("PADDD %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real); + + return 0; +} +static int +codegen_PADDSB(codeblock_t *block, uop_t *uop) +{ + int dest_reg = HOST_REG_GET(uop->dest_reg_a_real); + int src_reg_a = HOST_REG_GET(uop->src_reg_a_real); + int src_reg_b = HOST_REG_GET(uop->src_reg_b_real); + int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real); + int src_size_a = IREG_GET_SIZE(uop->src_reg_a_real); + int src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); + + if (REG_IS_Q(dest_size) && REG_IS_Q(src_size_a) && REG_IS_Q(src_size_b)) { + host_arm64_SQADD_V8B(block, dest_reg, src_reg_a, src_reg_b); + } else + fatal("PADDSB %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real); + + return 0; +} +static int +codegen_PADDSW(codeblock_t *block, uop_t *uop) +{ + int dest_reg = HOST_REG_GET(uop->dest_reg_a_real); + int src_reg_a = HOST_REG_GET(uop->src_reg_a_real); + int src_reg_b = HOST_REG_GET(uop->src_reg_b_real); + int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real); + int src_size_a = IREG_GET_SIZE(uop->src_reg_a_real); + int src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); + + if (REG_IS_Q(dest_size) && REG_IS_Q(src_size_a) && REG_IS_Q(src_size_b)) { + host_arm64_SQADD_V4H(block, dest_reg, src_reg_a, src_reg_b); + } else + fatal("PADDSW %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real); + + return 0; +} +static int +codegen_PADDUSB(codeblock_t *block, uop_t *uop) +{ + int dest_reg = HOST_REG_GET(uop->dest_reg_a_real); + int src_reg_a = HOST_REG_GET(uop->src_reg_a_real); + int src_reg_b = HOST_REG_GET(uop->src_reg_b_real); + int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real); + int src_size_a = IREG_GET_SIZE(uop->src_reg_a_real); + int src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); + + if (REG_IS_Q(dest_size) && REG_IS_Q(src_size_a) && REG_IS_Q(src_size_b)) { + host_arm64_UQADD_V8B(block, dest_reg, src_reg_a, src_reg_b); + } else + fatal("PADDUSB %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real); + + return 0; +} +static int +codegen_PADDUSW(codeblock_t *block, uop_t *uop) +{ + int dest_reg = HOST_REG_GET(uop->dest_reg_a_real); + int src_reg_a = HOST_REG_GET(uop->src_reg_a_real); + int src_reg_b = HOST_REG_GET(uop->src_reg_b_real); + int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real); + int src_size_a = IREG_GET_SIZE(uop->src_reg_a_real); + int src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); + + if (REG_IS_Q(dest_size) && REG_IS_Q(src_size_a) && REG_IS_Q(src_size_b)) { + host_arm64_UQADD_V4H(block, dest_reg, src_reg_a, src_reg_b); + } else + fatal("PADDUSW %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real); + + return 0; +} + +static int +codegen_PCMPEQB(codeblock_t *block, uop_t *uop) +{ + int dest_reg = HOST_REG_GET(uop->dest_reg_a_real); + int src_reg_a = HOST_REG_GET(uop->src_reg_a_real); + int src_reg_b = HOST_REG_GET(uop->src_reg_b_real); + int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real); + int src_size_a = IREG_GET_SIZE(uop->src_reg_a_real); + int src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); + + if (REG_IS_Q(dest_size) && REG_IS_Q(src_size_a) && REG_IS_Q(src_size_b)) { + host_arm64_CMEQ_V8B(block, dest_reg, src_reg_a, src_reg_b); + } else + fatal("PCMPEQB %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real); + + return 0; +} +static int +codegen_PCMPEQW(codeblock_t *block, uop_t *uop) +{ + int dest_reg = HOST_REG_GET(uop->dest_reg_a_real); + int src_reg_a = HOST_REG_GET(uop->src_reg_a_real); + int src_reg_b = HOST_REG_GET(uop->src_reg_b_real); + int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real); + int src_size_a = IREG_GET_SIZE(uop->src_reg_a_real); + int src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); + + if (REG_IS_Q(dest_size) && REG_IS_Q(src_size_a) && REG_IS_Q(src_size_b)) { + host_arm64_CMEQ_V4H(block, dest_reg, src_reg_a, src_reg_b); + } else + fatal("PCMPEQW %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real); + + return 0; +} +static int +codegen_PCMPEQD(codeblock_t *block, uop_t *uop) +{ + int dest_reg = HOST_REG_GET(uop->dest_reg_a_real); + int src_reg_a = HOST_REG_GET(uop->src_reg_a_real); + int src_reg_b = HOST_REG_GET(uop->src_reg_b_real); + int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real); + int src_size_a = IREG_GET_SIZE(uop->src_reg_a_real); + int src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); + + if (REG_IS_Q(dest_size) && REG_IS_Q(src_size_a) && REG_IS_Q(src_size_b)) { + host_arm64_CMEQ_V2S(block, dest_reg, src_reg_a, src_reg_b); + } else + fatal("PCMPEQD %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real); + + return 0; +} +static int +codegen_PCMPGTB(codeblock_t *block, uop_t *uop) +{ + int dest_reg = HOST_REG_GET(uop->dest_reg_a_real); + int src_reg_a = HOST_REG_GET(uop->src_reg_a_real); + int src_reg_b = HOST_REG_GET(uop->src_reg_b_real); + int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real); + int src_size_a = IREG_GET_SIZE(uop->src_reg_a_real); + int src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); + + if (REG_IS_Q(dest_size) && REG_IS_Q(src_size_a) && REG_IS_Q(src_size_b)) { + host_arm64_CMGT_V8B(block, dest_reg, src_reg_a, src_reg_b); + } else + fatal("PCMPGTB %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real); + + return 0; +} +static int +codegen_PCMPGTW(codeblock_t *block, uop_t *uop) +{ + int dest_reg = HOST_REG_GET(uop->dest_reg_a_real); + int src_reg_a = HOST_REG_GET(uop->src_reg_a_real); + int src_reg_b = HOST_REG_GET(uop->src_reg_b_real); + int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real); + int src_size_a = IREG_GET_SIZE(uop->src_reg_a_real); + int src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); + + if (REG_IS_Q(dest_size) && REG_IS_Q(src_size_a) && REG_IS_Q(src_size_b)) { + host_arm64_CMGT_V4H(block, dest_reg, src_reg_a, src_reg_b); + } else + fatal("PCMPGTW %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real); + + return 0; +} +static int +codegen_PCMPGTD(codeblock_t *block, uop_t *uop) +{ + int dest_reg = HOST_REG_GET(uop->dest_reg_a_real); + int src_reg_a = HOST_REG_GET(uop->src_reg_a_real); + int src_reg_b = HOST_REG_GET(uop->src_reg_b_real); + int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real); + int src_size_a = IREG_GET_SIZE(uop->src_reg_a_real); + int src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); + + if (REG_IS_Q(dest_size) && REG_IS_Q(src_size_a) && REG_IS_Q(src_size_b)) { + host_arm64_CMGT_V2S(block, dest_reg, src_reg_a, src_reg_b); + } else + fatal("PCMPGTD %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real); + + return 0; +} + +static int +codegen_PF2ID(codeblock_t *block, uop_t *uop) +{ + int dest_reg = HOST_REG_GET(uop->dest_reg_a_real); + int src_reg_a = HOST_REG_GET(uop->src_reg_a_real); + int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real); + int src_size_a = IREG_GET_SIZE(uop->src_reg_a_real); + + if (REG_IS_Q(dest_size) && REG_IS_Q(src_size_a)) { + host_arm64_FCVTZS_V2S(block, dest_reg, src_reg_a); + } else + fatal("PF2ID %02x\n", uop->dest_reg_a_real); + + return 0; +} +static int +codegen_PFADD(codeblock_t *block, uop_t *uop) +{ + int dest_reg = HOST_REG_GET(uop->dest_reg_a_real); + int src_reg_a = HOST_REG_GET(uop->src_reg_a_real); + int src_reg_b = HOST_REG_GET(uop->src_reg_b_real); + int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real); + int src_size_a = IREG_GET_SIZE(uop->src_reg_a_real); + int src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); + + if (REG_IS_Q(dest_size) && REG_IS_Q(src_size_a) && REG_IS_Q(src_size_b)) { + host_arm64_FADD_V2S(block, dest_reg, src_reg_a, src_reg_b); + } else + fatal("PFADD %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real); + + return 0; +} +static int +codegen_PFCMPEQ(codeblock_t *block, uop_t *uop) +{ + int dest_reg = HOST_REG_GET(uop->dest_reg_a_real); + int src_reg_a = HOST_REG_GET(uop->src_reg_a_real); + int src_reg_b = HOST_REG_GET(uop->src_reg_b_real); + int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real); + int src_size_a = IREG_GET_SIZE(uop->src_reg_a_real); + int src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); + + if (REG_IS_Q(dest_size) && REG_IS_Q(src_size_a) && REG_IS_Q(src_size_b)) { + host_arm64_FCMEQ_V2S(block, dest_reg, src_reg_a, src_reg_b); + } else + fatal("PFCMPEQ %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real); + + return 0; +} +static int +codegen_PFCMPGE(codeblock_t *block, uop_t *uop) +{ + int dest_reg = HOST_REG_GET(uop->dest_reg_a_real); + int src_reg_a = HOST_REG_GET(uop->src_reg_a_real); + int src_reg_b = HOST_REG_GET(uop->src_reg_b_real); + int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real); + int src_size_a = IREG_GET_SIZE(uop->src_reg_a_real); + int src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); + + if (REG_IS_Q(dest_size) && REG_IS_Q(src_size_a) && REG_IS_Q(src_size_b)) { + host_arm64_FCMGE_V2S(block, dest_reg, src_reg_a, src_reg_b); + } else + fatal("PFCMPGE %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real); + + return 0; +} +static int +codegen_PFCMPGT(codeblock_t *block, uop_t *uop) +{ + int dest_reg = HOST_REG_GET(uop->dest_reg_a_real); + int src_reg_a = HOST_REG_GET(uop->src_reg_a_real); + int src_reg_b = HOST_REG_GET(uop->src_reg_b_real); + int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real); + int src_size_a = IREG_GET_SIZE(uop->src_reg_a_real); + int src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); + + if (REG_IS_Q(dest_size) && REG_IS_Q(src_size_a) && REG_IS_Q(src_size_b)) { + host_arm64_FCMGT_V2S(block, dest_reg, src_reg_a, src_reg_b); + } else + fatal("PFCMPGT %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real); + + return 0; +} +static int +codegen_PFMAX(codeblock_t *block, uop_t *uop) +{ + int dest_reg = HOST_REG_GET(uop->dest_reg_a_real); + int src_reg_a = HOST_REG_GET(uop->src_reg_a_real); + int src_reg_b = HOST_REG_GET(uop->src_reg_b_real); + int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real); + int src_size_a = IREG_GET_SIZE(uop->src_reg_a_real); + int src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); + + if (REG_IS_Q(dest_size) && REG_IS_Q(src_size_a) && REG_IS_Q(src_size_b)) { + host_arm64_FMAX_V2S(block, dest_reg, src_reg_a, src_reg_b); + } else + fatal("PFMAX %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real); + + return 0; +} +static int +codegen_PFMIN(codeblock_t *block, uop_t *uop) +{ + int dest_reg = HOST_REG_GET(uop->dest_reg_a_real); + int src_reg_a = HOST_REG_GET(uop->src_reg_a_real); + int src_reg_b = HOST_REG_GET(uop->src_reg_b_real); + int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real); + int src_size_a = IREG_GET_SIZE(uop->src_reg_a_real); + int src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); + + if (REG_IS_Q(dest_size) && REG_IS_Q(src_size_a) && REG_IS_Q(src_size_b)) { + host_arm64_FMIN_V2S(block, dest_reg, src_reg_a, src_reg_b); + } else + fatal("PFMIN %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real); + + return 0; +} +static int +codegen_PFMUL(codeblock_t *block, uop_t *uop) +{ + int dest_reg = HOST_REG_GET(uop->dest_reg_a_real); + int src_reg_a = HOST_REG_GET(uop->src_reg_a_real); + int src_reg_b = HOST_REG_GET(uop->src_reg_b_real); + int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real); + int src_size_a = IREG_GET_SIZE(uop->src_reg_a_real); + int src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); + + if (REG_IS_Q(dest_size) && REG_IS_Q(src_size_a) && REG_IS_Q(src_size_b)) { + host_arm64_FMUL_V2S(block, dest_reg, src_reg_a, src_reg_b); + } else + fatal("PFMUL %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real); + + return 0; +} +static int +codegen_PFRCP(codeblock_t *block, uop_t *uop) +{ + int dest_reg = HOST_REG_GET(uop->dest_reg_a_real); + int src_reg_a = HOST_REG_GET(uop->src_reg_a_real); + int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real); + int src_size_a = IREG_GET_SIZE(uop->src_reg_a_real); + + if (REG_IS_Q(dest_size) && REG_IS_Q(src_size_a)) { + /*TODO: This could be improved (use VRECPE/VRECPS)*/ + host_arm64_FMOV_S_ONE(block, REG_V_TEMP); + host_arm64_FDIV_S(block, dest_reg, REG_V_TEMP, src_reg_a); + host_arm64_DUP_V2S(block, dest_reg, dest_reg, 0); + } else + fatal("PFRCP %02x\n", uop->dest_reg_a_real); + + return 0; +} +static int +codegen_PFRSQRT(codeblock_t *block, uop_t *uop) +{ + int dest_reg = HOST_REG_GET(uop->dest_reg_a_real); + int src_reg_a = HOST_REG_GET(uop->src_reg_a_real); + int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real); + int src_size_a = IREG_GET_SIZE(uop->src_reg_a_real); + + if (REG_IS_Q(dest_size) && REG_IS_Q(src_size_a)) { + /*TODO: This could be improved (use VRSQRTE/VRSQRTS)*/ + host_arm64_FSQRT_S(block, REG_V_TEMP, src_reg_a); + host_arm64_FMOV_S_ONE(block, REG_V_TEMP); + host_arm64_FDIV_S(block, dest_reg, dest_reg, REG_V_TEMP); + host_arm64_DUP_V2S(block, dest_reg, dest_reg, 0); + } else + fatal("PFRSQRT %02x\n", uop->dest_reg_a_real); + + return 0; +} +static int +codegen_PFSUB(codeblock_t *block, uop_t *uop) +{ + int dest_reg = HOST_REG_GET(uop->dest_reg_a_real); + int src_reg_a = HOST_REG_GET(uop->src_reg_a_real); + int src_reg_b = HOST_REG_GET(uop->src_reg_b_real); + int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real); + int src_size_a = IREG_GET_SIZE(uop->src_reg_a_real); + int src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); + + if (REG_IS_Q(dest_size) && REG_IS_Q(src_size_a) && REG_IS_Q(src_size_b)) { + host_arm64_FSUB_V2S(block, dest_reg, src_reg_a, src_reg_b); + } else + fatal("PFSUB %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real); + + return 0; +} +static int +codegen_PI2FD(codeblock_t *block, uop_t *uop) +{ + int dest_reg = HOST_REG_GET(uop->dest_reg_a_real); + int src_reg_a = HOST_REG_GET(uop->src_reg_a_real); + int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real); + int src_size_a = IREG_GET_SIZE(uop->src_reg_a_real); + + if (REG_IS_Q(dest_size) && REG_IS_Q(src_size_a)) { + host_arm64_SCVTF_V2S(block, dest_reg, src_reg_a); + } else + fatal("PI2FD %02x\n", uop->dest_reg_a_real); + + return 0; +} + +static int +codegen_PMADDWD(codeblock_t *block, uop_t *uop) +{ + int dest_reg = HOST_REG_GET(uop->dest_reg_a_real); + int src_reg_a = HOST_REG_GET(uop->src_reg_a_real); + int src_reg_b = HOST_REG_GET(uop->src_reg_b_real); + int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real); + int src_size_a = IREG_GET_SIZE(uop->src_reg_a_real); + int src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); + + if (REG_IS_Q(dest_size) && REG_IS_Q(src_size_a) && REG_IS_Q(src_size_b)) { + host_arm64_SMULL_V4S_4H(block, REG_V_TEMP, src_reg_a, src_reg_b); + host_arm64_ADDP_V4S(block, dest_reg, REG_V_TEMP, REG_V_TEMP); + } else + fatal("PMULHW %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real); + + return 0; +} +static int +codegen_PMULHW(codeblock_t *block, uop_t *uop) +{ + int dest_reg = HOST_REG_GET(uop->dest_reg_a_real); + int src_reg_a = HOST_REG_GET(uop->src_reg_a_real); + int src_reg_b = HOST_REG_GET(uop->src_reg_b_real); + int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real); + int src_size_a = IREG_GET_SIZE(uop->src_reg_a_real); + int src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); + + if (REG_IS_Q(dest_size) && REG_IS_Q(src_size_a) && REG_IS_Q(src_size_b)) { + host_arm64_SMULL_V4S_4H(block, dest_reg, src_reg_a, src_reg_b); + host_arm64_SHRN_V4H_4S(block, dest_reg, dest_reg, 16); + } else + fatal("PMULHW %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real); + + return 0; +} +static int +codegen_PMULLW(codeblock_t *block, uop_t *uop) +{ + int dest_reg = HOST_REG_GET(uop->dest_reg_a_real); + int src_reg_a = HOST_REG_GET(uop->src_reg_a_real); + int src_reg_b = HOST_REG_GET(uop->src_reg_b_real); + int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real); + int src_size_a = IREG_GET_SIZE(uop->src_reg_a_real); + int src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); + + if (REG_IS_Q(dest_size) && REG_IS_Q(src_size_a) && REG_IS_Q(src_size_b)) { + host_arm64_MUL_V4H(block, dest_reg, src_reg_a, src_reg_b); + } else + fatal("PMULLW %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real); + + return 0; +} + +static int +codegen_PSLLW_IMM(codeblock_t *block, uop_t *uop) +{ + int dest_reg = HOST_REG_GET(uop->dest_reg_a_real); + int src_reg = HOST_REG_GET(uop->src_reg_a_real); + int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real); + int src_size = IREG_GET_SIZE(uop->src_reg_a_real); + + if (REG_IS_Q(dest_size) && REG_IS_Q(src_size)) { + if (uop->imm_data == 0) + host_arm64_FMOV_D_D(block, dest_reg, src_reg); + else if (uop->imm_data > 15) + host_arm64_EOR_REG_V(block, dest_reg, dest_reg, dest_reg); else - fatal("MOV_DOUBLE_INT %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real); + host_arm64_SHL_V4H(block, dest_reg, src_reg, uop->imm_data); + } else + fatal("PSLLW_IMM %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real); - return 0; + return 0; } -static int codegen_MOV_INT_DOUBLE(codeblock_t *block, uop_t *uop) +static int +codegen_PSLLD_IMM(codeblock_t *block, uop_t *uop) { - int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg = HOST_REG_GET(uop->src_reg_a_real); - int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size = IREG_GET_SIZE(uop->src_reg_a_real); + int dest_reg = HOST_REG_GET(uop->dest_reg_a_real); + int src_reg = HOST_REG_GET(uop->src_reg_a_real); + int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real); + int src_size = IREG_GET_SIZE(uop->src_reg_a_real); - if (REG_IS_L(dest_size) && REG_IS_D(src_size)) - { - host_arm64_FMOV_D_D(block, REG_V_TEMP, src_reg); - host_arm64_call(block, codegen_fp_round); - host_arm64_MOV_REG(block, dest_reg, REG_TEMP, 0); - } - else if (REG_IS_W(dest_size) && REG_IS_D(src_size)) - { - host_arm64_FMOV_D_D(block, REG_V_TEMP, src_reg); - host_arm64_call(block, codegen_fp_round); - host_arm64_BFI(block, dest_reg, REG_TEMP, 0, 16); - } + if (REG_IS_Q(dest_size) && REG_IS_Q(src_size)) { + if (uop->imm_data == 0) + host_arm64_FMOV_D_D(block, dest_reg, src_reg); + else if (uop->imm_data > 31) + host_arm64_EOR_REG_V(block, dest_reg, dest_reg, dest_reg); else - fatal("MOV_INT_DOUBLE %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real); + host_arm64_SHL_V2S(block, dest_reg, src_reg, uop->imm_data); + } else + fatal("PSLLD_IMM %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real); - return 0; + return 0; } -static int codegen_MOV_INT_DOUBLE_64(codeblock_t *block, uop_t *uop) +static int +codegen_PSLLQ_IMM(codeblock_t *block, uop_t *uop) { - int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg = HOST_REG_GET(uop->src_reg_a_real), src_64_reg = HOST_REG_GET(uop->src_reg_b_real), tag_reg = HOST_REG_GET(uop->src_reg_c_real); - int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size = IREG_GET_SIZE(uop->src_reg_a_real), src_64_size = IREG_GET_SIZE(uop->src_reg_b_real); + int dest_reg = HOST_REG_GET(uop->dest_reg_a_real); + int src_reg = HOST_REG_GET(uop->src_reg_a_real); + int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real); + int src_size = IREG_GET_SIZE(uop->src_reg_a_real); - if (REG_IS_Q(dest_size) && REG_IS_D(src_size) && REG_IS_Q(src_64_size)) - { - uint32_t *branch_offset; - - /*If TAG_UINT64 is set then the source is MM[]. Otherwise it is a double in ST()*/ - host_arm64_FMOV_D_D(block, dest_reg, src_64_reg); - branch_offset = host_arm64_TBNZ(block, tag_reg, 7); - - host_arm64_FMOV_D_D(block, REG_V_TEMP, src_reg); - host_arm64_call(block, codegen_fp_round_quad); - host_arm64_FMOV_D_Q(block, dest_reg, REG_TEMP); - - host_arm64_branch_set_offset(branch_offset, &block_write_data[block_pos]); - } + if (REG_IS_Q(dest_size) && REG_IS_Q(src_size)) { + if (uop->imm_data == 0) + host_arm64_FMOV_D_D(block, dest_reg, src_reg); + else if (uop->imm_data > 63) + host_arm64_EOR_REG_V(block, dest_reg, dest_reg, dest_reg); else - fatal("MOV_INT_DOUBLE_64 %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real); + host_arm64_SHL_V2D(block, dest_reg, src_reg, uop->imm_data); + } else + fatal("PSLLQ_IMM %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real); - return 0; + return 0; } -static int codegen_MOV_REG_PTR(codeblock_t *block, uop_t *uop) +static int +codegen_PSRAW_IMM(codeblock_t *block, uop_t *uop) { - int dest_reg = HOST_REG_GET(uop->dest_reg_a_real); - int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real); + int dest_reg = HOST_REG_GET(uop->dest_reg_a_real); + int src_reg = HOST_REG_GET(uop->src_reg_a_real); + int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real); + int src_size = IREG_GET_SIZE(uop->src_reg_a_real); - host_arm64_MOVX_IMM(block, REG_TEMP, (uint64_t)uop->p); - if (REG_IS_L(dest_size)) - { - host_arm64_LDR_IMM_W(block, dest_reg, REG_TEMP, 0); - } + if (REG_IS_Q(dest_size) && REG_IS_Q(src_size)) { + if (uop->imm_data == 0) + host_arm64_FMOV_D_D(block, dest_reg, src_reg); + else if (uop->imm_data > 15) + host_arm64_SSHR_V4H(block, dest_reg, src_reg, 15); else - fatal("MOV_REG_PTR %02x\n", uop->dest_reg_a_real); + host_arm64_SSHR_V4H(block, dest_reg, src_reg, uop->imm_data); + } else + fatal("PSRAW_IMM %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real); - return 0; + return 0; } -static int codegen_MOVZX_REG_PTR_8(codeblock_t *block, uop_t *uop) +static int +codegen_PSRAD_IMM(codeblock_t *block, uop_t *uop) { - int dest_reg = HOST_REG_GET(uop->dest_reg_a_real); - int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real); + int dest_reg = HOST_REG_GET(uop->dest_reg_a_real); + int src_reg = HOST_REG_GET(uop->src_reg_a_real); + int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real); + int src_size = IREG_GET_SIZE(uop->src_reg_a_real); - host_arm64_MOVX_IMM(block, REG_TEMP, (uint64_t)uop->p); - if (REG_IS_L(dest_size)) - { - host_arm64_LDRB_IMM_W(block, dest_reg, REG_TEMP, 0); - } - else if (REG_IS_W(dest_size)) - { - host_arm64_LDRB_IMM_W(block, REG_TEMP, REG_TEMP, 0); - host_arm64_BFI(block, dest_reg, REG_TEMP, 0, 16); - } - else if (REG_IS_B(dest_size)) - { - host_arm64_LDRB_IMM_W(block, REG_TEMP, REG_TEMP, 0); - host_arm64_BFI(block, dest_reg, REG_TEMP, 0, 8); - } + if (REG_IS_Q(dest_size) && REG_IS_Q(src_size)) { + if (uop->imm_data == 0) + host_arm64_FMOV_D_D(block, dest_reg, src_reg); + else if (uop->imm_data > 31) + host_arm64_SSHR_V2S(block, dest_reg, src_reg, 31); else - fatal("MOVZX_REG_PTR_8 %02x\n", uop->dest_reg_a_real); + host_arm64_SSHR_V2S(block, dest_reg, src_reg, uop->imm_data); + } else + fatal("PSRAD_IMM %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real); - return 0; + return 0; } -static int codegen_MOVZX_REG_PTR_16(codeblock_t *block, uop_t *uop) +static int +codegen_PSRAQ_IMM(codeblock_t *block, uop_t *uop) { - int dest_reg = HOST_REG_GET(uop->dest_reg_a_real); - int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real); + int dest_reg = HOST_REG_GET(uop->dest_reg_a_real); + int src_reg = HOST_REG_GET(uop->src_reg_a_real); + int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real); + int src_size = IREG_GET_SIZE(uop->src_reg_a_real); - host_arm64_MOVX_IMM(block, REG_TEMP, (uint64_t)uop->p); - if (REG_IS_L(dest_size)) - { - host_arm64_LDRH_IMM(block, dest_reg, REG_TEMP, 0); - } - else if (REG_IS_W(dest_size)) - { - host_arm64_LDRH_IMM(block, REG_TEMP, REG_TEMP, 0); - host_arm64_BFI(block, dest_reg, REG_TEMP, 0, 16); - } + if (REG_IS_Q(dest_size) && REG_IS_Q(src_size)) { + if (uop->imm_data == 0) + host_arm64_FMOV_D_D(block, dest_reg, src_reg); + else if (uop->imm_data > 63) + host_arm64_SSHR_V2D(block, dest_reg, src_reg, 63); else - fatal("MOVZX_REG_PTR_16 %02x\n", uop->dest_reg_a_real); + host_arm64_SSHR_V2D(block, dest_reg, src_reg, uop->imm_data); + } else + fatal("PSRAQ_IMM %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real); - return 0; + return 0; } - -static int codegen_NOP(codeblock_t *block, uop_t *uop) +static int +codegen_PSRLW_IMM(codeblock_t *block, uop_t *uop) { - return 0; -} + int dest_reg = HOST_REG_GET(uop->dest_reg_a_real); + int src_reg = HOST_REG_GET(uop->src_reg_a_real); + int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real); + int src_size = IREG_GET_SIZE(uop->src_reg_a_real); -static int codegen_OR(codeblock_t *block, uop_t *uop) -{ - int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg_a = HOST_REG_GET(uop->src_reg_a_real), src_reg_b = HOST_REG_GET(uop->src_reg_b_real); - int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size_a = IREG_GET_SIZE(uop->src_reg_a_real), src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); - - if (REG_IS_Q(dest_size) && REG_IS_Q(src_size_a) && REG_IS_Q(src_size_b)) - { - host_arm64_ORR_REG_V(block, dest_reg, src_reg_a, src_reg_b); - } - else if (REG_IS_L(dest_size) && REG_IS_L(src_size_a) && REG_IS_L(src_size_b)) - { - host_arm64_ORR_REG(block, dest_reg, src_reg_a, src_reg_b, 0); - } - else if (REG_IS_W(dest_size) && REG_IS_W(src_size_a) && REG_IS_W(src_size_b)) - { - host_arm64_ORR_REG(block, REG_TEMP, src_reg_a, src_reg_b, 0); - host_arm64_BFI(block, dest_reg, REG_TEMP, 0, 16); - } - else if (REG_IS_B(dest_size) && REG_IS_B(src_size_a) && REG_IS_B(src_size_b) && dest_reg == src_reg_a) - { - host_arm64_AND_IMM(block, REG_TEMP, src_reg_b, 0xff); - host_arm64_ORR_REG(block, dest_reg, src_reg_a, REG_TEMP, 0); - } - else if (REG_IS_B(dest_size) && REG_IS_B(src_size_a) && REG_IS_BH(src_size_b) && dest_reg == src_reg_a) - { - host_arm64_UBFX(block, REG_TEMP, src_reg_b, 8, 8); - host_arm64_ORR_REG(block, dest_reg, src_reg_a, REG_TEMP, 0); - } - else if (REG_IS_BH(dest_size) && REG_IS_BH(src_size_a) && REG_IS_B(src_size_b) && dest_reg == src_reg_a) - { - host_arm64_AND_IMM(block, REG_TEMP, src_reg_b, 0xff); - host_arm64_ORR_REG(block, dest_reg, src_reg_a, REG_TEMP, 8); - } - else if (REG_IS_BH(dest_size) && REG_IS_BH(src_size_a) && REG_IS_BH(src_size_b) && dest_reg == src_reg_a) - { - host_arm64_UBFX(block, REG_TEMP, src_reg_b, 8, 8); - host_arm64_ORR_REG(block, dest_reg, src_reg_a, REG_TEMP, 8); - } - else - fatal("OR %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real); - - return 0; -} -static int codegen_OR_IMM(codeblock_t *block, uop_t *uop) -{ - int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg = HOST_REG_GET(uop->src_reg_a_real); - int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size = IREG_GET_SIZE(uop->src_reg_a_real); - - if (REG_IS_L(dest_size) && REG_IS_L(src_size)) - { - host_arm64_ORR_IMM(block, dest_reg, src_reg, uop->imm_data); - } - else if (REG_IS_W(dest_size) && REG_IS_W(src_size) && dest_reg == src_reg) - { - host_arm64_ORR_IMM(block, dest_reg, src_reg, uop->imm_data); - } - else if (REG_IS_B(dest_size) && REG_IS_B(src_size) && dest_reg == src_reg) - { - host_arm64_ORR_IMM(block, dest_reg, src_reg, uop->imm_data); - } - else if (REG_IS_BH(dest_size) && REG_IS_BH(src_size) && dest_reg == src_reg) - { - host_arm64_ORR_IMM(block, dest_reg, src_reg, uop->imm_data << 8); - } - else - fatal("OR_IMM %x %x\n", uop->dest_reg_a_real, uop->src_reg_a_real); - - return 0; -} - -static int codegen_PACKSSWB(codeblock_t *block, uop_t *uop) -{ - int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg_b = HOST_REG_GET(uop->src_reg_b_real); - int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); - - if (REG_IS_Q(dest_size) && REG_IS_Q(src_size_b) && uop->dest_reg_a_real == uop->src_reg_a_real) - { - host_arm64_SQXTN_V8B_8H(block, REG_V_TEMP, src_reg_b); - host_arm64_SQXTN_V8B_8H(block, dest_reg, dest_reg); - host_arm64_ZIP1_V2S(block, dest_reg, dest_reg, REG_V_TEMP); - } + if (REG_IS_Q(dest_size) && REG_IS_Q(src_size)) { + if (uop->imm_data == 0) + host_arm64_FMOV_D_D(block, dest_reg, src_reg); + else if (uop->imm_data > 15) + host_arm64_EOR_REG_V(block, dest_reg, dest_reg, dest_reg); else - fatal("PACKSSWB %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real); + host_arm64_USHR_V4H(block, dest_reg, src_reg, uop->imm_data); + } else + fatal("PSRLW_IMM %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real); - return 0; + return 0; } -static int codegen_PACKSSDW(codeblock_t *block, uop_t *uop) +static int +codegen_PSRLD_IMM(codeblock_t *block, uop_t *uop) { - int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg_b = HOST_REG_GET(uop->src_reg_b_real); - int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); + int dest_reg = HOST_REG_GET(uop->dest_reg_a_real); + int src_reg = HOST_REG_GET(uop->src_reg_a_real); + int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real); + int src_size = IREG_GET_SIZE(uop->src_reg_a_real); - if (REG_IS_Q(dest_size) && REG_IS_Q(src_size_b) && uop->dest_reg_a_real == uop->src_reg_a_real) - { - host_arm64_SQXTN_V4H_4S(block, REG_V_TEMP, src_reg_b); - host_arm64_SQXTN_V4H_4S(block, dest_reg, dest_reg); - host_arm64_ZIP1_V2S(block, dest_reg, dest_reg, REG_V_TEMP); - } + if (REG_IS_Q(dest_size) && REG_IS_Q(src_size)) { + if (uop->imm_data == 0) + host_arm64_FMOV_D_D(block, dest_reg, src_reg); + else if (uop->imm_data > 31) + host_arm64_EOR_REG_V(block, dest_reg, dest_reg, dest_reg); else - fatal("PACKSSDW %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real); + host_arm64_USHR_V2S(block, dest_reg, src_reg, uop->imm_data); + } else + fatal("PSRLD_IMM %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real); - return 0; + return 0; } -static int codegen_PACKUSWB(codeblock_t *block, uop_t *uop) +static int +codegen_PSRLQ_IMM(codeblock_t *block, uop_t *uop) { - int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg_b = HOST_REG_GET(uop->src_reg_b_real); - int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); + int dest_reg = HOST_REG_GET(uop->dest_reg_a_real); + int src_reg = HOST_REG_GET(uop->src_reg_a_real); + int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real); + int src_size = IREG_GET_SIZE(uop->src_reg_a_real); - if (REG_IS_Q(dest_size) && REG_IS_Q(src_size_b) && uop->dest_reg_a_real == uop->src_reg_a_real) - { - host_arm64_UQXTN_V8B_8H(block, REG_V_TEMP, src_reg_b); - host_arm64_UQXTN_V8B_8H(block, dest_reg, dest_reg); - host_arm64_ZIP1_V2S(block, dest_reg, dest_reg, REG_V_TEMP); - } + if (REG_IS_Q(dest_size) && REG_IS_Q(src_size)) { + if (uop->imm_data == 0) + host_arm64_FMOV_D_D(block, dest_reg, src_reg); + else if (uop->imm_data > 63) + host_arm64_EOR_REG_V(block, dest_reg, dest_reg, dest_reg); else - fatal("PACKUSWB %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real); + host_arm64_USHR_V2D(block, dest_reg, src_reg, uop->imm_data); + } else + fatal("PSRLQ_IMM %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real); - return 0; + return 0; } -static int codegen_PADDB(codeblock_t *block, uop_t *uop) +static int +codegen_PSUBB(codeblock_t *block, uop_t *uop) { - int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg_a = HOST_REG_GET(uop->src_reg_a_real), src_reg_b = HOST_REG_GET(uop->src_reg_b_real); - int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size_a = IREG_GET_SIZE(uop->src_reg_a_real), src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); + int dest_reg = HOST_REG_GET(uop->dest_reg_a_real); + int src_reg_a = HOST_REG_GET(uop->src_reg_a_real); + int src_reg_b = HOST_REG_GET(uop->src_reg_b_real); + int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real); + int src_size_a = IREG_GET_SIZE(uop->src_reg_a_real); + int src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); - if (REG_IS_Q(dest_size) && REG_IS_Q(src_size_a) && REG_IS_Q(src_size_b)) - { - host_arm64_ADD_V8B(block, dest_reg, src_reg_a, src_reg_b); - } - else - fatal("PADDB %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real); + if (REG_IS_Q(dest_size) && REG_IS_Q(src_size_a) && REG_IS_Q(src_size_b)) { + host_arm64_SUB_V8B(block, dest_reg, src_reg_a, src_reg_b); + } else + fatal("PSUBB %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real); - return 0; + return 0; } -static int codegen_PADDW(codeblock_t *block, uop_t *uop) +static int +codegen_PSUBW(codeblock_t *block, uop_t *uop) { - int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg_a = HOST_REG_GET(uop->src_reg_a_real), src_reg_b = HOST_REG_GET(uop->src_reg_b_real); - int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size_a = IREG_GET_SIZE(uop->src_reg_a_real), src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); + int dest_reg = HOST_REG_GET(uop->dest_reg_a_real); + int src_reg_a = HOST_REG_GET(uop->src_reg_a_real); + int src_reg_b = HOST_REG_GET(uop->src_reg_b_real); + int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real); + int src_size_a = IREG_GET_SIZE(uop->src_reg_a_real); + int src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); - if (REG_IS_Q(dest_size) && REG_IS_Q(src_size_a) && REG_IS_Q(src_size_b)) - { - host_arm64_ADD_V4H(block, dest_reg, src_reg_a, src_reg_b); - } - else - fatal("PADDW %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real); + if (REG_IS_Q(dest_size) && REG_IS_Q(src_size_a) && REG_IS_Q(src_size_b)) { + host_arm64_SUB_V4H(block, dest_reg, src_reg_a, src_reg_b); + } else + fatal("PSUBW %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real); - return 0; + return 0; } -static int codegen_PADDD(codeblock_t *block, uop_t *uop) +static int +codegen_PSUBD(codeblock_t *block, uop_t *uop) { - int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg_a = HOST_REG_GET(uop->src_reg_a_real), src_reg_b = HOST_REG_GET(uop->src_reg_b_real); - int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size_a = IREG_GET_SIZE(uop->src_reg_a_real), src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); + int dest_reg = HOST_REG_GET(uop->dest_reg_a_real); + int src_reg_a = HOST_REG_GET(uop->src_reg_a_real); + int src_reg_b = HOST_REG_GET(uop->src_reg_b_real); + int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real); + int src_size_a = IREG_GET_SIZE(uop->src_reg_a_real); + int src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); - if (REG_IS_Q(dest_size) && REG_IS_Q(src_size_a) && REG_IS_Q(src_size_b)) - { - host_arm64_ADD_V2S(block, dest_reg, src_reg_a, src_reg_b); - } - else - fatal("PADDD %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real); + if (REG_IS_Q(dest_size) && REG_IS_Q(src_size_a) && REG_IS_Q(src_size_b)) { + host_arm64_SUB_V2S(block, dest_reg, src_reg_a, src_reg_b); + } else + fatal("PSUBD %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real); - return 0; + return 0; } -static int codegen_PADDSB(codeblock_t *block, uop_t *uop) +static int +codegen_PSUBSB(codeblock_t *block, uop_t *uop) { - int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg_a = HOST_REG_GET(uop->src_reg_a_real), src_reg_b = HOST_REG_GET(uop->src_reg_b_real); - int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size_a = IREG_GET_SIZE(uop->src_reg_a_real), src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); + int dest_reg = HOST_REG_GET(uop->dest_reg_a_real); + int src_reg_a = HOST_REG_GET(uop->src_reg_a_real); + int src_reg_b = HOST_REG_GET(uop->src_reg_b_real); + int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real); + int src_size_a = IREG_GET_SIZE(uop->src_reg_a_real); + int src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); - if (REG_IS_Q(dest_size) && REG_IS_Q(src_size_a) && REG_IS_Q(src_size_b)) - { - host_arm64_SQADD_V8B(block, dest_reg, src_reg_a, src_reg_b); - } - else - fatal("PADDSB %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real); + if (REG_IS_Q(dest_size) && REG_IS_Q(src_size_a) && REG_IS_Q(src_size_b)) { + host_arm64_SQSUB_V8B(block, dest_reg, src_reg_a, src_reg_b); + } else + fatal("PSUBSB %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real); - return 0; + return 0; } -static int codegen_PADDSW(codeblock_t *block, uop_t *uop) +static int +codegen_PSUBSW(codeblock_t *block, uop_t *uop) { - int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg_a = HOST_REG_GET(uop->src_reg_a_real), src_reg_b = HOST_REG_GET(uop->src_reg_b_real); - int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size_a = IREG_GET_SIZE(uop->src_reg_a_real), src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); + int dest_reg = HOST_REG_GET(uop->dest_reg_a_real); + int src_reg_a = HOST_REG_GET(uop->src_reg_a_real); + int src_reg_b = HOST_REG_GET(uop->src_reg_b_real); + int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real); + int src_size_a = IREG_GET_SIZE(uop->src_reg_a_real); + int src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); - if (REG_IS_Q(dest_size) && REG_IS_Q(src_size_a) && REG_IS_Q(src_size_b)) - { - host_arm64_SQADD_V4H(block, dest_reg, src_reg_a, src_reg_b); - } - else - fatal("PADDSW %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real); + if (REG_IS_Q(dest_size) && REG_IS_Q(src_size_a) && REG_IS_Q(src_size_b)) { + host_arm64_SQSUB_V4H(block, dest_reg, src_reg_a, src_reg_b); + } else + fatal("PSUBSW %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real); - return 0; + return 0; } -static int codegen_PADDUSB(codeblock_t *block, uop_t *uop) +static int +codegen_PSUBUSB(codeblock_t *block, uop_t *uop) { - int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg_a = HOST_REG_GET(uop->src_reg_a_real), src_reg_b = HOST_REG_GET(uop->src_reg_b_real); - int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size_a = IREG_GET_SIZE(uop->src_reg_a_real), src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); + int dest_reg = HOST_REG_GET(uop->dest_reg_a_real); + int src_reg_a = HOST_REG_GET(uop->src_reg_a_real); + int src_reg_b = HOST_REG_GET(uop->src_reg_b_real); + int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real); + int src_size_a = IREG_GET_SIZE(uop->src_reg_a_real); + int src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); - if (REG_IS_Q(dest_size) && REG_IS_Q(src_size_a) && REG_IS_Q(src_size_b)) - { - host_arm64_UQADD_V8B(block, dest_reg, src_reg_a, src_reg_b); - } - else - fatal("PADDUSB %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real); + if (REG_IS_Q(dest_size) && REG_IS_Q(src_size_a) && REG_IS_Q(src_size_b)) { + host_arm64_UQSUB_V8B(block, dest_reg, src_reg_a, src_reg_b); + } else + fatal("PSUBUSB %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real); - return 0; + return 0; } -static int codegen_PADDUSW(codeblock_t *block, uop_t *uop) +static int +codegen_PSUBUSW(codeblock_t *block, uop_t *uop) { - int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg_a = HOST_REG_GET(uop->src_reg_a_real), src_reg_b = HOST_REG_GET(uop->src_reg_b_real); - int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size_a = IREG_GET_SIZE(uop->src_reg_a_real), src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); + int dest_reg = HOST_REG_GET(uop->dest_reg_a_real); + int src_reg_a = HOST_REG_GET(uop->src_reg_a_real); + int src_reg_b = HOST_REG_GET(uop->src_reg_b_real); + int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real); + int src_size_a = IREG_GET_SIZE(uop->src_reg_a_real); + int src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); - if (REG_IS_Q(dest_size) && REG_IS_Q(src_size_a) && REG_IS_Q(src_size_b)) - { - host_arm64_UQADD_V4H(block, dest_reg, src_reg_a, src_reg_b); - } - else - fatal("PADDUSW %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real); + if (REG_IS_Q(dest_size) && REG_IS_Q(src_size_a) && REG_IS_Q(src_size_b)) { + host_arm64_UQSUB_V4H(block, dest_reg, src_reg_a, src_reg_b); + } else + fatal("PSUBUSW %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real); - return 0; + return 0; } -static int codegen_PCMPEQB(codeblock_t *block, uop_t *uop) +static int +codegen_PUNPCKHBW(codeblock_t *block, uop_t *uop) { - int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg_a = HOST_REG_GET(uop->src_reg_a_real), src_reg_b = HOST_REG_GET(uop->src_reg_b_real); - int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size_a = IREG_GET_SIZE(uop->src_reg_a_real), src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); + int dest_reg = HOST_REG_GET(uop->dest_reg_a_real); + int src_reg_a = HOST_REG_GET(uop->src_reg_a_real); + int src_reg_b = HOST_REG_GET(uop->src_reg_b_real); + int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real); + int src_size_a = IREG_GET_SIZE(uop->src_reg_a_real); + int src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); - if (REG_IS_Q(dest_size) && REG_IS_Q(src_size_a) && REG_IS_Q(src_size_b)) - { - host_arm64_CMEQ_V8B(block, dest_reg, src_reg_a, src_reg_b); - } - else - fatal("PCMPEQB %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real); + if (REG_IS_Q(dest_size) && REG_IS_Q(src_size_a) && REG_IS_Q(src_size_b)) { + host_arm64_ZIP2_V8B(block, dest_reg, src_reg_a, src_reg_b); + } else + fatal("PUNPCKHBW %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real); - return 0; + return 0; } -static int codegen_PCMPEQW(codeblock_t *block, uop_t *uop) +static int +codegen_PUNPCKHWD(codeblock_t *block, uop_t *uop) { - int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg_a = HOST_REG_GET(uop->src_reg_a_real), src_reg_b = HOST_REG_GET(uop->src_reg_b_real); - int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size_a = IREG_GET_SIZE(uop->src_reg_a_real), src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); + int dest_reg = HOST_REG_GET(uop->dest_reg_a_real); + int src_reg_a = HOST_REG_GET(uop->src_reg_a_real); + int src_reg_b = HOST_REG_GET(uop->src_reg_b_real); + int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real); + int src_size_a = IREG_GET_SIZE(uop->src_reg_a_real); + int src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); - if (REG_IS_Q(dest_size) && REG_IS_Q(src_size_a) && REG_IS_Q(src_size_b)) - { - host_arm64_CMEQ_V4H(block, dest_reg, src_reg_a, src_reg_b); - } - else - fatal("PCMPEQW %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real); + if (REG_IS_Q(dest_size) && REG_IS_Q(src_size_a) && REG_IS_Q(src_size_b)) { + host_arm64_ZIP2_V4H(block, dest_reg, src_reg_a, src_reg_b); + } else + fatal("PUNPCKHWD %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real); - return 0; + return 0; } -static int codegen_PCMPEQD(codeblock_t *block, uop_t *uop) +static int +codegen_PUNPCKHDQ(codeblock_t *block, uop_t *uop) { - int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg_a = HOST_REG_GET(uop->src_reg_a_real), src_reg_b = HOST_REG_GET(uop->src_reg_b_real); - int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size_a = IREG_GET_SIZE(uop->src_reg_a_real), src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); + int dest_reg = HOST_REG_GET(uop->dest_reg_a_real); + int src_reg_a = HOST_REG_GET(uop->src_reg_a_real); + int src_reg_b = HOST_REG_GET(uop->src_reg_b_real); + int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real); + int src_size_a = IREG_GET_SIZE(uop->src_reg_a_real); + int src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); - if (REG_IS_Q(dest_size) && REG_IS_Q(src_size_a) && REG_IS_Q(src_size_b)) - { - host_arm64_CMEQ_V2S(block, dest_reg, src_reg_a, src_reg_b); - } - else - fatal("PCMPEQD %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real); + if (REG_IS_Q(dest_size) && REG_IS_Q(src_size_a) && REG_IS_Q(src_size_b)) { + host_arm64_ZIP2_V2S(block, dest_reg, src_reg_a, src_reg_b); + } else + fatal("PUNPCKHDQ %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real); - return 0; + return 0; } -static int codegen_PCMPGTB(codeblock_t *block, uop_t *uop) +static int +codegen_PUNPCKLBW(codeblock_t *block, uop_t *uop) { - int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg_a = HOST_REG_GET(uop->src_reg_a_real), src_reg_b = HOST_REG_GET(uop->src_reg_b_real); - int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size_a = IREG_GET_SIZE(uop->src_reg_a_real), src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); + int dest_reg = HOST_REG_GET(uop->dest_reg_a_real); + int src_reg_a = HOST_REG_GET(uop->src_reg_a_real); + int src_reg_b = HOST_REG_GET(uop->src_reg_b_real); + int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real); + int src_size_a = IREG_GET_SIZE(uop->src_reg_a_real); + int src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); - if (REG_IS_Q(dest_size) && REG_IS_Q(src_size_a) && REG_IS_Q(src_size_b)) - { - host_arm64_CMGT_V8B(block, dest_reg, src_reg_a, src_reg_b); - } - else - fatal("PCMPGTB %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real); + if (REG_IS_Q(dest_size) && REG_IS_Q(src_size_a) && REG_IS_Q(src_size_b)) { + host_arm64_ZIP1_V8B(block, dest_reg, src_reg_a, src_reg_b); + } else + fatal("PUNPCKLBW %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real); - return 0; + return 0; } -static int codegen_PCMPGTW(codeblock_t *block, uop_t *uop) +static int +codegen_PUNPCKLWD(codeblock_t *block, uop_t *uop) { - int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg_a = HOST_REG_GET(uop->src_reg_a_real), src_reg_b = HOST_REG_GET(uop->src_reg_b_real); - int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size_a = IREG_GET_SIZE(uop->src_reg_a_real), src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); + int dest_reg = HOST_REG_GET(uop->dest_reg_a_real); + int src_reg_a = HOST_REG_GET(uop->src_reg_a_real); + int src_reg_b = HOST_REG_GET(uop->src_reg_b_real); + int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real); + int src_size_a = IREG_GET_SIZE(uop->src_reg_a_real); + int src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); - if (REG_IS_Q(dest_size) && REG_IS_Q(src_size_a) && REG_IS_Q(src_size_b)) - { - host_arm64_CMGT_V4H(block, dest_reg, src_reg_a, src_reg_b); - } - else - fatal("PCMPGTW %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real); + if (REG_IS_Q(dest_size) && REG_IS_Q(src_size_a) && REG_IS_Q(src_size_b)) { + host_arm64_ZIP1_V4H(block, dest_reg, src_reg_a, src_reg_b); + } else + fatal("PUNPCKLWD %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real); - return 0; + return 0; } -static int codegen_PCMPGTD(codeblock_t *block, uop_t *uop) +static int +codegen_PUNPCKLDQ(codeblock_t *block, uop_t *uop) { - int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg_a = HOST_REG_GET(uop->src_reg_a_real), src_reg_b = HOST_REG_GET(uop->src_reg_b_real); - int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size_a = IREG_GET_SIZE(uop->src_reg_a_real), src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); + int dest_reg = HOST_REG_GET(uop->dest_reg_a_real); + int src_reg_a = HOST_REG_GET(uop->src_reg_a_real); + int src_reg_b = HOST_REG_GET(uop->src_reg_b_real); + int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real); + int src_size_a = IREG_GET_SIZE(uop->src_reg_a_real); + int src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); - if (REG_IS_Q(dest_size) && REG_IS_Q(src_size_a) && REG_IS_Q(src_size_b)) - { - host_arm64_CMGT_V2S(block, dest_reg, src_reg_a, src_reg_b); - } - else - fatal("PCMPGTD %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real); + if (REG_IS_Q(dest_size) && REG_IS_Q(src_size_a) && REG_IS_Q(src_size_b)) { + host_arm64_ZIP1_V2S(block, dest_reg, src_reg_a, src_reg_b); + } else + fatal("PUNPCKLDQ %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real); - return 0; + return 0; } -static int codegen_PF2ID(codeblock_t *block, uop_t *uop) +static int +codegen_ROL(codeblock_t *block, uop_t *uop) { - int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg_a = HOST_REG_GET(uop->src_reg_a_real); - int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size_a = IREG_GET_SIZE(uop->src_reg_a_real); + int dest_reg = HOST_REG_GET(uop->dest_reg_a_real); + int src_reg = HOST_REG_GET(uop->src_reg_a_real); + int shift_reg = HOST_REG_GET(uop->src_reg_b_real); + int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real); + int src_size = IREG_GET_SIZE(uop->src_reg_a_real); - if (REG_IS_Q(dest_size) && REG_IS_Q(src_size_a)) - { - host_arm64_FCVTZS_V2S(block, dest_reg, src_reg_a); - } - else - fatal("PF2ID %02x %02x\n", uop->dest_reg_a_real); + if (REG_IS_L(dest_size) && REG_IS_L(src_size)) { + host_arm64_mov_imm(block, REG_TEMP2, 32); + host_arm64_SUB_REG(block, REG_TEMP2, REG_TEMP2, shift_reg, 0); + host_arm64_ROR(block, dest_reg, src_reg, REG_TEMP2); + } else if (REG_IS_W(dest_size) && REG_IS_W(src_size)) { + host_arm64_mov_imm(block, REG_TEMP2, 16); + host_arm64_UBFX(block, REG_TEMP, src_reg, 0, 16); + host_arm64_SUB_REG(block, REG_TEMP2, REG_TEMP2, shift_reg, 0); + host_arm64_ORR_REG(block, REG_TEMP, REG_TEMP, REG_TEMP, 16); + host_arm64_ROR(block, REG_TEMP, REG_TEMP, REG_TEMP2); + host_arm64_BFI(block, dest_reg, REG_TEMP, 0, 16); + cs = cs; + } else if (REG_IS_B(dest_size) && REG_IS_B(src_size)) { + host_arm64_mov_imm(block, REG_TEMP2, 8); + host_arm64_SUB_REG(block, REG_TEMP2, REG_TEMP2, shift_reg, 0); + host_arm64_UBFX(block, REG_TEMP, src_reg, 0, 8); + host_arm64_AND_IMM(block, REG_TEMP2, REG_TEMP2, 7); + host_arm64_ORR_REG(block, REG_TEMP, REG_TEMP, REG_TEMP, 8); + host_arm64_LSR(block, REG_TEMP, REG_TEMP, REG_TEMP2); + host_arm64_BFI(block, dest_reg, REG_TEMP, 0, 8); + } else if (REG_IS_BH(dest_size) && REG_IS_BH(src_size)) { + host_arm64_mov_imm(block, REG_TEMP2, 8); + host_arm64_SUB_REG(block, REG_TEMP2, REG_TEMP2, shift_reg, 0); + host_arm64_UBFX(block, REG_TEMP, src_reg, 8, 8); + host_arm64_AND_IMM(block, REG_TEMP2, REG_TEMP2, 7); + host_arm64_ORR_REG(block, REG_TEMP, REG_TEMP, REG_TEMP, 8); + host_arm64_LSR(block, REG_TEMP, REG_TEMP, REG_TEMP2); + host_arm64_BFI(block, dest_reg, REG_TEMP, 8, 8); + } else + fatal("ROL %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real); - return 0; + return 0; } -static int codegen_PFADD(codeblock_t *block, uop_t *uop) +static int +codegen_ROL_IMM(codeblock_t *block, uop_t *uop) { - int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg_a = HOST_REG_GET(uop->src_reg_a_real), src_reg_b = HOST_REG_GET(uop->src_reg_b_real); - int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size_a = IREG_GET_SIZE(uop->src_reg_a_real), src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); + int dest_reg = HOST_REG_GET(uop->dest_reg_a_real); + int src_reg = HOST_REG_GET(uop->src_reg_a_real); + int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real); + int src_size = IREG_GET_SIZE(uop->src_reg_a_real); - if (REG_IS_Q(dest_size) && REG_IS_Q(src_size_a) && REG_IS_Q(src_size_b)) - { - host_arm64_FADD_V2S(block, dest_reg, src_reg_a, src_reg_b); + if (REG_IS_L(dest_size) && REG_IS_L(src_size)) { + if (!(uop->imm_data & 31)) { + if (src_reg != dest_reg) + host_arm64_MOV_REG(block, dest_reg, src_reg, 0); + } else { + host_arm64_MOV_REG_ROR(block, dest_reg, src_reg, 32 - (uop->imm_data & 31)); } - else - fatal("PFADD %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real); - - return 0; -} -static int codegen_PFCMPEQ(codeblock_t *block, uop_t *uop) -{ - int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg_a = HOST_REG_GET(uop->src_reg_a_real), src_reg_b = HOST_REG_GET(uop->src_reg_b_real); - int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size_a = IREG_GET_SIZE(uop->src_reg_a_real), src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); - - if (REG_IS_Q(dest_size) && REG_IS_Q(src_size_a) && REG_IS_Q(src_size_b)) - { - host_arm64_FCMEQ_V2S(block, dest_reg, src_reg_a, src_reg_b); + } else if (REG_IS_W(dest_size) && REG_IS_W(src_size)) { + if ((uop->imm_data & 15) == 0) { + if (src_reg != dest_reg) + host_arm64_BFI(block, dest_reg, src_reg, 0, 16); + } else { + host_arm64_UBFX(block, REG_TEMP, src_reg, 0, 16); + host_arm64_ORR_REG(block, REG_TEMP, REG_TEMP, REG_TEMP, 16); + host_arm64_MOV_REG_LSR(block, REG_TEMP, REG_TEMP, 16 - (uop->imm_data & 15)); + host_arm64_BFI(block, dest_reg, REG_TEMP, 0, 16); } - else - fatal("PFCMPEQ %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real); - - return 0; -} -static int codegen_PFCMPGE(codeblock_t *block, uop_t *uop) -{ - int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg_a = HOST_REG_GET(uop->src_reg_a_real), src_reg_b = HOST_REG_GET(uop->src_reg_b_real); - int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size_a = IREG_GET_SIZE(uop->src_reg_a_real), src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); - - if (REG_IS_Q(dest_size) && REG_IS_Q(src_size_a) && REG_IS_Q(src_size_b)) - { - host_arm64_FCMGE_V2S(block, dest_reg, src_reg_a, src_reg_b); + } else if (REG_IS_B(dest_size) && REG_IS_B(src_size)) { + if ((uop->imm_data & 7) == 0) { + if (src_reg != dest_reg) + host_arm64_BFI(block, dest_reg, src_reg, 0, 8); + } else { + host_arm64_UBFX(block, REG_TEMP, src_reg, 0, 8); + host_arm64_ORR_REG(block, REG_TEMP, REG_TEMP, REG_TEMP, 8); + host_arm64_MOV_REG_LSR(block, REG_TEMP, REG_TEMP, 8 - (uop->imm_data & 7)); + host_arm64_BFI(block, dest_reg, REG_TEMP, 0, 8); } - else - fatal("PFCMPGE %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real); - - return 0; -} -static int codegen_PFCMPGT(codeblock_t *block, uop_t *uop) -{ - int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg_a = HOST_REG_GET(uop->src_reg_a_real), src_reg_b = HOST_REG_GET(uop->src_reg_b_real); - int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size_a = IREG_GET_SIZE(uop->src_reg_a_real), src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); - - if (REG_IS_Q(dest_size) && REG_IS_Q(src_size_a) && REG_IS_Q(src_size_b)) - { - host_arm64_FCMGT_V2S(block, dest_reg, src_reg_a, src_reg_b); - } - else - fatal("PFCMPGT %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real); - - return 0; -} -static int codegen_PFMAX(codeblock_t *block, uop_t *uop) -{ - int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg_a = HOST_REG_GET(uop->src_reg_a_real), src_reg_b = HOST_REG_GET(uop->src_reg_b_real); - int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size_a = IREG_GET_SIZE(uop->src_reg_a_real), src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); - - if (REG_IS_Q(dest_size) && REG_IS_Q(src_size_a) && REG_IS_Q(src_size_b)) - { - host_arm64_FMAX_V2S(block, dest_reg, src_reg_a, src_reg_b); - } - else - fatal("PFMAX %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real); - - return 0; -} -static int codegen_PFMIN(codeblock_t *block, uop_t *uop) -{ - int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg_a = HOST_REG_GET(uop->src_reg_a_real), src_reg_b = HOST_REG_GET(uop->src_reg_b_real); - int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size_a = IREG_GET_SIZE(uop->src_reg_a_real), src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); - - if (REG_IS_Q(dest_size) && REG_IS_Q(src_size_a) && REG_IS_Q(src_size_b)) - { - host_arm64_FMIN_V2S(block, dest_reg, src_reg_a, src_reg_b); - } - else - fatal("PFMIN %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real); - - return 0; -} -static int codegen_PFMUL(codeblock_t *block, uop_t *uop) -{ - int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg_a = HOST_REG_GET(uop->src_reg_a_real), src_reg_b = HOST_REG_GET(uop->src_reg_b_real); - int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size_a = IREG_GET_SIZE(uop->src_reg_a_real), src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); - - if (REG_IS_Q(dest_size) && REG_IS_Q(src_size_a) && REG_IS_Q(src_size_b)) - { - host_arm64_FMUL_V2S(block, dest_reg, src_reg_a, src_reg_b); - } - else - fatal("PFMUL %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real); - - return 0; -} -static int codegen_PFRCP(codeblock_t *block, uop_t *uop) -{ - int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg_a = HOST_REG_GET(uop->src_reg_a_real); - int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size_a = IREG_GET_SIZE(uop->src_reg_a_real); - - if (REG_IS_Q(dest_size) && REG_IS_Q(src_size_a)) - { - /*TODO: This could be improved (use VRECPE/VRECPS)*/ - host_arm64_FMOV_S_ONE(block, REG_V_TEMP); - host_arm64_FDIV_S(block, dest_reg, REG_V_TEMP, src_reg_a); - host_arm64_DUP_V2S(block, dest_reg, dest_reg, 0); - } - else - fatal("PFRCP %02x %02x\n", uop->dest_reg_a_real); - - return 0; -} -static int codegen_PFRSQRT(codeblock_t *block, uop_t *uop) -{ - int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg_a = HOST_REG_GET(uop->src_reg_a_real); - int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size_a = IREG_GET_SIZE(uop->src_reg_a_real); - - if (REG_IS_Q(dest_size) && REG_IS_Q(src_size_a)) - { - /*TODO: This could be improved (use VRSQRTE/VRSQRTS)*/ - host_arm64_FSQRT_S(block, REG_V_TEMP, src_reg_a); - host_arm64_FMOV_S_ONE(block, REG_V_TEMP); - host_arm64_FDIV_S(block, dest_reg, dest_reg, REG_V_TEMP); - host_arm64_DUP_V2S(block, dest_reg, dest_reg, 0); - } - else - fatal("PFRSQRT %02x %02x\n", uop->dest_reg_a_real); - - return 0; -} -static int codegen_PFSUB(codeblock_t *block, uop_t *uop) -{ - int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg_a = HOST_REG_GET(uop->src_reg_a_real), src_reg_b = HOST_REG_GET(uop->src_reg_b_real); - int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size_a = IREG_GET_SIZE(uop->src_reg_a_real), src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); - - if (REG_IS_Q(dest_size) && REG_IS_Q(src_size_a) && REG_IS_Q(src_size_b)) - { - host_arm64_FSUB_V2S(block, dest_reg, src_reg_a, src_reg_b); - } - else - fatal("PFSUB %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real); - - return 0; -} -static int codegen_PI2FD(codeblock_t *block, uop_t *uop) -{ - int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg_a = HOST_REG_GET(uop->src_reg_a_real); - int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size_a = IREG_GET_SIZE(uop->src_reg_a_real); - - if (REG_IS_Q(dest_size) && REG_IS_Q(src_size_a)) - { - host_arm64_SCVTF_V2S(block, dest_reg, src_reg_a); - } - else - fatal("PI2FD %02x %02x\n", uop->dest_reg_a_real); - - return 0; -} - -static int codegen_PMADDWD(codeblock_t *block, uop_t *uop) -{ - int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg_a = HOST_REG_GET(uop->src_reg_a_real), src_reg_b = HOST_REG_GET(uop->src_reg_b_real); - int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size_a = IREG_GET_SIZE(uop->src_reg_a_real), src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); - - if (REG_IS_Q(dest_size) && REG_IS_Q(src_size_a) && REG_IS_Q(src_size_b)) - { - host_arm64_SMULL_V4S_4H(block, REG_V_TEMP, src_reg_a, src_reg_b); - host_arm64_ADDP_V4S(block, dest_reg, REG_V_TEMP, REG_V_TEMP); - } - else - fatal("PMULHW %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real); - - return 0; -} -static int codegen_PMULHW(codeblock_t *block, uop_t *uop) -{ - int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg_a = HOST_REG_GET(uop->src_reg_a_real), src_reg_b = HOST_REG_GET(uop->src_reg_b_real); - int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size_a = IREG_GET_SIZE(uop->src_reg_a_real), src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); - - if (REG_IS_Q(dest_size) && REG_IS_Q(src_size_a) && REG_IS_Q(src_size_b)) - { - host_arm64_SMULL_V4S_4H(block, dest_reg, src_reg_a, src_reg_b); - host_arm64_SHRN_V4H_4S(block, dest_reg, dest_reg, 16); - } - else - fatal("PMULHW %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real); - - return 0; -} -static int codegen_PMULLW(codeblock_t *block, uop_t *uop) -{ - int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg_a = HOST_REG_GET(uop->src_reg_a_real), src_reg_b = HOST_REG_GET(uop->src_reg_b_real); - int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size_a = IREG_GET_SIZE(uop->src_reg_a_real), src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); - - if (REG_IS_Q(dest_size) && REG_IS_Q(src_size_a) && REG_IS_Q(src_size_b)) - { - host_arm64_MUL_V4H(block, dest_reg, src_reg_a, src_reg_b); - } - else - fatal("PMULLW %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real); - - return 0; -} - -static int codegen_PSLLW_IMM(codeblock_t *block, uop_t *uop) -{ - int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg = HOST_REG_GET(uop->src_reg_a_real); - int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size = IREG_GET_SIZE(uop->src_reg_a_real); - - if (REG_IS_Q(dest_size) && REG_IS_Q(src_size)) - { - if (uop->imm_data == 0) - host_arm64_FMOV_D_D(block, dest_reg, src_reg); - else if (uop->imm_data > 15) - host_arm64_EOR_REG_V(block, dest_reg, dest_reg, dest_reg); - else - host_arm64_SHL_V4H(block, dest_reg, src_reg, uop->imm_data); - } - else - fatal("PSLLW_IMM %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real); - - return 0; -} -static int codegen_PSLLD_IMM(codeblock_t *block, uop_t *uop) -{ - int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg = HOST_REG_GET(uop->src_reg_a_real); - int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size = IREG_GET_SIZE(uop->src_reg_a_real); - - if (REG_IS_Q(dest_size) && REG_IS_Q(src_size)) - { - if (uop->imm_data == 0) - host_arm64_FMOV_D_D(block, dest_reg, src_reg); - else if (uop->imm_data > 31) - host_arm64_EOR_REG_V(block, dest_reg, dest_reg, dest_reg); - else - host_arm64_SHL_V2S(block, dest_reg, src_reg, uop->imm_data); - } - else - fatal("PSLLD_IMM %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real); - - return 0; -} -static int codegen_PSLLQ_IMM(codeblock_t *block, uop_t *uop) -{ - int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg = HOST_REG_GET(uop->src_reg_a_real); - int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size = IREG_GET_SIZE(uop->src_reg_a_real); - - if (REG_IS_Q(dest_size) && REG_IS_Q(src_size)) - { - if (uop->imm_data == 0) - host_arm64_FMOV_D_D(block, dest_reg, src_reg); - else if (uop->imm_data > 63) - host_arm64_EOR_REG_V(block, dest_reg, dest_reg, dest_reg); - else - host_arm64_SHL_V2D(block, dest_reg, src_reg, uop->imm_data); - } - else - fatal("PSLLQ_IMM %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real); - - return 0; -} -static int codegen_PSRAW_IMM(codeblock_t *block, uop_t *uop) -{ - int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg = HOST_REG_GET(uop->src_reg_a_real); - int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size = IREG_GET_SIZE(uop->src_reg_a_real); - - if (REG_IS_Q(dest_size) && REG_IS_Q(src_size)) - { - if (uop->imm_data == 0) - host_arm64_FMOV_D_D(block, dest_reg, src_reg); - else if (uop->imm_data > 15) - host_arm64_SSHR_V4H(block, dest_reg, src_reg, 15); - else - host_arm64_SSHR_V4H(block, dest_reg, src_reg, uop->imm_data); - } - else - fatal("PSRAW_IMM %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real); - - return 0; -} -static int codegen_PSRAD_IMM(codeblock_t *block, uop_t *uop) -{ - int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg = HOST_REG_GET(uop->src_reg_a_real); - int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size = IREG_GET_SIZE(uop->src_reg_a_real); - - if (REG_IS_Q(dest_size) && REG_IS_Q(src_size)) - { - if (uop->imm_data == 0) - host_arm64_FMOV_D_D(block, dest_reg, src_reg); - else if (uop->imm_data > 31) - host_arm64_SSHR_V2S(block, dest_reg, src_reg, 31); - else - host_arm64_SSHR_V2S(block, dest_reg, src_reg, uop->imm_data); - } - else - fatal("PSRAD_IMM %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real); - - return 0; -} -static int codegen_PSRAQ_IMM(codeblock_t *block, uop_t *uop) -{ - int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg = HOST_REG_GET(uop->src_reg_a_real); - int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size = IREG_GET_SIZE(uop->src_reg_a_real); - - if (REG_IS_Q(dest_size) && REG_IS_Q(src_size)) - { - if (uop->imm_data == 0) - host_arm64_FMOV_D_D(block, dest_reg, src_reg); - else if (uop->imm_data > 63) - host_arm64_SSHR_V2D(block, dest_reg, src_reg, 63); - else - host_arm64_SSHR_V2D(block, dest_reg, src_reg, uop->imm_data); - } - else - fatal("PSRAQ_IMM %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real); - - return 0; -} -static int codegen_PSRLW_IMM(codeblock_t *block, uop_t *uop) -{ - int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg = HOST_REG_GET(uop->src_reg_a_real); - int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size = IREG_GET_SIZE(uop->src_reg_a_real); - - if (REG_IS_Q(dest_size) && REG_IS_Q(src_size)) - { - if (uop->imm_data == 0) - host_arm64_FMOV_D_D(block, dest_reg, src_reg); - else if (uop->imm_data > 15) - host_arm64_EOR_REG_V(block, dest_reg, dest_reg, dest_reg); - else - host_arm64_USHR_V4H(block, dest_reg, src_reg, uop->imm_data); - } - else - fatal("PSRLW_IMM %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real); - - return 0; -} -static int codegen_PSRLD_IMM(codeblock_t *block, uop_t *uop) -{ - int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg = HOST_REG_GET(uop->src_reg_a_real); - int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size = IREG_GET_SIZE(uop->src_reg_a_real); - - if (REG_IS_Q(dest_size) && REG_IS_Q(src_size)) - { - if (uop->imm_data == 0) - host_arm64_FMOV_D_D(block, dest_reg, src_reg); - else if (uop->imm_data > 31) - host_arm64_EOR_REG_V(block, dest_reg, dest_reg, dest_reg); - else - host_arm64_USHR_V2S(block, dest_reg, src_reg, uop->imm_data); - } - else - fatal("PSRLD_IMM %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real); - - return 0; -} -static int codegen_PSRLQ_IMM(codeblock_t *block, uop_t *uop) -{ - int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg = HOST_REG_GET(uop->src_reg_a_real); - int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size = IREG_GET_SIZE(uop->src_reg_a_real); - - if (REG_IS_Q(dest_size) && REG_IS_Q(src_size)) - { - if (uop->imm_data == 0) - host_arm64_FMOV_D_D(block, dest_reg, src_reg); - else if (uop->imm_data > 63) - host_arm64_EOR_REG_V(block, dest_reg, dest_reg, dest_reg); - else - host_arm64_USHR_V2D(block, dest_reg, src_reg, uop->imm_data); - } - else - fatal("PSRLQ_IMM %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real); - - return 0; -} - -static int codegen_PSUBB(codeblock_t *block, uop_t *uop) -{ - int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg_a = HOST_REG_GET(uop->src_reg_a_real), src_reg_b = HOST_REG_GET(uop->src_reg_b_real); - int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size_a = IREG_GET_SIZE(uop->src_reg_a_real), src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); - - if (REG_IS_Q(dest_size) && REG_IS_Q(src_size_a) && REG_IS_Q(src_size_b)) - { - host_arm64_SUB_V8B(block, dest_reg, src_reg_a, src_reg_b); - } - else - fatal("PSUBB %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real); - - return 0; -} -static int codegen_PSUBW(codeblock_t *block, uop_t *uop) -{ - int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg_a = HOST_REG_GET(uop->src_reg_a_real), src_reg_b = HOST_REG_GET(uop->src_reg_b_real); - int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size_a = IREG_GET_SIZE(uop->src_reg_a_real), src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); - - if (REG_IS_Q(dest_size) && REG_IS_Q(src_size_a) && REG_IS_Q(src_size_b)) - { - host_arm64_SUB_V4H(block, dest_reg, src_reg_a, src_reg_b); - } - else - fatal("PSUBW %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real); - - return 0; -} -static int codegen_PSUBD(codeblock_t *block, uop_t *uop) -{ - int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg_a = HOST_REG_GET(uop->src_reg_a_real), src_reg_b = HOST_REG_GET(uop->src_reg_b_real); - int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size_a = IREG_GET_SIZE(uop->src_reg_a_real), src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); - - if (REG_IS_Q(dest_size) && REG_IS_Q(src_size_a) && REG_IS_Q(src_size_b)) - { - host_arm64_SUB_V2S(block, dest_reg, src_reg_a, src_reg_b); - } - else - fatal("PSUBD %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real); - - return 0; -} -static int codegen_PSUBSB(codeblock_t *block, uop_t *uop) -{ - int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg_a = HOST_REG_GET(uop->src_reg_a_real), src_reg_b = HOST_REG_GET(uop->src_reg_b_real); - int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size_a = IREG_GET_SIZE(uop->src_reg_a_real), src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); - - if (REG_IS_Q(dest_size) && REG_IS_Q(src_size_a) && REG_IS_Q(src_size_b)) - { - host_arm64_SQSUB_V8B(block, dest_reg, src_reg_a, src_reg_b); - } - else - fatal("PSUBSB %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real); - - return 0; -} -static int codegen_PSUBSW(codeblock_t *block, uop_t *uop) -{ - int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg_a = HOST_REG_GET(uop->src_reg_a_real), src_reg_b = HOST_REG_GET(uop->src_reg_b_real); - int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size_a = IREG_GET_SIZE(uop->src_reg_a_real), src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); - - if (REG_IS_Q(dest_size) && REG_IS_Q(src_size_a) && REG_IS_Q(src_size_b)) - { - host_arm64_SQSUB_V4H(block, dest_reg, src_reg_a, src_reg_b); - } - else - fatal("PSUBSW %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real); - - return 0; -} -static int codegen_PSUBUSB(codeblock_t *block, uop_t *uop) -{ - int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg_a = HOST_REG_GET(uop->src_reg_a_real), src_reg_b = HOST_REG_GET(uop->src_reg_b_real); - int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size_a = IREG_GET_SIZE(uop->src_reg_a_real), src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); - - if (REG_IS_Q(dest_size) && REG_IS_Q(src_size_a) && REG_IS_Q(src_size_b)) - { - host_arm64_UQSUB_V8B(block, dest_reg, src_reg_a, src_reg_b); - } - else - fatal("PSUBUSB %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real); - - return 0; -} -static int codegen_PSUBUSW(codeblock_t *block, uop_t *uop) -{ - int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg_a = HOST_REG_GET(uop->src_reg_a_real), src_reg_b = HOST_REG_GET(uop->src_reg_b_real); - int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size_a = IREG_GET_SIZE(uop->src_reg_a_real), src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); - - if (REG_IS_Q(dest_size) && REG_IS_Q(src_size_a) && REG_IS_Q(src_size_b)) - { - host_arm64_UQSUB_V4H(block, dest_reg, src_reg_a, src_reg_b); - } - else - fatal("PSUBUSW %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real); - - return 0; -} - -static int codegen_PUNPCKHBW(codeblock_t *block, uop_t *uop) -{ - int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg_a = HOST_REG_GET(uop->src_reg_a_real), src_reg_b = HOST_REG_GET(uop->src_reg_b_real); - int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size_a = IREG_GET_SIZE(uop->src_reg_a_real), src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); - - if (REG_IS_Q(dest_size) && REG_IS_Q(src_size_a) && REG_IS_Q(src_size_b)) - { - host_arm64_ZIP2_V8B(block, dest_reg, src_reg_a, src_reg_b); - } - else - fatal("PUNPCKHBW %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real); - - return 0; -} -static int codegen_PUNPCKHWD(codeblock_t *block, uop_t *uop) -{ - int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg_a = HOST_REG_GET(uop->src_reg_a_real), src_reg_b = HOST_REG_GET(uop->src_reg_b_real); - int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size_a = IREG_GET_SIZE(uop->src_reg_a_real), src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); - - if (REG_IS_Q(dest_size) && REG_IS_Q(src_size_a) && REG_IS_Q(src_size_b)) - { - host_arm64_ZIP2_V4H(block, dest_reg, src_reg_a, src_reg_b); - } - else - fatal("PUNPCKHWD %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real); - - return 0; -} -static int codegen_PUNPCKHDQ(codeblock_t *block, uop_t *uop) -{ - int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg_a = HOST_REG_GET(uop->src_reg_a_real), src_reg_b = HOST_REG_GET(uop->src_reg_b_real); - int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size_a = IREG_GET_SIZE(uop->src_reg_a_real), src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); - - if (REG_IS_Q(dest_size) && REG_IS_Q(src_size_a) && REG_IS_Q(src_size_b)) - { - host_arm64_ZIP2_V2S(block, dest_reg, src_reg_a, src_reg_b); - } - else - fatal("PUNPCKHDQ %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real); - - return 0; -} -static int codegen_PUNPCKLBW(codeblock_t *block, uop_t *uop) -{ - int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg_a = HOST_REG_GET(uop->src_reg_a_real), src_reg_b = HOST_REG_GET(uop->src_reg_b_real); - int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size_a = IREG_GET_SIZE(uop->src_reg_a_real), src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); - - if (REG_IS_Q(dest_size) && REG_IS_Q(src_size_a) && REG_IS_Q(src_size_b)) - { - host_arm64_ZIP1_V8B(block, dest_reg, src_reg_a, src_reg_b); - } - else - fatal("PUNPCKLBW %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real); - - return 0; -} -static int codegen_PUNPCKLWD(codeblock_t *block, uop_t *uop) -{ - int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg_a = HOST_REG_GET(uop->src_reg_a_real), src_reg_b = HOST_REG_GET(uop->src_reg_b_real); - int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size_a = IREG_GET_SIZE(uop->src_reg_a_real), src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); - - if (REG_IS_Q(dest_size) && REG_IS_Q(src_size_a) && REG_IS_Q(src_size_b)) - { - host_arm64_ZIP1_V4H(block, dest_reg, src_reg_a, src_reg_b); - } - else - fatal("PUNPCKLWD %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real); - - return 0; -} -static int codegen_PUNPCKLDQ(codeblock_t *block, uop_t *uop) -{ - int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg_a = HOST_REG_GET(uop->src_reg_a_real), src_reg_b = HOST_REG_GET(uop->src_reg_b_real); - int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size_a = IREG_GET_SIZE(uop->src_reg_a_real), src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); - - if (REG_IS_Q(dest_size) && REG_IS_Q(src_size_a) && REG_IS_Q(src_size_b)) - { - host_arm64_ZIP1_V2S(block, dest_reg, src_reg_a, src_reg_b); - } - else - fatal("PUNPCKLDQ %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real); - - return 0; -} - -static int codegen_ROL(codeblock_t *block, uop_t *uop) -{ - int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg = HOST_REG_GET(uop->src_reg_a_real), shift_reg = HOST_REG_GET(uop->src_reg_b_real); - int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size = IREG_GET_SIZE(uop->src_reg_a_real); - - if (REG_IS_L(dest_size) && REG_IS_L(src_size)) - { - host_arm64_mov_imm(block, REG_TEMP2, 32); - host_arm64_SUB_REG(block, REG_TEMP2, REG_TEMP2, shift_reg, 0); - host_arm64_ROR(block, dest_reg, src_reg, REG_TEMP2); - } - else if (REG_IS_W(dest_size) && REG_IS_W(src_size)) - { - host_arm64_mov_imm(block, REG_TEMP2, 16); - host_arm64_UBFX(block, REG_TEMP, src_reg, 0, 16); - host_arm64_SUB_REG(block, REG_TEMP2, REG_TEMP2, shift_reg, 0); - host_arm64_ORR_REG(block, REG_TEMP, REG_TEMP, REG_TEMP, 16); - host_arm64_ROR(block, REG_TEMP, REG_TEMP, REG_TEMP2); - host_arm64_BFI(block, dest_reg, REG_TEMP, 0, 16); - cs = cs; - } - else if (REG_IS_B(dest_size) && REG_IS_B(src_size)) - { - host_arm64_mov_imm(block, REG_TEMP2, 8); - host_arm64_SUB_REG(block, REG_TEMP2, REG_TEMP2, shift_reg, 0); - host_arm64_UBFX(block, REG_TEMP, src_reg, 0, 8); - host_arm64_AND_IMM(block, REG_TEMP2, REG_TEMP2, 7); - host_arm64_ORR_REG(block, REG_TEMP, REG_TEMP, REG_TEMP, 8); - host_arm64_LSR(block, REG_TEMP, REG_TEMP, REG_TEMP2); - host_arm64_BFI(block, dest_reg, REG_TEMP, 0, 8); - } - else if (REG_IS_BH(dest_size) && REG_IS_BH(src_size)) - { - host_arm64_mov_imm(block, REG_TEMP2, 8); - host_arm64_SUB_REG(block, REG_TEMP2, REG_TEMP2, shift_reg, 0); - host_arm64_UBFX(block, REG_TEMP, src_reg, 8, 8); - host_arm64_AND_IMM(block, REG_TEMP2, REG_TEMP2, 7); - host_arm64_ORR_REG(block, REG_TEMP, REG_TEMP, REG_TEMP, 8); - host_arm64_LSR(block, REG_TEMP, REG_TEMP, REG_TEMP2); - host_arm64_BFI(block, dest_reg, REG_TEMP, 8, 8); - } - else - fatal("ROL %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real); - - return 0; -} -static int codegen_ROL_IMM(codeblock_t *block, uop_t *uop) -{ - int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg = HOST_REG_GET(uop->src_reg_a_real); - int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size = IREG_GET_SIZE(uop->src_reg_a_real); - - if (REG_IS_L(dest_size) && REG_IS_L(src_size)) - { - if (!(uop->imm_data & 31)) - { - if (src_reg != dest_reg) - host_arm64_MOV_REG(block, dest_reg, src_reg, 0); - } - else - { - host_arm64_MOV_REG_ROR(block, dest_reg, src_reg, 32 - (uop->imm_data & 31)); - } - } - else if (REG_IS_W(dest_size) && REG_IS_W(src_size)) - { - if ((uop->imm_data & 15) == 0) - { - if (src_reg != dest_reg) - host_arm64_BFI(block, dest_reg, src_reg, 0, 16); - } - else - { - host_arm64_UBFX(block, REG_TEMP, src_reg, 0, 16); - host_arm64_ORR_REG(block, REG_TEMP, REG_TEMP, REG_TEMP, 16); - host_arm64_MOV_REG_LSR(block, REG_TEMP, REG_TEMP, 16-(uop->imm_data & 15)); - host_arm64_BFI(block, dest_reg, REG_TEMP, 0, 16); - } - } - else if (REG_IS_B(dest_size) && REG_IS_B(src_size)) - { - if ((uop->imm_data & 7) == 0) - { - if (src_reg != dest_reg) - host_arm64_BFI(block, dest_reg, src_reg, 0, 8); - } - else - { - host_arm64_UBFX(block, REG_TEMP, src_reg, 0, 8); - host_arm64_ORR_REG(block, REG_TEMP, REG_TEMP, REG_TEMP, 8); - host_arm64_MOV_REG_LSR(block, REG_TEMP, REG_TEMP, 8-(uop->imm_data & 7)); - host_arm64_BFI(block, dest_reg, REG_TEMP, 0, 8); - } - } - else if (REG_IS_BH(dest_size) && REG_IS_BH(src_size)) - { - if ((uop->imm_data & 7) == 0) - { - if (src_reg != dest_reg) - fatal("ROL_IMM %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real); - } - else - { - host_arm64_UBFX(block, REG_TEMP, src_reg, 8, 8); - host_arm64_ORR_REG(block, REG_TEMP, REG_TEMP, REG_TEMP, 8); - host_arm64_MOV_REG_LSR(block, REG_TEMP, REG_TEMP, 8-(uop->imm_data & 7)); - host_arm64_BFI(block, dest_reg, REG_TEMP, 8, 8); - } - } - else + } else if (REG_IS_BH(dest_size) && REG_IS_BH(src_size)) { + if ((uop->imm_data & 7) == 0) { + if (src_reg != dest_reg) fatal("ROL_IMM %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real); + } else { + host_arm64_UBFX(block, REG_TEMP, src_reg, 8, 8); + host_arm64_ORR_REG(block, REG_TEMP, REG_TEMP, REG_TEMP, 8); + host_arm64_MOV_REG_LSR(block, REG_TEMP, REG_TEMP, 8 - (uop->imm_data & 7)); + host_arm64_BFI(block, dest_reg, REG_TEMP, 8, 8); + } + } else + fatal("ROL_IMM %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real); - return 0; + return 0; } -static int codegen_ROR(codeblock_t *block, uop_t *uop) +static int +codegen_ROR(codeblock_t *block, uop_t *uop) { - int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg = HOST_REG_GET(uop->src_reg_a_real), shift_reg = HOST_REG_GET(uop->src_reg_b_real); - int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size = IREG_GET_SIZE(uop->src_reg_a_real); + int dest_reg = HOST_REG_GET(uop->dest_reg_a_real); + int src_reg = HOST_REG_GET(uop->src_reg_a_real); + int shift_reg = HOST_REG_GET(uop->src_reg_b_real); + int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real); + int src_size = IREG_GET_SIZE(uop->src_reg_a_real); - if (REG_IS_L(dest_size) && REG_IS_L(src_size)) - { - host_arm64_ROR(block, dest_reg, src_reg, shift_reg); - } - else if (REG_IS_W(dest_size) && REG_IS_W(src_size)) - { - host_arm64_UBFX(block, REG_TEMP, src_reg, 0, 16); - host_arm64_AND_IMM(block, REG_TEMP2, shift_reg, 15); - host_arm64_ORR_REG(block, REG_TEMP, REG_TEMP, REG_TEMP, 16); - host_arm64_LSR(block, REG_TEMP, REG_TEMP, REG_TEMP2); - host_arm64_BFI(block, dest_reg, REG_TEMP, 0, 16); - } - else if (REG_IS_B(dest_size) && REG_IS_B(src_size)) - { - host_arm64_UBFX(block, REG_TEMP, src_reg, 0, 8); - host_arm64_AND_IMM(block, REG_TEMP2, shift_reg, 7); - host_arm64_ORR_REG(block, REG_TEMP, REG_TEMP, REG_TEMP, 8); - host_arm64_LSR(block, REG_TEMP, REG_TEMP, REG_TEMP2); - host_arm64_BFI(block, dest_reg, REG_TEMP, 0, 8); - } - else if (REG_IS_BH(dest_size) && REG_IS_BH(src_size)) - { - host_arm64_UBFX(block, REG_TEMP, src_reg, 8, 8); - host_arm64_AND_IMM(block, REG_TEMP2, shift_reg, 7); - host_arm64_ORR_REG(block, REG_TEMP, REG_TEMP, REG_TEMP, 8); - host_arm64_LSR(block, REG_TEMP, REG_TEMP, REG_TEMP2); - host_arm64_BFI(block, dest_reg, REG_TEMP, 8, 8); - } - else - fatal("ROR %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real); + if (REG_IS_L(dest_size) && REG_IS_L(src_size)) { + host_arm64_ROR(block, dest_reg, src_reg, shift_reg); + } else if (REG_IS_W(dest_size) && REG_IS_W(src_size)) { + host_arm64_UBFX(block, REG_TEMP, src_reg, 0, 16); + host_arm64_AND_IMM(block, REG_TEMP2, shift_reg, 15); + host_arm64_ORR_REG(block, REG_TEMP, REG_TEMP, REG_TEMP, 16); + host_arm64_LSR(block, REG_TEMP, REG_TEMP, REG_TEMP2); + host_arm64_BFI(block, dest_reg, REG_TEMP, 0, 16); + } else if (REG_IS_B(dest_size) && REG_IS_B(src_size)) { + host_arm64_UBFX(block, REG_TEMP, src_reg, 0, 8); + host_arm64_AND_IMM(block, REG_TEMP2, shift_reg, 7); + host_arm64_ORR_REG(block, REG_TEMP, REG_TEMP, REG_TEMP, 8); + host_arm64_LSR(block, REG_TEMP, REG_TEMP, REG_TEMP2); + host_arm64_BFI(block, dest_reg, REG_TEMP, 0, 8); + } else if (REG_IS_BH(dest_size) && REG_IS_BH(src_size)) { + host_arm64_UBFX(block, REG_TEMP, src_reg, 8, 8); + host_arm64_AND_IMM(block, REG_TEMP2, shift_reg, 7); + host_arm64_ORR_REG(block, REG_TEMP, REG_TEMP, REG_TEMP, 8); + host_arm64_LSR(block, REG_TEMP, REG_TEMP, REG_TEMP2); + host_arm64_BFI(block, dest_reg, REG_TEMP, 8, 8); + } else + fatal("ROR %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real); - return 0; + return 0; } -static int codegen_ROR_IMM(codeblock_t *block, uop_t *uop) +static int +codegen_ROR_IMM(codeblock_t *block, uop_t *uop) { - int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg = HOST_REG_GET(uop->src_reg_a_real); - int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size = IREG_GET_SIZE(uop->src_reg_a_real); + int dest_reg = HOST_REG_GET(uop->dest_reg_a_real); + int src_reg = HOST_REG_GET(uop->src_reg_a_real); + int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real); + int src_size = IREG_GET_SIZE(uop->src_reg_a_real); - if (REG_IS_L(dest_size) && REG_IS_L(src_size)) - { - if (!(uop->imm_data & 31)) - { - if (src_reg != dest_reg) - host_arm64_MOV_REG(block, dest_reg, src_reg, 0); - } - else - { - host_arm64_MOV_REG_ROR(block, dest_reg, src_reg, uop->imm_data & 31); - } + if (REG_IS_L(dest_size) && REG_IS_L(src_size)) { + if (!(uop->imm_data & 31)) { + if (src_reg != dest_reg) + host_arm64_MOV_REG(block, dest_reg, src_reg, 0); + } else { + host_arm64_MOV_REG_ROR(block, dest_reg, src_reg, uop->imm_data & 31); } - else if (REG_IS_W(dest_size) && REG_IS_W(src_size)) - { - if ((uop->imm_data & 15) == 0) - { - if (src_reg != dest_reg) - fatal("ROR_IMM %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real); - } - else - { - host_arm64_UBFX(block, REG_TEMP, src_reg, 0, 16); - host_arm64_ORR_REG(block, REG_TEMP, REG_TEMP, REG_TEMP, 16); - host_arm64_MOV_REG_LSR(block, REG_TEMP, REG_TEMP, uop->imm_data & 15); - host_arm64_BFI(block, dest_reg, REG_TEMP, 0, 16); - } - } - else if (REG_IS_B(dest_size) && REG_IS_B(src_size)) - { - if ((uop->imm_data & 7) == 0) - { - if (src_reg != dest_reg) - fatal("ROR_IMM %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real); - } - else - { - host_arm64_UBFX(block, REG_TEMP, src_reg, 0, 8); - host_arm64_ORR_REG(block, REG_TEMP, REG_TEMP, REG_TEMP, 8); - host_arm64_MOV_REG_LSR(block, REG_TEMP, REG_TEMP, uop->imm_data & 7); - host_arm64_BFI(block, dest_reg, REG_TEMP, 0, 8); - } - } - else if (REG_IS_BH(dest_size) && REG_IS_BH(src_size)) - { - if ((uop->imm_data & 7) == 0) - { - if (src_reg != dest_reg) - fatal("ROR_IMM %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real); - } - else - { - host_arm64_UBFX(block, REG_TEMP, src_reg, 8, 8); - host_arm64_ORR_REG(block, REG_TEMP, REG_TEMP, REG_TEMP, 8); - host_arm64_MOV_REG_LSR(block, REG_TEMP, REG_TEMP, uop->imm_data & 7); - host_arm64_BFI(block, dest_reg, REG_TEMP, 8, 8); - } - } - else + } else if (REG_IS_W(dest_size) && REG_IS_W(src_size)) { + if ((uop->imm_data & 15) == 0) { + if (src_reg != dest_reg) fatal("ROR_IMM %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real); + } else { + host_arm64_UBFX(block, REG_TEMP, src_reg, 0, 16); + host_arm64_ORR_REG(block, REG_TEMP, REG_TEMP, REG_TEMP, 16); + host_arm64_MOV_REG_LSR(block, REG_TEMP, REG_TEMP, uop->imm_data & 15); + host_arm64_BFI(block, dest_reg, REG_TEMP, 0, 16); + } + } else if (REG_IS_B(dest_size) && REG_IS_B(src_size)) { + if ((uop->imm_data & 7) == 0) { + if (src_reg != dest_reg) + fatal("ROR_IMM %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real); + } else { + host_arm64_UBFX(block, REG_TEMP, src_reg, 0, 8); + host_arm64_ORR_REG(block, REG_TEMP, REG_TEMP, REG_TEMP, 8); + host_arm64_MOV_REG_LSR(block, REG_TEMP, REG_TEMP, uop->imm_data & 7); + host_arm64_BFI(block, dest_reg, REG_TEMP, 0, 8); + } + } else if (REG_IS_BH(dest_size) && REG_IS_BH(src_size)) { + if ((uop->imm_data & 7) == 0) { + if (src_reg != dest_reg) + fatal("ROR_IMM %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real); + } else { + host_arm64_UBFX(block, REG_TEMP, src_reg, 8, 8); + host_arm64_ORR_REG(block, REG_TEMP, REG_TEMP, REG_TEMP, 8); + host_arm64_MOV_REG_LSR(block, REG_TEMP, REG_TEMP, uop->imm_data & 7); + host_arm64_BFI(block, dest_reg, REG_TEMP, 8, 8); + } + } else + fatal("ROR_IMM %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real); - return 0; + return 0; } -static int codegen_SAR(codeblock_t *block, uop_t *uop) +static int +codegen_SAR(codeblock_t *block, uop_t *uop) { - int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg = HOST_REG_GET(uop->src_reg_a_real), shift_reg = HOST_REG_GET(uop->src_reg_b_real); - int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size = IREG_GET_SIZE(uop->src_reg_a_real); + int dest_reg = HOST_REG_GET(uop->dest_reg_a_real); + int src_reg = HOST_REG_GET(uop->src_reg_a_real); + int shift_reg = HOST_REG_GET(uop->src_reg_b_real); + int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real); + int src_size = IREG_GET_SIZE(uop->src_reg_a_real); - if (REG_IS_L(dest_size) && REG_IS_L(src_size)) - { - host_arm64_ASR(block, dest_reg, src_reg, shift_reg); - } - else if (REG_IS_W(dest_size) && REG_IS_W(src_size)) - { - host_arm64_MOV_REG(block, REG_TEMP, src_reg, 16); - host_arm64_ASR(block, REG_TEMP, REG_TEMP, shift_reg); - host_arm64_UBFX(block, REG_TEMP, REG_TEMP, 16, 16); - host_arm64_BFI(block, dest_reg, REG_TEMP, 0, 16); - } - else if (REG_IS_B(dest_size) && REG_IS_B(src_size)) - { - host_arm64_MOV_REG(block, REG_TEMP, src_reg, 24); - host_arm64_ASR(block, REG_TEMP, REG_TEMP, shift_reg); - host_arm64_UBFX(block, REG_TEMP, REG_TEMP, 24, 8); - host_arm64_BFI(block, dest_reg, REG_TEMP, 0, 8); - } - else if (REG_IS_BH(dest_size) && REG_IS_BH(src_size)) - { - host_arm64_MOV_REG(block, REG_TEMP, src_reg, 16); - host_arm64_ASR(block, REG_TEMP, REG_TEMP, shift_reg); - host_arm64_UBFX(block, REG_TEMP, REG_TEMP, 24, 8); - host_arm64_BFI(block, dest_reg, REG_TEMP, 8, 8); - } - else - fatal("SAR %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real); + if (REG_IS_L(dest_size) && REG_IS_L(src_size)) { + host_arm64_ASR(block, dest_reg, src_reg, shift_reg); + } else if (REG_IS_W(dest_size) && REG_IS_W(src_size)) { + host_arm64_MOV_REG(block, REG_TEMP, src_reg, 16); + host_arm64_ASR(block, REG_TEMP, REG_TEMP, shift_reg); + host_arm64_UBFX(block, REG_TEMP, REG_TEMP, 16, 16); + host_arm64_BFI(block, dest_reg, REG_TEMP, 0, 16); + } else if (REG_IS_B(dest_size) && REG_IS_B(src_size)) { + host_arm64_MOV_REG(block, REG_TEMP, src_reg, 24); + host_arm64_ASR(block, REG_TEMP, REG_TEMP, shift_reg); + host_arm64_UBFX(block, REG_TEMP, REG_TEMP, 24, 8); + host_arm64_BFI(block, dest_reg, REG_TEMP, 0, 8); + } else if (REG_IS_BH(dest_size) && REG_IS_BH(src_size)) { + host_arm64_MOV_REG(block, REG_TEMP, src_reg, 16); + host_arm64_ASR(block, REG_TEMP, REG_TEMP, shift_reg); + host_arm64_UBFX(block, REG_TEMP, REG_TEMP, 24, 8); + host_arm64_BFI(block, dest_reg, REG_TEMP, 8, 8); + } else + fatal("SAR %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real); - return 0; + return 0; } -static int codegen_SAR_IMM(codeblock_t *block, uop_t *uop) +static int +codegen_SAR_IMM(codeblock_t *block, uop_t *uop) { - int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg = HOST_REG_GET(uop->src_reg_a_real); - int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size = IREG_GET_SIZE(uop->src_reg_a_real); + int dest_reg = HOST_REG_GET(uop->dest_reg_a_real); + int src_reg = HOST_REG_GET(uop->src_reg_a_real); + int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real); + int src_size = IREG_GET_SIZE(uop->src_reg_a_real); - if (REG_IS_L(dest_size) && REG_IS_L(src_size)) - { - host_arm64_MOV_REG_ASR(block, dest_reg, src_reg, uop->imm_data); - } - else if (REG_IS_W(dest_size) && REG_IS_W(src_size)) - { - host_arm64_MOV_REG(block, REG_TEMP, src_reg, 16); - host_arm64_MOV_REG_ASR(block, REG_TEMP, REG_TEMP, uop->imm_data); - host_arm64_UBFX(block, REG_TEMP, REG_TEMP, 16, 16); - host_arm64_BFI(block, dest_reg, REG_TEMP, 0, 16); - } - else if (REG_IS_B(dest_size) && REG_IS_B(src_size)) - { - host_arm64_MOV_REG(block, REG_TEMP, src_reg, 24); - host_arm64_MOV_REG_ASR(block, REG_TEMP, REG_TEMP, uop->imm_data); - host_arm64_UBFX(block, REG_TEMP, REG_TEMP, 24, 8); - host_arm64_BFI(block, dest_reg, REG_TEMP, 0, 8); - } - else if (REG_IS_BH(dest_size) && REG_IS_BH(src_size)) - { - host_arm64_MOV_REG(block, REG_TEMP, src_reg, 16); - host_arm64_MOV_REG_ASR(block, REG_TEMP, REG_TEMP, uop->imm_data); - host_arm64_UBFX(block, REG_TEMP, REG_TEMP, 24, 8); - host_arm64_BFI(block, dest_reg, REG_TEMP, 8, 8); - } - else - fatal("SAR_IMM %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real); + if (REG_IS_L(dest_size) && REG_IS_L(src_size)) { + host_arm64_MOV_REG_ASR(block, dest_reg, src_reg, uop->imm_data); + } else if (REG_IS_W(dest_size) && REG_IS_W(src_size)) { + host_arm64_MOV_REG(block, REG_TEMP, src_reg, 16); + host_arm64_MOV_REG_ASR(block, REG_TEMP, REG_TEMP, uop->imm_data); + host_arm64_UBFX(block, REG_TEMP, REG_TEMP, 16, 16); + host_arm64_BFI(block, dest_reg, REG_TEMP, 0, 16); + } else if (REG_IS_B(dest_size) && REG_IS_B(src_size)) { + host_arm64_MOV_REG(block, REG_TEMP, src_reg, 24); + host_arm64_MOV_REG_ASR(block, REG_TEMP, REG_TEMP, uop->imm_data); + host_arm64_UBFX(block, REG_TEMP, REG_TEMP, 24, 8); + host_arm64_BFI(block, dest_reg, REG_TEMP, 0, 8); + } else if (REG_IS_BH(dest_size) && REG_IS_BH(src_size)) { + host_arm64_MOV_REG(block, REG_TEMP, src_reg, 16); + host_arm64_MOV_REG_ASR(block, REG_TEMP, REG_TEMP, uop->imm_data); + host_arm64_UBFX(block, REG_TEMP, REG_TEMP, 24, 8); + host_arm64_BFI(block, dest_reg, REG_TEMP, 8, 8); + } else + fatal("SAR_IMM %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real); - return 0; + return 0; } -static int codegen_SHL(codeblock_t *block, uop_t *uop) +static int +codegen_SHL(codeblock_t *block, uop_t *uop) { - int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg = HOST_REG_GET(uop->src_reg_a_real), shift_reg = HOST_REG_GET(uop->src_reg_b_real); - int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size = IREG_GET_SIZE(uop->src_reg_a_real); + int dest_reg = HOST_REG_GET(uop->dest_reg_a_real); + int src_reg = HOST_REG_GET(uop->src_reg_a_real); + int shift_reg = HOST_REG_GET(uop->src_reg_b_real); + int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real); + int src_size = IREG_GET_SIZE(uop->src_reg_a_real); - if (REG_IS_L(dest_size) && REG_IS_L(src_size)) - { - host_arm64_LSL(block, dest_reg, src_reg, shift_reg); - } - else if (REG_IS_W(dest_size) && REG_IS_W(src_size)) - { - host_arm64_LSL(block, REG_TEMP, src_reg, shift_reg); - host_arm64_BFI(block, dest_reg, REG_TEMP, 0, 16); - } - else if (REG_IS_B(dest_size) && REG_IS_B(src_size)) - { - host_arm64_LSL(block, REG_TEMP, src_reg, shift_reg); - host_arm64_BFI(block, dest_reg, REG_TEMP, 0, 8); - } - else if (REG_IS_BH(dest_size) && REG_IS_BH(src_size)) - { - host_arm64_UBFX(block, REG_TEMP, src_reg, 8, 8); - host_arm64_LSL(block, REG_TEMP, REG_TEMP, shift_reg); - host_arm64_BFI(block, dest_reg, REG_TEMP, 8, 8); - } - else - fatal("SHL %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real); + if (REG_IS_L(dest_size) && REG_IS_L(src_size)) { + host_arm64_LSL(block, dest_reg, src_reg, shift_reg); + } else if (REG_IS_W(dest_size) && REG_IS_W(src_size)) { + host_arm64_LSL(block, REG_TEMP, src_reg, shift_reg); + host_arm64_BFI(block, dest_reg, REG_TEMP, 0, 16); + } else if (REG_IS_B(dest_size) && REG_IS_B(src_size)) { + host_arm64_LSL(block, REG_TEMP, src_reg, shift_reg); + host_arm64_BFI(block, dest_reg, REG_TEMP, 0, 8); + } else if (REG_IS_BH(dest_size) && REG_IS_BH(src_size)) { + host_arm64_UBFX(block, REG_TEMP, src_reg, 8, 8); + host_arm64_LSL(block, REG_TEMP, REG_TEMP, shift_reg); + host_arm64_BFI(block, dest_reg, REG_TEMP, 8, 8); + } else + fatal("SHL %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real); - return 0; + return 0; } -static int codegen_SHL_IMM(codeblock_t *block, uop_t *uop) +static int +codegen_SHL_IMM(codeblock_t *block, uop_t *uop) { - int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg = HOST_REG_GET(uop->src_reg_a_real); - int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size = IREG_GET_SIZE(uop->src_reg_a_real); + int dest_reg = HOST_REG_GET(uop->dest_reg_a_real); + int src_reg = HOST_REG_GET(uop->src_reg_a_real); + int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real); + int src_size = IREG_GET_SIZE(uop->src_reg_a_real); - if (REG_IS_L(dest_size) && REG_IS_L(src_size)) - { - host_arm64_MOV_REG(block, dest_reg, src_reg, uop->imm_data); - } - else if (REG_IS_W(dest_size) && REG_IS_W(src_size)) - { - host_arm64_MOV_REG(block, REG_TEMP, src_reg, uop->imm_data); - host_arm64_BFI(block, dest_reg, REG_TEMP, 0, 16); - } - else if (REG_IS_B(dest_size) && REG_IS_B(src_size)) - { - host_arm64_MOV_REG(block, REG_TEMP, src_reg, uop->imm_data); - host_arm64_BFI(block, dest_reg, REG_TEMP, 0, 8); - } - else if (REG_IS_BH(dest_size) && REG_IS_BH(src_size)) - { - host_arm64_UBFX(block, REG_TEMP, src_reg, 8, 8); - host_arm64_MOV_REG(block, REG_TEMP, REG_TEMP, uop->imm_data); - host_arm64_BFI(block, dest_reg, REG_TEMP, 8, 8); - } - else - fatal("SHL_IMM %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real); + if (REG_IS_L(dest_size) && REG_IS_L(src_size)) { + host_arm64_MOV_REG(block, dest_reg, src_reg, uop->imm_data); + } else if (REG_IS_W(dest_size) && REG_IS_W(src_size)) { + host_arm64_MOV_REG(block, REG_TEMP, src_reg, uop->imm_data); + host_arm64_BFI(block, dest_reg, REG_TEMP, 0, 16); + } else if (REG_IS_B(dest_size) && REG_IS_B(src_size)) { + host_arm64_MOV_REG(block, REG_TEMP, src_reg, uop->imm_data); + host_arm64_BFI(block, dest_reg, REG_TEMP, 0, 8); + } else if (REG_IS_BH(dest_size) && REG_IS_BH(src_size)) { + host_arm64_UBFX(block, REG_TEMP, src_reg, 8, 8); + host_arm64_MOV_REG(block, REG_TEMP, REG_TEMP, uop->imm_data); + host_arm64_BFI(block, dest_reg, REG_TEMP, 8, 8); + } else + fatal("SHL_IMM %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real); - return 0; + return 0; } -static int codegen_SHR(codeblock_t *block, uop_t *uop) +static int +codegen_SHR(codeblock_t *block, uop_t *uop) { - int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg = HOST_REG_GET(uop->src_reg_a_real), shift_reg = HOST_REG_GET(uop->src_reg_b_real); - int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size = IREG_GET_SIZE(uop->src_reg_a_real); + int dest_reg = HOST_REG_GET(uop->dest_reg_a_real); + int src_reg = HOST_REG_GET(uop->src_reg_a_real); + int shift_reg = HOST_REG_GET(uop->src_reg_b_real); + int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real); + int src_size = IREG_GET_SIZE(uop->src_reg_a_real); - if (REG_IS_L(dest_size) && REG_IS_L(src_size)) - { - host_arm64_LSR(block, dest_reg, src_reg, shift_reg); - } - else if (REG_IS_W(dest_size) && REG_IS_W(src_size)) - { - host_arm64_AND_IMM(block, REG_TEMP, src_reg, 0xffff); - host_arm64_LSR(block, REG_TEMP, REG_TEMP, shift_reg); - host_arm64_BFI(block, dest_reg, REG_TEMP, 0, 16); - } - else if (REG_IS_B(dest_size) && REG_IS_B(src_size)) - { - host_arm64_AND_IMM(block, REG_TEMP, src_reg, 0xff); - host_arm64_LSR(block, REG_TEMP, REG_TEMP, shift_reg); - host_arm64_BFI(block, dest_reg, REG_TEMP, 0, 8); - } - else if (REG_IS_BH(dest_size) && REG_IS_BH(src_size)) - { - host_arm64_UBFX(block, REG_TEMP, src_reg, 8, 8); - host_arm64_LSR(block, REG_TEMP, REG_TEMP, shift_reg); - host_arm64_BFI(block, dest_reg, REG_TEMP, 8, 8); - } - else - fatal("SHR %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real); + if (REG_IS_L(dest_size) && REG_IS_L(src_size)) { + host_arm64_LSR(block, dest_reg, src_reg, shift_reg); + } else if (REG_IS_W(dest_size) && REG_IS_W(src_size)) { + host_arm64_AND_IMM(block, REG_TEMP, src_reg, 0xffff); + host_arm64_LSR(block, REG_TEMP, REG_TEMP, shift_reg); + host_arm64_BFI(block, dest_reg, REG_TEMP, 0, 16); + } else if (REG_IS_B(dest_size) && REG_IS_B(src_size)) { + host_arm64_AND_IMM(block, REG_TEMP, src_reg, 0xff); + host_arm64_LSR(block, REG_TEMP, REG_TEMP, shift_reg); + host_arm64_BFI(block, dest_reg, REG_TEMP, 0, 8); + } else if (REG_IS_BH(dest_size) && REG_IS_BH(src_size)) { + host_arm64_UBFX(block, REG_TEMP, src_reg, 8, 8); + host_arm64_LSR(block, REG_TEMP, REG_TEMP, shift_reg); + host_arm64_BFI(block, dest_reg, REG_TEMP, 8, 8); + } else + fatal("SHR %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real); - return 0; + return 0; } -static int codegen_SHR_IMM(codeblock_t *block, uop_t *uop) +static int +codegen_SHR_IMM(codeblock_t *block, uop_t *uop) { - int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg = HOST_REG_GET(uop->src_reg_a_real); - int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size = IREG_GET_SIZE(uop->src_reg_a_real); + int dest_reg = HOST_REG_GET(uop->dest_reg_a_real); + int src_reg = HOST_REG_GET(uop->src_reg_a_real); + int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real); + int src_size = IREG_GET_SIZE(uop->src_reg_a_real); - if (REG_IS_L(dest_size) && REG_IS_L(src_size)) - { - host_arm64_MOV_REG_LSR(block, dest_reg, src_reg, uop->imm_data); - } - else if (REG_IS_W(dest_size) && REG_IS_W(src_size)) - { - host_arm64_AND_IMM(block, REG_TEMP, src_reg, 0xffff); - host_arm64_MOV_REG_LSR(block, REG_TEMP, REG_TEMP, uop->imm_data); - host_arm64_BFI(block, dest_reg, REG_TEMP, 0, 16); - } - else if (REG_IS_B(dest_size) && REG_IS_B(src_size)) - { - host_arm64_AND_IMM(block, REG_TEMP, src_reg, 0xff); - host_arm64_MOV_REG_LSR(block, REG_TEMP, REG_TEMP, uop->imm_data); - host_arm64_BFI(block, dest_reg, REG_TEMP, 0, 8); - } - else if (REG_IS_BH(dest_size) && REG_IS_BH(src_size)) - { - host_arm64_UBFX(block, REG_TEMP, src_reg, 8, 8); - host_arm64_MOV_REG_LSR(block, REG_TEMP, REG_TEMP, uop->imm_data); - host_arm64_BFI(block, dest_reg, REG_TEMP, 8, 8); - } - else - fatal("SHR_IMM %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real); + if (REG_IS_L(dest_size) && REG_IS_L(src_size)) { + host_arm64_MOV_REG_LSR(block, dest_reg, src_reg, uop->imm_data); + } else if (REG_IS_W(dest_size) && REG_IS_W(src_size)) { + host_arm64_AND_IMM(block, REG_TEMP, src_reg, 0xffff); + host_arm64_MOV_REG_LSR(block, REG_TEMP, REG_TEMP, uop->imm_data); + host_arm64_BFI(block, dest_reg, REG_TEMP, 0, 16); + } else if (REG_IS_B(dest_size) && REG_IS_B(src_size)) { + host_arm64_AND_IMM(block, REG_TEMP, src_reg, 0xff); + host_arm64_MOV_REG_LSR(block, REG_TEMP, REG_TEMP, uop->imm_data); + host_arm64_BFI(block, dest_reg, REG_TEMP, 0, 8); + } else if (REG_IS_BH(dest_size) && REG_IS_BH(src_size)) { + host_arm64_UBFX(block, REG_TEMP, src_reg, 8, 8); + host_arm64_MOV_REG_LSR(block, REG_TEMP, REG_TEMP, uop->imm_data); + host_arm64_BFI(block, dest_reg, REG_TEMP, 8, 8); + } else + fatal("SHR_IMM %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real); - return 0; + return 0; } -static int codegen_STORE_PTR_IMM(codeblock_t *block, uop_t *uop) +static int +codegen_STORE_PTR_IMM(codeblock_t *block, uop_t *uop) { - host_arm64_mov_imm(block, REG_W16, uop->imm_data); + host_arm64_mov_imm(block, REG_W16, uop->imm_data); - if (in_range12_w((uintptr_t)uop->p - (uintptr_t)&cpu_state)) - host_arm64_STR_IMM_W(block, REG_W16, REG_CPUSTATE, (uintptr_t)uop->p - (uintptr_t)&cpu_state); - else - fatal("codegen_STORE_PTR_IMM - not in range\n"); + if (in_range12_w((uintptr_t) uop->p - (uintptr_t) &cpu_state)) + host_arm64_STR_IMM_W(block, REG_W16, REG_CPUSTATE, (uintptr_t) uop->p - (uintptr_t) &cpu_state); + else + fatal("codegen_STORE_PTR_IMM - not in range\n"); - return 0; + return 0; } -static int codegen_STORE_PTR_IMM_8(codeblock_t *block, uop_t *uop) +static int +codegen_STORE_PTR_IMM_8(codeblock_t *block, uop_t *uop) { - host_arm64_mov_imm(block, REG_W16, uop->imm_data); + host_arm64_mov_imm(block, REG_W16, uop->imm_data); - if (in_range12_b((uintptr_t)uop->p - (uintptr_t)&cpu_state)) - host_arm64_STRB_IMM(block, REG_W16, REG_CPUSTATE, (uintptr_t)uop->p - (uintptr_t)&cpu_state); - else - fatal("codegen_STORE_PTR_IMM - not in range\n"); + if (in_range12_b((uintptr_t) uop->p - (uintptr_t) &cpu_state)) + host_arm64_STRB_IMM(block, REG_W16, REG_CPUSTATE, (uintptr_t) uop->p - (uintptr_t) &cpu_state); + else + fatal("codegen_STORE_PTR_IMM - not in range\n"); - return 0; + return 0; } -static int codegen_SUB(codeblock_t *block, uop_t *uop) +static int +codegen_SUB(codeblock_t *block, uop_t *uop) { - int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg_a = HOST_REG_GET(uop->src_reg_a_real), src_reg_b = HOST_REG_GET(uop->src_reg_b_real); - int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size_a = IREG_GET_SIZE(uop->src_reg_a_real), src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); + int dest_reg = HOST_REG_GET(uop->dest_reg_a_real); + int src_reg_a = HOST_REG_GET(uop->src_reg_a_real); + int src_reg_b = HOST_REG_GET(uop->src_reg_b_real); + int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real); + int src_size_a = IREG_GET_SIZE(uop->src_reg_a_real); + int src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); - if (REG_IS_L(dest_size) && REG_IS_L(src_size_a) && REG_IS_L(src_size_b)) - { - host_arm64_SUB_REG(block, dest_reg, src_reg_a, src_reg_b, 0); - } - else if (REG_IS_W(dest_size) && REG_IS_W(src_size_a) && REG_IS_W(src_size_b)) - { - host_arm64_SUB_REG(block, REG_TEMP, src_reg_a, src_reg_b, 0); - host_arm64_BFI(block, dest_reg, REG_TEMP, 0, 16); - } - else if (REG_IS_B(dest_size) && REG_IS_B(src_size_a) && REG_IS_B(src_size_b)) - { - host_arm64_SUB_REG(block, REG_TEMP, src_reg_a, src_reg_b, 0); - host_arm64_BFI(block, dest_reg, REG_TEMP, 0, 8); - } - else if (REG_IS_B(dest_size) && REG_IS_B(src_size_a) && REG_IS_BH(src_size_b)) - { - host_arm64_SUB_REG_LSR(block, REG_TEMP, src_reg_a, src_reg_b, 8); - host_arm64_BFI(block, dest_reg, REG_TEMP, 0, 8); - } - else if (REG_IS_B(dest_size) && REG_IS_BH(src_size_a) && REG_IS_B(src_size_b)) - { - host_arm64_SUB_REG(block, REG_TEMP, src_reg_a, src_reg_b, 8); - host_arm64_MOV_REG_LSR(block, REG_TEMP, REG_TEMP, 8); - host_arm64_BFI(block, dest_reg, REG_TEMP, 0, 8); - } - else if (REG_IS_B(dest_size) && REG_IS_BH(src_size_a) && REG_IS_BH(src_size_b)) - { - host_arm64_MOV_REG_LSR(block, REG_TEMP, src_reg_a, 8); - host_arm64_SUB_REG_LSR(block, REG_TEMP, REG_TEMP, src_reg_b, 8); - host_arm64_BFI(block, dest_reg, REG_TEMP, 0, 8); - } - else if (REG_IS_BH(dest_size) && REG_IS_BH(src_size_a) && REG_IS_B(src_size_b)) - { - host_arm64_SUB_REG(block, REG_TEMP, src_reg_a, src_reg_b, 8); - host_arm64_MOV_REG_LSR(block, REG_TEMP, REG_TEMP, 8); - host_arm64_BFI(block, dest_reg, REG_TEMP, 8, 8); - } - else if (REG_IS_BH(dest_size) && REG_IS_BH(src_size_a) && REG_IS_BH(src_size_b)) - { - host_arm64_MOV_REG_LSR(block, REG_TEMP, src_reg_a, 8); - host_arm64_SUB_REG_LSR(block, REG_TEMP, REG_TEMP, src_reg_b, 8); - host_arm64_BFI(block, dest_reg, REG_TEMP, 8, 8); - } - else - fatal("SUB %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real); + if (REG_IS_L(dest_size) && REG_IS_L(src_size_a) && REG_IS_L(src_size_b)) { + host_arm64_SUB_REG(block, dest_reg, src_reg_a, src_reg_b, 0); + } else if (REG_IS_W(dest_size) && REG_IS_W(src_size_a) && REG_IS_W(src_size_b)) { + host_arm64_SUB_REG(block, REG_TEMP, src_reg_a, src_reg_b, 0); + host_arm64_BFI(block, dest_reg, REG_TEMP, 0, 16); + } else if (REG_IS_B(dest_size) && REG_IS_B(src_size_a) && REG_IS_B(src_size_b)) { + host_arm64_SUB_REG(block, REG_TEMP, src_reg_a, src_reg_b, 0); + host_arm64_BFI(block, dest_reg, REG_TEMP, 0, 8); + } else if (REG_IS_B(dest_size) && REG_IS_B(src_size_a) && REG_IS_BH(src_size_b)) { + host_arm64_SUB_REG_LSR(block, REG_TEMP, src_reg_a, src_reg_b, 8); + host_arm64_BFI(block, dest_reg, REG_TEMP, 0, 8); + } else if (REG_IS_B(dest_size) && REG_IS_BH(src_size_a) && REG_IS_B(src_size_b)) { + host_arm64_SUB_REG(block, REG_TEMP, src_reg_a, src_reg_b, 8); + host_arm64_MOV_REG_LSR(block, REG_TEMP, REG_TEMP, 8); + host_arm64_BFI(block, dest_reg, REG_TEMP, 0, 8); + } else if (REG_IS_B(dest_size) && REG_IS_BH(src_size_a) && REG_IS_BH(src_size_b)) { + host_arm64_MOV_REG_LSR(block, REG_TEMP, src_reg_a, 8); + host_arm64_SUB_REG_LSR(block, REG_TEMP, REG_TEMP, src_reg_b, 8); + host_arm64_BFI(block, dest_reg, REG_TEMP, 0, 8); + } else if (REG_IS_BH(dest_size) && REG_IS_BH(src_size_a) && REG_IS_B(src_size_b)) { + host_arm64_SUB_REG(block, REG_TEMP, src_reg_a, src_reg_b, 8); + host_arm64_MOV_REG_LSR(block, REG_TEMP, REG_TEMP, 8); + host_arm64_BFI(block, dest_reg, REG_TEMP, 8, 8); + } else if (REG_IS_BH(dest_size) && REG_IS_BH(src_size_a) && REG_IS_BH(src_size_b)) { + host_arm64_MOV_REG_LSR(block, REG_TEMP, src_reg_a, 8); + host_arm64_SUB_REG_LSR(block, REG_TEMP, REG_TEMP, src_reg_b, 8); + host_arm64_BFI(block, dest_reg, REG_TEMP, 8, 8); + } else + fatal("SUB %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real); - return 0; + return 0; } -static int codegen_SUB_IMM(codeblock_t *block, uop_t *uop) +static int +codegen_SUB_IMM(codeblock_t *block, uop_t *uop) { - int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg = HOST_REG_GET(uop->src_reg_a_real); - int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size = IREG_GET_SIZE(uop->src_reg_a_real); + int dest_reg = HOST_REG_GET(uop->dest_reg_a_real); + int src_reg = HOST_REG_GET(uop->src_reg_a_real); + int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real); + int src_size = IREG_GET_SIZE(uop->src_reg_a_real); - if (REG_IS_L(dest_size) && REG_IS_L(src_size)) - { - host_arm64_SUB_IMM(block, dest_reg, src_reg, uop->imm_data); - } - else if (REG_IS_W(dest_size) && REG_IS_W(src_size)) - { - host_arm64_SUB_IMM(block, REG_TEMP, src_reg, uop->imm_data); - host_arm64_BFI(block, dest_reg, REG_TEMP, 0, 16); - } - else if (REG_IS_B(dest_size) && REG_IS_B(src_size)) - { - host_arm64_SUB_IMM(block, REG_TEMP, src_reg, uop->imm_data); - host_arm64_BFI(block, dest_reg, REG_TEMP, 0, 8); - } - else if (REG_IS_B(dest_size) && REG_IS_BH(src_size)) - { - host_arm64_SUB_IMM(block, REG_TEMP, src_reg, uop->imm_data << 8); - host_arm64_MOV_REG_LSR(block, REG_TEMP, REG_TEMP, 8); - host_arm64_BFI(block, dest_reg, REG_TEMP, 0, 8); - } - else if (REG_IS_BH(dest_size) && REG_IS_BH(src_size)) - { - host_arm64_SUB_IMM(block, REG_TEMP, src_reg, uop->imm_data << 8); - host_arm64_MOV_REG_LSR(block, REG_TEMP, REG_TEMP, 8); - host_arm64_BFI(block, dest_reg, REG_TEMP, 8, 8); - } - else - fatal("SUB_IMM %x %x\n", uop->dest_reg_a_real, uop->src_reg_a_real); + if (REG_IS_L(dest_size) && REG_IS_L(src_size)) { + host_arm64_SUB_IMM(block, dest_reg, src_reg, uop->imm_data); + } else if (REG_IS_W(dest_size) && REG_IS_W(src_size)) { + host_arm64_SUB_IMM(block, REG_TEMP, src_reg, uop->imm_data); + host_arm64_BFI(block, dest_reg, REG_TEMP, 0, 16); + } else if (REG_IS_B(dest_size) && REG_IS_B(src_size)) { + host_arm64_SUB_IMM(block, REG_TEMP, src_reg, uop->imm_data); + host_arm64_BFI(block, dest_reg, REG_TEMP, 0, 8); + } else if (REG_IS_B(dest_size) && REG_IS_BH(src_size)) { + host_arm64_SUB_IMM(block, REG_TEMP, src_reg, uop->imm_data << 8); + host_arm64_MOV_REG_LSR(block, REG_TEMP, REG_TEMP, 8); + host_arm64_BFI(block, dest_reg, REG_TEMP, 0, 8); + } else if (REG_IS_BH(dest_size) && REG_IS_BH(src_size)) { + host_arm64_SUB_IMM(block, REG_TEMP, src_reg, uop->imm_data << 8); + host_arm64_MOV_REG_LSR(block, REG_TEMP, REG_TEMP, 8); + host_arm64_BFI(block, dest_reg, REG_TEMP, 8, 8); + } else + fatal("SUB_IMM %x %x\n", uop->dest_reg_a_real, uop->src_reg_a_real); - return 0; + return 0; } -static int codegen_TEST_JNS_DEST(codeblock_t *block, uop_t *uop) +static int +codegen_TEST_JNS_DEST(codeblock_t *block, uop_t *uop) { - int src_reg = HOST_REG_GET(uop->src_reg_a_real); - int src_size = IREG_GET_SIZE(uop->src_reg_a_real); + int src_reg = HOST_REG_GET(uop->src_reg_a_real); + int src_size = IREG_GET_SIZE(uop->src_reg_a_real); - if (REG_IS_L(src_size)) - { - host_arm64_TST_IMM(block, src_reg, 1 << 31); - } - else if (REG_IS_W(src_size)) - { - host_arm64_TST_IMM(block, src_reg, 1 << 15); - } - else if (REG_IS_B(src_size)) - { - host_arm64_TST_IMM(block, src_reg, 1 << 7); - } - else - fatal("TEST_JNS_DEST %02x\n", uop->src_reg_a_real); + if (REG_IS_L(src_size)) { + host_arm64_TST_IMM(block, src_reg, 1 << 31); + } else if (REG_IS_W(src_size)) { + host_arm64_TST_IMM(block, src_reg, 1 << 15); + } else if (REG_IS_B(src_size)) { + host_arm64_TST_IMM(block, src_reg, 1 << 7); + } else + fatal("TEST_JNS_DEST %02x\n", uop->src_reg_a_real); - uop->p = host_arm64_BEQ_(block); + uop->p = host_arm64_BEQ_(block); - return 0; + return 0; } -static int codegen_TEST_JS_DEST(codeblock_t *block, uop_t *uop) +static int +codegen_TEST_JS_DEST(codeblock_t *block, uop_t *uop) { - int src_reg = HOST_REG_GET(uop->src_reg_a_real); - int src_size = IREG_GET_SIZE(uop->src_reg_a_real); + int src_reg = HOST_REG_GET(uop->src_reg_a_real); + int src_size = IREG_GET_SIZE(uop->src_reg_a_real); - if (REG_IS_L(src_size)) - { - host_arm64_TST_IMM(block, src_reg, 1 << 31); - } - else if (REG_IS_W(src_size)) - { - host_arm64_TST_IMM(block, src_reg, 1 << 15); - } - else if (REG_IS_B(src_size)) - { - host_arm64_TST_IMM(block, src_reg, 1 << 7); - } - else - fatal("TEST_JS_DEST %02x\n", uop->src_reg_a_real); + if (REG_IS_L(src_size)) { + host_arm64_TST_IMM(block, src_reg, 1 << 31); + } else if (REG_IS_W(src_size)) { + host_arm64_TST_IMM(block, src_reg, 1 << 15); + } else if (REG_IS_B(src_size)) { + host_arm64_TST_IMM(block, src_reg, 1 << 7); + } else + fatal("TEST_JS_DEST %02x\n", uop->src_reg_a_real); - uop->p = host_arm64_BNE_(block); + uop->p = host_arm64_BNE_(block); - return 0; + return 0; } -static int codegen_XOR(codeblock_t *block, uop_t *uop) +static int +codegen_XOR(codeblock_t *block, uop_t *uop) { - int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg_a = HOST_REG_GET(uop->src_reg_a_real), src_reg_b = HOST_REG_GET(uop->src_reg_b_real); - int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size_a = IREG_GET_SIZE(uop->src_reg_a_real), src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); + int dest_reg = HOST_REG_GET(uop->dest_reg_a_real); + int src_reg_a = HOST_REG_GET(uop->src_reg_a_real); + int src_reg_b = HOST_REG_GET(uop->src_reg_b_real); + int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real); + int src_size_a = IREG_GET_SIZE(uop->src_reg_a_real); + int src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); - if (REG_IS_Q(dest_size) && REG_IS_Q(src_size_a) && REG_IS_Q(src_size_b)) - { - host_arm64_EOR_REG_V(block, dest_reg, src_reg_a, src_reg_b); - } - else if (REG_IS_L(dest_size) && REG_IS_L(src_size_a) && REG_IS_L(src_size_b)) - { - host_arm64_EOR_REG(block, dest_reg, src_reg_a, src_reg_b, 0); - } - else if (REG_IS_W(dest_size) && REG_IS_W(src_size_a) && REG_IS_W(src_size_b) && dest_reg == src_reg_a) - { - host_arm64_AND_IMM(block, REG_TEMP, src_reg_b, 0xffff); - host_arm64_EOR_REG(block, dest_reg, src_reg_a, REG_TEMP, 0); - } - else if (REG_IS_B(dest_size) && REG_IS_B(src_size_a) && REG_IS_B(src_size_b) && dest_reg == src_reg_a) - { - host_arm64_AND_IMM(block, REG_TEMP, src_reg_b, 0xff); - host_arm64_EOR_REG(block, dest_reg, src_reg_a, REG_TEMP, 0); - } - else if (REG_IS_B(dest_size) && REG_IS_B(src_size_a) && REG_IS_BH(src_size_b) && dest_reg == src_reg_a) - { - host_arm64_UBFX(block, REG_TEMP, src_reg_b, 8, 8); - host_arm64_EOR_REG(block, dest_reg, src_reg_a, REG_TEMP, 0); - } - else if (REG_IS_BH(dest_size) && REG_IS_BH(src_size_a) && REG_IS_B(src_size_b) && dest_reg == src_reg_a) - { - host_arm64_AND_IMM(block, REG_TEMP, src_reg_b, 0xff); - host_arm64_EOR_REG(block, dest_reg, src_reg_a, REG_TEMP, 8); - } - else if (REG_IS_BH(dest_size) && REG_IS_BH(src_size_a) && REG_IS_BH(src_size_b) && dest_reg == src_reg_a) - { - host_arm64_UBFX(block, REG_TEMP, src_reg_b, 8, 8); - host_arm64_EOR_REG(block, dest_reg, src_reg_a, REG_TEMP, 8); - } - else - fatal("XOR %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real); + if (REG_IS_Q(dest_size) && REG_IS_Q(src_size_a) && REG_IS_Q(src_size_b)) { + host_arm64_EOR_REG_V(block, dest_reg, src_reg_a, src_reg_b); + } else if (REG_IS_L(dest_size) && REG_IS_L(src_size_a) && REG_IS_L(src_size_b)) { + host_arm64_EOR_REG(block, dest_reg, src_reg_a, src_reg_b, 0); + } else if (REG_IS_W(dest_size) && REG_IS_W(src_size_a) && REG_IS_W(src_size_b) && dest_reg == src_reg_a) { + host_arm64_AND_IMM(block, REG_TEMP, src_reg_b, 0xffff); + host_arm64_EOR_REG(block, dest_reg, src_reg_a, REG_TEMP, 0); + } else if (REG_IS_B(dest_size) && REG_IS_B(src_size_a) && REG_IS_B(src_size_b) && dest_reg == src_reg_a) { + host_arm64_AND_IMM(block, REG_TEMP, src_reg_b, 0xff); + host_arm64_EOR_REG(block, dest_reg, src_reg_a, REG_TEMP, 0); + } else if (REG_IS_B(dest_size) && REG_IS_B(src_size_a) && REG_IS_BH(src_size_b) && dest_reg == src_reg_a) { + host_arm64_UBFX(block, REG_TEMP, src_reg_b, 8, 8); + host_arm64_EOR_REG(block, dest_reg, src_reg_a, REG_TEMP, 0); + } else if (REG_IS_BH(dest_size) && REG_IS_BH(src_size_a) && REG_IS_B(src_size_b) && dest_reg == src_reg_a) { + host_arm64_AND_IMM(block, REG_TEMP, src_reg_b, 0xff); + host_arm64_EOR_REG(block, dest_reg, src_reg_a, REG_TEMP, 8); + } else if (REG_IS_BH(dest_size) && REG_IS_BH(src_size_a) && REG_IS_BH(src_size_b) && dest_reg == src_reg_a) { + host_arm64_UBFX(block, REG_TEMP, src_reg_b, 8, 8); + host_arm64_EOR_REG(block, dest_reg, src_reg_a, REG_TEMP, 8); + } else + fatal("XOR %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real); - return 0; + return 0; } -static int codegen_XOR_IMM(codeblock_t *block, uop_t *uop) +static int +codegen_XOR_IMM(codeblock_t *block, uop_t *uop) { - int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg = HOST_REG_GET(uop->src_reg_a_real); - int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size = IREG_GET_SIZE(uop->src_reg_a_real); + int dest_reg = HOST_REG_GET(uop->dest_reg_a_real); + int src_reg = HOST_REG_GET(uop->src_reg_a_real); + int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real); + int src_size = IREG_GET_SIZE(uop->src_reg_a_real); - if (REG_IS_L(dest_size) && REG_IS_L(src_size)) - { - host_arm64_EOR_IMM(block, dest_reg, src_reg, uop->imm_data); - } - else if (REG_IS_W(dest_size) && REG_IS_W(src_size) && dest_reg == src_reg) - { - host_arm64_EOR_IMM(block, dest_reg, src_reg, uop->imm_data); - } - else if (REG_IS_B(dest_size) && REG_IS_B(src_size) && dest_reg == src_reg) - { - host_arm64_EOR_IMM(block, dest_reg, src_reg, uop->imm_data); - } - else if (REG_IS_BH(dest_size) && REG_IS_BH(src_size) && dest_reg == src_reg) - { - host_arm64_EOR_IMM(block, dest_reg, src_reg, uop->imm_data << 8); - } - else - fatal("XOR_IMM %x %x\n", uop->dest_reg_a_real, uop->src_reg_a_real); + if (REG_IS_L(dest_size) && REG_IS_L(src_size)) { + host_arm64_EOR_IMM(block, dest_reg, src_reg, uop->imm_data); + } else if (REG_IS_W(dest_size) && REG_IS_W(src_size) && dest_reg == src_reg) { + host_arm64_EOR_IMM(block, dest_reg, src_reg, uop->imm_data); + } else if (REG_IS_B(dest_size) && REG_IS_B(src_size) && dest_reg == src_reg) { + host_arm64_EOR_IMM(block, dest_reg, src_reg, uop->imm_data); + } else if (REG_IS_BH(dest_size) && REG_IS_BH(src_size) && dest_reg == src_reg) { + host_arm64_EOR_IMM(block, dest_reg, src_reg, uop->imm_data << 8); + } else + fatal("XOR_IMM %x %x\n", uop->dest_reg_a_real, uop->src_reg_a_real); - return 0; + return 0; } -const uOpFn uop_handlers[UOP_MAX] = -{ - [UOP_CALL_FUNC & UOP_MASK] = codegen_CALL_FUNC, - [UOP_CALL_FUNC_RESULT & UOP_MASK] = codegen_CALL_FUNC_RESULT, - [UOP_CALL_INSTRUCTION_FUNC & UOP_MASK] = codegen_CALL_INSTRUCTION_FUNC, +const uOpFn uop_handlers[UOP_MAX] = { + [UOP_CALL_FUNC & UOP_MASK] = codegen_CALL_FUNC, + [UOP_CALL_FUNC_RESULT & + UOP_MASK] + = codegen_CALL_FUNC_RESULT, + [UOP_CALL_INSTRUCTION_FUNC & + UOP_MASK] + = codegen_CALL_INSTRUCTION_FUNC, - [UOP_JMP & UOP_MASK] = codegen_JMP, + [UOP_JMP & + UOP_MASK] + = codegen_JMP, - [UOP_LOAD_SEG & UOP_MASK] = codegen_LOAD_SEG, + [UOP_LOAD_SEG & + UOP_MASK] + = codegen_LOAD_SEG, - [UOP_LOAD_FUNC_ARG_0 & UOP_MASK] = codegen_LOAD_FUNC_ARG0, - [UOP_LOAD_FUNC_ARG_1 & UOP_MASK] = codegen_LOAD_FUNC_ARG1, - [UOP_LOAD_FUNC_ARG_2 & UOP_MASK] = codegen_LOAD_FUNC_ARG2, - [UOP_LOAD_FUNC_ARG_3 & UOP_MASK] = codegen_LOAD_FUNC_ARG3, + [UOP_LOAD_FUNC_ARG_0 & + UOP_MASK] + = codegen_LOAD_FUNC_ARG0, + [UOP_LOAD_FUNC_ARG_1 & + UOP_MASK] + = codegen_LOAD_FUNC_ARG1, + [UOP_LOAD_FUNC_ARG_2 & + UOP_MASK] + = codegen_LOAD_FUNC_ARG2, + [UOP_LOAD_FUNC_ARG_3 & + UOP_MASK] + = codegen_LOAD_FUNC_ARG3, - [UOP_LOAD_FUNC_ARG_0_IMM & UOP_MASK] = codegen_LOAD_FUNC_ARG0_IMM, - [UOP_LOAD_FUNC_ARG_1_IMM & UOP_MASK] = codegen_LOAD_FUNC_ARG1_IMM, - [UOP_LOAD_FUNC_ARG_2_IMM & UOP_MASK] = codegen_LOAD_FUNC_ARG2_IMM, - [UOP_LOAD_FUNC_ARG_3_IMM & UOP_MASK] = codegen_LOAD_FUNC_ARG3_IMM, + [UOP_LOAD_FUNC_ARG_0_IMM & + UOP_MASK] + = codegen_LOAD_FUNC_ARG0_IMM, + [UOP_LOAD_FUNC_ARG_1_IMM & + UOP_MASK] + = codegen_LOAD_FUNC_ARG1_IMM, + [UOP_LOAD_FUNC_ARG_2_IMM & + UOP_MASK] + = codegen_LOAD_FUNC_ARG2_IMM, + [UOP_LOAD_FUNC_ARG_3_IMM & + UOP_MASK] + = codegen_LOAD_FUNC_ARG3_IMM, - [UOP_STORE_P_IMM & UOP_MASK] = codegen_STORE_PTR_IMM, - [UOP_STORE_P_IMM_8 & UOP_MASK] = codegen_STORE_PTR_IMM_8, + [UOP_STORE_P_IMM & + UOP_MASK] + = codegen_STORE_PTR_IMM, + [UOP_STORE_P_IMM_8 & + UOP_MASK] + = codegen_STORE_PTR_IMM_8, - [UOP_MEM_LOAD_ABS & UOP_MASK] = codegen_MEM_LOAD_ABS, - [UOP_MEM_LOAD_REG & UOP_MASK] = codegen_MEM_LOAD_REG, - [UOP_MEM_LOAD_SINGLE & UOP_MASK] = codegen_MEM_LOAD_SINGLE, - [UOP_MEM_LOAD_DOUBLE & UOP_MASK] = codegen_MEM_LOAD_DOUBLE, + [UOP_MEM_LOAD_ABS & + UOP_MASK] + = codegen_MEM_LOAD_ABS, + [UOP_MEM_LOAD_REG & + UOP_MASK] + = codegen_MEM_LOAD_REG, + [UOP_MEM_LOAD_SINGLE & + UOP_MASK] + = codegen_MEM_LOAD_SINGLE, + [UOP_MEM_LOAD_DOUBLE & + UOP_MASK] + = codegen_MEM_LOAD_DOUBLE, - [UOP_MEM_STORE_ABS & UOP_MASK] = codegen_MEM_STORE_ABS, - [UOP_MEM_STORE_REG & UOP_MASK] = codegen_MEM_STORE_REG, - [UOP_MEM_STORE_IMM_8 & UOP_MASK] = codegen_MEM_STORE_IMM_8, - [UOP_MEM_STORE_IMM_16 & UOP_MASK] = codegen_MEM_STORE_IMM_16, - [UOP_MEM_STORE_IMM_32 & UOP_MASK] = codegen_MEM_STORE_IMM_32, - [UOP_MEM_STORE_SINGLE & UOP_MASK] = codegen_MEM_STORE_SINGLE, - [UOP_MEM_STORE_DOUBLE & UOP_MASK] = codegen_MEM_STORE_DOUBLE, + [UOP_MEM_STORE_ABS & + UOP_MASK] + = codegen_MEM_STORE_ABS, + [UOP_MEM_STORE_REG & + UOP_MASK] + = codegen_MEM_STORE_REG, + [UOP_MEM_STORE_IMM_8 & + UOP_MASK] + = codegen_MEM_STORE_IMM_8, + [UOP_MEM_STORE_IMM_16 & + UOP_MASK] + = codegen_MEM_STORE_IMM_16, + [UOP_MEM_STORE_IMM_32 & + UOP_MASK] + = codegen_MEM_STORE_IMM_32, + [UOP_MEM_STORE_SINGLE & + UOP_MASK] + = codegen_MEM_STORE_SINGLE, + [UOP_MEM_STORE_DOUBLE & + UOP_MASK] + = codegen_MEM_STORE_DOUBLE, - [UOP_MOV & UOP_MASK] = codegen_MOV, - [UOP_MOV_PTR & UOP_MASK] = codegen_MOV_PTR, - [UOP_MOV_IMM & UOP_MASK] = codegen_MOV_IMM, - [UOP_MOVSX & UOP_MASK] = codegen_MOVSX, - [UOP_MOVZX & UOP_MASK] = codegen_MOVZX, - [UOP_MOV_DOUBLE_INT & UOP_MASK] = codegen_MOV_DOUBLE_INT, - [UOP_MOV_INT_DOUBLE & UOP_MASK] = codegen_MOV_INT_DOUBLE, - [UOP_MOV_INT_DOUBLE_64 & UOP_MASK] = codegen_MOV_INT_DOUBLE_64, - [UOP_MOV_REG_PTR & UOP_MASK] = codegen_MOV_REG_PTR, - [UOP_MOVZX_REG_PTR_8 & UOP_MASK] = codegen_MOVZX_REG_PTR_8, - [UOP_MOVZX_REG_PTR_16 & UOP_MASK] = codegen_MOVZX_REG_PTR_16, + [UOP_MOV & + UOP_MASK] + = codegen_MOV, + [UOP_MOV_PTR & + UOP_MASK] + = codegen_MOV_PTR, + [UOP_MOV_IMM & + UOP_MASK] + = codegen_MOV_IMM, + [UOP_MOVSX & + UOP_MASK] + = codegen_MOVSX, + [UOP_MOVZX & + UOP_MASK] + = codegen_MOVZX, + [UOP_MOV_DOUBLE_INT & + UOP_MASK] + = codegen_MOV_DOUBLE_INT, + [UOP_MOV_INT_DOUBLE & + UOP_MASK] + = codegen_MOV_INT_DOUBLE, + [UOP_MOV_INT_DOUBLE_64 & + UOP_MASK] + = codegen_MOV_INT_DOUBLE_64, + [UOP_MOV_REG_PTR & + UOP_MASK] + = codegen_MOV_REG_PTR, + [UOP_MOVZX_REG_PTR_8 & + UOP_MASK] + = codegen_MOVZX_REG_PTR_8, + [UOP_MOVZX_REG_PTR_16 & + UOP_MASK] + = codegen_MOVZX_REG_PTR_16, - [UOP_ADD & UOP_MASK] = codegen_ADD, - [UOP_ADD_IMM & UOP_MASK] = codegen_ADD_IMM, - [UOP_ADD_LSHIFT & UOP_MASK] = codegen_ADD_LSHIFT, - [UOP_AND & UOP_MASK] = codegen_AND, - [UOP_AND_IMM & UOP_MASK] = codegen_AND_IMM, - [UOP_ANDN & UOP_MASK] = codegen_ANDN, - [UOP_OR & UOP_MASK] = codegen_OR, - [UOP_OR_IMM & UOP_MASK] = codegen_OR_IMM, - [UOP_SUB & UOP_MASK] = codegen_SUB, - [UOP_SUB_IMM & UOP_MASK] = codegen_SUB_IMM, - [UOP_XOR & UOP_MASK] = codegen_XOR, - [UOP_XOR_IMM & UOP_MASK] = codegen_XOR_IMM, + [UOP_ADD & + UOP_MASK] + = codegen_ADD, + [UOP_ADD_IMM & + UOP_MASK] + = codegen_ADD_IMM, + [UOP_ADD_LSHIFT & + UOP_MASK] + = codegen_ADD_LSHIFT, + [UOP_AND & + UOP_MASK] + = codegen_AND, + [UOP_AND_IMM & + UOP_MASK] + = codegen_AND_IMM, + [UOP_ANDN & + UOP_MASK] + = codegen_ANDN, + [UOP_OR & + UOP_MASK] + = codegen_OR, + [UOP_OR_IMM & + UOP_MASK] + = codegen_OR_IMM, + [UOP_SUB & + UOP_MASK] + = codegen_SUB, + [UOP_SUB_IMM & + UOP_MASK] + = codegen_SUB_IMM, + [UOP_XOR & + UOP_MASK] + = codegen_XOR, + [UOP_XOR_IMM & + UOP_MASK] + = codegen_XOR_IMM, - [UOP_SAR & UOP_MASK] = codegen_SAR, - [UOP_SAR_IMM & UOP_MASK] = codegen_SAR_IMM, - [UOP_SHL & UOP_MASK] = codegen_SHL, - [UOP_SHL_IMM & UOP_MASK] = codegen_SHL_IMM, - [UOP_SHR & UOP_MASK] = codegen_SHR, - [UOP_SHR_IMM & UOP_MASK] = codegen_SHR_IMM, - [UOP_ROL & UOP_MASK] = codegen_ROL, - [UOP_ROL_IMM & UOP_MASK] = codegen_ROL_IMM, - [UOP_ROR & UOP_MASK] = codegen_ROR, - [UOP_ROR_IMM & UOP_MASK] = codegen_ROR_IMM, + [UOP_SAR & + UOP_MASK] + = codegen_SAR, + [UOP_SAR_IMM & + UOP_MASK] + = codegen_SAR_IMM, + [UOP_SHL & + UOP_MASK] + = codegen_SHL, + [UOP_SHL_IMM & + UOP_MASK] + = codegen_SHL_IMM, + [UOP_SHR & + UOP_MASK] + = codegen_SHR, + [UOP_SHR_IMM & + UOP_MASK] + = codegen_SHR_IMM, + [UOP_ROL & + UOP_MASK] + = codegen_ROL, + [UOP_ROL_IMM & + UOP_MASK] + = codegen_ROL_IMM, + [UOP_ROR & + UOP_MASK] + = codegen_ROR, + [UOP_ROR_IMM & + UOP_MASK] + = codegen_ROR_IMM, - [UOP_CMP_IMM_JZ & UOP_MASK] = codegen_CMP_IMM_JZ, + [UOP_CMP_IMM_JZ & + UOP_MASK] + = codegen_CMP_IMM_JZ, - [UOP_CMP_JB & UOP_MASK] = codegen_CMP_JB, - [UOP_CMP_JNBE & UOP_MASK] = codegen_CMP_JNBE, + [UOP_CMP_JB & + UOP_MASK] + = codegen_CMP_JB, + [UOP_CMP_JNBE & + UOP_MASK] + = codegen_CMP_JNBE, - [UOP_CMP_JNB_DEST & UOP_MASK] = codegen_CMP_JNB_DEST, - [UOP_CMP_JNBE_DEST & UOP_MASK] = codegen_CMP_JNBE_DEST, - [UOP_CMP_JNL_DEST & UOP_MASK] = codegen_CMP_JNL_DEST, - [UOP_CMP_JNLE_DEST & UOP_MASK] = codegen_CMP_JNLE_DEST, - [UOP_CMP_JNO_DEST & UOP_MASK] = codegen_CMP_JNO_DEST, - [UOP_CMP_JNZ_DEST & UOP_MASK] = codegen_CMP_JNZ_DEST, - [UOP_CMP_JB_DEST & UOP_MASK] = codegen_CMP_JB_DEST, - [UOP_CMP_JBE_DEST & UOP_MASK] = codegen_CMP_JBE_DEST, - [UOP_CMP_JL_DEST & UOP_MASK] = codegen_CMP_JL_DEST, - [UOP_CMP_JLE_DEST & UOP_MASK] = codegen_CMP_JLE_DEST, - [UOP_CMP_JO_DEST & UOP_MASK] = codegen_CMP_JO_DEST, - [UOP_CMP_JZ_DEST & UOP_MASK] = codegen_CMP_JZ_DEST, + [UOP_CMP_JNB_DEST & + UOP_MASK] + = codegen_CMP_JNB_DEST, + [UOP_CMP_JNBE_DEST & + UOP_MASK] + = codegen_CMP_JNBE_DEST, + [UOP_CMP_JNL_DEST & + UOP_MASK] + = codegen_CMP_JNL_DEST, + [UOP_CMP_JNLE_DEST & + UOP_MASK] + = codegen_CMP_JNLE_DEST, + [UOP_CMP_JNO_DEST & + UOP_MASK] + = codegen_CMP_JNO_DEST, + [UOP_CMP_JNZ_DEST & + UOP_MASK] + = codegen_CMP_JNZ_DEST, + [UOP_CMP_JB_DEST & + UOP_MASK] + = codegen_CMP_JB_DEST, + [UOP_CMP_JBE_DEST & + UOP_MASK] + = codegen_CMP_JBE_DEST, + [UOP_CMP_JL_DEST & + UOP_MASK] + = codegen_CMP_JL_DEST, + [UOP_CMP_JLE_DEST & + UOP_MASK] + = codegen_CMP_JLE_DEST, + [UOP_CMP_JO_DEST & + UOP_MASK] + = codegen_CMP_JO_DEST, + [UOP_CMP_JZ_DEST & + UOP_MASK] + = codegen_CMP_JZ_DEST, - [UOP_CMP_IMM_JNZ_DEST & UOP_MASK] = codegen_CMP_IMM_JNZ_DEST, - [UOP_CMP_IMM_JZ_DEST & UOP_MASK] = codegen_CMP_IMM_JZ_DEST, + [UOP_CMP_IMM_JNZ_DEST & + UOP_MASK] + = codegen_CMP_IMM_JNZ_DEST, + [UOP_CMP_IMM_JZ_DEST & + UOP_MASK] + = codegen_CMP_IMM_JZ_DEST, - [UOP_TEST_JNS_DEST & UOP_MASK] = codegen_TEST_JNS_DEST, - [UOP_TEST_JS_DEST & UOP_MASK] = codegen_TEST_JS_DEST, + [UOP_TEST_JNS_DEST & + UOP_MASK] + = codegen_TEST_JNS_DEST, + [UOP_TEST_JS_DEST & + UOP_MASK] + = codegen_TEST_JS_DEST, - [UOP_FP_ENTER & UOP_MASK] = codegen_FP_ENTER, - [UOP_MMX_ENTER & UOP_MASK] = codegen_MMX_ENTER, + [UOP_FP_ENTER & + UOP_MASK] + = codegen_FP_ENTER, + [UOP_MMX_ENTER & + UOP_MASK] + = codegen_MMX_ENTER, - [UOP_FADD & UOP_MASK] = codegen_FADD, - [UOP_FCOM & UOP_MASK] = codegen_FCOM, - [UOP_FDIV & UOP_MASK] = codegen_FDIV, - [UOP_FMUL & UOP_MASK] = codegen_FMUL, - [UOP_FSUB & UOP_MASK] = codegen_FSUB, + [UOP_FADD & + UOP_MASK] + = codegen_FADD, + [UOP_FCOM & + UOP_MASK] + = codegen_FCOM, + [UOP_FDIV & + UOP_MASK] + = codegen_FDIV, + [UOP_FMUL & + UOP_MASK] + = codegen_FMUL, + [UOP_FSUB & + UOP_MASK] + = codegen_FSUB, - [UOP_FABS & UOP_MASK] = codegen_FABS, - [UOP_FCHS & UOP_MASK] = codegen_FCHS, - [UOP_FSQRT & UOP_MASK] = codegen_FSQRT, - [UOP_FTST & UOP_MASK] = codegen_FTST, + [UOP_FABS & + UOP_MASK] + = codegen_FABS, + [UOP_FCHS & + UOP_MASK] + = codegen_FCHS, + [UOP_FSQRT & + UOP_MASK] + = codegen_FSQRT, + [UOP_FTST & + UOP_MASK] + = codegen_FTST, - [UOP_PACKSSWB & UOP_MASK] = codegen_PACKSSWB, - [UOP_PACKSSDW & UOP_MASK] = codegen_PACKSSDW, - [UOP_PACKUSWB & UOP_MASK] = codegen_PACKUSWB, + [UOP_PACKSSWB & + UOP_MASK] + = codegen_PACKSSWB, + [UOP_PACKSSDW & + UOP_MASK] + = codegen_PACKSSDW, + [UOP_PACKUSWB & + UOP_MASK] + = codegen_PACKUSWB, - [UOP_PADDB & UOP_MASK] = codegen_PADDB, - [UOP_PADDW & UOP_MASK] = codegen_PADDW, - [UOP_PADDD & UOP_MASK] = codegen_PADDD, - [UOP_PADDSB & UOP_MASK] = codegen_PADDSB, - [UOP_PADDSW & UOP_MASK] = codegen_PADDSW, - [UOP_PADDUSB & UOP_MASK] = codegen_PADDUSB, - [UOP_PADDUSW & UOP_MASK] = codegen_PADDUSW, + [UOP_PADDB & + UOP_MASK] + = codegen_PADDB, + [UOP_PADDW & + UOP_MASK] + = codegen_PADDW, + [UOP_PADDD & + UOP_MASK] + = codegen_PADDD, + [UOP_PADDSB & + UOP_MASK] + = codegen_PADDSB, + [UOP_PADDSW & + UOP_MASK] + = codegen_PADDSW, + [UOP_PADDUSB & + UOP_MASK] + = codegen_PADDUSB, + [UOP_PADDUSW & + UOP_MASK] + = codegen_PADDUSW, - [UOP_PCMPEQB & UOP_MASK] = codegen_PCMPEQB, - [UOP_PCMPEQW & UOP_MASK] = codegen_PCMPEQW, - [UOP_PCMPEQD & UOP_MASK] = codegen_PCMPEQD, - [UOP_PCMPGTB & UOP_MASK] = codegen_PCMPGTB, - [UOP_PCMPGTW & UOP_MASK] = codegen_PCMPGTW, - [UOP_PCMPGTD & UOP_MASK] = codegen_PCMPGTD, + [UOP_PCMPEQB & + UOP_MASK] + = codegen_PCMPEQB, + [UOP_PCMPEQW & + UOP_MASK] + = codegen_PCMPEQW, + [UOP_PCMPEQD & + UOP_MASK] + = codegen_PCMPEQD, + [UOP_PCMPGTB & + UOP_MASK] + = codegen_PCMPGTB, + [UOP_PCMPGTW & + UOP_MASK] + = codegen_PCMPGTW, + [UOP_PCMPGTD & + UOP_MASK] + = codegen_PCMPGTD, - [UOP_PF2ID & UOP_MASK] = codegen_PF2ID, - [UOP_PFADD & UOP_MASK] = codegen_PFADD, - [UOP_PFCMPEQ & UOP_MASK] = codegen_PFCMPEQ, - [UOP_PFCMPGE & UOP_MASK] = codegen_PFCMPGE, - [UOP_PFCMPGT & UOP_MASK] = codegen_PFCMPGT, - [UOP_PFMAX & UOP_MASK] = codegen_PFMAX, - [UOP_PFMIN & UOP_MASK] = codegen_PFMIN, - [UOP_PFMUL & UOP_MASK] = codegen_PFMUL, - [UOP_PFRCP & UOP_MASK] = codegen_PFRCP, - [UOP_PFRSQRT & UOP_MASK] = codegen_PFRSQRT, - [UOP_PFSUB & UOP_MASK] = codegen_PFSUB, - [UOP_PI2FD & UOP_MASK] = codegen_PI2FD, + [UOP_PF2ID & + UOP_MASK] + = codegen_PF2ID, + [UOP_PFADD & + UOP_MASK] + = codegen_PFADD, + [UOP_PFCMPEQ & + UOP_MASK] + = codegen_PFCMPEQ, + [UOP_PFCMPGE & + UOP_MASK] + = codegen_PFCMPGE, + [UOP_PFCMPGT & + UOP_MASK] + = codegen_PFCMPGT, + [UOP_PFMAX & + UOP_MASK] + = codegen_PFMAX, + [UOP_PFMIN & + UOP_MASK] + = codegen_PFMIN, + [UOP_PFMUL & + UOP_MASK] + = codegen_PFMUL, + [UOP_PFRCP & + UOP_MASK] + = codegen_PFRCP, + [UOP_PFRSQRT & + UOP_MASK] + = codegen_PFRSQRT, + [UOP_PFSUB & + UOP_MASK] + = codegen_PFSUB, + [UOP_PI2FD & + UOP_MASK] + = codegen_PI2FD, - [UOP_PMADDWD & UOP_MASK] = codegen_PMADDWD, - [UOP_PMULHW & UOP_MASK] = codegen_PMULHW, - [UOP_PMULLW & UOP_MASK] = codegen_PMULLW, + [UOP_PMADDWD & + UOP_MASK] + = codegen_PMADDWD, + [UOP_PMULHW & + UOP_MASK] + = codegen_PMULHW, + [UOP_PMULLW & + UOP_MASK] + = codegen_PMULLW, - [UOP_PSLLW_IMM & UOP_MASK] = codegen_PSLLW_IMM, - [UOP_PSLLD_IMM & UOP_MASK] = codegen_PSLLD_IMM, - [UOP_PSLLQ_IMM & UOP_MASK] = codegen_PSLLQ_IMM, - [UOP_PSRAW_IMM & UOP_MASK] = codegen_PSRAW_IMM, - [UOP_PSRAD_IMM & UOP_MASK] = codegen_PSRAD_IMM, - [UOP_PSRAQ_IMM & UOP_MASK] = codegen_PSRAQ_IMM, - [UOP_PSRLW_IMM & UOP_MASK] = codegen_PSRLW_IMM, - [UOP_PSRLD_IMM & UOP_MASK] = codegen_PSRLD_IMM, - [UOP_PSRLQ_IMM & UOP_MASK] = codegen_PSRLQ_IMM, + [UOP_PSLLW_IMM & + UOP_MASK] + = codegen_PSLLW_IMM, + [UOP_PSLLD_IMM & + UOP_MASK] + = codegen_PSLLD_IMM, + [UOP_PSLLQ_IMM & + UOP_MASK] + = codegen_PSLLQ_IMM, + [UOP_PSRAW_IMM & + UOP_MASK] + = codegen_PSRAW_IMM, + [UOP_PSRAD_IMM & + UOP_MASK] + = codegen_PSRAD_IMM, + [UOP_PSRAQ_IMM & + UOP_MASK] + = codegen_PSRAQ_IMM, + [UOP_PSRLW_IMM & + UOP_MASK] + = codegen_PSRLW_IMM, + [UOP_PSRLD_IMM & + UOP_MASK] + = codegen_PSRLD_IMM, + [UOP_PSRLQ_IMM & + UOP_MASK] + = codegen_PSRLQ_IMM, - [UOP_PSUBB & UOP_MASK] = codegen_PSUBB, - [UOP_PSUBW & UOP_MASK] = codegen_PSUBW, - [UOP_PSUBD & UOP_MASK] = codegen_PSUBD, - [UOP_PSUBSB & UOP_MASK] = codegen_PSUBSB, - [UOP_PSUBSW & UOP_MASK] = codegen_PSUBSW, - [UOP_PSUBUSB & UOP_MASK] = codegen_PSUBUSB, - [UOP_PSUBUSW & UOP_MASK] = codegen_PSUBUSW, + [UOP_PSUBB & + UOP_MASK] + = codegen_PSUBB, + [UOP_PSUBW & + UOP_MASK] + = codegen_PSUBW, + [UOP_PSUBD & + UOP_MASK] + = codegen_PSUBD, + [UOP_PSUBSB & + UOP_MASK] + = codegen_PSUBSB, + [UOP_PSUBSW & + UOP_MASK] + = codegen_PSUBSW, + [UOP_PSUBUSB & + UOP_MASK] + = codegen_PSUBUSB, + [UOP_PSUBUSW & + UOP_MASK] + = codegen_PSUBUSW, - [UOP_PUNPCKHBW & UOP_MASK] = codegen_PUNPCKHBW, - [UOP_PUNPCKHWD & UOP_MASK] = codegen_PUNPCKHWD, - [UOP_PUNPCKHDQ & UOP_MASK] = codegen_PUNPCKHDQ, - [UOP_PUNPCKLBW & UOP_MASK] = codegen_PUNPCKLBW, - [UOP_PUNPCKLWD & UOP_MASK] = codegen_PUNPCKLWD, - [UOP_PUNPCKLDQ & UOP_MASK] = codegen_PUNPCKLDQ, + [UOP_PUNPCKHBW & + UOP_MASK] + = codegen_PUNPCKHBW, + [UOP_PUNPCKHWD & + UOP_MASK] + = codegen_PUNPCKHWD, + [UOP_PUNPCKHDQ & + UOP_MASK] + = codegen_PUNPCKHDQ, + [UOP_PUNPCKLBW & + UOP_MASK] + = codegen_PUNPCKLBW, + [UOP_PUNPCKLWD & + UOP_MASK] + = codegen_PUNPCKLWD, + [UOP_PUNPCKLDQ & + UOP_MASK] + = codegen_PUNPCKLDQ, - [UOP_NOP_BARRIER & UOP_MASK] = codegen_NOP + [UOP_NOP_BARRIER & + UOP_MASK] + = codegen_NOP }; -void codegen_direct_read_8(codeblock_t *block, int host_reg, void *p) +void +codegen_direct_read_8(codeblock_t *block, int host_reg, void *p) { - if (in_range12_b((uintptr_t)p - (uintptr_t)&cpu_state)) - host_arm64_LDRB_IMM_W(block, host_reg, REG_CPUSTATE, (uintptr_t)p - (uintptr_t)&cpu_state); - else - fatal("codegen_direct_read_8 - not in range\n"); + if (in_range12_b((uintptr_t) p - (uintptr_t) &cpu_state)) + host_arm64_LDRB_IMM_W(block, host_reg, REG_CPUSTATE, (uintptr_t) p - (uintptr_t) &cpu_state); + else + fatal("codegen_direct_read_8 - not in range\n"); } -void codegen_direct_read_16(codeblock_t *block, int host_reg, void *p) +void +codegen_direct_read_16(codeblock_t *block, int host_reg, void *p) { - if (in_range12_h((uintptr_t)p - (uintptr_t)&cpu_state)) - host_arm64_LDRH_IMM(block, host_reg, REG_CPUSTATE, (uintptr_t)p - (uintptr_t)&cpu_state); - else - fatal("codegen_direct_read_16 - not in range\n"); + if (in_range12_h((uintptr_t) p - (uintptr_t) &cpu_state)) + host_arm64_LDRH_IMM(block, host_reg, REG_CPUSTATE, (uintptr_t) p - (uintptr_t) &cpu_state); + else + fatal("codegen_direct_read_16 - not in range\n"); } -void codegen_direct_read_32(codeblock_t *block, int host_reg, void *p) +void +codegen_direct_read_32(codeblock_t *block, int host_reg, void *p) { - if (in_range12_w((uintptr_t)p - (uintptr_t)&cpu_state)) - host_arm64_LDR_IMM_W(block, host_reg, REG_CPUSTATE, (uintptr_t)p - (uintptr_t)&cpu_state); - else - fatal("codegen_direct_read_32 - not in range\n"); + if (in_range12_w((uintptr_t) p - (uintptr_t) &cpu_state)) + host_arm64_LDR_IMM_W(block, host_reg, REG_CPUSTATE, (uintptr_t) p - (uintptr_t) &cpu_state); + else + fatal("codegen_direct_read_32 - not in range\n"); } -void codegen_direct_read_64(codeblock_t *block, int host_reg, void *p) +void +codegen_direct_read_64(codeblock_t *block, int host_reg, void *p) { - if (in_range12_q((uintptr_t)p - (uintptr_t)&cpu_state)) - host_arm64_LDR_IMM_F64(block, host_reg, REG_CPUSTATE, (uintptr_t)p - (uintptr_t)&cpu_state); - else - fatal("codegen_direct_read_double - not in range\n"); + if (in_range12_q((uintptr_t) p - (uintptr_t) &cpu_state)) + host_arm64_LDR_IMM_F64(block, host_reg, REG_CPUSTATE, (uintptr_t) p - (uintptr_t) &cpu_state); + else + fatal("codegen_direct_read_double - not in range\n"); } -void codegen_direct_read_pointer(codeblock_t *block, int host_reg, void *p) +void +codegen_direct_read_pointer(codeblock_t *block, int host_reg, void *p) { - if (in_range12_q((uintptr_t)p - (uintptr_t)&cpu_state)) - host_arm64_LDR_IMM_X(block, host_reg, REG_CPUSTATE, (uintptr_t)p - (uintptr_t)&cpu_state); - else - fatal("codegen_direct_read_pointer - not in range\n"); + if (in_range12_q((uintptr_t) p - (uintptr_t) &cpu_state)) + host_arm64_LDR_IMM_X(block, host_reg, REG_CPUSTATE, (uintptr_t) p - (uintptr_t) &cpu_state); + else + fatal("codegen_direct_read_pointer - not in range\n"); } -void codegen_direct_read_double(codeblock_t *block, int host_reg, void *p) +void +codegen_direct_read_double(codeblock_t *block, int host_reg, void *p) { - if (in_range12_q((uintptr_t)p - (uintptr_t)&cpu_state)) - host_arm64_LDR_IMM_F64(block, host_reg, REG_CPUSTATE, (uintptr_t)p - (uintptr_t)&cpu_state); - else - fatal("codegen_direct_read_double - not in range\n"); + if (in_range12_q((uintptr_t) p - (uintptr_t) &cpu_state)) + host_arm64_LDR_IMM_F64(block, host_reg, REG_CPUSTATE, (uintptr_t) p - (uintptr_t) &cpu_state); + else + fatal("codegen_direct_read_double - not in range\n"); } -void codegen_direct_read_st_8(codeblock_t *block, int host_reg, void *base, int reg_idx) +void +codegen_direct_read_st_8(codeblock_t *block, int host_reg, void *base, int reg_idx) { - host_arm64_LDR_IMM_W(block, REG_TEMP, REG_XSP, IREG_TOP_diff_stack_offset); - host_arm64_ADD_IMM(block, REG_TEMP, REG_TEMP, reg_idx); - host_arm64_ADDX_IMM(block, REG_TEMP2, REG_CPUSTATE, (uintptr_t)base - (uintptr_t)&cpu_state); - host_arm64_AND_IMM(block, REG_TEMP, REG_TEMP, 7); - host_arm64_LDRB_REG(block, host_reg, REG_TEMP2, REG_TEMP); + host_arm64_LDR_IMM_W(block, REG_TEMP, REG_XSP, IREG_TOP_diff_stack_offset); + host_arm64_ADD_IMM(block, REG_TEMP, REG_TEMP, reg_idx); + host_arm64_ADDX_IMM(block, REG_TEMP2, REG_CPUSTATE, (uintptr_t) base - (uintptr_t) &cpu_state); + host_arm64_AND_IMM(block, REG_TEMP, REG_TEMP, 7); + host_arm64_LDRB_REG(block, host_reg, REG_TEMP2, REG_TEMP); } -void codegen_direct_read_st_64(codeblock_t *block, int host_reg, void *base, int reg_idx) +void +codegen_direct_read_st_64(codeblock_t *block, int host_reg, void *base, int reg_idx) { - host_arm64_LDR_IMM_W(block, REG_TEMP, REG_XSP, IREG_TOP_diff_stack_offset); - host_arm64_ADD_IMM(block, REG_TEMP, REG_TEMP, reg_idx); - host_arm64_ADDX_IMM(block, REG_TEMP2, REG_CPUSTATE, (uintptr_t)base - (uintptr_t)&cpu_state); - host_arm64_AND_IMM(block, REG_TEMP, REG_TEMP, 7); - host_arm64_LDR_REG_F64_S(block, host_reg, REG_TEMP2, REG_TEMP); + host_arm64_LDR_IMM_W(block, REG_TEMP, REG_XSP, IREG_TOP_diff_stack_offset); + host_arm64_ADD_IMM(block, REG_TEMP, REG_TEMP, reg_idx); + host_arm64_ADDX_IMM(block, REG_TEMP2, REG_CPUSTATE, (uintptr_t) base - (uintptr_t) &cpu_state); + host_arm64_AND_IMM(block, REG_TEMP, REG_TEMP, 7); + host_arm64_LDR_REG_F64_S(block, host_reg, REG_TEMP2, REG_TEMP); } -void codegen_direct_read_st_double(codeblock_t *block, int host_reg, void *base, int reg_idx) +void +codegen_direct_read_st_double(codeblock_t *block, int host_reg, void *base, int reg_idx) { - host_arm64_LDR_IMM_W(block, REG_TEMP, REG_XSP, IREG_TOP_diff_stack_offset); - host_arm64_ADD_IMM(block, REG_TEMP, REG_TEMP, reg_idx); - host_arm64_ADDX_IMM(block, REG_TEMP2, REG_CPUSTATE, (uintptr_t)base - (uintptr_t)&cpu_state); - host_arm64_AND_IMM(block, REG_TEMP, REG_TEMP, 7); - host_arm64_LDR_REG_F64_S(block, host_reg, REG_TEMP2, REG_TEMP); + host_arm64_LDR_IMM_W(block, REG_TEMP, REG_XSP, IREG_TOP_diff_stack_offset); + host_arm64_ADD_IMM(block, REG_TEMP, REG_TEMP, reg_idx); + host_arm64_ADDX_IMM(block, REG_TEMP2, REG_CPUSTATE, (uintptr_t) base - (uintptr_t) &cpu_state); + host_arm64_AND_IMM(block, REG_TEMP, REG_TEMP, 7); + host_arm64_LDR_REG_F64_S(block, host_reg, REG_TEMP2, REG_TEMP); } -void codegen_direct_write_8(codeblock_t *block, void *p, int host_reg) +void +codegen_direct_write_8(codeblock_t *block, void *p, int host_reg) { - if (in_range12_b((uintptr_t)p - (uintptr_t)&cpu_state)) - host_arm64_STRB_IMM(block, host_reg, REG_CPUSTATE, (uintptr_t)p - (uintptr_t)&cpu_state); - else - fatal("codegen_direct_write_8 - not in range\n"); + if (in_range12_b((uintptr_t) p - (uintptr_t) &cpu_state)) + host_arm64_STRB_IMM(block, host_reg, REG_CPUSTATE, (uintptr_t) p - (uintptr_t) &cpu_state); + else + fatal("codegen_direct_write_8 - not in range\n"); } -void codegen_direct_write_16(codeblock_t *block, void *p, int host_reg) +void +codegen_direct_write_16(codeblock_t *block, void *p, int host_reg) { - if (in_range12_h((uintptr_t)p - (uintptr_t)&cpu_state)) - host_arm64_STRH_IMM(block, host_reg, REG_CPUSTATE, (uintptr_t)p - (uintptr_t)&cpu_state); - else - fatal("codegen_direct_write_16 - not in range\n"); + if (in_range12_h((uintptr_t) p - (uintptr_t) &cpu_state)) + host_arm64_STRH_IMM(block, host_reg, REG_CPUSTATE, (uintptr_t) p - (uintptr_t) &cpu_state); + else + fatal("codegen_direct_write_16 - not in range\n"); } -void codegen_direct_write_32(codeblock_t *block, void *p, int host_reg) +void +codegen_direct_write_32(codeblock_t *block, void *p, int host_reg) { - if (in_range12_w((uintptr_t)p - (uintptr_t)&cpu_state)) - host_arm64_STR_IMM_W(block, host_reg, REG_CPUSTATE, (uintptr_t)p - (uintptr_t)&cpu_state); - else - fatal("codegen_direct_write_32 - not in range\n"); + if (in_range12_w((uintptr_t) p - (uintptr_t) &cpu_state)) + host_arm64_STR_IMM_W(block, host_reg, REG_CPUSTATE, (uintptr_t) p - (uintptr_t) &cpu_state); + else + fatal("codegen_direct_write_32 - not in range\n"); } -void codegen_direct_write_64(codeblock_t *block, void *p, int host_reg) +void +codegen_direct_write_64(codeblock_t *block, void *p, int host_reg) { - if (in_range12_q((uintptr_t)p - (uintptr_t)&cpu_state)) - host_arm64_STR_IMM_F64(block, host_reg, REG_CPUSTATE, (uintptr_t)p - (uintptr_t)&cpu_state); - else - fatal("codegen_direct_write_double - not in range\n"); + if (in_range12_q((uintptr_t) p - (uintptr_t) &cpu_state)) + host_arm64_STR_IMM_F64(block, host_reg, REG_CPUSTATE, (uintptr_t) p - (uintptr_t) &cpu_state); + else + fatal("codegen_direct_write_double - not in range\n"); } -void codegen_direct_write_double(codeblock_t *block, void *p, int host_reg) +void +codegen_direct_write_double(codeblock_t *block, void *p, int host_reg) { - if (in_range12_q((uintptr_t)p - (uintptr_t)&cpu_state)) - host_arm64_STR_IMM_F64(block, host_reg, REG_CPUSTATE, (uintptr_t)p - (uintptr_t)&cpu_state); - else - fatal("codegen_direct_write_double - not in range\n"); + if (in_range12_q((uintptr_t) p - (uintptr_t) &cpu_state)) + host_arm64_STR_IMM_F64(block, host_reg, REG_CPUSTATE, (uintptr_t) p - (uintptr_t) &cpu_state); + else + fatal("codegen_direct_write_double - not in range\n"); } -void codegen_direct_write_st_8(codeblock_t *block, void *base, int reg_idx, int host_reg) +void +codegen_direct_write_st_8(codeblock_t *block, void *base, int reg_idx, int host_reg) { - host_arm64_LDR_IMM_W(block, REG_TEMP, REG_XSP, IREG_TOP_diff_stack_offset); - host_arm64_ADD_IMM(block, REG_TEMP, REG_TEMP, reg_idx); - host_arm64_ADDX_IMM(block, REG_TEMP2, REG_CPUSTATE, (uintptr_t)base - (uintptr_t)&cpu_state); - host_arm64_AND_IMM(block, REG_TEMP, REG_TEMP, 7); - host_arm64_STRB_REG(block, host_reg, REG_TEMP2, REG_TEMP); + host_arm64_LDR_IMM_W(block, REG_TEMP, REG_XSP, IREG_TOP_diff_stack_offset); + host_arm64_ADD_IMM(block, REG_TEMP, REG_TEMP, reg_idx); + host_arm64_ADDX_IMM(block, REG_TEMP2, REG_CPUSTATE, (uintptr_t) base - (uintptr_t) &cpu_state); + host_arm64_AND_IMM(block, REG_TEMP, REG_TEMP, 7); + host_arm64_STRB_REG(block, host_reg, REG_TEMP2, REG_TEMP); } -void codegen_direct_write_st_64(codeblock_t *block, void *base, int reg_idx, int host_reg) +void +codegen_direct_write_st_64(codeblock_t *block, void *base, int reg_idx, int host_reg) { - host_arm64_LDR_IMM_W(block, REG_TEMP, REG_XSP, IREG_TOP_diff_stack_offset); - host_arm64_ADD_IMM(block, REG_TEMP, REG_TEMP, reg_idx); - host_arm64_ADDX_IMM(block, REG_TEMP2, REG_CPUSTATE, (uintptr_t)base - (uintptr_t)&cpu_state); - host_arm64_AND_IMM(block, REG_TEMP, REG_TEMP, 7); - host_arm64_STR_REG_F64_S(block, host_reg, REG_TEMP2, REG_TEMP); + host_arm64_LDR_IMM_W(block, REG_TEMP, REG_XSP, IREG_TOP_diff_stack_offset); + host_arm64_ADD_IMM(block, REG_TEMP, REG_TEMP, reg_idx); + host_arm64_ADDX_IMM(block, REG_TEMP2, REG_CPUSTATE, (uintptr_t) base - (uintptr_t) &cpu_state); + host_arm64_AND_IMM(block, REG_TEMP, REG_TEMP, 7); + host_arm64_STR_REG_F64_S(block, host_reg, REG_TEMP2, REG_TEMP); } -void codegen_direct_write_st_double(codeblock_t *block, void *base, int reg_idx, int host_reg) +void +codegen_direct_write_st_double(codeblock_t *block, void *base, int reg_idx, int host_reg) { - host_arm64_LDR_IMM_W(block, REG_TEMP, REG_XSP, IREG_TOP_diff_stack_offset); - host_arm64_ADD_IMM(block, REG_TEMP, REG_TEMP, reg_idx); - host_arm64_ADDX_IMM(block, REG_TEMP2, REG_CPUSTATE, (uintptr_t)base - (uintptr_t)&cpu_state); - host_arm64_AND_IMM(block, REG_TEMP, REG_TEMP, 7); - host_arm64_STR_REG_F64_S(block, host_reg, REG_TEMP2, REG_TEMP); + host_arm64_LDR_IMM_W(block, REG_TEMP, REG_XSP, IREG_TOP_diff_stack_offset); + host_arm64_ADD_IMM(block, REG_TEMP, REG_TEMP, reg_idx); + host_arm64_ADDX_IMM(block, REG_TEMP2, REG_CPUSTATE, (uintptr_t) base - (uintptr_t) &cpu_state); + host_arm64_AND_IMM(block, REG_TEMP, REG_TEMP, 7); + host_arm64_STR_REG_F64_S(block, host_reg, REG_TEMP2, REG_TEMP); } -void codegen_direct_write_ptr(codeblock_t *block, void *p, int host_reg) +void +codegen_direct_write_ptr(codeblock_t *block, void *p, int host_reg) { - if (in_range12_q((uintptr_t)p - (uintptr_t)&cpu_state)) - host_arm64_STR_IMM_Q(block, host_reg, REG_CPUSTATE, (uintptr_t)p - (uintptr_t)&cpu_state); - else - fatal("codegen_direct_write_ptr - not in range\n"); + if (in_range12_q((uintptr_t) p - (uintptr_t) &cpu_state)) + host_arm64_STR_IMM_Q(block, host_reg, REG_CPUSTATE, (uintptr_t) p - (uintptr_t) &cpu_state); + else + fatal("codegen_direct_write_ptr - not in range\n"); } -void codegen_direct_read_16_stack(codeblock_t *block, int host_reg, int stack_offset) +void +codegen_direct_read_16_stack(codeblock_t *block, int host_reg, int stack_offset) { - if (in_range12_h(stack_offset)) - host_arm64_LDRH_IMM(block, host_reg, REG_XSP, stack_offset); - else - fatal("codegen_direct_read_32_stack - not in range\n"); + if (in_range12_h(stack_offset)) + host_arm64_LDRH_IMM(block, host_reg, REG_XSP, stack_offset); + else + fatal("codegen_direct_read_32_stack - not in range\n"); } -void codegen_direct_read_32_stack(codeblock_t *block, int host_reg, int stack_offset) +void +codegen_direct_read_32_stack(codeblock_t *block, int host_reg, int stack_offset) { - if (in_range12_w(stack_offset)) - host_arm64_LDR_IMM_W(block, host_reg, REG_XSP, stack_offset); - else - fatal("codegen_direct_read_32_stack - not in range\n"); + if (in_range12_w(stack_offset)) + host_arm64_LDR_IMM_W(block, host_reg, REG_XSP, stack_offset); + else + fatal("codegen_direct_read_32_stack - not in range\n"); } -void codegen_direct_read_pointer_stack(codeblock_t *block, int host_reg, int stack_offset) +void +codegen_direct_read_pointer_stack(codeblock_t *block, int host_reg, int stack_offset) { - if (in_range12_q(stack_offset)) - host_arm64_LDR_IMM_X(block, host_reg, REG_XSP, stack_offset); - else - fatal("codegen_direct_read_pointer_stack - not in range\n"); + if (in_range12_q(stack_offset)) + host_arm64_LDR_IMM_X(block, host_reg, REG_XSP, stack_offset); + else + fatal("codegen_direct_read_pointer_stack - not in range\n"); } -void codegen_direct_read_64_stack(codeblock_t *block, int host_reg, int stack_offset) +void +codegen_direct_read_64_stack(codeblock_t *block, int host_reg, int stack_offset) { - host_arm64_LDR_IMM_F64(block, host_reg, REG_XSP, stack_offset); + host_arm64_LDR_IMM_F64(block, host_reg, REG_XSP, stack_offset); } -void codegen_direct_read_double_stack(codeblock_t *block, int host_reg, int stack_offset) +void +codegen_direct_read_double_stack(codeblock_t *block, int host_reg, int stack_offset) { - host_arm64_LDR_IMM_F64(block, host_reg, REG_XSP, stack_offset); + host_arm64_LDR_IMM_F64(block, host_reg, REG_XSP, stack_offset); } -void codegen_direct_write_32_stack(codeblock_t *block, int stack_offset, int host_reg) +void +codegen_direct_write_32_stack(codeblock_t *block, int stack_offset, int host_reg) { - if (in_range12_w(stack_offset)) - host_arm64_STR_IMM_W(block, host_reg, REG_XSP, stack_offset); - else - fatal("codegen_direct_write_32_stack - not in range\n"); + if (in_range12_w(stack_offset)) + host_arm64_STR_IMM_W(block, host_reg, REG_XSP, stack_offset); + else + fatal("codegen_direct_write_32_stack - not in range\n"); } -void codegen_direct_write_64_stack(codeblock_t *block, int stack_offset, int host_reg) +void +codegen_direct_write_64_stack(codeblock_t *block, int stack_offset, int host_reg) { - host_arm64_STR_IMM_F64(block, host_reg, REG_XSP, stack_offset); + host_arm64_STR_IMM_F64(block, host_reg, REG_XSP, stack_offset); } -void codegen_direct_write_double_stack(codeblock_t *block, int stack_offset, int host_reg) +void +codegen_direct_write_double_stack(codeblock_t *block, int stack_offset, int host_reg) { - host_arm64_STR_IMM_F64(block, host_reg, REG_XSP, stack_offset); + host_arm64_STR_IMM_F64(block, host_reg, REG_XSP, stack_offset); } -void codegen_set_jump_dest(codeblock_t *block, void *p) +void +codegen_set_jump_dest(codeblock_t *block, void *p) { - host_arm64_branch_set_offset(p, &block_write_data[block_pos]); + host_arm64_branch_set_offset(p, &block_write_data[block_pos]); } #endif diff --git a/src/codegen_new/codegen_backend_arm_defs.h b/src/codegen_new/codegen_backend_arm_defs.h index 74567998a..745854429 100644 --- a/src/codegen_new/codegen_backend_arm_defs.h +++ b/src/codegen_new/codegen_backend_arm_defs.h @@ -1,72 +1,71 @@ -#define REG_R0 0 -#define REG_R1 1 -#define REG_R2 2 -#define REG_R3 3 -#define REG_R4 4 -#define REG_R5 5 -#define REG_R6 6 -#define REG_R7 7 -#define REG_R8 8 -#define REG_R9 9 -#define REG_R10 10 -#define REG_R11 11 -#define REG_R12 12 -#define REG_HOST_SP 13 -#define REG_LR 14 -#define REG_PC 15 +#define REG_R0 0 +#define REG_R1 1 +#define REG_R2 2 +#define REG_R3 3 +#define REG_R4 4 +#define REG_R5 5 +#define REG_R6 6 +#define REG_R7 7 +#define REG_R8 8 +#define REG_R9 9 +#define REG_R10 10 +#define REG_R11 11 +#define REG_R12 12 +#define REG_HOST_SP 13 +#define REG_LR 14 +#define REG_PC 15 -#define REG_ARG0 REG_R0 -#define REG_ARG1 REG_R1 -#define REG_ARG2 REG_R2 -#define REG_ARG3 REG_R3 +#define REG_ARG0 REG_R0 +#define REG_ARG1 REG_R1 +#define REG_ARG2 REG_R2 +#define REG_ARG3 REG_R3 -#define REG_CPUSTATE REG_R10 +#define REG_CPUSTATE REG_R10 -#define REG_TEMP REG_R3 -#define REG_TEMP2 REG_R2 +#define REG_TEMP REG_R3 +#define REG_TEMP2 REG_R2 -#define REG_D0 0 -#define REG_D1 1 -#define REG_D2 2 -#define REG_D3 3 -#define REG_D4 4 -#define REG_D5 5 -#define REG_D6 6 -#define REG_D7 7 -#define REG_D8 8 -#define REG_D9 9 -#define REG_D10 10 -#define REG_D11 11 -#define REG_D12 12 -#define REG_D13 13 -#define REG_D14 14 -#define REG_D15 15 +#define REG_D0 0 +#define REG_D1 1 +#define REG_D2 2 +#define REG_D3 3 +#define REG_D4 4 +#define REG_D5 5 +#define REG_D6 6 +#define REG_D7 7 +#define REG_D8 8 +#define REG_D9 9 +#define REG_D10 10 +#define REG_D11 11 +#define REG_D12 12 +#define REG_D13 13 +#define REG_D14 14 +#define REG_D15 15 -#define REG_D_TEMP REG_D0 -#define REG_Q_TEMP REG_D0 -#define REG_Q_TEMP_2 REG_D2 +#define REG_D_TEMP REG_D0 +#define REG_Q_TEMP REG_D0 +#define REG_Q_TEMP_2 REG_D2 -#define REG_MASK_R0 (1 << REG_R0) -#define REG_MASK_R1 (1 << REG_R1) -#define REG_MASK_R2 (1 << REG_R2) -#define REG_MASK_R3 (1 << REG_R3) -#define REG_MASK_R4 (1 << REG_R4) -#define REG_MASK_R5 (1 << REG_R5) -#define REG_MASK_R6 (1 << REG_R6) -#define REG_MASK_R7 (1 << REG_R7) -#define REG_MASK_R8 (1 << REG_R8) -#define REG_MASK_R9 (1 << REG_R9) -#define REG_MASK_R10 (1 << REG_R10) -#define REG_MASK_R11 (1 << REG_R11) -#define REG_MASK_R12 (1 << REG_R12) -#define REG_MASK_SP (1 << REG_HOST_SP) -#define REG_MASK_LR (1 << REG_LR) -#define REG_MASK_PC (1 << REG_PC) +#define REG_MASK_R0 (1 << REG_R0) +#define REG_MASK_R1 (1 << REG_R1) +#define REG_MASK_R2 (1 << REG_R2) +#define REG_MASK_R3 (1 << REG_R3) +#define REG_MASK_R4 (1 << REG_R4) +#define REG_MASK_R5 (1 << REG_R5) +#define REG_MASK_R6 (1 << REG_R6) +#define REG_MASK_R7 (1 << REG_R7) +#define REG_MASK_R8 (1 << REG_R8) +#define REG_MASK_R9 (1 << REG_R9) +#define REG_MASK_R10 (1 << REG_R10) +#define REG_MASK_R11 (1 << REG_R11) +#define REG_MASK_R12 (1 << REG_R12) +#define REG_MASK_SP (1 << REG_HOST_SP) +#define REG_MASK_LR (1 << REG_LR) +#define REG_MASK_PC (1 << REG_PC) -#define REG_MASK_LOCAL (REG_MASK_R4 | REG_MASK_R5 | REG_MASK_R6 | REG_MASK_R7 | \ - REG_MASK_R8 | REG_MASK_R9 | REG_MASK_R10 | REG_MASK_R11) +#define REG_MASK_LOCAL (REG_MASK_R4 | REG_MASK_R5 | REG_MASK_R6 | REG_MASK_R7 | REG_MASK_R8 | REG_MASK_R9 | REG_MASK_R10 | REG_MASK_R11) -#define CODEGEN_HOST_REGS 7 +#define CODEGEN_HOST_REGS 7 #define CODEGEN_HOST_FP_REGS 8 extern void *codegen_mem_load_byte; diff --git a/src/codegen_new/codegen_backend_arm_ops.c b/src/codegen_new/codegen_backend_arm_ops.c index 43d1ea090..3331af4e0 100644 --- a/src/codegen_new/codegen_backend_arm_ops.c +++ b/src/codegen_new/codegen_backend_arm_ops.c @@ -1,1274 +1,1398 @@ #if defined __ARM_EABI__ || defined _ARM_ || defined _M_ARM -#include -#include <86box/86box.h> -#include "cpu.h" -#include <86box/mem.h> +# include +# include <86box/86box.h> +# include "cpu.h" +# include <86box/mem.h> +# include <86box/plat_unused.h> -#include "codegen.h" -#include "codegen_allocator.h" -#include "codegen_backend.h" -#include "codegen_backend_arm_defs.h" -#include "codegen_backend_arm_ops.h" +# include "codegen.h" +# include "codegen_allocator.h" +# include "codegen_backend.h" +# include "codegen_backend_arm_defs.h" +# include "codegen_backend_arm_ops.h" -#define Rm(x) (x) -#define Rs(x) ((x) << 8) -#define Rd(x) ((x) << 12) -#define Rt(x) ((x) << 12) -#define Rn(x) ((x) << 16) -#define Rt2(x) ((x) << 16) +# define Rm(x) (x) +# define Rs(x) ((x) << 8) +# define Rd(x) ((x) << 12) +# define Rt(x) ((x) << 12) +# define Rn(x) ((x) << 16) +# define Rt2(x) ((x) << 16) -#define Vm(x) (x) -#define Vd(x) ((x) << 12) -#define Vn(x) ((x) << 16) +# define Vm(x) (x) +# define Vd(x) ((x) << 12) +# define Vn(x) ((x) << 16) -#define DATA_OFFSET_UP (1 << 23) -#define DATA_OFFSET_DOWN (0 << 23) +# define DATA_OFFSET_UP (1 << 23) +# define DATA_OFFSET_DOWN (0 << 23) -#define OPCODE_SHIFT 20 -#define OPCODE_ADD_IMM (0x28 << OPCODE_SHIFT) -#define OPCODE_ADD_REG (0x08 << OPCODE_SHIFT) -#define OPCODE_AND_IMM (0x20 << OPCODE_SHIFT) -#define OPCODE_AND_REG (0x00 << OPCODE_SHIFT) -#define OPCODE_B (0xa0 << OPCODE_SHIFT) -#define OPCODE_BIC_IMM (0x3c << OPCODE_SHIFT) -#define OPCODE_BIC_REG (0x1c << OPCODE_SHIFT) -#define OPCODE_BL (0xb0 << OPCODE_SHIFT) -#define OPCODE_CMN_IMM (0x37 << OPCODE_SHIFT) -#define OPCODE_CMN_REG (0x17 << OPCODE_SHIFT) -#define OPCODE_CMP_IMM (0x35 << OPCODE_SHIFT) -#define OPCODE_CMP_REG (0x15 << OPCODE_SHIFT) -#define OPCODE_EOR_IMM (0x22 << OPCODE_SHIFT) -#define OPCODE_EOR_REG (0x02 << OPCODE_SHIFT) -#define OPCODE_LDMIA_WB (0x8b << OPCODE_SHIFT) -#define OPCODE_LDR_IMM (0x51 << OPCODE_SHIFT) -#define OPCODE_LDR_IMM_POST (0x41 << OPCODE_SHIFT) -#define OPCODE_LDR_REG (0x79 << OPCODE_SHIFT) -#define OPCODE_LDRB_IMM (0x55 << OPCODE_SHIFT) -#define OPCODE_LDRB_REG (0x7d << OPCODE_SHIFT) -#define OPCODE_MOV_IMM (0x3a << OPCODE_SHIFT) -#define OPCODE_MOVT_IMM (0x34 << OPCODE_SHIFT) -#define OPCODE_MOVW_IMM (0x30 << OPCODE_SHIFT) -#define OPCODE_MOV_REG (0x1a << OPCODE_SHIFT) -#define OPCODE_MVN_REG (0x1e << OPCODE_SHIFT) -#define OPCODE_ORR_IMM (0x38 << OPCODE_SHIFT) -#define OPCODE_ORR_REG (0x18 << OPCODE_SHIFT) -#define OPCODE_RSB_IMM (0x26 << OPCODE_SHIFT) -#define OPCODE_RSB_REG (0x06 << OPCODE_SHIFT) -#define OPCODE_STMDB_WB (0x92 << OPCODE_SHIFT) -#define OPCODE_STR_IMM (0x50 << OPCODE_SHIFT) -#define OPCODE_STR_IMM_WB (0x52 << OPCODE_SHIFT) -#define OPCODE_STR_REG (0x78 << OPCODE_SHIFT) -#define OPCODE_STRB_IMM (0x54 << OPCODE_SHIFT) -#define OPCODE_STRB_REG (0x7c << OPCODE_SHIFT) -#define OPCODE_SUB_IMM (0x24 << OPCODE_SHIFT) -#define OPCODE_SUB_REG (0x04 << OPCODE_SHIFT) -#define OPCODE_TST_IMM (0x31 << OPCODE_SHIFT) -#define OPCODE_TST_REG (0x11 << OPCODE_SHIFT) +# define OPCODE_SHIFT 20 +# define OPCODE_ADD_IMM (0x28 << OPCODE_SHIFT) +# define OPCODE_ADD_REG (0x08 << OPCODE_SHIFT) +# define OPCODE_AND_IMM (0x20 << OPCODE_SHIFT) +# define OPCODE_AND_REG (0x00 << OPCODE_SHIFT) +# define OPCODE_B (0xa0 << OPCODE_SHIFT) +# define OPCODE_BIC_IMM (0x3c << OPCODE_SHIFT) +# define OPCODE_BIC_REG (0x1c << OPCODE_SHIFT) +# define OPCODE_BL (0xb0 << OPCODE_SHIFT) +# define OPCODE_CMN_IMM (0x37 << OPCODE_SHIFT) +# define OPCODE_CMN_REG (0x17 << OPCODE_SHIFT) +# define OPCODE_CMP_IMM (0x35 << OPCODE_SHIFT) +# define OPCODE_CMP_REG (0x15 << OPCODE_SHIFT) +# define OPCODE_EOR_IMM (0x22 << OPCODE_SHIFT) +# define OPCODE_EOR_REG (0x02 << OPCODE_SHIFT) +# define OPCODE_LDMIA_WB (0x8b << OPCODE_SHIFT) +# define OPCODE_LDR_IMM (0x51 << OPCODE_SHIFT) +# define OPCODE_LDR_IMM_POST (0x41 << OPCODE_SHIFT) +# define OPCODE_LDR_REG (0x79 << OPCODE_SHIFT) +# define OPCODE_LDRB_IMM (0x55 << OPCODE_SHIFT) +# define OPCODE_LDRB_REG (0x7d << OPCODE_SHIFT) +# define OPCODE_MOV_IMM (0x3a << OPCODE_SHIFT) +# define OPCODE_MOVT_IMM (0x34 << OPCODE_SHIFT) +# define OPCODE_MOVW_IMM (0x30 << OPCODE_SHIFT) +# define OPCODE_MOV_REG (0x1a << OPCODE_SHIFT) +# define OPCODE_MVN_REG (0x1e << OPCODE_SHIFT) +# define OPCODE_ORR_IMM (0x38 << OPCODE_SHIFT) +# define OPCODE_ORR_REG (0x18 << OPCODE_SHIFT) +# define OPCODE_RSB_IMM (0x26 << OPCODE_SHIFT) +# define OPCODE_RSB_REG (0x06 << OPCODE_SHIFT) +# define OPCODE_STMDB_WB (0x92 << OPCODE_SHIFT) +# define OPCODE_STR_IMM (0x50 << OPCODE_SHIFT) +# define OPCODE_STR_IMM_WB (0x52 << OPCODE_SHIFT) +# define OPCODE_STR_REG (0x78 << OPCODE_SHIFT) +# define OPCODE_STRB_IMM (0x54 << OPCODE_SHIFT) +# define OPCODE_STRB_REG (0x7c << OPCODE_SHIFT) +# define OPCODE_SUB_IMM (0x24 << OPCODE_SHIFT) +# define OPCODE_SUB_REG (0x04 << OPCODE_SHIFT) +# define OPCODE_TST_IMM (0x31 << OPCODE_SHIFT) +# define OPCODE_TST_REG (0x11 << OPCODE_SHIFT) -#define OPCODE_BFI 0xe7c00010 -#define OPCODE_BLX 0xe12fff30 -#define OPCODE_BX 0xe12fff10 -#define OPCODE_LDRH_IMM 0xe1d000b0 -#define OPCODE_LDRH_REG 0xe19000b0 -#define OPCODE_STRH_IMM 0xe1c000b0 -#define OPCODE_STRH_REG 0xe18000b0 -#define OPCODE_SXTB 0xe6af0070 -#define OPCODE_SXTH 0xe6bf0070 -#define OPCODE_UADD8 0xe6500f90 -#define OPCODE_UADD16 0xe6500f10 -#define OPCODE_USUB8 0xe6500ff0 -#define OPCODE_USUB16 0xe6500f70 -#define OPCODE_UXTB 0xe6ef0070 -#define OPCODE_UXTH 0xe6ff0070 -#define OPCODE_VABS_D 0xeeb00bc0 -#define OPCODE_VADD 0xee300b00 -#define OPCODE_VADD_I8 0xf2000800 -#define OPCODE_VADD_I16 0xf2100800 -#define OPCODE_VADD_I32 0xf2200800 -#define OPCODE_VADD_F32 0xf2000d00 -#define OPCODE_VAND_D 0xf2000110 -#define OPCODE_VBIC_D 0xf2100110 -#define OPCODE_VCEQ_F32 0xf2000e00 -#define OPCODE_VCEQ_I8 0xf3000810 -#define OPCODE_VCEQ_I16 0xf3100810 -#define OPCODE_VCEQ_I32 0xf3200810 -#define OPCODE_VCGE_F32 0xf3000e00 -#define OPCODE_VCGT_F32 0xf3200e00 -#define OPCODE_VCGT_S8 0xf2000300 -#define OPCODE_VCGT_S16 0xf2100300 -#define OPCODE_VCGT_S32 0xf2200300 -#define OPCODE_VCMP_D 0xeeb40b40 -#define OPCODE_VCVT_D_IS 0xeeb80bc0 -#define OPCODE_VCVT_D_S 0xeeb70ac0 -#define OPCODE_VCVT_F32_S32 0xf3bb0700 -#define OPCODE_VCVT_IS_D 0xeebd0bc0 -#define OPCODE_VCVT_S32_F32 0xf3bb0600 -#define OPCODE_VCVT_S_D 0xeeb70bc0 -#define OPCODE_VCVTR_IS_D 0xeebd0b40 -#define OPCODE_VDIV 0xee800b00 -#define OPCODE_VDIV_S 0xee800a00 -#define OPCODE_VDUP_32 0xf3b40c00 -#define OPCODE_VEOR_D 0xf3000110 -#define OPCODE_VLDR_D 0xed900b00 -#define OPCODE_VLDR_S 0xed900a00 -#define OPCODE_VMAX_F32 0xf200f00 -#define OPCODE_VMIN_F32 0xf220f00 -#define OPCODE_VMOV_32_S 0xee100a10 -#define OPCODE_VMOV_64_D 0xec500b10 -#define OPCODE_VMOV_D_64 0xec400b10 -#define OPCODE_VMOV_S_32 0xee000a10 -#define OPCODE_VMOV_D_D 0xeeb00b40 -#define OPCODE_VMOVN_I32 0xf3b60200 -#define OPCODE_VMOVN_I64 0xf3ba0200 -#define OPCODE_VMOV_F32_ONE 0xf2870f10 -#define OPCODE_VMRS_APSR 0xeef1fa10 -#define OPCODE_VMSR_FPSCR 0xeee10a10 -#define OPCODE_VMUL 0xee200b00 -#define OPCODE_VMUL_F32 0xf3000d10 -#define OPCODE_VMUL_S16 0xf2100910 -#define OPCODE_VMULL_S16 0xf2900c00 -#define OPCODE_VNEG_D 0xeeb10b40 -#define OPCODE_VORR_D 0xf2200110 -#define OPCODE_VPADDL_S16 0xf3b40200 -#define OPCODE_VPADDL_S32 0xf3b80200 -#define OPCODE_VPADDL_Q_S32 0xf3b80240 -#define OPCODE_VQADD_S8 0xf2000010 -#define OPCODE_VQADD_S16 0xf2100010 -#define OPCODE_VQADD_U8 0xf3000010 -#define OPCODE_VQADD_U16 0xf3100010 -#define OPCODE_VQMOVN_S16 0xf3b20280 -#define OPCODE_VQMOVN_S32 0xf3b60280 -#define OPCODE_VQMOVN_U16 0xf3b202c0 -#define OPCODE_VQSUB_S8 0xf2000210 -#define OPCODE_VQSUB_S16 0xf2100210 -#define OPCODE_VQSUB_U8 0xf3000210 -#define OPCODE_VQSUB_U16 0xf3100210 -#define OPCODE_VSHL_D_IMM_16 0xf2900510 -#define OPCODE_VSHL_D_IMM_32 0xf2a00510 -#define OPCODE_VSHL_D_IMM_64 0xf2800590 -#define OPCODE_VSHR_D_S16 0xf2900010 -#define OPCODE_VSHR_D_S32 0xf2a00010 -#define OPCODE_VSHR_D_S64 0xf2800090 -#define OPCODE_VSHR_D_U16 0xf3900010 -#define OPCODE_VSHR_D_U32 0xf3a00010 -#define OPCODE_VSHR_D_U64 0xf3800090 -#define OPCODE_VSHRN 0xf2800810 -#define OPCODE_VSQRT_D 0xeeb10bc0 -#define OPCODE_VSQRT_S 0xeeb10ac0 -#define OPCODE_VSTR_D 0xed800b00 -#define OPCODE_VSTR_S 0xed800a00 -#define OPCODE_VSUB 0xee300b40 -#define OPCODE_VSUB_I8 0xf3000800 -#define OPCODE_VSUB_I16 0xf3100800 -#define OPCODE_VSUB_I32 0xf3200800 -#define OPCODE_VSUB_F32 0xf3000d00 -#define OPCODE_VZIP_D8 0xf3b20180 -#define OPCODE_VZIP_D16 0xf3b60180 -#define OPCODE_VZIP_D32 0xf3ba0080 +# define OPCODE_BFI 0xe7c00010 +# define OPCODE_BLX 0xe12fff30 +# define OPCODE_BX 0xe12fff10 +# define OPCODE_LDRH_IMM 0xe1d000b0 +# define OPCODE_LDRH_REG 0xe19000b0 +# define OPCODE_STRH_IMM 0xe1c000b0 +# define OPCODE_STRH_REG 0xe18000b0 +# define OPCODE_SXTB 0xe6af0070 +# define OPCODE_SXTH 0xe6bf0070 +# define OPCODE_UADD8 0xe6500f90 +# define OPCODE_UADD16 0xe6500f10 +# define OPCODE_USUB8 0xe6500ff0 +# define OPCODE_USUB16 0xe6500f70 +# define OPCODE_UXTB 0xe6ef0070 +# define OPCODE_UXTH 0xe6ff0070 +# define OPCODE_VABS_D 0xeeb00bc0 +# define OPCODE_VADD 0xee300b00 +# define OPCODE_VADD_I8 0xf2000800 +# define OPCODE_VADD_I16 0xf2100800 +# define OPCODE_VADD_I32 0xf2200800 +# define OPCODE_VADD_F32 0xf2000d00 +# define OPCODE_VAND_D 0xf2000110 +# define OPCODE_VBIC_D 0xf2100110 +# define OPCODE_VCEQ_F32 0xf2000e00 +# define OPCODE_VCEQ_I8 0xf3000810 +# define OPCODE_VCEQ_I16 0xf3100810 +# define OPCODE_VCEQ_I32 0xf3200810 +# define OPCODE_VCGE_F32 0xf3000e00 +# define OPCODE_VCGT_F32 0xf3200e00 +# define OPCODE_VCGT_S8 0xf2000300 +# define OPCODE_VCGT_S16 0xf2100300 +# define OPCODE_VCGT_S32 0xf2200300 +# define OPCODE_VCMP_D 0xeeb40b40 +# define OPCODE_VCVT_D_IS 0xeeb80bc0 +# define OPCODE_VCVT_D_S 0xeeb70ac0 +# define OPCODE_VCVT_F32_S32 0xf3bb0700 +# define OPCODE_VCVT_IS_D 0xeebd0bc0 +# define OPCODE_VCVT_S32_F32 0xf3bb0600 +# define OPCODE_VCVT_S_D 0xeeb70bc0 +# define OPCODE_VCVTR_IS_D 0xeebd0b40 +# define OPCODE_VDIV 0xee800b00 +# define OPCODE_VDIV_S 0xee800a00 +# define OPCODE_VDUP_32 0xf3b40c00 +# define OPCODE_VEOR_D 0xf3000110 +# define OPCODE_VLDR_D 0xed900b00 +# define OPCODE_VLDR_S 0xed900a00 +# define OPCODE_VMAX_F32 0xf200f00 +# define OPCODE_VMIN_F32 0xf220f00 +# define OPCODE_VMOV_32_S 0xee100a10 +# define OPCODE_VMOV_64_D 0xec500b10 +# define OPCODE_VMOV_D_64 0xec400b10 +# define OPCODE_VMOV_S_32 0xee000a10 +# define OPCODE_VMOV_D_D 0xeeb00b40 +# define OPCODE_VMOVN_I32 0xf3b60200 +# define OPCODE_VMOVN_I64 0xf3ba0200 +# define OPCODE_VMOV_F32_ONE 0xf2870f10 +# define OPCODE_VMRS_APSR 0xeef1fa10 +# define OPCODE_VMSR_FPSCR 0xeee10a10 +# define OPCODE_VMUL 0xee200b00 +# define OPCODE_VMUL_F32 0xf3000d10 +# define OPCODE_VMUL_S16 0xf2100910 +# define OPCODE_VMULL_S16 0xf2900c00 +# define OPCODE_VNEG_D 0xeeb10b40 +# define OPCODE_VORR_D 0xf2200110 +# define OPCODE_VPADDL_S16 0xf3b40200 +# define OPCODE_VPADDL_S32 0xf3b80200 +# define OPCODE_VPADDL_Q_S32 0xf3b80240 +# define OPCODE_VQADD_S8 0xf2000010 +# define OPCODE_VQADD_S16 0xf2100010 +# define OPCODE_VQADD_U8 0xf3000010 +# define OPCODE_VQADD_U16 0xf3100010 +# define OPCODE_VQMOVN_S16 0xf3b20280 +# define OPCODE_VQMOVN_S32 0xf3b60280 +# define OPCODE_VQMOVN_U16 0xf3b202c0 +# define OPCODE_VQSUB_S8 0xf2000210 +# define OPCODE_VQSUB_S16 0xf2100210 +# define OPCODE_VQSUB_U8 0xf3000210 +# define OPCODE_VQSUB_U16 0xf3100210 +# define OPCODE_VSHL_D_IMM_16 0xf2900510 +# define OPCODE_VSHL_D_IMM_32 0xf2a00510 +# define OPCODE_VSHL_D_IMM_64 0xf2800590 +# define OPCODE_VSHR_D_S16 0xf2900010 +# define OPCODE_VSHR_D_S32 0xf2a00010 +# define OPCODE_VSHR_D_S64 0xf2800090 +# define OPCODE_VSHR_D_U16 0xf3900010 +# define OPCODE_VSHR_D_U32 0xf3a00010 +# define OPCODE_VSHR_D_U64 0xf3800090 +# define OPCODE_VSHRN 0xf2800810 +# define OPCODE_VSQRT_D 0xeeb10bc0 +# define OPCODE_VSQRT_S 0xeeb10ac0 +# define OPCODE_VSTR_D 0xed800b00 +# define OPCODE_VSTR_S 0xed800a00 +# define OPCODE_VSUB 0xee300b40 +# define OPCODE_VSUB_I8 0xf3000800 +# define OPCODE_VSUB_I16 0xf3100800 +# define OPCODE_VSUB_I32 0xf3200800 +# define OPCODE_VSUB_F32 0xf3000d00 +# define OPCODE_VZIP_D8 0xf3b20180 +# define OPCODE_VZIP_D16 0xf3b60180 +# define OPCODE_VZIP_D32 0xf3ba0080 -#define B_OFFSET(x) (((x) >> 2) & 0xffffff) +# define B_OFFSET(x) (((x) >> 2) & 0xffffff) -#define SHIFT_TYPE_SHIFT 5 -#define SHIFT_TYPE_LSL (0 << SHIFT_TYPE_SHIFT) -#define SHIFT_TYPE_LSR (1 << SHIFT_TYPE_SHIFT) -#define SHIFT_TYPE_ASR (2 << SHIFT_TYPE_SHIFT) -#define SHIFT_TYPE_ROR (3 << SHIFT_TYPE_SHIFT) +# define SHIFT_TYPE_SHIFT 5 +# define SHIFT_TYPE_LSL (0 << SHIFT_TYPE_SHIFT) +# define SHIFT_TYPE_LSR (1 << SHIFT_TYPE_SHIFT) +# define SHIFT_TYPE_ASR (2 << SHIFT_TYPE_SHIFT) +# define SHIFT_TYPE_ROR (3 << SHIFT_TYPE_SHIFT) -#define SHIFT_TYPE_IMM (0 << 4) -#define SHIFT_TYPE_REG (1 << 4) +# define SHIFT_TYPE_IMM (0 << 4) +# define SHIFT_TYPE_REG (1 << 4) -#define SHIFT_IMM_SHIFT 7 -#define SHIFT_ASR_IMM(x) (SHIFT_TYPE_ASR | SHIFT_TYPE_IMM | ((x) << SHIFT_IMM_SHIFT)) -#define SHIFT_LSL_IMM(x) (SHIFT_TYPE_LSL | SHIFT_TYPE_IMM | ((x) << SHIFT_IMM_SHIFT)) -#define SHIFT_LSR_IMM(x) (SHIFT_TYPE_LSR | SHIFT_TYPE_IMM | ((x) << SHIFT_IMM_SHIFT)) -#define SHIFT_ROR_IMM(x) (SHIFT_TYPE_ROR | SHIFT_TYPE_IMM | ((x) << SHIFT_IMM_SHIFT)) +# define SHIFT_IMM_SHIFT 7 +# define SHIFT_ASR_IMM(x) (SHIFT_TYPE_ASR | SHIFT_TYPE_IMM | ((x) << SHIFT_IMM_SHIFT)) +# define SHIFT_LSL_IMM(x) (SHIFT_TYPE_LSL | SHIFT_TYPE_IMM | ((x) << SHIFT_IMM_SHIFT)) +# define SHIFT_LSR_IMM(x) (SHIFT_TYPE_LSR | SHIFT_TYPE_IMM | ((x) << SHIFT_IMM_SHIFT)) +# define SHIFT_ROR_IMM(x) (SHIFT_TYPE_ROR | SHIFT_TYPE_IMM | ((x) << SHIFT_IMM_SHIFT)) -#define SHIFT_ASR_REG(x) (SHIFT_TYPE_ASR | SHIFT_TYPE_REG | Rs(x)) -#define SHIFT_LSL_REG(x) (SHIFT_TYPE_LSL | SHIFT_TYPE_REG | Rs(x)) -#define SHIFT_LSR_REG(x) (SHIFT_TYPE_LSR | SHIFT_TYPE_REG | Rs(x)) -#define SHIFT_ROR_REG(x) (SHIFT_TYPE_ROR | SHIFT_TYPE_REG | Rs(x)) +# define SHIFT_ASR_REG(x) (SHIFT_TYPE_ASR | SHIFT_TYPE_REG | Rs(x)) +# define SHIFT_LSL_REG(x) (SHIFT_TYPE_LSL | SHIFT_TYPE_REG | Rs(x)) +# define SHIFT_LSR_REG(x) (SHIFT_TYPE_LSR | SHIFT_TYPE_REG | Rs(x)) +# define SHIFT_ROR_REG(x) (SHIFT_TYPE_ROR | SHIFT_TYPE_REG | Rs(x)) -#define BFI_lsb(lsb) ((lsb) << 7) -#define BFI_msb(msb) ((msb) << 16) +# define BFI_lsb(lsb) ((lsb) << 7) +# define BFI_msb(msb) ((msb) << 16) -#define UXTB_ROTATE(rotate) (((rotate) >> 3) << 10) +# define UXTB_ROTATE(rotate) (((rotate) >> 3) << 10) -#define MOVT_IMM(imm) (((imm) & 0xfff) | (((imm) & 0xf000) << 4)) -#define MOVW_IMM(imm) (((imm) & 0xfff) | (((imm) & 0xf000) << 4)) +# define MOVT_IMM(imm) (((imm) &0xfff) | (((imm) &0xf000) << 4)) +# define MOVW_IMM(imm) (((imm) &0xfff) | (((imm) &0xf000) << 4)) -#define LDRH_IMM(imm) (((imm) & 0xf) | (((imm) & 0xf0) << 4)) -#define STRH_IMM(imm) LDRH_IMM(imm) +# define LDRH_IMM(imm) (((imm) &0xf) | (((imm) &0xf0) << 4)) +# define STRH_IMM(imm) LDRH_IMM(imm) -#define VSHIFT_IMM(shift) ((shift) << 16) +# define VSHIFT_IMM(shift) ((shift) << 16) -#define VSHIFT_IMM_32(shift) (((16 - (shift)) | 0x10) << 16) +# define VSHIFT_IMM_32(shift) (((16 - (shift)) | 0x10) << 16) -#define VDUP_32_IMM(imm) ((imm) << 19) +# define VDUP_32_IMM(imm) ((imm) << 19) static void codegen_allocate_new_block(codeblock_t *block); -static inline void codegen_addlong(codeblock_t *block, uint32_t val) +static inline void +codegen_addlong(codeblock_t *block, uint32_t val) { - if (block_pos >= (BLOCK_MAX-4)) - codegen_allocate_new_block(block); - *(uint32_t *)&block_write_data[block_pos] = val; - block_pos += 4; + if (block_pos >= (BLOCK_MAX - 4)) + codegen_allocate_new_block(block); + *(uint32_t *) &block_write_data[block_pos] = val; + block_pos += 4; } -static void codegen_allocate_new_block(codeblock_t *block) +static void +codegen_allocate_new_block(codeblock_t *block) { - /*Current block is full. Allocate a new block*/ - struct mem_block_t *new_block = codegen_allocator_allocate(block->head_mem_block, get_block_nr(block)); - uint8_t *new_ptr = codeblock_allocator_get_ptr(new_block); - uint32_t offset = ((uintptr_t)new_ptr - (uintptr_t)&block_write_data[block_pos]) - 8; + /*Current block is full. Allocate a new block*/ + struct mem_block_t *new_block = codegen_allocator_allocate(block->head_mem_block, get_block_nr(block)); + uint8_t *new_ptr = codeblock_allocator_get_ptr(new_block); + uint32_t offset = ((uintptr_t) new_ptr - (uintptr_t) &block_write_data[block_pos]) - 8; - /*Add a jump instruction to the new block*/ - *(uint32_t *)&block_write_data[block_pos] = COND_AL | OPCODE_B | B_OFFSET(offset); + /*Add a jump instruction to the new block*/ + *(uint32_t *) &block_write_data[block_pos] = COND_AL | OPCODE_B | B_OFFSET(offset); - /*Set write address to start of new block*/ - block_pos = 0; - block_write_data = new_ptr; + /*Set write address to start of new block*/ + block_pos = 0; + block_write_data = new_ptr; } -static inline void codegen_alloc_4(codeblock_t *block) +static inline void +codegen_alloc_4(codeblock_t *block) { - if (block_pos >= (BLOCK_MAX-4)) - codegen_allocate_new_block(block); + if (block_pos >= (BLOCK_MAX - 4)) + codegen_allocate_new_block(block); } -void codegen_alloc(codeblock_t *block, int size) +void +codegen_alloc(codeblock_t *block, int size) { - if (block_pos >= (BLOCK_MAX-size)) - codegen_allocate_new_block(block); + if (block_pos >= (BLOCK_MAX - size)) + codegen_allocate_new_block(block); } -static inline uint32_t arm_data_offset(int offset) +static inline uint32_t +arm_data_offset(int offset) { - if (offset < -0xffc || offset > 0xffc) - fatal("arm_data_offset out of range - %i\n", offset); + if (offset < -0xffc || offset > 0xffc) + fatal("arm_data_offset out of range - %i\n", offset); - if (offset >= 0) - return offset | DATA_OFFSET_UP; - return (-offset) | DATA_OFFSET_DOWN; + if (offset >= 0) + return offset | DATA_OFFSET_UP; + return (-offset) | DATA_OFFSET_DOWN; } -static inline int get_arm_imm(uint32_t imm_data, uint32_t *arm_imm) +static inline int +get_arm_imm(uint32_t imm_data, uint32_t *arm_imm) { - int shift = 0; - if (!(imm_data & 0xffff)) - { - shift += 16; - imm_data >>= 16; - } - if (!(imm_data & 0xff)) - { - shift += 8; - imm_data >>= 8; - } - if (!(imm_data & 0xf)) - { - shift += 4; - imm_data >>= 4; - } - if (!(imm_data & 0x3)) - { - shift += 2; - imm_data >>= 2; - } - if (imm_data > 0xff) /*Note - should handle rotation round the word*/ - return 0; - *arm_imm = imm_data | ((((32 - shift) >> 1) & 15) << 8); - return 1; + int shift = 0; + if (!(imm_data & 0xffff)) { + shift += 16; + imm_data >>= 16; + } + if (!(imm_data & 0xff)) { + shift += 8; + imm_data >>= 8; + } + if (!(imm_data & 0xf)) { + shift += 4; + imm_data >>= 4; + } + if (!(imm_data & 0x3)) { + shift += 2; + imm_data >>= 2; + } + if (imm_data > 0xff) /*Note - should handle rotation round the word*/ + return 0; + *arm_imm = imm_data | ((((32 - shift) >> 1) & 15) << 8); + return 1; } -static inline int in_range(void *addr, void *base) +static inline int +in_range(void *addr, void *base) { - int diff = (uintptr_t)addr - (uintptr_t)base; + int diff = (uintptr_t) addr - (uintptr_t) base; - if (diff < -4095 || diff > 4095) - return 0; - return 1; + if (diff < -4095 || diff > 4095) + return 0; + return 1; } void host_arm_ADD_REG_LSL(codeblock_t *block, int dst_reg, int src_reg_n, int src_reg_m, int shift); void host_arm_AND_REG_LSL(codeblock_t *block, int dst_reg, int src_reg_n, int src_reg_m, int shift); void host_arm_EOR_REG_LSL(codeblock_t *block, int dst_reg, int src_reg_n, int src_reg_m, int shift); -//void host_arm_ORR_REG_LSL(codeblock_t *block, int dst_reg, int src_reg_n, int src_reg_m, int shift); +# if 0 +void host_arm_ORR_REG_LSL(codeblock_t *block, int dst_reg, int src_reg_n, int src_reg_m, int shift); +# endif void host_arm_SUB_REG_LSL(codeblock_t *block, int dst_reg, int src_reg_n, int src_reg_m, int shift); -void host_arm_ADD_IMM(codeblock_t *block, int dst_reg, int src_reg, uint32_t imm) +void +host_arm_ADD_IMM(codeblock_t *block, int dst_reg, int src_reg, uint32_t imm) { - uint32_t arm_imm; + uint32_t arm_imm; - if ((int32_t)imm < 0 && imm != 0x80000000) - { - host_arm_SUB_IMM(block, dst_reg, src_reg, -(int32_t)imm); - } - else if (get_arm_imm(imm, &arm_imm)) - { - codegen_addlong(block, COND_AL | OPCODE_ADD_IMM | Rd(dst_reg) | Rn(src_reg) | arm_imm); - } - else - { - host_arm_MOV_IMM(block, REG_TEMP, imm); - host_arm_ADD_REG_LSL(block, dst_reg, src_reg, REG_TEMP, 0); - } + if ((int32_t) imm < 0 && imm != 0x80000000) { + host_arm_SUB_IMM(block, dst_reg, src_reg, -(int32_t) imm); + } else if (get_arm_imm(imm, &arm_imm)) { + codegen_addlong(block, COND_AL | OPCODE_ADD_IMM | Rd(dst_reg) | Rn(src_reg) | arm_imm); + } else { + host_arm_MOV_IMM(block, REG_TEMP, imm); + host_arm_ADD_REG_LSL(block, dst_reg, src_reg, REG_TEMP, 0); + } } -void host_arm_ADD_REG_LSL(codeblock_t *block, int dst_reg, int src_reg_n, int src_reg_m, int shift) +void +host_arm_ADD_REG_LSL(codeblock_t *block, int dst_reg, int src_reg_n, int src_reg_m, int shift) { - codegen_addlong(block, COND_AL | OPCODE_ADD_REG | Rd(dst_reg) | Rn(src_reg_n) | Rm(src_reg_m) | SHIFT_LSL_IMM(shift)); + codegen_addlong(block, COND_AL | OPCODE_ADD_REG | Rd(dst_reg) | Rn(src_reg_n) | Rm(src_reg_m) | SHIFT_LSL_IMM(shift)); } -void host_arm_ADD_REG_LSR(codeblock_t *block, int dst_reg, int src_reg_n, int src_reg_m, int shift) +void +host_arm_ADD_REG_LSR(codeblock_t *block, int dst_reg, int src_reg_n, int src_reg_m, int shift) { - codegen_addlong(block, COND_AL | OPCODE_ADD_REG | Rd(dst_reg) | Rn(src_reg_n) | Rm(src_reg_m) | SHIFT_LSR_IMM(shift)); + codegen_addlong(block, COND_AL | OPCODE_ADD_REG | Rd(dst_reg) | Rn(src_reg_n) | Rm(src_reg_m) | SHIFT_LSR_IMM(shift)); } -void host_arm_AND_IMM(codeblock_t *block, int dst_reg, int src_reg, uint32_t imm) +void +host_arm_AND_IMM(codeblock_t *block, int dst_reg, int src_reg, uint32_t imm) { - uint32_t arm_imm; + uint32_t arm_imm; - if (get_arm_imm(imm, &arm_imm)) - { - codegen_addlong(block, COND_AL | OPCODE_AND_IMM | Rd(dst_reg) | Rn(src_reg) | arm_imm); - } - else if (get_arm_imm(~imm, &arm_imm)) - { - codegen_addlong(block, COND_AL | OPCODE_BIC_IMM | Rd(dst_reg) | Rn(src_reg) | arm_imm); - } - else - { - host_arm_MOV_IMM(block, REG_TEMP, imm); - host_arm_AND_REG_LSL(block, dst_reg, src_reg, REG_TEMP, 0); - } + if (get_arm_imm(imm, &arm_imm)) { + codegen_addlong(block, COND_AL | OPCODE_AND_IMM | Rd(dst_reg) | Rn(src_reg) | arm_imm); + } else if (get_arm_imm(~imm, &arm_imm)) { + codegen_addlong(block, COND_AL | OPCODE_BIC_IMM | Rd(dst_reg) | Rn(src_reg) | arm_imm); + } else { + host_arm_MOV_IMM(block, REG_TEMP, imm); + host_arm_AND_REG_LSL(block, dst_reg, src_reg, REG_TEMP, 0); + } } -void host_arm_AND_REG_LSL(codeblock_t *block, int dst_reg, int src_reg_n, int src_reg_m, int shift) +void +host_arm_AND_REG_LSL(codeblock_t *block, int dst_reg, int src_reg_n, int src_reg_m, int shift) { - codegen_addlong(block, COND_AL | OPCODE_AND_REG | Rd(dst_reg) | Rn(src_reg_n) | Rm(src_reg_m) | SHIFT_LSL_IMM(shift)); + codegen_addlong(block, COND_AL | OPCODE_AND_REG | Rd(dst_reg) | Rn(src_reg_n) | Rm(src_reg_m) | SHIFT_LSL_IMM(shift)); } -void host_arm_AND_REG_LSR(codeblock_t *block, int dst_reg, int src_reg_n, int src_reg_m, int shift) +void +host_arm_AND_REG_LSR(codeblock_t *block, int dst_reg, int src_reg_n, int src_reg_m, int shift) { - codegen_addlong(block, COND_AL | OPCODE_AND_REG | Rd(dst_reg) | Rn(src_reg_n) | Rm(src_reg_m) | SHIFT_LSR_IMM(shift)); + codegen_addlong(block, COND_AL | OPCODE_AND_REG | Rd(dst_reg) | Rn(src_reg_n) | Rm(src_reg_m) | SHIFT_LSR_IMM(shift)); } -void host_arm_B(codeblock_t *block, uintptr_t dest_addr) +void +host_arm_B(codeblock_t *block, uintptr_t dest_addr) { - uint32_t offset; + uint32_t offset; - codegen_alloc_4(block); - offset = (dest_addr - (uintptr_t)&block_write_data[block_pos]) - 8; + codegen_alloc_4(block); + offset = (dest_addr - (uintptr_t) &block_write_data[block_pos]) - 8; - if ((offset & 0xfe000000) && (offset & 0xfe000000) != 0xfe000000) - { - host_arm_MOV_IMM(block, REG_R3, dest_addr); - host_arm_BX(block, REG_R3); - } - else - codegen_addlong(block, COND_AL | OPCODE_B | B_OFFSET(offset)); + if ((offset & 0xfe000000) && (offset & 0xfe000000) != 0xfe000000) { + host_arm_MOV_IMM(block, REG_R3, dest_addr); + host_arm_BX(block, REG_R3); + } else + codegen_addlong(block, COND_AL | OPCODE_B | B_OFFSET(offset)); } -void host_arm_BFI(codeblock_t *block, int dst_reg, int src_reg, int lsb, int width) +void +host_arm_BFI(codeblock_t *block, int dst_reg, int src_reg, int lsb, int width) { - codegen_addlong(block, OPCODE_BFI | Rd(dst_reg) | Rm(src_reg) | BFI_lsb(lsb) | BFI_msb((lsb + width) - 1)); + codegen_addlong(block, OPCODE_BFI | Rd(dst_reg) | Rm(src_reg) | BFI_lsb(lsb) | BFI_msb((lsb + width) - 1)); } -void host_arm_BIC_IMM(codeblock_t *block, int dst_reg, int src_reg, uint32_t imm) +void +host_arm_BIC_IMM(codeblock_t *block, int dst_reg, int src_reg, uint32_t imm) { - uint32_t arm_imm; + uint32_t arm_imm; - if (get_arm_imm(imm, &arm_imm)) - { - codegen_addlong(block, COND_AL | OPCODE_BIC_IMM | Rd(dst_reg) | Rn(src_reg) | arm_imm); - } - else if (get_arm_imm(~imm, &arm_imm)) - { - codegen_addlong(block, COND_AL | OPCODE_AND_IMM | Rd(dst_reg) | Rn(src_reg) | arm_imm); - } - else - { - host_arm_MOV_IMM(block, REG_TEMP, imm); - host_arm_BIC_REG_LSL(block, dst_reg, src_reg, REG_TEMP, 0); - } + if (get_arm_imm(imm, &arm_imm)) { + codegen_addlong(block, COND_AL | OPCODE_BIC_IMM | Rd(dst_reg) | Rn(src_reg) | arm_imm); + } else if (get_arm_imm(~imm, &arm_imm)) { + codegen_addlong(block, COND_AL | OPCODE_AND_IMM | Rd(dst_reg) | Rn(src_reg) | arm_imm); + } else { + host_arm_MOV_IMM(block, REG_TEMP, imm); + host_arm_BIC_REG_LSL(block, dst_reg, src_reg, REG_TEMP, 0); + } } -void host_arm_BIC_REG_LSL(codeblock_t *block, int dst_reg, int src_reg_n, int src_reg_m, int shift) +void +host_arm_BIC_REG_LSL(codeblock_t *block, int dst_reg, int src_reg_n, int src_reg_m, int shift) { - codegen_addlong(block, COND_AL | OPCODE_BIC_REG | Rd(dst_reg) | Rn(src_reg_n) | Rm(src_reg_m) | SHIFT_LSL_IMM(shift)); + codegen_addlong(block, COND_AL | OPCODE_BIC_REG | Rd(dst_reg) | Rn(src_reg_n) | Rm(src_reg_m) | SHIFT_LSL_IMM(shift)); } -void host_arm_BIC_REG_LSR(codeblock_t *block, int dst_reg, int src_reg_n, int src_reg_m, int shift) +void +host_arm_BIC_REG_LSR(codeblock_t *block, int dst_reg, int src_reg_n, int src_reg_m, int shift) { - codegen_addlong(block, COND_AL | OPCODE_BIC_REG | Rd(dst_reg) | Rn(src_reg_n) | Rm(src_reg_m) | SHIFT_LSR_IMM(shift)); + codegen_addlong(block, COND_AL | OPCODE_BIC_REG | Rd(dst_reg) | Rn(src_reg_n) | Rm(src_reg_m) | SHIFT_LSR_IMM(shift)); } -void host_arm_BL(codeblock_t *block, uintptr_t dest_addr) +void +host_arm_BL(codeblock_t *block, uintptr_t dest_addr) { - uint32_t offset; + uint32_t offset; - codegen_alloc_4(block); - offset = (dest_addr - (uintptr_t)&block_write_data[block_pos]) - 8; + codegen_alloc_4(block); + offset = (dest_addr - (uintptr_t) &block_write_data[block_pos]) - 8; - if ((offset & 0xfe000000) && (offset & 0xfe000000) != 0xfe000000) - { - host_arm_MOV_IMM(block, REG_R3, dest_addr); - host_arm_BLX(block, REG_R3); - } - else - codegen_addlong(block, COND_AL | OPCODE_BL | B_OFFSET(offset)); + if ((offset & 0xfe000000) && (offset & 0xfe000000) != 0xfe000000) { + host_arm_MOV_IMM(block, REG_R3, dest_addr); + host_arm_BLX(block, REG_R3); + } else + codegen_addlong(block, COND_AL | OPCODE_BL | B_OFFSET(offset)); } -void host_arm_BL_r1(codeblock_t *block, uintptr_t dest_addr) +void +host_arm_BL_r1(codeblock_t *block, uintptr_t dest_addr) { - uint32_t offset; + uint32_t offset; - codegen_alloc_4(block); - offset = (dest_addr - (uintptr_t)&block_write_data[block_pos]) - 8; + codegen_alloc_4(block); + offset = (dest_addr - (uintptr_t) &block_write_data[block_pos]) - 8; - if ((offset & 0xfe000000) && (offset & 0xfe000000) != 0xfe000000) - { - host_arm_MOV_IMM(block, REG_R1, dest_addr); - host_arm_BLX(block, REG_R1); - } - else - codegen_addlong(block, COND_AL | OPCODE_BL | B_OFFSET(offset)); + if ((offset & 0xfe000000) && (offset & 0xfe000000) != 0xfe000000) { + host_arm_MOV_IMM(block, REG_R1, dest_addr); + host_arm_BLX(block, REG_R1); + } else + codegen_addlong(block, COND_AL | OPCODE_BL | B_OFFSET(offset)); } -void host_arm_BLX(codeblock_t *block, int addr_reg) +void +host_arm_BLX(codeblock_t *block, int addr_reg) { - codegen_addlong(block, OPCODE_BLX | Rm(addr_reg)); + codegen_addlong(block, OPCODE_BLX | Rm(addr_reg)); } -uint32_t *host_arm_BCC_(codeblock_t *block) +uint32_t * +host_arm_BCC_(codeblock_t *block) { - codegen_addlong(block, COND_CC | OPCODE_B); + codegen_addlong(block, COND_CC | OPCODE_B); - return (uint32_t *)&block_write_data[block_pos - 4]; + return (uint32_t *) &block_write_data[block_pos - 4]; } -uint32_t *host_arm_BCS_(codeblock_t *block) +uint32_t * +host_arm_BCS_(codeblock_t *block) { - codegen_addlong(block, COND_CS | OPCODE_B); + codegen_addlong(block, COND_CS | OPCODE_B); - return (uint32_t *)&block_write_data[block_pos - 4]; + return (uint32_t *) &block_write_data[block_pos - 4]; } -uint32_t *host_arm_BEQ_(codeblock_t *block) +uint32_t * +host_arm_BEQ_(codeblock_t *block) { - codegen_addlong(block, COND_EQ | OPCODE_B); + codegen_addlong(block, COND_EQ | OPCODE_B); - return (uint32_t *)&block_write_data[block_pos - 4]; + return (uint32_t *) &block_write_data[block_pos - 4]; } -uint32_t *host_arm_BGE_(codeblock_t *block) +uint32_t * +host_arm_BGE_(codeblock_t *block) { - codegen_addlong(block, COND_GE | OPCODE_B); + codegen_addlong(block, COND_GE | OPCODE_B); - return (uint32_t *)&block_write_data[block_pos - 4]; + return (uint32_t *) &block_write_data[block_pos - 4]; } -uint32_t *host_arm_BGT_(codeblock_t *block) +uint32_t * +host_arm_BGT_(codeblock_t *block) { - codegen_addlong(block, COND_GT | OPCODE_B); + codegen_addlong(block, COND_GT | OPCODE_B); - return (uint32_t *)&block_write_data[block_pos - 4]; + return (uint32_t *) &block_write_data[block_pos - 4]; } -uint32_t *host_arm_BHI_(codeblock_t *block) +uint32_t * +host_arm_BHI_(codeblock_t *block) { - codegen_addlong(block, COND_HI | OPCODE_B); + codegen_addlong(block, COND_HI | OPCODE_B); - return (uint32_t *)&block_write_data[block_pos - 4]; + return (uint32_t *) &block_write_data[block_pos - 4]; } -uint32_t *host_arm_BLE_(codeblock_t *block) +uint32_t * +host_arm_BLE_(codeblock_t *block) { - codegen_addlong(block, COND_LE | OPCODE_B); + codegen_addlong(block, COND_LE | OPCODE_B); - return (uint32_t *)&block_write_data[block_pos - 4]; + return (uint32_t *) &block_write_data[block_pos - 4]; } -uint32_t *host_arm_BLS_(codeblock_t *block) +uint32_t * +host_arm_BLS_(codeblock_t *block) { - codegen_addlong(block, COND_LS | OPCODE_B); + codegen_addlong(block, COND_LS | OPCODE_B); - return (uint32_t *)&block_write_data[block_pos - 4]; + return (uint32_t *) &block_write_data[block_pos - 4]; } -uint32_t *host_arm_BLT_(codeblock_t *block) +uint32_t * +host_arm_BLT_(codeblock_t *block) { - codegen_addlong(block, COND_LT | OPCODE_B); + codegen_addlong(block, COND_LT | OPCODE_B); - return (uint32_t *)&block_write_data[block_pos - 4]; + return (uint32_t *) &block_write_data[block_pos - 4]; } -uint32_t *host_arm_BMI_(codeblock_t *block) +uint32_t * +host_arm_BMI_(codeblock_t *block) { - codegen_addlong(block, COND_MI | OPCODE_B); + codegen_addlong(block, COND_MI | OPCODE_B); - return (uint32_t *)&block_write_data[block_pos - 4]; + return (uint32_t *) &block_write_data[block_pos - 4]; } -uint32_t *host_arm_BNE_(codeblock_t *block) +uint32_t * +host_arm_BNE_(codeblock_t *block) { - codegen_addlong(block, COND_NE | OPCODE_B); + codegen_addlong(block, COND_NE | OPCODE_B); - return (uint32_t *)&block_write_data[block_pos - 4]; + return (uint32_t *) &block_write_data[block_pos - 4]; } -uint32_t *host_arm_BPL_(codeblock_t *block) +uint32_t * +host_arm_BPL_(codeblock_t *block) { - codegen_addlong(block, COND_PL | OPCODE_B); + codegen_addlong(block, COND_PL | OPCODE_B); - return (uint32_t *)&block_write_data[block_pos - 4]; + return (uint32_t *) &block_write_data[block_pos - 4]; } -uint32_t *host_arm_BVC_(codeblock_t *block) +uint32_t * +host_arm_BVC_(codeblock_t *block) { - codegen_addlong(block, COND_VC | OPCODE_B); + codegen_addlong(block, COND_VC | OPCODE_B); - return (uint32_t *)&block_write_data[block_pos - 4]; + return (uint32_t *) &block_write_data[block_pos - 4]; } -uint32_t *host_arm_BVS_(codeblock_t *block) +uint32_t * +host_arm_BVS_(codeblock_t *block) { - codegen_addlong(block, COND_VS | OPCODE_B); + codegen_addlong(block, COND_VS | OPCODE_B); - return (uint32_t *)&block_write_data[block_pos - 4]; + return (uint32_t *) &block_write_data[block_pos - 4]; } -void host_arm_BEQ(codeblock_t *block, uintptr_t dest_addr) +void +host_arm_BEQ(codeblock_t *block, uintptr_t dest_addr) { - uint32_t offset; + uint32_t offset; - codegen_alloc_4(block); - offset = (dest_addr - (uintptr_t)&block_write_data[block_pos]) - 8; + codegen_alloc_4(block); + offset = (dest_addr - (uintptr_t) &block_write_data[block_pos]) - 8; - if ((offset & 0xfe000000) && (offset & 0xfe000000) != 0xfe000000) - fatal("host_arm_BEQ - out of range %08x %i\n", offset, offset); + if ((offset & 0xfe000000) && (offset & 0xfe000000) != 0xfe000000) + fatal("host_arm_BEQ - out of range %08x %i\n", offset, offset); - codegen_addlong(block, COND_EQ | OPCODE_B | B_OFFSET(offset)); + codegen_addlong(block, COND_EQ | OPCODE_B | B_OFFSET(offset)); } -void host_arm_BNE(codeblock_t *block, uintptr_t dest_addr) +void +host_arm_BNE(codeblock_t *block, uintptr_t dest_addr) { - uint32_t offset; + uint32_t offset; - codegen_alloc_4(block); - offset = (dest_addr - (uintptr_t)&block_write_data[block_pos]) - 8; + codegen_alloc_4(block); + offset = (dest_addr - (uintptr_t) &block_write_data[block_pos]) - 8; - if ((offset & 0xfe000000) && (offset & 0xfe000000) != 0xfe000000) - fatal("host_arm_BNE - out of range %08x %i\n", offset, offset); + if ((offset & 0xfe000000) && (offset & 0xfe000000) != 0xfe000000) + fatal("host_arm_BNE - out of range %08x %i\n", offset, offset); - codegen_addlong(block, COND_NE | OPCODE_B | B_OFFSET(offset)); + codegen_addlong(block, COND_NE | OPCODE_B | B_OFFSET(offset)); } -void host_arm_BX(codeblock_t *block, int addr_reg) +void +host_arm_BX(codeblock_t *block, int addr_reg) { - codegen_addlong(block, OPCODE_BLX | Rm(addr_reg)); + codegen_addlong(block, OPCODE_BLX | Rm(addr_reg)); } -void host_arm_CMN_IMM(codeblock_t *block, int src_reg, uint32_t imm) +void +host_arm_CMN_IMM(codeblock_t *block, int src_reg, uint32_t imm) { - uint32_t arm_imm; + uint32_t arm_imm; - if ((int32_t)imm < 0 && imm != 0x80000000) - { - host_arm_CMP_IMM(block, src_reg, -(int32_t)imm); - } - else if (get_arm_imm(imm, &arm_imm)) - { - codegen_addlong(block, COND_AL | OPCODE_CMN_IMM | Rn(src_reg) | arm_imm); - } - else - { - host_arm_MOV_IMM(block, REG_TEMP, imm); - host_arm_CMN_REG_LSL(block, src_reg, REG_TEMP, 0); - } + if ((int32_t) imm < 0 && imm != 0x80000000) { + host_arm_CMP_IMM(block, src_reg, -(int32_t) imm); + } else if (get_arm_imm(imm, &arm_imm)) { + codegen_addlong(block, COND_AL | OPCODE_CMN_IMM | Rn(src_reg) | arm_imm); + } else { + host_arm_MOV_IMM(block, REG_TEMP, imm); + host_arm_CMN_REG_LSL(block, src_reg, REG_TEMP, 0); + } } -void host_arm_CMN_REG_LSL(codeblock_t *block, int src_reg_n, int src_reg_m, int shift) +void +host_arm_CMN_REG_LSL(codeblock_t *block, int src_reg_n, int src_reg_m, int shift) { - codegen_addlong(block, COND_AL | OPCODE_CMN_REG | Rn(src_reg_n) | Rm(src_reg_m) | SHIFT_LSL_IMM(shift)); + codegen_addlong(block, COND_AL | OPCODE_CMN_REG | Rn(src_reg_n) | Rm(src_reg_m) | SHIFT_LSL_IMM(shift)); } -void host_arm_CMP_IMM(codeblock_t *block, int src_reg, uint32_t imm) +void +host_arm_CMP_IMM(codeblock_t *block, int src_reg, uint32_t imm) { - uint32_t arm_imm; + uint32_t arm_imm; - if ((int32_t)imm < 0 && imm != 0x80000000) - { - host_arm_CMN_IMM(block, src_reg, -(int32_t)imm); - } - else if (get_arm_imm(imm, &arm_imm)) - { - codegen_addlong(block, COND_AL | OPCODE_CMP_IMM | Rn(src_reg) | arm_imm); - } - else - { - host_arm_MOV_IMM(block, REG_TEMP, imm); - host_arm_CMP_REG_LSL(block, src_reg, REG_TEMP, 0); - } + if ((int32_t) imm < 0 && imm != 0x80000000) { + host_arm_CMN_IMM(block, src_reg, -(int32_t) imm); + } else if (get_arm_imm(imm, &arm_imm)) { + codegen_addlong(block, COND_AL | OPCODE_CMP_IMM | Rn(src_reg) | arm_imm); + } else { + host_arm_MOV_IMM(block, REG_TEMP, imm); + host_arm_CMP_REG_LSL(block, src_reg, REG_TEMP, 0); + } } -void host_arm_CMP_REG_LSL(codeblock_t *block, int src_reg_n, int src_reg_m, int shift) +void +host_arm_CMP_REG_LSL(codeblock_t *block, int src_reg_n, int src_reg_m, int shift) { - codegen_addlong(block, COND_AL | OPCODE_CMP_REG | Rn(src_reg_n) | Rm(src_reg_m) | SHIFT_LSL_IMM(shift)); + codegen_addlong(block, COND_AL | OPCODE_CMP_REG | Rn(src_reg_n) | Rm(src_reg_m) | SHIFT_LSL_IMM(shift)); } -void host_arm_EOR_IMM(codeblock_t *block, int dst_reg, int src_reg, uint32_t imm) +void +host_arm_EOR_IMM(codeblock_t *block, int dst_reg, int src_reg, uint32_t imm) { - uint32_t arm_imm; + uint32_t arm_imm; - if (get_arm_imm(imm, &arm_imm)) - { - codegen_addlong(block, COND_AL | OPCODE_EOR_IMM | Rd(dst_reg) | Rn(src_reg) | arm_imm); - } - else - { - host_arm_MOV_IMM(block, REG_TEMP, imm); - host_arm_EOR_REG_LSL(block, dst_reg, src_reg, REG_TEMP, 0); - } + if (get_arm_imm(imm, &arm_imm)) { + codegen_addlong(block, COND_AL | OPCODE_EOR_IMM | Rd(dst_reg) | Rn(src_reg) | arm_imm); + } else { + host_arm_MOV_IMM(block, REG_TEMP, imm); + host_arm_EOR_REG_LSL(block, dst_reg, src_reg, REG_TEMP, 0); + } } -void host_arm_EOR_REG_LSL(codeblock_t *block, int dst_reg, int src_reg_n, int src_reg_m, int shift) +void +host_arm_EOR_REG_LSL(codeblock_t *block, int dst_reg, int src_reg_n, int src_reg_m, int shift) { - codegen_addlong(block, COND_AL | OPCODE_EOR_REG | Rd(dst_reg) | Rn(src_reg_n) | Rm(src_reg_m) | SHIFT_LSL_IMM(shift)); + codegen_addlong(block, COND_AL | OPCODE_EOR_REG | Rd(dst_reg) | Rn(src_reg_n) | Rm(src_reg_m) | SHIFT_LSL_IMM(shift)); } -void host_arm_LDMIA_WB(codeblock_t *block, int addr_reg, uint32_t reg_mask) +void +host_arm_LDMIA_WB(codeblock_t *block, int addr_reg, uint32_t reg_mask) { - codegen_addlong(block, COND_AL | OPCODE_LDMIA_WB | Rn(addr_reg) | reg_mask); + codegen_addlong(block, COND_AL | OPCODE_LDMIA_WB | Rn(addr_reg) | reg_mask); } -void host_arm_LDR_IMM(codeblock_t *block, int dst_reg, int addr_reg, int offset) +void +host_arm_LDR_IMM(codeblock_t *block, int dst_reg, int addr_reg, int offset) { - codegen_addlong(block, COND_AL | OPCODE_LDR_IMM | Rn(addr_reg) | Rd(dst_reg) | arm_data_offset(offset)); + codegen_addlong(block, COND_AL | OPCODE_LDR_IMM | Rn(addr_reg) | Rd(dst_reg) | arm_data_offset(offset)); } -void host_arm_LDR_IMM_POST(codeblock_t *block, int dst_reg, int addr_reg, int offset) +void +host_arm_LDR_IMM_POST(codeblock_t *block, int dst_reg, int addr_reg, int offset) { - codegen_addlong(block, COND_AL | OPCODE_LDR_IMM_POST | Rn(addr_reg) | Rd(dst_reg) | arm_data_offset(offset)); + codegen_addlong(block, COND_AL | OPCODE_LDR_IMM_POST | Rn(addr_reg) | Rd(dst_reg) | arm_data_offset(offset)); } -void host_arm_LDR_REG_LSL(codeblock_t *block, int dst_reg, int addr_reg, int offset_reg, int shift) +void +host_arm_LDR_REG_LSL(codeblock_t *block, int dst_reg, int addr_reg, int offset_reg, int shift) { - codegen_addlong(block, COND_AL | OPCODE_LDR_REG | Rn(addr_reg) | Rd(dst_reg) | Rm(offset_reg) | SHIFT_LSL_IMM(shift)); + codegen_addlong(block, COND_AL | OPCODE_LDR_REG | Rn(addr_reg) | Rd(dst_reg) | Rm(offset_reg) | SHIFT_LSL_IMM(shift)); } -void host_arm_LDRB_ABS(codeblock_t *block, int dst_reg, void *p) +void +host_arm_LDRB_ABS(codeblock_t *block, int dst_reg, void *p) { - if (in_range(p, &cpu_state)) - host_arm_LDRB_IMM(block, dst_reg, REG_CPUSTATE, (uintptr_t)p - (uintptr_t)&cpu_state); - else - fatal("LDRB_ABS - not in range\n"); + if (in_range(p, &cpu_state)) + host_arm_LDRB_IMM(block, dst_reg, REG_CPUSTATE, (uintptr_t) p - (uintptr_t) &cpu_state); + else + fatal("LDRB_ABS - not in range\n"); } -void host_arm_LDRB_IMM(codeblock_t *block, int dst_reg, int addr_reg, int offset) +void +host_arm_LDRB_IMM(codeblock_t *block, int dst_reg, int addr_reg, int offset) { - codegen_addlong(block, COND_AL | OPCODE_LDRB_IMM | Rn(addr_reg) | Rd(dst_reg) | arm_data_offset(offset)); + codegen_addlong(block, COND_AL | OPCODE_LDRB_IMM | Rn(addr_reg) | Rd(dst_reg) | arm_data_offset(offset)); } -void host_arm_LDRB_REG_LSL(codeblock_t *block, int dst_reg, int addr_reg, int offset_reg, int shift) +void +host_arm_LDRB_REG_LSL(codeblock_t *block, int dst_reg, int addr_reg, int offset_reg, int shift) { - codegen_addlong(block, COND_AL | OPCODE_LDRB_REG | Rn(addr_reg) | Rd(dst_reg) | Rm(offset_reg) | SHIFT_LSL_IMM(shift)); + codegen_addlong(block, COND_AL | OPCODE_LDRB_REG | Rn(addr_reg) | Rd(dst_reg) | Rm(offset_reg) | SHIFT_LSL_IMM(shift)); } -void host_arm_LDRH_IMM(codeblock_t *block, int dst_reg, int addr_reg, int offset) +void +host_arm_LDRH_IMM(codeblock_t *block, int dst_reg, int addr_reg, int offset) { - codegen_addlong(block, COND_AL | OPCODE_LDRH_IMM | Rn(addr_reg) | Rd(dst_reg) | LDRH_IMM(offset)); + codegen_addlong(block, COND_AL | OPCODE_LDRH_IMM | Rn(addr_reg) | Rd(dst_reg) | LDRH_IMM(offset)); } -void host_arm_LDRH_REG(codeblock_t *block, int dst_reg, int addr_reg, int offset_reg) +void +host_arm_LDRH_REG(codeblock_t *block, int dst_reg, int addr_reg, int offset_reg) { - codegen_addlong(block, COND_AL | OPCODE_LDRH_REG | Rn(addr_reg) | Rd(dst_reg) | Rm(offset_reg)); + codegen_addlong(block, COND_AL | OPCODE_LDRH_REG | Rn(addr_reg) | Rd(dst_reg) | Rm(offset_reg)); } -void host_arm_MOV_IMM(codeblock_t *block, int dst_reg, uint32_t imm) +void +host_arm_MOV_IMM(codeblock_t *block, int dst_reg, uint32_t imm) { - uint32_t arm_imm; + uint32_t arm_imm; - if (get_arm_imm(imm, &arm_imm)) - { - codegen_addlong(block, COND_AL | OPCODE_MOV_IMM | Rd(dst_reg) | arm_imm); - } - else - { - host_arm_MOVW_IMM(block, dst_reg, imm & 0xffff); - if (imm >> 16) - host_arm_MOVT_IMM(block, dst_reg, imm >> 16); - } + if (get_arm_imm(imm, &arm_imm)) { + codegen_addlong(block, COND_AL | OPCODE_MOV_IMM | Rd(dst_reg) | arm_imm); + } else { + host_arm_MOVW_IMM(block, dst_reg, imm & 0xffff); + if (imm >> 16) + host_arm_MOVT_IMM(block, dst_reg, imm >> 16); + } } -void host_arm_MOV_REG_ASR(codeblock_t *block, int dst_reg, int src_reg, int shift) +void +host_arm_MOV_REG_ASR(codeblock_t *block, int dst_reg, int src_reg, int shift) { - codegen_addlong(block, COND_AL | OPCODE_MOV_REG | Rd(dst_reg) | Rm(src_reg) | SHIFT_ASR_IMM(shift)); + codegen_addlong(block, COND_AL | OPCODE_MOV_REG | Rd(dst_reg) | Rm(src_reg) | SHIFT_ASR_IMM(shift)); } -void host_arm_MOV_REG_ASR_REG(codeblock_t *block, int dst_reg, int src_reg, int shift_reg) +void +host_arm_MOV_REG_ASR_REG(codeblock_t *block, int dst_reg, int src_reg, int shift_reg) { - codegen_addlong(block, COND_AL | OPCODE_MOV_REG | Rd(dst_reg) | Rm(src_reg) | SHIFT_ASR_REG(shift_reg)); + codegen_addlong(block, COND_AL | OPCODE_MOV_REG | Rd(dst_reg) | Rm(src_reg) | SHIFT_ASR_REG(shift_reg)); } -void host_arm_MOV_REG_LSL(codeblock_t *block, int dst_reg, int src_reg, int shift) +void +host_arm_MOV_REG_LSL(codeblock_t *block, int dst_reg, int src_reg, int shift) { - codegen_addlong(block, COND_AL | OPCODE_MOV_REG | Rd(dst_reg) | Rm(src_reg) | SHIFT_LSL_IMM(shift)); + codegen_addlong(block, COND_AL | OPCODE_MOV_REG | Rd(dst_reg) | Rm(src_reg) | SHIFT_LSL_IMM(shift)); } -void host_arm_MOV_REG_LSL_REG(codeblock_t *block, int dst_reg, int src_reg, int shift_reg) +void +host_arm_MOV_REG_LSL_REG(codeblock_t *block, int dst_reg, int src_reg, int shift_reg) { - codegen_addlong(block, COND_AL | OPCODE_MOV_REG | Rd(dst_reg) | Rm(src_reg) | SHIFT_LSL_REG(shift_reg)); + codegen_addlong(block, COND_AL | OPCODE_MOV_REG | Rd(dst_reg) | Rm(src_reg) | SHIFT_LSL_REG(shift_reg)); } -void host_arm_MOV_REG_LSR(codeblock_t *block, int dst_reg, int src_reg, int shift) +void +host_arm_MOV_REG_LSR(codeblock_t *block, int dst_reg, int src_reg, int shift) { - codegen_addlong(block, COND_AL | OPCODE_MOV_REG | Rd(dst_reg) | Rm(src_reg) | SHIFT_LSR_IMM(shift)); + codegen_addlong(block, COND_AL | OPCODE_MOV_REG | Rd(dst_reg) | Rm(src_reg) | SHIFT_LSR_IMM(shift)); } -void host_arm_MOV_REG_LSR_REG(codeblock_t *block, int dst_reg, int src_reg, int shift_reg) +void +host_arm_MOV_REG_LSR_REG(codeblock_t *block, int dst_reg, int src_reg, int shift_reg) { - codegen_addlong(block, COND_AL | OPCODE_MOV_REG | Rd(dst_reg) | Rm(src_reg) | SHIFT_LSR_REG(shift_reg)); + codegen_addlong(block, COND_AL | OPCODE_MOV_REG | Rd(dst_reg) | Rm(src_reg) | SHIFT_LSR_REG(shift_reg)); } -void host_arm_MOV_REG_ROR(codeblock_t *block, int dst_reg, int src_reg, int shift) +void +host_arm_MOV_REG_ROR(codeblock_t *block, int dst_reg, int src_reg, int shift) { - codegen_addlong(block, COND_AL | OPCODE_MOV_REG | Rd(dst_reg) | Rm(src_reg) | SHIFT_ROR_IMM(shift)); + codegen_addlong(block, COND_AL | OPCODE_MOV_REG | Rd(dst_reg) | Rm(src_reg) | SHIFT_ROR_IMM(shift)); } -void host_arm_MOV_REG_ROR_REG(codeblock_t *block, int dst_reg, int src_reg, int shift_reg) +void +host_arm_MOV_REG_ROR_REG(codeblock_t *block, int dst_reg, int src_reg, int shift_reg) { - codegen_addlong(block, COND_AL | OPCODE_MOV_REG | Rd(dst_reg) | Rm(src_reg) | SHIFT_ROR_REG(shift_reg)); + codegen_addlong(block, COND_AL | OPCODE_MOV_REG | Rd(dst_reg) | Rm(src_reg) | SHIFT_ROR_REG(shift_reg)); } -void host_arm_MOVT_IMM(codeblock_t *block, int dst_reg, uint16_t imm) +void +host_arm_MOVT_IMM(codeblock_t *block, int dst_reg, uint16_t imm) { - codegen_addlong(block, COND_AL | OPCODE_MOVT_IMM | Rd(dst_reg) | MOVT_IMM(imm)); + codegen_addlong(block, COND_AL | OPCODE_MOVT_IMM | Rd(dst_reg) | MOVT_IMM(imm)); } -void host_arm_MOVW_IMM(codeblock_t *block, int dst_reg, uint16_t imm) +void +host_arm_MOVW_IMM(codeblock_t *block, int dst_reg, uint16_t imm) { - codegen_addlong(block, COND_AL | OPCODE_MOVW_IMM | Rd(dst_reg) | MOVW_IMM(imm)); + codegen_addlong(block, COND_AL | OPCODE_MOVW_IMM | Rd(dst_reg) | MOVW_IMM(imm)); } -void host_arm_MVN_REG_LSL(codeblock_t *block, int dst_reg, int src_reg, int shift) +void +host_arm_MVN_REG_LSL(codeblock_t *block, int dst_reg, int src_reg, int shift) { - codegen_addlong(block, COND_AL | OPCODE_MVN_REG | Rd(dst_reg) | Rm(src_reg) | SHIFT_LSL_IMM(shift)); + codegen_addlong(block, COND_AL | OPCODE_MVN_REG | Rd(dst_reg) | Rm(src_reg) | SHIFT_LSL_IMM(shift)); } -void host_arm_ORR_IMM_cond(codeblock_t *block, uint32_t cond, int dst_reg, int src_reg, uint32_t imm) +void +host_arm_ORR_IMM_cond(codeblock_t *block, uint32_t cond, int dst_reg, int src_reg, uint32_t imm) { - uint32_t arm_imm; + uint32_t arm_imm; - if (get_arm_imm(imm, &arm_imm)) - { - codegen_addlong(block, cond | OPCODE_ORR_IMM | Rd(dst_reg) | Rn(src_reg) | arm_imm); - } - else - { - host_arm_MOV_IMM(block, REG_TEMP, imm); - host_arm_ORR_REG_LSL_cond(block, cond, dst_reg, src_reg, REG_TEMP, 0); - } + if (get_arm_imm(imm, &arm_imm)) { + codegen_addlong(block, cond | OPCODE_ORR_IMM | Rd(dst_reg) | Rn(src_reg) | arm_imm); + } else { + host_arm_MOV_IMM(block, REG_TEMP, imm); + host_arm_ORR_REG_LSL_cond(block, cond, dst_reg, src_reg, REG_TEMP, 0); + } } -void host_arm_ORR_REG_LSL_cond(codeblock_t *block, uint32_t cond, int dst_reg, int src_reg_n, int src_reg_m, int shift) +void +host_arm_ORR_REG_LSL_cond(codeblock_t *block, uint32_t cond, int dst_reg, int src_reg_n, int src_reg_m, int shift) { - codegen_addlong(block, cond | OPCODE_ORR_REG | Rd(dst_reg) | Rn(src_reg_n) | Rm(src_reg_m) | SHIFT_LSL_IMM(shift)); + codegen_addlong(block, cond | OPCODE_ORR_REG | Rd(dst_reg) | Rn(src_reg_n) | Rm(src_reg_m) | SHIFT_LSL_IMM(shift)); } -void host_arm_RSB_IMM(codeblock_t *block, int dst_reg, int src_reg, uint32_t imm) +void +host_arm_RSB_IMM(codeblock_t *block, int dst_reg, int src_reg, uint32_t imm) { - uint32_t arm_imm; + uint32_t arm_imm; - if (get_arm_imm(imm, &arm_imm)) - { - codegen_addlong(block, COND_AL | OPCODE_RSB_IMM | Rd(dst_reg) | Rn(src_reg) | arm_imm); - } - else - { - host_arm_MOV_IMM(block, REG_TEMP, imm); - host_arm_RSB_REG_LSL(block, dst_reg, src_reg, REG_TEMP, 0); - } + if (get_arm_imm(imm, &arm_imm)) { + codegen_addlong(block, COND_AL | OPCODE_RSB_IMM | Rd(dst_reg) | Rn(src_reg) | arm_imm); + } else { + host_arm_MOV_IMM(block, REG_TEMP, imm); + host_arm_RSB_REG_LSL(block, dst_reg, src_reg, REG_TEMP, 0); + } } -void host_arm_RSB_REG_LSL(codeblock_t *block, int dst_reg, int src_reg_n, int src_reg_m, int shift) +void +host_arm_RSB_REG_LSL(codeblock_t *block, int dst_reg, int src_reg_n, int src_reg_m, int shift) { - codegen_addlong(block, COND_AL | OPCODE_RSB_REG | Rd(dst_reg) | Rn(src_reg_n) | Rm(src_reg_m) | SHIFT_LSL_IMM(shift)); + codegen_addlong(block, COND_AL | OPCODE_RSB_REG | Rd(dst_reg) | Rn(src_reg_n) | Rm(src_reg_m) | SHIFT_LSL_IMM(shift)); } -void host_arm_RSB_REG_LSR(codeblock_t *block, int dst_reg, int src_reg_n, int src_reg_m, int shift) +void +host_arm_RSB_REG_LSR(codeblock_t *block, int dst_reg, int src_reg_n, int src_reg_m, int shift) { - codegen_addlong(block, COND_AL | OPCODE_RSB_REG | Rd(dst_reg) | Rn(src_reg_n) | Rm(src_reg_m) | SHIFT_LSR_IMM(shift)); + codegen_addlong(block, COND_AL | OPCODE_RSB_REG | Rd(dst_reg) | Rn(src_reg_n) | Rm(src_reg_m) | SHIFT_LSR_IMM(shift)); } -void host_arm_STMDB_WB(codeblock_t *block, int addr_reg, uint32_t reg_mask) +void +host_arm_STMDB_WB(codeblock_t *block, int addr_reg, uint32_t reg_mask) { - codegen_addlong(block, COND_AL | OPCODE_STMDB_WB | Rn(addr_reg) | reg_mask); + codegen_addlong(block, COND_AL | OPCODE_STMDB_WB | Rn(addr_reg) | reg_mask); } -void host_arm_STR_IMM(codeblock_t *block, int src_reg, int addr_reg, int offset) +void +host_arm_STR_IMM(codeblock_t *block, int src_reg, int addr_reg, int offset) { - codegen_addlong(block, COND_AL | OPCODE_STR_IMM | Rn(addr_reg) | Rd(src_reg) | arm_data_offset(offset)); + codegen_addlong(block, COND_AL | OPCODE_STR_IMM | Rn(addr_reg) | Rd(src_reg) | arm_data_offset(offset)); } -void host_arm_STR_IMM_WB(codeblock_t *block, int src_reg, int addr_reg, int offset) +void +host_arm_STR_IMM_WB(codeblock_t *block, int src_reg, int addr_reg, int offset) { - codegen_addlong(block, COND_AL | OPCODE_STR_IMM_WB | Rn(addr_reg) | Rd(src_reg) | arm_data_offset(offset)); + codegen_addlong(block, COND_AL | OPCODE_STR_IMM_WB | Rn(addr_reg) | Rd(src_reg) | arm_data_offset(offset)); } -void host_arm_STR_REG_LSL(codeblock_t *block, int src_reg, int addr_reg, int offset_reg, int shift) +void +host_arm_STR_REG_LSL(codeblock_t *block, int src_reg, int addr_reg, int offset_reg, int shift) { - codegen_addlong(block, COND_AL | OPCODE_STR_REG | Rn(addr_reg) | Rd(src_reg) | Rm(offset_reg) | SHIFT_LSL_IMM(shift)); + codegen_addlong(block, COND_AL | OPCODE_STR_REG | Rn(addr_reg) | Rd(src_reg) | Rm(offset_reg) | SHIFT_LSL_IMM(shift)); } -void host_arm_STRB_IMM(codeblock_t *block, int src_reg, int addr_reg, int offset) +void +host_arm_STRB_IMM(codeblock_t *block, int src_reg, int addr_reg, int offset) { - codegen_addlong(block, COND_AL | OPCODE_STRB_IMM | Rn(addr_reg) | Rd(src_reg) | arm_data_offset(offset)); + codegen_addlong(block, COND_AL | OPCODE_STRB_IMM | Rn(addr_reg) | Rd(src_reg) | arm_data_offset(offset)); } -void host_arm_STRB_REG_LSL(codeblock_t *block, int src_reg, int addr_reg, int offset_reg, int shift) +void +host_arm_STRB_REG_LSL(codeblock_t *block, int src_reg, int addr_reg, int offset_reg, int shift) { - codegen_addlong(block, COND_AL | OPCODE_STRB_REG | Rn(addr_reg) | Rd(src_reg) | Rm(offset_reg) | SHIFT_LSL_IMM(shift)); + codegen_addlong(block, COND_AL | OPCODE_STRB_REG | Rn(addr_reg) | Rd(src_reg) | Rm(offset_reg) | SHIFT_LSL_IMM(shift)); } -void host_arm_STRH_IMM(codeblock_t *block, int dst_reg, int addr_reg, int offset) +void +host_arm_STRH_IMM(codeblock_t *block, int dst_reg, int addr_reg, int offset) { - codegen_addlong(block, COND_AL | OPCODE_STRH_IMM | Rn(addr_reg) | Rd(dst_reg) | STRH_IMM(offset)); + codegen_addlong(block, COND_AL | OPCODE_STRH_IMM | Rn(addr_reg) | Rd(dst_reg) | STRH_IMM(offset)); } -void host_arm_STRH_REG(codeblock_t *block, int src_reg, int addr_reg, int offset_reg) +void +host_arm_STRH_REG(codeblock_t *block, int src_reg, int addr_reg, int offset_reg) { - codegen_addlong(block, COND_AL | OPCODE_STRH_REG | Rn(addr_reg) | Rd(src_reg) | Rm(offset_reg)); + codegen_addlong(block, COND_AL | OPCODE_STRH_REG | Rn(addr_reg) | Rd(src_reg) | Rm(offset_reg)); } -void host_arm_SUB_IMM(codeblock_t *block, int dst_reg, int src_reg, uint32_t imm) +void +host_arm_SUB_IMM(codeblock_t *block, int dst_reg, int src_reg, uint32_t imm) { - uint32_t arm_imm; + uint32_t arm_imm; - if ((int32_t)imm < 0 && imm != 0x80000000) - { - host_arm_ADD_IMM(block, dst_reg, src_reg, -(int32_t)imm); - } - else if (get_arm_imm(imm, &arm_imm)) - { - codegen_addlong(block, COND_AL | OPCODE_SUB_IMM | Rd(dst_reg) | Rn(src_reg) | arm_imm); - } - else - { - host_arm_MOV_IMM(block, REG_TEMP, imm); - host_arm_SUB_REG_LSL(block, dst_reg, src_reg, REG_TEMP, 0); - } + if ((int32_t) imm < 0 && imm != 0x80000000) { + host_arm_ADD_IMM(block, dst_reg, src_reg, -(int32_t) imm); + } else if (get_arm_imm(imm, &arm_imm)) { + codegen_addlong(block, COND_AL | OPCODE_SUB_IMM | Rd(dst_reg) | Rn(src_reg) | arm_imm); + } else { + host_arm_MOV_IMM(block, REG_TEMP, imm); + host_arm_SUB_REG_LSL(block, dst_reg, src_reg, REG_TEMP, 0); + } } -void host_arm_SUB_REG_LSL(codeblock_t *block, int dst_reg, int src_reg_n, int src_reg_m, int shift) +void +host_arm_SUB_REG_LSL(codeblock_t *block, int dst_reg, int src_reg_n, int src_reg_m, int shift) { - codegen_addlong(block, COND_AL | OPCODE_SUB_REG | Rd(dst_reg) | Rn(src_reg_n) | Rm(src_reg_m) | SHIFT_LSL_IMM(shift)); + codegen_addlong(block, COND_AL | OPCODE_SUB_REG | Rd(dst_reg) | Rn(src_reg_n) | Rm(src_reg_m) | SHIFT_LSL_IMM(shift)); } -void host_arm_SUB_REG_LSR(codeblock_t *block, int dst_reg, int src_reg_n, int src_reg_m, int shift) +void +host_arm_SUB_REG_LSR(codeblock_t *block, int dst_reg, int src_reg_n, int src_reg_m, int shift) { - codegen_addlong(block, COND_AL | OPCODE_SUB_REG | Rd(dst_reg) | Rn(src_reg_n) | Rm(src_reg_m) | SHIFT_LSR_IMM(shift)); + codegen_addlong(block, COND_AL | OPCODE_SUB_REG | Rd(dst_reg) | Rn(src_reg_n) | Rm(src_reg_m) | SHIFT_LSR_IMM(shift)); } -void host_arm_SXTB(codeblock_t *block, int dst_reg, int src_reg, int rotate) +void +host_arm_SXTB(codeblock_t *block, int dst_reg, int src_reg, int rotate) { - codegen_addlong(block, OPCODE_SXTB | Rd(dst_reg) | Rm(src_reg) | UXTB_ROTATE(rotate)); + codegen_addlong(block, OPCODE_SXTB | Rd(dst_reg) | Rm(src_reg) | UXTB_ROTATE(rotate)); } -void host_arm_SXTH(codeblock_t *block, int dst_reg, int src_reg, int rotate) +void +host_arm_SXTH(codeblock_t *block, int dst_reg, int src_reg, int rotate) { - codegen_addlong(block, OPCODE_SXTH | Rd(dst_reg) | Rm(src_reg) | UXTB_ROTATE(rotate)); + codegen_addlong(block, OPCODE_SXTH | Rd(dst_reg) | Rm(src_reg) | UXTB_ROTATE(rotate)); } -void host_arm_TST_IMM(codeblock_t *block, int src_reg, uint32_t imm) +void +host_arm_TST_IMM(codeblock_t *block, int src_reg, uint32_t imm) { - uint32_t arm_imm; + uint32_t arm_imm; - if (get_arm_imm(imm, &arm_imm)) - { - codegen_addlong(block, COND_AL | OPCODE_TST_IMM | Rn(src_reg) | arm_imm); - } - else - { - host_arm_MOV_IMM(block, REG_TEMP, imm); - host_arm_TST_REG(block, src_reg, REG_TEMP); - } + if (get_arm_imm(imm, &arm_imm)) { + codegen_addlong(block, COND_AL | OPCODE_TST_IMM | Rn(src_reg) | arm_imm); + } else { + host_arm_MOV_IMM(block, REG_TEMP, imm); + host_arm_TST_REG(block, src_reg, REG_TEMP); + } } -void host_arm_TST_REG(codeblock_t *block, int src_reg1, int src_reg2) +void +host_arm_TST_REG(codeblock_t *block, int src_reg1, int src_reg2) { - codegen_addlong(block, COND_AL | OPCODE_TST_REG | Rn(src_reg1) | Rm(src_reg2)); + codegen_addlong(block, COND_AL | OPCODE_TST_REG | Rn(src_reg1) | Rm(src_reg2)); } -void host_arm_UADD8(codeblock_t *block, int dst_reg, int src_reg_a, int src_reg_b) +void +host_arm_UADD8(codeblock_t *block, int dst_reg, int src_reg_a, int src_reg_b) { - codegen_addlong(block, COND_AL | OPCODE_UADD8 | Rd(dst_reg) | Rn(src_reg_a) | Rm(src_reg_b)); + codegen_addlong(block, COND_AL | OPCODE_UADD8 | Rd(dst_reg) | Rn(src_reg_a) | Rm(src_reg_b)); } -void host_arm_UADD16(codeblock_t *block, int dst_reg, int src_reg_a, int src_reg_b) +void +host_arm_UADD16(codeblock_t *block, int dst_reg, int src_reg_a, int src_reg_b) { - codegen_addlong(block, COND_AL | OPCODE_UADD16 | Rd(dst_reg) | Rn(src_reg_a) | Rm(src_reg_b)); + codegen_addlong(block, COND_AL | OPCODE_UADD16 | Rd(dst_reg) | Rn(src_reg_a) | Rm(src_reg_b)); } -void host_arm_USUB8(codeblock_t *block, int dst_reg, int src_reg_a, int src_reg_b) +void +host_arm_USUB8(codeblock_t *block, int dst_reg, int src_reg_a, int src_reg_b) { - codegen_addlong(block, COND_AL | OPCODE_USUB8 | Rd(dst_reg) | Rn(src_reg_a) | Rm(src_reg_b)); + codegen_addlong(block, COND_AL | OPCODE_USUB8 | Rd(dst_reg) | Rn(src_reg_a) | Rm(src_reg_b)); } -void host_arm_USUB16(codeblock_t *block, int dst_reg, int src_reg_a, int src_reg_b) +void +host_arm_USUB16(codeblock_t *block, int dst_reg, int src_reg_a, int src_reg_b) { - codegen_addlong(block, COND_AL | OPCODE_USUB16 | Rd(dst_reg) | Rn(src_reg_a) | Rm(src_reg_b)); + codegen_addlong(block, COND_AL | OPCODE_USUB16 | Rd(dst_reg) | Rn(src_reg_a) | Rm(src_reg_b)); } -void host_arm_UXTB(codeblock_t *block, int dst_reg, int src_reg, int rotate) +void +host_arm_UXTB(codeblock_t *block, int dst_reg, int src_reg, int rotate) { - codegen_addlong(block, OPCODE_UXTB | Rd(dst_reg) | Rm(src_reg) | UXTB_ROTATE(rotate)); + codegen_addlong(block, OPCODE_UXTB | Rd(dst_reg) | Rm(src_reg) | UXTB_ROTATE(rotate)); } -void host_arm_UXTH(codeblock_t *block, int dst_reg, int src_reg, int rotate) +void +host_arm_UXTH(codeblock_t *block, int dst_reg, int src_reg, int rotate) { - codegen_addlong(block, OPCODE_UXTH | Rd(dst_reg) | Rm(src_reg) | UXTB_ROTATE(rotate)); + codegen_addlong(block, OPCODE_UXTH | Rd(dst_reg) | Rm(src_reg) | UXTB_ROTATE(rotate)); } -void host_arm_VABS_D(codeblock_t *block, int dest_reg, int src_reg) +void +host_arm_VABS_D(codeblock_t *block, int dest_reg, int src_reg) { - codegen_addlong(block, COND_AL | OPCODE_VABS_D | Vd(dest_reg) | Vm(src_reg)); + codegen_addlong(block, COND_AL | OPCODE_VABS_D | Vd(dest_reg) | Vm(src_reg)); } -void host_arm_VADD_D(codeblock_t *block, int dst_reg, int src_reg_n, int src_reg_m) +void +host_arm_VADD_D(codeblock_t *block, int dst_reg, int src_reg_n, int src_reg_m) { - codegen_addlong(block, COND_AL | OPCODE_VADD | Rd(dst_reg) | Rn(src_reg_n) | Rm(src_reg_m)); + codegen_addlong(block, COND_AL | OPCODE_VADD | Rd(dst_reg) | Rn(src_reg_n) | Rm(src_reg_m)); } -void host_arm_VADD_F32(codeblock_t *block, int dst_reg, int src_reg_n, int src_reg_m) +void +host_arm_VADD_F32(codeblock_t *block, int dst_reg, int src_reg_n, int src_reg_m) { - codegen_addlong(block, COND_AL | OPCODE_VADD_F32 | Rd(dst_reg) | Rn(src_reg_n) | Rm(src_reg_m)); + codegen_addlong(block, COND_AL | OPCODE_VADD_F32 | Rd(dst_reg) | Rn(src_reg_n) | Rm(src_reg_m)); } -void host_arm_VADD_I8(codeblock_t *block, int dst_reg, int src_reg_n, int src_reg_m) +void +host_arm_VADD_I8(codeblock_t *block, int dst_reg, int src_reg_n, int src_reg_m) { - codegen_addlong(block, OPCODE_VADD_I8 | Rd(dst_reg) | Rn(src_reg_n) | Rm(src_reg_m)); + codegen_addlong(block, OPCODE_VADD_I8 | Rd(dst_reg) | Rn(src_reg_n) | Rm(src_reg_m)); } -void host_arm_VADD_I16(codeblock_t *block, int dst_reg, int src_reg_n, int src_reg_m) +void +host_arm_VADD_I16(codeblock_t *block, int dst_reg, int src_reg_n, int src_reg_m) { - codegen_addlong(block, OPCODE_VADD_I16 | Rd(dst_reg) | Rn(src_reg_n) | Rm(src_reg_m)); + codegen_addlong(block, OPCODE_VADD_I16 | Rd(dst_reg) | Rn(src_reg_n) | Rm(src_reg_m)); } -void host_arm_VADD_I32(codeblock_t *block, int dst_reg, int src_reg_n, int src_reg_m) +void +host_arm_VADD_I32(codeblock_t *block, int dst_reg, int src_reg_n, int src_reg_m) { - codegen_addlong(block, OPCODE_VADD_I32 | Rd(dst_reg) | Rn(src_reg_n) | Rm(src_reg_m)); + codegen_addlong(block, OPCODE_VADD_I32 | Rd(dst_reg) | Rn(src_reg_n) | Rm(src_reg_m)); } -void host_arm_VAND_D(codeblock_t *block, int dst_reg, int src_reg_n, int src_reg_m) +void +host_arm_VAND_D(codeblock_t *block, int dst_reg, int src_reg_n, int src_reg_m) { - codegen_addlong(block, OPCODE_VAND_D | Rd(dst_reg) | Rn(src_reg_n) | Rm(src_reg_m)); + codegen_addlong(block, OPCODE_VAND_D | Rd(dst_reg) | Rn(src_reg_n) | Rm(src_reg_m)); } -void host_arm_VBIC_D(codeblock_t *block, int dst_reg, int src_reg_n, int src_reg_m) +void +host_arm_VBIC_D(codeblock_t *block, int dst_reg, int src_reg_n, int src_reg_m) { - codegen_addlong(block, OPCODE_VBIC_D | Rd(dst_reg) | Rn(src_reg_n) | Rm(src_reg_m)); + codegen_addlong(block, OPCODE_VBIC_D | Rd(dst_reg) | Rn(src_reg_n) | Rm(src_reg_m)); } -void host_arm_VCMP_D(codeblock_t *block, int src_reg_d, int src_reg_m) +void +host_arm_VCMP_D(codeblock_t *block, int src_reg_d, int src_reg_m) { - codegen_addlong(block, COND_AL | OPCODE_VCMP_D | Rd(src_reg_d) | Rm(src_reg_m)); + codegen_addlong(block, COND_AL | OPCODE_VCMP_D | Rd(src_reg_d) | Rm(src_reg_m)); } -void host_arm_VCEQ_F32(codeblock_t *block, int dst_reg, int src_reg_n, int src_reg_m) +void +host_arm_VCEQ_F32(codeblock_t *block, int dst_reg, int src_reg_n, int src_reg_m) { - codegen_addlong(block, OPCODE_VCEQ_F32 | Rd(dst_reg) | Rn(src_reg_n) | Rm(src_reg_m)); + codegen_addlong(block, OPCODE_VCEQ_F32 | Rd(dst_reg) | Rn(src_reg_n) | Rm(src_reg_m)); } -void host_arm_VCEQ_I8(codeblock_t *block, int dst_reg, int src_reg_n, int src_reg_m) +void +host_arm_VCEQ_I8(codeblock_t *block, int dst_reg, int src_reg_n, int src_reg_m) { - codegen_addlong(block, OPCODE_VCEQ_I8 | Rd(dst_reg) | Rn(src_reg_n) | Rm(src_reg_m)); + codegen_addlong(block, OPCODE_VCEQ_I8 | Rd(dst_reg) | Rn(src_reg_n) | Rm(src_reg_m)); } -void host_arm_VCEQ_I16(codeblock_t *block, int dst_reg, int src_reg_n, int src_reg_m) +void +host_arm_VCEQ_I16(codeblock_t *block, int dst_reg, int src_reg_n, int src_reg_m) { - codegen_addlong(block, OPCODE_VCEQ_I16 | Rd(dst_reg) | Rn(src_reg_n) | Rm(src_reg_m)); + codegen_addlong(block, OPCODE_VCEQ_I16 | Rd(dst_reg) | Rn(src_reg_n) | Rm(src_reg_m)); } -void host_arm_VCEQ_I32(codeblock_t *block, int dst_reg, int src_reg_n, int src_reg_m) +void +host_arm_VCEQ_I32(codeblock_t *block, int dst_reg, int src_reg_n, int src_reg_m) { - codegen_addlong(block, OPCODE_VCEQ_I32 | Rd(dst_reg) | Rn(src_reg_n) | Rm(src_reg_m)); + codegen_addlong(block, OPCODE_VCEQ_I32 | Rd(dst_reg) | Rn(src_reg_n) | Rm(src_reg_m)); } -void host_arm_VCGE_F32(codeblock_t *block, int dst_reg, int src_reg_n, int src_reg_m) +void +host_arm_VCGE_F32(codeblock_t *block, int dst_reg, int src_reg_n, int src_reg_m) { - codegen_addlong(block, OPCODE_VCGE_F32 | Rd(dst_reg) | Rn(src_reg_n) | Rm(src_reg_m)); + codegen_addlong(block, OPCODE_VCGE_F32 | Rd(dst_reg) | Rn(src_reg_n) | Rm(src_reg_m)); } -void host_arm_VCGT_F32(codeblock_t *block, int dst_reg, int src_reg_n, int src_reg_m) +void +host_arm_VCGT_F32(codeblock_t *block, int dst_reg, int src_reg_n, int src_reg_m) { - codegen_addlong(block, OPCODE_VCGT_F32 | Rd(dst_reg) | Rn(src_reg_n) | Rm(src_reg_m)); + codegen_addlong(block, OPCODE_VCGT_F32 | Rd(dst_reg) | Rn(src_reg_n) | Rm(src_reg_m)); } -void host_arm_VCGT_S8(codeblock_t *block, int dst_reg, int src_reg_n, int src_reg_m) +void +host_arm_VCGT_S8(codeblock_t *block, int dst_reg, int src_reg_n, int src_reg_m) { - codegen_addlong(block, OPCODE_VCGT_S8 | Rd(dst_reg) | Rn(src_reg_n) | Rm(src_reg_m)); + codegen_addlong(block, OPCODE_VCGT_S8 | Rd(dst_reg) | Rn(src_reg_n) | Rm(src_reg_m)); } -void host_arm_VCGT_S16(codeblock_t *block, int dst_reg, int src_reg_n, int src_reg_m) +void +host_arm_VCGT_S16(codeblock_t *block, int dst_reg, int src_reg_n, int src_reg_m) { - codegen_addlong(block, OPCODE_VCGT_S16 | Rd(dst_reg) | Rn(src_reg_n) | Rm(src_reg_m)); + codegen_addlong(block, OPCODE_VCGT_S16 | Rd(dst_reg) | Rn(src_reg_n) | Rm(src_reg_m)); } -void host_arm_VCGT_S32(codeblock_t *block, int dst_reg, int src_reg_n, int src_reg_m) +void +host_arm_VCGT_S32(codeblock_t *block, int dst_reg, int src_reg_n, int src_reg_m) { - codegen_addlong(block, OPCODE_VCGT_S32 | Rd(dst_reg) | Rn(src_reg_n) | Rm(src_reg_m)); + codegen_addlong(block, OPCODE_VCGT_S32 | Rd(dst_reg) | Rn(src_reg_n) | Rm(src_reg_m)); } -void host_arm_VCVT_D_IS(codeblock_t *block, int dest_reg, int src_reg) +void +host_arm_VCVT_D_IS(codeblock_t *block, int dest_reg, int src_reg) { - codegen_addlong(block, COND_AL | OPCODE_VCVT_D_IS | Vd(dest_reg) | Vm(src_reg)); + codegen_addlong(block, COND_AL | OPCODE_VCVT_D_IS | Vd(dest_reg) | Vm(src_reg)); } -void host_arm_VCVT_D_S(codeblock_t *block, int dest_reg, int src_reg) +void +host_arm_VCVT_D_S(codeblock_t *block, int dest_reg, int src_reg) { - codegen_addlong(block, COND_AL | OPCODE_VCVT_D_S | Vd(dest_reg) | Vm(src_reg)); + codegen_addlong(block, COND_AL | OPCODE_VCVT_D_S | Vd(dest_reg) | Vm(src_reg)); } -void host_arm_VCVT_F32_S32(codeblock_t *block, int dest_reg, int src_reg) +void +host_arm_VCVT_F32_S32(codeblock_t *block, int dest_reg, int src_reg) { - codegen_addlong(block, COND_AL | OPCODE_VCVT_F32_S32 | Vd(dest_reg) | Vm(src_reg)); + codegen_addlong(block, COND_AL | OPCODE_VCVT_F32_S32 | Vd(dest_reg) | Vm(src_reg)); } -void host_arm_VCVT_IS_D(codeblock_t *block, int dest_reg, int src_reg) +void +host_arm_VCVT_IS_D(codeblock_t *block, int dest_reg, int src_reg) { - codegen_addlong(block, COND_AL | OPCODE_VCVT_IS_D | Vd(dest_reg) | Vm(src_reg)); + codegen_addlong(block, COND_AL | OPCODE_VCVT_IS_D | Vd(dest_reg) | Vm(src_reg)); } -void host_arm_VCVT_S32_F32(codeblock_t *block, int dest_reg, int src_reg) +void +host_arm_VCVT_S32_F32(codeblock_t *block, int dest_reg, int src_reg) { - codegen_addlong(block, COND_AL | OPCODE_VCVT_S32_F32 | Vd(dest_reg) | Vm(src_reg)); + codegen_addlong(block, COND_AL | OPCODE_VCVT_S32_F32 | Vd(dest_reg) | Vm(src_reg)); } -void host_arm_VCVT_S_D(codeblock_t *block, int dest_reg, int src_reg) +void +host_arm_VCVT_S_D(codeblock_t *block, int dest_reg, int src_reg) { - codegen_addlong(block, COND_AL | OPCODE_VCVT_S_D | Vd(dest_reg) | Vm(src_reg)); + codegen_addlong(block, COND_AL | OPCODE_VCVT_S_D | Vd(dest_reg) | Vm(src_reg)); } -void host_arm_VCVTR_IS_D(codeblock_t *block, int dest_reg, int src_reg) +void +host_arm_VCVTR_IS_D(codeblock_t *block, int dest_reg, int src_reg) { - codegen_addlong(block, COND_AL | OPCODE_VCVTR_IS_D | Vd(dest_reg) | Vm(src_reg)); + codegen_addlong(block, COND_AL | OPCODE_VCVTR_IS_D | Vd(dest_reg) | Vm(src_reg)); } -void host_arm_VDIV_D(codeblock_t *block, int dst_reg, int src_reg_n, int src_reg_m) +void +host_arm_VDIV_D(codeblock_t *block, int dst_reg, int src_reg_n, int src_reg_m) { - codegen_addlong(block, COND_AL | OPCODE_VDIV | Rd(dst_reg) | Rn(src_reg_n) | Rm(src_reg_m)); + codegen_addlong(block, COND_AL | OPCODE_VDIV | Rd(dst_reg) | Rn(src_reg_n) | Rm(src_reg_m)); } -void host_arm_VDIV_S(codeblock_t *block, int dst_reg, int src_reg_n, int src_reg_m) +void +host_arm_VDIV_S(codeblock_t *block, int dst_reg, int src_reg_n, int src_reg_m) { - codegen_addlong(block, COND_AL | OPCODE_VDIV_S | Rd(dst_reg) | Rn(src_reg_n) | Rm(src_reg_m)); + codegen_addlong(block, COND_AL | OPCODE_VDIV_S | Rd(dst_reg) | Rn(src_reg_n) | Rm(src_reg_m)); } -void host_arm_VDUP_32(codeblock_t *block, int dst_reg, int src_reg_m, int imm) +void +host_arm_VDUP_32(codeblock_t *block, int dst_reg, int src_reg_m, int imm) { - codegen_addlong(block, COND_AL | OPCODE_VDUP_32 | Rd(dst_reg) | Rm(src_reg_m) | VDUP_32_IMM(imm)); + codegen_addlong(block, COND_AL | OPCODE_VDUP_32 | Rd(dst_reg) | Rm(src_reg_m) | VDUP_32_IMM(imm)); } -void host_arm_VEOR_D(codeblock_t *block, int dst_reg, int src_reg_n, int src_reg_m) +void +host_arm_VEOR_D(codeblock_t *block, int dst_reg, int src_reg_n, int src_reg_m) { - codegen_addlong(block, OPCODE_VEOR_D | Rd(dst_reg) | Rn(src_reg_n) | Rm(src_reg_m)); + codegen_addlong(block, OPCODE_VEOR_D | Rd(dst_reg) | Rn(src_reg_n) | Rm(src_reg_m)); } -void host_arm_VLDR_D(codeblock_t *block, int dest_reg, int base_reg, int offset) +void +host_arm_VLDR_D(codeblock_t *block, int dest_reg, int base_reg, int offset) { - if ((offset > 1020) || (offset & 3)) - fatal("VLDR_D bad offset %i\n", offset); - codegen_addlong(block, COND_AL | OPCODE_VLDR_D | Rd(dest_reg) | Rn(base_reg) | (offset >> 2)); + if ((offset > 1020) || (offset & 3)) + fatal("VLDR_D bad offset %i\n", offset); + codegen_addlong(block, COND_AL | OPCODE_VLDR_D | Rd(dest_reg) | Rn(base_reg) | (offset >> 2)); } -void host_arm_VLDR_S(codeblock_t *block, int dest_reg, int base_reg, int offset) +void +host_arm_VLDR_S(codeblock_t *block, int dest_reg, int base_reg, int offset) { - if ((offset > 1020) || (offset & 3)) - fatal("VLDR_S bad offset %i\n", offset); - codegen_addlong(block, COND_AL | OPCODE_VLDR_S | Rd(dest_reg) | Rn(base_reg) | (offset >> 2)); + if ((offset > 1020) || (offset & 3)) + fatal("VLDR_S bad offset %i\n", offset); + codegen_addlong(block, COND_AL | OPCODE_VLDR_S | Rd(dest_reg) | Rn(base_reg) | (offset >> 2)); } -void host_arm_VMOV_32_S(codeblock_t *block, int dest_reg, int src_reg) +void +host_arm_VMOV_32_S(codeblock_t *block, int dest_reg, int src_reg) { - codegen_addlong(block, COND_AL | OPCODE_VMOV_32_S | Rt(dest_reg) | Vn(src_reg)); + codegen_addlong(block, COND_AL | OPCODE_VMOV_32_S | Rt(dest_reg) | Vn(src_reg)); } -void host_arm_VMOV_64_D(codeblock_t *block, int dest_reg_low, int dest_reg_high, int src_reg) +void +host_arm_VMOV_64_D(codeblock_t *block, int dest_reg_low, int dest_reg_high, int src_reg) { - codegen_addlong(block, COND_AL | OPCODE_VMOV_64_D | Rt(dest_reg_low) | Rt2(dest_reg_high) | Vm(src_reg)); + codegen_addlong(block, COND_AL | OPCODE_VMOV_64_D | Rt(dest_reg_low) | Rt2(dest_reg_high) | Vm(src_reg)); } -void host_arm_VMOV_D_64(codeblock_t *block, int dest_reg, int src_reg_low, int src_reg_high) +void +host_arm_VMOV_D_64(codeblock_t *block, int dest_reg, int src_reg_low, int src_reg_high) { - codegen_addlong(block, COND_AL | OPCODE_VMOV_D_64 | Vm(dest_reg) | Rt(src_reg_low) | Rt2(src_reg_high)); + codegen_addlong(block, COND_AL | OPCODE_VMOV_D_64 | Vm(dest_reg) | Rt(src_reg_low) | Rt2(src_reg_high)); } -void host_arm_VMOV_S_32(codeblock_t *block, int dest_reg, int src_reg) +void +host_arm_VMOV_S_32(codeblock_t *block, int dest_reg, int src_reg) { - codegen_addlong(block, COND_AL | OPCODE_VMOV_S_32 | Vn(dest_reg) | Rt(src_reg)); + codegen_addlong(block, COND_AL | OPCODE_VMOV_S_32 | Vn(dest_reg) | Rt(src_reg)); } -void host_arm_VMOV_D_D(codeblock_t *block, int dest_reg, int src_reg) +void +host_arm_VMOV_D_D(codeblock_t *block, int dest_reg, int src_reg) { - codegen_addlong(block, COND_AL | OPCODE_VMOV_D_D | Vd(dest_reg) | Vm(src_reg)); + codegen_addlong(block, COND_AL | OPCODE_VMOV_D_D | Vd(dest_reg) | Vm(src_reg)); } -void host_arm_VMOVN_I32(codeblock_t *block, int dest_reg, int src_reg) +void +host_arm_VMOVN_I32(codeblock_t *block, int dest_reg, int src_reg) { - codegen_addlong(block, OPCODE_VMOVN_I32 | Vd(dest_reg) | Vm(src_reg)); + codegen_addlong(block, OPCODE_VMOVN_I32 | Vd(dest_reg) | Vm(src_reg)); } -void host_arm_VMOVN_I64(codeblock_t *block, int dest_reg, int src_reg) +void +host_arm_VMOVN_I64(codeblock_t *block, int dest_reg, int src_reg) { - codegen_addlong(block, OPCODE_VMOVN_I64 | Vd(dest_reg) | Vm(src_reg)); + codegen_addlong(block, OPCODE_VMOVN_I64 | Vd(dest_reg) | Vm(src_reg)); } -void host_arm_VMOV_F32_ONE(codeblock_t *block, int dst_reg) +void +host_arm_VMOV_F32_ONE(codeblock_t *block, int dst_reg) { - codegen_addlong(block, COND_AL | OPCODE_VMOV_F32_ONE | Rd(dst_reg)); + codegen_addlong(block, COND_AL | OPCODE_VMOV_F32_ONE | Rd(dst_reg)); } -void host_arm_VMSR_FPSCR(codeblock_t *block, int src_reg) +void +host_arm_VMSR_FPSCR(codeblock_t *block, int src_reg) { - codegen_addlong(block, COND_AL | OPCODE_VMSR_FPSCR | Rd(src_reg)); + codegen_addlong(block, COND_AL | OPCODE_VMSR_FPSCR | Rd(src_reg)); } -void host_arm_VMRS_APSR(codeblock_t *block) +void +host_arm_VMRS_APSR(codeblock_t *block) { - codegen_addlong(block, COND_AL | OPCODE_VMRS_APSR); + codegen_addlong(block, COND_AL | OPCODE_VMRS_APSR); } -void host_arm_VMAX_F32(codeblock_t *block, int dst_reg, int src_reg_n, int src_reg_m) +void +host_arm_VMAX_F32(codeblock_t *block, int dst_reg, int src_reg_n, int src_reg_m) { - codegen_addlong(block, OPCODE_VMAX_F32 | Rd(dst_reg) | Rn(src_reg_n) | Rm(src_reg_m)); + codegen_addlong(block, OPCODE_VMAX_F32 | Rd(dst_reg) | Rn(src_reg_n) | Rm(src_reg_m)); } -void host_arm_VMIN_F32(codeblock_t *block, int dst_reg, int src_reg_n, int src_reg_m) +void +host_arm_VMIN_F32(codeblock_t *block, int dst_reg, int src_reg_n, int src_reg_m) { - codegen_addlong(block, OPCODE_VMIN_F32 | Rd(dst_reg) | Rn(src_reg_n) | Rm(src_reg_m)); + codegen_addlong(block, OPCODE_VMIN_F32 | Rd(dst_reg) | Rn(src_reg_n) | Rm(src_reg_m)); } -void host_arm_VMUL_D(codeblock_t *block, int dst_reg, int src_reg_n, int src_reg_m) +void +host_arm_VMUL_D(codeblock_t *block, int dst_reg, int src_reg_n, int src_reg_m) { - codegen_addlong(block, COND_AL | OPCODE_VMUL | Rd(dst_reg) | Rn(src_reg_n) | Rm(src_reg_m)); + codegen_addlong(block, COND_AL | OPCODE_VMUL | Rd(dst_reg) | Rn(src_reg_n) | Rm(src_reg_m)); } -void host_arm_VMUL_F32(codeblock_t *block, int dst_reg, int src_reg_n, int src_reg_m) +void +host_arm_VMUL_F32(codeblock_t *block, int dst_reg, int src_reg_n, int src_reg_m) { - codegen_addlong(block, COND_AL | OPCODE_VMUL_F32 | Rd(dst_reg) | Rn(src_reg_n) | Rm(src_reg_m)); + codegen_addlong(block, COND_AL | OPCODE_VMUL_F32 | Rd(dst_reg) | Rn(src_reg_n) | Rm(src_reg_m)); } -void host_arm_VMUL_S16(codeblock_t *block, int dst_reg, int src_reg_n, int src_reg_m) +void +host_arm_VMUL_S16(codeblock_t *block, int dst_reg, int src_reg_n, int src_reg_m) { - codegen_addlong(block, OPCODE_VMUL_S16 | Rd(dst_reg) | Rn(src_reg_n) | Rm(src_reg_m)); + codegen_addlong(block, OPCODE_VMUL_S16 | Rd(dst_reg) | Rn(src_reg_n) | Rm(src_reg_m)); } -void host_arm_VMULL_S16(codeblock_t *block, int dst_reg, int src_reg_n, int src_reg_m) +void +host_arm_VMULL_S16(codeblock_t *block, int dst_reg, int src_reg_n, int src_reg_m) { - codegen_addlong(block, OPCODE_VMULL_S16 | Rd(dst_reg) | Rn(src_reg_n) | Rm(src_reg_m)); + codegen_addlong(block, OPCODE_VMULL_S16 | Rd(dst_reg) | Rn(src_reg_n) | Rm(src_reg_m)); } -void host_arm_VNEG_D(codeblock_t *block, int dest_reg, int src_reg) +void +host_arm_VNEG_D(codeblock_t *block, int dest_reg, int src_reg) { - codegen_addlong(block, COND_AL | OPCODE_VNEG_D | Vd(dest_reg) | Vm(src_reg)); + codegen_addlong(block, COND_AL | OPCODE_VNEG_D | Vd(dest_reg) | Vm(src_reg)); } -void host_arm_VORR_D(codeblock_t *block, int dst_reg, int src_reg_n, int src_reg_m) +void +host_arm_VORR_D(codeblock_t *block, int dst_reg, int src_reg_n, int src_reg_m) { - codegen_addlong(block, OPCODE_VORR_D | Rd(dst_reg) | Rn(src_reg_n) | Rm(src_reg_m)); + codegen_addlong(block, OPCODE_VORR_D | Rd(dst_reg) | Rn(src_reg_n) | Rm(src_reg_m)); } -void host_arm_VPADDL_S16(codeblock_t *block, int dst_reg, int src_reg) +void +host_arm_VPADDL_S16(codeblock_t *block, int dst_reg, int src_reg) { - codegen_addlong(block, OPCODE_VPADDL_S16 | Vd(dst_reg) | Vm(src_reg)); + codegen_addlong(block, OPCODE_VPADDL_S16 | Vd(dst_reg) | Vm(src_reg)); } -void host_arm_VPADDL_S32(codeblock_t *block, int dst_reg, int src_reg) +void +host_arm_VPADDL_S32(codeblock_t *block, int dst_reg, int src_reg) { - codegen_addlong(block, OPCODE_VPADDL_S32 | Vd(dst_reg) | Vm(src_reg)); + codegen_addlong(block, OPCODE_VPADDL_S32 | Vd(dst_reg) | Vm(src_reg)); } -void host_arm_VPADDL_Q_S32(codeblock_t *block, int dst_reg, int src_reg) +void +host_arm_VPADDL_Q_S32(codeblock_t *block, int dst_reg, int src_reg) { - codegen_addlong(block, OPCODE_VPADDL_Q_S32 | Vd(dst_reg) | Vm(src_reg)); + codegen_addlong(block, OPCODE_VPADDL_Q_S32 | Vd(dst_reg) | Vm(src_reg)); } -void host_arm_VQADD_S8(codeblock_t *block, int dst_reg, int src_reg_n, int src_reg_m) +void +host_arm_VQADD_S8(codeblock_t *block, int dst_reg, int src_reg_n, int src_reg_m) { - codegen_addlong(block, OPCODE_VQADD_S8 | Rd(dst_reg) | Rn(src_reg_n) | Rm(src_reg_m)); + codegen_addlong(block, OPCODE_VQADD_S8 | Rd(dst_reg) | Rn(src_reg_n) | Rm(src_reg_m)); } -void host_arm_VQADD_S16(codeblock_t *block, int dst_reg, int src_reg_n, int src_reg_m) +void +host_arm_VQADD_S16(codeblock_t *block, int dst_reg, int src_reg_n, int src_reg_m) { - codegen_addlong(block, OPCODE_VQADD_S16 | Rd(dst_reg) | Rn(src_reg_n) | Rm(src_reg_m)); + codegen_addlong(block, OPCODE_VQADD_S16 | Rd(dst_reg) | Rn(src_reg_n) | Rm(src_reg_m)); } -void host_arm_VQADD_U8(codeblock_t *block, int dst_reg, int src_reg_n, int src_reg_m) +void +host_arm_VQADD_U8(codeblock_t *block, int dst_reg, int src_reg_n, int src_reg_m) { - codegen_addlong(block, OPCODE_VQADD_U8 | Rd(dst_reg) | Rn(src_reg_n) | Rm(src_reg_m)); + codegen_addlong(block, OPCODE_VQADD_U8 | Rd(dst_reg) | Rn(src_reg_n) | Rm(src_reg_m)); } -void host_arm_VQADD_U16(codeblock_t *block, int dst_reg, int src_reg_n, int src_reg_m) +void +host_arm_VQADD_U16(codeblock_t *block, int dst_reg, int src_reg_n, int src_reg_m) { - codegen_addlong(block, OPCODE_VQADD_U16 | Rd(dst_reg) | Rn(src_reg_n) | Rm(src_reg_m)); + codegen_addlong(block, OPCODE_VQADD_U16 | Rd(dst_reg) | Rn(src_reg_n) | Rm(src_reg_m)); } -void host_arm_VQSUB_S8(codeblock_t *block, int dst_reg, int src_reg_n, int src_reg_m) +void +host_arm_VQSUB_S8(codeblock_t *block, int dst_reg, int src_reg_n, int src_reg_m) { - codegen_addlong(block, OPCODE_VQSUB_S8 | Rd(dst_reg) | Rn(src_reg_n) | Rm(src_reg_m)); + codegen_addlong(block, OPCODE_VQSUB_S8 | Rd(dst_reg) | Rn(src_reg_n) | Rm(src_reg_m)); } -void host_arm_VQSUB_S16(codeblock_t *block, int dst_reg, int src_reg_n, int src_reg_m) +void +host_arm_VQSUB_S16(codeblock_t *block, int dst_reg, int src_reg_n, int src_reg_m) { - codegen_addlong(block, OPCODE_VQSUB_S16 | Rd(dst_reg) | Rn(src_reg_n) | Rm(src_reg_m)); + codegen_addlong(block, OPCODE_VQSUB_S16 | Rd(dst_reg) | Rn(src_reg_n) | Rm(src_reg_m)); } -void host_arm_VQSUB_U8(codeblock_t *block, int dst_reg, int src_reg_n, int src_reg_m) +void +host_arm_VQSUB_U8(codeblock_t *block, int dst_reg, int src_reg_n, int src_reg_m) { - codegen_addlong(block, OPCODE_VQSUB_U8 | Rd(dst_reg) | Rn(src_reg_n) | Rm(src_reg_m)); + codegen_addlong(block, OPCODE_VQSUB_U8 | Rd(dst_reg) | Rn(src_reg_n) | Rm(src_reg_m)); } -void host_arm_VQSUB_U16(codeblock_t *block, int dst_reg, int src_reg_n, int src_reg_m) +void +host_arm_VQSUB_U16(codeblock_t *block, int dst_reg, int src_reg_n, int src_reg_m) { - codegen_addlong(block, OPCODE_VQSUB_U16 | Rd(dst_reg) | Rn(src_reg_n) | Rm(src_reg_m)); + codegen_addlong(block, OPCODE_VQSUB_U16 | Rd(dst_reg) | Rn(src_reg_n) | Rm(src_reg_m)); } -void host_arm_VQMOVN_S16(codeblock_t *block, int dst_reg, int src_reg) +void +host_arm_VQMOVN_S16(codeblock_t *block, int dst_reg, int src_reg) { - codegen_addlong(block, OPCODE_VQMOVN_S16 | Vd(dst_reg) | Vm(src_reg)); + codegen_addlong(block, OPCODE_VQMOVN_S16 | Vd(dst_reg) | Vm(src_reg)); } -void host_arm_VQMOVN_S32(codeblock_t *block, int dst_reg, int src_reg) +void +host_arm_VQMOVN_S32(codeblock_t *block, int dst_reg, int src_reg) { - codegen_addlong(block, OPCODE_VQMOVN_S32 | Vd(dst_reg) | Vm(src_reg)); + codegen_addlong(block, OPCODE_VQMOVN_S32 | Vd(dst_reg) | Vm(src_reg)); } -void host_arm_VQMOVN_U16(codeblock_t *block, int dst_reg, int src_reg) +void +host_arm_VQMOVN_U16(codeblock_t *block, int dst_reg, int src_reg) { - codegen_addlong(block, OPCODE_VQMOVN_U16 | Vd(dst_reg) | Vm(src_reg)); + codegen_addlong(block, OPCODE_VQMOVN_U16 | Vd(dst_reg) | Vm(src_reg)); } -void host_arm_VSHL_D_IMM_16(codeblock_t *block, int dst_reg, int src_reg, int shift) +void +host_arm_VSHL_D_IMM_16(codeblock_t *block, int dst_reg, int src_reg, int shift) { - if (shift > 15) - fatal("host_arm_VSHL_D_IMM_16 : shift > 15\n"); - codegen_addlong(block, OPCODE_VSHL_D_IMM_16 | Vd(dst_reg) | Vm(src_reg) | VSHIFT_IMM(shift)); + if (shift > 15) + fatal("host_arm_VSHL_D_IMM_16 : shift > 15\n"); + codegen_addlong(block, OPCODE_VSHL_D_IMM_16 | Vd(dst_reg) | Vm(src_reg) | VSHIFT_IMM(shift)); } -void host_arm_VSHL_D_IMM_32(codeblock_t *block, int dst_reg, int src_reg, int shift) +void +host_arm_VSHL_D_IMM_32(codeblock_t *block, int dst_reg, int src_reg, int shift) { - if (shift > 31) - fatal("host_arm_VSHL_D_IMM_32 : shift > 31\n"); - codegen_addlong(block, OPCODE_VSHL_D_IMM_32 | Vd(dst_reg) | Vm(src_reg) | VSHIFT_IMM(shift)); + if (shift > 31) + fatal("host_arm_VSHL_D_IMM_32 : shift > 31\n"); + codegen_addlong(block, OPCODE_VSHL_D_IMM_32 | Vd(dst_reg) | Vm(src_reg) | VSHIFT_IMM(shift)); } -void host_arm_VSHL_D_IMM_64(codeblock_t *block, int dst_reg, int src_reg, int shift) +void +host_arm_VSHL_D_IMM_64(codeblock_t *block, int dst_reg, int src_reg, int shift) { - if (shift > 63) - fatal("host_arm_VSHL_D_IMM_64 : shift > 63\n"); - codegen_addlong(block, OPCODE_VSHL_D_IMM_64 | Vd(dst_reg) | Vm(src_reg) | VSHIFT_IMM(shift)); + if (shift > 63) + fatal("host_arm_VSHL_D_IMM_64 : shift > 63\n"); + codegen_addlong(block, OPCODE_VSHL_D_IMM_64 | Vd(dst_reg) | Vm(src_reg) | VSHIFT_IMM(shift)); } -void host_arm_VSHR_D_S16(codeblock_t *block, int dst_reg, int src_reg, int shift) +void +host_arm_VSHR_D_S16(codeblock_t *block, int dst_reg, int src_reg, int shift) { - if (shift > 15) - fatal("host_arm_VSHR_SD_IMM_16 : shift > 15\n"); - codegen_addlong(block, OPCODE_VSHR_D_S16 | Vd(dst_reg) | Vm(src_reg) | VSHIFT_IMM(16-shift)); + if (shift > 15) + fatal("host_arm_VSHR_SD_IMM_16 : shift > 15\n"); + codegen_addlong(block, OPCODE_VSHR_D_S16 | Vd(dst_reg) | Vm(src_reg) | VSHIFT_IMM(16 - shift)); } -void host_arm_VSHR_D_S32(codeblock_t *block, int dst_reg, int src_reg, int shift) +void +host_arm_VSHR_D_S32(codeblock_t *block, int dst_reg, int src_reg, int shift) { - if (shift > 31) - fatal("host_arm_VSHR_SD_IMM_32 : shift > 31\n"); - codegen_addlong(block, OPCODE_VSHR_D_S32 | Vd(dst_reg) | Vm(src_reg) | VSHIFT_IMM(32-shift)); + if (shift > 31) + fatal("host_arm_VSHR_SD_IMM_32 : shift > 31\n"); + codegen_addlong(block, OPCODE_VSHR_D_S32 | Vd(dst_reg) | Vm(src_reg) | VSHIFT_IMM(32 - shift)); } -void host_arm_VSHR_D_S64(codeblock_t *block, int dst_reg, int src_reg, int shift) +void +host_arm_VSHR_D_S64(codeblock_t *block, int dst_reg, int src_reg, int shift) { - if (shift > 63) - fatal("host_arm_VSHR_SD_IMM_64 : shift > 63\n"); - codegen_addlong(block, OPCODE_VSHR_D_S64 | Vd(dst_reg) | Vm(src_reg) | VSHIFT_IMM(64-shift)); + if (shift > 63) + fatal("host_arm_VSHR_SD_IMM_64 : shift > 63\n"); + codegen_addlong(block, OPCODE_VSHR_D_S64 | Vd(dst_reg) | Vm(src_reg) | VSHIFT_IMM(64 - shift)); } -void host_arm_VSHR_D_U16(codeblock_t *block, int dst_reg, int src_reg, int shift) +void +host_arm_VSHR_D_U16(codeblock_t *block, int dst_reg, int src_reg, int shift) { - if (shift > 15) - fatal("host_arm_VSHR_UD_IMM_16 : shift > 15\n"); - codegen_addlong(block, OPCODE_VSHR_D_U16 | Vd(dst_reg) | Vm(src_reg) | VSHIFT_IMM(16-shift)); + if (shift > 15) + fatal("host_arm_VSHR_UD_IMM_16 : shift > 15\n"); + codegen_addlong(block, OPCODE_VSHR_D_U16 | Vd(dst_reg) | Vm(src_reg) | VSHIFT_IMM(16 - shift)); } -void host_arm_VSHR_D_U32(codeblock_t *block, int dst_reg, int src_reg, int shift) +void +host_arm_VSHR_D_U32(codeblock_t *block, int dst_reg, int src_reg, int shift) { - if (shift > 31) - fatal("host_arm_VSHR_UD_IMM_32 : shift > 31\n"); - codegen_addlong(block, OPCODE_VSHR_D_U32 | Vd(dst_reg) | Vm(src_reg) | VSHIFT_IMM(32-shift)); + if (shift > 31) + fatal("host_arm_VSHR_UD_IMM_32 : shift > 31\n"); + codegen_addlong(block, OPCODE_VSHR_D_U32 | Vd(dst_reg) | Vm(src_reg) | VSHIFT_IMM(32 - shift)); } -void host_arm_VSHR_D_U64(codeblock_t *block, int dst_reg, int src_reg, int shift) +void +host_arm_VSHR_D_U64(codeblock_t *block, int dst_reg, int src_reg, int shift) { - if (shift > 63) - fatal("host_arm_VSHR_UD_IMM_64 : shift > 63\n"); - codegen_addlong(block, OPCODE_VSHR_D_U64 | Vd(dst_reg) | Vm(src_reg) | VSHIFT_IMM(64-shift)); + if (shift > 63) + fatal("host_arm_VSHR_UD_IMM_64 : shift > 63\n"); + codegen_addlong(block, OPCODE_VSHR_D_U64 | Vd(dst_reg) | Vm(src_reg) | VSHIFT_IMM(64 - shift)); } -void host_arm_VSHRN_32(codeblock_t *block, int dst_reg, int src_reg, int shift) +void +host_arm_VSHRN_32(codeblock_t *block, int dst_reg, int src_reg, int shift) { - if (shift > 16) - fatal("host_arm_VSHRN_32 : shift > 16\n"); - codegen_addlong(block, OPCODE_VSHRN | Vd(dst_reg) | Vm(src_reg) | VSHIFT_IMM_32(16-shift)); + if (shift > 16) + fatal("host_arm_VSHRN_32 : shift > 16\n"); + codegen_addlong(block, OPCODE_VSHRN | Vd(dst_reg) | Vm(src_reg) | VSHIFT_IMM_32(16 - shift)); } -void host_arm_VSQRT_D(codeblock_t *block, int dest_reg, int src_reg) +void +host_arm_VSQRT_D(codeblock_t *block, int dest_reg, int src_reg) { - codegen_addlong(block, COND_AL | OPCODE_VSQRT_D | Vd(dest_reg) | Vm(src_reg)); + codegen_addlong(block, COND_AL | OPCODE_VSQRT_D | Vd(dest_reg) | Vm(src_reg)); } -void host_arm_VSQRT_S(codeblock_t *block, int dest_reg, int src_reg) +void +host_arm_VSQRT_S(codeblock_t *block, int dest_reg, int src_reg) { - codegen_addlong(block, COND_AL | OPCODE_VSQRT_S | Vd(dest_reg) | Vm(src_reg)); + codegen_addlong(block, COND_AL | OPCODE_VSQRT_S | Vd(dest_reg) | Vm(src_reg)); } -void host_arm_VSTR_D(codeblock_t *block, int src_reg, int base_reg, int offset) +void +host_arm_VSTR_D(codeblock_t *block, int src_reg, int base_reg, int offset) { - if ((offset > 1020) || (offset & 3)) - fatal("VSTR_D bad offset %i\n", offset); - codegen_addlong(block, COND_AL | OPCODE_VSTR_D | Rd(src_reg) | Rn(base_reg) | (offset >> 2)); + if ((offset > 1020) || (offset & 3)) + fatal("VSTR_D bad offset %i\n", offset); + codegen_addlong(block, COND_AL | OPCODE_VSTR_D | Rd(src_reg) | Rn(base_reg) | (offset >> 2)); } -void host_arm_VSTR_S(codeblock_t *block, int src_reg, int base_reg, int offset) +void +host_arm_VSTR_S(codeblock_t *block, int src_reg, int base_reg, int offset) { - if ((offset > 1020) || (offset & 3)) - fatal("VSTR_S bad offset %i\n", offset); - codegen_addlong(block, COND_AL | OPCODE_VSTR_S | Rd(src_reg) | Rn(base_reg) | (offset >> 2)); + if ((offset > 1020) || (offset & 3)) + fatal("VSTR_S bad offset %i\n", offset); + codegen_addlong(block, COND_AL | OPCODE_VSTR_S | Rd(src_reg) | Rn(base_reg) | (offset >> 2)); } -void host_arm_VSUB_D(codeblock_t *block, int dst_reg, int src_reg_n, int src_reg_m) +void +host_arm_VSUB_D(codeblock_t *block, int dst_reg, int src_reg_n, int src_reg_m) { - codegen_addlong(block, COND_AL | OPCODE_VSUB | Rd(dst_reg) | Rn(src_reg_n) | Rm(src_reg_m)); + codegen_addlong(block, COND_AL | OPCODE_VSUB | Rd(dst_reg) | Rn(src_reg_n) | Rm(src_reg_m)); } -void host_arm_VSUB_F32(codeblock_t *block, int dst_reg, int src_reg_n, int src_reg_m) +void +host_arm_VSUB_F32(codeblock_t *block, int dst_reg, int src_reg_n, int src_reg_m) { - codegen_addlong(block, COND_AL | OPCODE_VSUB_F32 | Rd(dst_reg) | Rn(src_reg_n) | Rm(src_reg_m)); + codegen_addlong(block, COND_AL | OPCODE_VSUB_F32 | Rd(dst_reg) | Rn(src_reg_n) | Rm(src_reg_m)); } -void host_arm_VSUB_I8(codeblock_t *block, int dst_reg, int src_reg_n, int src_reg_m) +void +host_arm_VSUB_I8(codeblock_t *block, int dst_reg, int src_reg_n, int src_reg_m) { - codegen_addlong(block, OPCODE_VSUB_I8 | Rd(dst_reg) | Rn(src_reg_n) | Rm(src_reg_m)); + codegen_addlong(block, OPCODE_VSUB_I8 | Rd(dst_reg) | Rn(src_reg_n) | Rm(src_reg_m)); } -void host_arm_VSUB_I16(codeblock_t *block, int dst_reg, int src_reg_n, int src_reg_m) +void +host_arm_VSUB_I16(codeblock_t *block, int dst_reg, int src_reg_n, int src_reg_m) { - codegen_addlong(block, OPCODE_VSUB_I16 | Rd(dst_reg) | Rn(src_reg_n) | Rm(src_reg_m)); + codegen_addlong(block, OPCODE_VSUB_I16 | Rd(dst_reg) | Rn(src_reg_n) | Rm(src_reg_m)); } -void host_arm_VSUB_I32(codeblock_t *block, int dst_reg, int src_reg_n, int src_reg_m) +void +host_arm_VSUB_I32(codeblock_t *block, int dst_reg, int src_reg_n, int src_reg_m) { - codegen_addlong(block, OPCODE_VSUB_I32 | Rd(dst_reg) | Rn(src_reg_n) | Rm(src_reg_m)); + codegen_addlong(block, OPCODE_VSUB_I32 | Rd(dst_reg) | Rn(src_reg_n) | Rm(src_reg_m)); } -void host_arm_VZIP_D8(codeblock_t *block, int d_reg, int m_reg) +void +host_arm_VZIP_D8(codeblock_t *block, int d_reg, int m_reg) { - codegen_addlong(block, OPCODE_VZIP_D8 | Vd(d_reg) | Vm(m_reg)); + codegen_addlong(block, OPCODE_VZIP_D8 | Vd(d_reg) | Vm(m_reg)); } -void host_arm_VZIP_D16(codeblock_t *block, int d_reg, int m_reg) +void +host_arm_VZIP_D16(codeblock_t *block, int d_reg, int m_reg) { - codegen_addlong(block, OPCODE_VZIP_D16 | Vd(d_reg) | Vm(m_reg)); + codegen_addlong(block, OPCODE_VZIP_D16 | Vd(d_reg) | Vm(m_reg)); } -void host_arm_VZIP_D32(codeblock_t *block, int d_reg, int m_reg) +void +host_arm_VZIP_D32(codeblock_t *block, int d_reg, int m_reg) { - codegen_addlong(block, OPCODE_VZIP_D32 | Vd(d_reg) | Vm(m_reg)); + codegen_addlong(block, OPCODE_VZIP_D32 | Vd(d_reg) | Vm(m_reg)); } #endif diff --git a/src/codegen_new/codegen_backend_arm_ops.h b/src/codegen_new/codegen_backend_arm_ops.h index 7627f51a7..271fbffbd 100644 --- a/src/codegen_new/codegen_backend_arm_ops.h +++ b/src/codegen_new/codegen_backend_arm_ops.h @@ -1,19 +1,19 @@ #define COND_SHIFT 28 -#define COND_EQ (0x0 << COND_SHIFT) -#define COND_NE (0x1 << COND_SHIFT) -#define COND_CS (0x2 << COND_SHIFT) -#define COND_CC (0x3 << COND_SHIFT) -#define COND_MI (0x4 << COND_SHIFT) -#define COND_PL (0x5 << COND_SHIFT) -#define COND_VS (0x6 << COND_SHIFT) -#define COND_VC (0x7 << COND_SHIFT) -#define COND_HI (0x8 << COND_SHIFT) -#define COND_LS (0x9 << COND_SHIFT) -#define COND_GE (0xa << COND_SHIFT) -#define COND_LT (0xb << COND_SHIFT) -#define COND_GT (0xc << COND_SHIFT) -#define COND_LE (0xd << COND_SHIFT) -#define COND_AL (0xe << COND_SHIFT) +#define COND_EQ (0x0 << COND_SHIFT) +#define COND_NE (0x1 << COND_SHIFT) +#define COND_CS (0x2 << COND_SHIFT) +#define COND_CC (0x3 << COND_SHIFT) +#define COND_MI (0x4 << COND_SHIFT) +#define COND_PL (0x5 << COND_SHIFT) +#define COND_VS (0x6 << COND_SHIFT) +#define COND_VC (0x7 << COND_SHIFT) +#define COND_HI (0x8 << COND_SHIFT) +#define COND_LS (0x9 << COND_SHIFT) +#define COND_GE (0xa << COND_SHIFT) +#define COND_LT (0xb << COND_SHIFT) +#define COND_GT (0xc << COND_SHIFT) +#define COND_LE (0xd << COND_SHIFT) +#define COND_AL (0xe << COND_SHIFT) void host_arm_ADD_IMM(codeblock_t *block, int dst_reg, int src_reg, uint32_t imm); #define host_arm_ADD_REG(block, dst_reg, src_reg_n, src_reg_m) host_arm_ADD_REG_LSL(block, dst_reg, src_reg_n, src_reg_m, 0) @@ -101,12 +101,12 @@ void host_arm_MVN_REG_LSL(codeblock_t *block, int dst_reg, int src_reg, int shif void host_arm_ORR_IMM_cond(codeblock_t *block, uint32_t cond, int dst_reg, int src_reg, uint32_t imm); void host_arm_ORR_REG_LSL_cond(codeblock_t *block, uint32_t cond, int dst_reg, int src_reg_n, int src_reg_m, int shift); -#define host_arm_ORR_IMM(block, dst_reg, src_reg, imm) host_arm_ORR_IMM_cond(block, COND_AL, dst_reg, src_reg, imm) +#define host_arm_ORR_IMM(block, dst_reg, src_reg, imm) host_arm_ORR_IMM_cond(block, COND_AL, dst_reg, src_reg, imm) #define host_arm_ORR_REG_LSL(block, dst_reg, src_reg_a, src_reg_b, shift) host_arm_ORR_REG_LSL_cond(block, COND_AL, dst_reg, src_reg_a, src_reg_b, shift) -#define host_arm_ORRCC_IMM(block, dst_reg, src_reg, imm) host_arm_ORR_IMM_cond(block, COND_CC, dst_reg, src_reg, imm) -#define host_arm_ORREQ_IMM(block, dst_reg, src_reg, imm) host_arm_ORR_IMM_cond(block, COND_EQ, dst_reg, src_reg, imm) -#define host_arm_ORRVS_IMM(block, dst_reg, src_reg, imm) host_arm_ORR_IMM_cond(block, COND_VS, dst_reg, src_reg, imm) +#define host_arm_ORRCC_IMM(block, dst_reg, src_reg, imm) host_arm_ORR_IMM_cond(block, COND_CC, dst_reg, src_reg, imm) +#define host_arm_ORREQ_IMM(block, dst_reg, src_reg, imm) host_arm_ORR_IMM_cond(block, COND_EQ, dst_reg, src_reg, imm) +#define host_arm_ORRVS_IMM(block, dst_reg, src_reg, imm) host_arm_ORR_IMM_cond(block, COND_VS, dst_reg, src_reg, imm) void host_arm_RSB_IMM(codeblock_t *block, int dst_reg, int src_reg, uint32_t imm); void host_arm_RSB_REG_LSL(codeblock_t *block, int dst_reg, int src_reg_n, int src_reg_m, int shift); diff --git a/src/codegen_new/codegen_backend_arm_uops.c b/src/codegen_new/codegen_backend_arm_uops.c index 6beab7232..338d3dd54 100644 --- a/src/codegen_new/codegen_backend_arm_uops.c +++ b/src/codegen_new/codegen_backend_arm_uops.c @@ -1,3502 +1,3716 @@ #if defined __ARM_EABI__ || defined _ARM_ || defined _M_ARM -#include -#include -#include <86box/86box.h> -#include "cpu.h" -#include <86box/mem.h> +# include +# include +# include <86box/86box.h> +# include "cpu.h" +# include <86box/mem.h> +# include <86box/plat_unused.h> -#include "x86.h" -#include "x87.h" -#include "386_common.h" -#include "codegen.h" -#include "codegen_allocator.h" -#include "codegen_backend.h" -#include "codegen_backend_arm_defs.h" -#include "codegen_backend_arm_ops.h" -#include "codegen_ir_defs.h" +# include "x86.h" +# include "x86seg_common.h" +# include "x86seg.h" +# include "x87.h" +# include "386_common.h" +# include "codegen.h" +# include "codegen_allocator.h" +# include "codegen_backend.h" +# include "codegen_backend_arm_defs.h" +# include "codegen_backend_arm_ops.h" +# include "codegen_ir_defs.h" -static inline int get_arm_imm(uint32_t imm_data, uint32_t *arm_imm) +static inline int +get_arm_imm(uint32_t imm_data, uint32_t *arm_imm) { - int shift = 0; - if (!(imm_data & 0xffff)) - { - shift += 16; - imm_data >>= 16; - } - if (!(imm_data & 0xff)) - { - shift += 8; - imm_data >>= 8; - } - if (!(imm_data & 0xf)) - { - shift += 4; - imm_data >>= 4; - } - if (!(imm_data & 0x3)) - { - shift += 2; - imm_data >>= 2; - } - if (imm_data > 0xff) /*Note - should handle rotation round the word*/ - return 0; - *arm_imm = imm_data | ((((32 - shift) >> 1) & 15) << 8); - return 1; -} - -static inline int in_range(void *addr, void *base) -{ - int diff = (uintptr_t)addr - (uintptr_t)base; - - if (diff < -4095 || diff > 4095) - return 0; - return 1; -} - -static inline int in_range_h(void *addr, void *base) -{ - int diff = (uintptr_t)addr - (uintptr_t)base; - - if (diff < 0 || diff > 255) - return 0; - return 1; -} - -void host_arm_call(codeblock_t *block, void *dst_addr) -{ - host_arm_MOV_IMM(block, REG_R3, (uintptr_t)dst_addr); - host_arm_BLX(block, REG_R3); -} - -void host_arm_nop(codeblock_t *block) -{ - host_arm_MOV_REG_LSL(block, REG_R0, REG_R0, 0); -} - -#define HOST_REG_GET(reg) (IREG_GET_REG(reg) & 0xf) - -#define REG_IS_L(size) (size == IREG_SIZE_L) -#define REG_IS_W(size) (size == IREG_SIZE_W) -#define REG_IS_B(size) (size == IREG_SIZE_B) -#define REG_IS_BH(size) (size == IREG_SIZE_BH) -#define REG_IS_D(size) (size == IREG_SIZE_D) -#define REG_IS_Q(size) (size == IREG_SIZE_Q) - -static int codegen_ADD(codeblock_t *block, uop_t *uop) -{ - int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg_a = HOST_REG_GET(uop->src_reg_a_real), src_reg_b = HOST_REG_GET(uop->src_reg_b_real); - int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size_a = IREG_GET_SIZE(uop->src_reg_a_real), src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); - - if (REG_IS_L(dest_size) && REG_IS_L(src_size_a) && REG_IS_L(src_size_b)) - { - host_arm_ADD_REG_LSL(block, dest_reg, src_reg_a, src_reg_b, 0); - } - else if (REG_IS_W(dest_size) && REG_IS_W(src_size_a) && REG_IS_W(src_size_b)) - { - host_arm_ADD_REG(block, REG_TEMP, src_reg_a, src_reg_b); - host_arm_BFI(block, dest_reg, REG_TEMP, 0, 16); - } - else if (REG_IS_B(dest_size) && REG_IS_B(src_size_a) && REG_IS_B(src_size_b)) - { - host_arm_ADD_REG(block, REG_TEMP, src_reg_a, src_reg_b); - host_arm_BFI(block, dest_reg, REG_TEMP, 0, 8); - } - else if (REG_IS_B(dest_size) && REG_IS_B(src_size_a) && REG_IS_BH(src_size_b) && dest_reg == src_reg_a) - { - host_arm_UXTB(block, REG_TEMP, src_reg_b, 8); - host_arm_UADD8(block, dest_reg, src_reg_a, REG_TEMP); - } - else if (REG_IS_B(dest_size) && REG_IS_B(src_size_a) && REG_IS_BH(src_size_b)) - { - host_arm_ADD_REG_LSR(block, REG_TEMP, src_reg_a, src_reg_b, 8); - host_arm_BFI(block, dest_reg, REG_TEMP, 8, 8); - } - else if (REG_IS_BH(dest_size) && REG_IS_BH(src_size_a) && REG_IS_B(src_size_b) && dest_reg == src_reg_a) - { - host_arm_UXTB(block, REG_TEMP, src_reg_b, 0); - host_arm_MOV_REG_LSL(block, REG_TEMP, REG_TEMP, 8); - host_arm_UADD8(block, dest_reg, src_reg_a, REG_TEMP); - } - else if (REG_IS_BH(dest_size) && REG_IS_BH(src_size_a) && REG_IS_BH(src_size_b) && dest_reg == src_reg_a) - { - host_arm_AND_IMM(block, REG_TEMP, src_reg_b, 0x0000ff00); - host_arm_UADD8(block, dest_reg, src_reg_a, REG_TEMP); - } - else - fatal("ADD %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real); - + int shift = 0; + if (!(imm_data & 0xffff)) { + shift += 16; + imm_data >>= 16; + } + if (!(imm_data & 0xff)) { + shift += 8; + imm_data >>= 8; + } + if (!(imm_data & 0xf)) { + shift += 4; + imm_data >>= 4; + } + if (!(imm_data & 0x3)) { + shift += 2; + imm_data >>= 2; + } + if (imm_data > 0xff) /*Note - should handle rotation round the word*/ return 0; + *arm_imm = imm_data | ((((32 - shift) >> 1) & 15) << 8); + return 1; } -static int codegen_ADD_IMM(codeblock_t *block, uop_t *uop) + +static inline int +in_range(void *addr, void *base) { -// host_arm_ADD_IMM(block, uop->dest_reg_a_real, uop->src_reg_a_real, uop->imm_data); -// return 0; - - int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg = HOST_REG_GET(uop->src_reg_a_real); - int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size = IREG_GET_SIZE(uop->src_reg_a_real); - - if (REG_IS_L(dest_size) && REG_IS_L(src_size)) - { - host_arm_ADD_IMM(block, dest_reg, src_reg, uop->imm_data); - } - else if (REG_IS_W(dest_size) && REG_IS_W(src_size)) - { - host_arm_ADD_IMM(block, REG_TEMP, src_reg, uop->imm_data); - host_arm_BFI(block, dest_reg, REG_TEMP, 0, 16); - } - else if (REG_IS_B(dest_size) && REG_IS_B(src_size)) - { - host_arm_ADD_IMM(block, REG_TEMP, src_reg, uop->imm_data); - host_arm_BFI(block, dest_reg, REG_TEMP, 0, 8); - } - else if (REG_IS_BH(dest_size) && REG_IS_BH(src_size) && src_reg == dest_reg) - { - host_arm_MOV_IMM(block, REG_TEMP, uop->imm_data << 8); - host_arm_UADD8(block, dest_reg, src_reg, REG_TEMP); - } - else - fatal("ADD_IMM %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real); + int diff = (uintptr_t) addr - (uintptr_t) base; + if (diff < -4095 || diff > 4095) return 0; - + return 1; } -static int codegen_ADD_LSHIFT(codeblock_t *block, uop_t *uop) + +static inline int +in_range_h(void *addr, void *base) { - host_arm_ADD_REG_LSL(block, uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real, uop->imm_data); + int diff = (uintptr_t) addr - (uintptr_t) base; + + if (diff < 0 || diff > 255) return 0; + return 1; } -static int codegen_AND(codeblock_t *block, uop_t *uop) +void +host_arm_call(codeblock_t *block, void *dst_addr) { - int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg_a = HOST_REG_GET(uop->src_reg_a_real), src_reg_b = HOST_REG_GET(uop->src_reg_b_real); - int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size_a = IREG_GET_SIZE(uop->src_reg_a_real), src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); + host_arm_MOV_IMM(block, REG_R3, (uintptr_t) dst_addr); + host_arm_BLX(block, REG_R3); +} - if (REG_IS_Q(dest_size) && REG_IS_Q(src_size_a) && REG_IS_Q(src_size_b)) - { - host_arm_VAND_D(block, dest_reg, src_reg_a, src_reg_b); - } - else if (REG_IS_L(dest_size) && REG_IS_L(src_size_a) && REG_IS_L(src_size_b)) - { - host_arm_AND_REG_LSL(block, dest_reg, src_reg_a, src_reg_b, 0); - } - else if (REG_IS_W(dest_size) && REG_IS_W(src_size_a) && REG_IS_W(src_size_b) && dest_reg == src_reg_a) - { - host_arm_MVN_REG_LSL(block, REG_TEMP, src_reg_b, 16); - host_arm_BIC_REG_LSR(block, dest_reg, src_reg_a, REG_TEMP, 16); - } - else if (REG_IS_B(dest_size) && REG_IS_B(src_size_a) && REG_IS_B(src_size_b) && dest_reg == src_reg_a) - { - host_arm_MVN_REG_LSL(block, REG_TEMP, src_reg_b, 24); - host_arm_BIC_REG_LSR(block, dest_reg, src_reg_a, REG_TEMP, 24); - } - else if (REG_IS_B(dest_size) && REG_IS_B(src_size_a) && REG_IS_BH(src_size_b) && dest_reg == src_reg_a) - { - host_arm_MVN_REG_LSL(block, REG_TEMP, src_reg_b, 16); - host_arm_BIC_REG_LSR(block, dest_reg, src_reg_a, REG_TEMP, 24); - } - else if (REG_IS_BH(dest_size) && REG_IS_BH(src_size_a) && REG_IS_B(src_size_b) && dest_reg == src_reg_a) - { - host_arm_MVN_REG_LSL(block, REG_TEMP, src_reg_b, 8); - host_arm_AND_IMM(block, REG_TEMP, REG_TEMP, 0x0000ff00); - host_arm_BIC_REG_LSL(block, dest_reg, src_reg_a, REG_TEMP, 0); - } - else if (REG_IS_BH(dest_size) && REG_IS_BH(src_size_a) && REG_IS_BH(src_size_b) && dest_reg == src_reg_a) - { - host_arm_MVN_REG_LSL(block, REG_TEMP, src_reg_b, 0); - host_arm_AND_IMM(block, REG_TEMP, REG_TEMP, 0x0000ff00); - host_arm_BIC_REG_LSL(block, dest_reg, src_reg_a, REG_TEMP, 0); - } - else if (REG_IS_W(dest_size) && REG_IS_W(src_size_a) && REG_IS_W(src_size_b)) - { - host_arm_AND_REG_LSL(block, REG_TEMP, src_reg_a, src_reg_b, 0); - host_arm_BFI(block, dest_reg, REG_TEMP, 0, 16); - } - else if (REG_IS_B(dest_size) && REG_IS_B(src_size_a) && REG_IS_B(src_size_b)) - { - host_arm_AND_REG_LSL(block, REG_TEMP, src_reg_a, src_reg_b, 0); - host_arm_BFI(block, dest_reg, REG_TEMP, 0, 8); - } - else if (REG_IS_B(dest_size) && REG_IS_B(src_size_a) && REG_IS_BH(src_size_b)) - { - host_arm_AND_REG_LSR(block, REG_TEMP, src_reg_a, src_reg_b, 8); - host_arm_BFI(block, dest_reg, REG_TEMP, 0, 8); - } - else if (REG_IS_B(dest_size) && REG_IS_BH(src_size_a) && REG_IS_B(src_size_b)) - { - host_arm_AND_REG_LSR(block, REG_TEMP, src_reg_b, src_reg_a, 8); - host_arm_BFI(block, dest_reg, REG_TEMP, 0, 8); - } - else if (REG_IS_B(dest_size) && REG_IS_BH(src_size_a) && REG_IS_BH(src_size_b)) - { - host_arm_AND_REG_LSL(block, REG_TEMP, src_reg_a, src_reg_b, 0); - host_arm_MOV_REG_LSR(block, REG_TEMP, REG_TEMP, 8); - host_arm_BFI(block, dest_reg, REG_TEMP, 0, 8); - } - else - fatal("AND %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real); +void +host_arm_nop(codeblock_t *block) +{ + host_arm_MOV_REG_LSL(block, REG_R0, REG_R0, 0); +} +# define HOST_REG_GET(reg) (IREG_GET_REG(reg) & 0xf) + +# define REG_IS_L(size) (size == IREG_SIZE_L) +# define REG_IS_W(size) (size == IREG_SIZE_W) +# define REG_IS_B(size) (size == IREG_SIZE_B) +# define REG_IS_BH(size) (size == IREG_SIZE_BH) +# define REG_IS_D(size) (size == IREG_SIZE_D) +# define REG_IS_Q(size) (size == IREG_SIZE_Q) + +static int +codegen_ADD(codeblock_t *block, uop_t *uop) +{ + int dest_reg = HOST_REG_GET(uop->dest_reg_a_real); + int src_reg_a = HOST_REG_GET(uop->src_reg_a_real); + int src_reg_b = HOST_REG_GET(uop->src_reg_b_real); + int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real); + int src_size_a = IREG_GET_SIZE(uop->src_reg_a_real); + int src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); + + if (REG_IS_L(dest_size) && REG_IS_L(src_size_a) && REG_IS_L(src_size_b)) { + host_arm_ADD_REG_LSL(block, dest_reg, src_reg_a, src_reg_b, 0); + } else if (REG_IS_W(dest_size) && REG_IS_W(src_size_a) && REG_IS_W(src_size_b)) { + host_arm_ADD_REG(block, REG_TEMP, src_reg_a, src_reg_b); + host_arm_BFI(block, dest_reg, REG_TEMP, 0, 16); + } else if (REG_IS_B(dest_size) && REG_IS_B(src_size_a) && REG_IS_B(src_size_b)) { + host_arm_ADD_REG(block, REG_TEMP, src_reg_a, src_reg_b); + host_arm_BFI(block, dest_reg, REG_TEMP, 0, 8); + } else if (REG_IS_B(dest_size) && REG_IS_B(src_size_a) && REG_IS_BH(src_size_b) && dest_reg == src_reg_a) { + host_arm_UXTB(block, REG_TEMP, src_reg_b, 8); + host_arm_UADD8(block, dest_reg, src_reg_a, REG_TEMP); + } else if (REG_IS_B(dest_size) && REG_IS_B(src_size_a) && REG_IS_BH(src_size_b)) { + host_arm_ADD_REG_LSR(block, REG_TEMP, src_reg_a, src_reg_b, 8); + host_arm_BFI(block, dest_reg, REG_TEMP, 8, 8); + } else if (REG_IS_BH(dest_size) && REG_IS_BH(src_size_a) && REG_IS_B(src_size_b) && dest_reg == src_reg_a) { + host_arm_UXTB(block, REG_TEMP, src_reg_b, 0); + host_arm_MOV_REG_LSL(block, REG_TEMP, REG_TEMP, 8); + host_arm_UADD8(block, dest_reg, src_reg_a, REG_TEMP); + } else if (REG_IS_BH(dest_size) && REG_IS_BH(src_size_a) && REG_IS_BH(src_size_b) && dest_reg == src_reg_a) { + host_arm_AND_IMM(block, REG_TEMP, src_reg_b, 0x0000ff00); + host_arm_UADD8(block, dest_reg, src_reg_a, REG_TEMP); + } else + fatal("ADD %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real); + + return 0; +} +static int +codegen_ADD_IMM(codeblock_t *block, uop_t *uop) +{ +# if 0 + host_arm_ADD_IMM(block, uop->dest_reg_a_real, uop->src_reg_a_real, uop->imm_data); return 0; +# endif + + int dest_reg = HOST_REG_GET(uop->dest_reg_a_real); + int src_reg = HOST_REG_GET(uop->src_reg_a_real); + int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real); + int src_size = IREG_GET_SIZE(uop->src_reg_a_real); + + if (REG_IS_L(dest_size) && REG_IS_L(src_size)) { + host_arm_ADD_IMM(block, dest_reg, src_reg, uop->imm_data); + } else if (REG_IS_W(dest_size) && REG_IS_W(src_size)) { + host_arm_ADD_IMM(block, REG_TEMP, src_reg, uop->imm_data); + host_arm_BFI(block, dest_reg, REG_TEMP, 0, 16); + } else if (REG_IS_B(dest_size) && REG_IS_B(src_size)) { + host_arm_ADD_IMM(block, REG_TEMP, src_reg, uop->imm_data); + host_arm_BFI(block, dest_reg, REG_TEMP, 0, 8); + } else if (REG_IS_BH(dest_size) && REG_IS_BH(src_size) && src_reg == dest_reg) { + host_arm_MOV_IMM(block, REG_TEMP, uop->imm_data << 8); + host_arm_UADD8(block, dest_reg, src_reg, REG_TEMP); + } else + fatal("ADD_IMM %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real); + + return 0; } -static int codegen_AND_IMM(codeblock_t *block, uop_t *uop) +static int +codegen_ADD_LSHIFT(codeblock_t *block, uop_t *uop) { - int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg = HOST_REG_GET(uop->src_reg_a_real); - int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size = IREG_GET_SIZE(uop->src_reg_a_real); - - if (REG_IS_L(dest_size) && REG_IS_L(src_size)) - { - host_arm_AND_IMM(block, dest_reg, src_reg, uop->imm_data); - } - else if (REG_IS_W(dest_size) && REG_IS_W(src_size) && dest_reg == src_reg) - { - host_arm_AND_IMM(block, dest_reg, src_reg, uop->imm_data | 0xffff0000); - } - else if (REG_IS_B(dest_size) && REG_IS_B(src_size) && dest_reg == src_reg) - { - host_arm_AND_IMM(block, dest_reg, src_reg, uop->imm_data | 0xffffff00); - } - else if (REG_IS_BH(dest_size) && REG_IS_BH(src_size) && dest_reg == src_reg) - { - host_arm_AND_IMM(block, dest_reg, src_reg, (uop->imm_data << 8) | 0xffff00ff); - } - else if (REG_IS_W(dest_size) && REG_IS_W(src_size)) - { - host_arm_AND_IMM(block, REG_TEMP, src_reg, uop->imm_data); - host_arm_BFI(block, dest_reg, REG_TEMP, 0, 16); - } - else if (REG_IS_B(dest_size) && REG_IS_B(src_size)) - { - host_arm_AND_IMM(block, REG_TEMP, src_reg, uop->imm_data); - host_arm_BFI(block, dest_reg, REG_TEMP, 0, 8); - } - else if (REG_IS_B(dest_size) && REG_IS_BH(src_size)) - { - host_arm_MOV_REG_LSR(block, REG_TEMP, src_reg, 8); - host_arm_AND_IMM(block, REG_TEMP, REG_TEMP, uop->imm_data); - host_arm_BFI(block, dest_reg, REG_TEMP, 0, 8); - } - else - fatal("AND_IMM %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real); - - return 0; -} -static int codegen_ANDN(codeblock_t *block, uop_t *uop) -{ - int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg_a = HOST_REG_GET(uop->src_reg_a_real), src_reg_b = HOST_REG_GET(uop->src_reg_b_real); - int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size_a = IREG_GET_SIZE(uop->src_reg_a_real), src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); - - if (REG_IS_Q(dest_size) && REG_IS_Q(src_size_a) && REG_IS_Q(src_size_b)) - { - host_arm_VBIC_D(block, dest_reg, src_reg_b, src_reg_a); - } - else - fatal("ANDN %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real); - - return 0; + host_arm_ADD_REG_LSL(block, uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real, uop->imm_data); + return 0; } -static int codegen_CALL_FUNC(codeblock_t *block, uop_t *uop) +static int +codegen_AND(codeblock_t *block, uop_t *uop) { - host_arm_call(block, uop->p); + int dest_reg = HOST_REG_GET(uop->dest_reg_a_real); + int src_reg_a = HOST_REG_GET(uop->src_reg_a_real); + int src_reg_b = HOST_REG_GET(uop->src_reg_b_real); + int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real); + int src_size_a = IREG_GET_SIZE(uop->src_reg_a_real); + int src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); - return 0; + if (REG_IS_Q(dest_size) && REG_IS_Q(src_size_a) && REG_IS_Q(src_size_b)) { + host_arm_VAND_D(block, dest_reg, src_reg_a, src_reg_b); + } else if (REG_IS_L(dest_size) && REG_IS_L(src_size_a) && REG_IS_L(src_size_b)) { + host_arm_AND_REG_LSL(block, dest_reg, src_reg_a, src_reg_b, 0); + } else if (REG_IS_W(dest_size) && REG_IS_W(src_size_a) && REG_IS_W(src_size_b) && dest_reg == src_reg_a) { + host_arm_MVN_REG_LSL(block, REG_TEMP, src_reg_b, 16); + host_arm_BIC_REG_LSR(block, dest_reg, src_reg_a, REG_TEMP, 16); + } else if (REG_IS_B(dest_size) && REG_IS_B(src_size_a) && REG_IS_B(src_size_b) && dest_reg == src_reg_a) { + host_arm_MVN_REG_LSL(block, REG_TEMP, src_reg_b, 24); + host_arm_BIC_REG_LSR(block, dest_reg, src_reg_a, REG_TEMP, 24); + } else if (REG_IS_B(dest_size) && REG_IS_B(src_size_a) && REG_IS_BH(src_size_b) && dest_reg == src_reg_a) { + host_arm_MVN_REG_LSL(block, REG_TEMP, src_reg_b, 16); + host_arm_BIC_REG_LSR(block, dest_reg, src_reg_a, REG_TEMP, 24); + } else if (REG_IS_BH(dest_size) && REG_IS_BH(src_size_a) && REG_IS_B(src_size_b) && dest_reg == src_reg_a) { + host_arm_MVN_REG_LSL(block, REG_TEMP, src_reg_b, 8); + host_arm_AND_IMM(block, REG_TEMP, REG_TEMP, 0x0000ff00); + host_arm_BIC_REG_LSL(block, dest_reg, src_reg_a, REG_TEMP, 0); + } else if (REG_IS_BH(dest_size) && REG_IS_BH(src_size_a) && REG_IS_BH(src_size_b) && dest_reg == src_reg_a) { + host_arm_MVN_REG_LSL(block, REG_TEMP, src_reg_b, 0); + host_arm_AND_IMM(block, REG_TEMP, REG_TEMP, 0x0000ff00); + host_arm_BIC_REG_LSL(block, dest_reg, src_reg_a, REG_TEMP, 0); + } else if (REG_IS_W(dest_size) && REG_IS_W(src_size_a) && REG_IS_W(src_size_b)) { + host_arm_AND_REG_LSL(block, REG_TEMP, src_reg_a, src_reg_b, 0); + host_arm_BFI(block, dest_reg, REG_TEMP, 0, 16); + } else if (REG_IS_B(dest_size) && REG_IS_B(src_size_a) && REG_IS_B(src_size_b)) { + host_arm_AND_REG_LSL(block, REG_TEMP, src_reg_a, src_reg_b, 0); + host_arm_BFI(block, dest_reg, REG_TEMP, 0, 8); + } else if (REG_IS_B(dest_size) && REG_IS_B(src_size_a) && REG_IS_BH(src_size_b)) { + host_arm_AND_REG_LSR(block, REG_TEMP, src_reg_a, src_reg_b, 8); + host_arm_BFI(block, dest_reg, REG_TEMP, 0, 8); + } else if (REG_IS_B(dest_size) && REG_IS_BH(src_size_a) && REG_IS_B(src_size_b)) { + host_arm_AND_REG_LSR(block, REG_TEMP, src_reg_b, src_reg_a, 8); + host_arm_BFI(block, dest_reg, REG_TEMP, 0, 8); + } else if (REG_IS_B(dest_size) && REG_IS_BH(src_size_a) && REG_IS_BH(src_size_b)) { + host_arm_AND_REG_LSL(block, REG_TEMP, src_reg_a, src_reg_b, 0); + host_arm_MOV_REG_LSR(block, REG_TEMP, REG_TEMP, 8); + host_arm_BFI(block, dest_reg, REG_TEMP, 0, 8); + } else + fatal("AND %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real); + + return 0; +} +static int +codegen_AND_IMM(codeblock_t *block, uop_t *uop) +{ + int dest_reg = HOST_REG_GET(uop->dest_reg_a_real); + int src_reg = HOST_REG_GET(uop->src_reg_a_real); + int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real); + int src_size = IREG_GET_SIZE(uop->src_reg_a_real); + + if (REG_IS_L(dest_size) && REG_IS_L(src_size)) { + host_arm_AND_IMM(block, dest_reg, src_reg, uop->imm_data); + } else if (REG_IS_W(dest_size) && REG_IS_W(src_size) && dest_reg == src_reg) { + host_arm_AND_IMM(block, dest_reg, src_reg, uop->imm_data | 0xffff0000); + } else if (REG_IS_B(dest_size) && REG_IS_B(src_size) && dest_reg == src_reg) { + host_arm_AND_IMM(block, dest_reg, src_reg, uop->imm_data | 0xffffff00); + } else if (REG_IS_BH(dest_size) && REG_IS_BH(src_size) && dest_reg == src_reg) { + host_arm_AND_IMM(block, dest_reg, src_reg, (uop->imm_data << 8) | 0xffff00ff); + } else if (REG_IS_W(dest_size) && REG_IS_W(src_size)) { + host_arm_AND_IMM(block, REG_TEMP, src_reg, uop->imm_data); + host_arm_BFI(block, dest_reg, REG_TEMP, 0, 16); + } else if (REG_IS_B(dest_size) && REG_IS_B(src_size)) { + host_arm_AND_IMM(block, REG_TEMP, src_reg, uop->imm_data); + host_arm_BFI(block, dest_reg, REG_TEMP, 0, 8); + } else if (REG_IS_B(dest_size) && REG_IS_BH(src_size)) { + host_arm_MOV_REG_LSR(block, REG_TEMP, src_reg, 8); + host_arm_AND_IMM(block, REG_TEMP, REG_TEMP, uop->imm_data); + host_arm_BFI(block, dest_reg, REG_TEMP, 0, 8); + } else + fatal("AND_IMM %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real); + + return 0; +} +static int +codegen_ANDN(codeblock_t *block, uop_t *uop) +{ + int dest_reg = HOST_REG_GET(uop->dest_reg_a_real); + int src_reg_a = HOST_REG_GET(uop->src_reg_a_real); + int src_reg_b = HOST_REG_GET(uop->src_reg_b_real); + int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real); + int src_size_a = IREG_GET_SIZE(uop->src_reg_a_real); + int src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); + + if (REG_IS_Q(dest_size) && REG_IS_Q(src_size_a) && REG_IS_Q(src_size_b)) { + host_arm_VBIC_D(block, dest_reg, src_reg_b, src_reg_a); + } else + fatal("ANDN %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real); + + return 0; } -static int codegen_CALL_FUNC_RESULT(codeblock_t *block, uop_t *uop) +static int +codegen_CALL_FUNC(codeblock_t *block, uop_t *uop) { - int dest_reg = HOST_REG_GET(uop->dest_reg_a_real); - int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real); + host_arm_call(block, uop->p); - if (!REG_IS_L(dest_size)) - fatal("CALL_FUNC_RESULT %02x\n", uop->dest_reg_a_real); - host_arm_call(block, uop->p); + return 0; +} + +static int +codegen_CALL_FUNC_RESULT(codeblock_t *block, uop_t *uop) +{ + int dest_reg = HOST_REG_GET(uop->dest_reg_a_real); + int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real); + + if (!REG_IS_L(dest_size)) + fatal("CALL_FUNC_RESULT %02x\n", uop->dest_reg_a_real); + host_arm_call(block, uop->p); + host_arm_MOV_REG(block, dest_reg, REG_R0); + + return 0; +} + +static int +codegen_CALL_INSTRUCTION_FUNC(codeblock_t *block, uop_t *uop) +{ + host_arm_call(block, uop->p); + host_arm_TST_REG(block, REG_R0, REG_R0); + host_arm_BNE(block, (uintptr_t) codegen_exit_rout); + + return 0; +} + +static int +codegen_CMP_IMM_JZ(codeblock_t *block, uop_t *uop) +{ + int src_reg = HOST_REG_GET(uop->src_reg_a_real); + int src_size = IREG_GET_SIZE(uop->src_reg_a_real); + + if (REG_IS_L(src_size)) { + host_arm_CMP_IMM(block, src_reg, uop->imm_data); + } else + fatal("CMP_IMM_JZ %02x\n", uop->src_reg_a_real); + host_arm_BEQ(block, (uintptr_t) uop->p); + + return 0; +} + +static int +codegen_CMP_IMM_JNZ_DEST(codeblock_t *block, uop_t *uop) +{ + int src_reg = HOST_REG_GET(uop->src_reg_a_real); + int src_size = IREG_GET_SIZE(uop->src_reg_a_real); + + if (REG_IS_L(src_size)) { + host_arm_CMP_IMM(block, src_reg, uop->imm_data); + } else if (REG_IS_W(src_size)) { + host_arm_UXTH(block, REG_TEMP, src_reg, 0); + host_arm_CMP_IMM(block, REG_TEMP, uop->imm_data); + } else + fatal("CMP_IMM_JNZ_DEST %02x\n", uop->src_reg_a_real); + + uop->p = host_arm_BNE_(block); + + return 0; +} +static int +codegen_CMP_IMM_JZ_DEST(codeblock_t *block, uop_t *uop) +{ + int src_reg = HOST_REG_GET(uop->src_reg_a_real); + int src_size = IREG_GET_SIZE(uop->src_reg_a_real); + + if (REG_IS_L(src_size)) { + host_arm_CMP_IMM(block, src_reg, uop->imm_data); + } else if (REG_IS_W(src_size)) { + host_arm_UXTH(block, REG_TEMP, src_reg, 0); + host_arm_CMP_IMM(block, REG_TEMP, uop->imm_data); + } else + fatal("CMP_IMM_JZ_DEST %02x\n", uop->src_reg_a_real); + + uop->p = host_arm_BEQ_(block); + + return 0; +} + +static int +codegen_CMP_JB(codeblock_t *block, uop_t *uop) +{ + int src_reg_a = HOST_REG_GET(uop->src_reg_a_real); + int src_reg_b = HOST_REG_GET(uop->src_reg_b_real); + int src_size_a = IREG_GET_SIZE(uop->src_reg_a_real); + int src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); + uint32_t *jump_p; + + if (REG_IS_L(src_size_a) && REG_IS_L(src_size_b)) { + host_arm_CMP_REG(block, src_reg_a, src_reg_b); + } else + fatal("CMP_JB %02x\n", uop->src_reg_a_real); + + jump_p = host_arm_BCC_(block); + *jump_p |= ((((uintptr_t) uop->p - (uintptr_t) jump_p) - 8) & 0x3fffffc) >> 2; + + return 0; +} +static int +codegen_CMP_JNBE(codeblock_t *block, uop_t *uop) +{ + int src_reg_a = HOST_REG_GET(uop->src_reg_a_real); + int src_reg_b = HOST_REG_GET(uop->src_reg_b_real); + int src_size_a = IREG_GET_SIZE(uop->src_reg_a_real); + int src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); + uint32_t *jump_p; + + if (REG_IS_L(src_size_a) && REG_IS_L(src_size_b)) { + host_arm_CMP_REG(block, src_reg_a, src_reg_b); + } else + fatal("CMP_JNBE %02x\n", uop->src_reg_a_real); + + jump_p = host_arm_BHI_(block); + *jump_p |= ((((uintptr_t) uop->p - (uintptr_t) jump_p) - 8) & 0x3fffffc) >> 2; + + return 0; +} + +static int +codegen_CMP_JNB_DEST(codeblock_t *block, uop_t *uop) +{ + int src_reg_a = HOST_REG_GET(uop->src_reg_a_real); + int src_reg_b = HOST_REG_GET(uop->src_reg_b_real); + int src_size_a = IREG_GET_SIZE(uop->src_reg_a_real); + int src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); + + if (REG_IS_L(src_size_a) && REG_IS_L(src_size_b)) { + host_arm_CMP_REG(block, src_reg_a, src_reg_b); + } else if (REG_IS_W(src_size_a) && REG_IS_W(src_size_b)) { + host_arm_MOV_REG_LSL(block, REG_TEMP, src_reg_a, 16); + host_arm_CMP_REG_LSL(block, REG_TEMP, src_reg_b, 16); + } else if (REG_IS_B(src_size_a) && REG_IS_B(src_size_b)) { + host_arm_MOV_REG_LSL(block, REG_TEMP, src_reg_a, 24); + host_arm_CMP_REG_LSL(block, REG_TEMP, src_reg_b, 24); + } else + fatal("CMP_JNB_DEST %02x\n", uop->src_reg_a_real); + + uop->p = host_arm_BCS_(block); + + return 0; +} +static int +codegen_CMP_JNBE_DEST(codeblock_t *block, uop_t *uop) +{ + int src_reg_a = HOST_REG_GET(uop->src_reg_a_real); + int src_reg_b = HOST_REG_GET(uop->src_reg_b_real); + int src_size_a = IREG_GET_SIZE(uop->src_reg_a_real); + int src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); + + if (REG_IS_L(src_size_a) && REG_IS_L(src_size_b)) { + host_arm_CMP_REG(block, src_reg_a, src_reg_b); + } else if (REG_IS_W(src_size_a) && REG_IS_W(src_size_b)) { + host_arm_MOV_REG_LSL(block, REG_TEMP, src_reg_a, 16); + host_arm_CMP_REG_LSL(block, REG_TEMP, src_reg_b, 16); + } else if (REG_IS_B(src_size_a) && REG_IS_B(src_size_b)) { + host_arm_MOV_REG_LSL(block, REG_TEMP, src_reg_a, 24); + host_arm_CMP_REG_LSL(block, REG_TEMP, src_reg_b, 24); + } else + fatal("CMP_JNBE_DEST %02x\n", uop->src_reg_a_real); + + uop->p = host_arm_BHI_(block); + + return 0; +} +static int +codegen_CMP_JNL_DEST(codeblock_t *block, uop_t *uop) +{ + int src_reg_a = HOST_REG_GET(uop->src_reg_a_real); + int src_reg_b = HOST_REG_GET(uop->src_reg_b_real); + int src_size_a = IREG_GET_SIZE(uop->src_reg_a_real); + int src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); + + if (REG_IS_L(src_size_a) && REG_IS_L(src_size_b)) { + host_arm_CMP_REG(block, src_reg_a, src_reg_b); + } else if (REG_IS_W(src_size_a) && REG_IS_W(src_size_b)) { + host_arm_MOV_REG_LSL(block, REG_TEMP, src_reg_a, 16); + host_arm_CMP_REG_LSL(block, REG_TEMP, src_reg_b, 16); + } else if (REG_IS_B(src_size_a) && REG_IS_B(src_size_b)) { + host_arm_MOV_REG_LSL(block, REG_TEMP, src_reg_a, 24); + host_arm_CMP_REG_LSL(block, REG_TEMP, src_reg_b, 24); + } else + fatal("CMP_JNL_DEST %02x\n", uop->src_reg_a_real); + + uop->p = host_arm_BGE_(block); + + return 0; +} +static int +codegen_CMP_JNLE_DEST(codeblock_t *block, uop_t *uop) +{ + int src_reg_a = HOST_REG_GET(uop->src_reg_a_real); + int src_reg_b = HOST_REG_GET(uop->src_reg_b_real); + int src_size_a = IREG_GET_SIZE(uop->src_reg_a_real); + int src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); + + if (REG_IS_L(src_size_a) && REG_IS_L(src_size_b)) { + host_arm_CMP_REG(block, src_reg_a, src_reg_b); + } else if (REG_IS_W(src_size_a) && REG_IS_W(src_size_b)) { + host_arm_MOV_REG_LSL(block, REG_TEMP, src_reg_a, 16); + host_arm_CMP_REG_LSL(block, REG_TEMP, src_reg_b, 16); + } else if (REG_IS_B(src_size_a) && REG_IS_B(src_size_b)) { + host_arm_MOV_REG_LSL(block, REG_TEMP, src_reg_a, 24); + host_arm_CMP_REG_LSL(block, REG_TEMP, src_reg_b, 24); + } else + fatal("CMP_JNLE_DEST %02x\n", uop->src_reg_a_real); + + uop->p = host_arm_BGT_(block); + + return 0; +} +static int +codegen_CMP_JNO_DEST(codeblock_t *block, uop_t *uop) +{ + int src_reg_a = HOST_REG_GET(uop->src_reg_a_real); + int src_reg_b = HOST_REG_GET(uop->src_reg_b_real); + int src_size_a = IREG_GET_SIZE(uop->src_reg_a_real); + int src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); + + if (REG_IS_L(src_size_a) && REG_IS_L(src_size_b)) { + host_arm_CMP_REG(block, src_reg_a, src_reg_b); + } else if (REG_IS_W(src_size_a) && REG_IS_W(src_size_b)) { + host_arm_MOV_REG_LSL(block, REG_TEMP, src_reg_a, 16); + host_arm_CMP_REG_LSL(block, REG_TEMP, src_reg_b, 16); + } else if (REG_IS_B(src_size_a) && REG_IS_B(src_size_b)) { + host_arm_MOV_REG_LSL(block, REG_TEMP, src_reg_a, 24); + host_arm_CMP_REG_LSL(block, REG_TEMP, src_reg_b, 24); + } else + fatal("CMP_JNO_DEST %02x\n", uop->src_reg_a_real); + + uop->p = host_arm_BVC_(block); + + return 0; +} +static int +codegen_CMP_JNZ_DEST(codeblock_t *block, uop_t *uop) +{ + int src_reg_a = HOST_REG_GET(uop->src_reg_a_real); + int src_reg_b = HOST_REG_GET(uop->src_reg_b_real); + int src_size_a = IREG_GET_SIZE(uop->src_reg_a_real); + int src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); + + if (REG_IS_L(src_size_a) && REG_IS_L(src_size_b)) { + host_arm_CMP_REG(block, src_reg_a, src_reg_b); + } else if (REG_IS_W(src_size_a) && REG_IS_W(src_size_b)) { + host_arm_MOV_REG_LSL(block, REG_TEMP, src_reg_a, 16); + host_arm_CMP_REG_LSL(block, REG_TEMP, src_reg_b, 16); + } else if (REG_IS_B(src_size_a) && REG_IS_B(src_size_b)) { + host_arm_MOV_REG_LSL(block, REG_TEMP, src_reg_a, 24); + host_arm_CMP_REG_LSL(block, REG_TEMP, src_reg_b, 24); + } else + fatal("CMP_JNZ_DEST %02x\n", uop->src_reg_a_real); + + uop->p = host_arm_BNE_(block); + + return 0; +} +static int +codegen_CMP_JB_DEST(codeblock_t *block, uop_t *uop) +{ + int src_reg_a = HOST_REG_GET(uop->src_reg_a_real); + int src_reg_b = HOST_REG_GET(uop->src_reg_b_real); + int src_size_a = IREG_GET_SIZE(uop->src_reg_a_real); + int src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); + + if (REG_IS_L(src_size_a) && REG_IS_L(src_size_b)) { + host_arm_CMP_REG(block, src_reg_a, src_reg_b); + } else if (REG_IS_W(src_size_a) && REG_IS_W(src_size_b)) { + host_arm_MOV_REG_LSL(block, REG_TEMP, src_reg_a, 16); + host_arm_CMP_REG_LSL(block, REG_TEMP, src_reg_b, 16); + } else if (REG_IS_B(src_size_a) && REG_IS_B(src_size_b)) { + host_arm_MOV_REG_LSL(block, REG_TEMP, src_reg_a, 24); + host_arm_CMP_REG_LSL(block, REG_TEMP, src_reg_b, 24); + } else + fatal("CMP_JB_DEST %02x\n", uop->src_reg_a_real); + + uop->p = host_arm_BCC_(block); + + return 0; +} +static int +codegen_CMP_JBE_DEST(codeblock_t *block, uop_t *uop) +{ + int src_reg_a = HOST_REG_GET(uop->src_reg_a_real); + int src_reg_b = HOST_REG_GET(uop->src_reg_b_real); + int src_size_a = IREG_GET_SIZE(uop->src_reg_a_real); + int src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); + + if (REG_IS_L(src_size_a) && REG_IS_L(src_size_b)) { + host_arm_CMP_REG(block, src_reg_a, src_reg_b); + } else if (REG_IS_W(src_size_a) && REG_IS_W(src_size_b)) { + host_arm_MOV_REG_LSL(block, REG_TEMP, src_reg_a, 16); + host_arm_CMP_REG_LSL(block, REG_TEMP, src_reg_b, 16); + } else if (REG_IS_B(src_size_a) && REG_IS_B(src_size_b)) { + host_arm_MOV_REG_LSL(block, REG_TEMP, src_reg_a, 24); + host_arm_CMP_REG_LSL(block, REG_TEMP, src_reg_b, 24); + } else + fatal("CMP_JBE_DEST %02x\n", uop->src_reg_a_real); + + uop->p = host_arm_BLS_(block); + + return 0; +} +static int +codegen_CMP_JL_DEST(codeblock_t *block, uop_t *uop) +{ + int src_reg_a = HOST_REG_GET(uop->src_reg_a_real); + int src_reg_b = HOST_REG_GET(uop->src_reg_b_real); + int src_size_a = IREG_GET_SIZE(uop->src_reg_a_real); + int src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); + + if (REG_IS_L(src_size_a) && REG_IS_L(src_size_b)) { + host_arm_CMP_REG(block, src_reg_a, src_reg_b); + } else if (REG_IS_W(src_size_a) && REG_IS_W(src_size_b)) { + host_arm_MOV_REG_LSL(block, REG_TEMP, src_reg_a, 16); + host_arm_CMP_REG_LSL(block, REG_TEMP, src_reg_b, 16); + } else if (REG_IS_B(src_size_a) && REG_IS_B(src_size_b)) { + host_arm_MOV_REG_LSL(block, REG_TEMP, src_reg_a, 24); + host_arm_CMP_REG_LSL(block, REG_TEMP, src_reg_b, 24); + } else + fatal("CMP_JL_DEST %02x\n", uop->src_reg_a_real); + + uop->p = host_arm_BLT_(block); + + return 0; +} +static int +codegen_CMP_JLE_DEST(codeblock_t *block, uop_t *uop) +{ + int src_reg_a = HOST_REG_GET(uop->src_reg_a_real); + int src_reg_b = HOST_REG_GET(uop->src_reg_b_real); + int src_size_a = IREG_GET_SIZE(uop->src_reg_a_real); + int src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); + + if (REG_IS_L(src_size_a) && REG_IS_L(src_size_b)) { + host_arm_CMP_REG(block, src_reg_a, src_reg_b); + } else if (REG_IS_W(src_size_a) && REG_IS_W(src_size_b)) { + host_arm_MOV_REG_LSL(block, REG_TEMP, src_reg_a, 16); + host_arm_CMP_REG_LSL(block, REG_TEMP, src_reg_b, 16); + } else if (REG_IS_B(src_size_a) && REG_IS_B(src_size_b)) { + host_arm_MOV_REG_LSL(block, REG_TEMP, src_reg_a, 24); + host_arm_CMP_REG_LSL(block, REG_TEMP, src_reg_b, 24); + } else + fatal("CMP_JLE_DEST %02x\n", uop->src_reg_a_real); + + uop->p = host_arm_BLE_(block); + + return 0; +} +static int +codegen_CMP_JO_DEST(codeblock_t *block, uop_t *uop) +{ + int src_reg_a = HOST_REG_GET(uop->src_reg_a_real); + int src_reg_b = HOST_REG_GET(uop->src_reg_b_real); + int src_size_a = IREG_GET_SIZE(uop->src_reg_a_real); + int src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); + + if (REG_IS_L(src_size_a) && REG_IS_L(src_size_b)) { + host_arm_CMP_REG(block, src_reg_a, src_reg_b); + } else if (REG_IS_W(src_size_a) && REG_IS_W(src_size_b)) { + host_arm_MOV_REG_LSL(block, REG_TEMP, src_reg_a, 16); + host_arm_CMP_REG_LSL(block, REG_TEMP, src_reg_b, 16); + } else if (REG_IS_B(src_size_a) && REG_IS_B(src_size_b)) { + host_arm_MOV_REG_LSL(block, REG_TEMP, src_reg_a, 24); + host_arm_CMP_REG_LSL(block, REG_TEMP, src_reg_b, 24); + } else + fatal("CMP_JO_DEST %02x\n", uop->src_reg_a_real); + + uop->p = host_arm_BVS_(block); + + return 0; +} +static int +codegen_CMP_JZ_DEST(codeblock_t *block, uop_t *uop) +{ + int src_reg_a = HOST_REG_GET(uop->src_reg_a_real); + int src_reg_b = HOST_REG_GET(uop->src_reg_b_real); + int src_size_a = IREG_GET_SIZE(uop->src_reg_a_real); + int src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); + + if (REG_IS_L(src_size_a) && REG_IS_L(src_size_b)) { + host_arm_CMP_REG(block, src_reg_a, src_reg_b); + } else if (REG_IS_W(src_size_a) && REG_IS_W(src_size_b)) { + host_arm_MOV_REG_LSL(block, REG_TEMP, src_reg_a, 16); + host_arm_CMP_REG_LSL(block, REG_TEMP, src_reg_b, 16); + } else if (REG_IS_B(src_size_a) && REG_IS_B(src_size_b)) { + host_arm_MOV_REG_LSL(block, REG_TEMP, src_reg_a, 24); + host_arm_CMP_REG_LSL(block, REG_TEMP, src_reg_b, 24); + } else + fatal("CMP_JZ_DEST %02x\n", uop->src_reg_a_real); + + uop->p = host_arm_BEQ_(block); + + return 0; +} + +static int +codegen_FABS(codeblock_t *block, uop_t *uop) +{ + int dest_reg = HOST_REG_GET(uop->dest_reg_a_real); + int src_reg_a = HOST_REG_GET(uop->src_reg_a_real); + int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real); + int src_size_a = IREG_GET_SIZE(uop->src_reg_a_real); + + if (REG_IS_D(dest_size) && REG_IS_D(src_size_a)) { + host_arm_VABS_D(block, dest_reg, src_reg_a); + } else + fatal("codegen_FABS %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real); + + return 0; +} +static int +codegen_FCHS(codeblock_t *block, uop_t *uop) +{ + int dest_reg = HOST_REG_GET(uop->dest_reg_a_real); + int src_reg_a = HOST_REG_GET(uop->src_reg_a_real); + int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real); + int src_size_a = IREG_GET_SIZE(uop->src_reg_a_real); + + if (REG_IS_D(dest_size) && REG_IS_D(src_size_a)) { + host_arm_VNEG_D(block, dest_reg, src_reg_a); + } else + fatal("codegen_FCHS %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real); + + return 0; +} +static int +codegen_FSQRT(codeblock_t *block, uop_t *uop) +{ + int dest_reg = HOST_REG_GET(uop->dest_reg_a_real); + int src_reg_a = HOST_REG_GET(uop->src_reg_a_real); + int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real); + int src_size_a = IREG_GET_SIZE(uop->src_reg_a_real); + + if (REG_IS_D(dest_size) && REG_IS_D(src_size_a)) { + host_arm_VSQRT_D(block, dest_reg, src_reg_a); + } else + fatal("codegen_FSQRT %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real); + + return 0; +} +static int +codegen_FTST(codeblock_t *block, uop_t *uop) +{ + int dest_reg = HOST_REG_GET(uop->dest_reg_a_real); + int src_reg_a = HOST_REG_GET(uop->src_reg_a_real); + int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real); + int src_size_a = IREG_GET_SIZE(uop->src_reg_a_real); + + if (REG_IS_W(dest_size) && REG_IS_D(src_size_a)) { + host_arm_VSUB_D(block, REG_D_TEMP, REG_D_TEMP, REG_D_TEMP); + host_arm_VCMP_D(block, src_reg_a, REG_D_TEMP); + host_arm_MOV_IMM(block, dest_reg, 0); + host_arm_VMRS_APSR(block); + host_arm_ORREQ_IMM(block, dest_reg, dest_reg, C3); + host_arm_ORRCC_IMM(block, dest_reg, dest_reg, C0); + host_arm_ORRVS_IMM(block, dest_reg, dest_reg, C0 | C2 | C3); + } else + fatal("codegen_FTST %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real); + + return 0; +} + +static int +codegen_FADD(codeblock_t *block, uop_t *uop) +{ + int dest_reg = HOST_REG_GET(uop->dest_reg_a_real); + int src_reg_a = HOST_REG_GET(uop->src_reg_a_real); + int src_reg_b = HOST_REG_GET(uop->src_reg_b_real); + int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real); + int src_size_a = IREG_GET_SIZE(uop->src_reg_a_real); + int src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); + + if (REG_IS_D(dest_size) && REG_IS_D(src_size_a) && REG_IS_D(src_size_b)) { + host_arm_VADD_D(block, dest_reg, src_reg_a, src_reg_b); + } else + fatal("codegen_FADD %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real); + + return 0; +} +static int +codegen_FCOM(codeblock_t *block, uop_t *uop) +{ + int dest_reg = HOST_REG_GET(uop->dest_reg_a_real); + int src_reg_a = HOST_REG_GET(uop->src_reg_a_real); + int src_reg_b = HOST_REG_GET(uop->src_reg_b_real); + int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real); + int src_size_a = IREG_GET_SIZE(uop->src_reg_a_real); + int src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); + + if (REG_IS_W(dest_size) && REG_IS_D(src_size_a) && REG_IS_D(src_size_b)) { + host_arm_VCMP_D(block, src_reg_a, src_reg_b); + host_arm_MOV_IMM(block, dest_reg, 0); + host_arm_VMRS_APSR(block); + host_arm_ORREQ_IMM(block, dest_reg, dest_reg, C3); + host_arm_ORRCC_IMM(block, dest_reg, dest_reg, C0); + host_arm_ORRVS_IMM(block, dest_reg, dest_reg, C0 | C2 | C3); + } else + fatal("codegen_FCOM %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real); + + return 0; +} +static int +codegen_FDIV(codeblock_t *block, uop_t *uop) +{ + int dest_reg = HOST_REG_GET(uop->dest_reg_a_real); + int src_reg_a = HOST_REG_GET(uop->src_reg_a_real); + int src_reg_b = HOST_REG_GET(uop->src_reg_b_real); + int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real); + int src_size_a = IREG_GET_SIZE(uop->src_reg_a_real); + int src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); + + if (REG_IS_D(dest_size) && REG_IS_D(src_size_a) && REG_IS_D(src_size_b)) { + host_arm_VDIV_D(block, dest_reg, src_reg_a, src_reg_b); + } else + fatal("codegen_FDIV %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real); + + return 0; +} +static int +codegen_FMUL(codeblock_t *block, uop_t *uop) +{ + int dest_reg = HOST_REG_GET(uop->dest_reg_a_real); + int src_reg_a = HOST_REG_GET(uop->src_reg_a_real); + int src_reg_b = HOST_REG_GET(uop->src_reg_b_real); + int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real); + int src_size_a = IREG_GET_SIZE(uop->src_reg_a_real); + int src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); + + if (REG_IS_D(dest_size) && REG_IS_D(src_size_a) && REG_IS_D(src_size_b)) { + host_arm_VMUL_D(block, dest_reg, src_reg_a, src_reg_b); + } else + fatal("codegen_FMUL %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real); + + return 0; +} +static int +codegen_FSUB(codeblock_t *block, uop_t *uop) +{ + int dest_reg = HOST_REG_GET(uop->dest_reg_a_real); + int src_reg_a = HOST_REG_GET(uop->src_reg_a_real); + int src_reg_b = HOST_REG_GET(uop->src_reg_b_real); + int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real); + int src_size_a = IREG_GET_SIZE(uop->src_reg_a_real); + int src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); + + if (REG_IS_D(dest_size) && REG_IS_D(src_size_a) && REG_IS_D(src_size_b)) { + host_arm_VSUB_D(block, dest_reg, src_reg_a, src_reg_b); + } else + fatal("codegen_FSUB %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real); + + return 0; +} + +static int +codegen_FP_ENTER(codeblock_t *block, uop_t *uop) +{ + uint32_t *branch_ptr; + + if (!in_range(&cr0, &cpu_state)) + fatal("codegen_FP_ENTER - out of range\n"); + + host_arm_LDR_IMM(block, REG_TEMP, REG_CPUSTATE, (uintptr_t) &cr0 - (uintptr_t) &cpu_state); + host_arm_TST_IMM(block, REG_TEMP, 0xc); + branch_ptr = host_arm_BEQ_(block); + + host_arm_MOV_IMM(block, REG_TEMP, uop->imm_data); + host_arm_STR_IMM(block, REG_TEMP, REG_CPUSTATE, (uintptr_t) &cpu_state.oldpc - (uintptr_t) &cpu_state); + host_arm_MOV_IMM(block, REG_ARG0, 7); + host_arm_call(block, x86_int); + host_arm_B(block, (uintptr_t) codegen_exit_rout); + + *branch_ptr |= ((((uintptr_t) &block_write_data[block_pos] - (uintptr_t) branch_ptr) - 8) & 0x3fffffc) >> 2; + + return 0; +} +static int +codegen_MMX_ENTER(codeblock_t *block, uop_t *uop) +{ + uint32_t *branch_ptr; + + if (!in_range(&cr0, &cpu_state)) + fatal("codegen_MMX_ENTER - out of range\n"); + + host_arm_LDR_IMM(block, REG_TEMP, REG_CPUSTATE, (uintptr_t) &cr0 - (uintptr_t) &cpu_state); + host_arm_TST_IMM(block, REG_TEMP, 0xc); + branch_ptr = host_arm_BEQ_(block); + + host_arm_MOV_IMM(block, REG_TEMP, uop->imm_data); + host_arm_STR_IMM(block, REG_TEMP, REG_CPUSTATE, (uintptr_t) &cpu_state.oldpc - (uintptr_t) &cpu_state); + host_arm_MOV_IMM(block, REG_ARG0, 7); + host_arm_call(block, x86_int); + host_arm_B(block, (uintptr_t) codegen_exit_rout); + + *branch_ptr |= ((((uintptr_t) &block_write_data[block_pos] - (uintptr_t) branch_ptr) - 8) & 0x3fffffc) >> 2; + + host_arm_MOV_IMM(block, REG_TEMP, 0x01010101); + host_arm_STR_IMM(block, REG_TEMP, REG_CPUSTATE, (uintptr_t) &cpu_state.tag[0] - (uintptr_t) &cpu_state); + host_arm_STR_IMM(block, REG_TEMP, REG_CPUSTATE, (uintptr_t) &cpu_state.tag[4] - (uintptr_t) &cpu_state); + host_arm_MOV_IMM(block, REG_TEMP, 0); + host_arm_STR_IMM(block, REG_TEMP, REG_CPUSTATE, (uintptr_t) &cpu_state.TOP - (uintptr_t) &cpu_state); + host_arm_STRB_IMM(block, REG_TEMP, REG_CPUSTATE, (uintptr_t) &cpu_state.ismmx - (uintptr_t) &cpu_state); + + return 0; +} + +static int +codegen_JMP(codeblock_t *block, uop_t *uop) +{ + host_arm_B(block, (uintptr_t) uop->p); + + return 0; +} + +static int +codegen_LOAD_FUNC_ARG0(codeblock_t *block, uop_t *uop) +{ + int src_reg = HOST_REG_GET(uop->src_reg_a_real); + int src_size = IREG_GET_SIZE(uop->src_reg_a_real); + + if (REG_IS_W(src_size)) { + host_arm_UXTH(block, REG_ARG0, src_reg, 0); + } else + fatal("codegen_LOAD_FUNC_ARG0 %02x\n", uop->src_reg_a_real); + + return 0; +} +static int +codegen_LOAD_FUNC_ARG1(codeblock_t *block, uop_t *uop) +{ + fatal("codegen_LOAD_FUNC_ARG1 %02x\n", uop->src_reg_a_real); + return 0; +} +static int +codegen_LOAD_FUNC_ARG2(codeblock_t *block, uop_t *uop) +{ + fatal("codegen_LOAD_FUNC_ARG2 %02x\n", uop->src_reg_a_real); + return 0; +} +static int +codegen_LOAD_FUNC_ARG3(codeblock_t *block, uop_t *uop) +{ + fatal("codegen_LOAD_FUNC_ARG3 %02x\n", uop->src_reg_a_real); + return 0; +} + +static int +codegen_LOAD_FUNC_ARG0_IMM(codeblock_t *block, uop_t *uop) +{ + host_arm_MOV_IMM(block, REG_ARG0, uop->imm_data); + return 0; +} +static int +codegen_LOAD_FUNC_ARG1_IMM(codeblock_t *block, uop_t *uop) +{ + host_arm_MOV_IMM(block, REG_ARG1, uop->imm_data); + return 0; +} +static int +codegen_LOAD_FUNC_ARG2_IMM(codeblock_t *block, uop_t *uop) +{ + host_arm_MOV_IMM(block, REG_ARG2, uop->imm_data); + return 0; +} +static int +codegen_LOAD_FUNC_ARG3_IMM(codeblock_t *block, uop_t *uop) +{ + host_arm_MOV_IMM(block, REG_ARG3, uop->imm_data); + return 0; +} + +static int +codegen_LOAD_SEG(codeblock_t *block, uop_t *uop) +{ + int src_reg = HOST_REG_GET(uop->src_reg_a_real); + int src_size = IREG_GET_SIZE(uop->src_reg_a_real); + + if (!REG_IS_W(src_size)) + fatal("LOAD_SEG %02x %p\n", uop->src_reg_a_real, uop->p); + host_arm_UXTH(block, REG_ARG0, src_reg, 0); + host_arm_MOV_IMM(block, REG_ARG1, (uint32_t) uop->p); + host_arm_call(block, loadseg); + host_arm_TST_REG(block, REG_R0, REG_R0); + host_arm_BNE(block, (uintptr_t) codegen_exit_rout); + + return 0; +} + +static int +codegen_MEM_LOAD_ABS(codeblock_t *block, uop_t *uop) +{ + int dest_reg = HOST_REG_GET(uop->dest_reg_a_real); + int seg_reg = HOST_REG_GET(uop->src_reg_a_real); + int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real); + + host_arm_ADD_IMM(block, REG_R0, seg_reg, uop->imm_data); + if (REG_IS_B(dest_size) || REG_IS_BH(dest_size)) { + host_arm_BL(block, (uintptr_t) codegen_mem_load_byte); + } else if (REG_IS_W(dest_size)) { + host_arm_BL(block, (uintptr_t) codegen_mem_load_word); + } else if (REG_IS_L(dest_size)) { + host_arm_BL(block, (uintptr_t) codegen_mem_load_long); + } else + fatal("MEM_LOAD_ABS - %02x\n", uop->dest_reg_a_real); + host_arm_TST_REG(block, REG_R1, REG_R1); + host_arm_BNE(block, (uintptr_t) codegen_exit_rout); + if (REG_IS_B(dest_size)) { + host_arm_BFI(block, dest_reg, REG_R0, 0, 8); + } else if (REG_IS_BH(dest_size)) { + host_arm_BFI(block, dest_reg, REG_R0, 8, 8); + } else if (REG_IS_W(dest_size)) { + host_arm_BFI(block, dest_reg, REG_R0, 0, 16); + } else if (REG_IS_L(dest_size)) { host_arm_MOV_REG(block, dest_reg, REG_R0); + } - return 0; + return 0; } -static int codegen_CALL_INSTRUCTION_FUNC(codeblock_t *block, uop_t *uop) +static int +codegen_MEM_LOAD_REG(codeblock_t *block, uop_t *uop) { - host_arm_call(block, uop->p); - host_arm_TST_REG(block, REG_R0, REG_R0); - host_arm_BNE(block, (uintptr_t)codegen_exit_rout); + int dest_reg = HOST_REG_GET(uop->dest_reg_a_real); + int seg_reg = HOST_REG_GET(uop->src_reg_a_real); + int addr_reg = HOST_REG_GET(uop->src_reg_b_real); + int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real); - return 0; + host_arm_ADD_REG(block, REG_R0, seg_reg, addr_reg); + if (uop->imm_data) + host_arm_ADD_IMM(block, REG_R0, REG_R0, uop->imm_data); + if (REG_IS_B(dest_size) || REG_IS_BH(dest_size)) { + host_arm_BL(block, (uintptr_t) codegen_mem_load_byte); + } else if (REG_IS_W(dest_size)) { + host_arm_BL(block, (uintptr_t) codegen_mem_load_word); + } else if (REG_IS_L(dest_size)) { + host_arm_BL(block, (uintptr_t) codegen_mem_load_long); + } else if (REG_IS_Q(dest_size)) { + host_arm_BL(block, (uintptr_t) codegen_mem_load_quad); + } else + fatal("MEM_LOAD_REG - %02x\n", uop->dest_reg_a_real); + host_arm_TST_REG(block, REG_R1, REG_R1); + host_arm_BNE(block, (uintptr_t) codegen_exit_rout); + if (REG_IS_B(dest_size)) { + host_arm_BFI(block, dest_reg, REG_R0, 0, 8); + } else if (REG_IS_BH(dest_size)) { + host_arm_BFI(block, dest_reg, REG_R0, 8, 8); + } else if (REG_IS_W(dest_size)) { + host_arm_BFI(block, dest_reg, REG_R0, 0, 16); + } else if (REG_IS_L(dest_size)) { + host_arm_MOV_REG(block, dest_reg, REG_R0); + } else if (REG_IS_Q(dest_size)) { + host_arm_VMOV_D_D(block, dest_reg, REG_D_TEMP); + } + + return 0; +} +static int +codegen_MEM_LOAD_SINGLE(codeblock_t *block, uop_t *uop) +{ + int dest_reg = HOST_REG_GET(uop->dest_reg_a_real); + int seg_reg = HOST_REG_GET(uop->src_reg_a_real); + int addr_reg = HOST_REG_GET(uop->src_reg_b_real); + int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real); + + if (!REG_IS_D(dest_size)) + fatal("MEM_LOAD_SINGLE - %02x\n", uop->dest_reg_a_real); + + host_arm_ADD_REG(block, REG_R0, seg_reg, addr_reg); + if (uop->imm_data) + host_arm_ADD_IMM(block, REG_R0, REG_R0, uop->imm_data); + host_arm_BL(block, (uintptr_t) codegen_mem_load_single); + host_arm_TST_REG(block, REG_R1, REG_R1); + host_arm_BNE(block, (uintptr_t) codegen_exit_rout); + host_arm_VCVT_D_S(block, dest_reg, REG_D_TEMP); + + return 0; +} +static int +codegen_MEM_LOAD_DOUBLE(codeblock_t *block, uop_t *uop) +{ + int dest_reg = HOST_REG_GET(uop->dest_reg_a_real); + int seg_reg = HOST_REG_GET(uop->src_reg_a_real); + int addr_reg = HOST_REG_GET(uop->src_reg_b_real); + int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real); + + if (!REG_IS_D(dest_size)) + fatal("MEM_LOAD_DOUBLE - %02x\n", uop->dest_reg_a_real); + + host_arm_ADD_REG(block, REG_R0, seg_reg, addr_reg); + if (uop->imm_data) + host_arm_ADD_IMM(block, REG_R0, REG_R0, uop->imm_data); + host_arm_BL(block, (uintptr_t) codegen_mem_load_double); + host_arm_TST_REG(block, REG_R1, REG_R1); + host_arm_BNE(block, (uintptr_t) codegen_exit_rout); + host_arm_VMOV_D_D(block, dest_reg, REG_D_TEMP); + + return 0; } -static int codegen_CMP_IMM_JZ(codeblock_t *block, uop_t *uop) +static int +codegen_MEM_STORE_ABS(codeblock_t *block, uop_t *uop) { - int src_reg = HOST_REG_GET(uop->src_reg_a_real); - int src_size = IREG_GET_SIZE(uop->src_reg_a_real); + int seg_reg = HOST_REG_GET(uop->src_reg_a_real); + int src_reg = HOST_REG_GET(uop->src_reg_b_real); + int src_size = IREG_GET_SIZE(uop->src_reg_b_real); - if (REG_IS_L(src_size)) - { - host_arm_CMP_IMM(block, src_reg, uop->imm_data); - } - else - fatal("CMP_IMM_JZ %02x\n", uop->src_reg_a_real); - host_arm_BEQ(block, (uintptr_t)uop->p); + host_arm_ADD_IMM(block, REG_R0, seg_reg, uop->imm_data); + if (REG_IS_B(src_size)) { + host_arm_MOV_REG(block, REG_R1, src_reg); + host_arm_BL(block, (uintptr_t) codegen_mem_store_byte); + } else if (REG_IS_W(src_size)) { + host_arm_MOV_REG(block, REG_R1, src_reg); + host_arm_BL(block, (uintptr_t) codegen_mem_store_word); + } else if (REG_IS_L(src_size)) { + host_arm_MOV_REG(block, REG_R1, src_reg); + host_arm_BL(block, (uintptr_t) codegen_mem_store_long); + } else + fatal("MEM_STORE_ABS - %02x\n", uop->src_reg_b_real); + host_arm_TST_REG(block, REG_R1, REG_R1); + host_arm_BNE(block, (uintptr_t) codegen_exit_rout); - return 0; + return 0; } -static int codegen_CMP_IMM_JNZ_DEST(codeblock_t *block, uop_t *uop) +static int +codegen_MEM_STORE_REG(codeblock_t *block, uop_t *uop) { - int src_reg = HOST_REG_GET(uop->src_reg_a_real); - int src_size = IREG_GET_SIZE(uop->src_reg_a_real); + int seg_reg = HOST_REG_GET(uop->src_reg_a_real); + int addr_reg = HOST_REG_GET(uop->src_reg_b_real); + int src_reg = HOST_REG_GET(uop->src_reg_c_real); + int src_size = IREG_GET_SIZE(uop->src_reg_c_real); - if (REG_IS_L(src_size)) - { - host_arm_CMP_IMM(block, src_reg, uop->imm_data); - } - else if (REG_IS_W(src_size)) - { - host_arm_UXTH(block, REG_TEMP, src_reg, 0); - host_arm_CMP_IMM(block, REG_TEMP, uop->imm_data); - } - else - fatal("CMP_IMM_JNZ_DEST %02x\n", uop->src_reg_a_real); + host_arm_ADD_REG(block, REG_R0, seg_reg, addr_reg); + if (uop->imm_data) + host_arm_ADD_IMM(block, REG_R0, REG_R0, uop->imm_data); + if (REG_IS_B(src_size)) { + host_arm_MOV_REG(block, REG_R1, src_reg); + host_arm_BL(block, (uintptr_t) codegen_mem_store_byte); + } else if (REG_IS_BH(src_size)) { + host_arm_MOV_REG_LSR(block, REG_R1, src_reg, 8); + host_arm_BL(block, (uintptr_t) codegen_mem_store_byte); + } else if (REG_IS_W(src_size)) { + host_arm_MOV_REG(block, REG_R1, src_reg); + host_arm_BL(block, (uintptr_t) codegen_mem_store_word); + } else if (REG_IS_L(src_size)) { + host_arm_MOV_REG(block, REG_R1, src_reg); + host_arm_BL(block, (uintptr_t) codegen_mem_store_long); + } else if (REG_IS_Q(src_size)) { + host_arm_VMOV_D_D(block, REG_D_TEMP, src_reg); + host_arm_BL(block, (uintptr_t) codegen_mem_store_quad); + } else + fatal("MEM_STORE_REG - %02x\n", uop->src_reg_c_real); + host_arm_TST_REG(block, REG_R1, REG_R1); + host_arm_BNE(block, (uintptr_t) codegen_exit_rout); - uop->p = host_arm_BNE_(block); - - return 0; -} -static int codegen_CMP_IMM_JZ_DEST(codeblock_t *block, uop_t *uop) -{ - int src_reg = HOST_REG_GET(uop->src_reg_a_real); - int src_size = IREG_GET_SIZE(uop->src_reg_a_real); - - if (REG_IS_L(src_size)) - { - host_arm_CMP_IMM(block, src_reg, uop->imm_data); - } - else if (REG_IS_W(src_size)) - { - host_arm_UXTH(block, REG_TEMP, src_reg, 0); - host_arm_CMP_IMM(block, REG_TEMP, uop->imm_data); - } - else - fatal("CMP_IMM_JZ_DEST %02x\n", uop->src_reg_a_real); - - uop->p = host_arm_BEQ_(block); - - return 0; + return 0; } -static int codegen_CMP_JB(codeblock_t *block, uop_t *uop) +static int +codegen_MEM_STORE_IMM_8(codeblock_t *block, uop_t *uop) { - int src_reg_a = HOST_REG_GET(uop->src_reg_a_real), src_reg_b = HOST_REG_GET(uop->src_reg_b_real); - int src_size_a = IREG_GET_SIZE(uop->src_reg_a_real), src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); - uint32_t *jump_p; + int seg_reg = HOST_REG_GET(uop->src_reg_a_real); + int addr_reg = HOST_REG_GET(uop->src_reg_b_real); - if (REG_IS_L(src_size_a) && REG_IS_L(src_size_b)) - { - host_arm_CMP_REG(block, src_reg_a, src_reg_b); - } - else - fatal("CMP_JB %02x\n", uop->src_reg_a_real); + host_arm_ADD_REG(block, REG_R0, seg_reg, addr_reg); + host_arm_MOV_IMM(block, REG_R1, uop->imm_data); + host_arm_BL(block, (uintptr_t) codegen_mem_store_byte); + host_arm_TST_REG(block, REG_R1, REG_R1); + host_arm_BNE(block, (uintptr_t) codegen_exit_rout); - jump_p = host_arm_BCC_(block); - *jump_p |= ((((uintptr_t)uop->p - (uintptr_t)jump_p) - 8) & 0x3fffffc) >> 2; - - return 0; + return 0; } -static int codegen_CMP_JNBE(codeblock_t *block, uop_t *uop) +static int +codegen_MEM_STORE_IMM_16(codeblock_t *block, uop_t *uop) { - int src_reg_a = HOST_REG_GET(uop->src_reg_a_real), src_reg_b = HOST_REG_GET(uop->src_reg_b_real); - int src_size_a = IREG_GET_SIZE(uop->src_reg_a_real), src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); - uint32_t *jump_p; + int seg_reg = HOST_REG_GET(uop->src_reg_a_real); + int addr_reg = HOST_REG_GET(uop->src_reg_b_real); - if (REG_IS_L(src_size_a) && REG_IS_L(src_size_b)) - { - host_arm_CMP_REG(block, src_reg_a, src_reg_b); - } - else - fatal("CMP_JNBE %02x\n", uop->src_reg_a_real); + host_arm_ADD_REG(block, REG_R0, seg_reg, addr_reg); + host_arm_MOV_IMM(block, REG_R1, uop->imm_data); + host_arm_BL(block, (uintptr_t) codegen_mem_store_word); + host_arm_TST_REG(block, REG_R1, REG_R1); + host_arm_BNE(block, (uintptr_t) codegen_exit_rout); - jump_p = host_arm_BHI_(block); - *jump_p |= ((((uintptr_t)uop->p - (uintptr_t)jump_p) - 8) & 0x3fffffc) >> 2; - - return 0; + return 0; +} +static int +codegen_MEM_STORE_IMM_32(codeblock_t *block, uop_t *uop) +{ + int seg_reg = HOST_REG_GET(uop->src_reg_a_real); + int addr_reg = HOST_REG_GET(uop->src_reg_b_real); + + host_arm_ADD_REG(block, REG_R0, seg_reg, addr_reg); + host_arm_MOV_IMM(block, REG_R1, uop->imm_data); + host_arm_BL(block, (uintptr_t) codegen_mem_store_long); + host_arm_TST_REG(block, REG_R1, REG_R1); + host_arm_BNE(block, (uintptr_t) codegen_exit_rout); + + return 0; +} +static int +codegen_MEM_STORE_SINGLE(codeblock_t *block, uop_t *uop) +{ + int seg_reg = HOST_REG_GET(uop->src_reg_a_real); + int addr_reg = HOST_REG_GET(uop->src_reg_b_real); + int src_reg = HOST_REG_GET(uop->src_reg_c_real); + int src_size = IREG_GET_SIZE(uop->src_reg_c_real); + + if (!REG_IS_D(src_size)) + fatal("MEM_STORE_REG - %02x\n", uop->dest_reg_a_real); + + host_arm_ADD_REG(block, REG_R0, seg_reg, addr_reg); + if (uop->imm_data) + host_arm_ADD_IMM(block, REG_R0, REG_R0, uop->imm_data); + host_arm_VCVT_S_D(block, REG_D_TEMP, src_reg); + host_arm_BL(block, (uintptr_t) codegen_mem_store_single); + host_arm_TST_REG(block, REG_R1, REG_R1); + host_arm_BNE(block, (uintptr_t) codegen_exit_rout); + + return 0; +} +static int +codegen_MEM_STORE_DOUBLE(codeblock_t *block, uop_t *uop) +{ + int seg_reg = HOST_REG_GET(uop->src_reg_a_real); + int addr_reg = HOST_REG_GET(uop->src_reg_b_real); + int src_reg = HOST_REG_GET(uop->src_reg_c_real); + int src_size = IREG_GET_SIZE(uop->src_reg_c_real); + + if (!REG_IS_D(src_size)) + fatal("MEM_STORE_REG - %02x\n", uop->dest_reg_a_real); + + host_arm_ADD_REG(block, REG_R0, seg_reg, addr_reg); + if (uop->imm_data) + host_arm_ADD_IMM(block, REG_R0, REG_R0, uop->imm_data); + host_arm_VMOV_D_D(block, REG_D_TEMP, src_reg); + host_arm_BL(block, (uintptr_t) codegen_mem_store_double); + host_arm_TST_REG(block, REG_R1, REG_R1); + host_arm_BNE(block, (uintptr_t) codegen_exit_rout); + + return 0; } -static int codegen_CMP_JNB_DEST(codeblock_t *block, uop_t *uop) +static int +codegen_MOV(codeblock_t *block, uop_t *uop) { - int src_reg_a = HOST_REG_GET(uop->src_reg_a_real), src_reg_b = HOST_REG_GET(uop->src_reg_b_real); - int src_size_a = IREG_GET_SIZE(uop->src_reg_a_real), src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); + int dest_reg = HOST_REG_GET(uop->dest_reg_a_real); + int src_reg = HOST_REG_GET(uop->src_reg_a_real); + int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real); + int src_size = IREG_GET_SIZE(uop->src_reg_a_real); - if (REG_IS_L(src_size_a) && REG_IS_L(src_size_b)) - { - host_arm_CMP_REG(block, src_reg_a, src_reg_b); - } - else if (REG_IS_W(src_size_a) && REG_IS_W(src_size_b)) - { - host_arm_MOV_REG_LSL(block, REG_TEMP, src_reg_a, 16); - host_arm_CMP_REG_LSL(block, REG_TEMP, src_reg_b, 16); - } - else if (REG_IS_B(src_size_a) && REG_IS_B(src_size_b)) - { - host_arm_MOV_REG_LSL(block, REG_TEMP, src_reg_a, 24); - host_arm_CMP_REG_LSL(block, REG_TEMP, src_reg_b, 24); - } - else - fatal("CMP_JNB_DEST %02x\n", uop->src_reg_a_real); + if (REG_IS_L(dest_size) && REG_IS_L(src_size)) { + host_arm_MOV_REG_LSL(block, dest_reg, src_reg, 0); + } else if (REG_IS_W(dest_size) && REG_IS_W(src_size)) { + host_arm_BFI(block, dest_reg, src_reg, 0, 16); + } else if (REG_IS_B(dest_size) && REG_IS_B(src_size)) { + host_arm_BFI(block, dest_reg, src_reg, 0, 8); + } else if (REG_IS_BH(dest_size) && REG_IS_B(src_size)) { + host_arm_BFI(block, dest_reg, src_reg, 8, 8); + } else if (REG_IS_B(dest_size) && REG_IS_BH(src_size)) { + host_arm_MOV_REG_LSR(block, REG_TEMP, src_reg, 8); + host_arm_BFI(block, dest_reg, REG_TEMP, 0, 8); + } else if (REG_IS_BH(dest_size) && REG_IS_BH(src_size)) { + host_arm_MOV_REG_LSR(block, REG_TEMP, src_reg, 8); + host_arm_BFI(block, dest_reg, REG_TEMP, 8, 8); + } else if (REG_IS_D(dest_size) && REG_IS_D(src_size)) { + host_arm_VMOV_D_D(block, dest_reg, src_reg); + } else if (REG_IS_Q(dest_size) && REG_IS_Q(src_size)) { + host_arm_VMOV_D_D(block, dest_reg, src_reg); + } else + fatal("MOV %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real); - uop->p = host_arm_BCS_(block); - - return 0; -} -static int codegen_CMP_JNBE_DEST(codeblock_t *block, uop_t *uop) -{ - int src_reg_a = HOST_REG_GET(uop->src_reg_a_real), src_reg_b = HOST_REG_GET(uop->src_reg_b_real); - int src_size_a = IREG_GET_SIZE(uop->src_reg_a_real), src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); - - if (REG_IS_L(src_size_a) && REG_IS_L(src_size_b)) - { - host_arm_CMP_REG(block, src_reg_a, src_reg_b); - } - else if (REG_IS_W(src_size_a) && REG_IS_W(src_size_b)) - { - host_arm_MOV_REG_LSL(block, REG_TEMP, src_reg_a, 16); - host_arm_CMP_REG_LSL(block, REG_TEMP, src_reg_b, 16); - } - else if (REG_IS_B(src_size_a) && REG_IS_B(src_size_b)) - { - host_arm_MOV_REG_LSL(block, REG_TEMP, src_reg_a, 24); - host_arm_CMP_REG_LSL(block, REG_TEMP, src_reg_b, 24); - } - else - fatal("CMP_JNBE_DEST %02x\n", uop->src_reg_a_real); - - uop->p = host_arm_BHI_(block); - - return 0; -} -static int codegen_CMP_JNL_DEST(codeblock_t *block, uop_t *uop) -{ - int src_reg_a = HOST_REG_GET(uop->src_reg_a_real), src_reg_b = HOST_REG_GET(uop->src_reg_b_real); - int src_size_a = IREG_GET_SIZE(uop->src_reg_a_real), src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); - - if (REG_IS_L(src_size_a) && REG_IS_L(src_size_b)) - { - host_arm_CMP_REG(block, src_reg_a, src_reg_b); - } - else if (REG_IS_W(src_size_a) && REG_IS_W(src_size_b)) - { - host_arm_MOV_REG_LSL(block, REG_TEMP, src_reg_a, 16); - host_arm_CMP_REG_LSL(block, REG_TEMP, src_reg_b, 16); - } - else if (REG_IS_B(src_size_a) && REG_IS_B(src_size_b)) - { - host_arm_MOV_REG_LSL(block, REG_TEMP, src_reg_a, 24); - host_arm_CMP_REG_LSL(block, REG_TEMP, src_reg_b, 24); - } - else - fatal("CMP_JNL_DEST %02x\n", uop->src_reg_a_real); - - uop->p = host_arm_BGE_(block); - - return 0; -} -static int codegen_CMP_JNLE_DEST(codeblock_t *block, uop_t *uop) -{ - int src_reg_a = HOST_REG_GET(uop->src_reg_a_real), src_reg_b = HOST_REG_GET(uop->src_reg_b_real); - int src_size_a = IREG_GET_SIZE(uop->src_reg_a_real), src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); - - if (REG_IS_L(src_size_a) && REG_IS_L(src_size_b)) - { - host_arm_CMP_REG(block, src_reg_a, src_reg_b); - } - else if (REG_IS_W(src_size_a) && REG_IS_W(src_size_b)) - { - host_arm_MOV_REG_LSL(block, REG_TEMP, src_reg_a, 16); - host_arm_CMP_REG_LSL(block, REG_TEMP, src_reg_b, 16); - } - else if (REG_IS_B(src_size_a) && REG_IS_B(src_size_b)) - { - host_arm_MOV_REG_LSL(block, REG_TEMP, src_reg_a, 24); - host_arm_CMP_REG_LSL(block, REG_TEMP, src_reg_b, 24); - } - else - fatal("CMP_JNLE_DEST %02x\n", uop->src_reg_a_real); - - uop->p = host_arm_BGT_(block); - - return 0; -} -static int codegen_CMP_JNO_DEST(codeblock_t *block, uop_t *uop) -{ - int src_reg_a = HOST_REG_GET(uop->src_reg_a_real), src_reg_b = HOST_REG_GET(uop->src_reg_b_real); - int src_size_a = IREG_GET_SIZE(uop->src_reg_a_real), src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); - - if (REG_IS_L(src_size_a) && REG_IS_L(src_size_b)) - { - host_arm_CMP_REG(block, src_reg_a, src_reg_b); - } - else if (REG_IS_W(src_size_a) && REG_IS_W(src_size_b)) - { - host_arm_MOV_REG_LSL(block, REG_TEMP, src_reg_a, 16); - host_arm_CMP_REG_LSL(block, REG_TEMP, src_reg_b, 16); - } - else if (REG_IS_B(src_size_a) && REG_IS_B(src_size_b)) - { - host_arm_MOV_REG_LSL(block, REG_TEMP, src_reg_a, 24); - host_arm_CMP_REG_LSL(block, REG_TEMP, src_reg_b, 24); - } - else - fatal("CMP_JNO_DEST %02x\n", uop->src_reg_a_real); - - uop->p = host_arm_BVC_(block); - - return 0; -} -static int codegen_CMP_JNZ_DEST(codeblock_t *block, uop_t *uop) -{ - int src_reg_a = HOST_REG_GET(uop->src_reg_a_real), src_reg_b = HOST_REG_GET(uop->src_reg_b_real); - int src_size_a = IREG_GET_SIZE(uop->src_reg_a_real), src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); - - if (REG_IS_L(src_size_a) && REG_IS_L(src_size_b)) - { - host_arm_CMP_REG(block, src_reg_a, src_reg_b); - } - else if (REG_IS_W(src_size_a) && REG_IS_W(src_size_b)) - { - host_arm_MOV_REG_LSL(block, REG_TEMP, src_reg_a, 16); - host_arm_CMP_REG_LSL(block, REG_TEMP, src_reg_b, 16); - } - else if (REG_IS_B(src_size_a) && REG_IS_B(src_size_b)) - { - host_arm_MOV_REG_LSL(block, REG_TEMP, src_reg_a, 24); - host_arm_CMP_REG_LSL(block, REG_TEMP, src_reg_b, 24); - } - else - fatal("CMP_JNZ_DEST %02x\n", uop->src_reg_a_real); - - uop->p = host_arm_BNE_(block); - - return 0; -} -static int codegen_CMP_JB_DEST(codeblock_t *block, uop_t *uop) -{ - int src_reg_a = HOST_REG_GET(uop->src_reg_a_real), src_reg_b = HOST_REG_GET(uop->src_reg_b_real); - int src_size_a = IREG_GET_SIZE(uop->src_reg_a_real), src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); - - if (REG_IS_L(src_size_a) && REG_IS_L(src_size_b)) - { - host_arm_CMP_REG(block, src_reg_a, src_reg_b); - } - else if (REG_IS_W(src_size_a) && REG_IS_W(src_size_b)) - { - host_arm_MOV_REG_LSL(block, REG_TEMP, src_reg_a, 16); - host_arm_CMP_REG_LSL(block, REG_TEMP, src_reg_b, 16); - } - else if (REG_IS_B(src_size_a) && REG_IS_B(src_size_b)) - { - host_arm_MOV_REG_LSL(block, REG_TEMP, src_reg_a, 24); - host_arm_CMP_REG_LSL(block, REG_TEMP, src_reg_b, 24); - } - else - fatal("CMP_JB_DEST %02x\n", uop->src_reg_a_real); - - uop->p = host_arm_BCC_(block); - - return 0; -} -static int codegen_CMP_JBE_DEST(codeblock_t *block, uop_t *uop) -{ - int src_reg_a = HOST_REG_GET(uop->src_reg_a_real), src_reg_b = HOST_REG_GET(uop->src_reg_b_real); - int src_size_a = IREG_GET_SIZE(uop->src_reg_a_real), src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); - - if (REG_IS_L(src_size_a) && REG_IS_L(src_size_b)) - { - host_arm_CMP_REG(block, src_reg_a, src_reg_b); - } - else if (REG_IS_W(src_size_a) && REG_IS_W(src_size_b)) - { - host_arm_MOV_REG_LSL(block, REG_TEMP, src_reg_a, 16); - host_arm_CMP_REG_LSL(block, REG_TEMP, src_reg_b, 16); - } - else if (REG_IS_B(src_size_a) && REG_IS_B(src_size_b)) - { - host_arm_MOV_REG_LSL(block, REG_TEMP, src_reg_a, 24); - host_arm_CMP_REG_LSL(block, REG_TEMP, src_reg_b, 24); - } - else - fatal("CMP_JBE_DEST %02x\n", uop->src_reg_a_real); - - uop->p = host_arm_BLS_(block); - - return 0; -} -static int codegen_CMP_JL_DEST(codeblock_t *block, uop_t *uop) -{ - int src_reg_a = HOST_REG_GET(uop->src_reg_a_real), src_reg_b = HOST_REG_GET(uop->src_reg_b_real); - int src_size_a = IREG_GET_SIZE(uop->src_reg_a_real), src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); - - if (REG_IS_L(src_size_a) && REG_IS_L(src_size_b)) - { - host_arm_CMP_REG(block, src_reg_a, src_reg_b); - } - else if (REG_IS_W(src_size_a) && REG_IS_W(src_size_b)) - { - host_arm_MOV_REG_LSL(block, REG_TEMP, src_reg_a, 16); - host_arm_CMP_REG_LSL(block, REG_TEMP, src_reg_b, 16); - } - else if (REG_IS_B(src_size_a) && REG_IS_B(src_size_b)) - { - host_arm_MOV_REG_LSL(block, REG_TEMP, src_reg_a, 24); - host_arm_CMP_REG_LSL(block, REG_TEMP, src_reg_b, 24); - } - else - fatal("CMP_JL_DEST %02x\n", uop->src_reg_a_real); - - uop->p = host_arm_BLT_(block); - - return 0; -} -static int codegen_CMP_JLE_DEST(codeblock_t *block, uop_t *uop) -{ - int src_reg_a = HOST_REG_GET(uop->src_reg_a_real), src_reg_b = HOST_REG_GET(uop->src_reg_b_real); - int src_size_a = IREG_GET_SIZE(uop->src_reg_a_real), src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); - - if (REG_IS_L(src_size_a) && REG_IS_L(src_size_b)) - { - host_arm_CMP_REG(block, src_reg_a, src_reg_b); - } - else if (REG_IS_W(src_size_a) && REG_IS_W(src_size_b)) - { - host_arm_MOV_REG_LSL(block, REG_TEMP, src_reg_a, 16); - host_arm_CMP_REG_LSL(block, REG_TEMP, src_reg_b, 16); - } - else if (REG_IS_B(src_size_a) && REG_IS_B(src_size_b)) - { - host_arm_MOV_REG_LSL(block, REG_TEMP, src_reg_a, 24); - host_arm_CMP_REG_LSL(block, REG_TEMP, src_reg_b, 24); - } - else - fatal("CMP_JLE_DEST %02x\n", uop->src_reg_a_real); - - uop->p = host_arm_BLE_(block); - - return 0; -} -static int codegen_CMP_JO_DEST(codeblock_t *block, uop_t *uop) -{ - int src_reg_a = HOST_REG_GET(uop->src_reg_a_real), src_reg_b = HOST_REG_GET(uop->src_reg_b_real); - int src_size_a = IREG_GET_SIZE(uop->src_reg_a_real), src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); - - if (REG_IS_L(src_size_a) && REG_IS_L(src_size_b)) - { - host_arm_CMP_REG(block, src_reg_a, src_reg_b); - } - else if (REG_IS_W(src_size_a) && REG_IS_W(src_size_b)) - { - host_arm_MOV_REG_LSL(block, REG_TEMP, src_reg_a, 16); - host_arm_CMP_REG_LSL(block, REG_TEMP, src_reg_b, 16); - } - else if (REG_IS_B(src_size_a) && REG_IS_B(src_size_b)) - { - host_arm_MOV_REG_LSL(block, REG_TEMP, src_reg_a, 24); - host_arm_CMP_REG_LSL(block, REG_TEMP, src_reg_b, 24); - } - else - fatal("CMP_JO_DEST %02x\n", uop->src_reg_a_real); - - uop->p = host_arm_BVS_(block); - - return 0; -} -static int codegen_CMP_JZ_DEST(codeblock_t *block, uop_t *uop) -{ - int src_reg_a = HOST_REG_GET(uop->src_reg_a_real), src_reg_b = HOST_REG_GET(uop->src_reg_b_real); - int src_size_a = IREG_GET_SIZE(uop->src_reg_a_real), src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); - - if (REG_IS_L(src_size_a) && REG_IS_L(src_size_b)) - { - host_arm_CMP_REG(block, src_reg_a, src_reg_b); - } - else if (REG_IS_W(src_size_a) && REG_IS_W(src_size_b)) - { - host_arm_MOV_REG_LSL(block, REG_TEMP, src_reg_a, 16); - host_arm_CMP_REG_LSL(block, REG_TEMP, src_reg_b, 16); - } - else if (REG_IS_B(src_size_a) && REG_IS_B(src_size_b)) - { - host_arm_MOV_REG_LSL(block, REG_TEMP, src_reg_a, 24); - host_arm_CMP_REG_LSL(block, REG_TEMP, src_reg_b, 24); - } - else - fatal("CMP_JZ_DEST %02x\n", uop->src_reg_a_real); - - uop->p = host_arm_BEQ_(block); - - return 0; + return 0; } -static int codegen_FABS(codeblock_t *block, uop_t *uop) +static int +codegen_MOV_IMM(codeblock_t *block, uop_t *uop) { - int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg_a = HOST_REG_GET(uop->src_reg_a_real); - int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size_a = IREG_GET_SIZE(uop->src_reg_a_real); + int dest_reg = HOST_REG_GET(uop->dest_reg_a_real); + int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real); - if (REG_IS_D(dest_size) && REG_IS_D(src_size_a)) - { - host_arm_VABS_D(block, dest_reg, src_reg_a); - } - else - fatal("codegen_FABS %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real); + if (REG_IS_L(dest_size)) { + host_arm_MOV_IMM(block, dest_reg, uop->imm_data); + } else if (REG_IS_W(dest_size)) { + host_arm_MOVW_IMM(block, REG_TEMP, uop->imm_data); + host_arm_BFI(block, dest_reg, REG_TEMP, 0, 16); + } else if (REG_IS_B(dest_size)) { + host_arm_AND_IMM(block, dest_reg, dest_reg, ~0x000000ff); + host_arm_ORR_IMM(block, dest_reg, dest_reg, uop->imm_data); + } else if (REG_IS_BH(dest_size)) { + host_arm_AND_IMM(block, dest_reg, dest_reg, ~0x0000ff00); + host_arm_ORR_IMM(block, dest_reg, dest_reg, uop->imm_data << 8); + } else + fatal("MOV_IMM %02x\n", uop->dest_reg_a_real); - return 0; + return 0; } -static int codegen_FCHS(codeblock_t *block, uop_t *uop) +static int +codegen_MOV_PTR(codeblock_t *block, uop_t *uop) { - int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg_a = HOST_REG_GET(uop->src_reg_a_real); - int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size_a = IREG_GET_SIZE(uop->src_reg_a_real); + host_arm_MOV_IMM(block, uop->dest_reg_a_real, (uintptr_t) uop->p); - if (REG_IS_D(dest_size) && REG_IS_D(src_size_a)) - { - host_arm_VNEG_D(block, dest_reg, src_reg_a); - } - else - fatal("codegen_FCHS %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real); - - return 0; -} -static int codegen_FSQRT(codeblock_t *block, uop_t *uop) -{ - int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg_a = HOST_REG_GET(uop->src_reg_a_real); - int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size_a = IREG_GET_SIZE(uop->src_reg_a_real); - - if (REG_IS_D(dest_size) && REG_IS_D(src_size_a)) - { - host_arm_VSQRT_D(block, dest_reg, src_reg_a); - } - else - fatal("codegen_FSQRT %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real); - - return 0; -} -static int codegen_FTST(codeblock_t *block, uop_t *uop) -{ - int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg_a = HOST_REG_GET(uop->src_reg_a_real); - int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size_a = IREG_GET_SIZE(uop->src_reg_a_real); - - if (REG_IS_W(dest_size) && REG_IS_D(src_size_a)) - { - host_arm_VSUB_D(block, REG_D_TEMP, REG_D_TEMP, REG_D_TEMP); - host_arm_VCMP_D(block, src_reg_a, REG_D_TEMP); - host_arm_MOV_IMM(block, dest_reg, 0); - host_arm_VMRS_APSR(block); - host_arm_ORREQ_IMM(block, dest_reg, dest_reg, C3); - host_arm_ORRCC_IMM(block, dest_reg, dest_reg, C0); - host_arm_ORRVS_IMM(block, dest_reg, dest_reg, C0|C2|C3); - } - else - fatal("codegen_FTST %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real); - - return 0; + return 0; } -static int codegen_FADD(codeblock_t *block, uop_t *uop) +static int +codegen_MOVSX(codeblock_t *block, uop_t *uop) { - int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg_a = HOST_REG_GET(uop->src_reg_a_real), src_reg_b = HOST_REG_GET(uop->src_reg_b_real); - int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size_a = IREG_GET_SIZE(uop->src_reg_a_real), src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); + int dest_reg = HOST_REG_GET(uop->dest_reg_a_real); + int src_reg = HOST_REG_GET(uop->src_reg_a_real); + int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real); + int src_size = IREG_GET_SIZE(uop->src_reg_a_real); - if (REG_IS_D(dest_size) && REG_IS_D(src_size_a) && REG_IS_D(src_size_b)) - { - host_arm_VADD_D(block, dest_reg, src_reg_a, src_reg_b); - } - else - fatal("codegen_FADD %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real); + if (REG_IS_L(dest_size) && REG_IS_B(src_size)) { + host_arm_SXTB(block, dest_reg, src_reg, 0); + } else if (REG_IS_L(dest_size) && REG_IS_BH(src_size)) { + host_arm_SXTB(block, dest_reg, src_reg, 8); + } else if (REG_IS_L(dest_size) && REG_IS_W(src_size)) { + host_arm_SXTH(block, dest_reg, src_reg, 0); + } else if (REG_IS_W(dest_size) && REG_IS_B(src_size)) { + host_arm_SXTB(block, REG_TEMP, src_reg, 0); + host_arm_BFI(block, dest_reg, REG_TEMP, 0, 16); + } else if (REG_IS_W(dest_size) && REG_IS_BH(src_size)) { + host_arm_SXTB(block, REG_TEMP, src_reg, 8); + host_arm_BFI(block, dest_reg, REG_TEMP, 0, 16); + } else + fatal("MOVSX %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real); - return 0; + return 0; } -static int codegen_FCOM(codeblock_t *block, uop_t *uop) +static int +codegen_MOVZX(codeblock_t *block, uop_t *uop) { - int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg_a = HOST_REG_GET(uop->src_reg_a_real), src_reg_b = HOST_REG_GET(uop->src_reg_b_real); - int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size_a = IREG_GET_SIZE(uop->src_reg_a_real), src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); + int dest_reg = HOST_REG_GET(uop->dest_reg_a_real); + int src_reg = HOST_REG_GET(uop->src_reg_a_real); + int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real); + int src_size = IREG_GET_SIZE(uop->src_reg_a_real); - if (REG_IS_W(dest_size) && REG_IS_D(src_size_a) && REG_IS_D(src_size_b)) - { - host_arm_VCMP_D(block, src_reg_a, src_reg_b); - host_arm_MOV_IMM(block, dest_reg, 0); - host_arm_VMRS_APSR(block); - host_arm_ORREQ_IMM(block, dest_reg, dest_reg, C3); - host_arm_ORRCC_IMM(block, dest_reg, dest_reg, C0); - host_arm_ORRVS_IMM(block, dest_reg, dest_reg, C0|C2|C3); - } - else - fatal("codegen_FCOM %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real); - - return 0; -} -static int codegen_FDIV(codeblock_t *block, uop_t *uop) -{ - int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg_a = HOST_REG_GET(uop->src_reg_a_real), src_reg_b = HOST_REG_GET(uop->src_reg_b_real); - int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size_a = IREG_GET_SIZE(uop->src_reg_a_real), src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); - - if (REG_IS_D(dest_size) && REG_IS_D(src_size_a) && REG_IS_D(src_size_b)) - { - host_arm_VDIV_D(block, dest_reg, src_reg_a, src_reg_b); - } - else - fatal("codegen_FDIV %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real); - - return 0; -} -static int codegen_FMUL(codeblock_t *block, uop_t *uop) -{ - int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg_a = HOST_REG_GET(uop->src_reg_a_real), src_reg_b = HOST_REG_GET(uop->src_reg_b_real); - int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size_a = IREG_GET_SIZE(uop->src_reg_a_real), src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); - - if (REG_IS_D(dest_size) && REG_IS_D(src_size_a) && REG_IS_D(src_size_b)) - { - host_arm_VMUL_D(block, dest_reg, src_reg_a, src_reg_b); - } - else - fatal("codegen_FMUL %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real); - - return 0; -} -static int codegen_FSUB(codeblock_t *block, uop_t *uop) -{ - int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg_a = HOST_REG_GET(uop->src_reg_a_real), src_reg_b = HOST_REG_GET(uop->src_reg_b_real); - int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size_a = IREG_GET_SIZE(uop->src_reg_a_real), src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); - - if (REG_IS_D(dest_size) && REG_IS_D(src_size_a) && REG_IS_D(src_size_b)) - { - host_arm_VSUB_D(block, dest_reg, src_reg_a, src_reg_b); - } - else - fatal("codegen_FSUB %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real); - - return 0; -} - -static int codegen_FP_ENTER(codeblock_t *block, uop_t *uop) -{ - uint32_t *branch_ptr; - - if (!in_range(&cr0, &cpu_state)) - fatal("codegen_FP_ENTER - out of range\n"); - - host_arm_LDR_IMM(block, REG_TEMP, REG_CPUSTATE, (uintptr_t)&cr0 - (uintptr_t)&cpu_state); - host_arm_TST_IMM(block, REG_TEMP, 0xc); - branch_ptr = host_arm_BEQ_(block); - - host_arm_MOV_IMM(block, REG_TEMP, uop->imm_data); - host_arm_STR_IMM(block, REG_TEMP, REG_CPUSTATE, (uintptr_t)&cpu_state.oldpc - (uintptr_t)&cpu_state); - host_arm_MOV_IMM(block, REG_ARG0, 7); - host_arm_call(block, x86_int); - host_arm_B(block, (uintptr_t)codegen_exit_rout); - - *branch_ptr |= ((((uintptr_t)&block_write_data[block_pos] - (uintptr_t)branch_ptr) - 8) & 0x3fffffc) >> 2; - - return 0; -} -static int codegen_MMX_ENTER(codeblock_t *block, uop_t *uop) -{ - uint32_t *branch_ptr; - - if (!in_range(&cr0, &cpu_state)) - fatal("codegen_MMX_ENTER - out of range\n"); - - host_arm_LDR_IMM(block, REG_TEMP, REG_CPUSTATE, (uintptr_t)&cr0 - (uintptr_t)&cpu_state); - host_arm_TST_IMM(block, REG_TEMP, 0xc); - branch_ptr = host_arm_BEQ_(block); - - host_arm_MOV_IMM(block, REG_TEMP, uop->imm_data); - host_arm_STR_IMM(block, REG_TEMP, REG_CPUSTATE, (uintptr_t)&cpu_state.oldpc - (uintptr_t)&cpu_state); - host_arm_MOV_IMM(block, REG_ARG0, 7); - host_arm_call(block, x86_int); - host_arm_B(block, (uintptr_t)codegen_exit_rout); - - *branch_ptr |= ((((uintptr_t)&block_write_data[block_pos] - (uintptr_t)branch_ptr) - 8) & 0x3fffffc) >> 2; - - host_arm_MOV_IMM(block, REG_TEMP, 0x01010101); - host_arm_STR_IMM(block, REG_TEMP, REG_CPUSTATE, (uintptr_t)&cpu_state.tag[0] - (uintptr_t)&cpu_state); - host_arm_STR_IMM(block, REG_TEMP, REG_CPUSTATE, (uintptr_t)&cpu_state.tag[4] - (uintptr_t)&cpu_state); + if (REG_IS_Q(dest_size) && REG_IS_L(src_size)) { host_arm_MOV_IMM(block, REG_TEMP, 0); - host_arm_STR_IMM(block, REG_TEMP, REG_CPUSTATE, (uintptr_t)&cpu_state.TOP - (uintptr_t)&cpu_state); - host_arm_STRB_IMM(block, REG_TEMP, REG_CPUSTATE, (uintptr_t)&cpu_state.ismmx - (uintptr_t)&cpu_state); - - return 0; -} - -static int codegen_JMP(codeblock_t *block, uop_t *uop) -{ - host_arm_B(block, (uintptr_t)uop->p); - - return 0; -} - -static int codegen_LOAD_FUNC_ARG0(codeblock_t *block, uop_t *uop) -{ - int src_reg = HOST_REG_GET(uop->src_reg_a_real); - int src_size = IREG_GET_SIZE(uop->src_reg_a_real); - - if (REG_IS_W(src_size)) - { - host_arm_UXTH(block, REG_ARG0, src_reg, 0); + host_arm_VMOV_D_64(block, dest_reg, src_reg, REG_TEMP); + } else if (REG_IS_L(dest_size) && REG_IS_Q(src_size)) { + host_arm_VMOV_32_S(block, dest_reg, src_reg); + } else if (REG_IS_L(dest_size) && REG_IS_B(src_size)) { + host_arm_UXTB(block, dest_reg, src_reg, 0); + } else if (REG_IS_L(dest_size) && REG_IS_BH(src_size)) { + host_arm_UXTB(block, dest_reg, src_reg, 8); + } else if (REG_IS_L(dest_size) && REG_IS_W(src_size)) { + host_arm_UXTH(block, dest_reg, src_reg, 0); + } else if (REG_IS_W(dest_size) && REG_IS_B(src_size)) { + if (src_reg == dest_reg) + host_arm_BIC_IMM(block, dest_reg, dest_reg, 0xff00); + else { + host_arm_UXTB(block, REG_TEMP, src_reg, 0); + host_arm_BFI(block, dest_reg, REG_TEMP, 0, 16); } + } else if (REG_IS_W(dest_size) && REG_IS_BH(src_size)) { + host_arm_MOV_REG_LSR(block, REG_TEMP, src_reg, 8); + host_arm_BIC_IMM(block, dest_reg, dest_reg, 0xff00); + host_arm_BFI(block, dest_reg, REG_TEMP, 0, 8); + } else + fatal("MOVZX %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real); + + return 0; +} +static double +int64_to_double(int64_t a) +{ + return (double) a; +} +static int +codegen_MOV_DOUBLE_INT(codeblock_t *block, uop_t *uop) +{ + int dest_reg = HOST_REG_GET(uop->dest_reg_a_real); + int src_reg = HOST_REG_GET(uop->src_reg_a_real); + int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real); + int src_size = IREG_GET_SIZE(uop->src_reg_a_real); + + if (REG_IS_D(dest_size) && REG_IS_L(src_size)) { + host_arm_VMOV_S_32(block, REG_D_TEMP, src_reg); + host_arm_VCVT_D_IS(block, dest_reg, REG_D_TEMP); + } else if (REG_IS_D(dest_size) && REG_IS_W(src_size)) { + host_arm_SXTH(block, REG_TEMP, src_reg, 0); + host_arm_VMOV_S_32(block, REG_D_TEMP, REG_TEMP); + host_arm_VCVT_D_IS(block, dest_reg, REG_D_TEMP); + } else if (REG_IS_D(dest_size) && REG_IS_Q(src_size)) { + /*ARMv7 has no instructions to convert a 64-bit integer to a double. + For simplicity, call a C function and let the compiler do it.*/ + host_arm_VMOV_64_D(block, REG_R0, REG_R1, src_reg); + host_arm_BL(block, (uintptr_t) int64_to_double); /*Input - R0/R1, Output - D0*/ + host_arm_VMOV_D_D(block, dest_reg, REG_D0); + } else + fatal("MOV_DOUBLE_INT %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real); + + return 0; +} +static int +codegen_MOV_INT_DOUBLE(codeblock_t *block, uop_t *uop) +{ + int dest_reg = HOST_REG_GET(uop->dest_reg_a_real); + int src_reg = HOST_REG_GET(uop->src_reg_a_real); + int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real); + int src_size = IREG_GET_SIZE(uop->src_reg_a_real); + + if (REG_IS_L(dest_size) && REG_IS_D(src_size)) { + host_arm_VMOV_D_D(block, REG_D_TEMP, src_reg); + host_arm_BL(block, (uintptr_t) codegen_fp_round); + host_arm_VMOV_32_S(block, dest_reg, REG_D_TEMP); + } else if (REG_IS_W(dest_size) && REG_IS_D(src_size)) { + host_arm_VMOV_D_D(block, REG_D_TEMP, src_reg); + host_arm_BL(block, (uintptr_t) codegen_fp_round); + host_arm_VMOV_32_S(block, REG_TEMP, REG_D_TEMP); + host_arm_BFI(block, dest_reg, REG_TEMP, 0, 16); + } else + fatal("MOV_INT_DOUBLE %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real); + + return 0; +} +static int64_t +x87_fround64(double b) +{ + int64_t a; + int64_t c; + + switch ((cpu_state.npxc >> 10) & 3) { + case 0: /*Nearest*/ + a = (int64_t) floor(b); + c = (int64_t) floor(b + 1.0); + if ((b - a) < (c - b)) + return a; + else if ((b - a) > (c - b)) + return c; + else + return (a & 1) ? c : a; + case 1: /*Down*/ + return (int64_t) floor(b); + case 2: /*Up*/ + return (int64_t) ceil(b); + case 3: /*Chop*/ + return (int64_t) b; + } + + return 0; +} +static int +codegen_MOV_INT_DOUBLE_64(codeblock_t *block, uop_t *uop) +{ + int dest_reg = HOST_REG_GET(uop->dest_reg_a_real); + int src_reg = HOST_REG_GET(uop->src_reg_a_real); + int src_64_reg = HOST_REG_GET(uop->src_reg_b_real); + int tag_reg = HOST_REG_GET(uop->src_reg_c_real); + int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real); + int src_size = IREG_GET_SIZE(uop->src_reg_a_real); + int src_64_size = IREG_GET_SIZE(uop->src_reg_b_real); + + if (REG_IS_Q(dest_size) && REG_IS_D(src_size) && REG_IS_Q(src_64_size)) { + uint32_t *branch_offset; + + /*If TAG_UINT64 is set then the source is MM[]. Otherwise it is a double in ST()*/ + host_arm_VMOV_D_D(block, dest_reg, src_64_reg); + host_arm_TST_IMM(block, tag_reg, TAG_UINT64); + branch_offset = host_arm_BNE_(block); + + /*VFP/NEON has no instructions to convert a float to 64-bit integer, + so call out to C.*/ + host_arm_VMOV_D_D(block, REG_D0, src_reg); + host_arm_call(block, x87_fround64); + host_arm_VMOV_D_64(block, REG_D_TEMP, REG_R0, REG_R1); + + *branch_offset |= ((((uintptr_t) &block_write_data[block_pos] - (uintptr_t) branch_offset) - 8) & 0x3fffffc) >> 2; + } else + fatal("MOV_INT_DOUBLE_64 %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real); + + return 0; +} +static int +codegen_MOV_REG_PTR(codeblock_t *block, uop_t *uop) +{ + int dest_reg = HOST_REG_GET(uop->dest_reg_a_real); + int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real); + + host_arm_MOV_IMM(block, REG_TEMP, (uintptr_t) uop->p); + if (REG_IS_L(dest_size)) { + host_arm_LDR_IMM(block, dest_reg, REG_TEMP, 0); + } else + fatal("MOV_REG_PTR %02x\n", uop->dest_reg_a_real); + + return 0; +} +static int +codegen_MOVZX_REG_PTR_8(codeblock_t *block, uop_t *uop) +{ + int dest_reg = HOST_REG_GET(uop->dest_reg_a_real); + int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real); + + host_arm_MOV_IMM(block, REG_TEMP, (uintptr_t) uop->p); + if (REG_IS_L(dest_size)) { + host_arm_LDRB_IMM(block, dest_reg, REG_TEMP, 0); + } else if (REG_IS_W(dest_size)) { + host_arm_LDRB_IMM(block, REG_TEMP, REG_TEMP, 0); + host_arm_BFI(block, dest_reg, REG_TEMP, 0, 16); + } else if (REG_IS_B(dest_size)) { + host_arm_LDRB_IMM(block, REG_TEMP, REG_TEMP, 0); + host_arm_BFI(block, dest_reg, REG_TEMP, 0, 8); + } else + fatal("MOVZX_REG_PTR_8 %02x\n", uop->dest_reg_a_real); + + return 0; +} +static int +codegen_MOVZX_REG_PTR_16(codeblock_t *block, uop_t *uop) +{ + int dest_reg = HOST_REG_GET(uop->dest_reg_a_real); + int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real); + + host_arm_MOV_IMM(block, REG_TEMP, (uintptr_t) uop->p); + if (REG_IS_L(dest_size)) { + host_arm_LDRH_IMM(block, dest_reg, REG_TEMP, 0); + } else if (REG_IS_W(dest_size)) { + host_arm_LDRH_IMM(block, REG_TEMP, REG_TEMP, 0); + host_arm_BFI(block, dest_reg, REG_TEMP, 0, 16); + } else + fatal("MOVZX_REG_PTR_16 %02x\n", uop->dest_reg_a_real); + + return 0; +} + +static int +codegen_NOP(codeblock_t *block, uop_t *uop) +{ + return 0; +} + +static int +codegen_OR(codeblock_t *block, uop_t *uop) +{ + int dest_reg = HOST_REG_GET(uop->dest_reg_a_real); + int src_reg_a = HOST_REG_GET(uop->src_reg_a_real); + int src_reg_b = HOST_REG_GET(uop->src_reg_b_real); + int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real); + int src_size_a = IREG_GET_SIZE(uop->src_reg_a_real); + int src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); + + if (REG_IS_Q(dest_size) && REG_IS_Q(src_size_a) && REG_IS_Q(src_size_b)) { + host_arm_VORR_D(block, dest_reg, src_reg_a, src_reg_b); + } else if (REG_IS_L(dest_size) && REG_IS_L(src_size_a) && REG_IS_L(src_size_b)) { + host_arm_ORR_REG_LSL(block, dest_reg, src_reg_a, src_reg_b, 0); + } else if (REG_IS_W(dest_size) && REG_IS_W(src_size_a) && REG_IS_W(src_size_b)) { + host_arm_ORR_REG_LSL(block, REG_TEMP, src_reg_a, src_reg_b, 0); + host_arm_BFI(block, dest_reg, REG_TEMP, 0, 16); + } else if (REG_IS_B(dest_size) && REG_IS_B(src_size_a) && REG_IS_B(src_size_b) && dest_reg == src_reg_a) { + host_arm_UXTB(block, REG_TEMP, src_reg_b, 0); + host_arm_ORR_REG_LSL(block, dest_reg, src_reg_a, REG_TEMP, 0); + } else if (REG_IS_B(dest_size) && REG_IS_B(src_size_a) && REG_IS_BH(src_size_b) && dest_reg == src_reg_a) { + host_arm_UXTB(block, REG_TEMP, src_reg_b, 8); + host_arm_ORR_REG_LSL(block, dest_reg, src_reg_a, REG_TEMP, 0); + } else if (REG_IS_BH(dest_size) && REG_IS_BH(src_size_a) && REG_IS_B(src_size_b) && dest_reg == src_reg_a) { + host_arm_UXTB(block, REG_TEMP, src_reg_b, 0); + host_arm_ORR_REG_LSL(block, dest_reg, src_reg_a, REG_TEMP, 8); + } else if (REG_IS_BH(dest_size) && REG_IS_BH(src_size_a) && REG_IS_BH(src_size_b) && dest_reg == src_reg_a) { + host_arm_UXTB(block, REG_TEMP, src_reg_b, 8); + host_arm_ORR_REG_LSL(block, dest_reg, src_reg_a, REG_TEMP, 8); + } else + fatal("OR %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real); + + return 0; +} +static int +codegen_OR_IMM(codeblock_t *block, uop_t *uop) +{ + int dest_reg = HOST_REG_GET(uop->dest_reg_a_real); + int src_reg = HOST_REG_GET(uop->src_reg_a_real); + int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real); + int src_size = IREG_GET_SIZE(uop->src_reg_a_real); + + if (REG_IS_L(dest_size) && REG_IS_L(src_size)) { + host_arm_ORR_IMM(block, dest_reg, src_reg, uop->imm_data); + } else if (REG_IS_W(dest_size) && REG_IS_W(src_size) && dest_reg == src_reg) { + host_arm_ORR_IMM(block, dest_reg, src_reg, uop->imm_data); + } else if (REG_IS_B(dest_size) && REG_IS_B(src_size) && dest_reg == src_reg) { + host_arm_ORR_IMM(block, dest_reg, src_reg, uop->imm_data); + } else if (REG_IS_BH(dest_size) && REG_IS_BH(src_size) && dest_reg == src_reg) { + host_arm_ORR_IMM(block, dest_reg, src_reg, uop->imm_data << 8); + } else + fatal("OR_IMM %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real); + + return 0; +} + +static int +codegen_PACKSSWB(codeblock_t *block, uop_t *uop) +{ + int dest_reg = HOST_REG_GET(uop->dest_reg_a_real); + int src_reg_a = HOST_REG_GET(uop->src_reg_a_real); + int src_reg_b = HOST_REG_GET(uop->src_reg_b_real); + int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real); + int src_size_a = IREG_GET_SIZE(uop->src_reg_a_real); + int src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); + + if (REG_IS_Q(dest_size) && REG_IS_Q(src_size_a) && REG_IS_Q(src_size_b)) { + host_arm_VMOV_D_D(block, REG_Q_TEMP, src_reg_a); + host_arm_VMOV_D_D(block, REG_Q_TEMP_2, src_reg_b); + host_arm_VQMOVN_S16(block, dest_reg, REG_Q_TEMP); + host_arm_VQMOVN_S16(block, REG_D_TEMP, REG_Q_TEMP_2); + host_arm_VZIP_D32(block, dest_reg, REG_D_TEMP); + } else + fatal("PACKSSWB %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real); + + return 0; +} +static int +codegen_PACKSSDW(codeblock_t *block, uop_t *uop) +{ + int dest_reg = HOST_REG_GET(uop->dest_reg_a_real); + int src_reg_a = HOST_REG_GET(uop->src_reg_a_real); + int src_reg_b = HOST_REG_GET(uop->src_reg_b_real); + int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real); + int src_size_a = IREG_GET_SIZE(uop->src_reg_a_real); + int src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); + + if (REG_IS_Q(dest_size) && REG_IS_Q(src_size_a) && REG_IS_Q(src_size_b)) { + host_arm_VMOV_D_D(block, REG_Q_TEMP, src_reg_a); + host_arm_VMOV_D_D(block, REG_Q_TEMP_2, src_reg_b); + host_arm_VQMOVN_S32(block, dest_reg, REG_Q_TEMP); + host_arm_VQMOVN_S32(block, REG_D_TEMP, REG_Q_TEMP_2); + host_arm_VZIP_D32(block, dest_reg, REG_D_TEMP); + } else + fatal("PACKSSDW %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real); + + return 0; +} +static int +codegen_PACKUSWB(codeblock_t *block, uop_t *uop) +{ + int dest_reg = HOST_REG_GET(uop->dest_reg_a_real); + int src_reg_a = HOST_REG_GET(uop->src_reg_a_real); + int src_reg_b = HOST_REG_GET(uop->src_reg_b_real); + int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real); + int src_size_a = IREG_GET_SIZE(uop->src_reg_a_real); + int src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); + + if (REG_IS_Q(dest_size) && REG_IS_Q(src_size_a) && REG_IS_Q(src_size_b)) { + host_arm_VMOV_D_D(block, REG_Q_TEMP, src_reg_a); + host_arm_VMOV_D_D(block, REG_Q_TEMP_2, src_reg_b); + host_arm_VQMOVN_U16(block, dest_reg, REG_Q_TEMP); + host_arm_VQMOVN_U16(block, REG_D_TEMP, REG_Q_TEMP_2); + host_arm_VZIP_D32(block, dest_reg, REG_D_TEMP); + } else + fatal("PACKUSWB %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real); + + return 0; +} + +static int +codegen_PADDB(codeblock_t *block, uop_t *uop) +{ + int dest_reg = HOST_REG_GET(uop->dest_reg_a_real); + int src_reg_a = HOST_REG_GET(uop->src_reg_a_real); + int src_reg_b = HOST_REG_GET(uop->src_reg_b_real); + int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real); + int src_size_a = IREG_GET_SIZE(uop->src_reg_a_real); + int src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); + + if (REG_IS_Q(dest_size) && REG_IS_Q(src_size_a) && REG_IS_Q(src_size_b)) { + host_arm_VADD_I8(block, dest_reg, src_reg_a, src_reg_b); + } else + fatal("PADDB %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real); + + return 0; +} +static int +codegen_PADDW(codeblock_t *block, uop_t *uop) +{ + int dest_reg = HOST_REG_GET(uop->dest_reg_a_real); + int src_reg_a = HOST_REG_GET(uop->src_reg_a_real); + int src_reg_b = HOST_REG_GET(uop->src_reg_b_real); + int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real); + int src_size_a = IREG_GET_SIZE(uop->src_reg_a_real); + int src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); + + if (REG_IS_Q(dest_size) && REG_IS_Q(src_size_a) && REG_IS_Q(src_size_b)) { + host_arm_VADD_I16(block, dest_reg, src_reg_a, src_reg_b); + } else + fatal("PADDW %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real); + + return 0; +} +static int +codegen_PADDD(codeblock_t *block, uop_t *uop) +{ + int dest_reg = HOST_REG_GET(uop->dest_reg_a_real); + int src_reg_a = HOST_REG_GET(uop->src_reg_a_real); + int src_reg_b = HOST_REG_GET(uop->src_reg_b_real); + int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real); + int src_size_a = IREG_GET_SIZE(uop->src_reg_a_real); + int src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); + + if (REG_IS_Q(dest_size) && REG_IS_Q(src_size_a) && REG_IS_Q(src_size_b)) { + host_arm_VADD_I32(block, dest_reg, src_reg_a, src_reg_b); + } else + fatal("PADDD %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real); + + return 0; +} +static int +codegen_PADDSB(codeblock_t *block, uop_t *uop) +{ + int dest_reg = HOST_REG_GET(uop->dest_reg_a_real); + int src_reg_a = HOST_REG_GET(uop->src_reg_a_real); + int src_reg_b = HOST_REG_GET(uop->src_reg_b_real); + int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real); + int src_size_a = IREG_GET_SIZE(uop->src_reg_a_real); + int src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); + + if (REG_IS_Q(dest_size) && REG_IS_Q(src_size_a) && REG_IS_Q(src_size_b)) { + host_arm_VQADD_S8(block, dest_reg, src_reg_a, src_reg_b); + } else + fatal("PADDSB %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real); + + return 0; +} +static int +codegen_PADDSW(codeblock_t *block, uop_t *uop) +{ + int dest_reg = HOST_REG_GET(uop->dest_reg_a_real); + int src_reg_a = HOST_REG_GET(uop->src_reg_a_real); + int src_reg_b = HOST_REG_GET(uop->src_reg_b_real); + int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real); + int src_size_a = IREG_GET_SIZE(uop->src_reg_a_real); + int src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); + + if (REG_IS_Q(dest_size) && REG_IS_Q(src_size_a) && REG_IS_Q(src_size_b)) { + host_arm_VQADD_S16(block, dest_reg, src_reg_a, src_reg_b); + } else + fatal("PADDSW %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real); + + return 0; +} +static int +codegen_PADDUSB(codeblock_t *block, uop_t *uop) +{ + int dest_reg = HOST_REG_GET(uop->dest_reg_a_real); + int src_reg_a = HOST_REG_GET(uop->src_reg_a_real); + int src_reg_b = HOST_REG_GET(uop->src_reg_b_real); + int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real); + int src_size_a = IREG_GET_SIZE(uop->src_reg_a_real); + int src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); + + if (REG_IS_Q(dest_size) && REG_IS_Q(src_size_a) && REG_IS_Q(src_size_b)) { + host_arm_VQADD_U8(block, dest_reg, src_reg_a, src_reg_b); + } else + fatal("PADDUSB %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real); + + return 0; +} +static int +codegen_PADDUSW(codeblock_t *block, uop_t *uop) +{ + int dest_reg = HOST_REG_GET(uop->dest_reg_a_real); + int src_reg_a = HOST_REG_GET(uop->src_reg_a_real); + int src_reg_b = HOST_REG_GET(uop->src_reg_b_real); + int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real); + int src_size_a = IREG_GET_SIZE(uop->src_reg_a_real); + int src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); + + if (REG_IS_Q(dest_size) && REG_IS_Q(src_size_a) && REG_IS_Q(src_size_b)) { + host_arm_VQADD_U16(block, dest_reg, src_reg_a, src_reg_b); + } else + fatal("PADDUSW %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real); + + return 0; +} + +static int +codegen_PCMPEQB(codeblock_t *block, uop_t *uop) +{ + int dest_reg = HOST_REG_GET(uop->dest_reg_a_real); + int src_reg_a = HOST_REG_GET(uop->src_reg_a_real); + int src_reg_b = HOST_REG_GET(uop->src_reg_b_real); + int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real); + int src_size_a = IREG_GET_SIZE(uop->src_reg_a_real); + int src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); + + if (REG_IS_Q(dest_size) && REG_IS_Q(src_size_a) && REG_IS_Q(src_size_b)) { + host_arm_VCEQ_I8(block, dest_reg, src_reg_a, src_reg_b); + } else + fatal("PCMPEQB %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real); + + return 0; +} +static int +codegen_PCMPEQW(codeblock_t *block, uop_t *uop) +{ + int dest_reg = HOST_REG_GET(uop->dest_reg_a_real); + int src_reg_a = HOST_REG_GET(uop->src_reg_a_real); + int src_reg_b = HOST_REG_GET(uop->src_reg_b_real); + int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real); + int src_size_a = IREG_GET_SIZE(uop->src_reg_a_real); + int src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); + + if (REG_IS_Q(dest_size) && REG_IS_Q(src_size_a) && REG_IS_Q(src_size_b)) { + host_arm_VCEQ_I16(block, dest_reg, src_reg_a, src_reg_b); + } else + fatal("PCMPEQW %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real); + + return 0; +} +static int +codegen_PCMPEQD(codeblock_t *block, uop_t *uop) +{ + int dest_reg = HOST_REG_GET(uop->dest_reg_a_real); + int src_reg_a = HOST_REG_GET(uop->src_reg_a_real); + int src_reg_b = HOST_REG_GET(uop->src_reg_b_real); + int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real); + int src_size_a = IREG_GET_SIZE(uop->src_reg_a_real); + int src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); + + if (REG_IS_Q(dest_size) && REG_IS_Q(src_size_a) && REG_IS_Q(src_size_b)) { + host_arm_VCEQ_I32(block, dest_reg, src_reg_a, src_reg_b); + } else + fatal("PCMPEQD %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real); + + return 0; +} +static int +codegen_PCMPGTB(codeblock_t *block, uop_t *uop) +{ + int dest_reg = HOST_REG_GET(uop->dest_reg_a_real); + int src_reg_a = HOST_REG_GET(uop->src_reg_a_real); + int src_reg_b = HOST_REG_GET(uop->src_reg_b_real); + int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real); + int src_size_a = IREG_GET_SIZE(uop->src_reg_a_real); + int src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); + + if (REG_IS_Q(dest_size) && REG_IS_Q(src_size_a) && REG_IS_Q(src_size_b)) { + host_arm_VCGT_S8(block, dest_reg, src_reg_a, src_reg_b); + } else + fatal("PCMPGTB %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real); + + return 0; +} +static int +codegen_PCMPGTW(codeblock_t *block, uop_t *uop) +{ + int dest_reg = HOST_REG_GET(uop->dest_reg_a_real); + int src_reg_a = HOST_REG_GET(uop->src_reg_a_real); + int src_reg_b = HOST_REG_GET(uop->src_reg_b_real); + int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real); + int src_size_a = IREG_GET_SIZE(uop->src_reg_a_real); + int src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); + + if (REG_IS_Q(dest_size) && REG_IS_Q(src_size_a) && REG_IS_Q(src_size_b)) { + host_arm_VCGT_S16(block, dest_reg, src_reg_a, src_reg_b); + } else + fatal("PCMPGTW %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real); + + return 0; +} +static int +codegen_PCMPGTD(codeblock_t *block, uop_t *uop) +{ + int dest_reg = HOST_REG_GET(uop->dest_reg_a_real); + int src_reg_a = HOST_REG_GET(uop->src_reg_a_real); + int src_reg_b = HOST_REG_GET(uop->src_reg_b_real); + int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real); + int src_size_a = IREG_GET_SIZE(uop->src_reg_a_real); + int src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); + + if (REG_IS_Q(dest_size) && REG_IS_Q(src_size_a) && REG_IS_Q(src_size_b)) { + host_arm_VCGT_S32(block, dest_reg, src_reg_a, src_reg_b); + } else + fatal("PCMPGTD %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real); + + return 0; +} + +static int +codegen_PF2ID(codeblock_t *block, uop_t *uop) +{ + int dest_reg = HOST_REG_GET(uop->dest_reg_a_real); + int src_reg_a = HOST_REG_GET(uop->src_reg_a_real); + int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real); + int src_size_a = IREG_GET_SIZE(uop->src_reg_a_real); + + if (REG_IS_Q(dest_size) && REG_IS_Q(src_size_a)) { + host_arm_VCVT_S32_F32(block, dest_reg, src_reg_a); + } else + fatal("PF2ID %02x %02x\n", uop->dest_reg_a_real); + + return 0; +} +static int +codegen_PFADD(codeblock_t *block, uop_t *uop) +{ + int dest_reg = HOST_REG_GET(uop->dest_reg_a_real); + int src_reg_a = HOST_REG_GET(uop->src_reg_a_real); + int src_reg_b = HOST_REG_GET(uop->src_reg_b_real); + int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real); + int src_size_a = IREG_GET_SIZE(uop->src_reg_a_real); + int src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); + + if (REG_IS_Q(dest_size) && REG_IS_Q(src_size_a) && REG_IS_Q(src_size_b)) { + host_arm_VADD_F32(block, dest_reg, src_reg_a, src_reg_b); + } else + fatal("PFADD %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real); + + return 0; +} +static int +codegen_PFCMPEQ(codeblock_t *block, uop_t *uop) +{ + int dest_reg = HOST_REG_GET(uop->dest_reg_a_real); + int src_reg_a = HOST_REG_GET(uop->src_reg_a_real); + int src_reg_b = HOST_REG_GET(uop->src_reg_b_real); + int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real); + int src_size_a = IREG_GET_SIZE(uop->src_reg_a_real); + int src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); + + if (REG_IS_Q(dest_size) && REG_IS_Q(src_size_a) && REG_IS_Q(src_size_b)) { + host_arm_VCEQ_F32(block, dest_reg, src_reg_a, src_reg_b); + } else + fatal("PFCMPEQ %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real); + + return 0; +} +static int +codegen_PFCMPGE(codeblock_t *block, uop_t *uop) +{ + int dest_reg = HOST_REG_GET(uop->dest_reg_a_real); + int src_reg_a = HOST_REG_GET(uop->src_reg_a_real); + int src_reg_b = HOST_REG_GET(uop->src_reg_b_real); + int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real); + int src_size_a = IREG_GET_SIZE(uop->src_reg_a_real); + int src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); + + if (REG_IS_Q(dest_size) && REG_IS_Q(src_size_a) && REG_IS_Q(src_size_b)) { + host_arm_VCGE_F32(block, dest_reg, src_reg_a, src_reg_b); + } else + fatal("PFCMPGE %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real); + + return 0; +} +static int +codegen_PFCMPGT(codeblock_t *block, uop_t *uop) +{ + int dest_reg = HOST_REG_GET(uop->dest_reg_a_real); + int src_reg_a = HOST_REG_GET(uop->src_reg_a_real); + int src_reg_b = HOST_REG_GET(uop->src_reg_b_real); + int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real); + int src_size_a = IREG_GET_SIZE(uop->src_reg_a_real); + int src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); + + if (REG_IS_Q(dest_size) && REG_IS_Q(src_size_a) && REG_IS_Q(src_size_b)) { + host_arm_VCGT_F32(block, dest_reg, src_reg_a, src_reg_b); + } else + fatal("PFCMPGT %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real); + + return 0; +} +static int +codegen_PFMAX(codeblock_t *block, uop_t *uop) +{ + int dest_reg = HOST_REG_GET(uop->dest_reg_a_real); + int src_reg_a = HOST_REG_GET(uop->src_reg_a_real); + int src_reg_b = HOST_REG_GET(uop->src_reg_b_real); + int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real); + int src_size_a = IREG_GET_SIZE(uop->src_reg_a_real); + int src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); + + if (REG_IS_Q(dest_size) && REG_IS_Q(src_size_a) && REG_IS_Q(src_size_b)) { + host_arm_VMAX_F32(block, dest_reg, src_reg_a, src_reg_b); + } else + fatal("PFMAX %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real); + + return 0; +} +static int +codegen_PFMIN(codeblock_t *block, uop_t *uop) +{ + int dest_reg = HOST_REG_GET(uop->dest_reg_a_real); + int src_reg_a = HOST_REG_GET(uop->src_reg_a_real); + int src_reg_b = HOST_REG_GET(uop->src_reg_b_real); + int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real); + int src_size_a = IREG_GET_SIZE(uop->src_reg_a_real); + int src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); + + if (REG_IS_Q(dest_size) && REG_IS_Q(src_size_a) && REG_IS_Q(src_size_b)) { + host_arm_VMIN_F32(block, dest_reg, src_reg_a, src_reg_b); + } else + fatal("PFMIN %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real); + + return 0; +} +static int +codegen_PFMUL(codeblock_t *block, uop_t *uop) +{ + int dest_reg = HOST_REG_GET(uop->dest_reg_a_real); + int src_reg_a = HOST_REG_GET(uop->src_reg_a_real); + int src_reg_b = HOST_REG_GET(uop->src_reg_b_real); + int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real); + int src_size_a = IREG_GET_SIZE(uop->src_reg_a_real); + int src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); + + if (REG_IS_Q(dest_size) && REG_IS_Q(src_size_a) && REG_IS_Q(src_size_b)) { + host_arm_VMUL_F32(block, dest_reg, src_reg_a, src_reg_b); + } else + fatal("PFMUL %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real); + + return 0; +} +static int +codegen_PFRCP(codeblock_t *block, uop_t *uop) +{ + int dest_reg = HOST_REG_GET(uop->dest_reg_a_real); + int src_reg_a = HOST_REG_GET(uop->src_reg_a_real); + int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real); + int src_size_a = IREG_GET_SIZE(uop->src_reg_a_real); + + if (REG_IS_Q(dest_size) && REG_IS_Q(src_size_a)) { + /*TODO: This could be improved (use VRECPE/VRECPS)*/ + host_arm_VMOV_F32_ONE(block, REG_D_TEMP); + host_arm_VDIV_S(block, dest_reg, REG_D_TEMP, src_reg_a); + host_arm_VDUP_32(block, dest_reg, dest_reg, 0); + } else + fatal("PFRCP %02x %02x\n", uop->dest_reg_a_real); + + return 0; +} +static int +codegen_PFRSQRT(codeblock_t *block, uop_t *uop) +{ + int dest_reg = HOST_REG_GET(uop->dest_reg_a_real); + int src_reg_a = HOST_REG_GET(uop->src_reg_a_real); + int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real); + int src_size_a = IREG_GET_SIZE(uop->src_reg_a_real); + + if (REG_IS_Q(dest_size) && REG_IS_Q(src_size_a)) { + /*TODO: This could be improved (use VRSQRTE/VRSQRTS)*/ + host_arm_VSQRT_S(block, REG_D_TEMP, src_reg_a); + host_arm_VMOV_F32_ONE(block, REG_D_TEMP); + host_arm_VDIV_S(block, dest_reg, dest_reg, REG_D_TEMP); + host_arm_VDUP_32(block, dest_reg, dest_reg, 0); + } else + fatal("PFRSQRT %02x %02x\n", uop->dest_reg_a_real); + + return 0; +} +static int +codegen_PFSUB(codeblock_t *block, uop_t *uop) +{ + int dest_reg = HOST_REG_GET(uop->dest_reg_a_real); + int src_reg_a = HOST_REG_GET(uop->src_reg_a_real); + int src_reg_b = HOST_REG_GET(uop->src_reg_b_real); + int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real); + int src_size_a = IREG_GET_SIZE(uop->src_reg_a_real); + int src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); + + if (REG_IS_Q(dest_size) && REG_IS_Q(src_size_a) && REG_IS_Q(src_size_b)) { + host_arm_VSUB_F32(block, dest_reg, src_reg_a, src_reg_b); + } else + fatal("PFSUB %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real); + + return 0; +} +static int +codegen_PI2FD(codeblock_t *block, uop_t *uop) +{ + int dest_reg = HOST_REG_GET(uop->dest_reg_a_real); + int src_reg_a = HOST_REG_GET(uop->src_reg_a_real); + int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real); + int src_size_a = IREG_GET_SIZE(uop->src_reg_a_real); + + if (REG_IS_Q(dest_size) && REG_IS_Q(src_size_a)) { + host_arm_VCVT_F32_S32(block, dest_reg, src_reg_a); + } else + fatal("PI2FD %02x %02x\n", uop->dest_reg_a_real); + + return 0; +} + +static int +codegen_PMADDWD(codeblock_t *block, uop_t *uop) +{ + int dest_reg = HOST_REG_GET(uop->dest_reg_a_real); + int src_reg_a = HOST_REG_GET(uop->src_reg_a_real); + int src_reg_b = HOST_REG_GET(uop->src_reg_b_real); + int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real); + int src_size_a = IREG_GET_SIZE(uop->src_reg_a_real); + int src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); + + if (REG_IS_Q(dest_size) && REG_IS_Q(src_size_a) && REG_IS_Q(src_size_b)) { + host_arm_VMULL_S16(block, REG_Q_TEMP, src_reg_a, src_reg_b); + host_arm_VPADDL_Q_S32(block, REG_Q_TEMP, REG_Q_TEMP); + host_arm_VMOVN_I64(block, dest_reg, REG_Q_TEMP); + } else + fatal("PMULHW %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real); + + return 0; +} +static int +codegen_PMULHW(codeblock_t *block, uop_t *uop) +{ + int dest_reg = HOST_REG_GET(uop->dest_reg_a_real); + int src_reg_a = HOST_REG_GET(uop->src_reg_a_real); + int src_reg_b = HOST_REG_GET(uop->src_reg_b_real); + int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real); + int src_size_a = IREG_GET_SIZE(uop->src_reg_a_real); + int src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); + + if (REG_IS_Q(dest_size) && REG_IS_Q(src_size_a) && REG_IS_Q(src_size_b)) { + host_arm_VMULL_S16(block, REG_Q_TEMP, src_reg_a, src_reg_b); + host_arm_VSHRN_32(block, dest_reg, REG_Q_TEMP, 16); + } else + fatal("PMULHW %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real); + + return 0; +} +static int +codegen_PMULLW(codeblock_t *block, uop_t *uop) +{ + int dest_reg = HOST_REG_GET(uop->dest_reg_a_real); + int src_reg_a = HOST_REG_GET(uop->src_reg_a_real); + int src_reg_b = HOST_REG_GET(uop->src_reg_b_real); + int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real); + int src_size_a = IREG_GET_SIZE(uop->src_reg_a_real); + int src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); + + if (REG_IS_Q(dest_size) && REG_IS_Q(src_size_a) && REG_IS_Q(src_size_b)) { + host_arm_VMUL_S16(block, dest_reg, src_reg_a, src_reg_b); + } else + fatal("PMULLW %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real); + + return 0; +} + +static int +codegen_PSLLW_IMM(codeblock_t *block, uop_t *uop) +{ + int dest_reg = HOST_REG_GET(uop->dest_reg_a_real); + int src_reg = HOST_REG_GET(uop->src_reg_a_real); + int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real); + int src_size = IREG_GET_SIZE(uop->src_reg_a_real); + + if (REG_IS_Q(dest_size) && REG_IS_Q(src_size)) { + if (uop->imm_data == 0) + host_arm_VMOV_D_D(block, dest_reg, src_reg); + else if (uop->imm_data > 15) + host_arm_VEOR_D(block, dest_reg, dest_reg, dest_reg); else - fatal("codegen_LOAD_FUNC_ARG0 %02x\n", uop->src_reg_a_real); + host_arm_VSHL_D_IMM_16(block, dest_reg, src_reg, uop->imm_data); + } else + fatal("PSLLW_IMM %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real); - return 0; + return 0; } -static int codegen_LOAD_FUNC_ARG1(codeblock_t *block, uop_t *uop) +static int +codegen_PSLLD_IMM(codeblock_t *block, uop_t *uop) { - fatal("codegen_LOAD_FUNC_ARG1 %02x\n", uop->src_reg_a_real); - return 0; -} -static int codegen_LOAD_FUNC_ARG2(codeblock_t *block, uop_t *uop) -{ - fatal("codegen_LOAD_FUNC_ARG2 %02x\n", uop->src_reg_a_real); - return 0; -} -static int codegen_LOAD_FUNC_ARG3(codeblock_t *block, uop_t *uop) -{ - fatal("codegen_LOAD_FUNC_ARG3 %02x\n", uop->src_reg_a_real); - return 0; -} + int dest_reg = HOST_REG_GET(uop->dest_reg_a_real); + int src_reg = HOST_REG_GET(uop->src_reg_a_real); + int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real); + int src_size = IREG_GET_SIZE(uop->src_reg_a_real); -static int codegen_LOAD_FUNC_ARG0_IMM(codeblock_t *block, uop_t *uop) -{ - host_arm_MOV_IMM(block, REG_ARG0, uop->imm_data); - return 0; -} -static int codegen_LOAD_FUNC_ARG1_IMM(codeblock_t *block, uop_t *uop) -{ - host_arm_MOV_IMM(block, REG_ARG1, uop->imm_data); - return 0; -} -static int codegen_LOAD_FUNC_ARG2_IMM(codeblock_t *block, uop_t *uop) -{ - host_arm_MOV_IMM(block, REG_ARG2, uop->imm_data); - return 0; -} -static int codegen_LOAD_FUNC_ARG3_IMM(codeblock_t *block, uop_t *uop) -{ - host_arm_MOV_IMM(block, REG_ARG3, uop->imm_data); - return 0; -} - -static int codegen_LOAD_SEG(codeblock_t *block, uop_t *uop) -{ - int src_reg = HOST_REG_GET(uop->src_reg_a_real); - int src_size = IREG_GET_SIZE(uop->src_reg_a_real); - - if (!REG_IS_W(src_size)) - fatal("LOAD_SEG %02x %p\n", uop->src_reg_a_real, uop->p); - host_arm_UXTH(block, REG_ARG0, src_reg, 0); - host_arm_MOV_IMM(block, REG_ARG1, (uint32_t)uop->p); - host_arm_call(block, loadseg); - host_arm_TST_REG(block, REG_R0, REG_R0); - host_arm_BNE(block, (uintptr_t)codegen_exit_rout); - - return 0; -} - -static int codegen_MEM_LOAD_ABS(codeblock_t *block, uop_t *uop) -{ - int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), seg_reg = HOST_REG_GET(uop->src_reg_a_real); - int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real); - - host_arm_ADD_IMM(block, REG_R0, seg_reg, uop->imm_data); - if (REG_IS_B(dest_size) || REG_IS_BH(dest_size)) - { - host_arm_BL(block, (uintptr_t)codegen_mem_load_byte); - } - else if (REG_IS_W(dest_size)) - { - host_arm_BL(block, (uintptr_t)codegen_mem_load_word); - } - else if (REG_IS_L(dest_size)) - { - host_arm_BL(block, (uintptr_t)codegen_mem_load_long); - } + if (REG_IS_Q(dest_size) && REG_IS_Q(src_size)) { + if (uop->imm_data == 0) + host_arm_VMOV_D_D(block, dest_reg, src_reg); + else if (uop->imm_data > 31) + host_arm_VEOR_D(block, dest_reg, dest_reg, dest_reg); else - fatal("MEM_LOAD_ABS - %02x\n", uop->dest_reg_a_real); - host_arm_TST_REG(block, REG_R1, REG_R1); - host_arm_BNE(block, (uintptr_t)codegen_exit_rout); - if (REG_IS_B(dest_size)) - { - host_arm_BFI(block, dest_reg, REG_R0, 0, 8); - } - else if (REG_IS_BH(dest_size)) - { - host_arm_BFI(block, dest_reg, REG_R0, 8, 8); - } - else if (REG_IS_W(dest_size)) - { - host_arm_BFI(block, dest_reg, REG_R0, 0, 16); - } - else if (REG_IS_L(dest_size)) - { - host_arm_MOV_REG(block, dest_reg, REG_R0); - } + host_arm_VSHL_D_IMM_32(block, dest_reg, src_reg, uop->imm_data); + } else + fatal("PSLLD_IMM %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real); - return 0; + return 0; } - -static int codegen_MEM_LOAD_REG(codeblock_t *block, uop_t *uop) +static int +codegen_PSLLQ_IMM(codeblock_t *block, uop_t *uop) { - int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), seg_reg = HOST_REG_GET(uop->src_reg_a_real), addr_reg = HOST_REG_GET(uop->src_reg_b_real); - int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real); + int dest_reg = HOST_REG_GET(uop->dest_reg_a_real); + int src_reg = HOST_REG_GET(uop->src_reg_a_real); + int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real); + int src_size = IREG_GET_SIZE(uop->src_reg_a_real); - host_arm_ADD_REG(block, REG_R0, seg_reg, addr_reg); - if (uop->imm_data) - host_arm_ADD_IMM(block, REG_R0, REG_R0, uop->imm_data); - if (REG_IS_B(dest_size) || REG_IS_BH(dest_size)) - { - host_arm_BL(block, (uintptr_t)codegen_mem_load_byte); - } - else if (REG_IS_W(dest_size)) - { - host_arm_BL(block, (uintptr_t)codegen_mem_load_word); - } - else if (REG_IS_L(dest_size)) - { - host_arm_BL(block, (uintptr_t)codegen_mem_load_long); - } - else if (REG_IS_Q(dest_size)) - { - host_arm_BL(block, (uintptr_t)codegen_mem_load_quad); - } + if (REG_IS_Q(dest_size) && REG_IS_Q(src_size)) { + if (uop->imm_data == 0) + host_arm_VMOV_D_D(block, dest_reg, src_reg); + else if (uop->imm_data > 63) + host_arm_VEOR_D(block, dest_reg, dest_reg, dest_reg); else - fatal("MEM_LOAD_REG - %02x\n", uop->dest_reg_a_real); - host_arm_TST_REG(block, REG_R1, REG_R1); - host_arm_BNE(block, (uintptr_t)codegen_exit_rout); - if (REG_IS_B(dest_size)) - { - host_arm_BFI(block, dest_reg, REG_R0, 0, 8); - } - else if (REG_IS_BH(dest_size)) - { - host_arm_BFI(block, dest_reg, REG_R0, 8, 8); - } - else if (REG_IS_W(dest_size)) - { - host_arm_BFI(block, dest_reg, REG_R0, 0, 16); - } - else if (REG_IS_L(dest_size)) - { - host_arm_MOV_REG(block, dest_reg, REG_R0); - } - else if (REG_IS_Q(dest_size)) - { - host_arm_VMOV_D_D(block, dest_reg, REG_D_TEMP); - } + host_arm_VSHL_D_IMM_64(block, dest_reg, src_reg, uop->imm_data); + } else + fatal("PSLLQ_IMM %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real); - return 0; + return 0; } -static int codegen_MEM_LOAD_SINGLE(codeblock_t *block, uop_t *uop) +static int +codegen_PSRAW_IMM(codeblock_t *block, uop_t *uop) { - int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), seg_reg = HOST_REG_GET(uop->src_reg_a_real), addr_reg = HOST_REG_GET(uop->src_reg_b_real); - int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real); + int dest_reg = HOST_REG_GET(uop->dest_reg_a_real); + int src_reg = HOST_REG_GET(uop->src_reg_a_real); + int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real); + int src_size = IREG_GET_SIZE(uop->src_reg_a_real); - if (!REG_IS_D(dest_size)) - fatal("MEM_LOAD_SINGLE - %02x\n", uop->dest_reg_a_real); - - host_arm_ADD_REG(block, REG_R0, seg_reg, addr_reg); - if (uop->imm_data) - host_arm_ADD_IMM(block, REG_R0, REG_R0, uop->imm_data); - host_arm_BL(block, (uintptr_t)codegen_mem_load_single); - host_arm_TST_REG(block, REG_R1, REG_R1); - host_arm_BNE(block, (uintptr_t)codegen_exit_rout); - host_arm_VCVT_D_S(block, dest_reg, REG_D_TEMP); - - return 0; -} -static int codegen_MEM_LOAD_DOUBLE(codeblock_t *block, uop_t *uop) -{ - int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), seg_reg = HOST_REG_GET(uop->src_reg_a_real), addr_reg = HOST_REG_GET(uop->src_reg_b_real); - int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real); - - if (!REG_IS_D(dest_size)) - fatal("MEM_LOAD_DOUBLE - %02x\n", uop->dest_reg_a_real); - - host_arm_ADD_REG(block, REG_R0, seg_reg, addr_reg); - if (uop->imm_data) - host_arm_ADD_IMM(block, REG_R0, REG_R0, uop->imm_data); - host_arm_BL(block, (uintptr_t)codegen_mem_load_double); - host_arm_TST_REG(block, REG_R1, REG_R1); - host_arm_BNE(block, (uintptr_t)codegen_exit_rout); - host_arm_VMOV_D_D(block, dest_reg, REG_D_TEMP); - - return 0; -} - -static int codegen_MEM_STORE_ABS(codeblock_t *block, uop_t *uop) -{ - int seg_reg = HOST_REG_GET(uop->src_reg_a_real), src_reg = HOST_REG_GET(uop->src_reg_b_real); - int src_size = IREG_GET_SIZE(uop->src_reg_b_real); - - host_arm_ADD_IMM(block, REG_R0, seg_reg, uop->imm_data); - if (REG_IS_B(src_size)) - { - host_arm_MOV_REG(block, REG_R1, src_reg); - host_arm_BL(block, (uintptr_t)codegen_mem_store_byte); - } - else if (REG_IS_W(src_size)) - { - host_arm_MOV_REG(block, REG_R1, src_reg); - host_arm_BL(block, (uintptr_t)codegen_mem_store_word); - } - else if (REG_IS_L(src_size)) - { - host_arm_MOV_REG(block, REG_R1, src_reg); - host_arm_BL(block, (uintptr_t)codegen_mem_store_long); - } + if (REG_IS_Q(dest_size) && REG_IS_Q(src_size)) { + if (uop->imm_data == 0) + host_arm_VMOV_D_D(block, dest_reg, src_reg); + else if (uop->imm_data > 15) + host_arm_VSHR_D_S16(block, dest_reg, src_reg, 15); else - fatal("MEM_STORE_ABS - %02x\n", uop->src_reg_b_real); - host_arm_TST_REG(block, REG_R1, REG_R1); - host_arm_BNE(block, (uintptr_t)codegen_exit_rout); + host_arm_VSHR_D_S16(block, dest_reg, src_reg, uop->imm_data); + } else + fatal("PSRAW_IMM %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real); - return 0; + return 0; } - -static int codegen_MEM_STORE_REG(codeblock_t *block, uop_t *uop) +static int +codegen_PSRAD_IMM(codeblock_t *block, uop_t *uop) { - int seg_reg = HOST_REG_GET(uop->src_reg_a_real), addr_reg = HOST_REG_GET(uop->src_reg_b_real), src_reg = HOST_REG_GET(uop->src_reg_c_real); - int src_size = IREG_GET_SIZE(uop->src_reg_c_real); + int dest_reg = HOST_REG_GET(uop->dest_reg_a_real); + int src_reg = HOST_REG_GET(uop->src_reg_a_real); + int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real); + int src_size = IREG_GET_SIZE(uop->src_reg_a_real); - host_arm_ADD_REG(block, REG_R0, seg_reg, addr_reg); - if (uop->imm_data) - host_arm_ADD_IMM(block, REG_R0, REG_R0, uop->imm_data); - if (REG_IS_B(src_size)) - { - host_arm_MOV_REG(block, REG_R1, src_reg); - host_arm_BL(block, (uintptr_t)codegen_mem_store_byte); - } - else if (REG_IS_BH(src_size)) - { - host_arm_MOV_REG_LSR(block, REG_R1, src_reg, 8); - host_arm_BL(block, (uintptr_t)codegen_mem_store_byte); - } - else if (REG_IS_W(src_size)) - { - host_arm_MOV_REG(block, REG_R1, src_reg); - host_arm_BL(block, (uintptr_t)codegen_mem_store_word); - } - else if (REG_IS_L(src_size)) - { - host_arm_MOV_REG(block, REG_R1, src_reg); - host_arm_BL(block, (uintptr_t)codegen_mem_store_long); - } - else if (REG_IS_Q(src_size)) - { - host_arm_VMOV_D_D(block, REG_D_TEMP, src_reg); - host_arm_BL(block, (uintptr_t)codegen_mem_store_quad); - } + if (REG_IS_Q(dest_size) && REG_IS_Q(src_size)) { + if (uop->imm_data == 0) + host_arm_VMOV_D_D(block, dest_reg, src_reg); + else if (uop->imm_data > 31) + host_arm_VSHR_D_S32(block, dest_reg, src_reg, 31); else - fatal("MEM_STORE_REG - %02x\n", uop->src_reg_c_real); - host_arm_TST_REG(block, REG_R1, REG_R1); - host_arm_BNE(block, (uintptr_t)codegen_exit_rout); + host_arm_VSHR_D_S32(block, dest_reg, src_reg, uop->imm_data); + } else + fatal("PSRAD_IMM %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real); - return 0; + return 0; } - -static int codegen_MEM_STORE_IMM_8(codeblock_t *block, uop_t *uop) +static int +codegen_PSRAQ_IMM(codeblock_t *block, uop_t *uop) { - int seg_reg = HOST_REG_GET(uop->src_reg_a_real), addr_reg = HOST_REG_GET(uop->src_reg_b_real); + int dest_reg = HOST_REG_GET(uop->dest_reg_a_real); + int src_reg = HOST_REG_GET(uop->src_reg_a_real); + int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real); + int src_size = IREG_GET_SIZE(uop->src_reg_a_real); - host_arm_ADD_REG(block, REG_R0, seg_reg, addr_reg); - host_arm_MOV_IMM(block, REG_R1, uop->imm_data); - host_arm_BL(block, (uintptr_t)codegen_mem_store_byte); - host_arm_TST_REG(block, REG_R1, REG_R1); - host_arm_BNE(block, (uintptr_t)codegen_exit_rout); - - return 0; -} -static int codegen_MEM_STORE_IMM_16(codeblock_t *block, uop_t *uop) -{ - int seg_reg = HOST_REG_GET(uop->src_reg_a_real), addr_reg = HOST_REG_GET(uop->src_reg_b_real); - - host_arm_ADD_REG(block, REG_R0, seg_reg, addr_reg); - host_arm_MOV_IMM(block, REG_R1, uop->imm_data); - host_arm_BL(block, (uintptr_t)codegen_mem_store_word); - host_arm_TST_REG(block, REG_R1, REG_R1); - host_arm_BNE(block, (uintptr_t)codegen_exit_rout); - - return 0; -} -static int codegen_MEM_STORE_IMM_32(codeblock_t *block, uop_t *uop) -{ - int seg_reg = HOST_REG_GET(uop->src_reg_a_real), addr_reg = HOST_REG_GET(uop->src_reg_b_real); - - host_arm_ADD_REG(block, REG_R0, seg_reg, addr_reg); - host_arm_MOV_IMM(block, REG_R1, uop->imm_data); - host_arm_BL(block, (uintptr_t)codegen_mem_store_long); - host_arm_TST_REG(block, REG_R1, REG_R1); - host_arm_BNE(block, (uintptr_t)codegen_exit_rout); - - return 0; -} -static int codegen_MEM_STORE_SINGLE(codeblock_t *block, uop_t *uop) -{ - int seg_reg = HOST_REG_GET(uop->src_reg_a_real), addr_reg = HOST_REG_GET(uop->src_reg_b_real), src_reg = HOST_REG_GET(uop->src_reg_c_real); - int src_size = IREG_GET_SIZE(uop->src_reg_c_real); - - if (!REG_IS_D(src_size)) - fatal("MEM_STORE_REG - %02x\n", uop->dest_reg_a_real); - - host_arm_ADD_REG(block, REG_R0, seg_reg, addr_reg); - if (uop->imm_data) - host_arm_ADD_IMM(block, REG_R0, REG_R0, uop->imm_data); - host_arm_VCVT_S_D(block, REG_D_TEMP, src_reg); - host_arm_BL(block, (uintptr_t)codegen_mem_store_single); - host_arm_TST_REG(block, REG_R1, REG_R1); - host_arm_BNE(block, (uintptr_t)codegen_exit_rout); - - return 0; -} -static int codegen_MEM_STORE_DOUBLE(codeblock_t *block, uop_t *uop) -{ - int seg_reg = HOST_REG_GET(uop->src_reg_a_real), addr_reg = HOST_REG_GET(uop->src_reg_b_real), src_reg = HOST_REG_GET(uop->src_reg_c_real); - int src_size = IREG_GET_SIZE(uop->src_reg_c_real); - - if (!REG_IS_D(src_size)) - fatal("MEM_STORE_REG - %02x\n", uop->dest_reg_a_real); - - host_arm_ADD_REG(block, REG_R0, seg_reg, addr_reg); - if (uop->imm_data) - host_arm_ADD_IMM(block, REG_R0, REG_R0, uop->imm_data); - host_arm_VMOV_D_D(block, REG_D_TEMP, src_reg); - host_arm_BL(block, (uintptr_t)codegen_mem_store_double); - host_arm_TST_REG(block, REG_R1, REG_R1); - host_arm_BNE(block, (uintptr_t)codegen_exit_rout); - - return 0; -} - -static int codegen_MOV(codeblock_t *block, uop_t *uop) -{ - int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg = HOST_REG_GET(uop->src_reg_a_real); - int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size = IREG_GET_SIZE(uop->src_reg_a_real); - - if (REG_IS_L(dest_size) && REG_IS_L(src_size)) - { - host_arm_MOV_REG_LSL(block, dest_reg, src_reg, 0); - } - else if (REG_IS_W(dest_size) && REG_IS_W(src_size)) - { - host_arm_BFI(block, dest_reg, src_reg, 0, 16); - } - else if (REG_IS_B(dest_size) && REG_IS_B(src_size)) - { - host_arm_BFI(block, dest_reg, src_reg, 0, 8); - } - else if (REG_IS_BH(dest_size) && REG_IS_B(src_size)) - { - host_arm_BFI(block, dest_reg, src_reg, 8, 8); - } - else if (REG_IS_B(dest_size) && REG_IS_BH(src_size)) - { - host_arm_MOV_REG_LSR(block, REG_TEMP, src_reg, 8); - host_arm_BFI(block, dest_reg, REG_TEMP, 0, 8); - } - else if (REG_IS_BH(dest_size) && REG_IS_BH(src_size)) - { - host_arm_MOV_REG_LSR(block, REG_TEMP, src_reg, 8); - host_arm_BFI(block, dest_reg, REG_TEMP, 8, 8); - } - else if (REG_IS_D(dest_size) && REG_IS_D(src_size)) - { - host_arm_VMOV_D_D(block, dest_reg, src_reg); - } - else if (REG_IS_Q(dest_size) && REG_IS_Q(src_size)) - { - host_arm_VMOV_D_D(block, dest_reg, src_reg); - } - else - fatal("MOV %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real); - - return 0; -} - -static int codegen_MOV_IMM(codeblock_t *block, uop_t *uop) -{ - int dest_reg = HOST_REG_GET(uop->dest_reg_a_real); - int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real); - - if (REG_IS_L(dest_size)) - { - host_arm_MOV_IMM(block, dest_reg, uop->imm_data); - } - else if (REG_IS_W(dest_size)) - { - host_arm_MOVW_IMM(block, REG_TEMP, uop->imm_data); - host_arm_BFI(block, dest_reg, REG_TEMP, 0, 16); - } - else if (REG_IS_B(dest_size)) - { - host_arm_AND_IMM(block, dest_reg, dest_reg, ~0x000000ff); - host_arm_ORR_IMM(block, dest_reg, dest_reg, uop->imm_data); - } - else if (REG_IS_BH(dest_size)) - { - host_arm_AND_IMM(block, dest_reg, dest_reg, ~0x0000ff00); - host_arm_ORR_IMM(block, dest_reg, dest_reg, uop->imm_data << 8); - } - else - fatal("MOV_IMM %02x\n", uop->dest_reg_a_real); - - return 0; -} -static int codegen_MOV_PTR(codeblock_t *block, uop_t *uop) -{ - host_arm_MOV_IMM(block, uop->dest_reg_a_real, (uintptr_t)uop->p); - - return 0; -} - -static int codegen_MOVSX(codeblock_t *block, uop_t *uop) -{ - int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg = HOST_REG_GET(uop->src_reg_a_real); - int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size = IREG_GET_SIZE(uop->src_reg_a_real); - - if (REG_IS_L(dest_size) && REG_IS_B(src_size)) - { - host_arm_SXTB(block, dest_reg, src_reg, 0); - } - else if (REG_IS_L(dest_size) && REG_IS_BH(src_size)) - { - host_arm_SXTB(block, dest_reg, src_reg, 8); - } - else if (REG_IS_L(dest_size) && REG_IS_W(src_size)) - { - host_arm_SXTH(block, dest_reg, src_reg, 0); - } - else if (REG_IS_W(dest_size) && REG_IS_B(src_size)) - { - host_arm_SXTB(block, REG_TEMP, src_reg, 0); - host_arm_BFI(block, dest_reg, REG_TEMP, 0, 16); - } - else if (REG_IS_W(dest_size) && REG_IS_BH(src_size)) - { - host_arm_SXTB(block, REG_TEMP, src_reg, 8); - host_arm_BFI(block, dest_reg, REG_TEMP, 0, 16); - } - else - fatal("MOVSX %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real); - - return 0; -} -static int codegen_MOVZX(codeblock_t *block, uop_t *uop) -{ - int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg = HOST_REG_GET(uop->src_reg_a_real); - int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size = IREG_GET_SIZE(uop->src_reg_a_real); - - if (REG_IS_Q(dest_size) && REG_IS_L(src_size)) - { - host_arm_MOV_IMM(block, REG_TEMP, 0); - host_arm_VMOV_D_64(block, dest_reg, src_reg, REG_TEMP); - } - else if (REG_IS_L(dest_size) && REG_IS_Q(src_size)) - { - host_arm_VMOV_32_S(block, dest_reg, src_reg); - } - else if (REG_IS_L(dest_size) && REG_IS_B(src_size)) - { - host_arm_UXTB(block, dest_reg, src_reg, 0); - } - else if (REG_IS_L(dest_size) && REG_IS_BH(src_size)) - { - host_arm_UXTB(block, dest_reg, src_reg, 8); - } - else if (REG_IS_L(dest_size) && REG_IS_W(src_size)) - { - host_arm_UXTH(block, dest_reg, src_reg, 0); - } - else if (REG_IS_W(dest_size) && REG_IS_B(src_size)) - { - if (src_reg == dest_reg) - host_arm_BIC_IMM(block, dest_reg, dest_reg, 0xff00); - else - { - host_arm_UXTB(block, REG_TEMP, src_reg, 0); - host_arm_BFI(block, dest_reg, REG_TEMP, 0, 16); - } - } - else if (REG_IS_W(dest_size) && REG_IS_BH(src_size)) - { - host_arm_MOV_REG_LSR(block, REG_TEMP, src_reg, 8); - host_arm_BIC_IMM(block, dest_reg, dest_reg, 0xff00); - host_arm_BFI(block, dest_reg, REG_TEMP, 0, 8); - } - else - fatal("MOVZX %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real); - - return 0; -} -static double int64_to_double(int64_t a) -{ - return (double)a; -} -static int codegen_MOV_DOUBLE_INT(codeblock_t *block, uop_t *uop) -{ - int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg = HOST_REG_GET(uop->src_reg_a_real); - int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size = IREG_GET_SIZE(uop->src_reg_a_real); - - if (REG_IS_D(dest_size) && REG_IS_L(src_size)) - { - host_arm_VMOV_S_32(block, REG_D_TEMP, src_reg); - host_arm_VCVT_D_IS(block, dest_reg, REG_D_TEMP); - } - else if (REG_IS_D(dest_size) && REG_IS_W(src_size)) - { - host_arm_SXTH(block, REG_TEMP, src_reg, 0); - host_arm_VMOV_S_32(block, REG_D_TEMP, REG_TEMP); - host_arm_VCVT_D_IS(block, dest_reg, REG_D_TEMP); - } - else if (REG_IS_D(dest_size) && REG_IS_Q(src_size)) - { - /*ARMv7 has no instructions to convert a 64-bit integer to a double. - For simplicity, call a C function and let the compiler do it.*/ - host_arm_VMOV_64_D(block, REG_R0, REG_R1, src_reg); - host_arm_BL(block, (uintptr_t)int64_to_double); /*Input - R0/R1, Output - D0*/ - host_arm_VMOV_D_D(block, dest_reg, REG_D0); - } + if (REG_IS_Q(dest_size) && REG_IS_Q(src_size)) { + if (uop->imm_data == 0) + host_arm_VMOV_D_D(block, dest_reg, src_reg); + else if (uop->imm_data > 63) + host_arm_VSHR_D_S64(block, dest_reg, src_reg, 63); else - fatal("MOV_DOUBLE_INT %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real); + host_arm_VSHR_D_S64(block, dest_reg, src_reg, uop->imm_data); + } else + fatal("PSRAQ_IMM %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real); - return 0; + return 0; } -static int codegen_MOV_INT_DOUBLE(codeblock_t *block, uop_t *uop) +static int +codegen_PSRLW_IMM(codeblock_t *block, uop_t *uop) { - int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg = HOST_REG_GET(uop->src_reg_a_real); - int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size = IREG_GET_SIZE(uop->src_reg_a_real); + int dest_reg = HOST_REG_GET(uop->dest_reg_a_real); + int src_reg = HOST_REG_GET(uop->src_reg_a_real); + int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real); + int src_size = IREG_GET_SIZE(uop->src_reg_a_real); - if (REG_IS_L(dest_size) && REG_IS_D(src_size)) - { - host_arm_VMOV_D_D(block, REG_D_TEMP, src_reg); - host_arm_BL(block, (uintptr_t)codegen_fp_round); - host_arm_VMOV_32_S(block, dest_reg, REG_D_TEMP); - } - else if (REG_IS_W(dest_size) && REG_IS_D(src_size)) - { - host_arm_VMOV_D_D(block, REG_D_TEMP, src_reg); - host_arm_BL(block, (uintptr_t)codegen_fp_round); - host_arm_VMOV_32_S(block, REG_TEMP, REG_D_TEMP); - host_arm_BFI(block, dest_reg, REG_TEMP, 0, 16); - } + if (REG_IS_Q(dest_size) && REG_IS_Q(src_size)) { + if (uop->imm_data == 0) + host_arm_VMOV_D_D(block, dest_reg, src_reg); + else if (uop->imm_data > 15) + host_arm_VEOR_D(block, dest_reg, dest_reg, dest_reg); else - fatal("MOV_INT_DOUBLE %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real); + host_arm_VSHR_D_U16(block, dest_reg, src_reg, uop->imm_data); + } else + fatal("PSRLW_IMM %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real); - return 0; + return 0; } -static int64_t x87_fround64(double b) +static int +codegen_PSRLD_IMM(codeblock_t *block, uop_t *uop) { - int64_t a, c; - - switch ((cpu_state.npxc >> 10) & 3) - { - case 0: /*Nearest*/ - a = (int64_t)floor(b); - c = (int64_t)floor(b + 1.0); - if ((b - a) < (c - b)) - return a; - else if ((b - a) > (c - b)) - return c; - else - return (a & 1) ? c : a; - case 1: /*Down*/ - return (int64_t)floor(b); - case 2: /*Up*/ - return (int64_t)ceil(b); - case 3: /*Chop*/ - return (int64_t)b; - } - - return 0; -} -static int codegen_MOV_INT_DOUBLE_64(codeblock_t *block, uop_t *uop) -{ - int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg = HOST_REG_GET(uop->src_reg_a_real), src_64_reg = HOST_REG_GET(uop->src_reg_b_real), tag_reg = HOST_REG_GET(uop->src_reg_c_real); - int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size = IREG_GET_SIZE(uop->src_reg_a_real), src_64_size = IREG_GET_SIZE(uop->src_reg_b_real); + int dest_reg = HOST_REG_GET(uop->dest_reg_a_real); + int src_reg = HOST_REG_GET(uop->src_reg_a_real); + int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real); + int src_size = IREG_GET_SIZE(uop->src_reg_a_real); - if (REG_IS_Q(dest_size) && REG_IS_D(src_size) && REG_IS_Q(src_64_size)) - { - uint32_t *branch_offset; - - /*If TAG_UINT64 is set then the source is MM[]. Otherwise it is a double in ST()*/ - host_arm_VMOV_D_D(block, dest_reg, src_64_reg); - host_arm_TST_IMM(block, tag_reg, TAG_UINT64); - branch_offset = host_arm_BNE_(block); - - /*VFP/NEON has no instructions to convert a float to 64-bit integer, - so call out to C.*/ - host_arm_VMOV_D_D(block, REG_D0, src_reg); - host_arm_call(block, x87_fround64); - host_arm_VMOV_D_64(block, REG_D_TEMP, REG_R0, REG_R1); - - *branch_offset |= ((((uintptr_t)&block_write_data[block_pos] - (uintptr_t)branch_offset) - 8) & 0x3fffffc) >> 2; - } + if (REG_IS_Q(dest_size) && REG_IS_Q(src_size)) { + if (uop->imm_data == 0) + host_arm_VMOV_D_D(block, dest_reg, src_reg); + else if (uop->imm_data > 31) + host_arm_VEOR_D(block, dest_reg, dest_reg, dest_reg); else - fatal("MOV_INT_DOUBLE_64 %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real); + host_arm_VSHR_D_U32(block, dest_reg, src_reg, uop->imm_data); + } else + fatal("PSRLD_IMM %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real); - return 0; + return 0; } -static int codegen_MOV_REG_PTR(codeblock_t *block, uop_t *uop) +static int +codegen_PSRLQ_IMM(codeblock_t *block, uop_t *uop) { - int dest_reg = HOST_REG_GET(uop->dest_reg_a_real); - int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real); + int dest_reg = HOST_REG_GET(uop->dest_reg_a_real); + int src_reg = HOST_REG_GET(uop->src_reg_a_real); + int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real); + int src_size = IREG_GET_SIZE(uop->src_reg_a_real); - host_arm_MOV_IMM(block, REG_TEMP, (uintptr_t)uop->p); - if (REG_IS_L(dest_size)) - { - host_arm_LDR_IMM(block, dest_reg, REG_TEMP, 0); - } + if (REG_IS_Q(dest_size) && REG_IS_Q(src_size)) { + if (uop->imm_data == 0) + host_arm_VMOV_D_D(block, dest_reg, src_reg); + else if (uop->imm_data > 63) + host_arm_VEOR_D(block, dest_reg, dest_reg, dest_reg); else - fatal("MOV_REG_PTR %02x\n", uop->dest_reg_a_real); + host_arm_VSHR_D_U64(block, dest_reg, src_reg, uop->imm_data); + } else + fatal("PSRLQ_IMM %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real); - return 0; -} -static int codegen_MOVZX_REG_PTR_8(codeblock_t *block, uop_t *uop) -{ - int dest_reg = HOST_REG_GET(uop->dest_reg_a_real); - int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real); - - host_arm_MOV_IMM(block, REG_TEMP, (uintptr_t)uop->p); - if (REG_IS_L(dest_size)) - { - host_arm_LDRB_IMM(block, dest_reg, REG_TEMP, 0); - } - else if (REG_IS_W(dest_size)) - { - host_arm_LDRB_IMM(block, REG_TEMP, REG_TEMP, 0); - host_arm_BFI(block, dest_reg, REG_TEMP, 0, 16); - } - else if (REG_IS_B(dest_size)) - { - host_arm_LDRB_IMM(block, REG_TEMP, REG_TEMP, 0); - host_arm_BFI(block, dest_reg, REG_TEMP, 0, 8); - } - else - fatal("MOVZX_REG_PTR_8 %02x\n", uop->dest_reg_a_real); - - return 0; -} -static int codegen_MOVZX_REG_PTR_16(codeblock_t *block, uop_t *uop) -{ - int dest_reg = HOST_REG_GET(uop->dest_reg_a_real); - int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real); - - host_arm_MOV_IMM(block, REG_TEMP, (uintptr_t)uop->p); - if (REG_IS_L(dest_size)) - { - host_arm_LDRH_IMM(block, dest_reg, REG_TEMP, 0); - } - else if (REG_IS_W(dest_size)) - { - host_arm_LDRH_IMM(block, REG_TEMP, REG_TEMP, 0); - host_arm_BFI(block, dest_reg, REG_TEMP, 0, 16); - } - else - fatal("MOVZX_REG_PTR_16 %02x\n", uop->dest_reg_a_real); - - return 0; + return 0; } -static int codegen_NOP(codeblock_t *block, uop_t *uop) +static int +codegen_PSUBB(codeblock_t *block, uop_t *uop) { - return 0; + int dest_reg = HOST_REG_GET(uop->dest_reg_a_real); + int src_reg_a = HOST_REG_GET(uop->src_reg_a_real); + int src_reg_b = HOST_REG_GET(uop->src_reg_b_real); + int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real); + int src_size_a = IREG_GET_SIZE(uop->src_reg_a_real); + int src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); + + if (REG_IS_Q(dest_size) && REG_IS_Q(src_size_a) && REG_IS_Q(src_size_b)) { + host_arm_VSUB_I8(block, dest_reg, src_reg_a, src_reg_b); + } else + fatal("PSUBB %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real); + + return 0; +} +static int +codegen_PSUBW(codeblock_t *block, uop_t *uop) +{ + int dest_reg = HOST_REG_GET(uop->dest_reg_a_real); + int src_reg_a = HOST_REG_GET(uop->src_reg_a_real); + int src_reg_b = HOST_REG_GET(uop->src_reg_b_real); + int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real); + int src_size_a = IREG_GET_SIZE(uop->src_reg_a_real); + int src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); + + if (REG_IS_Q(dest_size) && REG_IS_Q(src_size_a) && REG_IS_Q(src_size_b)) { + host_arm_VSUB_I16(block, dest_reg, src_reg_a, src_reg_b); + } else + fatal("PSUBW %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real); + + return 0; +} +static int +codegen_PSUBD(codeblock_t *block, uop_t *uop) +{ + int dest_reg = HOST_REG_GET(uop->dest_reg_a_real); + int src_reg_a = HOST_REG_GET(uop->src_reg_a_real); + int src_reg_b = HOST_REG_GET(uop->src_reg_b_real); + int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real); + int src_size_a = IREG_GET_SIZE(uop->src_reg_a_real); + int src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); + + if (REG_IS_Q(dest_size) && REG_IS_Q(src_size_a) && REG_IS_Q(src_size_b)) { + host_arm_VSUB_I32(block, dest_reg, src_reg_a, src_reg_b); + } else + fatal("PSUBD %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real); + + return 0; +} +static int +codegen_PSUBSB(codeblock_t *block, uop_t *uop) +{ + int dest_reg = HOST_REG_GET(uop->dest_reg_a_real); + int src_reg_a = HOST_REG_GET(uop->src_reg_a_real); + int src_reg_b = HOST_REG_GET(uop->src_reg_b_real); + int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real); + int src_size_a = IREG_GET_SIZE(uop->src_reg_a_real); + int src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); + + if (REG_IS_Q(dest_size) && REG_IS_Q(src_size_a) && REG_IS_Q(src_size_b)) { + host_arm_VQSUB_S8(block, dest_reg, src_reg_a, src_reg_b); + } else + fatal("PSUBSB %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real); + + return 0; +} +static int +codegen_PSUBSW(codeblock_t *block, uop_t *uop) +{ + int dest_reg = HOST_REG_GET(uop->dest_reg_a_real); + int src_reg_a = HOST_REG_GET(uop->src_reg_a_real); + int src_reg_b = HOST_REG_GET(uop->src_reg_b_real); + int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real); + int src_size_a = IREG_GET_SIZE(uop->src_reg_a_real); + int src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); + + if (REG_IS_Q(dest_size) && REG_IS_Q(src_size_a) && REG_IS_Q(src_size_b)) { + host_arm_VQSUB_S16(block, dest_reg, src_reg_a, src_reg_b); + } else + fatal("PSUBSW %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real); + + return 0; +} +static int +codegen_PSUBUSB(codeblock_t *block, uop_t *uop) +{ + int dest_reg = HOST_REG_GET(uop->dest_reg_a_real); + int src_reg_a = HOST_REG_GET(uop->src_reg_a_real); + int src_reg_b = HOST_REG_GET(uop->src_reg_b_real); + int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real); + int src_size_a = IREG_GET_SIZE(uop->src_reg_a_real); + int src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); + + if (REG_IS_Q(dest_size) && REG_IS_Q(src_size_a) && REG_IS_Q(src_size_b)) { + host_arm_VQSUB_U8(block, dest_reg, src_reg_a, src_reg_b); + } else + fatal("PSUBUSB %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real); + + return 0; +} +static int +codegen_PSUBUSW(codeblock_t *block, uop_t *uop) +{ + int dest_reg = HOST_REG_GET(uop->dest_reg_a_real); + int src_reg_a = HOST_REG_GET(uop->src_reg_a_real); + int src_reg_b = HOST_REG_GET(uop->src_reg_b_real); + int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real); + int src_size_a = IREG_GET_SIZE(uop->src_reg_a_real); + int src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); + + if (REG_IS_Q(dest_size) && REG_IS_Q(src_size_a) && REG_IS_Q(src_size_b)) { + host_arm_VQSUB_U16(block, dest_reg, src_reg_a, src_reg_b); + } else + fatal("PSUBUSW %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real); + + return 0; } -static int codegen_OR(codeblock_t *block, uop_t *uop) +static int +codegen_PUNPCKHBW(codeblock_t *block, uop_t *uop) { - int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg_a = HOST_REG_GET(uop->src_reg_a_real), src_reg_b = HOST_REG_GET(uop->src_reg_b_real); - int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size_a = IREG_GET_SIZE(uop->src_reg_a_real), src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); + int dest_reg = HOST_REG_GET(uop->dest_reg_a_real); + int src_reg_a = HOST_REG_GET(uop->src_reg_a_real); + int src_reg_b = HOST_REG_GET(uop->src_reg_b_real); + int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real); + int src_size_a = IREG_GET_SIZE(uop->src_reg_a_real); + int src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); - if (REG_IS_Q(dest_size) && REG_IS_Q(src_size_a) && REG_IS_Q(src_size_b)) - { - host_arm_VORR_D(block, dest_reg, src_reg_a, src_reg_b); - } - else if (REG_IS_L(dest_size) && REG_IS_L(src_size_a) && REG_IS_L(src_size_b)) - { - host_arm_ORR_REG_LSL(block, dest_reg, src_reg_a, src_reg_b, 0); - } - else if (REG_IS_W(dest_size) && REG_IS_W(src_size_a) && REG_IS_W(src_size_b)) - { - host_arm_ORR_REG_LSL(block, REG_TEMP, src_reg_a, src_reg_b, 0); - host_arm_BFI(block, dest_reg, REG_TEMP, 0, 16); - } - else if (REG_IS_B(dest_size) && REG_IS_B(src_size_a) && REG_IS_B(src_size_b) && dest_reg == src_reg_a) - { - host_arm_UXTB(block, REG_TEMP, src_reg_b, 0); - host_arm_ORR_REG_LSL(block, dest_reg, src_reg_a, REG_TEMP, 0); - } - else if (REG_IS_B(dest_size) && REG_IS_B(src_size_a) && REG_IS_BH(src_size_b) && dest_reg == src_reg_a) - { - host_arm_UXTB(block, REG_TEMP, src_reg_b, 8); - host_arm_ORR_REG_LSL(block, dest_reg, src_reg_a, REG_TEMP, 0); - } - else if (REG_IS_BH(dest_size) && REG_IS_BH(src_size_a) && REG_IS_B(src_size_b) && dest_reg == src_reg_a) - { - host_arm_UXTB(block, REG_TEMP, src_reg_b, 0); - host_arm_ORR_REG_LSL(block, dest_reg, src_reg_a, REG_TEMP, 8); - } - else if (REG_IS_BH(dest_size) && REG_IS_BH(src_size_a) && REG_IS_BH(src_size_b) && dest_reg == src_reg_a) - { - host_arm_UXTB(block, REG_TEMP, src_reg_b, 8); - host_arm_ORR_REG_LSL(block, dest_reg, src_reg_a, REG_TEMP, 8); - } - else - fatal("OR %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real); + if (REG_IS_Q(dest_size) && REG_IS_Q(src_size_a) && REG_IS_Q(src_size_b)) { + host_arm_VMOV_D_D(block, REG_D_TEMP, src_reg_b); + if (dest_reg != src_reg_a) + host_arm_VMOV_D_D(block, dest_reg, src_reg_a); + host_arm_VZIP_D8(block, dest_reg, REG_D_TEMP); + host_arm_VMOV_D_D(block, dest_reg, REG_D_TEMP); + } else + fatal("PUNPCKHBW %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real); - return 0; + return 0; } -static int codegen_OR_IMM(codeblock_t *block, uop_t *uop) +static int +codegen_PUNPCKHWD(codeblock_t *block, uop_t *uop) { - int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg = HOST_REG_GET(uop->src_reg_a_real); - int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size = IREG_GET_SIZE(uop->src_reg_a_real); + int dest_reg = HOST_REG_GET(uop->dest_reg_a_real); + int src_reg_a = HOST_REG_GET(uop->src_reg_a_real); + int src_reg_b = HOST_REG_GET(uop->src_reg_b_real); + int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real); + int src_size_a = IREG_GET_SIZE(uop->src_reg_a_real); + int src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); - if (REG_IS_L(dest_size) && REG_IS_L(src_size)) - { - host_arm_ORR_IMM(block, dest_reg, src_reg, uop->imm_data); - } - else if (REG_IS_W(dest_size) && REG_IS_W(src_size) && dest_reg == src_reg) - { - host_arm_ORR_IMM(block, dest_reg, src_reg, uop->imm_data); - } - else if (REG_IS_B(dest_size) && REG_IS_B(src_size) && dest_reg == src_reg) - { - host_arm_ORR_IMM(block, dest_reg, src_reg, uop->imm_data); - } - else if (REG_IS_BH(dest_size) && REG_IS_BH(src_size) && dest_reg == src_reg) - { - host_arm_ORR_IMM(block, dest_reg, src_reg, uop->imm_data << 8); - } - else - fatal("OR_IMM %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real); + if (REG_IS_Q(dest_size) && REG_IS_Q(src_size_a) && REG_IS_Q(src_size_b)) { + host_arm_VMOV_D_D(block, REG_D_TEMP, src_reg_b); + if (dest_reg != src_reg_a) + host_arm_VMOV_D_D(block, dest_reg, src_reg_a); + host_arm_VZIP_D16(block, dest_reg, REG_D_TEMP); + host_arm_VMOV_D_D(block, dest_reg, REG_D_TEMP); + } else + fatal("PUNPCKHWD %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real); - return 0; + return 0; +} +static int +codegen_PUNPCKHDQ(codeblock_t *block, uop_t *uop) +{ + int dest_reg = HOST_REG_GET(uop->dest_reg_a_real); + int src_reg_a = HOST_REG_GET(uop->src_reg_a_real); + int src_reg_b = HOST_REG_GET(uop->src_reg_b_real); + int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real); + int src_size_a = IREG_GET_SIZE(uop->src_reg_a_real); + int src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); + + if (REG_IS_Q(dest_size) && REG_IS_Q(src_size_a) && REG_IS_Q(src_size_b)) { + host_arm_VMOV_D_D(block, REG_D_TEMP, src_reg_b); + if (dest_reg != src_reg_a) + host_arm_VMOV_D_D(block, dest_reg, src_reg_a); + host_arm_VZIP_D32(block, dest_reg, REG_D_TEMP); + host_arm_VMOV_D_D(block, dest_reg, REG_D_TEMP); + } else + fatal("PUNPCKHDQ %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real); + + return 0; +} +static int +codegen_PUNPCKLBW(codeblock_t *block, uop_t *uop) +{ + int dest_reg = HOST_REG_GET(uop->dest_reg_a_real); + int src_reg_a = HOST_REG_GET(uop->src_reg_a_real); + int src_reg_b = HOST_REG_GET(uop->src_reg_b_real); + int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real); + int src_size_a = IREG_GET_SIZE(uop->src_reg_a_real); + int src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); + + if (REG_IS_Q(dest_size) && REG_IS_Q(src_size_a) && REG_IS_Q(src_size_b)) { + host_arm_VMOV_D_D(block, REG_D_TEMP, src_reg_b); + if (dest_reg != src_reg_a) + host_arm_VMOV_D_D(block, dest_reg, src_reg_a); + host_arm_VZIP_D8(block, dest_reg, REG_D_TEMP); + } else + fatal("PUNPCKLBW %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real); + + return 0; +} +static int +codegen_PUNPCKLWD(codeblock_t *block, uop_t *uop) +{ + int dest_reg = HOST_REG_GET(uop->dest_reg_a_real); + int src_reg_a = HOST_REG_GET(uop->src_reg_a_real); + int src_reg_b = HOST_REG_GET(uop->src_reg_b_real); + int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real); + int src_size_a = IREG_GET_SIZE(uop->src_reg_a_real); + int src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); + + if (REG_IS_Q(dest_size) && REG_IS_Q(src_size_a) && REG_IS_Q(src_size_b)) { + host_arm_VMOV_D_D(block, REG_D_TEMP, src_reg_b); + if (dest_reg != src_reg_a) + host_arm_VMOV_D_D(block, dest_reg, src_reg_a); + host_arm_VZIP_D16(block, dest_reg, REG_D_TEMP); + } else + fatal("PUNPCKLWD %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real); + + return 0; +} +static int +codegen_PUNPCKLDQ(codeblock_t *block, uop_t *uop) +{ + int dest_reg = HOST_REG_GET(uop->dest_reg_a_real); + int src_reg_a = HOST_REG_GET(uop->src_reg_a_real); + int src_reg_b = HOST_REG_GET(uop->src_reg_b_real); + int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real); + int src_size_a = IREG_GET_SIZE(uop->src_reg_a_real); + int src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); + + if (REG_IS_Q(dest_size) && REG_IS_Q(src_size_a) && REG_IS_Q(src_size_b)) { + host_arm_VMOV_D_D(block, REG_D_TEMP, src_reg_b); + if (dest_reg != src_reg_a) + host_arm_VMOV_D_D(block, dest_reg, src_reg_a); + host_arm_VZIP_D32(block, dest_reg, REG_D_TEMP); + } else + fatal("PUNPCKLDQ %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real); + + return 0; } -static int codegen_PACKSSWB(codeblock_t *block, uop_t *uop) +static int +codegen_ROL(codeblock_t *block, uop_t *uop) { - int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg_a = HOST_REG_GET(uop->src_reg_a_real), src_reg_b = HOST_REG_GET(uop->src_reg_b_real); - int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size_a = IREG_GET_SIZE(uop->src_reg_a_real), src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); + int dest_reg = HOST_REG_GET(uop->dest_reg_a_real); + int src_reg = HOST_REG_GET(uop->src_reg_a_real); + int shift_reg = HOST_REG_GET(uop->src_reg_b_real); + int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real); + int src_size = IREG_GET_SIZE(uop->src_reg_a_real); - if (REG_IS_Q(dest_size) && REG_IS_Q(src_size_a) && REG_IS_Q(src_size_b)) - { - host_arm_VMOV_D_D(block, REG_Q_TEMP, src_reg_a); - host_arm_VMOV_D_D(block, REG_Q_TEMP_2, src_reg_b); - host_arm_VQMOVN_S16(block, dest_reg, REG_Q_TEMP); - host_arm_VQMOVN_S16(block, REG_D_TEMP, REG_Q_TEMP_2); - host_arm_VZIP_D32(block, dest_reg, REG_D_TEMP); - } - else - fatal("PACKSSWB %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real); + if (REG_IS_L(dest_size) && REG_IS_L(src_size)) { + host_arm_RSB_IMM(block, REG_TEMP2, shift_reg, 32); + host_arm_MOV_REG_ROR_REG(block, dest_reg, src_reg, REG_TEMP2); + } else if (REG_IS_W(dest_size) && REG_IS_W(src_size)) { + host_arm_UXTH(block, REG_TEMP, src_reg, 0); + host_arm_RSB_IMM(block, REG_TEMP2, shift_reg, 16); + host_arm_ORR_REG_LSL(block, REG_TEMP, REG_TEMP, REG_TEMP, 16); + host_arm_MOV_REG_ROR_REG(block, REG_TEMP, REG_TEMP, REG_TEMP2); + host_arm_BFI(block, dest_reg, REG_TEMP, 0, 16); + } else if (REG_IS_B(dest_size) && REG_IS_B(src_size)) { + host_arm_RSB_IMM(block, REG_TEMP2, shift_reg, 8); + host_arm_UXTB(block, REG_TEMP, src_reg, 0); + host_arm_AND_IMM(block, REG_TEMP2, REG_TEMP2, 7); + host_arm_ORR_REG_LSL(block, REG_TEMP, REG_TEMP, REG_TEMP, 8); + host_arm_MOV_REG_LSR_REG(block, REG_TEMP, REG_TEMP, REG_TEMP2); + host_arm_BFI(block, dest_reg, REG_TEMP, 0, 8); + } else if (REG_IS_BH(dest_size) && REG_IS_BH(src_size)) { + host_arm_RSB_IMM(block, REG_TEMP2, shift_reg, 8); + host_arm_UXTB(block, REG_TEMP, src_reg, 8); + host_arm_AND_IMM(block, REG_TEMP2, REG_TEMP2, 7); + host_arm_ORR_REG_LSL(block, REG_TEMP, REG_TEMP, REG_TEMP, 8); + host_arm_MOV_REG_LSR_REG(block, REG_TEMP, REG_TEMP, REG_TEMP2); + host_arm_BFI(block, dest_reg, REG_TEMP, 8, 8); + } else + fatal("ROL %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real); - return 0; + return 0; } -static int codegen_PACKSSDW(codeblock_t *block, uop_t *uop) +static int +codegen_ROL_IMM(codeblock_t *block, uop_t *uop) { - int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg_a = HOST_REG_GET(uop->src_reg_a_real), src_reg_b = HOST_REG_GET(uop->src_reg_b_real); - int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size_a = IREG_GET_SIZE(uop->src_reg_a_real), src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); + int dest_reg = HOST_REG_GET(uop->dest_reg_a_real); + int src_reg = HOST_REG_GET(uop->src_reg_a_real); + int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real); + int src_size = IREG_GET_SIZE(uop->src_reg_a_real); - if (REG_IS_Q(dest_size) && REG_IS_Q(src_size_a) && REG_IS_Q(src_size_b)) - { - host_arm_VMOV_D_D(block, REG_Q_TEMP, src_reg_a); - host_arm_VMOV_D_D(block, REG_Q_TEMP_2, src_reg_b); - host_arm_VQMOVN_S32(block, dest_reg, REG_Q_TEMP); - host_arm_VQMOVN_S32(block, REG_D_TEMP, REG_Q_TEMP_2); - host_arm_VZIP_D32(block, dest_reg, REG_D_TEMP); + if (REG_IS_L(dest_size) && REG_IS_L(src_size)) { + if (!(uop->imm_data & 31)) { + if (src_reg != dest_reg) + host_arm_MOV_REG(block, dest_reg, src_reg); + } else { + host_arm_MOV_REG_ROR(block, dest_reg, src_reg, 32 - (uop->imm_data & 31)); } - else - fatal("PACKSSDW %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real); - - return 0; -} -static int codegen_PACKUSWB(codeblock_t *block, uop_t *uop) -{ - int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg_a = HOST_REG_GET(uop->src_reg_a_real), src_reg_b = HOST_REG_GET(uop->src_reg_b_real); - int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size_a = IREG_GET_SIZE(uop->src_reg_a_real), src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); - - if (REG_IS_Q(dest_size) && REG_IS_Q(src_size_a) && REG_IS_Q(src_size_b)) - { - host_arm_VMOV_D_D(block, REG_Q_TEMP, src_reg_a); - host_arm_VMOV_D_D(block, REG_Q_TEMP_2, src_reg_b); - host_arm_VQMOVN_U16(block, dest_reg, REG_Q_TEMP); - host_arm_VQMOVN_U16(block, REG_D_TEMP, REG_Q_TEMP_2); - host_arm_VZIP_D32(block, dest_reg, REG_D_TEMP); + } else if (REG_IS_W(dest_size) && REG_IS_W(src_size)) { + if ((uop->imm_data & 15) == 0) { + if (src_reg != dest_reg) + host_arm_BFI(block, dest_reg, src_reg, 0, 16); + } else { + host_arm_UXTH(block, REG_TEMP, src_reg, 0); + host_arm_ORR_REG_LSL(block, REG_TEMP, REG_TEMP, REG_TEMP, 16); + host_arm_MOV_REG_LSR(block, REG_TEMP, REG_TEMP, 16 - (uop->imm_data & 15)); + host_arm_BFI(block, dest_reg, REG_TEMP, 0, 16); } - else - fatal("PACKUSWB %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real); - - return 0; -} - -static int codegen_PADDB(codeblock_t *block, uop_t *uop) -{ - int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg_a = HOST_REG_GET(uop->src_reg_a_real), src_reg_b = HOST_REG_GET(uop->src_reg_b_real); - int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size_a = IREG_GET_SIZE(uop->src_reg_a_real), src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); - - if (REG_IS_Q(dest_size) && REG_IS_Q(src_size_a) && REG_IS_Q(src_size_b)) - { - host_arm_VADD_I8(block, dest_reg, src_reg_a, src_reg_b); + } else if (REG_IS_B(dest_size) && REG_IS_B(src_size)) { + if ((uop->imm_data & 7) == 0) { + if (src_reg != dest_reg) + host_arm_BFI(block, dest_reg, src_reg, 0, 8); + } else { + host_arm_UXTB(block, REG_TEMP, src_reg, 0); + host_arm_ORR_REG_LSL(block, REG_TEMP, REG_TEMP, REG_TEMP, 8); + host_arm_MOV_REG_LSR(block, REG_TEMP, REG_TEMP, 8 - (uop->imm_data & 7)); + host_arm_BFI(block, dest_reg, REG_TEMP, 0, 8); } - else - fatal("PADDB %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real); - - return 0; -} -static int codegen_PADDW(codeblock_t *block, uop_t *uop) -{ - int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg_a = HOST_REG_GET(uop->src_reg_a_real), src_reg_b = HOST_REG_GET(uop->src_reg_b_real); - int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size_a = IREG_GET_SIZE(uop->src_reg_a_real), src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); - - if (REG_IS_Q(dest_size) && REG_IS_Q(src_size_a) && REG_IS_Q(src_size_b)) - { - host_arm_VADD_I16(block, dest_reg, src_reg_a, src_reg_b); - } - else - fatal("PADDW %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real); - - return 0; -} -static int codegen_PADDD(codeblock_t *block, uop_t *uop) -{ - int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg_a = HOST_REG_GET(uop->src_reg_a_real), src_reg_b = HOST_REG_GET(uop->src_reg_b_real); - int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size_a = IREG_GET_SIZE(uop->src_reg_a_real), src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); - - if (REG_IS_Q(dest_size) && REG_IS_Q(src_size_a) && REG_IS_Q(src_size_b)) - { - host_arm_VADD_I32(block, dest_reg, src_reg_a, src_reg_b); - } - else - fatal("PADDD %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real); - - return 0; -} -static int codegen_PADDSB(codeblock_t *block, uop_t *uop) -{ - int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg_a = HOST_REG_GET(uop->src_reg_a_real), src_reg_b = HOST_REG_GET(uop->src_reg_b_real); - int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size_a = IREG_GET_SIZE(uop->src_reg_a_real), src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); - - if (REG_IS_Q(dest_size) && REG_IS_Q(src_size_a) && REG_IS_Q(src_size_b)) - { - host_arm_VQADD_S8(block, dest_reg, src_reg_a, src_reg_b); - } - else - fatal("PADDSB %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real); - - return 0; -} -static int codegen_PADDSW(codeblock_t *block, uop_t *uop) -{ - int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg_a = HOST_REG_GET(uop->src_reg_a_real), src_reg_b = HOST_REG_GET(uop->src_reg_b_real); - int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size_a = IREG_GET_SIZE(uop->src_reg_a_real), src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); - - if (REG_IS_Q(dest_size) && REG_IS_Q(src_size_a) && REG_IS_Q(src_size_b)) - { - host_arm_VQADD_S16(block, dest_reg, src_reg_a, src_reg_b); - } - else - fatal("PADDSW %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real); - - return 0; -} -static int codegen_PADDUSB(codeblock_t *block, uop_t *uop) -{ - int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg_a = HOST_REG_GET(uop->src_reg_a_real), src_reg_b = HOST_REG_GET(uop->src_reg_b_real); - int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size_a = IREG_GET_SIZE(uop->src_reg_a_real), src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); - - if (REG_IS_Q(dest_size) && REG_IS_Q(src_size_a) && REG_IS_Q(src_size_b)) - { - host_arm_VQADD_U8(block, dest_reg, src_reg_a, src_reg_b); - } - else - fatal("PADDUSB %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real); - - return 0; -} -static int codegen_PADDUSW(codeblock_t *block, uop_t *uop) -{ - int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg_a = HOST_REG_GET(uop->src_reg_a_real), src_reg_b = HOST_REG_GET(uop->src_reg_b_real); - int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size_a = IREG_GET_SIZE(uop->src_reg_a_real), src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); - - if (REG_IS_Q(dest_size) && REG_IS_Q(src_size_a) && REG_IS_Q(src_size_b)) - { - host_arm_VQADD_U16(block, dest_reg, src_reg_a, src_reg_b); - } - else - fatal("PADDUSW %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real); - - return 0; -} - -static int codegen_PCMPEQB(codeblock_t *block, uop_t *uop) -{ - int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg_a = HOST_REG_GET(uop->src_reg_a_real), src_reg_b = HOST_REG_GET(uop->src_reg_b_real); - int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size_a = IREG_GET_SIZE(uop->src_reg_a_real), src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); - - if (REG_IS_Q(dest_size) && REG_IS_Q(src_size_a) && REG_IS_Q(src_size_b)) - { - host_arm_VCEQ_I8(block, dest_reg, src_reg_a, src_reg_b); - } - else - fatal("PCMPEQB %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real); - - return 0; -} -static int codegen_PCMPEQW(codeblock_t *block, uop_t *uop) -{ - int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg_a = HOST_REG_GET(uop->src_reg_a_real), src_reg_b = HOST_REG_GET(uop->src_reg_b_real); - int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size_a = IREG_GET_SIZE(uop->src_reg_a_real), src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); - - if (REG_IS_Q(dest_size) && REG_IS_Q(src_size_a) && REG_IS_Q(src_size_b)) - { - host_arm_VCEQ_I16(block, dest_reg, src_reg_a, src_reg_b); - } - else - fatal("PCMPEQW %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real); - - return 0; -} -static int codegen_PCMPEQD(codeblock_t *block, uop_t *uop) -{ - int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg_a = HOST_REG_GET(uop->src_reg_a_real), src_reg_b = HOST_REG_GET(uop->src_reg_b_real); - int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size_a = IREG_GET_SIZE(uop->src_reg_a_real), src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); - - if (REG_IS_Q(dest_size) && REG_IS_Q(src_size_a) && REG_IS_Q(src_size_b)) - { - host_arm_VCEQ_I32(block, dest_reg, src_reg_a, src_reg_b); - } - else - fatal("PCMPEQD %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real); - - return 0; -} -static int codegen_PCMPGTB(codeblock_t *block, uop_t *uop) -{ - int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg_a = HOST_REG_GET(uop->src_reg_a_real), src_reg_b = HOST_REG_GET(uop->src_reg_b_real); - int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size_a = IREG_GET_SIZE(uop->src_reg_a_real), src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); - - if (REG_IS_Q(dest_size) && REG_IS_Q(src_size_a) && REG_IS_Q(src_size_b)) - { - host_arm_VCGT_S8(block, dest_reg, src_reg_a, src_reg_b); - } - else - fatal("PCMPGTB %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real); - - return 0; -} -static int codegen_PCMPGTW(codeblock_t *block, uop_t *uop) -{ - int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg_a = HOST_REG_GET(uop->src_reg_a_real), src_reg_b = HOST_REG_GET(uop->src_reg_b_real); - int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size_a = IREG_GET_SIZE(uop->src_reg_a_real), src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); - - if (REG_IS_Q(dest_size) && REG_IS_Q(src_size_a) && REG_IS_Q(src_size_b)) - { - host_arm_VCGT_S16(block, dest_reg, src_reg_a, src_reg_b); - } - else - fatal("PCMPGTW %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real); - - return 0; -} -static int codegen_PCMPGTD(codeblock_t *block, uop_t *uop) -{ - int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg_a = HOST_REG_GET(uop->src_reg_a_real), src_reg_b = HOST_REG_GET(uop->src_reg_b_real); - int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size_a = IREG_GET_SIZE(uop->src_reg_a_real), src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); - - if (REG_IS_Q(dest_size) && REG_IS_Q(src_size_a) && REG_IS_Q(src_size_b)) - { - host_arm_VCGT_S32(block, dest_reg, src_reg_a, src_reg_b); - } - else - fatal("PCMPGTD %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real); - - return 0; -} - -static int codegen_PF2ID(codeblock_t *block, uop_t *uop) -{ - int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg_a = HOST_REG_GET(uop->src_reg_a_real); - int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size_a = IREG_GET_SIZE(uop->src_reg_a_real); - - if (REG_IS_Q(dest_size) && REG_IS_Q(src_size_a)) - { - host_arm_VCVT_S32_F32(block, dest_reg, src_reg_a); - } - else - fatal("PF2ID %02x %02x\n", uop->dest_reg_a_real); - - return 0; -} -static int codegen_PFADD(codeblock_t *block, uop_t *uop) -{ - int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg_a = HOST_REG_GET(uop->src_reg_a_real), src_reg_b = HOST_REG_GET(uop->src_reg_b_real); - int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size_a = IREG_GET_SIZE(uop->src_reg_a_real), src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); - - if (REG_IS_Q(dest_size) && REG_IS_Q(src_size_a) && REG_IS_Q(src_size_b)) - { - host_arm_VADD_F32(block, dest_reg, src_reg_a, src_reg_b); - } - else - fatal("PFADD %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real); - - return 0; -} -static int codegen_PFCMPEQ(codeblock_t *block, uop_t *uop) -{ - int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg_a = HOST_REG_GET(uop->src_reg_a_real), src_reg_b = HOST_REG_GET(uop->src_reg_b_real); - int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size_a = IREG_GET_SIZE(uop->src_reg_a_real), src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); - - if (REG_IS_Q(dest_size) && REG_IS_Q(src_size_a) && REG_IS_Q(src_size_b)) - { - host_arm_VCEQ_F32(block, dest_reg, src_reg_a, src_reg_b); - } - else - fatal("PFCMPEQ %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real); - - return 0; -} -static int codegen_PFCMPGE(codeblock_t *block, uop_t *uop) -{ - int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg_a = HOST_REG_GET(uop->src_reg_a_real), src_reg_b = HOST_REG_GET(uop->src_reg_b_real); - int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size_a = IREG_GET_SIZE(uop->src_reg_a_real), src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); - - if (REG_IS_Q(dest_size) && REG_IS_Q(src_size_a) && REG_IS_Q(src_size_b)) - { - host_arm_VCGE_F32(block, dest_reg, src_reg_a, src_reg_b); - } - else - fatal("PFCMPGE %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real); - - return 0; -} -static int codegen_PFCMPGT(codeblock_t *block, uop_t *uop) -{ - int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg_a = HOST_REG_GET(uop->src_reg_a_real), src_reg_b = HOST_REG_GET(uop->src_reg_b_real); - int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size_a = IREG_GET_SIZE(uop->src_reg_a_real), src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); - - if (REG_IS_Q(dest_size) && REG_IS_Q(src_size_a) && REG_IS_Q(src_size_b)) - { - host_arm_VCGT_F32(block, dest_reg, src_reg_a, src_reg_b); - } - else - fatal("PFCMPGT %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real); - - return 0; -} -static int codegen_PFMAX(codeblock_t *block, uop_t *uop) -{ - int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg_a = HOST_REG_GET(uop->src_reg_a_real), src_reg_b = HOST_REG_GET(uop->src_reg_b_real); - int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size_a = IREG_GET_SIZE(uop->src_reg_a_real), src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); - - if (REG_IS_Q(dest_size) && REG_IS_Q(src_size_a) && REG_IS_Q(src_size_b)) - { - host_arm_VMAX_F32(block, dest_reg, src_reg_a, src_reg_b); - } - else - fatal("PFMAX %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real); - - return 0; -} -static int codegen_PFMIN(codeblock_t *block, uop_t *uop) -{ - int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg_a = HOST_REG_GET(uop->src_reg_a_real), src_reg_b = HOST_REG_GET(uop->src_reg_b_real); - int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size_a = IREG_GET_SIZE(uop->src_reg_a_real), src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); - - if (REG_IS_Q(dest_size) && REG_IS_Q(src_size_a) && REG_IS_Q(src_size_b)) - { - host_arm_VMIN_F32(block, dest_reg, src_reg_a, src_reg_b); - } - else - fatal("PFMIN %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real); - - return 0; -} -static int codegen_PFMUL(codeblock_t *block, uop_t *uop) -{ - int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg_a = HOST_REG_GET(uop->src_reg_a_real), src_reg_b = HOST_REG_GET(uop->src_reg_b_real); - int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size_a = IREG_GET_SIZE(uop->src_reg_a_real), src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); - - if (REG_IS_Q(dest_size) && REG_IS_Q(src_size_a) && REG_IS_Q(src_size_b)) - { - host_arm_VMUL_F32(block, dest_reg, src_reg_a, src_reg_b); - } - else - fatal("PFMUL %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real); - - return 0; -} -static int codegen_PFRCP(codeblock_t *block, uop_t *uop) -{ - int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg_a = HOST_REG_GET(uop->src_reg_a_real); - int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size_a = IREG_GET_SIZE(uop->src_reg_a_real); - - if (REG_IS_Q(dest_size) && REG_IS_Q(src_size_a)) - { - /*TODO: This could be improved (use VRECPE/VRECPS)*/ - host_arm_VMOV_F32_ONE(block, REG_D_TEMP); - host_arm_VDIV_S(block, dest_reg, REG_D_TEMP, src_reg_a); - host_arm_VDUP_32(block, dest_reg, dest_reg, 0); - } - else - fatal("PFRCP %02x %02x\n", uop->dest_reg_a_real); - - return 0; -} -static int codegen_PFRSQRT(codeblock_t *block, uop_t *uop) -{ - int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg_a = HOST_REG_GET(uop->src_reg_a_real); - int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size_a = IREG_GET_SIZE(uop->src_reg_a_real); - - if (REG_IS_Q(dest_size) && REG_IS_Q(src_size_a)) - { - /*TODO: This could be improved (use VRSQRTE/VRSQRTS)*/ - host_arm_VSQRT_S(block, REG_D_TEMP, src_reg_a); - host_arm_VMOV_F32_ONE(block, REG_D_TEMP); - host_arm_VDIV_S(block, dest_reg, dest_reg, REG_D_TEMP); - host_arm_VDUP_32(block, dest_reg, dest_reg, 0); - } - else - fatal("PFRSQRT %02x %02x\n", uop->dest_reg_a_real); - - return 0; -} -static int codegen_PFSUB(codeblock_t *block, uop_t *uop) -{ - int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg_a = HOST_REG_GET(uop->src_reg_a_real), src_reg_b = HOST_REG_GET(uop->src_reg_b_real); - int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size_a = IREG_GET_SIZE(uop->src_reg_a_real), src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); - - if (REG_IS_Q(dest_size) && REG_IS_Q(src_size_a) && REG_IS_Q(src_size_b)) - { - host_arm_VSUB_F32(block, dest_reg, src_reg_a, src_reg_b); - } - else - fatal("PFSUB %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real); - - return 0; -} -static int codegen_PI2FD(codeblock_t *block, uop_t *uop) -{ - int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg_a = HOST_REG_GET(uop->src_reg_a_real); - int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size_a = IREG_GET_SIZE(uop->src_reg_a_real); - - if (REG_IS_Q(dest_size) && REG_IS_Q(src_size_a)) - { - host_arm_VCVT_F32_S32(block, dest_reg, src_reg_a); - } - else - fatal("PI2FD %02x %02x\n", uop->dest_reg_a_real); - - return 0; -} - -static int codegen_PMADDWD(codeblock_t *block, uop_t *uop) -{ - int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg_a = HOST_REG_GET(uop->src_reg_a_real), src_reg_b = HOST_REG_GET(uop->src_reg_b_real); - int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size_a = IREG_GET_SIZE(uop->src_reg_a_real), src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); - - if (REG_IS_Q(dest_size) && REG_IS_Q(src_size_a) && REG_IS_Q(src_size_b)) - { - host_arm_VMULL_S16(block, REG_Q_TEMP, src_reg_a, src_reg_b); - host_arm_VPADDL_Q_S32(block, REG_Q_TEMP, REG_Q_TEMP); - host_arm_VMOVN_I64(block, dest_reg, REG_Q_TEMP); - } - else - fatal("PMULHW %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real); - - return 0; -} -static int codegen_PMULHW(codeblock_t *block, uop_t *uop) -{ - int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg_a = HOST_REG_GET(uop->src_reg_a_real), src_reg_b = HOST_REG_GET(uop->src_reg_b_real); - int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size_a = IREG_GET_SIZE(uop->src_reg_a_real), src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); - - if (REG_IS_Q(dest_size) && REG_IS_Q(src_size_a) && REG_IS_Q(src_size_b)) - { - host_arm_VMULL_S16(block, REG_Q_TEMP, src_reg_a, src_reg_b); - host_arm_VSHRN_32(block, dest_reg, REG_Q_TEMP, 16); - } - else - fatal("PMULHW %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real); - - return 0; -} -static int codegen_PMULLW(codeblock_t *block, uop_t *uop) -{ - int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg_a = HOST_REG_GET(uop->src_reg_a_real), src_reg_b = HOST_REG_GET(uop->src_reg_b_real); - int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size_a = IREG_GET_SIZE(uop->src_reg_a_real), src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); - - if (REG_IS_Q(dest_size) && REG_IS_Q(src_size_a) && REG_IS_Q(src_size_b)) - { - host_arm_VMUL_S16(block, dest_reg, src_reg_a, src_reg_b); - } - else - fatal("PMULLW %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real); - - return 0; -} - -static int codegen_PSLLW_IMM(codeblock_t *block, uop_t *uop) -{ - int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg = HOST_REG_GET(uop->src_reg_a_real); - int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size = IREG_GET_SIZE(uop->src_reg_a_real); - - if (REG_IS_Q(dest_size) && REG_IS_Q(src_size)) - { - if (uop->imm_data == 0) - host_arm_VMOV_D_D(block, dest_reg, src_reg); - else if (uop->imm_data > 15) - host_arm_VEOR_D(block, dest_reg, dest_reg, dest_reg); - else - host_arm_VSHL_D_IMM_16(block, dest_reg, src_reg, uop->imm_data); - } - else - fatal("PSLLW_IMM %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real); - - return 0; -} -static int codegen_PSLLD_IMM(codeblock_t *block, uop_t *uop) -{ - int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg = HOST_REG_GET(uop->src_reg_a_real); - int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size = IREG_GET_SIZE(uop->src_reg_a_real); - - if (REG_IS_Q(dest_size) && REG_IS_Q(src_size)) - { - if (uop->imm_data == 0) - host_arm_VMOV_D_D(block, dest_reg, src_reg); - else if (uop->imm_data > 31) - host_arm_VEOR_D(block, dest_reg, dest_reg, dest_reg); - else - host_arm_VSHL_D_IMM_32(block, dest_reg, src_reg, uop->imm_data); - } - else - fatal("PSLLD_IMM %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real); - - return 0; -} -static int codegen_PSLLQ_IMM(codeblock_t *block, uop_t *uop) -{ - int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg = HOST_REG_GET(uop->src_reg_a_real); - int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size = IREG_GET_SIZE(uop->src_reg_a_real); - - if (REG_IS_Q(dest_size) && REG_IS_Q(src_size)) - { - if (uop->imm_data == 0) - host_arm_VMOV_D_D(block, dest_reg, src_reg); - else if (uop->imm_data > 63) - host_arm_VEOR_D(block, dest_reg, dest_reg, dest_reg); - else - host_arm_VSHL_D_IMM_64(block, dest_reg, src_reg, uop->imm_data); - } - else - fatal("PSLLQ_IMM %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real); - - return 0; -} -static int codegen_PSRAW_IMM(codeblock_t *block, uop_t *uop) -{ - int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg = HOST_REG_GET(uop->src_reg_a_real); - int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size = IREG_GET_SIZE(uop->src_reg_a_real); - - if (REG_IS_Q(dest_size) && REG_IS_Q(src_size)) - { - if (uop->imm_data == 0) - host_arm_VMOV_D_D(block, dest_reg, src_reg); - else if (uop->imm_data > 15) - host_arm_VSHR_D_S16(block, dest_reg, src_reg, 15); - else - host_arm_VSHR_D_S16(block, dest_reg, src_reg, uop->imm_data); - } - else - fatal("PSRAW_IMM %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real); - - return 0; -} -static int codegen_PSRAD_IMM(codeblock_t *block, uop_t *uop) -{ - int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg = HOST_REG_GET(uop->src_reg_a_real); - int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size = IREG_GET_SIZE(uop->src_reg_a_real); - - if (REG_IS_Q(dest_size) && REG_IS_Q(src_size)) - { - if (uop->imm_data == 0) - host_arm_VMOV_D_D(block, dest_reg, src_reg); - else if (uop->imm_data > 31) - host_arm_VSHR_D_S32(block, dest_reg, src_reg, 31); - else - host_arm_VSHR_D_S32(block, dest_reg, src_reg, uop->imm_data); - } - else - fatal("PSRAD_IMM %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real); - - return 0; -} -static int codegen_PSRAQ_IMM(codeblock_t *block, uop_t *uop) -{ - int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg = HOST_REG_GET(uop->src_reg_a_real); - int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size = IREG_GET_SIZE(uop->src_reg_a_real); - - if (REG_IS_Q(dest_size) && REG_IS_Q(src_size)) - { - if (uop->imm_data == 0) - host_arm_VMOV_D_D(block, dest_reg, src_reg); - else if (uop->imm_data > 63) - host_arm_VSHR_D_S64(block, dest_reg, src_reg, 63); - else - host_arm_VSHR_D_S64(block, dest_reg, src_reg, uop->imm_data); - } - else - fatal("PSRAQ_IMM %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real); - - return 0; -} -static int codegen_PSRLW_IMM(codeblock_t *block, uop_t *uop) -{ - int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg = HOST_REG_GET(uop->src_reg_a_real); - int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size = IREG_GET_SIZE(uop->src_reg_a_real); - - if (REG_IS_Q(dest_size) && REG_IS_Q(src_size)) - { - if (uop->imm_data == 0) - host_arm_VMOV_D_D(block, dest_reg, src_reg); - else if (uop->imm_data > 15) - host_arm_VEOR_D(block, dest_reg, dest_reg, dest_reg); - else - host_arm_VSHR_D_U16(block, dest_reg, src_reg, uop->imm_data); - } - else - fatal("PSRLW_IMM %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real); - - return 0; -} -static int codegen_PSRLD_IMM(codeblock_t *block, uop_t *uop) -{ - int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg = HOST_REG_GET(uop->src_reg_a_real); - int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size = IREG_GET_SIZE(uop->src_reg_a_real); - - if (REG_IS_Q(dest_size) && REG_IS_Q(src_size)) - { - if (uop->imm_data == 0) - host_arm_VMOV_D_D(block, dest_reg, src_reg); - else if (uop->imm_data > 31) - host_arm_VEOR_D(block, dest_reg, dest_reg, dest_reg); - else - host_arm_VSHR_D_U32(block, dest_reg, src_reg, uop->imm_data); - } - else - fatal("PSRLD_IMM %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real); - - return 0; -} -static int codegen_PSRLQ_IMM(codeblock_t *block, uop_t *uop) -{ - int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg = HOST_REG_GET(uop->src_reg_a_real); - int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size = IREG_GET_SIZE(uop->src_reg_a_real); - - if (REG_IS_Q(dest_size) && REG_IS_Q(src_size)) - { - if (uop->imm_data == 0) - host_arm_VMOV_D_D(block, dest_reg, src_reg); - else if (uop->imm_data > 63) - host_arm_VEOR_D(block, dest_reg, dest_reg, dest_reg); - else - host_arm_VSHR_D_U64(block, dest_reg, src_reg, uop->imm_data); - } - else - fatal("PSRLQ_IMM %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real); - - return 0; -} - -static int codegen_PSUBB(codeblock_t *block, uop_t *uop) -{ - int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg_a = HOST_REG_GET(uop->src_reg_a_real), src_reg_b = HOST_REG_GET(uop->src_reg_b_real); - int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size_a = IREG_GET_SIZE(uop->src_reg_a_real), src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); - - if (REG_IS_Q(dest_size) && REG_IS_Q(src_size_a) && REG_IS_Q(src_size_b)) - { - host_arm_VSUB_I8(block, dest_reg, src_reg_a, src_reg_b); - } - else - fatal("PSUBB %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real); - - return 0; -} -static int codegen_PSUBW(codeblock_t *block, uop_t *uop) -{ - int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg_a = HOST_REG_GET(uop->src_reg_a_real), src_reg_b = HOST_REG_GET(uop->src_reg_b_real); - int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size_a = IREG_GET_SIZE(uop->src_reg_a_real), src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); - - if (REG_IS_Q(dest_size) && REG_IS_Q(src_size_a) && REG_IS_Q(src_size_b)) - { - host_arm_VSUB_I16(block, dest_reg, src_reg_a, src_reg_b); - } - else - fatal("PSUBW %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real); - - return 0; -} -static int codegen_PSUBD(codeblock_t *block, uop_t *uop) -{ - int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg_a = HOST_REG_GET(uop->src_reg_a_real), src_reg_b = HOST_REG_GET(uop->src_reg_b_real); - int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size_a = IREG_GET_SIZE(uop->src_reg_a_real), src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); - - if (REG_IS_Q(dest_size) && REG_IS_Q(src_size_a) && REG_IS_Q(src_size_b)) - { - host_arm_VSUB_I32(block, dest_reg, src_reg_a, src_reg_b); - } - else - fatal("PSUBD %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real); - - return 0; -} -static int codegen_PSUBSB(codeblock_t *block, uop_t *uop) -{ - int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg_a = HOST_REG_GET(uop->src_reg_a_real), src_reg_b = HOST_REG_GET(uop->src_reg_b_real); - int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size_a = IREG_GET_SIZE(uop->src_reg_a_real), src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); - - if (REG_IS_Q(dest_size) && REG_IS_Q(src_size_a) && REG_IS_Q(src_size_b)) - { - host_arm_VQSUB_S8(block, dest_reg, src_reg_a, src_reg_b); - } - else - fatal("PSUBSB %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real); - - return 0; -} -static int codegen_PSUBSW(codeblock_t *block, uop_t *uop) -{ - int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg_a = HOST_REG_GET(uop->src_reg_a_real), src_reg_b = HOST_REG_GET(uop->src_reg_b_real); - int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size_a = IREG_GET_SIZE(uop->src_reg_a_real), src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); - - if (REG_IS_Q(dest_size) && REG_IS_Q(src_size_a) && REG_IS_Q(src_size_b)) - { - host_arm_VQSUB_S16(block, dest_reg, src_reg_a, src_reg_b); - } - else - fatal("PSUBSW %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real); - - return 0; -} -static int codegen_PSUBUSB(codeblock_t *block, uop_t *uop) -{ - int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg_a = HOST_REG_GET(uop->src_reg_a_real), src_reg_b = HOST_REG_GET(uop->src_reg_b_real); - int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size_a = IREG_GET_SIZE(uop->src_reg_a_real), src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); - - if (REG_IS_Q(dest_size) && REG_IS_Q(src_size_a) && REG_IS_Q(src_size_b)) - { - host_arm_VQSUB_U8(block, dest_reg, src_reg_a, src_reg_b); - } - else - fatal("PSUBUSB %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real); - - return 0; -} -static int codegen_PSUBUSW(codeblock_t *block, uop_t *uop) -{ - int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg_a = HOST_REG_GET(uop->src_reg_a_real), src_reg_b = HOST_REG_GET(uop->src_reg_b_real); - int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size_a = IREG_GET_SIZE(uop->src_reg_a_real), src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); - - if (REG_IS_Q(dest_size) && REG_IS_Q(src_size_a) && REG_IS_Q(src_size_b)) - { - host_arm_VQSUB_U16(block, dest_reg, src_reg_a, src_reg_b); - } - else - fatal("PSUBUSW %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real); - - return 0; -} - -static int codegen_PUNPCKHBW(codeblock_t *block, uop_t *uop) -{ - int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg_a = HOST_REG_GET(uop->src_reg_a_real), src_reg_b = HOST_REG_GET(uop->src_reg_b_real); - int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size_a = IREG_GET_SIZE(uop->src_reg_a_real), src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); - - if (REG_IS_Q(dest_size) && REG_IS_Q(src_size_a) && REG_IS_Q(src_size_b)) - { - host_arm_VMOV_D_D(block, REG_D_TEMP, src_reg_b); - if (dest_reg != src_reg_a) - host_arm_VMOV_D_D(block, dest_reg, src_reg_a); - host_arm_VZIP_D8(block, dest_reg, REG_D_TEMP); - host_arm_VMOV_D_D(block, dest_reg, REG_D_TEMP); - } - else - fatal("PUNPCKHBW %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real); - - return 0; -} -static int codegen_PUNPCKHWD(codeblock_t *block, uop_t *uop) -{ - int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg_a = HOST_REG_GET(uop->src_reg_a_real), src_reg_b = HOST_REG_GET(uop->src_reg_b_real); - int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size_a = IREG_GET_SIZE(uop->src_reg_a_real), src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); - - if (REG_IS_Q(dest_size) && REG_IS_Q(src_size_a) && REG_IS_Q(src_size_b)) - { - host_arm_VMOV_D_D(block, REG_D_TEMP, src_reg_b); - if (dest_reg != src_reg_a) - host_arm_VMOV_D_D(block, dest_reg, src_reg_a); - host_arm_VZIP_D16(block, dest_reg, REG_D_TEMP); - host_arm_VMOV_D_D(block, dest_reg, REG_D_TEMP); - } - else - fatal("PUNPCKHWD %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real); - - return 0; -} -static int codegen_PUNPCKHDQ(codeblock_t *block, uop_t *uop) -{ - int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg_a = HOST_REG_GET(uop->src_reg_a_real), src_reg_b = HOST_REG_GET(uop->src_reg_b_real); - int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size_a = IREG_GET_SIZE(uop->src_reg_a_real), src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); - - if (REG_IS_Q(dest_size) && REG_IS_Q(src_size_a) && REG_IS_Q(src_size_b)) - { - host_arm_VMOV_D_D(block, REG_D_TEMP, src_reg_b); - if (dest_reg != src_reg_a) - host_arm_VMOV_D_D(block, dest_reg, src_reg_a); - host_arm_VZIP_D32(block, dest_reg, REG_D_TEMP); - host_arm_VMOV_D_D(block, dest_reg, REG_D_TEMP); - } - else - fatal("PUNPCKHDQ %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real); - - return 0; -} -static int codegen_PUNPCKLBW(codeblock_t *block, uop_t *uop) -{ - int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg_a = HOST_REG_GET(uop->src_reg_a_real), src_reg_b = HOST_REG_GET(uop->src_reg_b_real); - int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size_a = IREG_GET_SIZE(uop->src_reg_a_real), src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); - - if (REG_IS_Q(dest_size) && REG_IS_Q(src_size_a) && REG_IS_Q(src_size_b)) - { - host_arm_VMOV_D_D(block, REG_D_TEMP, src_reg_b); - if (dest_reg != src_reg_a) - host_arm_VMOV_D_D(block, dest_reg, src_reg_a); - host_arm_VZIP_D8(block, dest_reg, REG_D_TEMP); - } - else - fatal("PUNPCKLBW %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real); - - return 0; -} -static int codegen_PUNPCKLWD(codeblock_t *block, uop_t *uop) -{ - int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg_a = HOST_REG_GET(uop->src_reg_a_real), src_reg_b = HOST_REG_GET(uop->src_reg_b_real); - int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size_a = IREG_GET_SIZE(uop->src_reg_a_real), src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); - - if (REG_IS_Q(dest_size) && REG_IS_Q(src_size_a) && REG_IS_Q(src_size_b)) - { - host_arm_VMOV_D_D(block, REG_D_TEMP, src_reg_b); - if (dest_reg != src_reg_a) - host_arm_VMOV_D_D(block, dest_reg, src_reg_a); - host_arm_VZIP_D16(block, dest_reg, REG_D_TEMP); - } - else - fatal("PUNPCKLWD %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real); - - return 0; -} -static int codegen_PUNPCKLDQ(codeblock_t *block, uop_t *uop) -{ - int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg_a = HOST_REG_GET(uop->src_reg_a_real), src_reg_b = HOST_REG_GET(uop->src_reg_b_real); - int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size_a = IREG_GET_SIZE(uop->src_reg_a_real), src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); - - if (REG_IS_Q(dest_size) && REG_IS_Q(src_size_a) && REG_IS_Q(src_size_b)) - { - host_arm_VMOV_D_D(block, REG_D_TEMP, src_reg_b); - if (dest_reg != src_reg_a) - host_arm_VMOV_D_D(block, dest_reg, src_reg_a); - host_arm_VZIP_D32(block, dest_reg, REG_D_TEMP); - } - else - fatal("PUNPCKLDQ %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real); - - return 0; -} - -static int codegen_ROL(codeblock_t *block, uop_t *uop) -{ - int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg = HOST_REG_GET(uop->src_reg_a_real), shift_reg = HOST_REG_GET(uop->src_reg_b_real); - int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size = IREG_GET_SIZE(uop->src_reg_a_real); - - if (REG_IS_L(dest_size) && REG_IS_L(src_size)) - { - host_arm_RSB_IMM(block, REG_TEMP2, shift_reg, 32); - host_arm_MOV_REG_ROR_REG(block, dest_reg, src_reg, REG_TEMP2); - } - else if (REG_IS_W(dest_size) && REG_IS_W(src_size)) - { - host_arm_UXTH(block, REG_TEMP, src_reg, 0); - host_arm_RSB_IMM(block, REG_TEMP2, shift_reg, 16); - host_arm_ORR_REG_LSL(block, REG_TEMP, REG_TEMP, REG_TEMP, 16); - host_arm_MOV_REG_ROR_REG(block, REG_TEMP, REG_TEMP, REG_TEMP2); - host_arm_BFI(block, dest_reg, REG_TEMP, 0, 16); - } - else if (REG_IS_B(dest_size) && REG_IS_B(src_size)) - { - host_arm_RSB_IMM(block, REG_TEMP2, shift_reg, 8); - host_arm_UXTB(block, REG_TEMP, src_reg, 0); - host_arm_AND_IMM(block, REG_TEMP2, REG_TEMP2, 7); - host_arm_ORR_REG_LSL(block, REG_TEMP, REG_TEMP, REG_TEMP, 8); - host_arm_MOV_REG_LSR_REG(block, REG_TEMP, REG_TEMP, REG_TEMP2); - host_arm_BFI(block, dest_reg, REG_TEMP, 0, 8); - } - else if (REG_IS_BH(dest_size) && REG_IS_BH(src_size)) - { - host_arm_RSB_IMM(block, REG_TEMP2, shift_reg, 8); - host_arm_UXTB(block, REG_TEMP, src_reg, 8); - host_arm_AND_IMM(block, REG_TEMP2, REG_TEMP2, 7); - host_arm_ORR_REG_LSL(block, REG_TEMP, REG_TEMP, REG_TEMP, 8); - host_arm_MOV_REG_LSR_REG(block, REG_TEMP, REG_TEMP, REG_TEMP2); - host_arm_BFI(block, dest_reg, REG_TEMP, 8, 8); - } - else - fatal("ROL %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real); - - return 0; -} -static int codegen_ROL_IMM(codeblock_t *block, uop_t *uop) -{ - int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg = HOST_REG_GET(uop->src_reg_a_real); - int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size = IREG_GET_SIZE(uop->src_reg_a_real); - - if (REG_IS_L(dest_size) && REG_IS_L(src_size)) - { - if (!(uop->imm_data & 31)) - { - if (src_reg != dest_reg) - host_arm_MOV_REG(block, dest_reg, src_reg); - } - else - { - host_arm_MOV_REG_ROR(block, dest_reg, src_reg, 32 - (uop->imm_data & 31)); - } - } - else if (REG_IS_W(dest_size) && REG_IS_W(src_size)) - { - if ((uop->imm_data & 15) == 0) - { - if (src_reg != dest_reg) - host_arm_BFI(block, dest_reg, src_reg, 0, 16); - } - else - { - host_arm_UXTH(block, REG_TEMP, src_reg, 0); - host_arm_ORR_REG_LSL(block, REG_TEMP, REG_TEMP, REG_TEMP, 16); - host_arm_MOV_REG_LSR(block, REG_TEMP, REG_TEMP, 16-(uop->imm_data & 15)); - host_arm_BFI(block, dest_reg, REG_TEMP, 0, 16); - } - } - else if (REG_IS_B(dest_size) && REG_IS_B(src_size)) - { - if ((uop->imm_data & 7) == 0) - { - if (src_reg != dest_reg) - host_arm_BFI(block, dest_reg, src_reg, 0, 8); - } - else - { - host_arm_UXTB(block, REG_TEMP, src_reg, 0); - host_arm_ORR_REG_LSL(block, REG_TEMP, REG_TEMP, REG_TEMP, 8); - host_arm_MOV_REG_LSR(block, REG_TEMP, REG_TEMP, 8-(uop->imm_data & 7)); - host_arm_BFI(block, dest_reg, REG_TEMP, 0, 8); - } - } - else if (REG_IS_BH(dest_size) && REG_IS_BH(src_size)) - { - if ((uop->imm_data & 7) == 0) - { - if (src_reg != dest_reg) - fatal("ROL_IMM %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real); - } - else - { - host_arm_UXTB(block, REG_TEMP, src_reg, 8); - host_arm_ORR_REG_LSL(block, REG_TEMP, REG_TEMP, REG_TEMP, 8); - host_arm_MOV_REG_LSR(block, REG_TEMP, REG_TEMP, 8-(uop->imm_data & 7)); - host_arm_BFI(block, dest_reg, REG_TEMP, 8, 8); - } - } - else + } else if (REG_IS_BH(dest_size) && REG_IS_BH(src_size)) { + if ((uop->imm_data & 7) == 0) { + if (src_reg != dest_reg) fatal("ROL_IMM %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real); + } else { + host_arm_UXTB(block, REG_TEMP, src_reg, 8); + host_arm_ORR_REG_LSL(block, REG_TEMP, REG_TEMP, REG_TEMP, 8); + host_arm_MOV_REG_LSR(block, REG_TEMP, REG_TEMP, 8 - (uop->imm_data & 7)); + host_arm_BFI(block, dest_reg, REG_TEMP, 8, 8); + } + } else + fatal("ROL_IMM %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real); - return 0; + return 0; } -static int codegen_ROR(codeblock_t *block, uop_t *uop) +static int +codegen_ROR(codeblock_t *block, uop_t *uop) { - int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg = HOST_REG_GET(uop->src_reg_a_real), shift_reg = HOST_REG_GET(uop->src_reg_b_real); - int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size = IREG_GET_SIZE(uop->src_reg_a_real); + int dest_reg = HOST_REG_GET(uop->dest_reg_a_real); + int src_reg = HOST_REG_GET(uop->src_reg_a_real); + int shift_reg = HOST_REG_GET(uop->src_reg_b_real); + int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real); + int src_size = IREG_GET_SIZE(uop->src_reg_a_real); - if (REG_IS_L(dest_size) && REG_IS_L(src_size)) - { - host_arm_MOV_REG_ROR_REG(block, dest_reg, src_reg, shift_reg); - } - else if (REG_IS_W(dest_size) && REG_IS_W(src_size)) - { - host_arm_UXTH(block, REG_TEMP, src_reg, 0); - host_arm_AND_IMM(block, REG_TEMP2, shift_reg, 15); - host_arm_ORR_REG_LSL(block, REG_TEMP, REG_TEMP, REG_TEMP, 16); - host_arm_MOV_REG_LSR_REG(block, REG_TEMP, REG_TEMP, REG_TEMP2); - host_arm_BFI(block, dest_reg, REG_TEMP, 0, 16); - } - else if (REG_IS_B(dest_size) && REG_IS_B(src_size)) - { - host_arm_UXTB(block, REG_TEMP, src_reg, 0); - host_arm_AND_IMM(block, REG_TEMP2, shift_reg, 7); - host_arm_ORR_REG_LSL(block, REG_TEMP, REG_TEMP, REG_TEMP, 8); - host_arm_MOV_REG_LSR_REG(block, REG_TEMP, REG_TEMP, REG_TEMP2); - host_arm_BFI(block, dest_reg, REG_TEMP, 0, 8); - } - else if (REG_IS_BH(dest_size) && REG_IS_BH(src_size)) - { - host_arm_UXTB(block, REG_TEMP, src_reg, 8); - host_arm_AND_IMM(block, REG_TEMP2, shift_reg, 7); - host_arm_ORR_REG_LSL(block, REG_TEMP, REG_TEMP, REG_TEMP, 8); - host_arm_MOV_REG_LSR_REG(block, REG_TEMP, REG_TEMP, REG_TEMP2); - host_arm_BFI(block, dest_reg, REG_TEMP, 8, 8); - } - else - fatal("ROR %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real); + if (REG_IS_L(dest_size) && REG_IS_L(src_size)) { + host_arm_MOV_REG_ROR_REG(block, dest_reg, src_reg, shift_reg); + } else if (REG_IS_W(dest_size) && REG_IS_W(src_size)) { + host_arm_UXTH(block, REG_TEMP, src_reg, 0); + host_arm_AND_IMM(block, REG_TEMP2, shift_reg, 15); + host_arm_ORR_REG_LSL(block, REG_TEMP, REG_TEMP, REG_TEMP, 16); + host_arm_MOV_REG_LSR_REG(block, REG_TEMP, REG_TEMP, REG_TEMP2); + host_arm_BFI(block, dest_reg, REG_TEMP, 0, 16); + } else if (REG_IS_B(dest_size) && REG_IS_B(src_size)) { + host_arm_UXTB(block, REG_TEMP, src_reg, 0); + host_arm_AND_IMM(block, REG_TEMP2, shift_reg, 7); + host_arm_ORR_REG_LSL(block, REG_TEMP, REG_TEMP, REG_TEMP, 8); + host_arm_MOV_REG_LSR_REG(block, REG_TEMP, REG_TEMP, REG_TEMP2); + host_arm_BFI(block, dest_reg, REG_TEMP, 0, 8); + } else if (REG_IS_BH(dest_size) && REG_IS_BH(src_size)) { + host_arm_UXTB(block, REG_TEMP, src_reg, 8); + host_arm_AND_IMM(block, REG_TEMP2, shift_reg, 7); + host_arm_ORR_REG_LSL(block, REG_TEMP, REG_TEMP, REG_TEMP, 8); + host_arm_MOV_REG_LSR_REG(block, REG_TEMP, REG_TEMP, REG_TEMP2); + host_arm_BFI(block, dest_reg, REG_TEMP, 8, 8); + } else + fatal("ROR %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real); - return 0; + return 0; } -static int codegen_ROR_IMM(codeblock_t *block, uop_t *uop) +static int +codegen_ROR_IMM(codeblock_t *block, uop_t *uop) { - int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg = HOST_REG_GET(uop->src_reg_a_real); - int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size = IREG_GET_SIZE(uop->src_reg_a_real); + int dest_reg = HOST_REG_GET(uop->dest_reg_a_real); + int src_reg = HOST_REG_GET(uop->src_reg_a_real); + int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real); + int src_size = IREG_GET_SIZE(uop->src_reg_a_real); - if (REG_IS_L(dest_size) && REG_IS_L(src_size)) - { - if (!(uop->imm_data & 31)) - { - if (src_reg != dest_reg) - host_arm_MOV_REG(block, dest_reg, src_reg); - } - else - { - host_arm_MOV_REG_ROR(block, dest_reg, src_reg, uop->imm_data & 31); - } + if (REG_IS_L(dest_size) && REG_IS_L(src_size)) { + if (!(uop->imm_data & 31)) { + if (src_reg != dest_reg) + host_arm_MOV_REG(block, dest_reg, src_reg); + } else { + host_arm_MOV_REG_ROR(block, dest_reg, src_reg, uop->imm_data & 31); } - else if (REG_IS_W(dest_size) && REG_IS_W(src_size)) - { - if ((uop->imm_data & 15) == 0) - { - if (src_reg != dest_reg) - fatal("ROR_IMM %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real); - } - else - { - host_arm_UXTH(block, REG_TEMP, src_reg, 0); - host_arm_ORR_REG_LSL(block, REG_TEMP, REG_TEMP, REG_TEMP, 16); - host_arm_MOV_REG_LSR(block, REG_TEMP, REG_TEMP, uop->imm_data & 15); - host_arm_BFI(block, dest_reg, REG_TEMP, 0, 16); - } - } - else if (REG_IS_B(dest_size) && REG_IS_B(src_size)) - { - if ((uop->imm_data & 7) == 0) - { - if (src_reg != dest_reg) - fatal("ROR_IMM %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real); - } - else - { - host_arm_UXTB(block, REG_TEMP, src_reg, 0); - host_arm_ORR_REG_LSL(block, REG_TEMP, REG_TEMP, REG_TEMP, 8); - host_arm_MOV_REG_LSR(block, REG_TEMP, REG_TEMP, uop->imm_data & 7); - host_arm_BFI(block, dest_reg, REG_TEMP, 0, 8); - } - } - else if (REG_IS_BH(dest_size) && REG_IS_BH(src_size)) - { - if ((uop->imm_data & 7) == 0) - { - if (src_reg != dest_reg) - fatal("ROR_IMM %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real); - } - else - { - host_arm_UXTB(block, REG_TEMP, src_reg, 8); - host_arm_ORR_REG_LSL(block, REG_TEMP, REG_TEMP, REG_TEMP, 8); - host_arm_MOV_REG_LSR(block, REG_TEMP, REG_TEMP, uop->imm_data & 7); - host_arm_BFI(block, dest_reg, REG_TEMP, 8, 8); - } - } - else + } else if (REG_IS_W(dest_size) && REG_IS_W(src_size)) { + if ((uop->imm_data & 15) == 0) { + if (src_reg != dest_reg) fatal("ROR_IMM %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real); + } else { + host_arm_UXTH(block, REG_TEMP, src_reg, 0); + host_arm_ORR_REG_LSL(block, REG_TEMP, REG_TEMP, REG_TEMP, 16); + host_arm_MOV_REG_LSR(block, REG_TEMP, REG_TEMP, uop->imm_data & 15); + host_arm_BFI(block, dest_reg, REG_TEMP, 0, 16); + } + } else if (REG_IS_B(dest_size) && REG_IS_B(src_size)) { + if ((uop->imm_data & 7) == 0) { + if (src_reg != dest_reg) + fatal("ROR_IMM %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real); + } else { + host_arm_UXTB(block, REG_TEMP, src_reg, 0); + host_arm_ORR_REG_LSL(block, REG_TEMP, REG_TEMP, REG_TEMP, 8); + host_arm_MOV_REG_LSR(block, REG_TEMP, REG_TEMP, uop->imm_data & 7); + host_arm_BFI(block, dest_reg, REG_TEMP, 0, 8); + } + } else if (REG_IS_BH(dest_size) && REG_IS_BH(src_size)) { + if ((uop->imm_data & 7) == 0) { + if (src_reg != dest_reg) + fatal("ROR_IMM %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real); + } else { + host_arm_UXTB(block, REG_TEMP, src_reg, 8); + host_arm_ORR_REG_LSL(block, REG_TEMP, REG_TEMP, REG_TEMP, 8); + host_arm_MOV_REG_LSR(block, REG_TEMP, REG_TEMP, uop->imm_data & 7); + host_arm_BFI(block, dest_reg, REG_TEMP, 8, 8); + } + } else + fatal("ROR_IMM %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real); - return 0; + return 0; } -static int codegen_SAR(codeblock_t *block, uop_t *uop) +static int +codegen_SAR(codeblock_t *block, uop_t *uop) { - int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg = HOST_REG_GET(uop->src_reg_a_real), shift_reg = HOST_REG_GET(uop->src_reg_b_real); - int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size = IREG_GET_SIZE(uop->src_reg_a_real); + int dest_reg = HOST_REG_GET(uop->dest_reg_a_real); + int src_reg = HOST_REG_GET(uop->src_reg_a_real); + int shift_reg = HOST_REG_GET(uop->src_reg_b_real); + int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real); + int src_size = IREG_GET_SIZE(uop->src_reg_a_real); - if (REG_IS_L(dest_size) && REG_IS_L(src_size)) - { - host_arm_MOV_REG_ASR_REG(block, dest_reg, src_reg, shift_reg); - } - else if (REG_IS_W(dest_size) && REG_IS_W(src_size)) - { - host_arm_MOV_REG_LSL(block, REG_TEMP, src_reg, 16); - host_arm_MOV_REG_ASR_REG(block, REG_TEMP, REG_TEMP, shift_reg); - host_arm_UXTH(block, REG_TEMP, REG_TEMP, 16); - host_arm_BFI(block, dest_reg, REG_TEMP, 0, 16); - } - else if (REG_IS_B(dest_size) && REG_IS_B(src_size)) - { - host_arm_MOV_REG_LSL(block, REG_TEMP, src_reg, 24); - host_arm_MOV_REG_ASR_REG(block, REG_TEMP, REG_TEMP, shift_reg); - host_arm_UXTB(block, REG_TEMP, REG_TEMP, 24); - host_arm_BFI(block, dest_reg, REG_TEMP, 0, 8); - } - else if (REG_IS_BH(dest_size) && REG_IS_BH(src_size)) - { - host_arm_MOV_REG_LSL(block, REG_TEMP, src_reg, 16); - host_arm_MOV_REG_ASR_REG(block, REG_TEMP, REG_TEMP, shift_reg); - host_arm_UXTB(block, REG_TEMP, REG_TEMP, 24); - host_arm_BFI(block, dest_reg, REG_TEMP, 8, 8); - } - else - fatal("SAR %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real); + if (REG_IS_L(dest_size) && REG_IS_L(src_size)) { + host_arm_MOV_REG_ASR_REG(block, dest_reg, src_reg, shift_reg); + } else if (REG_IS_W(dest_size) && REG_IS_W(src_size)) { + host_arm_MOV_REG_LSL(block, REG_TEMP, src_reg, 16); + host_arm_MOV_REG_ASR_REG(block, REG_TEMP, REG_TEMP, shift_reg); + host_arm_UXTH(block, REG_TEMP, REG_TEMP, 16); + host_arm_BFI(block, dest_reg, REG_TEMP, 0, 16); + } else if (REG_IS_B(dest_size) && REG_IS_B(src_size)) { + host_arm_MOV_REG_LSL(block, REG_TEMP, src_reg, 24); + host_arm_MOV_REG_ASR_REG(block, REG_TEMP, REG_TEMP, shift_reg); + host_arm_UXTB(block, REG_TEMP, REG_TEMP, 24); + host_arm_BFI(block, dest_reg, REG_TEMP, 0, 8); + } else if (REG_IS_BH(dest_size) && REG_IS_BH(src_size)) { + host_arm_MOV_REG_LSL(block, REG_TEMP, src_reg, 16); + host_arm_MOV_REG_ASR_REG(block, REG_TEMP, REG_TEMP, shift_reg); + host_arm_UXTB(block, REG_TEMP, REG_TEMP, 24); + host_arm_BFI(block, dest_reg, REG_TEMP, 8, 8); + } else + fatal("SAR %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real); - return 0; + return 0; } -static int codegen_SAR_IMM(codeblock_t *block, uop_t *uop) +static int +codegen_SAR_IMM(codeblock_t *block, uop_t *uop) { - int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg = HOST_REG_GET(uop->src_reg_a_real); - int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size = IREG_GET_SIZE(uop->src_reg_a_real); + int dest_reg = HOST_REG_GET(uop->dest_reg_a_real); + int src_reg = HOST_REG_GET(uop->src_reg_a_real); + int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real); + int src_size = IREG_GET_SIZE(uop->src_reg_a_real); - if (REG_IS_L(dest_size) && REG_IS_L(src_size)) - { - host_arm_MOV_REG_ASR(block, dest_reg, src_reg, uop->imm_data); - } - else if (REG_IS_W(dest_size) && REG_IS_W(src_size)) - { - host_arm_MOV_REG_LSL(block, REG_TEMP, src_reg, 16); - host_arm_MOV_REG_ASR(block, REG_TEMP, REG_TEMP, uop->imm_data); - host_arm_UXTH(block, REG_TEMP, REG_TEMP, 16); - host_arm_BFI(block, dest_reg, REG_TEMP, 0, 16); - } - else if (REG_IS_B(dest_size) && REG_IS_B(src_size)) - { - host_arm_MOV_REG_LSL(block, REG_TEMP, src_reg, 24); - host_arm_MOV_REG_ASR(block, REG_TEMP, REG_TEMP, uop->imm_data); - host_arm_UXTB(block, REG_TEMP, REG_TEMP, 24); - host_arm_BFI(block, dest_reg, REG_TEMP, 0, 8); - } - else if (REG_IS_BH(dest_size) && REG_IS_BH(src_size)) - { - host_arm_MOV_REG_LSL(block, REG_TEMP, src_reg, 16); - host_arm_MOV_REG_ASR(block, REG_TEMP, REG_TEMP, uop->imm_data); - host_arm_UXTB(block, REG_TEMP, REG_TEMP, 24); - host_arm_BFI(block, dest_reg, REG_TEMP, 8, 8); - } - else - fatal("SAR_IMM %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real); + if (REG_IS_L(dest_size) && REG_IS_L(src_size)) { + host_arm_MOV_REG_ASR(block, dest_reg, src_reg, uop->imm_data); + } else if (REG_IS_W(dest_size) && REG_IS_W(src_size)) { + host_arm_MOV_REG_LSL(block, REG_TEMP, src_reg, 16); + host_arm_MOV_REG_ASR(block, REG_TEMP, REG_TEMP, uop->imm_data); + host_arm_UXTH(block, REG_TEMP, REG_TEMP, 16); + host_arm_BFI(block, dest_reg, REG_TEMP, 0, 16); + } else if (REG_IS_B(dest_size) && REG_IS_B(src_size)) { + host_arm_MOV_REG_LSL(block, REG_TEMP, src_reg, 24); + host_arm_MOV_REG_ASR(block, REG_TEMP, REG_TEMP, uop->imm_data); + host_arm_UXTB(block, REG_TEMP, REG_TEMP, 24); + host_arm_BFI(block, dest_reg, REG_TEMP, 0, 8); + } else if (REG_IS_BH(dest_size) && REG_IS_BH(src_size)) { + host_arm_MOV_REG_LSL(block, REG_TEMP, src_reg, 16); + host_arm_MOV_REG_ASR(block, REG_TEMP, REG_TEMP, uop->imm_data); + host_arm_UXTB(block, REG_TEMP, REG_TEMP, 24); + host_arm_BFI(block, dest_reg, REG_TEMP, 8, 8); + } else + fatal("SAR_IMM %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real); - return 0; + return 0; } -static int codegen_SHL(codeblock_t *block, uop_t *uop) +static int +codegen_SHL(codeblock_t *block, uop_t *uop) { - int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg = HOST_REG_GET(uop->src_reg_a_real), shift_reg = HOST_REG_GET(uop->src_reg_b_real); - int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size = IREG_GET_SIZE(uop->src_reg_a_real); + int dest_reg = HOST_REG_GET(uop->dest_reg_a_real); + int src_reg = HOST_REG_GET(uop->src_reg_a_real); + int shift_reg = HOST_REG_GET(uop->src_reg_b_real); + int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real); + int src_size = IREG_GET_SIZE(uop->src_reg_a_real); - if (REG_IS_L(dest_size) && REG_IS_L(src_size)) - { - host_arm_MOV_REG_LSL_REG(block, dest_reg, src_reg, shift_reg); - } - else if (REG_IS_W(dest_size) && REG_IS_W(src_size)) - { - host_arm_MOV_REG_LSL_REG(block, REG_TEMP, src_reg, shift_reg); - host_arm_BFI(block, dest_reg, REG_TEMP, 0, 16); - } - else if (REG_IS_B(dest_size) && REG_IS_B(src_size)) - { - host_arm_MOV_REG_LSL_REG(block, REG_TEMP, src_reg, shift_reg); - host_arm_BFI(block, dest_reg, REG_TEMP, 0, 8); - } - else if (REG_IS_BH(dest_size) && REG_IS_BH(src_size)) - { - host_arm_UXTB(block, REG_TEMP, src_reg, 8); - host_arm_MOV_REG_LSL_REG(block, REG_TEMP, REG_TEMP, shift_reg); - host_arm_BFI(block, dest_reg, REG_TEMP, 8, 8); - } - else - fatal("SHL %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real); + if (REG_IS_L(dest_size) && REG_IS_L(src_size)) { + host_arm_MOV_REG_LSL_REG(block, dest_reg, src_reg, shift_reg); + } else if (REG_IS_W(dest_size) && REG_IS_W(src_size)) { + host_arm_MOV_REG_LSL_REG(block, REG_TEMP, src_reg, shift_reg); + host_arm_BFI(block, dest_reg, REG_TEMP, 0, 16); + } else if (REG_IS_B(dest_size) && REG_IS_B(src_size)) { + host_arm_MOV_REG_LSL_REG(block, REG_TEMP, src_reg, shift_reg); + host_arm_BFI(block, dest_reg, REG_TEMP, 0, 8); + } else if (REG_IS_BH(dest_size) && REG_IS_BH(src_size)) { + host_arm_UXTB(block, REG_TEMP, src_reg, 8); + host_arm_MOV_REG_LSL_REG(block, REG_TEMP, REG_TEMP, shift_reg); + host_arm_BFI(block, dest_reg, REG_TEMP, 8, 8); + } else + fatal("SHL %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real); - return 0; + return 0; } -static int codegen_SHL_IMM(codeblock_t *block, uop_t *uop) +static int +codegen_SHL_IMM(codeblock_t *block, uop_t *uop) { - int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg = HOST_REG_GET(uop->src_reg_a_real); - int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size = IREG_GET_SIZE(uop->src_reg_a_real); + int dest_reg = HOST_REG_GET(uop->dest_reg_a_real); + int src_reg = HOST_REG_GET(uop->src_reg_a_real); + int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real); + int src_size = IREG_GET_SIZE(uop->src_reg_a_real); - if (REG_IS_L(dest_size) && REG_IS_L(src_size)) - { - host_arm_MOV_REG_LSL(block, dest_reg, src_reg, uop->imm_data); - } - else if (REG_IS_W(dest_size) && REG_IS_W(src_size)) - { - host_arm_MOV_REG_LSL(block, REG_TEMP, src_reg, uop->imm_data); - host_arm_BFI(block, dest_reg, REG_TEMP, 0, 16); - } - else if (REG_IS_B(dest_size) && REG_IS_B(src_size)) - { - host_arm_MOV_REG_LSL(block, REG_TEMP, src_reg, uop->imm_data); - host_arm_BFI(block, dest_reg, REG_TEMP, 0, 8); - } - else if (REG_IS_BH(dest_size) && REG_IS_BH(src_size)) - { - host_arm_UXTB(block, REG_TEMP, src_reg, 8); - host_arm_MOV_REG_LSL(block, REG_TEMP, REG_TEMP, uop->imm_data); - host_arm_BFI(block, dest_reg, REG_TEMP, 8, 8); - } - else - fatal("SHL_IMM %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real); + if (REG_IS_L(dest_size) && REG_IS_L(src_size)) { + host_arm_MOV_REG_LSL(block, dest_reg, src_reg, uop->imm_data); + } else if (REG_IS_W(dest_size) && REG_IS_W(src_size)) { + host_arm_MOV_REG_LSL(block, REG_TEMP, src_reg, uop->imm_data); + host_arm_BFI(block, dest_reg, REG_TEMP, 0, 16); + } else if (REG_IS_B(dest_size) && REG_IS_B(src_size)) { + host_arm_MOV_REG_LSL(block, REG_TEMP, src_reg, uop->imm_data); + host_arm_BFI(block, dest_reg, REG_TEMP, 0, 8); + } else if (REG_IS_BH(dest_size) && REG_IS_BH(src_size)) { + host_arm_UXTB(block, REG_TEMP, src_reg, 8); + host_arm_MOV_REG_LSL(block, REG_TEMP, REG_TEMP, uop->imm_data); + host_arm_BFI(block, dest_reg, REG_TEMP, 8, 8); + } else + fatal("SHL_IMM %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real); - return 0; + return 0; } -static int codegen_SHR(codeblock_t *block, uop_t *uop) +static int +codegen_SHR(codeblock_t *block, uop_t *uop) { - int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg = HOST_REG_GET(uop->src_reg_a_real), shift_reg = HOST_REG_GET(uop->src_reg_b_real); - int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size = IREG_GET_SIZE(uop->src_reg_a_real); + int dest_reg = HOST_REG_GET(uop->dest_reg_a_real); + int src_reg = HOST_REG_GET(uop->src_reg_a_real); + int shift_reg = HOST_REG_GET(uop->src_reg_b_real); + int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real); + int src_size = IREG_GET_SIZE(uop->src_reg_a_real); - if (REG_IS_L(dest_size) && REG_IS_L(src_size)) - { - host_arm_MOV_REG_LSR_REG(block, dest_reg, src_reg, shift_reg); - } - else if (REG_IS_W(dest_size) && REG_IS_W(src_size)) - { - host_arm_UXTH(block, REG_TEMP, src_reg, 0); - host_arm_MOV_REG_LSR_REG(block, REG_TEMP, REG_TEMP, shift_reg); - host_arm_BFI(block, dest_reg, REG_TEMP, 0, 16); - } - else if (REG_IS_B(dest_size) && REG_IS_B(src_size)) - { - host_arm_UXTB(block, REG_TEMP, src_reg, 0); - host_arm_MOV_REG_LSR_REG(block, REG_TEMP, REG_TEMP, shift_reg); - host_arm_BFI(block, dest_reg, REG_TEMP, 0, 8); - } - else if (REG_IS_BH(dest_size) && REG_IS_BH(src_size)) - { - host_arm_UXTB(block, REG_TEMP, src_reg, 8); - host_arm_MOV_REG_LSR_REG(block, REG_TEMP, REG_TEMP, shift_reg); - host_arm_BFI(block, dest_reg, REG_TEMP, 8, 8); - } - else - fatal("SHR %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real); + if (REG_IS_L(dest_size) && REG_IS_L(src_size)) { + host_arm_MOV_REG_LSR_REG(block, dest_reg, src_reg, shift_reg); + } else if (REG_IS_W(dest_size) && REG_IS_W(src_size)) { + host_arm_UXTH(block, REG_TEMP, src_reg, 0); + host_arm_MOV_REG_LSR_REG(block, REG_TEMP, REG_TEMP, shift_reg); + host_arm_BFI(block, dest_reg, REG_TEMP, 0, 16); + } else if (REG_IS_B(dest_size) && REG_IS_B(src_size)) { + host_arm_UXTB(block, REG_TEMP, src_reg, 0); + host_arm_MOV_REG_LSR_REG(block, REG_TEMP, REG_TEMP, shift_reg); + host_arm_BFI(block, dest_reg, REG_TEMP, 0, 8); + } else if (REG_IS_BH(dest_size) && REG_IS_BH(src_size)) { + host_arm_UXTB(block, REG_TEMP, src_reg, 8); + host_arm_MOV_REG_LSR_REG(block, REG_TEMP, REG_TEMP, shift_reg); + host_arm_BFI(block, dest_reg, REG_TEMP, 8, 8); + } else + fatal("SHR %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real); - return 0; + return 0; } -static int codegen_SHR_IMM(codeblock_t *block, uop_t *uop) +static int +codegen_SHR_IMM(codeblock_t *block, uop_t *uop) { - int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg = HOST_REG_GET(uop->src_reg_a_real); - int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size = IREG_GET_SIZE(uop->src_reg_a_real); + int dest_reg = HOST_REG_GET(uop->dest_reg_a_real); + int src_reg = HOST_REG_GET(uop->src_reg_a_real); + int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real); + int src_size = IREG_GET_SIZE(uop->src_reg_a_real); - if (REG_IS_L(dest_size) && REG_IS_L(src_size)) - { - host_arm_MOV_REG_LSR(block, dest_reg, src_reg, uop->imm_data); - } - else if (REG_IS_W(dest_size) && REG_IS_W(src_size)) - { - host_arm_UXTH(block, REG_TEMP, src_reg, 0); - host_arm_MOV_REG_LSR(block, REG_TEMP, REG_TEMP, uop->imm_data); - host_arm_BFI(block, dest_reg, REG_TEMP, 0, 16); - } - else if (REG_IS_B(dest_size) && REG_IS_B(src_size)) - { - host_arm_UXTB(block, REG_TEMP, src_reg, 0); - host_arm_MOV_REG_LSR(block, REG_TEMP, REG_TEMP, uop->imm_data); - host_arm_BFI(block, dest_reg, REG_TEMP, 0, 8); - } - else if (REG_IS_BH(dest_size) && REG_IS_BH(src_size)) - { - host_arm_UXTB(block, REG_TEMP, src_reg, 8); - host_arm_MOV_REG_LSR(block, REG_TEMP, REG_TEMP, uop->imm_data); - host_arm_BFI(block, dest_reg, REG_TEMP, 8, 8); - } - else - fatal("SHR_IMM %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real); + if (REG_IS_L(dest_size) && REG_IS_L(src_size)) { + host_arm_MOV_REG_LSR(block, dest_reg, src_reg, uop->imm_data); + } else if (REG_IS_W(dest_size) && REG_IS_W(src_size)) { + host_arm_UXTH(block, REG_TEMP, src_reg, 0); + host_arm_MOV_REG_LSR(block, REG_TEMP, REG_TEMP, uop->imm_data); + host_arm_BFI(block, dest_reg, REG_TEMP, 0, 16); + } else if (REG_IS_B(dest_size) && REG_IS_B(src_size)) { + host_arm_UXTB(block, REG_TEMP, src_reg, 0); + host_arm_MOV_REG_LSR(block, REG_TEMP, REG_TEMP, uop->imm_data); + host_arm_BFI(block, dest_reg, REG_TEMP, 0, 8); + } else if (REG_IS_BH(dest_size) && REG_IS_BH(src_size)) { + host_arm_UXTB(block, REG_TEMP, src_reg, 8); + host_arm_MOV_REG_LSR(block, REG_TEMP, REG_TEMP, uop->imm_data); + host_arm_BFI(block, dest_reg, REG_TEMP, 8, 8); + } else + fatal("SHR_IMM %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real); - return 0; + return 0; } -static int codegen_STORE_PTR_IMM(codeblock_t *block, uop_t *uop) +static int +codegen_STORE_PTR_IMM(codeblock_t *block, uop_t *uop) { - host_arm_MOV_IMM(block, REG_R0, uop->imm_data); + host_arm_MOV_IMM(block, REG_R0, uop->imm_data); - if (in_range(uop->p, &cpu_state)) - host_arm_STR_IMM(block, REG_R0, REG_CPUSTATE, (uintptr_t)uop->p - (uintptr_t)&cpu_state); - else - fatal("codegen_STORE_PTR_IMM - not in range\n"); + if (in_range(uop->p, &cpu_state)) + host_arm_STR_IMM(block, REG_R0, REG_CPUSTATE, (uintptr_t) uop->p - (uintptr_t) &cpu_state); + else + fatal("codegen_STORE_PTR_IMM - not in range\n"); - return 0; + return 0; } -static int codegen_STORE_PTR_IMM_8(codeblock_t *block, uop_t *uop) +static int +codegen_STORE_PTR_IMM_8(codeblock_t *block, uop_t *uop) { - host_arm_MOV_IMM(block, REG_R0, uop->imm_data); - if (in_range(uop->p, &cpu_state)) - host_arm_STRB_IMM(block, REG_R0, REG_CPUSTATE, (uintptr_t)uop->p - (uintptr_t)&cpu_state); - else - fatal("codegen_STORE_PTR_IMM - not in range\n"); + host_arm_MOV_IMM(block, REG_R0, uop->imm_data); + if (in_range(uop->p, &cpu_state)) + host_arm_STRB_IMM(block, REG_R0, REG_CPUSTATE, (uintptr_t) uop->p - (uintptr_t) &cpu_state); + else + fatal("codegen_STORE_PTR_IMM - not in range\n"); - return 0; + return 0; } -static int codegen_SUB(codeblock_t *block, uop_t *uop) +static int +codegen_SUB(codeblock_t *block, uop_t *uop) { - int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg_a = HOST_REG_GET(uop->src_reg_a_real), src_reg_b = HOST_REG_GET(uop->src_reg_b_real); - int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size_a = IREG_GET_SIZE(uop->src_reg_a_real), src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); + int dest_reg = HOST_REG_GET(uop->dest_reg_a_real); + int src_reg_a = HOST_REG_GET(uop->src_reg_a_real); + int src_reg_b = HOST_REG_GET(uop->src_reg_b_real); + int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real); + int src_size_a = IREG_GET_SIZE(uop->src_reg_a_real); + int src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); - if (REG_IS_L(dest_size) && REG_IS_L(src_size_a) && REG_IS_L(src_size_b)) - { - host_arm_SUB_REG_LSL(block, dest_reg, src_reg_a, src_reg_b, 0); - } - else if (REG_IS_W(dest_size) && REG_IS_W(src_size_a) && REG_IS_W(src_size_b)) - { - host_arm_SUB_REG_LSL(block, REG_TEMP, src_reg_a, src_reg_b, 0); - host_arm_BFI(block, dest_reg, REG_TEMP, 0, 16); - } - else if (REG_IS_B(dest_size) && REG_IS_B(src_size_a) && REG_IS_B(src_size_b)) - { - host_arm_SUB_REG_LSL(block, REG_TEMP, src_reg_a, src_reg_b, 0); - host_arm_BFI(block, dest_reg, REG_TEMP, 0, 8); - } - else if (REG_IS_B(dest_size) && REG_IS_B(src_size_a) && REG_IS_BH(src_size_b)) - { - host_arm_SUB_REG_LSR(block, REG_TEMP, src_reg_a, src_reg_b, 8); - host_arm_BFI(block, dest_reg, REG_TEMP, 0, 8); - } - else if (REG_IS_B(dest_size) && REG_IS_BH(src_size_a) && REG_IS_B(src_size_b)) - { - host_arm_RSB_REG_LSR(block, REG_TEMP, src_reg_b, src_reg_a, 8); - host_arm_BFI(block, dest_reg, REG_TEMP, 0, 8); - } - else if (REG_IS_B(dest_size) && REG_IS_BH(src_size_a) && REG_IS_BH(src_size_b)) - { - host_arm_SUB_REG_LSL(block, REG_TEMP, src_reg_a, src_reg_b, 0); - host_arm_MOV_REG_LSR(block, REG_TEMP, REG_TEMP, 8); - host_arm_BFI(block, dest_reg, REG_TEMP, 0, 8); - } - else if (REG_IS_BH(dest_size) && REG_IS_BH(src_size_a) && REG_IS_B(src_size_b)) - { - host_arm_RSB_REG_LSR(block, REG_TEMP, src_reg_b, src_reg_a, 8); - host_arm_BFI(block, dest_reg, REG_TEMP, 8, 8); - } - else if (REG_IS_BH(dest_size) && REG_IS_BH(src_size_a) && REG_IS_BH(src_size_b)) - { - host_arm_MOV_REG_LSR(block, REG_TEMP, src_reg_a, 8); - host_arm_SUB_REG_LSR(block, REG_TEMP, REG_TEMP, src_reg_b, 8); - host_arm_BFI(block, dest_reg, REG_TEMP, 8, 8); - } - else - fatal("SUB %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real); + if (REG_IS_L(dest_size) && REG_IS_L(src_size_a) && REG_IS_L(src_size_b)) { + host_arm_SUB_REG_LSL(block, dest_reg, src_reg_a, src_reg_b, 0); + } else if (REG_IS_W(dest_size) && REG_IS_W(src_size_a) && REG_IS_W(src_size_b)) { + host_arm_SUB_REG_LSL(block, REG_TEMP, src_reg_a, src_reg_b, 0); + host_arm_BFI(block, dest_reg, REG_TEMP, 0, 16); + } else if (REG_IS_B(dest_size) && REG_IS_B(src_size_a) && REG_IS_B(src_size_b)) { + host_arm_SUB_REG_LSL(block, REG_TEMP, src_reg_a, src_reg_b, 0); + host_arm_BFI(block, dest_reg, REG_TEMP, 0, 8); + } else if (REG_IS_B(dest_size) && REG_IS_B(src_size_a) && REG_IS_BH(src_size_b)) { + host_arm_SUB_REG_LSR(block, REG_TEMP, src_reg_a, src_reg_b, 8); + host_arm_BFI(block, dest_reg, REG_TEMP, 0, 8); + } else if (REG_IS_B(dest_size) && REG_IS_BH(src_size_a) && REG_IS_B(src_size_b)) { + host_arm_RSB_REG_LSR(block, REG_TEMP, src_reg_b, src_reg_a, 8); + host_arm_BFI(block, dest_reg, REG_TEMP, 0, 8); + } else if (REG_IS_B(dest_size) && REG_IS_BH(src_size_a) && REG_IS_BH(src_size_b)) { + host_arm_SUB_REG_LSL(block, REG_TEMP, src_reg_a, src_reg_b, 0); + host_arm_MOV_REG_LSR(block, REG_TEMP, REG_TEMP, 8); + host_arm_BFI(block, dest_reg, REG_TEMP, 0, 8); + } else if (REG_IS_BH(dest_size) && REG_IS_BH(src_size_a) && REG_IS_B(src_size_b)) { + host_arm_RSB_REG_LSR(block, REG_TEMP, src_reg_b, src_reg_a, 8); + host_arm_BFI(block, dest_reg, REG_TEMP, 8, 8); + } else if (REG_IS_BH(dest_size) && REG_IS_BH(src_size_a) && REG_IS_BH(src_size_b)) { + host_arm_MOV_REG_LSR(block, REG_TEMP, src_reg_a, 8); + host_arm_SUB_REG_LSR(block, REG_TEMP, REG_TEMP, src_reg_b, 8); + host_arm_BFI(block, dest_reg, REG_TEMP, 8, 8); + } else + fatal("SUB %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real); + return 0; + +# if 0 + host_arm_SUB_REG_LSL(block, uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real, 0); return 0; - -// host_arm_SUB_REG_LSL(block, uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real, 0); -// return 0; +# endif } -static int codegen_SUB_IMM(codeblock_t *block, uop_t *uop) +static int +codegen_SUB_IMM(codeblock_t *block, uop_t *uop) { - int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg = HOST_REG_GET(uop->src_reg_a_real); - int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size = IREG_GET_SIZE(uop->src_reg_a_real); + int dest_reg = HOST_REG_GET(uop->dest_reg_a_real); + int src_reg = HOST_REG_GET(uop->src_reg_a_real); + int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real); + int src_size = IREG_GET_SIZE(uop->src_reg_a_real); - if (REG_IS_L(dest_size) && REG_IS_L(src_size)) - { - host_arm_SUB_IMM(block, dest_reg, src_reg, uop->imm_data); - } - else if (REG_IS_W(dest_size) && REG_IS_W(src_size)) - { - host_arm_SUB_IMM(block, REG_TEMP, src_reg, uop->imm_data); - host_arm_BFI(block, dest_reg, REG_TEMP, 0, 16); - } - else if (REG_IS_B(dest_size) && REG_IS_B(src_size)) - { - host_arm_SUB_IMM(block, REG_TEMP, src_reg, uop->imm_data); - host_arm_BFI(block, dest_reg, REG_TEMP, 0, 8); - } - else if (REG_IS_B(dest_size) && REG_IS_BH(src_size)) - { - host_arm_SUB_IMM(block, REG_TEMP, src_reg, uop->imm_data << 8); - host_arm_MOV_REG_LSR(block, REG_TEMP, REG_TEMP, 8); - host_arm_BFI(block, dest_reg, REG_TEMP, 0, 8); - } - else if (REG_IS_BH(dest_size) && REG_IS_BH(src_size)) - { - host_arm_SUB_IMM(block, REG_TEMP, src_reg, uop->imm_data << 8); - host_arm_MOV_REG_LSR(block, REG_TEMP, REG_TEMP, 8); - host_arm_BFI(block, dest_reg, REG_TEMP, 8, 8); - } - else - fatal("SUB_IMM %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real); + if (REG_IS_L(dest_size) && REG_IS_L(src_size)) { + host_arm_SUB_IMM(block, dest_reg, src_reg, uop->imm_data); + } else if (REG_IS_W(dest_size) && REG_IS_W(src_size)) { + host_arm_SUB_IMM(block, REG_TEMP, src_reg, uop->imm_data); + host_arm_BFI(block, dest_reg, REG_TEMP, 0, 16); + } else if (REG_IS_B(dest_size) && REG_IS_B(src_size)) { + host_arm_SUB_IMM(block, REG_TEMP, src_reg, uop->imm_data); + host_arm_BFI(block, dest_reg, REG_TEMP, 0, 8); + } else if (REG_IS_B(dest_size) && REG_IS_BH(src_size)) { + host_arm_SUB_IMM(block, REG_TEMP, src_reg, uop->imm_data << 8); + host_arm_MOV_REG_LSR(block, REG_TEMP, REG_TEMP, 8); + host_arm_BFI(block, dest_reg, REG_TEMP, 0, 8); + } else if (REG_IS_BH(dest_size) && REG_IS_BH(src_size)) { + host_arm_SUB_IMM(block, REG_TEMP, src_reg, uop->imm_data << 8); + host_arm_MOV_REG_LSR(block, REG_TEMP, REG_TEMP, 8); + host_arm_BFI(block, dest_reg, REG_TEMP, 8, 8); + } else + fatal("SUB_IMM %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real); - return 0; + return 0; } -static int codegen_TEST_JNS_DEST(codeblock_t *block, uop_t *uop) +static int +codegen_TEST_JNS_DEST(codeblock_t *block, uop_t *uop) { - int src_reg = HOST_REG_GET(uop->src_reg_a_real); - int src_size = IREG_GET_SIZE(uop->src_reg_a_real); + int src_reg = HOST_REG_GET(uop->src_reg_a_real); + int src_size = IREG_GET_SIZE(uop->src_reg_a_real); - if (REG_IS_L(src_size)) - { - host_arm_TST_IMM(block, src_reg, 1 << 31); - } - else if (REG_IS_W(src_size)) - { - host_arm_TST_IMM(block, src_reg, 1 << 15); - } - else if (REG_IS_B(src_size)) - { - host_arm_TST_IMM(block, src_reg, 1 << 7); - } - else - fatal("TEST_JNS_DEST %02x\n", uop->src_reg_a_real); + if (REG_IS_L(src_size)) { + host_arm_TST_IMM(block, src_reg, 1 << 31); + } else if (REG_IS_W(src_size)) { + host_arm_TST_IMM(block, src_reg, 1 << 15); + } else if (REG_IS_B(src_size)) { + host_arm_TST_IMM(block, src_reg, 1 << 7); + } else + fatal("TEST_JNS_DEST %02x\n", uop->src_reg_a_real); - uop->p = host_arm_BEQ_(block); + uop->p = host_arm_BEQ_(block); - return 0; + return 0; } -static int codegen_TEST_JS_DEST(codeblock_t *block, uop_t *uop) +static int +codegen_TEST_JS_DEST(codeblock_t *block, uop_t *uop) { - int src_reg = HOST_REG_GET(uop->src_reg_a_real); - int src_size = IREG_GET_SIZE(uop->src_reg_a_real); + int src_reg = HOST_REG_GET(uop->src_reg_a_real); + int src_size = IREG_GET_SIZE(uop->src_reg_a_real); - if (REG_IS_L(src_size)) - { - host_arm_TST_IMM(block, src_reg, 1 << 31); - } - else if (REG_IS_W(src_size)) - { - host_arm_TST_IMM(block, src_reg, 1 << 15); - } - else if (REG_IS_B(src_size)) - { - host_arm_TST_IMM(block, src_reg, 1 << 7); - } - else - fatal("TEST_JS_DEST %02x\n", uop->src_reg_a_real); + if (REG_IS_L(src_size)) { + host_arm_TST_IMM(block, src_reg, 1 << 31); + } else if (REG_IS_W(src_size)) { + host_arm_TST_IMM(block, src_reg, 1 << 15); + } else if (REG_IS_B(src_size)) { + host_arm_TST_IMM(block, src_reg, 1 << 7); + } else + fatal("TEST_JS_DEST %02x\n", uop->src_reg_a_real); - uop->p = host_arm_BNE_(block); + uop->p = host_arm_BNE_(block); - return 0; + return 0; } -static int codegen_XOR(codeblock_t *block, uop_t *uop) +static int +codegen_XOR(codeblock_t *block, uop_t *uop) { - int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg_a = HOST_REG_GET(uop->src_reg_a_real), src_reg_b = HOST_REG_GET(uop->src_reg_b_real); - int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size_a = IREG_GET_SIZE(uop->src_reg_a_real), src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); + int dest_reg = HOST_REG_GET(uop->dest_reg_a_real); + int src_reg_a = HOST_REG_GET(uop->src_reg_a_real); + int src_reg_b = HOST_REG_GET(uop->src_reg_b_real); + int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real); + int src_size_a = IREG_GET_SIZE(uop->src_reg_a_real); + int src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); - if (REG_IS_Q(dest_size) && REG_IS_Q(src_size_a) && REG_IS_Q(src_size_b)) - { - host_arm_VEOR_D(block, dest_reg, src_reg_a, src_reg_b); - } - else if (REG_IS_L(dest_size) && REG_IS_L(src_size_a) && REG_IS_L(src_size_b)) - { - host_arm_EOR_REG_LSL(block, dest_reg, src_reg_a, src_reg_b, 0); - } - else if (REG_IS_W(dest_size) && REG_IS_W(src_size_a) && REG_IS_W(src_size_b) && dest_reg == src_reg_a) - { - host_arm_UXTH(block, REG_TEMP, src_reg_b, 0); - host_arm_EOR_REG_LSL(block, dest_reg, src_reg_a, REG_TEMP, 0); - } - else if (REG_IS_B(dest_size) && REG_IS_B(src_size_a) && REG_IS_B(src_size_b) && dest_reg == src_reg_a) - { - host_arm_UXTB(block, REG_TEMP, src_reg_b, 0); - host_arm_EOR_REG_LSL(block, dest_reg, src_reg_a, REG_TEMP, 0); - } - else if (REG_IS_B(dest_size) && REG_IS_B(src_size_a) && REG_IS_BH(src_size_b) && dest_reg == src_reg_a) - { - host_arm_UXTB(block, REG_TEMP, src_reg_b, 8); - host_arm_EOR_REG_LSL(block, dest_reg, src_reg_a, REG_TEMP, 0); - } - else if (REG_IS_BH(dest_size) && REG_IS_BH(src_size_a) && REG_IS_B(src_size_b) && dest_reg == src_reg_a) - { - host_arm_UXTB(block, REG_TEMP, src_reg_b, 0); - host_arm_EOR_REG_LSL(block, dest_reg, src_reg_a, REG_TEMP, 8); - } - else if (REG_IS_BH(dest_size) && REG_IS_BH(src_size_a) && REG_IS_BH(src_size_b) && dest_reg == src_reg_a) - { - host_arm_UXTB(block, REG_TEMP, src_reg_b, 8); - host_arm_EOR_REG_LSL(block, dest_reg, src_reg_a, REG_TEMP, 8); - } - else - fatal("XOR %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real); + if (REG_IS_Q(dest_size) && REG_IS_Q(src_size_a) && REG_IS_Q(src_size_b)) { + host_arm_VEOR_D(block, dest_reg, src_reg_a, src_reg_b); + } else if (REG_IS_L(dest_size) && REG_IS_L(src_size_a) && REG_IS_L(src_size_b)) { + host_arm_EOR_REG_LSL(block, dest_reg, src_reg_a, src_reg_b, 0); + } else if (REG_IS_W(dest_size) && REG_IS_W(src_size_a) && REG_IS_W(src_size_b) && dest_reg == src_reg_a) { + host_arm_UXTH(block, REG_TEMP, src_reg_b, 0); + host_arm_EOR_REG_LSL(block, dest_reg, src_reg_a, REG_TEMP, 0); + } else if (REG_IS_B(dest_size) && REG_IS_B(src_size_a) && REG_IS_B(src_size_b) && dest_reg == src_reg_a) { + host_arm_UXTB(block, REG_TEMP, src_reg_b, 0); + host_arm_EOR_REG_LSL(block, dest_reg, src_reg_a, REG_TEMP, 0); + } else if (REG_IS_B(dest_size) && REG_IS_B(src_size_a) && REG_IS_BH(src_size_b) && dest_reg == src_reg_a) { + host_arm_UXTB(block, REG_TEMP, src_reg_b, 8); + host_arm_EOR_REG_LSL(block, dest_reg, src_reg_a, REG_TEMP, 0); + } else if (REG_IS_BH(dest_size) && REG_IS_BH(src_size_a) && REG_IS_B(src_size_b) && dest_reg == src_reg_a) { + host_arm_UXTB(block, REG_TEMP, src_reg_b, 0); + host_arm_EOR_REG_LSL(block, dest_reg, src_reg_a, REG_TEMP, 8); + } else if (REG_IS_BH(dest_size) && REG_IS_BH(src_size_a) && REG_IS_BH(src_size_b) && dest_reg == src_reg_a) { + host_arm_UXTB(block, REG_TEMP, src_reg_b, 8); + host_arm_EOR_REG_LSL(block, dest_reg, src_reg_a, REG_TEMP, 8); + } else + fatal("XOR %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real); - return 0; + return 0; } -static int codegen_XOR_IMM(codeblock_t *block, uop_t *uop) +static int +codegen_XOR_IMM(codeblock_t *block, uop_t *uop) { - int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg = HOST_REG_GET(uop->src_reg_a_real); - int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size = IREG_GET_SIZE(uop->src_reg_a_real); + int dest_reg = HOST_REG_GET(uop->dest_reg_a_real); + int src_reg = HOST_REG_GET(uop->src_reg_a_real); + int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real); + int src_size = IREG_GET_SIZE(uop->src_reg_a_real); - if (REG_IS_L(dest_size) && REG_IS_L(src_size)) - { - host_arm_EOR_IMM(block, dest_reg, src_reg, uop->imm_data); - } - else if (REG_IS_W(dest_size) && REG_IS_W(src_size) && dest_reg == src_reg) - { - host_arm_EOR_IMM(block, dest_reg, src_reg, uop->imm_data); - } - else if (REG_IS_B(dest_size) && REG_IS_B(src_size) && dest_reg == src_reg) - { - host_arm_EOR_IMM(block, dest_reg, src_reg, uop->imm_data); - } - else if (REG_IS_BH(dest_size) && REG_IS_BH(src_size) && dest_reg == src_reg) - { - host_arm_EOR_IMM(block, dest_reg, src_reg, uop->imm_data << 8); - } - else - fatal("XOR_IMM %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real); + if (REG_IS_L(dest_size) && REG_IS_L(src_size)) { + host_arm_EOR_IMM(block, dest_reg, src_reg, uop->imm_data); + } else if (REG_IS_W(dest_size) && REG_IS_W(src_size) && dest_reg == src_reg) { + host_arm_EOR_IMM(block, dest_reg, src_reg, uop->imm_data); + } else if (REG_IS_B(dest_size) && REG_IS_B(src_size) && dest_reg == src_reg) { + host_arm_EOR_IMM(block, dest_reg, src_reg, uop->imm_data); + } else if (REG_IS_BH(dest_size) && REG_IS_BH(src_size) && dest_reg == src_reg) { + host_arm_EOR_IMM(block, dest_reg, src_reg, uop->imm_data << 8); + } else + fatal("XOR_IMM %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real); - return 0; + return 0; } -const uOpFn uop_handlers[UOP_MAX] = -{ - [UOP_CALL_FUNC & UOP_MASK] = codegen_CALL_FUNC, - [UOP_CALL_FUNC_RESULT & UOP_MASK] = codegen_CALL_FUNC_RESULT, - [UOP_CALL_INSTRUCTION_FUNC & UOP_MASK] = codegen_CALL_INSTRUCTION_FUNC, +const uOpFn uop_handlers[UOP_MAX] = { + [UOP_CALL_FUNC & UOP_MASK] = codegen_CALL_FUNC, + [UOP_CALL_FUNC_RESULT & + UOP_MASK] + = codegen_CALL_FUNC_RESULT, + [UOP_CALL_INSTRUCTION_FUNC & + UOP_MASK] + = codegen_CALL_INSTRUCTION_FUNC, - [UOP_JMP & UOP_MASK] = codegen_JMP, + [UOP_JMP & + UOP_MASK] + = codegen_JMP, - [UOP_LOAD_SEG & UOP_MASK] = codegen_LOAD_SEG, + [UOP_LOAD_SEG & + UOP_MASK] + = codegen_LOAD_SEG, - [UOP_LOAD_FUNC_ARG_0 & UOP_MASK] = codegen_LOAD_FUNC_ARG0, - [UOP_LOAD_FUNC_ARG_1 & UOP_MASK] = codegen_LOAD_FUNC_ARG1, - [UOP_LOAD_FUNC_ARG_2 & UOP_MASK] = codegen_LOAD_FUNC_ARG2, - [UOP_LOAD_FUNC_ARG_3 & UOP_MASK] = codegen_LOAD_FUNC_ARG3, + [UOP_LOAD_FUNC_ARG_0 & + UOP_MASK] + = codegen_LOAD_FUNC_ARG0, + [UOP_LOAD_FUNC_ARG_1 & + UOP_MASK] + = codegen_LOAD_FUNC_ARG1, + [UOP_LOAD_FUNC_ARG_2 & + UOP_MASK] + = codegen_LOAD_FUNC_ARG2, + [UOP_LOAD_FUNC_ARG_3 & + UOP_MASK] + = codegen_LOAD_FUNC_ARG3, - [UOP_LOAD_FUNC_ARG_0_IMM & UOP_MASK] = codegen_LOAD_FUNC_ARG0_IMM, - [UOP_LOAD_FUNC_ARG_1_IMM & UOP_MASK] = codegen_LOAD_FUNC_ARG1_IMM, - [UOP_LOAD_FUNC_ARG_2_IMM & UOP_MASK] = codegen_LOAD_FUNC_ARG2_IMM, - [UOP_LOAD_FUNC_ARG_3_IMM & UOP_MASK] = codegen_LOAD_FUNC_ARG3_IMM, + [UOP_LOAD_FUNC_ARG_0_IMM & + UOP_MASK] + = codegen_LOAD_FUNC_ARG0_IMM, + [UOP_LOAD_FUNC_ARG_1_IMM & + UOP_MASK] + = codegen_LOAD_FUNC_ARG1_IMM, + [UOP_LOAD_FUNC_ARG_2_IMM & + UOP_MASK] + = codegen_LOAD_FUNC_ARG2_IMM, + [UOP_LOAD_FUNC_ARG_3_IMM & + UOP_MASK] + = codegen_LOAD_FUNC_ARG3_IMM, - [UOP_STORE_P_IMM & UOP_MASK] = codegen_STORE_PTR_IMM, - [UOP_STORE_P_IMM_8 & UOP_MASK] = codegen_STORE_PTR_IMM_8, + [UOP_STORE_P_IMM & + UOP_MASK] + = codegen_STORE_PTR_IMM, + [UOP_STORE_P_IMM_8 & + UOP_MASK] + = codegen_STORE_PTR_IMM_8, - [UOP_MEM_LOAD_ABS & UOP_MASK] = codegen_MEM_LOAD_ABS, - [UOP_MEM_LOAD_REG & UOP_MASK] = codegen_MEM_LOAD_REG, - [UOP_MEM_LOAD_SINGLE & UOP_MASK] = codegen_MEM_LOAD_SINGLE, - [UOP_MEM_LOAD_DOUBLE & UOP_MASK] = codegen_MEM_LOAD_DOUBLE, + [UOP_MEM_LOAD_ABS & + UOP_MASK] + = codegen_MEM_LOAD_ABS, + [UOP_MEM_LOAD_REG & + UOP_MASK] + = codegen_MEM_LOAD_REG, + [UOP_MEM_LOAD_SINGLE & + UOP_MASK] + = codegen_MEM_LOAD_SINGLE, + [UOP_MEM_LOAD_DOUBLE & + UOP_MASK] + = codegen_MEM_LOAD_DOUBLE, - [UOP_MEM_STORE_ABS & UOP_MASK] = codegen_MEM_STORE_ABS, - [UOP_MEM_STORE_REG & UOP_MASK] = codegen_MEM_STORE_REG, - [UOP_MEM_STORE_IMM_8 & UOP_MASK] = codegen_MEM_STORE_IMM_8, - [UOP_MEM_STORE_IMM_16 & UOP_MASK] = codegen_MEM_STORE_IMM_16, - [UOP_MEM_STORE_IMM_32 & UOP_MASK] = codegen_MEM_STORE_IMM_32, - [UOP_MEM_STORE_SINGLE & UOP_MASK] = codegen_MEM_STORE_SINGLE, - [UOP_MEM_STORE_DOUBLE & UOP_MASK] = codegen_MEM_STORE_DOUBLE, + [UOP_MEM_STORE_ABS & + UOP_MASK] + = codegen_MEM_STORE_ABS, + [UOP_MEM_STORE_REG & + UOP_MASK] + = codegen_MEM_STORE_REG, + [UOP_MEM_STORE_IMM_8 & + UOP_MASK] + = codegen_MEM_STORE_IMM_8, + [UOP_MEM_STORE_IMM_16 & + UOP_MASK] + = codegen_MEM_STORE_IMM_16, + [UOP_MEM_STORE_IMM_32 & + UOP_MASK] + = codegen_MEM_STORE_IMM_32, + [UOP_MEM_STORE_SINGLE & + UOP_MASK] + = codegen_MEM_STORE_SINGLE, + [UOP_MEM_STORE_DOUBLE & + UOP_MASK] + = codegen_MEM_STORE_DOUBLE, - [UOP_MOV & UOP_MASK] = codegen_MOV, - [UOP_MOV_PTR & UOP_MASK] = codegen_MOV_PTR, - [UOP_MOV_IMM & UOP_MASK] = codegen_MOV_IMM, - [UOP_MOVSX & UOP_MASK] = codegen_MOVSX, - [UOP_MOVZX & UOP_MASK] = codegen_MOVZX, - [UOP_MOV_DOUBLE_INT & UOP_MASK] = codegen_MOV_DOUBLE_INT, - [UOP_MOV_INT_DOUBLE & UOP_MASK] = codegen_MOV_INT_DOUBLE, - [UOP_MOV_INT_DOUBLE_64 & UOP_MASK] = codegen_MOV_INT_DOUBLE_64, - [UOP_MOV_REG_PTR & UOP_MASK] = codegen_MOV_REG_PTR, - [UOP_MOVZX_REG_PTR_8 & UOP_MASK] = codegen_MOVZX_REG_PTR_8, - [UOP_MOVZX_REG_PTR_16 & UOP_MASK] = codegen_MOVZX_REG_PTR_16, + [UOP_MOV & + UOP_MASK] + = codegen_MOV, + [UOP_MOV_PTR & + UOP_MASK] + = codegen_MOV_PTR, + [UOP_MOV_IMM & + UOP_MASK] + = codegen_MOV_IMM, + [UOP_MOVSX & + UOP_MASK] + = codegen_MOVSX, + [UOP_MOVZX & + UOP_MASK] + = codegen_MOVZX, + [UOP_MOV_DOUBLE_INT & + UOP_MASK] + = codegen_MOV_DOUBLE_INT, + [UOP_MOV_INT_DOUBLE & + UOP_MASK] + = codegen_MOV_INT_DOUBLE, + [UOP_MOV_INT_DOUBLE_64 & + UOP_MASK] + = codegen_MOV_INT_DOUBLE_64, + [UOP_MOV_REG_PTR & + UOP_MASK] + = codegen_MOV_REG_PTR, + [UOP_MOVZX_REG_PTR_8 & + UOP_MASK] + = codegen_MOVZX_REG_PTR_8, + [UOP_MOVZX_REG_PTR_16 & + UOP_MASK] + = codegen_MOVZX_REG_PTR_16, - [UOP_ADD & UOP_MASK] = codegen_ADD, - [UOP_ADD_IMM & UOP_MASK] = codegen_ADD_IMM, - [UOP_ADD_LSHIFT & UOP_MASK] = codegen_ADD_LSHIFT, - [UOP_AND & UOP_MASK] = codegen_AND, - [UOP_AND_IMM & UOP_MASK] = codegen_AND_IMM, - [UOP_ANDN & UOP_MASK] = codegen_ANDN, - [UOP_OR & UOP_MASK] = codegen_OR, - [UOP_OR_IMM & UOP_MASK] = codegen_OR_IMM, - [UOP_SUB & UOP_MASK] = codegen_SUB, - [UOP_SUB_IMM & UOP_MASK] = codegen_SUB_IMM, - [UOP_XOR & UOP_MASK] = codegen_XOR, - [UOP_XOR_IMM & UOP_MASK] = codegen_XOR_IMM, + [UOP_ADD & + UOP_MASK] + = codegen_ADD, + [UOP_ADD_IMM & + UOP_MASK] + = codegen_ADD_IMM, + [UOP_ADD_LSHIFT & + UOP_MASK] + = codegen_ADD_LSHIFT, + [UOP_AND & + UOP_MASK] + = codegen_AND, + [UOP_AND_IMM & + UOP_MASK] + = codegen_AND_IMM, + [UOP_ANDN & + UOP_MASK] + = codegen_ANDN, + [UOP_OR & + UOP_MASK] + = codegen_OR, + [UOP_OR_IMM & + UOP_MASK] + = codegen_OR_IMM, + [UOP_SUB & + UOP_MASK] + = codegen_SUB, + [UOP_SUB_IMM & + UOP_MASK] + = codegen_SUB_IMM, + [UOP_XOR & + UOP_MASK] + = codegen_XOR, + [UOP_XOR_IMM & + UOP_MASK] + = codegen_XOR_IMM, - [UOP_SAR & UOP_MASK] = codegen_SAR, - [UOP_SAR_IMM & UOP_MASK] = codegen_SAR_IMM, - [UOP_SHL & UOP_MASK] = codegen_SHL, - [UOP_SHL_IMM & UOP_MASK] = codegen_SHL_IMM, - [UOP_SHR & UOP_MASK] = codegen_SHR, - [UOP_SHR_IMM & UOP_MASK] = codegen_SHR_IMM, - [UOP_ROL & UOP_MASK] = codegen_ROL, - [UOP_ROL_IMM & UOP_MASK] = codegen_ROL_IMM, - [UOP_ROR & UOP_MASK] = codegen_ROR, - [UOP_ROR_IMM & UOP_MASK] = codegen_ROR_IMM, + [UOP_SAR & + UOP_MASK] + = codegen_SAR, + [UOP_SAR_IMM & + UOP_MASK] + = codegen_SAR_IMM, + [UOP_SHL & + UOP_MASK] + = codegen_SHL, + [UOP_SHL_IMM & + UOP_MASK] + = codegen_SHL_IMM, + [UOP_SHR & + UOP_MASK] + = codegen_SHR, + [UOP_SHR_IMM & + UOP_MASK] + = codegen_SHR_IMM, + [UOP_ROL & + UOP_MASK] + = codegen_ROL, + [UOP_ROL_IMM & + UOP_MASK] + = codegen_ROL_IMM, + [UOP_ROR & + UOP_MASK] + = codegen_ROR, + [UOP_ROR_IMM & + UOP_MASK] + = codegen_ROR_IMM, - [UOP_CMP_IMM_JZ & UOP_MASK] = codegen_CMP_IMM_JZ, + [UOP_CMP_IMM_JZ & + UOP_MASK] + = codegen_CMP_IMM_JZ, - [UOP_CMP_JB & UOP_MASK] = codegen_CMP_JB, - [UOP_CMP_JNBE & UOP_MASK] = codegen_CMP_JNBE, + [UOP_CMP_JB & + UOP_MASK] + = codegen_CMP_JB, + [UOP_CMP_JNBE & + UOP_MASK] + = codegen_CMP_JNBE, - [UOP_CMP_JNB_DEST & UOP_MASK] = codegen_CMP_JNB_DEST, - [UOP_CMP_JNBE_DEST & UOP_MASK] = codegen_CMP_JNBE_DEST, - [UOP_CMP_JNL_DEST & UOP_MASK] = codegen_CMP_JNL_DEST, - [UOP_CMP_JNLE_DEST & UOP_MASK] = codegen_CMP_JNLE_DEST, - [UOP_CMP_JNO_DEST & UOP_MASK] = codegen_CMP_JNO_DEST, - [UOP_CMP_JNZ_DEST & UOP_MASK] = codegen_CMP_JNZ_DEST, - [UOP_CMP_JB_DEST & UOP_MASK] = codegen_CMP_JB_DEST, - [UOP_CMP_JBE_DEST & UOP_MASK] = codegen_CMP_JBE_DEST, - [UOP_CMP_JL_DEST & UOP_MASK] = codegen_CMP_JL_DEST, - [UOP_CMP_JLE_DEST & UOP_MASK] = codegen_CMP_JLE_DEST, - [UOP_CMP_JO_DEST & UOP_MASK] = codegen_CMP_JO_DEST, - [UOP_CMP_JZ_DEST & UOP_MASK] = codegen_CMP_JZ_DEST, + [UOP_CMP_JNB_DEST & + UOP_MASK] + = codegen_CMP_JNB_DEST, + [UOP_CMP_JNBE_DEST & + UOP_MASK] + = codegen_CMP_JNBE_DEST, + [UOP_CMP_JNL_DEST & + UOP_MASK] + = codegen_CMP_JNL_DEST, + [UOP_CMP_JNLE_DEST & + UOP_MASK] + = codegen_CMP_JNLE_DEST, + [UOP_CMP_JNO_DEST & + UOP_MASK] + = codegen_CMP_JNO_DEST, + [UOP_CMP_JNZ_DEST & + UOP_MASK] + = codegen_CMP_JNZ_DEST, + [UOP_CMP_JB_DEST & + UOP_MASK] + = codegen_CMP_JB_DEST, + [UOP_CMP_JBE_DEST & + UOP_MASK] + = codegen_CMP_JBE_DEST, + [UOP_CMP_JL_DEST & + UOP_MASK] + = codegen_CMP_JL_DEST, + [UOP_CMP_JLE_DEST & + UOP_MASK] + = codegen_CMP_JLE_DEST, + [UOP_CMP_JO_DEST & + UOP_MASK] + = codegen_CMP_JO_DEST, + [UOP_CMP_JZ_DEST & + UOP_MASK] + = codegen_CMP_JZ_DEST, - [UOP_CMP_IMM_JNZ_DEST & UOP_MASK] = codegen_CMP_IMM_JNZ_DEST, - [UOP_CMP_IMM_JZ_DEST & UOP_MASK] = codegen_CMP_IMM_JZ_DEST, + [UOP_CMP_IMM_JNZ_DEST & + UOP_MASK] + = codegen_CMP_IMM_JNZ_DEST, + [UOP_CMP_IMM_JZ_DEST & + UOP_MASK] + = codegen_CMP_IMM_JZ_DEST, - [UOP_TEST_JNS_DEST & UOP_MASK] = codegen_TEST_JNS_DEST, - [UOP_TEST_JS_DEST & UOP_MASK] = codegen_TEST_JS_DEST, + [UOP_TEST_JNS_DEST & + UOP_MASK] + = codegen_TEST_JNS_DEST, + [UOP_TEST_JS_DEST & + UOP_MASK] + = codegen_TEST_JS_DEST, - [UOP_FP_ENTER & UOP_MASK] = codegen_FP_ENTER, - [UOP_MMX_ENTER & UOP_MASK] = codegen_MMX_ENTER, + [UOP_FP_ENTER & + UOP_MASK] + = codegen_FP_ENTER, + [UOP_MMX_ENTER & + UOP_MASK] + = codegen_MMX_ENTER, - [UOP_FADD & UOP_MASK] = codegen_FADD, - [UOP_FCOM & UOP_MASK] = codegen_FCOM, - [UOP_FDIV & UOP_MASK] = codegen_FDIV, - [UOP_FMUL & UOP_MASK] = codegen_FMUL, - [UOP_FSUB & UOP_MASK] = codegen_FSUB, + [UOP_FADD & + UOP_MASK] + = codegen_FADD, + [UOP_FCOM & + UOP_MASK] + = codegen_FCOM, + [UOP_FDIV & + UOP_MASK] + = codegen_FDIV, + [UOP_FMUL & + UOP_MASK] + = codegen_FMUL, + [UOP_FSUB & + UOP_MASK] + = codegen_FSUB, - [UOP_FABS & UOP_MASK] = codegen_FABS, - [UOP_FCHS & UOP_MASK] = codegen_FCHS, - [UOP_FSQRT & UOP_MASK] = codegen_FSQRT, - [UOP_FTST & UOP_MASK] = codegen_FTST, + [UOP_FABS & + UOP_MASK] + = codegen_FABS, + [UOP_FCHS & + UOP_MASK] + = codegen_FCHS, + [UOP_FSQRT & + UOP_MASK] + = codegen_FSQRT, + [UOP_FTST & + UOP_MASK] + = codegen_FTST, - [UOP_PACKSSWB & UOP_MASK] = codegen_PACKSSWB, - [UOP_PACKSSDW & UOP_MASK] = codegen_PACKSSDW, - [UOP_PACKUSWB & UOP_MASK] = codegen_PACKUSWB, + [UOP_PACKSSWB & + UOP_MASK] + = codegen_PACKSSWB, + [UOP_PACKSSDW & + UOP_MASK] + = codegen_PACKSSDW, + [UOP_PACKUSWB & + UOP_MASK] + = codegen_PACKUSWB, - [UOP_PADDB & UOP_MASK] = codegen_PADDB, - [UOP_PADDW & UOP_MASK] = codegen_PADDW, - [UOP_PADDD & UOP_MASK] = codegen_PADDD, - [UOP_PADDSB & UOP_MASK] = codegen_PADDSB, - [UOP_PADDSW & UOP_MASK] = codegen_PADDSW, - [UOP_PADDUSB & UOP_MASK] = codegen_PADDUSB, - [UOP_PADDUSW & UOP_MASK] = codegen_PADDUSW, + [UOP_PADDB & + UOP_MASK] + = codegen_PADDB, + [UOP_PADDW & + UOP_MASK] + = codegen_PADDW, + [UOP_PADDD & + UOP_MASK] + = codegen_PADDD, + [UOP_PADDSB & + UOP_MASK] + = codegen_PADDSB, + [UOP_PADDSW & + UOP_MASK] + = codegen_PADDSW, + [UOP_PADDUSB & + UOP_MASK] + = codegen_PADDUSB, + [UOP_PADDUSW & + UOP_MASK] + = codegen_PADDUSW, - [UOP_PCMPEQB & UOP_MASK] = codegen_PCMPEQB, - [UOP_PCMPEQW & UOP_MASK] = codegen_PCMPEQW, - [UOP_PCMPEQD & UOP_MASK] = codegen_PCMPEQD, - [UOP_PCMPGTB & UOP_MASK] = codegen_PCMPGTB, - [UOP_PCMPGTW & UOP_MASK] = codegen_PCMPGTW, - [UOP_PCMPGTD & UOP_MASK] = codegen_PCMPGTD, + [UOP_PCMPEQB & + UOP_MASK] + = codegen_PCMPEQB, + [UOP_PCMPEQW & + UOP_MASK] + = codegen_PCMPEQW, + [UOP_PCMPEQD & + UOP_MASK] + = codegen_PCMPEQD, + [UOP_PCMPGTB & + UOP_MASK] + = codegen_PCMPGTB, + [UOP_PCMPGTW & + UOP_MASK] + = codegen_PCMPGTW, + [UOP_PCMPGTD & + UOP_MASK] + = codegen_PCMPGTD, - [UOP_PF2ID & UOP_MASK] = codegen_PF2ID, - [UOP_PFADD & UOP_MASK] = codegen_PFADD, - [UOP_PFCMPEQ & UOP_MASK] = codegen_PFCMPEQ, - [UOP_PFCMPGE & UOP_MASK] = codegen_PFCMPGE, - [UOP_PFCMPGT & UOP_MASK] = codegen_PFCMPGT, - [UOP_PFMAX & UOP_MASK] = codegen_PFMAX, - [UOP_PFMIN & UOP_MASK] = codegen_PFMIN, - [UOP_PFMUL & UOP_MASK] = codegen_PFMUL, - [UOP_PFRCP & UOP_MASK] = codegen_PFRCP, - [UOP_PFRSQRT & UOP_MASK] = codegen_PFRSQRT, - [UOP_PFSUB & UOP_MASK] = codegen_PFSUB, - [UOP_PI2FD & UOP_MASK] = codegen_PI2FD, + [UOP_PF2ID & + UOP_MASK] + = codegen_PF2ID, + [UOP_PFADD & + UOP_MASK] + = codegen_PFADD, + [UOP_PFCMPEQ & + UOP_MASK] + = codegen_PFCMPEQ, + [UOP_PFCMPGE & + UOP_MASK] + = codegen_PFCMPGE, + [UOP_PFCMPGT & + UOP_MASK] + = codegen_PFCMPGT, + [UOP_PFMAX & + UOP_MASK] + = codegen_PFMAX, + [UOP_PFMIN & + UOP_MASK] + = codegen_PFMIN, + [UOP_PFMUL & + UOP_MASK] + = codegen_PFMUL, + [UOP_PFRCP & + UOP_MASK] + = codegen_PFRCP, + [UOP_PFRSQRT & + UOP_MASK] + = codegen_PFRSQRT, + [UOP_PFSUB & + UOP_MASK] + = codegen_PFSUB, + [UOP_PI2FD & + UOP_MASK] + = codegen_PI2FD, - [UOP_PMADDWD & UOP_MASK] = codegen_PMADDWD, - [UOP_PMULHW & UOP_MASK] = codegen_PMULHW, - [UOP_PMULLW & UOP_MASK] = codegen_PMULLW, + [UOP_PMADDWD & + UOP_MASK] + = codegen_PMADDWD, + [UOP_PMULHW & + UOP_MASK] + = codegen_PMULHW, + [UOP_PMULLW & + UOP_MASK] + = codegen_PMULLW, - [UOP_PSLLW_IMM & UOP_MASK] = codegen_PSLLW_IMM, - [UOP_PSLLD_IMM & UOP_MASK] = codegen_PSLLD_IMM, - [UOP_PSLLQ_IMM & UOP_MASK] = codegen_PSLLQ_IMM, - [UOP_PSRAW_IMM & UOP_MASK] = codegen_PSRAW_IMM, - [UOP_PSRAD_IMM & UOP_MASK] = codegen_PSRAD_IMM, - [UOP_PSRAQ_IMM & UOP_MASK] = codegen_PSRAQ_IMM, - [UOP_PSRLW_IMM & UOP_MASK] = codegen_PSRLW_IMM, - [UOP_PSRLD_IMM & UOP_MASK] = codegen_PSRLD_IMM, - [UOP_PSRLQ_IMM & UOP_MASK] = codegen_PSRLQ_IMM, + [UOP_PSLLW_IMM & + UOP_MASK] + = codegen_PSLLW_IMM, + [UOP_PSLLD_IMM & + UOP_MASK] + = codegen_PSLLD_IMM, + [UOP_PSLLQ_IMM & + UOP_MASK] + = codegen_PSLLQ_IMM, + [UOP_PSRAW_IMM & + UOP_MASK] + = codegen_PSRAW_IMM, + [UOP_PSRAD_IMM & + UOP_MASK] + = codegen_PSRAD_IMM, + [UOP_PSRAQ_IMM & + UOP_MASK] + = codegen_PSRAQ_IMM, + [UOP_PSRLW_IMM & + UOP_MASK] + = codegen_PSRLW_IMM, + [UOP_PSRLD_IMM & + UOP_MASK] + = codegen_PSRLD_IMM, + [UOP_PSRLQ_IMM & + UOP_MASK] + = codegen_PSRLQ_IMM, - [UOP_PSUBB & UOP_MASK] = codegen_PSUBB, - [UOP_PSUBW & UOP_MASK] = codegen_PSUBW, - [UOP_PSUBD & UOP_MASK] = codegen_PSUBD, - [UOP_PSUBSB & UOP_MASK] = codegen_PSUBSB, - [UOP_PSUBSW & UOP_MASK] = codegen_PSUBSW, - [UOP_PSUBUSB & UOP_MASK] = codegen_PSUBUSB, - [UOP_PSUBUSW & UOP_MASK] = codegen_PSUBUSW, + [UOP_PSUBB & + UOP_MASK] + = codegen_PSUBB, + [UOP_PSUBW & + UOP_MASK] + = codegen_PSUBW, + [UOP_PSUBD & + UOP_MASK] + = codegen_PSUBD, + [UOP_PSUBSB & + UOP_MASK] + = codegen_PSUBSB, + [UOP_PSUBSW & + UOP_MASK] + = codegen_PSUBSW, + [UOP_PSUBUSB & + UOP_MASK] + = codegen_PSUBUSB, + [UOP_PSUBUSW & + UOP_MASK] + = codegen_PSUBUSW, - [UOP_PUNPCKHBW & UOP_MASK] = codegen_PUNPCKHBW, - [UOP_PUNPCKHWD & UOP_MASK] = codegen_PUNPCKHWD, - [UOP_PUNPCKHDQ & UOP_MASK] = codegen_PUNPCKHDQ, - [UOP_PUNPCKLBW & UOP_MASK] = codegen_PUNPCKLBW, - [UOP_PUNPCKLWD & UOP_MASK] = codegen_PUNPCKLWD, - [UOP_PUNPCKLDQ & UOP_MASK] = codegen_PUNPCKLDQ, + [UOP_PUNPCKHBW & + UOP_MASK] + = codegen_PUNPCKHBW, + [UOP_PUNPCKHWD & + UOP_MASK] + = codegen_PUNPCKHWD, + [UOP_PUNPCKHDQ & + UOP_MASK] + = codegen_PUNPCKHDQ, + [UOP_PUNPCKLBW & + UOP_MASK] + = codegen_PUNPCKLBW, + [UOP_PUNPCKLWD & + UOP_MASK] + = codegen_PUNPCKLWD, + [UOP_PUNPCKLDQ & + UOP_MASK] + = codegen_PUNPCKLDQ, - [UOP_NOP_BARRIER & UOP_MASK] = codegen_NOP + [UOP_NOP_BARRIER & + UOP_MASK] + = codegen_NOP }; -void codegen_direct_read_8(codeblock_t *block, int host_reg, void *p) +void +codegen_direct_read_8(codeblock_t *block, int host_reg, void *p) { - if (in_range_h(p, &cpu_state)) - host_arm_LDRB_IMM(block, host_reg, REG_CPUSTATE, (uintptr_t)p - (uintptr_t)&cpu_state); - else - fatal("codegen_direct_read_8 - not in range\n"); + if (in_range_h(p, &cpu_state)) + host_arm_LDRB_IMM(block, host_reg, REG_CPUSTATE, (uintptr_t) p - (uintptr_t) &cpu_state); + else + fatal("codegen_direct_read_8 - not in range\n"); } -void codegen_direct_read_16(codeblock_t *block, int host_reg, void *p) +void +codegen_direct_read_16(codeblock_t *block, int host_reg, void *p) { - if (in_range_h(p, &cpu_state)) - host_arm_LDRH_IMM(block, host_reg, REG_CPUSTATE, (uintptr_t)p - (uintptr_t)&cpu_state); - else - { - host_arm_MOV_IMM(block, REG_R3, (uintptr_t)p - (uintptr_t)&cpu_state); - host_arm_LDRH_REG(block, host_reg, REG_CPUSTATE, REG_R3); - } + if (in_range_h(p, &cpu_state)) + host_arm_LDRH_IMM(block, host_reg, REG_CPUSTATE, (uintptr_t) p - (uintptr_t) &cpu_state); + else { + host_arm_MOV_IMM(block, REG_R3, (uintptr_t) p - (uintptr_t) &cpu_state); + host_arm_LDRH_REG(block, host_reg, REG_CPUSTATE, REG_R3); + } } -void codegen_direct_read_32(codeblock_t *block, int host_reg, void *p) +void +codegen_direct_read_32(codeblock_t *block, int host_reg, void *p) { - if (in_range(p, &cpu_state)) - host_arm_LDR_IMM(block, host_reg, REG_CPUSTATE, (uintptr_t)p - (uintptr_t)&cpu_state); - else - fatal("codegen_direct_read_32 - not in range\n"); + if (in_range(p, &cpu_state)) + host_arm_LDR_IMM(block, host_reg, REG_CPUSTATE, (uintptr_t) p - (uintptr_t) &cpu_state); + else + fatal("codegen_direct_read_32 - not in range\n"); } -void codegen_direct_read_pointer(codeblock_t *block, int host_reg, void *p) +void +codegen_direct_read_pointer(codeblock_t *block, int host_reg, void *p) { - codegen_direct_read_32(block, host_reg, p); + codegen_direct_read_32(block, host_reg, p); } -void codegen_direct_read_64(codeblock_t *block, int host_reg, void *p) +void +codegen_direct_read_64(codeblock_t *block, int host_reg, void *p) { - host_arm_VLDR_D(block, host_reg, REG_CPUSTATE, (uintptr_t)p - (uintptr_t)&cpu_state); + host_arm_VLDR_D(block, host_reg, REG_CPUSTATE, (uintptr_t) p - (uintptr_t) &cpu_state); } -void codegen_direct_read_double(codeblock_t *block, int host_reg, void *p) +void +codegen_direct_read_double(codeblock_t *block, int host_reg, void *p) { - host_arm_VLDR_D(block, host_reg, REG_CPUSTATE, (uintptr_t)p - (uintptr_t)&cpu_state); + host_arm_VLDR_D(block, host_reg, REG_CPUSTATE, (uintptr_t) p - (uintptr_t) &cpu_state); } -void codegen_direct_read_st_8(codeblock_t *block, int host_reg, void *base, int reg_idx) +void +codegen_direct_read_st_8(codeblock_t *block, int host_reg, void *base, int reg_idx) { - host_arm_LDR_IMM(block, REG_TEMP, REG_HOST_SP, IREG_TOP_diff_stack_offset); - host_arm_ADD_IMM(block, REG_TEMP, REG_TEMP, reg_idx); - host_arm_AND_IMM(block, REG_TEMP, REG_TEMP, 7); - host_arm_ADD_REG_LSL(block, REG_TEMP, REG_CPUSTATE, REG_TEMP, 3); - host_arm_LDRB_IMM(block, host_reg, REG_TEMP, (uintptr_t)base - (uintptr_t)&cpu_state); + host_arm_LDR_IMM(block, REG_TEMP, REG_HOST_SP, IREG_TOP_diff_stack_offset); + host_arm_ADD_IMM(block, REG_TEMP, REG_TEMP, reg_idx); + host_arm_AND_IMM(block, REG_TEMP, REG_TEMP, 7); + host_arm_ADD_REG_LSL(block, REG_TEMP, REG_CPUSTATE, REG_TEMP, 3); + host_arm_LDRB_IMM(block, host_reg, REG_TEMP, (uintptr_t) base - (uintptr_t) &cpu_state); } -void codegen_direct_read_st_64(codeblock_t *block, int host_reg, void *base, int reg_idx) +void +codegen_direct_read_st_64(codeblock_t *block, int host_reg, void *base, int reg_idx) { - host_arm_LDR_IMM(block, REG_TEMP, REG_HOST_SP, IREG_TOP_diff_stack_offset); - host_arm_ADD_IMM(block, REG_TEMP, REG_TEMP, reg_idx); - host_arm_AND_IMM(block, REG_TEMP, REG_TEMP, 7); - host_arm_ADD_REG_LSL(block, REG_TEMP, REG_CPUSTATE, REG_TEMP, 3); - host_arm_VLDR_D(block, host_reg, REG_TEMP, (uintptr_t)base - (uintptr_t)&cpu_state); + host_arm_LDR_IMM(block, REG_TEMP, REG_HOST_SP, IREG_TOP_diff_stack_offset); + host_arm_ADD_IMM(block, REG_TEMP, REG_TEMP, reg_idx); + host_arm_AND_IMM(block, REG_TEMP, REG_TEMP, 7); + host_arm_ADD_REG_LSL(block, REG_TEMP, REG_CPUSTATE, REG_TEMP, 3); + host_arm_VLDR_D(block, host_reg, REG_TEMP, (uintptr_t) base - (uintptr_t) &cpu_state); } -void codegen_direct_read_st_double(codeblock_t *block, int host_reg, void *base, int reg_idx) +void +codegen_direct_read_st_double(codeblock_t *block, int host_reg, void *base, int reg_idx) { - host_arm_LDR_IMM(block, REG_TEMP, REG_HOST_SP, IREG_TOP_diff_stack_offset); - host_arm_ADD_IMM(block, REG_TEMP, REG_TEMP, reg_idx); - host_arm_AND_IMM(block, REG_TEMP, REG_TEMP, 7); - host_arm_ADD_REG_LSL(block, REG_TEMP, REG_CPUSTATE, REG_TEMP, 3); - host_arm_VLDR_D(block, host_reg, REG_TEMP, (uintptr_t)base - (uintptr_t)&cpu_state); + host_arm_LDR_IMM(block, REG_TEMP, REG_HOST_SP, IREG_TOP_diff_stack_offset); + host_arm_ADD_IMM(block, REG_TEMP, REG_TEMP, reg_idx); + host_arm_AND_IMM(block, REG_TEMP, REG_TEMP, 7); + host_arm_ADD_REG_LSL(block, REG_TEMP, REG_CPUSTATE, REG_TEMP, 3); + host_arm_VLDR_D(block, host_reg, REG_TEMP, (uintptr_t) base - (uintptr_t) &cpu_state); } -void codegen_direct_write_8(codeblock_t *block, void *p, int host_reg) +void +codegen_direct_write_8(codeblock_t *block, void *p, int host_reg) { - if (in_range(p, &cpu_state)) - host_arm_STRB_IMM(block, host_reg, REG_CPUSTATE, (uintptr_t)p - (uintptr_t)&cpu_state); - else - fatal("codegen_direct_write_8 - not in range\n"); + if (in_range(p, &cpu_state)) + host_arm_STRB_IMM(block, host_reg, REG_CPUSTATE, (uintptr_t) p - (uintptr_t) &cpu_state); + else + fatal("codegen_direct_write_8 - not in range\n"); } -void codegen_direct_write_16(codeblock_t *block, void *p, int host_reg) +void +codegen_direct_write_16(codeblock_t *block, void *p, int host_reg) { - if (in_range_h(p, &cpu_state)) - host_arm_STRH_IMM(block, host_reg, REG_CPUSTATE, (uintptr_t)p - (uintptr_t)&cpu_state); - else - { - host_arm_MOV_IMM(block, REG_R3, (uintptr_t)p - (uintptr_t)&cpu_state); - host_arm_STRH_REG(block, host_reg, REG_CPUSTATE, REG_R3); - } + if (in_range_h(p, &cpu_state)) + host_arm_STRH_IMM(block, host_reg, REG_CPUSTATE, (uintptr_t) p - (uintptr_t) &cpu_state); + else { + host_arm_MOV_IMM(block, REG_R3, (uintptr_t) p - (uintptr_t) &cpu_state); + host_arm_STRH_REG(block, host_reg, REG_CPUSTATE, REG_R3); + } } -void codegen_direct_write_32(codeblock_t *block, void *p, int host_reg) +void +codegen_direct_write_32(codeblock_t *block, void *p, int host_reg) { - if (in_range(p, &cpu_state)) - host_arm_STR_IMM(block, host_reg, REG_CPUSTATE, (uintptr_t)p - (uintptr_t)&cpu_state); - else - fatal("codegen_direct_write_32 - not in range\n"); + if (in_range(p, &cpu_state)) + host_arm_STR_IMM(block, host_reg, REG_CPUSTATE, (uintptr_t) p - (uintptr_t) &cpu_state); + else + fatal("codegen_direct_write_32 - not in range\n"); } -void codegen_direct_write_64(codeblock_t *block, void *p, int host_reg) +void +codegen_direct_write_64(codeblock_t *block, void *p, int host_reg) { - host_arm_VSTR_D(block, host_reg, REG_CPUSTATE, (uintptr_t)p - (uintptr_t)&cpu_state); + host_arm_VSTR_D(block, host_reg, REG_CPUSTATE, (uintptr_t) p - (uintptr_t) &cpu_state); } -void codegen_direct_write_double(codeblock_t *block, void *p, int host_reg) +void +codegen_direct_write_double(codeblock_t *block, void *p, int host_reg) { - host_arm_VSTR_D(block, host_reg, REG_CPUSTATE, (uintptr_t)p - (uintptr_t)&cpu_state); + host_arm_VSTR_D(block, host_reg, REG_CPUSTATE, (uintptr_t) p - (uintptr_t) &cpu_state); } -void codegen_direct_write_st_8(codeblock_t *block, void *base, int reg_idx, int host_reg) +void +codegen_direct_write_st_8(codeblock_t *block, void *base, int reg_idx, int host_reg) { - host_arm_LDR_IMM(block, REG_TEMP, REG_HOST_SP, IREG_TOP_diff_stack_offset); - host_arm_ADD_IMM(block, REG_TEMP, REG_TEMP, reg_idx); - host_arm_AND_IMM(block, REG_TEMP, REG_TEMP, 7); - host_arm_ADD_REG_LSL(block, REG_TEMP, REG_CPUSTATE, REG_TEMP, 3); - host_arm_STRB_IMM(block, host_reg, REG_TEMP, (uintptr_t)base - (uintptr_t)&cpu_state); + host_arm_LDR_IMM(block, REG_TEMP, REG_HOST_SP, IREG_TOP_diff_stack_offset); + host_arm_ADD_IMM(block, REG_TEMP, REG_TEMP, reg_idx); + host_arm_AND_IMM(block, REG_TEMP, REG_TEMP, 7); + host_arm_ADD_REG_LSL(block, REG_TEMP, REG_CPUSTATE, REG_TEMP, 3); + host_arm_STRB_IMM(block, host_reg, REG_TEMP, (uintptr_t) base - (uintptr_t) &cpu_state); } -void codegen_direct_write_st_64(codeblock_t *block, void *base, int reg_idx, int host_reg) +void +codegen_direct_write_st_64(codeblock_t *block, void *base, int reg_idx, int host_reg) { - host_arm_LDR_IMM(block, REG_TEMP, REG_HOST_SP, IREG_TOP_diff_stack_offset); - host_arm_ADD_IMM(block, REG_TEMP, REG_TEMP, reg_idx); - host_arm_AND_IMM(block, REG_TEMP, REG_TEMP, 7); - host_arm_ADD_REG_LSL(block, REG_TEMP, REG_CPUSTATE, REG_TEMP, 3); - host_arm_VSTR_D(block, host_reg, REG_TEMP, (uintptr_t)base - (uintptr_t)&cpu_state); + host_arm_LDR_IMM(block, REG_TEMP, REG_HOST_SP, IREG_TOP_diff_stack_offset); + host_arm_ADD_IMM(block, REG_TEMP, REG_TEMP, reg_idx); + host_arm_AND_IMM(block, REG_TEMP, REG_TEMP, 7); + host_arm_ADD_REG_LSL(block, REG_TEMP, REG_CPUSTATE, REG_TEMP, 3); + host_arm_VSTR_D(block, host_reg, REG_TEMP, (uintptr_t) base - (uintptr_t) &cpu_state); } -void codegen_direct_write_st_double(codeblock_t *block, void *base, int reg_idx, int host_reg) +void +codegen_direct_write_st_double(codeblock_t *block, void *base, int reg_idx, int host_reg) { - host_arm_LDR_IMM(block, REG_TEMP, REG_HOST_SP, IREG_TOP_diff_stack_offset); - host_arm_ADD_IMM(block, REG_TEMP, REG_TEMP, reg_idx); - host_arm_AND_IMM(block, REG_TEMP, REG_TEMP, 7); - host_arm_ADD_REG_LSL(block, REG_TEMP, REG_CPUSTATE, REG_TEMP, 3); - host_arm_VSTR_D(block, host_reg, REG_TEMP, (uintptr_t)base - (uintptr_t)&cpu_state); + host_arm_LDR_IMM(block, REG_TEMP, REG_HOST_SP, IREG_TOP_diff_stack_offset); + host_arm_ADD_IMM(block, REG_TEMP, REG_TEMP, reg_idx); + host_arm_AND_IMM(block, REG_TEMP, REG_TEMP, 7); + host_arm_ADD_REG_LSL(block, REG_TEMP, REG_CPUSTATE, REG_TEMP, 3); + host_arm_VSTR_D(block, host_reg, REG_TEMP, (uintptr_t) base - (uintptr_t) &cpu_state); } -void codegen_direct_write_ptr(codeblock_t *block, void *p, int host_reg) +void +codegen_direct_write_ptr(codeblock_t *block, void *p, int host_reg) { - if (in_range(p, &cpu_state)) - host_arm_STR_IMM(block, host_reg, REG_CPUSTATE, (uintptr_t)p - (uintptr_t)&cpu_state); - else - fatal("codegen_direct_write_ptr - not in range\n"); + if (in_range(p, &cpu_state)) + host_arm_STR_IMM(block, host_reg, REG_CPUSTATE, (uintptr_t) p - (uintptr_t) &cpu_state); + else + fatal("codegen_direct_write_ptr - not in range\n"); } -void codegen_direct_read_16_stack(codeblock_t *block, int host_reg, int stack_offset) +void +codegen_direct_read_16_stack(codeblock_t *block, int host_reg, int stack_offset) { - if (stack_offset >= 0 && stack_offset < 256) - host_arm_LDRH_IMM(block, host_reg, REG_HOST_SP, stack_offset); - else - fatal("codegen_direct_read_32 - not in range\n"); + if (stack_offset >= 0 && stack_offset < 256) + host_arm_LDRH_IMM(block, host_reg, REG_HOST_SP, stack_offset); + else + fatal("codegen_direct_read_32 - not in range\n"); } -void codegen_direct_read_32_stack(codeblock_t *block, int host_reg, int stack_offset) +void +codegen_direct_read_32_stack(codeblock_t *block, int host_reg, int stack_offset) { - if (stack_offset >= 0 && stack_offset < 4096) - host_arm_LDR_IMM(block, host_reg, REG_HOST_SP, stack_offset); - else - fatal("codegen_direct_read_32 - not in range\n"); + if (stack_offset >= 0 && stack_offset < 4096) + host_arm_LDR_IMM(block, host_reg, REG_HOST_SP, stack_offset); + else + fatal("codegen_direct_read_32 - not in range\n"); } -void codegen_direct_read_pointer_stack(codeblock_t *block, int host_reg, int stack_offset) +void +codegen_direct_read_pointer_stack(codeblock_t *block, int host_reg, int stack_offset) { - codegen_direct_read_32_stack(block, host_reg, stack_offset); + codegen_direct_read_32_stack(block, host_reg, stack_offset); } -void codegen_direct_read_64_stack(codeblock_t *block, int host_reg, int stack_offset) +void +codegen_direct_read_64_stack(codeblock_t *block, int host_reg, int stack_offset) { - host_arm_VLDR_D(block, host_reg, REG_HOST_SP, stack_offset); + host_arm_VLDR_D(block, host_reg, REG_HOST_SP, stack_offset); } -void codegen_direct_read_double_stack(codeblock_t *block, int host_reg, int stack_offset) +void +codegen_direct_read_double_stack(codeblock_t *block, int host_reg, int stack_offset) { - host_arm_VLDR_D(block, host_reg, REG_HOST_SP, stack_offset); + host_arm_VLDR_D(block, host_reg, REG_HOST_SP, stack_offset); } -void codegen_direct_write_32_stack(codeblock_t *block, int stack_offset, int host_reg) +void +codegen_direct_write_32_stack(codeblock_t *block, int stack_offset, int host_reg) { - if (stack_offset >= 0 && stack_offset < 4096) - host_arm_STR_IMM(block, host_reg, REG_HOST_SP, stack_offset); - else - fatal("codegen_direct_write_32 - not in range\n"); + if (stack_offset >= 0 && stack_offset < 4096) + host_arm_STR_IMM(block, host_reg, REG_HOST_SP, stack_offset); + else + fatal("codegen_direct_write_32 - not in range\n"); } -void codegen_direct_write_64_stack(codeblock_t *block, int stack_offset, int host_reg) +void +codegen_direct_write_64_stack(codeblock_t *block, int stack_offset, int host_reg) { - host_arm_VSTR_D(block, host_reg, REG_HOST_SP, stack_offset); + host_arm_VSTR_D(block, host_reg, REG_HOST_SP, stack_offset); } -void codegen_direct_write_double_stack(codeblock_t *block, int stack_offset, int host_reg) +void +codegen_direct_write_double_stack(codeblock_t *block, int stack_offset, int host_reg) { - host_arm_VSTR_D(block, host_reg, REG_HOST_SP, stack_offset); + host_arm_VSTR_D(block, host_reg, REG_HOST_SP, stack_offset); } -void codegen_set_jump_dest(codeblock_t *block, void *p) +void +codegen_set_jump_dest(codeblock_t *block, void *p) { - *(uint32_t *)p |= ((((uintptr_t)&block_write_data[block_pos] - (uintptr_t)p) - 8) & 0x3fffffc) >> 2; + *(uint32_t *) p |= ((((uintptr_t) &block_write_data[block_pos] - (uintptr_t) p) - 8) & 0x3fffffc) >> 2; } #endif diff --git a/src/codegen_new/codegen_backend_x86-64.c b/src/codegen_new/codegen_backend_x86-64.c index 02bcf2ab3..67355539b 100644 --- a/src/codegen_new/codegen_backend_x86-64.c +++ b/src/codegen_new/codegen_backend_x86-64.c @@ -1,28 +1,30 @@ #if defined __amd64__ || defined _M_X64 -#include -#include -#include <86box/86box.h> -#include "cpu.h" -#include <86box/mem.h> +# include +# include +# include <86box/86box.h> +# include "cpu.h" +# include <86box/mem.h> -#include "codegen.h" -#include "codegen_allocator.h" -#include "codegen_backend.h" -#include "codegen_backend_x86-64_defs.h" -#include "codegen_backend_x86-64_ops.h" -#include "codegen_backend_x86-64_ops_sse.h" -#include "codegen_reg.h" -#include "x86.h" +# include "codegen.h" +# include "codegen_allocator.h" +# include "codegen_backend.h" +# include "codegen_backend_x86-64_defs.h" +# include "codegen_backend_x86-64_ops.h" +# include "codegen_backend_x86-64_ops_sse.h" +# include "codegen_reg.h" +# include "x86.h" +# include "x86seg_common.h" +# include "x86seg.h" -#if defined(__linux__) || defined(__APPLE__) -#include -#include -#endif -#if defined WIN32 || defined _WIN32 || defined _WIN32 -#include -#endif -#include +# if defined(__linux__) || defined(__APPLE__) +# include +# include +# endif +# if defined WIN32 || defined _WIN32 || defined _WIN32 +# include +# endif +# include void *codegen_mem_load_byte; void *codegen_mem_load_word; @@ -41,352 +43,338 @@ void *codegen_mem_store_double; void *codegen_gpf_rout; void *codegen_exit_rout; -host_reg_def_t codegen_host_reg_list[CODEGEN_HOST_REGS] = -{ - /*Note: while EAX and EDX are normally volatile registers under x86 - calling conventions, the recompiler will explicitly save and restore - them across funcion calls*/ - {REG_EAX, 0}, - {REG_EBX, 0}, - {REG_EDX, 0} +host_reg_def_t codegen_host_reg_list[CODEGEN_HOST_REGS] = { + /*Note: while EAX and EDX are normally volatile registers under x86 + calling conventions, the recompiler will explicitly save and restore + them across funcion calls*/ + {REG_EAX, 0}, + { REG_EBX, 0}, + { REG_EDX, 0} }; -host_reg_def_t codegen_host_fp_reg_list[CODEGEN_HOST_FP_REGS] = -{ -#if _WIN64 - /*Windows x86-64 calling convention preserves XMM6-XMM15*/ - {REG_XMM6, 0}, - {REG_XMM7, 0}, -#else - /*System V AMD64 calling convention does not preserve any XMM registers*/ - {REG_XMM6, HOST_REG_FLAG_VOLATILE}, - {REG_XMM7, HOST_REG_FLAG_VOLATILE}, -#endif - {REG_XMM1, HOST_REG_FLAG_VOLATILE}, - {REG_XMM2, HOST_REG_FLAG_VOLATILE}, - {REG_XMM3, HOST_REG_FLAG_VOLATILE}, - {REG_XMM4, HOST_REG_FLAG_VOLATILE}, - {REG_XMM5, HOST_REG_FLAG_VOLATILE} +host_reg_def_t codegen_host_fp_reg_list[CODEGEN_HOST_FP_REGS] = { +# if _WIN64 + /*Windows x86-64 calling convention preserves XMM6-XMM15*/ + {REG_XMM6, 0 }, + { REG_XMM7, 0 }, +# else + /*System V AMD64 calling convention does not preserve any XMM registers*/ + { REG_XMM6, HOST_REG_FLAG_VOLATILE }, + { REG_XMM7, HOST_REG_FLAG_VOLATILE }, +# endif + { REG_XMM1, HOST_REG_FLAG_VOLATILE}, + { REG_XMM2, HOST_REG_FLAG_VOLATILE}, + { REG_XMM3, HOST_REG_FLAG_VOLATILE}, + { REG_XMM4, HOST_REG_FLAG_VOLATILE}, + { REG_XMM5, HOST_REG_FLAG_VOLATILE} }; -static void build_load_routine(codeblock_t *block, int size, int is_float) +static void +build_load_routine(codeblock_t *block, int size, int is_float) { - uint8_t *branch_offset; - uint8_t *misaligned_offset; + uint8_t *branch_offset; + uint8_t *misaligned_offset; - /*In - ESI = address - Out - ECX = data, ESI = abrt*/ - /*MOV ECX, ESI - SHR ESI, 12 - MOV RSI, [readlookup2+ESI*4] - CMP ESI, -1 - JNZ + - MOVZX ECX, B[RSI+RCX] - XOR ESI,ESI - RET - * PUSH EAX - PUSH EDX - PUSH ECX - CALL readmembl - POP ECX - POP EDX - POP EAX - MOVZX ECX, AL - RET - */ - host_x86_MOV32_REG_REG(block, REG_ECX, REG_ESI); - host_x86_SHR32_IMM(block, REG_ESI, 12); - host_x86_MOV64_REG_IMM(block, REG_RDI, (uint64_t)(uintptr_t)readlookup2); - host_x86_MOV64_REG_BASE_INDEX_SHIFT(block, REG_RSI, REG_RDI, REG_RSI, 3); - if (size != 1) - { - host_x86_TEST32_REG_IMM(block, REG_ECX, size-1); - misaligned_offset = host_x86_JNZ_short(block); - } - host_x86_CMP64_REG_IMM(block, REG_RSI, (uint32_t)-1); - branch_offset = host_x86_JZ_short(block); - if (size == 1 && !is_float) - host_x86_MOVZX_BASE_INDEX_32_8(block, REG_ECX, REG_RSI, REG_RCX); - else if (size == 2 && !is_float) - host_x86_MOVZX_BASE_INDEX_32_16(block, REG_ECX, REG_RSI, REG_RCX); - else if (size == 4 && !is_float) - host_x86_MOV32_REG_BASE_INDEX(block, REG_ECX, REG_RSI, REG_RCX); - else if (size == 4 && is_float) - host_x86_CVTSS2SD_XREG_BASE_INDEX(block, REG_XMM_TEMP, REG_RSI, REG_RCX); - else if (size == 8) - host_x86_MOVQ_XREG_BASE_INDEX(block, REG_XMM_TEMP, REG_RSI, REG_RCX); - else - fatal("build_load_routine: size=%i\n", size); - host_x86_XOR32_REG_REG(block, REG_ESI, REG_ESI); - host_x86_RET(block); + /*In - ESI = address + Out - ECX = data, ESI = abrt*/ + /*MOV ECX, ESI + SHR ESI, 12 + MOV RSI, [readlookup2+ESI*4] + CMP ESI, -1 + JNZ + + MOVZX ECX, B[RSI+RCX] + XOR ESI,ESI + RET + * PUSH EAX + PUSH EDX + PUSH ECX + CALL readmembl + POP ECX + POP EDX + POP EAX + MOVZX ECX, AL + RET + */ + host_x86_MOV32_REG_REG(block, REG_ECX, REG_ESI); + host_x86_SHR32_IMM(block, REG_ESI, 12); + host_x86_MOV64_REG_IMM(block, REG_RDI, (uint64_t) (uintptr_t) readlookup2); + host_x86_MOV64_REG_BASE_INDEX_SHIFT(block, REG_RSI, REG_RDI, REG_RSI, 3); + if (size != 1) { + host_x86_TEST32_REG_IMM(block, REG_ECX, size - 1); + misaligned_offset = host_x86_JNZ_short(block); + } + host_x86_CMP64_REG_IMM(block, REG_RSI, (uint32_t) -1); + branch_offset = host_x86_JZ_short(block); + if (size == 1 && !is_float) + host_x86_MOVZX_BASE_INDEX_32_8(block, REG_ECX, REG_RSI, REG_RCX); + else if (size == 2 && !is_float) + host_x86_MOVZX_BASE_INDEX_32_16(block, REG_ECX, REG_RSI, REG_RCX); + else if (size == 4 && !is_float) + host_x86_MOV32_REG_BASE_INDEX(block, REG_ECX, REG_RSI, REG_RCX); + else if (size == 4 && is_float) + host_x86_CVTSS2SD_XREG_BASE_INDEX(block, REG_XMM_TEMP, REG_RSI, REG_RCX); + else if (size == 8) + host_x86_MOVQ_XREG_BASE_INDEX(block, REG_XMM_TEMP, REG_RSI, REG_RCX); + else + fatal("build_load_routine: size=%i\n", size); + host_x86_XOR32_REG_REG(block, REG_ESI, REG_ESI); + host_x86_RET(block); - *branch_offset = (uint8_t)((uintptr_t)&block_write_data[block_pos] - (uintptr_t)branch_offset) - 1; - if (size != 1) - *misaligned_offset = (uint8_t)((uintptr_t)&block_write_data[block_pos] - (uintptr_t)misaligned_offset) - 1; - host_x86_PUSH(block, REG_RAX); - host_x86_PUSH(block, REG_RDX); -#if _WIN64 - host_x86_SUB64_REG_IMM(block, REG_RSP, 0x20); - //host_x86_MOV32_REG_REG(block, REG_ECX, uop->imm_data); -#else - host_x86_MOV32_REG_REG(block, REG_EDI, REG_ECX); -#endif - if (size == 1 && !is_float) - { - host_x86_CALL(block, (void *)readmembl); - host_x86_MOVZX_REG_32_8(block, REG_ECX, REG_EAX); - } - else if (size == 2 && !is_float) - { - host_x86_CALL(block, (void *)readmemwl); - host_x86_MOVZX_REG_32_16(block, REG_ECX, REG_EAX); - } - else if (size == 4 && !is_float) - { - host_x86_CALL(block, (void *)readmemll); - host_x86_MOV32_REG_REG(block, REG_ECX, REG_EAX); - } - else if (size == 4 && is_float) - { - host_x86_CALL(block, (void *)readmemll); - host_x86_MOVD_XREG_REG(block, REG_XMM_TEMP, REG_EAX); - host_x86_CVTSS2SD_XREG_XREG(block, REG_XMM_TEMP, REG_XMM_TEMP); - } - else if (size == 8) - { - host_x86_CALL(block, (void *)readmemql); - host_x86_MOVQ_XREG_REG(block, REG_XMM_TEMP, REG_RAX); - } -#if _WIN64 - host_x86_ADD64_REG_IMM(block, REG_RSP, 0x20); -#endif - host_x86_POP(block, REG_RDX); - host_x86_POP(block, REG_RAX); - host_x86_MOVZX_REG_ABS_32_8(block, REG_ESI, &cpu_state.abrt); - host_x86_RET(block); + *branch_offset = (uint8_t) ((uintptr_t) &block_write_data[block_pos] - (uintptr_t) branch_offset) - 1; + if (size != 1) + *misaligned_offset = (uint8_t) ((uintptr_t) &block_write_data[block_pos] - (uintptr_t) misaligned_offset) - 1; + host_x86_PUSH(block, REG_RAX); + host_x86_PUSH(block, REG_RDX); +# if _WIN64 + host_x86_SUB64_REG_IMM(block, REG_RSP, 0x20); + // host_x86_MOV32_REG_REG(block, REG_ECX, uop->imm_data); +# else + host_x86_MOV32_REG_REG(block, REG_EDI, REG_ECX); +# endif + if (size == 1 && !is_float) { + host_x86_CALL(block, (void *) readmembl); + host_x86_MOVZX_REG_32_8(block, REG_ECX, REG_EAX); + } else if (size == 2 && !is_float) { + host_x86_CALL(block, (void *) readmemwl); + host_x86_MOVZX_REG_32_16(block, REG_ECX, REG_EAX); + } else if (size == 4 && !is_float) { + host_x86_CALL(block, (void *) readmemll); + host_x86_MOV32_REG_REG(block, REG_ECX, REG_EAX); + } else if (size == 4 && is_float) { + host_x86_CALL(block, (void *) readmemll); + host_x86_MOVD_XREG_REG(block, REG_XMM_TEMP, REG_EAX); + host_x86_CVTSS2SD_XREG_XREG(block, REG_XMM_TEMP, REG_XMM_TEMP); + } else if (size == 8) { + host_x86_CALL(block, (void *) readmemql); + host_x86_MOVQ_XREG_REG(block, REG_XMM_TEMP, REG_RAX); + } +# if _WIN64 + host_x86_ADD64_REG_IMM(block, REG_RSP, 0x20); +# endif + host_x86_POP(block, REG_RDX); + host_x86_POP(block, REG_RAX); + host_x86_MOVZX_REG_ABS_32_8(block, REG_ESI, &cpu_state.abrt); + host_x86_RET(block); } -static void build_store_routine(codeblock_t *block, int size, int is_float) +static void +build_store_routine(codeblock_t *block, int size, int is_float) { - uint8_t *branch_offset; - uint8_t *misaligned_offset; + uint8_t *branch_offset; + uint8_t *misaligned_offset; - /*In - ECX = data, ESI = address - Out - ESI = abrt - Corrupts EDI*/ - /*MOV EDI, ESI - SHR ESI, 12 - MOV ESI, [writelookup2+ESI*4] - CMP ESI, -1 - JNZ + - MOV [RSI+RDI], ECX - XOR ESI,ESI - RET - * PUSH EAX - PUSH EDX - PUSH ECX - CALL writemembl - POP ECX - POP EDX - POP EAX - MOVZX ECX, AL - RET - */ - host_x86_MOV32_REG_REG(block, REG_EDI, REG_ESI); - host_x86_SHR32_IMM(block, REG_ESI, 12); - host_x86_MOV64_REG_IMM(block, REG_R8, (uint64_t)(uintptr_t)writelookup2); - host_x86_MOV64_REG_BASE_INDEX_SHIFT(block, REG_RSI, REG_R8, REG_RSI, 3); - if (size != 1) - { - host_x86_TEST32_REG_IMM(block, REG_EDI, size-1); - misaligned_offset = host_x86_JNZ_short(block); - } - host_x86_CMP64_REG_IMM(block, REG_RSI, (uint32_t)-1); - branch_offset = host_x86_JZ_short(block); - if (size == 1 && !is_float) - host_x86_MOV8_BASE_INDEX_REG(block, REG_RSI, REG_RDI, REG_ECX); - else if (size == 2 && !is_float) - host_x86_MOV16_BASE_INDEX_REG(block, REG_RSI, REG_RDI, REG_ECX); - else if (size == 4 && !is_float) - host_x86_MOV32_BASE_INDEX_REG(block, REG_RSI, REG_RDI, REG_ECX); - else if (size == 4 && is_float) - host_x86_MOVD_BASE_INDEX_XREG(block, REG_RSI, REG_RDI, REG_XMM_TEMP); - else if (size == 8) - host_x86_MOVQ_BASE_INDEX_XREG(block, REG_RSI, REG_RDI, REG_XMM_TEMP); - else - fatal("build_store_routine: size=%i\n", size); - host_x86_XOR32_REG_REG(block, REG_ESI, REG_ESI); - host_x86_RET(block); + /*In - ECX = data, ESI = address + Out - ESI = abrt + Corrupts EDI*/ + /*MOV EDI, ESI + SHR ESI, 12 + MOV ESI, [writelookup2+ESI*4] + CMP ESI, -1 + JNZ + + MOV [RSI+RDI], ECX + XOR ESI,ESI + RET + * PUSH EAX + PUSH EDX + PUSH ECX + CALL writemembl + POP ECX + POP EDX + POP EAX + MOVZX ECX, AL + RET + */ + host_x86_MOV32_REG_REG(block, REG_EDI, REG_ESI); + host_x86_SHR32_IMM(block, REG_ESI, 12); + host_x86_MOV64_REG_IMM(block, REG_R8, (uint64_t) (uintptr_t) writelookup2); + host_x86_MOV64_REG_BASE_INDEX_SHIFT(block, REG_RSI, REG_R8, REG_RSI, 3); + if (size != 1) { + host_x86_TEST32_REG_IMM(block, REG_EDI, size - 1); + misaligned_offset = host_x86_JNZ_short(block); + } + host_x86_CMP64_REG_IMM(block, REG_RSI, (uint32_t) -1); + branch_offset = host_x86_JZ_short(block); + if (size == 1 && !is_float) + host_x86_MOV8_BASE_INDEX_REG(block, REG_RSI, REG_RDI, REG_ECX); + else if (size == 2 && !is_float) + host_x86_MOV16_BASE_INDEX_REG(block, REG_RSI, REG_RDI, REG_ECX); + else if (size == 4 && !is_float) + host_x86_MOV32_BASE_INDEX_REG(block, REG_RSI, REG_RDI, REG_ECX); + else if (size == 4 && is_float) + host_x86_MOVD_BASE_INDEX_XREG(block, REG_RSI, REG_RDI, REG_XMM_TEMP); + else if (size == 8) + host_x86_MOVQ_BASE_INDEX_XREG(block, REG_RSI, REG_RDI, REG_XMM_TEMP); + else + fatal("build_store_routine: size=%i\n", size); + host_x86_XOR32_REG_REG(block, REG_ESI, REG_ESI); + host_x86_RET(block); - *branch_offset = (uint8_t)((uintptr_t)&block_write_data[block_pos] - (uintptr_t)branch_offset) - 1; - if (size != 1) - *misaligned_offset = (uint8_t)((uintptr_t)&block_write_data[block_pos] - (uintptr_t)misaligned_offset) - 1; - host_x86_PUSH(block, REG_RAX); - host_x86_PUSH(block, REG_RDX); -#if _WIN64 - host_x86_SUB64_REG_IMM(block, REG_RSP, 0x28); - if (size == 4 && is_float) - host_x86_MOVD_REG_XREG(block, REG_EDX, REG_XMM_TEMP); //data - else if (size == 8) - host_x86_MOVQ_REG_XREG(block, REG_RDX, REG_XMM_TEMP); //data - else - host_x86_MOV32_REG_REG(block, REG_EDX, REG_ECX); //data - host_x86_MOV32_REG_REG(block, REG_ECX, REG_EDI); //address -#else - host_x86_SUB64_REG_IMM(block, REG_RSP, 0x8); - //host_x86_MOV32_REG_REG(block, REG_EDI, REG_ECX); //address - if (size == 4 && is_float) - host_x86_MOVD_REG_XREG(block, REG_ESI, REG_XMM_TEMP); //data - else if (size == 8) - host_x86_MOVQ_REG_XREG(block, REG_RSI, REG_XMM_TEMP); //data - else - host_x86_MOV32_REG_REG(block, REG_ESI, REG_ECX); //data -#endif - if (size == 1) - host_x86_CALL(block, (void *)writemembl); - else if (size == 2) - host_x86_CALL(block, (void *)writememwl); - else if (size == 4) - host_x86_CALL(block, (void *)writememll); - else if (size == 8) - host_x86_CALL(block, (void *)writememql); -#if _WIN64 - host_x86_ADD64_REG_IMM(block, REG_RSP, 0x28); -#else - host_x86_ADD64_REG_IMM(block, REG_RSP, 0x8); -#endif - host_x86_POP(block, REG_RDX); - host_x86_POP(block, REG_RAX); - host_x86_MOVZX_REG_ABS_32_8(block, REG_ESI, &cpu_state.abrt); - host_x86_RET(block); + *branch_offset = (uint8_t) ((uintptr_t) &block_write_data[block_pos] - (uintptr_t) branch_offset) - 1; + if (size != 1) + *misaligned_offset = (uint8_t) ((uintptr_t) &block_write_data[block_pos] - (uintptr_t) misaligned_offset) - 1; + host_x86_PUSH(block, REG_RAX); + host_x86_PUSH(block, REG_RDX); +# if _WIN64 + host_x86_SUB64_REG_IMM(block, REG_RSP, 0x28); + if (size == 4 && is_float) + host_x86_MOVD_REG_XREG(block, REG_EDX, REG_XMM_TEMP); // data + else if (size == 8) + host_x86_MOVQ_REG_XREG(block, REG_RDX, REG_XMM_TEMP); // data + else + host_x86_MOV32_REG_REG(block, REG_EDX, REG_ECX); // data + host_x86_MOV32_REG_REG(block, REG_ECX, REG_EDI); // address +# else + host_x86_SUB64_REG_IMM(block, REG_RSP, 0x8); + // host_x86_MOV32_REG_REG(block, REG_EDI, REG_ECX); //address + if (size == 4 && is_float) + host_x86_MOVD_REG_XREG(block, REG_ESI, REG_XMM_TEMP); // data + else if (size == 8) + host_x86_MOVQ_REG_XREG(block, REG_RSI, REG_XMM_TEMP); // data + else + host_x86_MOV32_REG_REG(block, REG_ESI, REG_ECX); // data +# endif + if (size == 1) + host_x86_CALL(block, (void *) writemembl); + else if (size == 2) + host_x86_CALL(block, (void *) writememwl); + else if (size == 4) + host_x86_CALL(block, (void *) writememll); + else if (size == 8) + host_x86_CALL(block, (void *) writememql); +# if _WIN64 + host_x86_ADD64_REG_IMM(block, REG_RSP, 0x28); +# else + host_x86_ADD64_REG_IMM(block, REG_RSP, 0x8); +# endif + host_x86_POP(block, REG_RDX); + host_x86_POP(block, REG_RAX); + host_x86_MOVZX_REG_ABS_32_8(block, REG_ESI, &cpu_state.abrt); + host_x86_RET(block); } -static void build_loadstore_routines(codeblock_t *block) +static void +build_loadstore_routines(codeblock_t *block) { - codegen_mem_load_byte = &codeblock[block_current].data[block_pos]; - build_load_routine(block, 1, 0); - codegen_mem_load_word = &codeblock[block_current].data[block_pos]; - build_load_routine(block, 2, 0); - codegen_mem_load_long = &codeblock[block_current].data[block_pos]; - build_load_routine(block, 4, 0); - codegen_mem_load_quad = &codeblock[block_current].data[block_pos]; - build_load_routine(block, 8, 0); - codegen_mem_load_single = &codeblock[block_current].data[block_pos]; - build_load_routine(block, 4, 1); - codegen_mem_load_double = &codeblock[block_current].data[block_pos]; - build_load_routine(block, 8, 1); + codegen_mem_load_byte = &codeblock[block_current].data[block_pos]; + build_load_routine(block, 1, 0); + codegen_mem_load_word = &codeblock[block_current].data[block_pos]; + build_load_routine(block, 2, 0); + codegen_mem_load_long = &codeblock[block_current].data[block_pos]; + build_load_routine(block, 4, 0); + codegen_mem_load_quad = &codeblock[block_current].data[block_pos]; + build_load_routine(block, 8, 0); + codegen_mem_load_single = &codeblock[block_current].data[block_pos]; + build_load_routine(block, 4, 1); + codegen_mem_load_double = &codeblock[block_current].data[block_pos]; + build_load_routine(block, 8, 1); - codegen_mem_store_byte = &codeblock[block_current].data[block_pos]; - build_store_routine(block, 1, 0); - codegen_mem_store_word = &codeblock[block_current].data[block_pos]; - build_store_routine(block, 2, 0); - codegen_mem_store_long = &codeblock[block_current].data[block_pos]; - build_store_routine(block, 4, 0); - codegen_mem_store_quad = &codeblock[block_current].data[block_pos]; - build_store_routine(block, 8, 0); - codegen_mem_store_single = &codeblock[block_current].data[block_pos]; - build_store_routine(block, 4, 1); - codegen_mem_store_double = &codeblock[block_current].data[block_pos]; - build_store_routine(block, 8, 1); + codegen_mem_store_byte = &codeblock[block_current].data[block_pos]; + build_store_routine(block, 1, 0); + codegen_mem_store_word = &codeblock[block_current].data[block_pos]; + build_store_routine(block, 2, 0); + codegen_mem_store_long = &codeblock[block_current].data[block_pos]; + build_store_routine(block, 4, 0); + codegen_mem_store_quad = &codeblock[block_current].data[block_pos]; + build_store_routine(block, 8, 0); + codegen_mem_store_single = &codeblock[block_current].data[block_pos]; + build_store_routine(block, 4, 1); + codegen_mem_store_double = &codeblock[block_current].data[block_pos]; + build_store_routine(block, 8, 1); } -void codegen_backend_init() +void +codegen_backend_init(void) { - codeblock_t *block; - int c; -#if defined(__linux__) || defined(__APPLE__) - void *start; - size_t len; - long pagesize = sysconf(_SC_PAGESIZE); - long pagemask = ~(pagesize - 1); -#endif + codeblock_t *block; + int c; - codeblock = malloc(BLOCK_SIZE * sizeof(codeblock_t)); - codeblock_hash = malloc(HASH_SIZE * sizeof(codeblock_t *)); + codeblock = malloc(BLOCK_SIZE * sizeof(codeblock_t)); + codeblock_hash = malloc(HASH_SIZE * sizeof(codeblock_t *)); - memset(codeblock, 0, BLOCK_SIZE * sizeof(codeblock_t)); - memset(codeblock_hash, 0, HASH_SIZE * sizeof(codeblock_t *)); + memset(codeblock, 0, BLOCK_SIZE * sizeof(codeblock_t)); + memset(codeblock_hash, 0, HASH_SIZE * sizeof(codeblock_t *)); - for (c = 0; c < BLOCK_SIZE; c++) - codeblock[c].pc = BLOCK_PC_INVALID; + for (c = 0; c < BLOCK_SIZE; c++) + codeblock[c].pc = BLOCK_PC_INVALID; - block_current = 0; - block_pos = 0; - block = &codeblock[block_current]; - codeblock[block_current].head_mem_block = codegen_allocator_allocate(NULL, block_current); - codeblock[block_current].data = codeblock_allocator_get_ptr(codeblock[block_current].head_mem_block); - block_write_data = codeblock[block_current].data; - build_loadstore_routines(&codeblock[block_current]); + block_current = 0; + block_pos = 0; + block = &codeblock[block_current]; + codeblock[block_current].head_mem_block = codegen_allocator_allocate(NULL, block_current); + codeblock[block_current].data = codeblock_allocator_get_ptr(codeblock[block_current].head_mem_block); + block_write_data = codeblock[block_current].data; + build_loadstore_routines(&codeblock[block_current]); - codegen_gpf_rout = &codeblock[block_current].data[block_pos]; -#if _WIN64 - host_x86_XOR32_REG_REG(block, REG_ECX, REG_ECX); - host_x86_XOR32_REG_REG(block, REG_EDX, REG_EDX); -#else - host_x86_XOR32_REG_REG(block, REG_EDI, REG_EDI); - host_x86_XOR32_REG_REG(block, REG_ESI, REG_ESI); -#endif - host_x86_CALL(block, (void *)x86gpf); - codegen_exit_rout = &codeblock[block_current].data[block_pos]; - host_x86_ADD64_REG_IMM(block, REG_RSP, 0x38); - host_x86_POP(block, REG_R15); - host_x86_POP(block, REG_R14); - host_x86_POP(block, REG_R13); - host_x86_POP(block, REG_R12); - host_x86_POP(block, REG_RDI); - host_x86_POP(block, REG_RSI); - host_x86_POP(block, REG_RBP); - host_x86_POP(block, REG_RDX); - host_x86_RET(block); + codegen_gpf_rout = &codeblock[block_current].data[block_pos]; +# if _WIN64 + host_x86_XOR32_REG_REG(block, REG_ECX, REG_ECX); + host_x86_XOR32_REG_REG(block, REG_EDX, REG_EDX); +# else + host_x86_XOR32_REG_REG(block, REG_EDI, REG_EDI); + host_x86_XOR32_REG_REG(block, REG_ESI, REG_ESI); +# endif + host_x86_CALL(block, (void *) x86gpf); + codegen_exit_rout = &codeblock[block_current].data[block_pos]; + host_x86_ADD64_REG_IMM(block, REG_RSP, 0x38); + host_x86_POP(block, REG_R15); + host_x86_POP(block, REG_R14); + host_x86_POP(block, REG_R13); + host_x86_POP(block, REG_R12); + host_x86_POP(block, REG_RDI); + host_x86_POP(block, REG_RSI); + host_x86_POP(block, REG_RBP); + host_x86_POP(block, REG_RDX); + host_x86_RET(block); - block_write_data = NULL; + block_write_data = NULL; - asm( - "stmxcsr %0\n" - : "=m" (cpu_state.old_fp_control) - ); - cpu_state.trunc_fp_control = cpu_state.old_fp_control | 0x6000; + asm( + "stmxcsr %0\n" + : "=m"(cpu_state.old_fp_control)); + cpu_state.trunc_fp_control = cpu_state.old_fp_control | 0x6000; } -void codegen_set_rounding_mode(int mode) +void +codegen_set_rounding_mode(int mode) { - cpu_state.new_fp_control = (cpu_state.old_fp_control & ~0x6000) | (mode << 13); + cpu_state.new_fp_control = (cpu_state.old_fp_control & ~0x6000) | (mode << 13); } -void codegen_backend_prologue(codeblock_t *block) +void +codegen_backend_prologue(codeblock_t *block) { - block_pos = BLOCK_START; /*Entry code*/ - host_x86_PUSH(block, REG_RBX); - host_x86_PUSH(block, REG_RBP); - host_x86_PUSH(block, REG_RSI); - host_x86_PUSH(block, REG_RDI); - host_x86_PUSH(block, REG_R12); - host_x86_PUSH(block, REG_R13); - host_x86_PUSH(block, REG_R14); - host_x86_PUSH(block, REG_R15); - host_x86_SUB64_REG_IMM(block, REG_RSP, 0x38); - host_x86_MOV64_REG_IMM(block, REG_RBP, ((uintptr_t)&cpu_state) + 128); - if (block->flags & CODEBLOCK_HAS_FPU) - { - host_x86_MOV32_REG_ABS(block, REG_EAX, &cpu_state.TOP); - host_x86_SUB32_REG_IMM(block, REG_EAX, block->TOP); - host_x86_MOV32_BASE_OFFSET_REG(block, REG_RSP, IREG_TOP_diff_stack_offset, REG_EAX); - } - if (block->flags & CODEBLOCK_NO_IMMEDIATES) - host_x86_MOV64_REG_IMM(block, REG_R12, (uintptr_t)ram); + block_pos = BLOCK_START; /*Entry code*/ + host_x86_PUSH(block, REG_RBX); + host_x86_PUSH(block, REG_RBP); + host_x86_PUSH(block, REG_RSI); + host_x86_PUSH(block, REG_RDI); + host_x86_PUSH(block, REG_R12); + host_x86_PUSH(block, REG_R13); + host_x86_PUSH(block, REG_R14); + host_x86_PUSH(block, REG_R15); + host_x86_SUB64_REG_IMM(block, REG_RSP, 0x38); + host_x86_MOV64_REG_IMM(block, REG_RBP, ((uintptr_t) &cpu_state) + 128); + if (block->flags & CODEBLOCK_HAS_FPU) { + host_x86_MOV32_REG_ABS(block, REG_EAX, &cpu_state.TOP); + host_x86_SUB32_REG_IMM(block, REG_EAX, block->TOP); + host_x86_MOV32_BASE_OFFSET_REG(block, REG_RSP, IREG_TOP_diff_stack_offset, REG_EAX); + } + if (block->flags & CODEBLOCK_NO_IMMEDIATES) + host_x86_MOV64_REG_IMM(block, REG_R12, (uintptr_t) ram); } -void codegen_backend_epilogue(codeblock_t *block) +void +codegen_backend_epilogue(codeblock_t *block) { - host_x86_ADD64_REG_IMM(block, REG_RSP, 0x38); - host_x86_POP(block, REG_R15); - host_x86_POP(block, REG_R14); - host_x86_POP(block, REG_R13); - host_x86_POP(block, REG_R12); - host_x86_POP(block, REG_RDI); - host_x86_POP(block, REG_RSI); - host_x86_POP(block, REG_RBP); - host_x86_POP(block, REG_RDX); - host_x86_RET(block); + host_x86_ADD64_REG_IMM(block, REG_RSP, 0x38); + host_x86_POP(block, REG_R15); + host_x86_POP(block, REG_R14); + host_x86_POP(block, REG_R13); + host_x86_POP(block, REG_R12); + host_x86_POP(block, REG_RDI); + host_x86_POP(block, REG_RSI); + host_x86_POP(block, REG_RBP); + host_x86_POP(block, REG_RDX); + host_x86_RET(block); } #endif diff --git a/src/codegen_new/codegen_backend_x86-64.h b/src/codegen_new/codegen_backend_x86-64.h index ccc526b30..5f476010d 100644 --- a/src/codegen_new/codegen_backend_x86-64.h +++ b/src/codegen_new/codegen_backend_x86-64.h @@ -1,14 +1,14 @@ #include "codegen_backend_x86-64_defs.h" -#define BLOCK_SIZE 0x4000 -#define BLOCK_MASK 0x3fff +#define BLOCK_SIZE 0x4000 +#define BLOCK_MASK 0x3fff #define BLOCK_START 0 -#define HASH_SIZE 0x20000 -#define HASH_MASK 0x1ffff +#define HASH_SIZE 0x20000 +#define HASH_MASK 0x1ffff -#define HASH(l) ((l) & 0x1ffff) +#define HASH(l) ((l) &0x1ffff) -#define BLOCK_MAX 0x3c0 +#define BLOCK_MAX 0x3c0 #define CODEGEN_BACKEND_HAS_MOV_IMM diff --git a/src/codegen_new/codegen_backend_x86-64_defs.h b/src/codegen_new/codegen_backend_x86-64_defs.h index 8955773cd..12f05f01c 100644 --- a/src/codegen_new/codegen_backend_x86-64_defs.h +++ b/src/codegen_new/codegen_backend_x86-64_defs.h @@ -1,52 +1,52 @@ /*RBP = cpu_state + 128 R12 = ram (if block->flags & CODEBLOCK_NO_IMMEDIATES)*/ -#define REG_AX 0 -#define REG_CX 1 -#define REG_DX 2 -#define REG_BX 3 -#define REG_SP 4 -#define REG_BP 5 -#define REG_SI 6 -#define REG_DI 7 +#define REG_AX 0 +#define REG_CX 1 +#define REG_DX 2 +#define REG_BX 3 +#define REG_SP 4 +#define REG_BP 5 +#define REG_SI 6 +#define REG_DI 7 -#define REG_EAX 0 -#define REG_ECX 1 -#define REG_EDX 2 -#define REG_EBX 3 -#define REG_ESP 4 -#define REG_EBP 5 -#define REG_ESI 6 -#define REG_EDI 7 +#define REG_EAX 0 +#define REG_ECX 1 +#define REG_EDX 2 +#define REG_EBX 3 +#define REG_ESP 4 +#define REG_EBP 5 +#define REG_ESI 6 +#define REG_EDI 7 -#define REG_RAX 0 -#define REG_RCX 1 -#define REG_RDX 2 -#define REG_RBX 3 -#define REG_RSP 4 -#define REG_RBP 5 -#define REG_RSI 6 -#define REG_RDI 7 -#define REG_R8 8 -#define REG_R9 9 -#define REG_R10 10 -#define REG_R11 11 -#define REG_R12 12 -#define REG_R13 13 -#define REG_R14 14 -#define REG_R15 15 +#define REG_RAX 0 +#define REG_RCX 1 +#define REG_RDX 2 +#define REG_RBX 3 +#define REG_RSP 4 +#define REG_RBP 5 +#define REG_RSI 6 +#define REG_RDI 7 +#define REG_R8 8 +#define REG_R9 9 +#define REG_R10 10 +#define REG_R11 11 +#define REG_R12 12 +#define REG_R13 13 +#define REG_R14 14 +#define REG_R15 15 -#define REG_XMM0 0 -#define REG_XMM1 1 -#define REG_XMM2 2 -#define REG_XMM3 3 -#define REG_XMM4 4 -#define REG_XMM5 5 -#define REG_XMM6 6 -#define REG_XMM7 7 +#define REG_XMM0 0 +#define REG_XMM1 1 +#define REG_XMM2 2 +#define REG_XMM3 3 +#define REG_XMM4 4 +#define REG_XMM5 5 +#define REG_XMM6 6 +#define REG_XMM7 7 -#define REG_XMM_TEMP REG_XMM0 +#define REG_XMM_TEMP REG_XMM0 -#define CODEGEN_HOST_REGS 3 +#define CODEGEN_HOST_REGS 3 #define CODEGEN_HOST_FP_REGS 7 extern void *codegen_mem_load_byte; diff --git a/src/codegen_new/codegen_backend_x86-64_ops.c b/src/codegen_new/codegen_backend_x86-64_ops.c index 784bfa03d..236a86ce7 100644 --- a/src/codegen_new/codegen_backend_x86-64_ops.c +++ b/src/codegen_new/codegen_backend_x86-64_ops.c @@ -1,1831 +1,1770 @@ #if defined __amd64__ || defined _M_X64 -#include -#include <86box/86box.h> -#include "cpu.h" -#include <86box/mem.h> +# include +# include +# include <86box/86box.h> +# include "cpu.h" +# include <86box/mem.h> +# include <86box/plat_unused.h> -#include "codegen.h" -#include "codegen_allocator.h" -#include "codegen_backend.h" -#include "codegen_backend_x86-64_defs.h" -#include "codegen_backend_x86-64_ops.h" -#include "codegen_backend_x86-64_ops_helpers.h" +# include "codegen.h" +# include "codegen_allocator.h" +# include "codegen_backend.h" +# include "codegen_backend_x86-64_defs.h" +# include "codegen_backend_x86-64_ops.h" +# include "codegen_backend_x86-64_ops_helpers.h" -#define RM_OP_ADD 0x00 -#define RM_OP_OR 0x08 -#define RM_OP_AND 0x20 -#define RM_OP_SUB 0x28 -#define RM_OP_XOR 0x30 -#define RM_OP_CMP 0x38 +# define RM_OP_ADD 0x00 +# define RM_OP_OR 0x08 +# define RM_OP_AND 0x20 +# define RM_OP_SUB 0x28 +# define RM_OP_XOR 0x30 +# define RM_OP_CMP 0x38 -#define RM_OP_ROL 0x00 -#define RM_OP_ROR 0x08 -#define RM_OP_SHL 0x20 -#define RM_OP_SHR 0x28 -#define RM_OP_SAR 0x38 +# define RM_OP_ROL 0x00 +# define RM_OP_ROR 0x08 +# define RM_OP_SHL 0x20 +# define RM_OP_SHR 0x28 +# define RM_OP_SAR 0x38 -static inline void call(codeblock_t *block, uintptr_t func) +static inline void +call(codeblock_t *block, uintptr_t func) { - uintptr_t diff; + intptr_t diff; - codegen_alloc_bytes(block, 5); - diff = func - (uintptr_t)&block_write_data[block_pos + 5]; + codegen_alloc_bytes(block, 5); + diff = (intptr_t) (func - (uintptr_t) &block_write_data[block_pos + 5]); - if (diff >= -0x80000000 && diff < 0x7fffffff) - { - codegen_addbyte(block, 0xE8); /*CALL*/ - codegen_addlong(block, (uint32_t)diff); - } - else - { - codegen_alloc_bytes(block, 13); - codegen_addbyte2(block, 0x49, 0xb9); /*MOV R9, func*/ - codegen_addquad(block, func); - codegen_addbyte3(block, 0x41, 0xff, 0xd1); /*CALL R9*/ - } + if (diff >= -0x80000000LL && diff < 0x7fffffffLL) { + codegen_addbyte(block, 0xE8); /*CALL*/ + codegen_addlong(block, (uint32_t) diff); + } else { + codegen_alloc_bytes(block, 13); + codegen_addbyte2(block, 0x49, 0xb9); /*MOV R9, func*/ + codegen_addquad(block, func); + codegen_addbyte3(block, 0x41, 0xff, 0xd1); /*CALL R9*/ + } } -static inline void jmp(codeblock_t *block, uintptr_t func) +static inline void +jmp(codeblock_t *block, uintptr_t func) { - uintptr_t diff; + intptr_t diff; - codegen_alloc_bytes(block, 5); - diff = func - (uintptr_t)&block_write_data[block_pos + 5]; + codegen_alloc_bytes(block, 5); + diff = (intptr_t) (func - (uintptr_t) &block_write_data[block_pos + 5]); - if (diff >= -0x80000000 && diff < 0x7fffffff) - { - codegen_addbyte(block, 0xe9); /*JMP*/ - codegen_addlong(block, (uint32_t)diff); - } - else - { - codegen_alloc_bytes(block, 13); - codegen_addbyte2(block, 0x49, 0xb9); /*MOV R9, func*/ - codegen_addquad(block, func); - codegen_addbyte3(block, 0x41, 0xff, 0xe1); /*JMP R9*/ - } + if (diff >= -0x80000000LL && diff < 0x7fffffffLL) { + codegen_addbyte(block, 0xe9); /*JMP*/ + codegen_addlong(block, (uint32_t) diff); + } else { + codegen_alloc_bytes(block, 13); + codegen_addbyte2(block, 0x49, 0xb9); /*MOV R9, func*/ + codegen_addquad(block, func); + codegen_addbyte3(block, 0x41, 0xff, 0xe1); /*JMP R9*/ + } } -void host_x86_ADD8_REG_IMM(codeblock_t *block, int dst_reg, uint8_t imm_data) +void +host_x86_ADD8_REG_IMM(codeblock_t *block, int dst_reg, uint8_t imm_data) { - if (dst_reg & 8) - fatal("host_x86_ADD8_REG_IMM - dst_reg & 8\n"); - - if (dst_reg == REG_EAX) - { - codegen_alloc_bytes(block, 2); - codegen_addbyte2(block, 0x04, imm_data); /*ADD EAX, imm_data*/ - } - else - { - codegen_alloc_bytes(block, 3); - codegen_addbyte3(block, 0x80, 0xc0 | RM_OP_ADD | (dst_reg & 7), imm_data); /*ADD dst_reg, imm_data*/ - } -} -void host_x86_ADD16_REG_IMM(codeblock_t *block, int dst_reg, uint16_t imm_data) -{ - if (dst_reg & 8) - fatal("host_x86_ADD16_REG_IMM - dst_reg & 8\n"); - - if (is_imm8(imm_data)) - { - codegen_alloc_bytes(block, 4); - codegen_addbyte4(block, 0x66, 0x83, 0xc0 | RM_OP_ADD | (dst_reg & 7), imm_data & 0xff); /*ADD dst_reg, imm_data*/ - } - else if (dst_reg == REG_EAX) - { - codegen_alloc_bytes(block, 4); - codegen_addbyte2(block, 0x66, 0x05); /*AND AX, imm_data*/ - codegen_addword(block, imm_data); - } - else - { - codegen_alloc_bytes(block, 5); - codegen_addbyte3(block, 0x66, 0x81, 0xc0 | RM_OP_ADD | (dst_reg & 7)); /*ADD dst_reg, imm_data*/ - codegen_addword(block, imm_data); - } -} -void host_x86_ADD32_REG_IMM(codeblock_t *block, int dst_reg, uint32_t imm_data) -{ - if (dst_reg & 8) - fatal("host_x86_ADD32_REG_IMM - dst_reg & 8\n"); - - if (is_imm8(imm_data)) - { - codegen_alloc_bytes(block, 3); - codegen_addbyte3(block, 0x83, 0xc0 | RM_OP_ADD | (dst_reg & 7), imm_data & 0xff); /*ADD dst_reg, imm_data*/ - } - else if (dst_reg == REG_EAX) - { - codegen_alloc_bytes(block, 5); - codegen_addbyte(block, 0x05); /*ADD EAX, imm_data*/ - codegen_addlong(block, imm_data); - } - else - { - codegen_alloc_bytes(block, 6); - codegen_addbyte2(block, 0x81, 0xc0 | RM_OP_ADD | (dst_reg & 7)); /*ADD dst_reg, imm_data*/ - codegen_addlong(block, imm_data); - } -} -void host_x86_ADD64_REG_IMM(codeblock_t *block, int dst_reg, uint64_t imm_data) -{ - if (dst_reg & 8) - fatal("host_x86_ADD64_REG_IMM - dst_reg & 8\n"); - - if (is_imm8(imm_data)) - { - codegen_alloc_bytes(block, 4); - codegen_addbyte4(block, 0x48, 0x83, 0xc0 | RM_OP_ADD | (dst_reg & 7), imm_data & 0xff); /*ADD dst_reg, imm_data*/ - } - else - fatal("ADD64_REG_IMM !is_imm8 %016llx\n", imm_data); -} -void host_x86_ADD8_REG_REG(codeblock_t *block, int dst_reg, int src_reg) -{ - if ((dst_reg & 8) || (src_reg & 8)) - fatal("host_x86_ADD8_REG_REG - dst_reg & 8\n"); + if (dst_reg & 8) + fatal("host_x86_ADD8_REG_IMM - dst_reg & 8\n"); + if (dst_reg == REG_EAX) { codegen_alloc_bytes(block, 2); - codegen_addbyte2(block, 0x00, 0xc0 | (dst_reg & 7) | ((src_reg & 7) << 3)); /*ADD dst_reg, src_reg*/ -} -void host_x86_ADD16_REG_REG(codeblock_t *block, int dst_reg, int src_reg) -{ - if ((dst_reg & 8) || (src_reg & 8)) - fatal("host_x86_ADD16_REG_REG - dst_reg & 8\n"); - + codegen_addbyte2(block, 0x04, imm_data); /*ADD EAX, imm_data*/ + } else { codegen_alloc_bytes(block, 3); - codegen_addbyte3(block, 0x66, 0x01, 0xc0 | (dst_reg & 7) | ((src_reg & 7) << 3)); /*ADD dst_reg, src_reg*/ + codegen_addbyte3(block, 0x80, 0xc0 | RM_OP_ADD | (dst_reg & 7), imm_data); /*ADD dst_reg, imm_data*/ + } } -void host_x86_ADD32_REG_REG(codeblock_t *block, int dst_reg, int src_reg) +void +host_x86_ADD16_REG_IMM(codeblock_t *block, int dst_reg, uint16_t imm_data) { - if ((dst_reg & 8) || (src_reg & 8)) - fatal("host_x86_ADD32_REG_REG - dst_reg & 8\n"); + if (dst_reg & 8) + fatal("host_x86_ADD16_REG_IMM - dst_reg & 8\n"); - codegen_alloc_bytes(block, 2); - codegen_addbyte2(block, 0x01, 0xc0 | (dst_reg & 7) | ((src_reg & 7) << 3)); /*ADD dst_reg, src_reg*/ -} - -void host_x86_AND8_REG_IMM(codeblock_t *block, int dst_reg, uint8_t imm_data) -{ - if (dst_reg & 8) - fatal("host_x86_AND8_REG_IMM - dst_reg & 8\n"); - - if (dst_reg == REG_EAX) - { - codegen_alloc_bytes(block, 2); - codegen_addbyte2(block, 0x24, imm_data); /*AND EAX, imm_data*/ - } - else - { - codegen_alloc_bytes(block, 3); - codegen_addbyte3(block, 0x80, 0xc0 | RM_OP_AND | (dst_reg & 7), imm_data); /*AND dst_reg, imm_data*/ - } -} -void host_x86_AND16_REG_IMM(codeblock_t *block, int dst_reg, uint16_t imm_data) -{ - if (dst_reg & 8) - fatal("host_x86_AND16_REG_IMM - dst_reg & 8\n"); - - if (is_imm8(imm_data)) - { - codegen_alloc_bytes(block, 4); - codegen_addbyte4(block, 0x66, 0x83, 0xc0 | RM_OP_AND | (dst_reg & 7), imm_data & 0xff); /*AND dst_reg, imm_data*/ - } - else if (dst_reg == REG_EAX) - { - codegen_alloc_bytes(block, 4); - codegen_addbyte2(block, 0x66, 0x25); /*AND AX, imm_data*/ - codegen_addword(block, imm_data); - } - else - { - codegen_alloc_bytes(block, 5); - codegen_addbyte3(block, 0x66, 0x81, 0xc0 | RM_OP_AND | (dst_reg & 7)); /*AND dst_reg, imm_data*/ - codegen_addword(block, imm_data); - } -} -void host_x86_AND32_REG_IMM(codeblock_t *block, int dst_reg, uint32_t imm_data) -{ - if (dst_reg & 8) - fatal("host_x86_AND32_REG_IMM - dst_reg & 8\n"); - - if (is_imm8(imm_data)) - { - codegen_alloc_bytes(block, 3); - codegen_addbyte3(block, 0x83, 0xc0 | RM_OP_AND | (dst_reg & 7), imm_data & 0xff); /*AND dst_reg, imm_data*/ - } - else if (dst_reg == REG_EAX) - { - codegen_alloc_bytes(block, 5); - codegen_addbyte(block, 0x25); /*AND EAX, imm_data*/ - codegen_addlong(block, imm_data); - } - else - { - codegen_alloc_bytes(block, 6); - codegen_addbyte2(block, 0x81, 0xc0 | RM_OP_AND | (dst_reg & 7)); /*AND dst_reg, imm_data*/ - codegen_addlong(block, imm_data); - } -} -void host_x86_AND8_REG_REG(codeblock_t *block, int dst_reg, int src_reg) -{ - if ((dst_reg & 8) || (src_reg & 8)) - fatal("host_x86_AND8_REG_REG - dst_reg & 8\n"); - - codegen_alloc_bytes(block, 2); - codegen_addbyte2(block, 0x20, 0xc0 | (dst_reg & 7) | ((src_reg & 7) << 3)); /*AND dst_reg, src_reg*/ -} -void host_x86_AND16_REG_REG(codeblock_t *block, int dst_reg, int src_reg) -{ - if ((dst_reg & 8) || (src_reg & 8)) - fatal("host_x86_AND16_REG_REG - dst_reg & 8\n"); - - codegen_alloc_bytes(block, 3); - codegen_addbyte3(block, 0x66, 0x21, 0xc0 | (dst_reg & 7) | ((src_reg & 7) << 3)); /*AND dst_reg, src_reg*/ -} -void host_x86_AND32_REG_REG(codeblock_t *block, int dst_reg, int src_reg) -{ - if ((dst_reg & 8) || (src_reg & 8)) - fatal("host_x86_AND32_REG_REG - dst_reg & 8\n"); - - codegen_alloc_bytes(block, 2); - codegen_addbyte2(block, 0x21, 0xc0 | (dst_reg & 7) | ((src_reg & 7) << 3)); /*AND dst_reg, src_reg*/ -} - -void host_x86_CALL(codeblock_t *block, void *p) -{ - call(block, (uintptr_t)p); -} - -void host_x86_CMP16_REG_IMM(codeblock_t *block, int dst_reg, uint16_t imm_data) -{ - if (is_imm8(imm_data)) - { - codegen_alloc_bytes(block, 4); - codegen_addbyte4(block, 0x66, 0x83, 0xc0 | RM_OP_CMP | dst_reg, imm_data & 0xff); /*CMP dst_reg, imm_data*/ - } - else if (dst_reg == REG_EAX) - { - codegen_alloc_bytes(block, 4); - codegen_addbyte2(block, 0x66, 0x3d); /*CMP AX, imm_data*/ - codegen_addword(block, imm_data); - } - else - { - codegen_alloc_bytes(block, 5); - codegen_addbyte3(block, 0x66, 0x81, 0xc0 | RM_OP_CMP | dst_reg); /*CMP dst_reg, imm_data*/ - codegen_addword(block, imm_data); - } -} -void host_x86_CMP32_REG_IMM(codeblock_t *block, int dst_reg, uint32_t imm_data) -{ - if (is_imm8(imm_data)) - { - codegen_alloc_bytes(block, 3); - codegen_addbyte3(block, 0x83, 0xc0 | RM_OP_CMP | dst_reg, imm_data & 0xff); /*CMP dst_reg, imm_data*/ - } - else if (dst_reg == REG_EAX) - { - codegen_alloc_bytes(block, 5); - codegen_addbyte(block, 0x3d); /*CMP EAX, imm_data*/ - codegen_addlong(block, imm_data); - } - else - { - codegen_alloc_bytes(block, 6); - codegen_addbyte2(block, 0x81, 0xc0 | RM_OP_CMP | dst_reg); /*CMP dst_reg, imm_data*/ - codegen_addlong(block, imm_data); - } -} -void host_x86_CMP64_REG_IMM(codeblock_t *block, int dst_reg, uint64_t imm_data) -{ - if (is_imm8(imm_data)) - { - codegen_alloc_bytes(block, 4); - codegen_addbyte4(block, 0x48, 0x83, 0xc0 | RM_OP_CMP | dst_reg, imm_data & 0xff); /*CMP dst_reg, imm_data*/ - } - else - fatal("CMP64_REG_IMM not 8-bit imm\n"); -} - -void host_x86_CMP8_REG_REG(codeblock_t *block, int src_reg_a, int src_reg_b) -{ - codegen_alloc_bytes(block, 2); - codegen_addbyte2(block, 0x38, 0xc0 | src_reg_a | (src_reg_b << 3)); /*CMP src_reg_a, src_reg_b*/ -} -void host_x86_CMP16_REG_REG(codeblock_t *block, int src_reg_a, int src_reg_b) -{ - codegen_alloc_bytes(block, 3); - codegen_addbyte3(block, 0x66, 0x39, 0xc0 | src_reg_a | (src_reg_b << 3)); /*CMP src_reg_a, src_reg_b*/ -} -void host_x86_CMP32_REG_REG(codeblock_t *block, int src_reg_a, int src_reg_b) -{ - codegen_alloc_bytes(block, 2); - codegen_addbyte2(block, 0x39, 0xc0 | src_reg_a | (src_reg_b << 3)); /*CMP src_reg_a, src_reg_b*/ -} - -void host_x86_JMP(codeblock_t *block, void *p) -{ - jmp(block, (uintptr_t)p); -} - -void host_x86_JNZ(codeblock_t *block, void *p) -{ - codegen_alloc_bytes(block, 6); - codegen_addbyte2(block, 0x0f, 0x85); /*JNZ*/ - codegen_addlong(block, (uintptr_t)p - (uintptr_t)&block_write_data[block_pos + 4]); -} -void host_x86_JZ(codeblock_t *block, void *p) -{ - codegen_alloc_bytes(block, 6); - codegen_addbyte2(block, 0x0f, 0x84); /*JZ*/ - codegen_addlong(block, (uintptr_t)p - (uintptr_t)&block_write_data[block_pos + 4]); -} - -uint8_t *host_x86_JNZ_short(codeblock_t *block) -{ - codegen_alloc_bytes(block, 2); - codegen_addbyte2(block, 0x75, 0); /*JNZ*/ - return &block_write_data[block_pos-1]; -} -uint8_t *host_x86_JS_short(codeblock_t *block) -{ - codegen_alloc_bytes(block, 2); - codegen_addbyte2(block, 0x78, 0); /*JS*/ - return &block_write_data[block_pos-1]; -} -uint8_t *host_x86_JZ_short(codeblock_t *block) -{ - codegen_alloc_bytes(block, 2); - codegen_addbyte2(block, 0x74, 0); /*JZ*/ - return &block_write_data[block_pos-1]; -} - -uint32_t *host_x86_JNB_long(codeblock_t *block) -{ - codegen_alloc_bytes(block, 6); - codegen_addbyte2(block, 0x0f, 0x83); /*JNB*/ - codegen_addlong(block, 0); - return (uint32_t *)&block_write_data[block_pos-4]; -} -uint32_t *host_x86_JNBE_long(codeblock_t *block) -{ - codegen_alloc_bytes(block, 6); - codegen_addbyte2(block, 0x0f, 0x87); /*JNBE*/ - codegen_addlong(block, 0); - return (uint32_t *)&block_write_data[block_pos-4]; -} -uint32_t *host_x86_JNL_long(codeblock_t *block) -{ - codegen_alloc_bytes(block, 6); - codegen_addbyte2(block, 0x0f, 0x8d); /*JNL*/ - codegen_addlong(block, 0); - return (uint32_t *)&block_write_data[block_pos-4]; -} -uint32_t *host_x86_JNLE_long(codeblock_t *block) -{ - codegen_alloc_bytes(block, 6); - codegen_addbyte2(block, 0x0f, 0x8f); /*JNLE*/ - codegen_addlong(block, 0); - return (uint32_t *)&block_write_data[block_pos-4]; -} -uint32_t *host_x86_JNO_long(codeblock_t *block) -{ - codegen_alloc_bytes(block, 6); - codegen_addbyte2(block, 0x0f, 0x81); /*JNO*/ - codegen_addlong(block, 0); - return (uint32_t *)&block_write_data[block_pos-4]; -} -uint32_t *host_x86_JNS_long(codeblock_t *block) -{ - codegen_alloc_bytes(block, 6); - codegen_addbyte2(block, 0x0f, 0x89); /*JNS*/ - codegen_addlong(block, 0); - return (uint32_t *)&block_write_data[block_pos-4]; -} -uint32_t *host_x86_JNZ_long(codeblock_t *block) -{ - codegen_alloc_bytes(block, 6); - codegen_addbyte2(block, 0x0f, 0x85); /*JNZ*/ - codegen_addlong(block, 0); - return (uint32_t *)&block_write_data[block_pos-4]; -} -uint32_t *host_x86_JB_long(codeblock_t *block) -{ - codegen_alloc_bytes(block, 6); - codegen_addbyte2(block, 0x0f, 0x82); /*JB*/ - codegen_addlong(block, 0); - return (uint32_t *)&block_write_data[block_pos-4]; -} -uint32_t *host_x86_JBE_long(codeblock_t *block) -{ - codegen_alloc_bytes(block, 6); - codegen_addbyte2(block, 0x0f, 0x86); /*JBE*/ - codegen_addlong(block, 0); - return (uint32_t *)&block_write_data[block_pos-4]; -} -uint32_t *host_x86_JL_long(codeblock_t *block) -{ - codegen_alloc_bytes(block, 6); - codegen_addbyte2(block, 0x0f, 0x8c); /*JL*/ - codegen_addlong(block, 0); - return (uint32_t *)&block_write_data[block_pos-4]; -} -uint32_t *host_x86_JLE_long(codeblock_t *block) -{ - codegen_alloc_bytes(block, 6); - codegen_addbyte2(block, 0x0f, 0x8e); /*JLE*/ - codegen_addlong(block, 0); - return (uint32_t *)&block_write_data[block_pos-4]; -} -uint32_t *host_x86_JO_long(codeblock_t *block) -{ - codegen_alloc_bytes(block, 6); - codegen_addbyte2(block, 0x0f, 0x80); /*JO*/ - codegen_addlong(block, 0); - return (uint32_t *)&block_write_data[block_pos-4]; -} -uint32_t *host_x86_JS_long(codeblock_t *block) -{ - codegen_alloc_bytes(block, 6); - codegen_addbyte2(block, 0x0f, 0x88); /*JS*/ - codegen_addlong(block, 0); - return (uint32_t *)&block_write_data[block_pos-4]; -} -uint32_t *host_x86_JZ_long(codeblock_t *block) -{ - codegen_alloc_bytes(block, 6); - codegen_addbyte2(block, 0x0f, 0x84); /*JZ*/ - codegen_addlong(block, 0); - return (uint32_t *)&block_write_data[block_pos-4]; -} - -void host_x86_LAHF(codeblock_t *block) -{ - codegen_alloc_bytes(block, 1); - codegen_addbyte(block, 0x9f); /*LAHF*/ -} - -void host_x86_LEA_REG_IMM(codeblock_t *block, int dst_reg, int src_reg, uint32_t offset) -{ - if (offset) - { - codegen_alloc_bytes(block, 6); - codegen_addbyte2(block, 0x8d, 0x80 | (dst_reg << 3) | src_reg); /*LEA dst_reg, [offset+src_reg]*/ - codegen_addlong(block, offset); - } - else - { - codegen_alloc_bytes(block, 2); - codegen_addbyte2(block, 0x8d, 0x00 | (dst_reg << 3) | src_reg); /*LEA dst_reg, [src_reg]*/ - } -} -void host_x86_LEA_REG_REG(codeblock_t *block, int dst_reg, int src_reg_a, int src_reg_b) -{ - if ((dst_reg & 8) || (src_reg_a & 8) || (src_reg_b & 8)) - fatal("host_x86_LEA_REG_REG - bad reg\n"); - - codegen_alloc_bytes(block, 3); - codegen_addbyte3(block, 0x8d, 0x04 | ((dst_reg & 7) << 3), /*LEA dst_reg, [Rsrc_reg_a + Rsrc_reg_b]*/ - ((src_reg_b & 7) << 3) | (src_reg_a & 7)); -} -void host_x86_LEA_REG_REG_SHIFT(codeblock_t *block, int dst_reg, int src_reg_a, int src_reg_b, int shift) -{ - if ((dst_reg & 8) || (src_reg_a & 8) || (src_reg_b & 8)) - fatal("host_x86_LEA_REG_REG_SHIFT - bad reg\n"); - - codegen_alloc_bytes(block, 3); - codegen_addbyte3(block, 0x8d, 0x04 | ((dst_reg & 7) << 3), /*LEA dst_reg, [Rsrc_reg_a + Rsrc_reg_b * (1 << shift)]*/ - (shift << 6) | ((src_reg_b & 7) << 3) | (src_reg_a & 7)); -} - -void host_x86_MOV8_ABS_IMM(codeblock_t *block, void *p, uint32_t imm_data) -{ - int64_t offset = (uintptr_t)p - (((uintptr_t)&cpu_state) + 128); - - if (offset >= -128 && offset < 127) - { - codegen_alloc_bytes(block, 4); - codegen_addbyte3(block, 0xc6, 0x45, offset); /*MOVB offset[RBP], imm_data*/ - codegen_addbyte(block, imm_data); - } - else - { - if ((uintptr_t)p >> 32) - fatal("host_x86_MOV8_ABS_IMM - out of range %p\n", p); - codegen_alloc_bytes(block, 8); - codegen_addbyte3(block, 0xc6, 0x04, 0x25); /*MOVB p, imm_data*/ - codegen_addlong(block, (uint32_t)(uintptr_t)p); - codegen_addbyte(block, imm_data); - } -} -void host_x86_MOV16_ABS_IMM(codeblock_t *block, void *p, uint16_t imm_data) -{ - int64_t offset = (uintptr_t)p - (((uintptr_t)&cpu_state) + 128); - - if (offset >= -128 && offset < 127) - { - codegen_alloc_bytes(block, 6); - codegen_addbyte4(block, 0x66, 0xc7, 0x45, offset); /*MOV offset[RBP], imm_data*/ - codegen_addword(block, imm_data); - } - else - { - if ((uintptr_t)p >> 32) - fatal("host_x86_MOV32_ABS_IMM - out of range %p\n", p); - codegen_alloc_bytes(block, 10); - codegen_addbyte4(block, 0x66, 0xc7, 0x04, 0x25); /*MOV p, imm_data*/ - codegen_addlong(block, (uint32_t)(uintptr_t)p); - codegen_addword(block, imm_data); - } -} -void host_x86_MOV32_ABS_IMM(codeblock_t *block, void *p, uint32_t imm_data) -{ - int64_t offset = (uintptr_t)p - (((uintptr_t)&cpu_state) + 128); - - if (offset >= -128 && offset < 127) - { - codegen_alloc_bytes(block, 7); - codegen_addbyte3(block, 0xc7, 0x45, offset); /*MOV offset[RBP], imm_data*/ - codegen_addlong(block, imm_data); - } - else - { - if ((uintptr_t)p >> 32) - fatal("host_x86_MOV32_ABS_IMM - out of range %p\n", p); - codegen_alloc_bytes(block, 11); - codegen_addbyte3(block, 0xc7, 0x04, 0x25); /*MOV p, imm_data*/ - codegen_addlong(block, (uint32_t)(uintptr_t)p); - codegen_addlong(block, imm_data); - } -} - -void host_x86_MOV8_ABS_REG(codeblock_t *block, void *p, int src_reg) -{ - int64_t offset = (uintptr_t)p - (((uintptr_t)&cpu_state) + 128); - - if (src_reg & 8) - fatal("host_x86_MOV8_ABS_REG - bad reg\n"); - - if (offset >= -128 && offset < 127) - { - codegen_alloc_bytes(block, 3); - codegen_addbyte3(block, 0x88, 0x45 | ((src_reg & 7) << 3), offset); /*MOVB offset[RBP], src_reg*/ - } - else - { - if ((uintptr_t)p >> 32) - fatal("host_x86_MOV8_ABS_REG - out of range %p\n", p); - codegen_alloc_bytes(block, 6); - codegen_addbyte(block, 0x88); /*MOVB [p], src_reg*/ - codegen_addbyte(block, 0x05 | ((src_reg & 7) << 3)); - codegen_addlong(block, (uint32_t)(uintptr_t)p); - } -} -void host_x86_MOV16_ABS_REG(codeblock_t *block, void *p, int src_reg) -{ - int64_t offset = (uintptr_t)p - (((uintptr_t)&cpu_state) + 128); - - if (src_reg & 8) - fatal("host_x86_MOV16_ABS_REG - bad reg\n"); - - if (offset >= -128 && offset < 127) - { - codegen_alloc_bytes(block, 4); - codegen_addbyte4(block, 0x66, 0x89, 0x45 | ((src_reg & 7) << 3), offset); /*MOV offset[RBP], src_reg*/ - } - else if (offset < (1ull << 32)) - { - codegen_alloc_bytes(block, 7); - codegen_addbyte3(block, 0x66, 0x89, 0x85 | ((src_reg & 7) << 3)); /*MOV offset[RBP], src_reg*/ - codegen_addlong(block, offset); - } - else - { - if ((uintptr_t)p >> 32) - fatal("host_x86_MOV32_ABS_REG - out of range %p\n", p); - } -} -void host_x86_MOV32_ABS_REG(codeblock_t *block, void *p, int src_reg) -{ - int64_t offset = (uintptr_t)p - (((uintptr_t)&cpu_state) + 128); - - if (src_reg & 8) - fatal("host_x86_MOV32_ABS_REG - bad reg\n"); - - if (offset >= -128 && offset < 127) - { - codegen_alloc_bytes(block, 3); - codegen_addbyte3(block, 0x89, 0x45 | ((src_reg & 7) << 3), offset); /*MOV offset[RBP], src_reg*/ - } - else if (offset < (1ull << 32)) - { - codegen_alloc_bytes(block, 6); - codegen_addbyte2(block, 0x89, 0x85 | ((src_reg & 7) << 3)); /*MOV offset[RBP], src_reg*/ - codegen_addlong(block, offset); - } - else - { - if ((uintptr_t)p >> 32) - fatal("host_x86_MOV32_ABS_REG - out of range %p\n", p); - codegen_alloc_bytes(block, 6); - codegen_addbyte(block, 0x89); /*MOV [p], src_reg*/ - codegen_addbyte(block, 0x05 | ((src_reg & 7) << 3)); - codegen_addlong(block, (uint32_t)(uintptr_t)p); - } -} -void host_x86_MOV64_ABS_REG(codeblock_t *block, void *p, int src_reg) -{ - int64_t offset = (uintptr_t)p - (((uintptr_t)&cpu_state) + 128); - - if (src_reg & 8) - fatal("host_x86_MOV64_ABS_REG - bad reg\n"); - - if (offset >= -128 && offset < 127) - { - codegen_alloc_bytes(block, 4); - codegen_addbyte4(block, 0x48, 0x89, 0x45 | ((src_reg & 7) << 3), offset); /*MOV offset[RBP], src_reg*/ - } - else - { - if ((uintptr_t)p >> 32) - fatal("host_x86_MOV64_ABS_REG - out of range %p\n", p); - codegen_alloc_bytes(block, 8); - codegen_addbyte4(block, 0x48, 0x89, 0x04 | ((src_reg & 7) << 3), 0x25); /*MOV [p], src_reg*/ - codegen_addlong(block, (uint32_t)(uintptr_t)p); - } -} - -void host_x86_MOV8_ABS_REG_REG_SHIFT_REG(codeblock_t *block, uint32_t addr, int base_reg, int index_reg, int shift, int src_reg) -{ - if ((src_reg & 8) || (base_reg & 8) | (index_reg & 8)) - fatal("host_x86_MOV8_BASE_INDEX_REG reg & 8\n"); - if (addr < 0x80 || addr >= 0xffffff80) - { - codegen_alloc_bytes(block, 4); - codegen_addbyte4(block, 0x88, 0x44 | (src_reg << 3), base_reg | (index_reg << 3) | (shift << 6), addr & 0xff); /*MOV addr[base_reg + idx_reg << shift], src_reg*/ - } - else - { - codegen_alloc_bytes(block, 7); - codegen_addbyte3(block, 0x88, 0x84 | (src_reg << 3), base_reg | (index_reg << 3) | (shift << 6)); /*MOV addr[base_reg + idx_reg << shift], src_reg*/ - codegen_addlong(block, addr); - } -} - -void host_x86_MOV8_BASE_INDEX_REG(codeblock_t *block, int base_reg, int index_reg, int src_reg) -{ - if ((src_reg & 8) || (base_reg & 8) | (index_reg & 8)) - fatal("host_x86_MOV8_BASE_INDEX_REG reg & 8\n"); - codegen_alloc_bytes(block, 3); - codegen_addbyte3(block, 0x88, 0x04 | (src_reg << 3), (index_reg << 3) | base_reg); /*MOV B[base_reg + index_reg], src_reg*/ -} -void host_x86_MOV16_BASE_INDEX_REG(codeblock_t *block, int base_reg, int index_reg, int src_reg) -{ - if ((src_reg & 8) || (base_reg & 8) | (index_reg & 8)) - fatal("host_x86_MOV8_BASE_INDEX_REG reg & 8\n"); + if (is_imm8(imm_data)) { codegen_alloc_bytes(block, 4); - codegen_addbyte4(block, 0x66, 0x89, 0x04 | (src_reg << 3), (index_reg << 3) | base_reg); /*MOV W[base_reg + index_reg], src_reg*/ -} -void host_x86_MOV32_BASE_INDEX_REG(codeblock_t *block, int base_reg, int index_reg, int src_reg) -{ - if ((src_reg & 8) || (base_reg & 8) | (index_reg & 8)) - fatal("host_x86_MOV8_BASE_INDEX_REG reg & 8\n"); - codegen_alloc_bytes(block, 3); - codegen_addbyte3(block, 0x89, 0x04 | (src_reg << 3), (index_reg << 3) | base_reg); /*MOV L[base_reg + index_reg], src_reg*/ -} - -void host_x86_MOV8_REG_ABS(codeblock_t *block, int dst_reg, void *p) -{ - int64_t offset = (uintptr_t)p - (((uintptr_t)&cpu_state) + 128); - int64_t ram_offset = (uintptr_t)p - (uintptr_t)ram; - - if (dst_reg & 8) - fatal("host_x86_MOV8_REG_ABS reg & 8\n"); - - if (offset >= -128 && offset < 127) - { - codegen_alloc_bytes(block, 3); - codegen_addbyte3(block, 0x8a, 0x45 | ((dst_reg & 7) << 3), offset); /*MOV dst_reg, offset[RBP]*/ - } - else if (offset < (1ull << 32)) - { - codegen_alloc_bytes(block, 6); - codegen_addbyte2(block, 0x8a, 0x85 | ((dst_reg & 7) << 3)); /*MOV dst_reg, offset[RBP]*/ - codegen_addlong(block, offset); - } - else if ((ram_offset < (1ull << 32)) && (block->flags & CODEBLOCK_NO_IMMEDIATES)) - { - codegen_alloc_bytes(block, 8); - codegen_addbyte4(block, 0x41, 0x8a, 0x84 | ((dst_reg & 7) << 3), 0x24); /*MOV dst_reg, ram_offset[R12]*/ - codegen_addlong(block, ram_offset); - } - else - { - fatal("host_x86_MOV8_REG_ABS - out of range\n"); - } -} -void host_x86_MOV16_REG_ABS(codeblock_t *block, int dst_reg, void *p) -{ - int64_t offset = (uintptr_t)p - (((uintptr_t)&cpu_state) + 128); - int64_t ram_offset = (uintptr_t)p - (uintptr_t)ram; - - if (dst_reg & 8) - fatal("host_x86_MOV16_REG_ABS reg & 8\n"); - - if (offset >= -128 && offset < 127) - { - codegen_alloc_bytes(block, 4); - codegen_addbyte4(block, 0x66, 0x8b, 0x45 | ((dst_reg & 7) << 3), offset); /*MOV dst_reg, offset[RBP]*/ - } - else if (offset < (1ull << 32)) - { - codegen_alloc_bytes(block, 7); - codegen_addbyte3(block, 0x66, 0x8b, 0x85 | ((dst_reg & 7) << 3)); /*MOV dst_reg, offset[RBP]*/ - codegen_addlong(block, offset); - } - else if ((ram_offset < (1ull << 32)) && (block->flags & CODEBLOCK_NO_IMMEDIATES)) - { - codegen_alloc_bytes(block, 9); - codegen_addbyte4(block, 0x66, 0x41, 0x8b, 0x84 | ((dst_reg & 7) << 3)); /*MOV dst_reg, ram_offset[R12]*/ - codegen_addbyte(block, 0x24); - codegen_addlong(block, ram_offset); - } - else - { - fatal("host_x86_MOV16_REG_ABS - out of range\n"); - codegen_alloc_bytes(block, 10); - codegen_addbyte2(block, 0x49, 0xb9); /*MOV R9, p*/ - codegen_addquad(block, (uintptr_t)p); - codegen_alloc_bytes(block, 1); - codegen_addbyte4(block, 0x66, 0x41, 0x8b, 0x01 | ((dst_reg & 7) << 3)); /*MOV dst_reg, [r9]*/ - } -} -void host_x86_MOV32_REG_ABS(codeblock_t *block, int dst_reg, void *p) -{ - int64_t offset = (uintptr_t)p - (((uintptr_t)&cpu_state) + 128); - int64_t ram_offset = (uintptr_t)p - (uintptr_t)ram; - - if (dst_reg & 8) - fatal("host_x86_MOV32_REG_ABS reg & 8\n"); - - if (offset >= -128 && offset < 127) - { - codegen_alloc_bytes(block, 3); - codegen_addbyte3(block, 0x8b, 0x45 | ((dst_reg & 7) << 3), offset); /*MOV dst_reg, offset[RBP]*/ - } - else if (offset < (1ull << 32)) - { - codegen_alloc_bytes(block, 6); - codegen_addbyte2(block, 0x8b, 0x85 | ((dst_reg & 7) << 3)); /*MOV dst_reg, offset[RBP]*/ - codegen_addlong(block, offset); - } - else if ((ram_offset < (1ull << 32)) && (block->flags & CODEBLOCK_NO_IMMEDIATES)) - { - codegen_alloc_bytes(block, 8); - codegen_addbyte4(block, 0x41, 0x8b, 0x84 | ((dst_reg & 7) << 3), 0x24); /*MOV dst_reg, ram_offset[R12]*/ - codegen_addlong(block, ram_offset); - } - else - { - fatal("host_x86_MOV32_REG_ABS - out of range\n"); - codegen_alloc_bytes(block, 6); - codegen_addbyte(block, 0x8b); /*MOV [p], src_reg*/ - codegen_addbyte(block, 0x05 | ((dst_reg & 7) << 3)); - codegen_addlong(block, (uint32_t)(uintptr_t)p); - } -} -void host_x86_MOV64_REG_ABS(codeblock_t *block, int dst_reg, void *p) -{ - int64_t offset = (uintptr_t)p - (((uintptr_t)&cpu_state) + 128); - - if (dst_reg & 8) - fatal("host_x86_MOV64_REG_ABS reg & 8\n"); - - if (offset >= -128 && offset < 127) - { - codegen_alloc_bytes(block, 4); - codegen_addbyte4(block, 0x48, 0x8b, 0x45 | ((dst_reg & 7) << 3), offset); /*MOV dst_reg, offset[RBP]*/ - } - else if (offset < (1ull << 32)) - { - codegen_alloc_bytes(block, 7); - codegen_addbyte3(block, 0x48, 0x8b, 0x85 | ((dst_reg & 7) << 3)); /*MOV dst_reg, offset[RBP]*/ - codegen_addlong(block, offset); - } - else - fatal("host_x86_MOV64_REG_ABS - out of range\n"); -} - -void host_x86_MOV8_REG_ABS_REG_REG_SHIFT(codeblock_t *block, int dst_reg, uint32_t addr, int base_reg, int index_reg, int shift) -{ - if ((dst_reg & 8) || (base_reg & 8) | (index_reg & 8)) - fatal("host_x86_MOV8_REG_ABS_REG_REG_SHIFT reg & 8\n"); - if (addr < 0x80 || addr >= 0xffffff80) - { - codegen_alloc_bytes(block, 4); - codegen_addbyte4(block, 0x8a, 0x44 | (dst_reg << 3), base_reg | (index_reg << 3) | (shift << 6), addr & 0xff); /*MOV addr[base_reg + idx_reg << shift], src_reg*/ - } - else - { - codegen_alloc_bytes(block, 7); - codegen_addbyte3(block, 0x8a, 0x84 | (dst_reg << 3), base_reg | (index_reg << 3) | (shift << 6)); /*MOV addr[base_reg + idx_reg << shift], src_reg*/ - codegen_addlong(block, addr); - } -} - -void host_x86_MOV32_REG_BASE_INDEX(codeblock_t *block, int dst_reg, int base_reg, int index_reg) -{ - if ((dst_reg & 8) || (base_reg & 8) | (index_reg & 8)) - fatal("host_x86_MOV32_REG_BASE_INDEX reg & 8\n"); - codegen_alloc_bytes(block, 3); - codegen_addbyte3(block, 0x8b, 0x04 | (dst_reg << 3), (index_reg << 3) | base_reg); /*MOV dst_reg, Q[base_reg + index_reg]*/ -} - -void host_x86_MOV64_REG_BASE_INDEX_SHIFT(codeblock_t *block, int dst_reg, int base_reg, int index_reg, int scale) -{ - if ((dst_reg & 8) || (index_reg & 8)) - fatal("host_x86_MOV64_REG_BASE_INDEX_SHIFT reg & 8\n"); + codegen_addbyte4(block, 0x66, 0x83, 0xc0 | RM_OP_ADD | (dst_reg & 7), imm_data & 0xff); /*ADD dst_reg, imm_data*/ + } else if (dst_reg == REG_EAX) { codegen_alloc_bytes(block, 4); - if (base_reg & 8) - codegen_addbyte4(block, 0x49, 0x8b, 0x04 | ((dst_reg & 7) << 3), (scale << 6) | ((index_reg & 7) << 3) | (base_reg & 7)); /*MOV dst_reg, Q[base_reg + index_reg << scale]*/ - else - codegen_addbyte4(block, 0x48, 0x8b, 0x04 | ((dst_reg & 7) << 3), (scale << 6) | ((index_reg & 7) << 3) | (base_reg & 7)); /*MOV dst_reg, Q[base_reg + index_reg << scale]*/ -} - -void host_x86_MOV16_REG_BASE_OFFSET(codeblock_t *block, int dst_reg, int base_reg, int offset) -{ - if ((dst_reg & 8) || (base_reg & 8)) - fatal("host_x86_MOV16_REG_BASE_OFFSET reg & 8\n"); - - if (offset >= -128 && offset < 127) - { - if (base_reg == REG_RSP) - { - codegen_alloc_bytes(block, 5); - codegen_addbyte(block, 0x66); - codegen_addbyte4(block, 0x8b, 0x40 | base_reg | (dst_reg << 3), 0x24, offset); - } - else - { - codegen_alloc_bytes(block, 4); - codegen_addbyte4(block, 0x66, 0x8b, 0x40 | base_reg | (dst_reg << 3), offset); - } - } - else - fatal("MOV16_REG_BASE_OFFSET - offset %i\n", offset); -} -void host_x86_MOV32_REG_BASE_OFFSET(codeblock_t *block, int dst_reg, int base_reg, int offset) -{ - if ((dst_reg & 8) || (base_reg & 8)) - fatal("host_x86_MOV32_REG_BASE_OFFSET reg & 8\n"); - - if (offset >= -128 && offset < 127) - { - if (base_reg == REG_RSP) - { - codegen_alloc_bytes(block, 4); - codegen_addbyte4(block, 0x8b, 0x40 | base_reg | (dst_reg << 3), 0x24, offset); - } - else - { - codegen_alloc_bytes(block, 3); - codegen_addbyte3(block, 0x8b, 0x40 | base_reg | (dst_reg << 3), offset); - } - } - else - fatal("MOV32_REG_BASE_OFFSET - offset %i\n", offset); -} -void host_x86_MOV64_REG_BASE_OFFSET(codeblock_t *block, int dst_reg, int base_reg, int offset) -{ - if ((dst_reg & 8) || (base_reg & 8)) - fatal("host_x86_MOV64_REG_BASE_OFFSET reg & 8\n"); - - if (offset >= -128 && offset < 127) - { - if (base_reg == REG_RSP) - { - codegen_alloc_bytes(block, 5); - codegen_addbyte(block, 0x48); - codegen_addbyte4(block, 0x8b, 0x40 | base_reg | (dst_reg << 3), 0x24, offset); - } - else - { - codegen_alloc_bytes(block, 4); - codegen_addbyte4(block, 0x48, 0x8b, 0x40 | base_reg | (dst_reg << 3), offset); - } - } - else - fatal("MOV32_REG_BASE_OFFSET - offset %i\n", offset); -} - -void host_x86_MOV32_BASE_OFFSET_REG(codeblock_t *block, int base_reg, int offset, int src_reg) -{ - if ((src_reg & 8) || (base_reg & 8)) - fatal("host_x86_MOV32_BASE_OFFSET_REG reg & 8\n"); - - if (offset >= -128 && offset < 127) - { - if (base_reg == REG_RSP) - { - codegen_alloc_bytes(block, 4); - codegen_addbyte4(block, 0x89, 0x40 | base_reg | (src_reg << 3), 0x24, offset); - } - else - { - codegen_alloc_bytes(block, 3); - codegen_addbyte3(block, 0x89, 0x40 | base_reg | (src_reg << 3), offset); - } - } - else - fatal("MOV32_BASE_OFFSET_REG - offset %i\n", offset); -} -void host_x86_MOV64_BASE_OFFSET_REG(codeblock_t *block, int base_reg, int offset, int src_reg) -{ - if ((src_reg & 8) || (base_reg & 8)) - fatal("host_x86_MOV64_BASE_OFFSET_REG reg & 8\n"); - - if (offset >= -128 && offset < 127) - { - if (base_reg == REG_RSP) - { - codegen_alloc_bytes(block, 5); - codegen_addbyte(block, 0x48); - codegen_addbyte4(block, 0x89, 0x40 | base_reg | (src_reg << 3), 0x24, offset); - } - else - { - codegen_alloc_bytes(block, 4); - codegen_addbyte4(block, 0x48, 0x89, 0x40 | base_reg | (src_reg << 3), offset); - } - } - else - fatal("MOV64_BASE_OFFSET_REG - offset %i\n", offset); -} - -void host_x86_MOV32_BASE_OFFSET_IMM(codeblock_t *block, int base_reg, int offset, uint32_t imm_data) -{ - if (base_reg & 8) - fatal("host_x86_MOV32_BASE_OFFSET_IMM reg & 8\n"); - - if (offset >= -128 && offset < 127) - { - if (base_reg == REG_RSP) - { - codegen_alloc_bytes(block, 8); - codegen_addbyte4(block, 0xc7, 0x40 | base_reg, 0x24, offset); - codegen_addlong(block, imm_data); - } - else - { - codegen_alloc_bytes(block, 7); - codegen_addbyte3(block, 0xc7, 0x40 | base_reg, offset); - codegen_addlong(block, imm_data); - } - } - else - fatal("MOV32_BASE_OFFSET_IMM - offset %i\n", offset); -} - -void host_x86_MOV8_REG_IMM(codeblock_t *block, int reg, uint16_t imm_data) -{ - if (reg >= 8) - fatal("host_x86_MOV8_REG_IMM reg >= 4\n"); - codegen_alloc_bytes(block, 2); - codegen_addbyte2(block, 0xb0 | reg, imm_data); /*MOV reg, imm_data*/ -} -void host_x86_MOV16_REG_IMM(codeblock_t *block, int reg, uint16_t imm_data) -{ - if (reg & 8) - fatal("host_x86_MOV16_REG_IMM reg & 8\n"); - codegen_alloc_bytes(block, 6); - codegen_addbyte2(block, 0x66, 0xb8 | (reg & 7)); /*MOV reg, imm_data*/ + codegen_addbyte2(block, 0x66, 0x05); /*AND AX, imm_data*/ codegen_addword(block, imm_data); -} -void host_x86_MOV32_REG_IMM(codeblock_t *block, int reg, uint32_t imm_data) -{ - if (reg & 8) - fatal("host_x86_MOV32_REG_IMM reg & 8\n"); + } else { codegen_alloc_bytes(block, 5); - codegen_addbyte(block, 0xb8 | (reg & 7)); /*MOV reg, imm_data*/ + codegen_addbyte3(block, 0x66, 0x81, 0xc0 | RM_OP_ADD | (dst_reg & 7)); /*ADD dst_reg, imm_data*/ + codegen_addword(block, imm_data); + } +} +void +host_x86_ADD32_REG_IMM(codeblock_t *block, int dst_reg, uint32_t imm_data) +{ + if (dst_reg & 8) + fatal("host_x86_ADD32_REG_IMM - dst_reg & 8\n"); + + if (is_imm8(imm_data)) { + codegen_alloc_bytes(block, 3); + codegen_addbyte3(block, 0x83, 0xc0 | RM_OP_ADD | (dst_reg & 7), imm_data & 0xff); /*ADD dst_reg, imm_data*/ + } else if (dst_reg == REG_EAX) { + codegen_alloc_bytes(block, 5); + codegen_addbyte(block, 0x05); /*ADD EAX, imm_data*/ codegen_addlong(block, imm_data); + } else { + codegen_alloc_bytes(block, 6); + codegen_addbyte2(block, 0x81, 0xc0 | RM_OP_ADD | (dst_reg & 7)); /*ADD dst_reg, imm_data*/ + codegen_addlong(block, imm_data); + } +} +void +host_x86_ADD64_REG_IMM(codeblock_t *block, int dst_reg, uint64_t imm_data) +{ + if (dst_reg & 8) + fatal("host_x86_ADD64_REG_IMM - dst_reg & 8\n"); + + if (is_imm8(imm_data)) { + codegen_alloc_bytes(block, 4); + codegen_addbyte4(block, 0x48, 0x83, 0xc0 | RM_OP_ADD | (dst_reg & 7), imm_data & 0xff); /*ADD dst_reg, imm_data*/ + } else + fatal("ADD64_REG_IMM !is_imm8 %016" PRIx64 "\n", imm_data); +} +void +host_x86_ADD8_REG_REG(codeblock_t *block, int dst_reg, int src_reg) +{ + if ((dst_reg & 8) || (src_reg & 8)) + fatal("host_x86_ADD8_REG_REG - dst_reg & 8\n"); + + codegen_alloc_bytes(block, 2); + codegen_addbyte2(block, 0x00, 0xc0 | (dst_reg & 7) | ((src_reg & 7) << 3)); /*ADD dst_reg, src_reg*/ +} +void +host_x86_ADD16_REG_REG(codeblock_t *block, int dst_reg, int src_reg) +{ + if ((dst_reg & 8) || (src_reg & 8)) + fatal("host_x86_ADD16_REG_REG - dst_reg & 8\n"); + + codegen_alloc_bytes(block, 3); + codegen_addbyte3(block, 0x66, 0x01, 0xc0 | (dst_reg & 7) | ((src_reg & 7) << 3)); /*ADD dst_reg, src_reg*/ +} +void +host_x86_ADD32_REG_REG(codeblock_t *block, int dst_reg, int src_reg) +{ + if ((dst_reg & 8) || (src_reg & 8)) + fatal("host_x86_ADD32_REG_REG - dst_reg & 8\n"); + + codegen_alloc_bytes(block, 2); + codegen_addbyte2(block, 0x01, 0xc0 | (dst_reg & 7) | ((src_reg & 7) << 3)); /*ADD dst_reg, src_reg*/ } -void host_x86_MOV64_REG_IMM(codeblock_t *block, int reg, uint64_t imm_data) +void +host_x86_AND8_REG_IMM(codeblock_t *block, int dst_reg, uint8_t imm_data) { - if (reg & 8) - { - codegen_alloc_bytes(block, 10); - codegen_addbyte2(block, 0x49, 0xb8 | (reg & 7)); /*MOVQ reg, imm_data*/ - codegen_addquad(block, imm_data); - } - else - { - codegen_alloc_bytes(block, 10); - codegen_addbyte2(block, 0x48, 0xb8 | (reg & 7)); /*MOVQ reg, imm_data*/ - codegen_addquad(block, imm_data); - } -} - -void host_x86_MOV8_REG_REG(codeblock_t *block, int dst_reg, int src_reg) -{ - if ((dst_reg & 8) || (src_reg & 8)) - fatal("host_x86_MOV8_REG_REG - bad reg\n"); + if (dst_reg & 8) + fatal("host_x86_AND8_REG_IMM - dst_reg & 8\n"); + if (dst_reg == REG_EAX) { codegen_alloc_bytes(block, 2); - codegen_addbyte2(block, 0x88, 0xc0 | (dst_reg & 7) | ((src_reg & 7) << 3)); -} -void host_x86_MOV16_REG_REG(codeblock_t *block, int dst_reg, int src_reg) -{ - if ((dst_reg & 8) || (src_reg & 8)) - fatal("host_x86_MOV16_REG_REG - bad reg\n"); - + codegen_addbyte2(block, 0x24, imm_data); /*AND EAX, imm_data*/ + } else { codegen_alloc_bytes(block, 3); - codegen_addbyte3(block, 0x66, 0x89, 0xc0 | (dst_reg & 7) | ((src_reg & 7) << 3)); + codegen_addbyte3(block, 0x80, 0xc0 | RM_OP_AND | (dst_reg & 7), imm_data); /*AND dst_reg, imm_data*/ + } } -void host_x86_MOV32_REG_REG(codeblock_t *block, int dst_reg, int src_reg) +void +host_x86_AND16_REG_IMM(codeblock_t *block, int dst_reg, uint16_t imm_data) { - if ((dst_reg & 8) || (src_reg & 8)) - fatal("host_x86_MOV32_REG_REG - bad reg\n"); + if (dst_reg & 8) + fatal("host_x86_AND16_REG_IMM - dst_reg & 8\n"); + if (is_imm8(imm_data)) { + codegen_alloc_bytes(block, 4); + codegen_addbyte4(block, 0x66, 0x83, 0xc0 | RM_OP_AND | (dst_reg & 7), imm_data & 0xff); /*AND dst_reg, imm_data*/ + } else if (dst_reg == REG_EAX) { + codegen_alloc_bytes(block, 4); + codegen_addbyte2(block, 0x66, 0x25); /*AND AX, imm_data*/ + codegen_addword(block, imm_data); + } else { + codegen_alloc_bytes(block, 5); + codegen_addbyte3(block, 0x66, 0x81, 0xc0 | RM_OP_AND | (dst_reg & 7)); /*AND dst_reg, imm_data*/ + codegen_addword(block, imm_data); + } +} +void +host_x86_AND32_REG_IMM(codeblock_t *block, int dst_reg, uint32_t imm_data) +{ + if (dst_reg & 8) + fatal("host_x86_AND32_REG_IMM - dst_reg & 8\n"); + + if (is_imm8(imm_data)) { + codegen_alloc_bytes(block, 3); + codegen_addbyte3(block, 0x83, 0xc0 | RM_OP_AND | (dst_reg & 7), imm_data & 0xff); /*AND dst_reg, imm_data*/ + } else if (dst_reg == REG_EAX) { + codegen_alloc_bytes(block, 5); + codegen_addbyte(block, 0x25); /*AND EAX, imm_data*/ + codegen_addlong(block, imm_data); + } else { + codegen_alloc_bytes(block, 6); + codegen_addbyte2(block, 0x81, 0xc0 | RM_OP_AND | (dst_reg & 7)); /*AND dst_reg, imm_data*/ + codegen_addlong(block, imm_data); + } +} +void +host_x86_AND8_REG_REG(codeblock_t *block, int dst_reg, int src_reg) +{ + if ((dst_reg & 8) || (src_reg & 8)) + fatal("host_x86_AND8_REG_REG - dst_reg & 8\n"); + + codegen_alloc_bytes(block, 2); + codegen_addbyte2(block, 0x20, 0xc0 | (dst_reg & 7) | ((src_reg & 7) << 3)); /*AND dst_reg, src_reg*/ +} +void +host_x86_AND16_REG_REG(codeblock_t *block, int dst_reg, int src_reg) +{ + if ((dst_reg & 8) || (src_reg & 8)) + fatal("host_x86_AND16_REG_REG - dst_reg & 8\n"); + + codegen_alloc_bytes(block, 3); + codegen_addbyte3(block, 0x66, 0x21, 0xc0 | (dst_reg & 7) | ((src_reg & 7) << 3)); /*AND dst_reg, src_reg*/ +} +void +host_x86_AND32_REG_REG(codeblock_t *block, int dst_reg, int src_reg) +{ + if ((dst_reg & 8) || (src_reg & 8)) + fatal("host_x86_AND32_REG_REG - dst_reg & 8\n"); + + codegen_alloc_bytes(block, 2); + codegen_addbyte2(block, 0x21, 0xc0 | (dst_reg & 7) | ((src_reg & 7) << 3)); /*AND dst_reg, src_reg*/ +} + +void +host_x86_CALL(codeblock_t *block, void *p) +{ + call(block, (uintptr_t) p); +} + +void +host_x86_CMP16_REG_IMM(codeblock_t *block, int dst_reg, uint16_t imm_data) +{ + if (is_imm8(imm_data)) { + codegen_alloc_bytes(block, 4); + codegen_addbyte4(block, 0x66, 0x83, 0xc0 | RM_OP_CMP | dst_reg, imm_data & 0xff); /*CMP dst_reg, imm_data*/ + } else if (dst_reg == REG_EAX) { + codegen_alloc_bytes(block, 4); + codegen_addbyte2(block, 0x66, 0x3d); /*CMP AX, imm_data*/ + codegen_addword(block, imm_data); + } else { + codegen_alloc_bytes(block, 5); + codegen_addbyte3(block, 0x66, 0x81, 0xc0 | RM_OP_CMP | dst_reg); /*CMP dst_reg, imm_data*/ + codegen_addword(block, imm_data); + } +} +void +host_x86_CMP32_REG_IMM(codeblock_t *block, int dst_reg, uint32_t imm_data) +{ + if (is_imm8(imm_data)) { + codegen_alloc_bytes(block, 3); + codegen_addbyte3(block, 0x83, 0xc0 | RM_OP_CMP | dst_reg, imm_data & 0xff); /*CMP dst_reg, imm_data*/ + } else if (dst_reg == REG_EAX) { + codegen_alloc_bytes(block, 5); + codegen_addbyte(block, 0x3d); /*CMP EAX, imm_data*/ + codegen_addlong(block, imm_data); + } else { + codegen_alloc_bytes(block, 6); + codegen_addbyte2(block, 0x81, 0xc0 | RM_OP_CMP | dst_reg); /*CMP dst_reg, imm_data*/ + codegen_addlong(block, imm_data); + } +} +void +host_x86_CMP64_REG_IMM(codeblock_t *block, int dst_reg, uint64_t imm_data) +{ + if (is_imm8(imm_data)) { + codegen_alloc_bytes(block, 4); + codegen_addbyte4(block, 0x48, 0x83, 0xc0 | RM_OP_CMP | dst_reg, imm_data & 0xff); /*CMP dst_reg, imm_data*/ + } else + fatal("CMP64_REG_IMM not 8-bit imm\n"); +} + +void +host_x86_CMP8_REG_REG(codeblock_t *block, int src_reg_a, int src_reg_b) +{ + codegen_alloc_bytes(block, 2); + codegen_addbyte2(block, 0x38, 0xc0 | src_reg_a | (src_reg_b << 3)); /*CMP src_reg_a, src_reg_b*/ +} +void +host_x86_CMP16_REG_REG(codeblock_t *block, int src_reg_a, int src_reg_b) +{ + codegen_alloc_bytes(block, 3); + codegen_addbyte3(block, 0x66, 0x39, 0xc0 | src_reg_a | (src_reg_b << 3)); /*CMP src_reg_a, src_reg_b*/ +} +void +host_x86_CMP32_REG_REG(codeblock_t *block, int src_reg_a, int src_reg_b) +{ + codegen_alloc_bytes(block, 2); + codegen_addbyte2(block, 0x39, 0xc0 | src_reg_a | (src_reg_b << 3)); /*CMP src_reg_a, src_reg_b*/ +} + +void +host_x86_JMP(codeblock_t *block, void *p) +{ + jmp(block, (uintptr_t) p); +} + +void +host_x86_JNZ(codeblock_t *block, void *p) +{ + codegen_alloc_bytes(block, 6); + codegen_addbyte2(block, 0x0f, 0x85); /*JNZ*/ + codegen_addlong(block, (uintptr_t) p - (uintptr_t) &block_write_data[block_pos + 4]); +} +void +host_x86_JZ(codeblock_t *block, void *p) +{ + codegen_alloc_bytes(block, 6); + codegen_addbyte2(block, 0x0f, 0x84); /*JZ*/ + codegen_addlong(block, (uintptr_t) p - (uintptr_t) &block_write_data[block_pos + 4]); +} + +uint8_t * +host_x86_JNZ_short(codeblock_t *block) +{ + codegen_alloc_bytes(block, 2); + codegen_addbyte2(block, 0x75, 0); /*JNZ*/ + return &block_write_data[block_pos - 1]; +} +uint8_t * +host_x86_JS_short(codeblock_t *block) +{ + codegen_alloc_bytes(block, 2); + codegen_addbyte2(block, 0x78, 0); /*JS*/ + return &block_write_data[block_pos - 1]; +} +uint8_t * +host_x86_JZ_short(codeblock_t *block) +{ + codegen_alloc_bytes(block, 2); + codegen_addbyte2(block, 0x74, 0); /*JZ*/ + return &block_write_data[block_pos - 1]; +} + +uint32_t * +host_x86_JNB_long(codeblock_t *block) +{ + codegen_alloc_bytes(block, 6); + codegen_addbyte2(block, 0x0f, 0x83); /*JNB*/ + codegen_addlong(block, 0); + return (uint32_t *) &block_write_data[block_pos - 4]; +} +uint32_t * +host_x86_JNBE_long(codeblock_t *block) +{ + codegen_alloc_bytes(block, 6); + codegen_addbyte2(block, 0x0f, 0x87); /*JNBE*/ + codegen_addlong(block, 0); + return (uint32_t *) &block_write_data[block_pos - 4]; +} +uint32_t * +host_x86_JNL_long(codeblock_t *block) +{ + codegen_alloc_bytes(block, 6); + codegen_addbyte2(block, 0x0f, 0x8d); /*JNL*/ + codegen_addlong(block, 0); + return (uint32_t *) &block_write_data[block_pos - 4]; +} +uint32_t * +host_x86_JNLE_long(codeblock_t *block) +{ + codegen_alloc_bytes(block, 6); + codegen_addbyte2(block, 0x0f, 0x8f); /*JNLE*/ + codegen_addlong(block, 0); + return (uint32_t *) &block_write_data[block_pos - 4]; +} +uint32_t * +host_x86_JNO_long(codeblock_t *block) +{ + codegen_alloc_bytes(block, 6); + codegen_addbyte2(block, 0x0f, 0x81); /*JNO*/ + codegen_addlong(block, 0); + return (uint32_t *) &block_write_data[block_pos - 4]; +} +uint32_t * +host_x86_JNS_long(codeblock_t *block) +{ + codegen_alloc_bytes(block, 6); + codegen_addbyte2(block, 0x0f, 0x89); /*JNS*/ + codegen_addlong(block, 0); + return (uint32_t *) &block_write_data[block_pos - 4]; +} +uint32_t * +host_x86_JNZ_long(codeblock_t *block) +{ + codegen_alloc_bytes(block, 6); + codegen_addbyte2(block, 0x0f, 0x85); /*JNZ*/ + codegen_addlong(block, 0); + return (uint32_t *) &block_write_data[block_pos - 4]; +} +uint32_t * +host_x86_JB_long(codeblock_t *block) +{ + codegen_alloc_bytes(block, 6); + codegen_addbyte2(block, 0x0f, 0x82); /*JB*/ + codegen_addlong(block, 0); + return (uint32_t *) &block_write_data[block_pos - 4]; +} +uint32_t * +host_x86_JBE_long(codeblock_t *block) +{ + codegen_alloc_bytes(block, 6); + codegen_addbyte2(block, 0x0f, 0x86); /*JBE*/ + codegen_addlong(block, 0); + return (uint32_t *) &block_write_data[block_pos - 4]; +} +uint32_t * +host_x86_JL_long(codeblock_t *block) +{ + codegen_alloc_bytes(block, 6); + codegen_addbyte2(block, 0x0f, 0x8c); /*JL*/ + codegen_addlong(block, 0); + return (uint32_t *) &block_write_data[block_pos - 4]; +} +uint32_t * +host_x86_JLE_long(codeblock_t *block) +{ + codegen_alloc_bytes(block, 6); + codegen_addbyte2(block, 0x0f, 0x8e); /*JLE*/ + codegen_addlong(block, 0); + return (uint32_t *) &block_write_data[block_pos - 4]; +} +uint32_t * +host_x86_JO_long(codeblock_t *block) +{ + codegen_alloc_bytes(block, 6); + codegen_addbyte2(block, 0x0f, 0x80); /*JO*/ + codegen_addlong(block, 0); + return (uint32_t *) &block_write_data[block_pos - 4]; +} +uint32_t * +host_x86_JS_long(codeblock_t *block) +{ + codegen_alloc_bytes(block, 6); + codegen_addbyte2(block, 0x0f, 0x88); /*JS*/ + codegen_addlong(block, 0); + return (uint32_t *) &block_write_data[block_pos - 4]; +} +uint32_t * +host_x86_JZ_long(codeblock_t *block) +{ + codegen_alloc_bytes(block, 6); + codegen_addbyte2(block, 0x0f, 0x84); /*JZ*/ + codegen_addlong(block, 0); + return (uint32_t *) &block_write_data[block_pos - 4]; +} + +void +host_x86_LAHF(codeblock_t *block) +{ + codegen_alloc_bytes(block, 1); + codegen_addbyte(block, 0x9f); /*LAHF*/ +} + +void +host_x86_LEA_REG_IMM(codeblock_t *block, int dst_reg, int src_reg, uint32_t offset) +{ + if (offset) { + codegen_alloc_bytes(block, 6); + codegen_addbyte2(block, 0x8d, 0x80 | (dst_reg << 3) | src_reg); /*LEA dst_reg, [offset+src_reg]*/ + codegen_addlong(block, offset); + } else { codegen_alloc_bytes(block, 2); - codegen_addbyte2(block, 0x89, 0xc0 | (dst_reg & 7) | ((src_reg & 7) << 3)); + codegen_addbyte2(block, 0x8d, 0x00 | (dst_reg << 3) | src_reg); /*LEA dst_reg, [src_reg]*/ + } +} +void +host_x86_LEA_REG_REG(codeblock_t *block, int dst_reg, int src_reg_a, int src_reg_b) +{ + if ((dst_reg & 8) || (src_reg_a & 8) || (src_reg_b & 8)) + fatal("host_x86_LEA_REG_REG - bad reg\n"); + + codegen_alloc_bytes(block, 3); + codegen_addbyte3(block, 0x8d, 0x04 | ((dst_reg & 7) << 3), /*LEA dst_reg, [Rsrc_reg_a + Rsrc_reg_b]*/ + ((src_reg_b & 7) << 3) | (src_reg_a & 7)); +} +void +host_x86_LEA_REG_REG_SHIFT(codeblock_t *block, int dst_reg, int src_reg_a, int src_reg_b, int shift) +{ + if ((dst_reg & 8) || (src_reg_a & 8) || (src_reg_b & 8)) + fatal("host_x86_LEA_REG_REG_SHIFT - bad reg\n"); + + codegen_alloc_bytes(block, 3); + codegen_addbyte3(block, 0x8d, 0x04 | ((dst_reg & 7) << 3), /*LEA dst_reg, [Rsrc_reg_a + Rsrc_reg_b * (1 << shift)]*/ + (shift << 6) | ((src_reg_b & 7) << 3) | (src_reg_a & 7)); } -void host_x86_MOV32_STACK_IMM(codeblock_t *block, int32_t offset, uint32_t imm_data) +void +host_x86_MOV8_ABS_IMM(codeblock_t *block, void *p, uint32_t imm_data) { - if (!offset) - { - codegen_alloc_bytes(block, 7); - codegen_addbyte3(block, 0xc7, 0x04, 0x24); /*MOV [ESP], imm_data*/ - codegen_addlong(block, imm_data); - } - else if (offset >= -0x80 && offset < 0x80) - { - codegen_alloc_bytes(block, 8); - codegen_addbyte4(block, 0xc7, 0x44, 0x24, offset & 0xff); /*MOV offset[ESP], imm_data*/ - codegen_addlong(block, imm_data); - } - else - { - codegen_alloc_bytes(block, 11); - codegen_addbyte3(block, 0xc7, 0x84, 0x24); /*MOV offset[ESP], imm_data*/ - codegen_addlong(block, offset); - codegen_addlong(block, imm_data); - } -} + int64_t offset = (uintptr_t) p - (((uintptr_t) &cpu_state) + 128); -void host_x86_MOVSX_REG_16_8(codeblock_t *block, int dst_reg, int src_reg) -{ + if (offset >= -128 && offset < 127) { codegen_alloc_bytes(block, 4); - codegen_addbyte4(block, 0x66, 0x0f, 0xbe, 0xc0 | (dst_reg << 3) | src_reg); /*MOVSX dst_reg, src_reg*/ + codegen_addbyte3(block, 0xc6, 0x45, offset); /*MOVB offset[RBP], imm_data*/ + codegen_addbyte(block, imm_data); + } else { + if ((uintptr_t) p >> 32) + fatal("host_x86_MOV8_ABS_IMM - out of range %p\n", p); + codegen_alloc_bytes(block, 8); + codegen_addbyte3(block, 0xc6, 0x04, 0x25); /*MOVB p, imm_data*/ + codegen_addlong(block, (uint32_t) (uintptr_t) p); + codegen_addbyte(block, imm_data); + } } -void host_x86_MOVSX_REG_32_8(codeblock_t *block, int dst_reg, int src_reg) +void +host_x86_MOV16_ABS_IMM(codeblock_t *block, void *p, uint16_t imm_data) { - codegen_alloc_bytes(block, 3); - codegen_addbyte3(block, 0x0f, 0xbe, 0xc0 | (dst_reg << 3) | src_reg); /*MOVSX dst_reg, src_reg*/ + int64_t offset = (uintptr_t) p - (((uintptr_t) &cpu_state) + 128); + + if (offset >= -128 && offset < 127) { + codegen_alloc_bytes(block, 6); + codegen_addbyte4(block, 0x66, 0xc7, 0x45, offset); /*MOV offset[RBP], imm_data*/ + codegen_addword(block, imm_data); + } else { + if ((uintptr_t) p >> 32) + fatal("host_x86_MOV32_ABS_IMM - out of range %p\n", p); + codegen_alloc_bytes(block, 10); + codegen_addbyte4(block, 0x66, 0xc7, 0x04, 0x25); /*MOV p, imm_data*/ + codegen_addlong(block, (uint32_t) (uintptr_t) p); + codegen_addword(block, imm_data); + } } -void host_x86_MOVSX_REG_32_16(codeblock_t *block, int dst_reg, int src_reg) +void +host_x86_MOV32_ABS_IMM(codeblock_t *block, void *p, uint32_t imm_data) { - codegen_alloc_bytes(block, 3); - codegen_addbyte3(block, 0x0f, 0xbf, 0xc0 | (dst_reg << 3) | src_reg); /*MOVSX dst_reg, src_reg*/ + int64_t offset = (uintptr_t) p - (((uintptr_t) &cpu_state) + 128); + + if (offset >= -128 && offset < 127) { + codegen_alloc_bytes(block, 7); + codegen_addbyte3(block, 0xc7, 0x45, offset); /*MOV offset[RBP], imm_data*/ + codegen_addlong(block, imm_data); + } else { + if ((uintptr_t) p >> 32) + fatal("host_x86_MOV32_ABS_IMM - out of range %p\n", p); + codegen_alloc_bytes(block, 11); + codegen_addbyte3(block, 0xc7, 0x04, 0x25); /*MOV p, imm_data*/ + codegen_addlong(block, (uint32_t) (uintptr_t) p); + codegen_addlong(block, imm_data); + } } -void host_x86_MOVZX_BASE_INDEX_32_8(codeblock_t *block, int dst_reg, int base_reg, int index_reg) +void +host_x86_MOV8_ABS_REG(codeblock_t *block, void *p, int src_reg) { - if ((dst_reg & 8) || (base_reg & 8) | (index_reg & 8)) - fatal("host_x86_MOVZX_BASE_INDEX_32_8 reg & 8\n"); + int64_t offset = (uintptr_t) p - (((uintptr_t) &cpu_state) + 128); + if (src_reg & 8) + fatal("host_x86_MOV8_ABS_REG - bad reg\n"); + + if (offset >= -128 && offset < 127) { + codegen_alloc_bytes(block, 3); + codegen_addbyte3(block, 0x88, 0x45 | ((src_reg & 7) << 3), offset); /*MOVB offset[RBP], src_reg*/ + } else { + if ((uintptr_t) p >> 32) + fatal("host_x86_MOV8_ABS_REG - out of range %p\n", p); + codegen_alloc_bytes(block, 6); + codegen_addbyte(block, 0x88); /*MOVB [p], src_reg*/ + codegen_addbyte(block, 0x05 | ((src_reg & 7) << 3)); + codegen_addlong(block, (uint32_t) (uintptr_t) p); + } +} +void +host_x86_MOV16_ABS_REG(codeblock_t *block, void *p, int src_reg) +{ + int64_t offset = (uintptr_t) p - (((uintptr_t) &cpu_state) + 128); + + if (src_reg & 8) + fatal("host_x86_MOV16_ABS_REG - bad reg\n"); + + if (offset >= -128 && offset < 127) { codegen_alloc_bytes(block, 4); - codegen_addbyte4(block, 0x0f, 0xb6, 0x04 | (dst_reg << 3), (index_reg << 3) | base_reg); + codegen_addbyte4(block, 0x66, 0x89, 0x45 | ((src_reg & 7) << 3), offset); /*MOV offset[RBP], src_reg*/ + } else if (offset < (1ULL << 32)) { + codegen_alloc_bytes(block, 7); + codegen_addbyte3(block, 0x66, 0x89, 0x85 | ((src_reg & 7) << 3)); /*MOV offset[RBP], src_reg*/ + codegen_addlong(block, offset); + } else { + if ((uintptr_t) p >> 32) + fatal("host_x86_MOV32_ABS_REG - out of range %p\n", p); + } } -void host_x86_MOVZX_BASE_INDEX_32_16(codeblock_t *block, int dst_reg, int base_reg, int index_reg) +void +host_x86_MOV32_ABS_REG(codeblock_t *block, void *p, int src_reg) { - if ((dst_reg & 8) || (base_reg & 8) | (index_reg & 8)) - fatal("host_x86_MOVZX_BASE_INDEX_32_16 reg & 8\n"); + int64_t offset = (uintptr_t) p - (((uintptr_t) &cpu_state) + 128); - codegen_alloc_bytes(block, 4); - codegen_addbyte4(block, 0x0f, 0xb7, 0x04 | (dst_reg << 3), (index_reg << 3) | base_reg); -} - -void host_x86_MOVZX_REG_16_8(codeblock_t *block, int dst_reg, int src_reg) -{ - if ((dst_reg & 8) || (src_reg & 8)) - fatal("host_x86_MOVZX_REG_16_8 - bad reg\n"); - - codegen_alloc_bytes(block, 4); - codegen_addbyte4(block, 0x66, 0x0f, 0xb6, 0xc0 | (dst_reg << 3) | src_reg); /*MOVZX dst_reg, src_reg*/ -} -void host_x86_MOVZX_REG_32_8(codeblock_t *block, int dst_reg, int src_reg) -{ - if ((dst_reg & 8) || (src_reg & 8)) - fatal("host_x86_MOVZX_REG_32_8 - bad reg\n"); + if (src_reg & 8) + fatal("host_x86_MOV32_ABS_REG - bad reg\n"); + if (offset >= -128 && offset < 127) { codegen_alloc_bytes(block, 3); - codegen_addbyte3(block, 0x0f, 0xb6, 0xc0 | (dst_reg << 3) | src_reg); /*MOVZX dst_reg, src_reg*/ + codegen_addbyte3(block, 0x89, 0x45 | ((src_reg & 7) << 3), offset); /*MOV offset[RBP], src_reg*/ + } else if (offset < (1ULL << 32)) { + codegen_alloc_bytes(block, 6); + codegen_addbyte2(block, 0x89, 0x85 | ((src_reg & 7) << 3)); /*MOV offset[RBP], src_reg*/ + codegen_addlong(block, offset); + } else { + if ((uintptr_t) p >> 32) + fatal("host_x86_MOV32_ABS_REG - out of range %p\n", p); + codegen_alloc_bytes(block, 6); + codegen_addbyte(block, 0x89); /*MOV [p], src_reg*/ + codegen_addbyte(block, 0x05 | ((src_reg & 7) << 3)); + codegen_addlong(block, (uint32_t) (uintptr_t) p); + } } -void host_x86_MOVZX_REG_32_16(codeblock_t *block, int dst_reg, int src_reg) +void +host_x86_MOV64_ABS_REG(codeblock_t *block, void *p, int src_reg) { - if ((dst_reg & 8) || (src_reg & 8)) - fatal("host_x86_MOVZX_REG_16_8 - bad reg\n"); + int64_t offset = (uintptr_t) p - (((uintptr_t) &cpu_state) + 128); + if (src_reg & 8) + fatal("host_x86_MOV64_ABS_REG - bad reg\n"); + + if (offset >= -128 && offset < 127) { + codegen_alloc_bytes(block, 4); + codegen_addbyte4(block, 0x48, 0x89, 0x45 | ((src_reg & 7) << 3), offset); /*MOV offset[RBP], src_reg*/ + } else { + if ((uintptr_t) p >> 32) + fatal("host_x86_MOV64_ABS_REG - out of range %p\n", p); + codegen_alloc_bytes(block, 8); + codegen_addbyte4(block, 0x48, 0x89, 0x04 | ((src_reg & 7) << 3), 0x25); /*MOV [p], src_reg*/ + codegen_addlong(block, (uint32_t) (uintptr_t) p); + } +} + +void +host_x86_MOV8_ABS_REG_REG_SHIFT_REG(codeblock_t *block, uint32_t addr, int base_reg, int index_reg, int shift, int src_reg) +{ + if ((src_reg & 8) || (base_reg & 8) | (index_reg & 8)) + fatal("host_x86_MOV8_BASE_INDEX_REG reg & 8\n"); + if (addr < 0x80 || addr >= 0xffffff80) { + codegen_alloc_bytes(block, 4); + codegen_addbyte4(block, 0x88, 0x44 | (src_reg << 3), base_reg | (index_reg << 3) | (shift << 6), addr & 0xff); /*MOV addr[base_reg + idx_reg << shift], src_reg*/ + } else { + codegen_alloc_bytes(block, 7); + codegen_addbyte3(block, 0x88, 0x84 | (src_reg << 3), base_reg | (index_reg << 3) | (shift << 6)); /*MOV addr[base_reg + idx_reg << shift], src_reg*/ + codegen_addlong(block, addr); + } +} + +void +host_x86_MOV8_BASE_INDEX_REG(codeblock_t *block, int base_reg, int index_reg, int src_reg) +{ + if ((src_reg & 8) || (base_reg & 8) | (index_reg & 8)) + fatal("host_x86_MOV8_BASE_INDEX_REG reg & 8\n"); + codegen_alloc_bytes(block, 3); + codegen_addbyte3(block, 0x88, 0x04 | (src_reg << 3), (index_reg << 3) | base_reg); /*MOV B[base_reg + index_reg], src_reg*/ +} +void +host_x86_MOV16_BASE_INDEX_REG(codeblock_t *block, int base_reg, int index_reg, int src_reg) +{ + if ((src_reg & 8) || (base_reg & 8) | (index_reg & 8)) + fatal("host_x86_MOV8_BASE_INDEX_REG reg & 8\n"); + codegen_alloc_bytes(block, 4); + codegen_addbyte4(block, 0x66, 0x89, 0x04 | (src_reg << 3), (index_reg << 3) | base_reg); /*MOV W[base_reg + index_reg], src_reg*/ +} +void +host_x86_MOV32_BASE_INDEX_REG(codeblock_t *block, int base_reg, int index_reg, int src_reg) +{ + if ((src_reg & 8) || (base_reg & 8) | (index_reg & 8)) + fatal("host_x86_MOV8_BASE_INDEX_REG reg & 8\n"); + codegen_alloc_bytes(block, 3); + codegen_addbyte3(block, 0x89, 0x04 | (src_reg << 3), (index_reg << 3) | base_reg); /*MOV L[base_reg + index_reg], src_reg*/ +} + +void +host_x86_MOV8_REG_ABS(codeblock_t *block, int dst_reg, void *p) +{ + int64_t offset = (uintptr_t) p - (((uintptr_t) &cpu_state) + 128); + int64_t ram_offset = (uintptr_t) p - (uintptr_t) ram; + + if (dst_reg & 8) + fatal("host_x86_MOV8_REG_ABS reg & 8\n"); + + if (offset >= -128 && offset < 127) { codegen_alloc_bytes(block, 3); - codegen_addbyte3(block, 0x0f, 0xb7, 0xc0 | (dst_reg << 3) | src_reg); /*MOVZX dst_reg, src_reg*/ + codegen_addbyte3(block, 0x8a, 0x45 | ((dst_reg & 7) << 3), offset); /*MOV dst_reg, offset[RBP]*/ + } else if (offset < (1ULL << 32)) { + codegen_alloc_bytes(block, 6); + codegen_addbyte2(block, 0x8a, 0x85 | ((dst_reg & 7) << 3)); /*MOV dst_reg, offset[RBP]*/ + codegen_addlong(block, offset); + } else if ((ram_offset < (1ULL << 32)) && (block->flags & CODEBLOCK_NO_IMMEDIATES)) { + codegen_alloc_bytes(block, 8); + codegen_addbyte4(block, 0x41, 0x8a, 0x84 | ((dst_reg & 7) << 3), 0x24); /*MOV dst_reg, ram_offset[R12]*/ + codegen_addlong(block, ram_offset); + } else { + fatal("host_x86_MOV8_REG_ABS - out of range\n"); + } } - -void host_x86_MOVZX_REG_ABS_16_8(codeblock_t *block, int dst_reg, void *p) +void +host_x86_MOV16_REG_ABS(codeblock_t *block, int dst_reg, void *p) { - int64_t offset = (uintptr_t)p - (((uintptr_t)&cpu_state) + 128); - int64_t ram_offset = (uintptr_t)p - (uintptr_t)ram; - - if (dst_reg & 8) - fatal("host_x86_MOVZX_REG_ABS_16_8 - bad reg\n"); + int64_t offset = (uintptr_t) p - (((uintptr_t) &cpu_state) + 128); + int64_t ram_offset = (uintptr_t) p - (uintptr_t) ram; - if (offset >= -128 && offset < 127) - { - codegen_alloc_bytes(block, 5); - codegen_addbyte(block, 0x66); - codegen_addbyte4(block, 0x0f, 0xb6, 0x45 | ((dst_reg & 7) << 3), offset); /*MOVZX dst_reg, offset[RBP]*/ - } - else if ((ram_offset < (1ull << 32)) && (block->flags & CODEBLOCK_NO_IMMEDIATES)) - { - codegen_alloc_bytes(block, 10); - codegen_addbyte2(block, 0x66, 0x41); - codegen_addbyte4(block, 0x0f, 0xb6, 0x84 | ((dst_reg & 7) << 3), 0x24); /*MOVZX dst_reg, ram_offset[R12]*/ - codegen_addlong(block, ram_offset); - } - else - { - codegen_alloc_bytes(block, 10); - codegen_addbyte2(block, 0x49, 0xb9); /*MOV R9, p*/ - codegen_addquad(block, (uintptr_t)p); - codegen_alloc_bytes(block, 5); - codegen_addbyte(block, 0x66); - codegen_addbyte4(block, 0x41, 0x0f, 0xb6, 0x01 | ((dst_reg & 7) << 3)); /*MOVZX dst_reg, [r9]*/ - } -} -void host_x86_MOVZX_REG_ABS_32_8(codeblock_t *block, int dst_reg, void *p) -{ - int64_t offset = (uintptr_t)p - (((uintptr_t)&cpu_state) + 128); - int64_t ram_offset = (uintptr_t)p - (uintptr_t)ram; - -// if (dst_reg & 8) -// fatal("host_x86_MOVZX_REG_ABS_32_8 - bad reg\n"); + if (dst_reg & 8) + fatal("host_x86_MOV16_REG_ABS reg & 8\n"); - if (offset >= -128 && offset < 127) - { - if (dst_reg & 8) - { - codegen_alloc_bytes(block, 5); - codegen_addbyte(block, 0x44); - codegen_addbyte4(block, 0x0f, 0xb6, 0x45 | ((dst_reg & 7) << 3), offset); /*MOVZX dst_reg, offset[RBP]*/ - } - else - { - codegen_alloc_bytes(block, 4); - codegen_addbyte4(block, 0x0f, 0xb6, 0x45 | ((dst_reg & 7) << 3), offset); /*MOVZX dst_reg, offset[RBP]*/ - } - } - else if ((ram_offset < (1ull << 32)) && (block->flags & CODEBLOCK_NO_IMMEDIATES)) - { - if (dst_reg & 8) - fatal("host_x86_MOVZX_REG_ABS_32_8 - bad reg\n"); - - codegen_alloc_bytes(block, 9); - codegen_addbyte(block, 0x41); - codegen_addbyte4(block, 0x0f, 0xb6, 0x84 | ((dst_reg & 7) << 3), 0x24); /*MOVZX dst_reg, ram_offset[R12]*/ - codegen_addlong(block, ram_offset); - } - else - { - if (dst_reg & 8) - fatal("host_x86_MOVZX_REG_ABS_32_8 - bad reg\n"); - - codegen_alloc_bytes(block, 10); - codegen_addbyte2(block, 0x49, 0xb9); /*MOV R9, p*/ - codegen_addquad(block, (uintptr_t)p); - codegen_alloc_bytes(block, 4); - codegen_addbyte4(block, 0x41, 0x0f, 0xb6, 0x01 | ((dst_reg & 7) << 3)); /*MOVZX dst_reg, [r9]*/ - } -} -void host_x86_MOVZX_REG_ABS_32_16(codeblock_t *block, int dst_reg, void *p) -{ - int64_t offset = (uintptr_t)p - (((uintptr_t)&cpu_state) + 128); - int64_t ram_offset = (uintptr_t)p - (uintptr_t)ram; - - if (dst_reg & 8) - fatal("host_x86_MOVZX_REG_ABS_32_16 - bad reg\n"); - - if (offset >= -128 && offset < 127) - { - codegen_alloc_bytes(block, 4); - codegen_addbyte4(block, 0x0f, 0xb7, 0x45 | ((dst_reg & 7) << 3), offset); /*MOVZX dst_reg, offset[RBP]*/ - } - else if ((ram_offset < (1ull << 32)) && (block->flags & CODEBLOCK_NO_IMMEDIATES)) - { - codegen_alloc_bytes(block, 9); - codegen_addbyte(block, 0x41); - codegen_addbyte4(block, 0x0f, 0xb7, 0x84 | ((dst_reg & 7) << 3), 0x24); /*MOVZX dst_reg, ram_offset[R12]*/ - codegen_addlong(block, ram_offset); - } - else - { - codegen_alloc_bytes(block, 10); - codegen_addbyte2(block, 0x49, 0xb9); /*MOV R9, p*/ - codegen_addquad(block, (uintptr_t)p); - codegen_alloc_bytes(block, 4); - codegen_addbyte4(block, 0x41, 0x0f, 0xb7, 0x01 | ((dst_reg & 7) << 3)); /*MOVZX dst_reg, [r9]*/ - } -} - -void host_x86_NOP(codeblock_t *block) -{ + if (offset >= -128 && offset < 127) { + codegen_alloc_bytes(block, 4); + codegen_addbyte4(block, 0x66, 0x8b, 0x45 | ((dst_reg & 7) << 3), offset); /*MOV dst_reg, offset[RBP]*/ + } else if (offset < (1ULL << 32)) { + codegen_alloc_bytes(block, 7); + codegen_addbyte3(block, 0x66, 0x8b, 0x85 | ((dst_reg & 7) << 3)); /*MOV dst_reg, offset[RBP]*/ + codegen_addlong(block, offset); + } else if ((ram_offset < (1ULL << 32)) && (block->flags & CODEBLOCK_NO_IMMEDIATES)) { + codegen_alloc_bytes(block, 9); + codegen_addbyte4(block, 0x66, 0x41, 0x8b, 0x84 | ((dst_reg & 7) << 3)); /*MOV dst_reg, ram_offset[R12]*/ + codegen_addbyte(block, 0x24); + codegen_addlong(block, ram_offset); + } else { + fatal("host_x86_MOV16_REG_ABS - out of range\n"); + codegen_alloc_bytes(block, 10); + codegen_addbyte2(block, 0x49, 0xb9); /*MOV R9, p*/ + codegen_addquad(block, (uintptr_t) p); codegen_alloc_bytes(block, 1); - codegen_addbyte(block, 0x90); /*NOP*/ + codegen_addbyte4(block, 0x66, 0x41, 0x8b, 0x01 | ((dst_reg & 7) << 3)); /*MOV dst_reg, [r9]*/ + } } - -void host_x86_OR8_REG_IMM(codeblock_t *block, int dst_reg, uint8_t imm_data) +void +host_x86_MOV32_REG_ABS(codeblock_t *block, int dst_reg, void *p) { - if (dst_reg & 8) - fatal("host_x86_OR8_REG_IMM - dst_reg & 8\n"); + int64_t offset = (uintptr_t) p - (((uintptr_t) &cpu_state) + 128); + int64_t ram_offset = (uintptr_t) p - (uintptr_t) ram; - if (dst_reg == REG_EAX) - { - codegen_alloc_bytes(block, 2); - codegen_addbyte2(block, 0x0c, imm_data); /*OR EAX, imm_data*/ - } - else - { - codegen_alloc_bytes(block, 3); - codegen_addbyte3(block, 0x80, 0xc0 | RM_OP_OR | (dst_reg & 7), imm_data); /*OR dst_reg, imm_data*/ - } -} -void host_x86_OR16_REG_IMM(codeblock_t *block, int dst_reg, uint16_t imm_data) -{ - if (dst_reg & 8) - fatal("host_x86_OR16_REG_IMM - dst_reg & 8\n"); - - if (is_imm8(imm_data)) - { - codegen_alloc_bytes(block, 4); - codegen_addbyte4(block, 0x66, 0x83, 0xc0 | RM_OP_OR | (dst_reg & 7), imm_data & 0xff); /*OR dst_reg, imm_data*/ - } - else if (dst_reg == REG_EAX) - { - codegen_alloc_bytes(block, 4); - codegen_addbyte2(block, 0x66, 0x0d); /*OR AX, imm_data*/ - codegen_addword(block, imm_data); - } - else - { - codegen_alloc_bytes(block, 5); - codegen_addbyte3(block, 0x66, 0x81, 0xc0 | RM_OP_OR | (dst_reg & 7)); /*OR dst_reg, imm_data*/ - codegen_addword(block, imm_data); - } -} -void host_x86_OR32_REG_IMM(codeblock_t *block, int dst_reg, uint32_t imm_data) -{ - if (dst_reg & 8) - fatal("host_x86_OR32_REG_IMM - dst_reg & 8\n"); - - if (is_imm8(imm_data)) - { - codegen_alloc_bytes(block, 3); - codegen_addbyte3(block, 0x83, 0xc0 | RM_OP_OR | (dst_reg & 7), imm_data & 0xff); /*OR dst_reg, imm_data*/ - } - else if (dst_reg == REG_EAX) - { - codegen_alloc_bytes(block, 5); - codegen_addbyte(block, 0x0d); /*OR EAX, imm_data*/ - codegen_addlong(block, imm_data); - } - else - { - codegen_alloc_bytes(block, 6); - codegen_addbyte2(block, 0x81, 0xc0 | RM_OP_OR | (dst_reg & 7)); /*OR dst_reg, imm_data*/ - codegen_addlong(block, imm_data); - } -} -void host_x86_OR8_REG_REG(codeblock_t *block, int dst_reg, int src_reg) -{ - if ((dst_reg & 8) || (src_reg & 8)) - fatal("host_x86_OR8_REG_IMM - dst_reg & 8\n"); - - codegen_alloc_bytes(block, 2); - codegen_addbyte2(block, 0x08, 0xc0 | (dst_reg & 7) | ((src_reg & 7) << 3)); /*OR dst_reg, src_reg*/ -} -void host_x86_OR16_REG_REG(codeblock_t *block, int dst_reg, int src_reg) -{ - if ((dst_reg & 8) || (src_reg & 8)) - fatal("host_x86_OR16_REG_IMM - dst_reg & 8\n"); + if (dst_reg & 8) + fatal("host_x86_MOV32_REG_ABS reg & 8\n"); + if (offset >= -128 && offset < 127) { codegen_alloc_bytes(block, 3); - codegen_addbyte3(block, 0x66, 0x09, 0xc0 | (dst_reg & 7) | ((src_reg & 7) << 3)); /*OR dst_reg, src_reg*/ + codegen_addbyte3(block, 0x8b, 0x45 | ((dst_reg & 7) << 3), offset); /*MOV dst_reg, offset[RBP]*/ + } else if (offset < (1ULL << 32)) { + codegen_alloc_bytes(block, 6); + codegen_addbyte2(block, 0x8b, 0x85 | ((dst_reg & 7) << 3)); /*MOV dst_reg, offset[RBP]*/ + codegen_addlong(block, offset); + } else if ((ram_offset < (1ULL << 32)) && (block->flags & CODEBLOCK_NO_IMMEDIATES)) { + codegen_alloc_bytes(block, 8); + codegen_addbyte4(block, 0x41, 0x8b, 0x84 | ((dst_reg & 7) << 3), 0x24); /*MOV dst_reg, ram_offset[R12]*/ + codegen_addlong(block, ram_offset); + } else { + fatal("host_x86_MOV32_REG_ABS - out of range\n"); + codegen_alloc_bytes(block, 6); + codegen_addbyte(block, 0x8b); /*MOV [p], src_reg*/ + codegen_addbyte(block, 0x05 | ((dst_reg & 7) << 3)); + codegen_addlong(block, (uint32_t) (uintptr_t) p); + } } -void host_x86_OR32_REG_REG(codeblock_t *block, int dst_reg, int src_reg) +void +host_x86_MOV64_REG_ABS(codeblock_t *block, int dst_reg, void *p) { - if ((dst_reg & 8) || (src_reg & 8)) - fatal("host_x86_OR32_REG_IMM - dst_reg & 8\n"); + int64_t offset = (uintptr_t) p - (((uintptr_t) &cpu_state) + 128); - codegen_alloc_bytes(block, 2); - codegen_addbyte2(block, 0x09, 0xc0 | (dst_reg & 7) | ((src_reg & 7) << 3)); /*OR dst_reg, src_reg*/ + if (dst_reg & 8) + fatal("host_x86_MOV64_REG_ABS reg & 8\n"); + + if (offset >= -128 && offset < 127) { + codegen_alloc_bytes(block, 4); + codegen_addbyte4(block, 0x48, 0x8b, 0x45 | ((dst_reg & 7) << 3), offset); /*MOV dst_reg, offset[RBP]*/ + } else if (offset < (1ULL << 32)) { + codegen_alloc_bytes(block, 7); + codegen_addbyte3(block, 0x48, 0x8b, 0x85 | ((dst_reg & 7) << 3)); /*MOV dst_reg, offset[RBP]*/ + codegen_addlong(block, offset); + } else + fatal("host_x86_MOV64_REG_ABS - out of range\n"); } -void host_x86_POP(codeblock_t *block, int dst_reg) +void +host_x86_MOV8_REG_ABS_REG_REG_SHIFT(codeblock_t *block, int dst_reg, uint32_t addr, int base_reg, int index_reg, int shift) { + if ((dst_reg & 8) || (base_reg & 8) | (index_reg & 8)) + fatal("host_x86_MOV8_REG_ABS_REG_REG_SHIFT reg & 8\n"); + if (addr < 0x80 || addr >= 0xffffff80) { + codegen_alloc_bytes(block, 4); + codegen_addbyte4(block, 0x8a, 0x44 | (dst_reg << 3), base_reg | (index_reg << 3) | (shift << 6), addr & 0xff); /*MOV addr[base_reg + idx_reg << shift], src_reg*/ + } else { + codegen_alloc_bytes(block, 7); + codegen_addbyte3(block, 0x8a, 0x84 | (dst_reg << 3), base_reg | (index_reg << 3) | (shift << 6)); /*MOV addr[base_reg + idx_reg << shift], src_reg*/ + codegen_addlong(block, addr); + } +} + +void +host_x86_MOV32_REG_BASE_INDEX(codeblock_t *block, int dst_reg, int base_reg, int index_reg) +{ + if ((dst_reg & 8) || (base_reg & 8) | (index_reg & 8)) + fatal("host_x86_MOV32_REG_BASE_INDEX reg & 8\n"); + codegen_alloc_bytes(block, 3); + codegen_addbyte3(block, 0x8b, 0x04 | (dst_reg << 3), (index_reg << 3) | base_reg); /*MOV dst_reg, Q[base_reg + index_reg]*/ +} + +void +host_x86_MOV64_REG_BASE_INDEX_SHIFT(codeblock_t *block, int dst_reg, int base_reg, int index_reg, int scale) +{ + if ((dst_reg & 8) || (index_reg & 8)) + fatal("host_x86_MOV64_REG_BASE_INDEX_SHIFT reg & 8\n"); + codegen_alloc_bytes(block, 4); + if (base_reg & 8) + codegen_addbyte4(block, 0x49, 0x8b, 0x04 | ((dst_reg & 7) << 3), (scale << 6) | ((index_reg & 7) << 3) | (base_reg & 7)); /*MOV dst_reg, Q[base_reg + index_reg << scale]*/ + else + codegen_addbyte4(block, 0x48, 0x8b, 0x04 | ((dst_reg & 7) << 3), (scale << 6) | ((index_reg & 7) << 3) | (base_reg & 7)); /*MOV dst_reg, Q[base_reg + index_reg << scale]*/ +} + +void +host_x86_MOV16_REG_BASE_OFFSET(codeblock_t *block, int dst_reg, int base_reg, int offset) +{ + if ((dst_reg & 8) || (base_reg & 8)) + fatal("host_x86_MOV16_REG_BASE_OFFSET reg & 8\n"); + + if (offset >= -128 && offset < 127) { + if (base_reg == REG_RSP) { + codegen_alloc_bytes(block, 5); + codegen_addbyte(block, 0x66); + codegen_addbyte4(block, 0x8b, 0x40 | base_reg | (dst_reg << 3), 0x24, offset); + } else { + codegen_alloc_bytes(block, 4); + codegen_addbyte4(block, 0x66, 0x8b, 0x40 | base_reg | (dst_reg << 3), offset); + } + } else + fatal("MOV16_REG_BASE_OFFSET - offset %i\n", offset); +} +void +host_x86_MOV32_REG_BASE_OFFSET(codeblock_t *block, int dst_reg, int base_reg, int offset) +{ + if ((dst_reg & 8) || (base_reg & 8)) + fatal("host_x86_MOV32_REG_BASE_OFFSET reg & 8\n"); + + if (offset >= -128 && offset < 127) { + if (base_reg == REG_RSP) { + codegen_alloc_bytes(block, 4); + codegen_addbyte4(block, 0x8b, 0x40 | base_reg | (dst_reg << 3), 0x24, offset); + } else { + codegen_alloc_bytes(block, 3); + codegen_addbyte3(block, 0x8b, 0x40 | base_reg | (dst_reg << 3), offset); + } + } else + fatal("MOV32_REG_BASE_OFFSET - offset %i\n", offset); +} +void +host_x86_MOV64_REG_BASE_OFFSET(codeblock_t *block, int dst_reg, int base_reg, int offset) +{ + if ((dst_reg & 8) || (base_reg & 8)) + fatal("host_x86_MOV64_REG_BASE_OFFSET reg & 8\n"); + + if (offset >= -128 && offset < 127) { + if (base_reg == REG_RSP) { + codegen_alloc_bytes(block, 5); + codegen_addbyte(block, 0x48); + codegen_addbyte4(block, 0x8b, 0x40 | base_reg | (dst_reg << 3), 0x24, offset); + } else { + codegen_alloc_bytes(block, 4); + codegen_addbyte4(block, 0x48, 0x8b, 0x40 | base_reg | (dst_reg << 3), offset); + } + } else + fatal("MOV32_REG_BASE_OFFSET - offset %i\n", offset); +} + +void +host_x86_MOV32_BASE_OFFSET_REG(codeblock_t *block, int base_reg, int offset, int src_reg) +{ + if ((src_reg & 8) || (base_reg & 8)) + fatal("host_x86_MOV32_BASE_OFFSET_REG reg & 8\n"); + + if (offset >= -128 && offset < 127) { + if (base_reg == REG_RSP) { + codegen_alloc_bytes(block, 4); + codegen_addbyte4(block, 0x89, 0x40 | base_reg | (src_reg << 3), 0x24, offset); + } else { + codegen_alloc_bytes(block, 3); + codegen_addbyte3(block, 0x89, 0x40 | base_reg | (src_reg << 3), offset); + } + } else + fatal("MOV32_BASE_OFFSET_REG - offset %i\n", offset); +} +void +host_x86_MOV64_BASE_OFFSET_REG(codeblock_t *block, int base_reg, int offset, int src_reg) +{ + if ((src_reg & 8) || (base_reg & 8)) + fatal("host_x86_MOV64_BASE_OFFSET_REG reg & 8\n"); + + if (offset >= -128 && offset < 127) { + if (base_reg == REG_RSP) { + codegen_alloc_bytes(block, 5); + codegen_addbyte(block, 0x48); + codegen_addbyte4(block, 0x89, 0x40 | base_reg | (src_reg << 3), 0x24, offset); + } else { + codegen_alloc_bytes(block, 4); + codegen_addbyte4(block, 0x48, 0x89, 0x40 | base_reg | (src_reg << 3), offset); + } + } else + fatal("MOV64_BASE_OFFSET_REG - offset %i\n", offset); +} + +void +host_x86_MOV32_BASE_OFFSET_IMM(codeblock_t *block, int base_reg, int offset, uint32_t imm_data) +{ + if (base_reg & 8) + fatal("host_x86_MOV32_BASE_OFFSET_IMM reg & 8\n"); + + if (offset >= -128 && offset < 127) { + if (base_reg == REG_RSP) { + codegen_alloc_bytes(block, 8); + codegen_addbyte4(block, 0xc7, 0x40 | base_reg, 0x24, offset); + codegen_addlong(block, imm_data); + } else { + codegen_alloc_bytes(block, 7); + codegen_addbyte3(block, 0xc7, 0x40 | base_reg, offset); + codegen_addlong(block, imm_data); + } + } else + fatal("MOV32_BASE_OFFSET_IMM - offset %i\n", offset); +} + +void +host_x86_MOV8_REG_IMM(codeblock_t *block, int reg, uint16_t imm_data) +{ + if (reg >= 8) + fatal("host_x86_MOV8_REG_IMM reg >= 4\n"); + codegen_alloc_bytes(block, 2); + codegen_addbyte2(block, 0xb0 | reg, imm_data); /*MOV reg, imm_data*/ +} +void +host_x86_MOV16_REG_IMM(codeblock_t *block, int reg, uint16_t imm_data) +{ + if (reg & 8) + fatal("host_x86_MOV16_REG_IMM reg & 8\n"); + codegen_alloc_bytes(block, 6); + codegen_addbyte2(block, 0x66, 0xb8 | (reg & 7)); /*MOV reg, imm_data*/ + codegen_addword(block, imm_data); +} +void +host_x86_MOV32_REG_IMM(codeblock_t *block, int reg, uint32_t imm_data) +{ + if (reg & 8) + fatal("host_x86_MOV32_REG_IMM reg & 8\n"); + codegen_alloc_bytes(block, 5); + codegen_addbyte(block, 0xb8 | (reg & 7)); /*MOV reg, imm_data*/ + codegen_addlong(block, imm_data); +} + +void +host_x86_MOV64_REG_IMM(codeblock_t *block, int reg, uint64_t imm_data) +{ + if (reg & 8) { + codegen_alloc_bytes(block, 10); + codegen_addbyte2(block, 0x49, 0xb8 | (reg & 7)); /*MOVQ reg, imm_data*/ + codegen_addquad(block, imm_data); + } else { + codegen_alloc_bytes(block, 10); + codegen_addbyte2(block, 0x48, 0xb8 | (reg & 7)); /*MOVQ reg, imm_data*/ + codegen_addquad(block, imm_data); + } +} + +void +host_x86_MOV8_REG_REG(codeblock_t *block, int dst_reg, int src_reg) +{ + if ((dst_reg & 8) || (src_reg & 8)) + fatal("host_x86_MOV8_REG_REG - bad reg\n"); + + codegen_alloc_bytes(block, 2); + codegen_addbyte2(block, 0x88, 0xc0 | (dst_reg & 7) | ((src_reg & 7) << 3)); +} +void +host_x86_MOV16_REG_REG(codeblock_t *block, int dst_reg, int src_reg) +{ + if ((dst_reg & 8) || (src_reg & 8)) + fatal("host_x86_MOV16_REG_REG - bad reg\n"); + + codegen_alloc_bytes(block, 3); + codegen_addbyte3(block, 0x66, 0x89, 0xc0 | (dst_reg & 7) | ((src_reg & 7) << 3)); +} +void +host_x86_MOV32_REG_REG(codeblock_t *block, int dst_reg, int src_reg) +{ + if ((dst_reg & 8) || (src_reg & 8)) + fatal("host_x86_MOV32_REG_REG - bad reg\n"); + + codegen_alloc_bytes(block, 2); + codegen_addbyte2(block, 0x89, 0xc0 | (dst_reg & 7) | ((src_reg & 7) << 3)); +} + +void +host_x86_MOV32_STACK_IMM(codeblock_t *block, int32_t offset, uint32_t imm_data) +{ + if (!offset) { + codegen_alloc_bytes(block, 7); + codegen_addbyte3(block, 0xc7, 0x04, 0x24); /*MOV [ESP], imm_data*/ + codegen_addlong(block, imm_data); + } else if (offset >= -0x80 && offset < 0x80) { + codegen_alloc_bytes(block, 8); + codegen_addbyte4(block, 0xc7, 0x44, 0x24, offset & 0xff); /*MOV offset[ESP], imm_data*/ + codegen_addlong(block, imm_data); + } else { + codegen_alloc_bytes(block, 11); + codegen_addbyte3(block, 0xc7, 0x84, 0x24); /*MOV offset[ESP], imm_data*/ + codegen_addlong(block, offset); + codegen_addlong(block, imm_data); + } +} + +void +host_x86_MOVSX_REG_16_8(codeblock_t *block, int dst_reg, int src_reg) +{ + codegen_alloc_bytes(block, 4); + codegen_addbyte4(block, 0x66, 0x0f, 0xbe, 0xc0 | (dst_reg << 3) | src_reg); /*MOVSX dst_reg, src_reg*/ +} +void +host_x86_MOVSX_REG_32_8(codeblock_t *block, int dst_reg, int src_reg) +{ + codegen_alloc_bytes(block, 3); + codegen_addbyte3(block, 0x0f, 0xbe, 0xc0 | (dst_reg << 3) | src_reg); /*MOVSX dst_reg, src_reg*/ +} +void +host_x86_MOVSX_REG_32_16(codeblock_t *block, int dst_reg, int src_reg) +{ + codegen_alloc_bytes(block, 3); + codegen_addbyte3(block, 0x0f, 0xbf, 0xc0 | (dst_reg << 3) | src_reg); /*MOVSX dst_reg, src_reg*/ +} + +void +host_x86_MOVZX_BASE_INDEX_32_8(codeblock_t *block, int dst_reg, int base_reg, int index_reg) +{ + if ((dst_reg & 8) || (base_reg & 8) | (index_reg & 8)) + fatal("host_x86_MOVZX_BASE_INDEX_32_8 reg & 8\n"); + + codegen_alloc_bytes(block, 4); + codegen_addbyte4(block, 0x0f, 0xb6, 0x04 | (dst_reg << 3), (index_reg << 3) | base_reg); +} +void +host_x86_MOVZX_BASE_INDEX_32_16(codeblock_t *block, int dst_reg, int base_reg, int index_reg) +{ + if ((dst_reg & 8) || (base_reg & 8) | (index_reg & 8)) + fatal("host_x86_MOVZX_BASE_INDEX_32_16 reg & 8\n"); + + codegen_alloc_bytes(block, 4); + codegen_addbyte4(block, 0x0f, 0xb7, 0x04 | (dst_reg << 3), (index_reg << 3) | base_reg); +} + +void +host_x86_MOVZX_REG_16_8(codeblock_t *block, int dst_reg, int src_reg) +{ + if ((dst_reg & 8) || (src_reg & 8)) + fatal("host_x86_MOVZX_REG_16_8 - bad reg\n"); + + codegen_alloc_bytes(block, 4); + codegen_addbyte4(block, 0x66, 0x0f, 0xb6, 0xc0 | (dst_reg << 3) | src_reg); /*MOVZX dst_reg, src_reg*/ +} +void +host_x86_MOVZX_REG_32_8(codeblock_t *block, int dst_reg, int src_reg) +{ + if ((dst_reg & 8) || (src_reg & 8)) + fatal("host_x86_MOVZX_REG_32_8 - bad reg\n"); + + codegen_alloc_bytes(block, 3); + codegen_addbyte3(block, 0x0f, 0xb6, 0xc0 | (dst_reg << 3) | src_reg); /*MOVZX dst_reg, src_reg*/ +} +void +host_x86_MOVZX_REG_32_16(codeblock_t *block, int dst_reg, int src_reg) +{ + if ((dst_reg & 8) || (src_reg & 8)) + fatal("host_x86_MOVZX_REG_16_8 - bad reg\n"); + + codegen_alloc_bytes(block, 3); + codegen_addbyte3(block, 0x0f, 0xb7, 0xc0 | (dst_reg << 3) | src_reg); /*MOVZX dst_reg, src_reg*/ +} + +void +host_x86_MOVZX_REG_ABS_16_8(codeblock_t *block, int dst_reg, void *p) +{ + int64_t offset = (uintptr_t) p - (((uintptr_t) &cpu_state) + 128); + int64_t ram_offset = (uintptr_t) p - (uintptr_t) ram; + + if (dst_reg & 8) + fatal("host_x86_MOVZX_REG_ABS_16_8 - bad reg\n"); + + if (offset >= -128 && offset < 127) { + codegen_alloc_bytes(block, 5); + codegen_addbyte(block, 0x66); + codegen_addbyte4(block, 0x0f, 0xb6, 0x45 | ((dst_reg & 7) << 3), offset); /*MOVZX dst_reg, offset[RBP]*/ + } else if ((ram_offset < (1ULL << 32)) && (block->flags & CODEBLOCK_NO_IMMEDIATES)) { + codegen_alloc_bytes(block, 10); + codegen_addbyte2(block, 0x66, 0x41); + codegen_addbyte4(block, 0x0f, 0xb6, 0x84 | ((dst_reg & 7) << 3), 0x24); /*MOVZX dst_reg, ram_offset[R12]*/ + codegen_addlong(block, ram_offset); + } else { + codegen_alloc_bytes(block, 10); + codegen_addbyte2(block, 0x49, 0xb9); /*MOV R9, p*/ + codegen_addquad(block, (uintptr_t) p); + codegen_alloc_bytes(block, 5); + codegen_addbyte(block, 0x66); + codegen_addbyte4(block, 0x41, 0x0f, 0xb6, 0x01 | ((dst_reg & 7) << 3)); /*MOVZX dst_reg, [r9]*/ + } +} +void +host_x86_MOVZX_REG_ABS_32_8(codeblock_t *block, int dst_reg, void *p) +{ + int64_t offset = (uintptr_t) p - (((uintptr_t) &cpu_state) + 128); + int64_t ram_offset = (uintptr_t) p - (uintptr_t) ram; + +#if 0 + if (dst_reg & 8) + fatal("host_x86_MOVZX_REG_ABS_32_8 - bad reg\n"); +#endif + + if (offset >= -128 && offset < 127) { + if (dst_reg & 8) { + codegen_alloc_bytes(block, 5); + codegen_addbyte(block, 0x44); + codegen_addbyte4(block, 0x0f, 0xb6, 0x45 | ((dst_reg & 7) << 3), offset); /*MOVZX dst_reg, offset[RBP]*/ + } else { + codegen_alloc_bytes(block, 4); + codegen_addbyte4(block, 0x0f, 0xb6, 0x45 | ((dst_reg & 7) << 3), offset); /*MOVZX dst_reg, offset[RBP]*/ + } + } else if ((ram_offset < (1ULL << 32)) && (block->flags & CODEBLOCK_NO_IMMEDIATES)) { if (dst_reg & 8) - { - codegen_alloc_bytes(block, 2); - codegen_addbyte2(block, 0x41, 0x58 | (dst_reg & 7)); /*POP reg*/ - } - else - { - codegen_alloc_bytes(block, 1); - codegen_addbyte(block, 0x58 | dst_reg); /*POP reg*/ - } + fatal("host_x86_MOVZX_REG_ABS_32_8 - bad reg\n"); + + codegen_alloc_bytes(block, 9); + codegen_addbyte(block, 0x41); + codegen_addbyte4(block, 0x0f, 0xb6, 0x84 | ((dst_reg & 7) << 3), 0x24); /*MOVZX dst_reg, ram_offset[R12]*/ + codegen_addlong(block, ram_offset); + } else { + if (dst_reg & 8) + fatal("host_x86_MOVZX_REG_ABS_32_8 - bad reg\n"); + + codegen_alloc_bytes(block, 10); + codegen_addbyte2(block, 0x49, 0xb9); /*MOV R9, p*/ + codegen_addquad(block, (uintptr_t) p); + codegen_alloc_bytes(block, 4); + codegen_addbyte4(block, 0x41, 0x0f, 0xb6, 0x01 | ((dst_reg & 7) << 3)); /*MOVZX dst_reg, [r9]*/ + } +} +void +host_x86_MOVZX_REG_ABS_32_16(codeblock_t *block, int dst_reg, void *p) +{ + int64_t offset = (uintptr_t) p - (((uintptr_t) &cpu_state) + 128); + int64_t ram_offset = (uintptr_t) p - (uintptr_t) ram; + + if (dst_reg & 8) + fatal("host_x86_MOVZX_REG_ABS_32_16 - bad reg\n"); + + if (offset >= -128 && offset < 127) { + codegen_alloc_bytes(block, 4); + codegen_addbyte4(block, 0x0f, 0xb7, 0x45 | ((dst_reg & 7) << 3), offset); /*MOVZX dst_reg, offset[RBP]*/ + } else if ((ram_offset < (1ULL << 32)) && (block->flags & CODEBLOCK_NO_IMMEDIATES)) { + codegen_alloc_bytes(block, 9); + codegen_addbyte(block, 0x41); + codegen_addbyte4(block, 0x0f, 0xb7, 0x84 | ((dst_reg & 7) << 3), 0x24); /*MOVZX dst_reg, ram_offset[R12]*/ + codegen_addlong(block, ram_offset); + } else { + codegen_alloc_bytes(block, 10); + codegen_addbyte2(block, 0x49, 0xb9); /*MOV R9, p*/ + codegen_addquad(block, (uintptr_t) p); + codegen_alloc_bytes(block, 4); + codegen_addbyte4(block, 0x41, 0x0f, 0xb7, 0x01 | ((dst_reg & 7) << 3)); /*MOVZX dst_reg, [r9]*/ + } } -void host_x86_PUSH(codeblock_t *block, int src_reg) +void +host_x86_NOP(codeblock_t *block) { - if (src_reg & 8) - { - codegen_alloc_bytes(block, 2); - codegen_addbyte2(block, 0x41, 0x50 | (src_reg & 7)); /*PUSH reg*/ - } - else - { - codegen_alloc_bytes(block, 1); - codegen_addbyte(block, 0x50 | src_reg); /*PUSH reg*/ - } + codegen_alloc_bytes(block, 1); + codegen_addbyte(block, 0x90); /*NOP*/ } -void host_x86_RET(codeblock_t *block) +void +host_x86_OR8_REG_IMM(codeblock_t *block, int dst_reg, uint8_t imm_data) { + if (dst_reg & 8) + fatal("host_x86_OR8_REG_IMM - dst_reg & 8\n"); + + if (dst_reg == REG_EAX) { + codegen_alloc_bytes(block, 2); + codegen_addbyte2(block, 0x0c, imm_data); /*OR EAX, imm_data*/ + } else { + codegen_alloc_bytes(block, 3); + codegen_addbyte3(block, 0x80, 0xc0 | RM_OP_OR | (dst_reg & 7), imm_data); /*OR dst_reg, imm_data*/ + } +} +void +host_x86_OR16_REG_IMM(codeblock_t *block, int dst_reg, uint16_t imm_data) +{ + if (dst_reg & 8) + fatal("host_x86_OR16_REG_IMM - dst_reg & 8\n"); + + if (is_imm8(imm_data)) { + codegen_alloc_bytes(block, 4); + codegen_addbyte4(block, 0x66, 0x83, 0xc0 | RM_OP_OR | (dst_reg & 7), imm_data & 0xff); /*OR dst_reg, imm_data*/ + } else if (dst_reg == REG_EAX) { + codegen_alloc_bytes(block, 4); + codegen_addbyte2(block, 0x66, 0x0d); /*OR AX, imm_data*/ + codegen_addword(block, imm_data); + } else { + codegen_alloc_bytes(block, 5); + codegen_addbyte3(block, 0x66, 0x81, 0xc0 | RM_OP_OR | (dst_reg & 7)); /*OR dst_reg, imm_data*/ + codegen_addword(block, imm_data); + } +} +void +host_x86_OR32_REG_IMM(codeblock_t *block, int dst_reg, uint32_t imm_data) +{ + if (dst_reg & 8) + fatal("host_x86_OR32_REG_IMM - dst_reg & 8\n"); + + if (is_imm8(imm_data)) { + codegen_alloc_bytes(block, 3); + codegen_addbyte3(block, 0x83, 0xc0 | RM_OP_OR | (dst_reg & 7), imm_data & 0xff); /*OR dst_reg, imm_data*/ + } else if (dst_reg == REG_EAX) { + codegen_alloc_bytes(block, 5); + codegen_addbyte(block, 0x0d); /*OR EAX, imm_data*/ + codegen_addlong(block, imm_data); + } else { + codegen_alloc_bytes(block, 6); + codegen_addbyte2(block, 0x81, 0xc0 | RM_OP_OR | (dst_reg & 7)); /*OR dst_reg, imm_data*/ + codegen_addlong(block, imm_data); + } +} +void +host_x86_OR8_REG_REG(codeblock_t *block, int dst_reg, int src_reg) +{ + if ((dst_reg & 8) || (src_reg & 8)) + fatal("host_x86_OR8_REG_IMM - dst_reg & 8\n"); + + codegen_alloc_bytes(block, 2); + codegen_addbyte2(block, 0x08, 0xc0 | (dst_reg & 7) | ((src_reg & 7) << 3)); /*OR dst_reg, src_reg*/ +} +void +host_x86_OR16_REG_REG(codeblock_t *block, int dst_reg, int src_reg) +{ + if ((dst_reg & 8) || (src_reg & 8)) + fatal("host_x86_OR16_REG_IMM - dst_reg & 8\n"); + + codegen_alloc_bytes(block, 3); + codegen_addbyte3(block, 0x66, 0x09, 0xc0 | (dst_reg & 7) | ((src_reg & 7) << 3)); /*OR dst_reg, src_reg*/ +} +void +host_x86_OR32_REG_REG(codeblock_t *block, int dst_reg, int src_reg) +{ + if ((dst_reg & 8) || (src_reg & 8)) + fatal("host_x86_OR32_REG_IMM - dst_reg & 8\n"); + + codegen_alloc_bytes(block, 2); + codegen_addbyte2(block, 0x09, 0xc0 | (dst_reg & 7) | ((src_reg & 7) << 3)); /*OR dst_reg, src_reg*/ +} + +void +host_x86_POP(codeblock_t *block, int dst_reg) +{ + if (dst_reg & 8) { + codegen_alloc_bytes(block, 2); + codegen_addbyte2(block, 0x41, 0x58 | (dst_reg & 7)); /*POP reg*/ + } else { codegen_alloc_bytes(block, 1); - codegen_addbyte(block, 0xc3); /*RET*/ + codegen_addbyte(block, 0x58 | dst_reg); /*POP reg*/ + } } -void host_x86_ROL8_CL(codeblock_t *block, int dst_reg) +void +host_x86_PUSH(codeblock_t *block, int src_reg) { - if (dst_reg & 8) - fatal("ROL8 CL & 8\n"); + if (src_reg & 8) { codegen_alloc_bytes(block, 2); - codegen_addbyte2(block, 0xd2, 0xc0 | RM_OP_ROL | dst_reg); /*SHL dst_reg, CL*/ -} -void host_x86_ROL16_CL(codeblock_t *block, int dst_reg) -{ - if (dst_reg & 8) - fatal("ROL16 CL & 8\n"); - codegen_alloc_bytes(block, 3); - codegen_addbyte3(block, 0x66, 0xd3, 0xc0 | RM_OP_ROL | dst_reg); /*SHL dst_reg, CL*/ -} -void host_x86_ROL32_CL(codeblock_t *block, int dst_reg) -{ - if (dst_reg & 8) - fatal("ROL32 CL & 8\n"); - codegen_alloc_bytes(block, 2); - codegen_addbyte2(block, 0xd3, 0xc0 | RM_OP_ROL | dst_reg); /*SHL dst_reg, CL*/ + codegen_addbyte2(block, 0x41, 0x50 | (src_reg & 7)); /*PUSH reg*/ + } else { + codegen_alloc_bytes(block, 1); + codegen_addbyte(block, 0x50 | src_reg); /*PUSH reg*/ + } } -void host_x86_ROL8_IMM(codeblock_t *block, int dst_reg, int shift) +void +host_x86_RET(codeblock_t *block) { - if (dst_reg & 8) - fatal("ROL8 imm & 8\n"); - codegen_alloc_bytes(block, 3); - codegen_addbyte3(block, 0xc0, 0xc0 | RM_OP_ROL | dst_reg, shift); /*SHL dst_reg, shift*/ + codegen_alloc_bytes(block, 1); + codegen_addbyte(block, 0xc3); /*RET*/ } -void host_x86_ROL16_IMM(codeblock_t *block, int dst_reg, int shift) + +void +host_x86_ROL8_CL(codeblock_t *block, int dst_reg) { - if (dst_reg & 8) - fatal("ROL16 imm & 8\n"); + if (dst_reg & 8) + fatal("ROL8 CL & 8\n"); + codegen_alloc_bytes(block, 2); + codegen_addbyte2(block, 0xd2, 0xc0 | RM_OP_ROL | dst_reg); /*SHL dst_reg, CL*/ +} +void +host_x86_ROL16_CL(codeblock_t *block, int dst_reg) +{ + if (dst_reg & 8) + fatal("ROL16 CL & 8\n"); + codegen_alloc_bytes(block, 3); + codegen_addbyte3(block, 0x66, 0xd3, 0xc0 | RM_OP_ROL | dst_reg); /*SHL dst_reg, CL*/ +} +void +host_x86_ROL32_CL(codeblock_t *block, int dst_reg) +{ + if (dst_reg & 8) + fatal("ROL32 CL & 8\n"); + codegen_alloc_bytes(block, 2); + codegen_addbyte2(block, 0xd3, 0xc0 | RM_OP_ROL | dst_reg); /*SHL dst_reg, CL*/ +} + +void +host_x86_ROL8_IMM(codeblock_t *block, int dst_reg, int shift) +{ + if (dst_reg & 8) + fatal("ROL8 imm & 8\n"); + codegen_alloc_bytes(block, 3); + codegen_addbyte3(block, 0xc0, 0xc0 | RM_OP_ROL | dst_reg, shift); /*SHL dst_reg, shift*/ +} +void +host_x86_ROL16_IMM(codeblock_t *block, int dst_reg, int shift) +{ + if (dst_reg & 8) + fatal("ROL16 imm & 8\n"); + codegen_alloc_bytes(block, 4); + codegen_addbyte4(block, 0x66, 0xc1, 0xc0 | RM_OP_ROL | dst_reg, shift); /*SHL dst_reg, shift*/ +} +void +host_x86_ROL32_IMM(codeblock_t *block, int dst_reg, int shift) +{ + if (dst_reg & 8) + fatal("ROL32 imm & 8\n"); + codegen_alloc_bytes(block, 3); + codegen_addbyte3(block, 0xc1, 0xc0 | RM_OP_ROL | dst_reg, shift); /*SHL dst_reg, shift*/ +} + +void +host_x86_ROR8_CL(codeblock_t *block, int dst_reg) +{ + if (dst_reg & 8) + fatal("ROR8 CL & 8\n"); + codegen_alloc_bytes(block, 2); + codegen_addbyte2(block, 0xd2, 0xc0 | RM_OP_ROR | dst_reg); /*SHR dst_reg, CL*/ +} +void +host_x86_ROR16_CL(codeblock_t *block, int dst_reg) +{ + if (dst_reg & 8) + fatal("ROR16 CL & 8\n"); + codegen_alloc_bytes(block, 3); + codegen_addbyte3(block, 0x66, 0xd3, 0xc0 | RM_OP_ROR | dst_reg); /*SHR dst_reg, CL*/ +} +void +host_x86_ROR32_CL(codeblock_t *block, int dst_reg) +{ + if (dst_reg & 8) + fatal("ROR32 CL & 8\n"); + codegen_alloc_bytes(block, 2); + codegen_addbyte2(block, 0xd3, 0xc0 | RM_OP_ROR | dst_reg); /*SHR dst_reg, CL*/ +} + +void +host_x86_ROR8_IMM(codeblock_t *block, int dst_reg, int shift) +{ + if (dst_reg & 8) + fatal("ROR8 imm & 8\n"); + codegen_alloc_bytes(block, 3); + codegen_addbyte3(block, 0xc0, 0xc0 | RM_OP_ROR | dst_reg, shift); /*SHR dst_reg, shift*/ +} +void +host_x86_ROR16_IMM(codeblock_t *block, int dst_reg, int shift) +{ + if (dst_reg & 8) + fatal("ROR16 imm & 8\n"); + codegen_alloc_bytes(block, 4); + codegen_addbyte4(block, 0x66, 0xc1, 0xc0 | RM_OP_ROR | dst_reg, shift); /*SHR dst_reg, shift*/ +} +void +host_x86_ROR32_IMM(codeblock_t *block, int dst_reg, int shift) +{ + if (dst_reg & 8) + fatal("ROR32 im & 8\n"); + codegen_alloc_bytes(block, 3); + codegen_addbyte3(block, 0xc1, 0xc0 | RM_OP_ROR | dst_reg, shift); /*SHR dst_reg, shift*/ +} + +void +host_x86_SAR8_CL(codeblock_t *block, int dst_reg) +{ + if (dst_reg & 8) + fatal("SAR8 CL & 8\n"); + + codegen_alloc_bytes(block, 2); + codegen_addbyte2(block, 0xd2, 0xc0 | RM_OP_SAR | dst_reg); /*SAR dst_reg, CL*/ +} +void +host_x86_SAR16_CL(codeblock_t *block, int dst_reg) +{ + if (dst_reg & 8) + fatal("SAR16 CL & 8\n"); + + codegen_alloc_bytes(block, 3); + codegen_addbyte3(block, 0x66, 0xd3, 0xc0 | RM_OP_SAR | dst_reg); /*SAR dst_reg, CL*/ +} +void +host_x86_SAR32_CL(codeblock_t *block, int dst_reg) +{ + if (dst_reg & 8) + fatal("SAR32 CL & 8\n"); + + codegen_alloc_bytes(block, 2); + codegen_addbyte2(block, 0xd3, 0xc0 | RM_OP_SAR | dst_reg); /*SAR dst_reg, CL*/ +} + +void +host_x86_SAR8_IMM(codeblock_t *block, int dst_reg, int shift) +{ + if (dst_reg & 8) + fatal("SAR8 imm & 8\n"); + + codegen_alloc_bytes(block, 3); + codegen_addbyte3(block, 0xc0, 0xc0 | RM_OP_SAR | dst_reg, shift); /*SAR dst_reg, shift*/ +} +void +host_x86_SAR16_IMM(codeblock_t *block, int dst_reg, int shift) +{ + if (dst_reg & 8) + fatal("SAR16 imm & 8\n"); + + codegen_alloc_bytes(block, 4); + codegen_addbyte4(block, 0x66, 0xc1, 0xc0 | RM_OP_SAR | dst_reg, shift); /*SAR dst_reg, shift*/ +} +void +host_x86_SAR32_IMM(codeblock_t *block, int dst_reg, int shift) +{ + if (dst_reg & 8) + fatal("SAR32 imm & 8\n"); + codegen_alloc_bytes(block, 3); + codegen_addbyte3(block, 0xc1, 0xc0 | RM_OP_SAR | dst_reg, shift); /*SAR dst_reg, shift*/ +} + +void +host_x86_SHL8_CL(codeblock_t *block, int dst_reg) +{ + if (dst_reg & 8) + fatal("SHL8 CL & 8\n"); + + codegen_alloc_bytes(block, 2); + codegen_addbyte2(block, 0xd2, 0xc0 | RM_OP_SHL | dst_reg); /*SHL dst_reg, CL*/ +} +void +host_x86_SHL16_CL(codeblock_t *block, int dst_reg) +{ + if (dst_reg & 8) + fatal("SHL16 CL & 8\n"); + + codegen_alloc_bytes(block, 3); + codegen_addbyte3(block, 0x66, 0xd3, 0xc0 | RM_OP_SHL | dst_reg); /*SHL dst_reg, CL*/ +} +void +host_x86_SHL32_CL(codeblock_t *block, int dst_reg) +{ + if (dst_reg & 8) + fatal("SHL32 CL & 8\n"); + + codegen_alloc_bytes(block, 2); + codegen_addbyte2(block, 0xd3, 0xc0 | RM_OP_SHL | dst_reg); /*SHL dst_reg, CL*/ +} + +void +host_x86_SHL8_IMM(codeblock_t *block, int dst_reg, int shift) +{ + if (dst_reg & 8) + fatal("SHL8 imm & 8\n"); + + codegen_alloc_bytes(block, 3); + codegen_addbyte3(block, 0xc0, 0xc0 | RM_OP_SHL | dst_reg, shift); /*SHL dst_reg, shift*/ +} +void +host_x86_SHL16_IMM(codeblock_t *block, int dst_reg, int shift) +{ + if (dst_reg & 8) + fatal("SHL16 imm & 8\n"); + + codegen_alloc_bytes(block, 4); + codegen_addbyte4(block, 0x66, 0xc1, 0xc0 | RM_OP_SHL | dst_reg, shift); /*SHL dst_reg, shift*/ +} +void +host_x86_SHL32_IMM(codeblock_t *block, int dst_reg, int shift) +{ + if (dst_reg & 8) + fatal("SHL32 imm & 8\n"); + + codegen_alloc_bytes(block, 3); + codegen_addbyte3(block, 0xc1, 0xc0 | RM_OP_SHL | dst_reg, shift); /*SHL dst_reg, shift*/ +} + +void +host_x86_SHR8_CL(codeblock_t *block, int dst_reg) +{ + if (dst_reg & 8) + fatal("SHR8 CL & 8\n"); + + codegen_alloc_bytes(block, 2); + codegen_addbyte2(block, 0xd2, 0xc0 | RM_OP_SHR | dst_reg); /*SHR dst_reg, CL*/ +} +void +host_x86_SHR16_CL(codeblock_t *block, int dst_reg) +{ + if (dst_reg & 8) + fatal("SHR16 CL & 8\n"); + + codegen_alloc_bytes(block, 3); + codegen_addbyte3(block, 0x66, 0xd3, 0xc0 | RM_OP_SHR | dst_reg); /*SHR dst_reg, CL*/ +} +void +host_x86_SHR32_CL(codeblock_t *block, int dst_reg) +{ + if (dst_reg & 8) + fatal("SHR32 CL & 8\n"); + + codegen_alloc_bytes(block, 2); + codegen_addbyte2(block, 0xd3, 0xc0 | RM_OP_SHR | dst_reg); /*SHR dst_reg, CL*/ +} + +void +host_x86_SHR8_IMM(codeblock_t *block, int dst_reg, int shift) +{ + if (dst_reg & 8) + fatal("SHR8 imm & 8\n"); + + codegen_alloc_bytes(block, 3); + codegen_addbyte3(block, 0xc0, 0xc0 | RM_OP_SHR | dst_reg, shift); /*SHR dst_reg, shift*/ +} +void +host_x86_SHR16_IMM(codeblock_t *block, int dst_reg, int shift) +{ + if (dst_reg & 8) + fatal("SHR16 imm & 8\n"); + + codegen_alloc_bytes(block, 4); + codegen_addbyte4(block, 0x66, 0xc1, 0xc0 | RM_OP_SHR | dst_reg, shift); /*SHR dst_reg, shift*/ +} +void +host_x86_SHR32_IMM(codeblock_t *block, int dst_reg, int shift) +{ + if (dst_reg & 8) + fatal("SHR32 imm & 8\n"); + codegen_alloc_bytes(block, 3); + codegen_addbyte3(block, 0xc1, 0xc0 | RM_OP_SHR | dst_reg, shift); /*SHR dst_reg, shift*/ +} + +void +host_x86_SUB8_REG_IMM(codeblock_t *block, int dst_reg, uint8_t imm_data) +{ + if (dst_reg & 8) + fatal("host_x86_SUB8_REG_IMM - dst_reg & 8\n"); + + if (dst_reg == REG_EAX) { + codegen_alloc_bytes(block, 2); + codegen_addbyte2(block, 0x2c, imm_data); /*SUB EAX, imm_data*/ + } else { + codegen_alloc_bytes(block, 3); + codegen_addbyte3(block, 0x80, 0xc0 | RM_OP_SUB | (dst_reg & 7), imm_data); /*SUB dst_reg, imm_data*/ + } +} +void +host_x86_SUB16_REG_IMM(codeblock_t *block, int dst_reg, uint16_t imm_data) +{ + if (dst_reg & 8) + fatal("host_x86_SUB16_REG_IMM - dst_reg & 8\n"); + + if (is_imm8(imm_data)) { codegen_alloc_bytes(block, 4); - codegen_addbyte4(block, 0x66, 0xc1, 0xc0 | RM_OP_ROL | dst_reg, shift); /*SHL dst_reg, shift*/ -} -void host_x86_ROL32_IMM(codeblock_t *block, int dst_reg, int shift) -{ - if (dst_reg & 8) - fatal("ROL32 imm & 8\n"); - codegen_alloc_bytes(block, 3); - codegen_addbyte3(block, 0xc1, 0xc0 | RM_OP_ROL | dst_reg, shift); /*SHL dst_reg, shift*/ -} - -void host_x86_ROR8_CL(codeblock_t *block, int dst_reg) -{ - if (dst_reg & 8) - fatal("ROR8 CL & 8\n"); - codegen_alloc_bytes(block, 2); - codegen_addbyte2(block, 0xd2, 0xc0 | RM_OP_ROR | dst_reg); /*SHR dst_reg, CL*/ -} -void host_x86_ROR16_CL(codeblock_t *block, int dst_reg) -{ - if (dst_reg & 8) - fatal("ROR16 CL & 8\n"); - codegen_alloc_bytes(block, 3); - codegen_addbyte3(block, 0x66, 0xd3, 0xc0 | RM_OP_ROR | dst_reg); /*SHR dst_reg, CL*/ -} -void host_x86_ROR32_CL(codeblock_t *block, int dst_reg) -{ - if (dst_reg & 8) - fatal("ROR32 CL & 8\n"); - codegen_alloc_bytes(block, 2); - codegen_addbyte2(block, 0xd3, 0xc0 | RM_OP_ROR | dst_reg); /*SHR dst_reg, CL*/ -} - -void host_x86_ROR8_IMM(codeblock_t *block, int dst_reg, int shift) -{ - if (dst_reg & 8) - fatal("ROR8 imm & 8\n"); - codegen_alloc_bytes(block, 3); - codegen_addbyte3(block, 0xc0, 0xc0 | RM_OP_ROR | dst_reg, shift); /*SHR dst_reg, shift*/ -} -void host_x86_ROR16_IMM(codeblock_t *block, int dst_reg, int shift) -{ - if (dst_reg & 8) - fatal("ROR16 imm & 8\n"); + codegen_addbyte4(block, 0x66, 0x83, 0xc0 | RM_OP_SUB | (dst_reg & 7), imm_data & 0xff); /*SUB dst_reg, imm_data*/ + } else if (dst_reg == REG_EAX) { codegen_alloc_bytes(block, 4); - codegen_addbyte4(block, 0x66, 0xc1, 0xc0 | RM_OP_ROR | dst_reg, shift); /*SHR dst_reg, shift*/ + codegen_addbyte2(block, 0x66, 0x2d); /*SUB AX, imm_data*/ + codegen_addword(block, imm_data); + } else { + codegen_alloc_bytes(block, 5); + codegen_addbyte3(block, 0x66, 0x81, 0xc0 | RM_OP_SUB | (dst_reg & 7)); /*SUB dst_reg, imm_data*/ + codegen_addword(block, imm_data); + } } -void host_x86_ROR32_IMM(codeblock_t *block, int dst_reg, int shift) +void +host_x86_SUB32_REG_IMM(codeblock_t *block, int dst_reg, uint32_t imm_data) { - if (dst_reg & 8) - fatal("ROR32 im & 8\n"); + if (dst_reg & 8) + fatal("host_x86_SUB32_REG_IMM - dst_reg & 8\n"); + + if (is_imm8(imm_data)) { codegen_alloc_bytes(block, 3); - codegen_addbyte3(block, 0xc1, 0xc0 | RM_OP_ROR | dst_reg, shift); /*SHR dst_reg, shift*/ + codegen_addbyte3(block, 0x83, 0xc0 | RM_OP_SUB | (dst_reg & 7), imm_data & 0xff); /*SUB dst_reg, imm_data*/ + } else if (dst_reg == REG_EAX) { + codegen_alloc_bytes(block, 5); + codegen_addbyte(block, 0x2d); /*SUB EAX, imm_data*/ + codegen_addlong(block, imm_data); + } else { + codegen_alloc_bytes(block, 6); + codegen_addbyte2(block, 0x81, 0xc0 | RM_OP_SUB | (dst_reg & 7)); /*SUB dst_reg, imm_data*/ + codegen_addlong(block, imm_data); + } } - -void host_x86_SAR8_CL(codeblock_t *block, int dst_reg) +void +host_x86_SUB64_REG_IMM(codeblock_t *block, int dst_reg, uint64_t imm_data) { - if (dst_reg & 8) - fatal("SAR8 CL & 8\n"); - - codegen_alloc_bytes(block, 2); - codegen_addbyte2(block, 0xd2, 0xc0 | RM_OP_SAR | dst_reg); /*SAR dst_reg, CL*/ -} -void host_x86_SAR16_CL(codeblock_t *block, int dst_reg) -{ - if (dst_reg & 8) - fatal("SAR16 CL & 8\n"); - - codegen_alloc_bytes(block, 3); - codegen_addbyte3(block, 0x66, 0xd3, 0xc0 | RM_OP_SAR | dst_reg); /*SAR dst_reg, CL*/ -} -void host_x86_SAR32_CL(codeblock_t *block, int dst_reg) -{ - if (dst_reg & 8) - fatal("SAR32 CL & 8\n"); - - codegen_alloc_bytes(block, 2); - codegen_addbyte2(block, 0xd3, 0xc0 | RM_OP_SAR | dst_reg); /*SAR dst_reg, CL*/ -} - -void host_x86_SAR8_IMM(codeblock_t *block, int dst_reg, int shift) -{ - if (dst_reg & 8) - fatal("SAR8 imm & 8\n"); - - codegen_alloc_bytes(block, 3); - codegen_addbyte3(block, 0xc0, 0xc0 | RM_OP_SAR | dst_reg, shift); /*SAR dst_reg, shift*/ -} -void host_x86_SAR16_IMM(codeblock_t *block, int dst_reg, int shift) -{ - if (dst_reg & 8) - fatal("SAR16 imm & 8\n"); + if (dst_reg & 8) + fatal("host_x86_SUB64_REG_IMM - dst_reg & 8\n"); + if (is_imm8(imm_data)) { codegen_alloc_bytes(block, 4); - codegen_addbyte4(block, 0x66, 0xc1, 0xc0 | RM_OP_SAR | dst_reg, shift); /*SAR dst_reg, shift*/ + codegen_addbyte4(block, 0x48, 0x83, 0xc0 | RM_OP_SUB | (dst_reg & 7), imm_data & 0xff); /*SUB dst_reg, imm_data*/ + } else + fatal("SUB64_REG_IMM !is_imm8 %016" PRIx64 "\n", imm_data); } -void host_x86_SAR32_IMM(codeblock_t *block, int dst_reg, int shift) +void +host_x86_SUB8_REG_REG(codeblock_t *block, int dst_reg, int src_reg) { - if (dst_reg & 8) - fatal("SAR32 imm & 8\n"); - codegen_alloc_bytes(block, 3); - codegen_addbyte3(block, 0xc1, 0xc0 | RM_OP_SAR | dst_reg, shift); /*SAR dst_reg, shift*/ + if ((dst_reg & 8) || (src_reg & 8)) + fatal("host_x86_SUB8_REG_REG - dst_reg & 8\n"); + + codegen_alloc_bytes(block, 2); + codegen_addbyte2(block, 0x28, 0xc0 | (dst_reg & 7) | ((src_reg & 7) << 3)); /*SUB dst_reg, src_reg*/ +} +void +host_x86_SUB16_REG_REG(codeblock_t *block, int dst_reg, int src_reg) +{ + if ((dst_reg & 8) || (src_reg & 8)) + fatal("host_x86_SUB16_REG_REG - dst_reg & 8\n"); + + codegen_alloc_bytes(block, 3); + codegen_addbyte3(block, 0x66, 0x29, 0xc0 | (dst_reg & 7) | ((src_reg & 7) << 3)); /*SUB dst_reg, src_reg*/ +} +void +host_x86_SUB32_REG_REG(codeblock_t *block, int dst_reg, int src_reg) +{ + if ((dst_reg & 8) || (src_reg & 8)) + fatal("host_x86_SUB32_REG_REG - dst_reg & 8\n"); + + codegen_alloc_bytes(block, 2); + codegen_addbyte2(block, 0x29, 0xc0 | (dst_reg & 7) | ((src_reg & 7) << 3)); /*SUB dst_reg, src_reg*/ } -void host_x86_SHL8_CL(codeblock_t *block, int dst_reg) -{ - if (dst_reg & 8) - fatal("SHL8 CL & 8\n"); +# define MODRM_MOD_REG(rm, reg) (0xc0 | reg | (rm << 3)) +void +host_x86_TEST8_REG(codeblock_t *block, int src_host_reg, int dst_host_reg) +{ + codegen_alloc_bytes(block, 2); + codegen_addbyte2(block, 0x84, MODRM_MOD_REG(dst_host_reg, src_host_reg)); /*TEST dst_host_reg, src_host_reg*/ +} +void +host_x86_TEST16_REG(codeblock_t *block, int src_host_reg, int dst_host_reg) +{ + codegen_alloc_bytes(block, 3); + codegen_addbyte3(block, 0x66, 0x85, MODRM_MOD_REG(dst_host_reg, src_host_reg)); /*TEST dst_host_reg, src_host_reg*/ +} +void +host_x86_TEST32_REG(codeblock_t *block, int src_reg, int dst_reg) +{ + if ((dst_reg & 8) || (src_reg & 8)) + fatal("host_x86_TEST32_REG - bad reg\n"); + + codegen_alloc_bytes(block, 2); + codegen_addbyte2(block, 0x85, MODRM_MOD_REG(dst_reg, src_reg)); /*TEST dst_host_reg, src_host_reg*/ +} +void +host_x86_TEST32_REG_IMM(codeblock_t *block, int dst_reg, uint32_t imm_data) +{ + if (dst_reg & 8) + fatal("TEST32_REG_IMM reg & 8\n"); + if (dst_reg == REG_EAX) { + codegen_alloc_bytes(block, 5); + codegen_addbyte(block, 0xa9); /*TEST EAX, imm_data*/ + codegen_addlong(block, imm_data); + } else { + codegen_alloc_bytes(block, 6); + codegen_addbyte2(block, 0xf7, 0xc0 | dst_reg); /*TEST dst_reg, imm_data*/ + codegen_addlong(block, imm_data); + } +} + +void +host_x86_XOR8_REG_IMM(codeblock_t *block, int dst_reg, uint8_t imm_data) +{ + if (dst_reg & 8) + fatal("host_x86_XOR8_REG_IMM - dst_reg & 8\n"); + + if (dst_reg == REG_EAX) { codegen_alloc_bytes(block, 2); - codegen_addbyte2(block, 0xd2, 0xc0 | RM_OP_SHL | dst_reg); /*SHL dst_reg, CL*/ -} -void host_x86_SHL16_CL(codeblock_t *block, int dst_reg) -{ - if (dst_reg & 8) - fatal("SHL16 CL & 8\n"); - + codegen_addbyte2(block, 0x34, imm_data); /*XOR EAX, imm_data*/ + } else { codegen_alloc_bytes(block, 3); - codegen_addbyte3(block, 0x66, 0xd3, 0xc0 | RM_OP_SHL | dst_reg); /*SHL dst_reg, CL*/ + codegen_addbyte3(block, 0x80, 0xc0 | RM_OP_XOR | (dst_reg & 7), imm_data); /*XOR dst_reg, imm_data*/ + } } -void host_x86_SHL32_CL(codeblock_t *block, int dst_reg) +void +host_x86_XOR16_REG_IMM(codeblock_t *block, int dst_reg, uint16_t imm_data) { - if (dst_reg & 8) - fatal("SHL32 CL & 8\n"); - - codegen_alloc_bytes(block, 2); - codegen_addbyte2(block, 0xd3, 0xc0 | RM_OP_SHL | dst_reg); /*SHL dst_reg, CL*/ -} - -void host_x86_SHL8_IMM(codeblock_t *block, int dst_reg, int shift) -{ - if (dst_reg & 8) - fatal("SHL8 imm & 8\n"); - - codegen_alloc_bytes(block, 3); - codegen_addbyte3(block, 0xc0, 0xc0 | RM_OP_SHL | dst_reg, shift); /*SHL dst_reg, shift*/ -} -void host_x86_SHL16_IMM(codeblock_t *block, int dst_reg, int shift) -{ - if (dst_reg & 8) - fatal("SHL16 imm & 8\n"); + if (dst_reg & 8) + fatal("host_x86_XOR16_REG_IMM - dst_reg & 8\n"); + if (is_imm8(imm_data)) { codegen_alloc_bytes(block, 4); - codegen_addbyte4(block, 0x66, 0xc1, 0xc0 | RM_OP_SHL | dst_reg, shift); /*SHL dst_reg, shift*/ -} -void host_x86_SHL32_IMM(codeblock_t *block, int dst_reg, int shift) -{ - if (dst_reg & 8) - fatal("SHL32 imm & 8\n"); - - codegen_alloc_bytes(block, 3); - codegen_addbyte3(block, 0xc1, 0xc0 | RM_OP_SHL | dst_reg, shift); /*SHL dst_reg, shift*/ -} - -void host_x86_SHR8_CL(codeblock_t *block, int dst_reg) -{ - if (dst_reg & 8) - fatal("SHR8 CL & 8\n"); - - codegen_alloc_bytes(block, 2); - codegen_addbyte2(block, 0xd2, 0xc0 | RM_OP_SHR | dst_reg); /*SHR dst_reg, CL*/ -} -void host_x86_SHR16_CL(codeblock_t *block, int dst_reg) -{ - if (dst_reg & 8) - fatal("SHR16 CL & 8\n"); - - codegen_alloc_bytes(block, 3); - codegen_addbyte3(block, 0x66, 0xd3, 0xc0 | RM_OP_SHR | dst_reg); /*SHR dst_reg, CL*/ -} -void host_x86_SHR32_CL(codeblock_t *block, int dst_reg) -{ - if (dst_reg & 8) - fatal("SHR32 CL & 8\n"); - - codegen_alloc_bytes(block, 2); - codegen_addbyte2(block, 0xd3, 0xc0 | RM_OP_SHR | dst_reg); /*SHR dst_reg, CL*/ -} - -void host_x86_SHR8_IMM(codeblock_t *block, int dst_reg, int shift) -{ - if (dst_reg & 8) - fatal("SHR8 imm & 8\n"); - - codegen_alloc_bytes(block, 3); - codegen_addbyte3(block, 0xc0, 0xc0 | RM_OP_SHR | dst_reg, shift); /*SHR dst_reg, shift*/ -} -void host_x86_SHR16_IMM(codeblock_t *block, int dst_reg, int shift) -{ - if (dst_reg & 8) - fatal("SHR16 imm & 8\n"); - + codegen_addbyte4(block, 0x66, 0x83, 0xc0 | RM_OP_XOR | (dst_reg & 7), imm_data & 0xff); /*XOR dst_reg, imm_data*/ + } else if (dst_reg == REG_EAX) { codegen_alloc_bytes(block, 4); - codegen_addbyte4(block, 0x66, 0xc1, 0xc0 | RM_OP_SHR | dst_reg, shift); /*SHR dst_reg, shift*/ + codegen_addbyte2(block, 0x66, 0x35); /*XOR AX, imm_data*/ + codegen_addword(block, imm_data); + } else { + codegen_alloc_bytes(block, 5); + codegen_addbyte3(block, 0x66, 0x81, 0xc0 | RM_OP_XOR | (dst_reg & 7)); /*XOR dst_reg, imm_data*/ + codegen_addword(block, imm_data); + } } -void host_x86_SHR32_IMM(codeblock_t *block, int dst_reg, int shift) +void +host_x86_XOR32_REG_IMM(codeblock_t *block, int dst_reg, uint32_t imm_data) { - if (dst_reg & 8) - fatal("SHR32 imm & 8\n"); + if (dst_reg & 8) + fatal("host_x86_XOR32_REG_IMM - dst_reg & 8\n"); + + if (is_imm8(imm_data)) { codegen_alloc_bytes(block, 3); - codegen_addbyte3(block, 0xc1, 0xc0 | RM_OP_SHR | dst_reg, shift); /*SHR dst_reg, shift*/ + codegen_addbyte3(block, 0x83, 0xc0 | RM_OP_XOR | (dst_reg & 7), imm_data & 0xff); /*XOR dst_reg, imm_data*/ + } else if (dst_reg == REG_EAX) { + codegen_alloc_bytes(block, 5); + codegen_addbyte(block, 0x35); /*XOR EAX, imm_data*/ + codegen_addlong(block, imm_data); + } else { + codegen_alloc_bytes(block, 6); + codegen_addbyte2(block, 0x81, 0xc0 | RM_OP_XOR | (dst_reg & 7)); /*XOR dst_reg, imm_data*/ + codegen_addlong(block, imm_data); + } } - -void host_x86_SUB8_REG_IMM(codeblock_t *block, int dst_reg, uint8_t imm_data) +void +host_x86_XOR8_REG_REG(codeblock_t *block, int dst_reg, int src_reg) { - if (dst_reg & 8) - fatal("host_x86_SUB8_REG_IMM - dst_reg & 8\n"); + if ((dst_reg & 8) || (src_reg & 8)) + fatal("host_x86_XOR8_REG_IMM - dst_reg & 8\n"); - if (dst_reg == REG_EAX) - { - codegen_alloc_bytes(block, 2); - codegen_addbyte2(block, 0x2c, imm_data); /*SUB EAX, imm_data*/ - } - else - { - codegen_alloc_bytes(block, 3); - codegen_addbyte3(block, 0x80, 0xc0 | RM_OP_SUB | (dst_reg & 7), imm_data); /*SUB dst_reg, imm_data*/ - } + codegen_alloc_bytes(block, 2); + codegen_addbyte2(block, 0x30, 0xc0 | (dst_reg & 7) | ((src_reg & 7) << 3)); /*XOR dst_reg, src_reg*/ } -void host_x86_SUB16_REG_IMM(codeblock_t *block, int dst_reg, uint16_t imm_data) +void +host_x86_XOR16_REG_REG(codeblock_t *block, int dst_reg, int src_reg) { - if (dst_reg & 8) - fatal("host_x86_SUB16_REG_IMM - dst_reg & 8\n"); + if ((dst_reg & 8) || (src_reg & 8)) + fatal("host_x86_XOR16_REG_IMM - dst_reg & 8\n"); - if (is_imm8(imm_data)) - { - codegen_alloc_bytes(block, 4); - codegen_addbyte4(block, 0x66, 0x83, 0xc0 | RM_OP_SUB | (dst_reg & 7), imm_data & 0xff); /*SUB dst_reg, imm_data*/ - } - else if (dst_reg == REG_EAX) - { - codegen_alloc_bytes(block, 4); - codegen_addbyte2(block, 0x66, 0x2d); /*SUB AX, imm_data*/ - codegen_addword(block, imm_data); - } - else - { - codegen_alloc_bytes(block, 5); - codegen_addbyte3(block, 0x66, 0x81, 0xc0 | RM_OP_SUB | (dst_reg & 7)); /*SUB dst_reg, imm_data*/ - codegen_addword(block, imm_data); - } + codegen_alloc_bytes(block, 3); + codegen_addbyte3(block, 0x66, 0x31, 0xc0 | (dst_reg & 7) | ((src_reg & 7) << 3)); /*XOR dst_reg, src_reg*/ } -void host_x86_SUB32_REG_IMM(codeblock_t *block, int dst_reg, uint32_t imm_data) +void +host_x86_XOR32_REG_REG(codeblock_t *block, int dst_reg, int src_reg) { - if (dst_reg & 8) - fatal("host_x86_SUB32_REG_IMM - dst_reg & 8\n"); + if ((dst_reg & 8) || (src_reg & 8)) + fatal("host_x86_XOR32_REG_IMM - dst_reg & 8\n"); - if (is_imm8(imm_data)) - { - codegen_alloc_bytes(block, 3); - codegen_addbyte3(block, 0x83, 0xc0 | RM_OP_SUB | (dst_reg & 7), imm_data & 0xff); /*SUB dst_reg, imm_data*/ - } - else if (dst_reg == REG_EAX) - { - codegen_alloc_bytes(block, 5); - codegen_addbyte(block, 0x2d); /*SUB EAX, imm_data*/ - codegen_addlong(block, imm_data); - } - else - { - codegen_alloc_bytes(block, 6); - codegen_addbyte2(block, 0x81, 0xc0 | RM_OP_SUB | (dst_reg & 7)); /*SUB dst_reg, imm_data*/ - codegen_addlong(block, imm_data); - } -} -void host_x86_SUB64_REG_IMM(codeblock_t *block, int dst_reg, uint64_t imm_data) -{ - if (dst_reg & 8) - fatal("host_x86_SUB64_REG_IMM - dst_reg & 8\n"); - - if (is_imm8(imm_data)) - { - codegen_alloc_bytes(block, 4); - codegen_addbyte4(block, 0x48, 0x83, 0xc0 | RM_OP_SUB | (dst_reg & 7), imm_data & 0xff); /*SUB dst_reg, imm_data*/ - } - else - fatal("SUB64_REG_IMM !is_imm8 %016llx\n", imm_data); -} -void host_x86_SUB8_REG_REG(codeblock_t *block, int dst_reg, int src_reg) -{ - if ((dst_reg & 8) || (src_reg & 8)) - fatal("host_x86_SUB8_REG_REG - dst_reg & 8\n"); - - codegen_alloc_bytes(block, 2); - codegen_addbyte2(block, 0x28, 0xc0 | (dst_reg & 7) | ((src_reg & 7) << 3)); /*SUB dst_reg, src_reg*/ -} -void host_x86_SUB16_REG_REG(codeblock_t *block, int dst_reg, int src_reg) -{ - if ((dst_reg & 8) || (src_reg & 8)) - fatal("host_x86_SUB16_REG_REG - dst_reg & 8\n"); - - codegen_alloc_bytes(block, 3); - codegen_addbyte3(block, 0x66, 0x29, 0xc0 | (dst_reg & 7) | ((src_reg & 7) << 3)); /*SUB dst_reg, src_reg*/ -} -void host_x86_SUB32_REG_REG(codeblock_t *block, int dst_reg, int src_reg) -{ - if ((dst_reg & 8) || (src_reg & 8)) - fatal("host_x86_SUB32_REG_REG - dst_reg & 8\n"); - - codegen_alloc_bytes(block, 2); - codegen_addbyte2(block, 0x29, 0xc0 | (dst_reg & 7) | ((src_reg & 7) << 3)); /*SUB dst_reg, src_reg*/ -} - -#define MODRM_MOD_REG(rm, reg) (0xc0 | reg | (rm << 3)) - -void host_x86_TEST8_REG(codeblock_t *block, int src_host_reg, int dst_host_reg) -{ - codegen_alloc_bytes(block, 2); - codegen_addbyte2(block, 0x84, MODRM_MOD_REG(dst_host_reg, src_host_reg)); /*TEST dst_host_reg, src_host_reg*/ -} -void host_x86_TEST16_REG(codeblock_t *block, int src_host_reg, int dst_host_reg) -{ - codegen_alloc_bytes(block, 3); - codegen_addbyte3(block, 0x66, 0x85, MODRM_MOD_REG(dst_host_reg, src_host_reg)); /*TEST dst_host_reg, src_host_reg*/ -} -void host_x86_TEST32_REG(codeblock_t *block, int src_reg, int dst_reg) -{ - if ((dst_reg & 8) || (src_reg & 8)) - fatal("host_x86_TEST32_REG - bad reg\n"); - - codegen_alloc_bytes(block, 2); - codegen_addbyte2(block, 0x85, MODRM_MOD_REG(dst_reg, src_reg)); /*TEST dst_host_reg, src_host_reg*/ -} -void host_x86_TEST32_REG_IMM(codeblock_t *block, int dst_reg, uint32_t imm_data) -{ - if (dst_reg & 8) - fatal("TEST32_REG_IMM reg & 8\n"); - if (dst_reg == REG_EAX) - { - codegen_alloc_bytes(block, 5); - codegen_addbyte(block, 0xa9); /*TEST EAX, imm_data*/ - codegen_addlong(block, imm_data); - } - else - { - codegen_alloc_bytes(block, 6); - codegen_addbyte2(block, 0xf7, 0xc0 | dst_reg); /*TEST dst_reg, imm_data*/ - codegen_addlong(block, imm_data); - } -} - -void host_x86_XOR8_REG_IMM(codeblock_t *block, int dst_reg, uint8_t imm_data) -{ - if (dst_reg & 8) - fatal("host_x86_XOR8_REG_IMM - dst_reg & 8\n"); - - if (dst_reg == REG_EAX) - { - codegen_alloc_bytes(block, 2); - codegen_addbyte2(block, 0x34, imm_data); /*XOR EAX, imm_data*/ - } - else - { - codegen_alloc_bytes(block, 3); - codegen_addbyte3(block, 0x80, 0xc0 | RM_OP_XOR | (dst_reg & 7), imm_data); /*XOR dst_reg, imm_data*/ - } -} -void host_x86_XOR16_REG_IMM(codeblock_t *block, int dst_reg, uint16_t imm_data) -{ - if (dst_reg & 8) - fatal("host_x86_XOR16_REG_IMM - dst_reg & 8\n"); - - if (is_imm8(imm_data)) - { - codegen_alloc_bytes(block, 4); - codegen_addbyte4(block, 0x66, 0x83, 0xc0 | RM_OP_XOR | (dst_reg & 7), imm_data & 0xff); /*XOR dst_reg, imm_data*/ - } - else if (dst_reg == REG_EAX) - { - codegen_alloc_bytes(block, 4); - codegen_addbyte2(block, 0x66, 0x35); /*XOR AX, imm_data*/ - codegen_addword(block, imm_data); - } - else - { - codegen_alloc_bytes(block, 5); - codegen_addbyte3(block, 0x66, 0x81, 0xc0 | RM_OP_XOR | (dst_reg & 7)); /*XOR dst_reg, imm_data*/ - codegen_addword(block, imm_data); - } -} -void host_x86_XOR32_REG_IMM(codeblock_t *block, int dst_reg, uint32_t imm_data) -{ - if (dst_reg & 8) - fatal("host_x86_XOR32_REG_IMM - dst_reg & 8\n"); - - if (is_imm8(imm_data)) - { - codegen_alloc_bytes(block, 3); - codegen_addbyte3(block, 0x83, 0xc0 | RM_OP_XOR | (dst_reg & 7), imm_data & 0xff); /*XOR dst_reg, imm_data*/ - } - else if (dst_reg == REG_EAX) - { - codegen_alloc_bytes(block, 5); - codegen_addbyte(block, 0x35); /*XOR EAX, imm_data*/ - codegen_addlong(block, imm_data); - } - else - { - codegen_alloc_bytes(block, 6); - codegen_addbyte2(block, 0x81, 0xc0 | RM_OP_XOR | (dst_reg & 7)); /*XOR dst_reg, imm_data*/ - codegen_addlong(block, imm_data); - } -} -void host_x86_XOR8_REG_REG(codeblock_t *block, int dst_reg, int src_reg) -{ - if ((dst_reg & 8) || (src_reg & 8)) - fatal("host_x86_XOR8_REG_IMM - dst_reg & 8\n"); - - codegen_alloc_bytes(block, 2); - codegen_addbyte2(block, 0x30, 0xc0 | (dst_reg & 7) | ((src_reg & 7) << 3)); /*XOR dst_reg, src_reg*/ -} -void host_x86_XOR16_REG_REG(codeblock_t *block, int dst_reg, int src_reg) -{ - if ((dst_reg & 8) || (src_reg & 8)) - fatal("host_x86_XOR16_REG_IMM - dst_reg & 8\n"); - - codegen_alloc_bytes(block, 3); - codegen_addbyte3(block, 0x66, 0x31, 0xc0 | (dst_reg & 7) | ((src_reg & 7) << 3)); /*XOR dst_reg, src_reg*/ -} -void host_x86_XOR32_REG_REG(codeblock_t *block, int dst_reg, int src_reg) -{ - if ((dst_reg & 8) || (src_reg & 8)) - fatal("host_x86_XOR32_REG_IMM - dst_reg & 8\n"); - - codegen_alloc_bytes(block, 2); - codegen_addbyte2(block, 0x31, 0xc0 | (dst_reg & 7) | ((src_reg & 7) << 3)); /*XOR dst_reg, src_reg*/ + codegen_alloc_bytes(block, 2); + codegen_addbyte2(block, 0x31, 0xc0 | (dst_reg & 7) | ((src_reg & 7) << 3)); /*XOR dst_reg, src_reg*/ } #endif diff --git a/src/codegen_new/codegen_backend_x86-64_ops_helpers.h b/src/codegen_new/codegen_backend_x86-64_ops_helpers.h index a7755d1a8..b5d146439 100644 --- a/src/codegen_new/codegen_backend_x86-64_ops_helpers.h +++ b/src/codegen_new/codegen_backend_x86-64_ops_helpers.h @@ -1,102 +1,105 @@ #define JMP_LEN_BYTES 5 -static inline void codegen_addbyte(codeblock_t *block, uint8_t val) +static inline void +codegen_addbyte(UNUSED(codeblock_t *block), uint8_t val) { - if (block_pos >= BLOCK_MAX) - { - fatal("codegen_addbyte over! %i\n", block_pos); -// CPU_BLOCK_END(); - } - block_write_data[block_pos++] = val; + if (block_pos >= BLOCK_MAX) { + fatal("codegen_addbyte over! %i\n", block_pos); +#if 0 + CPU_BLOCK_END(); +#endif + } + block_write_data[block_pos++] = val; } -static inline void codegen_addbyte2(codeblock_t *block, uint8_t vala, uint8_t valb) +static inline void +codegen_addbyte2(UNUSED(codeblock_t *block), uint8_t vala, uint8_t valb) { - if (block_pos > (BLOCK_MAX-2)) - { - fatal("codegen_addbyte2 over! %i\n", block_pos); - CPU_BLOCK_END(); - } - block_write_data[block_pos++] = vala; - block_write_data[block_pos++] = valb; + if (block_pos > (BLOCK_MAX - 2)) { + fatal("codegen_addbyte2 over! %i\n", block_pos); + CPU_BLOCK_END(); + } + block_write_data[block_pos++] = vala; + block_write_data[block_pos++] = valb; } -static inline void codegen_addbyte3(codeblock_t *block, uint8_t vala, uint8_t valb, uint8_t valc) +static inline void +codegen_addbyte3(UNUSED(codeblock_t *block), uint8_t vala, uint8_t valb, uint8_t valc) { - if (block_pos > (BLOCK_MAX-3)) - { - fatal("codegen_addbyte3 over! %i\n", block_pos); - CPU_BLOCK_END(); - } - block_write_data[block_pos++] = vala; - block_write_data[block_pos++] = valb; - block_write_data[block_pos++] = valc; + if (block_pos > (BLOCK_MAX - 3)) { + fatal("codegen_addbyte3 over! %i\n", block_pos); + CPU_BLOCK_END(); + } + block_write_data[block_pos++] = vala; + block_write_data[block_pos++] = valb; + block_write_data[block_pos++] = valc; } -static inline void codegen_addbyte4(codeblock_t *block, uint8_t vala, uint8_t valb, uint8_t valc, uint8_t vald) +static inline void +codegen_addbyte4(UNUSED(codeblock_t *block), uint8_t vala, uint8_t valb, uint8_t valc, uint8_t vald) { - if (block_pos > (BLOCK_MAX-4)) - { - fatal("codegen_addbyte4 over! %i\n", block_pos); - CPU_BLOCK_END(); - } - block_write_data[block_pos++] = vala; - block_write_data[block_pos++] = valb; - block_write_data[block_pos++] = valc; - block_write_data[block_pos++] = vald; + if (block_pos > (BLOCK_MAX - 4)) { + fatal("codegen_addbyte4 over! %i\n", block_pos); + CPU_BLOCK_END(); + } + block_write_data[block_pos++] = vala; + block_write_data[block_pos++] = valb; + block_write_data[block_pos++] = valc; + block_write_data[block_pos++] = vald; } -static inline void codegen_addword(codeblock_t *block, uint16_t val) +static inline void +codegen_addword(UNUSED(codeblock_t *block), uint16_t val) { - if (block_pos > (BLOCK_MAX-2)) - { - fatal("codegen_addword over! %i\n", block_pos); - CPU_BLOCK_END(); - } - *(uint16_t *)&block_write_data[block_pos] = val; - block_pos += 2; + if (block_pos > (BLOCK_MAX - 2)) { + fatal("codegen_addword over! %i\n", block_pos); + CPU_BLOCK_END(); + } + *(uint16_t *) &block_write_data[block_pos] = val; + block_pos += 2; } -static inline void codegen_addlong(codeblock_t *block, uint32_t val) +static inline void +codegen_addlong(UNUSED(codeblock_t *block), uint32_t val) { - if (block_pos > (BLOCK_MAX-4)) - { - fatal("codegen_addlong over! %i\n", block_pos); - CPU_BLOCK_END(); - } - *(uint32_t *)&block_write_data[block_pos] = val; - block_pos += 4; + if (block_pos > (BLOCK_MAX - 4)) { + fatal("codegen_addlong over! %i\n", block_pos); + CPU_BLOCK_END(); + } + *(uint32_t *) &block_write_data[block_pos] = val; + block_pos += 4; } -static inline void codegen_addquad(codeblock_t *block, uint64_t val) +static inline void +codegen_addquad(UNUSED(codeblock_t *block), uint64_t val) { - if (block_pos > (BLOCK_MAX-8)) - { - fatal("codegen_addquad over! %i\n", block_pos); - CPU_BLOCK_END(); - } - *(uint64_t *)&block_write_data[block_pos] = val; - block_pos += 8; + if (block_pos > (BLOCK_MAX - 8)) { + fatal("codegen_addquad over! %i\n", block_pos); + CPU_BLOCK_END(); + } + *(uint64_t *) &block_write_data[block_pos] = val; + block_pos += 8; } -static inline void codegen_alloc_bytes(codeblock_t *block, int size) +static inline void +codegen_alloc_bytes(codeblock_t *block, int size) { - if (block_pos > ((BLOCK_MAX - size) - JMP_LEN_BYTES)) - { - /*Current block is full. Allocate a new block*/ - struct mem_block_t *new_block = codegen_allocator_allocate(block->head_mem_block, get_block_nr(block)); - uint8_t *new_ptr = codeblock_allocator_get_ptr(new_block); + if (block_pos > ((BLOCK_MAX - size) - JMP_LEN_BYTES)) { + /*Current block is full. Allocate a new block*/ + struct mem_block_t *new_block = codegen_allocator_allocate(block->head_mem_block, get_block_nr(block)); + uint8_t *new_ptr = codeblock_allocator_get_ptr(new_block); - /*Add a jump instruction to the new block*/ - codegen_addbyte(block, 0xe9); /*JMP*/ - codegen_addlong(block, (uintptr_t)new_ptr - (uintptr_t)&block_write_data[block_pos + 4]); + /*Add a jump instruction to the new block*/ + codegen_addbyte(block, 0xe9); /*JMP*/ + codegen_addlong(block, (uintptr_t) new_ptr - (uintptr_t) &block_write_data[block_pos + 4]); - /*Set write address to start of new block*/ - block_pos = 0; - block_write_data = new_ptr; - } + /*Set write address to start of new block*/ + block_pos = 0; + block_write_data = new_ptr; + } } -static inline int is_imm8(uint32_t imm_data) +static inline int +is_imm8(uint32_t imm_data) { - if (imm_data <= 0x7f || imm_data >= 0xffffff80) - return 1; - return 0; + if (imm_data <= 0x7f || imm_data >= 0xffffff80) + return 1; + return 0; } diff --git a/src/codegen_new/codegen_backend_x86-64_ops_sse.c b/src/codegen_new/codegen_backend_x86-64_ops_sse.c index e2a4e7044..caa925fc0 100644 --- a/src/codegen_new/codegen_backend_x86-64_ops_sse.c +++ b/src/codegen_new/codegen_backend_x86-64_ops_sse.c @@ -1,618 +1,679 @@ #if defined __amd64__ || defined _M_X64 -#include -#include <86box/86box.h> -#include "cpu.h" -#include <86box/mem.h> +# include +# include <86box/86box.h> +# include "cpu.h" +# include <86box/mem.h> +# include <86box/plat_unused.h> -#include "codegen.h" -#include "codegen_allocator.h" -#include "codegen_backend.h" -#include "codegen_backend_x86-64_defs.h" -#include "codegen_backend_x86-64_ops_sse.h" -#include "codegen_backend_x86-64_ops_helpers.h" +# include "codegen.h" +# include "codegen_allocator.h" +# include "codegen_backend.h" +# include "codegen_backend_x86-64_defs.h" +# include "codegen_backend_x86-64_ops_sse.h" +# include "codegen_backend_x86-64_ops_helpers.h" -void host_x86_ADDPS_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg) +void +host_x86_ADDPS_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg) { - codegen_alloc_bytes(block, 3); - codegen_addbyte3(block, 0x0f, 0x58, 0xc0 | src_reg | (dst_reg << 3)); /*ADDPS dst_reg, src_reg*/ + codegen_alloc_bytes(block, 3); + codegen_addbyte3(block, 0x0f, 0x58, 0xc0 | src_reg | (dst_reg << 3)); /*ADDPS dst_reg, src_reg*/ } -void host_x86_ADDSD_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg) +void +host_x86_ADDSD_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg) { + codegen_alloc_bytes(block, 4); + codegen_addbyte4(block, 0xf2, 0x0f, 0x58, 0xc0 | src_reg | (dst_reg << 3)); +} + +void +host_x86_CMPPS_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg, int type) +{ + codegen_alloc_bytes(block, 4); + codegen_addbyte4(block, 0x0f, 0xc2, 0xc0 | src_reg | (dst_reg << 3), type); /*CMPPS dst_reg, src_reg, type*/ +} + +void +host_x86_COMISD_XREG_XREG(codeblock_t *block, int src_reg_a, int src_reg_b) +{ + codegen_alloc_bytes(block, 4); + codegen_addbyte4(block, 0x66, 0x0f, 0x2e, 0xc0 | src_reg_b | (src_reg_a << 3)); +} + +void +host_x86_CVTDQ2PS_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg) +{ + codegen_alloc_bytes(block, 3); + codegen_addbyte3(block, 0x0f, 0x5b, 0xc0 | src_reg | (dst_reg << 3)); /*CVTDQ2PS dst_reg, src_reg*/ +} +void +host_x86_CVTPS2DQ_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg) +{ + codegen_alloc_bytes(block, 4); + codegen_addbyte4(block, 0x66, 0x0f, 0x5b, 0xc0 | src_reg | (dst_reg << 3)); /*CVTPS2DQ dst_reg, src_reg*/ +} + +void +host_x86_CVTSD2SI_REG_XREG(codeblock_t *block, int dst_reg, int src_reg) +{ + codegen_alloc_bytes(block, 4); + codegen_addbyte4(block, 0xf2, 0x0f, 0x2d, 0xc0 | src_reg | (dst_reg << 3)); /*CVTSD2SI dst_reg, src_reg*/ +} +void +host_x86_CVTSD2SI_REG64_XREG(codeblock_t *block, int dst_reg, int src_reg) +{ + codegen_alloc_bytes(block, 5); + codegen_addbyte4(block, 0xf2, 0x48, 0x0f, 0x2d); /*CVTSD2SI dst_reg, src_reg*/ + codegen_addbyte(block, 0xc0 | src_reg | (dst_reg << 3)); +} +void +host_x86_CVTSD2SS_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg) +{ + codegen_alloc_bytes(block, 4); + codegen_addbyte4(block, 0xf2, 0x0f, 0x5a, 0xc0 | src_reg | (dst_reg << 3)); +} + +void +host_x86_CVTSI2SD_XREG_REG(codeblock_t *block, int dst_reg, int src_reg) +{ + codegen_alloc_bytes(block, 4); + codegen_addbyte4(block, 0xf2, 0x0f, 0x2a, 0xc0 | src_reg | (dst_reg << 3)); /*CVTSI2SD dst_reg, src_reg*/ +} +void +host_x86_CVTSI2SS_XREG_REG(codeblock_t *block, int dst_reg, int src_reg) +{ + codegen_alloc_bytes(block, 4); + codegen_addbyte4(block, 0xf3, 0x0f, 0x2a, 0xc0 | src_reg | (dst_reg << 3)); /*CVTSI2SD dst_reg, src_reg*/ +} +void +host_x86_CVTSI2SD_XREG_REG64(codeblock_t *block, int dst_reg, int src_reg) +{ + codegen_alloc_bytes(block, 5); + codegen_addbyte4(block, 0xf2, 0x48, 0x0f, 0x2a); /*CVTSI2SD dst_reg, src_reg*/ + codegen_addbyte(block, 0xc0 | src_reg | (dst_reg << 3)); +} + +void +host_x86_CVTSS2SD_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg) +{ + codegen_alloc_bytes(block, 4); + codegen_addbyte4(block, 0xf3, 0x0f, 0x5a, 0xc0 | src_reg | (dst_reg << 3)); +} +void +host_x86_CVTSS2SD_XREG_BASE_INDEX(codeblock_t *block, int dst_reg, int base_reg, int idx_reg) +{ + codegen_alloc_bytes(block, 4); + codegen_addbyte4(block, 0xf3, 0x0f, 0x5a, 0x04 | (dst_reg << 3)); /*CVTSS2SD XMMx, [base_reg + idx_reg]*/ + codegen_addbyte(block, base_reg | (idx_reg << 3)); +} + +void +host_x86_DIVSD_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg) +{ + codegen_alloc_bytes(block, 4); + codegen_addbyte4(block, 0xf2, 0x0f, 0x5e, 0xc0 | src_reg | (dst_reg << 3)); +} +void +host_x86_DIVSS_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg) +{ + codegen_alloc_bytes(block, 4); + codegen_addbyte4(block, 0xf3, 0x0f, 0x5e, 0xc0 | src_reg | (dst_reg << 3)); /*DIVSS dst_reg, src_reg*/ +} + +void +host_x86_LDMXCSR(codeblock_t *block, void *p) +{ + int offset = (uintptr_t) p - (((uintptr_t) &cpu_state) + 128); + + if (offset >= -128 && offset < 127) { codegen_alloc_bytes(block, 4); - codegen_addbyte4(block, 0xf2, 0x0f, 0x58, 0xc0 | src_reg | (dst_reg << 3)); + codegen_addbyte4(block, 0x0f, 0xae, 0x50 | REG_EBP, offset); /*LDMXCSR offset[EBP]*/ + } else if (offset < (1ULL << 32)) { + codegen_alloc_bytes(block, 7); + codegen_addbyte3(block, 0x0f, 0xae, 0x90 | REG_EBP); /*LDMXCSR offset[EBP]*/ + codegen_addlong(block, offset); + } else { + fatal("host_x86_LDMXCSR - out of range %p\n", p); + } } -void host_x86_CMPPS_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg, int type) +void +host_x86_MAXSD_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg) { - codegen_alloc_bytes(block, 4); - codegen_addbyte4(block, 0x0f, 0xc2, 0xc0 | src_reg | (dst_reg << 3), type); /*CMPPS dst_reg, src_reg, type*/ + codegen_alloc_bytes(block, 4); + codegen_addbyte4(block, 0xf2, 0x0f, 0x5f, 0xc0 | src_reg | (dst_reg << 3)); /*MAXSD dst_reg, src_reg*/ } -void host_x86_COMISD_XREG_XREG(codeblock_t *block, int src_reg_a, int src_reg_b) +void +host_x86_MOVD_BASE_INDEX_XREG(codeblock_t *block, int base_reg, int idx_reg, int src_reg) { - codegen_alloc_bytes(block, 4); - codegen_addbyte4(block, 0x66, 0x0f, 0x2e, 0xc0 | src_reg_b | (src_reg_a << 3)); + codegen_alloc_bytes(block, 5); + codegen_addbyte4(block, 0x66, 0x0f, 0x7e, 0x04 | (src_reg << 3)); /*MOVD XMMx, [base_reg + idx_reg]*/ + codegen_addbyte(block, base_reg | (idx_reg << 3)); +} +void +host_x86_MOVD_REG_XREG(codeblock_t *block, int dst_reg, int src_reg) +{ + codegen_alloc_bytes(block, 4); + codegen_addbyte4(block, 0x66, 0x0f, 0x7e, 0xc0 | dst_reg | (src_reg << 3)); +} +void +host_x86_MOVD_XREG_BASE_INDEX(codeblock_t *block, int dst_reg, int base_reg, int idx_reg) +{ + codegen_alloc_bytes(block, 5); + codegen_addbyte4(block, 0x66, 0x0f, 0x6e, 0x04 | (dst_reg << 3)); /*MOVD XMMx, [base_reg + idx_reg]*/ + codegen_addbyte(block, base_reg | (idx_reg << 3)); +} +void +host_x86_MOVD_XREG_REG(codeblock_t *block, int dst_reg, int src_reg) +{ + codegen_alloc_bytes(block, 4); + codegen_addbyte4(block, 0x66, 0x0f, 0x6e, 0xc0 | src_reg | (dst_reg << 3)); } -void host_x86_CVTDQ2PS_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg) +void +host_x86_MOVQ_ABS_XREG(codeblock_t *block, void *p, int src_reg) { - codegen_alloc_bytes(block, 3); - codegen_addbyte3(block, 0x0f, 0x5b, 0xc0 | src_reg | (dst_reg << 3)); /*CVTDQ2PS dst_reg, src_reg*/ -} -void host_x86_CVTPS2DQ_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg) -{ - codegen_alloc_bytes(block, 4); - codegen_addbyte4(block, 0x66, 0x0f, 0x5b, 0xc0 | src_reg | (dst_reg << 3)); /*CVTPS2DQ dst_reg, src_reg*/ -} + int offset = (uintptr_t) p - (((uintptr_t) &cpu_state) + 128); -void host_x86_CVTSD2SI_REG_XREG(codeblock_t *block, int dst_reg, int src_reg) -{ - codegen_alloc_bytes(block, 4); - codegen_addbyte4(block, 0xf2, 0x0f, 0x2d, 0xc0 | src_reg | (dst_reg << 3)); /*CVTSD2SI dst_reg, src_reg*/ -} -void host_x86_CVTSD2SI_REG64_XREG(codeblock_t *block, int dst_reg, int src_reg) -{ + if (src_reg & 8) + fatal("host_x86_MOVQ_ABS_REG reg & 8\n"); + + if (offset >= -128 && offset < 127) { codegen_alloc_bytes(block, 5); - codegen_addbyte4(block, 0xf2, 0x48, 0x0f, 0x2d); /*CVTSD2SI dst_reg, src_reg*/ - codegen_addbyte(block, 0xc0 | src_reg | (dst_reg << 3)); -} -void host_x86_CVTSD2SS_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg) -{ - codegen_alloc_bytes(block, 4); - codegen_addbyte4(block, 0xf2, 0x0f, 0x5a, 0xc0 | src_reg | (dst_reg << 3)); -} - -void host_x86_CVTSI2SD_XREG_REG(codeblock_t *block, int dst_reg, int src_reg) -{ - codegen_alloc_bytes(block, 4); - codegen_addbyte4(block, 0xf2, 0x0f, 0x2a, 0xc0 | src_reg | (dst_reg << 3)); /*CVTSI2SD dst_reg, src_reg*/ -} -void host_x86_CVTSI2SS_XREG_REG(codeblock_t *block, int dst_reg, int src_reg) -{ - codegen_alloc_bytes(block, 4); - codegen_addbyte4(block, 0xf3, 0x0f, 0x2a, 0xc0 | src_reg | (dst_reg << 3)); /*CVTSI2SD dst_reg, src_reg*/ -} -void host_x86_CVTSI2SD_XREG_REG64(codeblock_t *block, int dst_reg, int src_reg) -{ - codegen_alloc_bytes(block, 5); - codegen_addbyte4(block, 0xf2, 0x48, 0x0f, 0x2a); /*CVTSI2SD dst_reg, src_reg*/ - codegen_addbyte(block, 0xc0 | src_reg | (dst_reg << 3)); -} - -void host_x86_CVTSS2SD_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg) -{ - codegen_alloc_bytes(block, 4); - codegen_addbyte4(block, 0xf3, 0x0f, 0x5a, 0xc0 | src_reg | (dst_reg << 3)); -} -void host_x86_CVTSS2SD_XREG_BASE_INDEX(codeblock_t *block, int dst_reg, int base_reg, int idx_reg) -{ - codegen_alloc_bytes(block, 4); - codegen_addbyte4(block, 0xf3, 0x0f, 0x5a, 0x04 | (dst_reg << 3)); /*CVTSS2SD XMMx, [base_reg + idx_reg]*/ - codegen_addbyte(block, base_reg | (idx_reg << 3)); -} - -void host_x86_DIVSD_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg) -{ - codegen_alloc_bytes(block, 4); - codegen_addbyte4(block, 0xf2, 0x0f, 0x5e, 0xc0 | src_reg | (dst_reg << 3)); -} -void host_x86_DIVSS_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg) -{ - codegen_alloc_bytes(block, 4); - codegen_addbyte4(block, 0xf3, 0x0f, 0x5e, 0xc0 | src_reg | (dst_reg << 3)); /*DIVSS dst_reg, src_reg*/ -} - -void host_x86_LDMXCSR(codeblock_t *block, void *p) -{ - int offset = (uintptr_t)p - (((uintptr_t)&cpu_state) + 128); - - if (offset >= -128 && offset < 127) - { - codegen_alloc_bytes(block, 4); - codegen_addbyte4(block, 0x0f, 0xae, 0x50 | REG_EBP, offset); /*LDMXCSR offset[EBP]*/ - } - else if (offset < (1ull << 32)) - { - codegen_alloc_bytes(block, 7); - codegen_addbyte3(block, 0x0f, 0xae, 0x90 | REG_EBP); /*LDMXCSR offset[EBP]*/ - codegen_addlong(block, offset); - } - else - { - fatal("host_x86_LDMXCSR - out of range %p\n", p); - } -} - -void host_x86_MAXSD_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg) -{ - codegen_alloc_bytes(block, 4); - codegen_addbyte4(block, 0xf2, 0x0f, 0x5f, 0xc0 | src_reg | (dst_reg << 3)); /*MAXSD dst_reg, src_reg*/ -} - -void host_x86_MOVD_BASE_INDEX_XREG(codeblock_t *block, int base_reg, int idx_reg, int src_reg) -{ - codegen_alloc_bytes(block, 5); - codegen_addbyte4(block, 0x66, 0x0f, 0x7e, 0x04 | (src_reg << 3)); /*MOVD XMMx, [base_reg + idx_reg]*/ - codegen_addbyte(block, base_reg | (idx_reg << 3)); -} -void host_x86_MOVD_REG_XREG(codeblock_t *block, int dst_reg, int src_reg) -{ - codegen_alloc_bytes(block, 4); - codegen_addbyte4(block, 0x66, 0x0f, 0x7e, 0xc0 | dst_reg | (src_reg << 3)); -} -void host_x86_MOVD_XREG_BASE_INDEX(codeblock_t *block, int dst_reg, int base_reg, int idx_reg) -{ - codegen_alloc_bytes(block, 5); - codegen_addbyte4(block, 0x66, 0x0f, 0x6e, 0x04 | (dst_reg << 3)); /*MOVD XMMx, [base_reg + idx_reg]*/ - codegen_addbyte(block, base_reg | (idx_reg << 3)); -} -void host_x86_MOVD_XREG_REG(codeblock_t *block, int dst_reg, int src_reg) -{ - codegen_alloc_bytes(block, 4); - codegen_addbyte4(block, 0x66, 0x0f, 0x6e, 0xc0 | src_reg | (dst_reg << 3)); -} - -void host_x86_MOVQ_ABS_XREG(codeblock_t *block, void *p, int src_reg) -{ - int offset = (uintptr_t)p - (((uintptr_t)&cpu_state) + 128); - - if (src_reg & 8) - fatal("host_x86_MOVQ_ABS_REG reg & 8\n"); - - if (offset >= -128 && offset < 127) - { - codegen_alloc_bytes(block, 5); - codegen_addbyte4(block, 0x66, 0x0f, 0xd6, 0x45 | (src_reg << 3)); /*MOVQ offset[EBP], src_reg*/ - codegen_addbyte(block, offset); - } - else - { - if ((uintptr_t)p >> 32) - fatal("host_x86_MOVQ_ABS_REG - out of range %p\n", p); - codegen_alloc_bytes(block, 9); - codegen_addbyte4(block, 0x66, 0x0f, 0xd6, 0x04 | (src_reg << 3)); /*MOVQ [p], src_reg*/ - codegen_addbyte(block, 0x25); - codegen_addlong(block, (uint32_t)(uintptr_t)p); - } -} -void host_x86_MOVQ_ABS_REG_REG_SHIFT_XREG(codeblock_t *block, uint32_t addr, int src_reg_a, int src_reg_b, int shift, int src_reg) -{ - if ((src_reg & 8) || (src_reg_a & 8) || (src_reg_b & 8)) - fatal("host_x86_MOVQ_ABS_REG_REG_SHIFT_REG - bad reg\n"); - - if (addr < 0x80 || addr >= 0xffffff80) - { - codegen_alloc_bytes(block, 6); - codegen_addbyte3(block, 0x66, 0x0f, 0xd6); /*MOVQ addr[src_reg_a + src_reg_b << shift], XMMx*/ - codegen_addbyte3(block, 0x44 | (src_reg << 3), src_reg_a | (src_reg_b << 3) | (shift << 6), addr & 0xff); - } - else - { - codegen_alloc_bytes(block, 9); - codegen_addbyte3(block, 0x66, 0x0f, 0xd6); /*MOVQ addr[src_reg_a + src_reg_b << shift], XMMx*/ - codegen_addbyte2(block, 0x84 | (src_reg << 3), src_reg_a | (src_reg_b << 3) | (shift << 6)); - codegen_addlong(block, addr); - } -} - -void host_x86_MOVQ_BASE_INDEX_XREG(codeblock_t *block, int base_reg, int idx_reg, int src_reg) -{ - codegen_alloc_bytes(block, 5); - codegen_addbyte4(block, 0x66, 0x0f, 0xd6, 0x04 | (src_reg << 3)); /*MOVD XMMx, [base_reg + idx_reg]*/ - codegen_addbyte(block, base_reg | (idx_reg << 3)); -} -void host_x86_MOVQ_BASE_OFFSET_XREG(codeblock_t *block, int base_reg, int offset, int src_reg) -{ - if (offset >= -128 && offset < 127) - { - if (base_reg == REG_RSP) - { - codegen_alloc_bytes(block, 6); - codegen_addbyte4(block, 0x66, 0x0f, 0xd6, 0x44 | (src_reg << 3)); /*MOVQ [RSP + offset], XMMx*/ - codegen_addbyte2(block, 0x24, offset); - } - else - { - codegen_alloc_bytes(block, 5); - codegen_addbyte4(block, 0x66, 0x0f, 0xd6, 0x40 | base_reg | (src_reg << 3)); /*MOVQ [base_reg + offset], XMMx*/ - codegen_addbyte(block, offset); - } - } - else - fatal("MOVQ_BASE_OFFSET_XREG - offset %i\n", offset); -} - -void host_x86_MOVQ_XREG_ABS(codeblock_t *block, int dst_reg, void *p) -{ - int offset = (uintptr_t)p - (((uintptr_t)&cpu_state) + 128); - - if (dst_reg & 8) - fatal("host_x86_MOVQ_REG_ABS reg & 8\n"); - - if (offset >= -128 && offset < 127) - { - codegen_alloc_bytes(block, 5); - codegen_addbyte4(block, 0xf3, 0x0f, 0x7e, 0x45 | (dst_reg << 3)); /*MOVQ offset[EBP], src_reg*/ - codegen_addbyte(block, offset); - } - else - { - if ((uintptr_t)p >> 32) - fatal("host_x86_MOVQ_REG_ABS - out of range %p\n", p); - codegen_alloc_bytes(block, 9); - codegen_addbyte4(block, 0xf3, 0x0f, 0x7e, 0x04 | (dst_reg << 3)); /*MOVQ [p], src_reg*/ - codegen_addbyte(block, 0x25); - codegen_addlong(block, (uint32_t)(uintptr_t)p); - } -} -void host_x86_MOVQ_XREG_ABS_REG_REG_SHIFT(codeblock_t *block, int dst_reg, uint32_t addr, int src_reg_a, int src_reg_b, int shift) -{ - if ((dst_reg & 8) || (src_reg_a & 8) || (src_reg_b & 8)) - fatal("host_x86_MOVQ_REG_ABS_REG_REG_SHIFT - bad reg\n"); - - if (addr < 0x80 || addr >= 0xffffff80) - { - codegen_alloc_bytes(block, 6); - codegen_addbyte3(block, 0xf3, 0x0f, 0x7e); /*MOVQ XMMx, addr[src_reg_a + src_reg_b << shift]*/ - codegen_addbyte3(block, 0x44 | (dst_reg << 3), src_reg_a | (src_reg_b << 3) | (shift << 6), addr & 0xff); - } - else - { - codegen_alloc_bytes(block, 9); - codegen_addbyte3(block, 0xf3, 0x0f, 0x7e); /*MOVQ XMMx, addr[src_reg_a + src_reg_b << shift]*/ - codegen_addbyte2(block, 0x84 | (dst_reg << 3), src_reg_a | (src_reg_b << 3) | (shift << 6)); - codegen_addlong(block, addr); - } -} -void host_x86_MOVQ_XREG_BASE_INDEX(codeblock_t *block, int dst_reg, int base_reg, int idx_reg) -{ - codegen_alloc_bytes(block, 5); - codegen_addbyte4(block, 0xf3, 0x0f, 0x7e, 0x04 | (dst_reg << 3)); /*MOVQ XMMx, [base_reg + idx_reg]*/ - codegen_addbyte(block, base_reg | (idx_reg << 3)); -} -void host_x86_MOVQ_XREG_BASE_OFFSET(codeblock_t *block, int dst_reg, int base_reg, int offset) -{ - if (offset >= -128 && offset < 127) - { - if (base_reg == REG_ESP) - { - codegen_alloc_bytes(block, 6); - codegen_addbyte4(block, 0xf3, 0x0f, 0x7e, 0x44 | (dst_reg << 3)); /*MOVQ XMMx, [ESP + offset]*/ - codegen_addbyte2(block, 0x24, offset); - } - else - { - codegen_alloc_bytes(block, 5); - codegen_addbyte4(block, 0xf3, 0x0f, 0x7e, 0x40 | base_reg | (dst_reg << 3)); /*MOVQ XMMx, [base_reg + offset]*/ - codegen_addbyte(block, offset); - } - } - else - fatal("MOVQ_REG_BASE_OFFSET - offset %i\n", offset); -} - -void host_x86_MOVQ_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg) -{ - codegen_alloc_bytes(block, 4); - codegen_addbyte4(block, 0xf3, 0x0f, 0x7e, 0xc0 | src_reg | (dst_reg << 3)); /*MOVQ dst_reg, src_reg*/ -} - -void host_x86_MOVQ_REG_XREG(codeblock_t *block, int dst_reg, int src_reg) -{ - codegen_alloc_bytes(block, 5); - codegen_addbyte4(block, 0x66, 0x48, 0x0f, 0x7e); /*MOVQ dst_reg, src_reg*/ - codegen_addbyte(block, 0xc0 | dst_reg | (src_reg << 3)); -} -void host_x86_MOVQ_XREG_REG(codeblock_t *block, int dst_reg, int src_reg) -{ - codegen_alloc_bytes(block, 5); - codegen_addbyte4(block, 0x66, 0x48, 0x0f, 0x6e); /*MOVQ dst_reg, src_reg*/ - codegen_addbyte(block, 0xc0 | src_reg | (dst_reg << 3)); -} - -void host_x86_MAXPS_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg) -{ - codegen_alloc_bytes(block, 3); - codegen_addbyte3(block, 0x0f, 0x5f, 0xc0 | src_reg | (dst_reg << 3)); /*MAXPS dst_reg, src_reg*/ -} -void host_x86_MINPS_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg) -{ - codegen_alloc_bytes(block, 3); - codegen_addbyte3(block, 0x0f, 0x5d, 0xc0 | src_reg | (dst_reg << 3)); /*MINPS dst_reg, src_reg*/ -} - -void host_x86_MULPS_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg) -{ - codegen_alloc_bytes(block, 3); - codegen_addbyte3(block, 0x0f, 0x59, 0xc0 | src_reg | (dst_reg << 3)); /*MULPS dst_reg, src_reg*/ -} -void host_x86_MULSD_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg) -{ - codegen_alloc_bytes(block, 4); - codegen_addbyte4(block, 0xf2, 0x0f, 0x59, 0xc0 | src_reg | (dst_reg << 3)); -} - -void host_x86_PACKSSWB_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg) -{ + codegen_addbyte4(block, 0x66, 0x0f, 0xd6, 0x45 | (src_reg << 3)); /*MOVQ offset[EBP], src_reg*/ + codegen_addbyte(block, offset); + } else { + if ((uintptr_t) p >> 32) + fatal("host_x86_MOVQ_ABS_REG - out of range %p\n", p); codegen_alloc_bytes(block, 9); - codegen_addbyte4(block, 0x66, 0x0f, 0x63, 0xc0 | src_reg | (dst_reg << 3)); /*PACKSSWB dst_reg, src_reg*/ - codegen_addbyte4(block, 0x66, 0x0f, 0x70, 0xc0 | dst_reg | (dst_reg << 3)); /*PSHUFD dst_reg, dst_reg, 0x88 (move bits 64-95 to 32-63)*/ - codegen_addbyte(block, 0x88); + codegen_addbyte4(block, 0x66, 0x0f, 0xd6, 0x04 | (src_reg << 3)); /*MOVQ [p], src_reg*/ + codegen_addbyte(block, 0x25); + codegen_addlong(block, (uint32_t) (uintptr_t) p); + } } -void host_x86_PACKSSDW_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg) +void +host_x86_MOVQ_ABS_REG_REG_SHIFT_XREG(codeblock_t *block, uint32_t addr, int src_reg_a, int src_reg_b, int shift, int src_reg) { + if ((src_reg & 8) || (src_reg_a & 8) || (src_reg_b & 8)) + fatal("host_x86_MOVQ_ABS_REG_REG_SHIFT_REG - bad reg\n"); + + if (addr < 0x80 || addr >= 0xffffff80) { + codegen_alloc_bytes(block, 6); + codegen_addbyte3(block, 0x66, 0x0f, 0xd6); /*MOVQ addr[src_reg_a + src_reg_b << shift], XMMx*/ + codegen_addbyte3(block, 0x44 | (src_reg << 3), src_reg_a | (src_reg_b << 3) | (shift << 6), addr & 0xff); + } else { codegen_alloc_bytes(block, 9); - codegen_addbyte4(block, 0x66, 0x0f, 0x6b, 0xc0 | src_reg | (dst_reg << 3)); /*PACKSSDW dst_reg, src_reg*/ - codegen_addbyte4(block, 0x66, 0x0f, 0x70, 0xc0 | dst_reg | (dst_reg << 3)); /*PSHUFD dst_reg, dst_reg, 0x88 (move bits 64-95 to 32-63)*/ - codegen_addbyte(block, 0x88); + codegen_addbyte3(block, 0x66, 0x0f, 0xd6); /*MOVQ addr[src_reg_a + src_reg_b << shift], XMMx*/ + codegen_addbyte2(block, 0x84 | (src_reg << 3), src_reg_a | (src_reg_b << 3) | (shift << 6)); + codegen_addlong(block, addr); + } } -void host_x86_PACKUSWB_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg) + +void +host_x86_MOVQ_BASE_INDEX_XREG(codeblock_t *block, int base_reg, int idx_reg, int src_reg) { + codegen_alloc_bytes(block, 5); + codegen_addbyte4(block, 0x66, 0x0f, 0xd6, 0x04 | (src_reg << 3)); /*MOVD XMMx, [base_reg + idx_reg]*/ + codegen_addbyte(block, base_reg | (idx_reg << 3)); +} +void +host_x86_MOVQ_BASE_OFFSET_XREG(codeblock_t *block, int base_reg, int offset, int src_reg) +{ + if (offset >= -128 && offset < 127) { + if (base_reg == REG_RSP) { + codegen_alloc_bytes(block, 6); + codegen_addbyte4(block, 0x66, 0x0f, 0xd6, 0x44 | (src_reg << 3)); /*MOVQ [RSP + offset], XMMx*/ + codegen_addbyte2(block, 0x24, offset); + } else { + codegen_alloc_bytes(block, 5); + codegen_addbyte4(block, 0x66, 0x0f, 0xd6, 0x40 | base_reg | (src_reg << 3)); /*MOVQ [base_reg + offset], XMMx*/ + codegen_addbyte(block, offset); + } + } else + fatal("MOVQ_BASE_OFFSET_XREG - offset %i\n", offset); +} + +void +host_x86_MOVQ_XREG_ABS(codeblock_t *block, int dst_reg, void *p) +{ + int offset = (uintptr_t) p - (((uintptr_t) &cpu_state) + 128); + + if (dst_reg & 8) + fatal("host_x86_MOVQ_REG_ABS reg & 8\n"); + + if (offset >= -128 && offset < 127) { + codegen_alloc_bytes(block, 5); + codegen_addbyte4(block, 0xf3, 0x0f, 0x7e, 0x45 | (dst_reg << 3)); /*MOVQ offset[EBP], src_reg*/ + codegen_addbyte(block, offset); + } else { + if ((uintptr_t) p >> 32) + fatal("host_x86_MOVQ_REG_ABS - out of range %p\n", p); codegen_alloc_bytes(block, 9); - codegen_addbyte4(block, 0x66, 0x0f, 0x67, 0xc0 | src_reg | (dst_reg << 3)); /*PACKUSWB dst_reg, src_reg*/ - codegen_addbyte4(block, 0x66, 0x0f, 0x70, 0xc0 | dst_reg | (dst_reg << 3)); /*PSHUFD dst_reg, dst_reg, 0x88 (move bits 64-95 to 32-63)*/ - codegen_addbyte(block, 0x88); + codegen_addbyte4(block, 0xf3, 0x0f, 0x7e, 0x04 | (dst_reg << 3)); /*MOVQ [p], src_reg*/ + codegen_addbyte(block, 0x25); + codegen_addlong(block, (uint32_t) (uintptr_t) p); + } } +void +host_x86_MOVQ_XREG_ABS_REG_REG_SHIFT(codeblock_t *block, int dst_reg, uint32_t addr, int src_reg_a, int src_reg_b, int shift) +{ + if ((dst_reg & 8) || (src_reg_a & 8) || (src_reg_b & 8)) + fatal("host_x86_MOVQ_REG_ABS_REG_REG_SHIFT - bad reg\n"); -void host_x86_PADDB_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg) -{ - codegen_alloc_bytes(block, 4); - codegen_addbyte4(block, 0x66, 0x0f, 0xfc, 0xc0 | src_reg | (dst_reg << 3)); /*PADDB dst_reg, src_reg*/ -} -void host_x86_PADDW_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg) -{ - codegen_alloc_bytes(block, 4); - codegen_addbyte4(block, 0x66, 0x0f, 0xfd, 0xc0 | src_reg | (dst_reg << 3)); /*PADDW dst_reg, src_reg*/ -} -void host_x86_PADDD_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg) -{ - codegen_alloc_bytes(block, 4); - codegen_addbyte4(block, 0x66, 0x0f, 0xfe, 0xc0 | src_reg | (dst_reg << 3)); /*PADDD dst_reg, src_reg*/ -} -void host_x86_PADDSB_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg) -{ - codegen_alloc_bytes(block, 4); - codegen_addbyte4(block, 0x66, 0x0f, 0xec, 0xc0 | src_reg | (dst_reg << 3)); /*PADDSB dst_reg, src_reg*/ -} -void host_x86_PADDSW_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg) -{ - codegen_alloc_bytes(block, 4); - codegen_addbyte4(block, 0x66, 0x0f, 0xed, 0xc0 | src_reg | (dst_reg << 3)); /*PADDSW dst_reg, src_reg*/ -} -void host_x86_PADDUSB_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg) -{ - codegen_alloc_bytes(block, 4); - codegen_addbyte4(block, 0x66, 0x0f, 0xdc, 0xc0 | src_reg | (dst_reg << 3)); /*PADDUSB dst_reg, src_reg*/ -} -void host_x86_PADDUSW_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg) -{ - codegen_alloc_bytes(block, 4); - codegen_addbyte4(block, 0x66, 0x0f, 0xdd, 0xc0 | src_reg | (dst_reg << 3)); /*PADDUSW dst_reg, src_reg*/ -} - -void host_x86_PAND_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg) -{ - codegen_alloc_bytes(block, 4); - codegen_addbyte4(block, 0x66, 0x0f, 0xdb, 0xc0 | src_reg | (dst_reg << 3)); /*PAND dst_reg, src_reg*/ -} -void host_x86_PANDN_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg) -{ - codegen_alloc_bytes(block, 4); - codegen_addbyte4(block, 0x66, 0x0f, 0xdf, 0xc0 | src_reg | (dst_reg << 3)); /*PANDN dst_reg, src_reg*/ -} -void host_x86_POR_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg) -{ - codegen_alloc_bytes(block, 4); - codegen_addbyte4(block, 0x66, 0x0f, 0xeb, 0xc0 | src_reg | (dst_reg << 3)); /*POR dst_reg, src_reg*/ -} -void host_x86_PXOR_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg) -{ - codegen_alloc_bytes(block, 4); - codegen_addbyte4(block, 0x66, 0x0f, 0xef, 0xc0 | src_reg | (dst_reg << 3)); /*PXOR dst_reg, src_reg*/ -} - -void host_x86_PCMPEQB_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg) -{ - codegen_alloc_bytes(block, 4); - codegen_addbyte4(block, 0x66, 0x0f, 0x74, 0xc0 | src_reg | (dst_reg << 3)); /*PCMPEQB dst_reg, src_reg*/ -} -void host_x86_PCMPEQW_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg) -{ - codegen_alloc_bytes(block, 4); - codegen_addbyte4(block, 0x66, 0x0f, 0x75, 0xc0 | src_reg | (dst_reg << 3)); /*PCMPEQW dst_reg, src_reg*/ -} -void host_x86_PCMPEQD_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg) -{ - codegen_alloc_bytes(block, 4); - codegen_addbyte4(block, 0x66, 0x0f, 0x76, 0xc0 | src_reg | (dst_reg << 3)); /*PCMPEQD dst_reg, src_reg*/ -} -void host_x86_PCMPGTB_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg) -{ - codegen_alloc_bytes(block, 4); - codegen_addbyte4(block, 0x66, 0x0f, 0x64, 0xc0 | src_reg | (dst_reg << 3)); /*PCMPGTB dst_reg, src_reg*/ -} -void host_x86_PCMPGTW_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg) -{ - codegen_alloc_bytes(block, 4); - codegen_addbyte4(block, 0x66, 0x0f, 0x65, 0xc0 | src_reg | (dst_reg << 3)); /*PCMPGTW dst_reg, src_reg*/ -} -void host_x86_PCMPGTD_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg) -{ - codegen_alloc_bytes(block, 4); - codegen_addbyte4(block, 0x66, 0x0f, 0x66, 0xc0 | src_reg | (dst_reg << 3)); /*PCMPGTD dst_reg, src_reg*/ -} - -void host_x86_PMADDWD_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg) -{ - codegen_alloc_bytes(block, 4); - codegen_addbyte4(block, 0x66, 0x0f, 0xf5, 0xc0 | src_reg | (dst_reg << 3)); /*PMULLW dst_reg, src_reg*/ -} -void host_x86_PMULHW_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg) -{ - codegen_alloc_bytes(block, 4); - codegen_addbyte4(block, 0x66, 0x0f, 0xe5, 0xc0 | src_reg | (dst_reg << 3)); /*PMULLW dst_reg, src_reg*/ -} -void host_x86_PMULLW_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg) -{ - codegen_alloc_bytes(block, 4); - codegen_addbyte4(block, 0x66, 0x0f, 0xd5, 0xc0 | src_reg | (dst_reg << 3)); /*PMULLW dst_reg, src_reg*/ -} - -void host_x86_PSLLW_XREG_IMM(codeblock_t *block, int dst_reg, int shift) -{ - codegen_alloc_bytes(block, 5); - codegen_addbyte4(block, 0x66, 0x0f, 0x71, 0xc0 | 0x30 | dst_reg); /*PSLLW dst_reg, imm*/ - codegen_addbyte(block, shift); -} -void host_x86_PSLLD_XREG_IMM(codeblock_t *block, int dst_reg, int shift) -{ - codegen_alloc_bytes(block, 5); - codegen_addbyte4(block, 0x66, 0x0f, 0x72, 0xc0 | 0x30 | dst_reg); /*PSLLD dst_reg, imm*/ - codegen_addbyte(block, shift); -} -void host_x86_PSLLQ_XREG_IMM(codeblock_t *block, int dst_reg, int shift) -{ - codegen_alloc_bytes(block, 5); - codegen_addbyte4(block, 0x66, 0x0f, 0x73, 0xc0 | 0x30 | dst_reg); /*PSLLD dst_reg, imm*/ - codegen_addbyte(block, shift); -} -void host_x86_PSRAW_XREG_IMM(codeblock_t *block, int dst_reg, int shift) -{ - codegen_alloc_bytes(block, 5); - codegen_addbyte4(block, 0x66, 0x0f, 0x71, 0xc0 | 0x20 | dst_reg); /*PSRAW dst_reg, imm*/ - codegen_addbyte(block, shift); -} -void host_x86_PSRAD_XREG_IMM(codeblock_t *block, int dst_reg, int shift) -{ - codegen_alloc_bytes(block, 5); - codegen_addbyte4(block, 0x66, 0x0f, 0x72, 0xc0 | 0x20 | dst_reg); /*PSRAD dst_reg, imm*/ - codegen_addbyte(block, shift); -} -void host_x86_PSRAQ_XREG_IMM(codeblock_t *block, int dst_reg, int shift) -{ - codegen_alloc_bytes(block, 5); - codegen_addbyte4(block, 0x66, 0x0f, 0x73, 0xc0 | 0x20 | dst_reg); /*PSRAD dst_reg, imm*/ - codegen_addbyte(block, shift); -} -void host_x86_PSRLW_XREG_IMM(codeblock_t *block, int dst_reg, int shift) -{ - codegen_alloc_bytes(block, 5); - codegen_addbyte4(block, 0x66, 0x0f, 0x71, 0xc0 | 0x10 | dst_reg); /*PSRLW dst_reg, imm*/ - codegen_addbyte(block, shift); -} -void host_x86_PSRLD_XREG_IMM(codeblock_t *block, int dst_reg, int shift) -{ - codegen_alloc_bytes(block, 5); - codegen_addbyte4(block, 0x66, 0x0f, 0x72, 0xc0 | 0x10 | dst_reg); /*PSRLD dst_reg, imm*/ - codegen_addbyte(block, shift); -} -void host_x86_PSRLQ_XREG_IMM(codeblock_t *block, int dst_reg, int shift) -{ - codegen_alloc_bytes(block, 5); - codegen_addbyte4(block, 0x66, 0x0f, 0x73, 0xc0 | 0x10 | dst_reg); /*PSRLD dst_reg, imm*/ - codegen_addbyte(block, shift); -} - -void host_x86_PSUBB_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg) -{ - codegen_alloc_bytes(block, 4); - codegen_addbyte4(block, 0x66, 0x0f, 0xf8, 0xc0 | src_reg | (dst_reg << 3)); /*PADDB dst_reg, src_reg*/ -} -void host_x86_PSUBW_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg) -{ - codegen_alloc_bytes(block, 4); - codegen_addbyte4(block, 0x66, 0x0f, 0xf9, 0xc0 | src_reg | (dst_reg << 3)); /*PADDW dst_reg, src_reg*/ -} -void host_x86_PSUBD_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg) -{ - codegen_alloc_bytes(block, 4); - codegen_addbyte4(block, 0x66, 0x0f, 0xfa, 0xc0 | src_reg | (dst_reg << 3)); /*PADDD dst_reg, src_reg*/ -} -void host_x86_PSUBSB_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg) -{ - codegen_alloc_bytes(block, 4); - codegen_addbyte4(block, 0x66, 0x0f, 0xe8, 0xc0 | src_reg | (dst_reg << 3)); /*PSUBSB dst_reg, src_reg*/ -} -void host_x86_PSUBSW_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg) -{ - codegen_alloc_bytes(block, 4); - codegen_addbyte4(block, 0x66, 0x0f, 0xe9, 0xc0 | src_reg | (dst_reg << 3)); /*PSUBSW dst_reg, src_reg*/ -} -void host_x86_PSUBUSB_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg) -{ - codegen_alloc_bytes(block, 4); - codegen_addbyte4(block, 0x66, 0x0f, 0xd8, 0xc0 | src_reg | (dst_reg << 3)); /*PSUBUSB dst_reg, src_reg*/ -} -void host_x86_PSUBUSW_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg) -{ - codegen_alloc_bytes(block, 4); - codegen_addbyte4(block, 0x66, 0x0f, 0xd9, 0xc0 | src_reg | (dst_reg << 3)); /*PSUBUSW dst_reg, src_reg*/ -} - -void host_x86_PUNPCKHBW_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg) -{ + if (addr < 0x80 || addr >= 0xffffff80) { + codegen_alloc_bytes(block, 6); + codegen_addbyte3(block, 0xf3, 0x0f, 0x7e); /*MOVQ XMMx, addr[src_reg_a + src_reg_b << shift]*/ + codegen_addbyte3(block, 0x44 | (dst_reg << 3), src_reg_a | (src_reg_b << 3) | (shift << 6), addr & 0xff); + } else { codegen_alloc_bytes(block, 9); - codegen_addbyte4(block, 0x66, 0x0f, 0x60, 0xc0 | src_reg | (dst_reg << 3)); /*PUNPCKLBW dst_reg, src_reg*/ - codegen_addbyte4(block, 0x66, 0x0f, 0x70, 0xc0 | dst_reg | (dst_reg << 3)); /*PSHUFD dst_reg, dst_reg, 0xee (move top 64-bits to low 64-bits)*/ - codegen_addbyte(block, 0xee); + codegen_addbyte3(block, 0xf3, 0x0f, 0x7e); /*MOVQ XMMx, addr[src_reg_a + src_reg_b << shift]*/ + codegen_addbyte2(block, 0x84 | (dst_reg << 3), src_reg_a | (src_reg_b << 3) | (shift << 6)); + codegen_addlong(block, addr); + } } -void host_x86_PUNPCKHWD_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg) +void +host_x86_MOVQ_XREG_BASE_INDEX(codeblock_t *block, int dst_reg, int base_reg, int idx_reg) { - codegen_alloc_bytes(block, 9); - codegen_addbyte4(block, 0x66, 0x0f, 0x61, 0xc0 | src_reg | (dst_reg << 3)); /*PUNPCKLWD dst_reg, src_reg*/ - codegen_addbyte4(block, 0x66, 0x0f, 0x70, 0xc0 | dst_reg | (dst_reg << 3)); /*PSHUFD dst_reg, dst_reg, 0xee (move top 64-bits to low 64-bits)*/ - codegen_addbyte(block, 0xee); + codegen_alloc_bytes(block, 5); + codegen_addbyte4(block, 0xf3, 0x0f, 0x7e, 0x04 | (dst_reg << 3)); /*MOVQ XMMx, [base_reg + idx_reg]*/ + codegen_addbyte(block, base_reg | (idx_reg << 3)); } -void host_x86_PUNPCKHDQ_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg) +void +host_x86_MOVQ_XREG_BASE_OFFSET(codeblock_t *block, int dst_reg, int base_reg, int offset) { - codegen_alloc_bytes(block, 9); - codegen_addbyte4(block, 0x66, 0x0f, 0x62, 0xc0 | src_reg | (dst_reg << 3)); /*PUNPCKLDQ dst_reg, src_reg*/ - codegen_addbyte4(block, 0x66, 0x0f, 0x70, 0xc0 | dst_reg | (dst_reg << 3)); /*PSHUFD dst_reg, dst_reg, 0xee (move top 64-bits to low 64-bits)*/ - codegen_addbyte(block, 0xee); -} -void host_x86_PUNPCKLBW_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg) -{ - codegen_alloc_bytes(block, 4); - codegen_addbyte4(block, 0x66, 0x0f, 0x60, 0xc0 | src_reg | (dst_reg << 3)); /*PUNPCKLBW dst_reg, src_reg*/ -} -void host_x86_PUNPCKLWD_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg) -{ - codegen_alloc_bytes(block, 4); - codegen_addbyte4(block, 0x66, 0x0f, 0x61, 0xc0 | src_reg | (dst_reg << 3)); /*PUNPCKLWD dst_reg, src_reg*/ -} -void host_x86_PUNPCKLDQ_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg) -{ - codegen_alloc_bytes(block, 4); - codegen_addbyte4(block, 0x66, 0x0f, 0x62, 0xc0 | src_reg | (dst_reg << 3)); /*PUNPCKLDQ dst_reg, src_reg*/ + if (offset >= -128 && offset < 127) { + if (base_reg == REG_ESP) { + codegen_alloc_bytes(block, 6); + codegen_addbyte4(block, 0xf3, 0x0f, 0x7e, 0x44 | (dst_reg << 3)); /*MOVQ XMMx, [ESP + offset]*/ + codegen_addbyte2(block, 0x24, offset); + } else { + codegen_alloc_bytes(block, 5); + codegen_addbyte4(block, 0xf3, 0x0f, 0x7e, 0x40 | base_reg | (dst_reg << 3)); /*MOVQ XMMx, [base_reg + offset]*/ + codegen_addbyte(block, offset); + } + } else + fatal("MOVQ_REG_BASE_OFFSET - offset %i\n", offset); } -void host_x86_SQRTSD_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg) +void +host_x86_MOVQ_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg) { - codegen_alloc_bytes(block, 4); - codegen_addbyte4(block, 0xf2, 0x0f, 0x51, 0xc0 | src_reg | (dst_reg << 3)); /*SQRTSD dst_reg, src_reg*/ -} -void host_x86_SQRTSS_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg) -{ - codegen_alloc_bytes(block, 4); - codegen_addbyte4(block, 0xf3, 0x0f, 0x51, 0xc0 | src_reg | (dst_reg << 3)); /*SQRTSS dst_reg, src_reg*/ + codegen_alloc_bytes(block, 4); + codegen_addbyte4(block, 0xf3, 0x0f, 0x7e, 0xc0 | src_reg | (dst_reg << 3)); /*MOVQ dst_reg, src_reg*/ } -void host_x86_SUBPS_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg) +void +host_x86_MOVQ_REG_XREG(codeblock_t *block, int dst_reg, int src_reg) { - codegen_alloc_bytes(block, 3); - codegen_addbyte3(block, 0x0f, 0x5c, 0xc0 | src_reg | (dst_reg << 3)); /*SUBPS dst_reg, src_reg*/ + codegen_alloc_bytes(block, 5); + codegen_addbyte4(block, 0x66, 0x48, 0x0f, 0x7e); /*MOVQ dst_reg, src_reg*/ + codegen_addbyte(block, 0xc0 | dst_reg | (src_reg << 3)); } -void host_x86_SUBSD_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg) +void +host_x86_MOVQ_XREG_REG(codeblock_t *block, int dst_reg, int src_reg) { - codegen_alloc_bytes(block, 4); - codegen_addbyte4(block, 0xf2, 0x0f, 0x5c, 0xc0 | src_reg | (dst_reg << 3)); + codegen_alloc_bytes(block, 5); + codegen_addbyte4(block, 0x66, 0x48, 0x0f, 0x6e); /*MOVQ dst_reg, src_reg*/ + codegen_addbyte(block, 0xc0 | src_reg | (dst_reg << 3)); } -void host_x86_UNPCKLPS_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg) +void +host_x86_MAXPS_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg) { - codegen_alloc_bytes(block, 3); - codegen_addbyte3(block, 0x0f, 0x14, 0xc0 | src_reg | (dst_reg << 3)); + codegen_alloc_bytes(block, 3); + codegen_addbyte3(block, 0x0f, 0x5f, 0xc0 | src_reg | (dst_reg << 3)); /*MAXPS dst_reg, src_reg*/ +} +void +host_x86_MINPS_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg) +{ + codegen_alloc_bytes(block, 3); + codegen_addbyte3(block, 0x0f, 0x5d, 0xc0 | src_reg | (dst_reg << 3)); /*MINPS dst_reg, src_reg*/ +} + +void +host_x86_MULPS_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg) +{ + codegen_alloc_bytes(block, 3); + codegen_addbyte3(block, 0x0f, 0x59, 0xc0 | src_reg | (dst_reg << 3)); /*MULPS dst_reg, src_reg*/ +} +void +host_x86_MULSD_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg) +{ + codegen_alloc_bytes(block, 4); + codegen_addbyte4(block, 0xf2, 0x0f, 0x59, 0xc0 | src_reg | (dst_reg << 3)); +} + +void +host_x86_PACKSSWB_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg) +{ + codegen_alloc_bytes(block, 9); + codegen_addbyte4(block, 0x66, 0x0f, 0x63, 0xc0 | src_reg | (dst_reg << 3)); /*PACKSSWB dst_reg, src_reg*/ + codegen_addbyte4(block, 0x66, 0x0f, 0x70, 0xc0 | dst_reg | (dst_reg << 3)); /*PSHUFD dst_reg, dst_reg, 0x88 (move bits 64-95 to 32-63)*/ + codegen_addbyte(block, 0x88); +} +void +host_x86_PACKSSDW_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg) +{ + codegen_alloc_bytes(block, 9); + codegen_addbyte4(block, 0x66, 0x0f, 0x6b, 0xc0 | src_reg | (dst_reg << 3)); /*PACKSSDW dst_reg, src_reg*/ + codegen_addbyte4(block, 0x66, 0x0f, 0x70, 0xc0 | dst_reg | (dst_reg << 3)); /*PSHUFD dst_reg, dst_reg, 0x88 (move bits 64-95 to 32-63)*/ + codegen_addbyte(block, 0x88); +} +void +host_x86_PACKUSWB_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg) +{ + codegen_alloc_bytes(block, 9); + codegen_addbyte4(block, 0x66, 0x0f, 0x67, 0xc0 | src_reg | (dst_reg << 3)); /*PACKUSWB dst_reg, src_reg*/ + codegen_addbyte4(block, 0x66, 0x0f, 0x70, 0xc0 | dst_reg | (dst_reg << 3)); /*PSHUFD dst_reg, dst_reg, 0x88 (move bits 64-95 to 32-63)*/ + codegen_addbyte(block, 0x88); +} + +void +host_x86_PADDB_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg) +{ + codegen_alloc_bytes(block, 4); + codegen_addbyte4(block, 0x66, 0x0f, 0xfc, 0xc0 | src_reg | (dst_reg << 3)); /*PADDB dst_reg, src_reg*/ +} +void +host_x86_PADDW_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg) +{ + codegen_alloc_bytes(block, 4); + codegen_addbyte4(block, 0x66, 0x0f, 0xfd, 0xc0 | src_reg | (dst_reg << 3)); /*PADDW dst_reg, src_reg*/ +} +void +host_x86_PADDD_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg) +{ + codegen_alloc_bytes(block, 4); + codegen_addbyte4(block, 0x66, 0x0f, 0xfe, 0xc0 | src_reg | (dst_reg << 3)); /*PADDD dst_reg, src_reg*/ +} +void +host_x86_PADDSB_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg) +{ + codegen_alloc_bytes(block, 4); + codegen_addbyte4(block, 0x66, 0x0f, 0xec, 0xc0 | src_reg | (dst_reg << 3)); /*PADDSB dst_reg, src_reg*/ +} +void +host_x86_PADDSW_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg) +{ + codegen_alloc_bytes(block, 4); + codegen_addbyte4(block, 0x66, 0x0f, 0xed, 0xc0 | src_reg | (dst_reg << 3)); /*PADDSW dst_reg, src_reg*/ +} +void +host_x86_PADDUSB_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg) +{ + codegen_alloc_bytes(block, 4); + codegen_addbyte4(block, 0x66, 0x0f, 0xdc, 0xc0 | src_reg | (dst_reg << 3)); /*PADDUSB dst_reg, src_reg*/ +} +void +host_x86_PADDUSW_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg) +{ + codegen_alloc_bytes(block, 4); + codegen_addbyte4(block, 0x66, 0x0f, 0xdd, 0xc0 | src_reg | (dst_reg << 3)); /*PADDUSW dst_reg, src_reg*/ +} + +void +host_x86_PAND_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg) +{ + codegen_alloc_bytes(block, 4); + codegen_addbyte4(block, 0x66, 0x0f, 0xdb, 0xc0 | src_reg | (dst_reg << 3)); /*PAND dst_reg, src_reg*/ +} +void +host_x86_PANDN_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg) +{ + codegen_alloc_bytes(block, 4); + codegen_addbyte4(block, 0x66, 0x0f, 0xdf, 0xc0 | src_reg | (dst_reg << 3)); /*PANDN dst_reg, src_reg*/ +} +void +host_x86_POR_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg) +{ + codegen_alloc_bytes(block, 4); + codegen_addbyte4(block, 0x66, 0x0f, 0xeb, 0xc0 | src_reg | (dst_reg << 3)); /*POR dst_reg, src_reg*/ +} +void +host_x86_PXOR_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg) +{ + codegen_alloc_bytes(block, 4); + codegen_addbyte4(block, 0x66, 0x0f, 0xef, 0xc0 | src_reg | (dst_reg << 3)); /*PXOR dst_reg, src_reg*/ +} + +void +host_x86_PCMPEQB_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg) +{ + codegen_alloc_bytes(block, 4); + codegen_addbyte4(block, 0x66, 0x0f, 0x74, 0xc0 | src_reg | (dst_reg << 3)); /*PCMPEQB dst_reg, src_reg*/ +} +void +host_x86_PCMPEQW_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg) +{ + codegen_alloc_bytes(block, 4); + codegen_addbyte4(block, 0x66, 0x0f, 0x75, 0xc0 | src_reg | (dst_reg << 3)); /*PCMPEQW dst_reg, src_reg*/ +} +void +host_x86_PCMPEQD_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg) +{ + codegen_alloc_bytes(block, 4); + codegen_addbyte4(block, 0x66, 0x0f, 0x76, 0xc0 | src_reg | (dst_reg << 3)); /*PCMPEQD dst_reg, src_reg*/ +} +void +host_x86_PCMPGTB_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg) +{ + codegen_alloc_bytes(block, 4); + codegen_addbyte4(block, 0x66, 0x0f, 0x64, 0xc0 | src_reg | (dst_reg << 3)); /*PCMPGTB dst_reg, src_reg*/ +} +void +host_x86_PCMPGTW_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg) +{ + codegen_alloc_bytes(block, 4); + codegen_addbyte4(block, 0x66, 0x0f, 0x65, 0xc0 | src_reg | (dst_reg << 3)); /*PCMPGTW dst_reg, src_reg*/ +} +void +host_x86_PCMPGTD_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg) +{ + codegen_alloc_bytes(block, 4); + codegen_addbyte4(block, 0x66, 0x0f, 0x66, 0xc0 | src_reg | (dst_reg << 3)); /*PCMPGTD dst_reg, src_reg*/ +} + +void +host_x86_PMADDWD_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg) +{ + codegen_alloc_bytes(block, 4); + codegen_addbyte4(block, 0x66, 0x0f, 0xf5, 0xc0 | src_reg | (dst_reg << 3)); /*PMULLW dst_reg, src_reg*/ +} +void +host_x86_PMULHW_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg) +{ + codegen_alloc_bytes(block, 4); + codegen_addbyte4(block, 0x66, 0x0f, 0xe5, 0xc0 | src_reg | (dst_reg << 3)); /*PMULLW dst_reg, src_reg*/ +} +void +host_x86_PMULLW_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg) +{ + codegen_alloc_bytes(block, 4); + codegen_addbyte4(block, 0x66, 0x0f, 0xd5, 0xc0 | src_reg | (dst_reg << 3)); /*PMULLW dst_reg, src_reg*/ +} + +void +host_x86_PSLLW_XREG_IMM(codeblock_t *block, int dst_reg, int shift) +{ + codegen_alloc_bytes(block, 5); + codegen_addbyte4(block, 0x66, 0x0f, 0x71, 0xc0 | 0x30 | dst_reg); /*PSLLW dst_reg, imm*/ + codegen_addbyte(block, shift); +} +void +host_x86_PSLLD_XREG_IMM(codeblock_t *block, int dst_reg, int shift) +{ + codegen_alloc_bytes(block, 5); + codegen_addbyte4(block, 0x66, 0x0f, 0x72, 0xc0 | 0x30 | dst_reg); /*PSLLD dst_reg, imm*/ + codegen_addbyte(block, shift); +} +void +host_x86_PSLLQ_XREG_IMM(codeblock_t *block, int dst_reg, int shift) +{ + codegen_alloc_bytes(block, 5); + codegen_addbyte4(block, 0x66, 0x0f, 0x73, 0xc0 | 0x30 | dst_reg); /*PSLLD dst_reg, imm*/ + codegen_addbyte(block, shift); +} +void +host_x86_PSRAW_XREG_IMM(codeblock_t *block, int dst_reg, int shift) +{ + codegen_alloc_bytes(block, 5); + codegen_addbyte4(block, 0x66, 0x0f, 0x71, 0xc0 | 0x20 | dst_reg); /*PSRAW dst_reg, imm*/ + codegen_addbyte(block, shift); +} +void +host_x86_PSRAD_XREG_IMM(codeblock_t *block, int dst_reg, int shift) +{ + codegen_alloc_bytes(block, 5); + codegen_addbyte4(block, 0x66, 0x0f, 0x72, 0xc0 | 0x20 | dst_reg); /*PSRAD dst_reg, imm*/ + codegen_addbyte(block, shift); +} +void +host_x86_PSRAQ_XREG_IMM(codeblock_t *block, int dst_reg, int shift) +{ + codegen_alloc_bytes(block, 5); + codegen_addbyte4(block, 0x66, 0x0f, 0x73, 0xc0 | 0x20 | dst_reg); /*PSRAD dst_reg, imm*/ + codegen_addbyte(block, shift); +} +void +host_x86_PSRLW_XREG_IMM(codeblock_t *block, int dst_reg, int shift) +{ + codegen_alloc_bytes(block, 5); + codegen_addbyte4(block, 0x66, 0x0f, 0x71, 0xc0 | 0x10 | dst_reg); /*PSRLW dst_reg, imm*/ + codegen_addbyte(block, shift); +} +void +host_x86_PSRLD_XREG_IMM(codeblock_t *block, int dst_reg, int shift) +{ + codegen_alloc_bytes(block, 5); + codegen_addbyte4(block, 0x66, 0x0f, 0x72, 0xc0 | 0x10 | dst_reg); /*PSRLD dst_reg, imm*/ + codegen_addbyte(block, shift); +} +void +host_x86_PSRLQ_XREG_IMM(codeblock_t *block, int dst_reg, int shift) +{ + codegen_alloc_bytes(block, 5); + codegen_addbyte4(block, 0x66, 0x0f, 0x73, 0xc0 | 0x10 | dst_reg); /*PSRLD dst_reg, imm*/ + codegen_addbyte(block, shift); +} + +void +host_x86_PSUBB_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg) +{ + codegen_alloc_bytes(block, 4); + codegen_addbyte4(block, 0x66, 0x0f, 0xf8, 0xc0 | src_reg | (dst_reg << 3)); /*PADDB dst_reg, src_reg*/ +} +void +host_x86_PSUBW_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg) +{ + codegen_alloc_bytes(block, 4); + codegen_addbyte4(block, 0x66, 0x0f, 0xf9, 0xc0 | src_reg | (dst_reg << 3)); /*PADDW dst_reg, src_reg*/ +} +void +host_x86_PSUBD_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg) +{ + codegen_alloc_bytes(block, 4); + codegen_addbyte4(block, 0x66, 0x0f, 0xfa, 0xc0 | src_reg | (dst_reg << 3)); /*PADDD dst_reg, src_reg*/ +} +void +host_x86_PSUBSB_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg) +{ + codegen_alloc_bytes(block, 4); + codegen_addbyte4(block, 0x66, 0x0f, 0xe8, 0xc0 | src_reg | (dst_reg << 3)); /*PSUBSB dst_reg, src_reg*/ +} +void +host_x86_PSUBSW_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg) +{ + codegen_alloc_bytes(block, 4); + codegen_addbyte4(block, 0x66, 0x0f, 0xe9, 0xc0 | src_reg | (dst_reg << 3)); /*PSUBSW dst_reg, src_reg*/ +} +void +host_x86_PSUBUSB_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg) +{ + codegen_alloc_bytes(block, 4); + codegen_addbyte4(block, 0x66, 0x0f, 0xd8, 0xc0 | src_reg | (dst_reg << 3)); /*PSUBUSB dst_reg, src_reg*/ +} +void +host_x86_PSUBUSW_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg) +{ + codegen_alloc_bytes(block, 4); + codegen_addbyte4(block, 0x66, 0x0f, 0xd9, 0xc0 | src_reg | (dst_reg << 3)); /*PSUBUSW dst_reg, src_reg*/ +} + +void +host_x86_PUNPCKHBW_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg) +{ + codegen_alloc_bytes(block, 9); + codegen_addbyte4(block, 0x66, 0x0f, 0x60, 0xc0 | src_reg | (dst_reg << 3)); /*PUNPCKLBW dst_reg, src_reg*/ + codegen_addbyte4(block, 0x66, 0x0f, 0x70, 0xc0 | dst_reg | (dst_reg << 3)); /*PSHUFD dst_reg, dst_reg, 0xee (move top 64-bits to low 64-bits)*/ + codegen_addbyte(block, 0xee); +} +void +host_x86_PUNPCKHWD_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg) +{ + codegen_alloc_bytes(block, 9); + codegen_addbyte4(block, 0x66, 0x0f, 0x61, 0xc0 | src_reg | (dst_reg << 3)); /*PUNPCKLWD dst_reg, src_reg*/ + codegen_addbyte4(block, 0x66, 0x0f, 0x70, 0xc0 | dst_reg | (dst_reg << 3)); /*PSHUFD dst_reg, dst_reg, 0xee (move top 64-bits to low 64-bits)*/ + codegen_addbyte(block, 0xee); +} +void +host_x86_PUNPCKHDQ_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg) +{ + codegen_alloc_bytes(block, 9); + codegen_addbyte4(block, 0x66, 0x0f, 0x62, 0xc0 | src_reg | (dst_reg << 3)); /*PUNPCKLDQ dst_reg, src_reg*/ + codegen_addbyte4(block, 0x66, 0x0f, 0x70, 0xc0 | dst_reg | (dst_reg << 3)); /*PSHUFD dst_reg, dst_reg, 0xee (move top 64-bits to low 64-bits)*/ + codegen_addbyte(block, 0xee); +} +void +host_x86_PUNPCKLBW_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg) +{ + codegen_alloc_bytes(block, 4); + codegen_addbyte4(block, 0x66, 0x0f, 0x60, 0xc0 | src_reg | (dst_reg << 3)); /*PUNPCKLBW dst_reg, src_reg*/ +} +void +host_x86_PUNPCKLWD_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg) +{ + codegen_alloc_bytes(block, 4); + codegen_addbyte4(block, 0x66, 0x0f, 0x61, 0xc0 | src_reg | (dst_reg << 3)); /*PUNPCKLWD dst_reg, src_reg*/ +} +void +host_x86_PUNPCKLDQ_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg) +{ + codegen_alloc_bytes(block, 4); + codegen_addbyte4(block, 0x66, 0x0f, 0x62, 0xc0 | src_reg | (dst_reg << 3)); /*PUNPCKLDQ dst_reg, src_reg*/ +} + +void +host_x86_SQRTSD_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg) +{ + codegen_alloc_bytes(block, 4); + codegen_addbyte4(block, 0xf2, 0x0f, 0x51, 0xc0 | src_reg | (dst_reg << 3)); /*SQRTSD dst_reg, src_reg*/ +} +void +host_x86_SQRTSS_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg) +{ + codegen_alloc_bytes(block, 4); + codegen_addbyte4(block, 0xf3, 0x0f, 0x51, 0xc0 | src_reg | (dst_reg << 3)); /*SQRTSS dst_reg, src_reg*/ +} + +void +host_x86_SUBPS_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg) +{ + codegen_alloc_bytes(block, 3); + codegen_addbyte3(block, 0x0f, 0x5c, 0xc0 | src_reg | (dst_reg << 3)); /*SUBPS dst_reg, src_reg*/ +} +void +host_x86_SUBSD_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg) +{ + codegen_alloc_bytes(block, 4); + codegen_addbyte4(block, 0xf2, 0x0f, 0x5c, 0xc0 | src_reg | (dst_reg << 3)); +} + +void +host_x86_UNPCKLPS_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg) +{ + codegen_alloc_bytes(block, 3); + codegen_addbyte3(block, 0x0f, 0x14, 0xc0 | src_reg | (dst_reg << 3)); } #endif diff --git a/src/codegen_new/codegen_backend_x86-64_uops.c b/src/codegen_new/codegen_backend_x86-64_uops.c index 471f982e8..fcab0f3ce 100644 --- a/src/codegen_new/codegen_backend_x86-64_uops.c +++ b/src/codegen_new/codegen_backend_x86-64_uops.c @@ -1,3165 +1,3519 @@ #if defined __amd64__ || defined _M_X64 -#include -#include <86box/86box.h> -#include "cpu.h" -#include <86box/mem.h> +# include +# include <86box/86box.h> +# include "cpu.h" +# include <86box/mem.h> +# include <86box/plat_unused.h> -#include "x86.h" -#include "x87.h" -#include "386_common.h" -#include "codegen.h" -#include "codegen_backend.h" -#include "codegen_backend_x86-64_defs.h" -#include "codegen_backend_x86-64_ops.h" -#include "codegen_backend_x86-64_ops_sse.h" -#include "codegen_ir_defs.h" +# include "x86.h" +# include "x86seg_common.h" +# include "x86seg.h" +# include "x87.h" +# include "386_common.h" +# include "codegen.h" +# include "codegen_backend.h" +# include "codegen_backend_x86-64_defs.h" +# include "codegen_backend_x86-64_ops.h" +# include "codegen_backend_x86-64_ops_sse.h" +# include "codegen_ir_defs.h" -#define STACK_ARG0 (0) -#define STACK_ARG1 (4) -#define STACK_ARG2 (8) -#define STACK_ARG3 (12) +# define STACK_ARG0 (0) +# define STACK_ARG1 (4) +# define STACK_ARG2 (8) +# define STACK_ARG3 (12) -#define HOST_REG_GET(reg) ((IREG_GET_SIZE(reg) == IREG_SIZE_BH) ? (IREG_GET_REG((reg) & 3) | 4) : (IREG_GET_REG(reg) & 7)) +# define HOST_REG_GET(reg) ((IREG_GET_SIZE(reg) == IREG_SIZE_BH) ? (IREG_GET_REG((reg) &3) | 4) : (IREG_GET_REG(reg) & 7)) -#define REG_IS_L(size) (size == IREG_SIZE_L) -#define REG_IS_W(size) (size == IREG_SIZE_W) -#define REG_IS_B(size) (size == IREG_SIZE_B || size == IREG_SIZE_BH) -#define REG_IS_BH(size) (size == IREG_SIZE_BH) -#define REG_IS_D(size) (size == IREG_SIZE_D) -#define REG_IS_Q(size) (size == IREG_SIZE_Q) +# define REG_IS_L(size) (size == IREG_SIZE_L) +# define REG_IS_W(size) (size == IREG_SIZE_W) +# define REG_IS_B(size) (size == IREG_SIZE_B || size == IREG_SIZE_BH) +# define REG_IS_BH(size) (size == IREG_SIZE_BH) +# define REG_IS_D(size) (size == IREG_SIZE_D) +# define REG_IS_Q(size) (size == IREG_SIZE_Q) -static int codegen_ADD(codeblock_t *block, uop_t *uop) +static int +codegen_ADD(codeblock_t *block, uop_t *uop) { - int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg_a = HOST_REG_GET(uop->src_reg_a_real), src_reg_b = HOST_REG_GET(uop->src_reg_b_real); - int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size_a = IREG_GET_SIZE(uop->src_reg_a_real), src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); + int dest_reg = HOST_REG_GET(uop->dest_reg_a_real); + int src_reg_a = HOST_REG_GET(uop->src_reg_a_real); + int src_reg_b = HOST_REG_GET(uop->src_reg_b_real); + int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real); + int src_size_a = IREG_GET_SIZE(uop->src_reg_a_real); + int src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); - if (REG_IS_L(dest_size) && REG_IS_L(src_size_a) && REG_IS_L(src_size_b)) - { - if (dest_reg != src_reg_a) - host_x86_LEA_REG_REG(block, dest_reg, src_reg_a, src_reg_b); - else - host_x86_ADD32_REG_REG(block, dest_reg, src_reg_b); - } - else if (REG_IS_W(dest_size) && REG_IS_W(src_size_a) && REG_IS_W(src_size_b)) - { - if (dest_reg != src_reg_a) - host_x86_MOV16_REG_REG(block, dest_reg, src_reg_a); - host_x86_ADD16_REG_REG(block, dest_reg, src_reg_b); - } - else if (REG_IS_B(dest_size) && REG_IS_B(src_size_a) && REG_IS_B(src_size_b)) - { - if (dest_reg != src_reg_a) - host_x86_MOV8_REG_REG(block, dest_reg, src_reg_a); - host_x86_ADD8_REG_REG(block, dest_reg, src_reg_b); - } -#ifdef RECOMPILER_DEBUG + if (REG_IS_L(dest_size) && REG_IS_L(src_size_a) && REG_IS_L(src_size_b)) { + if (dest_reg != src_reg_a) + host_x86_LEA_REG_REG(block, dest_reg, src_reg_a, src_reg_b); else - fatal("ADD %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real); -#endif - return 0; + host_x86_ADD32_REG_REG(block, dest_reg, src_reg_b); + } else if (REG_IS_W(dest_size) && REG_IS_W(src_size_a) && REG_IS_W(src_size_b)) { + if (dest_reg != src_reg_a) + host_x86_MOV16_REG_REG(block, dest_reg, src_reg_a); + host_x86_ADD16_REG_REG(block, dest_reg, src_reg_b); + } else if (REG_IS_B(dest_size) && REG_IS_B(src_size_a) && REG_IS_B(src_size_b)) { + if (dest_reg != src_reg_a) + host_x86_MOV8_REG_REG(block, dest_reg, src_reg_a); + host_x86_ADD8_REG_REG(block, dest_reg, src_reg_b); + } +# ifdef RECOMPILER_DEBUG + else + fatal("ADD %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real); +# endif + return 0; } -static int codegen_ADD_IMM(codeblock_t *block, uop_t *uop) +static int +codegen_ADD_IMM(codeblock_t *block, uop_t *uop) { - int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg = HOST_REG_GET(uop->src_reg_a_real); - int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size = IREG_GET_SIZE(uop->src_reg_a_real); + int dest_reg = HOST_REG_GET(uop->dest_reg_a_real); + int src_reg = HOST_REG_GET(uop->src_reg_a_real); + int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real); + int src_size = IREG_GET_SIZE(uop->src_reg_a_real); - if (REG_IS_L(dest_size) && REG_IS_L(src_size)) - { - if (dest_reg != src_reg) - host_x86_LEA_REG_IMM(block, dest_reg, src_reg, uop->imm_data); - else - host_x86_ADD32_REG_IMM(block, dest_reg, uop->imm_data); - } - else if (REG_IS_W(dest_size) && REG_IS_W(src_size)) - { - if (dest_reg != src_reg) - host_x86_MOV16_REG_REG(block, dest_reg, src_reg); - host_x86_ADD16_REG_IMM(block, dest_reg, uop->imm_data); - } - else if (REG_IS_B(dest_size) && REG_IS_B(src_size)) - { - if (dest_reg != src_reg) - host_x86_MOV8_REG_REG(block, dest_reg, src_reg); - host_x86_ADD8_REG_IMM(block, dest_reg, uop->imm_data); - } -#ifdef RECOMPILER_DEBUG + if (REG_IS_L(dest_size) && REG_IS_L(src_size)) { + if (dest_reg != src_reg) + host_x86_LEA_REG_IMM(block, dest_reg, src_reg, uop->imm_data); else - fatal("ADD_IMM %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real); -#endif - return 0; + host_x86_ADD32_REG_IMM(block, dest_reg, uop->imm_data); + } else if (REG_IS_W(dest_size) && REG_IS_W(src_size)) { + if (dest_reg != src_reg) + host_x86_MOV16_REG_REG(block, dest_reg, src_reg); + host_x86_ADD16_REG_IMM(block, dest_reg, uop->imm_data); + } else if (REG_IS_B(dest_size) && REG_IS_B(src_size)) { + if (dest_reg != src_reg) + host_x86_MOV8_REG_REG(block, dest_reg, src_reg); + host_x86_ADD8_REG_IMM(block, dest_reg, uop->imm_data); + } +# ifdef RECOMPILER_DEBUG + else + fatal("ADD_IMM %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real); +# endif + return 0; } -static int codegen_ADD_LSHIFT(codeblock_t *block, uop_t *uop) +static int +codegen_ADD_LSHIFT(codeblock_t *block, uop_t *uop) { - if (!uop->imm_data) - { - if (uop->dest_reg_a_real == uop->src_reg_a_real) - host_x86_ADD32_REG_REG(block, uop->dest_reg_a_real, uop->src_reg_b_real); - else - host_x86_LEA_REG_REG(block, uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real); - } - else if (uop->imm_data < 4) - host_x86_LEA_REG_REG_SHIFT(block, uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real, uop->imm_data); -#ifdef RECOMPILER_DEBUG + if (!uop->imm_data) { + if (uop->dest_reg_a_real == uop->src_reg_a_real) + host_x86_ADD32_REG_REG(block, uop->dest_reg_a_real, uop->src_reg_b_real); else - fatal("codegen_ADD_LSHIFT - shift out of range %i\n", uop->imm_data); -#endif - return 0; + host_x86_LEA_REG_REG(block, uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real); + } else if (uop->imm_data < 4) + host_x86_LEA_REG_REG_SHIFT(block, uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real, uop->imm_data); +# ifdef RECOMPILER_DEBUG + else + fatal("codegen_ADD_LSHIFT - shift out of range %i\n", uop->imm_data); +# endif + return 0; } -static int codegen_AND(codeblock_t *block, uop_t *uop) +static int +codegen_AND(codeblock_t *block, uop_t *uop) { - int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg_a = HOST_REG_GET(uop->src_reg_a_real), src_reg_b = HOST_REG_GET(uop->src_reg_b_real); - int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size_a = IREG_GET_SIZE(uop->src_reg_a_real), src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); + int dest_reg = HOST_REG_GET(uop->dest_reg_a_real); + int src_reg_a = HOST_REG_GET(uop->src_reg_a_real); + int src_reg_b = HOST_REG_GET(uop->src_reg_b_real); + int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real); + int src_size_a = IREG_GET_SIZE(uop->src_reg_a_real); + int src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); - if (REG_IS_Q(dest_size) && REG_IS_Q(src_size_a) && REG_IS_Q(src_size_b) && uop->dest_reg_a_real == uop->src_reg_a_real) - { - host_x86_PAND_XREG_XREG(block, dest_reg, src_reg_b); - } - else if (REG_IS_L(dest_size) && REG_IS_L(src_size_a) && REG_IS_L(src_size_b)) - { - if (dest_reg != src_reg_a) - host_x86_MOV32_REG_REG(block, dest_reg, src_reg_a); - host_x86_AND32_REG_REG(block, dest_reg, src_reg_b); - } - else if (REG_IS_W(dest_size) && REG_IS_W(src_size_a) && REG_IS_W(src_size_b)) - { - if (dest_reg != src_reg_a) - host_x86_MOV16_REG_REG(block, dest_reg, src_reg_a); - host_x86_AND16_REG_REG(block, dest_reg, src_reg_b); - } - else if (REG_IS_B(dest_size) && REG_IS_B(src_size_a) && REG_IS_B(src_size_b)) - { - if (dest_reg != src_reg_a) - host_x86_MOV8_REG_REG(block, dest_reg, src_reg_a); - host_x86_AND8_REG_REG(block, dest_reg, src_reg_b); - } -#ifdef RECOMPILER_DEBUG - else - fatal("AND %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real); -#endif - return 0; + if (REG_IS_Q(dest_size) && REG_IS_Q(src_size_a) && REG_IS_Q(src_size_b) && uop->dest_reg_a_real == uop->src_reg_a_real) { + host_x86_PAND_XREG_XREG(block, dest_reg, src_reg_b); + } else if (REG_IS_L(dest_size) && REG_IS_L(src_size_a) && REG_IS_L(src_size_b)) { + if (dest_reg != src_reg_a) + host_x86_MOV32_REG_REG(block, dest_reg, src_reg_a); + host_x86_AND32_REG_REG(block, dest_reg, src_reg_b); + } else if (REG_IS_W(dest_size) && REG_IS_W(src_size_a) && REG_IS_W(src_size_b)) { + if (dest_reg != src_reg_a) + host_x86_MOV16_REG_REG(block, dest_reg, src_reg_a); + host_x86_AND16_REG_REG(block, dest_reg, src_reg_b); + } else if (REG_IS_B(dest_size) && REG_IS_B(src_size_a) && REG_IS_B(src_size_b)) { + if (dest_reg != src_reg_a) + host_x86_MOV8_REG_REG(block, dest_reg, src_reg_a); + host_x86_AND8_REG_REG(block, dest_reg, src_reg_b); + } +# ifdef RECOMPILER_DEBUG + else + fatal("AND %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real); +# endif + return 0; } -static int codegen_AND_IMM(codeblock_t *block, uop_t *uop) +static int +codegen_AND_IMM(codeblock_t *block, uop_t *uop) { - int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg = HOST_REG_GET(uop->src_reg_a_real); - int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size = IREG_GET_SIZE(uop->src_reg_a_real); + int dest_reg = HOST_REG_GET(uop->dest_reg_a_real); + int src_reg = HOST_REG_GET(uop->src_reg_a_real); + int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real); + int src_size = IREG_GET_SIZE(uop->src_reg_a_real); - if (REG_IS_L(dest_size) && REG_IS_L(src_size)) - { - if (dest_reg != src_reg) - host_x86_MOV32_REG_REG(block, dest_reg, src_reg); - host_x86_AND32_REG_IMM(block, dest_reg, uop->imm_data); - } - else if (REG_IS_W(dest_size) && REG_IS_W(src_size)) - { - if (dest_reg != src_reg) - host_x86_MOV16_REG_REG(block, dest_reg, src_reg); - host_x86_AND16_REG_IMM(block, dest_reg, uop->imm_data); - } - else if (REG_IS_B(dest_size) && REG_IS_B(src_size)) - { - if (dest_reg != src_reg) - host_x86_MOV8_REG_REG(block, dest_reg, src_reg); - host_x86_AND8_REG_IMM(block, dest_reg, uop->imm_data); - } -#ifdef RECOMPILER_DEBUG - else - fatal("AND_IMM %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real); -#endif - return 0; + if (REG_IS_L(dest_size) && REG_IS_L(src_size)) { + if (dest_reg != src_reg) + host_x86_MOV32_REG_REG(block, dest_reg, src_reg); + host_x86_AND32_REG_IMM(block, dest_reg, uop->imm_data); + } else if (REG_IS_W(dest_size) && REG_IS_W(src_size)) { + if (dest_reg != src_reg) + host_x86_MOV16_REG_REG(block, dest_reg, src_reg); + host_x86_AND16_REG_IMM(block, dest_reg, uop->imm_data); + } else if (REG_IS_B(dest_size) && REG_IS_B(src_size)) { + if (dest_reg != src_reg) + host_x86_MOV8_REG_REG(block, dest_reg, src_reg); + host_x86_AND8_REG_IMM(block, dest_reg, uop->imm_data); + } +# ifdef RECOMPILER_DEBUG + else + fatal("AND_IMM %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real); +# endif + return 0; } -static int codegen_ANDN(codeblock_t *block, uop_t *uop) +static int +codegen_ANDN(codeblock_t *block, uop_t *uop) { - int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), /*src_reg_a = HOST_REG_GET(uop->src_reg_a_real), */src_reg_b = HOST_REG_GET(uop->src_reg_b_real); - int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size_a = IREG_GET_SIZE(uop->src_reg_a_real), src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); - - if (REG_IS_Q(dest_size) && REG_IS_Q(src_size_a) && REG_IS_Q(src_size_b) && uop->dest_reg_a_real == uop->src_reg_a_real) - { - host_x86_PANDN_XREG_XREG(block, dest_reg, src_reg_b); - } -#ifdef RECOMPILER_DEBUG - else - fatal("ANDN %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real); + int dest_reg = HOST_REG_GET(uop->dest_reg_a_real); +#if 0 + int src_reg_a = HOST_REG_GET(uop->src_reg_a_real); #endif - return 0; + int src_reg_b = HOST_REG_GET(uop->src_reg_b_real); + int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real); + int src_size_a = IREG_GET_SIZE(uop->src_reg_a_real); + int src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); + + if (REG_IS_Q(dest_size) && REG_IS_Q(src_size_a) && REG_IS_Q(src_size_b) && uop->dest_reg_a_real == uop->src_reg_a_real) { + host_x86_PANDN_XREG_XREG(block, dest_reg, src_reg_b); + } +# ifdef RECOMPILER_DEBUG + else + fatal("ANDN %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real); +# endif + return 0; } -static int codegen_CALL_FUNC(codeblock_t *block, uop_t *uop) +static int +codegen_CALL_FUNC(codeblock_t *block, uop_t *uop) { - host_x86_CALL(block, uop->p); + host_x86_CALL(block, uop->p); - return 0; + return 0; } -static int codegen_CALL_FUNC_RESULT(codeblock_t *block, uop_t *uop) +static int +codegen_CALL_FUNC_RESULT(codeblock_t *block, uop_t *uop) { - int dest_reg = HOST_REG_GET(uop->dest_reg_a_real); + int dest_reg = HOST_REG_GET(uop->dest_reg_a_real); -#ifdef RECOMPILER_DEBUG - int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real); - if (!REG_IS_L(dest_size)) - fatal("CALL_FUNC_RESULT %02x\n", uop->dest_reg_a_real); -#endif - host_x86_CALL(block, uop->p); - host_x86_MOV32_REG_REG(block, dest_reg, REG_EAX); +# ifdef RECOMPILER_DEBUG + int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real); + if (!REG_IS_L(dest_size)) + fatal("CALL_FUNC_RESULT %02x\n", uop->dest_reg_a_real); +# endif + host_x86_CALL(block, uop->p); + host_x86_MOV32_REG_REG(block, dest_reg, REG_EAX); - return 0; + return 0; } -static int codegen_CALL_INSTRUCTION_FUNC(codeblock_t *block, uop_t *uop) +static int +codegen_CALL_INSTRUCTION_FUNC(codeblock_t *block, uop_t *uop) { - host_x86_CALL(block, uop->p); - host_x86_TEST32_REG(block, REG_EAX, REG_EAX); - host_x86_JNZ(block, codegen_exit_rout); + host_x86_CALL(block, uop->p); + host_x86_TEST32_REG(block, REG_EAX, REG_EAX); + host_x86_JNZ(block, codegen_exit_rout); - return 0; + return 0; } -static int codegen_CMP_IMM_JZ(codeblock_t *block, uop_t *uop) +static int +codegen_CMP_IMM_JZ(codeblock_t *block, uop_t *uop) { - int src_reg = HOST_REG_GET(uop->src_reg_a_real); - int src_size = IREG_GET_SIZE(uop->src_reg_a_real); + int src_reg = HOST_REG_GET(uop->src_reg_a_real); + int src_size = IREG_GET_SIZE(uop->src_reg_a_real); - if (REG_IS_L(src_size)) - { - host_x86_CMP32_REG_IMM(block, src_reg, uop->imm_data); - } -#ifdef RECOMPILER_DEBUG - else - fatal("CMP_IMM_JZ %02x\n", uop->src_reg_a_real); -#endif - host_x86_JZ(block, uop->p); + if (REG_IS_L(src_size)) { + host_x86_CMP32_REG_IMM(block, src_reg, uop->imm_data); + } +# ifdef RECOMPILER_DEBUG + else + fatal("CMP_IMM_JZ %02x\n", uop->src_reg_a_real); +# endif + host_x86_JZ(block, uop->p); - return 0; + return 0; } -static int codegen_CMP_IMM_JNZ_DEST(codeblock_t *block, uop_t *uop) +static int +codegen_CMP_IMM_JNZ_DEST(codeblock_t *block, uop_t *uop) { - int src_reg = HOST_REG_GET(uop->src_reg_a_real); - int src_size = IREG_GET_SIZE(uop->src_reg_a_real); + int src_reg = HOST_REG_GET(uop->src_reg_a_real); + int src_size = IREG_GET_SIZE(uop->src_reg_a_real); - if (REG_IS_L(src_size)) - { - host_x86_CMP32_REG_IMM(block, src_reg, uop->imm_data); - } - else if (REG_IS_W(src_size)) - { - host_x86_CMP16_REG_IMM(block, src_reg, uop->imm_data); - } -#ifdef RECOMPILER_DEBUG - else - fatal("CMP_IMM_JNZ_DEST %02x\n", uop->src_reg_a_real); -#endif - uop->p = host_x86_JNZ_long(block); + if (REG_IS_L(src_size)) { + host_x86_CMP32_REG_IMM(block, src_reg, uop->imm_data); + } else if (REG_IS_W(src_size)) { + host_x86_CMP16_REG_IMM(block, src_reg, uop->imm_data); + } +# ifdef RECOMPILER_DEBUG + else + fatal("CMP_IMM_JNZ_DEST %02x\n", uop->src_reg_a_real); +# endif + uop->p = host_x86_JNZ_long(block); - return 0; + return 0; } -static int codegen_CMP_IMM_JZ_DEST(codeblock_t *block, uop_t *uop) +static int +codegen_CMP_IMM_JZ_DEST(codeblock_t *block, uop_t *uop) { - int src_reg = HOST_REG_GET(uop->src_reg_a_real); - int src_size = IREG_GET_SIZE(uop->src_reg_a_real); + int src_reg = HOST_REG_GET(uop->src_reg_a_real); + int src_size = IREG_GET_SIZE(uop->src_reg_a_real); - if (REG_IS_L(src_size)) - { - host_x86_CMP32_REG_IMM(block, src_reg, uop->imm_data); - } - else if (REG_IS_W(src_size)) - { - host_x86_CMP16_REG_IMM(block, src_reg, uop->imm_data); - } -#ifdef RECOMPILER_DEBUG - else - fatal("CMP_IMM_JZ_DEST %02x\n", uop->src_reg_a_real); -#endif - uop->p = host_x86_JZ_long(block); + if (REG_IS_L(src_size)) { + host_x86_CMP32_REG_IMM(block, src_reg, uop->imm_data); + } else if (REG_IS_W(src_size)) { + host_x86_CMP16_REG_IMM(block, src_reg, uop->imm_data); + } +# ifdef RECOMPILER_DEBUG + else + fatal("CMP_IMM_JZ_DEST %02x\n", uop->src_reg_a_real); +# endif + uop->p = host_x86_JZ_long(block); - return 0; + return 0; } -static int codegen_CMP_JB(codeblock_t *block, uop_t *uop) +static int +codegen_CMP_JB(codeblock_t *block, uop_t *uop) { - int src_reg_a = HOST_REG_GET(uop->src_reg_a_real), src_reg_b = HOST_REG_GET(uop->src_reg_b_real); - int src_size_a = IREG_GET_SIZE(uop->src_reg_a_real), src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); - uint32_t *jump_p; + int src_reg_a = HOST_REG_GET(uop->src_reg_a_real); + int src_reg_b = HOST_REG_GET(uop->src_reg_b_real); + int src_size_a = IREG_GET_SIZE(uop->src_reg_a_real); + int src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); + uint32_t *jump_p; - if (REG_IS_L(src_size_a) && REG_IS_L(src_size_b)) - { - host_x86_CMP32_REG_REG(block, src_reg_a, src_reg_b); - } -#ifdef RECOMPILER_DEBUG - else - fatal("CMP_JB %02x\n", uop->src_reg_a_real); -#endif - jump_p = host_x86_JB_long(block); - *jump_p = (uintptr_t)uop->p - ((uintptr_t)jump_p + 4); + if (REG_IS_L(src_size_a) && REG_IS_L(src_size_b)) { + host_x86_CMP32_REG_REG(block, src_reg_a, src_reg_b); + } +# ifdef RECOMPILER_DEBUG + else + fatal("CMP_JB %02x\n", uop->src_reg_a_real); +# endif + jump_p = host_x86_JB_long(block); + *jump_p = (uintptr_t) uop->p - ((uintptr_t) jump_p + 4); - return 0; + return 0; } -static int codegen_CMP_JNBE(codeblock_t *block, uop_t *uop) +static int +codegen_CMP_JNBE(codeblock_t *block, uop_t *uop) { - int src_reg_a = HOST_REG_GET(uop->src_reg_a_real), src_reg_b = HOST_REG_GET(uop->src_reg_b_real); - int src_size_a = IREG_GET_SIZE(uop->src_reg_a_real), src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); - uint32_t *jump_p; + int src_reg_a = HOST_REG_GET(uop->src_reg_a_real); + int src_reg_b = HOST_REG_GET(uop->src_reg_b_real); + int src_size_a = IREG_GET_SIZE(uop->src_reg_a_real); + int src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); + uint32_t *jump_p; - if (REG_IS_L(src_size_a) && REG_IS_L(src_size_b)) - { - host_x86_CMP32_REG_REG(block, src_reg_a, src_reg_b); - } -#ifdef RECOMPILER_DEBUG - else - fatal("CMP_JNBE %02x\n", uop->src_reg_a_real); -#endif - jump_p = host_x86_JNBE_long(block); - *jump_p = (uintptr_t)uop->p - ((uintptr_t)jump_p + 4); + if (REG_IS_L(src_size_a) && REG_IS_L(src_size_b)) { + host_x86_CMP32_REG_REG(block, src_reg_a, src_reg_b); + } +# ifdef RECOMPILER_DEBUG + else + fatal("CMP_JNBE %02x\n", uop->src_reg_a_real); +# endif + jump_p = host_x86_JNBE_long(block); + *jump_p = (uintptr_t) uop->p - ((uintptr_t) jump_p + 4); - return 0; + return 0; } -static int codegen_CMP_JNB_DEST(codeblock_t *block, uop_t *uop) +static int +codegen_CMP_JNB_DEST(codeblock_t *block, uop_t *uop) { - int src_reg_a = HOST_REG_GET(uop->src_reg_a_real), src_reg_b = HOST_REG_GET(uop->src_reg_b_real); - int src_size_a = IREG_GET_SIZE(uop->src_reg_a_real), src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); + int src_reg_a = HOST_REG_GET(uop->src_reg_a_real); + int src_reg_b = HOST_REG_GET(uop->src_reg_b_real); + int src_size_a = IREG_GET_SIZE(uop->src_reg_a_real); + int src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); - if (REG_IS_L(src_size_a) && REG_IS_L(src_size_b)) - { - host_x86_CMP32_REG_REG(block, src_reg_a, src_reg_b); - } - else if (REG_IS_W(src_size_a) && REG_IS_W(src_size_b)) - { - host_x86_CMP16_REG_REG(block, src_reg_a, src_reg_b); - } - else if (REG_IS_B(src_size_a) && REG_IS_B(src_size_b)) - { - host_x86_CMP8_REG_REG(block, src_reg_a, src_reg_b); - } -#ifdef RECOMPILER_DEBUG - else - fatal("CMP_JNB_DEST %02x\n", uop->src_reg_a_real); -#endif - uop->p = host_x86_JNB_long(block); + if (REG_IS_L(src_size_a) && REG_IS_L(src_size_b)) { + host_x86_CMP32_REG_REG(block, src_reg_a, src_reg_b); + } else if (REG_IS_W(src_size_a) && REG_IS_W(src_size_b)) { + host_x86_CMP16_REG_REG(block, src_reg_a, src_reg_b); + } else if (REG_IS_B(src_size_a) && REG_IS_B(src_size_b)) { + host_x86_CMP8_REG_REG(block, src_reg_a, src_reg_b); + } +# ifdef RECOMPILER_DEBUG + else + fatal("CMP_JNB_DEST %02x\n", uop->src_reg_a_real); +# endif + uop->p = host_x86_JNB_long(block); - return 0; + return 0; } -static int codegen_CMP_JNBE_DEST(codeblock_t *block, uop_t *uop) +static int +codegen_CMP_JNBE_DEST(codeblock_t *block, uop_t *uop) { - int src_reg_a = HOST_REG_GET(uop->src_reg_a_real), src_reg_b = HOST_REG_GET(uop->src_reg_b_real); - int src_size_a = IREG_GET_SIZE(uop->src_reg_a_real), src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); + int src_reg_a = HOST_REG_GET(uop->src_reg_a_real); + int src_reg_b = HOST_REG_GET(uop->src_reg_b_real); + int src_size_a = IREG_GET_SIZE(uop->src_reg_a_real); + int src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); - if (REG_IS_L(src_size_a) && REG_IS_L(src_size_b)) - { - host_x86_CMP32_REG_REG(block, src_reg_a, src_reg_b); - } - else if (REG_IS_W(src_size_a) && REG_IS_W(src_size_b)) - { - host_x86_CMP16_REG_REG(block, src_reg_a, src_reg_b); - } - else if (REG_IS_B(src_size_a) && REG_IS_B(src_size_b)) - { - host_x86_CMP8_REG_REG(block, src_reg_a, src_reg_b); - } -#ifdef RECOMPILER_DEBUG - else - fatal("CMP_JNBE_DEST %02x\n", uop->src_reg_a_real); -#endif - uop->p = host_x86_JNBE_long(block); + if (REG_IS_L(src_size_a) && REG_IS_L(src_size_b)) { + host_x86_CMP32_REG_REG(block, src_reg_a, src_reg_b); + } else if (REG_IS_W(src_size_a) && REG_IS_W(src_size_b)) { + host_x86_CMP16_REG_REG(block, src_reg_a, src_reg_b); + } else if (REG_IS_B(src_size_a) && REG_IS_B(src_size_b)) { + host_x86_CMP8_REG_REG(block, src_reg_a, src_reg_b); + } +# ifdef RECOMPILER_DEBUG + else + fatal("CMP_JNBE_DEST %02x\n", uop->src_reg_a_real); +# endif + uop->p = host_x86_JNBE_long(block); - return 0; + return 0; } -static int codegen_CMP_JNL_DEST(codeblock_t *block, uop_t *uop) +static int +codegen_CMP_JNL_DEST(codeblock_t *block, uop_t *uop) { - int src_reg_a = HOST_REG_GET(uop->src_reg_a_real), src_reg_b = HOST_REG_GET(uop->src_reg_b_real); - int src_size_a = IREG_GET_SIZE(uop->src_reg_a_real), src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); + int src_reg_a = HOST_REG_GET(uop->src_reg_a_real); + int src_reg_b = HOST_REG_GET(uop->src_reg_b_real); + int src_size_a = IREG_GET_SIZE(uop->src_reg_a_real); + int src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); - if (REG_IS_L(src_size_a) && REG_IS_L(src_size_b)) - { - host_x86_CMP32_REG_REG(block, src_reg_a, src_reg_b); - } - else if (REG_IS_W(src_size_a) && REG_IS_W(src_size_b)) - { - host_x86_CMP16_REG_REG(block, src_reg_a, src_reg_b); - } - else if (REG_IS_B(src_size_a) && REG_IS_B(src_size_b)) - { - host_x86_CMP8_REG_REG(block, src_reg_a, src_reg_b); - } -#ifdef RECOMPILER_DEBUG - else - fatal("CMP_JNL_DEST %02x\n", uop->src_reg_a_real); -#endif - uop->p = host_x86_JNL_long(block); + if (REG_IS_L(src_size_a) && REG_IS_L(src_size_b)) { + host_x86_CMP32_REG_REG(block, src_reg_a, src_reg_b); + } else if (REG_IS_W(src_size_a) && REG_IS_W(src_size_b)) { + host_x86_CMP16_REG_REG(block, src_reg_a, src_reg_b); + } else if (REG_IS_B(src_size_a) && REG_IS_B(src_size_b)) { + host_x86_CMP8_REG_REG(block, src_reg_a, src_reg_b); + } +# ifdef RECOMPILER_DEBUG + else + fatal("CMP_JNL_DEST %02x\n", uop->src_reg_a_real); +# endif + uop->p = host_x86_JNL_long(block); - return 0; + return 0; } -static int codegen_CMP_JNLE_DEST(codeblock_t *block, uop_t *uop) +static int +codegen_CMP_JNLE_DEST(codeblock_t *block, uop_t *uop) { - int src_reg_a = HOST_REG_GET(uop->src_reg_a_real), src_reg_b = HOST_REG_GET(uop->src_reg_b_real); - int src_size_a = IREG_GET_SIZE(uop->src_reg_a_real), src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); + int src_reg_a = HOST_REG_GET(uop->src_reg_a_real); + int src_reg_b = HOST_REG_GET(uop->src_reg_b_real); + int src_size_a = IREG_GET_SIZE(uop->src_reg_a_real); + int src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); - if (REG_IS_L(src_size_a) && REG_IS_L(src_size_b)) - { - host_x86_CMP32_REG_REG(block, src_reg_a, src_reg_b); - } - else if (REG_IS_W(src_size_a) && REG_IS_W(src_size_b)) - { - host_x86_CMP16_REG_REG(block, src_reg_a, src_reg_b); - } - else if (REG_IS_B(src_size_a) && REG_IS_B(src_size_b)) - { - host_x86_CMP8_REG_REG(block, src_reg_a, src_reg_b); - } -#ifdef RECOMPILER_DEBUG - else - fatal("CMP_JNLE_DEST %02x\n", uop->src_reg_a_real); -#endif - uop->p = host_x86_JNLE_long(block); + if (REG_IS_L(src_size_a) && REG_IS_L(src_size_b)) { + host_x86_CMP32_REG_REG(block, src_reg_a, src_reg_b); + } else if (REG_IS_W(src_size_a) && REG_IS_W(src_size_b)) { + host_x86_CMP16_REG_REG(block, src_reg_a, src_reg_b); + } else if (REG_IS_B(src_size_a) && REG_IS_B(src_size_b)) { + host_x86_CMP8_REG_REG(block, src_reg_a, src_reg_b); + } +# ifdef RECOMPILER_DEBUG + else + fatal("CMP_JNLE_DEST %02x\n", uop->src_reg_a_real); +# endif + uop->p = host_x86_JNLE_long(block); - return 0; + return 0; } -static int codegen_CMP_JNO_DEST(codeblock_t *block, uop_t *uop) +static int +codegen_CMP_JNO_DEST(codeblock_t *block, uop_t *uop) { - int src_reg_a = HOST_REG_GET(uop->src_reg_a_real), src_reg_b = HOST_REG_GET(uop->src_reg_b_real); - int src_size_a = IREG_GET_SIZE(uop->src_reg_a_real), src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); + int src_reg_a = HOST_REG_GET(uop->src_reg_a_real); + int src_reg_b = HOST_REG_GET(uop->src_reg_b_real); + int src_size_a = IREG_GET_SIZE(uop->src_reg_a_real); + int src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); - if (REG_IS_L(src_size_a) && REG_IS_L(src_size_b)) - { - host_x86_CMP32_REG_REG(block, src_reg_a, src_reg_b); - } - else if (REG_IS_W(src_size_a) && REG_IS_W(src_size_b)) - { - host_x86_CMP16_REG_REG(block, src_reg_a, src_reg_b); - } - else if (REG_IS_B(src_size_a) && REG_IS_B(src_size_b)) - { - host_x86_CMP8_REG_REG(block, src_reg_a, src_reg_b); - } -#ifdef RECOMPILER_DEBUG - else - fatal("CMP_JNO_DEST %02x\n", uop->src_reg_a_real); -#endif - uop->p = host_x86_JNO_long(block); + if (REG_IS_L(src_size_a) && REG_IS_L(src_size_b)) { + host_x86_CMP32_REG_REG(block, src_reg_a, src_reg_b); + } else if (REG_IS_W(src_size_a) && REG_IS_W(src_size_b)) { + host_x86_CMP16_REG_REG(block, src_reg_a, src_reg_b); + } else if (REG_IS_B(src_size_a) && REG_IS_B(src_size_b)) { + host_x86_CMP8_REG_REG(block, src_reg_a, src_reg_b); + } +# ifdef RECOMPILER_DEBUG + else + fatal("CMP_JNO_DEST %02x\n", uop->src_reg_a_real); +# endif + uop->p = host_x86_JNO_long(block); - return 0; + return 0; } -static int codegen_CMP_JNZ_DEST(codeblock_t *block, uop_t *uop) +static int +codegen_CMP_JNZ_DEST(codeblock_t *block, uop_t *uop) { - int src_reg_a = HOST_REG_GET(uop->src_reg_a_real), src_reg_b = HOST_REG_GET(uop->src_reg_b_real); - int src_size_a = IREG_GET_SIZE(uop->src_reg_a_real), src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); + int src_reg_a = HOST_REG_GET(uop->src_reg_a_real); + int src_reg_b = HOST_REG_GET(uop->src_reg_b_real); + int src_size_a = IREG_GET_SIZE(uop->src_reg_a_real); + int src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); - if (REG_IS_L(src_size_a) && REG_IS_L(src_size_b)) - { - host_x86_CMP32_REG_REG(block, src_reg_a, src_reg_b); - } - else if (REG_IS_W(src_size_a) && REG_IS_W(src_size_b)) - { - host_x86_CMP16_REG_REG(block, src_reg_a, src_reg_b); - } - else if (REG_IS_B(src_size_a) && REG_IS_B(src_size_b)) - { - host_x86_CMP8_REG_REG(block, src_reg_a, src_reg_b); - } -#ifdef RECOMPILER_DEBUG - else - fatal("CMP_JNZ_DEST %02x\n", uop->src_reg_a_real); -#endif - uop->p = host_x86_JNZ_long(block); + if (REG_IS_L(src_size_a) && REG_IS_L(src_size_b)) { + host_x86_CMP32_REG_REG(block, src_reg_a, src_reg_b); + } else if (REG_IS_W(src_size_a) && REG_IS_W(src_size_b)) { + host_x86_CMP16_REG_REG(block, src_reg_a, src_reg_b); + } else if (REG_IS_B(src_size_a) && REG_IS_B(src_size_b)) { + host_x86_CMP8_REG_REG(block, src_reg_a, src_reg_b); + } +# ifdef RECOMPILER_DEBUG + else + fatal("CMP_JNZ_DEST %02x\n", uop->src_reg_a_real); +# endif + uop->p = host_x86_JNZ_long(block); - return 0; + return 0; } -static int codegen_CMP_JB_DEST(codeblock_t *block, uop_t *uop) +static int +codegen_CMP_JB_DEST(codeblock_t *block, uop_t *uop) { - int src_reg_a = HOST_REG_GET(uop->src_reg_a_real), src_reg_b = HOST_REG_GET(uop->src_reg_b_real); - int src_size_a = IREG_GET_SIZE(uop->src_reg_a_real), src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); + int src_reg_a = HOST_REG_GET(uop->src_reg_a_real); + int src_reg_b = HOST_REG_GET(uop->src_reg_b_real); + int src_size_a = IREG_GET_SIZE(uop->src_reg_a_real); + int src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); - if (REG_IS_L(src_size_a) && REG_IS_L(src_size_b)) - { - host_x86_CMP32_REG_REG(block, src_reg_a, src_reg_b); - } - else if (REG_IS_W(src_size_a) && REG_IS_W(src_size_b)) - { - host_x86_CMP16_REG_REG(block, src_reg_a, src_reg_b); - } - else if (REG_IS_B(src_size_a) && REG_IS_B(src_size_b)) - { - host_x86_CMP8_REG_REG(block, src_reg_a, src_reg_b); - } -#ifdef RECOMPILER_DEBUG - else - fatal("CMP_JB_DEST %02x\n", uop->src_reg_a_real); -#endif - uop->p = host_x86_JB_long(block); + if (REG_IS_L(src_size_a) && REG_IS_L(src_size_b)) { + host_x86_CMP32_REG_REG(block, src_reg_a, src_reg_b); + } else if (REG_IS_W(src_size_a) && REG_IS_W(src_size_b)) { + host_x86_CMP16_REG_REG(block, src_reg_a, src_reg_b); + } else if (REG_IS_B(src_size_a) && REG_IS_B(src_size_b)) { + host_x86_CMP8_REG_REG(block, src_reg_a, src_reg_b); + } +# ifdef RECOMPILER_DEBUG + else + fatal("CMP_JB_DEST %02x\n", uop->src_reg_a_real); +# endif + uop->p = host_x86_JB_long(block); - return 0; + return 0; } -static int codegen_CMP_JBE_DEST(codeblock_t *block, uop_t *uop) +static int +codegen_CMP_JBE_DEST(codeblock_t *block, uop_t *uop) { - int src_reg_a = HOST_REG_GET(uop->src_reg_a_real), src_reg_b = HOST_REG_GET(uop->src_reg_b_real); - int src_size_a = IREG_GET_SIZE(uop->src_reg_a_real), src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); + int src_reg_a = HOST_REG_GET(uop->src_reg_a_real); + int src_reg_b = HOST_REG_GET(uop->src_reg_b_real); + int src_size_a = IREG_GET_SIZE(uop->src_reg_a_real); + int src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); - if (REG_IS_L(src_size_a) && REG_IS_L(src_size_b)) - { - host_x86_CMP32_REG_REG(block, src_reg_a, src_reg_b); - } - else if (REG_IS_W(src_size_a) && REG_IS_W(src_size_b)) - { - host_x86_CMP16_REG_REG(block, src_reg_a, src_reg_b); - } - else if (REG_IS_B(src_size_a) && REG_IS_B(src_size_b)) - { - host_x86_CMP8_REG_REG(block, src_reg_a, src_reg_b); - } -#ifdef RECOMPILER_DEBUG - else - fatal("CMP_JBE_DEST %02x\n", uop->src_reg_a_real); -#endif - uop->p = host_x86_JBE_long(block); + if (REG_IS_L(src_size_a) && REG_IS_L(src_size_b)) { + host_x86_CMP32_REG_REG(block, src_reg_a, src_reg_b); + } else if (REG_IS_W(src_size_a) && REG_IS_W(src_size_b)) { + host_x86_CMP16_REG_REG(block, src_reg_a, src_reg_b); + } else if (REG_IS_B(src_size_a) && REG_IS_B(src_size_b)) { + host_x86_CMP8_REG_REG(block, src_reg_a, src_reg_b); + } +# ifdef RECOMPILER_DEBUG + else + fatal("CMP_JBE_DEST %02x\n", uop->src_reg_a_real); +# endif + uop->p = host_x86_JBE_long(block); - return 0; + return 0; } -static int codegen_CMP_JL_DEST(codeblock_t *block, uop_t *uop) +static int +codegen_CMP_JL_DEST(codeblock_t *block, uop_t *uop) { - int src_reg_a = HOST_REG_GET(uop->src_reg_a_real), src_reg_b = HOST_REG_GET(uop->src_reg_b_real); - int src_size_a = IREG_GET_SIZE(uop->src_reg_a_real), src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); + int src_reg_a = HOST_REG_GET(uop->src_reg_a_real); + int src_reg_b = HOST_REG_GET(uop->src_reg_b_real); + int src_size_a = IREG_GET_SIZE(uop->src_reg_a_real); + int src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); - if (REG_IS_L(src_size_a) && REG_IS_L(src_size_b)) - { - host_x86_CMP32_REG_REG(block, src_reg_a, src_reg_b); - } - else if (REG_IS_W(src_size_a) && REG_IS_W(src_size_b)) - { - host_x86_CMP16_REG_REG(block, src_reg_a, src_reg_b); - } - else if (REG_IS_B(src_size_a) && REG_IS_B(src_size_b)) - { - host_x86_CMP8_REG_REG(block, src_reg_a, src_reg_b); - } -#ifdef RECOMPILER_DEBUG - else - fatal("CMP_JL_DEST %02x\n", uop->src_reg_a_real); -#endif - uop->p = host_x86_JL_long(block); + if (REG_IS_L(src_size_a) && REG_IS_L(src_size_b)) { + host_x86_CMP32_REG_REG(block, src_reg_a, src_reg_b); + } else if (REG_IS_W(src_size_a) && REG_IS_W(src_size_b)) { + host_x86_CMP16_REG_REG(block, src_reg_a, src_reg_b); + } else if (REG_IS_B(src_size_a) && REG_IS_B(src_size_b)) { + host_x86_CMP8_REG_REG(block, src_reg_a, src_reg_b); + } +# ifdef RECOMPILER_DEBUG + else + fatal("CMP_JL_DEST %02x\n", uop->src_reg_a_real); +# endif + uop->p = host_x86_JL_long(block); - return 0; + return 0; } -static int codegen_CMP_JLE_DEST(codeblock_t *block, uop_t *uop) +static int +codegen_CMP_JLE_DEST(codeblock_t *block, uop_t *uop) { - int src_reg_a = HOST_REG_GET(uop->src_reg_a_real), src_reg_b = HOST_REG_GET(uop->src_reg_b_real); - int src_size_a = IREG_GET_SIZE(uop->src_reg_a_real), src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); + int src_reg_a = HOST_REG_GET(uop->src_reg_a_real); + int src_reg_b = HOST_REG_GET(uop->src_reg_b_real); + int src_size_a = IREG_GET_SIZE(uop->src_reg_a_real); + int src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); - if (REG_IS_L(src_size_a) && REG_IS_L(src_size_b)) - { - host_x86_CMP32_REG_REG(block, src_reg_a, src_reg_b); - } - else if (REG_IS_W(src_size_a) && REG_IS_W(src_size_b)) - { - host_x86_CMP16_REG_REG(block, src_reg_a, src_reg_b); - } - else if (REG_IS_B(src_size_a) && REG_IS_B(src_size_b)) - { - host_x86_CMP8_REG_REG(block, src_reg_a, src_reg_b); - } -#ifdef RECOMPILER_DEBUG - else - fatal("CMP_JLE_DEST %02x\n", uop->src_reg_a_real); -#endif - uop->p = host_x86_JLE_long(block); + if (REG_IS_L(src_size_a) && REG_IS_L(src_size_b)) { + host_x86_CMP32_REG_REG(block, src_reg_a, src_reg_b); + } else if (REG_IS_W(src_size_a) && REG_IS_W(src_size_b)) { + host_x86_CMP16_REG_REG(block, src_reg_a, src_reg_b); + } else if (REG_IS_B(src_size_a) && REG_IS_B(src_size_b)) { + host_x86_CMP8_REG_REG(block, src_reg_a, src_reg_b); + } +# ifdef RECOMPILER_DEBUG + else + fatal("CMP_JLE_DEST %02x\n", uop->src_reg_a_real); +# endif + uop->p = host_x86_JLE_long(block); - return 0; + return 0; } -static int codegen_CMP_JO_DEST(codeblock_t *block, uop_t *uop) +static int +codegen_CMP_JO_DEST(codeblock_t *block, uop_t *uop) { - int src_reg_a = HOST_REG_GET(uop->src_reg_a_real), src_reg_b = HOST_REG_GET(uop->src_reg_b_real); - int src_size_a = IREG_GET_SIZE(uop->src_reg_a_real), src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); + int src_reg_a = HOST_REG_GET(uop->src_reg_a_real); + int src_reg_b = HOST_REG_GET(uop->src_reg_b_real); + int src_size_a = IREG_GET_SIZE(uop->src_reg_a_real); + int src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); - if (REG_IS_L(src_size_a) && REG_IS_L(src_size_b)) - { - host_x86_CMP32_REG_REG(block, src_reg_a, src_reg_b); - } - else if (REG_IS_W(src_size_a) && REG_IS_W(src_size_b)) - { - host_x86_CMP16_REG_REG(block, src_reg_a, src_reg_b); - } - else if (REG_IS_B(src_size_a) && REG_IS_B(src_size_b)) - { - host_x86_CMP8_REG_REG(block, src_reg_a, src_reg_b); - } -#ifdef RECOMPILER_DEBUG - else - fatal("CMP_JO_DEST %02x\n", uop->src_reg_a_real); -#endif - uop->p = host_x86_JO_long(block); + if (REG_IS_L(src_size_a) && REG_IS_L(src_size_b)) { + host_x86_CMP32_REG_REG(block, src_reg_a, src_reg_b); + } else if (REG_IS_W(src_size_a) && REG_IS_W(src_size_b)) { + host_x86_CMP16_REG_REG(block, src_reg_a, src_reg_b); + } else if (REG_IS_B(src_size_a) && REG_IS_B(src_size_b)) { + host_x86_CMP8_REG_REG(block, src_reg_a, src_reg_b); + } +# ifdef RECOMPILER_DEBUG + else + fatal("CMP_JO_DEST %02x\n", uop->src_reg_a_real); +# endif + uop->p = host_x86_JO_long(block); - return 0; + return 0; } -static int codegen_CMP_JZ_DEST(codeblock_t *block, uop_t *uop) +static int +codegen_CMP_JZ_DEST(codeblock_t *block, uop_t *uop) { - int src_reg_a = HOST_REG_GET(uop->src_reg_a_real), src_reg_b = HOST_REG_GET(uop->src_reg_b_real); - int src_size_a = IREG_GET_SIZE(uop->src_reg_a_real), src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); + int src_reg_a = HOST_REG_GET(uop->src_reg_a_real); + int src_reg_b = HOST_REG_GET(uop->src_reg_b_real); + int src_size_a = IREG_GET_SIZE(uop->src_reg_a_real); + int src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); - if (REG_IS_L(src_size_a) && REG_IS_L(src_size_b)) - { - host_x86_CMP32_REG_REG(block, src_reg_a, src_reg_b); - } - else if (REG_IS_W(src_size_a) && REG_IS_W(src_size_b)) - { - host_x86_CMP16_REG_REG(block, src_reg_a, src_reg_b); - } - else if (REG_IS_B(src_size_a) && REG_IS_B(src_size_b)) - { - host_x86_CMP8_REG_REG(block, src_reg_a, src_reg_b); - } -#ifdef RECOMPILER_DEBUG - else - fatal("CMP_JZ_DEST %02x\n", uop->src_reg_a_real); -#endif - uop->p = host_x86_JZ_long(block); + if (REG_IS_L(src_size_a) && REG_IS_L(src_size_b)) { + host_x86_CMP32_REG_REG(block, src_reg_a, src_reg_b); + } else if (REG_IS_W(src_size_a) && REG_IS_W(src_size_b)) { + host_x86_CMP16_REG_REG(block, src_reg_a, src_reg_b); + } else if (REG_IS_B(src_size_a) && REG_IS_B(src_size_b)) { + host_x86_CMP8_REG_REG(block, src_reg_a, src_reg_b); + } +# ifdef RECOMPILER_DEBUG + else + fatal("CMP_JZ_DEST %02x\n", uop->src_reg_a_real); +# endif + uop->p = host_x86_JZ_long(block); - return 0; + return 0; } -static int codegen_FABS(codeblock_t *block, uop_t *uop) +static int +codegen_FABS(codeblock_t *block, uop_t *uop) { - int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg_a = HOST_REG_GET(uop->src_reg_a_real); - int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size_a = IREG_GET_SIZE(uop->src_reg_a_real); + int dest_reg = HOST_REG_GET(uop->dest_reg_a_real); + int src_reg_a = HOST_REG_GET(uop->src_reg_a_real); + int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real); + int src_size_a = IREG_GET_SIZE(uop->src_reg_a_real); - if (REG_IS_D(dest_size) && REG_IS_D(src_size_a) && dest_reg == src_reg_a) - { - host_x86_PXOR_XREG_XREG(block, REG_XMM_TEMP, REG_XMM_TEMP); - host_x86_SUBSD_XREG_XREG(block, REG_XMM_TEMP, dest_reg); - host_x86_MAXSD_XREG_XREG(block, dest_reg, REG_XMM_TEMP); - } -#ifdef RECOMPILER_DEBUG - else - fatal("codegen_FABS %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real); -#endif - return 0; + if (REG_IS_D(dest_size) && REG_IS_D(src_size_a) && dest_reg == src_reg_a) { + host_x86_PXOR_XREG_XREG(block, REG_XMM_TEMP, REG_XMM_TEMP); + host_x86_SUBSD_XREG_XREG(block, REG_XMM_TEMP, dest_reg); + host_x86_MAXSD_XREG_XREG(block, dest_reg, REG_XMM_TEMP); + } +# ifdef RECOMPILER_DEBUG + else + fatal("codegen_FABS %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real); +# endif + return 0; } -static int codegen_FCHS(codeblock_t *block, uop_t *uop) +static int +codegen_FCHS(codeblock_t *block, uop_t *uop) { - int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg_a = HOST_REG_GET(uop->src_reg_a_real); - int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size_a = IREG_GET_SIZE(uop->src_reg_a_real); + int dest_reg = HOST_REG_GET(uop->dest_reg_a_real); + int src_reg_a = HOST_REG_GET(uop->src_reg_a_real); + int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real); + int src_size_a = IREG_GET_SIZE(uop->src_reg_a_real); - if (REG_IS_D(dest_size) && REG_IS_D(src_size_a)) - { - host_x86_MOVQ_XREG_XREG(block, REG_XMM_TEMP, src_reg_a); - host_x86_PXOR_XREG_XREG(block, dest_reg, dest_reg); - host_x86_SUBSD_XREG_XREG(block, dest_reg, REG_XMM_TEMP); - } -#ifdef RECOMPILER_DEBUG - else - fatal("codegen_FCHS %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real); -#endif - return 0; + if (REG_IS_D(dest_size) && REG_IS_D(src_size_a)) { + host_x86_MOVQ_XREG_XREG(block, REG_XMM_TEMP, src_reg_a); + host_x86_PXOR_XREG_XREG(block, dest_reg, dest_reg); + host_x86_SUBSD_XREG_XREG(block, dest_reg, REG_XMM_TEMP); + } +# ifdef RECOMPILER_DEBUG + else + fatal("codegen_FCHS %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real); +# endif + return 0; } -static int codegen_FSQRT(codeblock_t *block, uop_t *uop) +static int +codegen_FSQRT(codeblock_t *block, uop_t *uop) { - int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg_a = HOST_REG_GET(uop->src_reg_a_real); - int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size_a = IREG_GET_SIZE(uop->src_reg_a_real); + int dest_reg = HOST_REG_GET(uop->dest_reg_a_real); + int src_reg_a = HOST_REG_GET(uop->src_reg_a_real); + int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real); + int src_size_a = IREG_GET_SIZE(uop->src_reg_a_real); - if (REG_IS_D(dest_size) && REG_IS_D(src_size_a)) - { - host_x86_SQRTSD_XREG_XREG(block, dest_reg, src_reg_a); - } -#ifdef RECOMPILER_DEBUG - else - fatal("codegen_FSQRT %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real); -#endif - return 0; + if (REG_IS_D(dest_size) && REG_IS_D(src_size_a)) { + host_x86_SQRTSD_XREG_XREG(block, dest_reg, src_reg_a); + } +# ifdef RECOMPILER_DEBUG + else + fatal("codegen_FSQRT %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real); +# endif + return 0; } -static int codegen_FTST(codeblock_t *block, uop_t *uop) +static int +codegen_FTST(codeblock_t *block, uop_t *uop) { - int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg_a = HOST_REG_GET(uop->src_reg_a_real); - int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size_a = IREG_GET_SIZE(uop->src_reg_a_real); + int dest_reg = HOST_REG_GET(uop->dest_reg_a_real); + int src_reg_a = HOST_REG_GET(uop->src_reg_a_real); + int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real); + int src_size_a = IREG_GET_SIZE(uop->src_reg_a_real); - if (REG_IS_W(dest_size) && REG_IS_D(src_size_a)) - { - host_x86_PXOR_XREG_XREG(block, REG_XMM_TEMP, REG_XMM_TEMP); - if (dest_reg != REG_EAX) - host_x86_MOV32_REG_REG(block, REG_ECX, REG_EAX); - host_x86_XOR32_REG_REG(block, REG_EAX, REG_EAX); - host_x86_COMISD_XREG_XREG(block, src_reg_a, REG_XMM_TEMP); - host_x86_LAHF(block); - host_x86_AND16_REG_IMM(block, REG_EAX, C0|C2|C3); - if (dest_reg != REG_EAX) - { - host_x86_MOV16_REG_REG(block, dest_reg, REG_EAX); - host_x86_MOV32_REG_REG(block, REG_EAX, REG_ECX); - } + if (REG_IS_W(dest_size) && REG_IS_D(src_size_a)) { + host_x86_PXOR_XREG_XREG(block, REG_XMM_TEMP, REG_XMM_TEMP); + if (dest_reg != REG_EAX) + host_x86_MOV32_REG_REG(block, REG_ECX, REG_EAX); + host_x86_XOR32_REG_REG(block, REG_EAX, REG_EAX); + host_x86_COMISD_XREG_XREG(block, src_reg_a, REG_XMM_TEMP); + host_x86_LAHF(block); + host_x86_AND16_REG_IMM(block, REG_EAX, C0 | C2 | C3); + if (dest_reg != REG_EAX) { + host_x86_MOV16_REG_REG(block, dest_reg, REG_EAX); + host_x86_MOV32_REG_REG(block, REG_EAX, REG_ECX); } -#ifdef RECOMPILER_DEBUG - else - fatal("codegen_FTST %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real); -#endif - return 0; + } +# ifdef RECOMPILER_DEBUG + else + fatal("codegen_FTST %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real); +# endif + return 0; } -static int codegen_FADD(codeblock_t *block, uop_t *uop) +static int +codegen_FADD(codeblock_t *block, uop_t *uop) { - int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg_a = HOST_REG_GET(uop->src_reg_a_real), src_reg_b = HOST_REG_GET(uop->src_reg_b_real); - int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size_a = IREG_GET_SIZE(uop->src_reg_a_real), src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); + int dest_reg = HOST_REG_GET(uop->dest_reg_a_real); + int src_reg_a = HOST_REG_GET(uop->src_reg_a_real); + int src_reg_b = HOST_REG_GET(uop->src_reg_b_real); + int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real); + int src_size_a = IREG_GET_SIZE(uop->src_reg_a_real); + int src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); - if (REG_IS_D(dest_size) && REG_IS_D(src_size_a) && REG_IS_D(src_size_b) && dest_reg == src_reg_a) - { - host_x86_ADDSD_XREG_XREG(block, dest_reg, src_reg_b); - } -#ifdef RECOMPILER_DEBUG - else - fatal("codegen_FADD %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real); -#endif - return 0; + if (REG_IS_D(dest_size) && REG_IS_D(src_size_a) && REG_IS_D(src_size_b) && dest_reg == src_reg_a) { + host_x86_ADDSD_XREG_XREG(block, dest_reg, src_reg_b); + } +# ifdef RECOMPILER_DEBUG + else + fatal("codegen_FADD %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real); +# endif + return 0; } -static int codegen_FCOM(codeblock_t *block, uop_t *uop) +static int +codegen_FCOM(codeblock_t *block, uop_t *uop) { - int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg_a = HOST_REG_GET(uop->src_reg_a_real), src_reg_b = HOST_REG_GET(uop->src_reg_b_real); - int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size_a = IREG_GET_SIZE(uop->src_reg_a_real), src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); + int dest_reg = HOST_REG_GET(uop->dest_reg_a_real); + int src_reg_a = HOST_REG_GET(uop->src_reg_a_real); + int src_reg_b = HOST_REG_GET(uop->src_reg_b_real); + int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real); + int src_size_a = IREG_GET_SIZE(uop->src_reg_a_real); + int src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); - if (REG_IS_W(dest_size) && REG_IS_D(src_size_a) && REG_IS_D(src_size_b)) - { - if (dest_reg != REG_EAX) - host_x86_MOV32_REG_REG(block, REG_ECX, REG_EAX); - host_x86_XOR32_REG_REG(block, REG_EAX, REG_EAX); - host_x86_COMISD_XREG_XREG(block, src_reg_a, src_reg_b); - host_x86_LAHF(block); - host_x86_AND16_REG_IMM(block, REG_EAX, C0|C2|C3); - if (dest_reg != REG_EAX) - { - host_x86_MOV16_REG_REG(block, dest_reg, REG_EAX); - host_x86_MOV32_REG_REG(block, REG_EAX, REG_ECX); - } + if (REG_IS_W(dest_size) && REG_IS_D(src_size_a) && REG_IS_D(src_size_b)) { + if (dest_reg != REG_EAX) + host_x86_MOV32_REG_REG(block, REG_ECX, REG_EAX); + host_x86_XOR32_REG_REG(block, REG_EAX, REG_EAX); + host_x86_COMISD_XREG_XREG(block, src_reg_a, src_reg_b); + host_x86_LAHF(block); + host_x86_AND16_REG_IMM(block, REG_EAX, C0 | C2 | C3); + if (dest_reg != REG_EAX) { + host_x86_MOV16_REG_REG(block, dest_reg, REG_EAX); + host_x86_MOV32_REG_REG(block, REG_EAX, REG_ECX); } -#ifdef RECOMPILER_DEBUG - else - fatal("codegen_FCOM %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real); -#endif - return 0; + } +# ifdef RECOMPILER_DEBUG + else + fatal("codegen_FCOM %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real); +# endif + return 0; } -static int codegen_FDIV(codeblock_t *block, uop_t *uop) +static int +codegen_FDIV(codeblock_t *block, uop_t *uop) { - int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg_a = HOST_REG_GET(uop->src_reg_a_real), src_reg_b = HOST_REG_GET(uop->src_reg_b_real); - int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size_a = IREG_GET_SIZE(uop->src_reg_a_real), src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); + int dest_reg = HOST_REG_GET(uop->dest_reg_a_real); + int src_reg_a = HOST_REG_GET(uop->src_reg_a_real); + int src_reg_b = HOST_REG_GET(uop->src_reg_b_real); + int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real); + int src_size_a = IREG_GET_SIZE(uop->src_reg_a_real); + int src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); - if (REG_IS_D(dest_size) && REG_IS_D(src_size_a) && REG_IS_D(src_size_b) && dest_reg == src_reg_a) - { - host_x86_DIVSD_XREG_XREG(block, dest_reg, src_reg_b); - } - else if (REG_IS_D(dest_size) && REG_IS_D(src_size_a) && REG_IS_D(src_size_b)) - { - host_x86_MOVQ_XREG_XREG(block, REG_XMM_TEMP, src_reg_a); - host_x86_DIVSD_XREG_XREG(block, REG_XMM_TEMP, src_reg_b); - host_x86_MOVQ_XREG_XREG(block, dest_reg, REG_XMM_TEMP); - } -#ifdef RECOMPILER_DEBUG - else - fatal("codegen_FDIV %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real); -#endif - return 0; -} -static int codegen_FMUL(codeblock_t *block, uop_t *uop) -{ - int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg_a = HOST_REG_GET(uop->src_reg_a_real), src_reg_b = HOST_REG_GET(uop->src_reg_b_real); - int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size_a = IREG_GET_SIZE(uop->src_reg_a_real), src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); - - if (REG_IS_D(dest_size) && REG_IS_D(src_size_a) && REG_IS_D(src_size_b) && dest_reg == src_reg_a) - { - host_x86_MULSD_XREG_XREG(block, dest_reg, src_reg_b); - } -#ifdef RECOMPILER_DEBUG - else - fatal("codegen_FMUL %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real); -#endif - return 0; -} -static int codegen_FSUB(codeblock_t *block, uop_t *uop) -{ - int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg_a = HOST_REG_GET(uop->src_reg_a_real), src_reg_b = HOST_REG_GET(uop->src_reg_b_real); - int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size_a = IREG_GET_SIZE(uop->src_reg_a_real), src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); - - if (REG_IS_D(dest_size) && REG_IS_D(src_size_a) && REG_IS_D(src_size_b) && dest_reg == src_reg_a) - { - host_x86_SUBSD_XREG_XREG(block, dest_reg, src_reg_b); - } - else if (REG_IS_D(dest_size) && REG_IS_D(src_size_a) && REG_IS_D(src_size_b)) - { - host_x86_MOVQ_XREG_XREG(block, REG_XMM_TEMP, src_reg_a); - host_x86_SUBSD_XREG_XREG(block, REG_XMM_TEMP, src_reg_b); - host_x86_MOVQ_XREG_XREG(block, dest_reg, REG_XMM_TEMP); - } -#ifdef RECOMPILER_DEBUG - else - fatal("codegen_FSUB %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real); -#endif - return 0; -} - -static int codegen_FP_ENTER(codeblock_t *block, uop_t *uop) -{ - uint32_t *branch_offset; - - host_x86_MOV32_REG_ABS(block, REG_ECX, &cr0); - host_x86_TEST32_REG_IMM(block, REG_ECX, 0xc); - branch_offset = host_x86_JZ_long(block); - host_x86_MOV32_ABS_IMM(block, &cpu_state.oldpc, uop->imm_data); -#if _WIN64 - host_x86_MOV32_REG_IMM(block, REG_ECX, 7); -#else - host_x86_MOV32_REG_IMM(block, REG_EDI, 7); -#endif - host_x86_CALL(block, x86_int); - host_x86_JMP(block, codegen_exit_rout); - *branch_offset = (uint32_t)((uintptr_t)&block_write_data[block_pos] - (uintptr_t)branch_offset) - 4; - - return 0; -} -static int codegen_MMX_ENTER(codeblock_t *block, uop_t *uop) -{ - uint32_t *branch_offset; - - host_x86_MOV32_REG_ABS(block, REG_ECX, &cr0); - host_x86_TEST32_REG_IMM(block, REG_ECX, 0xc); - branch_offset = host_x86_JZ_long(block); - host_x86_MOV32_ABS_IMM(block, &cpu_state.oldpc, uop->imm_data); -#if _WIN64 - host_x86_MOV32_REG_IMM(block, REG_ECX, 7); -#else - host_x86_MOV32_REG_IMM(block, REG_EDI, 7); -#endif - host_x86_CALL(block, x86_int); - host_x86_JMP(block, codegen_exit_rout); - *branch_offset = (uint32_t)((uintptr_t)&block_write_data[block_pos] - (uintptr_t)branch_offset) - 4; - host_x86_MOV32_ABS_IMM(block, &cpu_state.tag[0], 0x01010101); - host_x86_MOV32_ABS_IMM(block, &cpu_state.tag[4], 0x01010101); - host_x86_MOV32_ABS_IMM(block, &cpu_state.TOP, 0); - host_x86_MOV8_ABS_IMM(block, &cpu_state.ismmx, 1); - - return 0; -} - -static int codegen_JMP(codeblock_t *block, uop_t *uop) -{ - host_x86_JMP(block, uop->p); - - return 0; -} - -static int codegen_LOAD_FUNC_ARG0(codeblock_t *block, uop_t *uop) -{ - int src_reg = HOST_REG_GET(uop->src_reg_a_real); - int src_size = IREG_GET_SIZE(uop->src_reg_a_real); - - if (REG_IS_W(src_size)) - { -#if _WIN64 - host_x86_MOVZX_REG_32_16(block, REG_ECX, src_reg); -#else - host_x86_MOVZX_REG_32_16(block, REG_EDI, src_reg); -#endif - } -#ifdef RECOMPILER_DEBUG - else - fatal("codegen_LOAD_FUNC_ARG0 %02x\n", uop->src_reg_a_real); -#endif - return 0; -} -static int codegen_LOAD_FUNC_ARG1(codeblock_t *block, uop_t *uop) -{ -#ifdef RECOMPILER_DEBUG - fatal("codegen_LOAD_FUNC_ARG1 %02x\n", uop->src_reg_a_real); -#endif - return 0; -} -static int codegen_LOAD_FUNC_ARG2(codeblock_t *block, uop_t *uop) -{ -#ifdef RECOMPILER_DEBUG - fatal("codegen_LOAD_FUNC_ARG2 %02x\n", uop->src_reg_a_real); -#endif - return 0; -} -static int codegen_LOAD_FUNC_ARG3(codeblock_t *block, uop_t *uop) -{ -#ifdef RECOMPILER_DEBUG - fatal("codegen_LOAD_FUNC_ARG3 %02x\n", uop->src_reg_a_real); -#endif - return 0; -} - -static int codegen_LOAD_FUNC_ARG0_IMM(codeblock_t *block, uop_t *uop) -{ -#if _WIN64 - host_x86_MOV32_REG_IMM(block, REG_ECX, uop->imm_data); -#else - host_x86_MOV32_REG_IMM(block, REG_EDI, uop->imm_data); -#endif - return 0; -} -static int codegen_LOAD_FUNC_ARG1_IMM(codeblock_t *block, uop_t *uop) -{ -#if _WIN64 - host_x86_MOV32_REG_IMM(block, REG_EDX, uop->imm_data); -#else - host_x86_MOV32_REG_IMM(block, REG_ESI, uop->imm_data); -#endif - return 0; -} -static int codegen_LOAD_FUNC_ARG2_IMM(codeblock_t *block, uop_t *uop) -{ -#ifdef RECOMPILER_DEBUG - fatal("codegen_LOAD_FUNC_ARG2_IMM\n"); -#endif - return 0; -} -static int codegen_LOAD_FUNC_ARG3_IMM(codeblock_t *block, uop_t *uop) -{ -#ifdef RECOMPILER_DEBUG - fatal("codegen_LOAD_FUNC_ARG3_IMM\n"); -#endif - return 0; -} - -static int codegen_LOAD_SEG(codeblock_t *block, uop_t *uop) -{ - int src_reg = HOST_REG_GET(uop->src_reg_a_real); - -#ifdef RECOMPILER_DEBUG - int src_size = IREG_GET_SIZE(uop->src_reg_a_real); - if (!REG_IS_W(src_size)) - fatal("LOAD_SEG %02x %p\n", uop->src_reg_a_real, uop->p); -#endif -#if _WIN64 - host_x86_MOV16_REG_REG(block, REG_CX, src_reg); - host_x86_MOV64_REG_IMM(block, REG_EDX, (uint64_t)uop->p); -#else - host_x86_MOV16_REG_REG(block, REG_DI, src_reg); - host_x86_MOV64_REG_IMM(block, REG_ESI, (uint64_t)uop->p); -#endif - host_x86_CALL(block, (void *)loadseg); - host_x86_TEST32_REG(block, REG_EAX, REG_EAX); - host_x86_JNZ(block, codegen_exit_rout); - - return 0; -} - -static int codegen_MEM_LOAD_ABS(codeblock_t *block, uop_t *uop) -{ - int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), seg_reg = HOST_REG_GET(uop->src_reg_a_real); - int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real); - - host_x86_LEA_REG_IMM(block, REG_ESI, seg_reg, uop->imm_data); - if (REG_IS_B(dest_size)) - { - host_x86_CALL(block, codegen_mem_load_byte); - } - else if (REG_IS_W(dest_size)) - { - host_x86_CALL(block, codegen_mem_load_word); - } - else if (REG_IS_L(dest_size)) - { - host_x86_CALL(block, codegen_mem_load_long); - } -#ifdef RECOMPILER_DEBUG - else - fatal("MEM_LOAD_ABS - %02x\n", uop->dest_reg_a_real); -#endif - host_x86_TEST32_REG(block, REG_ESI, REG_ESI); - host_x86_JNZ(block, codegen_exit_rout); - if (REG_IS_B(dest_size)) - { - host_x86_MOV8_REG_REG(block, dest_reg, REG_ECX); - } - else if (REG_IS_W(dest_size)) - { - host_x86_MOV16_REG_REG(block, dest_reg, REG_ECX); - } - else if (REG_IS_L(dest_size)) - { - host_x86_MOV32_REG_REG(block, dest_reg, REG_ECX); - } - - return 0; -} -static int codegen_MEM_LOAD_REG(codeblock_t *block, uop_t *uop) -{ - int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), seg_reg = HOST_REG_GET(uop->src_reg_a_real), addr_reg = HOST_REG_GET(uop->src_reg_b_real); - int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real); - - host_x86_LEA_REG_REG(block, REG_ESI, seg_reg, addr_reg); - if (uop->imm_data) - host_x86_ADD32_REG_IMM(block, REG_ESI, uop->imm_data); - if (REG_IS_B(dest_size)) - { - host_x86_CALL(block, codegen_mem_load_byte); - } - else if (REG_IS_W(dest_size)) - { - host_x86_CALL(block, codegen_mem_load_word); - } - else if (REG_IS_L(dest_size)) - { - host_x86_CALL(block, codegen_mem_load_long); - } - else if (REG_IS_Q(dest_size)) - { - host_x86_CALL(block, codegen_mem_load_quad); - } -#ifdef RECOMPILER_DEBUG - else - fatal("MEM_LOAD_REG - %02x\n", uop->dest_reg_a_real); -#endif - host_x86_TEST32_REG(block, REG_ESI, REG_ESI); - host_x86_JNZ(block, codegen_exit_rout); - if (REG_IS_B(dest_size)) - { - host_x86_MOV8_REG_REG(block, dest_reg, REG_ECX); - } - else if (REG_IS_W(dest_size)) - { - host_x86_MOV16_REG_REG(block, dest_reg, REG_ECX); - } - else if (REG_IS_L(dest_size)) - { - host_x86_MOV32_REG_REG(block, dest_reg, REG_ECX); - } - else if (REG_IS_Q(dest_size)) - { - host_x86_MOVQ_XREG_XREG(block, dest_reg, REG_XMM_TEMP); - } - - return 0; -} -static int codegen_MEM_LOAD_SINGLE(codeblock_t *block, uop_t *uop) -{ - int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), seg_reg = HOST_REG_GET(uop->src_reg_a_real), addr_reg = HOST_REG_GET(uop->src_reg_b_real); - -#ifdef RECOMPILER_DEBUG - int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real); - if (!REG_IS_D(dest_size)) - fatal("MEM_LOAD_SINGLE - %02x\n", uop->dest_reg_a_real); -#endif - host_x86_LEA_REG_REG(block, REG_ESI, seg_reg, addr_reg); - if (uop->imm_data) - host_x86_ADD32_REG_IMM(block, REG_ESI, uop->imm_data); - host_x86_CALL(block, codegen_mem_load_single); - host_x86_TEST32_REG(block, REG_ESI, REG_ESI); - host_x86_JNZ(block, codegen_exit_rout); + if (REG_IS_D(dest_size) && REG_IS_D(src_size_a) && REG_IS_D(src_size_b) && dest_reg == src_reg_a) { + host_x86_DIVSD_XREG_XREG(block, dest_reg, src_reg_b); + } else if (REG_IS_D(dest_size) && REG_IS_D(src_size_a) && REG_IS_D(src_size_b)) { + host_x86_MOVQ_XREG_XREG(block, REG_XMM_TEMP, src_reg_a); + host_x86_DIVSD_XREG_XREG(block, REG_XMM_TEMP, src_reg_b); host_x86_MOVQ_XREG_XREG(block, dest_reg, REG_XMM_TEMP); - - return 0; + } +# ifdef RECOMPILER_DEBUG + else + fatal("codegen_FDIV %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real); +# endif + return 0; } -static int codegen_MEM_LOAD_DOUBLE(codeblock_t *block, uop_t *uop) +static int +codegen_FMUL(codeblock_t *block, uop_t *uop) { - int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), seg_reg = HOST_REG_GET(uop->src_reg_a_real), addr_reg = HOST_REG_GET(uop->src_reg_b_real); + int dest_reg = HOST_REG_GET(uop->dest_reg_a_real); + int src_reg_a = HOST_REG_GET(uop->src_reg_a_real); + int src_reg_b = HOST_REG_GET(uop->src_reg_b_real); + int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real); + int src_size_a = IREG_GET_SIZE(uop->src_reg_a_real); + int src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); -#ifdef RECOMPILER_DEBUG - int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real); - if (!REG_IS_D(dest_size)) - fatal("MEM_LOAD_DOUBLE - %02x\n", uop->dest_reg_a_real); -#endif - host_x86_LEA_REG_REG(block, REG_ESI, seg_reg, addr_reg); - if (uop->imm_data) - host_x86_ADD32_REG_IMM(block, REG_ESI, uop->imm_data); - host_x86_CALL(block, codegen_mem_load_double); - host_x86_TEST32_REG(block, REG_ESI, REG_ESI); - host_x86_JNZ(block, codegen_exit_rout); + if (REG_IS_D(dest_size) && REG_IS_D(src_size_a) && REG_IS_D(src_size_b) && dest_reg == src_reg_a) { + host_x86_MULSD_XREG_XREG(block, dest_reg, src_reg_b); + } +# ifdef RECOMPILER_DEBUG + else + fatal("codegen_FMUL %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real); +# endif + return 0; +} +static int +codegen_FSUB(codeblock_t *block, uop_t *uop) +{ + int dest_reg = HOST_REG_GET(uop->dest_reg_a_real); + int src_reg_a = HOST_REG_GET(uop->src_reg_a_real); + int src_reg_b = HOST_REG_GET(uop->src_reg_b_real); + int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real); + int src_size_a = IREG_GET_SIZE(uop->src_reg_a_real); + int src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); + + if (REG_IS_D(dest_size) && REG_IS_D(src_size_a) && REG_IS_D(src_size_b) && dest_reg == src_reg_a) { + host_x86_SUBSD_XREG_XREG(block, dest_reg, src_reg_b); + } else if (REG_IS_D(dest_size) && REG_IS_D(src_size_a) && REG_IS_D(src_size_b)) { + host_x86_MOVQ_XREG_XREG(block, REG_XMM_TEMP, src_reg_a); + host_x86_SUBSD_XREG_XREG(block, REG_XMM_TEMP, src_reg_b); host_x86_MOVQ_XREG_XREG(block, dest_reg, REG_XMM_TEMP); - - return 0; + } +# ifdef RECOMPILER_DEBUG + else + fatal("codegen_FSUB %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real); +# endif + return 0; } -static int codegen_MEM_STORE_ABS(codeblock_t *block, uop_t *uop) +static int +codegen_FP_ENTER(codeblock_t *block, uop_t *uop) { - int seg_reg = HOST_REG_GET(uop->src_reg_a_real), src_reg = HOST_REG_GET(uop->src_reg_b_real); - int src_size = IREG_GET_SIZE(uop->src_reg_b_real); + uint32_t *branch_offset; - host_x86_LEA_REG_IMM(block, REG_ESI, seg_reg, uop->imm_data); - if (REG_IS_B(src_size)) - { - host_x86_MOV8_REG_REG(block, REG_ECX, src_reg); - host_x86_CALL(block, codegen_mem_store_byte); - } - else if (REG_IS_W(src_size)) - { - host_x86_MOV16_REG_REG(block, REG_ECX, src_reg); - host_x86_CALL(block, codegen_mem_store_word); - } - else if (REG_IS_L(src_size)) - { - host_x86_MOV32_REG_REG(block, REG_ECX, src_reg); - host_x86_CALL(block, codegen_mem_store_long); - } -#ifdef RECOMPILER_DEBUG - else - fatal("MEM_STORE_ABS - %02x\n", uop->src_reg_b_real); -#endif - host_x86_TEST32_REG(block, REG_ESI, REG_ESI); - host_x86_JNZ(block, codegen_exit_rout); + host_x86_MOV32_REG_ABS(block, REG_ECX, &cr0); + host_x86_TEST32_REG_IMM(block, REG_ECX, 0xc); + branch_offset = host_x86_JZ_long(block); + host_x86_MOV32_ABS_IMM(block, &cpu_state.oldpc, uop->imm_data); +# if _WIN64 + host_x86_MOV32_REG_IMM(block, REG_ECX, 7); +# else + host_x86_MOV32_REG_IMM(block, REG_EDI, 7); +# endif + host_x86_CALL(block, x86_int); + host_x86_JMP(block, codegen_exit_rout); + *branch_offset = (uint32_t) ((uintptr_t) &block_write_data[block_pos] - (uintptr_t) branch_offset) - 4; - return 0; + return 0; +} +static int +codegen_MMX_ENTER(codeblock_t *block, uop_t *uop) +{ + uint32_t *branch_offset; + + host_x86_MOV32_REG_ABS(block, REG_ECX, &cr0); + host_x86_TEST32_REG_IMM(block, REG_ECX, 0xc); + branch_offset = host_x86_JZ_long(block); + host_x86_MOV32_ABS_IMM(block, &cpu_state.oldpc, uop->imm_data); +# if _WIN64 + host_x86_MOV32_REG_IMM(block, REG_ECX, 7); +# else + host_x86_MOV32_REG_IMM(block, REG_EDI, 7); +# endif + host_x86_CALL(block, x86_int); + host_x86_JMP(block, codegen_exit_rout); + *branch_offset = (uint32_t) ((uintptr_t) &block_write_data[block_pos] - (uintptr_t) branch_offset) - 4; + host_x86_MOV32_ABS_IMM(block, &cpu_state.tag[0], 0x01010101); + host_x86_MOV32_ABS_IMM(block, &cpu_state.tag[4], 0x01010101); + host_x86_MOV32_ABS_IMM(block, &cpu_state.TOP, 0); + host_x86_MOV8_ABS_IMM(block, &cpu_state.ismmx, 1); + + return 0; } -static int codegen_MEM_STORE_IMM_8(codeblock_t *block, uop_t *uop) +static int +codegen_JMP(codeblock_t *block, uop_t *uop) { - int seg_reg = HOST_REG_GET(uop->src_reg_a_real), addr_reg = HOST_REG_GET(uop->src_reg_b_real); + host_x86_JMP(block, uop->p); - host_x86_LEA_REG_REG(block, REG_ESI, seg_reg, addr_reg); - host_x86_MOV8_REG_IMM(block, REG_ECX, uop->imm_data); + return 0; +} + +static int +codegen_LOAD_FUNC_ARG0(codeblock_t *block, uop_t *uop) +{ + int src_reg = HOST_REG_GET(uop->src_reg_a_real); + int src_size = IREG_GET_SIZE(uop->src_reg_a_real); + + if (REG_IS_W(src_size)) { +# if _WIN64 + host_x86_MOVZX_REG_32_16(block, REG_ECX, src_reg); +# else + host_x86_MOVZX_REG_32_16(block, REG_EDI, src_reg); +# endif + } +# ifdef RECOMPILER_DEBUG + else + fatal("codegen_LOAD_FUNC_ARG0 %02x\n", uop->src_reg_a_real); +# endif + return 0; +} +static int +codegen_LOAD_FUNC_ARG1(UNUSED(codeblock_t *block), UNUSED(uop_t *uop)) +{ +# ifdef RECOMPILER_DEBUG + fatal("codegen_LOAD_FUNC_ARG1 %02x\n", uop->src_reg_a_real); +# endif + return 0; +} +static int +codegen_LOAD_FUNC_ARG2(UNUSED(codeblock_t *block), UNUSED(uop_t *uop)) +{ +# ifdef RECOMPILER_DEBUG + fatal("codegen_LOAD_FUNC_ARG2 %02x\n", uop->src_reg_a_real); +# endif + return 0; +} +static int +codegen_LOAD_FUNC_ARG3(UNUSED(codeblock_t *block), UNUSED(uop_t *uop)) +{ +# ifdef RECOMPILER_DEBUG + fatal("codegen_LOAD_FUNC_ARG3 %02x\n", uop->src_reg_a_real); +# endif + return 0; +} + +static int +codegen_LOAD_FUNC_ARG0_IMM(codeblock_t *block, uop_t *uop) +{ +# if _WIN64 + host_x86_MOV32_REG_IMM(block, REG_ECX, uop->imm_data); +# else + host_x86_MOV32_REG_IMM(block, REG_EDI, uop->imm_data); +# endif + return 0; +} +static int +codegen_LOAD_FUNC_ARG1_IMM(codeblock_t *block, uop_t *uop) +{ +# if _WIN64 + host_x86_MOV32_REG_IMM(block, REG_EDX, uop->imm_data); +# else + host_x86_MOV32_REG_IMM(block, REG_ESI, uop->imm_data); +# endif + return 0; +} +static int +codegen_LOAD_FUNC_ARG2_IMM(UNUSED(codeblock_t *block), UNUSED(uop_t *uop)) +{ +# ifdef RECOMPILER_DEBUG + fatal("codegen_LOAD_FUNC_ARG2_IMM\n"); +# endif + return 0; +} +static int +codegen_LOAD_FUNC_ARG3_IMM(UNUSED(codeblock_t *block), UNUSED(uop_t *uop)) +{ +# ifdef RECOMPILER_DEBUG + fatal("codegen_LOAD_FUNC_ARG3_IMM\n"); +# endif + return 0; +} + +static int +codegen_LOAD_SEG(codeblock_t *block, uop_t *uop) +{ + int src_reg = HOST_REG_GET(uop->src_reg_a_real); + +# ifdef RECOMPILER_DEBUG + int src_size = IREG_GET_SIZE(uop->src_reg_a_real); + if (!REG_IS_W(src_size)) + fatal("LOAD_SEG %02x %p\n", uop->src_reg_a_real, uop->p); +# endif +# if _WIN64 + host_x86_MOV16_REG_REG(block, REG_CX, src_reg); + host_x86_MOV64_REG_IMM(block, REG_EDX, (uint64_t) uop->p); +# else + host_x86_MOV16_REG_REG(block, REG_DI, src_reg); + host_x86_MOV64_REG_IMM(block, REG_ESI, (uint64_t) uop->p); +# endif + host_x86_CALL(block, (void *) loadseg); + host_x86_TEST32_REG(block, REG_EAX, REG_EAX); + host_x86_JNZ(block, codegen_exit_rout); + + return 0; +} + +static int +codegen_MEM_LOAD_ABS(codeblock_t *block, uop_t *uop) +{ + int dest_reg = HOST_REG_GET(uop->dest_reg_a_real); + int seg_reg = HOST_REG_GET(uop->src_reg_a_real); + int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real); + + host_x86_LEA_REG_IMM(block, REG_ESI, seg_reg, uop->imm_data); + if (REG_IS_B(dest_size)) { + host_x86_CALL(block, codegen_mem_load_byte); + } else if (REG_IS_W(dest_size)) { + host_x86_CALL(block, codegen_mem_load_word); + } else if (REG_IS_L(dest_size)) { + host_x86_CALL(block, codegen_mem_load_long); + } +# ifdef RECOMPILER_DEBUG + else + fatal("MEM_LOAD_ABS - %02x\n", uop->dest_reg_a_real); +# endif + host_x86_TEST32_REG(block, REG_ESI, REG_ESI); + host_x86_JNZ(block, codegen_exit_rout); + if (REG_IS_B(dest_size)) { + host_x86_MOV8_REG_REG(block, dest_reg, REG_ECX); + } else if (REG_IS_W(dest_size)) { + host_x86_MOV16_REG_REG(block, dest_reg, REG_ECX); + } else if (REG_IS_L(dest_size)) { + host_x86_MOV32_REG_REG(block, dest_reg, REG_ECX); + } + + return 0; +} +static int +codegen_MEM_LOAD_REG(codeblock_t *block, uop_t *uop) +{ + int dest_reg = HOST_REG_GET(uop->dest_reg_a_real); + int seg_reg = HOST_REG_GET(uop->src_reg_a_real); + int addr_reg = HOST_REG_GET(uop->src_reg_b_real); + int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real); + + host_x86_LEA_REG_REG(block, REG_ESI, seg_reg, addr_reg); + if (uop->imm_data) + host_x86_ADD32_REG_IMM(block, REG_ESI, uop->imm_data); + if (REG_IS_B(dest_size)) { + host_x86_CALL(block, codegen_mem_load_byte); + } else if (REG_IS_W(dest_size)) { + host_x86_CALL(block, codegen_mem_load_word); + } else if (REG_IS_L(dest_size)) { + host_x86_CALL(block, codegen_mem_load_long); + } else if (REG_IS_Q(dest_size)) { + host_x86_CALL(block, codegen_mem_load_quad); + } +# ifdef RECOMPILER_DEBUG + else + fatal("MEM_LOAD_REG - %02x\n", uop->dest_reg_a_real); +# endif + host_x86_TEST32_REG(block, REG_ESI, REG_ESI); + host_x86_JNZ(block, codegen_exit_rout); + if (REG_IS_B(dest_size)) { + host_x86_MOV8_REG_REG(block, dest_reg, REG_ECX); + } else if (REG_IS_W(dest_size)) { + host_x86_MOV16_REG_REG(block, dest_reg, REG_ECX); + } else if (REG_IS_L(dest_size)) { + host_x86_MOV32_REG_REG(block, dest_reg, REG_ECX); + } else if (REG_IS_Q(dest_size)) { + host_x86_MOVQ_XREG_XREG(block, dest_reg, REG_XMM_TEMP); + } + + return 0; +} +static int +codegen_MEM_LOAD_SINGLE(codeblock_t *block, uop_t *uop) +{ + int dest_reg = HOST_REG_GET(uop->dest_reg_a_real); + int seg_reg = HOST_REG_GET(uop->src_reg_a_real); + int addr_reg = HOST_REG_GET(uop->src_reg_b_real); + +# ifdef RECOMPILER_DEBUG + int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real); + if (!REG_IS_D(dest_size)) + fatal("MEM_LOAD_SINGLE - %02x\n", uop->dest_reg_a_real); +# endif + host_x86_LEA_REG_REG(block, REG_ESI, seg_reg, addr_reg); + if (uop->imm_data) + host_x86_ADD32_REG_IMM(block, REG_ESI, uop->imm_data); + host_x86_CALL(block, codegen_mem_load_single); + host_x86_TEST32_REG(block, REG_ESI, REG_ESI); + host_x86_JNZ(block, codegen_exit_rout); + host_x86_MOVQ_XREG_XREG(block, dest_reg, REG_XMM_TEMP); + + return 0; +} +static int +codegen_MEM_LOAD_DOUBLE(codeblock_t *block, uop_t *uop) +{ + int dest_reg = HOST_REG_GET(uop->dest_reg_a_real); + int seg_reg = HOST_REG_GET(uop->src_reg_a_real); + int addr_reg = HOST_REG_GET(uop->src_reg_b_real); + +# ifdef RECOMPILER_DEBUG + int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real); + if (!REG_IS_D(dest_size)) + fatal("MEM_LOAD_DOUBLE - %02x\n", uop->dest_reg_a_real); +# endif + host_x86_LEA_REG_REG(block, REG_ESI, seg_reg, addr_reg); + if (uop->imm_data) + host_x86_ADD32_REG_IMM(block, REG_ESI, uop->imm_data); + host_x86_CALL(block, codegen_mem_load_double); + host_x86_TEST32_REG(block, REG_ESI, REG_ESI); + host_x86_JNZ(block, codegen_exit_rout); + host_x86_MOVQ_XREG_XREG(block, dest_reg, REG_XMM_TEMP); + + return 0; +} + +static int +codegen_MEM_STORE_ABS(codeblock_t *block, uop_t *uop) +{ + int seg_reg = HOST_REG_GET(uop->src_reg_a_real); + int src_reg = HOST_REG_GET(uop->src_reg_b_real); + int src_size = IREG_GET_SIZE(uop->src_reg_b_real); + + host_x86_LEA_REG_IMM(block, REG_ESI, seg_reg, uop->imm_data); + if (REG_IS_B(src_size)) { + host_x86_MOV8_REG_REG(block, REG_ECX, src_reg); host_x86_CALL(block, codegen_mem_store_byte); - host_x86_TEST32_REG(block, REG_ESI, REG_ESI); - host_x86_JNZ(block, codegen_exit_rout); - - return 0; -} -static int codegen_MEM_STORE_IMM_16(codeblock_t *block, uop_t *uop) -{ - int seg_reg = HOST_REG_GET(uop->src_reg_a_real), addr_reg = HOST_REG_GET(uop->src_reg_b_real); - - host_x86_LEA_REG_REG(block, REG_ESI, seg_reg, addr_reg); - host_x86_MOV16_REG_IMM(block, REG_ECX, uop->imm_data); + } else if (REG_IS_W(src_size)) { + host_x86_MOV16_REG_REG(block, REG_ECX, src_reg); host_x86_CALL(block, codegen_mem_store_word); - host_x86_TEST32_REG(block, REG_ESI, REG_ESI); - host_x86_JNZ(block, codegen_exit_rout); - - return 0; -} -static int codegen_MEM_STORE_IMM_32(codeblock_t *block, uop_t *uop) -{ - int seg_reg = HOST_REG_GET(uop->src_reg_a_real), addr_reg = HOST_REG_GET(uop->src_reg_b_real); - - host_x86_LEA_REG_REG(block, REG_ESI, seg_reg, addr_reg); - host_x86_MOV32_REG_IMM(block, REG_ECX, uop->imm_data); + } else if (REG_IS_L(src_size)) { + host_x86_MOV32_REG_REG(block, REG_ECX, src_reg); host_x86_CALL(block, codegen_mem_store_long); - host_x86_TEST32_REG(block, REG_ESI, REG_ESI); - host_x86_JNZ(block, codegen_exit_rout); + } +# ifdef RECOMPILER_DEBUG + else + fatal("MEM_STORE_ABS - %02x\n", uop->src_reg_b_real); +# endif + host_x86_TEST32_REG(block, REG_ESI, REG_ESI); + host_x86_JNZ(block, codegen_exit_rout); - return 0; + return 0; } -static int codegen_MEM_STORE_REG(codeblock_t *block, uop_t *uop) +static int +codegen_MEM_STORE_IMM_8(codeblock_t *block, uop_t *uop) { - int seg_reg = HOST_REG_GET(uop->src_reg_a_real), addr_reg = HOST_REG_GET(uop->src_reg_b_real), src_reg = HOST_REG_GET(uop->src_reg_c_real); - int src_size = IREG_GET_SIZE(uop->src_reg_c_real); + int seg_reg = HOST_REG_GET(uop->src_reg_a_real); + int addr_reg = HOST_REG_GET(uop->src_reg_b_real); - host_x86_LEA_REG_REG(block, REG_ESI, seg_reg, addr_reg); - if (uop->imm_data) - host_x86_ADD32_REG_IMM(block, REG_ESI, uop->imm_data); - if (REG_IS_B(src_size)) - { - host_x86_MOV8_REG_REG(block, REG_ECX, src_reg); - host_x86_CALL(block, codegen_mem_store_byte); - } - else if (REG_IS_W(src_size)) - { - host_x86_MOV16_REG_REG(block, REG_ECX, src_reg); - host_x86_CALL(block, codegen_mem_store_word); - } - else if (REG_IS_L(src_size)) - { - host_x86_MOV32_REG_REG(block, REG_ECX, src_reg); - host_x86_CALL(block, codegen_mem_store_long); - } - else if (REG_IS_Q(src_size)) - { - host_x86_MOVQ_XREG_XREG(block, REG_XMM_TEMP, src_reg); - host_x86_CALL(block, codegen_mem_store_quad); - } -#ifdef RECOMPILER_DEBUG - else - fatal("MEM_STORE_REG - %02x\n", uop->src_reg_b_real); -#endif - host_x86_TEST32_REG(block, REG_ESI, REG_ESI); - host_x86_JNZ(block, codegen_exit_rout); + host_x86_LEA_REG_REG(block, REG_ESI, seg_reg, addr_reg); + host_x86_MOV8_REG_IMM(block, REG_ECX, uop->imm_data); + host_x86_CALL(block, codegen_mem_store_byte); + host_x86_TEST32_REG(block, REG_ESI, REG_ESI); + host_x86_JNZ(block, codegen_exit_rout); - return 0; + return 0; +} +static int +codegen_MEM_STORE_IMM_16(codeblock_t *block, uop_t *uop) +{ + int seg_reg = HOST_REG_GET(uop->src_reg_a_real); + int addr_reg = HOST_REG_GET(uop->src_reg_b_real); + + host_x86_LEA_REG_REG(block, REG_ESI, seg_reg, addr_reg); + host_x86_MOV16_REG_IMM(block, REG_ECX, uop->imm_data); + host_x86_CALL(block, codegen_mem_store_word); + host_x86_TEST32_REG(block, REG_ESI, REG_ESI); + host_x86_JNZ(block, codegen_exit_rout); + + return 0; +} +static int +codegen_MEM_STORE_IMM_32(codeblock_t *block, uop_t *uop) +{ + int seg_reg = HOST_REG_GET(uop->src_reg_a_real); + int addr_reg = HOST_REG_GET(uop->src_reg_b_real); + + host_x86_LEA_REG_REG(block, REG_ESI, seg_reg, addr_reg); + host_x86_MOV32_REG_IMM(block, REG_ECX, uop->imm_data); + host_x86_CALL(block, codegen_mem_store_long); + host_x86_TEST32_REG(block, REG_ESI, REG_ESI); + host_x86_JNZ(block, codegen_exit_rout); + + return 0; } -static int codegen_MEM_STORE_SINGLE(codeblock_t *block, uop_t *uop) +static int +codegen_MEM_STORE_REG(codeblock_t *block, uop_t *uop) { - int seg_reg = HOST_REG_GET(uop->src_reg_a_real), addr_reg = HOST_REG_GET(uop->src_reg_b_real), src_reg = HOST_REG_GET(uop->src_reg_c_real); + int seg_reg = HOST_REG_GET(uop->src_reg_a_real); + int addr_reg = HOST_REG_GET(uop->src_reg_b_real); + int src_reg = HOST_REG_GET(uop->src_reg_c_real); + int src_size = IREG_GET_SIZE(uop->src_reg_c_real); -#ifdef RECOMPILER_DEBUG - int src_size = IREG_GET_SIZE(uop->src_reg_c_real); - if (!REG_IS_D(src_size)) - fatal("MEM_STORE_SINGLE - %02x\n", uop->src_reg_b_real); -#endif - host_x86_LEA_REG_REG(block, REG_ESI, seg_reg, addr_reg); - if (uop->imm_data) - host_x86_ADD32_REG_IMM(block, REG_ESI, uop->imm_data); - host_x86_CVTSD2SS_XREG_XREG(block, REG_XMM_TEMP, src_reg); - host_x86_CALL(block, codegen_mem_store_single); - host_x86_TEST32_REG(block, REG_ESI, REG_ESI); - host_x86_JNZ(block, codegen_exit_rout); - - return 0; -} -static int codegen_MEM_STORE_DOUBLE(codeblock_t *block, uop_t *uop) -{ - int seg_reg = HOST_REG_GET(uop->src_reg_a_real), addr_reg = HOST_REG_GET(uop->src_reg_b_real), src_reg = HOST_REG_GET(uop->src_reg_c_real); - -#ifdef RECOMPILER_DEBUG - int src_size = IREG_GET_SIZE(uop->src_reg_c_real); - if (!REG_IS_D(src_size)) - fatal("MEM_STORE_DOUBLE - %02x\n", uop->src_reg_b_real); -#endif - host_x86_LEA_REG_REG(block, REG_ESI, seg_reg, addr_reg); - if (uop->imm_data) - host_x86_ADD32_REG_IMM(block, REG_ESI, uop->imm_data); + host_x86_LEA_REG_REG(block, REG_ESI, seg_reg, addr_reg); + if (uop->imm_data) + host_x86_ADD32_REG_IMM(block, REG_ESI, uop->imm_data); + if (REG_IS_B(src_size)) { + host_x86_MOV8_REG_REG(block, REG_ECX, src_reg); + host_x86_CALL(block, codegen_mem_store_byte); + } else if (REG_IS_W(src_size)) { + host_x86_MOV16_REG_REG(block, REG_ECX, src_reg); + host_x86_CALL(block, codegen_mem_store_word); + } else if (REG_IS_L(src_size)) { + host_x86_MOV32_REG_REG(block, REG_ECX, src_reg); + host_x86_CALL(block, codegen_mem_store_long); + } else if (REG_IS_Q(src_size)) { host_x86_MOVQ_XREG_XREG(block, REG_XMM_TEMP, src_reg); - host_x86_CALL(block, codegen_mem_store_double); - host_x86_TEST32_REG(block, REG_ESI, REG_ESI); - host_x86_JNZ(block, codegen_exit_rout); - - return 0; -} - -static int codegen_MOV(codeblock_t *block, uop_t *uop) -{ - int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg = HOST_REG_GET(uop->src_reg_a_real); - int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size = IREG_GET_SIZE(uop->src_reg_a_real); - - if (REG_IS_L(dest_size) && REG_IS_L(src_size)) - { - host_x86_MOV32_REG_REG(block, dest_reg, src_reg); - } - else if (REG_IS_W(dest_size) && REG_IS_W(src_size)) - { - host_x86_MOV16_REG_REG(block, dest_reg, src_reg); - } - else if (REG_IS_B(dest_size) && REG_IS_B(src_size)) - { - host_x86_MOV8_REG_REG(block, dest_reg, src_reg); - } - else if (REG_IS_D(dest_size) && REG_IS_D(src_size)) - { - host_x86_MOVQ_XREG_XREG(block, dest_reg, src_reg); - } - else if (REG_IS_Q(dest_size) && REG_IS_Q(src_size)) - { - host_x86_MOVQ_XREG_XREG(block, dest_reg, src_reg); - } -#ifdef RECOMPILER_DEBUG - else - fatal("MOV %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real); -#endif - return 0; -} -static int codegen_MOV_IMM(codeblock_t *block, uop_t *uop) -{ - int dest_reg = HOST_REG_GET(uop->dest_reg_a_real); - int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real); - - if (REG_IS_L(dest_size)) - { - host_x86_MOV32_REG_IMM(block, dest_reg, uop->imm_data); - } - else if (REG_IS_W(dest_size)) - { - host_x86_MOV16_REG_IMM(block, dest_reg, uop->imm_data); - } - else if (REG_IS_B(dest_size)) - { - host_x86_MOV8_REG_IMM(block, dest_reg, uop->imm_data); - } -#ifdef RECOMPILER_DEBUG - else - fatal("MOV_IMM %02x\n", uop->dest_reg_a_real); -#endif - return 0; -} -static int codegen_MOV_PTR(codeblock_t *block, uop_t *uop) -{ - host_x86_MOV64_REG_IMM(block, uop->dest_reg_a_real, (uint64_t)uop->p); - return 0; -} -static int codegen_MOV_REG_PTR(codeblock_t *block, uop_t *uop) -{ - int dest_reg = HOST_REG_GET(uop->dest_reg_a_real); - int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real); - - if (REG_IS_L(dest_size)) - { - host_x86_MOV32_REG_ABS(block, dest_reg, uop->p); - } - else - fatal("MOV_REG_PTR %02x\n", uop->dest_reg_a_real); - - return 0; -} -static int codegen_MOVZX_REG_PTR_8(codeblock_t *block, uop_t *uop) -{ - int dest_reg = HOST_REG_GET(uop->dest_reg_a_real); - int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real); - - if (REG_IS_L(dest_size)) - { - host_x86_MOVZX_REG_ABS_32_8(block, dest_reg, uop->p); - } - else if (REG_IS_W(dest_size)) - { - host_x86_MOVZX_REG_ABS_16_8(block, dest_reg, uop->p); - } - else if (REG_IS_B(dest_size)) - { - host_x86_MOV8_REG_ABS(block, dest_reg, uop->p); - } - else - fatal("MOVZX_REG_PTR_8 %02x\n", uop->dest_reg_a_real); - - return 0; -} -static int codegen_MOVZX_REG_PTR_16(codeblock_t *block, uop_t *uop) -{ - int dest_reg = HOST_REG_GET(uop->dest_reg_a_real); - int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real); - - if (REG_IS_L(dest_size)) - { - host_x86_MOVZX_REG_ABS_32_16(block, dest_reg, uop->p); - } - else if (REG_IS_W(dest_size)) - { - host_x86_MOV16_REG_ABS(block, dest_reg, uop->p); - } - else - fatal("MOVZX_REG_PTR_16 %02x\n", uop->dest_reg_a_real); - - return 0; -} -static int codegen_MOVSX(codeblock_t *block, uop_t *uop) -{ - int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg = HOST_REG_GET(uop->src_reg_a_real); - int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size = IREG_GET_SIZE(uop->src_reg_a_real); - - if (REG_IS_L(dest_size) && REG_IS_W(src_size)) - { - host_x86_MOVSX_REG_32_16(block, dest_reg, src_reg); - } - else if (REG_IS_L(dest_size) && REG_IS_B(src_size)) - { - host_x86_MOVSX_REG_32_8(block, dest_reg, src_reg); - } - else if (REG_IS_W(dest_size) && REG_IS_B(src_size)) - { - host_x86_MOVSX_REG_16_8(block, dest_reg, src_reg); - } -#ifdef RECOMPILER_DEBUG - else - fatal("MOVSX %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real); -#endif - return 0; -} -static int codegen_MOVZX(codeblock_t *block, uop_t *uop) -{ - int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg = HOST_REG_GET(uop->src_reg_a_real); - int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size = IREG_GET_SIZE(uop->src_reg_a_real); - - if (REG_IS_Q(dest_size) && REG_IS_L(src_size)) - { - host_x86_MOVD_XREG_REG(block, dest_reg, src_reg); - } - else if (REG_IS_L(dest_size) && REG_IS_Q(src_size)) - { - host_x86_MOVD_REG_XREG(block, dest_reg, src_reg); - } - else if (REG_IS_L(dest_size) && REG_IS_W(src_size)) - { - host_x86_MOVZX_REG_32_16(block, dest_reg, src_reg); - } - else if (REG_IS_L(dest_size) && REG_IS_B(src_size)) - { - host_x86_MOVZX_REG_32_8(block, dest_reg, src_reg); - } - else if (REG_IS_W(dest_size) && REG_IS_B(src_size)) - { - host_x86_MOVZX_REG_16_8(block, dest_reg, src_reg); - } -#ifdef RECOMPILER_DEBUG - else - fatal("MOVZX %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real); -#endif - return 0; -} - -static int codegen_MOV_DOUBLE_INT(codeblock_t *block, uop_t *uop) -{ - int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg = HOST_REG_GET(uop->src_reg_a_real); - int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size = IREG_GET_SIZE(uop->src_reg_a_real); - - if (REG_IS_D(dest_size) && REG_IS_L(src_size)) - { - host_x86_CVTSI2SD_XREG_REG(block, dest_reg, src_reg); - } - else if (REG_IS_D(dest_size) && REG_IS_W(src_size)) - { - host_x86_MOVSX_REG_32_16(block, REG_ECX, src_reg); - host_x86_CVTSI2SD_XREG_REG(block, dest_reg, REG_ECX); - } - else if (REG_IS_D(dest_size) && REG_IS_Q(src_size)) - { - host_x86_MOVQ_REG_XREG(block, REG_RCX, src_reg); - host_x86_CVTSI2SD_XREG_REG64(block, dest_reg, REG_RCX); - } -#ifdef RECOMPILER_DEBUG - else - fatal("MOV_DOUBLE_INT %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real); -#endif - return 0; -} -static int codegen_MOV_INT_DOUBLE(codeblock_t *block, uop_t *uop) -{ - int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg = HOST_REG_GET(uop->src_reg_a_real); - int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size = IREG_GET_SIZE(uop->src_reg_a_real); - - if (REG_IS_L(dest_size) && REG_IS_D(src_size)) - { - host_x86_LDMXCSR(block, &cpu_state.new_fp_control); - host_x86_CVTSD2SI_REG_XREG(block, dest_reg, src_reg); - host_x86_LDMXCSR(block, &cpu_state.old_fp_control); - } - else if (REG_IS_W(dest_size) && REG_IS_D(src_size)) - { - host_x86_LDMXCSR(block, &cpu_state.new_fp_control); - host_x86_CVTSD2SI_REG_XREG(block, REG_ECX, src_reg); - host_x86_MOV16_REG_REG(block, dest_reg, REG_ECX); - host_x86_LDMXCSR(block, &cpu_state.old_fp_control); - } -#ifdef RECOMPILER_DEBUG - else - fatal("MOV_INT_DOUBLE %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real); -#endif - return 0; -} -static int codegen_MOV_INT_DOUBLE_64(codeblock_t *block, uop_t *uop) -{ - int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg = HOST_REG_GET(uop->src_reg_a_real), src_64_reg = HOST_REG_GET(uop->src_reg_b_real), tag_reg = HOST_REG_GET(uop->src_reg_c_real); - int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size = IREG_GET_SIZE(uop->src_reg_a_real), src_64_size = IREG_GET_SIZE(uop->src_reg_b_real); - - if (REG_IS_Q(dest_size) && REG_IS_D(src_size) && REG_IS_Q(src_64_size)) - { - uint32_t *branch_offset; - - /*If TAG_UINT64 is set then the source is MM[]. Otherwise it is a double in ST()*/ - host_x86_MOVQ_XREG_XREG(block, dest_reg, src_64_reg); - host_x86_TEST8_REG(block, tag_reg, tag_reg); - branch_offset = host_x86_JS_long(block); - - host_x86_LDMXCSR(block, &cpu_state.new_fp_control); - host_x86_CVTSD2SI_REG64_XREG(block, REG_RCX, src_reg); - host_x86_LDMXCSR(block, &cpu_state.old_fp_control); - host_x86_MOVQ_XREG_REG(block, dest_reg, REG_RCX); - - *branch_offset = (uint32_t)((uintptr_t)&block_write_data[block_pos] - (uintptr_t)branch_offset) - 4; - } -#ifdef RECOMPILER_DEBUG - else - fatal("MOV_INT_DOUBLE_64 %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real); -#endif - return 0; -} - -static int codegen_NOP(codeblock_t *block, uop_t *uop) -{ - return 0; -} - -static int codegen_OR(codeblock_t *block, uop_t *uop) -{ - int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg_a = HOST_REG_GET(uop->src_reg_a_real), src_reg_b = HOST_REG_GET(uop->src_reg_b_real); - int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size_a = IREG_GET_SIZE(uop->src_reg_a_real), src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); - - if (REG_IS_Q(dest_size) && REG_IS_Q(src_size_a) && REG_IS_Q(src_size_b) && uop->dest_reg_a_real == uop->src_reg_a_real) - { - host_x86_POR_XREG_XREG(block, dest_reg, src_reg_b); - } - else if (REG_IS_L(dest_size) && REG_IS_L(src_size_a) && REG_IS_L(src_size_b)) - { - if (dest_reg != src_reg_a) - host_x86_MOV32_REG_REG(block, dest_reg, src_reg_a); - host_x86_OR32_REG_REG(block, dest_reg, src_reg_b); - } - else if (REG_IS_W(dest_size) && REG_IS_W(src_size_a) && REG_IS_W(src_size_b)) - { - if (dest_reg != src_reg_a) - host_x86_MOV16_REG_REG(block, dest_reg, src_reg_a); - host_x86_OR16_REG_REG(block, dest_reg, src_reg_b); - } - else if (REG_IS_B(dest_size) && REG_IS_B(src_size_a) && REG_IS_B(src_size_b)) - { - if (dest_reg != src_reg_a) - host_x86_MOV8_REG_REG(block, dest_reg, src_reg_a); - host_x86_OR8_REG_REG(block, dest_reg, src_reg_b); - } -#ifdef RECOMPILER_DEBUG - else - fatal("OR %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real); -#endif - return 0; -} -static int codegen_OR_IMM(codeblock_t *block, uop_t *uop) -{ - int dest_reg = HOST_REG_GET(uop->dest_reg_a_real); - int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size = IREG_GET_SIZE(uop->src_reg_a_real); - - if (REG_IS_L(dest_size) && REG_IS_L(src_size)) - { - host_x86_OR32_REG_IMM(block, dest_reg, uop->imm_data); - } - else if (REG_IS_W(dest_size) && REG_IS_W(src_size)) - { - host_x86_OR16_REG_IMM(block, dest_reg, uop->imm_data); - } - else if (REG_IS_B(dest_size) && REG_IS_B(src_size)) - { - host_x86_OR8_REG_IMM(block, dest_reg, uop->imm_data); - } -#ifdef RECOMPILER_DEBUG - else - fatal("OR_IMM %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real); -#endif - return 0; -} - -static int codegen_PACKSSWB(codeblock_t *block, uop_t *uop) -{ - int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg_b = HOST_REG_GET(uop->src_reg_b_real); - int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); - - if (REG_IS_Q(dest_size) && REG_IS_Q(src_size_b) && uop->dest_reg_a_real == uop->src_reg_a_real) - { - host_x86_PACKSSWB_XREG_XREG(block, dest_reg, src_reg_b); - } -#ifdef RECOMPILER_DEBUG - else - fatal("PACKSSWB %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real); -#endif - return 0; -} -static int codegen_PACKSSDW(codeblock_t *block, uop_t *uop) -{ - int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg_b = HOST_REG_GET(uop->src_reg_b_real); - int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); - - if (REG_IS_Q(dest_size) && REG_IS_Q(src_size_b) && uop->dest_reg_a_real == uop->src_reg_a_real) - { - host_x86_PACKSSDW_XREG_XREG(block, dest_reg, src_reg_b); - } -#ifdef RECOMPILER_DEBUG - else - fatal("PACKSSDW %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real); -#endif - return 0; -} -static int codegen_PACKUSWB(codeblock_t *block, uop_t *uop) -{ - int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg_b = HOST_REG_GET(uop->src_reg_b_real); - int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); - - if (REG_IS_Q(dest_size) && REG_IS_Q(src_size_b) && uop->dest_reg_a_real == uop->src_reg_a_real) - { - host_x86_PACKUSWB_XREG_XREG(block, dest_reg, src_reg_b); - } -#ifdef RECOMPILER_DEBUG - else - fatal("PACKUSWB %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real); -#endif - return 0; -} - -static int codegen_PADDB(codeblock_t *block, uop_t *uop) -{ - int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg_b = HOST_REG_GET(uop->src_reg_b_real); - int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); - - if (REG_IS_Q(dest_size) && REG_IS_Q(src_size_b) && uop->dest_reg_a_real == uop->src_reg_a_real) - { - host_x86_PADDB_XREG_XREG(block, dest_reg, src_reg_b); - } -#ifdef RECOMPILER_DEBUG - else - fatal("PADDB %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real); -#endif - return 0; -} -static int codegen_PADDW(codeblock_t *block, uop_t *uop) -{ - int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg_b = HOST_REG_GET(uop->src_reg_b_real); - int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); - - if (REG_IS_Q(dest_size) && REG_IS_Q(src_size_b) && uop->dest_reg_a_real == uop->src_reg_a_real) - { - host_x86_PADDW_XREG_XREG(block, dest_reg, src_reg_b); - } -#ifdef RECOMPILER_DEBUG - else - fatal("PADDW %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real); -#endif - return 0; -} -static int codegen_PADDD(codeblock_t *block, uop_t *uop) -{ - int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg_b = HOST_REG_GET(uop->src_reg_b_real); - int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); - - if (REG_IS_Q(dest_size) && REG_IS_Q(src_size_b) && uop->dest_reg_a_real == uop->src_reg_a_real) - { - host_x86_PADDD_XREG_XREG(block, dest_reg, src_reg_b); - } -#ifdef RECOMPILER_DEBUG - else - fatal("PADDD %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real); -#endif - return 0; -} -static int codegen_PADDSB(codeblock_t *block, uop_t *uop) -{ - int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg_b = HOST_REG_GET(uop->src_reg_b_real); - int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); - - if (REG_IS_Q(dest_size) && REG_IS_Q(src_size_b) && uop->dest_reg_a_real == uop->src_reg_a_real) - { - host_x86_PADDSB_XREG_XREG(block, dest_reg, src_reg_b); - } -#ifdef RECOMPILER_DEBUG - else - fatal("PADDSB %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real); -#endif - return 0; -} -static int codegen_PADDSW(codeblock_t *block, uop_t *uop) -{ - int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg_b = HOST_REG_GET(uop->src_reg_b_real); - int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); - - if (REG_IS_Q(dest_size) && REG_IS_Q(src_size_b) && uop->dest_reg_a_real == uop->src_reg_a_real) - { - host_x86_PADDSW_XREG_XREG(block, dest_reg, src_reg_b); - } -#ifdef RECOMPILER_DEBUG - else - fatal("PADDSW %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real); -#endif - return 0; -} -static int codegen_PADDUSB(codeblock_t *block, uop_t *uop) -{ - int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg_b = HOST_REG_GET(uop->src_reg_b_real); - int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); - - if (REG_IS_Q(dest_size) && REG_IS_Q(src_size_b) && uop->dest_reg_a_real == uop->src_reg_a_real) - { - host_x86_PADDUSB_XREG_XREG(block, dest_reg, src_reg_b); - } -#ifdef RECOMPILER_DEBUG - else - fatal("PADDUSB %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real); -#endif - return 0; -} -static int codegen_PADDUSW(codeblock_t *block, uop_t *uop) -{ - int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg_b = HOST_REG_GET(uop->src_reg_b_real); - int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); - - if (REG_IS_Q(dest_size) && REG_IS_Q(src_size_b) && uop->dest_reg_a_real == uop->src_reg_a_real) - { - host_x86_PADDUSW_XREG_XREG(block, dest_reg, src_reg_b); - } -#ifdef RECOMPILER_DEBUG - else - fatal("PADDUSW %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real); -#endif - return 0; -} - -static int codegen_PCMPEQB(codeblock_t *block, uop_t *uop) -{ - int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg_b = HOST_REG_GET(uop->src_reg_b_real); - int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); - - if (REG_IS_Q(dest_size) && REG_IS_Q(src_size_b) && uop->dest_reg_a_real == uop->src_reg_a_real) - { - host_x86_PCMPEQB_XREG_XREG(block, dest_reg, src_reg_b); - } -#ifdef RECOMPILER_DEBUG - else - fatal("PCMPEQB %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real); -#endif - return 0; -} -static int codegen_PCMPEQW(codeblock_t *block, uop_t *uop) -{ - int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg_b = HOST_REG_GET(uop->src_reg_b_real); - int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); - - if (REG_IS_Q(dest_size) && REG_IS_Q(src_size_b) && uop->dest_reg_a_real == uop->src_reg_a_real) - { - host_x86_PCMPEQW_XREG_XREG(block, dest_reg, src_reg_b); - } -#ifdef RECOMPILER_DEBUG - else - fatal("PCMPEQW %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real); -#endif - return 0; -} -static int codegen_PCMPEQD(codeblock_t *block, uop_t *uop) -{ - int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg_b = HOST_REG_GET(uop->src_reg_b_real); - int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); - - if (REG_IS_Q(dest_size) && REG_IS_Q(src_size_b) && uop->dest_reg_a_real == uop->src_reg_a_real) - { - host_x86_PCMPEQD_XREG_XREG(block, dest_reg, src_reg_b); - } -#ifdef RECOMPILER_DEBUG - else - fatal("PCMPEQD %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real); -#endif - return 0; -} -static int codegen_PCMPGTB(codeblock_t *block, uop_t *uop) -{ - int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg_b = HOST_REG_GET(uop->src_reg_b_real); - int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); - - if (REG_IS_Q(dest_size) && REG_IS_Q(src_size_b) && uop->dest_reg_a_real == uop->src_reg_a_real) - { - host_x86_PCMPGTB_XREG_XREG(block, dest_reg, src_reg_b); - } -#ifdef RECOMPILER_DEBUG - else - fatal("PCMPGTB %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real); -#endif - return 0; -} -static int codegen_PCMPGTW(codeblock_t *block, uop_t *uop) -{ - int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg_b = HOST_REG_GET(uop->src_reg_b_real); - int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); - - if (REG_IS_Q(dest_size) && REG_IS_Q(src_size_b) && uop->dest_reg_a_real == uop->src_reg_a_real) - { - host_x86_PCMPGTW_XREG_XREG(block, dest_reg, src_reg_b); - } -#ifdef RECOMPILER_DEBUG - else - fatal("PCMPGTW %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real); -#endif - return 0; -} -static int codegen_PCMPGTD(codeblock_t *block, uop_t *uop) -{ - int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg_b = HOST_REG_GET(uop->src_reg_b_real); - int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); - - if (REG_IS_Q(dest_size) && REG_IS_Q(src_size_b) && uop->dest_reg_a_real == uop->src_reg_a_real) - { - host_x86_PCMPGTD_XREG_XREG(block, dest_reg, src_reg_b); - } -#ifdef RECOMPILER_DEBUG - else - fatal("PCMPGTD %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real); -#endif - return 0; -} - -static int codegen_PF2ID(codeblock_t *block, uop_t *uop) -{ - int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg_a = HOST_REG_GET(uop->src_reg_a_real); - int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size_a = IREG_GET_SIZE(uop->src_reg_a_real); - - if (REG_IS_Q(dest_size) && REG_IS_Q(src_size_a)) - { - host_x86_LDMXCSR(block, &cpu_state.trunc_fp_control); - host_x86_CVTPS2DQ_XREG_XREG(block, dest_reg, src_reg_a); - host_x86_LDMXCSR(block, &cpu_state.old_fp_control); - } -#ifdef RECOMPILER_DEBUG - else - fatal("PF2ID %02x %02x\n", uop->dest_reg_a_real); -#endif - return 0; -} -static int codegen_PFADD(codeblock_t *block, uop_t *uop) -{ - int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg_b = HOST_REG_GET(uop->src_reg_b_real); - int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); - - if (REG_IS_Q(dest_size) && REG_IS_Q(src_size_b) && uop->dest_reg_a_real == uop->src_reg_a_real) - { - host_x86_ADDPS_XREG_XREG(block, dest_reg, src_reg_b); - } -#ifdef RECOMPILER_DEBUG - else - fatal("PFADD %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real); -#endif - return 0; -} -static int codegen_PFCMPEQ(codeblock_t *block, uop_t *uop) -{ - int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg_b = HOST_REG_GET(uop->src_reg_b_real); - int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); - - if (REG_IS_Q(dest_size) && REG_IS_Q(src_size_b) && uop->dest_reg_a_real == uop->src_reg_a_real) - { - host_x86_CMPPS_XREG_XREG(block, dest_reg, src_reg_b, CMPPS_EQ); - } -#ifdef RECOMPILER_DEBUG - else - fatal("PFCMPEQ %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real); -#endif - return 0; -} -static int codegen_PFCMPGE(codeblock_t *block, uop_t *uop) -{ - int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg_b = HOST_REG_GET(uop->src_reg_b_real); - int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); - - if (REG_IS_Q(dest_size) && REG_IS_Q(src_size_b) && uop->dest_reg_a_real == uop->src_reg_a_real) - { - host_x86_CMPPS_XREG_XREG(block, dest_reg, src_reg_b, CMPPS_NLT); - } -#ifdef RECOMPILER_DEBUG - else - fatal("PFCMPGE %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real); -#endif - return 0; -} -static int codegen_PFCMPGT(codeblock_t *block, uop_t *uop) -{ - int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg_b = HOST_REG_GET(uop->src_reg_b_real); - int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); - - if (REG_IS_Q(dest_size) && REG_IS_Q(src_size_b) && uop->dest_reg_a_real == uop->src_reg_a_real) - { - host_x86_CMPPS_XREG_XREG(block, dest_reg, src_reg_b, CMPPS_NLE); - } -#ifdef RECOMPILER_DEBUG - else - fatal("PFCMPGT %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real); -#endif - return 0; -} -static int codegen_PFMAX(codeblock_t *block, uop_t *uop) -{ - int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg_b = HOST_REG_GET(uop->src_reg_b_real); - int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); - - if (REG_IS_Q(dest_size) && REG_IS_Q(src_size_b) && uop->dest_reg_a_real == uop->src_reg_a_real) - { - host_x86_MAXPS_XREG_XREG(block, dest_reg, src_reg_b); - } -#ifdef RECOMPILER_DEBUG - else - fatal("PFMAX %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real); -#endif - return 0; -} -static int codegen_PFMIN(codeblock_t *block, uop_t *uop) -{ - int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg_b = HOST_REG_GET(uop->src_reg_b_real); - int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); - - if (REG_IS_Q(dest_size) && REG_IS_Q(src_size_b) && uop->dest_reg_a_real == uop->src_reg_a_real) - { - host_x86_MINPS_XREG_XREG(block, dest_reg, src_reg_b); - } -#ifdef RECOMPILER_DEBUG - else - fatal("PFMIN %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real); -#endif - return 0; -} -static int codegen_PFMUL(codeblock_t *block, uop_t *uop) -{ - int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg_b = HOST_REG_GET(uop->src_reg_b_real); - int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); - - if (REG_IS_Q(dest_size) && REG_IS_Q(src_size_b) && uop->dest_reg_a_real == uop->src_reg_a_real) - { - host_x86_MULPS_XREG_XREG(block, dest_reg, src_reg_b); - } -#ifdef RECOMPILER_DEBUG - else - fatal("PFMUL %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real); -#endif - return 0; -} -static int codegen_PFRCP(codeblock_t *block, uop_t *uop) -{ - int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg_a = HOST_REG_GET(uop->src_reg_a_real); - int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size_a = IREG_GET_SIZE(uop->src_reg_a_real); - - if (REG_IS_Q(dest_size) && REG_IS_Q(src_size_a)) - { - /*TODO: This could be improved (use RCPSS + iteration)*/ - host_x86_MOV32_REG_IMM(block, REG_ECX, 1); - host_x86_MOVQ_XREG_XREG(block, REG_XMM_TEMP, src_reg_a); - host_x86_CVTSI2SS_XREG_REG(block, dest_reg, REG_ECX); - host_x86_DIVSS_XREG_XREG(block, dest_reg, REG_XMM_TEMP); - host_x86_UNPCKLPS_XREG_XREG(block, dest_reg, dest_reg); - } -#ifdef RECOMPILER_DEBUG - else - fatal("PFRCP %02x %02x\n", uop->dest_reg_a_real); -#endif - return 0; -} -static int codegen_PFRSQRT(codeblock_t *block, uop_t *uop) -{ - int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg_a = HOST_REG_GET(uop->src_reg_a_real); - int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size_a = IREG_GET_SIZE(uop->src_reg_a_real); - - if (REG_IS_Q(dest_size) && REG_IS_Q(src_size_a)) - { - /*TODO: This could be improved (use RSQRTSS + iteration)*/ - host_x86_SQRTSS_XREG_XREG(block, REG_XMM_TEMP, src_reg_a); - host_x86_MOV32_REG_IMM(block, REG_ECX, 1); - host_x86_CVTSI2SS_XREG_REG(block, dest_reg, REG_ECX); - host_x86_DIVSS_XREG_XREG(block, dest_reg, REG_XMM_TEMP); - host_x86_UNPCKLPS_XREG_XREG(block, dest_reg, dest_reg); - } -#ifdef RECOMPILER_DEBUG - else - fatal("PFRSQRT %02x %02x\n", uop->dest_reg_a_real); -#endif - return 0; -} -static int codegen_PFSUB(codeblock_t *block, uop_t *uop) -{ - int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg_a = HOST_REG_GET(uop->src_reg_a_real), src_reg_b = HOST_REG_GET(uop->src_reg_b_real); - int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size_a = IREG_GET_SIZE(uop->src_reg_a_real), src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); - - if (REG_IS_Q(dest_size) && REG_IS_Q(src_size_b) && uop->dest_reg_a_real == uop->src_reg_a_real) - { - host_x86_SUBPS_XREG_XREG(block, dest_reg, src_reg_b); - } - else if (REG_IS_Q(dest_size) && REG_IS_Q(src_size_a) && REG_IS_Q(src_size_b)) - { - host_x86_MOVQ_XREG_XREG(block, REG_XMM_TEMP, src_reg_a); - host_x86_SUBPS_XREG_XREG(block, REG_XMM_TEMP, src_reg_b); - host_x86_MOVQ_XREG_XREG(block, dest_reg, REG_XMM_TEMP); - } -#ifdef RECOMPILER_DEBUG - else - fatal("PFSUB %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real); -#endif - return 0; -} -static int codegen_PI2FD(codeblock_t *block, uop_t *uop) -{ - int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg_a = HOST_REG_GET(uop->src_reg_a_real); - int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size_a = IREG_GET_SIZE(uop->src_reg_a_real); - - if (REG_IS_Q(dest_size) && REG_IS_Q(src_size_a)) - { - host_x86_CVTDQ2PS_XREG_XREG(block, dest_reg, src_reg_a); - } -#ifdef RECOMPILER_DEBUG - else - fatal("PI2FD %02x %02x\n", uop->dest_reg_a_real); -#endif - return 0; -} - -static int codegen_PMADDWD(codeblock_t *block, uop_t *uop) -{ - int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg_b = HOST_REG_GET(uop->src_reg_b_real); - int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); - - if (REG_IS_Q(dest_size) && REG_IS_Q(src_size_b) && uop->dest_reg_a_real == uop->src_reg_a_real) - { - host_x86_PMADDWD_XREG_XREG(block, dest_reg, src_reg_b); - } -#ifdef RECOMPILER_DEBUG - else - fatal("PMULHW %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real); -#endif - return 0; -} -static int codegen_PMULHW(codeblock_t *block, uop_t *uop) -{ - int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg_b = HOST_REG_GET(uop->src_reg_b_real); - int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); - - if (REG_IS_Q(dest_size) && REG_IS_Q(src_size_b) && uop->dest_reg_a_real == uop->src_reg_a_real) - { - host_x86_PMULHW_XREG_XREG(block, dest_reg, src_reg_b); - } -#ifdef RECOMPILER_DEBUG - else - fatal("PMULHW %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real); -#endif - return 0; -} -static int codegen_PMULLW(codeblock_t *block, uop_t *uop) -{ - int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg_b = HOST_REG_GET(uop->src_reg_b_real); - int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); - - if (REG_IS_Q(dest_size) && REG_IS_Q(src_size_b) && uop->dest_reg_a_real == uop->src_reg_a_real) - { - host_x86_PMULLW_XREG_XREG(block, dest_reg, src_reg_b); - } -#ifdef RECOMPILER_DEBUG - else - fatal("PMULLW %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real); -#endif - return 0; -} - -static int codegen_PSLLW_IMM(codeblock_t *block, uop_t *uop) -{ - int dest_reg = HOST_REG_GET(uop->dest_reg_a_real); - int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real); - - if (REG_IS_Q(dest_size) && uop->dest_reg_a_real == uop->src_reg_a_real) - { - host_x86_PSLLW_XREG_IMM(block, dest_reg, uop->imm_data); - } -#ifdef RECOMPILER_DEBUG - else - fatal("PSLLW_IMM %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real); -#endif - return 0; -} -static int codegen_PSLLD_IMM(codeblock_t *block, uop_t *uop) -{ - int dest_reg = HOST_REG_GET(uop->dest_reg_a_real); - int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real); - - if (REG_IS_Q(dest_size) && uop->dest_reg_a_real == uop->src_reg_a_real) - { - host_x86_PSLLD_XREG_IMM(block, dest_reg, uop->imm_data); - } -#ifdef RECOMPILER_DEBUG - else - fatal("PSLLD_IMM %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real); -#endif - return 0; -} -static int codegen_PSLLQ_IMM(codeblock_t *block, uop_t *uop) -{ - int dest_reg = HOST_REG_GET(uop->dest_reg_a_real); - int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real); - - if (REG_IS_Q(dest_size) && uop->dest_reg_a_real == uop->src_reg_a_real) - { - host_x86_PSLLQ_XREG_IMM(block, dest_reg, uop->imm_data); - } -#ifdef RECOMPILER_DEBUG - else - fatal("PSLLQ_IMM %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real); -#endif - return 0; -} -static int codegen_PSRAW_IMM(codeblock_t *block, uop_t *uop) -{ - int dest_reg = HOST_REG_GET(uop->dest_reg_a_real); - int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real); - - if (REG_IS_Q(dest_size) && uop->dest_reg_a_real == uop->src_reg_a_real) - { - host_x86_PSRAW_XREG_IMM(block, dest_reg, uop->imm_data); - } -#ifdef RECOMPILER_DEBUG - else - fatal("PSRAW_IMM %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real); -#endif - return 0; -} -static int codegen_PSRAD_IMM(codeblock_t *block, uop_t *uop) -{ - int dest_reg = HOST_REG_GET(uop->dest_reg_a_real); - int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real); - - if (REG_IS_Q(dest_size) && uop->dest_reg_a_real == uop->src_reg_a_real) - { - host_x86_PSRAD_XREG_IMM(block, dest_reg, uop->imm_data); - } -#ifdef RECOMPILER_DEBUG - else - fatal("PSRAD_IMM %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real); -#endif - return 0; -} -static int codegen_PSRAQ_IMM(codeblock_t *block, uop_t *uop) -{ - int dest_reg = HOST_REG_GET(uop->dest_reg_a_real); - int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real); - - if (REG_IS_Q(dest_size) && uop->dest_reg_a_real == uop->src_reg_a_real) - { - host_x86_PSRAQ_XREG_IMM(block, dest_reg, uop->imm_data); - } -#ifdef RECOMPILER_DEBUG - else - fatal("PSRAQ_IMM %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real); -#endif - return 0; -} -static int codegen_PSRLW_IMM(codeblock_t *block, uop_t *uop) -{ - int dest_reg = HOST_REG_GET(uop->dest_reg_a_real); - int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real); - - if (REG_IS_Q(dest_size) && uop->dest_reg_a_real == uop->src_reg_a_real) - { - host_x86_PSRLW_XREG_IMM(block, dest_reg, uop->imm_data); - } -#ifdef RECOMPILER_DEBUG - else - fatal("PSRLW_IMM %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real); -#endif - return 0; -} -static int codegen_PSRLD_IMM(codeblock_t *block, uop_t *uop) -{ - int dest_reg = HOST_REG_GET(uop->dest_reg_a_real); - int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real); - - if (REG_IS_Q(dest_size) && uop->dest_reg_a_real == uop->src_reg_a_real) - { - host_x86_PSRLD_XREG_IMM(block, dest_reg, uop->imm_data); - } -#ifdef RECOMPILER_DEBUG - else - fatal("PSRLD_IMM %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real); -#endif - return 0; -} -static int codegen_PSRLQ_IMM(codeblock_t *block, uop_t *uop) -{ - int dest_reg = HOST_REG_GET(uop->dest_reg_a_real); - int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real); - - if (REG_IS_Q(dest_size) && uop->dest_reg_a_real == uop->src_reg_a_real) - { - host_x86_PSRLQ_XREG_IMM(block, dest_reg, uop->imm_data); - } -#ifdef RECOMPILER_DEBUG - else - fatal("PSRLQ_IMM %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real); -#endif - return 0; -} - -static int codegen_PSUBB(codeblock_t *block, uop_t *uop) -{ - int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg_b = HOST_REG_GET(uop->src_reg_b_real); - int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); - - if (REG_IS_Q(dest_size) && REG_IS_Q(src_size_b) && uop->dest_reg_a_real == uop->src_reg_a_real) - { - host_x86_PSUBB_XREG_XREG(block, dest_reg, src_reg_b); - } -#ifdef RECOMPILER_DEBUG - else - fatal("PSUBB %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real); -#endif - return 0; -} -static int codegen_PSUBW(codeblock_t *block, uop_t *uop) -{ - int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg_b = HOST_REG_GET(uop->src_reg_b_real); - int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); - - if (REG_IS_Q(dest_size) && REG_IS_Q(src_size_b) && uop->dest_reg_a_real == uop->src_reg_a_real) - { - host_x86_PSUBW_XREG_XREG(block, dest_reg, src_reg_b); - } -#ifdef RECOMPILER_DEBUG - else - fatal("PSUBW %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real); -#endif - return 0; -} -static int codegen_PSUBD(codeblock_t *block, uop_t *uop) -{ - int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg_b = HOST_REG_GET(uop->src_reg_b_real); - int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); - - if (REG_IS_Q(dest_size) && REG_IS_Q(src_size_b) && uop->dest_reg_a_real == uop->src_reg_a_real) - { - host_x86_PSUBD_XREG_XREG(block, dest_reg, src_reg_b); - } -#ifdef RECOMPILER_DEBUG - else - fatal("PSUBD %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real); -#endif - return 0; -} -static int codegen_PSUBSB(codeblock_t *block, uop_t *uop) -{ - int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg_b = HOST_REG_GET(uop->src_reg_b_real); - int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); - - if (REG_IS_Q(dest_size) && REG_IS_Q(src_size_b) && uop->dest_reg_a_real == uop->src_reg_a_real) - { - host_x86_PSUBSB_XREG_XREG(block, dest_reg, src_reg_b); - } -#ifdef RECOMPILER_DEBUG - else - fatal("PSUBSB %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real); -#endif - return 0; -} -static int codegen_PSUBSW(codeblock_t *block, uop_t *uop) -{ - int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg_b = HOST_REG_GET(uop->src_reg_b_real); - int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); - - if (REG_IS_Q(dest_size) && REG_IS_Q(src_size_b) && uop->dest_reg_a_real == uop->src_reg_a_real) - { - host_x86_PSUBSW_XREG_XREG(block, dest_reg, src_reg_b); - } -#ifdef RECOMPILER_DEBUG - else - fatal("PSUBSW %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real); -#endif - return 0; -} -static int codegen_PSUBUSB(codeblock_t *block, uop_t *uop) -{ - int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg_b = HOST_REG_GET(uop->src_reg_b_real); - int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); - - if (REG_IS_Q(dest_size) && REG_IS_Q(src_size_b) && uop->dest_reg_a_real == uop->src_reg_a_real) - { - host_x86_PSUBUSB_XREG_XREG(block, dest_reg, src_reg_b); - } -#ifdef RECOMPILER_DEBUG - else - fatal("PSUBUSB %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real); -#endif - return 0; -} -static int codegen_PSUBUSW(codeblock_t *block, uop_t *uop) -{ - int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg_b = HOST_REG_GET(uop->src_reg_b_real); - int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); - - if (REG_IS_Q(dest_size) && REG_IS_Q(src_size_b) && uop->dest_reg_a_real == uop->src_reg_a_real) - { - host_x86_PSUBUSW_XREG_XREG(block, dest_reg, src_reg_b); - } -#ifdef RECOMPILER_DEBUG - else - fatal("PSUBUSW %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real); -#endif - return 0; -} - -static int codegen_PUNPCKHBW(codeblock_t *block, uop_t *uop) -{ - int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg_b = HOST_REG_GET(uop->src_reg_b_real); - int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); - - if (REG_IS_Q(dest_size) && REG_IS_Q(src_size_b) && uop->dest_reg_a_real == uop->src_reg_a_real) - { - host_x86_PUNPCKHBW_XREG_XREG(block, dest_reg, src_reg_b); - } -#ifdef RECOMPILER_DEBUG - else - fatal("PUNPCKHBW %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real); -#endif - return 0; -} -static int codegen_PUNPCKHWD(codeblock_t *block, uop_t *uop) -{ - int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg_b = HOST_REG_GET(uop->src_reg_b_real); - int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); - - if (REG_IS_Q(dest_size) && REG_IS_Q(src_size_b) && uop->dest_reg_a_real == uop->src_reg_a_real) - { - host_x86_PUNPCKHWD_XREG_XREG(block, dest_reg, src_reg_b); - } -#ifdef RECOMPILER_DEBUG - else - fatal("PUNPCKHWD %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real); -#endif - return 0; -} -static int codegen_PUNPCKHDQ(codeblock_t *block, uop_t *uop) -{ - int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg_b = HOST_REG_GET(uop->src_reg_b_real); - int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); - - if (REG_IS_Q(dest_size) && REG_IS_Q(src_size_b) && uop->dest_reg_a_real == uop->src_reg_a_real) - { - host_x86_PUNPCKHDQ_XREG_XREG(block, dest_reg, src_reg_b); - } -#ifdef RECOMPILER_DEBUG - else - fatal("PUNPCKHDQ %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real); -#endif - return 0; -} -static int codegen_PUNPCKLBW(codeblock_t *block, uop_t *uop) -{ - int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg_b = HOST_REG_GET(uop->src_reg_b_real); - int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); - - if (REG_IS_Q(dest_size) && REG_IS_Q(src_size_b) && uop->dest_reg_a_real == uop->src_reg_a_real) - { - host_x86_PUNPCKLBW_XREG_XREG(block, dest_reg, src_reg_b); - } -#ifdef RECOMPILER_DEBUG - else - fatal("PUNPCKLBW %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real); -#endif - return 0; -} -static int codegen_PUNPCKLWD(codeblock_t *block, uop_t *uop) -{ - int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg_b = HOST_REG_GET(uop->src_reg_b_real); - int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); - - if (REG_IS_Q(dest_size) && REG_IS_Q(src_size_b) && uop->dest_reg_a_real == uop->src_reg_a_real) - { - host_x86_PUNPCKLWD_XREG_XREG(block, dest_reg, src_reg_b); - } -#ifdef RECOMPILER_DEBUG - else - fatal("PUNPCKLWD %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real); -#endif - return 0; -} -static int codegen_PUNPCKLDQ(codeblock_t *block, uop_t *uop) -{ - int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg_b = HOST_REG_GET(uop->src_reg_b_real); - int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); - - if (REG_IS_Q(dest_size) && REG_IS_Q(src_size_b) && uop->dest_reg_a_real == uop->src_reg_a_real) - { - host_x86_PUNPCKLDQ_XREG_XREG(block, dest_reg, src_reg_b); - } -#ifdef RECOMPILER_DEBUG - else - fatal("PUNPCKLDQ %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real); -#endif - return 0; -} - -static int codegen_ROL(codeblock_t *block, uop_t *uop) -{ - int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg = HOST_REG_GET(uop->src_reg_a_real), shift_reg = HOST_REG_GET(uop->src_reg_b_real); - int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size = IREG_GET_SIZE(uop->src_reg_a_real); - - host_x86_MOV32_REG_REG(block, REG_ECX, shift_reg); - if (REG_IS_L(dest_size) && REG_IS_L(src_size)) - { - if (uop->dest_reg_a_real != uop->src_reg_a_real) - host_x86_MOV32_REG_REG(block, dest_reg, src_reg); - host_x86_ROL32_CL(block, dest_reg); - } - else if (REG_IS_W(dest_size) && REG_IS_W(src_size)) - { - if (uop->dest_reg_a_real != uop->src_reg_a_real) - host_x86_MOV16_REG_REG(block, dest_reg, src_reg); - host_x86_ROL16_CL(block, dest_reg); - } - else if (REG_IS_B(dest_size) && REG_IS_B(src_size)) - { - if (uop->dest_reg_a_real != uop->src_reg_a_real) - host_x86_MOV8_REG_REG(block, dest_reg, src_reg); - host_x86_ROL8_CL(block, dest_reg); - } -#ifdef RECOMPILER_DEBUG - else - fatal("ROL %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real); -#endif - return 0; -} -static int codegen_ROL_IMM(codeblock_t *block, uop_t *uop) -{ - int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg = HOST_REG_GET(uop->src_reg_a_real); - int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size = IREG_GET_SIZE(uop->src_reg_a_real); - - if (REG_IS_L(dest_size) && REG_IS_L(src_size)) - { - if (uop->dest_reg_a_real != uop->src_reg_a_real) - host_x86_MOV32_REG_REG(block, dest_reg, src_reg); - host_x86_ROL32_IMM(block, dest_reg, uop->imm_data); - } - else if (REG_IS_W(dest_size) && REG_IS_W(src_size)) - { - if (uop->dest_reg_a_real != uop->src_reg_a_real) - host_x86_MOV16_REG_REG(block, dest_reg, src_reg); - host_x86_ROL16_IMM(block, dest_reg, uop->imm_data); - } - else if (REG_IS_B(dest_size) && REG_IS_B(src_size)) - { - if (uop->dest_reg_a_real != uop->src_reg_a_real) - host_x86_MOV8_REG_REG(block, dest_reg, src_reg); - host_x86_ROL8_IMM(block, dest_reg, uop->imm_data); - } -#ifdef RECOMPILER_DEBUG - else - fatal("ROL_IMM %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real); -#endif - return 0; -} -static int codegen_ROR(codeblock_t *block, uop_t *uop) -{ - int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg = HOST_REG_GET(uop->src_reg_a_real), shift_reg = HOST_REG_GET(uop->src_reg_b_real); - int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size = IREG_GET_SIZE(uop->src_reg_a_real); - - host_x86_MOV32_REG_REG(block, REG_ECX, shift_reg); - if (REG_IS_L(dest_size) && REG_IS_L(src_size)) - { - if (uop->dest_reg_a_real != uop->src_reg_a_real) - host_x86_MOV32_REG_REG(block, dest_reg, src_reg); - host_x86_ROR32_CL(block, dest_reg); - } - else if (REG_IS_W(dest_size) && REG_IS_W(src_size)) - { - if (uop->dest_reg_a_real != uop->src_reg_a_real) - host_x86_MOV16_REG_REG(block, dest_reg, src_reg); - host_x86_ROR16_CL(block, dest_reg); - } - else if (REG_IS_B(dest_size) && REG_IS_B(src_size)) - { - if (uop->dest_reg_a_real != uop->src_reg_a_real) - host_x86_MOV8_REG_REG(block, dest_reg, src_reg); - host_x86_ROR8_CL(block, dest_reg); - } -#ifdef RECOMPILER_DEBUG - else - fatal("ROR %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real); -#endif - return 0; -} -static int codegen_ROR_IMM(codeblock_t *block, uop_t *uop) -{ - int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg = HOST_REG_GET(uop->src_reg_a_real); - int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size = IREG_GET_SIZE(uop->src_reg_a_real); - - if (REG_IS_L(dest_size) && REG_IS_L(src_size)) - { - if (uop->dest_reg_a_real != uop->src_reg_a_real) - host_x86_MOV32_REG_REG(block, dest_reg, src_reg); - host_x86_ROR32_IMM(block, dest_reg, uop->imm_data); - } - else if (REG_IS_W(dest_size) && REG_IS_W(src_size)) - { - if (uop->dest_reg_a_real != uop->src_reg_a_real) - host_x86_MOV16_REG_REG(block, dest_reg, src_reg); - host_x86_ROR16_IMM(block, dest_reg, uop->imm_data); - } - else if (REG_IS_B(dest_size) && REG_IS_B(src_size)) - { - if (uop->dest_reg_a_real != uop->src_reg_a_real) - host_x86_MOV8_REG_REG(block, dest_reg, src_reg); - host_x86_ROR8_IMM(block, dest_reg, uop->imm_data); - } -#ifdef RECOMPILER_DEBUG - else - fatal("ROR_IMM %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real); -#endif - return 0; -} - -static int codegen_SAR(codeblock_t *block, uop_t *uop) -{ - int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg = HOST_REG_GET(uop->src_reg_a_real), shift_reg = HOST_REG_GET(uop->src_reg_b_real); - int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size = IREG_GET_SIZE(uop->src_reg_a_real); - - host_x86_MOV32_REG_REG(block, REG_ECX, shift_reg); - if (REG_IS_L(dest_size) && REG_IS_L(src_size)) - { - if (uop->dest_reg_a_real != uop->src_reg_a_real) - host_x86_MOV32_REG_REG(block, dest_reg, src_reg); - host_x86_SAR32_CL(block, dest_reg); - } - else if (REG_IS_W(dest_size) && REG_IS_W(src_size)) - { - if (uop->dest_reg_a_real != uop->src_reg_a_real) - host_x86_MOV16_REG_REG(block, dest_reg, src_reg); - host_x86_SAR16_CL(block, dest_reg); - } - else if (REG_IS_B(dest_size) && REG_IS_B(src_size)) - { - if (uop->dest_reg_a_real != uop->src_reg_a_real) - host_x86_MOV8_REG_REG(block, dest_reg, src_reg); - host_x86_SAR8_CL(block, dest_reg); - } -#ifdef RECOMPILER_DEBUG - else - fatal("SAR %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real); -#endif - return 0; -} -static int codegen_SAR_IMM(codeblock_t *block, uop_t *uop) -{ - int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg = HOST_REG_GET(uop->src_reg_a_real); - int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size = IREG_GET_SIZE(uop->src_reg_a_real); - - if (REG_IS_L(dest_size) && REG_IS_L(src_size)) - { - if (uop->dest_reg_a_real != uop->src_reg_a_real) - host_x86_MOV32_REG_REG(block, dest_reg, src_reg); - host_x86_SAR32_IMM(block, dest_reg, uop->imm_data); - } - else if (REG_IS_W(dest_size) && REG_IS_W(src_size)) - { - if (uop->dest_reg_a_real != uop->src_reg_a_real) - host_x86_MOV16_REG_REG(block, dest_reg, src_reg); - host_x86_SAR16_IMM(block, dest_reg, uop->imm_data); - } - else if (REG_IS_B(dest_size) && REG_IS_B(src_size)) - { - if (uop->dest_reg_a_real != uop->src_reg_a_real) - host_x86_MOV8_REG_REG(block, dest_reg, src_reg); - host_x86_SAR8_IMM(block, dest_reg, uop->imm_data); - } -#ifdef RECOMPILER_DEBUG - else - fatal("SAR_IMM %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real); -#endif - return 0; -} -static int codegen_SHL(codeblock_t *block, uop_t *uop) -{ - int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg = HOST_REG_GET(uop->src_reg_a_real), shift_reg = HOST_REG_GET(uop->src_reg_b_real); - int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size = IREG_GET_SIZE(uop->src_reg_a_real); - - host_x86_MOV32_REG_REG(block, REG_ECX, shift_reg); - if (REG_IS_L(dest_size) && REG_IS_L(src_size)) - { - if (uop->dest_reg_a_real != uop->src_reg_a_real) - host_x86_MOV32_REG_REG(block, dest_reg, src_reg); - host_x86_SHL32_CL(block, dest_reg); - } - else if (REG_IS_W(dest_size) && REG_IS_W(src_size)) - { - if (uop->dest_reg_a_real != uop->src_reg_a_real) - host_x86_MOV16_REG_REG(block, dest_reg, src_reg); - host_x86_SHL16_CL(block, dest_reg); - } - else if (REG_IS_B(dest_size) && REG_IS_B(src_size)) - { - if (uop->dest_reg_a_real != uop->src_reg_a_real) - host_x86_MOV8_REG_REG(block, dest_reg, src_reg); - host_x86_SHL8_CL(block, dest_reg); - } -#ifdef RECOMPILER_DEBUG - else - fatal("SHL %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real); -#endif - return 0; -} -static int codegen_SHL_IMM(codeblock_t *block, uop_t *uop) -{ - int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg = HOST_REG_GET(uop->src_reg_a_real); - int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size = IREG_GET_SIZE(uop->src_reg_a_real); - - if (REG_IS_L(dest_size) && REG_IS_L(src_size)) - { - if (uop->dest_reg_a_real != uop->src_reg_a_real) - host_x86_MOV32_REG_REG(block, dest_reg, src_reg); - host_x86_SHL32_IMM(block, dest_reg, uop->imm_data); - } - else if (REG_IS_W(dest_size) && REG_IS_W(src_size)) - { - if (uop->dest_reg_a_real != uop->src_reg_a_real) - host_x86_MOV16_REG_REG(block, dest_reg, src_reg); - host_x86_SHL16_IMM(block, dest_reg, uop->imm_data); - } - else if (REG_IS_B(dest_size) && REG_IS_B(src_size)) - { - if (uop->dest_reg_a_real != uop->src_reg_a_real) - host_x86_MOV8_REG_REG(block, dest_reg, src_reg); - host_x86_SHL8_IMM(block, dest_reg, uop->imm_data); - } -#ifdef RECOMPILER_DEBUG - else - fatal("SHL_IMM %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real); -#endif - return 0; -} -static int codegen_SHR(codeblock_t *block, uop_t *uop) -{ - int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg = HOST_REG_GET(uop->src_reg_a_real), shift_reg = HOST_REG_GET(uop->src_reg_b_real); - int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size = IREG_GET_SIZE(uop->src_reg_a_real); - - host_x86_MOV32_REG_REG(block, REG_ECX, shift_reg); - if (REG_IS_L(dest_size) && REG_IS_L(src_size)) - { - if (uop->dest_reg_a_real != uop->src_reg_a_real) - host_x86_MOV32_REG_REG(block, dest_reg, src_reg); - host_x86_SHR32_CL(block, dest_reg); - } - else if (REG_IS_W(dest_size) && REG_IS_W(src_size)) - { - if (uop->dest_reg_a_real != uop->src_reg_a_real) - host_x86_MOV16_REG_REG(block, dest_reg, src_reg); - host_x86_SHR16_CL(block, dest_reg); - } - else if (REG_IS_B(dest_size) && REG_IS_B(src_size)) - { - if (uop->dest_reg_a_real != uop->src_reg_a_real) - host_x86_MOV8_REG_REG(block, dest_reg, src_reg); - host_x86_SHR8_CL(block, dest_reg); - } -#ifdef RECOMPILER_DEBUG - else - fatal("SHR %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real); -#endif - return 0; -} -static int codegen_SHR_IMM(codeblock_t *block, uop_t *uop) -{ - int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg = HOST_REG_GET(uop->src_reg_a_real); - int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size = IREG_GET_SIZE(uop->src_reg_a_real); - - if (REG_IS_L(dest_size) && REG_IS_L(src_size)) - { - if (uop->dest_reg_a_real != uop->src_reg_a_real) - host_x86_MOV32_REG_REG(block, dest_reg, src_reg); - host_x86_SHR32_IMM(block, dest_reg, uop->imm_data); - } - else if (REG_IS_W(dest_size) && REG_IS_W(src_size)) - { - if (uop->dest_reg_a_real != uop->src_reg_a_real) - host_x86_MOV16_REG_REG(block, dest_reg, src_reg); - host_x86_SHR16_IMM(block, dest_reg, uop->imm_data); - } - else if (REG_IS_B(dest_size) && REG_IS_B(src_size)) - { - if (uop->dest_reg_a_real != uop->src_reg_a_real) - host_x86_MOV8_REG_REG(block, dest_reg, src_reg); - host_x86_SHR8_IMM(block, dest_reg, uop->imm_data); - } -#ifdef RECOMPILER_DEBUG - else - fatal("SHR_IMM %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real); -#endif - return 0; -} - -static int codegen_STORE_PTR_IMM(codeblock_t *block, uop_t *uop) -{ -#ifdef RECOMPILER_DEBUG - if (((uintptr_t)uop->p) >> 32) - fatal("STORE_PTR_IMM 64-bit addr\n"); -#endif - host_x86_MOV32_ABS_IMM(block, uop->p, uop->imm_data); - return 0; -} -static int codegen_STORE_PTR_IMM_8(codeblock_t *block, uop_t *uop) -{ -#ifdef RECOMPILER_DEBUG - if (((uintptr_t)uop->p) >> 32) - fatal("STORE_PTR_IMM_8 64-bit addr\n"); -#endif - host_x86_MOV8_ABS_IMM(block, uop->p, uop->imm_data); - return 0; -} - -static int codegen_SUB(codeblock_t *block, uop_t *uop) -{ - int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg_a = HOST_REG_GET(uop->src_reg_a_real), src_reg_b = HOST_REG_GET(uop->src_reg_b_real); - int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size_a = IREG_GET_SIZE(uop->src_reg_a_real), src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); - - if (REG_IS_L(dest_size) && REG_IS_L(src_size_a) && REG_IS_L(src_size_b)) - { - if (dest_reg != src_reg_a) - host_x86_MOV32_REG_REG(block, dest_reg, src_reg_a); - host_x86_SUB32_REG_REG(block, dest_reg, src_reg_b); - } - else if (REG_IS_W(dest_size) && REG_IS_W(src_size_a) && REG_IS_W(src_size_b)) - { - if (dest_reg != src_reg_a) - host_x86_MOV16_REG_REG(block, dest_reg, src_reg_a); - host_x86_SUB16_REG_REG(block, dest_reg, src_reg_b); - } - else if (REG_IS_B(dest_size) && REG_IS_B(src_size_a) && REG_IS_B(src_size_b)) - { - if (dest_reg != src_reg_a) - host_x86_MOV8_REG_REG(block, dest_reg, src_reg_a); - host_x86_SUB8_REG_REG(block, dest_reg, src_reg_b); - } -#ifdef RECOMPILER_DEBUG - else - fatal("SUB %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real); -#endif - return 0; -} -static int codegen_SUB_IMM(codeblock_t *block, uop_t *uop) -{ - int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg = HOST_REG_GET(uop->src_reg_a_real); - int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size = IREG_GET_SIZE(uop->src_reg_a_real); - - if (REG_IS_L(dest_size) && REG_IS_L(src_size)) - { - if (dest_reg != src_reg) - host_x86_MOV32_REG_REG(block, dest_reg, src_reg); - host_x86_SUB32_REG_IMM(block, dest_reg, uop->imm_data); - } - else if (REG_IS_W(dest_size) && REG_IS_W(src_size)) - { - if (dest_reg != src_reg) - host_x86_MOV16_REG_REG(block, dest_reg, src_reg); - host_x86_SUB16_REG_IMM(block, dest_reg, uop->imm_data); - } - else if (REG_IS_B(dest_size) && REG_IS_B(src_size)) - { - if (dest_reg != src_reg) - host_x86_MOV8_REG_REG(block, dest_reg, src_reg); - host_x86_SUB8_REG_IMM(block, dest_reg, uop->imm_data); - } -#ifdef RECOMPILER_DEBUG - else - fatal("SUB_IMM %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real); -#endif - return 0; -} - -static int codegen_TEST_JNS_DEST(codeblock_t *block, uop_t *uop) -{ - int src_reg = HOST_REG_GET(uop->src_reg_a_real); - int src_size = IREG_GET_SIZE(uop->src_reg_a_real); - - if (REG_IS_L(src_size)) - { - host_x86_TEST32_REG(block, src_reg, src_reg); - } - else if (REG_IS_W(src_size)) - { - host_x86_TEST16_REG(block, src_reg, src_reg); - } - else if (REG_IS_B(src_size)) - { - host_x86_TEST8_REG(block, src_reg, src_reg); - } -#ifdef RECOMPILER_DEBUG - else - fatal("TEST_JNS_DEST %02x\n", uop->src_reg_a_real); -#endif - uop->p = host_x86_JNS_long(block); - - return 0; -} -static int codegen_TEST_JS_DEST(codeblock_t *block, uop_t *uop) -{ - int src_reg = HOST_REG_GET(uop->src_reg_a_real); - int src_size = IREG_GET_SIZE(uop->src_reg_a_real); - - if (REG_IS_L(src_size)) - { - host_x86_TEST32_REG(block, src_reg, src_reg); - } - else if (REG_IS_W(src_size)) - { - host_x86_TEST16_REG(block, src_reg, src_reg); - } - else if (REG_IS_B(src_size)) - { - host_x86_TEST8_REG(block, src_reg, src_reg); - } -#ifdef RECOMPILER_DEBUG - else - fatal("TEST_JS_DEST %02x\n", uop->src_reg_a_real); -#endif - uop->p = host_x86_JS_long(block); - - return 0; -} - -static int codegen_XOR(codeblock_t *block, uop_t *uop) -{ - int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg_b = HOST_REG_GET(uop->src_reg_b_real); - int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size_a = IREG_GET_SIZE(uop->src_reg_a_real), src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); - - if (REG_IS_Q(dest_size) && REG_IS_Q(src_size_a) && REG_IS_Q(src_size_b) && uop->dest_reg_a_real == uop->src_reg_a_real) - { - host_x86_PXOR_XREG_XREG(block, dest_reg, src_reg_b); - } - else if (REG_IS_L(dest_size) && REG_IS_L(src_size_a) && REG_IS_L(src_size_b) && uop->dest_reg_a_real == uop->src_reg_a_real) - { - host_x86_XOR32_REG_REG(block, dest_reg, src_reg_b); - } - else if (REG_IS_W(dest_size) && REG_IS_W(src_size_a) && REG_IS_W(src_size_b) && uop->dest_reg_a_real == uop->src_reg_a_real) - { - host_x86_XOR16_REG_REG(block, dest_reg, src_reg_b); - } - else if (REG_IS_B(dest_size) && REG_IS_B(src_size_a) && REG_IS_B(src_size_b) && uop->dest_reg_a_real == uop->src_reg_a_real) - { - host_x86_XOR8_REG_REG(block, dest_reg, src_reg_b); - } -#ifdef RECOMPILER_DEBUG - else - fatal("XOR %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real); -#endif - return 0; -} -static int codegen_XOR_IMM(codeblock_t *block, uop_t *uop) -{ - int dest_reg = HOST_REG_GET(uop->dest_reg_a_real); - int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size = IREG_GET_SIZE(uop->src_reg_a_real); - - if (REG_IS_L(dest_size) && REG_IS_L(src_size)) - { - host_x86_XOR32_REG_IMM(block, dest_reg, uop->imm_data); - } - else if (REG_IS_W(dest_size) && REG_IS_W(src_size)) - { - host_x86_XOR16_REG_IMM(block, dest_reg, uop->imm_data); - } - else if (REG_IS_B(dest_size) && REG_IS_B(src_size)) - { - host_x86_XOR8_REG_IMM(block, dest_reg, uop->imm_data); - } -#ifdef RECOMPILER_DEBUG - else - fatal("XOR_IMM %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real); -#endif - return 0; -} - -const uOpFn uop_handlers[UOP_MAX] = -{ - [UOP_CALL_FUNC & UOP_MASK] = codegen_CALL_FUNC, - [UOP_CALL_FUNC_RESULT & UOP_MASK] = codegen_CALL_FUNC_RESULT, - [UOP_CALL_INSTRUCTION_FUNC & UOP_MASK] = codegen_CALL_INSTRUCTION_FUNC, - - [UOP_JMP & UOP_MASK] = codegen_JMP, - - [UOP_LOAD_SEG & UOP_MASK] = codegen_LOAD_SEG, - - [UOP_LOAD_FUNC_ARG_0 & UOP_MASK] = codegen_LOAD_FUNC_ARG0, - [UOP_LOAD_FUNC_ARG_1 & UOP_MASK] = codegen_LOAD_FUNC_ARG1, - [UOP_LOAD_FUNC_ARG_2 & UOP_MASK] = codegen_LOAD_FUNC_ARG2, - [UOP_LOAD_FUNC_ARG_3 & UOP_MASK] = codegen_LOAD_FUNC_ARG3, - - [UOP_LOAD_FUNC_ARG_0_IMM & UOP_MASK] = codegen_LOAD_FUNC_ARG0_IMM, - [UOP_LOAD_FUNC_ARG_1_IMM & UOP_MASK] = codegen_LOAD_FUNC_ARG1_IMM, - [UOP_LOAD_FUNC_ARG_2_IMM & UOP_MASK] = codegen_LOAD_FUNC_ARG2_IMM, - [UOP_LOAD_FUNC_ARG_3_IMM & UOP_MASK] = codegen_LOAD_FUNC_ARG3_IMM, - - [UOP_STORE_P_IMM & UOP_MASK] = codegen_STORE_PTR_IMM, - [UOP_STORE_P_IMM_8 & UOP_MASK] = codegen_STORE_PTR_IMM_8, - - [UOP_MEM_LOAD_ABS & UOP_MASK] = codegen_MEM_LOAD_ABS, - [UOP_MEM_LOAD_REG & UOP_MASK] = codegen_MEM_LOAD_REG, - [UOP_MEM_LOAD_SINGLE & UOP_MASK] = codegen_MEM_LOAD_SINGLE, - [UOP_MEM_LOAD_DOUBLE & UOP_MASK] = codegen_MEM_LOAD_DOUBLE, - - [UOP_MEM_STORE_ABS & UOP_MASK] = codegen_MEM_STORE_ABS, - [UOP_MEM_STORE_REG & UOP_MASK] = codegen_MEM_STORE_REG, - [UOP_MEM_STORE_IMM_8 & UOP_MASK] = codegen_MEM_STORE_IMM_8, - [UOP_MEM_STORE_IMM_16 & UOP_MASK] = codegen_MEM_STORE_IMM_16, - [UOP_MEM_STORE_IMM_32 & UOP_MASK] = codegen_MEM_STORE_IMM_32, - [UOP_MEM_STORE_SINGLE & UOP_MASK] = codegen_MEM_STORE_SINGLE, - [UOP_MEM_STORE_DOUBLE & UOP_MASK] = codegen_MEM_STORE_DOUBLE, - - [UOP_MOV & UOP_MASK] = codegen_MOV, - [UOP_MOV_PTR & UOP_MASK] = codegen_MOV_PTR, - [UOP_MOV_IMM & UOP_MASK] = codegen_MOV_IMM, - [UOP_MOVSX & UOP_MASK] = codegen_MOVSX, - [UOP_MOVZX & UOP_MASK] = codegen_MOVZX, - [UOP_MOV_DOUBLE_INT & UOP_MASK] = codegen_MOV_DOUBLE_INT, - [UOP_MOV_INT_DOUBLE & UOP_MASK] = codegen_MOV_INT_DOUBLE, - [UOP_MOV_INT_DOUBLE_64 & UOP_MASK] = codegen_MOV_INT_DOUBLE_64, - [UOP_MOV_REG_PTR & UOP_MASK] = codegen_MOV_REG_PTR, - [UOP_MOVZX_REG_PTR_8 & UOP_MASK] = codegen_MOVZX_REG_PTR_8, - [UOP_MOVZX_REG_PTR_16 & UOP_MASK] = codegen_MOVZX_REG_PTR_16, - - [UOP_ADD & UOP_MASK] = codegen_ADD, - [UOP_ADD_IMM & UOP_MASK] = codegen_ADD_IMM, - [UOP_ADD_LSHIFT & UOP_MASK] = codegen_ADD_LSHIFT, - [UOP_AND & UOP_MASK] = codegen_AND, - [UOP_ANDN & UOP_MASK] = codegen_ANDN, - [UOP_AND_IMM & UOP_MASK] = codegen_AND_IMM, - [UOP_OR & UOP_MASK] = codegen_OR, - [UOP_OR_IMM & UOP_MASK] = codegen_OR_IMM, - [UOP_SUB & UOP_MASK] = codegen_SUB, - [UOP_SUB_IMM & UOP_MASK] = codegen_SUB_IMM, - [UOP_XOR & UOP_MASK] = codegen_XOR, - [UOP_XOR_IMM & UOP_MASK] = codegen_XOR_IMM, - - [UOP_SAR & UOP_MASK] = codegen_SAR, - [UOP_SAR_IMM & UOP_MASK] = codegen_SAR_IMM, - [UOP_SHL & UOP_MASK] = codegen_SHL, - [UOP_SHL_IMM & UOP_MASK] = codegen_SHL_IMM, - [UOP_SHR & UOP_MASK] = codegen_SHR, - [UOP_SHR_IMM & UOP_MASK] = codegen_SHR_IMM, - [UOP_ROL & UOP_MASK] = codegen_ROL, - [UOP_ROL_IMM & UOP_MASK] = codegen_ROL_IMM, - [UOP_ROR & UOP_MASK] = codegen_ROR, - [UOP_ROR_IMM & UOP_MASK] = codegen_ROR_IMM, - - [UOP_CMP_IMM_JZ & UOP_MASK] = codegen_CMP_IMM_JZ, - - [UOP_CMP_JB & UOP_MASK] = codegen_CMP_JB, - [UOP_CMP_JNBE & UOP_MASK] = codegen_CMP_JNBE, - - [UOP_CMP_JNB_DEST & UOP_MASK] = codegen_CMP_JNB_DEST, - [UOP_CMP_JNBE_DEST & UOP_MASK] = codegen_CMP_JNBE_DEST, - [UOP_CMP_JNL_DEST & UOP_MASK] = codegen_CMP_JNL_DEST, - [UOP_CMP_JNLE_DEST & UOP_MASK] = codegen_CMP_JNLE_DEST, - [UOP_CMP_JNO_DEST & UOP_MASK] = codegen_CMP_JNO_DEST, - [UOP_CMP_JNZ_DEST & UOP_MASK] = codegen_CMP_JNZ_DEST, - [UOP_CMP_JB_DEST & UOP_MASK] = codegen_CMP_JB_DEST, - [UOP_CMP_JBE_DEST & UOP_MASK] = codegen_CMP_JBE_DEST, - [UOP_CMP_JL_DEST & UOP_MASK] = codegen_CMP_JL_DEST, - [UOP_CMP_JLE_DEST & UOP_MASK] = codegen_CMP_JLE_DEST, - [UOP_CMP_JO_DEST & UOP_MASK] = codegen_CMP_JO_DEST, - [UOP_CMP_JZ_DEST & UOP_MASK] = codegen_CMP_JZ_DEST, - - [UOP_CMP_IMM_JNZ_DEST & UOP_MASK] = codegen_CMP_IMM_JNZ_DEST, - [UOP_CMP_IMM_JZ_DEST & UOP_MASK] = codegen_CMP_IMM_JZ_DEST, - - [UOP_TEST_JNS_DEST & UOP_MASK] = codegen_TEST_JNS_DEST, - [UOP_TEST_JS_DEST & UOP_MASK] = codegen_TEST_JS_DEST, - - [UOP_FP_ENTER & UOP_MASK] = codegen_FP_ENTER, - [UOP_MMX_ENTER & UOP_MASK] = codegen_MMX_ENTER, - - [UOP_FADD & UOP_MASK] = codegen_FADD, - [UOP_FCOM & UOP_MASK] = codegen_FCOM, - [UOP_FDIV & UOP_MASK] = codegen_FDIV, - [UOP_FMUL & UOP_MASK] = codegen_FMUL, - [UOP_FSUB & UOP_MASK] = codegen_FSUB, - - [UOP_FABS & UOP_MASK] = codegen_FABS, - [UOP_FCHS & UOP_MASK] = codegen_FCHS, - [UOP_FSQRT & UOP_MASK] = codegen_FSQRT, - [UOP_FTST & UOP_MASK] = codegen_FTST, - - [UOP_PACKSSWB & UOP_MASK] = codegen_PACKSSWB, - [UOP_PACKSSDW & UOP_MASK] = codegen_PACKSSDW, - [UOP_PACKUSWB & UOP_MASK] = codegen_PACKUSWB, - - [UOP_PADDB & UOP_MASK] = codegen_PADDB, - [UOP_PADDW & UOP_MASK] = codegen_PADDW, - [UOP_PADDD & UOP_MASK] = codegen_PADDD, - [UOP_PADDSB & UOP_MASK] = codegen_PADDSB, - [UOP_PADDSW & UOP_MASK] = codegen_PADDSW, - [UOP_PADDUSB & UOP_MASK] = codegen_PADDUSB, - [UOP_PADDUSW & UOP_MASK] = codegen_PADDUSW, - - [UOP_PCMPEQB & UOP_MASK] = codegen_PCMPEQB, - [UOP_PCMPEQW & UOP_MASK] = codegen_PCMPEQW, - [UOP_PCMPEQD & UOP_MASK] = codegen_PCMPEQD, - [UOP_PCMPGTB & UOP_MASK] = codegen_PCMPGTB, - [UOP_PCMPGTW & UOP_MASK] = codegen_PCMPGTW, - [UOP_PCMPGTD & UOP_MASK] = codegen_PCMPGTD, - - [UOP_PF2ID & UOP_MASK] = codegen_PF2ID, - [UOP_PFADD & UOP_MASK] = codegen_PFADD, - [UOP_PFCMPEQ & UOP_MASK] = codegen_PFCMPEQ, - [UOP_PFCMPGE & UOP_MASK] = codegen_PFCMPGE, - [UOP_PFCMPGT & UOP_MASK] = codegen_PFCMPGT, - [UOP_PFMAX & UOP_MASK] = codegen_PFMAX, - [UOP_PFMIN & UOP_MASK] = codegen_PFMIN, - [UOP_PFMUL & UOP_MASK] = codegen_PFMUL, - [UOP_PFRCP & UOP_MASK] = codegen_PFRCP, - [UOP_PFRSQRT & UOP_MASK] = codegen_PFRSQRT, - [UOP_PFSUB & UOP_MASK] = codegen_PFSUB, - [UOP_PI2FD & UOP_MASK] = codegen_PI2FD, - - [UOP_PMADDWD & UOP_MASK] = codegen_PMADDWD, - [UOP_PMULHW & UOP_MASK] = codegen_PMULHW, - [UOP_PMULLW & UOP_MASK] = codegen_PMULLW, - - [UOP_PSLLW_IMM & UOP_MASK] = codegen_PSLLW_IMM, - [UOP_PSLLD_IMM & UOP_MASK] = codegen_PSLLD_IMM, - [UOP_PSLLQ_IMM & UOP_MASK] = codegen_PSLLQ_IMM, - [UOP_PSRAW_IMM & UOP_MASK] = codegen_PSRAW_IMM, - [UOP_PSRAD_IMM & UOP_MASK] = codegen_PSRAD_IMM, - [UOP_PSRAQ_IMM & UOP_MASK] = codegen_PSRAQ_IMM, - [UOP_PSRLW_IMM & UOP_MASK] = codegen_PSRLW_IMM, - [UOP_PSRLD_IMM & UOP_MASK] = codegen_PSRLD_IMM, - [UOP_PSRLQ_IMM & UOP_MASK] = codegen_PSRLQ_IMM, - - [UOP_PSUBB & UOP_MASK] = codegen_PSUBB, - [UOP_PSUBW & UOP_MASK] = codegen_PSUBW, - [UOP_PSUBD & UOP_MASK] = codegen_PSUBD, - [UOP_PSUBSB & UOP_MASK] = codegen_PSUBSB, - [UOP_PSUBSW & UOP_MASK] = codegen_PSUBSW, - [UOP_PSUBUSB & UOP_MASK] = codegen_PSUBUSB, - [UOP_PSUBUSW & UOP_MASK] = codegen_PSUBUSW, - - [UOP_PUNPCKHBW & UOP_MASK] = codegen_PUNPCKHBW, - [UOP_PUNPCKHWD & UOP_MASK] = codegen_PUNPCKHWD, - [UOP_PUNPCKHDQ & UOP_MASK] = codegen_PUNPCKHDQ, - [UOP_PUNPCKLBW & UOP_MASK] = codegen_PUNPCKLBW, - [UOP_PUNPCKLWD & UOP_MASK] = codegen_PUNPCKLWD, - [UOP_PUNPCKLDQ & UOP_MASK] = codegen_PUNPCKLDQ, - - [UOP_NOP_BARRIER & UOP_MASK] = codegen_NOP + host_x86_CALL(block, codegen_mem_store_quad); + } +# ifdef RECOMPILER_DEBUG + else + fatal("MEM_STORE_REG - %02x\n", uop->src_reg_b_real); +# endif + host_x86_TEST32_REG(block, REG_ESI, REG_ESI); + host_x86_JNZ(block, codegen_exit_rout); + + return 0; +} + +static int +codegen_MEM_STORE_SINGLE(codeblock_t *block, uop_t *uop) +{ + int seg_reg = HOST_REG_GET(uop->src_reg_a_real); + int addr_reg = HOST_REG_GET(uop->src_reg_b_real); + int src_reg = HOST_REG_GET(uop->src_reg_c_real); + +# ifdef RECOMPILER_DEBUG + int src_size = IREG_GET_SIZE(uop->src_reg_c_real); + if (!REG_IS_D(src_size)) + fatal("MEM_STORE_SINGLE - %02x\n", uop->src_reg_b_real); +# endif + host_x86_LEA_REG_REG(block, REG_ESI, seg_reg, addr_reg); + if (uop->imm_data) + host_x86_ADD32_REG_IMM(block, REG_ESI, uop->imm_data); + host_x86_CVTSD2SS_XREG_XREG(block, REG_XMM_TEMP, src_reg); + host_x86_CALL(block, codegen_mem_store_single); + host_x86_TEST32_REG(block, REG_ESI, REG_ESI); + host_x86_JNZ(block, codegen_exit_rout); + + return 0; +} +static int +codegen_MEM_STORE_DOUBLE(codeblock_t *block, uop_t *uop) +{ + int seg_reg = HOST_REG_GET(uop->src_reg_a_real); + int addr_reg = HOST_REG_GET(uop->src_reg_b_real); + int src_reg = HOST_REG_GET(uop->src_reg_c_real); + +# ifdef RECOMPILER_DEBUG + int src_size = IREG_GET_SIZE(uop->src_reg_c_real); + if (!REG_IS_D(src_size)) + fatal("MEM_STORE_DOUBLE - %02x\n", uop->src_reg_b_real); +# endif + host_x86_LEA_REG_REG(block, REG_ESI, seg_reg, addr_reg); + if (uop->imm_data) + host_x86_ADD32_REG_IMM(block, REG_ESI, uop->imm_data); + host_x86_MOVQ_XREG_XREG(block, REG_XMM_TEMP, src_reg); + host_x86_CALL(block, codegen_mem_store_double); + host_x86_TEST32_REG(block, REG_ESI, REG_ESI); + host_x86_JNZ(block, codegen_exit_rout); + + return 0; +} + +static int +codegen_MOV(codeblock_t *block, uop_t *uop) +{ + int dest_reg = HOST_REG_GET(uop->dest_reg_a_real); + int src_reg = HOST_REG_GET(uop->src_reg_a_real); + int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real); + int src_size = IREG_GET_SIZE(uop->src_reg_a_real); + + if (REG_IS_L(dest_size) && REG_IS_L(src_size)) { + host_x86_MOV32_REG_REG(block, dest_reg, src_reg); + } else if (REG_IS_W(dest_size) && REG_IS_W(src_size)) { + host_x86_MOV16_REG_REG(block, dest_reg, src_reg); + } else if (REG_IS_B(dest_size) && REG_IS_B(src_size)) { + host_x86_MOV8_REG_REG(block, dest_reg, src_reg); + } else if (REG_IS_D(dest_size) && REG_IS_D(src_size)) { + host_x86_MOVQ_XREG_XREG(block, dest_reg, src_reg); + } else if (REG_IS_Q(dest_size) && REG_IS_Q(src_size)) { + host_x86_MOVQ_XREG_XREG(block, dest_reg, src_reg); + } +# ifdef RECOMPILER_DEBUG + else + fatal("MOV %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real); +# endif + return 0; +} +static int +codegen_MOV_IMM(codeblock_t *block, uop_t *uop) +{ + int dest_reg = HOST_REG_GET(uop->dest_reg_a_real); + int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real); + + if (REG_IS_L(dest_size)) { + host_x86_MOV32_REG_IMM(block, dest_reg, uop->imm_data); + } else if (REG_IS_W(dest_size)) { + host_x86_MOV16_REG_IMM(block, dest_reg, uop->imm_data); + } else if (REG_IS_B(dest_size)) { + host_x86_MOV8_REG_IMM(block, dest_reg, uop->imm_data); + } +# ifdef RECOMPILER_DEBUG + else + fatal("MOV_IMM %02x\n", uop->dest_reg_a_real); +# endif + return 0; +} +static int +codegen_MOV_PTR(codeblock_t *block, uop_t *uop) +{ + host_x86_MOV64_REG_IMM(block, uop->dest_reg_a_real, (uint64_t) uop->p); + return 0; +} +static int +codegen_MOV_REG_PTR(codeblock_t *block, uop_t *uop) +{ + int dest_reg = HOST_REG_GET(uop->dest_reg_a_real); + int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real); + + if (REG_IS_L(dest_size)) { + host_x86_MOV32_REG_ABS(block, dest_reg, uop->p); + } else + fatal("MOV_REG_PTR %02x\n", uop->dest_reg_a_real); + + return 0; +} +static int +codegen_MOVZX_REG_PTR_8(codeblock_t *block, uop_t *uop) +{ + int dest_reg = HOST_REG_GET(uop->dest_reg_a_real); + int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real); + + if (REG_IS_L(dest_size)) { + host_x86_MOVZX_REG_ABS_32_8(block, dest_reg, uop->p); + } else if (REG_IS_W(dest_size)) { + host_x86_MOVZX_REG_ABS_16_8(block, dest_reg, uop->p); + } else if (REG_IS_B(dest_size)) { + host_x86_MOV8_REG_ABS(block, dest_reg, uop->p); + } else + fatal("MOVZX_REG_PTR_8 %02x\n", uop->dest_reg_a_real); + + return 0; +} +static int +codegen_MOVZX_REG_PTR_16(codeblock_t *block, uop_t *uop) +{ + int dest_reg = HOST_REG_GET(uop->dest_reg_a_real); + int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real); + + if (REG_IS_L(dest_size)) { + host_x86_MOVZX_REG_ABS_32_16(block, dest_reg, uop->p); + } else if (REG_IS_W(dest_size)) { + host_x86_MOV16_REG_ABS(block, dest_reg, uop->p); + } else + fatal("MOVZX_REG_PTR_16 %02x\n", uop->dest_reg_a_real); + + return 0; +} +static int +codegen_MOVSX(codeblock_t *block, uop_t *uop) +{ + int dest_reg = HOST_REG_GET(uop->dest_reg_a_real); + int src_reg = HOST_REG_GET(uop->src_reg_a_real); + int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real); + int src_size = IREG_GET_SIZE(uop->src_reg_a_real); + + if (REG_IS_L(dest_size) && REG_IS_W(src_size)) { + host_x86_MOVSX_REG_32_16(block, dest_reg, src_reg); + } else if (REG_IS_L(dest_size) && REG_IS_B(src_size)) { + host_x86_MOVSX_REG_32_8(block, dest_reg, src_reg); + } else if (REG_IS_W(dest_size) && REG_IS_B(src_size)) { + host_x86_MOVSX_REG_16_8(block, dest_reg, src_reg); + } +# ifdef RECOMPILER_DEBUG + else + fatal("MOVSX %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real); +# endif + return 0; +} +static int +codegen_MOVZX(codeblock_t *block, uop_t *uop) +{ + int dest_reg = HOST_REG_GET(uop->dest_reg_a_real); + int src_reg = HOST_REG_GET(uop->src_reg_a_real); + int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real); + int src_size = IREG_GET_SIZE(uop->src_reg_a_real); + + if (REG_IS_Q(dest_size) && REG_IS_L(src_size)) { + host_x86_MOVD_XREG_REG(block, dest_reg, src_reg); + } else if (REG_IS_L(dest_size) && REG_IS_Q(src_size)) { + host_x86_MOVD_REG_XREG(block, dest_reg, src_reg); + } else if (REG_IS_L(dest_size) && REG_IS_W(src_size)) { + host_x86_MOVZX_REG_32_16(block, dest_reg, src_reg); + } else if (REG_IS_L(dest_size) && REG_IS_B(src_size)) { + host_x86_MOVZX_REG_32_8(block, dest_reg, src_reg); + } else if (REG_IS_W(dest_size) && REG_IS_B(src_size)) { + host_x86_MOVZX_REG_16_8(block, dest_reg, src_reg); + } +# ifdef RECOMPILER_DEBUG + else + fatal("MOVZX %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real); +# endif + return 0; +} + +static int +codegen_MOV_DOUBLE_INT(codeblock_t *block, uop_t *uop) +{ + int dest_reg = HOST_REG_GET(uop->dest_reg_a_real); + int src_reg = HOST_REG_GET(uop->src_reg_a_real); + int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real); + int src_size = IREG_GET_SIZE(uop->src_reg_a_real); + + if (REG_IS_D(dest_size) && REG_IS_L(src_size)) { + host_x86_CVTSI2SD_XREG_REG(block, dest_reg, src_reg); + } else if (REG_IS_D(dest_size) && REG_IS_W(src_size)) { + host_x86_MOVSX_REG_32_16(block, REG_ECX, src_reg); + host_x86_CVTSI2SD_XREG_REG(block, dest_reg, REG_ECX); + } else if (REG_IS_D(dest_size) && REG_IS_Q(src_size)) { + host_x86_MOVQ_REG_XREG(block, REG_RCX, src_reg); + host_x86_CVTSI2SD_XREG_REG64(block, dest_reg, REG_RCX); + } +# ifdef RECOMPILER_DEBUG + else + fatal("MOV_DOUBLE_INT %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real); +# endif + return 0; +} +static int +codegen_MOV_INT_DOUBLE(codeblock_t *block, uop_t *uop) +{ + int dest_reg = HOST_REG_GET(uop->dest_reg_a_real); + int src_reg = HOST_REG_GET(uop->src_reg_a_real); + int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real); + int src_size = IREG_GET_SIZE(uop->src_reg_a_real); + + if (REG_IS_L(dest_size) && REG_IS_D(src_size)) { + host_x86_LDMXCSR(block, &cpu_state.new_fp_control); + host_x86_CVTSD2SI_REG_XREG(block, dest_reg, src_reg); + host_x86_LDMXCSR(block, &cpu_state.old_fp_control); + } else if (REG_IS_W(dest_size) && REG_IS_D(src_size)) { + host_x86_LDMXCSR(block, &cpu_state.new_fp_control); + host_x86_CVTSD2SI_REG_XREG(block, REG_ECX, src_reg); + host_x86_MOV16_REG_REG(block, dest_reg, REG_ECX); + host_x86_LDMXCSR(block, &cpu_state.old_fp_control); + } +# ifdef RECOMPILER_DEBUG + else + fatal("MOV_INT_DOUBLE %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real); +# endif + return 0; +} +static int +codegen_MOV_INT_DOUBLE_64(codeblock_t *block, uop_t *uop) +{ + int dest_reg = HOST_REG_GET(uop->dest_reg_a_real); + int src_reg = HOST_REG_GET(uop->src_reg_a_real); + int src_64_reg = HOST_REG_GET(uop->src_reg_b_real); + int tag_reg = HOST_REG_GET(uop->src_reg_c_real); + int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real); + int src_size = IREG_GET_SIZE(uop->src_reg_a_real); + int src_64_size = IREG_GET_SIZE(uop->src_reg_b_real); + + if (REG_IS_Q(dest_size) && REG_IS_D(src_size) && REG_IS_Q(src_64_size)) { + uint32_t *branch_offset; + + /*If TAG_UINT64 is set then the source is MM[]. Otherwise it is a double in ST()*/ + host_x86_MOVQ_XREG_XREG(block, dest_reg, src_64_reg); + host_x86_TEST8_REG(block, tag_reg, tag_reg); + branch_offset = host_x86_JS_long(block); + + host_x86_LDMXCSR(block, &cpu_state.new_fp_control); + host_x86_CVTSD2SI_REG64_XREG(block, REG_RCX, src_reg); + host_x86_LDMXCSR(block, &cpu_state.old_fp_control); + host_x86_MOVQ_XREG_REG(block, dest_reg, REG_RCX); + + *branch_offset = (uint32_t) ((uintptr_t) &block_write_data[block_pos] - (uintptr_t) branch_offset) - 4; + } +# ifdef RECOMPILER_DEBUG + else + fatal("MOV_INT_DOUBLE_64 %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real); +# endif + return 0; +} + +static int +codegen_NOP(UNUSED(codeblock_t *block), UNUSED(uop_t *uop)) +{ + return 0; +} + +static int +codegen_OR(codeblock_t *block, uop_t *uop) +{ + int dest_reg = HOST_REG_GET(uop->dest_reg_a_real); + int src_reg_a = HOST_REG_GET(uop->src_reg_a_real); + int src_reg_b = HOST_REG_GET(uop->src_reg_b_real); + int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real); + int src_size_a = IREG_GET_SIZE(uop->src_reg_a_real); + int src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); + + if (REG_IS_Q(dest_size) && REG_IS_Q(src_size_a) && REG_IS_Q(src_size_b) && uop->dest_reg_a_real == uop->src_reg_a_real) { + host_x86_POR_XREG_XREG(block, dest_reg, src_reg_b); + } else if (REG_IS_L(dest_size) && REG_IS_L(src_size_a) && REG_IS_L(src_size_b)) { + if (dest_reg != src_reg_a) + host_x86_MOV32_REG_REG(block, dest_reg, src_reg_a); + host_x86_OR32_REG_REG(block, dest_reg, src_reg_b); + } else if (REG_IS_W(dest_size) && REG_IS_W(src_size_a) && REG_IS_W(src_size_b)) { + if (dest_reg != src_reg_a) + host_x86_MOV16_REG_REG(block, dest_reg, src_reg_a); + host_x86_OR16_REG_REG(block, dest_reg, src_reg_b); + } else if (REG_IS_B(dest_size) && REG_IS_B(src_size_a) && REG_IS_B(src_size_b)) { + if (dest_reg != src_reg_a) + host_x86_MOV8_REG_REG(block, dest_reg, src_reg_a); + host_x86_OR8_REG_REG(block, dest_reg, src_reg_b); + } +# ifdef RECOMPILER_DEBUG + else + fatal("OR %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real); +# endif + return 0; +} +static int +codegen_OR_IMM(codeblock_t *block, uop_t *uop) +{ + int dest_reg = HOST_REG_GET(uop->dest_reg_a_real); + int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real); + int src_size = IREG_GET_SIZE(uop->src_reg_a_real); + + if (REG_IS_L(dest_size) && REG_IS_L(src_size)) { + host_x86_OR32_REG_IMM(block, dest_reg, uop->imm_data); + } else if (REG_IS_W(dest_size) && REG_IS_W(src_size)) { + host_x86_OR16_REG_IMM(block, dest_reg, uop->imm_data); + } else if (REG_IS_B(dest_size) && REG_IS_B(src_size)) { + host_x86_OR8_REG_IMM(block, dest_reg, uop->imm_data); + } +# ifdef RECOMPILER_DEBUG + else + fatal("OR_IMM %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real); +# endif + return 0; +} + +static int +codegen_PACKSSWB(codeblock_t *block, uop_t *uop) +{ + int dest_reg = HOST_REG_GET(uop->dest_reg_a_real); + int src_reg_b = HOST_REG_GET(uop->src_reg_b_real); + int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real); + int src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); + + if (REG_IS_Q(dest_size) && REG_IS_Q(src_size_b) && uop->dest_reg_a_real == uop->src_reg_a_real) { + host_x86_PACKSSWB_XREG_XREG(block, dest_reg, src_reg_b); + } +# ifdef RECOMPILER_DEBUG + else + fatal("PACKSSWB %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real); +# endif + return 0; +} +static int +codegen_PACKSSDW(codeblock_t *block, uop_t *uop) +{ + int dest_reg = HOST_REG_GET(uop->dest_reg_a_real); + int src_reg_b = HOST_REG_GET(uop->src_reg_b_real); + int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real); + int src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); + + if (REG_IS_Q(dest_size) && REG_IS_Q(src_size_b) && uop->dest_reg_a_real == uop->src_reg_a_real) { + host_x86_PACKSSDW_XREG_XREG(block, dest_reg, src_reg_b); + } +# ifdef RECOMPILER_DEBUG + else + fatal("PACKSSDW %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real); +# endif + return 0; +} +static int +codegen_PACKUSWB(codeblock_t *block, uop_t *uop) +{ + int dest_reg = HOST_REG_GET(uop->dest_reg_a_real); + int src_reg_b = HOST_REG_GET(uop->src_reg_b_real); + int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real); + int src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); + + if (REG_IS_Q(dest_size) && REG_IS_Q(src_size_b) && uop->dest_reg_a_real == uop->src_reg_a_real) { + host_x86_PACKUSWB_XREG_XREG(block, dest_reg, src_reg_b); + } +# ifdef RECOMPILER_DEBUG + else + fatal("PACKUSWB %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real); +# endif + return 0; +} + +static int +codegen_PADDB(codeblock_t *block, uop_t *uop) +{ + int dest_reg = HOST_REG_GET(uop->dest_reg_a_real); + int src_reg_b = HOST_REG_GET(uop->src_reg_b_real); + int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real); + int src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); + + if (REG_IS_Q(dest_size) && REG_IS_Q(src_size_b) && uop->dest_reg_a_real == uop->src_reg_a_real) { + host_x86_PADDB_XREG_XREG(block, dest_reg, src_reg_b); + } +# ifdef RECOMPILER_DEBUG + else + fatal("PADDB %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real); +# endif + return 0; +} +static int +codegen_PADDW(codeblock_t *block, uop_t *uop) +{ + int dest_reg = HOST_REG_GET(uop->dest_reg_a_real); + int src_reg_b = HOST_REG_GET(uop->src_reg_b_real); + int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real); + int src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); + + if (REG_IS_Q(dest_size) && REG_IS_Q(src_size_b) && uop->dest_reg_a_real == uop->src_reg_a_real) { + host_x86_PADDW_XREG_XREG(block, dest_reg, src_reg_b); + } +# ifdef RECOMPILER_DEBUG + else + fatal("PADDW %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real); +# endif + return 0; +} +static int +codegen_PADDD(codeblock_t *block, uop_t *uop) +{ + int dest_reg = HOST_REG_GET(uop->dest_reg_a_real); + int src_reg_b = HOST_REG_GET(uop->src_reg_b_real); + int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real); + int src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); + + if (REG_IS_Q(dest_size) && REG_IS_Q(src_size_b) && uop->dest_reg_a_real == uop->src_reg_a_real) { + host_x86_PADDD_XREG_XREG(block, dest_reg, src_reg_b); + } +# ifdef RECOMPILER_DEBUG + else + fatal("PADDD %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real); +# endif + return 0; +} +static int +codegen_PADDSB(codeblock_t *block, uop_t *uop) +{ + int dest_reg = HOST_REG_GET(uop->dest_reg_a_real); + int src_reg_b = HOST_REG_GET(uop->src_reg_b_real); + int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real); + int src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); + + if (REG_IS_Q(dest_size) && REG_IS_Q(src_size_b) && uop->dest_reg_a_real == uop->src_reg_a_real) { + host_x86_PADDSB_XREG_XREG(block, dest_reg, src_reg_b); + } +# ifdef RECOMPILER_DEBUG + else + fatal("PADDSB %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real); +# endif + return 0; +} +static int +codegen_PADDSW(codeblock_t *block, uop_t *uop) +{ + int dest_reg = HOST_REG_GET(uop->dest_reg_a_real); + int src_reg_b = HOST_REG_GET(uop->src_reg_b_real); + int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real); + int src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); + + if (REG_IS_Q(dest_size) && REG_IS_Q(src_size_b) && uop->dest_reg_a_real == uop->src_reg_a_real) { + host_x86_PADDSW_XREG_XREG(block, dest_reg, src_reg_b); + } +# ifdef RECOMPILER_DEBUG + else + fatal("PADDSW %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real); +# endif + return 0; +} +static int +codegen_PADDUSB(codeblock_t *block, uop_t *uop) +{ + int dest_reg = HOST_REG_GET(uop->dest_reg_a_real); + int src_reg_b = HOST_REG_GET(uop->src_reg_b_real); + int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real); + int src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); + + if (REG_IS_Q(dest_size) && REG_IS_Q(src_size_b) && uop->dest_reg_a_real == uop->src_reg_a_real) { + host_x86_PADDUSB_XREG_XREG(block, dest_reg, src_reg_b); + } +# ifdef RECOMPILER_DEBUG + else + fatal("PADDUSB %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real); +# endif + return 0; +} +static int +codegen_PADDUSW(codeblock_t *block, uop_t *uop) +{ + int dest_reg = HOST_REG_GET(uop->dest_reg_a_real); + int src_reg_b = HOST_REG_GET(uop->src_reg_b_real); + int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real); + int src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); + + if (REG_IS_Q(dest_size) && REG_IS_Q(src_size_b) && uop->dest_reg_a_real == uop->src_reg_a_real) { + host_x86_PADDUSW_XREG_XREG(block, dest_reg, src_reg_b); + } +# ifdef RECOMPILER_DEBUG + else + fatal("PADDUSW %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real); +# endif + return 0; +} + +static int +codegen_PCMPEQB(codeblock_t *block, uop_t *uop) +{ + int dest_reg = HOST_REG_GET(uop->dest_reg_a_real); + int src_reg_b = HOST_REG_GET(uop->src_reg_b_real); + int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real); + int src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); + + if (REG_IS_Q(dest_size) && REG_IS_Q(src_size_b) && uop->dest_reg_a_real == uop->src_reg_a_real) { + host_x86_PCMPEQB_XREG_XREG(block, dest_reg, src_reg_b); + } +# ifdef RECOMPILER_DEBUG + else + fatal("PCMPEQB %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real); +# endif + return 0; +} +static int +codegen_PCMPEQW(codeblock_t *block, uop_t *uop) +{ + int dest_reg = HOST_REG_GET(uop->dest_reg_a_real); + int src_reg_b = HOST_REG_GET(uop->src_reg_b_real); + int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real); + int src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); + + if (REG_IS_Q(dest_size) && REG_IS_Q(src_size_b) && uop->dest_reg_a_real == uop->src_reg_a_real) { + host_x86_PCMPEQW_XREG_XREG(block, dest_reg, src_reg_b); + } +# ifdef RECOMPILER_DEBUG + else + fatal("PCMPEQW %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real); +# endif + return 0; +} +static int +codegen_PCMPEQD(codeblock_t *block, uop_t *uop) +{ + int dest_reg = HOST_REG_GET(uop->dest_reg_a_real); + int src_reg_b = HOST_REG_GET(uop->src_reg_b_real); + int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real); + int src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); + + if (REG_IS_Q(dest_size) && REG_IS_Q(src_size_b) && uop->dest_reg_a_real == uop->src_reg_a_real) { + host_x86_PCMPEQD_XREG_XREG(block, dest_reg, src_reg_b); + } +# ifdef RECOMPILER_DEBUG + else + fatal("PCMPEQD %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real); +# endif + return 0; +} +static int +codegen_PCMPGTB(codeblock_t *block, uop_t *uop) +{ + int dest_reg = HOST_REG_GET(uop->dest_reg_a_real); + int src_reg_b = HOST_REG_GET(uop->src_reg_b_real); + int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real); + int src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); + + if (REG_IS_Q(dest_size) && REG_IS_Q(src_size_b) && uop->dest_reg_a_real == uop->src_reg_a_real) { + host_x86_PCMPGTB_XREG_XREG(block, dest_reg, src_reg_b); + } +# ifdef RECOMPILER_DEBUG + else + fatal("PCMPGTB %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real); +# endif + return 0; +} +static int +codegen_PCMPGTW(codeblock_t *block, uop_t *uop) +{ + int dest_reg = HOST_REG_GET(uop->dest_reg_a_real); + int src_reg_b = HOST_REG_GET(uop->src_reg_b_real); + int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real); + int src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); + + if (REG_IS_Q(dest_size) && REG_IS_Q(src_size_b) && uop->dest_reg_a_real == uop->src_reg_a_real) { + host_x86_PCMPGTW_XREG_XREG(block, dest_reg, src_reg_b); + } +# ifdef RECOMPILER_DEBUG + else + fatal("PCMPGTW %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real); +# endif + return 0; +} +static int +codegen_PCMPGTD(codeblock_t *block, uop_t *uop) +{ + int dest_reg = HOST_REG_GET(uop->dest_reg_a_real); + int src_reg_b = HOST_REG_GET(uop->src_reg_b_real); + int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real); + int src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); + + if (REG_IS_Q(dest_size) && REG_IS_Q(src_size_b) && uop->dest_reg_a_real == uop->src_reg_a_real) { + host_x86_PCMPGTD_XREG_XREG(block, dest_reg, src_reg_b); + } +# ifdef RECOMPILER_DEBUG + else + fatal("PCMPGTD %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real); +# endif + return 0; +} + +static int +codegen_PF2ID(codeblock_t *block, uop_t *uop) +{ + int dest_reg = HOST_REG_GET(uop->dest_reg_a_real); + int src_reg_a = HOST_REG_GET(uop->src_reg_a_real); + int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real); + int src_size_a = IREG_GET_SIZE(uop->src_reg_a_real); + + if (REG_IS_Q(dest_size) && REG_IS_Q(src_size_a)) { + host_x86_LDMXCSR(block, &cpu_state.trunc_fp_control); + host_x86_CVTPS2DQ_XREG_XREG(block, dest_reg, src_reg_a); + host_x86_LDMXCSR(block, &cpu_state.old_fp_control); + } +# ifdef RECOMPILER_DEBUG + else + fatal("PF2ID %02x %02x\n", uop->dest_reg_a_real); +# endif + return 0; +} +static int +codegen_PFADD(codeblock_t *block, uop_t *uop) +{ + int dest_reg = HOST_REG_GET(uop->dest_reg_a_real); + int src_reg_b = HOST_REG_GET(uop->src_reg_b_real); + int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real); + int src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); + + if (REG_IS_Q(dest_size) && REG_IS_Q(src_size_b) && uop->dest_reg_a_real == uop->src_reg_a_real) { + host_x86_ADDPS_XREG_XREG(block, dest_reg, src_reg_b); + } +# ifdef RECOMPILER_DEBUG + else + fatal("PFADD %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real); +# endif + return 0; +} +static int +codegen_PFCMPEQ(codeblock_t *block, uop_t *uop) +{ + int dest_reg = HOST_REG_GET(uop->dest_reg_a_real); + int src_reg_b = HOST_REG_GET(uop->src_reg_b_real); + int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real); + int src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); + + if (REG_IS_Q(dest_size) && REG_IS_Q(src_size_b) && uop->dest_reg_a_real == uop->src_reg_a_real) { + host_x86_CMPPS_XREG_XREG(block, dest_reg, src_reg_b, CMPPS_EQ); + } +# ifdef RECOMPILER_DEBUG + else + fatal("PFCMPEQ %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real); +# endif + return 0; +} +static int +codegen_PFCMPGE(codeblock_t *block, uop_t *uop) +{ + int dest_reg = HOST_REG_GET(uop->dest_reg_a_real); + int src_reg_b = HOST_REG_GET(uop->src_reg_b_real); + int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real); + int src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); + + if (REG_IS_Q(dest_size) && REG_IS_Q(src_size_b) && uop->dest_reg_a_real == uop->src_reg_a_real) { + host_x86_CMPPS_XREG_XREG(block, dest_reg, src_reg_b, CMPPS_NLT); + } +# ifdef RECOMPILER_DEBUG + else + fatal("PFCMPGE %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real); +# endif + return 0; +} +static int +codegen_PFCMPGT(codeblock_t *block, uop_t *uop) +{ + int dest_reg = HOST_REG_GET(uop->dest_reg_a_real); + int src_reg_b = HOST_REG_GET(uop->src_reg_b_real); + int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real); + int src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); + + if (REG_IS_Q(dest_size) && REG_IS_Q(src_size_b) && uop->dest_reg_a_real == uop->src_reg_a_real) { + host_x86_CMPPS_XREG_XREG(block, dest_reg, src_reg_b, CMPPS_NLE); + } +# ifdef RECOMPILER_DEBUG + else + fatal("PFCMPGT %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real); +# endif + return 0; +} +static int +codegen_PFMAX(codeblock_t *block, uop_t *uop) +{ + int dest_reg = HOST_REG_GET(uop->dest_reg_a_real); + int src_reg_b = HOST_REG_GET(uop->src_reg_b_real); + int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real); + int src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); + + if (REG_IS_Q(dest_size) && REG_IS_Q(src_size_b) && uop->dest_reg_a_real == uop->src_reg_a_real) { + host_x86_MAXPS_XREG_XREG(block, dest_reg, src_reg_b); + } +# ifdef RECOMPILER_DEBUG + else + fatal("PFMAX %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real); +# endif + return 0; +} +static int +codegen_PFMIN(codeblock_t *block, uop_t *uop) +{ + int dest_reg = HOST_REG_GET(uop->dest_reg_a_real); + int src_reg_b = HOST_REG_GET(uop->src_reg_b_real); + int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real); + int src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); + + if (REG_IS_Q(dest_size) && REG_IS_Q(src_size_b) && uop->dest_reg_a_real == uop->src_reg_a_real) { + host_x86_MINPS_XREG_XREG(block, dest_reg, src_reg_b); + } +# ifdef RECOMPILER_DEBUG + else + fatal("PFMIN %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real); +# endif + return 0; +} +static int +codegen_PFMUL(codeblock_t *block, uop_t *uop) +{ + int dest_reg = HOST_REG_GET(uop->dest_reg_a_real); + int src_reg_b = HOST_REG_GET(uop->src_reg_b_real); + int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real); + int src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); + + if (REG_IS_Q(dest_size) && REG_IS_Q(src_size_b) && uop->dest_reg_a_real == uop->src_reg_a_real) { + host_x86_MULPS_XREG_XREG(block, dest_reg, src_reg_b); + } +# ifdef RECOMPILER_DEBUG + else + fatal("PFMUL %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real); +# endif + return 0; +} +static int +codegen_PFRCP(codeblock_t *block, uop_t *uop) +{ + int dest_reg = HOST_REG_GET(uop->dest_reg_a_real); + int src_reg_a = HOST_REG_GET(uop->src_reg_a_real); + int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real); + int src_size_a = IREG_GET_SIZE(uop->src_reg_a_real); + + if (REG_IS_Q(dest_size) && REG_IS_Q(src_size_a)) { + /*TODO: This could be improved (use RCPSS + iteration)*/ + host_x86_MOV32_REG_IMM(block, REG_ECX, 1); + host_x86_MOVQ_XREG_XREG(block, REG_XMM_TEMP, src_reg_a); + host_x86_CVTSI2SS_XREG_REG(block, dest_reg, REG_ECX); + host_x86_DIVSS_XREG_XREG(block, dest_reg, REG_XMM_TEMP); + host_x86_UNPCKLPS_XREG_XREG(block, dest_reg, dest_reg); + } +# ifdef RECOMPILER_DEBUG + else + fatal("PFRCP %02x %02x\n", uop->dest_reg_a_real); +# endif + return 0; +} +static int +codegen_PFRSQRT(codeblock_t *block, uop_t *uop) +{ + int dest_reg = HOST_REG_GET(uop->dest_reg_a_real); + int src_reg_a = HOST_REG_GET(uop->src_reg_a_real); + int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real); + int src_size_a = IREG_GET_SIZE(uop->src_reg_a_real); + + if (REG_IS_Q(dest_size) && REG_IS_Q(src_size_a)) { + /*TODO: This could be improved (use RSQRTSS + iteration)*/ + host_x86_SQRTSS_XREG_XREG(block, REG_XMM_TEMP, src_reg_a); + host_x86_MOV32_REG_IMM(block, REG_ECX, 1); + host_x86_CVTSI2SS_XREG_REG(block, dest_reg, REG_ECX); + host_x86_DIVSS_XREG_XREG(block, dest_reg, REG_XMM_TEMP); + host_x86_UNPCKLPS_XREG_XREG(block, dest_reg, dest_reg); + } +# ifdef RECOMPILER_DEBUG + else + fatal("PFRSQRT %02x %02x\n", uop->dest_reg_a_real); +# endif + return 0; +} +static int +codegen_PFSUB(codeblock_t *block, uop_t *uop) +{ + int dest_reg = HOST_REG_GET(uop->dest_reg_a_real); + int src_reg_a = HOST_REG_GET(uop->src_reg_a_real); + int src_reg_b = HOST_REG_GET(uop->src_reg_b_real); + int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real); + int src_size_a = IREG_GET_SIZE(uop->src_reg_a_real); + int src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); + + if (REG_IS_Q(dest_size) && REG_IS_Q(src_size_b) && uop->dest_reg_a_real == uop->src_reg_a_real) { + host_x86_SUBPS_XREG_XREG(block, dest_reg, src_reg_b); + } else if (REG_IS_Q(dest_size) && REG_IS_Q(src_size_a) && REG_IS_Q(src_size_b)) { + host_x86_MOVQ_XREG_XREG(block, REG_XMM_TEMP, src_reg_a); + host_x86_SUBPS_XREG_XREG(block, REG_XMM_TEMP, src_reg_b); + host_x86_MOVQ_XREG_XREG(block, dest_reg, REG_XMM_TEMP); + } +# ifdef RECOMPILER_DEBUG + else + fatal("PFSUB %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real); +# endif + return 0; +} +static int +codegen_PI2FD(codeblock_t *block, uop_t *uop) +{ + int dest_reg = HOST_REG_GET(uop->dest_reg_a_real); + int src_reg_a = HOST_REG_GET(uop->src_reg_a_real); + int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real); + int src_size_a = IREG_GET_SIZE(uop->src_reg_a_real); + + if (REG_IS_Q(dest_size) && REG_IS_Q(src_size_a)) { + host_x86_CVTDQ2PS_XREG_XREG(block, dest_reg, src_reg_a); + } +# ifdef RECOMPILER_DEBUG + else + fatal("PI2FD %02x %02x\n", uop->dest_reg_a_real); +# endif + return 0; +} + +static int +codegen_PMADDWD(codeblock_t *block, uop_t *uop) +{ + int dest_reg = HOST_REG_GET(uop->dest_reg_a_real); + int src_reg_b = HOST_REG_GET(uop->src_reg_b_real); + int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real); + int src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); + + if (REG_IS_Q(dest_size) && REG_IS_Q(src_size_b) && uop->dest_reg_a_real == uop->src_reg_a_real) { + host_x86_PMADDWD_XREG_XREG(block, dest_reg, src_reg_b); + } +# ifdef RECOMPILER_DEBUG + else + fatal("PMULHW %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real); +# endif + return 0; +} +static int +codegen_PMULHW(codeblock_t *block, uop_t *uop) +{ + int dest_reg = HOST_REG_GET(uop->dest_reg_a_real); + int src_reg_b = HOST_REG_GET(uop->src_reg_b_real); + int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real); + int src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); + + if (REG_IS_Q(dest_size) && REG_IS_Q(src_size_b) && uop->dest_reg_a_real == uop->src_reg_a_real) { + host_x86_PMULHW_XREG_XREG(block, dest_reg, src_reg_b); + } +# ifdef RECOMPILER_DEBUG + else + fatal("PMULHW %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real); +# endif + return 0; +} +static int +codegen_PMULLW(codeblock_t *block, uop_t *uop) +{ + int dest_reg = HOST_REG_GET(uop->dest_reg_a_real); + int src_reg_b = HOST_REG_GET(uop->src_reg_b_real); + int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real); + int src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); + + if (REG_IS_Q(dest_size) && REG_IS_Q(src_size_b) && uop->dest_reg_a_real == uop->src_reg_a_real) { + host_x86_PMULLW_XREG_XREG(block, dest_reg, src_reg_b); + } +# ifdef RECOMPILER_DEBUG + else + fatal("PMULLW %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real); +# endif + return 0; +} + +static int +codegen_PSLLW_IMM(codeblock_t *block, uop_t *uop) +{ + int dest_reg = HOST_REG_GET(uop->dest_reg_a_real); + int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real); + + if (REG_IS_Q(dest_size) && uop->dest_reg_a_real == uop->src_reg_a_real) { + host_x86_PSLLW_XREG_IMM(block, dest_reg, uop->imm_data); + } +# ifdef RECOMPILER_DEBUG + else + fatal("PSLLW_IMM %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real); +# endif + return 0; +} +static int +codegen_PSLLD_IMM(codeblock_t *block, uop_t *uop) +{ + int dest_reg = HOST_REG_GET(uop->dest_reg_a_real); + int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real); + + if (REG_IS_Q(dest_size) && uop->dest_reg_a_real == uop->src_reg_a_real) { + host_x86_PSLLD_XREG_IMM(block, dest_reg, uop->imm_data); + } +# ifdef RECOMPILER_DEBUG + else + fatal("PSLLD_IMM %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real); +# endif + return 0; +} +static int +codegen_PSLLQ_IMM(codeblock_t *block, uop_t *uop) +{ + int dest_reg = HOST_REG_GET(uop->dest_reg_a_real); + int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real); + + if (REG_IS_Q(dest_size) && uop->dest_reg_a_real == uop->src_reg_a_real) { + host_x86_PSLLQ_XREG_IMM(block, dest_reg, uop->imm_data); + } +# ifdef RECOMPILER_DEBUG + else + fatal("PSLLQ_IMM %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real); +# endif + return 0; +} +static int +codegen_PSRAW_IMM(codeblock_t *block, uop_t *uop) +{ + int dest_reg = HOST_REG_GET(uop->dest_reg_a_real); + int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real); + + if (REG_IS_Q(dest_size) && uop->dest_reg_a_real == uop->src_reg_a_real) { + host_x86_PSRAW_XREG_IMM(block, dest_reg, uop->imm_data); + } +# ifdef RECOMPILER_DEBUG + else + fatal("PSRAW_IMM %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real); +# endif + return 0; +} +static int +codegen_PSRAD_IMM(codeblock_t *block, uop_t *uop) +{ + int dest_reg = HOST_REG_GET(uop->dest_reg_a_real); + int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real); + + if (REG_IS_Q(dest_size) && uop->dest_reg_a_real == uop->src_reg_a_real) { + host_x86_PSRAD_XREG_IMM(block, dest_reg, uop->imm_data); + } +# ifdef RECOMPILER_DEBUG + else + fatal("PSRAD_IMM %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real); +# endif + return 0; +} +static int +codegen_PSRAQ_IMM(codeblock_t *block, uop_t *uop) +{ + int dest_reg = HOST_REG_GET(uop->dest_reg_a_real); + int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real); + + if (REG_IS_Q(dest_size) && uop->dest_reg_a_real == uop->src_reg_a_real) { + host_x86_PSRAQ_XREG_IMM(block, dest_reg, uop->imm_data); + } +# ifdef RECOMPILER_DEBUG + else + fatal("PSRAQ_IMM %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real); +# endif + return 0; +} +static int +codegen_PSRLW_IMM(codeblock_t *block, uop_t *uop) +{ + int dest_reg = HOST_REG_GET(uop->dest_reg_a_real); + int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real); + + if (REG_IS_Q(dest_size) && uop->dest_reg_a_real == uop->src_reg_a_real) { + host_x86_PSRLW_XREG_IMM(block, dest_reg, uop->imm_data); + } +# ifdef RECOMPILER_DEBUG + else + fatal("PSRLW_IMM %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real); +# endif + return 0; +} +static int +codegen_PSRLD_IMM(codeblock_t *block, uop_t *uop) +{ + int dest_reg = HOST_REG_GET(uop->dest_reg_a_real); + int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real); + + if (REG_IS_Q(dest_size) && uop->dest_reg_a_real == uop->src_reg_a_real) { + host_x86_PSRLD_XREG_IMM(block, dest_reg, uop->imm_data); + } +# ifdef RECOMPILER_DEBUG + else + fatal("PSRLD_IMM %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real); +# endif + return 0; +} +static int +codegen_PSRLQ_IMM(codeblock_t *block, uop_t *uop) +{ + int dest_reg = HOST_REG_GET(uop->dest_reg_a_real); + int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real); + + if (REG_IS_Q(dest_size) && uop->dest_reg_a_real == uop->src_reg_a_real) { + host_x86_PSRLQ_XREG_IMM(block, dest_reg, uop->imm_data); + } +# ifdef RECOMPILER_DEBUG + else + fatal("PSRLQ_IMM %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real); +# endif + return 0; +} + +static int +codegen_PSUBB(codeblock_t *block, uop_t *uop) +{ + int dest_reg = HOST_REG_GET(uop->dest_reg_a_real); + int src_reg_b = HOST_REG_GET(uop->src_reg_b_real); + int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real); + int src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); + + if (REG_IS_Q(dest_size) && REG_IS_Q(src_size_b) && uop->dest_reg_a_real == uop->src_reg_a_real) { + host_x86_PSUBB_XREG_XREG(block, dest_reg, src_reg_b); + } +# ifdef RECOMPILER_DEBUG + else + fatal("PSUBB %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real); +# endif + return 0; +} +static int +codegen_PSUBW(codeblock_t *block, uop_t *uop) +{ + int dest_reg = HOST_REG_GET(uop->dest_reg_a_real); + int src_reg_b = HOST_REG_GET(uop->src_reg_b_real); + int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real); + int src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); + + if (REG_IS_Q(dest_size) && REG_IS_Q(src_size_b) && uop->dest_reg_a_real == uop->src_reg_a_real) { + host_x86_PSUBW_XREG_XREG(block, dest_reg, src_reg_b); + } +# ifdef RECOMPILER_DEBUG + else + fatal("PSUBW %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real); +# endif + return 0; +} +static int +codegen_PSUBD(codeblock_t *block, uop_t *uop) +{ + int dest_reg = HOST_REG_GET(uop->dest_reg_a_real); + int src_reg_b = HOST_REG_GET(uop->src_reg_b_real); + int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real); + int src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); + + if (REG_IS_Q(dest_size) && REG_IS_Q(src_size_b) && uop->dest_reg_a_real == uop->src_reg_a_real) { + host_x86_PSUBD_XREG_XREG(block, dest_reg, src_reg_b); + } +# ifdef RECOMPILER_DEBUG + else + fatal("PSUBD %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real); +# endif + return 0; +} +static int +codegen_PSUBSB(codeblock_t *block, uop_t *uop) +{ + int dest_reg = HOST_REG_GET(uop->dest_reg_a_real); + int src_reg_b = HOST_REG_GET(uop->src_reg_b_real); + int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real); + int src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); + + if (REG_IS_Q(dest_size) && REG_IS_Q(src_size_b) && uop->dest_reg_a_real == uop->src_reg_a_real) { + host_x86_PSUBSB_XREG_XREG(block, dest_reg, src_reg_b); + } +# ifdef RECOMPILER_DEBUG + else + fatal("PSUBSB %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real); +# endif + return 0; +} +static int +codegen_PSUBSW(codeblock_t *block, uop_t *uop) +{ + int dest_reg = HOST_REG_GET(uop->dest_reg_a_real); + int src_reg_b = HOST_REG_GET(uop->src_reg_b_real); + int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real); + int src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); + + if (REG_IS_Q(dest_size) && REG_IS_Q(src_size_b) && uop->dest_reg_a_real == uop->src_reg_a_real) { + host_x86_PSUBSW_XREG_XREG(block, dest_reg, src_reg_b); + } +# ifdef RECOMPILER_DEBUG + else + fatal("PSUBSW %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real); +# endif + return 0; +} +static int +codegen_PSUBUSB(codeblock_t *block, uop_t *uop) +{ + int dest_reg = HOST_REG_GET(uop->dest_reg_a_real); + int src_reg_b = HOST_REG_GET(uop->src_reg_b_real); + int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real); + int src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); + + if (REG_IS_Q(dest_size) && REG_IS_Q(src_size_b) && uop->dest_reg_a_real == uop->src_reg_a_real) { + host_x86_PSUBUSB_XREG_XREG(block, dest_reg, src_reg_b); + } +# ifdef RECOMPILER_DEBUG + else + fatal("PSUBUSB %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real); +# endif + return 0; +} +static int +codegen_PSUBUSW(codeblock_t *block, uop_t *uop) +{ + int dest_reg = HOST_REG_GET(uop->dest_reg_a_real); + int src_reg_b = HOST_REG_GET(uop->src_reg_b_real); + int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real); + int src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); + + if (REG_IS_Q(dest_size) && REG_IS_Q(src_size_b) && uop->dest_reg_a_real == uop->src_reg_a_real) { + host_x86_PSUBUSW_XREG_XREG(block, dest_reg, src_reg_b); + } +# ifdef RECOMPILER_DEBUG + else + fatal("PSUBUSW %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real); +# endif + return 0; +} + +static int +codegen_PUNPCKHBW(codeblock_t *block, uop_t *uop) +{ + int dest_reg = HOST_REG_GET(uop->dest_reg_a_real); + int src_reg_b = HOST_REG_GET(uop->src_reg_b_real); + int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real); + int src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); + + if (REG_IS_Q(dest_size) && REG_IS_Q(src_size_b) && uop->dest_reg_a_real == uop->src_reg_a_real) { + host_x86_PUNPCKHBW_XREG_XREG(block, dest_reg, src_reg_b); + } +# ifdef RECOMPILER_DEBUG + else + fatal("PUNPCKHBW %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real); +# endif + return 0; +} +static int +codegen_PUNPCKHWD(codeblock_t *block, uop_t *uop) +{ + int dest_reg = HOST_REG_GET(uop->dest_reg_a_real); + int src_reg_b = HOST_REG_GET(uop->src_reg_b_real); + int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real); + int src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); + + if (REG_IS_Q(dest_size) && REG_IS_Q(src_size_b) && uop->dest_reg_a_real == uop->src_reg_a_real) { + host_x86_PUNPCKHWD_XREG_XREG(block, dest_reg, src_reg_b); + } +# ifdef RECOMPILER_DEBUG + else + fatal("PUNPCKHWD %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real); +# endif + return 0; +} +static int +codegen_PUNPCKHDQ(codeblock_t *block, uop_t *uop) +{ + int dest_reg = HOST_REG_GET(uop->dest_reg_a_real); + int src_reg_b = HOST_REG_GET(uop->src_reg_b_real); + int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real); + int src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); + + if (REG_IS_Q(dest_size) && REG_IS_Q(src_size_b) && uop->dest_reg_a_real == uop->src_reg_a_real) { + host_x86_PUNPCKHDQ_XREG_XREG(block, dest_reg, src_reg_b); + } +# ifdef RECOMPILER_DEBUG + else + fatal("PUNPCKHDQ %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real); +# endif + return 0; +} +static int +codegen_PUNPCKLBW(codeblock_t *block, uop_t *uop) +{ + int dest_reg = HOST_REG_GET(uop->dest_reg_a_real); + int src_reg_b = HOST_REG_GET(uop->src_reg_b_real); + int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real); + int src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); + + if (REG_IS_Q(dest_size) && REG_IS_Q(src_size_b) && uop->dest_reg_a_real == uop->src_reg_a_real) { + host_x86_PUNPCKLBW_XREG_XREG(block, dest_reg, src_reg_b); + } +# ifdef RECOMPILER_DEBUG + else + fatal("PUNPCKLBW %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real); +# endif + return 0; +} +static int +codegen_PUNPCKLWD(codeblock_t *block, uop_t *uop) +{ + int dest_reg = HOST_REG_GET(uop->dest_reg_a_real); + int src_reg_b = HOST_REG_GET(uop->src_reg_b_real); + int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real); + int src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); + + if (REG_IS_Q(dest_size) && REG_IS_Q(src_size_b) && uop->dest_reg_a_real == uop->src_reg_a_real) { + host_x86_PUNPCKLWD_XREG_XREG(block, dest_reg, src_reg_b); + } +# ifdef RECOMPILER_DEBUG + else + fatal("PUNPCKLWD %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real); +# endif + return 0; +} +static int +codegen_PUNPCKLDQ(codeblock_t *block, uop_t *uop) +{ + int dest_reg = HOST_REG_GET(uop->dest_reg_a_real); + int src_reg_b = HOST_REG_GET(uop->src_reg_b_real); + int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real); + int src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); + + if (REG_IS_Q(dest_size) && REG_IS_Q(src_size_b) && uop->dest_reg_a_real == uop->src_reg_a_real) { + host_x86_PUNPCKLDQ_XREG_XREG(block, dest_reg, src_reg_b); + } +# ifdef RECOMPILER_DEBUG + else + fatal("PUNPCKLDQ %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real); +# endif + return 0; +} + +static int +codegen_ROL(codeblock_t *block, uop_t *uop) +{ + int dest_reg = HOST_REG_GET(uop->dest_reg_a_real); + int src_reg = HOST_REG_GET(uop->src_reg_a_real); + int shift_reg = HOST_REG_GET(uop->src_reg_b_real); + int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real); + int src_size = IREG_GET_SIZE(uop->src_reg_a_real); + + host_x86_MOV32_REG_REG(block, REG_ECX, shift_reg); + if (REG_IS_L(dest_size) && REG_IS_L(src_size)) { + if (uop->dest_reg_a_real != uop->src_reg_a_real) + host_x86_MOV32_REG_REG(block, dest_reg, src_reg); + host_x86_ROL32_CL(block, dest_reg); + } else if (REG_IS_W(dest_size) && REG_IS_W(src_size)) { + if (uop->dest_reg_a_real != uop->src_reg_a_real) + host_x86_MOV16_REG_REG(block, dest_reg, src_reg); + host_x86_ROL16_CL(block, dest_reg); + } else if (REG_IS_B(dest_size) && REG_IS_B(src_size)) { + if (uop->dest_reg_a_real != uop->src_reg_a_real) + host_x86_MOV8_REG_REG(block, dest_reg, src_reg); + host_x86_ROL8_CL(block, dest_reg); + } +# ifdef RECOMPILER_DEBUG + else + fatal("ROL %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real); +# endif + return 0; +} +static int +codegen_ROL_IMM(codeblock_t *block, uop_t *uop) +{ + int dest_reg = HOST_REG_GET(uop->dest_reg_a_real); + int src_reg = HOST_REG_GET(uop->src_reg_a_real); + int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real); + int src_size = IREG_GET_SIZE(uop->src_reg_a_real); + + if (REG_IS_L(dest_size) && REG_IS_L(src_size)) { + if (uop->dest_reg_a_real != uop->src_reg_a_real) + host_x86_MOV32_REG_REG(block, dest_reg, src_reg); + host_x86_ROL32_IMM(block, dest_reg, uop->imm_data); + } else if (REG_IS_W(dest_size) && REG_IS_W(src_size)) { + if (uop->dest_reg_a_real != uop->src_reg_a_real) + host_x86_MOV16_REG_REG(block, dest_reg, src_reg); + host_x86_ROL16_IMM(block, dest_reg, uop->imm_data); + } else if (REG_IS_B(dest_size) && REG_IS_B(src_size)) { + if (uop->dest_reg_a_real != uop->src_reg_a_real) + host_x86_MOV8_REG_REG(block, dest_reg, src_reg); + host_x86_ROL8_IMM(block, dest_reg, uop->imm_data); + } +# ifdef RECOMPILER_DEBUG + else + fatal("ROL_IMM %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real); +# endif + return 0; +} +static int +codegen_ROR(codeblock_t *block, uop_t *uop) +{ + int dest_reg = HOST_REG_GET(uop->dest_reg_a_real); + int src_reg = HOST_REG_GET(uop->src_reg_a_real); + int shift_reg = HOST_REG_GET(uop->src_reg_b_real); + int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real); + int src_size = IREG_GET_SIZE(uop->src_reg_a_real); + + host_x86_MOV32_REG_REG(block, REG_ECX, shift_reg); + if (REG_IS_L(dest_size) && REG_IS_L(src_size)) { + if (uop->dest_reg_a_real != uop->src_reg_a_real) + host_x86_MOV32_REG_REG(block, dest_reg, src_reg); + host_x86_ROR32_CL(block, dest_reg); + } else if (REG_IS_W(dest_size) && REG_IS_W(src_size)) { + if (uop->dest_reg_a_real != uop->src_reg_a_real) + host_x86_MOV16_REG_REG(block, dest_reg, src_reg); + host_x86_ROR16_CL(block, dest_reg); + } else if (REG_IS_B(dest_size) && REG_IS_B(src_size)) { + if (uop->dest_reg_a_real != uop->src_reg_a_real) + host_x86_MOV8_REG_REG(block, dest_reg, src_reg); + host_x86_ROR8_CL(block, dest_reg); + } +# ifdef RECOMPILER_DEBUG + else + fatal("ROR %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real); +# endif + return 0; +} +static int +codegen_ROR_IMM(codeblock_t *block, uop_t *uop) +{ + int dest_reg = HOST_REG_GET(uop->dest_reg_a_real); + int src_reg = HOST_REG_GET(uop->src_reg_a_real); + int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real); + int src_size = IREG_GET_SIZE(uop->src_reg_a_real); + + if (REG_IS_L(dest_size) && REG_IS_L(src_size)) { + if (uop->dest_reg_a_real != uop->src_reg_a_real) + host_x86_MOV32_REG_REG(block, dest_reg, src_reg); + host_x86_ROR32_IMM(block, dest_reg, uop->imm_data); + } else if (REG_IS_W(dest_size) && REG_IS_W(src_size)) { + if (uop->dest_reg_a_real != uop->src_reg_a_real) + host_x86_MOV16_REG_REG(block, dest_reg, src_reg); + host_x86_ROR16_IMM(block, dest_reg, uop->imm_data); + } else if (REG_IS_B(dest_size) && REG_IS_B(src_size)) { + if (uop->dest_reg_a_real != uop->src_reg_a_real) + host_x86_MOV8_REG_REG(block, dest_reg, src_reg); + host_x86_ROR8_IMM(block, dest_reg, uop->imm_data); + } +# ifdef RECOMPILER_DEBUG + else + fatal("ROR_IMM %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real); +# endif + return 0; +} + +static int +codegen_SAR(codeblock_t *block, uop_t *uop) +{ + int dest_reg = HOST_REG_GET(uop->dest_reg_a_real); + int src_reg = HOST_REG_GET(uop->src_reg_a_real); + int shift_reg = HOST_REG_GET(uop->src_reg_b_real); + int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real); + int src_size = IREG_GET_SIZE(uop->src_reg_a_real); + + host_x86_MOV32_REG_REG(block, REG_ECX, shift_reg); + if (REG_IS_L(dest_size) && REG_IS_L(src_size)) { + if (uop->dest_reg_a_real != uop->src_reg_a_real) + host_x86_MOV32_REG_REG(block, dest_reg, src_reg); + host_x86_SAR32_CL(block, dest_reg); + } else if (REG_IS_W(dest_size) && REG_IS_W(src_size)) { + if (uop->dest_reg_a_real != uop->src_reg_a_real) + host_x86_MOV16_REG_REG(block, dest_reg, src_reg); + host_x86_SAR16_CL(block, dest_reg); + } else if (REG_IS_B(dest_size) && REG_IS_B(src_size)) { + if (uop->dest_reg_a_real != uop->src_reg_a_real) + host_x86_MOV8_REG_REG(block, dest_reg, src_reg); + host_x86_SAR8_CL(block, dest_reg); + } +# ifdef RECOMPILER_DEBUG + else + fatal("SAR %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real); +# endif + return 0; +} +static int +codegen_SAR_IMM(codeblock_t *block, uop_t *uop) +{ + int dest_reg = HOST_REG_GET(uop->dest_reg_a_real); + int src_reg = HOST_REG_GET(uop->src_reg_a_real); + int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real); + int src_size = IREG_GET_SIZE(uop->src_reg_a_real); + + if (REG_IS_L(dest_size) && REG_IS_L(src_size)) { + if (uop->dest_reg_a_real != uop->src_reg_a_real) + host_x86_MOV32_REG_REG(block, dest_reg, src_reg); + host_x86_SAR32_IMM(block, dest_reg, uop->imm_data); + } else if (REG_IS_W(dest_size) && REG_IS_W(src_size)) { + if (uop->dest_reg_a_real != uop->src_reg_a_real) + host_x86_MOV16_REG_REG(block, dest_reg, src_reg); + host_x86_SAR16_IMM(block, dest_reg, uop->imm_data); + } else if (REG_IS_B(dest_size) && REG_IS_B(src_size)) { + if (uop->dest_reg_a_real != uop->src_reg_a_real) + host_x86_MOV8_REG_REG(block, dest_reg, src_reg); + host_x86_SAR8_IMM(block, dest_reg, uop->imm_data); + } +# ifdef RECOMPILER_DEBUG + else + fatal("SAR_IMM %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real); +# endif + return 0; +} +static int +codegen_SHL(codeblock_t *block, uop_t *uop) +{ + int dest_reg = HOST_REG_GET(uop->dest_reg_a_real); + int src_reg = HOST_REG_GET(uop->src_reg_a_real); + int shift_reg = HOST_REG_GET(uop->src_reg_b_real); + int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real); + int src_size = IREG_GET_SIZE(uop->src_reg_a_real); + + host_x86_MOV32_REG_REG(block, REG_ECX, shift_reg); + if (REG_IS_L(dest_size) && REG_IS_L(src_size)) { + if (uop->dest_reg_a_real != uop->src_reg_a_real) + host_x86_MOV32_REG_REG(block, dest_reg, src_reg); + host_x86_SHL32_CL(block, dest_reg); + } else if (REG_IS_W(dest_size) && REG_IS_W(src_size)) { + if (uop->dest_reg_a_real != uop->src_reg_a_real) + host_x86_MOV16_REG_REG(block, dest_reg, src_reg); + host_x86_SHL16_CL(block, dest_reg); + } else if (REG_IS_B(dest_size) && REG_IS_B(src_size)) { + if (uop->dest_reg_a_real != uop->src_reg_a_real) + host_x86_MOV8_REG_REG(block, dest_reg, src_reg); + host_x86_SHL8_CL(block, dest_reg); + } +# ifdef RECOMPILER_DEBUG + else + fatal("SHL %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real); +# endif + return 0; +} +static int +codegen_SHL_IMM(codeblock_t *block, uop_t *uop) +{ + int dest_reg = HOST_REG_GET(uop->dest_reg_a_real); + int src_reg = HOST_REG_GET(uop->src_reg_a_real); + int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real); + int src_size = IREG_GET_SIZE(uop->src_reg_a_real); + + if (REG_IS_L(dest_size) && REG_IS_L(src_size)) { + if (uop->dest_reg_a_real != uop->src_reg_a_real) + host_x86_MOV32_REG_REG(block, dest_reg, src_reg); + host_x86_SHL32_IMM(block, dest_reg, uop->imm_data); + } else if (REG_IS_W(dest_size) && REG_IS_W(src_size)) { + if (uop->dest_reg_a_real != uop->src_reg_a_real) + host_x86_MOV16_REG_REG(block, dest_reg, src_reg); + host_x86_SHL16_IMM(block, dest_reg, uop->imm_data); + } else if (REG_IS_B(dest_size) && REG_IS_B(src_size)) { + if (uop->dest_reg_a_real != uop->src_reg_a_real) + host_x86_MOV8_REG_REG(block, dest_reg, src_reg); + host_x86_SHL8_IMM(block, dest_reg, uop->imm_data); + } +# ifdef RECOMPILER_DEBUG + else + fatal("SHL_IMM %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real); +# endif + return 0; +} +static int +codegen_SHR(codeblock_t *block, uop_t *uop) +{ + int dest_reg = HOST_REG_GET(uop->dest_reg_a_real); + int src_reg = HOST_REG_GET(uop->src_reg_a_real); + int shift_reg = HOST_REG_GET(uop->src_reg_b_real); + int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real); + int src_size = IREG_GET_SIZE(uop->src_reg_a_real); + + host_x86_MOV32_REG_REG(block, REG_ECX, shift_reg); + if (REG_IS_L(dest_size) && REG_IS_L(src_size)) { + if (uop->dest_reg_a_real != uop->src_reg_a_real) + host_x86_MOV32_REG_REG(block, dest_reg, src_reg); + host_x86_SHR32_CL(block, dest_reg); + } else if (REG_IS_W(dest_size) && REG_IS_W(src_size)) { + if (uop->dest_reg_a_real != uop->src_reg_a_real) + host_x86_MOV16_REG_REG(block, dest_reg, src_reg); + host_x86_SHR16_CL(block, dest_reg); + } else if (REG_IS_B(dest_size) && REG_IS_B(src_size)) { + if (uop->dest_reg_a_real != uop->src_reg_a_real) + host_x86_MOV8_REG_REG(block, dest_reg, src_reg); + host_x86_SHR8_CL(block, dest_reg); + } +# ifdef RECOMPILER_DEBUG + else + fatal("SHR %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real); +# endif + return 0; +} +static int +codegen_SHR_IMM(codeblock_t *block, uop_t *uop) +{ + int dest_reg = HOST_REG_GET(uop->dest_reg_a_real); + int src_reg = HOST_REG_GET(uop->src_reg_a_real); + int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real); + int src_size = IREG_GET_SIZE(uop->src_reg_a_real); + + if (REG_IS_L(dest_size) && REG_IS_L(src_size)) { + if (uop->dest_reg_a_real != uop->src_reg_a_real) + host_x86_MOV32_REG_REG(block, dest_reg, src_reg); + host_x86_SHR32_IMM(block, dest_reg, uop->imm_data); + } else if (REG_IS_W(dest_size) && REG_IS_W(src_size)) { + if (uop->dest_reg_a_real != uop->src_reg_a_real) + host_x86_MOV16_REG_REG(block, dest_reg, src_reg); + host_x86_SHR16_IMM(block, dest_reg, uop->imm_data); + } else if (REG_IS_B(dest_size) && REG_IS_B(src_size)) { + if (uop->dest_reg_a_real != uop->src_reg_a_real) + host_x86_MOV8_REG_REG(block, dest_reg, src_reg); + host_x86_SHR8_IMM(block, dest_reg, uop->imm_data); + } +# ifdef RECOMPILER_DEBUG + else + fatal("SHR_IMM %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real); +# endif + return 0; +} + +static int +codegen_STORE_PTR_IMM(codeblock_t *block, uop_t *uop) +{ +# ifdef RECOMPILER_DEBUG + if (((uintptr_t) uop->p) >> 32) + fatal("STORE_PTR_IMM 64-bit addr\n"); +# endif + host_x86_MOV32_ABS_IMM(block, uop->p, uop->imm_data); + return 0; +} +static int +codegen_STORE_PTR_IMM_8(codeblock_t *block, uop_t *uop) +{ +# ifdef RECOMPILER_DEBUG + if (((uintptr_t) uop->p) >> 32) + fatal("STORE_PTR_IMM_8 64-bit addr\n"); +# endif + host_x86_MOV8_ABS_IMM(block, uop->p, uop->imm_data); + return 0; +} + +static int +codegen_SUB(codeblock_t *block, uop_t *uop) +{ + int dest_reg = HOST_REG_GET(uop->dest_reg_a_real); + int src_reg_a = HOST_REG_GET(uop->src_reg_a_real); + int src_reg_b = HOST_REG_GET(uop->src_reg_b_real); + int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real); + int src_size_a = IREG_GET_SIZE(uop->src_reg_a_real); + int src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); + + if (REG_IS_L(dest_size) && REG_IS_L(src_size_a) && REG_IS_L(src_size_b)) { + if (dest_reg != src_reg_a) + host_x86_MOV32_REG_REG(block, dest_reg, src_reg_a); + host_x86_SUB32_REG_REG(block, dest_reg, src_reg_b); + } else if (REG_IS_W(dest_size) && REG_IS_W(src_size_a) && REG_IS_W(src_size_b)) { + if (dest_reg != src_reg_a) + host_x86_MOV16_REG_REG(block, dest_reg, src_reg_a); + host_x86_SUB16_REG_REG(block, dest_reg, src_reg_b); + } else if (REG_IS_B(dest_size) && REG_IS_B(src_size_a) && REG_IS_B(src_size_b)) { + if (dest_reg != src_reg_a) + host_x86_MOV8_REG_REG(block, dest_reg, src_reg_a); + host_x86_SUB8_REG_REG(block, dest_reg, src_reg_b); + } +# ifdef RECOMPILER_DEBUG + else + fatal("SUB %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real); +# endif + return 0; +} +static int +codegen_SUB_IMM(codeblock_t *block, uop_t *uop) +{ + int dest_reg = HOST_REG_GET(uop->dest_reg_a_real); + int src_reg = HOST_REG_GET(uop->src_reg_a_real); + int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real); + int src_size = IREG_GET_SIZE(uop->src_reg_a_real); + + if (REG_IS_L(dest_size) && REG_IS_L(src_size)) { + if (dest_reg != src_reg) + host_x86_MOV32_REG_REG(block, dest_reg, src_reg); + host_x86_SUB32_REG_IMM(block, dest_reg, uop->imm_data); + } else if (REG_IS_W(dest_size) && REG_IS_W(src_size)) { + if (dest_reg != src_reg) + host_x86_MOV16_REG_REG(block, dest_reg, src_reg); + host_x86_SUB16_REG_IMM(block, dest_reg, uop->imm_data); + } else if (REG_IS_B(dest_size) && REG_IS_B(src_size)) { + if (dest_reg != src_reg) + host_x86_MOV8_REG_REG(block, dest_reg, src_reg); + host_x86_SUB8_REG_IMM(block, dest_reg, uop->imm_data); + } +# ifdef RECOMPILER_DEBUG + else + fatal("SUB_IMM %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real); +# endif + return 0; +} + +static int +codegen_TEST_JNS_DEST(codeblock_t *block, uop_t *uop) +{ + int src_reg = HOST_REG_GET(uop->src_reg_a_real); + int src_size = IREG_GET_SIZE(uop->src_reg_a_real); + + if (REG_IS_L(src_size)) { + host_x86_TEST32_REG(block, src_reg, src_reg); + } else if (REG_IS_W(src_size)) { + host_x86_TEST16_REG(block, src_reg, src_reg); + } else if (REG_IS_B(src_size)) { + host_x86_TEST8_REG(block, src_reg, src_reg); + } +# ifdef RECOMPILER_DEBUG + else + fatal("TEST_JNS_DEST %02x\n", uop->src_reg_a_real); +# endif + uop->p = host_x86_JNS_long(block); + + return 0; +} +static int +codegen_TEST_JS_DEST(codeblock_t *block, uop_t *uop) +{ + int src_reg = HOST_REG_GET(uop->src_reg_a_real); + int src_size = IREG_GET_SIZE(uop->src_reg_a_real); + + if (REG_IS_L(src_size)) { + host_x86_TEST32_REG(block, src_reg, src_reg); + } else if (REG_IS_W(src_size)) { + host_x86_TEST16_REG(block, src_reg, src_reg); + } else if (REG_IS_B(src_size)) { + host_x86_TEST8_REG(block, src_reg, src_reg); + } +# ifdef RECOMPILER_DEBUG + else + fatal("TEST_JS_DEST %02x\n", uop->src_reg_a_real); +# endif + uop->p = host_x86_JS_long(block); + + return 0; +} + +static int +codegen_XOR(codeblock_t *block, uop_t *uop) +{ + int dest_reg = HOST_REG_GET(uop->dest_reg_a_real); + int src_reg_b = HOST_REG_GET(uop->src_reg_b_real); + int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real); + int src_size_a = IREG_GET_SIZE(uop->src_reg_a_real); + int src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); + + if (REG_IS_Q(dest_size) && REG_IS_Q(src_size_a) && REG_IS_Q(src_size_b) && uop->dest_reg_a_real == uop->src_reg_a_real) { + host_x86_PXOR_XREG_XREG(block, dest_reg, src_reg_b); + } else if (REG_IS_L(dest_size) && REG_IS_L(src_size_a) && REG_IS_L(src_size_b) && uop->dest_reg_a_real == uop->src_reg_a_real) { + host_x86_XOR32_REG_REG(block, dest_reg, src_reg_b); + } else if (REG_IS_W(dest_size) && REG_IS_W(src_size_a) && REG_IS_W(src_size_b) && uop->dest_reg_a_real == uop->src_reg_a_real) { + host_x86_XOR16_REG_REG(block, dest_reg, src_reg_b); + } else if (REG_IS_B(dest_size) && REG_IS_B(src_size_a) && REG_IS_B(src_size_b) && uop->dest_reg_a_real == uop->src_reg_a_real) { + host_x86_XOR8_REG_REG(block, dest_reg, src_reg_b); + } +# ifdef RECOMPILER_DEBUG + else + fatal("XOR %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real); +# endif + return 0; +} +static int +codegen_XOR_IMM(codeblock_t *block, uop_t *uop) +{ + int dest_reg = HOST_REG_GET(uop->dest_reg_a_real); + int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real); + int src_size = IREG_GET_SIZE(uop->src_reg_a_real); + + if (REG_IS_L(dest_size) && REG_IS_L(src_size)) { + host_x86_XOR32_REG_IMM(block, dest_reg, uop->imm_data); + } else if (REG_IS_W(dest_size) && REG_IS_W(src_size)) { + host_x86_XOR16_REG_IMM(block, dest_reg, uop->imm_data); + } else if (REG_IS_B(dest_size) && REG_IS_B(src_size)) { + host_x86_XOR8_REG_IMM(block, dest_reg, uop->imm_data); + } +# ifdef RECOMPILER_DEBUG + else + fatal("XOR_IMM %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real); +# endif + return 0; +} + +const uOpFn uop_handlers[UOP_MAX] = { + [UOP_CALL_FUNC & UOP_MASK] = codegen_CALL_FUNC, + [UOP_CALL_FUNC_RESULT & + UOP_MASK] + = codegen_CALL_FUNC_RESULT, + [UOP_CALL_INSTRUCTION_FUNC & + UOP_MASK] + = codegen_CALL_INSTRUCTION_FUNC, + + [UOP_JMP & + UOP_MASK] + = codegen_JMP, + + [UOP_LOAD_SEG & + UOP_MASK] + = codegen_LOAD_SEG, + + [UOP_LOAD_FUNC_ARG_0 & + UOP_MASK] + = codegen_LOAD_FUNC_ARG0, + [UOP_LOAD_FUNC_ARG_1 & + UOP_MASK] + = codegen_LOAD_FUNC_ARG1, + [UOP_LOAD_FUNC_ARG_2 & + UOP_MASK] + = codegen_LOAD_FUNC_ARG2, + [UOP_LOAD_FUNC_ARG_3 & + UOP_MASK] + = codegen_LOAD_FUNC_ARG3, + + [UOP_LOAD_FUNC_ARG_0_IMM & + UOP_MASK] + = codegen_LOAD_FUNC_ARG0_IMM, + [UOP_LOAD_FUNC_ARG_1_IMM & + UOP_MASK] + = codegen_LOAD_FUNC_ARG1_IMM, + [UOP_LOAD_FUNC_ARG_2_IMM & + UOP_MASK] + = codegen_LOAD_FUNC_ARG2_IMM, + [UOP_LOAD_FUNC_ARG_3_IMM & + UOP_MASK] + = codegen_LOAD_FUNC_ARG3_IMM, + + [UOP_STORE_P_IMM & + UOP_MASK] + = codegen_STORE_PTR_IMM, + [UOP_STORE_P_IMM_8 & + UOP_MASK] + = codegen_STORE_PTR_IMM_8, + + [UOP_MEM_LOAD_ABS & + UOP_MASK] + = codegen_MEM_LOAD_ABS, + [UOP_MEM_LOAD_REG & + UOP_MASK] + = codegen_MEM_LOAD_REG, + [UOP_MEM_LOAD_SINGLE & + UOP_MASK] + = codegen_MEM_LOAD_SINGLE, + [UOP_MEM_LOAD_DOUBLE & + UOP_MASK] + = codegen_MEM_LOAD_DOUBLE, + + [UOP_MEM_STORE_ABS & + UOP_MASK] + = codegen_MEM_STORE_ABS, + [UOP_MEM_STORE_REG & + UOP_MASK] + = codegen_MEM_STORE_REG, + [UOP_MEM_STORE_IMM_8 & + UOP_MASK] + = codegen_MEM_STORE_IMM_8, + [UOP_MEM_STORE_IMM_16 & + UOP_MASK] + = codegen_MEM_STORE_IMM_16, + [UOP_MEM_STORE_IMM_32 & + UOP_MASK] + = codegen_MEM_STORE_IMM_32, + [UOP_MEM_STORE_SINGLE & + UOP_MASK] + = codegen_MEM_STORE_SINGLE, + [UOP_MEM_STORE_DOUBLE & + UOP_MASK] + = codegen_MEM_STORE_DOUBLE, + + [UOP_MOV & + UOP_MASK] + = codegen_MOV, + [UOP_MOV_PTR & + UOP_MASK] + = codegen_MOV_PTR, + [UOP_MOV_IMM & + UOP_MASK] + = codegen_MOV_IMM, + [UOP_MOVSX & + UOP_MASK] + = codegen_MOVSX, + [UOP_MOVZX & + UOP_MASK] + = codegen_MOVZX, + [UOP_MOV_DOUBLE_INT & + UOP_MASK] + = codegen_MOV_DOUBLE_INT, + [UOP_MOV_INT_DOUBLE & + UOP_MASK] + = codegen_MOV_INT_DOUBLE, + [UOP_MOV_INT_DOUBLE_64 & + UOP_MASK] + = codegen_MOV_INT_DOUBLE_64, + [UOP_MOV_REG_PTR & + UOP_MASK] + = codegen_MOV_REG_PTR, + [UOP_MOVZX_REG_PTR_8 & + UOP_MASK] + = codegen_MOVZX_REG_PTR_8, + [UOP_MOVZX_REG_PTR_16 & + UOP_MASK] + = codegen_MOVZX_REG_PTR_16, + + [UOP_ADD & + UOP_MASK] + = codegen_ADD, + [UOP_ADD_IMM & + UOP_MASK] + = codegen_ADD_IMM, + [UOP_ADD_LSHIFT & + UOP_MASK] + = codegen_ADD_LSHIFT, + [UOP_AND & + UOP_MASK] + = codegen_AND, + [UOP_ANDN & + UOP_MASK] + = codegen_ANDN, + [UOP_AND_IMM & + UOP_MASK] + = codegen_AND_IMM, + [UOP_OR & + UOP_MASK] + = codegen_OR, + [UOP_OR_IMM & + UOP_MASK] + = codegen_OR_IMM, + [UOP_SUB & + UOP_MASK] + = codegen_SUB, + [UOP_SUB_IMM & + UOP_MASK] + = codegen_SUB_IMM, + [UOP_XOR & + UOP_MASK] + = codegen_XOR, + [UOP_XOR_IMM & + UOP_MASK] + = codegen_XOR_IMM, + + [UOP_SAR & + UOP_MASK] + = codegen_SAR, + [UOP_SAR_IMM & + UOP_MASK] + = codegen_SAR_IMM, + [UOP_SHL & + UOP_MASK] + = codegen_SHL, + [UOP_SHL_IMM & + UOP_MASK] + = codegen_SHL_IMM, + [UOP_SHR & + UOP_MASK] + = codegen_SHR, + [UOP_SHR_IMM & + UOP_MASK] + = codegen_SHR_IMM, + [UOP_ROL & + UOP_MASK] + = codegen_ROL, + [UOP_ROL_IMM & + UOP_MASK] + = codegen_ROL_IMM, + [UOP_ROR & + UOP_MASK] + = codegen_ROR, + [UOP_ROR_IMM & + UOP_MASK] + = codegen_ROR_IMM, + + [UOP_CMP_IMM_JZ & + UOP_MASK] + = codegen_CMP_IMM_JZ, + + [UOP_CMP_JB & + UOP_MASK] + = codegen_CMP_JB, + [UOP_CMP_JNBE & + UOP_MASK] + = codegen_CMP_JNBE, + + [UOP_CMP_JNB_DEST & + UOP_MASK] + = codegen_CMP_JNB_DEST, + [UOP_CMP_JNBE_DEST & + UOP_MASK] + = codegen_CMP_JNBE_DEST, + [UOP_CMP_JNL_DEST & + UOP_MASK] + = codegen_CMP_JNL_DEST, + [UOP_CMP_JNLE_DEST & + UOP_MASK] + = codegen_CMP_JNLE_DEST, + [UOP_CMP_JNO_DEST & + UOP_MASK] + = codegen_CMP_JNO_DEST, + [UOP_CMP_JNZ_DEST & + UOP_MASK] + = codegen_CMP_JNZ_DEST, + [UOP_CMP_JB_DEST & + UOP_MASK] + = codegen_CMP_JB_DEST, + [UOP_CMP_JBE_DEST & + UOP_MASK] + = codegen_CMP_JBE_DEST, + [UOP_CMP_JL_DEST & + UOP_MASK] + = codegen_CMP_JL_DEST, + [UOP_CMP_JLE_DEST & + UOP_MASK] + = codegen_CMP_JLE_DEST, + [UOP_CMP_JO_DEST & + UOP_MASK] + = codegen_CMP_JO_DEST, + [UOP_CMP_JZ_DEST & + UOP_MASK] + = codegen_CMP_JZ_DEST, + + [UOP_CMP_IMM_JNZ_DEST & + UOP_MASK] + = codegen_CMP_IMM_JNZ_DEST, + [UOP_CMP_IMM_JZ_DEST & + UOP_MASK] + = codegen_CMP_IMM_JZ_DEST, + + [UOP_TEST_JNS_DEST & + UOP_MASK] + = codegen_TEST_JNS_DEST, + [UOP_TEST_JS_DEST & + UOP_MASK] + = codegen_TEST_JS_DEST, + + [UOP_FP_ENTER & + UOP_MASK] + = codegen_FP_ENTER, + [UOP_MMX_ENTER & + UOP_MASK] + = codegen_MMX_ENTER, + + [UOP_FADD & + UOP_MASK] + = codegen_FADD, + [UOP_FCOM & + UOP_MASK] + = codegen_FCOM, + [UOP_FDIV & + UOP_MASK] + = codegen_FDIV, + [UOP_FMUL & + UOP_MASK] + = codegen_FMUL, + [UOP_FSUB & + UOP_MASK] + = codegen_FSUB, + + [UOP_FABS & + UOP_MASK] + = codegen_FABS, + [UOP_FCHS & + UOP_MASK] + = codegen_FCHS, + [UOP_FSQRT & + UOP_MASK] + = codegen_FSQRT, + [UOP_FTST & + UOP_MASK] + = codegen_FTST, + + [UOP_PACKSSWB & + UOP_MASK] + = codegen_PACKSSWB, + [UOP_PACKSSDW & + UOP_MASK] + = codegen_PACKSSDW, + [UOP_PACKUSWB & + UOP_MASK] + = codegen_PACKUSWB, + + [UOP_PADDB & + UOP_MASK] + = codegen_PADDB, + [UOP_PADDW & + UOP_MASK] + = codegen_PADDW, + [UOP_PADDD & + UOP_MASK] + = codegen_PADDD, + [UOP_PADDSB & + UOP_MASK] + = codegen_PADDSB, + [UOP_PADDSW & + UOP_MASK] + = codegen_PADDSW, + [UOP_PADDUSB & + UOP_MASK] + = codegen_PADDUSB, + [UOP_PADDUSW & + UOP_MASK] + = codegen_PADDUSW, + + [UOP_PCMPEQB & + UOP_MASK] + = codegen_PCMPEQB, + [UOP_PCMPEQW & + UOP_MASK] + = codegen_PCMPEQW, + [UOP_PCMPEQD & + UOP_MASK] + = codegen_PCMPEQD, + [UOP_PCMPGTB & + UOP_MASK] + = codegen_PCMPGTB, + [UOP_PCMPGTW & + UOP_MASK] + = codegen_PCMPGTW, + [UOP_PCMPGTD & + UOP_MASK] + = codegen_PCMPGTD, + + [UOP_PF2ID & + UOP_MASK] + = codegen_PF2ID, + [UOP_PFADD & + UOP_MASK] + = codegen_PFADD, + [UOP_PFCMPEQ & + UOP_MASK] + = codegen_PFCMPEQ, + [UOP_PFCMPGE & + UOP_MASK] + = codegen_PFCMPGE, + [UOP_PFCMPGT & + UOP_MASK] + = codegen_PFCMPGT, + [UOP_PFMAX & + UOP_MASK] + = codegen_PFMAX, + [UOP_PFMIN & + UOP_MASK] + = codegen_PFMIN, + [UOP_PFMUL & + UOP_MASK] + = codegen_PFMUL, + [UOP_PFRCP & + UOP_MASK] + = codegen_PFRCP, + [UOP_PFRSQRT & + UOP_MASK] + = codegen_PFRSQRT, + [UOP_PFSUB & + UOP_MASK] + = codegen_PFSUB, + [UOP_PI2FD & + UOP_MASK] + = codegen_PI2FD, + + [UOP_PMADDWD & + UOP_MASK] + = codegen_PMADDWD, + [UOP_PMULHW & + UOP_MASK] + = codegen_PMULHW, + [UOP_PMULLW & + UOP_MASK] + = codegen_PMULLW, + + [UOP_PSLLW_IMM & + UOP_MASK] + = codegen_PSLLW_IMM, + [UOP_PSLLD_IMM & + UOP_MASK] + = codegen_PSLLD_IMM, + [UOP_PSLLQ_IMM & + UOP_MASK] + = codegen_PSLLQ_IMM, + [UOP_PSRAW_IMM & + UOP_MASK] + = codegen_PSRAW_IMM, + [UOP_PSRAD_IMM & + UOP_MASK] + = codegen_PSRAD_IMM, + [UOP_PSRAQ_IMM & + UOP_MASK] + = codegen_PSRAQ_IMM, + [UOP_PSRLW_IMM & + UOP_MASK] + = codegen_PSRLW_IMM, + [UOP_PSRLD_IMM & + UOP_MASK] + = codegen_PSRLD_IMM, + [UOP_PSRLQ_IMM & + UOP_MASK] + = codegen_PSRLQ_IMM, + + [UOP_PSUBB & + UOP_MASK] + = codegen_PSUBB, + [UOP_PSUBW & + UOP_MASK] + = codegen_PSUBW, + [UOP_PSUBD & + UOP_MASK] + = codegen_PSUBD, + [UOP_PSUBSB & + UOP_MASK] + = codegen_PSUBSB, + [UOP_PSUBSW & + UOP_MASK] + = codegen_PSUBSW, + [UOP_PSUBUSB & + UOP_MASK] + = codegen_PSUBUSB, + [UOP_PSUBUSW & + UOP_MASK] + = codegen_PSUBUSW, + + [UOP_PUNPCKHBW & + UOP_MASK] + = codegen_PUNPCKHBW, + [UOP_PUNPCKHWD & + UOP_MASK] + = codegen_PUNPCKHWD, + [UOP_PUNPCKHDQ & + UOP_MASK] + = codegen_PUNPCKHDQ, + [UOP_PUNPCKLBW & + UOP_MASK] + = codegen_PUNPCKLBW, + [UOP_PUNPCKLWD & + UOP_MASK] + = codegen_PUNPCKLWD, + [UOP_PUNPCKLDQ & + UOP_MASK] + = codegen_PUNPCKLDQ, + + [UOP_NOP_BARRIER & + UOP_MASK] + = codegen_NOP }; -void codegen_direct_read_8(codeblock_t *block, int host_reg, void *p) +void +codegen_direct_read_8(codeblock_t *block, int host_reg, void *p) { - host_x86_MOV8_REG_ABS(block, host_reg, p); + host_x86_MOV8_REG_ABS(block, host_reg, p); } -void codegen_direct_read_16(codeblock_t *block, int host_reg, void *p) +void +codegen_direct_read_16(codeblock_t *block, int host_reg, void *p) { - host_x86_MOV16_REG_ABS(block, host_reg, p); + host_x86_MOV16_REG_ABS(block, host_reg, p); } -void codegen_direct_read_32(codeblock_t *block, int host_reg, void *p) +void +codegen_direct_read_32(codeblock_t *block, int host_reg, void *p) { - host_x86_MOV32_REG_ABS(block, host_reg, p); + host_x86_MOV32_REG_ABS(block, host_reg, p); } -void codegen_direct_read_64(codeblock_t *block, int host_reg, void *p) +void +codegen_direct_read_64(codeblock_t *block, int host_reg, void *p) { - host_x86_MOVQ_XREG_ABS(block, host_reg, p); + host_x86_MOVQ_XREG_ABS(block, host_reg, p); } -void codegen_direct_read_pointer(codeblock_t *block, int host_reg, void *p) +void +codegen_direct_read_pointer(codeblock_t *block, int host_reg, void *p) { - host_x86_MOV64_REG_ABS(block, host_reg, p); + host_x86_MOV64_REG_ABS(block, host_reg, p); } -void codegen_direct_read_double(codeblock_t *block, int host_reg, void *p) +void +codegen_direct_read_double(codeblock_t *block, int host_reg, void *p) { - host_x86_MOVQ_XREG_ABS(block, host_reg, p); + host_x86_MOVQ_XREG_ABS(block, host_reg, p); } -void codegen_direct_read_st_8(codeblock_t *block, int host_reg, void *base, int reg_idx) +void +codegen_direct_read_st_8(codeblock_t *block, int host_reg, void *base, int reg_idx) { - int offset = (uintptr_t)base - (((uintptr_t)&cpu_state) + 128); + int offset = (uintptr_t) base - (((uintptr_t) &cpu_state) + 128); - host_x86_MOV32_REG_BASE_OFFSET(block, REG_ECX, REG_RSP, IREG_TOP_diff_stack_offset); - host_x86_ADD32_REG_IMM(block, REG_ECX, reg_idx); - host_x86_AND32_REG_IMM(block, REG_ECX, 7); - host_x86_MOV8_REG_ABS_REG_REG_SHIFT(block, host_reg, offset, REG_RBP, REG_ECX, 0); + host_x86_MOV32_REG_BASE_OFFSET(block, REG_ECX, REG_RSP, IREG_TOP_diff_stack_offset); + host_x86_ADD32_REG_IMM(block, REG_ECX, reg_idx); + host_x86_AND32_REG_IMM(block, REG_ECX, 7); + host_x86_MOV8_REG_ABS_REG_REG_SHIFT(block, host_reg, offset, REG_RBP, REG_ECX, 0); } -void codegen_direct_read_st_64(codeblock_t *block, int host_reg, void *base, int reg_idx) +void +codegen_direct_read_st_64(codeblock_t *block, int host_reg, void *base, int reg_idx) { - int offset = (uintptr_t)base - (((uintptr_t)&cpu_state) + 128); + int offset = (uintptr_t) base - (((uintptr_t) &cpu_state) + 128); - host_x86_MOV32_REG_BASE_OFFSET(block, REG_ECX, REG_RSP, IREG_TOP_diff_stack_offset); - host_x86_ADD32_REG_IMM(block, REG_ECX, reg_idx); - host_x86_AND32_REG_IMM(block, REG_ECX, 7); - host_x86_MOVQ_XREG_ABS_REG_REG_SHIFT(block, host_reg, offset, REG_RBP, REG_ECX, 3); + host_x86_MOV32_REG_BASE_OFFSET(block, REG_ECX, REG_RSP, IREG_TOP_diff_stack_offset); + host_x86_ADD32_REG_IMM(block, REG_ECX, reg_idx); + host_x86_AND32_REG_IMM(block, REG_ECX, 7); + host_x86_MOVQ_XREG_ABS_REG_REG_SHIFT(block, host_reg, offset, REG_RBP, REG_ECX, 3); } -void codegen_direct_read_st_double(codeblock_t *block, int host_reg, void *base, int reg_idx) +void +codegen_direct_read_st_double(codeblock_t *block, int host_reg, void *base, int reg_idx) { - int offset = (uintptr_t)base - (((uintptr_t)&cpu_state) + 128); + int offset = (uintptr_t) base - (((uintptr_t) &cpu_state) + 128); - host_x86_MOV32_REG_BASE_OFFSET(block, REG_ECX, REG_RSP, IREG_TOP_diff_stack_offset); - host_x86_ADD32_REG_IMM(block, REG_ECX, reg_idx); - host_x86_AND32_REG_IMM(block, REG_ECX, 7); - host_x86_MOVQ_XREG_ABS_REG_REG_SHIFT(block, host_reg, offset, REG_RBP, REG_ECX, 3); + host_x86_MOV32_REG_BASE_OFFSET(block, REG_ECX, REG_RSP, IREG_TOP_diff_stack_offset); + host_x86_ADD32_REG_IMM(block, REG_ECX, reg_idx); + host_x86_AND32_REG_IMM(block, REG_ECX, 7); + host_x86_MOVQ_XREG_ABS_REG_REG_SHIFT(block, host_reg, offset, REG_RBP, REG_ECX, 3); } -void codegen_direct_write_8(codeblock_t *block, void *p, int host_reg) +void +codegen_direct_write_8(codeblock_t *block, void *p, int host_reg) { - host_x86_MOV8_ABS_REG(block, p, host_reg); + host_x86_MOV8_ABS_REG(block, p, host_reg); } -void codegen_direct_write_16(codeblock_t *block, void *p, int host_reg) +void +codegen_direct_write_16(codeblock_t *block, void *p, int host_reg) { - host_x86_MOV16_ABS_REG(block, p, host_reg); + host_x86_MOV16_ABS_REG(block, p, host_reg); } -void codegen_direct_write_32(codeblock_t *block, void *p, int host_reg) +void +codegen_direct_write_32(codeblock_t *block, void *p, int host_reg) { - host_x86_MOV32_ABS_REG(block, p, host_reg); + host_x86_MOV32_ABS_REG(block, p, host_reg); } -void codegen_direct_write_64(codeblock_t *block, void *p, int host_reg) +void +codegen_direct_write_64(codeblock_t *block, void *p, int host_reg) { - host_x86_MOVQ_ABS_XREG(block, p, host_reg); + host_x86_MOVQ_ABS_XREG(block, p, host_reg); } -void codegen_direct_write_pointer(codeblock_t *block, void *p, int host_reg) +void +codegen_direct_write_pointer(codeblock_t *block, void *p, int host_reg) { - host_x86_MOV64_ABS_REG(block, p, host_reg); + host_x86_MOV64_ABS_REG(block, p, host_reg); } -void codegen_direct_write_double(codeblock_t *block, void *p, int host_reg) +void +codegen_direct_write_double(codeblock_t *block, void *p, int host_reg) { - host_x86_MOVQ_ABS_XREG(block, p, host_reg); + host_x86_MOVQ_ABS_XREG(block, p, host_reg); } -void codegen_direct_write_st_8(codeblock_t *block, void *base, int reg_idx, int host_reg) +void +codegen_direct_write_st_8(codeblock_t *block, void *base, int reg_idx, int host_reg) { - int offset = (uintptr_t)base - (((uintptr_t)&cpu_state) + 128); + int offset = (uintptr_t) base - (((uintptr_t) &cpu_state) + 128); - host_x86_MOV32_REG_BASE_OFFSET(block, REG_ECX, REG_RSP, IREG_TOP_diff_stack_offset); - host_x86_ADD32_REG_IMM(block, REG_ECX, reg_idx); - host_x86_AND32_REG_IMM(block, REG_ECX, 7); - host_x86_MOV8_ABS_REG_REG_SHIFT_REG(block, offset, REG_RBP, REG_ECX, 0, host_reg); + host_x86_MOV32_REG_BASE_OFFSET(block, REG_ECX, REG_RSP, IREG_TOP_diff_stack_offset); + host_x86_ADD32_REG_IMM(block, REG_ECX, reg_idx); + host_x86_AND32_REG_IMM(block, REG_ECX, 7); + host_x86_MOV8_ABS_REG_REG_SHIFT_REG(block, offset, REG_RBP, REG_ECX, 0, host_reg); } -void codegen_direct_write_st_64(codeblock_t *block, void *base, int reg_idx, int host_reg) +void +codegen_direct_write_st_64(codeblock_t *block, void *base, int reg_idx, int host_reg) { - int offset = (uintptr_t)base - (((uintptr_t)&cpu_state) + 128); + int offset = (uintptr_t) base - (((uintptr_t) &cpu_state) + 128); - host_x86_MOV32_REG_BASE_OFFSET(block, REG_ECX, REG_RSP, IREG_TOP_diff_stack_offset); - host_x86_ADD32_REG_IMM(block, REG_ECX, reg_idx); - host_x86_AND32_REG_IMM(block, REG_ECX, 7); - host_x86_MOVQ_ABS_REG_REG_SHIFT_XREG(block, offset, REG_RBP, REG_ECX, 3, host_reg); + host_x86_MOV32_REG_BASE_OFFSET(block, REG_ECX, REG_RSP, IREG_TOP_diff_stack_offset); + host_x86_ADD32_REG_IMM(block, REG_ECX, reg_idx); + host_x86_AND32_REG_IMM(block, REG_ECX, 7); + host_x86_MOVQ_ABS_REG_REG_SHIFT_XREG(block, offset, REG_RBP, REG_ECX, 3, host_reg); } -void codegen_direct_write_st_double(codeblock_t *block, void *base, int reg_idx, int host_reg) +void +codegen_direct_write_st_double(codeblock_t *block, void *base, int reg_idx, int host_reg) { - int offset = (uintptr_t)base - (((uintptr_t)&cpu_state) + 128); + int offset = (uintptr_t) base - (((uintptr_t) &cpu_state) + 128); - host_x86_MOV32_REG_BASE_OFFSET(block, REG_ECX, REG_RSP, IREG_TOP_diff_stack_offset); - host_x86_ADD32_REG_IMM(block, REG_ECX, reg_idx); - host_x86_AND32_REG_IMM(block, REG_ECX, 7); - host_x86_MOVQ_ABS_REG_REG_SHIFT_XREG(block, offset, REG_RBP, REG_ECX, 3, host_reg); + host_x86_MOV32_REG_BASE_OFFSET(block, REG_ECX, REG_RSP, IREG_TOP_diff_stack_offset); + host_x86_ADD32_REG_IMM(block, REG_ECX, reg_idx); + host_x86_AND32_REG_IMM(block, REG_ECX, 7); + host_x86_MOVQ_ABS_REG_REG_SHIFT_XREG(block, offset, REG_RBP, REG_ECX, 3, host_reg); } -void codegen_direct_write_ptr(codeblock_t *block, void *p, int host_reg) +void +codegen_direct_write_ptr(codeblock_t *block, void *p, int host_reg) { - host_x86_MOV64_ABS_REG(block, p, host_reg); + host_x86_MOV64_ABS_REG(block, p, host_reg); } -void codegen_direct_read_16_stack(codeblock_t *block, int host_reg, int stack_offset) +void +codegen_direct_read_16_stack(codeblock_t *block, int host_reg, int stack_offset) { - host_x86_MOV16_REG_BASE_OFFSET(block, host_reg, REG_ESP, stack_offset); + host_x86_MOV16_REG_BASE_OFFSET(block, host_reg, REG_ESP, stack_offset); } -void codegen_direct_read_32_stack(codeblock_t *block, int host_reg, int stack_offset) +void +codegen_direct_read_32_stack(codeblock_t *block, int host_reg, int stack_offset) { - host_x86_MOV32_REG_BASE_OFFSET(block, host_reg, REG_RSP, stack_offset); + host_x86_MOV32_REG_BASE_OFFSET(block, host_reg, REG_RSP, stack_offset); } -void codegen_direct_read_64_stack(codeblock_t *block, int host_reg, int stack_offset) +void +codegen_direct_read_64_stack(codeblock_t *block, int host_reg, int stack_offset) { - host_x86_MOVQ_XREG_BASE_OFFSET(block, host_reg, REG_RSP, stack_offset); + host_x86_MOVQ_XREG_BASE_OFFSET(block, host_reg, REG_RSP, stack_offset); } -void codegen_direct_read_pointer_stack(codeblock_t *block, int host_reg, int stack_offset) +void +codegen_direct_read_pointer_stack(codeblock_t *block, int host_reg, int stack_offset) { - host_x86_MOV64_REG_BASE_OFFSET(block, host_reg, REG_RSP, stack_offset); + host_x86_MOV64_REG_BASE_OFFSET(block, host_reg, REG_RSP, stack_offset); } -void codegen_direct_read_double_stack(codeblock_t *block, int host_reg, int stack_offset) +void +codegen_direct_read_double_stack(codeblock_t *block, int host_reg, int stack_offset) { - host_x86_MOVQ_XREG_BASE_OFFSET(block, host_reg, REG_RSP, stack_offset); + host_x86_MOVQ_XREG_BASE_OFFSET(block, host_reg, REG_RSP, stack_offset); } -void codegen_direct_write_32_stack(codeblock_t *block, int stack_offset, int host_reg) +void +codegen_direct_write_32_stack(codeblock_t *block, int stack_offset, int host_reg) { - host_x86_MOV32_BASE_OFFSET_REG(block, REG_RSP, stack_offset, host_reg); + host_x86_MOV32_BASE_OFFSET_REG(block, REG_RSP, stack_offset, host_reg); } -void codegen_direct_write_64_stack(codeblock_t *block, int stack_offset, int host_reg) +void +codegen_direct_write_64_stack(codeblock_t *block, int stack_offset, int host_reg) { - host_x86_MOVQ_BASE_OFFSET_XREG(block, REG_RSP, stack_offset, host_reg); + host_x86_MOVQ_BASE_OFFSET_XREG(block, REG_RSP, stack_offset, host_reg); } -void codegen_direct_write_pointer_stack(codeblock_t *block, int stack_offset, int host_reg) +void +codegen_direct_write_pointer_stack(codeblock_t *block, int stack_offset, int host_reg) { - host_x86_MOV64_BASE_OFFSET_REG(block, REG_RSP, stack_offset, host_reg); + host_x86_MOV64_BASE_OFFSET_REG(block, REG_RSP, stack_offset, host_reg); } -void codegen_direct_write_double_stack(codeblock_t *block, int stack_offset, int host_reg) +void +codegen_direct_write_double_stack(codeblock_t *block, int stack_offset, int host_reg) { - host_x86_MOVQ_BASE_OFFSET_XREG(block, REG_RSP, stack_offset, host_reg); + host_x86_MOVQ_BASE_OFFSET_XREG(block, REG_RSP, stack_offset, host_reg); } -void codegen_set_jump_dest(codeblock_t *block, void *p) +void +codegen_set_jump_dest(UNUSED(codeblock_t *block), void *p) { - *(uint32_t *)p = (uintptr_t)&block_write_data[block_pos] - ((uintptr_t)p + 4); + *(uint32_t *) p = (uintptr_t) &block_write_data[block_pos] - ((uintptr_t) p + 4); } -void codegen_direct_write_8_imm(codeblock_t *block, void *p, uint8_t imm_data) +void +codegen_direct_write_8_imm(codeblock_t *block, void *p, uint8_t imm_data) { - host_x86_MOV8_ABS_IMM(block, p, imm_data); + host_x86_MOV8_ABS_IMM(block, p, imm_data); } -void codegen_direct_write_16_imm(codeblock_t *block, void *p, uint16_t imm_data) +void +codegen_direct_write_16_imm(codeblock_t *block, void *p, uint16_t imm_data) { - host_x86_MOV16_ABS_IMM(block, p, imm_data); + host_x86_MOV16_ABS_IMM(block, p, imm_data); } -void codegen_direct_write_32_imm(codeblock_t *block, void *p, uint32_t imm_data) +void +codegen_direct_write_32_imm(codeblock_t *block, void *p, uint32_t imm_data) { - host_x86_MOV32_ABS_IMM(block, p, imm_data); + host_x86_MOV32_ABS_IMM(block, p, imm_data); } -void codegen_direct_write_32_imm_stack(codeblock_t *block, int stack_offset, uint32_t imm_data) +void +codegen_direct_write_32_imm_stack(codeblock_t *block, int stack_offset, uint32_t imm_data) { - host_x86_MOV32_BASE_OFFSET_IMM(block, REG_ESP, stack_offset, imm_data); + host_x86_MOV32_BASE_OFFSET_IMM(block, REG_ESP, stack_offset, imm_data); } #endif diff --git a/src/codegen_new/codegen_backend_x86.c b/src/codegen_new/codegen_backend_x86.c index 8aa2a5975..18235e2b2 100644 --- a/src/codegen_new/codegen_backend_x86.c +++ b/src/codegen_new/codegen_backend_x86.c @@ -1,29 +1,31 @@ #if defined i386 || defined __i386 || defined __i386__ || defined _X86_ || defined _M_IX86 -#include -#include -#include -#include <86box/86box.h> -#include "cpu.h" -#include <86box/mem.h> +# include +# include +# include +# include <86box/86box.h> +# include "cpu.h" +# include <86box/mem.h> -#include "codegen.h" -#include "codegen_allocator.h" -#include "codegen_backend.h" -#include "codegen_backend_x86_defs.h" -#include "codegen_backend_x86_ops.h" -#include "codegen_backend_x86_ops_sse.h" -#include "codegen_reg.h" -#include "x86.h" +# include "codegen.h" +# include "codegen_allocator.h" +# include "codegen_backend.h" +# include "codegen_backend_x86_defs.h" +# include "codegen_backend_x86_ops.h" +# include "codegen_backend_x86_ops_sse.h" +# include "codegen_reg.h" +# include "x86.h" +# include "x86seg_common.h" +# include "x86seg.h" -#if defined(__linux__) || defined(__APPLE__) -#include -#include -#endif -#if defined WIN32 || defined _WIN32 || defined _WIN32 -#include -#endif -#include +# if defined(__linux__) || defined(__APPLE__) +# include +# include +# endif +# if defined WIN32 || defined _WIN32 || defined _WIN32 +# include +# endif +# include void *codegen_mem_load_byte; void *codegen_mem_load_word; @@ -42,311 +44,302 @@ void *codegen_mem_store_double; void *codegen_gpf_rout; void *codegen_exit_rout; -host_reg_def_t codegen_host_reg_list[CODEGEN_HOST_REGS] = -{ - /*Note: while EAX and EDX are normally volatile registers under x86 - calling conventions, the recompiler will explicitly save and restore - them across funcion calls*/ - {REG_EAX, 0}, - {REG_EBX, 0}, - {REG_EDX, 0} +host_reg_def_t codegen_host_reg_list[CODEGEN_HOST_REGS] = { + /*Note: while EAX and EDX are normally volatile registers under x86 + calling conventions, the recompiler will explicitly save and restore + them across funcion calls*/ + {REG_EAX, 0}, + { REG_EBX, 0}, + { REG_EDX, 0} }; -host_reg_def_t codegen_host_fp_reg_list[CODEGEN_HOST_FP_REGS] = -{ - {REG_XMM0, HOST_REG_FLAG_VOLATILE}, - {REG_XMM1, HOST_REG_FLAG_VOLATILE}, - {REG_XMM2, HOST_REG_FLAG_VOLATILE}, - {REG_XMM3, HOST_REG_FLAG_VOLATILE}, - {REG_XMM4, HOST_REG_FLAG_VOLATILE}, - {REG_XMM5, HOST_REG_FLAG_VOLATILE} +host_reg_def_t codegen_host_fp_reg_list[CODEGEN_HOST_FP_REGS] = { + {REG_XMM0, HOST_REG_FLAG_VOLATILE}, + { REG_XMM1, HOST_REG_FLAG_VOLATILE}, + { REG_XMM2, HOST_REG_FLAG_VOLATILE}, + { REG_XMM3, HOST_REG_FLAG_VOLATILE}, + { REG_XMM4, HOST_REG_FLAG_VOLATILE}, + { REG_XMM5, HOST_REG_FLAG_VOLATILE} }; -static void build_load_routine(codeblock_t *block, int size, int is_float) +static void +build_load_routine(codeblock_t *block, int size, int is_float) { - uint8_t *branch_offset; - uint8_t *misaligned_offset = NULL; - - /*In - ESI = address - Out - ECX = data, ESI = abrt*/ - /*MOV ECX, ESI - SHR ESI, 12 - MOV ESI, [readlookup2+ESI*4] - CMP ESI, -1 - JNZ + - MOVZX ECX, B[ESI+ECX] - XOR ESI,ESI - RET - * PUSH EAX - PUSH EDX - PUSH ECX - CALL readmembl - POP ECX - POP EDX - POP EAX - MOVZX ECX, AL - RET - */ - host_x86_MOV32_REG_REG(block, REG_ECX, REG_ESI); - host_x86_SHR32_IMM(block, REG_ESI, 12); - host_x86_MOV32_REG_ABS_INDEX_SHIFT(block, REG_ESI, readlookup2, REG_ESI, 2); - if (size != 1) - { - host_x86_TEST32_REG_IMM(block, REG_ECX, size-1); - misaligned_offset = host_x86_JNZ_short(block); - } - host_x86_CMP32_REG_IMM(block, REG_ESI, (uint32_t)-1); - branch_offset = host_x86_JZ_short(block); - if (size == 1 && !is_float) - host_x86_MOVZX_BASE_INDEX_32_8(block, REG_ECX, REG_ESI, REG_ECX); - else if (size == 2 && !is_float) - host_x86_MOVZX_BASE_INDEX_32_16(block, REG_ECX, REG_ESI, REG_ECX); - else if (size == 4 && !is_float) - host_x86_MOV32_REG_BASE_INDEX(block, REG_ECX, REG_ESI, REG_ECX); - else if (size == 4 && is_float) - host_x86_CVTSS2SD_XREG_BASE_INDEX(block, REG_XMM_TEMP, REG_ESI, REG_ECX); - else if (size == 8) - host_x86_MOVQ_XREG_BASE_INDEX(block, REG_XMM_TEMP, REG_ESI, REG_ECX); - else - fatal("build_load_routine: size=%i\n", size); - host_x86_XOR32_REG_REG(block, REG_ESI, REG_ESI); - host_x86_RET(block); - - *branch_offset = (uint8_t)((uintptr_t)&block_write_data[block_pos] - (uintptr_t)branch_offset) - 1; - if (size != 1) - *misaligned_offset = (uint8_t)((uintptr_t)&block_write_data[block_pos] - (uintptr_t)misaligned_offset) - 1; - host_x86_PUSH(block, REG_EAX); - host_x86_PUSH(block, REG_EDX); - host_x86_PUSH(block, REG_ECX); - if (size == 1) - host_x86_CALL(block, (void *)readmembl); - else if (size == 2) - host_x86_CALL(block, (void *)readmemwl); - else if (size == 4) - host_x86_CALL(block, (void *)readmemll); - else if (size == 8) - host_x86_CALL(block, (void *)readmemql); - host_x86_POP(block, REG_ECX); - if (size == 1 && !is_float) - host_x86_MOVZX_REG_32_8(block, REG_ECX, REG_EAX); - else if (size == 2 && !is_float) - host_x86_MOVZX_REG_32_16(block, REG_ECX, REG_EAX); - else if (size == 4 && !is_float) - host_x86_MOV32_REG_REG(block, REG_ECX, REG_EAX); - else if (size == 4 && is_float) - { - host_x86_MOVD_XREG_REG(block, REG_XMM_TEMP, REG_EAX); - host_x86_CVTSS2SD_XREG_XREG(block, REG_XMM_TEMP, REG_XMM_TEMP); - } - else if (size == 8) - { - host_x86_MOVD_XREG_REG(block, REG_XMM_TEMP, REG_EAX); - host_x86_MOVD_XREG_REG(block, REG_XMM_TEMP2, REG_EDX); - host_x86_UNPCKLPS_XREG_XREG(block, REG_XMM_TEMP, REG_XMM_TEMP2); - } - host_x86_POP(block, REG_EDX); - host_x86_POP(block, REG_EAX); - host_x86_MOVZX_REG_ABS_32_8(block, REG_ESI, &cpu_state.abrt); - host_x86_RET(block); - block_pos = (block_pos + 63) & ~63; + uint8_t *branch_offset; + uint8_t *misaligned_offset = NULL; + + /*In - ESI = address + Out - ECX = data, ESI = abrt*/ + /*MOV ECX, ESI + SHR ESI, 12 + MOV ESI, [readlookup2+ESI*4] + CMP ESI, -1 + JNZ + + MOVZX ECX, B[ESI+ECX] + XOR ESI,ESI + RET + * PUSH EAX + PUSH EDX + PUSH ECX + CALL readmembl + POP ECX + POP EDX + POP EAX + MOVZX ECX, AL + RET + */ + host_x86_MOV32_REG_REG(block, REG_ECX, REG_ESI); + host_x86_SHR32_IMM(block, REG_ESI, 12); + host_x86_MOV32_REG_ABS_INDEX_SHIFT(block, REG_ESI, readlookup2, REG_ESI, 2); + if (size != 1) { + host_x86_TEST32_REG_IMM(block, REG_ECX, size - 1); + misaligned_offset = host_x86_JNZ_short(block); + } + host_x86_CMP32_REG_IMM(block, REG_ESI, (uint32_t) -1); + branch_offset = host_x86_JZ_short(block); + if (size == 1 && !is_float) + host_x86_MOVZX_BASE_INDEX_32_8(block, REG_ECX, REG_ESI, REG_ECX); + else if (size == 2 && !is_float) + host_x86_MOVZX_BASE_INDEX_32_16(block, REG_ECX, REG_ESI, REG_ECX); + else if (size == 4 && !is_float) + host_x86_MOV32_REG_BASE_INDEX(block, REG_ECX, REG_ESI, REG_ECX); + else if (size == 4 && is_float) + host_x86_CVTSS2SD_XREG_BASE_INDEX(block, REG_XMM_TEMP, REG_ESI, REG_ECX); + else if (size == 8) + host_x86_MOVQ_XREG_BASE_INDEX(block, REG_XMM_TEMP, REG_ESI, REG_ECX); + else + fatal("build_load_routine: size=%i\n", size); + host_x86_XOR32_REG_REG(block, REG_ESI, REG_ESI); + host_x86_RET(block); + + *branch_offset = (uint8_t) ((uintptr_t) &block_write_data[block_pos] - (uintptr_t) branch_offset) - 1; + if (size != 1) + *misaligned_offset = (uint8_t) ((uintptr_t) &block_write_data[block_pos] - (uintptr_t) misaligned_offset) - 1; + host_x86_PUSH(block, REG_EAX); + host_x86_PUSH(block, REG_EDX); + host_x86_PUSH(block, REG_ECX); + if (size == 1) + host_x86_CALL(block, (void *) readmembl); + else if (size == 2) + host_x86_CALL(block, (void *) readmemwl); + else if (size == 4) + host_x86_CALL(block, (void *) readmemll); + else if (size == 8) + host_x86_CALL(block, (void *) readmemql); + host_x86_POP(block, REG_ECX); + if (size == 1 && !is_float) + host_x86_MOVZX_REG_32_8(block, REG_ECX, REG_EAX); + else if (size == 2 && !is_float) + host_x86_MOVZX_REG_32_16(block, REG_ECX, REG_EAX); + else if (size == 4 && !is_float) + host_x86_MOV32_REG_REG(block, REG_ECX, REG_EAX); + else if (size == 4 && is_float) { + host_x86_MOVD_XREG_REG(block, REG_XMM_TEMP, REG_EAX); + host_x86_CVTSS2SD_XREG_XREG(block, REG_XMM_TEMP, REG_XMM_TEMP); + } else if (size == 8) { + host_x86_MOVD_XREG_REG(block, REG_XMM_TEMP, REG_EAX); + host_x86_MOVD_XREG_REG(block, REG_XMM_TEMP2, REG_EDX); + host_x86_UNPCKLPS_XREG_XREG(block, REG_XMM_TEMP, REG_XMM_TEMP2); + } + host_x86_POP(block, REG_EDX); + host_x86_POP(block, REG_EAX); + host_x86_MOVZX_REG_ABS_32_8(block, REG_ESI, &cpu_state.abrt); + host_x86_RET(block); + block_pos = (block_pos + 63) & ~63; } -static void build_store_routine(codeblock_t *block, int size, int is_float) +static void +build_store_routine(codeblock_t *block, int size, int is_float) { - uint8_t *branch_offset; - uint8_t *misaligned_offset = NULL; - - /*In - ECX = data, ESI = address - Out - ESI = abrt - Corrupts EDI*/ - /*MOV EDI, ESI - SHR ESI, 12 - MOV ESI, [writelookup2+ESI*4] - CMP ESI, -1 - JNZ + - MOV [ESI+EDI], ECX - XOR ESI,ESI - RET - * PUSH EAX - PUSH EDX - PUSH ECX - CALL writemembl - POP ECX - POP EDX - POP EAX - MOVZX ECX, AL - RET - */ - host_x86_MOV32_REG_REG(block, REG_EDI, REG_ESI); - host_x86_SHR32_IMM(block, REG_ESI, 12); - host_x86_MOV32_REG_ABS_INDEX_SHIFT(block, REG_ESI, writelookup2, REG_ESI, 2); - if (size != 1) - { - host_x86_TEST32_REG_IMM(block, REG_EDI, size-1); - misaligned_offset = host_x86_JNZ_short(block); - } - host_x86_CMP32_REG_IMM(block, REG_ESI, (uint32_t)-1); - branch_offset = host_x86_JZ_short(block); - if (size == 1 && !is_float) - host_x86_MOV8_BASE_INDEX_REG(block, REG_ESI, REG_EDI, REG_ECX); - else if (size == 2 && !is_float) - host_x86_MOV16_BASE_INDEX_REG(block, REG_ESI, REG_EDI, REG_ECX); - else if (size == 4 && !is_float) - host_x86_MOV32_BASE_INDEX_REG(block, REG_ESI, REG_EDI, REG_ECX); - else if (size == 4 && is_float) - host_x86_MOVD_BASE_INDEX_XREG(block, REG_ESI, REG_EDI, REG_XMM_TEMP); - else if (size == 8) - host_x86_MOVQ_BASE_INDEX_XREG(block, REG_ESI, REG_EDI, REG_XMM_TEMP); - else - fatal("build_store_routine: size=%i is_float=%i\n", size, is_float); - host_x86_XOR32_REG_REG(block, REG_ESI, REG_ESI); - host_x86_RET(block); + uint8_t *branch_offset; + uint8_t *misaligned_offset = NULL; - *branch_offset = (uint8_t)((uintptr_t)&block_write_data[block_pos] - (uintptr_t)branch_offset) - 1; - if (size != 1) - *misaligned_offset = (uint8_t)((uintptr_t)&block_write_data[block_pos] - (uintptr_t)misaligned_offset) - 1; - if (size == 4 && is_float) - host_x86_MOVD_REG_XREG(block, REG_ECX, REG_XMM_TEMP); - host_x86_PUSH(block, REG_EAX); - host_x86_PUSH(block, REG_EDX); - host_x86_PUSH(block, REG_ECX); - if (size == 8) - { - host_x86_MOVQ_STACK_OFFSET_XREG(block, -8, REG_XMM_TEMP); - host_x86_SUB32_REG_IMM(block, REG_ESP, 8); - } - host_x86_PUSH(block, REG_EDI); - if (size == 1) - host_x86_CALL(block, (void *)writemembl); - else if (size == 2) - host_x86_CALL(block, (void *)writememwl); - else if (size == 4) - host_x86_CALL(block, (void *)writememll); - else if (size == 8) - host_x86_CALL(block, (void *)writememql); - host_x86_POP(block, REG_EDI); - if (size == 8) - host_x86_ADD32_REG_IMM(block, REG_ESP, 8); - host_x86_POP(block, REG_ECX); - host_x86_POP(block, REG_EDX); - host_x86_POP(block, REG_EAX); - host_x86_MOVZX_REG_ABS_32_8(block, REG_ESI, &cpu_state.abrt); - host_x86_RET(block); - block_pos = (block_pos + 63) & ~63; + /*In - ECX = data, ESI = address + Out - ESI = abrt + Corrupts EDI*/ + /*MOV EDI, ESI + SHR ESI, 12 + MOV ESI, [writelookup2+ESI*4] + CMP ESI, -1 + JNZ + + MOV [ESI+EDI], ECX + XOR ESI,ESI + RET + * PUSH EAX + PUSH EDX + PUSH ECX + CALL writemembl + POP ECX + POP EDX + POP EAX + MOVZX ECX, AL + RET + */ + host_x86_MOV32_REG_REG(block, REG_EDI, REG_ESI); + host_x86_SHR32_IMM(block, REG_ESI, 12); + host_x86_MOV32_REG_ABS_INDEX_SHIFT(block, REG_ESI, writelookup2, REG_ESI, 2); + if (size != 1) { + host_x86_TEST32_REG_IMM(block, REG_EDI, size - 1); + misaligned_offset = host_x86_JNZ_short(block); + } + host_x86_CMP32_REG_IMM(block, REG_ESI, (uint32_t) -1); + branch_offset = host_x86_JZ_short(block); + if (size == 1 && !is_float) + host_x86_MOV8_BASE_INDEX_REG(block, REG_ESI, REG_EDI, REG_ECX); + else if (size == 2 && !is_float) + host_x86_MOV16_BASE_INDEX_REG(block, REG_ESI, REG_EDI, REG_ECX); + else if (size == 4 && !is_float) + host_x86_MOV32_BASE_INDEX_REG(block, REG_ESI, REG_EDI, REG_ECX); + else if (size == 4 && is_float) + host_x86_MOVD_BASE_INDEX_XREG(block, REG_ESI, REG_EDI, REG_XMM_TEMP); + else if (size == 8) + host_x86_MOVQ_BASE_INDEX_XREG(block, REG_ESI, REG_EDI, REG_XMM_TEMP); + else + fatal("build_store_routine: size=%i is_float=%i\n", size, is_float); + host_x86_XOR32_REG_REG(block, REG_ESI, REG_ESI); + host_x86_RET(block); + + *branch_offset = (uint8_t) ((uintptr_t) &block_write_data[block_pos] - (uintptr_t) branch_offset) - 1; + if (size != 1) + *misaligned_offset = (uint8_t) ((uintptr_t) &block_write_data[block_pos] - (uintptr_t) misaligned_offset) - 1; + if (size == 4 && is_float) + host_x86_MOVD_REG_XREG(block, REG_ECX, REG_XMM_TEMP); + host_x86_PUSH(block, REG_EAX); + host_x86_PUSH(block, REG_EDX); + host_x86_PUSH(block, REG_ECX); + if (size == 8) { + host_x86_MOVQ_STACK_OFFSET_XREG(block, -8, REG_XMM_TEMP); + host_x86_SUB32_REG_IMM(block, REG_ESP, 8); + } + host_x86_PUSH(block, REG_EDI); + if (size == 1) + host_x86_CALL(block, (void *) writemembl); + else if (size == 2) + host_x86_CALL(block, (void *) writememwl); + else if (size == 4) + host_x86_CALL(block, (void *) writememll); + else if (size == 8) + host_x86_CALL(block, (void *) writememql); + host_x86_POP(block, REG_EDI); + if (size == 8) + host_x86_ADD32_REG_IMM(block, REG_ESP, 8); + host_x86_POP(block, REG_ECX); + host_x86_POP(block, REG_EDX); + host_x86_POP(block, REG_EAX); + host_x86_MOVZX_REG_ABS_32_8(block, REG_ESI, &cpu_state.abrt); + host_x86_RET(block); + block_pos = (block_pos + 63) & ~63; } -static void build_loadstore_routines(codeblock_t *block) +static void +build_loadstore_routines(codeblock_t *block) { - codegen_mem_load_byte = &codeblock[block_current].data[block_pos]; - build_load_routine(block, 1, 0); - codegen_mem_load_word = &codeblock[block_current].data[block_pos]; - build_load_routine(block, 2, 0); - codegen_mem_load_long = &codeblock[block_current].data[block_pos]; - build_load_routine(block, 4, 0); - codegen_mem_load_quad = &codeblock[block_current].data[block_pos]; - build_load_routine(block, 8, 0); - codegen_mem_load_single = &codeblock[block_current].data[block_pos]; - build_load_routine(block, 4, 1); - codegen_mem_load_double = &codeblock[block_current].data[block_pos]; - build_load_routine(block, 8, 1); + codegen_mem_load_byte = &codeblock[block_current].data[block_pos]; + build_load_routine(block, 1, 0); + codegen_mem_load_word = &codeblock[block_current].data[block_pos]; + build_load_routine(block, 2, 0); + codegen_mem_load_long = &codeblock[block_current].data[block_pos]; + build_load_routine(block, 4, 0); + codegen_mem_load_quad = &codeblock[block_current].data[block_pos]; + build_load_routine(block, 8, 0); + codegen_mem_load_single = &codeblock[block_current].data[block_pos]; + build_load_routine(block, 4, 1); + codegen_mem_load_double = &codeblock[block_current].data[block_pos]; + build_load_routine(block, 8, 1); - codegen_mem_store_byte = &codeblock[block_current].data[block_pos]; - build_store_routine(block, 1, 0); - codegen_mem_store_word = &codeblock[block_current].data[block_pos]; - build_store_routine(block, 2, 0); - codegen_mem_store_long = &codeblock[block_current].data[block_pos]; - build_store_routine(block, 4, 0); - codegen_mem_store_quad = &codeblock[block_current].data[block_pos]; - build_store_routine(block, 8, 0); - codegen_mem_store_single = &codeblock[block_current].data[block_pos]; - build_store_routine(block, 4, 1); - codegen_mem_store_double = &codeblock[block_current].data[block_pos]; - build_store_routine(block, 8, 1); + codegen_mem_store_byte = &codeblock[block_current].data[block_pos]; + build_store_routine(block, 1, 0); + codegen_mem_store_word = &codeblock[block_current].data[block_pos]; + build_store_routine(block, 2, 0); + codegen_mem_store_long = &codeblock[block_current].data[block_pos]; + build_store_routine(block, 4, 0); + codegen_mem_store_quad = &codeblock[block_current].data[block_pos]; + build_store_routine(block, 8, 0); + codegen_mem_store_single = &codeblock[block_current].data[block_pos]; + build_store_routine(block, 4, 1); + codegen_mem_store_double = &codeblock[block_current].data[block_pos]; + build_store_routine(block, 8, 1); } -void codegen_backend_init() +void +codegen_backend_init(void) { - codeblock_t *block; - int c; -#if defined(__linux__) || defined(__APPLE__) - void *start; - size_t len; - long pagesize = sysconf(_SC_PAGESIZE); - long pagemask = ~(pagesize - 1); -#endif - codeblock = malloc(BLOCK_SIZE * sizeof(codeblock_t)); - codeblock_hash = malloc(HASH_SIZE * sizeof(codeblock_t *)); + codeblock_t *block; - memset(codeblock, 0, BLOCK_SIZE * sizeof(codeblock_t)); - memset(codeblock_hash, 0, HASH_SIZE * sizeof(codeblock_t *)); + codeblock = malloc(BLOCK_SIZE * sizeof(codeblock_t)); + codeblock_hash = malloc(HASH_SIZE * sizeof(codeblock_t *)); - for (c = 0; c < BLOCK_SIZE; c++) - codeblock[c].pc = BLOCK_PC_INVALID; + memset(codeblock, 0, BLOCK_SIZE * sizeof(codeblock_t)); + memset(codeblock_hash, 0, HASH_SIZE * sizeof(codeblock_t *)); - block_current = 0; - block_pos = 0; - block = &codeblock[block_current]; - block->head_mem_block = codegen_allocator_allocate(NULL, block_current); - block->data = codeblock_allocator_get_ptr(block->head_mem_block); - block_write_data = block->data; - build_loadstore_routines(block); - - codegen_gpf_rout = &codeblock[block_current].data[block_pos]; - host_x86_MOV32_STACK_IMM(block, STACK_ARG0, 0); - host_x86_MOV32_STACK_IMM(block, STACK_ARG1, 0); - host_x86_CALL(block, (void *)x86gpf); - codegen_exit_rout = &codeblock[block_current].data[block_pos]; - host_x86_ADD32_REG_IMM(block, REG_ESP, 64); - host_x86_POP(block, REG_EDI); - host_x86_POP(block, REG_ESI); - host_x86_POP(block, REG_EBP); - host_x86_POP(block, REG_EDX); - host_x86_RET(block); - block_write_data = NULL; + for (uint32_t c = 0; c < BLOCK_SIZE; c++) + codeblock[c].pc = BLOCK_PC_INVALID; - cpu_state.old_fp_control = 0; - asm( - "fstcw %0\n" - "stmxcsr %1\n" - : "=m" (cpu_state.old_fp_control2), - "=m" (cpu_state.old_fp_control) - ); - cpu_state.trunc_fp_control = cpu_state.old_fp_control | 0x6000; + block_current = 0; + block_pos = 0; + block = &codeblock[block_current]; + block->head_mem_block = codegen_allocator_allocate(NULL, block_current); + block->data = codeblock_allocator_get_ptr(block->head_mem_block); + block_write_data = block->data; + build_loadstore_routines(block); + + codegen_gpf_rout = &codeblock[block_current].data[block_pos]; + host_x86_MOV32_STACK_IMM(block, STACK_ARG0, 0); + host_x86_MOV32_STACK_IMM(block, STACK_ARG1, 0); + host_x86_CALL(block, (void *) x86gpf); + codegen_exit_rout = &codeblock[block_current].data[block_pos]; + host_x86_ADD32_REG_IMM(block, REG_ESP, 64); + host_x86_POP(block, REG_EDI); + host_x86_POP(block, REG_ESI); + host_x86_POP(block, REG_EBP); + host_x86_POP(block, REG_EDX); + host_x86_RET(block); + block_write_data = NULL; + + cpu_state.old_fp_control = 0; + asm( + "fstcw %0\n" + "stmxcsr %1\n" + : "=m"(cpu_state.old_fp_control2), + "=m"(cpu_state.old_fp_control)); + cpu_state.trunc_fp_control = cpu_state.old_fp_control | 0x6000; } -void codegen_set_rounding_mode(int mode) +void +codegen_set_rounding_mode(int mode) { - /*SSE*/ - cpu_state.new_fp_control = (cpu_state.old_fp_control & ~0x6000) | (mode << 13); - /*x87 - used for double -> i64 conversions*/ - cpu_state.new_fp_control2 = (cpu_state.old_fp_control2 & ~0x0c00) | (mode << 10); + /*SSE*/ + cpu_state.new_fp_control = (cpu_state.old_fp_control & ~0x6000) | (mode << 13); + /*x87 - used for double -> i64 conversions*/ + cpu_state.new_fp_control2 = (cpu_state.old_fp_control2 & ~0x0c00) | (mode << 10); } -void codegen_backend_prologue(codeblock_t *block) +void +codegen_backend_prologue(codeblock_t *block) { - block_pos = BLOCK_START; /*Entry code*/ - host_x86_PUSH(block, REG_EBX); - host_x86_PUSH(block, REG_EBP); - host_x86_PUSH(block, REG_ESI); - host_x86_PUSH(block, REG_EDI); - host_x86_SUB32_REG_IMM(block, REG_ESP, 64); - host_x86_MOV32_REG_IMM(block, REG_EBP, ((uintptr_t)&cpu_state) + 128); - if (block->flags & CODEBLOCK_HAS_FPU) - { - host_x86_MOV32_REG_ABS(block, REG_EAX, &cpu_state.TOP); - host_x86_SUB32_REG_IMM(block, REG_EAX, block->TOP); - host_x86_MOV32_BASE_OFFSET_REG(block, REG_ESP, IREG_TOP_diff_stack_offset, REG_EAX); - } + block_pos = BLOCK_START; /*Entry code*/ + host_x86_PUSH(block, REG_EBX); + host_x86_PUSH(block, REG_EBP); + host_x86_PUSH(block, REG_ESI); + host_x86_PUSH(block, REG_EDI); + host_x86_SUB32_REG_IMM(block, REG_ESP, 64); + host_x86_MOV32_REG_IMM(block, REG_EBP, ((uintptr_t) &cpu_state) + 128); + if (block->flags & CODEBLOCK_HAS_FPU) { + host_x86_MOV32_REG_ABS(block, REG_EAX, &cpu_state.TOP); + host_x86_SUB32_REG_IMM(block, REG_EAX, block->TOP); + host_x86_MOV32_BASE_OFFSET_REG(block, REG_ESP, IREG_TOP_diff_stack_offset, REG_EAX); + } } -void codegen_backend_epilogue(codeblock_t *block) +void +codegen_backend_epilogue(codeblock_t *block) { - host_x86_ADD32_REG_IMM(block, REG_ESP, 64); - host_x86_POP(block, REG_EDI); - host_x86_POP(block, REG_ESI); - host_x86_POP(block, REG_EBP); - host_x86_POP(block, REG_EDX); - host_x86_RET(block); + host_x86_ADD32_REG_IMM(block, REG_ESP, 64); + host_x86_POP(block, REG_EDI); + host_x86_POP(block, REG_ESI); + host_x86_POP(block, REG_EBP); + host_x86_POP(block, REG_EDX); + host_x86_RET(block); } #endif diff --git a/src/codegen_new/codegen_backend_x86.h b/src/codegen_new/codegen_backend_x86.h index 582e46430..646289fab 100644 --- a/src/codegen_new/codegen_backend_x86.h +++ b/src/codegen_new/codegen_backend_x86.h @@ -1,14 +1,14 @@ #include "codegen_backend_x86_defs.h" -#define BLOCK_SIZE 0x10000 -#define BLOCK_MASK 0xffff +#define BLOCK_SIZE 0x10000 +#define BLOCK_MASK 0xffff #define BLOCK_START 0 -#define HASH_SIZE 0x20000 -#define HASH_MASK 0x1ffff +#define HASH_SIZE 0x20000 +#define HASH_MASK 0x1ffff -#define HASH(l) ((l) & 0x1ffff) +#define HASH(l) ((l) &0x1ffff) -#define BLOCK_MAX 0x3c0 +#define BLOCK_MAX 0x3c0 #define CODEGEN_BACKEND_HAS_MOV_IMM diff --git a/src/codegen_new/codegen_backend_x86_defs.h b/src/codegen_new/codegen_backend_x86_defs.h index 25964ba3c..a86d6f309 100644 --- a/src/codegen_new/codegen_backend_x86_defs.h +++ b/src/codegen_new/codegen_backend_x86_defs.h @@ -1,28 +1,28 @@ #ifndef _CODEGEN_BACKEND_X86_DEFS_H_ #define _CODEGEN_BACKEND_X86_DEFS_H_ -#define REG_EAX 0 -#define REG_ECX 1 -#define REG_EDX 2 -#define REG_EBX 3 -#define REG_ESP 4 -#define REG_EBP 5 -#define REG_ESI 6 -#define REG_EDI 7 +#define REG_EAX 0 +#define REG_ECX 1 +#define REG_EDX 2 +#define REG_EBX 3 +#define REG_ESP 4 +#define REG_EBP 5 +#define REG_ESI 6 +#define REG_EDI 7 -#define REG_XMM0 0 -#define REG_XMM1 1 -#define REG_XMM2 2 -#define REG_XMM3 3 -#define REG_XMM4 4 -#define REG_XMM5 5 -#define REG_XMM6 6 -#define REG_XMM7 7 +#define REG_XMM0 0 +#define REG_XMM1 1 +#define REG_XMM2 2 +#define REG_XMM3 3 +#define REG_XMM4 4 +#define REG_XMM5 5 +#define REG_XMM6 6 +#define REG_XMM7 7 -#define REG_XMM_TEMP REG_XMM7 -#define REG_XMM_TEMP2 REG_XMM6 +#define REG_XMM_TEMP REG_XMM7 +#define REG_XMM_TEMP2 REG_XMM6 -#define CODEGEN_HOST_REGS 3 +#define CODEGEN_HOST_REGS 3 #define CODEGEN_HOST_FP_REGS 6 extern void *codegen_mem_load_byte; diff --git a/src/codegen_new/codegen_backend_x86_ops.c b/src/codegen_new/codegen_backend_x86_ops.c index 5e89ffbc8..90e59dcb0 100644 --- a/src/codegen_new/codegen_backend_x86_ops.c +++ b/src/codegen_new/codegen_backend_x86_ops.c @@ -1,1334 +1,1312 @@ #if defined i386 || defined __i386 || defined __i386__ || defined _X86_ || defined _M_IX86 -#include -#include <86box/86box.h> -#include "cpu.h" -#include <86box/mem.h> +# include +# include <86box/86box.h> +# include "cpu.h" +# include <86box/mem.h> +# include <86box/plat_unused.h> -#include "codegen.h" -#include "codegen_allocator.h" -#include "codegen_backend.h" -#include "codegen_backend_x86_defs.h" -#include "codegen_backend_x86_ops.h" -#include "codegen_backend_x86_ops_helpers.h" +# include "codegen.h" +# include "codegen_allocator.h" +# include "codegen_backend.h" +# include "codegen_backend_x86_defs.h" +# include "codegen_backend_x86_ops.h" +# include "codegen_backend_x86_ops_helpers.h" -#define RM_OP_ADD 0x00 -#define RM_OP_OR 0x08 -#define RM_OP_AND 0x20 -#define RM_OP_SUB 0x28 -#define RM_OP_XOR 0x30 -#define RM_OP_CMP 0x38 +# define RM_OP_ADD 0x00 +# define RM_OP_OR 0x08 +# define RM_OP_AND 0x20 +# define RM_OP_SUB 0x28 +# define RM_OP_XOR 0x30 +# define RM_OP_CMP 0x38 -#define RM_OP_ROL 0x00 -#define RM_OP_ROR 0x08 -#define RM_OP_SHL 0x20 -#define RM_OP_SHR 0x28 -#define RM_OP_SAR 0x38 +# define RM_OP_ROL 0x00 +# define RM_OP_ROR 0x08 +# define RM_OP_SHL 0x20 +# define RM_OP_SHR 0x28 +# define RM_OP_SAR 0x38 -void host_x86_ADD32_REG_ABS(codeblock_t *block, int dst_reg, void *p) +void +host_x86_ADD32_REG_ABS(codeblock_t *block, int dst_reg, void *p) { - int offset = (uintptr_t)p - (((uintptr_t)&cpu_state) + 128); + int offset = (uintptr_t) p - (((uintptr_t) &cpu_state) + 128); - if (offset >= -128 && offset < 127) - { - codegen_alloc_bytes(block, 3); - codegen_addbyte3(block, 0x03, 0x45 | (dst_reg << 3), offset); /*MOV offset[EBP], src_reg*/ - } - else - { - codegen_alloc_bytes(block, 6); - codegen_addbyte(block, 0x03); /*MOV [p], src_reg*/ - codegen_addbyte(block, 0x05 | (dst_reg << 3)); - codegen_addlong(block, (uint32_t)p); - } -} - -void host_x86_ADD8_REG_IMM(codeblock_t *block, int dst_reg, uint8_t imm_data) -{ - if (dst_reg == REG_EAX) - { - codegen_alloc_bytes(block, 2); - codegen_addbyte2(block, 0x04, imm_data); /*ADD AL, imm_data*/ - } - else - { - codegen_alloc_bytes(block, 3); - codegen_addbyte3(block, 0x80, 0xc0 | RM_OP_ADD | dst_reg, imm_data); /*ADD dst_reg, imm_data*/ - } -} -void host_x86_ADD16_REG_IMM(codeblock_t *block, int dst_reg, uint16_t imm_data) -{ - if (is_imm8(imm_data)) - { - codegen_alloc_bytes(block, 4); - codegen_addbyte4(block, 0x66, 0x83, 0xc0 | RM_OP_ADD | dst_reg, imm_data & 0xff); /*ADD dst_reg, imm_data*/ - } - else if (dst_reg == REG_EAX) - { - codegen_alloc_bytes(block, 4); - codegen_addbyte2(block, 0x66, 0x05); /*ADD AX, imm_data*/ - codegen_addword(block, imm_data); - } - else - { - codegen_alloc_bytes(block, 5); - codegen_addbyte3(block, 0x66, 0x81, 0xc0 | RM_OP_ADD | dst_reg); /*ADD dst_reg, imm_data*/ - codegen_addword(block, imm_data); - } -} -void host_x86_ADD32_REG_IMM(codeblock_t *block, int dst_reg, uint32_t imm_data) -{ - if (is_imm8(imm_data)) - { - codegen_alloc_bytes(block, 3); - codegen_addbyte3(block, 0x83, 0xc0 | RM_OP_ADD | dst_reg, imm_data & 0xff); /*ADD dst_reg, imm_data*/ - } - else if (dst_reg == REG_EAX) - { - codegen_alloc_bytes(block, 5); - codegen_addbyte(block, 0x05); /*ADD EAX, imm_data*/ - codegen_addlong(block, imm_data); - } - else - { - codegen_alloc_bytes(block, 6); - codegen_addbyte2(block, 0x81, 0xc0 | RM_OP_ADD | dst_reg); /*ADD dst_reg, imm_data*/ - codegen_addlong(block, imm_data); - } -} - -void host_x86_ADD8_REG_REG(codeblock_t *block, int dst_reg, int src_reg) -{ - codegen_alloc_bytes(block, 2); - codegen_addbyte2(block, 0x00, 0xc0 | dst_reg | (src_reg << 3)); /*ADD dst_reg, src_reg*/ -} -void host_x86_ADD16_REG_REG(codeblock_t *block, int dst_reg, int src_reg) -{ + if (offset >= -128 && offset < 127) { codegen_alloc_bytes(block, 3); - codegen_addbyte3(block, 0x66, 0x01, 0xc0 | dst_reg | (src_reg << 3)); /*ADD dst_reg, src_reg*/ + codegen_addbyte3(block, 0x03, 0x45 | (dst_reg << 3), offset); /*MOV offset[EBP], src_reg*/ + } else { + codegen_alloc_bytes(block, 6); + codegen_addbyte(block, 0x03); /*MOV [p], src_reg*/ + codegen_addbyte(block, 0x05 | (dst_reg << 3)); + codegen_addlong(block, (uint32_t) p); + } } -void host_x86_ADD32_REG_REG(codeblock_t *block, int dst_reg, int src_reg) + +void +host_x86_ADD8_REG_IMM(codeblock_t *block, int dst_reg, uint8_t imm_data) { + if (dst_reg == REG_EAX) { + codegen_alloc_bytes(block, 2); + codegen_addbyte2(block, 0x04, imm_data); /*ADD AL, imm_data*/ + } else { codegen_alloc_bytes(block, 3); - codegen_addbyte2(block, 0x01, 0xc0 | dst_reg | (src_reg << 3)); /*ADD dst_reg, src_reg*/ + codegen_addbyte3(block, 0x80, 0xc0 | RM_OP_ADD | dst_reg, imm_data); /*ADD dst_reg, imm_data*/ + } } - -void host_x86_AND8_REG_IMM(codeblock_t *block, int dst_reg, uint8_t imm_data) -{ - if (dst_reg == REG_EAX) - { - codegen_alloc_bytes(block, 2); - codegen_addbyte2(block, 0x24, imm_data); /*AND AL, imm_data*/ - } - else - { - codegen_alloc_bytes(block, 3); - codegen_addbyte3(block, 0x80, 0xc0 | RM_OP_AND | dst_reg, imm_data); /*AND dst_reg, imm_data*/ - } -} -void host_x86_AND16_REG_IMM(codeblock_t *block, int dst_reg, uint16_t imm_data) -{ - if (is_imm8(imm_data)) - { - codegen_alloc_bytes(block, 4); - codegen_addbyte4(block, 0x66, 0x83, 0xc0 | RM_OP_AND | dst_reg, imm_data & 0xff); /*AND dst_reg, imm_data*/ - } - else if (dst_reg == REG_EAX) - { - codegen_alloc_bytes(block, 6); - codegen_addbyte2(block, 0x66, 0x25); /*AND AX, imm_data*/ - codegen_addword(block, imm_data); - } - else - { - codegen_alloc_bytes(block, 5); - codegen_addbyte3(block, 0x66, 0x81, 0xc0 | RM_OP_AND | dst_reg); /*AND dst_reg, imm_data*/ - codegen_addword(block, imm_data); - } -} -void host_x86_AND32_REG_IMM(codeblock_t *block, int dst_reg, uint32_t imm_data) -{ - if (is_imm8(imm_data)) - { - codegen_alloc_bytes(block, 3); - codegen_addbyte3(block, 0x83, 0xc0 | RM_OP_AND | dst_reg, imm_data & 0xff); /*AND dst_reg, imm_data*/ - } - else if (dst_reg == REG_EAX) - { - codegen_alloc_bytes(block, 5); - codegen_addbyte(block, 0x25); /*AND EAX, imm_data*/ - codegen_addlong(block, imm_data); - } - else - { - codegen_alloc_bytes(block, 6); - codegen_addbyte2(block, 0x81, 0xc0 | RM_OP_AND | dst_reg); /*AND dst_reg, imm_data*/ - codegen_addlong(block, imm_data); - } -} - -void host_x86_AND8_REG_REG(codeblock_t *block, int dst_reg, int src_reg) -{ - codegen_alloc_bytes(block, 2); - codegen_addbyte2(block, 0x20, 0xc0 | dst_reg | (src_reg << 3)); /*AND dst_reg, src_reg_b*/ -} -void host_x86_AND16_REG_REG(codeblock_t *block, int dst_reg, int src_reg) -{ - codegen_alloc_bytes(block, 3); - codegen_addbyte3(block, 0x66, 0x21, 0xc0 | dst_reg | (src_reg << 3)); /*AND dst_reg, src_reg_b*/ -} -void host_x86_AND32_REG_REG(codeblock_t *block, int dst_reg, int src_reg) -{ - codegen_alloc_bytes(block, 2); - codegen_addbyte2(block, 0x21, 0xc0 | dst_reg | (src_reg << 3)); /*AND dst_reg, src_reg_b*/ -} - -void host_x86_CALL(codeblock_t *block, void *p) -{ - codegen_alloc_bytes(block, 5); - codegen_addbyte(block, 0xe8); /*CALL*/ - codegen_addlong(block, (uintptr_t)p - (uintptr_t)&block_write_data[block_pos + 4]); -} - -void host_x86_CMP16_REG_IMM(codeblock_t *block, int dst_reg, uint16_t imm_data) -{ - if (is_imm8(imm_data)) - { - codegen_alloc_bytes(block, 4); - codegen_addbyte4(block, 0x66, 0x83, 0xc0 | RM_OP_CMP | dst_reg, imm_data & 0xff); /*CMP dst_reg, imm_data*/ - } - else if (dst_reg == REG_EAX) - { - codegen_alloc_bytes(block, 4); - codegen_addbyte2(block, 0x66, 0x3d); /*CMP AX, imm_data*/ - codegen_addword(block, imm_data); - } - else - { - codegen_alloc_bytes(block, 5); - codegen_addbyte3(block, 0x66, 0x81, 0xc0 | RM_OP_CMP | dst_reg); /*CMP dst_reg, imm_data*/ - codegen_addword(block, imm_data); - } -} -void host_x86_CMP32_REG_IMM(codeblock_t *block, int dst_reg, uint32_t imm_data) -{ - if (is_imm8(imm_data)) - { - codegen_alloc_bytes(block, 3); - codegen_addbyte3(block, 0x83, 0xc0 | RM_OP_CMP | dst_reg, imm_data & 0xff); /*CMP dst_reg, imm_data*/ - } - else if (dst_reg == REG_EAX) - { - codegen_alloc_bytes(block, 5); - codegen_addbyte(block, 0x3d); /*CMP EAX, imm_data*/ - codegen_addlong(block, imm_data); - } - else - { - codegen_alloc_bytes(block, 6); - codegen_addbyte2(block, 0x81, 0xc0 | RM_OP_CMP | dst_reg); /*CMP dst_reg, imm_data*/ - codegen_addlong(block, imm_data); - } -} - -void host_x86_CMP8_REG_REG(codeblock_t *block, int src_reg_a, int src_reg_b) -{ - codegen_alloc_bytes(block, 2); - codegen_addbyte2(block, 0x38, 0xc0 | src_reg_a | (src_reg_b << 3)); /*CMP src_reg_a, src_reg_b*/ -} -void host_x86_CMP16_REG_REG(codeblock_t *block, int src_reg_a, int src_reg_b) -{ - codegen_alloc_bytes(block, 3); - codegen_addbyte3(block, 0x66, 0x39, 0xc0 | src_reg_a | (src_reg_b << 3)); /*CMP src_reg_a, src_reg_b*/ -} -void host_x86_CMP32_REG_REG(codeblock_t *block, int src_reg_a, int src_reg_b) -{ - codegen_alloc_bytes(block, 2); - codegen_addbyte2(block, 0x39, 0xc0 | src_reg_a | (src_reg_b << 3)); /*CMP src_reg_a, src_reg_b*/ -} - -void host_x86_INC32_ABS(codeblock_t *block, void *p) -{ - codegen_alloc_bytes(block, 6); - codegen_addbyte2(block, 0xff, 0x05); /*INC p*/ - codegen_addlong(block, (uint32_t)p); -} - -void host_x86_JMP(codeblock_t *block, void *p) -{ - codegen_alloc_bytes(block, 5); - codegen_addbyte(block, 0xe9); /*JMP*/ - codegen_addlong(block, (uintptr_t)p - (uintptr_t)&block_write_data[block_pos + 4]); -} -uint32_t *host_x86_JMP_long(codeblock_t *block) -{ - codegen_alloc_bytes(block, 5); - codegen_addbyte(block, 0xe9); /*JMP*/ - codegen_addlong(block, 0); - return (uint32_t *)&block_write_data[block_pos-4]; -} - -void host_x86_JNZ(codeblock_t *block, void *p) -{ - codegen_alloc_bytes(block, 6); - codegen_addbyte2(block, 0x0f, 0x85); /*JNZ*/ - codegen_addlong(block, (uintptr_t)p - (uintptr_t)&block_write_data[block_pos + 4]); -} -void host_x86_JZ(codeblock_t *block, void *p) -{ - codegen_alloc_bytes(block, 6); - codegen_addbyte2(block, 0x0f, 0x84); /*JZ*/ - codegen_addlong(block, (uintptr_t)p - (uintptr_t)&block_write_data[block_pos + 4]); -} - -uint8_t *host_x86_JNZ_short(codeblock_t *block) -{ - codegen_alloc_bytes(block, 2); - codegen_addbyte2(block, 0x75, 0); /*JNZ*/ - return &block_write_data[block_pos-1]; -} -uint8_t *host_x86_JS_short(codeblock_t *block) -{ - codegen_alloc_bytes(block, 2); - codegen_addbyte2(block, 0x78, 0); /*JS*/ - return &block_write_data[block_pos-1]; -} -uint8_t *host_x86_JZ_short(codeblock_t *block) -{ - codegen_alloc_bytes(block, 2); - codegen_addbyte2(block, 0x74, 0); /*JZ*/ - return &block_write_data[block_pos-1]; -} - -uint32_t *host_x86_JNB_long(codeblock_t *block) -{ - codegen_alloc_bytes(block, 6); - codegen_addbyte2(block, 0x0f, 0x83); /*JNB*/ - codegen_addlong(block, 0); - return (uint32_t *)&block_write_data[block_pos-4]; -} -uint32_t *host_x86_JNBE_long(codeblock_t *block) -{ - codegen_alloc_bytes(block, 6); - codegen_addbyte2(block, 0x0f, 0x87); /*JNBE*/ - codegen_addlong(block, 0); - return (uint32_t *)&block_write_data[block_pos-4]; -} -uint32_t *host_x86_JNL_long(codeblock_t *block) -{ - codegen_alloc_bytes(block, 6); - codegen_addbyte2(block, 0x0f, 0x8d); /*JNL*/ - codegen_addlong(block, 0); - return (uint32_t *)&block_write_data[block_pos-4]; -} -uint32_t *host_x86_JNLE_long(codeblock_t *block) -{ - codegen_alloc_bytes(block, 6); - codegen_addbyte2(block, 0x0f, 0x8f); /*JNLE*/ - codegen_addlong(block, 0); - return (uint32_t *)&block_write_data[block_pos-4]; -} -uint32_t *host_x86_JNO_long(codeblock_t *block) -{ - codegen_alloc_bytes(block, 6); - codegen_addbyte2(block, 0x0f, 0x81); /*JNO*/ - codegen_addlong(block, 0); - return (uint32_t *)&block_write_data[block_pos-4]; -} -uint32_t *host_x86_JNS_long(codeblock_t *block) -{ - codegen_alloc_bytes(block, 6); - codegen_addbyte2(block, 0x0f, 0x89); /*JNS*/ - codegen_addlong(block, 0); - return (uint32_t *)&block_write_data[block_pos-4]; -} -uint32_t *host_x86_JNZ_long(codeblock_t *block) -{ - codegen_alloc_bytes(block, 6); - codegen_addbyte2(block, 0x0f, 0x85); /*JNZ*/ - codegen_addlong(block, 0); - return (uint32_t *)&block_write_data[block_pos-4]; -} -uint32_t *host_x86_JB_long(codeblock_t *block) -{ - codegen_alloc_bytes(block, 6); - codegen_addbyte2(block, 0x0f, 0x82); /*JB*/ - codegen_addlong(block, 0); - return (uint32_t *)&block_write_data[block_pos-4]; -} -uint32_t *host_x86_JBE_long(codeblock_t *block) -{ - codegen_alloc_bytes(block, 6); - codegen_addbyte2(block, 0x0f, 0x86); /*JBE*/ - codegen_addlong(block, 0); - return (uint32_t *)&block_write_data[block_pos-4]; -} -uint32_t *host_x86_JL_long(codeblock_t *block) -{ - codegen_alloc_bytes(block, 6); - codegen_addbyte2(block, 0x0f, 0x8c); /*JL*/ - codegen_addlong(block, 0); - return (uint32_t *)&block_write_data[block_pos-4]; -} -uint32_t *host_x86_JLE_long(codeblock_t *block) -{ - codegen_alloc_bytes(block, 6); - codegen_addbyte2(block, 0x0f, 0x8e); /*JLE*/ - codegen_addlong(block, 0); - return (uint32_t *)&block_write_data[block_pos-4]; -} -uint32_t *host_x86_JO_long(codeblock_t *block) -{ - codegen_alloc_bytes(block, 6); - codegen_addbyte2(block, 0x0f, 0x80); /*JO*/ - codegen_addlong(block, 0); - return (uint32_t *)&block_write_data[block_pos-4]; -} -uint32_t *host_x86_JS_long(codeblock_t *block) -{ - codegen_alloc_bytes(block, 6); - codegen_addbyte2(block, 0x0f, 0x88); /*JS*/ - codegen_addlong(block, 0); - return (uint32_t *)&block_write_data[block_pos-4]; -} -uint32_t *host_x86_JZ_long(codeblock_t *block) -{ - codegen_alloc_bytes(block, 6); - codegen_addbyte2(block, 0x0f, 0x84); /*JZ*/ - codegen_addlong(block, 0); - return (uint32_t *)&block_write_data[block_pos-4]; -} - -void host_x86_LAHF(codeblock_t *block) -{ - codegen_alloc_bytes(block, 1); - codegen_addbyte(block, 0x9f); /*LAHF*/ -} - -void host_x86_LEA_REG_IMM(codeblock_t *block, int dst_reg, int src_reg, uint32_t offset) -{ - if (offset) - { - codegen_alloc_bytes(block, 6); - codegen_addbyte2(block, 0x8d, 0x80 | (dst_reg << 3) | src_reg); /*LEA dst_reg, [offset+src_reg]*/ - codegen_addlong(block, offset); - } - else - { - codegen_alloc_bytes(block, 2); - codegen_addbyte2(block, 0x8d, 0x00 | (dst_reg << 3) | src_reg); /*LEA dst_reg, [src_reg]*/ - } -} - -void host_x86_LEA_REG_REG(codeblock_t *block, int dst_reg, int src_reg_a, int src_reg_b) -{ - codegen_alloc_bytes(block, 3); - codegen_addbyte3(block, 0x8d, 0x04 | (dst_reg << 3), (src_reg_b << 3) | src_reg_a); /*LEA dst_reg, [src_reg_a + src_reg_b]*/ -} -void host_x86_LEA_REG_REG_SHIFT(codeblock_t *block, int dst_reg, int src_reg_a, int src_reg_b, int shift) -{ - codegen_alloc_bytes(block, 3); - codegen_addbyte3(block, 0x8d, 0x04 | (dst_reg << 3), (shift << 6) | (src_reg_b << 3) | src_reg_a); /*LEA dst_reg, [src_reg_a + src_reg_b * (1 << shift)]*/ -} - -void host_x86_MOV8_ABS_IMM(codeblock_t *block, void *p, uint32_t imm_data) -{ - int offset = (uintptr_t)p - (((uintptr_t)&cpu_state) + 128); - - if (offset >= -128 && offset < 127) - { - codegen_alloc_bytes(block, 4); - codegen_addbyte3(block, 0xc6, 0x45, offset); /*MOVB offset[EBP], imm_data*/ - codegen_addbyte(block, imm_data); - } - else - { - codegen_alloc_bytes(block, 7); - codegen_addbyte2(block, 0xc6, 0x05); /*MOVB p, imm_data*/ - codegen_addlong(block, (uint32_t)p); - codegen_addbyte(block, imm_data); - } -} -void host_x86_MOV16_ABS_IMM(codeblock_t *block, void *p, uint16_t imm_data) -{ - int offset = (uintptr_t)p - (((uintptr_t)&cpu_state) + 128); - - if (offset >= -128 && offset < 127) - { - codegen_alloc_bytes(block, 6); - codegen_addbyte4(block, 0x66, 0xc7, 0x45, offset); /*MOV offset[EBP], imm_data*/ - codegen_addword(block, imm_data); - } - else - { - codegen_alloc_bytes(block, 9); - codegen_addbyte3(block, 0x66, 0xc7, 0x05); /*MOV p, imm_data*/ - codegen_addlong(block, (uint32_t)p); - codegen_addword(block, imm_data); - } -} -void host_x86_MOV32_ABS_IMM(codeblock_t *block, void *p, uint32_t imm_data) -{ - int offset = (uintptr_t)p - (((uintptr_t)&cpu_state) + 128); - - if (offset >= -128 && offset < 127) - { - codegen_alloc_bytes(block, 7); - codegen_addbyte3(block, 0xc7, 0x45, offset); /*MOV offset[EBP], imm_data*/ - codegen_addlong(block, imm_data); - } - else - { - codegen_alloc_bytes(block, 10); - codegen_addbyte2(block, 0xc7, 0x05); /*MOV p, imm_data*/ - codegen_addlong(block, (uint32_t)p); - codegen_addlong(block, imm_data); - } -} - -void host_x86_MOV8_ABS_REG(codeblock_t *block, void *p, int src_reg) -{ - int offset = (uintptr_t)p - (((uintptr_t)&cpu_state) + 128); - - if (offset >= -128 && offset < 127) - { - codegen_alloc_bytes(block, 3); - codegen_addbyte3(block, 0x88, 0x45 | (src_reg << 3), offset); /*MOVB offset[EBP], src_reg*/ - } - else - { - codegen_alloc_bytes(block, 6); - codegen_addbyte(block, 0x88); /*MOVB [p], src_reg*/ - codegen_addbyte(block, 0x05 | (src_reg << 3)); - codegen_addlong(block, (uint32_t)p); - } -} -void host_x86_MOV16_ABS_REG(codeblock_t *block, void *p, int src_reg) -{ - int offset = (uintptr_t)p - (((uintptr_t)&cpu_state) + 128); - - if (offset >= -128 && offset < 127) - { - codegen_alloc_bytes(block, 4); - codegen_addbyte4(block, 0x66, 0x89, 0x45 | (src_reg << 3), offset); /*MOV offset[EBP], src_reg*/ - } - else - { - codegen_alloc_bytes(block, 7); - codegen_addbyte3(block, 0x66, 0x89, 0x05 | (src_reg << 3)); /*MOV [p], src_reg*/ - codegen_addlong(block, (uint32_t)p); - } -} -void host_x86_MOV32_ABS_REG(codeblock_t *block, void *p, int src_reg) -{ - int offset = (uintptr_t)p - (((uintptr_t)&cpu_state) + 128); - - if (offset >= -128 && offset < 127) - { - codegen_alloc_bytes(block, 3); - codegen_addbyte3(block, 0x89, 0x45 | (src_reg << 3), offset); /*MOV offset[EBP], src_reg*/ - } - else - { - codegen_alloc_bytes(block, 6); - codegen_addbyte(block, 0x89); /*MOV [p], src_reg*/ - codegen_addbyte(block, 0x05 | (src_reg << 3)); - codegen_addlong(block, (uint32_t)p); - } -} - -void host_x86_MOV8_ABS_REG_REG_SHIFT_REG(codeblock_t *block, uint32_t addr, int base_reg, int idx_reg, int shift, int src_reg) -{ - if (addr < 0x80 || addr >= 0xffffff80) - { - codegen_alloc_bytes(block, 4); - codegen_addbyte4(block, 0x88, 0x44 | (src_reg << 3), base_reg | (idx_reg << 3) | (shift << 6), addr & 0xff); /*MOV addr[base_reg + idx_reg << shift], src_reg*/ - } - else - { - codegen_alloc_bytes(block, 7); - codegen_addbyte3(block, 0x88, 0x84 | (src_reg << 3), base_reg | (idx_reg << 3) | (shift << 6)); /*MOV addr[base_reg + idx_reg << shift], src_reg*/ - codegen_addlong(block, addr); - } -} - -void host_x86_MOV8_BASE_INDEX_REG(codeblock_t *block, int base_reg, int idx_reg, int src_reg) -{ - codegen_alloc_bytes(block, 3); - codegen_addbyte3(block, 0x88, 0x04 | (src_reg << 3), base_reg | (idx_reg << 3)); /*MOV B[base_reg + idx_reg], src_reg*/ -} -void host_x86_MOV16_BASE_INDEX_REG(codeblock_t *block, int base_reg, int idx_reg, int src_reg) +void +host_x86_ADD16_REG_IMM(codeblock_t *block, int dst_reg, uint16_t imm_data) { + if (is_imm8(imm_data)) { codegen_alloc_bytes(block, 4); - codegen_addbyte4(block, 0x66, 0x89, 0x04 | (src_reg << 3), base_reg | (idx_reg << 3)); /*MOV W[base_reg + idx_reg], src_reg*/ + codegen_addbyte4(block, 0x66, 0x83, 0xc0 | RM_OP_ADD | dst_reg, imm_data & 0xff); /*ADD dst_reg, imm_data*/ + } else if (dst_reg == REG_EAX) { + codegen_alloc_bytes(block, 4); + codegen_addbyte2(block, 0x66, 0x05); /*ADD AX, imm_data*/ + codegen_addword(block, imm_data); + } else { + codegen_alloc_bytes(block, 5); + codegen_addbyte3(block, 0x66, 0x81, 0xc0 | RM_OP_ADD | dst_reg); /*ADD dst_reg, imm_data*/ + codegen_addword(block, imm_data); + } } -void host_x86_MOV32_BASE_INDEX_REG(codeblock_t *block, int base_reg, int idx_reg, int src_reg) +void +host_x86_ADD32_REG_IMM(codeblock_t *block, int dst_reg, uint32_t imm_data) { + if (is_imm8(imm_data)) { codegen_alloc_bytes(block, 3); - codegen_addbyte3(block, 0x89, 0x04 | (src_reg << 3), base_reg | (idx_reg << 3)); /*MOV L[base_reg + idx_reg], src_reg*/ + codegen_addbyte3(block, 0x83, 0xc0 | RM_OP_ADD | dst_reg, imm_data & 0xff); /*ADD dst_reg, imm_data*/ + } else if (dst_reg == REG_EAX) { + codegen_alloc_bytes(block, 5); + codegen_addbyte(block, 0x05); /*ADD EAX, imm_data*/ + codegen_addlong(block, imm_data); + } else { + codegen_alloc_bytes(block, 6); + codegen_addbyte2(block, 0x81, 0xc0 | RM_OP_ADD | dst_reg); /*ADD dst_reg, imm_data*/ + codegen_addlong(block, imm_data); + } } -void host_x86_MOV8_REG_ABS(codeblock_t *block, int dst_reg, void *p) +void +host_x86_ADD8_REG_REG(codeblock_t *block, int dst_reg, int src_reg) { - int offset = (uintptr_t)p - (((uintptr_t)&cpu_state) + 128); - - if (offset >= -128 && offset < 127) - { - codegen_alloc_bytes(block, 3); - codegen_addbyte3(block, 0x8a, 0x45 | (dst_reg << 3), offset); /*MOV offset[EBP], src_reg*/ - } - else - { - codegen_alloc_bytes(block, 6); - codegen_addbyte(block, 0x8a); /*MOV [p], src_reg*/ - codegen_addbyte(block, 0x05 | (dst_reg << 3)); - codegen_addlong(block, (uint32_t)p); - } + codegen_alloc_bytes(block, 2); + codegen_addbyte2(block, 0x00, 0xc0 | dst_reg | (src_reg << 3)); /*ADD dst_reg, src_reg*/ } -void host_x86_MOV16_REG_ABS(codeblock_t *block, int dst_reg, void *p) +void +host_x86_ADD16_REG_REG(codeblock_t *block, int dst_reg, int src_reg) { - int offset = (uintptr_t)p - (((uintptr_t)&cpu_state) + 128); - - if (offset >= -128 && offset < 127) - { - codegen_alloc_bytes(block, 4); - codegen_addbyte4(block, 0x66, 0x8b, 0x45 | (dst_reg << 3), offset); /*MOV offset[EBP], src_reg*/ - } - else - { - codegen_alloc_bytes(block, 7); - codegen_addbyte3(block, 0x66, 0x8b, 0x05 | (dst_reg << 3)); /*MOV [p], src_reg*/ - codegen_addlong(block, (uint32_t)p); - } + codegen_alloc_bytes(block, 3); + codegen_addbyte3(block, 0x66, 0x01, 0xc0 | dst_reg | (src_reg << 3)); /*ADD dst_reg, src_reg*/ } -void host_x86_MOV32_REG_ABS(codeblock_t *block, int dst_reg, void *p) +void +host_x86_ADD32_REG_REG(codeblock_t *block, int dst_reg, int src_reg) { - int offset = (uintptr_t)p - (((uintptr_t)&cpu_state) + 128); - - if (offset >= -128 && offset < 127) - { - codegen_alloc_bytes(block, 3); - codegen_addbyte3(block, 0x8b, 0x45 | (dst_reg << 3), offset); /*MOV offset[EBP], src_reg*/ - } - else - { - codegen_alloc_bytes(block, 6); - codegen_addbyte(block, 0x8b); /*MOV [p], src_reg*/ - codegen_addbyte(block, 0x05 | (dst_reg << 3)); - codegen_addlong(block, (uint32_t)p); - } + codegen_alloc_bytes(block, 3); + codegen_addbyte2(block, 0x01, 0xc0 | dst_reg | (src_reg << 3)); /*ADD dst_reg, src_reg*/ } -void host_x86_MOV32_REG_ABS_INDEX_SHIFT(codeblock_t *block, int dst_reg, void *p, int idx_reg, int shift) +void +host_x86_AND8_REG_IMM(codeblock_t *block, int dst_reg, uint8_t imm_data) { + if (dst_reg == REG_EAX) { + codegen_alloc_bytes(block, 2); + codegen_addbyte2(block, 0x24, imm_data); /*AND AL, imm_data*/ + } else { + codegen_alloc_bytes(block, 3); + codegen_addbyte3(block, 0x80, 0xc0 | RM_OP_AND | dst_reg, imm_data); /*AND dst_reg, imm_data*/ + } +} +void +host_x86_AND16_REG_IMM(codeblock_t *block, int dst_reg, uint16_t imm_data) +{ + if (is_imm8(imm_data)) { + codegen_alloc_bytes(block, 4); + codegen_addbyte4(block, 0x66, 0x83, 0xc0 | RM_OP_AND | dst_reg, imm_data & 0xff); /*AND dst_reg, imm_data*/ + } else if (dst_reg == REG_EAX) { + codegen_alloc_bytes(block, 6); + codegen_addbyte2(block, 0x66, 0x25); /*AND AX, imm_data*/ + codegen_addword(block, imm_data); + } else { + codegen_alloc_bytes(block, 5); + codegen_addbyte3(block, 0x66, 0x81, 0xc0 | RM_OP_AND | dst_reg); /*AND dst_reg, imm_data*/ + codegen_addword(block, imm_data); + } +} +void +host_x86_AND32_REG_IMM(codeblock_t *block, int dst_reg, uint32_t imm_data) +{ + if (is_imm8(imm_data)) { + codegen_alloc_bytes(block, 3); + codegen_addbyte3(block, 0x83, 0xc0 | RM_OP_AND | dst_reg, imm_data & 0xff); /*AND dst_reg, imm_data*/ + } else if (dst_reg == REG_EAX) { + codegen_alloc_bytes(block, 5); + codegen_addbyte(block, 0x25); /*AND EAX, imm_data*/ + codegen_addlong(block, imm_data); + } else { + codegen_alloc_bytes(block, 6); + codegen_addbyte2(block, 0x81, 0xc0 | RM_OP_AND | dst_reg); /*AND dst_reg, imm_data*/ + codegen_addlong(block, imm_data); + } +} + +void +host_x86_AND8_REG_REG(codeblock_t *block, int dst_reg, int src_reg) +{ + codegen_alloc_bytes(block, 2); + codegen_addbyte2(block, 0x20, 0xc0 | dst_reg | (src_reg << 3)); /*AND dst_reg, src_reg_b*/ +} +void +host_x86_AND16_REG_REG(codeblock_t *block, int dst_reg, int src_reg) +{ + codegen_alloc_bytes(block, 3); + codegen_addbyte3(block, 0x66, 0x21, 0xc0 | dst_reg | (src_reg << 3)); /*AND dst_reg, src_reg_b*/ +} +void +host_x86_AND32_REG_REG(codeblock_t *block, int dst_reg, int src_reg) +{ + codegen_alloc_bytes(block, 2); + codegen_addbyte2(block, 0x21, 0xc0 | dst_reg | (src_reg << 3)); /*AND dst_reg, src_reg_b*/ +} + +void +host_x86_CALL(codeblock_t *block, void *p) +{ + codegen_alloc_bytes(block, 5); + codegen_addbyte(block, 0xe8); /*CALL*/ + codegen_addlong(block, (uintptr_t) p - (uintptr_t) &block_write_data[block_pos + 4]); +} + +void +host_x86_CMP16_REG_IMM(codeblock_t *block, int dst_reg, uint16_t imm_data) +{ + if (is_imm8(imm_data)) { + codegen_alloc_bytes(block, 4); + codegen_addbyte4(block, 0x66, 0x83, 0xc0 | RM_OP_CMP | dst_reg, imm_data & 0xff); /*CMP dst_reg, imm_data*/ + } else if (dst_reg == REG_EAX) { + codegen_alloc_bytes(block, 4); + codegen_addbyte2(block, 0x66, 0x3d); /*CMP AX, imm_data*/ + codegen_addword(block, imm_data); + } else { + codegen_alloc_bytes(block, 5); + codegen_addbyte3(block, 0x66, 0x81, 0xc0 | RM_OP_CMP | dst_reg); /*CMP dst_reg, imm_data*/ + codegen_addword(block, imm_data); + } +} +void +host_x86_CMP32_REG_IMM(codeblock_t *block, int dst_reg, uint32_t imm_data) +{ + if (is_imm8(imm_data)) { + codegen_alloc_bytes(block, 3); + codegen_addbyte3(block, 0x83, 0xc0 | RM_OP_CMP | dst_reg, imm_data & 0xff); /*CMP dst_reg, imm_data*/ + } else if (dst_reg == REG_EAX) { + codegen_alloc_bytes(block, 5); + codegen_addbyte(block, 0x3d); /*CMP EAX, imm_data*/ + codegen_addlong(block, imm_data); + } else { + codegen_alloc_bytes(block, 6); + codegen_addbyte2(block, 0x81, 0xc0 | RM_OP_CMP | dst_reg); /*CMP dst_reg, imm_data*/ + codegen_addlong(block, imm_data); + } +} + +void +host_x86_CMP8_REG_REG(codeblock_t *block, int src_reg_a, int src_reg_b) +{ + codegen_alloc_bytes(block, 2); + codegen_addbyte2(block, 0x38, 0xc0 | src_reg_a | (src_reg_b << 3)); /*CMP src_reg_a, src_reg_b*/ +} +void +host_x86_CMP16_REG_REG(codeblock_t *block, int src_reg_a, int src_reg_b) +{ + codegen_alloc_bytes(block, 3); + codegen_addbyte3(block, 0x66, 0x39, 0xc0 | src_reg_a | (src_reg_b << 3)); /*CMP src_reg_a, src_reg_b*/ +} +void +host_x86_CMP32_REG_REG(codeblock_t *block, int src_reg_a, int src_reg_b) +{ + codegen_alloc_bytes(block, 2); + codegen_addbyte2(block, 0x39, 0xc0 | src_reg_a | (src_reg_b << 3)); /*CMP src_reg_a, src_reg_b*/ +} + +void +host_x86_INC32_ABS(codeblock_t *block, void *p) +{ + codegen_alloc_bytes(block, 6); + codegen_addbyte2(block, 0xff, 0x05); /*INC p*/ + codegen_addlong(block, (uint32_t) p); +} + +void +host_x86_JMP(codeblock_t *block, void *p) +{ + codegen_alloc_bytes(block, 5); + codegen_addbyte(block, 0xe9); /*JMP*/ + codegen_addlong(block, (uintptr_t) p - (uintptr_t) &block_write_data[block_pos + 4]); +} +uint32_t * +host_x86_JMP_long(codeblock_t *block) +{ + codegen_alloc_bytes(block, 5); + codegen_addbyte(block, 0xe9); /*JMP*/ + codegen_addlong(block, 0); + return (uint32_t *) &block_write_data[block_pos - 4]; +} + +void +host_x86_JNZ(codeblock_t *block, void *p) +{ + codegen_alloc_bytes(block, 6); + codegen_addbyte2(block, 0x0f, 0x85); /*JNZ*/ + codegen_addlong(block, (uintptr_t) p - (uintptr_t) &block_write_data[block_pos + 4]); +} +void +host_x86_JZ(codeblock_t *block, void *p) +{ + codegen_alloc_bytes(block, 6); + codegen_addbyte2(block, 0x0f, 0x84); /*JZ*/ + codegen_addlong(block, (uintptr_t) p - (uintptr_t) &block_write_data[block_pos + 4]); +} + +uint8_t * +host_x86_JNZ_short(codeblock_t *block) +{ + codegen_alloc_bytes(block, 2); + codegen_addbyte2(block, 0x75, 0); /*JNZ*/ + return &block_write_data[block_pos - 1]; +} +uint8_t * +host_x86_JS_short(codeblock_t *block) +{ + codegen_alloc_bytes(block, 2); + codegen_addbyte2(block, 0x78, 0); /*JS*/ + return &block_write_data[block_pos - 1]; +} +uint8_t * +host_x86_JZ_short(codeblock_t *block) +{ + codegen_alloc_bytes(block, 2); + codegen_addbyte2(block, 0x74, 0); /*JZ*/ + return &block_write_data[block_pos - 1]; +} + +uint32_t * +host_x86_JNB_long(codeblock_t *block) +{ + codegen_alloc_bytes(block, 6); + codegen_addbyte2(block, 0x0f, 0x83); /*JNB*/ + codegen_addlong(block, 0); + return (uint32_t *) &block_write_data[block_pos - 4]; +} +uint32_t * +host_x86_JNBE_long(codeblock_t *block) +{ + codegen_alloc_bytes(block, 6); + codegen_addbyte2(block, 0x0f, 0x87); /*JNBE*/ + codegen_addlong(block, 0); + return (uint32_t *) &block_write_data[block_pos - 4]; +} +uint32_t * +host_x86_JNL_long(codeblock_t *block) +{ + codegen_alloc_bytes(block, 6); + codegen_addbyte2(block, 0x0f, 0x8d); /*JNL*/ + codegen_addlong(block, 0); + return (uint32_t *) &block_write_data[block_pos - 4]; +} +uint32_t * +host_x86_JNLE_long(codeblock_t *block) +{ + codegen_alloc_bytes(block, 6); + codegen_addbyte2(block, 0x0f, 0x8f); /*JNLE*/ + codegen_addlong(block, 0); + return (uint32_t *) &block_write_data[block_pos - 4]; +} +uint32_t * +host_x86_JNO_long(codeblock_t *block) +{ + codegen_alloc_bytes(block, 6); + codegen_addbyte2(block, 0x0f, 0x81); /*JNO*/ + codegen_addlong(block, 0); + return (uint32_t *) &block_write_data[block_pos - 4]; +} +uint32_t * +host_x86_JNS_long(codeblock_t *block) +{ + codegen_alloc_bytes(block, 6); + codegen_addbyte2(block, 0x0f, 0x89); /*JNS*/ + codegen_addlong(block, 0); + return (uint32_t *) &block_write_data[block_pos - 4]; +} +uint32_t * +host_x86_JNZ_long(codeblock_t *block) +{ + codegen_alloc_bytes(block, 6); + codegen_addbyte2(block, 0x0f, 0x85); /*JNZ*/ + codegen_addlong(block, 0); + return (uint32_t *) &block_write_data[block_pos - 4]; +} +uint32_t * +host_x86_JB_long(codeblock_t *block) +{ + codegen_alloc_bytes(block, 6); + codegen_addbyte2(block, 0x0f, 0x82); /*JB*/ + codegen_addlong(block, 0); + return (uint32_t *) &block_write_data[block_pos - 4]; +} +uint32_t * +host_x86_JBE_long(codeblock_t *block) +{ + codegen_alloc_bytes(block, 6); + codegen_addbyte2(block, 0x0f, 0x86); /*JBE*/ + codegen_addlong(block, 0); + return (uint32_t *) &block_write_data[block_pos - 4]; +} +uint32_t * +host_x86_JL_long(codeblock_t *block) +{ + codegen_alloc_bytes(block, 6); + codegen_addbyte2(block, 0x0f, 0x8c); /*JL*/ + codegen_addlong(block, 0); + return (uint32_t *) &block_write_data[block_pos - 4]; +} +uint32_t * +host_x86_JLE_long(codeblock_t *block) +{ + codegen_alloc_bytes(block, 6); + codegen_addbyte2(block, 0x0f, 0x8e); /*JLE*/ + codegen_addlong(block, 0); + return (uint32_t *) &block_write_data[block_pos - 4]; +} +uint32_t * +host_x86_JO_long(codeblock_t *block) +{ + codegen_alloc_bytes(block, 6); + codegen_addbyte2(block, 0x0f, 0x80); /*JO*/ + codegen_addlong(block, 0); + return (uint32_t *) &block_write_data[block_pos - 4]; +} +uint32_t * +host_x86_JS_long(codeblock_t *block) +{ + codegen_alloc_bytes(block, 6); + codegen_addbyte2(block, 0x0f, 0x88); /*JS*/ + codegen_addlong(block, 0); + return (uint32_t *) &block_write_data[block_pos - 4]; +} +uint32_t * +host_x86_JZ_long(codeblock_t *block) +{ + codegen_alloc_bytes(block, 6); + codegen_addbyte2(block, 0x0f, 0x84); /*JZ*/ + codegen_addlong(block, 0); + return (uint32_t *) &block_write_data[block_pos - 4]; +} + +void +host_x86_LAHF(codeblock_t *block) +{ + codegen_alloc_bytes(block, 1); + codegen_addbyte(block, 0x9f); /*LAHF*/ +} + +void +host_x86_LEA_REG_IMM(codeblock_t *block, int dst_reg, int src_reg, uint32_t offset) +{ + if (offset) { + codegen_alloc_bytes(block, 6); + codegen_addbyte2(block, 0x8d, 0x80 | (dst_reg << 3) | src_reg); /*LEA dst_reg, [offset+src_reg]*/ + codegen_addlong(block, offset); + } else { + codegen_alloc_bytes(block, 2); + codegen_addbyte2(block, 0x8d, 0x00 | (dst_reg << 3) | src_reg); /*LEA dst_reg, [src_reg]*/ + } +} + +void +host_x86_LEA_REG_REG(codeblock_t *block, int dst_reg, int src_reg_a, int src_reg_b) +{ + codegen_alloc_bytes(block, 3); + codegen_addbyte3(block, 0x8d, 0x04 | (dst_reg << 3), (src_reg_b << 3) | src_reg_a); /*LEA dst_reg, [src_reg_a + src_reg_b]*/ +} +void +host_x86_LEA_REG_REG_SHIFT(codeblock_t *block, int dst_reg, int src_reg_a, int src_reg_b, int shift) +{ + codegen_alloc_bytes(block, 3); + codegen_addbyte3(block, 0x8d, 0x04 | (dst_reg << 3), (shift << 6) | (src_reg_b << 3) | src_reg_a); /*LEA dst_reg, [src_reg_a + src_reg_b * (1 << shift)]*/ +} + +void +host_x86_MOV8_ABS_IMM(codeblock_t *block, void *p, uint32_t imm_data) +{ + int offset = (uintptr_t) p - (((uintptr_t) &cpu_state) + 128); + + if (offset >= -128 && offset < 127) { + codegen_alloc_bytes(block, 4); + codegen_addbyte3(block, 0xc6, 0x45, offset); /*MOVB offset[EBP], imm_data*/ + codegen_addbyte(block, imm_data); + } else { codegen_alloc_bytes(block, 7); - codegen_addbyte3(block, 0x8b, 0x04 | (dst_reg << 3), (shift << 6) | (idx_reg << 3) | 0x05); /*MOV dst_reg, [p + idx_reg << shift]*/ - codegen_addlong(block, (uint32_t)p); + codegen_addbyte2(block, 0xc6, 0x05); /*MOVB p, imm_data*/ + codegen_addlong(block, (uint32_t) p); + codegen_addbyte(block, imm_data); + } +} +void +host_x86_MOV16_ABS_IMM(codeblock_t *block, void *p, uint16_t imm_data) +{ + int offset = (uintptr_t) p - (((uintptr_t) &cpu_state) + 128); + + if (offset >= -128 && offset < 127) { + codegen_alloc_bytes(block, 6); + codegen_addbyte4(block, 0x66, 0xc7, 0x45, offset); /*MOV offset[EBP], imm_data*/ + codegen_addword(block, imm_data); + } else { + codegen_alloc_bytes(block, 9); + codegen_addbyte3(block, 0x66, 0xc7, 0x05); /*MOV p, imm_data*/ + codegen_addlong(block, (uint32_t) p); + codegen_addword(block, imm_data); + } +} +void +host_x86_MOV32_ABS_IMM(codeblock_t *block, void *p, uint32_t imm_data) +{ + int offset = (uintptr_t) p - (((uintptr_t) &cpu_state) + 128); + + if (offset >= -128 && offset < 127) { + codegen_alloc_bytes(block, 7); + codegen_addbyte3(block, 0xc7, 0x45, offset); /*MOV offset[EBP], imm_data*/ + codegen_addlong(block, imm_data); + } else { + codegen_alloc_bytes(block, 10); + codegen_addbyte2(block, 0xc7, 0x05); /*MOV p, imm_data*/ + codegen_addlong(block, (uint32_t) p); + codegen_addlong(block, imm_data); + } } -void host_x86_MOV8_REG_ABS_REG_REG_SHIFT(codeblock_t *block, int dst_reg, uint32_t addr, int base_reg, int idx_reg, int shift) +void +host_x86_MOV8_ABS_REG(codeblock_t *block, void *p, int src_reg) { - if (addr < 0x80 || addr >= 0xffffff80) - { - codegen_alloc_bytes(block, 4); - codegen_addbyte4(block, 0x8a, 0x44 | (dst_reg << 3), base_reg | (idx_reg << 3) | (shift << 6), addr & 0xff); /*MOV addr[base_reg + idx_reg << shift], src_reg*/ - } - else - { - codegen_alloc_bytes(block, 7); - codegen_addbyte3(block, 0x8a, 0x84 | (dst_reg << 3), base_reg | (idx_reg << 3) | (shift << 6)); /*MOV addr[base_reg + idx_reg << shift], src_reg*/ - codegen_addlong(block, addr); - } -} + int offset = (uintptr_t) p - (((uintptr_t) &cpu_state) + 128); -void host_x86_MOV32_REG_BASE_INDEX(codeblock_t *block, int dst_reg, int base_reg, int idx_reg) -{ + if (offset >= -128 && offset < 127) { codegen_alloc_bytes(block, 3); - codegen_addbyte3(block, 0x8b, 0x04 | (dst_reg << 3), base_reg | (idx_reg << 3)); /*MOV dst_reg, L[base_reg + idx_reg]*/ + codegen_addbyte3(block, 0x88, 0x45 | (src_reg << 3), offset); /*MOVB offset[EBP], src_reg*/ + } else { + codegen_alloc_bytes(block, 6); + codegen_addbyte(block, 0x88); /*MOVB [p], src_reg*/ + codegen_addbyte(block, 0x05 | (src_reg << 3)); + codegen_addlong(block, (uint32_t) p); + } } +void +host_x86_MOV16_ABS_REG(codeblock_t *block, void *p, int src_reg) +{ + int offset = (uintptr_t) p - (((uintptr_t) &cpu_state) + 128); -void host_x86_MOV16_REG_BASE_OFFSET(codeblock_t *block, int dst_reg, int base_reg, int offset) -{ - if (offset >= -128 && offset < 127) - { - if (base_reg == REG_ESP) - { - codegen_alloc_bytes(block, 5); - codegen_addbyte(block, 0x66); - codegen_addbyte4(block, 0x8b, 0x40 | base_reg | (dst_reg << 3), 0x24, offset); - } - else - { - codegen_alloc_bytes(block, 4); - codegen_addbyte4(block, 0x66, 0x8b, 0x40 | base_reg | (dst_reg << 3), offset); - } - } - else - fatal("MOV16_REG_BASE_OFFSET - offset %i\n", offset); -} -void host_x86_MOV32_REG_BASE_OFFSET(codeblock_t *block, int dst_reg, int base_reg, int offset) -{ - if (offset >= -128 && offset < 127) - { - if (base_reg == REG_ESP) - { - codegen_alloc_bytes(block, 4); - codegen_addbyte4(block, 0x8b, 0x40 | base_reg | (dst_reg << 3), 0x24, offset); - } - else - { - codegen_alloc_bytes(block, 3); - codegen_addbyte3(block, 0x8b, 0x40 | base_reg | (dst_reg << 3), offset); - } - } - else - fatal("MOV32_REG_BASE_OFFSET - offset %i\n", offset); -} - -void host_x86_MOV16_BASE_OFFSET_REG(codeblock_t *block, int base_reg, int offset, int src_reg) -{ - if (offset >= -128 && offset < 127) - { - if (base_reg == REG_ESP) - { - codegen_alloc_bytes(block, 5); - codegen_addbyte(block, 0x66); - codegen_addbyte4(block, 0x89, 0x40 | base_reg | (src_reg << 3), 0x24, offset); - } - else - { - codegen_alloc_bytes(block, 4); - codegen_addbyte4(block, 0x66, 0x89, 0x40 | base_reg | (src_reg << 3), offset); - } - } - else - fatal("MOV16_BASE_OFFSET_REG - offset %i\n", offset); -} -void host_x86_MOV32_BASE_OFFSET_REG(codeblock_t *block, int base_reg, int offset, int src_reg) -{ - if (offset >= -128 && offset < 127) - { - if (base_reg == REG_ESP) - { - codegen_alloc_bytes(block, 4); - codegen_addbyte4(block, 0x89, 0x40 | base_reg | (src_reg << 3), 0x24, offset); - } - else - { - codegen_alloc_bytes(block, 3); - codegen_addbyte3(block, 0x89, 0x40 | base_reg | (src_reg << 3), offset); - } - } - else - fatal("MOV32_BASE_OFFSET_REG - offset %i\n", offset); -} - -void host_x86_MOV32_BASE_OFFSET_IMM(codeblock_t *block, int base_reg, int offset, uint32_t imm_data) -{ - if (offset >= -128 && offset < 127) - { - if (base_reg == REG_ESP) - { - codegen_alloc_bytes(block, 8); - codegen_addbyte4(block, 0xc7, 0x40 | base_reg, 0x24, offset); - codegen_addlong(block, imm_data); - } - else - { - codegen_alloc_bytes(block, 7); - codegen_addbyte3(block, 0xc7, 0x40 | base_reg, offset); - codegen_addlong(block, imm_data); - } - } - else - fatal("MOV32_BASE_OFFSET_IMM - offset %i\n", offset); -} - -void host_x86_MOV8_REG_IMM(codeblock_t *block, int dst_reg, uint8_t imm_data) -{ - codegen_alloc_bytes(block, 2); - codegen_addbyte2(block, 0xb0 + dst_reg, imm_data); /*MOV reg, imm_data*/ -} -void host_x86_MOV16_REG_IMM(codeblock_t *block, int dst_reg, uint16_t imm_data) -{ - if (!imm_data) - { - codegen_alloc_bytes(block, 3); - codegen_addbyte3(block, 0x66, 0x31, 0xc0 | dst_reg | (dst_reg << 3)); /*XOR dst_reg, dst_reg*/ - } - else - { - codegen_alloc_bytes(block, 6); - codegen_addbyte2(block, 0x66, 0xb8 + dst_reg); /*MOV reg, imm_data*/ - codegen_addword(block, imm_data); - } -} -void host_x86_MOV32_REG_IMM(codeblock_t *block, int dst_reg, uint32_t imm_data) -{ - if (!imm_data) - { - codegen_alloc_bytes(block, 2); - codegen_addbyte2(block, 0x31, 0xc0 | dst_reg | (dst_reg << 3)); /*XOR dst_reg, dst_reg*/ - } - else - { - codegen_alloc_bytes(block, 5); - codegen_addbyte(block, 0xb8 + dst_reg); /*MOV reg, imm_data*/ - codegen_addlong(block, imm_data); - } -} - -void host_x86_MOV8_REG_REG(codeblock_t *block, int dst_reg, int src_reg) -{ - codegen_alloc_bytes(block, 2); - codegen_addbyte2(block, 0x88, 0xc0 | dst_reg | (src_reg << 3)); -} -void host_x86_MOV16_REG_REG(codeblock_t *block, int dst_reg, int src_reg) -{ - codegen_alloc_bytes(block, 3); - codegen_addbyte3(block, 0x66, 0x89, 0xc0 | dst_reg | (src_reg << 3)); -} -void host_x86_MOV32_REG_REG(codeblock_t *block, int dst_reg, int src_reg) -{ - codegen_alloc_bytes(block, 2); - codegen_addbyte2(block, 0x89, 0xc0 | dst_reg | (src_reg << 3)); -} - -void host_x86_MOV32_STACK_IMM(codeblock_t *block, int32_t offset, uint32_t imm_data) -{ - if (!offset) - { - codegen_alloc_bytes(block, 7); - codegen_addbyte3(block, 0xc7, 0x04, 0x24); /*MOV [ESP], imm_data*/ - codegen_addlong(block, imm_data); - } - else if (offset >= -0x80 && offset < 0x80) - { - codegen_alloc_bytes(block, 8); - codegen_addbyte4(block, 0xc7, 0x44, 0x24, offset & 0xff); /*MOV offset[ESP], imm_data*/ - codegen_addlong(block, imm_data); - } - else - { - codegen_alloc_bytes(block, 11); - codegen_addbyte3(block, 0xc7, 0x84, 0x24); /*MOV offset[ESP], imm_data*/ - codegen_addlong(block, offset); - codegen_addlong(block, imm_data); - } -} - -void host_x86_MOVSX_REG_16_8(codeblock_t *block, int dst_reg, int src_reg) -{ + if (offset >= -128 && offset < 127) { codegen_alloc_bytes(block, 4); - codegen_addbyte4(block, 0x66, 0x0f, 0xbe, 0xc0 | (dst_reg << 3) | src_reg); /*MOVSX dst_reg, src_reg*/ + codegen_addbyte4(block, 0x66, 0x89, 0x45 | (src_reg << 3), offset); /*MOV offset[EBP], src_reg*/ + } else { + codegen_alloc_bytes(block, 7); + codegen_addbyte3(block, 0x66, 0x89, 0x05 | (src_reg << 3)); /*MOV [p], src_reg*/ + codegen_addlong(block, (uint32_t) p); + } } -void host_x86_MOVSX_REG_32_8(codeblock_t *block, int dst_reg, int src_reg) +void +host_x86_MOV32_ABS_REG(codeblock_t *block, void *p, int src_reg) { + int offset = (uintptr_t) p - (((uintptr_t) &cpu_state) + 128); + + if (offset >= -128 && offset < 127) { codegen_alloc_bytes(block, 3); - codegen_addbyte3(block, 0x0f, 0xbe, 0xc0 | (dst_reg << 3) | src_reg); /*MOVSX dst_reg, src_reg*/ -} -void host_x86_MOVSX_REG_32_16(codeblock_t *block, int dst_reg, int src_reg) -{ - codegen_alloc_bytes(block, 3); - codegen_addbyte3(block, 0x0f, 0xbf, 0xc0 | (dst_reg << 3) | src_reg); /*MOVSX dst_reg, src_reg*/ + codegen_addbyte3(block, 0x89, 0x45 | (src_reg << 3), offset); /*MOV offset[EBP], src_reg*/ + } else { + codegen_alloc_bytes(block, 6); + codegen_addbyte(block, 0x89); /*MOV [p], src_reg*/ + codegen_addbyte(block, 0x05 | (src_reg << 3)); + codegen_addlong(block, (uint32_t) p); + } } -void host_x86_MOVZX_REG_ABS_16_8(codeblock_t *block, int dst_reg, void *p) -{ - int offset = (uintptr_t)p - (((uintptr_t)&cpu_state) + 128); - - if (offset >= -128 && offset < 127) - { - codegen_alloc_bytes(block, 5); - codegen_addbyte(block, 0x66); - codegen_addbyte4(block, 0x0f, 0xb6, 0x45 | (dst_reg << 3), offset); /*MOV dest_reg, [EBP+offset]*/ - } - else - { - codegen_alloc_bytes(block, 8); - codegen_addbyte4(block, 0x66, 0x0f, 0xb6, 0x05 | (dst_reg << 3)); /*MOVZX dst_reg, [p]*/ - codegen_addlong(block, (uint32_t)p); - } -} -void host_x86_MOVZX_REG_ABS_32_8(codeblock_t *block, int dst_reg, void *p) -{ - int offset = (uintptr_t)p - (((uintptr_t)&cpu_state) + 128); - - if (offset >= -128 && offset < 127) - { - codegen_alloc_bytes(block, 4); - codegen_addbyte4(block, 0x0f, 0xb6, 0x45 | (dst_reg << 3), offset); /*MOV dest_reg, [EBP+offset]*/ - } - else - { - codegen_alloc_bytes(block, 7); - codegen_addbyte3(block, 0x0f, 0xb6, 0x05 | (dst_reg << 3)); /*MOVZX dst_reg, [p]*/ - codegen_addlong(block, (uint32_t)p); - } -} -void host_x86_MOVZX_REG_ABS_32_16(codeblock_t *block, int dst_reg, void *p) -{ - int offset = (uintptr_t)p - (((uintptr_t)&cpu_state) + 128); - - if (offset >= -128 && offset < 127) - { - codegen_alloc_bytes(block, 4); - codegen_addbyte4(block, 0x0f, 0xb7, 0x45 | (dst_reg << 3), offset); /*MOV dest_reg, [EBP+offset]*/ - } - else - { - codegen_alloc_bytes(block, 7); - codegen_addbyte3(block, 0x0f, 0xb7, 0x05 | (dst_reg << 3)); /*MOVZX dst_reg, [p]*/ - codegen_addlong(block, (uint32_t)p); - } -} - -void host_x86_MOVZX_REG_16_8(codeblock_t *block, int dst_reg, int src_reg) +void +host_x86_MOV8_ABS_REG_REG_SHIFT_REG(codeblock_t *block, uint32_t addr, int base_reg, int idx_reg, int shift, int src_reg) { + if (addr < 0x80 || addr >= 0xffffff80) { codegen_alloc_bytes(block, 4); - codegen_addbyte4(block, 0x66, 0x0f, 0xb6, 0xc0 | (dst_reg << 3) | src_reg); /*MOVZX dst_reg, src_reg*/ -} -void host_x86_MOVZX_REG_32_8(codeblock_t *block, int dst_reg, int src_reg) -{ - codegen_alloc_bytes(block, 3); - codegen_addbyte3(block, 0x0f, 0xb6, 0xc0 | (dst_reg << 3) | src_reg); /*MOVZX dst_reg, src_reg*/ -} -void host_x86_MOVZX_REG_32_16(codeblock_t *block, int dst_reg, int src_reg) -{ - codegen_alloc_bytes(block, 3); - codegen_addbyte3(block, 0x0f, 0xb7, 0xc0 | (dst_reg << 3) | src_reg); /*MOVZX dst_reg, src_reg*/ + codegen_addbyte4(block, 0x88, 0x44 | (src_reg << 3), base_reg | (idx_reg << 3) | (shift << 6), addr & 0xff); /*MOV addr[base_reg + idx_reg << shift], src_reg*/ + } else { + codegen_alloc_bytes(block, 7); + codegen_addbyte3(block, 0x88, 0x84 | (src_reg << 3), base_reg | (idx_reg << 3) | (shift << 6)); /*MOV addr[base_reg + idx_reg << shift], src_reg*/ + codegen_addlong(block, addr); + } } -void host_x86_MOVZX_BASE_INDEX_32_8(codeblock_t *block, int dst_reg, int base_reg, int idx_reg) +void +host_x86_MOV8_BASE_INDEX_REG(codeblock_t *block, int base_reg, int idx_reg, int src_reg) { + codegen_alloc_bytes(block, 3); + codegen_addbyte3(block, 0x88, 0x04 | (src_reg << 3), base_reg | (idx_reg << 3)); /*MOV B[base_reg + idx_reg], src_reg*/ +} +void +host_x86_MOV16_BASE_INDEX_REG(codeblock_t *block, int base_reg, int idx_reg, int src_reg) +{ + codegen_alloc_bytes(block, 4); + codegen_addbyte4(block, 0x66, 0x89, 0x04 | (src_reg << 3), base_reg | (idx_reg << 3)); /*MOV W[base_reg + idx_reg], src_reg*/ +} +void +host_x86_MOV32_BASE_INDEX_REG(codeblock_t *block, int base_reg, int idx_reg, int src_reg) +{ + codegen_alloc_bytes(block, 3); + codegen_addbyte3(block, 0x89, 0x04 | (src_reg << 3), base_reg | (idx_reg << 3)); /*MOV L[base_reg + idx_reg], src_reg*/ +} + +void +host_x86_MOV8_REG_ABS(codeblock_t *block, int dst_reg, void *p) +{ + int offset = (uintptr_t) p - (((uintptr_t) &cpu_state) + 128); + + if (offset >= -128 && offset < 127) { + codegen_alloc_bytes(block, 3); + codegen_addbyte3(block, 0x8a, 0x45 | (dst_reg << 3), offset); /*MOV offset[EBP], src_reg*/ + } else { + codegen_alloc_bytes(block, 6); + codegen_addbyte(block, 0x8a); /*MOV [p], src_reg*/ + codegen_addbyte(block, 0x05 | (dst_reg << 3)); + codegen_addlong(block, (uint32_t) p); + } +} +void +host_x86_MOV16_REG_ABS(codeblock_t *block, int dst_reg, void *p) +{ + int offset = (uintptr_t) p - (((uintptr_t) &cpu_state) + 128); + + if (offset >= -128 && offset < 127) { codegen_alloc_bytes(block, 4); - codegen_addbyte4(block, 0x0f, 0xb6, 0x04 | (dst_reg << 3), base_reg | (idx_reg << 3)); /*MOVZX dst_reg, B[base_reg + idx_reg]*/ + codegen_addbyte4(block, 0x66, 0x8b, 0x45 | (dst_reg << 3), offset); /*MOV offset[EBP], src_reg*/ + } else { + codegen_alloc_bytes(block, 7); + codegen_addbyte3(block, 0x66, 0x8b, 0x05 | (dst_reg << 3)); /*MOV [p], src_reg*/ + codegen_addlong(block, (uint32_t) p); + } } -void host_x86_MOVZX_BASE_INDEX_32_16(codeblock_t *block, int dst_reg, int base_reg, int idx_reg) +void +host_x86_MOV32_REG_ABS(codeblock_t *block, int dst_reg, void *p) { + int offset = (uintptr_t) p - (((uintptr_t) &cpu_state) + 128); + + if (offset >= -128 && offset < 127) { + codegen_alloc_bytes(block, 3); + codegen_addbyte3(block, 0x8b, 0x45 | (dst_reg << 3), offset); /*MOV offset[EBP], src_reg*/ + } else { + codegen_alloc_bytes(block, 6); + codegen_addbyte(block, 0x8b); /*MOV [p], src_reg*/ + codegen_addbyte(block, 0x05 | (dst_reg << 3)); + codegen_addlong(block, (uint32_t) p); + } +} + +void +host_x86_MOV32_REG_ABS_INDEX_SHIFT(codeblock_t *block, int dst_reg, void *p, int idx_reg, int shift) +{ + codegen_alloc_bytes(block, 7); + codegen_addbyte3(block, 0x8b, 0x04 | (dst_reg << 3), (shift << 6) | (idx_reg << 3) | 0x05); /*MOV dst_reg, [p + idx_reg << shift]*/ + codegen_addlong(block, (uint32_t) p); +} + +void +host_x86_MOV8_REG_ABS_REG_REG_SHIFT(codeblock_t *block, int dst_reg, uint32_t addr, int base_reg, int idx_reg, int shift) +{ + if (addr < 0x80 || addr >= 0xffffff80) { codegen_alloc_bytes(block, 4); - codegen_addbyte4(block, 0x0f, 0xb7, 0x04 | (dst_reg << 3), base_reg | (idx_reg << 3)); /*MOVZX dst_reg, W[base_reg + idx_reg]*/ + codegen_addbyte4(block, 0x8a, 0x44 | (dst_reg << 3), base_reg | (idx_reg << 3) | (shift << 6), addr & 0xff); /*MOV addr[base_reg + idx_reg << shift], src_reg*/ + } else { + codegen_alloc_bytes(block, 7); + codegen_addbyte3(block, 0x8a, 0x84 | (dst_reg << 3), base_reg | (idx_reg << 3) | (shift << 6)); /*MOV addr[base_reg + idx_reg << shift], src_reg*/ + codegen_addlong(block, addr); + } } -void host_x86_OR8_REG_REG(codeblock_t *block, int dst_reg, int src_reg) +void +host_x86_MOV32_REG_BASE_INDEX(codeblock_t *block, int dst_reg, int base_reg, int idx_reg) { - codegen_alloc_bytes(block, 2); - codegen_addbyte2(block, 0x08, 0xc0 | dst_reg | (src_reg << 3)); /*OR dst_reg, src_reg_b*/ + codegen_alloc_bytes(block, 3); + codegen_addbyte3(block, 0x8b, 0x04 | (dst_reg << 3), base_reg | (idx_reg << 3)); /*MOV dst_reg, L[base_reg + idx_reg]*/ } -void host_x86_OR16_REG_REG(codeblock_t *block, int dst_reg, int src_reg) + +void +host_x86_MOV16_REG_BASE_OFFSET(codeblock_t *block, int dst_reg, int base_reg, int offset) { + if (offset >= -128 && offset < 127) { + if (base_reg == REG_ESP) { + codegen_alloc_bytes(block, 5); + codegen_addbyte(block, 0x66); + codegen_addbyte4(block, 0x8b, 0x40 | base_reg | (dst_reg << 3), 0x24, offset); + } else { + codegen_alloc_bytes(block, 4); + codegen_addbyte4(block, 0x66, 0x8b, 0x40 | base_reg | (dst_reg << 3), offset); + } + } else + fatal("MOV16_REG_BASE_OFFSET - offset %i\n", offset); +} +void +host_x86_MOV32_REG_BASE_OFFSET(codeblock_t *block, int dst_reg, int base_reg, int offset) +{ + if (offset >= -128 && offset < 127) { + if (base_reg == REG_ESP) { + codegen_alloc_bytes(block, 4); + codegen_addbyte4(block, 0x8b, 0x40 | base_reg | (dst_reg << 3), 0x24, offset); + } else { + codegen_alloc_bytes(block, 3); + codegen_addbyte3(block, 0x8b, 0x40 | base_reg | (dst_reg << 3), offset); + } + } else + fatal("MOV32_REG_BASE_OFFSET - offset %i\n", offset); +} + +void +host_x86_MOV16_BASE_OFFSET_REG(codeblock_t *block, int base_reg, int offset, int src_reg) +{ + if (offset >= -128 && offset < 127) { + if (base_reg == REG_ESP) { + codegen_alloc_bytes(block, 5); + codegen_addbyte(block, 0x66); + codegen_addbyte4(block, 0x89, 0x40 | base_reg | (src_reg << 3), 0x24, offset); + } else { + codegen_alloc_bytes(block, 4); + codegen_addbyte4(block, 0x66, 0x89, 0x40 | base_reg | (src_reg << 3), offset); + } + } else + fatal("MOV16_BASE_OFFSET_REG - offset %i\n", offset); +} +void +host_x86_MOV32_BASE_OFFSET_REG(codeblock_t *block, int base_reg, int offset, int src_reg) +{ + if (offset >= -128 && offset < 127) { + if (base_reg == REG_ESP) { + codegen_alloc_bytes(block, 4); + codegen_addbyte4(block, 0x89, 0x40 | base_reg | (src_reg << 3), 0x24, offset); + } else { + codegen_alloc_bytes(block, 3); + codegen_addbyte3(block, 0x89, 0x40 | base_reg | (src_reg << 3), offset); + } + } else + fatal("MOV32_BASE_OFFSET_REG - offset %i\n", offset); +} + +void +host_x86_MOV32_BASE_OFFSET_IMM(codeblock_t *block, int base_reg, int offset, uint32_t imm_data) +{ + if (offset >= -128 && offset < 127) { + if (base_reg == REG_ESP) { + codegen_alloc_bytes(block, 8); + codegen_addbyte4(block, 0xc7, 0x40 | base_reg, 0x24, offset); + codegen_addlong(block, imm_data); + } else { + codegen_alloc_bytes(block, 7); + codegen_addbyte3(block, 0xc7, 0x40 | base_reg, offset); + codegen_addlong(block, imm_data); + } + } else + fatal("MOV32_BASE_OFFSET_IMM - offset %i\n", offset); +} + +void +host_x86_MOV8_REG_IMM(codeblock_t *block, int dst_reg, uint8_t imm_data) +{ + codegen_alloc_bytes(block, 2); + codegen_addbyte2(block, 0xb0 + dst_reg, imm_data); /*MOV reg, imm_data*/ +} +void +host_x86_MOV16_REG_IMM(codeblock_t *block, int dst_reg, uint16_t imm_data) +{ + if (!imm_data) { codegen_alloc_bytes(block, 3); - codegen_addbyte3(block, 0x66, 0x09, 0xc0 | dst_reg | (src_reg << 3)); /*OR dst_reg, src_reg_b*/ + codegen_addbyte3(block, 0x66, 0x31, 0xc0 | dst_reg | (dst_reg << 3)); /*XOR dst_reg, dst_reg*/ + } else { + codegen_alloc_bytes(block, 6); + codegen_addbyte2(block, 0x66, 0xb8 + dst_reg); /*MOV reg, imm_data*/ + codegen_addword(block, imm_data); + } } -void host_x86_OR32_REG_REG(codeblock_t *block, int dst_reg, int src_reg) +void +host_x86_MOV32_REG_IMM(codeblock_t *block, int dst_reg, uint32_t imm_data) { + if (!imm_data) { codegen_alloc_bytes(block, 2); - codegen_addbyte2(block, 0x09, 0xc0 | dst_reg | (src_reg << 3)); /*OR dst_reg, src_reg_b*/ + codegen_addbyte2(block, 0x31, 0xc0 | dst_reg | (dst_reg << 3)); /*XOR dst_reg, dst_reg*/ + } else { + codegen_alloc_bytes(block, 5); + codegen_addbyte(block, 0xb8 + dst_reg); /*MOV reg, imm_data*/ + codegen_addlong(block, imm_data); + } } -void host_x86_OR8_REG_IMM(codeblock_t *block, int dst_reg, uint8_t imm_data) +void +host_x86_MOV8_REG_REG(codeblock_t *block, int dst_reg, int src_reg) { - if (dst_reg == REG_EAX) - { - codegen_alloc_bytes(block, 2); - codegen_addbyte2(block, 0x0c, imm_data); /*OR AL, imm_data*/ - } - else - { - codegen_alloc_bytes(block, 3); - codegen_addbyte3(block, 0x80, 0xc0 | RM_OP_OR | dst_reg, imm_data); /*OR dst_reg, imm_data*/ - } + codegen_alloc_bytes(block, 2); + codegen_addbyte2(block, 0x88, 0xc0 | dst_reg | (src_reg << 3)); } -void host_x86_OR16_REG_IMM(codeblock_t *block, int dst_reg, uint16_t imm_data) +void +host_x86_MOV16_REG_REG(codeblock_t *block, int dst_reg, int src_reg) { - if (is_imm8(imm_data)) - { - codegen_alloc_bytes(block, 4); - codegen_addbyte4(block, 0x66, 0x83, 0xc0 | RM_OP_OR | dst_reg, imm_data & 0xff); /*OR dst_reg, imm_data*/ - } - else if (dst_reg == REG_EAX) - { - codegen_alloc_bytes(block, 6); - codegen_addbyte2(block, 0x66, 0x0d); /*OR AX, imm_data*/ - codegen_addword(block, imm_data); - } - else - { - codegen_alloc_bytes(block, 7); - codegen_addbyte3(block, 0x66, 0x81, 0xc0 | RM_OP_OR | dst_reg); /*OR dst_reg, imm_data*/ - codegen_addword(block, imm_data); - } + codegen_alloc_bytes(block, 3); + codegen_addbyte3(block, 0x66, 0x89, 0xc0 | dst_reg | (src_reg << 3)); } -void host_x86_OR32_REG_IMM(codeblock_t *block, int dst_reg, uint32_t imm_data) +void +host_x86_MOV32_REG_REG(codeblock_t *block, int dst_reg, int src_reg) { - if (is_imm8(imm_data)) - { - codegen_alloc_bytes(block, 3); - codegen_addbyte3(block, 0x83, 0xc0 | RM_OP_OR | dst_reg, imm_data & 0xff); /*OR dst_reg, imm_data*/ - } - else if (dst_reg == REG_EAX) - { - codegen_alloc_bytes(block, 5); - codegen_addbyte(block, 0x0d); /*OR EAX, imm_data*/ - codegen_addlong(block, imm_data); - } - else - { - codegen_alloc_bytes(block, 6); - codegen_addbyte2(block, 0x81, 0xc0 | RM_OP_OR | dst_reg); /*OR dst_reg, imm_data*/ - codegen_addlong(block, imm_data); - } + codegen_alloc_bytes(block, 2); + codegen_addbyte2(block, 0x89, 0xc0 | dst_reg | (src_reg << 3)); } -void host_x86_POP(codeblock_t *block, int src_reg) +void +host_x86_MOV32_STACK_IMM(codeblock_t *block, int32_t offset, uint32_t imm_data) { - codegen_alloc_bytes(block, 1); - codegen_addbyte(block, 0x58 | src_reg); /*POP reg*/ + if (!offset) { + codegen_alloc_bytes(block, 7); + codegen_addbyte3(block, 0xc7, 0x04, 0x24); /*MOV [ESP], imm_data*/ + codegen_addlong(block, imm_data); + } else if (offset >= -0x80 && offset < 0x80) { + codegen_alloc_bytes(block, 8); + codegen_addbyte4(block, 0xc7, 0x44, 0x24, offset & 0xff); /*MOV offset[ESP], imm_data*/ + codegen_addlong(block, imm_data); + } else { + codegen_alloc_bytes(block, 11); + codegen_addbyte3(block, 0xc7, 0x84, 0x24); /*MOV offset[ESP], imm_data*/ + codegen_addlong(block, offset); + codegen_addlong(block, imm_data); + } } -void host_x86_PUSH(codeblock_t *block, int src_reg) +void +host_x86_MOVSX_REG_16_8(codeblock_t *block, int dst_reg, int src_reg) { - codegen_alloc_bytes(block, 1); - codegen_addbyte(block, 0x50 | src_reg); /*PUSH reg*/ + codegen_alloc_bytes(block, 4); + codegen_addbyte4(block, 0x66, 0x0f, 0xbe, 0xc0 | (dst_reg << 3) | src_reg); /*MOVSX dst_reg, src_reg*/ +} +void +host_x86_MOVSX_REG_32_8(codeblock_t *block, int dst_reg, int src_reg) +{ + codegen_alloc_bytes(block, 3); + codegen_addbyte3(block, 0x0f, 0xbe, 0xc0 | (dst_reg << 3) | src_reg); /*MOVSX dst_reg, src_reg*/ +} +void +host_x86_MOVSX_REG_32_16(codeblock_t *block, int dst_reg, int src_reg) +{ + codegen_alloc_bytes(block, 3); + codegen_addbyte3(block, 0x0f, 0xbf, 0xc0 | (dst_reg << 3) | src_reg); /*MOVSX dst_reg, src_reg*/ } -void host_x86_RET(codeblock_t *block) +void +host_x86_MOVZX_REG_ABS_16_8(codeblock_t *block, int dst_reg, void *p) { - codegen_alloc_bytes(block, 1); - codegen_addbyte(block, 0xc3); /*RET*/ -} + int offset = (uintptr_t) p - (((uintptr_t) &cpu_state) + 128); -void host_x86_ROL8_CL(codeblock_t *block, int dst_reg) -{ - codegen_alloc_bytes(block, 2); - codegen_addbyte2(block, 0xd2, 0xc0 | RM_OP_ROL | dst_reg); /*SHL dst_reg, CL*/ + if (offset >= -128 && offset < 127) { + codegen_alloc_bytes(block, 5); + codegen_addbyte(block, 0x66); + codegen_addbyte4(block, 0x0f, 0xb6, 0x45 | (dst_reg << 3), offset); /*MOV dest_reg, [EBP+offset]*/ + } else { + codegen_alloc_bytes(block, 8); + codegen_addbyte4(block, 0x66, 0x0f, 0xb6, 0x05 | (dst_reg << 3)); /*MOVZX dst_reg, [p]*/ + codegen_addlong(block, (uint32_t) p); + } } -void host_x86_ROL16_CL(codeblock_t *block, int dst_reg) +void +host_x86_MOVZX_REG_ABS_32_8(codeblock_t *block, int dst_reg, void *p) { - codegen_alloc_bytes(block, 3); - codegen_addbyte3(block, 0x66, 0xd3, 0xc0 | RM_OP_ROL | dst_reg); /*SHL dst_reg, CL*/ -} -void host_x86_ROL32_CL(codeblock_t *block, int dst_reg) -{ - codegen_alloc_bytes(block, 2); - codegen_addbyte2(block, 0xd3, 0xc0 | RM_OP_ROL | dst_reg); /*SHL dst_reg, CL*/ -} + int offset = (uintptr_t) p - (((uintptr_t) &cpu_state) + 128); -void host_x86_ROL8_IMM(codeblock_t *block, int dst_reg, int shift) -{ - codegen_alloc_bytes(block, 3); - codegen_addbyte3(block, 0xc0, 0xc0 | RM_OP_ROL | dst_reg, shift); /*SHL dst_reg, shift*/ -} -void host_x86_ROL16_IMM(codeblock_t *block, int dst_reg, int shift) -{ + if (offset >= -128 && offset < 127) { codegen_alloc_bytes(block, 4); - codegen_addbyte4(block, 0x66, 0xc1, 0xc0 | RM_OP_ROL | dst_reg, shift); /*SHL dst_reg, shift*/ + codegen_addbyte4(block, 0x0f, 0xb6, 0x45 | (dst_reg << 3), offset); /*MOV dest_reg, [EBP+offset]*/ + } else { + codegen_alloc_bytes(block, 7); + codegen_addbyte3(block, 0x0f, 0xb6, 0x05 | (dst_reg << 3)); /*MOVZX dst_reg, [p]*/ + codegen_addlong(block, (uint32_t) p); + } } -void host_x86_ROL32_IMM(codeblock_t *block, int dst_reg, int shift) +void +host_x86_MOVZX_REG_ABS_32_16(codeblock_t *block, int dst_reg, void *p) { - codegen_alloc_bytes(block, 3); - codegen_addbyte3(block, 0xc1, 0xc0 | RM_OP_ROL | dst_reg, shift); /*SHL dst_reg, shift*/ -} + int offset = (uintptr_t) p - (((uintptr_t) &cpu_state) + 128); -void host_x86_ROR8_CL(codeblock_t *block, int dst_reg) -{ - codegen_alloc_bytes(block, 2); - codegen_addbyte2(block, 0xd2, 0xc0 | RM_OP_ROR | dst_reg); /*SHR dst_reg, CL*/ -} -void host_x86_ROR16_CL(codeblock_t *block, int dst_reg) -{ - codegen_alloc_bytes(block, 3); - codegen_addbyte3(block, 0x66, 0xd3, 0xc0 | RM_OP_ROR | dst_reg); /*SHR dst_reg, CL*/ -} -void host_x86_ROR32_CL(codeblock_t *block, int dst_reg) -{ - codegen_alloc_bytes(block, 2); - codegen_addbyte2(block, 0xd3, 0xc0 | RM_OP_ROR | dst_reg); /*SHR dst_reg, CL*/ -} - -void host_x86_ROR8_IMM(codeblock_t *block, int dst_reg, int shift) -{ - codegen_alloc_bytes(block, 3); - codegen_addbyte3(block, 0xc0, 0xc0 | RM_OP_ROR | dst_reg, shift); /*SHR dst_reg, shift*/ -} -void host_x86_ROR16_IMM(codeblock_t *block, int dst_reg, int shift) -{ + if (offset >= -128 && offset < 127) { codegen_alloc_bytes(block, 4); - codegen_addbyte4(block, 0x66, 0xc1, 0xc0 | RM_OP_ROR | dst_reg, shift); /*SHR dst_reg, shift*/ -} -void host_x86_ROR32_IMM(codeblock_t *block, int dst_reg, int shift) -{ - codegen_alloc_bytes(block, 3); - codegen_addbyte3(block, 0xc1, 0xc0 | RM_OP_ROR | dst_reg, shift); /*SHR dst_reg, shift*/ + codegen_addbyte4(block, 0x0f, 0xb7, 0x45 | (dst_reg << 3), offset); /*MOV dest_reg, [EBP+offset]*/ + } else { + codegen_alloc_bytes(block, 7); + codegen_addbyte3(block, 0x0f, 0xb7, 0x05 | (dst_reg << 3)); /*MOVZX dst_reg, [p]*/ + codegen_addlong(block, (uint32_t) p); + } } -#define MODRM_MOD_REG(rm, reg) (0xc0 | reg | (rm << 3)) - -void host_x86_SAR8_CL(codeblock_t *block, int dst_reg) +void +host_x86_MOVZX_REG_16_8(codeblock_t *block, int dst_reg, int src_reg) { + codegen_alloc_bytes(block, 4); + codegen_addbyte4(block, 0x66, 0x0f, 0xb6, 0xc0 | (dst_reg << 3) | src_reg); /*MOVZX dst_reg, src_reg*/ +} +void +host_x86_MOVZX_REG_32_8(codeblock_t *block, int dst_reg, int src_reg) +{ + codegen_alloc_bytes(block, 3); + codegen_addbyte3(block, 0x0f, 0xb6, 0xc0 | (dst_reg << 3) | src_reg); /*MOVZX dst_reg, src_reg*/ +} +void +host_x86_MOVZX_REG_32_16(codeblock_t *block, int dst_reg, int src_reg) +{ + codegen_alloc_bytes(block, 3); + codegen_addbyte3(block, 0x0f, 0xb7, 0xc0 | (dst_reg << 3) | src_reg); /*MOVZX dst_reg, src_reg*/ +} + +void +host_x86_MOVZX_BASE_INDEX_32_8(codeblock_t *block, int dst_reg, int base_reg, int idx_reg) +{ + codegen_alloc_bytes(block, 4); + codegen_addbyte4(block, 0x0f, 0xb6, 0x04 | (dst_reg << 3), base_reg | (idx_reg << 3)); /*MOVZX dst_reg, B[base_reg + idx_reg]*/ +} +void +host_x86_MOVZX_BASE_INDEX_32_16(codeblock_t *block, int dst_reg, int base_reg, int idx_reg) +{ + codegen_alloc_bytes(block, 4); + codegen_addbyte4(block, 0x0f, 0xb7, 0x04 | (dst_reg << 3), base_reg | (idx_reg << 3)); /*MOVZX dst_reg, W[base_reg + idx_reg]*/ +} + +void +host_x86_OR8_REG_REG(codeblock_t *block, int dst_reg, int src_reg) +{ + codegen_alloc_bytes(block, 2); + codegen_addbyte2(block, 0x08, 0xc0 | dst_reg | (src_reg << 3)); /*OR dst_reg, src_reg_b*/ +} +void +host_x86_OR16_REG_REG(codeblock_t *block, int dst_reg, int src_reg) +{ + codegen_alloc_bytes(block, 3); + codegen_addbyte3(block, 0x66, 0x09, 0xc0 | dst_reg | (src_reg << 3)); /*OR dst_reg, src_reg_b*/ +} +void +host_x86_OR32_REG_REG(codeblock_t *block, int dst_reg, int src_reg) +{ + codegen_alloc_bytes(block, 2); + codegen_addbyte2(block, 0x09, 0xc0 | dst_reg | (src_reg << 3)); /*OR dst_reg, src_reg_b*/ +} + +void +host_x86_OR8_REG_IMM(codeblock_t *block, int dst_reg, uint8_t imm_data) +{ + if (dst_reg == REG_EAX) { codegen_alloc_bytes(block, 2); - codegen_addbyte2(block, 0xd2, 0xc0 | RM_OP_SAR | dst_reg); /*SAR dst_reg, CL*/ -} -void host_x86_SAR16_CL(codeblock_t *block, int dst_reg) -{ + codegen_addbyte2(block, 0x0c, imm_data); /*OR AL, imm_data*/ + } else { codegen_alloc_bytes(block, 3); - codegen_addbyte3(block, 0x66, 0xd3, 0xc0 | RM_OP_SAR | dst_reg); /*SAR dst_reg, CL*/ + codegen_addbyte3(block, 0x80, 0xc0 | RM_OP_OR | dst_reg, imm_data); /*OR dst_reg, imm_data*/ + } } -void host_x86_SAR32_CL(codeblock_t *block, int dst_reg) -{ - codegen_alloc_bytes(block, 2); - codegen_addbyte2(block, 0xd3, 0xc0 | RM_OP_SAR | dst_reg); /*SAR dst_reg, CL*/ -} - -void host_x86_SAR8_IMM(codeblock_t *block, int dst_reg, int shift) -{ - codegen_alloc_bytes(block, 3); - codegen_addbyte3(block, 0xc0, 0xc0 | RM_OP_SAR | dst_reg, shift); /*SAR dst_reg, shift*/ -} -void host_x86_SAR16_IMM(codeblock_t *block, int dst_reg, int shift) +void +host_x86_OR16_REG_IMM(codeblock_t *block, int dst_reg, uint16_t imm_data) { + if (is_imm8(imm_data)) { codegen_alloc_bytes(block, 4); - codegen_addbyte4(block, 0x66, 0xc1, 0xc0 | RM_OP_SAR | dst_reg, shift); /*SAR dst_reg, shift*/ + codegen_addbyte4(block, 0x66, 0x83, 0xc0 | RM_OP_OR | dst_reg, imm_data & 0xff); /*OR dst_reg, imm_data*/ + } else if (dst_reg == REG_EAX) { + codegen_alloc_bytes(block, 6); + codegen_addbyte2(block, 0x66, 0x0d); /*OR AX, imm_data*/ + codegen_addword(block, imm_data); + } else { + codegen_alloc_bytes(block, 7); + codegen_addbyte3(block, 0x66, 0x81, 0xc0 | RM_OP_OR | dst_reg); /*OR dst_reg, imm_data*/ + codegen_addword(block, imm_data); + } } -void host_x86_SAR32_IMM(codeblock_t *block, int dst_reg, int shift) +void +host_x86_OR32_REG_IMM(codeblock_t *block, int dst_reg, uint32_t imm_data) { + if (is_imm8(imm_data)) { codegen_alloc_bytes(block, 3); - codegen_addbyte3(block, 0xc1, 0xc0 | RM_OP_SAR | dst_reg, shift); /*SAR dst_reg, shift*/ + codegen_addbyte3(block, 0x83, 0xc0 | RM_OP_OR | dst_reg, imm_data & 0xff); /*OR dst_reg, imm_data*/ + } else if (dst_reg == REG_EAX) { + codegen_alloc_bytes(block, 5); + codegen_addbyte(block, 0x0d); /*OR EAX, imm_data*/ + codegen_addlong(block, imm_data); + } else { + codegen_alloc_bytes(block, 6); + codegen_addbyte2(block, 0x81, 0xc0 | RM_OP_OR | dst_reg); /*OR dst_reg, imm_data*/ + codegen_addlong(block, imm_data); + } } -void host_x86_SHL8_CL(codeblock_t *block, int dst_reg) +void +host_x86_POP(codeblock_t *block, int src_reg) { - codegen_alloc_bytes(block, 2); - codegen_addbyte2(block, 0xd2, 0xc0 | RM_OP_SHL | dst_reg); /*SHL dst_reg, CL*/ -} -void host_x86_SHL16_CL(codeblock_t *block, int dst_reg) -{ - codegen_alloc_bytes(block, 3); - codegen_addbyte3(block, 0x66, 0xd3, 0xc0 | RM_OP_SHL | dst_reg); /*SHL dst_reg, CL*/ -} -void host_x86_SHL32_CL(codeblock_t *block, int dst_reg) -{ - codegen_alloc_bytes(block, 2); - codegen_addbyte2(block, 0xd3, 0xc0 | RM_OP_SHL | dst_reg); /*SHL dst_reg, CL*/ + codegen_alloc_bytes(block, 1); + codegen_addbyte(block, 0x58 | src_reg); /*POP reg*/ } -void host_x86_SHL8_IMM(codeblock_t *block, int dst_reg, int shift) +void +host_x86_PUSH(codeblock_t *block, int src_reg) { - codegen_alloc_bytes(block, 3); - codegen_addbyte3(block, 0xc0, 0xc0 | RM_OP_SHL | dst_reg, shift); /*SHL dst_reg, shift*/ + codegen_alloc_bytes(block, 1); + codegen_addbyte(block, 0x50 | src_reg); /*PUSH reg*/ } -void host_x86_SHL16_IMM(codeblock_t *block, int dst_reg, int shift) + +void +host_x86_RET(codeblock_t *block) { + codegen_alloc_bytes(block, 1); + codegen_addbyte(block, 0xc3); /*RET*/ +} + +void +host_x86_ROL8_CL(codeblock_t *block, int dst_reg) +{ + codegen_alloc_bytes(block, 2); + codegen_addbyte2(block, 0xd2, 0xc0 | RM_OP_ROL | dst_reg); /*SHL dst_reg, CL*/ +} +void +host_x86_ROL16_CL(codeblock_t *block, int dst_reg) +{ + codegen_alloc_bytes(block, 3); + codegen_addbyte3(block, 0x66, 0xd3, 0xc0 | RM_OP_ROL | dst_reg); /*SHL dst_reg, CL*/ +} +void +host_x86_ROL32_CL(codeblock_t *block, int dst_reg) +{ + codegen_alloc_bytes(block, 2); + codegen_addbyte2(block, 0xd3, 0xc0 | RM_OP_ROL | dst_reg); /*SHL dst_reg, CL*/ +} + +void +host_x86_ROL8_IMM(codeblock_t *block, int dst_reg, int shift) +{ + codegen_alloc_bytes(block, 3); + codegen_addbyte3(block, 0xc0, 0xc0 | RM_OP_ROL | dst_reg, shift); /*SHL dst_reg, shift*/ +} +void +host_x86_ROL16_IMM(codeblock_t *block, int dst_reg, int shift) +{ + codegen_alloc_bytes(block, 4); + codegen_addbyte4(block, 0x66, 0xc1, 0xc0 | RM_OP_ROL | dst_reg, shift); /*SHL dst_reg, shift*/ +} +void +host_x86_ROL32_IMM(codeblock_t *block, int dst_reg, int shift) +{ + codegen_alloc_bytes(block, 3); + codegen_addbyte3(block, 0xc1, 0xc0 | RM_OP_ROL | dst_reg, shift); /*SHL dst_reg, shift*/ +} + +void +host_x86_ROR8_CL(codeblock_t *block, int dst_reg) +{ + codegen_alloc_bytes(block, 2); + codegen_addbyte2(block, 0xd2, 0xc0 | RM_OP_ROR | dst_reg); /*SHR dst_reg, CL*/ +} +void +host_x86_ROR16_CL(codeblock_t *block, int dst_reg) +{ + codegen_alloc_bytes(block, 3); + codegen_addbyte3(block, 0x66, 0xd3, 0xc0 | RM_OP_ROR | dst_reg); /*SHR dst_reg, CL*/ +} +void +host_x86_ROR32_CL(codeblock_t *block, int dst_reg) +{ + codegen_alloc_bytes(block, 2); + codegen_addbyte2(block, 0xd3, 0xc0 | RM_OP_ROR | dst_reg); /*SHR dst_reg, CL*/ +} + +void +host_x86_ROR8_IMM(codeblock_t *block, int dst_reg, int shift) +{ + codegen_alloc_bytes(block, 3); + codegen_addbyte3(block, 0xc0, 0xc0 | RM_OP_ROR | dst_reg, shift); /*SHR dst_reg, shift*/ +} +void +host_x86_ROR16_IMM(codeblock_t *block, int dst_reg, int shift) +{ + codegen_alloc_bytes(block, 4); + codegen_addbyte4(block, 0x66, 0xc1, 0xc0 | RM_OP_ROR | dst_reg, shift); /*SHR dst_reg, shift*/ +} +void +host_x86_ROR32_IMM(codeblock_t *block, int dst_reg, int shift) +{ + codegen_alloc_bytes(block, 3); + codegen_addbyte3(block, 0xc1, 0xc0 | RM_OP_ROR | dst_reg, shift); /*SHR dst_reg, shift*/ +} + +# define MODRM_MOD_REG(rm, reg) (0xc0 | reg | (rm << 3)) + +void +host_x86_SAR8_CL(codeblock_t *block, int dst_reg) +{ + codegen_alloc_bytes(block, 2); + codegen_addbyte2(block, 0xd2, 0xc0 | RM_OP_SAR | dst_reg); /*SAR dst_reg, CL*/ +} +void +host_x86_SAR16_CL(codeblock_t *block, int dst_reg) +{ + codegen_alloc_bytes(block, 3); + codegen_addbyte3(block, 0x66, 0xd3, 0xc0 | RM_OP_SAR | dst_reg); /*SAR dst_reg, CL*/ +} +void +host_x86_SAR32_CL(codeblock_t *block, int dst_reg) +{ + codegen_alloc_bytes(block, 2); + codegen_addbyte2(block, 0xd3, 0xc0 | RM_OP_SAR | dst_reg); /*SAR dst_reg, CL*/ +} + +void +host_x86_SAR8_IMM(codeblock_t *block, int dst_reg, int shift) +{ + codegen_alloc_bytes(block, 3); + codegen_addbyte3(block, 0xc0, 0xc0 | RM_OP_SAR | dst_reg, shift); /*SAR dst_reg, shift*/ +} +void +host_x86_SAR16_IMM(codeblock_t *block, int dst_reg, int shift) +{ + codegen_alloc_bytes(block, 4); + codegen_addbyte4(block, 0x66, 0xc1, 0xc0 | RM_OP_SAR | dst_reg, shift); /*SAR dst_reg, shift*/ +} +void +host_x86_SAR32_IMM(codeblock_t *block, int dst_reg, int shift) +{ + codegen_alloc_bytes(block, 3); + codegen_addbyte3(block, 0xc1, 0xc0 | RM_OP_SAR | dst_reg, shift); /*SAR dst_reg, shift*/ +} + +void +host_x86_SHL8_CL(codeblock_t *block, int dst_reg) +{ + codegen_alloc_bytes(block, 2); + codegen_addbyte2(block, 0xd2, 0xc0 | RM_OP_SHL | dst_reg); /*SHL dst_reg, CL*/ +} +void +host_x86_SHL16_CL(codeblock_t *block, int dst_reg) +{ + codegen_alloc_bytes(block, 3); + codegen_addbyte3(block, 0x66, 0xd3, 0xc0 | RM_OP_SHL | dst_reg); /*SHL dst_reg, CL*/ +} +void +host_x86_SHL32_CL(codeblock_t *block, int dst_reg) +{ + codegen_alloc_bytes(block, 2); + codegen_addbyte2(block, 0xd3, 0xc0 | RM_OP_SHL | dst_reg); /*SHL dst_reg, CL*/ +} + +void +host_x86_SHL8_IMM(codeblock_t *block, int dst_reg, int shift) +{ + codegen_alloc_bytes(block, 3); + codegen_addbyte3(block, 0xc0, 0xc0 | RM_OP_SHL | dst_reg, shift); /*SHL dst_reg, shift*/ +} +void +host_x86_SHL16_IMM(codeblock_t *block, int dst_reg, int shift) +{ + codegen_alloc_bytes(block, 4); + codegen_addbyte4(block, 0x66, 0xc1, 0xc0 | RM_OP_SHL | dst_reg, shift); /*SHL dst_reg, shift*/ +} +void +host_x86_SHL32_IMM(codeblock_t *block, int dst_reg, int shift) +{ + codegen_alloc_bytes(block, 3); + codegen_addbyte3(block, 0xc1, 0xc0 | RM_OP_SHL | dst_reg, shift); /*SHL dst_reg, shift*/ +} + +void +host_x86_SHR8_CL(codeblock_t *block, int dst_reg) +{ + codegen_alloc_bytes(block, 2); + codegen_addbyte2(block, 0xd2, 0xc0 | RM_OP_SHR | dst_reg); /*SHR dst_reg, CL*/ +} +void +host_x86_SHR16_CL(codeblock_t *block, int dst_reg) +{ + codegen_alloc_bytes(block, 3); + codegen_addbyte3(block, 0x66, 0xd3, 0xc0 | RM_OP_SHR | dst_reg); /*SHR dst_reg, CL*/ +} +void +host_x86_SHR32_CL(codeblock_t *block, int dst_reg) +{ + codegen_alloc_bytes(block, 2); + codegen_addbyte2(block, 0xd3, 0xc0 | RM_OP_SHR | dst_reg); /*SHR dst_reg, CL*/ +} + +void +host_x86_SHR8_IMM(codeblock_t *block, int dst_reg, int shift) +{ + codegen_alloc_bytes(block, 3); + codegen_addbyte3(block, 0xc0, 0xc0 | RM_OP_SHR | dst_reg, shift); /*SHR dst_reg, shift*/ +} +void +host_x86_SHR16_IMM(codeblock_t *block, int dst_reg, int shift) +{ + codegen_alloc_bytes(block, 4); + codegen_addbyte4(block, 0x66, 0xc1, 0xc0 | RM_OP_SHR | dst_reg, shift); /*SHR dst_reg, shift*/ +} +void +host_x86_SHR32_IMM(codeblock_t *block, int dst_reg, int shift) +{ + codegen_alloc_bytes(block, 3); + codegen_addbyte3(block, 0xc1, 0xc0 | RM_OP_SHR | dst_reg, shift); /*SHR dst_reg, shift*/ +} + +void +host_x86_SUB8_REG_IMM(codeblock_t *block, int dst_reg, uint8_t imm_data) +{ + if (dst_reg == REG_EAX) { + codegen_alloc_bytes(block, 2); + codegen_addbyte2(block, 0x2c, imm_data); /*SUB AL, imm_data*/ + } else { + codegen_alloc_bytes(block, 3); + codegen_addbyte3(block, 0x80, 0xc0 | RM_OP_SUB | dst_reg, imm_data); /*SUB dst_reg, imm_data*/ + } +} +void +host_x86_SUB16_REG_IMM(codeblock_t *block, int dst_reg, uint16_t imm_data) +{ + if (is_imm8(imm_data)) { codegen_alloc_bytes(block, 4); - codegen_addbyte4(block, 0x66, 0xc1, 0xc0 | RM_OP_SHL | dst_reg, shift); /*SHL dst_reg, shift*/ -} -void host_x86_SHL32_IMM(codeblock_t *block, int dst_reg, int shift) -{ - codegen_alloc_bytes(block, 3); - codegen_addbyte3(block, 0xc1, 0xc0 | RM_OP_SHL | dst_reg, shift); /*SHL dst_reg, shift*/ -} - -void host_x86_SHR8_CL(codeblock_t *block, int dst_reg) -{ - codegen_alloc_bytes(block, 2); - codegen_addbyte2(block, 0xd2, 0xc0 | RM_OP_SHR | dst_reg); /*SHR dst_reg, CL*/ -} -void host_x86_SHR16_CL(codeblock_t *block, int dst_reg) -{ - codegen_alloc_bytes(block, 3); - codegen_addbyte3(block, 0x66, 0xd3, 0xc0 | RM_OP_SHR | dst_reg); /*SHR dst_reg, CL*/ -} -void host_x86_SHR32_CL(codeblock_t *block, int dst_reg) -{ - codegen_alloc_bytes(block, 2); - codegen_addbyte2(block, 0xd3, 0xc0 | RM_OP_SHR | dst_reg); /*SHR dst_reg, CL*/ -} - -void host_x86_SHR8_IMM(codeblock_t *block, int dst_reg, int shift) -{ - codegen_alloc_bytes(block, 3); - codegen_addbyte3(block, 0xc0, 0xc0 | RM_OP_SHR | dst_reg, shift); /*SHR dst_reg, shift*/ -} -void host_x86_SHR16_IMM(codeblock_t *block, int dst_reg, int shift) -{ + codegen_addbyte4(block, 0x66, 0x83, 0xc0 | RM_OP_SUB | dst_reg, imm_data & 0xff); /*SUB dst_reg, imm_data*/ + } else if (dst_reg == REG_EAX) { codegen_alloc_bytes(block, 4); - codegen_addbyte4(block, 0x66, 0xc1, 0xc0 | RM_OP_SHR | dst_reg, shift); /*SHR dst_reg, shift*/ + codegen_addbyte2(block, 0x66, 0x2d); /*SUB AX, imm_data*/ + codegen_addword(block, imm_data); + } else { + codegen_alloc_bytes(block, 5); + codegen_addbyte3(block, 0x66, 0x81, 0xc0 | RM_OP_SUB | dst_reg); /*SUB dst_reg, imm_data*/ + codegen_addword(block, imm_data); + } } -void host_x86_SHR32_IMM(codeblock_t *block, int dst_reg, int shift) +void +host_x86_SUB32_REG_IMM(codeblock_t *block, int dst_reg, uint32_t imm_data) { + if (is_imm8(imm_data)) { codegen_alloc_bytes(block, 3); - codegen_addbyte3(block, 0xc1, 0xc0 | RM_OP_SHR | dst_reg, shift); /*SHR dst_reg, shift*/ + codegen_addbyte3(block, 0x83, 0xc0 | RM_OP_SUB | dst_reg, imm_data & 0xff); /*SUB dst_reg, imm_data*/ + } else if (dst_reg == REG_EAX) { + codegen_alloc_bytes(block, 5); + codegen_addbyte(block, 0x2d); /*SUB EAX, imm_data*/ + codegen_addlong(block, imm_data); + } else { + codegen_alloc_bytes(block, 6); + codegen_addbyte2(block, 0x81, 0xc0 | RM_OP_SUB | dst_reg); /*SUB dst_reg, imm_data*/ + codegen_addlong(block, imm_data); + } } -void host_x86_SUB8_REG_IMM(codeblock_t *block, int dst_reg, uint8_t imm_data) +void +host_x86_SUB8_REG_REG(codeblock_t *block, int dst_reg, int src_reg) { - if (dst_reg == REG_EAX) - { - codegen_alloc_bytes(block, 2); - codegen_addbyte2(block, 0x2c, imm_data); /*SUB AL, imm_data*/ - } - else - { - codegen_alloc_bytes(block, 3); - codegen_addbyte3(block, 0x80, 0xc0 | RM_OP_SUB | dst_reg, imm_data); /*SUB dst_reg, imm_data*/ - } + codegen_alloc_bytes(block, 2); + codegen_addbyte2(block, 0x28, 0xc0 | dst_reg | (src_reg << 3)); /*SUB dst_reg, src_reg*/ } -void host_x86_SUB16_REG_IMM(codeblock_t *block, int dst_reg, uint16_t imm_data) +void +host_x86_SUB16_REG_REG(codeblock_t *block, int dst_reg, int src_reg) { - if (is_imm8(imm_data)) - { - codegen_alloc_bytes(block, 4); - codegen_addbyte4(block, 0x66, 0x83, 0xc0 | RM_OP_SUB | dst_reg, imm_data & 0xff); /*SUB dst_reg, imm_data*/ - } - else if (dst_reg == REG_EAX) - { - codegen_alloc_bytes(block, 4); - codegen_addbyte2(block, 0x66, 0x2d); /*SUB AX, imm_data*/ - codegen_addword(block, imm_data); - } - else - { - codegen_alloc_bytes(block, 5); - codegen_addbyte3(block, 0x66, 0x81, 0xc0 | RM_OP_SUB | dst_reg); /*SUB dst_reg, imm_data*/ - codegen_addword(block, imm_data); - } + codegen_alloc_bytes(block, 3); + codegen_addbyte3(block, 0x66, 0x29, 0xc0 | dst_reg | (src_reg << 3)); /*SUB dst_reg, src_reg*/ } -void host_x86_SUB32_REG_IMM(codeblock_t *block, int dst_reg, uint32_t imm_data) +void +host_x86_SUB32_REG_REG(codeblock_t *block, int dst_reg, int src_reg) { - if (is_imm8(imm_data)) - { - codegen_alloc_bytes(block, 3); - codegen_addbyte3(block, 0x83, 0xc0 | RM_OP_SUB | dst_reg, imm_data & 0xff); /*SUB dst_reg, imm_data*/ - } - else if (dst_reg == REG_EAX) - { - codegen_alloc_bytes(block, 5); - codegen_addbyte(block, 0x2d); /*SUB EAX, imm_data*/ - codegen_addlong(block, imm_data); - } - else - { - codegen_alloc_bytes(block, 6); - codegen_addbyte2(block, 0x81, 0xc0 | RM_OP_SUB | dst_reg); /*SUB dst_reg, imm_data*/ - codegen_addlong(block, imm_data); - } + codegen_alloc_bytes(block, 2); + codegen_addbyte2(block, 0x29, 0xc0 | dst_reg | (src_reg << 3)); /*SUB dst_reg, src_reg*/ } -void host_x86_SUB8_REG_REG(codeblock_t *block, int dst_reg, int src_reg) +void +host_x86_TEST8_REG(codeblock_t *block, int src_host_reg, int dst_host_reg) { + codegen_alloc_bytes(block, 2); + codegen_addbyte2(block, 0x84, MODRM_MOD_REG(dst_host_reg, src_host_reg)); /*TEST dst_host_reg, src_host_reg*/ +} +void +host_x86_TEST16_REG(codeblock_t *block, int src_host_reg, int dst_host_reg) +{ + codegen_alloc_bytes(block, 3); + codegen_addbyte3(block, 0x66, 0x85, MODRM_MOD_REG(dst_host_reg, src_host_reg)); /*TEST dst_host_reg, src_host_reg*/ +} +void +host_x86_TEST32_REG(codeblock_t *block, int src_host_reg, int dst_host_reg) +{ + codegen_alloc_bytes(block, 2); + codegen_addbyte2(block, 0x85, MODRM_MOD_REG(dst_host_reg, src_host_reg)); /*TEST dst_host_reg, src_host_reg*/ +} +void +host_x86_TEST32_REG_IMM(codeblock_t *block, int dst_reg, uint32_t imm_data) +{ + if (dst_reg == REG_EAX) { + codegen_alloc_bytes(block, 5); + codegen_addbyte(block, 0xa9); /*TEST EAX, imm_data*/ + codegen_addlong(block, imm_data); + } else { + codegen_alloc_bytes(block, 6); + codegen_addbyte2(block, 0xf7, 0xc0 | dst_reg); /*TEST dst_reg, imm_data*/ + codegen_addlong(block, imm_data); + } +} + +void +host_x86_XOR8_REG_REG(codeblock_t *block, int dst_reg, int src_reg) +{ + codegen_alloc_bytes(block, 2); + codegen_addbyte2(block, 0x30, 0xc0 | dst_reg | (src_reg << 3)); /*XOR dst_reg, src_reg*/ +} +void +host_x86_XOR16_REG_REG(codeblock_t *block, int dst_reg, int src_reg) +{ + codegen_alloc_bytes(block, 3); + codegen_addbyte3(block, 0x66, 0x31, 0xc0 | dst_reg | (src_reg << 3)); /*XOR dst_reg, src_reg*/ +} +void +host_x86_XOR32_REG_REG(codeblock_t *block, int dst_reg, int src_reg) +{ + codegen_alloc_bytes(block, 2); + codegen_addbyte2(block, 0x31, 0xc0 | dst_reg | (src_reg << 3)); /*XOR dst_reg, src_reg*/ +} + +void +host_x86_XOR8_REG_IMM(codeblock_t *block, int dst_reg, uint8_t imm_data) +{ + if (dst_reg == REG_EAX) { codegen_alloc_bytes(block, 2); - codegen_addbyte2(block, 0x28, 0xc0 | dst_reg | (src_reg << 3)); /*SUB dst_reg, src_reg*/ -} -void host_x86_SUB16_REG_REG(codeblock_t *block, int dst_reg, int src_reg) -{ + codegen_addbyte2(block, 0x34, imm_data); /*XOR AL, imm_data*/ + } else { codegen_alloc_bytes(block, 3); - codegen_addbyte3(block, 0x66, 0x29, 0xc0 | dst_reg | (src_reg << 3)); /*SUB dst_reg, src_reg*/ + codegen_addbyte3(block, 0x80, 0xc0 | RM_OP_XOR | dst_reg, imm_data); /*XOR dst_reg, imm_data*/ + } } -void host_x86_SUB32_REG_REG(codeblock_t *block, int dst_reg, int src_reg) +void +host_x86_XOR16_REG_IMM(codeblock_t *block, int dst_reg, uint16_t imm_data) { - codegen_alloc_bytes(block, 2); - codegen_addbyte2(block, 0x29, 0xc0 | dst_reg | (src_reg << 3)); /*SUB dst_reg, src_reg*/ + if (is_imm8(imm_data)) { + codegen_alloc_bytes(block, 4); + codegen_addbyte4(block, 0x66, 0x83, 0xc0 | RM_OP_XOR | dst_reg, imm_data & 0xff); /*XOR dst_reg, imm_data*/ + } else if (dst_reg == REG_EAX) { + codegen_alloc_bytes(block, 4); + codegen_addbyte2(block, 0x66, 0x35); /*XOR AX, imm_data*/ + codegen_addword(block, imm_data); + } else { + codegen_alloc_bytes(block, 5); + codegen_addbyte3(block, 0x66, 0x81, 0xc0 | RM_OP_XOR | dst_reg); /*XOR dst_reg, imm_data*/ + codegen_addword(block, imm_data); + } } - -void host_x86_TEST8_REG(codeblock_t *block, int src_host_reg, int dst_host_reg) -{ - codegen_alloc_bytes(block, 2); - codegen_addbyte2(block, 0x84, MODRM_MOD_REG(dst_host_reg, src_host_reg)); /*TEST dst_host_reg, src_host_reg*/ -} -void host_x86_TEST16_REG(codeblock_t *block, int src_host_reg, int dst_host_reg) +void +host_x86_XOR32_REG_IMM(codeblock_t *block, int dst_reg, uint32_t imm_data) { + if (is_imm8(imm_data)) { codegen_alloc_bytes(block, 3); - codegen_addbyte3(block, 0x66, 0x85, MODRM_MOD_REG(dst_host_reg, src_host_reg)); /*TEST dst_host_reg, src_host_reg*/ -} -void host_x86_TEST32_REG(codeblock_t *block, int src_host_reg, int dst_host_reg) -{ - codegen_alloc_bytes(block, 2); - codegen_addbyte2(block, 0x85, MODRM_MOD_REG(dst_host_reg, src_host_reg)); /*TEST dst_host_reg, src_host_reg*/ -} -void host_x86_TEST32_REG_IMM(codeblock_t *block, int dst_reg, uint32_t imm_data) -{ - if (dst_reg == REG_EAX) - { - codegen_alloc_bytes(block, 5); - codegen_addbyte(block, 0xa9); /*TEST EAX, imm_data*/ - codegen_addlong(block, imm_data); - } - else - { - codegen_alloc_bytes(block, 6); - codegen_addbyte2(block, 0xf7, 0xc0 | dst_reg); /*TEST dst_reg, imm_data*/ - codegen_addlong(block, imm_data); - } -} - -void host_x86_XOR8_REG_REG(codeblock_t *block, int dst_reg, int src_reg) -{ - codegen_alloc_bytes(block, 2); - codegen_addbyte2(block, 0x30, 0xc0 | dst_reg | (src_reg << 3)); /*XOR dst_reg, src_reg*/ -} -void host_x86_XOR16_REG_REG(codeblock_t *block, int dst_reg, int src_reg) -{ - codegen_alloc_bytes(block, 3); - codegen_addbyte3(block, 0x66, 0x31, 0xc0 | dst_reg | (src_reg << 3)); /*XOR dst_reg, src_reg*/ -} -void host_x86_XOR32_REG_REG(codeblock_t *block, int dst_reg, int src_reg) -{ - codegen_alloc_bytes(block, 2); - codegen_addbyte2(block, 0x31, 0xc0 | dst_reg | (src_reg << 3)); /*XOR dst_reg, src_reg*/ -} - -void host_x86_XOR8_REG_IMM(codeblock_t *block, int dst_reg, uint8_t imm_data) -{ - if (dst_reg == REG_EAX) - { - codegen_alloc_bytes(block, 2); - codegen_addbyte2(block, 0x34, imm_data); /*XOR AL, imm_data*/ - } - else - { - codegen_alloc_bytes(block, 3); - codegen_addbyte3(block, 0x80, 0xc0 | RM_OP_XOR | dst_reg, imm_data); /*XOR dst_reg, imm_data*/ - } -} -void host_x86_XOR16_REG_IMM(codeblock_t *block, int dst_reg, uint16_t imm_data) -{ - if (is_imm8(imm_data)) - { - codegen_alloc_bytes(block, 4); - codegen_addbyte4(block, 0x66, 0x83, 0xc0 | RM_OP_XOR | dst_reg, imm_data & 0xff); /*XOR dst_reg, imm_data*/ - } - else if (dst_reg == REG_EAX) - { - codegen_alloc_bytes(block, 4); - codegen_addbyte2(block, 0x66, 0x35); /*XOR AX, imm_data*/ - codegen_addword(block, imm_data); - } - else - { - codegen_alloc_bytes(block, 5); - codegen_addbyte3(block, 0x66, 0x81, 0xc0 | RM_OP_XOR | dst_reg); /*XOR dst_reg, imm_data*/ - codegen_addword(block, imm_data); - } -} -void host_x86_XOR32_REG_IMM(codeblock_t *block, int dst_reg, uint32_t imm_data) -{ - if (is_imm8(imm_data)) - { - codegen_alloc_bytes(block, 3); - codegen_addbyte3(block, 0x83, 0xc0 | RM_OP_XOR | dst_reg, imm_data & 0xff); /*XOR dst_reg, imm_data*/ - } - else if (dst_reg == REG_EAX) - { - codegen_alloc_bytes(block, 5); - codegen_addbyte(block, 0x35); /*XOR EAX, imm_data*/ - codegen_addlong(block, imm_data); - } - else - { - codegen_alloc_bytes(block, 6); - codegen_addbyte2(block, 0x81, 0xc0 | RM_OP_XOR | dst_reg); /*XOR dst_reg, imm_data*/ - codegen_addlong(block, imm_data); - } + codegen_addbyte3(block, 0x83, 0xc0 | RM_OP_XOR | dst_reg, imm_data & 0xff); /*XOR dst_reg, imm_data*/ + } else if (dst_reg == REG_EAX) { + codegen_alloc_bytes(block, 5); + codegen_addbyte(block, 0x35); /*XOR EAX, imm_data*/ + codegen_addlong(block, imm_data); + } else { + codegen_alloc_bytes(block, 6); + codegen_addbyte2(block, 0x81, 0xc0 | RM_OP_XOR | dst_reg); /*XOR dst_reg, imm_data*/ + codegen_addlong(block, imm_data); + } } #endif diff --git a/src/codegen_new/codegen_backend_x86_ops.h b/src/codegen_new/codegen_backend_x86_ops.h index 53b6e0e73..0890286ef 100644 --- a/src/codegen_new/codegen_backend_x86_ops.h +++ b/src/codegen_new/codegen_backend_x86_ops.h @@ -27,7 +27,7 @@ void host_x86_CMP32_REG_REG(codeblock_t *block, int src_reg_a, int src_reg_b); void host_x86_INC32_ABS(codeblock_t *block, void *p); -void host_x86_JMP(codeblock_t *block, void *p); +void host_x86_JMP(codeblock_t *block, void *p); uint32_t *host_x86_JMP_short(codeblock_t *block); uint32_t *host_x86_JMP_long(codeblock_t *block); diff --git a/src/codegen_new/codegen_backend_x86_ops_fpu.c b/src/codegen_new/codegen_backend_x86_ops_fpu.c index cb8f36ac6..7f4735124 100644 --- a/src/codegen_new/codegen_backend_x86_ops_fpu.c +++ b/src/codegen_new/codegen_backend_x86_ops_fpu.c @@ -1,84 +1,75 @@ #if defined i386 || defined __i386 || defined __i386__ || defined _X86_ || defined _M_IX86 -#include -#include <86box/86box.h> -#include "cpu.h" -#include <86box/mem.h> +# include +# include <86box/86box.h> +# include "cpu.h" +# include <86box/mem.h> +# include <86box/plat_unused.h> -#include "codegen.h" -#include "codegen_allocator.h" -#include "codegen_backend.h" -#include "codegen_backend_x86_defs.h" -#include "codegen_backend_x86_ops_fpu.h" -#include "codegen_backend_x86_ops_helpers.h" +# include "codegen.h" +# include "codegen_allocator.h" +# include "codegen_backend.h" +# include "codegen_backend_x86_defs.h" +# include "codegen_backend_x86_ops_fpu.h" +# include "codegen_backend_x86_ops_helpers.h" -void host_x87_FILDq_BASE(codeblock_t *block, int base_reg) +void +host_x87_FILDq_BASE(codeblock_t *block, int base_reg) { - if (base_reg == REG_ESP) - { - codegen_alloc_bytes(block, 3); - codegen_addbyte3(block, 0xdf, 0x2c, 0x24); /*FILDq [ESP]*/ - } - else - { - codegen_alloc_bytes(block, 2); - codegen_addbyte2(block, 0xdf, 0x28 | base_reg); /*FILDq [base_reg]*/ - } + if (base_reg == REG_ESP) { + codegen_alloc_bytes(block, 3); + codegen_addbyte3(block, 0xdf, 0x2c, 0x24); /*FILDq [ESP]*/ + } else { + codegen_alloc_bytes(block, 2); + codegen_addbyte2(block, 0xdf, 0x28 | base_reg); /*FILDq [base_reg]*/ + } } -void host_x87_FISTPq_BASE(codeblock_t *block, int base_reg) +void +host_x87_FISTPq_BASE(codeblock_t *block, int base_reg) { - if (base_reg == REG_ESP) - { - codegen_alloc_bytes(block, 3); - codegen_addbyte3(block, 0xdf, 0x3c, 0x24); /*FISTPq [ESP]*/ - } - else - { - codegen_alloc_bytes(block, 2); - codegen_addbyte2(block, 0xdf, 0x38 | base_reg); /*FISTPq [base_reg]*/ - } + if (base_reg == REG_ESP) { + codegen_alloc_bytes(block, 3); + codegen_addbyte3(block, 0xdf, 0x3c, 0x24); /*FISTPq [ESP]*/ + } else { + codegen_alloc_bytes(block, 2); + codegen_addbyte2(block, 0xdf, 0x38 | base_reg); /*FISTPq [base_reg]*/ + } } -void host_x87_FLDCW(codeblock_t *block, void *p) +void +host_x87_FLDCW(codeblock_t *block, void *p) { - int offset = (uintptr_t)p - (((uintptr_t)&cpu_state) + 128); + int offset = (uintptr_t) p - (((uintptr_t) &cpu_state) + 128); - if (offset >= -128 && offset < 127) - { - codegen_alloc_bytes(block, 3); - codegen_addbyte3(block, 0xd9, 0x68 | REG_EBP, offset); /*FLDCW offset[EBP]*/ - } - else - { - codegen_alloc_bytes(block, 6); - codegen_addbyte2(block, 0xd9, 0x2d); /*FLDCW [p]*/ - codegen_addlong(block, (uint32_t)p); - } + if (offset >= -128 && offset < 127) { + codegen_alloc_bytes(block, 3); + codegen_addbyte3(block, 0xd9, 0x68 | REG_EBP, offset); /*FLDCW offset[EBP]*/ + } else { + codegen_alloc_bytes(block, 6); + codegen_addbyte2(block, 0xd9, 0x2d); /*FLDCW [p]*/ + codegen_addlong(block, (uint32_t) p); + } } -void host_x87_FLDd_BASE(codeblock_t *block, int base_reg) +void +host_x87_FLDd_BASE(codeblock_t *block, int base_reg) { - if (base_reg == REG_ESP) - { - codegen_alloc_bytes(block, 3); - codegen_addbyte3(block, 0xdd, 0x04, 0x24); /*FILDq [ESP]*/ - } - else - { - codegen_alloc_bytes(block, 2); - codegen_addbyte2(block, 0xdd, 0x08 | base_reg); /*FILDq [base_reg]*/ - } + if (base_reg == REG_ESP) { + codegen_alloc_bytes(block, 3); + codegen_addbyte3(block, 0xdd, 0x04, 0x24); /*FILDq [ESP]*/ + } else { + codegen_alloc_bytes(block, 2); + codegen_addbyte2(block, 0xdd, 0x08 | base_reg); /*FILDq [base_reg]*/ + } } -void host_x87_FSTPd_BASE(codeblock_t *block, int base_reg) +void +host_x87_FSTPd_BASE(codeblock_t *block, int base_reg) { - if (base_reg == REG_ESP) - { - codegen_alloc_bytes(block, 3); - codegen_addbyte3(block, 0xdd, 0x1c, 0x24); /*FILDq [ESP]*/ - } - else - { - codegen_alloc_bytes(block, 2); - codegen_addbyte2(block, 0xdd, 0x18 | base_reg); /*FILDq [base_reg]*/ - } + if (base_reg == REG_ESP) { + codegen_alloc_bytes(block, 3); + codegen_addbyte3(block, 0xdd, 0x1c, 0x24); /*FILDq [ESP]*/ + } else { + codegen_alloc_bytes(block, 2); + codegen_addbyte2(block, 0xdd, 0x18 | base_reg); /*FILDq [base_reg]*/ + } } #endif diff --git a/src/codegen_new/codegen_backend_x86_ops_helpers.h b/src/codegen_new/codegen_backend_x86_ops_helpers.h index 3fca4f4d2..f0da3ff64 100644 --- a/src/codegen_new/codegen_backend_x86_ops_helpers.h +++ b/src/codegen_new/codegen_backend_x86_ops_helpers.h @@ -1,84 +1,94 @@ #define JMP_LEN_BYTES 5 -static inline void codegen_addbyte(codeblock_t *block, uint8_t val) +static inline void +codegen_addbyte(UNUSED(codeblock_t *block), uint8_t val) { - if (block_pos >= BLOCK_MAX) - fatal("codegen_addbyte over! %i\n", block_pos); - block_write_data[block_pos++] = val; + if (block_pos >= BLOCK_MAX) + fatal("codegen_addbyte over! %i\n", block_pos); + block_write_data[block_pos++] = val; } -static inline void codegen_addbyte2(codeblock_t *block, uint8_t vala, uint8_t valb) +static inline void +codegen_addbyte2(UNUSED(codeblock_t *block), uint8_t vala, uint8_t valb) { - if (block_pos > (BLOCK_MAX-2)) - fatal("codegen_addbyte2 over! %i\n", block_pos); - block_write_data[block_pos++] = vala; - block_write_data[block_pos++] = valb; + if (block_pos > (BLOCK_MAX - 2)) + fatal("codegen_addbyte2 over! %i\n", block_pos); + block_write_data[block_pos++] = vala; + block_write_data[block_pos++] = valb; } -static inline void codegen_addbyte3(codeblock_t *block, uint8_t vala, uint8_t valb, uint8_t valc) +static inline void +codegen_addbyte3(UNUSED(codeblock_t *block), uint8_t vala, uint8_t valb, uint8_t valc) { - if (block_pos > (BLOCK_MAX-3)) - fatal("codegen_addbyte3 over! %i\n", block_pos); - block_write_data[block_pos++] = vala; - block_write_data[block_pos++] = valb; - block_write_data[block_pos++] = valc; + if (block_pos > (BLOCK_MAX - 3)) + fatal("codegen_addbyte3 over! %i\n", block_pos); + block_write_data[block_pos++] = vala; + block_write_data[block_pos++] = valb; + block_write_data[block_pos++] = valc; } -static inline void codegen_addbyte4(codeblock_t *block, uint8_t vala, uint8_t valb, uint8_t valc, uint8_t vald) +static inline void +codegen_addbyte4(UNUSED(codeblock_t *block), uint8_t vala, uint8_t valb, uint8_t valc, uint8_t vald) { - if (block_pos > (BLOCK_MAX-4)) - fatal("codegen_addbyte4 over! %i\n", block_pos); - block_write_data[block_pos++] = vala; - block_write_data[block_pos++] = valb; - block_write_data[block_pos++] = valc; - block_write_data[block_pos++] = vald; + if (block_pos > (BLOCK_MAX - 4)) + fatal("codegen_addbyte4 over! %i\n", block_pos); + block_write_data[block_pos++] = vala; + block_write_data[block_pos++] = valb; + block_write_data[block_pos++] = valc; + block_write_data[block_pos++] = vald; } -static inline void codegen_addword(codeblock_t *block, uint16_t val) +static inline void +codegen_addword(UNUSED(codeblock_t *block), uint16_t val) { - if (block_pos > (BLOCK_MAX-2)) - fatal("codegen_addword over! %i\n", block_pos); - *(uint16_t *)&block_write_data[block_pos] = val; - block_pos += 2; + if (block_pos > (BLOCK_MAX - 2)) + fatal("codegen_addword over! %i\n", block_pos); + *(uint16_t *) &block_write_data[block_pos] = val; + block_pos += 2; } -static inline void codegen_addlong(codeblock_t *block, uint32_t val) +static inline void +codegen_addlong(UNUSED(codeblock_t *block), uint32_t val) { - if (block_pos > (BLOCK_MAX-4)) - fatal("codegen_addlong over! %i\n", block_pos); - *(uint32_t *)&block_write_data[block_pos] = val; - block_pos += 4; + if (block_pos > (BLOCK_MAX - 4)) + fatal("codegen_addlong over! %i\n", block_pos); + *(uint32_t *) &block_write_data[block_pos] = val; + block_pos += 4; } -static inline void codegen_addquad(codeblock_t *block, uint64_t val) +static inline void +codegen_addquad(UNUSED(codeblock_t *block), uint64_t val) { - if (block_pos > (BLOCK_MAX-8)) - fatal("codegen_addquad over! %i\n", block_pos); - *(uint64_t *)&block_write_data[block_pos] = val; - block_pos += 8; + if (block_pos > (BLOCK_MAX - 8)) + fatal("codegen_addquad over! %i\n", block_pos); + *(uint64_t *) &block_write_data[block_pos] = val; + block_pos += 8; } -static void codegen_allocate_new_block(codeblock_t *block) +static void +codegen_allocate_new_block(codeblock_t *block) { - /*Current block is full. Allocate a new block*/ - struct mem_block_t *new_block = codegen_allocator_allocate(block->head_mem_block, get_block_nr(block)); - uint8_t *new_ptr = codeblock_allocator_get_ptr(new_block); + /*Current block is full. Allocate a new block*/ + struct mem_block_t *new_block = codegen_allocator_allocate(block->head_mem_block, get_block_nr(block)); + uint8_t *new_ptr = codeblock_allocator_get_ptr(new_block); - /*Add a jump instruction to the new block*/ - codegen_addbyte(block, 0xe9); /*JMP*/ - codegen_addlong(block, (uintptr_t)new_ptr - (uintptr_t)&block_write_data[block_pos + 4]); + /*Add a jump instruction to the new block*/ + codegen_addbyte(block, 0xe9); /*JMP*/ + codegen_addlong(block, (uintptr_t) new_ptr - (uintptr_t) &block_write_data[block_pos + 4]); - /*Set write address to start of new block*/ - block_pos = 0; - block_write_data = new_ptr; + /*Set write address to start of new block*/ + block_pos = 0; + block_write_data = new_ptr; } -static inline void codegen_alloc_bytes(codeblock_t *block, int size) +static inline void +codegen_alloc_bytes(codeblock_t *block, int size) { - if (block_pos > ((BLOCK_MAX - size) - JMP_LEN_BYTES)) - codegen_allocate_new_block(block); + if (block_pos > ((BLOCK_MAX - size) - JMP_LEN_BYTES)) + codegen_allocate_new_block(block); } -static inline int is_imm8(uint32_t imm_data) +static inline int +is_imm8(uint32_t imm_data) { - if (imm_data <= 0x7f || imm_data >= 0xffffff80) - return 1; - return 0; + if (imm_data <= 0x7f || imm_data >= 0xffffff80) + return 1; + return 0; } diff --git a/src/codegen_new/codegen_backend_x86_ops_sse.c b/src/codegen_new/codegen_backend_x86_ops_sse.c index 0ab461e74..084e04a87 100644 --- a/src/codegen_new/codegen_backend_x86_ops_sse.c +++ b/src/codegen_new/codegen_backend_x86_ops_sse.c @@ -1,578 +1,630 @@ #if defined i386 || defined __i386 || defined __i386__ || defined _X86_ || defined _M_IX86 -#include -#include <86box/86box.h> -#include "cpu.h" -#include <86box/mem.h> +# include +# include <86box/86box.h> +# include "cpu.h" +# include <86box/mem.h> +# include <86box/plat_unused.h> -#include "codegen.h" -#include "codegen_allocator.h" -#include "codegen_backend.h" -#include "codegen_backend_x86_defs.h" -#include "codegen_backend_x86_ops_sse.h" -#include "codegen_backend_x86_ops_helpers.h" +# include "codegen.h" +# include "codegen_allocator.h" +# include "codegen_backend.h" +# include "codegen_backend_x86_defs.h" +# include "codegen_backend_x86_ops_sse.h" +# include "codegen_backend_x86_ops_helpers.h" -void host_x86_ADDPS_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg) +void +host_x86_ADDPS_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg) { - codegen_alloc_bytes(block, 3); - codegen_addbyte3(block, 0x0f, 0x58, 0xc0 | src_reg | (dst_reg << 3)); /*ADDPS dst_reg, src_reg*/ + codegen_alloc_bytes(block, 3); + codegen_addbyte3(block, 0x0f, 0x58, 0xc0 | src_reg | (dst_reg << 3)); /*ADDPS dst_reg, src_reg*/ } -void host_x86_ADDSD_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg) +void +host_x86_ADDSD_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg) { - codegen_alloc_bytes(block, 4); - codegen_addbyte4(block, 0xf2, 0x0f, 0x58, 0xc0 | src_reg | (dst_reg << 3)); + codegen_alloc_bytes(block, 4); + codegen_addbyte4(block, 0xf2, 0x0f, 0x58, 0xc0 | src_reg | (dst_reg << 3)); } -void host_x86_CMPPS_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg, int type) +void +host_x86_CMPPS_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg, int type) { - codegen_alloc_bytes(block, 4); - codegen_addbyte4(block, 0x0f, 0xc2, 0xc0 | src_reg | (dst_reg << 3), type); /*CMPPS dst_reg, src_reg, type*/ + codegen_alloc_bytes(block, 4); + codegen_addbyte4(block, 0x0f, 0xc2, 0xc0 | src_reg | (dst_reg << 3), type); /*CMPPS dst_reg, src_reg, type*/ } -void host_x86_COMISD_XREG_XREG(codeblock_t *block, int src_reg_a, int src_reg_b) +void +host_x86_COMISD_XREG_XREG(codeblock_t *block, int src_reg_a, int src_reg_b) { - codegen_alloc_bytes(block, 4); - codegen_addbyte4(block, 0x66, 0x0f, 0x2e, 0xc0 | src_reg_b | (src_reg_a << 3)); + codegen_alloc_bytes(block, 4); + codegen_addbyte4(block, 0x66, 0x0f, 0x2e, 0xc0 | src_reg_b | (src_reg_a << 3)); } -void host_x86_CVTDQ2PS_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg) +void +host_x86_CVTDQ2PS_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg) { - codegen_alloc_bytes(block, 3); - codegen_addbyte3(block, 0x0f, 0x5b, 0xc0 | src_reg | (dst_reg << 3)); /*CVTDQ2PS dst_reg, src_reg*/ + codegen_alloc_bytes(block, 3); + codegen_addbyte3(block, 0x0f, 0x5b, 0xc0 | src_reg | (dst_reg << 3)); /*CVTDQ2PS dst_reg, src_reg*/ } -void host_x86_CVTPS2DQ_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg) +void +host_x86_CVTPS2DQ_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg) { - codegen_alloc_bytes(block, 4); - codegen_addbyte4(block, 0x66, 0x0f, 0x5b, 0xc0 | src_reg | (dst_reg << 3)); /*CVTPS2DQ dst_reg, src_reg*/ + codegen_alloc_bytes(block, 4); + codegen_addbyte4(block, 0x66, 0x0f, 0x5b, 0xc0 | src_reg | (dst_reg << 3)); /*CVTPS2DQ dst_reg, src_reg*/ } -void host_x86_CVTSD2SI_REG_XREG(codeblock_t *block, int dst_reg, int src_reg) +void +host_x86_CVTSD2SI_REG_XREG(codeblock_t *block, int dst_reg, int src_reg) { - codegen_alloc_bytes(block, 4); - codegen_addbyte4(block, 0xf2, 0x0f, 0x2d, 0xc0 | src_reg | (dst_reg << 3)); /*CVTSD2SI dst_reg, src_reg*/ + codegen_alloc_bytes(block, 4); + codegen_addbyte4(block, 0xf2, 0x0f, 0x2d, 0xc0 | src_reg | (dst_reg << 3)); /*CVTSD2SI dst_reg, src_reg*/ } -void host_x86_CVTSD2SS_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg) +void +host_x86_CVTSD2SS_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg) { - codegen_alloc_bytes(block, 4); - codegen_addbyte4(block, 0xf2, 0x0f, 0x5a, 0xc0 | src_reg | (dst_reg << 3)); /*CVTSD2SS dst_reg, src_reg*/ + codegen_alloc_bytes(block, 4); + codegen_addbyte4(block, 0xf2, 0x0f, 0x5a, 0xc0 | src_reg | (dst_reg << 3)); /*CVTSD2SS dst_reg, src_reg*/ } -void host_x86_CVTSI2SD_XREG_REG(codeblock_t *block, int dst_reg, int src_reg) +void +host_x86_CVTSI2SD_XREG_REG(codeblock_t *block, int dst_reg, int src_reg) { - codegen_alloc_bytes(block, 4); - codegen_addbyte4(block, 0xf2, 0x0f, 0x2a, 0xc0 | src_reg | (dst_reg << 3)); /*CVTSI2SD dst_reg, src_reg*/ + codegen_alloc_bytes(block, 4); + codegen_addbyte4(block, 0xf2, 0x0f, 0x2a, 0xc0 | src_reg | (dst_reg << 3)); /*CVTSI2SD dst_reg, src_reg*/ } -void host_x86_CVTSI2SS_XREG_REG(codeblock_t *block, int dst_reg, int src_reg) +void +host_x86_CVTSI2SS_XREG_REG(codeblock_t *block, int dst_reg, int src_reg) { - codegen_alloc_bytes(block, 4); - codegen_addbyte4(block, 0xf3, 0x0f, 0x2a, 0xc0 | src_reg | (dst_reg << 3)); /*CVTSI2SD dst_reg, src_reg*/ + codegen_alloc_bytes(block, 4); + codegen_addbyte4(block, 0xf3, 0x0f, 0x2a, 0xc0 | src_reg | (dst_reg << 3)); /*CVTSI2SD dst_reg, src_reg*/ } -void host_x86_CVTSS2SD_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg) +void +host_x86_CVTSS2SD_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg) { - codegen_alloc_bytes(block, 4); - codegen_addbyte4(block, 0xf3, 0x0f, 0x5a, 0xc0 | src_reg | (dst_reg << 3)); + codegen_alloc_bytes(block, 4); + codegen_addbyte4(block, 0xf3, 0x0f, 0x5a, 0xc0 | src_reg | (dst_reg << 3)); } -void host_x86_CVTSS2SD_XREG_BASE_INDEX(codeblock_t *block, int dst_reg, int base_reg, int idx_reg) +void +host_x86_CVTSS2SD_XREG_BASE_INDEX(codeblock_t *block, int dst_reg, int base_reg, int idx_reg) { + codegen_alloc_bytes(block, 5); + codegen_addbyte4(block, 0xf3, 0x0f, 0x5a, 0x04 | (dst_reg << 3)); /*CVTSS2SD XMMx, [base_reg + idx_reg]*/ + codegen_addbyte(block, base_reg | (idx_reg << 3)); +} + +void +host_x86_DIVSD_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg) +{ + codegen_alloc_bytes(block, 4); + codegen_addbyte4(block, 0xf2, 0x0f, 0x5e, 0xc0 | src_reg | (dst_reg << 3)); /*DIVSD dst_reg, src_reg*/ +} +void +host_x86_DIVSS_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg) +{ + codegen_alloc_bytes(block, 4); + codegen_addbyte4(block, 0xf3, 0x0f, 0x5e, 0xc0 | src_reg | (dst_reg << 3)); /*DIVSS dst_reg, src_reg*/ +} + +void +host_x86_LDMXCSR(codeblock_t *block, void *p) +{ + int offset = (uintptr_t) p - (((uintptr_t) &cpu_state) + 128); + + if (offset >= -128 && offset < 127) { + codegen_alloc_bytes(block, 4); + codegen_addbyte4(block, 0x0f, 0xae, 0x50 | REG_EBP, offset); /*LDMXCSR offset[EBP]*/ + } else { + codegen_alloc_bytes(block, 7); + codegen_addbyte3(block, 0x0f, 0xae, 0x15); /*LDMXCSR [p]*/ + codegen_addlong(block, (uint32_t) p); + } +} + +void +host_x86_MAXSD_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg) +{ + codegen_alloc_bytes(block, 4); + codegen_addbyte4(block, 0xf2, 0x0f, 0x5f, 0xc0 | src_reg | (dst_reg << 3)); /*MAXSD dst_reg, src_reg*/ +} + +void +host_x86_MOVD_BASE_INDEX_XREG(codeblock_t *block, int base_reg, int idx_reg, int src_reg) +{ + codegen_alloc_bytes(block, 5); + codegen_addbyte4(block, 0x66, 0x0f, 0x7e, 0x04 | (src_reg << 3)); /*MOVD XMMx, [base_reg + idx_reg]*/ + codegen_addbyte(block, base_reg | (idx_reg << 3)); +} +void +host_x86_MOVD_REG_XREG(codeblock_t *block, int dst_reg, int src_reg) +{ + codegen_alloc_bytes(block, 4); + codegen_addbyte4(block, 0x66, 0x0f, 0x7e, 0xc0 | dst_reg | (src_reg << 3)); +} +void +host_x86_MOVD_XREG_BASE_INDEX(codeblock_t *block, int dst_reg, int base_reg, int idx_reg) +{ + codegen_alloc_bytes(block, 5); + codegen_addbyte4(block, 0x66, 0x0f, 0x6e, 0x04 | (dst_reg << 3)); /*MOVD XMMx, [base_reg + idx_reg]*/ + codegen_addbyte(block, base_reg | (idx_reg << 3)); +} +void +host_x86_MOVD_XREG_REG(codeblock_t *block, int dst_reg, int src_reg) +{ + codegen_alloc_bytes(block, 4); + codegen_addbyte4(block, 0x66, 0x0f, 0x6e, 0xc0 | src_reg | (dst_reg << 3)); +} + +void +host_x86_MOVQ_ABS_XREG(codeblock_t *block, void *p, int src_reg) +{ + int offset = (uintptr_t) p - (((uintptr_t) &cpu_state) + 128); + + if (offset >= -128 && offset < 127) { codegen_alloc_bytes(block, 5); - codegen_addbyte4(block, 0xf3, 0x0f, 0x5a, 0x04 | (dst_reg << 3)); /*CVTSS2SD XMMx, [base_reg + idx_reg]*/ - codegen_addbyte(block, base_reg | (idx_reg << 3)); + codegen_addbyte4(block, 0x66, 0x0f, 0xd6, 0x45 | (src_reg << 3)); /*MOVQ offset[EBP], src_reg*/ + codegen_addbyte(block, offset); + } else { + codegen_alloc_bytes(block, 8); + codegen_addbyte4(block, 0x66, 0x0f, 0xd6, 0x05 | (src_reg << 3)); /*MOVQ [p], src_reg*/ + codegen_addlong(block, (uint32_t) p); + } } - -void host_x86_DIVSD_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg) -{ - codegen_alloc_bytes(block, 4); - codegen_addbyte4(block, 0xf2, 0x0f, 0x5e, 0xc0 | src_reg | (dst_reg << 3)); /*DIVSD dst_reg, src_reg*/ -} -void host_x86_DIVSS_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg) -{ - codegen_alloc_bytes(block, 4); - codegen_addbyte4(block, 0xf3, 0x0f, 0x5e, 0xc0 | src_reg | (dst_reg << 3)); /*DIVSS dst_reg, src_reg*/ -} - -void host_x86_LDMXCSR(codeblock_t *block, void *p) -{ - int offset = (uintptr_t)p - (((uintptr_t)&cpu_state) + 128); - - if (offset >= -128 && offset < 127) - { - codegen_alloc_bytes(block, 4); - codegen_addbyte4(block, 0x0f, 0xae, 0x50 | REG_EBP, offset); /*LDMXCSR offset[EBP]*/ - } - else - { - codegen_alloc_bytes(block, 7); - codegen_addbyte3(block, 0x0f, 0xae, 0x15); /*LDMXCSR [p]*/ - codegen_addlong(block, (uint32_t)p); - } -} - -void host_x86_MAXSD_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg) -{ - codegen_alloc_bytes(block, 4); - codegen_addbyte4(block, 0xf2, 0x0f, 0x5f, 0xc0 | src_reg | (dst_reg << 3)); /*MAXSD dst_reg, src_reg*/ -} - -void host_x86_MOVD_BASE_INDEX_XREG(codeblock_t *block, int base_reg, int idx_reg, int src_reg) -{ - codegen_alloc_bytes(block, 5); - codegen_addbyte4(block, 0x66, 0x0f, 0x7e, 0x04 | (src_reg << 3)); /*MOVD XMMx, [base_reg + idx_reg]*/ - codegen_addbyte(block, base_reg | (idx_reg << 3)); -} -void host_x86_MOVD_REG_XREG(codeblock_t *block, int dst_reg, int src_reg) -{ - codegen_alloc_bytes(block, 4); - codegen_addbyte4(block, 0x66, 0x0f, 0x7e, 0xc0 | dst_reg | (src_reg << 3)); -} -void host_x86_MOVD_XREG_BASE_INDEX(codeblock_t *block, int dst_reg, int base_reg, int idx_reg) -{ - codegen_alloc_bytes(block, 5); - codegen_addbyte4(block, 0x66, 0x0f, 0x6e, 0x04 | (dst_reg << 3)); /*MOVD XMMx, [base_reg + idx_reg]*/ - codegen_addbyte(block, base_reg | (idx_reg << 3)); -} -void host_x86_MOVD_XREG_REG(codeblock_t *block, int dst_reg, int src_reg) -{ - codegen_alloc_bytes(block, 4); - codegen_addbyte4(block, 0x66, 0x0f, 0x6e, 0xc0 | src_reg | (dst_reg << 3)); -} - -void host_x86_MOVQ_ABS_XREG(codeblock_t *block, void *p, int src_reg) -{ - int offset = (uintptr_t)p - (((uintptr_t)&cpu_state) + 128); - - if (offset >= -128 && offset < 127) - { - codegen_alloc_bytes(block, 5); - codegen_addbyte4(block, 0x66, 0x0f, 0xd6, 0x45 | (src_reg << 3)); /*MOVQ offset[EBP], src_reg*/ - codegen_addbyte(block, offset); - } - else - { - codegen_alloc_bytes(block, 8); - codegen_addbyte4(block, 0x66, 0x0f, 0xd6, 0x05 | (src_reg << 3)); /*MOVQ [p], src_reg*/ - codegen_addlong(block, (uint32_t)p); - } -} -void host_x86_MOVQ_ABS_REG_REG_SHIFT_XREG(codeblock_t *block, uint32_t addr, int src_reg_a, int src_reg_b, int shift, int src_reg) -{ - if (addr < 0x80 || addr >= 0xffffff80) - { - codegen_alloc_bytes(block, 6); - codegen_addbyte3(block, 0x66, 0x0f, 0xd6); /*MOVQ addr[src_reg_a + src_reg_b << shift], XMMx*/ - codegen_addbyte3(block, 0x44 | (src_reg << 3), src_reg_a | (src_reg_b << 3) | (shift << 6), addr & 0xff); - } - else - { - codegen_alloc_bytes(block, 9); - codegen_addbyte3(block, 0x66, 0x0f, 0xd6); /*MOVQ addr[src_reg_a + src_reg_b << shift], XMMx*/ - codegen_addbyte2(block, 0x84 | (src_reg << 3), src_reg_a | (src_reg_b << 3) | (shift << 6)); - codegen_addlong(block, addr); - } -} -void host_x86_MOVQ_BASE_INDEX_XREG(codeblock_t *block, int base_reg, int idx_reg, int src_reg) -{ - codegen_alloc_bytes(block, 5); - codegen_addbyte4(block, 0x66, 0x0f, 0xd6, 0x04 | (src_reg << 3)); /*MOVQ XMMx, [base_reg + idx_reg]*/ - codegen_addbyte(block, base_reg | (idx_reg << 3)); -} -void host_x86_MOVQ_BASE_OFFSET_XREG(codeblock_t *block, int base_reg, int offset, int src_reg) -{ - if (offset >= -128 && offset < 127) - { - if (base_reg == REG_ESP) - { - codegen_alloc_bytes(block, 6); - codegen_addbyte4(block, 0x66, 0x0f, 0xd6, 0x44 | (src_reg << 3)); /*MOVQ [ESP + offset], XMMx*/ - codegen_addbyte2(block, 0x24, offset); - } - else - { - codegen_alloc_bytes(block, 5); - codegen_addbyte4(block, 0x66, 0x0f, 0xd6, 0x40 | base_reg | (src_reg << 3)); /*MOVQ [base_reg + offset], XMMx*/ - codegen_addbyte(block, offset); - } - } - else - fatal("MOVQ_BASE_OFFSET_XREG - offset %i\n", offset); -} -void host_x86_MOVQ_STACK_OFFSET_XREG(codeblock_t *block, int offset, int src_reg) -{ - if (!offset) - { - codegen_alloc_bytes(block, 5); - codegen_addbyte4(block, 0x66, 0x0f, 0xd6, 0x04 | (src_reg << 3)); /*MOVQ [ESP], src_reg*/ - codegen_addbyte(block, 0x24); - } - else if (offset >= -0x80 && offset < 0x80) - { - codegen_alloc_bytes(block, 6); - codegen_addbyte4(block, 0x66, 0x0f, 0xd6, 0x44 | (src_reg << 3)); /*MOVQ offset[ESP], src_reg*/ - codegen_addbyte2(block, 0x24, offset & 0xff); - } - else - { - codegen_alloc_bytes(block, 9); - codegen_addbyte4(block, 0x66, 0x0f, 0xd6, 0x84 | (src_reg << 3)); /*MOVQ offset[ESP], src_reg*/ - codegen_addbyte(block, 0x24); - codegen_addlong(block, offset); - } - -} - -void host_x86_MOVQ_XREG_ABS(codeblock_t *block, int dst_reg, void *p) -{ - int offset = (uintptr_t)p - (((uintptr_t)&cpu_state) + 128); - - if (offset >= -128 && offset < 127) - { - codegen_alloc_bytes(block, 5); - codegen_addbyte4(block, 0xf3, 0x0f, 0x7e, 0x45 | (dst_reg << 3)); /*MOVQ offset[EBP], src_reg*/ - codegen_addbyte(block, offset); - } - else - { - codegen_alloc_bytes(block, 8); - codegen_addbyte4(block, 0xf3, 0x0f, 0x7e, 0x05 | (dst_reg << 3)); /*MOVQ [p], src_reg*/ - codegen_addlong(block, (uint32_t)p); - } -} -void host_x86_MOVQ_XREG_ABS_REG_REG_SHIFT(codeblock_t *block, int dst_reg, uint32_t addr, int src_reg_a, int src_reg_b, int shift) -{ - if (addr < 0x80 || addr >= 0xffffff80) - { - codegen_alloc_bytes(block, 6); - codegen_addbyte3(block, 0xf3, 0x0f, 0x7e); /*MOVQ XMMx, addr[src_reg_a + src_reg_b << shift]*/ - codegen_addbyte3(block, 0x44 | (dst_reg << 3), src_reg_a | (src_reg_b << 3) | (shift << 6), addr & 0xff); - } - else - { - codegen_alloc_bytes(block, 9); - codegen_addbyte3(block, 0xf3, 0x0f, 0x7e); /*MOVQ XMMx, addr[src_reg_a + src_reg_b << shift]*/ - codegen_addbyte2(block, 0x84 | (dst_reg << 3), src_reg_a | (src_reg_b << 3) | (shift << 6)); - codegen_addlong(block, addr); - } -} -void host_x86_MOVQ_XREG_BASE_INDEX(codeblock_t *block, int dst_reg, int base_reg, int idx_reg) -{ - codegen_alloc_bytes(block, 5); - codegen_addbyte4(block, 0xf3, 0x0f, 0x7e, 0x04 | (dst_reg << 3)); /*MOVQ XMMx, [base_reg + idx_reg]*/ - codegen_addbyte(block, base_reg | (idx_reg << 3)); -} -void host_x86_MOVQ_XREG_BASE_OFFSET(codeblock_t *block, int dst_reg, int base_reg, int offset) -{ - if (offset >= -128 && offset < 127) - { - if (base_reg == REG_ESP) - { - codegen_alloc_bytes(block, 6); - codegen_addbyte4(block, 0xf3, 0x0f, 0x7e, 0x44 | (dst_reg << 3)); /*MOVQ XMMx, [ESP + offset]*/ - codegen_addbyte2(block, 0x24, offset); - } - else - { - codegen_alloc_bytes(block, 5); - codegen_addbyte4(block, 0xf3, 0x0f, 0x7e, 0x40 | base_reg | (dst_reg << 3)); /*MOVQ XMMx, [base_reg + offset]*/ - codegen_addbyte(block, offset); - } - } - else - fatal("MOVQ_REG_BASE_OFFSET - offset %i\n", offset); -} -void host_x86_MOVQ_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg) -{ - codegen_alloc_bytes(block, 4); - codegen_addbyte4(block, 0xf3, 0x0f, 0x7e, 0xc0 | src_reg | (dst_reg << 3)); /*MOVQ dst_reg, src_reg*/ -} - -void host_x86_MAXPS_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg) -{ - codegen_alloc_bytes(block, 3); - codegen_addbyte3(block, 0x0f, 0x5f, 0xc0 | src_reg | (dst_reg << 3)); /*MAXPS dst_reg, src_reg*/ -} -void host_x86_MINPS_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg) -{ - codegen_alloc_bytes(block, 3); - codegen_addbyte3(block, 0x0f, 0x5d, 0xc0 | src_reg | (dst_reg << 3)); /*MINPS dst_reg, src_reg*/ -} - -void host_x86_MULPS_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg) -{ - codegen_alloc_bytes(block, 3); - codegen_addbyte3(block, 0x0f, 0x59, 0xc0 | src_reg | (dst_reg << 3)); /*MULPS dst_reg, src_reg*/ -} -void host_x86_MULSD_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg) -{ - codegen_alloc_bytes(block, 4); - codegen_addbyte4(block, 0xf2, 0x0f, 0x59, 0xc0 | src_reg | (dst_reg << 3)); -} - -void host_x86_PACKSSWB_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg) +void +host_x86_MOVQ_ABS_REG_REG_SHIFT_XREG(codeblock_t *block, uint32_t addr, int src_reg_a, int src_reg_b, int shift, int src_reg) { + if (addr < 0x80 || addr >= 0xffffff80) { + codegen_alloc_bytes(block, 6); + codegen_addbyte3(block, 0x66, 0x0f, 0xd6); /*MOVQ addr[src_reg_a + src_reg_b << shift], XMMx*/ + codegen_addbyte3(block, 0x44 | (src_reg << 3), src_reg_a | (src_reg_b << 3) | (shift << 6), addr & 0xff); + } else { codegen_alloc_bytes(block, 9); - codegen_addbyte4(block, 0x66, 0x0f, 0x63, 0xc0 | src_reg | (dst_reg << 3)); /*PACKSSWB dst_reg, src_reg*/ - codegen_addbyte4(block, 0x66, 0x0f, 0x70, 0xc0 | dst_reg | (dst_reg << 3)); /*PSHUFD dst_reg, dst_reg, 0x88 (move bits 64-95 to 32-63)*/ - codegen_addbyte(block, 0x88); + codegen_addbyte3(block, 0x66, 0x0f, 0xd6); /*MOVQ addr[src_reg_a + src_reg_b << shift], XMMx*/ + codegen_addbyte2(block, 0x84 | (src_reg << 3), src_reg_a | (src_reg_b << 3) | (shift << 6)); + codegen_addlong(block, addr); + } } -void host_x86_PACKSSDW_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg) +void +host_x86_MOVQ_BASE_INDEX_XREG(codeblock_t *block, int base_reg, int idx_reg, int src_reg) { + codegen_alloc_bytes(block, 5); + codegen_addbyte4(block, 0x66, 0x0f, 0xd6, 0x04 | (src_reg << 3)); /*MOVQ XMMx, [base_reg + idx_reg]*/ + codegen_addbyte(block, base_reg | (idx_reg << 3)); +} +void +host_x86_MOVQ_BASE_OFFSET_XREG(codeblock_t *block, int base_reg, int offset, int src_reg) +{ + if (offset >= -128 && offset < 127) { + if (base_reg == REG_ESP) { + codegen_alloc_bytes(block, 6); + codegen_addbyte4(block, 0x66, 0x0f, 0xd6, 0x44 | (src_reg << 3)); /*MOVQ [ESP + offset], XMMx*/ + codegen_addbyte2(block, 0x24, offset); + } else { + codegen_alloc_bytes(block, 5); + codegen_addbyte4(block, 0x66, 0x0f, 0xd6, 0x40 | base_reg | (src_reg << 3)); /*MOVQ [base_reg + offset], XMMx*/ + codegen_addbyte(block, offset); + } + } else + fatal("MOVQ_BASE_OFFSET_XREG - offset %i\n", offset); +} +void +host_x86_MOVQ_STACK_OFFSET_XREG(codeblock_t *block, int offset, int src_reg) +{ + if (!offset) { + codegen_alloc_bytes(block, 5); + codegen_addbyte4(block, 0x66, 0x0f, 0xd6, 0x04 | (src_reg << 3)); /*MOVQ [ESP], src_reg*/ + codegen_addbyte(block, 0x24); + } else if (offset >= -0x80 && offset < 0x80) { + codegen_alloc_bytes(block, 6); + codegen_addbyte4(block, 0x66, 0x0f, 0xd6, 0x44 | (src_reg << 3)); /*MOVQ offset[ESP], src_reg*/ + codegen_addbyte2(block, 0x24, offset & 0xff); + } else { codegen_alloc_bytes(block, 9); - codegen_addbyte4(block, 0x66, 0x0f, 0x6b, 0xc0 | src_reg | (dst_reg << 3)); /*PACKSSDW dst_reg, src_reg*/ - codegen_addbyte4(block, 0x66, 0x0f, 0x70, 0xc0 | dst_reg | (dst_reg << 3)); /*PSHUFD dst_reg, dst_reg, 0x88 (move bits 64-95 to 32-63)*/ - codegen_addbyte(block, 0x88); + codegen_addbyte4(block, 0x66, 0x0f, 0xd6, 0x84 | (src_reg << 3)); /*MOVQ offset[ESP], src_reg*/ + codegen_addbyte(block, 0x24); + codegen_addlong(block, offset); + } } -void host_x86_PACKUSWB_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg) + +void +host_x86_MOVQ_XREG_ABS(codeblock_t *block, int dst_reg, void *p) { + int offset = (uintptr_t) p - (((uintptr_t) &cpu_state) + 128); + + if (offset >= -128 && offset < 127) { + codegen_alloc_bytes(block, 5); + codegen_addbyte4(block, 0xf3, 0x0f, 0x7e, 0x45 | (dst_reg << 3)); /*MOVQ offset[EBP], src_reg*/ + codegen_addbyte(block, offset); + } else { + codegen_alloc_bytes(block, 8); + codegen_addbyte4(block, 0xf3, 0x0f, 0x7e, 0x05 | (dst_reg << 3)); /*MOVQ [p], src_reg*/ + codegen_addlong(block, (uint32_t) p); + } +} +void +host_x86_MOVQ_XREG_ABS_REG_REG_SHIFT(codeblock_t *block, int dst_reg, uint32_t addr, int src_reg_a, int src_reg_b, int shift) +{ + if (addr < 0x80 || addr >= 0xffffff80) { + codegen_alloc_bytes(block, 6); + codegen_addbyte3(block, 0xf3, 0x0f, 0x7e); /*MOVQ XMMx, addr[src_reg_a + src_reg_b << shift]*/ + codegen_addbyte3(block, 0x44 | (dst_reg << 3), src_reg_a | (src_reg_b << 3) | (shift << 6), addr & 0xff); + } else { codegen_alloc_bytes(block, 9); - codegen_addbyte4(block, 0x66, 0x0f, 0x67, 0xc0 | src_reg | (dst_reg << 3)); /*PACKUSWB dst_reg, src_reg*/ - codegen_addbyte4(block, 0x66, 0x0f, 0x70, 0xc0 | dst_reg | (dst_reg << 3)); /*PSHUFD dst_reg, dst_reg, 0x88 (move bits 64-95 to 32-63)*/ - codegen_addbyte(block, 0x88); + codegen_addbyte3(block, 0xf3, 0x0f, 0x7e); /*MOVQ XMMx, addr[src_reg_a + src_reg_b << shift]*/ + codegen_addbyte2(block, 0x84 | (dst_reg << 3), src_reg_a | (src_reg_b << 3) | (shift << 6)); + codegen_addlong(block, addr); + } +} +void +host_x86_MOVQ_XREG_BASE_INDEX(codeblock_t *block, int dst_reg, int base_reg, int idx_reg) +{ + codegen_alloc_bytes(block, 5); + codegen_addbyte4(block, 0xf3, 0x0f, 0x7e, 0x04 | (dst_reg << 3)); /*MOVQ XMMx, [base_reg + idx_reg]*/ + codegen_addbyte(block, base_reg | (idx_reg << 3)); +} +void +host_x86_MOVQ_XREG_BASE_OFFSET(codeblock_t *block, int dst_reg, int base_reg, int offset) +{ + if (offset >= -128 && offset < 127) { + if (base_reg == REG_ESP) { + codegen_alloc_bytes(block, 6); + codegen_addbyte4(block, 0xf3, 0x0f, 0x7e, 0x44 | (dst_reg << 3)); /*MOVQ XMMx, [ESP + offset]*/ + codegen_addbyte2(block, 0x24, offset); + } else { + codegen_alloc_bytes(block, 5); + codegen_addbyte4(block, 0xf3, 0x0f, 0x7e, 0x40 | base_reg | (dst_reg << 3)); /*MOVQ XMMx, [base_reg + offset]*/ + codegen_addbyte(block, offset); + } + } else + fatal("MOVQ_REG_BASE_OFFSET - offset %i\n", offset); +} +void +host_x86_MOVQ_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg) +{ + codegen_alloc_bytes(block, 4); + codegen_addbyte4(block, 0xf3, 0x0f, 0x7e, 0xc0 | src_reg | (dst_reg << 3)); /*MOVQ dst_reg, src_reg*/ } -void host_x86_PADDB_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg) +void +host_x86_MAXPS_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg) { - codegen_alloc_bytes(block, 4); - codegen_addbyte4(block, 0x66, 0x0f, 0xfc, 0xc0 | src_reg | (dst_reg << 3)); /*PADDB dst_reg, src_reg*/ + codegen_alloc_bytes(block, 3); + codegen_addbyte3(block, 0x0f, 0x5f, 0xc0 | src_reg | (dst_reg << 3)); /*MAXPS dst_reg, src_reg*/ } -void host_x86_PADDW_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg) +void +host_x86_MINPS_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg) { - codegen_alloc_bytes(block, 4); - codegen_addbyte4(block, 0x66, 0x0f, 0xfd, 0xc0 | src_reg | (dst_reg << 3)); /*PADDW dst_reg, src_reg*/ -} -void host_x86_PADDD_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg) -{ - codegen_alloc_bytes(block, 4); - codegen_addbyte4(block, 0x66, 0x0f, 0xfe, 0xc0 | src_reg | (dst_reg << 3)); /*PADDD dst_reg, src_reg*/ -} -void host_x86_PADDSB_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg) -{ - codegen_alloc_bytes(block, 4); - codegen_addbyte4(block, 0x66, 0x0f, 0xec, 0xc0 | src_reg | (dst_reg << 3)); /*PADDSB dst_reg, src_reg*/ -} -void host_x86_PADDSW_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg) -{ - codegen_alloc_bytes(block, 4); - codegen_addbyte4(block, 0x66, 0x0f, 0xed, 0xc0 | src_reg | (dst_reg << 3)); /*PADDSW dst_reg, src_reg*/ -} -void host_x86_PADDUSB_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg) -{ - codegen_alloc_bytes(block, 4); - codegen_addbyte4(block, 0x66, 0x0f, 0xdc, 0xc0 | src_reg | (dst_reg << 3)); /*PADDUSB dst_reg, src_reg*/ -} -void host_x86_PADDUSW_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg) -{ - codegen_alloc_bytes(block, 4); - codegen_addbyte4(block, 0x66, 0x0f, 0xdd, 0xc0 | src_reg | (dst_reg << 3)); /*PADDUSW dst_reg, src_reg*/ + codegen_alloc_bytes(block, 3); + codegen_addbyte3(block, 0x0f, 0x5d, 0xc0 | src_reg | (dst_reg << 3)); /*MINPS dst_reg, src_reg*/ } -void host_x86_PAND_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg) +void +host_x86_MULPS_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg) { - codegen_alloc_bytes(block, 4); - codegen_addbyte4(block, 0x66, 0x0f, 0xdb, 0xc0 | src_reg | (dst_reg << 3)); /*PAND dst_reg, src_reg*/ + codegen_alloc_bytes(block, 3); + codegen_addbyte3(block, 0x0f, 0x59, 0xc0 | src_reg | (dst_reg << 3)); /*MULPS dst_reg, src_reg*/ } -void host_x86_PANDN_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg) +void +host_x86_MULSD_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg) { - codegen_alloc_bytes(block, 4); - codegen_addbyte4(block, 0x66, 0x0f, 0xdf, 0xc0 | src_reg | (dst_reg << 3)); /*PANDN dst_reg, src_reg*/ -} -void host_x86_POR_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg) -{ - codegen_alloc_bytes(block, 4); - codegen_addbyte4(block, 0x66, 0x0f, 0xeb, 0xc0 | src_reg | (dst_reg << 3)); /*POR dst_reg, src_reg*/ -} -void host_x86_PXOR_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg) -{ - codegen_alloc_bytes(block, 4); - codegen_addbyte4(block, 0x66, 0x0f, 0xef, 0xc0 | src_reg | (dst_reg << 3)); /*PXOR dst_reg, src_reg*/ + codegen_alloc_bytes(block, 4); + codegen_addbyte4(block, 0xf2, 0x0f, 0x59, 0xc0 | src_reg | (dst_reg << 3)); } -void host_x86_PCMPEQB_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg) +void +host_x86_PACKSSWB_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg) { - codegen_alloc_bytes(block, 4); - codegen_addbyte4(block, 0x66, 0x0f, 0x74, 0xc0 | src_reg | (dst_reg << 3)); /*PCMPEQB dst_reg, src_reg*/ + codegen_alloc_bytes(block, 9); + codegen_addbyte4(block, 0x66, 0x0f, 0x63, 0xc0 | src_reg | (dst_reg << 3)); /*PACKSSWB dst_reg, src_reg*/ + codegen_addbyte4(block, 0x66, 0x0f, 0x70, 0xc0 | dst_reg | (dst_reg << 3)); /*PSHUFD dst_reg, dst_reg, 0x88 (move bits 64-95 to 32-63)*/ + codegen_addbyte(block, 0x88); } -void host_x86_PCMPEQW_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg) +void +host_x86_PACKSSDW_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg) { - codegen_alloc_bytes(block, 4); - codegen_addbyte4(block, 0x66, 0x0f, 0x75, 0xc0 | src_reg | (dst_reg << 3)); /*PCMPEQW dst_reg, src_reg*/ + codegen_alloc_bytes(block, 9); + codegen_addbyte4(block, 0x66, 0x0f, 0x6b, 0xc0 | src_reg | (dst_reg << 3)); /*PACKSSDW dst_reg, src_reg*/ + codegen_addbyte4(block, 0x66, 0x0f, 0x70, 0xc0 | dst_reg | (dst_reg << 3)); /*PSHUFD dst_reg, dst_reg, 0x88 (move bits 64-95 to 32-63)*/ + codegen_addbyte(block, 0x88); } -void host_x86_PCMPEQD_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg) +void +host_x86_PACKUSWB_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg) { - codegen_alloc_bytes(block, 4); - codegen_addbyte4(block, 0x66, 0x0f, 0x76, 0xc0 | src_reg | (dst_reg << 3)); /*PCMPEQD dst_reg, src_reg*/ -} -void host_x86_PCMPGTB_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg) -{ - codegen_alloc_bytes(block, 4); - codegen_addbyte4(block, 0x66, 0x0f, 0x64, 0xc0 | src_reg | (dst_reg << 3)); /*PCMPGTB dst_reg, src_reg*/ -} -void host_x86_PCMPGTW_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg) -{ - codegen_alloc_bytes(block, 4); - codegen_addbyte4(block, 0x66, 0x0f, 0x65, 0xc0 | src_reg | (dst_reg << 3)); /*PCMPGTW dst_reg, src_reg*/ -} -void host_x86_PCMPGTD_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg) -{ - codegen_alloc_bytes(block, 4); - codegen_addbyte4(block, 0x66, 0x0f, 0x66, 0xc0 | src_reg | (dst_reg << 3)); /*PCMPGTD dst_reg, src_reg*/ + codegen_alloc_bytes(block, 9); + codegen_addbyte4(block, 0x66, 0x0f, 0x67, 0xc0 | src_reg | (dst_reg << 3)); /*PACKUSWB dst_reg, src_reg*/ + codegen_addbyte4(block, 0x66, 0x0f, 0x70, 0xc0 | dst_reg | (dst_reg << 3)); /*PSHUFD dst_reg, dst_reg, 0x88 (move bits 64-95 to 32-63)*/ + codegen_addbyte(block, 0x88); } -void host_x86_PMADDWD_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg) +void +host_x86_PADDB_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg) { - codegen_alloc_bytes(block, 4); - codegen_addbyte4(block, 0x66, 0x0f, 0xf5, 0xc0 | src_reg | (dst_reg << 3)); /*PMULLW dst_reg, src_reg*/ + codegen_alloc_bytes(block, 4); + codegen_addbyte4(block, 0x66, 0x0f, 0xfc, 0xc0 | src_reg | (dst_reg << 3)); /*PADDB dst_reg, src_reg*/ } -void host_x86_PMULHW_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg) +void +host_x86_PADDW_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg) { - codegen_alloc_bytes(block, 4); - codegen_addbyte4(block, 0x66, 0x0f, 0xe5, 0xc0 | src_reg | (dst_reg << 3)); /*PMULLW dst_reg, src_reg*/ + codegen_alloc_bytes(block, 4); + codegen_addbyte4(block, 0x66, 0x0f, 0xfd, 0xc0 | src_reg | (dst_reg << 3)); /*PADDW dst_reg, src_reg*/ } -void host_x86_PMULLW_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg) +void +host_x86_PADDD_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg) { - codegen_alloc_bytes(block, 4); - codegen_addbyte4(block, 0x66, 0x0f, 0xd5, 0xc0 | src_reg | (dst_reg << 3)); /*PMULLW dst_reg, src_reg*/ + codegen_alloc_bytes(block, 4); + codegen_addbyte4(block, 0x66, 0x0f, 0xfe, 0xc0 | src_reg | (dst_reg << 3)); /*PADDD dst_reg, src_reg*/ +} +void +host_x86_PADDSB_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg) +{ + codegen_alloc_bytes(block, 4); + codegen_addbyte4(block, 0x66, 0x0f, 0xec, 0xc0 | src_reg | (dst_reg << 3)); /*PADDSB dst_reg, src_reg*/ +} +void +host_x86_PADDSW_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg) +{ + codegen_alloc_bytes(block, 4); + codegen_addbyte4(block, 0x66, 0x0f, 0xed, 0xc0 | src_reg | (dst_reg << 3)); /*PADDSW dst_reg, src_reg*/ +} +void +host_x86_PADDUSB_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg) +{ + codegen_alloc_bytes(block, 4); + codegen_addbyte4(block, 0x66, 0x0f, 0xdc, 0xc0 | src_reg | (dst_reg << 3)); /*PADDUSB dst_reg, src_reg*/ +} +void +host_x86_PADDUSW_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg) +{ + codegen_alloc_bytes(block, 4); + codegen_addbyte4(block, 0x66, 0x0f, 0xdd, 0xc0 | src_reg | (dst_reg << 3)); /*PADDUSW dst_reg, src_reg*/ } -void host_x86_PSHUFD_XREG_XREG_IMM(codeblock_t *block, int dst_reg, int src_reg, uint8_t shuffle) +void +host_x86_PAND_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg) { - codegen_alloc_bytes(block, 5); - codegen_addbyte4(block, 0x66, 0x0f, 0x70, 0xc0 | src_reg | (dst_reg << 3)); /*PSHUFD dst_reg, dst_reg, 0xee (move top 64-bits to low 64-bits)*/ - codegen_addbyte(block, shuffle); + codegen_alloc_bytes(block, 4); + codegen_addbyte4(block, 0x66, 0x0f, 0xdb, 0xc0 | src_reg | (dst_reg << 3)); /*PAND dst_reg, src_reg*/ +} +void +host_x86_PANDN_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg) +{ + codegen_alloc_bytes(block, 4); + codegen_addbyte4(block, 0x66, 0x0f, 0xdf, 0xc0 | src_reg | (dst_reg << 3)); /*PANDN dst_reg, src_reg*/ +} +void +host_x86_POR_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg) +{ + codegen_alloc_bytes(block, 4); + codegen_addbyte4(block, 0x66, 0x0f, 0xeb, 0xc0 | src_reg | (dst_reg << 3)); /*POR dst_reg, src_reg*/ +} +void +host_x86_PXOR_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg) +{ + codegen_alloc_bytes(block, 4); + codegen_addbyte4(block, 0x66, 0x0f, 0xef, 0xc0 | src_reg | (dst_reg << 3)); /*PXOR dst_reg, src_reg*/ } -void host_x86_PSLLW_XREG_IMM(codeblock_t *block, int dst_reg, int shift) +void +host_x86_PCMPEQB_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg) { - codegen_alloc_bytes(block, 5); - codegen_addbyte4(block, 0x66, 0x0f, 0x71, 0xc0 | 0x30 | dst_reg); /*PSLLW dst_reg, imm*/ - codegen_addbyte(block, shift); + codegen_alloc_bytes(block, 4); + codegen_addbyte4(block, 0x66, 0x0f, 0x74, 0xc0 | src_reg | (dst_reg << 3)); /*PCMPEQB dst_reg, src_reg*/ } -void host_x86_PSLLD_XREG_IMM(codeblock_t *block, int dst_reg, int shift) +void +host_x86_PCMPEQW_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg) { - codegen_alloc_bytes(block, 5); - codegen_addbyte4(block, 0x66, 0x0f, 0x72, 0xc0 | 0x30 | dst_reg); /*PSLLD dst_reg, imm*/ - codegen_addbyte(block, shift); + codegen_alloc_bytes(block, 4); + codegen_addbyte4(block, 0x66, 0x0f, 0x75, 0xc0 | src_reg | (dst_reg << 3)); /*PCMPEQW dst_reg, src_reg*/ } -void host_x86_PSLLQ_XREG_IMM(codeblock_t *block, int dst_reg, int shift) +void +host_x86_PCMPEQD_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg) { - codegen_alloc_bytes(block, 5); - codegen_addbyte4(block, 0x66, 0x0f, 0x73, 0xc0 | 0x30 | dst_reg); /*PSLLD dst_reg, imm*/ - codegen_addbyte(block, shift); + codegen_alloc_bytes(block, 4); + codegen_addbyte4(block, 0x66, 0x0f, 0x76, 0xc0 | src_reg | (dst_reg << 3)); /*PCMPEQD dst_reg, src_reg*/ } -void host_x86_PSRAW_XREG_IMM(codeblock_t *block, int dst_reg, int shift) +void +host_x86_PCMPGTB_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg) { - codegen_alloc_bytes(block, 5); - codegen_addbyte4(block, 0x66, 0x0f, 0x71, 0xc0 | 0x20 | dst_reg); /*PSRAW dst_reg, imm*/ - codegen_addbyte(block, shift); + codegen_alloc_bytes(block, 4); + codegen_addbyte4(block, 0x66, 0x0f, 0x64, 0xc0 | src_reg | (dst_reg << 3)); /*PCMPGTB dst_reg, src_reg*/ } -void host_x86_PSRAD_XREG_IMM(codeblock_t *block, int dst_reg, int shift) +void +host_x86_PCMPGTW_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg) { - codegen_alloc_bytes(block, 5); - codegen_addbyte4(block, 0x66, 0x0f, 0x72, 0xc0 | 0x20 | dst_reg); /*PSRAD dst_reg, imm*/ - codegen_addbyte(block, shift); + codegen_alloc_bytes(block, 4); + codegen_addbyte4(block, 0x66, 0x0f, 0x65, 0xc0 | src_reg | (dst_reg << 3)); /*PCMPGTW dst_reg, src_reg*/ } -void host_x86_PSRAQ_XREG_IMM(codeblock_t *block, int dst_reg, int shift) +void +host_x86_PCMPGTD_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg) { - codegen_alloc_bytes(block, 5); - codegen_addbyte4(block, 0x66, 0x0f, 0x73, 0xc0 | 0x20 | dst_reg); /*PSRAD dst_reg, imm*/ - codegen_addbyte(block, shift); -} -void host_x86_PSRLW_XREG_IMM(codeblock_t *block, int dst_reg, int shift) -{ - codegen_alloc_bytes(block, 5); - codegen_addbyte4(block, 0x66, 0x0f, 0x71, 0xc0 | 0x10 | dst_reg); /*PSRLW dst_reg, imm*/ - codegen_addbyte(block, shift); -} -void host_x86_PSRLD_XREG_IMM(codeblock_t *block, int dst_reg, int shift) -{ - codegen_alloc_bytes(block, 5); - codegen_addbyte4(block, 0x66, 0x0f, 0x72, 0xc0 | 0x10 | dst_reg); /*PSRLD dst_reg, imm*/ - codegen_addbyte(block, shift); -} -void host_x86_PSRLQ_XREG_IMM(codeblock_t *block, int dst_reg, int shift) -{ - codegen_alloc_bytes(block, 5); - codegen_addbyte4(block, 0x66, 0x0f, 0x73, 0xc0 | 0x10 | dst_reg); /*PSRLD dst_reg, imm*/ - codegen_addbyte(block, shift); + codegen_alloc_bytes(block, 4); + codegen_addbyte4(block, 0x66, 0x0f, 0x66, 0xc0 | src_reg | (dst_reg << 3)); /*PCMPGTD dst_reg, src_reg*/ } -void host_x86_PSUBB_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg) +void +host_x86_PMADDWD_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg) { - codegen_alloc_bytes(block, 4); - codegen_addbyte4(block, 0x66, 0x0f, 0xf8, 0xc0 | src_reg | (dst_reg << 3)); /*PADDB dst_reg, src_reg*/ + codegen_alloc_bytes(block, 4); + codegen_addbyte4(block, 0x66, 0x0f, 0xf5, 0xc0 | src_reg | (dst_reg << 3)); /*PMULLW dst_reg, src_reg*/ } -void host_x86_PSUBW_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg) +void +host_x86_PMULHW_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg) { - codegen_alloc_bytes(block, 4); - codegen_addbyte4(block, 0x66, 0x0f, 0xf9, 0xc0 | src_reg | (dst_reg << 3)); /*PADDW dst_reg, src_reg*/ + codegen_alloc_bytes(block, 4); + codegen_addbyte4(block, 0x66, 0x0f, 0xe5, 0xc0 | src_reg | (dst_reg << 3)); /*PMULLW dst_reg, src_reg*/ } -void host_x86_PSUBD_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg) +void +host_x86_PMULLW_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg) { - codegen_alloc_bytes(block, 4); - codegen_addbyte4(block, 0x66, 0x0f, 0xfa, 0xc0 | src_reg | (dst_reg << 3)); /*PADDD dst_reg, src_reg*/ -} -void host_x86_PSUBSB_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg) -{ - codegen_alloc_bytes(block, 4); - codegen_addbyte4(block, 0x66, 0x0f, 0xe8, 0xc0 | src_reg | (dst_reg << 3)); /*PSUBSB dst_reg, src_reg*/ -} -void host_x86_PSUBSW_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg) -{ - codegen_alloc_bytes(block, 4); - codegen_addbyte4(block, 0x66, 0x0f, 0xe9, 0xc0 | src_reg | (dst_reg << 3)); /*PSUBSW dst_reg, src_reg*/ -} -void host_x86_PSUBUSB_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg) -{ - codegen_alloc_bytes(block, 4); - codegen_addbyte4(block, 0x66, 0x0f, 0xd8, 0xc0 | src_reg | (dst_reg << 3)); /*PSUBUSB dst_reg, src_reg*/ -} -void host_x86_PSUBUSW_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg) -{ - codegen_alloc_bytes(block, 4); - codegen_addbyte4(block, 0x66, 0x0f, 0xd9, 0xc0 | src_reg | (dst_reg << 3)); /*PSUBUSW dst_reg, src_reg*/ + codegen_alloc_bytes(block, 4); + codegen_addbyte4(block, 0x66, 0x0f, 0xd5, 0xc0 | src_reg | (dst_reg << 3)); /*PMULLW dst_reg, src_reg*/ } -void host_x86_PUNPCKLBW_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg) +void +host_x86_PSHUFD_XREG_XREG_IMM(codeblock_t *block, int dst_reg, int src_reg, uint8_t shuffle) { - codegen_alloc_bytes(block, 4); - codegen_addbyte4(block, 0x66, 0x0f, 0x60, 0xc0 | src_reg | (dst_reg << 3)); /*PUNPCKLBW dst_reg, src_reg*/ -} -void host_x86_PUNPCKLWD_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg) -{ - codegen_alloc_bytes(block, 4); - codegen_addbyte4(block, 0x66, 0x0f, 0x61, 0xc0 | src_reg | (dst_reg << 3)); /*PUNPCKLWD dst_reg, src_reg*/ -} -void host_x86_PUNPCKLDQ_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg) -{ - codegen_alloc_bytes(block, 4); - codegen_addbyte4(block, 0x66, 0x0f, 0x62, 0xc0 | src_reg | (dst_reg << 3)); /*PUNPCKLDQ dst_reg, src_reg*/ + codegen_alloc_bytes(block, 5); + codegen_addbyte4(block, 0x66, 0x0f, 0x70, 0xc0 | src_reg | (dst_reg << 3)); /*PSHUFD dst_reg, dst_reg, 0xee (move top 64-bits to low 64-bits)*/ + codegen_addbyte(block, shuffle); } -void host_x86_SQRTSD_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg) +void +host_x86_PSLLW_XREG_IMM(codeblock_t *block, int dst_reg, int shift) { - codegen_alloc_bytes(block, 4); - codegen_addbyte4(block, 0xf2, 0x0f, 0x51, 0xc0 | src_reg | (dst_reg << 3)); /*SQRTSD dst_reg, src_reg*/ + codegen_alloc_bytes(block, 5); + codegen_addbyte4(block, 0x66, 0x0f, 0x71, 0xc0 | 0x30 | dst_reg); /*PSLLW dst_reg, imm*/ + codegen_addbyte(block, shift); } -void host_x86_SQRTSS_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg) +void +host_x86_PSLLD_XREG_IMM(codeblock_t *block, int dst_reg, int shift) { - codegen_alloc_bytes(block, 4); - codegen_addbyte4(block, 0xf3, 0x0f, 0x51, 0xc0 | src_reg | (dst_reg << 3)); /*SQRTSS dst_reg, src_reg*/ + codegen_alloc_bytes(block, 5); + codegen_addbyte4(block, 0x66, 0x0f, 0x72, 0xc0 | 0x30 | dst_reg); /*PSLLD dst_reg, imm*/ + codegen_addbyte(block, shift); +} +void +host_x86_PSLLQ_XREG_IMM(codeblock_t *block, int dst_reg, int shift) +{ + codegen_alloc_bytes(block, 5); + codegen_addbyte4(block, 0x66, 0x0f, 0x73, 0xc0 | 0x30 | dst_reg); /*PSLLD dst_reg, imm*/ + codegen_addbyte(block, shift); +} +void +host_x86_PSRAW_XREG_IMM(codeblock_t *block, int dst_reg, int shift) +{ + codegen_alloc_bytes(block, 5); + codegen_addbyte4(block, 0x66, 0x0f, 0x71, 0xc0 | 0x20 | dst_reg); /*PSRAW dst_reg, imm*/ + codegen_addbyte(block, shift); +} +void +host_x86_PSRAD_XREG_IMM(codeblock_t *block, int dst_reg, int shift) +{ + codegen_alloc_bytes(block, 5); + codegen_addbyte4(block, 0x66, 0x0f, 0x72, 0xc0 | 0x20 | dst_reg); /*PSRAD dst_reg, imm*/ + codegen_addbyte(block, shift); +} +void +host_x86_PSRAQ_XREG_IMM(codeblock_t *block, int dst_reg, int shift) +{ + codegen_alloc_bytes(block, 5); + codegen_addbyte4(block, 0x66, 0x0f, 0x73, 0xc0 | 0x20 | dst_reg); /*PSRAD dst_reg, imm*/ + codegen_addbyte(block, shift); +} +void +host_x86_PSRLW_XREG_IMM(codeblock_t *block, int dst_reg, int shift) +{ + codegen_alloc_bytes(block, 5); + codegen_addbyte4(block, 0x66, 0x0f, 0x71, 0xc0 | 0x10 | dst_reg); /*PSRLW dst_reg, imm*/ + codegen_addbyte(block, shift); +} +void +host_x86_PSRLD_XREG_IMM(codeblock_t *block, int dst_reg, int shift) +{ + codegen_alloc_bytes(block, 5); + codegen_addbyte4(block, 0x66, 0x0f, 0x72, 0xc0 | 0x10 | dst_reg); /*PSRLD dst_reg, imm*/ + codegen_addbyte(block, shift); +} +void +host_x86_PSRLQ_XREG_IMM(codeblock_t *block, int dst_reg, int shift) +{ + codegen_alloc_bytes(block, 5); + codegen_addbyte4(block, 0x66, 0x0f, 0x73, 0xc0 | 0x10 | dst_reg); /*PSRLD dst_reg, imm*/ + codegen_addbyte(block, shift); } -void host_x86_SUBPS_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg) +void +host_x86_PSUBB_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg) { - codegen_alloc_bytes(block, 3); - codegen_addbyte3(block, 0x0f, 0x5c, 0xc0 | src_reg | (dst_reg << 3)); /*SUBPS dst_reg, src_reg*/ + codegen_alloc_bytes(block, 4); + codegen_addbyte4(block, 0x66, 0x0f, 0xf8, 0xc0 | src_reg | (dst_reg << 3)); /*PADDB dst_reg, src_reg*/ } -void host_x86_SUBSD_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg) +void +host_x86_PSUBW_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg) { - codegen_alloc_bytes(block, 4); - codegen_addbyte4(block, 0xf2, 0x0f, 0x5c, 0xc0 | src_reg | (dst_reg << 3)); + codegen_alloc_bytes(block, 4); + codegen_addbyte4(block, 0x66, 0x0f, 0xf9, 0xc0 | src_reg | (dst_reg << 3)); /*PADDW dst_reg, src_reg*/ +} +void +host_x86_PSUBD_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg) +{ + codegen_alloc_bytes(block, 4); + codegen_addbyte4(block, 0x66, 0x0f, 0xfa, 0xc0 | src_reg | (dst_reg << 3)); /*PADDD dst_reg, src_reg*/ +} +void +host_x86_PSUBSB_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg) +{ + codegen_alloc_bytes(block, 4); + codegen_addbyte4(block, 0x66, 0x0f, 0xe8, 0xc0 | src_reg | (dst_reg << 3)); /*PSUBSB dst_reg, src_reg*/ +} +void +host_x86_PSUBSW_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg) +{ + codegen_alloc_bytes(block, 4); + codegen_addbyte4(block, 0x66, 0x0f, 0xe9, 0xc0 | src_reg | (dst_reg << 3)); /*PSUBSW dst_reg, src_reg*/ +} +void +host_x86_PSUBUSB_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg) +{ + codegen_alloc_bytes(block, 4); + codegen_addbyte4(block, 0x66, 0x0f, 0xd8, 0xc0 | src_reg | (dst_reg << 3)); /*PSUBUSB dst_reg, src_reg*/ +} +void +host_x86_PSUBUSW_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg) +{ + codegen_alloc_bytes(block, 4); + codegen_addbyte4(block, 0x66, 0x0f, 0xd9, 0xc0 | src_reg | (dst_reg << 3)); /*PSUBUSW dst_reg, src_reg*/ } -void host_x86_UNPCKLPS_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg) +void +host_x86_PUNPCKLBW_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg) { - codegen_alloc_bytes(block, 3); - codegen_addbyte3(block, 0x0f, 0x14, 0xc0 | src_reg | (dst_reg << 3)); + codegen_alloc_bytes(block, 4); + codegen_addbyte4(block, 0x66, 0x0f, 0x60, 0xc0 | src_reg | (dst_reg << 3)); /*PUNPCKLBW dst_reg, src_reg*/ +} +void +host_x86_PUNPCKLWD_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg) +{ + codegen_alloc_bytes(block, 4); + codegen_addbyte4(block, 0x66, 0x0f, 0x61, 0xc0 | src_reg | (dst_reg << 3)); /*PUNPCKLWD dst_reg, src_reg*/ +} +void +host_x86_PUNPCKLDQ_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg) +{ + codegen_alloc_bytes(block, 4); + codegen_addbyte4(block, 0x66, 0x0f, 0x62, 0xc0 | src_reg | (dst_reg << 3)); /*PUNPCKLDQ dst_reg, src_reg*/ +} + +void +host_x86_SQRTSD_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg) +{ + codegen_alloc_bytes(block, 4); + codegen_addbyte4(block, 0xf2, 0x0f, 0x51, 0xc0 | src_reg | (dst_reg << 3)); /*SQRTSD dst_reg, src_reg*/ +} +void +host_x86_SQRTSS_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg) +{ + codegen_alloc_bytes(block, 4); + codegen_addbyte4(block, 0xf3, 0x0f, 0x51, 0xc0 | src_reg | (dst_reg << 3)); /*SQRTSS dst_reg, src_reg*/ +} + +void +host_x86_SUBPS_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg) +{ + codegen_alloc_bytes(block, 3); + codegen_addbyte3(block, 0x0f, 0x5c, 0xc0 | src_reg | (dst_reg << 3)); /*SUBPS dst_reg, src_reg*/ +} +void +host_x86_SUBSD_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg) +{ + codegen_alloc_bytes(block, 4); + codegen_addbyte4(block, 0xf2, 0x0f, 0x5c, 0xc0 | src_reg | (dst_reg << 3)); +} + +void +host_x86_UNPCKLPS_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg) +{ + codegen_alloc_bytes(block, 3); + codegen_addbyte3(block, 0x0f, 0x14, 0xc0 | src_reg | (dst_reg << 3)); } #endif diff --git a/src/codegen_new/codegen_backend_x86_uops.c b/src/codegen_new/codegen_backend_x86_uops.c index 9d423f772..5ef2d97b8 100644 --- a/src/codegen_new/codegen_backend_x86_uops.c +++ b/src/codegen_new/codegen_backend_x86_uops.c @@ -1,3164 +1,3527 @@ #if defined i386 || defined __i386 || defined __i386__ || defined _X86_ || defined _M_IX86 -#include -#include <86box/86box.h> -#include "cpu.h" -#include <86box/mem.h> +# include +# include <86box/86box.h> +# include "cpu.h" +# include <86box/mem.h> +# include <86box/plat_unused.h> -#include "x86.h" -#include "x86_ops.h" -#include "386_common.h" -#include "codegen.h" -#include "codegen_allocator.h" -#include "codegen_backend.h" -#include "codegen_backend_x86_defs.h" -#include "codegen_backend_x86_ops.h" -#include "codegen_backend_x86_ops_fpu.h" -#include "codegen_backend_x86_ops_sse.h" -#include "codegen_ir_defs.h" +# include "x86.h" +# include "x86_ops.h" +# include "x86seg_common.h" +# include "x86seg.h" +# include "386_common.h" +# include "codegen.h" +# include "codegen_allocator.h" +# include "codegen_backend.h" +# include "codegen_backend_x86_defs.h" +# include "codegen_backend_x86_ops.h" +# include "codegen_backend_x86_ops_fpu.h" +# include "codegen_backend_x86_ops_sse.h" +# include "codegen_ir_defs.h" -#define HOST_REG_IS_L(reg) (IREG_GET_SIZE(reg) == IREG_SIZE_L) -#define HOST_REG_IS_W(reg) (IREG_GET_SIZE(reg) == IREG_SIZE_W) -#define HOST_REG_IS_B(reg) (IREG_GET_SIZE(reg) == IREG_SIZE_B && IREG_GET_REG(reg) < 4) -#define HOST_REG_IS_BH(reg) (IREG_GET_SIZE(reg) == IREG_SIZE_BH && IREG_GET_REG(reg) < 4) +# define HOST_REG_IS_L(reg) (IREG_GET_SIZE(reg) == IREG_SIZE_L) +# define HOST_REG_IS_W(reg) (IREG_GET_SIZE(reg) == IREG_SIZE_W) +# define HOST_REG_IS_B(reg) (IREG_GET_SIZE(reg) == IREG_SIZE_B && IREG_GET_REG(reg) < 4) +# define HOST_REG_IS_BH(reg) (IREG_GET_SIZE(reg) == IREG_SIZE_BH && IREG_GET_REG(reg) < 4) -#define HOST_REG_GET(reg) ((IREG_GET_SIZE(reg) == IREG_SIZE_BH) ? (IREG_GET_REG((reg) & 3) | 4) : (IREG_GET_REG(reg) & 7)) +# define HOST_REG_GET(reg) ((IREG_GET_SIZE(reg) == IREG_SIZE_BH) ? (IREG_GET_REG((reg) &3) | 4) : (IREG_GET_REG(reg) & 7)) -#define REG_IS_L(size) (size == IREG_SIZE_L) -#define REG_IS_W(size) (size == IREG_SIZE_W) -#define REG_IS_B(size) (size == IREG_SIZE_B || size == IREG_SIZE_BH) -#define REG_IS_BH(size) (size == IREG_SIZE_BH) -#define REG_IS_D(size) (size == IREG_SIZE_D) -#define REG_IS_Q(size) (size == IREG_SIZE_Q) +# define REG_IS_L(size) (size == IREG_SIZE_L) +# define REG_IS_W(size) (size == IREG_SIZE_W) +# define REG_IS_B(size) (size == IREG_SIZE_B || size == IREG_SIZE_BH) +# define REG_IS_BH(size) (size == IREG_SIZE_BH) +# define REG_IS_D(size) (size == IREG_SIZE_D) +# define REG_IS_Q(size) (size == IREG_SIZE_Q) -static int codegen_ADD(codeblock_t *block, uop_t *uop) +static int +codegen_ADD(codeblock_t *block, uop_t *uop) { - int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg_a = HOST_REG_GET(uop->src_reg_a_real), src_reg_b = HOST_REG_GET(uop->src_reg_b_real); - int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size_a = IREG_GET_SIZE(uop->src_reg_a_real), src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); + int dest_reg = HOST_REG_GET(uop->dest_reg_a_real); + int src_reg_a = HOST_REG_GET(uop->src_reg_a_real); + int src_reg_b = HOST_REG_GET(uop->src_reg_b_real); + int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real); + int src_size_a = IREG_GET_SIZE(uop->src_reg_a_real); + int src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); - if (REG_IS_L(dest_size) && REG_IS_L(src_size_a) && REG_IS_L(src_size_b)) - { - if (uop->dest_reg_a_real != uop->src_reg_a_real) - host_x86_LEA_REG_REG(block, dest_reg, src_reg_a, src_reg_b); - else - host_x86_ADD32_REG_REG(block, dest_reg, src_reg_b); - } - else if (REG_IS_W(dest_size) && REG_IS_W(src_size_a) && REG_IS_W(src_size_b)) - { - if (uop->dest_reg_a_real != uop->src_reg_a_real) - host_x86_MOV16_REG_REG(block, dest_reg, src_reg_a); - host_x86_ADD16_REG_REG(block, dest_reg, src_reg_b); - } - else if (REG_IS_B(dest_size) && REG_IS_B(src_size_a) && REG_IS_B(src_size_b)) - { - if (uop->dest_reg_a_real != uop->src_reg_a_real) - host_x86_MOV8_REG_REG(block, dest_reg, src_reg_a); - host_x86_ADD8_REG_REG(block, dest_reg, src_reg_b); - } -#ifdef RECOMPILER_DEBUG + if (REG_IS_L(dest_size) && REG_IS_L(src_size_a) && REG_IS_L(src_size_b)) { + if (uop->dest_reg_a_real != uop->src_reg_a_real) + host_x86_LEA_REG_REG(block, dest_reg, src_reg_a, src_reg_b); else - fatal("ADD %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real); -#endif - return 0; + host_x86_ADD32_REG_REG(block, dest_reg, src_reg_b); + } else if (REG_IS_W(dest_size) && REG_IS_W(src_size_a) && REG_IS_W(src_size_b)) { + if (uop->dest_reg_a_real != uop->src_reg_a_real) + host_x86_MOV16_REG_REG(block, dest_reg, src_reg_a); + host_x86_ADD16_REG_REG(block, dest_reg, src_reg_b); + } else if (REG_IS_B(dest_size) && REG_IS_B(src_size_a) && REG_IS_B(src_size_b)) { + if (uop->dest_reg_a_real != uop->src_reg_a_real) + host_x86_MOV8_REG_REG(block, dest_reg, src_reg_a); + host_x86_ADD8_REG_REG(block, dest_reg, src_reg_b); + } +# ifdef RECOMPILER_DEBUG + else + fatal("ADD %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real); +# endif + return 0; } -static int codegen_ADD_IMM(codeblock_t *block, uop_t *uop) +static int +codegen_ADD_IMM(codeblock_t *block, uop_t *uop) { - int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg = HOST_REG_GET(uop->src_reg_a_real); - int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size = IREG_GET_SIZE(uop->src_reg_a_real); - - if (REG_IS_L(dest_size) && REG_IS_L(src_size)) - { - if (uop->dest_reg_a_real != uop->src_reg_a_real) - host_x86_LEA_REG_IMM(block, dest_reg, src_reg, uop->imm_data); - else - host_x86_ADD32_REG_IMM(block, dest_reg, uop->imm_data); - } - else if (REG_IS_W(dest_size) && REG_IS_W(src_size)) - { - if (uop->dest_reg_a_real != uop->src_reg_a_real) - host_x86_MOV16_REG_REG(block, dest_reg, src_reg); - host_x86_ADD16_REG_IMM(block, dest_reg, uop->imm_data); - } - else if (REG_IS_B(dest_size) && REG_IS_B(src_size)) - { - if (uop->dest_reg_a_real != uop->src_reg_a_real) - host_x86_MOV8_REG_REG(block, dest_reg, src_reg); - host_x86_ADD8_REG_IMM(block, dest_reg, uop->imm_data); - } -#ifdef RECOMPILER_DEBUG + int dest_reg = HOST_REG_GET(uop->dest_reg_a_real); + int src_reg = HOST_REG_GET(uop->src_reg_a_real); + int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real); + int src_size = IREG_GET_SIZE(uop->src_reg_a_real); + + if (REG_IS_L(dest_size) && REG_IS_L(src_size)) { + if (uop->dest_reg_a_real != uop->src_reg_a_real) + host_x86_LEA_REG_IMM(block, dest_reg, src_reg, uop->imm_data); else - fatal("ADD_IMM %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real); -#endif - return 0; + host_x86_ADD32_REG_IMM(block, dest_reg, uop->imm_data); + } else if (REG_IS_W(dest_size) && REG_IS_W(src_size)) { + if (uop->dest_reg_a_real != uop->src_reg_a_real) + host_x86_MOV16_REG_REG(block, dest_reg, src_reg); + host_x86_ADD16_REG_IMM(block, dest_reg, uop->imm_data); + } else if (REG_IS_B(dest_size) && REG_IS_B(src_size)) { + if (uop->dest_reg_a_real != uop->src_reg_a_real) + host_x86_MOV8_REG_REG(block, dest_reg, src_reg); + host_x86_ADD8_REG_IMM(block, dest_reg, uop->imm_data); + } +# ifdef RECOMPILER_DEBUG + else + fatal("ADD_IMM %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real); +# endif + return 0; } -static int codegen_ADD_LSHIFT(codeblock_t *block, uop_t *uop) +static int +codegen_ADD_LSHIFT(codeblock_t *block, uop_t *uop) { - if (!uop->imm_data) - { - if (uop->dest_reg_a_real == uop->src_reg_a_real) - host_x86_ADD32_REG_REG(block, uop->dest_reg_a_real, uop->src_reg_b_real); - else - host_x86_LEA_REG_REG(block, uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real); - } - else if (uop->imm_data < 4) - host_x86_LEA_REG_REG_SHIFT(block, uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real, uop->imm_data); -#ifdef RECOMPILER_DEBUG + if (!uop->imm_data) { + if (uop->dest_reg_a_real == uop->src_reg_a_real) + host_x86_ADD32_REG_REG(block, uop->dest_reg_a_real, uop->src_reg_b_real); else - fatal("codegen_ADD_LSHIFT - shift out of range %i\n", uop->imm_data); -#endif - return 0; + host_x86_LEA_REG_REG(block, uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real); + } else if (uop->imm_data < 4) + host_x86_LEA_REG_REG_SHIFT(block, uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real, uop->imm_data); +# ifdef RECOMPILER_DEBUG + else + fatal("codegen_ADD_LSHIFT - shift out of range %i\n", uop->imm_data); +# endif + return 0; } -static int codegen_AND(codeblock_t *block, uop_t *uop) +static int +codegen_AND(codeblock_t *block, uop_t *uop) { - int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg_a = HOST_REG_GET(uop->src_reg_a_real), src_reg_b = HOST_REG_GET(uop->src_reg_b_real); - int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size_a = IREG_GET_SIZE(uop->src_reg_a_real), src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); + int dest_reg = HOST_REG_GET(uop->dest_reg_a_real); + int src_reg_a = HOST_REG_GET(uop->src_reg_a_real); + int src_reg_b = HOST_REG_GET(uop->src_reg_b_real); + int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real); + int src_size_a = IREG_GET_SIZE(uop->src_reg_a_real); + int src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); - if (REG_IS_Q(dest_size) && REG_IS_Q(src_size_a) && REG_IS_Q(src_size_b) && uop->dest_reg_a_real == uop->src_reg_a_real) - { - host_x86_PAND_XREG_XREG(block, dest_reg, src_reg_b); - } - else if (REG_IS_L(dest_size) && REG_IS_L(src_size_a) && REG_IS_L(src_size_b)) - { - if (uop->dest_reg_a_real != uop->src_reg_a_real) - host_x86_MOV32_REG_REG(block, dest_reg, src_reg_a); - host_x86_AND32_REG_REG(block, dest_reg, src_reg_b); - } - else if (REG_IS_W(dest_size) && REG_IS_W(src_size_a) && REG_IS_W(src_size_b)) - { - if (uop->dest_reg_a_real != uop->src_reg_a_real) - host_x86_MOV16_REG_REG(block, dest_reg, src_reg_a); - host_x86_AND16_REG_REG(block, dest_reg, src_reg_b); - } - else if (REG_IS_B(dest_size) && REG_IS_B(src_size_a) && REG_IS_B(src_size_b)) - { - if (uop->dest_reg_a_real != uop->src_reg_a_real) - host_x86_MOV8_REG_REG(block, dest_reg, src_reg_a); - host_x86_AND8_REG_REG(block, dest_reg, src_reg_b); - } -#ifdef RECOMPILER_DEBUG - else - fatal("AND %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real); -#endif - return 0; + if (REG_IS_Q(dest_size) && REG_IS_Q(src_size_a) && REG_IS_Q(src_size_b) && uop->dest_reg_a_real == uop->src_reg_a_real) { + host_x86_PAND_XREG_XREG(block, dest_reg, src_reg_b); + } else if (REG_IS_L(dest_size) && REG_IS_L(src_size_a) && REG_IS_L(src_size_b)) { + if (uop->dest_reg_a_real != uop->src_reg_a_real) + host_x86_MOV32_REG_REG(block, dest_reg, src_reg_a); + host_x86_AND32_REG_REG(block, dest_reg, src_reg_b); + } else if (REG_IS_W(dest_size) && REG_IS_W(src_size_a) && REG_IS_W(src_size_b)) { + if (uop->dest_reg_a_real != uop->src_reg_a_real) + host_x86_MOV16_REG_REG(block, dest_reg, src_reg_a); + host_x86_AND16_REG_REG(block, dest_reg, src_reg_b); + } else if (REG_IS_B(dest_size) && REG_IS_B(src_size_a) && REG_IS_B(src_size_b)) { + if (uop->dest_reg_a_real != uop->src_reg_a_real) + host_x86_MOV8_REG_REG(block, dest_reg, src_reg_a); + host_x86_AND8_REG_REG(block, dest_reg, src_reg_b); + } +# ifdef RECOMPILER_DEBUG + else + fatal("AND %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real); +# endif + return 0; } -static int codegen_AND_IMM(codeblock_t *block, uop_t *uop) +static int +codegen_AND_IMM(codeblock_t *block, uop_t *uop) { - int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg = HOST_REG_GET(uop->src_reg_a_real); - int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size = IREG_GET_SIZE(uop->src_reg_a_real); + int dest_reg = HOST_REG_GET(uop->dest_reg_a_real); + int src_reg = HOST_REG_GET(uop->src_reg_a_real); + int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real); + int src_size = IREG_GET_SIZE(uop->src_reg_a_real); - if (REG_IS_L(dest_size) && REG_IS_L(src_size)) - { - if (uop->dest_reg_a_real != uop->src_reg_a_real) - host_x86_MOV32_REG_REG(block, dest_reg, src_reg); - host_x86_AND32_REG_IMM(block, dest_reg, uop->imm_data); - } - else if (REG_IS_W(dest_size) && REG_IS_W(src_size)) - { - if (uop->dest_reg_a_real != uop->src_reg_a_real) - host_x86_MOV16_REG_REG(block, dest_reg, src_reg); - host_x86_AND16_REG_IMM(block, dest_reg, uop->imm_data); - } - else if (REG_IS_B(dest_size) && REG_IS_B(src_size)) - { - if (uop->dest_reg_a_real != uop->src_reg_a_real) - host_x86_MOV8_REG_REG(block, dest_reg, src_reg); - host_x86_AND8_REG_IMM(block, dest_reg, uop->imm_data); - } -#ifdef RECOMPILER_DEBUG - else - fatal("AND_IMM %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real); -#endif - return 0; + if (REG_IS_L(dest_size) && REG_IS_L(src_size)) { + if (uop->dest_reg_a_real != uop->src_reg_a_real) + host_x86_MOV32_REG_REG(block, dest_reg, src_reg); + host_x86_AND32_REG_IMM(block, dest_reg, uop->imm_data); + } else if (REG_IS_W(dest_size) && REG_IS_W(src_size)) { + if (uop->dest_reg_a_real != uop->src_reg_a_real) + host_x86_MOV16_REG_REG(block, dest_reg, src_reg); + host_x86_AND16_REG_IMM(block, dest_reg, uop->imm_data); + } else if (REG_IS_B(dest_size) && REG_IS_B(src_size)) { + if (uop->dest_reg_a_real != uop->src_reg_a_real) + host_x86_MOV8_REG_REG(block, dest_reg, src_reg); + host_x86_AND8_REG_IMM(block, dest_reg, uop->imm_data); + } +# ifdef RECOMPILER_DEBUG + else + fatal("AND_IMM %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real); +# endif + return 0; } -static int codegen_ANDN(codeblock_t *block, uop_t *uop) +static int +codegen_ANDN(codeblock_t *block, uop_t *uop) { - int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), /*src_reg_a = HOST_REG_GET(uop->src_reg_a_real), */src_reg_b = HOST_REG_GET(uop->src_reg_b_real); - int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size_a = IREG_GET_SIZE(uop->src_reg_a_real), src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); + int dest_reg = HOST_REG_GET(uop->dest_reg_a_real); +# if 0 + int src_reg_a = HOST_REG_GET(uop->src_reg_a_real); +# endif + int src_reg_b = HOST_REG_GET(uop->src_reg_b_real); + int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real); + int src_size_a = IREG_GET_SIZE(uop->src_reg_a_real); + int src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); - if (REG_IS_Q(dest_size) && REG_IS_Q(src_size_a) && REG_IS_Q(src_size_b) && uop->dest_reg_a_real == uop->src_reg_a_real) - { - host_x86_PANDN_XREG_XREG(block, dest_reg, src_reg_b); - } -#ifdef RECOMPILER_DEBUG - else - fatal("ANDN %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real); -#endif - return 0; + if (REG_IS_Q(dest_size) && REG_IS_Q(src_size_a) && REG_IS_Q(src_size_b) && uop->dest_reg_a_real == uop->src_reg_a_real) { + host_x86_PANDN_XREG_XREG(block, dest_reg, src_reg_b); + } +# ifdef RECOMPILER_DEBUG + else + fatal("ANDN %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real); +# endif + return 0; } -static int codegen_CALL_FUNC(codeblock_t *block, uop_t *uop) +static int +codegen_CALL_FUNC(codeblock_t *block, uop_t *uop) { - host_x86_CALL(block, uop->p); + host_x86_CALL(block, uop->p); - return 0; + return 0; } -static int codegen_CALL_FUNC_RESULT(codeblock_t *block, uop_t *uop) +static int +codegen_CALL_FUNC_RESULT(codeblock_t *block, uop_t *uop) { - int dest_reg = HOST_REG_GET(uop->dest_reg_a_real); -#ifdef RECOMPILER_DEBUG - int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real); + int dest_reg = HOST_REG_GET(uop->dest_reg_a_real); +# ifdef RECOMPILER_DEBUG + int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real); - if (!REG_IS_L(dest_size)) - fatal("CALL_FUNC_RESULT %02x\n", uop->dest_reg_a_real); -#endif - host_x86_CALL(block, uop->p); - host_x86_MOV32_REG_REG(block, dest_reg, REG_EAX); + if (!REG_IS_L(dest_size)) + fatal("CALL_FUNC_RESULT %02x\n", uop->dest_reg_a_real); +# endif + host_x86_CALL(block, uop->p); + host_x86_MOV32_REG_REG(block, dest_reg, REG_EAX); - return 0; + return 0; } -static int codegen_CALL_INSTRUCTION_FUNC(codeblock_t *block, uop_t *uop) +static int +codegen_CALL_INSTRUCTION_FUNC(codeblock_t *block, uop_t *uop) { - host_x86_CALL(block, uop->p); - host_x86_TEST32_REG(block, REG_EAX, REG_EAX); - host_x86_JNZ(block, codegen_exit_rout); -// host_x86_CALL(block, codegen_debug); + host_x86_CALL(block, uop->p); + host_x86_TEST32_REG(block, REG_EAX, REG_EAX); + host_x86_JNZ(block, codegen_exit_rout); +# if 0 + host_x86_CALL(block, codegen_debug); +# endif - return 0; + return 0; } -static int codegen_CMP_IMM_JZ(codeblock_t *block, uop_t *uop) +static int +codegen_CMP_IMM_JZ(codeblock_t *block, uop_t *uop) { - int src_reg = HOST_REG_GET(uop->src_reg_a_real); - int src_size = IREG_GET_SIZE(uop->src_reg_a_real); + int src_reg = HOST_REG_GET(uop->src_reg_a_real); + int src_size = IREG_GET_SIZE(uop->src_reg_a_real); - if (REG_IS_L(src_size)) - { - host_x86_CMP32_REG_IMM(block, src_reg, uop->imm_data); - } -#ifdef RECOMPILER_DEBUG - else - fatal("CMP_IMM_JZ %02x\n", uop->src_reg_a_real); -#endif - host_x86_JZ(block, uop->p); + if (REG_IS_L(src_size)) { + host_x86_CMP32_REG_IMM(block, src_reg, uop->imm_data); + } +# ifdef RECOMPILER_DEBUG + else + fatal("CMP_IMM_JZ %02x\n", uop->src_reg_a_real); +# endif + host_x86_JZ(block, uop->p); - return 0; + return 0; } -static int codegen_CMP_IMM_JNZ_DEST(codeblock_t *block, uop_t *uop) +static int +codegen_CMP_IMM_JNZ_DEST(codeblock_t *block, uop_t *uop) { - int src_reg = HOST_REG_GET(uop->src_reg_a_real); - int src_size = IREG_GET_SIZE(uop->src_reg_a_real); + int src_reg = HOST_REG_GET(uop->src_reg_a_real); + int src_size = IREG_GET_SIZE(uop->src_reg_a_real); - if (REG_IS_L(src_size)) - { - host_x86_CMP32_REG_IMM(block, src_reg, uop->imm_data); - } - else if (REG_IS_W(src_size)) - { - host_x86_CMP16_REG_IMM(block, src_reg, uop->imm_data); - } -#ifdef RECOMPILER_DEBUG - else - fatal("CMP_IMM_JNZ_DEST %02x\n", uop->src_reg_a_real); -#endif - uop->p = host_x86_JNZ_long(block); + if (REG_IS_L(src_size)) { + host_x86_CMP32_REG_IMM(block, src_reg, uop->imm_data); + } else if (REG_IS_W(src_size)) { + host_x86_CMP16_REG_IMM(block, src_reg, uop->imm_data); + } +# ifdef RECOMPILER_DEBUG + else + fatal("CMP_IMM_JNZ_DEST %02x\n", uop->src_reg_a_real); +# endif + uop->p = host_x86_JNZ_long(block); - return 0; + return 0; } -static int codegen_CMP_IMM_JZ_DEST(codeblock_t *block, uop_t *uop) +static int +codegen_CMP_IMM_JZ_DEST(codeblock_t *block, uop_t *uop) { - int src_reg = HOST_REG_GET(uop->src_reg_a_real); - int src_size = IREG_GET_SIZE(uop->src_reg_a_real); + int src_reg = HOST_REG_GET(uop->src_reg_a_real); + int src_size = IREG_GET_SIZE(uop->src_reg_a_real); - if (REG_IS_L(src_size)) - { - host_x86_CMP32_REG_IMM(block, src_reg, uop->imm_data); - } - else if (REG_IS_W(src_size)) - { - host_x86_CMP16_REG_IMM(block, src_reg, uop->imm_data); - } -#ifdef RECOMPILER_DEBUG - else - fatal("CMP_IMM_JZ_DEST %02x\n", uop->src_reg_a_real); -#endif - uop->p = host_x86_JZ_long(block); - - return 0; + if (REG_IS_L(src_size)) { + host_x86_CMP32_REG_IMM(block, src_reg, uop->imm_data); + } else if (REG_IS_W(src_size)) { + host_x86_CMP16_REG_IMM(block, src_reg, uop->imm_data); + } +# ifdef RECOMPILER_DEBUG + else + fatal("CMP_IMM_JZ_DEST %02x\n", uop->src_reg_a_real); +# endif + uop->p = host_x86_JZ_long(block); + + return 0; } -static int codegen_CMP_JB(codeblock_t *block, uop_t *uop) +static int +codegen_CMP_JB(codeblock_t *block, uop_t *uop) { - int src_reg_a = HOST_REG_GET(uop->src_reg_a_real), src_reg_b = HOST_REG_GET(uop->src_reg_b_real); - int src_size_a = IREG_GET_SIZE(uop->src_reg_a_real), src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); - uint32_t *jump_p; + int src_reg_a = HOST_REG_GET(uop->src_reg_a_real); + int src_reg_b = HOST_REG_GET(uop->src_reg_b_real); + int src_size_a = IREG_GET_SIZE(uop->src_reg_a_real); + int src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); + uint32_t *jump_p; - if (REG_IS_L(src_size_a) && REG_IS_L(src_size_b)) - { - host_x86_CMP32_REG_REG(block, src_reg_a, src_reg_b); - } -#ifdef RECOMPILER_DEBUG - else - fatal("CMP_JB %02x\n", uop->src_reg_a_real); -#endif - jump_p = host_x86_JB_long(block); - *jump_p = (uintptr_t)uop->p - ((uintptr_t)jump_p + 4); + if (REG_IS_L(src_size_a) && REG_IS_L(src_size_b)) { + host_x86_CMP32_REG_REG(block, src_reg_a, src_reg_b); + } +# ifdef RECOMPILER_DEBUG + else + fatal("CMP_JB %02x\n", uop->src_reg_a_real); +# endif + jump_p = host_x86_JB_long(block); + *jump_p = (uintptr_t) uop->p - ((uintptr_t) jump_p + 4); - return 0; + return 0; } -static int codegen_CMP_JNBE(codeblock_t *block, uop_t *uop) +static int +codegen_CMP_JNBE(codeblock_t *block, uop_t *uop) { - int src_reg_a = HOST_REG_GET(uop->src_reg_a_real), src_reg_b = HOST_REG_GET(uop->src_reg_b_real); - int src_size_a = IREG_GET_SIZE(uop->src_reg_a_real), src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); - uint32_t *jump_p; + int src_reg_a = HOST_REG_GET(uop->src_reg_a_real); + int src_reg_b = HOST_REG_GET(uop->src_reg_b_real); + int src_size_a = IREG_GET_SIZE(uop->src_reg_a_real); + int src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); + uint32_t *jump_p; - if (REG_IS_L(src_size_a) && REG_IS_L(src_size_b)) - { - host_x86_CMP32_REG_REG(block, src_reg_a, src_reg_b); - } -#ifdef RECOMPILER_DEBUG - else - fatal("CMP_JNBE %02x\n", uop->src_reg_a_real); -#endif - jump_p = host_x86_JNBE_long(block); - *jump_p = (uintptr_t)uop->p - ((uintptr_t)jump_p + 4); - - return 0; + if (REG_IS_L(src_size_a) && REG_IS_L(src_size_b)) { + host_x86_CMP32_REG_REG(block, src_reg_a, src_reg_b); + } +# ifdef RECOMPILER_DEBUG + else + fatal("CMP_JNBE %02x\n", uop->src_reg_a_real); +# endif + jump_p = host_x86_JNBE_long(block); + *jump_p = (uintptr_t) uop->p - ((uintptr_t) jump_p + 4); + + return 0; } -static int codegen_CMP_JNB_DEST(codeblock_t *block, uop_t *uop) +static int +codegen_CMP_JNB_DEST(codeblock_t *block, uop_t *uop) { - int src_reg_a = HOST_REG_GET(uop->src_reg_a_real), src_reg_b = HOST_REG_GET(uop->src_reg_b_real); - int src_size_a = IREG_GET_SIZE(uop->src_reg_a_real), src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); + int src_reg_a = HOST_REG_GET(uop->src_reg_a_real); + int src_reg_b = HOST_REG_GET(uop->src_reg_b_real); + int src_size_a = IREG_GET_SIZE(uop->src_reg_a_real); + int src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); - if (REG_IS_L(src_size_a) && REG_IS_L(src_size_b)) - { - host_x86_CMP32_REG_REG(block, src_reg_a, src_reg_b); - } - else if (REG_IS_W(src_size_a) && REG_IS_W(src_size_b)) - { - host_x86_CMP16_REG_REG(block, src_reg_a, src_reg_b); - } - else if (REG_IS_B(src_size_a) && REG_IS_B(src_size_b)) - { - host_x86_CMP8_REG_REG(block, src_reg_a, src_reg_b); - } -#ifdef RECOMPILER_DEBUG - else - fatal("CMP_JNB_DEST %02x\n", uop->src_reg_a_real); -#endif - uop->p = host_x86_JNB_long(block); + if (REG_IS_L(src_size_a) && REG_IS_L(src_size_b)) { + host_x86_CMP32_REG_REG(block, src_reg_a, src_reg_b); + } else if (REG_IS_W(src_size_a) && REG_IS_W(src_size_b)) { + host_x86_CMP16_REG_REG(block, src_reg_a, src_reg_b); + } else if (REG_IS_B(src_size_a) && REG_IS_B(src_size_b)) { + host_x86_CMP8_REG_REG(block, src_reg_a, src_reg_b); + } +# ifdef RECOMPILER_DEBUG + else + fatal("CMP_JNB_DEST %02x\n", uop->src_reg_a_real); +# endif + uop->p = host_x86_JNB_long(block); - return 0; + return 0; } -static int codegen_CMP_JNBE_DEST(codeblock_t *block, uop_t *uop) +static int +codegen_CMP_JNBE_DEST(codeblock_t *block, uop_t *uop) { - int src_reg_a = HOST_REG_GET(uop->src_reg_a_real), src_reg_b = HOST_REG_GET(uop->src_reg_b_real); - int src_size_a = IREG_GET_SIZE(uop->src_reg_a_real), src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); + int src_reg_a = HOST_REG_GET(uop->src_reg_a_real); + int src_reg_b = HOST_REG_GET(uop->src_reg_b_real); + int src_size_a = IREG_GET_SIZE(uop->src_reg_a_real); + int src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); - if (REG_IS_L(src_size_a) && REG_IS_L(src_size_b)) - { - host_x86_CMP32_REG_REG(block, src_reg_a, src_reg_b); - } - else if (REG_IS_W(src_size_a) && REG_IS_W(src_size_b)) - { - host_x86_CMP16_REG_REG(block, src_reg_a, src_reg_b); - } - else if (REG_IS_B(src_size_a) && REG_IS_B(src_size_b)) - { - host_x86_CMP8_REG_REG(block, src_reg_a, src_reg_b); - } -#ifdef RECOMPILER_DEBUG - else - fatal("CMP_JNBE_DEST %02x\n", uop->src_reg_a_real); -#endif - uop->p = host_x86_JNBE_long(block); + if (REG_IS_L(src_size_a) && REG_IS_L(src_size_b)) { + host_x86_CMP32_REG_REG(block, src_reg_a, src_reg_b); + } else if (REG_IS_W(src_size_a) && REG_IS_W(src_size_b)) { + host_x86_CMP16_REG_REG(block, src_reg_a, src_reg_b); + } else if (REG_IS_B(src_size_a) && REG_IS_B(src_size_b)) { + host_x86_CMP8_REG_REG(block, src_reg_a, src_reg_b); + } +# ifdef RECOMPILER_DEBUG + else + fatal("CMP_JNBE_DEST %02x\n", uop->src_reg_a_real); +# endif + uop->p = host_x86_JNBE_long(block); - return 0; + return 0; } -static int codegen_CMP_JNL_DEST(codeblock_t *block, uop_t *uop) +static int +codegen_CMP_JNL_DEST(codeblock_t *block, uop_t *uop) { - int src_reg_a = HOST_REG_GET(uop->src_reg_a_real), src_reg_b = HOST_REG_GET(uop->src_reg_b_real); - int src_size_a = IREG_GET_SIZE(uop->src_reg_a_real), src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); + int src_reg_a = HOST_REG_GET(uop->src_reg_a_real); + int src_reg_b = HOST_REG_GET(uop->src_reg_b_real); + int src_size_a = IREG_GET_SIZE(uop->src_reg_a_real); + int src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); - if (REG_IS_L(src_size_a) && REG_IS_L(src_size_b)) - { - host_x86_CMP32_REG_REG(block, src_reg_a, src_reg_b); - } - else if (REG_IS_W(src_size_a) && REG_IS_W(src_size_b)) - { - host_x86_CMP16_REG_REG(block, src_reg_a, src_reg_b); - } - else if (REG_IS_B(src_size_a) && REG_IS_B(src_size_b)) - { - host_x86_CMP8_REG_REG(block, src_reg_a, src_reg_b); - } -#ifdef RECOMPILER_DEBUG - else - fatal("CMP_JNL_DEST %02x\n", uop->src_reg_a_real); -#endif - uop->p = host_x86_JNL_long(block); + if (REG_IS_L(src_size_a) && REG_IS_L(src_size_b)) { + host_x86_CMP32_REG_REG(block, src_reg_a, src_reg_b); + } else if (REG_IS_W(src_size_a) && REG_IS_W(src_size_b)) { + host_x86_CMP16_REG_REG(block, src_reg_a, src_reg_b); + } else if (REG_IS_B(src_size_a) && REG_IS_B(src_size_b)) { + host_x86_CMP8_REG_REG(block, src_reg_a, src_reg_b); + } +# ifdef RECOMPILER_DEBUG + else + fatal("CMP_JNL_DEST %02x\n", uop->src_reg_a_real); +# endif + uop->p = host_x86_JNL_long(block); - return 0; + return 0; } -static int codegen_CMP_JNLE_DEST(codeblock_t *block, uop_t *uop) +static int +codegen_CMP_JNLE_DEST(codeblock_t *block, uop_t *uop) { - int src_reg_a = HOST_REG_GET(uop->src_reg_a_real), src_reg_b = HOST_REG_GET(uop->src_reg_b_real); - int src_size_a = IREG_GET_SIZE(uop->src_reg_a_real), src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); + int src_reg_a = HOST_REG_GET(uop->src_reg_a_real); + int src_reg_b = HOST_REG_GET(uop->src_reg_b_real); + int src_size_a = IREG_GET_SIZE(uop->src_reg_a_real); + int src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); - if (REG_IS_L(src_size_a) && REG_IS_L(src_size_b)) - { - host_x86_CMP32_REG_REG(block, src_reg_a, src_reg_b); - } - else if (REG_IS_W(src_size_a) && REG_IS_W(src_size_b)) - { - host_x86_CMP16_REG_REG(block, src_reg_a, src_reg_b); - } - else if (REG_IS_B(src_size_a) && REG_IS_B(src_size_b)) - { - host_x86_CMP8_REG_REG(block, src_reg_a, src_reg_b); - } -#ifdef RECOMPILER_DEBUG - else - fatal("CMP_JNLE_DEST %02x\n", uop->src_reg_a_real); -#endif - uop->p = host_x86_JNLE_long(block); + if (REG_IS_L(src_size_a) && REG_IS_L(src_size_b)) { + host_x86_CMP32_REG_REG(block, src_reg_a, src_reg_b); + } else if (REG_IS_W(src_size_a) && REG_IS_W(src_size_b)) { + host_x86_CMP16_REG_REG(block, src_reg_a, src_reg_b); + } else if (REG_IS_B(src_size_a) && REG_IS_B(src_size_b)) { + host_x86_CMP8_REG_REG(block, src_reg_a, src_reg_b); + } +# ifdef RECOMPILER_DEBUG + else + fatal("CMP_JNLE_DEST %02x\n", uop->src_reg_a_real); +# endif + uop->p = host_x86_JNLE_long(block); - return 0; + return 0; } -static int codegen_CMP_JNO_DEST(codeblock_t *block, uop_t *uop) +static int +codegen_CMP_JNO_DEST(codeblock_t *block, uop_t *uop) { - int src_reg_a = HOST_REG_GET(uop->src_reg_a_real), src_reg_b = HOST_REG_GET(uop->src_reg_b_real); - int src_size_a = IREG_GET_SIZE(uop->src_reg_a_real), src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); + int src_reg_a = HOST_REG_GET(uop->src_reg_a_real); + int src_reg_b = HOST_REG_GET(uop->src_reg_b_real); + int src_size_a = IREG_GET_SIZE(uop->src_reg_a_real); + int src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); - if (REG_IS_L(src_size_a) && REG_IS_L(src_size_b)) - { - host_x86_CMP32_REG_REG(block, src_reg_a, src_reg_b); - } - else if (REG_IS_W(src_size_a) && REG_IS_W(src_size_b)) - { - host_x86_CMP16_REG_REG(block, src_reg_a, src_reg_b); - } - else if (REG_IS_B(src_size_a) && REG_IS_B(src_size_b)) - { - host_x86_CMP8_REG_REG(block, src_reg_a, src_reg_b); - } -#ifdef RECOMPILER_DEBUG - else - fatal("CMP_JNO_DEST %02x\n", uop->src_reg_a_real); -#endif - uop->p = host_x86_JNO_long(block); + if (REG_IS_L(src_size_a) && REG_IS_L(src_size_b)) { + host_x86_CMP32_REG_REG(block, src_reg_a, src_reg_b); + } else if (REG_IS_W(src_size_a) && REG_IS_W(src_size_b)) { + host_x86_CMP16_REG_REG(block, src_reg_a, src_reg_b); + } else if (REG_IS_B(src_size_a) && REG_IS_B(src_size_b)) { + host_x86_CMP8_REG_REG(block, src_reg_a, src_reg_b); + } +# ifdef RECOMPILER_DEBUG + else + fatal("CMP_JNO_DEST %02x\n", uop->src_reg_a_real); +# endif + uop->p = host_x86_JNO_long(block); - return 0; + return 0; } -static int codegen_CMP_JNZ_DEST(codeblock_t *block, uop_t *uop) +static int +codegen_CMP_JNZ_DEST(codeblock_t *block, uop_t *uop) { - int src_reg_a = HOST_REG_GET(uop->src_reg_a_real), src_reg_b = HOST_REG_GET(uop->src_reg_b_real); - int src_size_a = IREG_GET_SIZE(uop->src_reg_a_real), src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); + int src_reg_a = HOST_REG_GET(uop->src_reg_a_real); + int src_reg_b = HOST_REG_GET(uop->src_reg_b_real); + int src_size_a = IREG_GET_SIZE(uop->src_reg_a_real); + int src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); - if (REG_IS_L(src_size_a) && REG_IS_L(src_size_b)) - { - host_x86_CMP32_REG_REG(block, src_reg_a, src_reg_b); - } - else if (REG_IS_W(src_size_a) && REG_IS_W(src_size_b)) - { - host_x86_CMP16_REG_REG(block, src_reg_a, src_reg_b); - } - else if (REG_IS_B(src_size_a) && REG_IS_B(src_size_b)) - { - host_x86_CMP8_REG_REG(block, src_reg_a, src_reg_b); - } -#ifdef RECOMPILER_DEBUG - else - fatal("CMP_JNZ_DEST %02x\n", uop->src_reg_a_real); -#endif - uop->p = host_x86_JNZ_long(block); + if (REG_IS_L(src_size_a) && REG_IS_L(src_size_b)) { + host_x86_CMP32_REG_REG(block, src_reg_a, src_reg_b); + } else if (REG_IS_W(src_size_a) && REG_IS_W(src_size_b)) { + host_x86_CMP16_REG_REG(block, src_reg_a, src_reg_b); + } else if (REG_IS_B(src_size_a) && REG_IS_B(src_size_b)) { + host_x86_CMP8_REG_REG(block, src_reg_a, src_reg_b); + } +# ifdef RECOMPILER_DEBUG + else + fatal("CMP_JNZ_DEST %02x\n", uop->src_reg_a_real); +# endif + uop->p = host_x86_JNZ_long(block); - return 0; + return 0; } -static int codegen_CMP_JB_DEST(codeblock_t *block, uop_t *uop) +static int +codegen_CMP_JB_DEST(codeblock_t *block, uop_t *uop) { - int src_reg_a = HOST_REG_GET(uop->src_reg_a_real), src_reg_b = HOST_REG_GET(uop->src_reg_b_real); - int src_size_a = IREG_GET_SIZE(uop->src_reg_a_real), src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); + int src_reg_a = HOST_REG_GET(uop->src_reg_a_real); + int src_reg_b = HOST_REG_GET(uop->src_reg_b_real); + int src_size_a = IREG_GET_SIZE(uop->src_reg_a_real); + int src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); - if (REG_IS_L(src_size_a) && REG_IS_L(src_size_b)) - { - host_x86_CMP32_REG_REG(block, src_reg_a, src_reg_b); - } - else if (REG_IS_W(src_size_a) && REG_IS_W(src_size_b)) - { - host_x86_CMP16_REG_REG(block, src_reg_a, src_reg_b); - } - else if (REG_IS_B(src_size_a) && REG_IS_B(src_size_b)) - { - host_x86_CMP8_REG_REG(block, src_reg_a, src_reg_b); - } -#ifdef RECOMPILER_DEBUG - else - fatal("CMP_JB_DEST %02x\n", uop->src_reg_a_real); -#endif - uop->p = host_x86_JB_long(block); + if (REG_IS_L(src_size_a) && REG_IS_L(src_size_b)) { + host_x86_CMP32_REG_REG(block, src_reg_a, src_reg_b); + } else if (REG_IS_W(src_size_a) && REG_IS_W(src_size_b)) { + host_x86_CMP16_REG_REG(block, src_reg_a, src_reg_b); + } else if (REG_IS_B(src_size_a) && REG_IS_B(src_size_b)) { + host_x86_CMP8_REG_REG(block, src_reg_a, src_reg_b); + } +# ifdef RECOMPILER_DEBUG + else + fatal("CMP_JB_DEST %02x\n", uop->src_reg_a_real); +# endif + uop->p = host_x86_JB_long(block); - return 0; + return 0; } -static int codegen_CMP_JBE_DEST(codeblock_t *block, uop_t *uop) +static int +codegen_CMP_JBE_DEST(codeblock_t *block, uop_t *uop) { - int src_reg_a = HOST_REG_GET(uop->src_reg_a_real), src_reg_b = HOST_REG_GET(uop->src_reg_b_real); - int src_size_a = IREG_GET_SIZE(uop->src_reg_a_real), src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); + int src_reg_a = HOST_REG_GET(uop->src_reg_a_real); + int src_reg_b = HOST_REG_GET(uop->src_reg_b_real); + int src_size_a = IREG_GET_SIZE(uop->src_reg_a_real); + int src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); - if (REG_IS_L(src_size_a) && REG_IS_L(src_size_b)) - { - host_x86_CMP32_REG_REG(block, src_reg_a, src_reg_b); - } - else if (REG_IS_W(src_size_a) && REG_IS_W(src_size_b)) - { - host_x86_CMP16_REG_REG(block, src_reg_a, src_reg_b); - } - else if (REG_IS_B(src_size_a) && REG_IS_B(src_size_b)) - { - host_x86_CMP8_REG_REG(block, src_reg_a, src_reg_b); - } -#ifdef RECOMPILER_DEBUG - else - fatal("CMP_JBE_DEST %02x\n", uop->src_reg_a_real); -#endif - uop->p = host_x86_JBE_long(block); + if (REG_IS_L(src_size_a) && REG_IS_L(src_size_b)) { + host_x86_CMP32_REG_REG(block, src_reg_a, src_reg_b); + } else if (REG_IS_W(src_size_a) && REG_IS_W(src_size_b)) { + host_x86_CMP16_REG_REG(block, src_reg_a, src_reg_b); + } else if (REG_IS_B(src_size_a) && REG_IS_B(src_size_b)) { + host_x86_CMP8_REG_REG(block, src_reg_a, src_reg_b); + } +# ifdef RECOMPILER_DEBUG + else + fatal("CMP_JBE_DEST %02x\n", uop->src_reg_a_real); +# endif + uop->p = host_x86_JBE_long(block); - return 0; + return 0; } -static int codegen_CMP_JL_DEST(codeblock_t *block, uop_t *uop) +static int +codegen_CMP_JL_DEST(codeblock_t *block, uop_t *uop) { - int src_reg_a = HOST_REG_GET(uop->src_reg_a_real), src_reg_b = HOST_REG_GET(uop->src_reg_b_real); - int src_size_a = IREG_GET_SIZE(uop->src_reg_a_real), src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); + int src_reg_a = HOST_REG_GET(uop->src_reg_a_real); + int src_reg_b = HOST_REG_GET(uop->src_reg_b_real); + int src_size_a = IREG_GET_SIZE(uop->src_reg_a_real); + int src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); - if (REG_IS_L(src_size_a) && REG_IS_L(src_size_b)) - { - host_x86_CMP32_REG_REG(block, src_reg_a, src_reg_b); - } - else if (REG_IS_W(src_size_a) && REG_IS_W(src_size_b)) - { - host_x86_CMP16_REG_REG(block, src_reg_a, src_reg_b); - } - else if (REG_IS_B(src_size_a) && REG_IS_B(src_size_b)) - { - host_x86_CMP8_REG_REG(block, src_reg_a, src_reg_b); - } -#ifdef RECOMPILER_DEBUG - else - fatal("CMP_JL_DEST %02x\n", uop->src_reg_a_real); -#endif - uop->p = host_x86_JL_long(block); + if (REG_IS_L(src_size_a) && REG_IS_L(src_size_b)) { + host_x86_CMP32_REG_REG(block, src_reg_a, src_reg_b); + } else if (REG_IS_W(src_size_a) && REG_IS_W(src_size_b)) { + host_x86_CMP16_REG_REG(block, src_reg_a, src_reg_b); + } else if (REG_IS_B(src_size_a) && REG_IS_B(src_size_b)) { + host_x86_CMP8_REG_REG(block, src_reg_a, src_reg_b); + } +# ifdef RECOMPILER_DEBUG + else + fatal("CMP_JL_DEST %02x\n", uop->src_reg_a_real); +# endif + uop->p = host_x86_JL_long(block); - return 0; + return 0; } -static int codegen_CMP_JLE_DEST(codeblock_t *block, uop_t *uop) +static int +codegen_CMP_JLE_DEST(codeblock_t *block, uop_t *uop) { - int src_reg_a = HOST_REG_GET(uop->src_reg_a_real), src_reg_b = HOST_REG_GET(uop->src_reg_b_real); - int src_size_a = IREG_GET_SIZE(uop->src_reg_a_real), src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); + int src_reg_a = HOST_REG_GET(uop->src_reg_a_real); + int src_reg_b = HOST_REG_GET(uop->src_reg_b_real); + int src_size_a = IREG_GET_SIZE(uop->src_reg_a_real); + int src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); - if (REG_IS_L(src_size_a) && REG_IS_L(src_size_b)) - { - host_x86_CMP32_REG_REG(block, src_reg_a, src_reg_b); - } - else if (REG_IS_W(src_size_a) && REG_IS_W(src_size_b)) - { - host_x86_CMP16_REG_REG(block, src_reg_a, src_reg_b); - } - else if (REG_IS_B(src_size_a) && REG_IS_B(src_size_b)) - { - host_x86_CMP8_REG_REG(block, src_reg_a, src_reg_b); - } -#ifdef RECOMPILER_DEBUG - else - fatal("CMP_JLE_DEST %02x\n", uop->src_reg_a_real); -#endif - uop->p = host_x86_JLE_long(block); + if (REG_IS_L(src_size_a) && REG_IS_L(src_size_b)) { + host_x86_CMP32_REG_REG(block, src_reg_a, src_reg_b); + } else if (REG_IS_W(src_size_a) && REG_IS_W(src_size_b)) { + host_x86_CMP16_REG_REG(block, src_reg_a, src_reg_b); + } else if (REG_IS_B(src_size_a) && REG_IS_B(src_size_b)) { + host_x86_CMP8_REG_REG(block, src_reg_a, src_reg_b); + } +# ifdef RECOMPILER_DEBUG + else + fatal("CMP_JLE_DEST %02x\n", uop->src_reg_a_real); +# endif + uop->p = host_x86_JLE_long(block); - return 0; + return 0; } -static int codegen_CMP_JO_DEST(codeblock_t *block, uop_t *uop) +static int +codegen_CMP_JO_DEST(codeblock_t *block, uop_t *uop) { - int src_reg_a = HOST_REG_GET(uop->src_reg_a_real), src_reg_b = HOST_REG_GET(uop->src_reg_b_real); - int src_size_a = IREG_GET_SIZE(uop->src_reg_a_real), src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); + int src_reg_a = HOST_REG_GET(uop->src_reg_a_real); + int src_reg_b = HOST_REG_GET(uop->src_reg_b_real); + int src_size_a = IREG_GET_SIZE(uop->src_reg_a_real); + int src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); - if (REG_IS_L(src_size_a) && REG_IS_L(src_size_b)) - { - host_x86_CMP32_REG_REG(block, src_reg_a, src_reg_b); - } - else if (REG_IS_W(src_size_a) && REG_IS_W(src_size_b)) - { - host_x86_CMP16_REG_REG(block, src_reg_a, src_reg_b); - } - else if (REG_IS_B(src_size_a) && REG_IS_B(src_size_b)) - { - host_x86_CMP8_REG_REG(block, src_reg_a, src_reg_b); - } -#ifdef RECOMPILER_DEBUG - else - fatal("CMP_JO_DEST %02x\n", uop->src_reg_a_real); -#endif - uop->p = host_x86_JO_long(block); + if (REG_IS_L(src_size_a) && REG_IS_L(src_size_b)) { + host_x86_CMP32_REG_REG(block, src_reg_a, src_reg_b); + } else if (REG_IS_W(src_size_a) && REG_IS_W(src_size_b)) { + host_x86_CMP16_REG_REG(block, src_reg_a, src_reg_b); + } else if (REG_IS_B(src_size_a) && REG_IS_B(src_size_b)) { + host_x86_CMP8_REG_REG(block, src_reg_a, src_reg_b); + } +# ifdef RECOMPILER_DEBUG + else + fatal("CMP_JO_DEST %02x\n", uop->src_reg_a_real); +# endif + uop->p = host_x86_JO_long(block); - return 0; + return 0; } -static int codegen_CMP_JZ_DEST(codeblock_t *block, uop_t *uop) +static int +codegen_CMP_JZ_DEST(codeblock_t *block, uop_t *uop) { - int src_reg_a = HOST_REG_GET(uop->src_reg_a_real), src_reg_b = HOST_REG_GET(uop->src_reg_b_real); - int src_size_a = IREG_GET_SIZE(uop->src_reg_a_real), src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); + int src_reg_a = HOST_REG_GET(uop->src_reg_a_real); + int src_reg_b = HOST_REG_GET(uop->src_reg_b_real); + int src_size_a = IREG_GET_SIZE(uop->src_reg_a_real); + int src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); - if (REG_IS_L(src_size_a) && REG_IS_L(src_size_b)) - { - host_x86_CMP32_REG_REG(block, src_reg_a, src_reg_b); - } - else if (REG_IS_W(src_size_a) && REG_IS_W(src_size_b)) - { - host_x86_CMP16_REG_REG(block, src_reg_a, src_reg_b); - } - else if (REG_IS_B(src_size_a) && REG_IS_B(src_size_b)) - { - host_x86_CMP8_REG_REG(block, src_reg_a, src_reg_b); - } -#ifdef RECOMPILER_DEBUG - else - fatal("CMP_JZ_DEST %02x\n", uop->src_reg_a_real); -#endif - uop->p = host_x86_JZ_long(block); + if (REG_IS_L(src_size_a) && REG_IS_L(src_size_b)) { + host_x86_CMP32_REG_REG(block, src_reg_a, src_reg_b); + } else if (REG_IS_W(src_size_a) && REG_IS_W(src_size_b)) { + host_x86_CMP16_REG_REG(block, src_reg_a, src_reg_b); + } else if (REG_IS_B(src_size_a) && REG_IS_B(src_size_b)) { + host_x86_CMP8_REG_REG(block, src_reg_a, src_reg_b); + } +# ifdef RECOMPILER_DEBUG + else + fatal("CMP_JZ_DEST %02x\n", uop->src_reg_a_real); +# endif + uop->p = host_x86_JZ_long(block); - return 0; + return 0; } -static int codegen_FABS(codeblock_t *block, uop_t *uop) +static int +codegen_FABS(codeblock_t *block, uop_t *uop) { - int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg_a = HOST_REG_GET(uop->src_reg_a_real); - int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size_a = IREG_GET_SIZE(uop->src_reg_a_real); + int dest_reg = HOST_REG_GET(uop->dest_reg_a_real); + int src_reg_a = HOST_REG_GET(uop->src_reg_a_real); + int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real); + int src_size_a = IREG_GET_SIZE(uop->src_reg_a_real); - if (REG_IS_D(dest_size) && REG_IS_D(src_size_a) && dest_reg == src_reg_a) - { - host_x86_PXOR_XREG_XREG(block, REG_XMM_TEMP, REG_XMM_TEMP); - host_x86_SUBSD_XREG_XREG(block, REG_XMM_TEMP, dest_reg); - host_x86_MAXSD_XREG_XREG(block, dest_reg, REG_XMM_TEMP); + if (REG_IS_D(dest_size) && REG_IS_D(src_size_a) && dest_reg == src_reg_a) { + host_x86_PXOR_XREG_XREG(block, REG_XMM_TEMP, REG_XMM_TEMP); + host_x86_SUBSD_XREG_XREG(block, REG_XMM_TEMP, dest_reg); + host_x86_MAXSD_XREG_XREG(block, dest_reg, REG_XMM_TEMP); + } +# ifdef RECOMPILER_DEBUG + else + fatal("codegen_FABS %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real); +# endif + return 0; +} +static int +codegen_FCHS(codeblock_t *block, uop_t *uop) +{ + int dest_reg = HOST_REG_GET(uop->dest_reg_a_real); + int src_reg_a = HOST_REG_GET(uop->src_reg_a_real); + int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real); + int src_size_a = IREG_GET_SIZE(uop->src_reg_a_real); + + if (REG_IS_D(dest_size) && REG_IS_D(src_size_a)) { + host_x86_MOVQ_XREG_XREG(block, REG_XMM_TEMP, src_reg_a); + host_x86_PXOR_XREG_XREG(block, dest_reg, dest_reg); + host_x86_SUBSD_XREG_XREG(block, dest_reg, REG_XMM_TEMP); + } +# ifdef RECOMPILER_DEBUG + else + fatal("codegen_FCHS %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real); +# endif + return 0; +} +static int +codegen_FSQRT(codeblock_t *block, uop_t *uop) +{ + int dest_reg = HOST_REG_GET(uop->dest_reg_a_real); + int src_reg_a = HOST_REG_GET(uop->src_reg_a_real); + int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real); + int src_size_a = IREG_GET_SIZE(uop->src_reg_a_real); + + if (REG_IS_D(dest_size) && REG_IS_D(src_size_a)) { + host_x86_SQRTSD_XREG_XREG(block, dest_reg, src_reg_a); + } +# ifdef RECOMPILER_DEBUG + else + fatal("codegen_FSQRT %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real); +# endif + return 0; +} +static int +codegen_FTST(codeblock_t *block, uop_t *uop) +{ + int dest_reg = HOST_REG_GET(uop->dest_reg_a_real); + int src_reg_a = HOST_REG_GET(uop->src_reg_a_real); + int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real); + int src_size_a = IREG_GET_SIZE(uop->src_reg_a_real); + + if (REG_IS_W(dest_size) && REG_IS_D(src_size_a)) { + host_x86_PXOR_XREG_XREG(block, REG_XMM_TEMP, REG_XMM_TEMP); + if (dest_reg != REG_EAX) + host_x86_MOV32_REG_REG(block, REG_ECX, REG_EAX); + host_x86_XOR32_REG_REG(block, REG_EAX, REG_EAX); + host_x86_COMISD_XREG_XREG(block, src_reg_a, REG_XMM_TEMP); + host_x86_LAHF(block); + host_x86_AND16_REG_IMM(block, REG_EAX, C0 | C2 | C3); + if (dest_reg != REG_EAX) { + host_x86_MOV16_REG_REG(block, dest_reg, REG_EAX); + host_x86_MOV32_REG_REG(block, REG_EAX, REG_ECX); } -#ifdef RECOMPILER_DEBUG - else - fatal("codegen_FABS %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real); -#endif - return 0; + } +# ifdef RECOMPILER_DEBUG + else + fatal("codegen_FTST %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real); +# endif + return 0; } -static int codegen_FCHS(codeblock_t *block, uop_t *uop) -{ - int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg_a = HOST_REG_GET(uop->src_reg_a_real); - int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size_a = IREG_GET_SIZE(uop->src_reg_a_real); - if (REG_IS_D(dest_size) && REG_IS_D(src_size_a)) - { - host_x86_MOVQ_XREG_XREG(block, REG_XMM_TEMP, src_reg_a); - host_x86_PXOR_XREG_XREG(block, dest_reg, dest_reg); - host_x86_SUBSD_XREG_XREG(block, dest_reg, REG_XMM_TEMP); +static int +codegen_FADD(codeblock_t *block, uop_t *uop) +{ + int dest_reg = HOST_REG_GET(uop->dest_reg_a_real); + int src_reg_a = HOST_REG_GET(uop->src_reg_a_real); + int src_reg_b = HOST_REG_GET(uop->src_reg_b_real); + int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real); + int src_size_a = IREG_GET_SIZE(uop->src_reg_a_real); + int src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); + + if (REG_IS_D(dest_size) && REG_IS_D(src_size_a) && REG_IS_D(src_size_b) && dest_reg == src_reg_a) { + host_x86_ADDSD_XREG_XREG(block, dest_reg, src_reg_b); + } +# ifdef RECOMPILER_DEBUG + else + fatal("codegen_FADD %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real); +# endif + return 0; +} +static int +codegen_FCOM(codeblock_t *block, uop_t *uop) +{ + int dest_reg = HOST_REG_GET(uop->dest_reg_a_real); + int src_reg_a = HOST_REG_GET(uop->src_reg_a_real); + int src_reg_b = HOST_REG_GET(uop->src_reg_b_real); + int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real); + int src_size_a = IREG_GET_SIZE(uop->src_reg_a_real); + int src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); + + if (REG_IS_W(dest_size) && REG_IS_D(src_size_a) && REG_IS_D(src_size_b)) { + if (dest_reg != REG_EAX) + host_x86_MOV32_REG_REG(block, REG_ECX, REG_EAX); + host_x86_XOR32_REG_REG(block, REG_EAX, REG_EAX); + host_x86_COMISD_XREG_XREG(block, src_reg_a, src_reg_b); + host_x86_LAHF(block); + host_x86_AND16_REG_IMM(block, REG_EAX, C0 | C2 | C3); + if (dest_reg != REG_EAX) { + host_x86_MOV16_REG_REG(block, dest_reg, REG_EAX); + host_x86_MOV32_REG_REG(block, REG_EAX, REG_ECX); } -#ifdef RECOMPILER_DEBUG - else - fatal("codegen_FCHS %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real); -#endif - return 0; + } +# ifdef RECOMPILER_DEBUG + else + fatal("codegen_FCOM %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real); +# endif + return 0; } -static int codegen_FSQRT(codeblock_t *block, uop_t *uop) +static int +codegen_FDIV(codeblock_t *block, uop_t *uop) { - int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg_a = HOST_REG_GET(uop->src_reg_a_real); - int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size_a = IREG_GET_SIZE(uop->src_reg_a_real); + int dest_reg = HOST_REG_GET(uop->dest_reg_a_real); + int src_reg_a = HOST_REG_GET(uop->src_reg_a_real); + int src_reg_b = HOST_REG_GET(uop->src_reg_b_real); + int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real); + int src_size_a = IREG_GET_SIZE(uop->src_reg_a_real); + int src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); - if (REG_IS_D(dest_size) && REG_IS_D(src_size_a)) - { - host_x86_SQRTSD_XREG_XREG(block, dest_reg, src_reg_a); - } -#ifdef RECOMPILER_DEBUG - else - fatal("codegen_FSQRT %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real); -#endif - return 0; + if (REG_IS_D(dest_size) && REG_IS_D(src_size_a) && REG_IS_D(src_size_b) && dest_reg == src_reg_a) { + host_x86_DIVSD_XREG_XREG(block, dest_reg, src_reg_b); + } else if (REG_IS_D(dest_size) && REG_IS_D(src_size_a) && REG_IS_D(src_size_b)) { + host_x86_MOVQ_XREG_XREG(block, REG_XMM_TEMP, src_reg_a); + host_x86_DIVSD_XREG_XREG(block, REG_XMM_TEMP, src_reg_b); + host_x86_MOVQ_XREG_XREG(block, dest_reg, REG_XMM_TEMP); + } +# ifdef RECOMPILER_DEBUG + else + fatal("codegen_FDIV %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real); +# endif + return 0; } -static int codegen_FTST(codeblock_t *block, uop_t *uop) +static int +codegen_FMUL(codeblock_t *block, uop_t *uop) { - int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg_a = HOST_REG_GET(uop->src_reg_a_real); - int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size_a = IREG_GET_SIZE(uop->src_reg_a_real); + int dest_reg = HOST_REG_GET(uop->dest_reg_a_real); + int src_reg_a = HOST_REG_GET(uop->src_reg_a_real); + int src_reg_b = HOST_REG_GET(uop->src_reg_b_real); + int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real); + int src_size_a = IREG_GET_SIZE(uop->src_reg_a_real); + int src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); - if (REG_IS_W(dest_size) && REG_IS_D(src_size_a)) - { - host_x86_PXOR_XREG_XREG(block, REG_XMM_TEMP, REG_XMM_TEMP); - if (dest_reg != REG_EAX) - host_x86_MOV32_REG_REG(block, REG_ECX, REG_EAX); - host_x86_XOR32_REG_REG(block, REG_EAX, REG_EAX); - host_x86_COMISD_XREG_XREG(block, src_reg_a, REG_XMM_TEMP); - host_x86_LAHF(block); - host_x86_AND16_REG_IMM(block, REG_EAX, C0|C2|C3); - if (dest_reg != REG_EAX) - { - host_x86_MOV16_REG_REG(block, dest_reg, REG_EAX); - host_x86_MOV32_REG_REG(block, REG_EAX, REG_ECX); - } - } -#ifdef RECOMPILER_DEBUG - else - fatal("codegen_FTST %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real); -#endif - return 0; + if (REG_IS_D(dest_size) && REG_IS_D(src_size_a) && REG_IS_D(src_size_b) && dest_reg == src_reg_a) { + host_x86_MULSD_XREG_XREG(block, dest_reg, src_reg_b); + } +# ifdef RECOMPILER_DEBUG + else + fatal("codegen_FMUL %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real); +# endif + return 0; +} +static int +codegen_FSUB(codeblock_t *block, uop_t *uop) +{ + int dest_reg = HOST_REG_GET(uop->dest_reg_a_real); + int src_reg_a = HOST_REG_GET(uop->src_reg_a_real); + int src_reg_b = HOST_REG_GET(uop->src_reg_b_real); + int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real); + int src_size_a = IREG_GET_SIZE(uop->src_reg_a_real); + int src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); + + if (REG_IS_D(dest_size) && REG_IS_D(src_size_a) && REG_IS_D(src_size_b) && dest_reg == src_reg_a) { + host_x86_SUBSD_XREG_XREG(block, dest_reg, src_reg_b); + } else if (REG_IS_D(dest_size) && REG_IS_D(src_size_a) && REG_IS_D(src_size_b)) { + host_x86_MOVQ_XREG_XREG(block, REG_XMM_TEMP, src_reg_a); + host_x86_SUBSD_XREG_XREG(block, REG_XMM_TEMP, src_reg_b); + host_x86_MOVQ_XREG_XREG(block, dest_reg, REG_XMM_TEMP); + } +# ifdef RECOMPILER_DEBUG + else + fatal("codegen_FSUB %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real); +# endif + return 0; } -static int codegen_FADD(codeblock_t *block, uop_t *uop) +static int +codegen_FP_ENTER(codeblock_t *block, uop_t *uop) { - int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg_a = HOST_REG_GET(uop->src_reg_a_real), src_reg_b = HOST_REG_GET(uop->src_reg_b_real); - int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size_a = IREG_GET_SIZE(uop->src_reg_a_real), src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); + uint32_t *branch_offset; - if (REG_IS_D(dest_size) && REG_IS_D(src_size_a) && REG_IS_D(src_size_b) && dest_reg == src_reg_a) - { - host_x86_ADDSD_XREG_XREG(block, dest_reg, src_reg_b); - } -#ifdef RECOMPILER_DEBUG - else - fatal("codegen_FADD %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real); -#endif - return 0; -} -static int codegen_FCOM(codeblock_t *block, uop_t *uop) -{ - int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg_a = HOST_REG_GET(uop->src_reg_a_real), src_reg_b = HOST_REG_GET(uop->src_reg_b_real); - int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size_a = IREG_GET_SIZE(uop->src_reg_a_real), src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); + host_x86_MOV32_REG_ABS(block, REG_ECX, &cr0); + host_x86_TEST32_REG_IMM(block, REG_ECX, 0xc); + branch_offset = host_x86_JZ_long(block); + host_x86_MOV32_ABS_IMM(block, &cpu_state.oldpc, uop->imm_data); + host_x86_MOV32_STACK_IMM(block, STACK_ARG0, 7); + host_x86_CALL(block, x86_int); + host_x86_JMP(block, codegen_exit_rout); + *branch_offset = (uint32_t) ((uintptr_t) &block_write_data[block_pos] - (uintptr_t) branch_offset) - 4; - if (REG_IS_W(dest_size) && REG_IS_D(src_size_a) && REG_IS_D(src_size_b)) - { - if (dest_reg != REG_EAX) - host_x86_MOV32_REG_REG(block, REG_ECX, REG_EAX); - host_x86_XOR32_REG_REG(block, REG_EAX, REG_EAX); - host_x86_COMISD_XREG_XREG(block, src_reg_a, src_reg_b); - host_x86_LAHF(block); - host_x86_AND16_REG_IMM(block, REG_EAX, C0|C2|C3); - if (dest_reg != REG_EAX) - { - host_x86_MOV16_REG_REG(block, dest_reg, REG_EAX); - host_x86_MOV32_REG_REG(block, REG_EAX, REG_ECX); - } - } -#ifdef RECOMPILER_DEBUG - else - fatal("codegen_FCOM %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real); -#endif - return 0; -} -static int codegen_FDIV(codeblock_t *block, uop_t *uop) -{ - int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg_a = HOST_REG_GET(uop->src_reg_a_real), src_reg_b = HOST_REG_GET(uop->src_reg_b_real); - int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size_a = IREG_GET_SIZE(uop->src_reg_a_real), src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); - - if (REG_IS_D(dest_size) && REG_IS_D(src_size_a) && REG_IS_D(src_size_b) && dest_reg == src_reg_a) - { - host_x86_DIVSD_XREG_XREG(block, dest_reg, src_reg_b); - } - else if (REG_IS_D(dest_size) && REG_IS_D(src_size_a) && REG_IS_D(src_size_b)) - { - host_x86_MOVQ_XREG_XREG(block, REG_XMM_TEMP, src_reg_a); - host_x86_DIVSD_XREG_XREG(block, REG_XMM_TEMP, src_reg_b); - host_x86_MOVQ_XREG_XREG(block, dest_reg, REG_XMM_TEMP); - } -#ifdef RECOMPILER_DEBUG - else - fatal("codegen_FDIV %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real); -#endif - return 0; -} -static int codegen_FMUL(codeblock_t *block, uop_t *uop) -{ - int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg_a = HOST_REG_GET(uop->src_reg_a_real), src_reg_b = HOST_REG_GET(uop->src_reg_b_real); - int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size_a = IREG_GET_SIZE(uop->src_reg_a_real), src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); - - if (REG_IS_D(dest_size) && REG_IS_D(src_size_a) && REG_IS_D(src_size_b) && dest_reg == src_reg_a) - { - host_x86_MULSD_XREG_XREG(block, dest_reg, src_reg_b); - } -#ifdef RECOMPILER_DEBUG - else - fatal("codegen_FMUL %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real); -#endif - return 0; -} -static int codegen_FSUB(codeblock_t *block, uop_t *uop) -{ - int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg_a = HOST_REG_GET(uop->src_reg_a_real), src_reg_b = HOST_REG_GET(uop->src_reg_b_real); - int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size_a = IREG_GET_SIZE(uop->src_reg_a_real), src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); - - if (REG_IS_D(dest_size) && REG_IS_D(src_size_a) && REG_IS_D(src_size_b) && dest_reg == src_reg_a) - { - host_x86_SUBSD_XREG_XREG(block, dest_reg, src_reg_b); - } - else if (REG_IS_D(dest_size) && REG_IS_D(src_size_a) && REG_IS_D(src_size_b)) - { - host_x86_MOVQ_XREG_XREG(block, REG_XMM_TEMP, src_reg_a); - host_x86_SUBSD_XREG_XREG(block, REG_XMM_TEMP, src_reg_b); - host_x86_MOVQ_XREG_XREG(block, dest_reg, REG_XMM_TEMP); - } -#ifdef RECOMPILER_DEBUG - else - fatal("codegen_FSUB %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real); -#endif - return 0; + return 0; } -static int codegen_FP_ENTER(codeblock_t *block, uop_t *uop) +static int +codegen_MMX_ENTER(codeblock_t *block, uop_t *uop) { - uint32_t *branch_offset; - - host_x86_MOV32_REG_ABS(block, REG_ECX, &cr0); - host_x86_TEST32_REG_IMM(block, REG_ECX, 0xc); - branch_offset = host_x86_JZ_long(block); - host_x86_MOV32_ABS_IMM(block, &cpu_state.oldpc, uop->imm_data); - host_x86_MOV32_STACK_IMM(block, STACK_ARG0, 7); - host_x86_CALL(block, x86_int); - host_x86_JMP(block, codegen_exit_rout); - *branch_offset = (uint32_t)((uintptr_t)&block_write_data[block_pos] - (uintptr_t)branch_offset) - 4; + uint32_t *branch_offset; - return 0; + host_x86_MOV32_REG_ABS(block, REG_ECX, &cr0); + host_x86_TEST32_REG_IMM(block, REG_ECX, 0xc); + branch_offset = host_x86_JZ_long(block); + host_x86_MOV32_ABS_IMM(block, &cpu_state.oldpc, uop->imm_data); + host_x86_MOV32_STACK_IMM(block, STACK_ARG0, 7); + host_x86_CALL(block, x86_int); + host_x86_JMP(block, codegen_exit_rout); + *branch_offset = (uint32_t) ((uintptr_t) &block_write_data[block_pos] - (uintptr_t) branch_offset) - 4; + host_x86_MOV32_ABS_IMM(block, &cpu_state.tag[0], 0x01010101); + host_x86_MOV32_ABS_IMM(block, &cpu_state.tag[4], 0x01010101); + host_x86_MOV32_ABS_IMM(block, &cpu_state.TOP, 0); + host_x86_MOV8_ABS_IMM(block, &cpu_state.ismmx, 1); + + return 0; } -static int codegen_MMX_ENTER(codeblock_t *block, uop_t *uop) +static int +codegen_JMP(codeblock_t *block, uop_t *uop) { - uint32_t *branch_offset; + host_x86_JMP(block, uop->p); - host_x86_MOV32_REG_ABS(block, REG_ECX, &cr0); - host_x86_TEST32_REG_IMM(block, REG_ECX, 0xc); - branch_offset = host_x86_JZ_long(block); - host_x86_MOV32_ABS_IMM(block, &cpu_state.oldpc, uop->imm_data); - host_x86_MOV32_STACK_IMM(block, STACK_ARG0, 7); - host_x86_CALL(block, x86_int); - host_x86_JMP(block, codegen_exit_rout); - *branch_offset = (uint32_t)((uintptr_t)&block_write_data[block_pos] - (uintptr_t)branch_offset) - 4; - host_x86_MOV32_ABS_IMM(block, &cpu_state.tag[0], 0x01010101); - host_x86_MOV32_ABS_IMM(block, &cpu_state.tag[4], 0x01010101); - host_x86_MOV32_ABS_IMM(block, &cpu_state.TOP, 0); - host_x86_MOV8_ABS_IMM(block, &cpu_state.ismmx, 1); - - return 0; + return 0; +} +static int +codegen_JMP_DEST(codeblock_t *block, uop_t *uop) +{ + uop->p = host_x86_JMP_long(block); + + return 0; } -static int codegen_JMP(codeblock_t *block, uop_t *uop) +static int +codegen_LOAD_FUNC_ARG0(codeblock_t *block, uop_t *uop) { - host_x86_JMP(block, uop->p); + int src_reg = HOST_REG_GET(uop->src_reg_a_real); + int src_size = IREG_GET_SIZE(uop->src_reg_a_real); - return 0; -} -static int codegen_JMP_DEST(codeblock_t *block, uop_t *uop) -{ - uop->p = host_x86_JMP_long(block); - - return 0; -} - -static int codegen_LOAD_FUNC_ARG0(codeblock_t *block, uop_t *uop) -{ - int src_reg = HOST_REG_GET(uop->src_reg_a_real); - int src_size = IREG_GET_SIZE(uop->src_reg_a_real); - - if (REG_IS_W(src_size)) - { - host_x86_MOV16_STACK_REG(block, STACK_ARG0, src_reg); - } -#ifdef RECOMPILER_DEBUG - else - fatal("codegen_LOAD_FUNC_ARG0 %02x\n", uop->src_reg_a_real); -#endif - return 0; -} -static int codegen_LOAD_FUNC_ARG1(codeblock_t *block, uop_t *uop) -{ -#ifdef RECOMPILER_DEBUG - fatal("codegen_LOAD_FUNC_ARG1 %02x\n", uop->src_reg_a_real); -#endif - return 0; -} -static int codegen_LOAD_FUNC_ARG2(codeblock_t *block, uop_t *uop) -{ -#ifdef RECOMPILER_DEBUG - fatal("codegen_LOAD_FUNC_ARG2 %02x\n", uop->src_reg_a_real); -#endif - return 0; -} -static int codegen_LOAD_FUNC_ARG3(codeblock_t *block, uop_t *uop) -{ -#ifdef RECOMPILER_DEBUG - fatal("codegen_LOAD_FUNC_ARG3 %02x\n", uop->src_reg_a_real); -#endif - return 0; -} - -static int codegen_LOAD_FUNC_ARG0_IMM(codeblock_t *block, uop_t *uop) -{ - host_x86_MOV32_STACK_IMM(block, STACK_ARG0, uop->imm_data); - return 0; -} -static int codegen_LOAD_FUNC_ARG1_IMM(codeblock_t *block, uop_t *uop) -{ - host_x86_MOV32_STACK_IMM(block, STACK_ARG1, uop->imm_data); - return 0; -} -static int codegen_LOAD_FUNC_ARG2_IMM(codeblock_t *block, uop_t *uop) -{ - host_x86_MOV32_STACK_IMM(block, STACK_ARG2, uop->imm_data); - return 0; -} -static int codegen_LOAD_FUNC_ARG3_IMM(codeblock_t *block, uop_t *uop) -{ - host_x86_MOV32_STACK_IMM(block, STACK_ARG3, uop->imm_data); - return 0; -} - -static int codegen_LOAD_SEG(codeblock_t *block, uop_t *uop) -{ - int src_reg = HOST_REG_GET(uop->src_reg_a_real); -#ifdef RECOMPILER_DEBUG - int src_size = IREG_GET_SIZE(uop->src_reg_a_real); - - if (!REG_IS_W(src_size)) - fatal("LOAD_SEG %02x %p\n", uop->src_reg_a_real, uop->p); -#endif + if (REG_IS_W(src_size)) { host_x86_MOV16_STACK_REG(block, STACK_ARG0, src_reg); - host_x86_MOV32_STACK_IMM(block, STACK_ARG1, (uint32_t)uop->p); - host_x86_CALL(block, loadseg); - host_x86_TEST32_REG(block, REG_EAX, REG_EAX); - host_x86_JNZ(block, codegen_exit_rout); - - return 0; + } +# ifdef RECOMPILER_DEBUG + else + fatal("codegen_LOAD_FUNC_ARG0 %02x\n", uop->src_reg_a_real); +# endif + return 0; +} +static int +codegen_LOAD_FUNC_ARG1(UNUSED(codeblock_t *block), UNUSED(uop_t *uop)) +{ +# ifdef RECOMPILER_DEBUG + fatal("codegen_LOAD_FUNC_ARG1 %02x\n", uop->src_reg_a_real); +# endif + return 0; +} +static int +codegen_LOAD_FUNC_ARG2(UNUSED(codeblock_t *block), UNUSED(uop_t *uop)) +{ +# ifdef RECOMPILER_DEBUG + fatal("codegen_LOAD_FUNC_ARG2 %02x\n", uop->src_reg_a_real); +# endif + return 0; +} +static int +codegen_LOAD_FUNC_ARG3(UNUSED(codeblock_t *block), UNUSED(uop_t *uop)) +{ +# ifdef RECOMPILER_DEBUG + fatal("codegen_LOAD_FUNC_ARG3 %02x\n", uop->src_reg_a_real); +# endif + return 0; } -static int codegen_MEM_LOAD_ABS(codeblock_t *block, uop_t *uop) +static int +codegen_LOAD_FUNC_ARG0_IMM(codeblock_t *block, uop_t *uop) { - int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), seg_reg = HOST_REG_GET(uop->src_reg_a_real); - int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real); - - host_x86_LEA_REG_IMM(block, REG_ESI, seg_reg, uop->imm_data); - if (REG_IS_B(dest_size)) - { - host_x86_CALL(block, codegen_mem_load_byte); - } - else if (REG_IS_W(dest_size)) - { - host_x86_CALL(block, codegen_mem_load_word); - } - else if (REG_IS_L(dest_size)) - { - host_x86_CALL(block, codegen_mem_load_long); - } -#ifdef RECOMPILER_DEBUG - else - fatal("MEM_LOAD_ABS - %02x\n", uop->dest_reg_a_real); -#endif - host_x86_TEST32_REG(block, REG_ESI, REG_ESI); - host_x86_JNZ(block, codegen_exit_rout); - if (REG_IS_B(dest_size)) - { - host_x86_MOV8_REG_REG(block, dest_reg, REG_ECX); - } - else if (REG_IS_W(dest_size)) - { - host_x86_MOV16_REG_REG(block, dest_reg, REG_ECX); - } - else if (REG_IS_L(dest_size)) - { - host_x86_MOV32_REG_REG(block, dest_reg, REG_ECX); - } - - return 0; + host_x86_MOV32_STACK_IMM(block, STACK_ARG0, uop->imm_data); + return 0; } -static int codegen_MEM_LOAD_REG(codeblock_t *block, uop_t *uop) +static int +codegen_LOAD_FUNC_ARG1_IMM(codeblock_t *block, uop_t *uop) { - int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), seg_reg = HOST_REG_GET(uop->src_reg_a_real), addr_reg = HOST_REG_GET(uop->src_reg_b_real); - int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real); - - host_x86_LEA_REG_REG(block, REG_ESI, seg_reg, addr_reg); - if (uop->imm_data) - host_x86_ADD32_REG_IMM(block, REG_ESI, uop->imm_data); - if (REG_IS_B(dest_size)) - { - host_x86_CALL(block, codegen_mem_load_byte); - } - else if (REG_IS_W(dest_size)) - { - host_x86_CALL(block, codegen_mem_load_word); - } - else if (REG_IS_L(dest_size)) - { - host_x86_CALL(block, codegen_mem_load_long); - } - else if (REG_IS_Q(dest_size)) - { - host_x86_CALL(block, codegen_mem_load_quad); - } -#ifdef RECOMPILER_DEBUG - else - fatal("MEM_LOAD_REG - %02x\n", uop->dest_reg_a_real); -#endif - host_x86_TEST32_REG(block, REG_ESI, REG_ESI); - host_x86_JNZ(block, codegen_exit_rout); - if (REG_IS_B(dest_size)) - { - host_x86_MOV8_REG_REG(block, dest_reg, REG_ECX); - } - else if (REG_IS_W(dest_size)) - { - host_x86_MOV16_REG_REG(block, dest_reg, REG_ECX); - } - else if (REG_IS_L(dest_size)) - { - host_x86_MOV32_REG_REG(block, dest_reg, REG_ECX); - } - else if (REG_IS_Q(dest_size)) - { - host_x86_MOVQ_XREG_XREG(block, dest_reg, REG_XMM_TEMP); - } - - return 0; + host_x86_MOV32_STACK_IMM(block, STACK_ARG1, uop->imm_data); + return 0; } -static int codegen_MEM_LOAD_SINGLE(codeblock_t *block, uop_t *uop) +static int +codegen_LOAD_FUNC_ARG2_IMM(codeblock_t *block, uop_t *uop) { - int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), seg_reg = HOST_REG_GET(uop->src_reg_a_real), addr_reg = HOST_REG_GET(uop->src_reg_b_real); -#ifdef RECOMPILER_DEBUG - int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real); + host_x86_MOV32_STACK_IMM(block, STACK_ARG2, uop->imm_data); + return 0; +} +static int +codegen_LOAD_FUNC_ARG3_IMM(codeblock_t *block, uop_t *uop) +{ + host_x86_MOV32_STACK_IMM(block, STACK_ARG3, uop->imm_data); + return 0; +} - if (!REG_IS_D(dest_size)) - fatal("MEM_LOAD_SINGLE - %02x\n", uop->dest_reg_a_real); -#endif - host_x86_LEA_REG_REG(block, REG_ESI, seg_reg, addr_reg); - if (uop->imm_data) - host_x86_ADD32_REG_IMM(block, REG_ESI, uop->imm_data); - host_x86_CALL(block, codegen_mem_load_single); - host_x86_TEST32_REG(block, REG_ESI, REG_ESI); - host_x86_JNZ(block, codegen_exit_rout); +static int +codegen_LOAD_SEG(codeblock_t *block, uop_t *uop) +{ + int src_reg = HOST_REG_GET(uop->src_reg_a_real); +# ifdef RECOMPILER_DEBUG + int src_size = IREG_GET_SIZE(uop->src_reg_a_real); + + if (!REG_IS_W(src_size)) + fatal("LOAD_SEG %02x %p\n", uop->src_reg_a_real, uop->p); +# endif + host_x86_MOV16_STACK_REG(block, STACK_ARG0, src_reg); + host_x86_MOV32_STACK_IMM(block, STACK_ARG1, (uint32_t) uop->p); + host_x86_CALL(block, loadseg); + host_x86_TEST32_REG(block, REG_EAX, REG_EAX); + host_x86_JNZ(block, codegen_exit_rout); + + return 0; +} + +static int +codegen_MEM_LOAD_ABS(codeblock_t *block, uop_t *uop) +{ + int dest_reg = HOST_REG_GET(uop->dest_reg_a_real); + int seg_reg = HOST_REG_GET(uop->src_reg_a_real); + int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real); + + host_x86_LEA_REG_IMM(block, REG_ESI, seg_reg, uop->imm_data); + if (REG_IS_B(dest_size)) { + host_x86_CALL(block, codegen_mem_load_byte); + } else if (REG_IS_W(dest_size)) { + host_x86_CALL(block, codegen_mem_load_word); + } else if (REG_IS_L(dest_size)) { + host_x86_CALL(block, codegen_mem_load_long); + } +# ifdef RECOMPILER_DEBUG + else + fatal("MEM_LOAD_ABS - %02x\n", uop->dest_reg_a_real); +# endif + host_x86_TEST32_REG(block, REG_ESI, REG_ESI); + host_x86_JNZ(block, codegen_exit_rout); + if (REG_IS_B(dest_size)) { + host_x86_MOV8_REG_REG(block, dest_reg, REG_ECX); + } else if (REG_IS_W(dest_size)) { + host_x86_MOV16_REG_REG(block, dest_reg, REG_ECX); + } else if (REG_IS_L(dest_size)) { + host_x86_MOV32_REG_REG(block, dest_reg, REG_ECX); + } + + return 0; +} +static int +codegen_MEM_LOAD_REG(codeblock_t *block, uop_t *uop) +{ + int dest_reg = HOST_REG_GET(uop->dest_reg_a_real); + int seg_reg = HOST_REG_GET(uop->src_reg_a_real); + int addr_reg = HOST_REG_GET(uop->src_reg_b_real); + int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real); + + host_x86_LEA_REG_REG(block, REG_ESI, seg_reg, addr_reg); + if (uop->imm_data) + host_x86_ADD32_REG_IMM(block, REG_ESI, uop->imm_data); + if (REG_IS_B(dest_size)) { + host_x86_CALL(block, codegen_mem_load_byte); + } else if (REG_IS_W(dest_size)) { + host_x86_CALL(block, codegen_mem_load_word); + } else if (REG_IS_L(dest_size)) { + host_x86_CALL(block, codegen_mem_load_long); + } else if (REG_IS_Q(dest_size)) { + host_x86_CALL(block, codegen_mem_load_quad); + } +# ifdef RECOMPILER_DEBUG + else + fatal("MEM_LOAD_REG - %02x\n", uop->dest_reg_a_real); +# endif + host_x86_TEST32_REG(block, REG_ESI, REG_ESI); + host_x86_JNZ(block, codegen_exit_rout); + if (REG_IS_B(dest_size)) { + host_x86_MOV8_REG_REG(block, dest_reg, REG_ECX); + } else if (REG_IS_W(dest_size)) { + host_x86_MOV16_REG_REG(block, dest_reg, REG_ECX); + } else if (REG_IS_L(dest_size)) { + host_x86_MOV32_REG_REG(block, dest_reg, REG_ECX); + } else if (REG_IS_Q(dest_size)) { host_x86_MOVQ_XREG_XREG(block, dest_reg, REG_XMM_TEMP); + } - return 0; + return 0; +} +static int +codegen_MEM_LOAD_SINGLE(codeblock_t *block, uop_t *uop) +{ + int dest_reg = HOST_REG_GET(uop->dest_reg_a_real); + int seg_reg = HOST_REG_GET(uop->src_reg_a_real); + int addr_reg = HOST_REG_GET(uop->src_reg_b_real); +# ifdef RECOMPILER_DEBUG + int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real); + + if (!REG_IS_D(dest_size)) + fatal("MEM_LOAD_SINGLE - %02x\n", uop->dest_reg_a_real); +# endif + host_x86_LEA_REG_REG(block, REG_ESI, seg_reg, addr_reg); + if (uop->imm_data) + host_x86_ADD32_REG_IMM(block, REG_ESI, uop->imm_data); + host_x86_CALL(block, codegen_mem_load_single); + host_x86_TEST32_REG(block, REG_ESI, REG_ESI); + host_x86_JNZ(block, codegen_exit_rout); + host_x86_MOVQ_XREG_XREG(block, dest_reg, REG_XMM_TEMP); + + return 0; } -static int codegen_MEM_LOAD_DOUBLE(codeblock_t *block, uop_t *uop) +static int +codegen_MEM_LOAD_DOUBLE(codeblock_t *block, uop_t *uop) { - int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), seg_reg = HOST_REG_GET(uop->src_reg_a_real), addr_reg = HOST_REG_GET(uop->src_reg_b_real); -#ifdef RECOMPILER_DEBUG - int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real); + int dest_reg = HOST_REG_GET(uop->dest_reg_a_real); + int seg_reg = HOST_REG_GET(uop->src_reg_a_real); + int addr_reg = HOST_REG_GET(uop->src_reg_b_real); +# ifdef RECOMPILER_DEBUG + int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real); - if (!REG_IS_D(dest_size)) - fatal("MEM_LOAD_DOUBLE - %02x\n", uop->dest_reg_a_real); -#endif - host_x86_LEA_REG_REG(block, REG_ESI, seg_reg, addr_reg); - if (uop->imm_data) - host_x86_ADD32_REG_IMM(block, REG_ESI, uop->imm_data); - host_x86_CALL(block, codegen_mem_load_double); - host_x86_TEST32_REG(block, REG_ESI, REG_ESI); - host_x86_JNZ(block, codegen_exit_rout); - host_x86_MOVQ_XREG_XREG(block, dest_reg, REG_XMM_TEMP); - - return 0; + if (!REG_IS_D(dest_size)) + fatal("MEM_LOAD_DOUBLE - %02x\n", uop->dest_reg_a_real); +# endif + host_x86_LEA_REG_REG(block, REG_ESI, seg_reg, addr_reg); + if (uop->imm_data) + host_x86_ADD32_REG_IMM(block, REG_ESI, uop->imm_data); + host_x86_CALL(block, codegen_mem_load_double); + host_x86_TEST32_REG(block, REG_ESI, REG_ESI); + host_x86_JNZ(block, codegen_exit_rout); + host_x86_MOVQ_XREG_XREG(block, dest_reg, REG_XMM_TEMP); + + return 0; } -static int codegen_MEM_STORE_ABS(codeblock_t *block, uop_t *uop) +static int +codegen_MEM_STORE_ABS(codeblock_t *block, uop_t *uop) { - int seg_reg = HOST_REG_GET(uop->src_reg_a_real), src_reg = HOST_REG_GET(uop->src_reg_b_real); - int src_size = IREG_GET_SIZE(uop->src_reg_b_real); + int seg_reg = HOST_REG_GET(uop->src_reg_a_real); + int src_reg = HOST_REG_GET(uop->src_reg_b_real); + int src_size = IREG_GET_SIZE(uop->src_reg_b_real); - host_x86_LEA_REG_IMM(block, REG_ESI, seg_reg, uop->imm_data); - if (REG_IS_B(src_size)) - { - host_x86_MOV8_REG_REG(block, REG_ECX, src_reg); - host_x86_CALL(block, codegen_mem_store_byte); - } - else if (REG_IS_W(src_size)) - { - host_x86_MOV16_REG_REG(block, REG_ECX, src_reg); - host_x86_CALL(block, codegen_mem_store_word); - } - else if (REG_IS_L(src_size)) - { - host_x86_MOV32_REG_REG(block, REG_ECX, src_reg); - host_x86_CALL(block, codegen_mem_store_long); - } -#ifdef RECOMPILER_DEBUG - else - fatal("MEM_STORE_ABS - %02x\n", uop->src_reg_b_real); -#endif - host_x86_TEST32_REG(block, REG_ESI, REG_ESI); - host_x86_JNZ(block, codegen_exit_rout); - - return 0; -} - -static int codegen_MEM_STORE_REG(codeblock_t *block, uop_t *uop) -{ - int seg_reg = HOST_REG_GET(uop->src_reg_a_real), addr_reg = HOST_REG_GET(uop->src_reg_b_real), src_reg = HOST_REG_GET(uop->src_reg_c_real); - int src_size = IREG_GET_SIZE(uop->src_reg_c_real); - - host_x86_LEA_REG_REG(block, REG_ESI, seg_reg, addr_reg); - if (uop->imm_data) - host_x86_ADD32_REG_IMM(block, REG_ESI, uop->imm_data); - if (REG_IS_B(src_size)) - { - host_x86_MOV8_REG_REG(block, REG_ECX, src_reg); - host_x86_CALL(block, codegen_mem_store_byte); - } - else if (REG_IS_W(src_size)) - { - host_x86_MOV16_REG_REG(block, REG_ECX, src_reg); - host_x86_CALL(block, codegen_mem_store_word); - } - else if (REG_IS_L(src_size)) - { - host_x86_MOV32_REG_REG(block, REG_ECX, src_reg); - host_x86_CALL(block, codegen_mem_store_long); - } - else if (REG_IS_Q(src_size)) - { - host_x86_MOVQ_XREG_XREG(block, REG_XMM_TEMP, src_reg); - host_x86_CALL(block, codegen_mem_store_quad); - } -#ifdef RECOMPILER_DEBUG - else - fatal("MEM_STORE_REG - %02x\n", uop->src_reg_b_real); -#endif - host_x86_TEST32_REG(block, REG_ESI, REG_ESI); - host_x86_JNZ(block, codegen_exit_rout); - - return 0; -} - -static int codegen_MEM_STORE_IMM_8(codeblock_t *block, uop_t *uop) -{ - int seg_reg = HOST_REG_GET(uop->src_reg_a_real), addr_reg = HOST_REG_GET(uop->src_reg_b_real); - - host_x86_LEA_REG_REG(block, REG_ESI, seg_reg, addr_reg); - host_x86_MOV8_REG_IMM(block, REG_ECX, uop->imm_data); + host_x86_LEA_REG_IMM(block, REG_ESI, seg_reg, uop->imm_data); + if (REG_IS_B(src_size)) { + host_x86_MOV8_REG_REG(block, REG_ECX, src_reg); host_x86_CALL(block, codegen_mem_store_byte); - host_x86_TEST32_REG(block, REG_ESI, REG_ESI); - host_x86_JNZ(block, codegen_exit_rout); - - return 0; -} -static int codegen_MEM_STORE_IMM_16(codeblock_t *block, uop_t *uop) -{ - int seg_reg = HOST_REG_GET(uop->src_reg_a_real), addr_reg = HOST_REG_GET(uop->src_reg_b_real); - - host_x86_LEA_REG_REG(block, REG_ESI, seg_reg, addr_reg); - host_x86_MOV16_REG_IMM(block, REG_ECX, uop->imm_data); + } else if (REG_IS_W(src_size)) { + host_x86_MOV16_REG_REG(block, REG_ECX, src_reg); host_x86_CALL(block, codegen_mem_store_word); - host_x86_TEST32_REG(block, REG_ESI, REG_ESI); - host_x86_JNZ(block, codegen_exit_rout); - - return 0; -} -static int codegen_MEM_STORE_IMM_32(codeblock_t *block, uop_t *uop) -{ - int seg_reg = HOST_REG_GET(uop->src_reg_a_real), addr_reg = HOST_REG_GET(uop->src_reg_b_real); - - host_x86_LEA_REG_REG(block, REG_ESI, seg_reg, addr_reg); - host_x86_MOV32_REG_IMM(block, REG_ECX, uop->imm_data); + } else if (REG_IS_L(src_size)) { + host_x86_MOV32_REG_REG(block, REG_ECX, src_reg); host_x86_CALL(block, codegen_mem_store_long); - host_x86_TEST32_REG(block, REG_ESI, REG_ESI); - host_x86_JNZ(block, codegen_exit_rout); + } +# ifdef RECOMPILER_DEBUG + else + fatal("MEM_STORE_ABS - %02x\n", uop->src_reg_b_real); +# endif + host_x86_TEST32_REG(block, REG_ESI, REG_ESI); + host_x86_JNZ(block, codegen_exit_rout); - return 0; + return 0; } -static int codegen_MEM_STORE_SINGLE(codeblock_t *block, uop_t *uop) +static int +codegen_MEM_STORE_REG(codeblock_t *block, uop_t *uop) { - int seg_reg = HOST_REG_GET(uop->src_reg_a_real), addr_reg = HOST_REG_GET(uop->src_reg_b_real), src_reg = HOST_REG_GET(uop->src_reg_c_real); -#ifdef RECOMPILER_DEBUG - int src_size = IREG_GET_SIZE(uop->src_reg_c_real); + int seg_reg = HOST_REG_GET(uop->src_reg_a_real); + int addr_reg = HOST_REG_GET(uop->src_reg_b_real); + int src_reg = HOST_REG_GET(uop->src_reg_c_real); + int src_size = IREG_GET_SIZE(uop->src_reg_c_real); - if (!REG_IS_D(src_size)) - fatal("MEM_STORE_SINGLE - %02x\n", uop->src_reg_b_real); -#endif - host_x86_LEA_REG_REG(block, REG_ESI, seg_reg, addr_reg); - if (uop->imm_data) - host_x86_ADD32_REG_IMM(block, REG_ESI, uop->imm_data); - host_x86_CVTSD2SS_XREG_XREG(block, REG_XMM_TEMP, src_reg); - host_x86_CALL(block, codegen_mem_store_single); - host_x86_TEST32_REG(block, REG_ESI, REG_ESI); - host_x86_JNZ(block, codegen_exit_rout); - - return 0; -} -static int codegen_MEM_STORE_DOUBLE(codeblock_t *block, uop_t *uop) -{ - int seg_reg = HOST_REG_GET(uop->src_reg_a_real), addr_reg = HOST_REG_GET(uop->src_reg_b_real), src_reg = HOST_REG_GET(uop->src_reg_c_real); -#ifdef RECOMPILER_DEBUG - int src_size = IREG_GET_SIZE(uop->src_reg_c_real); - - if (!REG_IS_D(src_size)) - fatal("MEM_STORE_DOUBLE - %02x\n", uop->src_reg_b_real); -#endif - host_x86_LEA_REG_REG(block, REG_ESI, seg_reg, addr_reg); - if (uop->imm_data) - host_x86_ADD32_REG_IMM(block, REG_ESI, uop->imm_data); + host_x86_LEA_REG_REG(block, REG_ESI, seg_reg, addr_reg); + if (uop->imm_data) + host_x86_ADD32_REG_IMM(block, REG_ESI, uop->imm_data); + if (REG_IS_B(src_size)) { + host_x86_MOV8_REG_REG(block, REG_ECX, src_reg); + host_x86_CALL(block, codegen_mem_store_byte); + } else if (REG_IS_W(src_size)) { + host_x86_MOV16_REG_REG(block, REG_ECX, src_reg); + host_x86_CALL(block, codegen_mem_store_word); + } else if (REG_IS_L(src_size)) { + host_x86_MOV32_REG_REG(block, REG_ECX, src_reg); + host_x86_CALL(block, codegen_mem_store_long); + } else if (REG_IS_Q(src_size)) { host_x86_MOVQ_XREG_XREG(block, REG_XMM_TEMP, src_reg); - host_x86_CALL(block, codegen_mem_store_double); - host_x86_TEST32_REG(block, REG_ESI, REG_ESI); - host_x86_JNZ(block, codegen_exit_rout); - - return 0; -} - -static int codegen_MOV(codeblock_t *block, uop_t *uop) -{ - int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg = HOST_REG_GET(uop->src_reg_a_real); - int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size = IREG_GET_SIZE(uop->src_reg_a_real); - - if (REG_IS_L(dest_size) && REG_IS_L(src_size)) - { - host_x86_MOV32_REG_REG(block, dest_reg, src_reg); - } - else if (REG_IS_W(dest_size) && REG_IS_W(src_size)) - { - host_x86_MOV16_REG_REG(block, dest_reg, src_reg); - } - else if (REG_IS_B(dest_size) && REG_IS_B(src_size)) - { - host_x86_MOV8_REG_REG(block, dest_reg, src_reg); - } - else if (REG_IS_D(dest_size) && REG_IS_D(src_size)) - { - host_x86_MOVQ_XREG_XREG(block, dest_reg, src_reg); - } - else if (REG_IS_Q(dest_size) && REG_IS_Q(src_size)) - { - host_x86_MOVQ_XREG_XREG(block, dest_reg, src_reg); - } -#ifdef RECOMPILER_DEBUG - else - fatal("MOV %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real); -#endif - return 0; -} -static int codegen_MOV_IMM(codeblock_t *block, uop_t *uop) -{ - int dest_reg = HOST_REG_GET(uop->dest_reg_a_real); - int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real); - - if (REG_IS_L(dest_size)) - { - host_x86_MOV32_REG_IMM(block, dest_reg, uop->imm_data); - } - else if (REG_IS_W(dest_size)) - { - host_x86_MOV16_REG_IMM(block, dest_reg, uop->imm_data); - } - else if (REG_IS_B(dest_size)) - { - host_x86_MOV8_REG_IMM(block, dest_reg, uop->imm_data); - } -#ifdef RECOMPILER_DEBUG - else - fatal("MOV_IMM %02x\n", uop->dest_reg_a_real); -#endif - return 0; -} -static int codegen_MOV_PTR(codeblock_t *block, uop_t *uop) -{ - host_x86_MOV32_REG_IMM(block, uop->dest_reg_a_real, (uint32_t)uop->p); - return 0; -} -static int codegen_MOV_REG_PTR(codeblock_t *block, uop_t *uop) -{ - int dest_reg = HOST_REG_GET(uop->dest_reg_a_real); - int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real); - - if (REG_IS_L(dest_size)) - { - host_x86_MOV32_REG_ABS(block, dest_reg, uop->p); - } - else - fatal("MOV_REG_PTR %02x\n", uop->dest_reg_a_real); - - return 0; -} -static int codegen_MOVZX_REG_PTR_8(codeblock_t *block, uop_t *uop) -{ - int dest_reg = HOST_REG_GET(uop->dest_reg_a_real); - int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real); - - if (REG_IS_L(dest_size)) - { - host_x86_MOVZX_REG_ABS_32_8(block, dest_reg, uop->p); - } - else if (REG_IS_W(dest_size)) - { - host_x86_MOVZX_REG_ABS_16_8(block, dest_reg, uop->p); - } - else if (REG_IS_B(dest_size)) - { - host_x86_MOV8_REG_ABS(block, dest_reg, uop->p); - } - else - fatal("MOVZX_REG_PTR_8 %02x\n", uop->dest_reg_a_real); - - return 0; -} -static int codegen_MOVZX_REG_PTR_16(codeblock_t *block, uop_t *uop) -{ - int dest_reg = HOST_REG_GET(uop->dest_reg_a_real); - int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real); - - if (REG_IS_L(dest_size)) - { - host_x86_MOVZX_REG_ABS_32_16(block, dest_reg, uop->p); - } - else if (REG_IS_W(dest_size)) - { - host_x86_MOV16_REG_ABS(block, dest_reg, uop->p); - } - else - fatal("MOVZX_REG_PTR_16 %02x\n", uop->dest_reg_a_real); - - return 0; -} -static int codegen_MOVSX(codeblock_t *block, uop_t *uop) -{ - int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg = HOST_REG_GET(uop->src_reg_a_real); - int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size = IREG_GET_SIZE(uop->src_reg_a_real); - - if (REG_IS_L(dest_size) && REG_IS_W(src_size)) - { - host_x86_MOVSX_REG_32_16(block, dest_reg, src_reg); - } - else if (REG_IS_L(dest_size) && REG_IS_B(src_size)) - { - host_x86_MOVSX_REG_32_8(block, dest_reg, src_reg); - } - else if (REG_IS_W(dest_size) && REG_IS_B(src_size)) - { - host_x86_MOVSX_REG_16_8(block, dest_reg, src_reg); - } -#ifdef RECOMPILER_DEBUG - else - fatal("MOVSX %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real); -#endif - return 0; -} -static int codegen_MOVZX(codeblock_t *block, uop_t *uop) -{ - int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg = HOST_REG_GET(uop->src_reg_a_real); - int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size = IREG_GET_SIZE(uop->src_reg_a_real); - - if (REG_IS_Q(dest_size) && REG_IS_L(src_size)) - { - host_x86_MOVD_XREG_REG(block, dest_reg, src_reg); - } - else if (REG_IS_L(dest_size) && REG_IS_Q(src_size)) - { - host_x86_MOVD_REG_XREG(block, dest_reg, src_reg); - } - else if (REG_IS_L(dest_size) && REG_IS_W(src_size)) - { - host_x86_MOVZX_REG_32_16(block, dest_reg, src_reg); - } - else if (REG_IS_L(dest_size) && REG_IS_B(src_size)) - { - host_x86_MOVZX_REG_32_8(block, dest_reg, src_reg); - } - else if (REG_IS_W(dest_size) && REG_IS_B(src_size)) - { - host_x86_MOVZX_REG_16_8(block, dest_reg, src_reg); - } -#ifdef RECOMPILER_DEBUG - else - fatal("MOVZX %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real); -#endif - return 0; -} - -static int codegen_MOV_DOUBLE_INT(codeblock_t *block, uop_t *uop) -{ - int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg = HOST_REG_GET(uop->src_reg_a_real); - int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size = IREG_GET_SIZE(uop->src_reg_a_real); - - if (REG_IS_D(dest_size) && REG_IS_L(src_size)) - { - host_x86_CVTSI2SD_XREG_REG(block, dest_reg, src_reg); - } - else if (REG_IS_D(dest_size) && REG_IS_W(src_size)) - { - host_x86_MOVSX_REG_32_16(block, REG_ECX, src_reg); - host_x86_CVTSI2SD_XREG_REG(block, dest_reg, REG_ECX); - } - else if (REG_IS_D(dest_size) && REG_IS_Q(src_size)) - { - /*There is no SSE instruction to convert a 64-bit integer to a floating point value. - Instead we have to bounce the integer through memory via x87.*/ - host_x86_MOVQ_BASE_OFFSET_XREG(block, REG_ESP, 0, src_reg); - host_x87_FILDq_BASE(block, REG_ESP); - host_x87_FSTPd_BASE(block, REG_ESP); - host_x86_MOVQ_XREG_BASE_OFFSET(block, dest_reg, REG_ESP, 0); - } -#ifdef RECOMPILER_DEBUG - else - fatal("MOV_DOUBLE_INT %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real); -#endif - return 0; -} -static int codegen_MOV_INT_DOUBLE(codeblock_t *block, uop_t *uop) -{ - int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg = HOST_REG_GET(uop->src_reg_a_real); - int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size = IREG_GET_SIZE(uop->src_reg_a_real); - - if (REG_IS_L(dest_size) && REG_IS_D(src_size)) - { - host_x86_LDMXCSR(block, &cpu_state.new_fp_control); - host_x86_CVTSD2SI_REG_XREG(block, dest_reg, src_reg); - host_x86_LDMXCSR(block, &cpu_state.old_fp_control); - } - else if (REG_IS_W(dest_size) && REG_IS_D(src_size)) - { - host_x86_LDMXCSR(block, &cpu_state.new_fp_control); - host_x86_CVTSD2SI_REG_XREG(block, REG_ECX, src_reg); - host_x86_MOV16_REG_REG(block, dest_reg, REG_ECX); - host_x86_LDMXCSR(block, &cpu_state.old_fp_control); - } -#ifdef RECOMPILER_DEBUG - else - fatal("MOV_INT_DOUBLE %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real); -#endif - return 0; -} - -static int codegen_MOV_INT_DOUBLE_64(codeblock_t *block, uop_t *uop) -{ - int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg = HOST_REG_GET(uop->src_reg_a_real), src_64_reg = HOST_REG_GET(uop->src_reg_b_real), tag_reg = HOST_REG_GET(uop->src_reg_c_real); - int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size = IREG_GET_SIZE(uop->src_reg_a_real), src_64_size = IREG_GET_SIZE(uop->src_reg_b_real); - - if (REG_IS_Q(dest_size) && REG_IS_D(src_size) && REG_IS_Q(src_64_size)) - { - uint32_t *branch_offset; - - /*If TAG_UINT64 is set then the source is MM[]. Otherwise it is a double in ST()*/ - host_x86_MOVQ_XREG_XREG(block, dest_reg, src_64_reg); - host_x86_TEST8_REG(block, tag_reg, tag_reg); - branch_offset = host_x86_JS_long(block); - - /*There is no SSE instruction to convert a floating point value to a 64-bit integer. - Instead we have to bounce through memory via x87.*/ - host_x87_FLDCW(block, &cpu_state.new_fp_control2); - host_x86_MOVQ_BASE_OFFSET_XREG(block, REG_ESP, 0, src_reg); - host_x87_FLDd_BASE(block, REG_ESP); - host_x87_FISTPq_BASE(block, REG_ESP); - host_x86_MOVQ_XREG_BASE_OFFSET(block, dest_reg, REG_ESP, 0); - host_x87_FLDCW(block, &cpu_state.old_fp_control2); - - *branch_offset = (uint32_t)((uintptr_t)&block_write_data[block_pos] - (uintptr_t)branch_offset) - 4; - } -#ifdef RECOMPILER_DEBUG - else - fatal("MOV_INT_DOUBLE_64 %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real); -#endif - return 0; -} - -static int codegen_NOP(codeblock_t *block, uop_t *uop) -{ - return 0; -} - -static int codegen_OR(codeblock_t *block, uop_t *uop) -{ - int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg_a = HOST_REG_GET(uop->src_reg_a_real), src_reg_b = HOST_REG_GET(uop->src_reg_b_real); - int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size_a = IREG_GET_SIZE(uop->src_reg_a_real), src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); - - if (REG_IS_Q(dest_size) && REG_IS_Q(src_size_a) && REG_IS_Q(src_size_b) && uop->dest_reg_a_real == uop->src_reg_a_real) - { - host_x86_POR_XREG_XREG(block, dest_reg, src_reg_b); - } - else if (REG_IS_L(dest_size) && REG_IS_L(src_size_a) && REG_IS_L(src_size_b)) - { - if (uop->dest_reg_a_real != uop->src_reg_a_real) - host_x86_MOV32_REG_REG(block, dest_reg, src_reg_a); - host_x86_OR32_REG_REG(block, dest_reg, src_reg_b); - } - else if (REG_IS_W(dest_size) && REG_IS_W(src_size_a) && REG_IS_W(src_size_b)) - { - if (uop->dest_reg_a_real != uop->src_reg_a_real) - host_x86_MOV16_REG_REG(block, dest_reg, src_reg_a); - host_x86_OR16_REG_REG(block, dest_reg, src_reg_b); - } - else if (REG_IS_B(dest_size) && REG_IS_B(src_size_a) && REG_IS_B(src_size_b)) - { - if (uop->dest_reg_a_real != uop->src_reg_a_real) - host_x86_MOV8_REG_REG(block, dest_reg, src_reg_a); - host_x86_OR8_REG_REG(block, dest_reg, src_reg_b); - } -#ifdef RECOMPILER_DEBUG - else - fatal("OR %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real); -#endif - return 0; -} -static int codegen_OR_IMM(codeblock_t *block, uop_t *uop) -{ - int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg = HOST_REG_GET(uop->src_reg_a_real); - int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real); - - if (REG_IS_L(dest_size) && dest_reg == src_reg) - { - host_x86_OR32_REG_IMM(block, dest_reg, uop->imm_data); - } - else if (REG_IS_W(dest_size) && dest_reg == src_reg) - { - host_x86_OR16_REG_IMM(block, dest_reg, uop->imm_data); - } - else if (REG_IS_B(dest_size) && dest_reg == src_reg) - { - host_x86_OR8_REG_IMM(block, dest_reg, uop->imm_data); - } -#ifdef RECOMPILER_DEBUG - else - fatal("OR_IMM %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real); -#endif - return 0; -} - -static int codegen_PACKSSWB(codeblock_t *block, uop_t *uop) -{ - int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg_b = HOST_REG_GET(uop->src_reg_b_real); - int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); - - if (REG_IS_Q(dest_size) && REG_IS_Q(src_size_b) && uop->dest_reg_a_real == uop->src_reg_a_real) - { - host_x86_PACKSSWB_XREG_XREG(block, dest_reg, src_reg_b); - } -#ifdef RECOMPILER_DEBUG - else - fatal("PACKSSWB %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real); -#endif - return 0; -} -static int codegen_PACKSSDW(codeblock_t *block, uop_t *uop) -{ - int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg_b = HOST_REG_GET(uop->src_reg_b_real); - int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); - - if (REG_IS_Q(dest_size) && REG_IS_Q(src_size_b) && uop->dest_reg_a_real == uop->src_reg_a_real) - { - host_x86_PACKSSDW_XREG_XREG(block, dest_reg, src_reg_b); - } -#ifdef RECOMPILER_DEBUG - else - fatal("PACKSSDW %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real); -#endif - return 0; -} -static int codegen_PACKUSWB(codeblock_t *block, uop_t *uop) -{ - int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg_b = HOST_REG_GET(uop->src_reg_b_real); - int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); - - if (REG_IS_Q(dest_size) && REG_IS_Q(src_size_b) && uop->dest_reg_a_real == uop->src_reg_a_real) - { - host_x86_PACKUSWB_XREG_XREG(block, dest_reg, src_reg_b); - } -#ifdef RECOMPILER_DEBUG - else - fatal("PACKUSWB %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real); -#endif - return 0; -} - -static int codegen_PADDB(codeblock_t *block, uop_t *uop) -{ - int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg_b = HOST_REG_GET(uop->src_reg_b_real); - int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); - - if (REG_IS_Q(dest_size) && REG_IS_Q(src_size_b) && uop->dest_reg_a_real == uop->src_reg_a_real) - { - host_x86_PADDB_XREG_XREG(block, dest_reg, src_reg_b); - } -#ifdef RECOMPILER_DEBUG - else - fatal("PADDB %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real); -#endif - return 0; -} -static int codegen_PADDW(codeblock_t *block, uop_t *uop) -{ - int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg_b = HOST_REG_GET(uop->src_reg_b_real); - int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); - - if (REG_IS_Q(dest_size) && REG_IS_Q(src_size_b) && uop->dest_reg_a_real == uop->src_reg_a_real) - { - host_x86_PADDW_XREG_XREG(block, dest_reg, src_reg_b); - } -#ifdef RECOMPILER_DEBUG - else - fatal("PADDW %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real); -#endif - return 0; -} -static int codegen_PADDD(codeblock_t *block, uop_t *uop) -{ - int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg_b = HOST_REG_GET(uop->src_reg_b_real); - int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); - - if (REG_IS_Q(dest_size) && REG_IS_Q(src_size_b) && uop->dest_reg_a_real == uop->src_reg_a_real) - { - host_x86_PADDD_XREG_XREG(block, dest_reg, src_reg_b); - } -#ifdef RECOMPILER_DEBUG - else - fatal("PADDD %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real); -#endif - return 0; -} -static int codegen_PADDSB(codeblock_t *block, uop_t *uop) -{ - int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg_b = HOST_REG_GET(uop->src_reg_b_real); - int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); - - if (REG_IS_Q(dest_size) && REG_IS_Q(src_size_b) && uop->dest_reg_a_real == uop->src_reg_a_real) - { - host_x86_PADDSB_XREG_XREG(block, dest_reg, src_reg_b); - } -#ifdef RECOMPILER_DEBUG - else - fatal("PADDSB %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real); -#endif - return 0; -} -static int codegen_PADDSW(codeblock_t *block, uop_t *uop) -{ - int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg_b = HOST_REG_GET(uop->src_reg_b_real); - int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); - - if (REG_IS_Q(dest_size) && REG_IS_Q(src_size_b) && uop->dest_reg_a_real == uop->src_reg_a_real) - { - host_x86_PADDSW_XREG_XREG(block, dest_reg, src_reg_b); - } -#ifdef RECOMPILER_DEBUG - else - fatal("PADDSW %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real); -#endif - return 0; -} -static int codegen_PADDUSB(codeblock_t *block, uop_t *uop) -{ - int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg_b = HOST_REG_GET(uop->src_reg_b_real); - int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); - - if (REG_IS_Q(dest_size) && REG_IS_Q(src_size_b) && uop->dest_reg_a_real == uop->src_reg_a_real) - { - host_x86_PADDUSB_XREG_XREG(block, dest_reg, src_reg_b); - } -#ifdef RECOMPILER_DEBUG - else - fatal("PADDUSB %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real); -#endif - return 0; -} -static int codegen_PADDUSW(codeblock_t *block, uop_t *uop) -{ - int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg_b = HOST_REG_GET(uop->src_reg_b_real); - int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); - - if (REG_IS_Q(dest_size) && REG_IS_Q(src_size_b) && uop->dest_reg_a_real == uop->src_reg_a_real) - { - host_x86_PADDUSW_XREG_XREG(block, dest_reg, src_reg_b); - } -#ifdef RECOMPILER_DEBUG - else - fatal("PADDUSW %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real); -#endif - return 0; -} - -static int codegen_PCMPEQB(codeblock_t *block, uop_t *uop) -{ - int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg_b = HOST_REG_GET(uop->src_reg_b_real); - int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); - - if (REG_IS_Q(dest_size) && REG_IS_Q(src_size_b) && uop->dest_reg_a_real == uop->src_reg_a_real) - { - host_x86_PCMPEQB_XREG_XREG(block, dest_reg, src_reg_b); - } -#ifdef RECOMPILER_DEBUG - else - fatal("PCMPEQB %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real); -#endif - return 0; -} -static int codegen_PCMPEQW(codeblock_t *block, uop_t *uop) -{ - int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg_b = HOST_REG_GET(uop->src_reg_b_real); - int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); - - if (REG_IS_Q(dest_size) && REG_IS_Q(src_size_b) && uop->dest_reg_a_real == uop->src_reg_a_real) - { - host_x86_PCMPEQW_XREG_XREG(block, dest_reg, src_reg_b); - } -#ifdef RECOMPILER_DEBUG - else - fatal("PCMPEQW %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real); -#endif - return 0; -} -static int codegen_PCMPEQD(codeblock_t *block, uop_t *uop) -{ - int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg_b = HOST_REG_GET(uop->src_reg_b_real); - int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); - - if (REG_IS_Q(dest_size) && REG_IS_Q(src_size_b) && uop->dest_reg_a_real == uop->src_reg_a_real) - { - host_x86_PCMPEQD_XREG_XREG(block, dest_reg, src_reg_b); - } -#ifdef RECOMPILER_DEBUG - else - fatal("PCMPEQD %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real); -#endif - return 0; -} -static int codegen_PCMPGTB(codeblock_t *block, uop_t *uop) -{ - int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg_b = HOST_REG_GET(uop->src_reg_b_real); - int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); - - if (REG_IS_Q(dest_size) && REG_IS_Q(src_size_b) && uop->dest_reg_a_real == uop->src_reg_a_real) - { - host_x86_PCMPGTB_XREG_XREG(block, dest_reg, src_reg_b); - } -#ifdef RECOMPILER_DEBUG - else - fatal("PCMPGTB %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real); -#endif - return 0; -} -static int codegen_PCMPGTW(codeblock_t *block, uop_t *uop) -{ - int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg_b = HOST_REG_GET(uop->src_reg_b_real); - int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); - - if (REG_IS_Q(dest_size) && REG_IS_Q(src_size_b) && uop->dest_reg_a_real == uop->src_reg_a_real) - { - host_x86_PCMPGTW_XREG_XREG(block, dest_reg, src_reg_b); - } -#ifdef RECOMPILER_DEBUG - else - fatal("PCMPGTW %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real); -#endif - return 0; -} -static int codegen_PCMPGTD(codeblock_t *block, uop_t *uop) -{ - int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg_b = HOST_REG_GET(uop->src_reg_b_real); - int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); - - if (REG_IS_Q(dest_size) && REG_IS_Q(src_size_b) && uop->dest_reg_a_real == uop->src_reg_a_real) - { - host_x86_PCMPGTD_XREG_XREG(block, dest_reg, src_reg_b); - } -#ifdef RECOMPILER_DEBUG - else - fatal("PCMPGTD %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real); -#endif - return 0; -} - -static int codegen_PF2ID(codeblock_t *block, uop_t *uop) -{ - int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg_a = HOST_REG_GET(uop->src_reg_a_real); - int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size_a = IREG_GET_SIZE(uop->src_reg_a_real); - - if (REG_IS_Q(dest_size) && REG_IS_Q(src_size_a)) - { - host_x86_LDMXCSR(block, &cpu_state.trunc_fp_control); - host_x86_CVTPS2DQ_XREG_XREG(block, dest_reg, src_reg_a); - host_x86_LDMXCSR(block, &cpu_state.old_fp_control); - } -#ifdef RECOMPILER_DEBUG - else - fatal("PF2ID %02x %02x\n", uop->dest_reg_a_real); -#endif - return 0; -} -static int codegen_PFADD(codeblock_t *block, uop_t *uop) -{ - int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg_b = HOST_REG_GET(uop->src_reg_b_real); - int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); - - if (REG_IS_Q(dest_size) && REG_IS_Q(src_size_b) && uop->dest_reg_a_real == uop->src_reg_a_real) - { - host_x86_ADDPS_XREG_XREG(block, dest_reg, src_reg_b); - } -#ifdef RECOMPILER_DEBUG - else - fatal("PFADD %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real); -#endif - return 0; -} -static int codegen_PFCMPEQ(codeblock_t *block, uop_t *uop) -{ - int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg_b = HOST_REG_GET(uop->src_reg_b_real); - int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); - - if (REG_IS_Q(dest_size) && REG_IS_Q(src_size_b) && uop->dest_reg_a_real == uop->src_reg_a_real) - { - host_x86_CMPPS_XREG_XREG(block, dest_reg, src_reg_b, CMPPS_EQ); - } -#ifdef RECOMPILER_DEBUG - else - fatal("PFCMPEQ %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real); -#endif - return 0; -} -static int codegen_PFCMPGE(codeblock_t *block, uop_t *uop) -{ - int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg_b = HOST_REG_GET(uop->src_reg_b_real); - int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); - - if (REG_IS_Q(dest_size) && REG_IS_Q(src_size_b) && uop->dest_reg_a_real == uop->src_reg_a_real) - { - host_x86_CMPPS_XREG_XREG(block, dest_reg, src_reg_b, CMPPS_NLT); - } -#ifdef RECOMPILER_DEBUG - else - fatal("PFCMPGE %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real); -#endif - return 0; -} -static int codegen_PFCMPGT(codeblock_t *block, uop_t *uop) -{ - int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg_b = HOST_REG_GET(uop->src_reg_b_real); - int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); - - if (REG_IS_Q(dest_size) && REG_IS_Q(src_size_b) && uop->dest_reg_a_real == uop->src_reg_a_real) - { - host_x86_CMPPS_XREG_XREG(block, dest_reg, src_reg_b, CMPPS_NLE); - } -#ifdef RECOMPILER_DEBUG - else - fatal("PFCMPGT %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real); -#endif - return 0; -} -static int codegen_PFMAX(codeblock_t *block, uop_t *uop) -{ - int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg_b = HOST_REG_GET(uop->src_reg_b_real); - int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); - - if (REG_IS_Q(dest_size) && REG_IS_Q(src_size_b) && uop->dest_reg_a_real == uop->src_reg_a_real) - { - host_x86_MAXPS_XREG_XREG(block, dest_reg, src_reg_b); - } -#ifdef RECOMPILER_DEBUG - else - fatal("PFMAX %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real); -#endif - return 0; -} -static int codegen_PFMIN(codeblock_t *block, uop_t *uop) -{ - int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg_b = HOST_REG_GET(uop->src_reg_b_real); - int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); - - if (REG_IS_Q(dest_size) && REG_IS_Q(src_size_b) && uop->dest_reg_a_real == uop->src_reg_a_real) - { - host_x86_MINPS_XREG_XREG(block, dest_reg, src_reg_b); - } -#ifdef RECOMPILER_DEBUG - else - fatal("PFMIN %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real); -#endif - return 0; -} -static int codegen_PFMUL(codeblock_t *block, uop_t *uop) -{ - int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg_b = HOST_REG_GET(uop->src_reg_b_real); - int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); - - if (REG_IS_Q(dest_size) && REG_IS_Q(src_size_b) && uop->dest_reg_a_real == uop->src_reg_a_real) - { - host_x86_MULPS_XREG_XREG(block, dest_reg, src_reg_b); - } -#ifdef RECOMPILER_DEBUG - else - fatal("PFMUL %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real); -#endif - return 0; -} -static int codegen_PFRCP(codeblock_t *block, uop_t *uop) -{ - int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg_a = HOST_REG_GET(uop->src_reg_a_real); - int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size_a = IREG_GET_SIZE(uop->src_reg_a_real); - - if (REG_IS_Q(dest_size) && REG_IS_Q(src_size_a)) - { - /*TODO: This could be improved (use RCPSS + iteration)*/ - host_x86_MOV32_REG_IMM(block, REG_ECX, 1); - host_x86_MOVQ_XREG_XREG(block, REG_XMM_TEMP, src_reg_a); - host_x86_CVTSI2SS_XREG_REG(block, dest_reg, REG_ECX); - host_x86_DIVSS_XREG_XREG(block, dest_reg, REG_XMM_TEMP); - host_x86_UNPCKLPS_XREG_XREG(block, dest_reg, dest_reg); - } -#ifdef RECOMPILER_DEBUG - else - fatal("PFRCP %02x %02x\n", uop->dest_reg_a_real); -#endif - return 0; -} -static int codegen_PFRSQRT(codeblock_t *block, uop_t *uop) -{ - int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg_a = HOST_REG_GET(uop->src_reg_a_real); - int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size_a = IREG_GET_SIZE(uop->src_reg_a_real); - - if (REG_IS_Q(dest_size) && REG_IS_Q(src_size_a)) - { - /*TODO: This could be improved (use RSQRTSS + iteration)*/ - host_x86_SQRTSS_XREG_XREG(block, REG_XMM_TEMP, src_reg_a); - host_x86_MOV32_REG_IMM(block, REG_ECX, 1); - host_x86_CVTSI2SS_XREG_REG(block, dest_reg, REG_ECX); - host_x86_DIVSS_XREG_XREG(block, dest_reg, REG_XMM_TEMP); - host_x86_UNPCKLPS_XREG_XREG(block, dest_reg, dest_reg); - } -#ifdef RECOMPILER_DEBUG - else - fatal("PFRSQRT %02x %02x\n", uop->dest_reg_a_real); -#endif - return 0; -} -static int codegen_PFSUB(codeblock_t *block, uop_t *uop) -{ - int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg_a = HOST_REG_GET(uop->src_reg_a_real), src_reg_b = HOST_REG_GET(uop->src_reg_b_real); - int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size_a = IREG_GET_SIZE(uop->src_reg_a_real), src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); - - if (REG_IS_Q(dest_size) && REG_IS_Q(src_size_b) && uop->dest_reg_a_real == uop->src_reg_a_real) - { - host_x86_SUBPS_XREG_XREG(block, dest_reg, src_reg_b); - } - else if (REG_IS_Q(dest_size) && REG_IS_Q(src_size_a) && REG_IS_Q(src_size_b)) - { - host_x86_MOVQ_XREG_XREG(block, REG_XMM_TEMP, src_reg_a); - host_x86_SUBPS_XREG_XREG(block, REG_XMM_TEMP, src_reg_b); - host_x86_MOVQ_XREG_XREG(block, dest_reg, REG_XMM_TEMP); - } -#ifdef RECOMPILER_DEBUG - else - fatal("PFSUB %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real); -#endif - return 0; -} -static int codegen_PI2FD(codeblock_t *block, uop_t *uop) -{ - int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg_a = HOST_REG_GET(uop->src_reg_a_real); - int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size_a = IREG_GET_SIZE(uop->src_reg_a_real); - - if (REG_IS_Q(dest_size) && REG_IS_Q(src_size_a)) - { - host_x86_CVTDQ2PS_XREG_XREG(block, dest_reg, src_reg_a); - } -#ifdef RECOMPILER_DEBUG - else - fatal("PI2FD %02x %02x\n", uop->dest_reg_a_real); -#endif - return 0; -} - -static int codegen_PMADDWD(codeblock_t *block, uop_t *uop) -{ - int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg_b = HOST_REG_GET(uop->src_reg_b_real); - int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); - - if (REG_IS_Q(dest_size) && REG_IS_Q(src_size_b) && uop->dest_reg_a_real == uop->src_reg_a_real) - { - host_x86_PMADDWD_XREG_XREG(block, dest_reg, src_reg_b); - } -#ifdef RECOMPILER_DEBUG - else - fatal("PMULHW %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real); -#endif - return 0; -} -static int codegen_PMULHW(codeblock_t *block, uop_t *uop) -{ - int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg_b = HOST_REG_GET(uop->src_reg_b_real); - int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); - - if (REG_IS_Q(dest_size) && REG_IS_Q(src_size_b) && uop->dest_reg_a_real == uop->src_reg_a_real) - { - host_x86_PMULHW_XREG_XREG(block, dest_reg, src_reg_b); - } -#ifdef RECOMPILER_DEBUG - else - fatal("PMULHW %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real); -#endif - return 0; -} -static int codegen_PMULLW(codeblock_t *block, uop_t *uop) -{ - int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg_b = HOST_REG_GET(uop->src_reg_b_real); - int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); - - if (REG_IS_Q(dest_size) && REG_IS_Q(src_size_b) && uop->dest_reg_a_real == uop->src_reg_a_real) - { - host_x86_PMULLW_XREG_XREG(block, dest_reg, src_reg_b); - } -#ifdef RECOMPILER_DEBUG - else - fatal("PMULLW %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real); -#endif - return 0; -} - -static int codegen_PSLLW_IMM(codeblock_t *block, uop_t *uop) -{ - int dest_reg = HOST_REG_GET(uop->dest_reg_a_real); - int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real); - - if (REG_IS_Q(dest_size) && uop->dest_reg_a_real == uop->src_reg_a_real) - { - host_x86_PSLLW_XREG_IMM(block, dest_reg, uop->imm_data); - } -#ifdef RECOMPILER_DEBUG - else - fatal("PSLLW_IMM %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real); -#endif - return 0; -} -static int codegen_PSLLD_IMM(codeblock_t *block, uop_t *uop) -{ - int dest_reg = HOST_REG_GET(uop->dest_reg_a_real); - int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real); - - if (REG_IS_Q(dest_size) && uop->dest_reg_a_real == uop->src_reg_a_real) - { - host_x86_PSLLD_XREG_IMM(block, dest_reg, uop->imm_data); - } -#ifdef RECOMPILER_DEBUG - else - fatal("PSLLD_IMM %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real); -#endif - return 0; -} -static int codegen_PSLLQ_IMM(codeblock_t *block, uop_t *uop) -{ - int dest_reg = HOST_REG_GET(uop->dest_reg_a_real); - int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real); - - if (REG_IS_Q(dest_size) && uop->dest_reg_a_real == uop->src_reg_a_real) - { - host_x86_PSLLQ_XREG_IMM(block, dest_reg, uop->imm_data); - } -#ifdef RECOMPILER_DEBUG - else - fatal("PSLLQ_IMM %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real); -#endif - return 0; -} -static int codegen_PSRAW_IMM(codeblock_t *block, uop_t *uop) -{ - int dest_reg = HOST_REG_GET(uop->dest_reg_a_real); - int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real); - - if (REG_IS_Q(dest_size) && uop->dest_reg_a_real == uop->src_reg_a_real) - { - host_x86_PSRAW_XREG_IMM(block, dest_reg, uop->imm_data); - } -#ifdef RECOMPILER_DEBUG - else - fatal("PSRAW_IMM %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real); -#endif - return 0; -} -static int codegen_PSRAD_IMM(codeblock_t *block, uop_t *uop) -{ - int dest_reg = HOST_REG_GET(uop->dest_reg_a_real); - int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real); - - if (REG_IS_Q(dest_size) && uop->dest_reg_a_real == uop->src_reg_a_real) - { - host_x86_PSRAD_XREG_IMM(block, dest_reg, uop->imm_data); - } -#ifdef RECOMPILER_DEBUG - else - fatal("PSRAD_IMM %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real); -#endif - return 0; -} -static int codegen_PSRAQ_IMM(codeblock_t *block, uop_t *uop) -{ - int dest_reg = HOST_REG_GET(uop->dest_reg_a_real); - int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real); - - if (REG_IS_Q(dest_size) && uop->dest_reg_a_real == uop->src_reg_a_real) - { - host_x86_PSRAQ_XREG_IMM(block, dest_reg, uop->imm_data); - } -#ifdef RECOMPILER_DEBUG - else - fatal("PSRAQ_IMM %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real); -#endif - return 0; -} -static int codegen_PSRLW_IMM(codeblock_t *block, uop_t *uop) -{ - int dest_reg = HOST_REG_GET(uop->dest_reg_a_real); - int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real); - - if (REG_IS_Q(dest_size) && uop->dest_reg_a_real == uop->src_reg_a_real) - { - host_x86_PSRLW_XREG_IMM(block, dest_reg, uop->imm_data); - } -#ifdef RECOMPILER_DEBUG - else - fatal("PSRLW_IMM %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real); -#endif - return 0; -} -static int codegen_PSRLD_IMM(codeblock_t *block, uop_t *uop) -{ - int dest_reg = HOST_REG_GET(uop->dest_reg_a_real); - int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real); - - if (REG_IS_Q(dest_size) && uop->dest_reg_a_real == uop->src_reg_a_real) - { - host_x86_PSRLD_XREG_IMM(block, dest_reg, uop->imm_data); - } -#ifdef RECOMPILER_DEBUG - else - fatal("PSRLD_IMM %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real); -#endif - return 0; -} -static int codegen_PSRLQ_IMM(codeblock_t *block, uop_t *uop) -{ - int dest_reg = HOST_REG_GET(uop->dest_reg_a_real); - int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real); - - if (REG_IS_Q(dest_size) && uop->dest_reg_a_real == uop->src_reg_a_real) - { - host_x86_PSRLQ_XREG_IMM(block, dest_reg, uop->imm_data); - } -#ifdef RECOMPILER_DEBUG - else - fatal("PSRLQ_IMM %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real); -#endif - return 0; -} - -static int codegen_PSUBB(codeblock_t *block, uop_t *uop) -{ - int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg_b = HOST_REG_GET(uop->src_reg_b_real); - int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); - - if (REG_IS_Q(dest_size) && REG_IS_Q(src_size_b) && uop->dest_reg_a_real == uop->src_reg_a_real) - { - host_x86_PSUBB_XREG_XREG(block, dest_reg, src_reg_b); - } -#ifdef RECOMPILER_DEBUG - else - fatal("PSUBB %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real); -#endif - return 0; -} -static int codegen_PSUBW(codeblock_t *block, uop_t *uop) -{ - int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg_b = HOST_REG_GET(uop->src_reg_b_real); - int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); - - if (REG_IS_Q(dest_size) && REG_IS_Q(src_size_b) && uop->dest_reg_a_real == uop->src_reg_a_real) - { - host_x86_PSUBW_XREG_XREG(block, dest_reg, src_reg_b); - } -#ifdef RECOMPILER_DEBUG - else - fatal("PSUBW %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real); -#endif - return 0; -} -static int codegen_PSUBD(codeblock_t *block, uop_t *uop) -{ - int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg_b = HOST_REG_GET(uop->src_reg_b_real); - int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); - - if (REG_IS_Q(dest_size) && REG_IS_Q(src_size_b) && uop->dest_reg_a_real == uop->src_reg_a_real) - { - host_x86_PSUBD_XREG_XREG(block, dest_reg, src_reg_b); - } -#ifdef RECOMPILER_DEBUG - else - fatal("PSUBD %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real); -#endif - return 0; -} -static int codegen_PSUBSB(codeblock_t *block, uop_t *uop) -{ - int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg_b = HOST_REG_GET(uop->src_reg_b_real); - int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); - - if (REG_IS_Q(dest_size) && REG_IS_Q(src_size_b) && uop->dest_reg_a_real == uop->src_reg_a_real) - { - host_x86_PSUBSB_XREG_XREG(block, dest_reg, src_reg_b); - } -#ifdef RECOMPILER_DEBUG - else - fatal("PSUBSB %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real); -#endif - return 0; -} -static int codegen_PSUBSW(codeblock_t *block, uop_t *uop) -{ - int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg_b = HOST_REG_GET(uop->src_reg_b_real); - int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); - - if (REG_IS_Q(dest_size) && REG_IS_Q(src_size_b) && uop->dest_reg_a_real == uop->src_reg_a_real) - { - host_x86_PSUBSW_XREG_XREG(block, dest_reg, src_reg_b); - } -#ifdef RECOMPILER_DEBUG - else - fatal("PSUBSW %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real); -#endif - return 0; -} -static int codegen_PSUBUSB(codeblock_t *block, uop_t *uop) -{ - int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg_b = HOST_REG_GET(uop->src_reg_b_real); - int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); - - if (REG_IS_Q(dest_size) && REG_IS_Q(src_size_b) && uop->dest_reg_a_real == uop->src_reg_a_real) - { - host_x86_PSUBUSB_XREG_XREG(block, dest_reg, src_reg_b); - } -#ifdef RECOMPILER_DEBUG - else - fatal("PSUBUSB %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real); -#endif - return 0; -} -static int codegen_PSUBUSW(codeblock_t *block, uop_t *uop) -{ - int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg_b = HOST_REG_GET(uop->src_reg_b_real); - int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); - - if (REG_IS_Q(dest_size) && REG_IS_Q(src_size_b) && uop->dest_reg_a_real == uop->src_reg_a_real) - { - host_x86_PSUBUSW_XREG_XREG(block, dest_reg, src_reg_b); - } -#ifdef RECOMPILER_DEBUG - else - fatal("PSUBUSW %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real); -#endif - return 0; -} - -static int codegen_PUNPCKHBW(codeblock_t *block, uop_t *uop) -{ - int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg_b = HOST_REG_GET(uop->src_reg_b_real); - int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); - - if (REG_IS_Q(dest_size) && REG_IS_Q(src_size_b) && uop->dest_reg_a_real == uop->src_reg_a_real) - { - host_x86_PUNPCKLBW_XREG_XREG(block, dest_reg, src_reg_b); - host_x86_PSHUFD_XREG_XREG_IMM(block, dest_reg, dest_reg, 0xee); /*0xee = move top 64-bits to low 64-bits*/ - } -#ifdef RECOMPILER_DEBUG - else - fatal("PUNPCKHBW %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real); -#endif - return 0; -} -static int codegen_PUNPCKHWD(codeblock_t *block, uop_t *uop) -{ - int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg_b = HOST_REG_GET(uop->src_reg_b_real); - int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); - - if (REG_IS_Q(dest_size) && REG_IS_Q(src_size_b) && uop->dest_reg_a_real == uop->src_reg_a_real) - { - host_x86_PUNPCKLWD_XREG_XREG(block, dest_reg, src_reg_b); - host_x86_PSHUFD_XREG_XREG_IMM(block, dest_reg, dest_reg, 0xee); /*0xee = move top 64-bits to low 64-bits*/ - } -#ifdef RECOMPILER_DEBUG - else - fatal("PUNPCKHWD %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real); -#endif - return 0; -} -static int codegen_PUNPCKHDQ(codeblock_t *block, uop_t *uop) -{ - int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg_b = HOST_REG_GET(uop->src_reg_b_real); - int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); - - if (REG_IS_Q(dest_size) && REG_IS_Q(src_size_b) && uop->dest_reg_a_real == uop->src_reg_a_real) - { - host_x86_PUNPCKLDQ_XREG_XREG(block, dest_reg, src_reg_b); - host_x86_PSHUFD_XREG_XREG_IMM(block, dest_reg, dest_reg, 0xee); /*0xee = move top 64-bits to low 64-bits*/ - } -#ifdef RECOMPILER_DEBUG - else - fatal("PUNPCKHDQ %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real); -#endif - return 0; -} -static int codegen_PUNPCKLBW(codeblock_t *block, uop_t *uop) -{ - int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg_b = HOST_REG_GET(uop->src_reg_b_real); - int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); - - if (REG_IS_Q(dest_size) && REG_IS_Q(src_size_b) && uop->dest_reg_a_real == uop->src_reg_a_real) - { - host_x86_PUNPCKLBW_XREG_XREG(block, dest_reg, src_reg_b); - } -#ifdef RECOMPILER_DEBUG - else - fatal("PUNPCKLBW %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real); -#endif - return 0; -} -static int codegen_PUNPCKLWD(codeblock_t *block, uop_t *uop) -{ - int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg_b = HOST_REG_GET(uop->src_reg_b_real); - int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); - - if (REG_IS_Q(dest_size) && REG_IS_Q(src_size_b) && uop->dest_reg_a_real == uop->src_reg_a_real) - { - host_x86_PUNPCKLWD_XREG_XREG(block, dest_reg, src_reg_b); - } -#ifdef RECOMPILER_DEBUG - else - fatal("PUNPCKLWD %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real); -#endif - return 0; -} -static int codegen_PUNPCKLDQ(codeblock_t *block, uop_t *uop) -{ - int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg_b = HOST_REG_GET(uop->src_reg_b_real); - int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); - - if (REG_IS_Q(dest_size) && REG_IS_Q(src_size_b) && uop->dest_reg_a_real == uop->src_reg_a_real) - { - host_x86_PUNPCKLDQ_XREG_XREG(block, dest_reg, src_reg_b); - } -#ifdef RECOMPILER_DEBUG - else - fatal("PUNPCKLDQ %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real); -#endif - return 0; -} - -static int codegen_ROL(codeblock_t *block, uop_t *uop) -{ - int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg = HOST_REG_GET(uop->src_reg_a_real), shift_reg = HOST_REG_GET(uop->src_reg_b_real); - int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size = IREG_GET_SIZE(uop->src_reg_a_real); - - host_x86_MOV32_REG_REG(block, REG_ECX, shift_reg); - if (REG_IS_L(dest_size) && REG_IS_L(src_size)) - { - if (uop->dest_reg_a_real != uop->src_reg_a_real) - host_x86_MOV32_REG_REG(block, dest_reg, src_reg); - host_x86_ROL32_CL(block, dest_reg); - } - else if (REG_IS_W(dest_size) && REG_IS_W(src_size)) - { - if (uop->dest_reg_a_real != uop->src_reg_a_real) - host_x86_MOV16_REG_REG(block, dest_reg, src_reg); - host_x86_ROL16_CL(block, dest_reg); - } - else if (REG_IS_B(dest_size) && REG_IS_B(src_size)) - { - if (uop->dest_reg_a_real != uop->src_reg_a_real) - host_x86_MOV8_REG_REG(block, dest_reg, src_reg); - host_x86_ROL8_CL(block, dest_reg); - } -#ifdef RECOMPILER_DEBUG - else - fatal("ROL %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real); -#endif - return 0; -} -static int codegen_ROL_IMM(codeblock_t *block, uop_t *uop) -{ - int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg = HOST_REG_GET(uop->src_reg_a_real); - int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size = IREG_GET_SIZE(uop->src_reg_a_real); - - if (REG_IS_L(dest_size) && REG_IS_L(src_size)) - { - if (uop->dest_reg_a_real != uop->src_reg_a_real) - host_x86_MOV32_REG_REG(block, dest_reg, src_reg); - host_x86_ROL32_IMM(block, dest_reg, uop->imm_data); - } - else if (REG_IS_W(dest_size) && REG_IS_W(src_size)) - { - if (uop->dest_reg_a_real != uop->src_reg_a_real) - host_x86_MOV16_REG_REG(block, dest_reg, src_reg); - host_x86_ROL16_IMM(block, dest_reg, uop->imm_data); - } - else if (REG_IS_B(dest_size) && REG_IS_B(src_size)) - { - if (uop->dest_reg_a_real != uop->src_reg_a_real) - host_x86_MOV8_REG_REG(block, dest_reg, src_reg); - host_x86_ROL8_IMM(block, dest_reg, uop->imm_data); - } -#ifdef RECOMPILER_DEBUG - else - fatal("ROL_IMM %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real); -#endif - return 0; -} -static int codegen_ROR(codeblock_t *block, uop_t *uop) -{ - int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg = HOST_REG_GET(uop->src_reg_a_real), shift_reg = HOST_REG_GET(uop->src_reg_b_real); - int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size = IREG_GET_SIZE(uop->src_reg_a_real); - - host_x86_MOV32_REG_REG(block, REG_ECX, shift_reg); - if (REG_IS_L(dest_size) && REG_IS_L(src_size)) - { - if (uop->dest_reg_a_real != uop->src_reg_a_real) - host_x86_MOV32_REG_REG(block, dest_reg, src_reg); - host_x86_ROR32_CL(block, dest_reg); - } - else if (REG_IS_W(dest_size) && REG_IS_W(src_size)) - { - if (uop->dest_reg_a_real != uop->src_reg_a_real) - host_x86_MOV16_REG_REG(block, dest_reg, src_reg); - host_x86_ROR16_CL(block, dest_reg); - } - else if (REG_IS_B(dest_size) && REG_IS_B(src_size)) - { - if (uop->dest_reg_a_real != uop->src_reg_a_real) - host_x86_MOV8_REG_REG(block, dest_reg, src_reg); - host_x86_ROR8_CL(block, dest_reg); - } -#ifdef RECOMPILER_DEBUG - else - fatal("ROR %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real); -#endif - return 0; -} -static int codegen_ROR_IMM(codeblock_t *block, uop_t *uop) -{ - int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg = HOST_REG_GET(uop->src_reg_a_real); - int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size = IREG_GET_SIZE(uop->src_reg_a_real); - - if (REG_IS_L(dest_size) && REG_IS_L(src_size)) - { - if (uop->dest_reg_a_real != uop->src_reg_a_real) - host_x86_MOV32_REG_REG(block, dest_reg, src_reg); - host_x86_ROR32_IMM(block, dest_reg, uop->imm_data); - } - else if (REG_IS_W(dest_size) && REG_IS_W(src_size)) - { - if (uop->dest_reg_a_real != uop->src_reg_a_real) - host_x86_MOV16_REG_REG(block, dest_reg, src_reg); - host_x86_ROR16_IMM(block, dest_reg, uop->imm_data); - } - else if (REG_IS_B(dest_size) && REG_IS_B(src_size)) - { - if (uop->dest_reg_a_real != uop->src_reg_a_real) - host_x86_MOV8_REG_REG(block, dest_reg, src_reg); - host_x86_ROR8_IMM(block, dest_reg, uop->imm_data); - } -#ifdef RECOMPILER_DEBUG - else - fatal("ROR_IMM %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real); -#endif - return 0; -} - -static int codegen_SAR(codeblock_t *block, uop_t *uop) -{ - int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg = HOST_REG_GET(uop->src_reg_a_real), shift_reg = HOST_REG_GET(uop->src_reg_b_real); - int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size = IREG_GET_SIZE(uop->src_reg_a_real); - - host_x86_MOV32_REG_REG(block, REG_ECX, shift_reg); - if (REG_IS_L(dest_size) && REG_IS_L(src_size)) - { - if (uop->dest_reg_a_real != uop->src_reg_a_real) - host_x86_MOV32_REG_REG(block, dest_reg, src_reg); - host_x86_SAR32_CL(block, dest_reg); - } - else if (REG_IS_W(dest_size) && REG_IS_W(src_size)) - { - if (uop->dest_reg_a_real != uop->src_reg_a_real) - host_x86_MOV16_REG_REG(block, dest_reg, src_reg); - host_x86_SAR16_CL(block, dest_reg); - } - else if (REG_IS_B(dest_size) && REG_IS_B(src_size)) - { - if (uop->dest_reg_a_real != uop->src_reg_a_real) - host_x86_MOV8_REG_REG(block, dest_reg, src_reg); - host_x86_SAR8_CL(block, dest_reg); - } -#ifdef RECOMPILER_DEBUG - else - fatal("SAR %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real); -#endif - return 0; -} -static int codegen_SAR_IMM(codeblock_t *block, uop_t *uop) -{ - int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg = HOST_REG_GET(uop->src_reg_a_real); - int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size = IREG_GET_SIZE(uop->src_reg_a_real); - - if (REG_IS_L(dest_size) && REG_IS_L(src_size)) - { - if (uop->dest_reg_a_real != uop->src_reg_a_real) - host_x86_MOV32_REG_REG(block, dest_reg, src_reg); - host_x86_SAR32_IMM(block, dest_reg, uop->imm_data); - } - else if (REG_IS_W(dest_size) && REG_IS_W(src_size)) - { - if (uop->dest_reg_a_real != uop->src_reg_a_real) - host_x86_MOV16_REG_REG(block, dest_reg, src_reg); - host_x86_SAR16_IMM(block, dest_reg, uop->imm_data); - } - else if (REG_IS_B(dest_size) && REG_IS_B(src_size)) - { - if (uop->dest_reg_a_real != uop->src_reg_a_real) - host_x86_MOV8_REG_REG(block, dest_reg, src_reg); - host_x86_SAR8_IMM(block, dest_reg, uop->imm_data); - } -#ifdef RECOMPILER_DEBUG - else - fatal("SAR_IMM %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real); -#endif - return 0; -} -static int codegen_SHL(codeblock_t *block, uop_t *uop) -{ - int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg = HOST_REG_GET(uop->src_reg_a_real), shift_reg = HOST_REG_GET(uop->src_reg_b_real); - int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size = IREG_GET_SIZE(uop->src_reg_a_real); - - host_x86_MOV32_REG_REG(block, REG_ECX, shift_reg); - if (REG_IS_L(dest_size) && REG_IS_L(src_size)) - { - if (uop->dest_reg_a_real != uop->src_reg_a_real) - host_x86_MOV32_REG_REG(block, dest_reg, src_reg); - host_x86_SHL32_CL(block, dest_reg); - } - else if (REG_IS_W(dest_size) && REG_IS_W(src_size)) - { - if (uop->dest_reg_a_real != uop->src_reg_a_real) - host_x86_MOV16_REG_REG(block, dest_reg, src_reg); - host_x86_SHL16_CL(block, dest_reg); - } - else if (REG_IS_B(dest_size) && REG_IS_B(src_size)) - { - if (uop->dest_reg_a_real != uop->src_reg_a_real) - host_x86_MOV8_REG_REG(block, dest_reg, src_reg); - host_x86_SHL8_CL(block, dest_reg); - } -#ifdef RECOMPILER_DEBUG - else - fatal("SHL %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real); -#endif - return 0; -} -static int codegen_SHL_IMM(codeblock_t *block, uop_t *uop) -{ - int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg = HOST_REG_GET(uop->src_reg_a_real); - int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size = IREG_GET_SIZE(uop->src_reg_a_real); - - if (REG_IS_L(dest_size) && REG_IS_L(src_size)) - { - if (uop->dest_reg_a_real != uop->src_reg_a_real) - host_x86_MOV32_REG_REG(block, dest_reg, src_reg); - host_x86_SHL32_IMM(block, dest_reg, uop->imm_data); - } - else if (REG_IS_W(dest_size) && REG_IS_W(src_size)) - { - if (uop->dest_reg_a_real != uop->src_reg_a_real) - host_x86_MOV16_REG_REG(block, dest_reg, src_reg); - host_x86_SHL16_IMM(block, dest_reg, uop->imm_data); - } - else if (REG_IS_B(dest_size) && REG_IS_B(src_size)) - { - if (uop->dest_reg_a_real != uop->src_reg_a_real) - host_x86_MOV8_REG_REG(block, dest_reg, src_reg); - host_x86_SHL8_IMM(block, dest_reg, uop->imm_data); - } -#ifdef RECOMPILER_DEBUG - else - fatal("SHL_IMM %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real); -#endif - return 0; -} -static int codegen_SHR(codeblock_t *block, uop_t *uop) -{ - int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg = HOST_REG_GET(uop->src_reg_a_real), shift_reg = HOST_REG_GET(uop->src_reg_b_real); - int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size = IREG_GET_SIZE(uop->src_reg_a_real); - - host_x86_MOV32_REG_REG(block, REG_ECX, shift_reg); - if (REG_IS_L(dest_size) && REG_IS_L(src_size)) - { - if (uop->dest_reg_a_real != uop->src_reg_a_real) - host_x86_MOV32_REG_REG(block, dest_reg, src_reg); - host_x86_SHR32_CL(block, dest_reg); - } - else if (REG_IS_W(dest_size) && REG_IS_W(src_size)) - { - if (uop->dest_reg_a_real != uop->src_reg_a_real) - host_x86_MOV16_REG_REG(block, dest_reg, src_reg); - host_x86_SHR16_CL(block, dest_reg); - } - else if (REG_IS_B(dest_size) && REG_IS_B(src_size)) - { - if (uop->dest_reg_a_real != uop->src_reg_a_real) - host_x86_MOV8_REG_REG(block, dest_reg, src_reg); - host_x86_SHR8_CL(block, dest_reg); - } -#ifdef RECOMPILER_DEBUG - else - fatal("SHR %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real); -#endif - return 0; -} -static int codegen_SHR_IMM(codeblock_t *block, uop_t *uop) -{ - int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg = HOST_REG_GET(uop->src_reg_a_real); - int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size = IREG_GET_SIZE(uop->src_reg_a_real); - - if (REG_IS_L(dest_size) && REG_IS_L(src_size)) - { - if (uop->dest_reg_a_real != uop->src_reg_a_real) - host_x86_MOV32_REG_REG(block, dest_reg, src_reg); - host_x86_SHR32_IMM(block, dest_reg, uop->imm_data); - } - else if (REG_IS_W(dest_size) && REG_IS_W(src_size)) - { - if (uop->dest_reg_a_real != uop->src_reg_a_real) - host_x86_MOV16_REG_REG(block, dest_reg, src_reg); - host_x86_SHR16_IMM(block, dest_reg, uop->imm_data); - } - else if (REG_IS_B(dest_size) && REG_IS_B(src_size)) - { - if (uop->dest_reg_a_real != uop->src_reg_a_real) - host_x86_MOV8_REG_REG(block, dest_reg, src_reg); - host_x86_SHR8_IMM(block, dest_reg, uop->imm_data); - } -#ifdef RECOMPILER_DEBUG - else - fatal("SHR_IMM %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real); -#endif - return 0; -} - -static int codegen_STORE_PTR_IMM(codeblock_t *block, uop_t *uop) -{ - host_x86_MOV32_ABS_IMM(block, uop->p, uop->imm_data); - return 0; -} -static int codegen_STORE_PTR_IMM_8(codeblock_t *block, uop_t *uop) -{ - host_x86_MOV8_ABS_IMM(block, uop->p, uop->imm_data); - return 0; -} -static int codegen_STORE_PTR_IMM_16(codeblock_t *block, uop_t *uop) -{ - host_x86_MOV16_ABS_IMM(block, uop->p, uop->imm_data); - return 0; -} - -static int codegen_SUB(codeblock_t *block, uop_t *uop) -{ - int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg_a = HOST_REG_GET(uop->src_reg_a_real), src_reg_b = HOST_REG_GET(uop->src_reg_b_real); - int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size_a = IREG_GET_SIZE(uop->src_reg_a_real), src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); - - if (REG_IS_L(dest_size) && REG_IS_L(src_size_a) && REG_IS_L(src_size_b)) - { - if (uop->dest_reg_a_real != uop->src_reg_a_real) - host_x86_MOV32_REG_REG(block, dest_reg, src_reg_a); - host_x86_SUB32_REG_REG(block, dest_reg, src_reg_b); - } - else if (REG_IS_W(dest_size) && REG_IS_W(src_size_a) && REG_IS_W(src_size_b)) - { - if (uop->dest_reg_a_real != uop->src_reg_a_real) - host_x86_MOV16_REG_REG(block, dest_reg, src_reg_a); - host_x86_SUB16_REG_REG(block, dest_reg, src_reg_b); - } - else if (REG_IS_B(dest_size) && REG_IS_B(src_size_a) && REG_IS_B(src_size_b)) - { - if (uop->dest_reg_a_real != uop->src_reg_a_real) - host_x86_MOV8_REG_REG(block, dest_reg, src_reg_a); - host_x86_SUB8_REG_REG(block, dest_reg, src_reg_b); - } -#ifdef RECOMPILER_DEBUG - else - fatal("SUB %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real); -#endif - return 0; -} -static int codegen_SUB_IMM(codeblock_t *block, uop_t *uop) -{ - int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg = HOST_REG_GET(uop->src_reg_a_real); - int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size = IREG_GET_SIZE(uop->src_reg_a_real); - - if (REG_IS_L(dest_size) && REG_IS_L(src_size)) - { - if (dest_reg != src_reg) - host_x86_MOV32_REG_REG(block, dest_reg, src_reg); - host_x86_SUB32_REG_IMM(block, dest_reg, uop->imm_data); - } - else if (REG_IS_W(dest_size) && REG_IS_W(src_size)) - { - if (dest_reg != src_reg) - host_x86_MOV16_REG_REG(block, dest_reg, src_reg); - host_x86_SUB16_REG_IMM(block, dest_reg, uop->imm_data); - } - else if (REG_IS_B(dest_size) && REG_IS_B(src_size)) - { - if (dest_reg != src_reg) - host_x86_MOV8_REG_REG(block, dest_reg, src_reg); - host_x86_SUB8_REG_IMM(block, dest_reg, uop->imm_data); - } -#ifdef RECOMPILER_DEBUG - else - fatal("SUB_IMM %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real); -#endif - return 0; -} - -static int codegen_TEST_JNS_DEST(codeblock_t *block, uop_t *uop) -{ - int src_reg = HOST_REG_GET(uop->src_reg_a_real); - int src_size = IREG_GET_SIZE(uop->src_reg_a_real); - - if (REG_IS_L(src_size)) - { - host_x86_TEST32_REG(block, src_reg, src_reg); - } - else if (REG_IS_W(src_size)) - { - host_x86_TEST16_REG(block, src_reg, src_reg); - } - else if (REG_IS_B(src_size)) - { - host_x86_TEST8_REG(block, src_reg, src_reg); - } -#ifdef RECOMPILER_DEBUG - else - fatal("TEST_JNS_DEST %02x\n", uop->src_reg_a_real); -#endif - uop->p = host_x86_JNS_long(block); - - return 0; -} -static int codegen_TEST_JS_DEST(codeblock_t *block, uop_t *uop) -{ - int src_reg = HOST_REG_GET(uop->src_reg_a_real); - int src_size = IREG_GET_SIZE(uop->src_reg_a_real); - - if (REG_IS_L(src_size)) - { - host_x86_TEST32_REG(block, src_reg, src_reg); - } - else if (REG_IS_W(src_size)) - { - host_x86_TEST16_REG(block, src_reg, src_reg); - } - else if (REG_IS_B(src_size)) - { - host_x86_TEST8_REG(block, src_reg, src_reg); - } -#ifdef RECOMPILER_DEBUG - else - fatal("TEST_JS_DEST %02x\n", uop->src_reg_a_real); -#endif - uop->p = host_x86_JS_long(block); - - return 0; -} - -static int codegen_XOR(codeblock_t *block, uop_t *uop) -{ - int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg_b = HOST_REG_GET(uop->src_reg_b_real); - int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size_a = IREG_GET_SIZE(uop->src_reg_a_real), src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); - - if (REG_IS_Q(dest_size) && REG_IS_Q(src_size_a) && REG_IS_Q(src_size_b) && uop->dest_reg_a_real == uop->src_reg_a_real) - { - host_x86_PXOR_XREG_XREG(block, dest_reg, src_reg_b); - } - else if (REG_IS_L(dest_size) && REG_IS_L(src_size_a) && REG_IS_L(src_size_b) && uop->dest_reg_a_real == uop->src_reg_a_real) - { - host_x86_XOR32_REG_REG(block, dest_reg, src_reg_b); - } - else if (REG_IS_W(dest_size) && REG_IS_W(src_size_a) && REG_IS_W(src_size_b) && uop->dest_reg_a_real == uop->src_reg_a_real) - { - host_x86_XOR16_REG_REG(block, dest_reg, src_reg_b); - } - else if (REG_IS_B(dest_size) && REG_IS_B(src_size_a) && REG_IS_B(src_size_b) && uop->dest_reg_a_real == uop->src_reg_a_real) - { - host_x86_XOR8_REG_REG(block, dest_reg, src_reg_b); - } -#ifdef RECOMPILER_DEBUG - else - fatal("XOR %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real); -#endif - return 0; -} -static int codegen_XOR_IMM(codeblock_t *block, uop_t *uop) -{ - int dest_reg = HOST_REG_GET(uop->dest_reg_a_real); - int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size = IREG_GET_SIZE(uop->src_reg_a_real); - - if (REG_IS_L(dest_size) && REG_IS_L(src_size) && uop->dest_reg_a_real == uop->src_reg_a_real) - { - host_x86_XOR32_REG_IMM(block, dest_reg, uop->imm_data); - } - else if (REG_IS_W(dest_size) && REG_IS_W(src_size) && uop->dest_reg_a_real == uop->src_reg_a_real) - { - host_x86_XOR16_REG_IMM(block, dest_reg, uop->imm_data); - } - else if (REG_IS_B(dest_size) && REG_IS_B(src_size) && uop->dest_reg_a_real == uop->src_reg_a_real) - { - host_x86_XOR8_REG_IMM(block, dest_reg, uop->imm_data); - } -#ifdef RECOMPILER_DEBUG - else - fatal("XOR_IMM %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real); -#endif - return 0; -} - -#ifdef DEBUG_EXTRA -static int codegen_LOG_INSTR(codeblock_t *block, uop_t *uop) -{ - if (uop->imm_data > 256*256) - fatal("LOG_INSTR %08x\n", uop->imm_data); - host_x86_INC32_ABS(block, &instr_counts[uop->imm_data]); - return 0; -} -#endif - -const uOpFn uop_handlers[UOP_MAX] = -{ - [UOP_CALL_FUNC & UOP_MASK] = codegen_CALL_FUNC, - [UOP_CALL_FUNC_RESULT & UOP_MASK] = codegen_CALL_FUNC_RESULT, - [UOP_CALL_INSTRUCTION_FUNC & UOP_MASK] = codegen_CALL_INSTRUCTION_FUNC, - - [UOP_JMP & UOP_MASK] = codegen_JMP, - [UOP_JMP_DEST & UOP_MASK] = codegen_JMP_DEST, - - [UOP_LOAD_SEG & UOP_MASK] = codegen_LOAD_SEG, - - [UOP_LOAD_FUNC_ARG_0 & UOP_MASK] = codegen_LOAD_FUNC_ARG0, - [UOP_LOAD_FUNC_ARG_1 & UOP_MASK] = codegen_LOAD_FUNC_ARG1, - [UOP_LOAD_FUNC_ARG_2 & UOP_MASK] = codegen_LOAD_FUNC_ARG2, - [UOP_LOAD_FUNC_ARG_3 & UOP_MASK] = codegen_LOAD_FUNC_ARG3, - - [UOP_LOAD_FUNC_ARG_0_IMM & UOP_MASK] = codegen_LOAD_FUNC_ARG0_IMM, - [UOP_LOAD_FUNC_ARG_1_IMM & UOP_MASK] = codegen_LOAD_FUNC_ARG1_IMM, - [UOP_LOAD_FUNC_ARG_2_IMM & UOP_MASK] = codegen_LOAD_FUNC_ARG2_IMM, - [UOP_LOAD_FUNC_ARG_3_IMM & UOP_MASK] = codegen_LOAD_FUNC_ARG3_IMM, - - [UOP_STORE_P_IMM & UOP_MASK] = codegen_STORE_PTR_IMM, - [UOP_STORE_P_IMM_8 & UOP_MASK] = codegen_STORE_PTR_IMM_8, - [UOP_STORE_P_IMM_16 & UOP_MASK] = codegen_STORE_PTR_IMM_16, - - [UOP_MEM_LOAD_ABS & UOP_MASK] = codegen_MEM_LOAD_ABS, - [UOP_MEM_LOAD_REG & UOP_MASK] = codegen_MEM_LOAD_REG, - [UOP_MEM_LOAD_SINGLE & UOP_MASK] = codegen_MEM_LOAD_SINGLE, - [UOP_MEM_LOAD_DOUBLE & UOP_MASK] = codegen_MEM_LOAD_DOUBLE, - - [UOP_MEM_STORE_ABS & UOP_MASK] = codegen_MEM_STORE_ABS, - [UOP_MEM_STORE_REG & UOP_MASK] = codegen_MEM_STORE_REG, - [UOP_MEM_STORE_IMM_8 & UOP_MASK] = codegen_MEM_STORE_IMM_8, - [UOP_MEM_STORE_IMM_16 & UOP_MASK] = codegen_MEM_STORE_IMM_16, - [UOP_MEM_STORE_IMM_32 & UOP_MASK] = codegen_MEM_STORE_IMM_32, - [UOP_MEM_STORE_SINGLE & UOP_MASK] = codegen_MEM_STORE_SINGLE, - [UOP_MEM_STORE_DOUBLE & UOP_MASK] = codegen_MEM_STORE_DOUBLE, - - [UOP_MOV & UOP_MASK] = codegen_MOV, - [UOP_MOV_PTR & UOP_MASK] = codegen_MOV_PTR, - [UOP_MOV_IMM & UOP_MASK] = codegen_MOV_IMM, - [UOP_MOVSX & UOP_MASK] = codegen_MOVSX, - [UOP_MOVZX & UOP_MASK] = codegen_MOVZX, - [UOP_MOV_DOUBLE_INT & UOP_MASK] = codegen_MOV_DOUBLE_INT, - [UOP_MOV_INT_DOUBLE & UOP_MASK] = codegen_MOV_INT_DOUBLE, - [UOP_MOV_INT_DOUBLE_64 & UOP_MASK] = codegen_MOV_INT_DOUBLE_64, - [UOP_MOV_REG_PTR & UOP_MASK] = codegen_MOV_REG_PTR, - [UOP_MOVZX_REG_PTR_8 & UOP_MASK] = codegen_MOVZX_REG_PTR_8, - [UOP_MOVZX_REG_PTR_16 & UOP_MASK] = codegen_MOVZX_REG_PTR_16, - - [UOP_ADD & UOP_MASK] = codegen_ADD, - [UOP_ADD_IMM & UOP_MASK] = codegen_ADD_IMM, - [UOP_ADD_LSHIFT & UOP_MASK] = codegen_ADD_LSHIFT, - [UOP_AND & UOP_MASK] = codegen_AND, - [UOP_AND_IMM & UOP_MASK] = codegen_AND_IMM, - [UOP_ANDN & UOP_MASK] = codegen_ANDN, - [UOP_OR & UOP_MASK] = codegen_OR, - [UOP_OR_IMM & UOP_MASK] = codegen_OR_IMM, - [UOP_SUB & UOP_MASK] = codegen_SUB, - [UOP_SUB_IMM & UOP_MASK] = codegen_SUB_IMM, - [UOP_XOR & UOP_MASK] = codegen_XOR, - [UOP_XOR_IMM & UOP_MASK] = codegen_XOR_IMM, - - [UOP_SAR & UOP_MASK] = codegen_SAR, - [UOP_SAR_IMM & UOP_MASK] = codegen_SAR_IMM, - [UOP_SHL & UOP_MASK] = codegen_SHL, - [UOP_SHL_IMM & UOP_MASK] = codegen_SHL_IMM, - [UOP_SHR & UOP_MASK] = codegen_SHR, - [UOP_SHR_IMM & UOP_MASK] = codegen_SHR_IMM, - [UOP_ROL & UOP_MASK] = codegen_ROL, - [UOP_ROL_IMM & UOP_MASK] = codegen_ROL_IMM, - [UOP_ROR & UOP_MASK] = codegen_ROR, - [UOP_ROR_IMM & UOP_MASK] = codegen_ROR_IMM, - - [UOP_CMP_IMM_JZ & UOP_MASK] = codegen_CMP_IMM_JZ, - - [UOP_CMP_JB & UOP_MASK] = codegen_CMP_JB, - [UOP_CMP_JNBE & UOP_MASK] = codegen_CMP_JNBE, - - [UOP_CMP_JNB_DEST & UOP_MASK] = codegen_CMP_JNB_DEST, - [UOP_CMP_JNBE_DEST & UOP_MASK] = codegen_CMP_JNBE_DEST, - [UOP_CMP_JNL_DEST & UOP_MASK] = codegen_CMP_JNL_DEST, - [UOP_CMP_JNLE_DEST & UOP_MASK] = codegen_CMP_JNLE_DEST, - [UOP_CMP_JNO_DEST & UOP_MASK] = codegen_CMP_JNO_DEST, - [UOP_CMP_JNZ_DEST & UOP_MASK] = codegen_CMP_JNZ_DEST, - [UOP_CMP_JB_DEST & UOP_MASK] = codegen_CMP_JB_DEST, - [UOP_CMP_JBE_DEST & UOP_MASK] = codegen_CMP_JBE_DEST, - [UOP_CMP_JL_DEST & UOP_MASK] = codegen_CMP_JL_DEST, - [UOP_CMP_JLE_DEST & UOP_MASK] = codegen_CMP_JLE_DEST, - [UOP_CMP_JO_DEST & UOP_MASK] = codegen_CMP_JO_DEST, - [UOP_CMP_JZ_DEST & UOP_MASK] = codegen_CMP_JZ_DEST, - - [UOP_CMP_IMM_JNZ_DEST & UOP_MASK] = codegen_CMP_IMM_JNZ_DEST, - [UOP_CMP_IMM_JZ_DEST & UOP_MASK] = codegen_CMP_IMM_JZ_DEST, - - [UOP_TEST_JNS_DEST & UOP_MASK] = codegen_TEST_JNS_DEST, - [UOP_TEST_JS_DEST & UOP_MASK] = codegen_TEST_JS_DEST, - - [UOP_FP_ENTER & UOP_MASK] = codegen_FP_ENTER, - [UOP_MMX_ENTER & UOP_MASK] = codegen_MMX_ENTER, - - [UOP_FADD & UOP_MASK] = codegen_FADD, - [UOP_FDIV & UOP_MASK] = codegen_FDIV, - [UOP_FMUL & UOP_MASK] = codegen_FMUL, - [UOP_FSUB & UOP_MASK] = codegen_FSUB, - [UOP_FCOM & UOP_MASK] = codegen_FCOM, - - [UOP_FABS & UOP_MASK] = codegen_FABS, - [UOP_FCHS & UOP_MASK] = codegen_FCHS, - [UOP_FSQRT & UOP_MASK] = codegen_FSQRT, - [UOP_FTST & UOP_MASK] = codegen_FTST, - - [UOP_PACKSSWB & UOP_MASK] = codegen_PACKSSWB, - [UOP_PACKSSDW & UOP_MASK] = codegen_PACKSSDW, - [UOP_PACKUSWB & UOP_MASK] = codegen_PACKUSWB, - - [UOP_PADDB & UOP_MASK] = codegen_PADDB, - [UOP_PADDW & UOP_MASK] = codegen_PADDW, - [UOP_PADDD & UOP_MASK] = codegen_PADDD, - [UOP_PADDSB & UOP_MASK] = codegen_PADDSB, - [UOP_PADDSW & UOP_MASK] = codegen_PADDSW, - [UOP_PADDUSB & UOP_MASK] = codegen_PADDUSB, - [UOP_PADDUSW & UOP_MASK] = codegen_PADDUSW, - - [UOP_PCMPEQB & UOP_MASK] = codegen_PCMPEQB, - [UOP_PCMPEQW & UOP_MASK] = codegen_PCMPEQW, - [UOP_PCMPEQD & UOP_MASK] = codegen_PCMPEQD, - [UOP_PCMPGTB & UOP_MASK] = codegen_PCMPGTB, - [UOP_PCMPGTW & UOP_MASK] = codegen_PCMPGTW, - [UOP_PCMPGTD & UOP_MASK] = codegen_PCMPGTD, - - [UOP_PF2ID & UOP_MASK] = codegen_PF2ID, - [UOP_PFADD & UOP_MASK] = codegen_PFADD, - [UOP_PFCMPEQ & UOP_MASK] = codegen_PFCMPEQ, - [UOP_PFCMPGE & UOP_MASK] = codegen_PFCMPGE, - [UOP_PFCMPGT & UOP_MASK] = codegen_PFCMPGT, - [UOP_PFMAX & UOP_MASK] = codegen_PFMAX, - [UOP_PFMIN & UOP_MASK] = codegen_PFMIN, - [UOP_PFMUL & UOP_MASK] = codegen_PFMUL, - [UOP_PFRCP & UOP_MASK] = codegen_PFRCP, - [UOP_PFRSQRT & UOP_MASK] = codegen_PFRSQRT, - [UOP_PFSUB & UOP_MASK] = codegen_PFSUB, - [UOP_PI2FD & UOP_MASK] = codegen_PI2FD, - - [UOP_PMADDWD & UOP_MASK] = codegen_PMADDWD, - [UOP_PMULHW & UOP_MASK] = codegen_PMULHW, - [UOP_PMULLW & UOP_MASK] = codegen_PMULLW, - - [UOP_PSLLW_IMM & UOP_MASK] = codegen_PSLLW_IMM, - [UOP_PSLLD_IMM & UOP_MASK] = codegen_PSLLD_IMM, - [UOP_PSLLQ_IMM & UOP_MASK] = codegen_PSLLQ_IMM, - [UOP_PSRAW_IMM & UOP_MASK] = codegen_PSRAW_IMM, - [UOP_PSRAD_IMM & UOP_MASK] = codegen_PSRAD_IMM, - [UOP_PSRAQ_IMM & UOP_MASK] = codegen_PSRAQ_IMM, - [UOP_PSRLW_IMM & UOP_MASK] = codegen_PSRLW_IMM, - [UOP_PSRLD_IMM & UOP_MASK] = codegen_PSRLD_IMM, - [UOP_PSRLQ_IMM & UOP_MASK] = codegen_PSRLQ_IMM, - - [UOP_PSUBB & UOP_MASK] = codegen_PSUBB, - [UOP_PSUBW & UOP_MASK] = codegen_PSUBW, - [UOP_PSUBD & UOP_MASK] = codegen_PSUBD, - [UOP_PSUBSB & UOP_MASK] = codegen_PSUBSB, - [UOP_PSUBSW & UOP_MASK] = codegen_PSUBSW, - [UOP_PSUBUSB & UOP_MASK] = codegen_PSUBUSB, - [UOP_PSUBUSW & UOP_MASK] = codegen_PSUBUSW, - - [UOP_PUNPCKHBW & UOP_MASK] = codegen_PUNPCKHBW, - [UOP_PUNPCKHWD & UOP_MASK] = codegen_PUNPCKHWD, - [UOP_PUNPCKHDQ & UOP_MASK] = codegen_PUNPCKHDQ, - [UOP_PUNPCKLBW & UOP_MASK] = codegen_PUNPCKLBW, - [UOP_PUNPCKLWD & UOP_MASK] = codegen_PUNPCKLWD, - [UOP_PUNPCKLDQ & UOP_MASK] = codegen_PUNPCKLDQ, - - [UOP_NOP_BARRIER & UOP_MASK] = codegen_NOP, - -#ifdef DEBUG_EXTRA - [UOP_LOG_INSTR & UOP_MASK] = codegen_LOG_INSTR -#endif + host_x86_CALL(block, codegen_mem_store_quad); + } +# ifdef RECOMPILER_DEBUG + else + fatal("MEM_STORE_REG - %02x\n", uop->src_reg_b_real); +# endif + host_x86_TEST32_REG(block, REG_ESI, REG_ESI); + host_x86_JNZ(block, codegen_exit_rout); + + return 0; +} + +static int +codegen_MEM_STORE_IMM_8(codeblock_t *block, uop_t *uop) +{ + int seg_reg = HOST_REG_GET(uop->src_reg_a_real); + int addr_reg = HOST_REG_GET(uop->src_reg_b_real); + + host_x86_LEA_REG_REG(block, REG_ESI, seg_reg, addr_reg); + host_x86_MOV8_REG_IMM(block, REG_ECX, uop->imm_data); + host_x86_CALL(block, codegen_mem_store_byte); + host_x86_TEST32_REG(block, REG_ESI, REG_ESI); + host_x86_JNZ(block, codegen_exit_rout); + + return 0; +} +static int +codegen_MEM_STORE_IMM_16(codeblock_t *block, uop_t *uop) +{ + int seg_reg = HOST_REG_GET(uop->src_reg_a_real); + int addr_reg = HOST_REG_GET(uop->src_reg_b_real); + + host_x86_LEA_REG_REG(block, REG_ESI, seg_reg, addr_reg); + host_x86_MOV16_REG_IMM(block, REG_ECX, uop->imm_data); + host_x86_CALL(block, codegen_mem_store_word); + host_x86_TEST32_REG(block, REG_ESI, REG_ESI); + host_x86_JNZ(block, codegen_exit_rout); + + return 0; +} +static int +codegen_MEM_STORE_IMM_32(codeblock_t *block, uop_t *uop) +{ + int seg_reg = HOST_REG_GET(uop->src_reg_a_real); + int addr_reg = HOST_REG_GET(uop->src_reg_b_real); + + host_x86_LEA_REG_REG(block, REG_ESI, seg_reg, addr_reg); + host_x86_MOV32_REG_IMM(block, REG_ECX, uop->imm_data); + host_x86_CALL(block, codegen_mem_store_long); + host_x86_TEST32_REG(block, REG_ESI, REG_ESI); + host_x86_JNZ(block, codegen_exit_rout); + + return 0; +} + +static int +codegen_MEM_STORE_SINGLE(codeblock_t *block, uop_t *uop) +{ + int seg_reg = HOST_REG_GET(uop->src_reg_a_real); + int addr_reg = HOST_REG_GET(uop->src_reg_b_real); + int src_reg = HOST_REG_GET(uop->src_reg_c_real); +# ifdef RECOMPILER_DEBUG + int src_size = IREG_GET_SIZE(uop->src_reg_c_real); + + if (!REG_IS_D(src_size)) + fatal("MEM_STORE_SINGLE - %02x\n", uop->src_reg_b_real); +# endif + host_x86_LEA_REG_REG(block, REG_ESI, seg_reg, addr_reg); + if (uop->imm_data) + host_x86_ADD32_REG_IMM(block, REG_ESI, uop->imm_data); + host_x86_CVTSD2SS_XREG_XREG(block, REG_XMM_TEMP, src_reg); + host_x86_CALL(block, codegen_mem_store_single); + host_x86_TEST32_REG(block, REG_ESI, REG_ESI); + host_x86_JNZ(block, codegen_exit_rout); + + return 0; +} +static int +codegen_MEM_STORE_DOUBLE(codeblock_t *block, uop_t *uop) +{ + int seg_reg = HOST_REG_GET(uop->src_reg_a_real); + int addr_reg = HOST_REG_GET(uop->src_reg_b_real); + int src_reg = HOST_REG_GET(uop->src_reg_c_real); +# ifdef RECOMPILER_DEBUG + int src_size = IREG_GET_SIZE(uop->src_reg_c_real); + + if (!REG_IS_D(src_size)) + fatal("MEM_STORE_DOUBLE - %02x\n", uop->src_reg_b_real); +# endif + host_x86_LEA_REG_REG(block, REG_ESI, seg_reg, addr_reg); + if (uop->imm_data) + host_x86_ADD32_REG_IMM(block, REG_ESI, uop->imm_data); + host_x86_MOVQ_XREG_XREG(block, REG_XMM_TEMP, src_reg); + host_x86_CALL(block, codegen_mem_store_double); + host_x86_TEST32_REG(block, REG_ESI, REG_ESI); + host_x86_JNZ(block, codegen_exit_rout); + + return 0; +} + +static int +codegen_MOV(codeblock_t *block, uop_t *uop) +{ + int dest_reg = HOST_REG_GET(uop->dest_reg_a_real); + int src_reg = HOST_REG_GET(uop->src_reg_a_real); + int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real); + int src_size = IREG_GET_SIZE(uop->src_reg_a_real); + + if (REG_IS_L(dest_size) && REG_IS_L(src_size)) { + host_x86_MOV32_REG_REG(block, dest_reg, src_reg); + } else if (REG_IS_W(dest_size) && REG_IS_W(src_size)) { + host_x86_MOV16_REG_REG(block, dest_reg, src_reg); + } else if (REG_IS_B(dest_size) && REG_IS_B(src_size)) { + host_x86_MOV8_REG_REG(block, dest_reg, src_reg); + } else if (REG_IS_D(dest_size) && REG_IS_D(src_size)) { + host_x86_MOVQ_XREG_XREG(block, dest_reg, src_reg); + } else if (REG_IS_Q(dest_size) && REG_IS_Q(src_size)) { + host_x86_MOVQ_XREG_XREG(block, dest_reg, src_reg); + } +# ifdef RECOMPILER_DEBUG + else + fatal("MOV %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real); +# endif + return 0; +} +static int +codegen_MOV_IMM(codeblock_t *block, uop_t *uop) +{ + int dest_reg = HOST_REG_GET(uop->dest_reg_a_real); + int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real); + + if (REG_IS_L(dest_size)) { + host_x86_MOV32_REG_IMM(block, dest_reg, uop->imm_data); + } else if (REG_IS_W(dest_size)) { + host_x86_MOV16_REG_IMM(block, dest_reg, uop->imm_data); + } else if (REG_IS_B(dest_size)) { + host_x86_MOV8_REG_IMM(block, dest_reg, uop->imm_data); + } +# ifdef RECOMPILER_DEBUG + else + fatal("MOV_IMM %02x\n", uop->dest_reg_a_real); +# endif + return 0; +} +static int +codegen_MOV_PTR(codeblock_t *block, uop_t *uop) +{ + host_x86_MOV32_REG_IMM(block, uop->dest_reg_a_real, (uint32_t) uop->p); + return 0; +} +static int +codegen_MOV_REG_PTR(codeblock_t *block, uop_t *uop) +{ + int dest_reg = HOST_REG_GET(uop->dest_reg_a_real); + int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real); + + if (REG_IS_L(dest_size)) { + host_x86_MOV32_REG_ABS(block, dest_reg, uop->p); + } else + fatal("MOV_REG_PTR %02x\n", uop->dest_reg_a_real); + + return 0; +} +static int +codegen_MOVZX_REG_PTR_8(codeblock_t *block, uop_t *uop) +{ + int dest_reg = HOST_REG_GET(uop->dest_reg_a_real); + int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real); + + if (REG_IS_L(dest_size)) { + host_x86_MOVZX_REG_ABS_32_8(block, dest_reg, uop->p); + } else if (REG_IS_W(dest_size)) { + host_x86_MOVZX_REG_ABS_16_8(block, dest_reg, uop->p); + } else if (REG_IS_B(dest_size)) { + host_x86_MOV8_REG_ABS(block, dest_reg, uop->p); + } else + fatal("MOVZX_REG_PTR_8 %02x\n", uop->dest_reg_a_real); + + return 0; +} +static int +codegen_MOVZX_REG_PTR_16(codeblock_t *block, uop_t *uop) +{ + int dest_reg = HOST_REG_GET(uop->dest_reg_a_real); + int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real); + + if (REG_IS_L(dest_size)) { + host_x86_MOVZX_REG_ABS_32_16(block, dest_reg, uop->p); + } else if (REG_IS_W(dest_size)) { + host_x86_MOV16_REG_ABS(block, dest_reg, uop->p); + } else + fatal("MOVZX_REG_PTR_16 %02x\n", uop->dest_reg_a_real); + + return 0; +} +static int +codegen_MOVSX(codeblock_t *block, uop_t *uop) +{ + int dest_reg = HOST_REG_GET(uop->dest_reg_a_real); + int src_reg = HOST_REG_GET(uop->src_reg_a_real); + int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real); + int src_size = IREG_GET_SIZE(uop->src_reg_a_real); + + if (REG_IS_L(dest_size) && REG_IS_W(src_size)) { + host_x86_MOVSX_REG_32_16(block, dest_reg, src_reg); + } else if (REG_IS_L(dest_size) && REG_IS_B(src_size)) { + host_x86_MOVSX_REG_32_8(block, dest_reg, src_reg); + } else if (REG_IS_W(dest_size) && REG_IS_B(src_size)) { + host_x86_MOVSX_REG_16_8(block, dest_reg, src_reg); + } +# ifdef RECOMPILER_DEBUG + else + fatal("MOVSX %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real); +# endif + return 0; +} +static int +codegen_MOVZX(codeblock_t *block, uop_t *uop) +{ + int dest_reg = HOST_REG_GET(uop->dest_reg_a_real); + int src_reg = HOST_REG_GET(uop->src_reg_a_real); + int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real); + int src_size = IREG_GET_SIZE(uop->src_reg_a_real); + + if (REG_IS_Q(dest_size) && REG_IS_L(src_size)) { + host_x86_MOVD_XREG_REG(block, dest_reg, src_reg); + } else if (REG_IS_L(dest_size) && REG_IS_Q(src_size)) { + host_x86_MOVD_REG_XREG(block, dest_reg, src_reg); + } else if (REG_IS_L(dest_size) && REG_IS_W(src_size)) { + host_x86_MOVZX_REG_32_16(block, dest_reg, src_reg); + } else if (REG_IS_L(dest_size) && REG_IS_B(src_size)) { + host_x86_MOVZX_REG_32_8(block, dest_reg, src_reg); + } else if (REG_IS_W(dest_size) && REG_IS_B(src_size)) { + host_x86_MOVZX_REG_16_8(block, dest_reg, src_reg); + } +# ifdef RECOMPILER_DEBUG + else + fatal("MOVZX %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real); +# endif + return 0; +} + +static int +codegen_MOV_DOUBLE_INT(codeblock_t *block, uop_t *uop) +{ + int dest_reg = HOST_REG_GET(uop->dest_reg_a_real); + int src_reg = HOST_REG_GET(uop->src_reg_a_real); + int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real); + int src_size = IREG_GET_SIZE(uop->src_reg_a_real); + + if (REG_IS_D(dest_size) && REG_IS_L(src_size)) { + host_x86_CVTSI2SD_XREG_REG(block, dest_reg, src_reg); + } else if (REG_IS_D(dest_size) && REG_IS_W(src_size)) { + host_x86_MOVSX_REG_32_16(block, REG_ECX, src_reg); + host_x86_CVTSI2SD_XREG_REG(block, dest_reg, REG_ECX); + } else if (REG_IS_D(dest_size) && REG_IS_Q(src_size)) { + /*There is no SSE instruction to convert a 64-bit integer to a floating point value. + Instead we have to bounce the integer through memory via x87.*/ + host_x86_MOVQ_BASE_OFFSET_XREG(block, REG_ESP, 0, src_reg); + host_x87_FILDq_BASE(block, REG_ESP); + host_x87_FSTPd_BASE(block, REG_ESP); + host_x86_MOVQ_XREG_BASE_OFFSET(block, dest_reg, REG_ESP, 0); + } +# ifdef RECOMPILER_DEBUG + else + fatal("MOV_DOUBLE_INT %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real); +# endif + return 0; +} +static int +codegen_MOV_INT_DOUBLE(codeblock_t *block, uop_t *uop) +{ + int dest_reg = HOST_REG_GET(uop->dest_reg_a_real); + int src_reg = HOST_REG_GET(uop->src_reg_a_real); + int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real); + int src_size = IREG_GET_SIZE(uop->src_reg_a_real); + + if (REG_IS_L(dest_size) && REG_IS_D(src_size)) { + host_x86_LDMXCSR(block, &cpu_state.new_fp_control); + host_x86_CVTSD2SI_REG_XREG(block, dest_reg, src_reg); + host_x86_LDMXCSR(block, &cpu_state.old_fp_control); + } else if (REG_IS_W(dest_size) && REG_IS_D(src_size)) { + host_x86_LDMXCSR(block, &cpu_state.new_fp_control); + host_x86_CVTSD2SI_REG_XREG(block, REG_ECX, src_reg); + host_x86_MOV16_REG_REG(block, dest_reg, REG_ECX); + host_x86_LDMXCSR(block, &cpu_state.old_fp_control); + } +# ifdef RECOMPILER_DEBUG + else + fatal("MOV_INT_DOUBLE %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real); +# endif + return 0; +} + +static int +codegen_MOV_INT_DOUBLE_64(codeblock_t *block, uop_t *uop) +{ + int dest_reg = HOST_REG_GET(uop->dest_reg_a_real); + int src_reg = HOST_REG_GET(uop->src_reg_a_real); + int src_64_reg = HOST_REG_GET(uop->src_reg_b_real); + int tag_reg = HOST_REG_GET(uop->src_reg_c_real); + int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real); + int src_size = IREG_GET_SIZE(uop->src_reg_a_real); + int src_64_size = IREG_GET_SIZE(uop->src_reg_b_real); + + if (REG_IS_Q(dest_size) && REG_IS_D(src_size) && REG_IS_Q(src_64_size)) { + uint32_t *branch_offset; + + /*If TAG_UINT64 is set then the source is MM[]. Otherwise it is a double in ST()*/ + host_x86_MOVQ_XREG_XREG(block, dest_reg, src_64_reg); + host_x86_TEST8_REG(block, tag_reg, tag_reg); + branch_offset = host_x86_JS_long(block); + + /*There is no SSE instruction to convert a floating point value to a 64-bit integer. + Instead we have to bounce through memory via x87.*/ + host_x87_FLDCW(block, &cpu_state.new_fp_control2); + host_x86_MOVQ_BASE_OFFSET_XREG(block, REG_ESP, 0, src_reg); + host_x87_FLDd_BASE(block, REG_ESP); + host_x87_FISTPq_BASE(block, REG_ESP); + host_x86_MOVQ_XREG_BASE_OFFSET(block, dest_reg, REG_ESP, 0); + host_x87_FLDCW(block, &cpu_state.old_fp_control2); + + *branch_offset = (uint32_t) ((uintptr_t) &block_write_data[block_pos] - (uintptr_t) branch_offset) - 4; + } +# ifdef RECOMPILER_DEBUG + else + fatal("MOV_INT_DOUBLE_64 %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real); +# endif + return 0; +} + +static int +codegen_NOP(UNUSED(codeblock_t *block), UNUSED(uop_t *uop)) +{ + return 0; +} + +static int +codegen_OR(codeblock_t *block, uop_t *uop) +{ + int dest_reg = HOST_REG_GET(uop->dest_reg_a_real); + int src_reg_a = HOST_REG_GET(uop->src_reg_a_real); + int src_reg_b = HOST_REG_GET(uop->src_reg_b_real); + int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real); + int src_size_a = IREG_GET_SIZE(uop->src_reg_a_real); + int src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); + + if (REG_IS_Q(dest_size) && REG_IS_Q(src_size_a) && REG_IS_Q(src_size_b) && uop->dest_reg_a_real == uop->src_reg_a_real) { + host_x86_POR_XREG_XREG(block, dest_reg, src_reg_b); + } else if (REG_IS_L(dest_size) && REG_IS_L(src_size_a) && REG_IS_L(src_size_b)) { + if (uop->dest_reg_a_real != uop->src_reg_a_real) + host_x86_MOV32_REG_REG(block, dest_reg, src_reg_a); + host_x86_OR32_REG_REG(block, dest_reg, src_reg_b); + } else if (REG_IS_W(dest_size) && REG_IS_W(src_size_a) && REG_IS_W(src_size_b)) { + if (uop->dest_reg_a_real != uop->src_reg_a_real) + host_x86_MOV16_REG_REG(block, dest_reg, src_reg_a); + host_x86_OR16_REG_REG(block, dest_reg, src_reg_b); + } else if (REG_IS_B(dest_size) && REG_IS_B(src_size_a) && REG_IS_B(src_size_b)) { + if (uop->dest_reg_a_real != uop->src_reg_a_real) + host_x86_MOV8_REG_REG(block, dest_reg, src_reg_a); + host_x86_OR8_REG_REG(block, dest_reg, src_reg_b); + } +# ifdef RECOMPILER_DEBUG + else + fatal("OR %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real); +# endif + return 0; +} +static int +codegen_OR_IMM(codeblock_t *block, uop_t *uop) +{ + int dest_reg = HOST_REG_GET(uop->dest_reg_a_real); + int src_reg = HOST_REG_GET(uop->src_reg_a_real); + int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real); + + if (REG_IS_L(dest_size) && dest_reg == src_reg) { + host_x86_OR32_REG_IMM(block, dest_reg, uop->imm_data); + } else if (REG_IS_W(dest_size) && dest_reg == src_reg) { + host_x86_OR16_REG_IMM(block, dest_reg, uop->imm_data); + } else if (REG_IS_B(dest_size) && dest_reg == src_reg) { + host_x86_OR8_REG_IMM(block, dest_reg, uop->imm_data); + } +# ifdef RECOMPILER_DEBUG + else + fatal("OR_IMM %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real); +# endif + return 0; +} + +static int +codegen_PACKSSWB(codeblock_t *block, uop_t *uop) +{ + int dest_reg = HOST_REG_GET(uop->dest_reg_a_real); + int src_reg_b = HOST_REG_GET(uop->src_reg_b_real); + int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real); + int src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); + + if (REG_IS_Q(dest_size) && REG_IS_Q(src_size_b) && uop->dest_reg_a_real == uop->src_reg_a_real) { + host_x86_PACKSSWB_XREG_XREG(block, dest_reg, src_reg_b); + } +# ifdef RECOMPILER_DEBUG + else + fatal("PACKSSWB %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real); +# endif + return 0; +} +static int +codegen_PACKSSDW(codeblock_t *block, uop_t *uop) +{ + int dest_reg = HOST_REG_GET(uop->dest_reg_a_real); + int src_reg_b = HOST_REG_GET(uop->src_reg_b_real); + int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real); + int src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); + + if (REG_IS_Q(dest_size) && REG_IS_Q(src_size_b) && uop->dest_reg_a_real == uop->src_reg_a_real) { + host_x86_PACKSSDW_XREG_XREG(block, dest_reg, src_reg_b); + } +# ifdef RECOMPILER_DEBUG + else + fatal("PACKSSDW %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real); +# endif + return 0; +} +static int +codegen_PACKUSWB(codeblock_t *block, uop_t *uop) +{ + int dest_reg = HOST_REG_GET(uop->dest_reg_a_real); + int src_reg_b = HOST_REG_GET(uop->src_reg_b_real); + int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real); + int src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); + + if (REG_IS_Q(dest_size) && REG_IS_Q(src_size_b) && uop->dest_reg_a_real == uop->src_reg_a_real) { + host_x86_PACKUSWB_XREG_XREG(block, dest_reg, src_reg_b); + } +# ifdef RECOMPILER_DEBUG + else + fatal("PACKUSWB %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real); +# endif + return 0; +} + +static int +codegen_PADDB(codeblock_t *block, uop_t *uop) +{ + int dest_reg = HOST_REG_GET(uop->dest_reg_a_real); + int src_reg_b = HOST_REG_GET(uop->src_reg_b_real); + int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real); + int src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); + + if (REG_IS_Q(dest_size) && REG_IS_Q(src_size_b) && uop->dest_reg_a_real == uop->src_reg_a_real) { + host_x86_PADDB_XREG_XREG(block, dest_reg, src_reg_b); + } +# ifdef RECOMPILER_DEBUG + else + fatal("PADDB %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real); +# endif + return 0; +} +static int +codegen_PADDW(codeblock_t *block, uop_t *uop) +{ + int dest_reg = HOST_REG_GET(uop->dest_reg_a_real); + int src_reg_b = HOST_REG_GET(uop->src_reg_b_real); + int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real); + int src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); + + if (REG_IS_Q(dest_size) && REG_IS_Q(src_size_b) && uop->dest_reg_a_real == uop->src_reg_a_real) { + host_x86_PADDW_XREG_XREG(block, dest_reg, src_reg_b); + } +# ifdef RECOMPILER_DEBUG + else + fatal("PADDW %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real); +# endif + return 0; +} +static int +codegen_PADDD(codeblock_t *block, uop_t *uop) +{ + int dest_reg = HOST_REG_GET(uop->dest_reg_a_real); + int src_reg_b = HOST_REG_GET(uop->src_reg_b_real); + int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real); + int src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); + + if (REG_IS_Q(dest_size) && REG_IS_Q(src_size_b) && uop->dest_reg_a_real == uop->src_reg_a_real) { + host_x86_PADDD_XREG_XREG(block, dest_reg, src_reg_b); + } +# ifdef RECOMPILER_DEBUG + else + fatal("PADDD %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real); +# endif + return 0; +} +static int +codegen_PADDSB(codeblock_t *block, uop_t *uop) +{ + int dest_reg = HOST_REG_GET(uop->dest_reg_a_real); + int src_reg_b = HOST_REG_GET(uop->src_reg_b_real); + int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real); + int src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); + + if (REG_IS_Q(dest_size) && REG_IS_Q(src_size_b) && uop->dest_reg_a_real == uop->src_reg_a_real) { + host_x86_PADDSB_XREG_XREG(block, dest_reg, src_reg_b); + } +# ifdef RECOMPILER_DEBUG + else + fatal("PADDSB %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real); +# endif + return 0; +} +static int +codegen_PADDSW(codeblock_t *block, uop_t *uop) +{ + int dest_reg = HOST_REG_GET(uop->dest_reg_a_real); + int src_reg_b = HOST_REG_GET(uop->src_reg_b_real); + int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real); + int src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); + + if (REG_IS_Q(dest_size) && REG_IS_Q(src_size_b) && uop->dest_reg_a_real == uop->src_reg_a_real) { + host_x86_PADDSW_XREG_XREG(block, dest_reg, src_reg_b); + } +# ifdef RECOMPILER_DEBUG + else + fatal("PADDSW %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real); +# endif + return 0; +} +static int +codegen_PADDUSB(codeblock_t *block, uop_t *uop) +{ + int dest_reg = HOST_REG_GET(uop->dest_reg_a_real); + int src_reg_b = HOST_REG_GET(uop->src_reg_b_real); + int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real); + int src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); + + if (REG_IS_Q(dest_size) && REG_IS_Q(src_size_b) && uop->dest_reg_a_real == uop->src_reg_a_real) { + host_x86_PADDUSB_XREG_XREG(block, dest_reg, src_reg_b); + } +# ifdef RECOMPILER_DEBUG + else + fatal("PADDUSB %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real); +# endif + return 0; +} +static int +codegen_PADDUSW(codeblock_t *block, uop_t *uop) +{ + int dest_reg = HOST_REG_GET(uop->dest_reg_a_real); + int src_reg_b = HOST_REG_GET(uop->src_reg_b_real); + int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real); + int src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); + + if (REG_IS_Q(dest_size) && REG_IS_Q(src_size_b) && uop->dest_reg_a_real == uop->src_reg_a_real) { + host_x86_PADDUSW_XREG_XREG(block, dest_reg, src_reg_b); + } +# ifdef RECOMPILER_DEBUG + else + fatal("PADDUSW %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real); +# endif + return 0; +} + +static int +codegen_PCMPEQB(codeblock_t *block, uop_t *uop) +{ + int dest_reg = HOST_REG_GET(uop->dest_reg_a_real); + int src_reg_b = HOST_REG_GET(uop->src_reg_b_real); + int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real); + int src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); + + if (REG_IS_Q(dest_size) && REG_IS_Q(src_size_b) && uop->dest_reg_a_real == uop->src_reg_a_real) { + host_x86_PCMPEQB_XREG_XREG(block, dest_reg, src_reg_b); + } +# ifdef RECOMPILER_DEBUG + else + fatal("PCMPEQB %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real); +# endif + return 0; +} +static int +codegen_PCMPEQW(codeblock_t *block, uop_t *uop) +{ + int dest_reg = HOST_REG_GET(uop->dest_reg_a_real); + int src_reg_b = HOST_REG_GET(uop->src_reg_b_real); + int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real); + int src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); + + if (REG_IS_Q(dest_size) && REG_IS_Q(src_size_b) && uop->dest_reg_a_real == uop->src_reg_a_real) { + host_x86_PCMPEQW_XREG_XREG(block, dest_reg, src_reg_b); + } +# ifdef RECOMPILER_DEBUG + else + fatal("PCMPEQW %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real); +# endif + return 0; +} +static int +codegen_PCMPEQD(codeblock_t *block, uop_t *uop) +{ + int dest_reg = HOST_REG_GET(uop->dest_reg_a_real); + int src_reg_b = HOST_REG_GET(uop->src_reg_b_real); + int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real); + int src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); + + if (REG_IS_Q(dest_size) && REG_IS_Q(src_size_b) && uop->dest_reg_a_real == uop->src_reg_a_real) { + host_x86_PCMPEQD_XREG_XREG(block, dest_reg, src_reg_b); + } +# ifdef RECOMPILER_DEBUG + else + fatal("PCMPEQD %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real); +# endif + return 0; +} +static int +codegen_PCMPGTB(codeblock_t *block, uop_t *uop) +{ + int dest_reg = HOST_REG_GET(uop->dest_reg_a_real); + int src_reg_b = HOST_REG_GET(uop->src_reg_b_real); + int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real); + int src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); + + if (REG_IS_Q(dest_size) && REG_IS_Q(src_size_b) && uop->dest_reg_a_real == uop->src_reg_a_real) { + host_x86_PCMPGTB_XREG_XREG(block, dest_reg, src_reg_b); + } +# ifdef RECOMPILER_DEBUG + else + fatal("PCMPGTB %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real); +# endif + return 0; +} +static int +codegen_PCMPGTW(codeblock_t *block, uop_t *uop) +{ + int dest_reg = HOST_REG_GET(uop->dest_reg_a_real); + int src_reg_b = HOST_REG_GET(uop->src_reg_b_real); + int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real); + int src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); + + if (REG_IS_Q(dest_size) && REG_IS_Q(src_size_b) && uop->dest_reg_a_real == uop->src_reg_a_real) { + host_x86_PCMPGTW_XREG_XREG(block, dest_reg, src_reg_b); + } +# ifdef RECOMPILER_DEBUG + else + fatal("PCMPGTW %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real); +# endif + return 0; +} +static int +codegen_PCMPGTD(codeblock_t *block, uop_t *uop) +{ + int dest_reg = HOST_REG_GET(uop->dest_reg_a_real); + int src_reg_b = HOST_REG_GET(uop->src_reg_b_real); + int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real); + int src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); + + if (REG_IS_Q(dest_size) && REG_IS_Q(src_size_b) && uop->dest_reg_a_real == uop->src_reg_a_real) { + host_x86_PCMPGTD_XREG_XREG(block, dest_reg, src_reg_b); + } +# ifdef RECOMPILER_DEBUG + else + fatal("PCMPGTD %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real); +# endif + return 0; +} + +static int +codegen_PF2ID(codeblock_t *block, uop_t *uop) +{ + int dest_reg = HOST_REG_GET(uop->dest_reg_a_real); + int src_reg_a = HOST_REG_GET(uop->src_reg_a_real); + int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real); + int src_size_a = IREG_GET_SIZE(uop->src_reg_a_real); + + if (REG_IS_Q(dest_size) && REG_IS_Q(src_size_a)) { + host_x86_LDMXCSR(block, &cpu_state.trunc_fp_control); + host_x86_CVTPS2DQ_XREG_XREG(block, dest_reg, src_reg_a); + host_x86_LDMXCSR(block, &cpu_state.old_fp_control); + } +# ifdef RECOMPILER_DEBUG + else + fatal("PF2ID %02x %02x\n", uop->dest_reg_a_real); +# endif + return 0; +} +static int +codegen_PFADD(codeblock_t *block, uop_t *uop) +{ + int dest_reg = HOST_REG_GET(uop->dest_reg_a_real); + int src_reg_b = HOST_REG_GET(uop->src_reg_b_real); + int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real); + int src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); + + if (REG_IS_Q(dest_size) && REG_IS_Q(src_size_b) && uop->dest_reg_a_real == uop->src_reg_a_real) { + host_x86_ADDPS_XREG_XREG(block, dest_reg, src_reg_b); + } +# ifdef RECOMPILER_DEBUG + else + fatal("PFADD %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real); +# endif + return 0; +} +static int +codegen_PFCMPEQ(codeblock_t *block, uop_t *uop) +{ + int dest_reg = HOST_REG_GET(uop->dest_reg_a_real); + int src_reg_b = HOST_REG_GET(uop->src_reg_b_real); + int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real); + int src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); + + if (REG_IS_Q(dest_size) && REG_IS_Q(src_size_b) && uop->dest_reg_a_real == uop->src_reg_a_real) { + host_x86_CMPPS_XREG_XREG(block, dest_reg, src_reg_b, CMPPS_EQ); + } +# ifdef RECOMPILER_DEBUG + else + fatal("PFCMPEQ %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real); +# endif + return 0; +} +static int +codegen_PFCMPGE(codeblock_t *block, uop_t *uop) +{ + int dest_reg = HOST_REG_GET(uop->dest_reg_a_real); + int src_reg_b = HOST_REG_GET(uop->src_reg_b_real); + int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real); + int src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); + + if (REG_IS_Q(dest_size) && REG_IS_Q(src_size_b) && uop->dest_reg_a_real == uop->src_reg_a_real) { + host_x86_CMPPS_XREG_XREG(block, dest_reg, src_reg_b, CMPPS_NLT); + } +# ifdef RECOMPILER_DEBUG + else + fatal("PFCMPGE %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real); +# endif + return 0; +} +static int +codegen_PFCMPGT(codeblock_t *block, uop_t *uop) +{ + int dest_reg = HOST_REG_GET(uop->dest_reg_a_real); + int src_reg_b = HOST_REG_GET(uop->src_reg_b_real); + int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real); + int src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); + + if (REG_IS_Q(dest_size) && REG_IS_Q(src_size_b) && uop->dest_reg_a_real == uop->src_reg_a_real) { + host_x86_CMPPS_XREG_XREG(block, dest_reg, src_reg_b, CMPPS_NLE); + } +# ifdef RECOMPILER_DEBUG + else + fatal("PFCMPGT %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real); +# endif + return 0; +} +static int +codegen_PFMAX(codeblock_t *block, uop_t *uop) +{ + int dest_reg = HOST_REG_GET(uop->dest_reg_a_real); + int src_reg_b = HOST_REG_GET(uop->src_reg_b_real); + int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real); + int src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); + + if (REG_IS_Q(dest_size) && REG_IS_Q(src_size_b) && uop->dest_reg_a_real == uop->src_reg_a_real) { + host_x86_MAXPS_XREG_XREG(block, dest_reg, src_reg_b); + } +# ifdef RECOMPILER_DEBUG + else + fatal("PFMAX %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real); +# endif + return 0; +} +static int +codegen_PFMIN(codeblock_t *block, uop_t *uop) +{ + int dest_reg = HOST_REG_GET(uop->dest_reg_a_real); + int src_reg_b = HOST_REG_GET(uop->src_reg_b_real); + int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real); + int src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); + + if (REG_IS_Q(dest_size) && REG_IS_Q(src_size_b) && uop->dest_reg_a_real == uop->src_reg_a_real) { + host_x86_MINPS_XREG_XREG(block, dest_reg, src_reg_b); + } +# ifdef RECOMPILER_DEBUG + else + fatal("PFMIN %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real); +# endif + return 0; +} +static int +codegen_PFMUL(codeblock_t *block, uop_t *uop) +{ + int dest_reg = HOST_REG_GET(uop->dest_reg_a_real); + int src_reg_b = HOST_REG_GET(uop->src_reg_b_real); + int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real); + int src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); + + if (REG_IS_Q(dest_size) && REG_IS_Q(src_size_b) && uop->dest_reg_a_real == uop->src_reg_a_real) { + host_x86_MULPS_XREG_XREG(block, dest_reg, src_reg_b); + } +# ifdef RECOMPILER_DEBUG + else + fatal("PFMUL %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real); +# endif + return 0; +} +static int +codegen_PFRCP(codeblock_t *block, uop_t *uop) +{ + int dest_reg = HOST_REG_GET(uop->dest_reg_a_real); + int src_reg_a = HOST_REG_GET(uop->src_reg_a_real); + int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real); + int src_size_a = IREG_GET_SIZE(uop->src_reg_a_real); + + if (REG_IS_Q(dest_size) && REG_IS_Q(src_size_a)) { + /*TODO: This could be improved (use RCPSS + iteration)*/ + host_x86_MOV32_REG_IMM(block, REG_ECX, 1); + host_x86_MOVQ_XREG_XREG(block, REG_XMM_TEMP, src_reg_a); + host_x86_CVTSI2SS_XREG_REG(block, dest_reg, REG_ECX); + host_x86_DIVSS_XREG_XREG(block, dest_reg, REG_XMM_TEMP); + host_x86_UNPCKLPS_XREG_XREG(block, dest_reg, dest_reg); + } +# ifdef RECOMPILER_DEBUG + else + fatal("PFRCP %02x %02x\n", uop->dest_reg_a_real); +# endif + return 0; +} +static int +codegen_PFRSQRT(codeblock_t *block, uop_t *uop) +{ + int dest_reg = HOST_REG_GET(uop->dest_reg_a_real); + int src_reg_a = HOST_REG_GET(uop->src_reg_a_real); + int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real); + int src_size_a = IREG_GET_SIZE(uop->src_reg_a_real); + + if (REG_IS_Q(dest_size) && REG_IS_Q(src_size_a)) { + /*TODO: This could be improved (use RSQRTSS + iteration)*/ + host_x86_SQRTSS_XREG_XREG(block, REG_XMM_TEMP, src_reg_a); + host_x86_MOV32_REG_IMM(block, REG_ECX, 1); + host_x86_CVTSI2SS_XREG_REG(block, dest_reg, REG_ECX); + host_x86_DIVSS_XREG_XREG(block, dest_reg, REG_XMM_TEMP); + host_x86_UNPCKLPS_XREG_XREG(block, dest_reg, dest_reg); + } +# ifdef RECOMPILER_DEBUG + else + fatal("PFRSQRT %02x %02x\n", uop->dest_reg_a_real); +# endif + return 0; +} +static int +codegen_PFSUB(codeblock_t *block, uop_t *uop) +{ + int dest_reg = HOST_REG_GET(uop->dest_reg_a_real); + int src_reg_a = HOST_REG_GET(uop->src_reg_a_real); + int src_reg_b = HOST_REG_GET(uop->src_reg_b_real); + int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real); + int src_size_a = IREG_GET_SIZE(uop->src_reg_a_real); + int src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); + + if (REG_IS_Q(dest_size) && REG_IS_Q(src_size_b) && uop->dest_reg_a_real == uop->src_reg_a_real) { + host_x86_SUBPS_XREG_XREG(block, dest_reg, src_reg_b); + } else if (REG_IS_Q(dest_size) && REG_IS_Q(src_size_a) && REG_IS_Q(src_size_b)) { + host_x86_MOVQ_XREG_XREG(block, REG_XMM_TEMP, src_reg_a); + host_x86_SUBPS_XREG_XREG(block, REG_XMM_TEMP, src_reg_b); + host_x86_MOVQ_XREG_XREG(block, dest_reg, REG_XMM_TEMP); + } +# ifdef RECOMPILER_DEBUG + else + fatal("PFSUB %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real); +# endif + return 0; +} +static int +codegen_PI2FD(codeblock_t *block, uop_t *uop) +{ + int dest_reg = HOST_REG_GET(uop->dest_reg_a_real); + int src_reg_a = HOST_REG_GET(uop->src_reg_a_real); + int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real); + int src_size_a = IREG_GET_SIZE(uop->src_reg_a_real); + + if (REG_IS_Q(dest_size) && REG_IS_Q(src_size_a)) { + host_x86_CVTDQ2PS_XREG_XREG(block, dest_reg, src_reg_a); + } +# ifdef RECOMPILER_DEBUG + else + fatal("PI2FD %02x %02x\n", uop->dest_reg_a_real); +# endif + return 0; +} + +static int +codegen_PMADDWD(codeblock_t *block, uop_t *uop) +{ + int dest_reg = HOST_REG_GET(uop->dest_reg_a_real); + int src_reg_b = HOST_REG_GET(uop->src_reg_b_real); + int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real); + int src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); + + if (REG_IS_Q(dest_size) && REG_IS_Q(src_size_b) && uop->dest_reg_a_real == uop->src_reg_a_real) { + host_x86_PMADDWD_XREG_XREG(block, dest_reg, src_reg_b); + } +# ifdef RECOMPILER_DEBUG + else + fatal("PMULHW %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real); +# endif + return 0; +} +static int +codegen_PMULHW(codeblock_t *block, uop_t *uop) +{ + int dest_reg = HOST_REG_GET(uop->dest_reg_a_real); + int src_reg_b = HOST_REG_GET(uop->src_reg_b_real); + int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real); + int src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); + + if (REG_IS_Q(dest_size) && REG_IS_Q(src_size_b) && uop->dest_reg_a_real == uop->src_reg_a_real) { + host_x86_PMULHW_XREG_XREG(block, dest_reg, src_reg_b); + } +# ifdef RECOMPILER_DEBUG + else + fatal("PMULHW %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real); +# endif + return 0; +} +static int +codegen_PMULLW(codeblock_t *block, uop_t *uop) +{ + int dest_reg = HOST_REG_GET(uop->dest_reg_a_real); + int src_reg_b = HOST_REG_GET(uop->src_reg_b_real); + int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real); + int src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); + + if (REG_IS_Q(dest_size) && REG_IS_Q(src_size_b) && uop->dest_reg_a_real == uop->src_reg_a_real) { + host_x86_PMULLW_XREG_XREG(block, dest_reg, src_reg_b); + } +# ifdef RECOMPILER_DEBUG + else + fatal("PMULLW %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real); +# endif + return 0; +} + +static int +codegen_PSLLW_IMM(codeblock_t *block, uop_t *uop) +{ + int dest_reg = HOST_REG_GET(uop->dest_reg_a_real); + int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real); + + if (REG_IS_Q(dest_size) && uop->dest_reg_a_real == uop->src_reg_a_real) { + host_x86_PSLLW_XREG_IMM(block, dest_reg, uop->imm_data); + } +# ifdef RECOMPILER_DEBUG + else + fatal("PSLLW_IMM %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real); +# endif + return 0; +} +static int +codegen_PSLLD_IMM(codeblock_t *block, uop_t *uop) +{ + int dest_reg = HOST_REG_GET(uop->dest_reg_a_real); + int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real); + + if (REG_IS_Q(dest_size) && uop->dest_reg_a_real == uop->src_reg_a_real) { + host_x86_PSLLD_XREG_IMM(block, dest_reg, uop->imm_data); + } +# ifdef RECOMPILER_DEBUG + else + fatal("PSLLD_IMM %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real); +# endif + return 0; +} +static int +codegen_PSLLQ_IMM(codeblock_t *block, uop_t *uop) +{ + int dest_reg = HOST_REG_GET(uop->dest_reg_a_real); + int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real); + + if (REG_IS_Q(dest_size) && uop->dest_reg_a_real == uop->src_reg_a_real) { + host_x86_PSLLQ_XREG_IMM(block, dest_reg, uop->imm_data); + } +# ifdef RECOMPILER_DEBUG + else + fatal("PSLLQ_IMM %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real); +# endif + return 0; +} +static int +codegen_PSRAW_IMM(codeblock_t *block, uop_t *uop) +{ + int dest_reg = HOST_REG_GET(uop->dest_reg_a_real); + int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real); + + if (REG_IS_Q(dest_size) && uop->dest_reg_a_real == uop->src_reg_a_real) { + host_x86_PSRAW_XREG_IMM(block, dest_reg, uop->imm_data); + } +# ifdef RECOMPILER_DEBUG + else + fatal("PSRAW_IMM %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real); +# endif + return 0; +} +static int +codegen_PSRAD_IMM(codeblock_t *block, uop_t *uop) +{ + int dest_reg = HOST_REG_GET(uop->dest_reg_a_real); + int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real); + + if (REG_IS_Q(dest_size) && uop->dest_reg_a_real == uop->src_reg_a_real) { + host_x86_PSRAD_XREG_IMM(block, dest_reg, uop->imm_data); + } +# ifdef RECOMPILER_DEBUG + else + fatal("PSRAD_IMM %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real); +# endif + return 0; +} +static int +codegen_PSRAQ_IMM(codeblock_t *block, uop_t *uop) +{ + int dest_reg = HOST_REG_GET(uop->dest_reg_a_real); + int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real); + + if (REG_IS_Q(dest_size) && uop->dest_reg_a_real == uop->src_reg_a_real) { + host_x86_PSRAQ_XREG_IMM(block, dest_reg, uop->imm_data); + } +# ifdef RECOMPILER_DEBUG + else + fatal("PSRAQ_IMM %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real); +# endif + return 0; +} +static int +codegen_PSRLW_IMM(codeblock_t *block, uop_t *uop) +{ + int dest_reg = HOST_REG_GET(uop->dest_reg_a_real); + int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real); + + if (REG_IS_Q(dest_size) && uop->dest_reg_a_real == uop->src_reg_a_real) { + host_x86_PSRLW_XREG_IMM(block, dest_reg, uop->imm_data); + } +# ifdef RECOMPILER_DEBUG + else + fatal("PSRLW_IMM %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real); +# endif + return 0; +} +static int +codegen_PSRLD_IMM(codeblock_t *block, uop_t *uop) +{ + int dest_reg = HOST_REG_GET(uop->dest_reg_a_real); + int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real); + + if (REG_IS_Q(dest_size) && uop->dest_reg_a_real == uop->src_reg_a_real) { + host_x86_PSRLD_XREG_IMM(block, dest_reg, uop->imm_data); + } +# ifdef RECOMPILER_DEBUG + else + fatal("PSRLD_IMM %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real); +# endif + return 0; +} +static int +codegen_PSRLQ_IMM(codeblock_t *block, uop_t *uop) +{ + int dest_reg = HOST_REG_GET(uop->dest_reg_a_real); + int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real); + + if (REG_IS_Q(dest_size) && uop->dest_reg_a_real == uop->src_reg_a_real) { + host_x86_PSRLQ_XREG_IMM(block, dest_reg, uop->imm_data); + } +# ifdef RECOMPILER_DEBUG + else + fatal("PSRLQ_IMM %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real); +# endif + return 0; +} + +static int +codegen_PSUBB(codeblock_t *block, uop_t *uop) +{ + int dest_reg = HOST_REG_GET(uop->dest_reg_a_real); + int src_reg_b = HOST_REG_GET(uop->src_reg_b_real); + int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real); + int src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); + + if (REG_IS_Q(dest_size) && REG_IS_Q(src_size_b) && uop->dest_reg_a_real == uop->src_reg_a_real) { + host_x86_PSUBB_XREG_XREG(block, dest_reg, src_reg_b); + } +# ifdef RECOMPILER_DEBUG + else + fatal("PSUBB %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real); +# endif + return 0; +} +static int +codegen_PSUBW(codeblock_t *block, uop_t *uop) +{ + int dest_reg = HOST_REG_GET(uop->dest_reg_a_real); + int src_reg_b = HOST_REG_GET(uop->src_reg_b_real); + int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real); + int src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); + + if (REG_IS_Q(dest_size) && REG_IS_Q(src_size_b) && uop->dest_reg_a_real == uop->src_reg_a_real) { + host_x86_PSUBW_XREG_XREG(block, dest_reg, src_reg_b); + } +# ifdef RECOMPILER_DEBUG + else + fatal("PSUBW %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real); +# endif + return 0; +} +static int +codegen_PSUBD(codeblock_t *block, uop_t *uop) +{ + int dest_reg = HOST_REG_GET(uop->dest_reg_a_real); + int src_reg_b = HOST_REG_GET(uop->src_reg_b_real); + int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real); + int src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); + + if (REG_IS_Q(dest_size) && REG_IS_Q(src_size_b) && uop->dest_reg_a_real == uop->src_reg_a_real) { + host_x86_PSUBD_XREG_XREG(block, dest_reg, src_reg_b); + } +# ifdef RECOMPILER_DEBUG + else + fatal("PSUBD %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real); +# endif + return 0; +} +static int +codegen_PSUBSB(codeblock_t *block, uop_t *uop) +{ + int dest_reg = HOST_REG_GET(uop->dest_reg_a_real); + int src_reg_b = HOST_REG_GET(uop->src_reg_b_real); + int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real); + int src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); + + if (REG_IS_Q(dest_size) && REG_IS_Q(src_size_b) && uop->dest_reg_a_real == uop->src_reg_a_real) { + host_x86_PSUBSB_XREG_XREG(block, dest_reg, src_reg_b); + } +# ifdef RECOMPILER_DEBUG + else + fatal("PSUBSB %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real); +# endif + return 0; +} +static int +codegen_PSUBSW(codeblock_t *block, uop_t *uop) +{ + int dest_reg = HOST_REG_GET(uop->dest_reg_a_real); + int src_reg_b = HOST_REG_GET(uop->src_reg_b_real); + int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real); + int src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); + + if (REG_IS_Q(dest_size) && REG_IS_Q(src_size_b) && uop->dest_reg_a_real == uop->src_reg_a_real) { + host_x86_PSUBSW_XREG_XREG(block, dest_reg, src_reg_b); + } +# ifdef RECOMPILER_DEBUG + else + fatal("PSUBSW %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real); +# endif + return 0; +} +static int +codegen_PSUBUSB(codeblock_t *block, uop_t *uop) +{ + int dest_reg = HOST_REG_GET(uop->dest_reg_a_real); + int src_reg_b = HOST_REG_GET(uop->src_reg_b_real); + int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real); + int src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); + + if (REG_IS_Q(dest_size) && REG_IS_Q(src_size_b) && uop->dest_reg_a_real == uop->src_reg_a_real) { + host_x86_PSUBUSB_XREG_XREG(block, dest_reg, src_reg_b); + } +# ifdef RECOMPILER_DEBUG + else + fatal("PSUBUSB %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real); +# endif + return 0; +} +static int +codegen_PSUBUSW(codeblock_t *block, uop_t *uop) +{ + int dest_reg = HOST_REG_GET(uop->dest_reg_a_real); + int src_reg_b = HOST_REG_GET(uop->src_reg_b_real); + int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real); + int src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); + + if (REG_IS_Q(dest_size) && REG_IS_Q(src_size_b) && uop->dest_reg_a_real == uop->src_reg_a_real) { + host_x86_PSUBUSW_XREG_XREG(block, dest_reg, src_reg_b); + } +# ifdef RECOMPILER_DEBUG + else + fatal("PSUBUSW %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real); +# endif + return 0; +} + +static int +codegen_PUNPCKHBW(codeblock_t *block, uop_t *uop) +{ + int dest_reg = HOST_REG_GET(uop->dest_reg_a_real); + int src_reg_b = HOST_REG_GET(uop->src_reg_b_real); + int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real); + int src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); + + if (REG_IS_Q(dest_size) && REG_IS_Q(src_size_b) && uop->dest_reg_a_real == uop->src_reg_a_real) { + host_x86_PUNPCKLBW_XREG_XREG(block, dest_reg, src_reg_b); + host_x86_PSHUFD_XREG_XREG_IMM(block, dest_reg, dest_reg, 0xee); /*0xee = move top 64-bits to low 64-bits*/ + } +# ifdef RECOMPILER_DEBUG + else + fatal("PUNPCKHBW %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real); +# endif + return 0; +} +static int +codegen_PUNPCKHWD(codeblock_t *block, uop_t *uop) +{ + int dest_reg = HOST_REG_GET(uop->dest_reg_a_real); + int src_reg_b = HOST_REG_GET(uop->src_reg_b_real); + int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real); + int src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); + + if (REG_IS_Q(dest_size) && REG_IS_Q(src_size_b) && uop->dest_reg_a_real == uop->src_reg_a_real) { + host_x86_PUNPCKLWD_XREG_XREG(block, dest_reg, src_reg_b); + host_x86_PSHUFD_XREG_XREG_IMM(block, dest_reg, dest_reg, 0xee); /*0xee = move top 64-bits to low 64-bits*/ + } +# ifdef RECOMPILER_DEBUG + else + fatal("PUNPCKHWD %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real); +# endif + return 0; +} +static int +codegen_PUNPCKHDQ(codeblock_t *block, uop_t *uop) +{ + int dest_reg = HOST_REG_GET(uop->dest_reg_a_real); + int src_reg_b = HOST_REG_GET(uop->src_reg_b_real); + int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real); + int src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); + + if (REG_IS_Q(dest_size) && REG_IS_Q(src_size_b) && uop->dest_reg_a_real == uop->src_reg_a_real) { + host_x86_PUNPCKLDQ_XREG_XREG(block, dest_reg, src_reg_b); + host_x86_PSHUFD_XREG_XREG_IMM(block, dest_reg, dest_reg, 0xee); /*0xee = move top 64-bits to low 64-bits*/ + } +# ifdef RECOMPILER_DEBUG + else + fatal("PUNPCKHDQ %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real); +# endif + return 0; +} +static int +codegen_PUNPCKLBW(codeblock_t *block, uop_t *uop) +{ + int dest_reg = HOST_REG_GET(uop->dest_reg_a_real); + int src_reg_b = HOST_REG_GET(uop->src_reg_b_real); + int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real); + int src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); + + if (REG_IS_Q(dest_size) && REG_IS_Q(src_size_b) && uop->dest_reg_a_real == uop->src_reg_a_real) { + host_x86_PUNPCKLBW_XREG_XREG(block, dest_reg, src_reg_b); + } +# ifdef RECOMPILER_DEBUG + else + fatal("PUNPCKLBW %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real); +# endif + return 0; +} +static int +codegen_PUNPCKLWD(codeblock_t *block, uop_t *uop) +{ + int dest_reg = HOST_REG_GET(uop->dest_reg_a_real); + int src_reg_b = HOST_REG_GET(uop->src_reg_b_real); + int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real); + int src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); + + if (REG_IS_Q(dest_size) && REG_IS_Q(src_size_b) && uop->dest_reg_a_real == uop->src_reg_a_real) { + host_x86_PUNPCKLWD_XREG_XREG(block, dest_reg, src_reg_b); + } +# ifdef RECOMPILER_DEBUG + else + fatal("PUNPCKLWD %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real); +# endif + return 0; +} +static int +codegen_PUNPCKLDQ(codeblock_t *block, uop_t *uop) +{ + int dest_reg = HOST_REG_GET(uop->dest_reg_a_real); + int src_reg_b = HOST_REG_GET(uop->src_reg_b_real); + int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real); + int src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); + + if (REG_IS_Q(dest_size) && REG_IS_Q(src_size_b) && uop->dest_reg_a_real == uop->src_reg_a_real) { + host_x86_PUNPCKLDQ_XREG_XREG(block, dest_reg, src_reg_b); + } +# ifdef RECOMPILER_DEBUG + else + fatal("PUNPCKLDQ %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real); +# endif + return 0; +} + +static int +codegen_ROL(codeblock_t *block, uop_t *uop) +{ + int dest_reg = HOST_REG_GET(uop->dest_reg_a_real); + int src_reg = HOST_REG_GET(uop->src_reg_a_real); + int shift_reg = HOST_REG_GET(uop->src_reg_b_real); + int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real); + int src_size = IREG_GET_SIZE(uop->src_reg_a_real); + + host_x86_MOV32_REG_REG(block, REG_ECX, shift_reg); + if (REG_IS_L(dest_size) && REG_IS_L(src_size)) { + if (uop->dest_reg_a_real != uop->src_reg_a_real) + host_x86_MOV32_REG_REG(block, dest_reg, src_reg); + host_x86_ROL32_CL(block, dest_reg); + } else if (REG_IS_W(dest_size) && REG_IS_W(src_size)) { + if (uop->dest_reg_a_real != uop->src_reg_a_real) + host_x86_MOV16_REG_REG(block, dest_reg, src_reg); + host_x86_ROL16_CL(block, dest_reg); + } else if (REG_IS_B(dest_size) && REG_IS_B(src_size)) { + if (uop->dest_reg_a_real != uop->src_reg_a_real) + host_x86_MOV8_REG_REG(block, dest_reg, src_reg); + host_x86_ROL8_CL(block, dest_reg); + } +# ifdef RECOMPILER_DEBUG + else + fatal("ROL %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real); +# endif + return 0; +} +static int +codegen_ROL_IMM(codeblock_t *block, uop_t *uop) +{ + int dest_reg = HOST_REG_GET(uop->dest_reg_a_real); + int src_reg = HOST_REG_GET(uop->src_reg_a_real); + int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real); + int src_size = IREG_GET_SIZE(uop->src_reg_a_real); + + if (REG_IS_L(dest_size) && REG_IS_L(src_size)) { + if (uop->dest_reg_a_real != uop->src_reg_a_real) + host_x86_MOV32_REG_REG(block, dest_reg, src_reg); + host_x86_ROL32_IMM(block, dest_reg, uop->imm_data); + } else if (REG_IS_W(dest_size) && REG_IS_W(src_size)) { + if (uop->dest_reg_a_real != uop->src_reg_a_real) + host_x86_MOV16_REG_REG(block, dest_reg, src_reg); + host_x86_ROL16_IMM(block, dest_reg, uop->imm_data); + } else if (REG_IS_B(dest_size) && REG_IS_B(src_size)) { + if (uop->dest_reg_a_real != uop->src_reg_a_real) + host_x86_MOV8_REG_REG(block, dest_reg, src_reg); + host_x86_ROL8_IMM(block, dest_reg, uop->imm_data); + } +# ifdef RECOMPILER_DEBUG + else + fatal("ROL_IMM %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real); +# endif + return 0; +} +static int +codegen_ROR(codeblock_t *block, uop_t *uop) +{ + int dest_reg = HOST_REG_GET(uop->dest_reg_a_real); + int src_reg = HOST_REG_GET(uop->src_reg_a_real); + int shift_reg = HOST_REG_GET(uop->src_reg_b_real); + int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real); + int src_size = IREG_GET_SIZE(uop->src_reg_a_real); + + host_x86_MOV32_REG_REG(block, REG_ECX, shift_reg); + if (REG_IS_L(dest_size) && REG_IS_L(src_size)) { + if (uop->dest_reg_a_real != uop->src_reg_a_real) + host_x86_MOV32_REG_REG(block, dest_reg, src_reg); + host_x86_ROR32_CL(block, dest_reg); + } else if (REG_IS_W(dest_size) && REG_IS_W(src_size)) { + if (uop->dest_reg_a_real != uop->src_reg_a_real) + host_x86_MOV16_REG_REG(block, dest_reg, src_reg); + host_x86_ROR16_CL(block, dest_reg); + } else if (REG_IS_B(dest_size) && REG_IS_B(src_size)) { + if (uop->dest_reg_a_real != uop->src_reg_a_real) + host_x86_MOV8_REG_REG(block, dest_reg, src_reg); + host_x86_ROR8_CL(block, dest_reg); + } +# ifdef RECOMPILER_DEBUG + else + fatal("ROR %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real); +# endif + return 0; +} +static int +codegen_ROR_IMM(codeblock_t *block, uop_t *uop) +{ + int dest_reg = HOST_REG_GET(uop->dest_reg_a_real); + int src_reg = HOST_REG_GET(uop->src_reg_a_real); + int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real); + int src_size = IREG_GET_SIZE(uop->src_reg_a_real); + + if (REG_IS_L(dest_size) && REG_IS_L(src_size)) { + if (uop->dest_reg_a_real != uop->src_reg_a_real) + host_x86_MOV32_REG_REG(block, dest_reg, src_reg); + host_x86_ROR32_IMM(block, dest_reg, uop->imm_data); + } else if (REG_IS_W(dest_size) && REG_IS_W(src_size)) { + if (uop->dest_reg_a_real != uop->src_reg_a_real) + host_x86_MOV16_REG_REG(block, dest_reg, src_reg); + host_x86_ROR16_IMM(block, dest_reg, uop->imm_data); + } else if (REG_IS_B(dest_size) && REG_IS_B(src_size)) { + if (uop->dest_reg_a_real != uop->src_reg_a_real) + host_x86_MOV8_REG_REG(block, dest_reg, src_reg); + host_x86_ROR8_IMM(block, dest_reg, uop->imm_data); + } +# ifdef RECOMPILER_DEBUG + else + fatal("ROR_IMM %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real); +# endif + return 0; +} + +static int +codegen_SAR(codeblock_t *block, uop_t *uop) +{ + int dest_reg = HOST_REG_GET(uop->dest_reg_a_real); + int src_reg = HOST_REG_GET(uop->src_reg_a_real); + int shift_reg = HOST_REG_GET(uop->src_reg_b_real); + int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real); + int src_size = IREG_GET_SIZE(uop->src_reg_a_real); + + host_x86_MOV32_REG_REG(block, REG_ECX, shift_reg); + if (REG_IS_L(dest_size) && REG_IS_L(src_size)) { + if (uop->dest_reg_a_real != uop->src_reg_a_real) + host_x86_MOV32_REG_REG(block, dest_reg, src_reg); + host_x86_SAR32_CL(block, dest_reg); + } else if (REG_IS_W(dest_size) && REG_IS_W(src_size)) { + if (uop->dest_reg_a_real != uop->src_reg_a_real) + host_x86_MOV16_REG_REG(block, dest_reg, src_reg); + host_x86_SAR16_CL(block, dest_reg); + } else if (REG_IS_B(dest_size) && REG_IS_B(src_size)) { + if (uop->dest_reg_a_real != uop->src_reg_a_real) + host_x86_MOV8_REG_REG(block, dest_reg, src_reg); + host_x86_SAR8_CL(block, dest_reg); + } +# ifdef RECOMPILER_DEBUG + else + fatal("SAR %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real); +# endif + return 0; +} +static int +codegen_SAR_IMM(codeblock_t *block, uop_t *uop) +{ + int dest_reg = HOST_REG_GET(uop->dest_reg_a_real); + int src_reg = HOST_REG_GET(uop->src_reg_a_real); + int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real); + int src_size = IREG_GET_SIZE(uop->src_reg_a_real); + + if (REG_IS_L(dest_size) && REG_IS_L(src_size)) { + if (uop->dest_reg_a_real != uop->src_reg_a_real) + host_x86_MOV32_REG_REG(block, dest_reg, src_reg); + host_x86_SAR32_IMM(block, dest_reg, uop->imm_data); + } else if (REG_IS_W(dest_size) && REG_IS_W(src_size)) { + if (uop->dest_reg_a_real != uop->src_reg_a_real) + host_x86_MOV16_REG_REG(block, dest_reg, src_reg); + host_x86_SAR16_IMM(block, dest_reg, uop->imm_data); + } else if (REG_IS_B(dest_size) && REG_IS_B(src_size)) { + if (uop->dest_reg_a_real != uop->src_reg_a_real) + host_x86_MOV8_REG_REG(block, dest_reg, src_reg); + host_x86_SAR8_IMM(block, dest_reg, uop->imm_data); + } +# ifdef RECOMPILER_DEBUG + else + fatal("SAR_IMM %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real); +# endif + return 0; +} +static int +codegen_SHL(codeblock_t *block, uop_t *uop) +{ + int dest_reg = HOST_REG_GET(uop->dest_reg_a_real); + int src_reg = HOST_REG_GET(uop->src_reg_a_real); + int shift_reg = HOST_REG_GET(uop->src_reg_b_real); + int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real); + int src_size = IREG_GET_SIZE(uop->src_reg_a_real); + + host_x86_MOV32_REG_REG(block, REG_ECX, shift_reg); + if (REG_IS_L(dest_size) && REG_IS_L(src_size)) { + if (uop->dest_reg_a_real != uop->src_reg_a_real) + host_x86_MOV32_REG_REG(block, dest_reg, src_reg); + host_x86_SHL32_CL(block, dest_reg); + } else if (REG_IS_W(dest_size) && REG_IS_W(src_size)) { + if (uop->dest_reg_a_real != uop->src_reg_a_real) + host_x86_MOV16_REG_REG(block, dest_reg, src_reg); + host_x86_SHL16_CL(block, dest_reg); + } else if (REG_IS_B(dest_size) && REG_IS_B(src_size)) { + if (uop->dest_reg_a_real != uop->src_reg_a_real) + host_x86_MOV8_REG_REG(block, dest_reg, src_reg); + host_x86_SHL8_CL(block, dest_reg); + } +# ifdef RECOMPILER_DEBUG + else + fatal("SHL %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real); +# endif + return 0; +} +static int +codegen_SHL_IMM(codeblock_t *block, uop_t *uop) +{ + int dest_reg = HOST_REG_GET(uop->dest_reg_a_real); + int src_reg = HOST_REG_GET(uop->src_reg_a_real); + int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real); + int src_size = IREG_GET_SIZE(uop->src_reg_a_real); + + if (REG_IS_L(dest_size) && REG_IS_L(src_size)) { + if (uop->dest_reg_a_real != uop->src_reg_a_real) + host_x86_MOV32_REG_REG(block, dest_reg, src_reg); + host_x86_SHL32_IMM(block, dest_reg, uop->imm_data); + } else if (REG_IS_W(dest_size) && REG_IS_W(src_size)) { + if (uop->dest_reg_a_real != uop->src_reg_a_real) + host_x86_MOV16_REG_REG(block, dest_reg, src_reg); + host_x86_SHL16_IMM(block, dest_reg, uop->imm_data); + } else if (REG_IS_B(dest_size) && REG_IS_B(src_size)) { + if (uop->dest_reg_a_real != uop->src_reg_a_real) + host_x86_MOV8_REG_REG(block, dest_reg, src_reg); + host_x86_SHL8_IMM(block, dest_reg, uop->imm_data); + } +# ifdef RECOMPILER_DEBUG + else + fatal("SHL_IMM %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real); +# endif + return 0; +} +static int +codegen_SHR(codeblock_t *block, uop_t *uop) +{ + int dest_reg = HOST_REG_GET(uop->dest_reg_a_real); + int src_reg = HOST_REG_GET(uop->src_reg_a_real); + int shift_reg = HOST_REG_GET(uop->src_reg_b_real); + int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real); + int src_size = IREG_GET_SIZE(uop->src_reg_a_real); + + host_x86_MOV32_REG_REG(block, REG_ECX, shift_reg); + if (REG_IS_L(dest_size) && REG_IS_L(src_size)) { + if (uop->dest_reg_a_real != uop->src_reg_a_real) + host_x86_MOV32_REG_REG(block, dest_reg, src_reg); + host_x86_SHR32_CL(block, dest_reg); + } else if (REG_IS_W(dest_size) && REG_IS_W(src_size)) { + if (uop->dest_reg_a_real != uop->src_reg_a_real) + host_x86_MOV16_REG_REG(block, dest_reg, src_reg); + host_x86_SHR16_CL(block, dest_reg); + } else if (REG_IS_B(dest_size) && REG_IS_B(src_size)) { + if (uop->dest_reg_a_real != uop->src_reg_a_real) + host_x86_MOV8_REG_REG(block, dest_reg, src_reg); + host_x86_SHR8_CL(block, dest_reg); + } +# ifdef RECOMPILER_DEBUG + else + fatal("SHR %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real); +# endif + return 0; +} +static int +codegen_SHR_IMM(codeblock_t *block, uop_t *uop) +{ + int dest_reg = HOST_REG_GET(uop->dest_reg_a_real); + int src_reg = HOST_REG_GET(uop->src_reg_a_real); + int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real); + int src_size = IREG_GET_SIZE(uop->src_reg_a_real); + + if (REG_IS_L(dest_size) && REG_IS_L(src_size)) { + if (uop->dest_reg_a_real != uop->src_reg_a_real) + host_x86_MOV32_REG_REG(block, dest_reg, src_reg); + host_x86_SHR32_IMM(block, dest_reg, uop->imm_data); + } else if (REG_IS_W(dest_size) && REG_IS_W(src_size)) { + if (uop->dest_reg_a_real != uop->src_reg_a_real) + host_x86_MOV16_REG_REG(block, dest_reg, src_reg); + host_x86_SHR16_IMM(block, dest_reg, uop->imm_data); + } else if (REG_IS_B(dest_size) && REG_IS_B(src_size)) { + if (uop->dest_reg_a_real != uop->src_reg_a_real) + host_x86_MOV8_REG_REG(block, dest_reg, src_reg); + host_x86_SHR8_IMM(block, dest_reg, uop->imm_data); + } +# ifdef RECOMPILER_DEBUG + else + fatal("SHR_IMM %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real); +# endif + return 0; +} + +static int +codegen_STORE_PTR_IMM(codeblock_t *block, uop_t *uop) +{ + host_x86_MOV32_ABS_IMM(block, uop->p, uop->imm_data); + return 0; +} +static int +codegen_STORE_PTR_IMM_8(codeblock_t *block, uop_t *uop) +{ + host_x86_MOV8_ABS_IMM(block, uop->p, uop->imm_data); + return 0; +} +static int +codegen_STORE_PTR_IMM_16(codeblock_t *block, uop_t *uop) +{ + host_x86_MOV16_ABS_IMM(block, uop->p, uop->imm_data); + return 0; +} + +static int +codegen_SUB(codeblock_t *block, uop_t *uop) +{ + int dest_reg = HOST_REG_GET(uop->dest_reg_a_real); + int src_reg_a = HOST_REG_GET(uop->src_reg_a_real); + int src_reg_b = HOST_REG_GET(uop->src_reg_b_real); + int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real); + int src_size_a = IREG_GET_SIZE(uop->src_reg_a_real); + int src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); + + if (REG_IS_L(dest_size) && REG_IS_L(src_size_a) && REG_IS_L(src_size_b)) { + if (uop->dest_reg_a_real != uop->src_reg_a_real) + host_x86_MOV32_REG_REG(block, dest_reg, src_reg_a); + host_x86_SUB32_REG_REG(block, dest_reg, src_reg_b); + } else if (REG_IS_W(dest_size) && REG_IS_W(src_size_a) && REG_IS_W(src_size_b)) { + if (uop->dest_reg_a_real != uop->src_reg_a_real) + host_x86_MOV16_REG_REG(block, dest_reg, src_reg_a); + host_x86_SUB16_REG_REG(block, dest_reg, src_reg_b); + } else if (REG_IS_B(dest_size) && REG_IS_B(src_size_a) && REG_IS_B(src_size_b)) { + if (uop->dest_reg_a_real != uop->src_reg_a_real) + host_x86_MOV8_REG_REG(block, dest_reg, src_reg_a); + host_x86_SUB8_REG_REG(block, dest_reg, src_reg_b); + } +# ifdef RECOMPILER_DEBUG + else + fatal("SUB %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real); +# endif + return 0; +} +static int +codegen_SUB_IMM(codeblock_t *block, uop_t *uop) +{ + int dest_reg = HOST_REG_GET(uop->dest_reg_a_real); + int src_reg = HOST_REG_GET(uop->src_reg_a_real); + int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real); + int src_size = IREG_GET_SIZE(uop->src_reg_a_real); + + if (REG_IS_L(dest_size) && REG_IS_L(src_size)) { + if (dest_reg != src_reg) + host_x86_MOV32_REG_REG(block, dest_reg, src_reg); + host_x86_SUB32_REG_IMM(block, dest_reg, uop->imm_data); + } else if (REG_IS_W(dest_size) && REG_IS_W(src_size)) { + if (dest_reg != src_reg) + host_x86_MOV16_REG_REG(block, dest_reg, src_reg); + host_x86_SUB16_REG_IMM(block, dest_reg, uop->imm_data); + } else if (REG_IS_B(dest_size) && REG_IS_B(src_size)) { + if (dest_reg != src_reg) + host_x86_MOV8_REG_REG(block, dest_reg, src_reg); + host_x86_SUB8_REG_IMM(block, dest_reg, uop->imm_data); + } +# ifdef RECOMPILER_DEBUG + else + fatal("SUB_IMM %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real); +# endif + return 0; +} + +static int +codegen_TEST_JNS_DEST(codeblock_t *block, uop_t *uop) +{ + int src_reg = HOST_REG_GET(uop->src_reg_a_real); + int src_size = IREG_GET_SIZE(uop->src_reg_a_real); + + if (REG_IS_L(src_size)) { + host_x86_TEST32_REG(block, src_reg, src_reg); + } else if (REG_IS_W(src_size)) { + host_x86_TEST16_REG(block, src_reg, src_reg); + } else if (REG_IS_B(src_size)) { + host_x86_TEST8_REG(block, src_reg, src_reg); + } +# ifdef RECOMPILER_DEBUG + else + fatal("TEST_JNS_DEST %02x\n", uop->src_reg_a_real); +# endif + uop->p = host_x86_JNS_long(block); + + return 0; +} +static int +codegen_TEST_JS_DEST(codeblock_t *block, uop_t *uop) +{ + int src_reg = HOST_REG_GET(uop->src_reg_a_real); + int src_size = IREG_GET_SIZE(uop->src_reg_a_real); + + if (REG_IS_L(src_size)) { + host_x86_TEST32_REG(block, src_reg, src_reg); + } else if (REG_IS_W(src_size)) { + host_x86_TEST16_REG(block, src_reg, src_reg); + } else if (REG_IS_B(src_size)) { + host_x86_TEST8_REG(block, src_reg, src_reg); + } +# ifdef RECOMPILER_DEBUG + else + fatal("TEST_JS_DEST %02x\n", uop->src_reg_a_real); +# endif + uop->p = host_x86_JS_long(block); + + return 0; +} + +static int +codegen_XOR(codeblock_t *block, uop_t *uop) +{ + int dest_reg = HOST_REG_GET(uop->dest_reg_a_real); + int src_reg_b = HOST_REG_GET(uop->src_reg_b_real); + int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real); + int src_size_a = IREG_GET_SIZE(uop->src_reg_a_real); + int src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); + + if (REG_IS_Q(dest_size) && REG_IS_Q(src_size_a) && REG_IS_Q(src_size_b) && uop->dest_reg_a_real == uop->src_reg_a_real) { + host_x86_PXOR_XREG_XREG(block, dest_reg, src_reg_b); + } else if (REG_IS_L(dest_size) && REG_IS_L(src_size_a) && REG_IS_L(src_size_b) && uop->dest_reg_a_real == uop->src_reg_a_real) { + host_x86_XOR32_REG_REG(block, dest_reg, src_reg_b); + } else if (REG_IS_W(dest_size) && REG_IS_W(src_size_a) && REG_IS_W(src_size_b) && uop->dest_reg_a_real == uop->src_reg_a_real) { + host_x86_XOR16_REG_REG(block, dest_reg, src_reg_b); + } else if (REG_IS_B(dest_size) && REG_IS_B(src_size_a) && REG_IS_B(src_size_b) && uop->dest_reg_a_real == uop->src_reg_a_real) { + host_x86_XOR8_REG_REG(block, dest_reg, src_reg_b); + } +# ifdef RECOMPILER_DEBUG + else + fatal("XOR %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real); +# endif + return 0; +} +static int +codegen_XOR_IMM(codeblock_t *block, uop_t *uop) +{ + int dest_reg = HOST_REG_GET(uop->dest_reg_a_real); + int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real); + int src_size = IREG_GET_SIZE(uop->src_reg_a_real); + + if (REG_IS_L(dest_size) && REG_IS_L(src_size) && uop->dest_reg_a_real == uop->src_reg_a_real) { + host_x86_XOR32_REG_IMM(block, dest_reg, uop->imm_data); + } else if (REG_IS_W(dest_size) && REG_IS_W(src_size) && uop->dest_reg_a_real == uop->src_reg_a_real) { + host_x86_XOR16_REG_IMM(block, dest_reg, uop->imm_data); + } else if (REG_IS_B(dest_size) && REG_IS_B(src_size) && uop->dest_reg_a_real == uop->src_reg_a_real) { + host_x86_XOR8_REG_IMM(block, dest_reg, uop->imm_data); + } +# ifdef RECOMPILER_DEBUG + else + fatal("XOR_IMM %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real); +# endif + return 0; +} + +# ifdef DEBUG_EXTRA +static int +codegen_LOG_INSTR(codeblock_t *block, uop_t *uop) +{ + if (uop->imm_data > 256 * 256) + fatal("LOG_INSTR %08x\n", uop->imm_data); + host_x86_INC32_ABS(block, &instr_counts[uop->imm_data]); + return 0; +} +# endif + +const uOpFn uop_handlers[UOP_MAX] = { + [UOP_CALL_FUNC & UOP_MASK] = codegen_CALL_FUNC, + [UOP_CALL_FUNC_RESULT & + UOP_MASK] + = codegen_CALL_FUNC_RESULT, + [UOP_CALL_INSTRUCTION_FUNC & + UOP_MASK] + = codegen_CALL_INSTRUCTION_FUNC, + + [UOP_JMP & + UOP_MASK] + = codegen_JMP, + [UOP_JMP_DEST & + UOP_MASK] + = codegen_JMP_DEST, + + [UOP_LOAD_SEG & + UOP_MASK] + = codegen_LOAD_SEG, + + [UOP_LOAD_FUNC_ARG_0 & + UOP_MASK] + = codegen_LOAD_FUNC_ARG0, + [UOP_LOAD_FUNC_ARG_1 & + UOP_MASK] + = codegen_LOAD_FUNC_ARG1, + [UOP_LOAD_FUNC_ARG_2 & + UOP_MASK] + = codegen_LOAD_FUNC_ARG2, + [UOP_LOAD_FUNC_ARG_3 & + UOP_MASK] + = codegen_LOAD_FUNC_ARG3, + + [UOP_LOAD_FUNC_ARG_0_IMM & + UOP_MASK] + = codegen_LOAD_FUNC_ARG0_IMM, + [UOP_LOAD_FUNC_ARG_1_IMM & + UOP_MASK] + = codegen_LOAD_FUNC_ARG1_IMM, + [UOP_LOAD_FUNC_ARG_2_IMM & + UOP_MASK] + = codegen_LOAD_FUNC_ARG2_IMM, + [UOP_LOAD_FUNC_ARG_3_IMM & + UOP_MASK] + = codegen_LOAD_FUNC_ARG3_IMM, + + [UOP_STORE_P_IMM & + UOP_MASK] + = codegen_STORE_PTR_IMM, + [UOP_STORE_P_IMM_8 & + UOP_MASK] + = codegen_STORE_PTR_IMM_8, + [UOP_STORE_P_IMM_16 & + UOP_MASK] + = codegen_STORE_PTR_IMM_16, + + [UOP_MEM_LOAD_ABS & + UOP_MASK] + = codegen_MEM_LOAD_ABS, + [UOP_MEM_LOAD_REG & + UOP_MASK] + = codegen_MEM_LOAD_REG, + [UOP_MEM_LOAD_SINGLE & + UOP_MASK] + = codegen_MEM_LOAD_SINGLE, + [UOP_MEM_LOAD_DOUBLE & + UOP_MASK] + = codegen_MEM_LOAD_DOUBLE, + + [UOP_MEM_STORE_ABS & + UOP_MASK] + = codegen_MEM_STORE_ABS, + [UOP_MEM_STORE_REG & + UOP_MASK] + = codegen_MEM_STORE_REG, + [UOP_MEM_STORE_IMM_8 & + UOP_MASK] + = codegen_MEM_STORE_IMM_8, + [UOP_MEM_STORE_IMM_16 & + UOP_MASK] + = codegen_MEM_STORE_IMM_16, + [UOP_MEM_STORE_IMM_32 & + UOP_MASK] + = codegen_MEM_STORE_IMM_32, + [UOP_MEM_STORE_SINGLE & + UOP_MASK] + = codegen_MEM_STORE_SINGLE, + [UOP_MEM_STORE_DOUBLE & + UOP_MASK] + = codegen_MEM_STORE_DOUBLE, + + [UOP_MOV & + UOP_MASK] + = codegen_MOV, + [UOP_MOV_PTR & + UOP_MASK] + = codegen_MOV_PTR, + [UOP_MOV_IMM & + UOP_MASK] + = codegen_MOV_IMM, + [UOP_MOVSX & + UOP_MASK] + = codegen_MOVSX, + [UOP_MOVZX & + UOP_MASK] + = codegen_MOVZX, + [UOP_MOV_DOUBLE_INT & + UOP_MASK] + = codegen_MOV_DOUBLE_INT, + [UOP_MOV_INT_DOUBLE & + UOP_MASK] + = codegen_MOV_INT_DOUBLE, + [UOP_MOV_INT_DOUBLE_64 & + UOP_MASK] + = codegen_MOV_INT_DOUBLE_64, + [UOP_MOV_REG_PTR & + UOP_MASK] + = codegen_MOV_REG_PTR, + [UOP_MOVZX_REG_PTR_8 & + UOP_MASK] + = codegen_MOVZX_REG_PTR_8, + [UOP_MOVZX_REG_PTR_16 & + UOP_MASK] + = codegen_MOVZX_REG_PTR_16, + + [UOP_ADD & + UOP_MASK] + = codegen_ADD, + [UOP_ADD_IMM & + UOP_MASK] + = codegen_ADD_IMM, + [UOP_ADD_LSHIFT & + UOP_MASK] + = codegen_ADD_LSHIFT, + [UOP_AND & + UOP_MASK] + = codegen_AND, + [UOP_AND_IMM & + UOP_MASK] + = codegen_AND_IMM, + [UOP_ANDN & + UOP_MASK] + = codegen_ANDN, + [UOP_OR & + UOP_MASK] + = codegen_OR, + [UOP_OR_IMM & + UOP_MASK] + = codegen_OR_IMM, + [UOP_SUB & + UOP_MASK] + = codegen_SUB, + [UOP_SUB_IMM & + UOP_MASK] + = codegen_SUB_IMM, + [UOP_XOR & + UOP_MASK] + = codegen_XOR, + [UOP_XOR_IMM & + UOP_MASK] + = codegen_XOR_IMM, + + [UOP_SAR & + UOP_MASK] + = codegen_SAR, + [UOP_SAR_IMM & + UOP_MASK] + = codegen_SAR_IMM, + [UOP_SHL & + UOP_MASK] + = codegen_SHL, + [UOP_SHL_IMM & + UOP_MASK] + = codegen_SHL_IMM, + [UOP_SHR & + UOP_MASK] + = codegen_SHR, + [UOP_SHR_IMM & + UOP_MASK] + = codegen_SHR_IMM, + [UOP_ROL & + UOP_MASK] + = codegen_ROL, + [UOP_ROL_IMM & + UOP_MASK] + = codegen_ROL_IMM, + [UOP_ROR & + UOP_MASK] + = codegen_ROR, + [UOP_ROR_IMM & + UOP_MASK] + = codegen_ROR_IMM, + + [UOP_CMP_IMM_JZ & + UOP_MASK] + = codegen_CMP_IMM_JZ, + + [UOP_CMP_JB & + UOP_MASK] + = codegen_CMP_JB, + [UOP_CMP_JNBE & + UOP_MASK] + = codegen_CMP_JNBE, + + [UOP_CMP_JNB_DEST & + UOP_MASK] + = codegen_CMP_JNB_DEST, + [UOP_CMP_JNBE_DEST & + UOP_MASK] + = codegen_CMP_JNBE_DEST, + [UOP_CMP_JNL_DEST & + UOP_MASK] + = codegen_CMP_JNL_DEST, + [UOP_CMP_JNLE_DEST & + UOP_MASK] + = codegen_CMP_JNLE_DEST, + [UOP_CMP_JNO_DEST & + UOP_MASK] + = codegen_CMP_JNO_DEST, + [UOP_CMP_JNZ_DEST & + UOP_MASK] + = codegen_CMP_JNZ_DEST, + [UOP_CMP_JB_DEST & + UOP_MASK] + = codegen_CMP_JB_DEST, + [UOP_CMP_JBE_DEST & + UOP_MASK] + = codegen_CMP_JBE_DEST, + [UOP_CMP_JL_DEST & + UOP_MASK] + = codegen_CMP_JL_DEST, + [UOP_CMP_JLE_DEST & + UOP_MASK] + = codegen_CMP_JLE_DEST, + [UOP_CMP_JO_DEST & + UOP_MASK] + = codegen_CMP_JO_DEST, + [UOP_CMP_JZ_DEST & + UOP_MASK] + = codegen_CMP_JZ_DEST, + + [UOP_CMP_IMM_JNZ_DEST & + UOP_MASK] + = codegen_CMP_IMM_JNZ_DEST, + [UOP_CMP_IMM_JZ_DEST & + UOP_MASK] + = codegen_CMP_IMM_JZ_DEST, + + [UOP_TEST_JNS_DEST & + UOP_MASK] + = codegen_TEST_JNS_DEST, + [UOP_TEST_JS_DEST & + UOP_MASK] + = codegen_TEST_JS_DEST, + + [UOP_FP_ENTER & + UOP_MASK] + = codegen_FP_ENTER, + [UOP_MMX_ENTER & + UOP_MASK] + = codegen_MMX_ENTER, + + [UOP_FADD & + UOP_MASK] + = codegen_FADD, + [UOP_FDIV & + UOP_MASK] + = codegen_FDIV, + [UOP_FMUL & + UOP_MASK] + = codegen_FMUL, + [UOP_FSUB & + UOP_MASK] + = codegen_FSUB, + [UOP_FCOM & + UOP_MASK] + = codegen_FCOM, + + [UOP_FABS & + UOP_MASK] + = codegen_FABS, + [UOP_FCHS & + UOP_MASK] + = codegen_FCHS, + [UOP_FSQRT & + UOP_MASK] + = codegen_FSQRT, + [UOP_FTST & + UOP_MASK] + = codegen_FTST, + + [UOP_PACKSSWB & + UOP_MASK] + = codegen_PACKSSWB, + [UOP_PACKSSDW & + UOP_MASK] + = codegen_PACKSSDW, + [UOP_PACKUSWB & + UOP_MASK] + = codegen_PACKUSWB, + + [UOP_PADDB & + UOP_MASK] + = codegen_PADDB, + [UOP_PADDW & + UOP_MASK] + = codegen_PADDW, + [UOP_PADDD & + UOP_MASK] + = codegen_PADDD, + [UOP_PADDSB & + UOP_MASK] + = codegen_PADDSB, + [UOP_PADDSW & + UOP_MASK] + = codegen_PADDSW, + [UOP_PADDUSB & + UOP_MASK] + = codegen_PADDUSB, + [UOP_PADDUSW & + UOP_MASK] + = codegen_PADDUSW, + + [UOP_PCMPEQB & + UOP_MASK] + = codegen_PCMPEQB, + [UOP_PCMPEQW & + UOP_MASK] + = codegen_PCMPEQW, + [UOP_PCMPEQD & + UOP_MASK] + = codegen_PCMPEQD, + [UOP_PCMPGTB & + UOP_MASK] + = codegen_PCMPGTB, + [UOP_PCMPGTW & + UOP_MASK] + = codegen_PCMPGTW, + [UOP_PCMPGTD & + UOP_MASK] + = codegen_PCMPGTD, + + [UOP_PF2ID & + UOP_MASK] + = codegen_PF2ID, + [UOP_PFADD & + UOP_MASK] + = codegen_PFADD, + [UOP_PFCMPEQ & + UOP_MASK] + = codegen_PFCMPEQ, + [UOP_PFCMPGE & + UOP_MASK] + = codegen_PFCMPGE, + [UOP_PFCMPGT & + UOP_MASK] + = codegen_PFCMPGT, + [UOP_PFMAX & + UOP_MASK] + = codegen_PFMAX, + [UOP_PFMIN & + UOP_MASK] + = codegen_PFMIN, + [UOP_PFMUL & + UOP_MASK] + = codegen_PFMUL, + [UOP_PFRCP & + UOP_MASK] + = codegen_PFRCP, + [UOP_PFRSQRT & + UOP_MASK] + = codegen_PFRSQRT, + [UOP_PFSUB & + UOP_MASK] + = codegen_PFSUB, + [UOP_PI2FD & + UOP_MASK] + = codegen_PI2FD, + + [UOP_PMADDWD & + UOP_MASK] + = codegen_PMADDWD, + [UOP_PMULHW & + UOP_MASK] + = codegen_PMULHW, + [UOP_PMULLW & + UOP_MASK] + = codegen_PMULLW, + + [UOP_PSLLW_IMM & + UOP_MASK] + = codegen_PSLLW_IMM, + [UOP_PSLLD_IMM & + UOP_MASK] + = codegen_PSLLD_IMM, + [UOP_PSLLQ_IMM & + UOP_MASK] + = codegen_PSLLQ_IMM, + [UOP_PSRAW_IMM & + UOP_MASK] + = codegen_PSRAW_IMM, + [UOP_PSRAD_IMM & + UOP_MASK] + = codegen_PSRAD_IMM, + [UOP_PSRAQ_IMM & + UOP_MASK] + = codegen_PSRAQ_IMM, + [UOP_PSRLW_IMM & + UOP_MASK] + = codegen_PSRLW_IMM, + [UOP_PSRLD_IMM & + UOP_MASK] + = codegen_PSRLD_IMM, + [UOP_PSRLQ_IMM & + UOP_MASK] + = codegen_PSRLQ_IMM, + + [UOP_PSUBB & + UOP_MASK] + = codegen_PSUBB, + [UOP_PSUBW & + UOP_MASK] + = codegen_PSUBW, + [UOP_PSUBD & + UOP_MASK] + = codegen_PSUBD, + [UOP_PSUBSB & + UOP_MASK] + = codegen_PSUBSB, + [UOP_PSUBSW & + UOP_MASK] + = codegen_PSUBSW, + [UOP_PSUBUSB & + UOP_MASK] + = codegen_PSUBUSB, + [UOP_PSUBUSW & + UOP_MASK] + = codegen_PSUBUSW, + + [UOP_PUNPCKHBW & + UOP_MASK] + = codegen_PUNPCKHBW, + [UOP_PUNPCKHWD & + UOP_MASK] + = codegen_PUNPCKHWD, + [UOP_PUNPCKHDQ & + UOP_MASK] + = codegen_PUNPCKHDQ, + [UOP_PUNPCKLBW & + UOP_MASK] + = codegen_PUNPCKLBW, + [UOP_PUNPCKLWD & + UOP_MASK] + = codegen_PUNPCKLWD, + [UOP_PUNPCKLDQ & + UOP_MASK] + = codegen_PUNPCKLDQ, + + [UOP_NOP_BARRIER & + UOP_MASK] + = codegen_NOP, + +# ifdef DEBUG_EXTRA + [UOP_LOG_INSTR & + UOP_MASK] + = codegen_LOG_INSTR +# endif }; -void codegen_direct_read_8(codeblock_t *block, int host_reg, void *p) +void +codegen_direct_read_8(codeblock_t *block, int host_reg, void *p) { - host_x86_MOV8_REG_ABS(block, host_reg, p); + host_x86_MOV8_REG_ABS(block, host_reg, p); } -void codegen_direct_read_16(codeblock_t *block, int host_reg, void *p) +void +codegen_direct_read_16(codeblock_t *block, int host_reg, void *p) { - host_x86_MOV16_REG_ABS(block, host_reg, p); + host_x86_MOV16_REG_ABS(block, host_reg, p); } -void codegen_direct_read_32(codeblock_t *block, int host_reg, void *p) +void +codegen_direct_read_32(codeblock_t *block, int host_reg, void *p) { - host_x86_MOV32_REG_ABS(block, host_reg, p); + host_x86_MOV32_REG_ABS(block, host_reg, p); } -void codegen_direct_read_pointer(codeblock_t *block, int host_reg, void *p) +void +codegen_direct_read_pointer(codeblock_t *block, int host_reg, void *p) { - codegen_direct_read_32(block, host_reg, p); + codegen_direct_read_32(block, host_reg, p); } -void codegen_direct_read_64(codeblock_t *block, int host_reg, void *p) +void +codegen_direct_read_64(codeblock_t *block, int host_reg, void *p) { - host_x86_MOVQ_XREG_ABS(block, host_reg, p); + host_x86_MOVQ_XREG_ABS(block, host_reg, p); } -void codegen_direct_read_double(codeblock_t *block, int host_reg, void *p) +void +codegen_direct_read_double(codeblock_t *block, int host_reg, void *p) { - host_x86_MOVQ_XREG_ABS(block, host_reg, p); + host_x86_MOVQ_XREG_ABS(block, host_reg, p); } -void codegen_direct_read_st_8(codeblock_t *block, int host_reg, void *base, int reg_idx) +void +codegen_direct_read_st_8(codeblock_t *block, int host_reg, void *base, int reg_idx) { - int offset = (uintptr_t)base - (((uintptr_t)&cpu_state) + 128); + int offset = (uintptr_t) base - (((uintptr_t) &cpu_state) + 128); - host_x86_MOV32_REG_BASE_OFFSET(block, REG_ECX, REG_ESP, IREG_TOP_diff_stack_offset); - host_x86_ADD32_REG_IMM(block, REG_ECX, reg_idx); - host_x86_AND32_REG_IMM(block, REG_ECX, 7); - host_x86_MOV8_REG_ABS_REG_REG_SHIFT(block, host_reg, offset, REG_EBP, REG_ECX, 0); + host_x86_MOV32_REG_BASE_OFFSET(block, REG_ECX, REG_ESP, IREG_TOP_diff_stack_offset); + host_x86_ADD32_REG_IMM(block, REG_ECX, reg_idx); + host_x86_AND32_REG_IMM(block, REG_ECX, 7); + host_x86_MOV8_REG_ABS_REG_REG_SHIFT(block, host_reg, offset, REG_EBP, REG_ECX, 0); } -void codegen_direct_read_st_64(codeblock_t *block, int host_reg, void *base, int reg_idx) +void +codegen_direct_read_st_64(codeblock_t *block, int host_reg, void *base, int reg_idx) { - int offset = (uintptr_t)base - (((uintptr_t)&cpu_state) + 128); + int offset = (uintptr_t) base - (((uintptr_t) &cpu_state) + 128); - host_x86_MOV32_REG_BASE_OFFSET(block, REG_ECX, REG_ESP, IREG_TOP_diff_stack_offset); - host_x86_ADD32_REG_IMM(block, REG_ECX, reg_idx); - host_x86_AND32_REG_IMM(block, REG_ECX, 7); - host_x86_MOVQ_XREG_ABS_REG_REG_SHIFT(block, host_reg, offset, REG_EBP, REG_ECX, 3); + host_x86_MOV32_REG_BASE_OFFSET(block, REG_ECX, REG_ESP, IREG_TOP_diff_stack_offset); + host_x86_ADD32_REG_IMM(block, REG_ECX, reg_idx); + host_x86_AND32_REG_IMM(block, REG_ECX, 7); + host_x86_MOVQ_XREG_ABS_REG_REG_SHIFT(block, host_reg, offset, REG_EBP, REG_ECX, 3); } -void codegen_direct_read_st_double(codeblock_t *block, int host_reg, void *base, int reg_idx) +void +codegen_direct_read_st_double(codeblock_t *block, int host_reg, void *base, int reg_idx) { - int offset = (uintptr_t)base - (((uintptr_t)&cpu_state) + 128); + int offset = (uintptr_t) base - (((uintptr_t) &cpu_state) + 128); - host_x86_MOV32_REG_BASE_OFFSET(block, REG_ECX, REG_ESP, IREG_TOP_diff_stack_offset); - host_x86_ADD32_REG_IMM(block, REG_ECX, reg_idx); - host_x86_AND32_REG_IMM(block, REG_ECX, 7); - host_x86_MOVQ_XREG_ABS_REG_REG_SHIFT(block, host_reg, offset, REG_EBP, REG_ECX, 3); + host_x86_MOV32_REG_BASE_OFFSET(block, REG_ECX, REG_ESP, IREG_TOP_diff_stack_offset); + host_x86_ADD32_REG_IMM(block, REG_ECX, reg_idx); + host_x86_AND32_REG_IMM(block, REG_ECX, 7); + host_x86_MOVQ_XREG_ABS_REG_REG_SHIFT(block, host_reg, offset, REG_EBP, REG_ECX, 3); } -void codegen_direct_write_8(codeblock_t *block, void *p, int host_reg) +void +codegen_direct_write_8(codeblock_t *block, void *p, int host_reg) { - host_x86_MOV8_ABS_REG(block, p, host_reg); + host_x86_MOV8_ABS_REG(block, p, host_reg); } -void codegen_direct_write_16(codeblock_t *block, void *p, int host_reg) +void +codegen_direct_write_16(codeblock_t *block, void *p, int host_reg) { - host_x86_MOV16_ABS_REG(block, p, host_reg); + host_x86_MOV16_ABS_REG(block, p, host_reg); } -void codegen_direct_write_32(codeblock_t *block, void *p, int host_reg) +void +codegen_direct_write_32(codeblock_t *block, void *p, int host_reg) { - host_x86_MOV32_ABS_REG(block, p, host_reg); + host_x86_MOV32_ABS_REG(block, p, host_reg); } -void codegen_direct_write_64(codeblock_t *block, void *p, int host_reg) +void +codegen_direct_write_64(codeblock_t *block, void *p, int host_reg) { - host_x86_MOVQ_ABS_XREG(block, p, host_reg); + host_x86_MOVQ_ABS_XREG(block, p, host_reg); } -void codegen_direct_write_double(codeblock_t *block, void *p, int host_reg) +void +codegen_direct_write_double(codeblock_t *block, void *p, int host_reg) { - host_x86_MOVQ_ABS_XREG(block, p, host_reg); + host_x86_MOVQ_ABS_XREG(block, p, host_reg); } -void codegen_direct_write_st_8(codeblock_t *block, void *base, int reg_idx, int host_reg) +void +codegen_direct_write_st_8(codeblock_t *block, void *base, int reg_idx, int host_reg) { - int offset = (uintptr_t)base - (((uintptr_t)&cpu_state) + 128); + int offset = (uintptr_t) base - (((uintptr_t) &cpu_state) + 128); - host_x86_MOV32_REG_BASE_OFFSET(block, REG_ECX, REG_ESP, IREG_TOP_diff_stack_offset); - host_x86_ADD32_REG_IMM(block, REG_ECX, reg_idx); - host_x86_AND32_REG_IMM(block, REG_ECX, 7); - host_x86_MOV8_ABS_REG_REG_SHIFT_REG(block, offset, REG_EBP, REG_ECX, 0, host_reg); + host_x86_MOV32_REG_BASE_OFFSET(block, REG_ECX, REG_ESP, IREG_TOP_diff_stack_offset); + host_x86_ADD32_REG_IMM(block, REG_ECX, reg_idx); + host_x86_AND32_REG_IMM(block, REG_ECX, 7); + host_x86_MOV8_ABS_REG_REG_SHIFT_REG(block, offset, REG_EBP, REG_ECX, 0, host_reg); } -void codegen_direct_write_st_64(codeblock_t *block, void *base, int reg_idx, int host_reg) +void +codegen_direct_write_st_64(codeblock_t *block, void *base, int reg_idx, int host_reg) { - int offset = (uintptr_t)base - (((uintptr_t)&cpu_state) + 128); + int offset = (uintptr_t) base - (((uintptr_t) &cpu_state) + 128); - host_x86_MOV32_REG_BASE_OFFSET(block, REG_ECX, REG_ESP, IREG_TOP_diff_stack_offset); - host_x86_ADD32_REG_IMM(block, REG_ECX, reg_idx); - host_x86_AND32_REG_IMM(block, REG_ECX, 7); - host_x86_MOVQ_ABS_REG_REG_SHIFT_XREG(block, offset, REG_EBP, REG_ECX, 3, host_reg); + host_x86_MOV32_REG_BASE_OFFSET(block, REG_ECX, REG_ESP, IREG_TOP_diff_stack_offset); + host_x86_ADD32_REG_IMM(block, REG_ECX, reg_idx); + host_x86_AND32_REG_IMM(block, REG_ECX, 7); + host_x86_MOVQ_ABS_REG_REG_SHIFT_XREG(block, offset, REG_EBP, REG_ECX, 3, host_reg); } -void codegen_direct_write_st_double(codeblock_t *block, void *base, int reg_idx, int host_reg) +void +codegen_direct_write_st_double(codeblock_t *block, void *base, int reg_idx, int host_reg) { - int offset = (uintptr_t)base - (((uintptr_t)&cpu_state) + 128); + int offset = (uintptr_t) base - (((uintptr_t) &cpu_state) + 128); - host_x86_MOV32_REG_BASE_OFFSET(block, REG_ECX, REG_ESP, IREG_TOP_diff_stack_offset); - host_x86_ADD32_REG_IMM(block, REG_ECX, reg_idx); - host_x86_AND32_REG_IMM(block, REG_ECX, 7); - host_x86_MOVQ_ABS_REG_REG_SHIFT_XREG(block, offset, REG_EBP, REG_ECX, 3, host_reg); + host_x86_MOV32_REG_BASE_OFFSET(block, REG_ECX, REG_ESP, IREG_TOP_diff_stack_offset); + host_x86_ADD32_REG_IMM(block, REG_ECX, reg_idx); + host_x86_AND32_REG_IMM(block, REG_ECX, 7); + host_x86_MOVQ_ABS_REG_REG_SHIFT_XREG(block, offset, REG_EBP, REG_ECX, 3, host_reg); } -void codegen_direct_write_ptr(codeblock_t *block, void *p, int host_reg) +void +codegen_direct_write_ptr(codeblock_t *block, void *p, int host_reg) { - host_x86_MOV32_ABS_REG(block, p, host_reg); + host_x86_MOV32_ABS_REG(block, p, host_reg); } -void codegen_direct_read_16_stack(codeblock_t *block, int host_reg, int stack_offset) +void +codegen_direct_read_16_stack(codeblock_t *block, int host_reg, int stack_offset) { - host_x86_MOV16_REG_BASE_OFFSET(block, host_reg, REG_ESP, stack_offset); + host_x86_MOV16_REG_BASE_OFFSET(block, host_reg, REG_ESP, stack_offset); } -void codegen_direct_read_32_stack(codeblock_t *block, int host_reg, int stack_offset) +void +codegen_direct_read_32_stack(codeblock_t *block, int host_reg, int stack_offset) { - host_x86_MOV32_REG_BASE_OFFSET(block, host_reg, REG_ESP, stack_offset); + host_x86_MOV32_REG_BASE_OFFSET(block, host_reg, REG_ESP, stack_offset); } -void codegen_direct_read_pointer_stack(codeblock_t *block, int host_reg, int stack_offset) +void +codegen_direct_read_pointer_stack(codeblock_t *block, int host_reg, int stack_offset) { - codegen_direct_read_32_stack(block, host_reg, stack_offset); + codegen_direct_read_32_stack(block, host_reg, stack_offset); } -void codegen_direct_read_64_stack(codeblock_t *block, int host_reg, int stack_offset) +void +codegen_direct_read_64_stack(codeblock_t *block, int host_reg, int stack_offset) { - host_x86_MOVQ_XREG_BASE_OFFSET(block, host_reg, REG_ESP, stack_offset); + host_x86_MOVQ_XREG_BASE_OFFSET(block, host_reg, REG_ESP, stack_offset); } -void codegen_direct_read_double_stack(codeblock_t *block, int host_reg, int stack_offset) +void +codegen_direct_read_double_stack(codeblock_t *block, int host_reg, int stack_offset) { - host_x86_MOVQ_XREG_BASE_OFFSET(block, host_reg, REG_ESP, stack_offset); + host_x86_MOVQ_XREG_BASE_OFFSET(block, host_reg, REG_ESP, stack_offset); } -void codegen_direct_write_32_stack(codeblock_t *block, int stack_offset, int host_reg) +void +codegen_direct_write_32_stack(codeblock_t *block, int stack_offset, int host_reg) { - host_x86_MOV32_BASE_OFFSET_REG(block, REG_ESP, stack_offset, host_reg); + host_x86_MOV32_BASE_OFFSET_REG(block, REG_ESP, stack_offset, host_reg); } -void codegen_direct_write_64_stack(codeblock_t *block, int stack_offset, int host_reg) +void +codegen_direct_write_64_stack(codeblock_t *block, int stack_offset, int host_reg) { - host_x86_MOVQ_BASE_OFFSET_XREG(block, REG_ESP, stack_offset, host_reg); + host_x86_MOVQ_BASE_OFFSET_XREG(block, REG_ESP, stack_offset, host_reg); } -void codegen_direct_write_double_stack(codeblock_t *block, int stack_offset, int host_reg) +void +codegen_direct_write_double_stack(codeblock_t *block, int stack_offset, int host_reg) { - host_x86_MOVQ_BASE_OFFSET_XREG(block, REG_ESP, stack_offset, host_reg); + host_x86_MOVQ_BASE_OFFSET_XREG(block, REG_ESP, stack_offset, host_reg); } -void codegen_set_jump_dest(codeblock_t *block, void *p) +void +codegen_set_jump_dest(UNUSED(codeblock_t *block), void *p) { - *(uint32_t *)p = (uintptr_t)&block_write_data[block_pos] - ((uintptr_t)p + 4); + *(uint32_t *) p = (uintptr_t) &block_write_data[block_pos] - ((uintptr_t) p + 4); } -void codegen_direct_write_8_imm(codeblock_t *block, void *p, uint8_t imm_data) +void +codegen_direct_write_8_imm(codeblock_t *block, void *p, uint8_t imm_data) { - host_x86_MOV8_ABS_IMM(block, p, imm_data); + host_x86_MOV8_ABS_IMM(block, p, imm_data); } -void codegen_direct_write_16_imm(codeblock_t *block, void *p, uint16_t imm_data) +void +codegen_direct_write_16_imm(codeblock_t *block, void *p, uint16_t imm_data) { - host_x86_MOV16_ABS_IMM(block, p, imm_data); + host_x86_MOV16_ABS_IMM(block, p, imm_data); } -void codegen_direct_write_32_imm(codeblock_t *block, void *p, uint32_t imm_data) +void +codegen_direct_write_32_imm(codeblock_t *block, void *p, uint32_t imm_data) { - host_x86_MOV32_ABS_IMM(block, p, imm_data); + host_x86_MOV32_ABS_IMM(block, p, imm_data); } -void codegen_direct_write_32_imm_stack(codeblock_t *block, int stack_offset, uint32_t imm_data) +void +codegen_direct_write_32_imm_stack(codeblock_t *block, int stack_offset, uint32_t imm_data) { - host_x86_MOV32_BASE_OFFSET_IMM(block, REG_ESP, stack_offset, imm_data); + host_x86_MOV32_BASE_OFFSET_IMM(block, REG_ESP, stack_offset, imm_data); } #endif diff --git a/src/codegen_new/codegen_block.c b/src/codegen_new/codegen_block.c index 609d0927f..ee0a030ba 100644 --- a/src/codegen_new/codegen_block.c +++ b/src/codegen_new/codegen_block.c @@ -1,13 +1,17 @@ +#include #include #include #include #include <86box/86box.h> #include "cpu.h" #include <86box/mem.h> +#include <86box/plat_unused.h> #include "x86.h" #include "x86_flags.h" #include "x86_ops.h" +#include "x86seg_common.h" +#include "x86seg.h" #include "x87.h" #include "386_common.h" @@ -21,871 +25,810 @@ uint8_t *block_write_data = NULL; -int codegen_flat_ds, codegen_flat_ss; -int mmx_ebx_ecx_loaded; -int codegen_flags_changed = 0; -int codegen_fpu_entered = 0; -int codegen_mmx_entered = 0; -int codegen_fpu_loaded_iq[8]; -x86seg *op_ea_seg; -int op_ssegs; +int codegen_flat_ds; +int codegen_flat_ss; +int mmx_ebx_ecx_loaded; +int codegen_flags_changed = 0; +int codegen_fpu_entered = 0; +int codegen_mmx_entered = 0; +int codegen_fpu_loaded_iq[8]; +x86seg *op_ea_seg; +int op_ssegs; uint32_t op_old_pc; uint32_t recomp_page = -1; -int block_current = 0; +int block_current = 0; static int block_num; -int block_pos; +int block_pos; uint32_t codegen_endpc; -int codegen_block_cycles; +int codegen_block_cycles; static int codegen_block_ins; static int codegen_block_full_ins; static uint32_t last_op32; -static x86seg *last_ea_seg; -static int last_ssegs; +static x86seg *last_ea_seg; +static int last_ssegs; #ifdef DEBUG_EXTRA -uint32_t instr_counts[256*256]; +uint32_t instr_counts[256 * 256]; #endif static uint16_t block_free_list; -static void delete_block(codeblock_t *block); -static void delete_dirty_block(codeblock_t *block); +static void delete_block(codeblock_t *block); +static void delete_dirty_block(codeblock_t *block); /*Temporary list of code blocks that have recently been evicted. This allows for some historical state to be kept when a block is the target of self-modifying code. - + The size of this list is limited to DIRTY_LIST_MAX_SIZE blocks. When this is exceeded the oldest entry will be moved to the free list.*/ -static uint16_t block_dirty_list_head, block_dirty_list_tail; -static int dirty_list_size = 0; +static uint16_t block_dirty_list_head; +static uint16_t block_dirty_list_tail; +static int dirty_list_size = 0; #define DIRTY_LIST_MAX_SIZE 64 -static void block_free_list_add(codeblock_t *block) +static void +block_free_list_add(codeblock_t *block) { #ifndef RELEASE_BUILD - if (block->flags & CODEBLOCK_IN_DIRTY_LIST) - fatal("block_free_list_add: block=%p in dirty list\n", block); + if (block->flags & CODEBLOCK_IN_DIRTY_LIST) + fatal("block_free_list_add: block=%p in dirty list\n", block); #endif - if (block_free_list) - block->next = block_free_list; - else - block->next = 0; - block_free_list = get_block_nr(block); - block->flags = CODEBLOCK_IN_FREE_LIST; + if (block_free_list) + block->next = block_free_list; + else + block->next = 0; + block_free_list = get_block_nr(block); + block->flags = CODEBLOCK_IN_FREE_LIST; } -static void block_dirty_list_add(codeblock_t *block) +static void +block_dirty_list_add(codeblock_t *block) { #ifndef RELEASE_BUILD - if (block->flags & CODEBLOCK_IN_DIRTY_LIST) - fatal("block_dirty_list_add: block=%p already in dirty list\n", block); + if (block->flags & CODEBLOCK_IN_DIRTY_LIST) + fatal("block_dirty_list_add: block=%p already in dirty list\n", block); #endif - if (block_dirty_list_head != BLOCK_INVALID) - { - codeblock_t *old_head = &codeblock[block_dirty_list_head]; - - block->next = block_dirty_list_head; - block->prev = BLOCK_INVALID; - block_dirty_list_head = old_head->prev = get_block_nr(block); - } - else - { - /*List empty*/ - block->prev = block->next = BLOCK_INVALID; - block_dirty_list_head = block_dirty_list_tail = get_block_nr(block); - } - block->flags |= CODEBLOCK_IN_DIRTY_LIST; - dirty_list_size++; - if (dirty_list_size > DIRTY_LIST_MAX_SIZE) - { - /*Evict oldest block to the free list*/ - codeblock_t *evict_block = &codeblock[block_dirty_list_tail]; + if (block_dirty_list_head != BLOCK_INVALID) { + codeblock_t *old_head = &codeblock[block_dirty_list_head]; + + block->next = block_dirty_list_head; + block->prev = BLOCK_INVALID; + block_dirty_list_head = old_head->prev = get_block_nr(block); + } else { + /*List empty*/ + block->prev = block->next = BLOCK_INVALID; + block_dirty_list_head = block_dirty_list_tail = get_block_nr(block); + } + block->flags |= CODEBLOCK_IN_DIRTY_LIST; + dirty_list_size++; + if (dirty_list_size > DIRTY_LIST_MAX_SIZE) { + /*Evict oldest block to the free list*/ + codeblock_t *evict_block = &codeblock[block_dirty_list_tail]; #ifndef RELEASE_BUILD - if (!(evict_block->flags & CODEBLOCK_IN_DIRTY_LIST)) - fatal("block_dirty_list_add: evict_block=%p %x %x not in dirty list\n", evict_block, evict_block->phys, evict_block->flags); - if (!block_dirty_list_tail) - fatal("block_dirty_list_add - !block_dirty_list_tail\n"); - if (evict_block->prev == BLOCK_INVALID) - fatal("block_dirty_list_add - evict_block->prev == BLOCK_INVALID\n"); + if (!(evict_block->flags & CODEBLOCK_IN_DIRTY_LIST)) + fatal("block_dirty_list_add: evict_block=%p %x %x not in dirty list\n", evict_block, evict_block->phys, evict_block->flags); + if (!block_dirty_list_tail) + fatal("block_dirty_list_add - !block_dirty_list_tail\n"); + if (evict_block->prev == BLOCK_INVALID) + fatal("block_dirty_list_add - evict_block->prev == BLOCK_INVALID\n"); #endif - block_dirty_list_tail = evict_block->prev; - codeblock[evict_block->prev].next = BLOCK_INVALID; - - dirty_list_size--; - evict_block->flags &= ~CODEBLOCK_IN_DIRTY_LIST; - delete_dirty_block(evict_block); - } -} - -static void block_dirty_list_remove(codeblock_t *block) -{ - codeblock_t *prev_block = &codeblock[block->prev]; - codeblock_t *next_block = &codeblock[block->next]; - -#ifndef RELEASE_BUILD - if (!(block->flags & CODEBLOCK_IN_DIRTY_LIST)) - fatal("block_dirty_list_remove: block=%p not in dirty list\n", block); -#endif - - /*Is block head of list*/ - if (block->prev == BLOCK_INVALID) - block_dirty_list_head = block->next; - else - prev_block->next = block->next; - - /*Is block tail of list?*/ - if (block->next == BLOCK_INVALID) - block_dirty_list_tail = block->prev; - else - next_block->prev = block->prev; + block_dirty_list_tail = evict_block->prev; + codeblock[evict_block->prev].next = BLOCK_INVALID; dirty_list_size--; + evict_block->flags &= ~CODEBLOCK_IN_DIRTY_LIST; + delete_dirty_block(evict_block); + } +} + +static void +block_dirty_list_remove(codeblock_t *block) +{ + codeblock_t *prev_block = &codeblock[block->prev]; + codeblock_t *next_block = &codeblock[block->next]; + #ifndef RELEASE_BUILD - if (dirty_list_size < 0) - fatal("remove - dirty_list_size < 0!\n"); + if (!(block->flags & CODEBLOCK_IN_DIRTY_LIST)) + fatal("block_dirty_list_remove: block=%p not in dirty list\n", block); #endif - block->flags &= ~CODEBLOCK_IN_DIRTY_LIST; -} -int codegen_purge_purgable_list() -{ - if (purgable_page_list_head) - { - page_t *page = &pages[purgable_page_list_head]; + /*Is block head of list*/ + if (block->prev == BLOCK_INVALID) + block_dirty_list_head = block->next; + else + prev_block->next = block->next; - if (page->code_present_mask & page->dirty_mask) - { - codegen_check_flush(page, page->dirty_mask, purgable_page_list_head << 12); + /*Is block tail of list?*/ + if (block->next == BLOCK_INVALID) + block_dirty_list_tail = block->prev; + else + next_block->prev = block->prev; - if (block_free_list) - return 1; - } - } - return 0; -} - -static codeblock_t *block_free_list_get() -{ - codeblock_t *block = NULL; - - while (!block_free_list) - { - /*Free list is empty, check the dirty list*/ - if (block_dirty_list_tail) - { + dirty_list_size--; #ifndef RELEASE_BUILD - if (dirty_list_size <= 0) - fatal("get - dirty_list_size <= 0!\n"); + if (dirty_list_size < 0) + fatal("remove - dirty_list_size < 0!\n"); #endif - /*Reuse oldest block*/ - block = &codeblock[block_dirty_list_tail]; - - block_dirty_list_tail = block->prev; - if (block->prev == BLOCK_INVALID) - block_dirty_list_head = BLOCK_INVALID; - else - codeblock[block->prev].next = BLOCK_INVALID; - dirty_list_size--; - block->flags &= ~CODEBLOCK_IN_DIRTY_LIST; - delete_dirty_block(block); - block_free_list = get_block_nr(block); - break; - } - /*Free list is empty - free up a block*/ - if (!codegen_purge_purgable_list()) - codegen_delete_random_block(0); - } - - block = &codeblock[block_free_list]; - block_free_list = block->next; - block->flags &= ~CODEBLOCK_IN_FREE_LIST; - block->next = 0; - return block; + block->flags &= ~CODEBLOCK_IN_DIRTY_LIST; } -void codegen_init() +int +codegen_purge_purgable_list(void) { - int c; - - codegen_allocator_init(); - - codegen_backend_init(); - block_free_list = 0; - for (c = 0; c < BLOCK_SIZE; c++) - block_free_list_add(&codeblock[c]); - block_dirty_list_head = block_dirty_list_tail = 0; - dirty_list_size = 0; + if (purgable_page_list_head) { + page_t *page = &pages[purgable_page_list_head]; + + if (page->code_present_mask & page->dirty_mask) { + codegen_check_flush(page, page->dirty_mask, purgable_page_list_head << 12); + + if (block_free_list) + return 1; + } + } + return 0; +} + +static codeblock_t * +block_free_list_get(void) +{ + codeblock_t *block = NULL; + + while (!block_free_list) { + /*Free list is empty, check the dirty list*/ + if (block_dirty_list_tail) { +#ifndef RELEASE_BUILD + if (dirty_list_size <= 0) + fatal("get - dirty_list_size <= 0!\n"); +#endif + /*Reuse oldest block*/ + block = &codeblock[block_dirty_list_tail]; + + block_dirty_list_tail = block->prev; + if (block->prev == BLOCK_INVALID) + block_dirty_list_head = BLOCK_INVALID; + else + codeblock[block->prev].next = BLOCK_INVALID; + dirty_list_size--; + block->flags &= ~CODEBLOCK_IN_DIRTY_LIST; + delete_dirty_block(block); + block_free_list = get_block_nr(block); + break; + } + /*Free list is empty - free up a block*/ + if (!codegen_purge_purgable_list()) + codegen_delete_random_block(0); + } + + block = &codeblock[block_free_list]; + block_free_list = block->next; + block->flags &= ~CODEBLOCK_IN_FREE_LIST; + block->next = 0; + return block; +} + +void +codegen_init(void) +{ + codegen_allocator_init(); + + codegen_backend_init(); + block_free_list = 0; + for (uint32_t c = 0; c < BLOCK_SIZE; c++) + block_free_list_add(&codeblock[c]); + block_dirty_list_head = block_dirty_list_tail = 0; + dirty_list_size = 0; #ifdef DEBUG_EXTRA - memset(instr_counts, 0, sizeof(instr_counts)); + memset(instr_counts, 0, sizeof(instr_counts)); #endif } -void codegen_close() +void +codegen_reset(void) { -#ifdef DEBUG_EXTRA - pclog("Instruction counts :\n"); - while (1) - { - int c; - uint32_t highest_num = 0, highest_idx = 0; - - for (c = 0; c < 256*256; c++) - { - if (instr_counts[c] > highest_num) - { - highest_num = instr_counts[c]; - highest_idx = c; - } - } - if (!highest_num) - break; + int c; - instr_counts[highest_idx] = 0; - if (highest_idx > 256) - pclog(" %02x %02x = %u\n", highest_idx >> 8, highest_idx & 0xff, highest_num); - else - pclog(" %02x = %u\n", highest_idx & 0xff, highest_num); + for (c = 1; c < BLOCK_SIZE; c++) { + codeblock_t *block = &codeblock[c]; + + if (block->pc != BLOCK_PC_INVALID) { + block->phys = 0; + block->phys_2 = 0; + delete_block(block); } + } + + memset(codeblock, 0, BLOCK_SIZE * sizeof(codeblock_t)); + memset(codeblock_hash, 0, HASH_SIZE * sizeof(uint16_t)); + mem_reset_page_blocks(); + + block_free_list = 0; + for (c = 0; c < BLOCK_SIZE; c++) { + codeblock[c].pc = BLOCK_PC_INVALID; + block_free_list_add(&codeblock[c]); + } +} + +void +dump_block(void) +{ +#if 0 + codeblock_t *block = pages[0x119000 >> 12].block; + + pclog("dump_block:\n"); + while (block) { + uint32_t start_pc = (block->pc & 0xffc) | (block->phys & ~0xfff); + uint32_t end_pc = (block->endpc & 0xffc) | (block->phys & ~0xfff); + + pclog(" %p : %08x-%08x %08x-%08x %p %p\n", (void *)block, start_pc, end_pc, block->pc, block->endpc, (void *)block->prev, (void *)block->next); + + if (!block->pc) + fatal("Dead PC=0\n"); + + block = block->next; + } + + pclog("dump_block done\n");*/ #endif } -void codegen_reset() +static void +add_to_block_list(codeblock_t *block) { - int c; - - for (c = 1; c < BLOCK_SIZE; c++) - { - codeblock_t *block = &codeblock[c]; - - if (block->pc != BLOCK_PC_INVALID) - { - block->phys = 0; - block->phys_2 = 0; - delete_block(block); - } - } - - memset(codeblock, 0, BLOCK_SIZE * sizeof(codeblock_t)); - memset(codeblock_hash, 0, HASH_SIZE * sizeof(uint16_t)); - mem_reset_page_blocks(); - - block_free_list = 0; - for (c = 0; c < BLOCK_SIZE; c++) - { - codeblock[c].pc = BLOCK_PC_INVALID; - block_free_list_add(&codeblock[c]); - } -} - -void dump_block() -{ -/* codeblock_t *block = pages[0x119000 >> 12].block; - - pclog("dump_block:\n"); - while (block) - { - uint32_t start_pc = (block->pc & 0xffc) | (block->phys & ~0xfff); - uint32_t end_pc = (block->endpc & 0xffc) | (block->phys & ~0xfff); - pclog(" %p : %08x-%08x %08x-%08x %p %p\n", (void *)block, start_pc, end_pc, block->pc, block->endpc, (void *)block->prev, (void *)block->next); - if (!block->pc) - fatal("Dead PC=0\n"); - - block = block->next; - } - pclog("dump_block done\n");*/ -} - -static void add_to_block_list(codeblock_t *block) -{ - uint16_t block_prev_nr = pages[block->phys >> 12].block; - uint16_t block_nr = get_block_nr(block); + uint16_t block_prev_nr = pages[block->phys >> 12].block; + uint16_t block_nr = get_block_nr(block); #ifndef RELEASE_BUILD - if (!block->page_mask) - fatal("add_to_block_list - mask = 0 %llx %llx\n", block->page_mask,block->page_mask2); + if (!block->page_mask) + fatal("add_to_block_list - mask = 0 %" PRIx64 " %" PRIx64 "\n", block->page_mask, block->page_mask2); #endif - if (block_prev_nr) - { - block->next = block_prev_nr; - codeblock[block_prev_nr].prev = block_nr; - pages[block->phys >> 12].block = block_nr; - } - else - { - block->next = BLOCK_INVALID; - pages[block->phys >> 12].block = block_nr; - } + if (block_prev_nr) { + block->next = block_prev_nr; + codeblock[block_prev_nr].prev = block_nr; + pages[block->phys >> 12].block = block_nr; + } else { + block->next = BLOCK_INVALID; + pages[block->phys >> 12].block = block_nr; + } + if (block->next) { +#ifndef RELEASE_BUILD + if (codeblock[block->next].pc == BLOCK_PC_INVALID) + fatal("block->next->pc=BLOCK_PC_INVALID %p %p %x %x\n", (void *) &codeblock[block->next], (void *) codeblock, block_current, block_pos); +#endif + } + + if (block->page_mask2) { + block->flags |= CODEBLOCK_HAS_PAGE2; + + block_prev_nr = pages[block->phys_2 >> 12].block_2; + + if (block_prev_nr) { + block->next_2 = block_prev_nr; + codeblock[block_prev_nr].prev_2 = block_nr; + pages[block->phys_2 >> 12].block_2 = block_nr; + } else { + block->next_2 = BLOCK_INVALID; + pages[block->phys_2 >> 12].block_2 = block_nr; + } + } +} + +static void +remove_from_block_list(codeblock_t *block, UNUSED(uint32_t pc)) +{ + if (!block->page_mask) + return; +#ifndef RELEASE_BUILD + if (block->flags & CODEBLOCK_IN_DIRTY_LIST) + fatal("remove_from_block_list: in dirty list\n"); +#endif + if (block->prev) { + codeblock[block->prev].next = block->next; if (block->next) - { -#ifndef RELEASE_BUILD - if (codeblock[block->next].pc == BLOCK_PC_INVALID) - fatal("block->next->pc=BLOCK_PC_INVALID %p %p %x %x\n", (void *)&codeblock[block->next], (void *)codeblock, block_current, block_pos); -#endif - } - - if (block->page_mask2) - { - block->flags |= CODEBLOCK_HAS_PAGE2; - - block_prev_nr = pages[block->phys_2 >> 12].block_2; + codeblock[block->next].prev = block->prev; + } else { + pages[block->phys >> 12].block = block->next; + if (block->next) + codeblock[block->next].prev = BLOCK_INVALID; + else + mem_flush_write_page(block->phys, 0); + } - if (block_prev_nr) - { - block->next_2 = block_prev_nr; - codeblock[block_prev_nr].prev_2 = block_nr; - pages[block->phys_2 >> 12].block_2 = block_nr; - } - else - { - block->next_2 = BLOCK_INVALID; - pages[block->phys_2 >> 12].block_2 = block_nr; - } - } + if (!(block->flags & CODEBLOCK_HAS_PAGE2)) { +#ifndef RELEASE_BUILD + if (block->prev_2 || block->next_2) + fatal("Invalid block_2 %x %p %08x\n", block->flags, block, block->phys); +#endif + return; + } + block->flags &= ~CODEBLOCK_HAS_PAGE2; + + if (block->prev_2) { + codeblock[block->prev_2].next_2 = block->next_2; + if (block->next_2) + codeblock[block->next_2].prev_2 = block->prev_2; + } else { + pages[block->phys_2 >> 12].block_2 = block->next_2; + if (block->next_2) + codeblock[block->next_2].prev_2 = BLOCK_INVALID; + else + mem_flush_write_page(block->phys_2, 0); + } } -static void remove_from_block_list(codeblock_t *block, uint32_t pc) +static void +invalidate_block(codeblock_t *block) { - if (!block->page_mask) - return; -#ifndef RELEASE_BUILD - if (block->flags & CODEBLOCK_IN_DIRTY_LIST) - fatal("remove_from_block_list: in dirty list\n"); -#endif - if (block->prev) - { - codeblock[block->prev].next = block->next; - if (block->next) - codeblock[block->next].prev = block->prev; - } - else - { - pages[block->phys >> 12].block = block->next; - if (block->next) - codeblock[block->next].prev = BLOCK_INVALID; - else - mem_flush_write_page(block->phys, 0); - } + uint32_t old_pc = block->pc; - if (!(block->flags & CODEBLOCK_HAS_PAGE2)) - { #ifndef RELEASE_BUILD - if (block->prev_2 || block->next_2) - fatal("Invalid block_2 %x %p %08x\n", block->flags, block, block->phys); + if (block->flags & CODEBLOCK_IN_DIRTY_LIST) + fatal("invalidate_block: already in dirty list\n"); + if (block->pc == BLOCK_PC_INVALID) + fatal("Invalidating deleted block\n"); #endif - return; - } - block->flags &= ~CODEBLOCK_HAS_PAGE2; - - if (block->prev_2) - { - codeblock[block->prev_2].next_2 = block->next_2; - if (block->next_2) - codeblock[block->next_2].prev_2 = block->prev_2; - } - else - { - pages[block->phys_2 >> 12].block_2 = block->next_2; - if (block->next_2) - codeblock[block->next_2].prev_2 = BLOCK_INVALID; - else - mem_flush_write_page(block->phys_2, 0); - } + remove_from_block_list(block, old_pc); + block_dirty_list_add(block); + if (block->head_mem_block) + codegen_allocator_free(block->head_mem_block); + block->head_mem_block = NULL; } -static void invalidate_block(codeblock_t *block) +static void +delete_block(codeblock_t *block) { - uint32_t old_pc = block->pc; + uint32_t old_pc = block->pc; + + if (block == &codeblock[codeblock_hash[HASH(block->phys)]]) + codeblock_hash[HASH(block->phys)] = BLOCK_INVALID; #ifndef RELEASE_BUILD - if (block->flags & CODEBLOCK_IN_DIRTY_LIST) - fatal("invalidate_block: already in dirty list\n"); - if (block->pc == BLOCK_PC_INVALID) - fatal("Invalidating deleted block\n"); + if (block->pc == BLOCK_PC_INVALID) + fatal("Deleting deleted block\n"); #endif + block->pc = BLOCK_PC_INVALID; + + codeblock_tree_delete(block); + if (block->flags & CODEBLOCK_IN_DIRTY_LIST) + block_dirty_list_remove(block); + else remove_from_block_list(block, old_pc); - block_dirty_list_add(block); - if (block->head_mem_block) - codegen_allocator_free(block->head_mem_block); - block->head_mem_block = NULL; + if (block->head_mem_block) + codegen_allocator_free(block->head_mem_block); + block->head_mem_block = NULL; + block_free_list_add(block); } -static void delete_block(codeblock_t *block) +static void +delete_dirty_block(codeblock_t *block) { - uint32_t old_pc = block->pc; - - if (block == &codeblock[codeblock_hash[HASH(block->phys)]]) - codeblock_hash[HASH(block->phys)] = BLOCK_INVALID; + if (block == &codeblock[codeblock_hash[HASH(block->phys)]]) + codeblock_hash[HASH(block->phys)] = BLOCK_INVALID; #ifndef RELEASE_BUILD - if (block->pc == BLOCK_PC_INVALID) - fatal("Deleting deleted block\n"); + if (block->pc == BLOCK_PC_INVALID) + fatal("Deleting deleted block\n"); #endif - block->pc = BLOCK_PC_INVALID; + block->pc = BLOCK_PC_INVALID; - codeblock_tree_delete(block); - if (block->flags & CODEBLOCK_IN_DIRTY_LIST) - block_dirty_list_remove(block); - else - remove_from_block_list(block, old_pc); - if (block->head_mem_block) - codegen_allocator_free(block->head_mem_block); - block->head_mem_block = NULL; - block_free_list_add(block); + codeblock_tree_delete(block); + block_free_list_add(block); } -static void delete_dirty_block(codeblock_t *block) +void +codegen_delete_block(codeblock_t *block) { - if (block == &codeblock[codeblock_hash[HASH(block->phys)]]) - codeblock_hash[HASH(block->phys)] = BLOCK_INVALID; - -#ifndef RELEASE_BUILD - if (block->pc == BLOCK_PC_INVALID) - fatal("Deleting deleted block\n"); -#endif - block->pc = BLOCK_PC_INVALID; - - codeblock_tree_delete(block); - block_free_list_add(block); + if (block->pc != BLOCK_PC_INVALID) + delete_block(block); } -void codegen_delete_block(codeblock_t *block) +void +codegen_delete_random_block(int required_mem_block) { - if (block->pc != BLOCK_PC_INVALID) + int block_nr = rand() & BLOCK_MASK; + + while (1) { + if (block_nr && block_nr != block_current) { + codeblock_t *block = &codeblock[block_nr]; + + if (block->pc != BLOCK_PC_INVALID && (!required_mem_block || block->head_mem_block)) { delete_block(block); + return; + } + } + block_nr = (block_nr + 1) & BLOCK_MASK; + } } -void codegen_delete_random_block(int required_mem_block) +void +codegen_check_flush(page_t *page, UNUSED(uint64_t mask), UNUSED(uint32_t phys_addr)) { - int block_nr = rand() & BLOCK_MASK; - - while (1) - { - if (block_nr && block_nr != block_current) - { - codeblock_t *block = &codeblock[block_nr]; + uint16_t block_nr = page->block; + int remove_from_evict_list = 0; - if (block->pc != BLOCK_PC_INVALID && (!required_mem_block || block->head_mem_block)) - { - delete_block(block); - return; - } - } - block_nr = (block_nr + 1) & BLOCK_MASK; + while (block_nr) { + codeblock_t *block = &codeblock[block_nr]; + uint16_t next_block = block->next; + + if (*block->dirty_mask & block->page_mask) { + invalidate_block(block); } +#ifndef RELEASE_BUILD + if (block_nr == next_block) + fatal("Broken 1\n"); +#endif + block_nr = next_block; + } + + block_nr = page->block_2; + + while (block_nr) { + codeblock_t *block = &codeblock[block_nr]; + uint16_t next_block = block->next_2; + + if (*block->dirty_mask2 & block->page_mask2) { + invalidate_block(block); + } +#ifndef RELEASE_BUILD + if (block_nr == next_block) + fatal("Broken 2\n"); +#endif + block_nr = next_block; + } + + if (page->code_present_mask & page->dirty_mask) + remove_from_evict_list = 1; + page->code_present_mask &= ~page->dirty_mask; + page->dirty_mask = 0; + + for (uint8_t c = 0; c < 64; c++) { + if (page->byte_code_present_mask[c] & page->byte_dirty_mask[c]) + remove_from_evict_list = 0; + page->byte_code_present_mask[c] &= ~page->byte_dirty_mask[c]; + page->byte_dirty_mask[c] = 0; + } + if (remove_from_evict_list) + page_remove_from_evict_list(page); } -void codegen_check_flush(page_t *page, uint64_t mask, uint32_t phys_addr) +void +codegen_block_init(uint32_t phys_addr) { - uint16_t block_nr = page->block; - int remove_from_evict_list = 0; - int c; + codeblock_t *block; + page_t *page = &pages[phys_addr >> 12]; - while (block_nr) - { - codeblock_t *block = &codeblock[block_nr]; - uint16_t next_block = block->next; - - if (*block->dirty_mask & block->page_mask) - { - invalidate_block(block); - } + if (!page->block) + mem_flush_write_page(phys_addr, cs + cpu_state.pc); + block = block_free_list_get(); #ifndef RELEASE_BUILD - if (block_nr == next_block) - fatal("Broken 1\n"); + if (!block) + fatal("codegen_block_init: block_free_list_get() returned NULL\n"); #endif - block_nr = next_block; - } + block_current = get_block_nr(block); - block_nr = page->block_2; - - while (block_nr) - { - codeblock_t *block = &codeblock[block_nr]; - uint16_t next_block = block->next_2; + block_num = HASH(phys_addr); + codeblock_hash[block_num] = block_current; - if (*block->dirty_mask2 & block->page_mask2) - { - invalidate_block(block); - } -#ifndef RELEASE_BUILD - if (block_nr == next_block) - fatal("Broken 2\n"); -#endif - block_nr = next_block; - } - - if (page->code_present_mask & page->dirty_mask) - remove_from_evict_list = 1; - page->code_present_mask &= ~page->dirty_mask; - page->dirty_mask = 0; - - for (c = 0; c < 64; c++) - { - if (page->byte_code_present_mask[c] & page->byte_dirty_mask[c]) - remove_from_evict_list = 0; - page->byte_code_present_mask[c] &= ~page->byte_dirty_mask[c]; - page->byte_dirty_mask[c] = 0; - } - if (remove_from_evict_list) - page_remove_from_evict_list(page); -} + block->ins = 0; + block->pc = cs + cpu_state.pc; + block->_cs = cs; + block->phys = phys_addr; + block->dirty_mask = &page->dirty_mask; + block->dirty_mask2 = NULL; + block->next = block->prev = BLOCK_INVALID; + block->next_2 = block->prev_2 = BLOCK_INVALID; + block->page_mask = block->page_mask2 = 0; + block->flags = CODEBLOCK_STATIC_TOP; + block->status = cpu_cur_status; -void codegen_block_init(uint32_t phys_addr) -{ - codeblock_t *block; - page_t *page = &pages[phys_addr >> 12]; - - if (!page->block) - mem_flush_write_page(phys_addr, cs+cpu_state.pc); - block = block_free_list_get(); -#ifndef RELEASE_BUILD - if (!block) - fatal("codegen_block_init: block_free_list_get() returned NULL\n"); -#endif - block_current = get_block_nr(block); - - block_num = HASH(phys_addr); - codeblock_hash[block_num] = block_current; - - block->ins = 0; - block->pc = cs + cpu_state.pc; - block->_cs = cs; - block->phys = phys_addr; - block->dirty_mask = &page->dirty_mask; - block->dirty_mask2 = NULL; - block->next = block->prev = BLOCK_INVALID; - block->next_2 = block->prev_2 = BLOCK_INVALID; - block->page_mask = block->page_mask2 = 0; - block->flags = CODEBLOCK_STATIC_TOP; - block->status = cpu_cur_status; - - recomp_page = block->phys & ~0xfff; - codeblock_tree_add(block); + recomp_page = block->phys & ~0xfff; + codeblock_tree_add(block); } static ir_data_t *ir_data; -ir_data_t *codegen_get_ir_data() +ir_data_t * +codegen_get_ir_data(void) { - return ir_data; + return ir_data; } -void codegen_block_start_recompile(codeblock_t *block) +void +codegen_block_start_recompile(codeblock_t *block) { - page_t *page = &pages[block->phys >> 12]; + page_t *page = &pages[block->phys >> 12]; - if (!page->block) - mem_flush_write_page(block->phys, cs+cpu_state.pc); + if (!page->block) + mem_flush_write_page(block->phys, cs + cpu_state.pc); - block_num = HASH(block->phys); - block_current = get_block_nr(block);//block->pnt; + block_num = HASH(block->phys); + block_current = get_block_nr(block); // block->pnt; #ifndef RELEASE_BUILD - if (block->pc != cs + cpu_state.pc || (block->flags & CODEBLOCK_WAS_RECOMPILED)) - fatal("Recompile to used block!\n"); + if (block->pc != cs + cpu_state.pc || (block->flags & CODEBLOCK_WAS_RECOMPILED)) + fatal("Recompile to used block!\n"); #endif - block->head_mem_block = codegen_allocator_allocate(NULL, block_current); - block->data = codeblock_allocator_get_ptr(block->head_mem_block); + block->head_mem_block = codegen_allocator_allocate(NULL, block_current); + block->data = codeblock_allocator_get_ptr(block->head_mem_block); - block->status = cpu_cur_status; - - block->page_mask = block->page_mask2 = 0; - block->ins = 0; + block->status = cpu_cur_status; - cpu_block_end = 0; + block->page_mask = block->page_mask2 = 0; + block->ins = 0; - last_op32 = -1; - last_ea_seg = NULL; - last_ssegs = -1; - - codegen_block_cycles = 0; - codegen_timing_block_start(); - - codegen_block_ins = 0; - codegen_block_full_ins = 0; + cpu_block_end = 0; - recomp_page = block->phys & ~0xfff; - - codegen_flags_changed = 0; - codegen_fpu_entered = 0; - codegen_mmx_entered = 0; + last_op32 = -1; + last_ea_seg = NULL; + last_ssegs = -1; - codegen_fpu_loaded_iq[0] = codegen_fpu_loaded_iq[1] = codegen_fpu_loaded_iq[2] = codegen_fpu_loaded_iq[3] = - codegen_fpu_loaded_iq[4] = codegen_fpu_loaded_iq[5] = codegen_fpu_loaded_iq[6] = codegen_fpu_loaded_iq[7] = 0; - - cpu_state.seg_ds.checked = cpu_state.seg_es.checked = cpu_state.seg_fs.checked = cpu_state.seg_gs.checked = (cr0 & 1) ? 0 : 1; + codegen_block_cycles = 0; + codegen_timing_block_start(); - block->TOP = cpu_state.TOP & 7; - block->flags |= CODEBLOCK_WAS_RECOMPILED; + codegen_block_ins = 0; + codegen_block_full_ins = 0; - codegen_flat_ds = !(cpu_cur_status & CPU_STATUS_NOTFLATDS); - codegen_flat_ss = !(cpu_cur_status & CPU_STATUS_NOTFLATSS); - - if (block->flags & CODEBLOCK_BYTE_MASK) - { - block->dirty_mask = &page->byte_dirty_mask[(block->phys >> PAGE_BYTE_MASK_SHIFT) & PAGE_BYTE_MASK_OFFSET_MASK]; - block->dirty_mask2 = NULL; - } + recomp_page = block->phys & ~0xfff; - ir_data = codegen_ir_init(); - ir_data->block = block; - codegen_reg_reset(); - codegen_accumulate_reset(); - codegen_generate_reset(); + codegen_flags_changed = 0; + codegen_fpu_entered = 0; + codegen_mmx_entered = 0; + + codegen_fpu_loaded_iq[0] = codegen_fpu_loaded_iq[1] = codegen_fpu_loaded_iq[2] = codegen_fpu_loaded_iq[3] = codegen_fpu_loaded_iq[4] = codegen_fpu_loaded_iq[5] = codegen_fpu_loaded_iq[6] = codegen_fpu_loaded_iq[7] = 0; + + cpu_state.seg_ds.checked = cpu_state.seg_es.checked = cpu_state.seg_fs.checked = cpu_state.seg_gs.checked = (cr0 & 1) ? 0 : 1; + + block->TOP = cpu_state.TOP & 7; + block->flags |= CODEBLOCK_WAS_RECOMPILED; + + codegen_flat_ds = !(cpu_cur_status & CPU_STATUS_NOTFLATDS); + codegen_flat_ss = !(cpu_cur_status & CPU_STATUS_NOTFLATSS); + + if (block->flags & CODEBLOCK_BYTE_MASK) { + block->dirty_mask = &page->byte_dirty_mask[(block->phys >> PAGE_BYTE_MASK_SHIFT) & PAGE_BYTE_MASK_OFFSET_MASK]; + block->dirty_mask2 = NULL; + } + + ir_data = codegen_ir_init(); + ir_data->block = block; + codegen_reg_reset(); + codegen_accumulate_reset(); + codegen_generate_reset(); } - -void codegen_block_remove() +void +codegen_block_remove(void) { - codeblock_t *block = &codeblock[block_current]; + codeblock_t *block = &codeblock[block_current]; - delete_block(block); + delete_block(block); - recomp_page = -1; + recomp_page = -1; } -void codegen_block_generate_end_mask_recompile() +void +codegen_block_generate_end_mask_recompile(void) { - codeblock_t *block = &codeblock[block_current]; - page_t *p; + codeblock_t *block = &codeblock[block_current]; + page_t *p; - p = &pages[block->phys >> 12]; - if (block->flags & CODEBLOCK_BYTE_MASK) - { - int offset = (block->phys >> PAGE_BYTE_MASK_SHIFT) & PAGE_BYTE_MASK_OFFSET_MASK; + p = &pages[block->phys >> 12]; + if (block->flags & CODEBLOCK_BYTE_MASK) { + int offset = (block->phys >> PAGE_BYTE_MASK_SHIFT) & PAGE_BYTE_MASK_OFFSET_MASK; - p->byte_code_present_mask[offset] |= block->page_mask; - } - else - p->code_present_mask |= block->page_mask; - - if ((*(block->dirty_mask) & block->page_mask) && !page_in_evict_list(p)) - page_add_to_evict_list(p); - - block->phys_2 = -1; - block->next_2 = block->prev_2 = BLOCK_INVALID; - if (block->page_mask2) - { - block->phys_2 = get_phys_noabrt(codegen_endpc); - if (block->phys_2 != -1) - { - page_t *page_2 = &pages[block->phys_2 >> 12]; - - if (block->flags & CODEBLOCK_BYTE_MASK) - { - int offset = (block->phys_2 >> PAGE_BYTE_MASK_SHIFT) & PAGE_BYTE_MASK_OFFSET_MASK; - - page_2->byte_code_present_mask[offset] |= block->page_mask2; - block->dirty_mask2 = &page_2->byte_dirty_mask[offset]; - } - else - { - page_2->code_present_mask |= block->page_mask2; - block->dirty_mask2 = &page_2->dirty_mask; - } - if (((*block->dirty_mask2) & block->page_mask2) && !page_in_evict_list(page_2)) - page_add_to_evict_list(page_2); - - if (!pages[block->phys_2 >> 12].block_2) - mem_flush_write_page(block->phys_2, codegen_endpc); - -#ifndef RELEASE_BUILD - if (!block->page_mask2) - fatal("!page_mask2\n"); - if (block->next_2) - { - if (codeblock[block->next_2].pc == BLOCK_PC_INVALID) - fatal("block->next_2->pc=BLOCK_PC_INVALID %p\n", (void *)&codeblock[block->next_2]); - } -#endif - } - else - { - /*Second page not present. page_mask2 is most likely set only because - the recompiler didn't know how long the last instruction was, so - clear it*/ - block->page_mask2 = 0; - } - } - - recomp_page = -1; -} - -void codegen_block_generate_end_mask_mark() -{ - codeblock_t *block = &codeblock[block_current]; - uint32_t start_pc; - uint32_t end_pc; - page_t *p; - -#ifndef RELEASE_BUILD - if (block->flags & CODEBLOCK_BYTE_MASK) - fatal("codegen_block_generate_end_mask2() - BYTE_MASK\n"); -#endif - - block->page_mask = 0; - start_pc = (block->pc & 0xfff) & ~63; - if ((block->pc ^ codegen_endpc) & ~0xfff) - end_pc = 0xfff & ~63; - else - end_pc = (codegen_endpc & 0xfff) & ~63; - if (end_pc < start_pc) - end_pc = 0xfff; - start_pc >>= PAGE_MASK_SHIFT; - end_pc >>= PAGE_MASK_SHIFT; - - for (; start_pc <= end_pc; start_pc++) - { - block->page_mask |= ((uint64_t)1 << start_pc); - } - - p = &pages[block->phys >> 12]; + p->byte_code_present_mask[offset] |= block->page_mask; + } else p->code_present_mask |= block->page_mask; - if ((p->dirty_mask & block->page_mask) && !page_in_evict_list(p)) - page_add_to_evict_list(p); - block->phys_2 = -1; - block->page_mask2 = 0; - block->next_2 = block->prev_2 = BLOCK_INVALID; - if ((block->pc ^ codegen_endpc) & ~0xfff) - { - block->phys_2 = get_phys_noabrt(codegen_endpc); - if (block->phys_2 != -1) - { - page_t *page_2 = &pages[block->phys_2 >> 12]; + if ((*(block->dirty_mask) & block->page_mask) && !page_in_evict_list(p)) + page_add_to_evict_list(p); - start_pc = 0; - end_pc = (codegen_endpc & 0xfff) >> PAGE_MASK_SHIFT; - for (; start_pc <= end_pc; start_pc++) - block->page_mask2 |= ((uint64_t)1 << start_pc); + block->phys_2 = -1; + block->next_2 = block->prev_2 = BLOCK_INVALID; + if (block->page_mask2) { + block->phys_2 = get_phys_noabrt(codegen_endpc); + if (block->phys_2 != -1) { + page_t *page_2 = &pages[block->phys_2 >> 12]; - page_2->code_present_mask |= block->page_mask2; - if ((page_2->dirty_mask & block->page_mask2) && !page_in_evict_list(page_2)) - page_add_to_evict_list(page_2); + if (block->flags & CODEBLOCK_BYTE_MASK) { + int offset = (block->phys_2 >> PAGE_BYTE_MASK_SHIFT) & PAGE_BYTE_MASK_OFFSET_MASK; - if (!pages[block->phys_2 >> 12].block_2) - mem_flush_write_page(block->phys_2, codegen_endpc); + page_2->byte_code_present_mask[offset] |= block->page_mask2; + block->dirty_mask2 = &page_2->byte_dirty_mask[offset]; + } else { + page_2->code_present_mask |= block->page_mask2; + block->dirty_mask2 = &page_2->dirty_mask; + } + if (((*block->dirty_mask2) & block->page_mask2) && !page_in_evict_list(page_2)) + page_add_to_evict_list(page_2); + + if (!pages[block->phys_2 >> 12].block_2) + mem_flush_write_page(block->phys_2, codegen_endpc); #ifndef RELEASE_BUILD - if (!block->page_mask2) - fatal("!page_mask2\n"); - if (block->next_2) - { - if (codeblock[block->next_2].pc == BLOCK_PC_INVALID) - fatal("block->next_2->pc=BLOCK_PC_INVALID %p\n", (void *)&codeblock[block->next_2]); - } + if (!block->page_mask2) + fatal("!page_mask2\n"); + if (block->next_2) { + if (codeblock[block->next_2].pc == BLOCK_PC_INVALID) + fatal("block->next_2->pc=BLOCK_PC_INVALID %p\n", (void *) &codeblock[block->next_2]); + } #endif - block->dirty_mask2 = &page_2->dirty_mask; - } - else - { - /*Second page not present. page_mask2 is most likely set only because - the recompiler didn't know how long the last instruction was, so - clear it*/ - block->page_mask2 = 0; - } + } else { + /*Second page not present. page_mask2 is most likely set only because + the recompiler didn't know how long the last instruction was, so + clear it*/ + block->page_mask2 = 0; } + } - recomp_page = -1; + recomp_page = -1; } -void codegen_block_end() +void +codegen_block_generate_end_mask_mark(void) { - codeblock_t *block = &codeblock[block_current]; + codeblock_t *block = &codeblock[block_current]; + uint32_t start_pc; + uint32_t end_pc; + page_t *p; - codegen_block_generate_end_mask_mark(); - add_to_block_list(block); -} +#ifndef RELEASE_BUILD + if (block->flags & CODEBLOCK_BYTE_MASK) + fatal("codegen_block_generate_end_mask2() - BYTE_MASK\n"); +#endif -void codegen_block_end_recompile(codeblock_t *block) -{ - codegen_timing_block_end(); - codegen_accumulate(ir_data, ACCREG_cycles, -codegen_block_cycles); + block->page_mask = 0; + start_pc = (block->pc & 0xfff) & ~63; + if ((block->pc ^ codegen_endpc) & ~0xfff) + end_pc = 0xfff & ~63; + else + end_pc = (codegen_endpc & 0xfff) & ~63; + if (end_pc < start_pc) + end_pc = 0xfff; + start_pc >>= PAGE_MASK_SHIFT; + end_pc >>= PAGE_MASK_SHIFT; - if (block->flags & CODEBLOCK_IN_DIRTY_LIST) - block_dirty_list_remove(block); - else - remove_from_block_list(block, block->pc); - block->next = block->prev = BLOCK_INVALID; - block->next_2 = block->prev_2 = BLOCK_INVALID; - codegen_block_generate_end_mask_recompile(); - add_to_block_list(block); + for (; start_pc <= end_pc; start_pc++) { + block->page_mask |= ((uint64_t) 1 << start_pc); + } - if (!(block->flags & CODEBLOCK_HAS_FPU)) - block->flags &= ~CODEBLOCK_STATIC_TOP; + p = &pages[block->phys >> 12]; + p->code_present_mask |= block->page_mask; + if ((p->dirty_mask & block->page_mask) && !page_in_evict_list(p)) + page_add_to_evict_list(p); - codegen_accumulate_flush(ir_data); - codegen_ir_compile(ir_data, block); -} + block->phys_2 = -1; + block->page_mask2 = 0; + block->next_2 = block->prev_2 = BLOCK_INVALID; + if ((block->pc ^ codegen_endpc) & ~0xfff) { + block->phys_2 = get_phys_noabrt(codegen_endpc); + if (block->phys_2 != -1) { + page_t *page_2 = &pages[block->phys_2 >> 12]; -void codegen_flush() -{ - return; -} + start_pc = 0; + end_pc = (codegen_endpc & 0xfff) >> PAGE_MASK_SHIFT; + for (; start_pc <= end_pc; start_pc++) + block->page_mask2 |= ((uint64_t) 1 << start_pc); -void codegen_mark_code_present_multibyte(codeblock_t *block, uint32_t start_pc, int len) -{ - if (len) - { - uint32_t end_pc = start_pc + (len-1); + page_2->code_present_mask |= block->page_mask2; + if ((page_2->dirty_mask & block->page_mask2) && !page_in_evict_list(page_2)) + page_add_to_evict_list(page_2); - if (block->flags & CODEBLOCK_BYTE_MASK) - { - uint32_t start_pc_masked = start_pc & PAGE_MASK_MASK; - uint32_t end_pc_masked = end_pc & PAGE_MASK_MASK; + if (!pages[block->phys_2 >> 12].block_2) + mem_flush_write_page(block->phys_2, codegen_endpc); - if ((start_pc ^ block->pc) & ~0x3f) /*Starts in second page*/ - { - for (; start_pc_masked <= end_pc_masked; start_pc_masked++) - block->page_mask2 |= ((uint64_t)1 << start_pc_masked); - } - else if (((start_pc + (len-1)) ^ block->pc) & ~0x3f) /*Crosses both pages*/ - { - for (; start_pc_masked <= 63; start_pc_masked++) - block->page_mask |= ((uint64_t)1 << start_pc_masked); - for (start_pc_masked = 0; start_pc_masked <= end_pc_masked; start_pc_masked++) - block->page_mask2 |= ((uint64_t)1 << start_pc_masked); - } - else /*First page only*/ - { - for (; start_pc_masked <= end_pc_masked; start_pc_masked++) - block->page_mask |= ((uint64_t)1 << start_pc_masked); - } - } - else - { - uint32_t start_pc_shifted = start_pc >> PAGE_MASK_SHIFT; - uint32_t end_pc_shifted = end_pc >> PAGE_MASK_SHIFT; - start_pc_shifted &= PAGE_MASK_MASK; - end_pc_shifted &= PAGE_MASK_MASK; - - if ((start_pc ^ block->pc) & ~0xfff) /*Starts in second page*/ - { - for (; start_pc_shifted <= end_pc_shifted; start_pc_shifted++) - block->page_mask2 |= ((uint64_t)1 << start_pc_shifted); - } - else if (((start_pc + (len-1)) ^ block->pc) & ~0xfff) /*Crosses both pages*/ - { - for (; start_pc_shifted <= 63; start_pc_shifted++) - block->page_mask |= ((uint64_t)1 << start_pc_shifted); - for (start_pc_shifted = 0; start_pc_shifted <= end_pc_shifted; start_pc_shifted++) - block->page_mask2 |= ((uint64_t)1 << start_pc_shifted); - } - else /*First page only*/ - { - for (; start_pc_shifted <= end_pc_shifted; start_pc_shifted++) - block->page_mask |= ((uint64_t)1 << start_pc_shifted); - } - } +#ifndef RELEASE_BUILD + if (!block->page_mask2) + fatal("!page_mask2\n"); + if (block->next_2) { + if (codeblock[block->next_2].pc == BLOCK_PC_INVALID) + fatal("block->next_2->pc=BLOCK_PC_INVALID %p\n", (void *) &codeblock[block->next_2]); + } +#endif + block->dirty_mask2 = &page_2->dirty_mask; + } else { + /*Second page not present. page_mask2 is most likely set only because + the recompiler didn't know how long the last instruction was, so + clear it*/ + block->page_mask2 = 0; } + } + + recomp_page = -1; +} + +void +codegen_block_end(void) +{ + codeblock_t *block = &codeblock[block_current]; + + codegen_block_generate_end_mask_mark(); + add_to_block_list(block); +} + +void +codegen_block_end_recompile(codeblock_t *block) +{ + codegen_timing_block_end(); + codegen_accumulate(ir_data, ACCREG_cycles, -codegen_block_cycles); + + if (block->flags & CODEBLOCK_IN_DIRTY_LIST) + block_dirty_list_remove(block); + else + remove_from_block_list(block, block->pc); + block->next = block->prev = BLOCK_INVALID; + block->next_2 = block->prev_2 = BLOCK_INVALID; + codegen_block_generate_end_mask_recompile(); + add_to_block_list(block); + + if (!(block->flags & CODEBLOCK_HAS_FPU)) + block->flags &= ~CODEBLOCK_STATIC_TOP; + + codegen_accumulate_flush(ir_data); + codegen_ir_compile(ir_data, block); +} + +void +codegen_flush(void) +{ + return; +} + +void +codegen_mark_code_present_multibyte(codeblock_t *block, uint32_t start_pc, int len) +{ + if (len) { + uint32_t end_pc = start_pc + (len - 1); + + if (block->flags & CODEBLOCK_BYTE_MASK) { + uint32_t start_pc_masked = start_pc & PAGE_MASK_MASK; + uint32_t end_pc_masked = end_pc & PAGE_MASK_MASK; + + if ((start_pc ^ block->pc) & ~0x3f) /*Starts in second page*/ + { + for (; start_pc_masked <= end_pc_masked; start_pc_masked++) + block->page_mask2 |= ((uint64_t) 1 << start_pc_masked); + } else if (((start_pc + (len - 1)) ^ block->pc) & ~0x3f) /*Crosses both pages*/ + { + for (; start_pc_masked <= 63; start_pc_masked++) + block->page_mask |= ((uint64_t) 1 << start_pc_masked); + for (start_pc_masked = 0; start_pc_masked <= end_pc_masked; start_pc_masked++) + block->page_mask2 |= ((uint64_t) 1 << start_pc_masked); + } else /*First page only*/ + { + for (; start_pc_masked <= end_pc_masked; start_pc_masked++) + block->page_mask |= ((uint64_t) 1 << start_pc_masked); + } + } else { + uint32_t start_pc_shifted = start_pc >> PAGE_MASK_SHIFT; + uint32_t end_pc_shifted = end_pc >> PAGE_MASK_SHIFT; + start_pc_shifted &= PAGE_MASK_MASK; + end_pc_shifted &= PAGE_MASK_MASK; + + if ((start_pc ^ block->pc) & ~0xfff) /*Starts in second page*/ + { + for (; start_pc_shifted <= end_pc_shifted; start_pc_shifted++) + block->page_mask2 |= ((uint64_t) 1 << start_pc_shifted); + } else if (((start_pc + (len - 1)) ^ block->pc) & ~0xfff) /*Crosses both pages*/ + { + for (; start_pc_shifted <= 63; start_pc_shifted++) + block->page_mask |= ((uint64_t) 1 << start_pc_shifted); + for (start_pc_shifted = 0; start_pc_shifted <= end_pc_shifted; start_pc_shifted++) + block->page_mask2 |= ((uint64_t) 1 << start_pc_shifted); + } else /*First page only*/ + { + for (; start_pc_shifted <= end_pc_shifted; start_pc_shifted++) + block->page_mask |= ((uint64_t) 1 << start_pc_shifted); + } + } + } } diff --git a/src/codegen_new/codegen_ir.c b/src/codegen_new/codegen_ir.c index a949b7f86..6345bbe86 100644 --- a/src/codegen_new/codegen_ir.c +++ b/src/codegen_new/codegen_ir.c @@ -9,208 +9,188 @@ #include "codegen_ir.h" #include "codegen_reg.h" -extern int has_ea; +extern int has_ea; static ir_data_t ir_block; -static int codegen_unroll_start, codegen_unroll_count; +static int codegen_unroll_start; +static int codegen_unroll_count; static int codegen_unroll_first_instruction; -ir_data_t *codegen_ir_init() +ir_data_t * +codegen_ir_init(void) { - ir_block.wr_pos = 0; + ir_block.wr_pos = 0; - codegen_unroll_count = 0; + codegen_unroll_count = 0; - return &ir_block; + return &ir_block; } -void codegen_ir_set_unroll(int count, int start, int first_instruction) +void +codegen_ir_set_unroll(int count, int start, int first_instruction) { - codegen_unroll_count = count; - codegen_unroll_start = start; - codegen_unroll_first_instruction = first_instruction; + codegen_unroll_count = count; + codegen_unroll_start = start; + codegen_unroll_first_instruction = first_instruction; } -static void duplicate_uop(ir_data_t *ir, uop_t *uop, int offset) +static void +duplicate_uop(ir_data_t *ir, uop_t *uop, int offset) { - uop_t *new_uop = uop_alloc(ir, uop->type); + uop_t *new_uop = uop_alloc(ir, uop->type); - if (!ir_reg_is_invalid(uop->src_reg_a)) - new_uop->src_reg_a = codegen_reg_read(uop->src_reg_a.reg); - if (!ir_reg_is_invalid(uop->src_reg_b)) - new_uop->src_reg_b = codegen_reg_read(uop->src_reg_b.reg); - if (!ir_reg_is_invalid(uop->src_reg_c)) - new_uop->src_reg_c = codegen_reg_read(uop->src_reg_c.reg); - if (!ir_reg_is_invalid(uop->dest_reg_a)) - new_uop->dest_reg_a = codegen_reg_write(uop->dest_reg_a.reg, ir->wr_pos-1); + if (!ir_reg_is_invalid(uop->src_reg_a)) + new_uop->src_reg_a = codegen_reg_read(uop->src_reg_a.reg); + if (!ir_reg_is_invalid(uop->src_reg_b)) + new_uop->src_reg_b = codegen_reg_read(uop->src_reg_b.reg); + if (!ir_reg_is_invalid(uop->src_reg_c)) + new_uop->src_reg_c = codegen_reg_read(uop->src_reg_c.reg); + if (!ir_reg_is_invalid(uop->dest_reg_a)) + new_uop->dest_reg_a = codegen_reg_write(uop->dest_reg_a.reg, ir->wr_pos - 1); - new_uop->type = uop->type; - new_uop->imm_data = uop->imm_data; - new_uop->p = uop->p; - new_uop->pc = uop->pc; - - if (uop->jump_dest_uop != -1) - { - new_uop->jump_dest_uop = uop->jump_dest_uop + offset; + new_uop->type = uop->type; + new_uop->imm_data = uop->imm_data; + new_uop->p = uop->p; + new_uop->pc = uop->pc; + + if (uop->jump_dest_uop != -1) { + new_uop->jump_dest_uop = uop->jump_dest_uop + offset; + } +} + +void +codegen_ir_compile(ir_data_t *ir, codeblock_t *block) +{ + int jump_target_at_end = -1; + int c; + + if (codegen_unroll_count) { + int unroll_end; + + codegen_set_loop_start(ir, codegen_unroll_first_instruction); + unroll_end = ir->wr_pos; + + for (int unroll_count = 1; unroll_count < codegen_unroll_count; unroll_count++) { + int offset = ir->wr_pos - codegen_unroll_start; + // pclog("Unroll from %i to %i, offset %i - iteration %i\n", codegen_unroll_start, ir->wr_pos, offset, unroll_count); + for (c = codegen_unroll_start; c < unroll_end; c++) { + // pclog(" Duplicate uop %i\n", c); + duplicate_uop(ir, &ir->uops[c], offset); + } } -} + } -void codegen_ir_compile(ir_data_t *ir, codeblock_t *block) -{ - int jump_target_at_end = -1; - int c; + codegen_reg_mark_as_required(); + codegen_reg_process_dead_list(ir); + block_write_data = codeblock_allocator_get_ptr(block->head_mem_block); + block_pos = 0; + codegen_backend_prologue(block); - if (codegen_unroll_count) - { - int unroll_count; - int unroll_end; - - codegen_set_loop_start(ir, codegen_unroll_first_instruction); - unroll_end = ir->wr_pos; - - for (unroll_count = 1; unroll_count < codegen_unroll_count; unroll_count++) - { - int offset = ir->wr_pos - codegen_unroll_start; -// pclog("Unroll from %i to %i, offset %i - iteration %i\n", codegen_unroll_start, ir->wr_pos, offset, unroll_count); - for (c = codegen_unroll_start; c < unroll_end; c++) - { -// pclog(" Duplicate uop %i\n", c); - duplicate_uop(ir, &ir->uops[c], offset); - } - } + for (c = 0; c < ir->wr_pos; c++) { + uop_t *uop = &ir->uops[c]; + + // pclog("uOP %i : %08x\n", c, uop->type); + + if (uop->type & UOP_TYPE_BARRIER) + codegen_reg_flush_invalidate(ir, block); + + if (uop->type & UOP_TYPE_JUMP_DEST) { + uop_t *uop_dest = uop; + + while (uop_dest->jump_list_next != -1) { + uop_dest = &ir->uops[uop_dest->jump_list_next]; + codegen_set_jump_dest(block, uop_dest->p); + } } - codegen_reg_mark_as_required(); - codegen_reg_process_dead_list(ir); - block_write_data = codeblock_allocator_get_ptr(block->head_mem_block); - block_pos = 0; - codegen_backend_prologue(block); - - for (c = 0; c < ir->wr_pos; c++) - { - uop_t *uop = &ir->uops[c]; - -// pclog("uOP %i : %08x\n", c, uop->type); - - if (uop->type & UOP_TYPE_BARRIER) - codegen_reg_flush_invalidate(ir, block); - - if (uop->type & UOP_TYPE_JUMP_DEST) - { - uop_t *uop_dest = uop; - - while (uop_dest->jump_list_next != -1) - { - uop_dest = &ir->uops[uop_dest->jump_list_next]; - codegen_set_jump_dest(block, uop_dest->p); - } - } - - if ((uop->type & UOP_MASK) == UOP_INVALID) - continue; + if ((uop->type & UOP_MASK) == UOP_INVALID) + continue; #ifdef CODEGEN_BACKEND_HAS_MOV_IMM - if ((uop->type & UOP_MASK) == (UOP_MOV_IMM & UOP_MASK) && reg_is_native_size(uop->dest_reg_a) && !codegen_reg_is_loaded(uop->dest_reg_a) && reg_version[IREG_GET_REG(uop->dest_reg_a.reg)][uop->dest_reg_a.version].refcount <= 0) - { - /*Special case for UOP_MOV_IMM - if destination not already in host register - and won't be used again then just store directly to memory*/ - codegen_reg_write_imm(block, uop->dest_reg_a, uop->imm_data); - } - else + if ((uop->type & UOP_MASK) == (UOP_MOV_IMM & UOP_MASK) && reg_is_native_size(uop->dest_reg_a) && !codegen_reg_is_loaded(uop->dest_reg_a) && reg_version[IREG_GET_REG(uop->dest_reg_a.reg)][uop->dest_reg_a.version].refcount <= 0) { + /*Special case for UOP_MOV_IMM - if destination not already in host register + and won't be used again then just store directly to memory*/ + codegen_reg_write_imm(block, uop->dest_reg_a, uop->imm_data); + } else #endif - if ((uop->type & UOP_MASK) == (UOP_MOV & UOP_MASK) && reg_version[IREG_GET_REG(uop->src_reg_a.reg)][uop->src_reg_a.version].refcount <= 1 && - reg_is_native_size(uop->src_reg_a) && reg_is_native_size(uop->dest_reg_a)) - { - /*Special case for UOP_MOV - if source register won't be used again then - just rename it to dest register instead of moving*/ - codegen_reg_alloc_register(invalid_ir_reg, uop->src_reg_a, invalid_ir_reg, invalid_ir_reg); - uop->src_reg_a_real = codegen_reg_alloc_read_reg(block, uop->src_reg_a, NULL); - codegen_reg_rename(block, uop->src_reg_a, uop->dest_reg_a); - if (uop->type & UOP_TYPE_ORDER_BARRIER) - codegen_reg_flush(ir, block); + if ((uop->type & UOP_MASK) == (UOP_MOV & UOP_MASK) && reg_version[IREG_GET_REG(uop->src_reg_a.reg)][uop->src_reg_a.version].refcount <= 1 && reg_is_native_size(uop->src_reg_a) && reg_is_native_size(uop->dest_reg_a)) { + /*Special case for UOP_MOV - if source register won't be used again then + just rename it to dest register instead of moving*/ + codegen_reg_alloc_register(invalid_ir_reg, uop->src_reg_a, invalid_ir_reg, invalid_ir_reg); + uop->src_reg_a_real = codegen_reg_alloc_read_reg(block, uop->src_reg_a, NULL); + codegen_reg_rename(block, uop->src_reg_a, uop->dest_reg_a); + if (uop->type & UOP_TYPE_ORDER_BARRIER) + codegen_reg_flush(ir, block); + } else { + if (uop->type & UOP_TYPE_PARAMS_REGS) { + codegen_reg_alloc_register(uop->dest_reg_a, uop->src_reg_a, uop->src_reg_b, uop->src_reg_c); + if (uop->src_reg_a.reg != IREG_INVALID) { + uop->src_reg_a_real = codegen_reg_alloc_read_reg(block, uop->src_reg_a, NULL); } - else - { - if (uop->type & UOP_TYPE_PARAMS_REGS) - { - codegen_reg_alloc_register(uop->dest_reg_a, uop->src_reg_a, uop->src_reg_b, uop->src_reg_c); - if (uop->src_reg_a.reg != IREG_INVALID) - { - uop->src_reg_a_real = codegen_reg_alloc_read_reg(block, uop->src_reg_a, NULL); - } - if (uop->src_reg_b.reg != IREG_INVALID) - { - uop->src_reg_b_real = codegen_reg_alloc_read_reg(block, uop->src_reg_b, NULL); - } - if (uop->src_reg_c.reg != IREG_INVALID) - { - uop->src_reg_c_real = codegen_reg_alloc_read_reg(block, uop->src_reg_c, NULL); - } - } + if (uop->src_reg_b.reg != IREG_INVALID) { + uop->src_reg_b_real = codegen_reg_alloc_read_reg(block, uop->src_reg_b, NULL); + } + if (uop->src_reg_c.reg != IREG_INVALID) { + uop->src_reg_c_real = codegen_reg_alloc_read_reg(block, uop->src_reg_c, NULL); + } + } - if (uop->type & UOP_TYPE_ORDER_BARRIER) - codegen_reg_flush(ir, block); + if (uop->type & UOP_TYPE_ORDER_BARRIER) + codegen_reg_flush(ir, block); - if (uop->type & UOP_TYPE_PARAMS_REGS) - { - if (uop->dest_reg_a.reg != IREG_INVALID) - { - uop->dest_reg_a_real = codegen_reg_alloc_write_reg(block, uop->dest_reg_a); - } - } + if (uop->type & UOP_TYPE_PARAMS_REGS) { + if (uop->dest_reg_a.reg != IREG_INVALID) { + uop->dest_reg_a_real = codegen_reg_alloc_write_reg(block, uop->dest_reg_a); + } + } #ifndef RELEASE_BUILD - if (!uop_handlers[uop->type & UOP_MASK]) - fatal("!uop_handlers[uop->type & UOP_MASK] %08x\n", uop->type); + if (!uop_handlers[uop->type & UOP_MASK]) + fatal("!uop_handlers[uop->type & UOP_MASK] %08x\n", uop->type); #endif - uop_handlers[uop->type & UOP_MASK](block, uop); - } - - if (uop->type & UOP_TYPE_JUMP) - { - if (uop->jump_dest_uop == ir->wr_pos) - { - if (jump_target_at_end == -1) - jump_target_at_end = c; - else - { - uop_t *uop_dest = &ir->uops[jump_target_at_end]; - - while (uop_dest->jump_list_next != -1) - uop_dest = &ir->uops[uop_dest->jump_list_next]; - - uop_dest->jump_list_next = c; - } - } - else - { - uop_t *uop_dest = &ir->uops[uop->jump_dest_uop]; - - while (uop_dest->jump_list_next != -1) - uop_dest = &ir->uops[uop_dest->jump_list_next]; - - uop_dest->jump_list_next = c; - ir->uops[uop->jump_dest_uop].type |= UOP_TYPE_JUMP_DEST; - } - } + uop_handlers[uop->type & UOP_MASK](block, uop); } - codegen_reg_flush_invalidate(ir, block); - - if (jump_target_at_end != -1) - { - uop_t *uop_dest = &ir->uops[jump_target_at_end]; + if (uop->type & UOP_TYPE_JUMP) { + if (uop->jump_dest_uop == ir->wr_pos) { + if (jump_target_at_end == -1) + jump_target_at_end = c; + else { + uop_t *uop_dest = &ir->uops[jump_target_at_end]; - while (1) - { - codegen_set_jump_dest(block, uop_dest->p); - if (uop_dest->jump_list_next == -1) - break; + while (uop_dest->jump_list_next != -1) uop_dest = &ir->uops[uop_dest->jump_list_next]; - } - } - codegen_backend_epilogue(block); - block_write_data = NULL; -// if (has_ea) -// fatal("IR compilation complete\n"); + uop_dest->jump_list_next = c; + } + } else { + uop_t *uop_dest = &ir->uops[uop->jump_dest_uop]; + + while (uop_dest->jump_list_next != -1) + uop_dest = &ir->uops[uop_dest->jump_list_next]; + + uop_dest->jump_list_next = c; + ir->uops[uop->jump_dest_uop].type |= UOP_TYPE_JUMP_DEST; + } + } + } + + codegen_reg_flush_invalidate(ir, block); + + if (jump_target_at_end != -1) { + uop_t *uop_dest = &ir->uops[jump_target_at_end]; + + while (1) { + codegen_set_jump_dest(block, uop_dest->p); + if (uop_dest->jump_list_next == -1) + break; + uop_dest = &ir->uops[uop_dest->jump_list_next]; + } + } + + codegen_backend_epilogue(block); + block_write_data = NULL; +#if 0 + if (has_ea) + fatal("IR compilation complete\n"); +#endif } diff --git a/src/codegen_new/codegen_ir.h b/src/codegen_new/codegen_ir.h index 60e75cfc9..ffae3eb75 100644 --- a/src/codegen_new/codegen_ir.h +++ b/src/codegen_new/codegen_ir.h @@ -1,6 +1,6 @@ #include "codegen_ir_defs.h" -ir_data_t *codegen_ir_init(); +ir_data_t *codegen_ir_init(void); void codegen_ir_set_unroll(int count, int start, int first_instruction); void codegen_ir_compile(ir_data_t *ir, codeblock_t *block); diff --git a/src/codegen_new/codegen_ir_defs.h b/src/codegen_new/codegen_ir_defs.h index 86276a053..26a1c3cb4 100644 --- a/src/codegen_new/codegen_ir_defs.h +++ b/src/codegen_new/codegen_ir_defs.h @@ -9,7 +9,7 @@ All registers must have been written back or discarded. This should be used when calling external functions that may change any emulated registers.*/ -#define UOP_TYPE_BARRIER (1 << 31) +#define UOP_TYPE_BARRIER (1u << 31) /*uOP is a barrier. All previous uOPs must have completed before this one executes. All registers must have been written back, but do not have to be discarded. @@ -18,761 +18,793 @@ #define UOP_TYPE_ORDER_BARRIER (1 << 27) /*uOP uses source and dest registers*/ -#define UOP_TYPE_PARAMS_REGS (1 << 28) +#define UOP_TYPE_PARAMS_REGS (1 << 28) /*uOP uses pointer*/ #define UOP_TYPE_PARAMS_POINTER (1 << 29) /*uOP uses immediate data*/ -#define UOP_TYPE_PARAMS_IMM (1 << 30) +#define UOP_TYPE_PARAMS_IMM (1 << 30) /*uOP is a jump, with the destination uOP in uop->jump_dest_uop. The compiler must set jump_dest in the destination uOP to the address of the branch offset to be written when known.*/ -#define UOP_TYPE_JUMP (1 << 26) +#define UOP_TYPE_JUMP (1 << 26) /*uOP is the destination of a jump, and must set the destination offset of the jump at compile time.*/ #define UOP_TYPE_JUMP_DEST (1 << 25) - -#define UOP_LOAD_FUNC_ARG_0 (UOP_TYPE_PARAMS_REGS | 0x00) -#define UOP_LOAD_FUNC_ARG_1 (UOP_TYPE_PARAMS_REGS | 0x01) -#define UOP_LOAD_FUNC_ARG_2 (UOP_TYPE_PARAMS_REGS | 0x02) -#define UOP_LOAD_FUNC_ARG_3 (UOP_TYPE_PARAMS_REGS | 0x03) -#define UOP_LOAD_FUNC_ARG_0_IMM (UOP_TYPE_PARAMS_IMM | 0x08 | UOP_TYPE_BARRIER) -#define UOP_LOAD_FUNC_ARG_1_IMM (UOP_TYPE_PARAMS_IMM | 0x09 | UOP_TYPE_BARRIER) -#define UOP_LOAD_FUNC_ARG_2_IMM (UOP_TYPE_PARAMS_IMM | 0x0a | UOP_TYPE_BARRIER) -#define UOP_LOAD_FUNC_ARG_3_IMM (UOP_TYPE_PARAMS_IMM | 0x0b | UOP_TYPE_BARRIER) -#define UOP_CALL_FUNC (UOP_TYPE_PARAMS_POINTER | 0x10 | UOP_TYPE_BARRIER) +#define UOP_LOAD_FUNC_ARG_0 (UOP_TYPE_PARAMS_REGS | 0x00) +#define UOP_LOAD_FUNC_ARG_1 (UOP_TYPE_PARAMS_REGS | 0x01) +#define UOP_LOAD_FUNC_ARG_2 (UOP_TYPE_PARAMS_REGS | 0x02) +#define UOP_LOAD_FUNC_ARG_3 (UOP_TYPE_PARAMS_REGS | 0x03) +#define UOP_LOAD_FUNC_ARG_0_IMM (UOP_TYPE_PARAMS_IMM | 0x08 | UOP_TYPE_BARRIER) +#define UOP_LOAD_FUNC_ARG_1_IMM (UOP_TYPE_PARAMS_IMM | 0x09 | UOP_TYPE_BARRIER) +#define UOP_LOAD_FUNC_ARG_2_IMM (UOP_TYPE_PARAMS_IMM | 0x0a | UOP_TYPE_BARRIER) +#define UOP_LOAD_FUNC_ARG_3_IMM (UOP_TYPE_PARAMS_IMM | 0x0b | UOP_TYPE_BARRIER) +#define UOP_CALL_FUNC (UOP_TYPE_PARAMS_POINTER | 0x10 | UOP_TYPE_BARRIER) /*UOP_CALL_INSTRUCTION_FUNC - call instruction handler at p, check return value and exit block if non-zero*/ #define UOP_CALL_INSTRUCTION_FUNC (UOP_TYPE_PARAMS_POINTER | 0x11 | UOP_TYPE_BARRIER) -#define UOP_STORE_P_IMM (UOP_TYPE_PARAMS_IMM | 0x12) -#define UOP_STORE_P_IMM_8 (UOP_TYPE_PARAMS_IMM | 0x13) +#define UOP_STORE_P_IMM (UOP_TYPE_PARAMS_IMM | 0x12) +#define UOP_STORE_P_IMM_8 (UOP_TYPE_PARAMS_IMM | 0x13) /*UOP_LOAD_SEG - load segment in src_reg_a to segment p via loadseg(), check return value and exit block if non-zero*/ -#define UOP_LOAD_SEG (UOP_TYPE_PARAMS_REGS | UOP_TYPE_PARAMS_POINTER | 0x14 | UOP_TYPE_BARRIER) +#define UOP_LOAD_SEG (UOP_TYPE_PARAMS_REGS | UOP_TYPE_PARAMS_POINTER | 0x14 | UOP_TYPE_BARRIER) /*UOP_JMP - jump to ptr*/ -#define UOP_JMP (UOP_TYPE_PARAMS_POINTER | 0x15 | UOP_TYPE_ORDER_BARRIER) +#define UOP_JMP (UOP_TYPE_PARAMS_POINTER | 0x15 | UOP_TYPE_ORDER_BARRIER) /*UOP_CALL_FUNC - call instruction handler at p, dest_reg = return value*/ -#define UOP_CALL_FUNC_RESULT (UOP_TYPE_PARAMS_REGS | UOP_TYPE_PARAMS_POINTER | 0x16 | UOP_TYPE_BARRIER) +#define UOP_CALL_FUNC_RESULT (UOP_TYPE_PARAMS_REGS | UOP_TYPE_PARAMS_POINTER | 0x16 | UOP_TYPE_BARRIER) /*UOP_JMP_DEST - jump to ptr*/ -#define UOP_JMP_DEST (UOP_TYPE_PARAMS_IMM | UOP_TYPE_PARAMS_POINTER | 0x17 | UOP_TYPE_ORDER_BARRIER | UOP_TYPE_JUMP) -#define UOP_NOP_BARRIER (UOP_TYPE_BARRIER | 0x18) -#define UOP_STORE_P_IMM_16 (UOP_TYPE_PARAMS_IMM | 0x19) +#define UOP_JMP_DEST (UOP_TYPE_PARAMS_IMM | UOP_TYPE_PARAMS_POINTER | 0x17 | UOP_TYPE_ORDER_BARRIER | UOP_TYPE_JUMP) +#define UOP_NOP_BARRIER (UOP_TYPE_BARRIER | 0x18) +#define UOP_STORE_P_IMM_16 (UOP_TYPE_PARAMS_IMM | 0x19) #ifdef DEBUG_EXTRA /*UOP_LOG_INSTR - log non-recompiled instruction in imm_data*/ -#define UOP_LOG_INSTR (UOP_TYPE_PARAMS_IMM | 0x1f) +# define UOP_LOG_INSTR (UOP_TYPE_PARAMS_IMM | 0x1f) #endif /*UOP_MOV_PTR - dest_reg = p*/ -#define UOP_MOV_PTR (UOP_TYPE_PARAMS_REGS | UOP_TYPE_PARAMS_POINTER | 0x20) +#define UOP_MOV_PTR (UOP_TYPE_PARAMS_REGS | UOP_TYPE_PARAMS_POINTER | 0x20) /*UOP_MOV_IMM - dest_reg = imm_data*/ -#define UOP_MOV_IMM (UOP_TYPE_PARAMS_REGS | UOP_TYPE_PARAMS_IMM | 0x21) +#define UOP_MOV_IMM (UOP_TYPE_PARAMS_REGS | UOP_TYPE_PARAMS_IMM | 0x21) /*UOP_MOV - dest_reg = src_reg_a*/ -#define UOP_MOV (UOP_TYPE_PARAMS_REGS | 0x22) +#define UOP_MOV (UOP_TYPE_PARAMS_REGS | 0x22) /*UOP_MOVZX - dest_reg = zero_extend(src_reg_a)*/ -#define UOP_MOVZX (UOP_TYPE_PARAMS_REGS | 0x23) +#define UOP_MOVZX (UOP_TYPE_PARAMS_REGS | 0x23) /*UOP_MOVSX - dest_reg = sign_extend(src_reg_a)*/ -#define UOP_MOVSX (UOP_TYPE_PARAMS_REGS | 0x24) +#define UOP_MOVSX (UOP_TYPE_PARAMS_REGS | 0x24) /*UOP_MOV_DOUBLE_INT - dest_reg = (double)src_reg_a*/ -#define UOP_MOV_DOUBLE_INT (UOP_TYPE_PARAMS_REGS | 0x25) +#define UOP_MOV_DOUBLE_INT (UOP_TYPE_PARAMS_REGS | 0x25) /*UOP_MOV_INT_DOUBLE - dest_reg = (int)src_reg_a. New rounding control in src_reg_b, old rounding control in src_reg_c*/ -#define UOP_MOV_INT_DOUBLE (UOP_TYPE_PARAMS_REGS | 0x26) +#define UOP_MOV_INT_DOUBLE (UOP_TYPE_PARAMS_REGS | 0x26) /*UOP_MOV_INT_DOUBLE_64 - dest_reg = (int)src_reg_a. New rounding control in src_reg_b, old rounding control in src_reg_c*/ -#define UOP_MOV_INT_DOUBLE_64 (UOP_TYPE_PARAMS_REGS | 0x27) +#define UOP_MOV_INT_DOUBLE_64 (UOP_TYPE_PARAMS_REGS | 0x27) /*UOP_MOV_REG_PTR - dest_reg = *p*/ -#define UOP_MOV_REG_PTR (UOP_TYPE_PARAMS_REGS | UOP_TYPE_PARAMS_POINTER | 0x28) +#define UOP_MOV_REG_PTR (UOP_TYPE_PARAMS_REGS | UOP_TYPE_PARAMS_POINTER | 0x28) /*UOP_MOVZX_REG_PTR_8 - dest_reg = *(uint8_t *)p*/ -#define UOP_MOVZX_REG_PTR_8 (UOP_TYPE_PARAMS_REGS | UOP_TYPE_PARAMS_POINTER | 0x29) +#define UOP_MOVZX_REG_PTR_8 (UOP_TYPE_PARAMS_REGS | UOP_TYPE_PARAMS_POINTER | 0x29) /*UOP_MOVZX_REG_PTR_16 - dest_reg = *(uint16_t *)p*/ -#define UOP_MOVZX_REG_PTR_16 (UOP_TYPE_PARAMS_REGS | UOP_TYPE_PARAMS_POINTER | 0x2a) +#define UOP_MOVZX_REG_PTR_16 (UOP_TYPE_PARAMS_REGS | UOP_TYPE_PARAMS_POINTER | 0x2a) /*UOP_ADD - dest_reg = src_reg_a + src_reg_b*/ -#define UOP_ADD (UOP_TYPE_PARAMS_REGS | 0x30) +#define UOP_ADD (UOP_TYPE_PARAMS_REGS | 0x30) /*UOP_ADD_IMM - dest_reg = src_reg_a + immediate*/ -#define UOP_ADD_IMM (UOP_TYPE_PARAMS_REGS | UOP_TYPE_PARAMS_IMM | 0x31) +#define UOP_ADD_IMM (UOP_TYPE_PARAMS_REGS | UOP_TYPE_PARAMS_IMM | 0x31) /*UOP_AND - dest_reg = src_reg_a & src_reg_b*/ -#define UOP_AND (UOP_TYPE_PARAMS_REGS | UOP_TYPE_PARAMS_IMM | 0x32) +#define UOP_AND (UOP_TYPE_PARAMS_REGS | UOP_TYPE_PARAMS_IMM | 0x32) /*UOP_AND_IMM - dest_reg = src_reg_a & immediate*/ -#define UOP_AND_IMM (UOP_TYPE_PARAMS_REGS | UOP_TYPE_PARAMS_IMM | 0x33) +#define UOP_AND_IMM (UOP_TYPE_PARAMS_REGS | UOP_TYPE_PARAMS_IMM | 0x33) /*UOP_ADD_LSHIFT - dest_reg = src_reg_a + (src_reg_b << imm_data) Intended for EA calcluations, imm_data must be between 0 and 3*/ -#define UOP_ADD_LSHIFT (UOP_TYPE_PARAMS_REGS | UOP_TYPE_PARAMS_IMM | 0x34) +#define UOP_ADD_LSHIFT (UOP_TYPE_PARAMS_REGS | UOP_TYPE_PARAMS_IMM | 0x34) /*UOP_OR - dest_reg = src_reg_a | src_reg_b*/ -#define UOP_OR (UOP_TYPE_PARAMS_REGS | UOP_TYPE_PARAMS_IMM | 0x35) +#define UOP_OR (UOP_TYPE_PARAMS_REGS | UOP_TYPE_PARAMS_IMM | 0x35) /*UOP_OR_IMM - dest_reg = src_reg_a | immediate*/ -#define UOP_OR_IMM (UOP_TYPE_PARAMS_REGS | UOP_TYPE_PARAMS_IMM | 0x36) +#define UOP_OR_IMM (UOP_TYPE_PARAMS_REGS | UOP_TYPE_PARAMS_IMM | 0x36) /*UOP_SUB - dest_reg = src_reg_a - src_reg_b*/ -#define UOP_SUB (UOP_TYPE_PARAMS_REGS | 0x37) +#define UOP_SUB (UOP_TYPE_PARAMS_REGS | 0x37) /*UOP_SUB_IMM - dest_reg = src_reg_a - immediate*/ -#define UOP_SUB_IMM (UOP_TYPE_PARAMS_REGS | UOP_TYPE_PARAMS_IMM | 0x38) +#define UOP_SUB_IMM (UOP_TYPE_PARAMS_REGS | UOP_TYPE_PARAMS_IMM | 0x38) /*UOP_XOR - dest_reg = src_reg_a ^ src_reg_b*/ -#define UOP_XOR (UOP_TYPE_PARAMS_REGS | UOP_TYPE_PARAMS_IMM | 0x39) +#define UOP_XOR (UOP_TYPE_PARAMS_REGS | UOP_TYPE_PARAMS_IMM | 0x39) /*UOP_XOR_IMM - dest_reg = src_reg_a ^ immediate*/ -#define UOP_XOR_IMM (UOP_TYPE_PARAMS_REGS | UOP_TYPE_PARAMS_IMM | 0x3a) +#define UOP_XOR_IMM (UOP_TYPE_PARAMS_REGS | UOP_TYPE_PARAMS_IMM | 0x3a) /*UOP_ANDN - dest_reg = ~src_reg_a & src_reg_b*/ -#define UOP_ANDN (UOP_TYPE_PARAMS_REGS | UOP_TYPE_PARAMS_IMM | 0x3b) +#define UOP_ANDN (UOP_TYPE_PARAMS_REGS | UOP_TYPE_PARAMS_IMM | 0x3b) /*UOP_MEM_LOAD_ABS - dest_reg = src_reg_a:[immediate]*/ -#define UOP_MEM_LOAD_ABS (UOP_TYPE_PARAMS_REGS | UOP_TYPE_PARAMS_IMM | 0x40 | UOP_TYPE_ORDER_BARRIER) +#define UOP_MEM_LOAD_ABS (UOP_TYPE_PARAMS_REGS | UOP_TYPE_PARAMS_IMM | 0x40 | UOP_TYPE_ORDER_BARRIER) /*UOP_MEM_LOAD_REG - dest_reg = src_reg_a:[src_reg_b]*/ -#define UOP_MEM_LOAD_REG (UOP_TYPE_PARAMS_REGS | UOP_TYPE_PARAMS_IMM | 0x41 | UOP_TYPE_ORDER_BARRIER) +#define UOP_MEM_LOAD_REG (UOP_TYPE_PARAMS_REGS | UOP_TYPE_PARAMS_IMM | 0x41 | UOP_TYPE_ORDER_BARRIER) /*UOP_MEM_STORE_ABS - src_reg_a:[immediate] = src_reg_b*/ -#define UOP_MEM_STORE_ABS (UOP_TYPE_PARAMS_REGS | UOP_TYPE_PARAMS_IMM | 0x42 | UOP_TYPE_ORDER_BARRIER) +#define UOP_MEM_STORE_ABS (UOP_TYPE_PARAMS_REGS | UOP_TYPE_PARAMS_IMM | 0x42 | UOP_TYPE_ORDER_BARRIER) /*UOP_MEM_STORE_REG - src_reg_a:[src_reg_b] = src_reg_c*/ -#define UOP_MEM_STORE_REG (UOP_TYPE_PARAMS_REGS | 0x43 | UOP_TYPE_ORDER_BARRIER) +#define UOP_MEM_STORE_REG (UOP_TYPE_PARAMS_REGS | 0x43 | UOP_TYPE_ORDER_BARRIER) /*UOP_MEM_STORE_IMM_8 - byte src_reg_a:[src_reg_b] = imm_data*/ -#define UOP_MEM_STORE_IMM_8 (UOP_TYPE_PARAMS_REGS | UOP_TYPE_PARAMS_IMM | 0x44 | UOP_TYPE_ORDER_BARRIER) +#define UOP_MEM_STORE_IMM_8 (UOP_TYPE_PARAMS_REGS | UOP_TYPE_PARAMS_IMM | 0x44 | UOP_TYPE_ORDER_BARRIER) /*UOP_MEM_STORE_IMM_16 - word src_reg_a:[src_reg_b] = imm_data*/ -#define UOP_MEM_STORE_IMM_16 (UOP_TYPE_PARAMS_REGS | UOP_TYPE_PARAMS_IMM | 0x45 | UOP_TYPE_ORDER_BARRIER) +#define UOP_MEM_STORE_IMM_16 (UOP_TYPE_PARAMS_REGS | UOP_TYPE_PARAMS_IMM | 0x45 | UOP_TYPE_ORDER_BARRIER) /*UOP_MEM_STORE_IMM_32 - long src_reg_a:[src_reg_b] = imm_data*/ -#define UOP_MEM_STORE_IMM_32 (UOP_TYPE_PARAMS_REGS | UOP_TYPE_PARAMS_IMM | 0x46 | UOP_TYPE_ORDER_BARRIER) +#define UOP_MEM_STORE_IMM_32 (UOP_TYPE_PARAMS_REGS | UOP_TYPE_PARAMS_IMM | 0x46 | UOP_TYPE_ORDER_BARRIER) /*UOP_MEM_LOAD_SINGLE - dest_reg = (float)src_reg_a:[src_reg_b]*/ -#define UOP_MEM_LOAD_SINGLE (UOP_TYPE_PARAMS_REGS | UOP_TYPE_PARAMS_IMM | 0x47 | UOP_TYPE_ORDER_BARRIER) +#define UOP_MEM_LOAD_SINGLE (UOP_TYPE_PARAMS_REGS | UOP_TYPE_PARAMS_IMM | 0x47 | UOP_TYPE_ORDER_BARRIER) /*UOP_CMP_IMM_JZ - if (src_reg_a == imm_data) then jump to ptr*/ -#define UOP_CMP_IMM_JZ (UOP_TYPE_PARAMS_REGS | UOP_TYPE_PARAMS_IMM | UOP_TYPE_PARAMS_POINTER | 0x48 | UOP_TYPE_ORDER_BARRIER) +#define UOP_CMP_IMM_JZ (UOP_TYPE_PARAMS_REGS | UOP_TYPE_PARAMS_IMM | UOP_TYPE_PARAMS_POINTER | 0x48 | UOP_TYPE_ORDER_BARRIER) /*UOP_MEM_LOAD_DOUBLE - dest_reg = (double)src_reg_a:[src_reg_b]*/ -#define UOP_MEM_LOAD_DOUBLE (UOP_TYPE_PARAMS_REGS | UOP_TYPE_PARAMS_IMM | 0x49 | UOP_TYPE_ORDER_BARRIER) +#define UOP_MEM_LOAD_DOUBLE (UOP_TYPE_PARAMS_REGS | UOP_TYPE_PARAMS_IMM | 0x49 | UOP_TYPE_ORDER_BARRIER) /*UOP_MEM_STORE_SINGLE - src_reg_a:[src_reg_b] = src_reg_c*/ -#define UOP_MEM_STORE_SINGLE (UOP_TYPE_PARAMS_REGS | 0x4a | UOP_TYPE_ORDER_BARRIER) +#define UOP_MEM_STORE_SINGLE (UOP_TYPE_PARAMS_REGS | 0x4a | UOP_TYPE_ORDER_BARRIER) /*UOP_MEM_STORE_DOUBLE - src_reg_a:[src_reg_b] = src_reg_c*/ -#define UOP_MEM_STORE_DOUBLE (UOP_TYPE_PARAMS_REGS | 0x4b | UOP_TYPE_ORDER_BARRIER) +#define UOP_MEM_STORE_DOUBLE (UOP_TYPE_PARAMS_REGS | 0x4b | UOP_TYPE_ORDER_BARRIER) /*UOP_CMP_JB - if (src_reg_a < src_reg_b) then jump to ptr*/ -#define UOP_CMP_JB (UOP_TYPE_PARAMS_REGS | UOP_TYPE_PARAMS_POINTER | 0x4c | UOP_TYPE_ORDER_BARRIER) +#define UOP_CMP_JB (UOP_TYPE_PARAMS_REGS | UOP_TYPE_PARAMS_POINTER | 0x4c | UOP_TYPE_ORDER_BARRIER) /*UOP_CMP_JNBE - if (src_reg_a > src_reg_b) then jump to ptr*/ -#define UOP_CMP_JNBE (UOP_TYPE_PARAMS_REGS | UOP_TYPE_PARAMS_POINTER | 0x4d | UOP_TYPE_ORDER_BARRIER) +#define UOP_CMP_JNBE (UOP_TYPE_PARAMS_REGS | UOP_TYPE_PARAMS_POINTER | 0x4d | UOP_TYPE_ORDER_BARRIER) /*UOP_SAR - dest_reg = src_reg_a >> src_reg_b*/ -#define UOP_SAR (UOP_TYPE_PARAMS_REGS | 0x50) +#define UOP_SAR (UOP_TYPE_PARAMS_REGS | 0x50) /*UOP_SAR_IMM - dest_reg = src_reg_a >> immediate*/ -#define UOP_SAR_IMM (UOP_TYPE_PARAMS_REGS | UOP_TYPE_PARAMS_IMM | 0x51) +#define UOP_SAR_IMM (UOP_TYPE_PARAMS_REGS | UOP_TYPE_PARAMS_IMM | 0x51) /*UOP_SHL - dest_reg = src_reg_a << src_reg_b*/ -#define UOP_SHL (UOP_TYPE_PARAMS_REGS | 0x52) +#define UOP_SHL (UOP_TYPE_PARAMS_REGS | 0x52) /*UOP_SHL_IMM - dest_reg = src_reg_a << immediate*/ -#define UOP_SHL_IMM (UOP_TYPE_PARAMS_REGS | UOP_TYPE_PARAMS_IMM | 0x53) +#define UOP_SHL_IMM (UOP_TYPE_PARAMS_REGS | UOP_TYPE_PARAMS_IMM | 0x53) /*UOP_SHR - dest_reg = src_reg_a >> src_reg_b*/ -#define UOP_SHR (UOP_TYPE_PARAMS_REGS | 0x54) +#define UOP_SHR (UOP_TYPE_PARAMS_REGS | 0x54) /*UOP_SHR_IMM - dest_reg = src_reg_a >> immediate*/ -#define UOP_SHR_IMM (UOP_TYPE_PARAMS_REGS | UOP_TYPE_PARAMS_IMM | 0x55) +#define UOP_SHR_IMM (UOP_TYPE_PARAMS_REGS | UOP_TYPE_PARAMS_IMM | 0x55) /*UOP_ROL - dest_reg = src_reg_a rotate<< src_reg_b*/ -#define UOP_ROL (UOP_TYPE_PARAMS_REGS | 0x56) +#define UOP_ROL (UOP_TYPE_PARAMS_REGS | 0x56) /*UOP_ROL_IMM - dest_reg = src_reg_a rotate<< immediate*/ -#define UOP_ROL_IMM (UOP_TYPE_PARAMS_REGS | UOP_TYPE_PARAMS_IMM | 0x57) +#define UOP_ROL_IMM (UOP_TYPE_PARAMS_REGS | UOP_TYPE_PARAMS_IMM | 0x57) /*UOP_ROR - dest_reg = src_reg_a rotate>> src_reg_b*/ -#define UOP_ROR (UOP_TYPE_PARAMS_REGS | 0x58) +#define UOP_ROR (UOP_TYPE_PARAMS_REGS | 0x58) /*UOP_ROR_IMM - dest_reg = src_reg_a rotate>> immediate*/ -#define UOP_ROR_IMM (UOP_TYPE_PARAMS_REGS | UOP_TYPE_PARAMS_IMM | 0x59) +#define UOP_ROR_IMM (UOP_TYPE_PARAMS_REGS | UOP_TYPE_PARAMS_IMM | 0x59) /*UOP_CMP_IMM_JZ_DEST - if (src_reg_a == imm_data) then jump to ptr*/ -#define UOP_CMP_IMM_JZ_DEST (UOP_TYPE_PARAMS_REGS | UOP_TYPE_PARAMS_IMM | UOP_TYPE_PARAMS_POINTER | 0x60 | UOP_TYPE_ORDER_BARRIER | UOP_TYPE_JUMP) +#define UOP_CMP_IMM_JZ_DEST (UOP_TYPE_PARAMS_REGS | UOP_TYPE_PARAMS_IMM | UOP_TYPE_PARAMS_POINTER | 0x60 | UOP_TYPE_ORDER_BARRIER | UOP_TYPE_JUMP) /*UOP_CMP_IMM_JNZ_DEST - if (src_reg_a != imm_data) then jump to ptr*/ -#define UOP_CMP_IMM_JNZ_DEST (UOP_TYPE_PARAMS_REGS | UOP_TYPE_PARAMS_IMM | UOP_TYPE_PARAMS_POINTER | 0x61 | UOP_TYPE_ORDER_BARRIER | UOP_TYPE_JUMP) +#define UOP_CMP_IMM_JNZ_DEST (UOP_TYPE_PARAMS_REGS | UOP_TYPE_PARAMS_IMM | UOP_TYPE_PARAMS_POINTER | 0x61 | UOP_TYPE_ORDER_BARRIER | UOP_TYPE_JUMP) /*UOP_CMP_JB_DEST - if (src_reg_a < src_reg_b) then jump to ptr*/ -#define UOP_CMP_JB_DEST (UOP_TYPE_PARAMS_REGS | UOP_TYPE_PARAMS_IMM | UOP_TYPE_PARAMS_POINTER | 0x62 | UOP_TYPE_ORDER_BARRIER | UOP_TYPE_JUMP) +#define UOP_CMP_JB_DEST (UOP_TYPE_PARAMS_REGS | UOP_TYPE_PARAMS_IMM | UOP_TYPE_PARAMS_POINTER | 0x62 | UOP_TYPE_ORDER_BARRIER | UOP_TYPE_JUMP) /*UOP_CMP_JNB_DEST - if (src_reg_a >= src_reg_b) then jump to ptr*/ -#define UOP_CMP_JNB_DEST (UOP_TYPE_PARAMS_REGS | UOP_TYPE_PARAMS_IMM | UOP_TYPE_PARAMS_POINTER | 0x63 | UOP_TYPE_ORDER_BARRIER | UOP_TYPE_JUMP) +#define UOP_CMP_JNB_DEST (UOP_TYPE_PARAMS_REGS | UOP_TYPE_PARAMS_IMM | UOP_TYPE_PARAMS_POINTER | 0x63 | UOP_TYPE_ORDER_BARRIER | UOP_TYPE_JUMP) /*UOP_CMP_JO_DEST - if (src_reg_a < src_reg_b) then jump to ptr*/ -#define UOP_CMP_JO_DEST (UOP_TYPE_PARAMS_REGS | UOP_TYPE_PARAMS_IMM | UOP_TYPE_PARAMS_POINTER | 0x64 | UOP_TYPE_ORDER_BARRIER | UOP_TYPE_JUMP) +#define UOP_CMP_JO_DEST (UOP_TYPE_PARAMS_REGS | UOP_TYPE_PARAMS_IMM | UOP_TYPE_PARAMS_POINTER | 0x64 | UOP_TYPE_ORDER_BARRIER | UOP_TYPE_JUMP) /*UOP_CMP_JNO_DEST - if (src_reg_a >= src_reg_b) then jump to ptr*/ -#define UOP_CMP_JNO_DEST (UOP_TYPE_PARAMS_REGS | UOP_TYPE_PARAMS_IMM | UOP_TYPE_PARAMS_POINTER | 0x65 | UOP_TYPE_ORDER_BARRIER | UOP_TYPE_JUMP) +#define UOP_CMP_JNO_DEST (UOP_TYPE_PARAMS_REGS | UOP_TYPE_PARAMS_IMM | UOP_TYPE_PARAMS_POINTER | 0x65 | UOP_TYPE_ORDER_BARRIER | UOP_TYPE_JUMP) /*UOP_CMP_JZ_DEST - if (src_reg_a == src_reg_b) then jump to ptr*/ -#define UOP_CMP_JZ_DEST (UOP_TYPE_PARAMS_REGS | UOP_TYPE_PARAMS_IMM | UOP_TYPE_PARAMS_POINTER | 0x66 | UOP_TYPE_ORDER_BARRIER | UOP_TYPE_JUMP) +#define UOP_CMP_JZ_DEST (UOP_TYPE_PARAMS_REGS | UOP_TYPE_PARAMS_IMM | UOP_TYPE_PARAMS_POINTER | 0x66 | UOP_TYPE_ORDER_BARRIER | UOP_TYPE_JUMP) /*UOP_CMP_JNZ_DEST - if (src_reg_a != src_reg_b) then jump to ptr*/ -#define UOP_CMP_JNZ_DEST (UOP_TYPE_PARAMS_REGS | UOP_TYPE_PARAMS_IMM | UOP_TYPE_PARAMS_POINTER | 0x67 | UOP_TYPE_ORDER_BARRIER | UOP_TYPE_JUMP) +#define UOP_CMP_JNZ_DEST (UOP_TYPE_PARAMS_REGS | UOP_TYPE_PARAMS_IMM | UOP_TYPE_PARAMS_POINTER | 0x67 | UOP_TYPE_ORDER_BARRIER | UOP_TYPE_JUMP) /*UOP_CMP_JL_DEST - if (signed)(src_reg_a < src_reg_b) then jump to ptr*/ -#define UOP_CMP_JL_DEST (UOP_TYPE_PARAMS_REGS | UOP_TYPE_PARAMS_IMM | UOP_TYPE_PARAMS_POINTER | 0x68 | UOP_TYPE_ORDER_BARRIER | UOP_TYPE_JUMP) +#define UOP_CMP_JL_DEST (UOP_TYPE_PARAMS_REGS | UOP_TYPE_PARAMS_IMM | UOP_TYPE_PARAMS_POINTER | 0x68 | UOP_TYPE_ORDER_BARRIER | UOP_TYPE_JUMP) /*UOP_CMP_JNL_DEST - if (signed)(src_reg_a >= src_reg_b) then jump to ptr*/ -#define UOP_CMP_JNL_DEST (UOP_TYPE_PARAMS_REGS | UOP_TYPE_PARAMS_IMM | UOP_TYPE_PARAMS_POINTER | 0x69 | UOP_TYPE_ORDER_BARRIER | UOP_TYPE_JUMP) +#define UOP_CMP_JNL_DEST (UOP_TYPE_PARAMS_REGS | UOP_TYPE_PARAMS_IMM | UOP_TYPE_PARAMS_POINTER | 0x69 | UOP_TYPE_ORDER_BARRIER | UOP_TYPE_JUMP) /*UOP_CMP_JBE_DEST - if (src_reg_a <= src_reg_b) then jump to ptr*/ -#define UOP_CMP_JBE_DEST (UOP_TYPE_PARAMS_REGS | UOP_TYPE_PARAMS_IMM | UOP_TYPE_PARAMS_POINTER | 0x6a | UOP_TYPE_ORDER_BARRIER | UOP_TYPE_JUMP) +#define UOP_CMP_JBE_DEST (UOP_TYPE_PARAMS_REGS | UOP_TYPE_PARAMS_IMM | UOP_TYPE_PARAMS_POINTER | 0x6a | UOP_TYPE_ORDER_BARRIER | UOP_TYPE_JUMP) /*UOP_CMP_JNBE_DEST - if (src_reg_a > src_reg_b) then jump to ptr*/ -#define UOP_CMP_JNBE_DEST (UOP_TYPE_PARAMS_REGS | UOP_TYPE_PARAMS_IMM | UOP_TYPE_PARAMS_POINTER | 0x6b | UOP_TYPE_ORDER_BARRIER | UOP_TYPE_JUMP) +#define UOP_CMP_JNBE_DEST (UOP_TYPE_PARAMS_REGS | UOP_TYPE_PARAMS_IMM | UOP_TYPE_PARAMS_POINTER | 0x6b | UOP_TYPE_ORDER_BARRIER | UOP_TYPE_JUMP) /*UOP_CMP_JLE_DEST - if (signed)(src_reg_a <= src_reg_b) then jump to ptr*/ -#define UOP_CMP_JLE_DEST (UOP_TYPE_PARAMS_REGS | UOP_TYPE_PARAMS_IMM | UOP_TYPE_PARAMS_POINTER | 0x6c | UOP_TYPE_ORDER_BARRIER | UOP_TYPE_JUMP) +#define UOP_CMP_JLE_DEST (UOP_TYPE_PARAMS_REGS | UOP_TYPE_PARAMS_IMM | UOP_TYPE_PARAMS_POINTER | 0x6c | UOP_TYPE_ORDER_BARRIER | UOP_TYPE_JUMP) /*UOP_CMP_JNLE_DEST - if (signed)(src_reg_a > src_reg_b) then jump to ptr*/ -#define UOP_CMP_JNLE_DEST (UOP_TYPE_PARAMS_REGS | UOP_TYPE_PARAMS_IMM | UOP_TYPE_PARAMS_POINTER | 0x6d | UOP_TYPE_ORDER_BARRIER | UOP_TYPE_JUMP) - +#define UOP_CMP_JNLE_DEST (UOP_TYPE_PARAMS_REGS | UOP_TYPE_PARAMS_IMM | UOP_TYPE_PARAMS_POINTER | 0x6d | UOP_TYPE_ORDER_BARRIER | UOP_TYPE_JUMP) /*UOP_TEST_JNS_DEST - if (src_reg_a positive) then jump to ptr*/ -#define UOP_TEST_JNS_DEST (UOP_TYPE_PARAMS_REGS | UOP_TYPE_PARAMS_IMM | UOP_TYPE_PARAMS_POINTER | 0x70 | UOP_TYPE_ORDER_BARRIER | UOP_TYPE_JUMP) +#define UOP_TEST_JNS_DEST (UOP_TYPE_PARAMS_REGS | UOP_TYPE_PARAMS_IMM | UOP_TYPE_PARAMS_POINTER | 0x70 | UOP_TYPE_ORDER_BARRIER | UOP_TYPE_JUMP) /*UOP_TEST_JS_DEST - if (src_reg_a positive) then jump to ptr*/ -#define UOP_TEST_JS_DEST (UOP_TYPE_PARAMS_REGS | UOP_TYPE_PARAMS_IMM | UOP_TYPE_PARAMS_POINTER | 0x71 | UOP_TYPE_ORDER_BARRIER | UOP_TYPE_JUMP) +#define UOP_TEST_JS_DEST (UOP_TYPE_PARAMS_REGS | UOP_TYPE_PARAMS_IMM | UOP_TYPE_PARAMS_POINTER | 0x71 | UOP_TYPE_ORDER_BARRIER | UOP_TYPE_JUMP) /*UOP_FP_ENTER - must be called before any FPU register accessed*/ -#define UOP_FP_ENTER (UOP_TYPE_PARAMS_IMM | 0x80 | UOP_TYPE_BARRIER) +#define UOP_FP_ENTER (UOP_TYPE_PARAMS_IMM | 0x80 | UOP_TYPE_BARRIER) /*UOP_FADD - (floating point) dest_reg = src_reg_a + src_reg_b*/ -#define UOP_FADD (UOP_TYPE_PARAMS_REGS | 0x81) +#define UOP_FADD (UOP_TYPE_PARAMS_REGS | 0x81) /*UOP_FSUB - (floating point) dest_reg = src_reg_a - src_reg_b*/ -#define UOP_FSUB (UOP_TYPE_PARAMS_REGS | 0x82) +#define UOP_FSUB (UOP_TYPE_PARAMS_REGS | 0x82) /*UOP_FMUL - (floating point) dest_reg = src_reg_a * src_reg_b*/ -#define UOP_FMUL (UOP_TYPE_PARAMS_REGS | 0x83) +#define UOP_FMUL (UOP_TYPE_PARAMS_REGS | 0x83) /*UOP_FDIV - (floating point) dest_reg = src_reg_a / src_reg_b*/ -#define UOP_FDIV (UOP_TYPE_PARAMS_REGS | 0x84) +#define UOP_FDIV (UOP_TYPE_PARAMS_REGS | 0x84) /*UOP_FCOM - dest_reg = flags from compare(src_reg_a, src_reg_b)*/ -#define UOP_FCOM (UOP_TYPE_PARAMS_REGS | 0x85) +#define UOP_FCOM (UOP_TYPE_PARAMS_REGS | 0x85) /*UOP_FABS - dest_reg = fabs(src_reg_a)*/ -#define UOP_FABS (UOP_TYPE_PARAMS_REGS | 0x86) +#define UOP_FABS (UOP_TYPE_PARAMS_REGS | 0x86) /*UOP_FCHS - dest_reg = fabs(src_reg_a)*/ -#define UOP_FCHS (UOP_TYPE_PARAMS_REGS | 0x87) +#define UOP_FCHS (UOP_TYPE_PARAMS_REGS | 0x87) /*UOP_FTST - dest_reg = flags from compare(src_reg_a, 0)*/ -#define UOP_FTST (UOP_TYPE_PARAMS_REGS | 0x88) +#define UOP_FTST (UOP_TYPE_PARAMS_REGS | 0x88) /*UOP_FSQRT - dest_reg = fsqrt(src_reg_a)*/ -#define UOP_FSQRT (UOP_TYPE_PARAMS_REGS | 0x89) +#define UOP_FSQRT (UOP_TYPE_PARAMS_REGS | 0x89) /*UOP_MMX_ENTER - must be called before any MMX registers accessed*/ -#define UOP_MMX_ENTER (UOP_TYPE_PARAMS_IMM | 0x90 | UOP_TYPE_BARRIER) +#define UOP_MMX_ENTER (UOP_TYPE_PARAMS_IMM | 0x90 | UOP_TYPE_BARRIER) /*UOP_PADDB - (packed byte) dest_reg = src_reg_a + src_reg_b*/ -#define UOP_PADDB (UOP_TYPE_PARAMS_REGS | 0x91) +#define UOP_PADDB (UOP_TYPE_PARAMS_REGS | 0x91) /*UOP_PADDW - (packed word) dest_reg = src_reg_a + src_reg_b*/ -#define UOP_PADDW (UOP_TYPE_PARAMS_REGS | 0x92) +#define UOP_PADDW (UOP_TYPE_PARAMS_REGS | 0x92) /*UOP_PADDD - (packed long) dest_reg = src_reg_a + src_reg_b*/ -#define UOP_PADDD (UOP_TYPE_PARAMS_REGS | 0x93) +#define UOP_PADDD (UOP_TYPE_PARAMS_REGS | 0x93) /*UOP_PADDSB - (packed byte with signed saturation) dest_reg = src_reg_a + src_reg_b*/ -#define UOP_PADDSB (UOP_TYPE_PARAMS_REGS | 0x94) +#define UOP_PADDSB (UOP_TYPE_PARAMS_REGS | 0x94) /*UOP_PADDSW - (packed word with signed saturation) dest_reg = src_reg_a + src_reg_b*/ -#define UOP_PADDSW (UOP_TYPE_PARAMS_REGS | 0x95) +#define UOP_PADDSW (UOP_TYPE_PARAMS_REGS | 0x95) /*UOP_PADDUSB - (packed byte with unsigned saturation) dest_reg = src_reg_a + src_reg_b*/ -#define UOP_PADDUSB (UOP_TYPE_PARAMS_REGS | 0x96) +#define UOP_PADDUSB (UOP_TYPE_PARAMS_REGS | 0x96) /*UOP_PADDUSW - (packed word with unsigned saturation) dest_reg = src_reg_a + src_reg_b*/ -#define UOP_PADDUSW (UOP_TYPE_PARAMS_REGS | 0x97) +#define UOP_PADDUSW (UOP_TYPE_PARAMS_REGS | 0x97) /*UOP_PSUBB - (packed byte) dest_reg = src_reg_a - src_reg_b*/ -#define UOP_PSUBB (UOP_TYPE_PARAMS_REGS | 0x98) +#define UOP_PSUBB (UOP_TYPE_PARAMS_REGS | 0x98) /*UOP_PSUBW - (packed word) dest_reg = src_reg_a - src_reg_b*/ -#define UOP_PSUBW (UOP_TYPE_PARAMS_REGS | 0x99) +#define UOP_PSUBW (UOP_TYPE_PARAMS_REGS | 0x99) /*UOP_PSUBD - (packed long) dest_reg = src_reg_a - src_reg_b*/ -#define UOP_PSUBD (UOP_TYPE_PARAMS_REGS | 0x9a) +#define UOP_PSUBD (UOP_TYPE_PARAMS_REGS | 0x9a) /*UOP_PSUBSB - (packed byte with signed saturation) dest_reg = src_reg_a - src_reg_b*/ -#define UOP_PSUBSB (UOP_TYPE_PARAMS_REGS | 0x9b) +#define UOP_PSUBSB (UOP_TYPE_PARAMS_REGS | 0x9b) /*UOP_PSUBSW - (packed word with signed saturation) dest_reg = src_reg_a - src_reg_b*/ -#define UOP_PSUBSW (UOP_TYPE_PARAMS_REGS | 0x9c) +#define UOP_PSUBSW (UOP_TYPE_PARAMS_REGS | 0x9c) /*UOP_PSUBUSB - (packed byte with unsigned saturation) dest_reg = src_reg_a - src_reg_b*/ -#define UOP_PSUBUSB (UOP_TYPE_PARAMS_REGS | 0x9d) +#define UOP_PSUBUSB (UOP_TYPE_PARAMS_REGS | 0x9d) /*UOP_PSUBUSW - (packed word with unsigned saturation) dest_reg = src_reg_a - src_reg_b*/ -#define UOP_PSUBUSW (UOP_TYPE_PARAMS_REGS | 0x9e) +#define UOP_PSUBUSW (UOP_TYPE_PARAMS_REGS | 0x9e) /*UOP_PSLLW_IMM - (packed word) dest_reg = src_reg_a << immediate*/ -#define UOP_PSLLW_IMM (UOP_TYPE_PARAMS_REGS | 0x9f) +#define UOP_PSLLW_IMM (UOP_TYPE_PARAMS_REGS | 0x9f) /*UOP_PSLLD_IMM - (packed long) dest_reg = src_reg_a << immediate*/ -#define UOP_PSLLD_IMM (UOP_TYPE_PARAMS_REGS | 0xa0) +#define UOP_PSLLD_IMM (UOP_TYPE_PARAMS_REGS | 0xa0) /*UOP_PSLLQ_IMM - (packed quad) dest_reg = src_reg_a << immediate*/ -#define UOP_PSLLQ_IMM (UOP_TYPE_PARAMS_REGS | 0xa1) +#define UOP_PSLLQ_IMM (UOP_TYPE_PARAMS_REGS | 0xa1) /*UOP_PSRAW_IMM - (packed word) dest_reg = src_reg_a >> immediate*/ -#define UOP_PSRAW_IMM (UOP_TYPE_PARAMS_REGS | 0xa2) +#define UOP_PSRAW_IMM (UOP_TYPE_PARAMS_REGS | 0xa2) /*UOP_PSRAD_IMM - (packed long) dest_reg = src_reg_a >> immediate*/ -#define UOP_PSRAD_IMM (UOP_TYPE_PARAMS_REGS | 0xa3) +#define UOP_PSRAD_IMM (UOP_TYPE_PARAMS_REGS | 0xa3) /*UOP_PSRAQ_IMM - (packed quad) dest_reg = src_reg_a >> immediate*/ -#define UOP_PSRAQ_IMM (UOP_TYPE_PARAMS_REGS | 0xa4) +#define UOP_PSRAQ_IMM (UOP_TYPE_PARAMS_REGS | 0xa4) /*UOP_PSRLW_IMM - (packed word) dest_reg = src_reg_a >> immediate*/ -#define UOP_PSRLW_IMM (UOP_TYPE_PARAMS_REGS | 0xa5) +#define UOP_PSRLW_IMM (UOP_TYPE_PARAMS_REGS | 0xa5) /*UOP_PSRLD_IMM - (packed long) dest_reg = src_reg_a >> immediate*/ -#define UOP_PSRLD_IMM (UOP_TYPE_PARAMS_REGS | 0xa6) +#define UOP_PSRLD_IMM (UOP_TYPE_PARAMS_REGS | 0xa6) /*UOP_PSRLQ_IMM - (packed quad) dest_reg = src_reg_a >> immediate*/ -#define UOP_PSRLQ_IMM (UOP_TYPE_PARAMS_REGS | 0xa7) +#define UOP_PSRLQ_IMM (UOP_TYPE_PARAMS_REGS | 0xa7) /*UOP_PCMPEQB - (packed byte) dest_reg = (src_reg_a == src_reg_b) ? ~0 : 0*/ -#define UOP_PCMPEQB (UOP_TYPE_PARAMS_REGS | 0xa8) +#define UOP_PCMPEQB (UOP_TYPE_PARAMS_REGS | 0xa8) /*UOP_PCMPEQW - (packed word) dest_reg = (src_reg_a == src_reg_b) ? ~0 : 0*/ -#define UOP_PCMPEQW (UOP_TYPE_PARAMS_REGS | 0xa9) +#define UOP_PCMPEQW (UOP_TYPE_PARAMS_REGS | 0xa9) /*UOP_PCMPEQD - (packed long) dest_reg = (src_reg_a == src_reg_b) ? ~0 : 0*/ -#define UOP_PCMPEQD (UOP_TYPE_PARAMS_REGS | 0xaa) +#define UOP_PCMPEQD (UOP_TYPE_PARAMS_REGS | 0xaa) /*UOP_PCMPGTB - (packed signed byte) dest_reg = (src_reg_a > src_reg_b) ? ~0 : 0*/ -#define UOP_PCMPGTB (UOP_TYPE_PARAMS_REGS | 0xab) +#define UOP_PCMPGTB (UOP_TYPE_PARAMS_REGS | 0xab) /*UOP_PCMPGTW - (packed signed word) dest_reg = (src_reg_a > src_reg_b) ? ~0 : 0*/ -#define UOP_PCMPGTW (UOP_TYPE_PARAMS_REGS | 0xac) +#define UOP_PCMPGTW (UOP_TYPE_PARAMS_REGS | 0xac) /*UOP_PCMPGTD - (packed signed long) dest_reg = (src_reg_a > src_reg_b) ? ~0 : 0*/ -#define UOP_PCMPGTD (UOP_TYPE_PARAMS_REGS | 0xad) +#define UOP_PCMPGTD (UOP_TYPE_PARAMS_REGS | 0xad) /*UOP_PUNPCKLBW - (packed byte) dest_reg = interleave low src_reg_a/src_reg_b*/ -#define UOP_PUNPCKLBW (UOP_TYPE_PARAMS_REGS | 0xae) +#define UOP_PUNPCKLBW (UOP_TYPE_PARAMS_REGS | 0xae) /*UOP_PUNPCKLWD - (packed word) dest_reg = interleave low src_reg_a/src_reg_b*/ -#define UOP_PUNPCKLWD (UOP_TYPE_PARAMS_REGS | 0xaf) +#define UOP_PUNPCKLWD (UOP_TYPE_PARAMS_REGS | 0xaf) /*UOP_PUNPCKLDQ - (packed long) dest_reg = interleave low src_reg_a/src_reg_b*/ -#define UOP_PUNPCKLDQ (UOP_TYPE_PARAMS_REGS | 0xb0) +#define UOP_PUNPCKLDQ (UOP_TYPE_PARAMS_REGS | 0xb0) /*UOP_PUNPCKHBW - (packed byte) dest_reg = interleave high src_reg_a/src_reg_b*/ -#define UOP_PUNPCKHBW (UOP_TYPE_PARAMS_REGS | 0xb1) +#define UOP_PUNPCKHBW (UOP_TYPE_PARAMS_REGS | 0xb1) /*UOP_PUNPCKHWD - (packed word) dest_reg = interleave high src_reg_a/src_reg_b*/ -#define UOP_PUNPCKHWD (UOP_TYPE_PARAMS_REGS | 0xb2) +#define UOP_PUNPCKHWD (UOP_TYPE_PARAMS_REGS | 0xb2) /*UOP_PUNPCKHDQ - (packed long) dest_reg = interleave high src_reg_a/src_reg_b*/ -#define UOP_PUNPCKHDQ (UOP_TYPE_PARAMS_REGS | 0xb3) +#define UOP_PUNPCKHDQ (UOP_TYPE_PARAMS_REGS | 0xb3) /*UOP_PACKSSWB - dest_reg = interleave src_reg_a/src_reg_b, converting words to bytes with signed saturation*/ -#define UOP_PACKSSWB (UOP_TYPE_PARAMS_REGS | 0xb4) +#define UOP_PACKSSWB (UOP_TYPE_PARAMS_REGS | 0xb4) /*UOP_PACKSSDW - dest_reg = interleave src_reg_a/src_reg_b, converting longs to words with signed saturation*/ -#define UOP_PACKSSDW (UOP_TYPE_PARAMS_REGS | 0xb5) +#define UOP_PACKSSDW (UOP_TYPE_PARAMS_REGS | 0xb5) /*UOP_PACKUSWB - dest_reg = interleave src_reg_a/src_reg_b, converting words to bytes with unsigned saturation*/ -#define UOP_PACKUSWB (UOP_TYPE_PARAMS_REGS | 0xb6) +#define UOP_PACKUSWB (UOP_TYPE_PARAMS_REGS | 0xb6) /*UOP_PMULLW - (packed word) dest_reg = (src_reg_a * src_reg_b) & 0xffff*/ -#define UOP_PMULLW (UOP_TYPE_PARAMS_REGS | 0xb7) +#define UOP_PMULLW (UOP_TYPE_PARAMS_REGS | 0xb7) /*UOP_PMULHW - (packed word) dest_reg = (src_reg_a * src_reg_b) >> 16*/ -#define UOP_PMULHW (UOP_TYPE_PARAMS_REGS | 0xb8) +#define UOP_PMULHW (UOP_TYPE_PARAMS_REGS | 0xb8) /*UOP_PMADDWD - (packed word) dest_reg = (src_reg_a * src_reg_b) >> 16*/ -#define UOP_PMADDWD (UOP_TYPE_PARAMS_REGS | 0xb9) +#define UOP_PMADDWD (UOP_TYPE_PARAMS_REGS | 0xb9) /*UOP_PFADD - (packed float) dest_reg = src_reg_a + src_reg_b*/ -#define UOP_PFADD (UOP_TYPE_PARAMS_REGS | 0xba) +#define UOP_PFADD (UOP_TYPE_PARAMS_REGS | 0xba) /*UOP_PFSUB - (packed float) dest_reg = src_reg_a - src_reg_b*/ -#define UOP_PFSUB (UOP_TYPE_PARAMS_REGS | 0xbb) +#define UOP_PFSUB (UOP_TYPE_PARAMS_REGS | 0xbb) /*UOP_PFMUL - (packed float) dest_reg = src_reg_a * src_reg_b*/ -#define UOP_PFMUL (UOP_TYPE_PARAMS_REGS | 0xbc) +#define UOP_PFMUL (UOP_TYPE_PARAMS_REGS | 0xbc) /*UOP_PFMAX - (packed float) dest_reg = MAX(src_reg_a, src_reg_b)*/ -#define UOP_PFMAX (UOP_TYPE_PARAMS_REGS | 0xbd) +#define UOP_PFMAX (UOP_TYPE_PARAMS_REGS | 0xbd) /*UOP_PFMIN - (packed float) dest_reg = MIN(src_reg_a, src_reg_b)*/ -#define UOP_PFMIN (UOP_TYPE_PARAMS_REGS | 0xbe) +#define UOP_PFMIN (UOP_TYPE_PARAMS_REGS | 0xbe) /*UOP_PFCMPEQ - (packed float) dest_reg = (src_reg_a == src_reg_b) ? ~0 : 0*/ -#define UOP_PFCMPEQ (UOP_TYPE_PARAMS_REGS | 0xbf) +#define UOP_PFCMPEQ (UOP_TYPE_PARAMS_REGS | 0xbf) /*UOP_PFCMPGE - (packed float) dest_reg = (src_reg_a >= src_reg_b) ? ~0 : 0*/ -#define UOP_PFCMPGE (UOP_TYPE_PARAMS_REGS | 0xc0) +#define UOP_PFCMPGE (UOP_TYPE_PARAMS_REGS | 0xc0) /*UOP_PFCMPGT - (packed float) dest_reg = (src_reg_a > src_reg_b) ? ~0 : 0*/ -#define UOP_PFCMPGT (UOP_TYPE_PARAMS_REGS | 0xc1) +#define UOP_PFCMPGT (UOP_TYPE_PARAMS_REGS | 0xc1) /*UOP_PF2ID - (packed long)dest_reg = (packed float)src_reg_a*/ -#define UOP_PF2ID (UOP_TYPE_PARAMS_REGS | 0xc2) +#define UOP_PF2ID (UOP_TYPE_PARAMS_REGS | 0xc2) /*UOP_PI2FD - (packed float)dest_reg = (packed long)src_reg_a*/ -#define UOP_PI2FD (UOP_TYPE_PARAMS_REGS | 0xc3) +#define UOP_PI2FD (UOP_TYPE_PARAMS_REGS | 0xc3) /*UOP_PFRCP - (packed float) dest_reg[0] = dest_reg[1] = 1.0 / src_reg[0]*/ -#define UOP_PFRCP (UOP_TYPE_PARAMS_REGS | 0xc4) +#define UOP_PFRCP (UOP_TYPE_PARAMS_REGS | 0xc4) /*UOP_PFRSQRT - (packed float) dest_reg[0] = dest_reg[1] = 1.0 / sqrt(src_reg[0])*/ -#define UOP_PFRSQRT (UOP_TYPE_PARAMS_REGS | 0xc5) +#define UOP_PFRSQRT (UOP_TYPE_PARAMS_REGS | 0xc5) -#define UOP_MAX 0xc6 +#define UOP_MAX 0xc6 #define UOP_INVALID 0xff -#define UOP_MASK 0xffff +#define UOP_MASK 0xffff -typedef struct uop_t -{ - uint32_t type; - ir_reg_t dest_reg_a; - ir_reg_t src_reg_a; - ir_reg_t src_reg_b; - ir_reg_t src_reg_c; - uint32_t imm_data; - void *p; - ir_host_reg_t dest_reg_a_real; - ir_host_reg_t src_reg_a_real, src_reg_b_real, src_reg_c_real; - int jump_dest_uop; - int jump_list_next; - void *jump_dest; - uint32_t pc; +typedef struct uop_t { + uint32_t type; + ir_reg_t dest_reg_a; + ir_reg_t src_reg_a; + ir_reg_t src_reg_b; + ir_reg_t src_reg_c; + uint32_t imm_data; + void *p; + ir_host_reg_t dest_reg_a_real; + ir_host_reg_t src_reg_a_real, src_reg_b_real, src_reg_c_real; + int jump_dest_uop; + int jump_list_next; + void *jump_dest; + uint32_t pc; } uop_t; #define UOP_NR_MAX 4096 -typedef struct ir_data_t -{ - uop_t uops[UOP_NR_MAX]; - int wr_pos; - struct codeblock_t *block; +typedef struct ir_data_t { + uop_t uops[UOP_NR_MAX]; + int wr_pos; + struct codeblock_t *block; } ir_data_t; -static inline uop_t *uop_alloc(ir_data_t *ir, uint32_t uop_type) +static inline uop_t * +uop_alloc(ir_data_t *ir, uint32_t uop_type) { - uop_t *uop; - - if (ir->wr_pos >= UOP_NR_MAX) - fatal("Exceeded uOP max\n"); - - uop = &ir->uops[ir->wr_pos++]; - - uop->dest_reg_a = invalid_ir_reg; - uop->src_reg_a = invalid_ir_reg; - uop->src_reg_b = invalid_ir_reg; - uop->src_reg_c = invalid_ir_reg; - - uop->pc = cpu_state.oldpc; - - uop->jump_dest_uop = -1; - uop->jump_list_next = -1; + uop_t *uop; - if (uop_type & (UOP_TYPE_BARRIER | UOP_TYPE_ORDER_BARRIER)) - codegen_reg_mark_as_required(); + if (ir->wr_pos >= UOP_NR_MAX) + fatal("Exceeded uOP max\n"); - return uop; + uop = &ir->uops[ir->wr_pos++]; + + uop->dest_reg_a = invalid_ir_reg; + uop->src_reg_a = invalid_ir_reg; + uop->src_reg_b = invalid_ir_reg; + uop->src_reg_c = invalid_ir_reg; + + uop->pc = cpu_state.oldpc; + + uop->jump_dest_uop = -1; + uop->jump_list_next = -1; + + if (uop_type & (UOP_TYPE_BARRIER | UOP_TYPE_ORDER_BARRIER)) + codegen_reg_mark_as_required(); + + return uop; } -static inline void uop_set_jump_dest(ir_data_t *ir, int jump_uop) +static inline void +uop_set_jump_dest(ir_data_t *ir, int jump_uop) { - uop_t *uop = &ir->uops[jump_uop]; - - uop->jump_dest_uop = ir->wr_pos; + uop_t *uop = &ir->uops[jump_uop]; + + uop->jump_dest_uop = ir->wr_pos; } -static inline int uop_gen(uint32_t uop_type, ir_data_t *ir) +static inline int +uop_gen(uint32_t uop_type, ir_data_t *ir) { - uop_t *uop = uop_alloc(ir, uop_type); + uop_t *uop = uop_alloc(ir, uop_type); - uop->type = uop_type; + uop->type = uop_type; - return ir->wr_pos-1; + return ir->wr_pos - 1; } -static inline int uop_gen_reg_src1(uint32_t uop_type, ir_data_t *ir, int src_reg_a) +static inline int +uop_gen_reg_src1(uint32_t uop_type, ir_data_t *ir, int src_reg_a) { - uop_t *uop = uop_alloc(ir, uop_type); - - uop->type = uop_type; - uop->src_reg_a = codegen_reg_read(src_reg_a); + uop_t *uop = uop_alloc(ir, uop_type); - return ir->wr_pos-1; + uop->type = uop_type; + uop->src_reg_a = codegen_reg_read(src_reg_a); + + return ir->wr_pos - 1; } -static inline void uop_gen_reg_src1_arg(uint32_t uop_type, ir_data_t *ir, int arg, int src_reg_a) +static inline void +uop_gen_reg_src1_arg(uint32_t uop_type, ir_data_t *ir, int arg, int src_reg_a) { - uop_t *uop = uop_alloc(ir, uop_type); + uop_t *uop = uop_alloc(ir, uop_type); - uop->type = uop_type; - uop->src_reg_a = codegen_reg_read(src_reg_a); + uop->type = uop_type; + uop->src_reg_a = codegen_reg_read(src_reg_a); } -static inline int uop_gen_reg_src1_imm(uint32_t uop_type, ir_data_t *ir, int src_reg, uint32_t imm) +static inline int +uop_gen_reg_src1_imm(uint32_t uop_type, ir_data_t *ir, int src_reg, uint32_t imm) { - uop_t *uop = uop_alloc(ir, uop_type); + uop_t *uop = uop_alloc(ir, uop_type); - uop->type = uop_type; - uop->src_reg_a = codegen_reg_read(src_reg); - uop->imm_data = imm; - - return ir->wr_pos-1; + uop->type = uop_type; + uop->src_reg_a = codegen_reg_read(src_reg); + uop->imm_data = imm; + + return ir->wr_pos - 1; } -static inline void uop_gen_reg_dst_imm(uint32_t uop_type, ir_data_t *ir, int dest_reg, uint32_t imm) +static inline void +uop_gen_reg_dst_imm(uint32_t uop_type, ir_data_t *ir, int dest_reg, uint32_t imm) { - uop_t *uop = uop_alloc(ir, uop_type); + uop_t *uop = uop_alloc(ir, uop_type); - uop->type = uop_type; - uop->dest_reg_a = codegen_reg_write(dest_reg, ir->wr_pos - 1); - uop->imm_data = imm; + uop->type = uop_type; + uop->dest_reg_a = codegen_reg_write(dest_reg, ir->wr_pos - 1); + uop->imm_data = imm; } -static inline void uop_gen_reg_dst_pointer(uint32_t uop_type, ir_data_t *ir, int dest_reg, void *p) +static inline void +uop_gen_reg_dst_pointer(uint32_t uop_type, ir_data_t *ir, int dest_reg, void *p) { - uop_t *uop = uop_alloc(ir, uop_type); + uop_t *uop = uop_alloc(ir, uop_type); - uop->type = uop_type; - uop->dest_reg_a = codegen_reg_write(dest_reg, ir->wr_pos - 1); - uop->p = p; + uop->type = uop_type; + uop->dest_reg_a = codegen_reg_write(dest_reg, ir->wr_pos - 1); + uop->p = p; } -static inline void uop_gen_reg_dst_src1(uint32_t uop_type, ir_data_t *ir, int dest_reg, int src_reg) +static inline void +uop_gen_reg_dst_src1(uint32_t uop_type, ir_data_t *ir, int dest_reg, int src_reg) { - uop_t *uop = uop_alloc(ir, uop_type); + uop_t *uop = uop_alloc(ir, uop_type); - uop->type = uop_type; - uop->src_reg_a = codegen_reg_read(src_reg); - uop->dest_reg_a = codegen_reg_write(dest_reg, ir->wr_pos - 1); + uop->type = uop_type; + uop->src_reg_a = codegen_reg_read(src_reg); + uop->dest_reg_a = codegen_reg_write(dest_reg, ir->wr_pos - 1); } -static inline void uop_gen_reg_dst_src1_imm(uint32_t uop_type, ir_data_t *ir, int dest_reg, int src_reg_a, uint32_t imm) +static inline void +uop_gen_reg_dst_src1_imm(uint32_t uop_type, ir_data_t *ir, int dest_reg, int src_reg_a, uint32_t imm) { - uop_t *uop = uop_alloc(ir, uop_type); + uop_t *uop = uop_alloc(ir, uop_type); - uop->type = uop_type; - uop->src_reg_a = codegen_reg_read(src_reg_a); - uop->dest_reg_a = codegen_reg_write(dest_reg, ir->wr_pos - 1); - uop->imm_data = imm; + uop->type = uop_type; + uop->src_reg_a = codegen_reg_read(src_reg_a); + uop->dest_reg_a = codegen_reg_write(dest_reg, ir->wr_pos - 1); + uop->imm_data = imm; } -static inline void uop_gen_reg_dst_src2(uint32_t uop_type, ir_data_t *ir, int dest_reg, int src_reg_a, int src_reg_b) +static inline void +uop_gen_reg_dst_src2(uint32_t uop_type, ir_data_t *ir, int dest_reg, int src_reg_a, int src_reg_b) { - uop_t *uop = uop_alloc(ir, uop_type); + uop_t *uop = uop_alloc(ir, uop_type); - uop->type = uop_type; - uop->src_reg_a = codegen_reg_read(src_reg_a); - uop->src_reg_b = codegen_reg_read(src_reg_b); - uop->dest_reg_a = codegen_reg_write(dest_reg, ir->wr_pos - 1); + uop->type = uop_type; + uop->src_reg_a = codegen_reg_read(src_reg_a); + uop->src_reg_b = codegen_reg_read(src_reg_b); + uop->dest_reg_a = codegen_reg_write(dest_reg, ir->wr_pos - 1); } -static inline void uop_gen_reg_dst_src2_imm(uint32_t uop_type, ir_data_t *ir, int dest_reg, int src_reg_a, int src_reg_b, uint32_t imm) +static inline void +uop_gen_reg_dst_src2_imm(uint32_t uop_type, ir_data_t *ir, int dest_reg, int src_reg_a, int src_reg_b, uint32_t imm) { - uop_t *uop = uop_alloc(ir, uop_type); + uop_t *uop = uop_alloc(ir, uop_type); - uop->type = uop_type; - uop->src_reg_a = codegen_reg_read(src_reg_a); - uop->src_reg_b = codegen_reg_read(src_reg_b); - uop->dest_reg_a = codegen_reg_write(dest_reg, ir->wr_pos - 1); - uop->imm_data = imm; + uop->type = uop_type; + uop->src_reg_a = codegen_reg_read(src_reg_a); + uop->src_reg_b = codegen_reg_read(src_reg_b); + uop->dest_reg_a = codegen_reg_write(dest_reg, ir->wr_pos - 1); + uop->imm_data = imm; } -static inline void uop_gen_reg_dst_src3(uint32_t uop_type, ir_data_t *ir, int dest_reg, int src_reg_a, int src_reg_b, int src_reg_c) +static inline void +uop_gen_reg_dst_src3(uint32_t uop_type, ir_data_t *ir, int dest_reg, int src_reg_a, int src_reg_b, int src_reg_c) { - uop_t *uop = uop_alloc(ir, uop_type); + uop_t *uop = uop_alloc(ir, uop_type); - uop->type = uop_type; - uop->src_reg_a = codegen_reg_read(src_reg_a); - uop->src_reg_b = codegen_reg_read(src_reg_b); - uop->src_reg_c = codegen_reg_read(src_reg_c); - uop->dest_reg_a = codegen_reg_write(dest_reg, ir->wr_pos - 1); + uop->type = uop_type; + uop->src_reg_a = codegen_reg_read(src_reg_a); + uop->src_reg_b = codegen_reg_read(src_reg_b); + uop->src_reg_c = codegen_reg_read(src_reg_c); + uop->dest_reg_a = codegen_reg_write(dest_reg, ir->wr_pos - 1); } -static inline void uop_gen_reg_dst_src_imm(uint32_t uop_type, ir_data_t *ir, int dest_reg, int src_reg, uint32_t imm) +static inline void +uop_gen_reg_dst_src_imm(uint32_t uop_type, ir_data_t *ir, int dest_reg, int src_reg, uint32_t imm) { - uop_t *uop = uop_alloc(ir, uop_type); + uop_t *uop = uop_alloc(ir, uop_type); - uop->type = uop_type; - uop->src_reg_a = codegen_reg_read(src_reg); - uop->dest_reg_a = codegen_reg_write(dest_reg, ir->wr_pos - 1); - uop->imm_data = imm; + uop->type = uop_type; + uop->src_reg_a = codegen_reg_read(src_reg); + uop->dest_reg_a = codegen_reg_write(dest_reg, ir->wr_pos - 1); + uop->imm_data = imm; } -static inline int uop_gen_reg_src2(uint32_t uop_type, ir_data_t *ir, int src_reg_a, int src_reg_b) +static inline int +uop_gen_reg_src2(uint32_t uop_type, ir_data_t *ir, int src_reg_a, int src_reg_b) { - uop_t *uop = uop_alloc(ir, uop_type); + uop_t *uop = uop_alloc(ir, uop_type); - uop->type = uop_type; - uop->src_reg_a = codegen_reg_read(src_reg_a); - uop->src_reg_b = codegen_reg_read(src_reg_b); - - return ir->wr_pos-1; + uop->type = uop_type; + uop->src_reg_a = codegen_reg_read(src_reg_a); + uop->src_reg_b = codegen_reg_read(src_reg_b); + + return ir->wr_pos - 1; } -static inline void uop_gen_reg_src2_imm(uint32_t uop_type, ir_data_t *ir, int src_reg_a, int src_reg_b, uint32_t imm) +static inline void +uop_gen_reg_src2_imm(uint32_t uop_type, ir_data_t *ir, int src_reg_a, int src_reg_b, uint32_t imm) { - uop_t *uop = uop_alloc(ir, uop_type); + uop_t *uop = uop_alloc(ir, uop_type); - uop->type = uop_type; - uop->src_reg_a = codegen_reg_read(src_reg_a); - uop->src_reg_b = codegen_reg_read(src_reg_b); - uop->imm_data = imm; + uop->type = uop_type; + uop->src_reg_a = codegen_reg_read(src_reg_a); + uop->src_reg_b = codegen_reg_read(src_reg_b); + uop->imm_data = imm; } -static inline void uop_gen_reg_src3(uint32_t uop_type, ir_data_t *ir, int src_reg_a, int src_reg_b, int src_reg_c) +static inline void +uop_gen_reg_src3(uint32_t uop_type, ir_data_t *ir, int src_reg_a, int src_reg_b, int src_reg_c) { - uop_t *uop = uop_alloc(ir, uop_type); + uop_t *uop = uop_alloc(ir, uop_type); - uop->type = uop_type; - uop->src_reg_a = codegen_reg_read(src_reg_a); - uop->src_reg_b = codegen_reg_read(src_reg_b); - uop->src_reg_c = codegen_reg_read(src_reg_c); + uop->type = uop_type; + uop->src_reg_a = codegen_reg_read(src_reg_a); + uop->src_reg_b = codegen_reg_read(src_reg_b); + uop->src_reg_c = codegen_reg_read(src_reg_c); } -static inline void uop_gen_reg_src3_imm(uint32_t uop_type, ir_data_t *ir, int src_reg_a, int src_reg_b, int src_reg_c, uint32_t imm) +static inline void +uop_gen_reg_src3_imm(uint32_t uop_type, ir_data_t *ir, int src_reg_a, int src_reg_b, int src_reg_c, uint32_t imm) { - uop_t *uop = uop_alloc(ir, uop_type); + uop_t *uop = uop_alloc(ir, uop_type); - uop->type = uop_type; - uop->src_reg_a = codegen_reg_read(src_reg_a); - uop->src_reg_b = codegen_reg_read(src_reg_b); - uop->src_reg_c = codegen_reg_read(src_reg_c); - uop->imm_data = imm; + uop->type = uop_type; + uop->src_reg_a = codegen_reg_read(src_reg_a); + uop->src_reg_b = codegen_reg_read(src_reg_b); + uop->src_reg_c = codegen_reg_read(src_reg_c); + uop->imm_data = imm; } -static inline void uop_gen_imm(uint32_t uop_type, ir_data_t *ir, uint32_t imm) +static inline void +uop_gen_imm(uint32_t uop_type, ir_data_t *ir, uint32_t imm) { - uop_t *uop = uop_alloc(ir, uop_type); - - uop->type = uop_type; - uop->imm_data = imm; + uop_t *uop = uop_alloc(ir, uop_type); + + uop->type = uop_type; + uop->imm_data = imm; } -static inline void uop_gen_pointer(uint32_t uop_type, ir_data_t *ir, void *p) +static inline void +uop_gen_pointer(uint32_t uop_type, ir_data_t *ir, void *p) { - uop_t *uop = uop_alloc(ir, uop_type); - - uop->type = uop_type; - uop->p = p; + uop_t *uop = uop_alloc(ir, uop_type); + + uop->type = uop_type; + uop->p = p; } -static inline void uop_gen_pointer_imm(uint32_t uop_type, ir_data_t *ir, void *p, uint32_t imm) +static inline void +uop_gen_pointer_imm(uint32_t uop_type, ir_data_t *ir, void *p, uint32_t imm) { - uop_t *uop = uop_alloc(ir, uop_type); - - uop->type = uop_type; - uop->p = p; - uop->imm_data = imm; + uop_t *uop = uop_alloc(ir, uop_type); + + uop->type = uop_type; + uop->p = p; + uop->imm_data = imm; } -static inline void uop_gen_reg_src_pointer(uint32_t uop_type, ir_data_t *ir, int src_reg_a, void *p) +static inline void +uop_gen_reg_src_pointer(uint32_t uop_type, ir_data_t *ir, int src_reg_a, void *p) { - uop_t *uop = uop_alloc(ir, uop_type); + uop_t *uop = uop_alloc(ir, uop_type); - uop->type = uop_type; - uop->src_reg_a = codegen_reg_read(src_reg_a); - uop->p = p; + uop->type = uop_type; + uop->src_reg_a = codegen_reg_read(src_reg_a); + uop->p = p; } -static inline void uop_gen_reg_src_pointer_imm(uint32_t uop_type, ir_data_t *ir, int src_reg_a, void *p, uint32_t imm) +static inline void +uop_gen_reg_src_pointer_imm(uint32_t uop_type, ir_data_t *ir, int src_reg_a, void *p, uint32_t imm) { - uop_t *uop = uop_alloc(ir, uop_type); + uop_t *uop = uop_alloc(ir, uop_type); - uop->type = uop_type; - uop->src_reg_a = codegen_reg_read(src_reg_a); - uop->p = p; - uop->imm_data = imm; + uop->type = uop_type; + uop->src_reg_a = codegen_reg_read(src_reg_a); + uop->p = p; + uop->imm_data = imm; } -static inline void uop_gen_reg_src2_pointer(uint32_t uop_type, ir_data_t *ir, int src_reg_a, int src_reg_b, void *p) +static inline void +uop_gen_reg_src2_pointer(uint32_t uop_type, ir_data_t *ir, int src_reg_a, int src_reg_b, void *p) { - uop_t *uop = uop_alloc(ir, uop_type); + uop_t *uop = uop_alloc(ir, uop_type); - uop->type = uop_type; - uop->src_reg_a = codegen_reg_read(src_reg_a); - uop->src_reg_b = codegen_reg_read(src_reg_b); - uop->p = p; + uop->type = uop_type; + uop->src_reg_a = codegen_reg_read(src_reg_a); + uop->src_reg_b = codegen_reg_read(src_reg_b); + uop->p = p; } -#define uop_LOAD_FUNC_ARG_REG(ir, arg, reg) uop_gen_reg_src1(UOP_LOAD_FUNC_ARG_0 + arg, ir, reg) +#define uop_LOAD_FUNC_ARG_REG(ir, arg, reg) uop_gen_reg_src1(UOP_LOAD_FUNC_ARG_0 + arg, ir, reg) -#define uop_LOAD_FUNC_ARG_IMM(ir, arg, imm) uop_gen_imm(UOP_LOAD_FUNC_ARG_0_IMM + arg, ir, imm) +#define uop_LOAD_FUNC_ARG_IMM(ir, arg, imm) uop_gen_imm(UOP_LOAD_FUNC_ARG_0_IMM + arg, ir, imm) -#define uop_ADD(ir, dst_reg, src_reg_a, src_reg_b) uop_gen_reg_dst_src2(UOP_ADD, ir, dst_reg, src_reg_a, src_reg_b) -#define uop_ADD_IMM(ir, dst_reg, src_reg, imm) uop_gen_reg_dst_src_imm(UOP_ADD_IMM, ir, dst_reg, src_reg, imm) +#define uop_ADD(ir, dst_reg, src_reg_a, src_reg_b) uop_gen_reg_dst_src2(UOP_ADD, ir, dst_reg, src_reg_a, src_reg_b) +#define uop_ADD_IMM(ir, dst_reg, src_reg, imm) uop_gen_reg_dst_src_imm(UOP_ADD_IMM, ir, dst_reg, src_reg, imm) #define uop_ADD_LSHIFT(ir, dst_reg, src_reg_a, src_reg_b, shift) uop_gen_reg_dst_src2_imm(UOP_ADD_LSHIFT, ir, dst_reg, src_reg_a, src_reg_b, shift) -#define uop_AND(ir, dst_reg, src_reg_a, src_reg_b) uop_gen_reg_dst_src2(UOP_AND, ir, dst_reg, src_reg_a, src_reg_b) -#define uop_AND_IMM(ir, dst_reg, src_reg, imm) uop_gen_reg_dst_src_imm(UOP_AND_IMM, ir, dst_reg, src_reg, imm) -#define uop_ANDN(ir, dst_reg, src_reg_a, src_reg_b) uop_gen_reg_dst_src2(UOP_ANDN, ir, dst_reg, src_reg_a, src_reg_b) -#define uop_OR(ir, dst_reg, src_reg_a, src_reg_b) uop_gen_reg_dst_src2(UOP_OR, ir, dst_reg, src_reg_a, src_reg_b) -#define uop_OR_IMM(ir, dst_reg, src_reg, imm) uop_gen_reg_dst_src_imm(UOP_OR_IMM, ir, dst_reg, src_reg, imm) -#define uop_SUB(ir, dst_reg, src_reg_a, src_reg_b) uop_gen_reg_dst_src2(UOP_SUB, ir, dst_reg, src_reg_a, src_reg_b) -#define uop_SUB_IMM(ir, dst_reg, src_reg, imm) uop_gen_reg_dst_src_imm(UOP_SUB_IMM, ir, dst_reg, src_reg, imm) -#define uop_XOR(ir, dst_reg, src_reg_a, src_reg_b) uop_gen_reg_dst_src2(UOP_XOR, ir, dst_reg, src_reg_a, src_reg_b) -#define uop_XOR_IMM(ir, dst_reg, src_reg, imm) uop_gen_reg_dst_src_imm(UOP_XOR_IMM, ir, dst_reg, src_reg, imm) +#define uop_AND(ir, dst_reg, src_reg_a, src_reg_b) uop_gen_reg_dst_src2(UOP_AND, ir, dst_reg, src_reg_a, src_reg_b) +#define uop_AND_IMM(ir, dst_reg, src_reg, imm) uop_gen_reg_dst_src_imm(UOP_AND_IMM, ir, dst_reg, src_reg, imm) +#define uop_ANDN(ir, dst_reg, src_reg_a, src_reg_b) uop_gen_reg_dst_src2(UOP_ANDN, ir, dst_reg, src_reg_a, src_reg_b) +#define uop_OR(ir, dst_reg, src_reg_a, src_reg_b) uop_gen_reg_dst_src2(UOP_OR, ir, dst_reg, src_reg_a, src_reg_b) +#define uop_OR_IMM(ir, dst_reg, src_reg, imm) uop_gen_reg_dst_src_imm(UOP_OR_IMM, ir, dst_reg, src_reg, imm) +#define uop_SUB(ir, dst_reg, src_reg_a, src_reg_b) uop_gen_reg_dst_src2(UOP_SUB, ir, dst_reg, src_reg_a, src_reg_b) +#define uop_SUB_IMM(ir, dst_reg, src_reg, imm) uop_gen_reg_dst_src_imm(UOP_SUB_IMM, ir, dst_reg, src_reg, imm) +#define uop_XOR(ir, dst_reg, src_reg_a, src_reg_b) uop_gen_reg_dst_src2(UOP_XOR, ir, dst_reg, src_reg_a, src_reg_b) +#define uop_XOR_IMM(ir, dst_reg, src_reg, imm) uop_gen_reg_dst_src_imm(UOP_XOR_IMM, ir, dst_reg, src_reg, imm) -#define uop_SAR(ir, dst_reg, src_reg, shift_reg) uop_gen_reg_dst_src2(UOP_SAR, ir, dst_reg, src_reg, shift_reg) -#define uop_SAR_IMM(ir, dst_reg, src_reg, imm) uop_gen_reg_dst_src_imm(UOP_SAR_IMM, ir, dst_reg, src_reg, imm) -#define uop_SHL(ir, dst_reg, src_reg, shift_reg) uop_gen_reg_dst_src2(UOP_SHL, ir, dst_reg, src_reg, shift_reg) -#define uop_SHL_IMM(ir, dst_reg, src_reg, imm) uop_gen_reg_dst_src_imm(UOP_SHL_IMM, ir, dst_reg, src_reg, imm) -#define uop_SHR(ir, dst_reg, src_reg, shift_reg) uop_gen_reg_dst_src2(UOP_SHR, ir, dst_reg, src_reg, shift_reg) -#define uop_SHR_IMM(ir, dst_reg, src_reg, imm) uop_gen_reg_dst_src_imm(UOP_SHR_IMM, ir, dst_reg, src_reg, imm) -#define uop_ROL(ir, dst_reg, src_reg, shift_reg) uop_gen_reg_dst_src2(UOP_ROL, ir, dst_reg, src_reg, shift_reg) -#define uop_ROL_IMM(ir, dst_reg, src_reg, imm) uop_gen_reg_dst_src_imm(UOP_ROL_IMM, ir, dst_reg, src_reg, imm) -#define uop_ROR(ir, dst_reg, src_reg, shift_reg) uop_gen_reg_dst_src2(UOP_ROR, ir, dst_reg, src_reg, shift_reg) -#define uop_ROR_IMM(ir, dst_reg, src_reg, imm) uop_gen_reg_dst_src_imm(UOP_ROR_IMM, ir, dst_reg, src_reg, imm) +#define uop_SAR(ir, dst_reg, src_reg, shift_reg) uop_gen_reg_dst_src2(UOP_SAR, ir, dst_reg, src_reg, shift_reg) +#define uop_SAR_IMM(ir, dst_reg, src_reg, imm) uop_gen_reg_dst_src_imm(UOP_SAR_IMM, ir, dst_reg, src_reg, imm) +#define uop_SHL(ir, dst_reg, src_reg, shift_reg) uop_gen_reg_dst_src2(UOP_SHL, ir, dst_reg, src_reg, shift_reg) +#define uop_SHL_IMM(ir, dst_reg, src_reg, imm) uop_gen_reg_dst_src_imm(UOP_SHL_IMM, ir, dst_reg, src_reg, imm) +#define uop_SHR(ir, dst_reg, src_reg, shift_reg) uop_gen_reg_dst_src2(UOP_SHR, ir, dst_reg, src_reg, shift_reg) +#define uop_SHR_IMM(ir, dst_reg, src_reg, imm) uop_gen_reg_dst_src_imm(UOP_SHR_IMM, ir, dst_reg, src_reg, imm) +#define uop_ROL(ir, dst_reg, src_reg, shift_reg) uop_gen_reg_dst_src2(UOP_ROL, ir, dst_reg, src_reg, shift_reg) +#define uop_ROL_IMM(ir, dst_reg, src_reg, imm) uop_gen_reg_dst_src_imm(UOP_ROL_IMM, ir, dst_reg, src_reg, imm) +#define uop_ROR(ir, dst_reg, src_reg, shift_reg) uop_gen_reg_dst_src2(UOP_ROR, ir, dst_reg, src_reg, shift_reg) +#define uop_ROR_IMM(ir, dst_reg, src_reg, imm) uop_gen_reg_dst_src_imm(UOP_ROR_IMM, ir, dst_reg, src_reg, imm) -#define uop_CALL_FUNC(ir, p) uop_gen_pointer(UOP_CALL_FUNC, ir, p) -#define uop_CALL_FUNC_RESULT(ir, dst_reg, p) uop_gen_reg_dst_pointer(UOP_CALL_FUNC_RESULT, ir, dst_reg, p) -#define uop_CALL_INSTRUCTION_FUNC(ir, p) uop_gen_pointer(UOP_CALL_INSTRUCTION_FUNC, ir, p) +#define uop_CALL_FUNC(ir, p) uop_gen_pointer(UOP_CALL_FUNC, ir, p) +#define uop_CALL_FUNC_RESULT(ir, dst_reg, p) uop_gen_reg_dst_pointer(UOP_CALL_FUNC_RESULT, ir, dst_reg, p) +#define uop_CALL_INSTRUCTION_FUNC(ir, p) uop_gen_pointer(UOP_CALL_INSTRUCTION_FUNC, ir, p) -#define uop_CMP_IMM_JZ(ir, src_reg, imm, p) uop_gen_reg_src_pointer_imm(UOP_CMP_IMM_JZ, ir, src_reg, p, imm) +#define uop_CMP_IMM_JZ(ir, src_reg, imm, p) uop_gen_reg_src_pointer_imm(UOP_CMP_IMM_JZ, ir, src_reg, p, imm) -#define uop_CMP_IMM_JNZ_DEST(ir, src_reg, imm) uop_gen_reg_src1_imm(UOP_CMP_IMM_JNZ_DEST, ir, src_reg, imm) -#define uop_CMP_IMM_JZ_DEST(ir, src_reg, imm) uop_gen_reg_src1_imm(UOP_CMP_IMM_JZ_DEST, ir, src_reg, imm) +#define uop_CMP_IMM_JNZ_DEST(ir, src_reg, imm) uop_gen_reg_src1_imm(UOP_CMP_IMM_JNZ_DEST, ir, src_reg, imm) +#define uop_CMP_IMM_JZ_DEST(ir, src_reg, imm) uop_gen_reg_src1_imm(UOP_CMP_IMM_JZ_DEST, ir, src_reg, imm) -#define uop_CMP_JB(ir, src_reg_a, src_reg_b, p) uop_gen_reg_src2_pointer(UOP_CMP_JB, ir, src_reg_a, src_reg_b, p) -#define uop_CMP_JNBE(ir, src_reg_a, src_reg_b, p) uop_gen_reg_src2_pointer(UOP_CMP_JNBE, ir, src_reg_a, src_reg_b, p) +#define uop_CMP_JB(ir, src_reg_a, src_reg_b, p) uop_gen_reg_src2_pointer(UOP_CMP_JB, ir, src_reg_a, src_reg_b, p) +#define uop_CMP_JNBE(ir, src_reg_a, src_reg_b, p) uop_gen_reg_src2_pointer(UOP_CMP_JNBE, ir, src_reg_a, src_reg_b, p) -#define uop_CMP_JNB_DEST(ir, src_reg_a, src_reg_b) uop_gen_reg_src2(UOP_CMP_JNB_DEST, ir, src_reg_a, src_reg_b) -#define uop_CMP_JNBE_DEST(ir, src_reg_a, src_reg_b) uop_gen_reg_src2(UOP_CMP_JNBE_DEST, ir, src_reg_a, src_reg_b) -#define uop_CMP_JNL_DEST(ir, src_reg_a, src_reg_b) uop_gen_reg_src2(UOP_CMP_JNL_DEST, ir, src_reg_a, src_reg_b) -#define uop_CMP_JNLE_DEST(ir, src_reg_a, src_reg_b) uop_gen_reg_src2(UOP_CMP_JNLE_DEST, ir, src_reg_a, src_reg_b) -#define uop_CMP_JNO_DEST(ir, src_reg_a, src_reg_b) uop_gen_reg_src2(UOP_CMP_JNO_DEST, ir, src_reg_a, src_reg_b) -#define uop_CMP_JNZ_DEST(ir, src_reg_a, src_reg_b) uop_gen_reg_src2(UOP_CMP_JNZ_DEST, ir, src_reg_a, src_reg_b) -#define uop_CMP_JB_DEST(ir, src_reg_a, src_reg_b) uop_gen_reg_src2(UOP_CMP_JB_DEST, ir, src_reg_a, src_reg_b) -#define uop_CMP_JBE_DEST(ir, src_reg_a, src_reg_b) uop_gen_reg_src2(UOP_CMP_JBE_DEST, ir, src_reg_a, src_reg_b) -#define uop_CMP_JL_DEST(ir, src_reg_a, src_reg_b) uop_gen_reg_src2(UOP_CMP_JL_DEST, ir, src_reg_a, src_reg_b) -#define uop_CMP_JLE_DEST(ir, src_reg_a, src_reg_b) uop_gen_reg_src2(UOP_CMP_JLE_DEST, ir, src_reg_a, src_reg_b) -#define uop_CMP_JO_DEST(ir, src_reg_a, src_reg_b) uop_gen_reg_src2(UOP_CMP_JO_DEST, ir, src_reg_a, src_reg_b) -#define uop_CMP_JZ_DEST(ir, src_reg_a, src_reg_b) uop_gen_reg_src2(UOP_CMP_JZ_DEST, ir, src_reg_a, src_reg_b) +#define uop_CMP_JNB_DEST(ir, src_reg_a, src_reg_b) uop_gen_reg_src2(UOP_CMP_JNB_DEST, ir, src_reg_a, src_reg_b) +#define uop_CMP_JNBE_DEST(ir, src_reg_a, src_reg_b) uop_gen_reg_src2(UOP_CMP_JNBE_DEST, ir, src_reg_a, src_reg_b) +#define uop_CMP_JNL_DEST(ir, src_reg_a, src_reg_b) uop_gen_reg_src2(UOP_CMP_JNL_DEST, ir, src_reg_a, src_reg_b) +#define uop_CMP_JNLE_DEST(ir, src_reg_a, src_reg_b) uop_gen_reg_src2(UOP_CMP_JNLE_DEST, ir, src_reg_a, src_reg_b) +#define uop_CMP_JNO_DEST(ir, src_reg_a, src_reg_b) uop_gen_reg_src2(UOP_CMP_JNO_DEST, ir, src_reg_a, src_reg_b) +#define uop_CMP_JNZ_DEST(ir, src_reg_a, src_reg_b) uop_gen_reg_src2(UOP_CMP_JNZ_DEST, ir, src_reg_a, src_reg_b) +#define uop_CMP_JB_DEST(ir, src_reg_a, src_reg_b) uop_gen_reg_src2(UOP_CMP_JB_DEST, ir, src_reg_a, src_reg_b) +#define uop_CMP_JBE_DEST(ir, src_reg_a, src_reg_b) uop_gen_reg_src2(UOP_CMP_JBE_DEST, ir, src_reg_a, src_reg_b) +#define uop_CMP_JL_DEST(ir, src_reg_a, src_reg_b) uop_gen_reg_src2(UOP_CMP_JL_DEST, ir, src_reg_a, src_reg_b) +#define uop_CMP_JLE_DEST(ir, src_reg_a, src_reg_b) uop_gen_reg_src2(UOP_CMP_JLE_DEST, ir, src_reg_a, src_reg_b) +#define uop_CMP_JO_DEST(ir, src_reg_a, src_reg_b) uop_gen_reg_src2(UOP_CMP_JO_DEST, ir, src_reg_a, src_reg_b) +#define uop_CMP_JZ_DEST(ir, src_reg_a, src_reg_b) uop_gen_reg_src2(UOP_CMP_JZ_DEST, ir, src_reg_a, src_reg_b) -#define uop_FADD(ir, dst_reg, src_reg_a, src_reg_b) uop_gen_reg_dst_src2(UOP_FADD, ir, dst_reg, src_reg_a, src_reg_b) -#define uop_FCOM(ir, dst_reg, src_reg_a, src_reg_b) uop_gen_reg_dst_src2(UOP_FCOM, ir, dst_reg, src_reg_a, src_reg_b) -#define uop_FDIV(ir, dst_reg, src_reg_a, src_reg_b) uop_gen_reg_dst_src2(UOP_FDIV, ir, dst_reg, src_reg_a, src_reg_b) -#define uop_FMUL(ir, dst_reg, src_reg_a, src_reg_b) uop_gen_reg_dst_src2(UOP_FMUL, ir, dst_reg, src_reg_a, src_reg_b) -#define uop_FSUB(ir, dst_reg, src_reg_a, src_reg_b) uop_gen_reg_dst_src2(UOP_FSUB, ir, dst_reg, src_reg_a, src_reg_b) +#define uop_FADD(ir, dst_reg, src_reg_a, src_reg_b) uop_gen_reg_dst_src2(UOP_FADD, ir, dst_reg, src_reg_a, src_reg_b) +#define uop_FCOM(ir, dst_reg, src_reg_a, src_reg_b) uop_gen_reg_dst_src2(UOP_FCOM, ir, dst_reg, src_reg_a, src_reg_b) +#define uop_FDIV(ir, dst_reg, src_reg_a, src_reg_b) uop_gen_reg_dst_src2(UOP_FDIV, ir, dst_reg, src_reg_a, src_reg_b) +#define uop_FMUL(ir, dst_reg, src_reg_a, src_reg_b) uop_gen_reg_dst_src2(UOP_FMUL, ir, dst_reg, src_reg_a, src_reg_b) +#define uop_FSUB(ir, dst_reg, src_reg_a, src_reg_b) uop_gen_reg_dst_src2(UOP_FSUB, ir, dst_reg, src_reg_a, src_reg_b) -#define uop_FABS(ir, dst_reg, src_reg) uop_gen_reg_dst_src1(UOP_FABS, ir, dst_reg, src_reg) -#define uop_FCHS(ir, dst_reg, src_reg) uop_gen_reg_dst_src1(UOP_FCHS, ir, dst_reg, src_reg) -#define uop_FSQRT(ir, dst_reg, src_reg) uop_gen_reg_dst_src1(UOP_FSQRT, ir, dst_reg, src_reg) -#define uop_FTST(ir, dst_reg, src_reg) uop_gen_reg_dst_src1(UOP_FTST, ir, dst_reg, src_reg) +#define uop_FABS(ir, dst_reg, src_reg) uop_gen_reg_dst_src1(UOP_FABS, ir, dst_reg, src_reg) +#define uop_FCHS(ir, dst_reg, src_reg) uop_gen_reg_dst_src1(UOP_FCHS, ir, dst_reg, src_reg) +#define uop_FSQRT(ir, dst_reg, src_reg) uop_gen_reg_dst_src1(UOP_FSQRT, ir, dst_reg, src_reg) +#define uop_FTST(ir, dst_reg, src_reg) uop_gen_reg_dst_src1(UOP_FTST, ir, dst_reg, src_reg) -#define uop_FP_ENTER(ir) do { if (!codegen_fpu_entered) uop_gen_imm(UOP_FP_ENTER, ir, cpu_state.oldpc); codegen_fpu_entered = 1; codegen_mmx_entered = 0; } while (0) -#define uop_MMX_ENTER(ir) do { if (!codegen_mmx_entered) uop_gen_imm(UOP_MMX_ENTER, ir, cpu_state.oldpc); codegen_mmx_entered = 1; codegen_fpu_entered = 0; } while (0) +#define uop_FP_ENTER(ir) \ + do { \ + if (!codegen_fpu_entered) \ + uop_gen_imm(UOP_FP_ENTER, ir, cpu_state.oldpc); \ + codegen_fpu_entered = 1; \ + codegen_mmx_entered = 0; \ + } while (0) +#define uop_MMX_ENTER(ir) \ + do { \ + if (!codegen_mmx_entered) \ + uop_gen_imm(UOP_MMX_ENTER, ir, cpu_state.oldpc); \ + codegen_mmx_entered = 1; \ + codegen_fpu_entered = 0; \ + } while (0) -#define uop_JMP(ir, p) uop_gen_pointer(UOP_JMP, ir, p) -#define uop_JMP_DEST(ir) uop_gen(UOP_JMP_DEST, ir) +#define uop_JMP(ir, p) uop_gen_pointer(UOP_JMP, ir, p) +#define uop_JMP_DEST(ir) uop_gen(UOP_JMP_DEST, ir) -#define uop_LOAD_SEG(ir, p, src_reg) uop_gen_reg_src_pointer(UOP_LOAD_SEG, ir, src_reg, p) +#define uop_LOAD_SEG(ir, p, src_reg) uop_gen_reg_src_pointer(UOP_LOAD_SEG, ir, src_reg, p) -#define uop_MEM_LOAD_ABS(ir, dst_reg, seg_reg, imm) uop_gen_reg_dst_src_imm(UOP_MEM_LOAD_ABS, ir, dst_reg, seg_reg, imm) -#define uop_MEM_LOAD_REG(ir, dst_reg, seg_reg, addr_reg) uop_gen_reg_dst_src2_imm(UOP_MEM_LOAD_REG, ir, dst_reg, seg_reg, addr_reg, 0) -#define uop_MEM_LOAD_REG_OFFSET(ir, dst_reg, seg_reg, addr_reg, offset) uop_gen_reg_dst_src2_imm(UOP_MEM_LOAD_REG, ir, dst_reg, seg_reg, addr_reg, offset) -#define uop_MEM_LOAD_SINGLE(ir, dst_reg, seg_reg, addr_reg) uop_gen_reg_dst_src2_imm(UOP_MEM_LOAD_SINGLE, ir, dst_reg, seg_reg, addr_reg, 0) -#define uop_MEM_LOAD_DOUBLE(ir, dst_reg, seg_reg, addr_reg) uop_gen_reg_dst_src2_imm(UOP_MEM_LOAD_DOUBLE, ir, dst_reg, seg_reg, addr_reg, 0) -#define uop_MEM_STORE_ABS(ir, seg_reg, imm, src_reg) uop_gen_reg_src2_imm(UOP_MEM_STORE_ABS, ir, seg_reg, src_reg, imm) -#define uop_MEM_STORE_REG(ir, seg_reg, addr_reg, src_reg) uop_gen_reg_src3_imm(UOP_MEM_STORE_REG, ir, seg_reg, addr_reg, src_reg, 0) +#define uop_MEM_LOAD_ABS(ir, dst_reg, seg_reg, imm) uop_gen_reg_dst_src_imm(UOP_MEM_LOAD_ABS, ir, dst_reg, seg_reg, imm) +#define uop_MEM_LOAD_REG(ir, dst_reg, seg_reg, addr_reg) uop_gen_reg_dst_src2_imm(UOP_MEM_LOAD_REG, ir, dst_reg, seg_reg, addr_reg, 0) +#define uop_MEM_LOAD_REG_OFFSET(ir, dst_reg, seg_reg, addr_reg, offset) uop_gen_reg_dst_src2_imm(UOP_MEM_LOAD_REG, ir, dst_reg, seg_reg, addr_reg, offset) +#define uop_MEM_LOAD_SINGLE(ir, dst_reg, seg_reg, addr_reg) uop_gen_reg_dst_src2_imm(UOP_MEM_LOAD_SINGLE, ir, dst_reg, seg_reg, addr_reg, 0) +#define uop_MEM_LOAD_DOUBLE(ir, dst_reg, seg_reg, addr_reg) uop_gen_reg_dst_src2_imm(UOP_MEM_LOAD_DOUBLE, ir, dst_reg, seg_reg, addr_reg, 0) +#define uop_MEM_STORE_ABS(ir, seg_reg, imm, src_reg) uop_gen_reg_src2_imm(UOP_MEM_STORE_ABS, ir, seg_reg, src_reg, imm) +#define uop_MEM_STORE_REG(ir, seg_reg, addr_reg, src_reg) uop_gen_reg_src3_imm(UOP_MEM_STORE_REG, ir, seg_reg, addr_reg, src_reg, 0) #define uop_MEM_STORE_REG_OFFSET(ir, seg_reg, addr_reg, offset, src_reg) uop_gen_reg_src3_imm(UOP_MEM_STORE_REG, ir, seg_reg, addr_reg, src_reg, offset) -#define uop_MEM_STORE_IMM_8(ir, seg_reg, addr_reg, imm) uop_gen_reg_src2_imm(UOP_MEM_STORE_IMM_8, ir, seg_reg, addr_reg, imm) -#define uop_MEM_STORE_IMM_16(ir, seg_reg, addr_reg, imm) uop_gen_reg_src2_imm(UOP_MEM_STORE_IMM_16, ir, seg_reg, addr_reg, imm) -#define uop_MEM_STORE_IMM_32(ir, seg_reg, addr_reg, imm) uop_gen_reg_src2_imm(UOP_MEM_STORE_IMM_32, ir, seg_reg, addr_reg, imm) -#define uop_MEM_STORE_SINGLE(ir, seg_reg, addr_reg, src_reg) uop_gen_reg_src3_imm(UOP_MEM_STORE_SINGLE, ir, seg_reg, addr_reg, src_reg, 0) -#define uop_MEM_STORE_DOUBLE(ir, seg_reg, addr_reg, src_reg) uop_gen_reg_src3_imm(UOP_MEM_STORE_DOUBLE, ir, seg_reg, addr_reg, src_reg, 0) +#define uop_MEM_STORE_IMM_8(ir, seg_reg, addr_reg, imm) uop_gen_reg_src2_imm(UOP_MEM_STORE_IMM_8, ir, seg_reg, addr_reg, imm) +#define uop_MEM_STORE_IMM_16(ir, seg_reg, addr_reg, imm) uop_gen_reg_src2_imm(UOP_MEM_STORE_IMM_16, ir, seg_reg, addr_reg, imm) +#define uop_MEM_STORE_IMM_32(ir, seg_reg, addr_reg, imm) uop_gen_reg_src2_imm(UOP_MEM_STORE_IMM_32, ir, seg_reg, addr_reg, imm) +#define uop_MEM_STORE_SINGLE(ir, seg_reg, addr_reg, src_reg) uop_gen_reg_src3_imm(UOP_MEM_STORE_SINGLE, ir, seg_reg, addr_reg, src_reg, 0) +#define uop_MEM_STORE_DOUBLE(ir, seg_reg, addr_reg, src_reg) uop_gen_reg_src3_imm(UOP_MEM_STORE_DOUBLE, ir, seg_reg, addr_reg, src_reg, 0) -#define uop_MOV(ir, dst_reg, src_reg) uop_gen_reg_dst_src1(UOP_MOV, ir, dst_reg, src_reg) -#define uop_MOV_IMM(ir, reg, imm) uop_gen_reg_dst_imm(UOP_MOV_IMM, ir, reg, imm) -#define uop_MOV_PTR(ir, reg, p) uop_gen_reg_dst_pointer(UOP_MOV_PTR, ir, reg, p) -#define uop_MOV_REG_PTR(ir, reg, p) uop_gen_reg_dst_pointer(UOP_MOV_REG_PTR, ir, reg, p) -#define uop_MOVZX_REG_PTR_8(ir, reg, p) uop_gen_reg_dst_pointer(UOP_MOVZX_REG_PTR_8, ir, reg, p) -#define uop_MOVZX_REG_PTR_16(ir, reg, p) uop_gen_reg_dst_pointer(UOP_MOVZX_REG_PTR_16, ir, reg, p) -#define uop_MOVSX(ir, dst_reg, src_reg) uop_gen_reg_dst_src1(UOP_MOVSX, ir, dst_reg, src_reg) -#define uop_MOVZX(ir, dst_reg, src_reg) uop_gen_reg_dst_src1(UOP_MOVZX, ir, dst_reg, src_reg) -#define uop_MOV_DOUBLE_INT(ir, dst_reg, src_reg) uop_gen_reg_dst_src1(UOP_MOV_DOUBLE_INT, ir, dst_reg, src_reg) -#define uop_MOV_INT_DOUBLE(ir, dst_reg, src_reg/*, nrc, orc*/) uop_gen_reg_dst_src1(UOP_MOV_INT_DOUBLE, ir, dst_reg, src_reg/*, nrc, orc*/) -#define uop_MOV_INT_DOUBLE_64(ir, dst_reg, src_reg_d, src_reg_q, tag) uop_gen_reg_dst_src3(UOP_MOV_INT_DOUBLE_64, ir, dst_reg, src_reg_d, src_reg_q, tag) +#define uop_MOV(ir, dst_reg, src_reg) uop_gen_reg_dst_src1(UOP_MOV, ir, dst_reg, src_reg) +#define uop_MOV_IMM(ir, reg, imm) uop_gen_reg_dst_imm(UOP_MOV_IMM, ir, reg, imm) +#define uop_MOV_PTR(ir, reg, p) uop_gen_reg_dst_pointer(UOP_MOV_PTR, ir, reg, p) +#define uop_MOV_REG_PTR(ir, reg, p) uop_gen_reg_dst_pointer(UOP_MOV_REG_PTR, ir, reg, p) +#define uop_MOVZX_REG_PTR_8(ir, reg, p) uop_gen_reg_dst_pointer(UOP_MOVZX_REG_PTR_8, ir, reg, p) +#define uop_MOVZX_REG_PTR_16(ir, reg, p) uop_gen_reg_dst_pointer(UOP_MOVZX_REG_PTR_16, ir, reg, p) +#define uop_MOVSX(ir, dst_reg, src_reg) uop_gen_reg_dst_src1(UOP_MOVSX, ir, dst_reg, src_reg) +#define uop_MOVZX(ir, dst_reg, src_reg) uop_gen_reg_dst_src1(UOP_MOVZX, ir, dst_reg, src_reg) +#define uop_MOV_DOUBLE_INT(ir, dst_reg, src_reg) uop_gen_reg_dst_src1(UOP_MOV_DOUBLE_INT, ir, dst_reg, src_reg) +#define uop_MOV_INT_DOUBLE(ir, dst_reg, src_reg /*, nrc, orc*/) uop_gen_reg_dst_src1(UOP_MOV_INT_DOUBLE, ir, dst_reg, src_reg /*, nrc, orc*/) +#define uop_MOV_INT_DOUBLE_64(ir, dst_reg, src_reg_d, src_reg_q, tag) uop_gen_reg_dst_src3(UOP_MOV_INT_DOUBLE_64, ir, dst_reg, src_reg_d, src_reg_q, tag) -#define uop_NOP_BARRIER(ir) uop_gen(UOP_NOP_BARRIER, ir) +#define uop_NOP_BARRIER(ir) uop_gen(UOP_NOP_BARRIER, ir) -#define uop_PACKSSWB(ir, dst_reg, src_reg_a, src_reg_b) uop_gen_reg_dst_src2(UOP_PACKSSWB, ir, dst_reg, src_reg_a, src_reg_b) -#define uop_PACKSSDW(ir, dst_reg, src_reg_a, src_reg_b) uop_gen_reg_dst_src2(UOP_PACKSSDW, ir, dst_reg, src_reg_a, src_reg_b) -#define uop_PACKUSWB(ir, dst_reg, src_reg_a, src_reg_b) uop_gen_reg_dst_src2(UOP_PACKUSWB, ir, dst_reg, src_reg_a, src_reg_b) +#define uop_PACKSSWB(ir, dst_reg, src_reg_a, src_reg_b) uop_gen_reg_dst_src2(UOP_PACKSSWB, ir, dst_reg, src_reg_a, src_reg_b) +#define uop_PACKSSDW(ir, dst_reg, src_reg_a, src_reg_b) uop_gen_reg_dst_src2(UOP_PACKSSDW, ir, dst_reg, src_reg_a, src_reg_b) +#define uop_PACKUSWB(ir, dst_reg, src_reg_a, src_reg_b) uop_gen_reg_dst_src2(UOP_PACKUSWB, ir, dst_reg, src_reg_a, src_reg_b) -#define uop_PADDB(ir, dst_reg, src_reg_a, src_reg_b) uop_gen_reg_dst_src2(UOP_PADDB, ir, dst_reg, src_reg_a, src_reg_b) -#define uop_PADDW(ir, dst_reg, src_reg_a, src_reg_b) uop_gen_reg_dst_src2(UOP_PADDW, ir, dst_reg, src_reg_a, src_reg_b) -#define uop_PADDD(ir, dst_reg, src_reg_a, src_reg_b) uop_gen_reg_dst_src2(UOP_PADDD, ir, dst_reg, src_reg_a, src_reg_b) -#define uop_PADDSB(ir, dst_reg, src_reg_a, src_reg_b) uop_gen_reg_dst_src2(UOP_PADDSB, ir, dst_reg, src_reg_a, src_reg_b) -#define uop_PADDSW(ir, dst_reg, src_reg_a, src_reg_b) uop_gen_reg_dst_src2(UOP_PADDSW, ir, dst_reg, src_reg_a, src_reg_b) -#define uop_PADDUSB(ir, dst_reg, src_reg_a, src_reg_b) uop_gen_reg_dst_src2(UOP_PADDUSB, ir, dst_reg, src_reg_a, src_reg_b) -#define uop_PADDUSW(ir, dst_reg, src_reg_a, src_reg_b) uop_gen_reg_dst_src2(UOP_PADDUSW, ir, dst_reg, src_reg_a, src_reg_b) +#define uop_PADDB(ir, dst_reg, src_reg_a, src_reg_b) uop_gen_reg_dst_src2(UOP_PADDB, ir, dst_reg, src_reg_a, src_reg_b) +#define uop_PADDW(ir, dst_reg, src_reg_a, src_reg_b) uop_gen_reg_dst_src2(UOP_PADDW, ir, dst_reg, src_reg_a, src_reg_b) +#define uop_PADDD(ir, dst_reg, src_reg_a, src_reg_b) uop_gen_reg_dst_src2(UOP_PADDD, ir, dst_reg, src_reg_a, src_reg_b) +#define uop_PADDSB(ir, dst_reg, src_reg_a, src_reg_b) uop_gen_reg_dst_src2(UOP_PADDSB, ir, dst_reg, src_reg_a, src_reg_b) +#define uop_PADDSW(ir, dst_reg, src_reg_a, src_reg_b) uop_gen_reg_dst_src2(UOP_PADDSW, ir, dst_reg, src_reg_a, src_reg_b) +#define uop_PADDUSB(ir, dst_reg, src_reg_a, src_reg_b) uop_gen_reg_dst_src2(UOP_PADDUSB, ir, dst_reg, src_reg_a, src_reg_b) +#define uop_PADDUSW(ir, dst_reg, src_reg_a, src_reg_b) uop_gen_reg_dst_src2(UOP_PADDUSW, ir, dst_reg, src_reg_a, src_reg_b) -#define uop_PCMPEQB(ir, dst_reg, src_reg_a, src_reg_b) uop_gen_reg_dst_src2(UOP_PCMPEQB, ir, dst_reg, src_reg_a, src_reg_b) -#define uop_PCMPEQW(ir, dst_reg, src_reg_a, src_reg_b) uop_gen_reg_dst_src2(UOP_PCMPEQW, ir, dst_reg, src_reg_a, src_reg_b) -#define uop_PCMPEQD(ir, dst_reg, src_reg_a, src_reg_b) uop_gen_reg_dst_src2(UOP_PCMPEQD, ir, dst_reg, src_reg_a, src_reg_b) -#define uop_PCMPGTB(ir, dst_reg, src_reg_a, src_reg_b) uop_gen_reg_dst_src2(UOP_PCMPGTB, ir, dst_reg, src_reg_a, src_reg_b) -#define uop_PCMPGTW(ir, dst_reg, src_reg_a, src_reg_b) uop_gen_reg_dst_src2(UOP_PCMPGTW, ir, dst_reg, src_reg_a, src_reg_b) -#define uop_PCMPGTD(ir, dst_reg, src_reg_a, src_reg_b) uop_gen_reg_dst_src2(UOP_PCMPGTD, ir, dst_reg, src_reg_a, src_reg_b) +#define uop_PCMPEQB(ir, dst_reg, src_reg_a, src_reg_b) uop_gen_reg_dst_src2(UOP_PCMPEQB, ir, dst_reg, src_reg_a, src_reg_b) +#define uop_PCMPEQW(ir, dst_reg, src_reg_a, src_reg_b) uop_gen_reg_dst_src2(UOP_PCMPEQW, ir, dst_reg, src_reg_a, src_reg_b) +#define uop_PCMPEQD(ir, dst_reg, src_reg_a, src_reg_b) uop_gen_reg_dst_src2(UOP_PCMPEQD, ir, dst_reg, src_reg_a, src_reg_b) +#define uop_PCMPGTB(ir, dst_reg, src_reg_a, src_reg_b) uop_gen_reg_dst_src2(UOP_PCMPGTB, ir, dst_reg, src_reg_a, src_reg_b) +#define uop_PCMPGTW(ir, dst_reg, src_reg_a, src_reg_b) uop_gen_reg_dst_src2(UOP_PCMPGTW, ir, dst_reg, src_reg_a, src_reg_b) +#define uop_PCMPGTD(ir, dst_reg, src_reg_a, src_reg_b) uop_gen_reg_dst_src2(UOP_PCMPGTD, ir, dst_reg, src_reg_a, src_reg_b) -#define uop_PF2ID(ir, dst_reg, src_reg) uop_gen_reg_dst_src1(UOP_PF2ID, ir, dst_reg, src_reg) -#define uop_PFADD(ir, dst_reg, src_reg_a, src_reg_b) uop_gen_reg_dst_src2(UOP_PFADD, ir, dst_reg, src_reg_a, src_reg_b) -#define uop_PFCMPEQ(ir, dst_reg, src_reg_a, src_reg_b) uop_gen_reg_dst_src2(UOP_PFCMPEQ, ir, dst_reg, src_reg_a, src_reg_b) -#define uop_PFCMPGE(ir, dst_reg, src_reg_a, src_reg_b) uop_gen_reg_dst_src2(UOP_PFCMPGE, ir, dst_reg, src_reg_a, src_reg_b) -#define uop_PFCMPGT(ir, dst_reg, src_reg_a, src_reg_b) uop_gen_reg_dst_src2(UOP_PFCMPGT, ir, dst_reg, src_reg_a, src_reg_b) -#define uop_PFMAX(ir, dst_reg, src_reg_a, src_reg_b) uop_gen_reg_dst_src2(UOP_PFMAX, ir, dst_reg, src_reg_a, src_reg_b) -#define uop_PFMIN(ir, dst_reg, src_reg_a, src_reg_b) uop_gen_reg_dst_src2(UOP_PFMIN, ir, dst_reg, src_reg_a, src_reg_b) -#define uop_PFMUL(ir, dst_reg, src_reg_a, src_reg_b) uop_gen_reg_dst_src2(UOP_PFMUL, ir, dst_reg, src_reg_a, src_reg_b) -#define uop_PFRCP(ir, dst_reg, src_reg) uop_gen_reg_dst_src1(UOP_PFRCP, ir, dst_reg, src_reg) -#define uop_PFRSQRT(ir, dst_reg, src_reg) uop_gen_reg_dst_src1(UOP_PFRSQRT, ir, dst_reg, src_reg) -#define uop_PFSUB(ir, dst_reg, src_reg_a, src_reg_b) uop_gen_reg_dst_src2(UOP_PFSUB, ir, dst_reg, src_reg_a, src_reg_b) -#define uop_PI2FD(ir, dst_reg, src_reg) uop_gen_reg_dst_src1(UOP_PI2FD, ir, dst_reg, src_reg) +#define uop_PF2ID(ir, dst_reg, src_reg) uop_gen_reg_dst_src1(UOP_PF2ID, ir, dst_reg, src_reg) +#define uop_PFADD(ir, dst_reg, src_reg_a, src_reg_b) uop_gen_reg_dst_src2(UOP_PFADD, ir, dst_reg, src_reg_a, src_reg_b) +#define uop_PFCMPEQ(ir, dst_reg, src_reg_a, src_reg_b) uop_gen_reg_dst_src2(UOP_PFCMPEQ, ir, dst_reg, src_reg_a, src_reg_b) +#define uop_PFCMPGE(ir, dst_reg, src_reg_a, src_reg_b) uop_gen_reg_dst_src2(UOP_PFCMPGE, ir, dst_reg, src_reg_a, src_reg_b) +#define uop_PFCMPGT(ir, dst_reg, src_reg_a, src_reg_b) uop_gen_reg_dst_src2(UOP_PFCMPGT, ir, dst_reg, src_reg_a, src_reg_b) +#define uop_PFMAX(ir, dst_reg, src_reg_a, src_reg_b) uop_gen_reg_dst_src2(UOP_PFMAX, ir, dst_reg, src_reg_a, src_reg_b) +#define uop_PFMIN(ir, dst_reg, src_reg_a, src_reg_b) uop_gen_reg_dst_src2(UOP_PFMIN, ir, dst_reg, src_reg_a, src_reg_b) +#define uop_PFMUL(ir, dst_reg, src_reg_a, src_reg_b) uop_gen_reg_dst_src2(UOP_PFMUL, ir, dst_reg, src_reg_a, src_reg_b) +#define uop_PFRCP(ir, dst_reg, src_reg) uop_gen_reg_dst_src1(UOP_PFRCP, ir, dst_reg, src_reg) +#define uop_PFRSQRT(ir, dst_reg, src_reg) uop_gen_reg_dst_src1(UOP_PFRSQRT, ir, dst_reg, src_reg) +#define uop_PFSUB(ir, dst_reg, src_reg_a, src_reg_b) uop_gen_reg_dst_src2(UOP_PFSUB, ir, dst_reg, src_reg_a, src_reg_b) +#define uop_PI2FD(ir, dst_reg, src_reg) uop_gen_reg_dst_src1(UOP_PI2FD, ir, dst_reg, src_reg) -#define uop_PMADDWD(ir, dst_reg, src_reg_a, src_reg_b) uop_gen_reg_dst_src2(UOP_PMADDWD, ir, dst_reg, src_reg_a, src_reg_b) -#define uop_PMULHW(ir, dst_reg, src_reg_a, src_reg_b) uop_gen_reg_dst_src2(UOP_PMULHW, ir, dst_reg, src_reg_a, src_reg_b) -#define uop_PMULLW(ir, dst_reg, src_reg_a, src_reg_b) uop_gen_reg_dst_src2(UOP_PMULLW, ir, dst_reg, src_reg_a, src_reg_b) +#define uop_PMADDWD(ir, dst_reg, src_reg_a, src_reg_b) uop_gen_reg_dst_src2(UOP_PMADDWD, ir, dst_reg, src_reg_a, src_reg_b) +#define uop_PMULHW(ir, dst_reg, src_reg_a, src_reg_b) uop_gen_reg_dst_src2(UOP_PMULHW, ir, dst_reg, src_reg_a, src_reg_b) +#define uop_PMULLW(ir, dst_reg, src_reg_a, src_reg_b) uop_gen_reg_dst_src2(UOP_PMULLW, ir, dst_reg, src_reg_a, src_reg_b) -#define uop_PSLLW_IMM(ir, dst_reg, src_reg, imm) uop_gen_reg_dst_src_imm(UOP_PSLLW_IMM, ir, dst_reg, src_reg, imm) -#define uop_PSLLD_IMM(ir, dst_reg, src_reg, imm) uop_gen_reg_dst_src_imm(UOP_PSLLD_IMM, ir, dst_reg, src_reg, imm) -#define uop_PSLLQ_IMM(ir, dst_reg, src_reg, imm) uop_gen_reg_dst_src_imm(UOP_PSLLQ_IMM, ir, dst_reg, src_reg, imm) -#define uop_PSRAW_IMM(ir, dst_reg, src_reg, imm) uop_gen_reg_dst_src_imm(UOP_PSRAW_IMM, ir, dst_reg, src_reg, imm) -#define uop_PSRAD_IMM(ir, dst_reg, src_reg, imm) uop_gen_reg_dst_src_imm(UOP_PSRAD_IMM, ir, dst_reg, src_reg, imm) -#define uop_PSRAQ_IMM(ir, dst_reg, src_reg, imm) uop_gen_reg_dst_src_imm(UOP_PSRAQ_IMM, ir, dst_reg, src_reg, imm) -#define uop_PSRLW_IMM(ir, dst_reg, src_reg, imm) uop_gen_reg_dst_src_imm(UOP_PSRLW_IMM, ir, dst_reg, src_reg, imm) -#define uop_PSRLD_IMM(ir, dst_reg, src_reg, imm) uop_gen_reg_dst_src_imm(UOP_PSRLD_IMM, ir, dst_reg, src_reg, imm) -#define uop_PSRLQ_IMM(ir, dst_reg, src_reg, imm) uop_gen_reg_dst_src_imm(UOP_PSRLQ_IMM, ir, dst_reg, src_reg, imm) +#define uop_PSLLW_IMM(ir, dst_reg, src_reg, imm) uop_gen_reg_dst_src_imm(UOP_PSLLW_IMM, ir, dst_reg, src_reg, imm) +#define uop_PSLLD_IMM(ir, dst_reg, src_reg, imm) uop_gen_reg_dst_src_imm(UOP_PSLLD_IMM, ir, dst_reg, src_reg, imm) +#define uop_PSLLQ_IMM(ir, dst_reg, src_reg, imm) uop_gen_reg_dst_src_imm(UOP_PSLLQ_IMM, ir, dst_reg, src_reg, imm) +#define uop_PSRAW_IMM(ir, dst_reg, src_reg, imm) uop_gen_reg_dst_src_imm(UOP_PSRAW_IMM, ir, dst_reg, src_reg, imm) +#define uop_PSRAD_IMM(ir, dst_reg, src_reg, imm) uop_gen_reg_dst_src_imm(UOP_PSRAD_IMM, ir, dst_reg, src_reg, imm) +#define uop_PSRAQ_IMM(ir, dst_reg, src_reg, imm) uop_gen_reg_dst_src_imm(UOP_PSRAQ_IMM, ir, dst_reg, src_reg, imm) +#define uop_PSRLW_IMM(ir, dst_reg, src_reg, imm) uop_gen_reg_dst_src_imm(UOP_PSRLW_IMM, ir, dst_reg, src_reg, imm) +#define uop_PSRLD_IMM(ir, dst_reg, src_reg, imm) uop_gen_reg_dst_src_imm(UOP_PSRLD_IMM, ir, dst_reg, src_reg, imm) +#define uop_PSRLQ_IMM(ir, dst_reg, src_reg, imm) uop_gen_reg_dst_src_imm(UOP_PSRLQ_IMM, ir, dst_reg, src_reg, imm) -#define uop_PSUBB(ir, dst_reg, src_reg_a, src_reg_b) uop_gen_reg_dst_src2(UOP_PSUBB, ir, dst_reg, src_reg_a, src_reg_b) -#define uop_PSUBW(ir, dst_reg, src_reg_a, src_reg_b) uop_gen_reg_dst_src2(UOP_PSUBW, ir, dst_reg, src_reg_a, src_reg_b) -#define uop_PSUBD(ir, dst_reg, src_reg_a, src_reg_b) uop_gen_reg_dst_src2(UOP_PSUBD, ir, dst_reg, src_reg_a, src_reg_b) -#define uop_PSUBSB(ir, dst_reg, src_reg_a, src_reg_b) uop_gen_reg_dst_src2(UOP_PSUBSB, ir, dst_reg, src_reg_a, src_reg_b) -#define uop_PSUBSW(ir, dst_reg, src_reg_a, src_reg_b) uop_gen_reg_dst_src2(UOP_PSUBSW, ir, dst_reg, src_reg_a, src_reg_b) -#define uop_PSUBUSB(ir, dst_reg, src_reg_a, src_reg_b) uop_gen_reg_dst_src2(UOP_PSUBUSB, ir, dst_reg, src_reg_a, src_reg_b) -#define uop_PSUBUSW(ir, dst_reg, src_reg_a, src_reg_b) uop_gen_reg_dst_src2(UOP_PSUBUSW, ir, dst_reg, src_reg_a, src_reg_b) +#define uop_PSUBB(ir, dst_reg, src_reg_a, src_reg_b) uop_gen_reg_dst_src2(UOP_PSUBB, ir, dst_reg, src_reg_a, src_reg_b) +#define uop_PSUBW(ir, dst_reg, src_reg_a, src_reg_b) uop_gen_reg_dst_src2(UOP_PSUBW, ir, dst_reg, src_reg_a, src_reg_b) +#define uop_PSUBD(ir, dst_reg, src_reg_a, src_reg_b) uop_gen_reg_dst_src2(UOP_PSUBD, ir, dst_reg, src_reg_a, src_reg_b) +#define uop_PSUBSB(ir, dst_reg, src_reg_a, src_reg_b) uop_gen_reg_dst_src2(UOP_PSUBSB, ir, dst_reg, src_reg_a, src_reg_b) +#define uop_PSUBSW(ir, dst_reg, src_reg_a, src_reg_b) uop_gen_reg_dst_src2(UOP_PSUBSW, ir, dst_reg, src_reg_a, src_reg_b) +#define uop_PSUBUSB(ir, dst_reg, src_reg_a, src_reg_b) uop_gen_reg_dst_src2(UOP_PSUBUSB, ir, dst_reg, src_reg_a, src_reg_b) +#define uop_PSUBUSW(ir, dst_reg, src_reg_a, src_reg_b) uop_gen_reg_dst_src2(UOP_PSUBUSW, ir, dst_reg, src_reg_a, src_reg_b) -#define uop_PUNPCKHBW(ir, dst_reg, src_reg_a, src_reg_b) uop_gen_reg_dst_src2(UOP_PUNPCKHBW, ir, dst_reg, src_reg_a, src_reg_b) -#define uop_PUNPCKHWD(ir, dst_reg, src_reg_a, src_reg_b) uop_gen_reg_dst_src2(UOP_PUNPCKHWD, ir, dst_reg, src_reg_a, src_reg_b) -#define uop_PUNPCKHDQ(ir, dst_reg, src_reg_a, src_reg_b) uop_gen_reg_dst_src2(UOP_PUNPCKHDQ, ir, dst_reg, src_reg_a, src_reg_b) -#define uop_PUNPCKLBW(ir, dst_reg, src_reg_a, src_reg_b) uop_gen_reg_dst_src2(UOP_PUNPCKLBW, ir, dst_reg, src_reg_a, src_reg_b) -#define uop_PUNPCKLWD(ir, dst_reg, src_reg_a, src_reg_b) uop_gen_reg_dst_src2(UOP_PUNPCKLWD, ir, dst_reg, src_reg_a, src_reg_b) -#define uop_PUNPCKLDQ(ir, dst_reg, src_reg_a, src_reg_b) uop_gen_reg_dst_src2(UOP_PUNPCKLDQ, ir, dst_reg, src_reg_a, src_reg_b) +#define uop_PUNPCKHBW(ir, dst_reg, src_reg_a, src_reg_b) uop_gen_reg_dst_src2(UOP_PUNPCKHBW, ir, dst_reg, src_reg_a, src_reg_b) +#define uop_PUNPCKHWD(ir, dst_reg, src_reg_a, src_reg_b) uop_gen_reg_dst_src2(UOP_PUNPCKHWD, ir, dst_reg, src_reg_a, src_reg_b) +#define uop_PUNPCKHDQ(ir, dst_reg, src_reg_a, src_reg_b) uop_gen_reg_dst_src2(UOP_PUNPCKHDQ, ir, dst_reg, src_reg_a, src_reg_b) +#define uop_PUNPCKLBW(ir, dst_reg, src_reg_a, src_reg_b) uop_gen_reg_dst_src2(UOP_PUNPCKLBW, ir, dst_reg, src_reg_a, src_reg_b) +#define uop_PUNPCKLWD(ir, dst_reg, src_reg_a, src_reg_b) uop_gen_reg_dst_src2(UOP_PUNPCKLWD, ir, dst_reg, src_reg_a, src_reg_b) +#define uop_PUNPCKLDQ(ir, dst_reg, src_reg_a, src_reg_b) uop_gen_reg_dst_src2(UOP_PUNPCKLDQ, ir, dst_reg, src_reg_a, src_reg_b) -#define uop_STORE_PTR_IMM(ir, p, imm) uop_gen_pointer_imm(UOP_STORE_P_IMM, ir, p, imm) -#define uop_STORE_PTR_IMM_8(ir, p, imm) uop_gen_pointer_imm(UOP_STORE_P_IMM_8, ir, p, imm) -#define uop_STORE_PTR_IMM_16(ir, p, imm) uop_gen_pointer_imm(UOP_STORE_P_IMM_16, ir, p, imm) +#define uop_STORE_PTR_IMM(ir, p, imm) uop_gen_pointer_imm(UOP_STORE_P_IMM, ir, p, imm) +#define uop_STORE_PTR_IMM_8(ir, p, imm) uop_gen_pointer_imm(UOP_STORE_P_IMM_8, ir, p, imm) +#define uop_STORE_PTR_IMM_16(ir, p, imm) uop_gen_pointer_imm(UOP_STORE_P_IMM_16, ir, p, imm) -#define uop_TEST_JNS_DEST(ir, src_reg) uop_gen_reg_src1(UOP_TEST_JNS_DEST, ir, src_reg) -#define uop_TEST_JS_DEST(ir, src_reg) uop_gen_reg_src1(UOP_TEST_JS_DEST, ir, src_reg) +#define uop_TEST_JNS_DEST(ir, src_reg) uop_gen_reg_src1(UOP_TEST_JNS_DEST, ir, src_reg) +#define uop_TEST_JS_DEST(ir, src_reg) uop_gen_reg_src1(UOP_TEST_JS_DEST, ir, src_reg) #ifdef DEBUG_EXTRA -#define uop_LOG_INSTR(ir, imm) uop_gen_imm(UOP_LOG_INSTR, ir, imm) +# define uop_LOG_INSTR(ir, imm) uop_gen_imm(UOP_LOG_INSTR, ir, imm) #endif void codegen_direct_read_8(codeblock_t *block, int host_reg, void *p); diff --git a/src/codegen_new/codegen_ops.c b/src/codegen_new/codegen_ops.c index a1570fc31..59e148659 100644 --- a/src/codegen_new/codegen_ops.c +++ b/src/codegen_new/codegen_ops.c @@ -26,8 +26,8 @@ #include "codegen_ops_shift.h" #include "codegen_ops_stack.h" -RecompOpFn recomp_opcodes[512] = -{ +RecompOpFn recomp_opcodes[512] = { + // clang-format off /*16-bit data*/ /* 00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f*/ /*00*/ ropADD_b_rmw, ropADD_w_rmw, ropADD_b_rm, ropADD_w_rm, ropADD_AL_imm, ropADD_AX_imm, ropPUSH_ES_16, ropPOP_ES_16, ropOR_b_rmw, ropOR_w_rmw, ropOR_b_rm, ropOR_w_rm, ropOR_AL_imm, ropOR_AX_imm, ropPUSH_CS_16, NULL, @@ -71,11 +71,11 @@ RecompOpFn recomp_opcodes[512] = /*d0*/ ropD0, ropD1_l, ropD2, ropD3_l, NULL, NULL, NULL, ropXLAT, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, /*e0*/ ropLOOPNE, ropLOOPE, ropLOOP, ropJCXZ, NULL, NULL, NULL, NULL, ropCALL_r32, ropJMP_r32, ropJMP_far_32, ropJMP_r8, NULL, NULL, NULL, NULL, /*f0*/ NULL, NULL, NULL, NULL, NULL, ropCMC, ropF6, ropF7_32, ropCLC, ropSTC, ropCLI, ropSTI, ropCLD, ropSTD, ropINCDEC, ropFF_32 + // clang-format on }; - -RecompOpFn recomp_opcodes_0f[512] = -{ +RecompOpFn recomp_opcodes_0f[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, @@ -85,8 +85,13 @@ RecompOpFn recomp_opcodes_0f[512] = /*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, +#if defined __ARM_EABI__ || defined _ARM_ || defined _M_ARM || defined __aarch64__ || defined _M_ARM64 +/*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, +#else /*60*/ ropPUNPCKLBW, ropPUNPCKLWD, ropPUNPCKLDQ, ropPACKSSWB, ropPCMPGTB, ropPCMPGTW, ropPCMPGTD, ropPACKUSWB, ropPUNPCKHBW, ropPUNPCKHWD, ropPUNPCKHDQ, ropPACKSSDW, NULL, NULL, ropMOVD_r_d, ropMOVQ_r_q, /*70*/ NULL, ropPSxxW_imm, ropPSxxD_imm, ropPSxxQ_imm, ropPCMPEQB, ropPCMPEQW, ropPCMPEQD, NULL, NULL, NULL, NULL, NULL, NULL, NULL, ropMOVD_d_r, ropMOVQ_q_r, +#endif /*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, @@ -94,9 +99,15 @@ RecompOpFn recomp_opcodes_0f[512] = /*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, +#if defined __ARM_EABI__ || defined _ARM_ || defined _M_ARM || defined __aarch64__ || defined _M_ARM64 +/*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, +#else /*d0*/ NULL, NULL, NULL, NULL, NULL, ropPMULLW, NULL, NULL, ropPSUBUSB, ropPSUBUSW, NULL, ropPAND, ropPADDUSB, ropPADDUSW, NULL, ropPANDN, /*e0*/ NULL, NULL, NULL, NULL, NULL, ropPMULHW, NULL, NULL, ropPSUBSB, ropPSUBSW, NULL, ropPOR, ropPADDSB, ropPADDSW, NULL, ropPXOR, /*f0*/ NULL, NULL, NULL, NULL, NULL, ropPMADDWD, NULL, NULL, ropPSUBB, ropPSUBW, ropPSUBD, NULL, ropPADDB, ropPADDW, ropPADDD, NULL, +#endif /*32-bit data*/ /* 00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f*/ @@ -107,8 +118,13 @@ RecompOpFn recomp_opcodes_0f[512] = /*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, +#if defined __ARM_EABI__ || defined _ARM_ || defined _M_ARM || defined __aarch64__ || defined _M_ARM64 +/*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, +#else /*60*/ ropPUNPCKLBW, ropPUNPCKLWD, ropPUNPCKLDQ, ropPACKSSWB, ropPCMPGTB, ropPCMPGTW, ropPCMPGTD, ropPACKUSWB, ropPUNPCKHBW, ropPUNPCKHWD, ropPUNPCKHDQ, ropPACKSSDW, NULL, NULL, ropMOVD_r_d, ropMOVQ_r_q, /*70*/ NULL, ropPSxxW_imm, ropPSxxD_imm, ropPSxxQ_imm, ropPCMPEQB, ropPCMPEQW, ropPCMPEQD, NULL, NULL, NULL, NULL, NULL, NULL, NULL, ropMOVD_d_r, ropMOVQ_q_r, +#endif /*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, @@ -116,13 +132,71 @@ RecompOpFn recomp_opcodes_0f[512] = /*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, +#if defined __ARM_EABI__ || defined _ARM_ || defined _M_ARM || defined __aarch64__ || defined _M_ARM64 +/*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, +#else /*d0*/ NULL, NULL, NULL, NULL, NULL, ropPMULLW, NULL, NULL, ropPSUBUSB, ropPSUBUSW, NULL, ropPAND, ropPADDUSB, ropPADDUSW, NULL, ropPANDN, /*e0*/ NULL, NULL, NULL, NULL, NULL, ropPMULHW, NULL, NULL, ropPSUBSB, ropPSUBSW, NULL, ropPOR, ropPADDSB, ropPADDSW, NULL, ropPXOR, /*f0*/ NULL, NULL, NULL, NULL, NULL, ropPMADDWD, NULL, NULL, ropPSUBB, ropPSUBW, ropPSUBD, NULL, ropPADDB, ropPADDW, ropPADDD, NULL, +#endif + // clang-format on }; -RecompOpFn recomp_opcodes_3DNOW[256] = -{ +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 +0 +#else /* 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, ropPI2FD, NULL, NULL, /*10*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, ropPF2ID, NULL, NULL, @@ -143,10 +217,12 @@ RecompOpFn recomp_opcodes_3DNOW[256] = /*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, +#endif + // clang-format on }; -RecompOpFn recomp_opcodes_d8[512] = -{ +RecompOpFn recomp_opcodes_d8[512] = { + // clang-format off /*16-bit data*/ /* 00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f*/ /*00*/ ropFADDs, ropFADDs, ropFADDs, ropFADDs, ropFADDs, ropFADDs, ropFADDs, ropFADDs, ropFMULs, ropFMULs, ropFMULs, ropFMULs, ropFMULs, ropFMULs, ropFMULs, ropFMULs, @@ -190,10 +266,11 @@ RecompOpFn recomp_opcodes_d8[512] = /*d0*/ ropFCOM, ropFCOM, ropFCOM, ropFCOM, ropFCOM, ropFCOM, ropFCOM, ropFCOM, ropFCOMP, ropFCOMP, ropFCOMP, ropFCOMP, ropFCOMP, ropFCOMP, ropFCOMP, ropFCOMP, /*e0*/ ropFSUB, ropFSUB, ropFSUB, ropFSUB, ropFSUB, ropFSUB, ropFSUB, ropFSUB, ropFSUBR, ropFSUBR, ropFSUBR, ropFSUBR, ropFSUBR, ropFSUBR, ropFSUBR, ropFSUBR, /*f0*/ ropFDIV, ropFDIV, ropFDIV, ropFDIV, ropFDIV, ropFDIV, ropFDIV, ropFDIV, ropFDIVR, ropFDIVR, ropFDIVR, ropFDIVR, ropFDIVR, ropFDIVR, ropFDIVR, ropFDIVR, + // clang-format on }; -RecompOpFn recomp_opcodes_d9[512] = -{ +RecompOpFn recomp_opcodes_d9[512] = { + // clang-format off /*16-bit data*/ /* 00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f*/ /*00*/ ropFLDs, ropFLDs, ropFLDs, ropFLDs, ropFLDs, ropFLDs, ropFLDs, ropFLDs, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, @@ -237,10 +314,11 @@ RecompOpFn recomp_opcodes_d9[512] = /*d0*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, ropFSTP, ropFSTP, ropFSTP, ropFSTP, ropFSTP, ropFSTP, ropFSTP, ropFSTP, /*e0*/ ropFCHS, ropFABS, NULL, NULL, ropFTST, NULL, NULL, NULL, ropFLD1, NULL, NULL, NULL, NULL, NULL, ropFLDZ, NULL, /*f0*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, ropFSQRT, NULL, NULL, NULL, NULL, NULL, + // clang-format on }; -RecompOpFn recomp_opcodes_da[512] = -{ +RecompOpFn recomp_opcodes_da[512] = { + // clang-format off /*16-bit data*/ /* 00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f*/ /*00*/ ropFIADDl, ropFIADDl, ropFIADDl, ropFIADDl, ropFIADDl, ropFIADDl, ropFIADDl, ropFIADDl, ropFIMULl, ropFIMULl, ropFIMULl, ropFIMULl, ropFIMULl, ropFIMULl, ropFIMULl, ropFIMULl, @@ -284,10 +362,11 @@ RecompOpFn recomp_opcodes_da[512] = /*d0*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, ropFUCOMPP, 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_db[512] = -{ +RecompOpFn recomp_opcodes_db[512] = { + // clang-format off /*16-bit data*/ /* 00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f*/ /*00*/ ropFILDl, ropFILDl, ropFILDl, ropFILDl, ropFILDl, ropFILDl, ropFILDl, ropFILDl, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, @@ -331,10 +410,11 @@ RecompOpFn recomp_opcodes_db[512] = /*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_dc[512] = -{ +RecompOpFn recomp_opcodes_dc[512] = { + // clang-format off /*16-bit data*/ /* 00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f*/ /*00*/ ropFADDd, ropFADDd, ropFADDd, ropFADDd, ropFADDd, ropFADDd, ropFADDd, ropFADDd, ropFMULd, ropFMULd, ropFMULd, ropFMULd, ropFMULd, ropFMULd, ropFMULd, ropFMULd, @@ -378,10 +458,11 @@ RecompOpFn recomp_opcodes_dc[512] = /*d0*/ ropFCOM, ropFCOM, ropFCOM, ropFCOM, ropFCOM, ropFCOM, ropFCOM, ropFCOM, ropFCOMP, ropFCOMP, ropFCOMP, ropFCOMP, ropFCOMP, ropFCOMP, ropFCOMP, ropFCOMP, /*e0*/ ropFSUBRr, ropFSUBRr, ropFSUBRr, ropFSUBRr, ropFSUBRr, ropFSUBRr, ropFSUBRr, ropFSUBRr, ropFSUBr, ropFSUBr, ropFSUBr, ropFSUBr, ropFSUBr, ropFSUBr, ropFSUBr, ropFSUBr, /*f0*/ ropFDIVRr, ropFDIVRr, ropFDIVRr, ropFDIVRr, ropFDIVRr, ropFDIVRr, ropFDIVRr, ropFDIVRr, ropFDIVr, ropFDIVr, ropFDIVr, ropFDIVr, ropFDIVr, ropFDIVr, ropFDIVr, ropFDIVr, + // clang-format on }; -RecompOpFn recomp_opcodes_dd[512] = -{ +RecompOpFn recomp_opcodes_dd[512] = { + // clang-format off /*16-bit data*/ /* 00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f*/ /*00*/ ropFLDd, ropFLDd, ropFLDd, ropFLDd, ropFLDd, ropFLDd, ropFLDd, ropFLDd, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, @@ -425,10 +506,11 @@ RecompOpFn recomp_opcodes_dd[512] = /*d0*/ ropFST, ropFST, ropFST, ropFST, ropFST, ropFST, ropFST, ropFST, ropFSTP, ropFSTP, ropFSTP, ropFSTP, ropFSTP, ropFSTP, ropFSTP, ropFSTP, /*e0*/ ropFUCOM, ropFUCOM, ropFUCOM, ropFUCOM, ropFUCOM, ropFUCOM, ropFUCOM, ropFUCOM, ropFUCOMP, ropFUCOMP, ropFUCOMP, ropFUCOMP, ropFUCOMP, ropFUCOMP, ropFUCOMP, ropFUCOMP, /*f0*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + // clang-format on }; -RecompOpFn recomp_opcodes_de[512] = -{ +RecompOpFn recomp_opcodes_de[512] = { + // clang-format off /*16-bit data*/ /* 00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f*/ /*00*/ ropFIADDw, ropFIADDw, ropFIADDw, ropFIADDw, ropFIADDw, ropFIADDw, ropFIADDw, ropFIADDw, ropFIMULw, ropFIMULw, ropFIMULw, ropFIMULw, ropFIMULw, ropFIMULw, ropFIMULw, ropFIMULw, @@ -472,10 +554,11 @@ RecompOpFn recomp_opcodes_de[512] = /*d0*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, ropFCOMPP, NULL, NULL, NULL, NULL, NULL, NULL, /*e0*/ ropFSUBRP, ropFSUBRP, ropFSUBRP, ropFSUBRP, ropFSUBRP, ropFSUBRP, ropFSUBRP, ropFSUBRP, ropFSUBP, ropFSUBP, ropFSUBP, ropFSUBP, ropFSUBP, ropFSUBP, ropFSUBP, ropFSUBP, /*f0*/ ropFDIVRP, ropFDIVRP, ropFDIVRP, ropFDIVRP, ropFDIVRP, ropFDIVRP, ropFDIVRP, ropFDIVRP, ropFDIVP, ropFDIVP, ropFDIVP, ropFDIVP, ropFDIVP, ropFDIVP, ropFDIVP, ropFDIVP, + // clang-format on }; -RecompOpFn recomp_opcodes_df[512] = -{ +RecompOpFn recomp_opcodes_df[512] = { + // clang-format off /*16-bit data*/ /* 00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f*/ /*00*/ ropFILDw, ropFILDw, ropFILDw, ropFILDw, ropFILDw, ropFILDw, ropFILDw, ropFILDw, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, @@ -519,4 +602,5 @@ RecompOpFn recomp_opcodes_df[512] = /*d0*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, /*e0*/ ropFSTSW_AX, 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 }; diff --git a/src/codegen_new/codegen_ops.h b/src/codegen_new/codegen_ops.h index 361479b6d..a91382c2f 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]; @@ -18,8 +19,10 @@ extern RecompOpFn recomp_opcodes_dc[512]; extern RecompOpFn recomp_opcodes_dd[512]; extern RecompOpFn recomp_opcodes_de[512]; extern RecompOpFn recomp_opcodes_df[512]; -/*extern RecompOpFn recomp_opcodes_REPE[512]; -extern RecompOpFn recomp_opcodes_REPNE[512];*/ +#if 0 +extern RecompOpFn recomp_opcodes_REPE[512]; +extern RecompOpFn recomp_opcodes_REPNE[512]; +#endif #define REG_EAX 0 #define REG_ECX 1 @@ -29,21 +32,21 @@ extern RecompOpFn recomp_opcodes_REPNE[512];*/ #define REG_EBP 5 #define REG_ESI 6 #define REG_EDI 7 -#define REG_AX 0 -#define REG_CX 1 -#define REG_DX 2 -#define REG_BX 3 -#define REG_SP 4 -#define REG_BP 5 -#define REG_SI 6 -#define REG_DI 7 -#define REG_AL 0 -#define REG_AH 4 -#define REG_CL 1 -#define REG_CH 5 -#define REG_DL 2 -#define REG_DH 6 -#define REG_BL 3 -#define REG_BH 7 +#define REG_AX 0 +#define REG_CX 1 +#define REG_DX 2 +#define REG_BX 3 +#define REG_SP 4 +#define REG_BP 5 +#define REG_SI 6 +#define REG_DI 7 +#define REG_AL 0 +#define REG_AH 4 +#define REG_CL 1 +#define REG_CH 5 +#define REG_DL 2 +#define REG_DH 6 +#define REG_BL 3 +#define REG_BH 7 #endif diff --git a/src/codegen_new/codegen_ops_3dnow.c b/src/codegen_new/codegen_ops_3dnow.c index 2c4ecc353..8b4d471ba 100644 --- a/src/codegen_new/codegen_ops_3dnow.c +++ b/src/codegen_new/codegen_ops_3dnow.c @@ -2,9 +2,12 @@ #include <86box/86box.h> #include "cpu.h" #include <86box/mem.h> +#include <86box/plat_unused.h> #include "x86.h" #include "x86_flags.h" +#include "x86seg_common.h" +#include "x86seg.h" #include "386_common.h" #include "codegen.h" #include "codegen_accumulate.h" @@ -13,33 +16,31 @@ #include "codegen_ops_3dnow.h" #include "codegen_ops_helpers.h" -#define ropParith(func) \ -uint32_t rop ## func(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) \ -{ \ - int dest_reg = (fetchdat >> 3) & 7; \ - \ - uop_MMX_ENTER(ir); \ - codegen_mark_code_present(block, cs+op_pc, 1); \ - if ((fetchdat & 0xc0) == 0xc0) \ - { \ - int src_reg = fetchdat & 7; \ - uop_ ## func(ir, IREG_MM(dest_reg), IREG_MM(dest_reg), IREG_MM(src_reg)); \ - } \ - else \ - { \ - x86seg *target_seg; \ - \ - uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc); \ - target_seg = codegen_generate_ea(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32, 0); \ - codegen_check_seg_read(block, ir, target_seg); \ - uop_MEM_LOAD_REG(ir, IREG_temp0_Q, ireg_seg_base(target_seg), IREG_eaaddr); \ - uop_ ## func(ir, IREG_MM(dest_reg), IREG_MM(dest_reg), IREG_temp0_Q); \ - } \ - \ - codegen_mark_code_present(block, cs+op_pc+1, 1); \ - return op_pc + 2; \ -} +#define ropParith(func) \ + uint32_t rop##func(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) \ + { \ + int dest_reg = (fetchdat >> 3) & 7; \ + \ + uop_MMX_ENTER(ir); \ + codegen_mark_code_present(block, cs + op_pc, 1); \ + if ((fetchdat & 0xc0) == 0xc0) { \ + int src_reg = fetchdat & 7; \ + uop_##func(ir, IREG_MM(dest_reg), IREG_MM(dest_reg), IREG_MM(src_reg)); \ + } else { \ + x86seg *target_seg; \ + \ + uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc); \ + target_seg = codegen_generate_ea(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32, 0); \ + codegen_check_seg_read(block, ir, target_seg); \ + uop_MEM_LOAD_REG(ir, IREG_temp0_Q, ireg_seg_base(target_seg), IREG_eaaddr); \ + uop_##func(ir, IREG_MM(dest_reg), IREG_MM(dest_reg), IREG_temp0_Q); \ + } \ + \ + codegen_mark_code_present(block, cs + op_pc + 1, 1); \ + return op_pc + 2; \ + } +// clang-format off ropParith(PFADD) ropParith(PFCMPEQ) ropParith(PFCMPGE) @@ -48,164 +49,153 @@ ropParith(PFMAX) ropParith(PFMIN) ropParith(PFMUL) ropParith(PFSUB) + // clang-format on -uint32_t ropPF2ID(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) +uint32_t ropPF2ID(codeblock_t *block, ir_data_t *ir, UNUSED(uint8_t opcode), uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) { - int dest_reg = (fetchdat >> 3) & 7; + int dest_reg = (fetchdat >> 3) & 7; - uop_MMX_ENTER(ir); - codegen_mark_code_present(block, cs+op_pc, 1); - if ((fetchdat & 0xc0) == 0xc0) - { - int src_reg = fetchdat & 7; - uop_PF2ID(ir, IREG_MM(dest_reg), IREG_MM(src_reg)); - } - else - { - x86seg *target_seg; + uop_MMX_ENTER(ir); + codegen_mark_code_present(block, cs + op_pc, 1); + if ((fetchdat & 0xc0) == 0xc0) { + int src_reg = fetchdat & 7; + uop_PF2ID(ir, IREG_MM(dest_reg), IREG_MM(src_reg)); + } else { + x86seg *target_seg; - uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc); - target_seg = codegen_generate_ea(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32, 0); - codegen_check_seg_read(block, ir, target_seg); - uop_MEM_LOAD_REG(ir, IREG_temp0_Q, ireg_seg_base(target_seg), IREG_eaaddr); - uop_PF2ID(ir, IREG_MM(dest_reg), IREG_temp0_Q); - } + uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc); + target_seg = codegen_generate_ea(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32, 0); + codegen_check_seg_read(block, ir, target_seg); + uop_MEM_LOAD_REG(ir, IREG_temp0_Q, ireg_seg_base(target_seg), IREG_eaaddr); + uop_PF2ID(ir, IREG_MM(dest_reg), IREG_temp0_Q); + } - codegen_mark_code_present(block, cs+op_pc+1, 1); - return op_pc + 2; + codegen_mark_code_present(block, cs + op_pc + 1, 1); + return op_pc + 2; } -uint32_t ropPFSUBR(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) +uint32_t +ropPFSUBR(codeblock_t *block, ir_data_t *ir, UNUSED(uint8_t opcode), uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) { - int dest_reg = (fetchdat >> 3) & 7; + int dest_reg = (fetchdat >> 3) & 7; - uop_MMX_ENTER(ir); - codegen_mark_code_present(block, cs+op_pc, 1); - if ((fetchdat & 0xc0) == 0xc0) - { - int src_reg = fetchdat & 7; - uop_PFSUB(ir, IREG_MM(dest_reg), IREG_MM(src_reg), IREG_MM(dest_reg)); - } - else - { - x86seg *target_seg; + uop_MMX_ENTER(ir); + codegen_mark_code_present(block, cs + op_pc, 1); + if ((fetchdat & 0xc0) == 0xc0) { + int src_reg = fetchdat & 7; + uop_PFSUB(ir, IREG_MM(dest_reg), IREG_MM(src_reg), IREG_MM(dest_reg)); + } else { + x86seg *target_seg; - uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc); - target_seg = codegen_generate_ea(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32, 0); - codegen_check_seg_read(block, ir, target_seg); - uop_MEM_LOAD_REG(ir, IREG_temp0_Q, ireg_seg_base(target_seg), IREG_eaaddr); - uop_PFSUB(ir, IREG_MM(dest_reg), IREG_temp0_Q, IREG_MM(dest_reg)); - } + uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc); + target_seg = codegen_generate_ea(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32, 0); + codegen_check_seg_read(block, ir, target_seg); + uop_MEM_LOAD_REG(ir, IREG_temp0_Q, ireg_seg_base(target_seg), IREG_eaaddr); + uop_PFSUB(ir, IREG_MM(dest_reg), IREG_temp0_Q, IREG_MM(dest_reg)); + } - codegen_mark_code_present(block, cs+op_pc+1, 1); - return op_pc + 2; + codegen_mark_code_present(block, cs + op_pc + 1, 1); + return op_pc + 2; } -uint32_t ropPI2FD(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) +uint32_t +ropPI2FD(codeblock_t *block, ir_data_t *ir, UNUSED(uint8_t opcode), uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) { - int dest_reg = (fetchdat >> 3) & 7; + int dest_reg = (fetchdat >> 3) & 7; - uop_MMX_ENTER(ir); - codegen_mark_code_present(block, cs+op_pc, 1); - if ((fetchdat & 0xc0) == 0xc0) - { - int src_reg = fetchdat & 7; - uop_PI2FD(ir, IREG_MM(dest_reg), IREG_MM(src_reg)); - } - else - { - x86seg *target_seg; + uop_MMX_ENTER(ir); + codegen_mark_code_present(block, cs + op_pc, 1); + if ((fetchdat & 0xc0) == 0xc0) { + int src_reg = fetchdat & 7; + uop_PI2FD(ir, IREG_MM(dest_reg), IREG_MM(src_reg)); + } else { + x86seg *target_seg; - uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc); - target_seg = codegen_generate_ea(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32, 0); - codegen_check_seg_read(block, ir, target_seg); - uop_MEM_LOAD_REG(ir, IREG_temp0_Q, ireg_seg_base(target_seg), IREG_eaaddr); - uop_PI2FD(ir, IREG_MM(dest_reg), IREG_temp0_Q); - } + uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc); + target_seg = codegen_generate_ea(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32, 0); + codegen_check_seg_read(block, ir, target_seg); + uop_MEM_LOAD_REG(ir, IREG_temp0_Q, ireg_seg_base(target_seg), IREG_eaaddr); + uop_PI2FD(ir, IREG_MM(dest_reg), IREG_temp0_Q); + } - codegen_mark_code_present(block, cs+op_pc+1, 1); - return op_pc + 2; + codegen_mark_code_present(block, cs + op_pc + 1, 1); + return op_pc + 2; } -uint32_t ropPFRCPIT(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) +uint32_t +ropPFRCPIT(codeblock_t *block, ir_data_t *ir, UNUSED(uint8_t opcode), uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) { - int dest_reg = (fetchdat >> 3) & 7; + int dest_reg = (fetchdat >> 3) & 7; - uop_MMX_ENTER(ir); - codegen_mark_code_present(block, cs+op_pc, 1); - if ((fetchdat & 0xc0) == 0xc0) - { - int src_reg = fetchdat & 7; - uop_MOV(ir, IREG_MM(dest_reg), IREG_MM(src_reg)); - } - else - { - x86seg *target_seg; + uop_MMX_ENTER(ir); + codegen_mark_code_present(block, cs + op_pc, 1); + if ((fetchdat & 0xc0) == 0xc0) { + int src_reg = fetchdat & 7; + uop_MOV(ir, IREG_MM(dest_reg), IREG_MM(src_reg)); + } else { + x86seg *target_seg; - uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc); - target_seg = codegen_generate_ea(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32, 0); - codegen_check_seg_read(block, ir, target_seg); - uop_MEM_LOAD_REG(ir, IREG_MM(dest_reg), ireg_seg_base(target_seg), IREG_eaaddr); - } + uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc); + target_seg = codegen_generate_ea(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32, 0); + codegen_check_seg_read(block, ir, target_seg); + uop_MEM_LOAD_REG(ir, IREG_MM(dest_reg), ireg_seg_base(target_seg), IREG_eaaddr); + } - codegen_mark_code_present(block, cs+op_pc+1, 1); - return op_pc + 2; + codegen_mark_code_present(block, cs + op_pc + 1, 1); + return op_pc + 2; } -uint32_t ropPFRCP(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) +uint32_t +ropPFRCP(codeblock_t *block, ir_data_t *ir, UNUSED(uint8_t opcode), uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) { - int dest_reg = (fetchdat >> 3) & 7; + int dest_reg = (fetchdat >> 3) & 7; - uop_MMX_ENTER(ir); - codegen_mark_code_present(block, cs+op_pc, 1); - if ((fetchdat & 0xc0) == 0xc0) - { - int src_reg = fetchdat & 7; - uop_PFRCP(ir, IREG_MM(dest_reg), IREG_MM(src_reg)); - } - else - { - x86seg *target_seg; + uop_MMX_ENTER(ir); + codegen_mark_code_present(block, cs + op_pc, 1); + if ((fetchdat & 0xc0) == 0xc0) { + int src_reg = fetchdat & 7; + uop_PFRCP(ir, IREG_MM(dest_reg), IREG_MM(src_reg)); + } else { + x86seg *target_seg; - uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc); - target_seg = codegen_generate_ea(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32, 0); - codegen_check_seg_read(block, ir, target_seg); - uop_MEM_LOAD_REG(ir, IREG_temp0_Q, ireg_seg_base(target_seg), IREG_eaaddr); - uop_PFRCP(ir, IREG_MM(dest_reg), IREG_temp0_Q); - } + uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc); + target_seg = codegen_generate_ea(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32, 0); + codegen_check_seg_read(block, ir, target_seg); + uop_MEM_LOAD_REG(ir, IREG_temp0_Q, ireg_seg_base(target_seg), IREG_eaaddr); + uop_PFRCP(ir, IREG_MM(dest_reg), IREG_temp0_Q); + } - codegen_mark_code_present(block, cs+op_pc+1, 1); - return op_pc + 2; + codegen_mark_code_present(block, cs + op_pc + 1, 1); + return op_pc + 2; } -uint32_t ropPFRSQRT(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) +uint32_t +ropPFRSQRT(codeblock_t *block, ir_data_t *ir, UNUSED(uint8_t opcode), uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) { - int dest_reg = (fetchdat >> 3) & 7; + int dest_reg = (fetchdat >> 3) & 7; - uop_MMX_ENTER(ir); - codegen_mark_code_present(block, cs+op_pc, 1); - if ((fetchdat & 0xc0) == 0xc0) - { - int src_reg = fetchdat & 7; - uop_PFRSQRT(ir, IREG_MM(dest_reg), IREG_MM(src_reg)); - } - else - { - x86seg *target_seg; + uop_MMX_ENTER(ir); + codegen_mark_code_present(block, cs + op_pc, 1); + if ((fetchdat & 0xc0) == 0xc0) { + int src_reg = fetchdat & 7; + uop_PFRSQRT(ir, IREG_MM(dest_reg), IREG_MM(src_reg)); + } else { + x86seg *target_seg; - uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc); - target_seg = codegen_generate_ea(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32, 0); - codegen_check_seg_read(block, ir, target_seg); - uop_MEM_LOAD_REG(ir, IREG_temp0_Q, ireg_seg_base(target_seg), IREG_eaaddr); - uop_PFRSQRT(ir, IREG_MM(dest_reg), IREG_temp0_Q); - } + uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc); + target_seg = codegen_generate_ea(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32, 0); + codegen_check_seg_read(block, ir, target_seg); + uop_MEM_LOAD_REG(ir, IREG_temp0_Q, ireg_seg_base(target_seg), IREG_eaaddr); + uop_PFRSQRT(ir, IREG_MM(dest_reg), IREG_temp0_Q); + } - codegen_mark_code_present(block, cs+op_pc+1, 1); - return op_pc + 2; + codegen_mark_code_present(block, cs + op_pc + 1, 1); + return op_pc + 2; } -uint32_t ropPFRSQIT1(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) +uint32_t +ropPFRSQIT1(codeblock_t *block, ir_data_t *ir, UNUSED(uint8_t opcode), uint32_t fetchdat, UNUSED(uint32_t op_32), uint32_t op_pc) { - uop_MMX_ENTER(ir); + uop_MMX_ENTER(ir); - codegen_mark_code_present(block, cs+op_pc, 2); - return op_pc + 2; + codegen_mark_code_present(block, cs + op_pc, 2); + return op_pc + 2; } diff --git a/src/codegen_new/codegen_ops_arith.c b/src/codegen_new/codegen_ops_arith.c index 576cf7719..9e136ace5 100644 --- a/src/codegen_new/codegen_ops_arith.c +++ b/src/codegen_new/codegen_ops_arith.c @@ -2,9 +2,12 @@ #include <86box/86box.h> #include "cpu.h" #include <86box/mem.h> +#include <86box/plat_unused.h> #include "x86.h" #include "x86_flags.h" +#include "x86seg_common.h" +#include "x86seg.h" #include "386_common.h" #include "codegen.h" #include "codegen_ir.h" @@ -12,2509 +15,2381 @@ #include "codegen_ops_arith.h" #include "codegen_ops_helpers.h" -static inline void get_cf(ir_data_t *ir, int dest_reg) +static inline void +get_cf(ir_data_t *ir, int dest_reg) { - uop_CALL_FUNC_RESULT(ir, dest_reg, CF_SET); + uop_CALL_FUNC_RESULT(ir, dest_reg, CF_SET); } -uint32_t ropADC_AL_imm(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) +uint32_t +ropADC_AL_imm(codeblock_t *block, ir_data_t *ir, UNUSED(uint8_t opcode), uint32_t fetchdat, UNUSED(uint32_t op_32), uint32_t op_pc) { - uint8_t imm_data = fastreadb(cs + op_pc); + uint8_t imm_data = fastreadb(cs + op_pc); - get_cf(ir, IREG_temp0); - uop_MOVZX(ir, IREG_flags_op1, IREG_AL); - uop_ADD_IMM(ir, IREG_AL, IREG_AL, imm_data); - uop_MOV_IMM(ir, IREG_flags_op2, imm_data); - uop_ADD(ir, IREG_AL, IREG_AL, IREG_temp0_B); - uop_MOV_IMM(ir, IREG_flags_op, FLAGS_ADC8); - uop_MOVZX(ir, IREG_flags_res, IREG_AL); + get_cf(ir, IREG_temp0); + uop_MOVZX(ir, IREG_flags_op1, IREG_AL); + uop_ADD_IMM(ir, IREG_AL, IREG_AL, imm_data); + uop_MOV_IMM(ir, IREG_flags_op2, imm_data); + uop_ADD(ir, IREG_AL, IREG_AL, IREG_temp0_B); + uop_MOV_IMM(ir, IREG_flags_op, FLAGS_ADC8); + uop_MOVZX(ir, IREG_flags_res, IREG_AL); - codegen_flags_changed = 1; - codegen_mark_code_present(block, cs+op_pc, 1); - return op_pc + 1; + codegen_flags_changed = 1; + codegen_mark_code_present(block, cs + op_pc, 1); + return op_pc + 1; } -uint32_t ropADC_AX_imm(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) +uint32_t +ropADC_AX_imm(codeblock_t *block, ir_data_t *ir, UNUSED(uint8_t opcode), uint32_t fetchdat, UNUSED(uint32_t op_32), uint32_t op_pc) { - uint16_t imm_data = fastreadw(cs + op_pc); + uint16_t imm_data = fastreadw(cs + op_pc); - get_cf(ir, IREG_temp0); - uop_MOVZX(ir, IREG_flags_op1, IREG_AX); - uop_ADD_IMM(ir, IREG_AX, IREG_AX, imm_data); - uop_MOV_IMM(ir, IREG_flags_op2, imm_data); - uop_ADD(ir, IREG_AX, IREG_AX, IREG_temp0_W); - uop_MOV_IMM(ir, IREG_flags_op, FLAGS_ADC16); - uop_MOVZX(ir, IREG_flags_res, IREG_AX); + get_cf(ir, IREG_temp0); + uop_MOVZX(ir, IREG_flags_op1, IREG_AX); + uop_ADD_IMM(ir, IREG_AX, IREG_AX, imm_data); + uop_MOV_IMM(ir, IREG_flags_op2, imm_data); + uop_ADD(ir, IREG_AX, IREG_AX, IREG_temp0_W); + uop_MOV_IMM(ir, IREG_flags_op, FLAGS_ADC16); + uop_MOVZX(ir, IREG_flags_res, IREG_AX); - codegen_flags_changed = 1; - codegen_mark_code_present(block, cs+op_pc, 2); - return op_pc + 2; + codegen_flags_changed = 1; + codegen_mark_code_present(block, cs + op_pc, 2); + return op_pc + 2; } -uint32_t ropADC_EAX_imm(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) +uint32_t +ropADC_EAX_imm(codeblock_t *block, ir_data_t *ir, UNUSED(uint8_t opcode), uint32_t fetchdat, UNUSED(uint32_t op_32), uint32_t op_pc) { + fetchdat = fastreadl(cs + op_pc); + + get_cf(ir, IREG_temp0); + uop_MOV(ir, IREG_flags_op1, IREG_EAX); + uop_ADD_IMM(ir, IREG_EAX, IREG_EAX, fetchdat); + uop_MOV_IMM(ir, IREG_flags_op2, fetchdat); + uop_ADD(ir, IREG_EAX, IREG_EAX, IREG_temp0); + uop_MOV_IMM(ir, IREG_flags_op, FLAGS_ADC32); + uop_MOV(ir, IREG_flags_res, IREG_EAX); + + codegen_flags_changed = 1; + codegen_mark_code_present(block, cs + op_pc, 4); + return op_pc + 4; +} +uint32_t +ropADC_b_rm(codeblock_t *block, ir_data_t *ir, UNUSED(uint8_t opcode), uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) +{ + int dest_reg = (fetchdat >> 3) & 7; + + codegen_mark_code_present(block, cs + op_pc, 1); + get_cf(ir, IREG_temp1); + if ((fetchdat & 0xc0) == 0xc0) { + int src_reg = fetchdat & 7; + + uop_MOVZX(ir, IREG_flags_op1, IREG_8(dest_reg)); + uop_MOVZX(ir, IREG_flags_op2, IREG_8(src_reg)); + uop_ADD(ir, IREG_8(dest_reg), IREG_8(dest_reg), IREG_8(src_reg)); + } else { + x86seg *target_seg; + + uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc); + target_seg = codegen_generate_ea(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32, 0); + codegen_check_seg_read(block, ir, target_seg); + uop_MEM_LOAD_REG(ir, IREG_temp0_B, ireg_seg_base(target_seg), IREG_eaaddr); + uop_MOVZX(ir, IREG_flags_op1, IREG_8(dest_reg)); + uop_MOVZX(ir, IREG_flags_op2, IREG_temp0_B); + uop_ADD(ir, IREG_8(dest_reg), IREG_8(dest_reg), IREG_temp0_B); + } + + uop_ADD(ir, IREG_8(dest_reg), IREG_8(dest_reg), IREG_temp1_B); + uop_MOV_IMM(ir, IREG_flags_op, FLAGS_ADC8); + uop_MOVZX(ir, IREG_flags_res, IREG_8(dest_reg)); + + codegen_flags_changed = 1; + return op_pc + 1; +} +uint32_t +ropADC_b_rmw(codeblock_t *block, ir_data_t *ir, UNUSED(uint8_t opcode), uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) +{ + int src_reg = (fetchdat >> 3) & 7; + + codegen_mark_code_present(block, cs + op_pc, 1); + get_cf(ir, IREG_temp1); + if ((fetchdat & 0xc0) == 0xc0) { + int dest_reg = fetchdat & 7; + + uop_MOVZX(ir, IREG_flags_op1, IREG_8(dest_reg)); + uop_MOVZX(ir, IREG_flags_op2, IREG_8(src_reg)); + uop_ADD(ir, IREG_8(dest_reg), IREG_8(dest_reg), IREG_8(src_reg)); + uop_ADD(ir, IREG_8(dest_reg), IREG_8(dest_reg), IREG_temp1_B); + uop_MOVZX(ir, IREG_flags_res, IREG_8(dest_reg)); + } else { + x86seg *target_seg; + + uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc); + target_seg = codegen_generate_ea(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32, 0); + codegen_check_seg_write(block, ir, target_seg); + + uop_MEM_LOAD_REG(ir, IREG_temp0_B, ireg_seg_base(target_seg), IREG_eaaddr); + uop_ADD(ir, IREG_temp2_B, IREG_temp0_B, IREG_8(src_reg)); + uop_ADD(ir, IREG_temp2_B, IREG_temp2_B, IREG_temp1_B); + uop_MEM_STORE_REG(ir, ireg_seg_base(target_seg), IREG_eaaddr, IREG_temp2_B); + uop_MOVZX(ir, IREG_flags_op1, IREG_temp0_B); + uop_MOVZX(ir, IREG_flags_op2, IREG_8(src_reg)); + uop_MOVZX(ir, IREG_flags_res, IREG_temp2_B); + } + uop_MOV_IMM(ir, IREG_flags_op, FLAGS_ADC8); + + codegen_flags_changed = 1; + return op_pc + 1; +} +uint32_t +ropADC_w_rm(codeblock_t *block, ir_data_t *ir, UNUSED(uint8_t opcode), uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) +{ + int dest_reg = (fetchdat >> 3) & 7; + + codegen_mark_code_present(block, cs + op_pc, 1); + get_cf(ir, IREG_temp1); + if ((fetchdat & 0xc0) == 0xc0) { + int src_reg = fetchdat & 7; + + uop_MOVZX(ir, IREG_flags_op1, IREG_16(dest_reg)); + uop_MOVZX(ir, IREG_flags_op2, IREG_16(src_reg)); + uop_ADD(ir, IREG_16(dest_reg), IREG_16(dest_reg), IREG_16(src_reg)); + } else { + x86seg *target_seg; + + uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc); + target_seg = codegen_generate_ea(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32, 0); + codegen_check_seg_read(block, ir, target_seg); + uop_MEM_LOAD_REG(ir, IREG_temp0_W, ireg_seg_base(target_seg), IREG_eaaddr); + uop_MOVZX(ir, IREG_flags_op1, IREG_16(dest_reg)); + uop_MOVZX(ir, IREG_flags_op2, IREG_temp0_W); + uop_ADD(ir, IREG_16(dest_reg), IREG_16(dest_reg), IREG_temp0_W); + } + + uop_ADD(ir, IREG_16(dest_reg), IREG_16(dest_reg), IREG_temp1_W); + uop_MOV_IMM(ir, IREG_flags_op, FLAGS_ADC16); + uop_MOVZX(ir, IREG_flags_res, IREG_16(dest_reg)); + + codegen_flags_changed = 1; + return op_pc + 1; +} +uint32_t +ropADC_w_rmw(codeblock_t *block, ir_data_t *ir, UNUSED(uint8_t opcode), uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) +{ + int src_reg = (fetchdat >> 3) & 7; + + codegen_mark_code_present(block, cs + op_pc, 1); + get_cf(ir, IREG_temp1); + if ((fetchdat & 0xc0) == 0xc0) { + int dest_reg = fetchdat & 7; + + uop_MOVZX(ir, IREG_flags_op1, IREG_16(dest_reg)); + uop_MOVZX(ir, IREG_flags_op2, IREG_16(src_reg)); + uop_ADD(ir, IREG_16(dest_reg), IREG_16(dest_reg), IREG_16(src_reg)); + uop_ADD(ir, IREG_16(dest_reg), IREG_16(dest_reg), IREG_temp1_W); + uop_MOVZX(ir, IREG_flags_res, IREG_16(dest_reg)); + } else { + x86seg *target_seg; + + uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc); + target_seg = codegen_generate_ea(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32, 0); + codegen_check_seg_write(block, ir, target_seg); + + uop_MEM_LOAD_REG(ir, IREG_temp0_W, ireg_seg_base(target_seg), IREG_eaaddr); + uop_ADD(ir, IREG_temp2_W, IREG_temp0_W, IREG_16(src_reg)); + uop_ADD(ir, IREG_temp2_W, IREG_temp2_W, IREG_temp1_W); + uop_MEM_STORE_REG(ir, ireg_seg_base(target_seg), IREG_eaaddr, IREG_temp2_W); + uop_MOVZX(ir, IREG_flags_op1, IREG_temp0_W); + uop_MOVZX(ir, IREG_flags_op2, IREG_16(src_reg)); + uop_MOVZX(ir, IREG_flags_res, IREG_temp2_W); + } + uop_MOV_IMM(ir, IREG_flags_op, FLAGS_ADC16); + + codegen_flags_changed = 1; + return op_pc + 1; +} +uint32_t +ropADC_l_rm(codeblock_t *block, ir_data_t *ir, UNUSED(uint8_t opcode), uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) +{ + int dest_reg = (fetchdat >> 3) & 7; + + codegen_mark_code_present(block, cs + op_pc, 1); + get_cf(ir, IREG_temp1); + if ((fetchdat & 0xc0) == 0xc0) { + int src_reg = fetchdat & 7; + + uop_MOV(ir, IREG_flags_op1, IREG_32(dest_reg)); + uop_MOV(ir, IREG_flags_op2, IREG_32(src_reg)); + uop_ADD(ir, IREG_32(dest_reg), IREG_32(dest_reg), IREG_32(src_reg)); + } else { + x86seg *target_seg; + + uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc); + target_seg = codegen_generate_ea(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32, 0); + codegen_check_seg_read(block, ir, target_seg); + uop_MEM_LOAD_REG(ir, IREG_flags_op2, ireg_seg_base(target_seg), IREG_eaaddr); + uop_MOV(ir, IREG_flags_op1, IREG_32(dest_reg)); + uop_ADD(ir, IREG_32(dest_reg), IREG_32(dest_reg), IREG_flags_op2); + } + + uop_ADD(ir, IREG_32(dest_reg), IREG_32(dest_reg), IREG_temp1); + uop_MOV_IMM(ir, IREG_flags_op, FLAGS_ADC32); + uop_MOV(ir, IREG_flags_res, IREG_32(dest_reg)); + + codegen_flags_changed = 1; + return op_pc + 1; +} +uint32_t +ropADC_l_rmw(codeblock_t *block, ir_data_t *ir, UNUSED(uint8_t opcode), uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) +{ + int src_reg = (fetchdat >> 3) & 7; + + codegen_mark_code_present(block, cs + op_pc, 1); + get_cf(ir, IREG_temp1); + if ((fetchdat & 0xc0) == 0xc0) { + int dest_reg = fetchdat & 7; + + uop_MOV(ir, IREG_flags_op1, IREG_32(dest_reg)); + uop_MOV(ir, IREG_flags_op2, IREG_32(src_reg)); + uop_ADD(ir, IREG_32(dest_reg), IREG_32(dest_reg), IREG_32(src_reg)); + uop_ADD(ir, IREG_32(dest_reg), IREG_32(dest_reg), IREG_temp1); + uop_MOV(ir, IREG_flags_res, IREG_32(dest_reg)); + } else { + x86seg *target_seg; + + uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc); + target_seg = codegen_generate_ea(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32, 0); + codegen_check_seg_write(block, ir, target_seg); + + uop_MEM_LOAD_REG(ir, IREG_temp0, ireg_seg_base(target_seg), IREG_eaaddr); + uop_ADD(ir, IREG_temp2, IREG_temp0, IREG_32(src_reg)); + uop_ADD(ir, IREG_temp2, IREG_temp2, IREG_temp1); + uop_MEM_STORE_REG(ir, ireg_seg_base(target_seg), IREG_eaaddr, IREG_temp2); + uop_MOV(ir, IREG_flags_op1, IREG_temp0); + uop_MOV(ir, IREG_flags_op2, IREG_32(src_reg)); + uop_MOV(ir, IREG_flags_res, IREG_temp2); + } + uop_MOV_IMM(ir, IREG_flags_op, FLAGS_ADC32); + + codegen_flags_changed = 1; + return op_pc + 1; +} + +uint32_t +ropADD_AL_imm(codeblock_t *block, ir_data_t *ir, UNUSED(uint8_t opcode), uint32_t fetchdat, UNUSED(uint32_t op_32), uint32_t op_pc) +{ + uint8_t imm_data = fastreadb(cs + op_pc); + + uop_MOVZX(ir, IREG_flags_op1, IREG_AL); + uop_ADD_IMM(ir, IREG_AL, IREG_AL, imm_data); + uop_MOV_IMM(ir, IREG_flags_op2, imm_data); + uop_MOV_IMM(ir, IREG_flags_op, FLAGS_ADD8); + uop_MOVZX(ir, IREG_flags_res, IREG_AL); + + codegen_flags_changed = 1; + codegen_mark_code_present(block, cs + op_pc, 1); + return op_pc + 1; +} +uint32_t +ropADD_AX_imm(codeblock_t *block, ir_data_t *ir, UNUSED(uint8_t opcode), uint32_t fetchdat, UNUSED(uint32_t op_32), uint32_t op_pc) +{ + uint16_t imm_data = fastreadw(cs + op_pc); + + uop_MOVZX(ir, IREG_flags_op1, IREG_AX); + uop_ADD_IMM(ir, IREG_AX, IREG_AX, imm_data); + uop_MOV_IMM(ir, IREG_flags_op2, imm_data); + uop_MOV_IMM(ir, IREG_flags_op, FLAGS_ADD16); + uop_MOVZX(ir, IREG_flags_res, IREG_AX); + + codegen_flags_changed = 1; + codegen_mark_code_present(block, cs + op_pc, 2); + return op_pc + 2; +} +uint32_t +ropADD_EAX_imm(codeblock_t *block, ir_data_t *ir, UNUSED(uint8_t opcode), uint32_t fetchdat, UNUSED(uint32_t op_32), uint32_t op_pc) +{ + uop_MOV(ir, IREG_flags_op1, IREG_EAX); + + if (block->flags & CODEBLOCK_NO_IMMEDIATES) { + LOAD_IMMEDIATE_FROM_RAM_32(block, ir, IREG_temp0, cs + op_pc); + uop_ADD(ir, IREG_EAX, IREG_EAX, IREG_temp0); + uop_MOV(ir, IREG_flags_op2, IREG_temp0); + } else { fetchdat = fastreadl(cs + op_pc); - - get_cf(ir, IREG_temp0); - uop_MOV(ir, IREG_flags_op1, IREG_EAX); uop_ADD_IMM(ir, IREG_EAX, IREG_EAX, fetchdat); uop_MOV_IMM(ir, IREG_flags_op2, fetchdat); - uop_ADD(ir, IREG_EAX, IREG_EAX, IREG_temp0); - uop_MOV_IMM(ir, IREG_flags_op, FLAGS_ADC32); - uop_MOV(ir, IREG_flags_res, IREG_EAX); + codegen_mark_code_present(block, cs + op_pc, 4); + } - codegen_flags_changed = 1; - codegen_mark_code_present(block, cs+op_pc, 4); - return op_pc + 4; + uop_MOV_IMM(ir, IREG_flags_op, FLAGS_ADD32); + uop_MOV(ir, IREG_flags_res, IREG_EAX); + codegen_flags_changed = 1; + return op_pc + 4; } -uint32_t ropADC_b_rm(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) +uint32_t +ropADD_b_rm(codeblock_t *block, ir_data_t *ir, UNUSED(uint8_t opcode), uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) { - int dest_reg = (fetchdat >> 3) & 7; + int dest_reg = (fetchdat >> 3) & 7; - codegen_mark_code_present(block, cs+op_pc, 1); - get_cf(ir, IREG_temp1); - if ((fetchdat & 0xc0) == 0xc0) - { - int src_reg = fetchdat & 7; + codegen_mark_code_present(block, cs + op_pc, 1); + if ((fetchdat & 0xc0) == 0xc0) { + int src_reg = fetchdat & 7; - uop_MOVZX(ir, IREG_flags_op1, IREG_8(dest_reg)); - uop_MOVZX(ir, IREG_flags_op2, IREG_8(src_reg)); - uop_ADD(ir, IREG_8(dest_reg), IREG_8(dest_reg), IREG_8(src_reg)); - } - else - { - x86seg *target_seg; + uop_MOVZX(ir, IREG_flags_op1, IREG_8(dest_reg)); + uop_MOVZX(ir, IREG_flags_op2, IREG_8(src_reg)); + uop_ADD(ir, IREG_8(dest_reg), IREG_8(dest_reg), IREG_8(src_reg)); + } else { + x86seg *target_seg; - uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc); - target_seg = codegen_generate_ea(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32, 0); - codegen_check_seg_read(block, ir, target_seg); - uop_MEM_LOAD_REG(ir, IREG_temp0_B, ireg_seg_base(target_seg), IREG_eaaddr); - uop_MOVZX(ir, IREG_flags_op1, IREG_8(dest_reg)); - uop_MOVZX(ir, IREG_flags_op2, IREG_temp0_B); - uop_ADD(ir, IREG_8(dest_reg), IREG_8(dest_reg), IREG_temp0_B); - } + uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc); + target_seg = codegen_generate_ea(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32, 0); + codegen_check_seg_read(block, ir, target_seg); + uop_MEM_LOAD_REG(ir, IREG_temp0_B, ireg_seg_base(target_seg), IREG_eaaddr); + uop_MOVZX(ir, IREG_flags_op1, IREG_8(dest_reg)); + uop_MOVZX(ir, IREG_flags_op2, IREG_temp0_B); + uop_ADD(ir, IREG_8(dest_reg), IREG_8(dest_reg), IREG_temp0_B); + } - uop_ADD(ir, IREG_8(dest_reg), IREG_8(dest_reg), IREG_temp1_B); - uop_MOV_IMM(ir, IREG_flags_op, FLAGS_ADC8); + uop_MOV_IMM(ir, IREG_flags_op, FLAGS_ADD8); + uop_MOVZX(ir, IREG_flags_res, IREG_8(dest_reg)); + + codegen_flags_changed = 1; + return op_pc + 1; +} +uint32_t +ropADD_b_rmw(codeblock_t *block, ir_data_t *ir, UNUSED(uint8_t opcode), uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) +{ + int src_reg = (fetchdat >> 3) & 7; + + codegen_mark_code_present(block, cs + op_pc, 1); + if ((fetchdat & 0xc0) == 0xc0) { + int dest_reg = fetchdat & 7; + + uop_MOVZX(ir, IREG_flags_op1, IREG_8(dest_reg)); + uop_MOVZX(ir, IREG_flags_op2, IREG_8(src_reg)); + uop_ADD(ir, IREG_8(dest_reg), IREG_8(dest_reg), IREG_8(src_reg)); uop_MOVZX(ir, IREG_flags_res, IREG_8(dest_reg)); + } else { + x86seg *target_seg; - codegen_flags_changed = 1; - return op_pc + 1; + uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc); + target_seg = codegen_generate_ea(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32, 0); + codegen_check_seg_write(block, ir, target_seg); + + uop_MEM_LOAD_REG(ir, IREG_temp0_B, ireg_seg_base(target_seg), IREG_eaaddr); + uop_ADD(ir, IREG_temp1_B, IREG_temp0_B, IREG_8(src_reg)); + uop_MEM_STORE_REG(ir, ireg_seg_base(target_seg), IREG_eaaddr, IREG_temp1_B); + uop_MOVZX(ir, IREG_flags_op1, IREG_temp0_B); + uop_MOVZX(ir, IREG_flags_op2, IREG_8(src_reg)); + uop_MOVZX(ir, IREG_flags_res, IREG_temp1_B); + } + uop_MOV_IMM(ir, IREG_flags_op, FLAGS_ADD8); + + codegen_flags_changed = 1; + return op_pc + 1; } -uint32_t ropADC_b_rmw(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) +uint32_t +ropADD_w_rm(codeblock_t *block, ir_data_t *ir, UNUSED(uint8_t opcode), uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) { - int src_reg = (fetchdat >> 3) & 7; + int dest_reg = (fetchdat >> 3) & 7; - codegen_mark_code_present(block, cs+op_pc, 1); - get_cf(ir, IREG_temp1); - if ((fetchdat & 0xc0) == 0xc0) - { - int dest_reg = fetchdat & 7; + codegen_mark_code_present(block, cs + op_pc, 1); + if ((fetchdat & 0xc0) == 0xc0) { + int src_reg = fetchdat & 7; - uop_MOVZX(ir, IREG_flags_op1, IREG_8(dest_reg)); - uop_MOVZX(ir, IREG_flags_op2, IREG_8(src_reg)); - uop_ADD(ir, IREG_8(dest_reg), IREG_8(dest_reg), IREG_8(src_reg)); - uop_ADD(ir, IREG_8(dest_reg), IREG_8(dest_reg), IREG_temp1_B); - uop_MOVZX(ir, IREG_flags_res, IREG_8(dest_reg)); - } - else - { - x86seg *target_seg; + uop_MOVZX(ir, IREG_flags_op1, IREG_16(dest_reg)); + uop_MOVZX(ir, IREG_flags_op2, IREG_16(src_reg)); + uop_ADD(ir, IREG_16(dest_reg), IREG_16(dest_reg), IREG_16(src_reg)); + } else { + x86seg *target_seg; - uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc); - target_seg = codegen_generate_ea(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32, 0); - codegen_check_seg_write(block, ir, target_seg); + uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc); + target_seg = codegen_generate_ea(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32, 0); + codegen_check_seg_read(block, ir, target_seg); + uop_MEM_LOAD_REG(ir, IREG_temp0_W, ireg_seg_base(target_seg), IREG_eaaddr); + uop_MOVZX(ir, IREG_flags_op1, IREG_16(dest_reg)); + uop_MOVZX(ir, IREG_flags_op2, IREG_temp0_W); + uop_ADD(ir, IREG_16(dest_reg), IREG_16(dest_reg), IREG_temp0_W); + } - uop_MEM_LOAD_REG(ir, IREG_temp0_B, ireg_seg_base(target_seg), IREG_eaaddr); - uop_ADD(ir, IREG_temp2_B, IREG_temp0_B, IREG_8(src_reg)); - uop_ADD(ir, IREG_temp2_B, IREG_temp2_B, IREG_temp1_B); - uop_MEM_STORE_REG(ir, ireg_seg_base(target_seg), IREG_eaaddr, IREG_temp2_B); - uop_MOVZX(ir, IREG_flags_op1, IREG_temp0_B); - uop_MOVZX(ir, IREG_flags_op2, IREG_8(src_reg)); - uop_MOVZX(ir, IREG_flags_res, IREG_temp2_B); - } - uop_MOV_IMM(ir, IREG_flags_op, FLAGS_ADC8); + uop_MOV_IMM(ir, IREG_flags_op, FLAGS_ADD16); + uop_MOVZX(ir, IREG_flags_res, IREG_16(dest_reg)); - codegen_flags_changed = 1; - return op_pc + 1; + codegen_flags_changed = 1; + return op_pc + 1; } -uint32_t ropADC_w_rm(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) +uint32_t +ropADD_w_rmw(codeblock_t *block, ir_data_t *ir, UNUSED(uint8_t opcode), uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) { - int dest_reg = (fetchdat >> 3) & 7; + int src_reg = (fetchdat >> 3) & 7; - codegen_mark_code_present(block, cs+op_pc, 1); - get_cf(ir, IREG_temp1); - if ((fetchdat & 0xc0) == 0xc0) - { - int src_reg = fetchdat & 7; + codegen_mark_code_present(block, cs + op_pc, 1); + if ((fetchdat & 0xc0) == 0xc0) { + int dest_reg = fetchdat & 7; - uop_MOVZX(ir, IREG_flags_op1, IREG_16(dest_reg)); - uop_MOVZX(ir, IREG_flags_op2, IREG_16(src_reg)); - uop_ADD(ir, IREG_16(dest_reg), IREG_16(dest_reg), IREG_16(src_reg)); - } - else - { - x86seg *target_seg; - - uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc); - target_seg = codegen_generate_ea(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32, 0); - codegen_check_seg_read(block, ir, target_seg); - uop_MEM_LOAD_REG(ir, IREG_temp0_W, ireg_seg_base(target_seg), IREG_eaaddr); - uop_MOVZX(ir, IREG_flags_op1, IREG_16(dest_reg)); - uop_MOVZX(ir, IREG_flags_op2, IREG_temp0_W); - uop_ADD(ir, IREG_16(dest_reg), IREG_16(dest_reg), IREG_temp0_W); - } - - uop_ADD(ir, IREG_16(dest_reg), IREG_16(dest_reg), IREG_temp1_W); - uop_MOV_IMM(ir, IREG_flags_op, FLAGS_ADC16); + uop_MOVZX(ir, IREG_flags_op1, IREG_16(dest_reg)); + uop_MOVZX(ir, IREG_flags_op2, IREG_16(src_reg)); + uop_ADD(ir, IREG_16(dest_reg), IREG_16(dest_reg), IREG_16(src_reg)); uop_MOVZX(ir, IREG_flags_res, IREG_16(dest_reg)); + } else { + x86seg *target_seg; - codegen_flags_changed = 1; - return op_pc + 1; + uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc); + target_seg = codegen_generate_ea(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32, 0); + codegen_check_seg_write(block, ir, target_seg); + + uop_MEM_LOAD_REG(ir, IREG_temp0_W, ireg_seg_base(target_seg), IREG_eaaddr); + uop_ADD(ir, IREG_temp1_W, IREG_temp0_W, IREG_16(src_reg)); + uop_MEM_STORE_REG(ir, ireg_seg_base(target_seg), IREG_eaaddr, IREG_temp1_W); + uop_MOVZX(ir, IREG_flags_op1, IREG_temp0_W); + uop_MOVZX(ir, IREG_flags_op2, IREG_16(src_reg)); + uop_MOVZX(ir, IREG_flags_res, IREG_temp1_W); + } + uop_MOV_IMM(ir, IREG_flags_op, FLAGS_ADD16); + + codegen_flags_changed = 1; + return op_pc + 1; } -uint32_t ropADC_w_rmw(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) +uint32_t +ropADD_l_rm(codeblock_t *block, ir_data_t *ir, UNUSED(uint8_t opcode), uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) { - int src_reg = (fetchdat >> 3) & 7; + int dest_reg = (fetchdat >> 3) & 7; - codegen_mark_code_present(block, cs+op_pc, 1); - get_cf(ir, IREG_temp1); - if ((fetchdat & 0xc0) == 0xc0) - { - int dest_reg = fetchdat & 7; + codegen_mark_code_present(block, cs + op_pc, 1); + if ((fetchdat & 0xc0) == 0xc0) { + int src_reg = fetchdat & 7; - uop_MOVZX(ir, IREG_flags_op1, IREG_16(dest_reg)); - uop_MOVZX(ir, IREG_flags_op2, IREG_16(src_reg)); - uop_ADD(ir, IREG_16(dest_reg), IREG_16(dest_reg), IREG_16(src_reg)); - uop_ADD(ir, IREG_16(dest_reg), IREG_16(dest_reg), IREG_temp1_W); - uop_MOVZX(ir, IREG_flags_res, IREG_16(dest_reg)); - } - else - { - x86seg *target_seg; + uop_MOV(ir, IREG_flags_op1, IREG_32(dest_reg)); + uop_MOV(ir, IREG_flags_op2, IREG_32(src_reg)); + uop_ADD(ir, IREG_32(dest_reg), IREG_32(dest_reg), IREG_32(src_reg)); + } else { + x86seg *target_seg; - uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc); - target_seg = codegen_generate_ea(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32, 0); - codegen_check_seg_write(block, ir, target_seg); + uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc); + target_seg = codegen_generate_ea(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32, 0); + codegen_check_seg_read(block, ir, target_seg); + uop_MEM_LOAD_REG(ir, IREG_flags_op2, ireg_seg_base(target_seg), IREG_eaaddr); + uop_MOV(ir, IREG_flags_op1, IREG_32(dest_reg)); + uop_ADD(ir, IREG_32(dest_reg), IREG_32(dest_reg), IREG_flags_op2); + } - uop_MEM_LOAD_REG(ir, IREG_temp0_W, ireg_seg_base(target_seg), IREG_eaaddr); - uop_ADD(ir, IREG_temp2_W, IREG_temp0_W, IREG_16(src_reg)); - uop_ADD(ir, IREG_temp2_W, IREG_temp2_W, IREG_temp1_W); - uop_MEM_STORE_REG(ir, ireg_seg_base(target_seg), IREG_eaaddr, IREG_temp2_W); - uop_MOVZX(ir, IREG_flags_op1, IREG_temp0_W); - uop_MOVZX(ir, IREG_flags_op2, IREG_16(src_reg)); - uop_MOVZX(ir, IREG_flags_res, IREG_temp2_W); - } - uop_MOV_IMM(ir, IREG_flags_op, FLAGS_ADC16); + uop_MOV_IMM(ir, IREG_flags_op, FLAGS_ADD32); + uop_MOV(ir, IREG_flags_res, IREG_32(dest_reg)); - codegen_flags_changed = 1; - return op_pc + 1; + codegen_flags_changed = 1; + return op_pc + 1; } -uint32_t ropADC_l_rm(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) +uint32_t +ropADD_l_rmw(codeblock_t *block, ir_data_t *ir, UNUSED(uint8_t opcode), uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) { - int dest_reg = (fetchdat >> 3) & 7; + int src_reg = (fetchdat >> 3) & 7; - codegen_mark_code_present(block, cs+op_pc, 1); - get_cf(ir, IREG_temp1); - if ((fetchdat & 0xc0) == 0xc0) - { - int src_reg = fetchdat & 7; + codegen_mark_code_present(block, cs + op_pc, 1); + if ((fetchdat & 0xc0) == 0xc0) { + int dest_reg = fetchdat & 7; - uop_MOV(ir, IREG_flags_op1, IREG_32(dest_reg)); - uop_MOV(ir, IREG_flags_op2, IREG_32(src_reg)); - uop_ADD(ir, IREG_32(dest_reg), IREG_32(dest_reg), IREG_32(src_reg)); - } - else - { - x86seg *target_seg; - - uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc); - target_seg = codegen_generate_ea(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32, 0); - codegen_check_seg_read(block, ir, target_seg); - uop_MEM_LOAD_REG(ir, IREG_flags_op2, ireg_seg_base(target_seg), IREG_eaaddr); - uop_MOV(ir, IREG_flags_op1, IREG_32(dest_reg)); - uop_ADD(ir, IREG_32(dest_reg), IREG_32(dest_reg), IREG_flags_op2); - } - - uop_ADD(ir, IREG_32(dest_reg), IREG_32(dest_reg), IREG_temp1); - uop_MOV_IMM(ir, IREG_flags_op, FLAGS_ADC32); + uop_MOV(ir, IREG_flags_op1, IREG_32(dest_reg)); + uop_MOV(ir, IREG_flags_op2, IREG_32(src_reg)); + uop_ADD(ir, IREG_32(dest_reg), IREG_32(dest_reg), IREG_32(src_reg)); uop_MOV(ir, IREG_flags_res, IREG_32(dest_reg)); + } else { + x86seg *target_seg; - codegen_flags_changed = 1; - return op_pc + 1; -} -uint32_t ropADC_l_rmw(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) -{ - int src_reg = (fetchdat >> 3) & 7; + uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc); + target_seg = codegen_generate_ea(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32, 0); + codegen_check_seg_write(block, ir, target_seg); - codegen_mark_code_present(block, cs+op_pc, 1); - get_cf(ir, IREG_temp1); - if ((fetchdat & 0xc0) == 0xc0) - { - int dest_reg = fetchdat & 7; + uop_MEM_LOAD_REG(ir, IREG_temp0, ireg_seg_base(target_seg), IREG_eaaddr); + uop_ADD(ir, IREG_temp1, IREG_temp0, IREG_32(src_reg)); + uop_MEM_STORE_REG(ir, ireg_seg_base(target_seg), IREG_eaaddr, IREG_temp1); + uop_MOV(ir, IREG_flags_op1, IREG_temp0); + uop_MOV(ir, IREG_flags_op2, IREG_32(src_reg)); + uop_MOV(ir, IREG_flags_res, IREG_temp1); + } + uop_MOV_IMM(ir, IREG_flags_op, FLAGS_ADD32); - uop_MOV(ir, IREG_flags_op1, IREG_32(dest_reg)); - uop_MOV(ir, IREG_flags_op2, IREG_32(src_reg)); - uop_ADD(ir, IREG_32(dest_reg), IREG_32(dest_reg), IREG_32(src_reg)); - uop_ADD(ir, IREG_32(dest_reg), IREG_32(dest_reg), IREG_temp1); - uop_MOV(ir, IREG_flags_res, IREG_32(dest_reg)); - } - else - { - x86seg *target_seg; - - uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc); - target_seg = codegen_generate_ea(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32, 0); - codegen_check_seg_write(block, ir, target_seg); - - uop_MEM_LOAD_REG(ir, IREG_temp0, ireg_seg_base(target_seg), IREG_eaaddr); - uop_ADD(ir, IREG_temp2, IREG_temp0, IREG_32(src_reg)); - uop_ADD(ir, IREG_temp2, IREG_temp2, IREG_temp1); - uop_MEM_STORE_REG(ir, ireg_seg_base(target_seg), IREG_eaaddr, IREG_temp2); - uop_MOV(ir, IREG_flags_op1, IREG_temp0); - uop_MOV(ir, IREG_flags_op2, IREG_32(src_reg)); - uop_MOV(ir, IREG_flags_res, IREG_temp2); - } - uop_MOV_IMM(ir, IREG_flags_op, FLAGS_ADC32); - - codegen_flags_changed = 1; - return op_pc + 1; + codegen_flags_changed = 1; + return op_pc + 1; } -uint32_t ropADD_AL_imm(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) +uint32_t +ropCMP_AL_imm(codeblock_t *block, ir_data_t *ir, UNUSED(uint8_t opcode), uint32_t fetchdat, UNUSED(uint32_t op_32), uint32_t op_pc) { - uint8_t imm_data = fastreadb(cs + op_pc); + uint8_t imm_data = fastreadb(cs + op_pc); - uop_MOVZX(ir, IREG_flags_op1, IREG_AL); - uop_ADD_IMM(ir, IREG_AL, IREG_AL, imm_data); - uop_MOV_IMM(ir, IREG_flags_op2, imm_data); - uop_MOV_IMM(ir, IREG_flags_op, FLAGS_ADD8); - uop_MOVZX(ir, IREG_flags_res, IREG_AL); + uop_MOVZX(ir, IREG_flags_op1, IREG_AL); + uop_SUB_IMM(ir, IREG_flags_res_B, IREG_AL, imm_data); + uop_MOVZX(ir, IREG_flags_res, IREG_flags_res_B); + uop_MOV_IMM(ir, IREG_flags_op2, imm_data); + uop_MOV_IMM(ir, IREG_flags_op, FLAGS_SUB8); - codegen_flags_changed = 1; - codegen_mark_code_present(block, cs+op_pc, 1); - return op_pc + 1; + codegen_flags_changed = 1; + codegen_mark_code_present(block, cs + op_pc, 1); + return op_pc + 1; } -uint32_t ropADD_AX_imm(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) +uint32_t +ropCMP_AX_imm(codeblock_t *block, ir_data_t *ir, UNUSED(uint8_t opcode), uint32_t fetchdat, UNUSED(uint32_t op_32), uint32_t op_pc) { - uint16_t imm_data = fastreadw(cs + op_pc); + uint16_t imm_data = fastreadw(cs + op_pc); - uop_MOVZX(ir, IREG_flags_op1, IREG_AX); - uop_ADD_IMM(ir, IREG_AX, IREG_AX, imm_data); - uop_MOV_IMM(ir, IREG_flags_op2, imm_data); - uop_MOV_IMM(ir, IREG_flags_op, FLAGS_ADD16); - uop_MOVZX(ir, IREG_flags_res, IREG_AX); + uop_MOVZX(ir, IREG_flags_op1, IREG_AX); + uop_SUB_IMM(ir, IREG_flags_res_W, IREG_AX, imm_data); + uop_MOVZX(ir, IREG_flags_res, IREG_flags_res_W); + uop_MOV_IMM(ir, IREG_flags_op2, imm_data); + uop_MOV_IMM(ir, IREG_flags_op, FLAGS_SUB16); - codegen_flags_changed = 1; - codegen_mark_code_present(block, cs+op_pc, 2); - return op_pc + 2; + codegen_flags_changed = 1; + codegen_mark_code_present(block, cs + op_pc, 2); + return op_pc + 2; } -uint32_t ropADD_EAX_imm(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) +uint32_t +ropCMP_EAX_imm(codeblock_t *block, ir_data_t *ir, UNUSED(uint8_t opcode), uint32_t fetchdat, UNUSED(uint32_t op_32), uint32_t op_pc) { - uop_MOV(ir, IREG_flags_op1, IREG_EAX); - - if (block->flags & CODEBLOCK_NO_IMMEDIATES) - { - LOAD_IMMEDIATE_FROM_RAM_32(block, ir, IREG_temp0, cs + op_pc); - uop_ADD(ir, IREG_EAX, IREG_EAX, IREG_temp0); - uop_MOV(ir, IREG_flags_op2, IREG_temp0); - } - else - { - fetchdat = fastreadl(cs + op_pc); - uop_ADD_IMM(ir, IREG_EAX, IREG_EAX, fetchdat); - uop_MOV_IMM(ir, IREG_flags_op2, fetchdat); - codegen_mark_code_present(block, cs+op_pc, 4); - } + fetchdat = fastreadl(cs + op_pc); - uop_MOV_IMM(ir, IREG_flags_op, FLAGS_ADD32); - uop_MOV(ir, IREG_flags_res, IREG_EAX); - codegen_flags_changed = 1; - return op_pc + 4; + uop_MOV(ir, IREG_flags_op1, IREG_EAX); + uop_SUB_IMM(ir, IREG_flags_res, IREG_EAX, fetchdat); + uop_MOV_IMM(ir, IREG_flags_op2, fetchdat); + uop_MOV_IMM(ir, IREG_flags_op, FLAGS_SUB32); + + codegen_flags_changed = 1; + codegen_mark_code_present(block, cs + op_pc, 4); + return op_pc + 4; } -uint32_t ropADD_b_rm(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) +uint32_t +ropCMP_b_rm(codeblock_t *block, ir_data_t *ir, UNUSED(uint8_t opcode), uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) { - int dest_reg = (fetchdat >> 3) & 7; + int dest_reg = (fetchdat >> 3) & 7; - codegen_mark_code_present(block, cs+op_pc, 1); - if ((fetchdat & 0xc0) == 0xc0) - { - int src_reg = fetchdat & 7; - - uop_MOVZX(ir, IREG_flags_op1, IREG_8(dest_reg)); - uop_MOVZX(ir, IREG_flags_op2, IREG_8(src_reg)); - uop_ADD(ir, IREG_8(dest_reg), IREG_8(dest_reg), IREG_8(src_reg)); - } - else - { - x86seg *target_seg; + codegen_mark_code_present(block, cs + op_pc, 1); + if ((fetchdat & 0xc0) == 0xc0) { + int src_reg = fetchdat & 7; - uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc); - target_seg = codegen_generate_ea(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32, 0); - codegen_check_seg_read(block, ir, target_seg); - uop_MEM_LOAD_REG(ir, IREG_temp0_B, ireg_seg_base(target_seg), IREG_eaaddr); - uop_MOVZX(ir, IREG_flags_op1, IREG_8(dest_reg)); - uop_MOVZX(ir, IREG_flags_op2, IREG_temp0_B); - uop_ADD(ir, IREG_8(dest_reg), IREG_8(dest_reg), IREG_temp0_B); - } + uop_MOVZX(ir, IREG_flags_op1, IREG_8(dest_reg)); + uop_MOVZX(ir, IREG_flags_op2, IREG_8(src_reg)); + uop_SUB(ir, IREG_flags_res_B, IREG_8(dest_reg), IREG_8(src_reg)); + } else { + x86seg *target_seg; - uop_MOV_IMM(ir, IREG_flags_op, FLAGS_ADD8); + uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc); + target_seg = codegen_generate_ea(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32, 0); + codegen_check_seg_read(block, ir, target_seg); + uop_MEM_LOAD_REG(ir, IREG_temp0_B, ireg_seg_base(target_seg), IREG_eaaddr); + uop_MOVZX(ir, IREG_flags_op1, IREG_8(dest_reg)); + uop_MOVZX(ir, IREG_flags_op2, IREG_temp0_B); + uop_SUB(ir, IREG_flags_res_B, IREG_8(dest_reg), IREG_temp0_B); + } + + uop_MOVZX(ir, IREG_flags_res, IREG_flags_res_B); + uop_MOV_IMM(ir, IREG_flags_op, FLAGS_SUB8); + + codegen_flags_changed = 1; + return op_pc + 1; +} +uint32_t +ropCMP_b_rmw(codeblock_t *block, ir_data_t *ir, UNUSED(uint8_t opcode), uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) +{ + int src_reg = (fetchdat >> 3) & 7; + + codegen_mark_code_present(block, cs + op_pc, 1); + if ((fetchdat & 0xc0) == 0xc0) { + int dest_reg = fetchdat & 7; + + uop_MOVZX(ir, IREG_flags_op1, IREG_8(dest_reg)); + uop_MOVZX(ir, IREG_flags_op2, IREG_8(src_reg)); + uop_SUB(ir, IREG_flags_res_B, IREG_8(dest_reg), IREG_8(src_reg)); + } else { + x86seg *target_seg; + + uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc); + target_seg = codegen_generate_ea(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32, 0); + codegen_check_seg_read(block, ir, target_seg); + uop_MEM_LOAD_REG(ir, IREG_temp0_B, ireg_seg_base(target_seg), IREG_eaaddr); + uop_MOVZX(ir, IREG_flags_op1, IREG_temp0_B); + uop_MOVZX(ir, IREG_flags_op2, IREG_8(src_reg)); + uop_SUB(ir, IREG_flags_res_B, IREG_temp0_B, IREG_8(src_reg)); + } + + uop_MOVZX(ir, IREG_flags_res, IREG_flags_res_B); + uop_MOV_IMM(ir, IREG_flags_op, FLAGS_SUB8); + + codegen_flags_changed = 1; + return op_pc + 1; +} +uint32_t +ropCMP_w_rm(codeblock_t *block, ir_data_t *ir, UNUSED(uint8_t opcode), uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) +{ + int dest_reg = (fetchdat >> 3) & 7; + + codegen_mark_code_present(block, cs + op_pc, 1); + if ((fetchdat & 0xc0) == 0xc0) { + int src_reg = fetchdat & 7; + + uop_MOVZX(ir, IREG_flags_op1, IREG_16(dest_reg)); + uop_MOVZX(ir, IREG_flags_op2, IREG_16(src_reg)); + uop_SUB(ir, IREG_flags_res_W, IREG_16(dest_reg), IREG_16(src_reg)); + } else { + x86seg *target_seg; + + uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc); + target_seg = codegen_generate_ea(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32, 0); + codegen_check_seg_read(block, ir, target_seg); + uop_MEM_LOAD_REG(ir, IREG_temp0_W, ireg_seg_base(target_seg), IREG_eaaddr); + uop_MOVZX(ir, IREG_flags_op1, IREG_16(dest_reg)); + uop_MOVZX(ir, IREG_flags_op2, IREG_temp0_W); + uop_SUB(ir, IREG_flags_res_W, IREG_16(dest_reg), IREG_temp0_W); + } + + uop_MOVZX(ir, IREG_flags_res, IREG_flags_res_W); + uop_MOV_IMM(ir, IREG_flags_op, FLAGS_SUB16); + + codegen_flags_changed = 1; + return op_pc + 1; +} +uint32_t +ropCMP_w_rmw(codeblock_t *block, ir_data_t *ir, UNUSED(uint8_t opcode), uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) +{ + int src_reg = (fetchdat >> 3) & 7; + + codegen_mark_code_present(block, cs + op_pc, 1); + if ((fetchdat & 0xc0) == 0xc0) { + int dest_reg = fetchdat & 7; + + uop_MOVZX(ir, IREG_flags_op1, IREG_16(dest_reg)); + uop_MOVZX(ir, IREG_flags_op2, IREG_16(src_reg)); + uop_SUB(ir, IREG_flags_res_W, IREG_16(dest_reg), IREG_16(src_reg)); + } else { + x86seg *target_seg; + + uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc); + target_seg = codegen_generate_ea(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32, 0); + codegen_check_seg_read(block, ir, target_seg); + uop_MEM_LOAD_REG(ir, IREG_temp0_W, ireg_seg_base(target_seg), IREG_eaaddr); + uop_MOVZX(ir, IREG_flags_op1, IREG_temp0_W); + uop_MOVZX(ir, IREG_flags_op2, IREG_16(src_reg)); + uop_SUB(ir, IREG_flags_res_W, IREG_temp0_W, IREG_16(src_reg)); + } + + uop_MOVZX(ir, IREG_flags_res, IREG_flags_res_W); + uop_MOV_IMM(ir, IREG_flags_op, FLAGS_SUB16); + + codegen_flags_changed = 1; + return op_pc + 1; +} +uint32_t +ropCMP_l_rm(codeblock_t *block, ir_data_t *ir, UNUSED(uint8_t opcode), uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) +{ + int dest_reg = (fetchdat >> 3) & 7; + + codegen_mark_code_present(block, cs + op_pc, 1); + if ((fetchdat & 0xc0) == 0xc0) { + int src_reg = fetchdat & 7; + + uop_MOV(ir, IREG_flags_op1, IREG_32(dest_reg)); + uop_MOV(ir, IREG_flags_op2, IREG_32(src_reg)); + uop_SUB(ir, IREG_flags_res, IREG_32(dest_reg), IREG_32(src_reg)); + } else { + x86seg *target_seg; + + uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc); + target_seg = codegen_generate_ea(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32, 0); + codegen_check_seg_read(block, ir, target_seg); + uop_MEM_LOAD_REG(ir, IREG_temp0, ireg_seg_base(target_seg), IREG_eaaddr); + uop_MOV(ir, IREG_flags_op1, IREG_32(dest_reg)); + uop_MOV(ir, IREG_flags_op2, IREG_temp0); + uop_SUB(ir, IREG_flags_res, IREG_32(dest_reg), IREG_temp0); + } + + uop_MOV_IMM(ir, IREG_flags_op, FLAGS_SUB32); + + codegen_flags_changed = 1; + return op_pc + 1; +} +uint32_t +ropCMP_l_rmw(codeblock_t *block, ir_data_t *ir, UNUSED(uint8_t opcode), uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) +{ + int src_reg = (fetchdat >> 3) & 7; + + codegen_mark_code_present(block, cs + op_pc, 1); + if ((fetchdat & 0xc0) == 0xc0) { + int dest_reg = fetchdat & 7; + + uop_MOV(ir, IREG_flags_op1, IREG_32(dest_reg)); + uop_MOV(ir, IREG_flags_op2, IREG_32(src_reg)); + uop_SUB(ir, IREG_flags_res, IREG_32(dest_reg), IREG_32(src_reg)); + } else { + x86seg *target_seg; + + uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc); + target_seg = codegen_generate_ea(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32, 0); + codegen_check_seg_read(block, ir, target_seg); + uop_MEM_LOAD_REG(ir, IREG_temp0, ireg_seg_base(target_seg), IREG_eaaddr); + uop_MOV(ir, IREG_flags_op1, IREG_temp0); + uop_MOV(ir, IREG_flags_op2, IREG_32(src_reg)); + uop_SUB(ir, IREG_flags_res, IREG_temp0, IREG_32(src_reg)); + } + + uop_MOV_IMM(ir, IREG_flags_op, FLAGS_SUB32); + + codegen_flags_changed = 1; + return op_pc + 1; +} + +uint32_t +ropSBB_AL_imm(codeblock_t *block, ir_data_t *ir, UNUSED(uint8_t opcode), uint32_t fetchdat, UNUSED(uint32_t op_32), uint32_t op_pc) +{ + uint8_t imm_data = fastreadb(cs + op_pc); + + get_cf(ir, IREG_temp0); + uop_MOVZX(ir, IREG_flags_op1, IREG_AL); + uop_SUB_IMM(ir, IREG_AL, IREG_AL, imm_data); + uop_MOV_IMM(ir, IREG_flags_op2, imm_data); + uop_SUB(ir, IREG_AL, IREG_AL, IREG_temp0_B); + uop_MOV_IMM(ir, IREG_flags_op, FLAGS_SBC8); + uop_MOVZX(ir, IREG_flags_res, IREG_AL); + + codegen_flags_changed = 1; + codegen_mark_code_present(block, cs + op_pc, 1); + return op_pc + 1; +} +uint32_t +ropSBB_AX_imm(codeblock_t *block, ir_data_t *ir, UNUSED(uint8_t opcode), uint32_t fetchdat, UNUSED(uint32_t op_32), uint32_t op_pc) +{ + uint16_t imm_data = fastreadw(cs + op_pc); + + get_cf(ir, IREG_temp0); + uop_MOVZX(ir, IREG_flags_op1, IREG_AX); + uop_SUB_IMM(ir, IREG_AX, IREG_AX, imm_data); + uop_MOV_IMM(ir, IREG_flags_op2, imm_data); + uop_SUB(ir, IREG_AX, IREG_AX, IREG_temp0_W); + uop_MOV_IMM(ir, IREG_flags_op, FLAGS_SBC16); + uop_MOVZX(ir, IREG_flags_res, IREG_AX); + + codegen_flags_changed = 1; + codegen_mark_code_present(block, cs + op_pc, 2); + return op_pc + 2; +} +uint32_t +ropSBB_EAX_imm(codeblock_t *block, ir_data_t *ir, UNUSED(uint8_t opcode), uint32_t fetchdat, UNUSED(uint32_t op_32), uint32_t op_pc) +{ + fetchdat = fastreadl(cs + op_pc); + + get_cf(ir, IREG_temp0); + uop_MOV(ir, IREG_flags_op1, IREG_EAX); + uop_SUB_IMM(ir, IREG_EAX, IREG_EAX, fetchdat); + uop_MOV_IMM(ir, IREG_flags_op2, fetchdat); + uop_SUB(ir, IREG_EAX, IREG_EAX, IREG_temp0); + uop_MOV_IMM(ir, IREG_flags_op, FLAGS_SBC32); + uop_MOV(ir, IREG_flags_res, IREG_EAX); + + codegen_flags_changed = 1; + codegen_mark_code_present(block, cs + op_pc, 4); + return op_pc + 4; +} +uint32_t +ropSBB_b_rm(codeblock_t *block, ir_data_t *ir, UNUSED(uint8_t opcode), uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) +{ + int dest_reg = (fetchdat >> 3) & 7; + + codegen_mark_code_present(block, cs + op_pc, 1); + get_cf(ir, IREG_temp1); + if ((fetchdat & 0xc0) == 0xc0) { + int src_reg = fetchdat & 7; + + uop_MOVZX(ir, IREG_flags_op1, IREG_8(dest_reg)); + uop_MOVZX(ir, IREG_flags_op2, IREG_8(src_reg)); + uop_SUB(ir, IREG_8(dest_reg), IREG_8(dest_reg), IREG_8(src_reg)); + } else { + x86seg *target_seg; + + uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc); + target_seg = codegen_generate_ea(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32, 0); + codegen_check_seg_read(block, ir, target_seg); + uop_MEM_LOAD_REG(ir, IREG_temp0_B, ireg_seg_base(target_seg), IREG_eaaddr); + uop_MOVZX(ir, IREG_flags_op1, IREG_8(dest_reg)); + uop_MOVZX(ir, IREG_flags_op2, IREG_temp0_B); + uop_SUB(ir, IREG_8(dest_reg), IREG_8(dest_reg), IREG_temp0_B); + } + + uop_SUB(ir, IREG_8(dest_reg), IREG_8(dest_reg), IREG_temp1_B); + uop_MOV_IMM(ir, IREG_flags_op, FLAGS_SBC8); + uop_MOVZX(ir, IREG_flags_res, IREG_8(dest_reg)); + + codegen_flags_changed = 1; + return op_pc + 1; +} +uint32_t +ropSBB_b_rmw(codeblock_t *block, ir_data_t *ir, UNUSED(uint8_t opcode), uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) +{ + int src_reg = (fetchdat >> 3) & 7; + + codegen_mark_code_present(block, cs + op_pc, 1); + get_cf(ir, IREG_temp1); + if ((fetchdat & 0xc0) == 0xc0) { + int dest_reg = fetchdat & 7; + + uop_MOVZX(ir, IREG_flags_op1, IREG_8(dest_reg)); + uop_MOVZX(ir, IREG_flags_op2, IREG_8(src_reg)); + uop_SUB(ir, IREG_8(dest_reg), IREG_8(dest_reg), IREG_8(src_reg)); + uop_SUB(ir, IREG_8(dest_reg), IREG_8(dest_reg), IREG_temp1_B); uop_MOVZX(ir, IREG_flags_res, IREG_8(dest_reg)); + } else { + x86seg *target_seg; - codegen_flags_changed = 1; - return op_pc + 1; + uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc); + target_seg = codegen_generate_ea(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32, 0); + codegen_check_seg_write(block, ir, target_seg); + + uop_MEM_LOAD_REG(ir, IREG_temp0_B, ireg_seg_base(target_seg), IREG_eaaddr); + uop_SUB(ir, IREG_temp2_B, IREG_temp0_B, IREG_8(src_reg)); + uop_SUB(ir, IREG_temp2_B, IREG_temp2_B, IREG_temp1_B); + uop_MEM_STORE_REG(ir, ireg_seg_base(target_seg), IREG_eaaddr, IREG_temp2_B); + uop_MOVZX(ir, IREG_flags_op1, IREG_temp0_B); + uop_MOVZX(ir, IREG_flags_op2, IREG_8(src_reg)); + uop_MOVZX(ir, IREG_flags_res, IREG_temp2_B); + } + uop_MOV_IMM(ir, IREG_flags_op, FLAGS_SBC8); + + codegen_flags_changed = 1; + return op_pc + 1; } -uint32_t ropADD_b_rmw(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) +uint32_t +ropSBB_w_rm(codeblock_t *block, ir_data_t *ir, UNUSED(uint8_t opcode), uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) { - int src_reg = (fetchdat >> 3) & 7; + int dest_reg = (fetchdat >> 3) & 7; - codegen_mark_code_present(block, cs+op_pc, 1); - if ((fetchdat & 0xc0) == 0xc0) - { - int dest_reg = fetchdat & 7; + codegen_mark_code_present(block, cs + op_pc, 1); + get_cf(ir, IREG_temp1); + if ((fetchdat & 0xc0) == 0xc0) { + int src_reg = fetchdat & 7; - uop_MOVZX(ir, IREG_flags_op1, IREG_8(dest_reg)); - uop_MOVZX(ir, IREG_flags_op2, IREG_8(src_reg)); - uop_ADD(ir, IREG_8(dest_reg), IREG_8(dest_reg), IREG_8(src_reg)); - uop_MOVZX(ir, IREG_flags_res, IREG_8(dest_reg)); - } - else - { - x86seg *target_seg; + uop_MOVZX(ir, IREG_flags_op1, IREG_16(dest_reg)); + uop_MOVZX(ir, IREG_flags_op2, IREG_16(src_reg)); + uop_SUB(ir, IREG_16(dest_reg), IREG_16(dest_reg), IREG_16(src_reg)); + } else { + x86seg *target_seg; - uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc); - target_seg = codegen_generate_ea(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32, 0); - codegen_check_seg_write(block, ir, target_seg); + uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc); + target_seg = codegen_generate_ea(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32, 0); + codegen_check_seg_read(block, ir, target_seg); + uop_MEM_LOAD_REG(ir, IREG_temp0_W, ireg_seg_base(target_seg), IREG_eaaddr); + uop_MOVZX(ir, IREG_flags_op1, IREG_16(dest_reg)); + uop_MOVZX(ir, IREG_flags_op2, IREG_temp0_W); + uop_SUB(ir, IREG_16(dest_reg), IREG_16(dest_reg), IREG_temp0_W); + } - uop_MEM_LOAD_REG(ir, IREG_temp0_B, ireg_seg_base(target_seg), IREG_eaaddr); - uop_ADD(ir, IREG_temp1_B, IREG_temp0_B, IREG_8(src_reg)); - uop_MEM_STORE_REG(ir, ireg_seg_base(target_seg), IREG_eaaddr, IREG_temp1_B); - uop_MOVZX(ir, IREG_flags_op1, IREG_temp0_B); - uop_MOVZX(ir, IREG_flags_op2, IREG_8(src_reg)); - uop_MOVZX(ir, IREG_flags_res, IREG_temp1_B); - } - uop_MOV_IMM(ir, IREG_flags_op, FLAGS_ADD8); + uop_SUB(ir, IREG_16(dest_reg), IREG_16(dest_reg), IREG_temp1_W); + uop_MOV_IMM(ir, IREG_flags_op, FLAGS_SBC16); + uop_MOVZX(ir, IREG_flags_res, IREG_16(dest_reg)); - codegen_flags_changed = 1; - return op_pc + 1; + codegen_flags_changed = 1; + return op_pc + 1; } -uint32_t ropADD_w_rm(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) +uint32_t +ropSBB_w_rmw(codeblock_t *block, ir_data_t *ir, UNUSED(uint8_t opcode), uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) { - int dest_reg = (fetchdat >> 3) & 7; + int src_reg = (fetchdat >> 3) & 7; - codegen_mark_code_present(block, cs+op_pc, 1); - if ((fetchdat & 0xc0) == 0xc0) - { - int src_reg = fetchdat & 7; + codegen_mark_code_present(block, cs + op_pc, 1); + get_cf(ir, IREG_temp1); + if ((fetchdat & 0xc0) == 0xc0) { + int dest_reg = fetchdat & 7; - uop_MOVZX(ir, IREG_flags_op1, IREG_16(dest_reg)); - uop_MOVZX(ir, IREG_flags_op2, IREG_16(src_reg)); - uop_ADD(ir, IREG_16(dest_reg), IREG_16(dest_reg), IREG_16(src_reg)); - } - else - { - x86seg *target_seg; - - uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc); - target_seg = codegen_generate_ea(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32, 0); - codegen_check_seg_read(block, ir, target_seg); - uop_MEM_LOAD_REG(ir, IREG_temp0_W, ireg_seg_base(target_seg), IREG_eaaddr); - uop_MOVZX(ir, IREG_flags_op1, IREG_16(dest_reg)); - uop_MOVZX(ir, IREG_flags_op2, IREG_temp0_W); - uop_ADD(ir, IREG_16(dest_reg), IREG_16(dest_reg), IREG_temp0_W); - } - - uop_MOV_IMM(ir, IREG_flags_op, FLAGS_ADD16); + uop_MOVZX(ir, IREG_flags_op1, IREG_16(dest_reg)); + uop_MOVZX(ir, IREG_flags_op2, IREG_16(src_reg)); + uop_SUB(ir, IREG_16(dest_reg), IREG_16(dest_reg), IREG_16(src_reg)); + uop_SUB(ir, IREG_16(dest_reg), IREG_16(dest_reg), IREG_temp1_W); uop_MOVZX(ir, IREG_flags_res, IREG_16(dest_reg)); + } else { + x86seg *target_seg; - codegen_flags_changed = 1; - return op_pc + 1; + uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc); + target_seg = codegen_generate_ea(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32, 0); + codegen_check_seg_write(block, ir, target_seg); + + uop_MEM_LOAD_REG(ir, IREG_temp0_W, ireg_seg_base(target_seg), IREG_eaaddr); + uop_SUB(ir, IREG_temp2_W, IREG_temp0_W, IREG_16(src_reg)); + uop_SUB(ir, IREG_temp2_W, IREG_temp2_W, IREG_temp1_W); + uop_MEM_STORE_REG(ir, ireg_seg_base(target_seg), IREG_eaaddr, IREG_temp2_W); + uop_MOVZX(ir, IREG_flags_op1, IREG_temp0_W); + uop_MOVZX(ir, IREG_flags_op2, IREG_16(src_reg)); + uop_MOVZX(ir, IREG_flags_res, IREG_temp2_W); + } + + uop_MOV_IMM(ir, IREG_flags_op, FLAGS_SBC16); + + codegen_flags_changed = 1; + return op_pc + 1; } -uint32_t ropADD_w_rmw(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) +uint32_t +ropSBB_l_rm(codeblock_t *block, ir_data_t *ir, UNUSED(uint8_t opcode), uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) { - int src_reg = (fetchdat >> 3) & 7; + int dest_reg = (fetchdat >> 3) & 7; - codegen_mark_code_present(block, cs+op_pc, 1); - if ((fetchdat & 0xc0) == 0xc0) - { - int dest_reg = fetchdat & 7; + codegen_mark_code_present(block, cs + op_pc, 1); + get_cf(ir, IREG_temp1); + if ((fetchdat & 0xc0) == 0xc0) { + int src_reg = fetchdat & 7; - uop_MOVZX(ir, IREG_flags_op1, IREG_16(dest_reg)); - uop_MOVZX(ir, IREG_flags_op2, IREG_16(src_reg)); - uop_ADD(ir, IREG_16(dest_reg), IREG_16(dest_reg), IREG_16(src_reg)); - uop_MOVZX(ir, IREG_flags_res, IREG_16(dest_reg)); - } - else - { - x86seg *target_seg; + uop_MOV(ir, IREG_flags_op1, IREG_32(dest_reg)); + uop_MOV(ir, IREG_flags_op2, IREG_32(src_reg)); + uop_SUB(ir, IREG_32(dest_reg), IREG_32(dest_reg), IREG_32(src_reg)); + } else { + x86seg *target_seg; - uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc); - target_seg = codegen_generate_ea(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32, 0); - codegen_check_seg_write(block, ir, target_seg); + uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc); + target_seg = codegen_generate_ea(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32, 0); + codegen_check_seg_read(block, ir, target_seg); + uop_MEM_LOAD_REG(ir, IREG_flags_op2, ireg_seg_base(target_seg), IREG_eaaddr); + uop_MOV(ir, IREG_flags_op1, IREG_32(dest_reg)); + uop_SUB(ir, IREG_32(dest_reg), IREG_32(dest_reg), IREG_flags_op2); + } - uop_MEM_LOAD_REG(ir, IREG_temp0_W, ireg_seg_base(target_seg), IREG_eaaddr); - uop_ADD(ir, IREG_temp1_W, IREG_temp0_W, IREG_16(src_reg)); - uop_MEM_STORE_REG(ir, ireg_seg_base(target_seg), IREG_eaaddr, IREG_temp1_W); - uop_MOVZX(ir, IREG_flags_op1, IREG_temp0_W); - uop_MOVZX(ir, IREG_flags_op2, IREG_16(src_reg)); - uop_MOVZX(ir, IREG_flags_res, IREG_temp1_W); - } - uop_MOV_IMM(ir, IREG_flags_op, FLAGS_ADD16); + uop_SUB(ir, IREG_32(dest_reg), IREG_32(dest_reg), IREG_temp1); + uop_MOV_IMM(ir, IREG_flags_op, FLAGS_SBC32); + uop_MOV(ir, IREG_flags_res, IREG_32(dest_reg)); - codegen_flags_changed = 1; - return op_pc + 1; + codegen_flags_changed = 1; + return op_pc + 1; } -uint32_t ropADD_l_rm(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) +uint32_t +ropSBB_l_rmw(codeblock_t *block, ir_data_t *ir, UNUSED(uint8_t opcode), uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) { - int dest_reg = (fetchdat >> 3) & 7; + int src_reg = (fetchdat >> 3) & 7; - codegen_mark_code_present(block, cs+op_pc, 1); - if ((fetchdat & 0xc0) == 0xc0) - { - int src_reg = fetchdat & 7; + codegen_mark_code_present(block, cs + op_pc, 1); + get_cf(ir, IREG_temp1); + if ((fetchdat & 0xc0) == 0xc0) { + int dest_reg = fetchdat & 7; - uop_MOV(ir, IREG_flags_op1, IREG_32(dest_reg)); - uop_MOV(ir, IREG_flags_op2, IREG_32(src_reg)); - uop_ADD(ir, IREG_32(dest_reg), IREG_32(dest_reg), IREG_32(src_reg)); - } - else - { - x86seg *target_seg; - - uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc); - target_seg = codegen_generate_ea(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32, 0); - codegen_check_seg_read(block, ir, target_seg); - uop_MEM_LOAD_REG(ir, IREG_flags_op2, ireg_seg_base(target_seg), IREG_eaaddr); - uop_MOV(ir, IREG_flags_op1, IREG_32(dest_reg)); - uop_ADD(ir, IREG_32(dest_reg), IREG_32(dest_reg), IREG_flags_op2); - } - - uop_MOV_IMM(ir, IREG_flags_op, FLAGS_ADD32); + uop_MOV(ir, IREG_flags_op1, IREG_32(dest_reg)); + uop_MOV(ir, IREG_flags_op2, IREG_32(src_reg)); + uop_SUB(ir, IREG_32(dest_reg), IREG_32(dest_reg), IREG_32(src_reg)); + uop_SUB(ir, IREG_32(dest_reg), IREG_32(dest_reg), IREG_temp1); uop_MOV(ir, IREG_flags_res, IREG_32(dest_reg)); + } else { + x86seg *target_seg; - codegen_flags_changed = 1; - return op_pc + 1; -} -uint32_t ropADD_l_rmw(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) -{ - int src_reg = (fetchdat >> 3) & 7; + uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc); + target_seg = codegen_generate_ea(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32, 0); + codegen_check_seg_write(block, ir, target_seg); - codegen_mark_code_present(block, cs+op_pc, 1); - if ((fetchdat & 0xc0) == 0xc0) - { - int dest_reg = fetchdat & 7; + uop_MEM_LOAD_REG(ir, IREG_temp0, ireg_seg_base(target_seg), IREG_eaaddr); + uop_SUB(ir, IREG_temp2, IREG_temp0, IREG_32(src_reg)); + uop_SUB(ir, IREG_temp2, IREG_temp2, IREG_temp1); + uop_MEM_STORE_REG(ir, ireg_seg_base(target_seg), IREG_eaaddr, IREG_temp2); + uop_MOV(ir, IREG_flags_op1, IREG_temp0); + uop_MOV(ir, IREG_flags_op2, IREG_32(src_reg)); + uop_MOV(ir, IREG_flags_res, IREG_temp2); + } - uop_MOV(ir, IREG_flags_op1, IREG_32(dest_reg)); - uop_MOV(ir, IREG_flags_op2, IREG_32(src_reg)); - uop_ADD(ir, IREG_32(dest_reg), IREG_32(dest_reg), IREG_32(src_reg)); - uop_MOV(ir, IREG_flags_res, IREG_32(dest_reg)); - } - else - { - x86seg *target_seg; + uop_MOV_IMM(ir, IREG_flags_op, FLAGS_SBC32); - uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc); - target_seg = codegen_generate_ea(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32, 0); - codegen_check_seg_write(block, ir, target_seg); - - uop_MEM_LOAD_REG(ir, IREG_temp0, ireg_seg_base(target_seg), IREG_eaaddr); - uop_ADD(ir, IREG_temp1, IREG_temp0, IREG_32(src_reg)); - uop_MEM_STORE_REG(ir, ireg_seg_base(target_seg), IREG_eaaddr, IREG_temp1); - uop_MOV(ir, IREG_flags_op1, IREG_temp0); - uop_MOV(ir, IREG_flags_op2, IREG_32(src_reg)); - uop_MOV(ir, IREG_flags_res, IREG_temp1); - } - uop_MOV_IMM(ir, IREG_flags_op, FLAGS_ADD32); - - codegen_flags_changed = 1; - return op_pc + 1; + codegen_flags_changed = 1; + return op_pc + 1; } -uint32_t ropCMP_AL_imm(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) +uint32_t +ropSUB_AL_imm(codeblock_t *block, ir_data_t *ir, UNUSED(uint8_t opcode), uint32_t fetchdat, UNUSED(uint32_t op_32), uint32_t op_pc) { - uint8_t imm_data = fastreadb(cs + op_pc); + uint8_t imm_data = fastreadb(cs + op_pc); - uop_MOVZX(ir, IREG_flags_op1, IREG_AL); - uop_SUB_IMM(ir, IREG_flags_res_B, IREG_AL, imm_data); - uop_MOVZX(ir, IREG_flags_res, IREG_flags_res_B); - uop_MOV_IMM(ir, IREG_flags_op2, imm_data); - uop_MOV_IMM(ir, IREG_flags_op, FLAGS_SUB8); + uop_MOVZX(ir, IREG_flags_op1, IREG_AL); + uop_SUB_IMM(ir, IREG_AL, IREG_AL, imm_data); + uop_MOV_IMM(ir, IREG_flags_op2, imm_data); + uop_MOV_IMM(ir, IREG_flags_op, FLAGS_SUB8); + uop_MOVZX(ir, IREG_flags_res, IREG_AL); - codegen_flags_changed = 1; - codegen_mark_code_present(block, cs+op_pc, 1); - return op_pc + 1; + codegen_flags_changed = 1; + codegen_mark_code_present(block, cs + op_pc, 1); + return op_pc + 1; } -uint32_t ropCMP_AX_imm(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) +uint32_t +ropSUB_AX_imm(codeblock_t *block, ir_data_t *ir, UNUSED(uint8_t opcode), uint32_t fetchdat, UNUSED(uint32_t op_32), uint32_t op_pc) { - uint16_t imm_data = fastreadw(cs + op_pc); + uint16_t imm_data = fastreadw(cs + op_pc); - uop_MOVZX(ir, IREG_flags_op1, IREG_AX); - uop_SUB_IMM(ir, IREG_flags_res_W, IREG_AX, imm_data); - uop_MOVZX(ir, IREG_flags_res, IREG_flags_res_W); - uop_MOV_IMM(ir, IREG_flags_op2, imm_data); - uop_MOV_IMM(ir, IREG_flags_op, FLAGS_SUB16); + uop_MOVZX(ir, IREG_flags_op1, IREG_AX); + uop_SUB_IMM(ir, IREG_AX, IREG_AX, imm_data); + uop_MOV_IMM(ir, IREG_flags_op2, imm_data); + uop_MOV_IMM(ir, IREG_flags_op, FLAGS_SUB16); + uop_MOVZX(ir, IREG_flags_res, IREG_AX); - codegen_flags_changed = 1; - codegen_mark_code_present(block, cs+op_pc, 2); - return op_pc + 2; + codegen_flags_changed = 1; + codegen_mark_code_present(block, cs + op_pc, 2); + return op_pc + 2; } -uint32_t ropCMP_EAX_imm(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) +uint32_t +ropSUB_EAX_imm(codeblock_t *block, ir_data_t *ir, UNUSED(uint8_t opcode), uint32_t fetchdat, UNUSED(uint32_t op_32), uint32_t op_pc) { + uop_MOV(ir, IREG_flags_op1, IREG_EAX); + + if (block->flags & CODEBLOCK_NO_IMMEDIATES) { + LOAD_IMMEDIATE_FROM_RAM_32(block, ir, IREG_temp0, cs + op_pc); + uop_SUB(ir, IREG_EAX, IREG_EAX, IREG_temp0); + uop_MOV(ir, IREG_flags_op2, IREG_temp0); + } else { fetchdat = fastreadl(cs + op_pc); - - uop_MOV(ir, IREG_flags_op1, IREG_EAX); - uop_SUB_IMM(ir, IREG_flags_res, IREG_EAX, fetchdat); - uop_MOV_IMM(ir, IREG_flags_op2, fetchdat); - uop_MOV_IMM(ir, IREG_flags_op, FLAGS_SUB32); - - codegen_flags_changed = 1; - codegen_mark_code_present(block, cs+op_pc, 4); - return op_pc + 4; -} -uint32_t ropCMP_b_rm(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) -{ - int dest_reg = (fetchdat >> 3) & 7; - - codegen_mark_code_present(block, cs+op_pc, 1); - if ((fetchdat & 0xc0) == 0xc0) - { - int src_reg = fetchdat & 7; - - uop_MOVZX(ir, IREG_flags_op1, IREG_8(dest_reg)); - uop_MOVZX(ir, IREG_flags_op2, IREG_8(src_reg)); - uop_SUB(ir, IREG_flags_res_B, IREG_8(dest_reg), IREG_8(src_reg)); - } - else - { - x86seg *target_seg; - - uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc); - target_seg = codegen_generate_ea(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32, 0); - codegen_check_seg_read(block, ir, target_seg); - uop_MEM_LOAD_REG(ir, IREG_temp0_B, ireg_seg_base(target_seg), IREG_eaaddr); - uop_MOVZX(ir, IREG_flags_op1, IREG_8(dest_reg)); - uop_MOVZX(ir, IREG_flags_op2, IREG_temp0_B); - uop_SUB(ir, IREG_flags_res_B, IREG_8(dest_reg), IREG_temp0_B); - } - - uop_MOVZX(ir, IREG_flags_res, IREG_flags_res_B); - uop_MOV_IMM(ir, IREG_flags_op, FLAGS_SUB8); - - codegen_flags_changed = 1; - return op_pc + 1; -} -uint32_t ropCMP_b_rmw(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) -{ - int src_reg = (fetchdat >> 3) & 7; - - codegen_mark_code_present(block, cs+op_pc, 1); - if ((fetchdat & 0xc0) == 0xc0) - { - int dest_reg = fetchdat & 7; - - uop_MOVZX(ir, IREG_flags_op1, IREG_8(dest_reg)); - uop_MOVZX(ir, IREG_flags_op2, IREG_8(src_reg)); - uop_SUB(ir, IREG_flags_res_B, IREG_8(dest_reg), IREG_8(src_reg)); - } - else - { - x86seg *target_seg; - - uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc); - target_seg = codegen_generate_ea(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32, 0); - codegen_check_seg_read(block, ir, target_seg); - uop_MEM_LOAD_REG(ir, IREG_temp0_B, ireg_seg_base(target_seg), IREG_eaaddr); - uop_MOVZX(ir, IREG_flags_op1, IREG_temp0_B); - uop_MOVZX(ir, IREG_flags_op2, IREG_8(src_reg)); - uop_SUB(ir, IREG_flags_res_B, IREG_temp0_B, IREG_8(src_reg)); - } - - uop_MOVZX(ir, IREG_flags_res, IREG_flags_res_B); - uop_MOV_IMM(ir, IREG_flags_op, FLAGS_SUB8); - - codegen_flags_changed = 1; - return op_pc + 1; -} -uint32_t ropCMP_w_rm(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) -{ - int dest_reg = (fetchdat >> 3) & 7; - - codegen_mark_code_present(block, cs+op_pc, 1); - if ((fetchdat & 0xc0) == 0xc0) - { - int src_reg = fetchdat & 7; - - uop_MOVZX(ir, IREG_flags_op1, IREG_16(dest_reg)); - uop_MOVZX(ir, IREG_flags_op2, IREG_16(src_reg)); - uop_SUB(ir, IREG_flags_res_W, IREG_16(dest_reg), IREG_16(src_reg)); - } - else - { - x86seg *target_seg; - - uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc); - target_seg = codegen_generate_ea(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32, 0); - codegen_check_seg_read(block, ir, target_seg); - uop_MEM_LOAD_REG(ir, IREG_temp0_W, ireg_seg_base(target_seg), IREG_eaaddr); - uop_MOVZX(ir, IREG_flags_op1, IREG_16(dest_reg)); - uop_MOVZX(ir, IREG_flags_op2, IREG_temp0_W); - uop_SUB(ir, IREG_flags_res_W, IREG_16(dest_reg), IREG_temp0_W); - } - - uop_MOVZX(ir, IREG_flags_res, IREG_flags_res_W); - uop_MOV_IMM(ir, IREG_flags_op, FLAGS_SUB16); - - codegen_flags_changed = 1; - return op_pc + 1; -} -uint32_t ropCMP_w_rmw(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) -{ - int src_reg = (fetchdat >> 3) & 7; - - codegen_mark_code_present(block, cs+op_pc, 1); - if ((fetchdat & 0xc0) == 0xc0) - { - int dest_reg = fetchdat & 7; - - uop_MOVZX(ir, IREG_flags_op1, IREG_16(dest_reg)); - uop_MOVZX(ir, IREG_flags_op2, IREG_16(src_reg)); - uop_SUB(ir, IREG_flags_res_W, IREG_16(dest_reg), IREG_16(src_reg)); - } - else - { - x86seg *target_seg; - - uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc); - target_seg = codegen_generate_ea(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32, 0); - codegen_check_seg_read(block, ir, target_seg); - uop_MEM_LOAD_REG(ir, IREG_temp0_W, ireg_seg_base(target_seg), IREG_eaaddr); - uop_MOVZX(ir, IREG_flags_op1, IREG_temp0_W); - uop_MOVZX(ir, IREG_flags_op2, IREG_16(src_reg)); - uop_SUB(ir, IREG_flags_res_W, IREG_temp0_W, IREG_16(src_reg)); - } - - uop_MOVZX(ir, IREG_flags_res, IREG_flags_res_W); - uop_MOV_IMM(ir, IREG_flags_op, FLAGS_SUB16); - - codegen_flags_changed = 1; - return op_pc + 1; -} -uint32_t ropCMP_l_rm(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) -{ - int dest_reg = (fetchdat >> 3) & 7; - - codegen_mark_code_present(block, cs+op_pc, 1); - if ((fetchdat & 0xc0) == 0xc0) - { - int src_reg = fetchdat & 7; - - uop_MOV(ir, IREG_flags_op1, IREG_32(dest_reg)); - uop_MOV(ir, IREG_flags_op2, IREG_32(src_reg)); - uop_SUB(ir, IREG_flags_res, IREG_32(dest_reg), IREG_32(src_reg)); - } - else - { - x86seg *target_seg; - - uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc); - target_seg = codegen_generate_ea(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32, 0); - codegen_check_seg_read(block, ir, target_seg); - uop_MEM_LOAD_REG(ir, IREG_temp0, ireg_seg_base(target_seg), IREG_eaaddr); - uop_MOV(ir, IREG_flags_op1, IREG_32(dest_reg)); - uop_MOV(ir, IREG_flags_op2, IREG_temp0); - uop_SUB(ir, IREG_flags_res, IREG_32(dest_reg), IREG_temp0); - } - - uop_MOV_IMM(ir, IREG_flags_op, FLAGS_SUB32); - - codegen_flags_changed = 1; - return op_pc + 1; -} -uint32_t ropCMP_l_rmw(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) -{ - int src_reg = (fetchdat >> 3) & 7; - - codegen_mark_code_present(block, cs+op_pc, 1); - if ((fetchdat & 0xc0) == 0xc0) - { - int dest_reg = fetchdat & 7; - - uop_MOV(ir, IREG_flags_op1, IREG_32(dest_reg)); - uop_MOV(ir, IREG_flags_op2, IREG_32(src_reg)); - uop_SUB(ir, IREG_flags_res, IREG_32(dest_reg), IREG_32(src_reg)); - } - else - { - x86seg *target_seg; - - uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc); - target_seg = codegen_generate_ea(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32, 0); - codegen_check_seg_read(block, ir, target_seg); - uop_MEM_LOAD_REG(ir, IREG_temp0, ireg_seg_base(target_seg), IREG_eaaddr); - uop_MOV(ir, IREG_flags_op1, IREG_temp0); - uop_MOV(ir, IREG_flags_op2, IREG_32(src_reg)); - uop_SUB(ir, IREG_flags_res, IREG_temp0, IREG_32(src_reg)); - } - - uop_MOV_IMM(ir, IREG_flags_op, FLAGS_SUB32); - - codegen_flags_changed = 1; - return op_pc + 1; -} - -uint32_t ropSBB_AL_imm(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) -{ - uint8_t imm_data = fastreadb(cs + op_pc); - - get_cf(ir, IREG_temp0); - uop_MOVZX(ir, IREG_flags_op1, IREG_AL); - uop_SUB_IMM(ir, IREG_AL, IREG_AL, imm_data); - uop_MOV_IMM(ir, IREG_flags_op2, imm_data); - uop_SUB(ir, IREG_AL, IREG_AL, IREG_temp0_B); - uop_MOV_IMM(ir, IREG_flags_op, FLAGS_SBC8); - uop_MOVZX(ir, IREG_flags_res, IREG_AL); - - codegen_flags_changed = 1; - codegen_mark_code_present(block, cs+op_pc, 1); - return op_pc + 1; -} -uint32_t ropSBB_AX_imm(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) -{ - uint16_t imm_data = fastreadw(cs + op_pc); - - get_cf(ir, IREG_temp0); - uop_MOVZX(ir, IREG_flags_op1, IREG_AX); - uop_SUB_IMM(ir, IREG_AX, IREG_AX, imm_data); - uop_MOV_IMM(ir, IREG_flags_op2, imm_data); - uop_SUB(ir, IREG_AX, IREG_AX, IREG_temp0_W); - uop_MOV_IMM(ir, IREG_flags_op, FLAGS_SBC16); - uop_MOVZX(ir, IREG_flags_res, IREG_AX); - - codegen_flags_changed = 1; - codegen_mark_code_present(block, cs+op_pc, 2); - return op_pc + 2; -} -uint32_t ropSBB_EAX_imm(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) -{ - fetchdat = fastreadl(cs + op_pc); - - get_cf(ir, IREG_temp0); - uop_MOV(ir, IREG_flags_op1, IREG_EAX); + codegen_mark_code_present(block, cs + op_pc, 4); uop_SUB_IMM(ir, IREG_EAX, IREG_EAX, fetchdat); uop_MOV_IMM(ir, IREG_flags_op2, fetchdat); - uop_SUB(ir, IREG_EAX, IREG_EAX, IREG_temp0); - uop_MOV_IMM(ir, IREG_flags_op, FLAGS_SBC32); - uop_MOV(ir, IREG_flags_res, IREG_EAX); + } - codegen_flags_changed = 1; - codegen_mark_code_present(block, cs+op_pc, 4); - return op_pc + 4; + uop_MOV_IMM(ir, IREG_flags_op, FLAGS_SUB32); + uop_MOV(ir, IREG_flags_res, IREG_EAX); + + codegen_flags_changed = 1; + return op_pc + 4; } -uint32_t ropSBB_b_rm(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) +uint32_t +ropSUB_b_rm(codeblock_t *block, ir_data_t *ir, UNUSED(uint8_t opcode), uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) { - int dest_reg = (fetchdat >> 3) & 7; + int dest_reg = (fetchdat >> 3) & 7; - codegen_mark_code_present(block, cs+op_pc, 1); - get_cf(ir, IREG_temp1); - if ((fetchdat & 0xc0) == 0xc0) - { - int src_reg = fetchdat & 7; + codegen_mark_code_present(block, cs + op_pc, 1); + if ((fetchdat & 0xc0) == 0xc0) { + int src_reg = fetchdat & 7; - uop_MOVZX(ir, IREG_flags_op1, IREG_8(dest_reg)); - uop_MOVZX(ir, IREG_flags_op2, IREG_8(src_reg)); - uop_SUB(ir, IREG_8(dest_reg), IREG_8(dest_reg), IREG_8(src_reg)); - } - else - { - x86seg *target_seg; + uop_MOVZX(ir, IREG_flags_op1, IREG_8(dest_reg)); + uop_MOVZX(ir, IREG_flags_op2, IREG_8(src_reg)); + uop_SUB(ir, IREG_8(dest_reg), IREG_8(dest_reg), IREG_8(src_reg)); + } else { + x86seg *target_seg; - uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc); - target_seg = codegen_generate_ea(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32, 0); - codegen_check_seg_read(block, ir, target_seg); - uop_MEM_LOAD_REG(ir, IREG_temp0_B, ireg_seg_base(target_seg), IREG_eaaddr); - uop_MOVZX(ir, IREG_flags_op1, IREG_8(dest_reg)); - uop_MOVZX(ir, IREG_flags_op2, IREG_temp0_B); - uop_SUB(ir, IREG_8(dest_reg), IREG_8(dest_reg), IREG_temp0_B); - } + uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc); + target_seg = codegen_generate_ea(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32, 0); + codegen_check_seg_read(block, ir, target_seg); + uop_MEM_LOAD_REG(ir, IREG_temp0_B, ireg_seg_base(target_seg), IREG_eaaddr); + uop_MOVZX(ir, IREG_flags_op1, IREG_8(dest_reg)); + uop_MOVZX(ir, IREG_flags_op2, IREG_temp0_B); + uop_SUB(ir, IREG_8(dest_reg), IREG_8(dest_reg), IREG_temp0_B); + } - uop_SUB(ir, IREG_8(dest_reg), IREG_8(dest_reg), IREG_temp1_B); - uop_MOV_IMM(ir, IREG_flags_op, FLAGS_SBC8); + uop_MOV_IMM(ir, IREG_flags_op, FLAGS_SUB8); + uop_MOVZX(ir, IREG_flags_res, IREG_8(dest_reg)); + + codegen_flags_changed = 1; + return op_pc + 1; +} +uint32_t +ropSUB_b_rmw(codeblock_t *block, ir_data_t *ir, UNUSED(uint8_t opcode), uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) +{ + int src_reg = (fetchdat >> 3) & 7; + + codegen_mark_code_present(block, cs + op_pc, 1); + if ((fetchdat & 0xc0) == 0xc0) { + int dest_reg = fetchdat & 7; + + uop_MOVZX(ir, IREG_flags_op1, IREG_8(dest_reg)); + uop_MOVZX(ir, IREG_flags_op2, IREG_8(src_reg)); + uop_SUB(ir, IREG_8(dest_reg), IREG_8(dest_reg), IREG_8(src_reg)); uop_MOVZX(ir, IREG_flags_res, IREG_8(dest_reg)); + } else { + x86seg *target_seg; - codegen_flags_changed = 1; - return op_pc + 1; + uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc); + target_seg = codegen_generate_ea(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32, 0); + codegen_check_seg_write(block, ir, target_seg); + + uop_MEM_LOAD_REG(ir, IREG_temp0_B, ireg_seg_base(target_seg), IREG_eaaddr); + uop_SUB(ir, IREG_temp1_B, IREG_temp0_B, IREG_8(src_reg)); + uop_MEM_STORE_REG(ir, ireg_seg_base(target_seg), IREG_eaaddr, IREG_temp1_B); + uop_MOVZX(ir, IREG_flags_op1, IREG_temp0_B); + uop_MOVZX(ir, IREG_flags_op2, IREG_8(src_reg)); + uop_MOVZX(ir, IREG_flags_res, IREG_temp1_B); + } + uop_MOV_IMM(ir, IREG_flags_op, FLAGS_SUB8); + + codegen_flags_changed = 1; + return op_pc + 1; } -uint32_t ropSBB_b_rmw(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) +uint32_t +ropSUB_w_rm(codeblock_t *block, ir_data_t *ir, UNUSED(uint8_t opcode), uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) { - int src_reg = (fetchdat >> 3) & 7; + int dest_reg = (fetchdat >> 3) & 7; - codegen_mark_code_present(block, cs+op_pc, 1); - get_cf(ir, IREG_temp1); - if ((fetchdat & 0xc0) == 0xc0) - { - int dest_reg = fetchdat & 7; + codegen_mark_code_present(block, cs + op_pc, 1); + if ((fetchdat & 0xc0) == 0xc0) { + int src_reg = fetchdat & 7; - uop_MOVZX(ir, IREG_flags_op1, IREG_8(dest_reg)); - uop_MOVZX(ir, IREG_flags_op2, IREG_8(src_reg)); - uop_SUB(ir, IREG_8(dest_reg), IREG_8(dest_reg), IREG_8(src_reg)); - uop_SUB(ir, IREG_8(dest_reg), IREG_8(dest_reg), IREG_temp1_B); - uop_MOVZX(ir, IREG_flags_res, IREG_8(dest_reg)); - } - else - { - x86seg *target_seg; + uop_MOVZX(ir, IREG_flags_op1, IREG_16(dest_reg)); + uop_MOVZX(ir, IREG_flags_op2, IREG_16(src_reg)); + uop_SUB(ir, IREG_16(dest_reg), IREG_16(dest_reg), IREG_16(src_reg)); + } else { + x86seg *target_seg; - uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc); - target_seg = codegen_generate_ea(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32, 0); - codegen_check_seg_write(block, ir, target_seg); + uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc); + target_seg = codegen_generate_ea(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32, 0); + codegen_check_seg_read(block, ir, target_seg); + uop_MEM_LOAD_REG(ir, IREG_temp0_W, ireg_seg_base(target_seg), IREG_eaaddr); + uop_MOVZX(ir, IREG_flags_op1, IREG_16(dest_reg)); + uop_MOVZX(ir, IREG_flags_op2, IREG_temp0_W); + uop_SUB(ir, IREG_16(dest_reg), IREG_16(dest_reg), IREG_temp0_W); + } - uop_MEM_LOAD_REG(ir, IREG_temp0_B, ireg_seg_base(target_seg), IREG_eaaddr); - uop_SUB(ir, IREG_temp2_B, IREG_temp0_B, IREG_8(src_reg)); - uop_SUB(ir, IREG_temp2_B, IREG_temp2_B, IREG_temp1_B); - uop_MEM_STORE_REG(ir, ireg_seg_base(target_seg), IREG_eaaddr, IREG_temp2_B); - uop_MOVZX(ir, IREG_flags_op1, IREG_temp0_B); - uop_MOVZX(ir, IREG_flags_op2, IREG_8(src_reg)); - uop_MOVZX(ir, IREG_flags_res, IREG_temp2_B); - } - uop_MOV_IMM(ir, IREG_flags_op, FLAGS_SBC8); + uop_MOV_IMM(ir, IREG_flags_op, FLAGS_SUB16); + uop_MOVZX(ir, IREG_flags_res, IREG_16(dest_reg)); - codegen_flags_changed = 1; - return op_pc + 1; + codegen_flags_changed = 1; + return op_pc + 1; } -uint32_t ropSBB_w_rm(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) +uint32_t +ropSUB_w_rmw(codeblock_t *block, ir_data_t *ir, UNUSED(uint8_t opcode), uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) { - int dest_reg = (fetchdat >> 3) & 7; + int src_reg = (fetchdat >> 3) & 7; - codegen_mark_code_present(block, cs+op_pc, 1); - get_cf(ir, IREG_temp1); - if ((fetchdat & 0xc0) == 0xc0) - { - int src_reg = fetchdat & 7; + codegen_mark_code_present(block, cs + op_pc, 1); + if ((fetchdat & 0xc0) == 0xc0) { + int dest_reg = fetchdat & 7; - uop_MOVZX(ir, IREG_flags_op1, IREG_16(dest_reg)); - uop_MOVZX(ir, IREG_flags_op2, IREG_16(src_reg)); - uop_SUB(ir, IREG_16(dest_reg), IREG_16(dest_reg), IREG_16(src_reg)); - } - else - { - x86seg *target_seg; - - uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc); - target_seg = codegen_generate_ea(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32, 0); - codegen_check_seg_read(block, ir, target_seg); - uop_MEM_LOAD_REG(ir, IREG_temp0_W, ireg_seg_base(target_seg), IREG_eaaddr); - uop_MOVZX(ir, IREG_flags_op1, IREG_16(dest_reg)); - uop_MOVZX(ir, IREG_flags_op2, IREG_temp0_W); - uop_SUB(ir, IREG_16(dest_reg), IREG_16(dest_reg), IREG_temp0_W); - } - - uop_SUB(ir, IREG_16(dest_reg), IREG_16(dest_reg), IREG_temp1_W); - uop_MOV_IMM(ir, IREG_flags_op, FLAGS_SBC16); + uop_MOVZX(ir, IREG_flags_op1, IREG_16(dest_reg)); + uop_MOVZX(ir, IREG_flags_op2, IREG_16(src_reg)); + uop_SUB(ir, IREG_16(dest_reg), IREG_16(dest_reg), IREG_16(src_reg)); uop_MOVZX(ir, IREG_flags_res, IREG_16(dest_reg)); + } else { + x86seg *target_seg; - codegen_flags_changed = 1; - return op_pc + 1; + uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc); + target_seg = codegen_generate_ea(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32, 0); + codegen_check_seg_write(block, ir, target_seg); + + uop_MEM_LOAD_REG(ir, IREG_temp0_W, ireg_seg_base(target_seg), IREG_eaaddr); + uop_SUB(ir, IREG_temp1_W, IREG_temp0_W, IREG_16(src_reg)); + uop_MEM_STORE_REG(ir, ireg_seg_base(target_seg), IREG_eaaddr, IREG_temp1_W); + uop_MOVZX(ir, IREG_flags_op1, IREG_temp0_W); + uop_MOVZX(ir, IREG_flags_op2, IREG_16(src_reg)); + uop_MOVZX(ir, IREG_flags_res, IREG_temp1_W); + } + + uop_MOV_IMM(ir, IREG_flags_op, FLAGS_SUB16); + + codegen_flags_changed = 1; + return op_pc + 1; } -uint32_t ropSBB_w_rmw(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) +uint32_t +ropSUB_l_rm(codeblock_t *block, ir_data_t *ir, UNUSED(uint8_t opcode), uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) { - int src_reg = (fetchdat >> 3) & 7; + int dest_reg = (fetchdat >> 3) & 7; - codegen_mark_code_present(block, cs+op_pc, 1); - get_cf(ir, IREG_temp1); - if ((fetchdat & 0xc0) == 0xc0) - { - int dest_reg = fetchdat & 7; + codegen_mark_code_present(block, cs + op_pc, 1); + if ((fetchdat & 0xc0) == 0xc0) { + int src_reg = fetchdat & 7; - uop_MOVZX(ir, IREG_flags_op1, IREG_16(dest_reg)); - uop_MOVZX(ir, IREG_flags_op2, IREG_16(src_reg)); - uop_SUB(ir, IREG_16(dest_reg), IREG_16(dest_reg), IREG_16(src_reg)); - uop_SUB(ir, IREG_16(dest_reg), IREG_16(dest_reg), IREG_temp1_W); - uop_MOVZX(ir, IREG_flags_res, IREG_16(dest_reg)); - } - else - { - x86seg *target_seg; + uop_MOV(ir, IREG_flags_op1, IREG_32(dest_reg)); + uop_MOV(ir, IREG_flags_op2, IREG_32(src_reg)); + uop_SUB(ir, IREG_32(dest_reg), IREG_32(dest_reg), IREG_32(src_reg)); + } else { + x86seg *target_seg; - uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc); - target_seg = codegen_generate_ea(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32, 0); - codegen_check_seg_write(block, ir, target_seg); + uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc); + target_seg = codegen_generate_ea(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32, 0); + codegen_check_seg_read(block, ir, target_seg); + uop_MEM_LOAD_REG(ir, IREG_flags_op2, ireg_seg_base(target_seg), IREG_eaaddr); + uop_MOV(ir, IREG_flags_op1, IREG_32(dest_reg)); + uop_SUB(ir, IREG_32(dest_reg), IREG_32(dest_reg), IREG_flags_op2); + } - uop_MEM_LOAD_REG(ir, IREG_temp0_W, ireg_seg_base(target_seg), IREG_eaaddr); - uop_SUB(ir, IREG_temp2_W, IREG_temp0_W, IREG_16(src_reg)); - uop_SUB(ir, IREG_temp2_W, IREG_temp2_W, IREG_temp1_W); - uop_MEM_STORE_REG(ir, ireg_seg_base(target_seg), IREG_eaaddr, IREG_temp2_W); - uop_MOVZX(ir, IREG_flags_op1, IREG_temp0_W); - uop_MOVZX(ir, IREG_flags_op2, IREG_16(src_reg)); - uop_MOVZX(ir, IREG_flags_res, IREG_temp2_W); - } + uop_MOV_IMM(ir, IREG_flags_op, FLAGS_SUB32); + uop_MOV(ir, IREG_flags_res, IREG_32(dest_reg)); - uop_MOV_IMM(ir, IREG_flags_op, FLAGS_SBC16); - - codegen_flags_changed = 1; - return op_pc + 1; + codegen_flags_changed = 1; + return op_pc + 1; } -uint32_t ropSBB_l_rm(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) +uint32_t +ropSUB_l_rmw(codeblock_t *block, ir_data_t *ir, UNUSED(uint8_t opcode), uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) { - int dest_reg = (fetchdat >> 3) & 7; + int src_reg = (fetchdat >> 3) & 7; - codegen_mark_code_present(block, cs+op_pc, 1); - get_cf(ir, IREG_temp1); - if ((fetchdat & 0xc0) == 0xc0) - { - int src_reg = fetchdat & 7; + codegen_mark_code_present(block, cs + op_pc, 1); + if ((fetchdat & 0xc0) == 0xc0) { + int dest_reg = fetchdat & 7; - uop_MOV(ir, IREG_flags_op1, IREG_32(dest_reg)); - uop_MOV(ir, IREG_flags_op2, IREG_32(src_reg)); - uop_SUB(ir, IREG_32(dest_reg), IREG_32(dest_reg), IREG_32(src_reg)); - } - else - { - x86seg *target_seg; - - uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc); - target_seg = codegen_generate_ea(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32, 0); - codegen_check_seg_read(block, ir, target_seg); - uop_MEM_LOAD_REG(ir, IREG_flags_op2, ireg_seg_base(target_seg), IREG_eaaddr); - uop_MOV(ir, IREG_flags_op1, IREG_32(dest_reg)); - uop_SUB(ir, IREG_32(dest_reg), IREG_32(dest_reg), IREG_flags_op2); - } - - uop_SUB(ir, IREG_32(dest_reg), IREG_32(dest_reg), IREG_temp1); - uop_MOV_IMM(ir, IREG_flags_op, FLAGS_SBC32); + uop_MOV(ir, IREG_flags_op1, IREG_32(dest_reg)); + uop_MOV(ir, IREG_flags_op2, IREG_32(src_reg)); + uop_SUB(ir, IREG_32(dest_reg), IREG_32(dest_reg), IREG_32(src_reg)); uop_MOV(ir, IREG_flags_res, IREG_32(dest_reg)); + } else { + x86seg *target_seg; - codegen_flags_changed = 1; - return op_pc + 1; + uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc); + target_seg = codegen_generate_ea(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32, 0); + codegen_check_seg_write(block, ir, target_seg); + + uop_MEM_LOAD_REG(ir, IREG_temp0, ireg_seg_base(target_seg), IREG_eaaddr); + uop_SUB(ir, IREG_temp1, IREG_temp0, IREG_32(src_reg)); + uop_MEM_STORE_REG(ir, ireg_seg_base(target_seg), IREG_eaaddr, IREG_temp1); + uop_MOV(ir, IREG_flags_op1, IREG_temp0); + uop_MOV(ir, IREG_flags_op2, IREG_32(src_reg)); + uop_MOV(ir, IREG_flags_res, IREG_temp1); + } + + uop_MOV_IMM(ir, IREG_flags_op, FLAGS_SUB32); + + codegen_flags_changed = 1; + return op_pc + 1; } -uint32_t ropSBB_l_rmw(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) + +uint32_t +rop80(codeblock_t *block, ir_data_t *ir, UNUSED(uint8_t opcode), uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) { - int src_reg = (fetchdat >> 3) & 7; + int skip_immediate = 0; - codegen_mark_code_present(block, cs+op_pc, 1); - get_cf(ir, IREG_temp1); - if ((fetchdat & 0xc0) == 0xc0) - { - int dest_reg = fetchdat & 7; + codegen_mark_code_present(block, cs + op_pc, 1); + if ((fetchdat & 0xc0) == 0xc0) { + int dest_reg = fetchdat & 7; + uint8_t imm = fastreadb(cs + op_pc + 1); - uop_MOV(ir, IREG_flags_op1, IREG_32(dest_reg)); - uop_MOV(ir, IREG_flags_op2, IREG_32(src_reg)); - uop_SUB(ir, IREG_32(dest_reg), IREG_32(dest_reg), IREG_32(src_reg)); - uop_SUB(ir, IREG_32(dest_reg), IREG_32(dest_reg), IREG_temp1); - uop_MOV(ir, IREG_flags_res, IREG_32(dest_reg)); - } - else - { - x86seg *target_seg; - - uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc); - target_seg = codegen_generate_ea(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32, 0); - codegen_check_seg_write(block, ir, target_seg); - - uop_MEM_LOAD_REG(ir, IREG_temp0, ireg_seg_base(target_seg), IREG_eaaddr); - uop_SUB(ir, IREG_temp2, IREG_temp0, IREG_32(src_reg)); - uop_SUB(ir, IREG_temp2, IREG_temp2, IREG_temp1); - uop_MEM_STORE_REG(ir, ireg_seg_base(target_seg), IREG_eaaddr, IREG_temp2); - uop_MOV(ir, IREG_flags_op1, IREG_temp0); - uop_MOV(ir, IREG_flags_op2, IREG_32(src_reg)); - uop_MOV(ir, IREG_flags_res, IREG_temp2); + if (block->flags & CODEBLOCK_NO_IMMEDIATES) { + skip_immediate = 1; + LOAD_IMMEDIATE_FROM_RAM_8(block, ir, IREG_temp0_B, cs + op_pc + 1); } - uop_MOV_IMM(ir, IREG_flags_op, FLAGS_SBC32); - - codegen_flags_changed = 1; - return op_pc + 1; -} - -uint32_t ropSUB_AL_imm(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) -{ - uint8_t imm_data = fastreadb(cs + op_pc); - - uop_MOVZX(ir, IREG_flags_op1, IREG_AL); - uop_SUB_IMM(ir, IREG_AL, IREG_AL, imm_data); - uop_MOV_IMM(ir, IREG_flags_op2, imm_data); - uop_MOV_IMM(ir, IREG_flags_op, FLAGS_SUB8); - uop_MOVZX(ir, IREG_flags_res, IREG_AL); - - codegen_flags_changed = 1; - codegen_mark_code_present(block, cs+op_pc, 1); - return op_pc + 1; -} -uint32_t ropSUB_AX_imm(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) -{ - uint16_t imm_data = fastreadw(cs + op_pc); - - uop_MOVZX(ir, IREG_flags_op1, IREG_AX); - uop_SUB_IMM(ir, IREG_AX, IREG_AX, imm_data); - uop_MOV_IMM(ir, IREG_flags_op2, imm_data); - uop_MOV_IMM(ir, IREG_flags_op, FLAGS_SUB16); - uop_MOVZX(ir, IREG_flags_res, IREG_AX); - - codegen_flags_changed = 1; - codegen_mark_code_present(block, cs+op_pc, 2); - return op_pc + 2; -} -uint32_t ropSUB_EAX_imm(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) -{ - uop_MOV(ir, IREG_flags_op1, IREG_EAX); - - if (block->flags & CODEBLOCK_NO_IMMEDIATES) - { - LOAD_IMMEDIATE_FROM_RAM_32(block, ir, IREG_temp0, cs + op_pc); - uop_SUB(ir, IREG_EAX, IREG_EAX, IREG_temp0); - uop_MOV(ir, IREG_flags_op2, IREG_temp0); - } - else - { - fetchdat = fastreadl(cs + op_pc); - codegen_mark_code_present(block, cs+op_pc, 4); - uop_SUB_IMM(ir, IREG_EAX, IREG_EAX, fetchdat); - uop_MOV_IMM(ir, IREG_flags_op2, fetchdat); - } - - uop_MOV_IMM(ir, IREG_flags_op, FLAGS_SUB32); - uop_MOV(ir, IREG_flags_res, IREG_EAX); - - codegen_flags_changed = 1; - return op_pc + 4; -} -uint32_t ropSUB_b_rm(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) -{ - int dest_reg = (fetchdat >> 3) & 7; - - codegen_mark_code_present(block, cs+op_pc, 1); - if ((fetchdat & 0xc0) == 0xc0) - { - int src_reg = fetchdat & 7; - + switch (fetchdat & 0x38) { + case 0x00: /*ADD*/ uop_MOVZX(ir, IREG_flags_op1, IREG_8(dest_reg)); - uop_MOVZX(ir, IREG_flags_op2, IREG_8(src_reg)); - uop_SUB(ir, IREG_8(dest_reg), IREG_8(dest_reg), IREG_8(src_reg)); - } - else - { - x86seg *target_seg; - - uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc); - target_seg = codegen_generate_ea(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32, 0); - codegen_check_seg_read(block, ir, target_seg); - uop_MEM_LOAD_REG(ir, IREG_temp0_B, ireg_seg_base(target_seg), IREG_eaaddr); - uop_MOVZX(ir, IREG_flags_op1, IREG_8(dest_reg)); - uop_MOVZX(ir, IREG_flags_op2, IREG_temp0_B); - uop_SUB(ir, IREG_8(dest_reg), IREG_8(dest_reg), IREG_temp0_B); - } - - uop_MOV_IMM(ir, IREG_flags_op, FLAGS_SUB8); - uop_MOVZX(ir, IREG_flags_res, IREG_8(dest_reg)); - - codegen_flags_changed = 1; - return op_pc + 1; -} -uint32_t ropSUB_b_rmw(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) -{ - int src_reg = (fetchdat >> 3) & 7; - - codegen_mark_code_present(block, cs+op_pc, 1); - if ((fetchdat & 0xc0) == 0xc0) - { - int dest_reg = fetchdat & 7; - - uop_MOVZX(ir, IREG_flags_op1, IREG_8(dest_reg)); - uop_MOVZX(ir, IREG_flags_op2, IREG_8(src_reg)); - uop_SUB(ir, IREG_8(dest_reg), IREG_8(dest_reg), IREG_8(src_reg)); + if (block->flags & CODEBLOCK_NO_IMMEDIATES) { + uop_ADD(ir, IREG_8(dest_reg), IREG_8(dest_reg), IREG_temp0_B); + uop_MOVZX(ir, IREG_flags_op2, IREG_temp0_B); + } else { + uop_ADD_IMM(ir, IREG_8(dest_reg), IREG_8(dest_reg), imm); + uop_MOV_IMM(ir, IREG_flags_op2, imm); + } + uop_MOV_IMM(ir, IREG_flags_op, FLAGS_ADD8); uop_MOVZX(ir, IREG_flags_res, IREG_8(dest_reg)); + break; + + case 0x08: /*OR*/ + if (block->flags & CODEBLOCK_NO_IMMEDIATES) + uop_OR(ir, IREG_8(dest_reg), IREG_8(dest_reg), IREG_temp0_B); + else + uop_OR_IMM(ir, IREG_8(dest_reg), IREG_8(dest_reg), imm); + uop_MOV_IMM(ir, IREG_flags_op, FLAGS_ZN8); + uop_MOVZX(ir, IREG_flags_res, IREG_8(dest_reg)); + break; + + case 0x10: /*ADC*/ + get_cf(ir, IREG_temp1); + uop_MOVZX(ir, IREG_flags_op1, IREG_8(dest_reg)); + if (block->flags & CODEBLOCK_NO_IMMEDIATES) { + uop_ADD(ir, IREG_8(dest_reg), IREG_8(dest_reg), IREG_temp0_B); + uop_MOVZX(ir, IREG_flags_op2, IREG_temp0_B); + } else { + uop_ADD_IMM(ir, IREG_8(dest_reg), IREG_8(dest_reg), imm); + uop_MOV_IMM(ir, IREG_flags_op2, imm); + } + uop_ADD(ir, IREG_8(dest_reg), IREG_8(dest_reg), IREG_temp1_B); + uop_MOV_IMM(ir, IREG_flags_op, FLAGS_ADC8); + uop_MOVZX(ir, IREG_flags_res, IREG_8(dest_reg)); + break; + + case 0x18: /*SBB*/ + get_cf(ir, IREG_temp1); + uop_MOVZX(ir, IREG_flags_op1, IREG_8(dest_reg)); + if (block->flags & CODEBLOCK_NO_IMMEDIATES) { + uop_SUB(ir, IREG_8(dest_reg), IREG_8(dest_reg), IREG_temp0_B); + uop_MOVZX(ir, IREG_flags_op2, IREG_temp0_B); + } else { + uop_SUB_IMM(ir, IREG_8(dest_reg), IREG_8(dest_reg), imm); + uop_MOV_IMM(ir, IREG_flags_op2, imm); + } + uop_SUB(ir, IREG_8(dest_reg), IREG_8(dest_reg), IREG_temp1_B); + uop_MOV_IMM(ir, IREG_flags_op, FLAGS_SBC8); + uop_MOVZX(ir, IREG_flags_res, IREG_8(dest_reg)); + break; + + case 0x20: /*AND*/ + if (block->flags & CODEBLOCK_NO_IMMEDIATES) + uop_AND(ir, IREG_8(dest_reg), IREG_8(dest_reg), IREG_temp0_B); + else + uop_AND_IMM(ir, IREG_8(dest_reg), IREG_8(dest_reg), imm); + uop_MOV_IMM(ir, IREG_flags_op, FLAGS_ZN8); + uop_MOVZX(ir, IREG_flags_res, IREG_8(dest_reg)); + break; + + case 0x28: /*SUB*/ + uop_MOVZX(ir, IREG_flags_op1, IREG_8(dest_reg)); + if (block->flags & CODEBLOCK_NO_IMMEDIATES) { + uop_SUB(ir, IREG_8(dest_reg), IREG_8(dest_reg), IREG_temp0_B); + uop_MOVZX(ir, IREG_flags_op2, IREG_temp0_B); + } else { + uop_SUB_IMM(ir, IREG_8(dest_reg), IREG_8(dest_reg), imm); + uop_MOV_IMM(ir, IREG_flags_op2, imm); + } + uop_MOV_IMM(ir, IREG_flags_op, FLAGS_SUB8); + uop_MOVZX(ir, IREG_flags_res, IREG_8(dest_reg)); + break; + + case 0x30: /*XOR*/ + if (block->flags & CODEBLOCK_NO_IMMEDIATES) + uop_XOR(ir, IREG_8(dest_reg), IREG_8(dest_reg), IREG_temp0_B); + else + uop_XOR_IMM(ir, IREG_8(dest_reg), IREG_8(dest_reg), imm); + uop_MOV_IMM(ir, IREG_flags_op, FLAGS_ZN8); + uop_MOVZX(ir, IREG_flags_res, IREG_8(dest_reg)); + break; + + case 0x38: /*CMP*/ + uop_MOVZX(ir, IREG_flags_op1, IREG_8(dest_reg)); + if (block->flags & CODEBLOCK_NO_IMMEDIATES) { + uop_SUB(ir, IREG_flags_res_B, IREG_8(dest_reg), IREG_temp0_B); + uop_MOVZX(ir, IREG_flags_op2, IREG_temp0_B); + } else { + uop_SUB_IMM(ir, IREG_flags_res_B, IREG_8(dest_reg), imm); + uop_MOV_IMM(ir, IREG_flags_op2, imm); + } + uop_MOVZX(ir, IREG_flags_res, IREG_flags_res_B); + uop_MOV_IMM(ir, IREG_flags_op, FLAGS_SUB8); + break; + + default: + return 0; } + } else { + x86seg *target_seg; + uint8_t imm; + + uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc); + target_seg = codegen_generate_ea(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32, 0); + if ((fetchdat & 0x38) == 0x38) /*CMP*/ + codegen_check_seg_read(block, ir, target_seg); else - { - x86seg *target_seg; + codegen_check_seg_write(block, ir, target_seg); + imm = fastreadb(cs + op_pc + 1); + uop_MEM_LOAD_REG(ir, IREG_temp0_B, ireg_seg_base(target_seg), IREG_eaaddr); - uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc); - target_seg = codegen_generate_ea(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32, 0); - codegen_check_seg_write(block, ir, target_seg); - - uop_MEM_LOAD_REG(ir, IREG_temp0_B, ireg_seg_base(target_seg), IREG_eaaddr); - uop_SUB(ir, IREG_temp1_B, IREG_temp0_B, IREG_8(src_reg)); + switch (fetchdat & 0x38) { + case 0x00: /*ADD*/ + uop_ADD_IMM(ir, IREG_temp1_B, IREG_temp0_B, imm); uop_MEM_STORE_REG(ir, ireg_seg_base(target_seg), IREG_eaaddr, IREG_temp1_B); uop_MOVZX(ir, IREG_flags_op1, IREG_temp0_B); - uop_MOVZX(ir, IREG_flags_op2, IREG_8(src_reg)); + uop_MOV_IMM(ir, IREG_flags_op2, imm); + uop_MOV_IMM(ir, IREG_flags_op, FLAGS_ADD8); uop_MOVZX(ir, IREG_flags_res, IREG_temp1_B); - } - uop_MOV_IMM(ir, IREG_flags_op, FLAGS_SUB8); + break; - codegen_flags_changed = 1; - return op_pc + 1; + case 0x08: /*OR*/ + uop_OR_IMM(ir, IREG_temp0_B, IREG_temp0_B, imm); + uop_MEM_STORE_REG(ir, ireg_seg_base(target_seg), IREG_eaaddr, IREG_temp0_B); + uop_MOVZX(ir, IREG_flags_res, IREG_temp0_B); + uop_MOV_IMM(ir, IREG_flags_op, FLAGS_ZN8); + break; + + case 0x10: /*ADC*/ + get_cf(ir, IREG_temp2); + uop_ADD_IMM(ir, IREG_temp1_B, IREG_temp0_B, imm); + uop_ADD(ir, IREG_temp1_B, IREG_temp1_B, IREG_temp2_B); + uop_MEM_STORE_REG(ir, ireg_seg_base(target_seg), IREG_eaaddr, IREG_temp1_B); + uop_MOVZX(ir, IREG_flags_op1, IREG_temp0_B); + uop_MOV_IMM(ir, IREG_flags_op2, imm); + uop_MOV_IMM(ir, IREG_flags_op, FLAGS_ADC8); + uop_MOVZX(ir, IREG_flags_res, IREG_temp1_B); + break; + + case 0x18: /*SBB*/ + get_cf(ir, IREG_temp2); + uop_SUB_IMM(ir, IREG_temp1_B, IREG_temp0_B, imm); + uop_SUB(ir, IREG_temp1_B, IREG_temp1_B, IREG_temp2_B); + uop_MEM_STORE_REG(ir, ireg_seg_base(target_seg), IREG_eaaddr, IREG_temp1_B); + uop_MOVZX(ir, IREG_flags_op1, IREG_temp0_B); + uop_MOV_IMM(ir, IREG_flags_op2, imm); + uop_MOV_IMM(ir, IREG_flags_op, FLAGS_SBC8); + uop_MOVZX(ir, IREG_flags_res, IREG_temp1_B); + break; + + case 0x20: /*AND*/ + uop_AND_IMM(ir, IREG_temp0_B, IREG_temp0_B, imm); + uop_MEM_STORE_REG(ir, ireg_seg_base(target_seg), IREG_eaaddr, IREG_temp0_B); + uop_MOVZX(ir, IREG_flags_res, IREG_temp0_B); + uop_MOV_IMM(ir, IREG_flags_op, FLAGS_ZN8); + break; + + case 0x28: /*SUB*/ + uop_SUB_IMM(ir, IREG_temp1_B, IREG_temp0_B, imm); + uop_MEM_STORE_REG(ir, ireg_seg_base(target_seg), IREG_eaaddr, IREG_temp1_B); + uop_MOVZX(ir, IREG_flags_op1, IREG_temp0_B); + uop_MOV_IMM(ir, IREG_flags_op2, imm); + uop_MOV_IMM(ir, IREG_flags_op, FLAGS_SUB8); + uop_MOVZX(ir, IREG_flags_res, IREG_temp1_B); + break; + + case 0x30: /*XOR*/ + uop_XOR_IMM(ir, IREG_temp0_B, IREG_temp0_B, imm); + uop_MEM_STORE_REG(ir, ireg_seg_base(target_seg), IREG_eaaddr, IREG_temp0_B); + uop_MOVZX(ir, IREG_flags_res, IREG_temp0_B); + uop_MOV_IMM(ir, IREG_flags_op, FLAGS_ZN8); + break; + + case 0x38: /*CMP*/ + uop_MOVZX(ir, IREG_flags_op1, IREG_temp0_B); + uop_MOV_IMM(ir, IREG_flags_op2, imm); + uop_SUB_IMM(ir, IREG_flags_res_B, IREG_temp0_B, imm); + uop_MOVZX(ir, IREG_flags_res, IREG_flags_res_B); + uop_MOV_IMM(ir, IREG_flags_op, FLAGS_SUB8); + break; + + default: + return 0; + } + } + + codegen_flags_changed = 1; + if (!skip_immediate) + codegen_mark_code_present(block, cs + op_pc + 1, 1); + return op_pc + 2; } -uint32_t ropSUB_w_rm(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) +uint32_t +rop81_w(codeblock_t *block, ir_data_t *ir, UNUSED(uint8_t opcode), uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) { - int dest_reg = (fetchdat >> 3) & 7; + int skip_immediate = 0; - codegen_mark_code_present(block, cs+op_pc, 1); - if ((fetchdat & 0xc0) == 0xc0) - { - int src_reg = fetchdat & 7; + codegen_mark_code_present(block, cs + op_pc, 1); + if ((fetchdat & 0xc0) == 0xc0) { + int dest_reg = fetchdat & 7; + uint16_t imm = fastreadw(cs + op_pc + 1); - uop_MOVZX(ir, IREG_flags_op1, IREG_16(dest_reg)); - uop_MOVZX(ir, IREG_flags_op2, IREG_16(src_reg)); - uop_SUB(ir, IREG_16(dest_reg), IREG_16(dest_reg), IREG_16(src_reg)); - } - else - { - x86seg *target_seg; - - uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc); - target_seg = codegen_generate_ea(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32, 0); - codegen_check_seg_read(block, ir, target_seg); - uop_MEM_LOAD_REG(ir, IREG_temp0_W, ireg_seg_base(target_seg), IREG_eaaddr); - uop_MOVZX(ir, IREG_flags_op1, IREG_16(dest_reg)); - uop_MOVZX(ir, IREG_flags_op2, IREG_temp0_W); - uop_SUB(ir, IREG_16(dest_reg), IREG_16(dest_reg), IREG_temp0_W); + if (block->flags & CODEBLOCK_NO_IMMEDIATES) { + skip_immediate = 1; + LOAD_IMMEDIATE_FROM_RAM_16(block, ir, IREG_temp0_W, cs + op_pc + 1); } - uop_MOV_IMM(ir, IREG_flags_op, FLAGS_SUB16); - uop_MOVZX(ir, IREG_flags_res, IREG_16(dest_reg)); - - codegen_flags_changed = 1; - return op_pc + 1; -} -uint32_t ropSUB_w_rmw(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) -{ - int src_reg = (fetchdat >> 3) & 7; - - codegen_mark_code_present(block, cs+op_pc, 1); - if ((fetchdat & 0xc0) == 0xc0) - { - int dest_reg = fetchdat & 7; - + switch (fetchdat & 0x38) { + case 0x00: /*ADD*/ uop_MOVZX(ir, IREG_flags_op1, IREG_16(dest_reg)); - uop_MOVZX(ir, IREG_flags_op2, IREG_16(src_reg)); - uop_SUB(ir, IREG_16(dest_reg), IREG_16(dest_reg), IREG_16(src_reg)); + if (block->flags & CODEBLOCK_NO_IMMEDIATES) { + uop_ADD(ir, IREG_16(dest_reg), IREG_16(dest_reg), IREG_temp0_W); + uop_MOVZX(ir, IREG_flags_op2, IREG_temp0_W); + } else { + uop_ADD_IMM(ir, IREG_16(dest_reg), IREG_16(dest_reg), imm); + uop_MOV_IMM(ir, IREG_flags_op2, imm); + } + uop_MOV_IMM(ir, IREG_flags_op, FLAGS_ADD16); uop_MOVZX(ir, IREG_flags_res, IREG_16(dest_reg)); + break; + + case 0x08: /*OR*/ + if (block->flags & CODEBLOCK_NO_IMMEDIATES) + uop_OR(ir, IREG_16(dest_reg), IREG_16(dest_reg), IREG_temp0_W); + else + uop_OR_IMM(ir, IREG_16(dest_reg), IREG_16(dest_reg), imm); + uop_MOV_IMM(ir, IREG_flags_op, FLAGS_ZN16); + uop_MOVZX(ir, IREG_flags_res, IREG_16(dest_reg)); + break; + + case 0x10: /*ADC*/ + get_cf(ir, IREG_temp1); + uop_MOVZX(ir, IREG_flags_op1, IREG_16(dest_reg)); + if (block->flags & CODEBLOCK_NO_IMMEDIATES) { + uop_ADD(ir, IREG_16(dest_reg), IREG_16(dest_reg), IREG_temp0_W); + uop_MOVZX(ir, IREG_flags_op2, IREG_temp0_W); + } else { + uop_ADD_IMM(ir, IREG_16(dest_reg), IREG_16(dest_reg), imm); + uop_MOV_IMM(ir, IREG_flags_op2, imm); + } + uop_ADD(ir, IREG_16(dest_reg), IREG_16(dest_reg), IREG_temp1_W); + uop_MOV_IMM(ir, IREG_flags_op, FLAGS_ADC16); + uop_MOVZX(ir, IREG_flags_res, IREG_16(dest_reg)); + break; + + case 0x18: /*SBB*/ + get_cf(ir, IREG_temp1); + uop_MOVZX(ir, IREG_flags_op1, IREG_16(dest_reg)); + if (block->flags & CODEBLOCK_NO_IMMEDIATES) { + uop_SUB(ir, IREG_16(dest_reg), IREG_16(dest_reg), IREG_temp0_W); + uop_MOVZX(ir, IREG_flags_op2, IREG_temp0_W); + } else { + uop_SUB_IMM(ir, IREG_16(dest_reg), IREG_16(dest_reg), imm); + uop_MOV_IMM(ir, IREG_flags_op2, imm); + } + uop_SUB(ir, IREG_16(dest_reg), IREG_16(dest_reg), IREG_temp1_W); + uop_MOV_IMM(ir, IREG_flags_op, FLAGS_SBC16); + uop_MOVZX(ir, IREG_flags_res, IREG_16(dest_reg)); + break; + + case 0x20: /*AND*/ + if (block->flags & CODEBLOCK_NO_IMMEDIATES) + uop_AND(ir, IREG_16(dest_reg), IREG_16(dest_reg), IREG_temp0_W); + else + uop_AND_IMM(ir, IREG_16(dest_reg), IREG_16(dest_reg), imm); + uop_MOV_IMM(ir, IREG_flags_op, FLAGS_ZN16); + uop_MOVZX(ir, IREG_flags_res, IREG_16(dest_reg)); + break; + + case 0x28: /*SUB*/ + uop_MOVZX(ir, IREG_flags_op1, IREG_16(dest_reg)); + if (block->flags & CODEBLOCK_NO_IMMEDIATES) { + uop_SUB(ir, IREG_16(dest_reg), IREG_16(dest_reg), IREG_temp0_W); + uop_MOVZX(ir, IREG_flags_op2, IREG_temp0_W); + } else { + uop_SUB_IMM(ir, IREG_16(dest_reg), IREG_16(dest_reg), imm); + uop_MOV_IMM(ir, IREG_flags_op2, imm); + } + uop_MOV_IMM(ir, IREG_flags_op, FLAGS_SUB16); + uop_MOVZX(ir, IREG_flags_res, IREG_16(dest_reg)); + break; + + case 0x30: /*XOR*/ + if (block->flags & CODEBLOCK_NO_IMMEDIATES) + uop_XOR(ir, IREG_16(dest_reg), IREG_16(dest_reg), IREG_temp0_W); + else + uop_XOR_IMM(ir, IREG_16(dest_reg), IREG_16(dest_reg), imm); + uop_MOV_IMM(ir, IREG_flags_op, FLAGS_ZN16); + uop_MOVZX(ir, IREG_flags_res, IREG_16(dest_reg)); + break; + + case 0x38: /*CMP*/ + uop_MOVZX(ir, IREG_flags_op1, IREG_16(dest_reg)); + if (block->flags & CODEBLOCK_NO_IMMEDIATES) { + uop_SUB(ir, IREG_flags_res_W, IREG_16(dest_reg), IREG_temp0_W); + uop_MOVZX(ir, IREG_flags_op2, IREG_temp0_W); + } else { + uop_SUB_IMM(ir, IREG_flags_res_W, IREG_16(dest_reg), imm); + uop_MOV_IMM(ir, IREG_flags_op2, imm); + } + uop_MOVZX(ir, IREG_flags_res, IREG_flags_res_W); + uop_MOV_IMM(ir, IREG_flags_op, FLAGS_SUB16); + break; + + default: + return 0; } + } else { + x86seg *target_seg; + uint16_t imm; + + uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc); + target_seg = codegen_generate_ea(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32, 0); + if ((fetchdat & 0x38) == 0x38) /*CMP*/ + codegen_check_seg_read(block, ir, target_seg); else - { - x86seg *target_seg; + codegen_check_seg_write(block, ir, target_seg); + imm = fastreadw(cs + op_pc + 1); + uop_MEM_LOAD_REG(ir, IREG_temp0_W, ireg_seg_base(target_seg), IREG_eaaddr); + if (block->flags & CODEBLOCK_NO_IMMEDIATES) { + skip_immediate = 1; + LOAD_IMMEDIATE_FROM_RAM_16(block, ir, IREG_temp2_W, cs + op_pc + 1); + } - uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc); - target_seg = codegen_generate_ea(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32, 0); - codegen_check_seg_write(block, ir, target_seg); - - uop_MEM_LOAD_REG(ir, IREG_temp0_W, ireg_seg_base(target_seg), IREG_eaaddr); - uop_SUB(ir, IREG_temp1_W, IREG_temp0_W, IREG_16(src_reg)); + switch (fetchdat & 0x38) { + case 0x00: /*ADD*/ + if (block->flags & CODEBLOCK_NO_IMMEDIATES) + uop_ADD(ir, IREG_temp1_W, IREG_temp0_W, IREG_temp2_W); + else + uop_ADD_IMM(ir, IREG_temp1_W, IREG_temp0_W, imm); uop_MEM_STORE_REG(ir, ireg_seg_base(target_seg), IREG_eaaddr, IREG_temp1_W); uop_MOVZX(ir, IREG_flags_op1, IREG_temp0_W); - uop_MOVZX(ir, IREG_flags_op2, IREG_16(src_reg)); + if (block->flags & CODEBLOCK_NO_IMMEDIATES) + uop_MOVZX(ir, IREG_flags_op2, IREG_temp2_W); + else + uop_MOV_IMM(ir, IREG_flags_op2, imm); + uop_MOV_IMM(ir, IREG_flags_op, FLAGS_ADD16); uop_MOVZX(ir, IREG_flags_res, IREG_temp1_W); + break; + + case 0x08: /*OR*/ + if (block->flags & CODEBLOCK_NO_IMMEDIATES) + uop_OR(ir, IREG_temp0_W, IREG_temp0_W, IREG_temp2_W); + else + uop_OR_IMM(ir, IREG_temp0_W, IREG_temp0_W, imm); + uop_MEM_STORE_REG(ir, ireg_seg_base(target_seg), IREG_eaaddr, IREG_temp0_W); + uop_MOVZX(ir, IREG_flags_res, IREG_temp0_W); + uop_MOV_IMM(ir, IREG_flags_op, FLAGS_ZN16); + break; + + case 0x10: /*ADC*/ + get_cf(ir, IREG_temp3); + if (block->flags & CODEBLOCK_NO_IMMEDIATES) + uop_ADD(ir, IREG_temp1_W, IREG_temp0_W, IREG_temp2_W); + else + uop_ADD_IMM(ir, IREG_temp1_W, IREG_temp0_W, imm); + uop_ADD(ir, IREG_temp1_W, IREG_temp1_W, IREG_temp3_W); + uop_MEM_STORE_REG(ir, ireg_seg_base(target_seg), IREG_eaaddr, IREG_temp1_W); + uop_MOVZX(ir, IREG_flags_op1, IREG_temp0_W); + if (block->flags & CODEBLOCK_NO_IMMEDIATES) + uop_MOVZX(ir, IREG_flags_op2, IREG_temp2_W); + else + uop_MOV_IMM(ir, IREG_flags_op2, imm); + uop_MOV_IMM(ir, IREG_flags_op, FLAGS_ADC16); + uop_MOVZX(ir, IREG_flags_res, IREG_temp1_W); + break; + + case 0x18: /*SBB*/ + get_cf(ir, IREG_temp3); + if (block->flags & CODEBLOCK_NO_IMMEDIATES) + uop_SUB(ir, IREG_temp1_W, IREG_temp0_W, IREG_temp2_W); + else + uop_SUB_IMM(ir, IREG_temp1_W, IREG_temp0_W, imm); + uop_SUB(ir, IREG_temp1_W, IREG_temp1_W, IREG_temp3_W); + uop_MEM_STORE_REG(ir, ireg_seg_base(target_seg), IREG_eaaddr, IREG_temp1_W); + uop_MOVZX(ir, IREG_flags_op1, IREG_temp0_W); + if (block->flags & CODEBLOCK_NO_IMMEDIATES) + uop_MOVZX(ir, IREG_flags_op2, IREG_temp2_W); + else + uop_MOV_IMM(ir, IREG_flags_op2, imm); + uop_MOV_IMM(ir, IREG_flags_op, FLAGS_SBC16); + uop_MOVZX(ir, IREG_flags_res, IREG_temp1_W); + break; + + case 0x20: /*AND*/ + if (block->flags & CODEBLOCK_NO_IMMEDIATES) + uop_AND(ir, IREG_temp0_W, IREG_temp0_W, IREG_temp2_W); + else + uop_AND_IMM(ir, IREG_temp0_W, IREG_temp0_W, imm); + uop_MEM_STORE_REG(ir, ireg_seg_base(target_seg), IREG_eaaddr, IREG_temp0_W); + uop_MOVZX(ir, IREG_flags_res, IREG_temp0_W); + uop_MOV_IMM(ir, IREG_flags_op, FLAGS_ZN16); + break; + + case 0x28: /*SUB*/ + if (block->flags & CODEBLOCK_NO_IMMEDIATES) + uop_SUB(ir, IREG_temp1_W, IREG_temp0_W, IREG_temp2_W); + else + uop_SUB_IMM(ir, IREG_temp1_W, IREG_temp0_W, imm); + uop_MEM_STORE_REG(ir, ireg_seg_base(target_seg), IREG_eaaddr, IREG_temp1_W); + uop_MOVZX(ir, IREG_flags_op1, IREG_temp0_W); + if (block->flags & CODEBLOCK_NO_IMMEDIATES) + uop_MOVZX(ir, IREG_flags_op2, IREG_temp2_W); + else + uop_MOV_IMM(ir, IREG_flags_op2, imm); + uop_MOV_IMM(ir, IREG_flags_op, FLAGS_SUB16); + uop_MOVZX(ir, IREG_flags_res, IREG_temp1_W); + break; + + case 0x30: /*XOR*/ + if (block->flags & CODEBLOCK_NO_IMMEDIATES) + uop_XOR(ir, IREG_temp0_W, IREG_temp0_W, IREG_temp2_W); + else + uop_XOR_IMM(ir, IREG_temp0_W, IREG_temp0_W, imm); + uop_MEM_STORE_REG(ir, ireg_seg_base(target_seg), IREG_eaaddr, IREG_temp0_W); + uop_MOVZX(ir, IREG_flags_res, IREG_temp0_W); + uop_MOV_IMM(ir, IREG_flags_op, FLAGS_ZN16); + break; + + case 0x38: /*CMP*/ + uop_MOVZX(ir, IREG_flags_op1, IREG_temp0_W); + if (block->flags & CODEBLOCK_NO_IMMEDIATES) { + uop_MOVZX(ir, IREG_flags_op2, IREG_temp2_W); + uop_SUB(ir, IREG_flags_res_W, IREG_temp0_W, IREG_temp2_W); + } else { + uop_MOV_IMM(ir, IREG_flags_op2, imm); + uop_SUB_IMM(ir, IREG_flags_res_W, IREG_temp0_W, imm); + } + uop_MOVZX(ir, IREG_flags_res, IREG_flags_res_W); + uop_MOV_IMM(ir, IREG_flags_op, FLAGS_SUB16); + break; + + default: + return 0; } + } - uop_MOV_IMM(ir, IREG_flags_op, FLAGS_SUB16); - - codegen_flags_changed = 1; - return op_pc + 1; + codegen_flags_changed = 1; + if (!skip_immediate) + codegen_mark_code_present(block, cs + op_pc + 1, 2); + return op_pc + 3; } -uint32_t ropSUB_l_rm(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) +uint32_t +rop81_l(codeblock_t *block, ir_data_t *ir, UNUSED(uint8_t opcode), uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) { - int dest_reg = (fetchdat >> 3) & 7; + int skip_immediate = 0; - codegen_mark_code_present(block, cs+op_pc, 1); - if ((fetchdat & 0xc0) == 0xc0) - { - int src_reg = fetchdat & 7; + codegen_mark_code_present(block, cs + op_pc, 1); + if ((fetchdat & 0xc0) == 0xc0) { + int dest_reg = fetchdat & 7; + uint32_t imm = fastreadl(cs + op_pc + 1); - uop_MOV(ir, IREG_flags_op1, IREG_32(dest_reg)); - uop_MOV(ir, IREG_flags_op2, IREG_32(src_reg)); - uop_SUB(ir, IREG_32(dest_reg), IREG_32(dest_reg), IREG_32(src_reg)); - } - else - { - x86seg *target_seg; - - uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc); - target_seg = codegen_generate_ea(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32, 0); - codegen_check_seg_read(block, ir, target_seg); - uop_MEM_LOAD_REG(ir, IREG_flags_op2, ireg_seg_base(target_seg), IREG_eaaddr); - uop_MOV(ir, IREG_flags_op1, IREG_32(dest_reg)); - uop_SUB(ir, IREG_32(dest_reg), IREG_32(dest_reg), IREG_flags_op2); + if (block->flags & CODEBLOCK_NO_IMMEDIATES) { + skip_immediate = 1; + LOAD_IMMEDIATE_FROM_RAM_32(block, ir, IREG_temp0, cs + op_pc + 1); } - uop_MOV_IMM(ir, IREG_flags_op, FLAGS_SUB32); - uop_MOV(ir, IREG_flags_res, IREG_32(dest_reg)); - - codegen_flags_changed = 1; - return op_pc + 1; -} -uint32_t ropSUB_l_rmw(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) -{ - int src_reg = (fetchdat >> 3) & 7; - - codegen_mark_code_present(block, cs+op_pc, 1); - if ((fetchdat & 0xc0) == 0xc0) - { - int dest_reg = fetchdat & 7; - + switch (fetchdat & 0x38) { + case 0x00: /*ADD*/ uop_MOV(ir, IREG_flags_op1, IREG_32(dest_reg)); - uop_MOV(ir, IREG_flags_op2, IREG_32(src_reg)); - uop_SUB(ir, IREG_32(dest_reg), IREG_32(dest_reg), IREG_32(src_reg)); + if (block->flags & CODEBLOCK_NO_IMMEDIATES) { + uop_ADD(ir, IREG_32(dest_reg), IREG_32(dest_reg), IREG_temp0); + uop_MOV(ir, IREG_flags_op2, IREG_temp0); + } else { + uop_ADD_IMM(ir, IREG_32(dest_reg), IREG_32(dest_reg), imm); + uop_MOV_IMM(ir, IREG_flags_op2, imm); + } + uop_MOV_IMM(ir, IREG_flags_op, FLAGS_ADD32); uop_MOV(ir, IREG_flags_res, IREG_32(dest_reg)); + break; + + case 0x08: /*OR*/ + if (block->flags & CODEBLOCK_NO_IMMEDIATES) + uop_OR(ir, IREG_32(dest_reg), IREG_32(dest_reg), IREG_temp0); + else + uop_OR_IMM(ir, IREG_32(dest_reg), IREG_32(dest_reg), imm); + uop_MOV_IMM(ir, IREG_flags_op, FLAGS_ZN32); + uop_MOV(ir, IREG_flags_res, IREG_32(dest_reg)); + break; + + case 0x10: /*ADC*/ + get_cf(ir, IREG_temp1); + uop_MOV(ir, IREG_flags_op1, IREG_32(dest_reg)); + if (block->flags & CODEBLOCK_NO_IMMEDIATES) { + uop_ADD(ir, IREG_32(dest_reg), IREG_32(dest_reg), IREG_temp0); + uop_MOV(ir, IREG_flags_op2, IREG_temp0); + } else { + uop_ADD_IMM(ir, IREG_32(dest_reg), IREG_32(dest_reg), imm); + uop_MOV_IMM(ir, IREG_flags_op2, imm); + } + uop_ADD(ir, IREG_32(dest_reg), IREG_32(dest_reg), IREG_temp1); + uop_MOV_IMM(ir, IREG_flags_op, FLAGS_ADC32); + uop_MOV(ir, IREG_flags_res, IREG_32(dest_reg)); + break; + + case 0x18: /*SBB*/ + get_cf(ir, IREG_temp1); + uop_MOV(ir, IREG_flags_op1, IREG_32(dest_reg)); + if (block->flags & CODEBLOCK_NO_IMMEDIATES) { + uop_SUB(ir, IREG_32(dest_reg), IREG_32(dest_reg), IREG_temp0); + uop_MOV(ir, IREG_flags_op2, IREG_temp0); + } else { + uop_SUB_IMM(ir, IREG_32(dest_reg), IREG_32(dest_reg), imm); + uop_MOV_IMM(ir, IREG_flags_op2, imm); + } + uop_SUB(ir, IREG_32(dest_reg), IREG_32(dest_reg), IREG_temp1); + uop_MOV_IMM(ir, IREG_flags_op, FLAGS_SBC32); + uop_MOV(ir, IREG_flags_res, IREG_32(dest_reg)); + break; + + case 0x20: /*AND*/ + if (block->flags & CODEBLOCK_NO_IMMEDIATES) + uop_AND(ir, IREG_32(dest_reg), IREG_32(dest_reg), IREG_temp0); + else + uop_AND_IMM(ir, IREG_32(dest_reg), IREG_32(dest_reg), imm); + uop_MOV_IMM(ir, IREG_flags_op, FLAGS_ZN32); + uop_MOV(ir, IREG_flags_res, IREG_32(dest_reg)); + break; + + case 0x28: /*SUB*/ + uop_MOV(ir, IREG_flags_op1, IREG_32(dest_reg)); + if (block->flags & CODEBLOCK_NO_IMMEDIATES) { + uop_SUB(ir, IREG_32(dest_reg), IREG_32(dest_reg), IREG_temp0); + uop_MOV(ir, IREG_flags_op2, IREG_temp0); + } else { + uop_SUB_IMM(ir, IREG_32(dest_reg), IREG_32(dest_reg), imm); + uop_MOV_IMM(ir, IREG_flags_op2, imm); + } + uop_MOV_IMM(ir, IREG_flags_op, FLAGS_SUB32); + uop_MOV(ir, IREG_flags_res, IREG_32(dest_reg)); + break; + + case 0x30: /*XOR*/ + if (block->flags & CODEBLOCK_NO_IMMEDIATES) + uop_XOR(ir, IREG_32(dest_reg), IREG_32(dest_reg), IREG_temp0); + else + uop_XOR_IMM(ir, IREG_32(dest_reg), IREG_32(dest_reg), imm); + uop_MOV_IMM(ir, IREG_flags_op, FLAGS_ZN32); + uop_MOV(ir, IREG_flags_res, IREG_32(dest_reg)); + break; + + case 0x38: /*CMP*/ + uop_MOV(ir, IREG_flags_op1, IREG_32(dest_reg)); + if (block->flags & CODEBLOCK_NO_IMMEDIATES) { + uop_SUB(ir, IREG_flags_res, IREG_32(dest_reg), IREG_temp0); + uop_MOV(ir, IREG_flags_op2, IREG_temp0); + } else { + uop_SUB_IMM(ir, IREG_flags_res, IREG_32(dest_reg), imm); + uop_MOV_IMM(ir, IREG_flags_op2, imm); + } + uop_MOV_IMM(ir, IREG_flags_op, FLAGS_SUB32); + break; + + default: + return 0; } + } else { + x86seg *target_seg; + uint32_t imm; + + uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc); + target_seg = codegen_generate_ea(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32, 0); + if ((fetchdat & 0x38) == 0x38) /*CMP*/ + codegen_check_seg_read(block, ir, target_seg); else - { - x86seg *target_seg; + codegen_check_seg_write(block, ir, target_seg); + imm = fastreadl(cs + op_pc + 1); + uop_MEM_LOAD_REG(ir, IREG_temp0, ireg_seg_base(target_seg), IREG_eaaddr); - uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc); - target_seg = codegen_generate_ea(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32, 0); - codegen_check_seg_write(block, ir, target_seg); + if (block->flags & CODEBLOCK_NO_IMMEDIATES) { + skip_immediate = 1; + LOAD_IMMEDIATE_FROM_RAM_32(block, ir, IREG_temp2, cs + op_pc + 1); + } - uop_MEM_LOAD_REG(ir, IREG_temp0, ireg_seg_base(target_seg), IREG_eaaddr); - uop_SUB(ir, IREG_temp1, IREG_temp0, IREG_32(src_reg)); + switch (fetchdat & 0x38) { + case 0x00: /*ADD*/ + if (block->flags & CODEBLOCK_NO_IMMEDIATES) + uop_ADD(ir, IREG_temp1, IREG_temp0, IREG_temp2); + else + uop_ADD_IMM(ir, IREG_temp1, IREG_temp0, imm); uop_MEM_STORE_REG(ir, ireg_seg_base(target_seg), IREG_eaaddr, IREG_temp1); uop_MOV(ir, IREG_flags_op1, IREG_temp0); - uop_MOV(ir, IREG_flags_op2, IREG_32(src_reg)); + if (block->flags & CODEBLOCK_NO_IMMEDIATES) + uop_MOV(ir, IREG_flags_op2, IREG_temp2); + else + uop_MOV_IMM(ir, IREG_flags_op2, imm); + uop_MOV_IMM(ir, IREG_flags_op, FLAGS_ADD32); uop_MOV(ir, IREG_flags_res, IREG_temp1); - } + break; - uop_MOV_IMM(ir, IREG_flags_op, FLAGS_SUB32); - - codegen_flags_changed = 1; - return op_pc + 1; -} - -uint32_t rop80(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) -{ - int skip_immediate = 0; - - codegen_mark_code_present(block, cs+op_pc, 1); - if ((fetchdat & 0xc0) == 0xc0) - { - int dest_reg = fetchdat & 7; - uint8_t imm = fastreadb(cs + op_pc + 1); - + case 0x08: /*OR*/ if (block->flags & CODEBLOCK_NO_IMMEDIATES) - { - skip_immediate = 1; - LOAD_IMMEDIATE_FROM_RAM_8(block, ir, IREG_temp0_B, cs+op_pc+1); - } - - switch (fetchdat & 0x38) - { - case 0x00: /*ADD*/ - uop_MOVZX(ir, IREG_flags_op1, IREG_8(dest_reg)); - if (block->flags & CODEBLOCK_NO_IMMEDIATES) - { - uop_ADD(ir, IREG_8(dest_reg), IREG_8(dest_reg), IREG_temp0_B); - uop_MOVZX(ir, IREG_flags_op2, IREG_temp0_B); - } - else - { - uop_ADD_IMM(ir, IREG_8(dest_reg), IREG_8(dest_reg), imm); - uop_MOV_IMM(ir, IREG_flags_op2, imm); - } - uop_MOV_IMM(ir, IREG_flags_op, FLAGS_ADD8); - uop_MOVZX(ir, IREG_flags_res, IREG_8(dest_reg)); - break; - - case 0x08: /*OR*/ - if (block->flags & CODEBLOCK_NO_IMMEDIATES) - uop_OR(ir, IREG_8(dest_reg), IREG_8(dest_reg), IREG_temp0_B); - else - uop_OR_IMM(ir, IREG_8(dest_reg), IREG_8(dest_reg), imm); - uop_MOV_IMM(ir, IREG_flags_op, FLAGS_ZN8); - uop_MOVZX(ir, IREG_flags_res, IREG_8(dest_reg)); - break; - - case 0x10: /*ADC*/ - get_cf(ir, IREG_temp1); - uop_MOVZX(ir, IREG_flags_op1, IREG_8(dest_reg)); - if (block->flags & CODEBLOCK_NO_IMMEDIATES) - { - uop_ADD(ir, IREG_8(dest_reg), IREG_8(dest_reg), IREG_temp0_B); - uop_MOVZX(ir, IREG_flags_op2, IREG_temp0_B); - } - else - { - uop_ADD_IMM(ir, IREG_8(dest_reg), IREG_8(dest_reg), imm); - uop_MOV_IMM(ir, IREG_flags_op2, imm); - } - uop_ADD(ir, IREG_8(dest_reg), IREG_8(dest_reg), IREG_temp1_B); - uop_MOV_IMM(ir, IREG_flags_op, FLAGS_ADC8); - uop_MOVZX(ir, IREG_flags_res, IREG_8(dest_reg)); - break; - - case 0x18: /*SBB*/ - get_cf(ir, IREG_temp1); - uop_MOVZX(ir, IREG_flags_op1, IREG_8(dest_reg)); - if (block->flags & CODEBLOCK_NO_IMMEDIATES) - { - uop_SUB(ir, IREG_8(dest_reg), IREG_8(dest_reg), IREG_temp0_B); - uop_MOVZX(ir, IREG_flags_op2, IREG_temp0_B); - } - else - { - uop_SUB_IMM(ir, IREG_8(dest_reg), IREG_8(dest_reg), imm); - uop_MOV_IMM(ir, IREG_flags_op2, imm); - } - uop_SUB(ir, IREG_8(dest_reg), IREG_8(dest_reg), IREG_temp1_B); - uop_MOV_IMM(ir, IREG_flags_op, FLAGS_SBC8); - uop_MOVZX(ir, IREG_flags_res, IREG_8(dest_reg)); - break; - - case 0x20: /*AND*/ - if (block->flags & CODEBLOCK_NO_IMMEDIATES) - uop_AND(ir, IREG_8(dest_reg), IREG_8(dest_reg), IREG_temp0_B); - else - uop_AND_IMM(ir, IREG_8(dest_reg), IREG_8(dest_reg), imm); - uop_MOV_IMM(ir, IREG_flags_op, FLAGS_ZN8); - uop_MOVZX(ir, IREG_flags_res, IREG_8(dest_reg)); - break; - - case 0x28: /*SUB*/ - uop_MOVZX(ir, IREG_flags_op1, IREG_8(dest_reg)); - if (block->flags & CODEBLOCK_NO_IMMEDIATES) - { - uop_SUB(ir, IREG_8(dest_reg), IREG_8(dest_reg), IREG_temp0_B); - uop_MOVZX(ir, IREG_flags_op2, IREG_temp0_B); - } - else - { - uop_SUB_IMM(ir, IREG_8(dest_reg), IREG_8(dest_reg), imm); - uop_MOV_IMM(ir, IREG_flags_op2, imm); - } - uop_MOV_IMM(ir, IREG_flags_op, FLAGS_SUB8); - uop_MOVZX(ir, IREG_flags_res, IREG_8(dest_reg)); - break; - - case 0x30: /*XOR*/ - if (block->flags & CODEBLOCK_NO_IMMEDIATES) - uop_XOR(ir, IREG_8(dest_reg), IREG_8(dest_reg), IREG_temp0_B); - else - uop_XOR_IMM(ir, IREG_8(dest_reg), IREG_8(dest_reg), imm); - uop_MOV_IMM(ir, IREG_flags_op, FLAGS_ZN8); - uop_MOVZX(ir, IREG_flags_res, IREG_8(dest_reg)); - break; - - case 0x38: /*CMP*/ - uop_MOVZX(ir, IREG_flags_op1, IREG_8(dest_reg)); - if (block->flags & CODEBLOCK_NO_IMMEDIATES) - { - uop_SUB(ir, IREG_flags_res_B, IREG_8(dest_reg), IREG_temp0_B); - uop_MOVZX(ir, IREG_flags_op2, IREG_temp0_B); - } - else - { - uop_SUB_IMM(ir, IREG_flags_res_B, IREG_8(dest_reg), imm); - uop_MOV_IMM(ir, IREG_flags_op2, imm); - } - uop_MOVZX(ir, IREG_flags_res, IREG_flags_res_B); - uop_MOV_IMM(ir, IREG_flags_op, FLAGS_SUB8); - break; - - default: - return 0; - } - } - else - { - x86seg *target_seg; - uint8_t imm; - - uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc); - target_seg = codegen_generate_ea(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32, 0); - if ((fetchdat & 0x38) == 0x38) /*CMP*/ - codegen_check_seg_read(block, ir, target_seg); + uop_OR(ir, IREG_temp0, IREG_temp0, IREG_temp2); else - codegen_check_seg_write(block, ir, target_seg); - imm = fastreadb(cs + op_pc + 1); - uop_MEM_LOAD_REG(ir, IREG_temp0_B, ireg_seg_base(target_seg), IREG_eaaddr); - - switch (fetchdat & 0x38) - { - case 0x00: /*ADD*/ - uop_ADD_IMM(ir, IREG_temp1_B, IREG_temp0_B, imm); - uop_MEM_STORE_REG(ir, ireg_seg_base(target_seg), IREG_eaaddr, IREG_temp1_B); - uop_MOVZX(ir, IREG_flags_op1, IREG_temp0_B); - uop_MOV_IMM(ir, IREG_flags_op2, imm); - uop_MOV_IMM(ir, IREG_flags_op, FLAGS_ADD8); - uop_MOVZX(ir, IREG_flags_res, IREG_temp1_B); - break; - - case 0x08: /*OR*/ - uop_OR_IMM(ir, IREG_temp0_B, IREG_temp0_B, imm); - uop_MEM_STORE_REG(ir, ireg_seg_base(target_seg), IREG_eaaddr, IREG_temp0_B); - uop_MOVZX(ir, IREG_flags_res, IREG_temp0_B); - uop_MOV_IMM(ir, IREG_flags_op, FLAGS_ZN8); - break; - - case 0x10: /*ADC*/ - get_cf(ir, IREG_temp2); - uop_ADD_IMM(ir, IREG_temp1_B, IREG_temp0_B, imm); - uop_ADD(ir, IREG_temp1_B, IREG_temp1_B, IREG_temp2_B); - uop_MEM_STORE_REG(ir, ireg_seg_base(target_seg), IREG_eaaddr, IREG_temp1_B); - uop_MOVZX(ir, IREG_flags_op1, IREG_temp0_B); - uop_MOV_IMM(ir, IREG_flags_op2, imm); - uop_MOV_IMM(ir, IREG_flags_op, FLAGS_ADC8); - uop_MOVZX(ir, IREG_flags_res, IREG_temp1_B); - break; - - case 0x18: /*SBB*/ - get_cf(ir, IREG_temp2); - uop_SUB_IMM(ir, IREG_temp1_B, IREG_temp0_B, imm); - uop_SUB(ir, IREG_temp1_B, IREG_temp1_B, IREG_temp2_B); - uop_MEM_STORE_REG(ir, ireg_seg_base(target_seg), IREG_eaaddr, IREG_temp1_B); - uop_MOVZX(ir, IREG_flags_op1, IREG_temp0_B); - uop_MOV_IMM(ir, IREG_flags_op2, imm); - uop_MOV_IMM(ir, IREG_flags_op, FLAGS_SBC8); - uop_MOVZX(ir, IREG_flags_res, IREG_temp1_B); - break; - - case 0x20: /*AND*/ - uop_AND_IMM(ir, IREG_temp0_B, IREG_temp0_B, imm); - uop_MEM_STORE_REG(ir, ireg_seg_base(target_seg), IREG_eaaddr, IREG_temp0_B); - uop_MOVZX(ir, IREG_flags_res, IREG_temp0_B); - uop_MOV_IMM(ir, IREG_flags_op, FLAGS_ZN8); - break; - - case 0x28: /*SUB*/ - uop_SUB_IMM(ir, IREG_temp1_B, IREG_temp0_B, imm); - uop_MEM_STORE_REG(ir, ireg_seg_base(target_seg), IREG_eaaddr, IREG_temp1_B); - uop_MOVZX(ir, IREG_flags_op1, IREG_temp0_B); - uop_MOV_IMM(ir, IREG_flags_op2, imm); - uop_MOV_IMM(ir, IREG_flags_op, FLAGS_SUB8); - uop_MOVZX(ir, IREG_flags_res, IREG_temp1_B); - break; - - case 0x30: /*XOR*/ - uop_XOR_IMM(ir, IREG_temp0_B, IREG_temp0_B, imm); - uop_MEM_STORE_REG(ir, ireg_seg_base(target_seg), IREG_eaaddr, IREG_temp0_B); - uop_MOVZX(ir, IREG_flags_res, IREG_temp0_B); - uop_MOV_IMM(ir, IREG_flags_op, FLAGS_ZN8); - break; - - case 0x38: /*CMP*/ - uop_MOVZX(ir, IREG_flags_op1, IREG_temp0_B); - uop_MOV_IMM(ir, IREG_flags_op2, imm); - uop_SUB_IMM(ir, IREG_flags_res_B, IREG_temp0_B, imm); - uop_MOVZX(ir, IREG_flags_res, IREG_flags_res_B); - uop_MOV_IMM(ir, IREG_flags_op, FLAGS_SUB8); - break; - - default: - return 0; - } - } - - codegen_flags_changed = 1; - if (!skip_immediate) - codegen_mark_code_present(block, cs+op_pc+1, 1); - return op_pc + 2; -} -uint32_t rop81_w(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) -{ - int skip_immediate = 0; - - codegen_mark_code_present(block, cs+op_pc, 1); - if ((fetchdat & 0xc0) == 0xc0) - { - int dest_reg = fetchdat & 7; - uint16_t imm = fastreadw(cs + op_pc + 1); + uop_OR_IMM(ir, IREG_temp0, IREG_temp0, imm); + uop_MEM_STORE_REG(ir, ireg_seg_base(target_seg), IREG_eaaddr, IREG_temp0); + uop_MOV(ir, IREG_flags_res, IREG_temp0); + uop_MOV_IMM(ir, IREG_flags_op, FLAGS_ZN32); + break; + case 0x10: /*ADC*/ + get_cf(ir, IREG_temp3); if (block->flags & CODEBLOCK_NO_IMMEDIATES) - { - skip_immediate = 1; - LOAD_IMMEDIATE_FROM_RAM_16(block, ir, IREG_temp0_W, cs+op_pc+1); - } - - switch (fetchdat & 0x38) - { - case 0x00: /*ADD*/ - uop_MOVZX(ir, IREG_flags_op1, IREG_16(dest_reg)); - if (block->flags & CODEBLOCK_NO_IMMEDIATES) - { - uop_ADD(ir, IREG_16(dest_reg), IREG_16(dest_reg), IREG_temp0_W); - uop_MOVZX(ir, IREG_flags_op2, IREG_temp0_W); - } - else - { - uop_ADD_IMM(ir, IREG_16(dest_reg), IREG_16(dest_reg), imm); - uop_MOV_IMM(ir, IREG_flags_op2, imm); - } - uop_MOV_IMM(ir, IREG_flags_op, FLAGS_ADD16); - uop_MOVZX(ir, IREG_flags_res, IREG_16(dest_reg)); - break; - - case 0x08: /*OR*/ - if (block->flags & CODEBLOCK_NO_IMMEDIATES) - uop_OR(ir, IREG_16(dest_reg), IREG_16(dest_reg), IREG_temp0_W); - else - uop_OR_IMM(ir, IREG_16(dest_reg), IREG_16(dest_reg), imm); - uop_MOV_IMM(ir, IREG_flags_op, FLAGS_ZN16); - uop_MOVZX(ir, IREG_flags_res, IREG_16(dest_reg)); - break; - - case 0x10: /*ADC*/ - get_cf(ir, IREG_temp1); - uop_MOVZX(ir, IREG_flags_op1, IREG_16(dest_reg)); - if (block->flags & CODEBLOCK_NO_IMMEDIATES) - { - uop_ADD(ir, IREG_16(dest_reg), IREG_16(dest_reg), IREG_temp0_W); - uop_MOVZX(ir, IREG_flags_op2, IREG_temp0_W); - } - else - { - uop_ADD_IMM(ir, IREG_16(dest_reg), IREG_16(dest_reg), imm); - uop_MOV_IMM(ir, IREG_flags_op2, imm); - } - uop_ADD(ir, IREG_16(dest_reg), IREG_16(dest_reg), IREG_temp1_W); - uop_MOV_IMM(ir, IREG_flags_op, FLAGS_ADC16); - uop_MOVZX(ir, IREG_flags_res, IREG_16(dest_reg)); - break; - - case 0x18: /*SBB*/ - get_cf(ir, IREG_temp1); - uop_MOVZX(ir, IREG_flags_op1, IREG_16(dest_reg)); - if (block->flags & CODEBLOCK_NO_IMMEDIATES) - { - uop_SUB(ir, IREG_16(dest_reg), IREG_16(dest_reg), IREG_temp0_W); - uop_MOVZX(ir, IREG_flags_op2, IREG_temp0_W); - } - else - { - uop_SUB_IMM(ir, IREG_16(dest_reg), IREG_16(dest_reg), imm); - uop_MOV_IMM(ir, IREG_flags_op2, imm); - } - uop_SUB(ir, IREG_16(dest_reg), IREG_16(dest_reg), IREG_temp1_W); - uop_MOV_IMM(ir, IREG_flags_op, FLAGS_SBC16); - uop_MOVZX(ir, IREG_flags_res, IREG_16(dest_reg)); - break; - - case 0x20: /*AND*/ - if (block->flags & CODEBLOCK_NO_IMMEDIATES) - uop_AND(ir, IREG_16(dest_reg), IREG_16(dest_reg), IREG_temp0_W); - else - uop_AND_IMM(ir, IREG_16(dest_reg), IREG_16(dest_reg), imm); - uop_MOV_IMM(ir, IREG_flags_op, FLAGS_ZN16); - uop_MOVZX(ir, IREG_flags_res, IREG_16(dest_reg)); - break; - - case 0x28: /*SUB*/ - uop_MOVZX(ir, IREG_flags_op1, IREG_16(dest_reg)); - if (block->flags & CODEBLOCK_NO_IMMEDIATES) - { - uop_SUB(ir, IREG_16(dest_reg), IREG_16(dest_reg), IREG_temp0_W); - uop_MOVZX(ir, IREG_flags_op2, IREG_temp0_W); - } - else - { - uop_SUB_IMM(ir, IREG_16(dest_reg), IREG_16(dest_reg), imm); - uop_MOV_IMM(ir, IREG_flags_op2, imm); - } - uop_MOV_IMM(ir, IREG_flags_op, FLAGS_SUB16); - uop_MOVZX(ir, IREG_flags_res, IREG_16(dest_reg)); - break; - - case 0x30: /*XOR*/ - if (block->flags & CODEBLOCK_NO_IMMEDIATES) - uop_XOR(ir, IREG_16(dest_reg), IREG_16(dest_reg), IREG_temp0_W); - else - uop_XOR_IMM(ir, IREG_16(dest_reg), IREG_16(dest_reg), imm); - uop_MOV_IMM(ir, IREG_flags_op, FLAGS_ZN16); - uop_MOVZX(ir, IREG_flags_res, IREG_16(dest_reg)); - break; - - case 0x38: /*CMP*/ - uop_MOVZX(ir, IREG_flags_op1, IREG_16(dest_reg)); - if (block->flags & CODEBLOCK_NO_IMMEDIATES) - { - uop_SUB(ir, IREG_flags_res_W, IREG_16(dest_reg), IREG_temp0_W); - uop_MOVZX(ir, IREG_flags_op2, IREG_temp0_W); - } - else - { - uop_SUB_IMM(ir, IREG_flags_res_W, IREG_16(dest_reg), imm); - uop_MOV_IMM(ir, IREG_flags_op2, imm); - } - uop_MOVZX(ir, IREG_flags_res, IREG_flags_res_W); - uop_MOV_IMM(ir, IREG_flags_op, FLAGS_SUB16); - break; - - default: - return 0; - } - } - else - { - x86seg *target_seg; - uint16_t imm; - - uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc); - target_seg = codegen_generate_ea(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32, 0); - if ((fetchdat & 0x38) == 0x38) /*CMP*/ - codegen_check_seg_read(block, ir, target_seg); + uop_ADD(ir, IREG_temp1, IREG_temp0, IREG_temp2); else - codegen_check_seg_write(block, ir, target_seg); - imm = fastreadw(cs + op_pc + 1); - uop_MEM_LOAD_REG(ir, IREG_temp0_W, ireg_seg_base(target_seg), IREG_eaaddr); + uop_ADD_IMM(ir, IREG_temp1, IREG_temp0, imm); + uop_ADD(ir, IREG_temp1, IREG_temp1, IREG_temp3); + uop_MEM_STORE_REG(ir, ireg_seg_base(target_seg), IREG_eaaddr, IREG_temp1); + uop_MOV(ir, IREG_flags_op1, IREG_temp0); if (block->flags & CODEBLOCK_NO_IMMEDIATES) - { - skip_immediate = 1; - LOAD_IMMEDIATE_FROM_RAM_16(block, ir, IREG_temp2_W, cs+op_pc+1); - } - - switch (fetchdat & 0x38) - { - case 0x00: /*ADD*/ - if (block->flags & CODEBLOCK_NO_IMMEDIATES) - uop_ADD(ir, IREG_temp1_W, IREG_temp0_W, IREG_temp2_W); - else - uop_ADD_IMM(ir, IREG_temp1_W, IREG_temp0_W, imm); - uop_MEM_STORE_REG(ir, ireg_seg_base(target_seg), IREG_eaaddr, IREG_temp1_W); - uop_MOVZX(ir, IREG_flags_op1, IREG_temp0_W); - if (block->flags & CODEBLOCK_NO_IMMEDIATES) - uop_MOVZX(ir, IREG_flags_op2, IREG_temp2_W); - else - uop_MOV_IMM(ir, IREG_flags_op2, imm); - uop_MOV_IMM(ir, IREG_flags_op, FLAGS_ADD16); - uop_MOVZX(ir, IREG_flags_res, IREG_temp1_W); - break; - - case 0x08: /*OR*/ - if (block->flags & CODEBLOCK_NO_IMMEDIATES) - uop_OR(ir, IREG_temp0_W, IREG_temp0_W, IREG_temp2_W); - else - uop_OR_IMM(ir, IREG_temp0_W, IREG_temp0_W, imm); - uop_MEM_STORE_REG(ir, ireg_seg_base(target_seg), IREG_eaaddr, IREG_temp0_W); - uop_MOVZX(ir, IREG_flags_res, IREG_temp0_W); - uop_MOV_IMM(ir, IREG_flags_op, FLAGS_ZN16); - break; - - case 0x10: /*ADC*/ - get_cf(ir, IREG_temp3); - if (block->flags & CODEBLOCK_NO_IMMEDIATES) - uop_ADD(ir, IREG_temp1_W, IREG_temp0_W, IREG_temp2_W); - else - uop_ADD_IMM(ir, IREG_temp1_W, IREG_temp0_W, imm); - uop_ADD(ir, IREG_temp1_W, IREG_temp1_W, IREG_temp3_W); - uop_MEM_STORE_REG(ir, ireg_seg_base(target_seg), IREG_eaaddr, IREG_temp1_W); - uop_MOVZX(ir, IREG_flags_op1, IREG_temp0_W); - if (block->flags & CODEBLOCK_NO_IMMEDIATES) - uop_MOVZX(ir, IREG_flags_op2, IREG_temp2_W); - else - uop_MOV_IMM(ir, IREG_flags_op2, imm); - uop_MOV_IMM(ir, IREG_flags_op, FLAGS_ADC16); - uop_MOVZX(ir, IREG_flags_res, IREG_temp1_W); - break; - - case 0x18: /*SBB*/ - get_cf(ir, IREG_temp3); - if (block->flags & CODEBLOCK_NO_IMMEDIATES) - uop_SUB(ir, IREG_temp1_W, IREG_temp0_W, IREG_temp2_W); - else - uop_SUB_IMM(ir, IREG_temp1_W, IREG_temp0_W, imm); - uop_SUB(ir, IREG_temp1_W, IREG_temp1_W, IREG_temp3_W); - uop_MEM_STORE_REG(ir, ireg_seg_base(target_seg), IREG_eaaddr, IREG_temp1_W); - uop_MOVZX(ir, IREG_flags_op1, IREG_temp0_W); - if (block->flags & CODEBLOCK_NO_IMMEDIATES) - uop_MOVZX(ir, IREG_flags_op2, IREG_temp2_W); - else - uop_MOV_IMM(ir, IREG_flags_op2, imm); - uop_MOV_IMM(ir, IREG_flags_op, FLAGS_SBC16); - uop_MOVZX(ir, IREG_flags_res, IREG_temp1_W); - break; - - case 0x20: /*AND*/ - if (block->flags & CODEBLOCK_NO_IMMEDIATES) - uop_AND(ir, IREG_temp0_W, IREG_temp0_W, IREG_temp2_W); - else - uop_AND_IMM(ir, IREG_temp0_W, IREG_temp0_W, imm); - uop_MEM_STORE_REG(ir, ireg_seg_base(target_seg), IREG_eaaddr, IREG_temp0_W); - uop_MOVZX(ir, IREG_flags_res, IREG_temp0_W); - uop_MOV_IMM(ir, IREG_flags_op, FLAGS_ZN16); - break; - - case 0x28: /*SUB*/ - if (block->flags & CODEBLOCK_NO_IMMEDIATES) - uop_SUB(ir, IREG_temp1_W, IREG_temp0_W, IREG_temp2_W); - else - uop_SUB_IMM(ir, IREG_temp1_W, IREG_temp0_W, imm); - uop_MEM_STORE_REG(ir, ireg_seg_base(target_seg), IREG_eaaddr, IREG_temp1_W); - uop_MOVZX(ir, IREG_flags_op1, IREG_temp0_W); - if (block->flags & CODEBLOCK_NO_IMMEDIATES) - uop_MOVZX(ir, IREG_flags_op2, IREG_temp2_W); - else - uop_MOV_IMM(ir, IREG_flags_op2, imm); - uop_MOV_IMM(ir, IREG_flags_op, FLAGS_SUB16); - uop_MOVZX(ir, IREG_flags_res, IREG_temp1_W); - break; - - case 0x30: /*XOR*/ - if (block->flags & CODEBLOCK_NO_IMMEDIATES) - uop_XOR(ir, IREG_temp0_W, IREG_temp0_W, IREG_temp2_W); - else - uop_XOR_IMM(ir, IREG_temp0_W, IREG_temp0_W, imm); - uop_MEM_STORE_REG(ir, ireg_seg_base(target_seg), IREG_eaaddr, IREG_temp0_W); - uop_MOVZX(ir, IREG_flags_res, IREG_temp0_W); - uop_MOV_IMM(ir, IREG_flags_op, FLAGS_ZN16); - break; - - case 0x38: /*CMP*/ - uop_MOVZX(ir, IREG_flags_op1, IREG_temp0_W); - if (block->flags & CODEBLOCK_NO_IMMEDIATES) - { - uop_MOVZX(ir, IREG_flags_op2, IREG_temp2_W); - uop_SUB(ir, IREG_flags_res_W, IREG_temp0_W, IREG_temp2_W); - } - else - { - uop_MOV_IMM(ir, IREG_flags_op2, imm); - uop_SUB_IMM(ir, IREG_flags_res_W, IREG_temp0_W, imm); - } - uop_MOVZX(ir, IREG_flags_res, IREG_flags_res_W); - uop_MOV_IMM(ir, IREG_flags_op, FLAGS_SUB16); - break; - - default: - return 0; - } - } - - codegen_flags_changed = 1; - if (!skip_immediate) - codegen_mark_code_present(block, cs+op_pc+1, 2); - return op_pc + 3; -} -uint32_t rop81_l(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) -{ - int skip_immediate = 0; - - codegen_mark_code_present(block, cs+op_pc, 1); - if ((fetchdat & 0xc0) == 0xc0) - { - int dest_reg = fetchdat & 7; - uint32_t imm = fastreadl(cs + op_pc + 1); + uop_MOV(ir, IREG_flags_op2, IREG_temp2); + else + uop_MOV_IMM(ir, IREG_flags_op2, imm); + uop_MOV_IMM(ir, IREG_flags_op, FLAGS_ADC32); + uop_MOV(ir, IREG_flags_res, IREG_temp1); + break; + case 0x18: /*SBB*/ + get_cf(ir, IREG_temp3); if (block->flags & CODEBLOCK_NO_IMMEDIATES) - { - skip_immediate = 1; - LOAD_IMMEDIATE_FROM_RAM_32(block, ir, IREG_temp0, cs+op_pc+1); - } - - switch (fetchdat & 0x38) - { - case 0x00: /*ADD*/ - uop_MOV(ir, IREG_flags_op1, IREG_32(dest_reg)); - if (block->flags & CODEBLOCK_NO_IMMEDIATES) - { - uop_ADD(ir, IREG_32(dest_reg), IREG_32(dest_reg), IREG_temp0); - uop_MOV(ir, IREG_flags_op2, IREG_temp0); - } - else - { - uop_ADD_IMM(ir, IREG_32(dest_reg), IREG_32(dest_reg), imm); - uop_MOV_IMM(ir, IREG_flags_op2, imm); - } - uop_MOV_IMM(ir, IREG_flags_op, FLAGS_ADD32); - uop_MOV(ir, IREG_flags_res, IREG_32(dest_reg)); - break; - - case 0x08: /*OR*/ - if (block->flags & CODEBLOCK_NO_IMMEDIATES) - uop_OR(ir, IREG_32(dest_reg), IREG_32(dest_reg), IREG_temp0); - else - uop_OR_IMM(ir, IREG_32(dest_reg), IREG_32(dest_reg), imm); - uop_MOV_IMM(ir, IREG_flags_op, FLAGS_ZN32); - uop_MOV(ir, IREG_flags_res, IREG_32(dest_reg)); - break; - - case 0x10: /*ADC*/ - get_cf(ir, IREG_temp1); - uop_MOV(ir, IREG_flags_op1, IREG_32(dest_reg)); - if (block->flags & CODEBLOCK_NO_IMMEDIATES) - { - uop_ADD(ir, IREG_32(dest_reg), IREG_32(dest_reg), IREG_temp0); - uop_MOV(ir, IREG_flags_op2, IREG_temp0); - } - else - { - uop_ADD_IMM(ir, IREG_32(dest_reg), IREG_32(dest_reg), imm); - uop_MOV_IMM(ir, IREG_flags_op2, imm); - } - uop_ADD(ir, IREG_32(dest_reg), IREG_32(dest_reg), IREG_temp1); - uop_MOV_IMM(ir, IREG_flags_op, FLAGS_ADC32); - uop_MOV(ir, IREG_flags_res, IREG_32(dest_reg)); - break; - - case 0x18: /*SBB*/ - get_cf(ir, IREG_temp1); - uop_MOV(ir, IREG_flags_op1, IREG_32(dest_reg)); - if (block->flags & CODEBLOCK_NO_IMMEDIATES) - { - uop_SUB(ir, IREG_32(dest_reg), IREG_32(dest_reg), IREG_temp0); - uop_MOV(ir, IREG_flags_op2, IREG_temp0); - } - else - { - uop_SUB_IMM(ir, IREG_32(dest_reg), IREG_32(dest_reg), imm); - uop_MOV_IMM(ir, IREG_flags_op2, imm); - } - uop_SUB(ir, IREG_32(dest_reg), IREG_32(dest_reg), IREG_temp1); - uop_MOV_IMM(ir, IREG_flags_op, FLAGS_SBC32); - uop_MOV(ir, IREG_flags_res, IREG_32(dest_reg)); - break; - - case 0x20: /*AND*/ - if (block->flags & CODEBLOCK_NO_IMMEDIATES) - uop_AND(ir, IREG_32(dest_reg), IREG_32(dest_reg), IREG_temp0); - else - uop_AND_IMM(ir, IREG_32(dest_reg), IREG_32(dest_reg), imm); - uop_MOV_IMM(ir, IREG_flags_op, FLAGS_ZN32); - uop_MOV(ir, IREG_flags_res, IREG_32(dest_reg)); - break; - - case 0x28: /*SUB*/ - uop_MOV(ir, IREG_flags_op1, IREG_32(dest_reg)); - if (block->flags & CODEBLOCK_NO_IMMEDIATES) - { - uop_SUB(ir, IREG_32(dest_reg), IREG_32(dest_reg), IREG_temp0); - uop_MOV(ir, IREG_flags_op2, IREG_temp0); - } - else - { - uop_SUB_IMM(ir, IREG_32(dest_reg), IREG_32(dest_reg), imm); - uop_MOV_IMM(ir, IREG_flags_op2, imm); - } - uop_MOV_IMM(ir, IREG_flags_op, FLAGS_SUB32); - uop_MOV(ir, IREG_flags_res, IREG_32(dest_reg)); - break; - - case 0x30: /*XOR*/ - if (block->flags & CODEBLOCK_NO_IMMEDIATES) - uop_XOR(ir, IREG_32(dest_reg), IREG_32(dest_reg), IREG_temp0); - else - uop_XOR_IMM(ir, IREG_32(dest_reg), IREG_32(dest_reg), imm); - uop_MOV_IMM(ir, IREG_flags_op, FLAGS_ZN32); - uop_MOV(ir, IREG_flags_res, IREG_32(dest_reg)); - break; - - case 0x38: /*CMP*/ - uop_MOV(ir, IREG_flags_op1, IREG_32(dest_reg)); - if (block->flags & CODEBLOCK_NO_IMMEDIATES) - { - uop_SUB(ir, IREG_flags_res, IREG_32(dest_reg), IREG_temp0); - uop_MOV(ir, IREG_flags_op2, IREG_temp0); - } - else - { - uop_SUB_IMM(ir, IREG_flags_res, IREG_32(dest_reg), imm); - uop_MOV_IMM(ir, IREG_flags_op2, imm); - } - uop_MOV_IMM(ir, IREG_flags_op, FLAGS_SUB32); - break; - - default: - return 0; - } - } - else - { - x86seg *target_seg; - uint32_t imm; - - uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc); - target_seg = codegen_generate_ea(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32, 0); - if ((fetchdat & 0x38) == 0x38) /*CMP*/ - codegen_check_seg_read(block, ir, target_seg); + uop_SUB(ir, IREG_temp1, IREG_temp0, IREG_temp2); else - codegen_check_seg_write(block, ir, target_seg); - imm = fastreadl(cs + op_pc + 1); - uop_MEM_LOAD_REG(ir, IREG_temp0, ireg_seg_base(target_seg), IREG_eaaddr); - + uop_SUB_IMM(ir, IREG_temp1, IREG_temp0, imm); + uop_SUB(ir, IREG_temp1, IREG_temp1, IREG_temp3); + uop_MEM_STORE_REG(ir, ireg_seg_base(target_seg), IREG_eaaddr, IREG_temp1); + uop_MOV(ir, IREG_flags_op1, IREG_temp0); if (block->flags & CODEBLOCK_NO_IMMEDIATES) - { - skip_immediate = 1; - LOAD_IMMEDIATE_FROM_RAM_32(block, ir, IREG_temp2, cs+op_pc+1); - } - - switch (fetchdat & 0x38) - { - case 0x00: /*ADD*/ - if (block->flags & CODEBLOCK_NO_IMMEDIATES) - uop_ADD(ir, IREG_temp1, IREG_temp0, IREG_temp2); - else - uop_ADD_IMM(ir, IREG_temp1, IREG_temp0, imm); - uop_MEM_STORE_REG(ir, ireg_seg_base(target_seg), IREG_eaaddr, IREG_temp1); - uop_MOV(ir, IREG_flags_op1, IREG_temp0); - if (block->flags & CODEBLOCK_NO_IMMEDIATES) - uop_MOV(ir, IREG_flags_op2, IREG_temp2); - else - uop_MOV_IMM(ir, IREG_flags_op2, imm); - uop_MOV_IMM(ir, IREG_flags_op, FLAGS_ADD32); - uop_MOV(ir, IREG_flags_res, IREG_temp1); - break; - - case 0x08: /*OR*/ - if (block->flags & CODEBLOCK_NO_IMMEDIATES) - uop_OR(ir, IREG_temp0, IREG_temp0, IREG_temp2); - else - uop_OR_IMM(ir, IREG_temp0, IREG_temp0, imm); - uop_MEM_STORE_REG(ir, ireg_seg_base(target_seg), IREG_eaaddr, IREG_temp0); - uop_MOV(ir, IREG_flags_res, IREG_temp0); - uop_MOV_IMM(ir, IREG_flags_op, FLAGS_ZN32); - break; - - case 0x10: /*ADC*/ - get_cf(ir, IREG_temp3); - if (block->flags & CODEBLOCK_NO_IMMEDIATES) - uop_ADD(ir, IREG_temp1, IREG_temp0, IREG_temp2); - else - uop_ADD_IMM(ir, IREG_temp1, IREG_temp0, imm); - uop_ADD(ir, IREG_temp1, IREG_temp1, IREG_temp3); - uop_MEM_STORE_REG(ir, ireg_seg_base(target_seg), IREG_eaaddr, IREG_temp1); - uop_MOV(ir, IREG_flags_op1, IREG_temp0); - if (block->flags & CODEBLOCK_NO_IMMEDIATES) - uop_MOV(ir, IREG_flags_op2, IREG_temp2); - else - uop_MOV_IMM(ir, IREG_flags_op2, imm); - uop_MOV_IMM(ir, IREG_flags_op, FLAGS_ADC32); - uop_MOV(ir, IREG_flags_res, IREG_temp1); - break; - - case 0x18: /*SBB*/ - get_cf(ir, IREG_temp3); - if (block->flags & CODEBLOCK_NO_IMMEDIATES) - uop_SUB(ir, IREG_temp1, IREG_temp0, IREG_temp2); - else - uop_SUB_IMM(ir, IREG_temp1, IREG_temp0, imm); - uop_SUB(ir, IREG_temp1, IREG_temp1, IREG_temp3); - uop_MEM_STORE_REG(ir, ireg_seg_base(target_seg), IREG_eaaddr, IREG_temp1); - uop_MOV(ir, IREG_flags_op1, IREG_temp0); - if (block->flags & CODEBLOCK_NO_IMMEDIATES) - uop_MOV(ir, IREG_flags_op2, IREG_temp2); - else - uop_MOV_IMM(ir, IREG_flags_op2, imm); - uop_MOV_IMM(ir, IREG_flags_op, FLAGS_SBC32); - uop_MOV(ir, IREG_flags_res, IREG_temp1); - break; - - case 0x20: /*AND*/ - if (block->flags & CODEBLOCK_NO_IMMEDIATES) - uop_AND(ir, IREG_temp0, IREG_temp0, IREG_temp2); - else - uop_AND_IMM(ir, IREG_temp0, IREG_temp0, imm); - uop_MEM_STORE_REG(ir, ireg_seg_base(target_seg), IREG_eaaddr, IREG_temp0); - uop_MOV(ir, IREG_flags_res, IREG_temp0); - uop_MOV_IMM(ir, IREG_flags_op, FLAGS_ZN32); - break; - - case 0x28: /*SUB*/ - if (block->flags & CODEBLOCK_NO_IMMEDIATES) - uop_SUB(ir, IREG_temp1, IREG_temp0, IREG_temp2); - else - uop_SUB_IMM(ir, IREG_temp1, IREG_temp0, imm); - uop_MEM_STORE_REG(ir, ireg_seg_base(target_seg), IREG_eaaddr, IREG_temp1); - uop_MOV(ir, IREG_flags_op1, IREG_temp0); - if (block->flags & CODEBLOCK_NO_IMMEDIATES) - uop_MOV(ir, IREG_flags_op2, IREG_temp2); - else - uop_MOV_IMM(ir, IREG_flags_op2, imm); - uop_MOV_IMM(ir, IREG_flags_op, FLAGS_SUB32); - uop_MOV(ir, IREG_flags_res, IREG_temp1); - break; - - case 0x30: /*XOR*/ - if (block->flags & CODEBLOCK_NO_IMMEDIATES) - uop_XOR(ir, IREG_temp0, IREG_temp0, IREG_temp2); - else - uop_XOR_IMM(ir, IREG_temp0, IREG_temp0, imm); - uop_MEM_STORE_REG(ir, ireg_seg_base(target_seg), IREG_eaaddr, IREG_temp0); - uop_MOV(ir, IREG_flags_res, IREG_temp0); - uop_MOV_IMM(ir, IREG_flags_op, FLAGS_ZN32); - break; - - case 0x38: /*CMP*/ - uop_MOV(ir, IREG_flags_op1, IREG_temp0); - if (block->flags & CODEBLOCK_NO_IMMEDIATES) - { - uop_MOV(ir, IREG_flags_op2, IREG_temp2); - uop_SUB(ir, IREG_flags_res, IREG_temp0, IREG_temp2); - } - else - { - uop_MOV_IMM(ir, IREG_flags_op2, imm); - uop_SUB_IMM(ir, IREG_flags_res, IREG_temp0, imm); - } - uop_MOV_IMM(ir, IREG_flags_op, FLAGS_SUB32); - break; - - default: - return 0; - } - } - - codegen_flags_changed = 1; - if (!skip_immediate) - codegen_mark_code_present(block, cs+op_pc+1, 4); - return op_pc + 5; -} - -uint32_t rop83_w(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) -{ - codegen_mark_code_present(block, cs+op_pc, 1); - if ((fetchdat & 0xc0) == 0xc0) - { - int dest_reg = fetchdat & 7; - uint16_t imm = (int16_t)(int8_t)fastreadb(cs + op_pc + 1); - - switch (fetchdat & 0x38) - { - case 0x00: /*ADD*/ - uop_MOVZX(ir, IREG_flags_op1, IREG_16(dest_reg)); - uop_ADD_IMM(ir, IREG_16(dest_reg), IREG_16(dest_reg), imm); - uop_MOV_IMM(ir, IREG_flags_op2, imm); - uop_MOV_IMM(ir, IREG_flags_op, FLAGS_ADD16); - uop_MOVZX(ir, IREG_flags_res, IREG_16(dest_reg)); - break; - - case 0x08: /*OR*/ - uop_OR_IMM(ir, IREG_16(dest_reg), IREG_16(dest_reg), imm); - uop_MOV_IMM(ir, IREG_flags_op, FLAGS_ZN16); - uop_MOVZX(ir, IREG_flags_res, IREG_16(dest_reg)); - break; - - case 0x10: /*ADC*/ - get_cf(ir, IREG_temp1); - uop_MOVZX(ir, IREG_flags_op1, IREG_16(dest_reg)); - uop_ADD_IMM(ir, IREG_16(dest_reg), IREG_16(dest_reg), imm); - uop_MOV_IMM(ir, IREG_flags_op2, imm); - uop_ADD(ir, IREG_16(dest_reg), IREG_16(dest_reg), IREG_temp1_W); - uop_MOV_IMM(ir, IREG_flags_op, FLAGS_ADC16); - uop_MOVZX(ir, IREG_flags_res, IREG_16(dest_reg)); - break; - - case 0x18: /*SBB*/ - get_cf(ir, IREG_temp1); - uop_MOVZX(ir, IREG_flags_op1, IREG_16(dest_reg)); - uop_SUB_IMM(ir, IREG_16(dest_reg), IREG_16(dest_reg), imm); - uop_MOV_IMM(ir, IREG_flags_op2, imm); - uop_SUB(ir, IREG_16(dest_reg), IREG_16(dest_reg), IREG_temp1_W); - uop_MOV_IMM(ir, IREG_flags_op, FLAGS_SBC16); - uop_MOVZX(ir, IREG_flags_res, IREG_16(dest_reg)); - break; - - case 0x20: /*AND*/ - uop_AND_IMM(ir, IREG_16(dest_reg), IREG_16(dest_reg), imm); - uop_MOV_IMM(ir, IREG_flags_op, FLAGS_ZN16); - uop_MOVZX(ir, IREG_flags_res, IREG_16(dest_reg)); - break; - - case 0x28: /*SUB*/ - uop_MOVZX(ir, IREG_flags_op1, IREG_16(dest_reg)); - uop_SUB_IMM(ir, IREG_16(dest_reg), IREG_16(dest_reg), imm); - uop_MOV_IMM(ir, IREG_flags_op2, imm); - uop_MOV_IMM(ir, IREG_flags_op, FLAGS_SUB16); - uop_MOVZX(ir, IREG_flags_res, IREG_16(dest_reg)); - break; - - case 0x30: /*XOR*/ - uop_XOR_IMM(ir, IREG_16(dest_reg), IREG_16(dest_reg), imm); - uop_MOV_IMM(ir, IREG_flags_op, FLAGS_ZN16); - uop_MOVZX(ir, IREG_flags_res, IREG_16(dest_reg)); - break; - - case 0x38: /*CMP*/ - uop_MOVZX(ir, IREG_flags_op1, IREG_16(dest_reg)); - uop_SUB_IMM(ir, IREG_flags_res_W, IREG_16(dest_reg), imm); - uop_MOVZX(ir, IREG_flags_res, IREG_flags_res_W); - uop_MOV_IMM(ir, IREG_flags_op2, imm); - uop_MOV_IMM(ir, IREG_flags_op, FLAGS_SUB16); - break; - - default: - return 0; - } - } - else - { - x86seg *target_seg; - uint16_t imm; - - uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc); - target_seg = codegen_generate_ea(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32, 0); - if ((fetchdat & 0x38) == 0x38) /*CMP*/ - codegen_check_seg_read(block, ir, target_seg); + uop_MOV(ir, IREG_flags_op2, IREG_temp2); else - codegen_check_seg_write(block, ir, target_seg); - imm = (int16_t)(int8_t)fastreadb(cs + op_pc + 1); - uop_MEM_LOAD_REG(ir, IREG_temp0_W, ireg_seg_base(target_seg), IREG_eaaddr); + uop_MOV_IMM(ir, IREG_flags_op2, imm); + uop_MOV_IMM(ir, IREG_flags_op, FLAGS_SBC32); + uop_MOV(ir, IREG_flags_res, IREG_temp1); + break; - switch (fetchdat & 0x38) - { - case 0x00: /*ADD*/ - uop_ADD_IMM(ir, IREG_temp1_W, IREG_temp0_W, imm); - uop_MEM_STORE_REG(ir, ireg_seg_base(target_seg), IREG_eaaddr, IREG_temp1_W); - uop_MOVZX(ir, IREG_flags_op1, IREG_temp0_W); - uop_MOV_IMM(ir, IREG_flags_op2, imm); - uop_MOV_IMM(ir, IREG_flags_op, FLAGS_ADD16); - uop_MOVZX(ir, IREG_flags_res, IREG_temp1_W); - break; - - case 0x08: /*OR*/ - uop_OR_IMM(ir, IREG_temp0_W, IREG_temp0_W, imm); - uop_MEM_STORE_REG(ir, ireg_seg_base(target_seg), IREG_eaaddr, IREG_temp0_W); - uop_MOVZX(ir, IREG_flags_res, IREG_temp0_W); - uop_MOV_IMM(ir, IREG_flags_op, FLAGS_ZN16); - break; - - case 0x10: /*ADC*/ - get_cf(ir, IREG_temp2); - uop_ADD_IMM(ir, IREG_temp1_W, IREG_temp0_W, imm); - uop_ADD(ir, IREG_temp1_W, IREG_temp1_W, IREG_temp2_W); - uop_MEM_STORE_REG(ir, ireg_seg_base(target_seg), IREG_eaaddr, IREG_temp1_W); - uop_MOVZX(ir, IREG_flags_op1, IREG_temp0_W); - uop_MOV_IMM(ir, IREG_flags_op2, imm); - uop_MOV_IMM(ir, IREG_flags_op, FLAGS_ADC16); - uop_MOVZX(ir, IREG_flags_res, IREG_temp1_W); - break; - - case 0x18: /*SBB*/ - get_cf(ir, IREG_temp2); - uop_SUB_IMM(ir, IREG_temp1_W, IREG_temp0_W, imm); - uop_SUB(ir, IREG_temp1_W, IREG_temp1_W, IREG_temp2_W); - uop_MEM_STORE_REG(ir, ireg_seg_base(target_seg), IREG_eaaddr, IREG_temp1_W); - uop_MOVZX(ir, IREG_flags_op1, IREG_temp0_W); - uop_MOV_IMM(ir, IREG_flags_op2, imm); - uop_MOV_IMM(ir, IREG_flags_op, FLAGS_SBC16); - uop_MOVZX(ir, IREG_flags_res, IREG_temp1_W); - break; - - case 0x20: /*AND*/ - uop_AND_IMM(ir, IREG_temp0_W, IREG_temp0_W, imm); - uop_MEM_STORE_REG(ir, ireg_seg_base(target_seg), IREG_eaaddr, IREG_temp0_W); - uop_MOVZX(ir, IREG_flags_res, IREG_temp0_W); - uop_MOV_IMM(ir, IREG_flags_op, FLAGS_ZN16); - break; - - case 0x28: /*SUB*/ - uop_SUB_IMM(ir, IREG_temp1_W, IREG_temp0_W, imm); - uop_MEM_STORE_REG(ir, ireg_seg_base(target_seg), IREG_eaaddr, IREG_temp1_W); - uop_MOVZX(ir, IREG_flags_op1, IREG_temp0_W); - uop_MOV_IMM(ir, IREG_flags_op2, imm); - uop_MOV_IMM(ir, IREG_flags_op, FLAGS_SUB16); - uop_MOVZX(ir, IREG_flags_res, IREG_temp1_W); - break; - - case 0x30: /*XOR*/ - uop_XOR_IMM(ir, IREG_temp0_W, IREG_temp0_W, imm); - uop_MEM_STORE_REG(ir, ireg_seg_base(target_seg), IREG_eaaddr, IREG_temp0_W); - uop_MOVZX(ir, IREG_flags_res, IREG_temp0_W); - uop_MOV_IMM(ir, IREG_flags_op, FLAGS_ZN16); - break; - - case 0x38: /*CMP*/ - uop_MOVZX(ir, IREG_flags_op1, IREG_temp0_W); - uop_MOV_IMM(ir, IREG_flags_op2, imm); - uop_SUB_IMM(ir, IREG_flags_res_W, IREG_temp0_W, imm); - uop_MOVZX(ir, IREG_flags_res, IREG_flags_res_W); - uop_MOV_IMM(ir, IREG_flags_op, FLAGS_SUB16); - break; - - default: - return 0; - } - } - - codegen_flags_changed = 1; - codegen_mark_code_present(block, cs+op_pc+1, 1); - return op_pc + 2; -} -uint32_t rop83_l(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) -{ - codegen_mark_code_present(block, cs+op_pc, 1); - if ((fetchdat & 0xc0) == 0xc0) - { - int dest_reg = fetchdat & 7; - uint32_t imm = (int32_t)(int8_t)fastreadb(cs + op_pc + 1); - - switch (fetchdat & 0x38) - { - case 0x00: /*ADD*/ - uop_MOV(ir, IREG_flags_op1, IREG_32(dest_reg)); - uop_ADD_IMM(ir, IREG_32(dest_reg), IREG_32(dest_reg), imm); - uop_MOV_IMM(ir, IREG_flags_op2, imm); - uop_MOV_IMM(ir, IREG_flags_op, FLAGS_ADD32); - uop_MOV(ir, IREG_flags_res, IREG_32(dest_reg)); - break; - - case 0x08: /*OR*/ - uop_OR_IMM(ir, IREG_32(dest_reg), IREG_32(dest_reg), imm); - uop_MOV_IMM(ir, IREG_flags_op, FLAGS_ZN32); - uop_MOV(ir, IREG_flags_res, IREG_32(dest_reg)); - break; - - case 0x10: /*ADC*/ - get_cf(ir, IREG_temp1); - uop_MOV(ir, IREG_flags_op1, IREG_32(dest_reg)); - uop_ADD_IMM(ir, IREG_32(dest_reg), IREG_32(dest_reg), imm); - uop_MOV_IMM(ir, IREG_flags_op2, imm); - uop_ADD(ir, IREG_32(dest_reg), IREG_32(dest_reg), IREG_temp1); - uop_MOV_IMM(ir, IREG_flags_op, FLAGS_ADC32); - uop_MOV(ir, IREG_flags_res, IREG_32(dest_reg)); - break; - - case 0x18: /*SBB*/ - get_cf(ir, IREG_temp1); - uop_MOV(ir, IREG_flags_op1, IREG_32(dest_reg)); - uop_SUB_IMM(ir, IREG_32(dest_reg), IREG_32(dest_reg), imm); - uop_MOV_IMM(ir, IREG_flags_op2, imm); - uop_SUB(ir, IREG_32(dest_reg), IREG_32(dest_reg), IREG_temp1); - uop_MOV_IMM(ir, IREG_flags_op, FLAGS_SBC32); - uop_MOV(ir, IREG_flags_res, IREG_32(dest_reg)); - break; - - case 0x20: /*AND*/ - uop_AND_IMM(ir, IREG_32(dest_reg), IREG_32(dest_reg), imm); - uop_MOV_IMM(ir, IREG_flags_op, FLAGS_ZN32); - uop_MOV(ir, IREG_flags_res, IREG_32(dest_reg)); - break; - - case 0x28: /*SUB*/ - uop_MOV(ir, IREG_flags_op1, IREG_32(dest_reg)); - uop_SUB_IMM(ir, IREG_32(dest_reg), IREG_32(dest_reg), imm); - uop_MOV_IMM(ir, IREG_flags_op2, imm); - uop_MOV_IMM(ir, IREG_flags_op, FLAGS_SUB32); - uop_MOV(ir, IREG_flags_res, IREG_32(dest_reg)); - break; - - case 0x30: /*XOR*/ - uop_XOR_IMM(ir, IREG_32(dest_reg), IREG_32(dest_reg), imm); - uop_MOV_IMM(ir, IREG_flags_op, FLAGS_ZN32); - uop_MOV(ir, IREG_flags_res, IREG_32(dest_reg)); - break; - - case 0x38: /*CMP*/ - uop_MOV(ir, IREG_flags_op1, IREG_32(dest_reg)); - uop_SUB_IMM(ir, IREG_flags_res, IREG_32(dest_reg), imm); - uop_MOV_IMM(ir, IREG_flags_op2, imm); - uop_MOV_IMM(ir, IREG_flags_op, FLAGS_SUB32); - break; - - default: - return 0; - } - } - else - { - x86seg *target_seg; - uint32_t imm; - - uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc); - target_seg = codegen_generate_ea(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32, 0); - if ((fetchdat & 0x38) == 0x38) /*CMP*/ - codegen_check_seg_read(block, ir, target_seg); + case 0x20: /*AND*/ + if (block->flags & CODEBLOCK_NO_IMMEDIATES) + uop_AND(ir, IREG_temp0, IREG_temp0, IREG_temp2); else - codegen_check_seg_write(block, ir, target_seg); - imm = (int32_t)(int8_t)fastreadb(cs + op_pc + 1); - uop_MEM_LOAD_REG(ir, IREG_temp0, ireg_seg_base(target_seg), IREG_eaaddr); + uop_AND_IMM(ir, IREG_temp0, IREG_temp0, imm); + uop_MEM_STORE_REG(ir, ireg_seg_base(target_seg), IREG_eaaddr, IREG_temp0); + uop_MOV(ir, IREG_flags_res, IREG_temp0); + uop_MOV_IMM(ir, IREG_flags_op, FLAGS_ZN32); + break; - switch (fetchdat & 0x38) - { - case 0x00: /*ADD*/ - uop_ADD_IMM(ir, IREG_temp1, IREG_temp0, imm); - uop_MEM_STORE_REG(ir, ireg_seg_base(target_seg), IREG_eaaddr, IREG_temp1); - uop_MOV(ir, IREG_flags_op1, IREG_temp0); - uop_MOV_IMM(ir, IREG_flags_op2, imm); - uop_MOV_IMM(ir, IREG_flags_op, FLAGS_ADD32); - uop_MOV(ir, IREG_flags_res, IREG_temp1); - break; + case 0x28: /*SUB*/ + if (block->flags & CODEBLOCK_NO_IMMEDIATES) + uop_SUB(ir, IREG_temp1, IREG_temp0, IREG_temp2); + else + uop_SUB_IMM(ir, IREG_temp1, IREG_temp0, imm); + uop_MEM_STORE_REG(ir, ireg_seg_base(target_seg), IREG_eaaddr, IREG_temp1); + uop_MOV(ir, IREG_flags_op1, IREG_temp0); + if (block->flags & CODEBLOCK_NO_IMMEDIATES) + uop_MOV(ir, IREG_flags_op2, IREG_temp2); + else + uop_MOV_IMM(ir, IREG_flags_op2, imm); + uop_MOV_IMM(ir, IREG_flags_op, FLAGS_SUB32); + uop_MOV(ir, IREG_flags_res, IREG_temp1); + break; - case 0x08: /*OR*/ - uop_OR_IMM(ir, IREG_temp0, IREG_temp0, imm); - uop_MEM_STORE_REG(ir, ireg_seg_base(target_seg), IREG_eaaddr, IREG_temp0); - uop_MOV(ir, IREG_flags_res, IREG_temp0); - uop_MOV_IMM(ir, IREG_flags_op, FLAGS_ZN32); - break; - - case 0x10: /*ADC*/ - get_cf(ir, IREG_temp2); - uop_ADD_IMM(ir, IREG_temp1, IREG_temp0, imm); - uop_ADD(ir, IREG_temp1, IREG_temp1, IREG_temp2); - uop_MEM_STORE_REG(ir, ireg_seg_base(target_seg), IREG_eaaddr, IREG_temp1); - uop_MOV(ir, IREG_flags_op1, IREG_temp0); - uop_MOV_IMM(ir, IREG_flags_op2, imm); - uop_MOV_IMM(ir, IREG_flags_op, FLAGS_ADC32); - uop_MOV(ir, IREG_flags_res, IREG_temp1); - break; + case 0x30: /*XOR*/ + if (block->flags & CODEBLOCK_NO_IMMEDIATES) + uop_XOR(ir, IREG_temp0, IREG_temp0, IREG_temp2); + else + uop_XOR_IMM(ir, IREG_temp0, IREG_temp0, imm); + uop_MEM_STORE_REG(ir, ireg_seg_base(target_seg), IREG_eaaddr, IREG_temp0); + uop_MOV(ir, IREG_flags_res, IREG_temp0); + uop_MOV_IMM(ir, IREG_flags_op, FLAGS_ZN32); + break; - case 0x18: /*SBB*/ - get_cf(ir, IREG_temp2); - uop_SUB_IMM(ir, IREG_temp1, IREG_temp0, imm); - uop_SUB(ir, IREG_temp1, IREG_temp1, IREG_temp2); - uop_MEM_STORE_REG(ir, ireg_seg_base(target_seg), IREG_eaaddr, IREG_temp1); - uop_MOV(ir, IREG_flags_op1, IREG_temp0); - uop_MOV_IMM(ir, IREG_flags_op2, imm); - uop_MOV_IMM(ir, IREG_flags_op, FLAGS_SBC32); - uop_MOV(ir, IREG_flags_res, IREG_temp1); - break; - - case 0x20: /*AND*/ - uop_AND_IMM(ir, IREG_temp0, IREG_temp0, imm); - uop_MEM_STORE_REG(ir, ireg_seg_base(target_seg), IREG_eaaddr, IREG_temp0); - uop_MOV(ir, IREG_flags_res, IREG_temp0); - uop_MOV_IMM(ir, IREG_flags_op, FLAGS_ZN32); - break; - - case 0x28: /*SUB*/ - uop_SUB_IMM(ir, IREG_temp1, IREG_temp0, imm); - uop_MEM_STORE_REG(ir, ireg_seg_base(target_seg), IREG_eaaddr, IREG_temp1); - uop_MOV(ir, IREG_flags_op1, IREG_temp0); - uop_MOV_IMM(ir, IREG_flags_op2, imm); - uop_MOV_IMM(ir, IREG_flags_op, FLAGS_SUB32); - uop_MOV(ir, IREG_flags_res, IREG_temp1); - break; - - case 0x30: /*XOR*/ - uop_XOR_IMM(ir, IREG_temp0, IREG_temp0, imm); - uop_MEM_STORE_REG(ir, ireg_seg_base(target_seg), IREG_eaaddr, IREG_temp0); - uop_MOV(ir, IREG_flags_res, IREG_temp0); - uop_MOV_IMM(ir, IREG_flags_op, FLAGS_ZN32); - break; - - case 0x38: /*CMP*/ - uop_MOV(ir, IREG_flags_op1, IREG_temp0); - uop_MOV_IMM(ir, IREG_flags_op2, imm); - uop_SUB_IMM(ir, IREG_flags_res, IREG_temp0, imm); - uop_MOV_IMM(ir, IREG_flags_op, FLAGS_SUB32); - break; - - default: - return 0; + case 0x38: /*CMP*/ + uop_MOV(ir, IREG_flags_op1, IREG_temp0); + if (block->flags & CODEBLOCK_NO_IMMEDIATES) { + uop_MOV(ir, IREG_flags_op2, IREG_temp2); + uop_SUB(ir, IREG_flags_res, IREG_temp0, IREG_temp2); + } else { + uop_MOV_IMM(ir, IREG_flags_op2, imm); + uop_SUB_IMM(ir, IREG_flags_res, IREG_temp0, imm); } - } + uop_MOV_IMM(ir, IREG_flags_op, FLAGS_SUB32); + break; - codegen_flags_changed = 1; - codegen_mark_code_present(block, cs+op_pc+1, 1); - return op_pc + 2; + default: + return 0; + } + } + + codegen_flags_changed = 1; + if (!skip_immediate) + codegen_mark_code_present(block, cs + op_pc + 1, 4); + return op_pc + 5; } -static void rebuild_c(ir_data_t *ir) +uint32_t +rop83_w(codeblock_t *block, ir_data_t *ir, UNUSED(uint8_t opcode), uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) { - int needs_rebuild = 1; - - if (codegen_flags_changed) - { - switch (cpu_state.flags_op) - { - case FLAGS_INC8: case FLAGS_INC16: case FLAGS_INC32: - case FLAGS_DEC8: case FLAGS_DEC16: case FLAGS_DEC32: - needs_rebuild = 0; - break; - } + codegen_mark_code_present(block, cs + op_pc, 1); + if ((fetchdat & 0xc0) == 0xc0) { + int dest_reg = fetchdat & 7; + uint16_t imm = (int16_t) (int8_t) fastreadb(cs + op_pc + 1); + + switch (fetchdat & 0x38) { + case 0x00: /*ADD*/ + uop_MOVZX(ir, IREG_flags_op1, IREG_16(dest_reg)); + uop_ADD_IMM(ir, IREG_16(dest_reg), IREG_16(dest_reg), imm); + uop_MOV_IMM(ir, IREG_flags_op2, imm); + uop_MOV_IMM(ir, IREG_flags_op, FLAGS_ADD16); + uop_MOVZX(ir, IREG_flags_res, IREG_16(dest_reg)); + break; + + case 0x08: /*OR*/ + uop_OR_IMM(ir, IREG_16(dest_reg), IREG_16(dest_reg), imm); + uop_MOV_IMM(ir, IREG_flags_op, FLAGS_ZN16); + uop_MOVZX(ir, IREG_flags_res, IREG_16(dest_reg)); + break; + + case 0x10: /*ADC*/ + get_cf(ir, IREG_temp1); + uop_MOVZX(ir, IREG_flags_op1, IREG_16(dest_reg)); + uop_ADD_IMM(ir, IREG_16(dest_reg), IREG_16(dest_reg), imm); + uop_MOV_IMM(ir, IREG_flags_op2, imm); + uop_ADD(ir, IREG_16(dest_reg), IREG_16(dest_reg), IREG_temp1_W); + uop_MOV_IMM(ir, IREG_flags_op, FLAGS_ADC16); + uop_MOVZX(ir, IREG_flags_res, IREG_16(dest_reg)); + break; + + case 0x18: /*SBB*/ + get_cf(ir, IREG_temp1); + uop_MOVZX(ir, IREG_flags_op1, IREG_16(dest_reg)); + uop_SUB_IMM(ir, IREG_16(dest_reg), IREG_16(dest_reg), imm); + uop_MOV_IMM(ir, IREG_flags_op2, imm); + uop_SUB(ir, IREG_16(dest_reg), IREG_16(dest_reg), IREG_temp1_W); + uop_MOV_IMM(ir, IREG_flags_op, FLAGS_SBC16); + uop_MOVZX(ir, IREG_flags_res, IREG_16(dest_reg)); + break; + + case 0x20: /*AND*/ + uop_AND_IMM(ir, IREG_16(dest_reg), IREG_16(dest_reg), imm); + uop_MOV_IMM(ir, IREG_flags_op, FLAGS_ZN16); + uop_MOVZX(ir, IREG_flags_res, IREG_16(dest_reg)); + break; + + case 0x28: /*SUB*/ + uop_MOVZX(ir, IREG_flags_op1, IREG_16(dest_reg)); + uop_SUB_IMM(ir, IREG_16(dest_reg), IREG_16(dest_reg), imm); + uop_MOV_IMM(ir, IREG_flags_op2, imm); + uop_MOV_IMM(ir, IREG_flags_op, FLAGS_SUB16); + uop_MOVZX(ir, IREG_flags_res, IREG_16(dest_reg)); + break; + + case 0x30: /*XOR*/ + uop_XOR_IMM(ir, IREG_16(dest_reg), IREG_16(dest_reg), imm); + uop_MOV_IMM(ir, IREG_flags_op, FLAGS_ZN16); + uop_MOVZX(ir, IREG_flags_res, IREG_16(dest_reg)); + break; + + case 0x38: /*CMP*/ + uop_MOVZX(ir, IREG_flags_op1, IREG_16(dest_reg)); + uop_SUB_IMM(ir, IREG_flags_res_W, IREG_16(dest_reg), imm); + uop_MOVZX(ir, IREG_flags_res, IREG_flags_res_W); + uop_MOV_IMM(ir, IREG_flags_op2, imm); + uop_MOV_IMM(ir, IREG_flags_op, FLAGS_SUB16); + break; + + default: + return 0; } - - if (needs_rebuild) - { - uop_CALL_FUNC(ir, flags_rebuild_c); + } else { + x86seg *target_seg; + uint16_t imm; + + uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc); + target_seg = codegen_generate_ea(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32, 0); + if ((fetchdat & 0x38) == 0x38) /*CMP*/ + codegen_check_seg_read(block, ir, target_seg); + else + codegen_check_seg_write(block, ir, target_seg); + imm = (int16_t) (int8_t) fastreadb(cs + op_pc + 1); + uop_MEM_LOAD_REG(ir, IREG_temp0_W, ireg_seg_base(target_seg), IREG_eaaddr); + + switch (fetchdat & 0x38) { + case 0x00: /*ADD*/ + uop_ADD_IMM(ir, IREG_temp1_W, IREG_temp0_W, imm); + uop_MEM_STORE_REG(ir, ireg_seg_base(target_seg), IREG_eaaddr, IREG_temp1_W); + uop_MOVZX(ir, IREG_flags_op1, IREG_temp0_W); + uop_MOV_IMM(ir, IREG_flags_op2, imm); + uop_MOV_IMM(ir, IREG_flags_op, FLAGS_ADD16); + uop_MOVZX(ir, IREG_flags_res, IREG_temp1_W); + break; + + case 0x08: /*OR*/ + uop_OR_IMM(ir, IREG_temp0_W, IREG_temp0_W, imm); + uop_MEM_STORE_REG(ir, ireg_seg_base(target_seg), IREG_eaaddr, IREG_temp0_W); + uop_MOVZX(ir, IREG_flags_res, IREG_temp0_W); + uop_MOV_IMM(ir, IREG_flags_op, FLAGS_ZN16); + break; + + case 0x10: /*ADC*/ + get_cf(ir, IREG_temp2); + uop_ADD_IMM(ir, IREG_temp1_W, IREG_temp0_W, imm); + uop_ADD(ir, IREG_temp1_W, IREG_temp1_W, IREG_temp2_W); + uop_MEM_STORE_REG(ir, ireg_seg_base(target_seg), IREG_eaaddr, IREG_temp1_W); + uop_MOVZX(ir, IREG_flags_op1, IREG_temp0_W); + uop_MOV_IMM(ir, IREG_flags_op2, imm); + uop_MOV_IMM(ir, IREG_flags_op, FLAGS_ADC16); + uop_MOVZX(ir, IREG_flags_res, IREG_temp1_W); + break; + + case 0x18: /*SBB*/ + get_cf(ir, IREG_temp2); + uop_SUB_IMM(ir, IREG_temp1_W, IREG_temp0_W, imm); + uop_SUB(ir, IREG_temp1_W, IREG_temp1_W, IREG_temp2_W); + uop_MEM_STORE_REG(ir, ireg_seg_base(target_seg), IREG_eaaddr, IREG_temp1_W); + uop_MOVZX(ir, IREG_flags_op1, IREG_temp0_W); + uop_MOV_IMM(ir, IREG_flags_op2, imm); + uop_MOV_IMM(ir, IREG_flags_op, FLAGS_SBC16); + uop_MOVZX(ir, IREG_flags_res, IREG_temp1_W); + break; + + case 0x20: /*AND*/ + uop_AND_IMM(ir, IREG_temp0_W, IREG_temp0_W, imm); + uop_MEM_STORE_REG(ir, ireg_seg_base(target_seg), IREG_eaaddr, IREG_temp0_W); + uop_MOVZX(ir, IREG_flags_res, IREG_temp0_W); + uop_MOV_IMM(ir, IREG_flags_op, FLAGS_ZN16); + break; + + case 0x28: /*SUB*/ + uop_SUB_IMM(ir, IREG_temp1_W, IREG_temp0_W, imm); + uop_MEM_STORE_REG(ir, ireg_seg_base(target_seg), IREG_eaaddr, IREG_temp1_W); + uop_MOVZX(ir, IREG_flags_op1, IREG_temp0_W); + uop_MOV_IMM(ir, IREG_flags_op2, imm); + uop_MOV_IMM(ir, IREG_flags_op, FLAGS_SUB16); + uop_MOVZX(ir, IREG_flags_res, IREG_temp1_W); + break; + + case 0x30: /*XOR*/ + uop_XOR_IMM(ir, IREG_temp0_W, IREG_temp0_W, imm); + uop_MEM_STORE_REG(ir, ireg_seg_base(target_seg), IREG_eaaddr, IREG_temp0_W); + uop_MOVZX(ir, IREG_flags_res, IREG_temp0_W); + uop_MOV_IMM(ir, IREG_flags_op, FLAGS_ZN16); + break; + + case 0x38: /*CMP*/ + uop_MOVZX(ir, IREG_flags_op1, IREG_temp0_W); + uop_MOV_IMM(ir, IREG_flags_op2, imm); + uop_SUB_IMM(ir, IREG_flags_res_W, IREG_temp0_W, imm); + uop_MOVZX(ir, IREG_flags_res, IREG_flags_res_W); + uop_MOV_IMM(ir, IREG_flags_op, FLAGS_SUB16); + break; + + default: + return 0; } + } + + codegen_flags_changed = 1; + codegen_mark_code_present(block, cs + op_pc + 1, 1); + return op_pc + 2; +} +uint32_t +rop83_l(codeblock_t *block, ir_data_t *ir, UNUSED(uint8_t opcode), uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) +{ + codegen_mark_code_present(block, cs + op_pc, 1); + if ((fetchdat & 0xc0) == 0xc0) { + int dest_reg = fetchdat & 7; + uint32_t imm = (int32_t) (int8_t) fastreadb(cs + op_pc + 1); + + switch (fetchdat & 0x38) { + case 0x00: /*ADD*/ + uop_MOV(ir, IREG_flags_op1, IREG_32(dest_reg)); + uop_ADD_IMM(ir, IREG_32(dest_reg), IREG_32(dest_reg), imm); + uop_MOV_IMM(ir, IREG_flags_op2, imm); + uop_MOV_IMM(ir, IREG_flags_op, FLAGS_ADD32); + uop_MOV(ir, IREG_flags_res, IREG_32(dest_reg)); + break; + + case 0x08: /*OR*/ + uop_OR_IMM(ir, IREG_32(dest_reg), IREG_32(dest_reg), imm); + uop_MOV_IMM(ir, IREG_flags_op, FLAGS_ZN32); + uop_MOV(ir, IREG_flags_res, IREG_32(dest_reg)); + break; + + case 0x10: /*ADC*/ + get_cf(ir, IREG_temp1); + uop_MOV(ir, IREG_flags_op1, IREG_32(dest_reg)); + uop_ADD_IMM(ir, IREG_32(dest_reg), IREG_32(dest_reg), imm); + uop_MOV_IMM(ir, IREG_flags_op2, imm); + uop_ADD(ir, IREG_32(dest_reg), IREG_32(dest_reg), IREG_temp1); + uop_MOV_IMM(ir, IREG_flags_op, FLAGS_ADC32); + uop_MOV(ir, IREG_flags_res, IREG_32(dest_reg)); + break; + + case 0x18: /*SBB*/ + get_cf(ir, IREG_temp1); + uop_MOV(ir, IREG_flags_op1, IREG_32(dest_reg)); + uop_SUB_IMM(ir, IREG_32(dest_reg), IREG_32(dest_reg), imm); + uop_MOV_IMM(ir, IREG_flags_op2, imm); + uop_SUB(ir, IREG_32(dest_reg), IREG_32(dest_reg), IREG_temp1); + uop_MOV_IMM(ir, IREG_flags_op, FLAGS_SBC32); + uop_MOV(ir, IREG_flags_res, IREG_32(dest_reg)); + break; + + case 0x20: /*AND*/ + uop_AND_IMM(ir, IREG_32(dest_reg), IREG_32(dest_reg), imm); + uop_MOV_IMM(ir, IREG_flags_op, FLAGS_ZN32); + uop_MOV(ir, IREG_flags_res, IREG_32(dest_reg)); + break; + + case 0x28: /*SUB*/ + uop_MOV(ir, IREG_flags_op1, IREG_32(dest_reg)); + uop_SUB_IMM(ir, IREG_32(dest_reg), IREG_32(dest_reg), imm); + uop_MOV_IMM(ir, IREG_flags_op2, imm); + uop_MOV_IMM(ir, IREG_flags_op, FLAGS_SUB32); + uop_MOV(ir, IREG_flags_res, IREG_32(dest_reg)); + break; + + case 0x30: /*XOR*/ + uop_XOR_IMM(ir, IREG_32(dest_reg), IREG_32(dest_reg), imm); + uop_MOV_IMM(ir, IREG_flags_op, FLAGS_ZN32); + uop_MOV(ir, IREG_flags_res, IREG_32(dest_reg)); + break; + + case 0x38: /*CMP*/ + uop_MOV(ir, IREG_flags_op1, IREG_32(dest_reg)); + uop_SUB_IMM(ir, IREG_flags_res, IREG_32(dest_reg), imm); + uop_MOV_IMM(ir, IREG_flags_op2, imm); + uop_MOV_IMM(ir, IREG_flags_op, FLAGS_SUB32); + break; + + default: + return 0; + } + } else { + x86seg *target_seg; + uint32_t imm; + + uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc); + target_seg = codegen_generate_ea(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32, 0); + if ((fetchdat & 0x38) == 0x38) /*CMP*/ + codegen_check_seg_read(block, ir, target_seg); + else + codegen_check_seg_write(block, ir, target_seg); + imm = (int32_t) (int8_t) fastreadb(cs + op_pc + 1); + uop_MEM_LOAD_REG(ir, IREG_temp0, ireg_seg_base(target_seg), IREG_eaaddr); + + switch (fetchdat & 0x38) { + case 0x00: /*ADD*/ + uop_ADD_IMM(ir, IREG_temp1, IREG_temp0, imm); + uop_MEM_STORE_REG(ir, ireg_seg_base(target_seg), IREG_eaaddr, IREG_temp1); + uop_MOV(ir, IREG_flags_op1, IREG_temp0); + uop_MOV_IMM(ir, IREG_flags_op2, imm); + uop_MOV_IMM(ir, IREG_flags_op, FLAGS_ADD32); + uop_MOV(ir, IREG_flags_res, IREG_temp1); + break; + + case 0x08: /*OR*/ + uop_OR_IMM(ir, IREG_temp0, IREG_temp0, imm); + uop_MEM_STORE_REG(ir, ireg_seg_base(target_seg), IREG_eaaddr, IREG_temp0); + uop_MOV(ir, IREG_flags_res, IREG_temp0); + uop_MOV_IMM(ir, IREG_flags_op, FLAGS_ZN32); + break; + + case 0x10: /*ADC*/ + get_cf(ir, IREG_temp2); + uop_ADD_IMM(ir, IREG_temp1, IREG_temp0, imm); + uop_ADD(ir, IREG_temp1, IREG_temp1, IREG_temp2); + uop_MEM_STORE_REG(ir, ireg_seg_base(target_seg), IREG_eaaddr, IREG_temp1); + uop_MOV(ir, IREG_flags_op1, IREG_temp0); + uop_MOV_IMM(ir, IREG_flags_op2, imm); + uop_MOV_IMM(ir, IREG_flags_op, FLAGS_ADC32); + uop_MOV(ir, IREG_flags_res, IREG_temp1); + break; + + case 0x18: /*SBB*/ + get_cf(ir, IREG_temp2); + uop_SUB_IMM(ir, IREG_temp1, IREG_temp0, imm); + uop_SUB(ir, IREG_temp1, IREG_temp1, IREG_temp2); + uop_MEM_STORE_REG(ir, ireg_seg_base(target_seg), IREG_eaaddr, IREG_temp1); + uop_MOV(ir, IREG_flags_op1, IREG_temp0); + uop_MOV_IMM(ir, IREG_flags_op2, imm); + uop_MOV_IMM(ir, IREG_flags_op, FLAGS_SBC32); + uop_MOV(ir, IREG_flags_res, IREG_temp1); + break; + + case 0x20: /*AND*/ + uop_AND_IMM(ir, IREG_temp0, IREG_temp0, imm); + uop_MEM_STORE_REG(ir, ireg_seg_base(target_seg), IREG_eaaddr, IREG_temp0); + uop_MOV(ir, IREG_flags_res, IREG_temp0); + uop_MOV_IMM(ir, IREG_flags_op, FLAGS_ZN32); + break; + + case 0x28: /*SUB*/ + uop_SUB_IMM(ir, IREG_temp1, IREG_temp0, imm); + uop_MEM_STORE_REG(ir, ireg_seg_base(target_seg), IREG_eaaddr, IREG_temp1); + uop_MOV(ir, IREG_flags_op1, IREG_temp0); + uop_MOV_IMM(ir, IREG_flags_op2, imm); + uop_MOV_IMM(ir, IREG_flags_op, FLAGS_SUB32); + uop_MOV(ir, IREG_flags_res, IREG_temp1); + break; + + case 0x30: /*XOR*/ + uop_XOR_IMM(ir, IREG_temp0, IREG_temp0, imm); + uop_MEM_STORE_REG(ir, ireg_seg_base(target_seg), IREG_eaaddr, IREG_temp0); + uop_MOV(ir, IREG_flags_res, IREG_temp0); + uop_MOV_IMM(ir, IREG_flags_op, FLAGS_ZN32); + break; + + case 0x38: /*CMP*/ + uop_MOV(ir, IREG_flags_op1, IREG_temp0); + uop_MOV_IMM(ir, IREG_flags_op2, imm); + uop_SUB_IMM(ir, IREG_flags_res, IREG_temp0, imm); + uop_MOV_IMM(ir, IREG_flags_op, FLAGS_SUB32); + break; + + default: + return 0; + } + } + + codegen_flags_changed = 1; + codegen_mark_code_present(block, cs + op_pc + 1, 1); + return op_pc + 2; } -uint32_t ropINC_r16(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) +static void +rebuild_c(ir_data_t *ir) { - rebuild_c(ir); + int needs_rebuild = 1; - uop_MOVZX(ir, IREG_flags_op1, IREG_16(opcode & 7)); - uop_ADD_IMM(ir, IREG_16(opcode & 7), IREG_16(opcode & 7), 1); - uop_MOVZX(ir, IREG_flags_res, IREG_16(opcode & 7)); + if (codegen_flags_changed) { + switch (cpu_state.flags_op) { + case FLAGS_INC8: + case FLAGS_INC16: + case FLAGS_INC32: + case FLAGS_DEC8: + case FLAGS_DEC16: + case FLAGS_DEC32: + needs_rebuild = 0; + break; + + default: + break; + } + } + + if (needs_rebuild) { + uop_CALL_FUNC(ir, flags_rebuild_c); + } +} + +uint32_t +ropINC_r16(UNUSED(UNUSED(codeblock_t *block)), ir_data_t *ir, UNUSED(uint8_t opcode), uint32_t fetchdat, UNUSED(uint32_t op_32), uint32_t op_pc) +{ + rebuild_c(ir); + + uop_MOVZX(ir, IREG_flags_op1, IREG_16(opcode & 7)); + uop_ADD_IMM(ir, IREG_16(opcode & 7), IREG_16(opcode & 7), 1); + uop_MOVZX(ir, IREG_flags_res, IREG_16(opcode & 7)); + uop_MOV_IMM(ir, IREG_flags_op2, 1); + uop_MOV_IMM(ir, IREG_flags_op, FLAGS_INC16); + codegen_flags_changed = 1; + + return op_pc; +} +uint32_t +ropINC_r32(UNUSED(UNUSED(codeblock_t *block)), ir_data_t *ir, UNUSED(uint8_t opcode), uint32_t fetchdat, UNUSED(uint32_t op_32), uint32_t op_pc) +{ + rebuild_c(ir); + + uop_MOV(ir, IREG_flags_op1, IREG_32(opcode & 7)); + uop_ADD_IMM(ir, IREG_32(opcode & 7), IREG_32(opcode & 7), 1); + uop_MOV(ir, IREG_flags_res, IREG_32(opcode & 7)); + uop_MOV_IMM(ir, IREG_flags_op2, 1); + uop_MOV_IMM(ir, IREG_flags_op, FLAGS_INC32); + codegen_flags_changed = 1; + + return op_pc; +} + +uint32_t +ropDEC_r16(UNUSED(codeblock_t *block), ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, UNUSED(uint32_t op_32), uint32_t op_pc) +{ + rebuild_c(ir); + + uop_MOVZX(ir, IREG_flags_op1, IREG_16(opcode & 7)); + uop_SUB_IMM(ir, IREG_16(opcode & 7), IREG_16(opcode & 7), 1); + uop_MOVZX(ir, IREG_flags_res, IREG_16(opcode & 7)); + uop_MOV_IMM(ir, IREG_flags_op2, 1); + uop_MOV_IMM(ir, IREG_flags_op, FLAGS_DEC16); + codegen_flags_changed = 1; + + return op_pc; +} +uint32_t +ropDEC_r32(UNUSED(codeblock_t *block), ir_data_t *ir, UNUSED(uint8_t opcode), uint32_t fetchdat, UNUSED(uint32_t op_32), uint32_t op_pc) +{ + rebuild_c(ir); + + uop_MOV(ir, IREG_flags_op1, IREG_32(opcode & 7)); + uop_SUB_IMM(ir, IREG_32(opcode & 7), IREG_32(opcode & 7), 1); + uop_MOV(ir, IREG_flags_res, IREG_32(opcode & 7)); + uop_MOV_IMM(ir, IREG_flags_op2, 1); + uop_MOV_IMM(ir, IREG_flags_op, FLAGS_DEC32); + codegen_flags_changed = 1; + + return op_pc; +} + +uint32_t +ropINCDEC(codeblock_t *block, ir_data_t *ir, UNUSED(uint8_t opcode), uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) +{ + codegen_mark_code_present(block, cs + op_pc, 1); + rebuild_c(ir); + + if ((fetchdat & 0xc0) == 0xc0) { + uop_MOVZX(ir, IREG_flags_op1, IREG_8(fetchdat & 7)); + if (fetchdat & 0x38) { + uop_SUB_IMM(ir, IREG_8(fetchdat & 7), IREG_8(fetchdat & 7), 1); + uop_MOV_IMM(ir, IREG_flags_op, FLAGS_DEC8); + } else { + uop_ADD_IMM(ir, IREG_8(fetchdat & 7), IREG_8(fetchdat & 7), 1); + uop_MOV_IMM(ir, IREG_flags_op, FLAGS_INC8); + } + uop_MOVZX(ir, IREG_flags_res, IREG_8(fetchdat & 7)); uop_MOV_IMM(ir, IREG_flags_op2, 1); - uop_MOV_IMM(ir, IREG_flags_op, FLAGS_INC16); - codegen_flags_changed = 1; + } else { + x86seg *target_seg; - return op_pc; -} -uint32_t ropINC_r32(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) -{ - rebuild_c(ir); - - uop_MOV(ir, IREG_flags_op1, IREG_32(opcode & 7)); - uop_ADD_IMM(ir, IREG_32(opcode & 7), IREG_32(opcode & 7), 1); - uop_MOV(ir, IREG_flags_res, IREG_32(opcode & 7)); - uop_MOV_IMM(ir, IREG_flags_op2, 1); - uop_MOV_IMM(ir, IREG_flags_op, FLAGS_INC32); - codegen_flags_changed = 1; + uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc); + target_seg = codegen_generate_ea(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32, 0); + codegen_check_seg_write(block, ir, target_seg); + uop_MEM_LOAD_REG(ir, IREG_temp0_B, ireg_seg_base(target_seg), IREG_eaaddr); - return op_pc; -} - -uint32_t ropDEC_r16(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) -{ - rebuild_c(ir); - - uop_MOVZX(ir, IREG_flags_op1, IREG_16(opcode & 7)); - uop_SUB_IMM(ir, IREG_16(opcode & 7), IREG_16(opcode & 7), 1); - uop_MOVZX(ir, IREG_flags_res, IREG_16(opcode & 7)); - uop_MOV_IMM(ir, IREG_flags_op2, 1); - uop_MOV_IMM(ir, IREG_flags_op, FLAGS_DEC16); - codegen_flags_changed = 1; - - return op_pc; -} -uint32_t ropDEC_r32(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) -{ - rebuild_c(ir); - - uop_MOV(ir, IREG_flags_op1, IREG_32(opcode & 7)); - uop_SUB_IMM(ir, IREG_32(opcode & 7), IREG_32(opcode & 7), 1); - uop_MOV(ir, IREG_flags_res, IREG_32(opcode & 7)); - uop_MOV_IMM(ir, IREG_flags_op2, 1); - uop_MOV_IMM(ir, IREG_flags_op, FLAGS_DEC32); - codegen_flags_changed = 1; - - return op_pc; -} - -uint32_t ropINCDEC(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) -{ - codegen_mark_code_present(block, cs+op_pc, 1); - rebuild_c(ir); - - if ((fetchdat & 0xc0) == 0xc0) - { - uop_MOVZX(ir, IREG_flags_op1, IREG_8(fetchdat & 7)); - if (fetchdat & 0x38) - { - uop_SUB_IMM(ir, IREG_8(fetchdat & 7), IREG_8(fetchdat & 7), 1); - uop_MOV_IMM(ir, IREG_flags_op, FLAGS_DEC8); - } - else - { - uop_ADD_IMM(ir, IREG_8(fetchdat & 7), IREG_8(fetchdat & 7), 1); - uop_MOV_IMM(ir, IREG_flags_op, FLAGS_INC8); - } - uop_MOVZX(ir, IREG_flags_res, IREG_8(fetchdat & 7)); - uop_MOV_IMM(ir, IREG_flags_op2, 1); + if (fetchdat & 0x38) { + uop_SUB_IMM(ir, IREG_temp1_B, IREG_temp0_B, 1); + } else { + uop_ADD_IMM(ir, IREG_temp1_B, IREG_temp0_B, 1); } - else - { - x86seg *target_seg; - - uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc); - target_seg = codegen_generate_ea(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32, 0); - codegen_check_seg_write(block, ir, target_seg); - uop_MEM_LOAD_REG(ir, IREG_temp0_B, ireg_seg_base(target_seg), IREG_eaaddr); - - if (fetchdat & 0x38) - { - uop_SUB_IMM(ir, IREG_temp1_B, IREG_temp0_B, 1); - } - else - { - uop_ADD_IMM(ir, IREG_temp1_B, IREG_temp0_B, 1); - } - uop_MEM_STORE_REG(ir, ireg_seg_base(target_seg), IREG_eaaddr, IREG_temp1_B); - uop_MOVZX(ir, IREG_flags_op1, IREG_temp0_B); - uop_MOVZX(ir, IREG_flags_res, IREG_temp1_B); - uop_MOV_IMM(ir, IREG_flags_op2, 1); - if (fetchdat & 0x38) - { - uop_MOV_IMM(ir, IREG_flags_op, FLAGS_DEC8); - } - else - { - uop_MOV_IMM(ir, IREG_flags_op, FLAGS_INC8); - } + uop_MEM_STORE_REG(ir, ireg_seg_base(target_seg), IREG_eaaddr, IREG_temp1_B); + uop_MOVZX(ir, IREG_flags_op1, IREG_temp0_B); + uop_MOVZX(ir, IREG_flags_res, IREG_temp1_B); + uop_MOV_IMM(ir, IREG_flags_op2, 1); + if (fetchdat & 0x38) { + uop_MOV_IMM(ir, IREG_flags_op, FLAGS_DEC8); + } else { + uop_MOV_IMM(ir, IREG_flags_op, FLAGS_INC8); } + } - return op_pc+1; + return op_pc + 1; } diff --git a/src/codegen_new/codegen_ops_arith.h b/src/codegen_new/codegen_ops_arith.h index d1bbaa75d..176d4be7a 100644 --- a/src/codegen_new/codegen_ops_arith.h +++ b/src/codegen_new/codegen_ops_arith.h @@ -54,7 +54,6 @@ uint32_t rop81_l(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fet uint32_t rop83_w(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc); uint32_t rop83_l(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc); - uint32_t ropDEC_r16(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc); uint32_t ropDEC_r32(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc); diff --git a/src/codegen_new/codegen_ops_branch.c b/src/codegen_new/codegen_ops_branch.c index 88c30f2af..cedb54177 100644 --- a/src/codegen_new/codegen_ops_branch.c +++ b/src/codegen_new/codegen_ops_branch.c @@ -2,8 +2,11 @@ #include <86box/86box.h> #include "cpu.h" #include <86box/mem.h> +#include <86box/plat_unused.h> #include "x86.h" +#include "x86seg_common.h" +#include "x86seg.h" #include "386_common.h" #include "x86_flags.h" #include "codegen.h" @@ -13,843 +16,841 @@ #include "codegen_ops_helpers.h" #include "codegen_ops_mov.h" -static int NF_SET_01() +static int +NF_SET_01(void) { - return NF_SET() ? 1 : 0; + return NF_SET() ? 1 : 0; } -static int VF_SET_01() +static int +VF_SET_01(void) { - return VF_SET() ? 1 : 0; + return VF_SET() ? 1 : 0; } -static int ropJO_common(codeblock_t *block, ir_data_t *ir, uint32_t dest_addr, uint32_t next_pc) +static int +ropJO_common(UNUSED(codeblock_t *block), ir_data_t *ir, uint32_t dest_addr, UNUSED(uint32_t next_pc)) { - int jump_uop; + int jump_uop; - switch (codegen_flags_changed ? cpu_state.flags_op : FLAGS_UNKNOWN) - { - case FLAGS_ZN8: case FLAGS_ZN16: case FLAGS_ZN32: - /*Overflow is always zero*/ - return 0; + switch (codegen_flags_changed ? cpu_state.flags_op : FLAGS_UNKNOWN) { + case FLAGS_ZN8: + case FLAGS_ZN16: + case FLAGS_ZN32: + /*Overflow is always zero*/ + return 0; - case FLAGS_SUB8: case FLAGS_DEC8: - jump_uop = uop_CMP_JNO_DEST(ir, IREG_flags_op1_B, IREG_flags_op2_B); - break; + case FLAGS_SUB8: + case FLAGS_DEC8: + jump_uop = uop_CMP_JNO_DEST(ir, IREG_flags_op1_B, IREG_flags_op2_B); + break; - case FLAGS_SUB16: case FLAGS_DEC16: - jump_uop = uop_CMP_JNO_DEST(ir, IREG_flags_op1_W, IREG_flags_op2_W); - break; + case FLAGS_SUB16: + case FLAGS_DEC16: + jump_uop = uop_CMP_JNO_DEST(ir, IREG_flags_op1_W, IREG_flags_op2_W); + break; - case FLAGS_SUB32: case FLAGS_DEC32: - jump_uop = uop_CMP_JNO_DEST(ir, IREG_flags_op1, IREG_flags_op2); - break; + case FLAGS_SUB32: + case FLAGS_DEC32: + jump_uop = uop_CMP_JNO_DEST(ir, IREG_flags_op1, IREG_flags_op2); + break; - case FLAGS_UNKNOWN: - default: - uop_CALL_FUNC_RESULT(ir, IREG_temp0, VF_SET); - jump_uop = uop_CMP_IMM_JZ_DEST(ir, IREG_temp0, 0); - break; - } - uop_MOV_IMM(ir, IREG_pc, dest_addr); - uop_JMP(ir, codegen_exit_rout); - uop_set_jump_dest(ir, jump_uop); - return 0; + case FLAGS_UNKNOWN: + default: + uop_CALL_FUNC_RESULT(ir, IREG_temp0, VF_SET); + jump_uop = uop_CMP_IMM_JZ_DEST(ir, IREG_temp0, 0); + break; + } + uop_MOV_IMM(ir, IREG_pc, dest_addr); + uop_JMP(ir, codegen_exit_rout); + uop_set_jump_dest(ir, jump_uop); + return 0; } -static int ropJNO_common(codeblock_t *block, ir_data_t *ir, uint32_t dest_addr, uint32_t next_pc) +static int +ropJNO_common(UNUSED(codeblock_t *block), ir_data_t *ir, uint32_t dest_addr, UNUSED(uint32_t next_pc)) { - int jump_uop; + int jump_uop; - switch (codegen_flags_changed ? cpu_state.flags_op : FLAGS_UNKNOWN) - { - case FLAGS_ZN8: case FLAGS_ZN16: case FLAGS_ZN32: - /*Overflow is always zero*/ - uop_MOV_IMM(ir, IREG_pc, dest_addr); - uop_JMP(ir, codegen_exit_rout); - return 0; + switch (codegen_flags_changed ? cpu_state.flags_op : FLAGS_UNKNOWN) { + case FLAGS_ZN8: + case FLAGS_ZN16: + case FLAGS_ZN32: + /*Overflow is always zero*/ + uop_MOV_IMM(ir, IREG_pc, dest_addr); + uop_JMP(ir, codegen_exit_rout); + return 0; - case FLAGS_SUB8: case FLAGS_DEC8: - jump_uop = uop_CMP_JO_DEST(ir, IREG_flags_op1_B, IREG_flags_op2_B); - break; + case FLAGS_SUB8: + case FLAGS_DEC8: + jump_uop = uop_CMP_JO_DEST(ir, IREG_flags_op1_B, IREG_flags_op2_B); + break; - case FLAGS_SUB16: case FLAGS_DEC16: - jump_uop = uop_CMP_JO_DEST(ir, IREG_flags_op1_W, IREG_flags_op2_W); - break; + case FLAGS_SUB16: + case FLAGS_DEC16: + jump_uop = uop_CMP_JO_DEST(ir, IREG_flags_op1_W, IREG_flags_op2_W); + break; - case FLAGS_SUB32: case FLAGS_DEC32: - jump_uop = uop_CMP_JO_DEST(ir, IREG_flags_op1, IREG_flags_op2); - break; + case FLAGS_SUB32: + case FLAGS_DEC32: + jump_uop = uop_CMP_JO_DEST(ir, IREG_flags_op1, IREG_flags_op2); + break; - case FLAGS_UNKNOWN: - default: - uop_CALL_FUNC_RESULT(ir, IREG_temp0, VF_SET); + case FLAGS_UNKNOWN: + default: + uop_CALL_FUNC_RESULT(ir, IREG_temp0, VF_SET); + jump_uop = uop_CMP_IMM_JNZ_DEST(ir, IREG_temp0, 0); + break; + } + uop_MOV_IMM(ir, IREG_pc, dest_addr); + uop_JMP(ir, codegen_exit_rout); + uop_set_jump_dest(ir, jump_uop); + return 0; +} + +static int +ropJB_common(codeblock_t *block, ir_data_t *ir, uint32_t dest_addr, uint32_t next_pc) +{ + int jump_uop; + int do_unroll = (CF_SET() && codegen_can_unroll(block, ir, next_pc, dest_addr)); + + switch (codegen_flags_changed ? cpu_state.flags_op : FLAGS_UNKNOWN) { + case FLAGS_ZN8: + case FLAGS_ZN16: + case FLAGS_ZN32: + /*Carry is always zero*/ + return 0; + + case FLAGS_SUB8: + if (do_unroll) + jump_uop = uop_CMP_JB_DEST(ir, IREG_flags_op1_B, IREG_flags_op2_B); + else + jump_uop = uop_CMP_JNB_DEST(ir, IREG_flags_op1_B, IREG_flags_op2_B); + break; + + case FLAGS_SUB16: + if (do_unroll) + jump_uop = uop_CMP_JB_DEST(ir, IREG_flags_op1_W, IREG_flags_op2_W); + else + jump_uop = uop_CMP_JNB_DEST(ir, IREG_flags_op1_W, IREG_flags_op2_W); + break; + + case FLAGS_SUB32: + if (do_unroll) + jump_uop = uop_CMP_JB_DEST(ir, IREG_flags_op1, IREG_flags_op2); + else + jump_uop = uop_CMP_JNB_DEST(ir, IREG_flags_op1, IREG_flags_op2); + break; + + case FLAGS_UNKNOWN: + default: + uop_CALL_FUNC_RESULT(ir, IREG_temp0, CF_SET); + if (do_unroll) jump_uop = uop_CMP_IMM_JNZ_DEST(ir, IREG_temp0, 0); - break; + else + jump_uop = uop_CMP_IMM_JZ_DEST(ir, IREG_temp0, 0); + break; + } + uop_MOV_IMM(ir, IREG_pc, do_unroll ? next_pc : dest_addr); + uop_JMP(ir, codegen_exit_rout); + uop_set_jump_dest(ir, jump_uop); + return do_unroll ? 1 : 0; +} +static int +ropJNB_common(codeblock_t *block, ir_data_t *ir, uint32_t dest_addr, uint32_t next_pc) +{ + int jump_uop; + int do_unroll = (!CF_SET() && codegen_can_unroll(block, ir, next_pc, dest_addr)); + + switch (codegen_flags_changed ? cpu_state.flags_op : FLAGS_UNKNOWN) { + case FLAGS_ZN8: + case FLAGS_ZN16: + case FLAGS_ZN32: + /*Carry is always zero*/ + uop_MOV_IMM(ir, IREG_pc, dest_addr); + uop_JMP(ir, codegen_exit_rout); + return 0; + + case FLAGS_SUB8: + if (do_unroll) + jump_uop = uop_CMP_JNB_DEST(ir, IREG_flags_op1_B, IREG_flags_op2_B); + else + jump_uop = uop_CMP_JB_DEST(ir, IREG_flags_op1_B, IREG_flags_op2_B); + break; + + case FLAGS_SUB16: + if (do_unroll) + jump_uop = uop_CMP_JNB_DEST(ir, IREG_flags_op1_W, IREG_flags_op2_W); + else + jump_uop = uop_CMP_JB_DEST(ir, IREG_flags_op1_W, IREG_flags_op2_W); + break; + + case FLAGS_SUB32: + if (do_unroll) + jump_uop = uop_CMP_JNB_DEST(ir, IREG_flags_op1, IREG_flags_op2); + else + jump_uop = uop_CMP_JB_DEST(ir, IREG_flags_op1, IREG_flags_op2); + break; + + case FLAGS_UNKNOWN: + default: + uop_CALL_FUNC_RESULT(ir, IREG_temp0, CF_SET); + if (do_unroll) + jump_uop = uop_CMP_IMM_JZ_DEST(ir, IREG_temp0, 0); + else + jump_uop = uop_CMP_IMM_JNZ_DEST(ir, IREG_temp0, 0); + break; + } + uop_MOV_IMM(ir, IREG_pc, do_unroll ? next_pc : dest_addr); + uop_JMP(ir, codegen_exit_rout); + uop_set_jump_dest(ir, jump_uop); + return do_unroll ? 1 : 0; +} + +static int +ropJE_common(codeblock_t *block, ir_data_t *ir, uint32_t dest_addr, uint32_t next_pc) +{ + int jump_uop; + + if (ZF_SET() && codegen_can_unroll(block, ir, next_pc, dest_addr)) { + if (!codegen_flags_changed || !flags_res_valid()) { + uop_CALL_FUNC_RESULT(ir, IREG_temp0, ZF_SET); + jump_uop = uop_CMP_IMM_JNZ_DEST(ir, IREG_temp0, 0); + } else { + jump_uop = uop_CMP_IMM_JZ_DEST(ir, IREG_flags_res, 0); + } + uop_MOV_IMM(ir, IREG_pc, next_pc); + uop_JMP(ir, codegen_exit_rout); + uop_set_jump_dest(ir, jump_uop); + return 1; + } else { + if (!codegen_flags_changed || !flags_res_valid()) { + uop_CALL_FUNC_RESULT(ir, IREG_temp0, ZF_SET); + jump_uop = uop_CMP_IMM_JZ_DEST(ir, IREG_temp0, 0); + } else { + jump_uop = uop_CMP_IMM_JNZ_DEST(ir, IREG_flags_res, 0); } uop_MOV_IMM(ir, IREG_pc, dest_addr); uop_JMP(ir, codegen_exit_rout); uop_set_jump_dest(ir, jump_uop); - return 0; + } + return 0; +} +int +ropJNE_common(codeblock_t *block, ir_data_t *ir, uint32_t dest_addr, uint32_t next_pc) +{ + int jump_uop; + + if (!ZF_SET() && codegen_can_unroll(block, ir, next_pc, dest_addr)) { + if (!codegen_flags_changed || !flags_res_valid()) { + uop_CALL_FUNC_RESULT(ir, IREG_temp0, ZF_SET); + jump_uop = uop_CMP_IMM_JZ_DEST(ir, IREG_temp0, 0); + } else { + jump_uop = uop_CMP_IMM_JNZ_DEST(ir, IREG_flags_res, 0); + } + uop_MOV_IMM(ir, IREG_pc, next_pc); + uop_JMP(ir, codegen_exit_rout); + uop_set_jump_dest(ir, jump_uop); + return 1; + } else { + if (!codegen_flags_changed || !flags_res_valid()) { + uop_CALL_FUNC_RESULT(ir, IREG_temp0, ZF_SET); + jump_uop = uop_CMP_IMM_JNZ_DEST(ir, IREG_temp0, 0); + } else { + jump_uop = uop_CMP_IMM_JZ_DEST(ir, IREG_flags_res, 0); + } + uop_MOV_IMM(ir, IREG_pc, dest_addr); + uop_JMP(ir, codegen_exit_rout); + uop_set_jump_dest(ir, jump_uop); + } + return 0; } -static int ropJB_common(codeblock_t *block, ir_data_t *ir, uint32_t dest_addr, uint32_t next_pc) +static int +ropJBE_common(codeblock_t *block, ir_data_t *ir, uint32_t dest_addr, uint32_t next_pc) { - int jump_uop; - int do_unroll = (CF_SET() && codegen_can_unroll(block, ir, next_pc, dest_addr)); + int jump_uop; + int jump_uop2 = -1; + int do_unroll = ((CF_SET() || ZF_SET()) && codegen_can_unroll(block, ir, next_pc, dest_addr)); - switch (codegen_flags_changed ? cpu_state.flags_op : FLAGS_UNKNOWN) - { - case FLAGS_ZN8: case FLAGS_ZN16: case FLAGS_ZN32: - /*Carry is always zero*/ - return 0; + switch (codegen_flags_changed ? cpu_state.flags_op : FLAGS_UNKNOWN) { + case FLAGS_ZN8: + case FLAGS_ZN16: + case FLAGS_ZN32: + /*Carry is always zero, so test zero only*/ + if (do_unroll) + jump_uop = uop_CMP_IMM_JZ_DEST(ir, IREG_flags_res, 0); + else + jump_uop = uop_CMP_IMM_JNZ_DEST(ir, IREG_flags_res, 0); + break; - case FLAGS_SUB8: - if (do_unroll) - jump_uop = uop_CMP_JB_DEST(ir, IREG_flags_op1_B, IREG_flags_op2_B); - else - jump_uop = uop_CMP_JNB_DEST(ir, IREG_flags_op1_B, IREG_flags_op2_B); - break; + case FLAGS_SUB8: + if (do_unroll) + jump_uop = uop_CMP_JBE_DEST(ir, IREG_flags_op1_B, IREG_flags_op2_B); + else + jump_uop = uop_CMP_JNBE_DEST(ir, IREG_flags_op1_B, IREG_flags_op2_B); + break; + case FLAGS_SUB16: + if (do_unroll) + jump_uop = uop_CMP_JBE_DEST(ir, IREG_flags_op1_W, IREG_flags_op2_W); + else + jump_uop = uop_CMP_JNBE_DEST(ir, IREG_flags_op1_W, IREG_flags_op2_W); + break; + case FLAGS_SUB32: + if (do_unroll) + jump_uop = uop_CMP_JBE_DEST(ir, IREG_flags_op1, IREG_flags_op2); + else + jump_uop = uop_CMP_JNBE_DEST(ir, IREG_flags_op1, IREG_flags_op2); + break; - case FLAGS_SUB16: - if (do_unroll) - jump_uop = uop_CMP_JB_DEST(ir, IREG_flags_op1_W, IREG_flags_op2_W); - else - jump_uop = uop_CMP_JNB_DEST(ir, IREG_flags_op1_W, IREG_flags_op2_W); - break; - - case FLAGS_SUB32: - if (do_unroll) - jump_uop = uop_CMP_JB_DEST(ir, IREG_flags_op1, IREG_flags_op2); - else - jump_uop = uop_CMP_JNB_DEST(ir, IREG_flags_op1, IREG_flags_op2); - break; - - case FLAGS_UNKNOWN: - default: + case FLAGS_UNKNOWN: + default: + if (do_unroll) { uop_CALL_FUNC_RESULT(ir, IREG_temp0, CF_SET); - if (do_unroll) - jump_uop = uop_CMP_IMM_JNZ_DEST(ir, IREG_temp0, 0); - else - jump_uop = uop_CMP_IMM_JZ_DEST(ir, IREG_temp0, 0); - break; - } - uop_MOV_IMM(ir, IREG_pc, do_unroll ? next_pc : dest_addr); - uop_JMP(ir, codegen_exit_rout); - uop_set_jump_dest(ir, jump_uop); - return do_unroll ? 1 : 0; -} -static int ropJNB_common(codeblock_t *block, ir_data_t *ir, uint32_t dest_addr, uint32_t next_pc) -{ - int jump_uop; - int do_unroll = (!CF_SET() && codegen_can_unroll(block, ir, next_pc, dest_addr)); - - switch (codegen_flags_changed ? cpu_state.flags_op : FLAGS_UNKNOWN) - { - case FLAGS_ZN8: case FLAGS_ZN16: case FLAGS_ZN32: - /*Carry is always zero*/ - uop_MOV_IMM(ir, IREG_pc, dest_addr); - uop_JMP(ir, codegen_exit_rout); - return 0; - - case FLAGS_SUB8: - if (do_unroll) - jump_uop = uop_CMP_JNB_DEST(ir, IREG_flags_op1_B, IREG_flags_op2_B); - else - jump_uop = uop_CMP_JB_DEST(ir, IREG_flags_op1_B, IREG_flags_op2_B); - break; - - case FLAGS_SUB16: - if (do_unroll) - jump_uop = uop_CMP_JNB_DEST(ir, IREG_flags_op1_W, IREG_flags_op2_W); - else - jump_uop = uop_CMP_JB_DEST(ir, IREG_flags_op1_W, IREG_flags_op2_W); - break; - - case FLAGS_SUB32: - if (do_unroll) - jump_uop = uop_CMP_JNB_DEST(ir, IREG_flags_op1, IREG_flags_op2); - else - jump_uop = uop_CMP_JB_DEST(ir, IREG_flags_op1, IREG_flags_op2); - break; - - case FLAGS_UNKNOWN: - default: + jump_uop2 = uop_CMP_IMM_JNZ_DEST(ir, IREG_temp0, 0); + uop_CALL_FUNC_RESULT(ir, IREG_temp0, ZF_SET); + jump_uop = uop_CMP_IMM_JNZ_DEST(ir, IREG_temp0, 0); + } else { uop_CALL_FUNC_RESULT(ir, IREG_temp0, CF_SET); - if (do_unroll) - jump_uop = uop_CMP_IMM_JZ_DEST(ir, IREG_temp0, 0); - else - jump_uop = uop_CMP_IMM_JNZ_DEST(ir, IREG_temp0, 0); - break; - } - uop_MOV_IMM(ir, IREG_pc, do_unroll ? next_pc : dest_addr); + jump_uop2 = uop_CMP_IMM_JNZ_DEST(ir, IREG_temp0, 0); + uop_CALL_FUNC_RESULT(ir, IREG_temp0, ZF_SET); + jump_uop = uop_CMP_IMM_JZ_DEST(ir, IREG_temp0, 0); + } + break; + } + if (do_unroll) { + uop_MOV_IMM(ir, IREG_pc, next_pc); uop_JMP(ir, codegen_exit_rout); uop_set_jump_dest(ir, jump_uop); - return do_unroll ? 1 : 0; -} - -static int ropJE_common(codeblock_t *block, ir_data_t *ir, uint32_t dest_addr, uint32_t next_pc) -{ - int jump_uop; - - if (ZF_SET() && codegen_can_unroll(block, ir, next_pc, dest_addr)) - { - if (!codegen_flags_changed || !flags_res_valid()) - { - uop_CALL_FUNC_RESULT(ir, IREG_temp0, ZF_SET); - jump_uop = uop_CMP_IMM_JNZ_DEST(ir, IREG_temp0, 0); - } - else - { - jump_uop = uop_CMP_IMM_JZ_DEST(ir, IREG_flags_res, 0); - } - uop_MOV_IMM(ir, IREG_pc, next_pc); - uop_JMP(ir, codegen_exit_rout); - uop_set_jump_dest(ir, jump_uop); - return 1; - } - else - { - if (!codegen_flags_changed || !flags_res_valid()) - { - uop_CALL_FUNC_RESULT(ir, IREG_temp0, ZF_SET); - jump_uop = uop_CMP_IMM_JZ_DEST(ir, IREG_temp0, 0); - } - else - { - jump_uop = uop_CMP_IMM_JNZ_DEST(ir, IREG_flags_res, 0); - } - uop_MOV_IMM(ir, IREG_pc, dest_addr); - uop_JMP(ir, codegen_exit_rout); - uop_set_jump_dest(ir, jump_uop); - } - return 0; -} -int ropJNE_common(codeblock_t *block, ir_data_t *ir, uint32_t dest_addr, uint32_t next_pc) -{ - int jump_uop; - - if (!ZF_SET() && codegen_can_unroll(block, ir, next_pc, dest_addr)) - { - if (!codegen_flags_changed || !flags_res_valid()) - { - uop_CALL_FUNC_RESULT(ir, IREG_temp0, ZF_SET); - jump_uop = uop_CMP_IMM_JZ_DEST(ir, IREG_temp0, 0); - } - else - { - jump_uop = uop_CMP_IMM_JNZ_DEST(ir, IREG_flags_res, 0); - } - uop_MOV_IMM(ir, IREG_pc, next_pc); - uop_JMP(ir, codegen_exit_rout); - uop_set_jump_dest(ir, jump_uop); - return 1; - } - else - { - if (!codegen_flags_changed || !flags_res_valid()) - { - uop_CALL_FUNC_RESULT(ir, IREG_temp0, ZF_SET); - jump_uop = uop_CMP_IMM_JNZ_DEST(ir, IREG_temp0, 0); - } - else - { - jump_uop = uop_CMP_IMM_JZ_DEST(ir, IREG_flags_res, 0); - } - uop_MOV_IMM(ir, IREG_pc, dest_addr); - uop_JMP(ir, codegen_exit_rout); - uop_set_jump_dest(ir, jump_uop); - } - return 0; -} - -static int ropJBE_common(codeblock_t *block, ir_data_t *ir, uint32_t dest_addr, uint32_t next_pc) -{ - int jump_uop, jump_uop2 = -1; - int do_unroll = ((CF_SET() || ZF_SET()) && codegen_can_unroll(block, ir, next_pc, dest_addr)); - - switch (codegen_flags_changed ? cpu_state.flags_op : FLAGS_UNKNOWN) - { - case FLAGS_ZN8: case FLAGS_ZN16: case FLAGS_ZN32: - /*Carry is always zero, so test zero only*/ - if (do_unroll) - jump_uop = uop_CMP_IMM_JZ_DEST(ir, IREG_flags_res, 0); - else - jump_uop = uop_CMP_IMM_JNZ_DEST(ir, IREG_flags_res, 0); - break; - - case FLAGS_SUB8: - if (do_unroll) - jump_uop = uop_CMP_JBE_DEST(ir, IREG_flags_op1_B, IREG_flags_op2_B); - else - jump_uop = uop_CMP_JNBE_DEST(ir, IREG_flags_op1_B, IREG_flags_op2_B); - break; - case FLAGS_SUB16: - if (do_unroll) - jump_uop = uop_CMP_JBE_DEST(ir, IREG_flags_op1_W, IREG_flags_op2_W); - else - jump_uop = uop_CMP_JNBE_DEST(ir, IREG_flags_op1_W, IREG_flags_op2_W); - break; - case FLAGS_SUB32: - if (do_unroll) - jump_uop = uop_CMP_JBE_DEST(ir, IREG_flags_op1, IREG_flags_op2); - else - jump_uop = uop_CMP_JNBE_DEST(ir, IREG_flags_op1, IREG_flags_op2); - break; - - case FLAGS_UNKNOWN: - default: - if (do_unroll) - { - uop_CALL_FUNC_RESULT(ir, IREG_temp0, CF_SET); - jump_uop2 = uop_CMP_IMM_JNZ_DEST(ir, IREG_temp0, 0); - uop_CALL_FUNC_RESULT(ir, IREG_temp0, ZF_SET); - jump_uop = uop_CMP_IMM_JNZ_DEST(ir, IREG_temp0, 0); - } - else - { - uop_CALL_FUNC_RESULT(ir, IREG_temp0, CF_SET); - jump_uop2 = uop_CMP_IMM_JNZ_DEST(ir, IREG_temp0, 0); - uop_CALL_FUNC_RESULT(ir, IREG_temp0, ZF_SET); - jump_uop = uop_CMP_IMM_JZ_DEST(ir, IREG_temp0, 0); - } - break; - } - if (do_unroll) - { - uop_MOV_IMM(ir, IREG_pc, next_pc); - uop_JMP(ir, codegen_exit_rout); - uop_set_jump_dest(ir, jump_uop); - if (jump_uop2 != -1) - uop_set_jump_dest(ir, jump_uop2); - return 1; - } - else - { - if (jump_uop2 != -1) - uop_set_jump_dest(ir, jump_uop2); - uop_MOV_IMM(ir, IREG_pc, dest_addr); - uop_JMP(ir, codegen_exit_rout); - uop_set_jump_dest(ir, jump_uop); - return 0; - } -} -static int ropJNBE_common(codeblock_t *block, ir_data_t *ir, uint32_t dest_addr, uint32_t next_pc) -{ - int jump_uop, jump_uop2 = -1; - int do_unroll = ((!CF_SET() && !ZF_SET()) && codegen_can_unroll(block, ir, next_pc, dest_addr)); - - switch (codegen_flags_changed ? cpu_state.flags_op : FLAGS_UNKNOWN) - { - case FLAGS_ZN8: case FLAGS_ZN16: case FLAGS_ZN32: - /*Carry is always zero, so test zero only*/ - if (do_unroll) - jump_uop = uop_CMP_IMM_JNZ_DEST(ir, IREG_flags_res, 0); - else - jump_uop = uop_CMP_IMM_JZ_DEST(ir, IREG_flags_res, 0); - break; - - case FLAGS_SUB8: - if (do_unroll) - jump_uop = uop_CMP_JNBE_DEST(ir, IREG_flags_op1_B, IREG_flags_op2_B); - else - jump_uop = uop_CMP_JBE_DEST(ir, IREG_flags_op1_B, IREG_flags_op2_B); - break; - case FLAGS_SUB16: - if (do_unroll) - jump_uop = uop_CMP_JNBE_DEST(ir, IREG_flags_op1_W, IREG_flags_op2_W); - else - jump_uop = uop_CMP_JBE_DEST(ir, IREG_flags_op1_W, IREG_flags_op2_W); - break; - case FLAGS_SUB32: - if (do_unroll) - jump_uop = uop_CMP_JNBE_DEST(ir, IREG_flags_op1, IREG_flags_op2); - else - jump_uop = uop_CMP_JBE_DEST(ir, IREG_flags_op1, IREG_flags_op2); - break; - - case FLAGS_UNKNOWN: - default: - if (do_unroll) - { - uop_CALL_FUNC_RESULT(ir, IREG_temp0, CF_SET); - jump_uop2 = uop_CMP_IMM_JNZ_DEST(ir, IREG_temp0, 0); - uop_CALL_FUNC_RESULT(ir, IREG_temp0, ZF_SET); - jump_uop = uop_CMP_IMM_JZ_DEST(ir, IREG_temp0, 0); - } - else - { - uop_CALL_FUNC_RESULT(ir, IREG_temp0, CF_SET); - jump_uop = uop_CMP_IMM_JNZ_DEST(ir, IREG_temp0, 0); - uop_CALL_FUNC_RESULT(ir, IREG_temp0, ZF_SET); - jump_uop2 = uop_CMP_IMM_JNZ_DEST(ir, IREG_temp0, 0); - } - break; - } - if (do_unroll) - { - if (jump_uop2 != -1) - uop_set_jump_dest(ir, jump_uop2); - uop_MOV_IMM(ir, IREG_pc, next_pc); - uop_JMP(ir, codegen_exit_rout); - uop_set_jump_dest(ir, jump_uop); - return 1; - } - else - { - uop_MOV_IMM(ir, IREG_pc, dest_addr); - uop_JMP(ir, codegen_exit_rout); - uop_set_jump_dest(ir, jump_uop); - if (jump_uop2 != -1) - uop_set_jump_dest(ir, jump_uop2); - return 0; - } -} - -static int ropJS_common(codeblock_t *block, ir_data_t *ir, uint32_t dest_addr, uint32_t next_pc) -{ - int jump_uop; - int do_unroll = (NF_SET() && codegen_can_unroll(block, ir, next_pc, dest_addr)); - - switch (codegen_flags_changed ? cpu_state.flags_op : FLAGS_UNKNOWN) - { - case FLAGS_ZN8: - case FLAGS_ADD8: - case FLAGS_SUB8: - case FLAGS_SHL8: - case FLAGS_SHR8: - case FLAGS_SAR8: - case FLAGS_INC8: - case FLAGS_DEC8: - if (do_unroll) - jump_uop = uop_TEST_JS_DEST(ir, IREG_flags_res_B); - else - jump_uop = uop_TEST_JNS_DEST(ir, IREG_flags_res_B); - break; - - case FLAGS_ZN16: - case FLAGS_ADD16: - case FLAGS_SUB16: - case FLAGS_SHL16: - case FLAGS_SHR16: - case FLAGS_SAR16: - case FLAGS_INC16: - case FLAGS_DEC16: - if (do_unroll) - jump_uop = uop_TEST_JS_DEST(ir, IREG_flags_res_W); - else - jump_uop = uop_TEST_JNS_DEST(ir, IREG_flags_res_W); - break; - - case FLAGS_ZN32: - case FLAGS_ADD32: - case FLAGS_SUB32: - case FLAGS_SHL32: - case FLAGS_SHR32: - case FLAGS_SAR32: - case FLAGS_INC32: - case FLAGS_DEC32: - if (do_unroll) - jump_uop = uop_TEST_JS_DEST(ir, IREG_flags_res); - else - jump_uop = uop_TEST_JNS_DEST(ir, IREG_flags_res); - break; - - case FLAGS_UNKNOWN: - default: - uop_CALL_FUNC_RESULT(ir, IREG_temp0, NF_SET); - if (do_unroll) - jump_uop = uop_CMP_IMM_JNZ_DEST(ir, IREG_temp0, 0); - else - jump_uop = uop_CMP_IMM_JZ_DEST(ir, IREG_temp0, 0); - break; - } - uop_MOV_IMM(ir, IREG_pc, do_unroll ? next_pc : dest_addr); - uop_JMP(ir, codegen_exit_rout); - uop_set_jump_dest(ir, jump_uop); - return do_unroll ? 1 : 0; -} -static int ropJNS_common(codeblock_t *block, ir_data_t *ir, uint32_t dest_addr, uint32_t next_pc) -{ - int jump_uop; - int do_unroll = (!NF_SET() && codegen_can_unroll(block, ir, next_pc, dest_addr)); - - switch (codegen_flags_changed ? cpu_state.flags_op : FLAGS_UNKNOWN) - { - case FLAGS_ZN8: - case FLAGS_ADD8: - case FLAGS_SUB8: - case FLAGS_SHL8: - case FLAGS_SHR8: - case FLAGS_SAR8: - case FLAGS_INC8: - case FLAGS_DEC8: - if (do_unroll) - jump_uop = uop_TEST_JNS_DEST(ir, IREG_flags_res_B); - else - jump_uop = uop_TEST_JS_DEST(ir, IREG_flags_res_B); - break; - - case FLAGS_ZN16: - case FLAGS_ADD16: - case FLAGS_SUB16: - case FLAGS_SHL16: - case FLAGS_SHR16: - case FLAGS_SAR16: - case FLAGS_INC16: - case FLAGS_DEC16: - if (do_unroll) - jump_uop = uop_TEST_JNS_DEST(ir, IREG_flags_res_W); - else - jump_uop = uop_TEST_JS_DEST(ir, IREG_flags_res_W); - break; - - case FLAGS_ZN32: - case FLAGS_ADD32: - case FLAGS_SUB32: - case FLAGS_SHL32: - case FLAGS_SHR32: - case FLAGS_SAR32: - case FLAGS_INC32: - case FLAGS_DEC32: - if (do_unroll) - jump_uop = uop_TEST_JNS_DEST(ir, IREG_flags_res); - else - jump_uop = uop_TEST_JS_DEST(ir, IREG_flags_res); - break; - - case FLAGS_UNKNOWN: - default: - uop_CALL_FUNC_RESULT(ir, IREG_temp0, NF_SET); - if (do_unroll) - jump_uop = uop_CMP_IMM_JZ_DEST(ir, IREG_temp0, 0); - else - jump_uop = uop_CMP_IMM_JNZ_DEST(ir, IREG_temp0, 0); - break; - } - uop_MOV_IMM(ir, IREG_pc, do_unroll ? next_pc : dest_addr); - uop_JMP(ir, codegen_exit_rout); - uop_set_jump_dest(ir, jump_uop); - return do_unroll ? 1 : 0; -} - -static int ropJP_common(codeblock_t *block, ir_data_t *ir, uint32_t dest_addr, uint32_t next_pc) -{ - int jump_uop; - - uop_CALL_FUNC_RESULT(ir, IREG_temp0, PF_SET); - jump_uop = uop_CMP_IMM_JZ_DEST(ir, IREG_temp0, 0); + if (jump_uop2 != -1) + uop_set_jump_dest(ir, jump_uop2); + return 1; + } else { + if (jump_uop2 != -1) + uop_set_jump_dest(ir, jump_uop2); uop_MOV_IMM(ir, IREG_pc, dest_addr); uop_JMP(ir, codegen_exit_rout); uop_set_jump_dest(ir, jump_uop); return 0; + } } -static int ropJNP_common(codeblock_t *block, ir_data_t *ir, uint32_t dest_addr, uint32_t next_pc) +static int +ropJNBE_common(codeblock_t *block, ir_data_t *ir, uint32_t dest_addr, uint32_t next_pc) { - int jump_uop; + int jump_uop; + int jump_uop2 = -1; + int do_unroll = ((!CF_SET() && !ZF_SET()) && codegen_can_unroll(block, ir, next_pc, dest_addr)); - uop_CALL_FUNC_RESULT(ir, IREG_temp0, PF_SET); - jump_uop = uop_CMP_IMM_JNZ_DEST(ir, IREG_temp0, 0); + switch (codegen_flags_changed ? cpu_state.flags_op : FLAGS_UNKNOWN) { + case FLAGS_ZN8: + case FLAGS_ZN16: + case FLAGS_ZN32: + /*Carry is always zero, so test zero only*/ + if (do_unroll) + jump_uop = uop_CMP_IMM_JNZ_DEST(ir, IREG_flags_res, 0); + else + jump_uop = uop_CMP_IMM_JZ_DEST(ir, IREG_flags_res, 0); + break; + + case FLAGS_SUB8: + if (do_unroll) + jump_uop = uop_CMP_JNBE_DEST(ir, IREG_flags_op1_B, IREG_flags_op2_B); + else + jump_uop = uop_CMP_JBE_DEST(ir, IREG_flags_op1_B, IREG_flags_op2_B); + break; + case FLAGS_SUB16: + if (do_unroll) + jump_uop = uop_CMP_JNBE_DEST(ir, IREG_flags_op1_W, IREG_flags_op2_W); + else + jump_uop = uop_CMP_JBE_DEST(ir, IREG_flags_op1_W, IREG_flags_op2_W); + break; + case FLAGS_SUB32: + if (do_unroll) + jump_uop = uop_CMP_JNBE_DEST(ir, IREG_flags_op1, IREG_flags_op2); + else + jump_uop = uop_CMP_JBE_DEST(ir, IREG_flags_op1, IREG_flags_op2); + break; + + case FLAGS_UNKNOWN: + default: + if (do_unroll) { + uop_CALL_FUNC_RESULT(ir, IREG_temp0, CF_SET); + jump_uop2 = uop_CMP_IMM_JNZ_DEST(ir, IREG_temp0, 0); + uop_CALL_FUNC_RESULT(ir, IREG_temp0, ZF_SET); + jump_uop = uop_CMP_IMM_JZ_DEST(ir, IREG_temp0, 0); + } else { + uop_CALL_FUNC_RESULT(ir, IREG_temp0, CF_SET); + jump_uop = uop_CMP_IMM_JNZ_DEST(ir, IREG_temp0, 0); + uop_CALL_FUNC_RESULT(ir, IREG_temp0, ZF_SET); + jump_uop2 = uop_CMP_IMM_JNZ_DEST(ir, IREG_temp0, 0); + } + break; + } + if (do_unroll) { + if (jump_uop2 != -1) + uop_set_jump_dest(ir, jump_uop2); + uop_MOV_IMM(ir, IREG_pc, next_pc); + uop_JMP(ir, codegen_exit_rout); + uop_set_jump_dest(ir, jump_uop); + return 1; + } else { uop_MOV_IMM(ir, IREG_pc, dest_addr); uop_JMP(ir, codegen_exit_rout); uop_set_jump_dest(ir, jump_uop); + if (jump_uop2 != -1) + uop_set_jump_dest(ir, jump_uop2); return 0; + } } -static int ropJL_common(codeblock_t *block, ir_data_t *ir, uint32_t dest_addr, uint32_t next_pc) +static int +ropJS_common(codeblock_t *block, ir_data_t *ir, uint32_t dest_addr, uint32_t next_pc) { - int jump_uop; - int do_unroll = ((NF_SET() ? 1 : 0) != (VF_SET() ? 1 : 0) && codegen_can_unroll(block, ir, next_pc, dest_addr)); + int jump_uop; + int do_unroll = (NF_SET() && codegen_can_unroll(block, ir, next_pc, dest_addr)); - switch (codegen_flags_changed ? cpu_state.flags_op : FLAGS_UNKNOWN) - { - case FLAGS_ZN8: - /*V flag is always clear. Condition is true if N is set*/ - if (do_unroll) - jump_uop = uop_TEST_JS_DEST(ir, IREG_flags_res_B); - else - jump_uop = uop_TEST_JNS_DEST(ir, IREG_flags_res_B); - break; - case FLAGS_ZN16: - if (do_unroll) - jump_uop = uop_TEST_JS_DEST(ir, IREG_flags_res_W); - else - jump_uop = uop_TEST_JNS_DEST(ir, IREG_flags_res_W); - break; - case FLAGS_ZN32: - if (do_unroll) - jump_uop = uop_TEST_JS_DEST(ir, IREG_flags_res); - else - jump_uop = uop_TEST_JNS_DEST(ir, IREG_flags_res); - break; + switch (codegen_flags_changed ? cpu_state.flags_op : FLAGS_UNKNOWN) { + case FLAGS_ZN8: + case FLAGS_ADD8: + case FLAGS_SUB8: + case FLAGS_SHL8: + case FLAGS_SHR8: + case FLAGS_SAR8: + case FLAGS_INC8: + case FLAGS_DEC8: + if (do_unroll) + jump_uop = uop_TEST_JS_DEST(ir, IREG_flags_res_B); + else + jump_uop = uop_TEST_JNS_DEST(ir, IREG_flags_res_B); + break; - case FLAGS_SUB8: case FLAGS_DEC8: - if (do_unroll) - jump_uop = uop_CMP_JL_DEST(ir, IREG_flags_op1_B, IREG_flags_op2_B); - else - jump_uop = uop_CMP_JNL_DEST(ir, IREG_flags_op1_B, IREG_flags_op2_B); - break; - case FLAGS_SUB16: case FLAGS_DEC16: - if (do_unroll) - jump_uop = uop_CMP_JL_DEST(ir, IREG_flags_op1_W, IREG_flags_op2_W); - else - jump_uop = uop_CMP_JNL_DEST(ir, IREG_flags_op1_W, IREG_flags_op2_W); - break; - case FLAGS_SUB32: case FLAGS_DEC32: - if (do_unroll) - jump_uop = uop_CMP_JL_DEST(ir, IREG_flags_op1, IREG_flags_op2); - else - jump_uop = uop_CMP_JNL_DEST(ir, IREG_flags_op1, IREG_flags_op2); - break; + case FLAGS_ZN16: + case FLAGS_ADD16: + case FLAGS_SUB16: + case FLAGS_SHL16: + case FLAGS_SHR16: + case FLAGS_SAR16: + case FLAGS_INC16: + case FLAGS_DEC16: + if (do_unroll) + jump_uop = uop_TEST_JS_DEST(ir, IREG_flags_res_W); + else + jump_uop = uop_TEST_JNS_DEST(ir, IREG_flags_res_W); + break; - case FLAGS_UNKNOWN: - default: + case FLAGS_ZN32: + case FLAGS_ADD32: + case FLAGS_SUB32: + case FLAGS_SHL32: + case FLAGS_SHR32: + case FLAGS_SAR32: + case FLAGS_INC32: + case FLAGS_DEC32: + if (do_unroll) + jump_uop = uop_TEST_JS_DEST(ir, IREG_flags_res); + else + jump_uop = uop_TEST_JNS_DEST(ir, IREG_flags_res); + break; + + case FLAGS_UNKNOWN: + default: + uop_CALL_FUNC_RESULT(ir, IREG_temp0, NF_SET); + if (do_unroll) + jump_uop = uop_CMP_IMM_JNZ_DEST(ir, IREG_temp0, 0); + else + jump_uop = uop_CMP_IMM_JZ_DEST(ir, IREG_temp0, 0); + break; + } + uop_MOV_IMM(ir, IREG_pc, do_unroll ? next_pc : dest_addr); + uop_JMP(ir, codegen_exit_rout); + uop_set_jump_dest(ir, jump_uop); + return do_unroll ? 1 : 0; +} +static int +ropJNS_common(codeblock_t *block, ir_data_t *ir, uint32_t dest_addr, uint32_t next_pc) +{ + int jump_uop; + int do_unroll = (!NF_SET() && codegen_can_unroll(block, ir, next_pc, dest_addr)); + + switch (codegen_flags_changed ? cpu_state.flags_op : FLAGS_UNKNOWN) { + case FLAGS_ZN8: + case FLAGS_ADD8: + case FLAGS_SUB8: + case FLAGS_SHL8: + case FLAGS_SHR8: + case FLAGS_SAR8: + case FLAGS_INC8: + case FLAGS_DEC8: + if (do_unroll) + jump_uop = uop_TEST_JNS_DEST(ir, IREG_flags_res_B); + else + jump_uop = uop_TEST_JS_DEST(ir, IREG_flags_res_B); + break; + + case FLAGS_ZN16: + case FLAGS_ADD16: + case FLAGS_SUB16: + case FLAGS_SHL16: + case FLAGS_SHR16: + case FLAGS_SAR16: + case FLAGS_INC16: + case FLAGS_DEC16: + if (do_unroll) + jump_uop = uop_TEST_JNS_DEST(ir, IREG_flags_res_W); + else + jump_uop = uop_TEST_JS_DEST(ir, IREG_flags_res_W); + break; + + case FLAGS_ZN32: + case FLAGS_ADD32: + case FLAGS_SUB32: + case FLAGS_SHL32: + case FLAGS_SHR32: + case FLAGS_SAR32: + case FLAGS_INC32: + case FLAGS_DEC32: + if (do_unroll) + jump_uop = uop_TEST_JNS_DEST(ir, IREG_flags_res); + else + jump_uop = uop_TEST_JS_DEST(ir, IREG_flags_res); + break; + + case FLAGS_UNKNOWN: + default: + uop_CALL_FUNC_RESULT(ir, IREG_temp0, NF_SET); + if (do_unroll) + jump_uop = uop_CMP_IMM_JZ_DEST(ir, IREG_temp0, 0); + else + jump_uop = uop_CMP_IMM_JNZ_DEST(ir, IREG_temp0, 0); + break; + } + uop_MOV_IMM(ir, IREG_pc, do_unroll ? next_pc : dest_addr); + uop_JMP(ir, codegen_exit_rout); + uop_set_jump_dest(ir, jump_uop); + return do_unroll ? 1 : 0; +} + +static int +ropJP_common(UNUSED(codeblock_t *block), ir_data_t *ir, uint32_t dest_addr, UNUSED(uint32_t next_pc)) +{ + int jump_uop; + + uop_CALL_FUNC_RESULT(ir, IREG_temp0, PF_SET); + jump_uop = uop_CMP_IMM_JZ_DEST(ir, IREG_temp0, 0); + uop_MOV_IMM(ir, IREG_pc, dest_addr); + uop_JMP(ir, codegen_exit_rout); + uop_set_jump_dest(ir, jump_uop); + return 0; +} +static int +ropJNP_common(UNUSED(codeblock_t *block), ir_data_t *ir, uint32_t dest_addr, UNUSED(uint32_t next_pc)) +{ + int jump_uop; + + uop_CALL_FUNC_RESULT(ir, IREG_temp0, PF_SET); + jump_uop = uop_CMP_IMM_JNZ_DEST(ir, IREG_temp0, 0); + uop_MOV_IMM(ir, IREG_pc, dest_addr); + uop_JMP(ir, codegen_exit_rout); + uop_set_jump_dest(ir, jump_uop); + return 0; +} + +static int +ropJL_common(codeblock_t *block, ir_data_t *ir, uint32_t dest_addr, uint32_t next_pc) +{ + int jump_uop; + int do_unroll = ((NF_SET() ? 1 : 0) != (VF_SET() ? 1 : 0) && codegen_can_unroll(block, ir, next_pc, dest_addr)); + + switch (codegen_flags_changed ? cpu_state.flags_op : FLAGS_UNKNOWN) { + case FLAGS_ZN8: + /*V flag is always clear. Condition is true if N is set*/ + if (do_unroll) + jump_uop = uop_TEST_JS_DEST(ir, IREG_flags_res_B); + else + jump_uop = uop_TEST_JNS_DEST(ir, IREG_flags_res_B); + break; + case FLAGS_ZN16: + if (do_unroll) + jump_uop = uop_TEST_JS_DEST(ir, IREG_flags_res_W); + else + jump_uop = uop_TEST_JNS_DEST(ir, IREG_flags_res_W); + break; + case FLAGS_ZN32: + if (do_unroll) + jump_uop = uop_TEST_JS_DEST(ir, IREG_flags_res); + else + jump_uop = uop_TEST_JNS_DEST(ir, IREG_flags_res); + break; + + case FLAGS_SUB8: + case FLAGS_DEC8: + if (do_unroll) + jump_uop = uop_CMP_JL_DEST(ir, IREG_flags_op1_B, IREG_flags_op2_B); + else + jump_uop = uop_CMP_JNL_DEST(ir, IREG_flags_op1_B, IREG_flags_op2_B); + break; + case FLAGS_SUB16: + case FLAGS_DEC16: + if (do_unroll) + jump_uop = uop_CMP_JL_DEST(ir, IREG_flags_op1_W, IREG_flags_op2_W); + else + jump_uop = uop_CMP_JNL_DEST(ir, IREG_flags_op1_W, IREG_flags_op2_W); + break; + case FLAGS_SUB32: + case FLAGS_DEC32: + if (do_unroll) + jump_uop = uop_CMP_JL_DEST(ir, IREG_flags_op1, IREG_flags_op2); + else + jump_uop = uop_CMP_JNL_DEST(ir, IREG_flags_op1, IREG_flags_op2); + break; + + case FLAGS_UNKNOWN: + default: + uop_CALL_FUNC_RESULT(ir, IREG_temp0, NF_SET_01); + uop_CALL_FUNC_RESULT(ir, IREG_temp1, VF_SET_01); + if (do_unroll) + jump_uop = uop_CMP_JNZ_DEST(ir, IREG_temp0, IREG_temp1); + else + jump_uop = uop_CMP_JZ_DEST(ir, IREG_temp0, IREG_temp1); + break; + } + if (do_unroll) + uop_MOV_IMM(ir, IREG_pc, next_pc); + else + uop_MOV_IMM(ir, IREG_pc, dest_addr); + uop_JMP(ir, codegen_exit_rout); + uop_set_jump_dest(ir, jump_uop); + return do_unroll ? 1 : 0; +} +static int +ropJNL_common(codeblock_t *block, ir_data_t *ir, uint32_t dest_addr, uint32_t next_pc) +{ + int jump_uop; + int do_unroll = ((NF_SET() ? 1 : 0) == (VF_SET() ? 1 : 0) && codegen_can_unroll(block, ir, next_pc, dest_addr)); + + switch (codegen_flags_changed ? cpu_state.flags_op : FLAGS_UNKNOWN) { + case FLAGS_ZN8: + /*V flag is always clear. Condition is true if N is set*/ + if (do_unroll) + jump_uop = uop_TEST_JNS_DEST(ir, IREG_flags_res_B); + else + jump_uop = uop_TEST_JS_DEST(ir, IREG_flags_res_B); + break; + case FLAGS_ZN16: + if (do_unroll) + jump_uop = uop_TEST_JNS_DEST(ir, IREG_flags_res_W); + else + jump_uop = uop_TEST_JS_DEST(ir, IREG_flags_res_W); + break; + case FLAGS_ZN32: + if (do_unroll) + jump_uop = uop_TEST_JNS_DEST(ir, IREG_flags_res); + else + jump_uop = uop_TEST_JS_DEST(ir, IREG_flags_res); + break; + + case FLAGS_SUB8: + case FLAGS_DEC8: + if (do_unroll) + jump_uop = uop_CMP_JNL_DEST(ir, IREG_flags_op1_B, IREG_flags_op2_B); + else + jump_uop = uop_CMP_JL_DEST(ir, IREG_flags_op1_B, IREG_flags_op2_B); + break; + case FLAGS_SUB16: + case FLAGS_DEC16: + if (do_unroll) + jump_uop = uop_CMP_JNL_DEST(ir, IREG_flags_op1_W, IREG_flags_op2_W); + else + jump_uop = uop_CMP_JL_DEST(ir, IREG_flags_op1_W, IREG_flags_op2_W); + break; + case FLAGS_SUB32: + case FLAGS_DEC32: + if (do_unroll) + jump_uop = uop_CMP_JNL_DEST(ir, IREG_flags_op1, IREG_flags_op2); + else + jump_uop = uop_CMP_JL_DEST(ir, IREG_flags_op1, IREG_flags_op2); + break; + + case FLAGS_UNKNOWN: + default: + uop_CALL_FUNC_RESULT(ir, IREG_temp0, NF_SET_01); + uop_CALL_FUNC_RESULT(ir, IREG_temp1, VF_SET_01); + if (do_unroll) + jump_uop = uop_CMP_JZ_DEST(ir, IREG_temp0, IREG_temp1); + else + jump_uop = uop_CMP_JNZ_DEST(ir, IREG_temp0, IREG_temp1); + break; + } + if (do_unroll) + uop_MOV_IMM(ir, IREG_pc, next_pc); + else + uop_MOV_IMM(ir, IREG_pc, dest_addr); + uop_JMP(ir, codegen_exit_rout); + uop_set_jump_dest(ir, jump_uop); + return do_unroll ? 1 : 0; +} + +static int +ropJLE_common(codeblock_t *block, ir_data_t *ir, uint32_t dest_addr, uint32_t next_pc) +{ + int jump_uop; + int jump_uop2 = -1; + int do_unroll = (((NF_SET() ? 1 : 0) != (VF_SET() ? 1 : 0) || ZF_SET()) && codegen_can_unroll(block, ir, next_pc, dest_addr)); + + switch (codegen_flags_changed ? cpu_state.flags_op : FLAGS_UNKNOWN) { + case FLAGS_SUB8: + case FLAGS_DEC8: + if (do_unroll) + jump_uop = uop_CMP_JLE_DEST(ir, IREG_flags_op1_B, IREG_flags_op2_B); + else + jump_uop = uop_CMP_JNLE_DEST(ir, IREG_flags_op1_B, IREG_flags_op2_B); + break; + case FLAGS_SUB16: + case FLAGS_DEC16: + if (do_unroll) + jump_uop = uop_CMP_JLE_DEST(ir, IREG_flags_op1_W, IREG_flags_op2_W); + else + jump_uop = uop_CMP_JNLE_DEST(ir, IREG_flags_op1_W, IREG_flags_op2_W); + break; + case FLAGS_SUB32: + case FLAGS_DEC32: + if (do_unroll) + jump_uop = uop_CMP_JLE_DEST(ir, IREG_flags_op1, IREG_flags_op2); + else + jump_uop = uop_CMP_JNLE_DEST(ir, IREG_flags_op1, IREG_flags_op2); + break; + + case FLAGS_UNKNOWN: + default: + if (do_unroll) { + uop_CALL_FUNC_RESULT(ir, IREG_temp0, ZF_SET); + jump_uop2 = uop_CMP_IMM_JNZ_DEST(ir, IREG_temp0, 0); uop_CALL_FUNC_RESULT(ir, IREG_temp0, NF_SET_01); uop_CALL_FUNC_RESULT(ir, IREG_temp1, VF_SET_01); - if (do_unroll) - jump_uop = uop_CMP_JNZ_DEST(ir, IREG_temp0, IREG_temp1); - else - jump_uop = uop_CMP_JZ_DEST(ir, IREG_temp0, IREG_temp1); - break; - } - if (do_unroll) - uop_MOV_IMM(ir, IREG_pc, next_pc); - else - uop_MOV_IMM(ir, IREG_pc, dest_addr); - uop_JMP(ir, codegen_exit_rout); - uop_set_jump_dest(ir, jump_uop); - return do_unroll ? 1 : 0; -} -static int ropJNL_common(codeblock_t *block, ir_data_t *ir, uint32_t dest_addr, uint32_t next_pc) -{ - int jump_uop; - int do_unroll = ((NF_SET() ? 1 : 0) == (VF_SET() ? 1 : 0) && codegen_can_unroll(block, ir, next_pc, dest_addr)); - - switch (codegen_flags_changed ? cpu_state.flags_op : FLAGS_UNKNOWN) - { - case FLAGS_ZN8: - /*V flag is always clear. Condition is true if N is set*/ - if (do_unroll) - jump_uop = uop_TEST_JNS_DEST(ir, IREG_flags_res_B); - else - jump_uop = uop_TEST_JS_DEST(ir, IREG_flags_res_B); - break; - case FLAGS_ZN16: - if (do_unroll) - jump_uop = uop_TEST_JNS_DEST(ir, IREG_flags_res_W); - else - jump_uop = uop_TEST_JS_DEST(ir, IREG_flags_res_W); - break; - case FLAGS_ZN32: - if (do_unroll) - jump_uop = uop_TEST_JNS_DEST(ir, IREG_flags_res); - else - jump_uop = uop_TEST_JS_DEST(ir, IREG_flags_res); - break; - - case FLAGS_SUB8: case FLAGS_DEC8: - if (do_unroll) - jump_uop = uop_CMP_JNL_DEST(ir, IREG_flags_op1_B, IREG_flags_op2_B); - else - jump_uop = uop_CMP_JL_DEST(ir, IREG_flags_op1_B, IREG_flags_op2_B); - break; - case FLAGS_SUB16: case FLAGS_DEC16: - if (do_unroll) - jump_uop = uop_CMP_JNL_DEST(ir, IREG_flags_op1_W, IREG_flags_op2_W); - else - jump_uop = uop_CMP_JL_DEST(ir, IREG_flags_op1_W, IREG_flags_op2_W); - break; - case FLAGS_SUB32: case FLAGS_DEC32: - if (do_unroll) - jump_uop = uop_CMP_JNL_DEST(ir, IREG_flags_op1, IREG_flags_op2); - else - jump_uop = uop_CMP_JL_DEST(ir, IREG_flags_op1, IREG_flags_op2); - break; - - case FLAGS_UNKNOWN: - default: + jump_uop = uop_CMP_JNZ_DEST(ir, IREG_temp0, IREG_temp1); + } else { + uop_CALL_FUNC_RESULT(ir, IREG_temp0, ZF_SET); + jump_uop2 = uop_CMP_IMM_JNZ_DEST(ir, IREG_temp0, 0); uop_CALL_FUNC_RESULT(ir, IREG_temp0, NF_SET_01); uop_CALL_FUNC_RESULT(ir, IREG_temp1, VF_SET_01); - if (do_unroll) - jump_uop = uop_CMP_JZ_DEST(ir, IREG_temp0, IREG_temp1); - else - jump_uop = uop_CMP_JNZ_DEST(ir, IREG_temp0, IREG_temp1); - break; - } - if (do_unroll) - uop_MOV_IMM(ir, IREG_pc, next_pc); - else - uop_MOV_IMM(ir, IREG_pc, dest_addr); + jump_uop = uop_CMP_JZ_DEST(ir, IREG_temp0, IREG_temp1); + } + break; + } + if (do_unroll) { + uop_MOV_IMM(ir, IREG_pc, next_pc); uop_JMP(ir, codegen_exit_rout); uop_set_jump_dest(ir, jump_uop); - return do_unroll ? 1 : 0; + if (jump_uop2 != -1) + uop_set_jump_dest(ir, jump_uop2); + return 1; + } else { + if (jump_uop2 != -1) + uop_set_jump_dest(ir, jump_uop2); + uop_MOV_IMM(ir, IREG_pc, dest_addr); + uop_JMP(ir, codegen_exit_rout); + uop_set_jump_dest(ir, jump_uop); + return 0; + } } - -static int ropJLE_common(codeblock_t *block, ir_data_t *ir, uint32_t dest_addr, uint32_t next_pc) +static int +ropJNLE_common(codeblock_t *block, ir_data_t *ir, uint32_t dest_addr, uint32_t next_pc) { - int jump_uop, jump_uop2 = -1; - int do_unroll = (((NF_SET() ? 1 : 0) != (VF_SET() ? 1 : 0) || ZF_SET()) && codegen_can_unroll(block, ir, next_pc, dest_addr)); + int jump_uop; + int jump_uop2 = -1; + int do_unroll = ((NF_SET() ? 1 : 0) == (VF_SET() ? 1 : 0) && !ZF_SET() && codegen_can_unroll(block, ir, next_pc, dest_addr)); - switch (codegen_flags_changed ? cpu_state.flags_op : FLAGS_UNKNOWN) - { - case FLAGS_SUB8: case FLAGS_DEC8: - if (do_unroll) - jump_uop = uop_CMP_JLE_DEST(ir, IREG_flags_op1_B, IREG_flags_op2_B); - else - jump_uop = uop_CMP_JNLE_DEST(ir, IREG_flags_op1_B, IREG_flags_op2_B); - break; - case FLAGS_SUB16: case FLAGS_DEC16: - if (do_unroll) - jump_uop = uop_CMP_JLE_DEST(ir, IREG_flags_op1_W, IREG_flags_op2_W); - else - jump_uop = uop_CMP_JNLE_DEST(ir, IREG_flags_op1_W, IREG_flags_op2_W); - break; - case FLAGS_SUB32: case FLAGS_DEC32: - if (do_unroll) - jump_uop = uop_CMP_JLE_DEST(ir, IREG_flags_op1, IREG_flags_op2); - else - jump_uop = uop_CMP_JNLE_DEST(ir, IREG_flags_op1, IREG_flags_op2); - break; + switch (codegen_flags_changed ? cpu_state.flags_op : FLAGS_UNKNOWN) { + case FLAGS_SUB8: + case FLAGS_DEC8: + if (do_unroll) + jump_uop = uop_CMP_JNLE_DEST(ir, IREG_flags_op1_B, IREG_flags_op2_B); + else + jump_uop = uop_CMP_JLE_DEST(ir, IREG_flags_op1_B, IREG_flags_op2_B); + break; + case FLAGS_SUB16: + case FLAGS_DEC16: + if (do_unroll) + jump_uop = uop_CMP_JNLE_DEST(ir, IREG_flags_op1_W, IREG_flags_op2_W); + else + jump_uop = uop_CMP_JLE_DEST(ir, IREG_flags_op1_W, IREG_flags_op2_W); + break; + case FLAGS_SUB32: + case FLAGS_DEC32: + if (do_unroll) + jump_uop = uop_CMP_JNLE_DEST(ir, IREG_flags_op1, IREG_flags_op2); + else + jump_uop = uop_CMP_JLE_DEST(ir, IREG_flags_op1, IREG_flags_op2); + break; - case FLAGS_UNKNOWN: - default: - if (do_unroll) - { - uop_CALL_FUNC_RESULT(ir, IREG_temp0, ZF_SET); - jump_uop2 = uop_CMP_IMM_JNZ_DEST(ir, IREG_temp0, 0); - uop_CALL_FUNC_RESULT(ir, IREG_temp0, NF_SET_01); - uop_CALL_FUNC_RESULT(ir, IREG_temp1, VF_SET_01); - jump_uop = uop_CMP_JNZ_DEST(ir, IREG_temp0, IREG_temp1); - } - else - { - uop_CALL_FUNC_RESULT(ir, IREG_temp0, ZF_SET); - jump_uop2 = uop_CMP_IMM_JNZ_DEST(ir, IREG_temp0, 0); - uop_CALL_FUNC_RESULT(ir, IREG_temp0, NF_SET_01); - uop_CALL_FUNC_RESULT(ir, IREG_temp1, VF_SET_01); - jump_uop = uop_CMP_JZ_DEST(ir, IREG_temp0, IREG_temp1); - } - break; - } - if (do_unroll) - { - uop_MOV_IMM(ir, IREG_pc, next_pc); - uop_JMP(ir, codegen_exit_rout); - uop_set_jump_dest(ir, jump_uop); - if (jump_uop2 != -1) - uop_set_jump_dest(ir, jump_uop2); - return 1; - } - else - { - if (jump_uop2 != -1) - uop_set_jump_dest(ir, jump_uop2); - uop_MOV_IMM(ir, IREG_pc, dest_addr); - uop_JMP(ir, codegen_exit_rout); - uop_set_jump_dest(ir, jump_uop); - return 0; - } -} -static int ropJNLE_common(codeblock_t *block, ir_data_t *ir, uint32_t dest_addr, uint32_t next_pc) -{ - int jump_uop, jump_uop2 = -1; - int do_unroll = ((NF_SET() ? 1 : 0) == (VF_SET() ? 1 : 0) && !ZF_SET() && codegen_can_unroll(block, ir, next_pc, dest_addr)); - - switch (codegen_flags_changed ? cpu_state.flags_op : FLAGS_UNKNOWN) - { - case FLAGS_SUB8: case FLAGS_DEC8: - if (do_unroll) - jump_uop = uop_CMP_JNLE_DEST(ir, IREG_flags_op1_B, IREG_flags_op2_B); - else - jump_uop = uop_CMP_JLE_DEST(ir, IREG_flags_op1_B, IREG_flags_op2_B); - break; - case FLAGS_SUB16: case FLAGS_DEC16: - if (do_unroll) - jump_uop = uop_CMP_JNLE_DEST(ir, IREG_flags_op1_W, IREG_flags_op2_W); - else - jump_uop = uop_CMP_JLE_DEST(ir, IREG_flags_op1_W, IREG_flags_op2_W); - break; - case FLAGS_SUB32: case FLAGS_DEC32: - if (do_unroll) - jump_uop = uop_CMP_JNLE_DEST(ir, IREG_flags_op1, IREG_flags_op2); - else - jump_uop = uop_CMP_JLE_DEST(ir, IREG_flags_op1, IREG_flags_op2); - break; - - case FLAGS_UNKNOWN: - default: - if (do_unroll) - { - uop_CALL_FUNC_RESULT(ir, IREG_temp0, ZF_SET); - jump_uop2 = uop_CMP_IMM_JNZ_DEST(ir, IREG_temp0, 0); - uop_CALL_FUNC_RESULT(ir, IREG_temp0, NF_SET_01); - uop_CALL_FUNC_RESULT(ir, IREG_temp1, VF_SET_01); - jump_uop = uop_CMP_JZ_DEST(ir, IREG_temp0, IREG_temp1); - } - else - { - uop_CALL_FUNC_RESULT(ir, IREG_temp0, ZF_SET); - jump_uop2 = uop_CMP_IMM_JNZ_DEST(ir, IREG_temp0, 0); - uop_CALL_FUNC_RESULT(ir, IREG_temp0, NF_SET_01); - uop_CALL_FUNC_RESULT(ir, IREG_temp1, VF_SET_01); - jump_uop = uop_CMP_JNZ_DEST(ir, IREG_temp0, IREG_temp1); - } - break; - } - if (do_unroll) - { - if (jump_uop2 != -1) - uop_set_jump_dest(ir, jump_uop2); - uop_MOV_IMM(ir, IREG_pc, next_pc); - uop_JMP(ir, codegen_exit_rout); - uop_set_jump_dest(ir, jump_uop); - return 1; - } - else - { - uop_MOV_IMM(ir, IREG_pc, dest_addr); - uop_JMP(ir, codegen_exit_rout); - uop_set_jump_dest(ir, jump_uop); - if (jump_uop2 != -1) - uop_set_jump_dest(ir, jump_uop2); - return 0; - } + case FLAGS_UNKNOWN: + default: + if (do_unroll) { + uop_CALL_FUNC_RESULT(ir, IREG_temp0, ZF_SET); + jump_uop2 = uop_CMP_IMM_JNZ_DEST(ir, IREG_temp0, 0); + uop_CALL_FUNC_RESULT(ir, IREG_temp0, NF_SET_01); + uop_CALL_FUNC_RESULT(ir, IREG_temp1, VF_SET_01); + jump_uop = uop_CMP_JZ_DEST(ir, IREG_temp0, IREG_temp1); + } else { + uop_CALL_FUNC_RESULT(ir, IREG_temp0, ZF_SET); + jump_uop2 = uop_CMP_IMM_JNZ_DEST(ir, IREG_temp0, 0); + uop_CALL_FUNC_RESULT(ir, IREG_temp0, NF_SET_01); + uop_CALL_FUNC_RESULT(ir, IREG_temp1, VF_SET_01); + jump_uop = uop_CMP_JNZ_DEST(ir, IREG_temp0, IREG_temp1); + } + break; + } + if (do_unroll) { + if (jump_uop2 != -1) + uop_set_jump_dest(ir, jump_uop2); + uop_MOV_IMM(ir, IREG_pc, next_pc); + uop_JMP(ir, codegen_exit_rout); + uop_set_jump_dest(ir, jump_uop); + return 1; + } else { + uop_MOV_IMM(ir, IREG_pc, dest_addr); + uop_JMP(ir, codegen_exit_rout); + uop_set_jump_dest(ir, jump_uop); + if (jump_uop2 != -1) + uop_set_jump_dest(ir, jump_uop2); + return 0; + } } -#define ropJ(cond) \ -uint32_t ropJ ## cond ## _8(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) \ -{ \ - uint32_t offset = (int32_t)(int8_t)fastreadb(cs + op_pc); \ - uint32_t dest_addr = op_pc + 1 + offset; \ - int ret; \ - \ - if (!(op_32 & 0x100)) \ - dest_addr &= 0xffff; \ - ret = ropJ ## cond ## _common(block, ir, dest_addr, op_pc+1); \ - \ - codegen_mark_code_present(block, cs+op_pc, 1); \ - return ret ? dest_addr : (op_pc+1); \ -} \ -uint32_t ropJ ## cond ## _16(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) \ -{ \ - uint32_t offset = (int32_t)(int16_t)fastreadw(cs + op_pc); \ - uint32_t dest_addr = (op_pc + 2 + offset) & 0xffff; \ - int ret; \ - \ - ret = ropJ ## cond ## _common(block, ir, dest_addr, op_pc+2); \ - \ - codegen_mark_code_present(block, cs+op_pc, 2); \ - return ret ? dest_addr : (op_pc+2); \ -} \ -uint32_t ropJ ## cond ## _32(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) \ -{ \ - uint32_t offset = fastreadl(cs + op_pc); \ - uint32_t dest_addr = op_pc + 4 + offset; \ - int ret; \ - \ - ret = ropJ ## cond ## _common(block, ir, dest_addr, op_pc+4); \ - \ - codegen_mark_code_present(block, cs+op_pc, 4); \ - return ret ? dest_addr : (op_pc+4); \ -} +#define ropJ(cond) \ + uint32_t ropJ##cond##_8(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) \ + { \ + uint32_t offset = (int32_t) (int8_t) fastreadb(cs + op_pc); \ + uint32_t dest_addr = op_pc + 1 + offset; \ + int ret; \ + \ + if (!(op_32 & 0x100)) \ + dest_addr &= 0xffff; \ + ret = ropJ##cond##_common(block, ir, dest_addr, op_pc + 1); \ + \ + codegen_mark_code_present(block, cs + op_pc, 1); \ + return ret ? dest_addr : (op_pc + 1); \ + } \ + uint32_t ropJ##cond##_16(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) \ + { \ + uint32_t offset = (int32_t) (int16_t) fastreadw(cs + op_pc); \ + uint32_t dest_addr = (op_pc + 2 + offset) & 0xffff; \ + int ret; \ + \ + ret = ropJ##cond##_common(block, ir, dest_addr, op_pc + 2); \ + \ + codegen_mark_code_present(block, cs + op_pc, 2); \ + return ret ? dest_addr : (op_pc + 2); \ + } \ + uint32_t ropJ##cond##_32(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) \ + { \ + uint32_t offset = fastreadl(cs + op_pc); \ + uint32_t dest_addr = op_pc + 4 + offset; \ + int ret; \ + \ + ret = ropJ##cond##_common(block, ir, dest_addr, op_pc + 4); \ + \ + codegen_mark_code_present(block, cs + op_pc, 4); \ + return ret ? dest_addr : (op_pc + 4); \ + } ropJ(O) ropJ(NO) @@ -868,147 +869,131 @@ ropJ(NL) ropJ(LE) ropJ(NLE) - -uint32_t ropJCXZ(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) +uint32_t +ropJCXZ(codeblock_t *block, ir_data_t *ir, UNUSED(uint8_t opcode), uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) { - uint32_t offset = (int32_t)(int8_t)fastreadb(cs + op_pc); - uint32_t dest_addr = op_pc + 1 + offset; - int jump_uop; + uint32_t offset = (int32_t) (int8_t) fastreadb(cs + op_pc); + uint32_t dest_addr = op_pc + 1 + offset; + int jump_uop; - if (!(op_32 & 0x100)) - dest_addr &= 0xffff; + if (!(op_32 & 0x100)) + dest_addr &= 0xffff; - if (op_32 & 0x200) - jump_uop = uop_CMP_IMM_JNZ_DEST(ir, IREG_ECX, 0); - else - jump_uop = uop_CMP_IMM_JNZ_DEST(ir, IREG_CX, 0); - uop_MOV_IMM(ir, IREG_pc, dest_addr); - uop_JMP(ir, codegen_exit_rout); - uop_set_jump_dest(ir, jump_uop); + if (op_32 & 0x200) + jump_uop = uop_CMP_IMM_JNZ_DEST(ir, IREG_ECX, 0); + else + jump_uop = uop_CMP_IMM_JNZ_DEST(ir, IREG_CX, 0); + uop_MOV_IMM(ir, IREG_pc, dest_addr); + uop_JMP(ir, codegen_exit_rout); + uop_set_jump_dest(ir, jump_uop); - codegen_mark_code_present(block, cs+op_pc, 1); - return op_pc+1; + codegen_mark_code_present(block, cs + op_pc, 1); + return op_pc + 1; } -uint32_t ropLOOP(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) +uint32_t +ropLOOP(codeblock_t *block, ir_data_t *ir, UNUSED(uint8_t opcode), uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) { - uint32_t offset = (int32_t)(int8_t)fastreadb(cs + op_pc); - uint32_t dest_addr = op_pc + 1 + offset; - uint32_t ret_addr; - int jump_uop; + uint32_t offset = (int32_t) (int8_t) fastreadb(cs + op_pc); + uint32_t dest_addr = op_pc + 1 + offset; + uint32_t ret_addr; + int jump_uop; - if (!(op_32 & 0x100)) - dest_addr &= 0xffff; + if (!(op_32 & 0x100)) + dest_addr &= 0xffff; - if (((op_32 & 0x200) ? ECX : CX) != 1 && codegen_can_unroll(block, ir, op_pc+1, dest_addr)) - { - if (op_32 & 0x200) - { - uop_SUB_IMM(ir, IREG_ECX, IREG_ECX, 1); - jump_uop = uop_CMP_IMM_JNZ_DEST(ir, IREG_ECX, 0); - } - else - { - uop_SUB_IMM(ir, IREG_CX, IREG_CX, 1); - jump_uop = uop_CMP_IMM_JNZ_DEST(ir, IREG_CX, 0); - } - uop_MOV_IMM(ir, IREG_pc, op_pc+1); - ret_addr = dest_addr; - CPU_BLOCK_END(); + if (((op_32 & 0x200) ? ECX : CX) != 1 && codegen_can_unroll(block, ir, op_pc + 1, dest_addr)) { + if (op_32 & 0x200) { + uop_SUB_IMM(ir, IREG_ECX, IREG_ECX, 1); + jump_uop = uop_CMP_IMM_JNZ_DEST(ir, IREG_ECX, 0); + } else { + uop_SUB_IMM(ir, IREG_CX, IREG_CX, 1); + jump_uop = uop_CMP_IMM_JNZ_DEST(ir, IREG_CX, 0); } - else - { - if (op_32 & 0x200) - { - uop_SUB_IMM(ir, IREG_ECX, IREG_ECX, 1); - jump_uop = uop_CMP_IMM_JZ_DEST(ir, IREG_ECX, 0); - } - else - { - uop_SUB_IMM(ir, IREG_CX, IREG_CX, 1); - jump_uop = uop_CMP_IMM_JZ_DEST(ir, IREG_CX, 0); - } - uop_MOV_IMM(ir, IREG_pc, dest_addr); - ret_addr = op_pc+1; - } - uop_JMP(ir, codegen_exit_rout); - uop_set_jump_dest(ir, jump_uop); - - codegen_mark_code_present(block, cs+op_pc, 1); - return ret_addr; -} - -uint32_t ropLOOPE(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) -{ - uint32_t offset = (int32_t)(int8_t)fastreadb(cs + op_pc); - uint32_t dest_addr = op_pc + 1 + offset; - int jump_uop, jump_uop2; - - if (!(op_32 & 0x100)) - dest_addr &= 0xffff; - - if (op_32 & 0x200) - { - uop_SUB_IMM(ir, IREG_ECX, IREG_ECX, 1); - jump_uop = uop_CMP_IMM_JZ_DEST(ir, IREG_ECX, 0); - } - else - { - uop_SUB_IMM(ir, IREG_CX, IREG_CX, 1); - jump_uop = uop_CMP_IMM_JZ_DEST(ir, IREG_CX, 0); - } - if (!codegen_flags_changed || !flags_res_valid()) - { - uop_CALL_FUNC_RESULT(ir, IREG_temp0, ZF_SET); - jump_uop2 = uop_CMP_IMM_JZ_DEST(ir, IREG_temp0, 0); - } - else - { - jump_uop2 = uop_CMP_IMM_JNZ_DEST(ir, IREG_flags_res, 0); + uop_MOV_IMM(ir, IREG_pc, op_pc + 1); + ret_addr = dest_addr; + CPU_BLOCK_END(); + } else { + if (op_32 & 0x200) { + uop_SUB_IMM(ir, IREG_ECX, IREG_ECX, 1); + jump_uop = uop_CMP_IMM_JZ_DEST(ir, IREG_ECX, 0); + } else { + uop_SUB_IMM(ir, IREG_CX, IREG_CX, 1); + jump_uop = uop_CMP_IMM_JZ_DEST(ir, IREG_CX, 0); } uop_MOV_IMM(ir, IREG_pc, dest_addr); - uop_JMP(ir, codegen_exit_rout); - uop_NOP_BARRIER(ir); - uop_set_jump_dest(ir, jump_uop); - uop_set_jump_dest(ir, jump_uop2); + ret_addr = op_pc + 1; + } + uop_JMP(ir, codegen_exit_rout); + uop_set_jump_dest(ir, jump_uop); - codegen_mark_code_present(block, cs+op_pc, 1); - return op_pc+1; + codegen_mark_code_present(block, cs + op_pc, 1); + return ret_addr; } -uint32_t ropLOOPNE(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) + +uint32_t +ropLOOPE(codeblock_t *block, ir_data_t *ir, UNUSED(uint8_t opcode), uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) { - uint32_t offset = (int32_t)(int8_t)fastreadb(cs + op_pc); - uint32_t dest_addr = op_pc + 1 + offset; - int jump_uop, jump_uop2; + uint32_t offset = (int32_t) (int8_t) fastreadb(cs + op_pc); + uint32_t dest_addr = op_pc + 1 + offset; + int jump_uop; + int jump_uop2; - if (!(op_32 & 0x100)) - dest_addr &= 0xffff; + if (!(op_32 & 0x100)) + dest_addr &= 0xffff; - if (op_32 & 0x200) - { - uop_SUB_IMM(ir, IREG_ECX, IREG_ECX, 1); - jump_uop = uop_CMP_IMM_JZ_DEST(ir, IREG_ECX, 0); - } - else - { - uop_SUB_IMM(ir, IREG_CX, IREG_CX, 1); - jump_uop = uop_CMP_IMM_JZ_DEST(ir, IREG_CX, 0); - } - if (!codegen_flags_changed || !flags_res_valid()) - { - uop_CALL_FUNC_RESULT(ir, IREG_temp0, ZF_SET); - jump_uop2 = uop_CMP_IMM_JNZ_DEST(ir, IREG_temp0, 0); - } - else - { - jump_uop2 = uop_CMP_IMM_JZ_DEST(ir, IREG_flags_res, 0); - } - uop_MOV_IMM(ir, IREG_pc, dest_addr); - uop_JMP(ir, codegen_exit_rout); - uop_NOP_BARRIER(ir); - uop_set_jump_dest(ir, jump_uop); - uop_set_jump_dest(ir, jump_uop2); + if (op_32 & 0x200) { + uop_SUB_IMM(ir, IREG_ECX, IREG_ECX, 1); + jump_uop = uop_CMP_IMM_JZ_DEST(ir, IREG_ECX, 0); + } else { + uop_SUB_IMM(ir, IREG_CX, IREG_CX, 1); + jump_uop = uop_CMP_IMM_JZ_DEST(ir, IREG_CX, 0); + } + if (!codegen_flags_changed || !flags_res_valid()) { + uop_CALL_FUNC_RESULT(ir, IREG_temp0, ZF_SET); + jump_uop2 = uop_CMP_IMM_JZ_DEST(ir, IREG_temp0, 0); + } else { + jump_uop2 = uop_CMP_IMM_JNZ_DEST(ir, IREG_flags_res, 0); + } + uop_MOV_IMM(ir, IREG_pc, dest_addr); + uop_JMP(ir, codegen_exit_rout); + uop_NOP_BARRIER(ir); + uop_set_jump_dest(ir, jump_uop); + uop_set_jump_dest(ir, jump_uop2); - codegen_mark_code_present(block, cs+op_pc, 1); - return op_pc+1; + codegen_mark_code_present(block, cs + op_pc, 1); + return op_pc + 1; +} +uint32_t +ropLOOPNE(codeblock_t *block, ir_data_t *ir, UNUSED(uint8_t opcode), uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) +{ + uint32_t offset = (int32_t) (int8_t) fastreadb(cs + op_pc); + uint32_t dest_addr = op_pc + 1 + offset; + int jump_uop; + int jump_uop2; + + if (!(op_32 & 0x100)) + dest_addr &= 0xffff; + + if (op_32 & 0x200) { + uop_SUB_IMM(ir, IREG_ECX, IREG_ECX, 1); + jump_uop = uop_CMP_IMM_JZ_DEST(ir, IREG_ECX, 0); + } else { + uop_SUB_IMM(ir, IREG_CX, IREG_CX, 1); + jump_uop = uop_CMP_IMM_JZ_DEST(ir, IREG_CX, 0); + } + if (!codegen_flags_changed || !flags_res_valid()) { + uop_CALL_FUNC_RESULT(ir, IREG_temp0, ZF_SET); + jump_uop2 = uop_CMP_IMM_JNZ_DEST(ir, IREG_temp0, 0); + } else { + jump_uop2 = uop_CMP_IMM_JZ_DEST(ir, IREG_flags_res, 0); + } + uop_MOV_IMM(ir, IREG_pc, dest_addr); + uop_JMP(ir, codegen_exit_rout); + uop_NOP_BARRIER(ir); + uop_set_jump_dest(ir, jump_uop); + uop_set_jump_dest(ir, jump_uop2); + + codegen_mark_code_present(block, cs + op_pc, 1); + return op_pc + 1; } diff --git a/src/codegen_new/codegen_ops_fpu_arith.c b/src/codegen_new/codegen_ops_fpu_arith.c index d4ba9aebb..3ab7be8ac 100644 --- a/src/codegen_new/codegen_ops_fpu_arith.c +++ b/src/codegen_new/codegen_ops_fpu_arith.c @@ -2,9 +2,12 @@ #include <86box/86box.h> #include "cpu.h" #include <86box/mem.h> +#include <86box/plat_unused.h> #include "x86.h" #include "x86_flags.h" +#include "x86seg_common.h" +#include "x86seg.h" #include "386_common.h" #include "x87.h" #include "codegen.h" @@ -14,562 +17,591 @@ #include "codegen_ops_fpu_arith.h" #include "codegen_ops_helpers.h" -uint32_t ropFADD(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) +uint32_t +ropFADD(UNUSED(codeblock_t *block), ir_data_t *ir, UNUSED(uint8_t opcode), uint32_t fetchdat, UNUSED(uint32_t op_32), uint32_t op_pc) { - int src_reg = fetchdat & 7; + int src_reg = fetchdat & 7; - uop_FP_ENTER(ir); - uop_FADD(ir, IREG_ST(0), IREG_ST(0), IREG_ST(src_reg)); - uop_MOV_IMM(ir, IREG_tag(0), TAG_VALID); - - return op_pc; + uop_FP_ENTER(ir); + uop_FADD(ir, IREG_ST(0), IREG_ST(0), IREG_ST(src_reg)); + uop_MOV_IMM(ir, IREG_tag(0), TAG_VALID); + + return op_pc; } -uint32_t ropFADDr(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) +uint32_t +ropFADDr(UNUSED(codeblock_t *block), ir_data_t *ir, UNUSED(uint8_t opcode), uint32_t fetchdat, UNUSED(uint32_t op_32), uint32_t op_pc) { - int dest_reg = fetchdat & 7; + int dest_reg = fetchdat & 7; - uop_FP_ENTER(ir); - uop_FADD(ir, IREG_ST(dest_reg), IREG_ST(dest_reg), IREG_ST(0)); - uop_MOV_IMM(ir, IREG_tag(dest_reg), TAG_VALID); + uop_FP_ENTER(ir); + uop_FADD(ir, IREG_ST(dest_reg), IREG_ST(dest_reg), IREG_ST(0)); + uop_MOV_IMM(ir, IREG_tag(dest_reg), TAG_VALID); - return op_pc; + return op_pc; } -uint32_t ropFADDP(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) +uint32_t +ropFADDP(codeblock_t *block, ir_data_t *ir, UNUSED(uint8_t opcode), uint32_t fetchdat, UNUSED(uint32_t op_32), uint32_t op_pc) { - int dest_reg = fetchdat & 7; + int dest_reg = fetchdat & 7; - uop_FP_ENTER(ir); - uop_FADD(ir, IREG_ST(dest_reg), IREG_ST(dest_reg), IREG_ST(0)); - uop_MOV_IMM(ir, IREG_tag(dest_reg), TAG_VALID); - fpu_POP(block, ir); - - return op_pc; + uop_FP_ENTER(ir); + uop_FADD(ir, IREG_ST(dest_reg), IREG_ST(dest_reg), IREG_ST(0)); + uop_MOV_IMM(ir, IREG_tag(dest_reg), TAG_VALID); + fpu_POP(block, ir); + + return op_pc; } -uint32_t ropFCOM(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) +uint32_t +ropFCOM(UNUSED(codeblock_t *block), ir_data_t *ir, UNUSED(uint8_t opcode), uint32_t fetchdat, UNUSED(uint32_t op_32), uint32_t op_pc) { - int src_reg = fetchdat & 7; + int src_reg = fetchdat & 7; - uop_FP_ENTER(ir); - uop_FCOM(ir, IREG_temp0_W, IREG_ST(0), IREG_ST(src_reg)); - uop_AND_IMM(ir, IREG_NPXS, IREG_NPXS, ~(C0|C2|C3)); - uop_OR(ir, IREG_NPXS, IREG_NPXS, IREG_temp0_W); + uop_FP_ENTER(ir); + uop_FCOM(ir, IREG_temp0_W, IREG_ST(0), IREG_ST(src_reg)); + uop_AND_IMM(ir, IREG_NPXS, IREG_NPXS, ~(C0 | C2 | C3)); + uop_OR(ir, IREG_NPXS, IREG_NPXS, IREG_temp0_W); - return op_pc; + return op_pc; } -uint32_t ropFCOMP(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) +uint32_t +ropFCOMP(codeblock_t *block, ir_data_t *ir, UNUSED(uint8_t opcode), uint32_t fetchdat, UNUSED(uint32_t op_32), uint32_t op_pc) { - int src_reg = fetchdat & 7; + int src_reg = fetchdat & 7; - uop_FP_ENTER(ir); - uop_FCOM(ir, IREG_temp0_W, IREG_ST(0), IREG_ST(src_reg)); - uop_AND_IMM(ir, IREG_NPXS, IREG_NPXS, ~(C0|C2|C3)); - uop_OR(ir, IREG_NPXS, IREG_NPXS, IREG_temp0_W); - fpu_POP(block, ir); + uop_FP_ENTER(ir); + uop_FCOM(ir, IREG_temp0_W, IREG_ST(0), IREG_ST(src_reg)); + uop_AND_IMM(ir, IREG_NPXS, IREG_NPXS, ~(C0 | C2 | C3)); + uop_OR(ir, IREG_NPXS, IREG_NPXS, IREG_temp0_W); + fpu_POP(block, ir); - return op_pc; + return op_pc; } -uint32_t ropFCOMPP(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) +uint32_t +ropFCOMPP(codeblock_t *block, ir_data_t *ir, UNUSED(uint8_t opcode), uint32_t fetchdat, UNUSED(uint32_t op_32), uint32_t op_pc) { - uop_FP_ENTER(ir); - uop_FCOM(ir, IREG_temp0_W, IREG_ST(0), IREG_ST(1)); - uop_AND_IMM(ir, IREG_NPXS, IREG_NPXS, ~(C0|C2|C3)); - uop_OR(ir, IREG_NPXS, IREG_NPXS, IREG_temp0_W); - fpu_POP2(block, ir); + uop_FP_ENTER(ir); + uop_FCOM(ir, IREG_temp0_W, IREG_ST(0), IREG_ST(1)); + uop_AND_IMM(ir, IREG_NPXS, IREG_NPXS, ~(C0 | C2 | C3)); + uop_OR(ir, IREG_NPXS, IREG_NPXS, IREG_temp0_W); + fpu_POP2(block, ir); - return op_pc; + return op_pc; } -uint32_t ropFDIV(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) +uint32_t +ropFDIV(UNUSED(codeblock_t *block), ir_data_t *ir, UNUSED(uint8_t opcode), uint32_t fetchdat, UNUSED(uint32_t op_32), uint32_t op_pc) { - int src_reg = fetchdat & 7; + int src_reg = fetchdat & 7; - uop_FP_ENTER(ir); - uop_FDIV(ir, IREG_ST(0), IREG_ST(0), IREG_ST(src_reg)); - uop_MOV_IMM(ir, IREG_tag(0), TAG_VALID); + uop_FP_ENTER(ir); + uop_FDIV(ir, IREG_ST(0), IREG_ST(0), IREG_ST(src_reg)); + uop_MOV_IMM(ir, IREG_tag(0), TAG_VALID); - return op_pc; + return op_pc; } -uint32_t ropFDIVR(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) +uint32_t +ropFDIVR(UNUSED(codeblock_t *block), ir_data_t *ir, UNUSED(uint8_t opcode), uint32_t fetchdat, UNUSED(uint32_t op_32), uint32_t op_pc) { - int src_reg = fetchdat & 7; + int src_reg = fetchdat & 7; - uop_FP_ENTER(ir); - uop_FDIV(ir, IREG_ST(0), IREG_ST(src_reg), IREG_ST(0)); - uop_MOV_IMM(ir, IREG_tag(0), TAG_VALID); + uop_FP_ENTER(ir); + uop_FDIV(ir, IREG_ST(0), IREG_ST(src_reg), IREG_ST(0)); + uop_MOV_IMM(ir, IREG_tag(0), TAG_VALID); - return op_pc; + return op_pc; } -uint32_t ropFDIVr(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) +uint32_t +ropFDIVr(UNUSED(codeblock_t *block), ir_data_t *ir, UNUSED(uint8_t opcode), uint32_t fetchdat, UNUSED(uint32_t op_32), uint32_t op_pc) { - int dest_reg = fetchdat & 7; + int dest_reg = fetchdat & 7; - uop_FP_ENTER(ir); - uop_FDIV(ir, IREG_ST(dest_reg), IREG_ST(dest_reg), IREG_ST(0)); - uop_MOV_IMM(ir, IREG_tag(dest_reg), TAG_VALID); + uop_FP_ENTER(ir); + uop_FDIV(ir, IREG_ST(dest_reg), IREG_ST(dest_reg), IREG_ST(0)); + uop_MOV_IMM(ir, IREG_tag(dest_reg), TAG_VALID); - return op_pc; + return op_pc; } -uint32_t ropFDIVRr(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) +uint32_t +ropFDIVRr(UNUSED(codeblock_t *block), ir_data_t *ir, UNUSED(uint8_t opcode), uint32_t fetchdat, UNUSED(uint32_t op_32), uint32_t op_pc) { - int dest_reg = fetchdat & 7; + int dest_reg = fetchdat & 7; - uop_FP_ENTER(ir); - uop_FDIV(ir, IREG_ST(dest_reg), IREG_ST(0), IREG_ST(dest_reg)); - uop_MOV_IMM(ir, IREG_tag(dest_reg), TAG_VALID); + uop_FP_ENTER(ir); + uop_FDIV(ir, IREG_ST(dest_reg), IREG_ST(0), IREG_ST(dest_reg)); + uop_MOV_IMM(ir, IREG_tag(dest_reg), TAG_VALID); - return op_pc; + return op_pc; } -uint32_t ropFDIVP(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) +uint32_t +ropFDIVP(codeblock_t *block, ir_data_t *ir, UNUSED(uint8_t opcode), uint32_t fetchdat, UNUSED(uint32_t op_32), uint32_t op_pc) { - int dest_reg = fetchdat & 7; + int dest_reg = fetchdat & 7; - uop_FP_ENTER(ir); - uop_FDIV(ir, IREG_ST(dest_reg), IREG_ST(dest_reg), IREG_ST(0)); - uop_MOV_IMM(ir, IREG_tag(dest_reg), TAG_VALID); - fpu_POP(block, ir); - - return op_pc; + uop_FP_ENTER(ir); + uop_FDIV(ir, IREG_ST(dest_reg), IREG_ST(dest_reg), IREG_ST(0)); + uop_MOV_IMM(ir, IREG_tag(dest_reg), TAG_VALID); + fpu_POP(block, ir); + + return op_pc; } -uint32_t ropFDIVRP(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) +uint32_t +ropFDIVRP(codeblock_t *block, ir_data_t *ir, UNUSED(uint8_t opcode), uint32_t fetchdat, UNUSED(uint32_t op_32), uint32_t op_pc) { - int dest_reg = fetchdat & 7; + int dest_reg = fetchdat & 7; - uop_FP_ENTER(ir); - uop_FDIV(ir, IREG_ST(dest_reg), IREG_ST(0), IREG_ST(dest_reg)); - uop_MOV_IMM(ir, IREG_tag(dest_reg), TAG_VALID); - fpu_POP(block, ir); + uop_FP_ENTER(ir); + uop_FDIV(ir, IREG_ST(dest_reg), IREG_ST(0), IREG_ST(dest_reg)); + uop_MOV_IMM(ir, IREG_tag(dest_reg), TAG_VALID); + fpu_POP(block, ir); - return op_pc; + return op_pc; } -uint32_t ropFMUL(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) +uint32_t +ropFMUL(UNUSED(codeblock_t *block), ir_data_t *ir, UNUSED(uint8_t opcode), uint32_t fetchdat, UNUSED(uint32_t op_32), uint32_t op_pc) { - int src_reg = fetchdat & 7; + int src_reg = fetchdat & 7; - uop_FP_ENTER(ir); - uop_FMUL(ir, IREG_ST(0), IREG_ST(0), IREG_ST(src_reg)); - uop_MOV_IMM(ir, IREG_tag(0), TAG_VALID); + uop_FP_ENTER(ir); + uop_FMUL(ir, IREG_ST(0), IREG_ST(0), IREG_ST(src_reg)); + uop_MOV_IMM(ir, IREG_tag(0), TAG_VALID); - return op_pc; + return op_pc; } -uint32_t ropFMULr(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) +uint32_t +ropFMULr(UNUSED(codeblock_t *block), ir_data_t *ir, UNUSED(uint8_t opcode), uint32_t fetchdat, UNUSED(uint32_t op_32), uint32_t op_pc) { - int dest_reg = fetchdat & 7; + int dest_reg = fetchdat & 7; - uop_FP_ENTER(ir); - uop_FMUL(ir, IREG_ST(dest_reg), IREG_ST(dest_reg), IREG_ST(0)); - uop_MOV_IMM(ir, IREG_tag(dest_reg), TAG_VALID); + uop_FP_ENTER(ir); + uop_FMUL(ir, IREG_ST(dest_reg), IREG_ST(dest_reg), IREG_ST(0)); + uop_MOV_IMM(ir, IREG_tag(dest_reg), TAG_VALID); - return op_pc; + return op_pc; } -uint32_t ropFMULP(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) +uint32_t +ropFMULP(codeblock_t *block, ir_data_t *ir, UNUSED(uint8_t opcode), uint32_t fetchdat, UNUSED(uint32_t op_32), uint32_t op_pc) { - int dest_reg = fetchdat & 7; + int dest_reg = fetchdat & 7; - uop_FP_ENTER(ir); - uop_FMUL(ir, IREG_ST(dest_reg), IREG_ST(dest_reg), IREG_ST(0)); - uop_MOV_IMM(ir, IREG_tag(dest_reg), TAG_VALID); - fpu_POP(block, ir); + uop_FP_ENTER(ir); + uop_FMUL(ir, IREG_ST(dest_reg), IREG_ST(dest_reg), IREG_ST(0)); + uop_MOV_IMM(ir, IREG_tag(dest_reg), TAG_VALID); + fpu_POP(block, ir); - return op_pc; + return op_pc; } -uint32_t ropFSUB(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) +uint32_t +ropFSUB(UNUSED(codeblock_t *block), ir_data_t *ir, UNUSED(uint8_t opcode), uint32_t fetchdat, UNUSED(uint32_t op_32), uint32_t op_pc) { - int src_reg = fetchdat & 7; + int src_reg = fetchdat & 7; - uop_FP_ENTER(ir); - uop_FSUB(ir, IREG_ST(0), IREG_ST(0), IREG_ST(src_reg)); - uop_MOV_IMM(ir, IREG_tag(0), TAG_VALID); + uop_FP_ENTER(ir); + uop_FSUB(ir, IREG_ST(0), IREG_ST(0), IREG_ST(src_reg)); + uop_MOV_IMM(ir, IREG_tag(0), TAG_VALID); - return op_pc; + return op_pc; } -uint32_t ropFSUBR(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) +uint32_t +ropFSUBR(UNUSED(codeblock_t *block), ir_data_t *ir, UNUSED(uint8_t opcode), uint32_t fetchdat, UNUSED(uint32_t op_32), uint32_t op_pc) { - int src_reg = fetchdat & 7; + int src_reg = fetchdat & 7; - uop_FP_ENTER(ir); - uop_FSUB(ir, IREG_ST(0), IREG_ST(src_reg), IREG_ST(0)); - uop_MOV_IMM(ir, IREG_tag(0), TAG_VALID); + uop_FP_ENTER(ir); + uop_FSUB(ir, IREG_ST(0), IREG_ST(src_reg), IREG_ST(0)); + uop_MOV_IMM(ir, IREG_tag(0), TAG_VALID); - return op_pc; + return op_pc; } -uint32_t ropFSUBr(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) +uint32_t +ropFSUBr(UNUSED(codeblock_t *block), ir_data_t *ir, UNUSED(uint8_t opcode), uint32_t fetchdat, UNUSED(uint32_t op_32), uint32_t op_pc) { - int dest_reg = fetchdat & 7; + int dest_reg = fetchdat & 7; - uop_FP_ENTER(ir); - uop_FSUB(ir, IREG_ST(dest_reg), IREG_ST(dest_reg), IREG_ST(0)); - uop_MOV_IMM(ir, IREG_tag(dest_reg), TAG_VALID); + uop_FP_ENTER(ir); + uop_FSUB(ir, IREG_ST(dest_reg), IREG_ST(dest_reg), IREG_ST(0)); + uop_MOV_IMM(ir, IREG_tag(dest_reg), TAG_VALID); - return op_pc; + return op_pc; } -uint32_t ropFSUBRr(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) +uint32_t +ropFSUBRr(UNUSED(codeblock_t *block), ir_data_t *ir, UNUSED(uint8_t opcode), uint32_t fetchdat, UNUSED(uint32_t op_32), uint32_t op_pc) { - int dest_reg = fetchdat & 7; + int dest_reg = fetchdat & 7; - uop_FP_ENTER(ir); - uop_FSUB(ir, IREG_ST(dest_reg), IREG_ST(0), IREG_ST(dest_reg)); - uop_MOV_IMM(ir, IREG_tag(dest_reg), TAG_VALID); + uop_FP_ENTER(ir); + uop_FSUB(ir, IREG_ST(dest_reg), IREG_ST(0), IREG_ST(dest_reg)); + uop_MOV_IMM(ir, IREG_tag(dest_reg), TAG_VALID); - return op_pc; + return op_pc; } -uint32_t ropFSUBP(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) +uint32_t +ropFSUBP(codeblock_t *block, ir_data_t *ir, UNUSED(uint8_t opcode), uint32_t fetchdat, UNUSED(uint32_t op_32), uint32_t op_pc) { - int dest_reg = fetchdat & 7; + int dest_reg = fetchdat & 7; - uop_FP_ENTER(ir); - uop_FSUB(ir, IREG_ST(dest_reg), IREG_ST(dest_reg), IREG_ST(0)); - uop_MOV_IMM(ir, IREG_tag(dest_reg), TAG_VALID); - fpu_POP(block, ir); + uop_FP_ENTER(ir); + uop_FSUB(ir, IREG_ST(dest_reg), IREG_ST(dest_reg), IREG_ST(0)); + uop_MOV_IMM(ir, IREG_tag(dest_reg), TAG_VALID); + fpu_POP(block, ir); - return op_pc; + return op_pc; } -uint32_t ropFSUBRP(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) +uint32_t +ropFSUBRP(codeblock_t *block, ir_data_t *ir, UNUSED(uint8_t opcode), uint32_t fetchdat, UNUSED(uint32_t op_32), uint32_t op_pc) { - int dest_reg = fetchdat & 7; + int dest_reg = fetchdat & 7; - uop_FP_ENTER(ir); - uop_FSUB(ir, IREG_ST(dest_reg), IREG_ST(0), IREG_ST(dest_reg)); - uop_MOV_IMM(ir, IREG_tag(dest_reg), TAG_VALID); - fpu_POP(block, ir); - - return op_pc; + uop_FP_ENTER(ir); + uop_FSUB(ir, IREG_ST(dest_reg), IREG_ST(0), IREG_ST(dest_reg)); + uop_MOV_IMM(ir, IREG_tag(dest_reg), TAG_VALID); + fpu_POP(block, ir); + + return op_pc; } -uint32_t ropFUCOM(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) +uint32_t +ropFUCOM(UNUSED(codeblock_t *block), ir_data_t *ir, UNUSED(uint8_t opcode), uint32_t fetchdat, UNUSED(uint32_t op_32), uint32_t op_pc) { - int src_reg = fetchdat & 7; + int src_reg = fetchdat & 7; - uop_FP_ENTER(ir); - uop_FCOM(ir, IREG_temp0_W, IREG_ST(0), IREG_ST(src_reg)); - uop_AND_IMM(ir, IREG_NPXS, IREG_NPXS, ~(C0|C2|C3)); - uop_OR(ir, IREG_NPXS, IREG_NPXS, IREG_temp0_W); + uop_FP_ENTER(ir); + uop_FCOM(ir, IREG_temp0_W, IREG_ST(0), IREG_ST(src_reg)); + uop_AND_IMM(ir, IREG_NPXS, IREG_NPXS, ~(C0 | C2 | C3)); + uop_OR(ir, IREG_NPXS, IREG_NPXS, IREG_temp0_W); - return op_pc; + return op_pc; } -uint32_t ropFUCOMP(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) +uint32_t +ropFUCOMP(codeblock_t *block, ir_data_t *ir, UNUSED(uint8_t opcode), uint32_t fetchdat, UNUSED(uint32_t op_32), uint32_t op_pc) { - int src_reg = fetchdat & 7; + int src_reg = fetchdat & 7; - uop_FP_ENTER(ir); - uop_FCOM(ir, IREG_temp0_W, IREG_ST(0), IREG_ST(src_reg)); - uop_AND_IMM(ir, IREG_NPXS, IREG_NPXS, ~(C0|C2|C3)); - uop_OR(ir, IREG_NPXS, IREG_NPXS, IREG_temp0_W); - fpu_POP(block, ir); + uop_FP_ENTER(ir); + uop_FCOM(ir, IREG_temp0_W, IREG_ST(0), IREG_ST(src_reg)); + uop_AND_IMM(ir, IREG_NPXS, IREG_NPXS, ~(C0 | C2 | C3)); + uop_OR(ir, IREG_NPXS, IREG_NPXS, IREG_temp0_W); + fpu_POP(block, ir); - return op_pc; + return op_pc; } -uint32_t ropFUCOMPP(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) +uint32_t +ropFUCOMPP(codeblock_t *block, ir_data_t *ir, UNUSED(uint8_t opcode), uint32_t fetchdat, UNUSED(uint32_t op_32), uint32_t op_pc) { - uop_FP_ENTER(ir); - uop_FCOM(ir, IREG_temp0_W, IREG_ST(0), IREG_ST(1)); - uop_AND_IMM(ir, IREG_NPXS, IREG_NPXS, ~(C0|C2|C3)); - uop_OR(ir, IREG_NPXS, IREG_NPXS, IREG_temp0_W); - fpu_POP2(block, ir); + uop_FP_ENTER(ir); + uop_FCOM(ir, IREG_temp0_W, IREG_ST(0), IREG_ST(1)); + uop_AND_IMM(ir, IREG_NPXS, IREG_NPXS, ~(C0 | C2 | C3)); + uop_OR(ir, IREG_NPXS, IREG_NPXS, IREG_temp0_W); + fpu_POP2(block, ir); - return op_pc; + return op_pc; } -#define ropF_arith_mem(name, load_uop) \ -uint32_t ropFADD ## name(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) \ -{ \ - x86seg *target_seg; \ - \ - if ((cpu_state.npxc >> 10) & 3) \ - return 0; \ - uop_FP_ENTER(ir); \ - uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc); \ - op_pc--; \ - target_seg = codegen_generate_ea(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32, 0); \ - codegen_check_seg_read(block, ir, target_seg); \ - load_uop(ir, IREG_temp0_D, ireg_seg_base(target_seg), IREG_eaaddr); \ - uop_FADD(ir, IREG_ST(0), IREG_ST(0), IREG_temp0_D); \ - uop_MOV_IMM(ir, IREG_tag(0), TAG_VALID); \ - \ - return op_pc+1; \ -} \ -uint32_t ropFCOM ## name(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) \ -{ \ - x86seg *target_seg; \ - \ - uop_FP_ENTER(ir); \ - uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc); \ - op_pc--; \ - target_seg = codegen_generate_ea(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32, 0); \ - codegen_check_seg_read(block, ir, target_seg); \ - load_uop(ir, IREG_temp0_D, ireg_seg_base(target_seg), IREG_eaaddr); \ - uop_FCOM(ir, IREG_temp1_W, IREG_ST(0), IREG_temp0_D); \ - uop_AND_IMM(ir, IREG_NPXS, IREG_NPXS, ~(C0|C2|C3)); \ - uop_OR(ir, IREG_NPXS, IREG_NPXS, IREG_temp1_W); \ - \ - return op_pc+1; \ -} \ -uint32_t ropFCOMP ## name(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) \ -{ \ - x86seg *target_seg; \ - \ - uop_FP_ENTER(ir); \ - uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc); \ - op_pc--; \ - target_seg = codegen_generate_ea(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32, 0); \ - codegen_check_seg_read(block, ir, target_seg); \ - load_uop(ir, IREG_temp0_D, ireg_seg_base(target_seg), IREG_eaaddr); \ - uop_FCOM(ir, IREG_temp1_W, IREG_ST(0), IREG_temp0_D); \ - uop_AND_IMM(ir, IREG_NPXS, IREG_NPXS, ~(C0|C2|C3)); \ - uop_OR(ir, IREG_NPXS, IREG_NPXS, IREG_temp1_W); \ - fpu_POP(block, ir); \ - \ - return op_pc+1; \ -} \ -uint32_t ropFDIV ## name(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) \ -{ \ - x86seg *target_seg; \ - \ - uop_FP_ENTER(ir); \ - uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc); \ - op_pc--; \ - target_seg = codegen_generate_ea(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32, 0); \ - codegen_check_seg_read(block, ir, target_seg); \ - load_uop(ir, IREG_temp0_D, ireg_seg_base(target_seg), IREG_eaaddr); \ - uop_FDIV(ir, IREG_ST(0), IREG_ST(0), IREG_temp0_D); \ - uop_MOV_IMM(ir, IREG_tag(0), TAG_VALID); \ - \ - return op_pc+1; \ -} \ -uint32_t ropFDIVR ## name(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) \ -{ \ - x86seg *target_seg; \ - \ - uop_FP_ENTER(ir); \ - uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc); \ - op_pc--; \ - target_seg = codegen_generate_ea(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32, 0); \ - codegen_check_seg_read(block, ir, target_seg); \ - load_uop(ir, IREG_temp0_D, ireg_seg_base(target_seg), IREG_eaaddr); \ - uop_FDIV(ir, IREG_ST(0), IREG_temp0_D, IREG_ST(0)); \ - uop_MOV_IMM(ir, IREG_tag(0), TAG_VALID); \ - \ - return op_pc+1; \ -} \ -uint32_t ropFMUL ## name(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) \ -{ \ - x86seg *target_seg; \ - \ - uop_FP_ENTER(ir); \ - uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc); \ - op_pc--; \ - target_seg = codegen_generate_ea(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32, 0); \ - codegen_check_seg_read(block, ir, target_seg); \ - load_uop(ir, IREG_temp0_D, ireg_seg_base(target_seg), IREG_eaaddr); \ - uop_FMUL(ir, IREG_ST(0), IREG_ST(0), IREG_temp0_D); \ - uop_MOV_IMM(ir, IREG_tag(0), TAG_VALID); \ - \ - return op_pc+1; \ -} \ -uint32_t ropFSUB ## name(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) \ -{ \ - x86seg *target_seg; \ - \ - uop_FP_ENTER(ir); \ - uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc); \ - op_pc--; \ - target_seg = codegen_generate_ea(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32, 0); \ - codegen_check_seg_read(block, ir, target_seg); \ - load_uop(ir, IREG_temp0_D, ireg_seg_base(target_seg), IREG_eaaddr); \ - uop_FSUB(ir, IREG_ST(0), IREG_ST(0), IREG_temp0_D); \ - uop_MOV_IMM(ir, IREG_tag(0), TAG_VALID); \ - \ - return op_pc+1; \ -} \ -uint32_t ropFSUBR ## name(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) \ -{ \ - x86seg *target_seg; \ - \ - uop_FP_ENTER(ir); \ - uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc); \ - op_pc--; \ - target_seg = codegen_generate_ea(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32, 0); \ - codegen_check_seg_read(block, ir, target_seg); \ - load_uop(ir, IREG_temp0_D, ireg_seg_base(target_seg), IREG_eaaddr); \ - uop_FSUB(ir, IREG_ST(0), IREG_temp0_D, IREG_ST(0)); \ - uop_MOV_IMM(ir, IREG_tag(0), TAG_VALID); \ - \ - return op_pc+1; \ -} +#define ropF_arith_mem(name, load_uop) \ + uint32_t ropFADD##name(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) \ + { \ + x86seg *target_seg; \ + \ + if ((cpu_state.npxc >> 10) & 3) \ + return 0; \ + uop_FP_ENTER(ir); \ + uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc); \ + op_pc--; \ + target_seg = codegen_generate_ea(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32, 0); \ + codegen_check_seg_read(block, ir, target_seg); \ + load_uop(ir, IREG_temp0_D, ireg_seg_base(target_seg), IREG_eaaddr); \ + uop_FADD(ir, IREG_ST(0), IREG_ST(0), IREG_temp0_D); \ + uop_MOV_IMM(ir, IREG_tag(0), TAG_VALID); \ + \ + return op_pc + 1; \ + } \ + uint32_t ropFCOM##name(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) \ + { \ + x86seg *target_seg; \ + \ + uop_FP_ENTER(ir); \ + uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc); \ + op_pc--; \ + target_seg = codegen_generate_ea(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32, 0); \ + codegen_check_seg_read(block, ir, target_seg); \ + load_uop(ir, IREG_temp0_D, ireg_seg_base(target_seg), IREG_eaaddr); \ + uop_FCOM(ir, IREG_temp1_W, IREG_ST(0), IREG_temp0_D); \ + uop_AND_IMM(ir, IREG_NPXS, IREG_NPXS, ~(C0 | C2 | C3)); \ + uop_OR(ir, IREG_NPXS, IREG_NPXS, IREG_temp1_W); \ + \ + return op_pc + 1; \ + } \ + uint32_t ropFCOMP##name(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) \ + { \ + x86seg *target_seg; \ + \ + uop_FP_ENTER(ir); \ + uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc); \ + op_pc--; \ + target_seg = codegen_generate_ea(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32, 0); \ + codegen_check_seg_read(block, ir, target_seg); \ + load_uop(ir, IREG_temp0_D, ireg_seg_base(target_seg), IREG_eaaddr); \ + uop_FCOM(ir, IREG_temp1_W, IREG_ST(0), IREG_temp0_D); \ + uop_AND_IMM(ir, IREG_NPXS, IREG_NPXS, ~(C0 | C2 | C3)); \ + uop_OR(ir, IREG_NPXS, IREG_NPXS, IREG_temp1_W); \ + fpu_POP(block, ir); \ + \ + return op_pc + 1; \ + } \ + uint32_t ropFDIV##name(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) \ + { \ + x86seg *target_seg; \ + \ + uop_FP_ENTER(ir); \ + uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc); \ + op_pc--; \ + target_seg = codegen_generate_ea(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32, 0); \ + codegen_check_seg_read(block, ir, target_seg); \ + load_uop(ir, IREG_temp0_D, ireg_seg_base(target_seg), IREG_eaaddr); \ + uop_FDIV(ir, IREG_ST(0), IREG_ST(0), IREG_temp0_D); \ + uop_MOV_IMM(ir, IREG_tag(0), TAG_VALID); \ + \ + return op_pc + 1; \ + } \ + uint32_t ropFDIVR##name(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) \ + { \ + x86seg *target_seg; \ + \ + uop_FP_ENTER(ir); \ + uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc); \ + op_pc--; \ + target_seg = codegen_generate_ea(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32, 0); \ + codegen_check_seg_read(block, ir, target_seg); \ + load_uop(ir, IREG_temp0_D, ireg_seg_base(target_seg), IREG_eaaddr); \ + uop_FDIV(ir, IREG_ST(0), IREG_temp0_D, IREG_ST(0)); \ + uop_MOV_IMM(ir, IREG_tag(0), TAG_VALID); \ + \ + return op_pc + 1; \ + } \ + uint32_t ropFMUL##name(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) \ + { \ + x86seg *target_seg; \ + \ + uop_FP_ENTER(ir); \ + uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc); \ + op_pc--; \ + target_seg = codegen_generate_ea(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32, 0); \ + codegen_check_seg_read(block, ir, target_seg); \ + load_uop(ir, IREG_temp0_D, ireg_seg_base(target_seg), IREG_eaaddr); \ + uop_FMUL(ir, IREG_ST(0), IREG_ST(0), IREG_temp0_D); \ + uop_MOV_IMM(ir, IREG_tag(0), TAG_VALID); \ + \ + return op_pc + 1; \ + } \ + uint32_t ropFSUB##name(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) \ + { \ + x86seg *target_seg; \ + \ + uop_FP_ENTER(ir); \ + uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc); \ + op_pc--; \ + target_seg = codegen_generate_ea(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32, 0); \ + codegen_check_seg_read(block, ir, target_seg); \ + load_uop(ir, IREG_temp0_D, ireg_seg_base(target_seg), IREG_eaaddr); \ + uop_FSUB(ir, IREG_ST(0), IREG_ST(0), IREG_temp0_D); \ + uop_MOV_IMM(ir, IREG_tag(0), TAG_VALID); \ + \ + return op_pc + 1; \ + } \ + uint32_t ropFSUBR##name(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) \ + { \ + x86seg *target_seg; \ + \ + uop_FP_ENTER(ir); \ + uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc); \ + op_pc--; \ + target_seg = codegen_generate_ea(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32, 0); \ + codegen_check_seg_read(block, ir, target_seg); \ + load_uop(ir, IREG_temp0_D, ireg_seg_base(target_seg), IREG_eaaddr); \ + uop_FSUB(ir, IREG_ST(0), IREG_temp0_D, IREG_ST(0)); \ + uop_MOV_IMM(ir, IREG_tag(0), TAG_VALID); \ + \ + return op_pc + 1; \ + } +// clang-format off ropF_arith_mem(s, uop_MEM_LOAD_SINGLE) ropF_arith_mem(d, uop_MEM_LOAD_DOUBLE) +// clang-format on -#define ropFI_arith_mem(name, temp_reg) \ -uint32_t ropFIADD ## name(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) \ -{ \ - x86seg *target_seg; \ - \ - uop_FP_ENTER(ir); \ - uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc); \ - op_pc--; \ - target_seg = codegen_generate_ea(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32, 0); \ - codegen_check_seg_read(block, ir, target_seg); \ - uop_MEM_LOAD_REG(ir, temp_reg, ireg_seg_base(target_seg), IREG_eaaddr); \ - uop_MOV_DOUBLE_INT(ir, IREG_temp0_D, temp_reg); \ - uop_FADD(ir, IREG_ST(0), IREG_ST(0), IREG_temp0_D); \ - uop_MOV_IMM(ir, IREG_tag(0), TAG_VALID); \ - \ - return op_pc+1; \ -} \ -uint32_t ropFICOM ## name(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) \ -{ \ - x86seg *target_seg; \ - \ - uop_FP_ENTER(ir); \ - uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc); \ - op_pc--; \ - target_seg = codegen_generate_ea(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32, 0); \ - codegen_check_seg_read(block, ir, target_seg); \ - uop_MEM_LOAD_REG(ir, temp_reg, ireg_seg_base(target_seg), IREG_eaaddr); \ - uop_MOV_DOUBLE_INT(ir, IREG_temp0_D, temp_reg); \ - uop_FCOM(ir, IREG_temp1_W, IREG_ST(0), IREG_temp0_D); \ - uop_AND_IMM(ir, IREG_NPXS, IREG_NPXS, ~(C0|C2|C3)); \ - uop_OR(ir, IREG_NPXS, IREG_NPXS, IREG_temp1_W); \ - \ - return op_pc+1; \ -} \ -uint32_t ropFICOMP ## name(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) \ -{ \ - x86seg *target_seg; \ - \ - uop_FP_ENTER(ir); \ - uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc); \ - op_pc--; \ - target_seg = codegen_generate_ea(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32, 0); \ - codegen_check_seg_read(block, ir, target_seg); \ - uop_MEM_LOAD_REG(ir, temp_reg, ireg_seg_base(target_seg), IREG_eaaddr); \ - uop_MOV_DOUBLE_INT(ir, IREG_temp0_D, temp_reg); \ - uop_FCOM(ir, IREG_temp1_W, IREG_ST(0), IREG_temp0_D); \ - uop_AND_IMM(ir, IREG_NPXS, IREG_NPXS, ~(C0|C2|C3)); \ - uop_OR(ir, IREG_NPXS, IREG_NPXS, IREG_temp1_W); \ - fpu_POP(block, ir); \ - \ - return op_pc+1; \ -} \ -uint32_t ropFIDIV ## name(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) \ -{ \ - x86seg *target_seg; \ - \ - uop_FP_ENTER(ir); \ - uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc); \ - op_pc--; \ - target_seg = codegen_generate_ea(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32, 0); \ - codegen_check_seg_read(block, ir, target_seg); \ - uop_MEM_LOAD_REG(ir, temp_reg, ireg_seg_base(target_seg), IREG_eaaddr); \ - uop_MOV_DOUBLE_INT(ir, IREG_temp0_D, temp_reg); \ - uop_FDIV(ir, IREG_ST(0), IREG_ST(0), IREG_temp0_D); \ - uop_MOV_IMM(ir, IREG_tag(0), TAG_VALID); \ - \ - return op_pc+1; \ -} \ -uint32_t ropFIDIVR ## name(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc)\ -{ \ - x86seg *target_seg; \ - \ - uop_FP_ENTER(ir); \ - uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc); \ - op_pc--; \ - target_seg = codegen_generate_ea(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32, 0); \ - codegen_check_seg_read(block, ir, target_seg); \ - uop_MEM_LOAD_REG(ir, temp_reg, ireg_seg_base(target_seg), IREG_eaaddr); \ - uop_MOV_DOUBLE_INT(ir, IREG_temp0_D, temp_reg); \ - uop_FDIV(ir, IREG_ST(0), IREG_temp0_D, IREG_ST(0)); \ - uop_MOV_IMM(ir, IREG_tag(0), TAG_VALID); \ - \ - return op_pc+1; \ -} \ -uint32_t ropFIMUL ## name(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) \ -{ \ - x86seg *target_seg; \ - \ - uop_FP_ENTER(ir); \ - uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc); \ - op_pc--; \ - target_seg = codegen_generate_ea(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32, 0); \ - codegen_check_seg_read(block, ir, target_seg); \ - uop_MEM_LOAD_REG(ir, temp_reg, ireg_seg_base(target_seg), IREG_eaaddr); \ - uop_MOV_DOUBLE_INT(ir, IREG_temp0_D, temp_reg); \ - uop_FMUL(ir, IREG_ST(0), IREG_ST(0), IREG_temp0_D); \ - uop_MOV_IMM(ir, IREG_tag(0), TAG_VALID); \ - \ - return op_pc+1; \ -} \ -uint32_t ropFISUB ## name(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) \ -{ \ - x86seg *target_seg; \ - \ - uop_FP_ENTER(ir); \ - uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc); \ - op_pc--; \ - target_seg = codegen_generate_ea(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32, 0); \ - codegen_check_seg_read(block, ir, target_seg); \ - uop_MEM_LOAD_REG(ir, temp_reg, ireg_seg_base(target_seg), IREG_eaaddr); \ - uop_MOV_DOUBLE_INT(ir, IREG_temp0_D, temp_reg); \ - uop_FSUB(ir, IREG_ST(0), IREG_ST(0), IREG_temp0_D); \ - uop_MOV_IMM(ir, IREG_tag(0), TAG_VALID); \ - \ - return op_pc+1; \ -} \ -uint32_t ropFISUBR ## name(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc)\ -{ \ - x86seg *target_seg; \ - \ - uop_FP_ENTER(ir); \ - uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc); \ - op_pc--; \ - target_seg = codegen_generate_ea(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32, 0); \ - codegen_check_seg_read(block, ir, target_seg); \ - uop_MEM_LOAD_REG(ir, temp_reg, ireg_seg_base(target_seg), IREG_eaaddr); \ - uop_MOV_DOUBLE_INT(ir, IREG_temp0_D, temp_reg); \ - uop_FSUB(ir, IREG_ST(0), IREG_temp0_D, IREG_ST(0)); \ - uop_MOV_IMM(ir, IREG_tag(0), TAG_VALID); \ - \ - return op_pc+1; \ -} +#define ropFI_arith_mem(name, temp_reg) \ + uint32_t ropFIADD##name(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) \ + { \ + x86seg *target_seg; \ + \ + uop_FP_ENTER(ir); \ + uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc); \ + op_pc--; \ + target_seg = codegen_generate_ea(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32, 0); \ + codegen_check_seg_read(block, ir, target_seg); \ + uop_MEM_LOAD_REG(ir, temp_reg, ireg_seg_base(target_seg), IREG_eaaddr); \ + uop_MOV_DOUBLE_INT(ir, IREG_temp0_D, temp_reg); \ + uop_FADD(ir, IREG_ST(0), IREG_ST(0), IREG_temp0_D); \ + uop_MOV_IMM(ir, IREG_tag(0), TAG_VALID); \ + \ + return op_pc + 1; \ + } \ + uint32_t ropFICOM##name(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) \ + { \ + x86seg *target_seg; \ + \ + uop_FP_ENTER(ir); \ + uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc); \ + op_pc--; \ + target_seg = codegen_generate_ea(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32, 0); \ + codegen_check_seg_read(block, ir, target_seg); \ + uop_MEM_LOAD_REG(ir, temp_reg, ireg_seg_base(target_seg), IREG_eaaddr); \ + uop_MOV_DOUBLE_INT(ir, IREG_temp0_D, temp_reg); \ + uop_FCOM(ir, IREG_temp1_W, IREG_ST(0), IREG_temp0_D); \ + uop_AND_IMM(ir, IREG_NPXS, IREG_NPXS, ~(C0 | C2 | C3)); \ + uop_OR(ir, IREG_NPXS, IREG_NPXS, IREG_temp1_W); \ + \ + return op_pc + 1; \ + } \ + uint32_t ropFICOMP##name(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) \ + { \ + x86seg *target_seg; \ + \ + uop_FP_ENTER(ir); \ + uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc); \ + op_pc--; \ + target_seg = codegen_generate_ea(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32, 0); \ + codegen_check_seg_read(block, ir, target_seg); \ + uop_MEM_LOAD_REG(ir, temp_reg, ireg_seg_base(target_seg), IREG_eaaddr); \ + uop_MOV_DOUBLE_INT(ir, IREG_temp0_D, temp_reg); \ + uop_FCOM(ir, IREG_temp1_W, IREG_ST(0), IREG_temp0_D); \ + uop_AND_IMM(ir, IREG_NPXS, IREG_NPXS, ~(C0 | C2 | C3)); \ + uop_OR(ir, IREG_NPXS, IREG_NPXS, IREG_temp1_W); \ + fpu_POP(block, ir); \ + \ + return op_pc + 1; \ + } \ + uint32_t ropFIDIV##name(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) \ + { \ + x86seg *target_seg; \ + \ + uop_FP_ENTER(ir); \ + uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc); \ + op_pc--; \ + target_seg = codegen_generate_ea(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32, 0); \ + codegen_check_seg_read(block, ir, target_seg); \ + uop_MEM_LOAD_REG(ir, temp_reg, ireg_seg_base(target_seg), IREG_eaaddr); \ + uop_MOV_DOUBLE_INT(ir, IREG_temp0_D, temp_reg); \ + uop_FDIV(ir, IREG_ST(0), IREG_ST(0), IREG_temp0_D); \ + uop_MOV_IMM(ir, IREG_tag(0), TAG_VALID); \ + \ + return op_pc + 1; \ + } \ + uint32_t ropFIDIVR##name(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) \ + { \ + x86seg *target_seg; \ + \ + uop_FP_ENTER(ir); \ + uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc); \ + op_pc--; \ + target_seg = codegen_generate_ea(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32, 0); \ + codegen_check_seg_read(block, ir, target_seg); \ + uop_MEM_LOAD_REG(ir, temp_reg, ireg_seg_base(target_seg), IREG_eaaddr); \ + uop_MOV_DOUBLE_INT(ir, IREG_temp0_D, temp_reg); \ + uop_FDIV(ir, IREG_ST(0), IREG_temp0_D, IREG_ST(0)); \ + uop_MOV_IMM(ir, IREG_tag(0), TAG_VALID); \ + \ + return op_pc + 1; \ + } \ + uint32_t ropFIMUL##name(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) \ + { \ + x86seg *target_seg; \ + \ + uop_FP_ENTER(ir); \ + uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc); \ + op_pc--; \ + target_seg = codegen_generate_ea(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32, 0); \ + codegen_check_seg_read(block, ir, target_seg); \ + uop_MEM_LOAD_REG(ir, temp_reg, ireg_seg_base(target_seg), IREG_eaaddr); \ + uop_MOV_DOUBLE_INT(ir, IREG_temp0_D, temp_reg); \ + uop_FMUL(ir, IREG_ST(0), IREG_ST(0), IREG_temp0_D); \ + uop_MOV_IMM(ir, IREG_tag(0), TAG_VALID); \ + \ + return op_pc + 1; \ + } \ + uint32_t ropFISUB##name(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) \ + { \ + x86seg *target_seg; \ + \ + uop_FP_ENTER(ir); \ + uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc); \ + op_pc--; \ + target_seg = codegen_generate_ea(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32, 0); \ + codegen_check_seg_read(block, ir, target_seg); \ + uop_MEM_LOAD_REG(ir, temp_reg, ireg_seg_base(target_seg), IREG_eaaddr); \ + uop_MOV_DOUBLE_INT(ir, IREG_temp0_D, temp_reg); \ + uop_FSUB(ir, IREG_ST(0), IREG_ST(0), IREG_temp0_D); \ + uop_MOV_IMM(ir, IREG_tag(0), TAG_VALID); \ + \ + return op_pc + 1; \ + } \ + uint32_t ropFISUBR##name(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) \ + { \ + x86seg *target_seg; \ + \ + uop_FP_ENTER(ir); \ + uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc); \ + op_pc--; \ + target_seg = codegen_generate_ea(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32, 0); \ + codegen_check_seg_read(block, ir, target_seg); \ + uop_MEM_LOAD_REG(ir, temp_reg, ireg_seg_base(target_seg), IREG_eaaddr); \ + uop_MOV_DOUBLE_INT(ir, IREG_temp0_D, temp_reg); \ + uop_FSUB(ir, IREG_ST(0), IREG_temp0_D, IREG_ST(0)); \ + uop_MOV_IMM(ir, IREG_tag(0), TAG_VALID); \ + \ + return op_pc + 1; \ + } ropFI_arith_mem(l, IREG_temp0) ropFI_arith_mem(w, IREG_temp0_W) - -uint32_t ropFABS(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) +uint32_t +ropFABS(UNUSED(codeblock_t *block), ir_data_t *ir, UNUSED(uint8_t opcode), uint32_t fetchdat, UNUSED(uint32_t op_32), uint32_t op_pc) { - uop_FP_ENTER(ir); - uop_FABS(ir, IREG_ST(0), IREG_ST(0)); - uop_MOV_IMM(ir, IREG_tag(0), TAG_VALID); + uop_FP_ENTER(ir); + uop_FABS(ir, IREG_ST(0), IREG_ST(0)); + uop_MOV_IMM(ir, IREG_tag(0), TAG_VALID); - return op_pc; + return op_pc; } -uint32_t ropFCHS(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) +uint32_t +ropFCHS(UNUSED(codeblock_t *block), ir_data_t *ir, UNUSED(uint8_t opcode), uint32_t fetchdat, UNUSED(uint32_t op_32), uint32_t op_pc) { - uop_FP_ENTER(ir); - uop_FCHS(ir, IREG_ST(0), IREG_ST(0)); - uop_MOV_IMM(ir, IREG_tag(0), TAG_VALID); + uop_FP_ENTER(ir); + uop_FCHS(ir, IREG_ST(0), IREG_ST(0)); + uop_MOV_IMM(ir, IREG_tag(0), TAG_VALID); - return op_pc; + return op_pc; } -uint32_t ropFSQRT(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) +uint32_t +ropFSQRT(UNUSED(codeblock_t *block), ir_data_t *ir, UNUSED(uint8_t opcode), uint32_t fetchdat, UNUSED(uint32_t op_32), uint32_t op_pc) { - uop_FP_ENTER(ir); - uop_FSQRT(ir, IREG_ST(0), IREG_ST(0)); - uop_MOV_IMM(ir, IREG_tag(0), TAG_VALID); + uop_FP_ENTER(ir); + uop_FSQRT(ir, IREG_ST(0), IREG_ST(0)); + uop_MOV_IMM(ir, IREG_tag(0), TAG_VALID); - return op_pc; + return op_pc; } -uint32_t ropFTST(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) +uint32_t +ropFTST(UNUSED(codeblock_t *block), ir_data_t *ir, UNUSED(uint8_t opcode), uint32_t fetchdat, UNUSED(uint32_t op_32), uint32_t op_pc) { - uop_FP_ENTER(ir); - uop_FTST(ir, IREG_temp0_W, IREG_ST(0)); - uop_AND_IMM(ir, IREG_NPXS, IREG_NPXS, ~(C0|C2|C3)); - uop_OR(ir, IREG_NPXS, IREG_NPXS, IREG_temp0_W); + uop_FP_ENTER(ir); + uop_FTST(ir, IREG_temp0_W, IREG_ST(0)); + uop_AND_IMM(ir, IREG_NPXS, IREG_NPXS, ~(C0 | C2 | C3)); + uop_OR(ir, IREG_NPXS, IREG_NPXS, IREG_temp0_W); - return op_pc; + return op_pc; } diff --git a/src/codegen_new/codegen_ops_fpu_constant.c b/src/codegen_new/codegen_ops_fpu_constant.c index a9888f9b3..862845868 100644 --- a/src/codegen_new/codegen_ops_fpu_constant.c +++ b/src/codegen_new/codegen_ops_fpu_constant.c @@ -2,9 +2,12 @@ #include <86box/86box.h> #include "cpu.h" #include <86box/mem.h> +#include <86box/plat_unused.h> #include "x86.h" #include "x86_flags.h" +#include "x86seg_common.h" +#include "x86seg.h" #include "386_common.h" #include "x87.h" #include "codegen.h" @@ -14,23 +17,25 @@ #include "codegen_ops_fpu_constant.h" #include "codegen_ops_helpers.h" -uint32_t ropFLD1(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) +uint32_t +ropFLD1(codeblock_t *block, ir_data_t *ir, UNUSED(uint8_t opcode), uint32_t fetchdat, UNUSED(uint32_t op_32), uint32_t op_pc) { - uop_FP_ENTER(ir); - uop_MOV_IMM(ir, IREG_temp0, 1); - uop_MOV_DOUBLE_INT(ir, IREG_ST(-1), IREG_temp0); - uop_MOV_IMM(ir, IREG_tag(-1), TAG_VALID); - fpu_PUSH(block, ir); + uop_FP_ENTER(ir); + uop_MOV_IMM(ir, IREG_temp0, 1); + uop_MOV_DOUBLE_INT(ir, IREG_ST(-1), IREG_temp0); + uop_MOV_IMM(ir, IREG_tag(-1), TAG_VALID); + fpu_PUSH(block, ir); - return op_pc; + return op_pc; } -uint32_t ropFLDZ(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) +uint32_t +ropFLDZ(codeblock_t *block, ir_data_t *ir, UNUSED(uint8_t opcode), uint32_t fetchdat, UNUSED(uint32_t op_32), uint32_t op_pc) { - uop_FP_ENTER(ir); - uop_MOV_IMM(ir, IREG_temp0, 0); - uop_MOV_DOUBLE_INT(ir, IREG_ST(-1), IREG_temp0); - uop_MOV_IMM(ir, IREG_tag(-1), TAG_VALID); - fpu_PUSH(block, ir); - - return op_pc; + uop_FP_ENTER(ir); + uop_MOV_IMM(ir, IREG_temp0, 0); + uop_MOV_DOUBLE_INT(ir, IREG_ST(-1), IREG_temp0); + uop_MOV_IMM(ir, IREG_tag(-1), TAG_VALID); + fpu_PUSH(block, ir); + + return op_pc; } diff --git a/src/codegen_new/codegen_ops_fpu_loadstore.c b/src/codegen_new/codegen_ops_fpu_loadstore.c index 349d10de7..7635063e8 100644 --- a/src/codegen_new/codegen_ops_fpu_loadstore.c +++ b/src/codegen_new/codegen_ops_fpu_loadstore.c @@ -2,9 +2,12 @@ #include <86box/86box.h> #include "cpu.h" #include <86box/mem.h> +#include <86box/plat_unused.h> #include "x86.h" #include "x86_flags.h" +#include "x86seg_common.h" +#include "x86seg.h" #include "386_common.h" #include "x87.h" #include "codegen.h" @@ -14,221 +17,234 @@ #include "codegen_ops_fpu_arith.h" #include "codegen_ops_helpers.h" -uint32_t ropFLDs(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) +uint32_t +ropFLDs(codeblock_t *block, ir_data_t *ir, UNUSED(uint8_t opcode), uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) { - x86seg *target_seg; + x86seg *target_seg; - uop_FP_ENTER(ir); - uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc); - op_pc--; - target_seg = codegen_generate_ea(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32, 0); - codegen_check_seg_read(block, ir, target_seg); - uop_MEM_LOAD_SINGLE(ir, IREG_ST(-1), ireg_seg_base(target_seg), IREG_eaaddr); - uop_MOV_IMM(ir, IREG_tag(-1), TAG_VALID); - fpu_PUSH(block, ir); + uop_FP_ENTER(ir); + uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc); + op_pc--; + target_seg = codegen_generate_ea(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32, 0); + codegen_check_seg_read(block, ir, target_seg); + uop_MEM_LOAD_SINGLE(ir, IREG_ST(-1), ireg_seg_base(target_seg), IREG_eaaddr); + uop_MOV_IMM(ir, IREG_tag(-1), TAG_VALID); + fpu_PUSH(block, ir); - return op_pc+1; + return op_pc + 1; } -uint32_t ropFLDd(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) +uint32_t +ropFLDd(codeblock_t *block, ir_data_t *ir, UNUSED(uint8_t opcode), uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) { - x86seg *target_seg; + x86seg *target_seg; - uop_FP_ENTER(ir); - uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc); - op_pc--; - target_seg = codegen_generate_ea(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32, 0); - codegen_check_seg_read(block, ir, target_seg); - uop_MEM_LOAD_DOUBLE(ir, IREG_ST(-1), ireg_seg_base(target_seg), IREG_eaaddr); - uop_MOV_IMM(ir, IREG_tag(-1), TAG_VALID); - fpu_PUSH(block, ir); + uop_FP_ENTER(ir); + uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc); + op_pc--; + target_seg = codegen_generate_ea(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32, 0); + codegen_check_seg_read(block, ir, target_seg); + uop_MEM_LOAD_DOUBLE(ir, IREG_ST(-1), ireg_seg_base(target_seg), IREG_eaaddr); + uop_MOV_IMM(ir, IREG_tag(-1), TAG_VALID); + fpu_PUSH(block, ir); - return op_pc+1; + return op_pc + 1; } -uint32_t ropFSTs(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) +uint32_t +ropFSTs(codeblock_t *block, ir_data_t *ir, UNUSED(uint8_t opcode), uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) { - x86seg *target_seg; + x86seg *target_seg; - uop_FP_ENTER(ir); - uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc); - op_pc--; - target_seg = codegen_generate_ea(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32, 0); - codegen_check_seg_write(block, ir, target_seg); - uop_MEM_STORE_SINGLE(ir, ireg_seg_base(target_seg), IREG_eaaddr, IREG_ST(0)); + uop_FP_ENTER(ir); + uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc); + op_pc--; + target_seg = codegen_generate_ea(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32, 0); + codegen_check_seg_write(block, ir, target_seg); + uop_MEM_STORE_SINGLE(ir, ireg_seg_base(target_seg), IREG_eaaddr, IREG_ST(0)); - return op_pc+1; + return op_pc + 1; } -uint32_t ropFSTPs(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) +uint32_t +ropFSTPs(codeblock_t *block, ir_data_t *ir, UNUSED(uint8_t opcode), uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) { - x86seg *target_seg; + x86seg *target_seg; - uop_FP_ENTER(ir); - uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc); - op_pc--; - target_seg = codegen_generate_ea(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32, 0); - codegen_check_seg_write(block, ir, target_seg); - uop_MEM_STORE_SINGLE(ir, ireg_seg_base(target_seg), IREG_eaaddr, IREG_ST(0)); - uop_MOV_IMM(ir, IREG_tag(0), TAG_EMPTY); - fpu_POP(block, ir); + uop_FP_ENTER(ir); + uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc); + op_pc--; + target_seg = codegen_generate_ea(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32, 0); + codegen_check_seg_write(block, ir, target_seg); + uop_MEM_STORE_SINGLE(ir, ireg_seg_base(target_seg), IREG_eaaddr, IREG_ST(0)); + uop_MOV_IMM(ir, IREG_tag(0), TAG_EMPTY); + fpu_POP(block, ir); - return op_pc+1; + return op_pc + 1; } -uint32_t ropFSTd(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) +uint32_t +ropFSTd(codeblock_t *block, ir_data_t *ir, UNUSED(uint8_t opcode), uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) { - x86seg *target_seg; + x86seg *target_seg; - uop_FP_ENTER(ir); - uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc); - op_pc--; - target_seg = codegen_generate_ea(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32, 0); - codegen_check_seg_write(block, ir, target_seg); - CHECK_SEG_LIMITS(block, ir, target_seg, IREG_eaaddr, 7); - uop_MEM_STORE_DOUBLE(ir, ireg_seg_base(target_seg), IREG_eaaddr, IREG_ST(0)); + uop_FP_ENTER(ir); + uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc); + op_pc--; + target_seg = codegen_generate_ea(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32, 0); + codegen_check_seg_write(block, ir, target_seg); + CHECK_SEG_LIMITS(block, ir, target_seg, IREG_eaaddr, 7); + uop_MEM_STORE_DOUBLE(ir, ireg_seg_base(target_seg), IREG_eaaddr, IREG_ST(0)); - return op_pc+1; + return op_pc + 1; } -uint32_t ropFSTPd(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) +uint32_t +ropFSTPd(codeblock_t *block, ir_data_t *ir, UNUSED(uint8_t opcode), uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) { - x86seg *target_seg; + x86seg *target_seg; - uop_FP_ENTER(ir); - uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc); - op_pc--; - target_seg = codegen_generate_ea(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32, 0); - codegen_check_seg_write(block, ir, target_seg); - CHECK_SEG_LIMITS(block, ir, target_seg, IREG_eaaddr, 7); - uop_MEM_STORE_DOUBLE(ir, ireg_seg_base(target_seg), IREG_eaaddr, IREG_ST(0)); - uop_MOV_IMM(ir, IREG_tag(0), TAG_EMPTY); - fpu_POP(block, ir); + uop_FP_ENTER(ir); + uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc); + op_pc--; + target_seg = codegen_generate_ea(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32, 0); + codegen_check_seg_write(block, ir, target_seg); + CHECK_SEG_LIMITS(block, ir, target_seg, IREG_eaaddr, 7); + uop_MEM_STORE_DOUBLE(ir, ireg_seg_base(target_seg), IREG_eaaddr, IREG_ST(0)); + uop_MOV_IMM(ir, IREG_tag(0), TAG_EMPTY); + fpu_POP(block, ir); - return op_pc+1; + return op_pc + 1; } - -uint32_t ropFILDw(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) +uint32_t +ropFILDw(codeblock_t *block, ir_data_t *ir, UNUSED(uint8_t opcode), uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) { - x86seg *target_seg; + x86seg *target_seg; - uop_FP_ENTER(ir); - uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc); - op_pc--; - target_seg = codegen_generate_ea(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32, 0); - codegen_check_seg_read(block, ir, target_seg); - uop_MEM_LOAD_REG(ir, IREG_temp0_W, ireg_seg_base(target_seg), IREG_eaaddr); - uop_MOV_DOUBLE_INT(ir, IREG_ST(-1), IREG_temp0_W); - uop_MOV_IMM(ir, IREG_tag(-1), TAG_VALID); - fpu_PUSH(block, ir); + uop_FP_ENTER(ir); + uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc); + op_pc--; + target_seg = codegen_generate_ea(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32, 0); + codegen_check_seg_read(block, ir, target_seg); + uop_MEM_LOAD_REG(ir, IREG_temp0_W, ireg_seg_base(target_seg), IREG_eaaddr); + uop_MOV_DOUBLE_INT(ir, IREG_ST(-1), IREG_temp0_W); + uop_MOV_IMM(ir, IREG_tag(-1), TAG_VALID); + fpu_PUSH(block, ir); - return op_pc+1; + return op_pc + 1; } -uint32_t ropFILDl(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) +uint32_t +ropFILDl(codeblock_t *block, ir_data_t *ir, uint8_t UNUSED(opcode), uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) { - x86seg *target_seg; + x86seg *target_seg; - uop_FP_ENTER(ir); - uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc); - op_pc--; - target_seg = codegen_generate_ea(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32, 0); - codegen_check_seg_read(block, ir, target_seg); - uop_MEM_LOAD_REG(ir, IREG_temp0, ireg_seg_base(target_seg), IREG_eaaddr); - uop_MOV_DOUBLE_INT(ir, IREG_ST(-1), IREG_temp0); - uop_MOV_IMM(ir, IREG_tag(-1), TAG_VALID); - fpu_PUSH(block, ir); + uop_FP_ENTER(ir); + uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc); + op_pc--; + target_seg = codegen_generate_ea(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32, 0); + codegen_check_seg_read(block, ir, target_seg); + uop_MEM_LOAD_REG(ir, IREG_temp0, ireg_seg_base(target_seg), IREG_eaaddr); + uop_MOV_DOUBLE_INT(ir, IREG_ST(-1), IREG_temp0); + uop_MOV_IMM(ir, IREG_tag(-1), TAG_VALID); + fpu_PUSH(block, ir); - return op_pc+1; + return op_pc + 1; } -uint32_t ropFILDq(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) +uint32_t +ropFILDq(codeblock_t *block, ir_data_t *ir, UNUSED(uint8_t opcode), uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) { - x86seg *target_seg; + x86seg *target_seg; - uop_FP_ENTER(ir); - uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc); - op_pc--; - target_seg = codegen_generate_ea(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32, 0); - codegen_check_seg_read(block, ir, target_seg); - uop_MEM_LOAD_REG(ir, IREG_ST_i64(-1), ireg_seg_base(target_seg), IREG_eaaddr); - uop_MOV_DOUBLE_INT(ir, IREG_ST(-1), IREG_ST_i64(-1)); - uop_MOV_IMM(ir, IREG_tag(-1), TAG_VALID | TAG_UINT64); - fpu_PUSH(block, ir); + uop_FP_ENTER(ir); + uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc); + op_pc--; + target_seg = codegen_generate_ea(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32, 0); + codegen_check_seg_read(block, ir, target_seg); + uop_MEM_LOAD_REG(ir, IREG_ST_i64(-1), ireg_seg_base(target_seg), IREG_eaaddr); + uop_MOV_DOUBLE_INT(ir, IREG_ST(-1), IREG_ST_i64(-1)); + uop_MOV_IMM(ir, IREG_tag(-1), TAG_VALID | TAG_UINT64); + fpu_PUSH(block, ir); - return op_pc+1; + return op_pc + 1; } -uint32_t ropFISTw(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) +uint32_t +ropFISTw(codeblock_t *block, ir_data_t *ir, UNUSED(uint8_t opcode), uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) { - x86seg *target_seg; + x86seg *target_seg; - uop_FP_ENTER(ir); - uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc); - op_pc--; - target_seg = codegen_generate_ea(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32, 0); - codegen_check_seg_write(block, ir, target_seg); - uop_MOV_INT_DOUBLE(ir, IREG_temp0_W, IREG_ST(0)); - uop_MEM_STORE_REG(ir, ireg_seg_base(target_seg), IREG_eaaddr, IREG_temp0_W); - uop_MOV_IMM(ir, IREG_tag(0), TAG_EMPTY); + uop_FP_ENTER(ir); + uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc); + op_pc--; + target_seg = codegen_generate_ea(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32, 0); + codegen_check_seg_write(block, ir, target_seg); + uop_MOV_INT_DOUBLE(ir, IREG_temp0_W, IREG_ST(0)); + uop_MEM_STORE_REG(ir, ireg_seg_base(target_seg), IREG_eaaddr, IREG_temp0_W); + uop_MOV_IMM(ir, IREG_tag(0), TAG_EMPTY); - return op_pc+1; + return op_pc + 1; } -uint32_t ropFISTPw(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) +uint32_t +ropFISTPw(codeblock_t *block, ir_data_t *ir, UNUSED(uint8_t opcode), uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) { - x86seg *target_seg; + x86seg *target_seg; - uop_FP_ENTER(ir); - uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc); - op_pc--; - target_seg = codegen_generate_ea(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32, 0); - codegen_check_seg_write(block, ir, target_seg); - uop_MOV_INT_DOUBLE(ir, IREG_temp0_W, IREG_ST(0)); - uop_MEM_STORE_REG(ir, ireg_seg_base(target_seg), IREG_eaaddr, IREG_temp0_W); - uop_MOV_IMM(ir, IREG_tag(0), TAG_EMPTY); - fpu_POP(block, ir); + uop_FP_ENTER(ir); + uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc); + op_pc--; + target_seg = codegen_generate_ea(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32, 0); + codegen_check_seg_write(block, ir, target_seg); + uop_MOV_INT_DOUBLE(ir, IREG_temp0_W, IREG_ST(0)); + uop_MEM_STORE_REG(ir, ireg_seg_base(target_seg), IREG_eaaddr, IREG_temp0_W); + uop_MOV_IMM(ir, IREG_tag(0), TAG_EMPTY); + fpu_POP(block, ir); - return op_pc+1; + return op_pc + 1; } -uint32_t ropFISTl(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) +uint32_t +ropFISTl(codeblock_t *block, ir_data_t *ir, UNUSED(uint8_t opcode), uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) { - x86seg *target_seg; + x86seg *target_seg; - uop_FP_ENTER(ir); - uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc); - op_pc--; - target_seg = codegen_generate_ea(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32, 0); - codegen_check_seg_write(block, ir, target_seg); - uop_MOV_INT_DOUBLE(ir, IREG_temp0, IREG_ST(0)); - uop_MEM_STORE_REG(ir, ireg_seg_base(target_seg), IREG_eaaddr, IREG_temp0); - uop_MOV_IMM(ir, IREG_tag(0), TAG_EMPTY); + uop_FP_ENTER(ir); + uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc); + op_pc--; + target_seg = codegen_generate_ea(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32, 0); + codegen_check_seg_write(block, ir, target_seg); + uop_MOV_INT_DOUBLE(ir, IREG_temp0, IREG_ST(0)); + uop_MEM_STORE_REG(ir, ireg_seg_base(target_seg), IREG_eaaddr, IREG_temp0); + uop_MOV_IMM(ir, IREG_tag(0), TAG_EMPTY); - return op_pc+1; + return op_pc + 1; } -uint32_t ropFISTPl(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) +uint32_t +ropFISTPl(codeblock_t *block, ir_data_t *ir, UNUSED(uint8_t opcode), uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) { - x86seg *target_seg; + x86seg *target_seg; - uop_FP_ENTER(ir); - uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc); - op_pc--; - target_seg = codegen_generate_ea(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32, 0); - codegen_check_seg_write(block, ir, target_seg); - uop_MOV_INT_DOUBLE(ir, IREG_temp0, IREG_ST(0)); - uop_MEM_STORE_REG(ir, ireg_seg_base(target_seg), IREG_eaaddr, IREG_temp0); - uop_MOV_IMM(ir, IREG_tag(0), TAG_EMPTY); - fpu_POP(block, ir); + uop_FP_ENTER(ir); + uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc); + op_pc--; + target_seg = codegen_generate_ea(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32, 0); + codegen_check_seg_write(block, ir, target_seg); + uop_MOV_INT_DOUBLE(ir, IREG_temp0, IREG_ST(0)); + uop_MEM_STORE_REG(ir, ireg_seg_base(target_seg), IREG_eaaddr, IREG_temp0); + uop_MOV_IMM(ir, IREG_tag(0), TAG_EMPTY); + fpu_POP(block, ir); - return op_pc+1; + return op_pc + 1; } -uint32_t ropFISTPq(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) +uint32_t +ropFISTPq(codeblock_t *block, ir_data_t *ir, UNUSED(uint8_t opcode), uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) { - x86seg *target_seg; + x86seg *target_seg; - uop_FP_ENTER(ir); - uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc); - op_pc--; - target_seg = codegen_generate_ea(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32, 0); - codegen_check_seg_write(block, ir, target_seg); - uop_MOV_INT_DOUBLE_64(ir, IREG_temp0_Q, IREG_ST(0), IREG_ST_i64(0), IREG_tag(0)); - uop_MEM_STORE_REG(ir, ireg_seg_base(target_seg), IREG_eaaddr, IREG_temp0_Q); - uop_MOV_IMM(ir, IREG_tag(0), TAG_EMPTY); - fpu_POP(block, ir); + uop_FP_ENTER(ir); + uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc); + op_pc--; + target_seg = codegen_generate_ea(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32, 0); + codegen_check_seg_write(block, ir, target_seg); + uop_MOV_INT_DOUBLE_64(ir, IREG_temp0_Q, IREG_ST(0), IREG_ST_i64(0), IREG_tag(0)); + uop_MEM_STORE_REG(ir, ireg_seg_base(target_seg), IREG_eaaddr, IREG_temp0_Q); + uop_MOV_IMM(ir, IREG_tag(0), TAG_EMPTY); + fpu_POP(block, ir); - return op_pc+1; + return op_pc + 1; } diff --git a/src/codegen_new/codegen_ops_fpu_misc.c b/src/codegen_new/codegen_ops_fpu_misc.c index 2aea3678b..7865e0573 100644 --- a/src/codegen_new/codegen_ops_fpu_misc.c +++ b/src/codegen_new/codegen_ops_fpu_misc.c @@ -2,9 +2,12 @@ #include <86box/86box.h> #include "cpu.h" #include <86box/mem.h> +#include <86box/plat_unused.h> #include "x86.h" #include "x86_flags.h" +#include "x86seg_common.h" +#include "x86seg.h" #include "386_common.h" #include "x87.h" #include "codegen.h" @@ -14,101 +17,109 @@ #include "codegen_ops_fpu_misc.h" #include "codegen_ops_helpers.h" -uint32_t ropFFREE(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) +uint32_t +ropFFREE(UNUSED(codeblock_t *block), ir_data_t *ir, UNUSED(uint8_t opcode), uint32_t fetchdat, UNUSED(uint32_t op_32), uint32_t op_pc) { - int dest_reg = fetchdat & 7; + int dest_reg = fetchdat & 7; - uop_FP_ENTER(ir); - uop_MOV(ir, IREG_tag(dest_reg), TAG_EMPTY); + uop_FP_ENTER(ir); + uop_MOV(ir, IREG_tag(dest_reg), TAG_EMPTY); - return op_pc; + return op_pc; } -uint32_t ropFLD(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) +uint32_t +ropFLD(codeblock_t *block, ir_data_t *ir, UNUSED(uint8_t opcode), uint32_t fetchdat, UNUSED(uint32_t op_32), uint32_t op_pc) { - int src_reg = fetchdat & 7; + int src_reg = fetchdat & 7; - uop_FP_ENTER(ir); - uop_MOV(ir, IREG_ST(-1), IREG_ST(src_reg)); - uop_MOV(ir, IREG_ST_i64(-1), IREG_ST_i64(src_reg)); - uop_MOV(ir, IREG_tag(-1), IREG_tag(src_reg)); - fpu_PUSH(block, ir); + uop_FP_ENTER(ir); + uop_MOV(ir, IREG_ST(-1), IREG_ST(src_reg)); + uop_MOV(ir, IREG_ST_i64(-1), IREG_ST_i64(src_reg)); + uop_MOV(ir, IREG_tag(-1), IREG_tag(src_reg)); + fpu_PUSH(block, ir); - return op_pc; + return op_pc; } -uint32_t ropFST(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) +uint32_t +ropFST(UNUSED(codeblock_t *block), ir_data_t *ir, UNUSED(uint8_t opcode), uint32_t fetchdat, UNUSED(uint32_t op_32), uint32_t op_pc) { - int dest_reg = fetchdat & 7; + int dest_reg = fetchdat & 7; - uop_FP_ENTER(ir); - uop_MOV(ir, IREG_ST(dest_reg), IREG_ST(0)); - uop_MOV(ir, IREG_ST_i64(dest_reg), IREG_ST_i64(0)); - uop_MOV(ir, IREG_tag(dest_reg), IREG_tag(0)); + uop_FP_ENTER(ir); + uop_MOV(ir, IREG_ST(dest_reg), IREG_ST(0)); + uop_MOV(ir, IREG_ST_i64(dest_reg), IREG_ST_i64(0)); + uop_MOV(ir, IREG_tag(dest_reg), IREG_tag(0)); - return op_pc; + return op_pc; } -uint32_t ropFSTP(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) +uint32_t +ropFSTP(codeblock_t *block, ir_data_t *ir, UNUSED(uint8_t opcode), uint32_t fetchdat, UNUSED(uint32_t op_32), uint32_t op_pc) { - int dest_reg = fetchdat & 7; + int dest_reg = fetchdat & 7; - uop_FP_ENTER(ir); - uop_MOV(ir, IREG_ST(dest_reg), IREG_ST(0)); - uop_MOV(ir, IREG_ST_i64(dest_reg), IREG_ST_i64(0)); - uop_MOV(ir, IREG_tag(dest_reg), IREG_tag(0)); - fpu_POP(block, ir); + uop_FP_ENTER(ir); + uop_MOV(ir, IREG_ST(dest_reg), IREG_ST(0)); + uop_MOV(ir, IREG_ST_i64(dest_reg), IREG_ST_i64(0)); + uop_MOV(ir, IREG_tag(dest_reg), IREG_tag(0)); + fpu_POP(block, ir); - return op_pc; + return op_pc; } -uint32_t ropFSTCW(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) +uint32_t +ropFSTCW(codeblock_t *block, ir_data_t *ir, UNUSED(uint8_t opcode), uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) { - x86seg *target_seg; + x86seg *target_seg; - uop_FP_ENTER(ir); - uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc); - op_pc--; - target_seg = codegen_generate_ea(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32, 0); - codegen_check_seg_write(block, ir, target_seg); - uop_MEM_STORE_REG(ir, ireg_seg_base(target_seg), IREG_eaaddr, IREG_NPXC); + uop_FP_ENTER(ir); + uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc); + op_pc--; + target_seg = codegen_generate_ea(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32, 0); + codegen_check_seg_write(block, ir, target_seg); + uop_MEM_STORE_REG(ir, ireg_seg_base(target_seg), IREG_eaaddr, IREG_NPXC); - return op_pc+1; + return op_pc + 1; } -uint32_t ropFSTSW(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) +uint32_t +ropFSTSW(codeblock_t *block, ir_data_t *ir, UNUSED(uint8_t opcode), uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) { - x86seg *target_seg; + x86seg *target_seg; - uop_FP_ENTER(ir); - uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc); - op_pc--; - target_seg = codegen_generate_ea(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32, 0); - codegen_check_seg_write(block, ir, target_seg); - uop_MEM_STORE_REG(ir, ireg_seg_base(target_seg), IREG_eaaddr, IREG_NPXS); + uop_FP_ENTER(ir); + uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc); + op_pc--; + target_seg = codegen_generate_ea(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32, 0); + codegen_check_seg_write(block, ir, target_seg); + uop_MEM_STORE_REG(ir, ireg_seg_base(target_seg), IREG_eaaddr, IREG_NPXS); - return op_pc+1; + return op_pc + 1; } -uint32_t ropFSTSW_AX(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) +uint32_t +ropFSTSW_AX(UNUSED(codeblock_t *block), ir_data_t *ir, UNUSED(uint8_t opcode), uint32_t fetchdat, UNUSED(uint32_t op_32), uint32_t op_pc) { - uop_FP_ENTER(ir); - uop_MOV(ir, IREG_AX, IREG_NPXS); - - return op_pc; + uop_FP_ENTER(ir); + uop_MOV(ir, IREG_AX, IREG_NPXS); + + return op_pc; } -uint32_t ropFXCH(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) +uint32_t +ropFXCH(UNUSED(codeblock_t *block), ir_data_t *ir, UNUSED(uint8_t opcode), uint32_t fetchdat, UNUSED(uint32_t op_32), uint32_t op_pc) { - int dest_reg = fetchdat & 7; + int dest_reg = fetchdat & 7; - uop_FP_ENTER(ir); - uop_MOV(ir, IREG_temp0_D, IREG_ST(0)); - uop_MOV(ir, IREG_temp1_Q, IREG_ST_i64(0)); - uop_MOV(ir, IREG_temp2, IREG_tag(0)); - uop_MOV(ir, IREG_ST(0), IREG_ST(dest_reg)); - uop_MOV(ir, IREG_ST_i64(0), IREG_ST_i64(dest_reg)); - uop_MOV(ir, IREG_tag(0), IREG_tag(dest_reg)); - uop_MOV(ir, IREG_ST(dest_reg), IREG_temp0_D); - uop_MOV(ir, IREG_ST_i64(dest_reg), IREG_temp1_Q); - uop_MOV(ir, IREG_tag(dest_reg), IREG_temp2); + uop_FP_ENTER(ir); + uop_MOV(ir, IREG_temp0_D, IREG_ST(0)); + uop_MOV(ir, IREG_temp1_Q, IREG_ST_i64(0)); + uop_MOV(ir, IREG_temp2, IREG_tag(0)); + uop_MOV(ir, IREG_ST(0), IREG_ST(dest_reg)); + uop_MOV(ir, IREG_ST_i64(0), IREG_ST_i64(dest_reg)); + uop_MOV(ir, IREG_tag(0), IREG_tag(dest_reg)); + uop_MOV(ir, IREG_ST(dest_reg), IREG_temp0_D); + uop_MOV(ir, IREG_ST_i64(dest_reg), IREG_temp1_Q); + uop_MOV(ir, IREG_tag(dest_reg), IREG_temp2); - return op_pc; + return op_pc; } diff --git a/src/codegen_new/codegen_ops_helpers.c b/src/codegen_new/codegen_ops_helpers.c index 6d8cbfd3a..f2a4ce41a 100644 --- a/src/codegen_new/codegen_ops_helpers.c +++ b/src/codegen_new/codegen_ops_helpers.c @@ -2,8 +2,11 @@ #include <86box/86box.h> #include "cpu.h" #include <86box/mem.h> +#include <86box/plat_unused.h> #include "x86.h" +#include "x86seg_common.h" +#include "x86seg.h" #include "386_common.h" #include "codegen.h" #include "codegen_ir.h" @@ -11,65 +14,64 @@ #include "codegen_reg.h" #include "codegen_ops_helpers.h" -void LOAD_IMMEDIATE_FROM_RAM_16_unaligned(codeblock_t *block, ir_data_t *ir, int dest_reg, uint32_t addr) +void +LOAD_IMMEDIATE_FROM_RAM_16_unaligned(UNUSED(codeblock_t *block), ir_data_t *ir, int dest_reg, uint32_t addr) { - /*Word access that crosses two pages. Perform reads from both pages, shift and combine*/ - uop_MOVZX_REG_PTR_8(ir, IREG_temp3_W, get_ram_ptr(addr)); - uop_MOVZX_REG_PTR_8(ir, dest_reg, get_ram_ptr(addr+1)); - uop_SHL_IMM(ir, IREG_temp3_W, IREG_temp3_W, 8); - uop_OR(ir, dest_reg, dest_reg, IREG_temp3_W); + /*Word access that crosses two pages. Perform reads from both pages, shift and combine*/ + uop_MOVZX_REG_PTR_8(ir, IREG_temp3_W, get_ram_ptr(addr)); + uop_MOVZX_REG_PTR_8(ir, dest_reg, get_ram_ptr(addr + 1)); + uop_SHL_IMM(ir, IREG_temp3_W, IREG_temp3_W, 8); + uop_OR(ir, dest_reg, dest_reg, IREG_temp3_W); } -void LOAD_IMMEDIATE_FROM_RAM_32_unaligned(codeblock_t *block, ir_data_t *ir, int dest_reg, uint32_t addr) +void +LOAD_IMMEDIATE_FROM_RAM_32_unaligned(UNUSED(codeblock_t *block), ir_data_t *ir, int dest_reg, uint32_t addr) { - /*Dword access that crosses two pages. Perform reads from both pages, shift and combine*/ - uop_MOV_REG_PTR(ir, dest_reg, get_ram_ptr(addr & ~3)); - uop_MOV_REG_PTR(ir, IREG_temp3, get_ram_ptr((addr + 4) & ~3)); - uop_SHR_IMM(ir, dest_reg, dest_reg, (addr & 3) * 8); - uop_SHL_IMM(ir, IREG_temp3, IREG_temp3, (4 - (addr & 3)) * 8); - uop_OR(ir, dest_reg, dest_reg, IREG_temp3); + /*Dword access that crosses two pages. Perform reads from both pages, shift and combine*/ + uop_MOV_REG_PTR(ir, dest_reg, get_ram_ptr(addr & ~3)); + uop_MOV_REG_PTR(ir, IREG_temp3, get_ram_ptr((addr + 4) & ~3)); + uop_SHR_IMM(ir, dest_reg, dest_reg, (addr & 3) * 8); + uop_SHL_IMM(ir, IREG_temp3, IREG_temp3, (4 - (addr & 3)) * 8); + uop_OR(ir, dest_reg, dest_reg, IREG_temp3); } #define UNROLL_MAX_REG_REFERENCES 200 -#define UNROLL_MAX_UOPS 1000 -#define UNROLL_MAX_COUNT 10 -int codegen_can_unroll_full(codeblock_t *block, ir_data_t *ir, uint32_t next_pc, uint32_t dest_addr) +#define UNROLL_MAX_UOPS 1000 +#define UNROLL_MAX_COUNT 10 +int +codegen_can_unroll_full(codeblock_t *block, ir_data_t *ir, UNUSED(uint32_t next_pc), uint32_t dest_addr) { - int start; - int max_unroll; - int first_instruction; - int TOP = -1; + int start; + int max_unroll; + int first_instruction; + int TOP = -1; - /*Check that dest instruction was actually compiled into block*/ - start = codegen_get_instruction_uop(block, dest_addr, &first_instruction, &TOP); + /*Check that dest instruction was actually compiled into block*/ + start = codegen_get_instruction_uop(block, dest_addr, &first_instruction, &TOP); - /*Couldn't find any uOPs corresponding to the destination instruction*/ - if (start == -1) - { - /*Is instruction jumping to itself?*/ - if (dest_addr != cpu_state.oldpc) - { - return 0; - } - else - { - start = ir->wr_pos; - TOP = cpu_state.TOP; - } + /*Couldn't find any uOPs corresponding to the destination instruction*/ + if (start == -1) { + /*Is instruction jumping to itself?*/ + if (dest_addr != cpu_state.oldpc) { + return 0; + } else { + start = ir->wr_pos; + TOP = cpu_state.TOP; } - - if (TOP != cpu_state.TOP) - return 0; + } - max_unroll = UNROLL_MAX_UOPS / ((ir->wr_pos-start)+6); - if ((max_version_refcount != 0) && (max_unroll > (UNROLL_MAX_REG_REFERENCES / max_version_refcount))) - max_unroll = (UNROLL_MAX_REG_REFERENCES / max_version_refcount); - if (max_unroll > UNROLL_MAX_COUNT) - max_unroll = UNROLL_MAX_COUNT; - if (max_unroll <= 1) - return 0; + if (TOP != cpu_state.TOP) + return 0; - codegen_ir_set_unroll(max_unroll, start, first_instruction); + max_unroll = UNROLL_MAX_UOPS / ((ir->wr_pos - start) + 6); + if ((max_version_refcount != 0) && (max_unroll > (UNROLL_MAX_REG_REFERENCES / max_version_refcount))) + max_unroll = (UNROLL_MAX_REG_REFERENCES / max_version_refcount); + if (max_unroll > UNROLL_MAX_COUNT) + max_unroll = UNROLL_MAX_COUNT; + if (max_unroll <= 1) + return 0; - return 1; + codegen_ir_set_unroll(max_unroll, start, first_instruction); + + return 1; } diff --git a/src/codegen_new/codegen_ops_helpers.h b/src/codegen_new/codegen_ops_helpers.h index 41ffe297f..5a8f1e1c7 100644 --- a/src/codegen_new/codegen_ops_helpers.h +++ b/src/codegen_new/codegen_ops_helpers.h @@ -1,126 +1,127 @@ #include "386_common.h" #include "codegen_backend.h" -static inline int LOAD_SP_WITH_OFFSET(ir_data_t *ir, int offset) +static inline int +LOAD_SP_WITH_OFFSET(ir_data_t *ir, int offset) { - if (stack32) - { - if (offset) - { - uop_ADD_IMM(ir, IREG_eaaddr, IREG_ESP, offset); - return IREG_eaaddr; - } - else - return IREG_ESP; - } - else - { - if (offset) - { - uop_ADD_IMM(ir, IREG_eaaddr_W, IREG_SP, offset); - uop_MOVZX(ir, IREG_eaaddr, IREG_eaaddr_W); - return IREG_eaaddr; - } - else - { - uop_MOVZX(ir, IREG_eaaddr, IREG_SP); - return IREG_eaaddr; - } + if (stack32) { + if (offset) { + uop_ADD_IMM(ir, IREG_eaaddr, IREG_ESP, offset); + return IREG_eaaddr; + } else + return IREG_ESP; + } else { + if (offset) { + uop_ADD_IMM(ir, IREG_eaaddr_W, IREG_SP, offset); + uop_MOVZX(ir, IREG_eaaddr, IREG_eaaddr_W); + return IREG_eaaddr; + } else { + uop_MOVZX(ir, IREG_eaaddr, IREG_SP); + return IREG_eaaddr; } + } } -static inline int LOAD_SP(ir_data_t *ir) +static inline int +LOAD_SP(ir_data_t *ir) { - return LOAD_SP_WITH_OFFSET(ir, 0); + return LOAD_SP_WITH_OFFSET(ir, 0); } -static inline void ADD_SP(ir_data_t *ir, int offset) +static inline void +ADD_SP(ir_data_t *ir, int offset) { - if (stack32) - uop_ADD_IMM(ir, IREG_ESP, IREG_ESP, offset); - else - uop_ADD_IMM(ir, IREG_SP, IREG_SP, offset); + if (stack32) + uop_ADD_IMM(ir, IREG_ESP, IREG_ESP, offset); + else + uop_ADD_IMM(ir, IREG_SP, IREG_SP, offset); } -static inline void SUB_SP(ir_data_t *ir, int offset) +static inline void +SUB_SP(ir_data_t *ir, int offset) { - if (stack32) - uop_SUB_IMM(ir, IREG_ESP, IREG_ESP, offset); - else - uop_SUB_IMM(ir, IREG_SP, IREG_SP, offset); + if (stack32) + uop_SUB_IMM(ir, IREG_ESP, IREG_ESP, offset); + else + uop_SUB_IMM(ir, IREG_SP, IREG_SP, offset); } -static inline void fpu_POP(codeblock_t *block, ir_data_t *ir) +static inline void +fpu_POP(codeblock_t *block, ir_data_t *ir) { - if (block->flags & CODEBLOCK_STATIC_TOP) - uop_MOV_IMM(ir, IREG_FPU_TOP, cpu_state.TOP + 1); - else - uop_ADD_IMM(ir, IREG_FPU_TOP, IREG_FPU_TOP, 1); + if (block->flags & CODEBLOCK_STATIC_TOP) + uop_MOV_IMM(ir, IREG_FPU_TOP, cpu_state.TOP + 1); + else + uop_ADD_IMM(ir, IREG_FPU_TOP, IREG_FPU_TOP, 1); } -static inline void fpu_POP2(codeblock_t *block, ir_data_t *ir) +static inline void +fpu_POP2(codeblock_t *block, ir_data_t *ir) { - if (block->flags & CODEBLOCK_STATIC_TOP) - uop_MOV_IMM(ir, IREG_FPU_TOP, cpu_state.TOP + 2); - else - uop_ADD_IMM(ir, IREG_FPU_TOP, IREG_FPU_TOP, 2); + if (block->flags & CODEBLOCK_STATIC_TOP) + uop_MOV_IMM(ir, IREG_FPU_TOP, cpu_state.TOP + 2); + else + uop_ADD_IMM(ir, IREG_FPU_TOP, IREG_FPU_TOP, 2); } -static inline void fpu_PUSH(codeblock_t *block, ir_data_t *ir) +static inline void +fpu_PUSH(codeblock_t *block, ir_data_t *ir) { - if (block->flags & CODEBLOCK_STATIC_TOP) - uop_MOV_IMM(ir, IREG_FPU_TOP, cpu_state.TOP - 1); - else - uop_SUB_IMM(ir, IREG_FPU_TOP, IREG_FPU_TOP, 1); + if (block->flags & CODEBLOCK_STATIC_TOP) + uop_MOV_IMM(ir, IREG_FPU_TOP, cpu_state.TOP - 1); + else + uop_SUB_IMM(ir, IREG_FPU_TOP, IREG_FPU_TOP, 1); } -static inline void CHECK_SEG_LIMITS(codeblock_t *block, ir_data_t *ir, x86seg *seg, int addr_reg, int end_offset) +static inline void +CHECK_SEG_LIMITS(codeblock_t *block, ir_data_t *ir, x86seg *seg, int addr_reg, int end_offset) { - if ((seg == &cpu_state.seg_ds && codegen_flat_ds && !(cpu_cur_status & CPU_STATUS_NOTFLATDS)) || - (seg == &cpu_state.seg_ss && codegen_flat_ss && !(cpu_cur_status & CPU_STATUS_NOTFLATSS))) - return; + if ((seg == &cpu_state.seg_ds && codegen_flat_ds && !(cpu_cur_status & CPU_STATUS_NOTFLATDS)) || (seg == &cpu_state.seg_ss && codegen_flat_ss && !(cpu_cur_status & CPU_STATUS_NOTFLATSS))) + return; - uop_CMP_JB(ir, addr_reg, ireg_seg_limit_low(seg), codegen_gpf_rout); - if (end_offset) - { - uop_ADD_IMM(ir, IREG_temp3, addr_reg, end_offset); - uop_CMP_JNBE(ir, IREG_temp3, ireg_seg_limit_high(seg), codegen_gpf_rout); - } - else - uop_CMP_JNBE(ir, addr_reg, ireg_seg_limit_high(seg), codegen_gpf_rout); + uop_CMP_JB(ir, addr_reg, ireg_seg_limit_low(seg), codegen_gpf_rout); + if (end_offset) { + uop_ADD_IMM(ir, IREG_temp3, addr_reg, end_offset); + uop_CMP_JNBE(ir, IREG_temp3, ireg_seg_limit_high(seg), codegen_gpf_rout); + } else + uop_CMP_JNBE(ir, addr_reg, ireg_seg_limit_high(seg), codegen_gpf_rout); } -static inline void LOAD_IMMEDIATE_FROM_RAM_8(codeblock_t *block, ir_data_t *ir, int dest_reg, uint32_t addr) +static inline void +LOAD_IMMEDIATE_FROM_RAM_8(codeblock_t *block, ir_data_t *ir, int dest_reg, uint32_t addr) { - uop_MOVZX_REG_PTR_8(ir, dest_reg, get_ram_ptr(addr)); + uop_MOVZX_REG_PTR_8(ir, dest_reg, get_ram_ptr(addr)); } void LOAD_IMMEDIATE_FROM_RAM_16_unaligned(codeblock_t *block, ir_data_t *ir, int dest_reg, uint32_t addr); -static inline void LOAD_IMMEDIATE_FROM_RAM_16(codeblock_t *block, ir_data_t *ir, int dest_reg, uint32_t addr) +static inline void +LOAD_IMMEDIATE_FROM_RAM_16(codeblock_t *block, ir_data_t *ir, int dest_reg, uint32_t addr) { - if ((addr & 0xfff) == 0xfff) - LOAD_IMMEDIATE_FROM_RAM_16_unaligned(block, ir, dest_reg, addr); - else - uop_MOVZX_REG_PTR_16(ir, dest_reg, get_ram_ptr(addr)); + if ((addr & 0xfff) == 0xfff) + LOAD_IMMEDIATE_FROM_RAM_16_unaligned(block, ir, dest_reg, addr); + else + uop_MOVZX_REG_PTR_16(ir, dest_reg, get_ram_ptr(addr)); } void LOAD_IMMEDIATE_FROM_RAM_32_unaligned(codeblock_t *block, ir_data_t *ir, int dest_reg, uint32_t addr); -static inline void LOAD_IMMEDIATE_FROM_RAM_32(codeblock_t *block, ir_data_t *ir, int dest_reg, uint32_t addr) +static inline void +LOAD_IMMEDIATE_FROM_RAM_32(codeblock_t *block, ir_data_t *ir, int dest_reg, uint32_t addr) { - if ((addr & 0xfff) >= 0xffd) - LOAD_IMMEDIATE_FROM_RAM_32_unaligned(block, ir, dest_reg, addr); - else - uop_MOV_REG_PTR(ir, dest_reg, get_ram_ptr(addr)); + if ((addr & 0xfff) >= 0xffd) + LOAD_IMMEDIATE_FROM_RAM_32_unaligned(block, ir, dest_reg, addr); + else + uop_MOV_REG_PTR(ir, dest_reg, get_ram_ptr(addr)); } int codegen_can_unroll_full(codeblock_t *block, ir_data_t *ir, uint32_t next_pc, uint32_t dest_addr); -static inline int codegen_can_unroll(codeblock_t *block, ir_data_t *ir, uint32_t next_pc, uint32_t dest_addr) +static inline int +codegen_can_unroll(codeblock_t *block, ir_data_t *ir, uint32_t next_pc, uint32_t dest_addr) { - if (block->flags & CODEBLOCK_BYTE_MASK) - return 0; + if (block->flags & CODEBLOCK_BYTE_MASK) + return 0; - /*Is dest within block?*/ - if (dest_addr > next_pc) - return 0; - if ((cs+dest_addr) < block->pc) - return 0; + /*Is dest within block?*/ + if (dest_addr > next_pc) + return 0; + if ((cs + dest_addr) < block->pc) + return 0; - return codegen_can_unroll_full(block, ir, next_pc, dest_addr); + return codegen_can_unroll_full(block, ir, next_pc, dest_addr); } diff --git a/src/codegen_new/codegen_ops_jump.c b/src/codegen_new/codegen_ops_jump.c index f7a5145a0..fb2f1e5ba 100644 --- a/src/codegen_new/codegen_ops_jump.c +++ b/src/codegen_new/codegen_ops_jump.c @@ -2,8 +2,11 @@ #include <86box/86box.h> #include "cpu.h" #include <86box/mem.h> +#include <86box/plat_unused.h> #include "x86.h" +#include "x86seg_common.h" +#include "x86seg.h" #include "386_common.h" #include "codegen.h" #include "codegen_ir.h" @@ -11,282 +14,281 @@ #include "codegen_ops_helpers.h" #include "codegen_ops_mov.h" -uint32_t ropJMP_r8(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) +uint32_t +ropJMP_r8(codeblock_t *block, ir_data_t *ir, UNUSED(uint8_t opcode), uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) { - uint32_t offset = (int32_t)(int8_t)fastreadb(cs + op_pc); - uint32_t dest_addr = op_pc+1+offset; + uint32_t offset = (int32_t) (int8_t) fastreadb(cs + op_pc); + uint32_t dest_addr = op_pc + 1 + offset; - if (!(op_32 & 0x100)) - dest_addr &= 0xffff; - - if (offset < 0) - codegen_can_unroll(block, ir, op_pc+1, dest_addr); - codegen_mark_code_present(block, cs+op_pc, 1); - return dest_addr; -} -uint32_t ropJMP_r16(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) -{ - uint32_t offset = (int32_t)(int16_t)fastreadw(cs + op_pc); - uint32_t dest_addr = op_pc+2+offset; - + if (!(op_32 & 0x100)) dest_addr &= 0xffff; - if (offset < 0) - codegen_can_unroll(block, ir, op_pc+1, dest_addr); - codegen_mark_code_present(block, cs+op_pc, 2); - return dest_addr; + if (offset < 0) + codegen_can_unroll(block, ir, op_pc + 1, dest_addr); + codegen_mark_code_present(block, cs + op_pc, 1); + return dest_addr; } -uint32_t ropJMP_r32(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) +uint32_t +ropJMP_r16(codeblock_t *block, ir_data_t *ir, UNUSED(uint8_t opcode), uint32_t fetchdat, UNUSED(uint32_t op_32), uint32_t op_pc) { - uint32_t offset = fastreadl(cs + op_pc); - uint32_t dest_addr = op_pc+4+offset; - - if (offset < 0) - codegen_can_unroll(block, ir, op_pc+1, dest_addr); - codegen_mark_code_present(block, cs+op_pc, 4); - return dest_addr; -} + uint32_t offset = (int32_t) (int16_t) fastreadw(cs + op_pc); + uint32_t dest_addr = op_pc + 2 + offset; -uint32_t ropJMP_far_16(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) + dest_addr &= 0xffff; + + if (offset < 0) + codegen_can_unroll(block, ir, op_pc + 1, dest_addr); + codegen_mark_code_present(block, cs + op_pc, 2); + return dest_addr; +} +uint32_t +ropJMP_r32(codeblock_t *block, ir_data_t *ir, UNUSED(uint8_t opcode), uint32_t fetchdat, UNUSED(uint32_t op_32), uint32_t op_pc) { - uint16_t new_pc = fastreadw(cs + op_pc); - uint16_t new_cs = fastreadw(cs + op_pc + 2); + uint32_t offset = fastreadl(cs + op_pc); + uint32_t dest_addr = op_pc + 4 + offset; - uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc); - uop_MOV_IMM(ir, IREG_pc, new_pc); - uop_LOAD_FUNC_ARG_IMM(ir, 0, new_cs); - uop_LOAD_FUNC_ARG_IMM(ir, 1, op_pc + 4); - uop_CALL_FUNC(ir, loadcsjmp); - - codegen_mark_code_present(block, cs+op_pc, 4); - return -1; + if (offset < 0) + codegen_can_unroll(block, ir, op_pc + 1, dest_addr); + codegen_mark_code_present(block, cs + op_pc, 4); + return dest_addr; } -uint32_t ropJMP_far_32(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) + +uint32_t +ropJMP_far_16(codeblock_t *block, ir_data_t *ir, UNUSED(uint8_t opcode), uint32_t fetchdat, UNUSED(uint32_t op_32), uint32_t op_pc) { - uint32_t new_pc = fastreadl(cs + op_pc); - uint16_t new_cs = fastreadw(cs + op_pc + 4); + uint16_t new_pc = fastreadw(cs + op_pc); + uint16_t new_cs = fastreadw(cs + op_pc + 2); - uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc); - uop_MOV_IMM(ir, IREG_pc, new_pc); - uop_LOAD_FUNC_ARG_IMM(ir, 0, new_cs); - uop_LOAD_FUNC_ARG_IMM(ir, 1, op_pc + 4); - uop_CALL_FUNC(ir, loadcsjmp); + uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc); + uop_MOV_IMM(ir, IREG_pc, new_pc); + uop_LOAD_FUNC_ARG_IMM(ir, 0, new_cs); + uop_LOAD_FUNC_ARG_IMM(ir, 1, op_pc + 4); + uop_CALL_FUNC(ir, loadcsjmp); - codegen_mark_code_present(block, cs+op_pc, 6); - return -1; + codegen_mark_code_present(block, cs + op_pc, 4); + return -1; } - -uint32_t ropCALL_r16(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) +uint32_t +ropJMP_far_32(codeblock_t *block, ir_data_t *ir, UNUSED(uint8_t opcode), uint32_t fetchdat, UNUSED(uint32_t op_32), uint32_t op_pc) { - uint32_t offset = (int32_t)(int16_t)fastreadw(cs + op_pc); - uint16_t ret_addr = op_pc + 2; - uint16_t dest_addr = ret_addr + offset; - int sp_reg; + uint32_t new_pc = fastreadl(cs + op_pc); + uint16_t new_cs = fastreadw(cs + op_pc + 4); - dest_addr &= 0xffff; + uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc); + uop_MOV_IMM(ir, IREG_pc, new_pc); + uop_LOAD_FUNC_ARG_IMM(ir, 0, new_cs); + uop_LOAD_FUNC_ARG_IMM(ir, 1, op_pc + 4); + uop_CALL_FUNC(ir, loadcsjmp); - uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc); - sp_reg = LOAD_SP_WITH_OFFSET(ir, -2); - uop_MEM_STORE_IMM_16(ir, IREG_SS_base, sp_reg, ret_addr); - SUB_SP(ir, 2); - uop_MOV_IMM(ir, IREG_pc, dest_addr); - - codegen_mark_code_present(block, cs+op_pc, 2); - return -1; + codegen_mark_code_present(block, cs + op_pc, 6); + return -1; } -uint32_t ropCALL_r32(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) + +uint32_t +ropCALL_r16(codeblock_t *block, ir_data_t *ir, UNUSED(uint8_t opcode), uint32_t fetchdat, UNUSED(uint32_t op_32), uint32_t op_pc) { - uint32_t offset = fastreadl(cs + op_pc); - uint32_t ret_addr = op_pc + 4; - uint32_t dest_addr = ret_addr + offset; - int sp_reg; - - uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc); - sp_reg = LOAD_SP_WITH_OFFSET(ir, -4); - uop_MEM_STORE_IMM_32(ir, IREG_SS_base, sp_reg, ret_addr); - SUB_SP(ir, 4); - uop_MOV_IMM(ir, IREG_pc, dest_addr); - - codegen_mark_code_present(block, cs+op_pc, 4); - return -1; -} + uint32_t offset = (int32_t) (int16_t) fastreadw(cs + op_pc); + uint16_t ret_addr = op_pc + 2; + uint16_t dest_addr = ret_addr + offset; + int sp_reg; -uint32_t ropRET_16(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) + dest_addr &= 0xffff; + + uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc); + sp_reg = LOAD_SP_WITH_OFFSET(ir, -2); + uop_MEM_STORE_IMM_16(ir, IREG_SS_base, sp_reg, ret_addr); + SUB_SP(ir, 2); + uop_MOV_IMM(ir, IREG_pc, dest_addr); + + codegen_mark_code_present(block, cs + op_pc, 2); + return -1; +} +uint32_t +ropCALL_r32(codeblock_t *block, ir_data_t *ir, UNUSED(uint8_t opcode), uint32_t fetchdat, UNUSED(uint32_t op_32), uint32_t op_pc) { - uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc); - - if (stack32) - uop_MEM_LOAD_REG(ir, IREG_temp0_W, IREG_SS_base, IREG_ESP); - else - { - uop_MOVZX(ir, IREG_eaaddr, IREG_SP); - uop_MEM_LOAD_REG(ir, IREG_temp0_W, IREG_SS_base, IREG_eaaddr); - } - ADD_SP(ir, 2); - uop_MOVZX(ir, IREG_pc, IREG_temp0_W); + uint32_t offset = fastreadl(cs + op_pc); + uint32_t ret_addr = op_pc + 4; + uint32_t dest_addr = ret_addr + offset; + int sp_reg; - return -1; + uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc); + sp_reg = LOAD_SP_WITH_OFFSET(ir, -4); + uop_MEM_STORE_IMM_32(ir, IREG_SS_base, sp_reg, ret_addr); + SUB_SP(ir, 4); + uop_MOV_IMM(ir, IREG_pc, dest_addr); + + codegen_mark_code_present(block, cs + op_pc, 4); + return -1; } -uint32_t ropRET_32(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) + +uint32_t +ropRET_16(UNUSED(codeblock_t *block), ir_data_t *ir, UNUSED(uint8_t opcode), uint32_t fetchdat, UNUSED(uint32_t op_32), UNUSED(uint32_t op_pc)) { - uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc); - - if (stack32) - uop_MEM_LOAD_REG(ir, IREG_pc, IREG_SS_base, IREG_ESP); - else - { - uop_MOVZX(ir, IREG_eaaddr, IREG_SP); - uop_MEM_LOAD_REG(ir, IREG_pc, IREG_SS_base, IREG_eaaddr); - } - ADD_SP(ir, 4); + uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc); - return -1; + if (stack32) + uop_MEM_LOAD_REG(ir, IREG_temp0_W, IREG_SS_base, IREG_ESP); + else { + uop_MOVZX(ir, IREG_eaaddr, IREG_SP); + uop_MEM_LOAD_REG(ir, IREG_temp0_W, IREG_SS_base, IREG_eaaddr); + } + ADD_SP(ir, 2); + uop_MOVZX(ir, IREG_pc, IREG_temp0_W); + + return -1; } - -uint32_t ropRET_imm_16(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) +uint32_t +ropRET_32(UNUSED(codeblock_t *block), ir_data_t *ir, UNUSED(uint8_t opcode), uint32_t fetchdat, UNUSED(uint32_t op_32), UNUSED(uint32_t op_pc)) { - uint16_t offset = fastreadw(cs + op_pc); - - uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc); + uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc); - if (stack32) - uop_MEM_LOAD_REG(ir, IREG_temp0_W, IREG_SS_base, IREG_ESP); - else - { - uop_MOVZX(ir, IREG_eaaddr, IREG_SP); - uop_MEM_LOAD_REG(ir, IREG_temp0_W, IREG_SS_base, IREG_eaaddr); - } - ADD_SP(ir, 2+offset); - uop_MOVZX(ir, IREG_pc, IREG_temp0_W); + if (stack32) + uop_MEM_LOAD_REG(ir, IREG_pc, IREG_SS_base, IREG_ESP); + else { + uop_MOVZX(ir, IREG_eaaddr, IREG_SP); + uop_MEM_LOAD_REG(ir, IREG_pc, IREG_SS_base, IREG_eaaddr); + } + ADD_SP(ir, 4); - codegen_mark_code_present(block, cs+op_pc, 2); - return -1; + return -1; } -uint32_t ropRET_imm_32(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) + +uint32_t +ropRET_imm_16(codeblock_t *block, ir_data_t *ir, UNUSED(uint8_t opcode), uint32_t fetchdat, UNUSED(uint32_t op_32), uint32_t op_pc) { - uint16_t offset = fastreadw(cs + op_pc); + uint16_t offset = fastreadw(cs + op_pc); - uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc); + uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc); - if (stack32) - uop_MEM_LOAD_REG(ir, IREG_pc, IREG_SS_base, IREG_ESP); - else - { - uop_MOVZX(ir, IREG_eaaddr, IREG_SP); - uop_MEM_LOAD_REG(ir, IREG_pc, IREG_SS_base, IREG_eaaddr); - } - ADD_SP(ir, 4+offset); + if (stack32) + uop_MEM_LOAD_REG(ir, IREG_temp0_W, IREG_SS_base, IREG_ESP); + else { + uop_MOVZX(ir, IREG_eaaddr, IREG_SP); + uop_MEM_LOAD_REG(ir, IREG_temp0_W, IREG_SS_base, IREG_eaaddr); + } + ADD_SP(ir, 2 + offset); + uop_MOVZX(ir, IREG_pc, IREG_temp0_W); - codegen_mark_code_present(block, cs+op_pc, 2); - return -1; + codegen_mark_code_present(block, cs + op_pc, 2); + return -1; } - -uint32_t ropRETF_16(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) +uint32_t +ropRET_imm_32(codeblock_t *block, ir_data_t *ir, UNUSED(uint8_t opcode), uint32_t fetchdat, UNUSED(uint32_t op_32), uint32_t op_pc) { - if ((msw&1) && !(cpu_state.eflags&VM_FLAG)) - return 0; + uint16_t offset = fastreadw(cs + op_pc); - uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc); + uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc); - if (stack32) - { - uop_MEM_LOAD_REG(ir, IREG_temp0_W, IREG_SS_base, IREG_ESP); - uop_MEM_LOAD_REG_OFFSET(ir, IREG_temp1_W, IREG_SS_base, IREG_ESP, 2); - } - else - { - uop_MOVZX(ir, IREG_eaaddr, IREG_SP); - uop_MEM_LOAD_REG(ir, IREG_temp0_W, IREG_SS_base, IREG_eaaddr); - uop_MEM_LOAD_REG_OFFSET(ir, IREG_temp1_W, IREG_SS_base, IREG_eaaddr, 2); - } - uop_MOVZX(ir, IREG_pc, IREG_temp0_W); - uop_LOAD_FUNC_ARG_REG(ir, 0, IREG_temp1_W); - uop_CALL_FUNC(ir, loadcs); - ADD_SP(ir, 4); + if (stack32) + uop_MEM_LOAD_REG(ir, IREG_pc, IREG_SS_base, IREG_ESP); + else { + uop_MOVZX(ir, IREG_eaaddr, IREG_SP); + uop_MEM_LOAD_REG(ir, IREG_pc, IREG_SS_base, IREG_eaaddr); + } + ADD_SP(ir, 4 + offset); - return -1; + codegen_mark_code_present(block, cs + op_pc, 2); + return -1; } -uint32_t ropRETF_32(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) + +uint32_t +ropRETF_16(UNUSED(codeblock_t *block), ir_data_t *ir, UNUSED(uint8_t opcode), uint32_t fetchdat, UNUSED(uint32_t op_32), UNUSED(uint32_t op_pc)) { - if ((msw&1) && !(cpu_state.eflags&VM_FLAG)) - return 0; + if ((msw & 1) && !(cpu_state.eflags & VM_FLAG)) + return 0; - uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc); + uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc); - if (stack32) - { - uop_MEM_LOAD_REG(ir, IREG_temp0, IREG_SS_base, IREG_ESP); - uop_MEM_LOAD_REG_OFFSET(ir, IREG_temp1_W, IREG_SS_base, IREG_ESP, 4); - } - else - { - uop_MOVZX(ir, IREG_eaaddr, IREG_SP); - uop_MEM_LOAD_REG(ir, IREG_temp0, IREG_SS_base, IREG_eaaddr); - uop_MEM_LOAD_REG_OFFSET(ir, IREG_temp1_W, IREG_SS_base, IREG_eaaddr, 4); - } - uop_MOV(ir, IREG_pc, IREG_temp0); - uop_LOAD_FUNC_ARG_REG(ir, 0, IREG_temp1_W); - uop_CALL_FUNC(ir, loadcs); - ADD_SP(ir, 8); + if (stack32) { + uop_MEM_LOAD_REG(ir, IREG_temp0_W, IREG_SS_base, IREG_ESP); + uop_MEM_LOAD_REG_OFFSET(ir, IREG_temp1_W, IREG_SS_base, IREG_ESP, 2); + } else { + uop_MOVZX(ir, IREG_eaaddr, IREG_SP); + uop_MEM_LOAD_REG(ir, IREG_temp0_W, IREG_SS_base, IREG_eaaddr); + uop_MEM_LOAD_REG_OFFSET(ir, IREG_temp1_W, IREG_SS_base, IREG_eaaddr, 2); + } + uop_MOVZX(ir, IREG_pc, IREG_temp0_W); + uop_LOAD_FUNC_ARG_REG(ir, 0, IREG_temp1_W); + uop_CALL_FUNC(ir, loadcs); + ADD_SP(ir, 4); - return -1; + return -1; } - -uint32_t ropRETF_imm_16(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) +uint32_t +ropRETF_32(UNUSED(codeblock_t *block), ir_data_t *ir, UNUSED(uint8_t opcode), uint32_t fetchdat, UNUSED(uint32_t op_32), UNUSED(uint32_t op_pc)) { - uint16_t offset; + if ((msw & 1) && !(cpu_state.eflags & VM_FLAG)) + return 0; - if ((msw&1) && !(cpu_state.eflags&VM_FLAG)) - return 0; + uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc); - offset = fastreadw(cs + op_pc); - uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc); + if (stack32) { + uop_MEM_LOAD_REG(ir, IREG_temp0, IREG_SS_base, IREG_ESP); + uop_MEM_LOAD_REG_OFFSET(ir, IREG_temp1_W, IREG_SS_base, IREG_ESP, 4); + } else { + uop_MOVZX(ir, IREG_eaaddr, IREG_SP); + uop_MEM_LOAD_REG(ir, IREG_temp0, IREG_SS_base, IREG_eaaddr); + uop_MEM_LOAD_REG_OFFSET(ir, IREG_temp1_W, IREG_SS_base, IREG_eaaddr, 4); + } + uop_MOV(ir, IREG_pc, IREG_temp0); + uop_LOAD_FUNC_ARG_REG(ir, 0, IREG_temp1_W); + uop_CALL_FUNC(ir, loadcs); + ADD_SP(ir, 8); - if (stack32) - { - uop_MEM_LOAD_REG(ir, IREG_temp0_W, IREG_SS_base, IREG_ESP); - uop_MEM_LOAD_REG_OFFSET(ir, IREG_temp1_W, IREG_SS_base, IREG_ESP, 2); - } - else - { - uop_MOVZX(ir, IREG_eaaddr, IREG_SP); - uop_MEM_LOAD_REG(ir, IREG_temp0_W, IREG_SS_base, IREG_eaaddr); - uop_MEM_LOAD_REG_OFFSET(ir, IREG_temp1_W, IREG_SS_base, IREG_eaaddr, 2); - } - uop_MOVZX(ir, IREG_pc, IREG_temp0_W); - uop_LOAD_FUNC_ARG_REG(ir, 0, IREG_temp1_W); - uop_CALL_FUNC(ir, loadcs); - ADD_SP(ir, 4+offset); - - codegen_mark_code_present(block, cs+op_pc, 2); - return -1; + return -1; } -uint32_t ropRETF_imm_32(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) + +uint32_t +ropRETF_imm_16(codeblock_t *block, ir_data_t *ir, UNUSED(uint8_t opcode), uint32_t fetchdat, UNUSED(uint32_t op_32), uint32_t op_pc) { - uint16_t offset; + uint16_t offset; - if ((msw&1) && !(cpu_state.eflags&VM_FLAG)) - return 0; - - offset = fastreadw(cs + op_pc); - uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc); + if ((msw & 1) && !(cpu_state.eflags & VM_FLAG)) + return 0; - if (stack32) - { - uop_MEM_LOAD_REG(ir, IREG_temp0, IREG_SS_base, IREG_ESP); - uop_MEM_LOAD_REG_OFFSET(ir, IREG_temp1_W, IREG_SS_base, IREG_ESP, 4); - } - else - { - uop_MOVZX(ir, IREG_eaaddr, IREG_SP); - uop_MEM_LOAD_REG(ir, IREG_temp0, IREG_SS_base, IREG_eaaddr); - uop_MEM_LOAD_REG_OFFSET(ir, IREG_temp1_W, IREG_SS_base, IREG_eaaddr, 4); - } - uop_MOV(ir, IREG_pc, IREG_temp0); - uop_LOAD_FUNC_ARG_REG(ir, 0, IREG_temp1_W); - uop_CALL_FUNC(ir, loadcs); - ADD_SP(ir, 8+offset); + offset = fastreadw(cs + op_pc); + uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc); - codegen_mark_code_present(block, cs+op_pc, 2); - return -1; + if (stack32) { + uop_MEM_LOAD_REG(ir, IREG_temp0_W, IREG_SS_base, IREG_ESP); + uop_MEM_LOAD_REG_OFFSET(ir, IREG_temp1_W, IREG_SS_base, IREG_ESP, 2); + } else { + uop_MOVZX(ir, IREG_eaaddr, IREG_SP); + uop_MEM_LOAD_REG(ir, IREG_temp0_W, IREG_SS_base, IREG_eaaddr); + uop_MEM_LOAD_REG_OFFSET(ir, IREG_temp1_W, IREG_SS_base, IREG_eaaddr, 2); + } + uop_MOVZX(ir, IREG_pc, IREG_temp0_W); + uop_LOAD_FUNC_ARG_REG(ir, 0, IREG_temp1_W); + uop_CALL_FUNC(ir, loadcs); + ADD_SP(ir, 4 + offset); + + codegen_mark_code_present(block, cs + op_pc, 2); + return -1; +} +uint32_t +ropRETF_imm_32(codeblock_t *block, ir_data_t *ir, UNUSED(uint8_t opcode), uint32_t fetchdat, UNUSED(uint32_t op_32), uint32_t op_pc) +{ + uint16_t offset; + + if ((msw & 1) && !(cpu_state.eflags & VM_FLAG)) + return 0; + + offset = fastreadw(cs + op_pc); + uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc); + + if (stack32) { + uop_MEM_LOAD_REG(ir, IREG_temp0, IREG_SS_base, IREG_ESP); + uop_MEM_LOAD_REG_OFFSET(ir, IREG_temp1_W, IREG_SS_base, IREG_ESP, 4); + } else { + uop_MOVZX(ir, IREG_eaaddr, IREG_SP); + uop_MEM_LOAD_REG(ir, IREG_temp0, IREG_SS_base, IREG_eaaddr); + uop_MEM_LOAD_REG_OFFSET(ir, IREG_temp1_W, IREG_SS_base, IREG_eaaddr, 4); + } + uop_MOV(ir, IREG_pc, IREG_temp0); + uop_LOAD_FUNC_ARG_REG(ir, 0, IREG_temp1_W); + uop_CALL_FUNC(ir, loadcs); + ADD_SP(ir, 8 + offset); + + codegen_mark_code_present(block, cs + op_pc, 2); + return -1; } diff --git a/src/codegen_new/codegen_ops_logic.c b/src/codegen_new/codegen_ops_logic.c index 5d50423c1..684052fea 100644 --- a/src/codegen_new/codegen_ops_logic.c +++ b/src/codegen_new/codegen_ops_logic.c @@ -2,9 +2,12 @@ #include <86box/86box.h> #include "cpu.h" #include <86box/mem.h> +#include <86box/plat_unused.h> #include "x86.h" #include "x86_flags.h" +#include "x86seg_common.h" +#include "x86seg.h" #include "386_common.h" #include "codegen.h" #include "codegen_ir.h" @@ -12,796 +15,754 @@ #include "codegen_ops_helpers.h" #include "codegen_ops_logic.h" -uint32_t ropAND_AL_imm(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) +uint32_t +ropAND_AL_imm(codeblock_t *block, ir_data_t *ir, UNUSED(uint8_t opcode), uint32_t fetchdat, UNUSED(uint32_t op_32), uint32_t op_pc) { - uint8_t imm_data = fastreadb(cs + op_pc); + uint8_t imm_data = fastreadb(cs + op_pc); - uop_AND_IMM(ir, IREG_AL, IREG_AL, imm_data); - uop_MOV_IMM(ir, IREG_flags_op, FLAGS_ZN8); - uop_MOVZX(ir, IREG_flags_res, IREG_AL); + uop_AND_IMM(ir, IREG_AL, IREG_AL, imm_data); + uop_MOV_IMM(ir, IREG_flags_op, FLAGS_ZN8); + uop_MOVZX(ir, IREG_flags_res, IREG_AL); - codegen_flags_changed = 1; - codegen_mark_code_present(block, cs+op_pc, 1); - return op_pc + 1; + codegen_flags_changed = 1; + codegen_mark_code_present(block, cs + op_pc, 1); + return op_pc + 1; } -uint32_t ropAND_AX_imm(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) +uint32_t +ropAND_AX_imm(codeblock_t *block, ir_data_t *ir, UNUSED(uint8_t opcode), uint32_t fetchdat, UNUSED(uint32_t op_32), uint32_t op_pc) { - uint16_t imm_data = fastreadw(cs + op_pc); + uint16_t imm_data = fastreadw(cs + op_pc); - uop_AND_IMM(ir, IREG_AX, IREG_AX, imm_data); - uop_MOV_IMM(ir, IREG_flags_op, FLAGS_ZN16); - uop_MOVZX(ir, IREG_flags_res, IREG_AX); + uop_AND_IMM(ir, IREG_AX, IREG_AX, imm_data); + uop_MOV_IMM(ir, IREG_flags_op, FLAGS_ZN16); + uop_MOVZX(ir, IREG_flags_res, IREG_AX); - codegen_flags_changed = 1; - codegen_mark_code_present(block, cs+op_pc, 2); - return op_pc + 2; + codegen_flags_changed = 1; + codegen_mark_code_present(block, cs + op_pc, 2); + return op_pc + 2; } -uint32_t ropAND_EAX_imm(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) +uint32_t +ropAND_EAX_imm(codeblock_t *block, ir_data_t *ir, UNUSED(uint8_t opcode), uint32_t fetchdat, UNUSED(uint32_t op_32), uint32_t op_pc) { - if (block->flags & CODEBLOCK_NO_IMMEDIATES) - { - LOAD_IMMEDIATE_FROM_RAM_32(block, ir, IREG_temp0, cs + op_pc); - uop_AND(ir, IREG_EAX, IREG_EAX, IREG_temp0); - } - else - { - fetchdat = fastreadl(cs + op_pc); - codegen_mark_code_present(block, cs+op_pc, 4); - uop_AND_IMM(ir, IREG_EAX, IREG_EAX, fetchdat); - } + if (block->flags & CODEBLOCK_NO_IMMEDIATES) { + LOAD_IMMEDIATE_FROM_RAM_32(block, ir, IREG_temp0, cs + op_pc); + uop_AND(ir, IREG_EAX, IREG_EAX, IREG_temp0); + } else { + fetchdat = fastreadl(cs + op_pc); + codegen_mark_code_present(block, cs + op_pc, 4); + uop_AND_IMM(ir, IREG_EAX, IREG_EAX, fetchdat); + } - uop_MOV_IMM(ir, IREG_flags_op, FLAGS_ZN32); - uop_MOV(ir, IREG_flags_res, IREG_EAX); + uop_MOV_IMM(ir, IREG_flags_op, FLAGS_ZN32); + uop_MOV(ir, IREG_flags_res, IREG_EAX); - codegen_flags_changed = 1; - return op_pc + 4; + codegen_flags_changed = 1; + return op_pc + 4; } -uint32_t ropAND_b_rm(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) +uint32_t +ropAND_b_rm(codeblock_t *block, ir_data_t *ir, UNUSED(uint8_t opcode), uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) { - int dest_reg = (fetchdat >> 3) & 7; + int dest_reg = (fetchdat >> 3) & 7; - codegen_mark_code_present(block, cs+op_pc, 1); - if ((fetchdat & 0xc0) == 0xc0) - { - int src_reg = fetchdat & 7; - - uop_AND(ir, IREG_8(dest_reg), IREG_8(dest_reg), IREG_8(src_reg)); - } - else - { - x86seg *target_seg; + codegen_mark_code_present(block, cs + op_pc, 1); + if ((fetchdat & 0xc0) == 0xc0) { + int src_reg = fetchdat & 7; - uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc); - target_seg = codegen_generate_ea(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32, 0); - codegen_check_seg_read(block, ir, target_seg); - uop_MEM_LOAD_REG(ir, IREG_temp0_B, ireg_seg_base(target_seg), IREG_eaaddr); - uop_AND(ir, IREG_8(dest_reg), IREG_8(dest_reg), IREG_temp0_B); - } + uop_AND(ir, IREG_8(dest_reg), IREG_8(dest_reg), IREG_8(src_reg)); + } else { + x86seg *target_seg; - uop_MOV_IMM(ir, IREG_flags_op, FLAGS_ZN8); + uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc); + target_seg = codegen_generate_ea(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32, 0); + codegen_check_seg_read(block, ir, target_seg); + uop_MEM_LOAD_REG(ir, IREG_temp0_B, ireg_seg_base(target_seg), IREG_eaaddr); + uop_AND(ir, IREG_8(dest_reg), IREG_8(dest_reg), IREG_temp0_B); + } + + uop_MOV_IMM(ir, IREG_flags_op, FLAGS_ZN8); + uop_MOVZX(ir, IREG_flags_res, IREG_8(dest_reg)); + + codegen_flags_changed = 1; + return op_pc + 1; +} +uint32_t +ropAND_b_rmw(codeblock_t *block, ir_data_t *ir, UNUSED(uint8_t opcode), uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) +{ + int src_reg = (fetchdat >> 3) & 7; + + codegen_mark_code_present(block, cs + op_pc, 1); + if ((fetchdat & 0xc0) == 0xc0) { + int dest_reg = fetchdat & 7; + + uop_AND(ir, IREG_8(dest_reg), IREG_8(dest_reg), IREG_8(src_reg)); uop_MOVZX(ir, IREG_flags_res, IREG_8(dest_reg)); + } else { + x86seg *target_seg; - codegen_flags_changed = 1; - return op_pc + 1; + uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc); + target_seg = codegen_generate_ea(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32, 0); + codegen_check_seg_write(block, ir, target_seg); + + uop_MEM_LOAD_REG(ir, IREG_temp0_B, ireg_seg_base(target_seg), IREG_eaaddr); + uop_AND(ir, IREG_temp0_B, IREG_temp0_B, IREG_8(src_reg)); + uop_MEM_STORE_REG(ir, ireg_seg_base(target_seg), IREG_eaaddr, IREG_temp0_B); + uop_MOVZX(ir, IREG_flags_res, IREG_temp0_B); + } + + uop_MOV_IMM(ir, IREG_flags_op, FLAGS_ZN8); + + codegen_flags_changed = 1; + return op_pc + 1; } -uint32_t ropAND_b_rmw(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) +uint32_t +ropAND_w_rm(codeblock_t *block, ir_data_t *ir, UNUSED(uint8_t opcode), uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) { - int src_reg = (fetchdat >> 3) & 7; + int dest_reg = (fetchdat >> 3) & 7; - codegen_mark_code_present(block, cs+op_pc, 1); - if ((fetchdat & 0xc0) == 0xc0) - { - int dest_reg = fetchdat & 7; + codegen_mark_code_present(block, cs + op_pc, 1); + if ((fetchdat & 0xc0) == 0xc0) { + int src_reg = fetchdat & 7; - uop_AND(ir, IREG_8(dest_reg), IREG_8(dest_reg), IREG_8(src_reg)); - uop_MOVZX(ir, IREG_flags_res, IREG_8(dest_reg)); - } - else - { - x86seg *target_seg; + uop_AND(ir, IREG_16(dest_reg), IREG_16(dest_reg), IREG_16(src_reg)); + } else { + x86seg *target_seg; - uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc); - target_seg = codegen_generate_ea(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32, 0); - codegen_check_seg_write(block, ir, target_seg); + uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc); + target_seg = codegen_generate_ea(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32, 0); + codegen_check_seg_read(block, ir, target_seg); + uop_MEM_LOAD_REG(ir, IREG_temp0_W, ireg_seg_base(target_seg), IREG_eaaddr); + uop_AND(ir, IREG_16(dest_reg), IREG_16(dest_reg), IREG_temp0_W); + } - uop_MEM_LOAD_REG(ir, IREG_temp0_B, ireg_seg_base(target_seg), IREG_eaaddr); - uop_AND(ir, IREG_temp0_B, IREG_temp0_B, IREG_8(src_reg)); - uop_MEM_STORE_REG(ir, ireg_seg_base(target_seg), IREG_eaaddr, IREG_temp0_B); - uop_MOVZX(ir, IREG_flags_res, IREG_temp0_B); - } + uop_MOV_IMM(ir, IREG_flags_op, FLAGS_ZN16); + uop_MOVZX(ir, IREG_flags_res, IREG_16(dest_reg)); - uop_MOV_IMM(ir, IREG_flags_op, FLAGS_ZN8); - - codegen_flags_changed = 1; - return op_pc + 1; + codegen_flags_changed = 1; + return op_pc + 1; } -uint32_t ropAND_w_rm(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) +uint32_t +ropAND_w_rmw(codeblock_t *block, ir_data_t *ir, UNUSED(uint8_t opcode), uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) { - int dest_reg = (fetchdat >> 3) & 7; + int src_reg = (fetchdat >> 3) & 7; - codegen_mark_code_present(block, cs+op_pc, 1); - if ((fetchdat & 0xc0) == 0xc0) - { - int src_reg = fetchdat & 7; + codegen_mark_code_present(block, cs + op_pc, 1); + if ((fetchdat & 0xc0) == 0xc0) { + int dest_reg = fetchdat & 7; - uop_AND(ir, IREG_16(dest_reg), IREG_16(dest_reg), IREG_16(src_reg)); - } - else - { - x86seg *target_seg; - - uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc); - target_seg = codegen_generate_ea(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32, 0); - codegen_check_seg_read(block, ir, target_seg); - uop_MEM_LOAD_REG(ir, IREG_temp0_W, ireg_seg_base(target_seg), IREG_eaaddr); - uop_AND(ir, IREG_16(dest_reg), IREG_16(dest_reg), IREG_temp0_W); - } - - uop_MOV_IMM(ir, IREG_flags_op, FLAGS_ZN16); + uop_AND(ir, IREG_16(dest_reg), IREG_16(dest_reg), IREG_16(src_reg)); uop_MOVZX(ir, IREG_flags_res, IREG_16(dest_reg)); + } else { + x86seg *target_seg; - codegen_flags_changed = 1; - return op_pc + 1; + uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc); + target_seg = codegen_generate_ea(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32, 0); + codegen_check_seg_write(block, ir, target_seg); + + uop_MEM_LOAD_REG(ir, IREG_temp0_W, ireg_seg_base(target_seg), IREG_eaaddr); + uop_AND(ir, IREG_temp0_W, IREG_temp0_W, IREG_16(src_reg)); + uop_MEM_STORE_REG(ir, ireg_seg_base(target_seg), IREG_eaaddr, IREG_temp0_W); + uop_MOVZX(ir, IREG_flags_res, IREG_temp0_W); + } + + uop_MOV_IMM(ir, IREG_flags_op, FLAGS_ZN16); + + codegen_flags_changed = 1; + return op_pc + 1; } -uint32_t ropAND_w_rmw(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) +uint32_t +ropAND_l_rm(codeblock_t *block, ir_data_t *ir, UNUSED(uint8_t opcode), uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) { - int src_reg = (fetchdat >> 3) & 7; + int dest_reg = (fetchdat >> 3) & 7; - codegen_mark_code_present(block, cs+op_pc, 1); - if ((fetchdat & 0xc0) == 0xc0) - { - int dest_reg = fetchdat & 7; + codegen_mark_code_present(block, cs + op_pc, 1); + if ((fetchdat & 0xc0) == 0xc0) { + int src_reg = fetchdat & 7; - uop_AND(ir, IREG_16(dest_reg), IREG_16(dest_reg), IREG_16(src_reg)); - uop_MOVZX(ir, IREG_flags_res, IREG_16(dest_reg)); - } - else - { - x86seg *target_seg; + uop_AND(ir, IREG_32(dest_reg), IREG_32(dest_reg), IREG_32(src_reg)); + } else { + x86seg *target_seg; - uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc); - target_seg = codegen_generate_ea(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32, 0); - codegen_check_seg_write(block, ir, target_seg); + uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc); + target_seg = codegen_generate_ea(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32, 0); + codegen_check_seg_read(block, ir, target_seg); + uop_MEM_LOAD_REG(ir, IREG_temp0, ireg_seg_base(target_seg), IREG_eaaddr); + uop_AND(ir, IREG_32(dest_reg), IREG_32(dest_reg), IREG_temp0); + } - uop_MEM_LOAD_REG(ir, IREG_temp0_W, ireg_seg_base(target_seg), IREG_eaaddr); - uop_AND(ir, IREG_temp0_W, IREG_temp0_W, IREG_16(src_reg)); - uop_MEM_STORE_REG(ir, ireg_seg_base(target_seg), IREG_eaaddr, IREG_temp0_W); - uop_MOVZX(ir, IREG_flags_res, IREG_temp0_W); - } + uop_MOV_IMM(ir, IREG_flags_op, FLAGS_ZN32); + uop_MOV(ir, IREG_flags_res, IREG_32(dest_reg)); - uop_MOV_IMM(ir, IREG_flags_op, FLAGS_ZN16); - - codegen_flags_changed = 1; - return op_pc + 1; + codegen_flags_changed = 1; + return op_pc + 1; } -uint32_t ropAND_l_rm(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) +uint32_t +ropAND_l_rmw(codeblock_t *block, ir_data_t *ir, UNUSED(uint8_t opcode), uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) { - int dest_reg = (fetchdat >> 3) & 7; + int src_reg = (fetchdat >> 3) & 7; - codegen_mark_code_present(block, cs+op_pc, 1); - if ((fetchdat & 0xc0) == 0xc0) - { - int src_reg = fetchdat & 7; + codegen_mark_code_present(block, cs + op_pc, 1); + if ((fetchdat & 0xc0) == 0xc0) { + int dest_reg = fetchdat & 7; - uop_AND(ir, IREG_32(dest_reg), IREG_32(dest_reg), IREG_32(src_reg)); - } - else - { - x86seg *target_seg; - - uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc); - target_seg = codegen_generate_ea(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32, 0); - codegen_check_seg_read(block, ir, target_seg); - uop_MEM_LOAD_REG(ir, IREG_temp0, ireg_seg_base(target_seg), IREG_eaaddr); - uop_AND(ir, IREG_32(dest_reg), IREG_32(dest_reg), IREG_temp0); - } - - uop_MOV_IMM(ir, IREG_flags_op, FLAGS_ZN32); + uop_AND(ir, IREG_32(dest_reg), IREG_32(dest_reg), IREG_32(src_reg)); uop_MOV(ir, IREG_flags_res, IREG_32(dest_reg)); + } else { + x86seg *target_seg; - codegen_flags_changed = 1; - return op_pc + 1; -} -uint32_t ropAND_l_rmw(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) -{ - int src_reg = (fetchdat >> 3) & 7; + uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc); + target_seg = codegen_generate_ea(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32, 0); + codegen_check_seg_write(block, ir, target_seg); - codegen_mark_code_present(block, cs+op_pc, 1); - if ((fetchdat & 0xc0) == 0xc0) - { - int dest_reg = fetchdat & 7; + uop_MEM_LOAD_REG(ir, IREG_temp0, ireg_seg_base(target_seg), IREG_eaaddr); + uop_AND(ir, IREG_temp0, IREG_temp0, IREG_32(src_reg)); + uop_MEM_STORE_REG(ir, ireg_seg_base(target_seg), IREG_eaaddr, IREG_temp0); + uop_MOV(ir, IREG_flags_res, IREG_temp0); + } - uop_AND(ir, IREG_32(dest_reg), IREG_32(dest_reg), IREG_32(src_reg)); - uop_MOV(ir, IREG_flags_res, IREG_32(dest_reg)); - } - else - { - x86seg *target_seg; + uop_MOV_IMM(ir, IREG_flags_op, FLAGS_ZN32); - uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc); - target_seg = codegen_generate_ea(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32, 0); - codegen_check_seg_write(block, ir, target_seg); - - uop_MEM_LOAD_REG(ir, IREG_temp0, ireg_seg_base(target_seg), IREG_eaaddr); - uop_AND(ir, IREG_temp0, IREG_temp0, IREG_32(src_reg)); - uop_MEM_STORE_REG(ir, ireg_seg_base(target_seg), IREG_eaaddr, IREG_temp0); - uop_MOV(ir, IREG_flags_res, IREG_temp0); - } - - uop_MOV_IMM(ir, IREG_flags_op, FLAGS_ZN32); - - codegen_flags_changed = 1; - return op_pc + 1; + codegen_flags_changed = 1; + return op_pc + 1; } -uint32_t ropOR_AL_imm(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) +uint32_t +ropOR_AL_imm(codeblock_t *block, ir_data_t *ir, UNUSED(uint8_t opcode), uint32_t fetchdat, UNUSED(uint32_t op_32), uint32_t op_pc) { - uint8_t imm_data = fastreadb(cs + op_pc); + uint8_t imm_data = fastreadb(cs + op_pc); - uop_OR_IMM(ir, IREG_AL, IREG_AL, imm_data); - uop_MOV_IMM(ir, IREG_flags_op, FLAGS_ZN8); - uop_MOVZX(ir, IREG_flags_res, IREG_AL); + uop_OR_IMM(ir, IREG_AL, IREG_AL, imm_data); + uop_MOV_IMM(ir, IREG_flags_op, FLAGS_ZN8); + uop_MOVZX(ir, IREG_flags_res, IREG_AL); - codegen_flags_changed = 1; - codegen_mark_code_present(block, cs+op_pc, 1); - return op_pc + 1; + codegen_flags_changed = 1; + codegen_mark_code_present(block, cs + op_pc, 1); + return op_pc + 1; } -uint32_t ropOR_AX_imm(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) +uint32_t +ropOR_AX_imm(codeblock_t *block, ir_data_t *ir, UNUSED(uint8_t opcode), uint32_t fetchdat, UNUSED(uint32_t op_32), uint32_t op_pc) { - uint16_t imm_data = fastreadw(cs + op_pc); + uint16_t imm_data = fastreadw(cs + op_pc); - uop_OR_IMM(ir, IREG_AX, IREG_AX, imm_data); - uop_MOV_IMM(ir, IREG_flags_op, FLAGS_ZN16); - uop_MOVZX(ir, IREG_flags_res, IREG_AX); + uop_OR_IMM(ir, IREG_AX, IREG_AX, imm_data); + uop_MOV_IMM(ir, IREG_flags_op, FLAGS_ZN16); + uop_MOVZX(ir, IREG_flags_res, IREG_AX); - codegen_flags_changed = 1; - codegen_mark_code_present(block, cs+op_pc, 2); - return op_pc + 2; + codegen_flags_changed = 1; + codegen_mark_code_present(block, cs + op_pc, 2); + return op_pc + 2; } -uint32_t ropOR_EAX_imm(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) +uint32_t +ropOR_EAX_imm(codeblock_t *block, ir_data_t *ir, UNUSED(uint8_t opcode), uint32_t fetchdat, UNUSED(uint32_t op_32), uint32_t op_pc) { - if (block->flags & CODEBLOCK_NO_IMMEDIATES) - { - LOAD_IMMEDIATE_FROM_RAM_32(block, ir, IREG_temp0, cs + op_pc); - uop_OR(ir, IREG_EAX, IREG_EAX, IREG_temp0); - } - else - { - fetchdat = fastreadl(cs + op_pc); - codegen_mark_code_present(block, cs+op_pc, 4); - uop_OR_IMM(ir, IREG_EAX, IREG_EAX, fetchdat); - } + if (block->flags & CODEBLOCK_NO_IMMEDIATES) { + LOAD_IMMEDIATE_FROM_RAM_32(block, ir, IREG_temp0, cs + op_pc); + uop_OR(ir, IREG_EAX, IREG_EAX, IREG_temp0); + } else { + fetchdat = fastreadl(cs + op_pc); + codegen_mark_code_present(block, cs + op_pc, 4); + uop_OR_IMM(ir, IREG_EAX, IREG_EAX, fetchdat); + } - uop_MOV_IMM(ir, IREG_flags_op, FLAGS_ZN32); - uop_MOV(ir, IREG_flags_res, IREG_EAX); + uop_MOV_IMM(ir, IREG_flags_op, FLAGS_ZN32); + uop_MOV(ir, IREG_flags_res, IREG_EAX); - codegen_flags_changed = 1; - codegen_mark_code_present(block, cs+op_pc, 4); - return op_pc + 4; + codegen_flags_changed = 1; + codegen_mark_code_present(block, cs + op_pc, 4); + return op_pc + 4; } -uint32_t ropOR_b_rm(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) +uint32_t +ropOR_b_rm(codeblock_t *block, ir_data_t *ir, UNUSED(uint8_t opcode), uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) { - int dest_reg = (fetchdat >> 3) & 7; + int dest_reg = (fetchdat >> 3) & 7; - codegen_mark_code_present(block, cs+op_pc, 1); - if ((fetchdat & 0xc0) == 0xc0) - { - int src_reg = fetchdat & 7; + codegen_mark_code_present(block, cs + op_pc, 1); + if ((fetchdat & 0xc0) == 0xc0) { + int src_reg = fetchdat & 7; - uop_OR(ir, IREG_8(dest_reg), IREG_8(dest_reg), IREG_8(src_reg)); - } - else - { - x86seg *target_seg; + uop_OR(ir, IREG_8(dest_reg), IREG_8(dest_reg), IREG_8(src_reg)); + } else { + x86seg *target_seg; - uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc); - target_seg = codegen_generate_ea(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32, 0); - codegen_check_seg_read(block, ir, target_seg); - uop_MEM_LOAD_REG(ir, IREG_temp0_B, ireg_seg_base(target_seg), IREG_eaaddr); - uop_OR(ir, IREG_8(dest_reg), IREG_8(dest_reg), IREG_temp0_B); - } + uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc); + target_seg = codegen_generate_ea(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32, 0); + codegen_check_seg_read(block, ir, target_seg); + uop_MEM_LOAD_REG(ir, IREG_temp0_B, ireg_seg_base(target_seg), IREG_eaaddr); + uop_OR(ir, IREG_8(dest_reg), IREG_8(dest_reg), IREG_temp0_B); + } - uop_MOV_IMM(ir, IREG_flags_op, FLAGS_ZN8); + uop_MOV_IMM(ir, IREG_flags_op, FLAGS_ZN8); + uop_MOVZX(ir, IREG_flags_res, IREG_8(dest_reg)); + + codegen_flags_changed = 1; + return op_pc + 1; +} +uint32_t +ropOR_b_rmw(codeblock_t *block, ir_data_t *ir, UNUSED(uint8_t opcode), uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) +{ + int src_reg = (fetchdat >> 3) & 7; + + codegen_mark_code_present(block, cs + op_pc, 1); + if ((fetchdat & 0xc0) == 0xc0) { + int dest_reg = fetchdat & 7; + + uop_OR(ir, IREG_8(dest_reg), IREG_8(dest_reg), IREG_8(src_reg)); uop_MOVZX(ir, IREG_flags_res, IREG_8(dest_reg)); + } else { + x86seg *target_seg; - codegen_flags_changed = 1; - return op_pc + 1; + uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc); + target_seg = codegen_generate_ea(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32, 0); + codegen_check_seg_write(block, ir, target_seg); + + uop_MEM_LOAD_REG(ir, IREG_temp0_B, ireg_seg_base(target_seg), IREG_eaaddr); + uop_OR(ir, IREG_temp0_B, IREG_temp0_B, IREG_8(src_reg)); + uop_MEM_STORE_REG(ir, ireg_seg_base(target_seg), IREG_eaaddr, IREG_temp0_B); + uop_MOVZX(ir, IREG_flags_res, IREG_temp0_B); + } + + uop_MOV_IMM(ir, IREG_flags_op, FLAGS_ZN8); + + codegen_flags_changed = 1; + return op_pc + 1; } -uint32_t ropOR_b_rmw(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) +uint32_t +ropOR_w_rm(codeblock_t *block, ir_data_t *ir, UNUSED(uint8_t opcode), uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) { - int src_reg = (fetchdat >> 3) & 7; + int dest_reg = (fetchdat >> 3) & 7; - codegen_mark_code_present(block, cs+op_pc, 1); - if ((fetchdat & 0xc0) == 0xc0) - { - int dest_reg = fetchdat & 7; + codegen_mark_code_present(block, cs + op_pc, 1); + if ((fetchdat & 0xc0) == 0xc0) { + int src_reg = fetchdat & 7; - uop_OR(ir, IREG_8(dest_reg), IREG_8(dest_reg), IREG_8(src_reg)); - uop_MOVZX(ir, IREG_flags_res, IREG_8(dest_reg)); - } - else - { - x86seg *target_seg; + uop_OR(ir, IREG_16(dest_reg), IREG_16(dest_reg), IREG_16(src_reg)); + } else { + x86seg *target_seg; - uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc); - target_seg = codegen_generate_ea(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32, 0); - codegen_check_seg_write(block, ir, target_seg); + uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc); + target_seg = codegen_generate_ea(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32, 0); + codegen_check_seg_read(block, ir, target_seg); + uop_MEM_LOAD_REG(ir, IREG_temp0_W, ireg_seg_base(target_seg), IREG_eaaddr); + uop_OR(ir, IREG_16(dest_reg), IREG_16(dest_reg), IREG_temp0_W); + } - uop_MEM_LOAD_REG(ir, IREG_temp0_B, ireg_seg_base(target_seg), IREG_eaaddr); - uop_OR(ir, IREG_temp0_B, IREG_temp0_B, IREG_8(src_reg)); - uop_MEM_STORE_REG(ir, ireg_seg_base(target_seg), IREG_eaaddr, IREG_temp0_B); - uop_MOVZX(ir, IREG_flags_res, IREG_temp0_B); - } + uop_MOV_IMM(ir, IREG_flags_op, FLAGS_ZN16); + uop_MOVZX(ir, IREG_flags_res, IREG_16(dest_reg)); - uop_MOV_IMM(ir, IREG_flags_op, FLAGS_ZN8); - - codegen_flags_changed = 1; - return op_pc + 1; + codegen_flags_changed = 1; + return op_pc + 1; } -uint32_t ropOR_w_rm(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) +uint32_t +ropOR_w_rmw(codeblock_t *block, ir_data_t *ir, UNUSED(uint8_t opcode), uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) { - int dest_reg = (fetchdat >> 3) & 7; + int src_reg = (fetchdat >> 3) & 7; - codegen_mark_code_present(block, cs+op_pc, 1); - if ((fetchdat & 0xc0) == 0xc0) - { - int src_reg = fetchdat & 7; + codegen_mark_code_present(block, cs + op_pc, 1); + if ((fetchdat & 0xc0) == 0xc0) { + int dest_reg = fetchdat & 7; - uop_OR(ir, IREG_16(dest_reg), IREG_16(dest_reg), IREG_16(src_reg)); - } - else - { - x86seg *target_seg; - - uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc); - target_seg = codegen_generate_ea(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32, 0); - codegen_check_seg_read(block, ir, target_seg); - uop_MEM_LOAD_REG(ir, IREG_temp0_W, ireg_seg_base(target_seg), IREG_eaaddr); - uop_OR(ir, IREG_16(dest_reg), IREG_16(dest_reg), IREG_temp0_W); - } - - uop_MOV_IMM(ir, IREG_flags_op, FLAGS_ZN16); + uop_OR(ir, IREG_16(dest_reg), IREG_16(dest_reg), IREG_16(src_reg)); uop_MOVZX(ir, IREG_flags_res, IREG_16(dest_reg)); + } else { + x86seg *target_seg; - codegen_flags_changed = 1; - return op_pc + 1; + uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc); + target_seg = codegen_generate_ea(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32, 0); + codegen_check_seg_write(block, ir, target_seg); + + uop_MEM_LOAD_REG(ir, IREG_temp0_W, ireg_seg_base(target_seg), IREG_eaaddr); + uop_OR(ir, IREG_temp0_W, IREG_temp0_W, IREG_16(src_reg)); + uop_MEM_STORE_REG(ir, ireg_seg_base(target_seg), IREG_eaaddr, IREG_temp0_W); + uop_MOVZX(ir, IREG_flags_res, IREG_temp0_W); + } + + uop_MOV_IMM(ir, IREG_flags_op, FLAGS_ZN16); + + codegen_flags_changed = 1; + return op_pc + 1; } -uint32_t ropOR_w_rmw(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) +uint32_t +ropOR_l_rm(codeblock_t *block, ir_data_t *ir, UNUSED(uint8_t opcode), uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) { - int src_reg = (fetchdat >> 3) & 7; + int dest_reg = (fetchdat >> 3) & 7; - codegen_mark_code_present(block, cs+op_pc, 1); - if ((fetchdat & 0xc0) == 0xc0) - { - int dest_reg = fetchdat & 7; + codegen_mark_code_present(block, cs + op_pc, 1); + if ((fetchdat & 0xc0) == 0xc0) { + int src_reg = fetchdat & 7; - uop_OR(ir, IREG_16(dest_reg), IREG_16(dest_reg), IREG_16(src_reg)); - uop_MOVZX(ir, IREG_flags_res, IREG_16(dest_reg)); - } - else - { - x86seg *target_seg; + uop_OR(ir, IREG_32(dest_reg), IREG_32(dest_reg), IREG_32(src_reg)); + } else { + x86seg *target_seg; - uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc); - target_seg = codegen_generate_ea(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32, 0); - codegen_check_seg_write(block, ir, target_seg); + uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc); + target_seg = codegen_generate_ea(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32, 0); + codegen_check_seg_read(block, ir, target_seg); + uop_MEM_LOAD_REG(ir, IREG_temp0, ireg_seg_base(target_seg), IREG_eaaddr); + uop_OR(ir, IREG_32(dest_reg), IREG_32(dest_reg), IREG_temp0); + } - uop_MEM_LOAD_REG(ir, IREG_temp0_W, ireg_seg_base(target_seg), IREG_eaaddr); - uop_OR(ir, IREG_temp0_W, IREG_temp0_W, IREG_16(src_reg)); - uop_MEM_STORE_REG(ir, ireg_seg_base(target_seg), IREG_eaaddr, IREG_temp0_W); - uop_MOVZX(ir, IREG_flags_res, IREG_temp0_W); - } + uop_MOV_IMM(ir, IREG_flags_op, FLAGS_ZN32); + uop_MOV(ir, IREG_flags_res, dest_reg); - uop_MOV_IMM(ir, IREG_flags_op, FLAGS_ZN16); - - codegen_flags_changed = 1; - return op_pc + 1; + codegen_flags_changed = 1; + return op_pc + 1; } -uint32_t ropOR_l_rm(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) +uint32_t +ropOR_l_rmw(codeblock_t *block, ir_data_t *ir, UNUSED(uint8_t opcode), uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) { - int dest_reg = (fetchdat >> 3) & 7; + int src_reg = (fetchdat >> 3) & 7; - codegen_mark_code_present(block, cs+op_pc, 1); - if ((fetchdat & 0xc0) == 0xc0) - { - int src_reg = fetchdat & 7; + codegen_mark_code_present(block, cs + op_pc, 1); + if ((fetchdat & 0xc0) == 0xc0) { + int dest_reg = fetchdat & 7; - uop_OR(ir, IREG_32(dest_reg), IREG_32(dest_reg), IREG_32(src_reg)); - } - else - { - x86seg *target_seg; + uop_OR(ir, IREG_32(dest_reg), IREG_32(dest_reg), IREG_32(src_reg)); + uop_MOV(ir, IREG_flags_res, IREG_32(dest_reg)); + } else { + x86seg *target_seg; - uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc); - target_seg = codegen_generate_ea(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32, 0); - codegen_check_seg_read(block, ir, target_seg); - uop_MEM_LOAD_REG(ir, IREG_temp0, ireg_seg_base(target_seg), IREG_eaaddr); - uop_OR(ir, IREG_32(dest_reg), IREG_32(dest_reg), IREG_temp0); - } + uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc); + target_seg = codegen_generate_ea(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32, 0); + codegen_check_seg_write(block, ir, target_seg); - uop_MOV_IMM(ir, IREG_flags_op, FLAGS_ZN32); - uop_MOV(ir, IREG_flags_res, dest_reg); + uop_MEM_LOAD_REG(ir, IREG_temp0, ireg_seg_base(target_seg), IREG_eaaddr); + uop_OR(ir, IREG_temp0, IREG_temp0, IREG_32(src_reg)); + uop_MEM_STORE_REG(ir, ireg_seg_base(target_seg), IREG_eaaddr, IREG_temp0); + uop_MOV(ir, IREG_flags_res, IREG_temp0); + } - codegen_flags_changed = 1; - return op_pc + 1; -} -uint32_t ropOR_l_rmw(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) -{ - int src_reg = (fetchdat >> 3) & 7; + uop_MOV_IMM(ir, IREG_flags_op, FLAGS_ZN32); - codegen_mark_code_present(block, cs+op_pc, 1); - if ((fetchdat & 0xc0) == 0xc0) - { - int dest_reg = fetchdat & 7; - - uop_OR(ir, IREG_32(dest_reg), IREG_32(dest_reg), IREG_32(src_reg)); - uop_MOV(ir, IREG_flags_res, IREG_32(dest_reg)); - } - else - { - x86seg *target_seg; - - uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc); - target_seg = codegen_generate_ea(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32, 0); - codegen_check_seg_write(block, ir, target_seg); - - uop_MEM_LOAD_REG(ir, IREG_temp0, ireg_seg_base(target_seg), IREG_eaaddr); - uop_OR(ir, IREG_temp0, IREG_temp0, IREG_32(src_reg)); - uop_MEM_STORE_REG(ir, ireg_seg_base(target_seg), IREG_eaaddr, IREG_temp0); - uop_MOV(ir, IREG_flags_res, IREG_temp0); - } - - uop_MOV_IMM(ir, IREG_flags_op, FLAGS_ZN32); - - codegen_flags_changed = 1; - return op_pc + 1; + codegen_flags_changed = 1; + return op_pc + 1; } -uint32_t ropTEST_AL_imm(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) +uint32_t +ropTEST_AL_imm(codeblock_t *block, ir_data_t *ir, UNUSED(uint8_t opcode), uint32_t fetchdat, UNUSED(uint32_t op_32), uint32_t op_pc) { - uint8_t imm_data = fastreadb(cs + op_pc); + uint8_t imm_data = fastreadb(cs + op_pc); - uop_AND_IMM(ir, IREG_flags_res, IREG_EAX, imm_data); - uop_MOV_IMM(ir, IREG_flags_op, FLAGS_ZN8); + uop_AND_IMM(ir, IREG_flags_res, IREG_EAX, imm_data); + uop_MOV_IMM(ir, IREG_flags_op, FLAGS_ZN8); - codegen_flags_changed = 1; - codegen_mark_code_present(block, cs+op_pc, 1); - return op_pc + 1; + codegen_flags_changed = 1; + codegen_mark_code_present(block, cs + op_pc, 1); + return op_pc + 1; } -uint32_t ropTEST_AX_imm(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) +uint32_t +ropTEST_AX_imm(codeblock_t *block, ir_data_t *ir, UNUSED(uint8_t opcode), uint32_t fetchdat, UNUSED(uint32_t op_32), uint32_t op_pc) { - uint16_t imm_data = fastreadw(cs + op_pc); + uint16_t imm_data = fastreadw(cs + op_pc); - uop_AND_IMM(ir, IREG_flags_res, IREG_EAX, imm_data); - uop_MOV_IMM(ir, IREG_flags_op, FLAGS_ZN16); + uop_AND_IMM(ir, IREG_flags_res, IREG_EAX, imm_data); + uop_MOV_IMM(ir, IREG_flags_op, FLAGS_ZN16); - codegen_flags_changed = 1; - codegen_mark_code_present(block, cs+op_pc, 2); - return op_pc + 2; + codegen_flags_changed = 1; + codegen_mark_code_present(block, cs + op_pc, 2); + return op_pc + 2; } -uint32_t ropTEST_EAX_imm(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) +uint32_t +ropTEST_EAX_imm(codeblock_t *block, ir_data_t *ir, UNUSED(uint8_t opcode), uint32_t fetchdat, UNUSED(uint32_t op_32), uint32_t op_pc) { - if (block->flags & CODEBLOCK_NO_IMMEDIATES) - { - LOAD_IMMEDIATE_FROM_RAM_32(block, ir, IREG_temp0, cs + op_pc); - uop_AND(ir, IREG_flags_res, IREG_EAX, IREG_temp0); - } - else - { - fetchdat = fastreadl(cs + op_pc); - codegen_mark_code_present(block, cs+op_pc, 4); - uop_AND_IMM(ir, IREG_flags_res, IREG_EAX, fetchdat); - } + if (block->flags & CODEBLOCK_NO_IMMEDIATES) { + LOAD_IMMEDIATE_FROM_RAM_32(block, ir, IREG_temp0, cs + op_pc); + uop_AND(ir, IREG_flags_res, IREG_EAX, IREG_temp0); + } else { + fetchdat = fastreadl(cs + op_pc); + codegen_mark_code_present(block, cs + op_pc, 4); + uop_AND_IMM(ir, IREG_flags_res, IREG_EAX, fetchdat); + } - uop_MOV_IMM(ir, IREG_flags_op, FLAGS_ZN32); + uop_MOV_IMM(ir, IREG_flags_op, FLAGS_ZN32); - codegen_flags_changed = 1; - codegen_mark_code_present(block, cs+op_pc, 4); - return op_pc + 4; + codegen_flags_changed = 1; + codegen_mark_code_present(block, cs + op_pc, 4); + return op_pc + 4; } -uint32_t ropTEST_b_rm(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) +uint32_t +ropTEST_b_rm(codeblock_t *block, ir_data_t *ir, UNUSED(uint8_t opcode), uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) { - int dest_reg = (fetchdat >> 3) & 7; + int dest_reg = (fetchdat >> 3) & 7; - codegen_mark_code_present(block, cs+op_pc, 1); - if ((fetchdat & 0xc0) == 0xc0) - { - int src_reg = fetchdat & 7; + codegen_mark_code_present(block, cs + op_pc, 1); + if ((fetchdat & 0xc0) == 0xc0) { + int src_reg = fetchdat & 7; - uop_AND(ir, IREG_flags_res_B, IREG_8(dest_reg), IREG_8(src_reg)); - } - else - { - x86seg *target_seg; + uop_AND(ir, IREG_flags_res_B, IREG_8(dest_reg), IREG_8(src_reg)); + } else { + x86seg *target_seg; - uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc); - target_seg = codegen_generate_ea(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32, 0); - codegen_check_seg_read(block, ir, target_seg); - uop_MEM_LOAD_REG(ir, IREG_temp0_B, ireg_seg_base(target_seg), IREG_eaaddr); - uop_AND(ir, IREG_flags_res_B, IREG_8(dest_reg), IREG_temp0_B); - } + uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc); + target_seg = codegen_generate_ea(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32, 0); + codegen_check_seg_read(block, ir, target_seg); + uop_MEM_LOAD_REG(ir, IREG_temp0_B, ireg_seg_base(target_seg), IREG_eaaddr); + uop_AND(ir, IREG_flags_res_B, IREG_8(dest_reg), IREG_temp0_B); + } - uop_MOVZX(ir, IREG_flags_res, IREG_flags_res_B); - uop_MOV_IMM(ir, IREG_flags_op, FLAGS_ZN8); + uop_MOVZX(ir, IREG_flags_res, IREG_flags_res_B); + uop_MOV_IMM(ir, IREG_flags_op, FLAGS_ZN8); - codegen_flags_changed = 1; - return op_pc + 1; + codegen_flags_changed = 1; + return op_pc + 1; } -uint32_t ropTEST_w_rm(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) +uint32_t +ropTEST_w_rm(codeblock_t *block, ir_data_t *ir, UNUSED(uint8_t opcode), uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) { - int dest_reg = (fetchdat >> 3) & 7; + int dest_reg = (fetchdat >> 3) & 7; - codegen_mark_code_present(block, cs+op_pc, 1); - if ((fetchdat & 0xc0) == 0xc0) - { - int src_reg = fetchdat & 7; + codegen_mark_code_present(block, cs + op_pc, 1); + if ((fetchdat & 0xc0) == 0xc0) { + int src_reg = fetchdat & 7; - uop_AND(ir, IREG_flags_res_W, IREG_16(dest_reg), IREG_16(src_reg)); - } - else - { - x86seg *target_seg; + uop_AND(ir, IREG_flags_res_W, IREG_16(dest_reg), IREG_16(src_reg)); + } else { + x86seg *target_seg; - uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc); - target_seg = codegen_generate_ea(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32, 0); - codegen_check_seg_read(block, ir, target_seg); - uop_MEM_LOAD_REG(ir, IREG_temp0_W, ireg_seg_base(target_seg), IREG_eaaddr); - uop_AND(ir, IREG_flags_res_W, IREG_16(dest_reg), IREG_temp0_W); - } + uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc); + target_seg = codegen_generate_ea(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32, 0); + codegen_check_seg_read(block, ir, target_seg); + uop_MEM_LOAD_REG(ir, IREG_temp0_W, ireg_seg_base(target_seg), IREG_eaaddr); + uop_AND(ir, IREG_flags_res_W, IREG_16(dest_reg), IREG_temp0_W); + } - uop_MOVZX(ir, IREG_flags_res, IREG_flags_res_W); - uop_MOV_IMM(ir, IREG_flags_op, FLAGS_ZN16); + uop_MOVZX(ir, IREG_flags_res, IREG_flags_res_W); + uop_MOV_IMM(ir, IREG_flags_op, FLAGS_ZN16); - codegen_flags_changed = 1; - return op_pc + 1; + codegen_flags_changed = 1; + return op_pc + 1; } -uint32_t ropTEST_l_rm(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) +uint32_t +ropTEST_l_rm(codeblock_t *block, ir_data_t *ir, UNUSED(uint8_t opcode), uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) { - int dest_reg = (fetchdat >> 3) & 7; + int dest_reg = (fetchdat >> 3) & 7; - codegen_mark_code_present(block, cs+op_pc, 1); - if ((fetchdat & 0xc0) == 0xc0) - { - int src_reg = fetchdat & 7; + codegen_mark_code_present(block, cs + op_pc, 1); + if ((fetchdat & 0xc0) == 0xc0) { + int src_reg = fetchdat & 7; - uop_AND(ir, IREG_flags_res, IREG_32(dest_reg), IREG_32(src_reg)); - } - else - { - x86seg *target_seg; + uop_AND(ir, IREG_flags_res, IREG_32(dest_reg), IREG_32(src_reg)); + } else { + x86seg *target_seg; - uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc); - target_seg = codegen_generate_ea(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32, 0); - codegen_check_seg_read(block, ir, target_seg); - uop_MEM_LOAD_REG(ir, IREG_temp0, ireg_seg_base(target_seg), IREG_eaaddr); - uop_AND(ir, IREG_flags_res, IREG_32(dest_reg), IREG_temp0); - } + uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc); + target_seg = codegen_generate_ea(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32, 0); + codegen_check_seg_read(block, ir, target_seg); + uop_MEM_LOAD_REG(ir, IREG_temp0, ireg_seg_base(target_seg), IREG_eaaddr); + uop_AND(ir, IREG_flags_res, IREG_32(dest_reg), IREG_temp0); + } - uop_MOV_IMM(ir, IREG_flags_op, FLAGS_ZN32); + uop_MOV_IMM(ir, IREG_flags_op, FLAGS_ZN32); - codegen_flags_changed = 1; - return op_pc + 1; + codegen_flags_changed = 1; + return op_pc + 1; } -uint32_t ropXOR_AL_imm(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) +uint32_t +ropXOR_AL_imm(codeblock_t *block, ir_data_t *ir, UNUSED(uint8_t opcode), uint32_t fetchdat, UNUSED(uint32_t op_32), uint32_t op_pc) { - uint8_t imm_data = fastreadb(cs + op_pc); + uint8_t imm_data = fastreadb(cs + op_pc); - uop_XOR_IMM(ir, IREG_AL, IREG_AL, imm_data); - uop_MOV_IMM(ir, IREG_flags_op, FLAGS_ZN8); - uop_MOVZX(ir, IREG_flags_res, IREG_AL); + uop_XOR_IMM(ir, IREG_AL, IREG_AL, imm_data); + uop_MOV_IMM(ir, IREG_flags_op, FLAGS_ZN8); + uop_MOVZX(ir, IREG_flags_res, IREG_AL); - codegen_flags_changed = 1; - codegen_mark_code_present(block, cs+op_pc, 1); - return op_pc + 1; + codegen_flags_changed = 1; + codegen_mark_code_present(block, cs + op_pc, 1); + return op_pc + 1; } -uint32_t ropXOR_AX_imm(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) +uint32_t +ropXOR_AX_imm(codeblock_t *block, ir_data_t *ir, UNUSED(uint8_t opcode), uint32_t fetchdat, UNUSED(uint32_t op_32), uint32_t op_pc) { - uint16_t imm_data = fastreadw(cs + op_pc); + uint16_t imm_data = fastreadw(cs + op_pc); - uop_XOR_IMM(ir, IREG_AX, IREG_AX, imm_data); - uop_MOV_IMM(ir, IREG_flags_op, FLAGS_ZN16); - uop_MOVZX(ir, IREG_flags_res, IREG_AX); + uop_XOR_IMM(ir, IREG_AX, IREG_AX, imm_data); + uop_MOV_IMM(ir, IREG_flags_op, FLAGS_ZN16); + uop_MOVZX(ir, IREG_flags_res, IREG_AX); - codegen_flags_changed = 1; - codegen_mark_code_present(block, cs+op_pc, 2); - return op_pc + 2; + codegen_flags_changed = 1; + codegen_mark_code_present(block, cs + op_pc, 2); + return op_pc + 2; } -uint32_t ropXOR_EAX_imm(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) +uint32_t +ropXOR_EAX_imm(codeblock_t *block, ir_data_t *ir, UNUSED(uint8_t opcode), uint32_t fetchdat, UNUSED(uint32_t op_32), uint32_t op_pc) { - if (block->flags & CODEBLOCK_NO_IMMEDIATES) - { - LOAD_IMMEDIATE_FROM_RAM_32(block, ir, IREG_temp0, cs + op_pc); - uop_XOR(ir, IREG_EAX, IREG_EAX, IREG_temp0); - } - else - { - fetchdat = fastreadl(cs + op_pc); - codegen_mark_code_present(block, cs+op_pc, 4); - uop_XOR_IMM(ir, IREG_EAX, IREG_EAX, fetchdat); - } + if (block->flags & CODEBLOCK_NO_IMMEDIATES) { + LOAD_IMMEDIATE_FROM_RAM_32(block, ir, IREG_temp0, cs + op_pc); + uop_XOR(ir, IREG_EAX, IREG_EAX, IREG_temp0); + } else { + fetchdat = fastreadl(cs + op_pc); + codegen_mark_code_present(block, cs + op_pc, 4); + uop_XOR_IMM(ir, IREG_EAX, IREG_EAX, fetchdat); + } - uop_MOV_IMM(ir, IREG_flags_op, FLAGS_ZN32); - uop_MOV(ir, IREG_flags_res, IREG_EAX); + uop_MOV_IMM(ir, IREG_flags_op, FLAGS_ZN32); + uop_MOV(ir, IREG_flags_res, IREG_EAX); - codegen_flags_changed = 1; - codegen_mark_code_present(block, cs+op_pc, 4); - return op_pc + 4; + codegen_flags_changed = 1; + codegen_mark_code_present(block, cs + op_pc, 4); + return op_pc + 4; } -uint32_t ropXOR_b_rm(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) +uint32_t +ropXOR_b_rm(codeblock_t *block, ir_data_t *ir, UNUSED(uint8_t opcode), uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) { - int dest_reg = (fetchdat >> 3) & 7; + int dest_reg = (fetchdat >> 3) & 7; - codegen_mark_code_present(block, cs+op_pc, 1); - if ((fetchdat & 0xc0) == 0xc0) - { - int src_reg = fetchdat & 7; + codegen_mark_code_present(block, cs + op_pc, 1); + if ((fetchdat & 0xc0) == 0xc0) { + int src_reg = fetchdat & 7; - uop_XOR(ir, IREG_8(dest_reg), IREG_8(dest_reg), IREG_8(src_reg)); - } - else - { - x86seg *target_seg; + uop_XOR(ir, IREG_8(dest_reg), IREG_8(dest_reg), IREG_8(src_reg)); + } else { + x86seg *target_seg; - uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc); - target_seg = codegen_generate_ea(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32, 0); - codegen_check_seg_read(block, ir, target_seg); - uop_MEM_LOAD_REG(ir, IREG_temp0_B, ireg_seg_base(target_seg), IREG_eaaddr); - uop_XOR(ir, IREG_8(dest_reg), IREG_8(dest_reg), IREG_temp0_B); - } + uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc); + target_seg = codegen_generate_ea(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32, 0); + codegen_check_seg_read(block, ir, target_seg); + uop_MEM_LOAD_REG(ir, IREG_temp0_B, ireg_seg_base(target_seg), IREG_eaaddr); + uop_XOR(ir, IREG_8(dest_reg), IREG_8(dest_reg), IREG_temp0_B); + } - uop_MOV_IMM(ir, IREG_flags_op, FLAGS_ZN8); + uop_MOV_IMM(ir, IREG_flags_op, FLAGS_ZN8); + uop_MOVZX(ir, IREG_flags_res, IREG_8(dest_reg)); + + codegen_flags_changed = 1; + return op_pc + 1; +} +uint32_t +ropXOR_b_rmw(codeblock_t *block, ir_data_t *ir, UNUSED(uint8_t opcode), uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) +{ + int src_reg = (fetchdat >> 3) & 7; + + codegen_mark_code_present(block, cs + op_pc, 1); + if ((fetchdat & 0xc0) == 0xc0) { + int dest_reg = fetchdat & 7; + + uop_XOR(ir, IREG_8(dest_reg), IREG_8(dest_reg), IREG_8(src_reg)); uop_MOVZX(ir, IREG_flags_res, IREG_8(dest_reg)); + } else { + x86seg *target_seg; - codegen_flags_changed = 1; - return op_pc + 1; + uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc); + target_seg = codegen_generate_ea(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32, 0); + codegen_check_seg_write(block, ir, target_seg); + + uop_MEM_LOAD_REG(ir, IREG_temp0_B, ireg_seg_base(target_seg), IREG_eaaddr); + uop_XOR(ir, IREG_temp0_B, IREG_temp0_B, IREG_8(src_reg)); + uop_MEM_STORE_REG(ir, ireg_seg_base(target_seg), IREG_eaaddr, IREG_temp0_B); + uop_MOVZX(ir, IREG_flags_res, IREG_temp0_B); + } + + uop_MOV_IMM(ir, IREG_flags_op, FLAGS_ZN8); + + codegen_flags_changed = 1; + return op_pc + 1; } -uint32_t ropXOR_b_rmw(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) +uint32_t +ropXOR_w_rm(codeblock_t *block, ir_data_t *ir, UNUSED(uint8_t opcode), uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) { - int src_reg = (fetchdat >> 3) & 7; + int dest_reg = (fetchdat >> 3) & 7; - codegen_mark_code_present(block, cs+op_pc, 1); - if ((fetchdat & 0xc0) == 0xc0) - { - int dest_reg = fetchdat & 7; + codegen_mark_code_present(block, cs + op_pc, 1); + if ((fetchdat & 0xc0) == 0xc0) { + int src_reg = fetchdat & 7; - uop_XOR(ir, IREG_8(dest_reg), IREG_8(dest_reg), IREG_8(src_reg)); - uop_MOVZX(ir, IREG_flags_res, IREG_8(dest_reg)); - } - else - { - x86seg *target_seg; + uop_XOR(ir, IREG_16(dest_reg), IREG_16(dest_reg), IREG_16(src_reg)); + } else { + x86seg *target_seg; - uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc); - target_seg = codegen_generate_ea(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32, 0); - codegen_check_seg_write(block, ir, target_seg); + uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc); + target_seg = codegen_generate_ea(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32, 0); + codegen_check_seg_read(block, ir, target_seg); + uop_MEM_LOAD_REG(ir, IREG_temp0_W, ireg_seg_base(target_seg), IREG_eaaddr); + uop_XOR(ir, IREG_16(dest_reg), IREG_16(dest_reg), IREG_temp0_W); + } - uop_MEM_LOAD_REG(ir, IREG_temp0_B, ireg_seg_base(target_seg), IREG_eaaddr); - uop_XOR(ir, IREG_temp0_B, IREG_temp0_B, IREG_8(src_reg)); - uop_MEM_STORE_REG(ir, ireg_seg_base(target_seg), IREG_eaaddr, IREG_temp0_B); - uop_MOVZX(ir, IREG_flags_res, IREG_temp0_B); - } + uop_MOV_IMM(ir, IREG_flags_op, FLAGS_ZN16); + uop_MOVZX(ir, IREG_flags_res, IREG_16(dest_reg)); - uop_MOV_IMM(ir, IREG_flags_op, FLAGS_ZN8); - - codegen_flags_changed = 1; - return op_pc + 1; + codegen_flags_changed = 1; + return op_pc + 1; } -uint32_t ropXOR_w_rm(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) +uint32_t +ropXOR_w_rmw(codeblock_t *block, ir_data_t *ir, UNUSED(uint8_t opcode), uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) { - int dest_reg = (fetchdat >> 3) & 7; + int src_reg = (fetchdat >> 3) & 7; - codegen_mark_code_present(block, cs+op_pc, 1); - if ((fetchdat & 0xc0) == 0xc0) - { - int src_reg = fetchdat & 7; + codegen_mark_code_present(block, cs + op_pc, 1); + if ((fetchdat & 0xc0) == 0xc0) { + int dest_reg = fetchdat & 7; - uop_XOR(ir, IREG_16(dest_reg), IREG_16(dest_reg), IREG_16(src_reg)); - } - else - { - x86seg *target_seg; - - uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc); - target_seg = codegen_generate_ea(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32, 0); - codegen_check_seg_read(block, ir, target_seg); - uop_MEM_LOAD_REG(ir, IREG_temp0_W, ireg_seg_base(target_seg), IREG_eaaddr); - uop_XOR(ir, IREG_16(dest_reg), IREG_16(dest_reg), IREG_temp0_W); - } - - uop_MOV_IMM(ir, IREG_flags_op, FLAGS_ZN16); + uop_XOR(ir, IREG_16(dest_reg), IREG_16(dest_reg), IREG_16(src_reg)); uop_MOVZX(ir, IREG_flags_res, IREG_16(dest_reg)); + } else { + x86seg *target_seg; - codegen_flags_changed = 1; - return op_pc + 1; + uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc); + target_seg = codegen_generate_ea(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32, 0); + codegen_check_seg_write(block, ir, target_seg); + + uop_MEM_LOAD_REG(ir, IREG_temp0_W, ireg_seg_base(target_seg), IREG_eaaddr); + uop_XOR(ir, IREG_temp0_W, IREG_temp0_W, IREG_16(src_reg)); + uop_MEM_STORE_REG(ir, ireg_seg_base(target_seg), IREG_eaaddr, IREG_temp0_W); + uop_MOVZX(ir, IREG_flags_res, IREG_temp0_W); + } + + uop_MOV_IMM(ir, IREG_flags_op, FLAGS_ZN16); + + codegen_flags_changed = 1; + return op_pc + 1; } -uint32_t ropXOR_w_rmw(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) +uint32_t +ropXOR_l_rm(codeblock_t *block, ir_data_t *ir, UNUSED(uint8_t opcode), uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) { - int src_reg = (fetchdat >> 3) & 7; + int dest_reg = (fetchdat >> 3) & 7; - codegen_mark_code_present(block, cs+op_pc, 1); - if ((fetchdat & 0xc0) == 0xc0) - { - int dest_reg = fetchdat & 7; + codegen_mark_code_present(block, cs + op_pc, 1); + if ((fetchdat & 0xc0) == 0xc0) { + int src_reg = fetchdat & 7; - uop_XOR(ir, IREG_16(dest_reg), IREG_16(dest_reg), IREG_16(src_reg)); - uop_MOVZX(ir, IREG_flags_res, IREG_16(dest_reg)); - } - else - { - x86seg *target_seg; + uop_XOR(ir, IREG_32(dest_reg), IREG_32(dest_reg), IREG_32(src_reg)); + } else { + x86seg *target_seg; - uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc); - target_seg = codegen_generate_ea(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32, 0); - codegen_check_seg_write(block, ir, target_seg); + uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc); + target_seg = codegen_generate_ea(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32, 0); + codegen_check_seg_read(block, ir, target_seg); + uop_MEM_LOAD_REG(ir, IREG_temp0, ireg_seg_base(target_seg), IREG_eaaddr); + uop_XOR(ir, IREG_32(dest_reg), IREG_32(dest_reg), IREG_temp0); + } - uop_MEM_LOAD_REG(ir, IREG_temp0_W, ireg_seg_base(target_seg), IREG_eaaddr); - uop_XOR(ir, IREG_temp0_W, IREG_temp0_W, IREG_16(src_reg)); - uop_MEM_STORE_REG(ir, ireg_seg_base(target_seg), IREG_eaaddr, IREG_temp0_W); - uop_MOVZX(ir, IREG_flags_res, IREG_temp0_W); - } + uop_MOV_IMM(ir, IREG_flags_op, FLAGS_ZN32); + uop_MOV(ir, IREG_flags_res, dest_reg); - uop_MOV_IMM(ir, IREG_flags_op, FLAGS_ZN16); - - codegen_flags_changed = 1; - return op_pc + 1; + codegen_flags_changed = 1; + return op_pc + 1; } -uint32_t ropXOR_l_rm(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) +uint32_t +ropXOR_l_rmw(codeblock_t *block, ir_data_t *ir, UNUSED(uint8_t opcode), uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) { - int dest_reg = (fetchdat >> 3) & 7; + int src_reg = (fetchdat >> 3) & 7; - codegen_mark_code_present(block, cs+op_pc, 1); - if ((fetchdat & 0xc0) == 0xc0) - { - int src_reg = fetchdat & 7; + codegen_mark_code_present(block, cs + op_pc, 1); + if ((fetchdat & 0xc0) == 0xc0) { + int dest_reg = fetchdat & 7; - uop_XOR(ir, IREG_32(dest_reg), IREG_32(dest_reg), IREG_32(src_reg)); - } - else - { - x86seg *target_seg; + uop_XOR(ir, IREG_32(dest_reg), IREG_32(dest_reg), IREG_32(src_reg)); + uop_MOV(ir, IREG_flags_res, IREG_32(dest_reg)); + } else { + x86seg *target_seg; - uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc); - target_seg = codegen_generate_ea(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32, 0); - codegen_check_seg_read(block, ir, target_seg); - uop_MEM_LOAD_REG(ir, IREG_temp0, ireg_seg_base(target_seg), IREG_eaaddr); - uop_XOR(ir, IREG_32(dest_reg), IREG_32(dest_reg), IREG_temp0); - } + uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc); + target_seg = codegen_generate_ea(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32, 0); + codegen_check_seg_write(block, ir, target_seg); - uop_MOV_IMM(ir, IREG_flags_op, FLAGS_ZN32); - uop_MOV(ir, IREG_flags_res, dest_reg); + uop_MEM_LOAD_REG(ir, IREG_temp0, ireg_seg_base(target_seg), IREG_eaaddr); + uop_XOR(ir, IREG_temp0, IREG_temp0, IREG_32(src_reg)); + uop_MEM_STORE_REG(ir, ireg_seg_base(target_seg), IREG_eaaddr, IREG_temp0); + uop_MOV(ir, IREG_flags_res, IREG_temp0); + } - codegen_flags_changed = 1; - return op_pc + 1; -} -uint32_t ropXOR_l_rmw(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) -{ - int src_reg = (fetchdat >> 3) & 7; - - codegen_mark_code_present(block, cs+op_pc, 1); - if ((fetchdat & 0xc0) == 0xc0) - { - int dest_reg = fetchdat & 7; - - uop_XOR(ir, IREG_32(dest_reg), IREG_32(dest_reg), IREG_32(src_reg)); - uop_MOV(ir, IREG_flags_res, IREG_32(dest_reg)); - } - else - { - x86seg *target_seg; - - uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc); - target_seg = codegen_generate_ea(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32, 0); - codegen_check_seg_write(block, ir, target_seg); - - uop_MEM_LOAD_REG(ir, IREG_temp0, ireg_seg_base(target_seg), IREG_eaaddr); - uop_XOR(ir, IREG_temp0, IREG_temp0, IREG_32(src_reg)); - uop_MEM_STORE_REG(ir, ireg_seg_base(target_seg), IREG_eaaddr, IREG_temp0); - uop_MOV(ir, IREG_flags_res, IREG_temp0); - } - - uop_MOV_IMM(ir, IREG_flags_op, FLAGS_ZN32); - - codegen_flags_changed = 1; - return op_pc + 1; + uop_MOV_IMM(ir, IREG_flags_op, FLAGS_ZN32); + + codegen_flags_changed = 1; + return op_pc + 1; } diff --git a/src/codegen_new/codegen_ops_misc.c b/src/codegen_new/codegen_ops_misc.c index c4aae7598..545634672 100644 --- a/src/codegen_new/codegen_ops_misc.c +++ b/src/codegen_new/codegen_ops_misc.c @@ -2,9 +2,12 @@ #include <86box/86box.h> #include "cpu.h" #include <86box/mem.h> +#include <86box/plat_unused.h> #include "x86.h" #include "x86_flags.h" +#include "x86seg_common.h" +#include "x86seg.h" #include "386_common.h" #include "codegen.h" #include "codegen_ir.h" @@ -12,553 +15,555 @@ #include "codegen_ops_helpers.h" #include "codegen_ops_misc.h" -uint32_t ropLEA_16(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) +uint32_t +ropLEA_16(codeblock_t *block, ir_data_t *ir, UNUSED(uint8_t opcode), uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) { - int dest_reg = (fetchdat >> 3) & 7; + int dest_reg = (fetchdat >> 3) & 7; - if ((fetchdat & 0xc0) == 0xc0) - return 0; - - codegen_mark_code_present(block, cs+op_pc, 1); - codegen_generate_ea(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32, 0); - uop_MOV(ir, IREG_16(dest_reg), IREG_eaaddr_W); - - return op_pc + 1; -} -uint32_t ropLEA_32(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) -{ - int dest_reg = (fetchdat >> 3) & 7; - - if ((fetchdat & 0xc0) == 0xc0) - return 0; - - codegen_mark_code_present(block, cs+op_pc, 1); - codegen_generate_ea(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32, 0); - uop_MOV(ir, IREG_32(dest_reg), IREG_eaaddr); - - return op_pc + 1; -} - -uint32_t ropF6(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) -{ - x86seg *target_seg = NULL; - uint8_t imm_data; - int reg; - - if (fetchdat & 0x20) - return 0; - - codegen_mark_code_present(block, cs+op_pc, 1); - if ((fetchdat & 0xc0) == 0xc0) - reg = IREG_8(fetchdat & 7); - else - { - uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc); - target_seg = codegen_generate_ea(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32, 0); - if ((fetchdat & 0x30) == 0x10) /*NEG/NOT*/ - codegen_check_seg_write(block, ir, target_seg); - else - codegen_check_seg_read(block, ir, target_seg); - uop_MEM_LOAD_REG(ir, IREG_temp0_B, ireg_seg_base(target_seg), IREG_eaaddr); - reg = IREG_temp0_B; - } - - switch (fetchdat & 0x38) - { - case 0x00: case 0x08: /*TEST*/ - imm_data = fastreadb(cs + op_pc + 1); - - uop_AND_IMM(ir, IREG_flags_res_B, reg, imm_data); - uop_MOVZX(ir, IREG_flags_res, IREG_flags_res_B); - uop_MOV_IMM(ir, IREG_flags_op, FLAGS_ZN8); - - codegen_flags_changed = 1; - codegen_mark_code_present(block, cs+op_pc+1, 1); - return op_pc+2; - - case 0x10: /*NOT*/ - uop_XOR_IMM(ir, reg, reg, 0xff); - if ((fetchdat & 0xc0) != 0xc0) - uop_MEM_STORE_REG(ir, ireg_seg_base(target_seg), IREG_eaaddr, reg); - - codegen_flags_changed = 1; - return op_pc+1; - - case 0x18: /*NEG*/ - uop_MOV_IMM(ir, IREG_temp1_B, 0); - - if ((fetchdat & 0xc0) == 0xc0) - { - uop_MOVZX(ir, IREG_flags_op2, reg); - uop_SUB(ir, IREG_temp1_B, IREG_temp1_B, reg); - uop_MOVZX(ir, IREG_flags_res, IREG_temp1_B); - uop_MOV(ir, reg, IREG_temp1_B); - } - else - { - uop_SUB(ir, IREG_temp1_B, IREG_temp1_B, reg); - uop_MEM_STORE_REG(ir, ireg_seg_base(target_seg), IREG_eaaddr, IREG_temp1_B); - uop_MOVZX(ir, IREG_flags_op2, IREG_temp0_B); - uop_MOVZX(ir, IREG_flags_res, IREG_temp1_B); - } - uop_MOV_IMM(ir, IREG_flags_op, FLAGS_SUB8); - uop_MOV_IMM(ir, IREG_flags_op1, 0); - - codegen_flags_changed = 1; - return op_pc+1; - } + if ((fetchdat & 0xc0) == 0xc0) return 0; + + codegen_mark_code_present(block, cs + op_pc, 1); + codegen_generate_ea(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32, 0); + uop_MOV(ir, IREG_16(dest_reg), IREG_eaaddr_W); + + return op_pc + 1; } -uint32_t ropF7_16(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) +uint32_t +ropLEA_32(codeblock_t *block, ir_data_t *ir, UNUSED(uint8_t opcode), uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) { - x86seg *target_seg = NULL; - uint16_t imm_data; - int reg; + int dest_reg = (fetchdat >> 3) & 7; - if (fetchdat & 0x20) - return 0; - - codegen_mark_code_present(block, cs+op_pc, 1); - if ((fetchdat & 0xc0) == 0xc0) - reg = IREG_16(fetchdat & 7); - else - { - uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc); - target_seg = codegen_generate_ea(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32, 0); - if ((fetchdat & 0x30) == 0x10) /*NEG/NOT*/ - codegen_check_seg_write(block, ir, target_seg); - else - codegen_check_seg_read(block, ir, target_seg); - uop_MEM_LOAD_REG(ir, IREG_temp0_W, ireg_seg_base(target_seg), IREG_eaaddr); - reg = IREG_temp0_W; - } - - switch (fetchdat & 0x38) - { - case 0x00: case 0x08: /*TEST*/ - imm_data = fastreadw(cs + op_pc + 1); - - uop_AND_IMM(ir, IREG_flags_res_W, reg, imm_data); - uop_MOVZX(ir, IREG_flags_res, IREG_flags_res_W); - uop_MOV_IMM(ir, IREG_flags_op, FLAGS_ZN16); - - codegen_flags_changed = 1; - codegen_mark_code_present(block, cs+op_pc+1, 2); - return op_pc+3; - - case 0x10: /*NOT*/ - uop_XOR_IMM(ir, reg, reg, 0xffff); - if ((fetchdat & 0xc0) != 0xc0) - uop_MEM_STORE_REG(ir, ireg_seg_base(target_seg), IREG_eaaddr, reg); - - codegen_flags_changed = 1; - return op_pc+1; - - case 0x18: /*NEG*/ - uop_MOV_IMM(ir, IREG_temp1_W, 0); - - if ((fetchdat & 0xc0) == 0xc0) - { - uop_MOVZX(ir, IREG_flags_op2, reg); - uop_SUB(ir, IREG_temp1_W, IREG_temp1_W, reg); - uop_MOVZX(ir, IREG_flags_res, IREG_temp1_W); - uop_MOV(ir, reg, IREG_temp1_W); - } - else - { - uop_SUB(ir, IREG_temp1_W, IREG_temp1_W, reg); - uop_MEM_STORE_REG(ir, ireg_seg_base(target_seg), IREG_eaaddr, IREG_temp1_W); - uop_MOVZX(ir, IREG_flags_op2, IREG_temp0_W); - uop_MOVZX(ir, IREG_flags_res, IREG_temp1_W); - } - uop_MOV_IMM(ir, IREG_flags_op, FLAGS_SUB16); - uop_MOV_IMM(ir, IREG_flags_op1, 0); - - codegen_flags_changed = 1; - return op_pc+1; - } + if ((fetchdat & 0xc0) == 0xc0) return 0; + + codegen_mark_code_present(block, cs + op_pc, 1); + codegen_generate_ea(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32, 0); + uop_MOV(ir, IREG_32(dest_reg), IREG_eaaddr); + + return op_pc + 1; } -uint32_t ropF7_32(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) + +uint32_t +ropF6(codeblock_t *block, ir_data_t *ir, UNUSED(uint8_t opcode), uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) { - x86seg *target_seg = NULL; - uint32_t imm_data; - int reg; + x86seg *target_seg = NULL; + uint8_t imm_data; + int reg; - if (fetchdat & 0x20) - return 0; - - codegen_mark_code_present(block, cs+op_pc, 1); - if ((fetchdat & 0xc0) == 0xc0) - reg = IREG_32(fetchdat & 7); - else - { - uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc); - target_seg = codegen_generate_ea(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32, 0); - if ((fetchdat & 0x30) == 0x10) /*NEG/NOT*/ - codegen_check_seg_write(block, ir, target_seg); - else - codegen_check_seg_read(block, ir, target_seg); - uop_MEM_LOAD_REG(ir, IREG_temp0, ireg_seg_base(target_seg), IREG_eaaddr); - reg = IREG_temp0; - } - - switch (fetchdat & 0x38) - { - case 0x00: case 0x08: /*TEST*/ - imm_data = fastreadl(cs + op_pc + 1); - - uop_AND_IMM(ir, IREG_flags_res, reg, imm_data); - uop_MOV_IMM(ir, IREG_flags_op, FLAGS_ZN32); - - codegen_flags_changed = 1; - codegen_mark_code_present(block, cs+op_pc+1, 4); - return op_pc+5; - - case 0x10: /*NOT*/ - uop_XOR_IMM(ir, reg, reg, 0xffffffff); - if ((fetchdat & 0xc0) != 0xc0) - uop_MEM_STORE_REG(ir, ireg_seg_base(target_seg), IREG_eaaddr, reg); - - codegen_flags_changed = 1; - return op_pc+1; - - case 0x18: /*NEG*/ - uop_MOV_IMM(ir, IREG_temp1, 0); - - if ((fetchdat & 0xc0) == 0xc0) - { - uop_MOV(ir, IREG_flags_op2, reg); - uop_SUB(ir, IREG_temp1, IREG_temp1, reg); - uop_MOV(ir, IREG_flags_res, IREG_temp1); - uop_MOV(ir, reg, IREG_temp1); - } - else - { - uop_SUB(ir, IREG_temp1, IREG_temp1, reg); - uop_MEM_STORE_REG(ir, ireg_seg_base(target_seg), IREG_eaaddr, IREG_temp1); - uop_MOV(ir, IREG_flags_op2, IREG_temp0); - uop_MOV(ir, IREG_flags_res, IREG_temp1); - } - uop_MOV_IMM(ir, IREG_flags_op, FLAGS_SUB32); - uop_MOV_IMM(ir, IREG_flags_op1, 0); - - codegen_flags_changed = 1; - return op_pc+1; - } + if (fetchdat & 0x20) return 0; -} -static void rebuild_c(ir_data_t *ir) -{ - int needs_rebuild = 1; - - if (codegen_flags_changed) - { - switch (cpu_state.flags_op) - { - case FLAGS_INC8: case FLAGS_INC16: case FLAGS_INC32: - case FLAGS_DEC8: case FLAGS_DEC16: case FLAGS_DEC32: - needs_rebuild = 0; - break; - } - } - - if (needs_rebuild) - { - uop_CALL_FUNC(ir, flags_rebuild_c); - } -} - -uint32_t ropFF_16(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) -{ - x86seg *target_seg = NULL; - int src_reg, sp_reg; - - if ((fetchdat & 0x38) != 0x00 && (fetchdat & 0x38) != 0x08 && (fetchdat & 0x38) != 0x10 && (fetchdat & 0x38) != 0x20 && (fetchdat & 0x38) != 0x28 && (fetchdat & 0x38) != 0x30) - return 0; - - codegen_mark_code_present(block, cs+op_pc, 1); - if ((fetchdat & 0xc0) == 0xc0) - { - if ((fetchdat & 0x38) == 0x28) - return 0; - src_reg = IREG_16(fetchdat & 7); - } + codegen_mark_code_present(block, cs + op_pc, 1); + if ((fetchdat & 0xc0) == 0xc0) + reg = IREG_8(fetchdat & 7); + else { + uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc); + target_seg = codegen_generate_ea(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32, 0); + if ((fetchdat & 0x30) == 0x10) /*NEG/NOT*/ + codegen_check_seg_write(block, ir, target_seg); else - { - uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc); - target_seg = codegen_generate_ea(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32, 0); - if (!(fetchdat & 0x30)) /*INC/DEC*/ - codegen_check_seg_write(block, ir, target_seg); - else - codegen_check_seg_read(block, ir, target_seg); - uop_MEM_LOAD_REG(ir, IREG_temp0_W, ireg_seg_base(target_seg), IREG_eaaddr); - src_reg = IREG_temp0_W; - } + codegen_check_seg_read(block, ir, target_seg); + uop_MEM_LOAD_REG(ir, IREG_temp0_B, ireg_seg_base(target_seg), IREG_eaaddr); + reg = IREG_temp0_B; + } - switch (fetchdat & 0x38) - { - case 0x00: /*INC*/ - rebuild_c(ir); - codegen_flags_changed = 1; + switch (fetchdat & 0x38) { + case 0x00: + case 0x08: /*TEST*/ + imm_data = fastreadb(cs + op_pc + 1); - if ((fetchdat & 0xc0) == 0xc0) - { - uop_MOVZX(ir, IREG_flags_op1, src_reg); - uop_ADD_IMM(ir, src_reg, src_reg, 1); - uop_MOVZX(ir, IREG_flags_res, src_reg); - uop_MOV_IMM(ir, IREG_flags_op2, 1); - uop_MOV_IMM(ir, IREG_flags_op, FLAGS_INC16); - } - else - { - uop_ADD_IMM(ir, IREG_temp1_W, src_reg, 1); - uop_MEM_STORE_REG(ir, ireg_seg_base(target_seg), IREG_eaaddr, IREG_temp1_W); - uop_MOVZX(ir, IREG_flags_op1, src_reg); - uop_MOVZX(ir, IREG_flags_res, IREG_temp1_W); - uop_MOV_IMM(ir, IREG_flags_op2, 1); - uop_MOV_IMM(ir, IREG_flags_op, FLAGS_INC16); - } - return op_pc+1; - - case 0x08: /*DEC*/ - rebuild_c(ir); - codegen_flags_changed = 1; + uop_AND_IMM(ir, IREG_flags_res_B, reg, imm_data); + uop_MOVZX(ir, IREG_flags_res, IREG_flags_res_B); + uop_MOV_IMM(ir, IREG_flags_op, FLAGS_ZN8); - if ((fetchdat & 0xc0) == 0xc0) - { - uop_MOVZX(ir, IREG_flags_op1, src_reg); - uop_SUB_IMM(ir, src_reg, src_reg, 1); - uop_MOVZX(ir, IREG_flags_res, src_reg); - uop_MOV_IMM(ir, IREG_flags_op2, 1); - uop_MOV_IMM(ir, IREG_flags_op, FLAGS_DEC16); - } - else - { - uop_SUB_IMM(ir, IREG_temp1_W, src_reg, 1); - uop_MEM_STORE_REG(ir, ireg_seg_base(target_seg), IREG_eaaddr, IREG_temp1_W); - uop_MOVZX(ir, IREG_flags_op1, src_reg); - uop_MOVZX(ir, IREG_flags_res, IREG_temp1_W); - uop_MOV_IMM(ir, IREG_flags_op2, 1); - uop_MOV_IMM(ir, IREG_flags_op, FLAGS_DEC16); - } - return op_pc+1; + codegen_flags_changed = 1; + codegen_mark_code_present(block, cs + op_pc + 1, 1); + return op_pc + 2; - case 0x10: /*CALL*/ - if ((fetchdat & 0xc0) == 0xc0) - uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc); - sp_reg = LOAD_SP_WITH_OFFSET(ir, -2); - uop_MEM_STORE_IMM_16(ir, IREG_SS_base, sp_reg, op_pc + 1); - SUB_SP(ir, 2); - uop_MOVZX(ir, IREG_pc, src_reg); - return -1; + case 0x10: /*NOT*/ + uop_XOR_IMM(ir, reg, reg, 0xff); + if ((fetchdat & 0xc0) != 0xc0) + uop_MEM_STORE_REG(ir, ireg_seg_base(target_seg), IREG_eaaddr, reg); - case 0x20: /*JMP*/ - uop_MOVZX(ir, IREG_pc, src_reg); - return -1; - - case 0x28: /*JMP far*/ - uop_MOVZX(ir, IREG_pc, src_reg); - uop_MEM_LOAD_REG_OFFSET(ir, IREG_temp1_W, ireg_seg_base(target_seg), IREG_eaaddr, 2); - uop_LOAD_FUNC_ARG_REG(ir, 0, IREG_temp1_W); - uop_LOAD_FUNC_ARG_IMM(ir, 1, op_pc + 1); - uop_CALL_FUNC(ir, loadcsjmp); - return -1; + codegen_flags_changed = 1; + return op_pc + 1; - case 0x30: /*PUSH*/ - if ((fetchdat & 0xc0) == 0xc0) - uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc); - sp_reg = LOAD_SP_WITH_OFFSET(ir, -2); - uop_MEM_STORE_REG(ir, IREG_SS_base, sp_reg, src_reg); - SUB_SP(ir, 2); - return op_pc+1; - } - return 0; + case 0x18: /*NEG*/ + uop_MOV_IMM(ir, IREG_temp1_B, 0); + + if ((fetchdat & 0xc0) == 0xc0) { + uop_MOVZX(ir, IREG_flags_op2, reg); + uop_SUB(ir, IREG_temp1_B, IREG_temp1_B, reg); + uop_MOVZX(ir, IREG_flags_res, IREG_temp1_B); + uop_MOV(ir, reg, IREG_temp1_B); + } else { + uop_SUB(ir, IREG_temp1_B, IREG_temp1_B, reg); + uop_MEM_STORE_REG(ir, ireg_seg_base(target_seg), IREG_eaaddr, IREG_temp1_B); + uop_MOVZX(ir, IREG_flags_op2, IREG_temp0_B); + uop_MOVZX(ir, IREG_flags_res, IREG_temp1_B); + } + uop_MOV_IMM(ir, IREG_flags_op, FLAGS_SUB8); + uop_MOV_IMM(ir, IREG_flags_op1, 0); + + codegen_flags_changed = 1; + return op_pc + 1; + + default: + break; + } + return 0; } - -uint32_t ropFF_32(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) +uint32_t +ropF7_16(codeblock_t *block, ir_data_t *ir, UNUSED(uint8_t opcode), uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) { - x86seg *target_seg = NULL; - int src_reg, sp_reg; + x86seg *target_seg = NULL; + uint16_t imm_data; + int reg; - if ((fetchdat & 0x38) != 0x00 && (fetchdat & 0x38) != 0x08 && (fetchdat & 0x38) != 0x10 && (fetchdat & 0x38) != 0x20 && (fetchdat & 0x38) != 0x28 && (fetchdat & 0x38) != 0x30) - return 0; + if (fetchdat & 0x20) + return 0; - codegen_mark_code_present(block, cs+op_pc, 1); - if ((fetchdat & 0xc0) == 0xc0) - { - if ((fetchdat & 0x38) == 0x28) - return 0; - src_reg = IREG_32(fetchdat & 7); - } + codegen_mark_code_present(block, cs + op_pc, 1); + if ((fetchdat & 0xc0) == 0xc0) + reg = IREG_16(fetchdat & 7); + else { + uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc); + target_seg = codegen_generate_ea(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32, 0); + if ((fetchdat & 0x30) == 0x10) /*NEG/NOT*/ + codegen_check_seg_write(block, ir, target_seg); else - { - uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc); - target_seg = codegen_generate_ea(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32, 0); - if (!(fetchdat & 0x30)) /*INC/DEC*/ - codegen_check_seg_write(block, ir, target_seg); - else - codegen_check_seg_read(block, ir, target_seg); - uop_MEM_LOAD_REG(ir, IREG_temp0, ireg_seg_base(target_seg), IREG_eaaddr); - src_reg = IREG_temp0; - } + codegen_check_seg_read(block, ir, target_seg); + uop_MEM_LOAD_REG(ir, IREG_temp0_W, ireg_seg_base(target_seg), IREG_eaaddr); + reg = IREG_temp0_W; + } - switch (fetchdat & 0x38) - { - case 0x00: /*INC*/ - rebuild_c(ir); - codegen_flags_changed = 1; + switch (fetchdat & 0x38) { + case 0x00: + case 0x08: /*TEST*/ + imm_data = fastreadw(cs + op_pc + 1); - if ((fetchdat & 0xc0) == 0xc0) - { - uop_MOV(ir, IREG_flags_op1, src_reg); - uop_ADD_IMM(ir, src_reg, src_reg, 1); - uop_MOV(ir, IREG_flags_res, src_reg); - uop_MOV_IMM(ir, IREG_flags_op2, 1); - uop_MOV_IMM(ir, IREG_flags_op, FLAGS_INC32); - } - else - { - uop_ADD_IMM(ir, IREG_temp1, src_reg, 1); - uop_MEM_STORE_REG(ir, ireg_seg_base(target_seg), IREG_eaaddr, IREG_temp1); - uop_MOV(ir, IREG_flags_op1, src_reg); - uop_MOV(ir, IREG_flags_res, IREG_temp1); - uop_MOV_IMM(ir, IREG_flags_op2, 1); - uop_MOV_IMM(ir, IREG_flags_op, FLAGS_INC32); - } - return op_pc+1; + uop_AND_IMM(ir, IREG_flags_res_W, reg, imm_data); + uop_MOVZX(ir, IREG_flags_res, IREG_flags_res_W); + uop_MOV_IMM(ir, IREG_flags_op, FLAGS_ZN16); - case 0x08: /*DEC*/ - rebuild_c(ir); - codegen_flags_changed = 1; + codegen_flags_changed = 1; + codegen_mark_code_present(block, cs + op_pc + 1, 2); + return op_pc + 3; - if ((fetchdat & 0xc0) == 0xc0) - { - uop_MOV(ir, IREG_flags_op1, src_reg); - uop_SUB_IMM(ir, src_reg, src_reg, 1); - uop_MOV(ir, IREG_flags_res, src_reg); - uop_MOV_IMM(ir, IREG_flags_op2, 1); - uop_MOV_IMM(ir, IREG_flags_op, FLAGS_DEC32); - } - else - { - uop_SUB_IMM(ir, IREG_temp1, src_reg, 1); - uop_MEM_STORE_REG(ir, ireg_seg_base(target_seg), IREG_eaaddr, IREG_temp1); - uop_MOV(ir, IREG_flags_op1, src_reg); - uop_MOV(ir, IREG_flags_res, IREG_temp1); - uop_MOV_IMM(ir, IREG_flags_op2, 1); - uop_MOV_IMM(ir, IREG_flags_op, FLAGS_DEC32); - } - return op_pc+1; + case 0x10: /*NOT*/ + uop_XOR_IMM(ir, reg, reg, 0xffff); + if ((fetchdat & 0xc0) != 0xc0) + uop_MEM_STORE_REG(ir, ireg_seg_base(target_seg), IREG_eaaddr, reg); - case 0x10: /*CALL*/ - if ((fetchdat & 0xc0) == 0xc0) - uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc); - sp_reg = LOAD_SP_WITH_OFFSET(ir, -4); - uop_MEM_STORE_IMM_32(ir, IREG_SS_base, sp_reg, op_pc + 1); - SUB_SP(ir, 4); - uop_MOV(ir, IREG_pc, src_reg); - return -1; + codegen_flags_changed = 1; + return op_pc + 1; - case 0x20: /*JMP*/ - uop_MOV(ir, IREG_pc, src_reg); - return -1; + case 0x18: /*NEG*/ + uop_MOV_IMM(ir, IREG_temp1_W, 0); - case 0x28: /*JMP far*/ - uop_MOV(ir, IREG_pc, src_reg); - uop_MEM_LOAD_REG_OFFSET(ir, IREG_temp1_W, ireg_seg_base(target_seg), IREG_eaaddr, 4); - uop_LOAD_FUNC_ARG_REG(ir, 0, IREG_temp1_W); - uop_LOAD_FUNC_ARG_IMM(ir, 1, op_pc + 1); - uop_CALL_FUNC(ir, loadcsjmp); - return -1; + if ((fetchdat & 0xc0) == 0xc0) { + uop_MOVZX(ir, IREG_flags_op2, reg); + uop_SUB(ir, IREG_temp1_W, IREG_temp1_W, reg); + uop_MOVZX(ir, IREG_flags_res, IREG_temp1_W); + uop_MOV(ir, reg, IREG_temp1_W); + } else { + uop_SUB(ir, IREG_temp1_W, IREG_temp1_W, reg); + uop_MEM_STORE_REG(ir, ireg_seg_base(target_seg), IREG_eaaddr, IREG_temp1_W); + uop_MOVZX(ir, IREG_flags_op2, IREG_temp0_W); + uop_MOVZX(ir, IREG_flags_res, IREG_temp1_W); + } + uop_MOV_IMM(ir, IREG_flags_op, FLAGS_SUB16); + uop_MOV_IMM(ir, IREG_flags_op1, 0); - case 0x30: /*PUSH*/ - if ((fetchdat & 0xc0) == 0xc0) - uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc); - sp_reg = LOAD_SP_WITH_OFFSET(ir, -4); - uop_MEM_STORE_REG(ir, IREG_SS_base, sp_reg, src_reg); - SUB_SP(ir, 4); - return op_pc+1; - } + codegen_flags_changed = 1; + return op_pc + 1; + + default: + break; + } + return 0; +} +uint32_t +ropF7_32(codeblock_t *block, ir_data_t *ir, UNUSED(uint8_t opcode), uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) +{ + x86seg *target_seg = NULL; + uint32_t imm_data; + int reg; + + if (fetchdat & 0x20) return 0; + + codegen_mark_code_present(block, cs + op_pc, 1); + if ((fetchdat & 0xc0) == 0xc0) + reg = IREG_32(fetchdat & 7); + else { + uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc); + target_seg = codegen_generate_ea(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32, 0); + if ((fetchdat & 0x30) == 0x10) /*NEG/NOT*/ + codegen_check_seg_write(block, ir, target_seg); + else + codegen_check_seg_read(block, ir, target_seg); + uop_MEM_LOAD_REG(ir, IREG_temp0, ireg_seg_base(target_seg), IREG_eaaddr); + reg = IREG_temp0; + } + + switch (fetchdat & 0x38) { + case 0x00: + case 0x08: /*TEST*/ + imm_data = fastreadl(cs + op_pc + 1); + + uop_AND_IMM(ir, IREG_flags_res, reg, imm_data); + uop_MOV_IMM(ir, IREG_flags_op, FLAGS_ZN32); + + codegen_flags_changed = 1; + codegen_mark_code_present(block, cs + op_pc + 1, 4); + return op_pc + 5; + + case 0x10: /*NOT*/ + uop_XOR_IMM(ir, reg, reg, 0xffffffff); + if ((fetchdat & 0xc0) != 0xc0) + uop_MEM_STORE_REG(ir, ireg_seg_base(target_seg), IREG_eaaddr, reg); + + codegen_flags_changed = 1; + return op_pc + 1; + + case 0x18: /*NEG*/ + uop_MOV_IMM(ir, IREG_temp1, 0); + + if ((fetchdat & 0xc0) == 0xc0) { + uop_MOV(ir, IREG_flags_op2, reg); + uop_SUB(ir, IREG_temp1, IREG_temp1, reg); + uop_MOV(ir, IREG_flags_res, IREG_temp1); + uop_MOV(ir, reg, IREG_temp1); + } else { + uop_SUB(ir, IREG_temp1, IREG_temp1, reg); + uop_MEM_STORE_REG(ir, ireg_seg_base(target_seg), IREG_eaaddr, IREG_temp1); + uop_MOV(ir, IREG_flags_op2, IREG_temp0); + uop_MOV(ir, IREG_flags_res, IREG_temp1); + } + uop_MOV_IMM(ir, IREG_flags_op, FLAGS_SUB32); + uop_MOV_IMM(ir, IREG_flags_op1, 0); + + codegen_flags_changed = 1; + return op_pc + 1; + + default: + break; + } + return 0; } -uint32_t ropNOP(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) +static void +rebuild_c(ir_data_t *ir) { - return op_pc; + int needs_rebuild = 1; + + if (codegen_flags_changed) { + switch (cpu_state.flags_op) { + case FLAGS_INC8: + case FLAGS_INC16: + case FLAGS_INC32: + case FLAGS_DEC8: + case FLAGS_DEC16: + case FLAGS_DEC32: + needs_rebuild = 0; + break; + + default: + break; + } + } + + if (needs_rebuild) { + uop_CALL_FUNC(ir, flags_rebuild_c); + } } -uint32_t ropCBW(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) +uint32_t +ropFF_16(codeblock_t *block, ir_data_t *ir, UNUSED(uint8_t opcode), uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) { - uop_MOVSX(ir, IREG_AX, IREG_AL); + x86seg *target_seg = NULL; + int src_reg; + int sp_reg; - return op_pc; + if ((fetchdat & 0x38) != 0x00 && (fetchdat & 0x38) != 0x08 && (fetchdat & 0x38) != 0x10 && (fetchdat & 0x38) != 0x20 && (fetchdat & 0x38) != 0x28 && (fetchdat & 0x38) != 0x30) + return 0; + + codegen_mark_code_present(block, cs + op_pc, 1); + if ((fetchdat & 0xc0) == 0xc0) { + if ((fetchdat & 0x38) == 0x28) + return 0; + src_reg = IREG_16(fetchdat & 7); + } else { + uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc); + target_seg = codegen_generate_ea(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32, 0); + if (!(fetchdat & 0x30)) /*INC/DEC*/ + codegen_check_seg_write(block, ir, target_seg); + else + codegen_check_seg_read(block, ir, target_seg); + uop_MEM_LOAD_REG(ir, IREG_temp0_W, ireg_seg_base(target_seg), IREG_eaaddr); + src_reg = IREG_temp0_W; + } + + switch (fetchdat & 0x38) { + case 0x00: /*INC*/ + rebuild_c(ir); + codegen_flags_changed = 1; + + if ((fetchdat & 0xc0) == 0xc0) { + uop_MOVZX(ir, IREG_flags_op1, src_reg); + uop_ADD_IMM(ir, src_reg, src_reg, 1); + uop_MOVZX(ir, IREG_flags_res, src_reg); + uop_MOV_IMM(ir, IREG_flags_op2, 1); + uop_MOV_IMM(ir, IREG_flags_op, FLAGS_INC16); + } else { + uop_ADD_IMM(ir, IREG_temp1_W, src_reg, 1); + uop_MEM_STORE_REG(ir, ireg_seg_base(target_seg), IREG_eaaddr, IREG_temp1_W); + uop_MOVZX(ir, IREG_flags_op1, src_reg); + uop_MOVZX(ir, IREG_flags_res, IREG_temp1_W); + uop_MOV_IMM(ir, IREG_flags_op2, 1); + uop_MOV_IMM(ir, IREG_flags_op, FLAGS_INC16); + } + return op_pc + 1; + + case 0x08: /*DEC*/ + rebuild_c(ir); + codegen_flags_changed = 1; + + if ((fetchdat & 0xc0) == 0xc0) { + uop_MOVZX(ir, IREG_flags_op1, src_reg); + uop_SUB_IMM(ir, src_reg, src_reg, 1); + uop_MOVZX(ir, IREG_flags_res, src_reg); + uop_MOV_IMM(ir, IREG_flags_op2, 1); + uop_MOV_IMM(ir, IREG_flags_op, FLAGS_DEC16); + } else { + uop_SUB_IMM(ir, IREG_temp1_W, src_reg, 1); + uop_MEM_STORE_REG(ir, ireg_seg_base(target_seg), IREG_eaaddr, IREG_temp1_W); + uop_MOVZX(ir, IREG_flags_op1, src_reg); + uop_MOVZX(ir, IREG_flags_res, IREG_temp1_W); + uop_MOV_IMM(ir, IREG_flags_op2, 1); + uop_MOV_IMM(ir, IREG_flags_op, FLAGS_DEC16); + } + return op_pc + 1; + + case 0x10: /*CALL*/ + if ((fetchdat & 0xc0) == 0xc0) + uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc); + sp_reg = LOAD_SP_WITH_OFFSET(ir, -2); + uop_MEM_STORE_IMM_16(ir, IREG_SS_base, sp_reg, op_pc + 1); + SUB_SP(ir, 2); + uop_MOVZX(ir, IREG_pc, src_reg); + return -1; + + case 0x20: /*JMP*/ + uop_MOVZX(ir, IREG_pc, src_reg); + return -1; + + case 0x28: /*JMP far*/ + uop_MOVZX(ir, IREG_pc, src_reg); + uop_MEM_LOAD_REG_OFFSET(ir, IREG_temp1_W, ireg_seg_base(target_seg), IREG_eaaddr, 2); + uop_LOAD_FUNC_ARG_REG(ir, 0, IREG_temp1_W); + uop_LOAD_FUNC_ARG_IMM(ir, 1, op_pc + 1); + uop_CALL_FUNC(ir, loadcsjmp); + return -1; + + case 0x30: /*PUSH*/ + if ((fetchdat & 0xc0) == 0xc0) + uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc); + sp_reg = LOAD_SP_WITH_OFFSET(ir, -2); + uop_MEM_STORE_REG(ir, IREG_SS_base, sp_reg, src_reg); + SUB_SP(ir, 2); + return op_pc + 1; + + default: + break; + } + return 0; } -uint32_t ropCDQ(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) + +uint32_t +ropFF_32(codeblock_t *block, ir_data_t *ir, UNUSED(uint8_t opcode), uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) { - uop_SAR_IMM(ir, IREG_EDX, IREG_EAX, 31); + x86seg *target_seg = NULL; + int src_reg; + int sp_reg; - return op_pc; + if ((fetchdat & 0x38) != 0x00 && (fetchdat & 0x38) != 0x08 && (fetchdat & 0x38) != 0x10 && (fetchdat & 0x38) != 0x20 && (fetchdat & 0x38) != 0x28 && (fetchdat & 0x38) != 0x30) + return 0; + + codegen_mark_code_present(block, cs + op_pc, 1); + if ((fetchdat & 0xc0) == 0xc0) { + if ((fetchdat & 0x38) == 0x28) + return 0; + src_reg = IREG_32(fetchdat & 7); + } else { + uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc); + target_seg = codegen_generate_ea(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32, 0); + if (!(fetchdat & 0x30)) /*INC/DEC*/ + codegen_check_seg_write(block, ir, target_seg); + else + codegen_check_seg_read(block, ir, target_seg); + uop_MEM_LOAD_REG(ir, IREG_temp0, ireg_seg_base(target_seg), IREG_eaaddr); + src_reg = IREG_temp0; + } + + switch (fetchdat & 0x38) { + case 0x00: /*INC*/ + rebuild_c(ir); + codegen_flags_changed = 1; + + if ((fetchdat & 0xc0) == 0xc0) { + uop_MOV(ir, IREG_flags_op1, src_reg); + uop_ADD_IMM(ir, src_reg, src_reg, 1); + uop_MOV(ir, IREG_flags_res, src_reg); + uop_MOV_IMM(ir, IREG_flags_op2, 1); + uop_MOV_IMM(ir, IREG_flags_op, FLAGS_INC32); + } else { + uop_ADD_IMM(ir, IREG_temp1, src_reg, 1); + uop_MEM_STORE_REG(ir, ireg_seg_base(target_seg), IREG_eaaddr, IREG_temp1); + uop_MOV(ir, IREG_flags_op1, src_reg); + uop_MOV(ir, IREG_flags_res, IREG_temp1); + uop_MOV_IMM(ir, IREG_flags_op2, 1); + uop_MOV_IMM(ir, IREG_flags_op, FLAGS_INC32); + } + return op_pc + 1; + + case 0x08: /*DEC*/ + rebuild_c(ir); + codegen_flags_changed = 1; + + if ((fetchdat & 0xc0) == 0xc0) { + uop_MOV(ir, IREG_flags_op1, src_reg); + uop_SUB_IMM(ir, src_reg, src_reg, 1); + uop_MOV(ir, IREG_flags_res, src_reg); + uop_MOV_IMM(ir, IREG_flags_op2, 1); + uop_MOV_IMM(ir, IREG_flags_op, FLAGS_DEC32); + } else { + uop_SUB_IMM(ir, IREG_temp1, src_reg, 1); + uop_MEM_STORE_REG(ir, ireg_seg_base(target_seg), IREG_eaaddr, IREG_temp1); + uop_MOV(ir, IREG_flags_op1, src_reg); + uop_MOV(ir, IREG_flags_res, IREG_temp1); + uop_MOV_IMM(ir, IREG_flags_op2, 1); + uop_MOV_IMM(ir, IREG_flags_op, FLAGS_DEC32); + } + return op_pc + 1; + + case 0x10: /*CALL*/ + if ((fetchdat & 0xc0) == 0xc0) + uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc); + sp_reg = LOAD_SP_WITH_OFFSET(ir, -4); + uop_MEM_STORE_IMM_32(ir, IREG_SS_base, sp_reg, op_pc + 1); + SUB_SP(ir, 4); + uop_MOV(ir, IREG_pc, src_reg); + return -1; + + case 0x20: /*JMP*/ + uop_MOV(ir, IREG_pc, src_reg); + return -1; + + case 0x28: /*JMP far*/ + uop_MOV(ir, IREG_pc, src_reg); + uop_MEM_LOAD_REG_OFFSET(ir, IREG_temp1_W, ireg_seg_base(target_seg), IREG_eaaddr, 4); + uop_LOAD_FUNC_ARG_REG(ir, 0, IREG_temp1_W); + uop_LOAD_FUNC_ARG_IMM(ir, 1, op_pc + 1); + uop_CALL_FUNC(ir, loadcsjmp); + return -1; + + case 0x30: /*PUSH*/ + if ((fetchdat & 0xc0) == 0xc0) + uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc); + sp_reg = LOAD_SP_WITH_OFFSET(ir, -4); + uop_MEM_STORE_REG(ir, IREG_SS_base, sp_reg, src_reg); + SUB_SP(ir, 4); + return op_pc + 1; + + default: + break; + } + return 0; } -uint32_t ropCWD(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) + +uint32_t +ropNOP(UNUSED(codeblock_t *block), UNUSED(ir_data_t *ir), UNUSED(uint8_t opcode), uint32_t fetchdat, UNUSED(uint32_t op_32), uint32_t op_pc) { - uop_SAR_IMM(ir, IREG_DX, IREG_AX, 15); - - return op_pc; + return op_pc; } -uint32_t ropCWDE(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) + +uint32_t +ropCBW(UNUSED(codeblock_t *block), ir_data_t *ir, UNUSED(uint8_t opcode), uint32_t fetchdat, UNUSED(uint32_t op_32), uint32_t op_pc) { - uop_MOVSX(ir, IREG_EAX, IREG_AX); + uop_MOVSX(ir, IREG_AX, IREG_AL); - return op_pc; + return op_pc; +} +uint32_t +ropCDQ(UNUSED(codeblock_t *block), ir_data_t *ir, UNUSED(uint8_t opcode), uint32_t fetchdat, UNUSED(uint32_t op_32), uint32_t op_pc) +{ + uop_SAR_IMM(ir, IREG_EDX, IREG_EAX, 31); + + return op_pc; +} +uint32_t +ropCWD(UNUSED(codeblock_t *block), ir_data_t *ir, UNUSED(uint8_t opcode), uint32_t fetchdat, UNUSED(uint32_t op_32), uint32_t op_pc) +{ + uop_SAR_IMM(ir, IREG_DX, IREG_AX, 15); + + return op_pc; +} +uint32_t +ropCWDE(UNUSED(codeblock_t *block), ir_data_t *ir, UNUSED(uint8_t opcode), uint32_t fetchdat, UNUSED(uint32_t op_32), uint32_t op_pc) +{ + uop_MOVSX(ir, IREG_EAX, IREG_AX); + + return op_pc; } -#define ropLxS(name, seg) \ -uint32_t rop ## name ## _16(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) \ -{ \ - x86seg *target_seg = NULL; \ - int dest_reg = (fetchdat >> 3) & 7; \ - \ - if ((fetchdat & 0xc0) == 0xc0) \ - return 0; \ - \ - codegen_mark_code_present(block, cs+op_pc, 1); \ - uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc); \ - target_seg = codegen_generate_ea(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32, 0); \ - codegen_check_seg_read(block, ir, target_seg); \ - uop_MEM_LOAD_REG(ir, IREG_temp0_W, ireg_seg_base(target_seg), IREG_eaaddr); \ - uop_MEM_LOAD_REG_OFFSET(ir, IREG_temp1_W, ireg_seg_base(target_seg), IREG_eaaddr, 2); \ - uop_LOAD_SEG(ir, seg, IREG_temp1_W); \ - uop_MOV(ir, IREG_16(dest_reg), IREG_temp0_W); \ - \ - if (seg == &cpu_state.seg_ss) \ - CPU_BLOCK_END(); \ - \ - return op_pc + 1; \ -} \ -uint32_t rop ## name ## _32(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) \ -{ \ - x86seg *target_seg = NULL; \ - int dest_reg = (fetchdat >> 3) & 7; \ - \ - if ((fetchdat & 0xc0) == 0xc0) \ - return 0; \ - \ - codegen_mark_code_present(block, cs+op_pc, 1); \ - uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc); \ - target_seg = codegen_generate_ea(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32, 0); \ - codegen_check_seg_read(block, ir, target_seg); \ - uop_MEM_LOAD_REG(ir, IREG_temp0, ireg_seg_base(target_seg), IREG_eaaddr); \ - uop_MEM_LOAD_REG_OFFSET(ir, IREG_temp1_W, ireg_seg_base(target_seg), IREG_eaaddr, 4); \ - uop_LOAD_SEG(ir, seg, IREG_temp1_W); \ - uop_MOV(ir, IREG_32(dest_reg), IREG_temp0); \ - \ - if (seg == &cpu_state.seg_ss) \ - CPU_BLOCK_END(); \ - \ - return op_pc + 1; \ -} +#define ropLxS(name, seg) \ + uint32_t rop##name##_16(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) \ + { \ + x86seg *target_seg = NULL; \ + int dest_reg = (fetchdat >> 3) & 7; \ + \ + if ((fetchdat & 0xc0) == 0xc0) \ + return 0; \ + \ + codegen_mark_code_present(block, cs + op_pc, 1); \ + uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc); \ + target_seg = codegen_generate_ea(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32, 0); \ + codegen_check_seg_read(block, ir, target_seg); \ + uop_MEM_LOAD_REG(ir, IREG_temp0_W, ireg_seg_base(target_seg), IREG_eaaddr); \ + uop_MEM_LOAD_REG_OFFSET(ir, IREG_temp1_W, ireg_seg_base(target_seg), IREG_eaaddr, 2); \ + uop_LOAD_SEG(ir, seg, IREG_temp1_W); \ + uop_MOV(ir, IREG_16(dest_reg), IREG_temp0_W); \ + \ + if (seg == &cpu_state.seg_ss) \ + CPU_BLOCK_END(); \ + \ + return op_pc + 1; \ + } \ + uint32_t rop##name##_32(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) \ + { \ + x86seg *target_seg = NULL; \ + int dest_reg = (fetchdat >> 3) & 7; \ + \ + if ((fetchdat & 0xc0) == 0xc0) \ + return 0; \ + \ + codegen_mark_code_present(block, cs + op_pc, 1); \ + uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc); \ + target_seg = codegen_generate_ea(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32, 0); \ + codegen_check_seg_read(block, ir, target_seg); \ + uop_MEM_LOAD_REG(ir, IREG_temp0, ireg_seg_base(target_seg), IREG_eaaddr); \ + uop_MEM_LOAD_REG_OFFSET(ir, IREG_temp1_W, ireg_seg_base(target_seg), IREG_eaaddr, 4); \ + uop_LOAD_SEG(ir, seg, IREG_temp1_W); \ + uop_MOV(ir, IREG_32(dest_reg), IREG_temp0); \ + \ + if (seg == &cpu_state.seg_ss) \ + CPU_BLOCK_END(); \ + \ + return op_pc + 1; \ + } ropLxS(LDS, &cpu_state.seg_ds) ropLxS(LES, &cpu_state.seg_es) @@ -566,49 +571,56 @@ ropLxS(LFS, &cpu_state.seg_fs) ropLxS(LGS, &cpu_state.seg_gs) ropLxS(LSS, &cpu_state.seg_ss) -uint32_t ropCLC(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) +uint32_t +ropCLC(UNUSED(codeblock_t *block), ir_data_t *ir, UNUSED(uint8_t opcode), uint32_t fetchdat, UNUSED(uint32_t op_32), uint32_t op_pc) { - uop_CALL_FUNC(ir, flags_rebuild); - uop_AND_IMM(ir, IREG_flags, IREG_flags, ~C_FLAG); - return op_pc; + uop_CALL_FUNC(ir, flags_rebuild); + uop_AND_IMM(ir, IREG_flags, IREG_flags, ~C_FLAG); + return op_pc; } -uint32_t ropCMC(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) +uint32_t +ropCMC(UNUSED(codeblock_t *block), ir_data_t *ir, UNUSED(uint8_t opcode), uint32_t fetchdat, UNUSED(uint32_t op_32), uint32_t op_pc) { - uop_CALL_FUNC(ir, flags_rebuild); - uop_XOR_IMM(ir, IREG_flags, IREG_flags, C_FLAG); - return op_pc; + uop_CALL_FUNC(ir, flags_rebuild); + uop_XOR_IMM(ir, IREG_flags, IREG_flags, C_FLAG); + return op_pc; } -uint32_t ropSTC(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) +uint32_t +ropSTC(UNUSED(codeblock_t *block), ir_data_t *ir, UNUSED(uint8_t opcode), uint32_t fetchdat, UNUSED(uint32_t op_32), uint32_t op_pc) { - uop_CALL_FUNC(ir, flags_rebuild); - uop_OR_IMM(ir, IREG_flags, IREG_flags, C_FLAG); - return op_pc; + uop_CALL_FUNC(ir, flags_rebuild); + uop_OR_IMM(ir, IREG_flags, IREG_flags, C_FLAG); + return op_pc; } -uint32_t ropCLD(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) +uint32_t +ropCLD(UNUSED(codeblock_t *block), ir_data_t *ir, UNUSED(uint8_t opcode), uint32_t fetchdat, UNUSED(uint32_t op_32), uint32_t op_pc) { - uop_AND_IMM(ir, IREG_flags, IREG_flags, ~D_FLAG); - return op_pc; + uop_AND_IMM(ir, IREG_flags, IREG_flags, ~D_FLAG); + return op_pc; } -uint32_t ropSTD(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) +uint32_t +ropSTD(UNUSED(codeblock_t *block), ir_data_t *ir, UNUSED(uint8_t opcode), uint32_t fetchdat, UNUSED(uint32_t op_32), uint32_t op_pc) { - uop_OR_IMM(ir, IREG_flags, IREG_flags, D_FLAG); - return op_pc; + uop_OR_IMM(ir, IREG_flags, IREG_flags, D_FLAG); + return op_pc; } -uint32_t ropCLI(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) +uint32_t +ropCLI(UNUSED(codeblock_t *block), ir_data_t *ir, UNUSED(uint8_t opcode), uint32_t fetchdat, UNUSED(uint32_t op_32), uint32_t op_pc) { - if (!IOPLp && (cr4 & (CR4_VME | CR4_PVI))) - return 0; + if (!IOPLp && (cr4 & (CR4_VME | CR4_PVI))) + return 0; - uop_AND_IMM(ir, IREG_flags, IREG_flags, ~I_FLAG); - return op_pc; + uop_AND_IMM(ir, IREG_flags, IREG_flags, ~I_FLAG); + return op_pc; } -uint32_t ropSTI(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) +uint32_t +ropSTI(UNUSED(codeblock_t *block), ir_data_t *ir, UNUSED(uint8_t opcode), uint32_t fetchdat, UNUSED(uint32_t op_32), uint32_t op_pc) { - if (!IOPLp && (cr4 & (CR4_VME | CR4_PVI))) - return 0; + if (!IOPLp && (cr4 & (CR4_VME | CR4_PVI))) + return 0; - uop_OR_IMM(ir, IREG_flags, IREG_flags, I_FLAG); - return op_pc; + uop_OR_IMM(ir, IREG_flags, IREG_flags, I_FLAG); + return op_pc; } diff --git a/src/codegen_new/codegen_ops_mmx_arith.c b/src/codegen_new/codegen_ops_mmx_arith.c index 66124ca5e..e99b4c56d 100644 --- a/src/codegen_new/codegen_ops_mmx_arith.c +++ b/src/codegen_new/codegen_ops_mmx_arith.c @@ -5,6 +5,8 @@ #include "x86.h" #include "x86_flags.h" +#include "x86seg_common.h" +#include "x86seg.h" #include "386_common.h" #include "codegen.h" #include "codegen_accumulate.h" @@ -13,32 +15,30 @@ #include "codegen_ops_mmx_arith.h" #include "codegen_ops_helpers.h" -#define ropParith(func) \ -uint32_t rop ## func(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) \ -{ \ - int dest_reg = (fetchdat >> 3) & 7; \ - \ - uop_MMX_ENTER(ir); \ - codegen_mark_code_present(block, cs+op_pc, 1); \ - if ((fetchdat & 0xc0) == 0xc0) \ - { \ - int src_reg = fetchdat & 7; \ - uop_ ## func(ir, IREG_MM(dest_reg), IREG_MM(dest_reg), IREG_MM(src_reg)); \ - } \ - else \ - { \ - x86seg *target_seg; \ - \ - uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc); \ - target_seg = codegen_generate_ea(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32, 0); \ - codegen_check_seg_read(block, ir, target_seg); \ - uop_MEM_LOAD_REG(ir, IREG_temp0_Q, ireg_seg_base(target_seg), IREG_eaaddr); \ - uop_ ## func(ir, IREG_MM(dest_reg), IREG_MM(dest_reg), IREG_temp0_Q); \ - } \ - \ - return op_pc + 1; \ -} +#define ropParith(func) \ + uint32_t rop##func(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) \ + { \ + int dest_reg = (fetchdat >> 3) & 7; \ + \ + uop_MMX_ENTER(ir); \ + codegen_mark_code_present(block, cs + op_pc, 1); \ + if ((fetchdat & 0xc0) == 0xc0) { \ + int src_reg = fetchdat & 7; \ + uop_##func(ir, IREG_MM(dest_reg), IREG_MM(dest_reg), IREG_MM(src_reg)); \ + } else { \ + x86seg *target_seg; \ + \ + uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc); \ + target_seg = codegen_generate_ea(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32, 0); \ + codegen_check_seg_read(block, ir, target_seg); \ + uop_MEM_LOAD_REG(ir, IREG_temp0_Q, ireg_seg_base(target_seg), IREG_eaaddr); \ + uop_##func(ir, IREG_MM(dest_reg), IREG_MM(dest_reg), IREG_temp0_Q); \ + } \ + \ + return op_pc + 1; \ + } +// clang-format off ropParith(PADDB) ropParith(PADDW) ropParith(PADDD) @@ -58,3 +58,4 @@ ropParith(PSUBUSW) ropParith(PMADDWD) ropParith(PMULHW) ropParith(PMULLW) + // clang-format on diff --git a/src/codegen_new/codegen_ops_mmx_cmp.c b/src/codegen_new/codegen_ops_mmx_cmp.c index 29a28e14f..6f38cba67 100644 --- a/src/codegen_new/codegen_ops_mmx_cmp.c +++ b/src/codegen_new/codegen_ops_mmx_cmp.c @@ -5,6 +5,8 @@ #include "x86.h" #include "x86_flags.h" +#include "x86seg_common.h" +#include "x86seg.h" #include "386_common.h" #include "codegen.h" #include "codegen_accumulate.h" @@ -13,35 +15,34 @@ #include "codegen_ops_mmx_cmp.h" #include "codegen_ops_helpers.h" -#define ropPcmp(func) \ -uint32_t rop ## func(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) \ -{ \ - int dest_reg = (fetchdat >> 3) & 7; \ - \ - uop_MMX_ENTER(ir); \ - codegen_mark_code_present(block, cs+op_pc, 1); \ - if ((fetchdat & 0xc0) == 0xc0) \ - { \ - int src_reg = fetchdat & 7; \ - uop_ ## func(ir, IREG_MM(dest_reg), IREG_MM(dest_reg), IREG_MM(src_reg)); \ - } \ - else \ - { \ - x86seg *target_seg; \ - \ - uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc); \ - target_seg = codegen_generate_ea(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32, 0); \ - codegen_check_seg_read(block, ir, target_seg); \ - uop_MEM_LOAD_REG(ir, IREG_temp0_Q, ireg_seg_base(target_seg), IREG_eaaddr); \ - uop_ ## func(ir, IREG_MM(dest_reg), IREG_MM(dest_reg), IREG_temp0_Q); \ - } \ - \ - return op_pc + 1; \ -} +#define ropPcmp(func) \ + uint32_t rop##func(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) \ + { \ + int dest_reg = (fetchdat >> 3) & 7; \ + \ + uop_MMX_ENTER(ir); \ + codegen_mark_code_present(block, cs + op_pc, 1); \ + if ((fetchdat & 0xc0) == 0xc0) { \ + int src_reg = fetchdat & 7; \ + uop_##func(ir, IREG_MM(dest_reg), IREG_MM(dest_reg), IREG_MM(src_reg)); \ + } else { \ + x86seg *target_seg; \ + \ + uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc); \ + target_seg = codegen_generate_ea(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32, 0); \ + codegen_check_seg_read(block, ir, target_seg); \ + uop_MEM_LOAD_REG(ir, IREG_temp0_Q, ireg_seg_base(target_seg), IREG_eaaddr); \ + uop_##func(ir, IREG_MM(dest_reg), IREG_MM(dest_reg), IREG_temp0_Q); \ + } \ + \ + return op_pc + 1; \ + } +// clang-format off ropPcmp(PCMPEQB) ropPcmp(PCMPEQW) ropPcmp(PCMPEQD) ropPcmp(PCMPGTB) ropPcmp(PCMPGTW) ropPcmp(PCMPGTD) + // clang-format on diff --git a/src/codegen_new/codegen_ops_mmx_loadstore.c b/src/codegen_new/codegen_ops_mmx_loadstore.c index ebdf81555..9d37228ec 100644 --- a/src/codegen_new/codegen_ops_mmx_loadstore.c +++ b/src/codegen_new/codegen_ops_mmx_loadstore.c @@ -2,9 +2,12 @@ #include <86box/86box.h> #include "cpu.h" #include <86box/mem.h> +#include <86box/plat_unused.h> #include "x86.h" #include "x86_flags.h" +#include "x86seg_common.h" +#include "x86seg.h" #include "386_common.h" #include "codegen.h" #include "codegen_accumulate.h" @@ -13,104 +16,96 @@ #include "codegen_ops_mmx_loadstore.h" #include "codegen_ops_helpers.h" -uint32_t ropMOVD_r_d(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) +uint32_t +ropMOVD_r_d(codeblock_t *block, ir_data_t *ir, UNUSED(uint8_t opcode), uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) { - int dest_reg = (fetchdat >> 3) & 7; + int dest_reg = (fetchdat >> 3) & 7; - uop_MMX_ENTER(ir); - codegen_mark_code_present(block, cs+op_pc, 1); - if ((fetchdat & 0xc0) == 0xc0) - { - int src_reg = fetchdat & 7; - uop_MOVZX(ir, IREG_MM(dest_reg), IREG_32(src_reg)); - } - else - { - x86seg *target_seg; + uop_MMX_ENTER(ir); + codegen_mark_code_present(block, cs + op_pc, 1); + if ((fetchdat & 0xc0) == 0xc0) { + int src_reg = fetchdat & 7; + uop_MOVZX(ir, IREG_MM(dest_reg), IREG_32(src_reg)); + } else { + x86seg *target_seg; - uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc); - target_seg = codegen_generate_ea(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32, 0); - codegen_check_seg_read(block, ir, target_seg); - uop_MEM_LOAD_REG(ir, IREG_temp0, ireg_seg_base(target_seg), IREG_eaaddr); - uop_MOVZX(ir, IREG_MM(dest_reg), IREG_temp0); - } + uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc); + target_seg = codegen_generate_ea(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32, 0); + codegen_check_seg_read(block, ir, target_seg); + uop_MEM_LOAD_REG(ir, IREG_temp0, ireg_seg_base(target_seg), IREG_eaaddr); + uop_MOVZX(ir, IREG_MM(dest_reg), IREG_temp0); + } - return op_pc + 1; + return op_pc + 1; } -uint32_t ropMOVD_d_r(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) +uint32_t +ropMOVD_d_r(codeblock_t *block, ir_data_t *ir, UNUSED(uint8_t opcode), uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) { - int src_reg = (fetchdat >> 3) & 7; + int src_reg = (fetchdat >> 3) & 7; - if (cpu_iscyrix && in_smm) - return 0; + if (cpu_iscyrix && in_smm) + return 0; - uop_MMX_ENTER(ir); - codegen_mark_code_present(block, cs+op_pc, 1); - if ((fetchdat & 0xc0) == 0xc0) - { - int dest_reg = fetchdat & 7; - uop_MOVZX(ir, IREG_32(dest_reg), IREG_MM(src_reg)); - } - else - { - x86seg *target_seg; + uop_MMX_ENTER(ir); + codegen_mark_code_present(block, cs + op_pc, 1); + if ((fetchdat & 0xc0) == 0xc0) { + int dest_reg = fetchdat & 7; + uop_MOVZX(ir, IREG_32(dest_reg), IREG_MM(src_reg)); + } else { + x86seg *target_seg; - uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc); - target_seg = codegen_generate_ea(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32, 0); - codegen_check_seg_write(block, ir, target_seg); - CHECK_SEG_LIMITS(block, ir, target_seg, IREG_eaaddr, 3); - uop_MOVZX(ir, IREG_temp0, IREG_MM(src_reg)); - uop_MEM_STORE_REG(ir, ireg_seg_base(target_seg), IREG_eaaddr, IREG_temp0); - } + uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc); + target_seg = codegen_generate_ea(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32, 0); + codegen_check_seg_write(block, ir, target_seg); + CHECK_SEG_LIMITS(block, ir, target_seg, IREG_eaaddr, 3); + uop_MOVZX(ir, IREG_temp0, IREG_MM(src_reg)); + uop_MEM_STORE_REG(ir, ireg_seg_base(target_seg), IREG_eaaddr, IREG_temp0); + } - return op_pc + 1; + return op_pc + 1; } -uint32_t ropMOVQ_r_q(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) +uint32_t +ropMOVQ_r_q(codeblock_t *block, ir_data_t *ir, UNUSED(uint8_t opcode), uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) { - int dest_reg = (fetchdat >> 3) & 7; + int dest_reg = (fetchdat >> 3) & 7; - uop_MMX_ENTER(ir); - codegen_mark_code_present(block, cs+op_pc, 1); - if ((fetchdat & 0xc0) == 0xc0) - { - int src_reg = fetchdat & 7; - uop_MOV(ir, IREG_MM(dest_reg), IREG_MM(src_reg)); - } - else - { - x86seg *target_seg; + uop_MMX_ENTER(ir); + codegen_mark_code_present(block, cs + op_pc, 1); + if ((fetchdat & 0xc0) == 0xc0) { + int src_reg = fetchdat & 7; + uop_MOV(ir, IREG_MM(dest_reg), IREG_MM(src_reg)); + } else { + x86seg *target_seg; - uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc); - target_seg = codegen_generate_ea(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32, 0); - codegen_check_seg_read(block, ir, target_seg); - uop_MEM_LOAD_REG(ir, IREG_MM(dest_reg), ireg_seg_base(target_seg), IREG_eaaddr); - } + uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc); + target_seg = codegen_generate_ea(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32, 0); + codegen_check_seg_read(block, ir, target_seg); + uop_MEM_LOAD_REG(ir, IREG_MM(dest_reg), ireg_seg_base(target_seg), IREG_eaaddr); + } - return op_pc + 1; + return op_pc + 1; } -uint32_t ropMOVQ_q_r(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) +uint32_t +ropMOVQ_q_r(codeblock_t *block, ir_data_t *ir, UNUSED(uint8_t opcode), uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) { - int src_reg = (fetchdat >> 3) & 7; + int src_reg = (fetchdat >> 3) & 7; - uop_MMX_ENTER(ir); - codegen_mark_code_present(block, cs+op_pc, 1); - if ((fetchdat & 0xc0) == 0xc0) - { - int dest_reg = fetchdat & 7; - uop_MOV(ir, IREG_MM(dest_reg), IREG_MM(src_reg)); - } - else - { - x86seg *target_seg; + uop_MMX_ENTER(ir); + codegen_mark_code_present(block, cs + op_pc, 1); + if ((fetchdat & 0xc0) == 0xc0) { + int dest_reg = fetchdat & 7; + uop_MOV(ir, IREG_MM(dest_reg), IREG_MM(src_reg)); + } else { + x86seg *target_seg; - uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc); - target_seg = codegen_generate_ea(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32, 0); - codegen_check_seg_write(block, ir, target_seg); - CHECK_SEG_LIMITS(block, ir, target_seg, IREG_eaaddr, 7); - uop_MEM_STORE_REG(ir, ireg_seg_base(target_seg), IREG_eaaddr, IREG_MM(src_reg)); - } + uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc); + target_seg = codegen_generate_ea(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32, 0); + codegen_check_seg_write(block, ir, target_seg); + CHECK_SEG_LIMITS(block, ir, target_seg, IREG_eaaddr, 7); + uop_MEM_STORE_REG(ir, ireg_seg_base(target_seg), IREG_eaaddr, IREG_MM(src_reg)); + } - return op_pc + 1; + return op_pc + 1; } diff --git a/src/codegen_new/codegen_ops_mmx_logic.c b/src/codegen_new/codegen_ops_mmx_logic.c index 24dc2b4c7..dd50b486e 100644 --- a/src/codegen_new/codegen_ops_mmx_logic.c +++ b/src/codegen_new/codegen_ops_mmx_logic.c @@ -2,9 +2,12 @@ #include <86box/86box.h> #include "cpu.h" #include <86box/mem.h> +#include <86box/plat_unused.h> #include "x86.h" #include "x86_flags.h" +#include "x86seg_common.h" +#include "x86seg.h" #include "386_common.h" #include "codegen.h" #include "codegen_accumulate.h" @@ -13,99 +16,91 @@ #include "codegen_ops_mmx_logic.h" #include "codegen_ops_helpers.h" -uint32_t ropPAND(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) +uint32_t +ropPAND(codeblock_t *block, ir_data_t *ir, UNUSED(uint8_t opcode), uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) { - int dest_reg = (fetchdat >> 3) & 7; + int dest_reg = (fetchdat >> 3) & 7; - uop_MMX_ENTER(ir); - codegen_mark_code_present(block, cs+op_pc, 1); - if ((fetchdat & 0xc0) == 0xc0) - { - int src_reg = fetchdat & 7; - uop_AND(ir, IREG_MM(dest_reg), IREG_MM(dest_reg), IREG_MM(src_reg)); - } - else - { - x86seg *target_seg; + uop_MMX_ENTER(ir); + codegen_mark_code_present(block, cs + op_pc, 1); + if ((fetchdat & 0xc0) == 0xc0) { + int src_reg = fetchdat & 7; + uop_AND(ir, IREG_MM(dest_reg), IREG_MM(dest_reg), IREG_MM(src_reg)); + } else { + x86seg *target_seg; - uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc); - target_seg = codegen_generate_ea(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32, 0); - codegen_check_seg_read(block, ir, target_seg); - uop_MEM_LOAD_REG(ir, IREG_temp0_Q, ireg_seg_base(target_seg), IREG_eaaddr); - uop_AND(ir, IREG_MM(dest_reg), IREG_MM(dest_reg), IREG_temp0_Q); - } + uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc); + target_seg = codegen_generate_ea(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32, 0); + codegen_check_seg_read(block, ir, target_seg); + uop_MEM_LOAD_REG(ir, IREG_temp0_Q, ireg_seg_base(target_seg), IREG_eaaddr); + uop_AND(ir, IREG_MM(dest_reg), IREG_MM(dest_reg), IREG_temp0_Q); + } - return op_pc + 1; + return op_pc + 1; } -uint32_t ropPANDN(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) +uint32_t +ropPANDN(codeblock_t *block, ir_data_t *ir, UNUSED(uint8_t opcode), uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) { - int dest_reg = (fetchdat >> 3) & 7; + int dest_reg = (fetchdat >> 3) & 7; - uop_MMX_ENTER(ir); - codegen_mark_code_present(block, cs+op_pc, 1); - if ((fetchdat & 0xc0) == 0xc0) - { - int src_reg = fetchdat & 7; - uop_ANDN(ir, IREG_MM(dest_reg), IREG_MM(dest_reg), IREG_MM(src_reg)); - } - else - { - x86seg *target_seg; + uop_MMX_ENTER(ir); + codegen_mark_code_present(block, cs + op_pc, 1); + if ((fetchdat & 0xc0) == 0xc0) { + int src_reg = fetchdat & 7; + uop_ANDN(ir, IREG_MM(dest_reg), IREG_MM(dest_reg), IREG_MM(src_reg)); + } else { + x86seg *target_seg; - uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc); - target_seg = codegen_generate_ea(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32, 0); - codegen_check_seg_read(block, ir, target_seg); - uop_MEM_LOAD_REG(ir, IREG_temp0_Q, ireg_seg_base(target_seg), IREG_eaaddr); - uop_ANDN(ir, IREG_MM(dest_reg), IREG_MM(dest_reg), IREG_temp0_Q); - } + uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc); + target_seg = codegen_generate_ea(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32, 0); + codegen_check_seg_read(block, ir, target_seg); + uop_MEM_LOAD_REG(ir, IREG_temp0_Q, ireg_seg_base(target_seg), IREG_eaaddr); + uop_ANDN(ir, IREG_MM(dest_reg), IREG_MM(dest_reg), IREG_temp0_Q); + } - return op_pc + 1; + return op_pc + 1; } -uint32_t ropPOR(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) +uint32_t +ropPOR(codeblock_t *block, ir_data_t *ir, UNUSED(uint8_t opcode), uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) { - int dest_reg = (fetchdat >> 3) & 7; + int dest_reg = (fetchdat >> 3) & 7; - uop_MMX_ENTER(ir); - codegen_mark_code_present(block, cs+op_pc, 1); - if ((fetchdat & 0xc0) == 0xc0) - { - int src_reg = fetchdat & 7; - uop_OR(ir, IREG_MM(dest_reg), IREG_MM(dest_reg), IREG_MM(src_reg)); - } - else - { - x86seg *target_seg; + uop_MMX_ENTER(ir); + codegen_mark_code_present(block, cs + op_pc, 1); + if ((fetchdat & 0xc0) == 0xc0) { + int src_reg = fetchdat & 7; + uop_OR(ir, IREG_MM(dest_reg), IREG_MM(dest_reg), IREG_MM(src_reg)); + } else { + x86seg *target_seg; - uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc); - target_seg = codegen_generate_ea(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32, 0); - codegen_check_seg_read(block, ir, target_seg); - uop_MEM_LOAD_REG(ir, IREG_temp0_Q, ireg_seg_base(target_seg), IREG_eaaddr); - uop_OR(ir, IREG_MM(dest_reg), IREG_MM(dest_reg), IREG_temp0_Q); - } + uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc); + target_seg = codegen_generate_ea(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32, 0); + codegen_check_seg_read(block, ir, target_seg); + uop_MEM_LOAD_REG(ir, IREG_temp0_Q, ireg_seg_base(target_seg), IREG_eaaddr); + uop_OR(ir, IREG_MM(dest_reg), IREG_MM(dest_reg), IREG_temp0_Q); + } - return op_pc + 1; + return op_pc + 1; } -uint32_t ropPXOR(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) +uint32_t +ropPXOR(codeblock_t *block, ir_data_t *ir, UNUSED(uint8_t opcode), uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) { - int dest_reg = (fetchdat >> 3) & 7; + int dest_reg = (fetchdat >> 3) & 7; - uop_MMX_ENTER(ir); - codegen_mark_code_present(block, cs+op_pc, 1); - if ((fetchdat & 0xc0) == 0xc0) - { - int src_reg = fetchdat & 7; - uop_XOR(ir, IREG_MM(dest_reg), IREG_MM(dest_reg), IREG_MM(src_reg)); - } - else - { - x86seg *target_seg; + uop_MMX_ENTER(ir); + codegen_mark_code_present(block, cs + op_pc, 1); + if ((fetchdat & 0xc0) == 0xc0) { + int src_reg = fetchdat & 7; + uop_XOR(ir, IREG_MM(dest_reg), IREG_MM(dest_reg), IREG_MM(src_reg)); + } else { + x86seg *target_seg; - uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc); - target_seg = codegen_generate_ea(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32, 0); - codegen_check_seg_read(block, ir, target_seg); - uop_MEM_LOAD_REG(ir, IREG_temp0_Q, ireg_seg_base(target_seg), IREG_eaaddr); - uop_XOR(ir, IREG_MM(dest_reg), IREG_MM(dest_reg), IREG_temp0_Q); - } + uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc); + target_seg = codegen_generate_ea(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32, 0); + codegen_check_seg_read(block, ir, target_seg); + uop_MEM_LOAD_REG(ir, IREG_temp0_Q, ireg_seg_base(target_seg), IREG_eaaddr); + uop_XOR(ir, IREG_MM(dest_reg), IREG_MM(dest_reg), IREG_temp0_Q); + } - return op_pc + 1; + return op_pc + 1; } diff --git a/src/codegen_new/codegen_ops_mmx_pack.c b/src/codegen_new/codegen_ops_mmx_pack.c index 87b562d17..d25edd52e 100644 --- a/src/codegen_new/codegen_ops_mmx_pack.c +++ b/src/codegen_new/codegen_ops_mmx_pack.c @@ -5,6 +5,8 @@ #include "x86.h" #include "x86_flags.h" +#include "x86seg_common.h" +#include "x86seg.h" #include "386_common.h" #include "codegen.h" #include "codegen_accumulate.h" @@ -13,32 +15,30 @@ #include "codegen_ops_mmx_pack.h" #include "codegen_ops_helpers.h" -#define ropPpack(func) \ -uint32_t rop ## func(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) \ -{ \ - int dest_reg = (fetchdat >> 3) & 7; \ - \ - uop_MMX_ENTER(ir); \ - codegen_mark_code_present(block, cs+op_pc, 1); \ - if ((fetchdat & 0xc0) == 0xc0) \ - { \ - int src_reg = fetchdat & 7; \ - uop_ ## func(ir, IREG_MM(dest_reg), IREG_MM(dest_reg), IREG_MM(src_reg)); \ - } \ - else \ - { \ - x86seg *target_seg; \ - \ - uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc); \ - target_seg = codegen_generate_ea(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32, 0); \ - codegen_check_seg_read(block, ir, target_seg); \ - uop_MEM_LOAD_REG(ir, IREG_temp0_Q, ireg_seg_base(target_seg), IREG_eaaddr); \ - uop_ ## func(ir, IREG_MM(dest_reg), IREG_MM(dest_reg), IREG_temp0_Q); \ - } \ - \ - return op_pc + 1; \ -} +#define ropPpack(func) \ + uint32_t rop##func(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) \ + { \ + int dest_reg = (fetchdat >> 3) & 7; \ + \ + uop_MMX_ENTER(ir); \ + codegen_mark_code_present(block, cs + op_pc, 1); \ + if ((fetchdat & 0xc0) == 0xc0) { \ + int src_reg = fetchdat & 7; \ + uop_##func(ir, IREG_MM(dest_reg), IREG_MM(dest_reg), IREG_MM(src_reg)); \ + } else { \ + x86seg *target_seg; \ + \ + uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc); \ + target_seg = codegen_generate_ea(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32, 0); \ + codegen_check_seg_read(block, ir, target_seg); \ + uop_MEM_LOAD_REG(ir, IREG_temp0_Q, ireg_seg_base(target_seg), IREG_eaaddr); \ + uop_##func(ir, IREG_MM(dest_reg), IREG_MM(dest_reg), IREG_temp0_Q); \ + } \ + \ + return op_pc + 1; \ + } +// clang-format off ropPpack(PACKSSWB) ropPpack(PACKSSDW) ropPpack(PACKUSWB) @@ -48,3 +48,4 @@ ropPpack(PUNPCKLDQ) ropPpack(PUNPCKHBW) ropPpack(PUNPCKHWD) ropPpack(PUNPCKHDQ) + // clang-format on diff --git a/src/codegen_new/codegen_ops_mmx_shift.c b/src/codegen_new/codegen_ops_mmx_shift.c index bb5277ef3..b812a9bb2 100644 --- a/src/codegen_new/codegen_ops_mmx_shift.c +++ b/src/codegen_new/codegen_ops_mmx_shift.c @@ -2,9 +2,12 @@ #include <86box/86box.h> #include "cpu.h" #include <86box/mem.h> +#include <86box/plat_unused.h> #include "x86.h" #include "x86_flags.h" +#include "x86seg_common.h" +#include "x86seg.h" #include "386_common.h" #include "codegen.h" #include "codegen_accumulate.h" @@ -13,84 +16,81 @@ #include "codegen_ops_mmx_shift.h" #include "codegen_ops_helpers.h" -uint32_t ropPSxxW_imm(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) +uint32_t +ropPSxxW_imm(codeblock_t *block, ir_data_t *ir, UNUSED(uint8_t opcode), uint32_t fetchdat, UNUSED(uint32_t op_32), uint32_t op_pc) { - int reg = fetchdat & 7; - int op = fetchdat & 0x38; - int shift = fastreadb(cs + op_pc + 1); + int reg = fetchdat & 7; + int op = fetchdat & 0x38; + int shift = fastreadb(cs + op_pc + 1); - uop_MMX_ENTER(ir); - codegen_mark_code_present(block, cs+op_pc, 1); - switch (op) - { - case 0x10: /*PSRLW*/ - uop_PSRLW_IMM(ir, IREG_MM(reg), IREG_MM(reg), shift); - break; - case 0x20: /*PSRAW*/ - uop_PSRAW_IMM(ir, IREG_MM(reg), IREG_MM(reg), shift); - break; - case 0x30: /*PSLLW*/ - uop_PSLLW_IMM(ir, IREG_MM(reg), IREG_MM(reg), shift); - break; - default: - return 0; + uop_MMX_ENTER(ir); + codegen_mark_code_present(block, cs + op_pc, 1); + switch (op) { + case 0x10: /*PSRLW*/ + uop_PSRLW_IMM(ir, IREG_MM(reg), IREG_MM(reg), shift); + break; + case 0x20: /*PSRAW*/ + uop_PSRAW_IMM(ir, IREG_MM(reg), IREG_MM(reg), shift); + break; + case 0x30: /*PSLLW*/ + uop_PSLLW_IMM(ir, IREG_MM(reg), IREG_MM(reg), shift); + break; + default: + return 0; + } - } - - codegen_mark_code_present(block, cs+op_pc+1, 1); - return op_pc + 2; + codegen_mark_code_present(block, cs + op_pc + 1, 1); + return op_pc + 2; } -uint32_t ropPSxxD_imm(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) +uint32_t +ropPSxxD_imm(codeblock_t *block, ir_data_t *ir, UNUSED(uint8_t opcode), uint32_t fetchdat, UNUSED(uint32_t op_32), uint32_t op_pc) { - int reg = fetchdat & 7; - int op = fetchdat & 0x38; - int shift = fastreadb(cs + op_pc + 1); + int reg = fetchdat & 7; + int op = fetchdat & 0x38; + int shift = fastreadb(cs + op_pc + 1); - uop_MMX_ENTER(ir); - codegen_mark_code_present(block, cs+op_pc, 1); - switch (op) - { - case 0x10: /*PSRLD*/ - uop_PSRLD_IMM(ir, IREG_MM(reg), IREG_MM(reg), shift); - break; - case 0x20: /*PSRAD*/ - uop_PSRAD_IMM(ir, IREG_MM(reg), IREG_MM(reg), shift); - break; - case 0x30: /*PSLLD*/ - uop_PSLLD_IMM(ir, IREG_MM(reg), IREG_MM(reg), shift); - break; - default: - return 0; + uop_MMX_ENTER(ir); + codegen_mark_code_present(block, cs + op_pc, 1); + switch (op) { + case 0x10: /*PSRLD*/ + uop_PSRLD_IMM(ir, IREG_MM(reg), IREG_MM(reg), shift); + break; + case 0x20: /*PSRAD*/ + uop_PSRAD_IMM(ir, IREG_MM(reg), IREG_MM(reg), shift); + break; + case 0x30: /*PSLLD*/ + uop_PSLLD_IMM(ir, IREG_MM(reg), IREG_MM(reg), shift); + break; + default: + return 0; + } - } - - codegen_mark_code_present(block, cs+op_pc+1, 1); - return op_pc + 2; + codegen_mark_code_present(block, cs + op_pc + 1, 1); + return op_pc + 2; } -uint32_t ropPSxxQ_imm(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) +uint32_t +ropPSxxQ_imm(codeblock_t *block, ir_data_t *ir, UNUSED(uint8_t opcode), uint32_t fetchdat, UNUSED(uint32_t op_32), uint32_t op_pc) { - int reg = fetchdat & 7; - int op = fetchdat & 0x38; - int shift = fastreadb(cs + op_pc + 1); + int reg = fetchdat & 7; + int op = fetchdat & 0x38; + int shift = fastreadb(cs + op_pc + 1); - uop_MMX_ENTER(ir); - codegen_mark_code_present(block, cs+op_pc, 1); - switch (op) - { - case 0x10: /*PSRLQ*/ - uop_PSRLQ_IMM(ir, IREG_MM(reg), IREG_MM(reg), shift); - break; - case 0x20: /*PSRAQ*/ - uop_PSRAQ_IMM(ir, IREG_MM(reg), IREG_MM(reg), shift); - break; - case 0x30: /*PSLLQ*/ - uop_PSLLQ_IMM(ir, IREG_MM(reg), IREG_MM(reg), shift); - break; - default: - return 0; + uop_MMX_ENTER(ir); + codegen_mark_code_present(block, cs + op_pc, 1); + switch (op) { + case 0x10: /*PSRLQ*/ + uop_PSRLQ_IMM(ir, IREG_MM(reg), IREG_MM(reg), shift); + break; + case 0x20: /*PSRAQ*/ + uop_PSRAQ_IMM(ir, IREG_MM(reg), IREG_MM(reg), shift); + break; + case 0x30: /*PSLLQ*/ + uop_PSLLQ_IMM(ir, IREG_MM(reg), IREG_MM(reg), shift); + break; + default: + return 0; + } - } - - codegen_mark_code_present(block, cs+op_pc+1, 1); - return op_pc + 2; + codegen_mark_code_present(block, cs + op_pc + 1, 1); + return op_pc + 2; } diff --git a/src/codegen_new/codegen_ops_mov.c b/src/codegen_new/codegen_ops_mov.c index a5618f354..eae7045a8 100644 --- a/src/codegen_new/codegen_ops_mov.c +++ b/src/codegen_new/codegen_ops_mov.c @@ -2,8 +2,11 @@ #include <86box/86box.h> #include "cpu.h" #include <86box/mem.h> +#include <86box/plat_unused.h> #include "x86.h" +#include "x86seg_common.h" +#include "x86seg.h" #include "386_common.h" #include "codegen.h" #include "codegen_ir.h" @@ -11,763 +14,718 @@ #include "codegen_ops_helpers.h" #include "codegen_ops_mov.h" -uint32_t ropMOV_rb_imm(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) +uint32_t +ropMOV_rb_imm(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, UNUSED(uint32_t op_32), uint32_t op_pc) { - uint8_t imm = fastreadb(cs + op_pc); + uint8_t imm = fastreadb(cs + op_pc); - uop_MOV_IMM(ir, IREG_8(opcode & 7), imm); + uop_MOV_IMM(ir, IREG_8(opcode & 7), imm); - codegen_mark_code_present(block, cs+op_pc, 1); - return op_pc + 1; + codegen_mark_code_present(block, cs + op_pc, 1); + return op_pc + 1; } -uint32_t ropMOV_rw_imm(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) +uint32_t +ropMOV_rw_imm(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, UNUSED(uint32_t op_32), uint32_t op_pc) { - uint16_t imm = fastreadw(cs + op_pc); + uint16_t imm = fastreadw(cs + op_pc); - uop_MOV_IMM(ir, IREG_16(opcode & 7), imm); + uop_MOV_IMM(ir, IREG_16(opcode & 7), imm); - codegen_mark_code_present(block, cs+op_pc, 2); - return op_pc + 2; + codegen_mark_code_present(block, cs + op_pc, 2); + return op_pc + 2; } -uint32_t ropMOV_rl_imm(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) +uint32_t +ropMOV_rl_imm(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, UNUSED(uint32_t op_32), uint32_t op_pc) { - if (block->flags & CODEBLOCK_NO_IMMEDIATES) - { - LOAD_IMMEDIATE_FROM_RAM_32(block, ir, IREG_32(opcode & 7), cs + op_pc); - } - else - { - fetchdat = fastreadl(cs + op_pc); - uop_MOV_IMM(ir, IREG_32(opcode & 7), fetchdat); - codegen_mark_code_present(block, cs+op_pc, 4); - } - return op_pc + 4; + if (block->flags & CODEBLOCK_NO_IMMEDIATES) { + LOAD_IMMEDIATE_FROM_RAM_32(block, ir, IREG_32(opcode & 7), cs + op_pc); + } else { + fetchdat = fastreadl(cs + op_pc); + uop_MOV_IMM(ir, IREG_32(opcode & 7), fetchdat); + codegen_mark_code_present(block, cs + op_pc, 4); + } + return op_pc + 4; } - - -uint32_t ropMOV_b_r(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) +uint32_t +ropMOV_b_r(codeblock_t *block, ir_data_t *ir, UNUSED(uint8_t opcode), uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) { - int src_reg = (fetchdat >> 3) & 7; + int src_reg = (fetchdat >> 3) & 7; - codegen_mark_code_present(block, cs+op_pc, 1); - if ((fetchdat & 0xc0) == 0xc0) - { - int dest_reg = fetchdat & 7; - uop_MOV(ir, IREG_8(dest_reg), IREG_8(src_reg)); - } - else - { - x86seg *target_seg; - - uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc); - target_seg = codegen_generate_ea(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32, 0); - codegen_check_seg_write(block, ir, target_seg); - CHECK_SEG_LIMITS(block, ir, target_seg, IREG_eaaddr, 0); - uop_MEM_STORE_REG(ir, ireg_seg_base(target_seg), IREG_eaaddr, IREG_8(src_reg)); - } - - return op_pc + 1; -} -uint32_t ropMOV_w_r(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) -{ - int src_reg = (fetchdat >> 3) & 7; - - codegen_mark_code_present(block, cs+op_pc, 1); - if ((fetchdat & 0xc0) == 0xc0) - { - int dest_reg = fetchdat & 7; - uop_MOV(ir, IREG_16(dest_reg), IREG_16(src_reg)); - } - else - { - x86seg *target_seg; - - uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc); - target_seg = codegen_generate_ea(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32, 0); - codegen_check_seg_write(block, ir, target_seg); - CHECK_SEG_LIMITS(block, ir, target_seg, IREG_eaaddr, 1); - uop_MEM_STORE_REG(ir, ireg_seg_base(target_seg), IREG_eaaddr, IREG_16(src_reg)); - } - - return op_pc + 1; -} -uint32_t ropMOV_l_r(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) -{ - int src_reg = (fetchdat >> 3) & 7; - - codegen_mark_code_present(block, cs+op_pc, 1); - if ((fetchdat & 0xc0) == 0xc0) - { - int dest_reg = fetchdat & 7; - uop_MOV(ir, IREG_32(dest_reg), IREG_32(src_reg)); - } - else - { - x86seg *target_seg; - - uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc); - target_seg = codegen_generate_ea(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32, 0); - codegen_check_seg_write(block, ir, target_seg); - CHECK_SEG_LIMITS(block, ir, target_seg, IREG_eaaddr, 3); - uop_MEM_STORE_REG(ir, ireg_seg_base(target_seg), IREG_eaaddr, IREG_32(src_reg)); - } - - return op_pc + 1; -} -uint32_t ropMOV_r_b(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) -{ - int dest_reg = (fetchdat >> 3) & 7; - - codegen_mark_code_present(block, cs+op_pc, 1); - if ((fetchdat & 0xc0) == 0xc0) - { - int src_reg = fetchdat & 7; - uop_MOV(ir, IREG_8(dest_reg), IREG_8(src_reg)); - } - else - { - x86seg *target_seg; - - uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc); - target_seg = codegen_generate_ea(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32, 0); - codegen_check_seg_read(block, ir, target_seg); - uop_MEM_LOAD_REG(ir, IREG_8(dest_reg), ireg_seg_base(target_seg), IREG_eaaddr); - } - - return op_pc + 1; -} -uint32_t ropMOV_r_w(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) -{ - int dest_reg = (fetchdat >> 3) & 7; - - codegen_mark_code_present(block, cs+op_pc, 1); - if ((fetchdat & 0xc0) == 0xc0) - { - int src_reg = fetchdat & 7; - uop_MOV(ir, IREG_16(dest_reg), IREG_16(src_reg)); - } - else - { - x86seg *target_seg; - - uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc); - target_seg = codegen_generate_ea(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32, 0); - codegen_check_seg_read(block, ir, target_seg); - uop_MEM_LOAD_REG(ir, IREG_16(dest_reg), ireg_seg_base(target_seg), IREG_eaaddr); - } - - return op_pc + 1; -} -uint32_t ropMOV_r_l(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) -{ - int dest_reg = (fetchdat >> 3) & 7; - - codegen_mark_code_present(block, cs+op_pc, 1); - if ((fetchdat & 0xc0) == 0xc0) - { - int src_reg = fetchdat & 7; - uop_MOV(ir, IREG_32(dest_reg), IREG_32(src_reg)); - } - else - { - x86seg *target_seg; - - uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc); - target_seg = codegen_generate_ea(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32, 0); - codegen_check_seg_read(block, ir, target_seg); - uop_MEM_LOAD_REG(ir, IREG_32(dest_reg), ireg_seg_base(target_seg), IREG_eaaddr); - } - - return op_pc + 1; -} - -uint32_t ropMOV_AL_abs(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) -{ - uint32_t addr; - - if (op_32 & 0x200) - addr = fastreadl(cs + op_pc); - else - addr = fastreadw(cs + op_pc); - - uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc); - codegen_check_seg_read(block, ir, op_ea_seg); - uop_MEM_LOAD_ABS(ir, IREG_AL, ireg_seg_base(op_ea_seg), addr); - - codegen_mark_code_present(block, cs+op_pc, (op_32 & 0x200) ? 4 : 2); - return op_pc + ((op_32 & 0x200) ? 4 : 2); -} -uint32_t ropMOV_AX_abs(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) -{ - uint32_t addr; - - if (op_32 & 0x200) - addr = fastreadl(cs + op_pc); - else - addr = fastreadw(cs + op_pc); - - uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc); - codegen_check_seg_read(block, ir, op_ea_seg); - uop_MEM_LOAD_ABS(ir, IREG_AX, ireg_seg_base(op_ea_seg), addr); - - codegen_mark_code_present(block, cs+op_pc, (op_32 & 0x200) ? 4 : 2); - return op_pc + ((op_32 & 0x200) ? 4 : 2); -} -uint32_t ropMOV_EAX_abs(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) -{ - uint32_t addr = 0; - - if (op_32 & 0x200) - { - if (block->flags & CODEBLOCK_NO_IMMEDIATES) - { - LOAD_IMMEDIATE_FROM_RAM_32(block, ir, IREG_eaaddr, cs + op_pc); - } - else - { - addr = fastreadl(cs + op_pc); - codegen_mark_code_present(block, cs+op_pc, 4); - } - } - else - { - addr = fastreadw(cs + op_pc); - codegen_mark_code_present(block, cs+op_pc, 2); - } - - uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc); - codegen_check_seg_read(block, ir, op_ea_seg); - if ((block->flags & CODEBLOCK_NO_IMMEDIATES) && (op_32 & 0x200)) - uop_MEM_LOAD_REG(ir, IREG_EAX, ireg_seg_base(op_ea_seg), IREG_eaaddr); - else - uop_MEM_LOAD_ABS(ir, IREG_EAX, ireg_seg_base(op_ea_seg), addr); - - return op_pc + ((op_32 & 0x200) ? 4 : 2); -} - -uint32_t ropMOV_abs_AL(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) -{ - uint32_t addr; - - if (op_32 & 0x200) - addr = fastreadl(cs + op_pc); - else - addr = fastreadw(cs + op_pc); - - uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc); - codegen_check_seg_write(block, ir, op_ea_seg); - uop_MEM_STORE_ABS(ir, ireg_seg_base(op_ea_seg), addr, IREG_AL); - - codegen_mark_code_present(block, cs+op_pc, (op_32 & 0x200) ? 4 : 2); - return op_pc + ((op_32 & 0x200) ? 4 : 2); -} -uint32_t ropMOV_abs_AX(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) -{ - uint32_t addr; - - if (op_32 & 0x200) - addr = fastreadl(cs + op_pc); - else - addr = fastreadw(cs + op_pc); - - uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc); - codegen_check_seg_write(block, ir, op_ea_seg); - uop_MEM_STORE_ABS(ir, ireg_seg_base(op_ea_seg), addr, IREG_AX); - - codegen_mark_code_present(block, cs+op_pc, (op_32 & 0x200) ? 4 : 2); - return op_pc + ((op_32 & 0x200) ? 4 : 2); -} -uint32_t ropMOV_abs_EAX(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) -{ - uint32_t addr; - - if (op_32 & 0x200) - addr = fastreadl(cs + op_pc); - else - addr = fastreadw(cs + op_pc); - - uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc); - codegen_check_seg_write(block, ir, op_ea_seg); - uop_MEM_STORE_ABS(ir, ireg_seg_base(op_ea_seg), addr, IREG_EAX); - - codegen_mark_code_present(block, cs+op_pc, (op_32 & 0x200) ? 4 : 2); - return op_pc + ((op_32 & 0x200) ? 4 : 2); -} - -uint32_t ropMOV_b_imm(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) -{ + codegen_mark_code_present(block, cs + op_pc, 1); + if ((fetchdat & 0xc0) == 0xc0) { + int dest_reg = fetchdat & 7; + uop_MOV(ir, IREG_8(dest_reg), IREG_8(src_reg)); + } else { x86seg *target_seg; - uint8_t imm; - - codegen_mark_code_present(block, cs+op_pc, 1); - if ((fetchdat & 0xc0) == 0xc0) - { - int dest_reg = fetchdat & 7; - - imm = fastreadb(cs + op_pc + 1); - uop_MOV_IMM(ir, IREG_8(dest_reg), imm); - } - else - { - uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc); - target_seg = codegen_generate_ea(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32, 0); - codegen_check_seg_write(block, ir, target_seg); - imm = fastreadb(cs + op_pc + 1); - uop_MEM_STORE_IMM_8(ir, ireg_seg_base(target_seg), IREG_eaaddr, imm); - } - - codegen_mark_code_present(block, cs+op_pc+1, 1); - return op_pc + 2; -} -uint32_t ropMOV_w_imm(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) -{ - x86seg *target_seg; - uint16_t imm; - - codegen_mark_code_present(block, cs+op_pc, 1); - if ((fetchdat & 0xc0) == 0xc0) - { - int dest_reg = fetchdat & 7; - - imm = fastreadw(cs + op_pc + 1); - uop_MOV_IMM(ir, IREG_16(dest_reg), imm); - } - else - { - uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc); - target_seg = codegen_generate_ea(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32, 0); - codegen_check_seg_write(block, ir, target_seg); - imm = fastreadw(cs + op_pc + 1); - uop_MEM_STORE_IMM_16(ir, ireg_seg_base(target_seg), IREG_eaaddr, imm); - } - - codegen_mark_code_present(block, cs+op_pc+1, 2); - return op_pc + 3; -} -uint32_t ropMOV_l_imm(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) -{ - x86seg *target_seg; - uint32_t imm; - - codegen_mark_code_present(block, cs+op_pc, 1); - if ((fetchdat & 0xc0) == 0xc0) - { - int dest_reg = fetchdat & 7; - - imm = fastreadl(cs + op_pc + 1); - uop_MOV_IMM(ir, IREG_32(dest_reg), imm); - } - else - { - uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc); - target_seg = codegen_generate_ea(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32, 0); - codegen_check_seg_write(block, ir, target_seg); - imm = fastreadl(cs + op_pc + 1); - uop_MEM_STORE_IMM_32(ir, ireg_seg_base(target_seg), IREG_eaaddr, imm); - } - - codegen_mark_code_present(block, cs+op_pc+1, 4); - return op_pc + 5; -} - -uint32_t ropMOV_w_seg(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) -{ - int src_reg; - - codegen_mark_code_present(block, cs+op_pc, 1); - switch (fetchdat & 0x38) - { - case 0x00: /*ES*/ - src_reg = IREG_ES_seg_W; - break; - case 0x08: /*CS*/ - src_reg = IREG_CS_seg_W; - break; - case 0x18: /*DS*/ - src_reg = IREG_DS_seg_W; - break; - case 0x10: /*SS*/ - src_reg = IREG_SS_seg_W; - break; - case 0x20: /*FS*/ - src_reg = IREG_FS_seg_W; - break; - case 0x28: /*GS*/ - src_reg = IREG_GS_seg_W; - break; - default: - return 0; - } - - if ((fetchdat & 0xc0) == 0xc0) - { - int dest_reg = fetchdat & 7; - uop_MOV(ir, IREG_16(dest_reg), src_reg); - } - else - { - x86seg *target_seg; - - uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc); - target_seg = codegen_generate_ea(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32, 0); - codegen_check_seg_write(block, ir, target_seg); - CHECK_SEG_LIMITS(block, ir, target_seg, IREG_eaaddr, 1); - uop_MEM_STORE_REG(ir, ireg_seg_base(target_seg), IREG_eaaddr, src_reg); - } - - return op_pc + 1; -} -uint32_t ropMOV_l_seg(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) -{ - int src_reg; - - codegen_mark_code_present(block, cs+op_pc, 1); - switch (fetchdat & 0x38) - { - case 0x00: /*ES*/ - src_reg = IREG_ES_seg_W; - break; - case 0x08: /*CS*/ - src_reg = IREG_CS_seg_W; - break; - case 0x18: /*DS*/ - src_reg = IREG_DS_seg_W; - break; - case 0x10: /*SS*/ - src_reg = IREG_SS_seg_W; - break; - case 0x20: /*FS*/ - src_reg = IREG_FS_seg_W; - break; - case 0x28: /*GS*/ - src_reg = IREG_GS_seg_W; - break; - default: - return 0; - } - - if ((fetchdat & 0xc0) == 0xc0) - { - int dest_reg = fetchdat & 7; - uop_MOVZX(ir, IREG_32(dest_reg), src_reg); - } - else - { - x86seg *target_seg; - - uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc); - target_seg = codegen_generate_ea(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32, 0); - codegen_check_seg_write(block, ir, target_seg); - uop_MEM_STORE_REG(ir, ireg_seg_base(target_seg), IREG_eaaddr, src_reg); - } - - return op_pc + 1; -} - -uint32_t ropMOV_seg_w(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) -{ - int src_reg; - x86seg *rseg; - - codegen_mark_code_present(block, cs+op_pc, 1); - switch (fetchdat & 0x38) - { - case 0x00: /*ES*/ - rseg = &cpu_state.seg_es; - break; - case 0x18: /*DS*/ - rseg = &cpu_state.seg_ds; - break; - case 0x20: /*FS*/ - rseg = &cpu_state.seg_fs; - break; - case 0x28: /*GS*/ - rseg = &cpu_state.seg_gs; - break; - default: - return 0; - } uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc); - - if ((fetchdat & 0xc0) == 0xc0) - { - uop_MOV(ir, IREG_temp0_W, IREG_16(fetchdat & 7)); - src_reg = IREG_temp0_W; - } - else - { - x86seg *target_seg; + target_seg = codegen_generate_ea(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32, 0); + codegen_check_seg_write(block, ir, target_seg); + CHECK_SEG_LIMITS(block, ir, target_seg, IREG_eaaddr, 0); + uop_MEM_STORE_REG(ir, ireg_seg_base(target_seg), IREG_eaaddr, IREG_8(src_reg)); + } - target_seg = codegen_generate_ea(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32, 0); - codegen_check_seg_read(block, ir, target_seg); - uop_MEM_LOAD_REG(ir, IREG_temp0_W, ireg_seg_base(target_seg), IREG_eaaddr); - src_reg = IREG_temp0_W; - } + return op_pc + 1; +} +uint32_t +ropMOV_w_r(codeblock_t *block, ir_data_t *ir, UNUSED(uint8_t opcode), uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) +{ + int src_reg = (fetchdat >> 3) & 7; - uop_LOAD_SEG(ir, rseg, src_reg); + codegen_mark_code_present(block, cs + op_pc, 1); + if ((fetchdat & 0xc0) == 0xc0) { + int dest_reg = fetchdat & 7; + uop_MOV(ir, IREG_16(dest_reg), IREG_16(src_reg)); + } else { + x86seg *target_seg; - return op_pc + 1; + uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc); + target_seg = codegen_generate_ea(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32, 0); + codegen_check_seg_write(block, ir, target_seg); + CHECK_SEG_LIMITS(block, ir, target_seg, IREG_eaaddr, 1); + uop_MEM_STORE_REG(ir, ireg_seg_base(target_seg), IREG_eaaddr, IREG_16(src_reg)); + } + + return op_pc + 1; +} +uint32_t +ropMOV_l_r(codeblock_t *block, ir_data_t *ir, UNUSED(uint8_t opcode), uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) +{ + int src_reg = (fetchdat >> 3) & 7; + + codegen_mark_code_present(block, cs + op_pc, 1); + if ((fetchdat & 0xc0) == 0xc0) { + int dest_reg = fetchdat & 7; + uop_MOV(ir, IREG_32(dest_reg), IREG_32(src_reg)); + } else { + x86seg *target_seg; + + uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc); + target_seg = codegen_generate_ea(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32, 0); + codegen_check_seg_write(block, ir, target_seg); + CHECK_SEG_LIMITS(block, ir, target_seg, IREG_eaaddr, 3); + uop_MEM_STORE_REG(ir, ireg_seg_base(target_seg), IREG_eaaddr, IREG_32(src_reg)); + } + + return op_pc + 1; +} +uint32_t +ropMOV_r_b(codeblock_t *block, ir_data_t *ir, UNUSED(uint8_t opcode), uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) +{ + int dest_reg = (fetchdat >> 3) & 7; + + codegen_mark_code_present(block, cs + op_pc, 1); + if ((fetchdat & 0xc0) == 0xc0) { + int src_reg = fetchdat & 7; + uop_MOV(ir, IREG_8(dest_reg), IREG_8(src_reg)); + } else { + x86seg *target_seg; + + uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc); + target_seg = codegen_generate_ea(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32, 0); + codegen_check_seg_read(block, ir, target_seg); + uop_MEM_LOAD_REG(ir, IREG_8(dest_reg), ireg_seg_base(target_seg), IREG_eaaddr); + } + + return op_pc + 1; +} +uint32_t +ropMOV_r_w(codeblock_t *block, ir_data_t *ir, UNUSED(uint8_t opcode), uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) +{ + int dest_reg = (fetchdat >> 3) & 7; + + codegen_mark_code_present(block, cs + op_pc, 1); + if ((fetchdat & 0xc0) == 0xc0) { + int src_reg = fetchdat & 7; + uop_MOV(ir, IREG_16(dest_reg), IREG_16(src_reg)); + } else { + x86seg *target_seg; + + uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc); + target_seg = codegen_generate_ea(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32, 0); + codegen_check_seg_read(block, ir, target_seg); + uop_MEM_LOAD_REG(ir, IREG_16(dest_reg), ireg_seg_base(target_seg), IREG_eaaddr); + } + + return op_pc + 1; +} +uint32_t +ropMOV_r_l(codeblock_t *block, ir_data_t *ir, UNUSED(uint8_t opcode), uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) +{ + int dest_reg = (fetchdat >> 3) & 7; + + codegen_mark_code_present(block, cs + op_pc, 1); + if ((fetchdat & 0xc0) == 0xc0) { + int src_reg = fetchdat & 7; + uop_MOV(ir, IREG_32(dest_reg), IREG_32(src_reg)); + } else { + x86seg *target_seg; + + uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc); + target_seg = codegen_generate_ea(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32, 0); + codegen_check_seg_read(block, ir, target_seg); + uop_MEM_LOAD_REG(ir, IREG_32(dest_reg), ireg_seg_base(target_seg), IREG_eaaddr); + } + + return op_pc + 1; } -uint32_t ropMOVSX_16_8(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) +uint32_t +ropMOV_AL_abs(codeblock_t *block, ir_data_t *ir, UNUSED(uint8_t opcode), uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) { - int dest_reg = (fetchdat >> 3) & 7; + uint32_t addr; - codegen_mark_code_present(block, cs+op_pc, 1); - if ((fetchdat & 0xc0) == 0xc0) - { - int src_reg = fetchdat & 7; - uop_MOVSX(ir, IREG_16(dest_reg), IREG_8(src_reg)); - } - else - { - x86seg *target_seg; + if (op_32 & 0x200) + addr = fastreadl(cs + op_pc); + else + addr = fastreadw(cs + op_pc); - uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc); - target_seg = codegen_generate_ea(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32, 0); - codegen_check_seg_read(block, ir, target_seg); - uop_MEM_LOAD_REG(ir, IREG_temp0_B, ireg_seg_base(target_seg), IREG_eaaddr); - uop_MOVSX(ir, IREG_16(dest_reg), IREG_temp0_B); - } + uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc); + codegen_check_seg_read(block, ir, op_ea_seg); + uop_MEM_LOAD_ABS(ir, IREG_AL, ireg_seg_base(op_ea_seg), addr); - return op_pc + 1; + codegen_mark_code_present(block, cs + op_pc, (op_32 & 0x200) ? 4 : 2); + return op_pc + ((op_32 & 0x200) ? 4 : 2); } -uint32_t ropMOVSX_32_8(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) +uint32_t +ropMOV_AX_abs(codeblock_t *block, ir_data_t *ir, UNUSED(uint8_t opcode), uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) { - int dest_reg = (fetchdat >> 3) & 7; + uint32_t addr; - codegen_mark_code_present(block, cs+op_pc, 1); - if ((fetchdat & 0xc0) == 0xc0) - { - int src_reg = fetchdat & 7; - uop_MOVSX(ir, IREG_32(dest_reg), IREG_8(src_reg)); - } - else - { - x86seg *target_seg; + if (op_32 & 0x200) + addr = fastreadl(cs + op_pc); + else + addr = fastreadw(cs + op_pc); - uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc); - target_seg = codegen_generate_ea(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32, 0); - codegen_check_seg_read(block, ir, target_seg); - uop_MEM_LOAD_REG(ir, IREG_temp0_B, ireg_seg_base(target_seg), IREG_eaaddr); - uop_MOVSX(ir, IREG_32(dest_reg), IREG_temp0_B); - } + uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc); + codegen_check_seg_read(block, ir, op_ea_seg); + uop_MEM_LOAD_ABS(ir, IREG_AX, ireg_seg_base(op_ea_seg), addr); - return op_pc + 1; + codegen_mark_code_present(block, cs + op_pc, (op_32 & 0x200) ? 4 : 2); + return op_pc + ((op_32 & 0x200) ? 4 : 2); } -uint32_t ropMOVSX_32_16(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) +uint32_t +ropMOV_EAX_abs(codeblock_t *block, ir_data_t *ir, UNUSED(uint8_t opcode), uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) { - int dest_reg = (fetchdat >> 3) & 7; + uint32_t addr = 0; - codegen_mark_code_present(block, cs+op_pc, 1); - if ((fetchdat & 0xc0) == 0xc0) - { - int src_reg = fetchdat & 7; - uop_MOVSX(ir, IREG_32(dest_reg), IREG_16(src_reg)); + if (op_32 & 0x200) { + if (block->flags & CODEBLOCK_NO_IMMEDIATES) { + LOAD_IMMEDIATE_FROM_RAM_32(block, ir, IREG_eaaddr, cs + op_pc); + } else { + addr = fastreadl(cs + op_pc); + codegen_mark_code_present(block, cs + op_pc, 4); } - else - { - x86seg *target_seg; + } else { + addr = fastreadw(cs + op_pc); + codegen_mark_code_present(block, cs + op_pc, 2); + } - uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc); - target_seg = codegen_generate_ea(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32, 0); - codegen_check_seg_read(block, ir, target_seg); - uop_MEM_LOAD_REG(ir, IREG_temp0_W, ireg_seg_base(target_seg), IREG_eaaddr); - uop_MOVSX(ir, IREG_32(dest_reg), IREG_temp0_W); - } + uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc); + codegen_check_seg_read(block, ir, op_ea_seg); + if ((block->flags & CODEBLOCK_NO_IMMEDIATES) && (op_32 & 0x200)) + uop_MEM_LOAD_REG(ir, IREG_EAX, ireg_seg_base(op_ea_seg), IREG_eaaddr); + else + uop_MEM_LOAD_ABS(ir, IREG_EAX, ireg_seg_base(op_ea_seg), addr); - return op_pc + 1; + return op_pc + ((op_32 & 0x200) ? 4 : 2); } -uint32_t ropMOVZX_16_8(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) +uint32_t +ropMOV_abs_AL(codeblock_t *block, ir_data_t *ir, UNUSED(uint8_t opcode), uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) { - int dest_reg = (fetchdat >> 3) & 7; + uint32_t addr; - codegen_mark_code_present(block, cs+op_pc, 1); - if ((fetchdat & 0xc0) == 0xc0) - { - int src_reg = fetchdat & 7; - uop_MOVZX(ir, IREG_16(dest_reg), IREG_8(src_reg)); - } - else - { - x86seg *target_seg; + if (op_32 & 0x200) + addr = fastreadl(cs + op_pc); + else + addr = fastreadw(cs + op_pc); - uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc); - target_seg = codegen_generate_ea(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32, 0); - codegen_check_seg_read(block, ir, target_seg); - uop_MEM_LOAD_REG(ir, IREG_temp0_B, ireg_seg_base(target_seg), IREG_eaaddr); - uop_MOVZX(ir, IREG_16(dest_reg), IREG_temp0_B); - } + uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc); + codegen_check_seg_write(block, ir, op_ea_seg); + uop_MEM_STORE_ABS(ir, ireg_seg_base(op_ea_seg), addr, IREG_AL); - return op_pc + 1; + codegen_mark_code_present(block, cs + op_pc, (op_32 & 0x200) ? 4 : 2); + return op_pc + ((op_32 & 0x200) ? 4 : 2); } -uint32_t ropMOVZX_32_8(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) +uint32_t +ropMOV_abs_AX(codeblock_t *block, ir_data_t *ir, UNUSED(uint8_t opcode), uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) { - int dest_reg = (fetchdat >> 3) & 7; + uint32_t addr; - codegen_mark_code_present(block, cs+op_pc, 1); - if ((fetchdat & 0xc0) == 0xc0) - { - int src_reg = fetchdat & 7; - uop_MOVZX(ir, IREG_32(dest_reg), IREG_8(src_reg)); - } - else - { - x86seg *target_seg; + if (op_32 & 0x200) + addr = fastreadl(cs + op_pc); + else + addr = fastreadw(cs + op_pc); - uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc); - target_seg = codegen_generate_ea(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32, 0); - codegen_check_seg_read(block, ir, target_seg); - uop_MEM_LOAD_REG(ir, IREG_temp0_B, ireg_seg_base(target_seg), IREG_eaaddr); - uop_MOVZX(ir, IREG_32(dest_reg), IREG_temp0_B); - } + uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc); + codegen_check_seg_write(block, ir, op_ea_seg); + uop_MEM_STORE_ABS(ir, ireg_seg_base(op_ea_seg), addr, IREG_AX); - return op_pc + 1; + codegen_mark_code_present(block, cs + op_pc, (op_32 & 0x200) ? 4 : 2); + return op_pc + ((op_32 & 0x200) ? 4 : 2); } -uint32_t ropMOVZX_32_16(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) +uint32_t +ropMOV_abs_EAX(codeblock_t *block, ir_data_t *ir, UNUSED(uint8_t opcode), uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) { - int dest_reg = (fetchdat >> 3) & 7; + uint32_t addr; - codegen_mark_code_present(block, cs+op_pc, 1); - if ((fetchdat & 0xc0) == 0xc0) - { - int src_reg = fetchdat & 7; - uop_MOVZX(ir, IREG_32(dest_reg), IREG_16(src_reg)); - } - else - { - x86seg *target_seg; + if (op_32 & 0x200) + addr = fastreadl(cs + op_pc); + else + addr = fastreadw(cs + op_pc); - uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc); - target_seg = codegen_generate_ea(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32, 0); - codegen_check_seg_read(block, ir, target_seg); - uop_MEM_LOAD_REG(ir, IREG_temp0_W, ireg_seg_base(target_seg), IREG_eaaddr); - uop_MOVZX(ir, IREG_32(dest_reg), IREG_temp0_W); - } + uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc); + codegen_check_seg_write(block, ir, op_ea_seg); + uop_MEM_STORE_ABS(ir, ireg_seg_base(op_ea_seg), addr, IREG_EAX); - return op_pc + 1; + codegen_mark_code_present(block, cs + op_pc, (op_32 & 0x200) ? 4 : 2); + return op_pc + ((op_32 & 0x200) ? 4 : 2); } - -uint32_t ropXCHG_AX(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) +uint32_t +ropMOV_b_imm(codeblock_t *block, ir_data_t *ir, UNUSED(uint8_t opcode), uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) { - int reg2 = IREG_16(opcode & 7); - - uop_MOV(ir, IREG_temp0_W, IREG_AX); - uop_MOV(ir, IREG_AX, reg2); + x86seg *target_seg; + uint8_t imm; + + codegen_mark_code_present(block, cs + op_pc, 1); + if ((fetchdat & 0xc0) == 0xc0) { + int dest_reg = fetchdat & 7; + + imm = fastreadb(cs + op_pc + 1); + uop_MOV_IMM(ir, IREG_8(dest_reg), imm); + } else { + uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc); + target_seg = codegen_generate_ea(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32, 0); + codegen_check_seg_write(block, ir, target_seg); + imm = fastreadb(cs + op_pc + 1); + uop_MEM_STORE_IMM_8(ir, ireg_seg_base(target_seg), IREG_eaaddr, imm); + } + + codegen_mark_code_present(block, cs + op_pc + 1, 1); + return op_pc + 2; +} +uint32_t +ropMOV_w_imm(codeblock_t *block, ir_data_t *ir, UNUSED(uint8_t opcode), uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) +{ + x86seg *target_seg; + uint16_t imm; + + codegen_mark_code_present(block, cs + op_pc, 1); + if ((fetchdat & 0xc0) == 0xc0) { + int dest_reg = fetchdat & 7; + + imm = fastreadw(cs + op_pc + 1); + uop_MOV_IMM(ir, IREG_16(dest_reg), imm); + } else { + uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc); + target_seg = codegen_generate_ea(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32, 0); + codegen_check_seg_write(block, ir, target_seg); + imm = fastreadw(cs + op_pc + 1); + uop_MEM_STORE_IMM_16(ir, ireg_seg_base(target_seg), IREG_eaaddr, imm); + } + + codegen_mark_code_present(block, cs + op_pc + 1, 2); + return op_pc + 3; +} +uint32_t +ropMOV_l_imm(codeblock_t *block, ir_data_t *ir, UNUSED(uint8_t opcode), uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) +{ + x86seg *target_seg; + uint32_t imm; + + codegen_mark_code_present(block, cs + op_pc, 1); + if ((fetchdat & 0xc0) == 0xc0) { + int dest_reg = fetchdat & 7; + + imm = fastreadl(cs + op_pc + 1); + uop_MOV_IMM(ir, IREG_32(dest_reg), imm); + } else { + uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc); + target_seg = codegen_generate_ea(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32, 0); + codegen_check_seg_write(block, ir, target_seg); + imm = fastreadl(cs + op_pc + 1); + uop_MEM_STORE_IMM_32(ir, ireg_seg_base(target_seg), IREG_eaaddr, imm); + } + + codegen_mark_code_present(block, cs + op_pc + 1, 4); + return op_pc + 5; +} + +uint32_t +ropMOV_w_seg(codeblock_t *block, ir_data_t *ir, UNUSED(uint8_t opcode), uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) +{ + int src_reg; + + codegen_mark_code_present(block, cs + op_pc, 1); + switch (fetchdat & 0x38) { + case 0x00: /*ES*/ + src_reg = IREG_ES_seg_W; + break; + case 0x08: /*CS*/ + src_reg = IREG_CS_seg_W; + break; + case 0x18: /*DS*/ + src_reg = IREG_DS_seg_W; + break; + case 0x10: /*SS*/ + src_reg = IREG_SS_seg_W; + break; + case 0x20: /*FS*/ + src_reg = IREG_FS_seg_W; + break; + case 0x28: /*GS*/ + src_reg = IREG_GS_seg_W; + break; + default: + return 0; + } + + if ((fetchdat & 0xc0) == 0xc0) { + int dest_reg = fetchdat & 7; + uop_MOV(ir, IREG_16(dest_reg), src_reg); + } else { + x86seg *target_seg; + + uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc); + target_seg = codegen_generate_ea(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32, 0); + codegen_check_seg_write(block, ir, target_seg); + CHECK_SEG_LIMITS(block, ir, target_seg, IREG_eaaddr, 1); + uop_MEM_STORE_REG(ir, ireg_seg_base(target_seg), IREG_eaaddr, src_reg); + } + + return op_pc + 1; +} +uint32_t +ropMOV_l_seg(codeblock_t *block, ir_data_t *ir, UNUSED(uint8_t opcode), uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) +{ + int src_reg; + + codegen_mark_code_present(block, cs + op_pc, 1); + switch (fetchdat & 0x38) { + case 0x00: /*ES*/ + src_reg = IREG_ES_seg_W; + break; + case 0x08: /*CS*/ + src_reg = IREG_CS_seg_W; + break; + case 0x18: /*DS*/ + src_reg = IREG_DS_seg_W; + break; + case 0x10: /*SS*/ + src_reg = IREG_SS_seg_W; + break; + case 0x20: /*FS*/ + src_reg = IREG_FS_seg_W; + break; + case 0x28: /*GS*/ + src_reg = IREG_GS_seg_W; + break; + default: + return 0; + } + + if ((fetchdat & 0xc0) == 0xc0) { + int dest_reg = fetchdat & 7; + uop_MOVZX(ir, IREG_32(dest_reg), src_reg); + } else { + x86seg *target_seg; + + uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc); + target_seg = codegen_generate_ea(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32, 0); + codegen_check_seg_write(block, ir, target_seg); + uop_MEM_STORE_REG(ir, ireg_seg_base(target_seg), IREG_eaaddr, src_reg); + } + + return op_pc + 1; +} + +uint32_t +ropMOV_seg_w(codeblock_t *block, ir_data_t *ir, UNUSED(uint8_t opcode), uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) +{ + int src_reg; + x86seg *rseg; + + codegen_mark_code_present(block, cs + op_pc, 1); + switch (fetchdat & 0x38) { + case 0x00: /*ES*/ + rseg = &cpu_state.seg_es; + break; + case 0x18: /*DS*/ + rseg = &cpu_state.seg_ds; + break; + case 0x20: /*FS*/ + rseg = &cpu_state.seg_fs; + break; + case 0x28: /*GS*/ + rseg = &cpu_state.seg_gs; + break; + default: + return 0; + } + + uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc); + + if ((fetchdat & 0xc0) == 0xc0) { + uop_MOV(ir, IREG_temp0_W, IREG_16(fetchdat & 7)); + src_reg = IREG_temp0_W; + } else { + x86seg *target_seg; + + target_seg = codegen_generate_ea(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32, 0); + codegen_check_seg_read(block, ir, target_seg); + uop_MEM_LOAD_REG(ir, IREG_temp0_W, ireg_seg_base(target_seg), IREG_eaaddr); + src_reg = IREG_temp0_W; + } + + uop_LOAD_SEG(ir, rseg, src_reg); + + return op_pc + 1; +} + +uint32_t +ropMOVSX_16_8(codeblock_t *block, ir_data_t *ir, UNUSED(uint8_t opcode), uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) +{ + int dest_reg = (fetchdat >> 3) & 7; + + codegen_mark_code_present(block, cs + op_pc, 1); + if ((fetchdat & 0xc0) == 0xc0) { + int src_reg = fetchdat & 7; + uop_MOVSX(ir, IREG_16(dest_reg), IREG_8(src_reg)); + } else { + x86seg *target_seg; + + uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc); + target_seg = codegen_generate_ea(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32, 0); + codegen_check_seg_read(block, ir, target_seg); + uop_MEM_LOAD_REG(ir, IREG_temp0_B, ireg_seg_base(target_seg), IREG_eaaddr); + uop_MOVSX(ir, IREG_16(dest_reg), IREG_temp0_B); + } + + return op_pc + 1; +} +uint32_t +ropMOVSX_32_8(codeblock_t *block, ir_data_t *ir, UNUSED(uint8_t opcode), uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) +{ + int dest_reg = (fetchdat >> 3) & 7; + + codegen_mark_code_present(block, cs + op_pc, 1); + if ((fetchdat & 0xc0) == 0xc0) { + int src_reg = fetchdat & 7; + uop_MOVSX(ir, IREG_32(dest_reg), IREG_8(src_reg)); + } else { + x86seg *target_seg; + + uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc); + target_seg = codegen_generate_ea(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32, 0); + codegen_check_seg_read(block, ir, target_seg); + uop_MEM_LOAD_REG(ir, IREG_temp0_B, ireg_seg_base(target_seg), IREG_eaaddr); + uop_MOVSX(ir, IREG_32(dest_reg), IREG_temp0_B); + } + + return op_pc + 1; +} +uint32_t +ropMOVSX_32_16(codeblock_t *block, ir_data_t *ir, UNUSED(uint8_t opcode), uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) +{ + int dest_reg = (fetchdat >> 3) & 7; + + codegen_mark_code_present(block, cs + op_pc, 1); + if ((fetchdat & 0xc0) == 0xc0) { + int src_reg = fetchdat & 7; + uop_MOVSX(ir, IREG_32(dest_reg), IREG_16(src_reg)); + } else { + x86seg *target_seg; + + uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc); + target_seg = codegen_generate_ea(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32, 0); + codegen_check_seg_read(block, ir, target_seg); + uop_MEM_LOAD_REG(ir, IREG_temp0_W, ireg_seg_base(target_seg), IREG_eaaddr); + uop_MOVSX(ir, IREG_32(dest_reg), IREG_temp0_W); + } + + return op_pc + 1; +} + +uint32_t +ropMOVZX_16_8(codeblock_t *block, ir_data_t *ir, UNUSED(uint8_t opcode), uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) +{ + int dest_reg = (fetchdat >> 3) & 7; + + codegen_mark_code_present(block, cs + op_pc, 1); + if ((fetchdat & 0xc0) == 0xc0) { + int src_reg = fetchdat & 7; + uop_MOVZX(ir, IREG_16(dest_reg), IREG_8(src_reg)); + } else { + x86seg *target_seg; + + uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc); + target_seg = codegen_generate_ea(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32, 0); + codegen_check_seg_read(block, ir, target_seg); + uop_MEM_LOAD_REG(ir, IREG_temp0_B, ireg_seg_base(target_seg), IREG_eaaddr); + uop_MOVZX(ir, IREG_16(dest_reg), IREG_temp0_B); + } + + return op_pc + 1; +} +uint32_t +ropMOVZX_32_8(codeblock_t *block, ir_data_t *ir, UNUSED(uint8_t opcode), uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) +{ + int dest_reg = (fetchdat >> 3) & 7; + + codegen_mark_code_present(block, cs + op_pc, 1); + if ((fetchdat & 0xc0) == 0xc0) { + int src_reg = fetchdat & 7; + uop_MOVZX(ir, IREG_32(dest_reg), IREG_8(src_reg)); + } else { + x86seg *target_seg; + + uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc); + target_seg = codegen_generate_ea(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32, 0); + codegen_check_seg_read(block, ir, target_seg); + uop_MEM_LOAD_REG(ir, IREG_temp0_B, ireg_seg_base(target_seg), IREG_eaaddr); + uop_MOVZX(ir, IREG_32(dest_reg), IREG_temp0_B); + } + + return op_pc + 1; +} +uint32_t +ropMOVZX_32_16(codeblock_t *block, ir_data_t *ir, UNUSED(uint8_t opcode), uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) +{ + int dest_reg = (fetchdat >> 3) & 7; + + codegen_mark_code_present(block, cs + op_pc, 1); + if ((fetchdat & 0xc0) == 0xc0) { + int src_reg = fetchdat & 7; + uop_MOVZX(ir, IREG_32(dest_reg), IREG_16(src_reg)); + } else { + x86seg *target_seg; + + uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc); + target_seg = codegen_generate_ea(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32, 0); + codegen_check_seg_read(block, ir, target_seg); + uop_MEM_LOAD_REG(ir, IREG_temp0_W, ireg_seg_base(target_seg), IREG_eaaddr); + uop_MOVZX(ir, IREG_32(dest_reg), IREG_temp0_W); + } + + return op_pc + 1; +} + +uint32_t +ropXCHG_AX(UNUSED(codeblock_t *block), ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, UNUSED(uint32_t op_32), uint32_t op_pc) +{ + int reg2 = IREG_16(opcode & 7); + + uop_MOV(ir, IREG_temp0_W, IREG_AX); + uop_MOV(ir, IREG_AX, reg2); + uop_MOV(ir, reg2, IREG_temp0_W); + + return op_pc; +} +uint32_t +ropXCHG_EAX(UNUSED(codeblock_t *block), ir_data_t *ir, UNUSED(uint8_t opcode), uint32_t fetchdat, UNUSED(uint32_t op_32), uint32_t op_pc) +{ + int reg2 = IREG_32(opcode & 7); + + uop_MOV(ir, IREG_temp0, IREG_EAX); + uop_MOV(ir, IREG_EAX, reg2); + uop_MOV(ir, reg2, IREG_temp0); + + return op_pc; +} + +uint32_t +ropXCHG_8(codeblock_t *block, ir_data_t *ir, UNUSED(uint8_t opcode), uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) +{ + int reg1 = IREG_8((fetchdat >> 3) & 7); + + codegen_mark_code_present(block, cs + op_pc, 1); + if ((fetchdat & 0xc0) == 0xc0) { + int reg2 = IREG_8(fetchdat & 7); + + uop_MOV(ir, IREG_temp0_B, reg1); + uop_MOV(ir, reg1, reg2); + uop_MOV(ir, reg2, IREG_temp0_B); + } else { + x86seg *target_seg; + + uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc); + target_seg = codegen_generate_ea(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32, 0); + codegen_check_seg_write(block, ir, target_seg); + + uop_MEM_LOAD_REG(ir, IREG_temp0_B, ireg_seg_base(target_seg), IREG_eaaddr); + uop_MEM_STORE_REG(ir, ireg_seg_base(target_seg), IREG_eaaddr, reg1); + uop_MOV(ir, reg1, IREG_temp0_B); + } + + return op_pc + 1; +} +uint32_t +ropXCHG_16(codeblock_t *block, ir_data_t *ir, UNUSED(uint8_t opcode), uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) +{ + int reg1 = IREG_16((fetchdat >> 3) & 7); + + codegen_mark_code_present(block, cs + op_pc, 1); + if ((fetchdat & 0xc0) == 0xc0) { + int reg2 = IREG_16(fetchdat & 7); + + uop_MOV(ir, IREG_temp0_W, reg1); + uop_MOV(ir, reg1, reg2); uop_MOV(ir, reg2, IREG_temp0_W); - - return op_pc; -} -uint32_t ropXCHG_EAX(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) -{ - int reg2 = IREG_32(opcode & 7); + } else { + x86seg *target_seg; - uop_MOV(ir, IREG_temp0, IREG_EAX); - uop_MOV(ir, IREG_EAX, reg2); - uop_MOV(ir, reg2, IREG_temp0); - - return op_pc; -} - -uint32_t ropXCHG_8(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) -{ - int reg1 = IREG_8((fetchdat >> 3) & 7); - - codegen_mark_code_present(block, cs+op_pc, 1); - if ((fetchdat & 0xc0) == 0xc0) - { - int reg2 = IREG_8(fetchdat & 7); - - uop_MOV(ir, IREG_temp0_B, reg1); - uop_MOV(ir, reg1, reg2); - uop_MOV(ir, reg2, IREG_temp0_B); - } - else - { - x86seg *target_seg; - - uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc); - target_seg = codegen_generate_ea(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32, 0); - codegen_check_seg_write(block, ir, target_seg); - - uop_MEM_LOAD_REG(ir, IREG_temp0_B, ireg_seg_base(target_seg), IREG_eaaddr); - uop_MEM_STORE_REG(ir, ireg_seg_base(target_seg), IREG_eaaddr, reg1); - uop_MOV(ir, reg1, IREG_temp0_B); - } - - return op_pc + 1; -} -uint32_t ropXCHG_16(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) -{ - int reg1 = IREG_16((fetchdat >> 3) & 7); - - codegen_mark_code_present(block, cs+op_pc, 1); - if ((fetchdat & 0xc0) == 0xc0) - { - int reg2 = IREG_16(fetchdat & 7); - - uop_MOV(ir, IREG_temp0_W, reg1); - uop_MOV(ir, reg1, reg2); - uop_MOV(ir, reg2, IREG_temp0_W); - } - else - { - x86seg *target_seg; - - uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc); - target_seg = codegen_generate_ea(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32, 0); - codegen_check_seg_write(block, ir, target_seg); - - uop_MEM_LOAD_REG(ir, IREG_temp0_W, ireg_seg_base(target_seg), IREG_eaaddr); - uop_MEM_STORE_REG(ir, ireg_seg_base(target_seg), IREG_eaaddr, reg1); - uop_MOV(ir, reg1, IREG_temp0_W); - } - - return op_pc + 1; -} -uint32_t ropXCHG_32(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) -{ - int reg1 = IREG_32((fetchdat >> 3) & 7); - - codegen_mark_code_present(block, cs+op_pc, 1); - if ((fetchdat & 0xc0) == 0xc0) - { - int reg2 = IREG_32(fetchdat & 7); - - uop_MOV(ir, IREG_temp0, reg1); - uop_MOV(ir, reg1, reg2); - uop_MOV(ir, reg2, IREG_temp0); - } - else - { - x86seg *target_seg; - - uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc); - target_seg = codegen_generate_ea(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32, 0); - codegen_check_seg_write(block, ir, target_seg); - - uop_MEM_LOAD_REG(ir, IREG_temp0, ireg_seg_base(target_seg), IREG_eaaddr); - uop_MEM_STORE_REG(ir, ireg_seg_base(target_seg), IREG_eaaddr, reg1); - uop_MOV(ir, reg1, IREG_temp0); - } - - return op_pc + 1; -} - -uint32_t ropXLAT(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) -{ uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc); - - uop_MOVZX(ir, IREG_eaaddr, IREG_AL); - uop_ADD(ir, IREG_eaaddr, IREG_eaaddr, IREG_EBX); - if (!(op_32 & 0x200)) - uop_AND_IMM(ir, IREG_eaaddr, IREG_eaaddr, 0xffff); + target_seg = codegen_generate_ea(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32, 0); + codegen_check_seg_write(block, ir, target_seg); - uop_MEM_LOAD_REG(ir, IREG_AL, ireg_seg_base(op_ea_seg), IREG_eaaddr); + uop_MEM_LOAD_REG(ir, IREG_temp0_W, ireg_seg_base(target_seg), IREG_eaaddr); + uop_MEM_STORE_REG(ir, ireg_seg_base(target_seg), IREG_eaaddr, reg1); + uop_MOV(ir, reg1, IREG_temp0_W); + } - return op_pc; + return op_pc + 1; +} +uint32_t +ropXCHG_32(codeblock_t *block, ir_data_t *ir, UNUSED(uint8_t opcode), uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) +{ + int reg1 = IREG_32((fetchdat >> 3) & 7); + + codegen_mark_code_present(block, cs + op_pc, 1); + if ((fetchdat & 0xc0) == 0xc0) { + int reg2 = IREG_32(fetchdat & 7); + + uop_MOV(ir, IREG_temp0, reg1); + uop_MOV(ir, reg1, reg2); + uop_MOV(ir, reg2, IREG_temp0); + } else { + x86seg *target_seg; + + uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc); + target_seg = codegen_generate_ea(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32, 0); + codegen_check_seg_write(block, ir, target_seg); + + uop_MEM_LOAD_REG(ir, IREG_temp0, ireg_seg_base(target_seg), IREG_eaaddr); + uop_MEM_STORE_REG(ir, ireg_seg_base(target_seg), IREG_eaaddr, reg1); + uop_MOV(ir, reg1, IREG_temp0); + } + + return op_pc + 1; +} + +uint32_t +ropXLAT(UNUSED(codeblock_t *block), ir_data_t *ir, UNUSED(uint8_t opcode), uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) +{ + uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc); + + uop_MOVZX(ir, IREG_eaaddr, IREG_AL); + uop_ADD(ir, IREG_eaaddr, IREG_eaaddr, IREG_EBX); + if (!(op_32 & 0x200)) + uop_AND_IMM(ir, IREG_eaaddr, IREG_eaaddr, 0xffff); + + uop_MEM_LOAD_REG(ir, IREG_AL, ireg_seg_base(op_ea_seg), IREG_eaaddr); + + return op_pc; } diff --git a/src/codegen_new/codegen_ops_shift.c b/src/codegen_new/codegen_ops_shift.c index de9a0fecf..0daebff67 100644 --- a/src/codegen_new/codegen_ops_shift.c +++ b/src/codegen_new/codegen_ops_shift.c @@ -2,8 +2,11 @@ #include <86box/86box.h> #include "cpu.h" #include <86box/mem.h> +#include <86box/plat_unused.h> #include "x86.h" +#include "x86seg_common.h" +#include "x86seg.h" #include "x86_flags.h" #include "386_common.h" #include "codegen.h" @@ -13,1126 +16,1097 @@ #include "codegen_ops_helpers.h" #include "codegen_ops_shift.h" -static uint32_t shift_common_8(ir_data_t *ir, uint32_t fetchdat, uint32_t op_pc, x86seg *target_seg, int count) +static uint32_t +shift_common_8(ir_data_t *ir, uint32_t fetchdat, uint32_t op_pc, x86seg *target_seg, int count) { - if ((fetchdat & 0xc0) == 0xc0) - { - int dest_reg = fetchdat & 7; + if ((fetchdat & 0xc0) == 0xc0) { + int dest_reg = fetchdat & 7; - switch (fetchdat & 0x38) - { - case 0x00: /*ROL*/ - uop_CALL_FUNC(ir, flags_rebuild); - uop_ROL_IMM(ir, IREG_8(dest_reg), IREG_8(dest_reg), count); - uop_MOV_IMM(ir, IREG_flags_op, FLAGS_ROL8); - uop_MOVZX(ir, IREG_flags_res, IREG_8(dest_reg)); - break; + switch (fetchdat & 0x38) { + case 0x00: /*ROL*/ + uop_CALL_FUNC(ir, flags_rebuild); + uop_ROL_IMM(ir, IREG_8(dest_reg), IREG_8(dest_reg), count); + uop_MOV_IMM(ir, IREG_flags_op, FLAGS_ROL8); + uop_MOVZX(ir, IREG_flags_res, IREG_8(dest_reg)); + break; - case 0x08: /*ROR*/ - uop_CALL_FUNC(ir, flags_rebuild); - uop_ROR_IMM(ir, IREG_8(dest_reg), IREG_8(dest_reg), count); - uop_MOV_IMM(ir, IREG_flags_op, FLAGS_ROR8); - uop_MOVZX(ir, IREG_flags_res, IREG_8(dest_reg)); - break; + case 0x08: /*ROR*/ + uop_CALL_FUNC(ir, flags_rebuild); + uop_ROR_IMM(ir, IREG_8(dest_reg), IREG_8(dest_reg), count); + uop_MOV_IMM(ir, IREG_flags_op, FLAGS_ROR8); + uop_MOVZX(ir, IREG_flags_res, IREG_8(dest_reg)); + break; - case 0x20: case 0x30: /*SHL*/ - uop_MOVZX(ir, IREG_flags_op1, IREG_8(dest_reg)); - uop_SHL_IMM(ir, IREG_8(dest_reg), IREG_8(dest_reg), count); - uop_MOV_IMM(ir, IREG_flags_op2, count); - uop_MOV_IMM(ir, IREG_flags_op, FLAGS_SHL8); - uop_MOVZX(ir, IREG_flags_res, IREG_8(dest_reg)); - break; + case 0x20: + case 0x30: /*SHL*/ + uop_MOVZX(ir, IREG_flags_op1, IREG_8(dest_reg)); + uop_SHL_IMM(ir, IREG_8(dest_reg), IREG_8(dest_reg), count); + uop_MOV_IMM(ir, IREG_flags_op2, count); + uop_MOV_IMM(ir, IREG_flags_op, FLAGS_SHL8); + uop_MOVZX(ir, IREG_flags_res, IREG_8(dest_reg)); + break; - case 0x28: /*SHR*/ - uop_MOVZX(ir, IREG_flags_op1, IREG_8(dest_reg)); - uop_SHR_IMM(ir, IREG_8(dest_reg), IREG_8(dest_reg), count); - uop_MOV_IMM(ir, IREG_flags_op2, count); - uop_MOV_IMM(ir, IREG_flags_op, FLAGS_SHR8); - uop_MOVZX(ir, IREG_flags_res, IREG_8(dest_reg)); - break; + case 0x28: /*SHR*/ + uop_MOVZX(ir, IREG_flags_op1, IREG_8(dest_reg)); + uop_SHR_IMM(ir, IREG_8(dest_reg), IREG_8(dest_reg), count); + uop_MOV_IMM(ir, IREG_flags_op2, count); + uop_MOV_IMM(ir, IREG_flags_op, FLAGS_SHR8); + uop_MOVZX(ir, IREG_flags_res, IREG_8(dest_reg)); + break; - case 0x38: /*SAR*/ - uop_MOVZX(ir, IREG_flags_op1, IREG_8(dest_reg)); - uop_SAR_IMM(ir, IREG_8(dest_reg), IREG_8(dest_reg), count); - uop_MOV_IMM(ir, IREG_flags_op2, count); - uop_MOV_IMM(ir, IREG_flags_op, FLAGS_SAR8); - uop_MOVZX(ir, IREG_flags_res, IREG_8(dest_reg)); - break; - - default: - return 0; - } - } - else - { - switch (fetchdat & 0x38) - { - case 0x00: /*ROL*/ - uop_CALL_FUNC(ir, flags_rebuild); - uop_ROL_IMM(ir, IREG_temp0_B, IREG_temp0_B, count); - uop_MEM_STORE_REG(ir, ireg_seg_base(target_seg), IREG_eaaddr, IREG_temp0_B); - uop_MOV_IMM(ir, IREG_flags_op, FLAGS_ROL8); - uop_MOVZX(ir, IREG_flags_res, IREG_temp0_B); - break; + case 0x38: /*SAR*/ + uop_MOVZX(ir, IREG_flags_op1, IREG_8(dest_reg)); + uop_SAR_IMM(ir, IREG_8(dest_reg), IREG_8(dest_reg), count); + uop_MOV_IMM(ir, IREG_flags_op2, count); + uop_MOV_IMM(ir, IREG_flags_op, FLAGS_SAR8); + uop_MOVZX(ir, IREG_flags_res, IREG_8(dest_reg)); + break; - case 0x08: /*ROR*/ - uop_CALL_FUNC(ir, flags_rebuild); - uop_ROR_IMM(ir, IREG_temp0_B, IREG_temp0_B, count); - uop_MEM_STORE_REG(ir, ireg_seg_base(target_seg), IREG_eaaddr, IREG_temp0_B); - uop_MOV_IMM(ir, IREG_flags_op, FLAGS_ROR8); - uop_MOVZX(ir, IREG_flags_res, IREG_temp0_B); - break; - - case 0x20: case 0x30: /*SHL*/ - uop_SHL_IMM(ir, IREG_temp1_B, IREG_temp0_B, count); - uop_MEM_STORE_REG(ir, ireg_seg_base(target_seg), IREG_eaaddr, IREG_temp1_B); - uop_MOVZX(ir, IREG_flags_op1, IREG_temp0_B); - uop_MOV_IMM(ir, IREG_flags_op2, count); - uop_MOV_IMM(ir, IREG_flags_op, FLAGS_SHL8); - uop_MOVZX(ir, IREG_flags_res, IREG_temp1_B); - break; - - case 0x28: /*SHR*/ - uop_SHR_IMM(ir, IREG_temp1_B, IREG_temp0_B, count); - uop_MEM_STORE_REG(ir, ireg_seg_base(target_seg), IREG_eaaddr, IREG_temp1_B); - uop_MOVZX(ir, IREG_flags_op1, IREG_temp0_B); - uop_MOV_IMM(ir, IREG_flags_op2, count); - uop_MOV_IMM(ir, IREG_flags_op, FLAGS_SHR8); - uop_MOVZX(ir, IREG_flags_res, IREG_temp1_B); - break; - - case 0x38: /*SAR*/ - uop_SAR_IMM(ir, IREG_temp1_B, IREG_temp0_B, count); - uop_MEM_STORE_REG(ir, ireg_seg_base(target_seg), IREG_eaaddr, IREG_temp1_B); - uop_MOVZX(ir, IREG_flags_op1, IREG_temp0_B); - uop_MOV_IMM(ir, IREG_flags_op2, count); - uop_MOV_IMM(ir, IREG_flags_op, FLAGS_SAR8); - uop_MOVZX(ir, IREG_flags_res, IREG_temp1_B); - break; - - default: - return 0; - } - } - - codegen_flags_changed = 1; - return op_pc + 1; -} - -static uint32_t shift_common_16(ir_data_t *ir, uint32_t fetchdat, uint32_t op_pc, x86seg *target_seg, int count) -{ - if ((fetchdat & 0xc0) == 0xc0) - { - int dest_reg = fetchdat & 7; - - switch (fetchdat & 0x38) - { - case 0x00: /*ROL*/ - uop_CALL_FUNC(ir, flags_rebuild); - uop_ROL_IMM(ir, IREG_16(dest_reg), IREG_16(dest_reg), count); - uop_MOV_IMM(ir, IREG_flags_op, FLAGS_ROL16); - uop_MOVZX(ir, IREG_flags_res, IREG_16(dest_reg)); - break; - - case 0x08: /*ROR*/ - uop_CALL_FUNC(ir, flags_rebuild); - uop_ROR_IMM(ir, IREG_16(dest_reg), IREG_16(dest_reg), count); - uop_MOV_IMM(ir, IREG_flags_op, FLAGS_ROR16); - uop_MOVZX(ir, IREG_flags_res, IREG_16(dest_reg)); - break; - - case 0x20: case 0x30: /*SHL*/ - uop_MOVZX(ir, IREG_flags_op1, IREG_16(dest_reg)); - uop_SHL_IMM(ir, IREG_16(dest_reg), IREG_16(dest_reg), count); - uop_MOV_IMM(ir, IREG_flags_op2, count); - uop_MOV_IMM(ir, IREG_flags_op, FLAGS_SHL16); - uop_MOVZX(ir, IREG_flags_res, IREG_16(dest_reg)); - break; - - case 0x28: /*SHR*/ - uop_MOVZX(ir, IREG_flags_op1, IREG_16(dest_reg)); - uop_SHR_IMM(ir, IREG_16(dest_reg), IREG_16(dest_reg), count); - uop_MOV_IMM(ir, IREG_flags_op2, count); - uop_MOV_IMM(ir, IREG_flags_op, FLAGS_SHR16); - uop_MOVZX(ir, IREG_flags_res, IREG_16(dest_reg)); - break; - - case 0x38: /*SAR*/ - uop_MOVZX(ir, IREG_flags_op1, IREG_16(dest_reg)); - uop_SAR_IMM(ir, IREG_16(dest_reg), IREG_16(dest_reg), count); - uop_MOV_IMM(ir, IREG_flags_op2, count); - uop_MOV_IMM(ir, IREG_flags_op, FLAGS_SAR16); - uop_MOVZX(ir, IREG_flags_res, IREG_16(dest_reg)); - break; - - default: - return 0; - } - } - else - { - switch (fetchdat & 0x38) - { - case 0x00: /*ROL*/ - uop_CALL_FUNC(ir, flags_rebuild); - uop_ROL_IMM(ir, IREG_temp0_W, IREG_temp0_W, count); - uop_MEM_STORE_REG(ir, ireg_seg_base(target_seg), IREG_eaaddr, IREG_temp0_W); - uop_MOV_IMM(ir, IREG_flags_op, FLAGS_ROL16); - uop_MOVZX(ir, IREG_flags_res, IREG_temp0_W); - break; - - case 0x08: /*ROR*/ - uop_CALL_FUNC(ir, flags_rebuild); - uop_ROR_IMM(ir, IREG_temp0_W, IREG_temp0_W, count); - uop_MEM_STORE_REG(ir, ireg_seg_base(target_seg), IREG_eaaddr, IREG_temp0_W); - uop_MOV_IMM(ir, IREG_flags_op, FLAGS_ROR16); - uop_MOVZX(ir, IREG_flags_res, IREG_temp0_W); - break; - - case 0x20: case 0x30: /*SHL*/ - uop_SHL_IMM(ir, IREG_temp1_W, IREG_temp0_W, count); - uop_MEM_STORE_REG(ir, ireg_seg_base(target_seg), IREG_eaaddr, IREG_temp1_W); - uop_MOVZX(ir, IREG_flags_op1, IREG_temp0_W); - uop_MOV_IMM(ir, IREG_flags_op2, count); - uop_MOV_IMM(ir, IREG_flags_op, FLAGS_SHL16); - uop_MOVZX(ir, IREG_flags_res, IREG_temp1_W); - break; - - case 0x28: /*SHR*/ - uop_SHR_IMM(ir, IREG_temp1_W, IREG_temp0_W, count); - uop_MEM_STORE_REG(ir, ireg_seg_base(target_seg), IREG_eaaddr, IREG_temp1_W); - uop_MOVZX(ir, IREG_flags_op1, IREG_temp0_W); - uop_MOV_IMM(ir, IREG_flags_op2, count); - uop_MOV_IMM(ir, IREG_flags_op, FLAGS_SHR16); - uop_MOVZX(ir, IREG_flags_res, IREG_temp1_W); - break; - - case 0x38: /*SAR*/ - uop_SAR_IMM(ir, IREG_temp1_W, IREG_temp0_W, count); - uop_MEM_STORE_REG(ir, ireg_seg_base(target_seg), IREG_eaaddr, IREG_temp1_W); - uop_MOVZX(ir, IREG_flags_op1, IREG_temp0_W); - uop_MOV_IMM(ir, IREG_flags_op2, count); - uop_MOV_IMM(ir, IREG_flags_op, FLAGS_SAR16); - uop_MOVZX(ir, IREG_flags_res, IREG_temp1_W); - break; - - default: - return 0; - } - } - - codegen_flags_changed = 1; - return op_pc + 1; -} -static uint32_t shift_common_32(ir_data_t *ir, uint32_t fetchdat, uint32_t op_pc, x86seg *target_seg, int count) -{ - if ((fetchdat & 0xc0) == 0xc0) - { - int dest_reg = fetchdat & 7; - - switch (fetchdat & 0x38) - { - case 0x00: /*ROL*/ - uop_CALL_FUNC(ir, flags_rebuild); - uop_ROL_IMM(ir, IREG_32(dest_reg), IREG_32(dest_reg), count); - uop_MOV_IMM(ir, IREG_flags_op, FLAGS_ROL32); - uop_MOV(ir, IREG_flags_res, IREG_32(dest_reg)); - break; - - case 0x08: /*ROR*/ - uop_CALL_FUNC(ir, flags_rebuild); - uop_ROR_IMM(ir, IREG_32(dest_reg), IREG_32(dest_reg), count); - uop_MOV_IMM(ir, IREG_flags_op, FLAGS_ROR32); - uop_MOV(ir, IREG_flags_res, IREG_32(dest_reg)); - break; - - case 0x20: case 0x30: /*SHL*/ - uop_MOV(ir, IREG_flags_op1, IREG_32(dest_reg)); - uop_SHL_IMM(ir, IREG_32(dest_reg), IREG_32(dest_reg), count); - uop_MOV_IMM(ir, IREG_flags_op2, count); - uop_MOV_IMM(ir, IREG_flags_op, FLAGS_SHL32); - uop_MOV(ir, IREG_flags_res, IREG_32(dest_reg)); - break; - - case 0x28: /*SHR*/ - uop_MOV(ir, IREG_flags_op1, IREG_32(dest_reg)); - uop_SHR_IMM(ir, IREG_32(dest_reg), IREG_32(dest_reg), count); - uop_MOV_IMM(ir, IREG_flags_op2, count); - uop_MOV_IMM(ir, IREG_flags_op, FLAGS_SHR32); - uop_MOV(ir, IREG_flags_res, IREG_32(dest_reg)); - break; - - case 0x38: /*SAR*/ - uop_MOV(ir, IREG_flags_op1, IREG_32(dest_reg)); - uop_SAR_IMM(ir, IREG_32(dest_reg), IREG_32(dest_reg), count); - uop_MOV_IMM(ir, IREG_flags_op2, count); - uop_MOV_IMM(ir, IREG_flags_op, FLAGS_SAR32); - uop_MOV(ir, IREG_flags_res, IREG_32(dest_reg)); - break; - - default: - return 0; - } - } - else - { - switch (fetchdat & 0x38) - { - case 0x00: /*ROL*/ - uop_CALL_FUNC(ir, flags_rebuild); - uop_ROL_IMM(ir, IREG_temp0, IREG_temp0, count); - uop_MEM_STORE_REG(ir, ireg_seg_base(target_seg), IREG_eaaddr, IREG_temp0); - uop_MOV_IMM(ir, IREG_flags_op, FLAGS_ROL32); - uop_MOV(ir, IREG_flags_res, IREG_temp0); - break; - - case 0x08: /*ROR*/ - uop_CALL_FUNC(ir, flags_rebuild); - uop_ROR_IMM(ir, IREG_temp0, IREG_temp0, count); - uop_MEM_STORE_REG(ir, ireg_seg_base(target_seg), IREG_eaaddr, IREG_temp0); - uop_MOV_IMM(ir, IREG_flags_op, FLAGS_ROR32); - uop_MOV(ir, IREG_flags_res, IREG_temp0); - break; - - case 0x20: case 0x30: /*SHL*/ - uop_SHL_IMM(ir, IREG_temp1, IREG_temp0, count); - uop_MEM_STORE_REG(ir, ireg_seg_base(target_seg), IREG_eaaddr, IREG_temp1); - uop_MOV(ir, IREG_flags_op1, IREG_temp0); - uop_MOV_IMM(ir, IREG_flags_op2, count); - uop_MOV_IMM(ir, IREG_flags_op, FLAGS_SHL32); - uop_MOV(ir, IREG_flags_res, IREG_temp1); - break; - - case 0x28: /*SHR*/ - uop_SHR_IMM(ir, IREG_temp1, IREG_temp0, count); - uop_MEM_STORE_REG(ir, ireg_seg_base(target_seg), IREG_eaaddr, IREG_temp1); - uop_MOV(ir, IREG_flags_op1, IREG_temp0); - uop_MOV_IMM(ir, IREG_flags_op2, count); - uop_MOV_IMM(ir, IREG_flags_op, FLAGS_SHR32); - uop_MOV(ir, IREG_flags_res, IREG_temp1); - break; - - case 0x38: /*SAR*/ - uop_SAR_IMM(ir, IREG_temp1, IREG_temp0, count); - uop_MEM_STORE_REG(ir, ireg_seg_base(target_seg), IREG_eaaddr, IREG_temp1); - uop_MOV(ir, IREG_flags_op1, IREG_temp0); - uop_MOV_IMM(ir, IREG_flags_op2, count); - uop_MOV_IMM(ir, IREG_flags_op, FLAGS_SAR32); - uop_MOV(ir, IREG_flags_res, IREG_temp1); - break; - - default: - return 0; - } - } - - codegen_flags_changed = 1; - return op_pc + 1; -} - -static uint32_t shift_common_variable_32(ir_data_t *ir, uint32_t fetchdat, uint32_t op_pc, x86seg *target_seg, int count_reg) -{ - if ((fetchdat & 0xc0) == 0xc0) - { - int dest_reg = fetchdat & 7; - - switch (fetchdat & 0x38) - { - case 0x00: /*ROL*/ - uop_CALL_FUNC(ir, flags_rebuild); - uop_ROL(ir, IREG_32(dest_reg), IREG_32(dest_reg), count_reg); - uop_MOV_IMM(ir, IREG_flags_op, FLAGS_ROL32); - uop_MOV(ir, IREG_flags_res, IREG_32(dest_reg)); - break; - - case 0x08: /*ROR*/ - uop_CALL_FUNC(ir, flags_rebuild); - uop_ROR(ir, IREG_32(dest_reg), IREG_32(dest_reg), count_reg); - uop_MOV_IMM(ir, IREG_flags_op, FLAGS_ROR32); - uop_MOV(ir, IREG_flags_res, IREG_32(dest_reg)); - break; - - case 0x20: case 0x30: /*SHL*/ - uop_MOV(ir, IREG_flags_op1, IREG_32(dest_reg)); - uop_SHL(ir, IREG_32(dest_reg), IREG_32(dest_reg), count_reg); - uop_MOV(ir, IREG_flags_op2, count_reg); - uop_MOV_IMM(ir, IREG_flags_op, FLAGS_SHL32); - uop_MOV(ir, IREG_flags_res, IREG_32(dest_reg)); - break; - - case 0x28: /*SHR*/ - uop_MOV(ir, IREG_flags_op1, IREG_32(dest_reg)); - uop_SHR(ir, IREG_32(dest_reg), IREG_32(dest_reg), count_reg); - uop_MOV(ir, IREG_flags_op2, count_reg); - uop_MOV_IMM(ir, IREG_flags_op, FLAGS_SHR32); - uop_MOV(ir, IREG_flags_res, IREG_32(dest_reg)); - break; - - case 0x38: /*SAR*/ - uop_MOV(ir, IREG_flags_op1, IREG_32(dest_reg)); - uop_SAR(ir, IREG_32(dest_reg), IREG_32(dest_reg), count_reg); - uop_MOV(ir, IREG_flags_op2, count_reg); - uop_MOV_IMM(ir, IREG_flags_op, FLAGS_SAR32); - uop_MOV(ir, IREG_flags_res, IREG_32(dest_reg)); - break; - - default: - return 0; - } - } - else - { - switch (fetchdat & 0x38) - { - case 0x00: /*ROL*/ - uop_CALL_FUNC(ir, flags_rebuild); - uop_ROL(ir, IREG_temp0, IREG_temp0, count_reg); - uop_MEM_STORE_REG(ir, ireg_seg_base(target_seg), IREG_eaaddr, IREG_temp0); - uop_MOV_IMM(ir, IREG_flags_op, FLAGS_ROL32); - uop_MOV(ir, IREG_flags_res, IREG_temp0); - break; - - case 0x08: /*ROR*/ - uop_CALL_FUNC(ir, flags_rebuild); - uop_ROR(ir, IREG_temp0, IREG_temp0, count_reg); - uop_MEM_STORE_REG(ir, ireg_seg_base(target_seg), IREG_eaaddr, IREG_temp0); - uop_MOV_IMM(ir, IREG_flags_op, FLAGS_ROR32); - uop_MOV(ir, IREG_flags_res, IREG_temp0); - break; - - case 0x20: case 0x30: /*SHL*/ - uop_SHL(ir, IREG_temp1, IREG_temp0, count_reg); - uop_MEM_STORE_REG(ir, ireg_seg_base(target_seg), IREG_eaaddr, IREG_temp1); - uop_MOV(ir, IREG_flags_op1, IREG_temp0); - uop_MOV(ir, IREG_flags_op2, count_reg); - uop_MOV_IMM(ir, IREG_flags_op, FLAGS_SHL32); - uop_MOV(ir, IREG_flags_res, IREG_temp1); - break; - - case 0x28: /*SHR*/ - uop_SHR(ir, IREG_temp1, IREG_temp0, count_reg); - uop_MEM_STORE_REG(ir, ireg_seg_base(target_seg), IREG_eaaddr, IREG_temp1); - uop_MOV(ir, IREG_flags_op1, IREG_temp0); - uop_MOV(ir, IREG_flags_op2, count_reg); - uop_MOV_IMM(ir, IREG_flags_op, FLAGS_SHR32); - uop_MOV(ir, IREG_flags_res, IREG_temp1); - break; - - case 0x38: /*SAR*/ - uop_SAR(ir, IREG_temp1, IREG_temp0, count_reg); - uop_MEM_STORE_REG(ir, ireg_seg_base(target_seg), IREG_eaaddr, IREG_temp1); - uop_MOV(ir, IREG_flags_op1, IREG_temp0); - uop_MOV(ir, IREG_flags_op2, count_reg); - uop_MOV_IMM(ir, IREG_flags_op, FLAGS_SAR32); - uop_MOV(ir, IREG_flags_res, IREG_temp1); - break; - - default: - return 0; - } - } - - codegen_flags_changed = 1; - return op_pc + 1; -} - -uint32_t ropC0(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) -{ - x86seg *target_seg = NULL; - uint8_t imm; - - if ((fetchdat & 0x30) == 0x10) /*RCL/RCR*/ + default: return 0; - - codegen_mark_code_present(block, cs+op_pc, 1); - if ((fetchdat & 0xc0) != 0xc0) - { - uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc); - target_seg = codegen_generate_ea(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32, 0); - codegen_check_seg_write(block, ir, target_seg); - uop_MEM_LOAD_REG(ir, IREG_temp0_B, ireg_seg_base(target_seg), IREG_eaaddr); } - imm = fastreadb(cs + op_pc + 1) & 0x1f; - codegen_mark_code_present(block, cs+op_pc+1, 1); - - if (imm) - return shift_common_8(ir, fetchdat, op_pc, target_seg, imm) + 1; - return op_pc+1; -} -uint32_t ropC1_w(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) -{ - x86seg *target_seg = NULL; - uint8_t imm; + } else { + switch (fetchdat & 0x38) { + case 0x00: /*ROL*/ + uop_CALL_FUNC(ir, flags_rebuild); + uop_ROL_IMM(ir, IREG_temp0_B, IREG_temp0_B, count); + uop_MEM_STORE_REG(ir, ireg_seg_base(target_seg), IREG_eaaddr, IREG_temp0_B); + uop_MOV_IMM(ir, IREG_flags_op, FLAGS_ROL8); + uop_MOVZX(ir, IREG_flags_res, IREG_temp0_B); + break; - if ((fetchdat & 0x30) == 0x10) /*RCL/RCR*/ + case 0x08: /*ROR*/ + uop_CALL_FUNC(ir, flags_rebuild); + uop_ROR_IMM(ir, IREG_temp0_B, IREG_temp0_B, count); + uop_MEM_STORE_REG(ir, ireg_seg_base(target_seg), IREG_eaaddr, IREG_temp0_B); + uop_MOV_IMM(ir, IREG_flags_op, FLAGS_ROR8); + uop_MOVZX(ir, IREG_flags_res, IREG_temp0_B); + break; + + case 0x20: + case 0x30: /*SHL*/ + uop_SHL_IMM(ir, IREG_temp1_B, IREG_temp0_B, count); + uop_MEM_STORE_REG(ir, ireg_seg_base(target_seg), IREG_eaaddr, IREG_temp1_B); + uop_MOVZX(ir, IREG_flags_op1, IREG_temp0_B); + uop_MOV_IMM(ir, IREG_flags_op2, count); + uop_MOV_IMM(ir, IREG_flags_op, FLAGS_SHL8); + uop_MOVZX(ir, IREG_flags_res, IREG_temp1_B); + break; + + case 0x28: /*SHR*/ + uop_SHR_IMM(ir, IREG_temp1_B, IREG_temp0_B, count); + uop_MEM_STORE_REG(ir, ireg_seg_base(target_seg), IREG_eaaddr, IREG_temp1_B); + uop_MOVZX(ir, IREG_flags_op1, IREG_temp0_B); + uop_MOV_IMM(ir, IREG_flags_op2, count); + uop_MOV_IMM(ir, IREG_flags_op, FLAGS_SHR8); + uop_MOVZX(ir, IREG_flags_res, IREG_temp1_B); + break; + + case 0x38: /*SAR*/ + uop_SAR_IMM(ir, IREG_temp1_B, IREG_temp0_B, count); + uop_MEM_STORE_REG(ir, ireg_seg_base(target_seg), IREG_eaaddr, IREG_temp1_B); + uop_MOVZX(ir, IREG_flags_op1, IREG_temp0_B); + uop_MOV_IMM(ir, IREG_flags_op2, count); + uop_MOV_IMM(ir, IREG_flags_op, FLAGS_SAR8); + uop_MOVZX(ir, IREG_flags_res, IREG_temp1_B); + break; + + default: return 0; - - codegen_mark_code_present(block, cs+op_pc, 1); - if ((fetchdat & 0xc0) != 0xc0) - { - uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc); - target_seg = codegen_generate_ea(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32, 0); - codegen_check_seg_write(block, ir, target_seg); - uop_MEM_LOAD_REG(ir, IREG_temp0_W, ireg_seg_base(target_seg), IREG_eaaddr); } - imm = fastreadb(cs + op_pc + 1) & 0x1f; - codegen_mark_code_present(block, cs+op_pc+1, 1); - - if (imm) - return shift_common_16(ir, fetchdat, op_pc, target_seg, imm) + 1; - return op_pc+1; -} -uint32_t ropC1_l(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) -{ - x86seg *target_seg = NULL; + } - if ((fetchdat & 0x30) == 0x10) /*RCL/RCR*/ - return 0; - - codegen_mark_code_present(block, cs+op_pc, 1); - if ((fetchdat & 0xc0) != 0xc0) - { - uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc); - target_seg = codegen_generate_ea(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32, 0); - codegen_check_seg_write(block, ir, target_seg); - uop_MEM_LOAD_REG(ir, IREG_temp0, ireg_seg_base(target_seg), IREG_eaaddr); - } - if (block->flags & CODEBLOCK_NO_IMMEDIATES) - { - uint32_t new_pc; - int jump_uop; - - LOAD_IMMEDIATE_FROM_RAM_8(block, ir, IREG_temp2, cs + op_pc + 1); - uop_AND_IMM(ir, IREG_temp2, IREG_temp2, 0x1f); - jump_uop = uop_CMP_IMM_JZ_DEST(ir, IREG_temp2, 0); - - new_pc = shift_common_variable_32(ir, fetchdat, op_pc, target_seg, IREG_temp2) + 1; - uop_NOP_BARRIER(ir); - uop_set_jump_dest(ir, jump_uop); - return new_pc; - } - else - { - uint8_t imm = fastreadb(cs + op_pc + 1) & 0x1f; - codegen_mark_code_present(block, cs+op_pc+1, 1); - - if (imm) - return shift_common_32(ir, fetchdat, op_pc, target_seg, imm) + 1; - } - return op_pc+1; + codegen_flags_changed = 1; + return op_pc + 1; } -uint32_t ropD0(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) +static uint32_t +shift_common_16(ir_data_t *ir, uint32_t fetchdat, uint32_t op_pc, x86seg *target_seg, int count) { - x86seg *target_seg = NULL; + if ((fetchdat & 0xc0) == 0xc0) { + int dest_reg = fetchdat & 7; - if ((fetchdat & 0x30) == 0x10) /*RCL/RCR*/ - return 0; + switch (fetchdat & 0x38) { + case 0x00: /*ROL*/ + uop_CALL_FUNC(ir, flags_rebuild); + uop_ROL_IMM(ir, IREG_16(dest_reg), IREG_16(dest_reg), count); + uop_MOV_IMM(ir, IREG_flags_op, FLAGS_ROL16); + uop_MOVZX(ir, IREG_flags_res, IREG_16(dest_reg)); + break; - codegen_mark_code_present(block, cs+op_pc, 1); - if ((fetchdat & 0xc0) != 0xc0) - { - uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc); - target_seg = codegen_generate_ea(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32, 0); - codegen_check_seg_write(block, ir, target_seg); - uop_MEM_LOAD_REG(ir, IREG_temp0_B, ireg_seg_base(target_seg), IREG_eaaddr); - } - - return shift_common_8(ir, fetchdat, op_pc, target_seg, 1); -} -uint32_t ropD1_w(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) -{ - x86seg *target_seg = NULL; - - if ((fetchdat & 0x30) == 0x10) /*RCL/RCR*/ - return 0; - - codegen_mark_code_present(block, cs+op_pc, 1); - if ((fetchdat & 0xc0) != 0xc0) - { - uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc); - target_seg = codegen_generate_ea(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32, 0); - codegen_check_seg_write(block, ir, target_seg); - uop_MEM_LOAD_REG(ir, IREG_temp0_W, ireg_seg_base(target_seg), IREG_eaaddr); - } - - return shift_common_16(ir, fetchdat, op_pc, target_seg, 1); -} -uint32_t ropD1_l(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) -{ - x86seg *target_seg = NULL; - - if ((fetchdat & 0x30) == 0x10) /*RCL/RCR*/ - return 0; - - codegen_mark_code_present(block, cs+op_pc, 1); - if ((fetchdat & 0xc0) != 0xc0) - { - uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc); - target_seg = codegen_generate_ea(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32, 0); - codegen_check_seg_write(block, ir, target_seg); - uop_MEM_LOAD_REG(ir, IREG_temp0, ireg_seg_base(target_seg), IREG_eaaddr); - } - - return shift_common_32(ir, fetchdat, op_pc, target_seg, 1); -} - -uint32_t ropD2(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) -{ - if ((fetchdat & 0x30) == 0x10) /*RCL/RCR*/ - return 0; - - if (!(CL & 0x1f) || !block->ins) - return 0; - - uop_AND_IMM(ir, IREG_temp2, REG_ECX, 0x1f); - uop_CMP_IMM_JZ(ir, IREG_temp2, 0, codegen_exit_rout); - - codegen_mark_code_present(block, cs+op_pc, 1); - if ((fetchdat & 0xc0) == 0xc0) - { - int dest_reg = fetchdat & 7; - - switch (fetchdat & 0x38) - { - case 0x00: /*ROL*/ - uop_CALL_FUNC(ir, flags_rebuild); - uop_ROL(ir, IREG_8(dest_reg), IREG_8(dest_reg), IREG_temp2); - uop_MOV_IMM(ir, IREG_flags_op, FLAGS_ROL8); - uop_MOVZX(ir, IREG_flags_res, IREG_8(dest_reg)); - break; - - case 0x08: /*ROR*/ - uop_CALL_FUNC(ir, flags_rebuild); - uop_ROR(ir, IREG_8(dest_reg), IREG_8(dest_reg), IREG_temp2); - uop_MOV_IMM(ir, IREG_flags_op, FLAGS_ROR8); - uop_MOVZX(ir, IREG_flags_res, IREG_8(dest_reg)); - break; - - case 0x20: case 0x30: /*SHL*/ - uop_MOVZX(ir, IREG_flags_op1, IREG_8(dest_reg)); - uop_SHL(ir, IREG_8(dest_reg), IREG_8(dest_reg), IREG_temp2); - uop_MOV(ir, IREG_flags_op2, IREG_temp2); - uop_MOV_IMM(ir, IREG_flags_op, FLAGS_SHL8); - uop_MOVZX(ir, IREG_flags_res, IREG_8(dest_reg)); - break; - - case 0x28: /*SHR*/ - uop_MOVZX(ir, IREG_flags_op1, IREG_8(dest_reg)); - uop_SHR(ir, IREG_8(dest_reg), IREG_8(dest_reg), IREG_temp2); - uop_MOV(ir, IREG_flags_op2, IREG_temp2); - uop_MOV_IMM(ir, IREG_flags_op, FLAGS_SHR8); - uop_MOVZX(ir, IREG_flags_res, IREG_8(dest_reg)); - break; - - case 0x38: /*SAR*/ - uop_MOVZX(ir, IREG_flags_op1, IREG_8(dest_reg)); - uop_SAR(ir, IREG_8(dest_reg), IREG_8(dest_reg), IREG_temp2); - uop_MOV(ir, IREG_flags_op2, IREG_temp2); - uop_MOV_IMM(ir, IREG_flags_op, FLAGS_SAR8); - uop_MOVZX(ir, IREG_flags_res, IREG_8(dest_reg)); - break; - - default: - return 0; - } - } - else - { - x86seg *target_seg; - - uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc); - target_seg = codegen_generate_ea(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32, 0); - codegen_check_seg_write(block, ir, target_seg); - uop_MEM_LOAD_REG(ir, IREG_temp0_B, ireg_seg_base(target_seg), IREG_eaaddr); - - switch (fetchdat & 0x38) - { - case 0x00: /*ROL*/ - uop_CALL_FUNC(ir, flags_rebuild); - uop_ROL(ir, IREG_temp0_B, IREG_temp0_B, IREG_temp2); - uop_MEM_STORE_REG(ir, ireg_seg_base(target_seg), IREG_eaaddr, IREG_temp0_B); - uop_MOV_IMM(ir, IREG_flags_op, FLAGS_ROL8); - uop_MOVZX(ir, IREG_flags_res, IREG_temp0_B); - break; - - case 0x08: /*ROR*/ - uop_CALL_FUNC(ir, flags_rebuild); - uop_ROR(ir, IREG_temp0_B, IREG_temp0_B, IREG_temp2); - uop_MEM_STORE_REG(ir, ireg_seg_base(target_seg), IREG_eaaddr, IREG_temp0_B); - uop_MOV_IMM(ir, IREG_flags_op, FLAGS_ROR8); - uop_MOVZX(ir, IREG_flags_res, IREG_temp0_B); - break; - - case 0x20: case 0x30: /*SHL*/ - uop_SHL(ir, IREG_temp1_B, IREG_temp0_B, IREG_temp2); - uop_MEM_STORE_REG(ir, ireg_seg_base(target_seg), IREG_eaaddr, IREG_temp1_B); - uop_MOVZX(ir, IREG_flags_op1, IREG_temp0_B); - uop_MOV(ir, IREG_flags_op2, IREG_temp2); - uop_MOV_IMM(ir, IREG_flags_op, FLAGS_SHL8); - uop_MOVZX(ir, IREG_flags_res, IREG_temp1_B); - break; - - case 0x28: /*SHR*/ - uop_SHR(ir, IREG_temp1_B, IREG_temp0_B, IREG_temp2); - uop_MEM_STORE_REG(ir, ireg_seg_base(target_seg), IREG_eaaddr, IREG_temp1_B); - uop_MOVZX(ir, IREG_flags_op1, IREG_temp0_B); - uop_MOV(ir, IREG_flags_op2, IREG_temp2); - uop_MOV_IMM(ir, IREG_flags_op, FLAGS_SHR8); - uop_MOVZX(ir, IREG_flags_res, IREG_temp1_B); - break; - - case 0x38: /*SAR*/ - uop_SAR(ir, IREG_temp1_B, IREG_temp0_B, IREG_temp2); - uop_MEM_STORE_REG(ir, ireg_seg_base(target_seg), IREG_eaaddr, IREG_temp1_B); - uop_MOVZX(ir, IREG_flags_op1, IREG_temp0_B); - uop_MOV(ir, IREG_flags_op2, IREG_temp2); - uop_MOV_IMM(ir, IREG_flags_op, FLAGS_SAR8); - uop_MOVZX(ir, IREG_flags_res, IREG_temp1_B); - break; - - default: - return 0; - } - } - - codegen_flags_changed = 1; - return op_pc + 1; -} -uint32_t ropD3_w(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) -{ - if ((fetchdat & 0x30) == 0x10) /*RCL/RCR*/ - return 0; - - if (!(CL & 0x1f) || !block->ins) - return 0; - - uop_AND_IMM(ir, IREG_temp2, REG_ECX, 0x1f); - uop_CMP_IMM_JZ(ir, IREG_temp2, 0, codegen_exit_rout); - - codegen_mark_code_present(block, cs+op_pc, 1); - if ((fetchdat & 0xc0) == 0xc0) - { - int dest_reg = fetchdat & 7; - - switch (fetchdat & 0x38) - { - case 0x00: /*ROL*/ - uop_CALL_FUNC(ir, flags_rebuild); - uop_ROL(ir, IREG_16(dest_reg), IREG_16(dest_reg), IREG_temp2); - uop_MOV_IMM(ir, IREG_flags_op, FLAGS_ROL16); - uop_MOVZX(ir, IREG_flags_res, IREG_16(dest_reg)); - break; - - case 0x08: /*ROR*/ - uop_CALL_FUNC(ir, flags_rebuild); - uop_ROR(ir, IREG_16(dest_reg), IREG_16(dest_reg), IREG_temp2); - uop_MOV_IMM(ir, IREG_flags_op, FLAGS_ROR16); - uop_MOVZX(ir, IREG_flags_res, IREG_16(dest_reg)); - break; - - case 0x20: case 0x30: /*SHL*/ - uop_MOVZX(ir, IREG_flags_op1, IREG_16(dest_reg)); - uop_SHL(ir, IREG_16(dest_reg), IREG_16(dest_reg), IREG_temp2); - uop_MOV(ir, IREG_flags_op2, IREG_temp2); - uop_MOV_IMM(ir, IREG_flags_op, FLAGS_SHL16); - uop_MOVZX(ir, IREG_flags_res, IREG_16(dest_reg)); - break; - - case 0x28: /*SHR*/ - uop_MOVZX(ir, IREG_flags_op1, IREG_16(dest_reg)); - uop_SHR(ir, IREG_16(dest_reg), IREG_16(dest_reg), IREG_temp2); - uop_MOV(ir, IREG_flags_op2, IREG_temp2); - uop_MOV_IMM(ir, IREG_flags_op, FLAGS_SHR16); - uop_MOVZX(ir, IREG_flags_res, IREG_16(dest_reg)); - break; - - case 0x38: /*SAR*/ - uop_MOVZX(ir, IREG_flags_op1, IREG_16(dest_reg)); - uop_SAR(ir, IREG_16(dest_reg), IREG_16(dest_reg), IREG_temp2); - uop_MOV(ir, IREG_flags_op2, IREG_temp2); - uop_MOV_IMM(ir, IREG_flags_op, FLAGS_SAR16); - uop_MOVZX(ir, IREG_flags_res, IREG_16(dest_reg)); - break; - - default: - return 0; - } - } - else - { - x86seg *target_seg; - - uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc); - target_seg = codegen_generate_ea(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32, 0); - codegen_check_seg_write(block, ir, target_seg); - uop_MEM_LOAD_REG(ir, IREG_temp0_W, ireg_seg_base(target_seg), IREG_eaaddr); - - switch (fetchdat & 0x38) - { - case 0x00: /*ROL*/ - uop_CALL_FUNC(ir, flags_rebuild); - uop_ROL(ir, IREG_temp0_W, IREG_temp0_W, IREG_temp2); - uop_MEM_STORE_REG(ir, ireg_seg_base(target_seg), IREG_eaaddr, IREG_temp0_W); - uop_MOV_IMM(ir, IREG_flags_op, FLAGS_ROL16); - uop_MOVZX(ir, IREG_flags_res, IREG_temp0_W); - break; - - case 0x08: /*ROR*/ - uop_CALL_FUNC(ir, flags_rebuild); - uop_ROR(ir, IREG_temp0_W, IREG_temp0_W, IREG_temp2); - uop_MEM_STORE_REG(ir, ireg_seg_base(target_seg), IREG_eaaddr, IREG_temp0_W); - uop_MOV_IMM(ir, IREG_flags_op, FLAGS_ROR16); - uop_MOVZX(ir, IREG_flags_res, IREG_temp0_W); - break; - - case 0x20: case 0x30: /*SHL*/ - uop_SHL(ir, IREG_temp1_W, IREG_temp0_W, IREG_temp2); - uop_MEM_STORE_REG(ir, ireg_seg_base(target_seg), IREG_eaaddr, IREG_temp1_W); - uop_MOVZX(ir, IREG_flags_op1, IREG_temp0_W); - uop_MOV(ir, IREG_flags_op2, IREG_temp2); - uop_MOV_IMM(ir, IREG_flags_op, FLAGS_SHL16); - uop_MOVZX(ir, IREG_flags_res, IREG_temp1_W); - break; - - case 0x28: /*SHR*/ - uop_SHR(ir, IREG_temp1_W, IREG_temp0_W, IREG_temp2); - uop_MEM_STORE_REG(ir, ireg_seg_base(target_seg), IREG_eaaddr, IREG_temp1_W); - uop_MOVZX(ir, IREG_flags_op1, IREG_temp0_W); - uop_MOV(ir, IREG_flags_op2, IREG_temp2); - uop_MOV_IMM(ir, IREG_flags_op, FLAGS_SHR16); - uop_MOVZX(ir, IREG_flags_res, IREG_temp1_W); - break; - - case 0x38: /*SAR*/ - uop_SAR(ir, IREG_temp1_W, IREG_temp0_W, IREG_temp2); - uop_MEM_STORE_REG(ir, ireg_seg_base(target_seg), IREG_eaaddr, IREG_temp1_W); - uop_MOVZX(ir, IREG_flags_op1, IREG_temp0_W); - uop_MOV(ir, IREG_flags_op2, IREG_temp2); - uop_MOV_IMM(ir, IREG_flags_op, FLAGS_SAR16); - uop_MOVZX(ir, IREG_flags_res, IREG_temp1_W); - break; - - default: - return 0; - } - } - - codegen_flags_changed = 1; - return op_pc + 1; -} -uint32_t ropD3_l(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) -{ - if ((fetchdat & 0x30) == 0x10) /*RCL/RCR*/ - return 0; - - if (!(CL & 0x1f) || !block->ins) - return 0; - - uop_AND_IMM(ir, IREG_temp2, REG_ECX, 0x1f); - uop_CMP_IMM_JZ(ir, IREG_temp2, 0, codegen_exit_rout); - - codegen_mark_code_present(block, cs+op_pc, 1); - if ((fetchdat & 0xc0) == 0xc0) - { - int dest_reg = fetchdat & 7; - - switch (fetchdat & 0x38) - { - case 0x00: /*ROL*/ - uop_CALL_FUNC(ir, flags_rebuild); - uop_ROL(ir, IREG_32(dest_reg), IREG_32(dest_reg), IREG_temp2); - uop_MOV_IMM(ir, IREG_flags_op, FLAGS_ROL32); - uop_MOV(ir, IREG_flags_res, IREG_32(dest_reg)); - break; - - case 0x08: /*ROR*/ - uop_CALL_FUNC(ir, flags_rebuild); - uop_ROR(ir, IREG_32(dest_reg), IREG_32(dest_reg), IREG_temp2); - uop_MOV_IMM(ir, IREG_flags_op, FLAGS_ROR32); - uop_MOV(ir, IREG_flags_res, IREG_32(dest_reg)); - break; - - case 0x20: case 0x30: /*SHL*/ - uop_MOV(ir, IREG_flags_op1, IREG_32(dest_reg)); - uop_SHL(ir, IREG_32(dest_reg), IREG_32(dest_reg), IREG_temp2); - uop_MOV(ir, IREG_flags_op2, IREG_temp2); - uop_MOV_IMM(ir, IREG_flags_op, FLAGS_SHL32); - uop_MOV(ir, IREG_flags_res, IREG_32(dest_reg)); - break; - - case 0x28: /*SHR*/ - uop_MOV(ir, IREG_flags_op1, IREG_32(dest_reg)); - uop_SHR(ir, IREG_32(dest_reg), IREG_32(dest_reg), IREG_temp2); - uop_MOV(ir, IREG_flags_op2, IREG_temp2); - uop_MOV_IMM(ir, IREG_flags_op, FLAGS_SHR32); - uop_MOV(ir, IREG_flags_res, IREG_32(dest_reg)); - break; - - case 0x38: /*SAR*/ - uop_MOV(ir, IREG_flags_op1, IREG_32(dest_reg)); - uop_SAR(ir, IREG_32(dest_reg), IREG_32(dest_reg), IREG_temp2); - uop_MOV(ir, IREG_flags_op2, IREG_temp2); - uop_MOV_IMM(ir, IREG_flags_op, FLAGS_SAR32); - uop_MOV(ir, IREG_flags_res, IREG_32(dest_reg)); - break; - - default: - return 0; - } - } - else - { - x86seg *target_seg; - - uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc); - target_seg = codegen_generate_ea(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32, 0); - codegen_check_seg_write(block, ir, target_seg); - uop_MEM_LOAD_REG(ir, IREG_temp0, ireg_seg_base(target_seg), IREG_eaaddr); - - switch (fetchdat & 0x38) - { - case 0x00: /*ROL*/ - uop_CALL_FUNC(ir, flags_rebuild); - uop_ROL(ir, IREG_temp0, IREG_temp0, IREG_temp2); - uop_MEM_STORE_REG(ir, ireg_seg_base(target_seg), IREG_eaaddr, IREG_temp0); - uop_MOV_IMM(ir, IREG_flags_op, FLAGS_ROL32); - uop_MOV(ir, IREG_flags_res, IREG_temp0); - break; - - case 0x08: /*ROR*/ - uop_CALL_FUNC(ir, flags_rebuild); - uop_ROR(ir, IREG_temp0, IREG_temp0, IREG_temp2); - uop_MEM_STORE_REG(ir, ireg_seg_base(target_seg), IREG_eaaddr, IREG_temp0); - uop_MOV_IMM(ir, IREG_flags_op, FLAGS_ROR32); - uop_MOV(ir, IREG_flags_res, IREG_temp0); - break; - - case 0x20: case 0x30: /*SHL*/ - uop_SHL(ir, IREG_temp1, IREG_temp0, IREG_temp2); - uop_MEM_STORE_REG(ir, ireg_seg_base(target_seg), IREG_eaaddr, IREG_temp1); - uop_MOV(ir, IREG_flags_op1, IREG_temp0); - uop_MOV(ir, IREG_flags_op2, IREG_temp2); - uop_MOV_IMM(ir, IREG_flags_op, FLAGS_SHL32); - uop_MOV(ir, IREG_flags_res, IREG_temp1); - break; - - case 0x28: /*SHR*/ - uop_SHR(ir, IREG_temp1, IREG_temp0, IREG_temp2); - uop_MEM_STORE_REG(ir, ireg_seg_base(target_seg), IREG_eaaddr, IREG_temp1); - uop_MOV(ir, IREG_flags_op1, IREG_temp0); - uop_MOV(ir, IREG_flags_op2, IREG_temp2); - uop_MOV_IMM(ir, IREG_flags_op, FLAGS_SHR32); - uop_MOV(ir, IREG_flags_res, IREG_temp1); - break; - - case 0x38: /*SAR*/ - uop_SAR(ir, IREG_temp1, IREG_temp0, IREG_temp2); - uop_MEM_STORE_REG(ir, ireg_seg_base(target_seg), IREG_eaaddr, IREG_temp1); - uop_MOV(ir, IREG_flags_op1, IREG_temp0); - uop_MOV(ir, IREG_flags_op2, IREG_temp2); - uop_MOV_IMM(ir, IREG_flags_op, FLAGS_SAR32); - uop_MOV(ir, IREG_flags_res, IREG_temp1); - break; - - default: - return 0; - } - } - - codegen_flags_changed = 1; - return op_pc + 1; -} - -uint32_t ropSHLD_16_imm(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) -{ - x86seg *target_seg = NULL; - int src_reg = (fetchdat >> 3) & 7; - uint8_t imm; - - codegen_mark_code_present(block, cs+op_pc, 1); - if ((fetchdat & 0xc0) != 0xc0) - { - uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc); - target_seg = codegen_generate_ea(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32, 0); - } - imm = fastreadb(cs + op_pc + 1) & 0x1f; - codegen_mark_code_present(block, cs+op_pc+1, 1); - - if (!imm) - return op_pc+2; - - if ((fetchdat & 0xc0) == 0xc0) - { - int dest_reg = fetchdat & 7; + case 0x08: /*ROR*/ + uop_CALL_FUNC(ir, flags_rebuild); + uop_ROR_IMM(ir, IREG_16(dest_reg), IREG_16(dest_reg), count); + uop_MOV_IMM(ir, IREG_flags_op, FLAGS_ROR16); + uop_MOVZX(ir, IREG_flags_res, IREG_16(dest_reg)); + break; + case 0x20: + case 0x30: /*SHL*/ uop_MOVZX(ir, IREG_flags_op1, IREG_16(dest_reg)); - uop_SHL_IMM(ir, IREG_temp0_W, IREG_16(dest_reg), imm); - uop_SHR_IMM(ir, IREG_temp1_W, IREG_16(src_reg), 16 - imm); - uop_OR(ir, IREG_16(dest_reg), IREG_temp0_W, IREG_temp1_W); - uop_MOV_IMM(ir, IREG_flags_op2, imm); + uop_SHL_IMM(ir, IREG_16(dest_reg), IREG_16(dest_reg), count); + uop_MOV_IMM(ir, IREG_flags_op2, count); uop_MOV_IMM(ir, IREG_flags_op, FLAGS_SHL16); uop_MOVZX(ir, IREG_flags_res, IREG_16(dest_reg)); - } - else - { - codegen_check_seg_write(block, ir, target_seg); - uop_MEM_LOAD_REG(ir, IREG_temp2_W, ireg_seg_base(target_seg), IREG_eaaddr); - - uop_SHL_IMM(ir, IREG_temp0_W, IREG_temp2, imm); - uop_SHR_IMM(ir, IREG_temp1_W, IREG_16(src_reg), 16 - imm); - uop_OR(ir, IREG_temp0_W, IREG_temp0_W, IREG_temp1_W); - uop_MEM_STORE_REG(ir, ireg_seg_base(target_seg), IREG_eaaddr, IREG_temp0_W); - - uop_MOVZX(ir, IREG_flags_op1, IREG_temp2_W); - uop_MOVZX(ir, IREG_flags_res, IREG_temp0_W); - uop_MOV_IMM(ir, IREG_flags_op2, imm); - uop_MOV_IMM(ir, IREG_flags_op, FLAGS_SHL16); - } - - return op_pc+2; -} -uint32_t ropSHLD_32_imm(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) -{ - x86seg *target_seg = NULL; - int src_reg = (fetchdat >> 3) & 7; - uint8_t imm; - - codegen_mark_code_present(block, cs+op_pc, 1); - if ((fetchdat & 0xc0) != 0xc0) - { - uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc); - target_seg = codegen_generate_ea(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32, 0); - } - imm = fastreadb(cs + op_pc + 1) & 0x1f; - codegen_mark_code_present(block, cs+op_pc+1, 1); - - if (!imm) - return op_pc+2; - - if ((fetchdat & 0xc0) == 0xc0) - { - int dest_reg = fetchdat & 7; - - uop_MOV(ir, IREG_flags_op1, IREG_32(dest_reg)); - uop_SHL_IMM(ir, IREG_temp0, IREG_32(dest_reg), imm); - uop_SHR_IMM(ir, IREG_temp1, IREG_32(src_reg), 32 - imm); - uop_OR(ir, IREG_32(dest_reg), IREG_temp0, IREG_temp1); - uop_MOV_IMM(ir, IREG_flags_op2, imm); - uop_MOV_IMM(ir, IREG_flags_op, FLAGS_SHL32); - uop_MOV(ir, IREG_flags_res, IREG_32(dest_reg)); - } - else - { - codegen_check_seg_write(block, ir, target_seg); - uop_MEM_LOAD_REG(ir, IREG_temp2, ireg_seg_base(target_seg), IREG_eaaddr); - - uop_SHL_IMM(ir, IREG_temp0, IREG_temp2, imm); - uop_SHR_IMM(ir, IREG_temp1, IREG_32(src_reg), 32 - imm); - uop_OR(ir, IREG_temp0, IREG_temp0, IREG_temp1); - uop_MEM_STORE_REG(ir, ireg_seg_base(target_seg), IREG_eaaddr, IREG_temp0); - - uop_MOV(ir, IREG_flags_op1, IREG_temp2); - uop_MOV(ir, IREG_flags_res, IREG_temp0); - uop_MOV_IMM(ir, IREG_flags_op2, imm); - uop_MOV_IMM(ir, IREG_flags_op, FLAGS_SHL32); - } - - return op_pc+2; -} -uint32_t ropSHRD_16_imm(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) -{ - x86seg *target_seg = NULL; - int src_reg = (fetchdat >> 3) & 7; - uint8_t imm; - - codegen_mark_code_present(block, cs+op_pc, 1); - if ((fetchdat & 0xc0) != 0xc0) - { - uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc); - target_seg = codegen_generate_ea(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32, 0); - } - imm = fastreadb(cs + op_pc + 1) & 0x1f; - codegen_mark_code_present(block, cs+op_pc+1, 1); - - if (!imm) - return op_pc+2; - - if ((fetchdat & 0xc0) == 0xc0) - { - int dest_reg = fetchdat & 7; + break; + case 0x28: /*SHR*/ uop_MOVZX(ir, IREG_flags_op1, IREG_16(dest_reg)); - uop_SHR_IMM(ir, IREG_temp0_W, IREG_16(dest_reg), imm); - uop_SHL_IMM(ir, IREG_temp1_W, IREG_16(src_reg), 16 - imm); - uop_OR(ir, IREG_16(dest_reg), IREG_temp0_W, IREG_temp1_W); - uop_MOV_IMM(ir, IREG_flags_op2, imm); + uop_SHR_IMM(ir, IREG_16(dest_reg), IREG_16(dest_reg), count); + uop_MOV_IMM(ir, IREG_flags_op2, count); uop_MOV_IMM(ir, IREG_flags_op, FLAGS_SHR16); uop_MOVZX(ir, IREG_flags_res, IREG_16(dest_reg)); - } - else - { - codegen_check_seg_write(block, ir, target_seg); - uop_MEM_LOAD_REG(ir, IREG_temp2_W, ireg_seg_base(target_seg), IREG_eaaddr); + break; - uop_SHR_IMM(ir, IREG_temp0_W, IREG_temp2, imm); - uop_SHL_IMM(ir, IREG_temp1_W, IREG_16(src_reg), 16 - imm); - uop_OR(ir, IREG_temp0_W, IREG_temp0_W, IREG_temp1_W); + case 0x38: /*SAR*/ + uop_MOVZX(ir, IREG_flags_op1, IREG_16(dest_reg)); + uop_SAR_IMM(ir, IREG_16(dest_reg), IREG_16(dest_reg), count); + uop_MOV_IMM(ir, IREG_flags_op2, count); + uop_MOV_IMM(ir, IREG_flags_op, FLAGS_SAR16); + uop_MOVZX(ir, IREG_flags_res, IREG_16(dest_reg)); + break; + + default: + return 0; + } + } else { + switch (fetchdat & 0x38) { + case 0x00: /*ROL*/ + uop_CALL_FUNC(ir, flags_rebuild); + uop_ROL_IMM(ir, IREG_temp0_W, IREG_temp0_W, count); uop_MEM_STORE_REG(ir, ireg_seg_base(target_seg), IREG_eaaddr, IREG_temp0_W); - - uop_MOVZX(ir, IREG_flags_op1, IREG_temp2_W); + uop_MOV_IMM(ir, IREG_flags_op, FLAGS_ROL16); uop_MOVZX(ir, IREG_flags_res, IREG_temp0_W); - uop_MOV_IMM(ir, IREG_flags_op2, imm); + break; + + case 0x08: /*ROR*/ + uop_CALL_FUNC(ir, flags_rebuild); + uop_ROR_IMM(ir, IREG_temp0_W, IREG_temp0_W, count); + uop_MEM_STORE_REG(ir, ireg_seg_base(target_seg), IREG_eaaddr, IREG_temp0_W); + uop_MOV_IMM(ir, IREG_flags_op, FLAGS_ROR16); + uop_MOVZX(ir, IREG_flags_res, IREG_temp0_W); + break; + + case 0x20: + case 0x30: /*SHL*/ + uop_SHL_IMM(ir, IREG_temp1_W, IREG_temp0_W, count); + uop_MEM_STORE_REG(ir, ireg_seg_base(target_seg), IREG_eaaddr, IREG_temp1_W); + uop_MOVZX(ir, IREG_flags_op1, IREG_temp0_W); + uop_MOV_IMM(ir, IREG_flags_op2, count); + uop_MOV_IMM(ir, IREG_flags_op, FLAGS_SHL16); + uop_MOVZX(ir, IREG_flags_res, IREG_temp1_W); + break; + + case 0x28: /*SHR*/ + uop_SHR_IMM(ir, IREG_temp1_W, IREG_temp0_W, count); + uop_MEM_STORE_REG(ir, ireg_seg_base(target_seg), IREG_eaaddr, IREG_temp1_W); + uop_MOVZX(ir, IREG_flags_op1, IREG_temp0_W); + uop_MOV_IMM(ir, IREG_flags_op2, count); uop_MOV_IMM(ir, IREG_flags_op, FLAGS_SHR16); - } + uop_MOVZX(ir, IREG_flags_res, IREG_temp1_W); + break; - return op_pc+2; + case 0x38: /*SAR*/ + uop_SAR_IMM(ir, IREG_temp1_W, IREG_temp0_W, count); + uop_MEM_STORE_REG(ir, ireg_seg_base(target_seg), IREG_eaaddr, IREG_temp1_W); + uop_MOVZX(ir, IREG_flags_op1, IREG_temp0_W); + uop_MOV_IMM(ir, IREG_flags_op2, count); + uop_MOV_IMM(ir, IREG_flags_op, FLAGS_SAR16); + uop_MOVZX(ir, IREG_flags_res, IREG_temp1_W); + break; + + default: + return 0; + } + } + + codegen_flags_changed = 1; + return op_pc + 1; } -uint32_t ropSHRD_32_imm(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) +static uint32_t +shift_common_32(ir_data_t *ir, uint32_t fetchdat, uint32_t op_pc, x86seg *target_seg, int count) { - x86seg *target_seg = NULL; - int src_reg = (fetchdat >> 3) & 7; - uint8_t imm; + if ((fetchdat & 0xc0) == 0xc0) { + int dest_reg = fetchdat & 7; - codegen_mark_code_present(block, cs+op_pc, 1); - if ((fetchdat & 0xc0) != 0xc0) - { - uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc); - target_seg = codegen_generate_ea(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32, 0); - } - imm = fastreadb(cs + op_pc + 1) & 0x1f; - codegen_mark_code_present(block, cs+op_pc+1, 1); - - if (!imm) - return op_pc+2; + switch (fetchdat & 0x38) { + case 0x00: /*ROL*/ + uop_CALL_FUNC(ir, flags_rebuild); + uop_ROL_IMM(ir, IREG_32(dest_reg), IREG_32(dest_reg), count); + uop_MOV_IMM(ir, IREG_flags_op, FLAGS_ROL32); + uop_MOV(ir, IREG_flags_res, IREG_32(dest_reg)); + break; - if ((fetchdat & 0xc0) == 0xc0) - { - int dest_reg = fetchdat & 7; + case 0x08: /*ROR*/ + uop_CALL_FUNC(ir, flags_rebuild); + uop_ROR_IMM(ir, IREG_32(dest_reg), IREG_32(dest_reg), count); + uop_MOV_IMM(ir, IREG_flags_op, FLAGS_ROR32); + uop_MOV(ir, IREG_flags_res, IREG_32(dest_reg)); + break; + case 0x20: + case 0x30: /*SHL*/ uop_MOV(ir, IREG_flags_op1, IREG_32(dest_reg)); - uop_SHR_IMM(ir, IREG_temp0, IREG_32(dest_reg), imm); - uop_SHL_IMM(ir, IREG_temp1, IREG_32(src_reg), 32 - imm); - uop_OR(ir, IREG_32(dest_reg), IREG_temp0, IREG_temp1); - uop_MOV_IMM(ir, IREG_flags_op2, imm); + uop_SHL_IMM(ir, IREG_32(dest_reg), IREG_32(dest_reg), count); + uop_MOV_IMM(ir, IREG_flags_op2, count); + uop_MOV_IMM(ir, IREG_flags_op, FLAGS_SHL32); + uop_MOV(ir, IREG_flags_res, IREG_32(dest_reg)); + break; + + case 0x28: /*SHR*/ + uop_MOV(ir, IREG_flags_op1, IREG_32(dest_reg)); + uop_SHR_IMM(ir, IREG_32(dest_reg), IREG_32(dest_reg), count); + uop_MOV_IMM(ir, IREG_flags_op2, count); uop_MOV_IMM(ir, IREG_flags_op, FLAGS_SHR32); uop_MOV(ir, IREG_flags_res, IREG_32(dest_reg)); - } - else - { - codegen_check_seg_write(block, ir, target_seg); - uop_MEM_LOAD_REG(ir, IREG_temp2, ireg_seg_base(target_seg), IREG_eaaddr); + break; - uop_SHR_IMM(ir, IREG_temp0, IREG_temp2, imm); - uop_SHL_IMM(ir, IREG_temp1, IREG_32(src_reg), 32 - imm); - uop_OR(ir, IREG_temp0, IREG_temp0, IREG_temp1); + case 0x38: /*SAR*/ + uop_MOV(ir, IREG_flags_op1, IREG_32(dest_reg)); + uop_SAR_IMM(ir, IREG_32(dest_reg), IREG_32(dest_reg), count); + uop_MOV_IMM(ir, IREG_flags_op2, count); + uop_MOV_IMM(ir, IREG_flags_op, FLAGS_SAR32); + uop_MOV(ir, IREG_flags_res, IREG_32(dest_reg)); + break; + + default: + return 0; + } + } else { + switch (fetchdat & 0x38) { + case 0x00: /*ROL*/ + uop_CALL_FUNC(ir, flags_rebuild); + uop_ROL_IMM(ir, IREG_temp0, IREG_temp0, count); uop_MEM_STORE_REG(ir, ireg_seg_base(target_seg), IREG_eaaddr, IREG_temp0); - - uop_MOV(ir, IREG_flags_op1, IREG_temp2); + uop_MOV_IMM(ir, IREG_flags_op, FLAGS_ROL32); uop_MOV(ir, IREG_flags_res, IREG_temp0); - uop_MOV_IMM(ir, IREG_flags_op2, imm); - uop_MOV_IMM(ir, IREG_flags_op, FLAGS_SHR32); - } + break; - return op_pc+2; + case 0x08: /*ROR*/ + uop_CALL_FUNC(ir, flags_rebuild); + uop_ROR_IMM(ir, IREG_temp0, IREG_temp0, count); + uop_MEM_STORE_REG(ir, ireg_seg_base(target_seg), IREG_eaaddr, IREG_temp0); + uop_MOV_IMM(ir, IREG_flags_op, FLAGS_ROR32); + uop_MOV(ir, IREG_flags_res, IREG_temp0); + break; + + case 0x20: + case 0x30: /*SHL*/ + uop_SHL_IMM(ir, IREG_temp1, IREG_temp0, count); + uop_MEM_STORE_REG(ir, ireg_seg_base(target_seg), IREG_eaaddr, IREG_temp1); + uop_MOV(ir, IREG_flags_op1, IREG_temp0); + uop_MOV_IMM(ir, IREG_flags_op2, count); + uop_MOV_IMM(ir, IREG_flags_op, FLAGS_SHL32); + uop_MOV(ir, IREG_flags_res, IREG_temp1); + break; + + case 0x28: /*SHR*/ + uop_SHR_IMM(ir, IREG_temp1, IREG_temp0, count); + uop_MEM_STORE_REG(ir, ireg_seg_base(target_seg), IREG_eaaddr, IREG_temp1); + uop_MOV(ir, IREG_flags_op1, IREG_temp0); + uop_MOV_IMM(ir, IREG_flags_op2, count); + uop_MOV_IMM(ir, IREG_flags_op, FLAGS_SHR32); + uop_MOV(ir, IREG_flags_res, IREG_temp1); + break; + + case 0x38: /*SAR*/ + uop_SAR_IMM(ir, IREG_temp1, IREG_temp0, count); + uop_MEM_STORE_REG(ir, ireg_seg_base(target_seg), IREG_eaaddr, IREG_temp1); + uop_MOV(ir, IREG_flags_op1, IREG_temp0); + uop_MOV_IMM(ir, IREG_flags_op2, count); + uop_MOV_IMM(ir, IREG_flags_op, FLAGS_SAR32); + uop_MOV(ir, IREG_flags_res, IREG_temp1); + break; + + default: + return 0; + } + } + + codegen_flags_changed = 1; + return op_pc + 1; +} + +static uint32_t +shift_common_variable_32(ir_data_t *ir, uint32_t fetchdat, uint32_t op_pc, x86seg *target_seg, int count_reg) +{ + if ((fetchdat & 0xc0) == 0xc0) { + int dest_reg = fetchdat & 7; + + switch (fetchdat & 0x38) { + case 0x00: /*ROL*/ + uop_CALL_FUNC(ir, flags_rebuild); + uop_ROL(ir, IREG_32(dest_reg), IREG_32(dest_reg), count_reg); + uop_MOV_IMM(ir, IREG_flags_op, FLAGS_ROL32); + uop_MOV(ir, IREG_flags_res, IREG_32(dest_reg)); + break; + + case 0x08: /*ROR*/ + uop_CALL_FUNC(ir, flags_rebuild); + uop_ROR(ir, IREG_32(dest_reg), IREG_32(dest_reg), count_reg); + uop_MOV_IMM(ir, IREG_flags_op, FLAGS_ROR32); + uop_MOV(ir, IREG_flags_res, IREG_32(dest_reg)); + break; + + case 0x20: + case 0x30: /*SHL*/ + uop_MOV(ir, IREG_flags_op1, IREG_32(dest_reg)); + uop_SHL(ir, IREG_32(dest_reg), IREG_32(dest_reg), count_reg); + uop_MOV(ir, IREG_flags_op2, count_reg); + uop_MOV_IMM(ir, IREG_flags_op, FLAGS_SHL32); + uop_MOV(ir, IREG_flags_res, IREG_32(dest_reg)); + break; + + case 0x28: /*SHR*/ + uop_MOV(ir, IREG_flags_op1, IREG_32(dest_reg)); + uop_SHR(ir, IREG_32(dest_reg), IREG_32(dest_reg), count_reg); + uop_MOV(ir, IREG_flags_op2, count_reg); + uop_MOV_IMM(ir, IREG_flags_op, FLAGS_SHR32); + uop_MOV(ir, IREG_flags_res, IREG_32(dest_reg)); + break; + + case 0x38: /*SAR*/ + uop_MOV(ir, IREG_flags_op1, IREG_32(dest_reg)); + uop_SAR(ir, IREG_32(dest_reg), IREG_32(dest_reg), count_reg); + uop_MOV(ir, IREG_flags_op2, count_reg); + uop_MOV_IMM(ir, IREG_flags_op, FLAGS_SAR32); + uop_MOV(ir, IREG_flags_res, IREG_32(dest_reg)); + break; + + default: + return 0; + } + } else { + switch (fetchdat & 0x38) { + case 0x00: /*ROL*/ + uop_CALL_FUNC(ir, flags_rebuild); + uop_ROL(ir, IREG_temp0, IREG_temp0, count_reg); + uop_MEM_STORE_REG(ir, ireg_seg_base(target_seg), IREG_eaaddr, IREG_temp0); + uop_MOV_IMM(ir, IREG_flags_op, FLAGS_ROL32); + uop_MOV(ir, IREG_flags_res, IREG_temp0); + break; + + case 0x08: /*ROR*/ + uop_CALL_FUNC(ir, flags_rebuild); + uop_ROR(ir, IREG_temp0, IREG_temp0, count_reg); + uop_MEM_STORE_REG(ir, ireg_seg_base(target_seg), IREG_eaaddr, IREG_temp0); + uop_MOV_IMM(ir, IREG_flags_op, FLAGS_ROR32); + uop_MOV(ir, IREG_flags_res, IREG_temp0); + break; + + case 0x20: + case 0x30: /*SHL*/ + uop_SHL(ir, IREG_temp1, IREG_temp0, count_reg); + uop_MEM_STORE_REG(ir, ireg_seg_base(target_seg), IREG_eaaddr, IREG_temp1); + uop_MOV(ir, IREG_flags_op1, IREG_temp0); + uop_MOV(ir, IREG_flags_op2, count_reg); + uop_MOV_IMM(ir, IREG_flags_op, FLAGS_SHL32); + uop_MOV(ir, IREG_flags_res, IREG_temp1); + break; + + case 0x28: /*SHR*/ + uop_SHR(ir, IREG_temp1, IREG_temp0, count_reg); + uop_MEM_STORE_REG(ir, ireg_seg_base(target_seg), IREG_eaaddr, IREG_temp1); + uop_MOV(ir, IREG_flags_op1, IREG_temp0); + uop_MOV(ir, IREG_flags_op2, count_reg); + uop_MOV_IMM(ir, IREG_flags_op, FLAGS_SHR32); + uop_MOV(ir, IREG_flags_res, IREG_temp1); + break; + + case 0x38: /*SAR*/ + uop_SAR(ir, IREG_temp1, IREG_temp0, count_reg); + uop_MEM_STORE_REG(ir, ireg_seg_base(target_seg), IREG_eaaddr, IREG_temp1); + uop_MOV(ir, IREG_flags_op1, IREG_temp0); + uop_MOV(ir, IREG_flags_op2, count_reg); + uop_MOV_IMM(ir, IREG_flags_op, FLAGS_SAR32); + uop_MOV(ir, IREG_flags_res, IREG_temp1); + break; + + default: + return 0; + } + } + + codegen_flags_changed = 1; + return op_pc + 1; +} + +uint32_t +ropC0(codeblock_t *block, ir_data_t *ir, UNUSED(uint8_t opcode), uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) +{ + x86seg *target_seg = NULL; + uint8_t imm; + + if ((fetchdat & 0x30) == 0x10) /*RCL/RCR*/ + return 0; + + codegen_mark_code_present(block, cs + op_pc, 1); + if ((fetchdat & 0xc0) != 0xc0) { + uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc); + target_seg = codegen_generate_ea(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32, 0); + codegen_check_seg_write(block, ir, target_seg); + uop_MEM_LOAD_REG(ir, IREG_temp0_B, ireg_seg_base(target_seg), IREG_eaaddr); + } + imm = fastreadb(cs + op_pc + 1) & 0x1f; + codegen_mark_code_present(block, cs + op_pc + 1, 1); + + if (imm) + return shift_common_8(ir, fetchdat, op_pc, target_seg, imm) + 1; + return op_pc + 1; +} +uint32_t +ropC1_w(codeblock_t *block, ir_data_t *ir, UNUSED(uint8_t opcode), uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) +{ + x86seg *target_seg = NULL; + uint8_t imm; + + if ((fetchdat & 0x30) == 0x10) /*RCL/RCR*/ + return 0; + + codegen_mark_code_present(block, cs + op_pc, 1); + if ((fetchdat & 0xc0) != 0xc0) { + uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc); + target_seg = codegen_generate_ea(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32, 0); + codegen_check_seg_write(block, ir, target_seg); + uop_MEM_LOAD_REG(ir, IREG_temp0_W, ireg_seg_base(target_seg), IREG_eaaddr); + } + imm = fastreadb(cs + op_pc + 1) & 0x1f; + codegen_mark_code_present(block, cs + op_pc + 1, 1); + + if (imm) + return shift_common_16(ir, fetchdat, op_pc, target_seg, imm) + 1; + return op_pc + 1; +} +uint32_t +ropC1_l(codeblock_t *block, ir_data_t *ir, UNUSED(uint8_t opcode), uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) +{ + x86seg *target_seg = NULL; + + if ((fetchdat & 0x30) == 0x10) /*RCL/RCR*/ + return 0; + + codegen_mark_code_present(block, cs + op_pc, 1); + if ((fetchdat & 0xc0) != 0xc0) { + uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc); + target_seg = codegen_generate_ea(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32, 0); + codegen_check_seg_write(block, ir, target_seg); + uop_MEM_LOAD_REG(ir, IREG_temp0, ireg_seg_base(target_seg), IREG_eaaddr); + } + if (block->flags & CODEBLOCK_NO_IMMEDIATES) { + uint32_t new_pc; + int jump_uop; + + LOAD_IMMEDIATE_FROM_RAM_8(block, ir, IREG_temp2, cs + op_pc + 1); + uop_AND_IMM(ir, IREG_temp2, IREG_temp2, 0x1f); + jump_uop = uop_CMP_IMM_JZ_DEST(ir, IREG_temp2, 0); + + new_pc = shift_common_variable_32(ir, fetchdat, op_pc, target_seg, IREG_temp2) + 1; + uop_NOP_BARRIER(ir); + uop_set_jump_dest(ir, jump_uop); + return new_pc; + } else { + uint8_t imm = fastreadb(cs + op_pc + 1) & 0x1f; + codegen_mark_code_present(block, cs + op_pc + 1, 1); + + if (imm) + return shift_common_32(ir, fetchdat, op_pc, target_seg, imm) + 1; + } + return op_pc + 1; +} + +uint32_t +ropD0(codeblock_t *block, ir_data_t *ir, UNUSED(uint8_t opcode), uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) +{ + x86seg *target_seg = NULL; + + if ((fetchdat & 0x30) == 0x10) /*RCL/RCR*/ + return 0; + + codegen_mark_code_present(block, cs + op_pc, 1); + if ((fetchdat & 0xc0) != 0xc0) { + uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc); + target_seg = codegen_generate_ea(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32, 0); + codegen_check_seg_write(block, ir, target_seg); + uop_MEM_LOAD_REG(ir, IREG_temp0_B, ireg_seg_base(target_seg), IREG_eaaddr); + } + + return shift_common_8(ir, fetchdat, op_pc, target_seg, 1); +} +uint32_t +ropD1_w(codeblock_t *block, ir_data_t *ir, UNUSED(uint8_t opcode), uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) +{ + x86seg *target_seg = NULL; + + if ((fetchdat & 0x30) == 0x10) /*RCL/RCR*/ + return 0; + + codegen_mark_code_present(block, cs + op_pc, 1); + if ((fetchdat & 0xc0) != 0xc0) { + uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc); + target_seg = codegen_generate_ea(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32, 0); + codegen_check_seg_write(block, ir, target_seg); + uop_MEM_LOAD_REG(ir, IREG_temp0_W, ireg_seg_base(target_seg), IREG_eaaddr); + } + + return shift_common_16(ir, fetchdat, op_pc, target_seg, 1); +} +uint32_t +ropD1_l(codeblock_t *block, ir_data_t *ir, UNUSED(uint8_t opcode), uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) +{ + x86seg *target_seg = NULL; + + if ((fetchdat & 0x30) == 0x10) /*RCL/RCR*/ + return 0; + + codegen_mark_code_present(block, cs + op_pc, 1); + if ((fetchdat & 0xc0) != 0xc0) { + uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc); + target_seg = codegen_generate_ea(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32, 0); + codegen_check_seg_write(block, ir, target_seg); + uop_MEM_LOAD_REG(ir, IREG_temp0, ireg_seg_base(target_seg), IREG_eaaddr); + } + + return shift_common_32(ir, fetchdat, op_pc, target_seg, 1); +} + +uint32_t +ropD2(codeblock_t *block, ir_data_t *ir, UNUSED(uint8_t opcode), uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) +{ + if ((fetchdat & 0x30) == 0x10) /*RCL/RCR*/ + return 0; + + if (!(CL & 0x1f) || !block->ins) + return 0; + + uop_AND_IMM(ir, IREG_temp2, REG_ECX, 0x1f); + uop_CMP_IMM_JZ(ir, IREG_temp2, 0, codegen_exit_rout); + + codegen_mark_code_present(block, cs + op_pc, 1); + if ((fetchdat & 0xc0) == 0xc0) { + int dest_reg = fetchdat & 7; + + switch (fetchdat & 0x38) { + case 0x00: /*ROL*/ + uop_CALL_FUNC(ir, flags_rebuild); + uop_ROL(ir, IREG_8(dest_reg), IREG_8(dest_reg), IREG_temp2); + uop_MOV_IMM(ir, IREG_flags_op, FLAGS_ROL8); + uop_MOVZX(ir, IREG_flags_res, IREG_8(dest_reg)); + break; + + case 0x08: /*ROR*/ + uop_CALL_FUNC(ir, flags_rebuild); + uop_ROR(ir, IREG_8(dest_reg), IREG_8(dest_reg), IREG_temp2); + uop_MOV_IMM(ir, IREG_flags_op, FLAGS_ROR8); + uop_MOVZX(ir, IREG_flags_res, IREG_8(dest_reg)); + break; + + case 0x20: + case 0x30: /*SHL*/ + uop_MOVZX(ir, IREG_flags_op1, IREG_8(dest_reg)); + uop_SHL(ir, IREG_8(dest_reg), IREG_8(dest_reg), IREG_temp2); + uop_MOV(ir, IREG_flags_op2, IREG_temp2); + uop_MOV_IMM(ir, IREG_flags_op, FLAGS_SHL8); + uop_MOVZX(ir, IREG_flags_res, IREG_8(dest_reg)); + break; + + case 0x28: /*SHR*/ + uop_MOVZX(ir, IREG_flags_op1, IREG_8(dest_reg)); + uop_SHR(ir, IREG_8(dest_reg), IREG_8(dest_reg), IREG_temp2); + uop_MOV(ir, IREG_flags_op2, IREG_temp2); + uop_MOV_IMM(ir, IREG_flags_op, FLAGS_SHR8); + uop_MOVZX(ir, IREG_flags_res, IREG_8(dest_reg)); + break; + + case 0x38: /*SAR*/ + uop_MOVZX(ir, IREG_flags_op1, IREG_8(dest_reg)); + uop_SAR(ir, IREG_8(dest_reg), IREG_8(dest_reg), IREG_temp2); + uop_MOV(ir, IREG_flags_op2, IREG_temp2); + uop_MOV_IMM(ir, IREG_flags_op, FLAGS_SAR8); + uop_MOVZX(ir, IREG_flags_res, IREG_8(dest_reg)); + break; + + default: + return 0; + } + } else { + x86seg *target_seg; + + uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc); + target_seg = codegen_generate_ea(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32, 0); + codegen_check_seg_write(block, ir, target_seg); + uop_MEM_LOAD_REG(ir, IREG_temp0_B, ireg_seg_base(target_seg), IREG_eaaddr); + + switch (fetchdat & 0x38) { + case 0x00: /*ROL*/ + uop_CALL_FUNC(ir, flags_rebuild); + uop_ROL(ir, IREG_temp0_B, IREG_temp0_B, IREG_temp2); + uop_MEM_STORE_REG(ir, ireg_seg_base(target_seg), IREG_eaaddr, IREG_temp0_B); + uop_MOV_IMM(ir, IREG_flags_op, FLAGS_ROL8); + uop_MOVZX(ir, IREG_flags_res, IREG_temp0_B); + break; + + case 0x08: /*ROR*/ + uop_CALL_FUNC(ir, flags_rebuild); + uop_ROR(ir, IREG_temp0_B, IREG_temp0_B, IREG_temp2); + uop_MEM_STORE_REG(ir, ireg_seg_base(target_seg), IREG_eaaddr, IREG_temp0_B); + uop_MOV_IMM(ir, IREG_flags_op, FLAGS_ROR8); + uop_MOVZX(ir, IREG_flags_res, IREG_temp0_B); + break; + + case 0x20: + case 0x30: /*SHL*/ + uop_SHL(ir, IREG_temp1_B, IREG_temp0_B, IREG_temp2); + uop_MEM_STORE_REG(ir, ireg_seg_base(target_seg), IREG_eaaddr, IREG_temp1_B); + uop_MOVZX(ir, IREG_flags_op1, IREG_temp0_B); + uop_MOV(ir, IREG_flags_op2, IREG_temp2); + uop_MOV_IMM(ir, IREG_flags_op, FLAGS_SHL8); + uop_MOVZX(ir, IREG_flags_res, IREG_temp1_B); + break; + + case 0x28: /*SHR*/ + uop_SHR(ir, IREG_temp1_B, IREG_temp0_B, IREG_temp2); + uop_MEM_STORE_REG(ir, ireg_seg_base(target_seg), IREG_eaaddr, IREG_temp1_B); + uop_MOVZX(ir, IREG_flags_op1, IREG_temp0_B); + uop_MOV(ir, IREG_flags_op2, IREG_temp2); + uop_MOV_IMM(ir, IREG_flags_op, FLAGS_SHR8); + uop_MOVZX(ir, IREG_flags_res, IREG_temp1_B); + break; + + case 0x38: /*SAR*/ + uop_SAR(ir, IREG_temp1_B, IREG_temp0_B, IREG_temp2); + uop_MEM_STORE_REG(ir, ireg_seg_base(target_seg), IREG_eaaddr, IREG_temp1_B); + uop_MOVZX(ir, IREG_flags_op1, IREG_temp0_B); + uop_MOV(ir, IREG_flags_op2, IREG_temp2); + uop_MOV_IMM(ir, IREG_flags_op, FLAGS_SAR8); + uop_MOVZX(ir, IREG_flags_res, IREG_temp1_B); + break; + + default: + return 0; + } + } + + codegen_flags_changed = 1; + return op_pc + 1; +} +uint32_t +ropD3_w(codeblock_t *block, ir_data_t *ir, UNUSED(uint8_t opcode), uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) +{ + if ((fetchdat & 0x30) == 0x10) /*RCL/RCR*/ + return 0; + + if (!(CL & 0x1f) || !block->ins) + return 0; + + uop_AND_IMM(ir, IREG_temp2, REG_ECX, 0x1f); + uop_CMP_IMM_JZ(ir, IREG_temp2, 0, codegen_exit_rout); + + codegen_mark_code_present(block, cs + op_pc, 1); + if ((fetchdat & 0xc0) == 0xc0) { + int dest_reg = fetchdat & 7; + + switch (fetchdat & 0x38) { + case 0x00: /*ROL*/ + uop_CALL_FUNC(ir, flags_rebuild); + uop_ROL(ir, IREG_16(dest_reg), IREG_16(dest_reg), IREG_temp2); + uop_MOV_IMM(ir, IREG_flags_op, FLAGS_ROL16); + uop_MOVZX(ir, IREG_flags_res, IREG_16(dest_reg)); + break; + + case 0x08: /*ROR*/ + uop_CALL_FUNC(ir, flags_rebuild); + uop_ROR(ir, IREG_16(dest_reg), IREG_16(dest_reg), IREG_temp2); + uop_MOV_IMM(ir, IREG_flags_op, FLAGS_ROR16); + uop_MOVZX(ir, IREG_flags_res, IREG_16(dest_reg)); + break; + + case 0x20: + case 0x30: /*SHL*/ + uop_MOVZX(ir, IREG_flags_op1, IREG_16(dest_reg)); + uop_SHL(ir, IREG_16(dest_reg), IREG_16(dest_reg), IREG_temp2); + uop_MOV(ir, IREG_flags_op2, IREG_temp2); + uop_MOV_IMM(ir, IREG_flags_op, FLAGS_SHL16); + uop_MOVZX(ir, IREG_flags_res, IREG_16(dest_reg)); + break; + + case 0x28: /*SHR*/ + uop_MOVZX(ir, IREG_flags_op1, IREG_16(dest_reg)); + uop_SHR(ir, IREG_16(dest_reg), IREG_16(dest_reg), IREG_temp2); + uop_MOV(ir, IREG_flags_op2, IREG_temp2); + uop_MOV_IMM(ir, IREG_flags_op, FLAGS_SHR16); + uop_MOVZX(ir, IREG_flags_res, IREG_16(dest_reg)); + break; + + case 0x38: /*SAR*/ + uop_MOVZX(ir, IREG_flags_op1, IREG_16(dest_reg)); + uop_SAR(ir, IREG_16(dest_reg), IREG_16(dest_reg), IREG_temp2); + uop_MOV(ir, IREG_flags_op2, IREG_temp2); + uop_MOV_IMM(ir, IREG_flags_op, FLAGS_SAR16); + uop_MOVZX(ir, IREG_flags_res, IREG_16(dest_reg)); + break; + + default: + return 0; + } + } else { + x86seg *target_seg; + + uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc); + target_seg = codegen_generate_ea(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32, 0); + codegen_check_seg_write(block, ir, target_seg); + uop_MEM_LOAD_REG(ir, IREG_temp0_W, ireg_seg_base(target_seg), IREG_eaaddr); + + switch (fetchdat & 0x38) { + case 0x00: /*ROL*/ + uop_CALL_FUNC(ir, flags_rebuild); + uop_ROL(ir, IREG_temp0_W, IREG_temp0_W, IREG_temp2); + uop_MEM_STORE_REG(ir, ireg_seg_base(target_seg), IREG_eaaddr, IREG_temp0_W); + uop_MOV_IMM(ir, IREG_flags_op, FLAGS_ROL16); + uop_MOVZX(ir, IREG_flags_res, IREG_temp0_W); + break; + + case 0x08: /*ROR*/ + uop_CALL_FUNC(ir, flags_rebuild); + uop_ROR(ir, IREG_temp0_W, IREG_temp0_W, IREG_temp2); + uop_MEM_STORE_REG(ir, ireg_seg_base(target_seg), IREG_eaaddr, IREG_temp0_W); + uop_MOV_IMM(ir, IREG_flags_op, FLAGS_ROR16); + uop_MOVZX(ir, IREG_flags_res, IREG_temp0_W); + break; + + case 0x20: + case 0x30: /*SHL*/ + uop_SHL(ir, IREG_temp1_W, IREG_temp0_W, IREG_temp2); + uop_MEM_STORE_REG(ir, ireg_seg_base(target_seg), IREG_eaaddr, IREG_temp1_W); + uop_MOVZX(ir, IREG_flags_op1, IREG_temp0_W); + uop_MOV(ir, IREG_flags_op2, IREG_temp2); + uop_MOV_IMM(ir, IREG_flags_op, FLAGS_SHL16); + uop_MOVZX(ir, IREG_flags_res, IREG_temp1_W); + break; + + case 0x28: /*SHR*/ + uop_SHR(ir, IREG_temp1_W, IREG_temp0_W, IREG_temp2); + uop_MEM_STORE_REG(ir, ireg_seg_base(target_seg), IREG_eaaddr, IREG_temp1_W); + uop_MOVZX(ir, IREG_flags_op1, IREG_temp0_W); + uop_MOV(ir, IREG_flags_op2, IREG_temp2); + uop_MOV_IMM(ir, IREG_flags_op, FLAGS_SHR16); + uop_MOVZX(ir, IREG_flags_res, IREG_temp1_W); + break; + + case 0x38: /*SAR*/ + uop_SAR(ir, IREG_temp1_W, IREG_temp0_W, IREG_temp2); + uop_MEM_STORE_REG(ir, ireg_seg_base(target_seg), IREG_eaaddr, IREG_temp1_W); + uop_MOVZX(ir, IREG_flags_op1, IREG_temp0_W); + uop_MOV(ir, IREG_flags_op2, IREG_temp2); + uop_MOV_IMM(ir, IREG_flags_op, FLAGS_SAR16); + uop_MOVZX(ir, IREG_flags_res, IREG_temp1_W); + break; + + default: + return 0; + } + } + + codegen_flags_changed = 1; + return op_pc + 1; +} +uint32_t +ropD3_l(codeblock_t *block, ir_data_t *ir, UNUSED(uint8_t opcode), uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) +{ + if ((fetchdat & 0x30) == 0x10) /*RCL/RCR*/ + return 0; + + if (!(CL & 0x1f) || !block->ins) + return 0; + + uop_AND_IMM(ir, IREG_temp2, REG_ECX, 0x1f); + uop_CMP_IMM_JZ(ir, IREG_temp2, 0, codegen_exit_rout); + + codegen_mark_code_present(block, cs + op_pc, 1); + if ((fetchdat & 0xc0) == 0xc0) { + int dest_reg = fetchdat & 7; + + switch (fetchdat & 0x38) { + case 0x00: /*ROL*/ + uop_CALL_FUNC(ir, flags_rebuild); + uop_ROL(ir, IREG_32(dest_reg), IREG_32(dest_reg), IREG_temp2); + uop_MOV_IMM(ir, IREG_flags_op, FLAGS_ROL32); + uop_MOV(ir, IREG_flags_res, IREG_32(dest_reg)); + break; + + case 0x08: /*ROR*/ + uop_CALL_FUNC(ir, flags_rebuild); + uop_ROR(ir, IREG_32(dest_reg), IREG_32(dest_reg), IREG_temp2); + uop_MOV_IMM(ir, IREG_flags_op, FLAGS_ROR32); + uop_MOV(ir, IREG_flags_res, IREG_32(dest_reg)); + break; + + case 0x20: + case 0x30: /*SHL*/ + uop_MOV(ir, IREG_flags_op1, IREG_32(dest_reg)); + uop_SHL(ir, IREG_32(dest_reg), IREG_32(dest_reg), IREG_temp2); + uop_MOV(ir, IREG_flags_op2, IREG_temp2); + uop_MOV_IMM(ir, IREG_flags_op, FLAGS_SHL32); + uop_MOV(ir, IREG_flags_res, IREG_32(dest_reg)); + break; + + case 0x28: /*SHR*/ + uop_MOV(ir, IREG_flags_op1, IREG_32(dest_reg)); + uop_SHR(ir, IREG_32(dest_reg), IREG_32(dest_reg), IREG_temp2); + uop_MOV(ir, IREG_flags_op2, IREG_temp2); + uop_MOV_IMM(ir, IREG_flags_op, FLAGS_SHR32); + uop_MOV(ir, IREG_flags_res, IREG_32(dest_reg)); + break; + + case 0x38: /*SAR*/ + uop_MOV(ir, IREG_flags_op1, IREG_32(dest_reg)); + uop_SAR(ir, IREG_32(dest_reg), IREG_32(dest_reg), IREG_temp2); + uop_MOV(ir, IREG_flags_op2, IREG_temp2); + uop_MOV_IMM(ir, IREG_flags_op, FLAGS_SAR32); + uop_MOV(ir, IREG_flags_res, IREG_32(dest_reg)); + break; + + default: + return 0; + } + } else { + x86seg *target_seg; + + uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc); + target_seg = codegen_generate_ea(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32, 0); + codegen_check_seg_write(block, ir, target_seg); + uop_MEM_LOAD_REG(ir, IREG_temp0, ireg_seg_base(target_seg), IREG_eaaddr); + + switch (fetchdat & 0x38) { + case 0x00: /*ROL*/ + uop_CALL_FUNC(ir, flags_rebuild); + uop_ROL(ir, IREG_temp0, IREG_temp0, IREG_temp2); + uop_MEM_STORE_REG(ir, ireg_seg_base(target_seg), IREG_eaaddr, IREG_temp0); + uop_MOV_IMM(ir, IREG_flags_op, FLAGS_ROL32); + uop_MOV(ir, IREG_flags_res, IREG_temp0); + break; + + case 0x08: /*ROR*/ + uop_CALL_FUNC(ir, flags_rebuild); + uop_ROR(ir, IREG_temp0, IREG_temp0, IREG_temp2); + uop_MEM_STORE_REG(ir, ireg_seg_base(target_seg), IREG_eaaddr, IREG_temp0); + uop_MOV_IMM(ir, IREG_flags_op, FLAGS_ROR32); + uop_MOV(ir, IREG_flags_res, IREG_temp0); + break; + + case 0x20: + case 0x30: /*SHL*/ + uop_SHL(ir, IREG_temp1, IREG_temp0, IREG_temp2); + uop_MEM_STORE_REG(ir, ireg_seg_base(target_seg), IREG_eaaddr, IREG_temp1); + uop_MOV(ir, IREG_flags_op1, IREG_temp0); + uop_MOV(ir, IREG_flags_op2, IREG_temp2); + uop_MOV_IMM(ir, IREG_flags_op, FLAGS_SHL32); + uop_MOV(ir, IREG_flags_res, IREG_temp1); + break; + + case 0x28: /*SHR*/ + uop_SHR(ir, IREG_temp1, IREG_temp0, IREG_temp2); + uop_MEM_STORE_REG(ir, ireg_seg_base(target_seg), IREG_eaaddr, IREG_temp1); + uop_MOV(ir, IREG_flags_op1, IREG_temp0); + uop_MOV(ir, IREG_flags_op2, IREG_temp2); + uop_MOV_IMM(ir, IREG_flags_op, FLAGS_SHR32); + uop_MOV(ir, IREG_flags_res, IREG_temp1); + break; + + case 0x38: /*SAR*/ + uop_SAR(ir, IREG_temp1, IREG_temp0, IREG_temp2); + uop_MEM_STORE_REG(ir, ireg_seg_base(target_seg), IREG_eaaddr, IREG_temp1); + uop_MOV(ir, IREG_flags_op1, IREG_temp0); + uop_MOV(ir, IREG_flags_op2, IREG_temp2); + uop_MOV_IMM(ir, IREG_flags_op, FLAGS_SAR32); + uop_MOV(ir, IREG_flags_res, IREG_temp1); + break; + + default: + return 0; + } + } + + codegen_flags_changed = 1; + return op_pc + 1; +} + +uint32_t +ropSHLD_16_imm(codeblock_t *block, ir_data_t *ir, UNUSED(uint8_t opcode), uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) +{ + x86seg *target_seg = NULL; + int src_reg = (fetchdat >> 3) & 7; + uint8_t imm; + + codegen_mark_code_present(block, cs + op_pc, 1); + if ((fetchdat & 0xc0) != 0xc0) { + uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc); + target_seg = codegen_generate_ea(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32, 0); + } + imm = fastreadb(cs + op_pc + 1) & 0x1f; + codegen_mark_code_present(block, cs + op_pc + 1, 1); + + if (!imm) + return op_pc + 2; + + if ((fetchdat & 0xc0) == 0xc0) { + int dest_reg = fetchdat & 7; + + uop_MOVZX(ir, IREG_flags_op1, IREG_16(dest_reg)); + uop_SHL_IMM(ir, IREG_temp0_W, IREG_16(dest_reg), imm); + uop_SHR_IMM(ir, IREG_temp1_W, IREG_16(src_reg), 16 - imm); + uop_OR(ir, IREG_16(dest_reg), IREG_temp0_W, IREG_temp1_W); + uop_MOV_IMM(ir, IREG_flags_op2, imm); + uop_MOV_IMM(ir, IREG_flags_op, FLAGS_SHL16); + uop_MOVZX(ir, IREG_flags_res, IREG_16(dest_reg)); + } else { + codegen_check_seg_write(block, ir, target_seg); + uop_MEM_LOAD_REG(ir, IREG_temp2_W, ireg_seg_base(target_seg), IREG_eaaddr); + + uop_SHL_IMM(ir, IREG_temp0_W, IREG_temp2, imm); + uop_SHR_IMM(ir, IREG_temp1_W, IREG_16(src_reg), 16 - imm); + uop_OR(ir, IREG_temp0_W, IREG_temp0_W, IREG_temp1_W); + uop_MEM_STORE_REG(ir, ireg_seg_base(target_seg), IREG_eaaddr, IREG_temp0_W); + + uop_MOVZX(ir, IREG_flags_op1, IREG_temp2_W); + uop_MOVZX(ir, IREG_flags_res, IREG_temp0_W); + uop_MOV_IMM(ir, IREG_flags_op2, imm); + uop_MOV_IMM(ir, IREG_flags_op, FLAGS_SHL16); + } + + return op_pc + 2; +} +uint32_t +ropSHLD_32_imm(codeblock_t *block, ir_data_t *ir, UNUSED(uint8_t opcode), uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) +{ + x86seg *target_seg = NULL; + int src_reg = (fetchdat >> 3) & 7; + uint8_t imm; + + codegen_mark_code_present(block, cs + op_pc, 1); + if ((fetchdat & 0xc0) != 0xc0) { + uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc); + target_seg = codegen_generate_ea(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32, 0); + } + imm = fastreadb(cs + op_pc + 1) & 0x1f; + codegen_mark_code_present(block, cs + op_pc + 1, 1); + + if (!imm) + return op_pc + 2; + + if ((fetchdat & 0xc0) == 0xc0) { + int dest_reg = fetchdat & 7; + + uop_MOV(ir, IREG_flags_op1, IREG_32(dest_reg)); + uop_SHL_IMM(ir, IREG_temp0, IREG_32(dest_reg), imm); + uop_SHR_IMM(ir, IREG_temp1, IREG_32(src_reg), 32 - imm); + uop_OR(ir, IREG_32(dest_reg), IREG_temp0, IREG_temp1); + uop_MOV_IMM(ir, IREG_flags_op2, imm); + uop_MOV_IMM(ir, IREG_flags_op, FLAGS_SHL32); + uop_MOV(ir, IREG_flags_res, IREG_32(dest_reg)); + } else { + codegen_check_seg_write(block, ir, target_seg); + uop_MEM_LOAD_REG(ir, IREG_temp2, ireg_seg_base(target_seg), IREG_eaaddr); + + uop_SHL_IMM(ir, IREG_temp0, IREG_temp2, imm); + uop_SHR_IMM(ir, IREG_temp1, IREG_32(src_reg), 32 - imm); + uop_OR(ir, IREG_temp0, IREG_temp0, IREG_temp1); + uop_MEM_STORE_REG(ir, ireg_seg_base(target_seg), IREG_eaaddr, IREG_temp0); + + uop_MOV(ir, IREG_flags_op1, IREG_temp2); + uop_MOV(ir, IREG_flags_res, IREG_temp0); + uop_MOV_IMM(ir, IREG_flags_op2, imm); + uop_MOV_IMM(ir, IREG_flags_op, FLAGS_SHL32); + } + + return op_pc + 2; +} +uint32_t +ropSHRD_16_imm(codeblock_t *block, ir_data_t *ir, UNUSED(uint8_t opcode), uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) +{ + x86seg *target_seg = NULL; + int src_reg = (fetchdat >> 3) & 7; + uint8_t imm; + + codegen_mark_code_present(block, cs + op_pc, 1); + if ((fetchdat & 0xc0) != 0xc0) { + uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc); + target_seg = codegen_generate_ea(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32, 0); + } + imm = fastreadb(cs + op_pc + 1) & 0x1f; + codegen_mark_code_present(block, cs + op_pc + 1, 1); + + if (!imm) + return op_pc + 2; + + if ((fetchdat & 0xc0) == 0xc0) { + int dest_reg = fetchdat & 7; + + uop_MOVZX(ir, IREG_flags_op1, IREG_16(dest_reg)); + uop_SHR_IMM(ir, IREG_temp0_W, IREG_16(dest_reg), imm); + uop_SHL_IMM(ir, IREG_temp1_W, IREG_16(src_reg), 16 - imm); + uop_OR(ir, IREG_16(dest_reg), IREG_temp0_W, IREG_temp1_W); + uop_MOV_IMM(ir, IREG_flags_op2, imm); + uop_MOV_IMM(ir, IREG_flags_op, FLAGS_SHR16); + uop_MOVZX(ir, IREG_flags_res, IREG_16(dest_reg)); + } else { + codegen_check_seg_write(block, ir, target_seg); + uop_MEM_LOAD_REG(ir, IREG_temp2_W, ireg_seg_base(target_seg), IREG_eaaddr); + + uop_SHR_IMM(ir, IREG_temp0_W, IREG_temp2, imm); + uop_SHL_IMM(ir, IREG_temp1_W, IREG_16(src_reg), 16 - imm); + uop_OR(ir, IREG_temp0_W, IREG_temp0_W, IREG_temp1_W); + uop_MEM_STORE_REG(ir, ireg_seg_base(target_seg), IREG_eaaddr, IREG_temp0_W); + + uop_MOVZX(ir, IREG_flags_op1, IREG_temp2_W); + uop_MOVZX(ir, IREG_flags_res, IREG_temp0_W); + uop_MOV_IMM(ir, IREG_flags_op2, imm); + uop_MOV_IMM(ir, IREG_flags_op, FLAGS_SHR16); + } + + return op_pc + 2; +} +uint32_t +ropSHRD_32_imm(codeblock_t *block, ir_data_t *ir, UNUSED(uint8_t opcode), uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) +{ + x86seg *target_seg = NULL; + int src_reg = (fetchdat >> 3) & 7; + uint8_t imm; + + codegen_mark_code_present(block, cs + op_pc, 1); + if ((fetchdat & 0xc0) != 0xc0) { + uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc); + target_seg = codegen_generate_ea(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32, 0); + } + imm = fastreadb(cs + op_pc + 1) & 0x1f; + codegen_mark_code_present(block, cs + op_pc + 1, 1); + + if (!imm) + return op_pc + 2; + + if ((fetchdat & 0xc0) == 0xc0) { + int dest_reg = fetchdat & 7; + + uop_MOV(ir, IREG_flags_op1, IREG_32(dest_reg)); + uop_SHR_IMM(ir, IREG_temp0, IREG_32(dest_reg), imm); + uop_SHL_IMM(ir, IREG_temp1, IREG_32(src_reg), 32 - imm); + uop_OR(ir, IREG_32(dest_reg), IREG_temp0, IREG_temp1); + uop_MOV_IMM(ir, IREG_flags_op2, imm); + uop_MOV_IMM(ir, IREG_flags_op, FLAGS_SHR32); + uop_MOV(ir, IREG_flags_res, IREG_32(dest_reg)); + } else { + codegen_check_seg_write(block, ir, target_seg); + uop_MEM_LOAD_REG(ir, IREG_temp2, ireg_seg_base(target_seg), IREG_eaaddr); + + uop_SHR_IMM(ir, IREG_temp0, IREG_temp2, imm); + uop_SHL_IMM(ir, IREG_temp1, IREG_32(src_reg), 32 - imm); + uop_OR(ir, IREG_temp0, IREG_temp0, IREG_temp1); + uop_MEM_STORE_REG(ir, ireg_seg_base(target_seg), IREG_eaaddr, IREG_temp0); + + uop_MOV(ir, IREG_flags_op1, IREG_temp2); + uop_MOV(ir, IREG_flags_res, IREG_temp0); + uop_MOV_IMM(ir, IREG_flags_op2, imm); + uop_MOV_IMM(ir, IREG_flags_op, FLAGS_SHR32); + } + + return op_pc + 2; } diff --git a/src/codegen_new/codegen_ops_stack.c b/src/codegen_new/codegen_ops_stack.c index 1bb791a3b..92ad9509d 100644 --- a/src/codegen_new/codegen_ops_stack.c +++ b/src/codegen_new/codegen_ops_stack.c @@ -2,8 +2,11 @@ #include <86box/86box.h> #include "cpu.h" #include <86box/mem.h> +#include <86box/plat_unused.h> #include "x86.h" +#include "x86seg_common.h" +#include "x86seg.h" #include "x86_flags.h" #include "386_common.h" #include "codegen.h" @@ -12,248 +15,243 @@ #include "codegen_ops_helpers.h" #include "codegen_ops_misc.h" -uint32_t ropPUSH_r16(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) +uint32_t +ropPUSH_r16(UNUSED(codeblock_t *block), ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, UNUSED(uint32_t op_32), uint32_t op_pc) { - int sp_reg; + int sp_reg; - uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc); - sp_reg = LOAD_SP_WITH_OFFSET(ir, -2); - uop_MEM_STORE_REG(ir, IREG_SS_base, sp_reg, IREG_16(opcode & 7)); - SUB_SP(ir, 2); + uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc); + sp_reg = LOAD_SP_WITH_OFFSET(ir, -2); + uop_MEM_STORE_REG(ir, IREG_SS_base, sp_reg, IREG_16(opcode & 7)); + SUB_SP(ir, 2); - return op_pc; + return op_pc; } -uint32_t ropPUSH_r32(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) +uint32_t +ropPUSH_r32(UNUSED(codeblock_t *block), ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, UNUSED(uint32_t op_32), uint32_t op_pc) { - int sp_reg; + int sp_reg; - uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc); - sp_reg = LOAD_SP_WITH_OFFSET(ir, -4); - uop_MEM_STORE_REG(ir, IREG_SS_base, sp_reg, IREG_32(opcode & 7)); - SUB_SP(ir, 4); + uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc); + sp_reg = LOAD_SP_WITH_OFFSET(ir, -4); + uop_MEM_STORE_REG(ir, IREG_SS_base, sp_reg, IREG_32(opcode & 7)); + SUB_SP(ir, 4); - return op_pc; + return op_pc; } -uint32_t ropPOP_r16(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) +uint32_t +ropPOP_r16(UNUSED(codeblock_t *block), ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, UNUSED(uint32_t op_32), uint32_t op_pc) { - uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc); + uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc); + + if (stack32) + uop_MEM_LOAD_REG(ir, IREG_16(opcode & 7), IREG_SS_base, IREG_ESP); + else { + uop_MOVZX(ir, IREG_eaaddr, IREG_SP); + uop_MEM_LOAD_REG(ir, IREG_16(opcode & 7), IREG_SS_base, IREG_eaaddr); + } + if ((opcode & 7) != REG_SP) + ADD_SP(ir, 2); + + return op_pc; +} +uint32_t +ropPOP_r32(UNUSED(codeblock_t *block), ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, UNUSED(uint32_t op_32), uint32_t op_pc) +{ + uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc); + + if (stack32) + uop_MEM_LOAD_REG(ir, IREG_32(opcode & 7), IREG_SS_base, IREG_ESP); + else { + uop_MOVZX(ir, IREG_eaaddr, IREG_SP); + uop_MEM_LOAD_REG(ir, IREG_32(opcode & 7), IREG_SS_base, IREG_eaaddr); + } + if ((opcode & 7) != REG_ESP) + ADD_SP(ir, 4); + + return op_pc; +} + +uint32_t +ropPUSH_imm_16(codeblock_t *block, ir_data_t *ir, UNUSED(uint8_t opcode), uint32_t fetchdat, UNUSED(uint32_t op_32), uint32_t op_pc) +{ + uint16_t imm = fastreadw(cs + op_pc); + int sp_reg; + + uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc); + sp_reg = LOAD_SP_WITH_OFFSET(ir, -2); + uop_MEM_STORE_IMM_16(ir, IREG_SS_base, sp_reg, imm); + SUB_SP(ir, 2); + + codegen_mark_code_present(block, cs + op_pc, 2); + return op_pc + 2; +} +uint32_t +ropPUSH_imm_32(codeblock_t *block, ir_data_t *ir, UNUSED(uint8_t opcode), uint32_t fetchdat, UNUSED(uint32_t op_32), uint32_t op_pc) +{ + uint32_t imm = fastreadl(cs + op_pc); + int sp_reg; + + uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc); + sp_reg = LOAD_SP_WITH_OFFSET(ir, -4); + uop_MEM_STORE_IMM_32(ir, IREG_SS_base, sp_reg, imm); + SUB_SP(ir, 4); + + codegen_mark_code_present(block, cs + op_pc, 4); + return op_pc + 4; +} + +uint32_t +ropPUSH_imm_16_8(codeblock_t *block, ir_data_t *ir, UNUSED(uint8_t opcode), uint32_t fetchdat, UNUSED(uint32_t op_32), uint32_t op_pc) +{ + uint16_t imm = (int16_t) (int8_t) fastreadb(cs + op_pc); + int sp_reg; + + uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc); + sp_reg = LOAD_SP_WITH_OFFSET(ir, -2); + uop_MEM_STORE_IMM_16(ir, IREG_SS_base, sp_reg, imm); + SUB_SP(ir, 2); + + codegen_mark_code_present(block, cs + op_pc, 1); + return op_pc + 1; +} +uint32_t +ropPUSH_imm_32_8(codeblock_t *block, ir_data_t *ir, UNUSED(uint8_t opcode), uint32_t fetchdat, UNUSED(uint32_t op_32), uint32_t op_pc) +{ + uint32_t imm = (int32_t) (int8_t) fastreadb(cs + op_pc); + int sp_reg; + + uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc); + sp_reg = LOAD_SP_WITH_OFFSET(ir, -4); + uop_MEM_STORE_IMM_32(ir, IREG_SS_base, sp_reg, imm); + SUB_SP(ir, 4); + + codegen_mark_code_present(block, cs + op_pc, 1); + return op_pc + 1; +} + +uint32_t +ropPOP_W(codeblock_t *block, ir_data_t *ir, UNUSED(uint8_t opcode), uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) +{ + uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc); + + codegen_mark_code_present(block, cs + op_pc, 1); + if ((fetchdat & 0xc0) == 0xc0) { + if (stack32) + uop_MEM_LOAD_REG(ir, IREG_16(fetchdat & 7), IREG_SS_base, IREG_ESP); + else { + uop_MOVZX(ir, IREG_eaaddr, IREG_SP); + uop_MEM_LOAD_REG(ir, IREG_16(fetchdat & 7), IREG_SS_base, IREG_eaaddr); + } + } else { + x86seg *target_seg = codegen_generate_ea(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32, 2); + codegen_check_seg_write(block, ir, target_seg); if (stack32) - uop_MEM_LOAD_REG(ir, IREG_16(opcode & 7), IREG_SS_base, IREG_ESP); - else - { - uop_MOVZX(ir, IREG_eaaddr, IREG_SP); - uop_MEM_LOAD_REG(ir, IREG_16(opcode & 7), IREG_SS_base, IREG_eaaddr); + uop_MEM_LOAD_REG(ir, IREG_temp0_W, IREG_SS_base, IREG_ESP); + else { + uop_MOVZX(ir, IREG_temp0, IREG_SP); + uop_MEM_LOAD_REG(ir, IREG_temp0_W, IREG_SS_base, IREG_temp0); } - if ((opcode & 7) != REG_SP) - ADD_SP(ir, 2); - return op_pc; + uop_MEM_STORE_REG(ir, ireg_seg_base(target_seg), IREG_eaaddr, IREG_temp0_W); + } + + if ((fetchdat & 0xc7) != (0xc0 | REG_SP)) + ADD_SP(ir, 2); + + return op_pc + 1; } -uint32_t ropPOP_r32(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) +uint32_t +ropPOP_L(codeblock_t *block, ir_data_t *ir, UNUSED(uint8_t opcode), uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) { - uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc); + uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc); + + codegen_mark_code_present(block, cs + op_pc, 1); + if ((fetchdat & 0xc0) == 0xc0) { + if (stack32) + uop_MEM_LOAD_REG(ir, IREG_32(fetchdat & 7), IREG_SS_base, IREG_ESP); + else { + uop_MOVZX(ir, IREG_eaaddr, IREG_SP); + uop_MEM_LOAD_REG(ir, IREG_32(fetchdat & 7), IREG_SS_base, IREG_eaaddr); + } + } else { + x86seg *target_seg = codegen_generate_ea(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32, 4); + codegen_check_seg_write(block, ir, target_seg); if (stack32) - uop_MEM_LOAD_REG(ir, IREG_32(opcode & 7), IREG_SS_base, IREG_ESP); - else - { - uop_MOVZX(ir, IREG_eaaddr, IREG_SP); - uop_MEM_LOAD_REG(ir, IREG_32(opcode & 7), IREG_SS_base, IREG_eaaddr); - } - if ((opcode & 7) != REG_ESP) - ADD_SP(ir, 4); - - return op_pc; -} - -uint32_t ropPUSH_imm_16(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) -{ - uint16_t imm = fastreadw(cs + op_pc); - int sp_reg; - - uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc); - sp_reg = LOAD_SP_WITH_OFFSET(ir, -2); - uop_MEM_STORE_IMM_16(ir, IREG_SS_base, sp_reg, imm); - SUB_SP(ir, 2); - - codegen_mark_code_present(block, cs+op_pc, 2); - return op_pc + 2; -} -uint32_t ropPUSH_imm_32(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) -{ - uint32_t imm = fastreadl(cs + op_pc); - int sp_reg; - - uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc); - sp_reg = LOAD_SP_WITH_OFFSET(ir, -4); - uop_MEM_STORE_IMM_32(ir, IREG_SS_base, sp_reg, imm); - SUB_SP(ir, 4); - - codegen_mark_code_present(block, cs+op_pc, 4); - return op_pc + 4; -} - -uint32_t ropPUSH_imm_16_8(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) -{ - uint16_t imm = (int16_t)(int8_t)fastreadb(cs + op_pc); - int sp_reg; - - uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc); - sp_reg = LOAD_SP_WITH_OFFSET(ir, -2); - uop_MEM_STORE_IMM_16(ir, IREG_SS_base, sp_reg, imm); - SUB_SP(ir, 2); - - codegen_mark_code_present(block, cs+op_pc, 1); - return op_pc + 1; -} -uint32_t ropPUSH_imm_32_8(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) -{ - uint32_t imm = (int32_t)(int8_t)fastreadb(cs + op_pc); - int sp_reg; - - uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc); - sp_reg = LOAD_SP_WITH_OFFSET(ir, -4); - uop_MEM_STORE_IMM_32(ir, IREG_SS_base, sp_reg, imm); - SUB_SP(ir, 4); - - codegen_mark_code_present(block, cs+op_pc, 1); - return op_pc + 1; -} - -uint32_t ropPOP_W(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) -{ - uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc); - - codegen_mark_code_present(block, cs+op_pc, 1); - if ((fetchdat & 0xc0) == 0xc0) - { - if (stack32) - uop_MEM_LOAD_REG(ir, IREG_16(fetchdat & 7), IREG_SS_base, IREG_ESP); - else - { - uop_MOVZX(ir, IREG_eaaddr, IREG_SP); - uop_MEM_LOAD_REG(ir, IREG_16(fetchdat & 7), IREG_SS_base, IREG_eaaddr); - } - } - else - { - x86seg *target_seg = codegen_generate_ea(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32, 2); - codegen_check_seg_write(block, ir, target_seg); - - if (stack32) - uop_MEM_LOAD_REG(ir, IREG_temp0_W, IREG_SS_base, IREG_ESP); - else - { - uop_MOVZX(ir, IREG_temp0, IREG_SP); - uop_MEM_LOAD_REG(ir, IREG_temp0_W, IREG_SS_base, IREG_temp0); - } - - uop_MEM_STORE_REG(ir, ireg_seg_base(target_seg), IREG_eaaddr, IREG_temp0_W); + uop_MEM_LOAD_REG(ir, IREG_temp0, IREG_SS_base, IREG_ESP); + else { + uop_MOVZX(ir, IREG_temp0, IREG_SP); + uop_MEM_LOAD_REG(ir, IREG_temp0, IREG_SS_base, IREG_temp0); } - if ((fetchdat & 0xc7) != (0xc0 | REG_SP)) - ADD_SP(ir, 2); + uop_MEM_STORE_REG(ir, ireg_seg_base(target_seg), IREG_eaaddr, IREG_temp0); + } - return op_pc + 1; -} -uint32_t ropPOP_L(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) -{ - uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc); + if ((fetchdat & 0xc7) != (0xc0 | REG_ESP)) + ADD_SP(ir, 4); - codegen_mark_code_present(block, cs+op_pc, 1); - if ((fetchdat & 0xc0) == 0xc0) - { - if (stack32) - uop_MEM_LOAD_REG(ir, IREG_32(fetchdat & 7), IREG_SS_base, IREG_ESP); - else - { - uop_MOVZX(ir, IREG_eaaddr, IREG_SP); - uop_MEM_LOAD_REG(ir, IREG_32(fetchdat & 7), IREG_SS_base, IREG_eaaddr); - } - } - else - { - x86seg *target_seg = codegen_generate_ea(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32, 4); - codegen_check_seg_write(block, ir, target_seg); - - if (stack32) - uop_MEM_LOAD_REG(ir, IREG_temp0, IREG_SS_base, IREG_ESP); - else - { - uop_MOVZX(ir, IREG_temp0, IREG_SP); - uop_MEM_LOAD_REG(ir, IREG_temp0, IREG_SS_base, IREG_temp0); - } - - uop_MEM_STORE_REG(ir, ireg_seg_base(target_seg), IREG_eaaddr, IREG_temp0); - } - - if ((fetchdat & 0xc7) != (0xc0 | REG_ESP)) - ADD_SP(ir, 4); - - return op_pc + 1; + return op_pc + 1; } -#define ROP_PUSH_SEG(seg) \ -uint32_t ropPUSH_ ## seg ## _16(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) \ -{ \ - int sp_reg; \ - \ - uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc); \ - sp_reg = LOAD_SP_WITH_OFFSET(ir, -2); \ - uop_MEM_STORE_REG(ir, IREG_SS_base, sp_reg, IREG_ ## seg ## _seg_W); \ - SUB_SP(ir, 2); \ - \ - return op_pc; \ -} \ -uint32_t ropPUSH_ ## seg ## _32(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) \ -{ \ - int sp_reg; \ - \ - uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc); \ - sp_reg = LOAD_SP_WITH_OFFSET(ir, -4); \ - uop_MOVZX(ir, IREG_temp0, IREG_ ## seg ## _seg_W); \ - uop_MEM_STORE_REG(ir, IREG_SS_base, sp_reg, IREG_temp0); \ - SUB_SP(ir, 4); \ - \ - return op_pc; \ -} - -#define ROP_POP_SEG(seg, rseg) \ -uint32_t ropPOP_ ## seg ## _16(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) \ -{ \ - uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc); \ - \ - if (stack32) \ - uop_MEM_LOAD_REG(ir, IREG_temp0_W, IREG_SS_base, IREG_ESP); \ - else \ - { \ - uop_MOVZX(ir, IREG_eaaddr, IREG_SP); \ - uop_MEM_LOAD_REG(ir, IREG_temp0_W, IREG_SS_base, IREG_eaaddr); \ - } \ - uop_LOAD_SEG(ir, &rseg, IREG_temp0_W); \ - ADD_SP(ir, 2); \ - \ - return op_pc; \ -} \ -uint32_t ropPOP_ ## seg ## _32(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) \ -{ \ - uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc); \ - \ - if (stack32) \ - uop_MEM_LOAD_REG(ir, IREG_temp0_W, IREG_SS_base, IREG_ESP); \ - else \ - { \ - uop_MOVZX(ir, IREG_eaaddr, IREG_SP); \ - uop_MEM_LOAD_REG(ir, IREG_temp0_W, IREG_SS_base, IREG_eaaddr); \ - } \ - uop_LOAD_SEG(ir, &rseg, IREG_temp0_W); \ - ADD_SP(ir, 4); \ - \ - return op_pc; \ -} +#define ROP_PUSH_SEG(seg) \ + uint32_t ropPUSH_##seg##_16(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) \ + { \ + int sp_reg; \ + \ + uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc); \ + sp_reg = LOAD_SP_WITH_OFFSET(ir, -2); \ + uop_MEM_STORE_REG(ir, IREG_SS_base, sp_reg, IREG_##seg##_seg_W); \ + SUB_SP(ir, 2); \ + \ + return op_pc; \ + } \ + uint32_t ropPUSH_##seg##_32(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) \ + { \ + int sp_reg; \ + \ + uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc); \ + sp_reg = LOAD_SP_WITH_OFFSET(ir, -4); \ + uop_MOVZX(ir, IREG_temp0, IREG_##seg##_seg_W); \ + uop_MEM_STORE_REG(ir, IREG_SS_base, sp_reg, IREG_temp0); \ + SUB_SP(ir, 4); \ + \ + return op_pc; \ + } +#define ROP_POP_SEG(seg, rseg) \ + uint32_t ropPOP_##seg##_16(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) \ + { \ + uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc); \ + \ + if (stack32) \ + uop_MEM_LOAD_REG(ir, IREG_temp0_W, IREG_SS_base, IREG_ESP); \ + else { \ + uop_MOVZX(ir, IREG_eaaddr, IREG_SP); \ + uop_MEM_LOAD_REG(ir, IREG_temp0_W, IREG_SS_base, IREG_eaaddr); \ + } \ + uop_LOAD_SEG(ir, &rseg, IREG_temp0_W); \ + ADD_SP(ir, 2); \ + \ + return op_pc; \ + } \ + uint32_t ropPOP_##seg##_32(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) \ + { \ + uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc); \ + \ + if (stack32) \ + uop_MEM_LOAD_REG(ir, IREG_temp0_W, IREG_SS_base, IREG_ESP); \ + else { \ + uop_MOVZX(ir, IREG_eaaddr, IREG_SP); \ + uop_MEM_LOAD_REG(ir, IREG_temp0_W, IREG_SS_base, IREG_eaaddr); \ + } \ + uop_LOAD_SEG(ir, &rseg, IREG_temp0_W); \ + ADD_SP(ir, 4); \ + \ + return op_pc; \ + } ROP_PUSH_SEG(CS) ROP_PUSH_SEG(DS) @@ -266,147 +264,152 @@ ROP_POP_SEG(ES, cpu_state.seg_es) ROP_POP_SEG(FS, cpu_state.seg_fs) ROP_POP_SEG(GS, cpu_state.seg_gs) -uint32_t ropLEAVE_16(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) +uint32_t +ropLEAVE_16(UNUSED(codeblock_t *block), ir_data_t *ir, UNUSED(uint8_t opcode), uint32_t fetchdat, UNUSED(uint32_t op_32), uint32_t op_pc) { - uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc); + uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc); - if (stack32) - uop_MEM_LOAD_REG(ir, IREG_temp0_W, IREG_SS_base, IREG_EBP); - else - { - uop_MOVZX(ir, IREG_eaaddr, IREG_BP); - uop_MEM_LOAD_REG(ir, IREG_temp0_W, IREG_SS_base, IREG_eaaddr); - } - uop_ADD_IMM(ir, IREG_SP, IREG_BP, 2); - uop_MOV(ir, IREG_BP, IREG_temp0_W); + if (stack32) + uop_MEM_LOAD_REG(ir, IREG_temp0_W, IREG_SS_base, IREG_EBP); + else { + uop_MOVZX(ir, IREG_eaaddr, IREG_BP); + uop_MEM_LOAD_REG(ir, IREG_temp0_W, IREG_SS_base, IREG_eaaddr); + } + uop_ADD_IMM(ir, IREG_SP, IREG_BP, 2); + uop_MOV(ir, IREG_BP, IREG_temp0_W); - return op_pc; + return op_pc; } -uint32_t ropLEAVE_32(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) +uint32_t +ropLEAVE_32(UNUSED(codeblock_t *block), ir_data_t *ir, UNUSED(uint8_t opcode), uint32_t fetchdat, UNUSED(uint32_t op_32), uint32_t op_pc) { - uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc); + uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc); - if (stack32) - uop_MEM_LOAD_REG(ir, IREG_temp0, IREG_SS_base, IREG_EBP); - else - { - uop_MOVZX(ir, IREG_eaaddr, IREG_BP); - uop_MEM_LOAD_REG(ir, IREG_temp0, IREG_SS_base, IREG_eaaddr); - } - uop_ADD_IMM(ir, IREG_ESP, IREG_EBP, 4); - uop_MOV(ir, IREG_EBP, IREG_temp0); + if (stack32) + uop_MEM_LOAD_REG(ir, IREG_temp0, IREG_SS_base, IREG_EBP); + else { + uop_MOVZX(ir, IREG_eaaddr, IREG_BP); + uop_MEM_LOAD_REG(ir, IREG_temp0, IREG_SS_base, IREG_eaaddr); + } + uop_ADD_IMM(ir, IREG_ESP, IREG_EBP, 4); + uop_MOV(ir, IREG_EBP, IREG_temp0); - return op_pc; + return op_pc; } - -uint32_t ropPUSHA_16(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) +uint32_t +ropPUSHA_16(UNUSED(codeblock_t *block), ir_data_t *ir, UNUSED(uint8_t opcode), uint32_t fetchdat, UNUSED(uint32_t op_32), uint32_t op_pc) { - int sp_reg; + int sp_reg; - uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc); - sp_reg = LOAD_SP_WITH_OFFSET(ir, -16); - uop_MEM_STORE_REG_OFFSET(ir, IREG_SS_base, sp_reg, 14, IREG_AX); - uop_MEM_STORE_REG_OFFSET(ir, IREG_SS_base, sp_reg, 12, IREG_CX); - uop_MEM_STORE_REG_OFFSET(ir, IREG_SS_base, sp_reg, 10, IREG_DX); - uop_MEM_STORE_REG_OFFSET(ir, IREG_SS_base, sp_reg, 8, IREG_BX); - uop_MEM_STORE_REG_OFFSET(ir, IREG_SS_base, sp_reg, 6, IREG_SP); - uop_MEM_STORE_REG_OFFSET(ir, IREG_SS_base, sp_reg, 4, IREG_BP); - uop_MEM_STORE_REG_OFFSET(ir, IREG_SS_base, sp_reg, 2, IREG_SI); - uop_MEM_STORE_REG(ir, IREG_SS_base, sp_reg, IREG_DI); - SUB_SP(ir, 16); + uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc); + sp_reg = LOAD_SP_WITH_OFFSET(ir, -16); + uop_MEM_STORE_REG_OFFSET(ir, IREG_SS_base, sp_reg, 14, IREG_AX); + uop_MEM_STORE_REG_OFFSET(ir, IREG_SS_base, sp_reg, 12, IREG_CX); + uop_MEM_STORE_REG_OFFSET(ir, IREG_SS_base, sp_reg, 10, IREG_DX); + uop_MEM_STORE_REG_OFFSET(ir, IREG_SS_base, sp_reg, 8, IREG_BX); + uop_MEM_STORE_REG_OFFSET(ir, IREG_SS_base, sp_reg, 6, IREG_SP); + uop_MEM_STORE_REG_OFFSET(ir, IREG_SS_base, sp_reg, 4, IREG_BP); + uop_MEM_STORE_REG_OFFSET(ir, IREG_SS_base, sp_reg, 2, IREG_SI); + uop_MEM_STORE_REG(ir, IREG_SS_base, sp_reg, IREG_DI); + SUB_SP(ir, 16); - return op_pc; + return op_pc; } -uint32_t ropPUSHA_32(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) +uint32_t +ropPUSHA_32(UNUSED(codeblock_t *block), ir_data_t *ir, UNUSED(uint8_t opcode), uint32_t fetchdat, UNUSED(uint32_t op_32), uint32_t op_pc) { - int sp_reg; + int sp_reg; - uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc); - sp_reg = LOAD_SP_WITH_OFFSET(ir, -32); - uop_MEM_STORE_REG_OFFSET(ir, IREG_SS_base, sp_reg, 28, IREG_EAX); - uop_MEM_STORE_REG_OFFSET(ir, IREG_SS_base, sp_reg, 24, IREG_ECX); - uop_MEM_STORE_REG_OFFSET(ir, IREG_SS_base, sp_reg, 20, IREG_EDX); - uop_MEM_STORE_REG_OFFSET(ir, IREG_SS_base, sp_reg, 16, IREG_EBX); - uop_MEM_STORE_REG_OFFSET(ir, IREG_SS_base, sp_reg, 12, IREG_ESP); - uop_MEM_STORE_REG_OFFSET(ir, IREG_SS_base, sp_reg, 8, IREG_EBP); - uop_MEM_STORE_REG_OFFSET(ir, IREG_SS_base, sp_reg, 4, IREG_ESI); - uop_MEM_STORE_REG(ir, IREG_SS_base, sp_reg, IREG_EDI); - SUB_SP(ir, 32); + uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc); + sp_reg = LOAD_SP_WITH_OFFSET(ir, -32); + uop_MEM_STORE_REG_OFFSET(ir, IREG_SS_base, sp_reg, 28, IREG_EAX); + uop_MEM_STORE_REG_OFFSET(ir, IREG_SS_base, sp_reg, 24, IREG_ECX); + uop_MEM_STORE_REG_OFFSET(ir, IREG_SS_base, sp_reg, 20, IREG_EDX); + uop_MEM_STORE_REG_OFFSET(ir, IREG_SS_base, sp_reg, 16, IREG_EBX); + uop_MEM_STORE_REG_OFFSET(ir, IREG_SS_base, sp_reg, 12, IREG_ESP); + uop_MEM_STORE_REG_OFFSET(ir, IREG_SS_base, sp_reg, 8, IREG_EBP); + uop_MEM_STORE_REG_OFFSET(ir, IREG_SS_base, sp_reg, 4, IREG_ESI); + uop_MEM_STORE_REG(ir, IREG_SS_base, sp_reg, IREG_EDI); + SUB_SP(ir, 32); - return op_pc; + return op_pc; } -uint32_t ropPOPA_16(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) +uint32_t +ropPOPA_16(UNUSED(codeblock_t *block), ir_data_t *ir, UNUSED(uint8_t opcode), uint32_t fetchdat, UNUSED(uint32_t op_32), uint32_t op_pc) { - int sp_reg; - - uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc); - sp_reg = LOAD_SP(ir); - uop_MEM_LOAD_REG(ir, IREG_DI, IREG_SS_base, sp_reg); - uop_MEM_LOAD_REG_OFFSET(ir, IREG_SI, IREG_SS_base, sp_reg, 2); - uop_MEM_LOAD_REG_OFFSET(ir, IREG_BP, IREG_SS_base, sp_reg, 4); - uop_MEM_LOAD_REG_OFFSET(ir, IREG_BX, IREG_SS_base, sp_reg, 8); - uop_MEM_LOAD_REG_OFFSET(ir, IREG_DX, IREG_SS_base, sp_reg, 10); - uop_MEM_LOAD_REG_OFFSET(ir, IREG_CX, IREG_SS_base, sp_reg, 12); - uop_MEM_LOAD_REG_OFFSET(ir, IREG_AX, IREG_SS_base, sp_reg, 14); - ADD_SP(ir, 16); + int sp_reg; - return op_pc; + uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc); + sp_reg = LOAD_SP(ir); + uop_MEM_LOAD_REG(ir, IREG_DI, IREG_SS_base, sp_reg); + uop_MEM_LOAD_REG_OFFSET(ir, IREG_SI, IREG_SS_base, sp_reg, 2); + uop_MEM_LOAD_REG_OFFSET(ir, IREG_BP, IREG_SS_base, sp_reg, 4); + uop_MEM_LOAD_REG_OFFSET(ir, IREG_BX, IREG_SS_base, sp_reg, 8); + uop_MEM_LOAD_REG_OFFSET(ir, IREG_DX, IREG_SS_base, sp_reg, 10); + uop_MEM_LOAD_REG_OFFSET(ir, IREG_CX, IREG_SS_base, sp_reg, 12); + uop_MEM_LOAD_REG_OFFSET(ir, IREG_AX, IREG_SS_base, sp_reg, 14); + ADD_SP(ir, 16); + + return op_pc; } -uint32_t ropPOPA_32(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) +uint32_t +ropPOPA_32(UNUSED(codeblock_t *block), ir_data_t *ir, UNUSED(uint8_t opcode), uint32_t fetchdat, UNUSED(uint32_t op_32), uint32_t op_pc) { - int sp_reg; + int sp_reg; - uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc); - sp_reg = LOAD_SP(ir); - uop_MEM_LOAD_REG(ir, IREG_EDI, IREG_SS_base, sp_reg); - uop_MEM_LOAD_REG_OFFSET(ir, IREG_ESI, IREG_SS_base, sp_reg, 4); - uop_MEM_LOAD_REG_OFFSET(ir, IREG_EBP, IREG_SS_base, sp_reg, 8); - uop_MEM_LOAD_REG_OFFSET(ir, IREG_EBX, IREG_SS_base, sp_reg, 16); - uop_MEM_LOAD_REG_OFFSET(ir, IREG_EDX, IREG_SS_base, sp_reg, 20); - uop_MEM_LOAD_REG_OFFSET(ir, IREG_ECX, IREG_SS_base, sp_reg, 24); - uop_MEM_LOAD_REG_OFFSET(ir, IREG_EAX, IREG_SS_base, sp_reg, 28); - ADD_SP(ir, 32); + uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc); + sp_reg = LOAD_SP(ir); + uop_MEM_LOAD_REG(ir, IREG_EDI, IREG_SS_base, sp_reg); + uop_MEM_LOAD_REG_OFFSET(ir, IREG_ESI, IREG_SS_base, sp_reg, 4); + uop_MEM_LOAD_REG_OFFSET(ir, IREG_EBP, IREG_SS_base, sp_reg, 8); + uop_MEM_LOAD_REG_OFFSET(ir, IREG_EBX, IREG_SS_base, sp_reg, 16); + uop_MEM_LOAD_REG_OFFSET(ir, IREG_EDX, IREG_SS_base, sp_reg, 20); + uop_MEM_LOAD_REG_OFFSET(ir, IREG_ECX, IREG_SS_base, sp_reg, 24); + uop_MEM_LOAD_REG_OFFSET(ir, IREG_EAX, IREG_SS_base, sp_reg, 28); + ADD_SP(ir, 32); - return op_pc; + return op_pc; } -uint32_t ropPUSHF(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) +uint32_t +ropPUSHF(UNUSED(codeblock_t *block), ir_data_t *ir, UNUSED(uint8_t opcode), uint32_t fetchdat, UNUSED(uint32_t op_32), uint32_t op_pc) { - int sp_reg; + int sp_reg; - if ((cpu_state.eflags & VM_FLAG) && (IOPL < 3)) - return 0; + if ((cpu_state.eflags & VM_FLAG) && (IOPL < 3)) + return 0; - uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc); - uop_CALL_FUNC(ir, flags_rebuild); - sp_reg = LOAD_SP_WITH_OFFSET(ir, -2); - uop_MEM_STORE_REG(ir, IREG_SS_base, sp_reg, IREG_flags); - SUB_SP(ir, 2); + uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc); + uop_CALL_FUNC(ir, flags_rebuild); + sp_reg = LOAD_SP_WITH_OFFSET(ir, -2); + uop_MEM_STORE_REG(ir, IREG_SS_base, sp_reg, IREG_flags); + SUB_SP(ir, 2); - return op_pc; + return op_pc; } -uint32_t ropPUSHFD(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) +uint32_t +ropPUSHFD(UNUSED(codeblock_t *block), ir_data_t *ir, UNUSED(uint8_t opcode), uint32_t fetchdat, UNUSED(uint32_t op_32), uint32_t op_pc) { - int sp_reg; + int sp_reg; - if ((cpu_state.eflags & VM_FLAG) && (IOPL < 3)) - return 0; + if ((cpu_state.eflags & VM_FLAG) && (IOPL < 3)) + return 0; - uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc); - uop_CALL_FUNC(ir, flags_rebuild); + uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc); + uop_CALL_FUNC(ir, flags_rebuild); - if (cpu_CR4_mask & CR4_VME) - uop_AND_IMM(ir, IREG_temp0_W, IREG_eflags, 0x3c); - else if (CPUID) - uop_AND_IMM(ir, IREG_temp0_W, IREG_eflags, 0x24); - else - uop_AND_IMM(ir, IREG_temp0_W, IREG_eflags, 4); - sp_reg = LOAD_SP_WITH_OFFSET(ir, -4); - uop_MEM_STORE_REG(ir, IREG_SS_base, sp_reg, IREG_flags); - uop_MEM_STORE_REG_OFFSET(ir, IREG_SS_base, sp_reg, 2, IREG_temp0_W); - SUB_SP(ir, 4); + if (cpu_CR4_mask & CR4_VME) + uop_AND_IMM(ir, IREG_temp0_W, IREG_eflags, 0x3c); + else if (CPUID) + uop_AND_IMM(ir, IREG_temp0_W, IREG_eflags, 0x24); + else + uop_AND_IMM(ir, IREG_temp0_W, IREG_eflags, 4); + sp_reg = LOAD_SP_WITH_OFFSET(ir, -4); + uop_MEM_STORE_REG(ir, IREG_SS_base, sp_reg, IREG_flags); + uop_MEM_STORE_REG_OFFSET(ir, IREG_SS_base, sp_reg, 2, IREG_temp0_W); + SUB_SP(ir, 4); - return op_pc; + return op_pc; } diff --git a/src/codegen_new/codegen_reg.c b/src/codegen_new/codegen_reg.c index 04fd88ce8..a3f000826 100644 --- a/src/codegen_new/codegen_reg.c +++ b/src/codegen_new/codegen_reg.c @@ -2,922 +2,887 @@ #include <86box/86box.h> #include "cpu.h" #include <86box/mem.h> +#include <86box/plat_unused.h> #include "codegen.h" #include "codegen_backend.h" #include "codegen_ir_defs.h" #include "codegen_reg.h" -int max_version_refcount; +int max_version_refcount; uint16_t reg_dead_list = 0; -uint8_t reg_last_version[IREG_COUNT]; +uint8_t reg_last_version[IREG_COUNT]; reg_version_t reg_version[IREG_COUNT][256]; -ir_reg_t invalid_ir_reg = {IREG_INVALID}; +ir_reg_t invalid_ir_reg = { IREG_INVALID }; -ir_reg_t _host_regs[CODEGEN_HOST_REGS]; +ir_reg_t _host_regs[CODEGEN_HOST_REGS]; static uint8_t _host_reg_dirty[CODEGEN_HOST_REGS]; -ir_reg_t host_fp_regs[CODEGEN_HOST_FP_REGS]; +ir_reg_t host_fp_regs[CODEGEN_HOST_FP_REGS]; static uint8_t host_fp_reg_dirty[CODEGEN_HOST_FP_REGS]; -typedef struct host_reg_set_t -{ - ir_reg_t *regs; - uint8_t *dirty; - host_reg_def_t *reg_list; - uint16_t locked; - int nr_regs; +typedef struct host_reg_set_t { + ir_reg_t *regs; + uint8_t *dirty; + host_reg_def_t *reg_list; + uint16_t locked; + int nr_regs; } host_reg_set_t; -static host_reg_set_t host_reg_set, host_fp_reg_set; +static host_reg_set_t host_reg_set; +static host_reg_set_t host_fp_reg_set; -enum -{ - REG_BYTE, - REG_WORD, - REG_DWORD, - REG_QWORD, - REG_POINTER, - REG_DOUBLE, - REG_FPU_ST_BYTE, - REG_FPU_ST_DOUBLE, - REG_FPU_ST_QWORD +enum { + REG_BYTE, + REG_WORD, + REG_DWORD, + REG_QWORD, + REG_POINTER, + REG_DOUBLE, + REG_FPU_ST_BYTE, + REG_FPU_ST_DOUBLE, + REG_FPU_ST_QWORD }; -enum -{ - REG_INTEGER, - REG_FP +enum { + REG_INTEGER, + REG_FP }; -enum -{ - /*Register may be accessed outside of code block, and must be written - back before any control transfers*/ - REG_PERMANENT = 0, - /*Register will not be accessed outside of code block, and does not need - to be written back if there are no readers remaining*/ - REG_VOLATILE = 1 +enum { + /*Register may be accessed outside of code block, and must be written + back before any control transfers*/ + REG_PERMANENT = 0, + /*Register will not be accessed outside of code block, and does not need + to be written back if there are no readers remaining*/ + REG_VOLATILE = 1 }; struct { - int native_size; - void *p; - int type; - int is_volatile; -} ireg_data[IREG_COUNT] = -{ - [IREG_EAX] = {REG_DWORD, &EAX, REG_INTEGER, REG_PERMANENT}, - [IREG_ECX] = {REG_DWORD, &ECX, REG_INTEGER, REG_PERMANENT}, - [IREG_EDX] = {REG_DWORD, &EDX, REG_INTEGER, REG_PERMANENT}, - [IREG_EBX] = {REG_DWORD, &EBX, REG_INTEGER, REG_PERMANENT}, - [IREG_ESP] = {REG_DWORD, &ESP, REG_INTEGER, REG_PERMANENT}, - [IREG_EBP] = {REG_DWORD, &EBP, REG_INTEGER, REG_PERMANENT}, - [IREG_ESI] = {REG_DWORD, &ESI, REG_INTEGER, REG_PERMANENT}, - [IREG_EDI] = {REG_DWORD, &EDI, REG_INTEGER, REG_PERMANENT}, + int native_size; + void *p; + int type; + int is_volatile; +} ireg_data[IREG_COUNT] = { + [IREG_EAX] = {REG_DWORD, &EAX, REG_INTEGER, REG_PERMANENT}, + [IREG_ECX] = { REG_DWORD, &ECX, REG_INTEGER, REG_PERMANENT}, + [IREG_EDX] = { REG_DWORD, &EDX, REG_INTEGER, REG_PERMANENT}, + [IREG_EBX] = { REG_DWORD, &EBX, REG_INTEGER, REG_PERMANENT}, + [IREG_ESP] = { REG_DWORD, &ESP, REG_INTEGER, REG_PERMANENT}, + [IREG_EBP] = { REG_DWORD, &EBP, REG_INTEGER, REG_PERMANENT}, + [IREG_ESI] = { REG_DWORD, &ESI, REG_INTEGER, REG_PERMANENT}, + [IREG_EDI] = { REG_DWORD, &EDI, REG_INTEGER, REG_PERMANENT}, - [IREG_flags_op] = {REG_DWORD, &cpu_state.flags_op, REG_INTEGER, REG_PERMANENT}, - [IREG_flags_res] = {REG_DWORD, &cpu_state.flags_res, REG_INTEGER, REG_PERMANENT}, - [IREG_flags_op1] = {REG_DWORD, &cpu_state.flags_op1, REG_INTEGER, REG_PERMANENT}, - [IREG_flags_op2] = {REG_DWORD, &cpu_state.flags_op2, REG_INTEGER, REG_PERMANENT}, + [IREG_flags_op] = { REG_DWORD, &cpu_state.flags_op, REG_INTEGER, REG_PERMANENT}, + [IREG_flags_res] = { REG_DWORD, &cpu_state.flags_res, REG_INTEGER, REG_PERMANENT}, + [IREG_flags_op1] = { REG_DWORD, &cpu_state.flags_op1, REG_INTEGER, REG_PERMANENT}, + [IREG_flags_op2] = { REG_DWORD, &cpu_state.flags_op2, REG_INTEGER, REG_PERMANENT}, - [IREG_pc] = {REG_DWORD, &cpu_state.pc, REG_INTEGER, REG_PERMANENT}, - [IREG_oldpc] = {REG_DWORD, &cpu_state.oldpc, REG_INTEGER, REG_PERMANENT}, + [IREG_pc] = { REG_DWORD, &cpu_state.pc, REG_INTEGER, REG_PERMANENT}, + [IREG_oldpc] = { REG_DWORD, &cpu_state.oldpc, REG_INTEGER, REG_PERMANENT}, - [IREG_eaaddr] = {REG_DWORD, &cpu_state.eaaddr, REG_INTEGER, REG_PERMANENT}, - [IREG_ea_seg] = {REG_POINTER, &cpu_state.ea_seg, REG_INTEGER, REG_PERMANENT}, + [IREG_eaaddr] = { REG_DWORD, &cpu_state.eaaddr, REG_INTEGER, REG_PERMANENT}, + [IREG_ea_seg] = { REG_POINTER, &cpu_state.ea_seg, REG_INTEGER, REG_PERMANENT}, - [IREG_op32] = {REG_DWORD, &cpu_state.op32, REG_INTEGER, REG_PERMANENT}, - [IREG_ssegsx] = {REG_BYTE, &cpu_state.ssegs, REG_INTEGER, REG_PERMANENT}, - - [IREG_rm_mod_reg] = {REG_DWORD, &cpu_state.rm_data.rm_mod_reg_data, REG_INTEGER, REG_PERMANENT}, + [IREG_op32] = { REG_DWORD, &cpu_state.op32, REG_INTEGER, REG_PERMANENT}, + [IREG_ssegsx] = { REG_BYTE, &cpu_state.ssegs, REG_INTEGER, REG_PERMANENT}, + + [IREG_rm_mod_reg] = { REG_DWORD, &cpu_state.rm_data.rm_mod_reg_data, REG_INTEGER, REG_PERMANENT}, #ifdef USE_ACYCS - [IREG_acycs] = {REG_DWORD, &acycs, REG_INTEGER, REG_PERMANENT}, + [IREG_acycs] = { REG_DWORD, &acycs, REG_INTEGER, REG_PERMANENT}, #endif - [IREG_cycles] = {REG_DWORD, &cpu_state._cycles, REG_INTEGER, REG_PERMANENT}, - - [IREG_CS_base] = {REG_DWORD, &cpu_state.seg_cs.base, REG_INTEGER, REG_PERMANENT}, - [IREG_DS_base] = {REG_DWORD, &cpu_state.seg_ds.base, REG_INTEGER, REG_PERMANENT}, - [IREG_ES_base] = {REG_DWORD, &cpu_state.seg_es.base, REG_INTEGER, REG_PERMANENT}, - [IREG_FS_base] = {REG_DWORD, &cpu_state.seg_fs.base, REG_INTEGER, REG_PERMANENT}, - [IREG_GS_base] = {REG_DWORD, &cpu_state.seg_gs.base, REG_INTEGER, REG_PERMANENT}, - [IREG_SS_base] = {REG_DWORD, &cpu_state.seg_ss.base, REG_INTEGER, REG_PERMANENT}, + [IREG_cycles] = { REG_DWORD, &cpu_state._cycles, REG_INTEGER, REG_PERMANENT}, - [IREG_CS_seg] = {REG_WORD, &cpu_state.seg_cs.seg, REG_INTEGER, REG_PERMANENT}, - [IREG_DS_seg] = {REG_WORD, &cpu_state.seg_ds.seg, REG_INTEGER, REG_PERMANENT}, - [IREG_ES_seg] = {REG_WORD, &cpu_state.seg_es.seg, REG_INTEGER, REG_PERMANENT}, - [IREG_FS_seg] = {REG_WORD, &cpu_state.seg_fs.seg, REG_INTEGER, REG_PERMANENT}, - [IREG_GS_seg] = {REG_WORD, &cpu_state.seg_gs.seg, REG_INTEGER, REG_PERMANENT}, - [IREG_SS_seg] = {REG_WORD, &cpu_state.seg_ss.seg, REG_INTEGER, REG_PERMANENT}, - - [IREG_FPU_TOP] = {REG_DWORD, &cpu_state.TOP, REG_INTEGER, REG_PERMANENT}, + [IREG_CS_base] = { REG_DWORD, &cpu_state.seg_cs.base, REG_INTEGER, REG_PERMANENT}, + [IREG_DS_base] = { REG_DWORD, &cpu_state.seg_ds.base, REG_INTEGER, REG_PERMANENT}, + [IREG_ES_base] = { REG_DWORD, &cpu_state.seg_es.base, REG_INTEGER, REG_PERMANENT}, + [IREG_FS_base] = { REG_DWORD, &cpu_state.seg_fs.base, REG_INTEGER, REG_PERMANENT}, + [IREG_GS_base] = { REG_DWORD, &cpu_state.seg_gs.base, REG_INTEGER, REG_PERMANENT}, + [IREG_SS_base] = { REG_DWORD, &cpu_state.seg_ss.base, REG_INTEGER, REG_PERMANENT}, - [IREG_ST0] = {REG_FPU_ST_DOUBLE, &cpu_state.ST[0], REG_FP, REG_PERMANENT}, - [IREG_ST1] = {REG_FPU_ST_DOUBLE, &cpu_state.ST[0], REG_FP, REG_PERMANENT}, - [IREG_ST2] = {REG_FPU_ST_DOUBLE, &cpu_state.ST[0], REG_FP, REG_PERMANENT}, - [IREG_ST3] = {REG_FPU_ST_DOUBLE, &cpu_state.ST[0], REG_FP, REG_PERMANENT}, - [IREG_ST4] = {REG_FPU_ST_DOUBLE, &cpu_state.ST[0], REG_FP, REG_PERMANENT}, - [IREG_ST5] = {REG_FPU_ST_DOUBLE, &cpu_state.ST[0], REG_FP, REG_PERMANENT}, - [IREG_ST6] = {REG_FPU_ST_DOUBLE, &cpu_state.ST[0], REG_FP, REG_PERMANENT}, - [IREG_ST7] = {REG_FPU_ST_DOUBLE, &cpu_state.ST[0], REG_FP, REG_PERMANENT}, - - [IREG_tag0] = {REG_FPU_ST_BYTE, &cpu_state.tag[0], REG_INTEGER, REG_PERMANENT}, - [IREG_tag1] = {REG_FPU_ST_BYTE, &cpu_state.tag[0], REG_INTEGER, REG_PERMANENT}, - [IREG_tag2] = {REG_FPU_ST_BYTE, &cpu_state.tag[0], REG_INTEGER, REG_PERMANENT}, - [IREG_tag3] = {REG_FPU_ST_BYTE, &cpu_state.tag[0], REG_INTEGER, REG_PERMANENT}, - [IREG_tag4] = {REG_FPU_ST_BYTE, &cpu_state.tag[0], REG_INTEGER, REG_PERMANENT}, - [IREG_tag5] = {REG_FPU_ST_BYTE, &cpu_state.tag[0], REG_INTEGER, REG_PERMANENT}, - [IREG_tag6] = {REG_FPU_ST_BYTE, &cpu_state.tag[0], REG_INTEGER, REG_PERMANENT}, - [IREG_tag7] = {REG_FPU_ST_BYTE, &cpu_state.tag[0], REG_INTEGER, REG_PERMANENT}, + [IREG_CS_seg] = { REG_WORD, &cpu_state.seg_cs.seg, REG_INTEGER, REG_PERMANENT}, + [IREG_DS_seg] = { REG_WORD, &cpu_state.seg_ds.seg, REG_INTEGER, REG_PERMANENT}, + [IREG_ES_seg] = { REG_WORD, &cpu_state.seg_es.seg, REG_INTEGER, REG_PERMANENT}, + [IREG_FS_seg] = { REG_WORD, &cpu_state.seg_fs.seg, REG_INTEGER, REG_PERMANENT}, + [IREG_GS_seg] = { REG_WORD, &cpu_state.seg_gs.seg, REG_INTEGER, REG_PERMANENT}, + [IREG_SS_seg] = { REG_WORD, &cpu_state.seg_ss.seg, REG_INTEGER, REG_PERMANENT}, - [IREG_ST0_i64] = {REG_FPU_ST_QWORD, &cpu_state.MM[0], REG_FP, REG_PERMANENT}, - [IREG_ST1_i64] = {REG_FPU_ST_QWORD, &cpu_state.MM[0], REG_FP, REG_PERMANENT}, - [IREG_ST2_i64] = {REG_FPU_ST_QWORD, &cpu_state.MM[0], REG_FP, REG_PERMANENT}, - [IREG_ST3_i64] = {REG_FPU_ST_QWORD, &cpu_state.MM[0], REG_FP, REG_PERMANENT}, - [IREG_ST4_i64] = {REG_FPU_ST_QWORD, &cpu_state.MM[0], REG_FP, REG_PERMANENT}, - [IREG_ST5_i64] = {REG_FPU_ST_QWORD, &cpu_state.MM[0], REG_FP, REG_PERMANENT}, - [IREG_ST6_i64] = {REG_FPU_ST_QWORD, &cpu_state.MM[0], REG_FP, REG_PERMANENT}, - [IREG_ST7_i64] = {REG_FPU_ST_QWORD, &cpu_state.MM[0], REG_FP, REG_PERMANENT}, + [IREG_FPU_TOP] = { REG_DWORD, &cpu_state.TOP, REG_INTEGER, REG_PERMANENT}, - [IREG_MM0x] = {REG_QWORD, &cpu_state.MM[0], REG_FP, REG_PERMANENT}, - [IREG_MM1x] = {REG_QWORD, &cpu_state.MM[1], REG_FP, REG_PERMANENT}, - [IREG_MM2x] = {REG_QWORD, &cpu_state.MM[2], REG_FP, REG_PERMANENT}, - [IREG_MM3x] = {REG_QWORD, &cpu_state.MM[3], REG_FP, REG_PERMANENT}, - [IREG_MM4x] = {REG_QWORD, &cpu_state.MM[4], REG_FP, REG_PERMANENT}, - [IREG_MM5x] = {REG_QWORD, &cpu_state.MM[5], REG_FP, REG_PERMANENT}, - [IREG_MM6x] = {REG_QWORD, &cpu_state.MM[6], REG_FP, REG_PERMANENT}, - [IREG_MM7x] = {REG_QWORD, &cpu_state.MM[7], REG_FP, REG_PERMANENT}, - - [IREG_NPXCx] = {REG_WORD, &cpu_state.npxc, REG_INTEGER, REG_PERMANENT}, - [IREG_NPXSx] = {REG_WORD, &cpu_state.npxs, REG_INTEGER, REG_PERMANENT}, + [IREG_ST0] = { REG_FPU_ST_DOUBLE, &cpu_state.ST[0], REG_FP, REG_PERMANENT}, + [IREG_ST1] = { REG_FPU_ST_DOUBLE, &cpu_state.ST[0], REG_FP, REG_PERMANENT}, + [IREG_ST2] = { REG_FPU_ST_DOUBLE, &cpu_state.ST[0], REG_FP, REG_PERMANENT}, + [IREG_ST3] = { REG_FPU_ST_DOUBLE, &cpu_state.ST[0], REG_FP, REG_PERMANENT}, + [IREG_ST4] = { REG_FPU_ST_DOUBLE, &cpu_state.ST[0], REG_FP, REG_PERMANENT}, + [IREG_ST5] = { REG_FPU_ST_DOUBLE, &cpu_state.ST[0], REG_FP, REG_PERMANENT}, + [IREG_ST6] = { REG_FPU_ST_DOUBLE, &cpu_state.ST[0], REG_FP, REG_PERMANENT}, + [IREG_ST7] = { REG_FPU_ST_DOUBLE, &cpu_state.ST[0], REG_FP, REG_PERMANENT}, - [IREG_flagsx] = {REG_WORD, &cpu_state.flags, REG_INTEGER, REG_PERMANENT}, - [IREG_eflagsx] = {REG_WORD, &cpu_state.eflags, REG_INTEGER, REG_PERMANENT}, + [IREG_tag0] = { REG_FPU_ST_BYTE, &cpu_state.tag[0], REG_INTEGER, REG_PERMANENT}, + [IREG_tag1] = { REG_FPU_ST_BYTE, &cpu_state.tag[0], REG_INTEGER, REG_PERMANENT}, + [IREG_tag2] = { REG_FPU_ST_BYTE, &cpu_state.tag[0], REG_INTEGER, REG_PERMANENT}, + [IREG_tag3] = { REG_FPU_ST_BYTE, &cpu_state.tag[0], REG_INTEGER, REG_PERMANENT}, + [IREG_tag4] = { REG_FPU_ST_BYTE, &cpu_state.tag[0], REG_INTEGER, REG_PERMANENT}, + [IREG_tag5] = { REG_FPU_ST_BYTE, &cpu_state.tag[0], REG_INTEGER, REG_PERMANENT}, + [IREG_tag6] = { REG_FPU_ST_BYTE, &cpu_state.tag[0], REG_INTEGER, REG_PERMANENT}, + [IREG_tag7] = { REG_FPU_ST_BYTE, &cpu_state.tag[0], REG_INTEGER, REG_PERMANENT}, - [IREG_CS_limit_low] = {REG_DWORD, &cpu_state.seg_cs.limit_low, REG_INTEGER, REG_PERMANENT}, - [IREG_DS_limit_low] = {REG_DWORD, &cpu_state.seg_ds.limit_low, REG_INTEGER, REG_PERMANENT}, - [IREG_ES_limit_low] = {REG_DWORD, &cpu_state.seg_es.limit_low, REG_INTEGER, REG_PERMANENT}, - [IREG_FS_limit_low] = {REG_DWORD, &cpu_state.seg_fs.limit_low, REG_INTEGER, REG_PERMANENT}, - [IREG_GS_limit_low] = {REG_DWORD, &cpu_state.seg_gs.limit_low, REG_INTEGER, REG_PERMANENT}, - [IREG_SS_limit_low] = {REG_DWORD, &cpu_state.seg_ss.limit_low, REG_INTEGER, REG_PERMANENT}, + [IREG_ST0_i64] = { REG_FPU_ST_QWORD, &cpu_state.MM[0], REG_FP, REG_PERMANENT}, + [IREG_ST1_i64] = { REG_FPU_ST_QWORD, &cpu_state.MM[0], REG_FP, REG_PERMANENT}, + [IREG_ST2_i64] = { REG_FPU_ST_QWORD, &cpu_state.MM[0], REG_FP, REG_PERMANENT}, + [IREG_ST3_i64] = { REG_FPU_ST_QWORD, &cpu_state.MM[0], REG_FP, REG_PERMANENT}, + [IREG_ST4_i64] = { REG_FPU_ST_QWORD, &cpu_state.MM[0], REG_FP, REG_PERMANENT}, + [IREG_ST5_i64] = { REG_FPU_ST_QWORD, &cpu_state.MM[0], REG_FP, REG_PERMANENT}, + [IREG_ST6_i64] = { REG_FPU_ST_QWORD, &cpu_state.MM[0], REG_FP, REG_PERMANENT}, + [IREG_ST7_i64] = { REG_FPU_ST_QWORD, &cpu_state.MM[0], REG_FP, REG_PERMANENT}, - [IREG_CS_limit_high] = {REG_DWORD, &cpu_state.seg_cs.limit_high, REG_INTEGER, REG_PERMANENT}, - [IREG_DS_limit_high] = {REG_DWORD, &cpu_state.seg_ds.limit_high, REG_INTEGER, REG_PERMANENT}, - [IREG_ES_limit_high] = {REG_DWORD, &cpu_state.seg_es.limit_high, REG_INTEGER, REG_PERMANENT}, - [IREG_FS_limit_high] = {REG_DWORD, &cpu_state.seg_fs.limit_high, REG_INTEGER, REG_PERMANENT}, - [IREG_GS_limit_high] = {REG_DWORD, &cpu_state.seg_gs.limit_high, REG_INTEGER, REG_PERMANENT}, - [IREG_SS_limit_high] = {REG_DWORD, &cpu_state.seg_ss.limit_high, REG_INTEGER, REG_PERMANENT}, + [IREG_MM0x] = { REG_QWORD, &cpu_state.MM[0], REG_FP, REG_PERMANENT}, + [IREG_MM1x] = { REG_QWORD, &cpu_state.MM[1], REG_FP, REG_PERMANENT}, + [IREG_MM2x] = { REG_QWORD, &cpu_state.MM[2], REG_FP, REG_PERMANENT}, + [IREG_MM3x] = { REG_QWORD, &cpu_state.MM[3], REG_FP, REG_PERMANENT}, + [IREG_MM4x] = { REG_QWORD, &cpu_state.MM[4], REG_FP, REG_PERMANENT}, + [IREG_MM5x] = { REG_QWORD, &cpu_state.MM[5], REG_FP, REG_PERMANENT}, + [IREG_MM6x] = { REG_QWORD, &cpu_state.MM[6], REG_FP, REG_PERMANENT}, + [IREG_MM7x] = { REG_QWORD, &cpu_state.MM[7], REG_FP, REG_PERMANENT}, - /*Temporary registers are stored on the stack, and are not guaranteed to - be preserved across uOPs. They will not be written back if they will - not be read again.*/ - [IREG_temp0] = {REG_DWORD, (void *)16, REG_INTEGER, REG_VOLATILE}, - [IREG_temp1] = {REG_DWORD, (void *)20, REG_INTEGER, REG_VOLATILE}, - [IREG_temp2] = {REG_DWORD, (void *)24, REG_INTEGER, REG_VOLATILE}, - [IREG_temp3] = {REG_DWORD, (void *)28, REG_INTEGER, REG_VOLATILE}, - - [IREG_temp0d] = {REG_DOUBLE, (void *)40, REG_FP, REG_VOLATILE}, - [IREG_temp1d] = {REG_DOUBLE, (void *)48, REG_FP, REG_VOLATILE}, + [IREG_NPXCx] = { REG_WORD, &cpu_state.npxc, REG_INTEGER, REG_PERMANENT}, + [IREG_NPXSx] = { REG_WORD, &cpu_state.npxs, REG_INTEGER, REG_PERMANENT}, + + [IREG_flagsx] = { REG_WORD, &cpu_state.flags, REG_INTEGER, REG_PERMANENT}, + [IREG_eflagsx] = { REG_WORD, &cpu_state.eflags, REG_INTEGER, REG_PERMANENT}, + + [IREG_CS_limit_low] = { REG_DWORD, &cpu_state.seg_cs.limit_low, REG_INTEGER, REG_PERMANENT}, + [IREG_DS_limit_low] = { REG_DWORD, &cpu_state.seg_ds.limit_low, REG_INTEGER, REG_PERMANENT}, + [IREG_ES_limit_low] = { REG_DWORD, &cpu_state.seg_es.limit_low, REG_INTEGER, REG_PERMANENT}, + [IREG_FS_limit_low] = { REG_DWORD, &cpu_state.seg_fs.limit_low, REG_INTEGER, REG_PERMANENT}, + [IREG_GS_limit_low] = { REG_DWORD, &cpu_state.seg_gs.limit_low, REG_INTEGER, REG_PERMANENT}, + [IREG_SS_limit_low] = { REG_DWORD, &cpu_state.seg_ss.limit_low, REG_INTEGER, REG_PERMANENT}, + + [IREG_CS_limit_high] = { REG_DWORD, &cpu_state.seg_cs.limit_high, REG_INTEGER, REG_PERMANENT}, + [IREG_DS_limit_high] = { REG_DWORD, &cpu_state.seg_ds.limit_high, REG_INTEGER, REG_PERMANENT}, + [IREG_ES_limit_high] = { REG_DWORD, &cpu_state.seg_es.limit_high, REG_INTEGER, REG_PERMANENT}, + [IREG_FS_limit_high] = { REG_DWORD, &cpu_state.seg_fs.limit_high, REG_INTEGER, REG_PERMANENT}, + [IREG_GS_limit_high] = { REG_DWORD, &cpu_state.seg_gs.limit_high, REG_INTEGER, REG_PERMANENT}, + [IREG_SS_limit_high] = { REG_DWORD, &cpu_state.seg_ss.limit_high, REG_INTEGER, REG_PERMANENT}, + + /*Temporary registers are stored on the stack, and are not guaranteed to + be preserved across uOPs. They will not be written back if they will + not be read again.*/ + [IREG_temp0] = { REG_DWORD, (void *) 16, REG_INTEGER, REG_VOLATILE }, + [IREG_temp1] = { REG_DWORD, (void *) 20, REG_INTEGER, REG_VOLATILE }, + [IREG_temp2] = { REG_DWORD, (void *) 24, REG_INTEGER, REG_VOLATILE }, + [IREG_temp3] = { REG_DWORD, (void *) 28, REG_INTEGER, REG_VOLATILE }, + + [IREG_temp0d] = { REG_DOUBLE, (void *) 40, REG_FP, REG_VOLATILE }, + [IREG_temp1d] = { REG_DOUBLE, (void *) 48, REG_FP, REG_VOLATILE }, }; -void codegen_reg_mark_as_required() +void +codegen_reg_mark_as_required(void) { - int reg; - - for (reg = 0; reg < IREG_COUNT; reg++) - { - int last_version = reg_last_version[reg]; - - if (last_version > 0 && ireg_data[reg].is_volatile == REG_PERMANENT) - reg_version[reg][last_version].flags |= REG_FLAGS_REQUIRED; - } + for (uint8_t reg = 0; reg < IREG_COUNT; reg++) { + int last_version = reg_last_version[reg]; + + if (last_version > 0 && ireg_data[reg].is_volatile == REG_PERMANENT) + reg_version[reg][last_version].flags |= REG_FLAGS_REQUIRED; + } } -int reg_is_native_size(ir_reg_t ir_reg) +int +reg_is_native_size(ir_reg_t ir_reg) { - int native_size = ireg_data[IREG_GET_REG(ir_reg.reg)].native_size; - int requested_size = IREG_GET_SIZE(ir_reg.reg); - - switch (native_size) - { - case REG_BYTE: case REG_FPU_ST_BYTE: - return (requested_size == IREG_SIZE_B); - case REG_WORD: - return (requested_size == IREG_SIZE_W); - case REG_DWORD: + int native_size = ireg_data[IREG_GET_REG(ir_reg.reg)].native_size; + int requested_size = IREG_GET_SIZE(ir_reg.reg); + + switch (native_size) { + case REG_BYTE: + case REG_FPU_ST_BYTE: + return (requested_size == IREG_SIZE_B); + case REG_WORD: + return (requested_size == IREG_SIZE_W); + case REG_DWORD: + return (requested_size == IREG_SIZE_L); + case REG_QWORD: + case REG_FPU_ST_QWORD: + case REG_DOUBLE: + case REG_FPU_ST_DOUBLE: + return ((requested_size == IREG_SIZE_D) || (requested_size == IREG_SIZE_Q)); + case REG_POINTER: + if (sizeof(void *) == 4) return (requested_size == IREG_SIZE_L); - case REG_QWORD: case REG_FPU_ST_QWORD: case REG_DOUBLE: case REG_FPU_ST_DOUBLE: - return ((requested_size == IREG_SIZE_D) || (requested_size == IREG_SIZE_Q)); - case REG_POINTER: - if (sizeof(void *) == 4) - return (requested_size == IREG_SIZE_L); - return (requested_size == IREG_SIZE_Q); - - default: - fatal("get_reg_is_native_size: unknown native size %i\n", native_size); - } - - return 0; + return (requested_size == IREG_SIZE_Q); + + default: + fatal("get_reg_is_native_size: unknown native size %i\n", native_size); + } + + return 0; } -void codegen_reg_reset() +void +codegen_reg_reset(void) { - int c; + int c; - host_reg_set.regs = _host_regs; - host_reg_set.dirty = _host_reg_dirty; - host_reg_set.reg_list = codegen_host_reg_list; - host_reg_set.locked = 0; - host_reg_set.nr_regs = CODEGEN_HOST_REGS; - host_fp_reg_set.regs = host_fp_regs; - host_fp_reg_set.dirty = host_fp_reg_dirty; - host_fp_reg_set.reg_list = codegen_host_fp_reg_list; - host_fp_reg_set.locked = 0; - host_fp_reg_set.nr_regs = CODEGEN_HOST_FP_REGS; + host_reg_set.regs = _host_regs; + host_reg_set.dirty = _host_reg_dirty; + host_reg_set.reg_list = codegen_host_reg_list; + host_reg_set.locked = 0; + host_reg_set.nr_regs = CODEGEN_HOST_REGS; + host_fp_reg_set.regs = host_fp_regs; + host_fp_reg_set.dirty = host_fp_reg_dirty; + host_fp_reg_set.reg_list = codegen_host_fp_reg_list; + host_fp_reg_set.locked = 0; + host_fp_reg_set.nr_regs = CODEGEN_HOST_FP_REGS; - for (c = 0; c < IREG_COUNT; c++) - { - reg_last_version[c] = 0; - reg_version[c][0].refcount = 0; - } - for (c = 0; c < CODEGEN_HOST_REGS; c++) - { - host_reg_set.regs[c] = invalid_ir_reg; - host_reg_set.dirty[c] = 0; - } - for (c = 0; c < CODEGEN_HOST_FP_REGS; c++) - { - host_fp_reg_set.regs[c] = invalid_ir_reg; - host_fp_reg_set.dirty[c] = 0; - } - - reg_dead_list = 0; - max_version_refcount = 0; + for (c = 0; c < IREG_COUNT; c++) { + reg_last_version[c] = 0; + reg_version[c][0].refcount = 0; + } + for (c = 0; c < CODEGEN_HOST_REGS; c++) { + host_reg_set.regs[c] = invalid_ir_reg; + host_reg_set.dirty[c] = 0; + } + for (c = 0; c < CODEGEN_HOST_FP_REGS; c++) { + host_fp_reg_set.regs[c] = invalid_ir_reg; + host_fp_reg_set.dirty[c] = 0; + } + + reg_dead_list = 0; + max_version_refcount = 0; } -static inline int ir_get_refcount(ir_reg_t ir_reg) +static inline int +ir_get_refcount(ir_reg_t ir_reg) { - return reg_version[IREG_GET_REG(ir_reg.reg)][ir_reg.version].refcount; + return reg_version[IREG_GET_REG(ir_reg.reg)][ir_reg.version].refcount; } -static inline host_reg_set_t *get_reg_set(ir_reg_t ir_reg) +static inline host_reg_set_t * +get_reg_set(ir_reg_t ir_reg) { - if (ireg_data[IREG_GET_REG(ir_reg.reg)].type == REG_INTEGER) - return &host_reg_set; - else - return &host_fp_reg_set; + if (ireg_data[IREG_GET_REG(ir_reg.reg)].type == REG_INTEGER) + return &host_reg_set; + else + return &host_fp_reg_set; } -static void codegen_reg_load(host_reg_set_t *reg_set, codeblock_t *block, int c, ir_reg_t ir_reg) +static void +codegen_reg_load(host_reg_set_t *reg_set, codeblock_t *block, int c, ir_reg_t ir_reg) { - switch (ireg_data[IREG_GET_REG(ir_reg.reg)].native_size) - { - case REG_WORD: + switch (ireg_data[IREG_GET_REG(ir_reg.reg)].native_size) { + case REG_WORD: #ifndef RELEASE_BUILD - if (ireg_data[IREG_GET_REG(ir_reg.reg)].type != REG_INTEGER) - fatal("codegen_reg_load - REG_WORD !REG_INTEGER\n"); + if (ireg_data[IREG_GET_REG(ir_reg.reg)].type != REG_INTEGER) + fatal("codegen_reg_load - REG_WORD !REG_INTEGER\n"); #endif - if ((uintptr_t)ireg_data[IREG_GET_REG(ir_reg.reg)].p < 256) - codegen_direct_read_16_stack(block, reg_set->reg_list[c].reg, (intptr_t)ireg_data[IREG_GET_REG(ir_reg.reg)].p); - else - codegen_direct_read_16(block, reg_set->reg_list[c].reg, ireg_data[IREG_GET_REG(ir_reg.reg)].p); - break; + if ((uintptr_t) ireg_data[IREG_GET_REG(ir_reg.reg)].p < 256) + codegen_direct_read_16_stack(block, reg_set->reg_list[c].reg, (intptr_t) ireg_data[IREG_GET_REG(ir_reg.reg)].p); + else + codegen_direct_read_16(block, reg_set->reg_list[c].reg, ireg_data[IREG_GET_REG(ir_reg.reg)].p); + break; - case REG_DWORD: + case REG_DWORD: #ifndef RELEASE_BUILD - if (ireg_data[IREG_GET_REG(ir_reg.reg)].type != REG_INTEGER) - fatal("codegen_reg_load - REG_DWORD !REG_INTEGER\n"); + if (ireg_data[IREG_GET_REG(ir_reg.reg)].type != REG_INTEGER) + fatal("codegen_reg_load - REG_DWORD !REG_INTEGER\n"); #endif - if ((uintptr_t)ireg_data[IREG_GET_REG(ir_reg.reg)].p < 256) - codegen_direct_read_32_stack(block, reg_set->reg_list[c].reg, (intptr_t)ireg_data[IREG_GET_REG(ir_reg.reg)].p); - else - codegen_direct_read_32(block, reg_set->reg_list[c].reg, ireg_data[IREG_GET_REG(ir_reg.reg)].p); - break; + if ((uintptr_t) ireg_data[IREG_GET_REG(ir_reg.reg)].p < 256) + codegen_direct_read_32_stack(block, reg_set->reg_list[c].reg, (intptr_t) ireg_data[IREG_GET_REG(ir_reg.reg)].p); + else + codegen_direct_read_32(block, reg_set->reg_list[c].reg, ireg_data[IREG_GET_REG(ir_reg.reg)].p); + break; - case REG_QWORD: + case REG_QWORD: #ifndef RELEASE_BUILD - if (ireg_data[IREG_GET_REG(ir_reg.reg)].type != REG_FP) - fatal("codegen_reg_load - REG_QWORD !REG_FP\n"); + if (ireg_data[IREG_GET_REG(ir_reg.reg)].type != REG_FP) + fatal("codegen_reg_load - REG_QWORD !REG_FP\n"); #endif - if ((uintptr_t)ireg_data[IREG_GET_REG(ir_reg.reg)].p < 256) - codegen_direct_read_64_stack(block, reg_set->reg_list[c].reg, (intptr_t)ireg_data[IREG_GET_REG(ir_reg.reg)].p); - else - codegen_direct_read_64(block, reg_set->reg_list[c].reg, ireg_data[IREG_GET_REG(ir_reg.reg)].p); - break; - - case REG_POINTER: -#ifndef RELEASE_BUILD - if (ireg_data[IREG_GET_REG(ir_reg.reg)].type != REG_INTEGER) - fatal("codegen_reg_load - REG_POINTER !REG_INTEGER\n"); -#endif - if ((uintptr_t)ireg_data[IREG_GET_REG(ir_reg.reg)].p < 256) - codegen_direct_read_pointer_stack(block, reg_set->reg_list[c].reg, (intptr_t)ireg_data[IREG_GET_REG(ir_reg.reg)].p); - else - codegen_direct_read_pointer(block, reg_set->reg_list[c].reg, ireg_data[IREG_GET_REG(ir_reg.reg)].p); - break; + if ((uintptr_t) ireg_data[IREG_GET_REG(ir_reg.reg)].p < 256) + codegen_direct_read_64_stack(block, reg_set->reg_list[c].reg, (intptr_t) ireg_data[IREG_GET_REG(ir_reg.reg)].p); + else + codegen_direct_read_64(block, reg_set->reg_list[c].reg, ireg_data[IREG_GET_REG(ir_reg.reg)].p); + break; - case REG_DOUBLE: + case REG_POINTER: #ifndef RELEASE_BUILD - if (ireg_data[IREG_GET_REG(ir_reg.reg)].type != REG_FP) - fatal("codegen_reg_load - REG_DOUBLE !REG_FP\n"); + if (ireg_data[IREG_GET_REG(ir_reg.reg)].type != REG_INTEGER) + fatal("codegen_reg_load - REG_POINTER !REG_INTEGER\n"); #endif - if ((uintptr_t)ireg_data[IREG_GET_REG(ir_reg.reg)].p < 256) - codegen_direct_read_double_stack(block, reg_set->reg_list[c].reg, (intptr_t)ireg_data[IREG_GET_REG(ir_reg.reg)].p); - else - codegen_direct_read_double(block, reg_set->reg_list[c].reg, ireg_data[IREG_GET_REG(ir_reg.reg)].p); - break; - - case REG_FPU_ST_BYTE: + if ((uintptr_t) ireg_data[IREG_GET_REG(ir_reg.reg)].p < 256) + codegen_direct_read_pointer_stack(block, reg_set->reg_list[c].reg, (intptr_t) ireg_data[IREG_GET_REG(ir_reg.reg)].p); + else + codegen_direct_read_pointer(block, reg_set->reg_list[c].reg, ireg_data[IREG_GET_REG(ir_reg.reg)].p); + break; + + case REG_DOUBLE: #ifndef RELEASE_BUILD - if (ireg_data[IREG_GET_REG(ir_reg.reg)].type != REG_INTEGER) - fatal("codegen_reg_load - REG_FPU_ST_BYTE !REG_INTEGER\n"); + if (ireg_data[IREG_GET_REG(ir_reg.reg)].type != REG_FP) + fatal("codegen_reg_load - REG_DOUBLE !REG_FP\n"); #endif - if (block->flags & CODEBLOCK_STATIC_TOP) - codegen_direct_read_8(block, reg_set->reg_list[c].reg, &cpu_state.tag[ir_reg.reg & 7]); - else - codegen_direct_read_st_8(block, reg_set->reg_list[c].reg, &cpu_state.tag[0], ir_reg.reg & 7); - break; + if ((uintptr_t) ireg_data[IREG_GET_REG(ir_reg.reg)].p < 256) + codegen_direct_read_double_stack(block, reg_set->reg_list[c].reg, (intptr_t) ireg_data[IREG_GET_REG(ir_reg.reg)].p); + else + codegen_direct_read_double(block, reg_set->reg_list[c].reg, ireg_data[IREG_GET_REG(ir_reg.reg)].p); + break; - case REG_FPU_ST_QWORD: + case REG_FPU_ST_BYTE: #ifndef RELEASE_BUILD - if (ireg_data[IREG_GET_REG(ir_reg.reg)].type != REG_FP) - fatal("codegen_reg_load - REG_FPU_ST_QWORD !REG_FP\n"); + if (ireg_data[IREG_GET_REG(ir_reg.reg)].type != REG_INTEGER) + fatal("codegen_reg_load - REG_FPU_ST_BYTE !REG_INTEGER\n"); #endif - if (block->flags & CODEBLOCK_STATIC_TOP) - codegen_direct_read_64(block, reg_set->reg_list[c].reg, &cpu_state.MM[ir_reg.reg & 7]); - else - codegen_direct_read_st_64(block, reg_set->reg_list[c].reg, &cpu_state.MM[0], ir_reg.reg & 7); - break; + if (block->flags & CODEBLOCK_STATIC_TOP) + codegen_direct_read_8(block, reg_set->reg_list[c].reg, &cpu_state.tag[ir_reg.reg & 7]); + else + codegen_direct_read_st_8(block, reg_set->reg_list[c].reg, &cpu_state.tag[0], ir_reg.reg & 7); + break; - case REG_FPU_ST_DOUBLE: + case REG_FPU_ST_QWORD: #ifndef RELEASE_BUILD - if (ireg_data[IREG_GET_REG(ir_reg.reg)].type != REG_FP) - fatal("codegen_reg_load - REG_FPU_ST_DOUBLE !REG_FP\n"); + if (ireg_data[IREG_GET_REG(ir_reg.reg)].type != REG_FP) + fatal("codegen_reg_load - REG_FPU_ST_QWORD !REG_FP\n"); #endif - if (block->flags & CODEBLOCK_STATIC_TOP) - codegen_direct_read_double(block, reg_set->reg_list[c].reg, &cpu_state.ST[ir_reg.reg & 7]); - else - codegen_direct_read_st_double(block, reg_set->reg_list[c].reg, &cpu_state.ST[0], ir_reg.reg & 7); - break; + if (block->flags & CODEBLOCK_STATIC_TOP) + codegen_direct_read_64(block, reg_set->reg_list[c].reg, &cpu_state.MM[ir_reg.reg & 7]); + else + codegen_direct_read_st_64(block, reg_set->reg_list[c].reg, &cpu_state.MM[0], ir_reg.reg & 7); + break; - default: - fatal("codegen_reg_load - native_size=%i reg=%i\n", ireg_data[IREG_GET_REG(ir_reg.reg)].native_size, IREG_GET_REG(ir_reg.reg)); - } + case REG_FPU_ST_DOUBLE: +#ifndef RELEASE_BUILD + if (ireg_data[IREG_GET_REG(ir_reg.reg)].type != REG_FP) + fatal("codegen_reg_load - REG_FPU_ST_DOUBLE !REG_FP\n"); +#endif + if (block->flags & CODEBLOCK_STATIC_TOP) + codegen_direct_read_double(block, reg_set->reg_list[c].reg, &cpu_state.ST[ir_reg.reg & 7]); + else + codegen_direct_read_st_double(block, reg_set->reg_list[c].reg, &cpu_state.ST[0], ir_reg.reg & 7); + break; - reg_set->regs[c] = ir_reg; + default: + fatal("codegen_reg_load - native_size=%i reg=%i\n", ireg_data[IREG_GET_REG(ir_reg.reg)].native_size, IREG_GET_REG(ir_reg.reg)); + } + + reg_set->regs[c] = ir_reg; } -static void codegen_reg_writeback(host_reg_set_t *reg_set, codeblock_t *block, int c, int invalidate) +static void +codegen_reg_writeback(host_reg_set_t *reg_set, codeblock_t *block, int c, int invalidate) { - int ir_reg = IREG_GET_REG(reg_set->regs[c].reg); - void *p = ireg_data[ir_reg].p; + int ir_reg = IREG_GET_REG(reg_set->regs[c].reg); + void *p = ireg_data[ir_reg].p; - if (!reg_version[ir_reg][reg_set->regs[c].version].refcount && - ireg_data[ir_reg].is_volatile) - return; + if (!reg_version[ir_reg][reg_set->regs[c].version].refcount && ireg_data[ir_reg].is_volatile) + return; - switch (ireg_data[ir_reg].native_size) - { - case REG_BYTE: + switch (ireg_data[ir_reg].native_size) { + case REG_BYTE: #ifndef RELEASE_BUILD - if (ireg_data[ir_reg].type != REG_INTEGER) - fatal("codegen_reg_writeback - REG_BYTE !REG_INTEGER\n"); - if ((uintptr_t)p < 256) - fatal("codegen_reg_writeback - REG_BYTE %p\n", p); + if (ireg_data[ir_reg].type != REG_INTEGER) + fatal("codegen_reg_writeback - REG_BYTE !REG_INTEGER\n"); + if ((uintptr_t) p < 256) + fatal("codegen_reg_writeback - REG_BYTE %p\n", p); #endif - codegen_direct_write_8(block, p, reg_set->reg_list[c].reg); - break; + codegen_direct_write_8(block, p, reg_set->reg_list[c].reg); + break; - case REG_WORD: + case REG_WORD: #ifndef RELEASE_BUILD - if (ireg_data[ir_reg].type != REG_INTEGER) - fatal("codegen_reg_writeback - REG_WORD !REG_INTEGER\n"); - if ((uintptr_t)p < 256) - fatal("codegen_reg_writeback - REG_WORD %p\n", p); + if (ireg_data[ir_reg].type != REG_INTEGER) + fatal("codegen_reg_writeback - REG_WORD !REG_INTEGER\n"); + if ((uintptr_t) p < 256) + fatal("codegen_reg_writeback - REG_WORD %p\n", p); #endif - codegen_direct_write_16(block, p, reg_set->reg_list[c].reg); - break; + codegen_direct_write_16(block, p, reg_set->reg_list[c].reg); + break; - case REG_DWORD: + case REG_DWORD: #ifndef RELEASE_BUILD - if (ireg_data[ir_reg].type != REG_INTEGER) - fatal("codegen_reg_writeback - REG_DWORD !REG_INTEGER\n"); + if (ireg_data[ir_reg].type != REG_INTEGER) + fatal("codegen_reg_writeback - REG_DWORD !REG_INTEGER\n"); #endif - if ((uintptr_t)p < 256) - codegen_direct_write_32_stack(block, (intptr_t)p, reg_set->reg_list[c].reg); - else - codegen_direct_write_32(block, p, reg_set->reg_list[c].reg); - break; + if ((uintptr_t) p < 256) + codegen_direct_write_32_stack(block, (intptr_t) p, reg_set->reg_list[c].reg); + else + codegen_direct_write_32(block, p, reg_set->reg_list[c].reg); + break; - case REG_QWORD: + case REG_QWORD: #ifndef RELEASE_BUILD - if (ireg_data[ir_reg].type != REG_FP) - fatal("codegen_reg_writeback - REG_QWORD !REG_FP\n"); + if (ireg_data[ir_reg].type != REG_FP) + fatal("codegen_reg_writeback - REG_QWORD !REG_FP\n"); #endif - if ((uintptr_t)p < 256) - codegen_direct_write_64_stack(block, (intptr_t)p, reg_set->reg_list[c].reg); - else - codegen_direct_write_64(block, p, reg_set->reg_list[c].reg); - break; + if ((uintptr_t) p < 256) + codegen_direct_write_64_stack(block, (intptr_t) p, reg_set->reg_list[c].reg); + else + codegen_direct_write_64(block, p, reg_set->reg_list[c].reg); + break; - case REG_POINTER: + case REG_POINTER: #ifndef RELEASE_BUILD - if (ireg_data[ir_reg].type != REG_INTEGER) - fatal("codegen_reg_writeback - REG_POINTER !REG_INTEGER\n"); - if ((uintptr_t)p < 256) - fatal("codegen_reg_writeback - REG_POINTER %p\n", p); + if (ireg_data[ir_reg].type != REG_INTEGER) + fatal("codegen_reg_writeback - REG_POINTER !REG_INTEGER\n"); + if ((uintptr_t) p < 256) + fatal("codegen_reg_writeback - REG_POINTER %p\n", p); #endif - codegen_direct_write_ptr(block, p, reg_set->reg_list[c].reg); - break; + codegen_direct_write_ptr(block, p, reg_set->reg_list[c].reg); + break; - case REG_DOUBLE: + case REG_DOUBLE: #ifndef RELEASE_BUILD - if (ireg_data[ir_reg].type != REG_FP) - fatal("codegen_reg_writeback - REG_DOUBLE !REG_FP\n"); + if (ireg_data[ir_reg].type != REG_FP) + fatal("codegen_reg_writeback - REG_DOUBLE !REG_FP\n"); #endif - if ((uintptr_t)p < 256) - codegen_direct_write_double_stack(block, (intptr_t)p, reg_set->reg_list[c].reg); - else - codegen_direct_write_double(block, p, reg_set->reg_list[c].reg); - break; + if ((uintptr_t) p < 256) + codegen_direct_write_double_stack(block, (intptr_t) p, reg_set->reg_list[c].reg); + else + codegen_direct_write_double(block, p, reg_set->reg_list[c].reg); + break; - case REG_FPU_ST_BYTE: + case REG_FPU_ST_BYTE: #ifndef RELEASE_BUILD - if (ireg_data[ir_reg].type != REG_INTEGER) - fatal("codegen_reg_writeback - REG_FPU_ST_BYTE !REG_INTEGER\n"); + if (ireg_data[ir_reg].type != REG_INTEGER) + fatal("codegen_reg_writeback - REG_FPU_ST_BYTE !REG_INTEGER\n"); #endif - if (block->flags & CODEBLOCK_STATIC_TOP) - codegen_direct_write_8(block, &cpu_state.tag[reg_set->regs[c].reg & 7], reg_set->reg_list[c].reg); - else - codegen_direct_write_st_8(block, &cpu_state.tag[0], reg_set->regs[c].reg & 7, reg_set->reg_list[c].reg); - break; + if (block->flags & CODEBLOCK_STATIC_TOP) + codegen_direct_write_8(block, &cpu_state.tag[reg_set->regs[c].reg & 7], reg_set->reg_list[c].reg); + else + codegen_direct_write_st_8(block, &cpu_state.tag[0], reg_set->regs[c].reg & 7, reg_set->reg_list[c].reg); + break; - case REG_FPU_ST_QWORD: + case REG_FPU_ST_QWORD: #ifndef RELEASE_BUILD - if (ireg_data[ir_reg].type != REG_FP) - fatal("codegen_reg_writeback - REG_FPU_ST_QWORD !REG_FP\n"); + if (ireg_data[ir_reg].type != REG_FP) + fatal("codegen_reg_writeback - REG_FPU_ST_QWORD !REG_FP\n"); #endif - if (block->flags & CODEBLOCK_STATIC_TOP) - codegen_direct_write_64(block, &cpu_state.MM[reg_set->regs[c].reg & 7], reg_set->reg_list[c].reg); - else - codegen_direct_write_st_64(block, &cpu_state.MM[0], reg_set->regs[c].reg & 7, reg_set->reg_list[c].reg); - break; + if (block->flags & CODEBLOCK_STATIC_TOP) + codegen_direct_write_64(block, &cpu_state.MM[reg_set->regs[c].reg & 7], reg_set->reg_list[c].reg); + else + codegen_direct_write_st_64(block, &cpu_state.MM[0], reg_set->regs[c].reg & 7, reg_set->reg_list[c].reg); + break; - case REG_FPU_ST_DOUBLE: + case REG_FPU_ST_DOUBLE: #ifndef RELEASE_BUILD - if (ireg_data[ir_reg].type != REG_FP) - fatal("codegen_reg_writeback - REG_FPU_ST_DOUBLE !REG_FP\n"); + if (ireg_data[ir_reg].type != REG_FP) + fatal("codegen_reg_writeback - REG_FPU_ST_DOUBLE !REG_FP\n"); #endif - if (block->flags & CODEBLOCK_STATIC_TOP) - codegen_direct_write_double(block, &cpu_state.ST[reg_set->regs[c].reg & 7], reg_set->reg_list[c].reg); - else - codegen_direct_write_st_double(block, &cpu_state.ST[0], reg_set->regs[c].reg & 7, reg_set->reg_list[c].reg); - break; + if (block->flags & CODEBLOCK_STATIC_TOP) + codegen_direct_write_double(block, &cpu_state.ST[reg_set->regs[c].reg & 7], reg_set->reg_list[c].reg); + else + codegen_direct_write_st_double(block, &cpu_state.ST[0], reg_set->regs[c].reg & 7, reg_set->reg_list[c].reg); + break; - default: - fatal("codegen_reg_flush - native_size=%i\n", ireg_data[ir_reg].native_size); - } + default: + fatal("codegen_reg_flush - native_size=%i\n", ireg_data[ir_reg].native_size); + } - if (invalidate) - reg_set->regs[c] = invalid_ir_reg; - reg_set->dirty[c] = 0; + if (invalidate) + reg_set->regs[c] = invalid_ir_reg; + reg_set->dirty[c] = 0; } #ifdef CODEGEN_BACKEND_HAS_MOV_IMM -void codegen_reg_write_imm(codeblock_t *block, ir_reg_t ir_reg, uint32_t imm_data) +void +codegen_reg_write_imm(codeblock_t *block, ir_reg_t ir_reg, uint32_t imm_data) { - int reg_idx = IREG_GET_REG(ir_reg.reg); - void *p = ireg_data[reg_idx].p; + int reg_idx = IREG_GET_REG(ir_reg.reg); + void *p = ireg_data[reg_idx].p; - switch (ireg_data[reg_idx].native_size) - { - case REG_BYTE: -#ifndef RELEASE_BUILD - if ((uintptr_t)p < 256) - fatal("codegen_reg_write_imm - REG_BYTE %p\n", p); -#endif - codegen_direct_write_8_imm(block, p, imm_data); - break; + switch (ireg_data[reg_idx].native_size) { + case REG_BYTE: +# ifndef RELEASE_BUILD + if ((uintptr_t) p < 256) + fatal("codegen_reg_write_imm - REG_BYTE %p\n", p); +# endif + codegen_direct_write_8_imm(block, p, imm_data); + break; - case REG_WORD: -#ifndef RELEASE_BUILD - if ((uintptr_t)p < 256) - fatal("codegen_reg_write_imm - REG_WORD %p\n", p); -#endif - codegen_direct_write_16_imm(block, p, imm_data); - break; + case REG_WORD: +# ifndef RELEASE_BUILD + if ((uintptr_t) p < 256) + fatal("codegen_reg_write_imm - REG_WORD %p\n", p); +# endif + codegen_direct_write_16_imm(block, p, imm_data); + break; - case REG_DWORD: - if ((uintptr_t)p < 256) - codegen_direct_write_32_imm_stack(block, (int)p, imm_data); - else - codegen_direct_write_32_imm(block, p, imm_data); - break; + case REG_DWORD: + if ((uintptr_t) p < 256) + codegen_direct_write_32_imm_stack(block, (int) ((uintptr_t) p), imm_data); + else + codegen_direct_write_32_imm(block, p, imm_data); + break; - case REG_POINTER: - case REG_QWORD: - case REG_DOUBLE: - case REG_FPU_ST_BYTE: - case REG_FPU_ST_QWORD: - case REG_FPU_ST_DOUBLE: - default: - fatal("codegen_reg_write_imm - native_size=%i\n", ireg_data[reg_idx].native_size); - } + case REG_POINTER: + case REG_QWORD: + case REG_DOUBLE: + case REG_FPU_ST_BYTE: + case REG_FPU_ST_QWORD: + case REG_FPU_ST_DOUBLE: + default: + fatal("codegen_reg_write_imm - native_size=%i\n", ireg_data[reg_idx].native_size); + } } #endif -static void alloc_reg(ir_reg_t ir_reg) +static void +alloc_reg(ir_reg_t ir_reg) { - host_reg_set_t *reg_set = get_reg_set(ir_reg); - int nr_regs = (reg_set == &host_reg_set) ? CODEGEN_HOST_REGS : CODEGEN_HOST_FP_REGS; - int c; - - for (c = 0; c < nr_regs; c++) - { - if (IREG_GET_REG(reg_set->regs[c].reg) == IREG_GET_REG(ir_reg.reg)) - { + host_reg_set_t *reg_set = get_reg_set(ir_reg); + int nr_regs = (reg_set == &host_reg_set) ? CODEGEN_HOST_REGS : CODEGEN_HOST_FP_REGS; + + for (int c = 0; c < nr_regs; c++) { + if (IREG_GET_REG(reg_set->regs[c].reg) == IREG_GET_REG(ir_reg.reg)) { #ifndef RELEASE_BUILD - if (reg_set->regs[c].version != ir_reg.version) - fatal("alloc_reg - host_regs[c].version != ir_reg.version %i %p %p %i %i\n", c, reg_set, &host_reg_set, reg_set->regs[c].reg, ir_reg.reg); + if (reg_set->regs[c].version != ir_reg.version) + fatal("alloc_reg - host_regs[c].version != ir_reg.version %i %p %p %i %i\n", c, reg_set, &host_reg_set, reg_set->regs[c].reg, ir_reg.reg); #endif + reg_set->locked |= (1 << c); + return; + } + } +} + +static void +alloc_dest_reg(ir_reg_t ir_reg, int dest_reference) +{ + host_reg_set_t *reg_set = get_reg_set(ir_reg); + int nr_regs = (reg_set == &host_reg_set) ? CODEGEN_HOST_REGS : CODEGEN_HOST_FP_REGS; + + for (int c = 0; c < nr_regs; c++) { + if (IREG_GET_REG(reg_set->regs[c].reg) == IREG_GET_REG(ir_reg.reg)) { + if (reg_set->regs[c].version == ir_reg.version) { + reg_set->locked |= (1 << c); + } else { + /*The immediate prior version may have been + optimised out, so search backwards to find the + last valid version*/ + int prev_version = ir_reg.version - 1; + while (prev_version >= 0) { + const reg_version_t *regv = ®_version[IREG_GET_REG(reg_set->regs[c].reg)][prev_version]; + + if (!(regv->flags & REG_FLAGS_DEAD) && regv->refcount == dest_reference) { reg_set->locked |= (1 << c); return; + } + prev_version--; } + fatal("codegen_reg_alloc_register - host_regs[c].version != dest_reg_a.version %i,%i %i\n", reg_set->regs[c].version, ir_reg.version, dest_reference); + } + return; } + } } -static void alloc_dest_reg(ir_reg_t ir_reg, int dest_reference) +void +codegen_reg_alloc_register(ir_reg_t dest_reg_a, ir_reg_t src_reg_a, ir_reg_t src_reg_b, ir_reg_t src_reg_c) { - host_reg_set_t *reg_set = get_reg_set(ir_reg); - int nr_regs = (reg_set == &host_reg_set) ? CODEGEN_HOST_REGS : CODEGEN_HOST_FP_REGS; - int c; + int dest_reference = 0; - for (c = 0; c < nr_regs; c++) - { - if (IREG_GET_REG(reg_set->regs[c].reg) == IREG_GET_REG(ir_reg.reg)) - { - if (reg_set->regs[c].version == ir_reg.version) - { - reg_set->locked |= (1 << c); - } - else - { - /*The immediate prior version may have been - optimised out, so search backwards to find the - last valid version*/ - int prev_version = ir_reg.version-1; - while (prev_version >= 0) - { - reg_version_t *regv = ®_version[IREG_GET_REG(reg_set->regs[c].reg)][prev_version]; + host_reg_set.locked = 0; + host_fp_reg_set.locked = 0; - if (!(regv->flags & REG_FLAGS_DEAD) && regv->refcount == dest_reference) - { - reg_set->locked |= (1 << c); - return; - } - prev_version--; - } - fatal("codegen_reg_alloc_register - host_regs[c].version != dest_reg_a.version %i,%i %i\n", reg_set->regs[c].version, ir_reg.version, dest_reference); - } - return; - } - } + if (!ir_reg_is_invalid(dest_reg_a)) { + if (!ir_reg_is_invalid(src_reg_a) && IREG_GET_REG(src_reg_a.reg) == IREG_GET_REG(dest_reg_a.reg) && src_reg_a.version == dest_reg_a.version - 1) + dest_reference++; + if (!ir_reg_is_invalid(src_reg_b) && IREG_GET_REG(src_reg_b.reg) == IREG_GET_REG(dest_reg_a.reg) && src_reg_b.version == dest_reg_a.version - 1) + dest_reference++; + if (!ir_reg_is_invalid(src_reg_c) && IREG_GET_REG(src_reg_c.reg) == IREG_GET_REG(dest_reg_a.reg) && src_reg_c.version == dest_reg_a.version - 1) + dest_reference++; + } + if (!ir_reg_is_invalid(src_reg_a)) + alloc_reg(src_reg_a); + if (!ir_reg_is_invalid(src_reg_b)) + alloc_reg(src_reg_b); + if (!ir_reg_is_invalid(src_reg_c)) + alloc_reg(src_reg_c); + if (!ir_reg_is_invalid(dest_reg_a)) + alloc_dest_reg(dest_reg_a, dest_reference); } -void codegen_reg_alloc_register(ir_reg_t dest_reg_a, ir_reg_t src_reg_a, ir_reg_t src_reg_b, ir_reg_t src_reg_c) +ir_host_reg_t +codegen_reg_alloc_read_reg(codeblock_t *block, ir_reg_t ir_reg, int *host_reg_idx) { - int dest_reference = 0; - - host_reg_set.locked = 0; - host_fp_reg_set.locked = 0; + host_reg_set_t *reg_set = get_reg_set(ir_reg); + int c; - if (!ir_reg_is_invalid(dest_reg_a)) - { - if (!ir_reg_is_invalid(src_reg_a) && IREG_GET_REG(src_reg_a.reg) == IREG_GET_REG(dest_reg_a.reg) && src_reg_a.version == dest_reg_a.version-1) - dest_reference++; - if (!ir_reg_is_invalid(src_reg_b) && IREG_GET_REG(src_reg_b.reg) == IREG_GET_REG(dest_reg_a.reg) && src_reg_b.version == dest_reg_a.version-1) - dest_reference++; - if (!ir_reg_is_invalid(src_reg_c) && IREG_GET_REG(src_reg_c.reg) == IREG_GET_REG(dest_reg_a.reg) && src_reg_c.version == dest_reg_a.version-1) - dest_reference++; + /*Search for required register*/ + for (c = 0; c < reg_set->nr_regs; c++) { + if (!ir_reg_is_invalid(reg_set->regs[c]) && IREG_GET_REG(reg_set->regs[c].reg) == IREG_GET_REG(ir_reg.reg) && reg_set->regs[c].version == ir_reg.version) + break; + + if (!ir_reg_is_invalid(reg_set->regs[c]) && IREG_GET_REG(reg_set->regs[c].reg) == IREG_GET_REG(ir_reg.reg) && reg_set->regs[c].version <= ir_reg.version) { + reg_version[IREG_GET_REG(reg_set->regs[c].reg)][reg_set->regs[c].version].refcount++; + break; } - if (!ir_reg_is_invalid(src_reg_a)) - alloc_reg(src_reg_a); - if (!ir_reg_is_invalid(src_reg_b)) - alloc_reg(src_reg_b); - if (!ir_reg_is_invalid(src_reg_c)) - alloc_reg(src_reg_c); - if (!ir_reg_is_invalid(dest_reg_a)) - alloc_dest_reg(dest_reg_a, dest_reference); + +#ifndef RELEASE_BUILD + if (!ir_reg_is_invalid(reg_set->regs[c]) && IREG_GET_REG(reg_set->regs[c].reg) == IREG_GET_REG(ir_reg.reg) && reg_version[IREG_GET_REG(reg_set->regs[c].reg)][reg_set->regs[c].version].refcount) + fatal("codegen_reg_alloc_read_reg - version mismatch!\n"); +#endif + } + + if (c == reg_set->nr_regs) { + /*No unused registers. Search for an unlocked register with no pending reads*/ + for (c = 0; c < reg_set->nr_regs; c++) { + if (!(reg_set->locked & (1 << c)) && IREG_GET_REG(reg_set->regs[c].reg) != IREG_INVALID && !ir_get_refcount(reg_set->regs[c])) + break; + } + if (c == reg_set->nr_regs) { + /*Search for any unlocked register*/ + for (c = 0; c < reg_set->nr_regs; c++) { + if (!(reg_set->locked & (1 << c))) + break; + } +#ifndef RELEASE_BUILD + if (c == reg_set->nr_regs) + fatal("codegen_reg_alloc_read_reg - out of registers\n"); +#endif + } + if (reg_set->dirty[c]) + codegen_reg_writeback(reg_set, block, c, 1); + codegen_reg_load(reg_set, block, c, ir_reg); + reg_set->locked |= (1 << c); + reg_set->dirty[c] = 0; + } + + reg_version[IREG_GET_REG(reg_set->regs[c].reg)][reg_set->regs[c].version].refcount--; +#ifndef RELEASE_BUILD + if (reg_version[IREG_GET_REG(reg_set->regs[c].reg)][reg_set->regs[c].version].refcount == (uint8_t) -1) + fatal("codegen_reg_alloc_read_reg - refcount < 0\n"); +#endif + + if (host_reg_idx) + *host_reg_idx = c; + return reg_set->reg_list[c].reg | IREG_GET_SIZE(ir_reg.reg); } -ir_host_reg_t codegen_reg_alloc_read_reg(codeblock_t *block, ir_reg_t ir_reg, int *host_reg_idx) +ir_host_reg_t +codegen_reg_alloc_write_reg(codeblock_t *block, ir_reg_t ir_reg) { - host_reg_set_t *reg_set = get_reg_set(ir_reg); - int c; + host_reg_set_t *reg_set = get_reg_set(ir_reg); + int c; - /*Search for required register*/ - for (c = 0; c < reg_set->nr_regs; c++) - { - if (!ir_reg_is_invalid(reg_set->regs[c]) && IREG_GET_REG(reg_set->regs[c].reg) == IREG_GET_REG(ir_reg.reg) && reg_set->regs[c].version == ir_reg.version) - break; + if (!reg_is_native_size(ir_reg)) { + /*Read in parent register so we can do partial accesses to it*/ + ir_reg_t parent_reg; - if (!ir_reg_is_invalid(reg_set->regs[c]) && IREG_GET_REG(reg_set->regs[c].reg) == IREG_GET_REG(ir_reg.reg) && reg_set->regs[c].version <= ir_reg.version) - { - reg_version[IREG_GET_REG(reg_set->regs[c].reg)][reg_set->regs[c].version].refcount++; - break; - } + parent_reg.reg = IREG_GET_REG(ir_reg.reg) | IREG_SIZE_L; + parent_reg.version = ir_reg.version - 1; + reg_version[IREG_GET_REG(ir_reg.reg)][ir_reg.version - 1].refcount++; + + codegen_reg_alloc_read_reg(block, parent_reg, &c); #ifndef RELEASE_BUILD - if (!ir_reg_is_invalid(reg_set->regs[c]) && IREG_GET_REG(reg_set->regs[c].reg) == IREG_GET_REG(ir_reg.reg) && reg_version[IREG_GET_REG(reg_set->regs[c].reg)][reg_set->regs[c].version].refcount) - fatal("codegen_reg_alloc_read_reg - version mismatch!\n"); -#endif - } - - if (c == reg_set->nr_regs) - { - /*No unused registers. Search for an unlocked register with no pending reads*/ - for (c = 0; c < reg_set->nr_regs; c++) - { - if (!(reg_set->locked & (1 << c)) && IREG_GET_REG(reg_set->regs[c].reg) != IREG_INVALID && !ir_get_refcount(reg_set->regs[c])) - break; - } - if (c == reg_set->nr_regs) - { - /*Search for any unlocked register*/ - for (c = 0; c < reg_set->nr_regs; c++) - { - if (!(reg_set->locked & (1 << c))) - break; - } -#ifndef RELEASE_BUILD - if (c == reg_set->nr_regs) - fatal("codegen_reg_alloc_read_reg - out of registers\n"); -#endif - } - if (reg_set->dirty[c]) - codegen_reg_writeback(reg_set, block, c, 1); - codegen_reg_load(reg_set, block, c, ir_reg); - reg_set->locked |= (1 << c); - reg_set->dirty[c] = 0; - } - - reg_version[IREG_GET_REG(reg_set->regs[c].reg)][reg_set->regs[c].version].refcount--; -#ifndef RELEASE_BUILD - if (reg_version[IREG_GET_REG(reg_set->regs[c].reg)][reg_set->regs[c].version].refcount == (uint8_t)-1) - fatal("codegen_reg_alloc_read_reg - refcount < 0\n"); + if (IREG_GET_REG(reg_set->regs[c].reg) != IREG_GET_REG(ir_reg.reg) || reg_set->regs[c].version > ir_reg.version - 1) + fatal("codegen_reg_alloc_write_reg sub_reg - doesn't match %i %02x.%i %02x.%i\n", c, + reg_set->regs[c].reg, reg_set->regs[c].version, + ir_reg.reg, ir_reg.version); #endif - if (host_reg_idx) - *host_reg_idx = c; - return reg_set->reg_list[c].reg | IREG_GET_SIZE(ir_reg.reg); -} - -ir_host_reg_t codegen_reg_alloc_write_reg(codeblock_t *block, ir_reg_t ir_reg) -{ - host_reg_set_t *reg_set = get_reg_set(ir_reg); - int c; - - if (!reg_is_native_size(ir_reg)) - { - /*Read in parent register so we can do partial accesses to it*/ - ir_reg_t parent_reg; - - parent_reg.reg = IREG_GET_REG(ir_reg.reg) | IREG_SIZE_L; - parent_reg.version = ir_reg.version - 1; - reg_version[IREG_GET_REG(ir_reg.reg)][ir_reg.version - 1].refcount++; - - codegen_reg_alloc_read_reg(block, parent_reg, &c); - -#ifndef RELEASE_BUILD - if (IREG_GET_REG(reg_set->regs[c].reg) != IREG_GET_REG(ir_reg.reg) || reg_set->regs[c].version > ir_reg.version-1) - fatal("codegen_reg_alloc_write_reg sub_reg - doesn't match %i %02x.%i %02x.%i\n", c, - reg_set->regs[c].reg,reg_set->regs[c].version, - ir_reg.reg,ir_reg.version); -#endif - - reg_set->regs[c].reg = ir_reg.reg; - reg_set->regs[c].version = ir_reg.version; - reg_set->dirty[c] = 1; - return reg_set->reg_list[c].reg | IREG_GET_SIZE(ir_reg.reg); - } - - /*Search for previous version in host register*/ - for (c = 0; c < reg_set->nr_regs; c++) - { - if (!ir_reg_is_invalid(reg_set->regs[c]) && IREG_GET_REG(reg_set->regs[c].reg) == IREG_GET_REG(ir_reg.reg)) - { - if (reg_set->regs[c].version <= ir_reg.version-1) - { -#ifndef RELEASE_BUILD - if (reg_version[IREG_GET_REG(reg_set->regs[c].reg)][reg_set->regs[c].version].refcount != 0) - fatal("codegen_reg_alloc_write_reg - previous version refcount != 0\n"); -#endif - break; - } - } - } - - if (c == reg_set->nr_regs) - { - /*Search for unused registers*/ - for (c = 0; c < reg_set->nr_regs; c++) - { - if (ir_reg_is_invalid(reg_set->regs[c])) - break; - } - - if (c == reg_set->nr_regs) - { - /*No unused registers. Search for an unlocked register*/ - for (c = 0; c < reg_set->nr_regs; c++) - { - if (!(reg_set->locked & (1 << c))) - break; - } -#ifndef RELEASE_BUILD - if (c == reg_set->nr_regs) - fatal("codegen_reg_alloc_write_reg - out of registers\n"); -#endif - if (reg_set->dirty[c]) - codegen_reg_writeback(reg_set, block, c, 1); - } - } - - reg_set->regs[c].reg = ir_reg.reg; + reg_set->regs[c].reg = ir_reg.reg; reg_set->regs[c].version = ir_reg.version; - reg_set->dirty[c] = 1; + reg_set->dirty[c] = 1; return reg_set->reg_list[c].reg | IREG_GET_SIZE(ir_reg.reg); + } + + /*Search for previous version in host register*/ + for (c = 0; c < reg_set->nr_regs; c++) { + if (!ir_reg_is_invalid(reg_set->regs[c]) && IREG_GET_REG(reg_set->regs[c].reg) == IREG_GET_REG(ir_reg.reg)) { + if (reg_set->regs[c].version <= ir_reg.version - 1) { +#ifndef RELEASE_BUILD + if (reg_version[IREG_GET_REG(reg_set->regs[c].reg)][reg_set->regs[c].version].refcount != 0) + fatal("codegen_reg_alloc_write_reg - previous version refcount != 0\n"); +#endif + break; + } + } + } + + if (c == reg_set->nr_regs) { + /*Search for unused registers*/ + for (c = 0; c < reg_set->nr_regs; c++) { + if (ir_reg_is_invalid(reg_set->regs[c])) + break; + } + + if (c == reg_set->nr_regs) { + /*No unused registers. Search for an unlocked register*/ + for (c = 0; c < reg_set->nr_regs; c++) { + if (!(reg_set->locked & (1 << c))) + break; + } +#ifndef RELEASE_BUILD + if (c == reg_set->nr_regs) + fatal("codegen_reg_alloc_write_reg - out of registers\n"); +#endif + if (reg_set->dirty[c]) + codegen_reg_writeback(reg_set, block, c, 1); + } + } + + reg_set->regs[c].reg = ir_reg.reg; + reg_set->regs[c].version = ir_reg.version; + reg_set->dirty[c] = 1; + return reg_set->reg_list[c].reg | IREG_GET_SIZE(ir_reg.reg); } #ifdef CODEGEN_BACKEND_HAS_MOV_IMM -int codegen_reg_is_loaded(ir_reg_t ir_reg) +int +codegen_reg_is_loaded(ir_reg_t ir_reg) { - host_reg_set_t *reg_set = get_reg_set(ir_reg); - int c; + const host_reg_set_t *reg_set = get_reg_set(ir_reg); - /*Search for previous version in host register*/ - for (c = 0; c < reg_set->nr_regs; c++) - { - if (!ir_reg_is_invalid(reg_set->regs[c]) && IREG_GET_REG(reg_set->regs[c].reg) == IREG_GET_REG(ir_reg.reg)) - { - if (reg_set->regs[c].version <= ir_reg.version-1) - { + /*Search for previous version in host register*/ + for (int c = 0; c < reg_set->nr_regs; c++) { + if (!ir_reg_is_invalid(reg_set->regs[c]) && IREG_GET_REG(reg_set->regs[c].reg) == IREG_GET_REG(ir_reg.reg)) { + if (reg_set->regs[c].version <= ir_reg.version - 1) { +# ifndef RELEASE_BUILD + if (reg_version[IREG_GET_REG(reg_set->regs[c].reg)][reg_set->regs[c].version].refcount != 0) + fatal("codegen_reg_alloc_write_reg - previous version refcount != 0\n"); +# endif + return 1; + } + } + } + return 0; +} +#endif + +void +codegen_reg_rename(codeblock_t *block, ir_reg_t src, ir_reg_t dst) +{ + host_reg_set_t *reg_set = get_reg_set(src); + int c; + int target; + +#if 0 + pclog("rename: %i.%i -> %i.%i\n", src.reg,src.version, dst.reg, dst.version); +#endif + + /*Search for required register*/ + for (c = 0; c < reg_set->nr_regs; c++) { + if (!ir_reg_is_invalid(reg_set->regs[c]) && IREG_GET_REG(reg_set->regs[c].reg) == IREG_GET_REG(src.reg) && reg_set->regs[c].version == src.version) + break; + } #ifndef RELEASE_BUILD - if (reg_version[IREG_GET_REG(reg_set->regs[c].reg)][reg_set->regs[c].version].refcount != 0) - fatal("codegen_reg_alloc_write_reg - previous version refcount != 0\n"); + if (c == reg_set->nr_regs) + fatal("codegen_reg_rename: Can't find register to rename\n"); #endif - return 1; - } - } - } - return 0; -} + target = c; + if (reg_set->dirty[target]) + codegen_reg_writeback(reg_set, block, target, 0); + reg_set->regs[target] = dst; + reg_set->dirty[target] = 1; +#if 0 + pclog("renamed reg %i dest=%i.%i\n", target, dst.reg, dst.version); #endif -void codegen_reg_rename(codeblock_t *block, ir_reg_t src, ir_reg_t dst) -{ - host_reg_set_t *reg_set = get_reg_set(src); - int c; - int target; - -// pclog("rename: %i.%i -> %i.%i\n", src.reg,src.version, dst.reg, dst.version); - /*Search for required register*/ - for (c = 0; c < reg_set->nr_regs; c++) - { - if (!ir_reg_is_invalid(reg_set->regs[c]) && IREG_GET_REG(reg_set->regs[c].reg) == IREG_GET_REG(src.reg) && reg_set->regs[c].version == src.version) - break; - } -#ifndef RELEASE_BUILD - if (c == reg_set->nr_regs) - fatal("codegen_reg_rename: Can't find register to rename\n"); -#endif - target = c; - if (reg_set->dirty[target]) - codegen_reg_writeback(reg_set, block, target, 0); - reg_set->regs[target] = dst; - reg_set->dirty[target] = 1; -// pclog("renamed reg %i dest=%i.%i\n", target, dst.reg, dst.version); - - /*Invalidate any stale copies of the dest register*/ - for (c = 0; c < reg_set->nr_regs; c++) - { - if (c == target) - continue; - if (!ir_reg_is_invalid(reg_set->regs[c]) && IREG_GET_REG(reg_set->regs[c].reg) == IREG_GET_REG(dst.reg)) - { - reg_set->regs[c] = invalid_ir_reg; - reg_set->dirty[c] = 0; - } + /*Invalidate any stale copies of the dest register*/ + for (c = 0; c < reg_set->nr_regs; c++) { + if (c == target) + continue; + if (!ir_reg_is_invalid(reg_set->regs[c]) && IREG_GET_REG(reg_set->regs[c].reg) == IREG_GET_REG(dst.reg)) { + reg_set->regs[c] = invalid_ir_reg; + reg_set->dirty[c] = 0; } + } } -void codegen_reg_flush(ir_data_t *ir, codeblock_t *block) +void +codegen_reg_flush(UNUSED(ir_data_t *ir), codeblock_t *block) { - host_reg_set_t *reg_set; - int c; - - reg_set = &host_reg_set; - for (c = 0; c < reg_set->nr_regs; c++) - { - if (!ir_reg_is_invalid(reg_set->regs[c]) && reg_set->dirty[c]) - { - codegen_reg_writeback(reg_set, block, c, 0); - } - if (reg_set->reg_list[c].flags & HOST_REG_FLAG_VOLATILE) - { - reg_set->regs[c] = invalid_ir_reg; - reg_set->dirty[c] = 0; - } - } + host_reg_set_t *reg_set; + int c; - reg_set = &host_fp_reg_set; - for (c = 0; c < reg_set->nr_regs; c++) - { - if (!ir_reg_is_invalid(reg_set->regs[c]) && reg_set->dirty[c]) - { - codegen_reg_writeback(reg_set, block, c, 0); - } - if (reg_set->reg_list[c].flags & HOST_REG_FLAG_VOLATILE) - { - reg_set->regs[c] = invalid_ir_reg; - reg_set->dirty[c] = 0; - } + reg_set = &host_reg_set; + for (c = 0; c < reg_set->nr_regs; c++) { + if (!ir_reg_is_invalid(reg_set->regs[c]) && reg_set->dirty[c]) { + codegen_reg_writeback(reg_set, block, c, 0); } + if (reg_set->reg_list[c].flags & HOST_REG_FLAG_VOLATILE) { + reg_set->regs[c] = invalid_ir_reg; + reg_set->dirty[c] = 0; + } + } + + reg_set = &host_fp_reg_set; + for (c = 0; c < reg_set->nr_regs; c++) { + if (!ir_reg_is_invalid(reg_set->regs[c]) && reg_set->dirty[c]) { + codegen_reg_writeback(reg_set, block, c, 0); + } + if (reg_set->reg_list[c].flags & HOST_REG_FLAG_VOLATILE) { + reg_set->regs[c] = invalid_ir_reg; + reg_set->dirty[c] = 0; + } + } } -void codegen_reg_flush_invalidate(ir_data_t *ir, codeblock_t *block) +void +codegen_reg_flush_invalidate(UNUSED(ir_data_t *ir), codeblock_t *block) { - host_reg_set_t *reg_set; - int c; - - reg_set = &host_reg_set; - for (c = 0; c < reg_set->nr_regs; c++) - { - if (!ir_reg_is_invalid(reg_set->regs[c]) && reg_set->dirty[c]) - { - codegen_reg_writeback(reg_set, block, c, 1); - } - reg_set->regs[c] = invalid_ir_reg; - reg_set->dirty[c] = 0; - } + host_reg_set_t *reg_set; + int c; - reg_set = &host_fp_reg_set; - for (c = 0; c < reg_set->nr_regs; c++) - { - if (!ir_reg_is_invalid(reg_set->regs[c]) && reg_set->dirty[c]) - { - codegen_reg_writeback(reg_set, block, c, 1); - } - reg_set->regs[c] = invalid_ir_reg; - reg_set->dirty[c] = 0; + reg_set = &host_reg_set; + for (c = 0; c < reg_set->nr_regs; c++) { + if (!ir_reg_is_invalid(reg_set->regs[c]) && reg_set->dirty[c]) { + codegen_reg_writeback(reg_set, block, c, 1); } + reg_set->regs[c] = invalid_ir_reg; + reg_set->dirty[c] = 0; + } + + reg_set = &host_fp_reg_set; + for (c = 0; c < reg_set->nr_regs; c++) { + if (!ir_reg_is_invalid(reg_set->regs[c]) && reg_set->dirty[c]) { + codegen_reg_writeback(reg_set, block, c, 1); + } + reg_set->regs[c] = invalid_ir_reg; + reg_set->dirty[c] = 0; + } } /*Process dead register list, and optimise out register versions and uOPs where possible*/ -void codegen_reg_process_dead_list(ir_data_t *ir) +void +codegen_reg_process_dead_list(ir_data_t *ir) { - while (reg_dead_list) - { - int version = reg_dead_list & 0xff; - int reg = reg_dead_list >> 8; - reg_version_t *regv = ®_version[reg][version]; - uop_t *uop = &ir->uops[regv->parent_uop]; + while (reg_dead_list) { + int version = reg_dead_list & 0xff; + int reg = reg_dead_list >> 8; + reg_version_t *regv = ®_version[reg][version]; + uop_t *uop = &ir->uops[regv->parent_uop]; - /*Barrier uOPs should be preserved*/ - if (!(uop->type & (UOP_TYPE_BARRIER | UOP_TYPE_ORDER_BARRIER))) - { - uop->type = UOP_INVALID; - /*Adjust refcounts on source registers. If these drop to - zero then those registers can be considered for removal*/ - if (uop->src_reg_a.reg != IREG_INVALID) - { - reg_version_t *src_regv = ®_version[IREG_GET_REG(uop->src_reg_a.reg)][uop->src_reg_a.version]; - src_regv->refcount--; - if (!src_regv->refcount) - add_to_dead_list(src_regv, IREG_GET_REG(uop->src_reg_a.reg), uop->src_reg_a.version); - } - if (uop->src_reg_b.reg != IREG_INVALID) - { - reg_version_t *src_regv = ®_version[IREG_GET_REG(uop->src_reg_b.reg)][uop->src_reg_b.version]; - src_regv->refcount--; - if (!src_regv->refcount) - add_to_dead_list(src_regv, IREG_GET_REG(uop->src_reg_b.reg), uop->src_reg_b.version); - } - if (uop->src_reg_c.reg != IREG_INVALID) - { - reg_version_t *src_regv = ®_version[IREG_GET_REG(uop->src_reg_c.reg)][uop->src_reg_c.version]; - src_regv->refcount--; - if (!src_regv->refcount) - add_to_dead_list(src_regv, IREG_GET_REG(uop->src_reg_c.reg), uop->src_reg_c.version); - } - regv->flags |= REG_FLAGS_DEAD; - } - - reg_dead_list = regv->next; + /*Barrier uOPs should be preserved*/ + if (!(uop->type & (UOP_TYPE_BARRIER | UOP_TYPE_ORDER_BARRIER))) { + uop->type = UOP_INVALID; + /*Adjust refcounts on source registers. If these drop to + zero then those registers can be considered for removal*/ + if (uop->src_reg_a.reg != IREG_INVALID) { + reg_version_t *src_regv = ®_version[IREG_GET_REG(uop->src_reg_a.reg)][uop->src_reg_a.version]; + src_regv->refcount--; + if (!src_regv->refcount) + add_to_dead_list(src_regv, IREG_GET_REG(uop->src_reg_a.reg), uop->src_reg_a.version); + } + if (uop->src_reg_b.reg != IREG_INVALID) { + reg_version_t *src_regv = ®_version[IREG_GET_REG(uop->src_reg_b.reg)][uop->src_reg_b.version]; + src_regv->refcount--; + if (!src_regv->refcount) + add_to_dead_list(src_regv, IREG_GET_REG(uop->src_reg_b.reg), uop->src_reg_b.version); + } + if (uop->src_reg_c.reg != IREG_INVALID) { + reg_version_t *src_regv = ®_version[IREG_GET_REG(uop->src_reg_c.reg)][uop->src_reg_c.version]; + src_regv->refcount--; + if (!src_regv->refcount) + add_to_dead_list(src_regv, IREG_GET_REG(uop->src_reg_c.reg), uop->src_reg_c.version); + } + regv->flags |= REG_FLAGS_DEAD; } + + reg_dead_list = regv->next; + } } diff --git a/src/codegen_new/codegen_reg.h b/src/codegen_new/codegen_reg.h index 8bb84e5f9..ebb90b42f 100644 --- a/src/codegen_new/codegen_reg.h +++ b/src/codegen_new/codegen_reg.h @@ -1,276 +1,278 @@ #ifndef _CODEGEN_REG_H_ #define _CODEGEN_REG_H_ -#define IREG_REG_MASK 0xff -#define IREG_SIZE_SHIFT 8 -#define IREG_SIZE_MASK (7 << IREG_SIZE_SHIFT) +#define IREG_REG_MASK 0xff +#define IREG_SIZE_SHIFT 8 +#define IREG_SIZE_MASK (7 << IREG_SIZE_SHIFT) -#define IREG_GET_REG(reg) ((reg) & IREG_REG_MASK) -#define IREG_GET_SIZE(reg) ((reg) & IREG_SIZE_MASK) +#define IREG_GET_REG(reg) ((reg) &IREG_REG_MASK) +#define IREG_GET_SIZE(reg) ((reg) &IREG_SIZE_MASK) -#define IREG_SIZE_L (0 << IREG_SIZE_SHIFT) -#define IREG_SIZE_W (1 << IREG_SIZE_SHIFT) -#define IREG_SIZE_B (2 << IREG_SIZE_SHIFT) -#define IREG_SIZE_BH (3 << IREG_SIZE_SHIFT) -#define IREG_SIZE_D (4 << IREG_SIZE_SHIFT) -#define IREG_SIZE_Q (5 << IREG_SIZE_SHIFT) +#define IREG_SIZE_L (0 << IREG_SIZE_SHIFT) +#define IREG_SIZE_W (1 << IREG_SIZE_SHIFT) +#define IREG_SIZE_B (2 << IREG_SIZE_SHIFT) +#define IREG_SIZE_BH (3 << IREG_SIZE_SHIFT) +#define IREG_SIZE_D (4 << IREG_SIZE_SHIFT) +#define IREG_SIZE_Q (5 << IREG_SIZE_SHIFT) -enum -{ - IREG_EAX = 0, - IREG_ECX = 1, - IREG_EDX = 2, - IREG_EBX = 3, - IREG_ESP = 4, - IREG_EBP = 5, - IREG_ESI = 6, - IREG_EDI = 7, +enum { + IREG_EAX = 0, + IREG_ECX = 1, + IREG_EDX = 2, + IREG_EBX = 3, + IREG_ESP = 4, + IREG_EBP = 5, + IREG_ESI = 6, + IREG_EDI = 7, - IREG_flags_op = 8, - IREG_flags_res = 9, - IREG_flags_op1 = 10, - IREG_flags_op2 = 11, + IREG_flags_op = 8, + IREG_flags_res = 9, + IREG_flags_op1 = 10, + IREG_flags_op2 = 11, - IREG_pc = 12, - IREG_oldpc = 13, + IREG_pc = 12, + IREG_oldpc = 13, - IREG_eaaddr = 14, - IREG_ea_seg = 15, - IREG_op32 = 16, - IREG_ssegsx = 17, - - IREG_rm_mod_reg = 18, - - IREG_acycs = 19, - IREG_cycles = 20, + IREG_eaaddr = 14, + IREG_ea_seg = 15, + IREG_op32 = 16, + IREG_ssegsx = 17, - IREG_CS_base = 21, - IREG_DS_base = 22, - IREG_ES_base = 23, - IREG_FS_base = 24, - IREG_GS_base = 25, - IREG_SS_base = 26, + IREG_rm_mod_reg = 18, - IREG_CS_seg = 27, - IREG_DS_seg = 28, - IREG_ES_seg = 29, - IREG_FS_seg = 30, - IREG_GS_seg = 31, - IREG_SS_seg = 32, + IREG_acycs = 19, + IREG_cycles = 20, - /*Temporary registers are stored on the stack, and are not guaranteed to - be preserved across uOPs. They will not be written back if they will - not be read again.*/ - IREG_temp0 = 33, - IREG_temp1 = 34, - IREG_temp2 = 35, - IREG_temp3 = 36, + IREG_CS_base = 21, + IREG_DS_base = 22, + IREG_ES_base = 23, + IREG_FS_base = 24, + IREG_GS_base = 25, + IREG_SS_base = 26, - IREG_FPU_TOP = 37, + IREG_CS_seg = 27, + IREG_DS_seg = 28, + IREG_ES_seg = 29, + IREG_FS_seg = 30, + IREG_GS_seg = 31, + IREG_SS_seg = 32, - IREG_temp0d = 38, - IREG_temp1d = 39, - - /*FPU stack registers are physical registers. Use IREG_ST() / IREG_tag() - to access. - When CODEBLOCK_STATIC_TOP is set, the physical register number will be - used directly to index the stack. When it is clear, the difference - between the current value of TOP and the value when the block was - first compiled will be added to adjust for any changes in TOP.*/ - IREG_ST0 = 40, - IREG_ST1 = 41, - IREG_ST2 = 42, - IREG_ST3 = 43, - IREG_ST4 = 44, - IREG_ST5 = 45, - IREG_ST6 = 46, - IREG_ST7 = 47, - - IREG_tag0 = 48, - IREG_tag1 = 49, - IREG_tag2 = 50, - IREG_tag3 = 51, - IREG_tag4 = 52, - IREG_tag5 = 53, - IREG_tag6 = 54, - IREG_tag7 = 55, + /*Temporary registers are stored on the stack, and are not guaranteed to + be preserved across uOPs. They will not be written back if they will + not be read again.*/ + IREG_temp0 = 33, + IREG_temp1 = 34, + IREG_temp2 = 35, + IREG_temp3 = 36, - IREG_ST0_i64 = 56, - IREG_ST1_i64 = 57, - IREG_ST2_i64 = 58, - IREG_ST3_i64 = 59, - IREG_ST4_i64 = 60, - IREG_ST5_i64 = 61, - IREG_ST6_i64 = 62, - IREG_ST7_i64 = 63, - - IREG_MM0x = 64, - IREG_MM1x = 65, - IREG_MM2x = 66, - IREG_MM3x = 67, - IREG_MM4x = 68, - IREG_MM5x = 69, - IREG_MM6x = 70, - IREG_MM7x = 71, - - IREG_NPXCx = 72, - IREG_NPXSx = 73, - - IREG_flagsx = 74, - IREG_eflagsx = 75, - - IREG_CS_limit_low = 76, - IREG_DS_limit_low = 77, - IREG_ES_limit_low = 78, - IREG_FS_limit_low = 79, - IREG_GS_limit_low = 80, - IREG_SS_limit_low = 81, + IREG_FPU_TOP = 37, - IREG_CS_limit_high = 82, - IREG_DS_limit_high = 83, - IREG_ES_limit_high = 84, - IREG_FS_limit_high = 85, - IREG_GS_limit_high = 86, - IREG_SS_limit_high = 87, + IREG_temp0d = 38, + IREG_temp1d = 39, - IREG_COUNT = 88, - - IREG_INVALID = 255, - - IREG_AX = IREG_EAX + IREG_SIZE_W, - IREG_CX = IREG_ECX + IREG_SIZE_W, - IREG_DX = IREG_EDX + IREG_SIZE_W, - IREG_BX = IREG_EBX + IREG_SIZE_W, - IREG_SP = IREG_ESP + IREG_SIZE_W, - IREG_BP = IREG_EBP + IREG_SIZE_W, - IREG_SI = IREG_ESI + IREG_SIZE_W, - IREG_DI = IREG_EDI + IREG_SIZE_W, + /*FPU stack registers are physical registers. Use IREG_ST() / IREG_tag() + to access. + When CODEBLOCK_STATIC_TOP is set, the physical register number will be + used directly to index the stack. When it is clear, the difference + between the current value of TOP and the value when the block was + first compiled will be added to adjust for any changes in TOP.*/ + IREG_ST0 = 40, + IREG_ST1 = 41, + IREG_ST2 = 42, + IREG_ST3 = 43, + IREG_ST4 = 44, + IREG_ST5 = 45, + IREG_ST6 = 46, + IREG_ST7 = 47, - IREG_AL = IREG_EAX + IREG_SIZE_B, - IREG_CL = IREG_ECX + IREG_SIZE_B, - IREG_DL = IREG_EDX + IREG_SIZE_B, - IREG_BL = IREG_EBX + IREG_SIZE_B, + IREG_tag0 = 48, + IREG_tag1 = 49, + IREG_tag2 = 50, + IREG_tag3 = 51, + IREG_tag4 = 52, + IREG_tag5 = 53, + IREG_tag6 = 54, + IREG_tag7 = 55, - IREG_AH = IREG_EAX + IREG_SIZE_BH, - IREG_CH = IREG_ECX + IREG_SIZE_BH, - IREG_DH = IREG_EDX + IREG_SIZE_BH, - IREG_BH = IREG_EBX + IREG_SIZE_BH, - - IREG_flags_res_W = IREG_flags_res + IREG_SIZE_W, - IREG_flags_op1_W = IREG_flags_op1 + IREG_SIZE_W, - IREG_flags_op2_W = IREG_flags_op2 + IREG_SIZE_W, + IREG_ST0_i64 = 56, + IREG_ST1_i64 = 57, + IREG_ST2_i64 = 58, + IREG_ST3_i64 = 59, + IREG_ST4_i64 = 60, + IREG_ST5_i64 = 61, + IREG_ST6_i64 = 62, + IREG_ST7_i64 = 63, - IREG_flags_res_B = IREG_flags_res + IREG_SIZE_B, - IREG_flags_op1_B = IREG_flags_op1 + IREG_SIZE_B, - IREG_flags_op2_B = IREG_flags_op2 + IREG_SIZE_B, + IREG_MM0x = 64, + IREG_MM1x = 65, + IREG_MM2x = 66, + IREG_MM3x = 67, + IREG_MM4x = 68, + IREG_MM5x = 69, + IREG_MM6x = 70, + IREG_MM7x = 71, - IREG_temp0_W = IREG_temp0 + IREG_SIZE_W, - IREG_temp1_W = IREG_temp1 + IREG_SIZE_W, - IREG_temp2_W = IREG_temp2 + IREG_SIZE_W, - IREG_temp3_W = IREG_temp3 + IREG_SIZE_W, - - IREG_temp0_B = IREG_temp0 + IREG_SIZE_B, - IREG_temp1_B = IREG_temp1 + IREG_SIZE_B, - IREG_temp2_B = IREG_temp2 + IREG_SIZE_B, - IREG_temp3_B = IREG_temp3 + IREG_SIZE_B, + IREG_NPXCx = 72, + IREG_NPXSx = 73, - IREG_temp0_D = IREG_temp0d + IREG_SIZE_D, - IREG_temp1_D = IREG_temp1d + IREG_SIZE_D, + IREG_flagsx = 74, + IREG_eflagsx = 75, - IREG_temp0_Q = IREG_temp0d + IREG_SIZE_Q, - IREG_temp1_Q = IREG_temp1d + IREG_SIZE_Q, + IREG_CS_limit_low = 76, + IREG_DS_limit_low = 77, + IREG_ES_limit_low = 78, + IREG_FS_limit_low = 79, + IREG_GS_limit_low = 80, + IREG_SS_limit_low = 81, - IREG_eaaddr_W = IREG_eaaddr + IREG_SIZE_W, - - IREG_CS_seg_W = IREG_CS_seg + IREG_SIZE_W, - IREG_DS_seg_W = IREG_DS_seg + IREG_SIZE_W, - IREG_ES_seg_W = IREG_ES_seg + IREG_SIZE_W, - IREG_FS_seg_W = IREG_FS_seg + IREG_SIZE_W, - IREG_GS_seg_W = IREG_GS_seg + IREG_SIZE_W, - IREG_SS_seg_W = IREG_SS_seg + IREG_SIZE_W, - - IREG_MM0 = IREG_MM0x + IREG_SIZE_Q, - IREG_MM1 = IREG_MM1x + IREG_SIZE_Q, - IREG_MM2 = IREG_MM2x + IREG_SIZE_Q, - IREG_MM3 = IREG_MM3x + IREG_SIZE_Q, - IREG_MM4 = IREG_MM4x + IREG_SIZE_Q, - IREG_MM5 = IREG_MM5x + IREG_SIZE_Q, - IREG_MM6 = IREG_MM6x + IREG_SIZE_Q, - IREG_MM7 = IREG_MM7x + IREG_SIZE_Q, - - IREG_NPXC = IREG_NPXCx + IREG_SIZE_W, - IREG_NPXS = IREG_NPXSx + IREG_SIZE_W, - - IREG_ssegs = IREG_ssegsx + IREG_SIZE_B, - - IREG_flags = IREG_flagsx + IREG_SIZE_W, - IREG_eflags = IREG_eflagsx + IREG_SIZE_W + IREG_CS_limit_high = 82, + IREG_DS_limit_high = 83, + IREG_ES_limit_high = 84, + IREG_FS_limit_high = 85, + IREG_GS_limit_high = 86, + IREG_SS_limit_high = 87, + + IREG_COUNT = 88, + + IREG_INVALID = 255, + + IREG_AX = IREG_EAX + IREG_SIZE_W, + IREG_CX = IREG_ECX + IREG_SIZE_W, + IREG_DX = IREG_EDX + IREG_SIZE_W, + IREG_BX = IREG_EBX + IREG_SIZE_W, + IREG_SP = IREG_ESP + IREG_SIZE_W, + IREG_BP = IREG_EBP + IREG_SIZE_W, + IREG_SI = IREG_ESI + IREG_SIZE_W, + IREG_DI = IREG_EDI + IREG_SIZE_W, + + IREG_AL = IREG_EAX + IREG_SIZE_B, + IREG_CL = IREG_ECX + IREG_SIZE_B, + IREG_DL = IREG_EDX + IREG_SIZE_B, + IREG_BL = IREG_EBX + IREG_SIZE_B, + + IREG_AH = IREG_EAX + IREG_SIZE_BH, + IREG_CH = IREG_ECX + IREG_SIZE_BH, + IREG_DH = IREG_EDX + IREG_SIZE_BH, + IREG_BH = IREG_EBX + IREG_SIZE_BH, + + IREG_flags_res_W = IREG_flags_res + IREG_SIZE_W, + IREG_flags_op1_W = IREG_flags_op1 + IREG_SIZE_W, + IREG_flags_op2_W = IREG_flags_op2 + IREG_SIZE_W, + + IREG_flags_res_B = IREG_flags_res + IREG_SIZE_B, + IREG_flags_op1_B = IREG_flags_op1 + IREG_SIZE_B, + IREG_flags_op2_B = IREG_flags_op2 + IREG_SIZE_B, + + IREG_temp0_W = IREG_temp0 + IREG_SIZE_W, + IREG_temp1_W = IREG_temp1 + IREG_SIZE_W, + IREG_temp2_W = IREG_temp2 + IREG_SIZE_W, + IREG_temp3_W = IREG_temp3 + IREG_SIZE_W, + + IREG_temp0_B = IREG_temp0 + IREG_SIZE_B, + IREG_temp1_B = IREG_temp1 + IREG_SIZE_B, + IREG_temp2_B = IREG_temp2 + IREG_SIZE_B, + IREG_temp3_B = IREG_temp3 + IREG_SIZE_B, + + IREG_temp0_D = IREG_temp0d + IREG_SIZE_D, + IREG_temp1_D = IREG_temp1d + IREG_SIZE_D, + + IREG_temp0_Q = IREG_temp0d + IREG_SIZE_Q, + IREG_temp1_Q = IREG_temp1d + IREG_SIZE_Q, + + IREG_eaaddr_W = IREG_eaaddr + IREG_SIZE_W, + + IREG_CS_seg_W = IREG_CS_seg + IREG_SIZE_W, + IREG_DS_seg_W = IREG_DS_seg + IREG_SIZE_W, + IREG_ES_seg_W = IREG_ES_seg + IREG_SIZE_W, + IREG_FS_seg_W = IREG_FS_seg + IREG_SIZE_W, + IREG_GS_seg_W = IREG_GS_seg + IREG_SIZE_W, + IREG_SS_seg_W = IREG_SS_seg + IREG_SIZE_W, + + IREG_MM0 = IREG_MM0x + IREG_SIZE_Q, + IREG_MM1 = IREG_MM1x + IREG_SIZE_Q, + IREG_MM2 = IREG_MM2x + IREG_SIZE_Q, + IREG_MM3 = IREG_MM3x + IREG_SIZE_Q, + IREG_MM4 = IREG_MM4x + IREG_SIZE_Q, + IREG_MM5 = IREG_MM5x + IREG_SIZE_Q, + IREG_MM6 = IREG_MM6x + IREG_SIZE_Q, + IREG_MM7 = IREG_MM7x + IREG_SIZE_Q, + + IREG_NPXC = IREG_NPXCx + IREG_SIZE_W, + IREG_NPXS = IREG_NPXSx + IREG_SIZE_W, + + IREG_ssegs = IREG_ssegsx + IREG_SIZE_B, + + IREG_flags = IREG_flagsx + IREG_SIZE_W, + IREG_eflags = IREG_eflagsx + IREG_SIZE_W }; -#define IREG_8(reg) (((reg) & 4) ? (((reg) & 3) + IREG_AH) : ((reg) + IREG_AL)) -#define IREG_16(reg) ((reg) + IREG_AX) -#define IREG_32(reg) ((reg) + IREG_EAX) +#define IREG_8(reg) (((reg) &4) ? (((reg) &3) + IREG_AH) : ((reg) + IREG_AL)) +#define IREG_16(reg) ((reg) + IREG_AX) +#define IREG_32(reg) ((reg) + IREG_EAX) -#define IREG_ST(r) (IREG_ST0 + ((cpu_state.TOP + (r)) & 7) + IREG_SIZE_D) -#define IREG_ST_i64(r) (IREG_ST0_i64 + ((cpu_state.TOP + (r)) & 7) + IREG_SIZE_Q) -#define IREG_tag(r) (IREG_tag0 + ((cpu_state.TOP + (r)) & 7)) -#define IREG_tag_B(r) (IREG_tag0 + ((cpu_state.TOP + (r)) & 7) + IREG_SIZE_B) +#define IREG_ST(r) (IREG_ST0 + ((cpu_state.TOP + (r)) & 7) + IREG_SIZE_D) +#define IREG_ST_i64(r) (IREG_ST0_i64 + ((cpu_state.TOP + (r)) & 7) + IREG_SIZE_Q) +#define IREG_tag(r) (IREG_tag0 + ((cpu_state.TOP + (r)) & 7)) +#define IREG_tag_B(r) (IREG_tag0 + ((cpu_state.TOP + (r)) & 7) + IREG_SIZE_B) -#define IREG_MM(reg) ((reg) + IREG_MM0) +#define IREG_MM(reg) ((reg) + IREG_MM0) #define IREG_TOP_diff_stack_offset 32 -static inline int ireg_seg_base(x86seg *seg) +static inline int +ireg_seg_base(x86seg *seg) { - if (seg == &cpu_state.seg_cs) - return IREG_CS_base; - if (seg == &cpu_state.seg_ds) - return IREG_DS_base; - if (seg == &cpu_state.seg_es) - return IREG_ES_base; - if (seg == &cpu_state.seg_fs) - return IREG_FS_base; - if (seg == &cpu_state.seg_gs) - return IREG_GS_base; - if (seg == &cpu_state.seg_ss) - return IREG_SS_base; - fatal("ireg_seg_base : unknown segment\n"); - return 0; + if (seg == &cpu_state.seg_cs) + return IREG_CS_base; + if (seg == &cpu_state.seg_ds) + return IREG_DS_base; + if (seg == &cpu_state.seg_es) + return IREG_ES_base; + if (seg == &cpu_state.seg_fs) + return IREG_FS_base; + if (seg == &cpu_state.seg_gs) + return IREG_GS_base; + if (seg == &cpu_state.seg_ss) + return IREG_SS_base; + fatal("ireg_seg_base : unknown segment\n"); + return 0; } -static inline int ireg_seg_limit_low(x86seg *seg) +static inline int +ireg_seg_limit_low(x86seg *seg) { - if (seg == &cpu_state.seg_cs) - return IREG_CS_limit_low; - if (seg == &cpu_state.seg_ds) - return IREG_DS_limit_low; - if (seg == &cpu_state.seg_es) - return IREG_ES_limit_low; - if (seg == &cpu_state.seg_fs) - return IREG_FS_limit_low; - if (seg == &cpu_state.seg_gs) - return IREG_GS_limit_low; - if (seg == &cpu_state.seg_ss) - return IREG_SS_limit_low; - fatal("ireg_seg_limit_low : unknown segment\n"); - return 0; + if (seg == &cpu_state.seg_cs) + return IREG_CS_limit_low; + if (seg == &cpu_state.seg_ds) + return IREG_DS_limit_low; + if (seg == &cpu_state.seg_es) + return IREG_ES_limit_low; + if (seg == &cpu_state.seg_fs) + return IREG_FS_limit_low; + if (seg == &cpu_state.seg_gs) + return IREG_GS_limit_low; + if (seg == &cpu_state.seg_ss) + return IREG_SS_limit_low; + fatal("ireg_seg_limit_low : unknown segment\n"); + return 0; } -static inline int ireg_seg_limit_high(x86seg *seg) +static inline int +ireg_seg_limit_high(x86seg *seg) { - if (seg == &cpu_state.seg_cs) - return IREG_CS_limit_high; - if (seg == &cpu_state.seg_ds) - return IREG_DS_limit_high; - if (seg == &cpu_state.seg_es) - return IREG_ES_limit_high; - if (seg == &cpu_state.seg_fs) - return IREG_FS_limit_high; - if (seg == &cpu_state.seg_gs) - return IREG_GS_limit_high; - if (seg == &cpu_state.seg_ss) - return IREG_SS_limit_high; - fatal("ireg_seg_limit_high : unknown segment\n"); - return 0; + if (seg == &cpu_state.seg_cs) + return IREG_CS_limit_high; + if (seg == &cpu_state.seg_ds) + return IREG_DS_limit_high; + if (seg == &cpu_state.seg_es) + return IREG_ES_limit_high; + if (seg == &cpu_state.seg_fs) + return IREG_FS_limit_high; + if (seg == &cpu_state.seg_gs) + return IREG_GS_limit_high; + if (seg == &cpu_state.seg_ss) + return IREG_SS_limit_high; + fatal("ireg_seg_limit_high : unknown segment\n"); + return 0; } extern uint8_t reg_last_version[IREG_COUNT]; @@ -279,18 +281,17 @@ extern uint8_t reg_last_version[IREG_COUNT]; apparently required or not. Do not optimise out.*/ #define REG_FLAGS_REQUIRED (1 << 0) /*This register and the parent uOP have been optimised out.*/ -#define REG_FLAGS_DEAD (1 << 1) +#define REG_FLAGS_DEAD (1 << 1) -typedef struct -{ - /*Refcount of pending reads on this register version*/ - uint8_t refcount; - /*Flags*/ - uint8_t flags; - /*uOP that generated this register version*/ - uint16_t parent_uop; - /*Pointer to next register version in dead register list*/ - uint16_t next; +typedef struct { + /*Refcount of pending reads on this register version*/ + uint8_t refcount; + /*Flags*/ + uint8_t flags; + /*uOP that generated this register version*/ + uint16_t parent_uop; + /*Pointer to next register version in dead register list*/ + uint16_t next; } reg_version_t; extern reg_version_t reg_version[IREG_COUNT][256]; @@ -299,16 +300,16 @@ extern reg_version_t reg_version[IREG_COUNT][256]; can be optimised out*/ extern uint16_t reg_dead_list; -static inline void add_to_dead_list(reg_version_t *regv, int reg, int version) +static inline void +add_to_dead_list(reg_version_t *regv, int reg, int version) { - regv->next = reg_dead_list; - reg_dead_list = version | (reg << 8); + regv->next = reg_dead_list; + reg_dead_list = version | (reg << 8); } -typedef struct -{ - uint16_t reg; - uint16_t version; +typedef struct { + uint16_t reg; + uint16_t version; } ir_reg_t; extern ir_reg_t invalid_ir_reg; @@ -317,85 +318,90 @@ typedef uint16_t ir_host_reg_t; extern int max_version_refcount; -#define REG_VERSION_MAX 250 +#define REG_VERSION_MAX 250 #define REG_REFCOUNT_MAX 250 -static inline ir_reg_t codegen_reg_read(int reg) +static inline ir_reg_t +codegen_reg_read(int reg) { - ir_reg_t ireg; - reg_version_t *version; - + ir_reg_t ireg; + reg_version_t *version; + #ifndef RELEASE_BUILD - if (IREG_GET_REG(reg) == IREG_INVALID) - fatal("codegen_reg_read - IREG_INVALID\n"); + if (IREG_GET_REG(reg) == IREG_INVALID) + fatal("codegen_reg_read - IREG_INVALID\n"); #endif - ireg.reg = reg; - ireg.version = reg_last_version[IREG_GET_REG(reg)]; - version = ®_version[IREG_GET_REG(ireg.reg)][ireg.version]; - version->flags = 0; - version->refcount++; + ireg.reg = reg; + ireg.version = reg_last_version[IREG_GET_REG(reg)]; + version = ®_version[IREG_GET_REG(ireg.reg)][ireg.version]; + version->flags = 0; + version->refcount++; #ifndef RELEASE_BUILD - if (!version->refcount) - fatal("codegen_reg_read - refcount overflow\n"); - else + if (!version->refcount) + fatal("codegen_reg_read - refcount overflow\n"); + else #endif if (version->refcount > REG_REFCOUNT_MAX) - CPU_BLOCK_END(); - if (version->refcount > max_version_refcount) - max_version_refcount = version->refcount; -// pclog("codegen_reg_read: %i %i %i\n", reg & IREG_REG_MASK, ireg.version, reg_version_refcount[IREG_GET_REG(ireg.reg)][ireg.version]); - return ireg; + CPU_BLOCK_END(); + if (version->refcount > max_version_refcount) + max_version_refcount = version->refcount; +#if 0 + pclog("codegen_reg_read: %i %i %i\n", reg & IREG_REG_MASK, ireg.version, reg_version_refcount[IREG_GET_REG(ireg.reg)][ireg.version]); +#endif + return ireg; } int reg_is_native_size(ir_reg_t ir_reg); -static inline ir_reg_t codegen_reg_write(int reg, int uop_nr) +static inline ir_reg_t +codegen_reg_write(int reg, int uop_nr) { - ir_reg_t ireg; - int last_version = reg_last_version[IREG_GET_REG(reg)]; - reg_version_t *version; - + ir_reg_t ireg; + int last_version = reg_last_version[IREG_GET_REG(reg)]; + reg_version_t *version; + #ifndef RELEASE_BUILD - if (IREG_GET_REG(reg) == IREG_INVALID) - fatal("codegen_reg_write - IREG_INVALID\n"); + if (IREG_GET_REG(reg) == IREG_INVALID) + fatal("codegen_reg_write - IREG_INVALID\n"); #endif - ireg.reg = reg; - ireg.version = last_version + 1; - - if (IREG_GET_REG(reg) > IREG_EBX && last_version && !reg_version[IREG_GET_REG(reg)][last_version].refcount && - !(reg_version[IREG_GET_REG(reg)][last_version].flags & REG_FLAGS_REQUIRED)) - { - if (reg_is_native_size(ireg)) /*Non-native size registers have an implicit dependency on the previous version, so don't add to dead list*/ - add_to_dead_list(®_version[IREG_GET_REG(reg)][last_version], IREG_GET_REG(reg), last_version); - } - - reg_last_version[IREG_GET_REG(reg)]++; + ireg.reg = reg; + ireg.version = last_version + 1; + + if (IREG_GET_REG(reg) > IREG_EBX && last_version && !reg_version[IREG_GET_REG(reg)][last_version].refcount && !(reg_version[IREG_GET_REG(reg)][last_version].flags & REG_FLAGS_REQUIRED)) { + if (reg_is_native_size(ireg)) /*Non-native size registers have an implicit dependency on the previous version, so don't add to dead list*/ + add_to_dead_list(®_version[IREG_GET_REG(reg)][last_version], IREG_GET_REG(reg), last_version); + } + + reg_last_version[IREG_GET_REG(reg)]++; #ifndef RELEASE_BUILD - if (!reg_last_version[IREG_GET_REG(reg)]) - fatal("codegen_reg_write - version overflow\n"); - else + if (!reg_last_version[IREG_GET_REG(reg)]) + fatal("codegen_reg_write - version overflow\n"); + else #endif if (reg_last_version[IREG_GET_REG(reg)] > REG_VERSION_MAX) - CPU_BLOCK_END(); - if (reg_last_version[IREG_GET_REG(reg)] > max_version_refcount) - max_version_refcount = reg_last_version[IREG_GET_REG(reg)]; + CPU_BLOCK_END(); + if (reg_last_version[IREG_GET_REG(reg)] > max_version_refcount) + max_version_refcount = reg_last_version[IREG_GET_REG(reg)]; - version = ®_version[IREG_GET_REG(reg)][ireg.version]; - version->refcount = 0; - version->flags = 0; - version->parent_uop = uop_nr; -// pclog("codegen_reg_write: %i\n", reg & IREG_REG_MASK); - return ireg; + version = ®_version[IREG_GET_REG(reg)][ireg.version]; + version->refcount = 0; + version->flags = 0; + version->parent_uop = uop_nr; +#if 0 + pclog("codegen_reg_write: %i\n", reg & IREG_REG_MASK); +#endif + return ireg; } -static inline int ir_reg_is_invalid(ir_reg_t ir_reg) +static inline int +ir_reg_is_invalid(ir_reg_t ir_reg) { - return (IREG_GET_REG(ir_reg.reg) == IREG_INVALID); + return (IREG_GET_REG(ir_reg.reg) == IREG_INVALID); } struct ir_data_t; -void codegen_reg_reset(); +void codegen_reg_reset(void); /*Write back all dirty registers*/ void codegen_reg_flush(struct ir_data_t *ir, codeblock_t *block); /*Write back and evict all registers*/ @@ -405,7 +411,7 @@ void codegen_reg_flush_invalidate(struct ir_data_t *ir, codeblock_t *block); void codegen_reg_alloc_register(ir_reg_t dest_reg_a, ir_reg_t src_reg_a, ir_reg_t src_reg_b, ir_reg_t src_reg_c); #ifdef CODEGEN_BACKEND_HAS_MOV_IMM -int codegen_reg_is_loaded(ir_reg_t ir_reg); +int codegen_reg_is_loaded(ir_reg_t ir_reg); void codegen_reg_write_imm(codeblock_t *block, ir_reg_t ir_reg, uint32_t imm_data); #endif @@ -414,6 +420,6 @@ ir_host_reg_t codegen_reg_alloc_write_reg(codeblock_t *block, ir_reg_t ir_reg); void codegen_reg_rename(codeblock_t *block, ir_reg_t src, ir_reg_t dst); -void codegen_reg_mark_as_required(); +void codegen_reg_mark_as_required(void); void codegen_reg_process_dead_list(struct ir_data_t *ir); #endif diff --git a/src/config.c b/src/config.c index b110d6984..7d6df5074 100644 --- a/src/config.c +++ b/src/config.c @@ -1,30 +1,33 @@ /* - * 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. + * 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. + * This file is part of the 86Box distribution. * - * Configuration file handler. + * Configuration file handler. * * * - * Authors: Sarah Walker, - * Miran Grca, - * Fred N. van Kempen, - * Overdoze, - * David HrdliÄka, + * Authors: Sarah Walker, + * Miran Grca, + * Fred N. van Kempen, + * Overdoze, + * David HrdliÄka, * - * Copyright 2008-2019 Sarah Walker. - * Copyright 2016-2019 Miran Grca. - * Copyright 2017-2019 Fred N. van Kempen. - * Copyright 2018,2019 David HrdliÄka. + * Copyright 2008-2019 Sarah Walker. + * Copyright 2016-2019 Miran Grca. + * Copyright 2017-2019 Fred N. van Kempen. + * Copyright 2018-2019 David HrdliÄka. + * Copyright 2021 Andreas J. Reichel. + * Copyright 2021-2022 Jasmine Iwanek. * - * NOTE: Forcing config files to be in Unicode encoding breaks - * it on Windows XP, and possibly also Vista. Use the - * -DANSI_CFG for use on these systems. + * NOTE: Forcing config files to be in Unicode encoding breaks + * it on Windows XP, and possibly also Vista. Use the + * -DANSI_CFG for use on these systems. */ + #include #include #include @@ -40,10 +43,12 @@ #include <86box/cassette.h> #include <86box/cartridge.h> #include <86box/nvr.h> +#include <86box/ini.h> #include <86box/config.h> #include <86box/isamem.h> #include <86box/isartc.h> #include <86box/lpt.h> +#include <86box/serial.h> #include <86box/hdd.h> #include <86box/hdc.h> #include <86box/hdc_ide.h> @@ -51,2001 +56,1478 @@ #include <86box/fdc.h> #include <86box/fdc_ext.h> #include <86box/gameport.h> +#include <86box/serial.h> +#include <86box/serial_passthrough.h> #include <86box/machine.h> #include <86box/mouse.h> +#include <86box/thread.h> #include <86box/network.h> #include <86box/scsi.h> #include <86box/scsi_device.h> #include <86box/cdrom.h> +#include <86box/cdrom_interface.h> #include <86box/zip.h> #include <86box/mo.h> #include <86box/sound.h> #include <86box/midi.h> #include <86box/snd_mpu401.h> #include <86box/video.h> +#include <86box/path.h> #include <86box/plat.h> #include <86box/plat_dir.h> #include <86box/ui.h> +#include <86box/snd_opl.h> - -typedef struct _list_ { - struct _list_ *next; -} list_t; - -typedef struct { - list_t list; - - char name[128]; - - list_t entry_head; -} section_t; - -typedef struct { - list_t list; - - char name[128]; - char data[512]; - wchar_t wdata[512]; -} entry_t; - -#define list_add(new, head) { \ - list_t *next = head; \ - \ - while (next->next != NULL) \ - next = next->next; \ - \ - (next)->next = new; \ - (new)->next = NULL; \ -} - -#define list_delete(old, head) { \ - list_t *next = head; \ - \ - while ((next)->next != old) { \ - next = (next)->next; \ - } \ - \ - (next)->next = (old)->next; \ - if ((next) == (head)) \ - (head)->next = (old)->next; \ -} - - -static list_t config_head; - -/* TODO: Backwards compatibility, get rid of this when enough time has passed. */ -static int backwards_compat = 0; -static int backwards_compat2 = 0; - +static int cx; +static int cy; +static int cw; +static int ch; +static ini_t config; #ifdef ENABLE_CONFIG_LOG int config_do_log = ENABLE_CONFIG_LOG; - static void config_log(const char *fmt, ...) { va_list ap; if (config_do_log) { - va_start(ap, fmt); - pclog_ex(fmt, ap); - va_end(ap); + va_start(ap, fmt); + pclog_ex(fmt, ap); + va_end(ap); } } #else -#define config_log(fmt, ...) +# define config_log(fmt, ...) #endif - -static section_t * -find_section(char *name) -{ - section_t *sec; - char blank[] = ""; - - sec = (section_t *)config_head.next; - if (name == NULL) - name = blank; - - while (sec != NULL) { - if (! strncmp(sec->name, name, sizeof(sec->name))) - return(sec); - - sec = (section_t *)sec->list.next; - } - - return(NULL); -} - - -void * -config_find_section(char *name) -{ - return (void *) find_section(name); -} - - -void -config_rename_section(void *priv, char *name) -{ - section_t *sec = (section_t *) priv; - - memset(sec->name, 0x00, sizeof(sec->name)); - memcpy(sec->name, name, MIN(128, strlen(name) + 1)); -} - - -static entry_t * -find_entry(section_t *section, char *name) -{ - entry_t *ent; - - ent = (entry_t *)section->entry_head.next; - - while (ent != NULL) { - if (! strncmp(ent->name, name, sizeof(ent->name))) - return(ent); - - ent = (entry_t *)ent->list.next; - } - - return(NULL); -} - - -static int -entries_num(section_t *section) -{ - entry_t *ent; - int i = 0; - - ent = (entry_t *)section->entry_head.next; - - while (ent != NULL) { - if (strlen(ent->name) > 0) i++; - - ent = (entry_t *)ent->list.next; - } - - return(i); -} - - -static void -delete_section_if_empty(char *head) -{ - section_t *section; - - section = find_section(head); - if (section == NULL) return; - - if (entries_num(section) == 0) { - list_delete(§ion->list, &config_head); - free(section); - } -} - - -static section_t * -create_section(char *name) -{ - section_t *ns = malloc(sizeof(section_t)); - - memset(ns, 0x00, sizeof(section_t)); - memcpy(ns->name, name, strlen(name) + 1); - list_add(&ns->list, &config_head); - - return(ns); -} - - -static entry_t * -create_entry(section_t *section, char *name) -{ - entry_t *ne = malloc(sizeof(entry_t)); - - memset(ne, 0x00, sizeof(entry_t)); - memcpy(ne->name, name, strlen(name) + 1); - list_add(&ne->list, §ion->entry_head); - - return(ne); -} - - -#if 0 -static void -config_free(void) -{ - section_t *sec, *ns; - entry_t *ent; - - sec = (section_t *)config_head.next; - while (sec != NULL) { - ns = (section_t *)sec->list.next; - ent = (entry_t *)sec->entry_head.next; - - while (ent != NULL) { - entry_t *nent = (entry_t *)ent->list.next; - - free(ent); - ent = nent; - } - - free(sec); - sec = ns; - } -} -#endif - -static int -config_detect_bom(char *fn) -{ - FILE *f; - unsigned char bom[4] = { 0, 0, 0, 0 }; - -#if defined(ANSI_CFG) || !defined(_WIN32) - f = plat_fopen(fn, "rt"); -#else - f = plat_fopen(fn, "rt, ccs=UTF-8"); -#endif - if (f == NULL) return(0); - fread(bom, 1, 3, f); - if (bom[0] == 0xEF && bom[1] == 0xBB && bom[2] == 0xBF) - { - fclose(f); - return 1; - } - fclose(f); - return 0; -} - -/* Read and parse the configuration file into memory. */ -static int -config_read(char *fn) -{ - char sname[128], ename[128]; - wchar_t buff[1024]; - section_t *sec, *ns; - entry_t *ne; - int c, d, bom; - FILE *f; - - bom = config_detect_bom(fn); -#if defined(ANSI_CFG) || !defined(_WIN32) - f = plat_fopen(fn, "rt"); -#else - f = plat_fopen(fn, "rt, ccs=UTF-8"); -#endif - if (f == NULL) return(0); - - sec = malloc(sizeof(section_t)); - memset(sec, 0x00, sizeof(section_t)); - memset(&config_head, 0x00, sizeof(list_t)); - list_add(&sec->list, &config_head); - if (bom) - fseek(f, 3, SEEK_SET); - - while (1) { - memset(buff, 0x00, sizeof(buff)); - fgetws(buff, sizeof_w(buff), f); - if (feof(f)) break; - - /* Make sure there are no stray newlines or hard-returns in there. */ - if (wcslen(buff) > 0) - if (buff[wcslen(buff)-1] == L'\n') buff[wcslen(buff)-1] = L'\0'; - if (wcslen(buff) > 0) - if (buff[wcslen(buff)-1] == L'\r') buff[wcslen(buff)-1] = L'\0'; - - /* Skip any leading whitespace. */ - c = 0; - while ((buff[c] == L' ') || (buff[c] == L'\t')) - c++; - - /* Skip empty lines. */ - if (buff[c] == L'\0') continue; - - /* Skip lines that (only) have a comment. */ - if ((buff[c] == L'#') || (buff[c] == L';')) continue; - - if (buff[c] == L'[') { /*Section*/ - c++; - d = 0; - while (buff[c] != L']' && buff[c]) - wctomb(&(sname[d++]), buff[c++]); - sname[d] = L'\0'; - - /* Is the section name properly terminated? */ - if (buff[c] != L']') continue; - - /* Create a new section and insert it. */ - ns = malloc(sizeof(section_t)); - memset(ns, 0x00, sizeof(section_t)); - memcpy(ns->name, sname, 128); - list_add(&ns->list, &config_head); - - /* New section is now the current one. */ - sec = ns; - continue; - } - - /* Get the variable name. */ - d = 0; - while ((buff[c] != L'=') && (buff[c] != L' ') && buff[c]) - wctomb(&(ename[d++]), buff[c++]); - ename[d] = L'\0'; - - /* Skip incomplete lines. */ - if (buff[c] == L'\0') continue; - - /* Look for =, skip whitespace. */ - while ((buff[c] == L'=' || buff[c] == L' ') && buff[c]) - c++; - - /* Skip incomplete lines. */ - if (buff[c] == L'\0') continue; - - /* This is where the value part starts. */ - d = c; - - /* Allocate a new variable entry.. */ - ne = malloc(sizeof(entry_t)); - memset(ne, 0x00, sizeof(entry_t)); - memcpy(ne->name, ename, 128); - wcsncpy(ne->wdata, &buff[d], sizeof_w(ne->wdata)-1); - ne->wdata[sizeof_w(ne->wdata)-1] = L'\0'; -#ifdef _WIN32 /* Make sure the string is converted to UTF-8 rather than a legacy codepage */ - c16stombs(ne->data, ne->wdata, sizeof(ne->data)); -#else - wcstombs(ne->data, ne->wdata, sizeof(ne->data)); -#endif - ne->data[sizeof(ne->data)-1] = '\0'; - - /* .. and insert it. */ - list_add(&ne->list, &sec->entry_head); - } - - (void)fclose(f); - - if (do_dump_config) - config_dump(); - - return(1); -} - - -/* - * Write the in-memory configuration to disk. - * This is a public function, because the Settings UI - * want to directly write the configuration after it - * has changed it. - */ -void -config_write(char *fn) -{ - wchar_t wtemp[512]; - section_t *sec; - FILE *f; - int fl = 0; - -#if defined(ANSI_CFG) || !defined(_WIN32) - f = plat_fopen(fn, "wt"); -#else - f = plat_fopen(fn, "wt, ccs=UTF-8"); -#endif - if (f == NULL) return; - - sec = (section_t *)config_head.next; - while (sec != NULL) { - entry_t *ent; - - if (sec->name[0]) { - mbstowcs(wtemp, sec->name, strlen(sec->name)+1); - if (fl) - fwprintf(f, L"\n[%ls]\n", wtemp); - else - fwprintf(f, L"[%ls]\n", wtemp); - fl++; - } - - ent = (entry_t *)sec->entry_head.next; - while (ent != NULL) { - if (ent->name[0] != '\0') { - mbstowcs(wtemp, ent->name, 128); - if (ent->wdata[0] == L'\0') - fwprintf(f, L"%ls = \n", wtemp); - else - fwprintf(f, L"%ls = %ls\n", wtemp, ent->wdata); - fl++; - } - - ent = (entry_t *)ent->list.next; - } - - sec = (section_t *)sec->list.next; - } - - (void)fclose(f); -} - - -#if NOT_USED -static void -config_new(void) -{ -#if defined(ANSI_CFG) || !defined(_WIN32) - FILE *f = _wfopen(config_file, L"wt"); -#else - FILE *f = _wfopen(config_file, L"wt, ccs=UTF-8"); -#endif - - if (file != NULL) - (void)fclose(f); -} -#endif - - /* Load "General" section. */ static void load_general(void) { - char *cat = "General"; - char temp[512]; - char *p; + ini_section_t cat = ini_find_section(config, "General"); + char temp[512]; + char *p; - vid_resize = config_get_int(cat, "vid_resize", 0); + vid_resize = ini_section_get_int(cat, "vid_resize", 0); if (vid_resize & ~3) - vid_resize &= 3; + vid_resize &= 3; memset(temp, '\0', sizeof(temp)); - p = config_get_string(cat, "vid_renderer", "default"); + p = ini_section_get_string(cat, "vid_renderer", "default"); vid_api = plat_vidapi(p); - config_delete_var(cat, "vid_api"); + ini_section_delete_var(cat, "vid_api"); - video_fullscreen_scale = config_get_int(cat, "video_fullscreen_scale", 0); + video_fullscreen_scale = ini_section_get_int(cat, "video_fullscreen_scale", 1); - video_fullscreen_first = config_get_int(cat, "video_fullscreen_first", 1); + video_fullscreen_first = ini_section_get_int(cat, "video_fullscreen_first", 1); - video_filter_method = config_get_int(cat, "video_filter_method", 1); + video_filter_method = ini_section_get_int(cat, "video_filter_method", 1); - force_43 = !!config_get_int(cat, "force_43", 0); - scale = config_get_int(cat, "scale", 1); - if (scale > 3) - scale = 3; - dpi_scale = config_get_int(cat, "dpi_scale", 1); + force_43 = !!ini_section_get_int(cat, "force_43", 0); + scale = ini_section_get_int(cat, "scale", 1); + if (scale > 9) + scale = 9; + dpi_scale = ini_section_get_int(cat, "dpi_scale", 1); - enable_overscan = !!config_get_int(cat, "enable_overscan", 0); - vid_cga_contrast = !!config_get_int(cat, "vid_cga_contrast", 0); - video_grayscale = config_get_int(cat, "video_grayscale", 0); - video_graytype = config_get_int(cat, "video_graytype", 0); + enable_overscan = !!ini_section_get_int(cat, "enable_overscan", 0); + vid_cga_contrast = !!ini_section_get_int(cat, "vid_cga_contrast", 0); + video_grayscale = ini_section_get_int(cat, "video_grayscale", 0); + video_graytype = ini_section_get_int(cat, "video_graytype", 0); + + rctrl_is_lalt = ini_section_get_int(cat, "rctrl_is_lalt", 0); + update_icons = ini_section_get_int(cat, "update_icons", 1); - rctrl_is_lalt = config_get_int(cat, "rctrl_is_lalt", 0); - update_icons = config_get_int(cat, "update_icons", 1); status_icons_fullscreen = !!config_get_int(cat, "status_icons_fullscreen", 0); - window_remember = config_get_int(cat, "window_remember", 0); - if (window_remember || (vid_resize & 2)) { - if (!window_remember) - config_delete_var(cat, "window_remember"); + window_remember = ini_section_get_int(cat, "window_remember", 0); - p = config_get_string(cat, "window_coordinates", NULL); - if (p == NULL) - p = "0, 0, 0, 0"; - sscanf(p, "%i, %i, %i, %i", &window_w, &window_h, &window_x, &window_y); - } else { - config_delete_var(cat, "window_remember"); - config_delete_var(cat, "window_coordinates"); - - window_w = window_h = window_x = window_y = 0; - } + if (!window_remember && !(vid_resize & 2)) + window_w = window_h = window_x = window_y = 0; if (vid_resize & 2) { - p = config_get_string(cat, "window_fixed_res", NULL); - if (p == NULL) - p = "120x120"; - sscanf(p, "%ix%i", &fixed_size_x, &fixed_size_y); - if (fixed_size_x < 120) - fixed_size_x = 120; - if (fixed_size_x > 2048) - fixed_size_x = 2048; - if (fixed_size_y < 120) - fixed_size_y = 120; - if (fixed_size_y > 2048) - fixed_size_y = 2048; + p = ini_section_get_string(cat, "window_fixed_res", NULL); + if (p == NULL) + p = "120x120"; + sscanf(p, "%ix%i", &fixed_size_x, &fixed_size_y); + if (fixed_size_x < 120) + fixed_size_x = 120; + if (fixed_size_x > 2048) + fixed_size_x = 2048; + if (fixed_size_y < 120) + fixed_size_y = 120; + if (fixed_size_y > 2048) + fixed_size_y = 2048; } else { - config_delete_var(cat, "window_fixed_res"); + ini_section_delete_var(cat, "window_fixed_res"); - fixed_size_x = fixed_size_y = 120; + fixed_size_x = fixed_size_y = 120; } - sound_gain = config_get_int(cat, "sound_gain", 0); + sound_gain = ini_section_get_int(cat, "sound_gain", 0); - kbd_req_capture = config_get_int(cat, "kbd_req_capture", 0); - hide_status_bar = config_get_int(cat, "hide_status_bar", 0); - hide_tool_bar = config_get_int(cat, "hide_tool_bar", 0); + kbd_req_capture = ini_section_get_int(cat, "kbd_req_capture", 0); + hide_status_bar = ini_section_get_int(cat, "hide_status_bar", 0); + hide_tool_bar = ini_section_get_int(cat, "hide_tool_bar", 0); - confirm_reset = config_get_int(cat, "confirm_reset", 1); - confirm_exit = config_get_int(cat, "confirm_exit", 1); - confirm_save = config_get_int(cat, "confirm_save", 1); + confirm_reset = ini_section_get_int(cat, "confirm_reset", 1); + confirm_exit = ini_section_get_int(cat, "confirm_exit", 1); + confirm_save = ini_section_get_int(cat, "confirm_save", 1); - p = config_get_string(cat, "language", NULL); - if (p != NULL) - { - lang_id = plat_language_code(p); - } - - p = config_get_string(cat, "iconset", NULL); - if (p != NULL) - strcpy(icon_set, p); - else - strcpy(icon_set, ""); - - enable_discord = !!config_get_int(cat, "enable_discord", 0); + p = ini_section_get_string(cat, "language", NULL); + if (p != NULL) + lang_id = plat_language_code(p); - video_framerate = config_get_int(cat, "video_gl_framerate", -1); - video_vsync = config_get_int(cat, "video_gl_vsync", 0); - strncpy(video_shader, config_get_string(cat, "video_gl_shader", ""), sizeof(video_shader)); + mouse_sensitivity = ini_section_get_double(cat, "mouse_sensitivity", 1.0); + if (mouse_sensitivity < 0.1) + mouse_sensitivity = 0.1; + else if (mouse_sensitivity > 2.0) + mouse_sensitivity = 2.0; + + p = ini_section_get_string(cat, "iconset", NULL); + if (p != NULL) + strcpy(icon_set, p); + else + strcpy(icon_set, ""); + + enable_discord = !!ini_section_get_int(cat, "enable_discord", 0); + + open_dir_usr_path = ini_section_get_int(cat, "open_dir_usr_path", 0); + + video_framerate = ini_section_get_int(cat, "video_gl_framerate", -1); + video_vsync = ini_section_get_int(cat, "video_gl_vsync", 0); + strncpy(video_shader, ini_section_get_string(cat, "video_gl_shader", ""), sizeof(video_shader) - 1); + + window_remember = ini_section_get_int(cat, "window_remember", 0); + if (window_remember) { + p = ini_section_get_string(cat, "window_coordinates", NULL); + if (p == NULL) + p = "0, 0, 0, 0"; + sscanf(p, "%i, %i, %i, %i", &cw, &ch, &cx, &cy); + } else + cw = ch = cx = cy = 0; + + ini_section_delete_var(cat, "window_coordinates"); + + do_auto_pause = ini_section_get_int(cat, "do_auto_pause", 0); } +/* Load monitor section. */ +static void +load_monitor(int monitor_index) +{ + ini_section_t cat; + char name[512]; + char temp[512]; + const char * p = NULL; + monitor_settings_t *ms = &monitor_settings[monitor_index]; + + sprintf(name, "Monitor #%i", monitor_index + 1); + sprintf(temp, "%i, %i, %i, %i", cx, cy, cw, ch); + + cat = ini_find_section(config, name); + + p = ini_section_get_string(cat, "window_coordinates", temp); + + if (window_remember) { + sscanf(p, "%i, %i, %i, %i", &ms->mon_window_x, &ms->mon_window_y, + &ms->mon_window_w, &ms->mon_window_h); + ms->mon_window_maximized = !!ini_section_get_int(cat, "window_maximized", 0); + } else + ms->mon_window_maximized = 0; +} /* Load "Machine" section. */ static void load_machine(void) { - char *cat = "Machine"; - char *p, *migrate_from = NULL; - int c, i, j, speed, legacy_mfg, legacy_cpu; - double multi; + ini_section_t cat = ini_find_section(config, "Machine"); + const char *p; + int c; + int i; + int speed; + double multi; - p = config_get_string(cat, "machine", NULL); - if (p != NULL) { - migrate_from = p; - if (! strcmp(p, "8500ttc")) /* migrate typo... */ - machine = machine_get_machine_from_internal_name("8600ttc"); - else if (! strcmp(p, "eagle_pcspirit")) /* ...legacy names... */ - machine = machine_get_machine_from_internal_name("pcspirit"); - else if (! strcmp(p, "multitech_pc700")) - machine = machine_get_machine_from_internal_name("pc700"); - else if (! strcmp(p, "ncr_pc4i")) - machine = machine_get_machine_from_internal_name("pc4i"); - else if (! strcmp(p, "olivetti_m19")) - machine = machine_get_machine_from_internal_name("m19"); - else if (! strcmp(p, "open_xt")) - machine = machine_get_machine_from_internal_name("openxt"); - else if (! strcmp(p, "open_at")) - machine = machine_get_machine_from_internal_name("openat"); - else if (! strcmp(p, "philips_p3105")) - machine = machine_get_machine_from_internal_name("p3105"); - else if (! strcmp(p, "philips_p3120")) - machine = machine_get_machine_from_internal_name("p3120"); - else if (! strcmp(p, "olivetti_m24")) - machine = machine_get_machine_from_internal_name("m24"); - else if (! strcmp(p, "olivetti_m240")) - machine = machine_get_machine_from_internal_name("m240"); - else if (! strcmp(p, "ncr_pc8")) - machine = machine_get_machine_from_internal_name("pc8"); - else if (! strcmp(p, "olivetti_m290")) - machine = machine_get_machine_from_internal_name("m290"); - else if (! strcmp(p, "ncr_3302")) - machine = machine_get_machine_from_internal_name("3302"); - else if (! strcmp(p, "ncr_pc916sx")) - machine = machine_get_machine_from_internal_name("pc916sx"); - else if (! strcmp(p, "cbm_sl386sx16")) - machine = machine_get_machine_from_internal_name("cmdsl386sx16"); - else if (! strcmp(p, "cbm_sl386sx25")) - machine = machine_get_machine_from_internal_name("cmdsl386sx25"); - else if (! strcmp(p, "mr586")) - machine = machine_get_machine_from_internal_name("p54tp4xe_mr"); - else if (! strcmp(p, "pcv240")) - machine = machine_get_machine_from_internal_name("pcv90"); - else if (! strcmp(p, "v60n")) - machine = machine_get_machine_from_internal_name("acerv60n"); - else if (! strcmp(p, "tsunamiatx")) - machine = machine_get_machine_from_internal_name("s1846"); - else if (! strcmp(p, "trinity371")) - machine = machine_get_machine_from_internal_name("s1857"); - else if (! strcmp(p, "63a")) - machine = machine_get_machine_from_internal_name("63a1"); - else if (! strcmp(p, "4sa2")) - machine = machine_get_machine_from_internal_name("4saw2"); - else if (! strcmp(p, "award386dx")) /* ...merged machines... */ - machine = machine_get_machine_from_internal_name("award495"); - else if (! strcmp(p, "ami386dx")) - machine = machine_get_machine_from_internal_name("ami495"); - else if (! strcmp(p, "mr386dx")) - machine = machine_get_machine_from_internal_name("mr495"); - else if (! strcmp(p, "award486")) - machine = machine_get_machine_from_internal_name("award495"); - else if (! strcmp(p, "ami486")) - machine = machine_get_machine_from_internal_name("ami495"); - else if (! strcmp(p, "mr486")) - machine = machine_get_machine_from_internal_name("mr495"); - else if (! strcmp(p, "ibmps1_2121_isa")) - machine = machine_get_machine_from_internal_name("ibmps1_2121"); - else if (! strcmp(p, "fw6400gx_s1")) - machine = machine_get_machine_from_internal_name("fw6400gx"); - else if (! strcmp(p, "p54vl")) - machine = machine_get_machine_from_internal_name("p5vl"); - else if (! strcmp(p, "chariot")) - machine = machine_get_machine_from_internal_name("fmb"); - else if (! strcmp(p, "president")) { /* ...and removed machines */ - machine = machine_get_machine_from_internal_name("mb500n"); - migrate_from = NULL; - } else if (! strcmp(p, "j656vxd")) { - machine = machine_get_machine_from_internal_name("p55va"); - migrate_from = NULL; - } else { - machine = machine_get_machine_from_internal_name(p); - migrate_from = NULL; - } - } else - machine = 0; + p = ini_section_get_string(cat, "machine", NULL); + if (p != NULL) + machine = machine_get_machine_from_internal_name(p); + else + machine = 0; - /* This is for backwards compatibility. */ - p = config_get_string(cat, "model", NULL); - if (p != NULL) { - migrate_from = p; - if (! strcmp(p, "p55r2p4")) /* migrate typo */ - machine = machine_get_machine_from_internal_name("p55t2p4"); - else { - machine = machine_get_machine_from_internal_name(p); - migrate_from = NULL; - } - config_delete_var(cat, "model"); - } if (machine >= machine_count()) - machine = machine_count() - 1; + machine = machine_count() - 1; - /* Copy NVR files when migrating a machine to a new internal name. */ - if (migrate_from) { - char old_fn[256]; - strcpy(old_fn, migrate_from); - strcat(old_fn, "."); - c = strlen(old_fn); - char new_fn[256]; - strcpy(new_fn, machines[machine].internal_name); - strcat(new_fn, "."); - i = strlen(new_fn); - - /* Iterate through NVR files. */ - DIR *dirp = opendir(nvr_path(".")); - if (dirp) { - struct dirent *entry; - while ((entry = readdir(dirp))) { - /* Check if this file corresponds to the old name. */ - if (strncmp(entry->d_name, old_fn, c)) - continue; - - /* Add extension to the new name. */ - strcpy(&new_fn[i], &entry->d_name[c]); - - /* Only copy if a file with the new name doesn't already exist. */ - FILE *g = nvr_fopen(new_fn, "rb"); - if (!g) { - FILE *f = nvr_fopen(entry->d_name, "rb"); - g = nvr_fopen(new_fn, "wb"); - - uint8_t buf[4096]; - while ((j = fread(buf, 1, sizeof(buf), f))) - fwrite(buf, 1, j, g); - - fclose(f); - } - fclose(g); - } - } - } - - cpu_override = config_get_int(cat, "cpu_override", 0); - cpu_f = NULL; - p = config_get_string(cat, "cpu_family", NULL); + cpu_override = ini_section_get_int(cat, "cpu_override", 0); + cpu_f = NULL; + p = ini_section_get_string(cat, "cpu_family", NULL); if (p) { - if (! strcmp(p, "enh_am486dx2")) /* migrate modified names */ - cpu_f = cpu_get_family("am486dx2_slenh"); - else if (! strcmp(p, "enh_am486dx4")) - cpu_f = cpu_get_family("am486dx4_slenh"); - else - cpu_f = cpu_get_family(p); + cpu_f = cpu_get_family(p); - if (cpu_f && !cpu_family_is_eligible(cpu_f, machine)) /* only honor eligible families */ - cpu_f = NULL; - } else { - /* Backwards compatibility with the previous CPU model system. */ - legacy_mfg = config_get_int(cat, "cpu_manufacturer", 0); - legacy_cpu = config_get_int(cat, "cpu", 0); - - /* Check if either legacy ID is present, and if they are within bounds. */ - if (((legacy_mfg > 0) || (legacy_cpu > 0)) && (legacy_mfg >= 0) && (legacy_mfg < 4) && (legacy_cpu >= 0)) { - /* Look for a machine entry on the legacy table. */ - p = machine_get_internal_name(); - c = 0; - while (cpu_legacy_table[c].machine) { - if (!strcmp(p, cpu_legacy_table[c].machine)) - break; - c++; - } - if (cpu_legacy_table[c].machine) { - /* Determine the amount of CPU entries on the table. */ - i = -1; - while (cpu_legacy_table[c].tables[legacy_mfg][++i].family); - - /* If the CPU ID is out of bounds, reset to the last known ID. */ - if (legacy_cpu >= i) - legacy_cpu = i - 1; - - const cpu_legacy_table_t *legacy_table_entry = &cpu_legacy_table[c].tables[legacy_mfg][legacy_cpu]; - - /* Check if the referenced family exists. */ - cpu_f = cpu_get_family(legacy_table_entry->family); - if (cpu_f) { - /* Save the new values. */ - config_set_string(cat, "cpu_family", (char *) legacy_table_entry->family); - config_set_int(cat, "cpu_speed", legacy_table_entry->rspeed); - config_set_double(cat, "cpu_multi", legacy_table_entry->multi); - } - } - } + if (cpu_f && !cpu_family_is_eligible(cpu_f, machine)) /* only honor eligible families */ + cpu_f = NULL; } if (cpu_f) { - speed = config_get_int(cat, "cpu_speed", 0); - multi = config_get_double(cat, "cpu_multi", 0); + speed = ini_section_get_int(cat, "cpu_speed", 0); + multi = ini_section_get_double(cat, "cpu_multi", 0); - /* Find the configured CPU. */ - cpu = 0; - c = 0; - i = 256; - while (cpu_f->cpus[cpu].cpu_type) { - if (cpu_is_eligible(cpu_f, cpu, machine)) { /* skip ineligible CPUs */ - if ((cpu_f->cpus[cpu].rspeed == speed) && (cpu_f->cpus[cpu].multi == multi)) /* exact speed/multiplier match */ - break; - else if ((cpu_f->cpus[cpu].rspeed >= speed) && (i == 256)) /* closest speed match */ - i = cpu; - c = cpu; /* store fastest eligible CPU */ - } - cpu++; - } - if (!cpu_f->cpus[cpu].cpu_type) /* if no exact match was found, use closest matching faster CPU, or fastest eligible CPU */ - cpu = MIN(i, c); - } else { /* default */ - /* Find first eligible family. */ - c = 0; - while (!cpu_family_is_eligible(&cpu_families[c], machine)) { - if (cpu_families[c++].package == 0) { /* end of list */ - fatal("No eligible CPU families for the selected machine\n"); - return; - } - } - cpu_f = (cpu_family_t *) &cpu_families[c]; + /* Find the configured CPU. */ + cpu = 0; + c = 0; + i = 256; + while (cpu_f->cpus[cpu].cpu_type) { + if (cpu_is_eligible(cpu_f, cpu, machine)) { + /* Skip ineligible CPUs. */ + if ((cpu_f->cpus[cpu].rspeed == speed) && (cpu_f->cpus[cpu].multi == multi)) + /* Exact speed/multiplier match. */ + break; + else if ((cpu_f->cpus[cpu].rspeed >= speed) && (i == 256)) + /* Closest speed match. */ + i = cpu; + c = cpu; /* store fastest eligible CPU */ + } + cpu++; + } + if (!cpu_f->cpus[cpu].cpu_type) + /* if no exact match was found, use closest matching faster CPU or fastest eligible CPU. */ + cpu = MIN(i, c); + } else { + /* Default, find first eligible family. */ + c = 0; + while (!cpu_family_is_eligible(&cpu_families[c], machine)) { + if (cpu_families[c++].package == 0) { + /* End of list. */ + fatal("No eligible CPU families for the selected machine\n"); + return; + } + } + cpu_f = (cpu_family_t *) &cpu_families[c]; - /* Find first eligible CPU in that family. */ - cpu = 0; - while (!cpu_is_eligible(cpu_f, cpu, machine)) { - if (cpu_f->cpus[cpu++].cpu_type == 0) { /* end of list */ - cpu = 0; - break; - } - } + /* Find first eligible CPU in that family. */ + cpu = 0; + while (!cpu_is_eligible(cpu_f, cpu, machine)) { + if (cpu_f->cpus[cpu++].cpu_type == 0) { + /* End of list. */ + cpu = 0; + break; + } + } } cpu_s = (CPU *) &cpu_f->cpus[cpu]; - cpu_waitstates = config_get_int(cat, "cpu_waitstates", 0); + cpu_waitstates = ini_section_get_int(cat, "cpu_waitstates", 0); - p = (char *)config_get_string(cat, "fpu_type", "none"); + p = ini_section_get_string(cat, "fpu_type", "none"); fpu_type = fpu_get_type(cpu_f, cpu, p); - mem_size = config_get_int(cat, "mem_size", 64); -#if 0 - if (mem_size < ((machine_has_bus(machine, MACHINE_AT) && - (machines[machine].ram_granularity < 128)) ? machines[machine].min_ram*1024 : machines[machine].min_ram)) - mem_size = (((machine_has_bus(machine, MACHINE_AT) && (machines[machine].ram_granularity < 128)) ? machines[machine].min_ram*1024 : machines[machine].min_ram); -#endif - - if (mem_size > 2097152) - mem_size = 2097152; + mem_size = ini_section_get_int(cat, "mem_size", 64); - cpu_use_dynarec = !!config_get_int(cat, "cpu_use_dynarec", 0); + if (mem_size > machine_get_max_ram(machine)) + mem_size = machine_get_max_ram(machine); - p = config_get_string(cat, "time_sync", NULL); - if (p != NULL) { - if (!strcmp(p, "disabled")) - time_sync = TIME_SYNC_DISABLED; - else - if (!strcmp(p, "local")) - time_sync = TIME_SYNC_ENABLED; - else - if (!strcmp(p, "utc") || !strcmp(p, "gmt")) - time_sync = TIME_SYNC_ENABLED | TIME_SYNC_UTC; - else - time_sync = TIME_SYNC_ENABLED; + cpu_use_dynarec = !!ini_section_get_int(cat, "cpu_use_dynarec", 0); + fpu_softfloat = !!ini_section_get_int(cat, "fpu_softfloat", 0); + if ((fpu_type != FPU_NONE) && machine_has_flags(machine, MACHINE_SOFTFLOAT_ONLY)) + fpu_softfloat = 1; + + p = ini_section_get_string(cat, "time_sync", NULL); + if (p != NULL) { + if (!strcmp(p, "disabled")) + time_sync = TIME_SYNC_DISABLED; + else if (!strcmp(p, "local")) + time_sync = TIME_SYNC_ENABLED; + else if (!strcmp(p, "utc") || !strcmp(p, "gmt")) + time_sync = TIME_SYNC_ENABLED | TIME_SYNC_UTC; + else + time_sync = TIME_SYNC_ENABLED; } else - time_sync = !!config_get_int(cat, "enable_sync", 1); + time_sync = !!ini_section_get_int(cat, "enable_sync", 1); - /* Remove this after a while.. */ - config_delete_var(cat, "nvr_path"); - config_delete_var(cat, "enable_sync"); + pit_mode = ini_section_get_int(cat, "pit_mode", -1); } - /* Load "Video" section. */ static void load_video(void) { - char *cat = "Video"; - char *p; - int free_p = 0; + ini_section_t cat = ini_find_section(config, "Video"); + char *p; + int free_p = 0; if (machine_has_flags(machine, MACHINE_VIDEO_ONLY)) { - config_delete_var(cat, "gfxcard"); - gfxcard = VID_INTERNAL; + ini_section_delete_var(cat, "gfxcard"); + gfxcard[0] = VID_INTERNAL; } else { - p = config_get_string(cat, "gfxcard", NULL); - if (p == NULL) { - if (machine_has_flags(machine, MACHINE_VIDEO)) { - p = (char *)malloc((strlen("internal")+1)*sizeof(char)); - strcpy(p, "internal"); - } else { - p = (char *)malloc((strlen("none")+1)*sizeof(char)); - strcpy(p, "none"); - } - free_p = 1; - } - if (!strcmp(p, "virge375_vbe20_pci")) /* migrate renamed cards */ - gfxcard = video_get_video_from_internal_name("virge385_pci"); - else - gfxcard = video_get_video_from_internal_name(p); - if (free_p) - free(p); + p = ini_section_get_string(cat, "gfxcard", NULL); + if (p == NULL) { + if (machine_has_flags(machine, MACHINE_VIDEO)) { + p = (char *) malloc((strlen("internal") + 1) * sizeof(char)); + strcpy(p, "internal"); + } else { + p = (char *) malloc((strlen("none") + 1) * sizeof(char)); + strcpy(p, "none"); + } + free_p = 1; + } + gfxcard[0] = video_get_video_from_internal_name(p); + if (free_p) + free(p); } - voodoo_enabled = !!config_get_int(cat, "voodoo", 0); -} + if (((gfxcard[0] == VID_INTERNAL) && machine_has_flags(machine, MACHINE_VIDEO_8514A)) || + video_card_get_flags(gfxcard[0]) == VIDEO_FLAG_TYPE_8514) + ini_section_delete_var(cat, "8514a"); + if (((gfxcard[0] == VID_INTERNAL) && machine_has_flags(machine, MACHINE_VIDEO_XGA)) || + video_card_get_flags(gfxcard[0]) == VIDEO_FLAG_TYPE_XGA) + ini_section_delete_var(cat, "xga"); + voodoo_enabled = !!ini_section_get_int(cat, "voodoo", 0); + ibm8514_standalone_enabled = !!ini_section_get_int(cat, "8514a", 0); + ibm8514_active = ibm8514_standalone_enabled; + xga_standalone_enabled = !!ini_section_get_int(cat, "xga", 0); + xga_active = xga_standalone_enabled; + show_second_monitors = !!ini_section_get_int(cat, "show_second_monitors", 1); + video_fullscreen_scale_maximized = !!ini_section_get_int(cat, "video_fullscreen_scale_maximized", 0); + + p = ini_section_get_string(cat, "gfxcard_2", NULL); + if (!p) + p = "none"; + gfxcard[1] = video_get_video_from_internal_name(p); +} /* Load "Input Devices" section. */ static void load_input_devices(void) { - char *cat = "Input devices"; - char temp[512]; - int c, d; - char *p; + ini_section_t cat = ini_find_section(config, "Input devices"); + char temp[512]; + int c; + int d; + char *p; - p = config_get_string(cat, "mouse_type", NULL); + p = ini_section_get_string(cat, "mouse_type", NULL); if (p != NULL) - mouse_type = mouse_get_from_internal_name(p); - else - mouse_type = 0; + mouse_type = mouse_get_from_internal_name(p); + else + mouse_type = 0; - p = config_get_string(cat, "joystick_type", NULL); + p = ini_section_get_string(cat, "joystick_type", NULL); if (p != NULL) { - if (!strcmp(p, "standard_2button")) /* migrate renamed types */ - joystick_type = joystick_get_from_internal_name("2axis_2button"); - else if (!strcmp(p, "standard_4button")) - joystick_type = joystick_get_from_internal_name("2axis_4button"); - else if (!strcmp(p, "standard_6button")) - joystick_type = joystick_get_from_internal_name("2axis_6button"); - else if (!strcmp(p, "standard_8button")) - joystick_type = joystick_get_from_internal_name("2axis_8button"); - else if (!strcmp(p, "ch_flighstick_pro")) /* fix typo */ - joystick_type = joystick_get_from_internal_name("ch_flightstick_pro"); - else - joystick_type = joystick_get_from_internal_name(p); + joystick_type = joystick_get_from_internal_name(p); - if (!joystick_type) { - /* Try to read an integer for backwards compatibility with old configs */ - if (!strcmp(p, "0")) /* workaround for config_get_int returning 0 on non-integer data */ - joystick_type = joystick_get_from_internal_name("2axis_2button"); - else { - c = config_get_int(cat, "joystick_type", 8); - switch (c) { - case 1: - joystick_type = joystick_get_from_internal_name("2axis_4button"); - break; - case 2: - joystick_type = joystick_get_from_internal_name("2axis_6button"); - break; - case 3: - joystick_type = joystick_get_from_internal_name("2axis_8button"); - break; - case 4: - joystick_type = joystick_get_from_internal_name("4axis_4button"); - break; - case 5: - joystick_type = joystick_get_from_internal_name("ch_flightstick_pro"); - break; - case 6: - joystick_type = joystick_get_from_internal_name("sidewinder_pad"); - break; - case 7: - joystick_type = joystick_get_from_internal_name("thrustmaster_fcs"); - break; - default: - joystick_type = 0; - break; - } - } - } + if (!joystick_type) { + /* Try to read an integer for backwards compatibility with old configs */ + if (!strcmp(p, "0")) + /* Workaround for ini_section_get_int returning 0 on non-integer data */ + joystick_type = joystick_get_from_internal_name("2axis_2button"); + else { + c = ini_section_get_int(cat, "joystick_type", 8); + switch (c) { + case JS_TYPE_2AXIS_4BUTTON: + joystick_type = joystick_get_from_internal_name("2axis_4button"); + break; + case JS_TYPE_2AXIS_6BUTTON: + joystick_type = joystick_get_from_internal_name("2axis_6button"); + break; + case JS_TYPE_2AXIS_8BUTTON: + joystick_type = joystick_get_from_internal_name("2axis_8button"); + break; + case JS_TYPE_4AXIS_4BUTTON: + joystick_type = joystick_get_from_internal_name("4axis_4button"); + break; + case JS_TYPE_CH_FLIGHTSTICK_PRO: + joystick_type = joystick_get_from_internal_name("ch_flightstick_pro"); + break; + case JS_TYPE_SIDEWINDER_PAD: + joystick_type = joystick_get_from_internal_name("sidewinder_pad"); + break; + case JS_TYPE_THRUSTMASTER_FCS: + joystick_type = joystick_get_from_internal_name("thrustmaster_fcs"); + break; + default: + joystick_type = JS_TYPE_NONE; + break; + } + } + } } else - joystick_type = 0; + joystick_type = JS_TYPE_NONE; - for (c=0; c 511) - fatal("load_sound(): strlen(p) > 511\n"); + sound_card_current[0] = sound_card_get_from_internal_name(p); else - strncpy(temp, p, strlen(p) + 1); - if (!strcmp(temp, "float") || !strcmp(temp, "1")) - sound_is_float = 1; - else - sound_is_float = 0; -} + sound_card_current[0] = 0; + p = ini_section_get_string(cat, "sndcard2", NULL); + /* FIXME: Hack to not break configs with the Sound Blaster 128 PCI set. */ + if ((p != NULL) && (!strcmp(p, "sbpci128") || !strcmp(p, "sb128pci"))) + p = "es1371"; + if (p != NULL) + sound_card_current[1] = sound_card_get_from_internal_name(p); + else + sound_card_current[1] = 0; + + p = ini_section_get_string(cat, "sndcard3", NULL); + /* FIXME: Hack to not break configs with the Sound Blaster 128 PCI set. */ + if ((p != NULL) && (!strcmp(p, "sbpci128") || !strcmp(p, "sb128pci"))) + p = "es1371"; + if (p != NULL) + sound_card_current[2] = sound_card_get_from_internal_name(p); + else + sound_card_current[2] = 0; + + p = ini_section_get_string(cat, "sndcard4", NULL); + /* FIXME: Hack to not break configs with the Sound Blaster 128 PCI set. */ + if ((p != NULL) && (!strcmp(p, "sbpci128") || !strcmp(p, "sb128pci"))) + p = "es1371"; + if (p != NULL) + sound_card_current[3] = sound_card_get_from_internal_name(p); + else + sound_card_current[3] = 0; + + p = ini_section_get_string(cat, "midi_device", NULL); + if (p != NULL) + midi_output_device_current = midi_out_device_get_from_internal_name(p); + else + midi_output_device_current = 0; + + p = ini_section_get_string(cat, "midi_in_device", NULL); + if (p != NULL) + midi_input_device_current = midi_in_device_get_from_internal_name(p); + else + midi_input_device_current = 0; + + mpu401_standalone_enable = !!ini_section_get_int(cat, "mpu401_standalone", 0); + + /* Backwards compatibility for standalone SSI-2001, CMS and GUS from v3.11 and older. */ + const char *legacy_cards[][2] = { + {"ssi2001", "ssi2001"}, + { "gameblaster", "cms" }, + { "gus", "gus" } + }; + for (int i = 0, j = 0; i < (sizeof(legacy_cards) / sizeof(legacy_cards[0])); i++) { + if (ini_section_get_int(cat, legacy_cards[i][0], 0) == 1) { + /* Migrate to the first available sound card slot. */ + for (; j < (sizeof(sound_card_current) / sizeof(sound_card_current[0])); j++) { + if (!sound_card_current[j]) { + sound_card_current[j] = sound_card_get_from_internal_name(legacy_cards[i][1]); + break; + } + } + } + } + + memset(temp, '\0', sizeof(temp)); + p = ini_section_get_string(cat, "sound_type", "float"); + if (strlen(p) > 511) + fatal("load_sound(): strlen(p) > 511\n"); + else + strncpy(temp, p, 511); + if (!strcmp(temp, "float") || !strcmp(temp, "1")) + sound_is_float = 1; + else + sound_is_float = 0; + + p = ini_section_get_string(cat, "fm_driver", "nuked"); + if (!strcmp(p, "ymfm")) { + fm_driver = FM_DRV_YMFM; + } else { + fm_driver = FM_DRV_NUKED; + } +} /* Load "Network" section. */ static void load_network(void) { - char *cat = "Network"; - char *p; + ini_section_t cat = ini_find_section(config, "Network"); + char * p; + char temp[512]; + uint16_t c = 0; + uint16_t min = 0; + netcard_conf_t *nc = &net_cards_conf[c]; - p = config_get_string(cat, "net_type", NULL); + /* Handle legacy configuration which supported only one NIC */ + p = ini_section_get_string(cat, "net_card", NULL); if (p != NULL) { - if (!strcmp(p, "pcap") || !strcmp(p, "1")) - network_type = NET_TYPE_PCAP; - else - if (!strcmp(p, "slirp") || !strcmp(p, "2")) - network_type = NET_TYPE_SLIRP; - else - network_type = NET_TYPE_NONE; - } else - network_type = NET_TYPE_NONE; + nc->device_num = network_card_get_from_internal_name(p); - memset(network_host, '\0', sizeof(network_host)); - p = config_get_string(cat, "net_host_device", NULL); - if (p == NULL) { - p = config_get_string(cat, "net_host_device", NULL); - if (p != NULL) - config_delete_var(cat, "net_host_device"); + p = ini_section_get_string(cat, "net_type", NULL); + if (p != NULL) { + if (!strcmp(p, "pcap") || !strcmp(p, "1")) + nc->net_type = NET_TYPE_PCAP; + else if (!strcmp(p, "slirp") || !strcmp(p, "2")) + nc->net_type = NET_TYPE_SLIRP; + else if (!strcmp(p, "vde") || !strcmp(p, "2")) + nc->net_type = NET_TYPE_VDE; + else + nc->net_type = NET_TYPE_NONE; + } else + nc->net_type = NET_TYPE_NONE; + + p = ini_section_get_string(cat, "net_host_device", NULL); + if (p != NULL) { + if (nc->net_type == NET_TYPE_PCAP) { + if ((network_dev_to_id(p) == -1) || (network_ndev == 1)) { + if (network_ndev == 1) + ui_msgbox_header(MBX_ERROR, (wchar_t *) IDS_2095, (wchar_t *) IDS_2130); + else if (network_dev_to_id(p) == -1) + ui_msgbox_header(MBX_ERROR, (wchar_t *) IDS_2096, (wchar_t *) IDS_2130); + strcpy(nc->host_dev_name, "none"); + } else + strncpy(nc->host_dev_name, p, sizeof(nc->host_dev_name) - 1); + } else + strncpy(nc->host_dev_name, p, sizeof(nc->host_dev_name) - 1); + } else + strcpy(nc->host_dev_name, "none"); + + min++; } - if (p != NULL) { - if ((network_dev_to_id(p) == -1) || (network_ndev == 1)) { - if ((network_ndev == 1) && strcmp(network_host, "none")) { - ui_msgbox_header(MBX_ERROR, (wchar_t *) IDS_2094, (wchar_t *) IDS_2129); - } else if (network_dev_to_id(p) == -1) { - ui_msgbox_header(MBX_ERROR, (wchar_t *) IDS_2095, (wchar_t *) IDS_2129); - } - strcpy(network_host, "none"); - } else { - strncpy(network_host, p, sizeof(network_host) - 1); - } - } else - strcpy(network_host, "none"); + ini_section_delete_var(cat, "net_card"); + ini_section_delete_var(cat, "net_type"); + ini_section_delete_var(cat, "net_host_device"); - p = config_get_string(cat, "net_card", NULL); - if (p != NULL) - network_card = network_card_get_from_internal_name(p); - else - network_card = 0; + for (c = min; c < NET_CARD_MAX; c++) { + nc = &net_cards_conf[c]; + sprintf(temp, "net_%02i_card", c + 1); + p = ini_section_get_string(cat, temp, NULL); + if (p != NULL) + nc->device_num = network_card_get_from_internal_name(p); + else + nc->device_num = 0; + + sprintf(temp, "net_%02i_net_type", c + 1); + p = ini_section_get_string(cat, temp, NULL); + if (p != NULL) { + if (!strcmp(p, "pcap") || !strcmp(p, "1")) + nc->net_type = NET_TYPE_PCAP; + else if (!strcmp(p, "slirp") || !strcmp(p, "2")) + nc->net_type = NET_TYPE_SLIRP; + else if (!strcmp(p, "vde") || !strcmp(p, "2")) + nc->net_type = NET_TYPE_VDE; + else + nc->net_type = NET_TYPE_NONE; + } else + nc->net_type = NET_TYPE_NONE; + + sprintf(temp, "net_%02i_host_device", c + 1); + p = ini_section_get_string(cat, temp, NULL); + if (p != NULL) { + if (nc->net_type == NET_TYPE_PCAP) { + if ((network_dev_to_id(p) == -1) || (network_ndev == 1)) { + if (network_ndev == 1) + ui_msgbox_header(MBX_ERROR, (wchar_t *) IDS_2095, (wchar_t *) IDS_2130); + else if (network_dev_to_id(p) == -1) + ui_msgbox_header(MBX_ERROR, (wchar_t *) IDS_2096, (wchar_t *) IDS_2130); + strcpy(nc->host_dev_name, "none"); + } else + strncpy(nc->host_dev_name, p, sizeof(nc->host_dev_name) - 1); + } else + strncpy(nc->host_dev_name, p, sizeof(nc->host_dev_name) - 1); + } else + strcpy(nc->host_dev_name, "none"); + + sprintf(temp, "net_%02i_link", c + 1); + nc->link_state = ini_section_get_int(cat, temp, + (NET_LINK_10_HD | NET_LINK_10_FD | + NET_LINK_100_HD | NET_LINK_100_FD | + NET_LINK_1000_HD | NET_LINK_1000_FD)); + } } - /* Load "Ports" section. */ static void load_ports(void) { - char *cat = "Ports (COM & LPT)"; - char *p; - char temp[512]; - int c, d; + ini_section_t cat = ini_find_section(config, "Ports (COM & LPT)"); + char *p; + char temp[512]; + int c; + int d; + + memset(temp, 0, sizeof(temp)); for (c = 0; c < SERIAL_MAX; c++) { - sprintf(temp, "serial%d_enabled", c + 1); - serial_enabled[c] = !!config_get_int(cat, temp, (c >= 2) ? 0 : 1); + sprintf(temp, "serial%d_enabled", c + 1); + com_ports[c].enabled = !!ini_section_get_int(cat, temp, (c >= 2) ? 0 : 1); -/* - sprintf(temp, "serial%d_device", c + 1); - p = (char *) config_get_string(cat, temp, "none"); - com_ports[c].device = com_device_get_from_internal_name(p); -*/ + sprintf(temp, "serial%d_passthrough_enabled", c + 1); + serial_passthrough_enabled[c] = !!ini_section_get_int(cat, temp, 0); + + if (serial_passthrough_enabled[c]) + config_log("Serial Port %d: passthrough enabled.\n\n", c + 1); } for (c = 0; c < PARALLEL_MAX; c++) { - sprintf(temp, "lpt%d_enabled", c + 1); - lpt_ports[c].enabled = !!config_get_int(cat, temp, (c == 0) ? 1 : 0); + sprintf(temp, "lpt%d_enabled", c + 1); + lpt_ports[c].enabled = !!ini_section_get_int(cat, temp, (c == 0) ? 1 : 0); - sprintf(temp, "lpt%d_device", c + 1); - p = (char *) config_get_string(cat, temp, "none"); - lpt_ports[c].device = lpt_device_get_from_internal_name(p); + sprintf(temp, "lpt%d_device", c + 1); + p = ini_section_get_string(cat, temp, "none"); + lpt_ports[c].device = lpt_device_get_from_internal_name(p); } /* Legacy config compatibility. */ - d = config_get_int(cat, "lpt_enabled", 2); + d = ini_section_get_int(cat, "lpt_enabled", 2); if (d < 2) { - for (c = 0; c < PARALLEL_MAX; c++) - lpt_ports[c].enabled = d; + for (c = 0; c < PARALLEL_MAX; c++) + lpt_ports[c].enabled = d; } - config_delete_var(cat, "lpt_enabled"); + ini_section_delete_var(cat, "lpt_enabled"); } - /* Load "Storage Controllers" section. */ static void load_storage_controllers(void) { - char *cat = "Storage controllers"; - char *p, temp[512]; - int c, min = 0; - int free_p = 0; - - /* TODO: Backwards compatibility, get rid of this when enough time has passed. */ - backwards_compat2 = (find_section(cat) == NULL); - - /* TODO: Backwards compatibility, get rid of this when enough time has passed. */ - p = config_get_string(cat, "scsicard", NULL); - if (p != NULL) { - scsi_card_current[0] = scsi_card_get_from_internal_name(p); - min++; - } - config_delete_var(cat, "scsi_card"); + ini_section_t cat = ini_find_section(config, "Storage controllers"); + char *p; + char temp[512]; + int c; + int min = 0; + int free_p = 0; for (c = min; c < SCSI_BUS_MAX; c++) { - sprintf(temp, "scsicard_%d", c + 1); + sprintf(temp, "scsicard_%d", c + 1); - p = config_get_string(cat, temp, NULL); - if (p != NULL) - scsi_card_current[c] = scsi_card_get_from_internal_name(p); - else - scsi_card_current[c] = 0; + p = ini_section_get_string(cat, temp, NULL); + if (p != NULL) + scsi_card_current[c] = scsi_card_get_from_internal_name(p); + else + scsi_card_current[c] = 0; } - p = config_get_string(cat, "fdc", NULL); + p = ini_section_get_string(cat, "fdc", NULL); if (p != NULL) - fdc_type = fdc_card_get_from_internal_name(p); - else - fdc_type = FDC_INTERNAL; + fdc_type = fdc_card_get_from_internal_name(p); + else + fdc_type = FDC_INTERNAL; - p = config_get_string(cat, "hdc", NULL); + p = ini_section_get_string(cat, "hdc", NULL); if (p == NULL) { - if (machine_has_flags(machine, MACHINE_HDC)) { - p = (char *)malloc((strlen("internal")+1)*sizeof(char)); - strcpy(p, "internal"); - } else { - p = (char *)malloc((strlen("none")+1)*sizeof(char)); - strcpy(p, "none"); - } - free_p = 1; + if (machine_has_flags(machine, MACHINE_HDC)) { + p = (char *) malloc((strlen("internal") + 1) * sizeof(char)); + strcpy(p, "internal"); + } else { + p = (char *) malloc((strlen("none") + 1) * sizeof(char)); + strcpy(p, "none"); + } + free_p = 1; } if (!strcmp(p, "mfm_xt")) - hdc_current = hdc_get_from_internal_name("st506_xt"); + hdc_current = hdc_get_from_internal_name("st506_xt"); else if (!strcmp(p, "mfm_xt_dtc5150x")) - hdc_current = hdc_get_from_internal_name("st506_xt_dtc5150x"); + hdc_current = hdc_get_from_internal_name("st506_xt_dtc5150x"); else if (!strcmp(p, "mfm_at")) - hdc_current = hdc_get_from_internal_name("st506_at"); + hdc_current = hdc_get_from_internal_name("st506_at"); else if (!strcmp(p, "vlb_isa")) - hdc_current = hdc_get_from_internal_name("ide_vlb"); + hdc_current = hdc_get_from_internal_name("ide_vlb"); else if (!strcmp(p, "vlb_isa_2ch")) - hdc_current = hdc_get_from_internal_name("ide_vlb_2ch"); + hdc_current = hdc_get_from_internal_name("ide_vlb_2ch"); else - hdc_current = hdc_get_from_internal_name(p); + hdc_current = hdc_get_from_internal_name(p); if (free_p) { - free(p); - p = NULL; + free(p); + p = NULL; } - ide_ter_enabled = !!config_get_int(cat, "ide_ter", 0); - ide_qua_enabled = !!config_get_int(cat, "ide_qua", 0); + p = ini_section_get_string(cat, "cdrom_interface", NULL); + if (p != NULL) + cdrom_interface_current = cdrom_interface_get_from_internal_name(p); - /* TODO: Re-enable by default after we actually have a proper machine flag for this. */ - cassette_enable = !!config_get_int(cat, "cassette_enabled", 0); - p = config_get_string(cat, "cassette_file", ""); - if (strlen(p) > 511) - fatal("load_storage_controllers(): strlen(p) > 511\n"); + if (free_p) { + free(p); + p = NULL; + } + + ide_ter_enabled = !!ini_section_get_int(cat, "ide_ter", 0); + ide_qua_enabled = !!ini_section_get_int(cat, "ide_qua", 0); + + if (machine_has_bus(machine, MACHINE_BUS_CASSETTE)) + cassette_enable = !!ini_section_get_int(cat, "cassette_enabled", 0); else - strncpy(cassette_fname, p, MIN(512, strlen(p) + 1)); - p = config_get_string(cat, "cassette_mode", ""); + cassette_enable = 0; + p = ini_section_get_string(cat, "cassette_file", ""); if (strlen(p) > 511) - fatal("load_storage_controllers(): strlen(p) > 511\n"); + fatal("load_storage_controllers(): strlen(p) > 511\n"); else - strncpy(cassette_mode, p, MIN(512, strlen(p) + 1)); - cassette_pos = config_get_int(cat, "cassette_position", 0); - cassette_srate = config_get_int(cat, "cassette_srate", 44100); - cassette_append = !!config_get_int(cat, "cassette_append", 0); - cassette_pcm = config_get_int(cat, "cassette_pcm", 0); - cassette_ui_writeprot = !!config_get_int(cat, "cassette_writeprot", 0); + strncpy(cassette_fname, p, 511); + p = ini_section_get_string(cat, "cassette_mode", ""); + if (strlen(p) > 511) + fatal("load_storage_controllers(): strlen(p) > 511\n"); + else + strncpy(cassette_mode, p, 511); + cassette_pos = ini_section_get_int(cat, "cassette_position", 0); + cassette_srate = ini_section_get_int(cat, "cassette_srate", 44100); + cassette_append = !!ini_section_get_int(cat, "cassette_append", 0); + cassette_pcm = ini_section_get_int(cat, "cassette_pcm", 0); + cassette_ui_writeprot = !!ini_section_get_int(cat, "cassette_writeprot", 0); - for (c=0; c<2; c++) { - sprintf(temp, "cartridge_%02i_fn", c + 1); - p = config_get_string(cat, temp, ""); + for (c = 0; c < 2; c++) { + sprintf(temp, "cartridge_%02i_fn", c + 1); + p = ini_section_get_string(cat, temp, ""); -#if 0 - /* - * NOTE: - * Temporary hack to remove the absolute - * path currently saved in most config - * files. We should remove this before - * finalizing this release! --FvK - */ - if (! wcsnicmp(wp, usr_path, wcslen(usr_path))) { - /* - * Yep, its absolute and prefixed - * with the EXE path. Just strip - * that off for now... - */ - wcsncpy(floppyfns[c], &wp[wcslen(usr_path)], sizeof_w(cart_fns[c])); - } else -#endif - if (strlen(p) > 511) - fatal("load_storage_controllers(): strlen(p) > 511\n"); - else - strncpy(cart_fns[c], p, strlen(p) + 1); + if (!strcmp(p, usr_path)) + p[0] = 0x00; + + if (p[0] != 0x00) { + if (path_abs(p)) { + if (strlen(p) > 511) + fatal("load_storage_controllers(): strlen(p) > 511 (cart_fns[%i])\n", c); + else + strncpy(cart_fns[c], p, 511); + } else + path_append_filename(cart_fns[c], usr_path, p); + path_normalize(cart_fns[c]); + } } } - /* Load "Hard Disks" section. */ static void load_hard_disks(void) { - char *cat = "Hard disks"; - char temp[512], tmp2[512]; - char s[512]; - int c; - char *p; - uint32_t max_spt, max_hpc, max_tracks; - uint32_t board = 0, dev = 0; + ini_section_t cat = ini_find_section(config, "Hard disks"); + char temp[512]; + char tmp2[512]; + char s[512]; + char *p; + uint32_t max_spt; + uint32_t max_hpc; + uint32_t max_tracks; + uint32_t board = 0; + uint32_t dev = 0; memset(temp, '\0', sizeof(temp)); - for (c=0; c max_spt) - hdd[c].spt = max_spt; - if (hdd[c].hpc > max_hpc) - hdd[c].hpc = max_hpc; - if (hdd[c].tracks > max_tracks) - hdd[c].tracks = max_tracks; + if (hdd[c].spt > max_spt) + hdd[c].spt = max_spt; + if (hdd[c].hpc > max_hpc) + hdd[c].hpc = max_hpc; + if (hdd[c].tracks > max_tracks) + hdd[c].tracks = max_tracks; - /* MFM/RLL */ - sprintf(temp, "hdd_%02i_mfm_channel", c+1); - if (hdd[c].bus == HDD_BUS_MFM) - hdd[c].mfm_channel = !!config_get_int(cat, temp, c & 1); - else - config_delete_var(cat, temp); + sprintf(temp, "hdd_%02i_speed", c + 1); + switch (hdd[c].bus) { + case HDD_BUS_IDE: + case HDD_BUS_ESDI: + case HDD_BUS_ATAPI: + case HDD_BUS_SCSI: + sprintf(tmp2, "1997_5400rpm"); + break; + default: + sprintf(tmp2, "ramdisk"); + break; + } + p = ini_section_get_string(cat, temp, tmp2); + hdd[c].speed_preset = hdd_preset_get_from_internal_name(p); - /* XTA */ - sprintf(temp, "hdd_%02i_xta_channel", c+1); - if (hdd[c].bus == HDD_BUS_XTA) - hdd[c].xta_channel = !!config_get_int(cat, temp, c & 1); - else - config_delete_var(cat, temp); + /* MFM/RLL */ + sprintf(temp, "hdd_%02i_mfm_channel", c + 1); + if (hdd[c].bus == HDD_BUS_MFM) + hdd[c].mfm_channel = !!ini_section_get_int(cat, temp, c & 1); + else + ini_section_delete_var(cat, temp); - /* ESDI */ - sprintf(temp, "hdd_%02i_esdi_channel", c+1); - if (hdd[c].bus == HDD_BUS_ESDI) - hdd[c].esdi_channel = !!config_get_int(cat, temp, c & 1); - else - config_delete_var(cat, temp); + /* XTA */ + sprintf(temp, "hdd_%02i_xta_channel", c + 1); + if (hdd[c].bus == HDD_BUS_XTA) + hdd[c].xta_channel = !!ini_section_get_int(cat, temp, c & 1); + else + ini_section_delete_var(cat, temp); - /* IDE */ - sprintf(temp, "hdd_%02i_ide_channel", c+1); - if (hdd[c].bus == HDD_BUS_IDE) { - sprintf(tmp2, "%01u:%01u", c>>1, c&1); - p = config_get_string(cat, temp, tmp2); - sscanf(p, "%01u:%01u", &board, &dev); - board &= 3; - dev &= 1; - hdd[c].ide_channel = (board<<1) + dev; + /* ESDI */ + sprintf(temp, "hdd_%02i_esdi_channel", c + 1); + if (hdd[c].bus == HDD_BUS_ESDI) + hdd[c].esdi_channel = !!ini_section_get_int(cat, temp, c & 1); + else + ini_section_delete_var(cat, temp); - if (hdd[c].ide_channel > 7) - hdd[c].ide_channel = 7; - } else { - config_delete_var(cat, temp); - } + /* IDE */ + sprintf(temp, "hdd_%02i_ide_channel", c + 1); + if ((hdd[c].bus == HDD_BUS_IDE) || (hdd[c].bus == HDD_BUS_ATAPI)) { + sprintf(tmp2, "%01u:%01u", c >> 1, c & 1); + p = ini_section_get_string(cat, temp, tmp2); + sscanf(p, "%01u:%01u", &board, &dev); + board &= 3; + dev &= 1; + hdd[c].ide_channel = (board << 1) + dev; - /* SCSI */ - if (hdd[c].bus == HDD_BUS_SCSI) { - sprintf(temp, "hdd_%02i_scsi_location", c+1); - sprintf(tmp2, "%01u:%02u", SCSI_BUS_MAX, c+2); - p = config_get_string(cat, temp, tmp2); - sscanf(p, "%01u:%02u", &board, &dev); - if (board >= SCSI_BUS_MAX) { - /* Invalid bus - check legacy ID */ - sprintf(temp, "hdd_%02i_scsi_id", c+1); - hdd[c].scsi_id = config_get_int(cat, temp, c+2); + if (hdd[c].ide_channel > 7) + hdd[c].ide_channel = 7; + } else { + ini_section_delete_var(cat, temp); + } - if (hdd[c].scsi_id > 15) - hdd[c].scsi_id = 15; - } else { - board %= SCSI_BUS_MAX; - dev &= 15; - hdd[c].scsi_id = (board<<4)+dev; - } - } else { - sprintf(temp, "hdd_%02i_scsi_location", c+1); - config_delete_var(cat, temp); - } + /* SCSI */ + if (hdd[c].bus == HDD_BUS_SCSI) { + sprintf(temp, "hdd_%02i_scsi_location", c + 1); + sprintf(tmp2, "%01u:%02u", SCSI_BUS_MAX, c + 2); + p = ini_section_get_string(cat, temp, tmp2); + sscanf(p, "%01u:%02u", &board, &dev); + if (board >= SCSI_BUS_MAX) { + /* Invalid bus - check legacy ID */ + sprintf(temp, "hdd_%02i_scsi_id", c + 1); + hdd[c].scsi_id = ini_section_get_int(cat, temp, c + 2); - sprintf(temp, "hdd_%02i_scsi_id", c+1); - config_delete_var(cat, temp); + if (hdd[c].scsi_id > 15) + hdd[c].scsi_id = 15; + } else { + board %= SCSI_BUS_MAX; + dev &= 15; + hdd[c].scsi_id = (board << 4) + dev; + } + } else { + sprintf(temp, "hdd_%02i_scsi_location", c + 1); + ini_section_delete_var(cat, temp); + } - memset(hdd[c].fn, 0x00, sizeof(hdd[c].fn)); - memset(hdd[c].prev_fn, 0x00, sizeof(hdd[c].prev_fn)); - sprintf(temp, "hdd_%02i_fn", c+1); - p = config_get_string(cat, temp, ""); + sprintf(temp, "hdd_%02i_scsi_id", c + 1); + ini_section_delete_var(cat, temp); -#if 0 - /* - * NOTE: - * Temporary hack to remove the absolute - * path currently saved in most config - * files. We should remove this before - * finalizing this release! --FvK - */ - /* - * ANOTHER NOTE: - * When loading differencing VHDs, the absolute path is required. - * So we should not convert absolute paths to relative. -sards - */ - if (! wcsnicmp(wp, usr_path, wcslen(usr_path))) { - /* - * Yep, its absolute and prefixed - * with the CFG path. Just strip - * that off for now... - */ - wcsncpy(hdd[c].fn, &wp[wcslen(usr_path)], sizeof_w(hdd[c].fn)); - } else -#endif - if (plat_path_abs(p)) { - strncpy(hdd[c].fn, p, sizeof(hdd[c].fn) - 1); - } else { - plat_append_filename(hdd[c].fn, usr_path, p); - } + memset(hdd[c].fn, 0x00, sizeof(hdd[c].fn)); + sprintf(temp, "hdd_%02i_fn", c + 1); + p = ini_section_get_string(cat, temp, ""); - /* If disk is empty or invalid, mark it for deletion. */ - if (! hdd_is_valid(c)) { - sprintf(temp, "hdd_%02i_parameters", c+1); - config_delete_var(cat, temp); + /* + * NOTE: + * When loading differencing VHDs, the absolute path is required. + * So we should not convert absolute paths to relative. -sards + */ + if (!strcmp(p, usr_path)) + p[0] = 0x00; - sprintf(temp, "hdd_%02i_preide_channels", c+1); - config_delete_var(cat, temp); + if (p[0] != 0x00) { + if (path_abs(p)) { + if (strlen(p) > 511) + fatal("load_hard_disks(): strlen(p) > 511 (hdd[%i].fn)\n", c); + else + strncpy(hdd[c].fn, p, 511); + } else + path_append_filename(hdd[c].fn, usr_path, p); + path_normalize(hdd[c].fn); + } - sprintf(temp, "hdd_%02i_ide_channels", c+1); - config_delete_var(cat, temp); + sprintf(temp, "hdd_%02i_vhd_blocksize", c + 1); + hdd[c].vhd_blocksize = ini_section_get_int(cat, temp, 0); - sprintf(temp, "hdd_%02i_scsi_id", c+1); - config_delete_var(cat, temp); + sprintf(temp, "hdd_%02i_vhd_parent", c + 1); + p = ini_section_get_string(cat, temp, ""); + strncpy(hdd[c].vhd_parent, p, sizeof(hdd[c].vhd_parent) - 1); - sprintf(temp, "hdd_%02i_fn", c+1); - config_delete_var(cat, temp); - } + /* If disk is empty or invalid, mark it for deletion. */ + if (!hdd_is_valid(c)) { + sprintf(temp, "hdd_%02i_parameters", c + 1); + ini_section_delete_var(cat, temp); - sprintf(temp, "hdd_%02i_mfm_channel", c+1); - config_delete_var(cat, temp); + sprintf(temp, "hdd_%02i_preide_channels", c + 1); + ini_section_delete_var(cat, temp); - sprintf(temp, "hdd_%02i_ide_channel", c+1); - config_delete_var(cat, temp); + sprintf(temp, "hdd_%02i_ide_channels", c + 1); + ini_section_delete_var(cat, temp); + + sprintf(temp, "hdd_%02i_scsi_id", c + 1); + ini_section_delete_var(cat, temp); + + sprintf(temp, "hdd_%02i_fn", c + 1); + ini_section_delete_var(cat, temp); + } + + sprintf(temp, "hdd_%02i_mfm_channel", c + 1); + ini_section_delete_var(cat, temp); + + sprintf(temp, "hdd_%02i_ide_channel", c + 1); + ini_section_delete_var(cat, temp); } } - -/* TODO: Backwards compatibility, get rid of this when enough time has passed. */ -/* Load "Floppy Drives" section. */ -static void -load_floppy_drives(void) -{ - char *cat = "Floppy drives"; - char temp[512], *p; - int c; - - if (!backwards_compat) - return; - - for (c=0; c 13) - fdd_set_type(c, 13); - config_delete_var(cat, temp); - - sprintf(temp, "fdd_%02i_fn", c + 1); - p = config_get_string(cat, temp, ""); - config_delete_var(cat, temp); - -#if 0 - /* - * NOTE: - * Temporary hack to remove the absolute - * path currently saved in most config - * files. We should remove this before - * finalizing this release! --FvK - */ - if (! wcsnicmp(wp, usr_path, wcslen(usr_path))) { - /* - * Yep, its absolute and prefixed - * with the EXE path. Just strip - * that off for now... - */ - wcsncpy(floppyfns[c], &wp[wcslen(usr_path)], sizeof_w(floppyfns[c])); - } else -#endif - if (strlen(p) > 511) - fatal("load_floppy_drives(): strlen(p) > 511\n"); - else - strncpy(floppyfns[c], p, strlen(p) + 1); - - /* if (*wp != L'\0') - config_log("Floppy%d: %ls\n", c, floppyfns[c]); */ - sprintf(temp, "fdd_%02i_writeprot", c+1); - ui_writeprot[c] = !!config_get_int(cat, temp, 0); - config_delete_var(cat, temp); - sprintf(temp, "fdd_%02i_turbo", c + 1); - fdd_set_turbo(c, !!config_get_int(cat, temp, 0)); - config_delete_var(cat, temp); - sprintf(temp, "fdd_%02i_check_bpb", c+1); - fdd_set_check_bpb(c, !!config_get_int(cat, temp, 1)); - config_delete_var(cat, temp); - } - - delete_section_if_empty(cat); -} - - /* Load "Floppy and CD-ROM Drives" section. */ static void load_floppy_and_cdrom_drives(void) { - char *cat = "Floppy and CD-ROM drives"; - char temp[512], tmp2[512], *p; - char s[512]; - unsigned int board = 0, dev = 0; - int c, d = 0; - - /* TODO: Backwards compatibility, get rid of this when enough time has passed. */ - backwards_compat = (find_section(cat) == NULL); + ini_section_t cat = ini_find_section(config, "Floppy and CD-ROM drives"); + char temp[512]; + char tmp2[512]; + char *p; + char s[512]; + unsigned int board = 0; + unsigned int dev = 0; + int c; + int d = 0; memset(temp, 0x00, sizeof(temp)); - for (c=0; c 13) - fdd_set_type(c, 13); + for (c = 0; c < FDD_NUM; c++) { + sprintf(temp, "fdd_%02i_type", c + 1); + p = ini_section_get_string(cat, temp, (c < 2) ? "525_2dd" : "none"); + fdd_set_type(c, fdd_get_from_internal_name(p)); + if (fdd_get_type(c) > 13) + fdd_set_type(c, 13); - sprintf(temp, "fdd_%02i_fn", c + 1); - p = config_get_string(cat, temp, ""); + sprintf(temp, "fdd_%02i_fn", c + 1); + p = ini_section_get_string(cat, temp, ""); -#if 0 - /* - * NOTE: - * Temporary hack to remove the absolute - * path currently saved in most config - * files. We should remove this before - * finalizing this release! --FvK - */ - if (! wcsnicmp(wp, usr_path, wcslen(usr_path))) { - /* - * Yep, its absolute and prefixed - * with the EXE path. Just strip - * that off for now... - */ - wcsncpy(floppyfns[c], &wp[wcslen(usr_path)], sizeof_w(floppyfns[c])); - } else + if (!strcmp(p, usr_path)) + p[0] = 0x00; + + if (p[0] != 0x00) { + if (path_abs(p)) { + if (strlen(p) > 511) + fatal("load_floppy_and_cdrom_drives(): strlen(p) > 511 (floppyfns[%i])\n", c); + else + strncpy(floppyfns[c], p, 511); + } else + path_append_filename(floppyfns[c], usr_path, p); + path_normalize(floppyfns[c]); + } + +#if defined(ENABLE_CONFIG_LOG) && (ENABLE_CONFIG_LOG == 2) + if (*p != '\0') + config_log("Floppy%d: %ls\n", c, floppyfns[c]); #endif - if (strlen(p) > 511) - fatal("load_floppy_and_cdrom_drives(): strlen(p) > 511\n"); - else - strncpy(floppyfns[c], p, strlen(p) + 1); + sprintf(temp, "fdd_%02i_writeprot", c + 1); + ui_writeprot[c] = !!ini_section_get_int(cat, temp, 0); + sprintf(temp, "fdd_%02i_turbo", c + 1); + fdd_set_turbo(c, !!ini_section_get_int(cat, temp, 0)); + sprintf(temp, "fdd_%02i_check_bpb", c + 1); + fdd_set_check_bpb(c, !!ini_section_get_int(cat, temp, 1)); - /* if (*wp != L'\0') - config_log("Floppy%d: %ls\n", c, floppyfns[c]); */ - sprintf(temp, "fdd_%02i_writeprot", c+1); - ui_writeprot[c] = !!config_get_int(cat, temp, 0); - sprintf(temp, "fdd_%02i_turbo", c + 1); - fdd_set_turbo(c, !!config_get_int(cat, temp, 0)); - sprintf(temp, "fdd_%02i_check_bpb", c+1); - fdd_set_check_bpb(c, !!config_get_int(cat, temp, 1)); - - /* Check whether each value is default, if yes, delete it so that only non-default values will later be saved. */ - if (fdd_get_type(c) == ((c < 2) ? 2 : 0)) { - sprintf(temp, "fdd_%02i_type", c+1); - config_delete_var(cat, temp); - } - if (strlen(floppyfns[c]) == 0) { - sprintf(temp, "fdd_%02i_fn", c+1); - config_delete_var(cat, temp); - } - if (ui_writeprot[c] == 0) { - sprintf(temp, "fdd_%02i_writeprot", c+1); - config_delete_var(cat, temp); - } - if (fdd_get_turbo(c) == 0) { - sprintf(temp, "fdd_%02i_turbo", c+1); - config_delete_var(cat, temp); - } - if (fdd_get_check_bpb(c) == 1) { - sprintf(temp, "fdd_%02i_check_bpb", c+1); - config_delete_var(cat, temp); - } + /* Check whether each value is default, if yes, delete it so that only + non-default values will later be saved. */ + if (fdd_get_type(c) == ((c < 2) ? 2 : 0)) { + sprintf(temp, "fdd_%02i_type", c + 1); + ini_section_delete_var(cat, temp); + } + if (strlen(floppyfns[c]) == 0) { + sprintf(temp, "fdd_%02i_fn", c + 1); + ini_section_delete_var(cat, temp); + } + if (ui_writeprot[c] == 0) { + sprintf(temp, "fdd_%02i_writeprot", c + 1); + ini_section_delete_var(cat, temp); + } + if (fdd_get_turbo(c) == 0) { + sprintf(temp, "fdd_%02i_turbo", c + 1); + ini_section_delete_var(cat, temp); + } + if (fdd_get_check_bpb(c) == 1) { + sprintf(temp, "fdd_%02i_check_bpb", c + 1); + ini_section_delete_var(cat, temp); + } + for (int i = 0; i < MAX_PREV_IMAGES; i++) { + fdd_image_history[c][i] = (char *) calloc((MAX_IMAGE_PATH_LEN + 1) << 1, sizeof(char)); + sprintf(temp, "fdd_%02i_image_history_%02i", c + 1, i + 1); + p = ini_section_get_string(cat, temp, NULL); + if (p) { + if (path_abs(p)) { + if (strlen(p) > 255) + fatal("load_floppy_and_cdrom_drives(): strlen(p) > 255 " + "(fdd_image_history[%i][%i])\n", c, i); + else + snprintf(fdd_image_history[c][i], 255, "%s", p); + } else + snprintf(fdd_image_history[c][i], 255, "%s%s%s", usr_path, + path_get_slash(usr_path), p); + path_normalize(fdd_image_history[c][i]); + } + } } memset(temp, 0x00, sizeof(temp)); - for (c=0; c KNOWN_CDROM_DRIVE_TYPES) + cdrom_set_type(c, KNOWN_CDROM_DRIVE_TYPES); + ini_section_delete_var(cat, temp); - if (cdrom[c].bus_type == CDROM_BUS_ATAPI) { - sprintf(temp, "cdrom_%02i_ide_channel", c+1); - sprintf(tmp2, "%01u:%01u", (c+2)>>1, (c+2)&1); - p = config_get_string(cat, temp, tmp2); - sscanf(p, "%01u:%01u", &board, &dev); - board &= 3; - dev &= 1; - cdrom[c].ide_channel = (board<<1)+dev; + /* Default values, needed for proper operation of the Settings dialog. */ + cdrom[c].ide_channel = cdrom[c].scsi_device_id = c + 2; - if (cdrom[c].ide_channel > 7) - cdrom[c].ide_channel = 7; - } else if (cdrom[c].bus_type == CDROM_BUS_SCSI) { - sprintf(temp, "cdrom_%02i_scsi_location", c+1); - sprintf(tmp2, "%01u:%02u", SCSI_BUS_MAX, c+2); - p = config_get_string(cat, temp, tmp2); - sscanf(p, "%01u:%02u", &board, &dev); - if (board >= SCSI_BUS_MAX) { - /* Invalid bus - check legacy ID */ - sprintf(temp, "cdrom_%02i_scsi_id", c+1); - cdrom[c].scsi_device_id = config_get_int(cat, temp, c+2); + if (cdrom[c].bus_type == CDROM_BUS_ATAPI) { + sprintf(temp, "cdrom_%02i_ide_channel", c + 1); + sprintf(tmp2, "%01u:%01u", (c + 2) >> 1, (c + 2) & 1); + p = ini_section_get_string(cat, temp, tmp2); + sscanf(p, "%01u:%01u", &board, &dev); + board &= 3; + dev &= 1; + cdrom[c].ide_channel = (board << 1) + dev; - if (cdrom[c].scsi_device_id > 15) - cdrom[c].scsi_device_id = 15; - } else { - board %= SCSI_BUS_MAX; - dev &= 15; - cdrom[c].scsi_device_id = (board<<4)+dev; - } - } + if (cdrom[c].ide_channel > 7) + cdrom[c].ide_channel = 7; + } else if (cdrom[c].bus_type == CDROM_BUS_SCSI) { + sprintf(temp, "cdrom_%02i_scsi_location", c + 1); + sprintf(tmp2, "%01u:%02u", SCSI_BUS_MAX, c + 2); + p = ini_section_get_string(cat, temp, tmp2); + sscanf(p, "%01u:%02u", &board, &dev); + if (board >= SCSI_BUS_MAX) { + /* Invalid bus - check legacy ID */ + sprintf(temp, "cdrom_%02i_scsi_id", c + 1); + cdrom[c].scsi_device_id = ini_section_get_int(cat, temp, c + 2); - if (cdrom[c].bus_type != CDROM_BUS_ATAPI) { - sprintf(temp, "cdrom_%02i_ide_channel", c+1); - config_delete_var(cat, temp); - } + if (cdrom[c].scsi_device_id > 15) + cdrom[c].scsi_device_id = 15; + } else { + board %= SCSI_BUS_MAX; + dev &= 15; + cdrom[c].scsi_device_id = (board << 4) + dev; + } + } - if (cdrom[c].bus_type != CDROM_BUS_SCSI) { - sprintf(temp, "cdrom_%02i_scsi_location", c+1); - config_delete_var(cat, temp); - } + if (cdrom[c].bus_type != CDROM_BUS_ATAPI) { + sprintf(temp, "cdrom_%02i_ide_channel", c + 1); + ini_section_delete_var(cat, temp); + } - sprintf(temp, "cdrom_%02i_scsi_id", c+1); - config_delete_var(cat, temp); + if (cdrom[c].bus_type != CDROM_BUS_SCSI) { + sprintf(temp, "cdrom_%02i_scsi_location", c + 1); + ini_section_delete_var(cat, temp); + } - sprintf(temp, "cdrom_%02i_image_path", c+1); - p = config_get_string(cat, temp, ""); + sprintf(temp, "cdrom_%02i_scsi_id", c + 1); + ini_section_delete_var(cat, temp); -#if 0 - /* - * NOTE: - * Temporary hack to remove the absolute - * path currently saved in most config - * files. We should remove this before - * finalizing this release! --FvK - */ - if (! wcsnicmp(wp, usr_path, wcslen(usr_path))) { - /* - * Yep, its absolute and prefixed - * with the EXE path. Just strip - * that off for now... - */ - wcsncpy(cdrom[c].image_path, &wp[wcslen(usr_path)], sizeof_w(cdrom[c].image_path)); - } else -#endif - strncpy(cdrom[c].image_path, p, sizeof(cdrom[c].image_path) - 1); + sprintf(temp, "cdrom_%02i_image_path", c + 1); + p = ini_section_get_string(cat, temp, ""); - if (cdrom[c].host_drive && (cdrom[c].host_drive != 200)) - cdrom[c].host_drive = 0; + if (!strcmp(p, usr_path)) + p[0] = 0x00; - if ((cdrom[c].host_drive == 0x200) && - (strlen(cdrom[c].image_path) == 0)) - cdrom[c].host_drive = 0; + if (p[0] != 0x00) { + if (path_abs(p)) { + if (strlen(p) > 511) + fatal("load_floppy_and_cdrom_drives(): strlen(p) > 511 (cdrom[%i].image_path)\n", c); + else + strncpy(cdrom[c].image_path, p, 511); + } else + path_append_filename(cdrom[c].image_path, usr_path, p); + path_normalize(cdrom[c].image_path); + } - /* If the CD-ROM is disabled, delete all its variables. */ - if (cdrom[c].bus_type == CDROM_BUS_DISABLED) { - sprintf(temp, "cdrom_%02i_host_drive", c+1); - config_delete_var(cat, temp); + if (cdrom[c].host_drive && (cdrom[c].host_drive != 200)) + cdrom[c].host_drive = 0; - sprintf(temp, "cdrom_%02i_parameters", c+1); - config_delete_var(cat, temp); + if ((cdrom[c].host_drive == 0x200) && (strlen(cdrom[c].image_path) == 0)) + cdrom[c].host_drive = 0; - sprintf(temp, "cdrom_%02i_ide_channel", c+1); - config_delete_var(cat, temp); + for (int i = 0; i < MAX_PREV_IMAGES; i++) { + cdrom[c].image_history[i] = (char *) calloc((MAX_IMAGE_PATH_LEN + 1) << 1, sizeof(char)); + sprintf(temp, "cdrom_%02i_image_history_%02i", c + 1, i + 1); + p = ini_section_get_string(cat, temp, NULL); + if (p) { + if (path_abs(p)) { + if (strlen(p) > 511) + fatal("load_floppy_and_cdrom_drives(): strlen(p) > 511 " + "(cdrom[%i].image_history[%i])\n", c, i); + else + snprintf(cdrom[c].image_history[i], 511, "%s", p); + } else + snprintf(cdrom[c].image_history[i], 511, "%s%s%s", usr_path, + path_get_slash(usr_path), p); + path_normalize(cdrom[c].image_history[i]); + } + } - sprintf(temp, "cdrom_%02i_scsi_id", c+1); - config_delete_var(cat, temp); + /* If the CD-ROM is disabled, delete all its variables. */ + if (cdrom[c].bus_type == CDROM_BUS_DISABLED) { + sprintf(temp, "cdrom_%02i_host_drive", c + 1); + ini_section_delete_var(cat, temp); - sprintf(temp, "cdrom_%02i_image_path", c+1); - config_delete_var(cat, temp); - } + sprintf(temp, "cdrom_%02i_parameters", c + 1); + ini_section_delete_var(cat, temp); - sprintf(temp, "cdrom_%02i_iso_path", c+1); - config_delete_var(cat, temp); + sprintf(temp, "cdrom_%02i_ide_channel", c + 1); + ini_section_delete_var(cat, temp); + + sprintf(temp, "cdrom_%02i_scsi_id", c + 1); + ini_section_delete_var(cat, temp); + + sprintf(temp, "cdrom_%02i_image_path", c + 1); + ini_section_delete_var(cat, temp); + + for (int i = 0; i < MAX_PREV_IMAGES; i++) { + sprintf(temp, "cdrom_%02i_image_history_%02i", c + 1, i + 1); + ini_section_delete_var(cat, temp); + } + } + + sprintf(temp, "cdrom_%02i_iso_path", c + 1); + ini_section_delete_var(cat, temp); } } - /* Load "Other Removable Devices" section. */ static void load_other_removable_devices(void) { - char *cat = "Other removable devices"; - char temp[512], tmp2[512], *p; - char s[512]; - unsigned int board = 0, dev = 0; - int c, d = 0; - - /* TODO: Backwards compatibility, get rid of this when enough time has passed. */ - if (backwards_compat) { - memset(temp, 0x00, sizeof(temp)); - for (c=0; c>1, (c+2)&1); - p = config_get_string(cat, temp, tmp2); - sscanf(p, "%01u:%01u", &board, &dev); - board &= 3; - dev &= 1; - cdrom[c].ide_channel = (board<<1)+dev; - - if (cdrom[c].ide_channel > 7) - cdrom[c].ide_channel = 7; - - config_delete_var(cat, temp); - } else if (cdrom[c].bus_type == CDROM_BUS_SCSI) { - sprintf(temp, "cdrom_%02i_scsi_id", c+1); - cdrom[c].scsi_device_id = config_get_int(cat, temp, c+2); - - if (cdrom[c].scsi_device_id > 15) - cdrom[c].scsi_device_id = 15; - - config_delete_var(cat, temp); - } - - sprintf(temp, "cdrom_%02i_image_path", c+1); - p = config_get_string(cat, temp, ""); - config_delete_var(cat, temp); - -#if 0 - /* - * NOTE: - * Temporary hack to remove the absolute - * path currently saved in most config - * files. We should remove this before - * finalizing this release! --FvK - */ - if (! wcsnicmp(wp, usr_path, wcslen(usr_path))) { - /* - * Yep, its absolute and prefixed - * with the EXE path. Just strip - * that off for now... - */ - wcsncpy(cdrom[c].image_path, &wp[wcslen(usr_path)], sizeof_w(cdrom[c].image_path)); - } else -#endif - strncpy(cdrom[c].image_path, p, sizeof(cdrom[c].image_path) - 1); - - if (cdrom[c].host_drive && (cdrom[c].host_drive != 200)) - cdrom[c].host_drive = 0; - - if ((cdrom[c].host_drive == 0x200) && - (strlen(cdrom[c].image_path) == 0)) - cdrom[c].host_drive = 0; - } - } - backwards_compat = 0; + ini_section_t cat = ini_find_section(config, "Other removable devices"); + char temp[512]; + char tmp2[512]; + char *p; + char s[512]; + unsigned int board = 0; + unsigned int dev = 0; + int c; memset(temp, 0x00, sizeof(temp)); - for (c=0; c>1, (c+2)&1); - p = config_get_string(cat, temp, tmp2); - sscanf(p, "%01u:%01u", &board, &dev); - board &= 3; - dev &= 1; - zip_drives[c].ide_channel = (board<<1)+dev; + if (zip_drives[c].bus_type == ZIP_BUS_ATAPI) { + sprintf(temp, "zip_%02i_ide_channel", c + 1); + sprintf(tmp2, "%01u:%01u", (c + 2) >> 1, (c + 2) & 1); + p = ini_section_get_string(cat, temp, tmp2); + sscanf(p, "%01u:%01u", &board, &dev); + board &= 3; + dev &= 1; + zip_drives[c].ide_channel = (board << 1) + dev; - if (zip_drives[c].ide_channel > 7) - zip_drives[c].ide_channel = 7; - } else if (zip_drives[c].bus_type == ZIP_BUS_SCSI) { - sprintf(temp, "zip_%02i_scsi_location", c+1); - sprintf(tmp2, "%01u:%02u", SCSI_BUS_MAX, c+2); - p = config_get_string(cat, temp, tmp2); - sscanf(p, "%01u:%02u", &board, &dev); - if (board >= SCSI_BUS_MAX) { - /* Invalid bus - check legacy ID */ - sprintf(temp, "zip_%02i_scsi_id", c+1); - zip_drives[c].scsi_device_id = config_get_int(cat, temp, c+2); + if (zip_drives[c].ide_channel > 7) + zip_drives[c].ide_channel = 7; + } else if (zip_drives[c].bus_type == ZIP_BUS_SCSI) { + sprintf(temp, "zip_%02i_scsi_location", c + 1); + sprintf(tmp2, "%01u:%02u", SCSI_BUS_MAX, c + 2); + p = ini_section_get_string(cat, temp, tmp2); + sscanf(p, "%01u:%02u", &board, &dev); + if (board >= SCSI_BUS_MAX) { + /* Invalid bus - check legacy ID */ + sprintf(temp, "zip_%02i_scsi_id", c + 1); + zip_drives[c].scsi_device_id = ini_section_get_int(cat, temp, c + 2); - if (zip_drives[c].scsi_device_id > 15) - zip_drives[c].scsi_device_id = 15; - } else { - board %= SCSI_BUS_MAX; - dev &= 15; - zip_drives[c].scsi_device_id = (board<<4)+dev; - } - } + if (zip_drives[c].scsi_device_id > 15) + zip_drives[c].scsi_device_id = 15; + } else { + board %= SCSI_BUS_MAX; + dev &= 15; + zip_drives[c].scsi_device_id = (board << 4) + dev; + } + } - if (zip_drives[c].bus_type != ZIP_BUS_ATAPI) { - sprintf(temp, "zip_%02i_ide_channel", c+1); - config_delete_var(cat, temp); - } + if (zip_drives[c].bus_type != ZIP_BUS_ATAPI) { + sprintf(temp, "zip_%02i_ide_channel", c + 1); + ini_section_delete_var(cat, temp); + } - if (zip_drives[c].bus_type != ZIP_BUS_SCSI) { - sprintf(temp, "zip_%02i_scsi_location", c+1); - config_delete_var(cat, temp); - } + if (zip_drives[c].bus_type != ZIP_BUS_SCSI) { + sprintf(temp, "zip_%02i_scsi_location", c + 1); + ini_section_delete_var(cat, temp); + } - sprintf(temp, "zip_%02i_scsi_id", c+1); - config_delete_var(cat, temp); + sprintf(temp, "zip_%02i_scsi_id", c + 1); + ini_section_delete_var(cat, temp); - sprintf(temp, "zip_%02i_image_path", c+1); - p = config_get_string(cat, temp, ""); + sprintf(temp, "zip_%02i_image_path", c + 1); + p = ini_section_get_string(cat, temp, ""); -#if 0 - /* - * NOTE: - * Temporary hack to remove the absolute - * path currently saved in most config - * files. We should remove this before - * finalizing this release! --FvK - */ - if (! wcsnicmp(wp, usr_path, wcslen(usr_path))) { - /* - * Yep, its absolute and prefixed - * with the EXE path. Just strip - * that off for now... - */ - wcsncpy(zip_drives[c].image_path, &wp[wcslen(usr_path)], sizeof_w(zip_drives[c].image_path)); - } else -#endif - strncpy(zip_drives[c].image_path, p, sizeof(zip_drives[c].image_path) - 1); + if (!strcmp(p, usr_path)) + p[0] = 0x00; - /* If the CD-ROM is disabled, delete all its variables. */ - if (zip_drives[c].bus_type == ZIP_BUS_DISABLED) { - sprintf(temp, "zip_%02i_host_drive", c+1); - config_delete_var(cat, temp); + if (p[0] != 0x00) { + if (path_abs(p)) { + if (strlen(p) > 511) + fatal("load_other_removable_devices(): strlen(p) > 511 (zip_drives[%i].image_path)\n", + c); + else + strncpy(zip_drives[c].image_path, p, 511); + } else + path_append_filename(zip_drives[c].image_path, usr_path, p); + path_normalize(zip_drives[c].image_path); + } - sprintf(temp, "zip_%02i_parameters", c+1); - config_delete_var(cat, temp); + for (int i = 0; i < MAX_PREV_IMAGES; i++) { + zip_drives[c].image_history[i] = (char *) calloc((MAX_IMAGE_PATH_LEN + 1) << 1, sizeof(char)); + sprintf(temp, "zip_%02i_image_history_%02i", c + 1, i + 1); + p = ini_section_get_string(cat, temp, NULL); + if (p) { + if (path_abs(p)) { + if (strlen(p) > 511) + fatal("load_other_removable_devices(): strlen(p) > 511 " + "(zip_drives[%i].image_history[%i])\n", c, i); + else + snprintf(zip_drives[c].image_history[i], 511, "%s", p); + } else + snprintf(zip_drives[c].image_history[i], 511, "%s%s%s", usr_path, + path_get_slash(usr_path), p); + path_normalize(zip_drives[c].image_history[i]); + } + } - sprintf(temp, "zip_%02i_ide_channel", c+1); - config_delete_var(cat, temp); + /* If the ZIP drive is disabled, delete all its variables. */ + if (zip_drives[c].bus_type == ZIP_BUS_DISABLED) { + sprintf(temp, "zip_%02i_host_drive", c + 1); + ini_section_delete_var(cat, temp); - sprintf(temp, "zip_%02i_scsi_id", c+1); - config_delete_var(cat, temp); + sprintf(temp, "zip_%02i_parameters", c + 1); + ini_section_delete_var(cat, temp); - sprintf(temp, "zip_%02i_image_path", c+1); - config_delete_var(cat, temp); - } + sprintf(temp, "zip_%02i_ide_channel", c + 1); + ini_section_delete_var(cat, temp); - sprintf(temp, "zip_%02i_iso_path", c+1); - config_delete_var(cat, temp); + sprintf(temp, "zip_%02i_scsi_id", c + 1); + ini_section_delete_var(cat, temp); + + sprintf(temp, "zip_%02i_image_path", c + 1); + ini_section_delete_var(cat, temp); + + for (int i = 0; i < MAX_PREV_IMAGES; i++) { + sprintf(temp, "zip_%02i_image_history_%02i", c + 1, i + 1); + ini_section_delete_var(cat, temp); + } + } } memset(temp, 0x00, sizeof(temp)); - for (c=0; c>1, (c+2)&1); - p = config_get_string(cat, temp, tmp2); - sscanf(p, "%01u:%01u", &board, &dev); - board &= 3; - dev &= 1; - mo_drives[c].ide_channel = (board<<1)+dev; + if (mo_drives[c].bus_type == MO_BUS_ATAPI) { + sprintf(temp, "mo_%02i_ide_channel", c + 1); + sprintf(tmp2, "%01u:%01u", (c + 2) >> 1, (c + 2) & 1); + p = ini_section_get_string(cat, temp, tmp2); + sscanf(p, "%01u:%01u", &board, &dev); + board &= 3; + dev &= 1; + mo_drives[c].ide_channel = (board << 1) + dev; - if (mo_drives[c].ide_channel > 7) - mo_drives[c].ide_channel = 7; - } else if (mo_drives[c].bus_type == MO_BUS_SCSI) { - sprintf(temp, "mo_%02i_scsi_location", c+1); - sprintf(tmp2, "%01u:%02u", SCSI_BUS_MAX, c+2); - p = config_get_string(cat, temp, tmp2); - sscanf(p, "%01u:%02u", &board, &dev); - if (board >= SCSI_BUS_MAX) { - /* Invalid bus - check legacy ID */ - sprintf(temp, "mo_%02i_scsi_id", c+1); - mo_drives[c].scsi_device_id = config_get_int(cat, temp, c+2); + if (mo_drives[c].ide_channel > 7) + mo_drives[c].ide_channel = 7; + } else if (mo_drives[c].bus_type == MO_BUS_SCSI) { + sprintf(temp, "mo_%02i_scsi_location", c + 1); + sprintf(tmp2, "%01u:%02u", SCSI_BUS_MAX, c + 2); + p = ini_section_get_string(cat, temp, tmp2); + sscanf(p, "%01u:%02u", &board, &dev); + if (board >= SCSI_BUS_MAX) { + /* Invalid bus - check legacy ID */ + sprintf(temp, "mo_%02i_scsi_id", c + 1); + mo_drives[c].scsi_device_id = ini_section_get_int(cat, temp, c + 2); - if (mo_drives[c].scsi_device_id > 15) - mo_drives[c].scsi_device_id = 15; - } else { - board %= SCSI_BUS_MAX; - dev &= 15; - mo_drives[c].scsi_device_id = (board<<4)+dev; - } - } + if (mo_drives[c].scsi_device_id > 15) + mo_drives[c].scsi_device_id = 15; + } else { + board %= SCSI_BUS_MAX; + dev &= 15; + mo_drives[c].scsi_device_id = (board << 4) + dev; + } + } - if (mo_drives[c].bus_type != MO_BUS_ATAPI) { - sprintf(temp, "mo_%02i_ide_channel", c+1); - config_delete_var(cat, temp); - } + if (mo_drives[c].bus_type != MO_BUS_ATAPI) { + sprintf(temp, "mo_%02i_ide_channel", c + 1); + ini_section_delete_var(cat, temp); + } - if (mo_drives[c].bus_type != MO_BUS_SCSI) { - sprintf(temp, "mo_%02i_scsi_location", c+1); - config_delete_var(cat, temp); - } + if (mo_drives[c].bus_type != MO_BUS_SCSI) { + sprintf(temp, "mo_%02i_scsi_location", c + 1); + ini_section_delete_var(cat, temp); + } - sprintf(temp, "mo_%02i_scsi_id", c+1); - config_delete_var(cat, temp); + sprintf(temp, "mo_%02i_scsi_id", c + 1); + ini_section_delete_var(cat, temp); - sprintf(temp, "mo_%02i_image_path", c+1); - p = config_get_string(cat, temp, ""); + sprintf(temp, "mo_%02i_image_path", c + 1); + p = ini_section_get_string(cat, temp, ""); - strncpy(mo_drives[c].image_path, p, sizeof(mo_drives[c].image_path) - 1); + if (!strcmp(p, usr_path)) + p[0] = 0x00; - /* If the CD-ROM is disabled, delete all its variables. */ - if (mo_drives[c].bus_type == MO_BUS_DISABLED) { - sprintf(temp, "mo_%02i_host_drive", c+1); - config_delete_var(cat, temp); + if (p[0] != 0x00) { + if (path_abs(p)) { + if (strlen(p) > 511) + fatal("load_other_removable_devices(): strlen(p) > 511 (mo_drives[%i].image_path)\n", + c); + else + strncpy(mo_drives[c].image_path, p, 511); + } else + path_append_filename(mo_drives[c].image_path, usr_path, p); + path_normalize(mo_drives[c].image_path); + } - sprintf(temp, "mo_%02i_parameters", c+1); - config_delete_var(cat, temp); + for (int i = 0; i < MAX_PREV_IMAGES; i++) { + mo_drives[c].image_history[i] = (char *) calloc((MAX_IMAGE_PATH_LEN + 1) << 1, sizeof(char)); + sprintf(temp, "mo_%02i_image_history_%02i", c + 1, i + 1); + p = ini_section_get_string(cat, temp, NULL); + if (p) { + if (path_abs(p)) { + if (strlen(p) > 511) + fatal("load_other_removable_devices(): strlen(p) > 511 " + "(mo_drives[%i].image_history[%i])\n", c, i); + else + snprintf(mo_drives[c].image_history[i], 511, "%s", p); + } else + snprintf(mo_drives[c].image_history[i], 511, "%s%s%s", usr_path, + path_get_slash(usr_path), p); + path_normalize(mo_drives[c].image_history[i]); + } + } - sprintf(temp, "mo_%02i_ide_channel", c+1); - config_delete_var(cat, temp); + /* If the MO drive is disabled, delete all its variables. */ + if (mo_drives[c].bus_type == MO_BUS_DISABLED) { + sprintf(temp, "mo_%02i_host_drive", c + 1); + ini_section_delete_var(cat, temp); - sprintf(temp, "mo_%02i_scsi_id", c+1); - config_delete_var(cat, temp); + sprintf(temp, "mo_%02i_parameters", c + 1); + ini_section_delete_var(cat, temp); - sprintf(temp, "mo_%02i_image_path", c+1); - config_delete_var(cat, temp); - } + sprintf(temp, "mo_%02i_ide_channel", c + 1); + ini_section_delete_var(cat, temp); - sprintf(temp, "mo_%02i_iso_path", c+1); - config_delete_var(cat, temp); - } + sprintf(temp, "mo_%02i_scsi_id", c + 1); + ini_section_delete_var(cat, temp); + + sprintf(temp, "mo_%02i_image_path", c + 1); + ini_section_delete_var(cat, temp); + + for (int i = 0; i < MAX_PREV_IMAGES; i++) { + sprintf(temp, "mo_%02i_image_history_%02i", c + 1, i + 1); + ini_section_delete_var(cat, temp); + } + } + } } - /* Load "Other Peripherals" section. */ static void load_other_peripherals(void) { - char *cat = "Other peripherals"; - char *p; - char temp[512]; - int c, free_p = 0; + ini_section_t cat = ini_find_section(config, "Other peripherals"); + char *p; + char temp[512]; - if (backwards_compat2) { - p = config_get_string(cat, "scsicard", NULL); - if (p != NULL) - scsi_card_current[0] = scsi_card_get_from_internal_name(p); - else - scsi_card_current[0] = 0; - config_delete_var(cat, "scsicard"); + bugger_enabled = !!ini_section_get_int(cat, "bugger_enabled", 0); + postcard_enabled = !!ini_section_get_int(cat, "postcard_enabled", 0); - p = config_get_string(cat, "fdc", NULL); - if (p != NULL) - fdc_type = fdc_card_get_from_internal_name(p); - else - fdc_type = FDC_INTERNAL; - config_delete_var(cat, "fdc"); + for (uint8_t c = 0; c < ISAMEM_MAX; c++) { + sprintf(temp, "isamem%d_type", c); - p = config_get_string(cat, "hdc", NULL); - if (p == NULL) { - if (machine_has_flags(machine, MACHINE_HDC)) { - p = (char *)malloc((strlen("internal")+1)*sizeof(char)); - strcpy(p, "internal"); - } else { - p = (char *)malloc((strlen("none")+1)*sizeof(char)); - strcpy(p, "none"); - } - free_p = 1; - } - if (!strcmp(p, "mfm_xt")) - hdc_current = hdc_get_from_internal_name("st506_xt"); - else if (!strcmp(p, "mfm_xt_dtc5150x")) - hdc_current = hdc_get_from_internal_name("st506_xt_dtc5150x"); - else if (!strcmp(p, "mfm_at")) - hdc_current = hdc_get_from_internal_name("st506_at"); - else if (!strcmp(p, "vlb_isa")) - hdc_current = hdc_get_from_internal_name("ide_vlb"); - else if (!strcmp(p, "vlb_isa_2ch")) - hdc_current = hdc_get_from_internal_name("ide_vlb_2ch"); - else - hdc_current = hdc_get_from_internal_name(p); - config_delete_var(cat, "hdc"); - - if (free_p) { - free(p); - p = NULL; - } - - ide_ter_enabled = !!config_get_int(cat, "ide_ter", 0); - config_delete_var(cat, "ide_ter"); - ide_qua_enabled = !!config_get_int(cat, "ide_qua", 0); - config_delete_var(cat, "ide_qua"); - } - backwards_compat2 = 0; - - bugger_enabled = !!config_get_int(cat, "bugger_enabled", 0); - postcard_enabled = !!config_get_int(cat, "postcard_enabled", 0); - - for (c = 0; c < ISAMEM_MAX; c++) { - sprintf(temp, "isamem%d_type", c); - - p = config_get_string(cat, temp, "none"); - isamem_type[c] = isamem_get_from_internal_name(p); + p = ini_section_get_string(cat, temp, "none"); + isamem_type[c] = isamem_get_from_internal_name(p); } - p = config_get_string(cat, "isartc_type", "none"); - isartc_type = isartc_get_from_internal_name(p); + p = ini_section_get_string(cat, "isartc_type", "none"); + isartc_type = isartc_get_from_internal_name(p); } - /* Load the specified or a default configuration file. */ void config_load(void) @@ -2061,239 +1543,246 @@ config_load(void) #endif memset(zip_drives, 0, sizeof(zip_drive_t)); - if (! config_read(cfg_path)) { - config_changed = 1; + config = ini_read(cfg_path); - cpu_f = (cpu_family_t *) &cpu_families[0]; - cpu = 0; + if (!config) { + config = ini_new(); + config_changed = 1; - kbd_req_capture = 0; - hide_status_bar = 0; - hide_tool_bar = 0; - scale = 1; - machine = machine_get_machine_from_internal_name("ibmpc"); - dpi_scale = 1; + cpu_f = (cpu_family_t *) &cpu_families[0]; + cpu = 0; - fpu_type = fpu_get_type(cpu_f, cpu, "none"); - gfxcard = video_get_video_from_internal_name("cga"); - vid_api = plat_vidapi("default"); - vid_resize = 0; - video_fullscreen_first = 1; - time_sync = TIME_SYNC_ENABLED; - hdc_current = hdc_get_from_internal_name("none"); - serial_enabled[0] = 1; - serial_enabled[1] = 1; - serial_enabled[2] = 0; - serial_enabled[3] = 0; - lpt_ports[0].enabled = 1; - lpt_ports[1].enabled = 0; - lpt_ports[2].enabled = 0; - for (i = 0; i < FDD_NUM; i++) { - if (i < 2) - fdd_set_type(i, 2); - else - fdd_set_type(i, 0); + kbd_req_capture = 0; + hide_status_bar = 0; + hide_tool_bar = 0; + scale = 1; + machine = machine_get_machine_from_internal_name("ibmpc"); + dpi_scale = 1; + do_auto_pause = 0; - fdd_set_turbo(i, 0); - fdd_set_check_bpb(i, 1); - } + fpu_type = fpu_get_type(cpu_f, cpu, "none"); + gfxcard[0] = video_get_video_from_internal_name("cga"); + vid_api = plat_vidapi("default"); + vid_resize = 0; + video_fullscreen_first = 1; + video_fullscreen_scale = 1; + time_sync = TIME_SYNC_ENABLED; + hdc_current = hdc_get_from_internal_name("none"); - /* Unmute the CD audio on the first CD-ROM drive. */ - cdrom[0].sound_on = 1; - mem_size = 64; - isartc_type = 0; - for (i = 0; i < ISAMEM_MAX; i++) - isamem_type[i] = 0; + com_ports[0].enabled = 1; + com_ports[1].enabled = 1; + for (i = 2; i < SERIAL_MAX; i++) + com_ports[i].enabled = 0; - /* TODO: Re-enable by default when we have a proper machine flag for this. */ - cassette_enable = 0; - memset(cassette_fname, 0x00, sizeof(cassette_fname)); - memcpy(cassette_mode, "load", strlen("load") + 1); - cassette_pos = 0; - cassette_srate = 44100; - cassette_append = 0; - cassette_pcm = 0; - cassette_ui_writeprot = 0; + lpt_ports[0].enabled = 1; - config_log("Config file not present or invalid!\n"); + for (i = 1; i < PARALLEL_MAX; i++) + lpt_ports[i].enabled = 0; + + for (i = 0; i < FDD_NUM; i++) { + if (i < 2) + fdd_set_type(i, 2); + else + fdd_set_type(i, 0); + + fdd_set_turbo(i, 0); + fdd_set_check_bpb(i, 1); + } + + /* Unmute the CD audio on the first CD-ROM drive. */ + cdrom[0].sound_on = 1; + mem_size = 64; + isartc_type = 0; + for (i = 0; i < ISAMEM_MAX; i++) + isamem_type[i] = 0; + + cassette_enable = 1; + memset(cassette_fname, 0x00, sizeof(cassette_fname)); + memcpy(cassette_mode, "load", strlen("load") + 1); + cassette_pos = 0; + cassette_srate = 44100; + cassette_append = 0; + cassette_pcm = 0; + cassette_ui_writeprot = 0; + + config_log("Config file not present or invalid!\n"); } else { - load_general(); /* General */ - load_machine(); /* Machine */ - load_video(); /* Video */ - load_input_devices(); /* Input devices */ - load_sound(); /* Sound */ - load_network(); /* Network */ - load_ports(); /* Ports (COM & LPT) */ - load_storage_controllers(); /* Storage controllers */ - load_hard_disks(); /* Hard disks */ - load_floppy_and_cdrom_drives(); /* Floppy and CD-ROM drives */ - /* TODO: Backwards compatibility, get rid of this when enough time has passed. */ - load_floppy_drives(); /* Floppy drives */ - load_other_removable_devices(); /* Other removable devices */ - load_other_peripherals(); /* Other peripherals */ + load_general(); /* General */ + for (i = 0; i < MONITORS_NUM; i++) + load_monitor(i); /* Monitors */ + load_machine(); /* Machine */ + load_video(); /* Video */ + load_input_devices(); /* Input devices */ + load_sound(); /* Sound */ + load_network(); /* Network */ + load_ports(); /* Ports (COM & LPT) */ + load_storage_controllers(); /* Storage controllers */ + load_hard_disks(); /* Hard disks */ + load_floppy_and_cdrom_drives(); /* Floppy and CD-ROM drives */ + load_other_removable_devices(); /* Other removable devices */ + load_other_peripherals(); /* Other peripherals */ - /* Mark the configuration as changed. */ - config_changed = 1; + /* Mark the configuration as changed. */ + config_changed = 1; - config_log("Config loaded.\n\n"); + config_log("Config loaded.\n\n"); } video_copy = (video_grayscale || invert_display) ? video_transform_copy : memcpy; } - /* Save "General" section. */ static void save_general(void) { - char *cat = "General"; - char temp[512]; + ini_section_t cat = ini_find_or_create_section(config, "General"); + char temp[512]; + char buffer[512] = { 0 }; - char *va_name; + const char *va_name = NULL; - config_set_int(cat, "vid_resize", vid_resize); + ini_section_set_int(cat, "vid_resize", vid_resize); if (vid_resize == 0) - config_delete_var(cat, "vid_resize"); + ini_section_delete_var(cat, "vid_resize"); va_name = plat_vidapi_name(vid_api); - if (!strcmp(va_name, "default")) { - config_delete_var(cat, "vid_renderer"); - } else { - config_set_string(cat, "vid_renderer", va_name); - } + if (!strcmp(va_name, "default")) + ini_section_delete_var(cat, "vid_renderer"); + else + ini_section_set_string(cat, "vid_renderer", va_name); - if (video_fullscreen_scale == 0) - config_delete_var(cat, "video_fullscreen_scale"); - else - config_set_int(cat, "video_fullscreen_scale", video_fullscreen_scale); + if (video_fullscreen_scale == 1) + ini_section_delete_var(cat, "video_fullscreen_scale"); + else + ini_section_set_int(cat, "video_fullscreen_scale", video_fullscreen_scale); if (video_fullscreen_first == 1) - config_delete_var(cat, "video_fullscreen_first"); - else - config_set_int(cat, "video_fullscreen_first", video_fullscreen_first); + ini_section_delete_var(cat, "video_fullscreen_first"); + else + ini_section_set_int(cat, "video_fullscreen_first", video_fullscreen_first); if (video_filter_method == 1) - config_delete_var(cat, "video_filter_method"); - else - config_set_int(cat, "video_filter_method", video_filter_method); + ini_section_delete_var(cat, "video_filter_method"); + else + ini_section_set_int(cat, "video_filter_method", video_filter_method); if (force_43 == 0) - config_delete_var(cat, "force_43"); - else - config_set_int(cat, "force_43", force_43); + ini_section_delete_var(cat, "force_43"); + else + ini_section_set_int(cat, "force_43", force_43); if (scale == 1) - config_delete_var(cat, "scale"); - else - config_set_int(cat, "scale", scale); + ini_section_delete_var(cat, "scale"); + else + ini_section_set_int(cat, "scale", scale); if (dpi_scale == 1) - config_delete_var(cat, "dpi_scale"); - else - config_set_int(cat, "dpi_scale", dpi_scale); + ini_section_delete_var(cat, "dpi_scale"); + else + ini_section_set_int(cat, "dpi_scale", dpi_scale); if (enable_overscan == 0) - config_delete_var(cat, "enable_overscan"); - else - config_set_int(cat, "enable_overscan", enable_overscan); + ini_section_delete_var(cat, "enable_overscan"); + else + ini_section_set_int(cat, "enable_overscan", enable_overscan); if (vid_cga_contrast == 0) - config_delete_var(cat, "vid_cga_contrast"); - else - config_set_int(cat, "vid_cga_contrast", vid_cga_contrast); + ini_section_delete_var(cat, "vid_cga_contrast"); + else + ini_section_set_int(cat, "vid_cga_contrast", vid_cga_contrast); if (video_grayscale == 0) - config_delete_var(cat, "video_grayscale"); - else - config_set_int(cat, "video_grayscale", video_grayscale); + ini_section_delete_var(cat, "video_grayscale"); + else + ini_section_set_int(cat, "video_grayscale", video_grayscale); if (video_graytype == 0) - config_delete_var(cat, "video_graytype"); - else - config_set_int(cat, "video_graytype", video_graytype); + ini_section_delete_var(cat, "video_graytype"); + else + ini_section_set_int(cat, "video_graytype", video_graytype); if (rctrl_is_lalt == 0) - config_delete_var(cat, "rctrl_is_lalt"); - else - config_set_int(cat, "rctrl_is_lalt", rctrl_is_lalt); + ini_section_delete_var(cat, "rctrl_is_lalt"); + else + ini_section_set_int(cat, "rctrl_is_lalt", rctrl_is_lalt); if (update_icons == 1) - config_delete_var(cat, "update_icons"); - else - config_set_int(cat, "update_icons", update_icons); + ini_section_delete_var(cat, "update_icons"); + else + ini_section_set_int(cat, "update_icons", update_icons); - if (window_remember || (vid_resize & 2)) { - if (window_remember) - config_set_int(cat, "window_remember", window_remember); - else - config_delete_var(cat, "window_remember"); - - sprintf(temp, "%i, %i, %i, %i", window_w, window_h, window_x, window_y); - config_set_string(cat, "window_coordinates", temp); - } else { - config_delete_var(cat, "window_remember"); - config_delete_var(cat, "window_coordinates"); - } + if (window_remember) + ini_section_set_int(cat, "window_remember", window_remember); + else + ini_section_delete_var(cat, "window_remember"); if (vid_resize & 2) { - sprintf(temp, "%ix%i", fixed_size_x, fixed_size_y); - config_set_string(cat, "window_fixed_res", temp); + sprintf(temp, "%ix%i", fixed_size_x, fixed_size_y); + ini_section_set_string(cat, "window_fixed_res", temp); } else - config_delete_var(cat, "window_fixed_res"); + ini_section_delete_var(cat, "window_fixed_res"); if (sound_gain != 0) - config_set_int(cat, "sound_gain", sound_gain); + ini_section_set_int(cat, "sound_gain", sound_gain); else - config_delete_var(cat, "sound_gain"); + ini_section_delete_var(cat, "sound_gain"); if (kbd_req_capture != 0) - config_set_int(cat, "kbd_req_capture", kbd_req_capture); + ini_section_set_int(cat, "kbd_req_capture", kbd_req_capture); else - config_delete_var(cat, "kbd_req_capture"); + ini_section_delete_var(cat, "kbd_req_capture"); if (hide_status_bar != 0) - config_set_int(cat, "hide_status_bar", hide_status_bar); + ini_section_set_int(cat, "hide_status_bar", hide_status_bar); else - config_delete_var(cat, "hide_status_bar"); + ini_section_delete_var(cat, "hide_status_bar"); if (hide_tool_bar != 0) - config_set_int(cat, "hide_tool_bar", hide_tool_bar); + ini_section_set_int(cat, "hide_tool_bar", hide_tool_bar); else - config_delete_var(cat, "hide_tool_bar"); + ini_section_delete_var(cat, "hide_tool_bar"); if (confirm_reset != 1) - config_set_int(cat, "confirm_reset", confirm_reset); + ini_section_set_int(cat, "confirm_reset", confirm_reset); else - config_delete_var(cat, "confirm_reset"); + ini_section_delete_var(cat, "confirm_reset"); if (confirm_exit != 1) - config_set_int(cat, "confirm_exit", confirm_exit); + ini_section_set_int(cat, "confirm_exit", confirm_exit); else - config_delete_var(cat, "confirm_exit"); + ini_section_delete_var(cat, "confirm_exit"); if (confirm_save != 1) - config_set_int(cat, "confirm_save", confirm_save); + ini_section_set_int(cat, "confirm_save", confirm_save); else - config_delete_var(cat, "confirm_save"); + ini_section_delete_var(cat, "confirm_save"); + + if (mouse_sensitivity != 1.0) + ini_section_set_double(cat, "mouse_sensitivity", mouse_sensitivity); + else + ini_section_delete_var(cat, "mouse_sensitivity"); if (lang_id == DEFAULT_LANGUAGE) - config_delete_var(cat, "language"); - else - { - char buffer[512] = {0}; - plat_language_code_r(lang_id, buffer, 511); - config_set_string(cat, "language", buffer); - } - - if (!strcmp(icon_set, "")) - config_delete_var(cat, "iconset"); - else - config_set_string(cat, "iconset", icon_set); + ini_section_delete_var(cat, "language"); + else { + plat_language_code_r(lang_id, buffer, 511); + ini_section_set_string(cat, "language", buffer); + } + + if (!strcmp(icon_set, "")) + ini_section_delete_var(cat, "iconset"); + else + ini_section_set_string(cat, "iconset", icon_set); if (enable_discord) - config_set_int(cat, "enable_discord", enable_discord); + ini_section_set_int(cat, "enable_discord", enable_discord); else - config_delete_var(cat, "enable_discord"); + ini_section_delete_var(cat, "enable_discord"); + + if (open_dir_usr_path) + ini_section_set_int(cat, "open_dir_usr_path", open_dir_usr_path); + else + ini_section_delete_var(cat, "open_dir_usr_path"); if (status_icons_fullscreen) config_set_int(cat, "status_icons_fullscreen", status_icons_fullscreen); @@ -2301,1073 +1790,944 @@ save_general(void) config_delete_var(cat, "status_icons_fullscreen"); if (video_framerate != -1) - config_set_int(cat, "video_gl_framerate", video_framerate); + ini_section_set_int(cat, "video_gl_framerate", video_framerate); else - config_delete_var(cat, "video_gl_framerate"); + ini_section_delete_var(cat, "video_gl_framerate"); if (video_vsync != 0) - config_set_int(cat, "video_gl_vsync", video_vsync); + ini_section_set_int(cat, "video_gl_vsync", video_vsync); else - config_delete_var(cat, "video_gl_vsync"); + ini_section_delete_var(cat, "video_gl_vsync"); if (strlen(video_shader) > 0) - config_set_string(cat, "video_gl_shader", video_shader); + ini_section_set_string(cat, "video_gl_shader", video_shader); else - config_delete_var(cat, "video_gl_shader"); + ini_section_delete_var(cat, "video_gl_shader"); - delete_section_if_empty(cat); + if (do_auto_pause) + ini_section_set_int(cat, "do_auto_pause", do_auto_pause); + else + ini_section_delete_var(cat, "do_auto_pause"); + + ini_delete_section_if_empty(config, cat); } +/* Save monitor section. */ +static void +save_monitor(int monitor_index) +{ + ini_section_t cat; + char name[sizeof("Monitor #") + 12] = { [0] = 0 }; + char temp[512]; + monitor_settings_t *ms = &monitor_settings[monitor_index]; + + snprintf(name, sizeof(name), "Monitor #%i", monitor_index + 1); + cat = ini_find_or_create_section(config, name); + + if (window_remember) { + sprintf(temp, "%i, %i, %i, %i", ms->mon_window_x, ms->mon_window_y, + ms->mon_window_w, ms->mon_window_h); + + ini_section_set_string(cat, "window_coordinates", temp); + if (ms->mon_window_maximized != 0) + ini_section_set_int(cat, "window_maximized", ms->mon_window_maximized); + else + ini_section_delete_var(cat, "window_maximized"); + } else { + ini_section_delete_var(cat, "window_coordinates"); + ini_section_delete_var(cat, "window_maximized"); + } + + ini_delete_section_if_empty(config, cat); +} /* Save "Machine" section. */ static void save_machine(void) { - char *cat = "Machine"; - char *p; - int c, i = 0, legacy_mfg, legacy_cpu = -1, closest_legacy_cpu = -1; + ini_section_t cat = ini_find_or_create_section(config, "Machine"); + const char *p; + int c; + int i = 0; + int legacy_mfg; + int legacy_cpu = -1; + int closest_legacy_cpu = -1; p = machine_get_internal_name(); - config_set_string(cat, "machine", p); + ini_section_set_string(cat, "machine", p); - config_set_string(cat, "cpu_family", (char *) cpu_f->internal_name); - config_set_int(cat, "cpu_speed", cpu_f->cpus[cpu].rspeed); - config_set_double(cat, "cpu_multi", cpu_f->cpus[cpu].multi); + ini_section_set_string(cat, "cpu_family", cpu_f->internal_name); + ini_section_set_uint(cat, "cpu_speed", cpu_f->cpus[cpu].rspeed); + ini_section_set_double(cat, "cpu_multi", cpu_f->cpus[cpu].multi); if (cpu_override) - config_set_int(cat, "cpu_override", cpu_override); + ini_section_set_int(cat, "cpu_override", cpu_override); else - config_delete_var(cat, "cpu_override"); + ini_section_delete_var(cat, "cpu_override"); - /* Forwards compatibility with the previous CPU model system. */ - config_delete_var(cat, "cpu_manufacturer"); - config_delete_var(cat, "cpu"); + /* Downgrade compatibility with the previous CPU model system. */ + ini_section_delete_var(cat, "cpu_manufacturer"); + ini_section_delete_var(cat, "cpu"); /* Look for a machine entry on the legacy table. */ c = 0; while (cpu_legacy_table[c].machine) { - if (!strcmp(p, cpu_legacy_table[c].machine)) - break; - c++; + if (!strcmp(p, cpu_legacy_table[c].machine)) + break; + c++; } if (cpu_legacy_table[c].machine) { - /* Look for a corresponding CPU entry. */ - cpu_legacy_table_t *legacy_table_entry; - for (legacy_mfg = 0; legacy_mfg < 4; legacy_mfg++) { - if (!cpu_legacy_table[c].tables[legacy_mfg]) - continue; + /* Look for a corresponding CPU entry. */ + const cpu_legacy_table_t *legacy_table_entry; + for (legacy_mfg = 0; legacy_mfg < 4; legacy_mfg++) { + if (!cpu_legacy_table[c].tables[legacy_mfg]) + continue; - i = 0; - while (cpu_legacy_table[c].tables[legacy_mfg][i].family) { - legacy_table_entry = (cpu_legacy_table_t *) &cpu_legacy_table[c].tables[legacy_mfg][i]; + i = 0; + while (cpu_legacy_table[c].tables[legacy_mfg][i].family) { + legacy_table_entry = &cpu_legacy_table[c].tables[legacy_mfg][i]; - /* Match the family name, speed and multiplier. */ - if (!strcmp(cpu_f->internal_name, legacy_table_entry->family)) { - if ((legacy_table_entry->rspeed == cpu_f->cpus[cpu].rspeed) && - (legacy_table_entry->multi == cpu_f->cpus[cpu].multi)) { /* exact speed/multiplier match */ - legacy_cpu = i; - break; - } else if ((legacy_table_entry->rspeed >= cpu_f->cpus[cpu].rspeed) && - (closest_legacy_cpu == -1)) { /* closest speed match */ - closest_legacy_cpu = i; - } - } + /* Match the family name, speed and multiplier. */ + if (!strcmp(cpu_f->internal_name, legacy_table_entry->family)) { + if ((legacy_table_entry->rspeed == cpu_f->cpus[cpu].rspeed) && + (legacy_table_entry->multi == cpu_f->cpus[cpu].multi)) { + /* Exact speed/multiplier match. */ + legacy_cpu = i; + break; + } else if ((legacy_table_entry->rspeed >= cpu_f->cpus[cpu].rspeed) && + (closest_legacy_cpu == -1)) + /* Closest speed match. */ + closest_legacy_cpu = i; + } - i++; - } + i++; + } - /* Use the closest speed match if no exact match was found. */ - if ((legacy_cpu == -1) && (closest_legacy_cpu > -1)) { - legacy_cpu = closest_legacy_cpu; - break; - } else if (legacy_cpu > -1) /* exact match found */ - break; - } + /* Use the closest speed match if no exact match was found. */ + if ((legacy_cpu == -1) && (closest_legacy_cpu > -1)) { + legacy_cpu = closest_legacy_cpu; + break; + } else if (legacy_cpu > -1) /* exact match found */ + break; + } - /* Set legacy values if a match was found. */ - if (legacy_cpu > -1) { - if (legacy_mfg) - config_set_int(cat, "cpu_manufacturer", legacy_mfg); - if (legacy_cpu) - config_set_int(cat, "cpu", legacy_cpu); - } + /* Set legacy values if a match was found. */ + if (legacy_cpu > -1) { + if (legacy_mfg) + ini_section_set_int(cat, "cpu_manufacturer", legacy_mfg); + if (legacy_cpu) + ini_section_set_int(cat, "cpu", legacy_cpu); + } } if (cpu_waitstates == 0) - config_delete_var(cat, "cpu_waitstates"); - else - config_set_int(cat, "cpu_waitstates", cpu_waitstates); + ini_section_delete_var(cat, "cpu_waitstates"); + else + ini_section_set_int(cat, "cpu_waitstates", cpu_waitstates); if (fpu_type == 0) - config_delete_var(cat, "fpu_type"); - else - config_set_string(cat, "fpu_type", (char *) fpu_get_internal_name(cpu_f, cpu, fpu_type)); + ini_section_delete_var(cat, "fpu_type"); + else + ini_section_set_string(cat, "fpu_type", fpu_get_internal_name(cpu_f, cpu, fpu_type)); - //Write the mem_size explicitly to the setttings in order to help managers to display it without having the actual machine table - config_delete_var(cat, "mem_size"); - config_set_int(cat, "mem_size", mem_size); + /* Write the mem_size explicitly to the setttings in order to help managers + to display it without having the actual machine table. */ + ini_section_delete_var(cat, "mem_size"); + ini_section_set_int(cat, "mem_size", mem_size); - config_set_int(cat, "cpu_use_dynarec", cpu_use_dynarec); + ini_section_set_int(cat, "cpu_use_dynarec", cpu_use_dynarec); + ini_section_set_int(cat, "fpu_softfloat", fpu_softfloat); if (time_sync & TIME_SYNC_ENABLED) - if (time_sync & TIME_SYNC_UTC) - config_set_string(cat, "time_sync", "utc"); - else - config_set_string(cat, "time_sync", "local"); + if (time_sync & TIME_SYNC_UTC) + ini_section_set_string(cat, "time_sync", "utc"); + else + ini_section_set_string(cat, "time_sync", "local"); else - config_set_string(cat, "time_sync", "disabled"); + ini_section_set_string(cat, "time_sync", "disabled"); - delete_section_if_empty(cat); + if (pit_mode == -1) + ini_section_delete_var(cat, "pit_mode"); + else + ini_section_set_int(cat, "pit_mode", pit_mode); + + ini_delete_section_if_empty(config, cat); } - /* Save "Video" section. */ static void save_video(void) { - char *cat = "Video"; + ini_section_t cat = ini_find_or_create_section(config, "Video"); - config_set_string(cat, "gfxcard", - video_get_internal_name(gfxcard)); + ini_section_set_string(cat, "gfxcard", + video_get_internal_name(gfxcard[0])); if (voodoo_enabled == 0) - config_delete_var(cat, "voodoo"); - else - config_set_int(cat, "voodoo", voodoo_enabled); + ini_section_delete_var(cat, "voodoo"); + else + ini_section_set_int(cat, "voodoo", voodoo_enabled); - delete_section_if_empty(cat); + if (ibm8514_standalone_enabled == 0) + ini_section_delete_var(cat, "8514a"); + else + ini_section_set_int(cat, "8514a", ibm8514_standalone_enabled); + + if (xga_standalone_enabled == 0) + ini_section_delete_var(cat, "xga"); + else + ini_section_set_int(cat, "xga", xga_standalone_enabled); + + if (gfxcard[1] == 0) + ini_section_delete_var(cat, "gfxcard_2"); + else + ini_section_set_string(cat, "gfxcard_2", video_get_internal_name(gfxcard[1])); + + if (show_second_monitors == 1) + ini_section_delete_var(cat, "show_second_monitors"); + else + ini_section_set_int(cat, "show_second_monitors", show_second_monitors); + + if (video_fullscreen_scale_maximized == 0) + ini_section_delete_var(cat, "video_fullscreen_scale_maximized"); + else + ini_section_set_int(cat, "video_fullscreen_scale_maximized", video_fullscreen_scale_maximized); + + ini_delete_section_if_empty(config, cat); } - /* Save "Input Devices" section. */ static void save_input_devices(void) { - char *cat = "Input devices"; - char temp[512], tmp2[512]; - int c, d; + ini_section_t cat = ini_find_or_create_section(config, "Input devices"); + char temp[512]; + char tmp2[512]; + int c; + int d; - config_set_string(cat, "mouse_type", mouse_get_internal_name(mouse_type)); + ini_section_set_string(cat, "mouse_type", mouse_get_internal_name(mouse_type)); if (!joystick_type) { - config_delete_var(cat, "joystick_type"); + ini_section_delete_var(cat, "joystick_type"); - for (c = 0; c < 16; c++) { - sprintf(tmp2, "joystick_%i_nr", c); - config_delete_var(cat, tmp2); + for (c = 0; c < 16; c++) { + sprintf(tmp2, "joystick_%i_nr", c); + ini_section_delete_var(cat, tmp2); - for (d=0; d<16; d++) { - sprintf(tmp2, "joystick_%i_axis_%i", c, d); - config_delete_var(cat, tmp2); - } - for (d=0; d<16; d++) { - sprintf(tmp2, "joystick_%i_button_%i", c, d); - config_delete_var(cat, tmp2); - } - for (d=0; d<16; d++) { - sprintf(tmp2, "joystick_%i_pov_%i", c, d); - config_delete_var(cat, tmp2); - } - } + for (d = 0; d < 16; d++) { + sprintf(tmp2, "joystick_%i_axis_%i", c, d); + ini_section_delete_var(cat, tmp2); + } + for (d = 0; d < 16; d++) { + sprintf(tmp2, "joystick_%i_button_%i", c, d); + ini_section_delete_var(cat, tmp2); + } + for (d = 0; d < 16; d++) { + sprintf(tmp2, "joystick_%i_pov_%i", c, d); + ini_section_delete_var(cat, tmp2); + } + } } else { - config_set_string(cat, "joystick_type", joystick_get_internal_name(joystick_type)); + ini_section_set_string(cat, "joystick_type", joystick_get_internal_name(joystick_type)); - for (c = 0; c < joystick_get_max_joysticks(joystick_type); c++) { - sprintf(tmp2, "joystick_%i_nr", c); - config_set_int(cat, tmp2, joystick_state[c].plat_joystick_nr); + for (c = 0; c < joystick_get_max_joysticks(joystick_type); c++) { + sprintf(tmp2, "joystick_%i_nr", c); + ini_section_set_int(cat, tmp2, joystick_state[c].plat_joystick_nr); - if (joystick_state[c].plat_joystick_nr) { - for (d=0; d 0) /* not found */ + ini_section_delete_var(cat, legacy_cards[i][0]); + } if (sound_is_float == 1) - config_delete_var(cat, "sound_type"); - else - config_set_string(cat, "sound_type", (sound_is_float == 1) ? "float" : "int16"); + ini_section_delete_var(cat, "sound_type"); + else + ini_section_set_string(cat, "sound_type", (sound_is_float == 1) ? "float" : "int16"); - delete_section_if_empty(cat); + ini_section_set_string(cat, "fm_driver", (fm_driver == FM_DRV_NUKED) ? "nuked" : "ymfm"); + + ini_delete_section_if_empty(config, cat); } - /* Save "Network" section. */ static void save_network(void) { - char *cat = "Network"; + char temp[512]; + ini_section_t cat = ini_find_or_create_section(config, "Network"); + netcard_conf_t *nc; - if (network_type == NET_TYPE_NONE) - config_delete_var(cat, "net_type"); - else - config_set_string(cat, "net_type", - (network_type == NET_TYPE_SLIRP) ? "slirp" : "pcap"); + ini_section_delete_var(cat, "net_type"); + ini_section_delete_var(cat, "net_host_device"); + ini_section_delete_var(cat, "net_card"); - if (network_host[0] != '\0') { - if (! strcmp(network_host, "none")) - config_delete_var(cat, "net_host_device"); - else - config_set_string(cat, "net_host_device", network_host); - } else { - /* config_set_string(cat, "net_host_device", "none"); */ - config_delete_var(cat, "net_host_device"); + for (uint8_t c = 0; c < NET_CARD_MAX; c++) { + nc = &net_cards_conf[c]; + + sprintf(temp, "net_%02i_card", c + 1); + if (nc->device_num == 0) + ini_section_delete_var(cat, temp); + else + ini_section_set_string(cat, temp, network_card_get_internal_name(nc->device_num)); + + sprintf(temp, "net_%02i_net_type", c + 1); + switch(nc->net_type) { + case NET_TYPE_NONE: + ini_section_delete_var(cat, temp); + break; + case NET_TYPE_SLIRP: + ini_section_set_string(cat, temp, "slirp"); + break; + case NET_TYPE_PCAP: + ini_section_set_string(cat, temp, "pcap"); + break; + case NET_TYPE_VDE: + ini_section_set_string(cat, temp, "vde"); + break; + + default: + break; + } + + sprintf(temp, "net_%02i_host_device", c + 1); + if (nc->host_dev_name[0] != '\0') { + if (!strcmp(nc->host_dev_name, "none")) + ini_section_delete_var(cat, temp); + else + ini_section_set_string(cat, temp, nc->host_dev_name); + } else + ini_section_delete_var(cat, temp); + + sprintf(temp, "net_%02i_link", c + 1); + if (nc->link_state == (NET_LINK_10_HD | NET_LINK_10_FD | + NET_LINK_100_HD | NET_LINK_100_FD | + NET_LINK_1000_HD | NET_LINK_1000_FD)) + ini_section_delete_var(cat, temp); + else + ini_section_set_int(cat, temp, nc->link_state); } - if (network_card == 0) - config_delete_var(cat, "net_card"); - else - config_set_string(cat, "net_card", - network_card_get_internal_name(network_card)); - - delete_section_if_empty(cat); + ini_delete_section_if_empty(config, cat); } - /* Save "Ports" section. */ static void save_ports(void) { - char *cat = "Ports (COM & LPT)"; - char temp[512]; - int c, d; + ini_section_t cat = ini_find_or_create_section(config, "Ports (COM & LPT)"); + char temp[512]; + int c; + int d; for (c = 0; c < SERIAL_MAX; c++) { - sprintf(temp, "serial%d_enabled", c + 1); - if (((c < 2) && serial_enabled[c]) || ((c >= 2) && !serial_enabled[c])) - config_delete_var(cat, temp); - else - config_set_int(cat, temp, serial_enabled[c]); + sprintf(temp, "serial%d_enabled", c + 1); + if (((c < 2) && com_ports[c].enabled) || ((c >= 2) && !com_ports[c].enabled)) + ini_section_delete_var(cat, temp); + else + ini_section_set_int(cat, temp, com_ports[c].enabled); -/* - sprintf(temp, "serial%d_type", c + 1); - if (!serial_enabled[c]) - config_delete_var(cat, temp); -// else -// config_set_string(cat, temp, (char *) serial_type[c]) - - sprintf(temp, "serial%d_device", c + 1); - if (com_ports[c].device == 0) - config_delete_var(cat, temp); - else - config_set_string(cat, temp, - (char *) com_device_get_internal_name(com_ports[c].device)); -*/ + sprintf(temp, "serial%d_passthrough_enabled", c + 1); + if (serial_passthrough_enabled[c]) { + ini_section_set_int(cat, temp, 1); + } else { + ini_section_delete_var(cat, temp); + } } for (c = 0; c < PARALLEL_MAX; c++) { - sprintf(temp, "lpt%d_enabled", c + 1); - d = (c == 0) ? 1 : 0; - if (lpt_ports[c].enabled == d) - config_delete_var(cat, temp); - else - config_set_int(cat, temp, lpt_ports[c].enabled); + sprintf(temp, "lpt%d_enabled", c + 1); + d = (c == 0) ? 1 : 0; + if (lpt_ports[c].enabled == d) + ini_section_delete_var(cat, temp); + else + ini_section_set_int(cat, temp, lpt_ports[c].enabled); - sprintf(temp, "lpt%d_device", c + 1); - if (lpt_ports[c].device == 0) - config_delete_var(cat, temp); - else - config_set_string(cat, temp, - (char *) lpt_device_get_internal_name(lpt_ports[c].device)); + sprintf(temp, "lpt%d_device", c + 1); + if (lpt_ports[c].device == 0) + ini_section_delete_var(cat, temp); + else + ini_section_set_string(cat, temp, + lpt_device_get_internal_name(lpt_ports[c].device)); } - delete_section_if_empty(cat); + ini_delete_section_if_empty(config, cat); } - /* Save "Storage Controllers" section. */ static void save_storage_controllers(void) { - char *cat = "Storage controllers"; - char temp[512]; - int c; + ini_section_t cat = ini_find_or_create_section(config, "Storage controllers"); + char temp[512]; + int c; - config_delete_var(cat, "scsicard"); + ini_section_delete_var(cat, "scsicard"); for (c = 0; c < SCSI_BUS_MAX; c++) { - sprintf(temp, "scsicard_%d", c + 1); + sprintf(temp, "scsicard_%d", c + 1); - if (scsi_card_current[c] == 0) - config_delete_var(cat, temp); - else - config_set_string(cat, temp, - scsi_card_get_internal_name(scsi_card_current[c])); + if (scsi_card_current[c] == 0) + ini_section_delete_var(cat, temp); + else + ini_section_set_string(cat, temp, + scsi_card_get_internal_name(scsi_card_current[c])); } if (fdc_type == FDC_INTERNAL) - config_delete_var(cat, "fdc"); - else - config_set_string(cat, "fdc", - fdc_card_get_internal_name(fdc_type)); + ini_section_delete_var(cat, "fdc"); + else + ini_section_set_string(cat, "fdc", + fdc_card_get_internal_name(fdc_type)); - config_set_string(cat, "hdc", - hdc_get_internal_name(hdc_current)); + ini_section_set_string(cat, "hdc", + hdc_get_internal_name(hdc_current)); + + if (cdrom_interface_current == 0) + ini_section_delete_var(cat, "cdrom_interface"); + else + ini_section_set_string(cat, "cdrom_interface", + cdrom_interface_get_internal_name(cdrom_interface_current)); if (ide_ter_enabled == 0) - config_delete_var(cat, "ide_ter"); - else - config_set_int(cat, "ide_ter", ide_ter_enabled); + ini_section_delete_var(cat, "ide_ter"); + else + ini_section_set_int(cat, "ide_ter", ide_ter_enabled); if (ide_qua_enabled == 0) - config_delete_var(cat, "ide_qua"); - else - config_set_int(cat, "ide_qua", ide_qua_enabled); - - delete_section_if_empty(cat); - - if (cassette_enable == 1) - config_delete_var(cat, "cassette_enabled"); + ini_section_delete_var(cat, "ide_qua"); else - config_set_int(cat, "cassette_enabled", cassette_enable); + ini_section_set_int(cat, "ide_qua", ide_qua_enabled); + + ini_delete_section_if_empty(config, cat); + + if (cassette_enable == 0) + ini_section_delete_var(cat, "cassette_enabled"); + else + ini_section_set_int(cat, "cassette_enabled", cassette_enable); if (strlen(cassette_fname) == 0) - config_delete_var(cat, "cassette_file"); + ini_section_delete_var(cat, "cassette_file"); else - config_set_string(cat, "cassette_file", cassette_fname); + ini_section_set_string(cat, "cassette_file", cassette_fname); if (strlen(cassette_mode) == 0) - config_delete_var(cat, "cassette_mode"); + ini_section_delete_var(cat, "cassette_mode"); else - config_set_string(cat, "cassette_mode", cassette_mode); + ini_section_set_string(cat, "cassette_mode", cassette_mode); if (cassette_pos == 0) - config_delete_var(cat, "cassette_position"); + ini_section_delete_var(cat, "cassette_position"); else - config_set_int(cat, "cassette_position", cassette_pos); + ini_section_set_int(cat, "cassette_position", cassette_pos); if (cassette_srate == 44100) - config_delete_var(cat, "cassette_srate"); + ini_section_delete_var(cat, "cassette_srate"); else - config_set_int(cat, "cassette_srate", cassette_srate); + ini_section_set_int(cat, "cassette_srate", cassette_srate); if (cassette_append == 0) - config_delete_var(cat, "cassette_append"); + ini_section_delete_var(cat, "cassette_append"); else - config_set_int(cat, "cassette_append", cassette_append); + ini_section_set_int(cat, "cassette_append", cassette_append); if (cassette_pcm == 0) - config_delete_var(cat, "cassette_pcm"); + ini_section_delete_var(cat, "cassette_pcm"); else - config_set_int(cat, "cassette_pcm", cassette_pcm); + ini_section_set_int(cat, "cassette_pcm", cassette_pcm); if (cassette_ui_writeprot == 0) - config_delete_var(cat, "cassette_writeprot"); + ini_section_delete_var(cat, "cassette_writeprot"); else - config_set_int(cat, "cassette_writeprot", cassette_ui_writeprot); + ini_section_set_int(cat, "cassette_writeprot", cassette_ui_writeprot); - for (c=0; c<2; c++) { - sprintf(temp, "cartridge_%02i_fn", c+1); - if (strlen(cart_fns[c]) == 0) - config_delete_var(cat, temp); - else - config_set_string(cat, temp, cart_fns[c]); + for (c = 0; c < 2; c++) { + sprintf(temp, "cartridge_%02i_fn", c + 1); + if (strlen(cart_fns[c]) == 0) + ini_section_delete_var(cat, temp); + else + ini_section_set_string(cat, temp, cart_fns[c]); } } - /* Save "Other Peripherals" section. */ static void save_other_peripherals(void) { - char *cat = "Other peripherals"; - char temp[512]; - int c; + ini_section_t cat = ini_find_or_create_section(config, "Other peripherals"); + char temp[512]; if (bugger_enabled == 0) - config_delete_var(cat, "bugger_enabled"); - else - config_set_int(cat, "bugger_enabled", bugger_enabled); + ini_section_delete_var(cat, "bugger_enabled"); + else + ini_section_set_int(cat, "bugger_enabled", bugger_enabled); if (postcard_enabled == 0) - config_delete_var(cat, "postcard_enabled"); - else - config_set_int(cat, "postcard_enabled", postcard_enabled); + ini_section_delete_var(cat, "postcard_enabled"); + else + ini_section_set_int(cat, "postcard_enabled", postcard_enabled); - for (c = 0; c < ISAMEM_MAX; c++) { - sprintf(temp, "isamem%d_type", c); - if (isamem_type[c] == 0) - config_delete_var(cat, temp); - else - config_set_string(cat, temp, - (char *) isamem_get_internal_name(isamem_type[c])); + for (uint8_t c = 0; c < ISAMEM_MAX; c++) { + sprintf(temp, "isamem%d_type", c); + if (isamem_type[c] == 0) + ini_section_delete_var(cat, temp); + else + ini_section_set_string(cat, temp, + isamem_get_internal_name(isamem_type[c])); } if (isartc_type == 0) - config_delete_var(cat, "isartc_type"); - else - config_set_string(cat, "isartc_type", - isartc_get_internal_name(isartc_type)); - - delete_section_if_empty(cat); -} + ini_section_delete_var(cat, "isartc_type"); + else + ini_section_set_string(cat, "isartc_type", + isartc_get_internal_name(isartc_type)); + ini_delete_section_if_empty(config, cat); +} /* Save "Hard Disks" section. */ static void save_hard_disks(void) { - char *cat = "Hard disks"; - char temp[32], tmp2[512]; - char *p; - int c; + ini_section_t cat = ini_find_or_create_section(config, "Hard disks"); + char temp[32]; + char tmp2[512]; + char *p; memset(temp, 0x00, sizeof(temp)); - for (c=0; c> 1, hdd[c].ide_channel & 1); - config_set_string(cat, temp, tmp2); - } + sprintf(temp, "hdd_%02i_ide_channel", c + 1); + if (!hdd_is_valid(c) || ((hdd[c].bus != HDD_BUS_IDE) && (hdd[c].bus != HDD_BUS_ATAPI))) + ini_section_delete_var(cat, temp); + else { + sprintf(tmp2, "%01u:%01u", hdd[c].ide_channel >> 1, hdd[c].ide_channel & 1); + ini_section_set_string(cat, temp, tmp2); + } - sprintf(temp, "hdd_%02i_scsi_id", c+1); - config_delete_var(cat, temp); + sprintf(temp, "hdd_%02i_scsi_id", c + 1); + ini_section_delete_var(cat, temp); - sprintf(temp, "hdd_%02i_scsi_location", c+1); - if (hdd[c].bus != HDD_BUS_SCSI) - config_delete_var(cat, temp); - else { - sprintf(tmp2, "%01u:%02u", hdd[c].scsi_id>>4, - hdd[c].scsi_id & 15); - config_set_string(cat, temp, tmp2); - } + sprintf(temp, "hdd_%02i_scsi_location", c + 1); + if (hdd[c].bus != HDD_BUS_SCSI) + ini_section_delete_var(cat, temp); + else { + sprintf(tmp2, "%01u:%02u", hdd[c].scsi_id >> 4, + hdd[c].scsi_id & 15); + ini_section_set_string(cat, temp, tmp2); + } - sprintf(temp, "hdd_%02i_fn", c+1); - if (hdd_is_valid(c) && (strlen(hdd[c].fn) != 0)) - if (!strnicmp(hdd[c].fn, usr_path, strlen(usr_path))) - config_set_string(cat, temp, &hdd[c].fn[strlen(usr_path)]); - else - config_set_string(cat, temp, hdd[c].fn); - else - config_delete_var(cat, temp); + sprintf(temp, "hdd_%02i_fn", c + 1); + if (hdd_is_valid(c) && (strlen(hdd[c].fn) != 0)) { + path_normalize(hdd[c].fn); + if (!strnicmp(hdd[c].fn, usr_path, strlen(usr_path))) + ini_section_set_string(cat, temp, &hdd[c].fn[strlen(usr_path)]); + else + ini_section_set_string(cat, temp, hdd[c].fn); + } else + ini_section_delete_var(cat, temp); + + sprintf(temp, "hdd_%02i_vhd_blocksize", c + 1); + if (hdd_is_valid(c) && (hdd[c].vhd_blocksize > 0)) + ini_section_set_int(cat, temp, hdd[c].vhd_blocksize); + else + ini_section_delete_var(cat, temp); + + sprintf(temp, "hdd_%02i_vhd_parent", c + 1); + if (hdd_is_valid(c) && hdd[c].vhd_parent[0]) { + path_normalize(hdd[c].vhd_parent); + ini_section_set_string(cat, temp, hdd[c].vhd_parent); + } else + ini_section_delete_var(cat, temp); + + sprintf(temp, "hdd_%02i_speed", c + 1); + if (!hdd_is_valid(c) || ((hdd[c].bus != HDD_BUS_ESDI) && (hdd[c].bus != HDD_BUS_IDE) && + (hdd[c].bus != HDD_BUS_SCSI) && (hdd[c].bus != HDD_BUS_ATAPI))) + ini_section_delete_var(cat, temp); + else + ini_section_set_string(cat, temp, hdd_preset_get_internal_name(hdd[c].speed_preset)); } - delete_section_if_empty(cat); + ini_delete_section_if_empty(config, cat); } - /* Save "Floppy Drives" section. */ static void save_floppy_and_cdrom_drives(void) { - char *cat = "Floppy and CD-ROM drives"; - char temp[512], tmp2[512]; - int c; + ini_section_t cat = ini_find_or_create_section(config, "Floppy and CD-ROM drives"); + char temp[512]; + char tmp2[512]; + int c; - for (c=0; c>1, - cdrom[c].ide_channel & 1); - config_set_string(cat, temp, tmp2); - } + sprintf(temp, "cdrom_%02i_parameters", c + 1); + if (cdrom[c].bus_type == 0) + ini_section_delete_var(cat, temp); + else { + /* In case one wants an ATAPI drive on SCSI and vice-versa. */ + if ((cdrom_drive_types[cdrom_get_type(c)].bus_type != BUS_TYPE_BOTH) && + (cdrom_drive_types[cdrom_get_type(c)].bus_type != cdrom[c].bus_type)) + cdrom[c].bus_type = cdrom_drive_types[cdrom_get_type(c)].bus_type; - sprintf(temp, "cdrom_%02i_scsi_id", c + 1); - config_delete_var(cat, temp); + sprintf(tmp2, "%u, %s", cdrom[c].sound_on, + hdd_bus_to_string(cdrom[c].bus_type, 1)); + ini_section_set_string(cat, temp, tmp2); + } - sprintf(temp, "cdrom_%02i_scsi_location", c+1); - if (cdrom[c].bus_type != CDROM_BUS_SCSI) - config_delete_var(cat, temp); - else { - sprintf(tmp2, "%01u:%02u", cdrom[c].scsi_device_id>>4, - cdrom[c].scsi_device_id & 15); - config_set_string(cat, temp, tmp2); - } + sprintf(temp, "cdrom_%02i_ide_channel", c + 1); + if (cdrom[c].bus_type != CDROM_BUS_ATAPI) + ini_section_delete_var(cat, temp); + else { + sprintf(tmp2, "%01u:%01u", cdrom[c].ide_channel >> 1, + cdrom[c].ide_channel & 1); + ini_section_set_string(cat, temp, tmp2); + } - sprintf(temp, "cdrom_%02i_image_path", c + 1); - if ((cdrom[c].bus_type == 0) || - (strlen(cdrom[c].image_path) == 0)) { - config_delete_var(cat, temp); - } else { - config_set_string(cat, temp, cdrom[c].image_path); - } + sprintf(temp, "cdrom_%02i_scsi_id", c + 1); + ini_section_delete_var(cat, temp); + + sprintf(temp, "cdrom_%02i_scsi_location", c + 1); + if (cdrom[c].bus_type != CDROM_BUS_SCSI) + ini_section_delete_var(cat, temp); + else { + sprintf(tmp2, "%01u:%02u", cdrom[c].scsi_device_id >> 4, + cdrom[c].scsi_device_id & 15); + ini_section_set_string(cat, temp, tmp2); + } + + sprintf(temp, "cdrom_%02i_image_path", c + 1); + if ((cdrom[c].bus_type == 0) || (strlen(cdrom[c].image_path) == 0)) + ini_section_delete_var(cat, temp); + else { + path_normalize(cdrom[c].image_path); + if (!strnicmp(cdrom[c].image_path, usr_path, strlen(usr_path))) + ini_section_set_string(cat, temp, &cdrom[c].image_path[strlen(usr_path)]); + else + ini_section_set_string(cat, temp, cdrom[c].image_path); + } + + for (int i = 0; i < MAX_PREV_IMAGES; i++) { + sprintf(temp, "cdrom_%02i_image_history_%02i", c + 1, i + 1); + if ((cdrom[c].image_history[i] == 0) || strlen(cdrom[c].image_history[i]) == 0) + ini_section_delete_var(cat, temp); + else { + path_normalize(cdrom[c].image_history[i]); + if (!strnicmp(cdrom[c].image_history[i], usr_path, strlen(usr_path))) + ini_section_set_string(cat, temp, &cdrom[c].image_history[i][strlen(usr_path)]); + else + ini_section_set_string(cat, temp, cdrom[c].image_history[i]); + } + } } - delete_section_if_empty(cat); + ini_delete_section_if_empty(config, cat); } - /* Save "Other Removable Devices" section. */ static void save_other_removable_devices(void) { - char *cat = "Other removable devices"; - char temp[512], tmp2[512]; - int c; + ini_section_t cat = ini_find_or_create_section(config, "Other removable devices"); + char temp[512]; + char tmp2[512]; + int c; - for (c=0; c>1, - zip_drives[c].ide_channel & 1); - config_set_string(cat, temp, tmp2); - } + for (c = 0; c < ZIP_NUM; c++) { + sprintf(temp, "zip_%02i_parameters", c + 1); + if (zip_drives[c].bus_type == 0) { + ini_section_delete_var(cat, temp); + } else { + sprintf(tmp2, "%u, %s", zip_drives[c].is_250, + hdd_bus_to_string(zip_drives[c].bus_type, 1)); + ini_section_set_string(cat, temp, tmp2); + } - sprintf(temp, "zip_%02i_scsi_id", c + 1); - config_delete_var(cat, temp); + sprintf(temp, "zip_%02i_ide_channel", c + 1); + if (zip_drives[c].bus_type != ZIP_BUS_ATAPI) + ini_section_delete_var(cat, temp); + else { + sprintf(tmp2, "%01u:%01u", zip_drives[c].ide_channel >> 1, + zip_drives[c].ide_channel & 1); + ini_section_set_string(cat, temp, tmp2); + } - sprintf(temp, "zip_%02i_scsi_location", c+1); - if (zip_drives[c].bus_type != ZIP_BUS_SCSI) - config_delete_var(cat, temp); - else { - sprintf(tmp2, "%01u:%02u", zip_drives[c].scsi_device_id>>4, - zip_drives[c].scsi_device_id & 15); - config_set_string(cat, temp, tmp2); - } + sprintf(temp, "zip_%02i_scsi_id", c + 1); + ini_section_delete_var(cat, temp); - sprintf(temp, "zip_%02i_image_path", c + 1); - if ((zip_drives[c].bus_type == 0) || - (strlen(zip_drives[c].image_path) == 0)) { - config_delete_var(cat, temp); - } else { - config_set_string(cat, temp, zip_drives[c].image_path); - } + sprintf(temp, "zip_%02i_scsi_location", c + 1); + if (zip_drives[c].bus_type != ZIP_BUS_SCSI) + ini_section_delete_var(cat, temp); + else { + sprintf(tmp2, "%01u:%02u", zip_drives[c].scsi_device_id >> 4, + zip_drives[c].scsi_device_id & 15); + ini_section_set_string(cat, temp, tmp2); + } + + sprintf(temp, "zip_%02i_image_path", c + 1); + if ((zip_drives[c].bus_type == 0) || (strlen(zip_drives[c].image_path) == 0)) + ini_section_delete_var(cat, temp); + else { + path_normalize(zip_drives[c].image_path); + if (!strnicmp(zip_drives[c].image_path, usr_path, strlen(usr_path))) + ini_section_set_string(cat, temp, &zip_drives[c].image_path[strlen(usr_path)]); + else + ini_section_set_string(cat, temp, zip_drives[c].image_path); + } } - for (c=0; c>1, - mo_drives[c].ide_channel & 1); - config_set_string(cat, temp, tmp2); - } + for (c = 0; c < MO_NUM; c++) { + sprintf(temp, "mo_%02i_parameters", c + 1); + if (mo_drives[c].bus_type == 0) { + ini_section_delete_var(cat, temp); + } else { + sprintf(tmp2, "%u, %s", mo_drives[c].type, + hdd_bus_to_string(mo_drives[c].bus_type, 1)); + ini_section_set_string(cat, temp, tmp2); + } - sprintf(temp, "mo_%02i_scsi_id", c + 1); - config_delete_var(cat, temp); + sprintf(temp, "mo_%02i_ide_channel", c + 1); + if (mo_drives[c].bus_type != MO_BUS_ATAPI) + ini_section_delete_var(cat, temp); + else { + sprintf(tmp2, "%01u:%01u", mo_drives[c].ide_channel >> 1, + mo_drives[c].ide_channel & 1); + ini_section_set_string(cat, temp, tmp2); + } - sprintf(temp, "mo_%02i_scsi_location", c+1); - if (mo_drives[c].bus_type != MO_BUS_SCSI) - config_delete_var(cat, temp); - else { - sprintf(tmp2, "%01u:%02u", mo_drives[c].scsi_device_id>>4, - mo_drives[c].scsi_device_id & 15); - config_set_string(cat, temp, tmp2); - } + sprintf(temp, "mo_%02i_scsi_id", c + 1); + ini_section_delete_var(cat, temp); - sprintf(temp, "mo_%02i_image_path", c + 1); - if ((mo_drives[c].bus_type == 0) || - (strlen(mo_drives[c].image_path) == 0)) { - config_delete_var(cat, temp); - } else { - config_set_string(cat, temp, mo_drives[c].image_path); - } + sprintf(temp, "mo_%02i_scsi_location", c + 1); + if (mo_drives[c].bus_type != MO_BUS_SCSI) + ini_section_delete_var(cat, temp); + else { + sprintf(tmp2, "%01u:%02u", mo_drives[c].scsi_device_id >> 4, + mo_drives[c].scsi_device_id & 15); + ini_section_set_string(cat, temp, tmp2); + } + + sprintf(temp, "mo_%02i_image_path", c + 1); + if ((mo_drives[c].bus_type == 0) || (strlen(mo_drives[c].image_path) == 0)) + ini_section_delete_var(cat, temp); + else { + path_normalize(mo_drives[c].image_path); + if (!strnicmp(mo_drives[c].image_path, usr_path, strlen(usr_path))) + ini_section_set_string(cat, temp, &mo_drives[c].image_path[strlen(usr_path)]); + else + ini_section_set_string(cat, temp, mo_drives[c].image_path); + } } - delete_section_if_empty(cat); + ini_delete_section_if_empty(config, cat); } - void config_save(void) -{ - save_general(); /* General */ - save_machine(); /* Machine */ - save_video(); /* Video */ - save_input_devices(); /* Input devices */ - save_sound(); /* Sound */ - save_network(); /* Network */ - save_ports(); /* Ports (COM & LPT) */ - save_storage_controllers(); /* Storage controllers */ - save_hard_disks(); /* Hard disks */ - save_floppy_and_cdrom_drives(); /* Floppy and CD-ROM drives */ - save_other_removable_devices(); /* Other removable devices */ - save_other_peripherals(); /* Other peripherals */ - - config_write(cfg_path); -} - - -void -config_dump(void) { - section_t *sec; - - sec = (section_t *)config_head.next; - while (sec != NULL) { - entry_t *ent; + save_general(); /* General */ + for (uint8_t i = 0; i < MONITORS_NUM; i++) + save_monitor(i); /* Monitors */ + save_machine(); /* Machine */ + save_video(); /* Video */ + save_input_devices(); /* Input devices */ + save_sound(); /* Sound */ + save_network(); /* Network */ + save_ports(); /* Ports (COM & LPT) */ + save_storage_controllers(); /* Storage controllers */ + save_hard_disks(); /* Hard disks */ + save_floppy_and_cdrom_drives(); /* Floppy and CD-ROM drives */ + save_other_removable_devices(); /* Other removable devices */ + save_other_peripherals(); /* Other peripherals */ - if (sec->name[0]) - config_log("[%s]\n", sec->name); - - ent = (entry_t *)sec->entry_head.next; - while (ent != NULL) { - config_log("%s = %s\n", ent->name, ent->data); - - ent = (entry_t *)ent->list.next; - } - - sec = (section_t *)sec->list.next; - } + ini_write(config, cfg_path); } - -void -config_delete_var(char *head, char *name) +ini_t +config_get_ini(void) { - section_t *section; - entry_t *entry; - - section = find_section(head); - if (section == NULL) return; - - entry = find_entry(section, name); - if (entry != NULL) { - list_delete(&entry->list, §ion->entry_head); - free(entry); - } -} - - -int -config_get_int(char *head, char *name, int def) -{ - section_t *section; - entry_t *entry; - int value; - - section = find_section(head); - if (section == NULL) - return(def); - - entry = find_entry(section, name); - if (entry == NULL) - return(def); - - sscanf(entry->data, "%i", &value); - - return(value); -} - - -double -config_get_double(char *head, char *name, double def) -{ - section_t *section; - entry_t *entry; - double value; - - section = find_section(head); - if (section == NULL) - return(def); - - entry = find_entry(section, name); - if (entry == NULL) - return(def); - - sscanf(entry->data, "%lg", &value); - - return(value); -} - - -int -config_get_hex16(char *head, char *name, int def) -{ - section_t *section; - entry_t *entry; - unsigned int value; - - section = find_section(head); - if (section == NULL) - return(def); - - entry = find_entry(section, name); - if (entry == NULL) - return(def); - - sscanf(entry->data, "%04X", &value); - - return(value); -} - - -int -config_get_hex20(char *head, char *name, int def) -{ - section_t *section; - entry_t *entry; - unsigned int value; - - section = find_section(head); - if (section == NULL) - return(def); - - entry = find_entry(section, name); - if (entry == NULL) - return(def); - - sscanf(entry->data, "%05X", &value); - - return(value); -} - - -int -config_get_mac(char *head, char *name, int def) -{ - section_t *section; - entry_t *entry; - unsigned int val0 = 0, val1 = 0, val2 = 0; - - section = find_section(head); - if (section == NULL) - return(def); - - entry = find_entry(section, name); - if (entry == NULL) - return(def); - - sscanf(entry->data, "%02x:%02x:%02x", &val0, &val1, &val2); - - return((val0 << 16) + (val1 << 8) + val2); -} - - -char * -config_get_string(char *head, char *name, char *def) -{ - section_t *section; - entry_t *entry; - - section = find_section(head); - if (section == NULL) - return(def); - - entry = find_entry(section, name); - if (entry == NULL) - return(def); - - return(entry->data); -} - - -wchar_t * -config_get_wstring(char *head, char *name, wchar_t *def) -{ - section_t *section; - entry_t *entry; - - section = find_section(head); - if (section == NULL) - return(def); - - entry = find_entry(section, name); - if (entry == NULL) - return(def); - - return(entry->wdata); -} - - -void -config_set_int(char *head, char *name, int val) -{ - section_t *section; - entry_t *ent; - - section = find_section(head); - if (section == NULL) - section = create_section(head); - - ent = find_entry(section, name); - if (ent == NULL) - ent = create_entry(section, name); - - sprintf(ent->data, "%i", val); - mbstowcs(ent->wdata, ent->data, 512); -} - - -void -config_set_double(char *head, char *name, double val) -{ - section_t *section; - entry_t *ent; - - section = find_section(head); - if (section == NULL) - section = create_section(head); - - ent = find_entry(section, name); - if (ent == NULL) - ent = create_entry(section, name); - - sprintf(ent->data, "%lg", val); - mbstowcs(ent->wdata, ent->data, 512); -} - - -void -config_set_hex16(char *head, char *name, int val) -{ - section_t *section; - entry_t *ent; - - section = find_section(head); - if (section == NULL) - section = create_section(head); - - ent = find_entry(section, name); - if (ent == NULL) - ent = create_entry(section, name); - - sprintf(ent->data, "%04X", val); - mbstowcs(ent->wdata, ent->data, sizeof_w(ent->wdata)); -} - - -void -config_set_hex20(char *head, char *name, int val) -{ - section_t *section; - entry_t *ent; - - section = find_section(head); - if (section == NULL) - section = create_section(head); - - ent = find_entry(section, name); - if (ent == NULL) - ent = create_entry(section, name); - - sprintf(ent->data, "%05X", val); - mbstowcs(ent->wdata, ent->data, sizeof_w(ent->wdata)); -} - - -void -config_set_mac(char *head, char *name, int val) -{ - section_t *section; - entry_t *ent; - - section = find_section(head); - if (section == NULL) - section = create_section(head); - - ent = find_entry(section, name); - if (ent == NULL) - ent = create_entry(section, name); - - sprintf(ent->data, "%02x:%02x:%02x", - (val>>16)&0xff, (val>>8)&0xff, val&0xff); - mbstowcs(ent->wdata, ent->data, 512); -} - - -void -config_set_string(char *head, char *name, char *val) -{ - section_t *section; - entry_t *ent; - - section = find_section(head); - if (section == NULL) - section = create_section(head); - - ent = find_entry(section, name); - if (ent == NULL) - ent = create_entry(section, name); - - if ((strlen(val) + 1) <= sizeof(ent->data)) - memcpy(ent->data, val, strlen(val) + 1); - else - memcpy(ent->data, val, sizeof(ent->data)); -#ifdef _WIN32 /* Make sure the string is converted from UTF-8 rather than a legacy codepage */ - mbstoc16s(ent->wdata, ent->data, sizeof_w(ent->wdata)); -#else - mbstowcs(ent->wdata, ent->data, sizeof_w(ent->wdata)); -#endif -} - - -void -config_set_wstring(char *head, char *name, wchar_t *val) -{ - section_t *section; - entry_t *ent; - - section = find_section(head); - if (section == NULL) - section = create_section(head); - - ent = find_entry(section, name); - if (ent == NULL) - ent = create_entry(section, name); - - memcpy(ent->wdata, val, sizeof_w(ent->wdata)); -#ifdef _WIN32 /* Make sure the string is converted to UTF-8 rather than a legacy codepage */ - c16stombs(ent->data, ent->wdata, sizeof(ent->data)); -#else - wcstombs(ent->data, ent->wdata, sizeof(ent->data)); -#endif + return config; } diff --git a/src/cpu/386.c b/src/cpu/386.c index 6af8173eb..f89a8dc96 100644 --- a/src/cpu/386.c +++ b/src/cpu/386.c @@ -6,256 +6,375 @@ #include #include #ifndef INFINITY -# define INFINITY (__builtin_inff()) +# define INFINITY (__builtin_inff()) #endif #define HAVE_STDARG_H #include <86box/86box.h> #include "cpu.h" -#include <86box/timer.h> #include "x86.h" +#include "x86_ops.h" +#include "x86seg_common.h" #include "x87.h" +#include <86box/io.h> #include <86box/nmi.h> #include <86box/mem.h> #include <86box/pic.h> +#include <86box/timer.h> #include <86box/pit.h> #include <86box/fdd.h> #include <86box/fdc.h> #include <86box/machine.h> +#include <86box/gdbstub.h> +#ifndef OPS_286_386 +# define OPS_286_386 +#endif +#include "x86seg.h" #include "386_common.h" #ifdef USE_NEW_DYNAREC -#include "codegen.h" +# include "codegen.h" #endif - #undef CPU_BLOCK_END #define CPU_BLOCK_END() - extern int codegen_flags_changed; -int tempc, oldcpl, optype, inttype, oddeven = 0; -int timetolive; - -uint16_t oldcs; - -uint32_t oldds, oldss, olddslimit, oldsslimit, - olddslimitw, oldsslimitw; -uint32_t oxpc; -uint32_t rmdat32; -uint32_t backupregs[16]; - -x86seg _oldds; - - #ifdef ENABLE_386_LOG int x386_do_log = ENABLE_386_LOG; - void x386_log(const char *fmt, ...) { va_list ap; if (x386_do_log) { - va_start(ap, fmt); - pclog_ex(fmt, ap); - va_end(ap); + va_start(ap, fmt); + pclog_ex(fmt, ap); + va_end(ap); } } #else -#define x386_log(fmt, ...) +# define x386_log(fmt, ...) #endif - #undef CPU_BLOCK_END #define CPU_BLOCK_END() +#define getbytef() \ + ((uint8_t) (fetchdat)); \ + cpu_state.pc++ +#define getwordf() \ + ((uint16_t) (fetchdat)); \ + cpu_state.pc += 2 +#define getbyte2f() \ + ((uint8_t) (fetchdat >> 8)); \ + cpu_state.pc++ +#define getword2f() \ + ((uint16_t) (fetchdat >> 8)); \ + cpu_state.pc += 2 + +static __inline void +fetch_ea_32_long(uint32_t rmdat) +{ + easeg = cpu_state.ea_seg->base; + if (cpu_rm == 4) { + uint8_t sib = rmdat >> 8; + + switch (cpu_mod) { + case 0: + cpu_state.eaaddr = cpu_state.regs[sib & 7].l; + cpu_state.pc++; + break; + case 1: + cpu_state.pc++; + cpu_state.eaaddr = ((uint32_t) (int8_t) getbyte()) + cpu_state.regs[sib & 7].l; + break; + case 2: + cpu_state.eaaddr = (fastreadl(cs + cpu_state.pc + 1)) + cpu_state.regs[sib & 7].l; + cpu_state.pc += 5; + break; + } + /*SIB byte present*/ + if ((sib & 7) == 5 && !cpu_mod) + cpu_state.eaaddr = getlong(); + else if ((sib & 6) == 4 && !cpu_state.ssegs) { + easeg = ss; + cpu_state.ea_seg = &cpu_state.seg_ss; + } + if (((sib >> 3) & 7) != 4) + cpu_state.eaaddr += cpu_state.regs[(sib >> 3) & 7].l << (sib >> 6); + } else { + cpu_state.eaaddr = cpu_state.regs[cpu_rm].l; + if (cpu_mod) { + if (cpu_rm == 5 && !cpu_state.ssegs) { + easeg = ss; + cpu_state.ea_seg = &cpu_state.seg_ss; + } + if (cpu_mod == 1) { + cpu_state.eaaddr += ((uint32_t) (int8_t) (rmdat >> 8)); + cpu_state.pc++; + } else { + cpu_state.eaaddr += getlong(); + } + } else if (cpu_rm == 5) { + cpu_state.eaaddr = getlong(); + } + } +} + +static __inline void +fetch_ea_16_long(uint32_t rmdat) +{ + easeg = cpu_state.ea_seg->base; + if (!cpu_mod && cpu_rm == 6) { + cpu_state.eaaddr = getword(); + } else { + switch (cpu_mod) { + case 0: + cpu_state.eaaddr = 0; + break; + case 1: + cpu_state.eaaddr = (uint16_t) (int8_t) (rmdat >> 8); + cpu_state.pc++; + break; + case 2: + cpu_state.eaaddr = getword(); + break; + } + cpu_state.eaaddr += (*mod1add[0][cpu_rm]) + (*mod1add[1][cpu_rm]); + if (mod1seg[cpu_rm] == &ss && !cpu_state.ssegs) { + easeg = ss; + cpu_state.ea_seg = &cpu_state.seg_ss; + } + cpu_state.eaaddr &= 0xFFFF; + } +} + +#define fetch_ea_16(rmdat) \ + cpu_state.pc++; \ + cpu_mod = (rmdat >> 6) & 3; \ + cpu_reg = (rmdat >> 3) & 7; \ + cpu_rm = rmdat & 7; \ + if (cpu_mod != 3) { \ + fetch_ea_16_long(rmdat); \ + if (cpu_state.abrt) \ + return 1; \ + } +#define fetch_ea_32(rmdat) \ + cpu_state.pc++; \ + cpu_mod = (rmdat >> 6) & 3; \ + cpu_reg = (rmdat >> 3) & 7; \ + cpu_rm = rmdat & 7; \ + if (cpu_mod != 3) { \ + fetch_ea_32_long(rmdat); \ + } \ + if (cpu_state.abrt) \ + return 1 + #include "x86_flags.h" -#define getbytef() ((uint8_t)(fetchdat)); cpu_state.pc++ -#define getwordf() ((uint16_t)(fetchdat)); cpu_state.pc+=2 -#define getbyte2f() ((uint8_t)(fetchdat>>8)); cpu_state.pc++ -#define getword2f() ((uint16_t)(fetchdat>>8)); cpu_state.pc+=2 +#define PREFETCH_RUN(instr_cycles, bytes, modrm, reads, reads_l, writes, writes_l, ea32) \ + do { \ + if (cpu_prefetch_cycles) \ + prefetch_run(instr_cycles, bytes, modrm, reads, reads_l, writes, writes_l, ea32); \ + } while (0) +#define PREFETCH_PREFIX() \ + do { \ + if (cpu_prefetch_cycles) \ + prefetch_prefixes++; \ + } while (0) +#define PREFETCH_FLUSH() prefetch_flush() -#define OP_TABLE(name) ops_ ## name - -#if 0 -#define CLOCK_CYCLES(c) \ - {\ - if (fpu_cycles > 0) {\ - fpu_cycles -= (c);\ - if (fpu_cycles < 0) {\ - cycles += fpu_cycles;\ - }\ - } else {\ - cycles -= (c);\ - }\ - } - -#define CLOCK_CYCLES_FPU(c) cycles -= (c) -#define CONCURRENCY_CYCLES(c) fpu_cycles = (c) -#else -#define CLOCK_CYCLES(c) cycles -= (c) -#define CLOCK_CYCLES_FPU(c) cycles -= (c) -#define CONCURRENCY_CYCLES(c) +#ifndef FPU_CYCLES +# define FPU_CYCLES #endif +#define OP_TABLE(name) ops_2386_##name +#define CLOCK_CYCLES(c) \ + { \ + if (fpu_cycles > 0) { \ + fpu_cycles -= (c); \ + if (fpu_cycles < 0) { \ + cycles += fpu_cycles; \ + } \ + } else { \ + cycles -= (c); \ + } \ + } + +#define CLOCK_CYCLES_FPU(c) cycles -= (c) +#define CONCURRENCY_CYCLES(c) fpu_cycles = (c) + #define CLOCK_CYCLES_ALWAYS(c) cycles -= (c) -#include "x86_ops.h" +#define CHECK_READ_CS(size) \ + if ((cpu_state.pc < cpu_state.seg_cs.limit_low) || \ + ((cpu_state.pc + size - 1) > cpu_state.seg_cs.limit_high)) \ + x86gpf("Limit check (READ)", 0); \ + if (msw & 1 && !(cpu_state.eflags & VM_FLAG) && !(cpu_state.seg_cs.access & 0x80)) \ + x86np("Read from seg not present", cpu_state.seg_cs.seg & 0xfffc); \ +#include "386_ops.h" void -exec386(int cycs) +exec386_2386(int32_t cycs) { - int vector, tempi, cycdiff, oldcyc; - int cycle_period, ins_cycles; + int ol; + + int vector; + int tempi; + int32_t cycdiff; + int32_t oldcyc; + int32_t cycle_period; + int32_t ins_cycles; uint32_t addr; cycles += cycs; while (cycles > 0) { - cycle_period = (timer_target - (uint32_t)tsc) + 1; + cycle_period = (timer_target - (uint32_t) tsc) + 1; - x86_was_reset = 0; - cycdiff = 0; - oldcyc = cycles; - while (cycdiff < cycle_period) { - ins_cycles = cycles; + x86_was_reset = 0; + cycdiff = 0; + oldcyc = cycles; + while (cycdiff < cycle_period) { + ins_cycles = cycles; #ifndef USE_NEW_DYNAREC - oldcs=CS; - oldcpl=CPL; + oldcs = CS; + oldcpl = CPL; #endif - cpu_state.oldpc = cpu_state.pc; - cpu_state.op32 = use32; + cpu_state.oldpc = cpu_state.pc; + cpu_state.op32 = use32; #ifndef USE_NEW_DYNAREC - x86_was_reset = 0; + x86_was_reset = 0; #endif - cpu_state.ea_seg = &cpu_state.seg_ds; - cpu_state.ssegs = 0; + cpu_state.ea_seg = &cpu_state.seg_ds; + cpu_state.ssegs = 0; - fetchdat = fastreadl(cs + cpu_state.pc); + fetchdat = fastreadl_fetch(cs + cpu_state.pc); + ol = opcode_length[fetchdat & 0xff]; + CHECK_READ_CS(MIN(ol, 4)); - if (!cpu_state.abrt) { + if (!cpu_state.abrt) { #ifdef ENABLE_386_LOG - if (in_smm) - x386_log("[%04X:%08X] %08X\n", CS, cpu_state.pc, fetchdat); + if (in_smm) + x386_2386_log("[%04X:%08X] %08X\n", CS, cpu_state.pc, fetchdat); #endif - opcode = fetchdat & 0xFF; - fetchdat >>= 8; - trap = cpu_state.flags & T_FLAG; + opcode = fetchdat & 0xFF; + fetchdat >>= 8; + trap = cpu_state.flags & T_FLAG; - cpu_state.pc++; - x86_opcodes[(opcode | cpu_state.op32) & 0x3ff](fetchdat); - if (x86_was_reset) - break; - } + cpu_state.pc++; + x86_opcodes[(opcode | cpu_state.op32) & 0x3ff](fetchdat); + if (x86_was_reset) + break; + } #ifdef ENABLE_386_LOG - else if (in_smm) - x386_log("[%04X:%08X] ABRT\n", CS, cpu_state.pc); + else if (in_smm) + x386_log("[%04X:%08X] ABRT\n", CS, cpu_state.pc); #endif #ifndef USE_NEW_DYNAREC - if (!use32) cpu_state.pc &= 0xffff; + if (!use32) + cpu_state.pc &= 0xffff; #endif - if (cpu_end_block_after_ins) - cpu_end_block_after_ins--; + if (cpu_end_block_after_ins) + cpu_end_block_after_ins--; - if (cpu_state.abrt) { - flags_rebuild(); - tempi = cpu_state.abrt & ABRT_MASK; - cpu_state.abrt = 0; - x86_doabrt(tempi); - if (cpu_state.abrt) { - cpu_state.abrt = 0; + if (cpu_state.abrt) { + flags_rebuild(); + tempi = cpu_state.abrt & ABRT_MASK; + cpu_state.abrt = 0; + x86_doabrt_2386(tempi); + if (cpu_state.abrt) { + cpu_state.abrt = 0; #ifndef USE_NEW_DYNAREC - CS = oldcs; + CS = oldcs; #endif - cpu_state.pc = cpu_state.oldpc; - x386_log("Double fault\n"); - pmodeint(8, 0); - if (cpu_state.abrt) { - cpu_state.abrt = 0; - softresetx86(); - cpu_set_edx(); + cpu_state.pc = cpu_state.oldpc; + x386_log("Double fault\n"); + pmodeint_2386(8, 0); + if (cpu_state.abrt) { + cpu_state.abrt = 0; + softresetx86(); + cpu_set_edx(); #ifdef ENABLE_386_LOG - x386_log("Triple fault - reset\n"); + x386_log("Triple fault - reset\n"); #endif - } - } - } + } + } + } else if (trap) { + flags_rebuild(); + trap = 0; +#ifndef USE_NEW_DYNAREC + oldcs = CS; +#endif + cpu_state.oldpc = cpu_state.pc; + dr[6] |= 0x4000; + x86_int(1); + } - if (smi_line) - enter_smm_check(0); - else if (trap) { - flags_rebuild(); - if (msw&1) - pmodeint(1,0); - else { - writememw(ss, (SP - 2) & 0xFFFF, cpu_state.flags); - writememw(ss, (SP - 4) & 0xFFFF, CS); - writememw(ss, (SP - 6) & 0xFFFF, cpu_state.pc); - SP -= 6; - addr = (1 << 2) + idt.base; - cpu_state.flags &= ~I_FLAG; - cpu_state.flags &= ~T_FLAG; - cpu_state.pc = readmemw(0, addr); - loadcs(readmemw(0, addr + 2)); - } - } else if (nmi && nmi_enable && nmi_mask) { - if (is486 && (cpu_fast_off_flags & 0x20000000)) - cpu_fast_off_count = cpu_fast_off_val + 1; - - cpu_state.oldpc = cpu_state.pc; - x86_int(2); - nmi_enable = 0; + if (smi_line) + enter_smm_check(0); + else if (nmi && nmi_enable && nmi_mask) { +#ifndef USE_NEW_DYNAREC + oldcs = CS; +#endif + cpu_state.oldpc = cpu_state.pc; + x86_int(2); + nmi_enable = 0; #ifdef OLD_NMI_BEHAVIOR - if (nmi_auto_clear) { - nmi_auto_clear = 0; - nmi = 0; - } + if (nmi_auto_clear) { + nmi_auto_clear = 0; + nmi = 0; + } #else - nmi = 0; + nmi = 0; #endif - } else if ((cpu_state.flags & I_FLAG) && pic.int_pending && !cpu_end_block_after_ins) { - vector = picinterrupt(); - if (vector != -1) { - flags_rebuild(); - if (msw & 1) - pmodeint(vector, 0); - else { - writememw(ss, (SP - 2) & 0xFFFF, cpu_state.flags); - writememw(ss, (SP - 4) & 0xFFFF, CS); - writememw(ss, (SP - 6) & 0xFFFF, cpu_state.pc); - SP -= 6; - addr = (vector << 2) + idt.base; - cpu_state.flags &= ~I_FLAG; - cpu_state.flags &= ~T_FLAG; - cpu_state.pc = readmemw(0, addr); - loadcs(readmemw(0, addr + 2)); - } - } - } + } else if ((cpu_state.flags & I_FLAG) && pic.int_pending && !cpu_end_block_after_ins) { + vector = picinterrupt(); + if (vector != -1) { + flags_rebuild(); + if (msw & 1) + pmodeint_2386(vector, 0); + else { + writememw(ss, (SP - 2) & 0xFFFF, cpu_state.flags); + writememw(ss, (SP - 4) & 0xFFFF, CS); + writememw(ss, (SP - 6) & 0xFFFF, cpu_state.pc); + SP -= 6; + addr = (vector << 2) + idt.base; + cpu_state.flags &= ~I_FLAG; + cpu_state.flags &= ~T_FLAG; + cpu_state.pc = readmemw(0, addr); + loadcs_2386(readmemw(0, addr + 2)); + } + } + } - ins_cycles -= cycles; - tsc += ins_cycles; + ins_cycles -= cycles; + tsc += ins_cycles; - cycdiff = oldcyc - cycles; + cycdiff = oldcyc - cycles; - if (timetolive) { - timetolive--; - if (!timetolive) - fatal("Life expired\n"); - } + if (timetolive) { + timetolive--; + if (!timetolive) + fatal("Life expired\n"); + } - if (TIMER_VAL_LESS_THAN_VAL(timer_target, (uint32_t) tsc)) - timer_process_inline(); - } + if (TIMER_VAL_LESS_THAN_VAL(timer_target, (uint32_t) tsc)) + timer_process(); + +#ifdef USE_GDBSTUB + if (gdbstub_instruction()) + return; +#endif + } } } diff --git a/src/cpu/386_common.c b/src/cpu/386_common.c index 4eb9530ba..60ecd8954 100644 --- a/src/cpu/386_common.c +++ b/src/cpu/386_common.c @@ -6,13 +6,14 @@ #include #include #ifndef INFINITY -# define INFINITY (__builtin_inff()) +# define INFINITY (__builtin_inff()) #endif #define HAVE_STDARG_H #include <86box/86box.h> #include "cpu.h" #include <86box/timer.h> #include "x86.h" +#include "x86seg_common.h" #include "x87.h" #include <86box/nmi.h> #include <86box/mem.h> @@ -22,31 +23,40 @@ #include <86box/fdd.h> #include <86box/fdc.h> #include <86box/keyboard.h> +#include <86box/timer.h> + +#include "x86seg.h" #include "386_common.h" #include "x86_flags.h" -#include "x86seg.h" +#include <86box/plat_unused.h> #ifdef USE_DYNAREC -#include "codegen.h" -#define CPU_BLOCK_END() cpu_block_end = 1 +# include "codegen.h" +# define CPU_BLOCK_END() cpu_block_end = 1 #else -#define CPU_BLOCK_END() +# define CPU_BLOCK_END() #endif +x86seg gdt; +x86seg ldt; +x86seg idt; +x86seg tr; -x86seg gdt, ldt, idt, tr; - -uint32_t cr2, cr3, cr4; +uint32_t cr2; +uint32_t cr3; +uint32_t cr4; uint32_t dr[8]; uint32_t use32; -int stack32; +int stack32; -uint32_t *eal_r, *eal_w; +uint32_t *eal_r; +uint32_t *eal_w; int nmi_enable = 1; -int alt_access, cpl_override = 0; +int alt_access; +int cpl_override = 0; #ifdef USE_NEW_DYNAREC uint16_t cpu_cur_status = 0; @@ -56,360 +66,466 @@ uint32_t cpu_cur_status = 0; extern uint8_t *pccache2; -extern int optype; +extern int optype; extern uint32_t pccache; - -int in_sys = 0, unmask_a20_in_smm = 0; -uint32_t old_rammask = 0xffffffff; +int in_sys = 0; +int unmask_a20_in_smm = 0; +uint32_t old_rammask = 0xffffffff; int soft_reset_mask = 0; int smi_latched = 0; -int smm_in_hlt = 0, smi_block = 0; +int smm_in_hlt = 0; +int smi_block = 0; -uint32_t addr64, addr64_2; -uint32_t addr64a[8], addr64a_2[8]; +int prefetch_prefixes = 0; +int tempc; +int oldcpl; +int optype; +int inttype; +int oddeven = 0; +int timetolive; -#define AMD_SYSCALL_EIP (msr.star & 0xFFFFFFFF) -#define AMD_SYSCALL_SB ((msr.star >> 32) & 0xFFFF) -#define AMD_SYSRET_SB ((msr.star >> 48) & 0xFFFF) +uint16_t oldcs; +uint32_t oldds; +uint32_t oldss; +uint32_t olddslimit; +uint32_t oldsslimit; +uint32_t olddslimitw; +uint32_t oldsslimitw; +uint32_t oxpc; +uint32_t rmdat32; +uint32_t backupregs[16]; + +x86seg _oldds; + +int opcode_length[256] = { 3, 3, 3, 3, 3, 3, 1, 1, 3, 3, 3, 3, 3, 3, 1, 3, /* 0x0x */ + 3, 3, 3, 3, 3, 3, 1, 1, 3, 3, 3, 3, 3, 3, 1, 1, /* 0x1x */ + 3, 3, 3, 3, 3, 3, 1, 1, 3, 3, 3, 3, 3, 3, 1, 1, /* 0x2x */ + 3, 3, 3, 3, 3, 3, 1, 1, 3, 3, 3, 3, 3, 3, 1, 1, /* 0x3x */ + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* 0x4x */ + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* 0x5x */ + 1, 1, 3, 3, 1, 1, 1, 1, 3, 3, 2, 3, 1, 1, 1, 1, /* 0x6x */ + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, /* 0x7x */ + 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, /* 0x8x */ + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 3, 1, 1, 1, 1, 1, /* 0x9x */ + 3, 3, 3, 3, 1, 1, 1, 1, 2, 3, 1, 1, 1, 1, 1, 1, /* 0xax */ + 2, 2, 2, 2, 2, 2, 2, 2, 3, 3, 3, 3, 3, 3, 3, 3, /* 0xbx */ + 3, 3, 3, 1, 3, 3, 3, 3, 3, 1, 3, 1, 1, 2, 1, 1, /* 0xcx */ + 3, 3, 3, 3, 2, 2, 1, 1, 3, 3, 3, 3, 3, 3, 3, 3, /* 0xdx */ + 2, 2, 2, 2, 2, 2, 2, 2, 3, 3, 3, 2, 1, 1, 1, 1, /* 0xex */ + 1, 1, 1, 1, 1, 1, 3, 3, 1, 1, 1, 1, 1, 1, 3, 3 }; /* 0xfx */ + +uint32_t addr64; +uint32_t addr64_2; +uint32_t addr64a[8]; +uint32_t addr64a_2[8]; + +static pc_timer_t *cpu_fast_off_timer = NULL; +static double cpu_fast_off_period = 0.0; + +#define AMD_SYSCALL_EIP (msr.star & 0xFFFFFFFF) +#define AMD_SYSCALL_SB ((msr.star >> 32) & 0xFFFF) +#define AMD_SYSRET_SB ((msr.star >> 48) & 0xFFFF) /* These #define's and enum have been borrowed from Bochs. */ /* SMM feature masks */ -#define SMM_IO_INSTRUCTION_RESTART (0x00010000) -#define SMM_SMBASE_RELOCATION (0x00020000) -#define SMM_REVISION (0x20000000) +#define SMM_IO_INSTRUCTION_RESTART (0x00010000) +#define SMM_SMBASE_RELOCATION (0x00020000) +#define SMM_REVISION (0x20000000) /* TODO: Which CPU added SMBASE relocation? */ -#define SMM_REVISION_ID (SMM_SMBASE_RELOCATION | SMM_IO_INSTRUCTION_RESTART | SMM_REVISION) +#define SMM_REVISION_ID (SMM_SMBASE_RELOCATION | SMM_IO_INSTRUCTION_RESTART | SMM_REVISION) #define SMM_SAVE_STATE_MAP_SIZE 128 - enum SMMRAM_Fields_386_To_P5 { - SMRAM_FIELD_P5_CR0 = 0, /* 1FC */ - SMRAM_FIELD_P5_CR3, /* 1F8 */ - SMRAM_FIELD_P5_EFLAGS, /* 1F4 */ - SMRAM_FIELD_P5_EIP, /* 1F0 */ - SMRAM_FIELD_P5_EDI, /* 1EC */ - SMRAM_FIELD_P5_ESI, /* 1E8 */ - SMRAM_FIELD_P5_EBP, /* 1E4 */ - SMRAM_FIELD_P5_ESP, /* 1E0 */ - SMRAM_FIELD_P5_EBX, /* 1DC */ - SMRAM_FIELD_P5_EDX, /* 1D8 */ - SMRAM_FIELD_P5_ECX, /* 1D4 */ - SMRAM_FIELD_P5_EAX, /* 1D0 */ - SMRAM_FIELD_P5_DR6, /* 1CC */ - SMRAM_FIELD_P5_DR7, /* 1C8 */ - SMRAM_FIELD_P5_TR_SELECTOR, /* 1C4 */ - SMRAM_FIELD_P5_LDTR_SELECTOR, /* 1C0 */ - SMRAM_FIELD_P5_GS_SELECTOR, /* 1BC */ - SMRAM_FIELD_P5_FS_SELECTOR, /* 1B8 */ - SMRAM_FIELD_P5_DS_SELECTOR, /* 1B4 */ - SMRAM_FIELD_P5_SS_SELECTOR, /* 1B0 */ - SMRAM_FIELD_P5_CS_SELECTOR, /* 1AC */ - SMRAM_FIELD_P5_ES_SELECTOR, /* 1A8 */ - SMRAM_FIELD_P5_TR_ACCESS, /* 1A4 */ - SMRAM_FIELD_P5_TR_BASE, /* 1A0 */ - SMRAM_FIELD_P5_TR_LIMIT, /* 19C */ - SMRAM_FIELD_P5_IDTR_ACCESS, /* 198 */ - SMRAM_FIELD_P5_IDTR_BASE, /* 194 */ - SMRAM_FIELD_P5_IDTR_LIMIT, /* 190 */ - SMRAM_FIELD_P5_GDTR_ACCESS, /* 18C */ - SMRAM_FIELD_P5_GDTR_BASE, /* 188 */ - SMRAM_FIELD_P5_GDTR_LIMIT, /* 184 */ - SMRAM_FIELD_P5_LDTR_ACCESS, /* 180 */ - SMRAM_FIELD_P5_LDTR_BASE, /* 17C */ - SMRAM_FIELD_P5_LDTR_LIMIT, /* 178 */ - SMRAM_FIELD_P5_GS_ACCESS, /* 174 */ - SMRAM_FIELD_P5_GS_BASE, /* 170 */ - SMRAM_FIELD_P5_GS_LIMIT, /* 16C */ - SMRAM_FIELD_P5_FS_ACCESS, /* 168 */ - SMRAM_FIELD_P5_FS_BASE, /* 164 */ - SMRAM_FIELD_P5_FS_LIMIT, /* 160 */ - SMRAM_FIELD_P5_DS_ACCESS, /* 15C */ - SMRAM_FIELD_P5_DS_BASE, /* 158 */ - SMRAM_FIELD_P5_DS_LIMIT, /* 154 */ - SMRAM_FIELD_P5_SS_ACCESS, /* 150 */ - SMRAM_FIELD_P5_SS_BASE, /* 14C */ - SMRAM_FIELD_P5_SS_LIMIT, /* 148 */ - SMRAM_FIELD_P5_CS_ACCESS, /* 144 */ - SMRAM_FIELD_P5_CS_BASE, /* 140 */ - SMRAM_FIELD_P5_CS_LIMIT, /* 13C */ - SMRAM_FIELD_P5_ES_ACCESS, /* 138 */ - SMRAM_FIELD_P5_ES_BASE, /* 134 */ - SMRAM_FIELD_P5_ES_LIMIT, /* 130 */ - SMRAM_FIELD_P5_UNWRITTEN_1, /* 12C */ - SMRAM_FIELD_P5_CR4, /* 128 */ - SMRAM_FIELD_P5_ALTERNATE_DR6, /* 124 */ - SMRAM_FIELD_P5_RESERVED_1, /* 120 */ - SMRAM_FIELD_P5_RESERVED_2, /* 11C */ - SMRAM_FIELD_P5_RESERVED_3, /* 118 */ - SMRAM_FIELD_P5_RESERVED_4, /* 114 */ - SMRAM_FIELD_P5_IO_RESTART_EIP, /* 110 */ - SMRAM_FIELD_P5_IO_RESTART_ESI, /* 10C */ - SMRAM_FIELD_P5_IO_RESTART_ECX, /* 108 */ - SMRAM_FIELD_P5_IO_RESTART_EDI, /* 104 */ - SMRAM_FIELD_P5_AUTOHALT_RESTART, /* 100 */ - SMRAM_FIELD_P5_SMM_REVISION_ID, /* 0FC */ - SMRAM_FIELD_P5_SMBASE_OFFSET, /* 0F8 */ - SMRAM_FIELD_AM486_CR2, /* 0F4 */ - SMRAM_FIELD_AM486_DR0, /* 0F0 */ - SMRAM_FIELD_AM486_DR1, /* 0EC */ - SMRAM_FIELD_AM486_DR2, /* 0E8 */ - SMRAM_FIELD_AM486_DR3, /* 0E4 */ + SMRAM_FIELD_P5_CR0 = 0, /* 1FC */ + SMRAM_FIELD_P5_CR3, /* 1F8 */ + SMRAM_FIELD_P5_EFLAGS, /* 1F4 */ + SMRAM_FIELD_P5_EIP, /* 1F0 */ + SMRAM_FIELD_P5_EDI, /* 1EC */ + SMRAM_FIELD_P5_ESI, /* 1E8 */ + SMRAM_FIELD_P5_EBP, /* 1E4 */ + SMRAM_FIELD_P5_ESP, /* 1E0 */ + SMRAM_FIELD_P5_EBX, /* 1DC */ + SMRAM_FIELD_P5_EDX, /* 1D8 */ + SMRAM_FIELD_P5_ECX, /* 1D4 */ + SMRAM_FIELD_P5_EAX, /* 1D0 */ + SMRAM_FIELD_P5_DR6, /* 1CC */ + SMRAM_FIELD_P5_DR7, /* 1C8 */ + SMRAM_FIELD_P5_TR_SELECTOR, /* 1C4 */ + SMRAM_FIELD_P5_LDTR_SELECTOR, /* 1C0 */ + SMRAM_FIELD_P5_GS_SELECTOR, /* 1BC */ + SMRAM_FIELD_P5_FS_SELECTOR, /* 1B8 */ + SMRAM_FIELD_P5_DS_SELECTOR, /* 1B4 */ + SMRAM_FIELD_P5_SS_SELECTOR, /* 1B0 */ + SMRAM_FIELD_P5_CS_SELECTOR, /* 1AC */ + SMRAM_FIELD_P5_ES_SELECTOR, /* 1A8 */ + SMRAM_FIELD_P5_TR_ACCESS, /* 1A4 */ + SMRAM_FIELD_P5_TR_BASE, /* 1A0 */ + SMRAM_FIELD_P5_TR_LIMIT, /* 19C */ + SMRAM_FIELD_P5_IDTR_ACCESS, /* 198 */ + SMRAM_FIELD_P5_IDTR_BASE, /* 194 */ + SMRAM_FIELD_P5_IDTR_LIMIT, /* 190 */ + SMRAM_FIELD_P5_GDTR_ACCESS, /* 18C */ + SMRAM_FIELD_P5_GDTR_BASE, /* 188 */ + SMRAM_FIELD_P5_GDTR_LIMIT, /* 184 */ + SMRAM_FIELD_P5_LDTR_ACCESS, /* 180 */ + SMRAM_FIELD_P5_LDTR_BASE, /* 17C */ + SMRAM_FIELD_P5_LDTR_LIMIT, /* 178 */ + SMRAM_FIELD_P5_GS_ACCESS, /* 174 */ + SMRAM_FIELD_P5_GS_BASE, /* 170 */ + SMRAM_FIELD_P5_GS_LIMIT, /* 16C */ + SMRAM_FIELD_P5_FS_ACCESS, /* 168 */ + SMRAM_FIELD_P5_FS_BASE, /* 164 */ + SMRAM_FIELD_P5_FS_LIMIT, /* 160 */ + SMRAM_FIELD_P5_DS_ACCESS, /* 15C */ + SMRAM_FIELD_P5_DS_BASE, /* 158 */ + SMRAM_FIELD_P5_DS_LIMIT, /* 154 */ + SMRAM_FIELD_P5_SS_ACCESS, /* 150 */ + SMRAM_FIELD_P5_SS_BASE, /* 14C */ + SMRAM_FIELD_P5_SS_LIMIT, /* 148 */ + SMRAM_FIELD_P5_CS_ACCESS, /* 144 */ + SMRAM_FIELD_P5_CS_BASE, /* 140 */ + SMRAM_FIELD_P5_CS_LIMIT, /* 13C */ + SMRAM_FIELD_P5_ES_ACCESS, /* 138 */ + SMRAM_FIELD_P5_ES_BASE, /* 134 */ + SMRAM_FIELD_P5_ES_LIMIT, /* 130 */ + SMRAM_FIELD_P5_UNWRITTEN_1, /* 12C */ + SMRAM_FIELD_P5_CR4, /* 128 */ + SMRAM_FIELD_P5_ALTERNATE_DR6, /* 124 */ + SMRAM_FIELD_P5_RESERVED_1, /* 120 */ + SMRAM_FIELD_P5_RESERVED_2, /* 11C */ + SMRAM_FIELD_P5_RESERVED_3, /* 118 */ + SMRAM_FIELD_P5_RESERVED_4, /* 114 */ + SMRAM_FIELD_P5_IO_RESTART_EIP, /* 110 */ + SMRAM_FIELD_P5_IO_RESTART_ESI, /* 10C */ + SMRAM_FIELD_P5_IO_RESTART_ECX, /* 108 */ + SMRAM_FIELD_P5_IO_RESTART_EDI, /* 104 */ + SMRAM_FIELD_P5_AUTOHALT_RESTART, /* 100 */ + SMRAM_FIELD_P5_SMM_REVISION_ID, /* 0FC */ + SMRAM_FIELD_P5_SMBASE_OFFSET, /* 0F8 */ + SMRAM_FIELD_AM486_CR2, /* 0F4 */ + SMRAM_FIELD_AM486_DR0, /* 0F0 */ + SMRAM_FIELD_AM486_DR1, /* 0EC */ + SMRAM_FIELD_AM486_DR2, /* 0E8 */ + SMRAM_FIELD_AM486_DR3, /* 0E4 */ SMRAM_FIELD_P5_LAST }; enum SMMRAM_Fields_P6 { - SMRAM_FIELD_P6_CR0 = 0, /* 1FC */ - SMRAM_FIELD_P6_CR3, /* 1F8 */ - SMRAM_FIELD_P6_EFLAGS, /* 1F4 */ - SMRAM_FIELD_P6_EIP, /* 1F0 */ - SMRAM_FIELD_P6_EDI, /* 1EC */ - SMRAM_FIELD_P6_ESI, /* 1E8 */ - SMRAM_FIELD_P6_EBP, /* 1E4 */ - SMRAM_FIELD_P6_ESP, /* 1E0 */ - SMRAM_FIELD_P6_EBX, /* 1DC */ - SMRAM_FIELD_P6_EDX, /* 1D8 */ - SMRAM_FIELD_P6_ECX, /* 1D4 */ - SMRAM_FIELD_P6_EAX, /* 1D0 */ - SMRAM_FIELD_P6_DR6, /* 1CC */ - SMRAM_FIELD_P6_DR7, /* 1C8 */ - SMRAM_FIELD_P6_TR_SELECTOR, /* 1C4 */ - SMRAM_FIELD_P6_LDTR_SELECTOR, /* 1C0 */ - SMRAM_FIELD_P6_GS_SELECTOR, /* 1BC */ - SMRAM_FIELD_P6_FS_SELECTOR, /* 1B8 */ - SMRAM_FIELD_P6_DS_SELECTOR, /* 1B4 */ - SMRAM_FIELD_P6_SS_SELECTOR, /* 1B0 */ - SMRAM_FIELD_P6_CS_SELECTOR, /* 1AC */ - SMRAM_FIELD_P6_ES_SELECTOR, /* 1A8 */ - SMRAM_FIELD_P6_SS_BASE, /* 1A4 */ - SMRAM_FIELD_P6_SS_LIMIT, /* 1A0 */ - SMRAM_FIELD_P6_SS_SELECTOR_AR, /* 19C */ - SMRAM_FIELD_P6_CS_BASE, /* 198 */ - SMRAM_FIELD_P6_CS_LIMIT, /* 194 */ - SMRAM_FIELD_P6_CS_SELECTOR_AR, /* 190 */ - SMRAM_FIELD_P6_ES_BASE, /* 18C */ - SMRAM_FIELD_P6_ES_LIMIT, /* 188 */ - SMRAM_FIELD_P6_ES_SELECTOR_AR, /* 184 */ - SMRAM_FIELD_P6_LDTR_BASE, /* 180 */ - SMRAM_FIELD_P6_LDTR_LIMIT, /* 17C */ - SMRAM_FIELD_P6_LDTR_SELECTOR_AR, /* 178 */ - SMRAM_FIELD_P6_GDTR_BASE, /* 174 */ - SMRAM_FIELD_P6_GDTR_LIMIT, /* 170 */ - SMRAM_FIELD_P6_GDTR_SELECTOR_AR, /* 16C */ - SMRAM_FIELD_P6_SREG_STATUS1, /* 168 */ - SMRAM_FIELD_P6_TR_BASE, /* 164 */ - SMRAM_FIELD_P6_TR_LIMIT, /* 160 */ - SMRAM_FIELD_P6_TR_SELECTOR_AR, /* 15C */ - SMRAM_FIELD_P6_IDTR_BASE, /* 158 */ - SMRAM_FIELD_P6_IDTR_LIMIT, /* 154 */ - SMRAM_FIELD_P6_IDTR_SELECTOR_AR, /* 150 */ - SMRAM_FIELD_P6_GS_BASE, /* 14C */ - SMRAM_FIELD_P6_GS_LIMIT, /* 148 */ - SMRAM_FIELD_P6_GS_SELECTOR_AR, /* 144 */ - SMRAM_FIELD_P6_FS_BASE, /* 140 */ - SMRAM_FIELD_P6_FS_LIMIT, /* 13C */ - SMRAM_FIELD_P6_FS_SELECTOR_AR, /* 138 */ - SMRAM_FIELD_P6_DS_BASE, /* 134 */ - SMRAM_FIELD_P6_DS_LIMIT, /* 130 */ - SMRAM_FIELD_P6_DS_SELECTOR_AR, /* 12C */ - SMRAM_FIELD_P6_SREG_STATUS0, /* 128 */ - SMRAM_FIELD_P6_ALTERNATIVE_DR6, /* 124 */ - SMRAM_FIELD_P6_CPL, /* 120 */ - SMRAM_FIELD_P6_SMM_STATUS, /* 11C */ - SMRAM_FIELD_P6_A20M, /* 118 */ - SMRAM_FIELD_P6_CR4, /* 114 */ - SMRAM_FIELD_P6_IO_RESTART_EIP, /* 110 */ - SMRAM_FIELD_P6_IO_RESTART_ESI, /* 10C */ - SMRAM_FIELD_P6_IO_RESTART_ECX, /* 108 */ - SMRAM_FIELD_P6_IO_RESTART_EDI, /* 104 */ - SMRAM_FIELD_P6_AUTOHALT_RESTART, /* 100 */ - SMRAM_FIELD_P6_SMM_REVISION_ID, /* 0FC */ - SMRAM_FIELD_P6_SMBASE_OFFSET, /* 0F8 */ + SMRAM_FIELD_P6_CR0 = 0, /* 1FC */ + SMRAM_FIELD_P6_CR3, /* 1F8 */ + SMRAM_FIELD_P6_EFLAGS, /* 1F4 */ + SMRAM_FIELD_P6_EIP, /* 1F0 */ + SMRAM_FIELD_P6_EDI, /* 1EC */ + SMRAM_FIELD_P6_ESI, /* 1E8 */ + SMRAM_FIELD_P6_EBP, /* 1E4 */ + SMRAM_FIELD_P6_ESP, /* 1E0 */ + SMRAM_FIELD_P6_EBX, /* 1DC */ + SMRAM_FIELD_P6_EDX, /* 1D8 */ + SMRAM_FIELD_P6_ECX, /* 1D4 */ + SMRAM_FIELD_P6_EAX, /* 1D0 */ + SMRAM_FIELD_P6_DR6, /* 1CC */ + SMRAM_FIELD_P6_DR7, /* 1C8 */ + SMRAM_FIELD_P6_TR_SELECTOR, /* 1C4 */ + SMRAM_FIELD_P6_LDTR_SELECTOR, /* 1C0 */ + SMRAM_FIELD_P6_GS_SELECTOR, /* 1BC */ + SMRAM_FIELD_P6_FS_SELECTOR, /* 1B8 */ + SMRAM_FIELD_P6_DS_SELECTOR, /* 1B4 */ + SMRAM_FIELD_P6_SS_SELECTOR, /* 1B0 */ + SMRAM_FIELD_P6_CS_SELECTOR, /* 1AC */ + SMRAM_FIELD_P6_ES_SELECTOR, /* 1A8 */ + SMRAM_FIELD_P6_SS_BASE, /* 1A4 */ + SMRAM_FIELD_P6_SS_LIMIT, /* 1A0 */ + SMRAM_FIELD_P6_SS_SELECTOR_AR, /* 19C */ + SMRAM_FIELD_P6_CS_BASE, /* 198 */ + SMRAM_FIELD_P6_CS_LIMIT, /* 194 */ + SMRAM_FIELD_P6_CS_SELECTOR_AR, /* 190 */ + SMRAM_FIELD_P6_ES_BASE, /* 18C */ + SMRAM_FIELD_P6_ES_LIMIT, /* 188 */ + SMRAM_FIELD_P6_ES_SELECTOR_AR, /* 184 */ + SMRAM_FIELD_P6_LDTR_BASE, /* 180 */ + SMRAM_FIELD_P6_LDTR_LIMIT, /* 17C */ + SMRAM_FIELD_P6_LDTR_SELECTOR_AR, /* 178 */ + SMRAM_FIELD_P6_GDTR_BASE, /* 174 */ + SMRAM_FIELD_P6_GDTR_LIMIT, /* 170 */ + SMRAM_FIELD_P6_GDTR_SELECTOR_AR, /* 16C */ + SMRAM_FIELD_P6_SREG_STATUS1, /* 168 */ + SMRAM_FIELD_P6_TR_BASE, /* 164 */ + SMRAM_FIELD_P6_TR_LIMIT, /* 160 */ + SMRAM_FIELD_P6_TR_SELECTOR_AR, /* 15C */ + SMRAM_FIELD_P6_IDTR_BASE, /* 158 */ + SMRAM_FIELD_P6_IDTR_LIMIT, /* 154 */ + SMRAM_FIELD_P6_IDTR_SELECTOR_AR, /* 150 */ + SMRAM_FIELD_P6_GS_BASE, /* 14C */ + SMRAM_FIELD_P6_GS_LIMIT, /* 148 */ + SMRAM_FIELD_P6_GS_SELECTOR_AR, /* 144 */ + SMRAM_FIELD_P6_FS_BASE, /* 140 */ + SMRAM_FIELD_P6_FS_LIMIT, /* 13C */ + SMRAM_FIELD_P6_FS_SELECTOR_AR, /* 138 */ + SMRAM_FIELD_P6_DS_BASE, /* 134 */ + SMRAM_FIELD_P6_DS_LIMIT, /* 130 */ + SMRAM_FIELD_P6_DS_SELECTOR_AR, /* 12C */ + SMRAM_FIELD_P6_SREG_STATUS0, /* 128 */ + SMRAM_FIELD_P6_ALTERNATIVE_DR6, /* 124 */ + SMRAM_FIELD_P6_CPL, /* 120 */ + SMRAM_FIELD_P6_SMM_STATUS, /* 11C */ + SMRAM_FIELD_P6_A20M, /* 118 */ + SMRAM_FIELD_P6_CR4, /* 114 */ + SMRAM_FIELD_P6_IO_RESTART_EIP, /* 110 */ + SMRAM_FIELD_P6_IO_RESTART_ESI, /* 10C */ + SMRAM_FIELD_P6_IO_RESTART_ECX, /* 108 */ + SMRAM_FIELD_P6_IO_RESTART_EDI, /* 104 */ + SMRAM_FIELD_P6_AUTOHALT_RESTART, /* 100 */ + SMRAM_FIELD_P6_SMM_REVISION_ID, /* 0FC */ + SMRAM_FIELD_P6_SMBASE_OFFSET, /* 0F8 */ SMRAM_FIELD_P6_LAST }; enum SMMRAM_Fields_AMD_K { - SMRAM_FIELD_AMD_K_CR0 = 0, /* 1FC */ - SMRAM_FIELD_AMD_K_CR3, /* 1F8 */ - SMRAM_FIELD_AMD_K_EFLAGS, /* 1F4 */ - SMRAM_FIELD_AMD_K_EIP, /* 1F0 */ - SMRAM_FIELD_AMD_K_EDI, /* 1EC */ - SMRAM_FIELD_AMD_K_ESI, /* 1E8 */ - SMRAM_FIELD_AMD_K_EBP, /* 1E4 */ - SMRAM_FIELD_AMD_K_ESP, /* 1E0 */ - SMRAM_FIELD_AMD_K_EBX, /* 1DC */ - SMRAM_FIELD_AMD_K_EDX, /* 1D8 */ - SMRAM_FIELD_AMD_K_ECX, /* 1D4 */ - SMRAM_FIELD_AMD_K_EAX, /* 1D0 */ - SMRAM_FIELD_AMD_K_DR6, /* 1CC */ - SMRAM_FIELD_AMD_K_DR7, /* 1C8 */ - SMRAM_FIELD_AMD_K_TR_SELECTOR, /* 1C4 */ - SMRAM_FIELD_AMD_K_LDTR_SELECTOR, /* 1C0 */ - SMRAM_FIELD_AMD_K_GS_SELECTOR, /* 1BC */ - SMRAM_FIELD_AMD_K_FS_SELECTOR, /* 1B8 */ - SMRAM_FIELD_AMD_K_DS_SELECTOR, /* 1B4 */ - SMRAM_FIELD_AMD_K_SS_SELECTOR, /* 1B0 */ - SMRAM_FIELD_AMD_K_CS_SELECTOR, /* 1AC */ - SMRAM_FIELD_AMD_K_ES_SELECTOR, /* 1A8 */ - SMRAM_FIELD_AMD_K_IO_RESTART_DWORD, /* 1A4 */ - SMRAM_FIELD_AMD_K_RESERVED_1, /* 1A0 */ - SMRAM_FIELD_AMD_K_IO_RESTART_EIP, /* 19C */ - SMRAM_FIELD_AMD_K_RESERVED_2, /* 198 */ - SMRAM_FIELD_AMD_K_RESERVED_3, /* 194 */ - SMRAM_FIELD_AMD_K_IDTR_BASE, /* 190 */ - SMRAM_FIELD_AMD_K_IDTR_LIMIT, /* 18C */ - SMRAM_FIELD_AMD_K_GDTR_BASE, /* 188 */ - SMRAM_FIELD_AMD_K_GDTR_LIMIT, /* 184 */ - SMRAM_FIELD_AMD_K_TR_ACCESS, /* 180 */ - SMRAM_FIELD_AMD_K_TR_BASE, /* 17C */ - SMRAM_FIELD_AMD_K_TR_LIMIT, /* 178 */ - SMRAM_FIELD_AMD_K_LDTR_ACCESS, /* 174 - reserved on K6 */ - SMRAM_FIELD_AMD_K_LDTR_BASE, /* 170 */ - SMRAM_FIELD_AMD_K_LDTR_LIMIT, /* 16C */ - SMRAM_FIELD_AMD_K_GS_ACCESS, /* 168 */ - SMRAM_FIELD_AMD_K_GS_BASE, /* 164 */ - SMRAM_FIELD_AMD_K_GS_LIMIT, /* 160 */ - SMRAM_FIELD_AMD_K_FS_ACCESS, /* 15C */ - SMRAM_FIELD_AMD_K_FS_BASE, /* 158 */ - SMRAM_FIELD_AMD_K_FS_LIMIT, /* 154 */ - SMRAM_FIELD_AMD_K_DS_ACCESS, /* 150 */ - SMRAM_FIELD_AMD_K_DS_BASE, /* 14C */ - SMRAM_FIELD_AMD_K_DS_LIMIT, /* 148 */ - SMRAM_FIELD_AMD_K_SS_ACCESS, /* 144 */ - SMRAM_FIELD_AMD_K_SS_BASE, /* 140 */ - SMRAM_FIELD_AMD_K_SS_LIMIT, /* 13C */ - SMRAM_FIELD_AMD_K_CS_ACCESS, /* 138 */ - SMRAM_FIELD_AMD_K_CS_BASE, /* 134 */ - SMRAM_FIELD_AMD_K_CS_LIMIT, /* 130 */ - SMRAM_FIELD_AMD_K_ES_ACCESS, /* 12C */ - SMRAM_FIELD_AMD_K_ES_BASE, /* 128 */ - SMRAM_FIELD_AMD_K_ES_LIMIT, /* 124 */ - SMRAM_FIELD_AMD_K_RESERVED_4, /* 120 */ - SMRAM_FIELD_AMD_K_RESERVED_5, /* 11C */ - SMRAM_FIELD_AMD_K_RESERVED_6, /* 118 */ - SMRAM_FIELD_AMD_K_CR2, /* 114 */ - SMRAM_FIELD_AMD_K_CR4, /* 110 */ - SMRAM_FIELD_AMD_K_IO_RESTART_ESI, /* 10C */ - SMRAM_FIELD_AMD_K_IO_RESTART_ECX, /* 108 */ - SMRAM_FIELD_AMD_K_IO_RESTART_EDI, /* 104 */ - SMRAM_FIELD_AMD_K_AUTOHALT_RESTART, /* 100 */ - SMRAM_FIELD_AMD_K_SMM_REVISION_ID, /* 0FC */ - SMRAM_FIELD_AMD_K_SMBASE_OFFSET, /* 0F8 */ + SMRAM_FIELD_AMD_K_CR0 = 0, /* 1FC */ + SMRAM_FIELD_AMD_K_CR3, /* 1F8 */ + SMRAM_FIELD_AMD_K_EFLAGS, /* 1F4 */ + SMRAM_FIELD_AMD_K_EIP, /* 1F0 */ + SMRAM_FIELD_AMD_K_EDI, /* 1EC */ + SMRAM_FIELD_AMD_K_ESI, /* 1E8 */ + SMRAM_FIELD_AMD_K_EBP, /* 1E4 */ + SMRAM_FIELD_AMD_K_ESP, /* 1E0 */ + SMRAM_FIELD_AMD_K_EBX, /* 1DC */ + SMRAM_FIELD_AMD_K_EDX, /* 1D8 */ + SMRAM_FIELD_AMD_K_ECX, /* 1D4 */ + SMRAM_FIELD_AMD_K_EAX, /* 1D0 */ + SMRAM_FIELD_AMD_K_DR6, /* 1CC */ + SMRAM_FIELD_AMD_K_DR7, /* 1C8 */ + SMRAM_FIELD_AMD_K_TR_SELECTOR, /* 1C4 */ + SMRAM_FIELD_AMD_K_LDTR_SELECTOR, /* 1C0 */ + SMRAM_FIELD_AMD_K_GS_SELECTOR, /* 1BC */ + SMRAM_FIELD_AMD_K_FS_SELECTOR, /* 1B8 */ + SMRAM_FIELD_AMD_K_DS_SELECTOR, /* 1B4 */ + SMRAM_FIELD_AMD_K_SS_SELECTOR, /* 1B0 */ + SMRAM_FIELD_AMD_K_CS_SELECTOR, /* 1AC */ + SMRAM_FIELD_AMD_K_ES_SELECTOR, /* 1A8 */ + SMRAM_FIELD_AMD_K_IO_RESTART_DWORD, /* 1A4 */ + SMRAM_FIELD_AMD_K_RESERVED_1, /* 1A0 */ + SMRAM_FIELD_AMD_K_IO_RESTART_EIP, /* 19C */ + SMRAM_FIELD_AMD_K_RESERVED_2, /* 198 */ + SMRAM_FIELD_AMD_K_RESERVED_3, /* 194 */ + SMRAM_FIELD_AMD_K_IDTR_BASE, /* 190 */ + SMRAM_FIELD_AMD_K_IDTR_LIMIT, /* 18C */ + SMRAM_FIELD_AMD_K_GDTR_BASE, /* 188 */ + SMRAM_FIELD_AMD_K_GDTR_LIMIT, /* 184 */ + SMRAM_FIELD_AMD_K_TR_ACCESS, /* 180 */ + SMRAM_FIELD_AMD_K_TR_BASE, /* 17C */ + SMRAM_FIELD_AMD_K_TR_LIMIT, /* 178 */ + SMRAM_FIELD_AMD_K_LDTR_ACCESS, /* 174 - reserved on K6 */ + SMRAM_FIELD_AMD_K_LDTR_BASE, /* 170 */ + SMRAM_FIELD_AMD_K_LDTR_LIMIT, /* 16C */ + SMRAM_FIELD_AMD_K_GS_ACCESS, /* 168 */ + SMRAM_FIELD_AMD_K_GS_BASE, /* 164 */ + SMRAM_FIELD_AMD_K_GS_LIMIT, /* 160 */ + SMRAM_FIELD_AMD_K_FS_ACCESS, /* 15C */ + SMRAM_FIELD_AMD_K_FS_BASE, /* 158 */ + SMRAM_FIELD_AMD_K_FS_LIMIT, /* 154 */ + SMRAM_FIELD_AMD_K_DS_ACCESS, /* 150 */ + SMRAM_FIELD_AMD_K_DS_BASE, /* 14C */ + SMRAM_FIELD_AMD_K_DS_LIMIT, /* 148 */ + SMRAM_FIELD_AMD_K_SS_ACCESS, /* 144 */ + SMRAM_FIELD_AMD_K_SS_BASE, /* 140 */ + SMRAM_FIELD_AMD_K_SS_LIMIT, /* 13C */ + SMRAM_FIELD_AMD_K_CS_ACCESS, /* 138 */ + SMRAM_FIELD_AMD_K_CS_BASE, /* 134 */ + SMRAM_FIELD_AMD_K_CS_LIMIT, /* 130 */ + SMRAM_FIELD_AMD_K_ES_ACCESS, /* 12C */ + SMRAM_FIELD_AMD_K_ES_BASE, /* 128 */ + SMRAM_FIELD_AMD_K_ES_LIMIT, /* 124 */ + SMRAM_FIELD_AMD_K_RESERVED_4, /* 120 */ + SMRAM_FIELD_AMD_K_RESERVED_5, /* 11C */ + SMRAM_FIELD_AMD_K_RESERVED_6, /* 118 */ + SMRAM_FIELD_AMD_K_CR2, /* 114 */ + SMRAM_FIELD_AMD_K_CR4, /* 110 */ + SMRAM_FIELD_AMD_K_IO_RESTART_ESI, /* 10C */ + SMRAM_FIELD_AMD_K_IO_RESTART_ECX, /* 108 */ + SMRAM_FIELD_AMD_K_IO_RESTART_EDI, /* 104 */ + SMRAM_FIELD_AMD_K_AUTOHALT_RESTART, /* 100 */ + SMRAM_FIELD_AMD_K_SMM_REVISION_ID, /* 0FC */ + SMRAM_FIELD_AMD_K_SMBASE_OFFSET, /* 0F8 */ SMRAM_FIELD_AMD_K_LAST }; - #ifdef ENABLE_386_COMMON_LOG int x386_common_do_log = ENABLE_386_COMMON_LOG; - void x386_common_log(const char *fmt, ...) { va_list ap; if (x386_common_do_log) { - va_start(ap, fmt); - pclog_ex(fmt, ap); - va_end(ap); + va_start(ap, fmt); + pclog_ex(fmt, ap); + va_end(ap); } } #else -#define x386_common_log(fmt, ...) +# define x386_common_log(fmt, ...) #endif +/*Prefetch emulation is a fairly simplistic model: + - All instruction bytes must be fetched before it starts. + - Cycles used for non-instruction memory accesses are counted and subtracted + from the total cycles taken + - Any remaining cycles are used to refill the prefetch queue. + + Note that this is only used for 286 / 386 systems. It is disabled when the + internal cache on 486+ CPUs is enabled. +*/ +static int prefetch_bytes = 0; + +void +prefetch_run(int instr_cycles, int bytes, int modrm, int reads, int reads_l, int writes, int writes_l, int ea32) +{ + int mem_cycles = reads * cpu_cycles_read + reads_l * cpu_cycles_read_l + writes * cpu_cycles_write + writes_l * cpu_cycles_write_l; + + if (instr_cycles < mem_cycles) + instr_cycles = mem_cycles; + + prefetch_bytes -= prefetch_prefixes; + prefetch_bytes -= bytes; + if (modrm != -1) { + if (ea32) { + if ((modrm & 7) == 4) { + if ((modrm & 0x700) == 0x500) + prefetch_bytes -= 5; + else if ((modrm & 0xc0) == 0x40) + prefetch_bytes -= 2; + else if ((modrm & 0xc0) == 0x80) + prefetch_bytes -= 5; + } else { + if ((modrm & 0xc7) == 0x05) + prefetch_bytes -= 4; + else if ((modrm & 0xc0) == 0x40) + prefetch_bytes--; + else if ((modrm & 0xc0) == 0x80) + prefetch_bytes -= 4; + } + } else { + if ((modrm & 0xc7) == 0x06) + prefetch_bytes -= 2; + else if ((modrm & 0xc0) != 0xc0) + prefetch_bytes -= ((modrm & 0xc0) >> 6); + } + } + + /* Fill up prefetch queue */ + while (prefetch_bytes < 0) { + prefetch_bytes += cpu_prefetch_width; + cycles -= cpu_prefetch_cycles; + } + + /* Subtract cycles used for memory access by instruction */ + instr_cycles -= mem_cycles; + + while (instr_cycles >= cpu_prefetch_cycles) { + prefetch_bytes += cpu_prefetch_width; + instr_cycles -= cpu_prefetch_cycles; + } + + prefetch_prefixes = 0; + if (prefetch_bytes > 16) + prefetch_bytes = 16; +} + +void +prefetch_flush(void) +{ + prefetch_bytes = 0; +} static __inline void set_stack32(int s) { - if ((cr0 & 1) && ! (cpu_state.eflags & VM_FLAG)) - stack32 = s; + if ((cr0 & 1) && !(cpu_state.eflags & VM_FLAG)) + stack32 = s; else - stack32 = 0; + stack32 = 0; if (stack32) - cpu_cur_status |= CPU_STATUS_STACK32; + cpu_cur_status |= CPU_STATUS_STACK32; else - cpu_cur_status &= ~CPU_STATUS_STACK32; + cpu_cur_status &= ~CPU_STATUS_STACK32; } - static __inline void set_use32(int u) { - if ((cr0 & 1) && ! (cpu_state.eflags & VM_FLAG)) - use32 = u ? 0x300 : 0; + if ((cr0 & 1) && !(cpu_state.eflags & VM_FLAG)) + use32 = u ? 0x300 : 0; else - use32 = 0; + use32 = 0; if (use32) - cpu_cur_status |= CPU_STATUS_USE32; + cpu_cur_status |= CPU_STATUS_USE32; else - cpu_cur_status &= ~CPU_STATUS_USE32; + cpu_cur_status &= ~CPU_STATUS_USE32; } - static void smm_seg_load(x86seg *s) { if (!is386) - s->base &= 0x00ffffff; + s->base &= 0x00ffffff; if ((s->access & 0x18) != 0x10 || !(s->access & (1 << 2))) { - /* Expand down. */ - s->limit_high = s->limit; - s->limit_low = 0; + /* Expand down. */ + s->limit_high = s->limit; + s->limit_low = 0; } else { - s->limit_high = (s->ar_high & 0x40) ? 0xffffffff : 0xffff; - s->limit_low = s->limit + 1; + s->limit_high = (s->ar_high & 0x40) ? 0xffffffff : 0xffff; + s->limit_low = s->limit + 1; } if ((cr0 & 1) && !(cpu_state.eflags & VM_FLAG)) - s->checked = s->seg ? 1 : 0; + s->checked = s->seg ? 1 : 0; else - s->checked = 1; + s->checked = 1; if (s == &cpu_state.seg_cs) - set_use32(s->ar_high & 0x40); + set_use32(s->ar_high & 0x40); if (s == &cpu_state.seg_ds) { - if (s->base == 0 && s->limit_low == 0 && s->limit_high == 0xffffffff) - cpu_cur_status &= ~CPU_STATUS_NOTFLATDS; - else - cpu_cur_status |= CPU_STATUS_NOTFLATDS; + if (s->base == 0 && s->limit_low == 0 && s->limit_high == 0xffffffff) + cpu_cur_status &= ~CPU_STATUS_NOTFLATDS; + else + cpu_cur_status |= CPU_STATUS_NOTFLATDS; } if (s == &cpu_state.seg_ss) { - if (s->base == 0 && s->limit_low == 0 && s->limit_high == 0xffffffff) - cpu_cur_status &= ~CPU_STATUS_NOTFLATSS; - else - cpu_cur_status |= CPU_STATUS_NOTFLATSS; - set_stack32((s->ar_high & 0x40) ? 1 : 0); + if (s->base == 0 && s->limit_low == 0 && s->limit_high == 0xffffffff) + cpu_cur_status &= ~CPU_STATUS_NOTFLATSS; + else + cpu_cur_status |= CPU_STATUS_NOTFLATSS; + set_stack32((s->ar_high & 0x40) ? 1 : 0); } } - static void smram_save_state_p5(uint32_t *saved_state, int in_hlt) { - int n = 0; - saved_state[SMRAM_FIELD_P5_SMM_REVISION_ID] = SMM_REVISION_ID; - saved_state[SMRAM_FIELD_P5_SMBASE_OFFSET] = smbase; + saved_state[SMRAM_FIELD_P5_SMBASE_OFFSET] = smbase; - for (n = 0; n < 8; n++) - saved_state[SMRAM_FIELD_P5_EAX - n] = cpu_state.regs[n].l; + for (uint8_t n = 0; n < 8; n++) + saved_state[SMRAM_FIELD_P5_EAX - n] = cpu_state.regs[n].l; if (in_hlt) - saved_state[SMRAM_FIELD_P5_AUTOHALT_RESTART] = 1; + saved_state[SMRAM_FIELD_P5_AUTOHALT_RESTART] = 1; else - saved_state[SMRAM_FIELD_P5_AUTOHALT_RESTART] = 0; + saved_state[SMRAM_FIELD_P5_AUTOHALT_RESTART] = 0; saved_state[SMRAM_FIELD_P5_EIP] = cpu_state.pc; @@ -423,403 +539,385 @@ smram_save_state_p5(uint32_t *saved_state, int in_hlt) /* TR */ saved_state[SMRAM_FIELD_P5_TR_SELECTOR] = tr.seg; - saved_state[SMRAM_FIELD_P5_TR_BASE] = tr.base; - saved_state[SMRAM_FIELD_P5_TR_LIMIT] = tr.limit; - saved_state[SMRAM_FIELD_P5_TR_ACCESS] = (tr.ar_high << 16) | (tr.access << 8); + saved_state[SMRAM_FIELD_P5_TR_BASE] = tr.base; + saved_state[SMRAM_FIELD_P5_TR_LIMIT] = tr.limit; + saved_state[SMRAM_FIELD_P5_TR_ACCESS] = (tr.ar_high << 16) | (tr.access << 8); /* LDTR */ saved_state[SMRAM_FIELD_P5_LDTR_SELECTOR] = ldt.seg; - saved_state[SMRAM_FIELD_P5_LDTR_BASE] = ldt.base; - saved_state[SMRAM_FIELD_P5_LDTR_LIMIT] = ldt.limit; - saved_state[SMRAM_FIELD_P5_LDTR_ACCESS] = (ldt.ar_high << 16) | (ldt.access << 8); + saved_state[SMRAM_FIELD_P5_LDTR_BASE] = ldt.base; + saved_state[SMRAM_FIELD_P5_LDTR_LIMIT] = ldt.limit; + saved_state[SMRAM_FIELD_P5_LDTR_ACCESS] = (ldt.ar_high << 16) | (ldt.access << 8); /* IDTR */ - saved_state[SMRAM_FIELD_P5_IDTR_BASE] = idt.base; - saved_state[SMRAM_FIELD_P5_IDTR_LIMIT] = idt.limit; + saved_state[SMRAM_FIELD_P5_IDTR_BASE] = idt.base; + saved_state[SMRAM_FIELD_P5_IDTR_LIMIT] = idt.limit; saved_state[SMRAM_FIELD_P5_IDTR_ACCESS] = (idt.ar_high << 16) | (idt.access << 8); /* GDTR */ - saved_state[SMRAM_FIELD_P5_GDTR_BASE] = gdt.base; - saved_state[SMRAM_FIELD_P5_GDTR_LIMIT] = gdt.limit; + saved_state[SMRAM_FIELD_P5_GDTR_BASE] = gdt.base; + saved_state[SMRAM_FIELD_P5_GDTR_LIMIT] = gdt.limit; saved_state[SMRAM_FIELD_P5_GDTR_ACCESS] = (gdt.ar_high << 16) | (gdt.access << 8); /* ES */ saved_state[SMRAM_FIELD_P5_ES_SELECTOR] = cpu_state.seg_es.seg; - saved_state[SMRAM_FIELD_P5_ES_BASE] = cpu_state.seg_es.base; - saved_state[SMRAM_FIELD_P5_ES_LIMIT] = cpu_state.seg_es.limit; - saved_state[SMRAM_FIELD_P5_ES_ACCESS] = (cpu_state.seg_es.ar_high << 16) | (cpu_state.seg_es.access << 8); + saved_state[SMRAM_FIELD_P5_ES_BASE] = cpu_state.seg_es.base; + saved_state[SMRAM_FIELD_P5_ES_LIMIT] = cpu_state.seg_es.limit; + saved_state[SMRAM_FIELD_P5_ES_ACCESS] = (cpu_state.seg_es.ar_high << 16) | (cpu_state.seg_es.access << 8); /* CS */ saved_state[SMRAM_FIELD_P5_CS_SELECTOR] = cpu_state.seg_cs.seg; - saved_state[SMRAM_FIELD_P5_CS_BASE] = cpu_state.seg_cs.base; - saved_state[SMRAM_FIELD_P5_CS_LIMIT] = cpu_state.seg_cs.limit; - saved_state[SMRAM_FIELD_P5_CS_ACCESS] = (cpu_state.seg_cs.ar_high << 16) | (cpu_state.seg_cs.access << 8); + saved_state[SMRAM_FIELD_P5_CS_BASE] = cpu_state.seg_cs.base; + saved_state[SMRAM_FIELD_P5_CS_LIMIT] = cpu_state.seg_cs.limit; + saved_state[SMRAM_FIELD_P5_CS_ACCESS] = (cpu_state.seg_cs.ar_high << 16) | (cpu_state.seg_cs.access << 8); /* DS */ saved_state[SMRAM_FIELD_P5_DS_SELECTOR] = cpu_state.seg_ds.seg; - saved_state[SMRAM_FIELD_P5_DS_BASE] = cpu_state.seg_ds.base; - saved_state[SMRAM_FIELD_P5_DS_LIMIT] = cpu_state.seg_ds.limit; - saved_state[SMRAM_FIELD_P5_DS_ACCESS] = (cpu_state.seg_ds.ar_high << 16) | (cpu_state.seg_ds.access << 8); + saved_state[SMRAM_FIELD_P5_DS_BASE] = cpu_state.seg_ds.base; + saved_state[SMRAM_FIELD_P5_DS_LIMIT] = cpu_state.seg_ds.limit; + saved_state[SMRAM_FIELD_P5_DS_ACCESS] = (cpu_state.seg_ds.ar_high << 16) | (cpu_state.seg_ds.access << 8); /* SS */ saved_state[SMRAM_FIELD_P5_SS_SELECTOR] = cpu_state.seg_ss.seg; - saved_state[SMRAM_FIELD_P5_SS_BASE] = cpu_state.seg_ss.base; - saved_state[SMRAM_FIELD_P5_SS_LIMIT] = cpu_state.seg_ss.limit; - saved_state[SMRAM_FIELD_P5_SS_ACCESS] = (cpu_state.seg_ss.ar_high << 16) | (cpu_state.seg_ss.access << 8); + saved_state[SMRAM_FIELD_P5_SS_BASE] = cpu_state.seg_ss.base; + saved_state[SMRAM_FIELD_P5_SS_LIMIT] = cpu_state.seg_ss.limit; + saved_state[SMRAM_FIELD_P5_SS_ACCESS] = (cpu_state.seg_ss.ar_high << 16) | (cpu_state.seg_ss.access << 8); /* FS */ saved_state[SMRAM_FIELD_P5_FS_SELECTOR] = cpu_state.seg_fs.seg; - saved_state[SMRAM_FIELD_P5_FS_BASE] = cpu_state.seg_fs.base; - saved_state[SMRAM_FIELD_P5_FS_LIMIT] = cpu_state.seg_fs.limit; - saved_state[SMRAM_FIELD_P5_FS_ACCESS] = (cpu_state.seg_fs.ar_high << 16) | (cpu_state.seg_fs.access << 8); + saved_state[SMRAM_FIELD_P5_FS_BASE] = cpu_state.seg_fs.base; + saved_state[SMRAM_FIELD_P5_FS_LIMIT] = cpu_state.seg_fs.limit; + saved_state[SMRAM_FIELD_P5_FS_ACCESS] = (cpu_state.seg_fs.ar_high << 16) | (cpu_state.seg_fs.access << 8); /* GS */ saved_state[SMRAM_FIELD_P5_GS_SELECTOR] = cpu_state.seg_gs.seg; - saved_state[SMRAM_FIELD_P5_GS_BASE] = cpu_state.seg_gs.base; - saved_state[SMRAM_FIELD_P5_GS_LIMIT] = cpu_state.seg_gs.limit; - saved_state[SMRAM_FIELD_P5_GS_ACCESS] = (cpu_state.seg_gs.ar_high << 16) | (cpu_state.seg_gs.access << 8); + saved_state[SMRAM_FIELD_P5_GS_BASE] = cpu_state.seg_gs.base; + saved_state[SMRAM_FIELD_P5_GS_LIMIT] = cpu_state.seg_gs.limit; + saved_state[SMRAM_FIELD_P5_GS_ACCESS] = (cpu_state.seg_gs.ar_high << 16) | (cpu_state.seg_gs.access << 8); /* Am486/5x86 stuff */ if (!is_pentium) { - saved_state[SMRAM_FIELD_AM486_CR2] = cr2; - saved_state[SMRAM_FIELD_AM486_DR0] = dr[0]; - saved_state[SMRAM_FIELD_AM486_DR1] = dr[1]; - saved_state[SMRAM_FIELD_AM486_DR2] = dr[2]; - saved_state[SMRAM_FIELD_AM486_DR3] = dr[3]; + saved_state[SMRAM_FIELD_AM486_CR2] = cr2; + saved_state[SMRAM_FIELD_AM486_DR0] = dr[0]; + saved_state[SMRAM_FIELD_AM486_DR1] = dr[1]; + saved_state[SMRAM_FIELD_AM486_DR2] = dr[2]; + saved_state[SMRAM_FIELD_AM486_DR3] = dr[3]; } } - static void smram_restore_state_p5(uint32_t *saved_state) { - int n = 0; - - for (n = 0; n < 8; n++) - cpu_state.regs[n].l = saved_state[SMRAM_FIELD_P5_EAX - n]; + for (uint8_t n = 0; n < 8; n++) + cpu_state.regs[n].l = saved_state[SMRAM_FIELD_P5_EAX - n]; if (saved_state[SMRAM_FIELD_P5_AUTOHALT_RESTART] & 0xffff) - cpu_state.pc = saved_state[SMRAM_FIELD_P5_EIP] - 1; + cpu_state.pc = saved_state[SMRAM_FIELD_P5_EIP] - 1; else - cpu_state.pc = saved_state[SMRAM_FIELD_P5_EIP]; + cpu_state.pc = saved_state[SMRAM_FIELD_P5_EIP]; cpu_state.eflags = saved_state[SMRAM_FIELD_P5_EFLAGS] >> 16; - cpu_state.flags = saved_state[SMRAM_FIELD_P5_EFLAGS] & 0xffff; + cpu_state.flags = saved_state[SMRAM_FIELD_P5_EFLAGS] & 0xffff; - cr0 = saved_state[SMRAM_FIELD_P5_CR0]; - cr3 = saved_state[SMRAM_FIELD_P5_CR3]; - cr4 = saved_state[SMRAM_FIELD_P5_CR4]; + cr0 = saved_state[SMRAM_FIELD_P5_CR0]; + cr3 = saved_state[SMRAM_FIELD_P5_CR3]; + cr4 = saved_state[SMRAM_FIELD_P5_CR4]; dr[6] = saved_state[SMRAM_FIELD_P5_DR6]; dr[7] = saved_state[SMRAM_FIELD_P5_DR7]; /* TR */ - tr.seg = saved_state[SMRAM_FIELD_P5_TR_SELECTOR]; - tr.base = saved_state[SMRAM_FIELD_P5_TR_BASE]; - tr.limit = saved_state[SMRAM_FIELD_P5_TR_LIMIT]; - tr.access = (saved_state[SMRAM_FIELD_P5_TR_ACCESS] >> 8) & 0xff; + tr.seg = saved_state[SMRAM_FIELD_P5_TR_SELECTOR]; + tr.base = saved_state[SMRAM_FIELD_P5_TR_BASE]; + tr.limit = saved_state[SMRAM_FIELD_P5_TR_LIMIT]; + tr.access = (saved_state[SMRAM_FIELD_P5_TR_ACCESS] >> 8) & 0xff; tr.ar_high = (saved_state[SMRAM_FIELD_P5_TR_ACCESS] >> 16) & 0xff; smm_seg_load(&tr); /* LDTR */ - ldt.seg = saved_state[SMRAM_FIELD_P5_LDTR_SELECTOR]; - ldt.base = saved_state[SMRAM_FIELD_P5_LDTR_BASE]; - ldt.limit = saved_state[SMRAM_FIELD_P5_LDTR_LIMIT]; - ldt.access = (saved_state[SMRAM_FIELD_P5_LDTR_ACCESS] >> 8) & 0xff; + ldt.seg = saved_state[SMRAM_FIELD_P5_LDTR_SELECTOR]; + ldt.base = saved_state[SMRAM_FIELD_P5_LDTR_BASE]; + ldt.limit = saved_state[SMRAM_FIELD_P5_LDTR_LIMIT]; + ldt.access = (saved_state[SMRAM_FIELD_P5_LDTR_ACCESS] >> 8) & 0xff; ldt.ar_high = (saved_state[SMRAM_FIELD_P5_LDTR_ACCESS] >> 16) & 0xff; smm_seg_load(&ldt); /* IDTR */ - idt.base = saved_state[SMRAM_FIELD_P5_IDTR_BASE]; - idt.limit = saved_state[SMRAM_FIELD_P5_IDTR_LIMIT]; - idt.access = (saved_state[SMRAM_FIELD_P5_IDTR_ACCESS] >> 8) & 0xff; + idt.base = saved_state[SMRAM_FIELD_P5_IDTR_BASE]; + idt.limit = saved_state[SMRAM_FIELD_P5_IDTR_LIMIT]; + idt.access = (saved_state[SMRAM_FIELD_P5_IDTR_ACCESS] >> 8) & 0xff; idt.ar_high = (saved_state[SMRAM_FIELD_P5_IDTR_ACCESS] >> 16) & 0xff; /* GDTR */ - gdt.base = saved_state[SMRAM_FIELD_P5_GDTR_BASE]; - gdt.limit = saved_state[SMRAM_FIELD_P5_GDTR_LIMIT]; - gdt.access = (saved_state[SMRAM_FIELD_P5_GDTR_ACCESS] >> 8) & 0xff; + gdt.base = saved_state[SMRAM_FIELD_P5_GDTR_BASE]; + gdt.limit = saved_state[SMRAM_FIELD_P5_GDTR_LIMIT]; + gdt.access = (saved_state[SMRAM_FIELD_P5_GDTR_ACCESS] >> 8) & 0xff; gdt.ar_high = (saved_state[SMRAM_FIELD_P5_GDTR_ACCESS] >> 16) & 0xff; /* ES */ - cpu_state.seg_es.seg = saved_state[SMRAM_FIELD_P5_ES_SELECTOR]; - cpu_state.seg_es.base = saved_state[SMRAM_FIELD_P5_ES_BASE]; - cpu_state.seg_es.limit = saved_state[SMRAM_FIELD_P5_ES_LIMIT]; - cpu_state.seg_es.access = (saved_state[SMRAM_FIELD_P5_ES_ACCESS] >> 8) & 0xff; + cpu_state.seg_es.seg = saved_state[SMRAM_FIELD_P5_ES_SELECTOR]; + cpu_state.seg_es.base = saved_state[SMRAM_FIELD_P5_ES_BASE]; + cpu_state.seg_es.limit = saved_state[SMRAM_FIELD_P5_ES_LIMIT]; + cpu_state.seg_es.access = (saved_state[SMRAM_FIELD_P5_ES_ACCESS] >> 8) & 0xff; cpu_state.seg_es.ar_high = (saved_state[SMRAM_FIELD_P5_ES_ACCESS] >> 16) & 0xff; smm_seg_load(&cpu_state.seg_es); /* CS */ - cpu_state.seg_cs.seg = saved_state[SMRAM_FIELD_P5_CS_SELECTOR]; - cpu_state.seg_cs.base = saved_state[SMRAM_FIELD_P5_CS_BASE]; - cpu_state.seg_cs.limit = saved_state[SMRAM_FIELD_P5_CS_LIMIT]; - cpu_state.seg_cs.access = (saved_state[SMRAM_FIELD_P5_CS_ACCESS] >> 8) & 0xff; + cpu_state.seg_cs.seg = saved_state[SMRAM_FIELD_P5_CS_SELECTOR]; + cpu_state.seg_cs.base = saved_state[SMRAM_FIELD_P5_CS_BASE]; + cpu_state.seg_cs.limit = saved_state[SMRAM_FIELD_P5_CS_LIMIT]; + cpu_state.seg_cs.access = (saved_state[SMRAM_FIELD_P5_CS_ACCESS] >> 8) & 0xff; cpu_state.seg_cs.ar_high = (saved_state[SMRAM_FIELD_P5_CS_ACCESS] >> 16) & 0xff; smm_seg_load(&cpu_state.seg_cs); /* DS */ - cpu_state.seg_ds.seg = saved_state[SMRAM_FIELD_P5_DS_SELECTOR]; - cpu_state.seg_ds.base = saved_state[SMRAM_FIELD_P5_DS_BASE]; - cpu_state.seg_ds.limit = saved_state[SMRAM_FIELD_P5_DS_LIMIT]; - cpu_state.seg_ds.access = (saved_state[SMRAM_FIELD_P5_DS_ACCESS] >> 8) & 0xff; + cpu_state.seg_ds.seg = saved_state[SMRAM_FIELD_P5_DS_SELECTOR]; + cpu_state.seg_ds.base = saved_state[SMRAM_FIELD_P5_DS_BASE]; + cpu_state.seg_ds.limit = saved_state[SMRAM_FIELD_P5_DS_LIMIT]; + cpu_state.seg_ds.access = (saved_state[SMRAM_FIELD_P5_DS_ACCESS] >> 8) & 0xff; cpu_state.seg_ds.ar_high = (saved_state[SMRAM_FIELD_P5_DS_ACCESS] >> 16) & 0xff; smm_seg_load(&cpu_state.seg_ds); /* SS */ - cpu_state.seg_ss.seg = saved_state[SMRAM_FIELD_P5_SS_SELECTOR]; - cpu_state.seg_ss.base = saved_state[SMRAM_FIELD_P5_SS_BASE]; - cpu_state.seg_ss.limit = saved_state[SMRAM_FIELD_P5_SS_LIMIT]; + cpu_state.seg_ss.seg = saved_state[SMRAM_FIELD_P5_SS_SELECTOR]; + cpu_state.seg_ss.base = saved_state[SMRAM_FIELD_P5_SS_BASE]; + cpu_state.seg_ss.limit = saved_state[SMRAM_FIELD_P5_SS_LIMIT]; cpu_state.seg_ss.access = (saved_state[SMRAM_FIELD_P5_SS_ACCESS] >> 8) & 0xff; /* The actual CPL (DPL of CS) is overwritten with DPL of SS. */ - cpu_state.seg_cs.access = (cpu_state.seg_cs.access & ~0x60) | (cpu_state.seg_ss.access & 0x60); + cpu_state.seg_cs.access = (cpu_state.seg_cs.access & ~0x60) | (cpu_state.seg_ss.access & 0x60); cpu_state.seg_ss.ar_high = (saved_state[SMRAM_FIELD_P5_SS_ACCESS] >> 16) & 0xff; smm_seg_load(&cpu_state.seg_ss); /* FS */ - cpu_state.seg_fs.seg = saved_state[SMRAM_FIELD_P5_FS_SELECTOR]; - cpu_state.seg_fs.base = saved_state[SMRAM_FIELD_P5_FS_BASE]; - cpu_state.seg_fs.limit = saved_state[SMRAM_FIELD_P5_FS_LIMIT]; - cpu_state.seg_fs.access = (saved_state[SMRAM_FIELD_P5_FS_ACCESS] >> 8) & 0xff; + cpu_state.seg_fs.seg = saved_state[SMRAM_FIELD_P5_FS_SELECTOR]; + cpu_state.seg_fs.base = saved_state[SMRAM_FIELD_P5_FS_BASE]; + cpu_state.seg_fs.limit = saved_state[SMRAM_FIELD_P5_FS_LIMIT]; + cpu_state.seg_fs.access = (saved_state[SMRAM_FIELD_P5_FS_ACCESS] >> 8) & 0xff; cpu_state.seg_fs.ar_high = (saved_state[SMRAM_FIELD_P5_FS_ACCESS] >> 16) & 0xff; smm_seg_load(&cpu_state.seg_fs); /* GS */ - cpu_state.seg_gs.seg = saved_state[SMRAM_FIELD_P5_GS_SELECTOR]; - cpu_state.seg_gs.base = saved_state[SMRAM_FIELD_P5_GS_BASE]; - cpu_state.seg_gs.limit = saved_state[SMRAM_FIELD_P5_GS_LIMIT]; - cpu_state.seg_gs.access = (saved_state[SMRAM_FIELD_P5_GS_ACCESS] >> 8) & 0xff; + cpu_state.seg_gs.seg = saved_state[SMRAM_FIELD_P5_GS_SELECTOR]; + cpu_state.seg_gs.base = saved_state[SMRAM_FIELD_P5_GS_BASE]; + cpu_state.seg_gs.limit = saved_state[SMRAM_FIELD_P5_GS_LIMIT]; + cpu_state.seg_gs.access = (saved_state[SMRAM_FIELD_P5_GS_ACCESS] >> 8) & 0xff; cpu_state.seg_gs.ar_high = (saved_state[SMRAM_FIELD_P5_GS_ACCESS] >> 16) & 0xff; smm_seg_load(&cpu_state.seg_gs); if (SMM_REVISION_ID & SMM_SMBASE_RELOCATION) - smbase = saved_state[SMRAM_FIELD_P5_SMBASE_OFFSET]; + smbase = saved_state[SMRAM_FIELD_P5_SMBASE_OFFSET]; /* Am486/5x86 stuff */ if (!is_pentium) { - cr2 = saved_state[SMRAM_FIELD_AM486_CR2]; - dr[0] = saved_state[SMRAM_FIELD_AM486_DR0]; - dr[1] = saved_state[SMRAM_FIELD_AM486_DR1]; - dr[2] = saved_state[SMRAM_FIELD_AM486_DR2]; - dr[3] = saved_state[SMRAM_FIELD_AM486_DR3]; + cr2 = saved_state[SMRAM_FIELD_AM486_CR2]; + dr[0] = saved_state[SMRAM_FIELD_AM486_DR0]; + dr[1] = saved_state[SMRAM_FIELD_AM486_DR1]; + dr[2] = saved_state[SMRAM_FIELD_AM486_DR2]; + dr[3] = saved_state[SMRAM_FIELD_AM486_DR3]; } } - static void smram_save_state_p6(uint32_t *saved_state, int in_hlt) { - int n = 0; - saved_state[SMRAM_FIELD_P6_SMM_REVISION_ID] = SMM_REVISION_ID; - saved_state[SMRAM_FIELD_P6_SMBASE_OFFSET] = smbase; + saved_state[SMRAM_FIELD_P6_SMBASE_OFFSET] = smbase; - for (n = 0; n < 8; n++) - saved_state[SMRAM_FIELD_P6_EAX - n] = cpu_state.regs[n].l; + for (uint8_t n = 0; n < 8; n++) + saved_state[SMRAM_FIELD_P6_EAX - n] = cpu_state.regs[n].l; if (in_hlt) - saved_state[SMRAM_FIELD_P6_AUTOHALT_RESTART] = 1; + saved_state[SMRAM_FIELD_P6_AUTOHALT_RESTART] = 1; else - saved_state[SMRAM_FIELD_P6_AUTOHALT_RESTART] = 0; + saved_state[SMRAM_FIELD_P6_AUTOHALT_RESTART] = 0; saved_state[SMRAM_FIELD_P6_EIP] = cpu_state.pc; saved_state[SMRAM_FIELD_P6_EFLAGS] = (cpu_state.eflags << 16) | (cpu_state.flags); - saved_state[SMRAM_FIELD_P6_CR0] = cr0; - saved_state[SMRAM_FIELD_P6_CR3] = cr3; - saved_state[SMRAM_FIELD_P6_CR4] = cr4; - saved_state[SMRAM_FIELD_P6_DR6] = dr[6]; - saved_state[SMRAM_FIELD_P6_DR7] = dr[7]; - saved_state[SMRAM_FIELD_P6_CPL] = CPL; + saved_state[SMRAM_FIELD_P6_CR0] = cr0; + saved_state[SMRAM_FIELD_P6_CR3] = cr3; + saved_state[SMRAM_FIELD_P6_CR4] = cr4; + saved_state[SMRAM_FIELD_P6_DR6] = dr[6]; + saved_state[SMRAM_FIELD_P6_DR7] = dr[7]; + saved_state[SMRAM_FIELD_P6_CPL] = CPL; saved_state[SMRAM_FIELD_P6_A20M] = !mem_a20_state; /* TR */ - saved_state[SMRAM_FIELD_P6_TR_SELECTOR] = tr.seg; - saved_state[SMRAM_FIELD_P6_TR_BASE] = tr.base; - saved_state[SMRAM_FIELD_P6_TR_LIMIT] = tr.limit; + saved_state[SMRAM_FIELD_P6_TR_SELECTOR] = tr.seg; + saved_state[SMRAM_FIELD_P6_TR_BASE] = tr.base; + saved_state[SMRAM_FIELD_P6_TR_LIMIT] = tr.limit; saved_state[SMRAM_FIELD_P6_TR_SELECTOR_AR] = (tr.ar_high << 24) | (tr.access << 16) | tr.seg; /* LDTR */ - saved_state[SMRAM_FIELD_P6_LDTR_SELECTOR] = ldt.seg; - saved_state[SMRAM_FIELD_P6_LDTR_BASE] = ldt.base; - saved_state[SMRAM_FIELD_P6_LDTR_LIMIT] = ldt.limit; + saved_state[SMRAM_FIELD_P6_LDTR_SELECTOR] = ldt.seg; + saved_state[SMRAM_FIELD_P6_LDTR_BASE] = ldt.base; + saved_state[SMRAM_FIELD_P6_LDTR_LIMIT] = ldt.limit; saved_state[SMRAM_FIELD_P6_LDTR_SELECTOR_AR] = (ldt.ar_high << 24) | (ldt.access << 16) | ldt.seg; /* IDTR */ - saved_state[SMRAM_FIELD_P6_IDTR_BASE] = idt.base; - saved_state[SMRAM_FIELD_P6_IDTR_LIMIT] = idt.limit; + saved_state[SMRAM_FIELD_P6_IDTR_BASE] = idt.base; + saved_state[SMRAM_FIELD_P6_IDTR_LIMIT] = idt.limit; saved_state[SMRAM_FIELD_P6_IDTR_SELECTOR_AR] = (idt.ar_high << 24) | (idt.access << 16) | idt.seg; /* GDTR */ - saved_state[SMRAM_FIELD_P6_GDTR_BASE] = gdt.base; - saved_state[SMRAM_FIELD_P6_GDTR_LIMIT] = gdt.limit; + saved_state[SMRAM_FIELD_P6_GDTR_BASE] = gdt.base; + saved_state[SMRAM_FIELD_P6_GDTR_LIMIT] = gdt.limit; saved_state[SMRAM_FIELD_P6_GDTR_SELECTOR_AR] = (gdt.ar_high << 24) | (gdt.access << 16) | gdt.seg; /* ES */ - saved_state[SMRAM_FIELD_P6_ES_SELECTOR] = cpu_state.seg_es.seg; - saved_state[SMRAM_FIELD_P6_ES_BASE] = cpu_state.seg_es.base; - saved_state[SMRAM_FIELD_P6_ES_LIMIT] = cpu_state.seg_es.limit; - saved_state[SMRAM_FIELD_P6_ES_SELECTOR_AR] = - (cpu_state.seg_es.ar_high << 24) | (cpu_state.seg_es.access << 16) | cpu_state.seg_es.seg; + saved_state[SMRAM_FIELD_P6_ES_SELECTOR] = cpu_state.seg_es.seg; + saved_state[SMRAM_FIELD_P6_ES_BASE] = cpu_state.seg_es.base; + saved_state[SMRAM_FIELD_P6_ES_LIMIT] = cpu_state.seg_es.limit; + saved_state[SMRAM_FIELD_P6_ES_SELECTOR_AR] = (cpu_state.seg_es.ar_high << 24) | (cpu_state.seg_es.access << 16) | cpu_state.seg_es.seg; /* CS */ - saved_state[SMRAM_FIELD_P6_CS_SELECTOR] = cpu_state.seg_cs.seg; - saved_state[SMRAM_FIELD_P6_CS_BASE] = cpu_state.seg_cs.base; - saved_state[SMRAM_FIELD_P6_CS_LIMIT] = cpu_state.seg_cs.limit; - saved_state[SMRAM_FIELD_P6_CS_SELECTOR_AR] = - (cpu_state.seg_cs.ar_high << 24) | (cpu_state.seg_cs.access << 16) | cpu_state.seg_cs.seg; + saved_state[SMRAM_FIELD_P6_CS_SELECTOR] = cpu_state.seg_cs.seg; + saved_state[SMRAM_FIELD_P6_CS_BASE] = cpu_state.seg_cs.base; + saved_state[SMRAM_FIELD_P6_CS_LIMIT] = cpu_state.seg_cs.limit; + saved_state[SMRAM_FIELD_P6_CS_SELECTOR_AR] = (cpu_state.seg_cs.ar_high << 24) | (cpu_state.seg_cs.access << 16) | cpu_state.seg_cs.seg; /* DS */ - saved_state[SMRAM_FIELD_P6_DS_SELECTOR] = cpu_state.seg_ds.seg; - saved_state[SMRAM_FIELD_P6_DS_BASE] = cpu_state.seg_ds.base; - saved_state[SMRAM_FIELD_P6_DS_LIMIT] = cpu_state.seg_ds.limit; - saved_state[SMRAM_FIELD_P6_DS_SELECTOR_AR] = - (cpu_state.seg_ds.ar_high << 24) | (cpu_state.seg_ds.access << 16) | cpu_state.seg_ds.seg; + saved_state[SMRAM_FIELD_P6_DS_SELECTOR] = cpu_state.seg_ds.seg; + saved_state[SMRAM_FIELD_P6_DS_BASE] = cpu_state.seg_ds.base; + saved_state[SMRAM_FIELD_P6_DS_LIMIT] = cpu_state.seg_ds.limit; + saved_state[SMRAM_FIELD_P6_DS_SELECTOR_AR] = (cpu_state.seg_ds.ar_high << 24) | (cpu_state.seg_ds.access << 16) | cpu_state.seg_ds.seg; /* SS */ - saved_state[SMRAM_FIELD_P6_SS_SELECTOR] = cpu_state.seg_ss.seg; - saved_state[SMRAM_FIELD_P6_SS_BASE] = cpu_state.seg_ss.base; - saved_state[SMRAM_FIELD_P6_SS_LIMIT] = cpu_state.seg_ss.limit; - saved_state[SMRAM_FIELD_P6_SS_SELECTOR_AR] = - (cpu_state.seg_ss.ar_high << 24) | (cpu_state.seg_ss.access << 16) | cpu_state.seg_ss.seg; + saved_state[SMRAM_FIELD_P6_SS_SELECTOR] = cpu_state.seg_ss.seg; + saved_state[SMRAM_FIELD_P6_SS_BASE] = cpu_state.seg_ss.base; + saved_state[SMRAM_FIELD_P6_SS_LIMIT] = cpu_state.seg_ss.limit; + saved_state[SMRAM_FIELD_P6_SS_SELECTOR_AR] = (cpu_state.seg_ss.ar_high << 24) | (cpu_state.seg_ss.access << 16) | cpu_state.seg_ss.seg; /* FS */ - saved_state[SMRAM_FIELD_P6_FS_SELECTOR] = cpu_state.seg_fs.seg; - saved_state[SMRAM_FIELD_P6_FS_BASE] = cpu_state.seg_fs.base; - saved_state[SMRAM_FIELD_P6_FS_LIMIT] = cpu_state.seg_fs.limit; - saved_state[SMRAM_FIELD_P6_FS_SELECTOR_AR] = - (cpu_state.seg_fs.ar_high << 24) | (cpu_state.seg_fs.access << 16) | cpu_state.seg_fs.seg; + saved_state[SMRAM_FIELD_P6_FS_SELECTOR] = cpu_state.seg_fs.seg; + saved_state[SMRAM_FIELD_P6_FS_BASE] = cpu_state.seg_fs.base; + saved_state[SMRAM_FIELD_P6_FS_LIMIT] = cpu_state.seg_fs.limit; + saved_state[SMRAM_FIELD_P6_FS_SELECTOR_AR] = (cpu_state.seg_fs.ar_high << 24) | (cpu_state.seg_fs.access << 16) | cpu_state.seg_fs.seg; /* GS */ - saved_state[SMRAM_FIELD_P6_GS_SELECTOR] = cpu_state.seg_gs.seg; - saved_state[SMRAM_FIELD_P6_GS_BASE] = cpu_state.seg_gs.base; - saved_state[SMRAM_FIELD_P6_GS_LIMIT] = cpu_state.seg_gs.limit; - saved_state[SMRAM_FIELD_P6_GS_SELECTOR_AR] = - (cpu_state.seg_gs.ar_high << 24) | (cpu_state.seg_gs.access << 16) | cpu_state.seg_gs.seg; + saved_state[SMRAM_FIELD_P6_GS_SELECTOR] = cpu_state.seg_gs.seg; + saved_state[SMRAM_FIELD_P6_GS_BASE] = cpu_state.seg_gs.base; + saved_state[SMRAM_FIELD_P6_GS_LIMIT] = cpu_state.seg_gs.limit; + saved_state[SMRAM_FIELD_P6_GS_SELECTOR_AR] = (cpu_state.seg_gs.ar_high << 24) | (cpu_state.seg_gs.access << 16) | cpu_state.seg_gs.seg; } - static void smram_restore_state_p6(uint32_t *saved_state) { - int n = 0; - - for (n = 0; n < 8; n++) - cpu_state.regs[n].l = saved_state[SMRAM_FIELD_P6_EAX - n]; + for (uint8_t n = 0; n < 8; n++) + cpu_state.regs[n].l = saved_state[SMRAM_FIELD_P6_EAX - n]; if (saved_state[SMRAM_FIELD_P6_AUTOHALT_RESTART] & 0xffff) - cpu_state.pc = saved_state[SMRAM_FIELD_P6_EIP] - 1; + cpu_state.pc = saved_state[SMRAM_FIELD_P6_EIP] - 1; else - cpu_state.pc = saved_state[SMRAM_FIELD_P6_EIP]; + cpu_state.pc = saved_state[SMRAM_FIELD_P6_EIP]; cpu_state.eflags = saved_state[SMRAM_FIELD_P6_EFLAGS] >> 16; - cpu_state.flags = saved_state[SMRAM_FIELD_P6_EFLAGS] & 0xffff; + cpu_state.flags = saved_state[SMRAM_FIELD_P6_EFLAGS] & 0xffff; - cr0 = saved_state[SMRAM_FIELD_P6_CR0]; - cr3 = saved_state[SMRAM_FIELD_P6_CR3]; - cr4 = saved_state[SMRAM_FIELD_P6_CR4]; + cr0 = saved_state[SMRAM_FIELD_P6_CR0]; + cr3 = saved_state[SMRAM_FIELD_P6_CR3]; + cr4 = saved_state[SMRAM_FIELD_P6_CR4]; dr[6] = saved_state[SMRAM_FIELD_P6_DR6]; dr[7] = saved_state[SMRAM_FIELD_P6_DR7]; /* TR */ - tr.seg = saved_state[SMRAM_FIELD_P6_TR_SELECTOR]; - tr.base = saved_state[SMRAM_FIELD_P6_TR_BASE]; - tr.limit = saved_state[SMRAM_FIELD_P6_TR_LIMIT]; - tr.access = (saved_state[SMRAM_FIELD_P6_TR_SELECTOR_AR] >> 16) & 0xff; + tr.seg = saved_state[SMRAM_FIELD_P6_TR_SELECTOR]; + tr.base = saved_state[SMRAM_FIELD_P6_TR_BASE]; + tr.limit = saved_state[SMRAM_FIELD_P6_TR_LIMIT]; + tr.access = (saved_state[SMRAM_FIELD_P6_TR_SELECTOR_AR] >> 16) & 0xff; tr.ar_high = (saved_state[SMRAM_FIELD_P6_TR_SELECTOR_AR] >> 24) & 0xff; smm_seg_load(&tr); /* LDTR */ - ldt.seg = saved_state[SMRAM_FIELD_P6_LDTR_SELECTOR]; - ldt.base = saved_state[SMRAM_FIELD_P6_LDTR_BASE]; - ldt.limit = saved_state[SMRAM_FIELD_P6_LDTR_LIMIT]; - ldt.access = (saved_state[SMRAM_FIELD_P6_LDTR_SELECTOR_AR] >> 16) & 0xff; + ldt.seg = saved_state[SMRAM_FIELD_P6_LDTR_SELECTOR]; + ldt.base = saved_state[SMRAM_FIELD_P6_LDTR_BASE]; + ldt.limit = saved_state[SMRAM_FIELD_P6_LDTR_LIMIT]; + ldt.access = (saved_state[SMRAM_FIELD_P6_LDTR_SELECTOR_AR] >> 16) & 0xff; ldt.ar_high = (saved_state[SMRAM_FIELD_P6_LDTR_SELECTOR_AR] >> 24) & 0xff; smm_seg_load(&ldt); /* IDTR */ - idt.base = saved_state[SMRAM_FIELD_P6_IDTR_BASE]; - idt.limit = saved_state[SMRAM_FIELD_P6_IDTR_LIMIT]; - idt.access = (saved_state[SMRAM_FIELD_P6_IDTR_SELECTOR_AR] >> 16) & 0xff; + idt.base = saved_state[SMRAM_FIELD_P6_IDTR_BASE]; + idt.limit = saved_state[SMRAM_FIELD_P6_IDTR_LIMIT]; + idt.access = (saved_state[SMRAM_FIELD_P6_IDTR_SELECTOR_AR] >> 16) & 0xff; idt.ar_high = (saved_state[SMRAM_FIELD_P6_IDTR_SELECTOR_AR] >> 24) & 0xff; /* GDTR */ - gdt.base = saved_state[SMRAM_FIELD_P6_GDTR_BASE]; - gdt.limit = saved_state[SMRAM_FIELD_P6_GDTR_LIMIT]; - gdt.access = (saved_state[SMRAM_FIELD_P6_GDTR_SELECTOR_AR] >> 16) & 0xff; + gdt.base = saved_state[SMRAM_FIELD_P6_GDTR_BASE]; + gdt.limit = saved_state[SMRAM_FIELD_P6_GDTR_LIMIT]; + gdt.access = (saved_state[SMRAM_FIELD_P6_GDTR_SELECTOR_AR] >> 16) & 0xff; gdt.ar_high = (saved_state[SMRAM_FIELD_P6_GDTR_SELECTOR_AR] >> 24) & 0xff; /* ES */ - cpu_state.seg_es.seg = saved_state[SMRAM_FIELD_P6_ES_SELECTOR]; - cpu_state.seg_es.base = saved_state[SMRAM_FIELD_P6_ES_BASE]; - cpu_state.seg_es.limit = saved_state[SMRAM_FIELD_P6_ES_LIMIT]; - cpu_state.seg_es.access = (saved_state[SMRAM_FIELD_P6_ES_SELECTOR_AR] >> 16) & 0xff; + cpu_state.seg_es.seg = saved_state[SMRAM_FIELD_P6_ES_SELECTOR]; + cpu_state.seg_es.base = saved_state[SMRAM_FIELD_P6_ES_BASE]; + cpu_state.seg_es.limit = saved_state[SMRAM_FIELD_P6_ES_LIMIT]; + cpu_state.seg_es.access = (saved_state[SMRAM_FIELD_P6_ES_SELECTOR_AR] >> 16) & 0xff; cpu_state.seg_es.ar_high = (saved_state[SMRAM_FIELD_P6_ES_SELECTOR_AR] >> 24) & 0xff; smm_seg_load(&cpu_state.seg_es); /* CS */ - cpu_state.seg_cs.seg = saved_state[SMRAM_FIELD_P6_CS_SELECTOR]; - cpu_state.seg_cs.base = saved_state[SMRAM_FIELD_P6_CS_BASE]; - cpu_state.seg_cs.limit = saved_state[SMRAM_FIELD_P6_CS_LIMIT]; - cpu_state.seg_cs.access = (saved_state[SMRAM_FIELD_P6_CS_SELECTOR_AR] >> 16) & 0xff; + cpu_state.seg_cs.seg = saved_state[SMRAM_FIELD_P6_CS_SELECTOR]; + cpu_state.seg_cs.base = saved_state[SMRAM_FIELD_P6_CS_BASE]; + cpu_state.seg_cs.limit = saved_state[SMRAM_FIELD_P6_CS_LIMIT]; + cpu_state.seg_cs.access = (saved_state[SMRAM_FIELD_P6_CS_SELECTOR_AR] >> 16) & 0xff; cpu_state.seg_cs.ar_high = (saved_state[SMRAM_FIELD_P6_CS_SELECTOR_AR] >> 24) & 0xff; smm_seg_load(&cpu_state.seg_cs); cpu_state.seg_cs.access = (cpu_state.seg_cs.access & ~0x60) | ((saved_state[SMRAM_FIELD_P6_CPL] & 0x03) << 5); /* DS */ - cpu_state.seg_ds.seg = saved_state[SMRAM_FIELD_P6_DS_SELECTOR]; - cpu_state.seg_ds.base = saved_state[SMRAM_FIELD_P6_DS_BASE]; - cpu_state.seg_ds.limit = saved_state[SMRAM_FIELD_P6_DS_LIMIT]; - cpu_state.seg_ds.access = (saved_state[SMRAM_FIELD_P6_DS_SELECTOR_AR] >> 16) & 0xff; + cpu_state.seg_ds.seg = saved_state[SMRAM_FIELD_P6_DS_SELECTOR]; + cpu_state.seg_ds.base = saved_state[SMRAM_FIELD_P6_DS_BASE]; + cpu_state.seg_ds.limit = saved_state[SMRAM_FIELD_P6_DS_LIMIT]; + cpu_state.seg_ds.access = (saved_state[SMRAM_FIELD_P6_DS_SELECTOR_AR] >> 16) & 0xff; cpu_state.seg_ds.ar_high = (saved_state[SMRAM_FIELD_P6_DS_SELECTOR_AR] >> 24) & 0xff; smm_seg_load(&cpu_state.seg_ds); /* SS */ - cpu_state.seg_ss.seg = saved_state[SMRAM_FIELD_P6_SS_SELECTOR]; - cpu_state.seg_ss.base = saved_state[SMRAM_FIELD_P6_SS_BASE]; - cpu_state.seg_ss.limit = saved_state[SMRAM_FIELD_P6_SS_LIMIT]; - cpu_state.seg_ss.access = (saved_state[SMRAM_FIELD_P6_SS_SELECTOR_AR] >> 16) & 0xff; + cpu_state.seg_ss.seg = saved_state[SMRAM_FIELD_P6_SS_SELECTOR]; + cpu_state.seg_ss.base = saved_state[SMRAM_FIELD_P6_SS_BASE]; + cpu_state.seg_ss.limit = saved_state[SMRAM_FIELD_P6_SS_LIMIT]; + cpu_state.seg_ss.access = (saved_state[SMRAM_FIELD_P6_SS_SELECTOR_AR] >> 16) & 0xff; cpu_state.seg_ss.ar_high = (saved_state[SMRAM_FIELD_P6_SS_SELECTOR_AR] >> 24) & 0xff; smm_seg_load(&cpu_state.seg_ss); /* FS */ - cpu_state.seg_fs.seg = saved_state[SMRAM_FIELD_P6_FS_SELECTOR]; - cpu_state.seg_fs.base = saved_state[SMRAM_FIELD_P6_FS_BASE]; - cpu_state.seg_fs.limit = saved_state[SMRAM_FIELD_P6_FS_LIMIT]; - cpu_state.seg_fs.access = (saved_state[SMRAM_FIELD_P6_FS_SELECTOR_AR] >> 16) & 0xff; + cpu_state.seg_fs.seg = saved_state[SMRAM_FIELD_P6_FS_SELECTOR]; + cpu_state.seg_fs.base = saved_state[SMRAM_FIELD_P6_FS_BASE]; + cpu_state.seg_fs.limit = saved_state[SMRAM_FIELD_P6_FS_LIMIT]; + cpu_state.seg_fs.access = (saved_state[SMRAM_FIELD_P6_FS_SELECTOR_AR] >> 16) & 0xff; cpu_state.seg_fs.ar_high = (saved_state[SMRAM_FIELD_P6_FS_SELECTOR_AR] >> 24) & 0xff; smm_seg_load(&cpu_state.seg_fs); /* GS */ - cpu_state.seg_gs.seg = saved_state[SMRAM_FIELD_P6_GS_SELECTOR]; - cpu_state.seg_gs.base = saved_state[SMRAM_FIELD_P6_GS_BASE]; - cpu_state.seg_gs.limit = saved_state[SMRAM_FIELD_P6_GS_LIMIT]; - cpu_state.seg_gs.access = (saved_state[SMRAM_FIELD_P6_GS_SELECTOR_AR] >> 16) & 0xff; + cpu_state.seg_gs.seg = saved_state[SMRAM_FIELD_P6_GS_SELECTOR]; + cpu_state.seg_gs.base = saved_state[SMRAM_FIELD_P6_GS_BASE]; + cpu_state.seg_gs.limit = saved_state[SMRAM_FIELD_P6_GS_LIMIT]; + cpu_state.seg_gs.access = (saved_state[SMRAM_FIELD_P6_GS_SELECTOR_AR] >> 16) & 0xff; cpu_state.seg_gs.ar_high = (saved_state[SMRAM_FIELD_P6_GS_SELECTOR_AR] >> 24) & 0xff; smm_seg_load(&cpu_state.seg_gs); - mem_a20_alt = 0; - keyboard_at_set_a20_key(!saved_state[SMRAM_FIELD_P6_A20M]); + mem_a20_alt = 0x00; + mem_a20_key = saved_state[SMRAM_FIELD_P6_A20M] ? 0x00 : 0x02; mem_a20_recalc(); if (SMM_REVISION_ID & SMM_SMBASE_RELOCATION) - smbase = saved_state[SMRAM_FIELD_P6_SMBASE_OFFSET]; + smbase = saved_state[SMRAM_FIELD_P6_SMBASE_OFFSET]; } - static void smram_save_state_amd_k(uint32_t *saved_state, int in_hlt) { - int n = 0; - saved_state[SMRAM_FIELD_AMD_K_SMM_REVISION_ID] = SMM_REVISION_ID; - saved_state[SMRAM_FIELD_AMD_K_SMBASE_OFFSET] = smbase; + saved_state[SMRAM_FIELD_AMD_K_SMBASE_OFFSET] = smbase; - for (n = 0; n < 8; n++) - saved_state[SMRAM_FIELD_AMD_K_EAX - n] = cpu_state.regs[n].l; + for (uint8_t n = 0; n < 8; n++) + saved_state[SMRAM_FIELD_AMD_K_EAX - n] = cpu_state.regs[n].l; if (in_hlt) - saved_state[SMRAM_FIELD_AMD_K_AUTOHALT_RESTART] = 1; + saved_state[SMRAM_FIELD_AMD_K_AUTOHALT_RESTART] = 1; else - saved_state[SMRAM_FIELD_AMD_K_AUTOHALT_RESTART] = 0; + saved_state[SMRAM_FIELD_AMD_K_AUTOHALT_RESTART] = 0; saved_state[SMRAM_FIELD_AMD_K_EIP] = cpu_state.pc; @@ -834,169 +932,165 @@ smram_save_state_amd_k(uint32_t *saved_state, int in_hlt) /* TR */ saved_state[SMRAM_FIELD_AMD_K_TR_SELECTOR] = tr.seg; - saved_state[SMRAM_FIELD_AMD_K_TR_BASE] = tr.base; - saved_state[SMRAM_FIELD_AMD_K_TR_LIMIT] = tr.limit; - saved_state[SMRAM_FIELD_AMD_K_TR_ACCESS] = (tr.ar_high << 16) | (tr.access << 8); + saved_state[SMRAM_FIELD_AMD_K_TR_BASE] = tr.base; + saved_state[SMRAM_FIELD_AMD_K_TR_LIMIT] = tr.limit; + saved_state[SMRAM_FIELD_AMD_K_TR_ACCESS] = (tr.ar_high << 16) | (tr.access << 8); /* LDTR */ saved_state[SMRAM_FIELD_AMD_K_LDTR_SELECTOR] = ldt.seg; - saved_state[SMRAM_FIELD_AMD_K_LDTR_BASE] = ldt.base; - saved_state[SMRAM_FIELD_AMD_K_LDTR_LIMIT] = ldt.limit; + saved_state[SMRAM_FIELD_AMD_K_LDTR_BASE] = ldt.base; + saved_state[SMRAM_FIELD_AMD_K_LDTR_LIMIT] = ldt.limit; if (!is_k6) - saved_state[SMRAM_FIELD_AMD_K_LDTR_ACCESS] = (ldt.ar_high << 16) | (ldt.access << 8); + saved_state[SMRAM_FIELD_AMD_K_LDTR_ACCESS] = (ldt.ar_high << 16) | (ldt.access << 8); /* IDTR */ - saved_state[SMRAM_FIELD_AMD_K_IDTR_BASE] = idt.base; + saved_state[SMRAM_FIELD_AMD_K_IDTR_BASE] = idt.base; saved_state[SMRAM_FIELD_AMD_K_IDTR_LIMIT] = idt.limit; /* GDTR */ - saved_state[SMRAM_FIELD_AMD_K_GDTR_BASE] = gdt.base; + saved_state[SMRAM_FIELD_AMD_K_GDTR_BASE] = gdt.base; saved_state[SMRAM_FIELD_AMD_K_GDTR_LIMIT] = gdt.limit; /* ES */ saved_state[SMRAM_FIELD_AMD_K_ES_SELECTOR] = cpu_state.seg_es.seg; - saved_state[SMRAM_FIELD_AMD_K_ES_BASE] = cpu_state.seg_es.base; - saved_state[SMRAM_FIELD_AMD_K_ES_LIMIT] = cpu_state.seg_es.limit; - saved_state[SMRAM_FIELD_AMD_K_ES_ACCESS] = (cpu_state.seg_es.ar_high << 16) | (cpu_state.seg_es.access << 8); + saved_state[SMRAM_FIELD_AMD_K_ES_BASE] = cpu_state.seg_es.base; + saved_state[SMRAM_FIELD_AMD_K_ES_LIMIT] = cpu_state.seg_es.limit; + saved_state[SMRAM_FIELD_AMD_K_ES_ACCESS] = (cpu_state.seg_es.ar_high << 16) | (cpu_state.seg_es.access << 8); /* CS */ saved_state[SMRAM_FIELD_AMD_K_CS_SELECTOR] = cpu_state.seg_cs.seg; - saved_state[SMRAM_FIELD_AMD_K_CS_BASE] = cpu_state.seg_cs.base; - saved_state[SMRAM_FIELD_AMD_K_CS_LIMIT] = cpu_state.seg_cs.limit; - saved_state[SMRAM_FIELD_AMD_K_CS_ACCESS] = (cpu_state.seg_cs.ar_high << 16) | (cpu_state.seg_cs.access << 8); + saved_state[SMRAM_FIELD_AMD_K_CS_BASE] = cpu_state.seg_cs.base; + saved_state[SMRAM_FIELD_AMD_K_CS_LIMIT] = cpu_state.seg_cs.limit; + saved_state[SMRAM_FIELD_AMD_K_CS_ACCESS] = (cpu_state.seg_cs.ar_high << 16) | (cpu_state.seg_cs.access << 8); /* DS */ saved_state[SMRAM_FIELD_AMD_K_DS_SELECTOR] = cpu_state.seg_ds.seg; - saved_state[SMRAM_FIELD_AMD_K_DS_BASE] = cpu_state.seg_ds.base; - saved_state[SMRAM_FIELD_AMD_K_DS_LIMIT] = cpu_state.seg_ds.limit; - saved_state[SMRAM_FIELD_AMD_K_DS_ACCESS] = (cpu_state.seg_ds.ar_high << 16) | (cpu_state.seg_ds.access << 8); + saved_state[SMRAM_FIELD_AMD_K_DS_BASE] = cpu_state.seg_ds.base; + saved_state[SMRAM_FIELD_AMD_K_DS_LIMIT] = cpu_state.seg_ds.limit; + saved_state[SMRAM_FIELD_AMD_K_DS_ACCESS] = (cpu_state.seg_ds.ar_high << 16) | (cpu_state.seg_ds.access << 8); /* SS */ saved_state[SMRAM_FIELD_AMD_K_SS_SELECTOR] = cpu_state.seg_ss.seg; - saved_state[SMRAM_FIELD_AMD_K_SS_BASE] = cpu_state.seg_ss.base; - saved_state[SMRAM_FIELD_AMD_K_SS_LIMIT] = cpu_state.seg_ss.limit; - saved_state[SMRAM_FIELD_AMD_K_SS_ACCESS] = (cpu_state.seg_ss.ar_high << 16) | (cpu_state.seg_ss.access << 8); + saved_state[SMRAM_FIELD_AMD_K_SS_BASE] = cpu_state.seg_ss.base; + saved_state[SMRAM_FIELD_AMD_K_SS_LIMIT] = cpu_state.seg_ss.limit; + saved_state[SMRAM_FIELD_AMD_K_SS_ACCESS] = (cpu_state.seg_ss.ar_high << 16) | (cpu_state.seg_ss.access << 8); /* FS */ saved_state[SMRAM_FIELD_AMD_K_FS_SELECTOR] = cpu_state.seg_fs.seg; - saved_state[SMRAM_FIELD_AMD_K_FS_BASE] = cpu_state.seg_fs.base; - saved_state[SMRAM_FIELD_AMD_K_FS_LIMIT] = cpu_state.seg_fs.limit; - saved_state[SMRAM_FIELD_AMD_K_FS_ACCESS] = (cpu_state.seg_fs.ar_high << 16) | (cpu_state.seg_fs.access << 8); + saved_state[SMRAM_FIELD_AMD_K_FS_BASE] = cpu_state.seg_fs.base; + saved_state[SMRAM_FIELD_AMD_K_FS_LIMIT] = cpu_state.seg_fs.limit; + saved_state[SMRAM_FIELD_AMD_K_FS_ACCESS] = (cpu_state.seg_fs.ar_high << 16) | (cpu_state.seg_fs.access << 8); /* GS */ saved_state[SMRAM_FIELD_AMD_K_GS_SELECTOR] = cpu_state.seg_gs.seg; - saved_state[SMRAM_FIELD_AMD_K_GS_BASE] = cpu_state.seg_gs.base; - saved_state[SMRAM_FIELD_AMD_K_GS_LIMIT] = cpu_state.seg_gs.limit; - saved_state[SMRAM_FIELD_AMD_K_GS_ACCESS] = (cpu_state.seg_gs.ar_high << 16) | (cpu_state.seg_gs.access << 8); + saved_state[SMRAM_FIELD_AMD_K_GS_BASE] = cpu_state.seg_gs.base; + saved_state[SMRAM_FIELD_AMD_K_GS_LIMIT] = cpu_state.seg_gs.limit; + saved_state[SMRAM_FIELD_AMD_K_GS_ACCESS] = (cpu_state.seg_gs.ar_high << 16) | (cpu_state.seg_gs.access << 8); } - static void smram_restore_state_amd_k(uint32_t *saved_state) { - int n = 0; - - for (n = 0; n < 8; n++) - cpu_state.regs[n].l = saved_state[SMRAM_FIELD_AMD_K_EAX - n]; + for (uint8_t n = 0; n < 8; n++) + cpu_state.regs[n].l = saved_state[SMRAM_FIELD_AMD_K_EAX - n]; if (saved_state[SMRAM_FIELD_AMD_K_AUTOHALT_RESTART] & 0xffff) - cpu_state.pc = saved_state[SMRAM_FIELD_AMD_K_EIP] - 1; + cpu_state.pc = saved_state[SMRAM_FIELD_AMD_K_EIP] - 1; else - cpu_state.pc = saved_state[SMRAM_FIELD_AMD_K_EIP]; + cpu_state.pc = saved_state[SMRAM_FIELD_AMD_K_EIP]; cpu_state.eflags = saved_state[SMRAM_FIELD_AMD_K_EFLAGS] >> 16; - cpu_state.flags = saved_state[SMRAM_FIELD_AMD_K_EFLAGS] & 0xffff; + cpu_state.flags = saved_state[SMRAM_FIELD_AMD_K_EFLAGS] & 0xffff; - cr0 = saved_state[SMRAM_FIELD_AMD_K_CR0]; - cr2 = saved_state[SMRAM_FIELD_AMD_K_CR2]; - cr3 = saved_state[SMRAM_FIELD_AMD_K_CR3]; - cr4 = saved_state[SMRAM_FIELD_AMD_K_CR4]; + cr0 = saved_state[SMRAM_FIELD_AMD_K_CR0]; + cr2 = saved_state[SMRAM_FIELD_AMD_K_CR2]; + cr3 = saved_state[SMRAM_FIELD_AMD_K_CR3]; + cr4 = saved_state[SMRAM_FIELD_AMD_K_CR4]; dr[6] = saved_state[SMRAM_FIELD_AMD_K_DR6]; dr[7] = saved_state[SMRAM_FIELD_AMD_K_DR7]; /* TR */ - tr.seg = saved_state[SMRAM_FIELD_AMD_K_TR_SELECTOR]; - tr.base = saved_state[SMRAM_FIELD_AMD_K_TR_BASE]; - tr.limit = saved_state[SMRAM_FIELD_AMD_K_TR_LIMIT]; - tr.access = (saved_state[SMRAM_FIELD_AMD_K_TR_ACCESS] >> 8) & 0xff; + tr.seg = saved_state[SMRAM_FIELD_AMD_K_TR_SELECTOR]; + tr.base = saved_state[SMRAM_FIELD_AMD_K_TR_BASE]; + tr.limit = saved_state[SMRAM_FIELD_AMD_K_TR_LIMIT]; + tr.access = (saved_state[SMRAM_FIELD_AMD_K_TR_ACCESS] >> 8) & 0xff; tr.ar_high = (saved_state[SMRAM_FIELD_AMD_K_TR_ACCESS] >> 16) & 0xff; smm_seg_load(&tr); /* LDTR */ - ldt.seg = saved_state[SMRAM_FIELD_AMD_K_LDTR_SELECTOR]; - ldt.base = saved_state[SMRAM_FIELD_AMD_K_LDTR_BASE]; + ldt.seg = saved_state[SMRAM_FIELD_AMD_K_LDTR_SELECTOR]; + ldt.base = saved_state[SMRAM_FIELD_AMD_K_LDTR_BASE]; ldt.limit = saved_state[SMRAM_FIELD_AMD_K_LDTR_LIMIT]; if (!is_k6) { - ldt.access = (saved_state[SMRAM_FIELD_AMD_K_LDTR_ACCESS] >> 8) & 0xff; - ldt.ar_high = (saved_state[SMRAM_FIELD_AMD_K_LDTR_ACCESS] >> 16) & 0xff; + ldt.access = (saved_state[SMRAM_FIELD_AMD_K_LDTR_ACCESS] >> 8) & 0xff; + ldt.ar_high = (saved_state[SMRAM_FIELD_AMD_K_LDTR_ACCESS] >> 16) & 0xff; } smm_seg_load(&ldt); /* IDTR */ - idt.base = saved_state[SMRAM_FIELD_AMD_K_IDTR_BASE]; + idt.base = saved_state[SMRAM_FIELD_AMD_K_IDTR_BASE]; idt.limit = saved_state[SMRAM_FIELD_AMD_K_IDTR_LIMIT]; /* GDTR */ - gdt.base = saved_state[SMRAM_FIELD_AMD_K_GDTR_BASE]; + gdt.base = saved_state[SMRAM_FIELD_AMD_K_GDTR_BASE]; gdt.limit = saved_state[SMRAM_FIELD_AMD_K_GDTR_LIMIT]; /* ES */ - cpu_state.seg_es.seg = saved_state[SMRAM_FIELD_AMD_K_ES_SELECTOR]; - cpu_state.seg_es.base = saved_state[SMRAM_FIELD_AMD_K_ES_BASE]; - cpu_state.seg_es.limit = saved_state[SMRAM_FIELD_AMD_K_ES_LIMIT]; - cpu_state.seg_es.access = (saved_state[SMRAM_FIELD_AMD_K_ES_ACCESS] >> 8) & 0xff; + cpu_state.seg_es.seg = saved_state[SMRAM_FIELD_AMD_K_ES_SELECTOR]; + cpu_state.seg_es.base = saved_state[SMRAM_FIELD_AMD_K_ES_BASE]; + cpu_state.seg_es.limit = saved_state[SMRAM_FIELD_AMD_K_ES_LIMIT]; + cpu_state.seg_es.access = (saved_state[SMRAM_FIELD_AMD_K_ES_ACCESS] >> 8) & 0xff; cpu_state.seg_es.ar_high = (saved_state[SMRAM_FIELD_AMD_K_ES_ACCESS] >> 16) & 0xff; smm_seg_load(&cpu_state.seg_es); /* CS */ - cpu_state.seg_cs.seg = saved_state[SMRAM_FIELD_AMD_K_CS_SELECTOR]; - cpu_state.seg_cs.base = saved_state[SMRAM_FIELD_AMD_K_CS_BASE]; - cpu_state.seg_cs.limit = saved_state[SMRAM_FIELD_AMD_K_CS_LIMIT]; - cpu_state.seg_cs.access = (saved_state[SMRAM_FIELD_AMD_K_CS_ACCESS] >> 8) & 0xff; + cpu_state.seg_cs.seg = saved_state[SMRAM_FIELD_AMD_K_CS_SELECTOR]; + cpu_state.seg_cs.base = saved_state[SMRAM_FIELD_AMD_K_CS_BASE]; + cpu_state.seg_cs.limit = saved_state[SMRAM_FIELD_AMD_K_CS_LIMIT]; + cpu_state.seg_cs.access = (saved_state[SMRAM_FIELD_AMD_K_CS_ACCESS] >> 8) & 0xff; cpu_state.seg_cs.ar_high = (saved_state[SMRAM_FIELD_AMD_K_CS_ACCESS] >> 16) & 0xff; smm_seg_load(&cpu_state.seg_cs); /* DS */ - cpu_state.seg_ds.seg = saved_state[SMRAM_FIELD_AMD_K_DS_SELECTOR]; - cpu_state.seg_ds.base = saved_state[SMRAM_FIELD_AMD_K_DS_BASE]; - cpu_state.seg_ds.limit = saved_state[SMRAM_FIELD_AMD_K_DS_LIMIT]; - cpu_state.seg_ds.access = (saved_state[SMRAM_FIELD_AMD_K_DS_ACCESS] >> 8) & 0xff; + cpu_state.seg_ds.seg = saved_state[SMRAM_FIELD_AMD_K_DS_SELECTOR]; + cpu_state.seg_ds.base = saved_state[SMRAM_FIELD_AMD_K_DS_BASE]; + cpu_state.seg_ds.limit = saved_state[SMRAM_FIELD_AMD_K_DS_LIMIT]; + cpu_state.seg_ds.access = (saved_state[SMRAM_FIELD_AMD_K_DS_ACCESS] >> 8) & 0xff; cpu_state.seg_ds.ar_high = (saved_state[SMRAM_FIELD_AMD_K_DS_ACCESS] >> 16) & 0xff; smm_seg_load(&cpu_state.seg_ds); /* SS */ - cpu_state.seg_ss.seg = saved_state[SMRAM_FIELD_AMD_K_SS_SELECTOR]; - cpu_state.seg_ss.base = saved_state[SMRAM_FIELD_AMD_K_SS_BASE]; - cpu_state.seg_ss.limit = saved_state[SMRAM_FIELD_AMD_K_SS_LIMIT]; + cpu_state.seg_ss.seg = saved_state[SMRAM_FIELD_AMD_K_SS_SELECTOR]; + cpu_state.seg_ss.base = saved_state[SMRAM_FIELD_AMD_K_SS_BASE]; + cpu_state.seg_ss.limit = saved_state[SMRAM_FIELD_AMD_K_SS_LIMIT]; cpu_state.seg_ss.access = (saved_state[SMRAM_FIELD_AMD_K_SS_ACCESS] >> 8) & 0xff; /* The actual CPL (DPL of CS) is overwritten with DPL of SS. */ - cpu_state.seg_cs.access = (cpu_state.seg_cs.access & ~0x60) | (cpu_state.seg_ss.access & 0x60); + cpu_state.seg_cs.access = (cpu_state.seg_cs.access & ~0x60) | (cpu_state.seg_ss.access & 0x60); cpu_state.seg_ss.ar_high = (saved_state[SMRAM_FIELD_AMD_K_SS_ACCESS] >> 16) & 0xff; smm_seg_load(&cpu_state.seg_ss); /* FS */ - cpu_state.seg_fs.seg = saved_state[SMRAM_FIELD_AMD_K_FS_SELECTOR]; - cpu_state.seg_fs.base = saved_state[SMRAM_FIELD_AMD_K_FS_BASE]; - cpu_state.seg_fs.limit = saved_state[SMRAM_FIELD_AMD_K_FS_LIMIT]; - cpu_state.seg_fs.access = (saved_state[SMRAM_FIELD_AMD_K_FS_ACCESS] >> 8) & 0xff; + cpu_state.seg_fs.seg = saved_state[SMRAM_FIELD_AMD_K_FS_SELECTOR]; + cpu_state.seg_fs.base = saved_state[SMRAM_FIELD_AMD_K_FS_BASE]; + cpu_state.seg_fs.limit = saved_state[SMRAM_FIELD_AMD_K_FS_LIMIT]; + cpu_state.seg_fs.access = (saved_state[SMRAM_FIELD_AMD_K_FS_ACCESS] >> 8) & 0xff; cpu_state.seg_fs.ar_high = (saved_state[SMRAM_FIELD_AMD_K_FS_ACCESS] >> 16) & 0xff; smm_seg_load(&cpu_state.seg_fs); /* GS */ - cpu_state.seg_gs.seg = saved_state[SMRAM_FIELD_AMD_K_GS_SELECTOR]; - cpu_state.seg_gs.base = saved_state[SMRAM_FIELD_AMD_K_GS_BASE]; - cpu_state.seg_gs.limit = saved_state[SMRAM_FIELD_AMD_K_GS_LIMIT]; - cpu_state.seg_gs.access = (saved_state[SMRAM_FIELD_AMD_K_GS_ACCESS] >> 8) & 0xff; + cpu_state.seg_gs.seg = saved_state[SMRAM_FIELD_AMD_K_GS_SELECTOR]; + cpu_state.seg_gs.base = saved_state[SMRAM_FIELD_AMD_K_GS_BASE]; + cpu_state.seg_gs.limit = saved_state[SMRAM_FIELD_AMD_K_GS_LIMIT]; + cpu_state.seg_gs.access = (saved_state[SMRAM_FIELD_AMD_K_GS_ACCESS] >> 8) & 0xff; cpu_state.seg_gs.ar_high = (saved_state[SMRAM_FIELD_AMD_K_GS_ACCESS] >> 16) & 0xff; smm_seg_load(&cpu_state.seg_gs); if (SMM_REVISION_ID & SMM_SMBASE_RELOCATION) - smbase = saved_state[SMRAM_FIELD_AMD_K_SMBASE_OFFSET]; + smbase = saved_state[SMRAM_FIELD_AMD_K_SMBASE_OFFSET]; } - static void -smram_save_state_cyrix(uint32_t *saved_state, int in_hlt) +smram_save_state_cyrix(uint32_t *saved_state, UNUSED(int in_hlt)) { saved_state[0] = dr[7]; saved_state[1] = cpu_state.flags | (cpu_state.eflags << 16); @@ -1007,59 +1101,57 @@ smram_save_state_cyrix(uint32_t *saved_state, int in_hlt) saved_state[6] = 0x00000000; } - static void smram_restore_state_cyrix(uint32_t *saved_state) { - dr[7] = saved_state[0]; - cpu_state.flags = saved_state[1] & 0xffff; + dr[7] = saved_state[0]; + cpu_state.flags = saved_state[1] & 0xffff; cpu_state.eflags = saved_state[1] >> 16; - cr0 = saved_state[2]; - cpu_state.pc = saved_state[4]; + cr0 = saved_state[2]; + cpu_state.pc = saved_state[4]; } - void enter_smm(int in_hlt) { - uint32_t saved_state[SMM_SAVE_STATE_MAP_SIZE], n; + uint32_t saved_state[SMM_SAVE_STATE_MAP_SIZE]; uint32_t smram_state = smbase + 0x10000; /* If it's a CPU on which SMM is not supported, do nothing. */ if (!is_am486 && !is_pentium && !is_k5 && !is_k6 && !is_p6 && !is_cxsmm) - return; + return; x386_common_log("enter_smm(): smbase = %08X\n", smbase); x386_common_log("CS : seg = %04X, base = %08X, limit = %08X, limit_low = %08X, limit_high = %08X, access = %02X, ar_high = %02X\n", - cpu_state.seg_cs.seg, cpu_state.seg_cs.base, cpu_state.seg_cs.limit, cpu_state.seg_cs.limit_low, - cpu_state.seg_cs.limit_high, cpu_state.seg_cs.access, cpu_state.seg_cs.ar_high); + cpu_state.seg_cs.seg, cpu_state.seg_cs.base, cpu_state.seg_cs.limit, cpu_state.seg_cs.limit_low, + cpu_state.seg_cs.limit_high, cpu_state.seg_cs.access, cpu_state.seg_cs.ar_high); x386_common_log("DS : seg = %04X, base = %08X, limit = %08X, limit_low = %08X, limit_high = %08X, access = %02X, ar_high = %02X\n", - cpu_state.seg_ds.seg, cpu_state.seg_ds.base, cpu_state.seg_ds.limit, cpu_state.seg_ds.limit_low, - cpu_state.seg_ds.limit_high, cpu_state.seg_ds.access, cpu_state.seg_ds.ar_high); + cpu_state.seg_ds.seg, cpu_state.seg_ds.base, cpu_state.seg_ds.limit, cpu_state.seg_ds.limit_low, + cpu_state.seg_ds.limit_high, cpu_state.seg_ds.access, cpu_state.seg_ds.ar_high); x386_common_log("ES : seg = %04X, base = %08X, limit = %08X, limit_low = %08X, limit_high = %08X, access = %02X, ar_high = %02X\n", - cpu_state.seg_es.seg, cpu_state.seg_es.base, cpu_state.seg_es.limit, cpu_state.seg_es.limit_low, - cpu_state.seg_es.limit_high, cpu_state.seg_es.access, cpu_state.seg_es.ar_high); + cpu_state.seg_es.seg, cpu_state.seg_es.base, cpu_state.seg_es.limit, cpu_state.seg_es.limit_low, + cpu_state.seg_es.limit_high, cpu_state.seg_es.access, cpu_state.seg_es.ar_high); x386_common_log("FS : seg = %04X, base = %08X, limit = %08X, limit_low = %08X, limit_high = %08X, access = %02X, ar_high = %02X\n", - cpu_state.seg_fs.seg, cpu_state.seg_fs.base, cpu_state.seg_fs.limit, cpu_state.seg_fs.limit_low, - cpu_state.seg_fs.limit_high, cpu_state.seg_fs.access, cpu_state.seg_fs.ar_high); + cpu_state.seg_fs.seg, cpu_state.seg_fs.base, cpu_state.seg_fs.limit, cpu_state.seg_fs.limit_low, + cpu_state.seg_fs.limit_high, cpu_state.seg_fs.access, cpu_state.seg_fs.ar_high); x386_common_log("GS : seg = %04X, base = %08X, limit = %08X, limit_low = %08X, limit_high = %08X, access = %02X, ar_high = %02X\n", - cpu_state.seg_gs.seg, cpu_state.seg_gs.base, cpu_state.seg_gs.limit, cpu_state.seg_gs.limit_low, - cpu_state.seg_gs.limit_high, cpu_state.seg_gs.access, cpu_state.seg_gs.ar_high); + cpu_state.seg_gs.seg, cpu_state.seg_gs.base, cpu_state.seg_gs.limit, cpu_state.seg_gs.limit_low, + cpu_state.seg_gs.limit_high, cpu_state.seg_gs.access, cpu_state.seg_gs.ar_high); x386_common_log("SS : seg = %04X, base = %08X, limit = %08X, limit_low = %08X, limit_high = %08X, access = %02X, ar_high = %02X\n", - cpu_state.seg_ss.seg, cpu_state.seg_ss.base, cpu_state.seg_ss.limit, cpu_state.seg_ss.limit_low, - cpu_state.seg_ss.limit_high, cpu_state.seg_ss.access, cpu_state.seg_ss.ar_high); + cpu_state.seg_ss.seg, cpu_state.seg_ss.base, cpu_state.seg_ss.limit, cpu_state.seg_ss.limit_low, + cpu_state.seg_ss.limit_high, cpu_state.seg_ss.access, cpu_state.seg_ss.ar_high); x386_common_log("TR : seg = %04X, base = %08X, limit = %08X, limit_low = %08X, limit_high = %08X, access = %02X, ar_high = %02X\n", - tr.seg, tr.base, tr.limit, tr.limit_low, tr.limit_high, tr.access, tr.ar_high); + tr.seg, tr.base, tr.limit, tr.limit_low, tr.limit_high, tr.access, tr.ar_high); x386_common_log("LDT: seg = %04X, base = %08X, limit = %08X, limit_low = %08X, limit_high = %08X, access = %02X, ar_high = %02X\n", - ldt.seg, ldt.base, ldt.limit, ldt.limit_low, ldt.limit_high, ldt.access, ldt.ar_high); + ldt.seg, ldt.base, ldt.limit, ldt.limit_low, ldt.limit_high, ldt.access, ldt.ar_high); x386_common_log("GDT: seg = %04X, base = %08X, limit = %08X, limit_low = %08X, limit_high = %08X, access = %02X, ar_high = %02X\n", - gdt.seg, gdt.base, gdt.limit, gdt.limit_low, gdt.limit_high, gdt.access, gdt.ar_high); + gdt.seg, gdt.base, gdt.limit, gdt.limit_low, gdt.limit_high, gdt.access, gdt.ar_high); x386_common_log("IDT: seg = %04X, base = %08X, limit = %08X, limit_low = %08X, limit_high = %08X, access = %02X, ar_high = %02X\n", - idt.seg, idt.base, idt.limit, idt.limit_low, idt.limit_high, idt.access, idt.ar_high); + idt.seg, idt.base, idt.limit, idt.limit_low, idt.limit_high, idt.access, idt.ar_high); x386_common_log("CR0 = %08X, CR3 = %08X, CR4 = %08X, DR6 = %08X, DR7 = %08X\n", cr0, cr3, cr4, dr[6], dr[7]); x386_common_log("EIP = %08X, EFLAGS = %04X%04X\n", cpu_state.pc, cpu_state.eflags, cpu_state.flags); x386_common_log("EAX = %08X, EBX = %08X, ECX = %08X, EDX = %08X, ESI = %08X, EDI = %08X, ESP = %08X, EBP = %08X\n", - EAX, EBX, ECX, EDX, ESI, EDI, ESP, EBP); + EAX, EBX, ECX, EDX, ESI, EDI, ESP, EBP); flags_rebuild(); in_smm = 1; @@ -1067,24 +1159,24 @@ enter_smm(int in_hlt) smram_recalc_all(0); if (is_cxsmm) { - if (!(cyrix.smhr & SMHR_VALID)) - cyrix.smhr = (cyrix.arr[3].base + cyrix.arr[3].size) | SMHR_VALID; - smram_state = cyrix.smhr & SMHR_ADDR_MASK; + if (!(cyrix.smhr & SMHR_VALID)) + cyrix.smhr = (cyrix.arr[3].base + cyrix.arr[3].size) | SMHR_VALID; + smram_state = cyrix.smhr & SMHR_ADDR_MASK; } memset(saved_state, 0x00, SMM_SAVE_STATE_MAP_SIZE * sizeof(uint32_t)); - if (is_cxsmm) /* Cx6x86 */ - smram_save_state_cyrix(saved_state, in_hlt); - else if (is_pentium || is_am486) /* Am486 / 5x86 / Intel P5 (Pentium) */ - smram_save_state_p5(saved_state, in_hlt); - else if (is_k5 || is_k6) /* AMD K5 and K6 */ - smram_save_state_amd_k(saved_state, in_hlt); - else if (is_p6) /* Intel P6 (Pentium Pro, Pentium II, Celeron) */ - smram_save_state_p6(saved_state, in_hlt); + if (is_cxsmm) /* Cx6x86 */ + smram_save_state_cyrix(saved_state, in_hlt); + else if (is_pentium || is_am486) /* Am486 / 5x86 / Intel P5 (Pentium) */ + smram_save_state_p5(saved_state, in_hlt); + else if (is_k5 || is_k6) /* AMD K5 and K6 */ + smram_save_state_amd_k(saved_state, in_hlt); + else if (is_p6) /* Intel P6 (Pentium Pro, Pentium II, Celeron) */ + smram_save_state_p6(saved_state, in_hlt); cr0 &= ~0x8000000d; - cpu_state.flags = 2; + cpu_state.flags = 2; cpu_state.eflags = 0; cr4 = 0; @@ -1092,170 +1184,173 @@ enter_smm(int in_hlt) dr[7] = 0x400; if (is_cxsmm) { - cpu_state.pc = 0x0000; - cpl_override = 1; - cyrix_write_seg_descriptor(smram_state - 0x20, &cpu_state.seg_cs); - cpl_override = 0; - cpu_state.seg_cs.seg = (cyrix.arr[3].base >> 4); - cpu_state.seg_cs.base = cyrix.arr[3].base; - cpu_state.seg_cs.limit = 0xffffffff; - cpu_state.seg_cs.access = 0x93; - cpu_state.seg_cs.ar_high = 0x80; - cpu_state.seg_cs.checked = 1; + cpu_state.pc = 0x0000; + cpl_override = 1; + if (is486) + cyrix_write_seg_descriptor(smram_state - 0x20, &cpu_state.seg_cs); + else + cyrix_write_seg_descriptor_2386(smram_state - 0x20, &cpu_state.seg_cs); + cpl_override = 0; + cpu_state.seg_cs.seg = (cyrix.arr[3].base >> 4); + cpu_state.seg_cs.base = cyrix.arr[3].base; + cpu_state.seg_cs.limit = 0xffffffff; + cpu_state.seg_cs.access = 0x93; + cpu_state.seg_cs.ar_high = 0x80; + cpu_state.seg_cs.checked = 1; - smm_seg_load(&cpu_state.seg_cs); + smm_seg_load(&cpu_state.seg_cs); } else { - cpu_state.pc = 0x8000; - cpu_state.seg_ds.seg = 0x00000000; - cpu_state.seg_ds.base = 0x00000000; - cpu_state.seg_ds.limit = 0xffffffff; - cpu_state.seg_ds.access = 0x93; - cpu_state.seg_ds.ar_high = 0x80; + cpu_state.pc = 0x8000; + cpu_state.seg_ds.seg = 0x00000000; + cpu_state.seg_ds.base = 0x00000000; + cpu_state.seg_ds.limit = 0xffffffff; + cpu_state.seg_ds.access = 0x93; + cpu_state.seg_ds.ar_high = 0x80; - memcpy(&cpu_state.seg_es, &cpu_state.seg_ds, sizeof(x86seg)); - memcpy(&cpu_state.seg_ss, &cpu_state.seg_ds, sizeof(x86seg)); - memcpy(&cpu_state.seg_fs, &cpu_state.seg_ds, sizeof(x86seg)); - memcpy(&cpu_state.seg_gs, &cpu_state.seg_ds, sizeof(x86seg)); + memcpy(&cpu_state.seg_es, &cpu_state.seg_ds, sizeof(x86seg)); + memcpy(&cpu_state.seg_ss, &cpu_state.seg_ds, sizeof(x86seg)); + memcpy(&cpu_state.seg_fs, &cpu_state.seg_ds, sizeof(x86seg)); + memcpy(&cpu_state.seg_gs, &cpu_state.seg_ds, sizeof(x86seg)); - if (is_p6) - cpu_state.seg_cs.seg = (smbase >> 4); - else - cpu_state.seg_cs.seg = 0x3000; + if (is_p6) + cpu_state.seg_cs.seg = (smbase >> 4); + else + cpu_state.seg_cs.seg = 0x3000; - /* On Pentium, CS selector in SMM is always 3000, regardless of SMBASE. */ - cpu_state.seg_cs.base = smbase; - cpu_state.seg_cs.limit = 0xffffffff; - cpu_state.seg_cs.access = 0x93; - cpu_state.seg_cs.ar_high = 0x80; - cpu_state.seg_cs.checked = 1; + /* On Pentium, CS selector in SMM is always 3000, regardless of SMBASE. */ + cpu_state.seg_cs.base = smbase; + cpu_state.seg_cs.limit = 0xffffffff; + cpu_state.seg_cs.access = 0x93; + cpu_state.seg_cs.ar_high = 0x80; + cpu_state.seg_cs.checked = 1; - smm_seg_load(&cpu_state.seg_es); - smm_seg_load(&cpu_state.seg_cs); - smm_seg_load(&cpu_state.seg_ds); - smm_seg_load(&cpu_state.seg_ss); - smm_seg_load(&cpu_state.seg_fs); - smm_seg_load(&cpu_state.seg_gs); + smm_seg_load(&cpu_state.seg_es); + smm_seg_load(&cpu_state.seg_cs); + smm_seg_load(&cpu_state.seg_ds); + smm_seg_load(&cpu_state.seg_ss); + smm_seg_load(&cpu_state.seg_fs); + smm_seg_load(&cpu_state.seg_gs); } cpu_state.op32 = use32; cpl_override = 1; if (is_cxsmm) { - writememl(0, smram_state - 0x04, saved_state[0]); - writememl(0, smram_state - 0x08, saved_state[1]); - writememl(0, smram_state - 0x0c, saved_state[2]); - writememl(0, smram_state - 0x10, saved_state[3]); - writememl(0, smram_state - 0x14, saved_state[4]); - writememl(0, smram_state - 0x18, saved_state[5]); - writememl(0, smram_state - 0x24, saved_state[6]); + writememl(0, smram_state - 0x04, saved_state[0]); + writememl(0, smram_state - 0x08, saved_state[1]); + writememl(0, smram_state - 0x0c, saved_state[2]); + writememl(0, smram_state - 0x10, saved_state[3]); + writememl(0, smram_state - 0x14, saved_state[4]); + writememl(0, smram_state - 0x18, saved_state[5]); + writememl(0, smram_state - 0x24, saved_state[6]); } else { - for (n = 0; n < SMM_SAVE_STATE_MAP_SIZE; n++) { - smram_state -= 4; - writememl(0, smram_state, saved_state[n]); - } + for (uint8_t n = 0; n < SMM_SAVE_STATE_MAP_SIZE; n++) { + smram_state -= 4; + writememl(0, smram_state, saved_state[n]); + } } cpl_override = 0; nmi_mask = 0; if (smi_latched) { - in_smm = 2; - smi_latched = 0; + in_smm = 2; + smi_latched = 0; } else - in_smm = 1; + in_smm = 1; smm_in_hlt = in_hlt; if (unmask_a20_in_smm) { - old_rammask = rammask; - rammask = cpu_16bitbus ? 0xFFFFFF : 0xFFFFFFFF; + old_rammask = rammask; + rammask = cpu_16bitbus ? 0xFFFFFF : 0xFFFFFFFF; + if (is6117) + rammask |= 0x3000000; - flushmmucache(); + flushmmucache(); } - + oldcpl = 0; cpu_cur_status &= ~(CPU_STATUS_PMODE | CPU_STATUS_V86); CPU_BLOCK_END(); } - void enter_smm_check(int in_hlt) { - if (smi_line && (cpu_fast_off_flags & 0x80000000)) - cpu_fast_off_count = cpu_fast_off_val + 1; - if ((in_smm == 0) && smi_line) { #ifdef ENABLE_386_COMMON_LOG - x386_common_log("SMI while not in SMM\n"); + x386_common_log("SMI while not in SMM\n"); #endif - enter_smm(in_hlt); + enter_smm(in_hlt); } else if ((in_smm == 1) && smi_line) { - /* Mark this so that we don't latch more than one SMI. */ + /* Mark this so that we don't latch more than one SMI. */ #ifdef ENABLE_386_COMMON_LOG - x386_common_log("SMI while in unlatched SMM\n"); + x386_common_log("SMI while in unlatched SMM\n"); #endif - smi_latched = 1; + smi_latched = 1; } else if ((in_smm == 2) && smi_line) { - /* Mark this so that we don't latch more than one SMI. */ + /* Mark this so that we don't latch more than one SMI. */ #ifdef ENABLE_386_COMMON_LOG - x386_common_log("SMI while in latched SMM\n"); + x386_common_log("SMI while in latched SMM\n"); #endif } if (smi_line) - smi_line = 0; + smi_line = 0; } - void leave_smm(void) { - uint32_t saved_state[SMM_SAVE_STATE_MAP_SIZE], n; + uint32_t saved_state[SMM_SAVE_STATE_MAP_SIZE]; uint32_t smram_state = smbase + 0x10000; /* If it's a CPU on which SMM is not supported (or not implemented in 86Box), do nothing. */ if (!is_am486 && !is_pentium && !is_k5 && !is_k6 && !is_p6 && !is_cxsmm) - return; + return; memset(saved_state, 0x00, SMM_SAVE_STATE_MAP_SIZE * sizeof(uint32_t)); cpl_override = 1; if (is_cxsmm) { - smram_state = cyrix.smhr & SMHR_ADDR_MASK; - saved_state[0] = readmeml(0, smram_state - 0x04); - saved_state[1] = readmeml(0, smram_state - 0x08); - saved_state[2] = readmeml(0, smram_state - 0x0c); - saved_state[3] = readmeml(0, smram_state - 0x10); - saved_state[4] = readmeml(0, smram_state - 0x14); - saved_state[5] = readmeml(0, smram_state - 0x18); - cyrix_load_seg_descriptor(smram_state - 0x20, &cpu_state.seg_cs); - saved_state[6] = readmeml(0, smram_state - 0x24); + smram_state = cyrix.smhr & SMHR_ADDR_MASK; + saved_state[0] = readmeml(0, smram_state - 0x04); + saved_state[1] = readmeml(0, smram_state - 0x08); + saved_state[2] = readmeml(0, smram_state - 0x0c); + saved_state[3] = readmeml(0, smram_state - 0x10); + saved_state[4] = readmeml(0, smram_state - 0x14); + saved_state[5] = readmeml(0, smram_state - 0x18); + if (is486) + cyrix_load_seg_descriptor(smram_state - 0x20, &cpu_state.seg_cs); + else + cyrix_load_seg_descriptor_2386(smram_state - 0x20, &cpu_state.seg_cs); + saved_state[6] = readmeml(0, smram_state - 0x24); } else { - for (n = 0; n < SMM_SAVE_STATE_MAP_SIZE; n++) { - smram_state -= 4; - saved_state[n] = readmeml(0, smram_state); - x386_common_log("Reading %08X from memory at %08X to array element %i\n", saved_state[n], smram_state, n); - } + for (uint8_t n = 0; n < SMM_SAVE_STATE_MAP_SIZE; n++) { + smram_state -= 4; + saved_state[n] = readmeml(0, smram_state); + x386_common_log("Reading %08X from memory at %08X to array element %i\n", saved_state[n], smram_state, n); + } } cpl_override = 0; if (unmask_a20_in_smm) { - rammask = old_rammask; + rammask = old_rammask; - flushmmucache(); + flushmmucache(); } x386_common_log("New SMBASE: %08X (%08X)\n", saved_state[SMRAM_FIELD_P5_SMBASE_OFFSET], saved_state[66]); - if (is_cxsmm) /* Cx6x86 */ - smram_restore_state_cyrix(saved_state); - else if (is_pentium || is_am486) /* Am486 / 5x86 / Intel P5 (Pentium) */ - smram_restore_state_p5(saved_state); - else if (is_k5 || is_k6) /* AMD K5 and K6 */ - smram_restore_state_amd_k(saved_state); - else if (is_p6) /* Intel P6 (Pentium Pro, Pentium II, Celeron) */ - smram_restore_state_p6(saved_state); + if (is_cxsmm) /* Cx6x86 */ + smram_restore_state_cyrix(saved_state); + else if (is_pentium || is_am486) /* Am486 / 5x86 / Intel P5 (Pentium) */ + smram_restore_state_p5(saved_state); + else if (is_k5 || is_k6) /* AMD K5 and K6 */ + smram_restore_state_amd_k(saved_state); + else if (is_p6) /* Intel P6 (Pentium Pro, Pentium II, Celeron) */ + smram_restore_state_p6(saved_state); in_smm = 0; smram_recalc_all(1); @@ -1263,9 +1358,9 @@ leave_smm(void) cpu_386_flags_extract(); cpu_cur_status &= ~(CPU_STATUS_PMODE | CPU_STATUS_V86); if (cr0 & 1) { - cpu_cur_status |= CPU_STATUS_PMODE; - if (cpu_state.eflags & VM_FLAG) - cpu_cur_status |= CPU_STATUS_V86; + cpu_cur_status |= CPU_STATUS_PMODE; + if (cpu_state.eflags & VM_FLAG) + cpu_cur_status |= CPU_STATUS_V86; } nmi_mask = 1; @@ -1275,90 +1370,88 @@ leave_smm(void) CPU_BLOCK_END(); x386_common_log("CS : seg = %04X, base = %08X, limit = %08X, limit_low = %08X, limit_high = %08X, access = %02X, ar_high = %02X\n", - cpu_state.seg_cs.seg, cpu_state.seg_cs.base, cpu_state.seg_cs.limit, cpu_state.seg_cs.limit_low, - cpu_state.seg_cs.limit_high, cpu_state.seg_cs.access, cpu_state.seg_cs.ar_high); + cpu_state.seg_cs.seg, cpu_state.seg_cs.base, cpu_state.seg_cs.limit, cpu_state.seg_cs.limit_low, + cpu_state.seg_cs.limit_high, cpu_state.seg_cs.access, cpu_state.seg_cs.ar_high); x386_common_log("DS : seg = %04X, base = %08X, limit = %08X, limit_low = %08X, limit_high = %08X, access = %02X, ar_high = %02X\n", - cpu_state.seg_ds.seg, cpu_state.seg_ds.base, cpu_state.seg_ds.limit, cpu_state.seg_ds.limit_low, - cpu_state.seg_ds.limit_high, cpu_state.seg_ds.access, cpu_state.seg_ds.ar_high); + cpu_state.seg_ds.seg, cpu_state.seg_ds.base, cpu_state.seg_ds.limit, cpu_state.seg_ds.limit_low, + cpu_state.seg_ds.limit_high, cpu_state.seg_ds.access, cpu_state.seg_ds.ar_high); x386_common_log("ES : seg = %04X, base = %08X, limit = %08X, limit_low = %08X, limit_high = %08X, access = %02X, ar_high = %02X\n", - cpu_state.seg_es.seg, cpu_state.seg_es.base, cpu_state.seg_es.limit, cpu_state.seg_es.limit_low, - cpu_state.seg_es.limit_high, cpu_state.seg_es.access, cpu_state.seg_es.ar_high); + cpu_state.seg_es.seg, cpu_state.seg_es.base, cpu_state.seg_es.limit, cpu_state.seg_es.limit_low, + cpu_state.seg_es.limit_high, cpu_state.seg_es.access, cpu_state.seg_es.ar_high); x386_common_log("FS : seg = %04X, base = %08X, limit = %08X, limit_low = %08X, limit_high = %08X, access = %02X, ar_high = %02X\n", - cpu_state.seg_fs.seg, cpu_state.seg_fs.base, cpu_state.seg_fs.limit, cpu_state.seg_fs.limit_low, - cpu_state.seg_fs.limit_high, cpu_state.seg_fs.access, cpu_state.seg_fs.ar_high); + cpu_state.seg_fs.seg, cpu_state.seg_fs.base, cpu_state.seg_fs.limit, cpu_state.seg_fs.limit_low, + cpu_state.seg_fs.limit_high, cpu_state.seg_fs.access, cpu_state.seg_fs.ar_high); x386_common_log("GS : seg = %04X, base = %08X, limit = %08X, limit_low = %08X, limit_high = %08X, access = %02X, ar_high = %02X\n", - cpu_state.seg_gs.seg, cpu_state.seg_gs.base, cpu_state.seg_gs.limit, cpu_state.seg_gs.limit_low, - cpu_state.seg_gs.limit_high, cpu_state.seg_gs.access, cpu_state.seg_gs.ar_high); + cpu_state.seg_gs.seg, cpu_state.seg_gs.base, cpu_state.seg_gs.limit, cpu_state.seg_gs.limit_low, + cpu_state.seg_gs.limit_high, cpu_state.seg_gs.access, cpu_state.seg_gs.ar_high); x386_common_log("SS : seg = %04X, base = %08X, limit = %08X, limit_low = %08X, limit_high = %08X, access = %02X, ar_high = %02X\n", - cpu_state.seg_ss.seg, cpu_state.seg_ss.base, cpu_state.seg_ss.limit, cpu_state.seg_ss.limit_low, - cpu_state.seg_ss.limit_high, cpu_state.seg_ss.access, cpu_state.seg_ss.ar_high); + cpu_state.seg_ss.seg, cpu_state.seg_ss.base, cpu_state.seg_ss.limit, cpu_state.seg_ss.limit_low, + cpu_state.seg_ss.limit_high, cpu_state.seg_ss.access, cpu_state.seg_ss.ar_high); x386_common_log("TR : seg = %04X, base = %08X, limit = %08X, limit_low = %08X, limit_high = %08X, access = %02X, ar_high = %02X\n", - tr.seg, tr.base, tr.limit, tr.limit_low, tr.limit_high, tr.access, tr.ar_high); + tr.seg, tr.base, tr.limit, tr.limit_low, tr.limit_high, tr.access, tr.ar_high); x386_common_log("LDT: seg = %04X, base = %08X, limit = %08X, limit_low = %08X, limit_high = %08X, access = %02X, ar_high = %02X\n", - ldt.seg, ldt.base, ldt.limit, ldt.limit_low, ldt.limit_high, ldt.access, ldt.ar_high); + ldt.seg, ldt.base, ldt.limit, ldt.limit_low, ldt.limit_high, ldt.access, ldt.ar_high); x386_common_log("GDT: seg = %04X, base = %08X, limit = %08X, limit_low = %08X, limit_high = %08X, access = %02X, ar_high = %02X\n", - gdt.seg, gdt.base, gdt.limit, gdt.limit_low, gdt.limit_high, gdt.access, gdt.ar_high); + gdt.seg, gdt.base, gdt.limit, gdt.limit_low, gdt.limit_high, gdt.access, gdt.ar_high); x386_common_log("IDT: seg = %04X, base = %08X, limit = %08X, limit_low = %08X, limit_high = %08X, access = %02X, ar_high = %02X\n", - idt.seg, idt.base, idt.limit, idt.limit_low, idt.limit_high, idt.access, idt.ar_high); + idt.seg, idt.base, idt.limit, idt.limit_low, idt.limit_high, idt.access, idt.ar_high); x386_common_log("CR0 = %08X, CR3 = %08X, CR4 = %08X, DR6 = %08X, DR7 = %08X\n", cr0, cr3, cr4, dr[6], dr[7]); x386_common_log("EIP = %08X, EFLAGS = %04X%04X\n", cpu_state.pc, cpu_state.eflags, cpu_state.flags); x386_common_log("EAX = %08X, EBX = %08X, ECX = %08X, EDX = %08X, ESI = %08X, EDI = %08X, ESP = %08X, EBP = %08X\n", - EAX, EBX, ECX, EDX, ESI, EDI, ESP, EBP); + EAX, EBX, ECX, EDX, ESI, EDI, ESP, EBP); x386_common_log("leave_smm()\n"); } - void x86_int(int num) { uint32_t addr; flags_rebuild(); - cpu_state.pc=cpu_state.oldpc; + cpu_state.pc = cpu_state.oldpc; - if (msw&1) - pmodeint(num,0); + if (msw & 1) + is486 ? pmodeint(num, 0) : pmodeint_2386(num, 0); else { - addr = (num << 2) + idt.base; + addr = (num << 2) + idt.base; - if ((num << 2UL) + 3UL > idt.limit) { - if (idt.limit < 35) { - cpu_state.abrt = 0; - softresetx86(); - cpu_set_edx(); + if ((num << 2UL) + 3UL > idt.limit) { + if (idt.limit < 35) { + cpu_state.abrt = 0; + softresetx86(); + cpu_set_edx(); #ifdef ENABLE_386_COMMON_LOG - x386_common_log("Triple fault in real mode - reset\n"); + x386_common_log("Triple fault in real mode - reset\n"); #endif - } else - x86_int(8); - } else { - if (stack32) { - writememw(ss, ESP - 2, cpu_state.flags); - writememw(ss, ESP - 4, CS); - writememw(ss, ESP - 6, cpu_state.pc); - ESP -= 6; - } else { - writememw(ss, ((SP - 2) & 0xFFFF), cpu_state.flags); - writememw(ss, ((SP - 4) & 0xFFFF), CS); - writememw(ss, ((SP - 6) & 0xFFFF), cpu_state.pc); - SP -= 6; - } + } else + x86_int(8); + } else { + if (stack32) { + writememw(ss, ESP - 2, cpu_state.flags); + writememw(ss, ESP - 4, CS); + writememw(ss, ESP - 6, cpu_state.pc); + ESP -= 6; + } else { + writememw(ss, ((SP - 2) & 0xFFFF), cpu_state.flags); + writememw(ss, ((SP - 4) & 0xFFFF), CS); + writememw(ss, ((SP - 6) & 0xFFFF), cpu_state.pc); + SP -= 6; + } - cpu_state.flags &= ~I_FLAG; - cpu_state.flags &= ~T_FLAG; + cpu_state.flags &= ~I_FLAG; + cpu_state.flags &= ~T_FLAG; #ifndef USE_NEW_DYNAREC - oxpc = cpu_state.pc; + oxpc = cpu_state.pc; #endif - cpu_state.pc = readmemw(0, addr); - loadcs(readmemw(0, addr + 2)); - } + cpu_state.pc = readmemw(0, addr); + is486 ? loadcs(readmemw(0, addr + 2)) : loadcs_2386(readmemw(0, addr + 2)); + } } cycles -= 70; CPU_BLOCK_END(); } - void x86_int_sw(int num) { @@ -1367,75 +1460,75 @@ x86_int_sw(int num) flags_rebuild(); cycles -= timing_int; - if (msw&1) - pmodeint(num,1); + if (msw & 1) + is486 ? pmodeint(num, 1) : pmodeint_2386(num, 1); else { - addr = (num << 2) + idt.base; + addr = (num << 2) + idt.base; - if ((num << 2UL) + 3UL > idt.limit) - x86_int(0x0d); - else { - if (stack32) { - writememw(ss, ESP - 2, cpu_state.flags); - writememw(ss, ESP - 4, CS); - writememw(ss, ESP - 6, cpu_state.pc); - ESP -= 6; - } else { - writememw(ss, ((SP - 2) & 0xFFFF), cpu_state.flags); - writememw(ss, ((SP - 4) & 0xFFFF), CS); - writememw(ss, ((SP - 6) & 0xFFFF), cpu_state.pc); - SP -= 6; - } + if ((num << 2UL) + 3UL > idt.limit) + x86_int(0x0d); + else { + if (stack32) { + writememw(ss, ESP - 2, cpu_state.flags); + writememw(ss, ESP - 4, CS); + writememw(ss, ESP - 6, cpu_state.pc); + ESP -= 6; + } else { + writememw(ss, ((SP - 2) & 0xFFFF), cpu_state.flags); + writememw(ss, ((SP - 4) & 0xFFFF), CS); + writememw(ss, ((SP - 6) & 0xFFFF), cpu_state.pc); + SP -= 6; + } - cpu_state.flags &= ~I_FLAG; - cpu_state.flags &= ~T_FLAG; + cpu_state.flags &= ~I_FLAG; + cpu_state.flags &= ~T_FLAG; #ifndef USE_NEW_DYNAREC - oxpc = cpu_state.pc; + oxpc = cpu_state.pc; #endif - cpu_state.pc = readmemw(0, addr); - loadcs(readmemw(0, addr + 2)); - cycles -= timing_int_rm; - } + cpu_state.pc = readmemw(0, addr); + is486 ? loadcs(readmemw(0, addr + 2)) : loadcs_2386(readmemw(0, addr + 2)); + cycles -= timing_int_rm; + } } trap = 0; CPU_BLOCK_END(); } - int x86_int_sw_rm(int num) { uint32_t addr; - uint16_t new_pc, new_cs; + uint16_t new_pc; + uint16_t new_cs; flags_rebuild(); cycles -= timing_int; - addr = num << 2; + addr = num << 2; new_pc = readmemw(0, addr); new_cs = readmemw(0, addr + 2); if (cpu_state.abrt) - return 1; + return 1; writememw(ss, ((SP - 2) & 0xFFFF), cpu_state.flags); if (cpu_state.abrt) - return 1; + return 1; writememw(ss, ((SP - 4) & 0xFFFF), CS); writememw(ss, ((SP - 6) & 0xFFFF), cpu_state.pc); if (cpu_state.abrt) - return 1; + return 1; SP -= 6; cpu_state.eflags &= ~VIF_FLAG; cpu_state.flags &= ~T_FLAG; cpu_state.pc = new_pc; - loadcs(new_cs); + is486 ? loadcs(new_cs) : loadcs_2386(new_cs); #ifndef USE_NEW_DYNAREC oxpc = cpu_state.pc; #endif @@ -1447,62 +1540,72 @@ x86_int_sw_rm(int num) return 0; } - void -x86illegal() +x86illegal(void) { x86_int(6); } - int -checkio(uint32_t port) +checkio(uint32_t port, int mask) { - uint16_t t; - uint8_t d; + uint32_t t; cpl_override = 1; - t = readmemw(tr.base, 0x66); + t = readmemw(tr.base, 0x66); + + if (UNLIKELY(cpu_state.abrt)) { + cpl_override = 0; + return 0; + } + + t += (port >> 3UL); + mask <<= (port & 7); + if (UNLIKELY(mask & 0xff00)) { + if (LIKELY(t < tr.limit)) + mask &= readmemwl(tr.base + t); + } else { + if (LIKELY(t <= tr.limit)) + mask &= readmembl(tr.base + t); + } cpl_override = 0; - - if (cpu_state.abrt) - return 0; - - if ((t + (port >> 3UL)) > tr.limit) - return 1; - - cpl_override = 1; - d = readmembl(tr.base + t + (port >> 3)); - cpl_override = 0; - return d & (1 << (port & 7)); -} - - -#define divexcp() { \ - x386_common_log("Divide exception at %04X(%06X):%04X\n",CS,cs,cpu_state.pc); \ - x86_int(0); \ + return mask; } +#ifdef OLD_DIVEXCP +# define divexcp() \ + { \ + x386_common_log("Divide exception at %04X(%06X):%04X\n", CS, cs, cpu_state.pc); \ + x86_int(0); \ + } +#else +# define divexcp() \ + { \ + x86de(NULL, 0); \ + } +#endif int divl(uint32_t val) { - uint64_t num, quo; - uint32_t rem, quo32; + uint64_t num; + uint64_t quo; + uint32_t rem; + uint32_t quo32; if (val == 0) { - divexcp(); - return 1; + divexcp(); + return 1; } - num = (((uint64_t) EDX) << 32) | EAX; - quo = num / val; - rem = num % val; - quo32=(uint32_t)(quo&0xFFFFFFFF); + num = (((uint64_t) EDX) << 32) | EAX; + quo = num / val; + rem = num % val; + quo32 = (uint32_t) (quo & 0xFFFFFFFF); if (quo != (uint64_t) quo32) { - divexcp(); - return 1; + divexcp(); + return 1; } EDX = rem; @@ -1511,26 +1614,27 @@ divl(uint32_t val) return 0; } - int idivl(int32_t val) { - int64_t num, quo; - int32_t rem, quo32; + int64_t num; + int64_t quo; + int32_t rem; + int32_t quo32; - if (val == 0) { - divexcp(); - return 1; + if (val == 0) { + divexcp(); + return 1; } - num = (((uint64_t) EDX) << 32) | EAX; - quo = num / val; - rem = num % val; + num = (((uint64_t) EDX) << 32) | EAX; + quo = num / val; + rem = num % val; quo32 = (int32_t) (quo & 0xFFFFFFFF); if (quo != (int64_t) quo32) { - divexcp(); - return 1; + divexcp(); + return 1; } EDX = rem; @@ -1539,21 +1643,18 @@ idivl(int32_t val) return 0; } - void -cpu_386_flags_extract() +cpu_386_flags_extract(void) { flags_extract(); } - void -cpu_386_flags_rebuild() +cpu_386_flags_rebuild(void) { flags_rebuild(); } - int sysenter(uint32_t fetchdat) { @@ -1563,18 +1664,18 @@ sysenter(uint32_t fetchdat) if (!(msw & 1)) { #ifdef ENABLE_386_COMMON_LOG - x386_common_log("SYSENTER: CPU not in protected mode"); + x386_common_log("SYSENTER: CPU not in protected mode"); #endif - x86gpf("SYSENTER: CPU not in protected mode", 0); - return cpu_state.abrt; + x86gpf("SYSENTER: CPU not in protected mode", 0); + return cpu_state.abrt; } if (!(msr.sysenter_cs & 0xFFF8)) { #ifdef ENABLE_386_COMMON_LOG - x386_common_log("SYSENTER: CS MSR is zero"); + x386_common_log("SYSENTER: CS MSR is zero"); #endif - x86gpf("SYSENTER: CS MSR is zero", 0); - return cpu_state.abrt; + x86gpf("SYSENTER: CS MSR is zero", 0); + return cpu_state.abrt; } #ifdef ENABLE_386_COMMON_LOG @@ -1593,33 +1694,33 @@ sysenter(uint32_t fetchdat) oldcs = CS; #endif cpu_state.oldpc = cpu_state.pc; - ESP = msr.sysenter_esp; - cpu_state.pc = msr.sysenter_eip; + ESP = msr.sysenter_esp; + cpu_state.pc = msr.sysenter_eip; - cpu_state.seg_cs.seg = (msr.sysenter_cs & 0xfffc); - cpu_state.seg_cs.base = 0; - cpu_state.seg_cs.limit_low = 0; - cpu_state.seg_cs.limit = 0xffffffff; + cpu_state.seg_cs.seg = (msr.sysenter_cs & 0xfffc); + cpu_state.seg_cs.base = 0; + cpu_state.seg_cs.limit_low = 0; + cpu_state.seg_cs.limit = 0xffffffff; cpu_state.seg_cs.limit_high = 0xffffffff; - cpu_state.seg_cs.access = 0x9b; - cpu_state.seg_cs.ar_high = 0xcf; - cpu_state.seg_cs.checked = 1; - oldcpl = 0; + cpu_state.seg_cs.access = 0x9b; + cpu_state.seg_cs.ar_high = 0xcf; + cpu_state.seg_cs.checked = 1; + oldcpl = 0; - cpu_state.seg_ss.seg = ((msr.sysenter_cs + 8) & 0xfffc); - cpu_state.seg_ss.base = 0; - cpu_state.seg_ss.limit_low = 0; - cpu_state.seg_ss.limit = 0xffffffff; + cpu_state.seg_ss.seg = ((msr.sysenter_cs + 8) & 0xfffc); + cpu_state.seg_ss.base = 0; + cpu_state.seg_ss.limit_low = 0; + cpu_state.seg_ss.limit = 0xffffffff; cpu_state.seg_ss.limit_high = 0xffffffff; - cpu_state.seg_ss.access = 0x93; - cpu_state.seg_ss.ar_high = 0xcf; - cpu_state.seg_ss.checked = 1; + cpu_state.seg_ss.access = 0x93; + cpu_state.seg_ss.ar_high = 0xcf; + cpu_state.seg_ss.checked = 1; #ifdef USE_DYNAREC codegen_flat_ss = 0; #endif cpu_cur_status &= ~(CPU_STATUS_NOTFLATSS | CPU_STATUS_V86); - cpu_cur_status |= (CPU_STATUS_USE32 | CPU_STATUS_STACK32/* | CPU_STATUS_PMODE*/); + cpu_cur_status |= (CPU_STATUS_USE32 | CPU_STATUS_STACK32 /* | CPU_STATUS_PMODE*/); set_use32(1); set_stack32(1); @@ -1636,7 +1737,6 @@ sysenter(uint32_t fetchdat) return 1; } - int sysexit(uint32_t fetchdat) { @@ -1646,26 +1746,26 @@ sysexit(uint32_t fetchdat) if (!(msr.sysenter_cs & 0xFFF8)) { #ifdef ENABLE_386_COMMON_LOG - x386_common_log("SYSEXIT: CS MSR is zero"); + x386_common_log("SYSEXIT: CS MSR is zero"); #endif - x86gpf("SYSEXIT: CS MSR is zero", 0); - return cpu_state.abrt; + x86gpf("SYSEXIT: CS MSR is zero", 0); + return cpu_state.abrt; } if (!(msw & 1)) { #ifdef ENABLE_386_COMMON_LOG - x386_common_log("SYSEXIT: CPU not in protected mode"); + x386_common_log("SYSEXIT: CPU not in protected mode"); #endif - x86gpf("SYSEXIT: CPU not in protected mode", 0); - return cpu_state.abrt; + x86gpf("SYSEXIT: CPU not in protected mode", 0); + return cpu_state.abrt; } if (CPL) { #ifdef ENABLE_386_COMMON_LOG - x386_common_log("SYSEXIT: CPL not 0"); + x386_common_log("SYSEXIT: CPL not 0"); #endif - x86gpf("SYSEXIT: CPL not 0", 0); - return cpu_state.abrt; + x86gpf("SYSEXIT: CPL not 0", 0); + return cpu_state.abrt; } #ifdef ENABLE_386_COMMON_LOG @@ -1680,34 +1780,34 @@ sysexit(uint32_t fetchdat) oldcs = CS; #endif cpu_state.oldpc = cpu_state.pc; - ESP = ECX; - cpu_state.pc = EDX; + ESP = ECX; + cpu_state.pc = EDX; - cpu_state.seg_cs.seg = (((msr.sysenter_cs + 16) & 0xfffc) | 3); - cpu_state.seg_cs.base = 0; - cpu_state.seg_cs.limit_low = 0; - cpu_state.seg_cs.limit = 0xffffffff; + cpu_state.seg_cs.seg = (((msr.sysenter_cs + 16) & 0xfffc) | 3); + cpu_state.seg_cs.base = 0; + cpu_state.seg_cs.limit_low = 0; + cpu_state.seg_cs.limit = 0xffffffff; cpu_state.seg_cs.limit_high = 0xffffffff; - cpu_state.seg_cs.access = 0xfb; - cpu_state.seg_cs.ar_high = 0xcf; - cpu_state.seg_cs.checked = 1; - oldcpl = 3; + cpu_state.seg_cs.access = 0xfb; + cpu_state.seg_cs.ar_high = 0xcf; + cpu_state.seg_cs.checked = 1; + oldcpl = 3; - cpu_state.seg_ss.seg = (((msr.sysenter_cs + 24) & 0xfffc) | 3); - cpu_state.seg_ss.base = 0; - cpu_state.seg_ss.limit_low = 0; - cpu_state.seg_ss.limit = 0xffffffff; + cpu_state.seg_ss.seg = (((msr.sysenter_cs + 24) & 0xfffc) | 3); + cpu_state.seg_ss.base = 0; + cpu_state.seg_ss.limit_low = 0; + cpu_state.seg_ss.limit = 0xffffffff; cpu_state.seg_ss.limit_high = 0xffffffff; - cpu_state.seg_ss.access = 0xf3; - cpu_state.seg_ss.ar_high = 0xcf; - cpu_state.seg_ss.checked = 1; + cpu_state.seg_ss.access = 0xf3; + cpu_state.seg_ss.ar_high = 0xcf; + cpu_state.seg_ss.checked = 1; #ifdef USE_DYNAREC codegen_flat_ss = 0; #endif - cpu_cur_status &= ~(CPU_STATUS_NOTFLATSS/* | CPU_STATUS_V86*/); + cpu_cur_status &= ~(CPU_STATUS_NOTFLATSS /* | CPU_STATUS_V86*/); cpu_cur_status |= (CPU_STATUS_USE32 | CPU_STATUS_STACK32 | CPU_STATUS_PMODE); - flushmmucache_cr3(); + flushmmucache_nopc(); set_use32(1); set_stack32(1); @@ -1724,7 +1824,6 @@ sysexit(uint32_t fetchdat) return 1; } - int syscall_op(uint32_t fetchdat) { @@ -1741,28 +1840,28 @@ syscall_op(uint32_t fetchdat) oldcs = CS; #endif cpu_state.oldpc = cpu_state.pc; - ECX = cpu_state.pc; + ECX = cpu_state.pc; /* CS */ - CS = AMD_SYSCALL_SB & 0xfffc; - cpu_state.seg_cs.base = 0; - cpu_state.seg_cs.limit_low = 0; - cpu_state.seg_cs.limit = 0xffffffff; + CS = AMD_SYSCALL_SB & 0xfffc; + cpu_state.seg_cs.base = 0; + cpu_state.seg_cs.limit_low = 0; + cpu_state.seg_cs.limit = 0xffffffff; cpu_state.seg_cs.limit_high = 0xffffffff; - cpu_state.seg_cs.access = 0x9b; - cpu_state.seg_cs.ar_high = 0xcf; - cpu_state.seg_cs.checked = 1; - oldcpl = 0; + cpu_state.seg_cs.access = 0x9b; + cpu_state.seg_cs.ar_high = 0xcf; + cpu_state.seg_cs.checked = 1; + oldcpl = 0; /* SS */ - SS = (AMD_SYSCALL_SB + 8) & 0xfffc; - cpu_state.seg_ss.base = 0; - cpu_state.seg_ss.limit_low = 0; - cpu_state.seg_ss.limit = 0xffffffff; + SS = (AMD_SYSCALL_SB + 8) & 0xfffc; + cpu_state.seg_ss.base = 0; + cpu_state.seg_ss.limit_low = 0; + cpu_state.seg_ss.limit = 0xffffffff; cpu_state.seg_ss.limit_high = 0xffffffff; - cpu_state.seg_ss.access = 0x93; - cpu_state.seg_ss.ar_high = 0xcf; - cpu_state.seg_ss.checked = 1; + cpu_state.seg_ss.access = 0x93; + cpu_state.seg_ss.ar_high = 0xcf; + cpu_state.seg_ss.checked = 1; #ifdef USE_DYNAREC codegen_flat_ss = 0; #endif @@ -1777,7 +1876,6 @@ syscall_op(uint32_t fetchdat) return 1; } - int sysret(uint32_t fetchdat) { @@ -1787,10 +1885,10 @@ sysret(uint32_t fetchdat) if (CPL) { #ifdef ENABLE_386_COMMON_LOG - x386_common_log("SYSRET: CPL not 0"); + x386_common_log("SYSRET: CPL not 0"); #endif - x86gpf("SYSRET: CPL not 0", 0); - return cpu_state.abrt; + x86gpf("SYSRET: CPL not 0", 0); + return cpu_state.abrt; } cpu_state.flags |= I_FLAG; @@ -1802,35 +1900,35 @@ sysret(uint32_t fetchdat) oldcs = CS; #endif cpu_state.oldpc = cpu_state.pc; - cpu_state.pc = ECX; + cpu_state.pc = ECX; /* CS */ - CS = (AMD_SYSRET_SB & 0xfffc) | 3; - cpu_state.seg_cs.base = 0; - cpu_state.seg_cs.limit_low = 0; - cpu_state.seg_cs.limit = 0xffffffff; + CS = (AMD_SYSRET_SB & 0xfffc) | 3; + cpu_state.seg_cs.base = 0; + cpu_state.seg_cs.limit_low = 0; + cpu_state.seg_cs.limit = 0xffffffff; cpu_state.seg_cs.limit_high = 0xffffffff; - cpu_state.seg_cs.access = 0xfb; - cpu_state.seg_cs.ar_high = 0xcf; - cpu_state.seg_cs.checked = 1; - oldcpl = 3; + cpu_state.seg_cs.access = 0xfb; + cpu_state.seg_cs.ar_high = 0xcf; + cpu_state.seg_cs.checked = 1; + oldcpl = 3; /* SS */ - SS = ((AMD_SYSRET_SB + 8) & 0xfffc) | 3; - cpu_state.seg_ss.base = 0; - cpu_state.seg_ss.limit_low = 0; - cpu_state.seg_ss.limit = 0xffffffff; + SS = ((AMD_SYSRET_SB + 8) & 0xfffc) | 3; + cpu_state.seg_ss.base = 0; + cpu_state.seg_ss.limit_low = 0; + cpu_state.seg_ss.limit = 0xffffffff; cpu_state.seg_ss.limit_high = 0xffffffff; - cpu_state.seg_ss.access = 0xf3; - cpu_state.seg_cs.ar_high = 0xcf; - cpu_state.seg_ss.checked = 1; + cpu_state.seg_ss.access = 0xf3; + cpu_state.seg_cs.ar_high = 0xcf; + cpu_state.seg_ss.checked = 1; #ifdef USE_DYNAREC codegen_flat_ss = 0; #endif - cpu_cur_status &= ~(CPU_STATUS_NOTFLATSS/* | CPU_STATUS_V86*/); + cpu_cur_status &= ~(CPU_STATUS_NOTFLATSS /* | CPU_STATUS_V86*/); cpu_cur_status |= (CPU_STATUS_USE32 | CPU_STATUS_STACK32 | CPU_STATUS_PMODE); - flushmmucache_cr3(); + flushmmucache_nopc(); set_use32(1); set_stack32(1); @@ -1839,11 +1937,58 @@ sysret(uint32_t fetchdat) return 1; } +void +cpu_register_fast_off_handler(void *timer) +{ + cpu_fast_off_timer = (pc_timer_t *) timer; +} + +void +cpu_fast_off_advance(void) +{ + timer_disable(cpu_fast_off_timer); + if (cpu_fast_off_period != 0.0) + timer_on_auto(cpu_fast_off_timer, cpu_fast_off_period); +} + +void +cpu_fast_off_period_set(uint16_t val, double period) +{ + cpu_fast_off_period = ((double) (val + 1)) * period; + cpu_fast_off_advance(); +} + +void +cpu_fast_off_reset(void) +{ + cpu_register_fast_off_handler(NULL); + cpu_fast_off_period = 0.0; + cpu_fast_off_advance(); +} + +void +smi_raise(void) +{ + if (is486 && (cpu_fast_off_flags & 0x80000000)) + cpu_fast_off_advance(); + + smi_line = 1; +} + +void +nmi_raise(void) +{ + if (is486 && (cpu_fast_off_flags & 0x20000000)) + cpu_fast_off_advance(); + + nmi = 1; +} #ifndef USE_DYNAREC /* This is for compatibility with new x87 code. */ -void codegen_set_rounding_mode(int mode) +void +codegen_set_rounding_mode(int mode) { - /* cpu_state.new_npxc = (cpu_state.old_npxc & ~0xc00) | (mode << 10); */ + /* cpu_state.new_npxc = (cpu_state.old_npxc & ~0xc00) | (mode << 10); */ } #endif diff --git a/src/cpu/386_common.h b/src/cpu/386_common.h index d9201f997..22fbd4bff 100644 --- a/src/cpu/386_common.h +++ b/src/cpu/386_common.h @@ -1,327 +1,676 @@ /* - * 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. + * 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. + * This file is part of the 86Box distribution. * - * Common 386 CPU code. + * Common 386 CPU code. * * * - * Author: Sarah Walker, - * Miran Grca, - * Copyright 2008-2019 Sarah Walker. - * Copyright 2016-2019 Miran Grca. + * Authors: Sarah Walker, + * Miran Grca, + * + * Copyright 2008-2019 Sarah Walker. + * Copyright 2016-2019 Miran Grca. */ #ifndef _386_COMMON_H_ #define _386_COMMON_H_ #include +#include -#define readmemb_n(s,a,b) ((readlookup2[(uint32_t)((s)+(a))>>12]==(uintptr_t)LOOKUP_INV || (s)==0xFFFFFFFF)?readmembl_no_mmut((s)+(a),b): *(uint8_t *)(readlookup2[(uint32_t)((s)+(a))>>12] + (uintptr_t)((s) + (a))) ) -#define readmemw_n(s,a,b) ((readlookup2[(uint32_t)((s)+(a))>>12]==(uintptr_t)LOOKUP_INV || (s)==0xFFFFFFFF || (((s)+(a)) & 1))?readmemwl_no_mmut((s)+(a),b):*(uint16_t *)(readlookup2[(uint32_t)((s)+(a))>>12]+(uint32_t)((s)+(a)))) -#define readmeml_n(s,a,b) ((readlookup2[(uint32_t)((s)+(a))>>12]==(uintptr_t)LOOKUP_INV || (s)==0xFFFFFFFF || (((s)+(a)) & 3))?readmemll_no_mmut((s)+(a),b):*(uint32_t *)(readlookup2[(uint32_t)((s)+(a))>>12]+(uint32_t)((s)+(a)))) -#define readmemb(s,a) ((readlookup2[(uint32_t)((s)+(a))>>12]==(uintptr_t)LOOKUP_INV || (s)==0xFFFFFFFF)?readmembl((s)+(a)): *(uint8_t *)(readlookup2[(uint32_t)((s)+(a))>>12] + (uintptr_t)((s) + (a))) ) -#define readmemw(s,a) ((readlookup2[(uint32_t)((s)+(a))>>12]==(uintptr_t)LOOKUP_INV || (s)==0xFFFFFFFF || (((s)+(a)) & 1))?readmemwl((s)+(a)):*(uint16_t *)(readlookup2[(uint32_t)((s)+(a))>>12]+(uint32_t)((s)+(a)))) -#define readmeml(s,a) ((readlookup2[(uint32_t)((s)+(a))>>12]==(uintptr_t)LOOKUP_INV || (s)==0xFFFFFFFF || (((s)+(a)) & 3))?readmemll((s)+(a)):*(uint32_t *)(readlookup2[(uint32_t)((s)+(a))>>12]+(uint32_t)((s)+(a)))) -#define readmemq(s,a) ((readlookup2[(uint32_t)((s)+(a))>>12]==(uintptr_t)LOOKUP_INV || (s)==0xFFFFFFFF || (((s)+(a)) & 7))?readmemql((s)+(a)):*(uint64_t *)(readlookup2[(uint32_t)((s)+(a))>>12]+(uintptr_t)((s)+(a)))) +#ifdef OPS_286_386 +# define readmemb_n(s, a, b) readmembl_no_mmut_2386((s) + (a), b) +# define readmemw_n(s, a, b) readmemwl_no_mmut_2386((s) + (a), b) +# define readmeml_n(s, a, b) readmemll_no_mmut_2386((s) + (a), b) +# define readmemb(s, a) readmembl_2386((s) + (a)) +# define readmemw(s, a) readmemwl_2386((s) + (a)) +# define readmeml(s, a) readmemll_2386((s) + (a)) +# define readmemq(s, a) readmemql_2386((s) + (a)) -#define writememb_n(s,a,b,v) if (writelookup2[(uint32_t)((s)+(a))>>12]==(uintptr_t)LOOKUP_INV || (s)==0xFFFFFFFF) writemembl_no_mmut((s)+(a),b,v); else *(uint8_t *)(writelookup2[(uint32_t)((s) + (a)) >> 12] + (uintptr_t)((s) + (a))) = v -#define writememw_n(s,a,b,v) if (writelookup2[(uint32_t)((s)+(a))>>12]==(uintptr_t)LOOKUP_INV || (s)==0xFFFFFFFF || (((s)+(a)) & 1)) writememwl_no_mmut((s)+(a),b,v); else *(uint16_t *)(writelookup2[(uint32_t)((s) + (a)) >> 12] + (uintptr_t)((s) + (a))) = v -#define writememl_n(s,a,b,v) if (writelookup2[(uint32_t)((s)+(a))>>12]==(uintptr_t)LOOKUP_INV || (s)==0xFFFFFFFF || (((s)+(a)) & 3)) writememll_no_mmut((s)+(a),b,v); else *(uint32_t *)(writelookup2[(uint32_t)((s) + (a)) >> 12] + (uintptr_t)((s) + (a))) = v -#define writememb(s,a,v) if (writelookup2[(uint32_t)((s)+(a))>>12]==(uintptr_t)LOOKUP_INV || (s)==0xFFFFFFFF) writemembl((s)+(a),v); else *(uint8_t *)(writelookup2[(uint32_t)((s) + (a)) >> 12] + (uintptr_t)((s) + (a))) = v -#define writememw(s,a,v) if (writelookup2[(uint32_t)((s)+(a))>>12]==(uintptr_t)LOOKUP_INV || (s)==0xFFFFFFFF || (((s)+(a)) & 1)) writememwl((s)+(a),v); else *(uint16_t *)(writelookup2[(uint32_t)((s) + (a)) >> 12] + (uintptr_t)((s) + (a))) = v -#define writememl(s,a,v) if (writelookup2[(uint32_t)((s)+(a))>>12]==(uintptr_t)LOOKUP_INV || (s)==0xFFFFFFFF || (((s)+(a)) & 3)) writememll((s)+(a),v); else *(uint32_t *)(writelookup2[(uint32_t)((s) + (a)) >> 12] + (uintptr_t)((s) + (a))) = v -#define writememq(s,a,v) if (writelookup2[(uint32_t)((s)+(a))>>12]==(uintptr_t)LOOKUP_INV || (s)==0xFFFFFFFF || (((s)+(a)) & 7)) writememql((s)+(a),v); else *(uint64_t *)(writelookup2[(uint32_t)((s) + (a)) >> 12] + (uintptr_t)((s) + (a))) = v +# define writememb_n(s, a, b, v) writemembl_no_mmut_2386((s) + (a), b, v) +# define writememw_n(s, a, b, v) writememwl_no_mmut_2386((s) + (a), b, v) +# define writememl_n(s, a, b, v) writememll_no_mmut_2386((s) + (a), b, v) +# define writememb(s, a, v) writemembl_2386((s) + (a), v) +# define writememw(s, a, v) writememwl_2386((s) + (a), v) +# define writememl(s, a, v) writememll_2386((s) + (a), v) +# define writememq(s, a, v) writememql_2386((s) + (a), v) -#define do_mmut_rb(s,a,b) if (readlookup2[(uint32_t)((s)+(a))>>12]==(uintptr_t)LOOKUP_INV || (s)==0xFFFFFFFF) do_mmutranslate((s)+(a), b, 1, 0) -#define do_mmut_rw(s,a,b) if (readlookup2[(uint32_t)((s)+(a))>>12]==(uintptr_t)LOOKUP_INV || (s)==0xFFFFFFFF || (((s)+(a)) & 1)) do_mmutranslate((s)+(a), b, 2, 0) -#define do_mmut_rl(s,a,b) if (readlookup2[(uint32_t)((s)+(a))>>12]==(uintptr_t)LOOKUP_INV || (s)==0xFFFFFFFF || (((s)+(a)) & 3)) do_mmutranslate((s)+(a), b, 4, 0) -#define do_mmut_rb2(s,a,b) old_rl2 = readlookup2[(uint32_t)((s)+(a))>>12]; if (old_rl2==(uintptr_t)LOOKUP_INV || (s)==0xFFFFFFFF) do_mmutranslate((s)+(a), b, 1, 0) -#define do_mmut_rw2(s,a,b) old_rl2 = readlookup2[(uint32_t)((s)+(a))>>12]; if (old_rl2==(uintptr_t)LOOKUP_INV || (s)==0xFFFFFFFF || (((s)+(a)) & 1)) do_mmutranslate((s)+(a), b, 2, 0) -#define do_mmut_rl2(s,a,b) old_rl2 = readlookup2[(uint32_t)((s)+(a))>>12]; if (old_rl2==(uintptr_t)LOOKUP_INV || (s)==0xFFFFFFFF || (((s)+(a)) & 3)) do_mmutranslate((s)+(a), b, 4, 0) +# define do_mmut_rb(s, a, b) do_mmutranslate_2386((s) + (a), b, 1, 0) +# define do_mmut_rw(s, a, b) do_mmutranslate_2386((s) + (a), b, 2, 0) +# define do_mmut_rl(s, a, b) do_mmutranslate_2386((s) + (a), b, 4, 0) +# define do_mmut_rb2(s, a, b) do_mmutranslate_2386((s) + (a), b, 1, 0) +# define do_mmut_rw2(s, a, b) do_mmutranslate_2386((s) + (a), b, 2, 0) +# define do_mmut_rl2(s, a, b) do_mmutranslate_2386((s) + (a), b, 4, 0) -#define do_mmut_wb(s,a,b) if (writelookup2[(uint32_t)((s)+(a))>>12]==(uintptr_t)LOOKUP_INV || (s)==0xFFFFFFFF) do_mmutranslate((s)+(a), b, 1, 1) -#define do_mmut_ww(s,a,b) if (writelookup2[(uint32_t)((s)+(a))>>12]==(uintptr_t)LOOKUP_INV || (s)==0xFFFFFFFF || (((s)+(a)) & 1)) do_mmutranslate((s)+(a), b, 2, 1) -#define do_mmut_wl(s,a,b) if (writelookup2[(uint32_t)((s)+(a))>>12]==(uintptr_t)LOOKUP_INV || (s)==0xFFFFFFFF || (((s)+(a)) & 3)) do_mmutranslate((s)+(a), b, 4, 1) +# define do_mmut_wb(s, a, b) do_mmutranslate_2386((s) + (a), b, 1, 1) +# define do_mmut_ww(s, a, b) do_mmutranslate_2386((s) + (a), b, 2, 1) +# define do_mmut_wl(s, a, b) do_mmutranslate_2386((s) + (a), b, 4, 1) +#else +# define readmemb_n(s, a, b) ((readlookup2[(uint32_t) ((s) + (a)) >> 12] == (uintptr_t) LOOKUP_INV || (s) == 0xFFFFFFFF) ? readmembl_no_mmut((s) + (a), b) : *(uint8_t *) (readlookup2[(uint32_t) ((s) + (a)) >> 12] + (uintptr_t) ((s) + (a)))) +# define readmemw_n(s, a, b) ((readlookup2[(uint32_t) ((s) + (a)) >> 12] == (uintptr_t) LOOKUP_INV || (s) == 0xFFFFFFFF || (((s) + (a)) & 1)) ? readmemwl_no_mmut((s) + (a), b) : *(uint16_t *) (readlookup2[(uint32_t) ((s) + (a)) >> 12] + (uint32_t) ((s) + (a)))) +# define readmeml_n(s, a, b) ((readlookup2[(uint32_t) ((s) + (a)) >> 12] == (uintptr_t) LOOKUP_INV || (s) == 0xFFFFFFFF || (((s) + (a)) & 3)) ? readmemll_no_mmut((s) + (a), b) : *(uint32_t *) (readlookup2[(uint32_t) ((s) + (a)) >> 12] + (uint32_t) ((s) + (a)))) +# define readmemb(s, a) ((readlookup2[(uint32_t) ((s) + (a)) >> 12] == (uintptr_t) LOOKUP_INV || (s) == 0xFFFFFFFF) ? readmembl((s) + (a)) : *(uint8_t *) (readlookup2[(uint32_t) ((s) + (a)) >> 12] + (uintptr_t) ((s) + (a)))) +# define readmemw(s, a) ((readlookup2[(uint32_t) ((s) + (a)) >> 12] == (uintptr_t) LOOKUP_INV || (s) == 0xFFFFFFFF || (((s) + (a)) & 1)) ? readmemwl((s) + (a)) : *(uint16_t *) (readlookup2[(uint32_t) ((s) + (a)) >> 12] + (uint32_t) ((s) + (a)))) +# define readmeml(s, a) ((readlookup2[(uint32_t) ((s) + (a)) >> 12] == (uintptr_t) LOOKUP_INV || (s) == 0xFFFFFFFF || (((s) + (a)) & 3)) ? readmemll((s) + (a)) : *(uint32_t *) (readlookup2[(uint32_t) ((s) + (a)) >> 12] + (uint32_t) ((s) + (a)))) +# define readmemq(s, a) ((readlookup2[(uint32_t) ((s) + (a)) >> 12] == (uintptr_t) LOOKUP_INV || (s) == 0xFFFFFFFF || (((s) + (a)) & 7)) ? readmemql((s) + (a)) : *(uint64_t *) (readlookup2[(uint32_t) ((s) + (a)) >> 12] + (uintptr_t) ((s) + (a)))) +# define writememb_n(s, a, b, v) \ + if (writelookup2[(uint32_t) ((s) + (a)) >> 12] == (uintptr_t) LOOKUP_INV || (s) == 0xFFFFFFFF) \ + writemembl_no_mmut((s) + (a), b, v); \ + else \ + *(uint8_t *) (writelookup2[(uint32_t) ((s) + (a)) >> 12] + (uintptr_t) ((s) + (a))) = v +# define writememw_n(s, a, b, v) \ + if (writelookup2[(uint32_t) ((s) + (a)) >> 12] == (uintptr_t) LOOKUP_INV || (s) == 0xFFFFFFFF || (((s) + (a)) & 1)) \ + writememwl_no_mmut((s) + (a), b, v); \ + else \ + *(uint16_t *) (writelookup2[(uint32_t) ((s) + (a)) >> 12] + (uintptr_t) ((s) + (a))) = v +# define writememl_n(s, a, b, v) \ + if (writelookup2[(uint32_t) ((s) + (a)) >> 12] == (uintptr_t) LOOKUP_INV || (s) == 0xFFFFFFFF || (((s) + (a)) & 3)) \ + writememll_no_mmut((s) + (a), b, v); \ + else \ + *(uint32_t *) (writelookup2[(uint32_t) ((s) + (a)) >> 12] + (uintptr_t) ((s) + (a))) = v +# define writememb(s, a, v) \ + if (writelookup2[(uint32_t) ((s) + (a)) >> 12] == (uintptr_t) LOOKUP_INV || (s) == 0xFFFFFFFF) \ + writemembl((s) + (a), v); \ + else \ + *(uint8_t *) (writelookup2[(uint32_t) ((s) + (a)) >> 12] + (uintptr_t) ((s) + (a))) = v +# define writememw(s, a, v) \ + if (writelookup2[(uint32_t) ((s) + (a)) >> 12] == (uintptr_t) LOOKUP_INV || (s) == 0xFFFFFFFF || (((s) + (a)) & 1)) \ + writememwl((s) + (a), v); \ + else \ + *(uint16_t *) (writelookup2[(uint32_t) ((s) + (a)) >> 12] + (uintptr_t) ((s) + (a))) = v +# define writememl(s, a, v) \ + if (writelookup2[(uint32_t) ((s) + (a)) >> 12] == (uintptr_t) LOOKUP_INV || (s) == 0xFFFFFFFF || (((s) + (a)) & 3)) \ + writememll((s) + (a), v); \ + else \ + *(uint32_t *) (writelookup2[(uint32_t) ((s) + (a)) >> 12] + (uintptr_t) ((s) + (a))) = v +# define writememq(s, a, v) \ + if (writelookup2[(uint32_t) ((s) + (a)) >> 12] == (uintptr_t) LOOKUP_INV || (s) == 0xFFFFFFFF || (((s) + (a)) & 7)) \ + writememql((s) + (a), v); \ + else \ + *(uint64_t *) (writelookup2[(uint32_t) ((s) + (a)) >> 12] + (uintptr_t) ((s) + (a))) = v -int checkio(uint32_t port); +# define do_mmut_rb(s, a, b) \ + if (readlookup2[(uint32_t) ((s) + (a)) >> 12] == (uintptr_t) LOOKUP_INV || (s) == 0xFFFFFFFF) \ + do_mmutranslate((s) + (a), b, 1, 0) +# define do_mmut_rw(s, a, b) \ + if (readlookup2[(uint32_t) ((s) + (a)) >> 12] == (uintptr_t) LOOKUP_INV || (s) == 0xFFFFFFFF || (((s) + (a)) & 1)) \ + do_mmutranslate((s) + (a), b, 2, 0) +# define do_mmut_rl(s, a, b) \ + if (readlookup2[(uint32_t) ((s) + (a)) >> 12] == (uintptr_t) LOOKUP_INV || (s) == 0xFFFFFFFF || (((s) + (a)) & 3)) \ + do_mmutranslate((s) + (a), b, 4, 0) +# define do_mmut_rb2(s, a, b) \ + old_rl2 = readlookup2[(uint32_t) ((s) + (a)) >> 12]; \ + if (old_rl2 == (uintptr_t) LOOKUP_INV || (s) == 0xFFFFFFFF) \ + do_mmutranslate((s) + (a), b, 1, 0) +# define do_mmut_rw2(s, a, b) \ + old_rl2 = readlookup2[(uint32_t) ((s) + (a)) >> 12]; \ + if (old_rl2 == (uintptr_t) LOOKUP_INV || (s) == 0xFFFFFFFF || (((s) + (a)) & 1)) \ + do_mmutranslate((s) + (a), b, 2, 0) +# define do_mmut_rl2(s, a, b) \ + old_rl2 = readlookup2[(uint32_t) ((s) + (a)) >> 12]; \ + if (old_rl2 == (uintptr_t) LOOKUP_INV || (s) == 0xFFFFFFFF || (((s) + (a)) & 3)) \ + do_mmutranslate((s) + (a), b, 4, 0) +# define do_mmut_wb(s, a, b) \ + if (writelookup2[(uint32_t) ((s) + (a)) >> 12] == (uintptr_t) LOOKUP_INV || (s) == 0xFFFFFFFF) \ + do_mmutranslate((s) + (a), b, 1, 1) +# define do_mmut_ww(s, a, b) \ + if (writelookup2[(uint32_t) ((s) + (a)) >> 12] == (uintptr_t) LOOKUP_INV || (s) == 0xFFFFFFFF || (((s) + (a)) & 1)) \ + do_mmutranslate((s) + (a), b, 2, 1) +# define do_mmut_wl(s, a, b) \ + if (writelookup2[(uint32_t) ((s) + (a)) >> 12] == (uintptr_t) LOOKUP_INV || (s) == 0xFFFFFFFF || (((s) + (a)) & 3)) \ + do_mmutranslate((s) + (a), b, 4, 1) +#endif -#define check_io_perm(port) if (msw&1 && ((CPL > IOPL) || (cpu_state.eflags&VM_FLAG))) \ - { \ - int tempi = checkio(port); \ - if (cpu_state.abrt) return 1; \ - if (tempi) \ - { \ - if (cpu_state.eflags & VM_FLAG) \ - x86gpf_expected(NULL,0); \ - else \ - x86gpf(NULL,0); \ - return 1; \ - } \ - } +int checkio(uint32_t port, int mask); -#define SEG_CHECK_READ(seg) \ - do \ - { \ - if ((seg)->base == 0xffffffff) \ - { \ - x86gpf("Segment can't read", 0);\ - return 1; \ - } \ - } while (0) +#define check_io_perm(port, size) \ + if (msw & 1 && ((CPL > IOPL) || (cpu_state.eflags & VM_FLAG))) { \ + int tempi = checkio(port, (1 << size) - 1); \ + if (cpu_state.abrt) \ + return 1; \ + if (tempi) { \ + if (cpu_state.eflags & VM_FLAG) \ + x86gpf_expected(NULL, 0); \ + else \ + x86gpf(NULL, 0); \ + return 1; \ + } \ + } -#define SEG_CHECK_WRITE(seg) \ - do \ - { \ - if ((seg)->base == 0xffffffff) \ - { \ - x86gpf("Segment can't write", 0);\ - return 1; \ - } \ - } while (0) +#define SEG_CHECK_READ(seg) \ + do { \ + if ((seg)->base == 0xffffffff) { \ + x86gpf("Segment can't read", 0); \ + return 1; \ + } \ + } while (0) -#define CHECK_READ(chseg, low, high) \ - if ((low < (chseg)->limit_low) || (high > (chseg)->limit_high) || ((msw & 1) && !(cpu_state.eflags & VM_FLAG) && (((chseg)->access & 10) == 8))) \ - { \ - x86gpf("Limit check (READ)", 0); \ - return 1; \ - } \ - if (msw&1 && !(cpu_state.eflags&VM_FLAG) && !((chseg)->access & 0x80)) \ - { \ - if ((chseg) == &cpu_state.seg_ss) \ - x86ss(NULL,(chseg)->seg & 0xfffc); \ - else \ - x86np("Read from seg not present", (chseg)->seg & 0xfffc); \ - return 1; \ - } +#define SEG_CHECK_WRITE(seg) \ + do { \ + if ((seg)->base == 0xffffffff) { \ + x86gpf("Segment can't write", 0); \ + return 1; \ + } \ + } while (0) -#define CHECK_READ_REP(chseg, low, high) \ - if ((low < (chseg)->limit_low) || (high > (chseg)->limit_high)) \ - { \ - x86gpf("Limit check (READ)", 0); \ - break; \ - } \ - if (msw&1 && !(cpu_state.eflags&VM_FLAG) && !((chseg)->access & 0x80)) \ - { \ - if ((chseg) == &cpu_state.seg_ss) \ - x86ss(NULL,(chseg)->seg & 0xfffc); \ - else \ - x86np("Read from seg not present", (chseg)->seg & 0xfffc); \ - break; \ - } +#define CHECK_READ(chseg, low, high) \ + if ((low < (chseg)->limit_low) || (high > (chseg)->limit_high) || ((msw & 1) && !(cpu_state.eflags & VM_FLAG) && (((chseg)->access & 10) == 8))) { \ + x86gpf("Limit check (READ)", 0); \ + return 1; \ + } \ + if (msw & 1 && !(cpu_state.eflags & VM_FLAG) && !((chseg)->access & 0x80)) { \ + if ((chseg) == &cpu_state.seg_ss) \ + x86ss(NULL, (chseg)->seg & 0xfffc); \ + else \ + x86np("Read from seg not present", (chseg)->seg & 0xfffc); \ + return 1; \ + } -#define CHECK_WRITE_COMMON(chseg, low, high) \ - if ((low < (chseg)->limit_low) || (high > (chseg)->limit_high) || !((chseg)->access & 2) || ((msw & 1) && !(cpu_state.eflags & VM_FLAG) && ((chseg)->access & 8))) \ - { \ - x86gpf("Limit check (WRITE)", 0); \ - return 1; \ - } \ - if (msw&1 && !(cpu_state.eflags&VM_FLAG) && !((chseg)->access & 0x80)) \ - { \ - if ((chseg) == &cpu_state.seg_ss) \ - x86ss(NULL,(chseg)->seg & 0xfffc); \ - else \ - x86np("Write to seg not present", (chseg)->seg & 0xfffc); \ - return 1; \ - } +#define CHECK_READ_REP(chseg, low, high) \ + if ((low < (chseg)->limit_low) || (high > (chseg)->limit_high)) { \ + x86gpf("Limit check (READ)", 0); \ + break; \ + } \ + if (msw & 1 && !(cpu_state.eflags & VM_FLAG) && !((chseg)->access & 0x80)) { \ + if ((chseg) == &cpu_state.seg_ss) \ + x86ss(NULL, (chseg)->seg & 0xfffc); \ + else \ + x86np("Read from seg not present", (chseg)->seg & 0xfffc); \ + break; \ + } -#define CHECK_WRITE(chseg, low, high) \ - CHECK_WRITE_COMMON(chseg, low, high) +#define CHECK_WRITE_COMMON(chseg, low, high) \ + if ((low < (chseg)->limit_low) || (high > (chseg)->limit_high) || !((chseg)->access & 2) || ((msw & 1) && !(cpu_state.eflags & VM_FLAG) && ((chseg)->access & 8))) { \ + x86gpf("Limit check (WRITE)", 0); \ + return 1; \ + } \ + if (msw & 1 && !(cpu_state.eflags & VM_FLAG) && !((chseg)->access & 0x80)) { \ + if ((chseg) == &cpu_state.seg_ss) \ + x86ss(NULL, (chseg)->seg & 0xfffc); \ + else \ + x86np("Write to seg not present", (chseg)->seg & 0xfffc); \ + return 1; \ + } -#define CHECK_WRITE_REP(chseg, low, high) \ - if ((low < (chseg)->limit_low) || (high > (chseg)->limit_high)) \ - { \ - x86gpf("Limit check (WRITE REP)", 0); \ - break; \ - } \ - if (msw&1 && !(cpu_state.eflags&VM_FLAG) && !((chseg)->access & 0x80)) \ - { \ - if ((chseg) == &cpu_state.seg_ss) \ - x86ss(NULL,(chseg)->seg & 0xfffc); \ - else \ - x86np("Write (REP) to seg not present", (chseg)->seg & 0xfffc); \ - break; \ - } +#define CHECK_WRITE(chseg, low, high) \ + CHECK_WRITE_COMMON(chseg, low, high) +#define CHECK_WRITE_REP(chseg, low, high) \ + if ((low < (chseg)->limit_low) || (high > (chseg)->limit_high)) { \ + x86gpf("Limit check (WRITE REP)", 0); \ + break; \ + } \ + if (msw & 1 && !(cpu_state.eflags & VM_FLAG) && !((chseg)->access & 0x80)) { \ + if ((chseg) == &cpu_state.seg_ss) \ + x86ss(NULL, (chseg)->seg & 0xfffc); \ + else \ + x86np("Write (REP) to seg not present", (chseg)->seg & 0xfffc); \ + break; \ + } -#define NOTRM if (!(msw & 1) || (cpu_state.eflags & VM_FLAG))\ - { \ - x86_int(6); \ - return 1; \ - } +#define NOTRM \ + if (!(msw & 1) || (cpu_state.eflags & VM_FLAG)) { \ + x86_int(6); \ + return 1; \ + } - - - -static __inline uint8_t fastreadb(uint32_t a) +#ifdef OPS_286_386 +/* TODO: Introduce functions to read exec. */ +static __inline uint8_t +fastreadb(uint32_t a) { - uint8_t *t; - - if ((a >> 12) == pccache) - return *((uint8_t *)&pccache2[a]); - t = getpccache(a); - if (cpu_state.abrt) - return 0; - pccache = a >> 12; - pccache2 = t; - return *((uint8_t *)&pccache2[a]); + return readmembl_2386(a); } -static __inline uint16_t fastreadw(uint32_t a) +static __inline uint16_t +fastreadw(uint32_t a) { - uint8_t *t; - uint16_t val; - if ((a&0xFFF)>0xFFE) - { - val = fastreadb(a); - val |= (fastreadb(a + 1) << 8); - return val; - } - if ((a>>12)==pccache) return *((uint16_t *)&pccache2[a]); - t = getpccache(a); - if (cpu_state.abrt) - return 0; - - pccache = a >> 12; - pccache2 = t; - return *((uint16_t *)&pccache2[a]); + return readmemwl_2386(a); } -static __inline uint32_t fastreadl(uint32_t a) +static __inline uint32_t +fastreadl(uint32_t a) { - uint8_t *t; - uint32_t val; - if ((a&0xFFF)<0xFFD) - { - if ((a>>12)!=pccache) - { - t = getpccache(a); - if (cpu_state.abrt) - return 0; - pccache2 = t; - pccache=a>>12; - } - return *((uint32_t *)&pccache2[a]); - } - val = fastreadw(a); - val |= (fastreadw(a + 2) << 16); + return readmemll_2386(a); +} +#else +static __inline uint8_t +fastreadb(uint32_t a) +{ + uint8_t *t; + + if ((a >> 12) == pccache) +# if (defined __amd64__ || defined _M_X64 || defined __aarch64__ || defined _M_ARM64) + return *((uint8_t *) (((uintptr_t) &pccache2[a] & 0x00000000ffffffffULL) | ((uintptr_t) &pccache2[0] & 0xffffffff00000000ULL))); +# else + return *((uint8_t *) &pccache2[a]); +# endif + t = getpccache(a); + if (cpu_state.abrt) + return 0; + pccache = a >> 12; + pccache2 = t; +# if (defined __amd64__ || defined _M_X64 || defined __aarch64__ || defined _M_ARM64) + return *((uint8_t *) (((uintptr_t) &pccache2[a] & 0x00000000ffffffffULL) | ((uintptr_t) &pccache2[0] & 0xffffffff00000000ULL))); +# else + return *((uint8_t *) &pccache2[a]); +# endif +} + +static __inline uint16_t +fastreadw(uint32_t a) +{ + uint8_t *t; + uint16_t val; + if ((a & 0xFFF) > 0xFFE) { + val = fastreadb(a); + val |= (fastreadb(a + 1) << 8); return val; + } + if ((a >> 12) == pccache) +# if (defined __amd64__ || defined _M_X64 || defined __aarch64__ || defined _M_ARM64) + return *((uint16_t *) (((uintptr_t) &pccache2[a] & 0x00000000ffffffffULL) | ((uintptr_t) &pccache2[0] & 0xffffffff00000000ULL))); +# else + return *((uint16_t *) &pccache2[a]); +# endif + t = getpccache(a); + if (cpu_state.abrt) + return 0; + + pccache = a >> 12; + pccache2 = t; +# if (defined __amd64__ || defined _M_X64 || defined __aarch64__ || defined _M_ARM64) + return *((uint16_t *) (((uintptr_t) &pccache2[a] & 0x00000000ffffffffULL) | ((uintptr_t) &pccache2[0] & 0xffffffff00000000ULL))); +# else + return *((uint16_t *) &pccache2[a]); +# endif } -static __inline void *get_ram_ptr(uint32_t a) +static __inline uint32_t +fastreadl(uint32_t a) { - if ((a >> 12) == pccache) - return &pccache2[a]; - else - { - uint8_t *t = getpccache(a); - return &t[a]; + uint8_t *t; + uint32_t val; + if ((a & 0xFFF) < 0xFFD) { + if ((a >> 12) != pccache) { + t = getpccache(a); + if (cpu_state.abrt) + return 0; + pccache2 = t; + pccache = a >> 12; } +# if (defined __amd64__ || defined _M_X64 || defined __aarch64__ || defined _M_ARM64) + return *((uint32_t *) (((uintptr_t) &pccache2[a] & 0x00000000ffffffffULL) | ((uintptr_t) &pccache2[0] & 0xffffffff00000000ULL))); +# else + return *((uint32_t *) &pccache2[a]); +# endif + } + val = fastreadw(a); + val |= (fastreadw(a + 2) << 16); + return val; } +#endif -static __inline uint8_t getbyte() +static __inline void * +get_ram_ptr(uint32_t a) { - cpu_state.pc++; - return fastreadb(cs + (cpu_state.pc - 1)); + if ((a >> 12) == pccache) +#if (defined __amd64__ || defined _M_X64 || defined __aarch64__ || defined _M_ARM64) + return (void *) (((uintptr_t) &pccache2[a] & 0x00000000ffffffffULL) | ((uintptr_t) &pccache2[0] & 0xffffffff00000000ULL)); +#else + return &pccache2[a]; +#endif + else { + uint8_t *t = getpccache(a); +#if (defined __amd64__ || defined _M_X64 || defined __aarch64__ || defined _M_ARM64) + return (void *) (((uintptr_t) &t[a] & 0x00000000ffffffffULL) | ((uintptr_t) &t[0] & 0xffffffff00000000ULL)); +#else + return &t[a]; +#endif + } } -static __inline uint16_t getword() +extern int opcode_length[256]; + +#ifdef OPS_286_386 +static __inline uint16_t +fastreadw_fetch(uint32_t a) { - cpu_state.pc+=2; - return fastreadw(cs+(cpu_state.pc-2)); + uint16_t val; + + if ((a & 0xFFF) > 0xFFE) { + val = fastreadb(a); + if (opcode_length[val & 0xff] > 1) + val |= ((uint16_t) fastreadb(a + 1) << 8); + return val; + } + + return readmemwl_2386(a); } -static __inline uint32_t getlong() +static __inline uint32_t +fastreadl_fetch(uint32_t a) { - cpu_state.pc+=4; - return fastreadl(cs+(cpu_state.pc-4)); -} + uint32_t val; -static __inline uint64_t getquad() + if (cpu_16bitbus || ((a & 0xFFF) > 0xFFC)) { + val = fastreadw_fetch(a); + if (opcode_length[val & 0xff] > 2) + val |= ((uint32_t) fastreadw(a + 2) << 16); + return val; + } + + return readmemll_2386(a); +} +#else +static __inline uint16_t +fastreadw_fetch(uint32_t a) { - cpu_state.pc+=8; - return fastreadl(cs+(cpu_state.pc-8)) | ((uint64_t)fastreadl(cs+(cpu_state.pc-4)) << 32); + uint8_t *t; + uint16_t val; + if ((a & 0xFFF) > 0xFFE) { + val = fastreadb(a); + if (opcode_length[val & 0xff] > 1) + val |= (fastreadb(a + 1) << 8); + return val; + } + if ((a >> 12) == pccache) +# if (defined __amd64__ || defined _M_X64 || defined __aarch64__ || defined _M_ARM64) + return *((uint16_t *) (((uintptr_t) &pccache2[a] & 0x00000000ffffffffULL) | ((uintptr_t) &pccache2[0] & 0xffffffff00000000ULL))); +# else + return *((uint16_t *) &pccache2[a]); +# endif + t = getpccache(a); + if (cpu_state.abrt) + return 0; + + pccache = a >> 12; + pccache2 = t; +# if (defined __amd64__ || defined _M_X64 || defined __aarch64__ || defined _M_ARM64) + return *((uint16_t *) (((uintptr_t) &pccache2[a] & 0x00000000ffffffffULL) | ((uintptr_t) &pccache2[0] & 0xffffffff00000000ULL))); +# else + return *((uint16_t *) &pccache2[a]); +# endif } - - -static __inline uint8_t geteab() +static __inline uint32_t +fastreadl_fetch(uint32_t a) { - if (cpu_mod == 3) - return (cpu_rm & 4) ? cpu_state.regs[cpu_rm & 3].b.h : cpu_state.regs[cpu_rm&3].b.l; - if (eal_r) - return *(uint8_t *)eal_r; - return readmemb(easeg, cpu_state.eaaddr); + uint8_t *t; + uint32_t val; + if ((a & 0xFFF) < 0xFFD) { + if ((a >> 12) != pccache) { + t = getpccache(a); + if (cpu_state.abrt) + return 0; + pccache2 = t; + pccache = a >> 12; + } +# if (defined __amd64__ || defined _M_X64 || defined __aarch64__ || defined _M_ARM64) + return *((uint32_t *) (((uintptr_t) &pccache2[a] & 0x00000000ffffffffULL) | ((uintptr_t) &pccache2[0] & 0xffffffff00000000ULL))); +# else + return *((uint32_t *) &pccache2[a]); +# endif + } + val = fastreadw_fetch(a); + if (opcode_length[val & 0xff] > 2) + val |= (fastreadw(a + 2) << 16); + return val; } +#endif -static __inline uint16_t geteaw() +static __inline uint8_t +getbyte(void) { - if (cpu_mod == 3) - return cpu_state.regs[cpu_rm].w; - if (eal_r) - return *(uint16_t *)eal_r; - return readmemw(easeg, cpu_state.eaaddr); + cpu_state.pc++; + return fastreadb(cs + (cpu_state.pc - 1)); } -static __inline uint32_t geteal() +static __inline uint16_t +getword(void) { - if (cpu_mod == 3) - return cpu_state.regs[cpu_rm].l; - if (eal_r) - return *eal_r; - return readmeml(easeg, cpu_state.eaaddr); + cpu_state.pc += 2; + return fastreadw(cs + (cpu_state.pc - 2)); } -static __inline uint64_t geteaq() +static __inline uint32_t +getlong(void) { - return readmemq(easeg, cpu_state.eaaddr); + cpu_state.pc += 4; + return fastreadl(cs + (cpu_state.pc - 4)); } -static __inline uint8_t geteab_mem() +static __inline uint64_t +getquad(void) { - if (eal_r) return *(uint8_t *)eal_r; - return readmemb(easeg,cpu_state.eaaddr); + cpu_state.pc += 8; + return fastreadl(cs + (cpu_state.pc - 8)) | ((uint64_t) fastreadl(cs + (cpu_state.pc - 4)) << 32); } -static __inline uint16_t geteaw_mem() + +#ifdef OPS_286_386 +static __inline uint8_t +geteab(void) { - if (eal_r) return *(uint16_t *)eal_r; - return readmemw(easeg,cpu_state.eaaddr); + if (cpu_mod == 3) + return (cpu_rm & 4) ? cpu_state.regs[cpu_rm & 3].b.h : cpu_state.regs[cpu_rm & 3].b.l; + return readmemb(easeg, cpu_state.eaaddr); } -static __inline uint32_t geteal_mem() + +static __inline uint16_t +geteaw(void) { - if (eal_r) return *eal_r; - return readmeml(easeg,cpu_state.eaaddr); + if (cpu_mod == 3) + return cpu_state.regs[cpu_rm].w; + return readmemw(easeg, cpu_state.eaaddr); } -static __inline int seteaq_cwc(void) +static __inline uint32_t +geteal(void) { - CHECK_WRITE_COMMON(cpu_state.ea_seg, cpu_state.eaaddr, cpu_state.eaaddr); - return 0; + if (cpu_mod == 3) + return cpu_state.regs[cpu_rm].l; + return readmeml(easeg, cpu_state.eaaddr); } -static __inline void seteaq(uint64_t v) +static __inline uint64_t +geteaq(void) { - if (seteaq_cwc()) - return; - writememql(easeg + cpu_state.eaaddr, v); + return readmemq(easeg, cpu_state.eaaddr); } -#define seteab(v) if (cpu_mod!=3) { CHECK_WRITE_COMMON(cpu_state.ea_seg, cpu_state.eaaddr, cpu_state.eaaddr); if (eal_w) *(uint8_t *)eal_w=v; else writemembl(easeg+cpu_state.eaaddr,v); } else if (cpu_rm&4) cpu_state.regs[cpu_rm&3].b.h=v; else cpu_state.regs[cpu_rm].b.l=v -#define seteaw(v) if (cpu_mod!=3) { CHECK_WRITE_COMMON(cpu_state.ea_seg, cpu_state.eaaddr, cpu_state.eaaddr + 1); if (eal_w) *(uint16_t *)eal_w=v; else writememwl(easeg+cpu_state.eaaddr,v); } else cpu_state.regs[cpu_rm].w=v -#define seteal(v) if (cpu_mod!=3) { CHECK_WRITE_COMMON(cpu_state.ea_seg, cpu_state.eaaddr, cpu_state.eaaddr + 3); if (eal_w) *eal_w=v; else writememll(easeg+cpu_state.eaaddr,v); } else cpu_state.regs[cpu_rm].l=v +static __inline uint8_t +geteab_mem(void) +{ + return readmemb(easeg, cpu_state.eaaddr); +} +static __inline uint16_t +geteaw_mem(void) +{ + return readmemw(easeg, cpu_state.eaaddr); +} +static __inline uint32_t +geteal_mem(void) +{ + return readmeml(easeg, cpu_state.eaaddr); +} -#define seteab_mem(v) if (eal_w) *(uint8_t *)eal_w=v; else writemembl(easeg+cpu_state.eaaddr,v); -#define seteaw_mem(v) if (eal_w) *(uint16_t *)eal_w=v; else writememwl(easeg+cpu_state.eaaddr,v); -#define seteal_mem(v) if (eal_w) *eal_w=v; else writememll(easeg+cpu_state.eaaddr,v); +static __inline int +seteaq_cwc(void) +{ + CHECK_WRITE_COMMON(cpu_state.ea_seg, cpu_state.eaaddr, cpu_state.eaaddr); + return 0; +} -#define getbytef() ((uint8_t)(fetchdat)); cpu_state.pc++ -#define getwordf() ((uint16_t)(fetchdat)); cpu_state.pc+=2 -#define getbyte2f() ((uint8_t)(fetchdat>>8)); cpu_state.pc++ -#define getword2f() ((uint16_t)(fetchdat>>8)); cpu_state.pc+=2 +static __inline void +seteaq(uint64_t v) +{ + if (seteaq_cwc()) + return; + writememql(easeg + cpu_state.eaaddr, v); +} + +# define seteab(v) \ + if (cpu_mod != 3) { \ + CHECK_WRITE_COMMON(cpu_state.ea_seg, cpu_state.eaaddr, cpu_state.eaaddr); \ + writemembl_2386(easeg + cpu_state.eaaddr, v); \ + } else if (cpu_rm & 4) \ + cpu_state.regs[cpu_rm & 3].b.h = v; \ + else \ + cpu_state.regs[cpu_rm].b.l = v +# define seteaw(v) \ + if (cpu_mod != 3) { \ + CHECK_WRITE_COMMON(cpu_state.ea_seg, cpu_state.eaaddr, cpu_state.eaaddr + 1); \ + writememwl_2386(easeg + cpu_state.eaaddr, v); \ + } else \ + cpu_state.regs[cpu_rm].w = v +# define seteal(v) \ + if (cpu_mod != 3) { \ + CHECK_WRITE_COMMON(cpu_state.ea_seg, cpu_state.eaaddr, cpu_state.eaaddr + 3); \ + writememll_2386(easeg + cpu_state.eaaddr, v); \ + } else \ + cpu_state.regs[cpu_rm].l = v + +# define seteab_mem(v) writemembl_2386(easeg + cpu_state.eaaddr, v); +# define seteaw_mem(v) writememwl_2386(easeg + cpu_state.eaaddr, v); +# define seteal_mem(v) writememll_2386(easeg + cpu_state.eaaddr, v); +#else +static __inline uint8_t +geteab(void) +{ + if (cpu_mod == 3) + return (cpu_rm & 4) ? cpu_state.regs[cpu_rm & 3].b.h : cpu_state.regs[cpu_rm & 3].b.l; + if (eal_r) + return *(uint8_t *) eal_r; + return readmemb(easeg, cpu_state.eaaddr); +} + +static __inline uint16_t +geteaw(void) +{ + if (cpu_mod == 3) + return cpu_state.regs[cpu_rm].w; + if (eal_r) + return *(uint16_t *) eal_r; + return readmemw(easeg, cpu_state.eaaddr); +} + +static __inline uint32_t +geteal(void) +{ + if (cpu_mod == 3) + return cpu_state.regs[cpu_rm].l; + if (eal_r) + return *eal_r; + return readmeml(easeg, cpu_state.eaaddr); +} + +static __inline uint64_t +geteaq(void) +{ + return readmemq(easeg, cpu_state.eaaddr); +} + +static __inline uint8_t +geteab_mem(void) +{ + if (eal_r) + return *(uint8_t *) eal_r; + return readmemb(easeg, cpu_state.eaaddr); +} +static __inline uint16_t +geteaw_mem(void) +{ + if (eal_r) + return *(uint16_t *) eal_r; + return readmemw(easeg, cpu_state.eaaddr); +} +static __inline uint32_t +geteal_mem(void) +{ + if (eal_r) + return *eal_r; + return readmeml(easeg, cpu_state.eaaddr); +} + +static __inline int +seteaq_cwc(void) +{ + CHECK_WRITE_COMMON(cpu_state.ea_seg, cpu_state.eaaddr, cpu_state.eaaddr); + return 0; +} + +static __inline void +seteaq(uint64_t v) +{ + if (seteaq_cwc()) + return; + writememql(easeg + cpu_state.eaaddr, v); +} + +# define seteab(v) \ + if (cpu_mod != 3) { \ + CHECK_WRITE_COMMON(cpu_state.ea_seg, cpu_state.eaaddr, cpu_state.eaaddr); \ + if (eal_w) \ + *(uint8_t *) eal_w = v; \ + else \ + writemembl(easeg + cpu_state.eaaddr, v); \ + } else if (cpu_rm & 4) \ + cpu_state.regs[cpu_rm & 3].b.h = v; \ + else \ + cpu_state.regs[cpu_rm].b.l = v +# define seteaw(v) \ + if (cpu_mod != 3) { \ + CHECK_WRITE_COMMON(cpu_state.ea_seg, cpu_state.eaaddr, cpu_state.eaaddr + 1); \ + if (eal_w) \ + *(uint16_t *) eal_w = v; \ + else \ + writememwl(easeg + cpu_state.eaaddr, v); \ + } else \ + cpu_state.regs[cpu_rm].w = v +# define seteal(v) \ + if (cpu_mod != 3) { \ + CHECK_WRITE_COMMON(cpu_state.ea_seg, cpu_state.eaaddr, cpu_state.eaaddr + 3); \ + if (eal_w) \ + *eal_w = v; \ + else \ + writememll(easeg + cpu_state.eaaddr, v); \ + } else \ + cpu_state.regs[cpu_rm].l = v + +# define seteab_mem(v) \ + if (eal_w) \ + *(uint8_t *) eal_w = v; \ + else \ + writemembl(easeg + cpu_state.eaaddr, v); +# define seteaw_mem(v) \ + if (eal_w) \ + *(uint16_t *) eal_w = v; \ + else \ + writememwl(easeg + cpu_state.eaaddr, v); +# define seteal_mem(v) \ + if (eal_w) \ + *eal_w = v; \ + else \ + writememll(easeg + cpu_state.eaaddr, v); +#endif + +#define getbytef() \ + ((uint8_t) (fetchdat)); \ + cpu_state.pc++ +#define getwordf() \ + ((uint16_t) (fetchdat)); \ + cpu_state.pc += 2 +#define getbyte2f() \ + ((uint8_t) (fetchdat >> 8)); \ + cpu_state.pc++ +#define getword2f() \ + ((uint16_t) (fetchdat >> 8)); \ + cpu_state.pc += 2 #endif diff --git a/src/cpu/386_dynarec.c b/src/cpu/386_dynarec.c index 4371efd00..e4caa8a1b 100644 --- a/src/cpu/386_dynarec.c +++ b/src/cpu/386_dynarec.c @@ -4,12 +4,12 @@ #include #include #if defined(__APPLE__) && defined(__aarch64__) -#include +# include #endif #include #include #ifndef INFINITY -# define INFINITY (__builtin_inff()) +# define INFINITY (__builtin_inff()) #endif #define HAVE_STDARG_H @@ -17,6 +17,8 @@ #include "cpu.h" #include "x86.h" #include "x86_ops.h" +#include "x86seg_common.h" +#include "x86seg.h" #include "x87.h" #include <86box/io.h> #include <86box/mem.h> @@ -26,313 +28,240 @@ #include <86box/fdd.h> #include <86box/fdc.h> #include <86box/machine.h> +#include <86box/gdbstub.h> #ifdef USE_DYNAREC -#include "codegen.h" -#ifdef USE_NEW_DYNAREC -#include "codegen_backend.h" +# include "codegen.h" +# ifdef USE_NEW_DYNAREC +# include "codegen_backend.h" +# endif #endif + +#ifdef IS_DYNAREC +# undef IS_DYNAREC #endif + #include "386_common.h" #if defined(__APPLE__) && defined(__aarch64__) -#include +# include #endif #define CPU_BLOCK_END() cpu_block_end = 1 - -int inrecomp = 0, cpu_block_end = 0; +int inrecomp = 0; +int cpu_block_end = 0; int cpu_end_block_after_ins = 0; - #ifdef ENABLE_386_DYNAREC_LOG int x386_dynarec_do_log = ENABLE_386_DYNAREC_LOG; - void x386_dynarec_log(const char *fmt, ...) { va_list ap; if (x386_dynarec_do_log) { - va_start(ap, fmt); - pclog_ex(fmt, ap); - va_end(ap); + va_start(ap, fmt); + pclog_ex(fmt, ap); + va_end(ap); } } #else -#define x386_dynarec_log(fmt, ...) +# define x386_dynarec_log(fmt, ...) #endif - -static __inline void fetch_ea_32_long(uint32_t rmdat) +static __inline void +fetch_ea_32_long(uint32_t rmdat) { - eal_r = eal_w = NULL; - easeg = cpu_state.ea_seg->base; - if (cpu_rm == 4) - { - uint8_t sib = rmdat >> 8; - - switch (cpu_mod) - { - case 0: - cpu_state.eaaddr = cpu_state.regs[sib & 7].l; - cpu_state.pc++; - break; - case 1: - cpu_state.pc++; - cpu_state.eaaddr = ((uint32_t)(int8_t)getbyte()) + cpu_state.regs[sib & 7].l; - break; - case 2: - cpu_state.eaaddr = (fastreadl(cs + cpu_state.pc + 1)) + cpu_state.regs[sib & 7].l; - cpu_state.pc += 5; - break; - } - /*SIB byte present*/ - if ((sib & 7) == 5 && !cpu_mod) - cpu_state.eaaddr = getlong(); - else if ((sib & 6) == 4 && !cpu_state.ssegs) - { - easeg = ss; - cpu_state.ea_seg = &cpu_state.seg_ss; - } - if (((sib >> 3) & 7) != 4) - cpu_state.eaaddr += cpu_state.regs[(sib >> 3) & 7].l << (sib >> 6); - } - else - { - cpu_state.eaaddr = cpu_state.regs[cpu_rm].l; - if (cpu_mod) - { - if (cpu_rm == 5 && !cpu_state.ssegs) - { - easeg = ss; - cpu_state.ea_seg = &cpu_state.seg_ss; - } - if (cpu_mod == 1) - { - cpu_state.eaaddr += ((uint32_t)(int8_t)(rmdat >> 8)); - cpu_state.pc++; - } - else - { - cpu_state.eaaddr += getlong(); - } - } - else if (cpu_rm == 5) - { - cpu_state.eaaddr = getlong(); - } - } - if (easeg != 0xFFFFFFFF && ((easeg + cpu_state.eaaddr) & 0xFFF) <= 0xFFC) - { - uint32_t addr = easeg + cpu_state.eaaddr; - if ( readlookup2[addr >> 12] != (uintptr_t) -1) - eal_r = (uint32_t *)(readlookup2[addr >> 12] + addr); - if (writelookup2[addr >> 12] != (uintptr_t) -1) - eal_w = (uint32_t *)(writelookup2[addr >> 12] + addr); - } + eal_r = eal_w = NULL; + easeg = cpu_state.ea_seg->base; + if (cpu_rm == 4) { + uint8_t sib = rmdat >> 8; + + switch (cpu_mod) { + case 0: + cpu_state.eaaddr = cpu_state.regs[sib & 7].l; + cpu_state.pc++; + break; + case 1: + cpu_state.pc++; + cpu_state.eaaddr = ((uint32_t) (int8_t) getbyte()) + cpu_state.regs[sib & 7].l; + break; + case 2: + cpu_state.eaaddr = (fastreadl(cs + cpu_state.pc + 1)) + cpu_state.regs[sib & 7].l; + cpu_state.pc += 5; + break; + } + /*SIB byte present*/ + if ((sib & 7) == 5 && !cpu_mod) + cpu_state.eaaddr = getlong(); + else if ((sib & 6) == 4 && !cpu_state.ssegs) { + easeg = ss; + cpu_state.ea_seg = &cpu_state.seg_ss; + } + if (((sib >> 3) & 7) != 4) + cpu_state.eaaddr += cpu_state.regs[(sib >> 3) & 7].l << (sib >> 6); + } else { + cpu_state.eaaddr = cpu_state.regs[cpu_rm].l; + if (cpu_mod) { + if (cpu_rm == 5 && !cpu_state.ssegs) { + easeg = ss; + cpu_state.ea_seg = &cpu_state.seg_ss; + } + if (cpu_mod == 1) { + cpu_state.eaaddr += ((uint32_t) (int8_t) (rmdat >> 8)); + cpu_state.pc++; + } else { + cpu_state.eaaddr += getlong(); + } + } else if (cpu_rm == 5) { + cpu_state.eaaddr = getlong(); + } + } + if (easeg != 0xFFFFFFFF && ((easeg + cpu_state.eaaddr) & 0xFFF) <= 0xFFC) { + uint32_t addr = easeg + cpu_state.eaaddr; + if (readlookup2[addr >> 12] != (uintptr_t) -1) + eal_r = (uint32_t *) (readlookup2[addr >> 12] + addr); + if (writelookup2[addr >> 12] != (uintptr_t) -1) + eal_w = (uint32_t *) (writelookup2[addr >> 12] + addr); + } } -static __inline void fetch_ea_16_long(uint32_t rmdat) +static __inline void +fetch_ea_16_long(uint32_t rmdat) { - eal_r = eal_w = NULL; - easeg = cpu_state.ea_seg->base; - if (!cpu_mod && cpu_rm == 6) - { - cpu_state.eaaddr = getword(); - } - else - { - switch (cpu_mod) - { - case 0: - cpu_state.eaaddr = 0; - break; - case 1: - cpu_state.eaaddr = (uint16_t)(int8_t)(rmdat >> 8); cpu_state.pc++; - break; - case 2: - cpu_state.eaaddr = getword(); - break; - } - cpu_state.eaaddr += (*mod1add[0][cpu_rm]) + (*mod1add[1][cpu_rm]); - if (mod1seg[cpu_rm] == &ss && !cpu_state.ssegs) - { - easeg = ss; - cpu_state.ea_seg = &cpu_state.seg_ss; - } - cpu_state.eaaddr &= 0xFFFF; - } - if (easeg != 0xFFFFFFFF && ((easeg + cpu_state.eaaddr) & 0xFFF) <= 0xFFC) - { - uint32_t addr = easeg + cpu_state.eaaddr; - if (readlookup2[addr >> 12] != (uintptr_t) -1) - eal_r = (uint32_t *)(readlookup2[addr >> 12] + addr); - if (writelookup2[addr >> 12] != (uintptr_t) -1) - eal_w = (uint32_t *)(writelookup2[addr >> 12] + addr); - } + eal_r = eal_w = NULL; + easeg = cpu_state.ea_seg->base; + if (!cpu_mod && cpu_rm == 6) { + cpu_state.eaaddr = getword(); + } else { + switch (cpu_mod) { + case 0: + cpu_state.eaaddr = 0; + break; + case 1: + cpu_state.eaaddr = (uint16_t) (int8_t) (rmdat >> 8); + cpu_state.pc++; + break; + case 2: + cpu_state.eaaddr = getword(); + break; + } + cpu_state.eaaddr += (*mod1add[0][cpu_rm]) + (*mod1add[1][cpu_rm]); + if (mod1seg[cpu_rm] == &ss && !cpu_state.ssegs) { + easeg = ss; + cpu_state.ea_seg = &cpu_state.seg_ss; + } + cpu_state.eaaddr &= 0xFFFF; + } + if (easeg != 0xFFFFFFFF && ((easeg + cpu_state.eaaddr) & 0xFFF) <= 0xFFC) { + uint32_t addr = easeg + cpu_state.eaaddr; + if (readlookup2[addr >> 12] != (uintptr_t) -1) + eal_r = (uint32_t *) (readlookup2[addr >> 12] + addr); + if (writelookup2[addr >> 12] != (uintptr_t) -1) + eal_w = (uint32_t *) (writelookup2[addr >> 12] + addr); + } } -#define fetch_ea_16(rmdat) cpu_state.pc++; cpu_mod=(rmdat >> 6) & 3; cpu_reg=(rmdat >> 3) & 7; cpu_rm = rmdat & 7; if (cpu_mod != 3) { fetch_ea_16_long(rmdat); if (cpu_state.abrt) return 1; } -#define fetch_ea_32(rmdat) cpu_state.pc++; cpu_mod=(rmdat >> 6) & 3; cpu_reg=(rmdat >> 3) & 7; cpu_rm = rmdat & 7; if (cpu_mod != 3) { fetch_ea_32_long(rmdat); } if (cpu_state.abrt) return 1 +#define fetch_ea_16(rmdat) \ + cpu_state.pc++; \ + cpu_mod = (rmdat >> 6) & 3; \ + cpu_reg = (rmdat >> 3) & 7; \ + cpu_rm = rmdat & 7; \ + if (cpu_mod != 3) { \ + fetch_ea_16_long(rmdat); \ + if (cpu_state.abrt) \ + return 1; \ + } +#define fetch_ea_32(rmdat) \ + cpu_state.pc++; \ + cpu_mod = (rmdat >> 6) & 3; \ + cpu_reg = (rmdat >> 3) & 7; \ + cpu_rm = rmdat & 7; \ + if (cpu_mod != 3) { \ + fetch_ea_32_long(rmdat); \ + } \ + if (cpu_state.abrt) \ + return 1 #include "x86_flags.h" +#define PREFETCH_RUN(instr_cycles, bytes, modrm, reads, reads_l, writes, writes_l, ea32) \ + do { \ + if (cpu_prefetch_cycles) \ + prefetch_run(instr_cycles, bytes, modrm, reads, reads_l, writes, writes_l, ea32); \ + } while (0) -/*Prefetch emulation is a fairly simplistic model: - - All instruction bytes must be fetched before it starts. - - Cycles used for non-instruction memory accesses are counted and subtracted - from the total cycles taken - - Any remaining cycles are used to refill the prefetch queue. - - Note that this is only used for 286 / 386 systems. It is disabled when the - internal cache on 486+ CPUs is enabled. -*/ -static int prefetch_bytes = 0; -static int prefetch_prefixes = 0; - -static void prefetch_run(int instr_cycles, int bytes, int modrm, int reads, int reads_l, int writes, int writes_l, int ea32) -{ - int mem_cycles = reads*cpu_cycles_read + reads_l*cpu_cycles_read_l + writes*cpu_cycles_write + writes_l*cpu_cycles_write_l; - - if (instr_cycles < mem_cycles) - instr_cycles = mem_cycles; - - prefetch_bytes -= prefetch_prefixes; - prefetch_bytes -= bytes; - if (modrm != -1) - { - if (ea32) - { - if ((modrm & 7) == 4) - { - if ((modrm & 0x700) == 0x500) - prefetch_bytes -= 5; - else if ((modrm & 0xc0) == 0x40) - prefetch_bytes -= 2; - else if ((modrm & 0xc0) == 0x80) - prefetch_bytes -= 5; - } - else - { - if ((modrm & 0xc7) == 0x05) - prefetch_bytes -= 4; - else if ((modrm & 0xc0) == 0x40) - prefetch_bytes--; - else if ((modrm & 0xc0) == 0x80) - prefetch_bytes -= 4; - } - } - else - { - if ((modrm & 0xc7) == 0x06) - prefetch_bytes -= 2; - else if ((modrm & 0xc0) != 0xc0) - prefetch_bytes -= ((modrm & 0xc0) >> 6); - } - } - - /* Fill up prefetch queue */ - while (prefetch_bytes < 0) - { - prefetch_bytes += cpu_prefetch_width; - cycles -= cpu_prefetch_cycles; - } - - /* Subtract cycles used for memory access by instruction */ - instr_cycles -= mem_cycles; - - while (instr_cycles >= cpu_prefetch_cycles) - { - prefetch_bytes += cpu_prefetch_width; - instr_cycles -= cpu_prefetch_cycles; - } - - prefetch_prefixes = 0; - if (prefetch_bytes > 16) - prefetch_bytes = 16; -} - -static void prefetch_flush() -{ - prefetch_bytes = 0; -} - -#define PREFETCH_RUN(instr_cycles, bytes, modrm, reads, reads_l, writes, writes_l, ea32) \ - do { if (cpu_prefetch_cycles) prefetch_run(instr_cycles, bytes, modrm, reads, reads_l, writes, writes_l, ea32); } while (0) - -#define PREFETCH_PREFIX() do { if (cpu_prefetch_cycles) prefetch_prefixes++; } while (0) +#define PREFETCH_PREFIX() \ + do { \ + if (cpu_prefetch_cycles) \ + prefetch_prefixes++; \ + } while (0) #define PREFETCH_FLUSH() prefetch_flush() - -#define OP_TABLE(name) ops_ ## name +#define OP_TABLE(name) ops_##name #if 0 -#define CLOCK_CYCLES(c) \ - {\ - if (fpu_cycles > 0) {\ - fpu_cycles -= (c);\ - if (fpu_cycles < 0) {\ - cycles += fpu_cycles;\ - }\ - } else {\ - cycles -= (c);\ - }\ - } -#define CLOCK_CYCLES_FPU(c) cycles -= (c) -#define CONCURRENCY_CYCLES(c) fpu_cycles = (c) +# define CLOCK_CYCLES(c) \ + { \ + if (fpu_cycles > 0) { \ + fpu_cycles -= (c); \ + if (fpu_cycles < 0) { \ + cycles += fpu_cycles; \ + } \ + } else { \ + cycles -= (c); \ + } \ + } +# define CLOCK_CYCLES_FPU(c) cycles -= (c) +# define CONCURRENCY_CYCLES(c) fpu_cycles = (c) #else -#define CLOCK_CYCLES(c) cycles -= (c) -#define CLOCK_CYCLES_FPU(c) cycles -= (c) -#define CONCURRENCY_CYCLES(c) +# define CLOCK_CYCLES(c) cycles -= (c) +# define CLOCK_CYCLES_FPU(c) cycles -= (c) +# define CONCURRENCY_CYCLES(c) #endif #define CLOCK_CYCLES_ALWAYS(c) cycles -= (c) - #include "386_ops.h" - #define CACHE_ON() (!(cr0 & (1 << 30)) && !(cpu_state.flags & T_FLAG)) #ifdef USE_DYNAREC -int cycles_main = 0; -static int cycles_old = 0; -static uint64_t tsc_old = 0; - -#ifdef USE_ACYCS -int acycs = 0; -#endif +int32_t cycles_main = 0; +static int32_t cycles_old = 0; +static uint64_t tsc_old = 0; +# ifdef USE_ACYCS +int32_t acycs = 0; +# endif void update_tsc(void) { - int cycdiff; + int cycdiff; uint64_t delta; cycdiff = cycles_old - cycles; -#ifdef USE_ACYCS +# ifdef USE_ACYCS if (inrecomp) - cycdiff += acycs; -#endif + cycdiff += acycs; +# endif delta = tsc - tsc_old; if (delta > 0) { - /* TSC has changed, this means interim timer processing has happened, - see how much we still need to add. */ - cycdiff -= delta; + /* TSC has changed, this means interim timer processing has happened, + see how much we still need to add. */ + cycdiff -= delta; } if (cycdiff > 0) - tsc += cycdiff; + tsc += cycdiff; if (cycdiff > 0) { - if (TIMER_VAL_LESS_THAN_VAL(timer_target, (uint32_t)tsc)) - timer_process_inline(); + if (TIMER_VAL_LESS_THAN_VAL(timer_target, (uint32_t) tsc)) + timer_process(); } } - static __inline void exec386_dynarec_int(void) { @@ -340,527 +269,688 @@ exec386_dynarec_int(void) x86_was_reset = 0; while (!cpu_block_end) { -#ifndef USE_NEW_DYNAREC - oldcs = CS; - oldcpl = CPL; -#endif - cpu_state.oldpc = cpu_state.pc; - cpu_state.op32 = use32; +# ifndef USE_NEW_DYNAREC + oldcs = CS; + oldcpl = CPL; +# endif + cpu_state.oldpc = cpu_state.pc; + cpu_state.op32 = use32; - cpu_state.ea_seg = &cpu_state.seg_ds; - cpu_state.ssegs = 0; + cpu_state.ea_seg = &cpu_state.seg_ds; + cpu_state.ssegs = 0; - fetchdat = fastreadl(cs + cpu_state.pc); -#ifdef ENABLE_386_DYNAREC_LOG - if (in_smm) - x386_dynarec_log("[%04X:%08X] fetchdat = %08X\n", CS, cpu_state.pc, fetchdat); -#endif + fetchdat = fastreadl_fetch(cs + cpu_state.pc); +# ifdef ENABLE_386_DYNAREC_LOG + if (in_smm) + x386_dynarec_log("[%04X:%08X] fetchdat = %08X\n", CS, cpu_state.pc, fetchdat); +# endif - if (!cpu_state.abrt) { - opcode = fetchdat & 0xFF; - fetchdat >>= 8; + if (!cpu_state.abrt) { + opcode = fetchdat & 0xFF; + fetchdat >>= 8; - trap = cpu_state.flags & T_FLAG; + trap = cpu_state.flags & T_FLAG; - cpu_state.pc++; - x86_opcodes[(opcode | cpu_state.op32) & 0x3ff](fetchdat); - } + cpu_state.pc++; + x86_opcodes[(opcode | cpu_state.op32) & 0x3ff](fetchdat); + } -#ifndef USE_NEW_DYNAREC - if (!use32) - cpu_state.pc &= 0xffff; -#endif +# ifndef USE_NEW_DYNAREC + if (!use32) + cpu_state.pc &= 0xffff; +# endif - if (((cs + cpu_state.pc) >> 12) != pccache) - CPU_BLOCK_END(); + if (((cs + cpu_state.pc) >> 12) != pccache) + CPU_BLOCK_END(); - if (cpu_end_block_after_ins) { - cpu_end_block_after_ins--; - if (!cpu_end_block_after_ins) - CPU_BLOCK_END(); - } + if (cpu_end_block_after_ins) { + cpu_end_block_after_ins--; + if (!cpu_end_block_after_ins) + CPU_BLOCK_END(); + } - if (cpu_state.abrt) - CPU_BLOCK_END(); - if (smi_line) - CPU_BLOCK_END(); - else if (trap) - CPU_BLOCK_END(); - else if (nmi && nmi_enable && nmi_mask) - CPU_BLOCK_END(); - else if ((cpu_state.flags & I_FLAG) && pic.int_pending && !cpu_end_block_after_ins) - CPU_BLOCK_END(); + if (cpu_state.abrt) + CPU_BLOCK_END(); + if (smi_line) + CPU_BLOCK_END(); + else if (trap) + CPU_BLOCK_END(); + else if (nmi && nmi_enable && nmi_mask) + CPU_BLOCK_END(); + else if ((cpu_state.flags & I_FLAG) && pic.int_pending && !cpu_end_block_after_ins) + CPU_BLOCK_END(); } - if (trap) { - trap = 0; -#ifndef USE_NEW_DYNAREC - oldcs = CS; -#endif - cpu_state.oldpc = cpu_state.pc; - x86_int(1); + if (!cpu_state.abrt && trap) { + trap = 0; +# ifndef USE_NEW_DYNAREC + oldcs = CS; +# endif + cpu_state.oldpc = cpu_state.pc; + dr[6] |= 0x4000; + x86_int(1); } cpu_end_block_after_ins = 0; } - static __inline void exec386_dynarec_dyn(void) { - uint32_t start_pc = 0, phys_addr = get_phys(cs + cpu_state.pc); - int hash = HASH(phys_addr); -#ifdef USE_NEW_DYNAREC + uint32_t start_pc = 0; + uint32_t phys_addr = get_phys(cs + cpu_state.pc); + int hash = HASH(phys_addr); +# ifdef USE_NEW_DYNAREC codeblock_t *block = &codeblock[codeblock_hash[hash]]; -#else +# else codeblock_t *block = codeblock_hash[hash]; -#endif +# endif int valid_block = 0; -#ifdef USE_NEW_DYNAREC +# ifdef USE_NEW_DYNAREC if (!cpu_state.abrt) -#else +# else if (block && !cpu_state.abrt) -#endif +# endif { - page_t *page = &pages[phys_addr >> 12]; + page_t *page = &pages[phys_addr >> 12]; - /* Block must match current CS, PC, code segment size, - and physical address. The physical address check will - also catch any page faults at this stage */ - valid_block = (block->pc == cs + cpu_state.pc) && (block->_cs == cs) && - (block->phys == phys_addr) && !((block->status ^ cpu_cur_status) & CPU_STATUS_FLAGS) && - ((block->status & cpu_cur_status & CPU_STATUS_MASK) == (cpu_cur_status & CPU_STATUS_MASK)); - if (!valid_block) { - uint64_t mask = (uint64_t)1 << ((phys_addr >> PAGE_MASK_SHIFT) & PAGE_MASK_MASK); -#ifdef USE_NEW_DYNAREC - int byte_offset = (phys_addr >> PAGE_BYTE_MASK_SHIFT) & PAGE_BYTE_MASK_OFFSET_MASK; - uint64_t byte_mask = 1ull << (PAGE_BYTE_MASK_MASK & 0x3f); + /* Block must match current CS, PC, code segment size, + and physical address. The physical address check will + also catch any page faults at this stage */ + valid_block = (block->pc == cs + cpu_state.pc) && (block->_cs == cs) && (block->phys == phys_addr) && !((block->status ^ cpu_cur_status) & CPU_STATUS_FLAGS) && ((block->status & cpu_cur_status & CPU_STATUS_MASK) == (cpu_cur_status & CPU_STATUS_MASK)); + if (!valid_block) { + uint64_t mask = (uint64_t) 1 << ((phys_addr >> PAGE_MASK_SHIFT) & PAGE_MASK_MASK); +# ifdef USE_NEW_DYNAREC + int byte_offset = (phys_addr >> PAGE_BYTE_MASK_SHIFT) & PAGE_BYTE_MASK_OFFSET_MASK; + uint64_t byte_mask = 1ULL << (PAGE_BYTE_MASK_MASK & 0x3f); - if ((page->code_present_mask & mask) || (page->byte_code_present_mask[byte_offset] & byte_mask)) -#else - if (page->code_present_mask[(phys_addr >> PAGE_MASK_INDEX_SHIFT) & PAGE_MASK_INDEX_MASK] & mask) -#endif - { - /* Walk page tree to see if we find the correct block */ - codeblock_t *new_block = codeblock_tree_find(phys_addr, cs); - if (new_block) { - valid_block = (new_block->pc == cs + cpu_state.pc) && (new_block->_cs == cs) && - (new_block->phys == phys_addr) && !((new_block->status ^ cpu_cur_status) & CPU_STATUS_FLAGS) && - ((new_block->status & cpu_cur_status & CPU_STATUS_MASK) == (cpu_cur_status & CPU_STATUS_MASK)); - if (valid_block) { - block = new_block; -#ifdef USE_NEW_DYNAREC - codeblock_hash[hash] = get_block_nr(block); -#endif - } - } - } - } + if ((page->code_present_mask & mask) || (page->byte_code_present_mask[byte_offset] & byte_mask)) +# else + if (page->code_present_mask[(phys_addr >> PAGE_MASK_INDEX_SHIFT) & PAGE_MASK_INDEX_MASK] & mask) +# endif + { + /* Walk page tree to see if we find the correct block */ + codeblock_t *new_block = codeblock_tree_find(phys_addr, cs); + if (new_block) { + valid_block = (new_block->pc == cs + cpu_state.pc) && (new_block->_cs == cs) && (new_block->phys == phys_addr) && !((new_block->status ^ cpu_cur_status) & CPU_STATUS_FLAGS) && ((new_block->status & cpu_cur_status & CPU_STATUS_MASK) == (cpu_cur_status & CPU_STATUS_MASK)); + if (valid_block) { + block = new_block; +# ifdef USE_NEW_DYNAREC + codeblock_hash[hash] = get_block_nr(block); +# endif + } + } + } + } - if (valid_block && (block->page_mask & *block->dirty_mask)) { -#ifdef USE_NEW_DYNAREC - codegen_check_flush(page, page->dirty_mask, phys_addr); - if (block->pc == BLOCK_PC_INVALID) - valid_block = 0; - else if (block->flags & CODEBLOCK_IN_DIRTY_LIST) - block->flags &= ~CODEBLOCK_WAS_RECOMPILED; -#else - codegen_check_flush(page, page->dirty_mask[(phys_addr >> 10) & 3], phys_addr); - page->dirty_mask[(phys_addr >> 10) & 3] = 0; - if (!block->valid) - valid_block = 0; -#endif - } - if (valid_block && block->page_mask2) { - /* We don't want the second page to cause a page - fault at this stage - that would break any - code crossing a page boundary where the first - page is present but the second isn't. Instead - allow the first page to be interpreted and for - the page fault to occur when the page boundary - is actually crossed.*/ -#ifdef USE_NEW_DYNAREC - uint32_t phys_addr_2 = get_phys_noabrt(block->pc + ((block->flags & CODEBLOCK_BYTE_MASK) ? 0x40 : 0x400)); -#else - uint32_t phys_addr_2 = get_phys_noabrt(block->endpc); -#endif - page_t *page_2 = &pages[phys_addr_2 >> 12]; + if (valid_block && (block->page_mask & *block->dirty_mask)) { +# ifdef USE_NEW_DYNAREC + codegen_check_flush(page, page->dirty_mask, phys_addr); + if (block->pc == BLOCK_PC_INVALID) + valid_block = 0; + else if (block->flags & CODEBLOCK_IN_DIRTY_LIST) + block->flags &= ~CODEBLOCK_WAS_RECOMPILED; +# else + codegen_check_flush(page, page->dirty_mask[(phys_addr >> 10) & 3], phys_addr); + page->dirty_mask[(phys_addr >> 10) & 3] = 0; + if (!block->valid) + valid_block = 0; +# endif + } + if (valid_block && block->page_mask2) { + /* We don't want the second page to cause a page + fault at this stage - that would break any + code crossing a page boundary where the first + page is present but the second isn't. Instead + allow the first page to be interpreted and for + the page fault to occur when the page boundary + is actually crossed.*/ +# ifdef USE_NEW_DYNAREC + uint32_t phys_addr_2 = get_phys_noabrt(block->pc + ((block->flags & CODEBLOCK_BYTE_MASK) ? 0x40 : 0x400)); +# else + uint32_t phys_addr_2 = get_phys_noabrt(block->endpc); +# endif + page_t *page_2 = &pages[phys_addr_2 >> 12]; - if ((block->phys_2 ^ phys_addr_2) & ~0xfff) - valid_block = 0; - else if (block->page_mask2 & *block->dirty_mask2) { -#ifdef USE_NEW_DYNAREC - codegen_check_flush(page_2, page_2->dirty_mask, phys_addr_2); - if (block->pc == BLOCK_PC_INVALID) - valid_block = 0; - else if (block->flags & CODEBLOCK_IN_DIRTY_LIST) - block->flags &= ~CODEBLOCK_WAS_RECOMPILED; -#else - codegen_check_flush(page_2, page_2->dirty_mask[(phys_addr_2 >> 10) & 3], phys_addr_2); - page_2->dirty_mask[(phys_addr_2 >> 10) & 3] = 0; - if (!block->valid) - valid_block = 0; -#endif - } - } -#ifdef USE_NEW_DYNAREC - if (valid_block && (block->flags & CODEBLOCK_IN_DIRTY_LIST)) { - block->flags &= ~CODEBLOCK_WAS_RECOMPILED; - if (block->flags & CODEBLOCK_BYTE_MASK) - block->flags |= CODEBLOCK_NO_IMMEDIATES; - else - block->flags |= CODEBLOCK_BYTE_MASK; - } - if (valid_block && (block->flags & CODEBLOCK_WAS_RECOMPILED) && (block->flags & CODEBLOCK_STATIC_TOP) && block->TOP != (cpu_state.TOP & 7)) -#else - if (valid_block && block->was_recompiled && (block->flags & CODEBLOCK_STATIC_TOP) && block->TOP != cpu_state.TOP) -#endif - { - /* FPU top-of-stack does not match the value this block was compiled - with, re-compile using dynamic top-of-stack*/ -#ifdef USE_NEW_DYNAREC - block->flags &= ~(CODEBLOCK_STATIC_TOP | CODEBLOCK_WAS_RECOMPILED); -#else - block->flags &= ~CODEBLOCK_STATIC_TOP; - block->was_recompiled = 0; -#endif - } + if ((block->phys_2 ^ phys_addr_2) & ~0xfff) + valid_block = 0; + else if (block->page_mask2 & *block->dirty_mask2) { +# ifdef USE_NEW_DYNAREC + codegen_check_flush(page_2, page_2->dirty_mask, phys_addr_2); + if (block->pc == BLOCK_PC_INVALID) + valid_block = 0; + else if (block->flags & CODEBLOCK_IN_DIRTY_LIST) + block->flags &= ~CODEBLOCK_WAS_RECOMPILED; +# else + codegen_check_flush(page_2, page_2->dirty_mask[(phys_addr_2 >> 10) & 3], phys_addr_2); + page_2->dirty_mask[(phys_addr_2 >> 10) & 3] = 0; + if (!block->valid) + valid_block = 0; +# endif + } + } +# ifdef USE_NEW_DYNAREC + if (valid_block && (block->flags & CODEBLOCK_IN_DIRTY_LIST)) { + block->flags &= ~CODEBLOCK_WAS_RECOMPILED; + if (block->flags & CODEBLOCK_BYTE_MASK) + block->flags |= CODEBLOCK_NO_IMMEDIATES; + else + block->flags |= CODEBLOCK_BYTE_MASK; + } + if (valid_block && (block->flags & CODEBLOCK_WAS_RECOMPILED) && (block->flags & CODEBLOCK_STATIC_TOP) && block->TOP != (cpu_state.TOP & 7)) +# else + if (valid_block && block->was_recompiled && (block->flags & CODEBLOCK_STATIC_TOP) && block->TOP != cpu_state.TOP) +# endif + { + /* FPU top-of-stack does not match the value this block was compiled + with, re-compile using dynamic top-of-stack*/ +# ifdef USE_NEW_DYNAREC + block->flags &= ~(CODEBLOCK_STATIC_TOP | CODEBLOCK_WAS_RECOMPILED); +# else + block->flags &= ~CODEBLOCK_STATIC_TOP; + block->was_recompiled = 0; +# endif + } } -#ifdef USE_NEW_DYNAREC +# ifdef USE_NEW_DYNAREC if (valid_block && (block->flags & CODEBLOCK_WAS_RECOMPILED)) -#else +# else if (valid_block && block->was_recompiled) -#endif +# endif { - void (*code)() = (void *)&block->data[BLOCK_START]; + void (*code)(void) = (void *) &block->data[BLOCK_START]; -#ifndef USE_NEW_DYNAREC - codeblock_hash[hash] = block; -#endif - inrecomp = 1; - code(); -#ifdef USE_ACYCS - acycs = 0; -#endif - inrecomp = 0; +# ifndef USE_NEW_DYNAREC + codeblock_hash[hash] = block; +# endif + inrecomp = 1; + code(); +# ifdef USE_ACYCS + acycs = 0; +# endif + inrecomp = 0; -#ifndef USE_NEW_DYNAREC - if (!use32) cpu_state.pc &= 0xffff; -#endif +# ifndef USE_NEW_DYNAREC + if (!use32) + cpu_state.pc &= 0xffff; +# endif } else if (valid_block && !cpu_state.abrt) { -#ifdef USE_NEW_DYNAREC - start_pc = cs + cpu_state.pc; - const int max_block_size = (block->flags & CODEBLOCK_BYTE_MASK) ? ((128 - 25) - (start_pc & 0x3f)) : 1000; -#else - start_pc = cpu_state.pc; -#endif +# ifdef USE_NEW_DYNAREC + start_pc = cs + cpu_state.pc; + const int max_block_size = (block->flags & CODEBLOCK_BYTE_MASK) ? ((128 - 25) - (start_pc & 0x3f)) : 1000; +# else + start_pc = cpu_state.pc; +# endif - cpu_block_end = 0; - x86_was_reset = 0; + cpu_block_end = 0; + x86_was_reset = 0; -#if defined(__APPLE__) && defined(__aarch64__) - pthread_jit_write_protect_np(0); -#endif - codegen_block_start_recompile(block); - codegen_in_recompile = 1; +# if defined(__APPLE__) && defined(__aarch64__) + if (__builtin_available(macOS 11.0, *)) { + pthread_jit_write_protect_np(0); + } +# endif + codegen_block_start_recompile(block); + codegen_in_recompile = 1; - while (!cpu_block_end) { -#ifndef USE_NEW_DYNAREC - oldcs = CS; - oldcpl = CPL; -#endif - cpu_state.oldpc = cpu_state.pc; - cpu_state.op32 = use32; + while (!cpu_block_end) { +# ifndef USE_NEW_DYNAREC + oldcs = CS; + oldcpl = CPL; +# endif + cpu_state.oldpc = cpu_state.pc; + cpu_state.op32 = use32; - cpu_state.ea_seg = &cpu_state.seg_ds; - cpu_state.ssegs = 0; + cpu_state.ea_seg = &cpu_state.seg_ds; + cpu_state.ssegs = 0; - fetchdat = fastreadl(cs + cpu_state.pc); -#ifdef ENABLE_386_DYNAREC_LOG - if (in_smm) - x386_dynarec_log("[%04X:%08X] fetchdat = %08X\n", CS, cpu_state.pc, fetchdat); -#endif + fetchdat = fastreadl_fetch(cs + cpu_state.pc); +# ifdef ENABLE_386_DYNAREC_LOG + if (in_smm) + x386_dynarec_log("[%04X:%08X] fetchdat = %08X\n", CS, cpu_state.pc, fetchdat); +# endif - if (!cpu_state.abrt) { - opcode = fetchdat & 0xFF; - fetchdat >>= 8; + if (!cpu_state.abrt) { + opcode = fetchdat & 0xFF; + fetchdat >>= 8; - cpu_state.pc++; + cpu_state.pc++; - codegen_generate_call(opcode, x86_opcodes[(opcode | cpu_state.op32) & 0x3ff], fetchdat, cpu_state.pc, cpu_state.pc-1); + codegen_generate_call(opcode, x86_opcodes[(opcode | cpu_state.op32) & 0x3ff], fetchdat, cpu_state.pc, cpu_state.pc - 1); - x86_opcodes[(opcode | cpu_state.op32) & 0x3ff](fetchdat); + x86_opcodes[(opcode | cpu_state.op32) & 0x3ff](fetchdat); - if (x86_was_reset) - break; - } + if (x86_was_reset) + break; + } -#ifndef USE_NEW_DYNAREC - if (!use32) - cpu_state.pc &= 0xffff; -#endif +# ifndef USE_NEW_DYNAREC + if (!use32) + cpu_state.pc &= 0xffff; +# endif - /* Cap source code at 4000 bytes per block; this - will prevent any block from spanning more than - 2 pages. In practice this limit will never be - hit, as host block size is only 2kB*/ -#ifdef USE_NEW_DYNAREC - if (((cs + cpu_state.pc) - start_pc) >= max_block_size) -#else - if ((cpu_state.pc - start_pc) > 1000) -#endif - CPU_BLOCK_END(); + /* Cap source code at 4000 bytes per block; this + will prevent any block from spanning more than + 2 pages. In practice this limit will never be + hit, as host block size is only 2kB*/ +# ifdef USE_NEW_DYNAREC + if (((cs + cpu_state.pc) - start_pc) >= max_block_size) +# else + if ((cpu_state.pc - start_pc) > 1000) +# endif + CPU_BLOCK_END(); - if (cpu_state.flags & T_FLAG) - CPU_BLOCK_END(); - if (smi_line) - CPU_BLOCK_END(); - if (nmi && nmi_enable && nmi_mask) - CPU_BLOCK_END(); - if ((cpu_state.flags & I_FLAG) && pic.int_pending && !cpu_end_block_after_ins) - CPU_BLOCK_END(); + if (cpu_state.flags & T_FLAG) + CPU_BLOCK_END(); + if (smi_line) + CPU_BLOCK_END(); + if (nmi && nmi_enable && nmi_mask) + CPU_BLOCK_END(); + if ((cpu_state.flags & I_FLAG) && pic.int_pending && !cpu_end_block_after_ins) + CPU_BLOCK_END(); - if (cpu_end_block_after_ins) { - cpu_end_block_after_ins--; - if (!cpu_end_block_after_ins) - CPU_BLOCK_END(); - } + if (cpu_end_block_after_ins) { + cpu_end_block_after_ins--; + if (!cpu_end_block_after_ins) + CPU_BLOCK_END(); + } - if (cpu_state.abrt) { - if (!(cpu_state.abrt & ABRT_EXPECTED)) - codegen_block_remove(); - CPU_BLOCK_END(); - } - } + if (cpu_state.abrt) { + if (!(cpu_state.abrt & ABRT_EXPECTED)) + codegen_block_remove(); + CPU_BLOCK_END(); + } + } - cpu_end_block_after_ins = 0; + cpu_end_block_after_ins = 0; - if ((!cpu_state.abrt || (cpu_state.abrt & ABRT_EXPECTED)) && !x86_was_reset) - codegen_block_end_recompile(block); + if ((!cpu_state.abrt || (cpu_state.abrt & ABRT_EXPECTED)) && !x86_was_reset) + codegen_block_end_recompile(block); - if (x86_was_reset) - codegen_reset(); + if (x86_was_reset) + codegen_reset(); - codegen_in_recompile = 0; -#if defined(__APPLE__) && defined(__aarch64__) - pthread_jit_write_protect_np(1); -#endif + codegen_in_recompile = 0; +# if defined(__APPLE__) && defined(__aarch64__) + if (__builtin_available(macOS 11.0, *)) { + pthread_jit_write_protect_np(1); + } +# endif } else if (!cpu_state.abrt) { - /* Mark block but do not recompile */ -#ifdef USE_NEW_DYNAREC - start_pc = cs + cpu_state.pc; - const int max_block_size = (block->flags & CODEBLOCK_BYTE_MASK) ? ((128 - 25) - (start_pc & 0x3f)) : 1000; -#else - start_pc = cpu_state.pc; -#endif + /* Mark block but do not recompile */ +# ifdef USE_NEW_DYNAREC + start_pc = cs + cpu_state.pc; + const int max_block_size = (block->flags & CODEBLOCK_BYTE_MASK) ? ((128 - 25) - (start_pc & 0x3f)) : 1000; +# else + start_pc = cpu_state.pc; +# endif - cpu_block_end = 0; - x86_was_reset = 0; + cpu_block_end = 0; + x86_was_reset = 0; - codegen_block_init(phys_addr); + codegen_block_init(phys_addr); - while (!cpu_block_end) { -#ifndef USE_NEW_DYNAREC - oldcs = CS; - oldcpl = CPL; -#endif - cpu_state.oldpc = cpu_state.pc; - cpu_state.op32 = use32; + while (!cpu_block_end) { +# ifndef USE_NEW_DYNAREC + oldcs = CS; + oldcpl = CPL; +# endif + cpu_state.oldpc = cpu_state.pc; + cpu_state.op32 = use32; - cpu_state.ea_seg = &cpu_state.seg_ds; - cpu_state.ssegs = 0; + cpu_state.ea_seg = &cpu_state.seg_ds; + cpu_state.ssegs = 0; - codegen_endpc = (cs + cpu_state.pc) + 8; - fetchdat = fastreadl(cs + cpu_state.pc); + codegen_endpc = (cs + cpu_state.pc) + 8; + fetchdat = fastreadl_fetch(cs + cpu_state.pc); -#ifdef ENABLE_386_DYNAREC_LOG - if (in_smm) - x386_dynarec_log("[%04X:%08X] fetchdat = %08X\n", CS, cpu_state.pc, fetchdat); -#endif +# ifdef ENABLE_386_DYNAREC_LOG + if (in_smm) + x386_dynarec_log("[%04X:%08X] fetchdat = %08X\n", CS, cpu_state.pc, fetchdat); +# endif - if (!cpu_state.abrt) { - opcode = fetchdat & 0xFF; - fetchdat >>= 8; + if (!cpu_state.abrt) { + opcode = fetchdat & 0xFF; + fetchdat >>= 8; - cpu_state.pc++; + cpu_state.pc++; - x86_opcodes[(opcode | cpu_state.op32) & 0x3ff](fetchdat); + x86_opcodes[(opcode | cpu_state.op32) & 0x3ff](fetchdat); - if (x86_was_reset) - break; - } + if (x86_was_reset) + break; + } -#ifndef USE_NEW_DYNAREC - if (!use32) - cpu_state.pc &= 0xffff; -#endif +# ifndef USE_NEW_DYNAREC + if (!use32) + cpu_state.pc &= 0xffff; +# endif - /* Cap source code at 4000 bytes per block; this - will prevent any block from spanning more than - 2 pages. In practice this limit will never be - hit, as host block size is only 2kB */ -#ifdef USE_NEW_DYNAREC - if (((cs + cpu_state.pc) - start_pc) >= max_block_size) -#else - if ((cpu_state.pc - start_pc) > 1000) -#endif - CPU_BLOCK_END(); + /* Cap source code at 4000 bytes per block; this + will prevent any block from spanning more than + 2 pages. In practice this limit will never be + hit, as host block size is only 2kB */ +# ifdef USE_NEW_DYNAREC + if (((cs + cpu_state.pc) - start_pc) >= max_block_size) +# else + if ((cpu_state.pc - start_pc) > 1000) +# endif + CPU_BLOCK_END(); - if (cpu_state.flags & T_FLAG) - CPU_BLOCK_END(); - if (smi_line) - CPU_BLOCK_END(); - if (nmi && nmi_enable && nmi_mask) - CPU_BLOCK_END(); - if ((cpu_state.flags & I_FLAG) && pic.int_pending && !cpu_end_block_after_ins) - CPU_BLOCK_END(); + if (cpu_state.flags & T_FLAG) + CPU_BLOCK_END(); + if (smi_line) + CPU_BLOCK_END(); + if (nmi && nmi_enable && nmi_mask) + CPU_BLOCK_END(); + if ((cpu_state.flags & I_FLAG) && pic.int_pending && !cpu_end_block_after_ins) + CPU_BLOCK_END(); - if (cpu_end_block_after_ins) { - cpu_end_block_after_ins--; - if (!cpu_end_block_after_ins) - CPU_BLOCK_END(); - } + if (cpu_end_block_after_ins) { + cpu_end_block_after_ins--; + if (!cpu_end_block_after_ins) + CPU_BLOCK_END(); + } - if (cpu_state.abrt) { - if (!(cpu_state.abrt & ABRT_EXPECTED)) - codegen_block_remove(); - CPU_BLOCK_END(); - } - } + if (cpu_state.abrt) { + if (!(cpu_state.abrt & ABRT_EXPECTED)) + codegen_block_remove(); + CPU_BLOCK_END(); + } + } - cpu_end_block_after_ins = 0; + cpu_end_block_after_ins = 0; - if ((!cpu_state.abrt || (cpu_state.abrt & ABRT_EXPECTED)) && !x86_was_reset) - codegen_block_end(); + if ((!cpu_state.abrt || (cpu_state.abrt & ABRT_EXPECTED)) && !x86_was_reset) + codegen_block_end(); - if (x86_was_reset) - codegen_reset(); + if (x86_was_reset) + codegen_reset(); } -#ifdef USE_NEW_DYNAREC +# ifdef USE_NEW_DYNAREC else - cpu_state.oldpc = cpu_state.pc; -#endif + cpu_state.oldpc = cpu_state.pc; +# endif } - void -exec386_dynarec(int cycs) +exec386_dynarec(int32_t cycs) { - int vector, tempi; - int cycdiff; - int oldcyc, oldcyc2; - uint64_t oldtsc, delta; + int vector; + int tempi; + int32_t cycdiff; + int32_t oldcyc; + int32_t oldcyc2; + uint64_t oldtsc; + uint64_t delta; - int cyc_period = cycs / 2000; /*5us*/ + int32_t cyc_period = cycs / 2000; /*5us*/ -#ifdef USE_ACYCS +# ifdef USE_ACYCS acycs = 0; -#endif +# endif cycles_main += cycs; while (cycles_main > 0) { - int cycles_start; + int32_t cycles_start; - cycles += cyc_period; - cycles_start = cycles; + cycles += cyc_period; + cycles_start = cycles; - while (cycles > 0) { -#ifndef USE_NEW_DYNAREC - oldcs = CS; - cpu_state.oldpc = cpu_state.pc; - oldcpl = CPL; - cpu_state.op32 = use32; + while (cycles > 0) { +# ifndef USE_NEW_DYNAREC + oldcs = CS; + cpu_state.oldpc = cpu_state.pc; + oldcpl = CPL; + cpu_state.op32 = use32; - cycdiff = 0; -#endif - oldcyc = oldcyc2 = cycles; - cycles_old = cycles; - oldtsc = tsc; - tsc_old = tsc; - if (!CACHE_ON()) /*Interpret block*/ - { - exec386_dynarec_int(); - } - else - { - exec386_dynarec_dyn(); - } + cycdiff = 0; +# endif + oldcyc = oldcyc2 = cycles; + cycles_old = cycles; + oldtsc = tsc; + tsc_old = tsc; + if (!CACHE_ON()) /*Interpret block*/ + { + exec386_dynarec_int(); + } else { + exec386_dynarec_dyn(); + } - if (cpu_state.abrt) { - flags_rebuild(); - tempi = cpu_state.abrt & ABRT_MASK; - cpu_state.abrt = 0; - x86_doabrt(tempi); - if (cpu_state.abrt) { - cpu_state.abrt = 0; - cpu_state.pc = cpu_state.oldpc; -#ifndef USE_NEW_DYNAREC - CS = oldcs; -#endif - pmodeint(8, 0); - if (cpu_state.abrt) { - cpu_state.abrt = 0; - softresetx86(); - cpu_set_edx(); -#ifdef ENABLE_386_DYNAREC_LOG - x386_dynarec_log("Triple fault - reset\n"); -#endif - } - } - } + if (cpu_state.abrt) { + flags_rebuild(); + tempi = cpu_state.abrt & ABRT_MASK; + cpu_state.abrt = 0; + x86_doabrt(tempi); + if (cpu_state.abrt) { + cpu_state.abrt = 0; + cpu_state.pc = cpu_state.oldpc; +# ifndef USE_NEW_DYNAREC + CS = oldcs; +# endif + pmodeint(8, 0); + if (cpu_state.abrt) { + cpu_state.abrt = 0; + softresetx86(); + cpu_set_edx(); +# ifdef ENABLE_386_DYNAREC_LOG + x386_dynarec_log("Triple fault - reset\n"); +# endif + } + } + } - if (smi_line) - enter_smm_check(0); - else if (nmi && nmi_enable && nmi_mask) { - if (is486 && (cpu_fast_off_flags & 0x20000000)) - cpu_fast_off_count = cpu_fast_off_val + 1; + if (smi_line) + enter_smm_check(0); + else if (nmi && nmi_enable && nmi_mask) { +# ifndef USE_NEW_DYNAREC + oldcs = CS; +# endif + cpu_state.oldpc = cpu_state.pc; + x86_int(2); + nmi_enable = 0; +# ifdef OLD_NMI_BEHAVIOR + if (nmi_auto_clear) { + nmi_auto_clear = 0; + nmi = 0; + } +# else + nmi = 0; +# endif + } else if ((cpu_state.flags & I_FLAG) && pic.int_pending) { + vector = picinterrupt(); + if (vector != -1) { +# ifndef USE_NEW_DYNAREC + oldcs = CS; +# endif + cpu_state.oldpc = cpu_state.pc; + x86_int(vector); + } + } -#ifndef USE_NEW_DYNAREC - oldcs = CS; -#endif - cpu_state.oldpc = cpu_state.pc; - x86_int(2); - nmi_enable = 0; -#ifdef OLD_NMI_BEHAVIOR - if (nmi_auto_clear) { - nmi_auto_clear = 0; - nmi = 0; - } -#else - nmi = 0; -#endif - } else if ((cpu_state.flags & I_FLAG) && pic.int_pending) { - vector = picinterrupt(); - if (vector != -1) { -#ifndef USE_NEW_DYNAREC - oldcs = CS; -#endif - cpu_state.oldpc = cpu_state.pc; - x86_int(vector); - } - } + cycdiff = oldcyc - cycles; + delta = tsc - oldtsc; + if (delta > 0) { + /* TSC has changed, this means interim timer processing has happened, + see how much we still need to add. */ + cycdiff -= delta; + if (cycdiff > 0) + tsc += cycdiff; + } else { + /* TSC has not changed. */ + tsc += cycdiff; + } - cycdiff = oldcyc - cycles; - delta = tsc - oldtsc; - if (delta > 0) { - /* TSC has changed, this means interim timer processing has happened, - see how much we still need to add. */ - cycdiff -= delta; - if (cycdiff > 0) - tsc += cycdiff; - } else { - /* TSC has not changed. */ - tsc += cycdiff; - } + if (cycdiff > 0) { + if (TIMER_VAL_LESS_THAN_VAL(timer_target, (uint32_t) tsc)) + timer_process(); + } - if (cycdiff > 0) { - if (TIMER_VAL_LESS_THAN_VAL(timer_target, (uint32_t) tsc)) - timer_process_inline(); - } - } +# ifdef USE_GDBSTUB + if (gdbstub_instruction()) + return; +# endif + } - cycles_main -= (cycles_start - cycles); + cycles_main -= (cycles_start - cycles); } } #endif + +void +exec386(int32_t cycs) +{ + int vector; + int tempi; + int32_t cycdiff; + int32_t oldcyc; + int32_t cycle_period; + int32_t ins_cycles; + uint32_t addr; + + cycles += cycs; + + while (cycles > 0) { + cycle_period = (timer_target - (uint32_t) tsc) + 1; + + x86_was_reset = 0; + cycdiff = 0; + oldcyc = cycles; + while (cycdiff < cycle_period) { + ins_cycles = cycles; + +#ifndef USE_NEW_DYNAREC + oldcs = CS; + oldcpl = CPL; +#endif + cpu_state.oldpc = cpu_state.pc; + cpu_state.op32 = use32; + +#ifndef USE_NEW_DYNAREC + x86_was_reset = 0; +#endif + + cpu_state.ea_seg = &cpu_state.seg_ds; + cpu_state.ssegs = 0; + + fetchdat = fastreadl_fetch(cs + cpu_state.pc); + + if (!cpu_state.abrt) { +#ifdef ENABLE_386_LOG + if (in_smm) + x386_dynarec_log("[%04X:%08X] %08X\n", CS, cpu_state.pc, fetchdat); +#endif + opcode = fetchdat & 0xFF; + fetchdat >>= 8; + trap = cpu_state.flags & T_FLAG; + + cpu_state.pc++; + x86_opcodes[(opcode | cpu_state.op32) & 0x3ff](fetchdat); + if (x86_was_reset) + break; + } +#ifdef ENABLE_386_LOG + else if (in_smm) + x386_dynarec_log("[%04X:%08X] ABRT\n", CS, cpu_state.pc); +#endif + +#ifndef USE_NEW_DYNAREC + if (!use32) + cpu_state.pc &= 0xffff; +#endif + + if (cpu_end_block_after_ins) + cpu_end_block_after_ins--; + + if (cpu_state.abrt) { + flags_rebuild(); + tempi = cpu_state.abrt & ABRT_MASK; + cpu_state.abrt = 0; + x86_doabrt(tempi); + if (cpu_state.abrt) { + cpu_state.abrt = 0; +#ifndef USE_NEW_DYNAREC + CS = oldcs; +#endif + cpu_state.pc = cpu_state.oldpc; + x386_dynarec_log("Double fault\n"); + pmodeint(8, 0); + if (cpu_state.abrt) { + cpu_state.abrt = 0; + softresetx86(); + cpu_set_edx(); +#ifdef ENABLE_386_LOG + x386_dynarec_log("Triple fault - reset\n"); +#endif + } + } + } else if (trap) { + flags_rebuild(); + trap = 0; +#ifndef USE_NEW_DYNAREC + oldcs = CS; +#endif + cpu_state.oldpc = cpu_state.pc; + dr[6] |= 0x4000; + x86_int(1); + } + + if (smi_line) + enter_smm_check(0); + else if (nmi && nmi_enable && nmi_mask) { +#ifndef USE_NEW_DYNAREC + oldcs = CS; +#endif + cpu_state.oldpc = cpu_state.pc; + x86_int(2); + nmi_enable = 0; +#ifdef OLD_NMI_BEHAVIOR + if (nmi_auto_clear) { + nmi_auto_clear = 0; + nmi = 0; + } +#else + nmi = 0; +#endif + } else if ((cpu_state.flags & I_FLAG) && pic.int_pending && !cpu_end_block_after_ins) { + vector = picinterrupt(); + if (vector != -1) { + flags_rebuild(); + if (msw & 1) + pmodeint(vector, 0); + else { + writememw(ss, (SP - 2) & 0xFFFF, cpu_state.flags); + writememw(ss, (SP - 4) & 0xFFFF, CS); + writememw(ss, (SP - 6) & 0xFFFF, cpu_state.pc); + SP -= 6; + addr = (vector << 2) + idt.base; + cpu_state.flags &= ~I_FLAG; + cpu_state.flags &= ~T_FLAG; + cpu_state.pc = readmemw(0, addr); + loadcs(readmemw(0, addr + 2)); + } + } + } + + ins_cycles -= cycles; + tsc += ins_cycles; + + cycdiff = oldcyc - cycles; + + if (timetolive) { + timetolive--; + if (!timetolive) + fatal("Life expired\n"); + } + + if (TIMER_VAL_LESS_THAN_VAL(timer_target, (uint32_t) tsc)) + timer_process(); + +#ifdef USE_GDBSTUB + if (gdbstub_instruction()) + return; +#endif + } + } +} diff --git a/src/cpu/386_dynarec_ops.c b/src/cpu/386_dynarec_ops.c index 2eb3a5f00..77b72ef59 100644 --- a/src/cpu/386_dynarec_ops.c +++ b/src/cpu/386_dynarec_ops.c @@ -5,7 +5,7 @@ #include #include #ifndef INFINITY -# define INFINITY (__builtin_inff()) +# define INFINITY (__builtin_inff()) #endif #include <86box/86box.h> @@ -13,64 +13,76 @@ #include <86box/timer.h> #include "x86.h" #include "x86_ops.h" +#include "x86seg_common.h" +#include "x86seg.h" #include "x87.h" #include "x86_flags.h" #include <86box/io.h> #include <86box/mem.h> #include <86box/nmi.h> #include <86box/pic.h> +#include <86box/gdbstub.h> #include "codegen.h" +#include <86box/plat_unused.h> #define CPU_BLOCK_END() cpu_block_end = 1 +#ifndef IS_DYNAREC +# define IS_DYNAREC +#endif + #include "386_common.h" - -static __inline void fetch_ea_32_long(uint32_t rmdat) +static __inline void +fetch_ea_32_long(UNUSED(uint32_t rmdat)) { - eal_r = eal_w = NULL; - easeg = cpu_state.ea_seg->base; - if (easeg != 0xFFFFFFFF && ((easeg + cpu_state.eaaddr) & 0xFFF) <= 0xFFC) - { - uint32_t addr = easeg + cpu_state.eaaddr; - if ( readlookup2[addr >> 12] != (uintptr_t) LOOKUP_INV) - eal_r = (uint32_t *)(readlookup2[addr >> 12] + addr); - if (writelookup2[addr >> 12] != (uintptr_t) LOOKUP_INV) - eal_w = (uint32_t *)(writelookup2[addr >> 12] + addr); - } + eal_r = eal_w = NULL; + easeg = cpu_state.ea_seg->base; + if (easeg != 0xFFFFFFFF && ((easeg + cpu_state.eaaddr) & 0xFFF) <= 0xFFC) { + uint32_t addr = easeg + cpu_state.eaaddr; + if (readlookup2[addr >> 12] != (uintptr_t) LOOKUP_INV) + eal_r = (uint32_t *) (readlookup2[addr >> 12] + addr); + if (writelookup2[addr >> 12] != (uintptr_t) LOOKUP_INV) + eal_w = (uint32_t *) (writelookup2[addr >> 12] + addr); + } } -static __inline void fetch_ea_16_long(uint32_t rmdat) +static __inline void +fetch_ea_16_long(UNUSED(uint32_t rmdat)) { - eal_r = eal_w = NULL; - easeg = cpu_state.ea_seg->base; - if (easeg != 0xFFFFFFFF && ((easeg + cpu_state.eaaddr) & 0xFFF) <= 0xFFC) - { - uint32_t addr = easeg + cpu_state.eaaddr; - if ( readlookup2[addr >> 12] != (uintptr_t) LOOKUP_INV) - eal_r = (uint32_t *)(readlookup2[addr >> 12] + addr); - if (writelookup2[addr >> 12] != (uintptr_t) LOOKUP_INV) - eal_w = (uint32_t *)(writelookup2[addr >> 12] + addr); - } + eal_r = eal_w = NULL; + easeg = cpu_state.ea_seg->base; + if (easeg != 0xFFFFFFFF && ((easeg + cpu_state.eaaddr) & 0xFFF) <= 0xFFC) { + uint32_t addr = easeg + cpu_state.eaaddr; + if (readlookup2[addr >> 12] != (uintptr_t) LOOKUP_INV) + eal_r = (uint32_t *) (readlookup2[addr >> 12] + addr); + if (writelookup2[addr >> 12] != (uintptr_t) LOOKUP_INV) + eal_w = (uint32_t *) (writelookup2[addr >> 12] + addr); + } } -#define fetch_ea_16(rmdat) cpu_state.pc++; if (cpu_mod != 3) fetch_ea_16_long(rmdat); -#define fetch_ea_32(rmdat) cpu_state.pc++; if (cpu_mod != 3) fetch_ea_32_long(rmdat); - +#define fetch_ea_16(rmdat) \ + cpu_state.pc++; \ + if (cpu_mod != 3) \ + fetch_ea_16_long(rmdat); +#define fetch_ea_32(rmdat) \ + cpu_state.pc++; \ + if (cpu_mod != 3) \ + fetch_ea_32_long(rmdat); #define PREFETCH_RUN(instr_cycles, bytes, modrm, reads, read_ls, writes, write_ls, ea32) #define PREFETCH_PREFIX() #define PREFETCH_FLUSH() -#define OP_TABLE(name) dynarec_ops_ ## name +#define OP_TABLE(name) dynarec_ops_##name #define CLOCK_CYCLES(c) #if 0 -#define CLOCK_CYCLES_FPU(c) -#define CONCURRENCY_CYCLES(c) fpu_cycles = (c) +# define CLOCK_CYCLES_FPU(c) +# define CONCURRENCY_CYCLES(c) fpu_cycles = (c) #else -#define CLOCK_CYCLES_FPU(c) -#define CONCURRENCY_CYCLES(c) +# define CLOCK_CYCLES_FPU(c) +# define CONCURRENCY_CYCLES(c) #endif #define CLOCK_CYCLES_ALWAYS(c) cycles -= (c) diff --git a/src/cpu/386_ops.h b/src/cpu/386_ops.h index 8d2b9edf9..8a0f4cd5a 100644 --- a/src/cpu/386_ops.h +++ b/src/cpu/386_ops.h @@ -1,24 +1,24 @@ /* - * VARCem Virtual ARchaeological Computer EMulator. - * An emulator of (mostly) x86-based PC systems and devices, - * using the ISA,EISA,VLB,MCA and PCI system buses, roughly - * spanning the era between 1981 and 1995. + * VARCem Virtual ARchaeological Computer EMulator. + * An emulator of (mostly) x86-based PC systems and devices, + * using the ISA,EISA,VLB,MCA and PCI system buses, roughly + * spanning the era between 1981 and 1995. * - * This file is part of the VARCem Project. + * This file is part of the VARCem Project. * - * 286/386+ instruction handlers list. + * 286/386+ instruction handlers list. * * * - * Authors: Fred N. van Kempen, - * Sarah Walker, - * leilei, - * Miran Grca, + * Authors: Fred N. van Kempen, + * Sarah Walker, + * leilei, + * Miran Grca, * - * Copyright 2018 Fred N. van Kempen. - * Copyright 2008-2018 Sarah Walker. - * Copyright 2016-2018 leilei. - * Copyright 2016-2018 Miran Grca. + * Copyright 2018 Fred N. van Kempen. + * Copyright 2008-2018 Sarah Walker. + * Copyright 2016-2018 leilei. + * Copyright 2016-2018 Miran Grca. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -40,137 +40,147 @@ */ #include "x86_ops.h" +#define ILLEGAL_ON(cond) \ + do { \ + if ((cond)) { \ + cpu_state.pc = cpu_state.oldpc; \ + x86illegal(); \ + return 0; \ + } \ + } while (0) -#define ILLEGAL_ON(cond) \ - do \ - { \ - if ((cond)) \ - { \ - cpu_state.pc = cpu_state.oldpc; \ - x86illegal(); \ - return 0; \ - } \ - } while (0) - -static __inline void PUSH_W(uint16_t val) +static __inline void +PUSH_W(uint16_t val) { - if (stack32) - { - writememw(ss, ESP - 2, val); if (cpu_state.abrt) return; - ESP -= 2; - } - else - { - writememw(ss, (SP - 2) & 0xFFFF, val); if (cpu_state.abrt) return; - SP -= 2; - } + if (stack32) { + writememw(ss, ESP - 2, val); + if (cpu_state.abrt) + return; + ESP -= 2; + } else { + writememw(ss, (SP - 2) & 0xFFFF, val); + if (cpu_state.abrt) + return; + SP -= 2; + } } -static __inline void PUSH_L(uint32_t val) +static __inline void +PUSH_L(uint32_t val) { - if (stack32) - { - writememl(ss, ESP - 4, val); if (cpu_state.abrt) return; - ESP -= 4; - } - else - { - writememl(ss, (SP - 4) & 0xFFFF, val); if (cpu_state.abrt) return; - SP -= 4; - } + if (stack32) { + writememl(ss, ESP - 4, val); + if (cpu_state.abrt) + return; + ESP -= 4; + } else { + writememl(ss, (SP - 4) & 0xFFFF, val); + if (cpu_state.abrt) + return; + SP -= 4; + } } -static __inline uint16_t POP_W() +static __inline uint16_t +POP_W(void) { - uint16_t ret; - if (stack32) - { - ret = readmemw(ss, ESP); if (cpu_state.abrt) return 0; - ESP += 2; - } - else - { - ret = readmemw(ss, SP); if (cpu_state.abrt) return 0; - SP += 2; - } - return ret; + uint16_t ret; + if (stack32) { + ret = readmemw(ss, ESP); + if (cpu_state.abrt) + return 0; + ESP += 2; + } else { + ret = readmemw(ss, SP); + if (cpu_state.abrt) + return 0; + SP += 2; + } + return ret; } -static __inline uint32_t POP_L() +static __inline uint32_t +POP_L(void) { - uint32_t ret; - if (stack32) - { - ret = readmeml(ss, ESP); if (cpu_state.abrt) return 0; - ESP += 4; - } - else - { - ret = readmeml(ss, SP); if (cpu_state.abrt) return 0; - SP += 4; - } - return ret; + uint32_t ret; + if (stack32) { + ret = readmeml(ss, ESP); + if (cpu_state.abrt) + return 0; + ESP += 4; + } else { + ret = readmeml(ss, SP); + if (cpu_state.abrt) + return 0; + SP += 4; + } + return ret; } -static __inline uint16_t POP_W_seg(uint32_t seg) +static __inline uint16_t +POP_W_seg(uint32_t seg) { - uint16_t ret; - if (stack32) - { - ret = readmemw(seg, ESP); if (cpu_state.abrt) return 0; - ESP += 2; - } - else - { - ret = readmemw(seg, SP); if (cpu_state.abrt) return 0; - SP += 2; - } - return ret; + uint16_t ret; + if (stack32) { + ret = readmemw(seg, ESP); + if (cpu_state.abrt) + return 0; + ESP += 2; + } else { + ret = readmemw(seg, SP); + if (cpu_state.abrt) + return 0; + SP += 2; + } + return ret; } -static __inline uint32_t POP_L_seg(uint32_t seg) +static __inline uint32_t +POP_L_seg(uint32_t seg) { - uint32_t ret; - if (stack32) - { - ret = readmeml(seg, ESP); if (cpu_state.abrt) return 0; - ESP += 4; - } - else - { - ret = readmeml(seg, SP); if (cpu_state.abrt) return 0; - SP += 4; - } - return ret; + uint32_t ret; + if (stack32) { + ret = readmeml(seg, ESP); + if (cpu_state.abrt) + return 0; + ESP += 4; + } else { + ret = readmeml(seg, SP); + if (cpu_state.abrt) + return 0; + SP += 4; + } + return ret; } static int fopcode; -static int ILLEGAL(uint32_t fetchdat) +static int +ILLEGAL(uint32_t fetchdat) { - pclog("[%04X:%08X] Illegal instruction %08X (%02X)\n", CS, cpu_state.pc, fetchdat, fopcode); - cpu_state.pc = cpu_state.oldpc; + pclog("[%04X:%08X] Illegal instruction %08X (%02X)\n", CS, cpu_state.pc, fetchdat, fopcode); + cpu_state.pc = cpu_state.oldpc; - x86illegal(); - return 0; + x86illegal(); + return 0; } - #ifdef ENABLE_386_DYNAREC_LOG -extern void x386_dynarec_log(const char *fmt, ...); +extern void x386_dynarec_log(const char *fmt, ...); #else -#ifndef x386_dynarec_log -#define x386_dynarec_log(fmt, ...) -#endif +# ifndef x386_dynarec_log +# define x386_dynarec_log(fmt, ...) +# endif #endif -#include "x86seg.h" #include "x86_ops_arith.h" #include "x86_ops_atomic.h" #include "x86_ops_bcd.h" #include "x86_ops_bit.h" #include "x86_ops_bitscan.h" -#include "x86_ops_cyrix.h" +#ifndef OPS_286_386 +# include "x86_ops_cyrix.h" +#endif #include "x86_ops_flag.h" #include "x86_ops_fpu.h" #include "x86_ops_inc_dec.h" @@ -179,192 +189,354 @@ extern void x386_dynarec_log(const char *fmt, ...); #include "x86_ops_jump.h" #include "x86_ops_misc.h" #include "x87_ops.h" -#include "x86_ops_i686.h" -#include "x86_ops_mmx.h" -#include "x86_ops_mmx_arith.h" -#include "x86_ops_mmx_cmp.h" -#include "x86_ops_mmx_logic.h" -#include "x86_ops_mmx_mov.h" -#include "x86_ops_mmx_pack.h" -#include "x86_ops_mmx_shift.h" +#ifndef OPS_286_386 +# include "x86_ops_i686.h" +# include "x86_ops_mmx.h" +# include "x86_ops_mmx_arith.h" +# include "x86_ops_mmx_cmp.h" +# include "x86_ops_mmx_logic.h" +# include "x86_ops_mmx_mov.h" +# include "x86_ops_mmx_pack.h" +# include "x86_ops_mmx_shift.h" +#endif #include "x86_ops_mov.h" #include "x86_ops_mov_ctrl.h" #include "x86_ops_mov_seg.h" #include "x86_ops_movx.h" -#include "x86_ops_msr.h" +#ifndef OPS_286_386 +# include "x86_ops_msr.h" +#endif #include "x86_ops_mul.h" #include "x86_ops_pmode.h" #include "x86_ops_prefix.h" -#include "x86_ops_rep.h" +#ifdef IS_DYNAREC +# include "x86_ops_rep_dyn.h" +#else +# ifdef OPS_286_386 +# include "x86_ops_rep_2386.h" +# else +# include "x86_ops_rep.h" +# endif +#endif #include "x86_ops_ret.h" #include "x86_ops_set.h" #include "x86_ops_stack.h" -#include "x86_ops_string.h" +#ifdef OPS_286_386 +# include "x86_ops_string_2386.h" +#else +# include "x86_ops_string.h" +#endif #include "x86_ops_xchg.h" #include "x86_ops_call.h" #include "x86_ops_shift.h" -#include "x86_ops_amd.h" -#include "x86_ops_3dnow.h" +#ifndef OPS_286_386 +# include "x86_ops_amd.h" +# include "x86_ops_3dnow.h" +#endif #include - -static int opVPCEXT(uint32_t fetchdat) +#ifndef OPS_286_386 +static int +opVPCEXT(uint32_t fetchdat) { - uint8_t b1, b2; - uint16_t cent; - time_t now; - struct tm *tm; + uint8_t b1; + uint8_t b2; + uint16_t cent; + time_t now; + struct tm *tm = NULL; - if (!is_vpc) /* only emulate this on Virtual PC machines */ - return ILLEGAL(fetchdat); + if (!is_vpc) /* only emulate this on Virtual PC machines */ + return ILLEGAL(fetchdat); - cpu_state.pc += 2; + cpu_state.pc += 2; - b1 = fetchdat & 0xff; - b2 = (fetchdat >> 8) & 0xff; + b1 = fetchdat & 0xff; + b2 = (fetchdat >> 8) & 0xff; - /* a lot of these opcodes (which?) return illegal instruction in user mode */ - ILLEGAL_ON(CPL > 0); + /* a lot of these opcodes (which?) return illegal instruction in user mode */ + ILLEGAL_ON(CPL > 0); - CLOCK_CYCLES(1); + CLOCK_CYCLES(1); - /* 0f 3f 03 xx opcodes are mostly related to the host clock, so fetch it now */ - if (b1 == 0x03) { - (void)time(&now); - tm = localtime(&now); - } + /* 0f 3f 03 xx opcodes are mostly related to the host clock, so fetch it now */ + if (b1 == 0x03) { + (void) time(&now); + tm = localtime(&now); + } - if ((b1 == 0x07) && (b2 == 0x0b)) { - /* 0f 3f 07 0b: unknown, EDX output depends on EAX input */ - switch (EAX) { - case 0x00000000: - EDX = 0x00000003; - break; + if ((b1 == 0x07) && (b2 == 0x0b)) { + /* 0f 3f 07 0b: unknown, EDX output depends on EAX input */ + switch (EAX) { + case 0x00000000: + EDX = 0x00000003; + break; - case 0x00000001: - EDX = 0x00000012; - break; + case 0x00000001: + EDX = 0x00000012; + break; - case 0x00000002: - case 0x00000003: - case 0x00000004: - case 0x00000005: - EDX = 0x00000001; - break; + case 0x00000002: + case 0x00000003: + case 0x00000004: + case 0x00000005: + EDX = 0x00000001; + break; - case 0x00000007: - EDX = 0x0000009c; - break; + case 0x00000007: + EDX = 0x0000009c; + break; - default: - EDX = 0x00000000; - if (EAX > 0x00000012) /* unknown EAX values set zero flag */ - cpu_state.flags &= ~(Z_FLAG); - } - } else if ((b1 == 0x03) && (b2 == 0x00)) { - /* 0f 3f 03 00: host time in BCD */ - EDX = BCD8(tm->tm_hour); - ECX = BCD8(tm->tm_min); - EAX = BCD8(tm->tm_sec); - } else if ((b1 == 0x03) && (b2 == 0x01)) { - /* 0f 3f 03 00: host date in BCD */ - EDX = BCD8(tm->tm_year % 100); - ECX = BCD8(tm->tm_mon + 1); - EAX = BCD8(tm->tm_mday); - cent = (((tm->tm_year - (tm->tm_year % 100)) / 100) % 4); /* Sunday = 0 */ - EBX = ((tm->tm_mday + tm->tm_mon + (tm->tm_year % 100) + cent + 3) % 7); - } else if ((b1 == 0x03) && (b2 == 0x03)) { - /* 0f 3f 03 03: host time in binary */ - EDX = tm->tm_hour; - ECX = tm->tm_min; - EAX = tm->tm_sec; - } else if ((b1 == 0x03) && (b2 == 0x04)) { - /* 0f 3f 03 04: host date in binary */ - EDX = 1900 + tm->tm_year; - ECX = tm->tm_mon + 1; - EBX = tm->tm_mday; - } else if ((b1 == 0x03) && (b2 == 0x05)) { - /* 0f 3f 03 05: unknown */ - EBX = 0x0000000F; - ECX = 0x0000000A; - } else if ((b1 == 0x03) && (b2 == 0x06)) { - /* 0f 3f 03 06: some kind of timestamp. BX jumps around very quickly, CX not so much. */ - EBX = 0x00000000; - ECX = 0x00000000; - } else if ((b1 == 0x03) && (b2 >= 0x07)) { - /* 0f 3f 03 07+: set zero flag */ - cpu_state.flags &= ~(Z_FLAG); - } else if ((b1 == 0x0a) && (b2 == 0x00)) { - /* 0f 3f 0a 00: memory size in KB */ - EAX = mem_size; - } else if ((b1 == 0x11) && (b2 == 0x00)) { - /* 0f 3f 11 00: unknown, set EAX to 0 */ - EAX = 0x00000000; - } else if ((b1 == 0x11) && (b2 == 0x01)) { - /* 0f 3f 11 00: unknown, set EAX to 0 and set zero flag */ - EAX = 0x00000000; - cpu_state.flags &= ~(Z_FLAG); - } else if ((b1 == 0x11) && (b2 == 0x02)) { - /* 0f 3f 11 02: unknown, no-op */ - } else { - /* other unknown opcodes: illegal instruction */ - cpu_state.pc = cpu_state.oldpc; + default: + EDX = 0x00000000; + if (EAX > 0x00000012) /* unknown EAX values set zero flag */ + cpu_state.flags &= ~(Z_FLAG); + } + } else if ((b1 == 0x03) && (b2 == 0x00)) { + /* 0f 3f 03 00: host time in BCD */ + EDX = BCD8(tm->tm_hour); + ECX = BCD8(tm->tm_min); + EAX = BCD8(tm->tm_sec); + } else if ((b1 == 0x03) && (b2 == 0x01)) { + /* 0f 3f 03 00: host date in BCD */ + EDX = BCD8(tm->tm_year % 100); + ECX = BCD8(tm->tm_mon + 1); + EAX = BCD8(tm->tm_mday); + cent = (((tm->tm_year - (tm->tm_year % 100)) / 100) % 4); /* Sunday = 0 */ + EBX = ((tm->tm_mday + tm->tm_mon + (tm->tm_year % 100) + cent + 3) % 7); + } else if ((b1 == 0x03) && (b2 == 0x03)) { + /* 0f 3f 03 03: host time in binary */ + EDX = tm->tm_hour; + ECX = tm->tm_min; + EAX = tm->tm_sec; + } else if ((b1 == 0x03) && (b2 == 0x04)) { + /* 0f 3f 03 04: host date in binary */ + EDX = 1900 + tm->tm_year; + ECX = tm->tm_mon + 1; + EBX = tm->tm_mday; + } else if ((b1 == 0x03) && (b2 == 0x05)) { + /* 0f 3f 03 05: unknown */ + EBX = 0x0000000F; + ECX = 0x0000000A; + } else if ((b1 == 0x03) && (b2 == 0x06)) { + /* 0f 3f 03 06: some kind of timestamp. BX jumps around very quickly, CX not so much. */ + EBX = 0x00000000; + ECX = 0x00000000; + } else if ((b1 == 0x03) && (b2 >= 0x07)) { + /* 0f 3f 03 07+: set zero flag */ + cpu_state.flags &= ~(Z_FLAG); + } else if ((b1 == 0x0a) && (b2 == 0x00)) { + /* 0f 3f 0a 00: memory size in KB */ + EAX = mem_size; + } else if ((b1 == 0x11) && (b2 == 0x00)) { + /* 0f 3f 11 00: unknown, set EAX to 0 */ + EAX = 0x00000000; + } else if ((b1 == 0x11) && (b2 == 0x01)) { + /* 0f 3f 11 00: unknown, set EAX to 0 and set zero flag */ + EAX = 0x00000000; + cpu_state.flags &= ~(Z_FLAG); + } else if ((b1 == 0x11) && (b2 == 0x02)) { + /* 0f 3f 11 02: unknown, no-op */ + } else { + /* other unknown opcodes: illegal instruction */ + cpu_state.pc = cpu_state.oldpc; - pclog("Illegal VPCEXT %08X (%02X %02X)\n", fetchdat, b1, b2); - x86illegal(); - return 0; - } + pclog("Illegal VPCEXT %08X (%02X %02X)\n", fetchdat, b1, b2); + x86illegal(); + return 0; + } - return 1; + return 1; } +#endif - -static int op0F_w_a16(uint32_t fetchdat) +#ifdef OPS_286_386 +static int +op0F_w_a16(uint32_t fetchdat) { - int opcode = fetchdat & 0xff; - fopcode = opcode; - cpu_state.pc++; + int opcode = fetchdat & 0xff; + fopcode = opcode; + cpu_state.pc++; - PREFETCH_PREFIX(); + PREFETCH_PREFIX(); - return x86_opcodes_0f[opcode](fetchdat >> 8); + return x86_2386_opcodes_0f[opcode](fetchdat >> 8); } -static int op0F_l_a16(uint32_t fetchdat) +static int +op0F_l_a16(uint32_t fetchdat) { - int opcode = fetchdat & 0xff; - fopcode = opcode; - cpu_state.pc++; - - PREFETCH_PREFIX(); + int opcode = fetchdat & 0xff; + fopcode = opcode; + cpu_state.pc++; - return x86_opcodes_0f[opcode | 0x100](fetchdat >> 8); + PREFETCH_PREFIX(); + + return x86_2386_opcodes_0f[opcode | 0x100](fetchdat >> 8); } -static int op0F_w_a32(uint32_t fetchdat) +static int +op0F_w_a32(uint32_t fetchdat) { - int opcode = fetchdat & 0xff; - fopcode = opcode; - cpu_state.pc++; - - PREFETCH_PREFIX(); + int opcode = fetchdat & 0xff; + fopcode = opcode; + cpu_state.pc++; - return x86_opcodes_0f[opcode | 0x200](fetchdat >> 8); + PREFETCH_PREFIX(); + + return x86_2386_opcodes_0f[opcode | 0x200](fetchdat >> 8); } -static int op0F_l_a32(uint32_t fetchdat) +static int +op0F_l_a32(uint32_t fetchdat) { - int opcode = fetchdat & 0xff; - fopcode = opcode; - cpu_state.pc++; - - PREFETCH_PREFIX(); + int opcode = fetchdat & 0xff; + fopcode = opcode; + cpu_state.pc++; - return x86_opcodes_0f[opcode | 0x300](fetchdat >> 8); + PREFETCH_PREFIX(); + + return x86_2386_opcodes_0f[opcode | 0x300](fetchdat >> 8); } - - -const OpFn OP_TABLE(286_0f)[1024] = +#else +static int +op0F_w_a16(uint32_t fetchdat) { + int opcode = fetchdat & 0xff; + fopcode = opcode; + cpu_state.pc++; + + PREFETCH_PREFIX(); + + return x86_opcodes_0f[opcode](fetchdat >> 8); +} +static int +op0F_l_a16(uint32_t fetchdat) +{ + int opcode = fetchdat & 0xff; + fopcode = opcode; + cpu_state.pc++; + + PREFETCH_PREFIX(); + + return x86_opcodes_0f[opcode | 0x100](fetchdat >> 8); +} +static int +op0F_w_a32(uint32_t fetchdat) +{ + int opcode = fetchdat & 0xff; + fopcode = opcode; + cpu_state.pc++; + + PREFETCH_PREFIX(); + + return x86_opcodes_0f[opcode | 0x200](fetchdat >> 8); +} +static int +op0F_l_a32(uint32_t fetchdat) +{ + int opcode = fetchdat & 0xff; + fopcode = opcode; + cpu_state.pc++; + + PREFETCH_PREFIX(); + + return x86_opcodes_0f[opcode | 0x300](fetchdat >> 8); +} +#endif + +const OpFn OP_TABLE(186_0f)[1024] = { + // clang-format off /*16-bit data, 16-bit addr*/ -/* 00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f*/ +/* 00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f*/ +/*00*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, +/*10*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, +/*20*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, +/*30*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, + +/*40*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, +/*50*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, +/*60*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, +/*70*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, + +/*80*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, +/*90*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, +/*a0*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, +/*b0*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, + +/*c0*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, +/*d0*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, +/*e0*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, +/*f0*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, + + /*32-bit data, 16-bit addr*/ +/* 00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f*/ +/*00*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, +/*10*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, +/*20*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, +/*30*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, + +/*40*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, +/*50*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, +/*60*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, +/*70*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, + +/*80*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, +/*90*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, +/*a0*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, +/*b0*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, + +/*c0*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, +/*d0*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, +/*e0*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, +/*f0*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, + + /*16-bit data, 32-bit addr*/ +/* 00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f*/ +/*00*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, +/*10*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, +/*20*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, +/*30*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, + +/*40*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, +/*50*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, +/*60*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, +/*70*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, + +/*80*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, +/*90*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, +/*a0*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, +/*b0*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, + +/*c0*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, +/*d0*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, +/*e0*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, +/*f0*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, + + /*32-bit data, 32-bit addr*/ +/* 00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f*/ +/*00*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, +/*10*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, +/*20*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, +/*30*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, + +/*40*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, +/*50*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, +/*60*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, +/*70*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, + +/*80*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, +/*90*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, +/*a0*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, +/*b0*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, + +/*c0*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, +/*d0*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, +/*e0*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, +/*f0*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, + // clang-format on +}; + +const OpFn OP_TABLE(286_0f)[1024] = { + // clang-format off + /*16-bit data, 16-bit addr*/ +/* 00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f*/ /*00*/ op0F00_a16, op0F01_286, opLAR_w_a16, opLSL_w_a16, ILLEGAL, opLOADALL, opCLTS, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, /*10*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, /*20*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, @@ -386,7 +558,7 @@ const OpFn OP_TABLE(286_0f)[1024] = /*f0*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, /*32-bit data, 16-bit addr*/ -/* 00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f*/ +/* 00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f*/ /*00*/ op0F00_a16, op0F01_286, opLAR_w_a16, opLSL_w_a16, ILLEGAL, opLOADALL, opCLTS, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, /*10*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, /*20*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, @@ -408,7 +580,7 @@ const OpFn OP_TABLE(286_0f)[1024] = /*f0*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, /*16-bit data, 32-bit addr*/ -/* 00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f*/ +/* 00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f*/ /*00*/ op0F00_a16, op0F01_286, opLAR_w_a16, opLSL_w_a16, ILLEGAL, opLOADALL, opCLTS, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, /*10*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, /*20*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, @@ -430,7 +602,7 @@ const OpFn OP_TABLE(286_0f)[1024] = /*f0*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, /*32-bit data, 32-bit addr*/ -/* 00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f*/ +/* 00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f*/ /*00*/ op0F00_a16, op0F01_286, opLAR_w_a16, opLSL_w_a16, ILLEGAL, opLOADALL, opCLTS, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, /*10*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, /*20*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, @@ -450,12 +622,13 @@ const OpFn OP_TABLE(286_0f)[1024] = /*d0*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, /*e0*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, /*f0*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, + // clang-format on }; -const OpFn OP_TABLE(386_0f)[1024] = -{ +const OpFn OP_TABLE(386_0f)[1024] = { + // clang-format off /*16-bit data, 16-bit addr*/ -/* 00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f*/ +/* 00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f*/ /*00*/ op0F00_a16, op0F01_w_a16, opLAR_w_a16, opLSL_w_a16, ILLEGAL, ILLEGAL, opCLTS, opLOADALL386, opINVD, opWBINVD, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, /*10*/ opMOV_b_r_a16, opMOV_w_r_a16, opMOV_r_b_a16, opMOV_r_w_a16, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, /*20*/ opMOV_r_CRx_a16,opMOV_r_DRx_a16,opMOV_CRx_r_a16,opMOV_DRx_r_a16,opMOV_r_TRx_a16,ILLEGAL, opMOV_TRx_r_a16,ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, @@ -477,7 +650,7 @@ const OpFn OP_TABLE(386_0f)[1024] = /*f0*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, /*32-bit data, 16-bit addr*/ -/* 00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f*/ +/* 00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f*/ /*00*/ op0F00_a16, op0F01_l_a16, opLAR_l_a16, opLSL_l_a16, ILLEGAL, ILLEGAL, opCLTS, opLOADALL386, opINVD, opWBINVD, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, /*10*/ opMOV_b_r_a16, opMOV_l_r_a16, opMOV_r_b_a16, opMOV_r_l_a16, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, /*20*/ opMOV_r_CRx_a16,opMOV_r_DRx_a16,opMOV_CRx_r_a16,opMOV_DRx_r_a16,opMOV_r_TRx_a16,ILLEGAL, opMOV_TRx_r_a16,ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, @@ -499,7 +672,7 @@ const OpFn OP_TABLE(386_0f)[1024] = /*f0*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, /*16-bit data, 32-bit addr*/ -/* 00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f*/ +/* 00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f*/ /*00*/ op0F00_a32, op0F01_w_a32, opLAR_w_a32, opLSL_w_a32, ILLEGAL, ILLEGAL, opCLTS, opLOADALL386, opINVD, opWBINVD, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, /*10*/ opMOV_b_r_a32, opMOV_w_r_a32, opMOV_r_b_a32, opMOV_r_w_a32, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, /*20*/ opMOV_r_CRx_a32,opMOV_r_DRx_a32,opMOV_CRx_r_a32,opMOV_DRx_r_a32,opMOV_r_TRx_a32,ILLEGAL, opMOV_TRx_r_a32,ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, @@ -521,7 +694,7 @@ const OpFn OP_TABLE(386_0f)[1024] = /*f0*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, /*32-bit data, 32-bit addr*/ -/* 00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f*/ +/* 00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f*/ /*00*/ op0F00_a32, op0F01_l_a32, opLAR_l_a32, opLSL_l_a32, ILLEGAL, ILLEGAL, opCLTS, opLOADALL386, opINVD, opWBINVD, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, /*10*/ opMOV_b_r_a32, opMOV_l_r_a32, opMOV_r_b_a32, opMOV_r_l_a32, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, /*20*/ opMOV_r_CRx_a32,opMOV_r_DRx_a32,opMOV_CRx_r_a32,opMOV_DRx_r_a32,opMOV_r_TRx_a32,ILLEGAL, opMOV_TRx_r_a32,ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, @@ -541,12 +714,13 @@ const OpFn OP_TABLE(386_0f)[1024] = /*d0*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, /*e0*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, /*f0*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, + // clang-format on }; -const OpFn OP_TABLE(486_0f)[1024] = -{ +const OpFn OP_TABLE(486_0f)[1024] = { + // clang-format off /*16-bit data, 16-bit addr*/ -/* 00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f*/ +/* 00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f*/ /*00*/ op0F00_a16, op0F01_w_a16, opLAR_w_a16, opLSL_w_a16, ILLEGAL, ILLEGAL, opCLTS, opLOADALL386, opINVD, opWBINVD, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, /*10*/ opMOV_b_r_a16, opMOV_w_r_a16, opMOV_r_b_a16, opMOV_r_w_a16, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, /*20*/ opMOV_r_CRx_a16,opMOV_r_DRx_a16,opMOV_CRx_r_a16,opMOV_DRx_r_a16,opMOV_r_TRx_a16,ILLEGAL, opMOV_TRx_r_a16,ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, @@ -568,7 +742,7 @@ const OpFn OP_TABLE(486_0f)[1024] = /*f0*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, /*32-bit data, 16-bit addr*/ -/* 00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f*/ +/* 00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f*/ /*00*/ op0F00_a16, op0F01_l_a16, opLAR_l_a16, opLSL_l_a16, ILLEGAL, ILLEGAL, opCLTS, opLOADALL386, opINVD, opWBINVD, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, /*10*/ opMOV_b_r_a16, opMOV_l_r_a16, opMOV_r_b_a16, opMOV_r_l_a16, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, /*20*/ opMOV_r_CRx_a16,opMOV_r_DRx_a16,opMOV_CRx_r_a16,opMOV_DRx_r_a16,opMOV_r_TRx_a16,ILLEGAL, opMOV_TRx_r_a16,ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, @@ -590,7 +764,7 @@ const OpFn OP_TABLE(486_0f)[1024] = /*f0*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, /*16-bit data, 32-bit addr*/ -/* 00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f*/ +/* 00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f*/ /*00*/ op0F00_a32, op0F01_w_a32, opLAR_w_a32, opLSL_w_a32, ILLEGAL, ILLEGAL, opCLTS, opLOADALL386, opINVD, opWBINVD, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, /*10*/ opMOV_b_r_a32, opMOV_w_r_a32, opMOV_r_b_a32, opMOV_r_w_a32, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, /*20*/ opMOV_r_CRx_a32,opMOV_r_DRx_a32,opMOV_CRx_r_a32,opMOV_DRx_r_a32,opMOV_r_TRx_a32,ILLEGAL, opMOV_TRx_r_a32,ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, @@ -612,7 +786,7 @@ const OpFn OP_TABLE(486_0f)[1024] = /*f0*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, /*32-bit data, 32-bit addr*/ -/* 00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f*/ +/* 00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f*/ /*00*/ op0F00_a32, op0F01_l_a32, opLAR_l_a32, opLSL_l_a32, ILLEGAL, ILLEGAL, opCLTS, opLOADALL386, opINVD, opWBINVD, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, /*10*/ opMOV_b_r_a32, opMOV_l_r_a32, opMOV_r_b_a32, opMOV_r_l_a32, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, /*20*/ opMOV_r_CRx_a32,opMOV_r_DRx_a32,opMOV_CRx_r_a32,opMOV_DRx_r_a32,opMOV_r_TRx_a32,ILLEGAL, opMOV_TRx_r_a32,ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, @@ -632,12 +806,14 @@ const OpFn OP_TABLE(486_0f)[1024] = /*d0*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, /*e0*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, /*f0*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, + // clang-format on }; -const OpFn OP_TABLE(c486_0f)[1024] = -{ +#ifndef OPS_286_386 +const OpFn OP_TABLE(c486_0f)[1024] = { + // clang-format off /*16-bit data, 16-bit addr*/ -/* 00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f*/ +/* 00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f*/ /*00*/ op0F00_a16, op0F01_w_a16, opLAR_w_a16, opLSL_w_a16, ILLEGAL, ILLEGAL, opCLTS, opLOADALL386, opINVD, opWBINVD, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, /*10*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, /*20*/ opMOV_r_CRx_a16,opMOV_r_DRx_a16,opMOV_CRx_r_a16,opMOV_DRx_r_a16,opMOV_r_TRx_a16,ILLEGAL, opMOV_TRx_r_a16,ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, @@ -659,7 +835,7 @@ const OpFn OP_TABLE(c486_0f)[1024] = /*f0*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, /*32-bit data, 16-bit addr*/ -/* 00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f*/ +/* 00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f*/ /*00*/ op0F00_a16, op0F01_l_a16, opLAR_l_a16, opLSL_l_a16, ILLEGAL, ILLEGAL, opCLTS, opLOADALL386, opINVD, opWBINVD, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, /*10*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, /*20*/ opMOV_r_CRx_a16,opMOV_r_DRx_a16,opMOV_CRx_r_a16,opMOV_DRx_r_a16,opMOV_r_TRx_a16,ILLEGAL, opMOV_TRx_r_a16,ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, @@ -681,7 +857,7 @@ const OpFn OP_TABLE(c486_0f)[1024] = /*f0*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, /*16-bit data, 32-bit addr*/ -/* 00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f*/ +/* 00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f*/ /*00*/ op0F00_a32, op0F01_w_a32, opLAR_w_a32, opLSL_w_a32, ILLEGAL, ILLEGAL, opCLTS, opLOADALL386, opINVD, opWBINVD, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, /*10*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, /*20*/ opMOV_r_CRx_a32,opMOV_r_DRx_a32,opMOV_CRx_r_a32,opMOV_DRx_r_a32,opMOV_r_TRx_a32,ILLEGAL, opMOV_TRx_r_a32,ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, @@ -703,7 +879,7 @@ const OpFn OP_TABLE(c486_0f)[1024] = /*f0*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, /*32-bit data, 32-bit addr*/ -/* 00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f*/ +/* 00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f*/ /*00*/ op0F00_a32, op0F01_l_a32, opLAR_l_a32, opLSL_l_a32, ILLEGAL, ILLEGAL, opCLTS, opLOADALL386, opINVD, opWBINVD, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, /*10*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, /*20*/ opMOV_r_CRx_a32,opMOV_r_DRx_a32,opMOV_CRx_r_a32,opMOV_DRx_r_a32,opMOV_r_TRx_a32,ILLEGAL, opMOV_TRx_r_a32,ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, @@ -723,12 +899,13 @@ const OpFn OP_TABLE(c486_0f)[1024] = /*d0*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, /*e0*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, /*f0*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, + // clang-format on }; -const OpFn OP_TABLE(stpc_0f)[1024] = -{ +const OpFn OP_TABLE(stpc_0f)[1024] = { + // clang-format off /*16-bit data, 16-bit addr*/ -/* 00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f*/ +/* 00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f*/ /*00*/ op0F00_a16, op0F01_w_a16, opLAR_w_a16, opLSL_w_a16, ILLEGAL, ILLEGAL, opCLTS, opLOADALL386, opINVD, opWBINVD, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, /*10*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, /*20*/ opMOV_r_CRx_a16,opMOV_r_DRx_a16,opMOV_CRx_r_a16,opMOV_DRx_r_a16,opMOV_r_TRx_a16,ILLEGAL, opMOV_TRx_r_a16,ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, @@ -750,7 +927,7 @@ const OpFn OP_TABLE(stpc_0f)[1024] = /*f0*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, /*32-bit data, 16-bit addr*/ -/* 00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f*/ +/* 00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f*/ /*00*/ op0F00_a16, op0F01_l_a16, opLAR_l_a16, opLSL_l_a16, ILLEGAL, ILLEGAL, opCLTS, opLOADALL386, opINVD, opWBINVD, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, /*10*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, /*20*/ opMOV_r_CRx_a16,opMOV_r_DRx_a16,opMOV_CRx_r_a16,opMOV_DRx_r_a16,opMOV_r_TRx_a16,ILLEGAL, opMOV_TRx_r_a16,ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, @@ -772,7 +949,7 @@ const OpFn OP_TABLE(stpc_0f)[1024] = /*f0*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, /*16-bit data, 32-bit addr*/ -/* 00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f*/ +/* 00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f*/ /*00*/ op0F00_a32, op0F01_w_a32, opLAR_w_a32, opLSL_w_a32, ILLEGAL, ILLEGAL, opCLTS, opLOADALL386, opINVD, opWBINVD, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, /*10*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, /*20*/ opMOV_r_CRx_a32,opMOV_r_DRx_a32,opMOV_CRx_r_a32,opMOV_DRx_r_a32,opMOV_r_TRx_a32,ILLEGAL, opMOV_TRx_r_a32,ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, @@ -794,7 +971,7 @@ const OpFn OP_TABLE(stpc_0f)[1024] = /*f0*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, /*32-bit data, 32-bit addr*/ -/* 00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f*/ +/* 00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f*/ /*00*/ op0F00_a32, op0F01_l_a32, opLAR_l_a32, opLSL_l_a32, ILLEGAL, ILLEGAL, opCLTS, opLOADALL386, opINVD, opWBINVD, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, /*10*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, /*20*/ opMOV_r_CRx_a32,opMOV_r_DRx_a32,opMOV_CRx_r_a32,opMOV_DRx_r_a32,opMOV_r_TRx_a32,ILLEGAL, opMOV_TRx_r_a32,ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, @@ -814,12 +991,14 @@ const OpFn OP_TABLE(stpc_0f)[1024] = /*d0*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, /*e0*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, /*f0*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, + // clang-format on }; +#endif -const OpFn OP_TABLE(ibm486_0f)[1024] = -{ +const OpFn OP_TABLE(ibm486_0f)[1024] = { + // clang-format off /*16-bit data, 16-bit addr*/ -/* 00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f*/ +/* 00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f*/ /*00*/ op0F00_a16, op0F01_w_a16, opLAR_w_a16, opLSL_w_a16, ILLEGAL, ILLEGAL, opCLTS, opLOADALL386, opINVD, opWBINVD, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, /*10*/ opMOV_b_r_a16, opMOV_w_r_a16, opMOV_r_b_a16, opMOV_r_w_a16, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, /*20*/ opMOV_r_CRx_a16,opMOV_r_DRx_a16,opMOV_CRx_r_a16,opMOV_DRx_r_a16,opMOV_r_TRx_a16,ILLEGAL, opMOV_TRx_r_a16,ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, @@ -841,7 +1020,7 @@ const OpFn OP_TABLE(ibm486_0f)[1024] = /*f0*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, /*32-bit data, 16-bit addr*/ -/* 00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f*/ +/* 00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f*/ /*00*/ op0F00_a16, op0F01_l_a16, opLAR_l_a16, opLSL_l_a16, ILLEGAL, ILLEGAL, opCLTS, opLOADALL386, opINVD, opWBINVD, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, /*10*/ opMOV_b_r_a16, opMOV_l_r_a16, opMOV_r_b_a16, opMOV_r_l_a16, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, /*20*/ opMOV_r_CRx_a16,opMOV_r_DRx_a16,opMOV_CRx_r_a16,opMOV_DRx_r_a16,opMOV_r_TRx_a16,ILLEGAL, opMOV_TRx_r_a16,ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, @@ -863,7 +1042,7 @@ const OpFn OP_TABLE(ibm486_0f)[1024] = /*f0*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, /*16-bit data, 32-bit addr*/ -/* 00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f*/ +/* 00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f*/ /*00*/ op0F00_a32, op0F01_w_a32, opLAR_w_a32, opLSL_w_a32, ILLEGAL, ILLEGAL, opCLTS, opLOADALL386, opINVD, opWBINVD, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, /*10*/ opMOV_b_r_a32, opMOV_w_r_a32, opMOV_r_b_a32, opMOV_r_w_a32, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, /*20*/ opMOV_r_CRx_a32,opMOV_r_DRx_a32,opMOV_CRx_r_a32,opMOV_DRx_r_a32,opMOV_r_TRx_a32,ILLEGAL, opMOV_TRx_r_a32,ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, @@ -885,7 +1064,7 @@ const OpFn OP_TABLE(ibm486_0f)[1024] = /*f0*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, /*32-bit data, 32-bit addr*/ -/* 00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f*/ +/* 00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f*/ /*00*/ op0F00_a32, op0F01_l_a32, opLAR_l_a32, opLSL_l_a32, ILLEGAL, ILLEGAL, opCLTS, opLOADALL386, opINVD, opWBINVD, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, /*10*/ opMOV_b_r_a32, opMOV_l_r_a32, opMOV_r_b_a32, opMOV_r_l_a32, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, /*20*/ opMOV_r_CRx_a32,opMOV_r_DRx_a32,opMOV_CRx_r_a32,opMOV_DRx_r_a32,opMOV_r_TRx_a32,ILLEGAL, opMOV_TRx_r_a32,ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, @@ -905,12 +1084,14 @@ const OpFn OP_TABLE(ibm486_0f)[1024] = /*d0*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, /*e0*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, /*f0*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, + // clang-format on }; -const OpFn OP_TABLE(winchip_0f)[1024] = -{ +#ifndef OPS_286_386 +const OpFn OP_TABLE(winchip_0f)[1024] = { + // clang-format off /*16-bit data, 16-bit addr*/ -/* 00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f*/ +/* 00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f*/ /*00*/ op0F00_a16, op0F01_w_a16, opLAR_w_a16, opLSL_w_a16, ILLEGAL, ILLEGAL, opCLTS, ILLEGAL, opINVD, opWBINVD, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, /*10*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, /*20*/ opMOV_r_CRx_a16,opMOV_r_DRx_a16,opMOV_CRx_r_a16,opMOV_DRx_r_a16,opMOV_r_TRx_a16,ILLEGAL, opMOV_TRx_r_a16,ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, @@ -932,7 +1113,7 @@ const OpFn OP_TABLE(winchip_0f)[1024] = /*f0*/ ILLEGAL, opPSLLW_a16, opPSLLD_a16, opPSLLQ_a16, ILLEGAL, opPMADDWD_a16, ILLEGAL, ILLEGAL, opPSUBB_a16, opPSUBW_a16, opPSUBD_a16, ILLEGAL, opPADDB_a16, opPADDW_a16, opPADDD_a16, ILLEGAL, /*32-bit data, 16-bit addr*/ -/* 00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f*/ +/* 00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f*/ /*00*/ op0F00_a16, op0F01_l_a16, opLAR_l_a16, opLSL_l_a16, ILLEGAL, ILLEGAL, opCLTS, ILLEGAL, opINVD, opWBINVD, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, /*10*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, /*20*/ opMOV_r_CRx_a16,opMOV_r_DRx_a16,opMOV_CRx_r_a16,opMOV_DRx_r_a16,opMOV_r_TRx_a16,ILLEGAL, opMOV_TRx_r_a16,ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, @@ -954,7 +1135,7 @@ const OpFn OP_TABLE(winchip_0f)[1024] = /*f0*/ ILLEGAL, opPSLLW_a16, opPSLLD_a16, opPSLLQ_a16, ILLEGAL, opPMADDWD_a16, ILLEGAL, ILLEGAL, opPSUBB_a16, opPSUBW_a16, opPSUBD_a16, ILLEGAL, opPADDB_a16, opPADDW_a16, opPADDD_a16, ILLEGAL, /*16-bit data, 32-bit addr*/ -/* 00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f*/ +/* 00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f*/ /*00*/ op0F00_a32, op0F01_w_a32, opLAR_w_a32, opLSL_w_a32, ILLEGAL, ILLEGAL, opCLTS, ILLEGAL, opINVD, opWBINVD, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, /*10*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, /*20*/ opMOV_r_CRx_a32,opMOV_r_DRx_a32,opMOV_CRx_r_a32,opMOV_DRx_r_a32,opMOV_r_TRx_a32,ILLEGAL, opMOV_TRx_r_a32,ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, @@ -976,7 +1157,7 @@ const OpFn OP_TABLE(winchip_0f)[1024] = /*f0*/ ILLEGAL, opPSLLW_a32, opPSLLD_a32, opPSLLQ_a32, ILLEGAL, opPMADDWD_a32, ILLEGAL, ILLEGAL, opPSUBB_a32, opPSUBW_a32, opPSUBD_a32, ILLEGAL, opPADDB_a32, opPADDW_a32, opPADDD_a32, ILLEGAL, /*32-bit data, 32-bit addr*/ -/* 00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f*/ +/* 00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f*/ /*00*/ op0F00_a32, op0F01_l_a32, opLAR_l_a32, opLSL_l_a32, ILLEGAL, ILLEGAL, opCLTS, ILLEGAL, opINVD, opWBINVD, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, /*10*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, /*20*/ opMOV_r_CRx_a32,opMOV_r_DRx_a32,opMOV_CRx_r_a32,opMOV_DRx_r_a32,opMOV_r_TRx_a32,ILLEGAL, opMOV_TRx_r_a32,ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, @@ -996,10 +1177,11 @@ const OpFn OP_TABLE(winchip_0f)[1024] = /*d0*/ ILLEGAL, opPSRLW_a32, opPSRLD_a32, opPSRLQ_a32, ILLEGAL, opPMULLW_a32, ILLEGAL, ILLEGAL, opPSUBUSB_a32, opPSUBUSW_a32, NULL, opPAND_a32, opPADDUSB_a32, opPADDUSW_a32, NULL, opPANDN_a32, /*e0*/ ILLEGAL, opPSRAW_a32, opPSRAD_a32, ILLEGAL, ILLEGAL, opPMULHW_a32, ILLEGAL, ILLEGAL, opPSUBSB_a32, opPSUBSW_a32, NULL, opPOR_a32, opPADDSB_a32, opPADDSW_a32, NULL, opPXOR_a32, /*f0*/ ILLEGAL, opPSLLW_a32, opPSLLD_a32, opPSLLQ_a32, ILLEGAL, opPMADDWD_a32, ILLEGAL, ILLEGAL, opPSUBB_a32, opPSUBW_a32, opPSUBD_a32, ILLEGAL, opPADDB_a32, opPADDW_a32, opPADDD_a32, ILLEGAL, + // clang-format on }; -const OpFn OP_TABLE(winchip2_0f)[1024] = -{ +const OpFn OP_TABLE(winchip2_0f)[1024] = { + // clang-format off /*16-bit data, 16-bit addr*/ /* 00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f*/ /*00*/ op0F00_a16, op0F01_w_a16, opLAR_w_a16, opLSL_w_a16, ILLEGAL, ILLEGAL, opCLTS, ILLEGAL, opINVD, opWBINVD, ILLEGAL, ILLEGAL, ILLEGAL, opPREFETCH_a16, opFEMMS, op3DNOW_a16, @@ -1087,12 +1269,13 @@ const OpFn OP_TABLE(winchip2_0f)[1024] = /*d0*/ ILLEGAL, opPSRLW_a32, opPSRLD_a32, opPSRLQ_a32, ILLEGAL, opPMULLW_a32, ILLEGAL, ILLEGAL, opPSUBUSB_a32, opPSUBUSW_a32, NULL, opPAND_a32, opPADDUSB_a32, opPADDUSW_a32, NULL, opPANDN_a32, /*e0*/ ILLEGAL, opPSRAW_a32, opPSRAD_a32, ILLEGAL, ILLEGAL, opPMULHW_a32, ILLEGAL, ILLEGAL, opPSUBSB_a32, opPSUBSW_a32, NULL, opPOR_a32, opPADDSB_a32, opPADDSW_a32, NULL, opPXOR_a32, /*f0*/ ILLEGAL, opPSLLW_a32, opPSLLD_a32, opPSLLQ_a32, ILLEGAL, opPMADDWD_a32, ILLEGAL, ILLEGAL, opPSUBB_a32, opPSUBW_a32, opPSUBD_a32, ILLEGAL, opPADDB_a32, opPADDW_a32, opPADDD_a32, ILLEGAL, + // clang-format on }; -const OpFn OP_TABLE(pentium_0f)[1024] = -{ +const OpFn OP_TABLE(pentium_0f)[1024] = { + // clang-format off /*16-bit data, 16-bit addr*/ -/* 00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f*/ +/* 00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f*/ /*00*/ op0F00_a16, op0F01_w_a16, opLAR_w_a16, opLSL_w_a16, ILLEGAL, ILLEGAL, opCLTS, ILLEGAL, opINVD, opWBINVD, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, /*10*/ opMOV_b_r_a16, opMOV_w_r_a16, opMOV_r_b_a16, opMOV_r_w_a16, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, /*20*/ opMOV_r_CRx_a16,opMOV_r_DRx_a16,opMOV_CRx_r_a16,opMOV_DRx_r_a16,opMOV_r_TRx_a16,ILLEGAL, opMOV_TRx_r_a16,ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, @@ -1114,7 +1297,7 @@ const OpFn OP_TABLE(pentium_0f)[1024] = /*f0*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, /*32-bit data, 16-bit addr*/ -/* 00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f*/ +/* 00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f*/ /*00*/ op0F00_a16, op0F01_l_a16, opLAR_l_a16, opLSL_l_a16, ILLEGAL, ILLEGAL, opCLTS, ILLEGAL, opINVD, opWBINVD, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, /*10*/ opMOV_b_r_a16, opMOV_l_r_a16, opMOV_r_b_a16, opMOV_r_l_a16, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, /*20*/ opMOV_r_CRx_a16,opMOV_r_DRx_a16,opMOV_CRx_r_a16,opMOV_DRx_r_a16,opMOV_r_TRx_a16,ILLEGAL, opMOV_TRx_r_a16,ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, @@ -1136,7 +1319,7 @@ const OpFn OP_TABLE(pentium_0f)[1024] = /*f0*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, /*16-bit data, 32-bit addr*/ -/* 00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f*/ +/* 00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f*/ /*00*/ op0F00_a32, op0F01_w_a32, opLAR_w_a32, opLSL_w_a32, ILLEGAL, ILLEGAL, opCLTS, ILLEGAL, opINVD, opWBINVD, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, /*10*/ opMOV_b_r_a32, opMOV_w_r_a32, opMOV_r_b_a32, opMOV_r_w_a32, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, /*20*/ opMOV_r_CRx_a32,opMOV_r_DRx_a32,opMOV_CRx_r_a32,opMOV_DRx_r_a32,opMOV_r_TRx_a32,ILLEGAL, opMOV_TRx_r_a32,ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, @@ -1158,7 +1341,7 @@ const OpFn OP_TABLE(pentium_0f)[1024] = /*f0*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, /*32-bit data, 32-bit addr*/ -/* 00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f*/ +/* 00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f*/ /*00*/ op0F00_a32, op0F01_l_a32, opLAR_l_a32, opLSL_l_a32, ILLEGAL, ILLEGAL, opCLTS, ILLEGAL, opINVD, opWBINVD, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, /*10*/ opMOV_b_r_a32, opMOV_l_r_a32, opMOV_r_b_a32, opMOV_r_l_a32, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, /*20*/ opMOV_r_CRx_a32,opMOV_r_DRx_a32,opMOV_CRx_r_a32,opMOV_DRx_r_a32,opMOV_r_TRx_a32,ILLEGAL, opMOV_TRx_r_a32,ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, @@ -1178,11 +1361,12 @@ const OpFn OP_TABLE(pentium_0f)[1024] = /*d0*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, /*e0*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, /*f0*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, + // clang-format on }; -#if defined(DEV_BRANCH) && defined(USE_CYRIX_6X86) -const OpFn OP_TABLE(c6x86_0f)[1024] = -{ +# if defined(DEV_BRANCH) && defined(USE_CYRIX_6X86) +const OpFn OP_TABLE(c6x86_0f)[1024] = { + // clang-format off /*16-bit data, 16-bit addr*/ /* 00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f*/ /*00*/ op0F00_a16, op0F01_w_a16, opLAR_w_a16, opLSL_w_a16, ILLEGAL, ILLEGAL, opCLTS, ILLEGAL, opINVD, opWBINVD, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, @@ -1270,13 +1454,14 @@ const OpFn OP_TABLE(c6x86_0f)[1024] = /*d0*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, /*e0*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, /*f0*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, + // clang-format on }; -#endif +# endif -const OpFn OP_TABLE(pentiummmx_0f)[1024] = -{ +const OpFn OP_TABLE(pentiummmx_0f)[1024] = { + // clang-format off /*16-bit data, 16-bit addr*/ -/* 00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f*/ +/* 00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f*/ /*00*/ op0F00_a16, op0F01_w_a16, opLAR_w_a16, opLSL_w_a16, ILLEGAL, ILLEGAL, opCLTS, ILLEGAL, opINVD, opWBINVD, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, /*10*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, /*20*/ opMOV_r_CRx_a16,opMOV_r_DRx_a16,opMOV_CRx_r_a16,opMOV_DRx_r_a16,opMOV_r_TRx_a16,ILLEGAL, opMOV_TRx_r_a16,ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, @@ -1298,7 +1483,7 @@ const OpFn OP_TABLE(pentiummmx_0f)[1024] = /*f0*/ ILLEGAL, opPSLLW_a16, opPSLLD_a16, opPSLLQ_a16, ILLEGAL, opPMADDWD_a16, ILLEGAL, ILLEGAL, opPSUBB_a16, opPSUBW_a16, opPSUBD_a16, ILLEGAL, opPADDB_a16, opPADDW_a16, opPADDD_a16, ILLEGAL, /*32-bit data, 16-bit addr*/ -/* 00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f*/ +/* 00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f*/ /*00*/ op0F00_a16, op0F01_l_a16, opLAR_l_a16, opLSL_l_a16, ILLEGAL, ILLEGAL, opCLTS, ILLEGAL, opINVD, opWBINVD, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, /*10*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, /*20*/ opMOV_r_CRx_a16,opMOV_r_DRx_a16,opMOV_CRx_r_a16,opMOV_DRx_r_a16,opMOV_r_TRx_a16,ILLEGAL, opMOV_TRx_r_a16,ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, @@ -1320,7 +1505,7 @@ const OpFn OP_TABLE(pentiummmx_0f)[1024] = /*f0*/ ILLEGAL, opPSLLW_a16, opPSLLD_a16, opPSLLQ_a16, ILLEGAL, opPMADDWD_a16, ILLEGAL, ILLEGAL, opPSUBB_a16, opPSUBW_a16, opPSUBD_a16, ILLEGAL, opPADDB_a16, opPADDW_a16, opPADDD_a16, ILLEGAL, /*16-bit data, 32-bit addr*/ -/* 00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f*/ +/* 00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f*/ /*00*/ op0F00_a32, op0F01_w_a32, opLAR_w_a32, opLSL_w_a32, ILLEGAL, ILLEGAL, opCLTS, ILLEGAL, opINVD, opWBINVD, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, /*10*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, /*20*/ opMOV_r_CRx_a32,opMOV_r_DRx_a32,opMOV_CRx_r_a32,opMOV_DRx_r_a32,opMOV_r_TRx_a32,ILLEGAL, opMOV_TRx_r_a32,ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, @@ -1342,7 +1527,7 @@ const OpFn OP_TABLE(pentiummmx_0f)[1024] = /*f0*/ ILLEGAL, opPSLLW_a32, opPSLLD_a32, opPSLLQ_a32, ILLEGAL, opPMADDWD_a32, ILLEGAL, ILLEGAL, opPSUBB_a32, opPSUBW_a32, opPSUBD_a32, ILLEGAL, opPADDB_a32, opPADDW_a32, opPADDD_a32, ILLEGAL, /*32-bit data, 32-bit addr*/ -/* 00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f*/ +/* 00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f*/ /*00*/ op0F00_a32, op0F01_l_a32, opLAR_l_a32, opLSL_l_a32, ILLEGAL, ILLEGAL, opCLTS, ILLEGAL, opINVD, opWBINVD, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, /*10*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, /*20*/ opMOV_r_CRx_a32,opMOV_r_DRx_a32,opMOV_CRx_r_a32,opMOV_DRx_r_a32,opMOV_r_TRx_a32,ILLEGAL, opMOV_TRx_r_a32,ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, @@ -1362,12 +1547,13 @@ const OpFn OP_TABLE(pentiummmx_0f)[1024] = /*d0*/ ILLEGAL, opPSRLW_a32, opPSRLD_a32, opPSRLQ_a32, ILLEGAL, opPMULLW_a32, ILLEGAL, ILLEGAL, opPSUBUSB_a32, opPSUBUSW_a32, NULL, opPAND_a32, opPADDUSB_a32, opPADDUSW_a32, NULL, opPANDN_a32, /*e0*/ ILLEGAL, opPSRAW_a32, opPSRAD_a32, ILLEGAL, ILLEGAL, opPMULHW_a32, ILLEGAL, ILLEGAL, opPSUBSB_a32, opPSUBSW_a32, NULL, opPOR_a32, opPADDSB_a32, opPADDSW_a32, NULL, opPXOR_a32, /*f0*/ ILLEGAL, opPSLLW_a32, opPSLLD_a32, opPSLLQ_a32, ILLEGAL, opPMADDWD_a32, ILLEGAL, ILLEGAL, opPSUBB_a32, opPSUBW_a32, opPSUBD_a32, ILLEGAL, opPADDB_a32, opPADDW_a32, opPADDD_a32, ILLEGAL, + // clang-format on }; -const OpFn OP_TABLE(k6_0f)[1024] = -{ +const OpFn OP_TABLE(k6_0f)[1024] = { + // clang-format off /*16-bit data, 16-bit addr*/ -/* 00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f*/ +/* 00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f*/ /*00*/ op0F00_a16, op0F01_w_a16, opLAR_w_a16, opLSL_w_a16, ILLEGAL, opSYSCALL, opCLTS, opSYSRET, opINVD, opWBINVD, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, /*10*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, /*20*/ opMOV_r_CRx_a16,opMOV_r_DRx_a16,opMOV_CRx_r_a16,opMOV_DRx_r_a16,opMOV_r_TRx_a16,ILLEGAL, opMOV_TRx_r_a16,ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, @@ -1389,7 +1575,7 @@ const OpFn OP_TABLE(k6_0f)[1024] = /*f0*/ ILLEGAL, opPSLLW_a16, opPSLLD_a16, opPSLLQ_a16, ILLEGAL, opPMADDWD_a16, ILLEGAL, ILLEGAL, opPSUBB_a16, opPSUBW_a16, opPSUBD_a16, ILLEGAL, opPADDB_a16, opPADDW_a16, opPADDD_a16, ILLEGAL, /*32-bit data, 16-bit addr*/ -/* 00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f*/ +/* 00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f*/ /*00*/ op0F00_a16, op0F01_l_a16, opLAR_l_a16, opLSL_l_a16, ILLEGAL, opSYSCALL, opCLTS, opSYSRET, opINVD, opWBINVD, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, /*10*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, /*20*/ opMOV_r_CRx_a16,opMOV_r_DRx_a16,opMOV_CRx_r_a16,opMOV_DRx_r_a16,opMOV_r_TRx_a16,ILLEGAL, opMOV_TRx_r_a16,ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, @@ -1411,7 +1597,7 @@ const OpFn OP_TABLE(k6_0f)[1024] = /*f0*/ ILLEGAL, opPSLLW_a16, opPSLLD_a16, opPSLLQ_a16, ILLEGAL, opPMADDWD_a16, ILLEGAL, ILLEGAL, opPSUBB_a16, opPSUBW_a16, opPSUBD_a16, ILLEGAL, opPADDB_a16, opPADDW_a16, opPADDD_a16, ILLEGAL, /*16-bit data, 32-bit addr*/ -/* 00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f*/ +/* 00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f*/ /*00*/ op0F00_a32, op0F01_w_a32, opLAR_w_a32, opLSL_w_a32, ILLEGAL, opSYSCALL, opCLTS, opSYSRET, opINVD, opWBINVD, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, /*10*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, /*20*/ opMOV_r_CRx_a32,opMOV_r_DRx_a32,opMOV_CRx_r_a32,opMOV_DRx_r_a32,opMOV_r_TRx_a32,ILLEGAL, opMOV_TRx_r_a32,ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, @@ -1433,7 +1619,7 @@ const OpFn OP_TABLE(k6_0f)[1024] = /*f0*/ ILLEGAL, opPSLLW_a32, opPSLLD_a32, opPSLLQ_a32, ILLEGAL, opPMADDWD_a32, ILLEGAL, ILLEGAL, opPSUBB_a32, opPSUBW_a32, opPSUBD_a32, ILLEGAL, opPADDB_a32, opPADDW_a32, opPADDD_a32, ILLEGAL, /*32-bit data, 32-bit addr*/ -/* 00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f*/ +/* 00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f*/ /*00*/ op0F00_a32, op0F01_l_a32, opLAR_l_a32, opLSL_l_a32, ILLEGAL, opSYSCALL, opCLTS, opSYSRET, opINVD, opWBINVD, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, /*10*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, /*20*/ opMOV_r_CRx_a32,opMOV_r_DRx_a32,opMOV_CRx_r_a32,opMOV_DRx_r_a32,opMOV_r_TRx_a32,ILLEGAL, opMOV_TRx_r_a32,ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, @@ -1453,12 +1639,13 @@ const OpFn OP_TABLE(k6_0f)[1024] = /*d0*/ ILLEGAL, opPSRLW_a32, opPSRLD_a32, opPSRLQ_a32, ILLEGAL, opPMULLW_a32, ILLEGAL, ILLEGAL, opPSUBUSB_a32, opPSUBUSW_a32, NULL, opPAND_a32, opPADDUSB_a32, opPADDUSW_a32, NULL, opPANDN_a32, /*e0*/ ILLEGAL, opPSRAW_a32, opPSRAD_a32, ILLEGAL, ILLEGAL, opPMULHW_a32, ILLEGAL, ILLEGAL, opPSUBSB_a32, opPSUBSW_a32, NULL, opPOR_a32, opPADDSB_a32, opPADDSW_a32, NULL, opPXOR_a32, /*f0*/ ILLEGAL, opPSLLW_a32, opPSLLD_a32, opPSLLQ_a32, ILLEGAL, opPMADDWD_a32, ILLEGAL, ILLEGAL, opPSUBB_a32, opPSUBW_a32, opPSUBD_a32, ILLEGAL, opPADDB_a32, opPADDW_a32, opPADDD_a32, ILLEGAL, + // clang-format on }; -const OpFn OP_TABLE(k62_0f)[1024] = -{ +const OpFn OP_TABLE(k62_0f)[1024] = { + // clang-format off /*16-bit data, 16-bit addr*/ -/* 00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f*/ +/* 00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f*/ /*00*/ op0F00_a16, op0F01_w_a16, opLAR_w_a16, opLSL_w_a16, ILLEGAL, opSYSCALL, opCLTS, opSYSRET, opINVD, opWBINVD, ILLEGAL, ILLEGAL, ILLEGAL, opPREFETCH_a16, opFEMMS, op3DNOW_a16, /*10*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, /*20*/ opMOV_r_CRx_a16,opMOV_r_DRx_a16,opMOV_CRx_r_a16,opMOV_DRx_r_a16,opMOV_r_TRx_a16,ILLEGAL, opMOV_TRx_r_a16,ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, @@ -1480,7 +1667,7 @@ const OpFn OP_TABLE(k62_0f)[1024] = /*f0*/ ILLEGAL, opPSLLW_a16, opPSLLD_a16, opPSLLQ_a16, ILLEGAL, opPMADDWD_a16, ILLEGAL, ILLEGAL, opPSUBB_a16, opPSUBW_a16, opPSUBD_a16, ILLEGAL, opPADDB_a16, opPADDW_a16, opPADDD_a16, ILLEGAL, /*32-bit data, 16-bit addr*/ -/* 00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f*/ +/* 00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f*/ /*00*/ op0F00_a16, op0F01_l_a16, opLAR_l_a16, opLSL_l_a16, ILLEGAL, opSYSCALL, opCLTS, opSYSRET, opINVD, opWBINVD, ILLEGAL, ILLEGAL, ILLEGAL, opPREFETCH_a16, opFEMMS, op3DNOW_a16, /*10*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, /*20*/ opMOV_r_CRx_a16,opMOV_r_DRx_a16,opMOV_CRx_r_a16,opMOV_DRx_r_a16,opMOV_r_TRx_a16,ILLEGAL, opMOV_TRx_r_a16,ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, @@ -1502,7 +1689,7 @@ const OpFn OP_TABLE(k62_0f)[1024] = /*f0*/ ILLEGAL, opPSLLW_a16, opPSLLD_a16, opPSLLQ_a16, ILLEGAL, opPMADDWD_a16, ILLEGAL, ILLEGAL, opPSUBB_a16, opPSUBW_a16, opPSUBD_a16, ILLEGAL, opPADDB_a16, opPADDW_a16, opPADDD_a16, ILLEGAL, /*16-bit data, 32-bit addr*/ -/* 00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f*/ +/* 00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f*/ /*00*/ op0F00_a32, op0F01_w_a32, opLAR_w_a32, opLSL_w_a32, ILLEGAL, opSYSCALL, opCLTS, opSYSRET, opINVD, opWBINVD, ILLEGAL, ILLEGAL, ILLEGAL, opPREFETCH_a32, opFEMMS, op3DNOW_a32, /*10*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, /*20*/ opMOV_r_CRx_a32,opMOV_r_DRx_a32,opMOV_CRx_r_a32,opMOV_DRx_r_a32,opMOV_r_TRx_a32,ILLEGAL, opMOV_TRx_r_a32,ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, @@ -1524,7 +1711,7 @@ const OpFn OP_TABLE(k62_0f)[1024] = /*f0*/ ILLEGAL, opPSLLW_a32, opPSLLD_a32, opPSLLQ_a32, ILLEGAL, opPMADDWD_a32, ILLEGAL, ILLEGAL, opPSUBB_a32, opPSUBW_a32, opPSUBD_a32, ILLEGAL, opPADDB_a32, opPADDW_a32, opPADDD_a32, ILLEGAL, /*32-bit data, 32-bit addr*/ -/* 00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f*/ +/* 00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f*/ /*00*/ op0F00_a32, op0F01_l_a32, opLAR_l_a32, opLSL_l_a32, ILLEGAL, opSYSCALL, opCLTS, opSYSRET, opINVD, opWBINVD, ILLEGAL, ILLEGAL, ILLEGAL, opPREFETCH_a32, opFEMMS, op3DNOW_a32, /*10*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, /*20*/ opMOV_r_CRx_a32,opMOV_r_DRx_a32,opMOV_CRx_r_a32,opMOV_DRx_r_a32,opMOV_r_TRx_a32,ILLEGAL, opMOV_TRx_r_a32,ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, @@ -1544,13 +1731,14 @@ const OpFn OP_TABLE(k62_0f)[1024] = /*d0*/ ILLEGAL, opPSRLW_a32, opPSRLD_a32, opPSRLQ_a32, ILLEGAL, opPMULLW_a32, ILLEGAL, ILLEGAL, opPSUBUSB_a32, opPSUBUSW_a32, NULL, opPAND_a32, opPADDUSB_a32, opPADDUSW_a32, NULL, opPANDN_a32, /*e0*/ ILLEGAL, opPSRAW_a32, opPSRAD_a32, ILLEGAL, ILLEGAL, opPMULHW_a32, ILLEGAL, ILLEGAL, opPSUBSB_a32, opPSUBSW_a32, NULL, opPOR_a32, opPADDSB_a32, opPADDSW_a32, NULL, opPXOR_a32, /*f0*/ ILLEGAL, opPSLLW_a32, opPSLLD_a32, opPSLLQ_a32, ILLEGAL, opPMADDWD_a32, ILLEGAL, ILLEGAL, opPSUBB_a32, opPSUBW_a32, opPSUBD_a32, ILLEGAL, opPADDB_a32, opPADDW_a32, opPADDD_a32, ILLEGAL, + // clang-format on }; -#if defined(DEV_BRANCH) && defined(USE_CYRIX_6X86) -const OpFn OP_TABLE(c6x86mx_0f)[1024] = -{ +# if defined(DEV_BRANCH) && defined(USE_CYRIX_6X86) +const OpFn OP_TABLE(c6x86mx_0f)[1024] = { + // clang-format off /*16-bit data, 16-bit addr*/ -/* 00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f*/ +/* 00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f*/ /*00*/ op0F00_a16, op0F01_w_a16, opLAR_w_a16, opLSL_w_a16, ILLEGAL, ILLEGAL, opCLTS, ILLEGAL, opINVD, opWBINVD, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, /*10*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, /*20*/ opMOV_r_CRx_a16,opMOV_r_DRx_a16,opMOV_CRx_r_a16,opMOV_DRx_r_a16,opMOV_r_TRx_a16,ILLEGAL, opMOV_TRx_r_a16,ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, @@ -1572,7 +1760,7 @@ const OpFn OP_TABLE(c6x86mx_0f)[1024] = /*f0*/ ILLEGAL, opPSLLW_a16, opPSLLD_a16, opPSLLQ_a16, ILLEGAL, opPMADDWD_a16, ILLEGAL, ILLEGAL, opPSUBB_a16, opPSUBW_a16, opPSUBD_a16, ILLEGAL, opPADDB_a16, opPADDW_a16, opPADDD_a16, ILLEGAL, /*32-bit data, 16-bit addr*/ -/* 00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f*/ +/* 00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f*/ /*00*/ op0F00_a16, op0F01_l_a16, opLAR_l_a16, opLSL_l_a16, ILLEGAL, ILLEGAL, opCLTS, ILLEGAL, opINVD, opWBINVD, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, /*10*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, /*20*/ opMOV_r_CRx_a16,opMOV_r_DRx_a16,opMOV_CRx_r_a16,opMOV_DRx_r_a16,opMOV_r_TRx_a16,ILLEGAL, opMOV_TRx_r_a16,ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, @@ -1594,7 +1782,7 @@ const OpFn OP_TABLE(c6x86mx_0f)[1024] = /*f0*/ ILLEGAL, opPSLLW_a16, opPSLLD_a16, opPSLLQ_a16, ILLEGAL, opPMADDWD_a16, ILLEGAL, ILLEGAL, opPSUBB_a16, opPSUBW_a16, opPSUBD_a16, ILLEGAL, opPADDB_a16, opPADDW_a16, opPADDD_a16, ILLEGAL, /*16-bit data, 32-bit addr*/ -/* 00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f*/ +/* 00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f*/ /*00*/ op0F00_a32, op0F01_w_a32, opLAR_w_a32, opLSL_w_a32, ILLEGAL, ILLEGAL, opCLTS, ILLEGAL, opINVD, opWBINVD, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, /*10*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, /*20*/ opMOV_r_CRx_a32,opMOV_r_DRx_a32,opMOV_CRx_r_a32,opMOV_DRx_r_a32,opMOV_r_TRx_a32,ILLEGAL, opMOV_TRx_r_a32,ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, @@ -1616,7 +1804,7 @@ const OpFn OP_TABLE(c6x86mx_0f)[1024] = /*f0*/ ILLEGAL, opPSLLW_a32, opPSLLD_a32, opPSLLQ_a32, ILLEGAL, opPMADDWD_a32, ILLEGAL, ILLEGAL, opPSUBB_a32, opPSUBW_a32, opPSUBD_a32, ILLEGAL, opPADDB_a32, opPADDW_a32, opPADDD_a32, ILLEGAL, /*32-bit data, 32-bit addr*/ -/* 00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f*/ +/* 00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f*/ /*00*/ op0F00_a32, op0F01_l_a32, opLAR_l_a32, opLSL_l_a32, ILLEGAL, ILLEGAL, opCLTS, ILLEGAL, opINVD, opWBINVD, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, /*10*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, /*20*/ opMOV_r_CRx_a32,opMOV_r_DRx_a32,opMOV_CRx_r_a32,opMOV_DRx_r_a32,opMOV_r_TRx_a32,ILLEGAL, opMOV_TRx_r_a32,ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, @@ -1636,13 +1824,14 @@ const OpFn OP_TABLE(c6x86mx_0f)[1024] = /*d0*/ ILLEGAL, opPSRLW_a32, opPSRLD_a32, opPSRLQ_a32, ILLEGAL, opPMULLW_a32, ILLEGAL, ILLEGAL, opPSUBUSB_a32, opPSUBUSW_a32, NULL, opPAND_a32, opPADDUSB_a32, opPADDUSW_a32, NULL, opPANDN_a32, /*e0*/ ILLEGAL, opPSRAW_a32, opPSRAD_a32, ILLEGAL, ILLEGAL, opPMULHW_a32, ILLEGAL, ILLEGAL, opPSUBSB_a32, opPSUBSW_a32, NULL, opPOR_a32, opPADDSB_a32, opPADDSW_a32, NULL, opPXOR_a32, /*f0*/ ILLEGAL, opPSLLW_a32, opPSLLD_a32, opPSLLQ_a32, ILLEGAL, opPMADDWD_a32, ILLEGAL, ILLEGAL, opPSUBB_a32, opPSUBW_a32, opPSUBD_a32, ILLEGAL, opPADDB_a32, opPADDW_a32, opPADDD_a32, ILLEGAL, + // clang-format on }; -#endif +# endif -const OpFn OP_TABLE(pentiumpro_0f)[1024] = -{ +const OpFn OP_TABLE(pentiumpro_0f)[1024] = { + // clang-format off /*16-bit data, 16-bit addr*/ -/* 00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f*/ +/* 00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f*/ /*00*/ op0F00_a16, op0F01_w_a16, opLAR_w_a16, opLSL_w_a16, ILLEGAL, ILLEGAL, opCLTS, ILLEGAL, opINVD, opWBINVD, ILLEGAL, ILLEGAL, ILLEGAL, opNOP, ILLEGAL, ILLEGAL, /*10*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, opHINT_NOP_a16, opHINT_NOP_a16, opHINT_NOP_a16, opHINT_NOP_a16, opHINT_NOP_a16, opHINT_NOP_a16, opHINT_NOP_a16, opHINT_NOP_a16, /*20*/ opMOV_r_CRx_a16,opMOV_r_DRx_a16,opMOV_CRx_r_a16,opMOV_DRx_r_a16,opMOV_r_TRx_a16,ILLEGAL, opMOV_TRx_r_a16,ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, @@ -1664,7 +1853,7 @@ const OpFn OP_TABLE(pentiumpro_0f)[1024] = /*f0*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, /*32-bit data, 16-bit addr*/ -/* 00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f*/ +/* 00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f*/ /*00*/ op0F00_a16, op0F01_l_a16, opLAR_l_a16, opLSL_l_a16, ILLEGAL, ILLEGAL, opCLTS, ILLEGAL, opINVD, opWBINVD, ILLEGAL, ILLEGAL, ILLEGAL, opNOP, ILLEGAL, ILLEGAL, /*10*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, opHINT_NOP_a16, opHINT_NOP_a16, opHINT_NOP_a16, opHINT_NOP_a16, opHINT_NOP_a16, opHINT_NOP_a16, opHINT_NOP_a16, opHINT_NOP_a16, /*20*/ opMOV_r_CRx_a16,opMOV_r_DRx_a16,opMOV_CRx_r_a16,opMOV_DRx_r_a16,opMOV_r_TRx_a16,ILLEGAL, opMOV_TRx_r_a16,ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, @@ -1686,7 +1875,7 @@ const OpFn OP_TABLE(pentiumpro_0f)[1024] = /*f0*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, /*16-bit data, 32-bit addr*/ -/* 00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f*/ +/* 00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f*/ /*00*/ op0F00_a32, op0F01_w_a32, opLAR_w_a32, opLSL_w_a32, ILLEGAL, ILLEGAL, opCLTS, ILLEGAL, opINVD, opWBINVD, ILLEGAL, ILLEGAL, ILLEGAL, opNOP, ILLEGAL, ILLEGAL, /*10*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, opHINT_NOP_a32, opHINT_NOP_a32, opHINT_NOP_a32, opHINT_NOP_a32, opHINT_NOP_a32, opHINT_NOP_a32, opHINT_NOP_a32, opHINT_NOP_a32, /*20*/ opMOV_r_CRx_a32,opMOV_r_DRx_a32,opMOV_CRx_r_a32,opMOV_DRx_r_a32,opMOV_r_TRx_a32,ILLEGAL, opMOV_TRx_r_a32,ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, @@ -1708,7 +1897,7 @@ const OpFn OP_TABLE(pentiumpro_0f)[1024] = /*f0*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, /*32-bit data, 32-bit addr*/ -/* 00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f*/ +/* 00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f*/ /*00*/ op0F00_a32, op0F01_l_a32, opLAR_l_a32, opLSL_l_a32, ILLEGAL, ILLEGAL, opCLTS, ILLEGAL, opINVD, opWBINVD, ILLEGAL, ILLEGAL, ILLEGAL, opNOP, ILLEGAL, ILLEGAL, /*10*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, opHINT_NOP_a32, opHINT_NOP_a32, opHINT_NOP_a32, opHINT_NOP_a32, opHINT_NOP_a32, opHINT_NOP_a32, opHINT_NOP_a32, opHINT_NOP_a32, /*20*/ opMOV_r_CRx_a32,opMOV_r_DRx_a32,opMOV_CRx_r_a32,opMOV_DRx_r_a32,opMOV_r_TRx_a32,ILLEGAL, opMOV_TRx_r_a32,ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, @@ -1728,12 +1917,13 @@ const OpFn OP_TABLE(pentiumpro_0f)[1024] = /*d0*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, /*e0*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, /*f0*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, + // clang-format on }; -const OpFn OP_TABLE(pentium2_0f)[1024] = -{ +const OpFn OP_TABLE(pentium2_0f)[1024] = { + // clang-format off /*16-bit data, 16-bit addr*/ -/* 00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f*/ +/* 00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f*/ /*00*/ op0F00_a16, op0F01_w_a16, opLAR_w_a16, opLSL_w_a16, ILLEGAL, ILLEGAL, opCLTS, ILLEGAL, opINVD, opWBINVD, ILLEGAL, ILLEGAL, ILLEGAL, opNOP, ILLEGAL, ILLEGAL, /*10*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, opHINT_NOP_a16, opHINT_NOP_a16, opHINT_NOP_a16, opHINT_NOP_a16, opHINT_NOP_a16, opHINT_NOP_a16, opHINT_NOP_a16, opHINT_NOP_a16, /*20*/ opMOV_r_CRx_a16,opMOV_r_DRx_a16,opMOV_CRx_r_a16,opMOV_DRx_r_a16,opMOV_r_TRx_a16,ILLEGAL, opMOV_TRx_r_a16,ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, @@ -1755,7 +1945,7 @@ const OpFn OP_TABLE(pentium2_0f)[1024] = /*f0*/ ILLEGAL, opPSLLW_a16, opPSLLD_a16, opPSLLQ_a16, ILLEGAL, opPMADDWD_a16, ILLEGAL, ILLEGAL, opPSUBB_a16, opPSUBW_a16, opPSUBD_a16, ILLEGAL, opPADDB_a16, opPADDW_a16, opPADDD_a16, ILLEGAL, /*32-bit data, 16-bit addr*/ -/* 00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f*/ +/* 00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f*/ /*00*/ op0F00_a16, op0F01_l_a16, opLAR_l_a16, opLSL_l_a16, ILLEGAL, ILLEGAL, opCLTS, ILLEGAL, opINVD, opWBINVD, ILLEGAL, ILLEGAL, ILLEGAL, opNOP, ILLEGAL, ILLEGAL, /*10*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, opHINT_NOP_a16, opHINT_NOP_a16, opHINT_NOP_a16, opHINT_NOP_a16, opHINT_NOP_a16, opHINT_NOP_a16, opHINT_NOP_a16, opHINT_NOP_a16, /*20*/ opMOV_r_CRx_a16,opMOV_r_DRx_a16,opMOV_CRx_r_a16,opMOV_DRx_r_a16,opMOV_r_TRx_a16,ILLEGAL, opMOV_TRx_r_a16,ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, @@ -1777,7 +1967,7 @@ const OpFn OP_TABLE(pentium2_0f)[1024] = /*f0*/ ILLEGAL, opPSLLW_a16, opPSLLD_a16, opPSLLQ_a16, ILLEGAL, opPMADDWD_a16, ILLEGAL, ILLEGAL, opPSUBB_a16, opPSUBW_a16, opPSUBD_a16, ILLEGAL, opPADDB_a16, opPADDW_a16, opPADDD_a16, ILLEGAL, /*16-bit data, 32-bit addr*/ -/* 00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f*/ +/* 00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f*/ /*00*/ op0F00_a32, op0F01_w_a32, opLAR_w_a32, opLSL_w_a32, ILLEGAL, ILLEGAL, opCLTS, ILLEGAL, opINVD, opWBINVD, ILLEGAL, ILLEGAL, ILLEGAL, opNOP, ILLEGAL, ILLEGAL, /*10*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, opHINT_NOP_a32, opHINT_NOP_a32, opHINT_NOP_a32, opHINT_NOP_a32, opHINT_NOP_a32, opHINT_NOP_a32, opHINT_NOP_a32, opHINT_NOP_a32, /*20*/ opMOV_r_CRx_a32,opMOV_r_DRx_a32,opMOV_CRx_r_a32,opMOV_DRx_r_a32,opMOV_r_TRx_a32,ILLEGAL, opMOV_TRx_r_a32,ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, @@ -1799,7 +1989,7 @@ const OpFn OP_TABLE(pentium2_0f)[1024] = /*f0*/ ILLEGAL, opPSLLW_a32, opPSLLD_a32, opPSLLQ_a32, ILLEGAL, opPMADDWD_a32, ILLEGAL, ILLEGAL, opPSUBB_a32, opPSUBW_a32, opPSUBD_a32, ILLEGAL, opPADDB_a32, opPADDW_a32, opPADDD_a32, ILLEGAL, /*32-bit data, 32-bit addr*/ -/* 00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f*/ +/* 00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f*/ /*00*/ op0F00_a32, op0F01_l_a32, opLAR_l_a32, opLSL_l_a32, ILLEGAL, ILLEGAL, opCLTS, ILLEGAL, opINVD, opWBINVD, ILLEGAL, ILLEGAL, ILLEGAL, opNOP, ILLEGAL, ILLEGAL, /*10*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, opHINT_NOP_a32, opHINT_NOP_a32, opHINT_NOP_a32, opHINT_NOP_a32, opHINT_NOP_a32, opHINT_NOP_a32, opHINT_NOP_a32, opHINT_NOP_a32, /*20*/ opMOV_r_CRx_a32,opMOV_r_DRx_a32,opMOV_CRx_r_a32,opMOV_DRx_r_a32,opMOV_r_TRx_a32,ILLEGAL, opMOV_TRx_r_a32,ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, @@ -1819,12 +2009,13 @@ const OpFn OP_TABLE(pentium2_0f)[1024] = /*d0*/ ILLEGAL, opPSRLW_a32, opPSRLD_a32, opPSRLQ_a32, ILLEGAL, opPMULLW_a32, ILLEGAL, ILLEGAL, opPSUBUSB_a32, opPSUBUSW_a32, NULL, opPAND_a32, opPADDUSB_a32, opPADDUSW_a32, NULL, opPANDN_a32, /*e0*/ ILLEGAL, opPSRAW_a32, opPSRAD_a32, ILLEGAL, ILLEGAL, opPMULHW_a32, ILLEGAL, ILLEGAL, opPSUBSB_a32, opPSUBSW_a32, NULL, opPOR_a32, opPADDSB_a32, opPADDSW_a32, NULL, opPXOR_a32, /*f0*/ ILLEGAL, opPSLLW_a32, opPSLLD_a32, opPSLLQ_a32, ILLEGAL, opPMADDWD_a32, ILLEGAL, ILLEGAL, opPSUBB_a32, opPSUBW_a32, opPSUBD_a32, ILLEGAL, opPADDB_a32, opPADDW_a32, opPADDD_a32, ILLEGAL, + // clang-format on }; -const OpFn OP_TABLE(pentium2d_0f)[1024] = -{ +const OpFn OP_TABLE(pentium2d_0f)[1024] = { + // clang-format off /*16-bit data, 16-bit addr*/ -/* 00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f*/ +/* 00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f*/ /*00*/ op0F00_a16, op0F01_w_a16, opLAR_w_a16, opLSL_w_a16, ILLEGAL, ILLEGAL, opCLTS, ILLEGAL, opINVD, opWBINVD, ILLEGAL, ILLEGAL, ILLEGAL, opNOP, ILLEGAL, ILLEGAL, /*10*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, opHINT_NOP_a16, opHINT_NOP_a16, opHINT_NOP_a16, opHINT_NOP_a16, opHINT_NOP_a16, opHINT_NOP_a16, opHINT_NOP_a16, opHINT_NOP_a16, /*20*/ opMOV_r_CRx_a16,opMOV_r_DRx_a16,opMOV_CRx_r_a16,opMOV_DRx_r_a16,opMOV_r_TRx_a16,ILLEGAL, opMOV_TRx_r_a16,ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, @@ -1846,7 +2037,7 @@ const OpFn OP_TABLE(pentium2d_0f)[1024] = /*f0*/ ILLEGAL, opPSLLW_a16, opPSLLD_a16, opPSLLQ_a16, ILLEGAL, opPMADDWD_a16, ILLEGAL, ILLEGAL, opPSUBB_a16, opPSUBW_a16, opPSUBD_a16, ILLEGAL, opPADDB_a16, opPADDW_a16, opPADDD_a16, ILLEGAL, /*32-bit data, 16-bit addr*/ -/* 00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f*/ +/* 00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f*/ /*00*/ op0F00_a16, op0F01_l_a16, opLAR_l_a16, opLSL_l_a16, ILLEGAL, ILLEGAL, opCLTS, ILLEGAL, opINVD, opWBINVD, ILLEGAL, ILLEGAL, ILLEGAL, opNOP, ILLEGAL, ILLEGAL, /*10*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, opHINT_NOP_a16, opHINT_NOP_a16, opHINT_NOP_a16, opHINT_NOP_a16, opHINT_NOP_a16, opHINT_NOP_a16, opHINT_NOP_a16, opHINT_NOP_a16, /*20*/ opMOV_r_CRx_a16,opMOV_r_DRx_a16,opMOV_CRx_r_a16,opMOV_DRx_r_a16,opMOV_r_TRx_a16,ILLEGAL, opMOV_TRx_r_a16,ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, @@ -1868,7 +2059,7 @@ const OpFn OP_TABLE(pentium2d_0f)[1024] = /*f0*/ ILLEGAL, opPSLLW_a16, opPSLLD_a16, opPSLLQ_a16, ILLEGAL, opPMADDWD_a16, ILLEGAL, ILLEGAL, opPSUBB_a16, opPSUBW_a16, opPSUBD_a16, ILLEGAL, opPADDB_a16, opPADDW_a16, opPADDD_a16, ILLEGAL, /*16-bit data, 32-bit addr*/ -/* 00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f*/ +/* 00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f*/ /*00*/ op0F00_a32, op0F01_w_a32, opLAR_w_a32, opLSL_w_a32, ILLEGAL, ILLEGAL, opCLTS, ILLEGAL, opINVD, opWBINVD, ILLEGAL, ILLEGAL, ILLEGAL, opNOP, ILLEGAL, ILLEGAL, /*10*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, opHINT_NOP_a32, opHINT_NOP_a32, opHINT_NOP_a32, opHINT_NOP_a32, opHINT_NOP_a32, opHINT_NOP_a32, opHINT_NOP_a32, opHINT_NOP_a32, /*20*/ opMOV_r_CRx_a32,opMOV_r_DRx_a32,opMOV_CRx_r_a32,opMOV_DRx_r_a32,opMOV_r_TRx_a32,ILLEGAL, opMOV_TRx_r_a32,ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, @@ -1890,7 +2081,7 @@ const OpFn OP_TABLE(pentium2d_0f)[1024] = /*f0*/ ILLEGAL, opPSLLW_a32, opPSLLD_a32, opPSLLQ_a32, ILLEGAL, opPMADDWD_a32, ILLEGAL, ILLEGAL, opPSUBB_a32, opPSUBW_a32, opPSUBD_a32, ILLEGAL, opPADDB_a32, opPADDW_a32, opPADDD_a32, ILLEGAL, /*32-bit data, 32-bit addr*/ -/* 00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f*/ +/* 00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f*/ /*00*/ op0F00_a32, op0F01_l_a32, opLAR_l_a32, opLSL_l_a32, ILLEGAL, ILLEGAL, opCLTS, ILLEGAL, opINVD, opWBINVD, ILLEGAL, ILLEGAL, ILLEGAL, opNOP, ILLEGAL, ILLEGAL, /*10*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, opHINT_NOP_a32, opHINT_NOP_a32, opHINT_NOP_a32, opHINT_NOP_a32, opHINT_NOP_a32, opHINT_NOP_a32, opHINT_NOP_a32, opHINT_NOP_a32, /*20*/ opMOV_r_CRx_a32,opMOV_r_DRx_a32,opMOV_CRx_r_a32,opMOV_DRx_r_a32,opMOV_r_TRx_a32,ILLEGAL, opMOV_TRx_r_a32,ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, @@ -1910,19 +2101,113 @@ const OpFn OP_TABLE(pentium2d_0f)[1024] = /*d0*/ ILLEGAL, opPSRLW_a32, opPSRLD_a32, opPSRLQ_a32, ILLEGAL, opPMULLW_a32, ILLEGAL, ILLEGAL, opPSUBUSB_a32, opPSUBUSW_a32, NULL, opPAND_a32, opPADDUSB_a32, opPADDUSW_a32, NULL, opPANDN_a32, /*e0*/ ILLEGAL, opPSRAW_a32, opPSRAD_a32, ILLEGAL, ILLEGAL, opPMULHW_a32, ILLEGAL, ILLEGAL, opPSUBSB_a32, opPSUBSW_a32, NULL, opPOR_a32, opPADDSB_a32, opPADDSW_a32, NULL, opPXOR_a32, /*f0*/ ILLEGAL, opPSLLW_a32, opPSLLD_a32, opPSLLQ_a32, ILLEGAL, opPMADDWD_a32, ILLEGAL, ILLEGAL, opPSUBB_a32, opPSUBW_a32, opPSUBD_a32, ILLEGAL, opPADDB_a32, opPADDW_a32, opPADDD_a32, ILLEGAL, + // clang-format on }; +#endif -const OpFn OP_TABLE(286)[1024] = -{ +const OpFn OP_TABLE(186)[1024] = { + // clang-format off /*16-bit data, 16-bit addr*/ -/* 00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f*/ +/* 00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f*/ /*00*/ opADD_b_rmw_a16,opADD_w_rmw_a16,opADD_b_rm_a16, opADD_w_rm_a16, opADD_AL_imm, opADD_AX_imm, opPUSH_ES_w, opPOP_ES_w, opOR_b_rmw_a16, opOR_w_rmw_a16, opOR_b_rm_a16, opOR_w_rm_a16, opOR_AL_imm, opOR_AX_imm, opPUSH_CS_w, op0F_w_a16, /*10*/ opADC_b_rmw_a16,opADC_w_rmw_a16,opADC_b_rm_a16, opADC_w_rm_a16, opADC_AL_imm, opADC_AX_imm, opPUSH_SS_w, opPOP_SS_w, opSBB_b_rmw_a16,opSBB_w_rmw_a16,opSBB_b_rm_a16, opSBB_w_rm_a16, opSBB_AL_imm, opSBB_AX_imm, opPUSH_DS_w, opPOP_DS_w, /*20*/ opAND_b_rmw_a16,opAND_w_rmw_a16,opAND_b_rm_a16, opAND_w_rm_a16, opAND_AL_imm, opAND_AX_imm, opES_w_a16, opDAA, opSUB_b_rmw_a16,opSUB_w_rmw_a16,opSUB_b_rm_a16, opSUB_w_rm_a16, opSUB_AL_imm, opSUB_AX_imm, opCS_w_a16, opDAS, /*30*/ opXOR_b_rmw_a16,opXOR_w_rmw_a16,opXOR_b_rm_a16, opXOR_w_rm_a16, opXOR_AL_imm, opXOR_AX_imm, opSS_w_a16, opAAA, opCMP_b_rmw_a16,opCMP_w_rmw_a16,opCMP_b_rm_a16, opCMP_w_rm_a16, opCMP_AL_imm, opCMP_AX_imm, opDS_w_a16, opAAS, -/*40*/ opINC_AX, opINC_CX, opINC_DX, opINC_BX, opINC_SP, opINC_BP, opINC_SI, opINC_DI, opDEC_AX, opDEC_CX, opDEC_DX, opDEC_BX, opDEC_SP, opDEC_BP, opDEC_SI, opDEC_DI, -/*50*/ opPUSH_AX, opPUSH_CX, opPUSH_DX, opPUSH_BX, opPUSH_SP, opPUSH_BP, opPUSH_SI, opPUSH_DI, opPOP_AX, opPOP_CX, opPOP_DX, opPOP_BX, opPOP_SP, opPOP_BP, opPOP_SI, opPOP_DI, +/*40*/ opINC_AX, opINC_CX, opINC_DX, opINC_BX, opINC_SP, opINC_BP, opINC_SI, opINC_DI, opDEC_AX, opDEC_CX, opDEC_DX, opDEC_BX, opDEC_SP, opDEC_BP, opDEC_SI, opDEC_DI, +/*50*/ opPUSH_AX, opPUSH_CX, opPUSH_DX, opPUSH_BX, opPUSH_SP, opPUSH_BP, opPUSH_SI, opPUSH_DI, opPOP_AX, opPOP_CX, opPOP_DX, opPOP_BX, opPOP_SP, opPOP_BP, opPOP_SI, opPOP_DI, +/*60*/ opPUSHA_w, opPOPA_w, opBOUND_w_a16, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, opPUSH_imm_w, opIMUL_w_iw_a16,opPUSH_imm_bw, opIMUL_w_ib_a16,opINSB_a16, opINSW_a16, opOUTSB_a16, opOUTSW_a16, +/*70*/ opJO, opJNO, opJB, opJNB, opJE, opJNE, opJBE, opJNBE, opJS, opJNS, opJP, opJNP, opJL, opJNL, opJLE, opJNLE, + +/*80*/ op80_a16, op81_w_a16, op80_a16, op83_w_a16, opTEST_b_a16, opTEST_w_a16, opXCHG_b_a16, opXCHG_w_a16, opMOV_b_r_a16, opMOV_w_r_a16, opMOV_r_b_a16, opMOV_r_w_a16, opMOV_w_seg_a16,opLEA_w_a16, opMOV_seg_w_a16,opPOPW_a16, +/*90*/ opNOP, opXCHG_AX_CX, opXCHG_AX_DX, opXCHG_AX_BX, opXCHG_AX_SP, opXCHG_AX_BP, opXCHG_AX_SI, opXCHG_AX_DI, opCBW, opCWD, opCALL_far_w, opWAIT, opPUSHF, opPOPF_186, opSAHF, opLAHF, +/*a0*/ opMOV_AL_a16, opMOV_AX_a16, opMOV_a16_AL, opMOV_a16_AX, opMOVSB_a16, opMOVSW_a16, opCMPSB_a16, opCMPSW_a16, opTEST_AL, opTEST_AX, opSTOSB_a16, opSTOSW_a16, opLODSB_a16, opLODSW_a16, opSCASB_a16, opSCASW_a16, +/*b0*/ opMOV_AL_imm, opMOV_CL_imm, opMOV_DL_imm, opMOV_BL_imm, opMOV_AH_imm, opMOV_CH_imm, opMOV_DH_imm, opMOV_BH_imm, opMOV_AX_imm, opMOV_CX_imm, opMOV_DX_imm, opMOV_BX_imm, opMOV_SP_imm, opMOV_BP_imm, opMOV_SI_imm, opMOV_DI_imm, + +/*c0*/ opC0_a16, opC1_w_a16, opRET_w_imm, opRET_w, opLES_w_a16, opLDS_w_a16, opMOV_b_imm_a16,opMOV_w_imm_a16,opENTER_w, opLEAVE_w, opRETF_a16_imm, opRETF_a16, opINT3, opINT, opINTO, opIRET_186, +/*d0*/ opD0_a16, opD1_w_a16, opD2_a16, opD3_w_a16, opAAM, opAAD, opSETALC, opXLAT_a16, opESCAPE_d8_a16,opESCAPE_d9_a16,opESCAPE_da_a16,opESCAPE_db_a16,opESCAPE_dc_a16,opESCAPE_dd_a16,opESCAPE_de_a16,opESCAPE_df_a16, +/*e0*/ opLOOPNE_w, opLOOPE_w, opLOOP_w, opJCXZ, opIN_AL_imm, opIN_AX_imm, opOUT_AL_imm, opOUT_AX_imm, opCALL_r16, opJMP_r16, opJMP_far_a16, opJMP_r8, opIN_AL_DX, opIN_AX_DX, opOUT_AL_DX, opOUT_AX_DX, +/*f0*/ opLOCK, opLOCK, opREPNE, opREPE, opHLT, opCMC, opF6_a16, opF7_w_a16, opCLC, opSTC, opCLI, opSTI, opCLD, opSTD, opINCDEC_b_a16, opFF_w_a16, + + /*32-bit data, 16-bit addr*/ +/* 00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f*/ +/*00*/ opADD_b_rmw_a16,opADD_w_rmw_a16,opADD_b_rm_a16, opADD_w_rm_a16, opADD_AL_imm, opADD_AX_imm, opPUSH_ES_w, opPOP_ES_w, opOR_b_rmw_a16, opOR_w_rmw_a16, opOR_b_rm_a16, opOR_w_rm_a16, opOR_AL_imm, opOR_AX_imm, opPUSH_CS_w, op0F_w_a16, +/*10*/ opADC_b_rmw_a16,opADC_w_rmw_a16,opADC_b_rm_a16, opADC_w_rm_a16, opADC_AL_imm, opADC_AX_imm, opPUSH_SS_w, opPOP_SS_w, opSBB_b_rmw_a16,opSBB_w_rmw_a16,opSBB_b_rm_a16, opSBB_w_rm_a16, opSBB_AL_imm, opSBB_AX_imm, opPUSH_DS_w, opPOP_DS_w, +/*20*/ opAND_b_rmw_a16,opAND_w_rmw_a16,opAND_b_rm_a16, opAND_w_rm_a16, opAND_AL_imm, opAND_AX_imm, opES_w_a16, opDAA, opSUB_b_rmw_a16,opSUB_w_rmw_a16,opSUB_b_rm_a16, opSUB_w_rm_a16, opSUB_AL_imm, opSUB_AX_imm, opCS_w_a16, opDAS, +/*30*/ opXOR_b_rmw_a16,opXOR_w_rmw_a16,opXOR_b_rm_a16, opXOR_w_rm_a16, opXOR_AL_imm, opXOR_AX_imm, opSS_w_a16, opAAA, opCMP_b_rmw_a16,opCMP_w_rmw_a16,opCMP_b_rm_a16, opCMP_w_rm_a16, opCMP_AL_imm, opCMP_AX_imm, opDS_w_a16, opAAS, + +/*40*/ opINC_AX, opINC_CX, opINC_DX, opINC_BX, opINC_SP, opINC_BP, opINC_SI, opINC_DI, opDEC_AX, opDEC_CX, opDEC_DX, opDEC_BX, opDEC_SP, opDEC_BP, opDEC_SI, opDEC_DI, +/*50*/ opPUSH_AX, opPUSH_CX, opPUSH_DX, opPUSH_BX, opPUSH_SP, opPUSH_BP, opPUSH_SI, opPUSH_DI, opPOP_AX, opPOP_CX, opPOP_DX, opPOP_BX, opPOP_SP, opPOP_BP, opPOP_SI, opPOP_DI, +/*60*/ opPUSHA_w, opPOPA_w, opBOUND_w_a16, opARPL_a16, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, opPUSH_imm_w, opIMUL_w_iw_a16,opPUSH_imm_bw, opIMUL_w_ib_a16,opINSB_a16, opINSW_a16, opOUTSB_a16, opOUTSW_a16, +/*70*/ opJO, opJNO, opJB, opJNB, opJE, opJNE, opJBE, opJNBE, opJS, opJNS, opJP, opJNP, opJL, opJNL, opJLE, opJNLE, + +/*80*/ op80_a16, op81_w_a16, op80_a16, op83_w_a16, opTEST_b_a16, opTEST_w_a16, opXCHG_b_a16, opXCHG_w_a16, opMOV_b_r_a16, opMOV_w_r_a16, opMOV_r_b_a16, opMOV_r_w_a16, opMOV_w_seg_a16,opLEA_w_a16, opMOV_seg_w_a16,opPOPW_a16, +/*90*/ opNOP, opXCHG_AX_CX, opXCHG_AX_DX, opXCHG_AX_BX, opXCHG_AX_SP, opXCHG_AX_BP, opXCHG_AX_SI, opXCHG_AX_DI, opCBW, opCWD, opCALL_far_w, opWAIT, opPUSHF, opPOPF_186, opSAHF, opLAHF, +/*a0*/ opMOV_AL_a16, opMOV_AX_a16, opMOV_a16_AL, opMOV_a16_AX, opMOVSB_a16, opMOVSW_a16, opCMPSB_a16, opCMPSW_a16, opTEST_AL, opTEST_AX, opSTOSB_a16, opSTOSW_a16, opLODSB_a16, opLODSW_a16, opSCASB_a16, opSCASW_a16, +/*b0*/ opMOV_AL_imm, opMOV_CL_imm, opMOV_DL_imm, opMOV_BL_imm, opMOV_AH_imm, opMOV_CH_imm, opMOV_DH_imm, opMOV_BH_imm, opMOV_AX_imm, opMOV_CX_imm, opMOV_DX_imm, opMOV_BX_imm, opMOV_SP_imm, opMOV_BP_imm, opMOV_SI_imm, opMOV_DI_imm, + +/*c0*/ opC0_a16, opC1_w_a16, opRET_w_imm, opRET_w, opLES_w_a16, opLDS_w_a16, opMOV_b_imm_a16,opMOV_w_imm_a16,opENTER_w, opLEAVE_w, opRETF_a16_imm, opRETF_a16, opINT3, opINT, opINTO, opIRET_186, +/*d0*/ opD0_a16, opD1_w_a16, opD2_a16, opD3_w_a16, opAAM, opAAD, opSETALC, opXLAT_a16, opESCAPE_d8_a16,opESCAPE_d9_a16,opESCAPE_da_a16,opESCAPE_db_a16,opESCAPE_dc_a16,opESCAPE_dd_a16,opESCAPE_de_a16,opESCAPE_df_a16, +/*e0*/ opLOOPNE_w, opLOOPE_w, opLOOP_w, opJCXZ, opIN_AL_imm, opIN_AX_imm, opOUT_AL_imm, opOUT_AX_imm, opCALL_r16, opJMP_r16, opJMP_far_a16, opJMP_r8, opIN_AL_DX, opIN_AX_DX, opOUT_AL_DX, opOUT_AX_DX, +/*f0*/ opLOCK, opLOCK, opREPNE, opREPE, opHLT, opCMC, opF6_a16, opF7_w_a16, opCLC, opSTC, opCLI, opSTI, opCLD, opSTD, opINCDEC_b_a16, opFF_w_a16, + + /*16-bit data, 32-bit addr*/ +/* 00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f*/ +/*00*/ opADD_b_rmw_a16,opADD_w_rmw_a16,opADD_b_rm_a16, opADD_w_rm_a16, opADD_AL_imm, opADD_AX_imm, opPUSH_ES_w, opPOP_ES_w, opOR_b_rmw_a16, opOR_w_rmw_a16, opOR_b_rm_a16, opOR_w_rm_a16, opOR_AL_imm, opOR_AX_imm, opPUSH_CS_w, op0F_w_a16, +/*10*/ opADC_b_rmw_a16,opADC_w_rmw_a16,opADC_b_rm_a16, opADC_w_rm_a16, opADC_AL_imm, opADC_AX_imm, opPUSH_SS_w, opPOP_SS_w, opSBB_b_rmw_a16,opSBB_w_rmw_a16,opSBB_b_rm_a16, opSBB_w_rm_a16, opSBB_AL_imm, opSBB_AX_imm, opPUSH_DS_w, opPOP_DS_w, +/*20*/ opAND_b_rmw_a16,opAND_w_rmw_a16,opAND_b_rm_a16, opAND_w_rm_a16, opAND_AL_imm, opAND_AX_imm, opES_w_a16, opDAA, opSUB_b_rmw_a16,opSUB_w_rmw_a16,opSUB_b_rm_a16, opSUB_w_rm_a16, opSUB_AL_imm, opSUB_AX_imm, opCS_w_a16, opDAS, +/*30*/ opXOR_b_rmw_a16,opXOR_w_rmw_a16,opXOR_b_rm_a16, opXOR_w_rm_a16, opXOR_AL_imm, opXOR_AX_imm, opSS_w_a16, opAAA, opCMP_b_rmw_a16,opCMP_w_rmw_a16,opCMP_b_rm_a16, opCMP_w_rm_a16, opCMP_AL_imm, opCMP_AX_imm, opDS_w_a16, opAAS, + +/*40*/ opINC_AX, opINC_CX, opINC_DX, opINC_BX, opINC_SP, opINC_BP, opINC_SI, opINC_DI, opDEC_AX, opDEC_CX, opDEC_DX, opDEC_BX, opDEC_SP, opDEC_BP, opDEC_SI, opDEC_DI, +/*50*/ opPUSH_AX, opPUSH_CX, opPUSH_DX, opPUSH_BX, opPUSH_SP, opPUSH_BP, opPUSH_SI, opPUSH_DI, opPOP_AX, opPOP_CX, opPOP_DX, opPOP_BX, opPOP_SP, opPOP_BP, opPOP_SI, opPOP_DI, +/*60*/ opPUSHA_w, opPOPA_w, opBOUND_w_a16, opARPL_a16, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, opPUSH_imm_w, opIMUL_w_iw_a16,opPUSH_imm_bw, opIMUL_w_ib_a16,opINSB_a16, opINSW_a16, opOUTSB_a16, opOUTSW_a16, +/*70*/ opJO, opJNO, opJB, opJNB, opJE, opJNE, opJBE, opJNBE, opJS, opJNS, opJP, opJNP, opJL, opJNL, opJLE, opJNLE, + +/*80*/ op80_a16, op81_w_a16, op80_a16, op83_w_a16, opTEST_b_a16, opTEST_w_a16, opXCHG_b_a16, opXCHG_w_a16, opMOV_b_r_a16, opMOV_w_r_a16, opMOV_r_b_a16, opMOV_r_w_a16, opMOV_w_seg_a16,opLEA_w_a16, opMOV_seg_w_a16,opPOPW_a16, +/*90*/ opNOP, opXCHG_AX_CX, opXCHG_AX_DX, opXCHG_AX_BX, opXCHG_AX_SP, opXCHG_AX_BP, opXCHG_AX_SI, opXCHG_AX_DI, opCBW, opCWD, opCALL_far_w, opWAIT, opPUSHF, opPOPF_186, opSAHF, opLAHF, +/*a0*/ opMOV_AL_a16, opMOV_AX_a16, opMOV_a16_AL, opMOV_a16_AX, opMOVSB_a16, opMOVSW_a16, opCMPSB_a16, opCMPSW_a16, opTEST_AL, opTEST_AX, opSTOSB_a16, opSTOSW_a16, opLODSB_a16, opLODSW_a16, opSCASB_a16, opSCASW_a16, +/*b0*/ opMOV_AL_imm, opMOV_CL_imm, opMOV_DL_imm, opMOV_BL_imm, opMOV_AH_imm, opMOV_CH_imm, opMOV_DH_imm, opMOV_BH_imm, opMOV_AX_imm, opMOV_CX_imm, opMOV_DX_imm, opMOV_BX_imm, opMOV_SP_imm, opMOV_BP_imm, opMOV_SI_imm, opMOV_DI_imm, + +/*c0*/ opC0_a16, opC1_w_a16, opRET_w_imm, opRET_w, opLES_w_a16, opLDS_w_a16, opMOV_b_imm_a16,opMOV_w_imm_a16,opENTER_w, opLEAVE_w, opRETF_a16_imm, opRETF_a16, opINT3, opINT, opINTO, opIRET_186, +/*d0*/ opD0_a16, opD1_w_a16, opD2_a16, opD3_w_a16, opAAM, opAAD, opSETALC, opXLAT_a16, opESCAPE_d8_a16,opESCAPE_d9_a16,opESCAPE_da_a16,opESCAPE_db_a16,opESCAPE_dc_a16,opESCAPE_dd_a16,opESCAPE_de_a16,opESCAPE_df_a16, +/*e0*/ opLOOPNE_w, opLOOPE_w, opLOOP_w, opJCXZ, opIN_AL_imm, opIN_AX_imm, opOUT_AL_imm, opOUT_AX_imm, opCALL_r16, opJMP_r16, opJMP_far_a16, opJMP_r8, opIN_AL_DX, opIN_AX_DX, opOUT_AL_DX, opOUT_AX_DX, +/*f0*/ opLOCK, opLOCK, opREPNE, opREPE, opHLT, opCMC, opF6_a16, opF7_w_a16, opCLC, opSTC, opCLI, opSTI, opCLD, opSTD, opINCDEC_b_a16, opFF_w_a16, + + /*32-bit data, 32-bit addr*/ +/* 00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f*/ +/*00*/ opADD_b_rmw_a16,opADD_w_rmw_a16,opADD_b_rm_a16, opADD_w_rm_a16, opADD_AL_imm, opADD_AX_imm, opPUSH_ES_w, opPOP_ES_w, opOR_b_rmw_a16, opOR_w_rmw_a16, opOR_b_rm_a16, opOR_w_rm_a16, opOR_AL_imm, opOR_AX_imm, opPUSH_CS_w, op0F_w_a16, +/*10*/ opADC_b_rmw_a16,opADC_w_rmw_a16,opADC_b_rm_a16, opADC_w_rm_a16, opADC_AL_imm, opADC_AX_imm, opPUSH_SS_w, opPOP_SS_w, opSBB_b_rmw_a16,opSBB_w_rmw_a16,opSBB_b_rm_a16, opSBB_w_rm_a16, opSBB_AL_imm, opSBB_AX_imm, opPUSH_DS_w, opPOP_DS_w, +/*20*/ opAND_b_rmw_a16,opAND_w_rmw_a16,opAND_b_rm_a16, opAND_w_rm_a16, opAND_AL_imm, opAND_AX_imm, opES_w_a16, opDAA, opSUB_b_rmw_a16,opSUB_w_rmw_a16,opSUB_b_rm_a16, opSUB_w_rm_a16, opSUB_AL_imm, opSUB_AX_imm, opCS_w_a16, opDAS, +/*30*/ opXOR_b_rmw_a16,opXOR_w_rmw_a16,opXOR_b_rm_a16, opXOR_w_rm_a16, opXOR_AL_imm, opXOR_AX_imm, opSS_w_a16, opAAA, opCMP_b_rmw_a16,opCMP_w_rmw_a16,opCMP_b_rm_a16, opCMP_w_rm_a16, opCMP_AL_imm, opCMP_AX_imm, opDS_w_a16, opAAS, + +/*40*/ opINC_AX, opINC_CX, opINC_DX, opINC_BX, opINC_SP, opINC_BP, opINC_SI, opINC_DI, opDEC_AX, opDEC_CX, opDEC_DX, opDEC_BX, opDEC_SP, opDEC_BP, opDEC_SI, opDEC_DI, +/*50*/ opPUSH_AX, opPUSH_CX, opPUSH_DX, opPUSH_BX, opPUSH_SP, opPUSH_BP, opPUSH_SI, opPUSH_DI, opPOP_AX, opPOP_CX, opPOP_DX, opPOP_BX, opPOP_SP, opPOP_BP, opPOP_SI, opPOP_DI, +/*60*/ opPUSHA_w, opPOPA_w, opBOUND_w_a16, opARPL_a16, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, opPUSH_imm_w, opIMUL_w_iw_a16,opPUSH_imm_bw, opIMUL_w_ib_a16,opINSB_a16, opINSW_a16, opOUTSB_a16, opOUTSW_a16, +/*70*/ opJO, opJNO, opJB, opJNB, opJE, opJNE, opJBE, opJNBE, opJS, opJNS, opJP, opJNP, opJL, opJNL, opJLE, opJNLE, + +/*80*/ op80_a16, op81_w_a16, op80_a16, op83_w_a16, opTEST_b_a16, opTEST_w_a16, opXCHG_b_a16, opXCHG_w_a16, opMOV_b_r_a16, opMOV_w_r_a16, opMOV_r_b_a16, opMOV_r_w_a16, opMOV_w_seg_a16,opLEA_w_a16, opMOV_seg_w_a16,opPOPW_a16, +/*90*/ opNOP, opXCHG_AX_CX, opXCHG_AX_DX, opXCHG_AX_BX, opXCHG_AX_SP, opXCHG_AX_BP, opXCHG_AX_SI, opXCHG_AX_DI, opCBW, opCWD, opCALL_far_w, opWAIT, opPUSHF, opPOPF_186, opSAHF, opLAHF, +/*a0*/ opMOV_AL_a16, opMOV_AX_a16, opMOV_a16_AL, opMOV_a16_AX, opMOVSB_a16, opMOVSW_a16, opCMPSB_a16, opCMPSW_a16, opTEST_AL, opTEST_AX, opSTOSB_a16, opSTOSW_a16, opLODSB_a16, opLODSW_a16, opSCASB_a16, opSCASW_a16, +/*b0*/ opMOV_AL_imm, opMOV_CL_imm, opMOV_DL_imm, opMOV_BL_imm, opMOV_AH_imm, opMOV_CH_imm, opMOV_DH_imm, opMOV_BH_imm, opMOV_AX_imm, opMOV_CX_imm, opMOV_DX_imm, opMOV_BX_imm, opMOV_SP_imm, opMOV_BP_imm, opMOV_SI_imm, opMOV_DI_imm, + +/*c0*/ opC0_a16, opC1_w_a16, opRET_w_imm, opRET_w, opLES_w_a16, opLDS_w_a16, opMOV_b_imm_a16,opMOV_w_imm_a16,opENTER_w, opLEAVE_w, opRETF_a16_imm, opRETF_a16, opINT3, opINT, opINTO, opIRET_186, +/*d0*/ opD0_a16, opD1_w_a16, opD2_a16, opD3_w_a16, opAAM, opAAD, opSETALC, opXLAT_a16, opESCAPE_d8_a16,opESCAPE_d9_a16,opESCAPE_da_a16,opESCAPE_db_a16,opESCAPE_dc_a16,opESCAPE_dd_a16,opESCAPE_de_a16,opESCAPE_df_a16, +/*e0*/ opLOOPNE_w, opLOOPE_w, opLOOP_w, opJCXZ, opIN_AL_imm, opIN_AX_imm, opOUT_AL_imm, opOUT_AX_imm, opCALL_r16, opJMP_r16, opJMP_far_a16, opJMP_r8, opIN_AL_DX, opIN_AX_DX, opOUT_AL_DX, opOUT_AX_DX, +/*f0*/ opLOCK, opLOCK, opREPNE, opREPE, opHLT, opCMC, opF6_a16, opF7_w_a16, opCLC, opSTC, opCLI, opSTI, opCLD, opSTD, opINCDEC_b_a16, opFF_w_a16, + // clang-format on +}; + +const OpFn OP_TABLE(286)[1024] = { + // clang-format off + /*16-bit data, 16-bit addr*/ +/* 00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f*/ +/*00*/ opADD_b_rmw_a16,opADD_w_rmw_a16,opADD_b_rm_a16, opADD_w_rm_a16, opADD_AL_imm, opADD_AX_imm, opPUSH_ES_w, opPOP_ES_w, opOR_b_rmw_a16, opOR_w_rmw_a16, opOR_b_rm_a16, opOR_w_rm_a16, opOR_AL_imm, opOR_AX_imm, opPUSH_CS_w, op0F_w_a16, +/*10*/ opADC_b_rmw_a16,opADC_w_rmw_a16,opADC_b_rm_a16, opADC_w_rm_a16, opADC_AL_imm, opADC_AX_imm, opPUSH_SS_w, opPOP_SS_w, opSBB_b_rmw_a16,opSBB_w_rmw_a16,opSBB_b_rm_a16, opSBB_w_rm_a16, opSBB_AL_imm, opSBB_AX_imm, opPUSH_DS_w, opPOP_DS_w, +/*20*/ opAND_b_rmw_a16,opAND_w_rmw_a16,opAND_b_rm_a16, opAND_w_rm_a16, opAND_AL_imm, opAND_AX_imm, opES_w_a16, opDAA, opSUB_b_rmw_a16,opSUB_w_rmw_a16,opSUB_b_rm_a16, opSUB_w_rm_a16, opSUB_AL_imm, opSUB_AX_imm, opCS_w_a16, opDAS, +/*30*/ opXOR_b_rmw_a16,opXOR_w_rmw_a16,opXOR_b_rm_a16, opXOR_w_rm_a16, opXOR_AL_imm, opXOR_AX_imm, opSS_w_a16, opAAA, opCMP_b_rmw_a16,opCMP_w_rmw_a16,opCMP_b_rm_a16, opCMP_w_rm_a16, opCMP_AL_imm, opCMP_AX_imm, opDS_w_a16, opAAS, + +/*40*/ opINC_AX, opINC_CX, opINC_DX, opINC_BX, opINC_SP, opINC_BP, opINC_SI, opINC_DI, opDEC_AX, opDEC_CX, opDEC_DX, opDEC_BX, opDEC_SP, opDEC_BP, opDEC_SI, opDEC_DI, +/*50*/ opPUSH_AX, opPUSH_CX, opPUSH_DX, opPUSH_BX, opPUSH_SP, opPUSH_BP, opPUSH_SI, opPUSH_DI, opPOP_AX, opPOP_CX, opPOP_DX, opPOP_BX, opPOP_SP, opPOP_BP, opPOP_SI, opPOP_DI, /*60*/ opPUSHA_w, opPOPA_w, opBOUND_w_a16, opARPL_a16, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, opPUSH_imm_w, opIMUL_w_iw_a16,opPUSH_imm_bw, opIMUL_w_ib_a16,opINSB_a16, opINSW_a16, opOUTSB_a16, opOUTSW_a16, /*70*/ opJO, opJNO, opJB, opJNB, opJE, opJNE, opJBE, opJNBE, opJS, opJNS, opJP, opJNP, opJL, opJNL, opJLE, opJNLE, @@ -1937,14 +2222,14 @@ const OpFn OP_TABLE(286)[1024] = /*f0*/ opLOCK, opLOCK, opREPNE, opREPE, opHLT, opCMC, opF6_a16, opF7_w_a16, opCLC, opSTC, opCLI, opSTI, opCLD, opSTD, opINCDEC_b_a16, opFF_w_a16, /*32-bit data, 16-bit addr*/ -/* 00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f*/ +/* 00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f*/ /*00*/ opADD_b_rmw_a16,opADD_w_rmw_a16,opADD_b_rm_a16, opADD_w_rm_a16, opADD_AL_imm, opADD_AX_imm, opPUSH_ES_w, opPOP_ES_w, opOR_b_rmw_a16, opOR_w_rmw_a16, opOR_b_rm_a16, opOR_w_rm_a16, opOR_AL_imm, opOR_AX_imm, opPUSH_CS_w, op0F_w_a16, /*10*/ opADC_b_rmw_a16,opADC_w_rmw_a16,opADC_b_rm_a16, opADC_w_rm_a16, opADC_AL_imm, opADC_AX_imm, opPUSH_SS_w, opPOP_SS_w, opSBB_b_rmw_a16,opSBB_w_rmw_a16,opSBB_b_rm_a16, opSBB_w_rm_a16, opSBB_AL_imm, opSBB_AX_imm, opPUSH_DS_w, opPOP_DS_w, /*20*/ opAND_b_rmw_a16,opAND_w_rmw_a16,opAND_b_rm_a16, opAND_w_rm_a16, opAND_AL_imm, opAND_AX_imm, opES_w_a16, opDAA, opSUB_b_rmw_a16,opSUB_w_rmw_a16,opSUB_b_rm_a16, opSUB_w_rm_a16, opSUB_AL_imm, opSUB_AX_imm, opCS_w_a16, opDAS, /*30*/ opXOR_b_rmw_a16,opXOR_w_rmw_a16,opXOR_b_rm_a16, opXOR_w_rm_a16, opXOR_AL_imm, opXOR_AX_imm, opSS_w_a16, opAAA, opCMP_b_rmw_a16,opCMP_w_rmw_a16,opCMP_b_rm_a16, opCMP_w_rm_a16, opCMP_AL_imm, opCMP_AX_imm, opDS_w_a16, opAAS, -/*40*/ opINC_AX, opINC_CX, opINC_DX, opINC_BX, opINC_SP, opINC_BP, opINC_SI, opINC_DI, opDEC_AX, opDEC_CX, opDEC_DX, opDEC_BX, opDEC_SP, opDEC_BP, opDEC_SI, opDEC_DI, -/*50*/ opPUSH_AX, opPUSH_CX, opPUSH_DX, opPUSH_BX, opPUSH_SP, opPUSH_BP, opPUSH_SI, opPUSH_DI, opPOP_AX, opPOP_CX, opPOP_DX, opPOP_BX, opPOP_SP, opPOP_BP, opPOP_SI, opPOP_DI, +/*40*/ opINC_AX, opINC_CX, opINC_DX, opINC_BX, opINC_SP, opINC_BP, opINC_SI, opINC_DI, opDEC_AX, opDEC_CX, opDEC_DX, opDEC_BX, opDEC_SP, opDEC_BP, opDEC_SI, opDEC_DI, +/*50*/ opPUSH_AX, opPUSH_CX, opPUSH_DX, opPUSH_BX, opPUSH_SP, opPUSH_BP, opPUSH_SI, opPUSH_DI, opPOP_AX, opPOP_CX, opPOP_DX, opPOP_BX, opPOP_SP, opPOP_BP, opPOP_SI, opPOP_DI, /*60*/ opPUSHA_w, opPOPA_w, opBOUND_w_a16, opARPL_a16, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, opPUSH_imm_w, opIMUL_w_iw_a16,opPUSH_imm_bw, opIMUL_w_ib_a16,opINSB_a16, opINSW_a16, opOUTSB_a16, opOUTSW_a16, /*70*/ opJO, opJNO, opJB, opJNB, opJE, opJNE, opJBE, opJNBE, opJS, opJNS, opJP, opJNP, opJL, opJNL, opJLE, opJNLE, @@ -1959,14 +2244,14 @@ const OpFn OP_TABLE(286)[1024] = /*f0*/ opLOCK, opLOCK, opREPNE, opREPE, opHLT, opCMC, opF6_a16, opF7_w_a16, opCLC, opSTC, opCLI, opSTI, opCLD, opSTD, opINCDEC_b_a16, opFF_w_a16, /*16-bit data, 32-bit addr*/ -/* 00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f*/ +/* 00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f*/ /*00*/ opADD_b_rmw_a16,opADD_w_rmw_a16,opADD_b_rm_a16, opADD_w_rm_a16, opADD_AL_imm, opADD_AX_imm, opPUSH_ES_w, opPOP_ES_w, opOR_b_rmw_a16, opOR_w_rmw_a16, opOR_b_rm_a16, opOR_w_rm_a16, opOR_AL_imm, opOR_AX_imm, opPUSH_CS_w, op0F_w_a16, /*10*/ opADC_b_rmw_a16,opADC_w_rmw_a16,opADC_b_rm_a16, opADC_w_rm_a16, opADC_AL_imm, opADC_AX_imm, opPUSH_SS_w, opPOP_SS_w, opSBB_b_rmw_a16,opSBB_w_rmw_a16,opSBB_b_rm_a16, opSBB_w_rm_a16, opSBB_AL_imm, opSBB_AX_imm, opPUSH_DS_w, opPOP_DS_w, /*20*/ opAND_b_rmw_a16,opAND_w_rmw_a16,opAND_b_rm_a16, opAND_w_rm_a16, opAND_AL_imm, opAND_AX_imm, opES_w_a16, opDAA, opSUB_b_rmw_a16,opSUB_w_rmw_a16,opSUB_b_rm_a16, opSUB_w_rm_a16, opSUB_AL_imm, opSUB_AX_imm, opCS_w_a16, opDAS, /*30*/ opXOR_b_rmw_a16,opXOR_w_rmw_a16,opXOR_b_rm_a16, opXOR_w_rm_a16, opXOR_AL_imm, opXOR_AX_imm, opSS_w_a16, opAAA, opCMP_b_rmw_a16,opCMP_w_rmw_a16,opCMP_b_rm_a16, opCMP_w_rm_a16, opCMP_AL_imm, opCMP_AX_imm, opDS_w_a16, opAAS, -/*40*/ opINC_AX, opINC_CX, opINC_DX, opINC_BX, opINC_SP, opINC_BP, opINC_SI, opINC_DI, opDEC_AX, opDEC_CX, opDEC_DX, opDEC_BX, opDEC_SP, opDEC_BP, opDEC_SI, opDEC_DI, -/*50*/ opPUSH_AX, opPUSH_CX, opPUSH_DX, opPUSH_BX, opPUSH_SP, opPUSH_BP, opPUSH_SI, opPUSH_DI, opPOP_AX, opPOP_CX, opPOP_DX, opPOP_BX, opPOP_SP, opPOP_BP, opPOP_SI, opPOP_DI, +/*40*/ opINC_AX, opINC_CX, opINC_DX, opINC_BX, opINC_SP, opINC_BP, opINC_SI, opINC_DI, opDEC_AX, opDEC_CX, opDEC_DX, opDEC_BX, opDEC_SP, opDEC_BP, opDEC_SI, opDEC_DI, +/*50*/ opPUSH_AX, opPUSH_CX, opPUSH_DX, opPUSH_BX, opPUSH_SP, opPUSH_BP, opPUSH_SI, opPUSH_DI, opPOP_AX, opPOP_CX, opPOP_DX, opPOP_BX, opPOP_SP, opPOP_BP, opPOP_SI, opPOP_DI, /*60*/ opPUSHA_w, opPOPA_w, opBOUND_w_a16, opARPL_a16, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, opPUSH_imm_w, opIMUL_w_iw_a16,opPUSH_imm_bw, opIMUL_w_ib_a16,opINSB_a16, opINSW_a16, opOUTSB_a16, opOUTSW_a16, /*70*/ opJO, opJNO, opJB, opJNB, opJE, opJNE, opJBE, opJNBE, opJS, opJNS, opJP, opJNP, opJL, opJNL, opJLE, opJNLE, @@ -1981,14 +2266,14 @@ const OpFn OP_TABLE(286)[1024] = /*f0*/ opLOCK, opLOCK, opREPNE, opREPE, opHLT, opCMC, opF6_a16, opF7_w_a16, opCLC, opSTC, opCLI, opSTI, opCLD, opSTD, opINCDEC_b_a16, opFF_w_a16, /*32-bit data, 32-bit addr*/ -/* 00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f*/ +/* 00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f*/ /*00*/ opADD_b_rmw_a16,opADD_w_rmw_a16,opADD_b_rm_a16, opADD_w_rm_a16, opADD_AL_imm, opADD_AX_imm, opPUSH_ES_w, opPOP_ES_w, opOR_b_rmw_a16, opOR_w_rmw_a16, opOR_b_rm_a16, opOR_w_rm_a16, opOR_AL_imm, opOR_AX_imm, opPUSH_CS_w, op0F_w_a16, /*10*/ opADC_b_rmw_a16,opADC_w_rmw_a16,opADC_b_rm_a16, opADC_w_rm_a16, opADC_AL_imm, opADC_AX_imm, opPUSH_SS_w, opPOP_SS_w, opSBB_b_rmw_a16,opSBB_w_rmw_a16,opSBB_b_rm_a16, opSBB_w_rm_a16, opSBB_AL_imm, opSBB_AX_imm, opPUSH_DS_w, opPOP_DS_w, /*20*/ opAND_b_rmw_a16,opAND_w_rmw_a16,opAND_b_rm_a16, opAND_w_rm_a16, opAND_AL_imm, opAND_AX_imm, opES_w_a16, opDAA, opSUB_b_rmw_a16,opSUB_w_rmw_a16,opSUB_b_rm_a16, opSUB_w_rm_a16, opSUB_AL_imm, opSUB_AX_imm, opCS_w_a16, opDAS, /*30*/ opXOR_b_rmw_a16,opXOR_w_rmw_a16,opXOR_b_rm_a16, opXOR_w_rm_a16, opXOR_AL_imm, opXOR_AX_imm, opSS_w_a16, opAAA, opCMP_b_rmw_a16,opCMP_w_rmw_a16,opCMP_b_rm_a16, opCMP_w_rm_a16, opCMP_AL_imm, opCMP_AX_imm, opDS_w_a16, opAAS, -/*40*/ opINC_AX, opINC_CX, opINC_DX, opINC_BX, opINC_SP, opINC_BP, opINC_SI, opINC_DI, opDEC_AX, opDEC_CX, opDEC_DX, opDEC_BX, opDEC_SP, opDEC_BP, opDEC_SI, opDEC_DI, -/*50*/ opPUSH_AX, opPUSH_CX, opPUSH_DX, opPUSH_BX, opPUSH_SP, opPUSH_BP, opPUSH_SI, opPUSH_DI, opPOP_AX, opPOP_CX, opPOP_DX, opPOP_BX, opPOP_SP, opPOP_BP, opPOP_SI, opPOP_DI, +/*40*/ opINC_AX, opINC_CX, opINC_DX, opINC_BX, opINC_SP, opINC_BP, opINC_SI, opINC_DI, opDEC_AX, opDEC_CX, opDEC_DX, opDEC_BX, opDEC_SP, opDEC_BP, opDEC_SI, opDEC_DI, +/*50*/ opPUSH_AX, opPUSH_CX, opPUSH_DX, opPUSH_BX, opPUSH_SP, opPUSH_BP, opPUSH_SI, opPUSH_DI, opPOP_AX, opPOP_CX, opPOP_DX, opPOP_BX, opPOP_SP, opPOP_BP, opPOP_SI, opPOP_DI, /*60*/ opPUSHA_w, opPOPA_w, opBOUND_w_a16, opARPL_a16, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, opPUSH_imm_w, opIMUL_w_iw_a16,opPUSH_imm_bw, opIMUL_w_ib_a16,opINSB_a16, opINSW_a16, opOUTSB_a16, opOUTSW_a16, /*70*/ opJO, opJNO, opJB, opJNB, opJE, opJNE, opJBE, opJNBE, opJS, opJNS, opJP, opJNP, opJL, opJNL, opJLE, opJNLE, @@ -2001,19 +2286,20 @@ const OpFn OP_TABLE(286)[1024] = /*d0*/ opD0_a16, opD1_w_a16, opD2_a16, opD3_w_a16, opAAM, opAAD, opSETALC, opXLAT_a16, opESCAPE_d8_a16,opESCAPE_d9_a16,opESCAPE_da_a16,opESCAPE_db_a16,opESCAPE_dc_a16,opESCAPE_dd_a16,opESCAPE_de_a16,opESCAPE_df_a16, /*e0*/ opLOOPNE_w, opLOOPE_w, opLOOP_w, opJCXZ, opIN_AL_imm, opIN_AX_imm, opOUT_AL_imm, opOUT_AX_imm, opCALL_r16, opJMP_r16, opJMP_far_a16, opJMP_r8, opIN_AL_DX, opIN_AX_DX, opOUT_AL_DX, opOUT_AX_DX, /*f0*/ opLOCK, opLOCK, opREPNE, opREPE, opHLT, opCMC, opF6_a16, opF7_w_a16, opCLC, opSTC, opCLI, opSTI, opCLD, opSTD, opINCDEC_b_a16, opFF_w_a16, + // clang-format on }; -const OpFn OP_TABLE(386)[1024] = -{ +const OpFn OP_TABLE(386)[1024] = { + // clang-format off /*16-bit data, 16-bit addr*/ -/* 00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f*/ +/* 00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f*/ /*00*/ opADD_b_rmw_a16,opADD_w_rmw_a16,opADD_b_rm_a16, opADD_w_rm_a16, opADD_AL_imm, opADD_AX_imm, opPUSH_ES_w, opPOP_ES_w, opOR_b_rmw_a16, opOR_w_rmw_a16, opOR_b_rm_a16, opOR_w_rm_a16, opOR_AL_imm, opOR_AX_imm, opPUSH_CS_w, op0F_w_a16, /*10*/ opADC_b_rmw_a16,opADC_w_rmw_a16,opADC_b_rm_a16, opADC_w_rm_a16, opADC_AL_imm, opADC_AX_imm, opPUSH_SS_w, opPOP_SS_w, opSBB_b_rmw_a16,opSBB_w_rmw_a16,opSBB_b_rm_a16, opSBB_w_rm_a16, opSBB_AL_imm, opSBB_AX_imm, opPUSH_DS_w, opPOP_DS_w, /*20*/ opAND_b_rmw_a16,opAND_w_rmw_a16,opAND_b_rm_a16, opAND_w_rm_a16, opAND_AL_imm, opAND_AX_imm, opES_w_a16, opDAA, opSUB_b_rmw_a16,opSUB_w_rmw_a16,opSUB_b_rm_a16, opSUB_w_rm_a16, opSUB_AL_imm, opSUB_AX_imm, opCS_w_a16, opDAS, /*30*/ opXOR_b_rmw_a16,opXOR_w_rmw_a16,opXOR_b_rm_a16, opXOR_w_rm_a16, opXOR_AL_imm, opXOR_AX_imm, opSS_w_a16, opAAA, opCMP_b_rmw_a16,opCMP_w_rmw_a16,opCMP_b_rm_a16, opCMP_w_rm_a16, opCMP_AL_imm, opCMP_AX_imm, opDS_w_a16, opAAS, -/*40*/ opINC_AX, opINC_CX, opINC_DX, opINC_BX, opINC_SP, opINC_BP, opINC_SI, opINC_DI, opDEC_AX, opDEC_CX, opDEC_DX, opDEC_BX, opDEC_SP, opDEC_BP, opDEC_SI, opDEC_DI, -/*50*/ opPUSH_AX, opPUSH_CX, opPUSH_DX, opPUSH_BX, opPUSH_SP, opPUSH_BP, opPUSH_SI, opPUSH_DI, opPOP_AX, opPOP_CX, opPOP_DX, opPOP_BX, opPOP_SP, opPOP_BP, opPOP_SI, opPOP_DI, +/*40*/ opINC_AX, opINC_CX, opINC_DX, opINC_BX, opINC_SP, opINC_BP, opINC_SI, opINC_DI, opDEC_AX, opDEC_CX, opDEC_DX, opDEC_BX, opDEC_SP, opDEC_BP, opDEC_SI, opDEC_DI, +/*50*/ opPUSH_AX, opPUSH_CX, opPUSH_DX, opPUSH_BX, opPUSH_SP, opPUSH_BP, opPUSH_SI, opPUSH_DI, opPOP_AX, opPOP_CX, opPOP_DX, opPOP_BX, opPOP_SP, opPOP_BP, opPOP_SI, opPOP_DI, /*60*/ opPUSHA_w, opPOPA_w, opBOUND_w_a16, opARPL_a16, opFS_w_a16, opGS_w_a16, op_66, op_67, opPUSH_imm_w, opIMUL_w_iw_a16,opPUSH_imm_bw, opIMUL_w_ib_a16,opINSB_a16, opINSW_a16, opOUTSB_a16, opOUTSW_a16, /*70*/ opJO, opJNO, opJB, opJNB, opJE, opJNE, opJBE, opJNBE, opJS, opJNS, opJP, opJNP, opJL, opJNL, opJLE, opJNLE, @@ -2035,7 +2321,7 @@ const OpFn OP_TABLE(386)[1024] = /*30*/ opXOR_b_rmw_a16,opXOR_l_rmw_a16,opXOR_b_rm_a16, opXOR_l_rm_a16, opXOR_AL_imm, opXOR_EAX_imm, opSS_l_a16, opAAA, opCMP_b_rmw_a16,opCMP_l_rmw_a16,opCMP_b_rm_a16, opCMP_l_rm_a16, opCMP_AL_imm, opCMP_EAX_imm, opDS_l_a16, opAAS, /*40*/ opINC_EAX, opINC_ECX, opINC_EDX, opINC_EBX, opINC_ESP, opINC_EBP, opINC_ESI, opINC_EDI, opDEC_EAX, opDEC_ECX, opDEC_EDX, opDEC_EBX, opDEC_ESP, opDEC_EBP, opDEC_ESI, opDEC_EDI, -/*50*/ opPUSH_EAX, opPUSH_ECX, opPUSH_EDX, opPUSH_EBX, opPUSH_ESP, opPUSH_EBP, opPUSH_ESI, opPUSH_EDI, opPOP_EAX, opPOP_ECX, opPOP_EDX, opPOP_EBX, opPOP_ESP, opPOP_EBP, opPOP_ESI, opPOP_EDI, +/*50*/ opPUSH_EAX, opPUSH_ECX, opPUSH_EDX, opPUSH_EBX, opPUSH_ESP, opPUSH_EBP, opPUSH_ESI, opPUSH_EDI, opPOP_EAX, opPOP_ECX, opPOP_EDX, opPOP_EBX, opPOP_ESP, opPOP_EBP, opPOP_ESI, opPOP_EDI, /*60*/ opPUSHA_l, opPOPA_l, opBOUND_l_a16, opARPL_a16, opFS_l_a16, opGS_l_a16, op_66, op_67, opPUSH_imm_l, opIMUL_l_il_a16,opPUSH_imm_bl, opIMUL_l_ib_a16,opINSB_a16, opINSL_a16, opOUTSB_a16, opOUTSL_a16, /*70*/ opJO, opJNO, opJB, opJNB, opJE, opJNE, opJBE, opJNBE, opJS, opJNS, opJP, opJNP, opJL, opJNL, opJLE, opJNLE, @@ -2056,8 +2342,8 @@ const OpFn OP_TABLE(386)[1024] = /*20*/ opAND_b_rmw_a32,opAND_w_rmw_a32,opAND_b_rm_a32, opAND_w_rm_a32, opAND_AL_imm, opAND_AX_imm, opES_w_a32, opDAA, opSUB_b_rmw_a32,opSUB_w_rmw_a32,opSUB_b_rm_a32, opSUB_w_rm_a32, opSUB_AL_imm, opSUB_AX_imm, opCS_w_a32, opDAS, /*30*/ opXOR_b_rmw_a32,opXOR_w_rmw_a32,opXOR_b_rm_a32, opXOR_w_rm_a32, opXOR_AL_imm, opXOR_AX_imm, opSS_w_a32, opAAA, opCMP_b_rmw_a32,opCMP_w_rmw_a32,opCMP_b_rm_a32, opCMP_w_rm_a32, opCMP_AL_imm, opCMP_AX_imm, opDS_w_a32, opAAS, -/*40*/ opINC_AX, opINC_CX, opINC_DX, opINC_BX, opINC_SP, opINC_BP, opINC_SI, opINC_DI, opDEC_AX, opDEC_CX, opDEC_DX, opDEC_BX, opDEC_SP, opDEC_BP, opDEC_SI, opDEC_DI, -/*50*/ opPUSH_AX, opPUSH_CX, opPUSH_DX, opPUSH_BX, opPUSH_SP, opPUSH_BP, opPUSH_SI, opPUSH_DI, opPOP_AX, opPOP_CX, opPOP_DX, opPOP_BX, opPOP_SP, opPOP_BP, opPOP_SI, opPOP_DI, +/*40*/ opINC_AX, opINC_CX, opINC_DX, opINC_BX, opINC_SP, opINC_BP, opINC_SI, opINC_DI, opDEC_AX, opDEC_CX, opDEC_DX, opDEC_BX, opDEC_SP, opDEC_BP, opDEC_SI, opDEC_DI, +/*50*/ opPUSH_AX, opPUSH_CX, opPUSH_DX, opPUSH_BX, opPUSH_SP, opPUSH_BP, opPUSH_SI, opPUSH_DI, opPOP_AX, opPOP_CX, opPOP_DX, opPOP_BX, opPOP_SP, opPOP_BP, opPOP_SI, opPOP_DI, /*60*/ opPUSHA_w, opPOPA_w, opBOUND_w_a32, opARPL_a32, opFS_w_a32, opGS_w_a32, op_66, op_67, opPUSH_imm_w, opIMUL_w_iw_a32,opPUSH_imm_bw, opIMUL_w_ib_a32,opINSB_a32, opINSW_a32, opOUTSB_a32, opOUTSW_a32, /*70*/ opJO, opJNO, opJB, opJNB, opJE, opJNE, opJBE, opJNBE, opJS, opJNS, opJP, opJNP, opJL, opJNL, opJLE, opJNLE, @@ -2079,7 +2365,7 @@ const OpFn OP_TABLE(386)[1024] = /*30*/ opXOR_b_rmw_a32,opXOR_l_rmw_a32,opXOR_b_rm_a32, opXOR_l_rm_a32, opXOR_AL_imm, opXOR_EAX_imm, opSS_l_a32, opAAA, opCMP_b_rmw_a32,opCMP_l_rmw_a32,opCMP_b_rm_a32, opCMP_l_rm_a32, opCMP_AL_imm, opCMP_EAX_imm, opDS_l_a32, opAAS, /*40*/ opINC_EAX, opINC_ECX, opINC_EDX, opINC_EBX, opINC_ESP, opINC_EBP, opINC_ESI, opINC_EDI, opDEC_EAX, opDEC_ECX, opDEC_EDX, opDEC_EBX, opDEC_ESP, opDEC_EBP, opDEC_ESI, opDEC_EDI, -/*50*/ opPUSH_EAX, opPUSH_ECX, opPUSH_EDX, opPUSH_EBX, opPUSH_ESP, opPUSH_EBP, opPUSH_ESI, opPUSH_EDI, opPOP_EAX, opPOP_ECX, opPOP_EDX, opPOP_EBX, opPOP_ESP, opPOP_EBP, opPOP_ESI, opPOP_EDI, +/*50*/ opPUSH_EAX, opPUSH_ECX, opPUSH_EDX, opPUSH_EBX, opPUSH_ESP, opPUSH_EBP, opPUSH_ESI, opPUSH_EDI, opPOP_EAX, opPOP_ECX, opPOP_EDX, opPOP_EBX, opPOP_ESP, opPOP_EBP, opPOP_ESI, opPOP_EDI, /*60*/ opPUSHA_l, opPOPA_l, opBOUND_l_a32, opARPL_a32, opFS_l_a32, opGS_l_a32, op_66, op_67, opPUSH_imm_l, opIMUL_l_il_a32,opPUSH_imm_bl, opIMUL_l_ib_a32,opINSB_a32, opINSL_a32, opOUTSB_a32, opOUTSL_a32, /*70*/ opJO, opJNO, opJB, opJNB, opJE, opJNE, opJBE, opJNBE, opJS, opJNS, opJP, opJNP, opJL, opJNL, opJLE, opJNLE, @@ -2092,12 +2378,13 @@ const OpFn OP_TABLE(386)[1024] = /*d0*/ opD0_a32, opD1_l_a32, opD2_a32, opD3_l_a32, opAAM, opAAD, opSETALC, opXLAT_a32, opESCAPE_d8_a32,opESCAPE_d9_a32,opESCAPE_da_a32,opESCAPE_db_a32,opESCAPE_dc_a32,opESCAPE_dd_a32,opESCAPE_de_a32,opESCAPE_df_a32, /*e0*/ opLOOPNE_l, opLOOPE_l, opLOOP_l, opJECXZ, opIN_AL_imm, opIN_EAX_imm, opOUT_AL_imm, opOUT_EAX_imm, opCALL_r32, opJMP_r32, opJMP_far_a32, opJMP_r8, opIN_AL_DX, opIN_EAX_DX, opOUT_AL_DX, opOUT_EAX_DX, /*f0*/ opLOCK, opINT1, opREPNE, opREPE, opHLT, opCMC, opF6_a32, opF7_l_a32, opCLC, opSTC, opCLI, opSTI, opCLD, opSTD, opINCDEC_b_a32, opFF_l_a32, -}; + // clang-format on +}; -const OpFn OP_TABLE(REPE)[1024] = -{ +const OpFn OP_TABLE(REPE)[1024] = { + // clang-format off /*16-bit data, 16-bit addr*/ -/* 00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f*/ +/* 00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f*/ /*00*/ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /*10*/ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /*20*/ 0, 0, 0, 0, 0, 0, opES_REPE_w_a16,0, 0, 0, 0, 0, 0, 0, opCS_REPE_w_a16,0, @@ -2119,7 +2406,7 @@ const OpFn OP_TABLE(REPE)[1024] = /*f0*/ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /*32-bit data, 16-bit addr*/ -/* 00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f*/ +/* 00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f*/ /*00*/ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /*10*/ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /*20*/ 0, 0, 0, 0, 0, 0, opES_REPE_l_a16,0, 0, 0, 0, 0, 0, 0, opCS_REPE_l_a16,0, @@ -2141,7 +2428,7 @@ const OpFn OP_TABLE(REPE)[1024] = /*f0*/ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /*16-bit data, 32-bit addr*/ -/* 00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f*/ +/* 00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f*/ /*00*/ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /*10*/ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /*20*/ 0, 0, 0, 0, 0, 0, opES_REPE_w_a32,0, 0, 0, 0, 0, 0, 0, opCS_REPE_w_a32,0, @@ -2163,7 +2450,7 @@ const OpFn OP_TABLE(REPE)[1024] = /*f0*/ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /*32-bit data, 32-bit addr*/ -/* 00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f*/ +/* 00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f*/ /*00*/ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /*10*/ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /*20*/ 0, 0, 0, 0, 0, 0, opES_REPE_l_a32,0, 0, 0, 0, 0, 0, 0, opCS_REPE_l_a32,0, @@ -2183,12 +2470,13 @@ const OpFn OP_TABLE(REPE)[1024] = /*d0*/ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /*e0*/ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /*f0*/ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + // clang-format on }; -const OpFn OP_TABLE(REPNE)[1024] = -{ +const OpFn OP_TABLE(REPNE)[1024] = { + // clang-format off /*16-bit data, 16-bit addr*/ -/* 00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f*/ +/* 00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f*/ /*00*/ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /*10*/ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /*20*/ 0, 0, 0, 0, 0, 0, opES_REPNE_w_a16,0, 0, 0, 0, 0, 0, 0, opCS_REPNE_w_a16,0, @@ -2210,7 +2498,7 @@ const OpFn OP_TABLE(REPNE)[1024] = /*f0*/ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /*32-bit data, 16-bit addr*/ -/* 00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f*/ +/* 00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f*/ /*00*/ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /*10*/ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /*20*/ 0, 0, 0, 0, 0, 0, opES_REPNE_l_a16,0, 0, 0, 0, 0, 0, 0, opCS_REPNE_l_a16,0, @@ -2232,7 +2520,7 @@ const OpFn OP_TABLE(REPNE)[1024] = /*f0*/ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /*16-bit data, 32-bit addr*/ -/* 00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f*/ +/* 00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f*/ /*00*/ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /*10*/ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /*20*/ 0, 0, 0, 0, 0, 0, opES_REPNE_w_a32,0, 0, 0, 0, 0, 0, 0, opCS_REPNE_w_a32,0, @@ -2254,7 +2542,7 @@ const OpFn OP_TABLE(REPNE)[1024] = /*f0*/ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /*32-bit data, 32-bit addr*/ -/* 00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f*/ +/* 00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f*/ /*00*/ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /*10*/ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /*20*/ 0, 0, 0, 0, 0, 0, opES_REPNE_l_a32,0, 0, 0, 0, 0, 0, 0, opCS_REPNE_l_a32,0, @@ -2274,4 +2562,5 @@ const OpFn OP_TABLE(REPNE)[1024] = /*d0*/ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /*e0*/ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /*f0*/ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + // clang-format on }; diff --git a/src/cpu/8080.c b/src/cpu/8080.c new file mode 100644 index 000000000..7a7e7b96c --- /dev/null +++ b/src/cpu/8080.c @@ -0,0 +1,290 @@ +/* + * 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. + * + * 8080 CPU emulation. + * + * Authors: Cacodemon345 + * + * Copyright 2022 Cacodemon345 + */ + +#include +#include +#include "cpu.h" +#include <86box/timer.h> +#include <86box/i8080.h> +#include <86box/mem.h> +#include <86box/plat_unused.h> + +static int completed = 1; +static int in_rep = 0; +static int repeating = 0; +static int rep_c_flag = 0; +static int oldc; +static int cycdiff; +#ifdef UNUSED_8080_VARS +static int prefetching = 1; +static int refresh = 0; +static int clear_lock = 0; + +static uint32_t cpu_src = 0; +static uint32_t cpu_dest = 0; +static uint32_t cpu_data = 0; +#endif + +static void +clock_start(void) +{ + cycdiff = cycles; +} + +static void +clock_end(void) +{ + int diff = cycdiff - cycles; + + /* On 808x systems, clock speed is usually crystal frequency divided by an integer. */ + tsc += (uint64_t) diff * (xt_cpu_multi >> 32ULL); /* Shift xt_cpu_multi by 32 bits to the right and then multiply. */ + if (TIMER_VAL_LESS_THAN_VAL(timer_target, (uint32_t) tsc)) + timer_process(); +} + +static void +i8080_wait(int c, int bus) +{ + cycles -= c; + if (bus < 2) { + clock_end(); + clock_start(); + } +} + +#ifdef UNUSED_8080_FUNCS +static uint8_t +readmemb(uint32_t a) +{ + uint8_t ret; + + i8080_wait(4, 1); + ret = read_mem_b(a); + + return ret; +} + +static uint8_t +ins_fetch(i8080 *cpu) +{ + uint8_t ret = cpu->readmembyte(cpu->pmembase + cpu->pc); + + cpu->pc++; + return ret; +} +#endif + +void +transfer_from_808x(i8080 *cpu) +{ + cpu->hl = BX; + cpu->bc = CX; + cpu->de = DX; + cpu->a = AL; + cpu->flags = cpu_state.flags & 0xFF; + cpu->sp = BP; + cpu->pc = cpu_state.pc; + cpu->oldpc = cpu_state.oldpc; + cpu->pmembase = cs; + cpu->dmembase = ds; +} + +void +transfer_to_808x(i8080 *cpu) +{ + BX = cpu->hl; + CX = cpu->bc; + DX = cpu->de; + AL = cpu->a; + cpu_state.flags &= 0xFF00; + cpu_state.flags |= cpu->flags & 0xFF; + BP = cpu->sp; + cpu_state.pc = cpu->pc; +} + +uint8_t +getreg_i8080(i8080 *cpu, uint8_t reg) +{ + uint8_t ret = 0xFF; + switch (reg) { + case 0x0: + ret = cpu->b; + break; + case 0x1: + ret = cpu->c; + break; + case 0x2: + ret = cpu->d; + break; + case 0x3: + ret = cpu->e; + break; + case 0x4: + ret = cpu->h; + break; + case 0x5: + ret = cpu->l; + break; + case 0x6: + ret = cpu->readmembyte(cpu->dmembase + cpu->sp); + break; + case 0x7: + ret = cpu->a; + break; + } + return ret; +} + +uint8_t +getreg_i8080_emu(i8080 *cpu, uint8_t reg) +{ + uint8_t ret = 0xFF; + switch (reg) { + case 0x0: + ret = CH; + break; + case 0x1: + ret = CL; + break; + case 0x2: + ret = DH; + break; + case 0x3: + ret = DL; + break; + case 0x4: + ret = BH; + break; + case 0x5: + ret = BL; + break; + case 0x6: + ret = cpu->readmembyte(cpu->dmembase + BP); + break; + case 0x7: + ret = AL; + break; + } + return ret; +} + +void +setreg_i8080_emu(i8080 *cpu, uint8_t reg, uint8_t val) +{ + switch (reg) { + case 0x0: + CH = val; + break; + case 0x1: + CL = val; + break; + case 0x2: + DH = val; + break; + case 0x3: + DL = val; + break; + case 0x4: + BH = val; + break; + case 0x5: + BL = val; + break; + case 0x6: + cpu->writemembyte(cpu->dmembase + BP, val); + break; + case 0x7: + AL = val; + break; + } +} + +void +setreg_i8080(i8080 *cpu, uint8_t reg, uint8_t val) +{ + switch (reg) { + case 0x0: + cpu->b = val; + break; + case 0x1: + cpu->c = val; + break; + case 0x2: + cpu->d = val; + break; + case 0x3: + cpu->e = val; + break; + case 0x4: + cpu->h = val; + break; + case 0x5: + cpu->l = val; + break; + case 0x6: + cpu->writemembyte(cpu->dmembase + cpu->sp, val); + break; + case 0x7: + cpu->a = val; + break; + } +} + +void +interpret_exec8080(UNUSED(i8080 *cpu), uint8_t opcode) +{ + switch (opcode) { + case 0x00: + { + break; + } + } +} + +/* Actually implement i8080 emulation. */ +void +exec8080(i8080 *cpu, int cycs) +{ +#ifdef UNUSED_8080_VARS + uint8_t temp = 0, temp2; + uint8_t old_af; + uint8_t handled = 0; + uint16_t addr, tempw; + uint16_t new_ip; + int bits; +#endif + + cycles += cycs; + + while (cycles > 0) { + cpu->startclock(); + + if (!repeating) { + cpu->oldpc = cpu->pc; + opcode = cpu->fetchinstruction(cpu); + oldc = cpu->flags & C_FLAG_I8080; + i8080_wait(1, 0); + } + completed = 1; + if (completed) { + repeating = 0; + in_rep = 0; + rep_c_flag = 0; + cpu->endclock(); + if (cpu->checkinterrupts) + cpu->checkinterrupts(); + } + } +} diff --git a/src/cpu/808x.c b/src/cpu/808x.c index 023d89a60..3572f2c9f 100644 --- a/src/cpu/808x.c +++ b/src/cpu/808x.c @@ -1,19 +1,19 @@ -/* - * 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. +/* + * 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. + * This file is part of the 86Box distribution. * - * 808x CPU emulation, mostly ported from reenigne's XTCE, which - * is cycle-accurate. + * 808x CPU emulation, mostly ported from reenigne's XTCE, which + * is cycle-accurate. * - * Authors: Andrew Jenner, - * Miran Grca, + * Authors: Andrew Jenner, + * Miran Grca, * - * Copyright 2015-2020 Andrew Jenner. - * Copyright 2016-2020 Miran Grca. + * Copyright 2015-2020 Andrew Jenner. + * Copyright 2016-2020 Miran Grca. */ #include #include @@ -34,13 +34,13 @@ #include <86box/pic.h> #include <86box/ppi.h> #include <86box/timer.h> +#include <86box/gdbstub.h> /* Is the CPU 8088 or 8086. */ int is8086 = 0; -uint8_t use_custom_nmi_vector = 0; -uint32_t custom_nmi_vector = 0x00000000; - +uint8_t use_custom_nmi_vector = 0; +uint32_t custom_nmi_vector = 0x00000000; /* The prefetch queue (4 bytes for 8088, 6 bytes for 8086). */ static uint8_t pfq[6]; @@ -53,9 +53,9 @@ static uint16_t pfq_ip; /* Pointer tables needed for segment overrides. */ static uint32_t *opseg[4]; -static x86seg *_opseg[4]; +static x86seg *_opseg[4]; -static int noint = 0; +static int noint = 0; static int in_lock = 0; static int cpu_alu_op, pfq_size; @@ -64,83 +64,77 @@ static uint32_t cpu_data = 0; static uint16_t last_addr = 0x0000; -static uint32_t *ovr_seg = NULL; -static int prefetching = 1, completed = 1; -static int in_rep = 0, repeating = 0; -static int oldc, clear_lock = 0; -static int refresh = 0, cycdiff; - +static uint32_t *ovr_seg = NULL; +static int prefetching = 1, completed = 1; +static int in_rep = 0, repeating = 0, rep_c_flag = 0; +static int oldc, clear_lock = 0; +static int refresh = 0, cycdiff; /* Various things needed for 8087. */ -#define OP_TABLE(name) ops_ ## name +#define OP_TABLE(name) ops_##name #define CPU_BLOCK_END() -#define SEG_CHECK_READ(seg) -#define SEG_CHECK_WRITE(seg) -#define CHECK_READ(a, b, c) -#define CHECK_WRITE(a, b, c) -#define UN_USED(x) (void)(x) -#define fetch_ea_16(val) -#define fetch_ea_32(val) -#define PREFETCH_RUN(a, b, c, d, e, f, g, h) +#define SEG_CHECK_READ(seg) +#define SEG_CHECK_WRITE(seg) +#define CHECK_READ(a, b, c) +#define CHECK_WRITE(a, b, c) +#define UN_USED(x) (void) (x) +#define fetch_ea_16(val) +#define fetch_ea_32(val) +#define PREFETCH_RUN(a, b, c, d, e, f, g, h) -#define CYCLES(val) \ - { \ - wait(val, 0); \ - } +#define CYCLES(val) \ + { \ + wait(val, 0); \ + } -#define CLOCK_CYCLES_ALWAYS(val) \ - { \ - wait(val, 0); \ - } +#define CLOCK_CYCLES_ALWAYS(val) \ + { \ + wait(val, 0); \ + } #if 0 -#define CLOCK_CYCLES_FPU(val) \ - { \ - wait(val, 0); \ - } +# define CLOCK_CYCLES_FPU(val) \ + { \ + wait(val, 0); \ + } +# define CLOCK_CYCLES(val) \ + { \ + if (fpu_cycles > 0) { \ + fpu_cycles -= (val); \ + if (fpu_cycles < 0) { \ + wait(val, 0); \ + } \ + } else { \ + wait(val, 0); \ + } \ + } -#define CLOCK_CYCLES(val) \ - { \ - if (fpu_cycles > 0) { \ - fpu_cycles -= (val); \ - if (fpu_cycles < 0) { \ - wait(val, 0); \ - } \ - } else { \ - wait(val, 0); \ - } \ - } - -#define CONCURRENCY_CYCLES(c) fpu_cycles = (c) +# define CONCURRENCY_CYCLES(c) fpu_cycles = (c) #else -#define CLOCK_CYCLES(val) \ - { \ - wait(val, 0); \ - } +# define CLOCK_CYCLES(val) \ + { \ + wait(val, 0); \ + } -#define CLOCK_CYCLES_FPU(val) \ - { \ - wait(val, 0); \ - } +# define CLOCK_CYCLES_FPU(val) \ + { \ + wait(val, 0); \ + } -#define CONCURRENCY_CYCLES(c) +# define CONCURRENCY_CYCLES(c) #endif +typedef int (*OpFn)(uint32_t fetchdat); -typedef int (*OpFn)(uint32_t fetchdat); - - -static int tempc_fpu = 0; - +static int tempc_fpu = 0; #ifdef ENABLE_808X_LOG -void dumpregs(int); +void dumpregs(int); int x808x_do_log = ENABLE_808X_LOG; -int indump = 0; - +int indump = 0; static void x808x_log(const char *fmt, ...) @@ -148,19 +142,17 @@ x808x_log(const char *fmt, ...) va_list ap; if (x808x_do_log) { - va_start(ap, fmt); - pclog_ex(fmt, ap); - va_end(ap); + va_start(ap, fmt); + pclog_ex(fmt, ap); + va_end(ap); } } #else -#define x808x_log(fmt, ...) +# define x808x_log(fmt, ...) #endif - -static void pfq_add(int c, int add); -static void set_pzs(int bits); - +static void pfq_add(int c, int add); +static void set_pzs(int bits); uint16_t get_last_addr(void) @@ -168,48 +160,44 @@ get_last_addr(void) return last_addr; } - static void clock_start(void) { cycdiff = cycles; } - static void clock_end(void) { int diff = cycdiff - cycles; /* On 808x systems, clock speed is usually crystal frequency divided by an integer. */ - tsc += (uint64_t)diff * ((uint64_t)xt_cpu_multi >> 32ULL); /* Shift xt_cpu_multi by 32 bits to the right and then multiply. */ - if (TIMER_VAL_LESS_THAN_VAL(timer_target, (uint32_t)tsc)) - timer_process(); + tsc += (uint64_t) diff * ((uint64_t) xt_cpu_multi >> 32ULL); /* Shift xt_cpu_multi by 32 bits to the right and then multiply. */ + if (TIMER_VAL_LESS_THAN_VAL(timer_target, (uint32_t) tsc)) + timer_process(); } - static void fetch_and_bus(int c, int bus) { if (refresh > 0) { - /* Finish the current fetch, if any. */ - cycles -= ((4 - (biu_cycles & 3)) & 3); - pfq_add((4 - (biu_cycles & 3)) & 3, 1); - /* Add 4 memory access cycles. */ - cycles -= 4; - pfq_add(4, 0); + /* Finish the current fetch, if any. */ + cycles -= ((4 - (biu_cycles & 3)) & 3); + pfq_add((4 - (biu_cycles & 3)) & 3, 1); + /* Add 4 memory access cycles. */ + cycles -= 4; + pfq_add(4, 0); - refresh--; + refresh--; } pfq_add(c, !bus); if (bus < 2) { - clock_end(); - clock_start(); + clock_end(); + clock_start(); } } - static void wait(int c, int bus) { @@ -217,83 +205,78 @@ wait(int c, int bus) fetch_and_bus(c, bus); } - /* This is for external subtraction of cycles. */ void sub_cycles(int c) { if (c <= 0) - return; + return; cycles -= c; if (!is286) - fetch_and_bus(c, 2); + fetch_and_bus(c, 2); } - void resub_cycles(int old_cycles) { int cyc_diff = 0; if (old_cycles > cycles) { - cyc_diff = old_cycles - cycles; - cycles = old_cycles; - sub_cycles(cyc_diff); + cyc_diff = old_cycles - cycles; + cycles = old_cycles; + sub_cycles(cyc_diff); } } - #undef readmemb #undef readmemw #undef readmeml #undef readmemq - static void cpu_io(int bits, int out, uint16_t port) { int old_cycles = cycles; if (out) { - wait(4, 1); - if (bits == 16) { - if (is8086 && !(port & 1)) { - old_cycles = cycles; - outw(port, AX); - } else { - wait(4, 1); - old_cycles = cycles; - outb(port++, AL); - outb(port, AH); - } - } else { - old_cycles = cycles; - outb(port, AL); - } + wait(4, 1); + if (bits == 16) { + if (is8086 && !(port & 1)) { + old_cycles = cycles; + outw(port, AX); + } else { + wait(4, 1); + old_cycles = cycles; + outb(port++, AL); + outb(port, AH); + } + } else { + old_cycles = cycles; + outb(port, AL); + } } else { - wait(4, 1); - if (bits == 16) { - if (is8086 && !(port & 1)) { - old_cycles = cycles; - AX = inw(port); - } else { - wait(4, 1); - old_cycles = cycles; - AL = inb(port++); - AH = inb(port); - } - } else { - old_cycles = cycles; - AL = inb(port); - } + wait(4, 1); + if (bits == 16) { + if (is8086 && !(port & 1)) { + old_cycles = cycles; + AX = inw(port); + } else { + wait(4, 1); + old_cycles = cycles; + AL = inb(port++); + AH = inb(port); + } + } else { + old_cycles = cycles; + AL = inb(port); + } } resub_cycles(old_cycles); } - /* Reads a byte from the memory and advances the BIU. */ static uint8_t readmemb(uint32_t a) @@ -306,20 +289,18 @@ readmemb(uint32_t a) return ret; } - /* Reads a byte from the memory but does not advance the BIU. */ static uint8_t readmembf(uint32_t a) { uint8_t ret; - a = cs + (a & 0xffff); + a = cs + (a & 0xffff); ret = read_mem_b(a); return ret; } - /* Reads a word from the memory and advances the BIU. */ static uint16_t readmemw(uint32_t s, uint16_t a) @@ -328,17 +309,16 @@ readmemw(uint32_t s, uint16_t a) wait(4, 1); if (is8086 && !(a & 1)) - ret = read_mem_w(s + a); + ret = read_mem_w(s + a); else { - wait(4, 1); - ret = read_mem_b(s + a); - ret |= read_mem_b(s + ((a + 1) & 0xffff)) << 8; + wait(4, 1); + ret = read_mem_b(s + a); + ret |= read_mem_b(s + ((is186 && !is_nec) ? (a + 1) : (a + 1) & 0xffff)) << 8; } return ret; } - static uint16_t readmemwf(uint16_t a) { @@ -349,17 +329,15 @@ readmemwf(uint16_t a) return ret; } - static uint16_t readmem(uint32_t s) { if (opcode & 1) - return readmemw(s, cpu_state.eaaddr); + return readmemw(s, cpu_state.eaaddr); else - return (uint16_t) readmemb(s + cpu_state.eaaddr); + return (uint16_t) readmemb(s + cpu_state.eaaddr); } - static uint32_t readmeml(uint32_t s, uint16_t a) { @@ -371,7 +349,6 @@ readmeml(uint32_t s, uint16_t a) return temp; } - static uint64_t readmemq(uint32_t s, uint16_t a) { @@ -383,7 +360,6 @@ readmemq(uint32_t s, uint16_t a) return temp; } - /* Writes a byte to the memory and advances the BIU. */ static void writememb(uint32_t s, uint32_t a, uint8_t v) @@ -394,10 +370,9 @@ writememb(uint32_t s, uint32_t a, uint8_t v) write_mem_b(addr, v); if ((addr >= 0xf0000) && (addr <= 0xfffff)) - last_addr = addr & 0xffff; + last_addr = addr & 0xffff; } - /* Writes a word to the memory and advances the BIU. */ static void writememw(uint32_t s, uint32_t a, uint16_t v) @@ -406,29 +381,27 @@ writememw(uint32_t s, uint32_t a, uint16_t v) wait(4, 1); if (is8086 && !(a & 1)) - write_mem_w(addr, v); + write_mem_w(addr, v); else { - write_mem_b(addr, v & 0xff); - wait(4, 1); - addr = s + ((a + 1) & 0xffff); - write_mem_b(addr, v >> 8); + write_mem_b(addr, v & 0xff); + wait(4, 1); + addr = s + ((is186 && !is_nec) ? (a + 1) : ((a + 1) & 0xffff)); + write_mem_b(addr, v >> 8); } if ((addr >= 0xf0000) && (addr <= 0xfffff)) - last_addr = addr & 0xffff; + last_addr = addr & 0xffff; } - static void writemem(uint32_t s, uint16_t v) { if (opcode & 1) - writememw(s, cpu_state.eaaddr, v); + writememw(s, cpu_state.eaaddr, v); else - writememb(s, cpu_state.eaaddr, (uint8_t) (v & 0xff)); + writememb(s, cpu_state.eaaddr, (uint8_t) (v & 0xff)); } - static void writememl(uint32_t s, uint32_t a, uint32_t v) { @@ -436,7 +409,6 @@ writememl(uint32_t s, uint32_t a, uint32_t v) writememw(s, a + 2, v >> 16); } - static void writememq(uint32_t s, uint32_t a, uint64_t v) { @@ -444,29 +416,27 @@ writememq(uint32_t s, uint32_t a, uint64_t v) writememl(s, a + 4, v >> 32); } - static void pfq_write(void) { uint16_t tempw; if (is8086 && (pfq_pos < (pfq_size - 1))) { - /* The 8086 fetches 2 bytes at a time, and only if there's at least 2 bytes - free in the queue. */ - tempw = readmemwf(pfq_ip); - *(uint16_t *) &(pfq[pfq_pos]) = tempw; - pfq_ip += 2; - pfq_pos += 2; + /* The 8086 fetches 2 bytes at a time, and only if there's at least 2 bytes + free in the queue. */ + tempw = readmemwf(pfq_ip); + *(uint16_t *) &(pfq[pfq_pos]) = tempw; + pfq_ip += 2; + pfq_pos += 2; } else if (!is8086 && (pfq_pos < pfq_size)) { - /* The 8088 fetches 1 byte at a time, and only if there's at least 1 byte - free in the queue. */ - pfq[pfq_pos] = readmembf(pfq_ip); - pfq_ip++; - pfq_pos++; + /* The 8088 fetches 1 byte at a time, and only if there's at least 1 byte + free in the queue. */ + pfq[pfq_pos] = readmembf(pfq_ip); + pfq_ip++; + pfq_pos++; } } - static uint8_t pfq_read(void) { @@ -474,13 +444,12 @@ pfq_read(void) temp = pfq[0]; for (i = 0; i < (pfq_size - 1); i++) - pfq[i] = pfq[i + 1]; + pfq[i] = pfq[i + 1]; pfq_pos--; cpu_state.pc = (cpu_state.pc + 1) & 0xffff; return temp; } - /* Fetches a byte from the prefetch queue, or from memory if the queue has been drained. */ static uint8_t @@ -489,10 +458,10 @@ pfq_fetchb_common(void) uint8_t temp; if (pfq_pos == 0) { - /* Reset prefetch queue internal position. */ - pfq_ip = cpu_state.pc; - /* Fill the queue. */ - wait(4 - (biu_cycles & 3), 0); + /* Reset prefetch queue internal position. */ + pfq_ip = cpu_state.pc; + /* Fill the queue. */ + wait(4 - (biu_cycles & 3), 0); } /* Fetch. */ @@ -500,7 +469,6 @@ pfq_fetchb_common(void) return temp; } - static uint8_t pfq_fetchb(void) { @@ -511,7 +479,6 @@ pfq_fetchb(void) return ret; } - /* Fetches a word from the prefetch queue, or from memory if the queue has been drained. */ static uint16_t @@ -526,17 +493,15 @@ pfq_fetchw(void) return temp; } - static uint16_t -pfq_fetch() +pfq_fetch(void) { if (opcode & 1) - return pfq_fetchw(); + return pfq_fetchw(); else - return (uint16_t) pfq_fetchb(); + return (uint16_t) pfq_fetchb(); } - /* Adds bytes to the prefetch queue based on the instruction's cycle count. */ static void pfq_add(int c, int add) @@ -544,293 +509,279 @@ pfq_add(int c, int add) int d; if ((c <= 0) || (pfq_pos >= pfq_size)) - return; + return; for (d = 0; d < c; d++) { - biu_cycles = (biu_cycles + 1) & 0x03; - if (prefetching && add && (biu_cycles == 0x00)) - pfq_write(); + biu_cycles = (biu_cycles + 1) & 0x03; + if (prefetching && add && (biu_cycles == 0x00)) + pfq_write(); } } - /* Clear the prefetch queue - called on reset and on anything that affects either CS or IP. */ static void -pfq_clear() +pfq_clear(void) { - pfq_pos = 0; + pfq_pos = 0; prefetching = 0; } - static void load_cs(uint16_t seg) { cpu_state.seg_cs.base = seg << 4; - cpu_state.seg_cs.seg = seg & 0xffff; + cpu_state.seg_cs.seg = seg & 0xffff; } - static void load_seg(uint16_t seg, x86seg *s) { s->base = seg << 4; - s->seg = seg & 0xffff; + s->seg = seg & 0xffff; } - void reset_808x(int hard) { biu_cycles = 0; - in_rep = 0; - in_lock = 0; - completed = 1; - repeating = 0; + in_rep = 0; + in_lock = 0; + completed = 1; + repeating = 0; clear_lock = 0; - refresh = 0; - ovr_seg = NULL; + refresh = 0; + ovr_seg = NULL; if (hard) { - opseg[0] = &es; - opseg[1] = &cs; - opseg[2] = &ss; - opseg[3] = &ds; - _opseg[0] = &cpu_state.seg_es; - _opseg[1] = &cpu_state.seg_cs; - _opseg[2] = &cpu_state.seg_ss; - _opseg[3] = &cpu_state.seg_ds; + opseg[0] = &es; + opseg[1] = &cs; + opseg[2] = &ss; + opseg[3] = &ds; + _opseg[0] = &cpu_state.seg_es; + _opseg[1] = &cpu_state.seg_cs; + _opseg[2] = &cpu_state.seg_ss; + _opseg[3] = &cpu_state.seg_ds; - pfq_size = (is8086) ? 6 : 4; - pfq_clear(); + pfq_size = (is8086) ? 6 : 4; + pfq_clear(); } load_cs(0xFFFF); cpu_state.pc = 0; + if (is_nec) + cpu_state.flags |= MD_FLAG; rammask = 0xfffff; prefetching = 1; - cpu_alu_op = 0; + cpu_alu_op = 0; use_custom_nmi_vector = 0x00; - custom_nmi_vector = 0x00000000; + custom_nmi_vector = 0x00000000; } - static void -set_ip(uint16_t new_ip) { +set_ip(uint16_t new_ip) +{ pfq_ip = cpu_state.pc = new_ip; - prefetching = 1; + prefetching = 1; } - /* Memory refresh read - called by reads and writes on DMA channel 0. */ void -refreshread(void) { +refreshread(void) +{ refresh++; } - static uint16_t get_accum(int bits) { return (bits == 16) ? AX : AL; } - static void set_accum(int bits, uint16_t val) { if (bits == 16) - AX = val; + AX = val; else - AL = val; + AL = val; } - static uint16_t sign_extend(uint8_t data) { return data + (data < 0x80 ? 0 : 0xff00); } - /* Fetches the effective address from the prefetch queue according to MOD and R/M. */ static void do_mod_rm(void) { - rmdat = pfq_fetchb(); + rmdat = pfq_fetchb(); cpu_reg = (rmdat >> 3) & 7; cpu_mod = (rmdat >> 6) & 3; - cpu_rm = rmdat & 7; + cpu_rm = rmdat & 7; if (cpu_mod == 3) - return; + return; wait(1, 0); if ((rmdat & 0xc7) == 0x06) { - wait(1, 0); - cpu_state.eaaddr = pfq_fetchw(); - easeg = ovr_seg ? *ovr_seg : ds; - wait(1, 0); - return; - } else switch (cpu_rm) { - case 0: - case 3: - wait(2, 0); - break; - case 1: - case 2: - wait(3, 0); - break; - } + wait(1, 0); + cpu_state.eaaddr = pfq_fetchw(); + easeg = ovr_seg ? *ovr_seg : ds; + wait(1, 0); + return; + } else + switch (cpu_rm) { + case 0: + case 3: + wait(2, 0); + break; + case 1: + case 2: + wait(3, 0); + break; + } cpu_state.eaaddr = (*mod1add[0][cpu_rm]) + (*mod1add[1][cpu_rm]); - easeg = ovr_seg ? *ovr_seg : *mod1seg[cpu_rm]; + easeg = ovr_seg ? *ovr_seg : *mod1seg[cpu_rm]; switch (rmdat & 0xc0) { - case 0x40: - wait(3, 0); - cpu_state.eaaddr += sign_extend(pfq_fetchb()); - break; - case 0x80: - wait(3, 0); - cpu_state.eaaddr += pfq_fetchw(); - break; + case 0x40: + wait(3, 0); + cpu_state.eaaddr += sign_extend(pfq_fetchb()); + break; + case 0x80: + wait(3, 0); + cpu_state.eaaddr += pfq_fetchw(); + break; } cpu_state.eaaddr &= 0xffff; wait(2, 0); } - #undef getr8 -#define getr8(r) ((r & 4) ? cpu_state.regs[r & 3].b.h : cpu_state.regs[r & 3].b.l) +#define getr8(r) ((r & 4) ? cpu_state.regs[r & 3].b.h : cpu_state.regs[r & 3].b.l) #undef setr8 -#define setr8(r,v) if (r & 4) cpu_state.regs[r & 3].b.h = v; \ - else cpu_state.regs[r & 3].b.l = v; - +#define setr8(r, v) \ + if (r & 4) \ + cpu_state.regs[r & 3].b.h = v; \ + else \ + cpu_state.regs[r & 3].b.l = v; /* Reads a byte from the effective address. */ static uint8_t geteab(void) { if (cpu_mod == 3) - return (getr8(cpu_rm)); + return (getr8(cpu_rm)); return readmemb(easeg + cpu_state.eaaddr); } - /* Reads a word from the effective address. */ static uint16_t geteaw(void) { if (cpu_mod == 3) - return cpu_state.regs[cpu_rm].w; + return cpu_state.regs[cpu_rm].w; return readmemw(easeg, cpu_state.eaaddr); } - /* Neede for 8087 - memory only. */ static uint32_t geteal(void) { if (cpu_mod == 3) { - fatal("808x register geteal()\n"); - return 0xffffffff; + fatal("808x register geteal()\n"); + return 0xffffffff; } return readmeml(easeg, cpu_state.eaaddr); } - /* Neede for 8087 - memory only. */ static uint64_t geteaq(void) { if (cpu_mod == 3) { - fatal("808x register geteaq()\n"); - return 0xffffffff; + fatal("808x register geteaq()\n"); + return 0xffffffff; } return readmemq(easeg, cpu_state.eaaddr); } - static void read_ea(int memory_only, int bits) { if (cpu_mod != 3) { - if (bits == 16) - cpu_data = readmemw(easeg, cpu_state.eaaddr); - else - cpu_data = readmemb(easeg + cpu_state.eaaddr); - return; + if (bits == 16) + cpu_data = readmemw(easeg, cpu_state.eaaddr); + else + cpu_data = readmemb(easeg + cpu_state.eaaddr); + return; } if (!memory_only) { - if (bits == 8) { - cpu_data = getr8(cpu_rm); - } else - cpu_data = cpu_state.regs[cpu_rm].w; + if (bits == 8) { + cpu_data = getr8(cpu_rm); + } else + cpu_data = cpu_state.regs[cpu_rm].w; } } - static void read_ea2(int bits) { cpu_state.eaaddr = (cpu_state.eaaddr + 2) & 0xffff; if (bits == 16) - cpu_data = readmemw(easeg, cpu_state.eaaddr); + cpu_data = readmemw(easeg, cpu_state.eaaddr); else - cpu_data = readmemb(easeg + cpu_state.eaaddr); + cpu_data = readmemb(easeg + cpu_state.eaaddr); } - /* Writes a byte to the effective address. */ static void seteab(uint8_t val) { if (cpu_mod == 3) { - setr8(cpu_rm, val); + setr8(cpu_rm, val); } else - writememb(easeg, cpu_state.eaaddr, val); + writememb(easeg, cpu_state.eaaddr, val); } - /* Writes a word to the effective address. */ static void seteaw(uint16_t val) { if (cpu_mod == 3) - cpu_state.regs[cpu_rm].w = val; + cpu_state.regs[cpu_rm].w = val; else - writememw(easeg, cpu_state.eaaddr, val); + writememw(easeg, cpu_state.eaaddr, val); } - static void seteal(uint32_t val) { if (cpu_mod == 3) { - fatal("808x register seteal()\n"); - return; + fatal("808x register seteal()\n"); + return; } else - writememl(easeg, cpu_state.eaaddr, val); + writememl(easeg, cpu_state.eaaddr, val); } - static void seteaq(uint64_t val) { if (cpu_mod == 3) { - fatal("808x register seteaq()\n"); - return; + fatal("808x register seteaq()\n"); + return; } else - writememq(easeg, cpu_state.eaaddr, val); + writememq(easeg, cpu_state.eaaddr, val); } - /* Leave out the 686 stuff as it's not needed and complicates compiling. */ #define FPU_8087 @@ -840,17 +791,20 @@ seteaq(uint64_t val) #undef tempc #undef FPU_8087 - /* Pushes a word to the stack. */ static void push(uint16_t *val) { + if ((is186 && !is_nec) && (SP == 1)) { + writememw(ss - 1, 0, *val); + SP = cpu_state.eaaddr = 0xFFFF; + return; + } SP -= 2; cpu_state.eaaddr = (SP & 0xffff); writememw(ss, cpu_state.eaaddr, *val); } - /* Pops a word from the stack. */ static uint16_t pop(void) @@ -860,90 +814,135 @@ pop(void) return readmemw(ss, cpu_state.eaaddr); } - static void access(int num, int bits) { switch (num) { - case 0: case 61: case 63: case 64: - case 67: case 69: case 71: case 72: - default: - break; - case 1: case 6: case 7: case 8: - case 9: case 17: case 20: case 21: - case 24: case 28: case 47: case 48: - case 49: case 50: case 51: case 55: - case 56: case 62: case 66: case 68: - wait(1, 0); - break; - case 3: case 11: case 15: case 22: - case 23: case 25: case 26: case 35: - case 44: case 45: case 46: case 52: - case 53: case 54: - wait(2, 0); - break; - case 16: case 18: case 19: case 27: - case 32: case 37: case 42: - wait(3, 0); - break; - case 10: case 12: case 13: case 14: - case 29: case 30: case 33: case 34: - case 39: case 41: case 60: - wait(4, 0); - break; - case 4: case 70: - wait(5, 0); - break; - case 31: case 38: case 40: - wait(6, 0); - break; - case 5: - if (opcode == 0xcc) - wait(7, 0); - else - wait(4, 0); - break; - case 36: - wait(1, 0); - pfq_clear(); - wait (1, 0); - if (cpu_mod != 3) - wait(1, 0); - wait(3, 0); - break; - case 43: - wait(2, 0); - pfq_clear(); - wait(1, 0); - break; - case 57: - if (cpu_mod != 3) - wait(2, 0); - wait(4, 0); - break; - case 58: - if (cpu_mod != 3) - wait(1, 0); - wait(4, 0); - break; - case 59: - wait(2, 0); - pfq_clear(); - if (cpu_mod != 3) - wait(1, 0); - wait(3, 0); - break; - case 65: - wait(1, 0); - pfq_clear(); - wait(2, 0); - if (cpu_mod != 3) - wait(1, 0); - break; + case 0: + case 61: + case 63: + case 64: + case 67: + case 69: + case 71: + case 72: + default: + break; + case 1: + case 6: + case 7: + case 8: + case 9: + case 17: + case 20: + case 21: + case 24: + case 28: + case 47: + case 48: + case 49: + case 50: + case 51: + case 55: + case 56: + case 62: + case 66: + case 68: + wait(1, 0); + break; + case 3: + case 11: + case 15: + case 22: + case 23: + case 25: + case 26: + case 35: + case 44: + case 45: + case 46: + case 52: + case 53: + case 54: + wait(2, 0); + break; + case 16: + case 18: + case 19: + case 27: + case 32: + case 37: + case 42: + wait(3, 0); + break; + case 10: + case 12: + case 13: + case 14: + case 29: + case 30: + case 33: + case 34: + case 39: + case 41: + case 60: + wait(4, 0); + break; + case 4: + case 70: + wait(5, 0); + break; + case 31: + case 38: + case 40: + wait(6, 0); + break; + case 5: + if (opcode == 0xcc) + wait(7, 0); + else + wait(4, 0); + break; + case 36: + wait(1, 0); + pfq_clear(); + wait(1, 0); + if (cpu_mod != 3) + wait(1, 0); + wait(3, 0); + break; + case 43: + wait(2, 0); + pfq_clear(); + wait(1, 0); + break; + case 57: + if (cpu_mod != 3) + wait(2, 0); + wait(4, 0); + break; + case 58: + if (cpu_mod != 3) + wait(1, 0); + wait(4, 0); + break; + case 59: + wait(2, 0); + pfq_clear(); + if (cpu_mod != 3) + wait(1, 0); + wait(3, 0); + break; + case 65: + wait(1, 0); + pfq_clear(); + wait(2, 0); + if (cpu_mod != 3) + wait(1, 0); + break; } } - /* Calls an interrupt. */ static void interrupt(uint16_t addr) @@ -954,18 +953,18 @@ interrupt(uint16_t addr) addr <<= 2; cpu_state.eaaddr = addr; - old_cs = CS; + old_cs = CS; access(5, 16); new_ip = readmemw(0, cpu_state.eaaddr); wait(1, 0); cpu_state.eaaddr = (cpu_state.eaaddr + 2) & 0xffff; access(6, 16); - new_cs = readmemw(0, cpu_state.eaaddr); + new_cs = readmemw(0, cpu_state.eaaddr); prefetching = 0; pfq_clear(); ovr_seg = NULL; access(39, 16); - tempf = cpu_state.flags & 0x0fd7; + tempf = cpu_state.flags & (is_nec ? 0x8fd7 : 0x0fd7); push(&tempf); cpu_state.flags &= ~(I_FLAG | T_FLAG); access(40, 16); @@ -978,6 +977,11 @@ interrupt(uint16_t addr) push(&old_ip); } +void +interrupt_808x(uint16_t addr) +{ + interrupt(addr); +} static void custom_nmi(void) @@ -987,7 +991,7 @@ custom_nmi(void) uint16_t tempf; cpu_state.eaaddr = 0x0002; - old_cs = CS; + old_cs = CS; access(5, 16); (void) readmemw(0, cpu_state.eaaddr); new_ip = custom_nmi_vector & 0xffff; @@ -995,12 +999,12 @@ custom_nmi(void) cpu_state.eaaddr = (cpu_state.eaaddr + 2) & 0xffff; access(6, 16); (void) readmemw(0, cpu_state.eaaddr); - new_cs = custom_nmi_vector >> 16; + new_cs = custom_nmi_vector >> 16; prefetching = 0; pfq_clear(); ovr_seg = NULL; access(39, 16); - tempf = cpu_state.flags & 0x0fd7; + tempf = cpu_state.flags & (is_nec ? 0x8fd7 : 0x0fd7); push(&tempf); cpu_state.flags &= ~(I_FLAG | T_FLAG); access(40, 16); @@ -1013,95 +1017,93 @@ custom_nmi(void) push(&old_ip); } - static int irq_pending(void) { uint8_t temp; - temp = (nmi && nmi_enable && nmi_mask) || ((cpu_state.flags & T_FLAG) && !noint) || - ((cpu_state.flags & I_FLAG) && pic.int_pending && !noint); + temp = (nmi && nmi_enable && nmi_mask) || ((cpu_state.flags & T_FLAG) && !noint) || ((cpu_state.flags & I_FLAG) && pic.int_pending && !noint); return temp; } - static void check_interrupts(void) { int temp; if (irq_pending()) { - if ((cpu_state.flags & T_FLAG) && !noint) { - interrupt(1); - return; - } - if (nmi && nmi_enable && nmi_mask) { - nmi_enable = 0; - if (use_custom_nmi_vector) - custom_nmi(); - else - interrupt(2); + if ((cpu_state.flags & T_FLAG) && !noint) { + interrupt(1); + return; + } + if (nmi && nmi_enable && nmi_mask) { + nmi_enable = 0; + if (use_custom_nmi_vector) + custom_nmi(); + else + interrupt(2); #ifndef OLD_NMI_BEHAVIOR - nmi = 0; + nmi = 0; #endif - return; - } - if ((cpu_state.flags & I_FLAG) && pic.int_pending && !noint) { - repeating = 0; - completed = 1; - ovr_seg = NULL; - wait(3, 0); - /* ACK to PIC */ - temp = pic_irq_ack(); - wait(4, 1); - wait(1, 0); - /* ACK to PIC */ - temp = pic_irq_ack(); - wait(4, 1); - wait(1, 0); - in_lock = 0; - clear_lock = 0; - wait(1, 0); - /* Here is where temp should be filled, but we cheat. */ - wait(3, 0); - opcode = 0x00; - interrupt(temp); - } + return; + } + if ((cpu_state.flags & I_FLAG) && pic.int_pending && !noint) { + repeating = 0; + completed = 1; + ovr_seg = NULL; + wait(3, 0); + /* ACK to PIC */ + temp = pic_irq_ack(); + wait(4, 1); + wait(1, 0); + /* ACK to PIC */ + temp = pic_irq_ack(); + wait(4, 1); + wait(1, 0); + in_lock = 0; + clear_lock = 0; + wait(1, 0); + /* Here is where temp should be filled, but we cheat. */ + wait(3, 0); + opcode = 0x00; + interrupt(temp); + } } } - static int rep_action(int bits) { uint16_t t; if (in_rep == 0) - return 0; + return 0; wait(2, 0); t = CX; if (irq_pending() && (repeating != 0)) { - access(71, bits); - pfq_clear(); - set_ip(cpu_state.pc - 2); - t = 0; + access(71, bits); + pfq_clear(); + if (is_nec && (ovr_seg != NULL)) + set_ip(cpu_state.pc - 3); + else + set_ip(cpu_state.pc - 2); + t = 0; } if (t == 0) { - wait(1, 0); - completed = 1; - repeating = 0; - return 1; + wait(1, 0); + completed = 1; + repeating = 0; + return 1; } --CX; completed = 0; wait(2, 0); if (!repeating) - wait(2, 0); + wait(2, 0); return 0; } - static uint16_t jump(uint16_t delta) { @@ -1114,21 +1116,18 @@ jump(uint16_t delta) return old_ip; } - static void jump_short(void) { jump(sign_extend((uint8_t) cpu_data)); } - static uint16_t jump_near(void) { return jump(pfq_fetchw()); } - /* Performs a conditional jump. */ static void jcc(uint8_t opcode, int cond) @@ -1139,31 +1138,27 @@ jcc(uint8_t opcode, int cond) cpu_data = pfq_fetchb(); wait(1, 0); if ((!cond) == !!(opcode & 0x01)) - jump_short(); + jump_short(); } - static void set_cf(int cond) { cpu_state.flags = (cpu_state.flags & ~C_FLAG) | (cond ? C_FLAG : 0); } - static void set_if(int cond) { cpu_state.flags = (cpu_state.flags & ~I_FLAG) | (cond ? I_FLAG : 0); } - static void set_df(int cond) { cpu_state.flags = (cpu_state.flags & ~D_FLAG) | (cond ? D_FLAG : 0); } - static void bitwise(int bits, uint16_t data) { @@ -1172,58 +1167,50 @@ bitwise(int bits, uint16_t data) set_pzs(bits); } - static void test(int bits, uint16_t dest, uint16_t src) { cpu_dest = dest; - cpu_src = src; + cpu_src = src; bitwise(bits, (cpu_dest & cpu_src)); } - static void set_of(int of) { cpu_state.flags = (cpu_state.flags & ~0x800) | (of ? 0x800 : 0); } - static int top_bit(uint16_t w, int bits) { return (w & (1 << (bits - 1))); } - static void set_of_add(int bits) { set_of(top_bit((cpu_data ^ cpu_src) & (cpu_data ^ cpu_dest), bits)); } - static void set_of_sub(int bits) { set_of(top_bit((cpu_dest ^ cpu_src) & (cpu_data ^ cpu_dest), bits)); } - static void set_af(int af) { cpu_state.flags = (cpu_state.flags & ~0x10) | (af ? 0x10 : 0); } - static void do_af(void) { set_af(((cpu_data ^ cpu_src ^ cpu_dest) & 0x10) != 0); } - static void set_apzs(int bits) { @@ -1231,7 +1218,6 @@ set_apzs(int bits) do_af(); } - static void add(int bits) { @@ -1244,12 +1230,11 @@ add(int bits) /* Anything - FF with carry on is basically anything + 0x100: value stays unchanged but carry goes on. */ if ((cpu_alu_op == 2) && !(cpu_src & size_mask) && (cpu_state.flags & C_FLAG)) - cpu_state.flags |= C_FLAG; + cpu_state.flags |= C_FLAG; else - set_cf((cpu_src & size_mask) > (cpu_data & size_mask)); + set_cf((cpu_src & size_mask) > (cpu_data & size_mask)); } - static void sub(int bits) { @@ -1262,81 +1247,60 @@ sub(int bits) /* Anything - FF with carry on is basically anything - 0x100: value stays unchanged but carry goes on. */ if ((cpu_alu_op == 3) && !(cpu_src & size_mask) && (cpu_state.flags & C_FLAG)) - cpu_state.flags |= C_FLAG; + cpu_state.flags |= C_FLAG; else - set_cf((cpu_src & size_mask) > (cpu_dest & size_mask)); + set_cf((cpu_src & size_mask) > (cpu_dest & size_mask)); } - static void alu_op(int bits) { - switch(cpu_alu_op) { - case 1: - bitwise(bits, (cpu_dest | cpu_src)); - break; - case 2: - if (cpu_state.flags & C_FLAG) - cpu_src++; - /* Fall through. */ - case 0: - add(bits); - break; - case 3: - if (cpu_state.flags & C_FLAG) - cpu_src++; - /* Fall through. */ - case 5: case 7: - sub(bits); - break; - case 4: - test(bits, cpu_dest, cpu_src); - break; - case 6: - bitwise(bits, (cpu_dest ^ cpu_src)); - break; + switch (cpu_alu_op) { + case 1: + bitwise(bits, (cpu_dest | cpu_src)); + break; + case 2: + if (cpu_state.flags & C_FLAG) + cpu_src++; + /* Fall through. */ + case 0: + add(bits); + break; + case 3: + if (cpu_state.flags & C_FLAG) + cpu_src++; + /* Fall through. */ + case 5: + case 7: + sub(bits); + break; + case 4: + test(bits, cpu_dest, cpu_src); + break; + case 6: + bitwise(bits, (cpu_dest ^ cpu_src)); + break; } } - static void set_sf(int bits) { cpu_state.flags = (cpu_state.flags & ~0x80) | (top_bit(cpu_data, bits) ? 0x80 : 0); } - static void set_pf(void) { - static uint8_t table[0x100] = { - 4, 0, 0, 4, 0, 4, 4, 0, 0, 4, 4, 0, 4, 0, 0, 4, - 0, 4, 4, 0, 4, 0, 0, 4, 4, 0, 0, 4, 0, 4, 4, 0, - 0, 4, 4, 0, 4, 0, 0, 4, 4, 0, 0, 4, 0, 4, 4, 0, - 4, 0, 0, 4, 0, 4, 4, 0, 0, 4, 4, 0, 4, 0, 0, 4, - 0, 4, 4, 0, 4, 0, 0, 4, 4, 0, 0, 4, 0, 4, 4, 0, - 4, 0, 0, 4, 0, 4, 4, 0, 0, 4, 4, 0, 4, 0, 0, 4, - 4, 0, 0, 4, 0, 4, 4, 0, 0, 4, 4, 0, 4, 0, 0, 4, - 0, 4, 4, 0, 4, 0, 0, 4, 4, 0, 0, 4, 0, 4, 4, 0, - 0, 4, 4, 0, 4, 0, 0, 4, 4, 0, 0, 4, 0, 4, 4, 0, - 4, 0, 0, 4, 0, 4, 4, 0, 0, 4, 4, 0, 4, 0, 0, 4, - 4, 0, 0, 4, 0, 4, 4, 0, 0, 4, 4, 0, 4, 0, 0, 4, - 0, 4, 4, 0, 4, 0, 0, 4, 4, 0, 0, 4, 0, 4, 4, 0, - 4, 0, 0, 4, 0, 4, 4, 0, 0, 4, 4, 0, 4, 0, 0, 4, - 0, 4, 4, 0, 4, 0, 0, 4, 4, 0, 0, 4, 0, 4, 4, 0, - 0, 4, 4, 0, 4, 0, 0, 4, 4, 0, 0, 4, 0, 4, 4, 0, - 4, 0, 0, 4, 0, 4, 4, 0, 0, 4, 4, 0, 4, 0, 0, 4}; - - cpu_state.flags = (cpu_state.flags & ~4) | table[cpu_data & 0xff]; + cpu_state.flags = (cpu_state.flags & ~4) | (!__builtin_parity(cpu_data & 0xFF) << 2); } - static void mul(uint16_t a, uint16_t b) { - int negate = 0; - int bit_count = 8; - int carry, i; + int negate = 0; + int bit_count = 8; + int carry, i; uint16_t high_bit = 0x80; uint16_t size_mask; uint16_t c, r; @@ -1344,36 +1308,36 @@ mul(uint16_t a, uint16_t b) size_mask = (1 << bit_count) - 1; if (opcode != 0xd5) { - if (opcode & 1) { - bit_count = 16; - high_bit = 0x8000; - } else - wait(8, 0); + if (opcode & 1) { + bit_count = 16; + high_bit = 0x8000; + } else + wait(8, 0); - size_mask = (1 << bit_count) - 1; + size_mask = (1 << bit_count) - 1; - if ((rmdat & 0x38) == 0x28) { - if (!top_bit(a, bit_count)) { - if (top_bit(b, bit_count)) { - wait(1, 0); - if ((b & size_mask) != ((opcode & 1) ? 0x8000 : 0x80)) - wait(1, 0); - b = ~b + 1; - negate = 1; - } - } else { - wait(1, 0); - a = ~a + 1; - negate = 1; - if (top_bit(b, bit_count)) { - b = ~b + 1; - negate = 0; - } else - wait(4, 0); - } - wait(10, 0); - } - wait(3, 0); + if ((rmdat & 0x38) == 0x28) { + if (!top_bit(a, bit_count)) { + if (top_bit(b, bit_count)) { + wait(1, 0); + if ((b & size_mask) != ((opcode & 1) ? 0x8000 : 0x80)) + wait(1, 0); + b = ~b + 1; + negate = 1; + } + } else { + wait(1, 0); + a = ~a + 1; + negate = 1; + if (top_bit(b, bit_count)) { + b = ~b + 1; + negate = 0; + } else + wait(4, 0); + } + wait(10, 0); + } + wait(3, 0); } c = 0; @@ -1381,28 +1345,28 @@ mul(uint16_t a, uint16_t b) carry = (a & 1) != 0; a >>= 1; for (i = 0; i < bit_count; ++i) { - wait(7, 0); - if (carry) { - cpu_src = c; - cpu_dest = b; - add(bit_count); - c = cpu_data & size_mask; - wait(1, 0); - carry = !!(cpu_state.flags & C_FLAG); - } - r = (c >> 1) + (carry ? high_bit : 0); - carry = (c & 1) != 0; - c = r; - r = (a >> 1) + (carry ? high_bit : 0); - carry = (a & 1) != 0; - a = r; + wait(7, 0); + if (carry) { + cpu_src = c; + cpu_dest = b; + add(bit_count); + c = cpu_data & size_mask; + wait(1, 0); + carry = !!(cpu_state.flags & C_FLAG); + } + r = (c >> 1) + (carry ? high_bit : 0); + carry = (c & 1) != 0; + c = r; + r = (a >> 1) + (carry ? high_bit : 0); + carry = (a & 1) != 0; + a = r; } if (negate) { - c = ~c; - a = (~a + 1) & size_mask; - if (a == 0) - ++c; - wait(9, 0); + c = ~c; + a = (~a + 1) & size_mask; + if (a == 0) + ++c; + wait(9, 0); } cpu_data = a; cpu_dest = c; @@ -1412,21 +1376,18 @@ mul(uint16_t a, uint16_t b) set_af(0); } - static void set_of_rotate(int bits) { set_of(top_bit(cpu_data ^ cpu_dest, bits)); } - static void set_zf_ex(int zf) { cpu_state.flags = (cpu_state.flags & ~0x40) | (zf ? 0x40 : 0); } - static void set_zf(int bits) { @@ -1435,7 +1396,6 @@ set_zf(int bits) set_zf_ex((cpu_data & size_mask) == 0); } - static void set_pzs(int bits) { @@ -1444,161 +1404,153 @@ set_pzs(int bits) set_sf(bits); } - static void set_co_mul(int bits, int carry) { set_cf(carry); set_of(carry); - /* NOTE: When implementing the V20, care should be taken to not change - the zero flag. */ set_zf_ex(!carry); if (!carry) - wait(1, 0); + wait(1, 0); } - /* Was div(), renamed to avoid conflicts with stdlib div(). */ static int x86_div(uint16_t l, uint16_t h) { - int b, bit_count = 8; - int negative = 0; - int dividend_negative = 0; - int size_mask, carry; + int b, bit_count = 8; + int negative = 0; + int dividend_negative = 0; + int size_mask, carry; uint16_t r; if (opcode & 1) { - l = AX; - h = DX; - bit_count = 16; + l = AX; + h = DX; + bit_count = 16; } size_mask = (1 << bit_count) - 1; if (opcode != 0xd4) { - if ((rmdat & 0x38) == 0x38) { - if (top_bit(h, bit_count)) { - h = ~h; - l = (~l + 1) & size_mask; - if (l == 0) - ++h; - h &= size_mask; - negative = 1; - dividend_negative = 1; - wait(4, 0); - } - if (top_bit(cpu_src, bit_count)) { - cpu_src = ~cpu_src + 1; - negative = !negative; - } else - wait(1, 0); - wait(9, 0); - } - wait(3, 0); + if ((rmdat & 0x38) == 0x38) { + if (top_bit(h, bit_count)) { + h = ~h; + l = (~l + 1) & size_mask; + if (l == 0) + ++h; + h &= size_mask; + negative = 1; + dividend_negative = 1; + wait(4, 0); + } + if (top_bit(cpu_src, bit_count)) { + cpu_src = ~cpu_src + 1; + negative = !negative; + } else + wait(1, 0); + wait(9, 0); + } + wait(3, 0); } wait(8, 0); cpu_src &= size_mask; if (h >= cpu_src) { - if (opcode != 0xd4) - wait(1, 0); - interrupt(0); - return 0; + if (opcode != 0xd4) + wait(1, 0); + interrupt(0); + return 0; } if (opcode != 0xd4) - wait(1, 0); + wait(1, 0); wait(2, 0); carry = 1; for (b = 0; b < bit_count; ++b) { - r = (l << 1) + (carry ? 1 : 0); - carry = top_bit(l, bit_count); - l = r; - r = (h << 1) + (carry ? 1 : 0); - carry = top_bit(h, bit_count); - h = r; - wait(8, 0); - if (carry) { - carry = 0; - h -= cpu_src; - if (b == bit_count - 1) - wait(2, 0); - } else { - carry = cpu_src > h; - if (!carry) { - h -= cpu_src; - wait(1, 0); - if (b == bit_count - 1) - wait(2, 0); - } - } + r = (l << 1) + (carry ? 1 : 0); + carry = top_bit(l, bit_count); + l = r; + r = (h << 1) + (carry ? 1 : 0); + carry = top_bit(h, bit_count); + h = r; + wait(8, 0); + if (carry) { + carry = 0; + h -= cpu_src; + if (b == bit_count - 1) + wait(2, 0); + } else { + carry = cpu_src > h; + if (!carry) { + h -= cpu_src; + wait(1, 0); + if (b == bit_count - 1) + wait(2, 0); + } + } } l = ~((l << 1) + (carry ? 1 : 0)); if (opcode != 0xd4 && (rmdat & 0x38) == 0x38) { - wait(4, 0); - if (top_bit(l, bit_count)) { - if (cpu_mod == 3) - wait(1, 0); - interrupt(0); - return 0; - } - wait(7, 0); - if (negative) - l = ~l + 1; - if (dividend_negative) - h = ~h + 1; + wait(4, 0); + if (top_bit(l, bit_count)) { + if (cpu_mod == 3) + wait(1, 0); + interrupt(0); + return 0; + } + wait(7, 0); + if (negative) + l = ~l + 1; + if (dividend_negative) + h = ~h + 1; } if (opcode == 0xd4) { - AL = h & 0xff; - AH = l & 0xff; + AL = h & 0xff; + AH = l & 0xff; } else { - AH = h & 0xff; - AL = l & 0xff; - if (opcode & 1) { - DX = h; - AX = l; - } + AH = h & 0xff; + AL = l & 0xff; + if (opcode & 1) { + DX = h; + AX = l; + } } return 1; } - static uint16_t string_increment(int bits) { int d = bits >> 3; if (cpu_state.flags & D_FLAG) - cpu_state.eaaddr -= d; + cpu_state.eaaddr -= d; else - cpu_state.eaaddr += d; + cpu_state.eaaddr += d; cpu_state.eaaddr &= 0xffff; return cpu_state.eaaddr; } - static void lods(int bits) { cpu_state.eaaddr = SI; if (bits == 16) - cpu_data = readmemw((ovr_seg ? *ovr_seg : ds), cpu_state.eaaddr); + cpu_data = readmemw((ovr_seg ? *ovr_seg : ds), cpu_state.eaaddr); else - cpu_data = readmemb((ovr_seg ? *ovr_seg : ds) + cpu_state.eaaddr); + cpu_data = readmemb((ovr_seg ? *ovr_seg : ds) + cpu_state.eaaddr); SI = string_increment(bits); } - static void stos(int bits) { cpu_state.eaaddr = DI; if (bits == 16) - writememw(es, cpu_state.eaaddr, cpu_data); + writememw(es, cpu_state.eaaddr, cpu_data); else - writememb(es, cpu_state.eaaddr, (uint8_t) (cpu_data & 0xff)); + writememb(es, cpu_state.eaaddr, (uint8_t) (cpu_data & 0xff)); DI = string_increment(bits); } - static void aa(void) { @@ -1607,7 +1559,6 @@ aa(void) wait(6, 0); } - static void set_ca(void) { @@ -1615,7 +1566,6 @@ set_ca(void) set_af(1); } - static void clear_ca(void) { @@ -1623,1214 +1573,1972 @@ clear_ca(void) set_af(0); } - static uint16_t get_ea(void) { if (opcode & 1) - return geteaw(); + return geteaw(); else - return (uint16_t) geteab(); + return (uint16_t) geteab(); } - static uint16_t get_reg(uint8_t reg) { if (opcode & 1) - return cpu_state.regs[reg].w; + return cpu_state.regs[reg].w; else - return (uint16_t) getr8(reg); + return (uint16_t) getr8(reg); } - static void set_ea(uint16_t val) { if (opcode & 1) - seteaw(val); + seteaw(val); else - seteab((uint8_t) (val & 0xff)); + seteab((uint8_t) (val & 0xff)); } - static void set_reg(uint8_t reg, uint16_t val) { if (opcode & 1) - cpu_state.regs[reg].w = val; + cpu_state.regs[reg].w = val; else - setr8(reg, (uint8_t) (val & 0xff)); + setr8(reg, (uint8_t) (val & 0xff)); } - static void -cpu_data_opff_rm(void) { +cpu_data_opff_rm(void) +{ if (!(opcode & 1)) { - if (cpu_mod != 3) - cpu_data |= 0xff00; - else - cpu_data = cpu_state.regs[cpu_rm].w; + if (cpu_mod != 3) + cpu_data |= 0xff00; + else + cpu_data = cpu_state.regs[cpu_rm].w; } } +uint16_t +cpu_inw(uint16_t port) +{ + if (is8086 && !(port & 1)) { + wait(4, 0); + } else { + wait(8, 0); + } + + return inw(port); +} + +void +cpu_outw(uint16_t port, uint16_t val) +{ + if (is8086 && !(port & 1)) { + wait(4, 0); + } else { + wait(8, 0); + } + + return outw(port, val); +} /* Executes instructions up to the specified number of cycles. */ void execx86(int cycs) { - uint8_t temp = 0, temp2; - uint8_t old_af; - uint16_t addr, tempw; - uint16_t new_cs, new_ip; - int bits; + uint8_t temp = 0, temp2, old_af, nests; + uint8_t temp_val, temp_al, bit, handled = 0; + uint8_t odd, zero, nibbles_count, destcmp; + uint8_t destbyte, srcbyte, nibble_result, bit_length; + uint8_t bit_offset; + int8_t nibble_result_s; + uint16_t addr, tempw, new_cs, new_ip; + uint16_t tempw_int, size, tempbp, lowbound; + uint16_t highbound, regval, orig_sp, wordtopush; + uint16_t immediate, old_flags; + int bits; + uint32_t dest_seg, i, carry, nibble; + uint32_t srcseg, byteaddr; cycles += cycs; while (cycles > 0) { - clock_start(); + clock_start(); - if (!repeating) { - cpu_state.oldpc = cpu_state.pc; - opcode = pfq_fetchb(); - oldc = cpu_state.flags & C_FLAG; - if (clear_lock) { - in_lock = 0; - clear_lock = 0; - } - wait(1, 0); - } + if (!repeating) { + cpu_state.oldpc = cpu_state.pc; + opcode = pfq_fetchb(); + handled = 0; + oldc = cpu_state.flags & C_FLAG; + if (clear_lock) { + in_lock = 0; + clear_lock = 0; + } + wait(1, 0); + } - completed = 1; - // pclog("[%04X:%04X] Opcode: %02X\n", CS, cpu_state.pc, opcode); - switch (opcode) { - case 0x06: case 0x0E: case 0x16: case 0x1E: /* PUSH seg */ - access(29, 16); - push(&(_opseg[(opcode >> 3) & 0x03]->seg)); - break; - case 0x07: case 0x0F: case 0x17: case 0x1F: /* POP seg */ - access(22, 16); - if (opcode == 0x0F) { - load_cs(pop()); - pfq_pos = 0; - } else - load_seg(pop(), _opseg[(opcode >> 3) & 0x03]); - wait(1, 0); - /* All POP segment instructions suppress interrupts for one instruction. */ - noint = 1; - break; + completed = 1; + // pclog("[%04X:%04X] Opcode: %02X\n", CS, cpu_state.pc, opcode); + if (is186) { + switch (opcode) { + case 0x60: /*PUSHA/PUSH R*/ + orig_sp = SP; + wait(1, 0); + push(&AX); + push(&CX); + push(&DX); + push(&BX); + push(&orig_sp); + push(&BP); + push(&SI); + push(&DI); + handled = 1; + break; + case 0x61: /*POPA/POP R*/ + wait(9, 0); + DI = pop(); + SI = pop(); + BP = pop(); + (void) pop(); /* former orig_sp */ + BX = pop(); + DX = pop(); + CX = pop(); + AX = pop(); + handled = 1; + break; - case 0x26: /*ES:*/ - case 0x2E: /*CS:*/ - case 0x36: /*SS:*/ - case 0x3E: /*DS:*/ - wait(1, 0); - ovr_seg = opseg[(opcode >> 3) & 0x03]; - completed = 0; - break; + case 0x62: /* BOUND r/m */ + lowbound = 0; + highbound = 0; + regval = 0; + do_mod_rm(); - case 0x00: case 0x01: case 0x02: case 0x03: - case 0x08: case 0x09: case 0x0a: case 0x0b: - case 0x10: case 0x11: case 0x12: case 0x13: - case 0x18: case 0x19: case 0x1a: case 0x1b: - case 0x20: case 0x21: case 0x22: case 0x23: - case 0x28: case 0x29: case 0x2a: case 0x2b: - case 0x30: case 0x31: case 0x32: case 0x33: - case 0x38: case 0x39: case 0x3a: case 0x3b: - /* alu rm, r / r, rm */ - bits = 8 << (opcode & 1); - do_mod_rm(); - access(46, bits); - tempw = get_ea(); - cpu_alu_op = (opcode >> 3) & 7; - if ((opcode & 2) == 0) { - cpu_dest = tempw; - cpu_src = get_reg(cpu_reg); - } else { - cpu_dest = get_reg(cpu_reg); - cpu_src = tempw; - } - if (cpu_mod != 3) - wait(2, 0); - wait(1, 0); - alu_op(bits); - if (cpu_alu_op != 7) { - if ((opcode & 2) == 0) { - access(10, bits); - set_ea(cpu_data); - if (cpu_mod == 3) - wait(1, 0); - } else { - set_reg(cpu_reg, cpu_data); - wait(1, 0); - } - } else - wait(1, 0); - break; + lowbound = readmemw(easeg, cpu_state.eaaddr); + highbound = readmemw(easeg, cpu_state.eaaddr + 2); + regval = get_reg(cpu_reg); + if (lowbound > regval || highbound < regval) { + cpu_state.pc = cpu_state.oldpc; + interrupt(5); + } + handled = 1; + break; - case 0x04: case 0x05: case 0x0c: case 0x0d: - case 0x14: case 0x15: case 0x1c: case 0x1d: - case 0x24: case 0x25: case 0x2c: case 0x2d: - case 0x34: case 0x35: case 0x3c: case 0x3d: - /* alu A, imm */ - bits = 8 << (opcode & 1); - wait(1, 0); - cpu_data = pfq_fetch(); - cpu_dest = get_accum(bits); /* AX/AL */ - cpu_src = cpu_data; - cpu_alu_op = (opcode >> 3) & 7; - alu_op(bits); - if (cpu_alu_op != 7) - set_accum(bits, cpu_data); - wait(1, 0); - break; + case 0x64: + case 0x65: + if (is_nec) { + /* REPC/REPNC */ + wait(1, 0); + in_rep = (opcode == 0x64 ? 1 : 2); + rep_c_flag = 1; + completed = 0; + handled = 1; + } + break; - case 0x27: /*DAA*/ - cpu_dest = AL; - set_of(0); - old_af = !!(cpu_state.flags & A_FLAG); - if ((cpu_state.flags & A_FLAG) || (AL & 0x0f) > 9) { - cpu_src = 6; - cpu_data = cpu_dest + cpu_src; - set_of_add(8); - cpu_dest = cpu_data; - set_af(1); - } - if ((cpu_state.flags & C_FLAG) || AL > (old_af ? 0x9f : 0x99)) { - cpu_src = 0x60; - cpu_data = cpu_dest + cpu_src; - set_of_add(8); - cpu_dest = cpu_data; - set_cf(1); - } - AL = cpu_dest; - set_pzs(8); - wait(3, 0); - break; - case 0x2F: /*DAS*/ - cpu_dest = AL; - set_of(0); - old_af = !!(cpu_state.flags & A_FLAG); - if ((cpu_state.flags & A_FLAG) || ((AL & 0xf) > 9)) { - cpu_src = 6; - cpu_data = cpu_dest - cpu_src; - set_of_sub(8); - cpu_dest = cpu_data; - set_af(1); - } - if ((cpu_state.flags & C_FLAG) || AL > (old_af ? 0x9f : 0x99)) { - cpu_src = 0x60; - cpu_data = cpu_dest - cpu_src; - set_of_sub(8); - cpu_dest = cpu_data; - set_cf(1); - } - AL = cpu_dest; - set_pzs(8); - wait(3, 0); - break; - case 0x37: /*AAA*/ - wait(1, 0); - if ((cpu_state.flags & A_FLAG) || ((AL & 0xf) > 9)) { - cpu_src = 6; - ++AH; - set_ca(); - } else { - cpu_src = 0; - clear_ca(); - wait(1, 0); - } - cpu_dest = AL; - cpu_data = cpu_dest + cpu_src; - set_of_add(8); - aa(); - break; - case 0x3F: /*AAS*/ - wait(1, 0); - if ((cpu_state.flags & A_FLAG) || ((AL & 0xf) > 9)) { - cpu_src = 6; - --AH; - set_ca(); - } else { - cpu_src = 0; - clear_ca(); - wait(1, 0); - } - cpu_dest = AL; - cpu_data = cpu_dest - cpu_src; - set_of_sub(8); - aa(); - break; + case 0x68: + wordtopush = pfq_fetchw(); + wait(1, 0); + push(&wordtopush); + handled = 1; + break; - case 0x40: case 0x41: case 0x42: case 0x43: - case 0x44: case 0x45: case 0x46: case 0x47: - case 0x48: case 0x49: case 0x4A: case 0x4B: - case 0x4C: case 0x4D: case 0x4E: case 0x4F: - /* INCDEC rw */ - wait(1, 0); - cpu_dest = cpu_state.regs[opcode & 7].w; - cpu_src = 1; - bits = 16; - if ((opcode & 8) == 0) { - cpu_data = cpu_dest + cpu_src; - set_of_add(bits); - } else { - cpu_data = cpu_dest - cpu_src; - set_of_sub(bits); - } - do_af(); - set_pzs(16); - cpu_state.regs[opcode & 7].w = cpu_data; - break; + case 0x69: + immediate = 0; + bits = 16; + do_mod_rm(); + read_ea(0, 16); + immediate = pfq_fetchw(); + mul(cpu_data & 0xFFFF, immediate); + set_reg(cpu_reg, cpu_data); + set_co_mul(16, cpu_dest != 0); + handled = 1; + break; - case 0x50: case 0x51: case 0x52: case 0x53: /*PUSH r16*/ - case 0x54: case 0x55: case 0x56: case 0x57: - access(30, 16); - push(&(cpu_state.regs[opcode & 0x07].w)); - break; - case 0x58: case 0x59: case 0x5A: case 0x5B: /*POP r16*/ - case 0x5C: case 0x5D: case 0x5E: case 0x5F: - access(23, 16); - cpu_state.regs[opcode & 0x07].w = pop(); - wait(1, 0); - break; + case 0x6a: + wordtopush = sign_extend(pfq_fetchb()); + push(&wordtopush); + handled = 1; + break; - case 0x60: /*JO alias*/ - case 0x70: /*JO*/ - case 0x61: /*JNO alias*/ - case 0x71: /*JNO*/ - jcc(opcode, cpu_state.flags & V_FLAG); - break; - case 0x62: /*JB alias*/ - case 0x72: /*JB*/ - case 0x63: /*JNB alias*/ - case 0x73: /*JNB*/ - jcc(opcode, cpu_state.flags & C_FLAG); - break; - case 0x64: /*JE alias*/ - case 0x74: /*JE*/ - case 0x65: /*JNE alias*/ - case 0x75: /*JNE*/ - jcc(opcode, cpu_state.flags & Z_FLAG); - break; - case 0x66: /*JBE alias*/ - case 0x76: /*JBE*/ - case 0x67: /*JNBE alias*/ - case 0x77: /*JNBE*/ - jcc(opcode, cpu_state.flags & (C_FLAG | Z_FLAG)); - break; - case 0x68: /*JS alias*/ - case 0x78: /*JS*/ - case 0x69: /*JNS alias*/ - case 0x79: /*JNS*/ - jcc(opcode, cpu_state.flags & N_FLAG); - break; - case 0x6A: /*JP alias*/ - case 0x7A: /*JP*/ - case 0x6B: /*JNP alias*/ - case 0x7B: /*JNP*/ - jcc(opcode, cpu_state.flags & P_FLAG); - break; - case 0x6C: /*JL alias*/ - case 0x7C: /*JL*/ - case 0x6D: /*JNL alias*/ - case 0x7D: /*JNL*/ - temp = (cpu_state.flags & N_FLAG) ? 1 : 0; - temp2 = (cpu_state.flags & V_FLAG) ? 1 : 0; - jcc(opcode, temp ^ temp2); - break; - case 0x6E: /*JLE alias*/ - case 0x7E: /*JLE*/ - case 0x6F: /*JNLE alias*/ - case 0x7F: /*JNLE*/ - temp = (cpu_state.flags & N_FLAG) ? 1 : 0; - temp2 = (cpu_state.flags & V_FLAG) ? 1 : 0; - jcc(opcode, (cpu_state.flags & Z_FLAG) || (temp != temp2)); - break; + case 0x6b: /* IMUL reg16,reg16/mem16,imm8 */ + immediate = 0; + bits = 16; + do_mod_rm(); + read_ea(0, 16); + immediate = pfq_fetchb(); + mul(cpu_data & 0xFFFF, immediate); + set_reg(cpu_reg, cpu_data); + set_co_mul(16, cpu_dest != 0); + handled = 1; + break; - case 0x80: case 0x81: case 0x82: case 0x83: - /* alu rm, imm */ - bits = 8 << (opcode & 1); - do_mod_rm(); - access(47, bits); - cpu_data = get_ea(); - cpu_dest = cpu_data; - if (cpu_mod != 3) - wait(3, 0); - if (opcode == 0x81) { - if (cpu_mod == 3) - wait(1, 0); - cpu_src = pfq_fetchw(); - } else { - if (cpu_mod == 3) - wait(1, 0); - if (opcode == 0x83) - cpu_src = sign_extend(pfq_fetchb()); - else - cpu_src = pfq_fetchb() | 0xff00; - } - wait(1, 0); - cpu_alu_op = (rmdat & 0x38) >> 3; - alu_op(bits); - if (cpu_alu_op != 7) { - access(11, bits); - set_ea(cpu_data); - } else { - if (cpu_mod != 3) - wait(1, 0); - } - break; + case 0x6c: + case 0x6d: /* INM dst, DW/INS dst, DX */ + bits = 8 << (opcode & 1); + handled = 1; + if (!repeating) + wait(2, 0); - case 0x84: case 0x85: - /* TEST rm, reg */ - bits = 8 << (opcode & 1); - do_mod_rm(); - access(48, bits); - cpu_data = get_ea(); - test(bits, cpu_data, get_reg(cpu_reg)); - if (cpu_mod == 3) - wait(2, 0); - wait(2, 0); - break; - case 0x86: case 0x87: - /* XCHG rm, reg */ - bits = 8 << (opcode & 1); - do_mod_rm(); - access(49, bits); - cpu_data = get_ea(); - cpu_src = get_reg(cpu_reg); - set_reg(cpu_reg, cpu_data); - wait(3, 0); - access(12, bits); - set_ea(cpu_src); - break; + if (rep_action(bits)) + break; + else if (!repeating) + wait(7, 0); - case 0x88: case 0x89: - /* MOV rm, reg */ - bits = 8 << (opcode & 1); - do_mod_rm(); - wait(1, 0); - access(13, bits); - set_ea(get_reg(cpu_reg)); - break; - case 0x8A: case 0x8B: - /* MOV reg, rm */ - bits = 8 << (opcode & 1); - do_mod_rm(); - access(50, bits); - set_reg(cpu_reg, get_ea()); - wait(1, 0); - if (cpu_mod != 3) - wait(2, 0); - break; + if (bits == 16) { + writememw(es, DI, cpu_inw(DX)); + DI += (cpu_state.flags & D_FLAG) ? -2 : 2; + } else { + wait(4, 0); + writememb(es, DI, inb(DX)); + DI += (cpu_state.flags & D_FLAG) ? -1 : 1; + } - case 0x8C: /*MOV w,sreg*/ - do_mod_rm(); - if (cpu_mod == 3) - wait(1, 0); - access(14, 16); - seteaw(_opseg[(rmdat & 0x18) >> 3]->seg); - break; + if (in_rep == 0) + break; - case 0x8D: /*LEA*/ - do_mod_rm(); - cpu_state.regs[cpu_reg].w = cpu_state.eaaddr; - wait(1, 0); - if (cpu_mod != 3) - wait(2, 0); - break; + repeating = 1; + clock_end(); + break; - case 0x8E: /*MOV sreg,w*/ - do_mod_rm(); - access(51, 16); - tempw = geteaw(); - if ((rmdat & 0x18) == 0x08) { - load_cs(tempw); - pfq_pos = 0; - } else - load_seg(tempw, _opseg[(rmdat & 0x18) >> 3]); - wait(1, 0); - if (cpu_mod != 3) - wait(2, 0); - if (((rmdat & 0x18) >> 3) == 2) - noint = 1; - break; + case 0x6e: + case 0x6f: /* OUTM DW, src/OUTS DX, src */ + dest_seg = ovr_seg ? *ovr_seg : ds; + bits = 8 << (opcode & 1); + handled = 1; + if (!repeating) + wait(2, 0); - case 0x8F: /*POPW*/ - do_mod_rm(); - wait(1, 0); - cpu_src = cpu_state.eaaddr; - access(24, 16); - if (cpu_mod != 3) - wait(2, 0); - cpu_data = pop(); - cpu_state.eaaddr = cpu_src; - wait(2, 0); - access(15, 16); - seteaw(cpu_data); - break; + if (rep_action(bits)) + break; + else if (!repeating) + wait(7, 0); - case 0x90: case 0x91: case 0x92: case 0x93: - case 0x94: case 0x95: case 0x96: case 0x97: - /* XCHG AX, rw */ - wait(1, 0); - cpu_data = cpu_state.regs[opcode & 7].w; - cpu_state.regs[opcode & 7].w = AX; - AX = cpu_data; - wait(1, 0); - break; + if (bits == 16) { + cpu_outw(DX, readmemw(dest_seg, SI)); + SI += (cpu_state.flags & D_FLAG) ? -2 : 2; + } else { + wait(4, 0); + outb(DX, readmemb(dest_seg + SI)); + SI += (cpu_state.flags & D_FLAG) ? -1 : 1; + } + if (in_rep == 0) + break; - case 0x98: /*CBW*/ - wait(1, 0); - AX = sign_extend(AL); - break; - case 0x99: /*CWD*/ - wait(4, 0); - if (!top_bit(AX, 16)) - DX = 0; - else { - wait(1, 0); - DX = 0xffff; - } - break; - case 0x9A: /*CALL FAR*/ - wait(1, 0); - new_ip = pfq_fetchw(); - wait(1, 0); - new_cs = pfq_fetchw(); - pfq_clear(); - access(31, 16); - push(&(CS)); - access(60, 16); - cpu_state.oldpc = cpu_state.pc; - load_cs(new_cs); - set_ip(new_ip); - access(32, 16); - push((uint16_t *) &(cpu_state.oldpc)); - break; - case 0x9B: /*WAIT*/ - if (!repeating) - wait(2, 0); - wait(5, 0); + repeating = 1; + clock_end(); + break; + + case 0xc8: /* ENTER/PREPARE */ + tempw_int = 0; + size = pfq_fetchw(); + nests = pfq_fetchb(); + i = 0; + + push(&BP); + tempw_int = SP; + if (nests > 0) { + while (--nests) { + tempbp = 0; + BP -= 2; + tempbp = readmemw(ss, BP); + push(&tempbp); + } + push(&tempw_int); + } + BP = tempw_int; + SP -= size; + handled = 1; + break; + + case 0xc0: + case 0xc1: /*rot imm8 */ + bits = 8 << (opcode & 1); + do_mod_rm(); + if (cpu_mod == 3) + wait(1, 0); + access(53, bits); + cpu_data = get_ea(); + cpu_src = pfq_fetchb(); + + wait((cpu_mod != 3) ? 9 : 6, 0); + + if (!is_nec) + cpu_src &= 0x1F; + while (cpu_src != 0) { + cpu_dest = cpu_data; + oldc = cpu_state.flags & C_FLAG; + switch (rmdat & 0x38) { + case 0x00: /* ROL */ + set_cf(top_bit(cpu_data, bits)); + cpu_data <<= 1; + cpu_data |= ((cpu_state.flags & C_FLAG) ? 1 : 0); + set_of_rotate(bits); + set_af(0); + break; + case 0x08: /* ROR */ + set_cf((cpu_data & 1) != 0); + cpu_data >>= 1; + if (cpu_state.flags & C_FLAG) + cpu_data |= (!(opcode & 1) ? 0x80 : 0x8000); + set_of_rotate(bits); + set_af(0); + break; + case 0x10: /* RCL */ + set_cf(top_bit(cpu_data, bits)); + cpu_data = (cpu_data << 1) | (oldc ? 1 : 0); + set_of_rotate(bits); + set_af(0); + break; + case 0x18: /* RCR */ + set_cf((cpu_data & 1) != 0); + cpu_data >>= 1; + if (oldc) + cpu_data |= (!(opcode & 0x01) ? 0x80 : 0x8000); + set_cf((cpu_dest & 1) != 0); + set_of_rotate(bits); + set_af(0); + break; + case 0x20: /* SHL */ + set_cf(top_bit(cpu_data, bits)); + cpu_data <<= 1; + set_of_rotate(bits); + set_af((cpu_data & 0x10) != 0); + set_pzs(bits); + break; + case 0x28: /* SHR */ + set_cf((cpu_data & 1) != 0); + cpu_data >>= 1; + set_of_rotate(bits); + set_af(0); + set_pzs(bits); + break; + case 0x30: /* SETMO - undocumented? */ + bitwise(bits, 0xffff); + set_cf(0); + set_of_rotate(bits); + set_af(0); + set_pzs(bits); + break; + case 0x38: /* SAR */ + set_cf((cpu_data & 1) != 0); + cpu_data >>= 1; + if (!(opcode & 1)) + cpu_data |= (cpu_dest & 0x80); + else + cpu_data |= (cpu_dest & 0x8000); + set_of_rotate(bits); + set_af(0); + set_pzs(bits); + break; + } + if ((opcode & 2) != 0) + wait(4, 0); + --cpu_src; + } + access(17, bits); + set_ea(cpu_data); + handled = 1; + break; + + case 0xc9: /* LEAVE/DISPOSE */ + SP = BP; + BP = pop(); + handled = 1; + break; + } + } + if (!handled) { + switch (opcode) { + case 0x06: + case 0x0E: + case 0x16: + case 0x1E: /* PUSH seg */ + access(29, 16); + push(&(_opseg[(opcode >> 3) & 0x03]->seg)); + break; + case 0x07: + case 0x0F: + case 0x17: + case 0x1F: /* POP seg */ + if (is_nec && (opcode == 0x0F)) { + uint8_t orig_opcode = opcode; + opcode = pfq_fetchb(); + switch (opcode) { + case 0x28: /* ROL4 r/m */ + do_mod_rm(); + wait(21, 0); + + temp_val = geteab(); + temp_al = AL; + + temp_al &= 0xF; + temp_al |= (temp_val & 0xF0); + temp_val = (temp_al & 0xF) | ((temp_val & 0xF) << 4); + temp_al >>= 4; + temp_al &= 0xF; + seteab(temp_val); + AL = temp_al; + + handled = 1; + break; + + case 0x2a: /* ROR4 r/m */ + do_mod_rm(); + wait(21, 0); + + temp_val = geteab(); + temp_al = AL; + + AL = temp_val & 0xF; + temp_val = (temp_val >> 4) | ((temp_al & 0xF) << 4); + + seteab(temp_val); + + handled = 1; + break; + + case 0x10: /* TEST1 r8/m8, CL*/ + case 0x11: /* TEST1 r16/m16, CL*/ + case 0x18: /* TEST1 r8/m8, imm3 */ + case 0x19: /* TEST1 r16/m16, imm4 */ + bits = 8 << (opcode & 0x1); + do_mod_rm(); + wait(3, 0); + + bit = (opcode & 0x8) ? (pfq_fetchb()) : (CL); + bit &= ((1 << (3 + (opcode & 0x1))) - 1); + read_ea(0, bits); + + set_zf_ex(!(cpu_data & (1 << bit))); + cpu_state.flags &= ~(V_FLAG | C_FLAG); + + handled = 1; + break; + + case 0x16: /* NOT1 r8/m8, CL*/ + case 0x17: /* NOT1 r16/m16, CL*/ + case 0x1e: /* NOT1 r8/m8, imm3 */ + case 0x1f: /* NOT1 r16/m16, imm4 */ + bits = 8 << (opcode & 0x1); + do_mod_rm(); + wait(3, 0); + + bit = (opcode & 0x8) ? (pfq_fetchb()) : (CL); + bit &= ((1 << (3 + (opcode & 0x1))) - 1); + read_ea(0, bits); + + if (bits == 8) + seteab((cpu_data & 0xFF) ^ (1 << bit)); + else + seteaw((cpu_data & 0xFFFF) ^ (1 << bit)); + + handled = 1; + break; + + case 0x14: /* SET1 r8/m8, CL*/ + case 0x15: /* SET1 r16/m16, CL*/ + case 0x1c: /* SET1 r8/m8, imm3 */ + case 0x1d: /* SET1 r16/m16, imm4 */ + bits = 8 << (opcode & 0x1); + do_mod_rm(); + wait(3, 0); + + bit = (opcode & 0x8) ? (pfq_fetchb()) : (CL); + bit &= ((1 << (3 + (opcode & 0x1))) - 1); + read_ea(0, bits); + + if (bits == 8) + seteab((cpu_data & 0xFF) | (1 << bit)); + else + seteaw((cpu_data & 0xFFFF) | (1 << bit)); + + handled = 1; + break; + + case 0x12: /* CLR1 r8/m8, CL*/ + case 0x13: /* CLR1 r16/m16, CL*/ + case 0x1a: /* CLR1 r8/m8, imm3 */ + case 0x1b: /* CLR1 r16/m16, imm4 */ + bits = 8 << (opcode & 0x1); + do_mod_rm(); + wait(3, 0); + + bit = (opcode & 0x8) ? (pfq_fetchb()) : (CL); + bit &= ((1 << (3 + (opcode & 0x1))) - 1); + read_ea(0, bits); + + if (bits == 8) + seteab((cpu_data & 0xFF) & ~(1 << bit)); + else + seteaw((cpu_data & 0xFFFF) & ~(1 << bit)); + + handled = 1; + break; + + case 0x20: /* ADD4S */ + odd = !!(CL % 2); + zero = 1; + nibbles_count = CL - odd; + i = 0; + carry = 0; + nibble = 0; + srcseg = ovr_seg ? *ovr_seg : ds; + + wait(5, 0); + for (i = 0; i < ((nibbles_count / 2) + odd); i++) { + wait(19, 0); + destcmp = read_mem_b((es) + DI + i); + for (nibble = 0; nibble < 2; nibble++) { + destbyte = destcmp >> (nibble ? 4 : 0); + srcbyte = read_mem_b(srcseg + SI + i) >> (nibble ? 4 : 0); + destbyte &= 0xF; + srcbyte &= 0xF; + nibble_result = (i == (nibbles_count / 2) && nibble == 1) ? (destbyte + carry) : ((uint8_t) (destbyte)) + ((uint8_t) (srcbyte)) + ((uint32_t) carry); + carry = 0; + while (nibble_result >= 10) { + nibble_result -= 10; + carry++; + } + if (zero != 0 || (i == (nibbles_count / 2) && nibble == 1)) + zero = (nibble_result == 0); + destcmp = ((destcmp & (nibble ? 0x0F : 0xF0)) | (nibble_result << (4 * nibble))); + } + write_mem_b(es + DI + i, destcmp); + } + set_cf(!!carry); + set_zf(!!zero); + handled = 1; + break; + + case 0x22: /* SUB4S */ + odd = !!(CL % 2); + zero = 1; + nibbles_count = CL - odd; + i = 0; + carry = 0; + nibble = 0; + srcseg = ovr_seg ? *ovr_seg : ds; + + wait(5, 0); + for (i = 0; i < ((nibbles_count / 2) + odd); i++) { + wait(19, 0); + destcmp = read_mem_b((es) + DI + i); + for (nibble = 0; nibble < 2; nibble++) { + destbyte = destcmp >> (nibble ? 4 : 0); + srcbyte = read_mem_b(srcseg + SI + i) >> (nibble ? 4 : 0); + destbyte &= 0xF; + srcbyte &= 0xF; + nibble_result_s = (i == (nibbles_count / 2) && nibble == 1) ? ((int8_t) destbyte - (int8_t) carry) : ((int8_t) (destbyte)) - ((int8_t) (srcbyte)) - ((int8_t) carry); + carry = 0; + while (nibble_result_s < 0) { + nibble_result_s += 10; + carry++; + } + if (zero != 0 || (i == (nibbles_count / 2) && nibble == 1)) + zero = (nibble_result_s == 0); + destcmp = ((destcmp & (nibble ? 0x0F : 0xF0)) | (nibble_result_s << (4 * nibble))); + } + write_mem_b(es + DI + i, destcmp); + } + set_cf(!!carry); + set_zf(!!zero); + handled = 1; + break; + + case 0x26: /* CMP4S */ + odd = !!(CL % 2); + zero = 1; + nibbles_count = CL - odd; + i = 0; + carry = 0; + nibble = 0; + srcseg = ovr_seg ? *ovr_seg : ds; + + wait(5, 0); + for (i = 0; i < ((nibbles_count / 2) + odd); i++) { + wait(19, 0); + destcmp = read_mem_b((es) + DI + i); + for (nibble = 0; nibble < 2; nibble++) { + destbyte = destcmp >> (nibble ? 4 : 0); + srcbyte = read_mem_b(srcseg + SI + i) >> (nibble ? 4 : 0); + destbyte &= 0xF; + srcbyte &= 0xF; + nibble_result_s = ((int8_t) (destbyte)) - ((int8_t) (srcbyte)) - ((int8_t) carry); + carry = 0; + while (nibble_result_s < 0) { + nibble_result_s += 10; + carry++; + } + if (zero != 0 || (i == (nibbles_count / 2) && nibble == 1)) + zero = (nibble_result_s == 0); + destcmp = ((destcmp & (nibble ? 0x0F : 0xF0)) | (nibble_result_s << (4 * nibble))); + } + } + set_cf(!!carry); + set_zf(!!zero); + handled = 1; + break; + + case 0x31: /* INS reg1, reg2 */ + case 0x39: /* INS reg8, imm4 */ + do_mod_rm(); + wait(1, 0); + + bit_length = ((opcode & 0x8) ? (pfq_fetchb() & 0xF) : (getr8(cpu_reg) & 0xF)) + 1; + bit_offset = getr8(cpu_rm) & 0xF; + byteaddr = (es) + DI; + i = 0; + + if (bit_offset >= 8) { + DI++; + byteaddr++; + bit_offset -= 8; + } + for (i = 0; i < bit_length; i++) { + byteaddr = (es) + DI; + writememb(es, DI, (read_mem_b(byteaddr) & ~(1 << (bit_offset))) | ((!!(AX & (1 << i))) << bit_offset)); + bit_offset++; + if (bit_offset == 8) { + DI++; + bit_offset = 0; + } + } + setr8(cpu_rm, bit_offset); + + handled = 1; + break; + + case 0x33: /* EXT reg1, reg2 */ + case 0x3b: /* EXT reg8, imm4 */ + do_mod_rm(); + wait(1, 0); + + bit_length = ((opcode & 0x8) ? (pfq_fetchb() & 0xF) : (getr8(cpu_reg) & 0xF)) + 1; + bit_offset = getr8(cpu_rm) & 0xF; + byteaddr = (ds) + SI; + i = 0; + + if (bit_offset >= 8) { + SI++; + byteaddr++; + bit_offset -= 8; + } + + AX = 0; + for (i = 0; i < bit_length; i++) { + byteaddr = (ds) + SI; + AX |= (!!(readmemb(byteaddr) & (1 << bit_offset))) << i; + bit_offset++; + if (bit_offset == 8) { + SI++; + bit_offset = 0; + } + } + setr8(cpu_rm, bit_offset); + + handled = 1; + break; + + case 0xFF: /* BRKEM */ + /* Unimplemented for now. */ + fatal("808x: Unsupported 8080 emulation mode attempted to enter into!"); + break; + + default: + opcode = orig_opcode; + cpu_state.pc--; + break; + } + } else + handled = 0; + if (handled) + break; + access(22, 16); + if (opcode == 0x0F) { + load_cs(pop()); + pfq_pos = 0; + } else + load_seg(pop(), _opseg[(opcode >> 3) & 0x03]); + wait(1, 0); + /* All POP segment instructions suppress interrupts for one instruction. */ + noint = 1; + break; + + case 0x26: /*ES:*/ + case 0x2E: /*CS:*/ + case 0x36: /*SS:*/ + case 0x3E: /*DS:*/ + wait(1, 0); + ovr_seg = opseg[(opcode >> 3) & 0x03]; + completed = 0; + break; + + case 0x00: + case 0x01: + case 0x02: + case 0x03: + case 0x08: + case 0x09: + case 0x0a: + case 0x0b: + case 0x10: + case 0x11: + case 0x12: + case 0x13: + case 0x18: + case 0x19: + case 0x1a: + case 0x1b: + case 0x20: + case 0x21: + case 0x22: + case 0x23: + case 0x28: + case 0x29: + case 0x2a: + case 0x2b: + case 0x30: + case 0x31: + case 0x32: + case 0x33: + case 0x38: + case 0x39: + case 0x3a: + case 0x3b: + /* alu rm, r / r, rm */ + bits = 8 << (opcode & 1); + do_mod_rm(); + access(46, bits); + tempw = get_ea(); + cpu_alu_op = (opcode >> 3) & 7; + if ((opcode & 2) == 0) { + cpu_dest = tempw; + cpu_src = get_reg(cpu_reg); + } else { + cpu_dest = get_reg(cpu_reg); + cpu_src = tempw; + } + if (cpu_mod != 3) + wait(2, 0); + wait(1, 0); + alu_op(bits); + if (cpu_alu_op != 7) { + if ((opcode & 2) == 0) { + access(10, bits); + set_ea(cpu_data); + if (cpu_mod == 3) + wait(1, 0); + } else { + set_reg(cpu_reg, cpu_data); + wait(1, 0); + } + } else + wait(1, 0); + break; + + case 0x04: + case 0x05: + case 0x0c: + case 0x0d: + case 0x14: + case 0x15: + case 0x1c: + case 0x1d: + case 0x24: + case 0x25: + case 0x2c: + case 0x2d: + case 0x34: + case 0x35: + case 0x3c: + case 0x3d: + /* alu A, imm */ + bits = 8 << (opcode & 1); + wait(1, 0); + cpu_data = pfq_fetch(); + cpu_dest = get_accum(bits); /* AX/AL */ + cpu_src = cpu_data; + cpu_alu_op = (opcode >> 3) & 7; + alu_op(bits); + if (cpu_alu_op != 7) + set_accum(bits, cpu_data); + wait(1, 0); + break; + + case 0x27: /*DAA*/ + cpu_dest = AL; + set_of(0); + old_af = !!(cpu_state.flags & A_FLAG); + if ((cpu_state.flags & A_FLAG) || (AL & 0x0f) > 9) { + cpu_src = 6; + cpu_data = cpu_dest + cpu_src; + set_of_add(8); + cpu_dest = cpu_data; + set_af(1); + } + if ((cpu_state.flags & C_FLAG) || AL > (old_af ? 0x9f : 0x99)) { + cpu_src = 0x60; + cpu_data = cpu_dest + cpu_src; + set_of_add(8); + cpu_dest = cpu_data; + set_cf(1); + } + AL = cpu_dest; + set_pzs(8); + wait(3, 0); + break; + case 0x2F: /*DAS*/ + cpu_dest = AL; + set_of(0); + old_af = !!(cpu_state.flags & A_FLAG); + if ((cpu_state.flags & A_FLAG) || ((AL & 0xf) > 9)) { + cpu_src = 6; + cpu_data = cpu_dest - cpu_src; + set_of_sub(8); + cpu_dest = cpu_data; + set_af(1); + } + if ((cpu_state.flags & C_FLAG) || AL > (old_af ? 0x9f : 0x99)) { + cpu_src = 0x60; + cpu_data = cpu_dest - cpu_src; + set_of_sub(8); + cpu_dest = cpu_data; + set_cf(1); + } + AL = cpu_dest; + set_pzs(8); + wait(3, 0); + break; + case 0x37: /*AAA*/ + wait(1, 0); + if ((cpu_state.flags & A_FLAG) || ((AL & 0xf) > 9)) { + cpu_src = 6; + ++AH; + set_ca(); + } else { + cpu_src = 0; + clear_ca(); + wait(1, 0); + } + cpu_dest = AL; + cpu_data = cpu_dest + cpu_src; + set_of_add(8); + aa(); + break; + case 0x3F: /*AAS*/ + wait(1, 0); + if ((cpu_state.flags & A_FLAG) || ((AL & 0xf) > 9)) { + cpu_src = 6; + --AH; + set_ca(); + } else { + cpu_src = 0; + clear_ca(); + wait(1, 0); + } + cpu_dest = AL; + cpu_data = cpu_dest - cpu_src; + set_of_sub(8); + aa(); + break; + + case 0x40: + case 0x41: + case 0x42: + case 0x43: + case 0x44: + case 0x45: + case 0x46: + case 0x47: + case 0x48: + case 0x49: + case 0x4A: + case 0x4B: + case 0x4C: + case 0x4D: + case 0x4E: + case 0x4F: + /* INCDEC rw */ + wait(1, 0); + cpu_dest = cpu_state.regs[opcode & 7].w; + cpu_src = 1; + bits = 16; + if ((opcode & 8) == 0) { + cpu_data = cpu_dest + cpu_src; + set_of_add(bits); + } else { + cpu_data = cpu_dest - cpu_src; + set_of_sub(bits); + } + do_af(); + set_pzs(16); + cpu_state.regs[opcode & 7].w = cpu_data; + break; + + case 0x50: + case 0x51: + case 0x52: + case 0x53: /*PUSH r16*/ + case 0x54: + case 0x55: + case 0x56: + case 0x57: + access(30, 16); + push(&(cpu_state.regs[opcode & 0x07].w)); + break; + case 0x58: + case 0x59: + case 0x5A: + case 0x5B: /*POP r16*/ + case 0x5C: + case 0x5D: + case 0x5E: + case 0x5F: + access(23, 16); + cpu_state.regs[opcode & 0x07].w = pop(); + wait(1, 0); + break; + + case 0x60: /*JO alias*/ + case 0x70: /*JO*/ + case 0x61: /*JNO alias*/ + case 0x71: /*JNO*/ + jcc(opcode, cpu_state.flags & V_FLAG); + break; + case 0x62: /*JB alias*/ + case 0x72: /*JB*/ + case 0x63: /*JNB alias*/ + case 0x73: /*JNB*/ + jcc(opcode, cpu_state.flags & C_FLAG); + break; + case 0x64: /*JE alias*/ + case 0x74: /*JE*/ + case 0x65: /*JNE alias*/ + case 0x75: /*JNE*/ + jcc(opcode, cpu_state.flags & Z_FLAG); + break; + case 0x66: /*JBE alias*/ + case 0x76: /*JBE*/ + case 0x67: /*JNBE alias*/ + case 0x77: /*JNBE*/ + jcc(opcode, cpu_state.flags & (C_FLAG | Z_FLAG)); + break; + case 0x68: /*JS alias*/ + case 0x78: /*JS*/ + case 0x69: /*JNS alias*/ + case 0x79: /*JNS*/ + jcc(opcode, cpu_state.flags & N_FLAG); + break; + case 0x6A: /*JP alias*/ + case 0x7A: /*JP*/ + case 0x6B: /*JNP alias*/ + case 0x7B: /*JNP*/ + jcc(opcode, cpu_state.flags & P_FLAG); + break; + case 0x6C: /*JL alias*/ + case 0x7C: /*JL*/ + case 0x6D: /*JNL alias*/ + case 0x7D: /*JNL*/ + temp = (cpu_state.flags & N_FLAG) ? 1 : 0; + temp2 = (cpu_state.flags & V_FLAG) ? 1 : 0; + jcc(opcode, temp ^ temp2); + break; + case 0x6E: /*JLE alias*/ + case 0x7E: /*JLE*/ + case 0x6F: /*JNLE alias*/ + case 0x7F: /*JNLE*/ + temp = (cpu_state.flags & N_FLAG) ? 1 : 0; + temp2 = (cpu_state.flags & V_FLAG) ? 1 : 0; + jcc(opcode, (cpu_state.flags & Z_FLAG) || (temp != temp2)); + break; + + case 0x80: + case 0x81: + case 0x82: + case 0x83: + /* alu rm, imm */ + bits = 8 << (opcode & 1); + do_mod_rm(); + access(47, bits); + cpu_data = get_ea(); + cpu_dest = cpu_data; + if (cpu_mod != 3) + wait(3, 0); + if (opcode == 0x81) { + if (cpu_mod == 3) + wait(1, 0); + cpu_src = pfq_fetchw(); + } else { + if (cpu_mod == 3) + wait(1, 0); + if (opcode == 0x83) + cpu_src = sign_extend(pfq_fetchb()); + else + cpu_src = pfq_fetchb() | 0xff00; + } + wait(1, 0); + cpu_alu_op = (rmdat & 0x38) >> 3; + alu_op(bits); + if (cpu_alu_op != 7) { + access(11, bits); + set_ea(cpu_data); + } else { + if (cpu_mod != 3) + wait(1, 0); + } + break; + + case 0x84: + case 0x85: + /* TEST rm, reg */ + bits = 8 << (opcode & 1); + do_mod_rm(); + access(48, bits); + cpu_data = get_ea(); + test(bits, cpu_data, get_reg(cpu_reg)); + if (cpu_mod == 3) + wait(2, 0); + wait(2, 0); + break; + case 0x86: + case 0x87: + /* XCHG rm, reg */ + bits = 8 << (opcode & 1); + do_mod_rm(); + access(49, bits); + cpu_data = get_ea(); + cpu_src = get_reg(cpu_reg); + set_reg(cpu_reg, cpu_data); + wait(3, 0); + access(12, bits); + set_ea(cpu_src); + break; + + case 0x88: + case 0x89: + /* MOV rm, reg */ + bits = 8 << (opcode & 1); + do_mod_rm(); + wait(1, 0); + access(13, bits); + set_ea(get_reg(cpu_reg)); + break; + case 0x8A: + case 0x8B: + /* MOV reg, rm */ + bits = 8 << (opcode & 1); + do_mod_rm(); + access(50, bits); + set_reg(cpu_reg, get_ea()); + wait(1, 0); + if (cpu_mod != 3) + wait(2, 0); + break; + + case 0x8C: /*MOV w,sreg*/ + do_mod_rm(); + if (cpu_mod == 3) + wait(1, 0); + access(14, 16); + seteaw(_opseg[(rmdat & 0x18) >> 3]->seg); + break; + + case 0x8D: /*LEA*/ + do_mod_rm(); + cpu_state.regs[cpu_reg].w = cpu_state.eaaddr; + wait(1, 0); + if (cpu_mod != 3) + wait(2, 0); + break; + + case 0x8E: /*MOV sreg,w*/ + do_mod_rm(); + access(51, 16); + tempw = geteaw(); + if ((rmdat & 0x18) == 0x08) { + load_cs(tempw); + pfq_pos = 0; + } else + load_seg(tempw, _opseg[(rmdat & 0x18) >> 3]); + wait(1, 0); + if (cpu_mod != 3) + wait(2, 0); + if (((rmdat & 0x18) >> 3) == 2) + noint = 1; + break; + + case 0x8F: /*POPW*/ + do_mod_rm(); + wait(1, 0); + cpu_src = cpu_state.eaaddr; + access(24, 16); + if (cpu_mod != 3) + wait(2, 0); + cpu_data = pop(); + cpu_state.eaaddr = cpu_src; + wait(2, 0); + access(15, 16); + seteaw(cpu_data); + break; + + case 0x90: + case 0x91: + case 0x92: + case 0x93: + case 0x94: + case 0x95: + case 0x96: + case 0x97: + /* XCHG AX, rw */ + wait(1, 0); + cpu_data = cpu_state.regs[opcode & 7].w; + cpu_state.regs[opcode & 7].w = AX; + AX = cpu_data; + wait(1, 0); + break; + + case 0x98: /*CBW*/ + wait(1, 0); + AX = sign_extend(AL); + break; + case 0x99: /*CWD*/ + wait(4, 0); + if (!top_bit(AX, 16)) + DX = 0; + else { + wait(1, 0); + DX = 0xffff; + } + break; + case 0x9A: /*CALL FAR*/ + wait(1, 0); + new_ip = pfq_fetchw(); + wait(1, 0); + new_cs = pfq_fetchw(); + pfq_clear(); + access(31, 16); + push(&(CS)); + access(60, 16); + cpu_state.oldpc = cpu_state.pc; + load_cs(new_cs); + set_ip(new_ip); + access(32, 16); + push((uint16_t *) &(cpu_state.oldpc)); + break; + case 0x9B: /*WAIT*/ + if (!repeating) + wait(2, 0); + wait(5, 0); #ifdef NO_HACK - if (irq_pending()) { - wait(7, 0); - check_interrupts(); - } else { - repeating = 1; - completed = 0; - clock_end(); - } + if (irq_pending()) { + wait(7, 0); + check_interrupts(); + } else { + repeating = 1; + completed = 0; + clock_end(); + } #else - wait(7, 0); - check_interrupts(); + wait(7, 0); + check_interrupts(); #endif - break; - case 0x9C: /*PUSHF*/ - access(33, 16); - tempw = (cpu_state.flags & 0x0fd7) | 0xf000; - push(&tempw); - break; - case 0x9D: /*POPF*/ - access(25, 16); - cpu_state.flags = pop() | 2; - wait(1, 0); - break; - case 0x9E: /*SAHF*/ - wait(1, 0); - cpu_state.flags = (cpu_state.flags & 0xff02) | AH; - wait(2, 0); - break; - case 0x9F: /*LAHF*/ - wait(1, 0); - AH = cpu_state.flags & 0xd7; - break; + break; + case 0x9C: /*PUSHF*/ + access(33, 16); + if (is_nec) + tempw = (cpu_state.flags & 0x8fd7) | 0x7000; + else + tempw = (cpu_state.flags & 0x0fd7) | 0xf000; + push(&tempw); + break; + case 0x9D: /*POPF*/ + access(25, 16); + if (is_nec) + cpu_state.flags = pop() | 0x8002; + else + cpu_state.flags = pop() | 0x0002; + wait(1, 0); + break; + case 0x9E: /*SAHF*/ + wait(1, 0); + cpu_state.flags = (cpu_state.flags & 0xff02) | AH; + wait(2, 0); + break; + case 0x9F: /*LAHF*/ + wait(1, 0); + AH = cpu_state.flags & 0xd7; + break; - case 0xA0: case 0xA1: - /* MOV A, [iw] */ - bits = 8 << (opcode & 1); - wait(1, 0); - cpu_state.eaaddr = pfq_fetchw(); - access(1, bits); - set_accum(bits, readmem((ovr_seg ? *ovr_seg : ds))); - wait(1, 0); - break; - case 0xA2: case 0xA3: - /* MOV [iw], A */ - bits = 8 << (opcode & 1); - wait(1, 0); - cpu_state.eaaddr = pfq_fetchw(); - access(7, bits); - writemem((ovr_seg ? *ovr_seg : ds), get_accum(bits)); - break; + case 0xA0: + case 0xA1: + /* MOV A, [iw] */ + bits = 8 << (opcode & 1); + wait(1, 0); + cpu_state.eaaddr = pfq_fetchw(); + access(1, bits); + set_accum(bits, readmem((ovr_seg ? *ovr_seg : ds))); + wait(1, 0); + break; + case 0xA2: + case 0xA3: + /* MOV [iw], A */ + bits = 8 << (opcode & 1); + wait(1, 0); + cpu_state.eaaddr = pfq_fetchw(); + access(7, bits); + writemem((ovr_seg ? *ovr_seg : ds), get_accum(bits)); + break; - case 0xA4: case 0xA5: /* MOVS */ - case 0xAC: case 0xAD: /* LODS */ - bits = 8 << (opcode & 1); - if (!repeating) { - wait(1, 0); - if ((opcode & 8) == 0 && in_rep != 0) - wait(1, 0); - } - if (rep_action(bits)) { - wait(1, 0); - if ((opcode & 8) != 0) - wait(1, 0); - break; - } - if (in_rep != 0 && (opcode & 8) != 0) - wait(1, 0); - access(20, bits); - lods(bits); - if ((opcode & 8) == 0) { - access(27, bits); - stos(bits); - } else { - set_accum(bits, cpu_data); - if (in_rep != 0) - wait(2, 0); - } - if (in_rep == 0) { - wait(3, 0); - if ((opcode & 8) != 0) - wait(1, 0); - break; - } - repeating = 1; - clock_end(); - break; + case 0xA4: + case 0xA5: /* MOVS */ + case 0xAC: + case 0xAD: /* LODS */ + bits = 8 << (opcode & 1); + if (!repeating) { + wait(1, 0); + if ((opcode & 8) == 0 && in_rep != 0) + wait(1, 0); + } + if (rep_action(bits)) { + wait(1, 0); + if ((opcode & 8) != 0) + wait(1, 0); + break; + } + if (in_rep != 0 && (opcode & 8) != 0) + wait(1, 0); + access(20, bits); + lods(bits); + if ((opcode & 8) == 0) { + access(27, bits); + stos(bits); + } else { + set_accum(bits, cpu_data); + if (in_rep != 0) + wait(2, 0); + } + if (in_rep == 0) { + wait(3, 0); + if ((opcode & 8) != 0) + wait(1, 0); + break; + } + repeating = 1; + clock_end(); + break; - case 0xA6: case 0xA7: /* CMPS */ - case 0xAE: case 0xAF: /* SCAS */ - bits = 8 << (opcode & 1); - if (!repeating) - wait(1, 0); - if (rep_action(bits)) { - wait(2, 0); - break; - } - if (in_rep != 0) - wait(1, 0); - wait(1, 0); - cpu_dest = get_accum(bits); - if ((opcode & 8) == 0) { - access(21, bits); - lods(bits); - wait(1, 0); - cpu_dest = cpu_data; - } - access(2, bits); - cpu_state.eaaddr = DI; - cpu_data = readmem(es); - DI = string_increment(bits); - cpu_src = cpu_data; - sub(bits); - wait(2, 0); - if (in_rep == 0) { - wait(3, 0); - break; - } - if ((!!(cpu_state.flags & Z_FLAG)) == (in_rep == 1)) { - completed = 1; - wait(4, 0); - break; - } - repeating = 1; - clock_end(); - break; + case 0xA6: + case 0xA7: /* CMPS */ + case 0xAE: + case 0xAF: /* SCAS */ + bits = 8 << (opcode & 1); + if (!repeating) + wait(1, 0); + if (rep_action(bits)) { + wait(2, 0); + break; + } + if (in_rep != 0) + wait(1, 0); + wait(1, 0); + cpu_dest = get_accum(bits); + if ((opcode & 8) == 0) { + access(21, bits); + lods(bits); + wait(1, 0); + cpu_dest = cpu_data; + } + access(2, bits); + cpu_state.eaaddr = DI; + cpu_data = readmem(es); + DI = string_increment(bits); + cpu_src = cpu_data; + sub(bits); + wait(2, 0); + if (in_rep == 0) { + wait(3, 0); + break; + } + if ((!!(cpu_state.flags & (rep_c_flag ? C_FLAG : Z_FLAG))) == (in_rep == 1)) { + completed = 1; + wait(4, 0); + break; + } + repeating = 1; + clock_end(); + break; - case 0xA8: case 0xA9: - /* TEST A, imm */ - bits = 8 << (opcode & 1); - wait(1, 0); - cpu_data = pfq_fetch(); - test(bits, get_accum(bits), cpu_data); - wait(1, 0); - break; + case 0xA8: + case 0xA9: + /* TEST A, imm */ + bits = 8 << (opcode & 1); + wait(1, 0); + cpu_data = pfq_fetch(); + test(bits, get_accum(bits), cpu_data); + wait(1, 0); + break; - case 0xAA: case 0xAB: /* STOS */ - bits = 8 << (opcode & 1); - if (!repeating) { - wait(1, 0); - if (in_rep != 0) - wait(1, 0); - } - if (rep_action(bits)) { - wait(1, 0); - break; - } - cpu_data = AX; - access(28, bits); - stos(bits); - if (in_rep == 0) { - wait(3, 0); - break; - } - repeating = 1; - clock_end(); - break; + case 0xAA: + case 0xAB: /* STOS */ + bits = 8 << (opcode & 1); + if (!repeating) { + wait(1, 0); + if (in_rep != 0) + wait(1, 0); + } + if (rep_action(bits)) { + wait(1, 0); + break; + } + cpu_data = AX; + access(28, bits); + stos(bits); + if (in_rep == 0) { + wait(3, 0); + break; + } + repeating = 1; + clock_end(); + break; - case 0xB0: case 0xB1: case 0xB2: case 0xB3: /*MOV cpu_reg,#8*/ - case 0xB4: case 0xB5: case 0xB6: case 0xB7: - wait(1, 0); - if (opcode & 0x04) - cpu_state.regs[opcode & 0x03].b.h = pfq_fetchb(); - else - cpu_state.regs[opcode & 0x03].b.l = pfq_fetchb(); - wait(1, 0); - break; + case 0xB0: + case 0xB1: + case 0xB2: + case 0xB3: /*MOV cpu_reg,#8*/ + case 0xB4: + case 0xB5: + case 0xB6: + case 0xB7: + wait(1, 0); + if (opcode & 0x04) + cpu_state.regs[opcode & 0x03].b.h = pfq_fetchb(); + else + cpu_state.regs[opcode & 0x03].b.l = pfq_fetchb(); + wait(1, 0); + break; - case 0xB8: case 0xB9: case 0xBA: case 0xBB: /*MOV cpu_reg,#16*/ - case 0xBC: case 0xBD: case 0xBE: case 0xBF: - wait(1, 0); - cpu_state.regs[opcode & 0x07].w = pfq_fetchw(); - wait(1, 0); - break; + case 0xB8: + case 0xB9: + case 0xBA: + case 0xBB: /*MOV cpu_reg,#16*/ + case 0xBC: + case 0xBD: + case 0xBE: + case 0xBF: + wait(1, 0); + cpu_state.regs[opcode & 0x07].w = pfq_fetchw(); + wait(1, 0); + break; - case 0xC0: case 0xC1: case 0xC2: case 0xC3: - case 0xC8: case 0xC9: case 0xCA: case 0xCB: - /* RET */ - bits = 8 + (opcode & 0x08); - if ((opcode & 9) != 1) - wait(1, 0); - if (!(opcode & 1)) { - cpu_src = pfq_fetchw(); - wait(1, 0); - } - if ((opcode & 9) == 9) - wait(1, 0); - pfq_clear(); - access(26, bits); - new_ip = pop(); - wait(2, 0); - if ((opcode & 8) == 0) - new_cs = CS; - else { - access(42, bits); - new_cs = pop(); - if (opcode & 1) - wait(1, 0); - } - if (!(opcode & 1)) { - SP += cpu_src; - wait(1, 0); - } - load_cs(new_cs); - access(72, bits); - set_ip(new_ip); - break; + case 0xC0: + case 0xC1: + case 0xC2: + case 0xC3: + case 0xC8: + case 0xC9: + case 0xCA: + case 0xCB: + /* RET */ + bits = 8 + (opcode & 0x08); + if ((opcode & 9) != 1) + wait(1, 0); + if (!(opcode & 1)) { + cpu_src = pfq_fetchw(); + wait(1, 0); + } + if ((opcode & 9) == 9) + wait(1, 0); + pfq_clear(); + access(26, bits); + new_ip = pop(); + wait(2, 0); + if ((opcode & 8) == 0) + new_cs = CS; + else { + access(42, bits); + new_cs = pop(); + if (opcode & 1) + wait(1, 0); + } + if (!(opcode & 1)) { + SP += cpu_src; + wait(1, 0); + } + load_cs(new_cs); + access(72, bits); + set_ip(new_ip); + break; - case 0xC4: case 0xC5: - /* LsS rw, rmd */ - do_mod_rm(); - bits = 16; - access(52, bits); - read_ea(1, bits); - cpu_state.regs[cpu_reg].w = cpu_data; - access(57, bits); - read_ea2(bits); - load_seg(cpu_data, (opcode & 0x01) ? &cpu_state.seg_ds : &cpu_state.seg_es); - wait(1, 0); - break; + case 0xC4: + case 0xC5: + /* LsS rw, rmd */ + do_mod_rm(); + bits = 16; + access(52, bits); + read_ea(1, bits); + cpu_state.regs[cpu_reg].w = cpu_data; + access(57, bits); + read_ea2(bits); + load_seg(cpu_data, (opcode & 0x01) ? &cpu_state.seg_ds : &cpu_state.seg_es); + wait(1, 0); + break; - case 0xC6: case 0xC7: - /* MOV rm, imm */ - bits = 8 << (opcode & 1); - do_mod_rm(); - wait(1, 0); - if (cpu_mod != 3) - wait(2, 0); - cpu_data = pfq_fetch(); - if (cpu_mod == 3) - wait(1, 0); - access(16, bits); - set_ea(cpu_data); - break; + case 0xC6: + case 0xC7: + /* MOV rm, imm */ + bits = 8 << (opcode & 1); + do_mod_rm(); + wait(1, 0); + if (cpu_mod != 3) + wait(2, 0); + cpu_data = pfq_fetch(); + if (cpu_mod == 3) + wait(1, 0); + access(16, bits); + set_ea(cpu_data); + break; - case 0xCC: /*INT 3*/ - interrupt(3); - break; - case 0xCD: /*INT*/ - wait(1, 0); - interrupt(pfq_fetchb()); - break; - case 0xCE: /*INTO*/ - wait(3, 0); - if (cpu_state.flags & V_FLAG) { - wait(2, 0); - interrupt(4); - } - break; + case 0xCC: /*INT 3*/ + interrupt(3); + break; + case 0xCD: /*INT*/ + wait(1, 0); + interrupt(pfq_fetchb()); + break; + case 0xCE: /*INTO*/ + wait(3, 0); + if (cpu_state.flags & V_FLAG) { + wait(2, 0); + interrupt(4); + } + break; - case 0xCF: /*IRET*/ - access(43, 8); - new_ip = pop(); - wait(3, 0); - access(44, 8); - new_cs = pop(); - load_cs(new_cs); - access(62, 8); - set_ip(new_ip); - access(45, 8); - cpu_state.flags = pop() | 2; - wait(5, 0); - noint = 1; - nmi_enable = 1; - break; + case 0xCF: /*IRET*/ + access(43, 8); + new_ip = pop(); + wait(3, 0); + access(44, 8); + new_cs = pop(); + load_cs(new_cs); + access(62, 8); + set_ip(new_ip); + access(45, 8); + if (is_nec) + cpu_state.flags = pop() | 0x8002; + else + cpu_state.flags = pop() | 0x0002; + wait(5, 0); + noint = 1; + nmi_enable = 1; + break; - case 0xD0: case 0xD1: case 0xD2: case 0xD3: - /* rot rm */ - bits = 8 << (opcode & 1); - do_mod_rm(); - if (cpu_mod == 3) - wait(1, 0); - access(53, bits); - cpu_data = get_ea(); - if ((opcode & 2) == 0) { - cpu_src = 1; - wait((cpu_mod != 3) ? 4 : 0, 0); - } else { - cpu_src = CL; - wait((cpu_mod != 3) ? 9 : 6, 0); - } - while (cpu_src != 0) { - cpu_dest = cpu_data; - oldc = cpu_state.flags & C_FLAG; - switch (rmdat & 0x38) { - case 0x00: /* ROL */ - set_cf(top_bit(cpu_data, bits)); - cpu_data <<= 1; - cpu_data |= ((cpu_state.flags & C_FLAG) ? 1 : 0); - set_of_rotate(bits); - set_af(0); - break; - case 0x08: /* ROR */ - set_cf((cpu_data & 1) != 0); - cpu_data >>= 1; - if (cpu_state.flags & C_FLAG) - cpu_data |= (!(opcode & 1) ? 0x80 : 0x8000); - set_of_rotate(bits); - set_af(0); - break; - case 0x10: /* RCL */ - set_cf(top_bit(cpu_data, bits)); - cpu_data = (cpu_data << 1) | (oldc ? 1 : 0); - set_of_rotate(bits); - set_af(0); - break; - case 0x18: /* RCR */ - set_cf((cpu_data & 1) != 0); - cpu_data >>= 1; - if (oldc) - cpu_data |= (!(opcode & 0x01) ? 0x80 : 0x8000); - set_cf((cpu_dest & 1) != 0); - set_of_rotate(bits); - set_af(0); - break; - case 0x20: /* SHL */ - set_cf(top_bit(cpu_data, bits)); - cpu_data <<= 1; - set_of_rotate(bits); - set_af((cpu_data & 0x10) != 0); - set_pzs(bits); - break; - case 0x28: /* SHR */ - set_cf((cpu_data & 1) != 0); - cpu_data >>= 1; - set_of_rotate(bits); - set_af(0); - set_pzs(bits); - break; - case 0x30: /* SETMO - undocumented? */ - bitwise(bits, 0xffff); - set_cf(0); - set_of_rotate(bits); - set_af(0); - set_pzs(bits); - break; - case 0x38: /* SAR */ - set_cf((cpu_data & 1) != 0); - cpu_data >>= 1; - if (!(opcode & 1)) - cpu_data |= (cpu_dest & 0x80); - else - cpu_data |= (cpu_dest & 0x8000); - set_of_rotate(bits); - set_af(0); - set_pzs(bits); - break; - } - if ((opcode & 2) != 0) - wait(4, 0); - --cpu_src; - } - access(17, bits); - set_ea(cpu_data); - break; + case 0xD0: + case 0xD1: + case 0xD2: + case 0xD3: + /* rot rm */ + bits = 8 << (opcode & 1); + do_mod_rm(); + if (cpu_mod == 3) + wait(1, 0); + access(53, bits); + cpu_data = get_ea(); + if ((opcode & 2) == 0) { + cpu_src = 1; + wait((cpu_mod != 3) ? 4 : 0, 0); + } else { + cpu_src = CL; + wait((cpu_mod != 3) ? 9 : 6, 0); + } + if (is186 && !is_nec) + cpu_src &= 0x1F; + while (cpu_src != 0) { + cpu_dest = cpu_data; + oldc = cpu_state.flags & C_FLAG; + switch (rmdat & 0x38) { + case 0x00: /* ROL */ + set_cf(top_bit(cpu_data, bits)); + cpu_data <<= 1; + cpu_data |= ((cpu_state.flags & C_FLAG) ? 1 : 0); + set_of_rotate(bits); + set_af(0); + break; + case 0x08: /* ROR */ + set_cf((cpu_data & 1) != 0); + cpu_data >>= 1; + if (cpu_state.flags & C_FLAG) + cpu_data |= (!(opcode & 1) ? 0x80 : 0x8000); + set_of_rotate(bits); + set_af(0); + break; + case 0x10: /* RCL */ + set_cf(top_bit(cpu_data, bits)); + cpu_data = (cpu_data << 1) | (oldc ? 1 : 0); + set_of_rotate(bits); + set_af(0); + break; + case 0x18: /* RCR */ + set_cf((cpu_data & 1) != 0); + cpu_data >>= 1; + if (oldc) + cpu_data |= (!(opcode & 0x01) ? 0x80 : 0x8000); + set_cf((cpu_dest & 1) != 0); + set_of_rotate(bits); + set_af(0); + break; + case 0x20: /* SHL */ + set_cf(top_bit(cpu_data, bits)); + cpu_data <<= 1; + set_of_rotate(bits); + set_af((cpu_data & 0x10) != 0); + set_pzs(bits); + break; + case 0x28: /* SHR */ + set_cf((cpu_data & 1) != 0); + cpu_data >>= 1; + set_of_rotate(bits); + set_af(0); + set_pzs(bits); + break; + case 0x30: /* SETMO - undocumented? */ + bitwise(bits, 0xffff); + set_cf(0); + set_of_rotate(bits); + set_af(0); + set_pzs(bits); + break; + case 0x38: /* SAR */ + set_cf((cpu_data & 1) != 0); + cpu_data >>= 1; + if (!(opcode & 1)) + cpu_data |= (cpu_dest & 0x80); + else + cpu_data |= (cpu_dest & 0x8000); + set_of_rotate(bits); + set_af(0); + set_pzs(bits); + break; + } + if ((opcode & 2) != 0) + wait(4, 0); + --cpu_src; + } + access(17, bits); + set_ea(cpu_data); + break; - case 0xD4: /*AAM*/ - wait(1, 0); - cpu_src = pfq_fetchb(); - if (x86_div(AL, 0)) - set_pzs(16); - break; - case 0xD5: /*AAD*/ - wait(1, 0); - mul(pfq_fetchb(), AH); - cpu_dest = AL; - cpu_src = cpu_data; - add(8); - AL = cpu_data; - AH = 0x00; - break; - case 0xD6: /*SALC*/ - wait(1, 0); - AL = (cpu_state.flags & C_FLAG) ? 0xff : 0x00; - wait(1, 0); - break; - case 0xD7: /*XLATB*/ - cpu_state.eaaddr = (BX + AL) & 0xffff; - access(4, 8); - AL = readmemb((ovr_seg ? *ovr_seg : ds) + cpu_state.eaaddr); - wait(1, 0); - break; + case 0xD4: /*AAM*/ + wait(1, 0); +#ifdef NO_VARIANT_ON_NEC + if (is_nec) { + (void) pfq_fetchb(); + cpu_src = 10; + } else + cpu_src = pfq_fetchb(); +#else + cpu_src = pfq_fetchb(); +#endif + if (x86_div(AL, 0)) + set_pzs(16); + break; + case 0xD5: /*AAD*/ + wait(1, 0); + if (is_nec) { + (void) pfq_fetchb(); + mul(10, AH); + } else + mul(pfq_fetchb(), AH); + cpu_dest = AL; + cpu_src = cpu_data; + add(8); + AL = cpu_data; + AH = 0x00; + break; + case 0xD6: /*SALC*/ + wait(1, 0); + AL = (cpu_state.flags & C_FLAG) ? 0xff : 0x00; + wait(1, 0); + break; + case 0xD7: /*XLATB*/ + cpu_state.eaaddr = (BX + AL) & 0xffff; + access(4, 8); + AL = readmemb((ovr_seg ? *ovr_seg : ds) + cpu_state.eaaddr); + wait(1, 0); + break; - case 0xD8: case 0xD9: case 0xDA: case 0xDB: - case 0xDD: case 0xDC: case 0xDE: case 0xDF: - /* esc i, r, rm */ - do_mod_rm(); - access(54, 16); - tempw = cpu_state.pc; - if (!hasfpu) - geteaw(); - else switch(opcode) { - case 0xD8: - ops_fpu_8087_d8[(rmdat >> 3) & 0x1f]((uint32_t) rmdat); - break; - case 0xD9: - ops_fpu_8087_d9[rmdat & 0xff]((uint32_t) rmdat); - break; - case 0xDA: - ops_fpu_8087_da[rmdat & 0xff]((uint32_t) rmdat); - break; - case 0xDB: - ops_fpu_8087_db[rmdat & 0xff]((uint32_t) rmdat); - break; - case 0xDC: - ops_fpu_8087_dc[(rmdat >> 3) & 0x1f]((uint32_t) rmdat); - break; - case 0xDD: - ops_fpu_8087_dd[rmdat & 0xff]((uint32_t) rmdat); - break; - case 0xDE: - ops_fpu_8087_de[rmdat & 0xff]((uint32_t) rmdat); - break; - case 0xDF: - ops_fpu_8087_df[rmdat & 0xff]((uint32_t) rmdat); - break; - } - cpu_state.pc = tempw; /* Do this as the x87 code advances it, which is needed on - the 286+ core, but not here. */ - wait(1, 0); - if (cpu_mod != 3) - wait(2, 0); - break; + case 0xD8: + case 0xD9: + case 0xDA: + case 0xDB: + case 0xDD: + case 0xDC: + case 0xDE: + case 0xDF: + /* esc i, r, rm */ + do_mod_rm(); + access(54, 16); + tempw = cpu_state.pc; + if (!hasfpu) + geteaw(); + else + switch (opcode) { + case 0xD8: + ops_fpu_8087_d8[(rmdat >> 3) & 0x1f]((uint32_t) rmdat); + break; + case 0xD9: + ops_fpu_8087_d9[rmdat & 0xff]((uint32_t) rmdat); + break; + case 0xDA: + ops_fpu_8087_da[rmdat & 0xff]((uint32_t) rmdat); + break; + case 0xDB: + ops_fpu_8087_db[rmdat & 0xff]((uint32_t) rmdat); + break; + case 0xDC: + ops_fpu_8087_dc[(rmdat >> 3) & 0x1f]((uint32_t) rmdat); + break; + case 0xDD: + ops_fpu_8087_dd[rmdat & 0xff]((uint32_t) rmdat); + break; + case 0xDE: + ops_fpu_8087_de[rmdat & 0xff]((uint32_t) rmdat); + break; + case 0xDF: + ops_fpu_8087_df[rmdat & 0xff]((uint32_t) rmdat); + break; + } + cpu_state.pc = tempw; /* Do this as the x87 code advances it, which is needed on + the 286+ core, but not here. */ + wait(1, 0); + if (cpu_mod != 3) + wait(2, 0); + break; - case 0xE0: case 0xE1: case 0xE2: case 0xE3: - /* LOOP */ - wait(3, 0); - cpu_data = pfq_fetchb(); - if (opcode != 0xe2) - wait(1, 0); - if (opcode != 0xe3) { - --CX; - oldc = (CX != 0); - switch (opcode) { - case 0xE0: - if (cpu_state.flags & Z_FLAG) - oldc = 0; - break; - case 0xE1: - if (!(cpu_state.flags & Z_FLAG)) - oldc = 0; - break; - } - } else - oldc = (CX == 0); - if (oldc) - jump_short(); - break; + case 0xE0: + case 0xE1: + case 0xE2: + case 0xE3: + /* LOOP */ + wait(3, 0); + cpu_data = pfq_fetchb(); + if (opcode != 0xe2) + wait(1, 0); + if (opcode != 0xe3) { + --CX; + oldc = (CX != 0); + switch (opcode) { + case 0xE0: + if (cpu_state.flags & Z_FLAG) + oldc = 0; + break; + case 0xE1: + if (!(cpu_state.flags & Z_FLAG)) + oldc = 0; + break; + } + } else + oldc = (CX == 0); + if (oldc) + jump_short(); + break; - case 0xE4: case 0xE5: case 0xE6: case 0xE7: - case 0xEC: case 0xED: case 0xEE: case 0xEF: - bits = 8 << (opcode & 1); - if ((opcode & 0x0e) != 0x0c) - wait(1, 0); - if ((opcode & 8) == 0) - cpu_data = pfq_fetchb(); - else - cpu_data = DX; - cpu_state.eaaddr = cpu_data; - if ((opcode & 2) == 0) { - access(3, bits); - if (opcode & 1) - cpu_io(16, 0, cpu_data); - else - cpu_io(8, 0, cpu_data); - wait(1, 0); - } else { - if ((opcode & 8) == 0) - access(8, bits); - else - access(9, bits); - if (opcode & 1) - cpu_io(16, 1, cpu_data); - else - cpu_io(8, 1, cpu_data); - } - break; + case 0xE4: + case 0xE5: + case 0xE6: + case 0xE7: + case 0xEC: + case 0xED: + case 0xEE: + case 0xEF: + bits = 8 << (opcode & 1); + if ((opcode & 0x0e) != 0x0c) + wait(1, 0); + if ((opcode & 8) == 0) + cpu_data = pfq_fetchb(); + else + cpu_data = DX; + cpu_state.eaaddr = cpu_data; + if ((opcode & 2) == 0) { + access(3, bits); + if (opcode & 1) + cpu_io(16, 0, cpu_data); + else + cpu_io(8, 0, cpu_data); + wait(1, 0); + } else { + if ((opcode & 8) == 0) + access(8, bits); + else + access(9, bits); + if (opcode & 1) + cpu_io(16, 1, cpu_data); + else + cpu_io(8, 1, cpu_data); + } + break; - case 0xE8: /*CALL rel 16*/ - wait(1, 0); - cpu_state.oldpc = jump_near(); - access(34, 8); - push((uint16_t *) &(cpu_state.oldpc)); - break; - case 0xE9: /*JMP rel 16*/ - wait(1, 0); - jump_near(); - break; - case 0xEA: /*JMP far*/ - wait(1, 0); - addr = pfq_fetchw(); - wait(1, 0); - tempw = pfq_fetchw(); - load_cs(tempw); - access(70, 8); - pfq_clear(); - set_ip(addr); - break; - case 0xEB: /*JMP rel*/ - wait(1, 0); - cpu_data = (int8_t) pfq_fetchb(); - jump_short(); - wait(1, 0); - break; + case 0xE8: /*CALL rel 16*/ + wait(1, 0); + cpu_state.oldpc = jump_near(); + access(34, 8); + push((uint16_t *) &(cpu_state.oldpc)); + break; + case 0xE9: /*JMP rel 16*/ + wait(1, 0); + jump_near(); + break; + case 0xEA: /*JMP far*/ + wait(1, 0); + addr = pfq_fetchw(); + wait(1, 0); + tempw = pfq_fetchw(); + load_cs(tempw); + access(70, 8); + pfq_clear(); + set_ip(addr); + break; + case 0xEB: /*JMP rel*/ + wait(1, 0); + cpu_data = (int8_t) pfq_fetchb(); + jump_short(); + wait(1, 0); + break; - case 0xF0: case 0xF1: /*LOCK - F1 is alias*/ - in_lock = 1; - wait(1, 0); - completed = 0; - break; + case 0xF0: + case 0xF1: /*LOCK - F1 is alias*/ + in_lock = 1; + wait(1, 0); + completed = 0; + break; - case 0xF2: /*REPNE*/ - case 0xF3: /*REPE*/ - wait(1, 0); - in_rep = (opcode == 0xf2 ? 1 : 2); - completed = 0; - break; + case 0xF2: /*REPNE*/ + case 0xF3: /*REPE*/ + wait(1, 0); + in_rep = (opcode == 0xf2 ? 1 : 2); + completed = 0; + rep_c_flag = 0; + break; - case 0xF4: /*HLT*/ - if (!repeating) { - wait(1, 0); - pfq_clear(); - } - wait(1, 0); - if (irq_pending()) { - wait(cycles & 1, 0); - check_interrupts(); - } else { - repeating = 1; - completed = 0; - clock_end(); - } - break; - case 0xF5: /*CMC*/ - wait(1, 0); - cpu_state.flags ^= C_FLAG; - break; + case 0xF4: /*HLT*/ + if (!repeating) { + wait(1, 0); + pfq_clear(); + } + wait(1, 0); + if (irq_pending()) { + wait(cycles & 1, 0); + check_interrupts(); + } else { + repeating = 1; + completed = 0; + clock_end(); + } + break; + case 0xF5: /*CMC*/ + wait(1, 0); + cpu_state.flags ^= C_FLAG; + break; - case 0xF6: case 0xF7: - bits = 8 << (opcode & 1); - do_mod_rm(); - access(55, bits); - cpu_data = get_ea(); - switch (rmdat & 0x38) { - case 0x00: case 0x08: - /* TEST */ - wait(2, 0); - if (cpu_mod != 3) - wait(1, 0); - cpu_src = pfq_fetch(); - wait(1, 0); - test(bits, cpu_data, cpu_src); - if (cpu_mod != 3) - wait(1, 0); - break; - case 0x10: /* NOT */ - case 0x18: /* NEG */ - wait(2, 0); - if ((rmdat & 0x38) == 0x10) - cpu_data = ~cpu_data; - else { - cpu_src = cpu_data; - cpu_dest = 0; - sub(bits); - } - access(18, bits); - set_ea(cpu_data); - break; - case 0x20: /* MUL */ - case 0x28: /* IMUL */ - wait(1, 0); - mul(get_accum(bits), cpu_data); - if (opcode & 1) { - AX = cpu_data; - DX = cpu_dest; - set_co_mul(bits, DX != ((AX & 0x8000) == 0 || (rmdat & 0x38) == 0x20 ? 0 : 0xffff)); - cpu_data = DX; - } else { - AL = (uint8_t) cpu_data; - AH = (uint8_t) cpu_dest; - set_co_mul(bits, AH != ((AL & 0x80) == 0 || (rmdat & 0x38) == 0x20 ? 0 : 0xff)); - cpu_data = AH; - } - /* NOTE: When implementing the V20, care should be taken to not change - the zero flag. */ - set_sf(bits); - set_pf(); - if (cpu_mod != 3) - wait(1, 0); - break; - case 0x30: /* DIV */ - case 0x38: /* IDIV */ - if (cpu_mod != 3) - wait(1, 0); - cpu_src = cpu_data; - if (x86_div(AL, AH)) - wait(1, 0); - break; - } - break; + case 0xF6: + case 0xF7: + bits = 8 << (opcode & 1); + do_mod_rm(); + access(55, bits); + cpu_data = get_ea(); + switch (rmdat & 0x38) { + case 0x00: + case 0x08: + /* TEST */ + wait(2, 0); + if (cpu_mod != 3) + wait(1, 0); + cpu_src = pfq_fetch(); + wait(1, 0); + test(bits, cpu_data, cpu_src); + if (cpu_mod != 3) + wait(1, 0); + break; + case 0x10: /* NOT */ + case 0x18: /* NEG */ + wait(2, 0); + if ((rmdat & 0x38) == 0x10) + cpu_data = ~cpu_data; + else { + cpu_src = cpu_data; + cpu_dest = 0; + sub(bits); + } + access(18, bits); + set_ea(cpu_data); + break; + case 0x20: /* MUL */ + case 0x28: /* IMUL */ + old_flags = cpu_state.flags; + wait(1, 0); + mul(get_accum(bits), cpu_data); + if (opcode & 1) { + AX = cpu_data; + DX = cpu_dest; + set_co_mul(bits, DX != ((AX & 0x8000) == 0 || (rmdat & 0x38) == 0x20 ? 0 : 0xffff)); + cpu_data = DX; + } else { + AL = (uint8_t) cpu_data; + AH = (uint8_t) cpu_dest; + set_co_mul(bits, AH != ((AL & 0x80) == 0 || (rmdat & 0x38) == 0x20 ? 0 : 0xff)); + if (!is_nec) + cpu_data = AH; + } + set_sf(bits); + set_pf(); + if (cpu_mod != 3) + wait(1, 0); + /* NOTE: When implementing the V20, care should be taken to not change + the zero flag. */ + if (is_nec) + cpu_state.flags = (cpu_state.flags & ~Z_FLAG) | (old_flags & Z_FLAG); + break; + case 0x30: /* DIV */ + case 0x38: /* IDIV */ + if (cpu_mod != 3) + wait(1, 0); + cpu_src = cpu_data; + if (x86_div(AL, AH)) + wait(1, 0); + break; + } + break; - case 0xF8: case 0xF9: - /* CLCSTC */ - wait(1, 0); - set_cf(opcode & 1); - break; - case 0xFA: case 0xFB: - /* CLISTI */ - wait(1, 0); - set_if(opcode & 1); - break; - case 0xFC: case 0xFD: - /* CLDSTD */ - wait(1, 0); - set_df(opcode & 1); - break; + case 0xF8: + case 0xF9: + /* CLCSTC */ + wait(1, 0); + set_cf(opcode & 1); + break; + case 0xFA: + case 0xFB: + /* CLISTI */ + wait(1, 0); + set_if(opcode & 1); + break; + case 0xFC: + case 0xFD: + /* CLDSTD */ + wait(1, 0); + set_df(opcode & 1); + break; - case 0xFE: case 0xFF: - /* misc */ - bits = 8 << (opcode & 1); - do_mod_rm(); - access(56, bits); - read_ea(((rmdat & 0x38) == 0x18) || ((rmdat & 0x38) == 0x28), bits); - switch (rmdat & 0x38) { - case 0x00: /* INC rm */ - case 0x08: /* DEC rm */ - cpu_dest = cpu_data; - cpu_src = 1; - if ((rmdat & 0x38) == 0x00) { - cpu_data = cpu_dest + cpu_src; - set_of_add(bits); - } else { - cpu_data = cpu_dest - cpu_src; - set_of_sub(bits); - } - do_af(); - set_pzs(bits); - wait(2, 0); - access(19, bits); - set_ea(cpu_data); - break; - case 0x10: /* CALL rm */ - cpu_data_opff_rm(); - access(63, bits); - wait(1, 0); - pfq_clear(); - wait(4, 0); - if (cpu_mod != 3) - wait(1, 0); - wait(1, 0); /* Wait. */ - cpu_state.oldpc = cpu_state.pc; - set_ip(cpu_data); - wait(2, 0); - access(35, bits); - push((uint16_t *) &(cpu_state.oldpc)); - break; - case 0x18: /* CALL rmd */ - new_ip = cpu_data; - access(58, bits); - read_ea2(bits); - if (!(opcode & 1)) - cpu_data |= 0xff00; - new_cs = cpu_data; - access(36, bits); - push(&(CS)); - access(64, bits); - wait(4, 0); - cpu_state.oldpc = cpu_state.pc; - load_cs(new_cs); - set_ip(new_ip); - access(37, bits); - push((uint16_t *) &(cpu_state.oldpc)); - break; - case 0x20: /* JMP rm */ - cpu_data_opff_rm(); - access(65, bits); - set_ip(cpu_data); - break; - case 0x28: /* JMP rmd */ - new_ip = cpu_data; - access(59, bits); - read_ea2(bits); - if (!(opcode & 1)) - cpu_data |= 0xff00; - new_cs = cpu_data; - load_cs(new_cs); - access(66, bits); - set_ip(new_ip); - break; - case 0x30: /* PUSH rm */ - case 0x38: - if (cpu_mod != 3) - wait(1, 0); - access(38, bits); - push((uint16_t *) &(cpu_data)); - break; - } - break; + case 0xFE: + case 0xFF: + /* misc */ + bits = 8 << (opcode & 1); + do_mod_rm(); + access(56, bits); + read_ea(((rmdat & 0x38) == 0x18) || ((rmdat & 0x38) == 0x28), bits); + switch (rmdat & 0x38) { + case 0x00: /* INC rm */ + case 0x08: /* DEC rm */ + cpu_dest = cpu_data; + cpu_src = 1; + if ((rmdat & 0x38) == 0x00) { + cpu_data = cpu_dest + cpu_src; + set_of_add(bits); + } else { + cpu_data = cpu_dest - cpu_src; + set_of_sub(bits); + } + do_af(); + set_pzs(bits); + wait(2, 0); + access(19, bits); + set_ea(cpu_data); + break; + case 0x10: /* CALL rm */ + cpu_data_opff_rm(); + access(63, bits); + wait(1, 0); + pfq_clear(); + wait(4, 0); + if (cpu_mod != 3) + wait(1, 0); + wait(1, 0); /* Wait. */ + cpu_state.oldpc = cpu_state.pc; + set_ip(cpu_data); + wait(2, 0); + access(35, bits); + push((uint16_t *) &(cpu_state.oldpc)); + break; + case 0x18: /* CALL rmd */ + new_ip = cpu_data; + access(58, bits); + read_ea2(bits); + if (!(opcode & 1)) + cpu_data |= 0xff00; + new_cs = cpu_data; + access(36, bits); + push(&(CS)); + access(64, bits); + wait(4, 0); + cpu_state.oldpc = cpu_state.pc; + load_cs(new_cs); + set_ip(new_ip); + access(37, bits); + push((uint16_t *) &(cpu_state.oldpc)); + break; + case 0x20: /* JMP rm */ + cpu_data_opff_rm(); + access(65, bits); + set_ip(cpu_data); + break; + case 0x28: /* JMP rmd */ + new_ip = cpu_data; + access(59, bits); + read_ea2(bits); + if (!(opcode & 1)) + cpu_data |= 0xff00; + new_cs = cpu_data; + load_cs(new_cs); + access(66, bits); + set_ip(new_ip); + break; + case 0x30: /* PUSH rm */ + case 0x38: + if (cpu_mod != 3) + wait(1, 0); + access(38, bits); + push((uint16_t *) &(cpu_data)); + break; + } + break; - default: - x808x_log("Illegal opcode: %02X\n", opcode); - pfq_fetchb(); - wait(8, 0); - break; - } + default: + x808x_log("Illegal opcode: %02X\n", opcode); + pfq_fetchb(); + wait(8, 0); + break; + } + } - if (completed) { - repeating = 0; - ovr_seg = NULL; - in_rep = 0; - if (in_lock) - clear_lock = 1; - clock_end(); - check_interrupts(); + if (completed) { + repeating = 0; + ovr_seg = NULL; + in_rep = 0; + rep_c_flag = 0; + if (in_lock) + clear_lock = 1; + clock_end(); + check_interrupts(); - if (noint) - noint = 0; + if (noint) + noint = 0; - cpu_alu_op = 0; - } + cpu_alu_op = 0; + } + +#ifdef USE_GDBSTUB + if (gdbstub_instruction()) + return; +#endif } } diff --git a/src/cpu/CMakeLists.txt b/src/cpu/CMakeLists.txt index 20452bf88..bd03a5558 100644 --- a/src/cpu/CMakeLists.txt +++ b/src/cpu/CMakeLists.txt @@ -1,20 +1,21 @@ # -# 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. +# 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. +# This file is part of the 86Box distribution. # -# CMake build script. +# CMake build script. # -# Authors: David HrdliÄka, +# Authors: David HrdliÄka, # -# Copyright 2020,2021 David HrdliÄka. +# Copyright 2020-2021 David HrdliÄka. # 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) + 386_dynarec.c x86_ops_mmx.c x86seg_common.c x86seg.c x86seg_2386.c x87.c + x87_timings.c 8080.c) if(AMD_K5) target_compile_definitions(cpu PRIVATE USE_AMD_K5) @@ -32,3 +33,6 @@ if(DYNAREC) codegen_timing_pentium.c codegen_timing_p6.c codegen_timing_winchip.c codegen_timing_winchip2.c) endif() + +add_subdirectory(softfloat) +target_link_libraries(86Box softfloat) diff --git a/src/cpu/codegen_public.h b/src/cpu/codegen_public.h index 868bc41ab..cb7ec57a7 100644 --- a/src/cpu/codegen_public.h +++ b/src/cpu/codegen_public.h @@ -1,18 +1,18 @@ /* - * VARCem Virtual ARchaeological Computer EMulator. - * An emulator of (mostly) x86-based PC systems and devices, - * using the ISA,EISA,VLB,MCA and PCI system buses, roughly - * spanning the era between 1981 and 1995. + * 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 VARCem Project. + * This file is part of the 86Box distribution. * - * Definitions for the code generator. + * Definitions for the code generator. * * * - * Authors: Miran Grca, + * Authors: Miran Grca, * - * Copyright 2020 Miran Grca. + * Copyright 2020 Miran Grca. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -36,29 +36,24 @@ #define _CODEGEN_PUBLIC_H_ #ifndef USE_NEW_DYNAREC -#define PAGE_MASK_INDEX_MASK 3 -#define PAGE_MASK_INDEX_SHIFT 10 -#define PAGE_MASK_SHIFT 4 +# define PAGE_MASK_INDEX_MASK 3 +# define PAGE_MASK_INDEX_SHIFT 10 +# define PAGE_MASK_SHIFT 4 #else -#define PAGE_MASK_SHIFT 6 +# define PAGE_MASK_SHIFT 6 #endif #define PAGE_MASK_MASK 63 #ifdef USE_NEW_DYNAREC -#define BLOCK_PC_INVALID 0xffffffff -#define BLOCK_INVALID 0 +# define BLOCK_PC_INVALID 0xffffffff +# define BLOCK_INVALID 0 #endif - -extern void codegen_init(); -#ifdef USE_NEW_DYNAREC -extern void codegen_close(); -#endif -extern void codegen_flush(); - +extern void codegen_init(void); +extern void codegen_flush(void); /*Current physical page of block being recompiled. -1 if no recompilation taking place */ -extern uint32_t recomp_page; -extern int codegen_in_recompile; +extern uint32_t recomp_page; +extern int codegen_in_recompile; #endif diff --git a/src/cpu/codegen_timing_486.c b/src/cpu/codegen_timing_486.c index a3859ecce..e862b123e 100644 --- a/src/cpu/codegen_timing_486.c +++ b/src/cpu/codegen_timing_486.c @@ -3,8 +3,10 @@ #include #include #include <86box/86box.h> -#include <86box/mem.h> #include "cpu.h" +#include <86box/mem.h> +#include <86box/plat_unused.h> + #include "x86.h" #include "x86_ops.h" #include "x87.h" @@ -12,11 +14,11 @@ #include "codegen_ops.h" #include "codegen_timing_common.h" -#define CYCLES(c) (int *)c -#define CYCLES2(c16, c32) (int *)((-1 & ~0xffff) | c16 | (c32 << 8)) +#define CYCLES(c) (int *) c +#define CYCLES2(c16, c32) (int *) ((-1 & ~0xffff) | c16 | (c32 << 8)) -static int *opcode_timings[256] = -{ +static int *opcode_timings[256] = { + // clang-format off /*00*/ &timing_mr, &timing_mr, &timing_rm, &timing_rm, &timing_rr, &timing_rr, CYCLES(2), CYCLES(3), &timing_mr, &timing_mr, &timing_rm, &timing_rm, &timing_rr, &timing_rr, CYCLES(2), NULL, /*10*/ &timing_mr, &timing_mr, &timing_rm, &timing_rm, &timing_rr, &timing_rr, CYCLES(2), CYCLES(3), &timing_mr, &timing_mr, &timing_rm, &timing_rm, &timing_rr, &timing_rr, CYCLES(2), CYCLES(3), /*20*/ &timing_mr, &timing_mr, &timing_rm, &timing_rm, &timing_rr, &timing_rr, CYCLES(4), CYCLES(3), &timing_mr, &timing_mr, &timing_rm, &timing_rm, &timing_rr, &timing_rr, CYCLES(4), CYCLES(3), @@ -36,10 +38,11 @@ static int *opcode_timings[256] = /*d0*/ CYCLES(4), CYCLES(4), CYCLES(4), CYCLES(4), CYCLES(15), CYCLES(14), CYCLES(2), CYCLES(4), NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, /*e0*/ CYCLES(6), CYCLES(6), CYCLES(6), CYCLES(5), CYCLES(14), CYCLES(14), CYCLES(16), CYCLES(16), CYCLES(3), CYCLES(3), CYCLES(17), CYCLES(3), CYCLES(14), CYCLES(14), CYCLES(14), CYCLES(14), /*f0*/ CYCLES(4), CYCLES(0), CYCLES(0), CYCLES(0), CYCLES(4), CYCLES(2), NULL, NULL, CYCLES(2), CYCLES(2), CYCLES(3), CYCLES(2), CYCLES(2), CYCLES(2), CYCLES(3), NULL + // clang-format on }; -static int *opcode_timings_mod3[256] = -{ +static int *opcode_timings_mod3[256] = { + // clang-format off /*00*/ &timing_rr, &timing_rr, &timing_rr, &timing_rr, &timing_rr, &timing_rr, CYCLES(2), CYCLES(3), &timing_rr, &timing_rr, &timing_rr, &timing_rr, &timing_rr, &timing_rr, CYCLES(2), NULL, /*10*/ &timing_rr, &timing_rr, &timing_rr, &timing_rr, &timing_rr, &timing_rr, CYCLES(2), CYCLES(3), &timing_rr, &timing_rr, &timing_rr, &timing_rr, &timing_rr, &timing_rr, CYCLES(2), CYCLES(3), /*20*/ &timing_rr, &timing_rr, &timing_rr, &timing_rr, &timing_rr, &timing_rr, CYCLES(4), CYCLES(3), &timing_rr, &timing_rr, &timing_rr, &timing_rr, &timing_rr, &timing_rr, CYCLES(4), CYCLES(3), @@ -59,10 +62,11 @@ static int *opcode_timings_mod3[256] = /*d0*/ CYCLES(4), CYCLES(4), CYCLES(4), CYCLES(4), CYCLES(15), CYCLES(14), CYCLES(2), CYCLES(4), NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, /*e0*/ CYCLES(6), CYCLES(6), CYCLES(6), CYCLES(5), CYCLES(14), CYCLES(14), CYCLES(16), CYCLES(16), CYCLES(3), CYCLES(3), CYCLES(17), CYCLES(3), CYCLES(14), CYCLES(14), CYCLES(14), CYCLES(14), /*f0*/ CYCLES(4), CYCLES(0), CYCLES(0), CYCLES(0), CYCLES(4), CYCLES(2), NULL, NULL, CYCLES(2), CYCLES(2), CYCLES(3), CYCLES(2), CYCLES(2), CYCLES(2), CYCLES(3), NULL + // clang-format on }; -static int *opcode_timings_0f[256] = -{ +static int *opcode_timings_0f[256] = { + // clang-format off /*00*/ CYCLES(20), CYCLES(11), CYCLES(11), CYCLES(10), NULL, CYCLES(195), CYCLES(7), NULL, CYCLES(1000), CYCLES(10000), NULL, NULL, NULL, NULL, NULL, NULL, /*10*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, /*20*/ CYCLES(6), CYCLES(6), CYCLES(6), CYCLES(6), CYCLES(6), CYCLES(6), NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, @@ -82,9 +86,10 @@ static int *opcode_timings_0f[256] = /*d0*/ NULL, &timing_rm, &timing_rm, &timing_rm, NULL, &timing_rm, NULL, NULL, &timing_rm, &timing_rm, NULL, &timing_rm, &timing_rm, &timing_rm, NULL, &timing_rm, /*e0*/ NULL, &timing_rm, &timing_rm, NULL, NULL, &timing_rm, NULL, NULL, &timing_rm, &timing_rm, NULL, &timing_rm, &timing_rm, &timing_rm, NULL, &timing_rm, /*f0*/ NULL, &timing_rm, &timing_rm, &timing_rm, NULL, &timing_rm, NULL, NULL, &timing_rm, &timing_rm, &timing_rm, NULL, &timing_rm, &timing_rm, &timing_rm, NULL, + // clang-format on }; -static int *opcode_timings_0f_mod3[256] = -{ +static int *opcode_timings_0f_mod3[256] = { + // clang-format off /*00*/ CYCLES(20), CYCLES(11), CYCLES(11), CYCLES(10), NULL, CYCLES(195), CYCLES(7), NULL, CYCLES(1000), CYCLES(10000), NULL, NULL, NULL, NULL, NULL, NULL, /*10*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, /*20*/ CYCLES(6), CYCLES(6), CYCLES(6), CYCLES(6), CYCLES(6), CYCLES(6), NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, @@ -104,60 +109,69 @@ static int *opcode_timings_0f_mod3[256] = /*d0*/ NULL, &timing_rr, &timing_rr, &timing_rr, NULL, &timing_rr, NULL, NULL, &timing_rr, &timing_rr, NULL, &timing_rr, &timing_rr, &timing_rr, NULL, &timing_rr, /*e0*/ NULL, &timing_rr, &timing_rr, NULL, NULL, &timing_rr, NULL, NULL, &timing_rr, &timing_rr, NULL, &timing_rr, &timing_rr, &timing_rr, NULL, &timing_rr, /*f0*/ NULL, &timing_rr, &timing_rr, &timing_rr, NULL, &timing_rr, NULL, NULL, &timing_rr, &timing_rr, &timing_rr, NULL, &timing_rr, &timing_rr, &timing_rr, NULL, + // clang-format on }; -static int *opcode_timings_shift[8] = -{ +static int *opcode_timings_shift[8] = { + // clang-format off CYCLES(7), CYCLES(7), CYCLES(10), CYCLES(10), CYCLES(7), CYCLES(7), CYCLES(7), CYCLES(7) }; -static int *opcode_timings_shift_mod3[8] = -{ +static int *opcode_timings_shift_mod3[8] = { +// clang-format off CYCLES(3), CYCLES(3), CYCLES(9), CYCLES(9), CYCLES(3), CYCLES(3), CYCLES(3), CYCLES(3) + // clang-format on }; -static int *opcode_timings_f6[8] = -{ +static int *opcode_timings_f6[8] = { + // clang-format off &timing_rm, NULL, &timing_mm, &timing_mm, CYCLES(13), CYCLES(14), CYCLES(16), CYCLES(19) + // clang-format on }; -static int *opcode_timings_f6_mod3[8] = -{ +static int *opcode_timings_f6_mod3[8] = { + // clang-format off &timing_rr, NULL, &timing_rr, &timing_rr, CYCLES(13), CYCLES(14), CYCLES(16), CYCLES(19) + // clang-format on }; -static int *opcode_timings_f7[8] = -{ +static int *opcode_timings_f7[8] = { + // clang-format off &timing_rm, NULL, &timing_mm, &timing_mm, CYCLES(21), CYCLES2(22,38), CYCLES2(24,40), CYCLES2(27,43) + // clang-format on }; -static int *opcode_timings_f7_mod3[8] = -{ +static int *opcode_timings_f7_mod3[8] = { + // clang-format off &timing_rr, NULL, &timing_rr, &timing_rr, CYCLES(21), CYCLES2(22,38), CYCLES2(24,40), CYCLES2(27,43) }; -static int *opcode_timings_ff[8] = -{ +static int *opcode_timings_ff[8] = { +// clang-format off &timing_mm, &timing_mm, CYCLES(5), CYCLES(0), CYCLES(5), CYCLES(0), CYCLES(5), NULL }; -static int *opcode_timings_ff_mod3[8] = -{ +static int *opcode_timings_ff_mod3[8] = { +// clang-format off &timing_rr, &timing_rr, CYCLES(5), CYCLES(0), CYCLES(5), CYCLES(0), CYCLES(5), NULL + // clang-format on }; -static int *opcode_timings_d8[8] = -{ +static int *opcode_timings_d8[8] = { + // clang-format off /* FADDil FMULil FCOMil FCOMPil FSUBil FSUBRil FDIVil FDIVRil*/ CYCLES(8), CYCLES(11), CYCLES(4), CYCLES(4), CYCLES(8), CYCLES(8), CYCLES(73), CYCLES(73) + // clang-format on }; -static int *opcode_timings_d8_mod3[8] = -{ +static int *opcode_timings_d8_mod3[8] = { + // clang-format off /* FADD FMUL FCOM FCOMP FSUB FSUBR FDIV FDIVR*/ CYCLES(8), CYCLES(16), CYCLES(4), CYCLES(4), CYCLES(8), CYCLES(8), CYCLES(73), CYCLES(73) + // clang-format on }; -static int *opcode_timings_d9[8] = -{ +static int *opcode_timings_d9[8] = { + // clang-format off /* FLDs FSTs FSTPs FLDENV FLDCW FSTENV FSTCW*/ CYCLES(3), NULL, CYCLES(7), CYCLES(7), CYCLES(34), CYCLES(4), CYCLES(67), CYCLES(3) + // clang-format on }; -static int *opcode_timings_d9_mod3[64] = -{ +static int *opcode_timings_d9_mod3[64] = { + // clang-format off /*FLD*/ CYCLES(4), CYCLES(4), CYCLES(4), CYCLES(4), CYCLES(4), CYCLES(4), CYCLES(4), CYCLES(4), /*FXCH*/ @@ -174,26 +188,29 @@ static int *opcode_timings_d9_mod3[64] = CYCLES(140), CYCLES(196), CYCLES(200), CYCLES(218), NULL, NULL, CYCLES(3), CYCLES(3), /* opFPREM opFSQRT opFSINCOS opFRNDINT opFSCALE opFSIN opFCOS*/ CYCLES(70), NULL, CYCLES(83), CYCLES(292), CYCLES(21), CYCLES(30), CYCLES(257), CYCLES(257) + // clang-format on }; -static int *opcode_timings_da[8] = -{ +static int *opcode_timings_da[8] = { + // clang-format off /* FADDil FMULil FCOMil FCOMPil FSUBil FSUBRil FDIVil FDIVRil*/ CYCLES(8), CYCLES(11), CYCLES(4), CYCLES(4), CYCLES(8), CYCLES(8), CYCLES(73), CYCLES(73) + // clang-format on }; -static int *opcode_timings_da_mod3[8] = -{ +static int *opcode_timings_da_mod3[8] = { + // clang-format off NULL, NULL, NULL, NULL, NULL, CYCLES(5), NULL, NULL + // clang-format on }; - -static int *opcode_timings_db[8] = -{ +static int *opcode_timings_db[8] = { + // clang-format off /* FLDil FSTil FSTPil FLDe FSTPe*/ CYCLES(9), NULL, CYCLES(28), CYCLES(28), NULL, CYCLES(5), NULL, CYCLES(6) + // clang-format on }; -static int *opcode_timings_db_mod3[64] = -{ +static int *opcode_timings_db_mod3[64] = { + // clang-format off NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, @@ -203,219 +220,242 @@ static int *opcode_timings_db_mod3[64] = NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + // clang-format on }; -static int *opcode_timings_dc[8] = -{ +static int *opcode_timings_dc[8] = { + // clang-format off /* opFADDd_a16 opFMULd_a16 opFCOMd_a16 opFCOMPd_a16 opFSUBd_a16 opFSUBRd_a16 opFDIVd_a16 opFDIVRd_a16*/ CYCLES(8), CYCLES(11), CYCLES(4), CYCLES(4), CYCLES(8), CYCLES(8), CYCLES(73), CYCLES(73) + // clang-format on }; -static int *opcode_timings_dc_mod3[8] = -{ +static int *opcode_timings_dc_mod3[8] = { + // clang-format off /* opFADDr opFMULr opFSUBRr opFSUBr opFDIVRr opFDIVr*/ CYCLES(8), CYCLES(16), NULL, NULL, CYCLES(8), CYCLES(8), CYCLES(73), CYCLES(73) + // clang-format on }; -static int *opcode_timings_dd[8] = -{ +static int *opcode_timings_dd[8] = { + // clang-format off /* FLDd FSTd FSTPd FRSTOR FSAVE FSTSW*/ CYCLES(3), NULL, CYCLES(8), CYCLES(8), CYCLES(131), NULL, CYCLES(154), CYCLES(3) + // clang-format on }; -static int *opcode_timings_dd_mod3[8] = -{ +static int *opcode_timings_dd_mod3[8] = { + // clang-format off /* FFFREE FST FSTP FUCOM FUCOMP*/ CYCLES(3), NULL, CYCLES(3), CYCLES(3), CYCLES(4), CYCLES(4), NULL, NULL + // clang-format on }; -static int *opcode_timings_de[8] = -{ +static int *opcode_timings_de[8] = { + // clang-format off /* FADDiw FMULiw FCOMiw FCOMPiw FSUBil FSUBRil FDIVil FDIVRil*/ CYCLES(8), CYCLES(11), CYCLES(4), CYCLES(4), CYCLES(8), CYCLES(8), CYCLES(73), CYCLES(73) + // clang-format on }; -static int *opcode_timings_de_mod3[8] = -{ +static int *opcode_timings_de_mod3[8] = { + // clang-format off /* FADD FMUL FCOMPP FSUB FSUBR FDIV FDIVR*/ CYCLES(8), CYCLES(16), NULL, CYCLES(5), CYCLES(8), CYCLES(8), CYCLES(73), CYCLES(73) + // clang-format on }; -static int *opcode_timings_df[8] = -{ +static int *opcode_timings_df[8] = { + // clang-format off /* FILDiw FISTiw FISTPiw FILDiq FBSTP FISTPiq*/ CYCLES(13), NULL, CYCLES(29), CYCLES(29), NULL, CYCLES(10), CYCLES(172), CYCLES(28) + // clang-format on }; -static int *opcode_timings_df_mod3[8] = -{ +static int *opcode_timings_df_mod3[8] = { + // clang-format off /* FFREE FST FSTP FUCOM FUCOMP*/ CYCLES(3), NULL, CYCLES(3), CYCLES(3), CYCLES(4), CYCLES(4), NULL, NULL + // clang-format on }; -static int *opcode_timings_8x[8] = -{ +static int *opcode_timings_8x[8] = { + // clang-format off &timing_mr, &timing_mr, &timing_mr, &timing_mr, &timing_mr, &timing_mr, &timing_mr, &timing_rm + // clang-format on }; -static int *opcode_timings_8x_mod3[8] = -{ +static int *opcode_timings_8x_mod3[8] = { + // clang-format off &timing_mr, &timing_mr, &timing_mr, &timing_mr, &timing_mr, &timing_mr, &timing_mr, &timing_rm + // clang-format on }; -static int *opcode_timings_81[8] = -{ +static int *opcode_timings_81[8] = { + // clang-format off &timing_mr, &timing_mr, &timing_mr, &timing_mr, &timing_mr, &timing_mr, &timing_mr, &timing_rm + // clang-format on }; -static int *opcode_timings_81_mod3[8] = -{ +static int *opcode_timings_81_mod3[8] = { + // clang-format off &timing_mr, &timing_mr, &timing_mr, &timing_mr, &timing_mr, &timing_mr, &timing_mr, &timing_rm + // clang-format on }; -static int timing_count; -static uint8_t last_prefix; +static int timing_count; +static uint8_t last_prefix; static uint32_t regmask_modified; -static inline int COUNT(int *c, int op_32) +static inline int +COUNT(int *c, int op_32) { - if ((uintptr_t)c <= 10000) - return (int)(uintptr_t)c; - if (((uintptr_t)c & ~0xffff) == (-1 & ~0xffff)) - { - if (op_32 & 0x100) - return ((uintptr_t)c >> 8) & 0xff; - return (uintptr_t)c & 0xff; - } - return *c; + if ((uintptr_t) c <= 10000) + return (int) (uintptr_t) c; + if (((uintptr_t) c & ~0xffff) == (-1 & ~0xffff)) { + if (op_32 & 0x100) + return ((uintptr_t) c >> 8) & 0xff; + return (uintptr_t) c & 0xff; + } + return *c; } -void codegen_timing_486_block_start() +void +codegen_timing_486_block_start(void) { - regmask_modified = 0; + regmask_modified = 0; } -void codegen_timing_486_start() +void +codegen_timing_486_start(void) { - timing_count = 0; - last_prefix = 0; + timing_count = 0; + last_prefix = 0; } -void codegen_timing_486_prefix(uint8_t prefix, uint32_t fetchdat) +void +codegen_timing_486_prefix(uint8_t prefix, uint32_t fetchdat) { - timing_count += COUNT(opcode_timings[prefix], 0); - last_prefix = prefix; + timing_count += COUNT(opcode_timings[prefix], 0); + last_prefix = prefix; } -void codegen_timing_486_opcode(uint8_t opcode, uint32_t fetchdat, int op_32, uint32_t op_pc) +void +codegen_timing_486_opcode(uint8_t opcode, uint32_t fetchdat, int op_32, UNUSED(uint32_t op_pc)) { - int **timings; - uint64_t *deps; - int mod3 = ((fetchdat & 0xc0) == 0xc0); - int bit8 = !(opcode & 1); - - switch (last_prefix) - { - case 0x0f: - timings = mod3 ? opcode_timings_0f_mod3 : opcode_timings_0f; - deps = mod3 ? opcode_deps_0f_mod3 : opcode_deps_0f; - break; - - case 0xd8: - timings = mod3 ? opcode_timings_d8_mod3 : opcode_timings_d8; - deps = mod3 ? opcode_deps_d8_mod3 : opcode_deps_d8; - opcode = (opcode >> 3) & 7; - break; - case 0xd9: - timings = mod3 ? opcode_timings_d9_mod3 : opcode_timings_d9; - deps = mod3 ? opcode_deps_d9_mod3 : opcode_deps_d9; - opcode = mod3 ? opcode & 0x3f : (opcode >> 3) & 7; - break; - case 0xda: - timings = mod3 ? opcode_timings_da_mod3 : opcode_timings_da; - deps = mod3 ? opcode_deps_da_mod3 : opcode_deps_da; - opcode = (opcode >> 3) & 7; - break; - case 0xdb: - timings = mod3 ? opcode_timings_db_mod3 : opcode_timings_db; - deps = mod3 ? opcode_deps_db_mod3 : opcode_deps_db; - opcode = mod3 ? opcode & 0x3f : (opcode >> 3) & 7; - break; - case 0xdc: - timings = mod3 ? opcode_timings_dc_mod3 : opcode_timings_dc; - deps = mod3 ? opcode_deps_dc_mod3 : opcode_deps_dc; - opcode = (opcode >> 3) & 7; - break; - case 0xdd: - timings = mod3 ? opcode_timings_dd_mod3 : opcode_timings_dd; - deps = mod3 ? opcode_deps_dd_mod3 : opcode_deps_dd; - opcode = (opcode >> 3) & 7; - break; - case 0xde: - timings = mod3 ? opcode_timings_de_mod3 : opcode_timings_de; - deps = mod3 ? opcode_deps_de_mod3 : opcode_deps_de; - opcode = (opcode >> 3) & 7; - break; - case 0xdf: - timings = mod3 ? opcode_timings_df_mod3 : opcode_timings_df; - deps = mod3 ? opcode_deps_df_mod3 : opcode_deps_df; - opcode = (opcode >> 3) & 7; - break; + int **timings; + const uint64_t *deps; + int mod3 = ((fetchdat & 0xc0) == 0xc0); + int bit8 = !(opcode & 1); + + switch (last_prefix) { + case 0x0f: + timings = mod3 ? opcode_timings_0f_mod3 : opcode_timings_0f; + deps = mod3 ? opcode_deps_0f_mod3 : opcode_deps_0f; + break; + + case 0xd8: + timings = mod3 ? opcode_timings_d8_mod3 : opcode_timings_d8; + deps = mod3 ? opcode_deps_d8_mod3 : opcode_deps_d8; + opcode = (opcode >> 3) & 7; + break; + case 0xd9: + timings = mod3 ? opcode_timings_d9_mod3 : opcode_timings_d9; + deps = mod3 ? opcode_deps_d9_mod3 : opcode_deps_d9; + opcode = mod3 ? opcode & 0x3f : (opcode >> 3) & 7; + break; + case 0xda: + timings = mod3 ? opcode_timings_da_mod3 : opcode_timings_da; + deps = mod3 ? opcode_deps_da_mod3 : opcode_deps_da; + opcode = (opcode >> 3) & 7; + break; + case 0xdb: + timings = mod3 ? opcode_timings_db_mod3 : opcode_timings_db; + deps = mod3 ? opcode_deps_db_mod3 : opcode_deps_db; + opcode = mod3 ? opcode & 0x3f : (opcode >> 3) & 7; + break; + case 0xdc: + timings = mod3 ? opcode_timings_dc_mod3 : opcode_timings_dc; + deps = mod3 ? opcode_deps_dc_mod3 : opcode_deps_dc; + opcode = (opcode >> 3) & 7; + break; + case 0xdd: + timings = mod3 ? opcode_timings_dd_mod3 : opcode_timings_dd; + deps = mod3 ? opcode_deps_dd_mod3 : opcode_deps_dd; + opcode = (opcode >> 3) & 7; + break; + case 0xde: + timings = mod3 ? opcode_timings_de_mod3 : opcode_timings_de; + deps = mod3 ? opcode_deps_de_mod3 : opcode_deps_de; + opcode = (opcode >> 3) & 7; + break; + case 0xdf: + timings = mod3 ? opcode_timings_df_mod3 : opcode_timings_df; + deps = mod3 ? opcode_deps_df_mod3 : opcode_deps_df; + opcode = (opcode >> 3) & 7; + break; + + default: + switch (opcode) { + case 0x80: + case 0x82: + case 0x83: + timings = mod3 ? opcode_timings_8x_mod3 : opcode_timings_8x; + deps = mod3 ? opcode_deps_8x_mod3 : opcode_deps_8x; + opcode = (fetchdat >> 3) & 7; + break; + case 0x81: + timings = mod3 ? opcode_timings_81_mod3 : opcode_timings_81; + deps = mod3 ? opcode_deps_81_mod3 : opcode_deps_81; + opcode = (fetchdat >> 3) & 7; + break; + + case 0xc0: + case 0xc1: + case 0xd0: + case 0xd1: + case 0xd2: + case 0xd3: + timings = mod3 ? opcode_timings_shift_mod3 : opcode_timings_shift; + deps = mod3 ? opcode_deps_shift_mod3 : opcode_deps_shift; + opcode = (fetchdat >> 3) & 7; + break; + + case 0xf6: + timings = mod3 ? opcode_timings_f6_mod3 : opcode_timings_f6; + deps = mod3 ? opcode_deps_f6_mod3 : opcode_deps_f6; + opcode = (fetchdat >> 3) & 7; + break; + case 0xf7: + timings = mod3 ? opcode_timings_f7_mod3 : opcode_timings_f7; + deps = mod3 ? opcode_deps_f7_mod3 : opcode_deps_f7; + opcode = (fetchdat >> 3) & 7; + break; + case 0xff: + timings = mod3 ? opcode_timings_ff_mod3 : opcode_timings_ff; + deps = mod3 ? opcode_deps_ff_mod3 : opcode_deps_ff; + opcode = (fetchdat >> 3) & 7; + break; default: - switch (opcode) - { - case 0x80: case 0x82: case 0x83: - timings = mod3 ? opcode_timings_8x_mod3 : opcode_timings_8x; - deps = mod3 ? opcode_deps_8x_mod3 : opcode_deps_8x; - opcode = (fetchdat >> 3) & 7; - break; - case 0x81: - timings = mod3 ? opcode_timings_81_mod3 : opcode_timings_81; - deps = mod3 ? opcode_deps_81_mod3 : opcode_deps_81; - opcode = (fetchdat >> 3) & 7; - break; - - case 0xc0: case 0xc1: case 0xd0: case 0xd1: case 0xd2: case 0xd3: - timings = mod3 ? opcode_timings_shift_mod3 : opcode_timings_shift; - deps = mod3 ? opcode_deps_shift_mod3 : opcode_deps_shift; - opcode = (fetchdat >> 3) & 7; - break; - - case 0xf6: - timings = mod3 ? opcode_timings_f6_mod3 : opcode_timings_f6; - deps = mod3 ? opcode_deps_f6_mod3 : opcode_deps_f6; - opcode = (fetchdat >> 3) & 7; - break; - case 0xf7: - timings = mod3 ? opcode_timings_f7_mod3 : opcode_timings_f7; - deps = mod3 ? opcode_deps_f7_mod3 : opcode_deps_f7; - opcode = (fetchdat >> 3) & 7; - break; - case 0xff: - timings = mod3 ? opcode_timings_ff_mod3 : opcode_timings_ff; - deps = mod3 ? opcode_deps_ff_mod3 : opcode_deps_ff; - opcode = (fetchdat >> 3) & 7; - break; + timings = mod3 ? opcode_timings_mod3 : opcode_timings; + deps = mod3 ? opcode_deps_mod3 : opcode_deps; + break; + } + } - default: - timings = mod3 ? opcode_timings_mod3 : opcode_timings; - deps = mod3 ? opcode_deps_mod3 : opcode_deps; - break; - } - } - - timing_count += COUNT(timings[opcode], op_32); - if (regmask_modified & get_addr_regmask(deps[opcode], fetchdat, op_32)) - timing_count++; /*AGI stall*/ - codegen_block_cycles += timing_count; - - regmask_modified = get_dstdep_mask(deps[opcode], fetchdat, bit8); + timing_count += COUNT(timings[opcode], op_32); + if (regmask_modified & get_addr_regmask(deps[opcode], fetchdat, op_32)) + timing_count++; /*AGI stall*/ + codegen_block_cycles += timing_count; + + regmask_modified = get_dstdep_mask(deps[opcode], fetchdat, bit8); } -void codegen_timing_486_block_end() +void +codegen_timing_486_block_end(void) { + // } -codegen_timing_t codegen_timing_486 = -{ - codegen_timing_486_start, - codegen_timing_486_prefix, - codegen_timing_486_opcode, - codegen_timing_486_block_start, - codegen_timing_486_block_end, - NULL +codegen_timing_t codegen_timing_486 = { + codegen_timing_486_start, + codegen_timing_486_prefix, + codegen_timing_486_opcode, + codegen_timing_486_block_start, + codegen_timing_486_block_end, + NULL }; diff --git a/src/cpu/codegen_timing_686.c b/src/cpu/codegen_timing_686.c index ff7ff54d2..a6800c5b2 100644 --- a/src/cpu/codegen_timing_686.c +++ b/src/cpu/codegen_timing_686.c @@ -13,8 +13,10 @@ #include #include #include <86box/86box.h> -#include <86box/mem.h> #include "cpu.h" +#include <86box/mem.h> +#include <86box/plat_unused.h> + #include "x86.h" #include "x86_ops.h" #include "x87.h" @@ -22,7 +24,7 @@ #include "codegen_timing_common.h" /*Instruction has different execution time for 16 and 32 bit data. Does not pair */ -#define CYCLES_HAS_MULTI (1 << 31) +#define CYCLES_HAS_MULTI (1 << 31) #define CYCLES_MULTI(c16, c32) (CYCLES_HAS_MULTI | c16 | (c32 << 8)) @@ -31,39 +33,39 @@ /*Instruction follows either register timing, read-modify, or read-modify-write. May be pairable*/ -#define CYCLES_REG (1 << 0) -#define CYCLES_RM (1 << 0) -#define CYCLES_RMW (1 << 0) +#define CYCLES_REG (1 << 0) +#define CYCLES_RM (1 << 0) +#define CYCLES_RMW (1 << 0) #define CYCLES_BRANCH (1 << 0) -#define CYCLES_MASK ((1 << 7) - 1) +#define CYCLES_MASK ((1 << 7) - 1) /*Instruction does not pair*/ #define PAIR_NP (0 << 29) /*Instruction pairs in X pipe only*/ -#define PAIR_X (1 << 29) +#define PAIR_X (1 << 29) /*Instruction pairs in X pipe only, and can not pair with a following instruction*/ -#define PAIR_X_BRANCH (2 << 29) +#define PAIR_X_BRANCH (2 << 29) /*Instruction pairs in both X and Y pipes*/ -#define PAIR_XY (3 << 29) +#define PAIR_XY (3 << 29) #define PAIR_MASK (3 << 29) -#define INVALID 0 +#define INVALID 0 -static int prev_full; -static uint32_t prev_opcode; +static int prev_full; +static uint32_t prev_opcode; static uint32_t *prev_timings; -static uint32_t prev_op_32; -static uint32_t prev_regmask; +static uint32_t prev_op_32; +static uint32_t prev_regmask; static uint64_t *prev_deps; -static uint32_t prev_fetchdat; +static uint32_t prev_fetchdat; static uint32_t last_regmask_modified; static uint32_t regmask_modified; -static uint32_t opcode_timings[256] = -{ +static uint32_t opcode_timings[256] = { + // clang-format off /* ADD ADD ADD ADD*/ /*00*/ PAIR_XY | CYCLES_RMW, PAIR_XY | CYCLES_RMW, PAIR_XY | CYCLES_RM, PAIR_XY | CYCLES_RM, /* ADD ADD PUSH ES POP ES*/ @@ -77,7 +79,7 @@ static uint32_t opcode_timings[256] = /*10*/ PAIR_XY | CYCLES_RMW, PAIR_XY | CYCLES_RMW, PAIR_XY | CYCLES_RM, PAIR_XY | CYCLES_RM, /* ADC ADC PUSH SS POP SS*/ PAIR_XY | CYCLES_REG, PAIR_XY | CYCLES_REG, PAIR_NP | CYCLES(1), PAIR_NP | CYCLES(3), -/* SBB SBB SBB SBB*/ +/* SBB SBB SBB SBB*/ PAIR_XY | CYCLES_RMW, PAIR_XY | CYCLES_RMW, PAIR_XY | CYCLES_RM, PAIR_XY | CYCLES_RM, /* SBB SBB PUSH DS POP DS*/ PAIR_XY | CYCLES_REG, PAIR_XY | CYCLES_REG, PAIR_NP | CYCLES(1), PAIR_NP | CYCLES(3), @@ -90,7 +92,7 @@ static uint32_t opcode_timings[256] = PAIR_XY | CYCLES_RMW, PAIR_XY | CYCLES_RMW, PAIR_XY | CYCLES_RM, PAIR_XY | CYCLES_RM, /* SUB SUB DAS*/ PAIR_XY | CYCLES_REG, PAIR_XY | CYCLES_REG, INVALID, PAIR_NP | CYCLES(7), - + /* XOR XOR XOR XOR*/ /*30*/ PAIR_XY | CYCLES_RMW, PAIR_XY | CYCLES_RMW, PAIR_XY | CYCLES_RM, PAIR_XY | CYCLES_RM, /* XOR XOR AAA*/ @@ -108,7 +110,7 @@ static uint32_t opcode_timings[256] = PAIR_XY | CYCLES_REG, PAIR_XY | CYCLES_REG, PAIR_XY | CYCLES_REG, PAIR_XY | CYCLES_REG, /* DEC ESP DEC EBP DEC ESI DEC EDI*/ PAIR_XY | CYCLES_REG, PAIR_XY | CYCLES_REG, PAIR_XY | CYCLES_REG, PAIR_XY | CYCLES_REG, - + /* PUSH EAX PUSH ECX PUSH EDX PUSH EBX*/ /*50*/ PAIR_XY | CYCLES_REG, PAIR_XY | CYCLES_REG, PAIR_XY | CYCLES_REG, PAIR_XY | CYCLES_REG, /* PUSH ESP PUSH EBP PUSH ESI PUSH EDI*/ @@ -125,8 +127,8 @@ static uint32_t opcode_timings[256] = PAIR_XY | CYCLES_REG, PAIR_NP | CYCLES(10), PAIR_XY | CYCLES_REG, PAIR_NP | CYCLES(10), /* INSB INSW OUTSB OUTSW*/ PAIR_NP | CYCLES(14), PAIR_NP | CYCLES(14), PAIR_NP | CYCLES(14), PAIR_NP | CYCLES(14), - -/* Jxx*/ + +/* Jxx*/ /*70*/ PAIR_X_BRANCH | CYCLES_BRANCH, PAIR_X_BRANCH | CYCLES_BRANCH, PAIR_X_BRANCH | CYCLES_BRANCH, PAIR_X_BRANCH | CYCLES_BRANCH, PAIR_X_BRANCH | CYCLES_BRANCH, PAIR_X_BRANCH | CYCLES_BRANCH, PAIR_X_BRANCH | CYCLES_BRANCH, PAIR_X_BRANCH | CYCLES_BRANCH, PAIR_X_BRANCH | CYCLES_BRANCH, PAIR_X_BRANCH | CYCLES_BRANCH, PAIR_X_BRANCH | CYCLES_BRANCH, PAIR_X_BRANCH | CYCLES_BRANCH, @@ -139,7 +141,7 @@ static uint32_t opcode_timings[256] = PAIR_XY | CYCLES_REG, PAIR_XY | CYCLES_REG, PAIR_XY | CYCLES_REG, PAIR_XY | CYCLES_REG, /* MOV from seg LEA MOV to seg POP*/ PAIR_XY | CYCLES(1), PAIR_XY | CYCLES_REG, CYCLES(3), PAIR_XY | CYCLES(1), - + /* NOP XCHG XCHG XCHG*/ /*90*/ PAIR_XY | CYCLES_REG, PAIR_XY | CYCLES(2), PAIR_XY | CYCLES(2), PAIR_XY | CYCLES(2), /* XCHG XCHG XCHG XCHG*/ @@ -149,7 +151,7 @@ static uint32_t opcode_timings[256] = /* PUSHF POPF SAHF LAHF*/ PAIR_XY | CYCLES(2), PAIR_XY | CYCLES(9), PAIR_XY | CYCLES(1), PAIR_XY | CYCLES(2), -/* MOV MOV MOV MOV*/ +/* MOV MOV MOV MOV*/ /*a0*/ PAIR_XY | CYCLES_REG, PAIR_XY | CYCLES_REG, PAIR_XY | CYCLES_REG, PAIR_XY | CYCLES_REG, /* MOVSB MOVSW CMPSB CMPSW*/ PAIR_NP | CYCLES(4), PAIR_NP | CYCLES(4), PAIR_NP | CYCLES(5), PAIR_NP | CYCLES(5), @@ -177,7 +179,7 @@ static uint32_t opcode_timings[256] = /*d0*/ INVALID, INVALID, INVALID, INVALID, /* AAM AAD SETALC XLAT*/ PAIR_XY | CYCLES(18), PAIR_XY | CYCLES(7), PAIR_XY | CYCLES(2), PAIR_XY | CYCLES(4), - INVALID, INVALID, INVALID, INVALID, + INVALID, INVALID, INVALID, INVALID, INVALID, INVALID, INVALID, INVALID, /* LOOPNE LOOPE LOOP JCXZ*/ /*e0*/ PAIR_X_BRANCH| CYCLES_BRANCH, PAIR_X_BRANCH | CYCLES_BRANCH, PAIR_X_BRANCH | CYCLES_BRANCH, PAIR_X_BRANCH | CYCLES_BRANCH, @@ -196,10 +198,11 @@ static uint32_t opcode_timings[256] = PAIR_XY | CYCLES(1), PAIR_XY | CYCLES(1), PAIR_XY | CYCLES(7), PAIR_XY | CYCLES(7), /* CLD STD INCDEC*/ PAIR_XY | CYCLES(7), PAIR_XY | CYCLES(7), PAIR_XY | CYCLES_RMW, INVALID + // clang-format on }; -static uint32_t opcode_timings_mod3[256] = -{ +static uint32_t opcode_timings_mod3[256] = { + // clang-format off /* ADD ADD ADD ADD*/ /*00*/ PAIR_XY | CYCLES_REG, PAIR_XY | CYCLES_REG, PAIR_XY | CYCLES_REG, PAIR_XY | CYCLES_REG, /* ADD ADD PUSH ES POP ES*/ @@ -213,7 +216,7 @@ static uint32_t opcode_timings_mod3[256] = /*10*/ PAIR_XY | CYCLES_REG, PAIR_XY | CYCLES_REG, PAIR_XY | CYCLES_REG, PAIR_XY | CYCLES_REG, /* ADC ADC PUSH SS POP SS*/ PAIR_XY | CYCLES_REG, PAIR_XY | CYCLES_REG, PAIR_NP | CYCLES(1), PAIR_NP | CYCLES(3), -/* SBB SBB SBB SBB*/ +/* SBB SBB SBB SBB*/ PAIR_XY | CYCLES_REG, PAIR_XY | CYCLES_REG, PAIR_XY | CYCLES_REG, PAIR_XY | CYCLES_REG, /* SBB SBB PUSH DS POP DS*/ PAIR_XY | CYCLES_REG, PAIR_XY | CYCLES_REG, PAIR_NP | CYCLES(1), PAIR_NP | CYCLES(3), @@ -226,7 +229,7 @@ static uint32_t opcode_timings_mod3[256] = PAIR_XY | CYCLES_REG, PAIR_XY | CYCLES_REG, PAIR_XY | CYCLES_REG, PAIR_XY | CYCLES_REG, /* SUB SUB DAS*/ PAIR_XY | CYCLES_REG, PAIR_XY | CYCLES_REG, INVALID, PAIR_NP | CYCLES(7), - + /* XOR XOR XOR XOR*/ /*30*/ PAIR_XY | CYCLES_REG, PAIR_XY | CYCLES_REG, PAIR_XY | CYCLES_REG, PAIR_XY | CYCLES_REG, /* XOR XOR AAA*/ @@ -244,7 +247,7 @@ static uint32_t opcode_timings_mod3[256] = PAIR_XY | CYCLES_REG, PAIR_XY | CYCLES_REG, PAIR_XY | CYCLES_REG, PAIR_XY | CYCLES_REG, /* DEC ESP DEC EBP DEC ESI DEC EDI*/ PAIR_XY | CYCLES_REG, PAIR_XY | CYCLES_REG, PAIR_XY | CYCLES_REG, PAIR_XY | CYCLES_REG, - + /* PUSH EAX PUSH ECX PUSH EDX PUSH EBX*/ /*50*/ PAIR_XY | CYCLES_REG, PAIR_XY | CYCLES_REG, PAIR_XY | CYCLES_REG, PAIR_XY | CYCLES_REG, /* PUSH ESP PUSH EBP PUSH ESI PUSH EDI*/ @@ -261,8 +264,8 @@ static uint32_t opcode_timings_mod3[256] = PAIR_XY | CYCLES_REG, PAIR_XY | CYCLES(10), PAIR_XY | CYCLES_REG, PAIR_XY | CYCLES(10), /* INSB INSW OUTSB OUTSW*/ PAIR_NP | CYCLES(14), PAIR_NP | CYCLES(14), PAIR_NP | CYCLES(14), PAIR_NP | CYCLES(14), - -/* Jxx*/ + +/* Jxx*/ /*70*/ PAIR_X_BRANCH | CYCLES_BRANCH, PAIR_X_BRANCH | CYCLES_BRANCH, PAIR_X_BRANCH | CYCLES_BRANCH, PAIR_X_BRANCH | CYCLES_BRANCH, PAIR_X_BRANCH | CYCLES_BRANCH, PAIR_X_BRANCH | CYCLES_BRANCH, PAIR_X_BRANCH | CYCLES_BRANCH, PAIR_X_BRANCH | CYCLES_BRANCH, PAIR_X_BRANCH | CYCLES_BRANCH, PAIR_X_BRANCH | CYCLES_BRANCH, PAIR_X_BRANCH | CYCLES_BRANCH, PAIR_X_BRANCH | CYCLES_BRANCH, @@ -275,7 +278,7 @@ static uint32_t opcode_timings_mod3[256] = PAIR_XY | CYCLES_REG, PAIR_XY | CYCLES_REG, PAIR_XY | CYCLES_REG, PAIR_XY | CYCLES_REG, /* MOV from seg LEA MOV to seg POP*/ PAIR_XY | CYCLES(1), PAIR_XY | CYCLES_REG, PAIR_NP | CYCLES(3), PAIR_XY | CYCLES(1), - + /* NOP XCHG XCHG XCHG*/ /*90*/ PAIR_XY | CYCLES_REG, PAIR_XY | CYCLES(2), PAIR_XY | CYCLES(2), PAIR_XY | CYCLES(2), /* XCHG XCHG XCHG XCHG*/ @@ -285,8 +288,8 @@ static uint32_t opcode_timings_mod3[256] = /* PUSHF POPF SAHF LAHF*/ PAIR_XY | CYCLES(2), PAIR_XY | CYCLES(9), PAIR_XY | CYCLES(1), PAIR_XY | CYCLES(2), -/* MOV MOV MOV MOV*/ -/*a0*/ PAIR_XY | CYCLES_REG, PAIR_XY | CYCLES_REG, PAIR_XY | CYCLES_REG, PAIR_XY | CYCLES_REG, +/* MOV MOV MOV MOV*/ +/*a0*/ PAIR_XY | CYCLES_REG, PAIR_XY | CYCLES_REG, PAIR_XY | CYCLES_REG, PAIR_XY | CYCLES_REG, /* MOVSB MOVSW CMPSB CMPSW*/ PAIR_NP | CYCLES(4), PAIR_NP | CYCLES(4), PAIR_NP | CYCLES(5), PAIR_NP | CYCLES(5), /* TEST TEST STOSB STOSW*/ @@ -313,7 +316,7 @@ static uint32_t opcode_timings_mod3[256] = /*d0*/ INVALID, INVALID, INVALID, INVALID, /* AAM AAD SETALC XLAT*/ PAIR_XY | CYCLES(18), PAIR_XY | CYCLES(7), PAIR_XY | CYCLES(2), PAIR_XY | CYCLES(4), - INVALID, INVALID, INVALID, INVALID, + INVALID, INVALID, INVALID, INVALID, INVALID, INVALID, INVALID, INVALID, /* LOOPNE LOOPE LOOP JCXZ*/ @@ -333,10 +336,11 @@ static uint32_t opcode_timings_mod3[256] = PAIR_XY | CYCLES(1), PAIR_XY | CYCLES(1), PAIR_XY | CYCLES(7), PAIR_XY | CYCLES(7), /* CLD STD INCDEC*/ PAIR_XY | CYCLES(7), PAIR_XY | CYCLES(7), PAIR_XY | CYCLES_REG, INVALID + // clang-format on }; -static uint32_t opcode_timings_0f[256] = -{ +static uint32_t opcode_timings_0f[256] = { + // clang-format off /*00*/ PAIR_NP | CYCLES(20), PAIR_NP | CYCLES(11), PAIR_NP | CYCLES(11), PAIR_NP | CYCLES(10), INVALID, PAIR_NP | CYCLES(195), PAIR_NP | CYCLES(7), INVALID, PAIR_NP | CYCLES(1000), PAIR_NP | CYCLES(10000), INVALID, INVALID, @@ -346,12 +350,12 @@ static uint32_t opcode_timings_0f[256] = INVALID, INVALID, INVALID, INVALID, INVALID, INVALID, INVALID, INVALID, INVALID, INVALID, INVALID, INVALID, - + /*20*/ PAIR_NP | CYCLES(6), PAIR_NP | CYCLES(6), PAIR_NP | CYCLES(6), PAIR_NP | CYCLES(6), PAIR_NP | CYCLES(6), PAIR_NP | CYCLES(6), INVALID, INVALID, INVALID, INVALID, INVALID, INVALID, INVALID, INVALID, INVALID, INVALID, - + /*30*/ PAIR_NP | CYCLES(9), CYCLES(1), PAIR_NP | CYCLES(9), INVALID, INVALID, INVALID, INVALID, INVALID, INVALID, INVALID, INVALID, INVALID, @@ -361,17 +365,17 @@ static uint32_t opcode_timings_0f[256] = PAIR_XY | CYCLES(1), PAIR_XY | CYCLES(1), PAIR_XY | CYCLES(1), PAIR_XY | CYCLES(1), PAIR_XY | CYCLES(1), PAIR_XY | CYCLES(1), PAIR_XY | CYCLES(1), PAIR_XY | CYCLES(1), PAIR_XY | CYCLES(1), PAIR_XY | CYCLES(1), PAIR_XY | CYCLES(1), PAIR_XY | CYCLES(1), - + /*50*/ INVALID, INVALID, INVALID, INVALID, INVALID, INVALID, INVALID, INVALID, INVALID, INVALID, INVALID, INVALID, INVALID, INVALID, INVALID, INVALID, - + /*60*/ PAIR_X | CYCLES_RM, PAIR_X | CYCLES_RM, PAIR_X | CYCLES_RM, PAIR_X | CYCLES_RM, PAIR_X | CYCLES_RM, PAIR_X | CYCLES_RM, PAIR_X | CYCLES_RM, PAIR_X | CYCLES_RM, PAIR_X | CYCLES_RM, PAIR_X | CYCLES_RM, PAIR_X | CYCLES_RM, PAIR_X | CYCLES_RM, INVALID, INVALID, PAIR_X | CYCLES_RM, PAIR_X | CYCLES_RM, - + /*70*/ INVALID, PAIR_X | CYCLES_RM, PAIR_X | CYCLES_RM, PAIR_X | CYCLES_RM, PAIR_X | CYCLES_RM, PAIR_X | CYCLES_RM, PAIR_X | CYCLES_RM, PAIR_X | CYCLES(1), INVALID, INVALID, INVALID, INVALID, @@ -381,17 +385,17 @@ static uint32_t opcode_timings_0f[256] = PAIR_X_BRANCH | CYCLES_BRANCH, PAIR_X_BRANCH | CYCLES_BRANCH, PAIR_X_BRANCH | CYCLES_BRANCH, PAIR_X_BRANCH | CYCLES_BRANCH, PAIR_X_BRANCH | CYCLES_BRANCH, PAIR_X_BRANCH | CYCLES_BRANCH, PAIR_X_BRANCH | CYCLES_BRANCH, PAIR_X_BRANCH | CYCLES_BRANCH, PAIR_X_BRANCH | CYCLES_BRANCH, PAIR_X_BRANCH | CYCLES_BRANCH, PAIR_X_BRANCH | CYCLES_BRANCH, PAIR_X_BRANCH | CYCLES_BRANCH, - + /*90*/ PAIR_XY | CYCLES(1), PAIR_XY | CYCLES(1), PAIR_XY | CYCLES(1), PAIR_XY | CYCLES(1), PAIR_XY | CYCLES(1), PAIR_XY | CYCLES(1), PAIR_XY | CYCLES(1), PAIR_XY | CYCLES(1), PAIR_XY | CYCLES(1), PAIR_XY | CYCLES(1), PAIR_XY | CYCLES(1), PAIR_XY | CYCLES(1), PAIR_XY | CYCLES(1), PAIR_XY | CYCLES(1), PAIR_XY | CYCLES(1), PAIR_XY | CYCLES(1), - + /*a0*/ PAIR_XY | CYCLES(3), PAIR_XY | CYCLES(1), PAIR_XY | CYCLES(12), PAIR_XY | CYCLES(5), PAIR_XY | CYCLES(4), PAIR_XY | CYCLES(5), INVALID, INVALID, PAIR_XY | CYCLES(3), PAIR_XY | CYCLES(1), INVALID, PAIR_XY | CYCLES(5), PAIR_NP | CYCLES(4), PAIR_NP | CYCLES(5), INVALID, PAIR_NP | CYCLES(10), - + /*b0*/ PAIR_NP | CYCLES(11), PAIR_NP | CYCLES(11), PAIR_NP | CYCLES(4), PAIR_XY | CYCLES(5), PAIR_NP | CYCLES(4), PAIR_NP | CYCLES(4), PAIR_XY | CYCLES(1), PAIR_XY | CYCLES(1), INVALID, INVALID, PAIR_XY | CYCLES(3), PAIR_XY | CYCLES(5), @@ -406,19 +410,20 @@ static uint32_t opcode_timings_0f[256] = INVALID, PAIR_X | CYCLES_RM, INVALID, INVALID, PAIR_X | CYCLES_RM, PAIR_X | CYCLES_RM, INVALID, PAIR_X | CYCLES_RM, PAIR_X | CYCLES_RM, PAIR_X | CYCLES_RM, INVALID, PAIR_X | CYCLES_RM, - + /*e0*/ INVALID, PAIR_X | CYCLES_RM, PAIR_X | CYCLES_RM, INVALID, INVALID, PAIR_X | CYCLES_RM, INVALID, INVALID, PAIR_X | CYCLES_RM, PAIR_X | CYCLES_RM, INVALID, PAIR_X | CYCLES_RM, PAIR_X | CYCLES_RM, PAIR_X | CYCLES_RM, INVALID, PAIR_X | CYCLES_RM, - + /*f0*/ INVALID, PAIR_X | CYCLES_RM, PAIR_X | CYCLES_RM, PAIR_X | CYCLES_RM, INVALID, PAIR_X | CYCLES_RM, INVALID, INVALID, PAIR_X | CYCLES_RM, PAIR_X | CYCLES_RM, PAIR_X | CYCLES_RM, INVALID, PAIR_X | CYCLES_RM, PAIR_X | CYCLES_RM, PAIR_X | CYCLES_RM, INVALID, + // clang-format on }; -static uint32_t opcode_timings_0f_mod3[256] = -{ +static uint32_t opcode_timings_0f_mod3[256] = { + // clang-format off /*00*/ PAIR_NP | CYCLES(20), PAIR_NP | CYCLES(11), PAIR_NP | CYCLES(11), PAIR_NP | CYCLES(10), INVALID, PAIR_NP | CYCLES(195), PAIR_NP | CYCLES(7), INVALID, PAIR_NP | CYCLES(1000), PAIR_NP | CYCLES(10000), INVALID, INVALID, @@ -428,12 +433,12 @@ static uint32_t opcode_timings_0f_mod3[256] = INVALID, INVALID, INVALID, INVALID, INVALID, INVALID, INVALID, INVALID, INVALID, INVALID, INVALID, INVALID, - + /*20*/ PAIR_NP | CYCLES(6), PAIR_NP | CYCLES(6), PAIR_NP | CYCLES(6), PAIR_NP | CYCLES(6), PAIR_NP | CYCLES(6), PAIR_NP | CYCLES(6), INVALID, INVALID, INVALID, INVALID, INVALID, INVALID, INVALID, INVALID, INVALID, INVALID, - + /*30*/ PAIR_NP | CYCLES(9), CYCLES(1), PAIR_NP | CYCLES(9), INVALID, INVALID, INVALID, INVALID, INVALID, INVALID, INVALID, INVALID, INVALID, @@ -443,17 +448,17 @@ static uint32_t opcode_timings_0f_mod3[256] = PAIR_XY | CYCLES(1), PAIR_XY | CYCLES(1), PAIR_XY | CYCLES(1), PAIR_XY | CYCLES(1), PAIR_XY | CYCLES(1), PAIR_XY | CYCLES(1), PAIR_XY | CYCLES(1), PAIR_XY | CYCLES(1), PAIR_XY | CYCLES(1), PAIR_XY | CYCLES(1), PAIR_XY | CYCLES(1), PAIR_XY | CYCLES(1), - + /*50*/ INVALID, INVALID, INVALID, INVALID, INVALID, INVALID, INVALID, INVALID, INVALID, INVALID, INVALID, INVALID, INVALID, INVALID, INVALID, INVALID, - + /*60*/ PAIR_X | CYCLES_REG, PAIR_X | CYCLES_REG, PAIR_X | CYCLES_REG, PAIR_X | CYCLES_REG, PAIR_X | CYCLES_REG, PAIR_X | CYCLES_REG, PAIR_X | CYCLES_REG, PAIR_X | CYCLES_REG, PAIR_X | CYCLES_REG, PAIR_X | CYCLES_REG, PAIR_X | CYCLES_REG, PAIR_X | CYCLES_REG, INVALID, INVALID, PAIR_X | CYCLES_REG, PAIR_X | CYCLES_REG, - + /*70*/ INVALID, PAIR_X | CYCLES_REG, PAIR_X | CYCLES_REG, PAIR_X | CYCLES_REG, PAIR_X | CYCLES_REG, PAIR_X | CYCLES_REG, PAIR_X | CYCLES_REG, PAIR_X | CYCLES(1), INVALID, INVALID, INVALID, INVALID, @@ -463,17 +468,17 @@ static uint32_t opcode_timings_0f_mod3[256] = PAIR_X_BRANCH | CYCLES_BRANCH, PAIR_X_BRANCH | CYCLES_BRANCH, PAIR_X_BRANCH | CYCLES_BRANCH, PAIR_X_BRANCH | CYCLES_BRANCH, PAIR_X_BRANCH | CYCLES_BRANCH, PAIR_X_BRANCH | CYCLES_BRANCH, PAIR_X_BRANCH | CYCLES_BRANCH, PAIR_X_BRANCH | CYCLES_BRANCH, PAIR_X_BRANCH | CYCLES_BRANCH, PAIR_X_BRANCH | CYCLES_BRANCH, PAIR_X_BRANCH | CYCLES_BRANCH, PAIR_X_BRANCH | CYCLES_BRANCH, - + /*90*/ PAIR_XY | CYCLES(1), PAIR_XY | CYCLES(1), PAIR_XY | CYCLES(1), PAIR_XY | CYCLES(1), PAIR_XY | CYCLES(1), PAIR_XY | CYCLES(1), PAIR_XY | CYCLES(1), PAIR_XY | CYCLES(1), PAIR_XY | CYCLES(1), PAIR_XY | CYCLES(1), PAIR_XY | CYCLES(1), PAIR_XY | CYCLES(1), PAIR_XY | CYCLES(1), PAIR_XY | CYCLES(1), PAIR_XY | CYCLES(1), PAIR_XY | CYCLES(1), - + /*a0*/ PAIR_XY | CYCLES(3), PAIR_XY | CYCLES(1), PAIR_XY | CYCLES(12), PAIR_XY | CYCLES(5), PAIR_XY | CYCLES(4), PAIR_XY | CYCLES(5), INVALID, INVALID, PAIR_XY | CYCLES(3), PAIR_XY | CYCLES(1), INVALID, PAIR_XY | CYCLES(5), PAIR_NP | CYCLES(4), PAIR_NP | CYCLES(5), INVALID, PAIR_NP | CYCLES(10), - + /*b0*/ PAIR_NP | CYCLES(11), PAIR_NP | CYCLES(11), PAIR_NP | CYCLES(4), PAIR_XY | CYCLES(5), PAIR_NP | CYCLES(4), PAIR_NP | CYCLES(4), PAIR_XY | CYCLES(1), PAIR_XY | CYCLES(1), INVALID, INVALID, PAIR_XY | CYCLES(3), PAIR_XY | CYCLES(5), @@ -482,121 +487,137 @@ static uint32_t opcode_timings_0f_mod3[256] = INVALID, INVALID, INVALID, INVALID, PAIR_NP | CYCLES(1), PAIR_NP | CYCLES(1), PAIR_NP | CYCLES(1), PAIR_NP | CYCLES(1), PAIR_NP | CYCLES(1), PAIR_NP | CYCLES(1), PAIR_NP | CYCLES(1), PAIR_NP | CYCLES(1), - + /*d0*/ INVALID, PAIR_X | CYCLES_REG, PAIR_X | CYCLES_REG, PAIR_X | CYCLES_REG, INVALID, PAIR_X | CYCLES_REG, INVALID, INVALID, PAIR_X | CYCLES_REG, PAIR_X | CYCLES_REG, INVALID, PAIR_X | CYCLES_REG, PAIR_X | CYCLES_REG, PAIR_X | CYCLES_REG, INVALID, PAIR_X | CYCLES_REG, - + /*e0*/ INVALID, PAIR_X | CYCLES_REG, PAIR_X | CYCLES_REG, INVALID, INVALID, PAIR_X | CYCLES_REG, INVALID, INVALID, PAIR_X | CYCLES_REG, PAIR_X | CYCLES_REG, INVALID, PAIR_X | CYCLES_REG, - PAIR_X | CYCLES_REG, PAIR_X | CYCLES_REG, INVALID, PAIR_X | CYCLES_REG, - + PAIR_X | CYCLES_REG, PAIR_X | CYCLES_REG, INVALID, PAIR_X | CYCLES_REG, + /*f0*/ INVALID, PAIR_X | CYCLES_REG, PAIR_X | CYCLES_REG, PAIR_X | CYCLES_REG, INVALID, PAIR_X | CYCLES_REG, INVALID, INVALID, PAIR_X | CYCLES_REG, PAIR_X | CYCLES_REG, PAIR_X | CYCLES_REG, INVALID, PAIR_X | CYCLES_REG, PAIR_X | CYCLES_REG, PAIR_X | CYCLES_REG, INVALID, + // clang-format on }; -static uint32_t opcode_timings_shift[8] = -{ +static uint32_t opcode_timings_shift[8] = { + // clang-format off PAIR_XY | CYCLES_RMW, PAIR_XY | CYCLES_RMW, PAIR_XY | CYCLES(3), PAIR_XY | CYCLES(4), PAIR_XY | CYCLES_RMW, PAIR_XY | CYCLES_RMW, PAIR_XY | CYCLES_RMW, PAIR_XY | CYCLES_RMW, + // clang-format on }; -static uint32_t opcode_timings_shift_mod3[8] = -{ +static uint32_t opcode_timings_shift_mod3[8] = { + // clang-format off PAIR_XY | CYCLES_REG, PAIR_XY | CYCLES_REG, PAIR_XY | CYCLES(3), PAIR_XY | CYCLES(4), PAIR_XY | CYCLES_REG, PAIR_XY | CYCLES_REG, PAIR_XY | CYCLES_REG, PAIR_XY | CYCLES_REG, + // clang-format on }; -static uint32_t opcode_timings_shift_imm[8] = -{ +static uint32_t opcode_timings_shift_imm[8] = { + // clang-format off PAIR_XY | CYCLES_RMW, PAIR_XY | CYCLES_RMW, PAIR_XY | CYCLES(8), PAIR_XY | CYCLES(9), PAIR_XY | CYCLES_RMW, PAIR_XY | CYCLES_RMW, PAIR_XY | CYCLES_RMW, PAIR_XY | CYCLES_RMW, + // clang-format on }; -static uint32_t opcode_timings_shift_imm_mod3[8] = -{ +static uint32_t opcode_timings_shift_imm_mod3[8] = { + // clang-format off PAIR_XY | CYCLES_REG, PAIR_XY | CYCLES_REG, PAIR_XY | CYCLES(3), PAIR_XY | CYCLES(4), PAIR_XY | CYCLES_REG, PAIR_XY | CYCLES_REG, PAIR_XY | CYCLES_REG, PAIR_XY | CYCLES_REG, + // clang-format on }; -static uint32_t opcode_timings_shift_cl[8] = -{ +static uint32_t opcode_timings_shift_cl[8] = { + // clang-format off PAIR_XY | CYCLES(2), PAIR_XY | CYCLES(2), PAIR_XY | CYCLES(8), PAIR_XY | CYCLES(9), PAIR_XY | CYCLES(2), PAIR_XY | CYCLES(2), PAIR_XY | CYCLES(2), PAIR_XY | CYCLES(2), + // clang-format on }; -static uint32_t opcode_timings_shift_cl_mod3[8] = -{ +static uint32_t opcode_timings_shift_cl_mod3[8] = { + // clang-format off PAIR_XY | CYCLES(2), PAIR_XY | CYCLES(2), PAIR_XY | CYCLES(8), PAIR_XY | CYCLES(9), PAIR_XY | CYCLES(2), PAIR_XY | CYCLES(2), PAIR_XY | CYCLES(2), PAIR_XY | CYCLES(2), + // clang-format on }; -static uint32_t opcode_timings_f6[8] = -{ +static uint32_t opcode_timings_f6[8] = { + // clang-format off /* TST NOT NEG*/ PAIR_XY | CYCLES_RM, INVALID, PAIR_XY | CYCLES(1), PAIR_XY | CYCLES(1), /* MUL IMUL DIV IDIV*/ PAIR_NP | CYCLES(4), PAIR_NP | CYCLES(4), PAIR_NP | CYCLES(18), PAIR_NP | CYCLES(18) + // clang-format on }; -static uint32_t opcode_timings_f6_mod3[8] = -{ +static uint32_t opcode_timings_f6_mod3[8] = { + // clang-format off /* TST NOT NEG*/ PAIR_XY | CYCLES_REG, INVALID, PAIR_XY | CYCLES(1), PAIR_XY | CYCLES(1), /* MUL IMUL DIV IDIV*/ PAIR_NP | CYCLES(4), PAIR_NP | CYCLES(4), PAIR_NP | CYCLES(18), PAIR_NP | CYCLES(18) + // clang-format on }; -static uint32_t opcode_timings_f7[8] = -{ +static uint32_t opcode_timings_f7[8] = { + // clang-format off /* TST NOT NEG*/ PAIR_XY | CYCLES_REG, INVALID, PAIR_XY | CYCLES(1), PAIR_XY | CYCLES(1), /* MUL IMUL DIV IDIV*/ PAIR_NP | CYCLES_MULTI(4,10), PAIR_NP | CYCLES_MULTI(4,10), PAIR_NP | CYCLES_MULTI(19,27), PAIR_NP | CYCLES_MULTI(22,30) + // clang-format on }; -static uint32_t opcode_timings_f7_mod3[8] = -{ +static uint32_t opcode_timings_f7_mod3[8] = { + // clang-format off /* TST NOT NEG*/ PAIR_XY | CYCLES_REG, INVALID, PAIR_XY | CYCLES(1), PAIR_XY | CYCLES(1), /* MUL IMUL DIV IDIV*/ PAIR_NP | CYCLES_MULTI(4,10), PAIR_NP | CYCLES_MULTI(4,10), PAIR_NP | CYCLES_MULTI(19,27), PAIR_NP | CYCLES_MULTI(22,30) + // clang-format on }; -static uint32_t opcode_timings_ff[8] = -{ +static uint32_t opcode_timings_ff[8] = { + // clang-format off /* INC DEC CALL CALL far*/ PAIR_XY | CYCLES_RMW, PAIR_XY | CYCLES_RMW, PAIR_X_BRANCH | CYCLES(3), PAIR_NP | CYCLES(5), /* JMP JMP far PUSH*/ PAIR_X_BRANCH | CYCLES(3), PAIR_NP | CYCLES(5), PAIR_XY | CYCLES(1), INVALID -}; -static uint32_t opcode_timings_ff_mod3[8] = -{ + // clang-format on +}; +static uint32_t opcode_timings_ff_mod3[8] = { + // clang-format off /* INC DEC CALL CALL far*/ PAIR_XY | CYCLES_REG, PAIR_XY | CYCLES_REG, PAIR_X_BRANCH | CYCLES(1), PAIR_XY | CYCLES(5), /* JMP JMP far PUSH*/ PAIR_X_BRANCH | CYCLES(1), PAIR_XY | CYCLES(5), PAIR_XY | CYCLES(2), INVALID + // clang-format on }; -static uint32_t opcode_timings_d8[8] = -{ +static uint32_t opcode_timings_d8[8] = { + // clang-format off /* FADDs FMULs FCOMs FCOMPs*/ PAIR_X | CYCLES(7), PAIR_X | CYCLES(6), PAIR_X | CYCLES(4), PAIR_X | CYCLES(4), /* FSUBs FSUBRs FDIVs FDIVRs*/ PAIR_X | CYCLES(7), PAIR_X | CYCLES(7), PAIR_X | CYCLES(34), PAIR_X | CYCLES(34) + // clang-format on }; -static uint32_t opcode_timings_d8_mod3[8] = -{ +static uint32_t opcode_timings_d8_mod3[8] = { + // clang-format off /* FADD FMUL FCOM FCOMP*/ PAIR_X | CYCLES(7), PAIR_X | CYCLES(6), PAIR_X | CYCLES(4), PAIR_X | CYCLES(4), /* FSUB FSUBR FDIV FDIVR*/ PAIR_X | CYCLES(7), PAIR_X | CYCLES(7), PAIR_X | CYCLES(34), PAIR_X | CYCLES(34) + // clang-format on }; -static uint32_t opcode_timings_d9[8] = -{ +static uint32_t opcode_timings_d9[8] = { + // clang-format off /* FLDs FSTs FSTPs*/ PAIR_X | CYCLES(2), INVALID, PAIR_X | CYCLES(2), PAIR_X | CYCLES(2), /* FLDENV FLDCW FSTENV FSTCW*/ PAIR_X | CYCLES(30), PAIR_X | CYCLES(4), PAIR_X | CYCLES(24), PAIR_X | CYCLES(5) + // clang-format on }; -static uint32_t opcode_timings_d9_mod3[64] = -{ +static uint32_t opcode_timings_d9_mod3[64] = { + // clang-format off /*FLD*/ PAIR_X | CYCLES(2), PAIR_X | CYCLES(2), PAIR_X | CYCLES(2), PAIR_X | CYCLES(2), PAIR_X | CYCLES(2), PAIR_X | CYCLES(2), PAIR_X | CYCLES(2), PAIR_X | CYCLES(2), @@ -605,10 +626,10 @@ static uint32_t opcode_timings_d9_mod3[64] = PAIR_X | CYCLES(3), PAIR_X | CYCLES(3), PAIR_X | CYCLES(3), PAIR_X | CYCLES(3), /*FNOP*/ PAIR_X | CYCLES(2), INVALID, INVALID, INVALID, - INVALID, INVALID, INVALID, INVALID, + INVALID, INVALID, INVALID, INVALID, /*FSTP*/ PAIR_X | CYCLES(2), PAIR_X | CYCLES(2), PAIR_X | CYCLES(2), PAIR_X | CYCLES(2), - PAIR_X | CYCLES(2), PAIR_X | CYCLES(2), PAIR_X | CYCLES(2), PAIR_X | CYCLES(2), + PAIR_X | CYCLES(2), PAIR_X | CYCLES(2), PAIR_X | CYCLES(2), PAIR_X | CYCLES(2), /* opFCHS opFABS*/ PAIR_X | CYCLES(2), PAIR_X | CYCLES(2), INVALID, INVALID, /* opFTST opFXAM (oddly low) */ @@ -625,433 +646,440 @@ static uint32_t opcode_timings_d9_mod3[64] = PAIR_X | CYCLES(91), INVALID, PAIR_X | CYCLES(60), PAIR_X | CYCLES(161), /* opFRNDINT opFSCALE opFSIN opFCOS*/ PAIR_X | CYCLES(20), PAIR_X | CYCLES(14), PAIR_X | CYCLES(140), PAIR_X | CYCLES(141) + // clang-format on }; -static uint32_t opcode_timings_da[8] = -{ +static uint32_t opcode_timings_da[8] = { + // clang-format off /* FIADDl FIMULl FICOMl FICOMPl*/ PAIR_X | CYCLES(12), PAIR_X | CYCLES(11), PAIR_X | CYCLES(10), PAIR_X | CYCLES(10), /* FISUBl FISUBRl FIDIVl FIDIVRl*/ PAIR_X | CYCLES(29), PAIR_X | CYCLES(27), PAIR_X | CYCLES(38), PAIR_X | CYCLES(48) + // clang-format on }; -static uint32_t opcode_timings_da_mod3[8] = -{ +static uint32_t opcode_timings_da_mod3[8] = { + // clang-format off PAIR_X | CYCLES(4), PAIR_X | CYCLES(4), PAIR_X | CYCLES(4), PAIR_X | CYCLES(4), INVALID, PAIR_X | CYCLES(5), INVALID, INVALID + // clang-format on }; - -static uint32_t opcode_timings_db[8] = -{ +static uint32_t opcode_timings_db[8] = { + // clang-format off /* FLDil FSTil FSTPil*/ PAIR_X | CYCLES(2), INVALID, PAIR_X | CYCLES(2), PAIR_X | CYCLES(2), /* FLDe FSTPe*/ INVALID, PAIR_X | CYCLES(2), INVALID, PAIR_X | CYCLES(2) + // clang-format on }; -static uint32_t opcode_timings_db_mod3[64] = -{ +static uint32_t opcode_timings_db_mod3[64] = { + // clang-format off PAIR_X | CYCLES(4), PAIR_X | CYCLES(4), PAIR_X | CYCLES(4), PAIR_X | CYCLES(4), PAIR_X | CYCLES(4), PAIR_X | CYCLES(4), PAIR_X | CYCLES(4), PAIR_X | CYCLES(4), - + PAIR_X | CYCLES(4), PAIR_X | CYCLES(4), PAIR_X | CYCLES(4), PAIR_X | CYCLES(4), PAIR_X | CYCLES(4), PAIR_X | CYCLES(4), PAIR_X | CYCLES(4), PAIR_X | CYCLES(4), - + PAIR_X | CYCLES(4), PAIR_X | CYCLES(4), PAIR_X | CYCLES(4), PAIR_X | CYCLES(4), PAIR_X | CYCLES(4), PAIR_X | CYCLES(4), PAIR_X | CYCLES(4), PAIR_X | CYCLES(4), - + PAIR_X | CYCLES(4), PAIR_X | CYCLES(4), PAIR_X | CYCLES(4), PAIR_X | CYCLES(4), PAIR_X | CYCLES(4), PAIR_X | CYCLES(4), PAIR_X | CYCLES(4), PAIR_X | CYCLES(4), - + /* opFNOP opFCLEX opFINIT*/ INVALID, PAIR_X | CYCLES(2), PAIR_X | CYCLES(5), PAIR_X | CYCLES(8), /* opFNOP opFNOP*/ PAIR_X | CYCLES(2), PAIR_X | CYCLES(2), INVALID, INVALID, - + INVALID, INVALID, INVALID, INVALID, INVALID, INVALID, INVALID, INVALID, - + INVALID, INVALID, INVALID, INVALID, INVALID, INVALID, INVALID, INVALID, - + INVALID, INVALID, INVALID, INVALID, INVALID, INVALID, INVALID, INVALID, + // clang-format on }; -static uint32_t opcode_timings_dc[8] = -{ +static uint32_t opcode_timings_dc[8] = { + // clang-format off /* FADDd FMULd FCOMd FCOMPd*/ PAIR_X | CYCLES(7), PAIR_X | CYCLES(7), PAIR_X | CYCLES(7), PAIR_X | CYCLES(7), /* FSUBd FSUBRd FDIVd FDIVRd*/ PAIR_X | CYCLES(7), PAIR_X | CYCLES(7), PAIR_X | CYCLES(34), PAIR_X | CYCLES(34) + // clang-format on }; -static uint32_t opcode_timings_dc_mod3[8] = -{ +static uint32_t opcode_timings_dc_mod3[8] = { + // clang-format off /* opFADDr opFMULr*/ PAIR_X | CYCLES(7), PAIR_X | CYCLES(7), INVALID, INVALID, /* opFSUBRr opFSUBr opFDIVRr opFDIVr*/ PAIR_X | CYCLES(7), PAIR_X | CYCLES(7), PAIR_X | CYCLES(34), PAIR_X | CYCLES(34) + // clang-format on }; -static uint32_t opcode_timings_dd[8] = -{ +static uint32_t opcode_timings_dd[8] = { + // clang-format off /* FLDd FSTd FSTPd*/ PAIR_X | CYCLES(2), INVALID, PAIR_X | CYCLES(2), PAIR_X | CYCLES(2), /* FRSTOR FSAVE FSTSW*/ PAIR_X | CYCLES(72), INVALID, PAIR_X | CYCLES(67), PAIR_X | CYCLES(2) + // clang-format on }; -static uint32_t opcode_timings_dd_mod3[8] = -{ +static uint32_t opcode_timings_dd_mod3[8] = { + // clang-format off /* FFFREE FST FSTP*/ PAIR_X | CYCLES(3), INVALID, PAIR_X | CYCLES(2), PAIR_X | CYCLES(2), /* FUCOM FUCOMP*/ PAIR_X | CYCLES(4), PAIR_X | CYCLES(4), INVALID, INVALID + // clang-format on }; -static uint32_t opcode_timings_de[8] = -{ +static uint32_t opcode_timings_de[8] = { + // clang-format off /* FIADDw FIMULw FICOMw FICOMPw*/ PAIR_X | CYCLES(12), PAIR_X | CYCLES(11), PAIR_X | CYCLES(10), PAIR_X | CYCLES(10), /* FISUBw FISUBRw FIDIVw FIDIVRw*/ PAIR_X | CYCLES(27), PAIR_X | CYCLES(27), PAIR_X | CYCLES(38), PAIR_X | CYCLES(38) }; -static uint32_t opcode_timings_de_mod3[8] = -{ +static uint32_t opcode_timings_de_mod3[8] = { + // clang-format off /* FADD FMUL FCOMPP*/ PAIR_X | CYCLES(7), PAIR_X | CYCLES(7), INVALID, PAIR_X | CYCLES(7), /* FSUB FSUBR FDIV FDIVR*/ PAIR_X | CYCLES(7), PAIR_X | CYCLES(7), PAIR_X | CYCLES(34), PAIR_X | CYCLES(34) + // clang-format on }; -static uint32_t opcode_timings_df[8] = -{ +static uint32_t opcode_timings_df[8] = { + // clang-format off /* FILDiw FISTiw FISTPiw*/ PAIR_X | CYCLES(8), INVALID, PAIR_X | CYCLES(10), PAIR_X | CYCLES(13), /* FILDiq FBSTP FISTPiq*/ INVALID, PAIR_X | CYCLES(8), PAIR_X | CYCLES(63), PAIR_X | CYCLES(13) + // clang-format on }; -static uint32_t opcode_timings_df_mod3[8] = -{ +static uint32_t opcode_timings_df_mod3[8] = { + // clang-format off INVALID, INVALID, INVALID, INVALID, /* FSTSW AX*/ PAIR_X | CYCLES(6), INVALID, INVALID, INVALID + // clang-format on }; -static uint32_t opcode_timings_8x[8] = -{ +static uint32_t opcode_timings_8x[8] = { + // clang-format off PAIR_XY | CYCLES_RMW, PAIR_XY | CYCLES_RMW, PAIR_XY | CYCLES_RMW, PAIR_XY | CYCLES_RMW, PAIR_XY | CYCLES_RMW, PAIR_XY | CYCLES_RMW, PAIR_XY | CYCLES_RMW, PAIR_XY | CYCLES_RM + // clang-format on }; -static uint32_t opcode_timings_8x_mod3[8] = -{ +static uint32_t opcode_timings_8x_mod3[8] = { + // clang-format off PAIR_XY | CYCLES_REG, PAIR_XY | CYCLES_REG, PAIR_XY | CYCLES_REG, PAIR_XY | CYCLES_REG, PAIR_XY | CYCLES_REG, PAIR_XY | CYCLES_REG, PAIR_XY | CYCLES_REG, PAIR_XY | CYCLES_REG + // clang-format on }; -static uint32_t opcode_timings_81[8] = -{ +static uint32_t opcode_timings_81[8] = { + // clang-format off PAIR_XY | CYCLES_RMW, PAIR_XY | CYCLES_RMW, PAIR_XY | CYCLES_RMW, PAIR_XY | CYCLES_RMW, PAIR_XY | CYCLES_RMW, PAIR_XY | CYCLES_RMW, PAIR_XY | CYCLES_RMW, PAIR_XY | CYCLES_RM + // clang-format on }; -static uint32_t opcode_timings_81_mod3[8] = -{ +static uint32_t opcode_timings_81_mod3[8] = { + // clang-format off PAIR_XY | CYCLES_REG, PAIR_XY | CYCLES_REG, PAIR_XY | CYCLES_REG, PAIR_XY | CYCLES_REG, PAIR_XY | CYCLES_REG, PAIR_XY | CYCLES_REG, PAIR_XY | CYCLES_REG, PAIR_XY | CYCLES_REG + // clang-format on }; -static int decode_delay; +static int decode_delay; static uint8_t last_prefix; -static inline int COUNT(uint32_t c, int op_32) +static inline int +COUNT(uint32_t c, int op_32) { - if (c & CYCLES_HAS_MULTI) - { - if (op_32 & 0x100) - return ((uintptr_t)c >> 8) & 0xff; - return (uintptr_t)c & 0xff; - } - if (!(c & PAIR_MASK)) - return c & 0xffff; + if (c & CYCLES_HAS_MULTI) { + if (op_32 & 0x100) + return ((uintptr_t) c >> 8) & 0xff; + return (uintptr_t) c & 0xff; + } + if (!(c & PAIR_MASK)) + return c & 0xffff; - return c & CYCLES_MASK; + return c & CYCLES_MASK; } -void codegen_timing_686_block_start() +void +codegen_timing_686_block_start(void) { - prev_full = decode_delay = 0; - regmask_modified = last_regmask_modified = 0; + prev_full = decode_delay = 0; + regmask_modified = last_regmask_modified = 0; } -void codegen_timing_686_start() +void +codegen_timing_686_start(void) { - decode_delay = 0; - last_prefix = 0; + decode_delay = 0; + last_prefix = 0; } -void codegen_timing_686_prefix(uint8_t prefix, uint32_t fetchdat) +void +codegen_timing_686_prefix(uint8_t prefix, uint32_t fetchdat) { - if ((prefix & 0xf8) == 0xd8) - { - last_prefix = prefix; - return; - } - if (prefix == 0x0f && (fetchdat & 0xf0) == 0x80) - { - /*0fh prefix is 'free' when used on conditional jumps*/ - last_prefix = prefix; - return; - } - - /*6x86 can decode 1 prefix per instruction per clock with no penalty. If - either instruction has more than one prefix then decode is delayed by - one cycle for each additional prefix*/ - decode_delay++; + if ((prefix & 0xf8) == 0xd8) { last_prefix = prefix; + return; + } + if (prefix == 0x0f && (fetchdat & 0xf0) == 0x80) { + /*0fh prefix is 'free' when used on conditional jumps*/ + last_prefix = prefix; + return; + } + + /*6x86 can decode 1 prefix per instruction per clock with no penalty. If + either instruction has more than one prefix then decode is delayed by + one cycle for each additional prefix*/ + decode_delay++; + last_prefix = prefix; } -static int check_agi(uint64_t *deps, uint8_t opcode, uint32_t fetchdat, int op_32) +static int +check_agi(uint64_t *deps, uint8_t opcode, uint32_t fetchdat, int op_32) { - uint32_t addr_regmask = get_addr_regmask(deps[opcode], fetchdat, op_32); + uint32_t addr_regmask = get_addr_regmask(deps[opcode], fetchdat, op_32); - if (addr_regmask & IMPL_ESP) - addr_regmask |= (1 << REG_ESP); + if (addr_regmask & IMPL_ESP) + addr_regmask |= (1 << REG_ESP); - if (regmask_modified & addr_regmask) - { - regmask_modified = 0; - return 2; - } + if (regmask_modified & addr_regmask) { + regmask_modified = 0; + return 2; + } - if (last_regmask_modified & addr_regmask) - return 1; - - return 0; + if (last_regmask_modified & addr_regmask) + return 1; + + return 0; } -void codegen_timing_686_opcode(uint8_t opcode, uint32_t fetchdat, int op_32, uint32_t op_pc) +void +codegen_timing_686_opcode(uint8_t opcode, uint32_t fetchdat, int op_32, UNUSED(uint32_t op_pc)) { - uint32_t *timings; - uint64_t *deps; - int mod3 = ((fetchdat & 0xc0) == 0xc0); - int bit8 = !(opcode & 1); + uint32_t *timings; + uint64_t *deps; + int mod3 = ((fetchdat & 0xc0) == 0xc0); + int bit8 = !(opcode & 1); - switch (last_prefix) - { - case 0x0f: - timings = mod3 ? opcode_timings_0f_mod3 : opcode_timings_0f; - deps = mod3 ? opcode_deps_0f_mod3 : opcode_deps_0f; - break; - - case 0xd8: - timings = mod3 ? opcode_timings_d8_mod3 : opcode_timings_d8; - deps = mod3 ? opcode_deps_d8_mod3 : opcode_deps_d8; - opcode = (opcode >> 3) & 7; - break; - case 0xd9: - timings = mod3 ? opcode_timings_d9_mod3 : opcode_timings_d9; - deps = mod3 ? opcode_deps_d9_mod3 : opcode_deps_d9; - opcode = mod3 ? opcode & 0x3f : (opcode >> 3) & 7; - break; - case 0xda: - timings = mod3 ? opcode_timings_da_mod3 : opcode_timings_da; - deps = mod3 ? opcode_deps_da_mod3 : opcode_deps_da; - opcode = (opcode >> 3) & 7; - break; - case 0xdb: - timings = mod3 ? opcode_timings_db_mod3 : opcode_timings_db; - deps = mod3 ? opcode_deps_db_mod3 : opcode_deps_db; - opcode = mod3 ? opcode & 0x3f : (opcode >> 3) & 7; - break; - case 0xdc: - timings = mod3 ? opcode_timings_dc_mod3 : opcode_timings_dc; - deps = mod3 ? opcode_deps_dc_mod3 : opcode_deps_dc; - opcode = (opcode >> 3) & 7; - break; - case 0xdd: - timings = mod3 ? opcode_timings_dd_mod3 : opcode_timings_dd; - deps = mod3 ? opcode_deps_dd_mod3 : opcode_deps_dd; - opcode = (opcode >> 3) & 7; - break; - case 0xde: - timings = mod3 ? opcode_timings_de_mod3 : opcode_timings_de; - deps = mod3 ? opcode_deps_de_mod3 : opcode_deps_de; - opcode = (opcode >> 3) & 7; - break; - case 0xdf: - timings = mod3 ? opcode_timings_df_mod3 : opcode_timings_df; - deps = mod3 ? opcode_deps_df_mod3 : opcode_deps_df; - opcode = (opcode >> 3) & 7; - break; + switch (last_prefix) { + case 0x0f: + timings = mod3 ? opcode_timings_0f_mod3 : opcode_timings_0f; + deps = mod3 ? opcode_deps_0f_mod3 : opcode_deps_0f; + break; + + case 0xd8: + timings = mod3 ? opcode_timings_d8_mod3 : opcode_timings_d8; + deps = mod3 ? opcode_deps_d8_mod3 : opcode_deps_d8; + opcode = (opcode >> 3) & 7; + break; + case 0xd9: + timings = mod3 ? opcode_timings_d9_mod3 : opcode_timings_d9; + deps = mod3 ? opcode_deps_d9_mod3 : opcode_deps_d9; + opcode = mod3 ? opcode & 0x3f : (opcode >> 3) & 7; + break; + case 0xda: + timings = mod3 ? opcode_timings_da_mod3 : opcode_timings_da; + deps = mod3 ? opcode_deps_da_mod3 : opcode_deps_da; + opcode = (opcode >> 3) & 7; + break; + case 0xdb: + timings = mod3 ? opcode_timings_db_mod3 : opcode_timings_db; + deps = mod3 ? opcode_deps_db_mod3 : opcode_deps_db; + opcode = mod3 ? opcode & 0x3f : (opcode >> 3) & 7; + break; + case 0xdc: + timings = mod3 ? opcode_timings_dc_mod3 : opcode_timings_dc; + deps = mod3 ? opcode_deps_dc_mod3 : opcode_deps_dc; + opcode = (opcode >> 3) & 7; + break; + case 0xdd: + timings = mod3 ? opcode_timings_dd_mod3 : opcode_timings_dd; + deps = mod3 ? opcode_deps_dd_mod3 : opcode_deps_dd; + opcode = (opcode >> 3) & 7; + break; + case 0xde: + timings = mod3 ? opcode_timings_de_mod3 : opcode_timings_de; + deps = mod3 ? opcode_deps_de_mod3 : opcode_deps_de; + opcode = (opcode >> 3) & 7; + break; + case 0xdf: + timings = mod3 ? opcode_timings_df_mod3 : opcode_timings_df; + deps = mod3 ? opcode_deps_df_mod3 : opcode_deps_df; + opcode = (opcode >> 3) & 7; + break; + + default: + switch (opcode) { + case 0x80: + case 0x82: + case 0x83: + timings = mod3 ? opcode_timings_8x_mod3 : opcode_timings_8x; + deps = mod3 ? opcode_deps_8x_mod3 : opcode_deps_8x; + opcode = (fetchdat >> 3) & 7; + break; + case 0x81: + timings = mod3 ? opcode_timings_81_mod3 : opcode_timings_81; + deps = mod3 ? opcode_deps_81_mod3 : opcode_deps_81; + opcode = (fetchdat >> 3) & 7; + break; + + case 0xc0: + case 0xc1: + timings = mod3 ? opcode_timings_shift_imm_mod3 : opcode_timings_shift_imm; + deps = mod3 ? opcode_deps_shift_mod3 : opcode_deps_shift; + opcode = (fetchdat >> 3) & 7; + break; + + case 0xd0: + case 0xd1: + timings = mod3 ? opcode_timings_shift_mod3 : opcode_timings_shift; + deps = mod3 ? opcode_deps_shift_mod3 : opcode_deps_shift; + opcode = (fetchdat >> 3) & 7; + break; + + case 0xd2: + case 0xd3: + timings = mod3 ? opcode_timings_shift_cl_mod3 : opcode_timings_shift_cl; + deps = mod3 ? opcode_deps_shift_cl_mod3 : opcode_deps_shift_cl; + opcode = (fetchdat >> 3) & 7; + break; + + case 0xf6: + timings = mod3 ? opcode_timings_f6_mod3 : opcode_timings_f6; + deps = mod3 ? opcode_deps_f6_mod3 : opcode_deps_f6; + opcode = (fetchdat >> 3) & 7; + break; + case 0xf7: + timings = mod3 ? opcode_timings_f7_mod3 : opcode_timings_f7; + deps = mod3 ? opcode_deps_f7_mod3 : opcode_deps_f7; + opcode = (fetchdat >> 3) & 7; + break; + case 0xff: + timings = mod3 ? opcode_timings_ff_mod3 : opcode_timings_ff; + deps = mod3 ? opcode_deps_ff_mod3 : opcode_deps_ff; + opcode = (fetchdat >> 3) & 7; + break; default: - switch (opcode) - { - case 0x80: case 0x82: case 0x83: - timings = mod3 ? opcode_timings_8x_mod3 : opcode_timings_8x; - deps = mod3 ? opcode_deps_8x_mod3 : opcode_deps_8x; - opcode = (fetchdat >> 3) & 7; - break; - case 0x81: - timings = mod3 ? opcode_timings_81_mod3 : opcode_timings_81; - deps = mod3 ? opcode_deps_81_mod3 : opcode_deps_81; - opcode = (fetchdat >> 3) & 7; - break; - - case 0xc0: case 0xc1: - timings = mod3 ? opcode_timings_shift_imm_mod3 : opcode_timings_shift_imm; - deps = mod3 ? opcode_deps_shift_mod3 : opcode_deps_shift; - opcode = (fetchdat >> 3) & 7; - break; + timings = mod3 ? opcode_timings_mod3 : opcode_timings; + deps = mod3 ? opcode_deps_mod3 : opcode_deps; + break; + } + } - case 0xd0: case 0xd1: - timings = mod3 ? opcode_timings_shift_mod3 : opcode_timings_shift; - deps = mod3 ? opcode_deps_shift_mod3 : opcode_deps_shift; - opcode = (fetchdat >> 3) & 7; - break; - - case 0xd2: case 0xd3: - timings = mod3 ? opcode_timings_shift_cl_mod3 : opcode_timings_shift_cl; - deps = mod3 ? opcode_deps_shift_cl_mod3 : opcode_deps_shift_cl; - opcode = (fetchdat >> 3) & 7; - break; - - case 0xf6: - timings = mod3 ? opcode_timings_f6_mod3 : opcode_timings_f6; - deps = mod3 ? opcode_deps_f6_mod3 : opcode_deps_f6; - opcode = (fetchdat >> 3) & 7; - break; - case 0xf7: - timings = mod3 ? opcode_timings_f7_mod3 : opcode_timings_f7; - deps = mod3 ? opcode_deps_f7_mod3 : opcode_deps_f7; - opcode = (fetchdat >> 3) & 7; - break; - case 0xff: - timings = mod3 ? opcode_timings_ff_mod3 : opcode_timings_ff; - deps = mod3 ? opcode_deps_ff_mod3 : opcode_deps_ff; - opcode = (fetchdat >> 3) & 7; - break; + /*One prefix per instruction is free*/ + decode_delay--; + if (decode_delay < 0) + decode_delay = 0; - default: - timings = mod3 ? opcode_timings_mod3 : opcode_timings; - deps = mod3 ? opcode_deps_mod3 : opcode_deps; - break; - } + if (prev_full) { + uint32_t regmask = get_srcdep_mask(deps[opcode], fetchdat, bit8, op_32); + int agi_stall = 0; + + if (regmask & IMPL_ESP) + regmask |= SRCDEP_ESP | DSTDEP_ESP; + + agi_stall = check_agi(prev_deps, prev_opcode, prev_fetchdat, prev_op_32); + + /*Second instruction in the pair*/ + if ((timings[opcode] & PAIR_MASK) == PAIR_NP) { + /*Instruction can not pair with previous*/ + /*Run previous now*/ + codegen_block_cycles += COUNT(prev_timings[prev_opcode], prev_op_32) + decode_delay + agi_stall; + decode_delay = (-COUNT(prev_timings[prev_opcode], prev_op_32)) + 1 + agi_stall; + prev_full = 0; + last_regmask_modified = regmask_modified; + regmask_modified = prev_regmask; + } else if (((timings[opcode] & PAIR_MASK) == PAIR_X || (timings[opcode] & PAIR_MASK) == PAIR_X_BRANCH) + && (prev_timings[opcode] & PAIR_MASK) == PAIR_X) { + /*Instruction can not pair with previous*/ + /*Run previous now*/ + codegen_block_cycles += COUNT(prev_timings[prev_opcode], prev_op_32) + decode_delay + agi_stall; + decode_delay = (-COUNT(prev_timings[prev_opcode], prev_op_32)) + 1 + agi_stall; + prev_full = 0; + last_regmask_modified = regmask_modified; + regmask_modified = prev_regmask; + } else if (prev_regmask & regmask) { + /*Instruction can not pair with previous*/ + /*Run previous now*/ + codegen_block_cycles += COUNT(prev_timings[prev_opcode], prev_op_32) + decode_delay + agi_stall; + decode_delay = (-COUNT(prev_timings[prev_opcode], prev_op_32)) + 1 + agi_stall; + prev_full = 0; + last_regmask_modified = regmask_modified; + regmask_modified = prev_regmask; + } else { + int t1 = COUNT(prev_timings[prev_opcode], prev_op_32); + int t2 = COUNT(timings[opcode], op_32); + int t_pair = (t1 > t2) ? t1 : t2; + + if (!t_pair) + fatal("Pairable 0 cycles! %02x %02x\n", opcode, prev_opcode); + + agi_stall = check_agi(deps, opcode, fetchdat, op_32); + + codegen_block_cycles += t_pair + agi_stall; + decode_delay = (-t_pair) + 1 + agi_stall; + + last_regmask_modified = regmask_modified; + regmask_modified = get_dstdep_mask(deps[opcode], fetchdat, bit8) | prev_regmask; + prev_full = 0; + return; } - - /*One prefix per instruction is free*/ - decode_delay--; - if (decode_delay < 0) - decode_delay = 0; - - if (prev_full) - { - uint32_t regmask = get_srcdep_mask(deps[opcode], fetchdat, bit8, op_32); - int agi_stall = 0; - - if (regmask & IMPL_ESP) - regmask |= SRCDEP_ESP | DSTDEP_ESP; + } - agi_stall = check_agi(prev_deps, prev_opcode, prev_fetchdat, prev_op_32); + if (!prev_full) { + /*First instruction in the pair*/ + if ((timings[opcode] & PAIR_MASK) == PAIR_NP || (timings[opcode] & PAIR_MASK) == PAIR_X_BRANCH) { + /*Instruction not pairable*/ + int agi_stall = 0; - /*Second instruction in the pair*/ - if ((timings[opcode] & PAIR_MASK) == PAIR_NP) - { - /*Instruction can not pair with previous*/ - /*Run previous now*/ - codegen_block_cycles += COUNT(prev_timings[prev_opcode], prev_op_32) + decode_delay + agi_stall; - decode_delay = (-COUNT(prev_timings[prev_opcode], prev_op_32)) + 1 + agi_stall; - prev_full = 0; - last_regmask_modified = regmask_modified; - regmask_modified = prev_regmask; - } - else if (((timings[opcode] & PAIR_MASK) == PAIR_X || (timings[opcode] & PAIR_MASK) == PAIR_X_BRANCH) - && (prev_timings[opcode] & PAIR_MASK) == PAIR_X) - { - /*Instruction can not pair with previous*/ - /*Run previous now*/ - codegen_block_cycles += COUNT(prev_timings[prev_opcode], prev_op_32) + decode_delay + agi_stall; - decode_delay = (-COUNT(prev_timings[prev_opcode], prev_op_32)) + 1 + agi_stall; - prev_full = 0; - last_regmask_modified = regmask_modified; - regmask_modified = prev_regmask; - } - else if (prev_regmask & regmask) - { - /*Instruction can not pair with previous*/ - /*Run previous now*/ - codegen_block_cycles += COUNT(prev_timings[prev_opcode], prev_op_32) + decode_delay + agi_stall; - decode_delay = (-COUNT(prev_timings[prev_opcode], prev_op_32)) + 1 + agi_stall; - prev_full = 0; - last_regmask_modified = regmask_modified; - regmask_modified = prev_regmask; - } - else - { - int t1 = COUNT(prev_timings[prev_opcode], prev_op_32); - int t2 = COUNT(timings[opcode], op_32); - int t_pair = (t1 > t2) ? t1 : t2; + agi_stall = check_agi(deps, opcode, fetchdat, op_32); - if (!t_pair) - fatal("Pairable 0 cycles! %02x %02x\n", opcode, prev_opcode); - - agi_stall = check_agi(deps, opcode, fetchdat, op_32); - - codegen_block_cycles += t_pair + agi_stall; - decode_delay = (-t_pair) + 1 + agi_stall; - - last_regmask_modified = regmask_modified; - regmask_modified = get_dstdep_mask(deps[opcode], fetchdat, bit8) | prev_regmask; - prev_full = 0; - return; - } - } - - if (!prev_full) - { - /*First instruction in the pair*/ - if ((timings[opcode] & PAIR_MASK) == PAIR_NP || (timings[opcode] & PAIR_MASK) == PAIR_X_BRANCH) - { - /*Instruction not pairable*/ - int agi_stall = 0; - - agi_stall = check_agi(deps, opcode, fetchdat, op_32); - - codegen_block_cycles += COUNT(timings[opcode], op_32) + decode_delay + agi_stall; - decode_delay = (-COUNT(timings[opcode], op_32)) + 1 + agi_stall; - last_regmask_modified = regmask_modified; - regmask_modified = get_dstdep_mask(deps[opcode], fetchdat, bit8); - } - else - { - /*Instruction might pair with next*/ - prev_full = 1; - prev_opcode = opcode; - prev_timings = timings; - prev_op_32 = op_32; - prev_regmask = get_dstdep_mask(deps[opcode], fetchdat, bit8); - if (prev_regmask & IMPL_ESP) - prev_regmask |= SRCDEP_ESP | DSTDEP_ESP; - prev_deps = deps; - prev_fetchdat = fetchdat; - return; - } + codegen_block_cycles += COUNT(timings[opcode], op_32) + decode_delay + agi_stall; + decode_delay = (-COUNT(timings[opcode], op_32)) + 1 + agi_stall; + last_regmask_modified = regmask_modified; + regmask_modified = get_dstdep_mask(deps[opcode], fetchdat, bit8); + } else { + /*Instruction might pair with next*/ + prev_full = 1; + prev_opcode = opcode; + prev_timings = timings; + prev_op_32 = op_32; + prev_regmask = get_dstdep_mask(deps[opcode], fetchdat, bit8); + if (prev_regmask & IMPL_ESP) + prev_regmask |= SRCDEP_ESP | DSTDEP_ESP; + prev_deps = deps; + prev_fetchdat = fetchdat; + return; } + } } -void codegen_timing_686_block_end() +void +codegen_timing_686_block_end(void) { - if (prev_full) - { - /*Run previous now*/ - codegen_block_cycles += COUNT(prev_timings[prev_opcode], prev_op_32) + decode_delay; - prev_full = 0; - } + if (prev_full) { + /*Run previous now*/ + codegen_block_cycles += COUNT(prev_timings[prev_opcode], prev_op_32) + decode_delay; + prev_full = 0; + } } -codegen_timing_t codegen_timing_686 = -{ - codegen_timing_686_start, - codegen_timing_686_prefix, - codegen_timing_686_opcode, - codegen_timing_686_block_start, - codegen_timing_686_block_end, - NULL +codegen_timing_t codegen_timing_686 = { + codegen_timing_686_start, + codegen_timing_686_prefix, + codegen_timing_686_opcode, + codegen_timing_686_block_start, + codegen_timing_686_block_end, + NULL }; diff --git a/src/cpu/codegen_timing_common.c b/src/cpu/codegen_timing_common.c index b6945cd0c..0c538fc4e 100644 --- a/src/cpu/codegen_timing_common.c +++ b/src/cpu/codegen_timing_common.c @@ -8,8 +8,8 @@ #include "codegen_timing_common.h" -uint64_t opcode_deps[256] = -{ +uint64_t opcode_deps[256] = { + // clang-format off /* ADD ADD ADD ADD*/ /*00*/ SRCDEP_REG | MODRM, SRCDEP_REG | MODRM, SRCDEP_REG | DSTDEP_REG | MODRM, SRCDEP_REG | DSTDEP_REG | MODRM, /* ADD ADD PUSH ES POP ES*/ @@ -36,7 +36,7 @@ uint64_t opcode_deps[256] = SRCDEP_REG | MODRM, SRCDEP_REG | MODRM, SRCDEP_REG | DSTDEP_REG | MODRM, SRCDEP_REG | DSTDEP_REG | MODRM, /* SUB SUB DAS*/ SRCDEP_EAX | DSTDEP_EAX | HAS_IMM8, SRCDEP_EAX | DSTDEP_EAX | HAS_IMM1632, 0, SRCDEP_EAX | DSTDEP_EAX, - + /* XOR XOR XOR XOR*/ /*30*/ SRCDEP_REG | MODRM, SRCDEP_REG | MODRM, SRCDEP_REG | DSTDEP_REG | MODRM, SRCDEP_REG | DSTDEP_REG | MODRM, /* XOR XOR AAA*/ @@ -54,7 +54,7 @@ uint64_t opcode_deps[256] = SRCDEP_EAX | DSTDEP_EAX, SRCDEP_ECX | DSTDEP_ECX, SRCDEP_EDX | DSTDEP_EDX, SRCDEP_EBX | DSTDEP_EBX, /* DEC ESP DEC EBP DEC ESI DEC EDI*/ SRCDEP_ESP | DSTDEP_ESP, SRCDEP_EBP | DSTDEP_EBP, SRCDEP_ESI | DSTDEP_ESI, SRCDEP_EDI | DSTDEP_EDI, - + /* PUSH EAX PUSH ECX PUSH EDX PUSH EBX*/ /*50*/ SRCDEP_EAX | IMPL_ESP, SRCDEP_ECX | IMPL_ESP, SRCDEP_EDX | IMPL_ESP, SRCDEP_EBX | IMPL_ESP, /* PUSH ESP PUSH EBP PUSH ESI PUSH EDI*/ @@ -71,8 +71,8 @@ uint64_t opcode_deps[256] = IMPL_ESP | HAS_IMM1632,DSTDEP_REG | MODRM, IMPL_ESP | HAS_IMM8, DSTDEP_REG | MODRM, /* INSB INSW OUTSB OUTSW*/ 0, 0, 0, 0, - -/* Jxx*/ + +/* Jxx*/ /*70*/ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /*80*/ 0, 0, 0, 0, @@ -82,7 +82,7 @@ uint64_t opcode_deps[256] = SRCDEP_REG | MODRM, SRCDEP_REG | MODRM, DSTDEP_REG | MODRM, DSTDEP_REG | MODRM, /* MOV from seg LEA MOV to seg POP*/ MODRM, DSTDEP_REG | MODRM, MODRM, IMPL_ESP | MODRM, - + /* NOP XCHG XCHG XCHG*/ /*90*/ 0, SRCDEP_EAX | DSTDEP_EAX | SRCDEP_ECX | DSTDEP_ECX, SRCDEP_EAX | DSTDEP_EAX | SRCDEP_EDX | DSTDEP_EDX, SRCDEP_EAX | DSTDEP_EAX | SRCDEP_EBX | DSTDEP_EBX, /* XCHG XCHG XCHG XCHG*/ @@ -92,7 +92,7 @@ uint64_t opcode_deps[256] = /* PUSHF POPF SAHF LAHF*/ IMPL_ESP, IMPL_ESP, SRCDEP_EAX, DSTDEP_EAX, -/* MOV MOV MOV MOV*/ +/* MOV MOV MOV MOV*/ /*a0*/ DSTDEP_EAX, DSTDEP_EAX, SRCDEP_EAX, SRCDEP_EAX, /* MOVSB MOVSW CMPSB CMPSW*/ 0, 0, 0, 0, @@ -140,10 +140,11 @@ uint64_t opcode_deps[256] = 0, 0, 0, 0, /* CLD STD INCDEC*/ 0, 0, MODRM, 0 + // clang-format on }; -uint64_t opcode_deps_mod3[256] = -{ +uint64_t opcode_deps_mod3[256] = { + // clang-format off /* ADD ADD ADD ADD*/ /*00*/ SRCDEP_REG | SRCDEP_RM | DSTDEP_RM | MODRM, SRCDEP_REG | SRCDEP_RM | DSTDEP_RM | MODRM, SRCDEP_REG | DSTDEP_REG | SRCDEP_RM | MODRM, SRCDEP_REG | DSTDEP_REG | SRCDEP_RM | MODRM, /* ADD ADD PUSH ES POP ES*/ @@ -157,7 +158,7 @@ uint64_t opcode_deps_mod3[256] = /*10*/ SRCDEP_REG | SRCDEP_RM | DSTDEP_RM | MODRM, SRCDEP_REG | SRCDEP_RM | DSTDEP_RM | MODRM, SRCDEP_REG | DSTDEP_REG | SRCDEP_RM | MODRM, SRCDEP_REG | DSTDEP_REG | SRCDEP_RM | MODRM, /* ADC ADC PUSH SS POP SS*/ SRCDEP_EAX | DSTDEP_EAX | HAS_IMM8, SRCDEP_EAX | DSTDEP_EAX | HAS_IMM1632, IMPL_ESP, IMPL_ESP, -/* SBB SBB SBB SBB*/ +/* SBB SBB SBB SBB*/ SRCDEP_REG |SRCDEP_RM | DSTDEP_RM | MODRM, SRCDEP_REG | SRCDEP_RM | DSTDEP_RM | MODRM, SRCDEP_REG | DSTDEP_REG | SRCDEP_RM | MODRM, SRCDEP_REG | DSTDEP_REG | SRCDEP_RM | MODRM, /* SBB SBB PUSH DS POP DS*/ SRCDEP_EAX | DSTDEP_EAX | HAS_IMM8, SRCDEP_EAX | DSTDEP_EAX | HAS_IMM1632, IMPL_ESP, IMPL_ESP, @@ -170,7 +171,7 @@ uint64_t opcode_deps_mod3[256] = SRCDEP_REG | SRCDEP_RM | DSTDEP_RM | MODRM, SRCDEP_REG | SRCDEP_RM | DSTDEP_RM | MODRM, SRCDEP_REG | DSTDEP_REG | SRCDEP_RM | MODRM, SRCDEP_REG | DSTDEP_REG | SRCDEP_RM | MODRM, /* SUB SUB DAS*/ SRCDEP_EAX | DSTDEP_EAX | HAS_IMM8, SRCDEP_EAX | DSTDEP_EAX | HAS_IMM1632, 0, SRCDEP_EAX | DSTDEP_EAX, - + /* XOR XOR XOR XOR*/ /*30*/ SRCDEP_REG | SRCDEP_RM | DSTDEP_RM | MODRM, SRCDEP_REG | SRCDEP_RM | DSTDEP_RM | MODRM, SRCDEP_REG | DSTDEP_REG | SRCDEP_RM | MODRM, SRCDEP_REG | DSTDEP_REG | SRCDEP_RM | MODRM, /* XOR XOR AAA*/ @@ -188,7 +189,7 @@ uint64_t opcode_deps_mod3[256] = SRCDEP_EAX | DSTDEP_EAX, SRCDEP_ECX | DSTDEP_ECX, SRCDEP_EDX | DSTDEP_EDX, SRCDEP_EBX | DSTDEP_EBX, /* DEC ESP DEC EBP DEC ESI DEC EDI*/ SRCDEP_ESP | DSTDEP_ESP, SRCDEP_EBP | DSTDEP_EBP, SRCDEP_ESI | DSTDEP_ESI, SRCDEP_EDI | DSTDEP_EDI, - + /* PUSH EAX PUSH ECX PUSH EDX PUSH EBX*/ /*50*/ SRCDEP_EAX | IMPL_ESP, SRCDEP_ECX | IMPL_ESP, SRCDEP_EDX | IMPL_ESP, SRCDEP_EBX | IMPL_ESP, /* PUSH ESP PUSH EBP PUSH ESI PUSH EDI*/ @@ -205,8 +206,8 @@ uint64_t opcode_deps_mod3[256] = IMPL_ESP | HAS_IMM1632,DSTDEP_REG | SRCDEP_RM | MODRM, IMPL_ESP | HAS_IMM8, DSTDEP_REG | SRCDEP_RM | MODRM, /* INSB INSW OUTSB OUTSW*/ 0, 0, 0, 0, - -/* Jxx*/ + +/* Jxx*/ /*70*/ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /*80*/ 0, 0, 0, 0, @@ -216,7 +217,7 @@ uint64_t opcode_deps_mod3[256] = SRCDEP_REG | DSTDEP_RM | MODRM, SRCDEP_REG | DSTDEP_RM | MODRM, SRCDEP_RM | DSTDEP_REG | MODRM, SRCDEP_RM | DSTDEP_REG | MODRM, /* MOV from seg LEA MOV to seg POP*/ DSTDEP_RM | MODRM, DSTDEP_REG | MODRM, SRCDEP_RM | MODRM, IMPL_ESP | DSTDEP_RM | MODRM, - + /* NOP XCHG XCHG XCHG*/ /*90*/ 0, SRCDEP_EAX | DSTDEP_EAX | SRCDEP_ECX | DSTDEP_ECX, SRCDEP_EAX | DSTDEP_EAX | SRCDEP_EDX | DSTDEP_EDX, SRCDEP_EAX | DSTDEP_EAX | SRCDEP_EBX | DSTDEP_EBX, /* XCHG XCHG XCHG XCHG*/ @@ -226,7 +227,7 @@ uint64_t opcode_deps_mod3[256] = /* PUSHF POPF SAHF LAHF*/ IMPL_ESP, IMPL_ESP, SRCDEP_EAX, DSTDEP_EAX, -/* MOV MOV MOV MOV*/ +/* MOV MOV MOV MOV*/ /*a0*/ DSTDEP_EAX, DSTDEP_EAX, SRCDEP_EAX, SRCDEP_EAX, /* MOVSB MOVSW CMPSB CMPSW*/ 0, 0, 0, 0, @@ -274,10 +275,11 @@ uint64_t opcode_deps_mod3[256] = 0, 0, 0, 0, /* CLD STD INCDEC*/ 0, 0, SRCDEP_RM | DSTDEP_RM | MODRM, 0 + // clang-format on }; -uint64_t opcode_deps_0f[256] = -{ +uint64_t opcode_deps_0f[256] = { + // clang-format off /*00*/ MODRM, MODRM, MODRM, MODRM, 0, 0, 0, 0, 0, 0, 0, 0, @@ -287,12 +289,12 @@ uint64_t opcode_deps_0f[256] = 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - + /*20*/ MODRM, MODRM, MODRM, MODRM, MODRM, MODRM, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - + /*30*/ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, @@ -302,17 +304,17 @@ uint64_t opcode_deps_0f[256] = 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - + /*50*/ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - + /*60*/ MODRM | MMX_SHIFTPACK, MODRM | MMX_SHIFTPACK, MODRM | MMX_SHIFTPACK, MODRM | MMX_SHIFTPACK, MODRM, MODRM, MODRM, MODRM, MODRM | MMX_SHIFTPACK, MODRM | MMX_SHIFTPACK, MODRM | MMX_SHIFTPACK, MODRM | MMX_SHIFTPACK, 0, 0, MODRM, MODRM, - + /*70*/ 0, MODRM | MMX_SHIFTPACK, MODRM | MMX_SHIFTPACK, MODRM | MMX_SHIFTPACK, MODRM, MODRM, MODRM, 0, 0, 0, 0, 0, @@ -322,17 +324,17 @@ uint64_t opcode_deps_0f[256] = 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - + /*90*/ MODRM, MODRM, MODRM, MODRM, MODRM, MODRM, MODRM, MODRM, MODRM, MODRM, MODRM, MODRM, MODRM, MODRM, MODRM, MODRM, - + /*a0*/ MODRM, MODRM, MODRM, MODRM, MODRM, MODRM, 0, 0, MODRM, MODRM, 0, MODRM, MODRM, MODRM, MODRM, MODRM, - + /*b0*/ MODRM, MODRM, MODRM, MODRM, MODRM, MODRM, MODRM, MODRM, 0, 0, MODRM, MODRM, @@ -347,19 +349,20 @@ uint64_t opcode_deps_0f[256] = 0, MODRM | MMX_MULTIPLY, 0, 0, MODRM, MODRM, 0, MODRM, MODRM, MODRM, 0, MODRM, - + /*e0*/ 0, MODRM | MMX_SHIFTPACK, MODRM | MMX_SHIFTPACK, 0, 0, MODRM | MMX_MULTIPLY, 0, 0, MODRM, MODRM, 0, MODRM, MODRM, MODRM, 0, MODRM, - + /*f0*/ 0, MODRM | MMX_SHIFTPACK, MODRM | MMX_SHIFTPACK, MODRM | MMX_SHIFTPACK, 0, MODRM | MMX_MULTIPLY, 0, 0, MODRM, MODRM, MODRM, 0, MODRM, MODRM, MODRM, 0, + // clang-format on }; -uint64_t opcode_deps_0f_mod3[256] = -{ +uint64_t opcode_deps_0f_mod3[256] = { + // clang-format off /*00*/ MODRM, MODRM, MODRM, MODRM, 0, 0, 0, 0, 0, 0, 0, 0, @@ -369,12 +372,12 @@ uint64_t opcode_deps_0f_mod3[256] = 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - + /*20*/ MODRM, MODRM, MODRM, MODRM, MODRM, MODRM, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - + /*30*/ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, @@ -384,17 +387,17 @@ uint64_t opcode_deps_0f_mod3[256] = 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - + /*50*/ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - + /*60*/ MODRM | MMX_SHIFTPACK, MODRM | MMX_SHIFTPACK, MODRM | MMX_SHIFTPACK, MODRM | MMX_SHIFTPACK, MODRM, MODRM, MODRM, MODRM, MODRM | MMX_SHIFTPACK, MODRM | MMX_SHIFTPACK, MODRM | MMX_SHIFTPACK, MODRM | MMX_SHIFTPACK, 0, 0, MODRM, MODRM, - + /*70*/ 0, MODRM | MMX_SHIFTPACK, MODRM | MMX_SHIFTPACK, MODRM | MMX_SHIFTPACK, MODRM, MODRM, MODRM, 0, 0, 0, 0, 0, @@ -404,17 +407,17 @@ uint64_t opcode_deps_0f_mod3[256] = 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - + /*90*/ MODRM, MODRM, MODRM, MODRM, MODRM, MODRM, MODRM, MODRM, MODRM, MODRM, MODRM, MODRM, MODRM, MODRM, MODRM, MODRM, - + /*a0*/ MODRM, MODRM, MODRM, MODRM, MODRM, MODRM, 0, 0, MODRM, MODRM, 0, MODRM, MODRM, MODRM, MODRM, MODRM, - + /*b0*/ MODRM, MODRM, MODRM, MODRM, MODRM, MODRM, MODRM, MODRM, 0, 0, MODRM, MODRM, @@ -429,20 +432,21 @@ uint64_t opcode_deps_0f_mod3[256] = 0, MODRM | MMX_MULTIPLY, 0, 0, MODRM, MODRM, 0, MODRM, MODRM, MODRM, 0, MODRM, - + /*e0*/ 0, MODRM | MMX_SHIFTPACK, MODRM | MMX_SHIFTPACK, 0, 0, MODRM | MMX_MULTIPLY, 0, 0, MODRM, MODRM, 0, MODRM, MODRM, MODRM, 0, MODRM, - + /*f0*/ 0, MODRM | MMX_SHIFTPACK, MODRM | MMX_SHIFTPACK, MODRM | MMX_SHIFTPACK, 0, MODRM | MMX_MULTIPLY, 0, 0, MODRM, MODRM, MODRM, 0, MODRM, MODRM, MODRM, 0, + // clang-format on }; -uint64_t opcode_deps_0f0f[256] = -{ +uint64_t opcode_deps_0f0f[256] = { + // clang-format off /*00*/ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, @@ -522,9 +526,10 @@ uint64_t opcode_deps_0f0f[256] = 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + // clang-format on }; -uint64_t opcode_deps_0f0f_mod3[256] = -{ +uint64_t opcode_deps_0f0f_mod3[256] = { + // clang-format off /*00*/ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, @@ -604,97 +609,111 @@ uint64_t opcode_deps_0f0f_mod3[256] = 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + // clang-format on }; -uint64_t opcode_deps_shift[8] = -{ +uint64_t opcode_deps_shift[8] = { + // clang-format off MODRM, MODRM, MODRM, MODRM, MODRM, MODRM, MODRM, MODRM, + // clang-format on }; -uint64_t opcode_deps_shift_mod3[8] = -{ +uint64_t opcode_deps_shift_mod3[8] = { + // clang-format off SRCDEP_RM | DSTDEP_RM | MODRM, SRCDEP_RM | DSTDEP_RM | MODRM, SRCDEP_RM | DSTDEP_RM | MODRM, SRCDEP_RM | DSTDEP_RM | MODRM, SRCDEP_RM | DSTDEP_RM | MODRM, SRCDEP_RM | DSTDEP_RM | MODRM, SRCDEP_RM | DSTDEP_RM | MODRM, SRCDEP_RM | DSTDEP_RM | MODRM, + // clang-format on }; -uint64_t opcode_deps_shift_cl[8] = -{ +uint64_t opcode_deps_shift_cl[8] = { + // clang-format off MODRM | SRCDEP_ECX, MODRM | SRCDEP_ECX, MODRM | SRCDEP_ECX, MODRM | SRCDEP_ECX, MODRM | SRCDEP_ECX, MODRM | SRCDEP_ECX, MODRM | SRCDEP_ECX, MODRM | SRCDEP_ECX, + // clang-format on }; -uint64_t opcode_deps_shift_cl_mod3[8] = -{ +uint64_t opcode_deps_shift_cl_mod3[8] = { + // clang-format off SRCDEP_RM | DSTDEP_RM | MODRM | SRCDEP_ECX, SRCDEP_RM | DSTDEP_RM | MODRM | SRCDEP_ECX, SRCDEP_RM | DSTDEP_RM | MODRM | SRCDEP_ECX, SRCDEP_RM | DSTDEP_RM | MODRM | SRCDEP_ECX, SRCDEP_RM | DSTDEP_RM | MODRM | SRCDEP_ECX, SRCDEP_RM | DSTDEP_RM | MODRM | SRCDEP_ECX, SRCDEP_RM | DSTDEP_RM | MODRM | SRCDEP_ECX, SRCDEP_RM | DSTDEP_RM | MODRM | SRCDEP_ECX, + // clang-format on }; -uint64_t opcode_deps_f6[8] = -{ +uint64_t opcode_deps_f6[8] = { + // clang-format off /* TST NOT NEG*/ MODRM, 0, MODRM, MODRM, /* MUL IMUL DIV IDIV*/ SRCDEP_EAX | DSTDEP_EAX | DSTDEP_EDX | MODRM, SRCDEP_EAX | DSTDEP_EAX | DSTDEP_EDX | MODRM, SRCDEP_EAX | SRCDEP_EDX | DSTDEP_EAX | DSTDEP_EDX | MODRM, SRCDEP_EAX | SRCDEP_EDX | DSTDEP_EAX | DSTDEP_EDX | MODRM + // clang-format on }; -uint64_t opcode_deps_f6_mod3[8] = -{ +uint64_t opcode_deps_f6_mod3[8] = { + // clang-format off /* TST NOT NEG*/ SRCDEP_RM | MODRM, 0, SRCDEP_RM | DSTDEP_RM | MODRM, SRCDEP_RM | DSTDEP_RM | MODRM, /* MUL IMUL DIV IDIV*/ SRCDEP_EAX | DSTDEP_EAX | DSTDEP_EDX | SRCDEP_RM | MODRM, SRCDEP_EAX | DSTDEP_EAX | DSTDEP_EDX | SRCDEP_RM | MODRM, SRCDEP_EAX | SRCDEP_EDX | DSTDEP_EAX | DSTDEP_EDX | SRCDEP_RM | MODRM, SRCDEP_EAX | SRCDEP_EDX | DSTDEP_EAX | DSTDEP_EDX | MODRM + // clang-format on }; -uint64_t opcode_deps_f7[8] = -{ +uint64_t opcode_deps_f7[8] = { + // clang-format off /* TST NOT NEG*/ MODRM, 0, MODRM, MODRM, /* MUL IMUL DIV IDIV*/ SRCDEP_EAX | DSTDEP_EAX | DSTDEP_EDX | MODRM, SRCDEP_EAX | DSTDEP_EAX | DSTDEP_EDX | MODRM, SRCDEP_EAX | SRCDEP_EDX | DSTDEP_EAX | DSTDEP_EDX | MODRM, SRCDEP_EAX | SRCDEP_EDX | DSTDEP_EAX | DSTDEP_EDX | MODRM + // clang-format on }; -uint64_t opcode_deps_f7_mod3[8] = -{ +uint64_t opcode_deps_f7_mod3[8] = { + // clang-format off /* TST NOT NEG*/ SRCDEP_RM | MODRM, 0, SRCDEP_RM | DSTDEP_RM | MODRM, SRCDEP_RM | DSTDEP_RM | MODRM, /* MUL IMUL DIV IDIV*/ SRCDEP_EAX | DSTDEP_EAX | DSTDEP_EDX | SRCDEP_RM | MODRM, SRCDEP_EAX | DSTDEP_EAX | DSTDEP_EDX | SRCDEP_RM | MODRM, SRCDEP_EAX | SRCDEP_EDX | DSTDEP_EAX | DSTDEP_EDX | SRCDEP_RM | MODRM, SRCDEP_EAX | SRCDEP_EDX | DSTDEP_EAX | DSTDEP_EDX | MODRM + // clang-format on }; -uint64_t opcode_deps_ff[8] = -{ +uint64_t opcode_deps_ff[8] = { + // clang-format off /* INC DEC CALL CALL far*/ MODRM, MODRM, MODRM | IMPL_ESP, MODRM, /* JMP JMP far PUSH*/ MODRM, MODRM, MODRM | IMPL_ESP, 0 + // clang-format on }; -uint64_t opcode_deps_ff_mod3[8] = -{ +uint64_t opcode_deps_ff_mod3[8] = { + // clang-format off /* INC DEC CALL CALL far*/ SRCDEP_RM | DSTDEP_RM | MODRM, SRCDEP_RM | DSTDEP_RM | MODRM, SRCDEP_RM | MODRM | IMPL_ESP, MODRM, /* JMP JMP far PUSH*/ SRCDEP_RM | MODRM, MODRM, SRCDEP_RM | MODRM | IMPL_ESP, 0 + // clang-format on }; -uint64_t opcode_deps_d8[8] = -{ +uint64_t opcode_deps_d8[8] = { + // clang-format off /* FADDs FMULs FCOMs FCOMPs*/ FPU_RW_ST0 | MODRM, FPU_RW_ST0 | MODRM, FPU_READ_ST0 | MODRM, FPU_POP | FPU_READ_ST0 | MODRM, /* FSUBs FSUBRs FDIVs FDIVRs*/ FPU_RW_ST0 | MODRM, FPU_RW_ST0 | MODRM, FPU_RW_ST0 | MODRM, FPU_RW_ST0 | MODRM + // clang-format on }; -uint64_t opcode_deps_d8_mod3[8] = -{ +uint64_t opcode_deps_d8_mod3[8] = { + // clang-format off /* FADD FMUL FCOM FCOMP*/ FPU_RW_ST0 | FPU_READ_STREG, FPU_RW_ST0 | FPU_READ_STREG, FPU_READ_ST0 | FPU_READ_STREG, FPU_POP | FPU_READ_ST0 | FPU_READ_STREG, /* FSUB FSUBR FDIV FDIVR*/ FPU_RW_ST0 | FPU_READ_STREG, FPU_RW_ST0 | FPU_READ_STREG, FPU_RW_ST0 | FPU_READ_STREG, FPU_RW_ST0 | FPU_READ_STREG + // clang-format on }; -uint64_t opcode_deps_d9[8] = -{ +uint64_t opcode_deps_d9[8] = { + // clang-format off /* FLDs FSTs FSTPs*/ FPU_PUSH | MODRM, 0, FPU_READ_ST0 | MODRM, FPU_POP | MODRM, /* FLDENV FLDCW FSTENV FSTCW*/ MODRM, MODRM, MODRM, MODRM + // clang-format on }; -uint64_t opcode_deps_d9_mod3[64] = -{ +uint64_t opcode_deps_d9_mod3[64] = { + // clang-format off /*FLD*/ FPU_PUSH | FPU_READ_STREG, FPU_PUSH | FPU_READ_STREG, FPU_PUSH | FPU_READ_STREG, FPU_PUSH | FPU_READ_STREG, FPU_PUSH | FPU_READ_STREG, FPU_PUSH | FPU_READ_STREG, FPU_PUSH | FPU_READ_STREG, FPU_PUSH | FPU_READ_STREG, @@ -722,129 +741,145 @@ uint64_t opcode_deps_d9_mod3[64] = 0, 0, 0, 0, /* opFRNDINT opFSCALE opFSIN opFCOS*/ 0, 0, 0, 0 + // clang-format on }; -uint64_t opcode_deps_da[8] = -{ +uint64_t opcode_deps_da[8] = { + // clang-format off /* FIADDl FIMULl FICOMl FICOMPl*/ FPU_RW_ST0 | MODRM, FPU_RW_ST0 | MODRM, FPU_READ_ST0 | MODRM, FPU_READ_ST0 | FPU_POP | MODRM, /* FISUBl FISUBRl FIDIVl FIDIVRl*/ FPU_RW_ST0 | MODRM, FPU_RW_ST0 | MODRM, FPU_RW_ST0 | MODRM, FPU_RW_ST0 | MODRM + // clang-format on }; -uint64_t opcode_deps_da_mod3[8] = -{ +uint64_t opcode_deps_da_mod3[8] = { + // clang-format off 0, 0, 0, 0, /* FCOMPP*/ 0, FPU_POP2, 0, 0 + // clang-format on }; - -uint64_t opcode_deps_db[8] = -{ +uint64_t opcode_deps_db[8] = { + // clang-format off /* FLDil FSTil FSTPil*/ FPU_PUSH | MODRM, 0, FPU_READ_ST0 | MODRM, FPU_READ_ST0 | FPU_POP | MODRM, /* FLDe FSTPe*/ 0, FPU_PUSH | MODRM, 0, FPU_READ_ST0 | FPU_POP | MODRM + // clang-format on }; -uint64_t opcode_deps_db_mod3[64] = -{ +uint64_t opcode_deps_db_mod3[64] = { + // clang-format off 0, 0, 0, 0, 0, 0, 0, 0, - + 0, 0, 0, 0, 0, 0, 0, 0, - + 0, 0, 0, 0, 0, 0, 0, 0, - - + + 0, 0, 0, 0, 0, 0, 0, 0, - + /* opFNOP opFCLEX opFINIT*/ 0, 0, 0, 0, /* opFNOP opFNOP*/ 0, 0, 0, 0, - + 0, 0, 0, 0, 0, 0, 0, 0, - + 0, 0, 0, 0, 0, 0, 0, 0, - - 0, 0, 0, 0, 0, 0, 0, 0, + + 0, 0, 0, 0, 0, 0, 0, 0, + // clang-format on }; -uint64_t opcode_deps_dc[8] = -{ +uint64_t opcode_deps_dc[8] = { + // clang-format off /* FADDd FMULd FCOMd FCOMPd*/ FPU_RW_ST0 | MODRM, FPU_RW_ST0 | MODRM, FPU_READ_ST0 | MODRM, FPU_READ_ST0 | FPU_POP | MODRM, /* FSUBd FSUBRd FDIVd FDIVRd*/ FPU_RW_ST0 | MODRM, FPU_RW_ST0 | MODRM, FPU_RW_ST0 | MODRM, FPU_RW_ST0 | MODRM + // clang-format on }; -uint64_t opcode_deps_dc_mod3[8] = -{ +uint64_t opcode_deps_dc_mod3[8] = { + // clang-format off /* opFADDr opFMULr*/ FPU_READ_ST0 | FPU_RW_STREG, FPU_READ_ST0 | FPU_RW_STREG, 0, 0, /* opFSUBRr opFSUBr opFDIVRr opFDIVr*/ FPU_READ_ST0 | FPU_RW_STREG, FPU_READ_ST0 | FPU_RW_STREG, FPU_READ_ST0 | FPU_RW_STREG, FPU_READ_ST0 | FPU_RW_STREG + // clang-format on }; -uint64_t opcode_deps_dd[8] = -{ +uint64_t opcode_deps_dd[8] = { + // clang-format off /* FLDd FSTd FSTPd*/ FPU_PUSH | MODRM, 0, FPU_READ_ST0 | MODRM, FPU_READ_ST0 | FPU_POP | MODRM, /* FRSTOR FSAVE FSTSW*/ MODRM, 0, MODRM, MODRM + // clang-format on }; -uint64_t opcode_deps_dd_mod3[8] = -{ +uint64_t opcode_deps_dd_mod3[8] = { + // clang-format off /* FFFREE FST FSTP*/ 0, 0, FPU_READ_ST0 | FPU_WRITE_STREG, FPU_READ_ST0 | FPU_WRITE_STREG | FPU_POP, /* FUCOM FUCOMP*/ FPU_READ_ST0 | FPU_READ_STREG, FPU_READ_ST0 | FPU_READ_STREG | FPU_POP, 0, 0 + // clang-format on }; -uint64_t opcode_deps_de[8] = -{ +uint64_t opcode_deps_de[8] = { + // clang-format off /* FIADDw FIMULw FICOMw FICOMPw*/ FPU_RW_ST0 | MODRM, FPU_RW_ST0 | MODRM, FPU_READ_ST0 | MODRM, FPU_READ_ST0 | FPU_POP | MODRM, /* FISUBw FISUBRw FIDIVw FIDIVRw*/ FPU_RW_ST0 | MODRM, FPU_RW_ST0 | MODRM, FPU_RW_ST0 | MODRM, FPU_RW_ST0 | MODRM + // clang-format on }; -uint64_t opcode_deps_de_mod3[8] = -{ +uint64_t opcode_deps_de_mod3[8] = { + // clang-format off /* FADDP FMULP FCOMPP*/ FPU_READ_ST0 | FPU_RW_STREG | FPU_POP, FPU_READ_ST0 | FPU_RW_STREG | FPU_POP, 0, FPU_READ_ST0 | FPU_READ_ST1 | FPU_POP2, /* FSUBP FSUBRP FDIVP FDIVRP*/ FPU_READ_ST0 | FPU_RW_STREG | FPU_POP, FPU_READ_ST0 | FPU_RW_STREG | FPU_POP, FPU_READ_ST0 | FPU_RW_STREG | FPU_POP, FPU_READ_ST0 | FPU_RW_STREG | FPU_POP + // clang-format on }; -uint64_t opcode_deps_df[8] = -{ +uint64_t opcode_deps_df[8] = { + // clang-format off /* FILDiw FISTiw FISTPiw*/ FPU_PUSH | MODRM, 0, FPU_READ_ST0 | MODRM, FPU_READ_ST0 | FPU_POP | MODRM, /* FILDiq FBSTP FISTPiq*/ 0, FPU_PUSH | MODRM, FPU_READ_ST0 | FPU_POP | MODRM, FPU_READ_ST0 | FPU_POP | MODRM + // clang-format on }; -uint64_t opcode_deps_df_mod3[8] = -{ +uint64_t opcode_deps_df_mod3[8] = { + // clang-format off 0, 0, 0, 0, /* FSTSW AX*/ 0, 0, 0, 0 + // clang-format on }; -uint64_t opcode_deps_81[8] = -{ +uint64_t opcode_deps_81[8] = { + // clang-format off MODRM | HAS_IMM1632, MODRM | HAS_IMM1632, MODRM | HAS_IMM1632, MODRM | HAS_IMM1632, MODRM | HAS_IMM1632, MODRM | HAS_IMM1632, MODRM | HAS_IMM1632, MODRM | HAS_IMM1632 + // clang-format on }; -uint64_t opcode_deps_81_mod3[8] = -{ +uint64_t opcode_deps_81_mod3[8] = { + // clang-format off SRCDEP_RM | DSTDEP_RM | MODRM | HAS_IMM1632, SRCDEP_RM | DSTDEP_RM | MODRM | HAS_IMM1632, SRCDEP_RM | DSTDEP_RM | MODRM | HAS_IMM1632, SRCDEP_RM | DSTDEP_RM | MODRM | HAS_IMM1632, SRCDEP_RM | DSTDEP_RM | MODRM | HAS_IMM1632, SRCDEP_RM | DSTDEP_RM | MODRM | HAS_IMM1632, SRCDEP_RM | DSTDEP_RM | MODRM | HAS_IMM1632, SRCDEP_RM | MODRM | HAS_IMM1632 + // clang-format on }; -uint64_t opcode_deps_8x[8] = -{ +uint64_t opcode_deps_8x[8] = { + // clang-format off MODRM | HAS_IMM8, MODRM | HAS_IMM8, MODRM | HAS_IMM8, MODRM | HAS_IMM8, MODRM | HAS_IMM8, MODRM | HAS_IMM8, MODRM | HAS_IMM8, MODRM | HAS_IMM8 + // clang-format on }; -uint64_t opcode_deps_8x_mod3[8] = -{ +uint64_t opcode_deps_8x_mod3[8] = { + // clang-format off SRCDEP_RM | DSTDEP_RM | MODRM | HAS_IMM8, SRCDEP_RM | DSTDEP_RM | MODRM | HAS_IMM8, SRCDEP_RM | DSTDEP_RM | MODRM | HAS_IMM8, SRCDEP_RM | DSTDEP_RM | MODRM | HAS_IMM8, SRCDEP_RM | DSTDEP_RM | MODRM | HAS_IMM8, SRCDEP_RM | DSTDEP_RM | MODRM | HAS_IMM8, SRCDEP_RM | DSTDEP_RM | MODRM | HAS_IMM8, SRCDEP_RM | MODRM | HAS_IMM8 + // clang-format on }; diff --git a/src/cpu/codegen_timing_common.h b/src/cpu/codegen_timing_common.h index 71daf80ef..3d28a89de 100644 --- a/src/cpu/codegen_timing_common.h +++ b/src/cpu/codegen_timing_common.h @@ -1,87 +1,84 @@ #include "codegen_ops.h" /*Instruction has input dependency on register in REG field*/ -#define SRCDEP_REG (1ull << 0) +#define SRCDEP_REG (1ULL << 0) /*Instruction has input dependency on register in R/M field*/ -#define SRCDEP_RM (1ull << 1) +#define SRCDEP_RM (1ULL << 1) /*Instruction modifies register in REG field*/ -#define DSTDEP_REG (1ull << 2) +#define DSTDEP_REG (1ULL << 2) /*Instruction modifies register in R/M field*/ -#define DSTDEP_RM (1ull << 3) +#define DSTDEP_RM (1ULL << 3) #define SRCDEP_SHIFT 4 #define DSTDEP_SHIFT 12 /*Instruction has input dependency on given register*/ -#define SRCDEP_EAX (1ull << 4) -#define SRCDEP_ECX (1ull << 5) -#define SRCDEP_EDX (1ull << 6) -#define SRCDEP_EBX (1ull << 7) -#define SRCDEP_ESP (1ull << 8) -#define SRCDEP_EBP (1ull << 9) -#define SRCDEP_ESI (1ull << 10) -#define SRCDEP_EDI (1ull << 11) +#define SRCDEP_EAX (1ULL << 4) +#define SRCDEP_ECX (1ULL << 5) +#define SRCDEP_EDX (1ULL << 6) +#define SRCDEP_EBX (1ULL << 7) +#define SRCDEP_ESP (1ULL << 8) +#define SRCDEP_EBP (1ULL << 9) +#define SRCDEP_ESI (1ULL << 10) +#define SRCDEP_EDI (1ULL << 11) /*Instruction modifies given register*/ -#define DSTDEP_EAX (1ull << 12) -#define DSTDEP_ECX (1ull << 13) -#define DSTDEP_EDX (1ull << 14) -#define DSTDEP_EBX (1ull << 15) -#define DSTDEP_ESP (1ull << 16) -#define DSTDEP_EBP (1ull << 17) -#define DSTDEP_ESI (1ull << 18) -#define DSTDEP_EDI (1ull << 19) +#define DSTDEP_EAX (1ULL << 12) +#define DSTDEP_ECX (1ULL << 13) +#define DSTDEP_EDX (1ULL << 14) +#define DSTDEP_EBX (1ULL << 15) +#define DSTDEP_ESP (1ULL << 16) +#define DSTDEP_EBP (1ULL << 17) +#define DSTDEP_ESI (1ULL << 18) +#define DSTDEP_EDI (1ULL << 19) /*Instruction has ModR/M byte*/ -#define MODRM (1ull << 20) +#define MODRM (1ULL << 20) /*Instruction implicitly uses ESP*/ -#define IMPL_ESP (1ull << 21) +#define IMPL_ESP (1ULL << 21) /*Instruction is MMX shift or pack/unpack instruction*/ -#define MMX_SHIFTPACK (1ull << 22) +#define MMX_SHIFTPACK (1ULL << 22) /*Instruction is MMX multiply instruction*/ -#define MMX_MULTIPLY (1ull << 23) +#define MMX_MULTIPLY (1ULL << 23) /*Instruction pops the FPU stack*/ -#define FPU_POP (1ull << 24) +#define FPU_POP (1ULL << 24) /*Instruction pops the FPU stack twice*/ -#define FPU_POP2 (1ull << 25) +#define FPU_POP2 (1ULL << 25) /*Instruction pushes onto the FPU stack*/ -#define FPU_PUSH (1ull << 26) +#define FPU_PUSH (1ULL << 26) /*Instruction writes to ST(0)*/ -#define FPU_WRITE_ST0 (1ull << 27) +#define FPU_WRITE_ST0 (1ULL << 27) /*Instruction reads from ST(0)*/ -#define FPU_READ_ST0 (1ull << 28) +#define FPU_READ_ST0 (1ULL << 28) /*Instruction reads from and writes to ST(0)*/ -#define FPU_RW_ST0 (3ull << 27) +#define FPU_RW_ST0 (3ULL << 27) /*Instruction reads from ST(1)*/ -#define FPU_READ_ST1 (1ull << 29) +#define FPU_READ_ST1 (1ULL << 29) /*Instruction writes to ST(1)*/ -#define FPU_WRITE_ST1 (1ull << 30) +#define FPU_WRITE_ST1 (1ULL << 30) /*Instruction reads from and writes to ST(1)*/ -#define FPU_RW_ST1 (3ull << 29) +#define FPU_RW_ST1 (3ULL << 29) /*Instruction reads from ST(reg)*/ -#define FPU_READ_STREG (1ull << 31) +#define FPU_READ_STREG (1ULL << 31) /*Instruction writes to ST(reg)*/ -#define FPU_WRITE_STREG (1ull << 32) +#define FPU_WRITE_STREG (1ULL << 32) /*Instruction reads from and writes to ST(reg)*/ -#define FPU_RW_STREG (3ull << 31) +#define FPU_RW_STREG (3ULL << 31) -#define FPU_FXCH (1ull << 33) +#define FPU_FXCH (1ULL << 33) +#define HAS_IMM8 (1ULL << 34) +#define HAS_IMM1632 (1ULL << 35) -#define HAS_IMM8 (1ull << 34) -#define HAS_IMM1632 (1ull << 35) - - -#define REGMASK_IMPL_ESP (1 << 8) +#define REGMASK_IMPL_ESP (1 << 8) #define REGMASK_SHIFTPACK (1 << 9) #define REGMASK_MULTIPLY (1 << 9) - extern uint64_t opcode_deps[256]; extern uint64_t opcode_deps_mod3[256]; extern uint64_t opcode_deps_0f[256]; @@ -119,114 +116,116 @@ extern uint64_t opcode_deps_81_mod3[8]; extern uint64_t opcode_deps_8x[8]; extern uint64_t opcode_deps_8x_mod3[8]; - - -static inline uint32_t get_addr_regmask(uint64_t data, uint32_t fetchdat, int op_32) +static inline uint32_t +get_addr_regmask(uint64_t data, uint32_t fetchdat, int op_32) { - uint32_t addr_regmask = 0; + uint32_t addr_regmask = 0; - if (data & MODRM) - { - uint8_t modrm = fetchdat & 0xff; + if (data & MODRM) { + uint8_t modrm = fetchdat & 0xff; - if ((modrm & 0xc0) != 0xc0) - { - if (op_32 & 0x200) - { - if ((modrm & 0x7) == 4) - { - uint8_t sib = (fetchdat >> 8) & 0xff; + if ((modrm & 0xc0) != 0xc0) { + if (op_32 & 0x200) { + if ((modrm & 0x7) == 4) { + uint8_t sib = (fetchdat >> 8) & 0xff; - if ((modrm & 0xc0) != 0xc0 && (sib & 7) != 5) - { - addr_regmask = 1 << (sib & 7); - if ((sib & 0x38) != 0x20) - addr_regmask |= 1 << ((sib >> 3) & 7); - } - } - else if ((modrm & 0xc7) != 5) - { - addr_regmask = 1 << (modrm & 7); - } - } - else - { - if ((modrm & 0xc7) != 0x06) - { - switch (modrm & 7) - { - case 0: addr_regmask = REG_BX | REG_SI; break; - case 1: addr_regmask = REG_BX | REG_DI; break; - case 2: addr_regmask = REG_BP | REG_SI; break; - case 3: addr_regmask = REG_BP | REG_DI; break; - case 4: addr_regmask = REG_SI; break; - case 5: addr_regmask = REG_DI; break; - case 6: addr_regmask = REG_BP; break; - case 7: addr_regmask = REG_BX; break; - } - } - } + if ((modrm & 0xc0) != 0xc0 && (sib & 7) != 5) { + addr_regmask = 1 << (sib & 7); + if ((sib & 0x38) != 0x20) + addr_regmask |= 1 << ((sib >> 3) & 7); + } + } else if ((modrm & 0xc7) != 5) { + addr_regmask = 1 << (modrm & 7); } + } else { + if ((modrm & 0xc7) != 0x06) { + switch (modrm & 7) { + case 0: + addr_regmask = REG_BX | REG_SI; + break; + case 1: + addr_regmask = REG_BX | REG_DI; + break; + case 2: + addr_regmask = REG_BP | REG_SI; + break; + case 3: + addr_regmask = REG_BP | REG_DI; + break; + case 4: + addr_regmask = REG_SI; + break; + case 5: + addr_regmask = REG_DI; + break; + case 6: + addr_regmask = REG_BP; + break; + case 7: + addr_regmask = REG_BX; + break; + } + } + } } + } - if (data & IMPL_ESP) - addr_regmask |= REGMASK_IMPL_ESP; - - return addr_regmask; + if (data & IMPL_ESP) + addr_regmask |= REGMASK_IMPL_ESP; + + return addr_regmask; } -static inline uint32_t get_srcdep_mask(uint64_t data, uint32_t fetchdat, int bit8, int op_32) +static inline uint32_t +get_srcdep_mask(uint64_t data, uint32_t fetchdat, int bit8, int op_32) { - uint32_t mask = 0; - if (data & SRCDEP_REG) - { - int reg = (fetchdat >> 3) & 7; - if (bit8) - reg &= 3; - mask |= (1 << reg); - } - if (data & SRCDEP_RM) - { - int reg = fetchdat & 7; - if (bit8) - reg &= 3; - mask |= (1 << reg); - } - mask |= ((data >> SRCDEP_SHIFT) & 0xff); - if (data & MMX_SHIFTPACK) - mask |= REGMASK_SHIFTPACK; - if (data & MMX_MULTIPLY) - mask |= REGMASK_MULTIPLY; + uint32_t mask = 0; + if (data & SRCDEP_REG) { + int reg = (fetchdat >> 3) & 7; + if (bit8) + reg &= 3; + mask |= (1 << reg); + } + if (data & SRCDEP_RM) { + int reg = fetchdat & 7; + if (bit8) + reg &= 3; + mask |= (1 << reg); + } + mask |= ((data >> SRCDEP_SHIFT) & 0xff); + if (data & MMX_SHIFTPACK) + mask |= REGMASK_SHIFTPACK; + if (data & MMX_MULTIPLY) + mask |= REGMASK_MULTIPLY; - mask |= get_addr_regmask(data, fetchdat, op_32); + mask |= get_addr_regmask(data, fetchdat, op_32); - return mask; + return mask; } -static inline uint32_t get_dstdep_mask(uint64_t data, uint32_t fetchdat, int bit8) +static inline uint32_t +get_dstdep_mask(uint64_t data, uint32_t fetchdat, int bit8) { - uint32_t mask = 0; - if (data & DSTDEP_REG) - { - int reg = (fetchdat >> 3) & 7; - if (bit8) - reg &= 3; - mask |= (1 << reg); - } - if (data & DSTDEP_RM) - { - int reg = fetchdat & 7; - if (bit8) - reg &= 3; - mask |= (1 << reg); - } - mask |= ((data >> DSTDEP_SHIFT) & 0xff); - if (data & MMX_SHIFTPACK) - mask |= REGMASK_SHIFTPACK; - if (data & MMX_MULTIPLY) - mask |= REGMASK_MULTIPLY; - if (data & IMPL_ESP) - mask |= REGMASK_IMPL_ESP | (1 << REG_ESP); + uint32_t mask = 0; + if (data & DSTDEP_REG) { + int reg = (fetchdat >> 3) & 7; + if (bit8) + reg &= 3; + mask |= (1 << reg); + } + if (data & DSTDEP_RM) { + int reg = fetchdat & 7; + if (bit8) + reg &= 3; + mask |= (1 << reg); + } + mask |= ((data >> DSTDEP_SHIFT) & 0xff); + if (data & MMX_SHIFTPACK) + mask |= REGMASK_SHIFTPACK; + if (data & MMX_MULTIPLY) + mask |= REGMASK_MULTIPLY; + if (data & IMPL_ESP) + mask |= REGMASK_IMPL_ESP | (1 << REG_ESP); - return mask; + return mask; } diff --git a/src/cpu/codegen_timing_k6.c b/src/cpu/codegen_timing_k6.c index 69c960b6e..4a9f23cd8 100644 --- a/src/cpu/codegen_timing_k6.c +++ b/src/cpu/codegen_timing_k6.c @@ -1,5 +1,5 @@ /*Most of the vector instructions here are a total guess. - Some of the timings are based on http://users.atw.hu/instlatx64/AuthenticAMD0000562_K6_InstLatX86.txt*/ + Some of the timings are based on http://http://web.archive.org/web/20181122095446/http://users.atw.hu/instlatx64/AuthenticAMD0000562_K6_InstLatX86.txt*/ #include #include #include @@ -8,873 +8,758 @@ #include <86box/mem.h> #include "cpu.h" #include <86box/machine.h> + #include "x86.h" #include "x86_ops.h" +#include "x86seg_common.h" #include "x87.h" #include "386_common.h" #include "codegen.h" #include "codegen_ops.h" #include "codegen_timing_common.h" -typedef enum uop_type_t -{ - UOP_ALU = 0, /*Executes in Integer X or Y units*/ - UOP_ALUX, /*Executes in Integer X unit*/ - UOP_LOAD, /*Executes in Load unit*/ - UOP_STORE, /*Executes in Store unit*/ - UOP_FLOAD, /*Executes in Load unit*/ - UOP_FSTORE, /*Executes in Store unit*/ - UOP_MLOAD, /*Executes in Load unit*/ - UOP_MSTORE, /*Executes in Store unit*/ - UOP_FLOAT, /*Executes in Floating Point unit*/ - UOP_MEU, /*Executes in Multimedia unit*/ - UOP_MEU_SHIFT, /*Executes in Multimedia unit or ALU X/Y. Uses MMX shifter*/ - UOP_MEU_MUL, /*Executes in Multimedia unit or ALU X/Y. Uses MMX/3DNow multiplier*/ - UOP_MEU_3DN, /*Executes in Multimedia unit or ALU X/Y. Uses 3DNow ALU*/ - UOP_BRANCH, /*Executes in Branch unit*/ - UOP_LIMM /*Does not require an execution unit*/ +typedef enum uop_type_t { + UOP_ALU = 0, /*Executes in Integer X or Y units*/ + UOP_ALUX, /*Executes in Integer X unit*/ + UOP_LOAD, /*Executes in Load unit*/ + UOP_STORE, /*Executes in Store unit*/ + UOP_FLOAD, /*Executes in Load unit*/ + UOP_FSTORE, /*Executes in Store unit*/ + UOP_MLOAD, /*Executes in Load unit*/ + UOP_MSTORE, /*Executes in Store unit*/ + UOP_FLOAT, /*Executes in Floating Point unit*/ + UOP_MEU, /*Executes in Multimedia unit*/ + UOP_MEU_SHIFT, /*Executes in Multimedia unit or ALU X/Y. Uses MMX shifter*/ + UOP_MEU_MUL, /*Executes in Multimedia unit or ALU X/Y. Uses MMX/3DNow multiplier*/ + UOP_MEU_3DN, /*Executes in Multimedia unit or ALU X/Y. Uses 3DNow ALU*/ + UOP_BRANCH, /*Executes in Branch unit*/ + UOP_LIMM /*Does not require an execution unit*/ } uop_type_t; -typedef enum decode_type_t -{ - DECODE_SHORT, - DECODE_LONG, - DECODE_VECTOR +typedef enum decode_type_t { + DECODE_SHORT, + DECODE_LONG, + DECODE_VECTOR } decode_type_t; #define MAX_UOPS 10 -typedef struct risc86_uop_t -{ - uop_type_t type; - int throughput; - int latency; +typedef struct risc86_uop_t { + uop_type_t type; + int throughput; + int latency; } risc86_uop_t; -typedef struct risc86_instruction_t -{ - int nr_uops; - decode_type_t decode_type; - risc86_uop_t uop[MAX_UOPS]; +typedef struct risc86_instruction_t { + int nr_uops; + decode_type_t decode_type; + risc86_uop_t uop[MAX_UOPS]; } risc86_instruction_t; -static const risc86_instruction_t alu_op = -{ - .nr_uops = 1, - .decode_type = DECODE_SHORT, - .uop[0] = {.type = UOP_ALU, .throughput = 1, .latency = 1} +static const risc86_instruction_t alu_op = { + .nr_uops = 1, + .decode_type = DECODE_SHORT, + .uop[0] = {.type = UOP_ALU, .throughput = 1, .latency = 1} }; -static const risc86_instruction_t alux_op = -{ - .nr_uops = 1, - .decode_type = DECODE_SHORT, - .uop[0] = {.type = UOP_ALUX, .throughput = 1, .latency = 1} +static const risc86_instruction_t alux_op = { + .nr_uops = 1, + .decode_type = DECODE_SHORT, + .uop[0] = {.type = UOP_ALUX, .throughput = 1, .latency = 1} }; -static const risc86_instruction_t load_alu_op = -{ - .nr_uops = 2, - .decode_type = DECODE_SHORT, - .uop[0] = {.type = UOP_LOAD, .throughput = 1, .latency = 2}, - .uop[1] = {.type = UOP_ALU, .throughput = 1, .latency = 1} +static const risc86_instruction_t load_alu_op = { + .nr_uops = 2, + .decode_type = DECODE_SHORT, + .uop[0] = {.type = UOP_LOAD, .throughput = 1, .latency = 2}, + .uop[1] = { .type = UOP_ALU, .throughput = 1, .latency = 1} }; -static const risc86_instruction_t load_alux_op = -{ - .nr_uops = 2, - .decode_type = DECODE_SHORT, - .uop[0] = {.type = UOP_LOAD, .throughput = 1, .latency = 2}, - .uop[1] = {.type = UOP_ALUX, .throughput = 1, .latency = 1} +static const risc86_instruction_t load_alux_op = { + .nr_uops = 2, + .decode_type = DECODE_SHORT, + .uop[0] = {.type = UOP_LOAD, .throughput = 1, .latency = 2}, + .uop[1] = { .type = UOP_ALUX, .throughput = 1, .latency = 1} }; -static const risc86_instruction_t alu_store_op = -{ - .nr_uops = 3, - .decode_type = DECODE_LONG, - .uop[0] = {.type = UOP_LOAD, .throughput = 1, .latency = 2}, - .uop[1] = {.type = UOP_ALU, .throughput = 1, .latency = 1}, - .uop[2] = {.type = UOP_STORE, .throughput = 1, .latency = 1} +static const risc86_instruction_t alu_store_op = { + .nr_uops = 3, + .decode_type = DECODE_LONG, + .uop[0] = {.type = UOP_LOAD, .throughput = 1, .latency = 2}, + .uop[1] = { .type = UOP_ALU, .throughput = 1, .latency = 1}, + .uop[2] = { .type = UOP_STORE, .throughput = 1, .latency = 1} }; -static const risc86_instruction_t alux_store_op = -{ - .nr_uops = 3, - .decode_type = DECODE_LONG, - .uop[0] = {.type = UOP_LOAD, .throughput = 1, .latency = 2}, - .uop[1] = {.type = UOP_ALUX, .throughput = 1, .latency = 1}, - .uop[2] = {.type = UOP_STORE, .throughput = 1, .latency = 1} +static const risc86_instruction_t alux_store_op = { + .nr_uops = 3, + .decode_type = DECODE_LONG, + .uop[0] = {.type = UOP_LOAD, .throughput = 1, .latency = 2}, + .uop[1] = { .type = UOP_ALUX, .throughput = 1, .latency = 1}, + .uop[2] = { .type = UOP_STORE, .throughput = 1, .latency = 1} }; -static const risc86_instruction_t branch_op = -{ - .nr_uops = 1, - .decode_type = DECODE_SHORT, - .uop[0] = {.type = UOP_BRANCH, .throughput = 1, .latency = 1} +static const risc86_instruction_t branch_op = { + .nr_uops = 1, + .decode_type = DECODE_SHORT, + .uop[0] = {.type = UOP_BRANCH, .throughput = 1, .latency = 1} }; -static const risc86_instruction_t limm_op = -{ - .nr_uops = 1, - .decode_type = DECODE_SHORT, - .uop[0] = {.type = UOP_LIMM, .throughput = 1, .latency = 1} +static const risc86_instruction_t limm_op = { + .nr_uops = 1, + .decode_type = DECODE_SHORT, + .uop[0] = {.type = UOP_LIMM, .throughput = 1, .latency = 1} }; -static const risc86_instruction_t load_op = -{ - .nr_uops = 1, - .decode_type = DECODE_SHORT, - .uop[0] = {.type = UOP_LOAD, .throughput = 1, .latency = 2} +static const risc86_instruction_t load_op = { + .nr_uops = 1, + .decode_type = DECODE_SHORT, + .uop[0] = {.type = UOP_LOAD, .throughput = 1, .latency = 2} }; -static const risc86_instruction_t store_op = -{ - .nr_uops = 1, - .decode_type = DECODE_SHORT, - .uop[0] = {.type = UOP_STORE, .throughput = 1, .latency = 1} +static const risc86_instruction_t store_op = { + .nr_uops = 1, + .decode_type = DECODE_SHORT, + .uop[0] = {.type = UOP_STORE, .throughput = 1, .latency = 1} }; - -static const risc86_instruction_t bswap_op = -{ - .nr_uops = 1, - .decode_type = DECODE_LONG, - .uop[0] = {.type = UOP_ALU, .throughput = 1, .latency = 1} +static const risc86_instruction_t bswap_op = { + .nr_uops = 1, + .decode_type = DECODE_LONG, + .uop[0] = {.type = UOP_ALU, .throughput = 1, .latency = 1} }; -static const risc86_instruction_t leave_op = -{ - .nr_uops = 3, - .decode_type = DECODE_LONG, - .uop[0] = {.type = UOP_LOAD, .throughput = 1, .latency = 2}, - .uop[1] = {.type = UOP_ALU, .throughput = 1, .latency = 1}, - .uop[2] = {.type = UOP_ALU, .throughput = 1, .latency = 1} +static const risc86_instruction_t leave_op = { + .nr_uops = 3, + .decode_type = DECODE_LONG, + .uop[0] = {.type = UOP_LOAD, .throughput = 1, .latency = 2}, + .uop[1] = { .type = UOP_ALU, .throughput = 1, .latency = 1}, + .uop[2] = { .type = UOP_ALU, .throughput = 1, .latency = 1} }; -static const risc86_instruction_t lods_op = -{ - .nr_uops = 2, - .decode_type = DECODE_LONG, - .uop[0] = {.type = UOP_LOAD, .throughput = 1, .latency = 2}, - .uop[1] = {.type = UOP_ALU, .throughput = 1, .latency = 1} +static const risc86_instruction_t lods_op = { + .nr_uops = 2, + .decode_type = DECODE_LONG, + .uop[0] = {.type = UOP_LOAD, .throughput = 1, .latency = 2}, + .uop[1] = { .type = UOP_ALU, .throughput = 1, .latency = 1} }; -static const risc86_instruction_t loop_op = -{ - .nr_uops = 2, - .decode_type = DECODE_SHORT, - .uop[0] = {.type = UOP_ALU, .throughput = 1, .latency = 1}, - .uop[1] = {.type = UOP_BRANCH, .throughput = 1, .latency = 1} +static const risc86_instruction_t loop_op = { + .nr_uops = 2, + .decode_type = DECODE_SHORT, + .uop[0] = {.type = UOP_ALU, .throughput = 1, .latency = 1}, + .uop[1] = { .type = UOP_BRANCH, .throughput = 1, .latency = 1} }; -static const risc86_instruction_t mov_reg_seg_op = -{ - .nr_uops = 1, - .decode_type = DECODE_LONG, - .uop[0] = {.type = UOP_LOAD, .throughput = 1, .latency = 2}, +static const risc86_instruction_t mov_reg_seg_op = { + .nr_uops = 1, + .decode_type = DECODE_LONG, + .uop[0] = {.type = UOP_LOAD, .throughput = 1, .latency = 2}, }; -static const risc86_instruction_t movs_op = -{ - .nr_uops = 4, - .decode_type = DECODE_LONG, - .uop[0] = {.type = UOP_LOAD, .throughput = 1, .latency = 2}, - .uop[1] = {.type = UOP_STORE, .throughput = 1, .latency = 1}, - .uop[2] = {.type = UOP_ALU, .throughput = 1, .latency = 1}, - .uop[3] = {.type = UOP_ALU, .throughput = 1, .latency = 1} +static const risc86_instruction_t movs_op = { + .nr_uops = 4, + .decode_type = DECODE_LONG, + .uop[0] = {.type = UOP_LOAD, .throughput = 1, .latency = 2}, + .uop[1] = { .type = UOP_STORE, .throughput = 1, .latency = 1}, + .uop[2] = { .type = UOP_ALU, .throughput = 1, .latency = 1}, + .uop[3] = { .type = UOP_ALU, .throughput = 1, .latency = 1} }; -static const risc86_instruction_t pop_reg_op = -{ - .nr_uops = 2, - .decode_type = DECODE_SHORT, - .uop[0] = {.type = UOP_LOAD, .throughput = 1, .latency = 2}, - .uop[1] = {.type = UOP_ALU, .throughput = 1, .latency = 1} +static const risc86_instruction_t pop_reg_op = { + .nr_uops = 2, + .decode_type = DECODE_SHORT, + .uop[0] = {.type = UOP_LOAD, .throughput = 1, .latency = 2}, + .uop[1] = { .type = UOP_ALU, .throughput = 1, .latency = 1} }; -static const risc86_instruction_t pop_mem_op = -{ - .nr_uops = 3, - .decode_type = DECODE_LONG, - .uop[0] = {.type = UOP_LOAD, .throughput = 1, .latency = 2}, - .uop[1] = {.type = UOP_STORE, .throughput = 1, .latency = 1}, - .uop[2] = {.type = UOP_ALU, .throughput = 1, .latency = 1} +static const risc86_instruction_t pop_mem_op = { + .nr_uops = 3, + .decode_type = DECODE_LONG, + .uop[0] = {.type = UOP_LOAD, .throughput = 1, .latency = 2}, + .uop[1] = { .type = UOP_STORE, .throughput = 1, .latency = 1}, + .uop[2] = { .type = UOP_ALU, .throughput = 1, .latency = 1} }; -static const risc86_instruction_t push_imm_op = -{ - .nr_uops = 1, - .decode_type = DECODE_LONG, - .uop[0] = {.type = UOP_STORE, .throughput = 1, .latency = 2}, +static const risc86_instruction_t push_imm_op = { + .nr_uops = 1, + .decode_type = DECODE_LONG, + .uop[0] = {.type = UOP_STORE, .throughput = 1, .latency = 2}, }; -static const risc86_instruction_t push_mem_op = -{ - .nr_uops = 2, - .decode_type = DECODE_LONG, - .uop[0] = {.type = UOP_LOAD, .throughput = 1, .latency = 2}, - .uop[1] = {.type = UOP_STORE, .throughput = 1, .latency = 1} +static const risc86_instruction_t push_mem_op = { + .nr_uops = 2, + .decode_type = DECODE_LONG, + .uop[0] = {.type = UOP_LOAD, .throughput = 1, .latency = 2}, + .uop[1] = { .type = UOP_STORE, .throughput = 1, .latency = 1} }; -static const risc86_instruction_t push_seg_op = -{ - .nr_uops = 2, - .decode_type = DECODE_LONG, - .uop[0] = {.type = UOP_LOAD, .throughput = 1, .latency = 2}, - .uop[1] = {.type = UOP_STORE, .throughput = 1, .latency = 1} +static const risc86_instruction_t push_seg_op = { + .nr_uops = 2, + .decode_type = DECODE_LONG, + .uop[0] = {.type = UOP_LOAD, .throughput = 1, .latency = 2}, + .uop[1] = { .type = UOP_STORE, .throughput = 1, .latency = 1} }; -static const risc86_instruction_t stos_op = -{ - .nr_uops = 2, - .decode_type = DECODE_LONG, - .uop[1] = {.type = UOP_STORE, .throughput = 1, .latency = 1}, - .uop[3] = {.type = UOP_ALU, .throughput = 1, .latency = 1} +static const risc86_instruction_t stos_op = { + .nr_uops = 2, + .decode_type = DECODE_LONG, + .uop[1] = {.type = UOP_STORE, .throughput = 1, .latency = 1}, + .uop[3] = { .type = UOP_ALU, .throughput = 1, .latency = 1} }; -static const risc86_instruction_t test_reg_op = -{ - .nr_uops = 1, - .decode_type = DECODE_LONG, - .uop[0] = {.type = UOP_ALU, .throughput = 1, .latency = 1} +static const risc86_instruction_t test_reg_op = { + .nr_uops = 1, + .decode_type = DECODE_LONG, + .uop[0] = {.type = UOP_ALU, .throughput = 1, .latency = 1} }; -static const risc86_instruction_t test_reg_b_op = -{ - .nr_uops = 1, - .decode_type = DECODE_LONG, - .uop[0] = {.type = UOP_ALUX, .throughput = 1, .latency = 1} +static const risc86_instruction_t test_reg_b_op = { + .nr_uops = 1, + .decode_type = DECODE_LONG, + .uop[0] = {.type = UOP_ALUX, .throughput = 1, .latency = 1} }; -static const risc86_instruction_t test_mem_imm_op = -{ - .nr_uops = 2, - .decode_type = DECODE_LONG, - .uop[0] = {.type = UOP_LOAD, .throughput = 1, .latency = 2}, - .uop[1] = {.type = UOP_ALU, .throughput = 1, .latency = 1} +static const risc86_instruction_t test_mem_imm_op = { + .nr_uops = 2, + .decode_type = DECODE_LONG, + .uop[0] = {.type = UOP_LOAD, .throughput = 1, .latency = 2}, + .uop[1] = { .type = UOP_ALU, .throughput = 1, .latency = 1} }; -static const risc86_instruction_t test_mem_imm_b_op = -{ - .nr_uops = 2, - .decode_type = DECODE_LONG, - .uop[0] = {.type = UOP_LOAD, .throughput = 1, .latency = 2}, - .uop[1] = {.type = UOP_ALUX, .throughput = 1, .latency = 1} +static const risc86_instruction_t test_mem_imm_b_op = { + .nr_uops = 2, + .decode_type = DECODE_LONG, + .uop[0] = {.type = UOP_LOAD, .throughput = 1, .latency = 2}, + .uop[1] = { .type = UOP_ALUX, .throughput = 1, .latency = 1} }; -static const risc86_instruction_t xchg_op = -{ - .nr_uops = 3, - .decode_type = DECODE_LONG, - .uop[0] = {.type = UOP_ALU, .throughput = 1, .latency = 1}, - .uop[1] = {.type = UOP_ALU, .throughput = 1, .latency = 1}, - .uop[2] = {.type = UOP_ALU, .throughput = 1, .latency = 1} +static const risc86_instruction_t xchg_op = { + .nr_uops = 3, + .decode_type = DECODE_LONG, + .uop[0] = {.type = UOP_ALU, .throughput = 1, .latency = 1}, + .uop[1] = { .type = UOP_ALU, .throughput = 1, .latency = 1}, + .uop[2] = { .type = UOP_ALU, .throughput = 1, .latency = 1} }; -static const risc86_instruction_t m3dn_op = -{ - .nr_uops = 1, - .decode_type = DECODE_SHORT, - .uop[0] = {.type = UOP_MEU_3DN, .throughput = 1, .latency = 1} +static const risc86_instruction_t m3dn_op = { + .nr_uops = 1, + .decode_type = DECODE_SHORT, + .uop[0] = {.type = UOP_MEU_3DN, .throughput = 1, .latency = 1} }; -static const risc86_instruction_t mmx_op = -{ - .nr_uops = 1, - .decode_type = DECODE_SHORT, - .uop[0] = {.type = UOP_MEU, .throughput = 1, .latency = 1} +static const risc86_instruction_t mmx_op = { + .nr_uops = 1, + .decode_type = DECODE_SHORT, + .uop[0] = {.type = UOP_MEU, .throughput = 1, .latency = 1} }; -static const risc86_instruction_t mmx_mul_op = -{ - .nr_uops = 1, - .decode_type = DECODE_SHORT, - .uop[0] = {.type = UOP_MEU_MUL, .throughput = 1, .latency = 2} +static const risc86_instruction_t mmx_mul_op = { + .nr_uops = 1, + .decode_type = DECODE_SHORT, + .uop[0] = {.type = UOP_MEU_MUL, .throughput = 1, .latency = 2} }; -static const risc86_instruction_t mmx_shift_op = -{ - .nr_uops = 1, - .decode_type = DECODE_SHORT, - .uop[0] = {.type = UOP_MEU_SHIFT, .throughput = 1, .latency = 1} +static const risc86_instruction_t mmx_shift_op = { + .nr_uops = 1, + .decode_type = DECODE_SHORT, + .uop[0] = {.type = UOP_MEU_SHIFT, .throughput = 1, .latency = 1} }; -static const risc86_instruction_t load_3dn_op = -{ - .nr_uops = 2, - .decode_type = DECODE_SHORT, - .uop[0] = {.type = UOP_LOAD, .throughput = 1, .latency = 2}, - .uop[1] = {.type = UOP_MEU_3DN, .throughput = 1, .latency = 1} +static const risc86_instruction_t load_3dn_op = { + .nr_uops = 2, + .decode_type = DECODE_SHORT, + .uop[0] = {.type = UOP_LOAD, .throughput = 1, .latency = 2}, + .uop[1] = { .type = UOP_MEU_3DN, .throughput = 1, .latency = 1} }; -static const risc86_instruction_t load_mmx_op = -{ - .nr_uops = 2, - .decode_type = DECODE_SHORT, - .uop[0] = {.type = UOP_LOAD, .throughput = 1, .latency = 2}, - .uop[1] = {.type = UOP_MEU, .throughput = 1, .latency = 1} +static const risc86_instruction_t load_mmx_op = { + .nr_uops = 2, + .decode_type = DECODE_SHORT, + .uop[0] = {.type = UOP_LOAD, .throughput = 1, .latency = 2}, + .uop[1] = { .type = UOP_MEU, .throughput = 1, .latency = 1} }; -static const risc86_instruction_t load_mmx_mul_op = -{ - .nr_uops = 2, - .decode_type = DECODE_SHORT, - .uop[0] = {.type = UOP_LOAD, .throughput = 1, .latency = 2}, - .uop[1] = {.type = UOP_MEU_MUL, .throughput = 1, .latency = 2} +static const risc86_instruction_t load_mmx_mul_op = { + .nr_uops = 2, + .decode_type = DECODE_SHORT, + .uop[0] = {.type = UOP_LOAD, .throughput = 1, .latency = 2}, + .uop[1] = { .type = UOP_MEU_MUL, .throughput = 1, .latency = 2} }; -static const risc86_instruction_t load_mmx_shift_op = -{ - .nr_uops = 2, - .decode_type = DECODE_SHORT, - .uop[0] = {.type = UOP_LOAD, .throughput = 1, .latency = 2}, - .uop[1] = {.type = UOP_MEU_SHIFT, .throughput = 1, .latency = 1} +static const risc86_instruction_t load_mmx_shift_op = { + .nr_uops = 2, + .decode_type = DECODE_SHORT, + .uop[0] = {.type = UOP_LOAD, .throughput = 1, .latency = 2}, + .uop[1] = { .type = UOP_MEU_SHIFT, .throughput = 1, .latency = 1} }; -static const risc86_instruction_t mload_op = -{ - .nr_uops = 1, - .decode_type = DECODE_SHORT, - .uop[0] = {.type = UOP_MLOAD, .throughput = 1, .latency = 2} +static const risc86_instruction_t mload_op = { + .nr_uops = 1, + .decode_type = DECODE_SHORT, + .uop[0] = {.type = UOP_MLOAD, .throughput = 1, .latency = 2} }; -static const risc86_instruction_t mstore_op = -{ - .nr_uops = 1, - .decode_type = DECODE_SHORT, - .uop[0] = {.type = UOP_MSTORE, .throughput = 1, .latency = 1} +static const risc86_instruction_t mstore_op = { + .nr_uops = 1, + .decode_type = DECODE_SHORT, + .uop[0] = {.type = UOP_MSTORE, .throughput = 1, .latency = 1} }; -static const risc86_instruction_t pmul_op = -{ - .nr_uops = 1, - .decode_type = DECODE_SHORT, - .uop[0] = {.type = UOP_MEU_MUL, .throughput = 1, .latency = 2} +static const risc86_instruction_t pmul_op = { + .nr_uops = 1, + .decode_type = DECODE_SHORT, + .uop[0] = {.type = UOP_MEU_MUL, .throughput = 1, .latency = 2} }; -static const risc86_instruction_t pmul_mem_op = -{ - .nr_uops = 2, - .decode_type = DECODE_SHORT, - .uop[0] = {.type = UOP_LOAD, .throughput = 1, .latency = 2}, - .uop[1] = {.type = UOP_MEU_MUL, .throughput = 1, .latency = 2} +static const risc86_instruction_t pmul_mem_op = { + .nr_uops = 2, + .decode_type = DECODE_SHORT, + .uop[0] = {.type = UOP_LOAD, .throughput = 1, .latency = 2}, + .uop[1] = { .type = UOP_MEU_MUL, .throughput = 1, .latency = 2} }; -static const risc86_instruction_t float_op = -{ - .nr_uops = 1, - .decode_type = DECODE_SHORT, - .uop[0] = {.type = UOP_FLOAT, .throughput = 2, .latency = 2} +static const risc86_instruction_t float_op = { + .nr_uops = 1, + .decode_type = DECODE_SHORT, + .uop[0] = {.type = UOP_FLOAT, .throughput = 2, .latency = 2} }; -static const risc86_instruction_t load_float_op = -{ - .nr_uops = 2, - .decode_type = DECODE_SHORT, - .uop[0] = {.type = UOP_FLOAD, .throughput = 1, .latency = 2}, - .uop[1] = {.type = UOP_FLOAT, .throughput = 2, .latency = 2} +static const risc86_instruction_t load_float_op = { + .nr_uops = 2, + .decode_type = DECODE_SHORT, + .uop[0] = {.type = UOP_FLOAD, .throughput = 1, .latency = 2}, + .uop[1] = { .type = UOP_FLOAT, .throughput = 2, .latency = 2} }; -static const risc86_instruction_t fstore_op = -{ - .nr_uops = 1, - .decode_type = DECODE_SHORT, - .uop[0] = {.type = UOP_FSTORE, .throughput = 1, .latency = 1} +static const risc86_instruction_t fstore_op = { + .nr_uops = 1, + .decode_type = DECODE_SHORT, + .uop[0] = {.type = UOP_FSTORE, .throughput = 1, .latency = 1} }; -static const risc86_instruction_t fdiv_op = -{ - .nr_uops = 1, - .decode_type = DECODE_SHORT, - .uop[0] = {.type = UOP_FLOAT, .throughput = 40, .latency = 40} +static const risc86_instruction_t fdiv_op = { + .nr_uops = 1, + .decode_type = DECODE_SHORT, + .uop[0] = {.type = UOP_FLOAT, .throughput = 40, .latency = 40} }; -static const risc86_instruction_t fdiv_mem_op = -{ - .nr_uops = 2, - .decode_type = DECODE_SHORT, - .uop[0] = {.type = UOP_FLOAD, .throughput = 1, .latency = 2}, - .uop[1] = {.type = UOP_FLOAT, .throughput = 40, .latency = 40} +static const risc86_instruction_t fdiv_mem_op = { + .nr_uops = 2, + .decode_type = DECODE_SHORT, + .uop[0] = {.type = UOP_FLOAD, .throughput = 1, .latency = 2 }, + .uop[1] = { .type = UOP_FLOAT, .throughput = 40, .latency = 40} }; -static const risc86_instruction_t fsin_op = -{ - .nr_uops = 1, - .decode_type = DECODE_SHORT, - .uop[0] = {.type = UOP_FLOAT, .throughput = 62, .latency = 62} +static const risc86_instruction_t fsin_op = { + .nr_uops = 1, + .decode_type = DECODE_SHORT, + .uop[0] = {.type = UOP_FLOAT, .throughput = 62, .latency = 62} }; -static const risc86_instruction_t fsqrt_op = -{ - .nr_uops = 1, - .decode_type = DECODE_SHORT, - .uop[0] = {.type = UOP_FLOAT, .throughput = 41, .latency = 41} +static const risc86_instruction_t fsqrt_op = { + .nr_uops = 1, + .decode_type = DECODE_SHORT, + .uop[0] = {.type = UOP_FLOAT, .throughput = 41, .latency = 41} }; -static const risc86_instruction_t vector_fldcw_op = -{ - .nr_uops = 1, - .decode_type = DECODE_VECTOR, - .uop[0] = {.type = UOP_FLOAT, .throughput = 8, .latency = 8} +static const risc86_instruction_t vector_fldcw_op = { + .nr_uops = 1, + .decode_type = DECODE_VECTOR, + .uop[0] = {.type = UOP_FLOAT, .throughput = 8, .latency = 8} }; -static const risc86_instruction_t vector_float_op = -{ - .nr_uops = 1, - .decode_type = DECODE_VECTOR, - .uop[0] = {.type = UOP_FLOAT, .throughput = 2, .latency = 2} +static const risc86_instruction_t vector_float_op = { + .nr_uops = 1, + .decode_type = DECODE_VECTOR, + .uop[0] = {.type = UOP_FLOAT, .throughput = 2, .latency = 2} }; -static const risc86_instruction_t vector_float_l_op = -{ - .nr_uops = 1, - .decode_type = DECODE_VECTOR, - .uop[0] = {.type = UOP_FLOAT, .throughput = 50, .latency = 50} +static const risc86_instruction_t vector_float_l_op = { + .nr_uops = 1, + .decode_type = DECODE_VECTOR, + .uop[0] = {.type = UOP_FLOAT, .throughput = 50, .latency = 50} }; -static const risc86_instruction_t vector_flde_op = -{ - .nr_uops = 2, - .decode_type = DECODE_VECTOR, - .uop[0] = {.type = UOP_FLOAD, .throughput = 1, .latency = 2}, - .uop[1] = {.type = UOP_FLOAD, .throughput = 1, .latency = 2}, - .uop[2] = {.type = UOP_FLOAT, .throughput = 2, .latency = 2} +static const risc86_instruction_t vector_flde_op = { + .nr_uops = 2, + .decode_type = DECODE_VECTOR, + .uop[0] = {.type = UOP_FLOAD, .throughput = 1, .latency = 2}, + .uop[1] = { .type = UOP_FLOAD, .throughput = 1, .latency = 2}, + .uop[2] = { .type = UOP_FLOAT, .throughput = 2, .latency = 2} }; -static const risc86_instruction_t vector_fste_op = -{ - .nr_uops = 3, - .decode_type = DECODE_VECTOR, - .uop[0] = {.type = UOP_FLOAT, .throughput = 2, .latency = 2}, - .uop[1] = {.type = UOP_FSTORE, .throughput = 1, .latency = 1}, - .uop[2] = {.type = UOP_FSTORE, .throughput = 1, .latency = 1} +static const risc86_instruction_t vector_fste_op = { + .nr_uops = 3, + .decode_type = DECODE_VECTOR, + .uop[0] = {.type = UOP_FLOAT, .throughput = 2, .latency = 2}, + .uop[1] = { .type = UOP_FSTORE, .throughput = 1, .latency = 1}, + .uop[2] = { .type = UOP_FSTORE, .throughput = 1, .latency = 1} }; -static const risc86_instruction_t vector_alu1_op = -{ - .nr_uops = 1, - .decode_type = DECODE_VECTOR, - .uop[0] = {.type = UOP_ALU, .throughput = 1, .latency = 1} +static const risc86_instruction_t vector_alu1_op = { + .nr_uops = 1, + .decode_type = DECODE_VECTOR, + .uop[0] = {.type = UOP_ALU, .throughput = 1, .latency = 1} }; -static const risc86_instruction_t vector_alu2_op = -{ - .nr_uops = 2, - .decode_type = DECODE_VECTOR, - .uop[0] = {.type = UOP_ALU, .throughput = 1, .latency = 1}, - .uop[1] = {.type = UOP_ALU, .throughput = 1, .latency = 1} +static const risc86_instruction_t vector_alu2_op = { + .nr_uops = 2, + .decode_type = DECODE_VECTOR, + .uop[0] = {.type = UOP_ALU, .throughput = 1, .latency = 1}, + .uop[1] = { .type = UOP_ALU, .throughput = 1, .latency = 1} }; -static const risc86_instruction_t vector_alu3_op = -{ - .nr_uops = 3, - .decode_type = DECODE_VECTOR, - .uop[0] = {.type = UOP_ALU, .throughput = 1, .latency = 1}, - .uop[1] = {.type = UOP_ALU, .throughput = 1, .latency = 1}, - .uop[2] = {.type = UOP_ALU, .throughput = 1, .latency = 1} +static const risc86_instruction_t vector_alu3_op = { + .nr_uops = 3, + .decode_type = DECODE_VECTOR, + .uop[0] = {.type = UOP_ALU, .throughput = 1, .latency = 1}, + .uop[1] = { .type = UOP_ALU, .throughput = 1, .latency = 1}, + .uop[2] = { .type = UOP_ALU, .throughput = 1, .latency = 1} }; -static const risc86_instruction_t vector_alu6_op = -{ - .nr_uops = 6, - .decode_type = DECODE_VECTOR, - .uop[0] = {.type = UOP_ALU, .throughput = 1, .latency = 1}, - .uop[1] = {.type = UOP_ALU, .throughput = 1, .latency = 1}, - .uop[2] = {.type = UOP_ALU, .throughput = 1, .latency = 1}, - .uop[3] = {.type = UOP_ALU, .throughput = 1, .latency = 1}, - .uop[4] = {.type = UOP_ALU, .throughput = 1, .latency = 1}, - .uop[5] = {.type = UOP_ALU, .throughput = 1, .latency = 1} +static const risc86_instruction_t vector_alu6_op = { + .nr_uops = 6, + .decode_type = DECODE_VECTOR, + .uop[0] = {.type = UOP_ALU, .throughput = 1, .latency = 1}, + .uop[1] = { .type = UOP_ALU, .throughput = 1, .latency = 1}, + .uop[2] = { .type = UOP_ALU, .throughput = 1, .latency = 1}, + .uop[3] = { .type = UOP_ALU, .throughput = 1, .latency = 1}, + .uop[4] = { .type = UOP_ALU, .throughput = 1, .latency = 1}, + .uop[5] = { .type = UOP_ALU, .throughput = 1, .latency = 1} }; -static const risc86_instruction_t vector_alux1_op = -{ - .nr_uops = 1, - .decode_type = DECODE_VECTOR, - .uop[0] = {.type = UOP_ALUX, .throughput = 1, .latency = 1} +static const risc86_instruction_t vector_alux1_op = { + .nr_uops = 1, + .decode_type = DECODE_VECTOR, + .uop[0] = {.type = UOP_ALUX, .throughput = 1, .latency = 1} }; -static const risc86_instruction_t vector_alux3_op = -{ - .nr_uops = 3, - .decode_type = DECODE_VECTOR, - .uop[0] = {.type = UOP_ALUX, .throughput = 1, .latency = 1}, - .uop[1] = {.type = UOP_ALUX, .throughput = 1, .latency = 1}, - .uop[2] = {.type = UOP_ALUX, .throughput = 1, .latency = 1} +static const risc86_instruction_t vector_alux3_op = { + .nr_uops = 3, + .decode_type = DECODE_VECTOR, + .uop[0] = {.type = UOP_ALUX, .throughput = 1, .latency = 1}, + .uop[1] = { .type = UOP_ALUX, .throughput = 1, .latency = 1}, + .uop[2] = { .type = UOP_ALUX, .throughput = 1, .latency = 1} }; -static const risc86_instruction_t vector_alux6_op = -{ - .nr_uops = 3, - .decode_type = DECODE_VECTOR, - .uop[0] = {.type = UOP_ALUX, .throughput = 1, .latency = 1}, - .uop[1] = {.type = UOP_ALUX, .throughput = 1, .latency = 1}, - .uop[2] = {.type = UOP_ALUX, .throughput = 1, .latency = 1}, - .uop[3] = {.type = UOP_ALUX, .throughput = 1, .latency = 1}, - .uop[4] = {.type = UOP_ALUX, .throughput = 1, .latency = 1}, - .uop[5] = {.type = UOP_ALUX, .throughput = 1, .latency = 1} +static const risc86_instruction_t vector_alux6_op = { + .nr_uops = 3, + .decode_type = DECODE_VECTOR, + .uop[0] = {.type = UOP_ALUX, .throughput = 1, .latency = 1}, + .uop[1] = { .type = UOP_ALUX, .throughput = 1, .latency = 1}, + .uop[2] = { .type = UOP_ALUX, .throughput = 1, .latency = 1}, + .uop[3] = { .type = UOP_ALUX, .throughput = 1, .latency = 1}, + .uop[4] = { .type = UOP_ALUX, .throughput = 1, .latency = 1}, + .uop[5] = { .type = UOP_ALUX, .throughput = 1, .latency = 1} }; -static const risc86_instruction_t vector_alu_store_op = -{ - .nr_uops = 3, - .decode_type = DECODE_VECTOR, - .uop[0] = {.type = UOP_LOAD, .throughput = 1, .latency = 2}, - .uop[1] = {.type = UOP_ALU, .throughput = 1, .latency = 1}, - .uop[2] = {.type = UOP_STORE, .throughput = 1, .latency = 1} +static const risc86_instruction_t vector_alu_store_op = { + .nr_uops = 3, + .decode_type = DECODE_VECTOR, + .uop[0] = {.type = UOP_LOAD, .throughput = 1, .latency = 2}, + .uop[1] = { .type = UOP_ALU, .throughput = 1, .latency = 1}, + .uop[2] = { .type = UOP_STORE, .throughput = 1, .latency = 1} }; -static const risc86_instruction_t vector_alux_store_op = -{ - .nr_uops = 3, - .decode_type = DECODE_VECTOR, - .uop[0] = {.type = UOP_LOAD, .throughput = 1, .latency = 2}, - .uop[1] = {.type = UOP_ALUX, .throughput = 1, .latency = 1}, - .uop[2] = {.type = UOP_STORE, .throughput = 1, .latency = 1} +static const risc86_instruction_t vector_alux_store_op = { + .nr_uops = 3, + .decode_type = DECODE_VECTOR, + .uop[0] = {.type = UOP_LOAD, .throughput = 1, .latency = 2}, + .uop[1] = { .type = UOP_ALUX, .throughput = 1, .latency = 1}, + .uop[2] = { .type = UOP_STORE, .throughput = 1, .latency = 1} }; -static const risc86_instruction_t vector_arpl_op = -{ - .nr_uops = 2, - .decode_type = DECODE_VECTOR, - .uop[0] = {.type = UOP_ALU, .throughput = 3, .latency = 3}, - .uop[1] = {.type = UOP_ALU, .throughput = 3, .latency = 3} +static const risc86_instruction_t vector_arpl_op = { + .nr_uops = 2, + .decode_type = DECODE_VECTOR, + .uop[0] = {.type = UOP_ALU, .throughput = 3, .latency = 3}, + .uop[1] = { .type = UOP_ALU, .throughput = 3, .latency = 3} }; -static const risc86_instruction_t vector_bound_op = -{ - .nr_uops = 4, - .decode_type = DECODE_VECTOR, - .uop[0] = {.type = UOP_LOAD, .throughput = 1, .latency = 2}, - .uop[1] = {.type = UOP_LOAD, .throughput = 1, .latency = 2}, - .uop[2] = {.type = UOP_ALU, .throughput = 1, .latency = 1}, - .uop[3] = {.type = UOP_ALU, .throughput = 1, .latency = 1} +static const risc86_instruction_t vector_bound_op = { + .nr_uops = 4, + .decode_type = DECODE_VECTOR, + .uop[0] = {.type = UOP_LOAD, .throughput = 1, .latency = 2}, + .uop[1] = { .type = UOP_LOAD, .throughput = 1, .latency = 2}, + .uop[2] = { .type = UOP_ALU, .throughput = 1, .latency = 1}, + .uop[3] = { .type = UOP_ALU, .throughput = 1, .latency = 1} }; -static const risc86_instruction_t vector_bsx_op = -{ - .nr_uops = 1, - .decode_type = DECODE_VECTOR, - .uop[0] = {.type = UOP_ALU, .throughput = 10, .latency = 10} +static const risc86_instruction_t vector_bsx_op = { + .nr_uops = 1, + .decode_type = DECODE_VECTOR, + .uop[0] = {.type = UOP_ALU, .throughput = 10, .latency = 10} }; -static const risc86_instruction_t vector_call_far_op = -{ - .nr_uops = 3, - .decode_type = DECODE_VECTOR, - .uop[0] = {.type = UOP_ALU, .throughput = 3, .latency = 3}, - .uop[1] = {.type = UOP_STORE, .throughput = 1, .latency = 1}, - .uop[2] = {.type = UOP_BRANCH, .throughput = 1, .latency = 1} +static const risc86_instruction_t vector_call_far_op = { + .nr_uops = 3, + .decode_type = DECODE_VECTOR, + .uop[0] = {.type = UOP_ALU, .throughput = 3, .latency = 3}, + .uop[1] = { .type = UOP_STORE, .throughput = 1, .latency = 1}, + .uop[2] = { .type = UOP_BRANCH, .throughput = 1, .latency = 1} }; -static const risc86_instruction_t vector_cli_sti_op = -{ - .nr_uops = 1, - .decode_type = DECODE_VECTOR, - .uop[0] = {.type = UOP_ALU, .throughput = 7, .latency = 7} +static const risc86_instruction_t vector_cli_sti_op = { + .nr_uops = 1, + .decode_type = DECODE_VECTOR, + .uop[0] = {.type = UOP_ALU, .throughput = 7, .latency = 7} }; -static const risc86_instruction_t vector_cmps_op = -{ - .nr_uops = 3, - .decode_type = DECODE_VECTOR, - .uop[0] = {.type = UOP_LOAD, .throughput = 1, .latency = 2}, - .uop[1] = {.type = UOP_ALU, .throughput = 1, .latency = 1}, - .uop[2] = {.type = UOP_ALU, .throughput = 1, .latency = 1} +static const risc86_instruction_t vector_cmps_op = { + .nr_uops = 3, + .decode_type = DECODE_VECTOR, + .uop[0] = {.type = UOP_LOAD, .throughput = 1, .latency = 2}, + .uop[1] = { .type = UOP_ALU, .throughput = 1, .latency = 1}, + .uop[2] = { .type = UOP_ALU, .throughput = 1, .latency = 1} }; -static const risc86_instruction_t vector_cmpsb_op = -{ - .nr_uops = 3, - .decode_type = DECODE_VECTOR, - .uop[0] = {.type = UOP_LOAD, .throughput = 1, .latency = 2}, - .uop[1] = {.type = UOP_ALUX, .throughput = 1, .latency = 1}, - .uop[2] = {.type = UOP_ALU, .throughput = 1, .latency = 1} +static const risc86_instruction_t vector_cmpsb_op = { + .nr_uops = 3, + .decode_type = DECODE_VECTOR, + .uop[0] = {.type = UOP_LOAD, .throughput = 1, .latency = 2}, + .uop[1] = { .type = UOP_ALUX, .throughput = 1, .latency = 1}, + .uop[2] = { .type = UOP_ALU, .throughput = 1, .latency = 1} }; -static const risc86_instruction_t vector_cmpxchg_op = -{ - .nr_uops = 3, - .decode_type = DECODE_VECTOR, - .uop[0] = {.type = UOP_LOAD, .throughput = 1, .latency = 2}, - .uop[1] = {.type = UOP_ALU, .throughput = 1, .latency = 1}, - .uop[2] = {.type = UOP_STORE, .throughput = 1, .latency = 1}, +static const risc86_instruction_t vector_cmpxchg_op = { + .nr_uops = 3, + .decode_type = DECODE_VECTOR, + .uop[0] = {.type = UOP_LOAD, .throughput = 1, .latency = 2}, + .uop[1] = { .type = UOP_ALU, .throughput = 1, .latency = 1}, + .uop[2] = { .type = UOP_STORE, .throughput = 1, .latency = 1}, }; -static const risc86_instruction_t vector_cmpxchg_b_op = -{ - .nr_uops = 3, - .decode_type = DECODE_VECTOR, - .uop[0] = {.type = UOP_LOAD, .throughput = 1, .latency = 2}, - .uop[1] = {.type = UOP_ALUX, .throughput = 1, .latency = 1}, - .uop[2] = {.type = UOP_STORE, .throughput = 1, .latency = 1}, +static const risc86_instruction_t vector_cmpxchg_b_op = { + .nr_uops = 3, + .decode_type = DECODE_VECTOR, + .uop[0] = {.type = UOP_LOAD, .throughput = 1, .latency = 2}, + .uop[1] = { .type = UOP_ALUX, .throughput = 1, .latency = 1}, + .uop[2] = { .type = UOP_STORE, .throughput = 1, .latency = 1}, }; -static const risc86_instruction_t vector_cpuid_op = -{ - .nr_uops = 1, - .decode_type = DECODE_VECTOR, - .uop[0] = {.type = UOP_ALU, .throughput = 22, .latency = 22} +static const risc86_instruction_t vector_cpuid_op = { + .nr_uops = 1, + .decode_type = DECODE_VECTOR, + .uop[0] = {.type = UOP_ALU, .throughput = 22, .latency = 22} }; -static const risc86_instruction_t vector_div16_op = -{ - .nr_uops = 1, - .decode_type = DECODE_VECTOR, - .uop[0] = {.type = UOP_ALUX, .throughput = 10, .latency = 10} +static const risc86_instruction_t vector_div16_op = { + .nr_uops = 1, + .decode_type = DECODE_VECTOR, + .uop[0] = {.type = UOP_ALUX, .throughput = 10, .latency = 10} }; -static const risc86_instruction_t vector_div16_mem_op = -{ - .nr_uops = 2, - .decode_type = DECODE_VECTOR, - .uop[0] = {.type = UOP_LOAD, .throughput = 1, .latency = 2}, - .uop[1] = {.type = UOP_ALUX, .throughput = 10, .latency = 10} +static const risc86_instruction_t vector_div16_mem_op = { + .nr_uops = 2, + .decode_type = DECODE_VECTOR, + .uop[0] = {.type = UOP_LOAD, .throughput = 1, .latency = 2 }, + .uop[1] = { .type = UOP_ALUX, .throughput = 10, .latency = 10} }; -static const risc86_instruction_t vector_div32_op = -{ - .nr_uops = 1, - .decode_type = DECODE_VECTOR, - .uop[0] = {.type = UOP_ALUX, .throughput = 18, .latency = 18} +static const risc86_instruction_t vector_div32_op = { + .nr_uops = 1, + .decode_type = DECODE_VECTOR, + .uop[0] = {.type = UOP_ALUX, .throughput = 18, .latency = 18} }; -static const risc86_instruction_t vector_div32_mem_op = -{ - .nr_uops = 2, - .decode_type = DECODE_VECTOR, - .uop[0] = {.type = UOP_LOAD, .throughput = 1, .latency = 2}, - .uop[1] = {.type = UOP_ALUX, .throughput = 18, .latency = 18} +static const risc86_instruction_t vector_div32_mem_op = { + .nr_uops = 2, + .decode_type = DECODE_VECTOR, + .uop[0] = {.type = UOP_LOAD, .throughput = 1, .latency = 2 }, + .uop[1] = { .type = UOP_ALUX, .throughput = 18, .latency = 18} }; -static const risc86_instruction_t vector_emms_op = -{ - .nr_uops = 1, - .decode_type = DECODE_VECTOR, - .uop[0] = {.type = UOP_ALU, .throughput = 25, .latency = 25} +static const risc86_instruction_t vector_emms_op = { + .nr_uops = 1, + .decode_type = DECODE_VECTOR, + .uop[0] = {.type = UOP_ALU, .throughput = 25, .latency = 25} }; -static const risc86_instruction_t vector_enter_op = -{ - .nr_uops = 2, - .decode_type = DECODE_VECTOR, - .uop[0] = {.type = UOP_STORE, .throughput = 1, .latency = 2}, - .uop[1] = {.type = UOP_ALU, .throughput = 10, .latency = 10} +static const risc86_instruction_t vector_enter_op = { + .nr_uops = 2, + .decode_type = DECODE_VECTOR, + .uop[0] = {.type = UOP_STORE, .throughput = 1, .latency = 2 }, + .uop[1] = { .type = UOP_ALU, .throughput = 10, .latency = 10} }; -static const risc86_instruction_t vector_femms_op = -{ - .nr_uops = 1, - .decode_type = DECODE_VECTOR, - .uop[0] = {.type = UOP_ALU, .throughput = 6, .latency = 6} +static const risc86_instruction_t vector_femms_op = { + .nr_uops = 1, + .decode_type = DECODE_VECTOR, + .uop[0] = {.type = UOP_ALU, .throughput = 6, .latency = 6} }; -static const risc86_instruction_t vector_in_op = -{ - .nr_uops = 1, - .decode_type = DECODE_VECTOR, - .uop[0] = {.type = UOP_LOAD, .throughput = 10, .latency = 11} +static const risc86_instruction_t vector_in_op = { + .nr_uops = 1, + .decode_type = DECODE_VECTOR, + .uop[0] = {.type = UOP_LOAD, .throughput = 10, .latency = 11} }; -static const risc86_instruction_t vector_ins_op = -{ - .nr_uops = 3, - .decode_type = DECODE_VECTOR, - .uop[0] = {.type = UOP_LOAD, .throughput = 10, .latency = 11}, - .uop[1] = {.type = UOP_STORE, .throughput = 1, .latency = 1}, - .uop[2] = {.type = UOP_ALU, .throughput = 1, .latency = 1} +static const risc86_instruction_t vector_ins_op = { + .nr_uops = 3, + .decode_type = DECODE_VECTOR, + .uop[0] = {.type = UOP_LOAD, .throughput = 10, .latency = 11}, + .uop[1] = { .type = UOP_STORE, .throughput = 1, .latency = 1 }, + .uop[2] = { .type = UOP_ALU, .throughput = 1, .latency = 1 } }; -static const risc86_instruction_t vector_int_op = -{ - .nr_uops = 5, - .decode_type = DECODE_VECTOR, - .uop[0] = {.type = UOP_ALU, .throughput = 20, .latency = 20}, - .uop[1] = {.type = UOP_STORE, .throughput = 1, .latency = 1}, - .uop[2] = {.type = UOP_STORE, .throughput = 1, .latency = 1}, - .uop[3] = {.type = UOP_STORE, .throughput = 1, .latency = 1}, - .uop[4] = {.type = UOP_BRANCH, .throughput = 1, .latency = 1} +static const risc86_instruction_t vector_int_op = { + .nr_uops = 5, + .decode_type = DECODE_VECTOR, + .uop[0] = {.type = UOP_ALU, .throughput = 20, .latency = 20}, + .uop[1] = { .type = UOP_STORE, .throughput = 1, .latency = 1 }, + .uop[2] = { .type = UOP_STORE, .throughput = 1, .latency = 1 }, + .uop[3] = { .type = UOP_STORE, .throughput = 1, .latency = 1 }, + .uop[4] = { .type = UOP_BRANCH, .throughput = 1, .latency = 1 } }; -static const risc86_instruction_t vector_iret_op = -{ - .nr_uops = 5, - .decode_type = DECODE_VECTOR, - .uop[0] = {.type = UOP_LOAD, .throughput = 1, .latency = 2}, - .uop[1] = {.type = UOP_LOAD, .throughput = 1, .latency = 2}, - .uop[2] = {.type = UOP_LOAD, .throughput = 1, .latency = 2}, - .uop[3] = {.type = UOP_ALU, .throughput = 20, .latency = 20}, - .uop[4] = {.type = UOP_BRANCH, .throughput = 1, .latency = 1} +static const risc86_instruction_t vector_iret_op = { + .nr_uops = 5, + .decode_type = DECODE_VECTOR, + .uop[0] = {.type = UOP_LOAD, .throughput = 1, .latency = 2 }, + .uop[1] = { .type = UOP_LOAD, .throughput = 1, .latency = 2 }, + .uop[2] = { .type = UOP_LOAD, .throughput = 1, .latency = 2 }, + .uop[3] = { .type = UOP_ALU, .throughput = 20, .latency = 20}, + .uop[4] = { .type = UOP_BRANCH, .throughput = 1, .latency = 1 } }; -static const risc86_instruction_t vector_invd_op = -{ - .nr_uops = 1, - .decode_type = DECODE_VECTOR, - .uop[0] = {.type = UOP_ALU, .throughput = 1000, .latency = 1000} +static const risc86_instruction_t vector_invd_op = { + .nr_uops = 1, + .decode_type = DECODE_VECTOR, + .uop[0] = {.type = UOP_ALU, .throughput = 1000, .latency = 1000} }; -static const risc86_instruction_t vector_jmp_far_op = -{ - .nr_uops = 2, - .decode_type = DECODE_VECTOR, - .uop[0] = {.type = UOP_ALU, .throughput = 3, .latency = 3}, - .uop[1] = {.type = UOP_BRANCH, .throughput = 1, .latency = 1} +static const risc86_instruction_t vector_jmp_far_op = { + .nr_uops = 2, + .decode_type = DECODE_VECTOR, + .uop[0] = {.type = UOP_ALU, .throughput = 3, .latency = 3}, + .uop[1] = { .type = UOP_BRANCH, .throughput = 1, .latency = 1} }; -static const risc86_instruction_t vector_load_alu_op = -{ - .nr_uops = 2, - .decode_type = DECODE_VECTOR, - .uop[0] = {.type = UOP_LOAD, .throughput = 1, .latency = 2}, - .uop[1] = {.type = UOP_ALU, .throughput = 1, .latency = 1} +static const risc86_instruction_t vector_load_alu_op = { + .nr_uops = 2, + .decode_type = DECODE_VECTOR, + .uop[0] = {.type = UOP_LOAD, .throughput = 1, .latency = 2}, + .uop[1] = { .type = UOP_ALU, .throughput = 1, .latency = 1} }; -static const risc86_instruction_t vector_load_alux_op = -{ - .nr_uops = 2, - .decode_type = DECODE_VECTOR, - .uop[0] = {.type = UOP_LOAD, .throughput = 1, .latency = 2}, - .uop[1] = {.type = UOP_ALUX, .throughput = 1, .latency = 1} +static const risc86_instruction_t vector_load_alux_op = { + .nr_uops = 2, + .decode_type = DECODE_VECTOR, + .uop[0] = {.type = UOP_LOAD, .throughput = 1, .latency = 2}, + .uop[1] = { .type = UOP_ALUX, .throughput = 1, .latency = 1} }; -static const risc86_instruction_t vector_loop_op = -{ - .nr_uops = 2, - .decode_type = DECODE_VECTOR, - .uop[0] = {.type = UOP_ALU, .throughput = 1, .latency = 1}, - .uop[1] = {.type = UOP_BRANCH, .throughput = 1, .latency = 1} +static const risc86_instruction_t vector_loop_op = { + .nr_uops = 2, + .decode_type = DECODE_VECTOR, + .uop[0] = {.type = UOP_ALU, .throughput = 1, .latency = 1}, + .uop[1] = { .type = UOP_BRANCH, .throughput = 1, .latency = 1} }; -static const risc86_instruction_t vector_lss_op = -{ - .nr_uops = 3, - .decode_type = DECODE_VECTOR, - .uop[0] = {.type = UOP_LOAD, .throughput = 1, .latency = 2}, - .uop[1] = {.type = UOP_LOAD, .throughput = 1, .latency = 2}, - .uop[2] = {.type = UOP_ALU, .throughput = 3, .latency = 3} +static const risc86_instruction_t vector_lss_op = { + .nr_uops = 3, + .decode_type = DECODE_VECTOR, + .uop[0] = {.type = UOP_LOAD, .throughput = 1, .latency = 2}, + .uop[1] = { .type = UOP_LOAD, .throughput = 1, .latency = 2}, + .uop[2] = { .type = UOP_ALU, .throughput = 3, .latency = 3} }; -static const risc86_instruction_t vector_mov_mem_seg_op = -{ - .nr_uops = 2, - .decode_type = DECODE_VECTOR, - .uop[0] = {.type = UOP_LOAD, .throughput = 1, .latency = 2}, - .uop[1] = {.type = UOP_STORE, .throughput = 1, .latency = 1} +static const risc86_instruction_t vector_mov_mem_seg_op = { + .nr_uops = 2, + .decode_type = DECODE_VECTOR, + .uop[0] = {.type = UOP_LOAD, .throughput = 1, .latency = 2}, + .uop[1] = { .type = UOP_STORE, .throughput = 1, .latency = 1} }; -static const risc86_instruction_t vector_mov_seg_mem_op = -{ - .nr_uops = 2, - .decode_type = DECODE_VECTOR, - .uop[0] = {.type = UOP_LOAD, .throughput = 1, .latency = 2}, - .uop[1] = {.type = UOP_ALU, .throughput = 3, .latency = 3} +static const risc86_instruction_t vector_mov_seg_mem_op = { + .nr_uops = 2, + .decode_type = DECODE_VECTOR, + .uop[0] = {.type = UOP_LOAD, .throughput = 1, .latency = 2}, + .uop[1] = { .type = UOP_ALU, .throughput = 3, .latency = 3} }; -static const risc86_instruction_t vector_mov_seg_reg_op = -{ - .nr_uops = 1, - .decode_type = DECODE_VECTOR, - .uop[0] = {.type = UOP_ALU, .throughput = 3, .latency = 3} +static const risc86_instruction_t vector_mov_seg_reg_op = { + .nr_uops = 1, + .decode_type = DECODE_VECTOR, + .uop[0] = {.type = UOP_ALU, .throughput = 3, .latency = 3} }; -static const risc86_instruction_t vector_mul_op = -{ - .nr_uops = 2, - .decode_type = DECODE_VECTOR, - .uop[0] = {.type = UOP_ALUX, .throughput = 1, .latency = 1}, - .uop[1] = {.type = UOP_ALUX, .throughput = 1, .latency = 1} +static const risc86_instruction_t vector_mul_op = { + .nr_uops = 2, + .decode_type = DECODE_VECTOR, + .uop[0] = {.type = UOP_ALUX, .throughput = 1, .latency = 1}, + .uop[1] = { .type = UOP_ALUX, .throughput = 1, .latency = 1} }; -static const risc86_instruction_t vector_mul_mem_op = -{ - .nr_uops = 3, - .decode_type = DECODE_VECTOR, - .uop[0] = {.type = UOP_LOAD, .throughput = 1, .latency = 2}, - .uop[1] = {.type = UOP_ALUX, .throughput = 1, .latency = 1}, - .uop[2] = {.type = UOP_ALUX, .throughput = 1, .latency = 1} +static const risc86_instruction_t vector_mul_mem_op = { + .nr_uops = 3, + .decode_type = DECODE_VECTOR, + .uop[0] = {.type = UOP_LOAD, .throughput = 1, .latency = 2}, + .uop[1] = { .type = UOP_ALUX, .throughput = 1, .latency = 1}, + .uop[2] = { .type = UOP_ALUX, .throughput = 1, .latency = 1} }; -static const risc86_instruction_t vector_mul64_op = -{ - .nr_uops = 3, - .decode_type = DECODE_VECTOR, - .uop[0] = {.type = UOP_ALUX, .throughput = 1, .latency = 1}, - .uop[1] = {.type = UOP_ALUX, .throughput = 1, .latency = 1}, - .uop[2] = {.type = UOP_ALUX, .throughput = 1, .latency = 1} +static const risc86_instruction_t vector_mul64_op = { + .nr_uops = 3, + .decode_type = DECODE_VECTOR, + .uop[0] = {.type = UOP_ALUX, .throughput = 1, .latency = 1}, + .uop[1] = { .type = UOP_ALUX, .throughput = 1, .latency = 1}, + .uop[2] = { .type = UOP_ALUX, .throughput = 1, .latency = 1} }; -static const risc86_instruction_t vector_mul64_mem_op = -{ - .nr_uops = 4, - .decode_type = DECODE_VECTOR, - .uop[0] = {.type = UOP_LOAD, .throughput = 1, .latency = 2}, - .uop[1] = {.type = UOP_ALUX, .throughput = 1, .latency = 1}, - .uop[2] = {.type = UOP_ALUX, .throughput = 1, .latency = 1}, - .uop[3] = {.type = UOP_ALUX, .throughput = 1, .latency = 1} +static const risc86_instruction_t vector_mul64_mem_op = { + .nr_uops = 4, + .decode_type = DECODE_VECTOR, + .uop[0] = {.type = UOP_LOAD, .throughput = 1, .latency = 2}, + .uop[1] = { .type = UOP_ALUX, .throughput = 1, .latency = 1}, + .uop[2] = { .type = UOP_ALUX, .throughput = 1, .latency = 1}, + .uop[3] = { .type = UOP_ALUX, .throughput = 1, .latency = 1} }; -static const risc86_instruction_t vector_out_op = -{ - .nr_uops = 1, - .decode_type = DECODE_VECTOR, - .uop[0] = {.type = UOP_STORE, .throughput = 10, .latency = 10} +static const risc86_instruction_t vector_out_op = { + .nr_uops = 1, + .decode_type = DECODE_VECTOR, + .uop[0] = {.type = UOP_STORE, .throughput = 10, .latency = 10} }; -static const risc86_instruction_t vector_outs_op = -{ - .nr_uops = 3, - .decode_type = DECODE_VECTOR, - .uop[0] = {.type = UOP_LOAD, .throughput = 1, .latency = 1}, - .uop[1] = {.type = UOP_STORE, .throughput = 10, .latency = 10}, - .uop[2] = {.type = UOP_ALU, .throughput = 1, .latency = 1} +static const risc86_instruction_t vector_outs_op = { + .nr_uops = 3, + .decode_type = DECODE_VECTOR, + .uop[0] = {.type = UOP_LOAD, .throughput = 1, .latency = 1 }, + .uop[1] = { .type = UOP_STORE, .throughput = 10, .latency = 10}, + .uop[2] = { .type = UOP_ALU, .throughput = 1, .latency = 1 } }; -static const risc86_instruction_t vector_pusha_op = -{ - .nr_uops = 8, - .decode_type = DECODE_VECTOR, - .uop[0] = {.type = UOP_STORE, .throughput = 1, .latency = 1}, - .uop[1] = {.type = UOP_STORE, .throughput = 1, .latency = 1}, - .uop[2] = {.type = UOP_STORE, .throughput = 1, .latency = 1}, - .uop[3] = {.type = UOP_STORE, .throughput = 1, .latency = 1}, - .uop[4] = {.type = UOP_STORE, .throughput = 1, .latency = 1}, - .uop[5] = {.type = UOP_STORE, .throughput = 1, .latency = 1}, - .uop[6] = {.type = UOP_STORE, .throughput = 1, .latency = 1}, - .uop[7] = {.type = UOP_STORE, .throughput = 1, .latency = 1} +static const risc86_instruction_t vector_pusha_op = { + .nr_uops = 8, + .decode_type = DECODE_VECTOR, + .uop[0] = {.type = UOP_STORE, .throughput = 1, .latency = 1}, + .uop[1] = { .type = UOP_STORE, .throughput = 1, .latency = 1}, + .uop[2] = { .type = UOP_STORE, .throughput = 1, .latency = 1}, + .uop[3] = { .type = UOP_STORE, .throughput = 1, .latency = 1}, + .uop[4] = { .type = UOP_STORE, .throughput = 1, .latency = 1}, + .uop[5] = { .type = UOP_STORE, .throughput = 1, .latency = 1}, + .uop[6] = { .type = UOP_STORE, .throughput = 1, .latency = 1}, + .uop[7] = { .type = UOP_STORE, .throughput = 1, .latency = 1} }; -static const risc86_instruction_t vector_popa_op = -{ - .nr_uops = 8, - .decode_type = DECODE_VECTOR, - .uop[0] = {.type = UOP_LOAD, .throughput = 1, .latency = 1}, - .uop[1] = {.type = UOP_LOAD, .throughput = 1, .latency = 1}, - .uop[2] = {.type = UOP_LOAD, .throughput = 1, .latency = 1}, - .uop[3] = {.type = UOP_LOAD, .throughput = 1, .latency = 1}, - .uop[4] = {.type = UOP_LOAD, .throughput = 1, .latency = 1}, - .uop[5] = {.type = UOP_LOAD, .throughput = 1, .latency = 1}, - .uop[6] = {.type = UOP_LOAD, .throughput = 1, .latency = 1}, - .uop[7] = {.type = UOP_LOAD, .throughput = 1, .latency = 1} +static const risc86_instruction_t vector_popa_op = { + .nr_uops = 8, + .decode_type = DECODE_VECTOR, + .uop[0] = {.type = UOP_LOAD, .throughput = 1, .latency = 1}, + .uop[1] = { .type = UOP_LOAD, .throughput = 1, .latency = 1}, + .uop[2] = { .type = UOP_LOAD, .throughput = 1, .latency = 1}, + .uop[3] = { .type = UOP_LOAD, .throughput = 1, .latency = 1}, + .uop[4] = { .type = UOP_LOAD, .throughput = 1, .latency = 1}, + .uop[5] = { .type = UOP_LOAD, .throughput = 1, .latency = 1}, + .uop[6] = { .type = UOP_LOAD, .throughput = 1, .latency = 1}, + .uop[7] = { .type = UOP_LOAD, .throughput = 1, .latency = 1} }; -static const risc86_instruction_t vector_popf_op = -{ - .nr_uops = 2, - .decode_type = DECODE_VECTOR, - .uop[0] = {.type = UOP_LOAD, .throughput = 1, .latency = 2}, - .uop[1] = {.type = UOP_ALUX, .throughput = 17, .latency = 17} +static const risc86_instruction_t vector_popf_op = { + .nr_uops = 2, + .decode_type = DECODE_VECTOR, + .uop[0] = {.type = UOP_LOAD, .throughput = 1, .latency = 2 }, + .uop[1] = { .type = UOP_ALUX, .throughput = 17, .latency = 17} }; -static const risc86_instruction_t vector_push_mem_op = -{ - .nr_uops = 1, - .decode_type = DECODE_VECTOR, - .uop[0] = {.type = UOP_STORE, .throughput = 1, .latency = 1} +static const risc86_instruction_t vector_push_mem_op = { + .nr_uops = 1, + .decode_type = DECODE_VECTOR, + .uop[0] = {.type = UOP_STORE, .throughput = 1, .latency = 1} }; -static const risc86_instruction_t vector_pushf_op = -{ - .nr_uops = 2, - .decode_type = DECODE_VECTOR, - .uop[0] = {.type = UOP_ALUX, .throughput = 1, .latency = 1}, - .uop[1] = {.type = UOP_STORE, .throughput = 1, .latency = 1} +static const risc86_instruction_t vector_pushf_op = { + .nr_uops = 2, + .decode_type = DECODE_VECTOR, + .uop[0] = {.type = UOP_ALUX, .throughput = 1, .latency = 1}, + .uop[1] = { .type = UOP_STORE, .throughput = 1, .latency = 1} }; -static const risc86_instruction_t vector_ret_op = -{ - .nr_uops = 2, - .decode_type = DECODE_VECTOR, - .uop[0] = {.type = UOP_LOAD, .throughput = 1, .latency = 2}, - .uop[1] = {.type = UOP_BRANCH, .throughput = 1, .latency = 1} +static const risc86_instruction_t vector_ret_op = { + .nr_uops = 2, + .decode_type = DECODE_VECTOR, + .uop[0] = {.type = UOP_LOAD, .throughput = 1, .latency = 2}, + .uop[1] = { .type = UOP_BRANCH, .throughput = 1, .latency = 1} }; -static const risc86_instruction_t vector_retf_op = -{ - .nr_uops = 3, - .decode_type = DECODE_VECTOR, - .uop[0] = {.type = UOP_LOAD, .throughput = 1, .latency = 2}, - .uop[1] = {.type = UOP_ALU, .throughput = 3, .latency = 3}, - .uop[2] = {.type = UOP_BRANCH, .throughput = 1, .latency = 1} +static const risc86_instruction_t vector_retf_op = { + .nr_uops = 3, + .decode_type = DECODE_VECTOR, + .uop[0] = {.type = UOP_LOAD, .throughput = 1, .latency = 2}, + .uop[1] = { .type = UOP_ALU, .throughput = 3, .latency = 3}, + .uop[2] = { .type = UOP_BRANCH, .throughput = 1, .latency = 1} }; -static const risc86_instruction_t vector_scas_op = -{ - .nr_uops = 2, - .decode_type = DECODE_VECTOR, - .uop[0] = {.type = UOP_LOAD, .throughput = 1, .latency = 2}, - .uop[1] = {.type = UOP_ALU, .throughput = 1, .latency = 1} +static const risc86_instruction_t vector_scas_op = { + .nr_uops = 2, + .decode_type = DECODE_VECTOR, + .uop[0] = {.type = UOP_LOAD, .throughput = 1, .latency = 2}, + .uop[1] = { .type = UOP_ALU, .throughput = 1, .latency = 1} }; -static const risc86_instruction_t vector_scasb_op = -{ - .nr_uops = 2, - .decode_type = DECODE_VECTOR, - .uop[0] = {.type = UOP_LOAD, .throughput = 1, .latency = 2}, - .uop[1] = {.type = UOP_ALU, .throughput = 1, .latency = 1} +static const risc86_instruction_t vector_scasb_op = { + .nr_uops = 2, + .decode_type = DECODE_VECTOR, + .uop[0] = {.type = UOP_LOAD, .throughput = 1, .latency = 2}, + .uop[1] = { .type = UOP_ALU, .throughput = 1, .latency = 1} }; -static const risc86_instruction_t vector_setcc_mem_op = -{ - .nr_uops = 3, - .decode_type = DECODE_VECTOR, - .uop[0] = {.type = UOP_ALUX, .throughput = 1, .latency = 1}, - .uop[1] = {.type = UOP_ALUX, .throughput = 1, .latency = 1}, - .uop[2] = {.type = UOP_FSTORE, .throughput = 1, .latency = 1} +static const risc86_instruction_t vector_setcc_mem_op = { + .nr_uops = 3, + .decode_type = DECODE_VECTOR, + .uop[0] = {.type = UOP_ALUX, .throughput = 1, .latency = 1}, + .uop[1] = { .type = UOP_ALUX, .throughput = 1, .latency = 1}, + .uop[2] = { .type = UOP_FSTORE, .throughput = 1, .latency = 1} }; -static const risc86_instruction_t vector_setcc_reg_op = -{ - .nr_uops = 3, - .decode_type = DECODE_VECTOR, - .uop[0] = {.type = UOP_ALUX, .throughput = 1, .latency = 1}, - .uop[1] = {.type = UOP_ALUX, .throughput = 1, .latency = 1}, - .uop[2] = {.type = UOP_ALU, .throughput = 1, .latency = 1} +static const risc86_instruction_t vector_setcc_reg_op = { + .nr_uops = 3, + .decode_type = DECODE_VECTOR, + .uop[0] = {.type = UOP_ALUX, .throughput = 1, .latency = 1}, + .uop[1] = { .type = UOP_ALUX, .throughput = 1, .latency = 1}, + .uop[2] = { .type = UOP_ALU, .throughput = 1, .latency = 1} }; -static const risc86_instruction_t vector_test_mem_op = -{ - .nr_uops = 2, - .decode_type = DECODE_VECTOR, - .uop[0] = {.type = UOP_LOAD, .throughput = 1, .latency = 2}, - .uop[1] = {.type = UOP_ALU, .throughput = 1, .latency = 1} +static const risc86_instruction_t vector_test_mem_op = { + .nr_uops = 2, + .decode_type = DECODE_VECTOR, + .uop[0] = {.type = UOP_LOAD, .throughput = 1, .latency = 2}, + .uop[1] = { .type = UOP_ALU, .throughput = 1, .latency = 1} }; -static const risc86_instruction_t vector_test_mem_b_op = -{ - .nr_uops = 2, - .decode_type = DECODE_VECTOR, - .uop[0] = {.type = UOP_LOAD, .throughput = 1, .latency = 2}, - .uop[1] = {.type = UOP_ALUX, .throughput = 1, .latency = 1} +static const risc86_instruction_t vector_test_mem_b_op = { + .nr_uops = 2, + .decode_type = DECODE_VECTOR, + .uop[0] = {.type = UOP_LOAD, .throughput = 1, .latency = 2}, + .uop[1] = { .type = UOP_ALUX, .throughput = 1, .latency = 1} }; -static const risc86_instruction_t vector_xchg_mem_op = -{ - .nr_uops = 3, - .decode_type = DECODE_VECTOR, - .uop[0] = {.type = UOP_LOAD, .throughput = 1, .latency = 1}, - .uop[1] = {.type = UOP_STORE, .throughput = 1, .latency = 1}, - .uop[2] = {.type = UOP_ALU, .throughput = 1, .latency = 1} +static const risc86_instruction_t vector_xchg_mem_op = { + .nr_uops = 3, + .decode_type = DECODE_VECTOR, + .uop[0] = {.type = UOP_LOAD, .throughput = 1, .latency = 1}, + .uop[1] = { .type = UOP_STORE, .throughput = 1, .latency = 1}, + .uop[2] = { .type = UOP_ALU, .throughput = 1, .latency = 1} }; -static const risc86_instruction_t vector_xlat_op = -{ - .nr_uops = 2, - .decode_type = DECODE_VECTOR, - .uop[0] = {.type = UOP_ALU, .throughput = 1, .latency = 1}, - .uop[1] = {.type = UOP_LOAD, .throughput = 1, .latency = 2} +static const risc86_instruction_t vector_xlat_op = { + .nr_uops = 2, + .decode_type = DECODE_VECTOR, + .uop[0] = {.type = UOP_ALU, .throughput = 1, .latency = 1}, + .uop[1] = { .type = UOP_LOAD, .throughput = 1, .latency = 2} }; -static const risc86_instruction_t vector_wbinvd_op = -{ - .nr_uops = 1, - .decode_type = DECODE_VECTOR, - .uop[0] = {.type = UOP_ALU, .throughput = 10000, .latency = 10000} +static const risc86_instruction_t vector_wbinvd_op = { + .nr_uops = 1, + .decode_type = DECODE_VECTOR, + .uop[0] = {.type = UOP_ALU, .throughput = 10000, .latency = 10000} }; #define INVALID NULL -static const risc86_instruction_t *opcode_timings[256] = -{ +static const risc86_instruction_t *opcode_timings[256] = { + // clang-format off /* ADD ADD ADD ADD*/ /*00*/ &alux_store_op, &alu_store_op, &load_alux_op, &load_alu_op, /* ADD ADD PUSH ES POP ES*/ @@ -1007,10 +892,11 @@ static const risc86_instruction_t *opcode_timings[256] = &vector_alu1_op, &vector_alu1_op, &vector_cli_sti_op, &vector_cli_sti_op, /* CLD STD INCDEC*/ &vector_alu1_op, &vector_alu1_op, &alux_store_op, INVALID + // clang-format on }; -static const risc86_instruction_t *opcode_timings_mod3[256] = -{ +static const risc86_instruction_t *opcode_timings_mod3[256] = { + // clang-format off /* ADD ADD ADD ADD*/ /*00*/ &alux_op, &alu_op, &alux_op, &alu_op, /* ADD ADD PUSH ES POP ES*/ @@ -1143,10 +1029,11 @@ static const risc86_instruction_t *opcode_timings_mod3[256] = &vector_alu1_op, &vector_alu1_op, &vector_cli_sti_op, &vector_cli_sti_op, /* CLD STD INCDEC*/ &vector_alu1_op, &vector_alu1_op, &vector_alux1_op, INVALID + // clang-format on }; -static const risc86_instruction_t *opcode_timings_0f[256] = -{ +static const risc86_instruction_t *opcode_timings_0f[256] = { + // clang-format off /*00*/ &vector_alu6_op, &vector_alu6_op, &vector_alu6_op, &vector_alu6_op, INVALID, &vector_alu6_op, &vector_alu6_op, INVALID, &vector_invd_op, &vector_wbinvd_op, INVALID, INVALID, @@ -1226,9 +1113,10 @@ static const risc86_instruction_t *opcode_timings_0f[256] = INVALID, &pmul_mem_op, INVALID, INVALID, &load_mmx_op, &load_mmx_op, &load_mmx_op, INVALID, &load_mmx_op, &load_mmx_op, &load_mmx_op, INVALID, + // clang-format on }; -static const risc86_instruction_t *opcode_timings_0f_mod3[256] = -{ +static const risc86_instruction_t *opcode_timings_0f_mod3[256] = { + // clang-format off /*00*/ &vector_alu6_op, &vector_alu6_op, &vector_alu6_op, &vector_alu6_op, INVALID, &vector_alu6_op, &vector_alu6_op, INVALID, &vector_invd_op, &vector_wbinvd_op, INVALID, INVALID, @@ -1308,10 +1196,11 @@ static const risc86_instruction_t *opcode_timings_0f_mod3[256] = INVALID, &pmul_op, INVALID, INVALID, &mmx_op, &mmx_op, &mmx_op, INVALID, &mmx_op, &mmx_op, &mmx_op, INVALID, + // clang-format on }; -static const risc86_instruction_t *opcode_timings_0f0f[256] = -{ +static const risc86_instruction_t *opcode_timings_0f0f[256] = { + // clang-format off /*00*/ INVALID, INVALID, INVALID, INVALID, INVALID, INVALID, INVALID, INVALID, INVALID, INVALID, INVALID, INVALID, @@ -1391,10 +1280,10 @@ static const risc86_instruction_t *opcode_timings_0f0f[256] = INVALID, INVALID, INVALID, INVALID, INVALID, INVALID, INVALID, INVALID, INVALID, INVALID, INVALID, INVALID, - + // clang-format on }; -static const risc86_instruction_t *opcode_timings_0f0f_mod3[256] = -{ +static const risc86_instruction_t *opcode_timings_0f0f_mod3[256] = { + // clang-format off /*00*/ INVALID, INVALID, INVALID, INVALID, INVALID, INVALID, INVALID, INVALID, INVALID, INVALID, INVALID, INVALID, @@ -1474,118 +1363,135 @@ static const risc86_instruction_t *opcode_timings_0f0f_mod3[256] = INVALID, INVALID, INVALID, INVALID, INVALID, INVALID, INVALID, INVALID, INVALID, INVALID, INVALID, INVALID, - + // clang-format on }; -static const risc86_instruction_t *opcode_timings_shift[8] = -{ +static const risc86_instruction_t *opcode_timings_shift[8] = { + // clang-format off &vector_alu_store_op, &vector_alu_store_op, &vector_alu_store_op, &vector_alu_store_op, &vector_alu_store_op, &vector_alu_store_op, &vector_alu_store_op, &vector_alu_store_op + // clang-format on }; -static const risc86_instruction_t *opcode_timings_shift_b[8] = -{ +static const risc86_instruction_t *opcode_timings_shift_b[8] = { + // clang-format off &vector_alux_store_op, &vector_alux_store_op, &vector_alux_store_op, &vector_alux_store_op, &vector_alux_store_op, &vector_alux_store_op, &vector_alux_store_op, &vector_alux_store_op + // clang-format on }; -static const risc86_instruction_t *opcode_timings_shift_mod3[8] = -{ +static const risc86_instruction_t *opcode_timings_shift_mod3[8] = { + // clang-format off &vector_alu1_op, &vector_alu1_op, &vector_alu1_op, &vector_alu1_op, &alu_op, &alu_op, &alu_op, &alu_op + // clang-format on }; -static const risc86_instruction_t *opcode_timings_shift_b_mod3[8] = -{ +static const risc86_instruction_t *opcode_timings_shift_b_mod3[8] = { + // clang-format off &vector_alux1_op, &vector_alux1_op, &vector_alux1_op, &vector_alux1_op, &alux_op, &alux_op, &alux_op, &alux_op + // clang-format on }; -static const risc86_instruction_t *opcode_timings_80[8] = -{ +static const risc86_instruction_t *opcode_timings_80[8] = { + // clang-format off &alux_store_op, &alux_store_op, &vector_alux_store_op, &vector_alux_store_op, &alux_store_op, &alux_store_op, &alux_store_op, &alux_store_op, + // clang-format on }; -static const risc86_instruction_t *opcode_timings_80_mod3[8] = -{ +static const risc86_instruction_t *opcode_timings_80_mod3[8] = { + // clang-format off &alux_op, &alux_op, &alux_store_op, &alux_store_op, &alux_op, &alux_op, &alux_op, &alux_op, + // clang-format on }; -static const risc86_instruction_t *opcode_timings_8x[8] = -{ +static const risc86_instruction_t *opcode_timings_8x[8] = { + // clang-format off &alu_store_op, &alu_store_op, &vector_alu_store_op, &vector_alu_store_op, &alu_store_op, &alu_store_op, &alu_store_op, &alu_store_op, + // clang-format on }; -static const risc86_instruction_t *opcode_timings_8x_mod3[8] = -{ +static const risc86_instruction_t *opcode_timings_8x_mod3[8] = { + // clang-format off &alu_op, &alu_op, &alu_store_op, &alu_store_op, &alu_op, &alu_op, &alu_op, &alu_op, + // clang-format on }; -static const risc86_instruction_t *opcode_timings_f6[8] = -{ +static const risc86_instruction_t *opcode_timings_f6[8] = { + // clang-format off /* TST NOT NEG*/ &test_mem_imm_b_op, INVALID, &vector_alux_store_op, &vector_alux_store_op, /* MUL IMUL DIV IDIV*/ &vector_mul_mem_op, &vector_mul_mem_op, &vector_div16_mem_op, &vector_div16_mem_op, + // clang-format on }; -static const risc86_instruction_t *opcode_timings_f6_mod3[8] = -{ +static const risc86_instruction_t *opcode_timings_f6_mod3[8] = { + // clang-format off /* TST NOT NEG*/ &test_reg_b_op, INVALID, &alux_op, &alux_op, /* MUL IMUL DIV IDIV*/ &vector_mul_op, &vector_mul_op, &vector_div16_op, &vector_div16_op, + // clang-format on }; -static const risc86_instruction_t *opcode_timings_f7[8] = -{ +static const risc86_instruction_t *opcode_timings_f7[8] = { + // clang-format off /* TST NOT NEG*/ &test_mem_imm_op, INVALID, &vector_alu_store_op, &vector_alu_store_op, /* MUL IMUL DIV IDIV*/ &vector_mul64_mem_op, &vector_mul64_mem_op, &vector_div32_mem_op, &vector_div32_mem_op, + // clang-format on }; -static const risc86_instruction_t *opcode_timings_f7_mod3[8] = -{ +static const risc86_instruction_t *opcode_timings_f7_mod3[8] = { + // clang-format off /* TST NOT NEG*/ &test_reg_op, INVALID, &alu_op, &alu_op, /* MUL IMUL DIV IDIV*/ &vector_mul64_op, &vector_mul64_op, &vector_div32_op, &vector_div32_op, + // clang-format on }; -static const risc86_instruction_t *opcode_timings_ff[8] = -{ +static const risc86_instruction_t *opcode_timings_ff[8] = { + // clang-format off /* INC DEC CALL CALL far*/ &alu_store_op, &alu_store_op, &store_op, &vector_call_far_op, /* JMP JMP far PUSH*/ &branch_op, &vector_jmp_far_op, &push_mem_op, INVALID + // clang-format on }; -static const risc86_instruction_t *opcode_timings_ff_mod3[8] = -{ +static const risc86_instruction_t *opcode_timings_ff_mod3[8] = { + // clang-format off /* INC DEC CALL CALL far*/ &vector_alu1_op, &vector_alu1_op, &store_op, &vector_call_far_op, /* JMP JMP far PUSH*/ &branch_op, &vector_jmp_far_op, &vector_push_mem_op, INVALID + // clang-format on }; -static const risc86_instruction_t *opcode_timings_d8[8] = -{ +static const risc86_instruction_t *opcode_timings_d8[8] = { + // clang-format off /* FADDs FMULs FCOMs FCOMPs*/ &load_float_op, &load_float_op, &load_float_op, &load_float_op, /* FSUBs FSUBRs FDIVs FDIVRs*/ &load_float_op, &load_float_op, &fdiv_mem_op, &fdiv_mem_op, + // clang-format on }; -static const risc86_instruction_t *opcode_timings_d8_mod3[8] = -{ +static const risc86_instruction_t *opcode_timings_d8_mod3[8] = { + // clang-format off /* FADD FMUL FCOM FCOMP*/ &float_op, &float_op, &float_op, &float_op, /* FSUB FSUBR FDIV FDIVR*/ &float_op, &float_op, &fdiv_op, &fdiv_op, + // clang-format on }; -static const risc86_instruction_t *opcode_timings_d9[8] = -{ +static const risc86_instruction_t *opcode_timings_d9[8] = { + // clang-format off /* FLDs FSTs FSTPs*/ &load_float_op, INVALID, &fstore_op, &fstore_op, /* FLDENV FLDCW FSTENV FSTCW*/ &vector_float_l_op, &vector_fldcw_op, &vector_float_l_op, &vector_float_op + // clang-format on }; -static const risc86_instruction_t *opcode_timings_d9_mod3[64] = -{ +static const risc86_instruction_t *opcode_timings_d9_mod3[64] = { + // clang-format off /*FLD*/ &float_op, &float_op, &float_op, &float_op, &float_op, &float_op, &float_op, &float_op, @@ -1614,31 +1520,35 @@ static const risc86_instruction_t *opcode_timings_d9_mod3[64] = &fdiv_op, INVALID, &fsqrt_op, &fsin_op, /* opFRNDINT opFSCALE opFSIN opFCOS*/ &float_op, &fdiv_op, &fsin_op, &fsin_op + // clang-format on }; -static const risc86_instruction_t *opcode_timings_da[8] = -{ +static const risc86_instruction_t *opcode_timings_da[8] = { + // clang-format off /* FIADDl FIMULl FICOMl FICOMPl*/ &load_float_op, &load_float_op, &load_float_op, &load_float_op, /* FISUBl FISUBRl FIDIVl FIDIVRl*/ &load_float_op, &load_float_op, &fdiv_mem_op, &fdiv_mem_op, + // clang-format on }; -static const risc86_instruction_t *opcode_timings_da_mod3[8] = -{ +static const risc86_instruction_t *opcode_timings_da_mod3[8] = { + // clang-format off INVALID, INVALID, INVALID, INVALID, /* FCOMPP*/ INVALID, &float_op, INVALID, INVALID + // clang-format on }; -static const risc86_instruction_t *opcode_timings_db[8] = -{ +static const risc86_instruction_t *opcode_timings_db[8] = { + // clang-format off /* FLDil FSTil FSTPil*/ &load_float_op, INVALID, &fstore_op, &fstore_op, /* FLDe FSTPe*/ INVALID, &vector_flde_op, INVALID, &vector_fste_op + // clang-format on }; -static const risc86_instruction_t *opcode_timings_db_mod3[64] = -{ +static const risc86_instruction_t *opcode_timings_db_mod3[64] = { + // clang-format off INVALID, INVALID, INVALID, INVALID, INVALID, INVALID, INVALID, INVALID, @@ -1664,108 +1574,113 @@ static const risc86_instruction_t *opcode_timings_db_mod3[64] = INVALID, INVALID, INVALID, INVALID, INVALID, INVALID, INVALID, INVALID, + // clang-format on }; -static const risc86_instruction_t *opcode_timings_dc[8] = -{ +static const risc86_instruction_t *opcode_timings_dc[8] = { + // clang-format off /* FADDd FMULd FCOMd FCOMPd*/ &load_float_op, &load_float_op, &load_float_op, &load_float_op, /* FSUBd FSUBRd FDIVd FDIVRd*/ &load_float_op, &load_float_op, &fdiv_mem_op, &fdiv_mem_op, + // clang-format on }; -static const risc86_instruction_t *opcode_timings_dc_mod3[8] = -{ +static const risc86_instruction_t *opcode_timings_dc_mod3[8] = { + // clang-format off /* opFADDr opFMULr*/ &float_op, &float_op, INVALID, INVALID, /* opFSUBRr opFSUBr opFDIVRr opFDIVr*/ &float_op, &float_op, &fdiv_op, &fdiv_op + // clang-format on }; -static const risc86_instruction_t *opcode_timings_dd[8] = -{ +static const risc86_instruction_t *opcode_timings_dd[8] = { + // clang-format off /* FLDd FSTd FSTPd*/ &load_float_op, INVALID, &fstore_op, &fstore_op, /* FRSTOR FSAVE FSTSW*/ &vector_float_l_op, INVALID, &vector_float_l_op, &vector_float_l_op + // clang-format on }; -static const risc86_instruction_t *opcode_timings_dd_mod3[8] = -{ +static const risc86_instruction_t *opcode_timings_dd_mod3[8] = { + // clang-format off /* FFFREE FST FSTP*/ &float_op, INVALID, &float_op, &float_op, /* FUCOM FUCOMP*/ &float_op, &float_op, INVALID, INVALID + // clang-format on }; -static const risc86_instruction_t *opcode_timings_de[8] = -{ +static const risc86_instruction_t *opcode_timings_de[8] = { + // clang-format off /* FIADDw FIMULw FICOMw FICOMPw*/ &load_float_op, &load_float_op, &load_float_op, &load_float_op, /* FISUBw FISUBRw FIDIVw FIDIVRw*/ &load_float_op, &load_float_op, &fdiv_mem_op, &fdiv_mem_op, + // clang-format on }; -static const risc86_instruction_t *opcode_timings_de_mod3[8] = -{ +static const risc86_instruction_t *opcode_timings_de_mod3[8] = { + // clang-format off /* FADDP FMULP FCOMPP*/ &float_op, &float_op, INVALID, &float_op, /* FSUBP FSUBRP FDIVP FDIVRP*/ &float_op, &float_op, &fdiv_op, &fdiv_op, + // clang-format on }; -static const risc86_instruction_t *opcode_timings_df[8] = -{ +static const risc86_instruction_t *opcode_timings_df[8] = { + // clang-format off /* FILDiw FISTiw FISTPiw*/ &load_float_op, INVALID, &fstore_op, &fstore_op, /* FILDiq FBSTP FISTPiq*/ INVALID, &load_float_op, &vector_float_l_op, &fstore_op, + // clang-format on }; -static const risc86_instruction_t *opcode_timings_df_mod3[8] = -{ +static const risc86_instruction_t *opcode_timings_df_mod3[8] = { + // clang-format off INVALID, INVALID, INVALID, INVALID, /* FSTSW AX*/ &float_op, INVALID, INVALID, INVALID + // clang-format on }; - static uint8_t last_prefix; -static int prefixes; +static int prefixes; static int decode_timestamp; static int last_complete_timestamp; -typedef struct k6_unit_t -{ - uint32_t uop_mask; - int first_available_cycle; +typedef struct k6_unit_t { + uint32_t uop_mask; + int first_available_cycle; } k6_unit_t; -static int nr_units; +static int nr_units; static k6_unit_t *units; /*K6 has dedicated MMX unit*/ -static k6_unit_t k6_units[] = -{ - {.uop_mask = (1 << UOP_ALU) | (1 << UOP_ALUX)}, /*Integer X*/ - {.uop_mask = (1 << UOP_ALU)}, /*Integer Y*/ - {.uop_mask = (1 << UOP_MEU) | (1 << UOP_MEU_SHIFT) | (1 << UOP_MEU_MUL)}, /*Multimedia*/ - {.uop_mask = (1 << UOP_FLOAT)}, /*Floating point*/ - {.uop_mask = (1 << UOP_LOAD) | (1 << UOP_FLOAD) | (1 << UOP_MLOAD)}, /*Load*/ - {.uop_mask = (1 << UOP_STORE) | (1 << UOP_FSTORE) | (1 << UOP_MSTORE)}, /*Store*/ - {.uop_mask = (1 << UOP_BRANCH)} /*Branch*/ +static k6_unit_t k6_units[] = { + { .uop_mask = (1 << UOP_ALU) | (1 << UOP_ALUX) }, /*Integer X*/ + { .uop_mask = (1 << UOP_ALU) }, /*Integer Y*/ + { .uop_mask = (1 << UOP_MEU) | (1 << UOP_MEU_SHIFT) | (1 << UOP_MEU_MUL) }, /*Multimedia*/ + { .uop_mask = (1 << UOP_FLOAT) }, /*Floating point*/ + { .uop_mask = (1 << UOP_LOAD) | (1 << UOP_FLOAD) | (1 << UOP_MLOAD) }, /*Load*/ + { .uop_mask = (1 << UOP_STORE) | (1 << UOP_FSTORE) | (1 << UOP_MSTORE) }, /*Store*/ + { .uop_mask = (1 << UOP_BRANCH) } /*Branch*/ }; #define NR_K6_UNITS (sizeof(k6_units) / sizeof(k6_unit_t)) /*K6-2 and later integrate MMX into ALU X & Y, sharing multiplier, shifter and 3DNow ALU between two execution units*/ -static k6_unit_t k6_2_units[] = -{ - {.uop_mask = (1 << UOP_ALU) | (1 << UOP_ALUX) | (1 << UOP_MEU) | /*Integer X*/ - (1 << UOP_MEU_SHIFT) | (1 << UOP_MEU_MUL) | (1 << UOP_MEU_3DN)}, - {.uop_mask = (1 << UOP_ALU) | (1 << UOP_MEU) | /*Integer Y*/ - (1 << UOP_MEU_SHIFT) | (1 << UOP_MEU_MUL) | (1 << UOP_MEU_3DN)}, - {.uop_mask = (1 << UOP_FLOAT)}, /*Floating point*/ - {.uop_mask = (1 << UOP_LOAD) | (1 << UOP_FLOAD) | (1 << UOP_MLOAD)}, /*Load*/ - {.uop_mask = (1 << UOP_STORE) | (1 << UOP_FSTORE) | (1 << UOP_MSTORE)}, /*Store*/ - {.uop_mask = (1 << UOP_BRANCH)} /*Branch*/ +static k6_unit_t k6_2_units[] = { + { .uop_mask = (1 << UOP_ALU) | (1 << UOP_ALUX) | (1 << UOP_MEU) | /*Integer X*/ + (1 << UOP_MEU_SHIFT) | (1 << UOP_MEU_MUL) | (1 << UOP_MEU_3DN) }, + { .uop_mask = (1 << UOP_ALU) | (1 << UOP_MEU) | /*Integer Y*/ + (1 << UOP_MEU_SHIFT) | (1 << UOP_MEU_MUL) | (1 << UOP_MEU_3DN) }, + { .uop_mask = (1 << UOP_FLOAT) }, /*Floating point*/ + { .uop_mask = (1 << UOP_LOAD) | (1 << UOP_FLOAD) | (1 << UOP_MLOAD) }, /*Load*/ + { .uop_mask = (1 << UOP_STORE) | (1 << UOP_FSTORE) | (1 << UOP_MSTORE) }, /*Store*/ + { .uop_mask = (1 << UOP_BRANCH) } /*Branch*/ }; #define NR_K6_2_UNITS (sizeof(k6_2_units) / sizeof(k6_unit_t)) @@ -1775,57 +1690,52 @@ static int mul_first_available_cycle; static int shift_first_available_cycle; static int m3dnow_first_available_cycle; -static int uop_run(const risc86_uop_t *uop, int decode_time) +static int +uop_run(const risc86_uop_t *uop, int decode_time) { - int c; - k6_unit_t *best_unit = NULL; - int best_start_cycle = 99999; - - /*UOP_LIMM does not require execution*/ - if (uop->type == UOP_LIMM) - return decode_time; + k6_unit_t *best_unit = NULL; + int best_start_cycle = 99999; - /*Handle shared units on K6-2 and later*/ - if (units == k6_2_units) - { - if (uop->type == UOP_MEU_MUL && decode_time < mul_first_available_cycle) - decode_time = mul_first_available_cycle; - else if (uop->type == UOP_MEU_SHIFT && decode_time < mul_first_available_cycle) - decode_time = shift_first_available_cycle; - else if (uop->type == UOP_MEU_3DN && decode_time < mul_first_available_cycle) - decode_time = m3dnow_first_available_cycle; + /*UOP_LIMM does not require execution*/ + if (uop->type == UOP_LIMM) + return decode_time; + + /*Handle shared units on K6-2 and later*/ + if (units == k6_2_units) { + if (uop->type == UOP_MEU_MUL && decode_time < mul_first_available_cycle) + decode_time = mul_first_available_cycle; + else if (uop->type == UOP_MEU_SHIFT && decode_time < mul_first_available_cycle) + decode_time = shift_first_available_cycle; + else if (uop->type == UOP_MEU_3DN && decode_time < mul_first_available_cycle) + decode_time = m3dnow_first_available_cycle; + } + + /*Find execution unit for this uOP*/ + for (int c = 0; c < nr_units; c++) { + if (units[c].uop_mask & (1 << uop->type)) { + if (units[c].first_available_cycle < best_start_cycle) { + best_unit = &units[c]; + best_start_cycle = units[c].first_available_cycle; + } } + } + if (!best_unit) + fatal("uop_run: can not find execution unit\n"); - /*Find execution unit for this uOP*/ - for (c = 0; c < nr_units; c++) - { - if (units[c].uop_mask & (1 << uop->type)) - { - if (units[c].first_available_cycle < best_start_cycle) - { - best_unit = &units[c]; - best_start_cycle = units[c].first_available_cycle; - } - } - } - if (!best_unit) - fatal("uop_run: can not find execution unit\n"); + if (best_start_cycle < decode_time) + best_start_cycle = decode_time; + best_unit->first_available_cycle = best_start_cycle + uop->throughput; - if (best_start_cycle < decode_time) - best_start_cycle = decode_time; - best_unit->first_available_cycle = best_start_cycle + uop->throughput; + if (units == k6_2_units) { + if (uop->type == UOP_MEU_MUL) + mul_first_available_cycle = best_start_cycle + uop->throughput; + else if (uop->type == UOP_MEU_SHIFT) + shift_first_available_cycle = best_start_cycle + uop->throughput; + else if (uop->type == UOP_MEU_3DN) + m3dnow_first_available_cycle = best_start_cycle + uop->throughput; + } - if (units == k6_2_units) - { - if (uop->type == UOP_MEU_MUL) - mul_first_available_cycle = best_start_cycle + uop->throughput; - else if (uop->type == UOP_MEU_SHIFT) - shift_first_available_cycle = best_start_cycle + uop->throughput; - else if (uop->type == UOP_MEU_3DN) - m3dnow_first_available_cycle = best_start_cycle + uop->throughput; - } - - return best_start_cycle + uop->throughput; + return best_start_cycle + uop->throughput; } /*The K6 decoder can decode, per clock : @@ -1833,14 +1743,13 @@ static int uop_run(const risc86_uop_t *uop, int decode_time) - 1 'long' instruction, up to 4 uOPs - 1 'vector' instruction, up to 4 uOPs per cycle, plus (I think) 1 cycle startup delay) */ -static struct -{ - int nr_uops; - const risc86_uop_t *uops[4]; - /*Earliest time a uop can start. If the timestamp is -1, then the uop is - part of a dependency chain and the start time is the completion time of - the previous uop*/ - int earliest_start[4]; +static struct { + int nr_uops; + const risc86_uop_t *uops[4]; + /*Earliest time a uop can start. If the timestamp is -1, then the uop is + part of a dependency chain and the start time is the completion time of + the previous uop*/ + int earliest_start[4]; } decode_buffer; #define NR_OPQUADS 6 @@ -1858,495 +1767,465 @@ static int fpu_st_timestamp[8]; dependent uop chains*/ static int last_uop_timestamp = 0; -void decode_flush() +void +decode_flush(void) { - int c; - int uop_timestamp = 0; + int uop_timestamp = 0; - /*Decoded opquad can not be submitted if there are no free spaces in the - opquad buffer*/ - if (decode_timestamp < opquad_completion_timestamp[next_opquad]) - decode_timestamp = opquad_completion_timestamp[next_opquad]; + /*Decoded opquad can not be submitted if there are no free spaces in the + opquad buffer*/ + if (decode_timestamp < opquad_completion_timestamp[next_opquad]) + decode_timestamp = opquad_completion_timestamp[next_opquad]; - /*Ensure that uops can not be submitted before they have been decoded*/ - if (decode_timestamp > last_uop_timestamp) - last_uop_timestamp = decode_timestamp; + /*Ensure that uops can not be submitted before they have been decoded*/ + if (decode_timestamp > last_uop_timestamp) + last_uop_timestamp = decode_timestamp; - /*Submit uops to execution units, and determine the latest completion time*/ - for (c = 0; c < decode_buffer.nr_uops; c++) - { - int start_timestamp; - - if (decode_buffer.earliest_start[c] == -1) - start_timestamp = last_uop_timestamp; - else - start_timestamp = decode_buffer.earliest_start[c]; - - last_uop_timestamp = uop_run(decode_buffer.uops[c], start_timestamp); - if (last_uop_timestamp > uop_timestamp) - uop_timestamp = last_uop_timestamp; - } + /*Submit uops to execution units, and determine the latest completion time*/ + for (int c = 0; c < decode_buffer.nr_uops; c++) { + int start_timestamp; - /*Calculate opquad completion time. Since opquads complete in order, it - must be after the last completion.*/ - if (uop_timestamp <= last_complete_timestamp) - last_complete_timestamp = last_complete_timestamp + 1; + if (decode_buffer.earliest_start[c] == -1) + start_timestamp = last_uop_timestamp; else - last_complete_timestamp = uop_timestamp; + start_timestamp = decode_buffer.earliest_start[c]; - /*Advance to next opquad in buffer*/ - opquad_completion_timestamp[next_opquad] = last_complete_timestamp; - next_opquad++; - if (next_opquad == NR_OPQUADS) - next_opquad = 0; + last_uop_timestamp = uop_run(decode_buffer.uops[c], start_timestamp); + if (last_uop_timestamp > uop_timestamp) + uop_timestamp = last_uop_timestamp; + } - decode_timestamp++; - decode_buffer.nr_uops = 0; + /*Calculate opquad completion time. Since opquads complete in order, it + must be after the last completion.*/ + if (uop_timestamp <= last_complete_timestamp) + last_complete_timestamp = last_complete_timestamp + 1; + else + last_complete_timestamp = uop_timestamp; + + /*Advance to next opquad in buffer*/ + opquad_completion_timestamp[next_opquad] = last_complete_timestamp; + next_opquad++; + if (next_opquad == NR_OPQUADS) + next_opquad = 0; + + decode_timestamp++; + decode_buffer.nr_uops = 0; } /*The instruction is only of interest here if it's longer than 7 bytes, as that's the limit on K6 short decoding*/ -static int codegen_timing_instr_length(uint64_t deps, uint32_t fetchdat, int op_32) +static int +codegen_timing_instr_length(uint64_t deps, uint32_t fetchdat, int op_32) { - int len = prefixes + 1; /*Opcode*/ - if (deps & MODRM) - { - len++; /*ModR/M*/ - if (deps & HAS_IMM8) - len++; - if (deps & HAS_IMM1632) - len += (op_32 & 0x100) ? 4 : 2; + int len = prefixes + 1; /*Opcode*/ + if (deps & MODRM) { + len++; /*ModR/M*/ + if (deps & HAS_IMM8) + len++; + if (deps & HAS_IMM1632) + len += (op_32 & 0x100) ? 4 : 2; - if (op_32 & 0x200) - { - if ((fetchdat & 7) == 4 && (fetchdat & 0xc0) != 0xc0) - { - /* Has SIB*/ - len++; - if ((fetchdat & 0xc0) == 0x40) - len++; - else if ((fetchdat & 0xc0) == 0x80) - len += 4; - else if ((fetchdat & 0x700) == 0x500) - len += 4; - } - else - { - if ((fetchdat & 0xc0) == 0x40) - len++; - else if ((fetchdat & 0xc0) == 0x80) - len += 4; - else if ((fetchdat & 0xc7) == 0x05) - len += 4; - } - } - else - { - if ((fetchdat & 0xc0) == 0x40) - len++; - else if ((fetchdat & 0xc0) == 0x80) - len += 2; - else if ((fetchdat & 0xc7) == 0x06) - len += 2; - } + if (op_32 & 0x200) { + if ((fetchdat & 7) == 4 && (fetchdat & 0xc0) != 0xc0) { + /* Has SIB*/ + len++; + if ((fetchdat & 0xc0) == 0x40) + len++; + else if ((fetchdat & 0xc0) == 0x80) + len += 4; + else if ((fetchdat & 0x700) == 0x500) + len += 4; + } else { + if ((fetchdat & 0xc0) == 0x40) + len++; + else if ((fetchdat & 0xc0) == 0x80) + len += 4; + else if ((fetchdat & 0xc7) == 0x05) + len += 4; + } + } else { + if ((fetchdat & 0xc0) == 0x40) + len++; + else if ((fetchdat & 0xc0) == 0x80) + len += 2; + else if ((fetchdat & 0xc7) == 0x06) + len += 2; } + } - return len; + return len; } -static void decode_instruction(const risc86_instruction_t *ins, uint64_t deps, uint32_t fetchdat, int op_32, int bit8) +static void +decode_instruction(const risc86_instruction_t *ins, uint64_t deps, uint32_t fetchdat, int op_32, int bit8) { - uint32_t regmask_required; - uint32_t regmask_modified; - int c, d; - int earliest_start = 0; - decode_type_t decode_type = ins->decode_type; - int instr_length = codegen_timing_instr_length(deps, fetchdat, op_32); + uint32_t regmask_required; + uint32_t regmask_modified; + int c; + int d; + int earliest_start = 0; + decode_type_t decode_type = ins->decode_type; + int instr_length = codegen_timing_instr_length(deps, fetchdat, op_32); - /*Generate input register mask, and determine the earliest time this - instruction can start. This is not accurate, as this is calculated per - x86 instruction when it should be handled per uop*/ - regmask_required = get_dstdep_mask(deps, fetchdat, bit8); - regmask_required |= get_addr_regmask(deps, fetchdat, op_32); - for (c = 0; c < 8; c++) - { - if (regmask_required & (1 << c)) - { - if (reg_available_timestamp[c] > decode_timestamp) - earliest_start = reg_available_timestamp[c]; - } + /*Generate input register mask, and determine the earliest time this + instruction can start. This is not accurate, as this is calculated per + x86 instruction when it should be handled per uop*/ + regmask_required = get_dstdep_mask(deps, fetchdat, bit8); + regmask_required |= get_addr_regmask(deps, fetchdat, op_32); + for (c = 0; c < 8; c++) { + if (regmask_required & (1 << c)) { + if (reg_available_timestamp[c] > decode_timestamp) + earliest_start = reg_available_timestamp[c]; } - if ((deps & FPU_RW_ST0) && fpu_st_timestamp[0] > decode_timestamp) - earliest_start = fpu_st_timestamp[0]; - if ((deps & FPU_RW_ST1) && fpu_st_timestamp[1] > decode_timestamp) - earliest_start = fpu_st_timestamp[1]; - if ((deps & FPU_RW_STREG)) - { - int reg = fetchdat & 7; + } + if ((deps & FPU_RW_ST0) && fpu_st_timestamp[0] > decode_timestamp) + earliest_start = fpu_st_timestamp[0]; + if ((deps & FPU_RW_ST1) && fpu_st_timestamp[1] > decode_timestamp) + earliest_start = fpu_st_timestamp[1]; + if (deps & FPU_RW_STREG) { + int reg = fetchdat & 7; - if (fpu_st_timestamp[reg] > decode_timestamp) - earliest_start = fpu_st_timestamp[reg]; - } + if (fpu_st_timestamp[reg] > decode_timestamp) + earliest_start = fpu_st_timestamp[reg]; + } - /*Short decoders are limited to 7 bytes*/ - if (decode_type == DECODE_SHORT && instr_length > 7) - decode_type = DECODE_LONG; - /*Long decoder is limited to 11 bytes*/ - else if (instr_length > 11) - decode_type = DECODE_VECTOR; + /*Short decoders are limited to 7 bytes*/ + if (decode_type == DECODE_SHORT && instr_length > 7) + decode_type = DECODE_LONG; + /*Long decoder is limited to 11 bytes*/ + else if (instr_length > 11) + decode_type = DECODE_VECTOR; - switch (decode_type) - { - case DECODE_SHORT: - if (decode_buffer.nr_uops) - { - decode_buffer.uops[decode_buffer.nr_uops] = &ins->uop[0]; - decode_buffer.earliest_start[decode_buffer.nr_uops] = earliest_start; - if (ins->nr_uops > 1) - { - decode_buffer.uops[decode_buffer.nr_uops+1] = &ins->uop[1]; - decode_buffer.earliest_start[decode_buffer.nr_uops+1] = -1; - } - decode_buffer.nr_uops += ins->nr_uops; - - decode_flush(); - } - else - { - decode_buffer.nr_uops = ins->nr_uops; - decode_buffer.uops[0] = &ins->uop[0]; - decode_buffer.earliest_start[0] = earliest_start; - if (ins->nr_uops > 1) - { - decode_buffer.uops[1] = &ins->uop[1]; - decode_buffer.earliest_start[1] = -1; - } - } - break; - - case DECODE_LONG: - if (decode_buffer.nr_uops) - decode_flush(); - - decode_buffer.nr_uops = ins->nr_uops; - for (c = 0; c < ins->nr_uops; c++) - { - decode_buffer.uops[c] = &ins->uop[c]; - if (c == 0) - decode_buffer.earliest_start[c] = earliest_start; - else - decode_buffer.earliest_start[c] = -1; + switch (decode_type) { + case DECODE_SHORT: + if (decode_buffer.nr_uops) { + decode_buffer.uops[decode_buffer.nr_uops] = &ins->uop[0]; + decode_buffer.earliest_start[decode_buffer.nr_uops] = earliest_start; + if (ins->nr_uops > 1) { + decode_buffer.uops[decode_buffer.nr_uops + 1] = &ins->uop[1]; + decode_buffer.earliest_start[decode_buffer.nr_uops + 1] = -1; } + decode_buffer.nr_uops += ins->nr_uops; + decode_flush(); - break; - - case DECODE_VECTOR: - if (decode_buffer.nr_uops) - decode_flush(); - - decode_timestamp++; - d = 0; - - for (c = 0; c < ins->nr_uops; c++) - { - decode_buffer.uops[d] = &ins->uop[c]; - if (c == 0) - decode_buffer.earliest_start[d] = earliest_start; - else - decode_buffer.earliest_start[d] = -1; - d++; - - if (d == 4) - { - d = 0; - decode_buffer.nr_uops = 4; - decode_flush(); - } + } else { + decode_buffer.nr_uops = ins->nr_uops; + decode_buffer.uops[0] = &ins->uop[0]; + decode_buffer.earliest_start[0] = earliest_start; + if (ins->nr_uops > 1) { + decode_buffer.uops[1] = &ins->uop[1]; + decode_buffer.earliest_start[1] = -1; } - if (d) - { - decode_buffer.nr_uops = d; - decode_flush(); - } - break; - } + } + break; - /*Update write timestamps for any output registers*/ - regmask_modified = get_dstdep_mask(deps, fetchdat, bit8); - for (c = 0; c < 8; c++) - { - if (regmask_modified & (1 << c)) - reg_available_timestamp[c] = last_complete_timestamp; - } - if (deps & FPU_POP) - { - for (c = 0; c < 7; c++) - fpu_st_timestamp[c] = fpu_st_timestamp[c+1]; - fpu_st_timestamp[7] = 0; - } - if (deps & FPU_POP2) - { - for (c = 0; c < 6; c++) - fpu_st_timestamp[c] = fpu_st_timestamp[c+2]; - fpu_st_timestamp[6] = fpu_st_timestamp[7] = 0; - } - if (deps & FPU_PUSH) - { - for (c = 0; c < 7; c++) - fpu_st_timestamp[c+1] = fpu_st_timestamp[c]; - fpu_st_timestamp[0] = 0; - } - if (deps & FPU_WRITE_ST0) - fpu_st_timestamp[0] = last_complete_timestamp; - if (deps & FPU_WRITE_ST1) - fpu_st_timestamp[1] = last_complete_timestamp; - if (deps & FPU_WRITE_STREG) - { - int reg = fetchdat & 7; - if (deps & FPU_POP) - reg--; - if (reg >= 0 && - !(reg == 0 && (deps & FPU_WRITE_ST0)) && - !(reg == 1 && (deps & FPU_WRITE_ST1))) - fpu_st_timestamp[reg] = last_complete_timestamp; - } -} + case DECODE_LONG: + if (decode_buffer.nr_uops) + decode_flush(); -void codegen_timing_k6_block_start() -{ - int c; - - for (c = 0; c < nr_units; c++) - units[c].first_available_cycle = 0; - - mul_first_available_cycle = 0; - shift_first_available_cycle = 0; - m3dnow_first_available_cycle = 0; - - decode_timestamp = 0; - last_complete_timestamp = 0; - - for (c = 0; c < NR_OPQUADS; c++) - opquad_completion_timestamp[c] = 0; - next_opquad = 0; - - for (c = 0; c < NR_REGS; c++) - reg_available_timestamp[c] = 0; - for (c = 0; c < 8; c++) - fpu_st_timestamp[c] = 0; -} - -void codegen_timing_k6_start() -{ - if (cpu_s->cpu_type == CPU_K6) - { - units = k6_units; - nr_units = NR_K6_UNITS; - } - else - { - units = k6_2_units; - nr_units = NR_K6_2_UNITS; - } - last_prefix = 0; - prefixes = 0; -} - -void codegen_timing_k6_prefix(uint8_t prefix, uint32_t fetchdat) -{ - if (prefix != 0x0f) - decode_timestamp++; - - last_prefix = prefix; - prefixes++; -} - -void codegen_timing_k6_opcode(uint8_t opcode, uint32_t fetchdat, int op_32, uint32_t op_pc) -{ - const risc86_instruction_t **ins_table; - uint64_t *deps; - int mod3 = ((fetchdat & 0xc0) == 0xc0); - int old_last_complete_timestamp = last_complete_timestamp; - int bit8 = !(opcode & 1); - - switch (last_prefix) - { - case 0x0f: - if (opcode == 0x0f) - { - /*3DNow has the actual opcode after ModR/M, SIB and any offset*/ - uint32_t opcode_pc = op_pc + 1; /*Byte after ModR/M*/ - uint8_t modrm = fetchdat & 0xff; - uint8_t sib = (fetchdat >> 8) & 0xff; - - if ((modrm & 0xc0) != 0xc0) - { - if (op_32 & 0x200) - { - if ((modrm & 7) == 4) - { - /* Has SIB*/ - opcode_pc++; - if ((modrm & 0xc0) == 0x40) - opcode_pc++; - else if ((modrm & 0xc0) == 0x80) - opcode_pc += 4; - else if ((sib & 0x07) == 0x05) - opcode_pc += 4; - } - else - { - if ((modrm & 0xc0) == 0x40) - opcode_pc++; - else if ((modrm & 0xc0) == 0x80) - opcode_pc += 4; - else if ((modrm & 0xc7) == 0x05) - opcode_pc += 4; - } - } - else - { - if ((modrm & 0xc0) == 0x40) - opcode_pc++; - else if ((modrm & 0xc0) == 0x80) - opcode_pc += 2; - else if ((modrm & 0xc7) == 0x06) - opcode_pc += 2; - } - } - - opcode = fastreadb(cs + opcode_pc); - - ins_table = mod3 ? opcode_timings_0f0f_mod3 : opcode_timings_0f0f; - deps = mod3 ? opcode_deps_0f0f_mod3 : opcode_deps_0f0f; - } + decode_buffer.nr_uops = ins->nr_uops; + for (c = 0; c < ins->nr_uops; c++) { + decode_buffer.uops[c] = &ins->uop[c]; + if (c == 0) + decode_buffer.earliest_start[c] = earliest_start; else - { - ins_table = mod3 ? opcode_timings_0f_mod3 : opcode_timings_0f; - deps = mod3 ? opcode_deps_0f_mod3 : opcode_deps_0f; - } - break; + decode_buffer.earliest_start[c] = -1; + } + decode_flush(); + break; - case 0xd8: - ins_table = mod3 ? opcode_timings_d8_mod3 : opcode_timings_d8; - deps = mod3 ? opcode_deps_d8_mod3 : opcode_deps_d8; - opcode = (opcode >> 3) & 7; - break; - case 0xd9: - ins_table = mod3 ? opcode_timings_d9_mod3 : opcode_timings_d9; - deps = mod3 ? opcode_deps_d9_mod3 : opcode_deps_d9; - opcode = mod3 ? opcode & 0x3f : (opcode >> 3) & 7; - break; - case 0xda: - ins_table = mod3 ? opcode_timings_da_mod3 : opcode_timings_da; - deps = mod3 ? opcode_deps_da_mod3 : opcode_deps_da; - opcode = (opcode >> 3) & 7; - break; - case 0xdb: - ins_table = mod3 ? opcode_timings_db_mod3 : opcode_timings_db; - deps = mod3 ? opcode_deps_db_mod3 : opcode_deps_db; - opcode = mod3 ? opcode & 0x3f : (opcode >> 3) & 7; - break; - case 0xdc: - ins_table = mod3 ? opcode_timings_dc_mod3 : opcode_timings_dc; - deps = mod3 ? opcode_deps_dc_mod3 : opcode_deps_dc; - opcode = (opcode >> 3) & 7; - break; - case 0xdd: - ins_table = mod3 ? opcode_timings_dd_mod3 : opcode_timings_dd; - deps = mod3 ? opcode_deps_dd_mod3 : opcode_deps_dd; - opcode = (opcode >> 3) & 7; - break; - case 0xde: - ins_table = mod3 ? opcode_timings_de_mod3 : opcode_timings_de; - deps = mod3 ? opcode_deps_de_mod3 : opcode_deps_de; - opcode = (opcode >> 3) & 7; - break; - case 0xdf: - ins_table = mod3 ? opcode_timings_df_mod3 : opcode_timings_df; - deps = mod3 ? opcode_deps_df_mod3 : opcode_deps_df; - opcode = (opcode >> 3) & 7; - break; + case DECODE_VECTOR: + if (decode_buffer.nr_uops) + decode_flush(); + + decode_timestamp++; + d = 0; + + for (c = 0; c < ins->nr_uops; c++) { + decode_buffer.uops[d] = &ins->uop[c]; + if (c == 0) + decode_buffer.earliest_start[d] = earliest_start; + else + decode_buffer.earliest_start[d] = -1; + d++; + + if (d == 4) { + d = 0; + decode_buffer.nr_uops = 4; + decode_flush(); + } + } + if (d) { + decode_buffer.nr_uops = d; + decode_flush(); + } + break; + } + + /*Update write timestamps for any output registers*/ + regmask_modified = get_dstdep_mask(deps, fetchdat, bit8); + for (c = 0; c < 8; c++) { + if (regmask_modified & (1 << c)) + reg_available_timestamp[c] = last_complete_timestamp; + } + if (deps & FPU_POP) { + for (c = 0; c < 7; c++) + fpu_st_timestamp[c] = fpu_st_timestamp[c + 1]; + fpu_st_timestamp[7] = 0; + } + if (deps & FPU_POP2) { + for (c = 0; c < 6; c++) + fpu_st_timestamp[c] = fpu_st_timestamp[c + 2]; + fpu_st_timestamp[6] = fpu_st_timestamp[7] = 0; + } + if (deps & FPU_PUSH) { + for (c = 0; c < 7; c++) + fpu_st_timestamp[c + 1] = fpu_st_timestamp[c]; + fpu_st_timestamp[0] = 0; + } + if (deps & FPU_WRITE_ST0) + fpu_st_timestamp[0] = last_complete_timestamp; + if (deps & FPU_WRITE_ST1) + fpu_st_timestamp[1] = last_complete_timestamp; + if (deps & FPU_WRITE_STREG) { + int reg = fetchdat & 7; + if (deps & FPU_POP) + reg--; + if (reg >= 0 && !(reg == 0 && (deps & FPU_WRITE_ST0)) && !(reg == 1 && (deps & FPU_WRITE_ST1))) + fpu_st_timestamp[reg] = last_complete_timestamp; + } +} + +void +codegen_timing_k6_block_start(void) +{ + int c; + + for (c = 0; c < nr_units; c++) + units[c].first_available_cycle = 0; + + mul_first_available_cycle = 0; + shift_first_available_cycle = 0; + m3dnow_first_available_cycle = 0; + + decode_timestamp = 0; + last_complete_timestamp = 0; + + for (c = 0; c < NR_OPQUADS; c++) + opquad_completion_timestamp[c] = 0; + next_opquad = 0; + + for (c = 0; c < NR_REGS; c++) + reg_available_timestamp[c] = 0; + for (c = 0; c < 8; c++) + fpu_st_timestamp[c] = 0; +} + +void +codegen_timing_k6_start(void) +{ + if (cpu_s->cpu_type == CPU_K6) { + units = k6_units; + nr_units = NR_K6_UNITS; + } else { + units = k6_2_units; + nr_units = NR_K6_2_UNITS; + } + last_prefix = 0; + prefixes = 0; +} + +void +codegen_timing_k6_prefix(uint8_t prefix, uint32_t fetchdat) +{ + if (prefix != 0x0f) + decode_timestamp++; + + last_prefix = prefix; + prefixes++; +} + +void +codegen_timing_k6_opcode(uint8_t opcode, uint32_t fetchdat, int op_32, uint32_t op_pc) +{ + const risc86_instruction_t **ins_table; + const uint64_t *deps; + int mod3 = ((fetchdat & 0xc0) == 0xc0); + int old_last_complete_timestamp = last_complete_timestamp; + int bit8 = !(opcode & 1); + + switch (last_prefix) { + case 0x0f: + if (opcode == 0x0f) { + /*3DNow has the actual opcode after ModR/M, SIB and any offset*/ + uint32_t opcode_pc = op_pc + 1; /*Byte after ModR/M*/ + uint8_t modrm = fetchdat & 0xff; + uint8_t sib = (fetchdat >> 8) & 0xff; + + if ((modrm & 0xc0) != 0xc0) { + if (op_32 & 0x200) { + if ((modrm & 7) == 4) { + /* Has SIB*/ + opcode_pc++; + if ((modrm & 0xc0) == 0x40) + opcode_pc++; + else if ((modrm & 0xc0) == 0x80) + opcode_pc += 4; + else if ((sib & 0x07) == 0x05) + opcode_pc += 4; + } else { + if ((modrm & 0xc0) == 0x40) + opcode_pc++; + else if ((modrm & 0xc0) == 0x80) + opcode_pc += 4; + else if ((modrm & 0xc7) == 0x05) + opcode_pc += 4; + } + } else { + if ((modrm & 0xc0) == 0x40) + opcode_pc++; + else if ((modrm & 0xc0) == 0x80) + opcode_pc += 2; + else if ((modrm & 0xc7) == 0x06) + opcode_pc += 2; + } + } + + opcode = fastreadb(cs + opcode_pc); + + ins_table = mod3 ? opcode_timings_0f0f_mod3 : opcode_timings_0f0f; + deps = mod3 ? opcode_deps_0f0f_mod3 : opcode_deps_0f0f; + } else { + ins_table = mod3 ? opcode_timings_0f_mod3 : opcode_timings_0f; + deps = mod3 ? opcode_deps_0f_mod3 : opcode_deps_0f; + } + break; + + case 0xd8: + ins_table = mod3 ? opcode_timings_d8_mod3 : opcode_timings_d8; + deps = mod3 ? opcode_deps_d8_mod3 : opcode_deps_d8; + opcode = (opcode >> 3) & 7; + break; + case 0xd9: + ins_table = mod3 ? opcode_timings_d9_mod3 : opcode_timings_d9; + deps = mod3 ? opcode_deps_d9_mod3 : opcode_deps_d9; + opcode = mod3 ? opcode & 0x3f : (opcode >> 3) & 7; + break; + case 0xda: + ins_table = mod3 ? opcode_timings_da_mod3 : opcode_timings_da; + deps = mod3 ? opcode_deps_da_mod3 : opcode_deps_da; + opcode = (opcode >> 3) & 7; + break; + case 0xdb: + ins_table = mod3 ? opcode_timings_db_mod3 : opcode_timings_db; + deps = mod3 ? opcode_deps_db_mod3 : opcode_deps_db; + opcode = mod3 ? opcode & 0x3f : (opcode >> 3) & 7; + break; + case 0xdc: + ins_table = mod3 ? opcode_timings_dc_mod3 : opcode_timings_dc; + deps = mod3 ? opcode_deps_dc_mod3 : opcode_deps_dc; + opcode = (opcode >> 3) & 7; + break; + case 0xdd: + ins_table = mod3 ? opcode_timings_dd_mod3 : opcode_timings_dd; + deps = mod3 ? opcode_deps_dd_mod3 : opcode_deps_dd; + opcode = (opcode >> 3) & 7; + break; + case 0xde: + ins_table = mod3 ? opcode_timings_de_mod3 : opcode_timings_de; + deps = mod3 ? opcode_deps_de_mod3 : opcode_deps_de; + opcode = (opcode >> 3) & 7; + break; + case 0xdf: + ins_table = mod3 ? opcode_timings_df_mod3 : opcode_timings_df; + deps = mod3 ? opcode_deps_df_mod3 : opcode_deps_df; + opcode = (opcode >> 3) & 7; + break; + + default: + switch (opcode) { + case 0x80: + case 0x82: + ins_table = mod3 ? opcode_timings_80_mod3 : opcode_timings_80; + deps = mod3 ? opcode_deps_8x_mod3 : opcode_deps_8x; + opcode = (fetchdat >> 3) & 7; + break; + case 0x81: + case 0x83: + ins_table = mod3 ? opcode_timings_8x_mod3 : opcode_timings_8x; + deps = mod3 ? opcode_deps_8x_mod3 : opcode_deps_8x; + opcode = (fetchdat >> 3) & 7; + break; + + case 0xc0: + case 0xd0: + case 0xd2: + ins_table = mod3 ? opcode_timings_shift_b_mod3 : opcode_timings_shift_b; + deps = mod3 ? opcode_deps_shift_mod3 : opcode_deps_shift; + opcode = (fetchdat >> 3) & 7; + break; + + case 0xc1: + case 0xd1: + case 0xd3: + ins_table = mod3 ? opcode_timings_shift_mod3 : opcode_timings_shift; + deps = mod3 ? opcode_deps_shift_mod3 : opcode_deps_shift; + opcode = (fetchdat >> 3) & 7; + break; + + case 0xf6: + ins_table = mod3 ? opcode_timings_f6_mod3 : opcode_timings_f6; + deps = mod3 ? opcode_deps_f6_mod3 : opcode_deps_f6; + opcode = (fetchdat >> 3) & 7; + break; + case 0xf7: + ins_table = mod3 ? opcode_timings_f7_mod3 : opcode_timings_f7; + deps = mod3 ? opcode_deps_f7_mod3 : opcode_deps_f7; + opcode = (fetchdat >> 3) & 7; + break; + case 0xff: + ins_table = mod3 ? opcode_timings_ff_mod3 : opcode_timings_ff; + deps = mod3 ? opcode_deps_ff_mod3 : opcode_deps_ff; + opcode = (fetchdat >> 3) & 7; + break; default: - switch (opcode) - { - case 0x80: case 0x82: - ins_table = mod3 ? opcode_timings_80_mod3 : opcode_timings_80; - deps = mod3 ? opcode_deps_8x_mod3 : opcode_deps_8x; - opcode = (fetchdat >> 3) & 7; - break; - case 0x81: case 0x83: - ins_table = mod3 ? opcode_timings_8x_mod3 : opcode_timings_8x; - deps = mod3 ? opcode_deps_8x_mod3 : opcode_deps_8x; - opcode = (fetchdat >> 3) & 7; - break; + ins_table = mod3 ? opcode_timings_mod3 : opcode_timings; + deps = mod3 ? opcode_deps_mod3 : opcode_deps; + break; + } + } - case 0xc0: case 0xd0: case 0xd2: - ins_table = mod3 ? opcode_timings_shift_b_mod3 : opcode_timings_shift_b; - deps = mod3 ? opcode_deps_shift_mod3 : opcode_deps_shift; - opcode = (fetchdat >> 3) & 7; - break; - - case 0xc1: case 0xd1: case 0xd3: - ins_table = mod3 ? opcode_timings_shift_mod3 : opcode_timings_shift; - deps = mod3 ? opcode_deps_shift_mod3 : opcode_deps_shift; - opcode = (fetchdat >> 3) & 7; - break; + if (ins_table[opcode]) + decode_instruction(ins_table[opcode], deps[opcode], fetchdat, op_32, bit8); + else + decode_instruction(&vector_alu1_op, 0, fetchdat, op_32, bit8); + codegen_block_cycles += (last_complete_timestamp - old_last_complete_timestamp); +} - case 0xf6: - ins_table = mod3 ? opcode_timings_f6_mod3 : opcode_timings_f6; - deps = mod3 ? opcode_deps_f6_mod3 : opcode_deps_f6; - opcode = (fetchdat >> 3) & 7; - break; - case 0xf7: - ins_table = mod3 ? opcode_timings_f7_mod3 : opcode_timings_f7; - deps = mod3 ? opcode_deps_f7_mod3 : opcode_deps_f7; - opcode = (fetchdat >> 3) & 7; - break; - case 0xff: - ins_table = mod3 ? opcode_timings_ff_mod3 : opcode_timings_ff; - deps = mod3 ? opcode_deps_ff_mod3 : opcode_deps_ff; - opcode = (fetchdat >> 3) & 7; - break; - - default: - ins_table = mod3 ? opcode_timings_mod3 : opcode_timings; - deps = mod3 ? opcode_deps_mod3 : opcode_deps; - break; - } - } - - if (ins_table[opcode]) - decode_instruction(ins_table[opcode], deps[opcode], fetchdat, op_32, bit8); - else - decode_instruction(&vector_alu1_op, 0, fetchdat, op_32, bit8); +void +codegen_timing_k6_block_end(void) +{ + if (decode_buffer.nr_uops) { + int old_last_complete_timestamp = last_complete_timestamp; + decode_flush(); codegen_block_cycles += (last_complete_timestamp - old_last_complete_timestamp); + } } -void codegen_timing_k6_block_end() +int +codegen_timing_k6_jump_cycles(void) { - if (decode_buffer.nr_uops) - { - int old_last_complete_timestamp = last_complete_timestamp; - decode_flush(); - codegen_block_cycles += (last_complete_timestamp - old_last_complete_timestamp); - } + if (decode_buffer.nr_uops) + return 1; + return 0; } -int codegen_timing_k6_jump_cycles() -{ - if (decode_buffer.nr_uops) - return 1; - return 0; -} - -codegen_timing_t codegen_timing_k6 = -{ - codegen_timing_k6_start, - codegen_timing_k6_prefix, - codegen_timing_k6_opcode, - codegen_timing_k6_block_start, - codegen_timing_k6_block_end, - codegen_timing_k6_jump_cycles +codegen_timing_t codegen_timing_k6 = { + codegen_timing_k6_start, + codegen_timing_k6_prefix, + codegen_timing_k6_opcode, + codegen_timing_k6_block_start, + codegen_timing_k6_block_end, + codegen_timing_k6_jump_cycles }; diff --git a/src/cpu/codegen_timing_p6.c b/src/cpu/codegen_timing_p6.c index 47b502ba0..2c087ae86 100644 --- a/src/cpu/codegen_timing_p6.c +++ b/src/cpu/codegen_timing_p6.c @@ -8,899 +8,786 @@ #include "cpu.h" #include <86box/mem.h> #include <86box/machine.h> +#include <86box/plat_unused.h> #include "x86.h" #include "x86_ops.h" +#include "x86seg_common.h" #include "x87.h" #include "386_common.h" #include "codegen.h" #include "codegen_ops.h" #include "codegen_timing_common.h" -typedef enum uop_type_t -{ - UOP_ALU = 0, /*Executes in Port 0 or 1 ALU units*/ - UOP_ALUP0, /*Executes in Port 0 ALU unit*/ - UOP_LOAD, /*Executes in Load unit*/ - UOP_STORED, /*Executes in Data Store unit*/ - UOP_STOREA, /*Executes in Address Store unit*/ - UOP_FLOAD, /*Executes in Load unit*/ - UOP_FSTORED, /*Executes in Data Store unit*/ - UOP_FSTOREA, /*Executes in Address Store unit*/ - UOP_MLOAD, /*Executes in Load unit*/ - UOP_MSTORED, /*Executes in Data Store unit*/ - UOP_MSTOREA, /*Executes in Address Store unit*/ - UOP_FLOAT, /*Executes in Floating Point unit*/ - UOP_MMX, /*Executes in Port 0 or 1 ALU units as MMX*/ - UOP_MMX_SHIFT, /*Executes in Port 1 ALU unit. Uses MMX shifter*/ - UOP_MMX_MUL, /*Executes in Port 0 ALU unit. Uses MMX multiplier*/ - UOP_BRANCH, /*Executes in Branch unit*/ - UOP_FXCH /*Does not require an execution unit*/ +typedef enum uop_type_t { + UOP_ALU = 0, /*Executes in Port 0 or 1 ALU units*/ + UOP_ALUP0, /*Executes in Port 0 ALU unit*/ + UOP_LOAD, /*Executes in Load unit*/ + UOP_STORED, /*Executes in Data Store unit*/ + UOP_STOREA, /*Executes in Address Store unit*/ + UOP_FLOAD, /*Executes in Load unit*/ + UOP_FSTORED, /*Executes in Data Store unit*/ + UOP_FSTOREA, /*Executes in Address Store unit*/ + UOP_MLOAD, /*Executes in Load unit*/ + UOP_MSTORED, /*Executes in Data Store unit*/ + UOP_MSTOREA, /*Executes in Address Store unit*/ + UOP_FLOAT, /*Executes in Floating Point unit*/ + UOP_MMX, /*Executes in Port 0 or 1 ALU units as MMX*/ + UOP_MMX_SHIFT, /*Executes in Port 1 ALU unit. Uses MMX shifter*/ + UOP_MMX_MUL, /*Executes in Port 0 ALU unit. Uses MMX multiplier*/ + UOP_BRANCH, /*Executes in Branch unit*/ + UOP_FXCH /*Does not require an execution unit*/ } uop_type_t; -typedef enum decode_type_t -{ - DECODE_SIMPLE, - DECODE_COMPLEX, +typedef enum decode_type_t { + DECODE_SIMPLE, + DECODE_COMPLEX, } decode_type_t; #define MAX_UOPS 10 -typedef struct p6_uop_t -{ - uop_type_t type; - int latency; +typedef struct p6_uop_t { + uop_type_t type; + int latency; } p6_uop_t; -typedef struct macro_op_t -{ - int nr_uops; - decode_type_t decode_type; - p6_uop_t uop[MAX_UOPS]; +typedef struct macro_op_t { + int nr_uops; + decode_type_t decode_type; + p6_uop_t uop[MAX_UOPS]; } macro_op_t; -static const macro_op_t alu_op = -{ - .nr_uops = 1, - .decode_type = DECODE_SIMPLE, - .uop[0] = {.type = UOP_ALU, .latency = 1} +static const macro_op_t alu_op = { + .nr_uops = 1, + .decode_type = DECODE_SIMPLE, + .uop[0] = {.type = UOP_ALU, .latency = 1} }; -static const macro_op_t alup0_op = -{ - .nr_uops = 1, - .decode_type = DECODE_SIMPLE, - .uop[0] = {.type = UOP_ALUP0, .latency = 1} +static const macro_op_t alup0_op = { + .nr_uops = 1, + .decode_type = DECODE_SIMPLE, + .uop[0] = {.type = UOP_ALUP0, .latency = 1} }; -static const macro_op_t load_alu_op = -{ - .nr_uops = 2, - .decode_type = DECODE_COMPLEX, - .uop[0] = {.type = UOP_LOAD, .latency = 1}, - .uop[1] = {.type = UOP_ALU, .latency = 1} +static const macro_op_t load_alu_op = { + .nr_uops = 2, + .decode_type = DECODE_COMPLEX, + .uop[0] = {.type = UOP_LOAD, .latency = 1}, + .uop[1] = { .type = UOP_ALU, .latency = 1} }; -static const macro_op_t load_alup0_op = -{ - .nr_uops = 2, - .decode_type = DECODE_COMPLEX, - .uop[0] = {.type = UOP_LOAD, .latency = 1}, - .uop[1] = {.type = UOP_ALUP0, .latency = 1} +static const macro_op_t load_alup0_op = { + .nr_uops = 2, + .decode_type = DECODE_COMPLEX, + .uop[0] = {.type = UOP_LOAD, .latency = 1}, + .uop[1] = { .type = UOP_ALUP0, .latency = 1} }; -static const macro_op_t alu_store_op = -{ - .nr_uops = 4, - .decode_type = DECODE_COMPLEX, - .uop[0] = {.type = UOP_LOAD, .latency = 1}, - .uop[1] = {.type = UOP_ALU, .latency = 1}, - .uop[2] = {.type = UOP_STORED, .latency = 1}, - .uop[3] = {.type = UOP_STOREA, .latency = 1} - }; -static const macro_op_t alup0_store_op = -{ - .nr_uops = 4, - .decode_type = DECODE_COMPLEX, - .uop[0] = {.type = UOP_LOAD, .latency = 1}, - .uop[1] = {.type = UOP_ALUP0, .latency = 1}, - .uop[2] = {.type = UOP_STORED, .latency = 1}, - .uop[3] = {.type = UOP_STOREA, .latency = 1} +static const macro_op_t alu_store_op = { + .nr_uops = 4, + .decode_type = DECODE_COMPLEX, + .uop[0] = {.type = UOP_LOAD, .latency = 1}, + .uop[1] = { .type = UOP_ALU, .latency = 1}, + .uop[2] = { .type = UOP_STORED, .latency = 1}, + .uop[3] = { .type = UOP_STOREA, .latency = 1} +}; +static const macro_op_t alup0_store_op = { + .nr_uops = 4, + .decode_type = DECODE_COMPLEX, + .uop[0] = {.type = UOP_LOAD, .latency = 1}, + .uop[1] = { .type = UOP_ALUP0, .latency = 1}, + .uop[2] = { .type = UOP_STORED, .latency = 1}, + .uop[3] = { .type = UOP_STOREA, .latency = 1} }; -static const macro_op_t branch_op = -{ - .nr_uops = 1, - .decode_type = DECODE_COMPLEX, - .uop[0] = {.type = UOP_BRANCH, .latency = 2} +static const macro_op_t branch_op = { + .nr_uops = 1, + .decode_type = DECODE_COMPLEX, + .uop[0] = {.type = UOP_BRANCH, .latency = 2} }; -static const macro_op_t fxch_op = -{ - .nr_uops = 1, - .decode_type = DECODE_SIMPLE, - .uop[0] = {.type = UOP_FXCH, .latency = 1} +static const macro_op_t fxch_op = { + .nr_uops = 1, + .decode_type = DECODE_SIMPLE, + .uop[0] = {.type = UOP_FXCH, .latency = 1} }; -static const macro_op_t load_op = -{ - .nr_uops = 1, - .decode_type = DECODE_SIMPLE, - .uop[0] = {.type = UOP_LOAD, .latency = 1} +static const macro_op_t load_op = { + .nr_uops = 1, + .decode_type = DECODE_SIMPLE, + .uop[0] = {.type = UOP_LOAD, .latency = 1} }; -static const macro_op_t store_op = -{ - .nr_uops = 2, - .decode_type = DECODE_COMPLEX, - .uop[0] = {.type = UOP_STORED, .latency = 1}, - .uop[1] = {.type = UOP_STOREA, .latency = 1} +static const macro_op_t store_op = { + .nr_uops = 2, + .decode_type = DECODE_COMPLEX, + .uop[0] = {.type = UOP_STORED, .latency = 1}, + .uop[1] = { .type = UOP_STOREA, .latency = 1} }; - -static const macro_op_t bswap_op = -{ - .nr_uops = 2, - .decode_type = DECODE_COMPLEX, - .uop[0] = {.type = UOP_ALU, .latency = 1}, - .uop[1] = {.type = UOP_ALU, .latency = 1}, +static const macro_op_t bswap_op = { + .nr_uops = 2, + .decode_type = DECODE_COMPLEX, + .uop[0] = {.type = UOP_ALU, .latency = 1}, + .uop[1] = { .type = UOP_ALU, .latency = 1}, }; -static const macro_op_t leave_op = -{ - .nr_uops = 3, - .decode_type = DECODE_COMPLEX, - .uop[0] = {.type = UOP_LOAD, .latency = 1}, - .uop[1] = {.type = UOP_ALU, .latency = 1}, - .uop[2] = {.type = UOP_ALU, .latency = 1} +static const macro_op_t leave_op = { + .nr_uops = 3, + .decode_type = DECODE_COMPLEX, + .uop[0] = {.type = UOP_LOAD, .latency = 1}, + .uop[1] = { .type = UOP_ALU, .latency = 1}, + .uop[2] = { .type = UOP_ALU, .latency = 1} }; -static const macro_op_t lods_op = -{ - .nr_uops = 2, - .decode_type = DECODE_COMPLEX, - .uop[0] = {.type = UOP_LOAD, .latency = 1}, - .uop[1] = {.type = UOP_ALU, .latency = 1} +static const macro_op_t lods_op = { + .nr_uops = 2, + .decode_type = DECODE_COMPLEX, + .uop[0] = {.type = UOP_LOAD, .latency = 1}, + .uop[1] = { .type = UOP_ALU, .latency = 1} }; -static const macro_op_t loop_op = -{ - .nr_uops = 2, - .decode_type = DECODE_COMPLEX, - .uop[0] = {.type = UOP_ALU, .latency = 1}, - .uop[1] = {.type = UOP_BRANCH, .latency = 2} +static const macro_op_t loop_op = { + .nr_uops = 5, + .decode_type = DECODE_COMPLEX, + .uop[0] = {.type = UOP_ALU, .latency = 1}, + .uop[1] = { .type = UOP_ALU, .latency = 1}, + .uop[2] = { .type = UOP_ALU, .latency = 1}, + .uop[3] = { .type = UOP_ALU, .latency = 1}, + .uop[4] = { .type = UOP_BRANCH, .latency = 1} }; -static const macro_op_t mov_reg_seg_op = -{ - .nr_uops = 1, - .decode_type = DECODE_COMPLEX, - .uop[0] = {.type = UOP_LOAD, .latency = 1}, +static const macro_op_t mov_reg_seg_op = { + .nr_uops = 1, + .decode_type = DECODE_COMPLEX, + .uop[0] = {.type = UOP_LOAD, .latency = 1}, }; -static const macro_op_t movs_op = -{ - .nr_uops = 4, - .decode_type = DECODE_COMPLEX, - .uop[0] = {.type = UOP_LOAD, .latency = 1}, - .uop[1] = {.type = UOP_STORED, .latency = 1}, - .uop[2] = {.type = UOP_STOREA, .latency = 1}, - .uop[3] = {.type = UOP_ALU, .latency = 1} +static const macro_op_t movs_op = { + .nr_uops = 4, + .decode_type = DECODE_COMPLEX, + .uop[0] = {.type = UOP_LOAD, .latency = 1}, + .uop[1] = { .type = UOP_STORED, .latency = 1}, + .uop[2] = { .type = UOP_STOREA, .latency = 1}, + .uop[3] = { .type = UOP_ALU, .latency = 1} }; -static const macro_op_t pop_reg_op = -{ - .nr_uops = 2, - .decode_type = DECODE_COMPLEX, - .uop[0] = {.type = UOP_LOAD, .latency = 1}, - .uop[1] = {.type = UOP_ALU, .latency = 1} +static const macro_op_t pop_reg_op = { + .nr_uops = 2, + .decode_type = DECODE_COMPLEX, + .uop[0] = {.type = UOP_LOAD, .latency = 1}, + .uop[1] = { .type = UOP_ALU, .latency = 1} }; -static const macro_op_t pop_mem_op = -{ - .nr_uops = 4, - .decode_type = DECODE_COMPLEX, - .uop[0] = {.type = UOP_LOAD, .latency = 1}, - .uop[1] = {.type = UOP_STORED, .latency = 1}, - .uop[2] = {.type = UOP_STOREA, .latency = 1}, - .uop[3] = {.type = UOP_ALU, .latency = 1} +static const macro_op_t pop_mem_op = { + .nr_uops = 4, + .decode_type = DECODE_COMPLEX, + .uop[0] = {.type = UOP_LOAD, .latency = 1}, + .uop[1] = { .type = UOP_STORED, .latency = 1}, + .uop[2] = { .type = UOP_STOREA, .latency = 1}, + .uop[3] = { .type = UOP_ALU, .latency = 1} }; -static const macro_op_t push_imm_op = -{ - .nr_uops = 2, - .decode_type = DECODE_COMPLEX, - .uop[0] = {.type = UOP_STORED, .latency = 1}, - .uop[1] = {.type = UOP_STOREA, .latency = 1}, +static const macro_op_t push_imm_op = { + .nr_uops = 2, + .decode_type = DECODE_COMPLEX, + .uop[0] = {.type = UOP_STORED, .latency = 1}, + .uop[1] = { .type = UOP_STOREA, .latency = 1}, }; -static const macro_op_t push_mem_op = -{ - .nr_uops = 3, - .decode_type = DECODE_COMPLEX, - .uop[0] = {.type = UOP_LOAD, .latency = 1}, - .uop[1] = {.type = UOP_STORED, .latency = 1}, - .uop[2] = {.type = UOP_STOREA, .latency = 1} +static const macro_op_t push_mem_op = { + .nr_uops = 3, + .decode_type = DECODE_COMPLEX, + .uop[0] = {.type = UOP_LOAD, .latency = 1}, + .uop[1] = { .type = UOP_STORED, .latency = 1}, + .uop[2] = { .type = UOP_STOREA, .latency = 1} }; -static const macro_op_t push_seg_op = -{ - .nr_uops = 3, - .decode_type = DECODE_COMPLEX, - .uop[0] = {.type = UOP_LOAD, .latency = 1}, - .uop[1] = {.type = UOP_STORED, .latency = 1}, - .uop[2] = {.type = UOP_STOREA, .latency = 1}, - .uop[3] = {.type = UOP_ALU, .latency = 1} +static const macro_op_t push_seg_op = { + .nr_uops = 3, + .decode_type = DECODE_COMPLEX, + .uop[0] = {.type = UOP_LOAD, .latency = 1}, + .uop[1] = { .type = UOP_STORED, .latency = 1}, + .uop[2] = { .type = UOP_STOREA, .latency = 1}, + .uop[3] = { .type = UOP_ALU, .latency = 1} }; -static const macro_op_t stos_op = -{ - .nr_uops = 3, - .decode_type = DECODE_COMPLEX, - .uop[1] = {.type = UOP_STORED, .latency = 1}, - .uop[2] = {.type = UOP_STOREA, .latency = 1}, - .uop[3] = {.type = UOP_ALU, .latency = 1} +static const macro_op_t stos_op = { + .nr_uops = 3, + .decode_type = DECODE_COMPLEX, + .uop[1] = {.type = UOP_STORED, .latency = 1}, + .uop[2] = { .type = UOP_STOREA, .latency = 1}, + .uop[3] = { .type = UOP_ALU, .latency = 1} }; -static const macro_op_t test_reg_op = -{ - .nr_uops = 1, - .decode_type = DECODE_COMPLEX, - .uop[0] = {.type = UOP_ALU, .latency = 1} +static const macro_op_t test_reg_op = { + .nr_uops = 1, + .decode_type = DECODE_COMPLEX, + .uop[0] = {.type = UOP_ALU, .latency = 1} }; -static const macro_op_t test_reg_b_op = -{ - .nr_uops = 1, - .decode_type = DECODE_COMPLEX, - .uop[0] = {.type = UOP_ALUP0, .latency = 1} +static const macro_op_t test_reg_b_op = { + .nr_uops = 1, + .decode_type = DECODE_COMPLEX, + .uop[0] = {.type = UOP_ALUP0, .latency = 1} }; -static const macro_op_t test_mem_imm_op = -{ - .nr_uops = 2, - .decode_type = DECODE_COMPLEX, - .uop[0] = {.type = UOP_LOAD, .latency = 1}, - .uop[1] = {.type = UOP_ALU, .latency = 1} +static const macro_op_t test_mem_imm_op = { + .nr_uops = 2, + .decode_type = DECODE_COMPLEX, + .uop[0] = {.type = UOP_LOAD, .latency = 1}, + .uop[1] = { .type = UOP_ALU, .latency = 1} }; -static const macro_op_t test_mem_imm_b_op = -{ - .nr_uops = 2, - .decode_type = DECODE_COMPLEX, - .uop[0] = {.type = UOP_LOAD, .latency = 1}, - .uop[1] = {.type = UOP_ALUP0, .latency = 1} +static const macro_op_t test_mem_imm_b_op = { + .nr_uops = 2, + .decode_type = DECODE_COMPLEX, + .uop[0] = {.type = UOP_LOAD, .latency = 1}, + .uop[1] = { .type = UOP_ALUP0, .latency = 1} }; -static const macro_op_t xchg_op = -{ - .nr_uops = 3, - .decode_type = DECODE_COMPLEX, - .uop[0] = {.type = UOP_ALU, .latency = 1}, - .uop[1] = {.type = UOP_ALU, .latency = 1}, - .uop[2] = {.type = UOP_ALU, .latency = 1} +static const macro_op_t xchg_op = { + .nr_uops = 3, + .decode_type = DECODE_COMPLEX, + .uop[0] = {.type = UOP_ALU, .latency = 1}, + .uop[1] = { .type = UOP_ALU, .latency = 1}, + .uop[2] = { .type = UOP_ALU, .latency = 1} }; - -static const macro_op_t mmx_op = -{ - .nr_uops = 1, - .decode_type = DECODE_SIMPLE, - .uop[0] = {.type = UOP_MMX, .latency = 1} +static const macro_op_t mmx_op = { + .nr_uops = 1, + .decode_type = DECODE_SIMPLE, + .uop[0] = {.type = UOP_MMX, .latency = 1} }; -static const macro_op_t mmx_mul_op = -{ - .nr_uops = 1, - .decode_type = DECODE_SIMPLE, - .uop[0] = {.type = UOP_MMX_MUL, .latency = 1} +static const macro_op_t mmx_mul_op = { + .nr_uops = 1, + .decode_type = DECODE_SIMPLE, + .uop[0] = {.type = UOP_MMX_MUL, .latency = 1} }; -static const macro_op_t mmx_shift_op = -{ - .nr_uops = 1, - .decode_type = DECODE_SIMPLE, - .uop[0] = {.type = UOP_MMX_SHIFT, .latency = 1} +static const macro_op_t mmx_shift_op = { + .nr_uops = 1, + .decode_type = DECODE_SIMPLE, + .uop[0] = {.type = UOP_MMX_SHIFT, .latency = 1} }; -static const macro_op_t load_mmx_op = -{ - .nr_uops = 2, - .decode_type = DECODE_COMPLEX, - .uop[0] = {.type = UOP_LOAD, .latency = 2}, - .uop[1] = {.type = UOP_MMX, .latency = 2} +static const macro_op_t load_mmx_op = { + .nr_uops = 2, + .decode_type = DECODE_COMPLEX, + .uop[0] = {.type = UOP_LOAD, .latency = 2}, + .uop[1] = { .type = UOP_MMX, .latency = 2} }; -static const macro_op_t load_mmx_mul_op = -{ - .nr_uops = 2, - .decode_type = DECODE_COMPLEX, - .uop[0] = {.type = UOP_LOAD, .latency = 2}, - .uop[1] = {.type = UOP_MMX_MUL, .latency = 2} +static const macro_op_t load_mmx_mul_op = { + .nr_uops = 2, + .decode_type = DECODE_COMPLEX, + .uop[0] = {.type = UOP_LOAD, .latency = 2}, + .uop[1] = { .type = UOP_MMX_MUL, .latency = 2} }; -static const macro_op_t load_mmx_shift_op = -{ - .nr_uops = 2, - .decode_type = DECODE_COMPLEX, - .uop[0] = {.type = UOP_LOAD, .latency = 2}, - .uop[1] = {.type = UOP_MMX_SHIFT, .latency = 2} +static const macro_op_t load_mmx_shift_op = { + .nr_uops = 2, + .decode_type = DECODE_COMPLEX, + .uop[0] = {.type = UOP_LOAD, .latency = 2}, + .uop[1] = { .type = UOP_MMX_SHIFT, .latency = 2} }; -static const macro_op_t mload_op = -{ - .nr_uops = 1, - .decode_type = DECODE_COMPLEX, - .uop[0] = {.type = UOP_MLOAD, .latency = 1}, +static const macro_op_t mload_op = { + .nr_uops = 1, + .decode_type = DECODE_COMPLEX, + .uop[0] = {.type = UOP_MLOAD, .latency = 1}, }; -static const macro_op_t mstore_op = -{ - .nr_uops = 2, - .decode_type = DECODE_COMPLEX, - .uop[0] = {.type = UOP_MSTORED, .latency = 1}, - .uop[1] = {.type = UOP_MSTOREA, .latency = 1} +static const macro_op_t mstore_op = { + .nr_uops = 2, + .decode_type = DECODE_COMPLEX, + .uop[0] = {.type = UOP_MSTORED, .latency = 1}, + .uop[1] = { .type = UOP_MSTOREA, .latency = 1} }; -static const macro_op_t pmul_op = -{ - .nr_uops = 1, - .decode_type = DECODE_SIMPLE, - .uop[0] = {.type = UOP_MMX_MUL, .latency = 1} +static const macro_op_t pmul_op = { + .nr_uops = 1, + .decode_type = DECODE_SIMPLE, + .uop[0] = {.type = UOP_MMX_MUL, .latency = 1} }; -static const macro_op_t pmul_mem_op = -{ - .nr_uops = 2, - .decode_type = DECODE_COMPLEX, - .uop[0] = {.type = UOP_LOAD, .latency = 2}, - .uop[1] = {.type = UOP_MMX_MUL, .latency = 2} +static const macro_op_t pmul_mem_op = { + .nr_uops = 2, + .decode_type = DECODE_COMPLEX, + .uop[0] = {.type = UOP_LOAD, .latency = 2}, + .uop[1] = { .type = UOP_MMX_MUL, .latency = 2} }; -static const macro_op_t float_op = -{ - .nr_uops = 1, - .decode_type = DECODE_SIMPLE, - .uop[0] = {.type = UOP_FLOAT, .latency = 1} +static const macro_op_t float_op = { + .nr_uops = 1, + .decode_type = DECODE_SIMPLE, + .uop[0] = {.type = UOP_FLOAT, .latency = 1} }; -static const macro_op_t fadd_op = -{ - .nr_uops = 1, - .decode_type = DECODE_SIMPLE, - .uop[0] = {.type = UOP_FLOAT, .latency = 2} +static const macro_op_t fadd_op = { + .nr_uops = 1, + .decode_type = DECODE_SIMPLE, + .uop[0] = {.type = UOP_FLOAT, .latency = 2} }; -static const macro_op_t fmul_op = -{ - .nr_uops = 1, - .decode_type = DECODE_SIMPLE, - .uop[0] = {.type = UOP_ALUP0, .latency = 3} +static const macro_op_t fmul_op = { + .nr_uops = 1, + .decode_type = DECODE_SIMPLE, + .uop[0] = {.type = UOP_ALUP0, .latency = 3} }; -static const macro_op_t float2_op = -{ - .nr_uops = 2, - .decode_type = DECODE_COMPLEX, - .uop[0] = {.type = UOP_FLOAT, .latency = 1}, - .uop[1] = {.type = UOP_FLOAT, .latency = 1} +static const macro_op_t float2_op = { + .nr_uops = 2, + .decode_type = DECODE_COMPLEX, + .uop[0] = {.type = UOP_FLOAT, .latency = 1}, + .uop[1] = { .type = UOP_FLOAT, .latency = 1} }; -static const macro_op_t fchs_op = -{ - .nr_uops = 3, - .decode_type = DECODE_COMPLEX, - .uop[0] = {.type = UOP_FLOAT, .latency = 2}, - .uop[1] = {.type = UOP_FLOAT, .latency = 2}, - .uop[2] = {.type = UOP_FLOAT, .latency = 2} +static const macro_op_t fchs_op = { + .nr_uops = 3, + .decode_type = DECODE_COMPLEX, + .uop[0] = {.type = UOP_FLOAT, .latency = 2}, + .uop[1] = { .type = UOP_FLOAT, .latency = 2}, + .uop[2] = { .type = UOP_FLOAT, .latency = 2} }; -static const macro_op_t load_float_op = -{ - .nr_uops = 2, - .decode_type = DECODE_COMPLEX, - .uop[0] = {.type = UOP_FLOAD, .latency = 1}, - .uop[1] = {.type = UOP_FLOAT, .latency = 1} +static const macro_op_t load_float_op = { + .nr_uops = 2, + .decode_type = DECODE_COMPLEX, + .uop[0] = {.type = UOP_FLOAD, .latency = 1}, + .uop[1] = { .type = UOP_FLOAT, .latency = 1} }; -static const macro_op_t load_fadd_op = -{ - .nr_uops = 2, - .decode_type = DECODE_COMPLEX, - .uop[0] = {.type = UOP_FLOAD, .latency = 1}, - .uop[1] = {.type = UOP_FLOAT, .latency = 2} +static const macro_op_t load_fadd_op = { + .nr_uops = 2, + .decode_type = DECODE_COMPLEX, + .uop[0] = {.type = UOP_FLOAD, .latency = 1}, + .uop[1] = { .type = UOP_FLOAT, .latency = 2} }; -static const macro_op_t load_fmul_op = -{ - .nr_uops = 2, - .decode_type = DECODE_COMPLEX, - .uop[0] = {.type = UOP_LOAD, .latency = 1}, - .uop[1] = {.type = UOP_ALU, .latency = 4} +static const macro_op_t load_fmul_op = { + .nr_uops = 2, + .decode_type = DECODE_COMPLEX, + .uop[0] = {.type = UOP_LOAD, .latency = 1}, + .uop[1] = { .type = UOP_ALU, .latency = 4} }; -static const macro_op_t fstore_op = -{ - .nr_uops = 2, - .decode_type = DECODE_COMPLEX, - .uop[0] = {.type = UOP_FSTORED, .latency = 1}, - .uop[1] = {.type = UOP_FSTOREA, .latency = 1}, +static const macro_op_t fstore_op = { + .nr_uops = 2, + .decode_type = DECODE_COMPLEX, + .uop[0] = {.type = UOP_FSTORED, .latency = 1}, + .uop[1] = { .type = UOP_FSTOREA, .latency = 1}, }; -static const macro_op_t load_fiadd_op = -{ - .nr_uops = 7, - .decode_type = DECODE_COMPLEX, - .uop[0] = {.type = UOP_FLOAD, .latency = 1}, - .uop[1] = {.type = UOP_FLOAT, .latency = 1}, - .uop[2] = {.type = UOP_FLOAT, .latency = 1}, - .uop[3] = {.type = UOP_FLOAT, .latency = 1}, - .uop[4] = {.type = UOP_FLOAT, .latency = 1}, - .uop[5] = {.type = UOP_FLOAT, .latency = 1}, - .uop[6] = {.type = UOP_FLOAT, .latency = 1} +static const macro_op_t load_fiadd_op = { + .nr_uops = 7, + .decode_type = DECODE_COMPLEX, + .uop[0] = {.type = UOP_FLOAD, .latency = 1}, + .uop[1] = { .type = UOP_FLOAT, .latency = 1}, + .uop[2] = { .type = UOP_FLOAT, .latency = 1}, + .uop[3] = { .type = UOP_FLOAT, .latency = 1}, + .uop[4] = { .type = UOP_FLOAT, .latency = 1}, + .uop[5] = { .type = UOP_FLOAT, .latency = 1}, + .uop[6] = { .type = UOP_FLOAT, .latency = 1} }; -static const macro_op_t fdiv_op = -{ - .nr_uops = 1, - .decode_type = DECODE_SIMPLE, - .uop[0] = {.type = UOP_FLOAT, .latency = 37} +static const macro_op_t fdiv_op = { + .nr_uops = 1, + .decode_type = DECODE_SIMPLE, + .uop[0] = {.type = UOP_FLOAT, .latency = 37} }; -static const macro_op_t fdiv_mem_op = -{ - .nr_uops = 2, - .decode_type = DECODE_COMPLEX, - .uop[0] = {.type = UOP_FLOAD, .latency = 1}, - .uop[1] = {.type = UOP_FLOAT, .latency = 37} +static const macro_op_t fdiv_mem_op = { + .nr_uops = 2, + .decode_type = DECODE_COMPLEX, + .uop[0] = {.type = UOP_FLOAD, .latency = 1 }, + .uop[1] = { .type = UOP_FLOAT, .latency = 37} }; -static const macro_op_t fsin_op = -{ - .nr_uops = 1, - .decode_type = DECODE_SIMPLE, - .uop[0] = {.type = UOP_FLOAT, .latency = 62} +static const macro_op_t fsin_op = { + .nr_uops = 1, + .decode_type = DECODE_SIMPLE, + .uop[0] = {.type = UOP_FLOAT, .latency = 62} }; -static const macro_op_t fsqrt_op = -{ - .nr_uops = 1, - .decode_type = DECODE_SIMPLE, - .uop[0] = {.type = UOP_FLOAT, .latency = 69} +static const macro_op_t fsqrt_op = { + .nr_uops = 1, + .decode_type = DECODE_SIMPLE, + .uop[0] = {.type = UOP_FLOAT, .latency = 69} }; -static const macro_op_t fldcw_op = -{ - .nr_uops = 1, - .decode_type = DECODE_SIMPLE, - .uop[0] = {.type = UOP_FLOAT, .latency = 10} +static const macro_op_t fldcw_op = { + .nr_uops = 1, + .decode_type = DECODE_SIMPLE, + .uop[0] = {.type = UOP_FLOAT, .latency = 10} }; -static const macro_op_t complex_float_op = -{ - .nr_uops = 1, - .decode_type = DECODE_COMPLEX, - .uop[0] = {.type = UOP_FLOAT, .latency = 1} +static const macro_op_t complex_float_op = { + .nr_uops = 1, + .decode_type = DECODE_COMPLEX, + .uop[0] = {.type = UOP_FLOAT, .latency = 1} }; -static const macro_op_t complex_float_l_op = -{ - .nr_uops = 1, - .decode_type = DECODE_COMPLEX, - .uop[0] = {.type = UOP_FLOAT, .latency = 50} +static const macro_op_t complex_float_l_op = { + .nr_uops = 1, + .decode_type = DECODE_COMPLEX, + .uop[0] = {.type = UOP_FLOAT, .latency = 50} }; -static const macro_op_t flde_op = -{ - .nr_uops = 3, - .decode_type = DECODE_COMPLEX, - .uop[0] = {.type = UOP_FLOAD, .latency = 1}, - .uop[1] = {.type = UOP_FLOAD, .latency = 1}, - .uop[2] = {.type = UOP_FLOAT, .latency = 2} +static const macro_op_t flde_op = { + .nr_uops = 3, + .decode_type = DECODE_COMPLEX, + .uop[0] = {.type = UOP_FLOAD, .latency = 1}, + .uop[1] = { .type = UOP_FLOAD, .latency = 1}, + .uop[2] = { .type = UOP_FLOAT, .latency = 2} }; -static const macro_op_t fste_op = -{ - .nr_uops = 3, - .decode_type = DECODE_COMPLEX, - .uop[0] = {.type = UOP_FLOAT, .latency = 2}, - .uop[1] = {.type = UOP_FSTORED, .latency = 1}, - .uop[2] = {.type = UOP_FSTOREA, .latency = 1} +static const macro_op_t fste_op = { + .nr_uops = 3, + .decode_type = DECODE_COMPLEX, + .uop[0] = {.type = UOP_FLOAT, .latency = 2}, + .uop[1] = { .type = UOP_FSTORED, .latency = 1}, + .uop[2] = { .type = UOP_FSTOREA, .latency = 1} }; -static const macro_op_t complex_alu1_op = -{ - .nr_uops = 1, - .decode_type = DECODE_COMPLEX, - .uop[0] = {.type = UOP_ALU, .latency = 1} +static const macro_op_t complex_alu1_op = { + .nr_uops = 1, + .decode_type = DECODE_COMPLEX, + .uop[0] = {.type = UOP_ALU, .latency = 1} }; -static const macro_op_t alu2_op = -{ - .nr_uops = 2, - .decode_type = DECODE_COMPLEX, - .uop[0] = {.type = UOP_ALU, .latency = 1}, - .uop[1] = {.type = UOP_ALU, .latency = 1} +static const macro_op_t alu2_op = { + .nr_uops = 2, + .decode_type = DECODE_COMPLEX, + .uop[0] = {.type = UOP_ALU, .latency = 1}, + .uop[1] = { .type = UOP_ALU, .latency = 1} }; -static const macro_op_t alu3_op = -{ - .nr_uops = 3, - .decode_type = DECODE_COMPLEX, - .uop[0] = {.type = UOP_ALU, .latency = 1}, - .uop[1] = {.type = UOP_ALU, .latency = 1}, - .uop[2] = {.type = UOP_ALU, .latency = 1} +static const macro_op_t alu3_op = { + .nr_uops = 3, + .decode_type = DECODE_COMPLEX, + .uop[0] = {.type = UOP_ALU, .latency = 1}, + .uop[1] = { .type = UOP_ALU, .latency = 1}, + .uop[2] = { .type = UOP_ALU, .latency = 1} }; -static const macro_op_t alu6_op = -{ - .nr_uops = 6, - .decode_type = DECODE_COMPLEX, - .uop[0] = {.type = UOP_ALU, .latency = 1}, - .uop[1] = {.type = UOP_ALU, .latency = 1}, - .uop[2] = {.type = UOP_ALU, .latency = 1}, - .uop[3] = {.type = UOP_ALU, .latency = 1}, - .uop[4] = {.type = UOP_ALU, .latency = 1}, - .uop[5] = {.type = UOP_ALU, .latency = 1} +static const macro_op_t alu6_op = { + .nr_uops = 6, + .decode_type = DECODE_COMPLEX, + .uop[0] = {.type = UOP_ALU, .latency = 1}, + .uop[1] = { .type = UOP_ALU, .latency = 1}, + .uop[2] = { .type = UOP_ALU, .latency = 1}, + .uop[3] = { .type = UOP_ALU, .latency = 1}, + .uop[4] = { .type = UOP_ALU, .latency = 1}, + .uop[5] = { .type = UOP_ALU, .latency = 1} }; -static const macro_op_t complex_alup0_1_op = -{ - .nr_uops = 1, - .decode_type = DECODE_COMPLEX, - .uop[0] = {.type = UOP_ALUP0, .latency = 1} +static const macro_op_t complex_alup0_1_op = { + .nr_uops = 1, + .decode_type = DECODE_COMPLEX, + .uop[0] = {.type = UOP_ALUP0, .latency = 1} }; -static const macro_op_t alup0_3_op = -{ - .nr_uops = 3, - .decode_type = DECODE_COMPLEX, - .uop[0] = {.type = UOP_ALUP0, .latency = 1}, - .uop[1] = {.type = UOP_ALUP0, .latency = 1}, - .uop[2] = {.type = UOP_ALUP0, .latency = 1} +static const macro_op_t alup0_3_op = { + .nr_uops = 3, + .decode_type = DECODE_COMPLEX, + .uop[0] = {.type = UOP_ALUP0, .latency = 1}, + .uop[1] = { .type = UOP_ALUP0, .latency = 1}, + .uop[2] = { .type = UOP_ALUP0, .latency = 1} }; -static const macro_op_t alup0_6_op = -{ - .nr_uops = 6, - .decode_type = DECODE_COMPLEX, - .uop[0] = {.type = UOP_ALUP0, .latency = 1}, - .uop[1] = {.type = UOP_ALUP0, .latency = 1}, - .uop[2] = {.type = UOP_ALUP0, .latency = 1}, - .uop[3] = {.type = UOP_ALUP0, .latency = 1}, - .uop[4] = {.type = UOP_ALUP0, .latency = 1}, - .uop[5] = {.type = UOP_ALUP0, .latency = 1} +static const macro_op_t alup0_6_op = { + .nr_uops = 6, + .decode_type = DECODE_COMPLEX, + .uop[0] = {.type = UOP_ALUP0, .latency = 1}, + .uop[1] = { .type = UOP_ALUP0, .latency = 1}, + .uop[2] = { .type = UOP_ALUP0, .latency = 1}, + .uop[3] = { .type = UOP_ALUP0, .latency = 1}, + .uop[4] = { .type = UOP_ALUP0, .latency = 1}, + .uop[5] = { .type = UOP_ALUP0, .latency = 1} }; -static const macro_op_t arpl_op = -{ - .nr_uops = 2, - .decode_type = DECODE_COMPLEX, - .uop[0] = {.type = UOP_ALU, .latency = 3}, - .uop[1] = {.type = UOP_ALU, .latency = 3} +static const macro_op_t arpl_op = { + .nr_uops = 2, + .decode_type = DECODE_COMPLEX, + .uop[0] = {.type = UOP_ALU, .latency = 3}, + .uop[1] = { .type = UOP_ALU, .latency = 3} }; -static const macro_op_t bound_op = -{ - .nr_uops = 4, - .decode_type = DECODE_COMPLEX, - .uop[0] = {.type = UOP_LOAD, .latency = 1}, - .uop[1] = {.type = UOP_LOAD, .latency = 1}, - .uop[2] = {.type = UOP_ALU, .latency = 1}, - .uop[3] = {.type = UOP_ALU, .latency = 1} +static const macro_op_t bound_op = { + .nr_uops = 4, + .decode_type = DECODE_COMPLEX, + .uop[0] = {.type = UOP_LOAD, .latency = 1}, + .uop[1] = { .type = UOP_LOAD, .latency = 1}, + .uop[2] = { .type = UOP_ALU, .latency = 1}, + .uop[3] = { .type = UOP_ALU, .latency = 1} }; -static const macro_op_t bsx_op = -{ - .nr_uops = 1, - .decode_type = DECODE_COMPLEX, - .uop[0] = {.type = UOP_ALU, .latency = 10} +static const macro_op_t bsx_op = { + .nr_uops = 1, + .decode_type = DECODE_COMPLEX, + .uop[0] = {.type = UOP_ALU, .latency = 10} }; -static const macro_op_t call_far_op = -{ - .nr_uops = 4, - .decode_type = DECODE_COMPLEX, - .uop[0] = {.type = UOP_ALU, .latency = 3}, - .uop[1] = {.type = UOP_STORED, .latency = 1}, - .uop[2] = {.type = UOP_STOREA, .latency = 1}, - .uop[3] = {.type = UOP_BRANCH, .latency = 1} +static const macro_op_t call_far_op = { + .nr_uops = 4, + .decode_type = DECODE_COMPLEX, + .uop[0] = {.type = UOP_ALU, .latency = 3}, + .uop[1] = { .type = UOP_STORED, .latency = 1}, + .uop[2] = { .type = UOP_STOREA, .latency = 1}, + .uop[3] = { .type = UOP_BRANCH, .latency = 1} }; -static const macro_op_t cli_sti_op = -{ - .nr_uops = 1, - .decode_type = DECODE_COMPLEX, - .uop[0] = {.type = UOP_ALU, .latency = 7} +static const macro_op_t cli_sti_op = { + .nr_uops = 1, + .decode_type = DECODE_COMPLEX, + .uop[0] = {.type = UOP_ALU, .latency = 7} }; -static const macro_op_t cmps_op = -{ - .nr_uops = 3, - .decode_type = DECODE_COMPLEX, - .uop[0] = {.type = UOP_LOAD, .latency = 1}, - .uop[1] = {.type = UOP_ALU, .latency = 1}, - .uop[2] = {.type = UOP_ALU, .latency = 1} +static const macro_op_t cmps_op = { + .nr_uops = 3, + .decode_type = DECODE_COMPLEX, + .uop[0] = {.type = UOP_LOAD, .latency = 1}, + .uop[1] = { .type = UOP_ALU, .latency = 1}, + .uop[2] = { .type = UOP_ALU, .latency = 1} }; -static const macro_op_t cmpsb_op = -{ - .nr_uops = 3, - .decode_type = DECODE_COMPLEX, - .uop[0] = {.type = UOP_LOAD, .latency = 1}, - .uop[1] = {.type = UOP_ALUP0, .latency = 1}, - .uop[2] = {.type = UOP_ALU, .latency = 1} +static const macro_op_t cmpsb_op = { + .nr_uops = 3, + .decode_type = DECODE_COMPLEX, + .uop[0] = {.type = UOP_LOAD, .latency = 1}, + .uop[1] = { .type = UOP_ALUP0, .latency = 1}, + .uop[2] = { .type = UOP_ALU, .latency = 1} }; -static const macro_op_t cmpxchg_op = -{ - .nr_uops = 4, - .decode_type = DECODE_COMPLEX, - .uop[0] = {.type = UOP_LOAD, .latency = 1}, - .uop[1] = {.type = UOP_ALU, .latency = 1}, - .uop[2] = {.type = UOP_STORED, .latency = 1}, - .uop[3] = {.type = UOP_STOREA, .latency = 1} +static const macro_op_t cmpxchg_op = { + .nr_uops = 4, + .decode_type = DECODE_COMPLEX, + .uop[0] = {.type = UOP_LOAD, .latency = 1}, + .uop[1] = { .type = UOP_ALU, .latency = 1}, + .uop[2] = { .type = UOP_STORED, .latency = 1}, + .uop[3] = { .type = UOP_STOREA, .latency = 1} }; -static const macro_op_t cmpxchg_b_op = -{ - .nr_uops = 4, - .decode_type = DECODE_COMPLEX, - .uop[0] = {.type = UOP_LOAD, .latency = 1}, - .uop[1] = {.type = UOP_ALUP0, .latency = 1}, - .uop[2] = {.type = UOP_STORED, .latency = 1}, - .uop[3] = {.type = UOP_STOREA, .latency = 1} +static const macro_op_t cmpxchg_b_op = { + .nr_uops = 4, + .decode_type = DECODE_COMPLEX, + .uop[0] = {.type = UOP_LOAD, .latency = 1}, + .uop[1] = { .type = UOP_ALUP0, .latency = 1}, + .uop[2] = { .type = UOP_STORED, .latency = 1}, + .uop[3] = { .type = UOP_STOREA, .latency = 1} }; -static const macro_op_t complex_push_mem_op = -{ - .nr_uops = 2, - .decode_type = DECODE_COMPLEX, - .uop[0] = {.type = UOP_STORED, .latency = 1}, - .uop[1] = {.type = UOP_STOREA, .latency = 1} +static const macro_op_t complex_push_mem_op = { + .nr_uops = 2, + .decode_type = DECODE_COMPLEX, + .uop[0] = {.type = UOP_STORED, .latency = 1}, + .uop[1] = { .type = UOP_STOREA, .latency = 1} }; -static const macro_op_t cpuid_op = -{ - .nr_uops = 1, - .decode_type = DECODE_COMPLEX, - .uop[0] = {.type = UOP_ALU, .latency = 23} +static const macro_op_t cpuid_op = { + .nr_uops = 1, + .decode_type = DECODE_COMPLEX, + .uop[0] = {.type = UOP_ALU, .latency = 23} }; -static const macro_op_t div16_op = -{ - .nr_uops = 1, - .decode_type = DECODE_COMPLEX, - .uop[0] = {.type = UOP_ALUP0, .latency = 21} +static const macro_op_t div16_op = { + .nr_uops = 1, + .decode_type = DECODE_COMPLEX, + .uop[0] = {.type = UOP_ALUP0, .latency = 21} }; -static const macro_op_t div16_mem_op = -{ - .nr_uops = 2, - .decode_type = DECODE_COMPLEX, - .uop[0] = {.type = UOP_LOAD, .latency = 1}, - .uop[1] = {.type = UOP_ALUP0, .latency = 21} +static const macro_op_t div16_mem_op = { + .nr_uops = 2, + .decode_type = DECODE_COMPLEX, + .uop[0] = {.type = UOP_LOAD, .latency = 1 }, + .uop[1] = { .type = UOP_ALUP0, .latency = 21} }; -static const macro_op_t div32_op = -{ - .nr_uops = 1, - .decode_type = DECODE_COMPLEX, - .uop[0] = {.type = UOP_ALUP0, .latency = 37} +static const macro_op_t div32_op = { + .nr_uops = 1, + .decode_type = DECODE_COMPLEX, + .uop[0] = {.type = UOP_ALUP0, .latency = 37} }; -static const macro_op_t div32_mem_op = -{ - .nr_uops = 2, - .decode_type = DECODE_COMPLEX, - .uop[0] = {.type = UOP_LOAD, .latency = 1}, - .uop[1] = {.type = UOP_ALUP0, .latency = 37} +static const macro_op_t div32_mem_op = { + .nr_uops = 2, + .decode_type = DECODE_COMPLEX, + .uop[0] = {.type = UOP_LOAD, .latency = 1 }, + .uop[1] = { .type = UOP_ALUP0, .latency = 37} }; -static const macro_op_t emms_op = -{ - .nr_uops = 1, - .decode_type = DECODE_COMPLEX, - .uop[0] = {.type = UOP_ALU, .latency = 50} +static const macro_op_t emms_op = { + .nr_uops = 1, + .decode_type = DECODE_COMPLEX, + .uop[0] = {.type = UOP_ALU, .latency = 50} }; -static const macro_op_t enter_op = -{ - .nr_uops = 3, - .decode_type = DECODE_COMPLEX, - .uop[0] = {.type = UOP_STORED, .latency = 1}, - .uop[1] = {.type = UOP_STOREA, .latency = 1}, - .uop[2] = {.type = UOP_ALU, .latency = 10} +static const macro_op_t enter_op = { + .nr_uops = 3, + .decode_type = DECODE_COMPLEX, + .uop[0] = {.type = UOP_STORED, .latency = 1 }, + .uop[1] = { .type = UOP_STOREA, .latency = 1 }, + .uop[2] = { .type = UOP_ALU, .latency = 10} }; -static const macro_op_t femms_op = -{ - .nr_uops = 1, - .decode_type = DECODE_COMPLEX, - .uop[0] = {.type = UOP_ALU, .latency = 6} +static const macro_op_t femms_op = { + .nr_uops = 1, + .decode_type = DECODE_COMPLEX, + .uop[0] = {.type = UOP_ALU, .latency = 6} }; -static const macro_op_t in_op = -{ - .nr_uops = 1, - .decode_type = DECODE_COMPLEX, - .uop[0] = {.type = UOP_LOAD, .latency = 18} +static const macro_op_t in_op = { + .nr_uops = 1, + .decode_type = DECODE_COMPLEX, + .uop[0] = {.type = UOP_LOAD, .latency = 18} }; -static const macro_op_t ins_op = -{ - .nr_uops = 4, - .decode_type = DECODE_COMPLEX, - .uop[0] = {.type = UOP_LOAD, .latency = 18}, - .uop[1] = {.type = UOP_STORED, .latency = 1}, - .uop[2] = {.type = UOP_STOREA, .latency = 1}, - .uop[3] = {.type = UOP_ALU, .latency = 1} +static const macro_op_t ins_op = { + .nr_uops = 4, + .decode_type = DECODE_COMPLEX, + .uop[0] = {.type = UOP_LOAD, .latency = 18}, + .uop[1] = { .type = UOP_STORED, .latency = 1 }, + .uop[2] = { .type = UOP_STOREA, .latency = 1 }, + .uop[3] = { .type = UOP_ALU, .latency = 1 } }; -static const macro_op_t int_op = -{ - .nr_uops = 8, - .decode_type = DECODE_COMPLEX, - .uop[0] = {.type = UOP_ALU, .latency = 20}, - .uop[1] = {.type = UOP_STORED, .latency = 1}, - .uop[2] = {.type = UOP_STOREA, .latency = 1}, - .uop[3] = {.type = UOP_STORED, .latency = 1}, - .uop[4] = {.type = UOP_STOREA, .latency = 1}, - .uop[5] = {.type = UOP_STORED, .latency = 1}, - .uop[6] = {.type = UOP_STOREA, .latency = 1}, - .uop[7] = {.type = UOP_BRANCH, .latency = 1} +static const macro_op_t int_op = { + .nr_uops = 8, + .decode_type = DECODE_COMPLEX, + .uop[0] = {.type = UOP_ALU, .latency = 20}, + .uop[1] = { .type = UOP_STORED, .latency = 1 }, + .uop[2] = { .type = UOP_STOREA, .latency = 1 }, + .uop[3] = { .type = UOP_STORED, .latency = 1 }, + .uop[4] = { .type = UOP_STOREA, .latency = 1 }, + .uop[5] = { .type = UOP_STORED, .latency = 1 }, + .uop[6] = { .type = UOP_STOREA, .latency = 1 }, + .uop[7] = { .type = UOP_BRANCH, .latency = 1 } }; -static const macro_op_t iret_op = -{ - .nr_uops = 5, - .decode_type = DECODE_COMPLEX, - .uop[0] = {.type = UOP_LOAD, .latency = 3}, - .uop[1] = {.type = UOP_LOAD, .latency = 3}, - .uop[2] = {.type = UOP_LOAD, .latency = 3}, - .uop[3] = {.type = UOP_ALU, .latency = 20}, - .uop[4] = {.type = UOP_BRANCH, .latency = 1} +static const macro_op_t iret_op = { + .nr_uops = 5, + .decode_type = DECODE_COMPLEX, + .uop[0] = {.type = UOP_LOAD, .latency = 3 }, + .uop[1] = { .type = UOP_LOAD, .latency = 3 }, + .uop[2] = { .type = UOP_LOAD, .latency = 3 }, + .uop[3] = { .type = UOP_ALU, .latency = 20}, + .uop[4] = { .type = UOP_BRANCH, .latency = 1 } }; -static const macro_op_t invd_op = -{ - .nr_uops = 1, - .decode_type = DECODE_COMPLEX, - .uop[0] = {.type = UOP_ALU, .latency = 500} +static const macro_op_t invd_op = { + .nr_uops = 1, + .decode_type = DECODE_COMPLEX, + .uop[0] = {.type = UOP_ALU, .latency = 500} }; -static const macro_op_t jmp_far_op = -{ - .nr_uops = 2, - .decode_type = DECODE_COMPLEX, - .uop[0] = {.type = UOP_ALU, .latency = 3}, - .uop[1] = {.type = UOP_BRANCH, .latency = 1} +static const macro_op_t jmp_far_op = { + .nr_uops = 2, + .decode_type = DECODE_COMPLEX, + .uop[0] = {.type = UOP_ALU, .latency = 3}, + .uop[1] = { .type = UOP_BRANCH, .latency = 1} }; -static const macro_op_t lss_op = -{ - .nr_uops = 3, - .decode_type = DECODE_COMPLEX, - .uop[0] = {.type = UOP_LOAD, .latency = 1}, - .uop[1] = {.type = UOP_LOAD, .latency = 1}, - .uop[2] = {.type = UOP_ALU, .latency = 3} +static const macro_op_t lss_op = { + .nr_uops = 3, + .decode_type = DECODE_COMPLEX, + .uop[0] = {.type = UOP_LOAD, .latency = 1}, + .uop[1] = { .type = UOP_LOAD, .latency = 1}, + .uop[2] = { .type = UOP_ALU, .latency = 3} }; -static const macro_op_t mov_mem_seg_op = -{ - .nr_uops = 3, - .decode_type = DECODE_COMPLEX, - .uop[0] = {.type = UOP_LOAD, .latency = 1}, - .uop[1] = {.type = UOP_STORED, .latency = 1}, - .uop[2] = {.type = UOP_STOREA, .latency = 1}, +static const macro_op_t mov_mem_seg_op = { + .nr_uops = 3, + .decode_type = DECODE_COMPLEX, + .uop[0] = {.type = UOP_LOAD, .latency = 1}, + .uop[1] = { .type = UOP_STORED, .latency = 1}, + .uop[2] = { .type = UOP_STOREA, .latency = 1}, }; -static const macro_op_t mov_seg_mem_op = -{ - .nr_uops = 2, - .decode_type = DECODE_COMPLEX, - .uop[0] = {.type = UOP_LOAD, .latency = 1}, - .uop[1] = {.type = UOP_ALU, .latency = 3} +static const macro_op_t mov_seg_mem_op = { + .nr_uops = 2, + .decode_type = DECODE_COMPLEX, + .uop[0] = {.type = UOP_LOAD, .latency = 1}, + .uop[1] = { .type = UOP_ALU, .latency = 3} }; -static const macro_op_t mov_seg_reg_op = -{ - .nr_uops = 1, - .decode_type = DECODE_COMPLEX, - .uop[0] = {.type = UOP_ALU, .latency = 3} +static const macro_op_t mov_seg_reg_op = { + .nr_uops = 1, + .decode_type = DECODE_COMPLEX, + .uop[0] = {.type = UOP_ALU, .latency = 3} }; -static const macro_op_t mul_op = -{ - .nr_uops = 1, - .decode_type = DECODE_SIMPLE, - .uop[0] = {.type = UOP_ALUP0, .latency = 1} +static const macro_op_t mul_op = { + .nr_uops = 1, + .decode_type = DECODE_SIMPLE, + .uop[0] = {.type = UOP_ALUP0, .latency = 1} }; -static const macro_op_t mul_mem_op = -{ - .nr_uops = 2, - .decode_type = DECODE_COMPLEX, - .uop[0] = {.type = UOP_LOAD, .latency = 1}, - .uop[1] = {.type = UOP_ALUP0, .latency = 1} +static const macro_op_t mul_mem_op = { + .nr_uops = 2, + .decode_type = DECODE_COMPLEX, + .uop[0] = {.type = UOP_LOAD, .latency = 1}, + .uop[1] = { .type = UOP_ALUP0, .latency = 1} }; -static const macro_op_t mul64_op = -{ - .nr_uops = 3, - .decode_type = DECODE_COMPLEX, - .uop[0] = {.type = UOP_ALUP0, .latency = 1}, - .uop[1] = {.type = UOP_ALUP0, .latency = 1}, - .uop[2] = {.type = UOP_ALUP0, .latency = 1} +static const macro_op_t mul64_op = { + .nr_uops = 3, + .decode_type = DECODE_COMPLEX, + .uop[0] = {.type = UOP_ALUP0, .latency = 1}, + .uop[1] = { .type = UOP_ALUP0, .latency = 1}, + .uop[2] = { .type = UOP_ALUP0, .latency = 1} }; -static const macro_op_t mul64_mem_op = -{ - .nr_uops = 4, - .decode_type = DECODE_COMPLEX, - .uop[0] = {.type = UOP_LOAD, .latency = 1}, - .uop[1] = {.type = UOP_ALUP0, .latency = 1}, - .uop[2] = {.type = UOP_ALUP0, .latency = 1}, - .uop[3] = {.type = UOP_ALUP0, .latency = 1} +static const macro_op_t mul64_mem_op = { + .nr_uops = 4, + .decode_type = DECODE_COMPLEX, + .uop[0] = {.type = UOP_LOAD, .latency = 1}, + .uop[1] = { .type = UOP_ALUP0, .latency = 1}, + .uop[2] = { .type = UOP_ALUP0, .latency = 1}, + .uop[3] = { .type = UOP_ALUP0, .latency = 1} }; -static const macro_op_t out_op = -{ - .nr_uops = 1, - .decode_type = DECODE_COMPLEX, - .uop[0] = {.type = UOP_ALU, .latency = 18} +static const macro_op_t out_op = { + .nr_uops = 1, + .decode_type = DECODE_COMPLEX, + .uop[0] = {.type = UOP_ALU, .latency = 18} }; -static const macro_op_t outs_op = -{ - .nr_uops = 3, - .decode_type = DECODE_COMPLEX, - .uop[0] = {.type = UOP_LOAD, .latency = 1}, - .uop[1] = {.type = UOP_ALU, .latency = 18} +static const macro_op_t outs_op = { + .nr_uops = 3, + .decode_type = DECODE_COMPLEX, + .uop[0] = {.type = UOP_LOAD, .latency = 1 }, + .uop[1] = { .type = UOP_ALU, .latency = 18} }; -static const macro_op_t pusha_op = -{ - .nr_uops = 8, - .decode_type = DECODE_COMPLEX, - .uop[0] = {.type = UOP_STORED, .latency = 2}, - .uop[1] = {.type = UOP_STOREA, .latency = 2}, - .uop[2] = {.type = UOP_STORED, .latency = 2}, - .uop[3] = {.type = UOP_STOREA, .latency = 2}, - .uop[4] = {.type = UOP_STORED, .latency = 2}, - .uop[5] = {.type = UOP_STOREA, .latency = 2}, - .uop[6] = {.type = UOP_STORED, .latency = 2}, - .uop[7] = {.type = UOP_STOREA, .latency = 2} +static const macro_op_t pusha_op = { + .nr_uops = 8, + .decode_type = DECODE_COMPLEX, + .uop[0] = {.type = UOP_STORED, .latency = 2}, + .uop[1] = { .type = UOP_STOREA, .latency = 2}, + .uop[2] = { .type = UOP_STORED, .latency = 2}, + .uop[3] = { .type = UOP_STOREA, .latency = 2}, + .uop[4] = { .type = UOP_STORED, .latency = 2}, + .uop[5] = { .type = UOP_STOREA, .latency = 2}, + .uop[6] = { .type = UOP_STORED, .latency = 2}, + .uop[7] = { .type = UOP_STOREA, .latency = 2} }; -static const macro_op_t popa_op = -{ - .nr_uops = 8, - .decode_type = DECODE_COMPLEX, - .uop[0] = {.type = UOP_LOAD, .latency = 1}, - .uop[1] = {.type = UOP_LOAD, .latency = 1}, - .uop[2] = {.type = UOP_LOAD, .latency = 1}, - .uop[3] = {.type = UOP_LOAD, .latency = 1}, - .uop[4] = {.type = UOP_LOAD, .latency = 1}, - .uop[5] = {.type = UOP_LOAD, .latency = 1}, - .uop[6] = {.type = UOP_LOAD, .latency = 1}, - .uop[7] = {.type = UOP_LOAD, .latency = 1} +static const macro_op_t popa_op = { + .nr_uops = 8, + .decode_type = DECODE_COMPLEX, + .uop[0] = {.type = UOP_LOAD, .latency = 1}, + .uop[1] = { .type = UOP_LOAD, .latency = 1}, + .uop[2] = { .type = UOP_LOAD, .latency = 1}, + .uop[3] = { .type = UOP_LOAD, .latency = 1}, + .uop[4] = { .type = UOP_LOAD, .latency = 1}, + .uop[5] = { .type = UOP_LOAD, .latency = 1}, + .uop[6] = { .type = UOP_LOAD, .latency = 1}, + .uop[7] = { .type = UOP_LOAD, .latency = 1} }; -static const macro_op_t popf_op = -{ - .nr_uops = 3, - .decode_type = DECODE_COMPLEX, - .uop[0] = {.type = UOP_LOAD, .latency = 1}, - .uop[1] = {.type = UOP_ALU, .latency = 6}, - .uop[2] = {.type = UOP_ALUP0, .latency = 10} +static const macro_op_t popf_op = { + .nr_uops = 3, + .decode_type = DECODE_COMPLEX, + .uop[0] = {.type = UOP_LOAD, .latency = 1 }, + .uop[1] = { .type = UOP_ALU, .latency = 6 }, + .uop[2] = { .type = UOP_ALUP0, .latency = 10} }; -static const macro_op_t pushf_op = -{ - .nr_uops = 3, - .decode_type = DECODE_COMPLEX, - .uop[0] = {.type = UOP_ALUP0, .latency = 1}, - .uop[1] = {.type = UOP_STORED, .latency = 1}, - .uop[2] = {.type = UOP_STOREA, .latency = 1} +static const macro_op_t pushf_op = { + .nr_uops = 3, + .decode_type = DECODE_COMPLEX, + .uop[0] = {.type = UOP_ALUP0, .latency = 1}, + .uop[1] = { .type = UOP_STORED, .latency = 1}, + .uop[2] = { .type = UOP_STOREA, .latency = 1} }; -static const macro_op_t ret_op = -{ - .nr_uops = 2, - .decode_type = DECODE_COMPLEX, - .uop[0] = {.type = UOP_LOAD, .latency = 1}, - .uop[1] = {.type = UOP_BRANCH, .latency = 1} +static const macro_op_t ret_op = { + .nr_uops = 2, + .decode_type = DECODE_COMPLEX, + .uop[0] = {.type = UOP_LOAD, .latency = 1}, + .uop[1] = { .type = UOP_BRANCH, .latency = 1} }; -static const macro_op_t retf_op = -{ - .nr_uops = 3, - .decode_type = DECODE_COMPLEX, - .uop[0] = {.type = UOP_LOAD, .latency = 1}, - .uop[1] = {.type = UOP_ALU, .latency = 3}, - .uop[2] = {.type = UOP_BRANCH, .latency = 1} +static const macro_op_t retf_op = { + .nr_uops = 3, + .decode_type = DECODE_COMPLEX, + .uop[0] = {.type = UOP_LOAD, .latency = 1}, + .uop[1] = { .type = UOP_ALU, .latency = 3}, + .uop[2] = { .type = UOP_BRANCH, .latency = 1} }; -static const macro_op_t scas_op = -{ - .nr_uops = 2, - .decode_type = DECODE_COMPLEX, - .uop[0] = {.type = UOP_LOAD, .latency = 1}, - .uop[1] = {.type = UOP_ALU, .latency = 1} +static const macro_op_t scas_op = { + .nr_uops = 2, + .decode_type = DECODE_COMPLEX, + .uop[0] = {.type = UOP_LOAD, .latency = 1}, + .uop[1] = { .type = UOP_ALU, .latency = 1} }; -static const macro_op_t scasb_op = -{ - .nr_uops = 2, - .decode_type = DECODE_COMPLEX, - .uop[0] = {.type = UOP_LOAD, .latency = 1}, - .uop[1] = {.type = UOP_ALU, .latency = 1} +static const macro_op_t scasb_op = { + .nr_uops = 2, + .decode_type = DECODE_COMPLEX, + .uop[0] = {.type = UOP_LOAD, .latency = 1}, + .uop[1] = { .type = UOP_ALU, .latency = 1} }; -static const macro_op_t setcc_mem_op = -{ - .nr_uops = 4, - .decode_type = DECODE_COMPLEX, - .uop[0] = {.type = UOP_ALUP0, .latency = 1}, - .uop[1] = {.type = UOP_ALUP0, .latency = 1}, - .uop[2] = {.type = UOP_FSTORED, .latency = 1}, - .uop[3] = {.type = UOP_FSTOREA, .latency = 1} +static const macro_op_t setcc_mem_op = { + .nr_uops = 4, + .decode_type = DECODE_COMPLEX, + .uop[0] = {.type = UOP_ALUP0, .latency = 1}, + .uop[1] = { .type = UOP_ALUP0, .latency = 1}, + .uop[2] = { .type = UOP_FSTORED, .latency = 1}, + .uop[3] = { .type = UOP_FSTOREA, .latency = 1} }; -static const macro_op_t setcc_reg_op = -{ - .nr_uops = 3, - .decode_type = DECODE_COMPLEX, - .uop[0] = {.type = UOP_ALUP0, .latency = 1}, - .uop[1] = {.type = UOP_ALUP0, .latency = 1}, - .uop[2] = {.type = UOP_ALU, .latency = 1} +static const macro_op_t setcc_reg_op = { + .nr_uops = 3, + .decode_type = DECODE_COMPLEX, + .uop[0] = {.type = UOP_ALUP0, .latency = 1}, + .uop[1] = { .type = UOP_ALUP0, .latency = 1}, + .uop[2] = { .type = UOP_ALU, .latency = 1} }; -static const macro_op_t test_mem_op = -{ - .nr_uops = 2, - .decode_type = DECODE_COMPLEX, - .uop[0] = {.type = UOP_LOAD, .latency = 1}, - .uop[1] = {.type = UOP_ALU, .latency = 1} +static const macro_op_t test_mem_op = { + .nr_uops = 2, + .decode_type = DECODE_COMPLEX, + .uop[0] = {.type = UOP_LOAD, .latency = 1}, + .uop[1] = { .type = UOP_ALU, .latency = 1} }; -static const macro_op_t test_mem_b_op = -{ - .nr_uops = 2, - .decode_type = DECODE_COMPLEX, - .uop[0] = {.type = UOP_LOAD, .latency = 1}, - .uop[1] = {.type = UOP_ALUP0, .latency = 1} +static const macro_op_t test_mem_b_op = { + .nr_uops = 2, + .decode_type = DECODE_COMPLEX, + .uop[0] = {.type = UOP_LOAD, .latency = 1}, + .uop[1] = { .type = UOP_ALUP0, .latency = 1} }; -static const macro_op_t xchg_mem_op = -{ - .nr_uops = 4, - .decode_type = DECODE_COMPLEX, - .uop[0] = {.type = UOP_LOAD, .latency = 1}, - .uop[1] = {.type = UOP_STORED, .latency = 1}, - .uop[2] = {.type = UOP_STOREA, .latency = 1}, - .uop[3] = {.type = UOP_ALU, .latency = 1} +static const macro_op_t xchg_mem_op = { + .nr_uops = 4, + .decode_type = DECODE_COMPLEX, + .uop[0] = {.type = UOP_LOAD, .latency = 1}, + .uop[1] = { .type = UOP_STORED, .latency = 1}, + .uop[2] = { .type = UOP_STOREA, .latency = 1}, + .uop[3] = { .type = UOP_ALU, .latency = 1} }; -static const macro_op_t xlat_op = -{ - .nr_uops = 2, - .decode_type = DECODE_COMPLEX, - .uop[0] = {.type = UOP_ALU, .latency = 1}, - .uop[1] = {.type = UOP_LOAD, .latency = 1} +static const macro_op_t xlat_op = { + .nr_uops = 2, + .decode_type = DECODE_COMPLEX, + .uop[0] = {.type = UOP_ALU, .latency = 1}, + .uop[1] = { .type = UOP_LOAD, .latency = 1} }; -static const macro_op_t wbinvd_op = -{ - .nr_uops = 1, - .decode_type = DECODE_COMPLEX, - .uop[0] = {.type = UOP_ALU, .latency = 10000} +static const macro_op_t wbinvd_op = { + .nr_uops = 1, + .decode_type = DECODE_COMPLEX, + .uop[0] = {.type = UOP_ALU, .latency = 10000} }; #define INVALID NULL -static const macro_op_t *opcode_timings[256] = -{ +static const macro_op_t *opcode_timings[256] = { + // clang-format off /* ADD ADD ADD ADD*/ /*00*/ &alup0_store_op, &alu_store_op, &load_alup0_op, &load_alu_op, /* ADD ADD PUSH ES POP ES*/ @@ -1033,10 +920,11 @@ static const macro_op_t *opcode_timings[256] = &complex_alu1_op, &complex_alu1_op, &cli_sti_op, &cli_sti_op, /* CLD STD INCDEC*/ &complex_alu1_op, &complex_alu1_op, &alup0_store_op, INVALID + // clang-format on }; -static const macro_op_t *opcode_timings_mod3[256] = -{ +static const macro_op_t *opcode_timings_mod3[256] = { + // clang-format off /* ADD ADD ADD ADD*/ /*00*/ &alup0_op, &alu_op, &alup0_op, &alu_op, /* ADD ADD PUSH ES POP ES*/ @@ -1152,7 +1040,7 @@ static const macro_op_t *opcode_timings_mod3[256] = &alup0_6_op, &alup0_3_op, &complex_alup0_1_op, &xlat_op, INVALID, INVALID, INVALID, INVALID, INVALID, INVALID, INVALID, INVALID, - + /* LOOPNE LOOPE LOOP JCXZ*/ /*e0*/ &loop_op, &loop_op, &loop_op, &loop_op, /* IN AL IN AX OUT_AL OUT_AX*/ @@ -1170,10 +1058,11 @@ static const macro_op_t *opcode_timings_mod3[256] = &complex_alu1_op, &complex_alu1_op, &cli_sti_op, &cli_sti_op, /* CLD STD INCDEC*/ &complex_alu1_op, &complex_alu1_op, &complex_alup0_1_op, INVALID + // clang-format on }; -static const macro_op_t *opcode_timings_0f[256] = -{ +static const macro_op_t *opcode_timings_0f[256] = { + // clang-format off /*00*/ &alu6_op, &alu6_op, &alu6_op, &alu6_op, INVALID, &alu6_op, &alu6_op, INVALID, &invd_op, &wbinvd_op, INVALID, INVALID, @@ -1253,9 +1142,10 @@ static const macro_op_t *opcode_timings_0f[256] = INVALID, &pmul_mem_op, INVALID, INVALID, &load_mmx_op, &load_mmx_op, &load_mmx_op, INVALID, &load_mmx_op, &load_mmx_op, &load_mmx_op, INVALID, + // clang-format on }; -static const macro_op_t *opcode_timings_0f_mod3[256] = -{ +static const macro_op_t *opcode_timings_0f_mod3[256] = { + // clang-format off /*00*/ &alu6_op, &alu6_op, &alu6_op, &alu6_op, INVALID, &alu6_op, &alu6_op, INVALID, &invd_op, &wbinvd_op, INVALID, INVALID, @@ -1339,113 +1229,131 @@ static const macro_op_t *opcode_timings_0f_mod3[256] = static const macro_op_t *opcode_timings_shift[8] = { + // clang-format off &alu_store_op, &alu_store_op, &alu_store_op, &alu_store_op, &alu_store_op, &alu_store_op, &alu_store_op, &alu_store_op + // clang-format on }; -static const macro_op_t *opcode_timings_shift_b[8] = -{ +static const macro_op_t *opcode_timings_shift_b[8] = { + // clang-format off &alup0_store_op, &alup0_store_op, &alup0_store_op, &alup0_store_op, &alup0_store_op, &alup0_store_op, &alup0_store_op, &alup0_store_op + // clang-format on }; -static const macro_op_t *opcode_timings_shift_mod3[8] = -{ +static const macro_op_t *opcode_timings_shift_mod3[8] = { + // clang-format off &complex_alu1_op, &complex_alu1_op, &complex_alu1_op, &complex_alu1_op, &alu_op, &alu_op, &alu_op, &alu_op + // clang-format on }; -static const macro_op_t *opcode_timings_shift_b_mod3[8] = -{ +static const macro_op_t *opcode_timings_shift_b_mod3[8] = { + // clang-format off &complex_alup0_1_op, &complex_alup0_1_op, &complex_alup0_1_op, &complex_alup0_1_op, &alup0_op, &alup0_op, &alup0_op, &alup0_op + // clang-format on }; -static const macro_op_t *opcode_timings_80[8] = -{ +static const macro_op_t *opcode_timings_80[8] = { + // clang-format off &alup0_store_op, &alup0_store_op, &alup0_store_op, &alup0_store_op, &alup0_store_op, &alup0_store_op, &alup0_store_op, &alup0_store_op, + // clang-format on }; -static const macro_op_t *opcode_timings_80_mod3[8] = -{ +static const macro_op_t *opcode_timings_80_mod3[8] = { + // clang-format off &alup0_op, &alup0_op, &alup0_store_op, &alup0_store_op, &alup0_op, &alup0_op, &alup0_op, &alup0_op, + // clang-format on }; -static const macro_op_t *opcode_timings_8x[8] = -{ +static const macro_op_t *opcode_timings_8x[8] = { + // clang-format off &alu_store_op, &alu_store_op, &alu_store_op, &alu_store_op, &alu_store_op, &alu_store_op, &alu_store_op, &alu_store_op, -}; -static const macro_op_t *opcode_timings_8x_mod3[8] = -{ + // clang-format on +}; +static const macro_op_t *opcode_timings_8x_mod3[8] = { + // clang-format off &alu_op, &alu_op, &alu_store_op, &alu_store_op, &alu_op, &alu_op, &alu_op, &alu_op, + // clang-format on }; -static const macro_op_t *opcode_timings_f6[8] = -{ +static const macro_op_t *opcode_timings_f6[8] = { + // clang-format off /* TST NOT NEG*/ &test_mem_imm_b_op, INVALID, &alup0_store_op, &alup0_store_op, /* MUL IMUL DIV IDIV*/ &mul_mem_op, &mul_mem_op, &div16_mem_op, &div16_mem_op, + // clang-format on }; -static const macro_op_t *opcode_timings_f6_mod3[8] = -{ +static const macro_op_t *opcode_timings_f6_mod3[8] = { + // clang-format off /* TST NOT NEG*/ &test_reg_b_op, INVALID, &alup0_op, &alup0_op, /* MUL IMUL DIV IDIV*/ &mul_op, &mul_op, &div16_op, &div16_op, + // clang-format on }; -static const macro_op_t *opcode_timings_f7[8] = -{ +static const macro_op_t *opcode_timings_f7[8] = { + // clang-format off /* TST NOT NEG*/ &test_mem_imm_op, INVALID, &alu_store_op, &alu_store_op, /* MUL IMUL DIV IDIV*/ &mul64_mem_op, &mul64_mem_op, &div32_mem_op, &div32_mem_op, + // clang-format on }; -static const macro_op_t *opcode_timings_f7_mod3[8] = -{ +static const macro_op_t *opcode_timings_f7_mod3[8] = { + // clang-format off /* TST NOT NEG*/ &test_reg_op, INVALID, &alu_op, &alu_op, /* MUL IMUL DIV IDIV*/ &mul64_op, &mul64_op, &div32_op, &div32_op, + // clang-format on }; -static const macro_op_t *opcode_timings_ff[8] = -{ +static const macro_op_t *opcode_timings_ff[8] = { + // clang-format off /* INC DEC CALL CALL far*/ &alu_store_op, &alu_store_op, &store_op, &call_far_op, /* JMP JMP far PUSH*/ &branch_op, &jmp_far_op, &push_mem_op, INVALID + // clang-format on }; -static const macro_op_t *opcode_timings_ff_mod3[8] = -{ +static const macro_op_t *opcode_timings_ff_mod3[8] = { + // clang-format off /* INC DEC CALL CALL far*/ &complex_alu1_op, &complex_alu1_op, &store_op, &call_far_op, /* JMP JMP far PUSH*/ &branch_op, &jmp_far_op, &complex_push_mem_op, INVALID + // clang-format on }; -static const macro_op_t *opcode_timings_d8[8] = -{ +static const macro_op_t *opcode_timings_d8[8] = { + // clang-format off /* FADDs FMULs FCOMs FCOMPs*/ &load_fadd_op, &load_fmul_op, &load_float_op, &load_float_op, /* FSUBs FSUBRs FDIVs FDIVRs*/ &load_float_op, &load_float_op, &fdiv_mem_op, &fdiv_mem_op, + // clang-format on }; -static const macro_op_t *opcode_timings_d8_mod3[8] = -{ +static const macro_op_t *opcode_timings_d8_mod3[8] = { + // clang-format off /* FADD FMUL FCOM FCOMP*/ &fadd_op, &fmul_op, &float_op, &float_op, /* FSUB FSUBR FDIV FDIVR*/ &float_op, &float_op, &fdiv_op, &fdiv_op, + // clang-format on }; -static const macro_op_t *opcode_timings_d9[8] = -{ +static const macro_op_t *opcode_timings_d9[8] = { + // clang-format off /* FLDs FSTs FSTPs*/ &load_float_op, INVALID, &fstore_op, &fstore_op, /* FLDENV FLDCW FSTENV FSTCW*/ &complex_float_l_op, &fldcw_op, &complex_float_l_op, &complex_float_op + // clang-format on }; -static const macro_op_t *opcode_timings_d9_mod3[64] = -{ +static const macro_op_t *opcode_timings_d9_mod3[64] = { + // clang-format off /*FLD*/ &float_op, &float_op, &float_op, &float_op, &float_op, &float_op, &float_op, &float_op, @@ -1474,31 +1382,35 @@ static const macro_op_t *opcode_timings_d9_mod3[64] = &fdiv_op, INVALID, &fsqrt_op, &fsin_op, /* opFRNDINT opFSCALE opFSIN opFCOS*/ &float_op, &fdiv_op, &fsin_op, &fsin_op + // clang-format on }; -static const macro_op_t *opcode_timings_da[8] = -{ +static const macro_op_t *opcode_timings_da[8] = { + // clang-format off /* FIADDl FIMULl FICOMl FICOMPl*/ &load_fadd_op, &load_fmul_op, &load_float_op, &load_float_op, /* FISUBl FISUBRl FIDIVl FIDIVRl*/ &load_float_op, &load_float_op, &fdiv_mem_op, &fdiv_mem_op, + // clang-format on }; -static const macro_op_t *opcode_timings_da_mod3[8] = -{ +static const macro_op_t *opcode_timings_da_mod3[8] = { + // clang-format off INVALID, INVALID, INVALID, INVALID, /* FCOMPP*/ INVALID, &float_op, INVALID, INVALID + // clang-format on }; -static const macro_op_t *opcode_timings_db[8] = -{ +static const macro_op_t *opcode_timings_db[8] = { + // clang-format off /* FLDil FSTil FSTPil*/ &load_float_op, INVALID, &fstore_op, &fstore_op, /* FLDe FSTPe*/ INVALID, &flde_op, INVALID, &fste_op + // clang-format on }; -static const macro_op_t *opcode_timings_db_mod3[64] = -{ +static const macro_op_t *opcode_timings_db_mod3[64] = { + // clang-format off INVALID, INVALID, INVALID, INVALID, INVALID, INVALID, INVALID, INVALID, @@ -1524,153 +1436,152 @@ static const macro_op_t *opcode_timings_db_mod3[64] = INVALID, INVALID, INVALID, INVALID, INVALID, INVALID, INVALID, INVALID, + // clang-format on }; -static const macro_op_t *opcode_timings_dc[8] = -{ +static const macro_op_t *opcode_timings_dc[8] = { + // clang-format off /* FADDd FMULd FCOMd FCOMPd*/ &load_fadd_op, &load_fmul_op, &load_float_op, &load_float_op, /* FSUBd FSUBRd FDIVd FDIVRd*/ &load_float_op, &load_float_op, &fdiv_mem_op, &fdiv_mem_op, + // clang-format on }; -static const macro_op_t *opcode_timings_dc_mod3[8] = -{ +static const macro_op_t *opcode_timings_dc_mod3[8] = { + // clang-format off /* opFADDr opFMULr*/ &fadd_op, &fmul_op, INVALID, INVALID, /* opFSUBRr opFSUBr opFDIVRr opFDIVr*/ &float_op, &float_op, &fdiv_op, &fdiv_op + // clang-format on }; -static const macro_op_t *opcode_timings_dd[8] = -{ +static const macro_op_t *opcode_timings_dd[8] = { + // clang-format off /* FLDd FSTd FSTPd*/ &load_float_op, INVALID, &fstore_op, &fstore_op, /* FRSTOR FSAVE FSTSW*/ &complex_float_l_op, INVALID, &complex_float_l_op, &complex_float_l_op + // clang-format on }; -static const macro_op_t *opcode_timings_dd_mod3[8] = -{ +static const macro_op_t *opcode_timings_dd_mod3[8] = { + // clang-format off /* FFFREE FST FSTP*/ &float_op, INVALID, &float_op, &float_op, /* FUCOM FUCOMP*/ &float_op, &float_op, INVALID, INVALID + // clang-format on }; -static const macro_op_t *opcode_timings_de[8] = -{ +static const macro_op_t *opcode_timings_de[8] = { + // clang-format off /* FIADDw FIMULw FICOMw FICOMPw*/ &load_fiadd_op, &load_fiadd_op, &load_fiadd_op, &load_fiadd_op, /* FISUBw FISUBRw FIDIVw FIDIVRw*/ &load_fiadd_op, &load_fiadd_op, &load_fiadd_op, &load_fiadd_op, + // clang-format on }; -static const macro_op_t *opcode_timings_de_mod3[8] = -{ +static const macro_op_t *opcode_timings_de_mod3[8] = { + // clang-format off /* FADDP FMULP FCOMPP*/ &fadd_op, &fmul_op, INVALID, &float_op, /* FSUBP FSUBRP FDIVP FDIVRP*/ &float_op, &float_op, &fdiv_op, &fdiv_op, + // clang-format on }; -static const macro_op_t *opcode_timings_df[8] = -{ +static const macro_op_t *opcode_timings_df[8] = { + // clang-format off /* FILDiw FISTiw FISTPiw*/ &load_float_op, INVALID, &fstore_op, &fstore_op, /* FILDiq FBSTP FISTPiq*/ INVALID, &load_float_op, &complex_float_l_op, &fstore_op, + // clang-format on }; -static const macro_op_t *opcode_timings_df_mod3[8] = -{ +static const macro_op_t *opcode_timings_df_mod3[8] = { + // clang-format off INVALID, INVALID, INVALID, INVALID, /* FSTSW AX*/ &float_op, INVALID, INVALID, INVALID + // clang-format on }; - static uint8_t last_prefix; -static int prefixes; +static int prefixes; static int decode_timestamp; static int last_complete_timestamp; -typedef struct p6_unit_t -{ - uint32_t uop_mask; - double first_available_cycle; +typedef struct p6_unit_t { + uint32_t uop_mask; + double first_available_cycle; } p6_unit_t; -static int nr_units; +static int nr_units; static p6_unit_t *units; /*Pentium Pro has no MMX*/ -static p6_unit_t ppro_units[] = -{ - {.uop_mask = (1 << UOP_ALU) | (1 << UOP_ALUP0) | (1 << UOP_FLOAT)}, /*Port 0*/ - {.uop_mask = (1 << UOP_ALU) | (1 << UOP_BRANCH)}, /*Port 1*/ - {.uop_mask = (1 << UOP_LOAD) | (1 << UOP_FLOAD)}, /*Port 2*/ - {.uop_mask = (1 << UOP_STORED) | (1 << UOP_FSTORED)}, /*Port 3*/ - {.uop_mask = (1 << UOP_STOREA) | (1 << UOP_FSTOREA)}, /*Port 4*/ +static p6_unit_t ppro_units[] = { + { .uop_mask = (1 << UOP_ALU) | (1 << UOP_ALUP0) | (1 << UOP_FLOAT) }, /*Port 0*/ + { .uop_mask = (1 << UOP_ALU) | (1 << UOP_BRANCH) }, /*Port 1*/ + { .uop_mask = (1 << UOP_LOAD) | (1 << UOP_FLOAD) }, /*Port 2*/ + { .uop_mask = (1 << UOP_STORED) | (1 << UOP_FSTORED) }, /*Port 3*/ + { .uop_mask = (1 << UOP_STOREA) | (1 << UOP_FSTOREA) }, /*Port 4*/ }; #define NR_PPRO_UNITS (sizeof(ppro_units) / sizeof(p6_unit_t)) /*Pentium II/Celeron assigns the multiplier to port 0, the shifter to port 1, and shares the MMX ALU*/ -static p6_unit_t p2_units[] = -{ - {.uop_mask = (1 << UOP_ALU) | (1 << UOP_ALUP0) | (1 << UOP_FLOAT) | /*Port 0*/ - (1 << UOP_MMX) | (1 << UOP_MMX_MUL)}, - {.uop_mask = (1 << UOP_ALU) | (1 << UOP_BRANCH) | /*Port 1*/ - (1 << UOP_MMX) | (1 << UOP_MMX_SHIFT)}, - {.uop_mask = (1 << UOP_LOAD) | (1 << UOP_FLOAD) | (1 << UOP_MLOAD)}, /*Port 2*/ - {.uop_mask = (1 << UOP_STORED) | (1 << UOP_FSTORED) | (1 << UOP_MSTORED)}, /*Port 3*/ - {.uop_mask = (1 << UOP_STOREA) | (1 << UOP_FSTOREA) | (1 << UOP_MSTOREA)}, /*Port 4*/ +static p6_unit_t p2_units[] = { + { .uop_mask = (1 << UOP_ALU) | (1 << UOP_ALUP0) | (1 << UOP_FLOAT) | /*Port 0*/ + (1 << UOP_MMX) | (1 << UOP_MMX_MUL) }, + { .uop_mask = (1 << UOP_ALU) | (1 << UOP_BRANCH) | /*Port 1*/ + (1 << UOP_MMX) | (1 << UOP_MMX_SHIFT) }, + { .uop_mask = (1 << UOP_LOAD) | (1 << UOP_FLOAD) | (1 << UOP_MLOAD) }, /*Port 2*/ + { .uop_mask = (1 << UOP_STORED) | (1 << UOP_FSTORED) | (1 << UOP_MSTORED) }, /*Port 3*/ + { .uop_mask = (1 << UOP_STOREA) | (1 << UOP_FSTOREA) | (1 << UOP_MSTOREA) }, /*Port 4*/ }; #define NR_P2_UNITS (sizeof(p2_units) / sizeof(p6_unit_t)) -static int uop_run(const p6_uop_t *uop, int decode_time) +static int +uop_run(const p6_uop_t *uop, int decode_time) { - int c; - p6_unit_t *best_unit = NULL; - int best_start_cycle = 99999; - - /*UOP_FXCH does not require execution*/ - if (uop->type == UOP_FXCH) - return decode_time; - - /*Find execution unit for this uOP*/ - for (c = 0; c < nr_units; c++) - { - if (units[c].uop_mask & (1 << uop->type)) - { - if (units[c].first_available_cycle < best_start_cycle) - { - best_unit = &units[c]; - best_start_cycle = units[c].first_available_cycle; - } - } + p6_unit_t *best_unit = NULL; + int best_start_cycle = 99999; + + /*UOP_FXCH does not require execution*/ + if (uop->type == UOP_FXCH) + return decode_time; + + /*Find execution unit for this uOP*/ + for (int c = 0; c < nr_units; c++) { + if (units[c].uop_mask & (1 << uop->type)) { + if (units[c].first_available_cycle < best_start_cycle) { + best_unit = &units[c]; + best_start_cycle = units[c].first_available_cycle; + } } - if (!best_unit) - fatal("uop_run: can not find execution unit\n"); + } + if (!best_unit) + fatal("uop_run: can not find execution unit\n"); - if (best_start_cycle < decode_time) - best_start_cycle = decode_time; - best_unit->first_available_cycle = best_start_cycle + uop->latency; - + if (best_start_cycle < decode_time) + best_start_cycle = decode_time; + best_unit->first_available_cycle = best_start_cycle + uop->latency; - - return best_start_cycle + uop->latency; + return best_start_cycle + uop->latency; } /*The P6 decoders can decode, per clock : - 1 to 3 'simple' instructions, each up to 1 uOP and 7 bytes long - 1 'complex' instruction, up to 4 uOPs or 3 per cycle for instructions longer than 4 uOPs */ -static struct -{ - int nr_uops; - const p6_uop_t *uops[6]; - /*Earliest time a uop can start. If the timestamp is -1, then the uop is - part of a dependency chain and the start time is the completion time of - the previous uop*/ - int earliest_start[6]; +static struct { + int nr_uops; + const p6_uop_t *uops[6]; + /*Earliest time a uop can start. If the timestamp is -1, then the uop is + part of a dependency chain and the start time is the completion time of + the previous uop*/ + int earliest_start[6]; } decode_buffer; #define NR_OPSEQS 3 @@ -1688,421 +1599,400 @@ static int fpu_st_timestamp[8]; dependent uop chains*/ static int last_uop_timestamp = 0; -void decode_flush_p6() +void +decode_flush_p6(void) { - int c; - int start_timestamp, uop_timestamp = 0; - - /*Decoded opseq can not be submitted if there are no free spaces in the - opseq buffer*/ - if (decode_timestamp < opseq_completion_timestamp[next_opseq]) - decode_timestamp = opseq_completion_timestamp[next_opseq]; + int start_timestamp; + int uop_timestamp = 0; - /*Ensure that uops can not be submitted before they have been decoded*/ - if (decode_timestamp > last_uop_timestamp) - last_uop_timestamp = decode_timestamp; + /*Decoded opseq can not be submitted if there are no free spaces in the + opseq buffer*/ + if (decode_timestamp < opseq_completion_timestamp[next_opseq]) + decode_timestamp = opseq_completion_timestamp[next_opseq]; - /*Submit uops to execution units, and determine the latest completion time*/ - for (c = 0; c < (decode_buffer.nr_uops); c++) - { - if (decode_buffer.earliest_start[c] == -1) - start_timestamp = last_uop_timestamp; - else - start_timestamp = decode_buffer.earliest_start[c]; - - last_uop_timestamp = uop_run(decode_buffer.uops[c], start_timestamp); - if (last_uop_timestamp > uop_timestamp) - uop_timestamp = last_uop_timestamp; - } + /*Ensure that uops can not be submitted before they have been decoded*/ + if (decode_timestamp > last_uop_timestamp) + last_uop_timestamp = decode_timestamp; - /*Calculate opseq completion time. Since opseqs complete in order, it - must be after the last completion.*/ - if (uop_timestamp <= last_complete_timestamp) - last_complete_timestamp = last_complete_timestamp + 1; + /*Submit uops to execution units, and determine the latest completion time*/ + for (int c = 0; c < (decode_buffer.nr_uops); c++) { + if (decode_buffer.earliest_start[c] == -1) + start_timestamp = last_uop_timestamp; else - last_complete_timestamp = uop_timestamp; + start_timestamp = decode_buffer.earliest_start[c]; - /*Advance to next opseq in buffer*/ - opseq_completion_timestamp[next_opseq] = last_complete_timestamp; - next_opseq++; - if (next_opseq == NR_OPSEQS) - next_opseq = 0; + last_uop_timestamp = uop_run(decode_buffer.uops[c], start_timestamp); + if (last_uop_timestamp > uop_timestamp) + uop_timestamp = last_uop_timestamp; + } - decode_timestamp++; - decode_buffer.nr_uops = 0; + /*Calculate opseq completion time. Since opseqs complete in order, it + must be after the last completion.*/ + if (uop_timestamp <= last_complete_timestamp) + last_complete_timestamp = last_complete_timestamp + 1; + else + last_complete_timestamp = uop_timestamp; + + /*Advance to next opseq in buffer*/ + opseq_completion_timestamp[next_opseq] = last_complete_timestamp; + next_opseq++; + if (next_opseq == NR_OPSEQS) + next_opseq = 0; + + decode_timestamp++; + decode_buffer.nr_uops = 0; } /*The instruction is only of interest here if it's longer than 7 bytes, as that's the limit on P6 simple decoding*/ -static int codegen_timing_instr_length(uint64_t deps, uint32_t fetchdat, int op_32) +static int +codegen_timing_instr_length(uint64_t deps, uint32_t fetchdat, int op_32) { - int len = prefixes + 1; /*Opcode*/ - if (deps & MODRM) - { - len++; /*ModR/M*/ - if (deps & HAS_IMM8) - len++; - if (deps & HAS_IMM1632) - len += (op_32 & 0x100) ? 4 : 2; + int len = prefixes + 1; /*Opcode*/ + if (deps & MODRM) { + len++; /*ModR/M*/ + if (deps & HAS_IMM8) + len++; + if (deps & HAS_IMM1632) + len += (op_32 & 0x100) ? 4 : 2; - if (op_32 & 0x200) - { - if ((fetchdat & 7) == 4 && (fetchdat & 0xc0) != 0xc0) - { - /* Has SIB*/ - len++; - if ((fetchdat & 0xc0) == 0x40) - len++; - else if ((fetchdat & 0xc0) == 0x80) - len += 4; - else if ((fetchdat & 0x700) == 0x500) - len += 4; - } - else - { - if ((fetchdat & 0xc0) == 0x40) - len++; - else if ((fetchdat & 0xc0) == 0x80) - len += 4; - else if ((fetchdat & 0xc7) == 0x05) - len += 4; - } - } - else - { - if ((fetchdat & 0xc0) == 0x40) - len++; - else if ((fetchdat & 0xc0) == 0x80) - len += 2; - else if ((fetchdat & 0xc7) == 0x06) - len += 2; - } + if (op_32 & 0x200) { + if ((fetchdat & 7) == 4 && (fetchdat & 0xc0) != 0xc0) { + /* Has SIB*/ + len++; + if ((fetchdat & 0xc0) == 0x40) + len++; + else if ((fetchdat & 0xc0) == 0x80) + len += 4; + else if ((fetchdat & 0x700) == 0x500) + len += 4; + } else { + if ((fetchdat & 0xc0) == 0x40) + len++; + else if ((fetchdat & 0xc0) == 0x80) + len += 4; + else if ((fetchdat & 0xc7) == 0x05) + len += 4; + } + } else { + if ((fetchdat & 0xc0) == 0x40) + len++; + else if ((fetchdat & 0xc0) == 0x80) + len += 2; + else if ((fetchdat & 0xc7) == 0x06) + len += 2; } + } - return len; + return len; } -static void decode_instruction(const macro_op_t *ins, uint64_t deps, uint32_t fetchdat, int op_32, int bit8) +static void +decode_instruction(const macro_op_t *ins, uint64_t deps, uint32_t fetchdat, int op_32, int bit8) { - uint32_t regmask_required; - uint32_t regmask_modified; - int c; - int d = 0; /*Complex decoder uOPs*/ - int earliest_start = 0; - decode_type_t decode_type = ins->decode_type; - int instr_length = codegen_timing_instr_length(deps, fetchdat, op_32); + uint32_t regmask_required; + uint32_t regmask_modified; + int c; + int d = 0; /*Complex decoder uOPs*/ + int earliest_start = 0; + decode_type_t decode_type = ins->decode_type; + int instr_length = codegen_timing_instr_length(deps, fetchdat, op_32); - /*Generate input register mask, and determine the earliest time this - instruction can start. This is not accurate, as this is calculated per - x86 instruction when it should be handled per uop*/ - regmask_required = get_dstdep_mask(deps, fetchdat, bit8); - regmask_required |= get_addr_regmask(deps, fetchdat, op_32); - for (c = 0; c < 8; c++) - { - if (regmask_required & (1 << c)) - { - if (reg_available_timestamp[c] > decode_timestamp) - earliest_start = reg_available_timestamp[c]; - } + /*Generate input register mask, and determine the earliest time this + instruction can start. This is not accurate, as this is calculated per + x86 instruction when it should be handled per uop*/ + regmask_required = get_dstdep_mask(deps, fetchdat, bit8); + regmask_required |= get_addr_regmask(deps, fetchdat, op_32); + for (c = 0; c < 8; c++) { + if (regmask_required & (1 << c)) { + if (reg_available_timestamp[c] > decode_timestamp) + earliest_start = reg_available_timestamp[c]; } - if ((deps & FPU_RW_ST0) && fpu_st_timestamp[0] > decode_timestamp) - earliest_start = fpu_st_timestamp[0]; - if ((deps & FPU_RW_ST1) && fpu_st_timestamp[1] > decode_timestamp) - earliest_start = fpu_st_timestamp[1]; - if ((deps & FPU_RW_STREG)) - { - int reg = fetchdat & 7; + } + if ((deps & FPU_RW_ST0) && fpu_st_timestamp[0] > decode_timestamp) + earliest_start = fpu_st_timestamp[0]; + if ((deps & FPU_RW_ST1) && fpu_st_timestamp[1] > decode_timestamp) + earliest_start = fpu_st_timestamp[1]; + if (deps & FPU_RW_STREG) { + int reg = fetchdat & 7; - if (fpu_st_timestamp[reg] > decode_timestamp) - earliest_start = fpu_st_timestamp[reg]; - } + if (fpu_st_timestamp[reg] > decode_timestamp) + earliest_start = fpu_st_timestamp[reg]; + } - /*Simple decoders are limited to 7 bytes & 1 uOP*/ - if ((decode_type == DECODE_SIMPLE && instr_length > 7) || (decode_type == DECODE_SIMPLE && ins->nr_uops > 1)) - decode_type = DECODE_COMPLEX; + /*Simple decoders are limited to 7 bytes & 1 uOP*/ + if ((decode_type == DECODE_SIMPLE && instr_length > 7) || (decode_type == DECODE_SIMPLE && ins->nr_uops > 1)) + decode_type = DECODE_COMPLEX; - switch (decode_type) - { - case DECODE_SIMPLE: - if (decode_buffer.nr_uops - d == 2) - { - decode_buffer.uops[decode_buffer.nr_uops] = &ins->uop[0]; - decode_buffer.earliest_start[decode_buffer.nr_uops] = earliest_start; - decode_buffer.nr_uops = 3; - decode_flush_p6(); - } - else if (decode_buffer.nr_uops - d == 1) - { - decode_buffer.uops[decode_buffer.nr_uops] = &ins->uop[0]; - decode_buffer.earliest_start[decode_buffer.nr_uops] = earliest_start; - decode_buffer.nr_uops = 2+d; - if (d) - decode_flush_p6(); - } - else if (decode_buffer.nr_uops) - { - decode_buffer.uops[decode_buffer.nr_uops] = &ins->uop[0]; - decode_buffer.earliest_start[decode_buffer.nr_uops] = earliest_start; - decode_buffer.nr_uops = 1+d; - } + switch (decode_type) { + case DECODE_SIMPLE: + if (decode_buffer.nr_uops - d == 2) { + decode_buffer.uops[decode_buffer.nr_uops] = &ins->uop[0]; + decode_buffer.earliest_start[decode_buffer.nr_uops] = earliest_start; + decode_buffer.nr_uops = 3; + decode_flush_p6(); + } else if (decode_buffer.nr_uops - d == 1) { + decode_buffer.uops[decode_buffer.nr_uops] = &ins->uop[0]; + decode_buffer.earliest_start[decode_buffer.nr_uops] = earliest_start; + decode_buffer.nr_uops = 2 + d; + if (d) + decode_flush_p6(); + } else if (decode_buffer.nr_uops) { + decode_buffer.uops[decode_buffer.nr_uops] = &ins->uop[0]; + decode_buffer.earliest_start[decode_buffer.nr_uops] = earliest_start; + decode_buffer.nr_uops = 1 + d; + } else { + decode_buffer.nr_uops = 1; + decode_buffer.uops[0] = &ins->uop[0]; + decode_buffer.earliest_start[0] = earliest_start; + } + break; + + case DECODE_COMPLEX: + if (decode_buffer.nr_uops) + decode_flush_p6(); /*The 4-1-1 arrangement implies that a complex ins. can't be decoded after a simple one*/ + + d = 0; + + for (c = 0; c < ins->nr_uops; c++) { + decode_buffer.uops[d] = &ins->uop[c]; + if (c == 0) + decode_buffer.earliest_start[d] = earliest_start; else - { - decode_buffer.nr_uops = 1; - decode_buffer.uops[0] = &ins->uop[0]; - decode_buffer.earliest_start[0] = earliest_start; - } - break; - - case DECODE_COMPLEX: - if (decode_buffer.nr_uops) - decode_flush_p6(); /*The 4-1-1 arrangement implies that a complex ins. can't be decoded after a simple one*/ - - d = 0; - - for (c = 0; c < ins->nr_uops; c++) - { - decode_buffer.uops[d] = &ins->uop[c]; - if (c == 0) - decode_buffer.earliest_start[d] = earliest_start; - else - decode_buffer.earliest_start[d] = -1; - d++; - - if ((d == 3) && (ins->nr_uops > 4)) /*Ins. with >4 uOPs require the use of special units only present on 3 translate PLAs*/ - { - d = 0; - decode_buffer.nr_uops = 3; - decode_flush_p6(); /*The other two decoders are halted to preserve in-order issue*/ - } - } - if (d) - { - decode_buffer.nr_uops = d; - } - break; - } + decode_buffer.earliest_start[d] = -1; + d++; - /*Update write timestamps for any output registers*/ - regmask_modified = get_dstdep_mask(deps, fetchdat, bit8); - for (c = 0; c < 8; c++) - { - if (regmask_modified & (1 << c)) - reg_available_timestamp[c] = last_complete_timestamp; - } + if ((d == 3) && (ins->nr_uops > 4)) { /*Ins. with >4 uOPs require the use of special units only present on 3 translate PLAs*/ + d = 0; + decode_buffer.nr_uops = 3; + decode_flush_p6(); /*The other two decoders are halted to preserve in-order issue*/ + } + } + if (d) { + decode_buffer.nr_uops = d; + } + break; + } + + /*Update write timestamps for any output registers*/ + regmask_modified = get_dstdep_mask(deps, fetchdat, bit8); + for (c = 0; c < 8; c++) { + if (regmask_modified & (1 << c)) + reg_available_timestamp[c] = last_complete_timestamp; + } + if (deps & FPU_POP) { + for (c = 0; c < 7; c++) + fpu_st_timestamp[c] = fpu_st_timestamp[c + 1]; + fpu_st_timestamp[7] = 0; + } + if (deps & FPU_POP2) { + for (c = 0; c < 6; c++) + fpu_st_timestamp[c] = fpu_st_timestamp[c + 2]; + fpu_st_timestamp[6] = fpu_st_timestamp[7] = 0; + } + if (deps & FPU_PUSH) { + for (c = 0; c < 7; c++) + fpu_st_timestamp[c + 1] = fpu_st_timestamp[c]; + fpu_st_timestamp[0] = 0; + } + if (deps & FPU_WRITE_ST0) + fpu_st_timestamp[0] = last_complete_timestamp; + if (deps & FPU_WRITE_ST1) + fpu_st_timestamp[1] = last_complete_timestamp; + if (deps & FPU_WRITE_STREG) { + int reg = fetchdat & 7; if (deps & FPU_POP) - { - for (c = 0; c < 7; c++) - fpu_st_timestamp[c] = fpu_st_timestamp[c+1]; - fpu_st_timestamp[7] = 0; - } - if (deps & FPU_POP2) - { - for (c = 0; c < 6; c++) - fpu_st_timestamp[c] = fpu_st_timestamp[c+2]; - fpu_st_timestamp[6] = fpu_st_timestamp[7] = 0; - } - if (deps & FPU_PUSH) - { - for (c = 0; c < 7; c++) - fpu_st_timestamp[c+1] = fpu_st_timestamp[c]; - fpu_st_timestamp[0] = 0; - } - if (deps & FPU_WRITE_ST0) - fpu_st_timestamp[0] = last_complete_timestamp; - if (deps & FPU_WRITE_ST1) - fpu_st_timestamp[1] = last_complete_timestamp; - if (deps & FPU_WRITE_STREG) - { - int reg = fetchdat & 7; - if (deps & FPU_POP) - reg--; - if (reg >= 0 && - !(reg == 0 && (deps & FPU_WRITE_ST0)) && - !(reg == 1 && (deps & FPU_WRITE_ST1))) - fpu_st_timestamp[reg] = last_complete_timestamp; - } + reg--; + if (reg >= 0 && !(reg == 0 && (deps & FPU_WRITE_ST0)) && !(reg == 1 && (deps & FPU_WRITE_ST1))) + fpu_st_timestamp[reg] = last_complete_timestamp; + } } -void codegen_timing_p6_block_start() +void +codegen_timing_p6_block_start(void) { - int c; + int c; - for (c = 0; c < nr_units; c++) - units[c].first_available_cycle = 0; + for (c = 0; c < nr_units; c++) + units[c].first_available_cycle = 0; - decode_timestamp = 0; - last_complete_timestamp = 0; - - for (c = 0; c < NR_OPSEQS; c++) - opseq_completion_timestamp[c] = 0; - next_opseq = 0; - - for (c = 0; c < NR_REGS; c++) - reg_available_timestamp[c] = 0; - for (c = 0; c < 8; c++) - fpu_st_timestamp[c] = 0; + decode_timestamp = 0; + last_complete_timestamp = 0; + + for (c = 0; c < NR_OPSEQS; c++) + opseq_completion_timestamp[c] = 0; + next_opseq = 0; + + for (c = 0; c < NR_REGS; c++) + reg_available_timestamp[c] = 0; + for (c = 0; c < 8; c++) + fpu_st_timestamp[c] = 0; } -void codegen_timing_p6_start() +void +codegen_timing_p6_start(void) { - if (cpu_s->cpu_type == CPU_PENTIUMPRO) - { - units = ppro_units; - nr_units = NR_PPRO_UNITS; - } - else - { - units = p2_units; - nr_units = NR_P2_UNITS; - } - last_prefix = 0; - prefixes = 0; + if (cpu_s->cpu_type == CPU_PENTIUMPRO) { + units = ppro_units; + nr_units = NR_PPRO_UNITS; + } else { + units = p2_units; + nr_units = NR_P2_UNITS; + } + last_prefix = 0; + prefixes = 0; } -void codegen_timing_p6_prefix(uint8_t prefix, uint32_t fetchdat) +void +codegen_timing_p6_prefix(uint8_t prefix, uint32_t fetchdat) { - if (prefix != 0x0f) - decode_timestamp++; + if (prefix != 0x0f) + decode_timestamp++; - last_prefix = prefix; - prefixes++; + last_prefix = prefix; + prefixes++; } -void codegen_timing_p6_opcode(uint8_t opcode, uint32_t fetchdat, int op_32, uint32_t op_pc) +void +codegen_timing_p6_opcode(uint8_t opcode, uint32_t fetchdat, int op_32, UNUSED(uint32_t op_pc)) { - const macro_op_t **ins_table; - uint64_t *deps; - int mod3 = ((fetchdat & 0xc0) == 0xc0); - int old_last_complete_timestamp = last_complete_timestamp; - int bit8 = !(opcode & 1); + const macro_op_t **ins_table; + const uint64_t *deps; + int mod3 = ((fetchdat & 0xc0) == 0xc0); + int old_last_complete_timestamp = last_complete_timestamp; + int bit8 = !(opcode & 1); - switch (last_prefix) - { - case 0x0f: - ins_table = mod3 ? opcode_timings_0f_mod3 : opcode_timings_0f; - deps = mod3 ? opcode_deps_0f_mod3 : opcode_deps_0f; - break; + switch (last_prefix) { + case 0x0f: + ins_table = mod3 ? opcode_timings_0f_mod3 : opcode_timings_0f; + deps = mod3 ? opcode_deps_0f_mod3 : opcode_deps_0f; + break; - case 0xd8: - ins_table = mod3 ? opcode_timings_d8_mod3 : opcode_timings_d8; - deps = mod3 ? opcode_deps_d8_mod3 : opcode_deps_d8; - opcode = (opcode >> 3) & 7; - break; - case 0xd9: - ins_table = mod3 ? opcode_timings_d9_mod3 : opcode_timings_d9; - deps = mod3 ? opcode_deps_d9_mod3 : opcode_deps_d9; - opcode = mod3 ? opcode & 0x3f : (opcode >> 3) & 7; - break; - case 0xda: - ins_table = mod3 ? opcode_timings_da_mod3 : opcode_timings_da; - deps = mod3 ? opcode_deps_da_mod3 : opcode_deps_da; - opcode = (opcode >> 3) & 7; - break; - case 0xdb: - ins_table = mod3 ? opcode_timings_db_mod3 : opcode_timings_db; - deps = mod3 ? opcode_deps_db_mod3 : opcode_deps_db; - opcode = mod3 ? opcode & 0x3f : (opcode >> 3) & 7; - break; - case 0xdc: - ins_table = mod3 ? opcode_timings_dc_mod3 : opcode_timings_dc; - deps = mod3 ? opcode_deps_dc_mod3 : opcode_deps_dc; - opcode = (opcode >> 3) & 7; - break; - case 0xdd: - ins_table = mod3 ? opcode_timings_dd_mod3 : opcode_timings_dd; - deps = mod3 ? opcode_deps_dd_mod3 : opcode_deps_dd; - opcode = (opcode >> 3) & 7; - break; - case 0xde: - ins_table = mod3 ? opcode_timings_de_mod3 : opcode_timings_de; - deps = mod3 ? opcode_deps_de_mod3 : opcode_deps_de; - opcode = (opcode >> 3) & 7; - break; - case 0xdf: - ins_table = mod3 ? opcode_timings_df_mod3 : opcode_timings_df; - deps = mod3 ? opcode_deps_df_mod3 : opcode_deps_df; - opcode = (opcode >> 3) & 7; - break; + case 0xd8: + ins_table = mod3 ? opcode_timings_d8_mod3 : opcode_timings_d8; + deps = mod3 ? opcode_deps_d8_mod3 : opcode_deps_d8; + opcode = (opcode >> 3) & 7; + break; + case 0xd9: + ins_table = mod3 ? opcode_timings_d9_mod3 : opcode_timings_d9; + deps = mod3 ? opcode_deps_d9_mod3 : opcode_deps_d9; + opcode = mod3 ? opcode & 0x3f : (opcode >> 3) & 7; + break; + case 0xda: + ins_table = mod3 ? opcode_timings_da_mod3 : opcode_timings_da; + deps = mod3 ? opcode_deps_da_mod3 : opcode_deps_da; + opcode = (opcode >> 3) & 7; + break; + case 0xdb: + ins_table = mod3 ? opcode_timings_db_mod3 : opcode_timings_db; + deps = mod3 ? opcode_deps_db_mod3 : opcode_deps_db; + opcode = mod3 ? opcode & 0x3f : (opcode >> 3) & 7; + break; + case 0xdc: + ins_table = mod3 ? opcode_timings_dc_mod3 : opcode_timings_dc; + deps = mod3 ? opcode_deps_dc_mod3 : opcode_deps_dc; + opcode = (opcode >> 3) & 7; + break; + case 0xdd: + ins_table = mod3 ? opcode_timings_dd_mod3 : opcode_timings_dd; + deps = mod3 ? opcode_deps_dd_mod3 : opcode_deps_dd; + opcode = (opcode >> 3) & 7; + break; + case 0xde: + ins_table = mod3 ? opcode_timings_de_mod3 : opcode_timings_de; + deps = mod3 ? opcode_deps_de_mod3 : opcode_deps_de; + opcode = (opcode >> 3) & 7; + break; + case 0xdf: + ins_table = mod3 ? opcode_timings_df_mod3 : opcode_timings_df; + deps = mod3 ? opcode_deps_df_mod3 : opcode_deps_df; + opcode = (opcode >> 3) & 7; + break; + + default: + switch (opcode) { + case 0x80: + case 0x82: + ins_table = mod3 ? opcode_timings_80_mod3 : opcode_timings_80; + deps = mod3 ? opcode_deps_8x_mod3 : opcode_deps_8x; + opcode = (fetchdat >> 3) & 7; + break; + case 0x81: + case 0x83: + ins_table = mod3 ? opcode_timings_8x_mod3 : opcode_timings_8x; + deps = mod3 ? opcode_deps_8x_mod3 : opcode_deps_8x; + opcode = (fetchdat >> 3) & 7; + break; + + case 0xc0: + case 0xd0: + case 0xd2: + ins_table = mod3 ? opcode_timings_shift_b_mod3 : opcode_timings_shift_b; + deps = mod3 ? opcode_deps_shift_mod3 : opcode_deps_shift; + opcode = (fetchdat >> 3) & 7; + break; + + case 0xc1: + case 0xd1: + case 0xd3: + ins_table = mod3 ? opcode_timings_shift_mod3 : opcode_timings_shift; + deps = mod3 ? opcode_deps_shift_mod3 : opcode_deps_shift; + opcode = (fetchdat >> 3) & 7; + break; + + case 0xf6: + ins_table = mod3 ? opcode_timings_f6_mod3 : opcode_timings_f6; + deps = mod3 ? opcode_deps_f6_mod3 : opcode_deps_f6; + opcode = (fetchdat >> 3) & 7; + break; + case 0xf7: + ins_table = mod3 ? opcode_timings_f7_mod3 : opcode_timings_f7; + deps = mod3 ? opcode_deps_f7_mod3 : opcode_deps_f7; + opcode = (fetchdat >> 3) & 7; + break; + case 0xff: + ins_table = mod3 ? opcode_timings_ff_mod3 : opcode_timings_ff; + deps = mod3 ? opcode_deps_ff_mod3 : opcode_deps_ff; + opcode = (fetchdat >> 3) & 7; + break; default: - switch (opcode) - { - case 0x80: case 0x82: - ins_table = mod3 ? opcode_timings_80_mod3 : opcode_timings_80; - deps = mod3 ? opcode_deps_8x_mod3 : opcode_deps_8x; - opcode = (fetchdat >> 3) & 7; - break; - case 0x81: case 0x83: - ins_table = mod3 ? opcode_timings_8x_mod3 : opcode_timings_8x; - deps = mod3 ? opcode_deps_8x_mod3 : opcode_deps_8x; - opcode = (fetchdat >> 3) & 7; - break; + ins_table = mod3 ? opcode_timings_mod3 : opcode_timings; + deps = mod3 ? opcode_deps_mod3 : opcode_deps; + break; + } + } - case 0xc0: case 0xd0: case 0xd2: - ins_table = mod3 ? opcode_timings_shift_b_mod3 : opcode_timings_shift_b; - deps = mod3 ? opcode_deps_shift_mod3 : opcode_deps_shift; - opcode = (fetchdat >> 3) & 7; - break; - - case 0xc1: case 0xd1: case 0xd3: - ins_table = mod3 ? opcode_timings_shift_mod3 : opcode_timings_shift; - deps = mod3 ? opcode_deps_shift_mod3 : opcode_deps_shift; - opcode = (fetchdat >> 3) & 7; - break; + if (ins_table[opcode]) + decode_instruction(ins_table[opcode], deps[opcode], fetchdat, op_32, bit8); + else + decode_instruction(&complex_alu1_op, 0, fetchdat, op_32, bit8); + codegen_block_cycles += (last_complete_timestamp - old_last_complete_timestamp); +} - case 0xf6: - ins_table = mod3 ? opcode_timings_f6_mod3 : opcode_timings_f6; - deps = mod3 ? opcode_deps_f6_mod3 : opcode_deps_f6; - opcode = (fetchdat >> 3) & 7; - break; - case 0xf7: - ins_table = mod3 ? opcode_timings_f7_mod3 : opcode_timings_f7; - deps = mod3 ? opcode_deps_f7_mod3 : opcode_deps_f7; - opcode = (fetchdat >> 3) & 7; - break; - case 0xff: - ins_table = mod3 ? opcode_timings_ff_mod3 : opcode_timings_ff; - deps = mod3 ? opcode_deps_ff_mod3 : opcode_deps_ff; - opcode = (fetchdat >> 3) & 7; - break; - - default: - ins_table = mod3 ? opcode_timings_mod3 : opcode_timings; - deps = mod3 ? opcode_deps_mod3 : opcode_deps; - break; - } - } - - if (ins_table[opcode]) - decode_instruction(ins_table[opcode], deps[opcode], fetchdat, op_32, bit8); - else - decode_instruction(&complex_alu1_op, 0, fetchdat, op_32, bit8); +void +codegen_timing_p6_block_end(void) +{ + if (decode_buffer.nr_uops) { + int old_last_complete_timestamp = last_complete_timestamp; + decode_flush_p6(); codegen_block_cycles += (last_complete_timestamp - old_last_complete_timestamp); + } } -void codegen_timing_p6_block_end() +int +codegen_timing_p6_jump_cycles(void) { - if (decode_buffer.nr_uops) - { - int old_last_complete_timestamp = last_complete_timestamp; - decode_flush_p6(); - codegen_block_cycles += (last_complete_timestamp - old_last_complete_timestamp); - } + if (decode_buffer.nr_uops) + return 1; + return 0; } -int codegen_timing_p6_jump_cycles() -{ - if (decode_buffer.nr_uops) - return 1; - return 0; -} - -codegen_timing_t codegen_timing_p6 = -{ - codegen_timing_p6_start, - codegen_timing_p6_prefix, - codegen_timing_p6_opcode, - codegen_timing_p6_block_start, - codegen_timing_p6_block_end, - codegen_timing_p6_jump_cycles +codegen_timing_t codegen_timing_p6 = { + codegen_timing_p6_start, + codegen_timing_p6_prefix, + codegen_timing_p6_opcode, + codegen_timing_p6_block_start, + codegen_timing_p6_block_end, + codegen_timing_p6_jump_cycles }; diff --git a/src/cpu/codegen_timing_pentium.c b/src/cpu/codegen_timing_pentium.c index ec6b8f2a7..3951acc94 100644 --- a/src/cpu/codegen_timing_pentium.c +++ b/src/cpu/codegen_timing_pentium.c @@ -14,8 +14,11 @@ #include #include #include <86box/86box.h> -#include <86box/mem.h> #include "cpu.h" +#include <86box/mem.h> +#include <86box/plat_unused.h> +#include + #include "x86.h" #include "x86_ops.h" #include "x87.h" @@ -23,46 +26,45 @@ #include "codegen_ops.h" #include "codegen_timing_common.h" - /*Instruction has different execution time for 16 and 32 bit data. Does not pair */ -#define CYCLES_HAS_MULTI (1 << 28) +#define CYCLES_HAS_MULTI (1 << 28) #define CYCLES_MULTI(c16, c32) (CYCLES_HAS_MULTI | c16 | (c32 << 8)) /*Instruction lasts given number of cycles. Does not pair*/ #define CYCLES(c) (c | PAIR_NP) - -static int pair_timings[4][4] = -{ -/* Reg RM RMW Branch*/ -/*Reg*/ {1, 2, 3, 2}, -/*RM*/ {2, 2, 3, 3}, -/*RMW*/ {3, 4, 5, 4}, -/*Branch*/ {-1, -1, -1, -1} +static int pair_timings[4][4] = { + /* Reg RM RMW Branch*/ + /*Reg*/ {1, 2, 3, 2 }, + /*RM*/ + { 2, 2, 3, 3 }, + /*RMW*/ + { 3, 4, 5, 4 }, + /*Branch*/ + { -1, -1, -1, -1} }; /*Instruction follows either register timing, read-modify, or read-modify-write. May be pairable*/ -#define CYCLES_REG (0ull << 0) -#define CYCLES_RM (1ull << 0) -#define CYCLES_RMW (2ull << 0) +#define CYCLES_REG (0ull << 0) +#define CYCLES_RM (1ull << 0) +#define CYCLES_RMW (2ull << 0) #define CYCLES_BRANCH (3ull << 0) /*Instruction has immediate data. Can only be used with PAIR_U/PAIR_V/PAIR_UV*/ -#define CYCLES_HASIMM (3ull << 2) +#define CYCLES_HASIMM (3ull << 2) #define CYCLES_IMM8 (1ull << 2) #define CYCLES_IMM1632 (2ull << 2) -#define CYCLES_MASK ((1ull << 7) - 1) - +#define CYCLES_MASK ((1ull << 7) - 1) /*Instruction does not pair*/ #define PAIR_NP (0ull << 29) /*Instruction pairs in U pipe only*/ -#define PAIR_U (1ull << 29) +#define PAIR_U (1ull << 29) /*Instruction pairs in V pipe only*/ -#define PAIR_V (2ull << 29) +#define PAIR_V (2ull << 29) /*Instruction pairs in both U and V pipes*/ #define PAIR_UV (3ull << 29) /*Instruction pairs in U pipe only and only with FXCH*/ @@ -70,36 +72,34 @@ static int pair_timings[4][4] = /*Instruction is FXCH and only pairs in V pipe with FX pairable instruction*/ #define PAIR_FXCH (6ull << 29) -#define PAIR_FPU (4ull << 29) +#define PAIR_FPU (4ull << 29) #define PAIR_MASK (7ull << 29) - /*comp_time = cycles until instruction complete i_overlap = cycles that overlap with integer f_overlap = cycles that overlap with subsequent FPU*/ -#define FPU_CYCLES(comp_time, i_overlap, f_overlap) ((uint64_t)comp_time) | ((uint64_t)i_overlap << 41) | ((uint64_t)f_overlap << 49) | PAIR_FPU +#define FPU_CYCLES(comp_time, i_overlap, f_overlap) ((uint64_t) comp_time) | ((uint64_t) i_overlap << 41) | ((uint64_t) f_overlap << 49) | PAIR_FPU -#define FPU_COMP_TIME(timing) (timing & 0xff) -#define FPU_I_OVERLAP(timing) ((timing >> 41) & 0xff) -#define FPU_F_OVERLAP(timing) ((timing >> 49) & 0xff) +#define FPU_COMP_TIME(timing) (timing & 0xff) +#define FPU_I_OVERLAP(timing) ((timing >> 41) & 0xff) +#define FPU_F_OVERLAP(timing) ((timing >> 49) & 0xff) -#define FPU_I_LATENCY(timing) (FPU_COMP_TIME(timing) - FPU_I_OVERLAP(timing)) +#define FPU_I_LATENCY(timing) (FPU_COMP_TIME(timing) - FPU_I_OVERLAP(timing)) -#define FPU_F_LATENCY(timing) (FPU_I_OVERLAP(timing) - FPU_F_OVERLAP(timing)) +#define FPU_F_LATENCY(timing) (FPU_I_OVERLAP(timing) - FPU_F_OVERLAP(timing)) -#define FPU_RESULT_LATENCY(timing) ((timing >> 41) & 0xff) +#define FPU_RESULT_LATENCY(timing) ((timing >> 41) & 0xff) +#define INVALID 0 -#define INVALID 0 - -static int u_pipe_full; -static uint32_t u_pipe_opcode; +static int u_pipe_full; +static uint32_t u_pipe_opcode; static uint64_t *u_pipe_timings; -static uint32_t u_pipe_op_32; -static uint32_t u_pipe_regmask; -static uint32_t u_pipe_fetchdat; -static int u_pipe_decode_delay_offset; +static uint32_t u_pipe_op_32; +static uint32_t u_pipe_regmask; +static uint32_t u_pipe_fetchdat; +static int u_pipe_decode_delay_offset; static uint64_t *u_pipe_deps; static uint32_t regmask_modified; @@ -109,8 +109,8 @@ static uint32_t addr_regmask; static int fpu_latency; static int fpu_st_latency[8]; -static uint64_t opcode_timings[256] = -{ +static uint64_t opcode_timings[256] = { + // clang-format off /* ADD ADD ADD ADD*/ /*00*/ PAIR_UV | CYCLES_RMW, PAIR_UV | CYCLES_RMW, PAIR_UV | CYCLES_RM, PAIR_UV | CYCLES_RM, /* ADD ADD PUSH ES POP ES*/ @@ -124,7 +124,7 @@ static uint64_t opcode_timings[256] = /*10*/ PAIR_U | CYCLES_RMW, PAIR_U | CYCLES_RMW, PAIR_U | CYCLES_RM, PAIR_U | CYCLES_RM, /* ADC ADC PUSH SS POP SS*/ PAIR_U | CYCLES_REG, PAIR_U | CYCLES_REG, PAIR_NP | CYCLES(1), PAIR_NP | CYCLES(3), -/* SBB SBB SBB SBB*/ +/* SBB SBB SBB SBB*/ PAIR_U | CYCLES_RMW, PAIR_U | CYCLES_RMW, PAIR_U | CYCLES_RM, PAIR_U | CYCLES_RM, /* SBB SBB PUSH DS POP DS*/ PAIR_U | CYCLES_REG, PAIR_U | CYCLES_REG, PAIR_NP | CYCLES(1), PAIR_NP | CYCLES(3), @@ -137,7 +137,7 @@ static uint64_t opcode_timings[256] = PAIR_UV | CYCLES_RMW, PAIR_UV | CYCLES_RMW, PAIR_UV | CYCLES_RM, PAIR_UV | CYCLES_RM, /* SUB SUB DAS*/ PAIR_UV | CYCLES_REG, PAIR_UV | CYCLES_REG, INVALID, PAIR_NP | CYCLES(3), - + /* XOR XOR XOR XOR*/ /*30*/ PAIR_UV | CYCLES_RMW, PAIR_UV | CYCLES_RMW, PAIR_UV | CYCLES_RM, PAIR_UV | CYCLES_RM, /* XOR XOR AAA*/ @@ -155,7 +155,7 @@ static uint64_t opcode_timings[256] = PAIR_UV | CYCLES_REG, PAIR_UV | CYCLES_REG, PAIR_UV | CYCLES_REG, PAIR_UV | CYCLES_REG, /* DEC ESP DEC EBP DEC ESI DEC EDI*/ PAIR_UV | CYCLES_REG, PAIR_UV | CYCLES_REG, PAIR_UV | CYCLES_REG, PAIR_UV | CYCLES_REG, - + /* PUSH EAX PUSH ECX PUSH EDX PUSH EBX*/ /*50*/ PAIR_UV | CYCLES_REG, PAIR_UV | CYCLES_REG, PAIR_UV | CYCLES_REG, PAIR_UV | CYCLES_REG, /* PUSH ESP PUSH EBP PUSH ESI PUSH EDI*/ @@ -172,8 +172,8 @@ static uint64_t opcode_timings[256] = PAIR_UV | CYCLES_REG, PAIR_NP | CYCLES(10), PAIR_UV | CYCLES_REG, PAIR_NP | CYCLES(10), /* INSB INSW OUTSB OUTSW*/ PAIR_NP | CYCLES(9), PAIR_NP | CYCLES(9), PAIR_NP | CYCLES(13), PAIR_NP | CYCLES(13), - -/* Jxx*/ + +/* Jxx*/ /*70*/ PAIR_V | CYCLES_BRANCH, PAIR_V | CYCLES_BRANCH, PAIR_V | CYCLES_BRANCH, PAIR_V | CYCLES_BRANCH, PAIR_V | CYCLES_BRANCH, PAIR_V | CYCLES_BRANCH, PAIR_V | CYCLES_BRANCH, PAIR_V | CYCLES_BRANCH, PAIR_V | CYCLES_BRANCH, PAIR_V | CYCLES_BRANCH, PAIR_V | CYCLES_BRANCH, PAIR_V | CYCLES_BRANCH, @@ -186,7 +186,7 @@ static uint64_t opcode_timings[256] = PAIR_UV | CYCLES_REG, PAIR_UV | CYCLES_REG, PAIR_UV | CYCLES_REG, PAIR_UV, /* MOV from seg LEA MOV to seg POP*/ PAIR_NP | CYCLES(1), PAIR_UV | CYCLES_REG, CYCLES(3), PAIR_NP | CYCLES(3), - + /* NOP XCHG XCHG XCHG*/ /*90*/ PAIR_UV | CYCLES_REG, PAIR_NP | CYCLES(2), PAIR_NP | CYCLES(2), PAIR_NP | CYCLES(2), /* XCHG XCHG XCHG XCHG*/ @@ -196,7 +196,7 @@ static uint64_t opcode_timings[256] = /* PUSHF POPF SAHF LAHF*/ PAIR_NP | CYCLES(3), PAIR_NP | CYCLES(4), PAIR_NP | CYCLES(2), PAIR_NP | CYCLES(2), -/* MOV MOV MOV MOV*/ +/* MOV MOV MOV MOV*/ /*a0*/ PAIR_UV | CYCLES_REG, PAIR_UV | CYCLES_REG, PAIR_UV | CYCLES_REG, PAIR_UV | CYCLES_REG, /* MOVSB MOVSW CMPSB CMPSW*/ PAIR_NP | CYCLES(4), PAIR_NP | CYCLES(4), PAIR_NP | CYCLES(5), PAIR_NP | CYCLES(5), @@ -224,7 +224,7 @@ static uint64_t opcode_timings[256] = /*d0*/ INVALID, INVALID, INVALID, INVALID, /* AAM AAD SETALC XLAT*/ PAIR_NP | CYCLES(18), PAIR_NP | CYCLES(10), PAIR_NP | CYCLES(2), PAIR_NP | CYCLES(4), - INVALID, INVALID, INVALID, INVALID, + INVALID, INVALID, INVALID, INVALID, INVALID, INVALID, INVALID, INVALID, /* LOOPNE LOOPE LOOP JCXZ*/ /*e0*/ PAIR_NP | CYCLES(7), PAIR_NP | CYCLES(7), PAIR_NP | CYCLES(5), PAIR_NP | CYCLES(5), @@ -243,10 +243,11 @@ static uint64_t opcode_timings[256] = PAIR_NP | CYCLES(2), PAIR_NP | CYCLES(2), PAIR_NP | CYCLES(7), PAIR_NP | CYCLES(7), /* CLD STD INCDEC*/ PAIR_NP | CYCLES(2), PAIR_NP | CYCLES(2), PAIR_UV | CYCLES_RMW, INVALID + // clang-format on }; -static uint64_t opcode_timings_mod3[256] = -{ +static uint64_t opcode_timings_mod3[256] = { + // clang-format off /* ADD ADD ADD ADD*/ /*00*/ PAIR_UV | CYCLES_REG, PAIR_UV | CYCLES_REG, PAIR_UV | CYCLES_REG, PAIR_UV | CYCLES_REG, /* ADD ADD PUSH ES POP ES*/ @@ -260,7 +261,7 @@ static uint64_t opcode_timings_mod3[256] = /*10*/ PAIR_U | CYCLES_REG, PAIR_U | CYCLES_REG, PAIR_U | CYCLES_REG, PAIR_U | CYCLES_REG, /* ADC ADC PUSH SS POP SS*/ PAIR_U | CYCLES_REG, PAIR_U | CYCLES_REG, PAIR_NP | CYCLES(1), PAIR_NP | CYCLES(3), -/* SBB SBB SBB SBB*/ +/* SBB SBB SBB SBB*/ PAIR_U | CYCLES_REG, PAIR_U | CYCLES_REG, PAIR_U | CYCLES_REG, PAIR_U | CYCLES_REG, /* SBB SBB PUSH DS POP DS*/ PAIR_U | CYCLES_REG, PAIR_U | CYCLES_REG, PAIR_NP | CYCLES(1), PAIR_NP | CYCLES(3), @@ -273,7 +274,7 @@ static uint64_t opcode_timings_mod3[256] = PAIR_UV | CYCLES_REG, PAIR_UV | CYCLES_REG, PAIR_UV | CYCLES_REG, PAIR_UV | CYCLES_REG, /* SUB SUB DAS*/ PAIR_UV | CYCLES_REG, PAIR_UV | CYCLES_REG, INVALID, PAIR_NP | CYCLES(3), - + /* XOR XOR XOR XOR*/ /*30*/ PAIR_UV | CYCLES_REG, PAIR_UV | CYCLES_REG, PAIR_UV | CYCLES_REG, PAIR_UV | CYCLES_REG, /* XOR XOR AAA*/ @@ -291,7 +292,7 @@ static uint64_t opcode_timings_mod3[256] = PAIR_UV | CYCLES_REG, PAIR_UV | CYCLES_REG, PAIR_UV | CYCLES_REG, PAIR_UV | CYCLES_REG, /* DEC ESP DEC EBP DEC ESI DEC EDI*/ PAIR_UV | CYCLES_REG, PAIR_UV | CYCLES_REG, PAIR_UV | CYCLES_REG, PAIR_UV | CYCLES_REG, - + /* PUSH EAX PUSH ECX PUSH EDX PUSH EBX*/ /*50*/ PAIR_UV | CYCLES_REG, PAIR_UV | CYCLES_REG, PAIR_UV | CYCLES_REG, PAIR_UV | CYCLES_REG, /* PUSH ESP PUSH EBP PUSH ESI PUSH EDI*/ @@ -308,8 +309,8 @@ static uint64_t opcode_timings_mod3[256] = PAIR_UV | CYCLES_REG, PAIR_NP | CYCLES(10), PAIR_UV | CYCLES_REG, PAIR_NP | CYCLES(10), /* INSB INSW OUTSB OUTSW*/ PAIR_NP | CYCLES(9), PAIR_NP | CYCLES(9), PAIR_NP | CYCLES(13), PAIR_NP | CYCLES(13), - -/* Jxx*/ + +/* Jxx*/ /*70*/ PAIR_V | CYCLES_BRANCH, PAIR_V | CYCLES_BRANCH, PAIR_V | CYCLES_BRANCH, PAIR_V | CYCLES_BRANCH, PAIR_V | CYCLES_BRANCH, PAIR_V | CYCLES_BRANCH, PAIR_V | CYCLES_BRANCH, PAIR_V | CYCLES_BRANCH, PAIR_V | CYCLES_BRANCH, PAIR_V | CYCLES_BRANCH, PAIR_V | CYCLES_BRANCH, PAIR_V | CYCLES_BRANCH, @@ -322,7 +323,7 @@ static uint64_t opcode_timings_mod3[256] = PAIR_UV | CYCLES_REG, PAIR_UV | CYCLES_REG, PAIR_UV | CYCLES_REG, PAIR_UV | CYCLES_REG, /* MOV from seg LEA MOV to seg POP*/ PAIR_NP | CYCLES(1), PAIR_UV | CYCLES_REG, PAIR_NP | CYCLES(3), PAIR_NP | CYCLES(3), - + /* NOP XCHG XCHG XCHG*/ /*90*/ PAIR_UV | CYCLES_REG, PAIR_NP | CYCLES(2), PAIR_NP | CYCLES(2), PAIR_NP | CYCLES(2), /* XCHG XCHG XCHG XCHG*/ @@ -332,7 +333,7 @@ static uint64_t opcode_timings_mod3[256] = /* PUSHF POPF SAHF LAHF*/ PAIR_NP | CYCLES(3), PAIR_NP | CYCLES(4), PAIR_NP | CYCLES(2), PAIR_NP | CYCLES(2), -/* MOV MOV MOV MOV*/ +/* MOV MOV MOV MOV*/ /*a0*/ PAIR_UV | CYCLES_REG, PAIR_UV | CYCLES_REG, PAIR_UV | CYCLES_REG, PAIR_UV | CYCLES_REG, /* MOVSB MOVSW CMPSB CMPSW*/ PAIR_NP | CYCLES(4), PAIR_NP | CYCLES(4), PAIR_NP | CYCLES(5), PAIR_NP | CYCLES(5), @@ -360,7 +361,7 @@ static uint64_t opcode_timings_mod3[256] = /*d0*/ INVALID, INVALID, INVALID, INVALID, /* AAM AAD SETALC XLAT*/ PAIR_NP | CYCLES(18), PAIR_NP | CYCLES(10), PAIR_NP | CYCLES(2), PAIR_NP | CYCLES(4), - INVALID, INVALID, INVALID, INVALID, + INVALID, INVALID, INVALID, INVALID, INVALID, INVALID, INVALID, INVALID, /* LOOPNE LOOPE LOOP JCXZ*/ @@ -380,10 +381,11 @@ static uint64_t opcode_timings_mod3[256] = PAIR_NP | CYCLES(2), PAIR_NP | CYCLES(2), PAIR_NP | CYCLES(7), PAIR_NP | CYCLES(7), /* CLD STD INCDEC*/ PAIR_NP | CYCLES(2), PAIR_NP | CYCLES(2), PAIR_UV | CYCLES_REG, INVALID + // clang-format on }; -static uint64_t opcode_timings_0f[256] = -{ +static uint64_t opcode_timings_0f[256] = { + // clang-format off /*00*/ PAIR_NP | CYCLES(20), PAIR_NP | CYCLES(11), PAIR_NP | CYCLES(11), PAIR_NP | CYCLES(10), INVALID, PAIR_NP | CYCLES(195), PAIR_NP | CYCLES(7), INVALID, PAIR_NP | CYCLES(1000), PAIR_NP | CYCLES(10000), INVALID, INVALID, @@ -393,32 +395,32 @@ static uint64_t opcode_timings_0f[256] = INVALID, INVALID, INVALID, INVALID, INVALID, INVALID, INVALID, INVALID, INVALID, INVALID, INVALID, INVALID, - + /*20*/ PAIR_NP | CYCLES(6), PAIR_NP | CYCLES(6), PAIR_NP | CYCLES(6), PAIR_NP | CYCLES(6), PAIR_NP | CYCLES(6), PAIR_NP | CYCLES(6), INVALID, INVALID, INVALID, INVALID, INVALID, INVALID, INVALID, INVALID, INVALID, INVALID, - + /*30*/ PAIR_NP | CYCLES(9), CYCLES(1), PAIR_NP | CYCLES(9), INVALID, INVALID, INVALID, INVALID, INVALID, INVALID, INVALID, INVALID, INVALID, INVALID, INVALID, INVALID, INVALID, -/*40*/ INVALID, INVALID, INVALID, INVALID, - INVALID, INVALID, INVALID, INVALID, +/*40*/ INVALID, INVALID, INVALID, INVALID, INVALID, INVALID, INVALID, INVALID, INVALID, INVALID, INVALID, INVALID, - + INVALID, INVALID, INVALID, INVALID, + /*50*/ INVALID, INVALID, INVALID, INVALID, INVALID, INVALID, INVALID, INVALID, INVALID, INVALID, INVALID, INVALID, INVALID, INVALID, INVALID, INVALID, - + /*60*/ PAIR_U | CYCLES_RM, PAIR_U | CYCLES_RM, PAIR_U | CYCLES_RM, PAIR_U | CYCLES_RM, PAIR_U | CYCLES_RM, PAIR_U | CYCLES_RM, PAIR_U | CYCLES_RM, PAIR_U | CYCLES_RM, PAIR_U | CYCLES_RM, PAIR_U | CYCLES_RM, PAIR_U | CYCLES_RM, PAIR_U | CYCLES_RM, INVALID, INVALID, PAIR_U | CYCLES_RM, PAIR_U | CYCLES_RM, - + /*70*/ INVALID, PAIR_U | CYCLES_RM, PAIR_U | CYCLES_RM, PAIR_U | CYCLES_RM, PAIR_U | CYCLES_RM, PAIR_U | CYCLES_RM, PAIR_U | CYCLES_RM, PAIR_NP | CYCLES(100), INVALID, INVALID, INVALID, INVALID, @@ -428,17 +430,17 @@ static uint64_t opcode_timings_0f[256] = PAIR_NP | CYCLES(2), PAIR_NP | CYCLES(2), PAIR_NP | CYCLES(2), PAIR_NP | CYCLES(2), PAIR_NP | CYCLES(2), PAIR_NP | CYCLES(2), PAIR_NP | CYCLES(2), PAIR_NP | CYCLES(2), PAIR_NP | CYCLES(2), PAIR_NP | CYCLES(2), PAIR_NP | CYCLES(2), PAIR_NP | CYCLES(2), - + /*90*/ PAIR_NP | CYCLES(3), PAIR_NP | CYCLES(3), PAIR_NP | CYCLES(3), PAIR_NP | CYCLES(3), PAIR_NP | CYCLES(3), PAIR_NP | CYCLES(3), PAIR_NP | CYCLES(3), PAIR_NP | CYCLES(3), PAIR_NP | CYCLES(3), PAIR_NP | CYCLES(3), PAIR_NP | CYCLES(3), PAIR_NP | CYCLES(3), PAIR_NP | CYCLES(3), PAIR_NP | CYCLES(3), PAIR_NP | CYCLES(3), PAIR_NP | CYCLES(3), - + /*a0*/ PAIR_NP | CYCLES(3), PAIR_NP | CYCLES(3), PAIR_NP | CYCLES(14), PAIR_NP | CYCLES(8), PAIR_NP | CYCLES(3), PAIR_NP | CYCLES(4), INVALID, INVALID, PAIR_NP | CYCLES(3), PAIR_NP | CYCLES(3), INVALID, PAIR_NP | CYCLES(13), PAIR_NP | CYCLES(3), PAIR_NP | CYCLES(3), INVALID, PAIR_NP | CYCLES(10), - + /*b0*/ PAIR_NP | CYCLES(10), PAIR_NP | CYCLES(10), PAIR_NP | CYCLES(6), PAIR_NP | CYCLES(13), PAIR_NP | CYCLES(6), PAIR_NP | CYCLES(6), PAIR_NP | CYCLES(3), PAIR_NP | CYCLES(3), INVALID, INVALID, PAIR_NP | CYCLES(6), PAIR_NP | CYCLES(13), @@ -453,24 +455,25 @@ static uint64_t opcode_timings_0f[256] = INVALID, PAIR_U | CYCLES_RM, INVALID, INVALID, PAIR_U | CYCLES_RM, PAIR_U | CYCLES_RM, INVALID, PAIR_U | CYCLES_RM, PAIR_U | CYCLES_RM, PAIR_U | CYCLES_RM, INVALID, PAIR_U | CYCLES_RM, - + /*e0*/ INVALID, PAIR_U | CYCLES_RM, PAIR_U | CYCLES_RM, INVALID, INVALID, PAIR_U | CYCLES_RM, INVALID, INVALID, PAIR_U | CYCLES_RM, PAIR_U | CYCLES_RM, INVALID, PAIR_U | CYCLES_RM, PAIR_U | CYCLES_RM, PAIR_U | CYCLES_RM, INVALID, PAIR_U | CYCLES_RM, - + /*f0*/ INVALID, PAIR_U | CYCLES_RM, PAIR_U | CYCLES_RM, PAIR_U | CYCLES_RM, INVALID, PAIR_U | CYCLES_RM, INVALID, INVALID, PAIR_U | CYCLES_RM, PAIR_U | CYCLES_RM, PAIR_U | CYCLES_RM, INVALID, PAIR_U | CYCLES_RM, PAIR_U | CYCLES_RM, PAIR_U | CYCLES_RM, INVALID, + // clang-format on }; -static uint64_t opcode_timings_0f_mod3[256] = -{ +static uint64_t opcode_timings_0f_mod3[256] = { + // clang-format off /*00*/ PAIR_NP | CYCLES(20), PAIR_NP | CYCLES(11), PAIR_NP | CYCLES(11), PAIR_NP | CYCLES(10), INVALID, PAIR_NP | CYCLES(195), PAIR_NP | CYCLES(7), INVALID, PAIR_NP | CYCLES(1000), PAIR_NP | CYCLES(10000), INVALID, INVALID, INVALID, INVALID, INVALID, INVALID, - + /*10*/ INVALID, INVALID, INVALID, INVALID, INVALID, INVALID, INVALID, INVALID, INVALID, INVALID, INVALID, INVALID, @@ -480,7 +483,7 @@ static uint64_t opcode_timings_0f_mod3[256] = PAIR_NP | CYCLES(6), PAIR_NP | CYCLES(6), INVALID, INVALID, INVALID, INVALID, INVALID, INVALID, INVALID, INVALID, INVALID, INVALID, - + /*30*/ PAIR_NP | CYCLES(9), PAIR_NP | CYCLES(1), PAIR_NP | CYCLES(9), INVALID, INVALID, INVALID, INVALID, INVALID, INVALID, INVALID, INVALID, INVALID, @@ -490,17 +493,17 @@ static uint64_t opcode_timings_0f_mod3[256] = INVALID, INVALID, INVALID, INVALID, INVALID, INVALID, INVALID, INVALID, INVALID, INVALID, INVALID, INVALID, - + /*50*/ INVALID, INVALID, INVALID, INVALID, INVALID, INVALID, INVALID, INVALID, INVALID, INVALID, INVALID, INVALID, INVALID, INVALID, INVALID, INVALID, - + /*60*/ PAIR_UV | CYCLES_REG, PAIR_UV | CYCLES_REG, PAIR_UV | CYCLES_REG, PAIR_UV | CYCLES_REG, PAIR_UV | CYCLES_REG, PAIR_UV | CYCLES_REG, PAIR_UV | CYCLES_REG, PAIR_UV | CYCLES_REG, PAIR_UV | CYCLES_REG, PAIR_UV | CYCLES_REG, PAIR_UV | CYCLES_REG, PAIR_UV | CYCLES_REG, INVALID, INVALID, PAIR_UV | CYCLES_REG, PAIR_UV | CYCLES_REG, - + /*70*/ INVALID, PAIR_UV | CYCLES_REG, PAIR_UV | CYCLES_REG, PAIR_UV | CYCLES_REG, PAIR_UV | CYCLES_REG, PAIR_UV | CYCLES_REG, PAIR_UV | CYCLES_REG, PAIR_NP | CYCLES(100), INVALID, INVALID, INVALID, INVALID, @@ -515,12 +518,12 @@ static uint64_t opcode_timings_0f_mod3[256] = PAIR_NP | CYCLES(3), PAIR_NP | CYCLES(3), PAIR_NP | CYCLES(3), PAIR_NP | CYCLES(3), PAIR_NP | CYCLES(3), PAIR_NP | CYCLES(3), PAIR_NP | CYCLES(3), PAIR_NP | CYCLES(3), PAIR_NP | CYCLES(3), PAIR_NP | CYCLES(3), PAIR_NP | CYCLES(3), PAIR_NP | CYCLES(3), - + /*a0*/ PAIR_NP | CYCLES(3), PAIR_NP | CYCLES(3), PAIR_NP | CYCLES(14), PAIR_NP | CYCLES(8), PAIR_NP | CYCLES(3), PAIR_NP | CYCLES(4), INVALID, INVALID, PAIR_NP | CYCLES(3), PAIR_NP | CYCLES(3), INVALID, PAIR_NP | CYCLES(13), PAIR_NP | CYCLES(3), PAIR_NP | CYCLES(3), INVALID, PAIR_NP | CYCLES(10), - + /*b0*/ PAIR_NP | CYCLES(10), PAIR_NP | CYCLES(10), PAIR_NP | CYCLES(6), PAIR_NP | CYCLES(13), PAIR_NP | CYCLES(6), PAIR_NP | CYCLES(6), PAIR_NP | CYCLES(3), PAIR_NP | CYCLES(3), INVALID, INVALID, PAIR_NP | CYCLES(6), PAIR_NP | CYCLES(13), @@ -530,101 +533,113 @@ static uint64_t opcode_timings_0f_mod3[256] = INVALID, INVALID, INVALID, INVALID, PAIR_NP | CYCLES(1), PAIR_NP | CYCLES(1), PAIR_NP | CYCLES(1), PAIR_NP | CYCLES(1), PAIR_NP | CYCLES(1), PAIR_NP | CYCLES(1), PAIR_NP | CYCLES(1), PAIR_NP | CYCLES(1), - + /*d0*/ INVALID, PAIR_UV | CYCLES_REG, PAIR_UV | CYCLES_REG, PAIR_UV | CYCLES_REG, INVALID, PAIR_UV | CYCLES_REG, INVALID, INVALID, PAIR_UV | CYCLES_REG, PAIR_UV | CYCLES_REG, INVALID, PAIR_UV | CYCLES_REG, PAIR_UV | CYCLES_REG, PAIR_UV | CYCLES_REG, INVALID, PAIR_UV | CYCLES_REG, - + /*e0*/ INVALID, PAIR_UV | CYCLES_REG, PAIR_UV | CYCLES_REG, INVALID, INVALID, PAIR_UV | CYCLES_REG, INVALID, INVALID, PAIR_UV | CYCLES_REG, PAIR_UV | CYCLES_REG, INVALID, PAIR_UV | CYCLES_REG, - PAIR_UV | CYCLES_REG, PAIR_UV | CYCLES_REG, INVALID, PAIR_UV | CYCLES_REG, - + PAIR_UV | CYCLES_REG, PAIR_UV | CYCLES_REG, INVALID, PAIR_UV | CYCLES_REG, + /*f0*/ INVALID, PAIR_UV | CYCLES_REG, PAIR_UV | CYCLES_REG, PAIR_UV | CYCLES_REG, INVALID, PAIR_UV | CYCLES_REG, INVALID, INVALID, PAIR_UV | CYCLES_REG, PAIR_UV | CYCLES_REG, PAIR_UV | CYCLES_REG, INVALID, PAIR_UV | CYCLES_REG, PAIR_UV | CYCLES_REG, PAIR_UV | CYCLES_REG, INVALID, + // clang-format on }; -static uint64_t opcode_timings_shift[8] = -{ +static uint64_t opcode_timings_shift[8] = { + // clang-format off PAIR_U | CYCLES_RMW, PAIR_U | CYCLES_RMW, PAIR_U | CYCLES_RMW, PAIR_U | CYCLES_RMW, PAIR_U | CYCLES_RMW, PAIR_U | CYCLES_RMW, PAIR_U | CYCLES_RMW, PAIR_U | CYCLES_RMW, + // clang-format on }; -static uint64_t opcode_timings_shift_mod3[8] = -{ +static uint64_t opcode_timings_shift_mod3[8] = { + // clang-format off PAIR_U | CYCLES_REG, PAIR_U | CYCLES_REG, PAIR_U | CYCLES_REG, PAIR_U | CYCLES_REG, PAIR_U | CYCLES_REG, PAIR_U | CYCLES_REG, PAIR_U | CYCLES_REG, PAIR_U | CYCLES_REG, + // clang-format on }; -static uint64_t opcode_timings_f6[8] = -{ +static uint64_t opcode_timings_f6[8] = { + // clang-format off /* TST NOT NEG*/ PAIR_UV | CYCLES_RM, INVALID, PAIR_NP | CYCLES(3), PAIR_NP | CYCLES(3), /* MUL IMUL DIV IDIV*/ PAIR_NP | CYCLES(11), PAIR_NP | CYCLES(11), PAIR_NP | CYCLES(17), PAIR_NP | CYCLES(22) + // clang-format on }; -static uint64_t opcode_timings_f6_mod3[8] = -{ +static uint64_t opcode_timings_f6_mod3[8] = { + // clang-format off /* TST NOT NEG*/ PAIR_UV | CYCLES_REG, INVALID, PAIR_NP | CYCLES(3), PAIR_NP | CYCLES(3), /* MUL IMUL DIV IDIV*/ PAIR_NP | CYCLES(11), PAIR_NP | CYCLES(11), PAIR_NP | CYCLES(17), PAIR_NP | CYCLES(22) + // clang-format on }; -static uint64_t opcode_timings_f7[8] = -{ +static uint64_t opcode_timings_f7[8] = { + // clang-format off /* TST NOT NEG*/ PAIR_UV | CYCLES_RM, INVALID, PAIR_NP | CYCLES(3), PAIR_NP | CYCLES(3), /* MUL IMUL DIV IDIV*/ PAIR_NP | CYCLES_MULTI(11,10), PAIR_NP | CYCLES_MULTI(11,10), PAIR_NP | CYCLES_MULTI(25,41), PAIR_NP | CYCLES_MULTI(30,46) + // clang-format on }; -static uint64_t opcode_timings_f7_mod3[8] = -{ +static uint64_t opcode_timings_f7_mod3[8] = { + // clang-format off /* TST NOT NEG*/ PAIR_UV | CYCLES_REG, INVALID, PAIR_NP | CYCLES(3), PAIR_NP | CYCLES(3), /* MUL IMUL DIV IDIV*/ PAIR_NP | CYCLES_MULTI(11,10), PAIR_NP | CYCLES_MULTI(11,10), PAIR_NP | CYCLES_MULTI(25,41), PAIR_NP | CYCLES_MULTI(30,46) + // clang-format on }; -static uint64_t opcode_timings_ff[8] = -{ +static uint64_t opcode_timings_ff[8] = { + // clang-format off /* INC DEC CALL CALL far*/ PAIR_UV | CYCLES_RMW, PAIR_UV | CYCLES_RMW, PAIR_NP | CYCLES(4), PAIR_NP | CYCLES(0), /* JMP JMP far PUSH*/ PAIR_NP | CYCLES(2), PAIR_NP | CYCLES(0), PAIR_NP | CYCLES(2), INVALID + // clang-format on }; -static uint64_t opcode_timings_ff_mod3[8] = -{ +static uint64_t opcode_timings_ff_mod3[8] = { + // clang-format off /* INC DEC CALL CALL far*/ PAIR_UV | CYCLES_REG, PAIR_UV | CYCLES_REG, PAIR_NP | CYCLES(4), PAIR_NP | CYCLES(0), /* JMP JMP far PUSH*/ PAIR_NP | CYCLES(2), PAIR_NP | CYCLES(0), PAIR_NP | CYCLES(2), INVALID + // clang-format on }; -static uint64_t opcode_timings_d8[8] = -{ +static uint64_t opcode_timings_d8[8] = { + // clang-format off /* FADDs FMULs FCOMs FCOMPs*/ PAIR_FX | FPU_CYCLES(3,2,2), PAIR_FX | FPU_CYCLES(3,2,2), PAIR_FX | FPU_CYCLES(1,0,0), PAIR_FX | FPU_CYCLES(1,0,0), /* FSUBs FSUBRs FDIVs FDIVRs*/ PAIR_FX | FPU_CYCLES(3,2,2), PAIR_FX | FPU_CYCLES(3,2,2), PAIR_FX | FPU_CYCLES(39,38,2), PAIR_FX | FPU_CYCLES(39,38,2) + // clang-format on }; -static uint64_t opcode_timings_d8_mod3[8] = -{ +static uint64_t opcode_timings_d8_mod3[8] = { + // clang-format off /* FADD FMUL FCOM FCOMP*/ PAIR_FX | FPU_CYCLES(3,2,2), PAIR_FX | FPU_CYCLES(3,2,2), PAIR_FX | FPU_CYCLES(1,0,0), PAIR_FX | FPU_CYCLES(1,0,0), /* FSUB FSUBR FDIV FDIVR*/ PAIR_FX | FPU_CYCLES(3,2,2), PAIR_FX | FPU_CYCLES(3,2,2), PAIR_FX | FPU_CYCLES(39,38,2), PAIR_FX | FPU_CYCLES(39,38,2) + // clang-format on }; -static uint64_t opcode_timings_d9[8] = -{ +static uint64_t opcode_timings_d9[8] = { + // clang-format off /* FLDs FSTs FSTPs*/ PAIR_FX | FPU_CYCLES(1,0,0), INVALID, PAIR_NP | FPU_CYCLES(2,0,0), PAIR_NP | FPU_CYCLES(2,0,0), /* FLDENV FLDCW FSTENV FSTCW*/ PAIR_NP | FPU_CYCLES(32,0,0), PAIR_NP | FPU_CYCLES(8,0,0), PAIR_NP | FPU_CYCLES(48,0,0), PAIR_NP | FPU_CYCLES(2,0,0) + // clang-format on }; -static uint64_t opcode_timings_d9_mod3[64] = -{ +static uint64_t opcode_timings_d9_mod3[64] = { + // clang-format off /*FLD*/ PAIR_FX | FPU_CYCLES(1,0,0), PAIR_FX | FPU_CYCLES(1,0,0), PAIR_FX | FPU_CYCLES(1,0,0), PAIR_FX | FPU_CYCLES(1,0,0), PAIR_FX | FPU_CYCLES(1,0,0), PAIR_FX | FPU_CYCLES(1,0,0), PAIR_FX | FPU_CYCLES(1,0,0), PAIR_FX | FPU_CYCLES(1,0,0), @@ -633,7 +648,7 @@ static uint64_t opcode_timings_d9_mod3[64] = PAIR_FXCH | CYCLES(0), PAIR_FXCH | CYCLES(0), PAIR_FXCH | CYCLES(0), PAIR_FXCH | CYCLES(0), /*FNOP*/ PAIR_NP | FPU_CYCLES(3,0,0), INVALID, INVALID, INVALID, - INVALID, INVALID, INVALID, INVALID, + INVALID, INVALID, INVALID, INVALID, /*FSTP*/ PAIR_NP | FPU_CYCLES(1,0,0), PAIR_NP | FPU_CYCLES(1,0,0), PAIR_NP | FPU_CYCLES(1,0,0), PAIR_NP | FPU_CYCLES(1,0,0), PAIR_NP | FPU_CYCLES(1,0,0), PAIR_NP | FPU_CYCLES(1,0,0), PAIR_NP | FPU_CYCLES(1,0,0), PAIR_NP | FPU_CYCLES(1,0,0), @@ -653,667 +668,660 @@ static uint64_t opcode_timings_d9_mod3[64] = PAIR_NP | FPU_CYCLES(64,2,2), INVALID, PAIR_NP | FPU_CYCLES(70,69,2), PAIR_NP | FPU_CYCLES(89,2,2), /* opFRNDINT opFSCALE opFSIN opFCOS*/ PAIR_NP | FPU_CYCLES(9,0,0), PAIR_NP | FPU_CYCLES(20,5,0), PAIR_NP | FPU_CYCLES(65,2,2), PAIR_NP | FPU_CYCLES(65,2,2) + // clang-format on }; -static uint64_t opcode_timings_da[8] = -{ +static uint64_t opcode_timings_da[8] = { + // clang-format off /* FIADDl FIMULl FICOMl FICOMPl*/ PAIR_NP | FPU_CYCLES(6,2,2), PAIR_NP | FPU_CYCLES(6,2,2), PAIR_NP | FPU_CYCLES(4,0,0), PAIR_NP | FPU_CYCLES(4,0,0), /* FISUBl FISUBRl FIDIVl FIDIVRl*/ PAIR_NP | FPU_CYCLES(6,2,2), PAIR_NP | FPU_CYCLES(6,2,2), PAIR_NP | FPU_CYCLES(42,38,2), PAIR_NP | FPU_CYCLES(42,38,2) + // clang-format on }; -static uint64_t opcode_timings_da_mod3[8] = -{ +static uint64_t opcode_timings_da_mod3[8] = { + // clang-format off INVALID, INVALID, INVALID, INVALID, /* FCOMPP*/ INVALID, PAIR_NP | FPU_CYCLES(1,0,0), INVALID, INVALID + // clang-format on }; - -static uint64_t opcode_timings_db[8] = -{ +static uint64_t opcode_timings_db[8] = { + // clang-format off /* FLDil FSTil FSTPil*/ PAIR_NP | FPU_CYCLES(3,2,2), INVALID, PAIR_NP | FPU_CYCLES(6,0,0), PAIR_NP | FPU_CYCLES(6,0,0), /* FLDe FSTPe*/ INVALID, PAIR_NP | FPU_CYCLES(3,0,0), INVALID, PAIR_NP | FPU_CYCLES(3,0,0) + // clang-format on }; -static uint64_t opcode_timings_db_mod3[64] = -{ +static uint64_t opcode_timings_db_mod3[64] = { + // clang-format off INVALID, INVALID, INVALID, INVALID, INVALID, INVALID, INVALID, INVALID, - + INVALID, INVALID, INVALID, INVALID, INVALID, INVALID, INVALID, INVALID, - + INVALID, INVALID, INVALID, INVALID, INVALID, INVALID, INVALID, INVALID, - + INVALID, INVALID, INVALID, INVALID, INVALID, INVALID, INVALID, INVALID, - + /* opFNOP opFCLEX opFINIT*/ INVALID, PAIR_NP | FPU_CYCLES(1,0,0), PAIR_NP | FPU_CYCLES(7,0,0), PAIR_NP | FPU_CYCLES(17,0,0), /* opFNOP opFNOP*/ PAIR_NP | FPU_CYCLES(1,0,0), PAIR_NP | FPU_CYCLES(1,0,0), INVALID, INVALID, - + INVALID, INVALID, INVALID, INVALID, INVALID, INVALID, INVALID, INVALID, - + INVALID, INVALID, INVALID, INVALID, INVALID, INVALID, INVALID, INVALID, - + INVALID, INVALID, INVALID, INVALID, INVALID, INVALID, INVALID, INVALID, + // clang-format on }; -static uint64_t opcode_timings_dc[8] = -{ +static uint64_t opcode_timings_dc[8] = { + // clang-format off /* FADDd FMULd FCOMd FCOMPd*/ PAIR_FX | FPU_CYCLES(3,2,2), PAIR_FX | FPU_CYCLES(3,2,2), PAIR_FX | FPU_CYCLES(1,0,0), PAIR_FX | FPU_CYCLES(1,0,0), /* FSUBd FSUBRd FDIVd FDIVRd*/ PAIR_FX | FPU_CYCLES(3,2,2), PAIR_FX | FPU_CYCLES(3,2,2), PAIR_FX | FPU_CYCLES(39,38,2), PAIR_FX | FPU_CYCLES(39,38,2) + // clang-format on }; -static uint64_t opcode_timings_dc_mod3[8] = -{ +static uint64_t opcode_timings_dc_mod3[8] = { + // clang-format off /* opFADDr opFMULr*/ PAIR_FX | FPU_CYCLES(3,2,2), PAIR_FX | FPU_CYCLES(3,2,2), INVALID, INVALID, /* opFSUBRr opFSUBr opFDIVRr opFDIVr*/ PAIR_FX | FPU_CYCLES(3,2,2), PAIR_FX | FPU_CYCLES(3,2,2), PAIR_FX | FPU_CYCLES(39,38,2), PAIR_FX | FPU_CYCLES(39,38,2) + // clang-format on }; -static uint64_t opcode_timings_dd[8] = -{ +static uint64_t opcode_timings_dd[8] = { + // clang-format off /* FLDd FSTd FSTPd*/ PAIR_FX | FPU_CYCLES(1,0,0), INVALID, PAIR_NP | FPU_CYCLES(2,0,0), PAIR_NP | FPU_CYCLES(2,0,0), /* FRSTOR FSAVE FSTSW*/ PAIR_NP | FPU_CYCLES(70,0,0), INVALID, PAIR_NP | FPU_CYCLES(127,0,0), PAIR_NP | FPU_CYCLES(6,0,0) + // clang-format on }; -static uint64_t opcode_timings_dd_mod3[8] = -{ +static uint64_t opcode_timings_dd_mod3[8] = { + // clang-format off /* FFFREE FST FSTP*/ PAIR_NP | FPU_CYCLES(2,0,0), INVALID, PAIR_NP | FPU_CYCLES(1,0,0), PAIR_NP | FPU_CYCLES(1,0,0), /* FUCOM FUCOMP*/ PAIR_NP | FPU_CYCLES(1,0,0), PAIR_NP | FPU_CYCLES(1,0,0), INVALID, INVALID + // clang-format on }; -static uint64_t opcode_timings_de[8] = -{ +static uint64_t opcode_timings_de[8] = { + // clang-format off /* FIADDw FIMULw FICOMw FICOMPw*/ PAIR_NP | FPU_CYCLES(6,2,2), PAIR_NP | FPU_CYCLES(6,2,2), PAIR_NP | FPU_CYCLES(4,0,0), PAIR_NP | FPU_CYCLES(4,0,0), /* FISUBw FISUBRw FIDIVw FIDIVRw*/ PAIR_NP | FPU_CYCLES(6,2,2), PAIR_NP | FPU_CYCLES(6,2,2), PAIR_NP | FPU_CYCLES(42,38,2), PAIR_NP | FPU_CYCLES(42,38,2) + // clang-format on }; -static uint64_t opcode_timings_de_mod3[8] = -{ +static uint64_t opcode_timings_de_mod3[8] = { + // clang-format off /* FADDP FMULP FCOMPP*/ PAIR_FX | FPU_CYCLES(3,2,2), PAIR_FX | FPU_CYCLES(3,2,2), INVALID, PAIR_FX | FPU_CYCLES(1,0,0), /* FSUBP FSUBRP FDIVP FDIVRP*/ PAIR_FX | FPU_CYCLES(3,2,2), PAIR_FX | FPU_CYCLES(3,2,2), PAIR_FX | FPU_CYCLES(39,38,2), PAIR_FX | FPU_CYCLES(39,38,2) + // clang-format on }; -static uint64_t opcode_timings_df[8] = -{ +static uint64_t opcode_timings_df[8] = { + // clang-format off /* FILDiw FISTiw FISTPiw*/ PAIR_NP | FPU_CYCLES(3,2,2), INVALID, PAIR_NP | FPU_CYCLES(6,0,0), PAIR_NP | FPU_CYCLES(6,0,0), /* FILDiq FBSTP FISTPiq*/ INVALID, PAIR_NP | FPU_CYCLES(3,2,2), PAIR_NP | FPU_CYCLES(148,0,0), PAIR_NP | FPU_CYCLES(6,0,0) + // clang-format on }; -static uint64_t opcode_timings_df_mod3[8] = -{ +static uint64_t opcode_timings_df_mod3[8] = { + // clang-format off INVALID, INVALID, INVALID, INVALID, /* FSTSW AX*/ PAIR_NP | FPU_CYCLES(6,0,0), INVALID, INVALID, INVALID + // clang-format on }; -static uint64_t opcode_timings_81[8] = -{ +static uint64_t opcode_timings_81[8] = { + // clang-format off PAIR_UV | CYCLES_RMW | CYCLES_IMM1632, PAIR_UV | CYCLES_RMW | CYCLES_IMM1632, PAIR_UV | CYCLES_RMW | CYCLES_IMM1632, PAIR_UV | CYCLES_RMW | CYCLES_IMM1632, PAIR_UV | CYCLES_RMW | CYCLES_IMM1632, PAIR_UV | CYCLES_RMW | CYCLES_IMM1632, PAIR_UV | CYCLES_RMW | CYCLES_IMM1632, PAIR_UV | CYCLES_RM | CYCLES_IMM1632 + // clang-format on }; -static uint64_t opcode_timings_81_mod3[8] = -{ +static uint64_t opcode_timings_81_mod3[8] = { + // clang-format off PAIR_UV | CYCLES_REG, PAIR_UV | CYCLES_REG, PAIR_UV | CYCLES_REG, PAIR_UV | CYCLES_REG, PAIR_UV | CYCLES_REG, PAIR_UV | CYCLES_REG, PAIR_UV | CYCLES_REG, PAIR_UV | CYCLES_REG + // clang-format on }; -static uint64_t opcode_timings_8x[8] = -{ +static uint64_t opcode_timings_8x[8] = { + // clang-format off PAIR_UV | CYCLES_RMW | CYCLES_IMM8, PAIR_UV | CYCLES_RMW | CYCLES_IMM8, PAIR_UV | CYCLES_RMW | CYCLES_IMM8, PAIR_UV | CYCLES_RMW | CYCLES_IMM8, PAIR_UV | CYCLES_RMW | CYCLES_IMM8, PAIR_UV | CYCLES_RMW | CYCLES_IMM8, PAIR_UV | CYCLES_RMW | CYCLES_IMM8, PAIR_UV | CYCLES_RM | CYCLES_IMM8 + // clang-format on }; -static uint64_t opcode_timings_8x_mod3[8] = -{ +static uint64_t opcode_timings_8x_mod3[8] = { + // clang-format off PAIR_UV | CYCLES_REG, PAIR_UV | CYCLES_REG, PAIR_UV | CYCLES_REG, PAIR_UV | CYCLES_REG, PAIR_UV | CYCLES_REG, PAIR_UV | CYCLES_REG, PAIR_UV | CYCLES_REG, PAIR_UV | CYCLES_REG + // clang-format on }; -static int decode_delay, decode_delay_offset; +static int decode_delay; +static int decode_delay_offset; static uint8_t last_prefix; -static int prefixes; +static int prefixes; -static inline int COUNT(uint64_t timings, uint64_t deps, int op_32) +static inline int +COUNT(uint64_t timings, uint64_t deps, int op_32) { - if ((timings & PAIR_FPU) && !(deps & FPU_FXCH)) - return FPU_I_LATENCY(timings); - if (timings & CYCLES_HAS_MULTI) - { - if (op_32 & 0x100) - return ((uintptr_t)timings >> 8) & 0xff; - return (uintptr_t)timings & 0xff; - } - if (!(timings & PAIR_MASK)) - return timings & 0xffff; - if ((timings & PAIR_MASK) == PAIR_FX) - return timings & 0xffff; - if ((timings & PAIR_MASK) == PAIR_FXCH) - return timings & 0xffff; - if ((timings & PAIR_UV) && !(timings & PAIR_FPU)) - timings &= 3; - switch (timings & CYCLES_MASK) - { - case CYCLES_REG: + if ((timings & PAIR_FPU) && !(deps & FPU_FXCH)) + return FPU_I_LATENCY(timings); + if (timings & CYCLES_HAS_MULTI) { + if (op_32 & 0x100) + return ((uintptr_t) timings >> 8) & 0xff; + return (uintptr_t) timings & 0xff; + } + if (!(timings & PAIR_MASK)) + return timings & 0xffff; + if ((timings & PAIR_MASK) == PAIR_FX) + return timings & 0xffff; + if ((timings & PAIR_MASK) == PAIR_FXCH) + return timings & 0xffff; + if ((timings & PAIR_UV) && !(timings & PAIR_FPU)) + timings &= 3; + switch (timings & CYCLES_MASK) { + case CYCLES_REG: + return 1; + case CYCLES_RM: + return 2; + case CYCLES_RMW: + return 3; + case CYCLES_BRANCH: + return cpu_has_feature(CPU_FEATURE_MMX) ? 1 : 2; + } + + fatal("Illegal COUNT %016" PRIu64 "\n", timings); + + return timings; +} + +static int +codegen_fpu_latencies(uint64_t deps, int reg) +{ + int latency = fpu_latency; + + if ((deps & FPU_RW_ST0) && fpu_st_latency[0] && fpu_st_latency[0] > latency) + latency = fpu_st_latency[0]; + if ((deps & FPU_RW_ST1) && fpu_st_latency[1] && fpu_st_latency[1] > latency) + latency = fpu_st_latency[1]; + if ((deps & FPU_RW_STREG) && fpu_st_latency[reg] && fpu_st_latency[reg] > latency) + latency = fpu_st_latency[reg]; + + return latency; +} + +#define SUB_AND_CLAMP(latency, count) \ + latency -= count; \ + if (latency < 0) \ + latency = 0 + +static void +codegen_fpu_latency_clock(int count) +{ + SUB_AND_CLAMP(fpu_latency, count); + SUB_AND_CLAMP(fpu_st_latency[0], count); + SUB_AND_CLAMP(fpu_st_latency[1], count); + SUB_AND_CLAMP(fpu_st_latency[2], count); + SUB_AND_CLAMP(fpu_st_latency[3], count); + SUB_AND_CLAMP(fpu_st_latency[4], count); + SUB_AND_CLAMP(fpu_st_latency[5], count); + SUB_AND_CLAMP(fpu_st_latency[6], count); + SUB_AND_CLAMP(fpu_st_latency[7], count); +} + +static inline int +codegen_timing_has_displacement(uint32_t fetchdat, int op_32) +{ + if (op_32 & 0x200) { + if ((fetchdat & 7) == 4 && (fetchdat & 0xc0) != 0xc0) { + /*Has SIB*/ + if ((fetchdat & 0xc0) == 0x40 || (fetchdat & 0xc0) == 0x80 || (fetchdat & 0x700) == 0x500) + return 1; + } else { + if ((fetchdat & 0xc0) == 0x40 || (fetchdat & 0xc0) == 0x80 || (fetchdat & 0xc7) == 0x05) return 1; - case CYCLES_RM: - return 2; - case CYCLES_RMW: - return 3; - case CYCLES_BRANCH: - return cpu_has_feature(CPU_FEATURE_MMX) ? 1 : 2; } - - fatal("Illegal COUNT %016llx\n", timings); - - return timings; + } else { + if ((fetchdat & 0xc0) == 0x40 || (fetchdat & 0xc0) == 0x80 || (fetchdat & 0xc7) == 0x06) + return 1; + } + return 0; } -static int codegen_fpu_latencies(uint64_t deps, int reg) -{ - int latency = fpu_latency; - - if ((deps & FPU_RW_ST0) && fpu_st_latency[0] && fpu_st_latency[0] > latency) - latency = fpu_st_latency[0]; - if ((deps & FPU_RW_ST1) && fpu_st_latency[1] && fpu_st_latency[1] > latency) - latency = fpu_st_latency[1]; - if ((deps & FPU_RW_STREG) && fpu_st_latency[reg] && fpu_st_latency[reg] > latency) - latency = fpu_st_latency[reg]; - - return latency; -} - -#define SUB_AND_CLAMP(latency, count) \ - latency -= count; \ - if (latency < 0) \ - latency = 0 - -static void codegen_fpu_latency_clock(int count) -{ - SUB_AND_CLAMP(fpu_latency, count); - SUB_AND_CLAMP(fpu_st_latency[0], count); - SUB_AND_CLAMP(fpu_st_latency[1], count); - SUB_AND_CLAMP(fpu_st_latency[2], count); - SUB_AND_CLAMP(fpu_st_latency[3], count); - SUB_AND_CLAMP(fpu_st_latency[4], count); - SUB_AND_CLAMP(fpu_st_latency[5], count); - SUB_AND_CLAMP(fpu_st_latency[6], count); - SUB_AND_CLAMP(fpu_st_latency[7], count); -} - -static inline int codegen_timing_has_displacement(uint32_t fetchdat, int op_32) -{ - if (op_32 & 0x200) - { - if ((fetchdat & 7) == 4 && (fetchdat & 0xc0) != 0xc0) - { - /*Has SIB*/ - if ((fetchdat & 0xc0) == 0x40 || (fetchdat & 0xc0) == 0x80 || (fetchdat & 0x700) == 0x500) - return 1; - } - else - { - if ((fetchdat & 0xc0) == 0x40 || (fetchdat & 0xc0) == 0x80 || (fetchdat & 0xc7) == 0x05) - return 1; - } - } - else - { - if ((fetchdat & 0xc0) == 0x40 || (fetchdat & 0xc0) == 0x80 || (fetchdat & 0xc7) == 0x06) - return 1; - } - return 0; -} - /*The instruction is only of interest here if it's longer than 7 bytes, as that's the limit on Pentium MMX parallel decoding*/ -static inline int codegen_timing_instr_length(uint64_t timing, uint32_t fetchdat, int op_32) +static inline int +codegen_timing_instr_length(uint64_t timing, uint32_t fetchdat, int op_32) { - int len = prefixes; - if ((timing & CYCLES_MASK) == CYCLES_RM || (timing & CYCLES_MASK) == CYCLES_RMW) - { - len += 2; /*Opcode + ModR/M*/ - if ((timing & CYCLES_HASIMM) == CYCLES_IMM8) - len++; - if ((timing & CYCLES_HASIMM) == CYCLES_IMM1632) - len += (op_32 & 0x100) ? 4 : 2; + int len = prefixes; + if ((timing & CYCLES_MASK) == CYCLES_RM || (timing & CYCLES_MASK) == CYCLES_RMW) { + len += 2; /*Opcode + ModR/M*/ + if ((timing & CYCLES_HASIMM) == CYCLES_IMM8) + len++; + if ((timing & CYCLES_HASIMM) == CYCLES_IMM1632) + len += (op_32 & 0x100) ? 4 : 2; - if (op_32 & 0x200) - { - if ((fetchdat & 7) == 4 && (fetchdat & 0xc0) != 0xc0) - { - /* Has SIB*/ - len++; - if ((fetchdat & 0xc0) == 0x40) - len++; - else if ((fetchdat & 0xc0) == 0x80) - len += 4; - else if ((fetchdat & 0x700) == 0x500) - len += 4; - } - else - { - if ((fetchdat & 0xc0) == 0x40) - len++; - else if ((fetchdat & 0xc0) == 0x80) - len += 4; - else if ((fetchdat & 0xc7) == 0x05) - len += 4; - } - } - else - { - if ((fetchdat & 0xc0) == 0x40) - len++; - else if ((fetchdat & 0xc0) == 0x80) - len += 2; - else if ((fetchdat & 0xc7) == 0x06) - len += 2; - } + if (op_32 & 0x200) { + if ((fetchdat & 7) == 4 && (fetchdat & 0xc0) != 0xc0) { + /* Has SIB*/ + len++; + if ((fetchdat & 0xc0) == 0x40) + len++; + else if ((fetchdat & 0xc0) == 0x80) + len += 4; + else if ((fetchdat & 0x700) == 0x500) + len += 4; + } else { + if ((fetchdat & 0xc0) == 0x40) + len++; + else if ((fetchdat & 0xc0) == 0x80) + len += 4; + else if ((fetchdat & 0xc7) == 0x05) + len += 4; + } + } else { + if ((fetchdat & 0xc0) == 0x40) + len++; + else if ((fetchdat & 0xc0) == 0x80) + len += 2; + else if ((fetchdat & 0xc7) == 0x06) + len += 2; } - - return len; + } + + return len; } -void codegen_timing_pentium_block_start() +void +codegen_timing_pentium_block_start(void) { - u_pipe_full = decode_delay = decode_delay_offset = 0; + u_pipe_full = decode_delay = decode_delay_offset = 0; } -void codegen_timing_pentium_start() +void +codegen_timing_pentium_start(void) { - last_prefix = 0; - prefixes = 0; + last_prefix = 0; + prefixes = 0; } -void codegen_timing_pentium_prefix(uint8_t prefix, uint32_t fetchdat) +void +codegen_timing_pentium_prefix(uint8_t prefix, uint32_t fetchdat) { - prefixes++; - if ((prefix & 0xf8) == 0xd8) - { - last_prefix = prefix; - return; - } - if (cpu_has_feature(CPU_FEATURE_MMX) && prefix == 0x0f) - { - /*On Pentium MMX 0fh prefix is 'free'*/ - last_prefix = prefix; - return; - } - if (cpu_has_feature(CPU_FEATURE_MMX) && (prefix == 0x66 || prefix == 0x67)) - { - /*On Pentium MMX 66h and 67h prefixes take 2 clocks*/ - decode_delay_offset += 2; - last_prefix = prefix; - return; - } - if (prefix == 0x0f && (fetchdat & 0xf0) == 0x80) - { - /*On Pentium 0fh prefix is 'free' when used on conditional jumps*/ - last_prefix = prefix; - return; - } - /*On Pentium all prefixes take 1 cycle to decode. Decode may be shadowed - by execution of previous instructions*/ - decode_delay_offset++; + prefixes++; + if ((prefix & 0xf8) == 0xd8) { last_prefix = prefix; + return; + } + if (cpu_has_feature(CPU_FEATURE_MMX) && prefix == 0x0f) { + /*On Pentium MMX 0fh prefix is 'free'*/ + last_prefix = prefix; + return; + } + if (cpu_has_feature(CPU_FEATURE_MMX) && (prefix == 0x66 || prefix == 0x67)) { + /*On Pentium MMX 66h and 67h prefixes take 2 clocks*/ + decode_delay_offset += 2; + last_prefix = prefix; + return; + } + if (prefix == 0x0f && (fetchdat & 0xf0) == 0x80) { + /*On Pentium 0fh prefix is 'free' when used on conditional jumps*/ + last_prefix = prefix; + return; + } + /*On Pentium all prefixes take 1 cycle to decode. Decode may be shadowed + by execution of previous instructions*/ + decode_delay_offset++; + last_prefix = prefix; } -static int check_agi(uint64_t *deps, uint8_t opcode, uint32_t fetchdat, int op_32) +static int +check_agi(uint64_t *deps, uint8_t opcode, uint32_t fetchdat, int op_32) { - uint32_t addr_regmask = get_addr_regmask(deps[opcode], fetchdat, op_32); + uint32_t addr_regmask = get_addr_regmask(deps[opcode], fetchdat, op_32); - /*Instructions that use ESP implicitly (eg PUSH, POP, CALL etc) do not - cause AGIs with each other, but do with instructions that use it explicitly*/ - if ((addr_regmask & REGMASK_IMPL_ESP) && (regmask_modified & (1 << REG_ESP)) && !(regmask_modified & REGMASK_IMPL_ESP)) - addr_regmask |= (1 << REG_ESP); + /*Instructions that use ESP implicitly (eg PUSH, POP, CALL etc) do not + cause AGIs with each other, but do with instructions that use it explicitly*/ + if ((addr_regmask & REGMASK_IMPL_ESP) && (regmask_modified & (1 << REG_ESP)) && !(regmask_modified & REGMASK_IMPL_ESP)) + addr_regmask |= (1 << REG_ESP); - return (regmask_modified & addr_regmask) & ~REGMASK_IMPL_ESP; + return (regmask_modified & addr_regmask) & ~REGMASK_IMPL_ESP; } -static void codegen_instruction(uint64_t *timings, uint64_t *deps, uint8_t opcode, uint32_t fetchdat, int decode_delay_offset, int op_32, int exec_delay) +static void +codegen_instruction(uint64_t *timings, uint64_t *deps, uint8_t opcode, uint32_t fetchdat, int decode_delay_offset, int op_32, int exec_delay) { - int instr_cycles, latency = 0; + int instr_cycles; + int latency = 0; - if ((timings[opcode] & PAIR_FPU) && !(deps[opcode] & FPU_FXCH)) - instr_cycles = latency = codegen_fpu_latencies(deps[opcode], fetchdat & 7); - else - { -/* if (timings[opcode] & FPU_WRITE_ST0) - fatal("FPU_WRITE_ST0\n"); - if (timings[opcode] & FPU_WRITE_ST1) - fatal("FPU_WRITE_ST1\n"); - if (timings[opcode] & FPU_WRITE_STREG) - fatal("FPU_WRITE_STREG\n");*/ - instr_cycles = 0; - } + if ((timings[opcode] & PAIR_FPU) && !(deps[opcode] & FPU_FXCH)) + instr_cycles = latency = codegen_fpu_latencies(deps[opcode], fetchdat & 7); + else { +#if 0 + if (timings[opcode] & FPU_WRITE_ST0) + fatal("FPU_WRITE_ST0\n"); + if (timings[opcode] & FPU_WRITE_ST1) + fatal("FPU_WRITE_ST1\n"); + if (timings[opcode] & FPU_WRITE_STREG) + fatal("FPU_WRITE_STREG\n");*/ +#endif + instr_cycles = 0; + } - if ((decode_delay + decode_delay_offset) > 0) - codegen_fpu_latency_clock(decode_delay + decode_delay_offset + instr_cycles); - else - codegen_fpu_latency_clock(instr_cycles); - instr_cycles += COUNT(timings[opcode], deps[opcode], op_32); - instr_cycles += exec_delay; - if ((decode_delay + decode_delay_offset) > 0) - codegen_block_cycles += instr_cycles + decode_delay + decode_delay_offset; - else - codegen_block_cycles += instr_cycles; + if ((decode_delay + decode_delay_offset) > 0) + codegen_fpu_latency_clock(decode_delay + decode_delay_offset + instr_cycles); + else + codegen_fpu_latency_clock(instr_cycles); + instr_cycles += COUNT(timings[opcode], deps[opcode], op_32); + instr_cycles += exec_delay; + if ((decode_delay + decode_delay_offset) > 0) + codegen_block_cycles += instr_cycles + decode_delay + decode_delay_offset; + else + codegen_block_cycles += instr_cycles; - decode_delay = (-instr_cycles) + 1; - + decode_delay = (-instr_cycles) + 1; + + if (deps[opcode] & FPU_POP) { + for (uint8_t c = 0; c < 7; c++) + fpu_st_latency[c] = fpu_st_latency[c + 1]; + fpu_st_latency[7] = 0; + } + if (deps[opcode] & FPU_POP2) { + for (uint8_t c = 0; c < 6; c++) + fpu_st_latency[c] = fpu_st_latency[c + 2]; + fpu_st_latency[6] = fpu_st_latency[7] = 0; + } + if ((timings[opcode] & PAIR_FPU) && !(deps[opcode] & FPU_FXCH)) { + fpu_latency = FPU_F_LATENCY(timings[opcode]); + } + + if (deps[opcode] & FPU_PUSH) { + for (uint8_t c = 0; c < 7; c++) + fpu_st_latency[c + 1] = fpu_st_latency[c]; + fpu_st_latency[0] = 0; + } + if (deps[opcode] & FPU_WRITE_ST0) { +#if 0 + if (fpu_st_latency[0]) + fatal("Bad latency ST0\n");*/ +#endif + fpu_st_latency[0] = FPU_RESULT_LATENCY(timings[opcode]); + } + if (deps[opcode] & FPU_WRITE_ST1) { +#if 0 + if (fpu_st_latency[1]) + fatal("Bad latency ST1\n");*/ +#endif + fpu_st_latency[1] = FPU_RESULT_LATENCY(timings[opcode]); + } + if (deps[opcode] & FPU_WRITE_STREG) { + int reg = fetchdat & 7; if (deps[opcode] & FPU_POP) - { - int c; - - for (c = 0; c < 7; c++) - fpu_st_latency[c] = fpu_st_latency[c+1]; - fpu_st_latency[7] = 0; - } - if (deps[opcode] & FPU_POP2) - { - int c; - - for (c = 0; c < 6; c++) - fpu_st_latency[c] = fpu_st_latency[c+2]; - fpu_st_latency[6] = fpu_st_latency[7] = 0; - } - if ((timings[opcode] & PAIR_FPU) && !(deps[opcode] & FPU_FXCH)) - { - fpu_latency = FPU_F_LATENCY(timings[opcode]); - } - - if (deps[opcode] & FPU_PUSH) - { - int c; - - for (c = 0; c < 7; c++) - fpu_st_latency[c+1] = fpu_st_latency[c]; - fpu_st_latency[0] = 0; - } - if (deps[opcode] & FPU_WRITE_ST0) - { -/* if (fpu_st_latency[0]) - fatal("Bad latency ST0\n");*/ - fpu_st_latency[0] = FPU_RESULT_LATENCY(timings[opcode]); - } - if (deps[opcode] & FPU_WRITE_ST1) - { -/* if (fpu_st_latency[1]) - fatal("Bad latency ST1\n");*/ - fpu_st_latency[1] = FPU_RESULT_LATENCY(timings[opcode]); - } - if (deps[opcode] & FPU_WRITE_STREG) - { - int reg = fetchdat & 7; - if (deps[opcode] & FPU_POP) - reg--; - if (reg >= 0 && - !(reg == 0 && (deps[opcode] & FPU_WRITE_ST0)) && - !(reg == 1 && (deps[opcode] & FPU_WRITE_ST1))) - { - fpu_st_latency[reg] = FPU_RESULT_LATENCY(timings[opcode]); - } + reg--; + if (reg >= 0 && !(reg == 0 && (deps[opcode] & FPU_WRITE_ST0)) && !(reg == 1 && (deps[opcode] & FPU_WRITE_ST1))) { + fpu_st_latency[reg] = FPU_RESULT_LATENCY(timings[opcode]); } + } } -void codegen_timing_pentium_opcode(uint8_t opcode, uint32_t fetchdat, int op_32, uint32_t op_pc) +void +codegen_timing_pentium_opcode(uint8_t opcode, uint32_t fetchdat, int op_32, UNUSED(uint32_t op_pc)) { - uint64_t *timings; - uint64_t *deps; - int mod3 = ((fetchdat & 0xc0) == 0xc0); - int bit8 = !(opcode & 1); - int agi_stall = 0; + uint64_t *timings; + uint64_t *deps; + int mod3 = ((fetchdat & 0xc0) == 0xc0); + int bit8 = !(opcode & 1); + int agi_stall = 0; - switch (last_prefix) - { - case 0x0f: - timings = mod3 ? opcode_timings_0f_mod3 : opcode_timings_0f; - deps = mod3 ? opcode_deps_0f_mod3 : opcode_deps_0f; - break; - - case 0xd8: - timings = mod3 ? opcode_timings_d8_mod3 : opcode_timings_d8; - deps = mod3 ? opcode_deps_d8_mod3 : opcode_deps_d8; - opcode = (opcode >> 3) & 7; - break; - case 0xd9: - timings = mod3 ? opcode_timings_d9_mod3 : opcode_timings_d9; - deps = mod3 ? opcode_deps_d9_mod3 : opcode_deps_d9; - opcode = mod3 ? opcode & 0x3f : (opcode >> 3) & 7; - break; - case 0xda: - timings = mod3 ? opcode_timings_da_mod3 : opcode_timings_da; - deps = mod3 ? opcode_deps_da_mod3 : opcode_deps_da; - opcode = (opcode >> 3) & 7; - break; - case 0xdb: - timings = mod3 ? opcode_timings_db_mod3 : opcode_timings_db; - deps = mod3 ? opcode_deps_db_mod3 : opcode_deps_db; - opcode = mod3 ? opcode & 0x3f : (opcode >> 3) & 7; - break; - case 0xdc: - timings = mod3 ? opcode_timings_dc_mod3 : opcode_timings_dc; - deps = mod3 ? opcode_deps_dc_mod3 : opcode_deps_dc; - opcode = (opcode >> 3) & 7; - break; - case 0xdd: - timings = mod3 ? opcode_timings_dd_mod3 : opcode_timings_dd; - deps = mod3 ? opcode_deps_dd_mod3 : opcode_deps_dd; - opcode = (opcode >> 3) & 7; - break; - case 0xde: - timings = mod3 ? opcode_timings_de_mod3 : opcode_timings_de; - deps = mod3 ? opcode_deps_de_mod3 : opcode_deps_de; - opcode = (opcode >> 3) & 7; - break; - case 0xdf: - timings = mod3 ? opcode_timings_df_mod3 : opcode_timings_df; - deps = mod3 ? opcode_deps_df_mod3 : opcode_deps_df; - opcode = (opcode >> 3) & 7; - break; + switch (last_prefix) { + case 0x0f: + timings = mod3 ? opcode_timings_0f_mod3 : opcode_timings_0f; + deps = mod3 ? opcode_deps_0f_mod3 : opcode_deps_0f; + break; + + case 0xd8: + timings = mod3 ? opcode_timings_d8_mod3 : opcode_timings_d8; + deps = mod3 ? opcode_deps_d8_mod3 : opcode_deps_d8; + opcode = (opcode >> 3) & 7; + break; + case 0xd9: + timings = mod3 ? opcode_timings_d9_mod3 : opcode_timings_d9; + deps = mod3 ? opcode_deps_d9_mod3 : opcode_deps_d9; + opcode = mod3 ? opcode & 0x3f : (opcode >> 3) & 7; + break; + case 0xda: + timings = mod3 ? opcode_timings_da_mod3 : opcode_timings_da; + deps = mod3 ? opcode_deps_da_mod3 : opcode_deps_da; + opcode = (opcode >> 3) & 7; + break; + case 0xdb: + timings = mod3 ? opcode_timings_db_mod3 : opcode_timings_db; + deps = mod3 ? opcode_deps_db_mod3 : opcode_deps_db; + opcode = mod3 ? opcode & 0x3f : (opcode >> 3) & 7; + break; + case 0xdc: + timings = mod3 ? opcode_timings_dc_mod3 : opcode_timings_dc; + deps = mod3 ? opcode_deps_dc_mod3 : opcode_deps_dc; + opcode = (opcode >> 3) & 7; + break; + case 0xdd: + timings = mod3 ? opcode_timings_dd_mod3 : opcode_timings_dd; + deps = mod3 ? opcode_deps_dd_mod3 : opcode_deps_dd; + opcode = (opcode >> 3) & 7; + break; + case 0xde: + timings = mod3 ? opcode_timings_de_mod3 : opcode_timings_de; + deps = mod3 ? opcode_deps_de_mod3 : opcode_deps_de; + opcode = (opcode >> 3) & 7; + break; + case 0xdf: + timings = mod3 ? opcode_timings_df_mod3 : opcode_timings_df; + deps = mod3 ? opcode_deps_df_mod3 : opcode_deps_df; + opcode = (opcode >> 3) & 7; + break; + + default: + switch (opcode) { + case 0x80: + case 0x82: + case 0x83: + timings = mod3 ? opcode_timings_8x_mod3 : opcode_timings_8x; + deps = mod3 ? opcode_deps_8x_mod3 : opcode_deps_8x; + opcode = (fetchdat >> 3) & 7; + break; + case 0x81: + timings = mod3 ? opcode_timings_81_mod3 : opcode_timings_81; + deps = mod3 ? opcode_deps_81_mod3 : opcode_deps_81; + opcode = (fetchdat >> 3) & 7; + break; + + case 0xc0: + case 0xc1: + case 0xd0: + case 0xd1: + timings = mod3 ? opcode_timings_shift_mod3 : opcode_timings_shift; + deps = mod3 ? opcode_deps_shift_mod3 : opcode_deps_shift; + opcode = (fetchdat >> 3) & 7; + break; + + case 0xd2: + case 0xd3: + timings = mod3 ? opcode_timings_shift_mod3 : opcode_timings_shift; + deps = mod3 ? opcode_deps_shift_cl_mod3 : opcode_deps_shift_cl; + opcode = (fetchdat >> 3) & 7; + break; + + case 0xf6: + timings = mod3 ? opcode_timings_f6_mod3 : opcode_timings_f6; + deps = mod3 ? opcode_deps_f6_mod3 : opcode_deps_f6; + opcode = (fetchdat >> 3) & 7; + break; + case 0xf7: + timings = mod3 ? opcode_timings_f7_mod3 : opcode_timings_f7; + deps = mod3 ? opcode_deps_f7_mod3 : opcode_deps_f7; + opcode = (fetchdat >> 3) & 7; + break; + case 0xff: + timings = mod3 ? opcode_timings_ff_mod3 : opcode_timings_ff; + deps = mod3 ? opcode_deps_ff_mod3 : opcode_deps_ff; + opcode = (fetchdat >> 3) & 7; + break; default: - switch (opcode) - { - case 0x80: case 0x82: case 0x83: - timings = mod3 ? opcode_timings_8x_mod3 : opcode_timings_8x; - deps = mod3 ? opcode_deps_8x_mod3 : opcode_deps_8x; - opcode = (fetchdat >> 3) & 7; - break; - case 0x81: - timings = mod3 ? opcode_timings_81_mod3 : opcode_timings_81; - deps = mod3 ? opcode_deps_81_mod3 : opcode_deps_81; - opcode = (fetchdat >> 3) & 7; - break; - - case 0xc0: case 0xc1: case 0xd0: case 0xd1: - timings = mod3 ? opcode_timings_shift_mod3 : opcode_timings_shift; - deps = mod3 ? opcode_deps_shift_mod3 : opcode_deps_shift; - opcode = (fetchdat >> 3) & 7; - break; - - case 0xd2: case 0xd3: - timings = mod3 ? opcode_timings_shift_mod3 : opcode_timings_shift; - deps = mod3 ? opcode_deps_shift_cl_mod3 : opcode_deps_shift_cl; - opcode = (fetchdat >> 3) & 7; - break; - - case 0xf6: - timings = mod3 ? opcode_timings_f6_mod3 : opcode_timings_f6; - deps = mod3 ? opcode_deps_f6_mod3 : opcode_deps_f6; - opcode = (fetchdat >> 3) & 7; - break; - case 0xf7: - timings = mod3 ? opcode_timings_f7_mod3 : opcode_timings_f7; - deps = mod3 ? opcode_deps_f7_mod3 : opcode_deps_f7; - opcode = (fetchdat >> 3) & 7; - break; - case 0xff: - timings = mod3 ? opcode_timings_ff_mod3 : opcode_timings_ff; - deps = mod3 ? opcode_deps_ff_mod3 : opcode_deps_ff; - opcode = (fetchdat >> 3) & 7; - break; + timings = mod3 ? opcode_timings_mod3 : opcode_timings; + deps = mod3 ? opcode_deps_mod3 : opcode_deps; + break; + } + } - default: - timings = mod3 ? opcode_timings_mod3 : opcode_timings; - deps = mod3 ? opcode_deps_mod3 : opcode_deps; - break; - } - } - - if (u_pipe_full) - { - uint8_t regmask = get_srcdep_mask(deps[opcode], fetchdat, bit8, u_pipe_op_32); + if (u_pipe_full) { + uint8_t regmask = get_srcdep_mask(deps[opcode], fetchdat, bit8, u_pipe_op_32); - if ((u_pipe_timings[u_pipe_opcode] & PAIR_MASK) == PAIR_FX && - (timings[opcode] & PAIR_MASK) != PAIR_FXCH) - goto nopair; + if ((u_pipe_timings[u_pipe_opcode] & PAIR_MASK) == PAIR_FX && (timings[opcode] & PAIR_MASK) != PAIR_FXCH) + goto nopair; - if ((timings[opcode] & PAIR_MASK) == PAIR_FXCH && - (u_pipe_timings[u_pipe_opcode] & PAIR_MASK) != PAIR_FX) - goto nopair; + if ((timings[opcode] & PAIR_MASK) == PAIR_FXCH && (u_pipe_timings[u_pipe_opcode] & PAIR_MASK) != PAIR_FX) + goto nopair; - if ((u_pipe_timings[u_pipe_opcode] & PAIR_MASK) == PAIR_FX && - (timings[opcode] & PAIR_MASK) == PAIR_FXCH) - { - int temp; + if ((u_pipe_timings[u_pipe_opcode] & PAIR_MASK) == PAIR_FX && (timings[opcode] & PAIR_MASK) == PAIR_FXCH) { + int temp; - if (check_agi(u_pipe_deps, u_pipe_opcode, u_pipe_fetchdat, u_pipe_op_32)) - agi_stall = 1; - - codegen_instruction(u_pipe_timings, u_pipe_deps, u_pipe_opcode, u_pipe_fetchdat, u_pipe_decode_delay_offset, u_pipe_op_32, agi_stall); - - temp = fpu_st_latency[fetchdat & 7]; - fpu_st_latency[fetchdat & 7] = fpu_st_latency[0]; - fpu_st_latency[0] = temp; - - u_pipe_full = 0; - decode_delay_offset = 0; - regmask_modified = u_pipe_regmask; - addr_regmask = 0; - return; - } - - if ((timings[opcode] & PAIR_V) && !(u_pipe_regmask & regmask) && (decode_delay+decode_delay_offset+u_pipe_decode_delay_offset) <= 0) - { - int has_displacement; - - if (timings[opcode] & CYCLES_HASIMM) - has_displacement = codegen_timing_has_displacement(fetchdat, op_32); - else - has_displacement = 0; - - if (!has_displacement && (!cpu_has_feature(CPU_FEATURE_MMX) || codegen_timing_instr_length(timings[opcode], fetchdat, op_32) <= 7)) - { - int t1 = u_pipe_timings[u_pipe_opcode] & CYCLES_MASK; - int t2 = timings[opcode] & CYCLES_MASK; - int t_pair; - uint64_t temp_timing; - uint64_t temp_deps = 0; - - if (!(u_pipe_timings[u_pipe_opcode] & PAIR_FPU)) - t1 &= 3; - if (!(timings[opcode] & PAIR_FPU)) - t2 &= 3; - - if (t1 < 0 || t2 < 0 || t1 > CYCLES_BRANCH || t2 > CYCLES_BRANCH) - fatal("Pair out of range\n"); - - t_pair = pair_timings[t1][t2]; - if (t_pair < 1) - fatal("Illegal pair timings : t1=%i t2=%i u_opcode=%02x v_opcode=%02x\n", t1, t2, u_pipe_opcode, opcode); - - /*Instruction can pair with previous*/ - temp_timing = t_pair; - if (check_agi(deps, opcode, fetchdat, op_32) || check_agi(u_pipe_deps, u_pipe_opcode, u_pipe_fetchdat, u_pipe_op_32)) - agi_stall = 1; - codegen_instruction(&temp_timing, &temp_deps, 0, 0, 0, 0, agi_stall); - u_pipe_full = 0; - decode_delay_offset = 0; - - regmask_modified = get_dstdep_mask(deps[opcode], fetchdat, bit8) | u_pipe_regmask; - addr_regmask = 0; - return; - } - } -nopair: - /*Instruction can not pair with previous*/ - /*Run previous now*/ - if (check_agi(u_pipe_deps, u_pipe_opcode, u_pipe_fetchdat, u_pipe_op_32)) - agi_stall = 1; - codegen_instruction(u_pipe_timings, u_pipe_deps, u_pipe_opcode, u_pipe_fetchdat, u_pipe_decode_delay_offset, u_pipe_op_32, agi_stall); - u_pipe_full = 0; - regmask_modified = u_pipe_regmask; - addr_regmask = 0; - } - - if ((timings[opcode] & PAIR_U) && (decode_delay + decode_delay_offset) <= 0) - { - int has_displacement; - - if (timings[opcode] & CYCLES_HASIMM) - has_displacement = codegen_timing_has_displacement(fetchdat, op_32); - else - has_displacement = 0; - - if ((!has_displacement || cpu_has_feature(CPU_FEATURE_MMX)) && (!cpu_has_feature(CPU_FEATURE_MMX) || codegen_timing_instr_length(timings[opcode], fetchdat, op_32) <= 7)) - { - /*Instruction might pair with next*/ - u_pipe_full = 1; - u_pipe_opcode = opcode; - u_pipe_timings = timings; - u_pipe_op_32 = op_32; - u_pipe_regmask = get_dstdep_mask(deps[opcode], fetchdat, bit8); - u_pipe_fetchdat = fetchdat; - u_pipe_decode_delay_offset = decode_delay_offset; - u_pipe_deps = deps; - decode_delay_offset = 0; - return; - } - } - /*Instruction can not pair and must run now*/ - if (check_agi(deps, opcode, fetchdat, op_32)) + if (check_agi(u_pipe_deps, u_pipe_opcode, u_pipe_fetchdat, u_pipe_op_32)) agi_stall = 1; - codegen_instruction(timings, deps, opcode, fetchdat, decode_delay_offset, op_32, agi_stall); - decode_delay_offset = 0; - regmask_modified = get_dstdep_mask(deps[opcode], fetchdat, bit8); - addr_regmask = 0; -} -void codegen_timing_pentium_block_end() -{ - if (u_pipe_full) - { - /*Run previous now*/ - if (check_agi(u_pipe_deps, u_pipe_opcode, u_pipe_fetchdat, u_pipe_op_32)) - codegen_block_cycles++; - codegen_block_cycles += COUNT(u_pipe_timings[u_pipe_opcode], u_pipe_deps[u_pipe_opcode], u_pipe_op_32) + decode_delay + decode_delay_offset; - u_pipe_full = 0; + codegen_instruction(u_pipe_timings, u_pipe_deps, u_pipe_opcode, u_pipe_fetchdat, u_pipe_decode_delay_offset, u_pipe_op_32, agi_stall); + + temp = fpu_st_latency[fetchdat & 7]; + fpu_st_latency[fetchdat & 7] = fpu_st_latency[0]; + fpu_st_latency[0] = temp; + + u_pipe_full = 0; + decode_delay_offset = 0; + regmask_modified = u_pipe_regmask; + addr_regmask = 0; + return; } + + if ((timings[opcode] & PAIR_V) && !(u_pipe_regmask & regmask) && (decode_delay + decode_delay_offset + u_pipe_decode_delay_offset) <= 0) { + int has_displacement; + + if (timings[opcode] & CYCLES_HASIMM) + has_displacement = codegen_timing_has_displacement(fetchdat, op_32); + else + has_displacement = 0; + + if (!has_displacement && (!cpu_has_feature(CPU_FEATURE_MMX) || codegen_timing_instr_length(timings[opcode], fetchdat, op_32) <= 7)) { + int t1 = u_pipe_timings[u_pipe_opcode] & CYCLES_MASK; + int t2 = timings[opcode] & CYCLES_MASK; + int t_pair; + uint64_t temp_timing; + uint64_t temp_deps = 0; + + if (!(u_pipe_timings[u_pipe_opcode] & PAIR_FPU)) + t1 &= 3; + if (!(timings[opcode] & PAIR_FPU)) + t2 &= 3; + + if (t1 < 0 || t2 < 0 || t1 > CYCLES_BRANCH || t2 > CYCLES_BRANCH) + fatal("Pair out of range\n"); + + t_pair = pair_timings[t1][t2]; + if (t_pair < 1) + fatal("Illegal pair timings : t1=%i t2=%i u_opcode=%02x v_opcode=%02x\n", t1, t2, u_pipe_opcode, opcode); + + /*Instruction can pair with previous*/ + temp_timing = t_pair; + if (check_agi(deps, opcode, fetchdat, op_32) || check_agi(u_pipe_deps, u_pipe_opcode, u_pipe_fetchdat, u_pipe_op_32)) + agi_stall = 1; + codegen_instruction(&temp_timing, &temp_deps, 0, 0, 0, 0, agi_stall); + u_pipe_full = 0; + decode_delay_offset = 0; + + regmask_modified = get_dstdep_mask(deps[opcode], fetchdat, bit8) | u_pipe_regmask; + addr_regmask = 0; + return; + } + } +nopair: + /*Instruction can not pair with previous*/ + /*Run previous now*/ + if (check_agi(u_pipe_deps, u_pipe_opcode, u_pipe_fetchdat, u_pipe_op_32)) + agi_stall = 1; + codegen_instruction(u_pipe_timings, u_pipe_deps, u_pipe_opcode, u_pipe_fetchdat, u_pipe_decode_delay_offset, u_pipe_op_32, agi_stall); + u_pipe_full = 0; + regmask_modified = u_pipe_regmask; + addr_regmask = 0; + } + + if ((timings[opcode] & PAIR_U) && (decode_delay + decode_delay_offset) <= 0) { + int has_displacement; + + if (timings[opcode] & CYCLES_HASIMM) + has_displacement = codegen_timing_has_displacement(fetchdat, op_32); + else + has_displacement = 0; + + if ((!has_displacement || cpu_has_feature(CPU_FEATURE_MMX)) && (!cpu_has_feature(CPU_FEATURE_MMX) || codegen_timing_instr_length(timings[opcode], fetchdat, op_32) <= 7)) { + /*Instruction might pair with next*/ + u_pipe_full = 1; + u_pipe_opcode = opcode; + u_pipe_timings = timings; + u_pipe_op_32 = op_32; + u_pipe_regmask = get_dstdep_mask(deps[opcode], fetchdat, bit8); + u_pipe_fetchdat = fetchdat; + u_pipe_decode_delay_offset = decode_delay_offset; + u_pipe_deps = deps; + decode_delay_offset = 0; + return; + } + } + /*Instruction can not pair and must run now*/ + if (check_agi(deps, opcode, fetchdat, op_32)) + agi_stall = 1; + codegen_instruction(timings, deps, opcode, fetchdat, decode_delay_offset, op_32, agi_stall); + decode_delay_offset = 0; + regmask_modified = get_dstdep_mask(deps[opcode], fetchdat, bit8); + addr_regmask = 0; } -codegen_timing_t codegen_timing_pentium = +void +codegen_timing_pentium_block_end(void) { - codegen_timing_pentium_start, - codegen_timing_pentium_prefix, - codegen_timing_pentium_opcode, - codegen_timing_pentium_block_start, - codegen_timing_pentium_block_end, - NULL + if (u_pipe_full) { + /*Run previous now*/ + if (check_agi(u_pipe_deps, u_pipe_opcode, u_pipe_fetchdat, u_pipe_op_32)) + codegen_block_cycles++; + codegen_block_cycles += COUNT(u_pipe_timings[u_pipe_opcode], u_pipe_deps[u_pipe_opcode], u_pipe_op_32) + decode_delay + decode_delay_offset; + u_pipe_full = 0; + } +} + +codegen_timing_t codegen_timing_pentium = { + codegen_timing_pentium_start, + codegen_timing_pentium_prefix, + codegen_timing_pentium_opcode, + codegen_timing_pentium_block_start, + codegen_timing_pentium_block_end, + NULL }; diff --git a/src/cpu/codegen_timing_winchip.c b/src/cpu/codegen_timing_winchip.c index dd2123f49..11dd912b4 100644 --- a/src/cpu/codegen_timing_winchip.c +++ b/src/cpu/codegen_timing_winchip.c @@ -4,19 +4,21 @@ #include #include <86box/86box.h> #include "cpu.h" +#include <86box/mem.h> +#include <86box/plat_unused.h> + #include "x86.h" #include "x86_ops.h" #include "x87.h" -#include <86box/mem.h> #include "codegen.h" #include "codegen_ops.h" #include "codegen_timing_common.h" -#define CYCLES(c) (int *)c -#define CYCLES2(c16, c32) (int *)((-1 & ~0xffff) | c16 | (c32 << 8)) +#define CYCLES(c) (int *) c +#define CYCLES2(c16, c32) (int *) ((-1 & ~0xffff) | c16 | (c32 << 8)) -static int *opcode_timings[256] = -{ +static int *opcode_timings[256] = { + // clang-format off /*00*/ &timing_mr, &timing_mr, &timing_rm, &timing_rm, &timing_rr, &timing_rr, CYCLES(2), CYCLES(3), &timing_mr, &timing_mr, &timing_rm, &timing_rm, &timing_rr, &timing_rr, CYCLES(2), NULL, /*10*/ &timing_mr, &timing_mr, &timing_rm, &timing_rm, &timing_rr, &timing_rr, CYCLES(2), CYCLES(3), &timing_mr, &timing_mr, &timing_rm, &timing_rm, &timing_rr, &timing_rr, CYCLES(2), CYCLES(3), /*20*/ &timing_mr, &timing_mr, &timing_rm, &timing_rm, &timing_rr, &timing_rr, CYCLES(4), CYCLES(3), &timing_mr, &timing_mr, &timing_rm, &timing_rm, &timing_rr, &timing_rr, CYCLES(4), CYCLES(3), @@ -36,10 +38,11 @@ static int *opcode_timings[256] = /*d0*/ CYCLES(4), CYCLES(4), CYCLES(4), CYCLES(4), CYCLES(15), CYCLES(14), CYCLES(2), CYCLES(4), NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, /*e0*/ CYCLES(6), CYCLES(6), CYCLES(6), CYCLES(5), CYCLES(14), CYCLES(14), CYCLES(16), CYCLES(16), CYCLES(3), CYCLES(3), CYCLES(17), CYCLES(3), CYCLES(14), CYCLES(14), CYCLES(14), CYCLES(14), /*f0*/ CYCLES(4), CYCLES(0), CYCLES(0), CYCLES(0), CYCLES(4), CYCLES(2), NULL, NULL, CYCLES(2), CYCLES(2), CYCLES(3), CYCLES(2), CYCLES(2), CYCLES(2), CYCLES(3), NULL + // clang-format on }; -static int *opcode_timings_mod3[256] = -{ +static int *opcode_timings_mod3[256] = { + // clang-format off /*00*/ &timing_rr, &timing_rr, &timing_rr, &timing_rr, &timing_rr, &timing_rr, CYCLES(2), CYCLES(3), &timing_rr, &timing_rr, &timing_rr, &timing_rr, &timing_rr, &timing_rr, CYCLES(2), NULL, /*10*/ &timing_rr, &timing_rr, &timing_rr, &timing_rr, &timing_rr, &timing_rr, CYCLES(2), CYCLES(3), &timing_rr, &timing_rr, &timing_rr, &timing_rr, &timing_rr, &timing_rr, CYCLES(2), CYCLES(3), /*20*/ &timing_rr, &timing_rr, &timing_rr, &timing_rr, &timing_rr, &timing_rr, CYCLES(4), CYCLES(3), &timing_rr, &timing_rr, &timing_rr, &timing_rr, &timing_rr, &timing_rr, CYCLES(4), CYCLES(3), @@ -59,10 +62,11 @@ static int *opcode_timings_mod3[256] = /*d0*/ CYCLES(4), CYCLES(4), CYCLES(4), CYCLES(4), CYCLES(15), CYCLES(14), CYCLES(2), CYCLES(4), NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, /*e0*/ CYCLES(6), CYCLES(6), CYCLES(6), CYCLES(5), CYCLES(14), CYCLES(14), CYCLES(16), CYCLES(16), CYCLES(3), CYCLES(3), CYCLES(17), CYCLES(3), CYCLES(14), CYCLES(14), CYCLES(14), CYCLES(14), /*f0*/ CYCLES(4), CYCLES(0), CYCLES(0), CYCLES(0), CYCLES(4), CYCLES(2), NULL, NULL, CYCLES(2), CYCLES(2), CYCLES(3), CYCLES(2), CYCLES(2), CYCLES(2), CYCLES(3), NULL + // clang-format on }; -static int *opcode_timings_0f[256] = -{ +static int *opcode_timings_0f[256] = { + // clang-format off /*00*/ CYCLES(20), CYCLES(11), CYCLES(11), CYCLES(10), NULL, CYCLES(195), CYCLES(7), NULL, CYCLES(1000), CYCLES(10000), NULL, NULL, NULL, NULL, NULL, NULL, /*10*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, /*20*/ CYCLES(6), CYCLES(6), CYCLES(6), CYCLES(6), CYCLES(6), CYCLES(6), NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, @@ -82,9 +86,10 @@ static int *opcode_timings_0f[256] = /*d0*/ NULL, &timing_rm, &timing_rm, &timing_rm, NULL, &timing_rm, NULL, NULL, &timing_rm, &timing_rm, NULL, &timing_rm, &timing_rm, &timing_rm, NULL, &timing_rm, /*e0*/ NULL, &timing_rm, &timing_rm, NULL, NULL, &timing_rm, NULL, NULL, &timing_rm, &timing_rm, NULL, &timing_rm, &timing_rm, &timing_rm, NULL, &timing_rm, /*f0*/ NULL, &timing_rm, &timing_rm, &timing_rm, NULL, &timing_rm, NULL, NULL, &timing_rm, &timing_rm, &timing_rm, NULL, &timing_rm, &timing_rm, &timing_rm, NULL, + // clang-format on }; -static int *opcode_timings_0f_mod3[256] = -{ +static int *opcode_timings_0f_mod3[256] = { + // clang-format off /*00*/ CYCLES(20), CYCLES(11), CYCLES(11), CYCLES(10), NULL, CYCLES(195), CYCLES(7), NULL, CYCLES(1000), CYCLES(10000), NULL, NULL, NULL, NULL, NULL, NULL, /*10*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, /*20*/ CYCLES(6), CYCLES(6), CYCLES(6), CYCLES(6), CYCLES(6), CYCLES(6), NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, @@ -104,60 +109,72 @@ static int *opcode_timings_0f_mod3[256] = /*d0*/ NULL, &timing_rr, &timing_rr, &timing_rr, NULL, &timing_rr, NULL, NULL, &timing_rr, &timing_rr, NULL, &timing_rr, &timing_rr, &timing_rr, NULL, &timing_rr, /*e0*/ NULL, &timing_rr, &timing_rr, NULL, NULL, &timing_rr, NULL, NULL, &timing_rr, &timing_rr, NULL, &timing_rr, &timing_rr, &timing_rr, NULL, &timing_rr, /*f0*/ NULL, &timing_rr, &timing_rr, &timing_rr, NULL, &timing_rr, NULL, NULL, &timing_rr, &timing_rr, &timing_rr, NULL, &timing_rr, &timing_rr, &timing_rr, NULL, + // clang-format on }; -static int *opcode_timings_shift[8] = -{ +static int *opcode_timings_shift[8] = { + // clang-format off CYCLES(7), CYCLES(7), CYCLES(10), CYCLES(10), CYCLES(7), CYCLES(7), CYCLES(7), CYCLES(7) + // clang-format on }; -static int *opcode_timings_shift_mod3[8] = -{ +static int *opcode_timings_shift_mod3[8] = { + // clang-format off CYCLES(3), CYCLES(3), CYCLES(9), CYCLES(9), CYCLES(3), CYCLES(3), CYCLES(3), CYCLES(3) + // clang-format on }; -static int *opcode_timings_f6[8] = -{ +static int *opcode_timings_f6[8] = { + // clang-format off &timing_rm, NULL, &timing_mm, &timing_mm, CYCLES(13), CYCLES(14), CYCLES(16), CYCLES(19) + // clang-format on }; -static int *opcode_timings_f6_mod3[8] = -{ +static int *opcode_timings_f6_mod3[8] = { + // clang-format off &timing_rr, NULL, &timing_rr, &timing_rr, CYCLES(13), CYCLES(14), CYCLES(16), CYCLES(19) + // clang-format on }; -static int *opcode_timings_f7[8] = -{ +static int *opcode_timings_f7[8] = { + // clang-format off &timing_rm, NULL, &timing_mm, &timing_mm, CYCLES(21), CYCLES2(22,38), CYCLES2(24,40), CYCLES2(27,43) + // clang-format on }; -static int *opcode_timings_f7_mod3[8] = -{ +static int *opcode_timings_f7_mod3[8] = { + // clang-format off &timing_rr, NULL, &timing_rr, &timing_rr, CYCLES(21), CYCLES2(22,38), CYCLES2(24,40), CYCLES2(27,43) + // clang-format on }; -static int *opcode_timings_ff[8] = -{ +static int *opcode_timings_ff[8] = { + // clang-format off &timing_mm, &timing_mm, CYCLES(5), CYCLES(0), CYCLES(5), CYCLES(0), CYCLES(5), NULL + // clang-format on }; -static int *opcode_timings_ff_mod3[8] = -{ +static int *opcode_timings_ff_mod3[8] = { + // clang-format off &timing_rr, &timing_rr, CYCLES(5), CYCLES(0), CYCLES(5), CYCLES(0), CYCLES(5), NULL + // clang-format on }; -static int *opcode_timings_d8[8] = -{ +static int *opcode_timings_d8[8] = { + // clang-format off /* FADDil FMULil FCOMil FCOMPil FSUBil FSUBRil FDIVil FDIVRil*/ CYCLES(10), CYCLES(12), CYCLES(9), CYCLES(9), CYCLES(10), CYCLES(10), CYCLES(78), CYCLES(78) + // clang-format on }; -static int *opcode_timings_d8_mod3[8] = -{ +static int *opcode_timings_d8_mod3[8] = { + // clang-format off /* FADD FMUL FCOM FCOMP FSUB FSUBR FDIV FDIVR*/ CYCLES(4), CYCLES(6), CYCLES(3), CYCLES(3), CYCLES(4), CYCLES(4), CYCLES(72), CYCLES(72) + // clang-format on }; -static int *opcode_timings_d9[8] = -{ +static int *opcode_timings_d9[8] = { + // clang-format off /* FLDs FSTs FSTPs FLDENV FLDCW FSTENV FSTCW*/ CYCLES(2), NULL, CYCLES(7), CYCLES(7), CYCLES(34), CYCLES(4), CYCLES(67), CYCLES(3) + // clang-format on }; -static int *opcode_timings_d9_mod3[64] = -{ +static int *opcode_timings_d9_mod3[64] = { + // clang-format off /*FLD*/ CYCLES(1), CYCLES(1), CYCLES(1), CYCLES(1), CYCLES(1), CYCLES(1), CYCLES(1), CYCLES(1), /*FXCH*/ @@ -174,26 +191,29 @@ static int *opcode_timings_d9_mod3[64] = CYCLES(300), CYCLES(58), CYCLES(676), CYCLES(355), NULL, NULL, CYCLES(3), CYCLES(3), /* opFPREM opFSQRT opFSINCOS opFRNDINT opFSCALE opFSIN opFCOS*/ CYCLES(70), NULL, CYCLES(72), CYCLES(292), CYCLES(21), CYCLES(30), CYCLES(474), CYCLES(474) + // clang-format on }; -static int *opcode_timings_da[8] = -{ +static int *opcode_timings_da[8] = { + // clang-format off /* FADDil FMULil FCOMil FCOMPil FSUBil FSUBRil FDIVil FDIVRil*/ CYCLES(10), CYCLES(12), CYCLES(9), CYCLES(9), CYCLES(10), CYCLES(10), CYCLES(78), CYCLES(78) + // clang-format on }; -static int *opcode_timings_da_mod3[8] = -{ +static int *opcode_timings_da_mod3[8] = { + // clang-format off NULL, NULL, NULL, NULL, NULL, CYCLES(5), NULL, NULL + // clang-format on }; - -static int *opcode_timings_db[8] = -{ +static int *opcode_timings_db[8] = { + // clang-format off /* FLDil FSTil FSTPil FLDe FSTPe*/ CYCLES(6), NULL, CYCLES(7), CYCLES(7), NULL, CYCLES(8), NULL, CYCLES(8) + // clang-format on }; -static int *opcode_timings_db_mod3[64] = -{ +static int *opcode_timings_db_mod3[64] = { + // clang-format off NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, @@ -203,54 +223,63 @@ static int *opcode_timings_db_mod3[64] = NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + // clang-format on }; -static int *opcode_timings_dc[8] = -{ +static int *opcode_timings_dc[8] = { + // clang-format off /* opFADDd_a16 opFMULd_a16 opFCOMd_a16 opFCOMPd_a16 opFSUBd_a16 opFSUBRd_a16 opFDIVd_a16 opFDIVRd_a16*/ CYCLES(6), CYCLES(8), CYCLES(5), CYCLES(5), CYCLES(6), CYCLES(6), CYCLES(74), CYCLES(74) + // clang-format on }; -static int *opcode_timings_dc_mod3[8] = -{ +static int *opcode_timings_dc_mod3[8] = { + // clang-format off /* opFADDr opFMULr opFSUBRr opFSUBr opFDIVRr opFDIVr*/ CYCLES(4), CYCLES(6), NULL, NULL, CYCLES(4), CYCLES(4), CYCLES(72), CYCLES(72) + // clang-format on }; -static int *opcode_timings_dd[8] = -{ +static int *opcode_timings_dd[8] = { + // clang-format off /* FLDd FSTd FSTPd FRSTOR FSAVE FSTSW*/ CYCLES(2), NULL, CYCLES(8), CYCLES(8), CYCLES(131), NULL, CYCLES(154), CYCLES(5) + // clang-format on }; -static int *opcode_timings_dd_mod3[8] = -{ +static int *opcode_timings_dd_mod3[8] = { + // clang-format off /* FFFREE FST FSTP FUCOM FUCOMP*/ CYCLES(3), NULL, CYCLES(1), CYCLES(1), CYCLES(3), CYCLES(3), NULL, NULL + // clang-format on }; -static int *opcode_timings_de[8] = -{ +static int *opcode_timings_de[8] = { + // clang-format off /* FADDiw FMULiw FCOMiw FCOMPiw FSUBil FSUBRil FDIVil FDIVRil*/ CYCLES(10), CYCLES(12), CYCLES(9), CYCLES(9), CYCLES(10), CYCLES(10), CYCLES(78), CYCLES(78) + // clang-format on }; -static int *opcode_timings_de_mod3[8] = -{ +static int *opcode_timings_de_mod3[8] = { + // clang-format off /* FADD FMUL FCOMPP FSUB FSUBR FDIV FDIVR*/ CYCLES(4), CYCLES(6), NULL, CYCLES(3), CYCLES(4), CYCLES(4), CYCLES(72), CYCLES(72) + // clang-format on }; -static int *opcode_timings_df[8] = -{ +static int *opcode_timings_df[8] = { + // clang-format off /* FILDiw FISTiw FISTPiw FILDiq FBSTP FISTPiq*/ CYCLES(6), NULL, CYCLES(7), CYCLES(7), NULL, CYCLES(8), CYCLES(172), CYCLES(8) + // clang-format on }; -static int *opcode_timings_df_mod3[8] = -{ +static int *opcode_timings_df_mod3[8] = { + // clang-format off /* FFREE FST FSTP FUCOM FUCOMP*/ CYCLES(3), NULL, CYCLES(1), CYCLES(1), CYCLES(3), CYCLES(3), NULL, NULL + // clang-format on }; -static int *opcode_timings_8x[8] = -{ +static int *opcode_timings_8x[8] = { + // clang-format off &timing_mr, &timing_mr, &timing_mr, &timing_mr, &timing_mr, &timing_mr, &timing_mr, &timing_rm }; static int *opcode_timings_8x_mod3[8] = @@ -264,158 +293,169 @@ static int *opcode_timings_81[8] = static int *opcode_timings_81_mod3[8] = { &timing_mr, &timing_mr, &timing_mr, &timing_mr, &timing_mr, &timing_mr, &timing_mr, &timing_rm + // clang-format on }; -static int timing_count; -static uint8_t last_prefix; +static int timing_count; +static uint8_t last_prefix; static uint32_t regmask_modified; -static inline int COUNT(int *c, int op_32) +static inline int +COUNT(int *c, int op_32) { - if ((uintptr_t)c <= 10000) - return (int)(uintptr_t)c; - if (((uintptr_t)c & ~0xffff) == (-1 & ~0xffff)) - { - if (op_32 & 0x100) - return ((uintptr_t)c >> 8) & 0xff; - return (uintptr_t)c & 0xff; - } - return *c; + if ((uintptr_t) c <= 10000) + return (int) (uintptr_t) c; + if (((uintptr_t) c & ~0xffff) == (-1 & ~0xffff)) { + if (op_32 & 0x100) + return ((uintptr_t) c >> 8) & 0xff; + return (uintptr_t) c & 0xff; + } + return *c; } -void codegen_timing_winchip_block_start() +void +codegen_timing_winchip_block_start(void) { - regmask_modified = 0; + regmask_modified = 0; } -void codegen_timing_winchip_start() +void +codegen_timing_winchip_start(void) { - timing_count = 0; - last_prefix = 0; + timing_count = 0; + last_prefix = 0; } -void codegen_timing_winchip_prefix(uint8_t prefix, uint32_t fetchdat) +void +codegen_timing_winchip_prefix(uint8_t prefix, uint32_t fetchdat) { - timing_count += COUNT(opcode_timings[prefix], 0); - last_prefix = prefix; + timing_count += COUNT(opcode_timings[prefix], 0); + last_prefix = prefix; } -void codegen_timing_winchip_opcode(uint8_t opcode, uint32_t fetchdat, int op_32, uint32_t op_pc) +void +codegen_timing_winchip_opcode(uint8_t opcode, uint32_t fetchdat, int op_32, UNUSED(uint32_t op_pc)) { - int **timings; - uint64_t *deps; - int mod3 = ((fetchdat & 0xc0) == 0xc0); - int bit8 = !(opcode & 1); + int **timings; + const uint64_t *deps; + int mod3 = ((fetchdat & 0xc0) == 0xc0); + int bit8 = !(opcode & 1); - switch (last_prefix) - { - case 0x0f: - timings = mod3 ? opcode_timings_0f_mod3 : opcode_timings_0f; - deps = mod3 ? opcode_deps_0f_mod3 : opcode_deps_0f; - break; - - case 0xd8: - timings = mod3 ? opcode_timings_d8_mod3 : opcode_timings_d8; - deps = mod3 ? opcode_deps_d8_mod3 : opcode_deps_d8; - opcode = (opcode >> 3) & 7; - break; - case 0xd9: - timings = mod3 ? opcode_timings_d9_mod3 : opcode_timings_d9; - deps = mod3 ? opcode_deps_d9_mod3 : opcode_deps_d9; - opcode = mod3 ? opcode & 0x3f : (opcode >> 3) & 7; - break; - case 0xda: - timings = mod3 ? opcode_timings_da_mod3 : opcode_timings_da; - deps = mod3 ? opcode_deps_da_mod3 : opcode_deps_da; - opcode = (opcode >> 3) & 7; - break; - case 0xdb: - timings = mod3 ? opcode_timings_db_mod3 : opcode_timings_db; - deps = mod3 ? opcode_deps_db_mod3 : opcode_deps_db; - opcode = mod3 ? opcode & 0x3f : (opcode >> 3) & 7; - break; - case 0xdc: - timings = mod3 ? opcode_timings_dc_mod3 : opcode_timings_dc; - deps = mod3 ? opcode_deps_dc_mod3 : opcode_deps_dc; - opcode = (opcode >> 3) & 7; - break; - case 0xdd: - timings = mod3 ? opcode_timings_dd_mod3 : opcode_timings_dd; - deps = mod3 ? opcode_deps_dd_mod3 : opcode_deps_dd; - opcode = (opcode >> 3) & 7; - break; - case 0xde: - timings = mod3 ? opcode_timings_de_mod3 : opcode_timings_de; - deps = mod3 ? opcode_deps_de_mod3 : opcode_deps_de; - opcode = (opcode >> 3) & 7; - break; - case 0xdf: - timings = mod3 ? opcode_timings_df_mod3 : opcode_timings_df; - deps = mod3 ? opcode_deps_df_mod3 : opcode_deps_df; - opcode = (opcode >> 3) & 7; - break; + switch (last_prefix) { + case 0x0f: + timings = mod3 ? opcode_timings_0f_mod3 : opcode_timings_0f; + deps = mod3 ? opcode_deps_0f_mod3 : opcode_deps_0f; + break; + + case 0xd8: + timings = mod3 ? opcode_timings_d8_mod3 : opcode_timings_d8; + deps = mod3 ? opcode_deps_d8_mod3 : opcode_deps_d8; + opcode = (opcode >> 3) & 7; + break; + case 0xd9: + timings = mod3 ? opcode_timings_d9_mod3 : opcode_timings_d9; + deps = mod3 ? opcode_deps_d9_mod3 : opcode_deps_d9; + opcode = mod3 ? opcode & 0x3f : (opcode >> 3) & 7; + break; + case 0xda: + timings = mod3 ? opcode_timings_da_mod3 : opcode_timings_da; + deps = mod3 ? opcode_deps_da_mod3 : opcode_deps_da; + opcode = (opcode >> 3) & 7; + break; + case 0xdb: + timings = mod3 ? opcode_timings_db_mod3 : opcode_timings_db; + deps = mod3 ? opcode_deps_db_mod3 : opcode_deps_db; + opcode = mod3 ? opcode & 0x3f : (opcode >> 3) & 7; + break; + case 0xdc: + timings = mod3 ? opcode_timings_dc_mod3 : opcode_timings_dc; + deps = mod3 ? opcode_deps_dc_mod3 : opcode_deps_dc; + opcode = (opcode >> 3) & 7; + break; + case 0xdd: + timings = mod3 ? opcode_timings_dd_mod3 : opcode_timings_dd; + deps = mod3 ? opcode_deps_dd_mod3 : opcode_deps_dd; + opcode = (opcode >> 3) & 7; + break; + case 0xde: + timings = mod3 ? opcode_timings_de_mod3 : opcode_timings_de; + deps = mod3 ? opcode_deps_de_mod3 : opcode_deps_de; + opcode = (opcode >> 3) & 7; + break; + case 0xdf: + timings = mod3 ? opcode_timings_df_mod3 : opcode_timings_df; + deps = mod3 ? opcode_deps_df_mod3 : opcode_deps_df; + opcode = (opcode >> 3) & 7; + break; + + default: + switch (opcode) { + case 0x80: + case 0x82: + case 0x83: + timings = mod3 ? opcode_timings_8x_mod3 : opcode_timings_8x; + deps = mod3 ? opcode_deps_8x_mod3 : opcode_deps_8x; + opcode = (fetchdat >> 3) & 7; + break; + case 0x81: + timings = mod3 ? opcode_timings_81_mod3 : opcode_timings_81; + deps = mod3 ? opcode_deps_81_mod3 : opcode_deps_81; + opcode = (fetchdat >> 3) & 7; + break; + + case 0xc0: + case 0xc1: + case 0xd0: + case 0xd1: + case 0xd2: + case 0xd3: + timings = mod3 ? opcode_timings_shift_mod3 : opcode_timings_shift; + deps = mod3 ? opcode_deps_shift_mod3 : opcode_deps_shift; + opcode = (fetchdat >> 3) & 7; + break; + + case 0xf6: + timings = mod3 ? opcode_timings_f6_mod3 : opcode_timings_f6; + deps = mod3 ? opcode_deps_f6_mod3 : opcode_deps_f6; + opcode = (fetchdat >> 3) & 7; + break; + case 0xf7: + timings = mod3 ? opcode_timings_f7_mod3 : opcode_timings_f7; + deps = mod3 ? opcode_deps_f7_mod3 : opcode_deps_f7; + opcode = (fetchdat >> 3) & 7; + break; + case 0xff: + timings = mod3 ? opcode_timings_ff_mod3 : opcode_timings_ff; + deps = mod3 ? opcode_deps_ff_mod3 : opcode_deps_ff; + opcode = (fetchdat >> 3) & 7; + break; default: - switch (opcode) - { - case 0x80: case 0x82: case 0x83: - timings = mod3 ? opcode_timings_8x_mod3 : opcode_timings_8x; - deps = mod3 ? opcode_deps_8x_mod3 : opcode_deps_8x; - opcode = (fetchdat >> 3) & 7; - break; - case 0x81: - timings = mod3 ? opcode_timings_81_mod3 : opcode_timings_81; - deps = mod3 ? opcode_deps_81_mod3 : opcode_deps_81; - opcode = (fetchdat >> 3) & 7; - break; - - case 0xc0: case 0xc1: case 0xd0: case 0xd1: case 0xd2: case 0xd3: - timings = mod3 ? opcode_timings_shift_mod3 : opcode_timings_shift; - deps = mod3 ? opcode_deps_shift_mod3 : opcode_deps_shift; - opcode = (fetchdat >> 3) & 7; - break; - - case 0xf6: - timings = mod3 ? opcode_timings_f6_mod3 : opcode_timings_f6; - deps = mod3 ? opcode_deps_f6_mod3 : opcode_deps_f6; - opcode = (fetchdat >> 3) & 7; - break; - case 0xf7: - timings = mod3 ? opcode_timings_f7_mod3 : opcode_timings_f7; - deps = mod3 ? opcode_deps_f7_mod3 : opcode_deps_f7; - opcode = (fetchdat >> 3) & 7; - break; - case 0xff: - timings = mod3 ? opcode_timings_ff_mod3 : opcode_timings_ff; - deps = mod3 ? opcode_deps_ff_mod3 : opcode_deps_ff; - opcode = (fetchdat >> 3) & 7; - break; + timings = mod3 ? opcode_timings_mod3 : opcode_timings; + deps = mod3 ? opcode_deps_mod3 : opcode_deps; + break; + } + } - default: - timings = mod3 ? opcode_timings_mod3 : opcode_timings; - deps = mod3 ? opcode_deps_mod3 : opcode_deps; - break; - } - } - - timing_count += COUNT(timings[opcode], op_32); - if (regmask_modified & get_addr_regmask(deps[opcode], fetchdat, op_32)) - timing_count++; /*AGI stall*/ - codegen_block_cycles += timing_count; - - regmask_modified = get_dstdep_mask(deps[opcode], fetchdat, bit8); + timing_count += COUNT(timings[opcode], op_32); + if (regmask_modified & get_addr_regmask(deps[opcode], fetchdat, op_32)) + timing_count++; /*AGI stall*/ + codegen_block_cycles += timing_count; + + regmask_modified = get_dstdep_mask(deps[opcode], fetchdat, bit8); } -void codegen_timing_winchip_block_end() +void +codegen_timing_winchip_block_end(void) { + // } -codegen_timing_t codegen_timing_winchip = -{ - codegen_timing_winchip_start, - codegen_timing_winchip_prefix, - codegen_timing_winchip_opcode, - codegen_timing_winchip_block_start, - codegen_timing_winchip_block_end, - NULL +codegen_timing_t codegen_timing_winchip = { + codegen_timing_winchip_start, + codegen_timing_winchip_prefix, + codegen_timing_winchip_opcode, + codegen_timing_winchip_block_start, + codegen_timing_winchip_block_end, + NULL }; diff --git a/src/cpu/codegen_timing_winchip2.c b/src/cpu/codegen_timing_winchip2.c index 06cc06697..d4e32611e 100644 --- a/src/cpu/codegen_timing_winchip2.c +++ b/src/cpu/codegen_timing_winchip2.c @@ -14,6 +14,7 @@ #include <86box/86box.h> #include "cpu.h" #include <86box/mem.h> +#include <86box/plat_unused.h> #include "x86.h" #include "x86_ops.h" @@ -23,46 +24,46 @@ #include "codegen_timing_common.h" /*Instruction has different execution time for 16 and 32 bit data. Does not pair */ -#define CYCLES_HAS_MULTI (1 << 31) +#define CYCLES_HAS_MULTI (1 << 31) -#define CYCLES_FPU (1 << 30) +#define CYCLES_FPU (1 << 30) #define CYCLES_IS_MMX_MUL (1 << 29) #define CYCLES_IS_MMX_SHIFT (1 << 28) #define CYCLES_IS_MMX_ANY (1 << 27) #define CYCLES_IS_3DNOW (1 << 26) -#define CYCLES_MMX_MUL(c) (CYCLES_IS_MMX_MUL | c) +#define CYCLES_MMX_MUL(c) (CYCLES_IS_MMX_MUL | c) #define CYCLES_MMX_SHIFT(c) (CYCLES_IS_MMX_SHIFT | c) -#define CYCLES_MMX_ANY(c) (CYCLES_IS_MMX_ANY | c) -#define CYCLES_3DNOW(c) (CYCLES_IS_3DNOW | c) +#define CYCLES_MMX_ANY(c) (CYCLES_IS_MMX_ANY | c) +#define CYCLES_3DNOW(c) (CYCLES_IS_3DNOW | c) -#define CYCLES_IS_MMX (CYCLES_IS_MMX_MUL | CYCLES_IS_MMX_SHIFT | CYCLES_IS_MMX_ANY | CYCLES_IS_3DNOW) +#define CYCLES_IS_MMX (CYCLES_IS_MMX_MUL | CYCLES_IS_MMX_SHIFT | CYCLES_IS_MMX_ANY | CYCLES_IS_3DNOW) -#define GET_CYCLES(c) (c & ~(CYCLES_HAS_MULTI | CYCLES_FPU | CYCLES_IS_MMX)) +#define GET_CYCLES(c) (c & ~(CYCLES_HAS_MULTI | CYCLES_FPU | CYCLES_IS_MMX)) -#define CYCLES(c) c -#define CYCLES2(c16, c32) (CYCLES_HAS_MULTI | c16 | (c32 << 8)) +#define CYCLES(c) c +#define CYCLES2(c16, c32) (CYCLES_HAS_MULTI | c16 | (c32 << 8)) /*comp_time = cycles until instruction complete i_overlap = cycles that overlap with integer f_overlap = cycles that overlap with subsequent FPU*/ #define FPU_CYCLES(comp_time, i_overlap, f_overlap) (comp_time) | (i_overlap << 8) | (f_overlap << 16) | CYCLES_FPU -#define FPU_COMP_TIME(timing) (timing & 0xff) -#define FPU_I_OVERLAP(timing) ((timing >> 8) & 0xff) -#define FPU_F_OVERLAP(timing) ((timing >> 16) & 0xff) +#define FPU_COMP_TIME(timing) (timing & 0xff) +#define FPU_I_OVERLAP(timing) ((timing >> 8) & 0xff) +#define FPU_F_OVERLAP(timing) ((timing >> 16) & 0xff) -#define FPU_I_LATENCY(timing) (FPU_COMP_TIME(timing) - FPU_I_OVERLAP(timing)) +#define FPU_I_LATENCY(timing) (FPU_COMP_TIME(timing) - FPU_I_OVERLAP(timing)) -#define FPU_F_LATENCY(timing) (FPU_I_OVERLAP(timing) - FPU_F_OVERLAP(timing)) +#define FPU_F_LATENCY(timing) (FPU_I_OVERLAP(timing) - FPU_F_OVERLAP(timing)) -#define FPU_RESULT_LATENCY(timing) ((timing >> 8) & 0xff) +#define FPU_RESULT_LATENCY(timing) ((timing >> 8) & 0xff) -#define INVALID 0 +#define INVALID 0 -static uint32_t opcode_timings[256] = -{ +static uint32_t opcode_timings[256] = { + // clang-format off /*00*/ CYCLES(2), CYCLES(2), CYCLES(2), CYCLES(2), CYCLES(1), CYCLES(1), CYCLES(2), CYCLES(3), CYCLES(2), CYCLES(2), CYCLES(2), CYCLES(2), CYCLES(1), CYCLES(1), CYCLES(2), INVALID, /*10*/ CYCLES(2), CYCLES(2), CYCLES(2), CYCLES(2), CYCLES(1), CYCLES(1), CYCLES(2), CYCLES(3), CYCLES(2), CYCLES(2), CYCLES(2), CYCLES(2), CYCLES(1), CYCLES(1), CYCLES(2), CYCLES(3), /*20*/ CYCLES(2), CYCLES(2), CYCLES(2), CYCLES(2), CYCLES(1), CYCLES(1), CYCLES(1), CYCLES(3), CYCLES(2), CYCLES(2), CYCLES(2), CYCLES(2), CYCLES(1), CYCLES(1), CYCLES(1), CYCLES(3), @@ -82,10 +83,11 @@ static uint32_t opcode_timings[256] = /*d0*/ CYCLES(4), CYCLES(4), CYCLES(4), CYCLES(4), CYCLES(15), CYCLES(14), CYCLES(2), CYCLES(4), INVALID, INVALID, INVALID, INVALID, INVALID, INVALID, INVALID, INVALID, /*e0*/ CYCLES(6), CYCLES(6), CYCLES(6), CYCLES(5), CYCLES(14), CYCLES(14), CYCLES(16), CYCLES(16), CYCLES(3), CYCLES(3), CYCLES(17), CYCLES(3), CYCLES(14), CYCLES(14), CYCLES(14), CYCLES(14), /*f0*/ CYCLES(4), CYCLES(0), CYCLES(0), CYCLES(0), CYCLES(4), CYCLES(2), INVALID, INVALID, CYCLES(2), CYCLES(2), CYCLES(3), CYCLES(2), CYCLES(2), CYCLES(2), CYCLES(3), INVALID + // clang-format on }; -static uint32_t opcode_timings_mod3[256] = -{ +static uint32_t opcode_timings_mod3[256] = { + // clang-format off /*00*/ CYCLES(1), CYCLES(1), CYCLES(1), CYCLES(1), CYCLES(1), CYCLES(1), CYCLES(2), CYCLES(3), CYCLES(1), CYCLES(1), CYCLES(1), CYCLES(1), CYCLES(1), CYCLES(1), CYCLES(2), INVALID, /*10*/ CYCLES(1), CYCLES(1), CYCLES(1), CYCLES(1), CYCLES(1), CYCLES(1), CYCLES(2), CYCLES(3), CYCLES(1), CYCLES(1), CYCLES(1), CYCLES(1), CYCLES(1), CYCLES(1), CYCLES(2), CYCLES(3), /*20*/ CYCLES(1), CYCLES(1), CYCLES(1), CYCLES(1), CYCLES(1), CYCLES(1), CYCLES(1), CYCLES(3), CYCLES(1), CYCLES(1), CYCLES(1), CYCLES(1), CYCLES(1), CYCLES(1), CYCLES(1), CYCLES(3), @@ -105,10 +107,11 @@ static uint32_t opcode_timings_mod3[256] = /*d0*/ CYCLES(4), CYCLES(4), CYCLES(4), CYCLES(4), CYCLES(15), CYCLES(14), CYCLES(2), CYCLES(4), INVALID, INVALID, INVALID, INVALID, INVALID, INVALID, INVALID, INVALID, /*e0*/ CYCLES(6), CYCLES(6), CYCLES(6), CYCLES(5), CYCLES(14), CYCLES(14), CYCLES(16), CYCLES(16), CYCLES(3), CYCLES(3), CYCLES(17), CYCLES(3), CYCLES(14), CYCLES(14), CYCLES(14), CYCLES(14), /*f0*/ CYCLES(4), CYCLES(0), CYCLES(0), CYCLES(0), CYCLES(4), CYCLES(2), INVALID, INVALID, CYCLES(2), CYCLES(2), CYCLES(3), CYCLES(2), CYCLES(2), CYCLES(2), CYCLES(3), INVALID, + // clang-format on }; -static uint32_t opcode_timings_0f[256] = -{ +static uint32_t opcode_timings_0f[256] = { + // clang-format off /*00*/ CYCLES(20), CYCLES(11), CYCLES(11), CYCLES(10), INVALID, CYCLES(195), CYCLES(7), INVALID, CYCLES(1000), CYCLES(10000), INVALID, INVALID, INVALID, CYCLES_3DNOW(1), CYCLES(1), CYCLES_3DNOW(1), /*10*/ INVALID, INVALID, INVALID, INVALID, INVALID, INVALID, INVALID, INVALID, INVALID, INVALID, INVALID, INVALID, INVALID, INVALID, INVALID, INVALID, /*20*/ CYCLES(6), CYCLES(6), CYCLES(6), CYCLES(6), CYCLES(6), CYCLES(6), INVALID, INVALID, INVALID, INVALID, INVALID, INVALID, INVALID, INVALID, INVALID, INVALID, @@ -128,9 +131,10 @@ static uint32_t opcode_timings_0f[256] = /*d0*/ INVALID, CYCLES_MMX_SHIFT(2), CYCLES_MMX_SHIFT(2), CYCLES_MMX_SHIFT(2), INVALID, CYCLES_MMX_MUL(2), INVALID, INVALID, CYCLES_MMX_ANY(2), CYCLES_MMX_ANY(2), INVALID, CYCLES_MMX_ANY(2), CYCLES_MMX_ANY(2), CYCLES_MMX_ANY(2), INVALID, CYCLES_MMX_ANY(2), /*e0*/ INVALID, CYCLES_MMX_SHIFT(2), CYCLES_MMX_SHIFT(2), INVALID, INVALID, CYCLES_MMX_MUL(2), INVALID, INVALID, CYCLES_MMX_ANY(2), CYCLES_MMX_ANY(2), INVALID, CYCLES_MMX_ANY(2), CYCLES_MMX_ANY(2), CYCLES_MMX_ANY(2), INVALID, CYCLES_MMX_ANY(2), /*f0*/ INVALID, CYCLES_MMX_SHIFT(2), CYCLES_MMX_SHIFT(2), CYCLES_MMX_SHIFT(2), INVALID, CYCLES_MMX_MUL(2), INVALID, INVALID, CYCLES_MMX_ANY(2), CYCLES_MMX_ANY(2), CYCLES_MMX_ANY(2), INVALID, CYCLES_MMX_ANY(2), CYCLES_MMX_ANY(2), CYCLES_MMX_ANY(2), INVALID, + // clang-format on }; -static uint32_t opcode_timings_0f_mod3[256] = -{ +static uint32_t opcode_timings_0f_mod3[256] = { + // clang-format off /*00*/ CYCLES(20), CYCLES(11), CYCLES(11), CYCLES(10), INVALID, CYCLES(195), CYCLES(7), INVALID, CYCLES(1000), CYCLES(10000), INVALID, INVALID, INVALID, CYCLES_3DNOW(1), CYCLES(1), CYCLES_3DNOW(1), /*10*/ INVALID, INVALID, INVALID, INVALID, INVALID, INVALID, INVALID, INVALID, INVALID, INVALID, INVALID, INVALID, INVALID, INVALID, INVALID, INVALID, /*20*/ CYCLES(6), CYCLES(6), CYCLES(6), CYCLES(6), CYCLES(6), CYCLES(6), INVALID, INVALID, INVALID, INVALID, INVALID, INVALID, INVALID, INVALID, INVALID, INVALID, @@ -150,66 +154,78 @@ static uint32_t opcode_timings_0f_mod3[256] = /*d0*/ INVALID, CYCLES_MMX_SHIFT(1), CYCLES_MMX_SHIFT(1), CYCLES_MMX_SHIFT(1), INVALID, CYCLES_MMX_MUL(1), INVALID, INVALID, CYCLES_MMX_ANY(1), CYCLES_MMX_ANY(1), INVALID, CYCLES_MMX_ANY(1), CYCLES_MMX_ANY(1), CYCLES_MMX_ANY(1), INVALID, CYCLES_MMX_ANY(1), /*e0*/ INVALID, CYCLES_MMX_SHIFT(1), CYCLES_MMX_SHIFT(1), INVALID, INVALID, CYCLES_MMX_MUL(1), INVALID, INVALID, CYCLES_MMX_ANY(1), CYCLES_MMX_ANY(1), INVALID, CYCLES_MMX_ANY(1), CYCLES_MMX_ANY(1), CYCLES_MMX_ANY(1), INVALID, CYCLES_MMX_ANY(1), /*f0*/ INVALID, CYCLES_MMX_SHIFT(1), CYCLES_MMX_SHIFT(1), CYCLES_MMX_SHIFT(1), INVALID, CYCLES_MMX_MUL(1), INVALID, INVALID, CYCLES_MMX_ANY(1), CYCLES_MMX_ANY(1), CYCLES_MMX_ANY(1), INVALID, CYCLES_MMX_ANY(1), CYCLES_MMX_ANY(1), CYCLES_MMX_ANY(1), INVALID, + // clang-format on }; -static uint32_t opcode_timings_shift[8] = -{ +static uint32_t opcode_timings_shift[8] = { + // clang-format off CYCLES(7), CYCLES(7), CYCLES(10), CYCLES(10), CYCLES(7), CYCLES(7), CYCLES(7), CYCLES(7) + // clang-format on }; -static uint32_t opcode_timings_shift_mod3[8] = -{ +static uint32_t opcode_timings_shift_mod3[8] = { + // clang-format off CYCLES(3), CYCLES(3), CYCLES(9), CYCLES(9), CYCLES(3), CYCLES(3), CYCLES(3), CYCLES(3) + // clang-format on }; -static uint32_t opcode_timings_f6[8] = -{ +static uint32_t opcode_timings_f6[8] = { + // clang-format off CYCLES(2), INVALID, CYCLES(2), CYCLES(2), CYCLES(13), CYCLES(14), CYCLES(16), CYCLES(19) + // clang-format on }; -static uint32_t opcode_timings_f6_mod3[8] = -{ +static uint32_t opcode_timings_f6_mod3[8] = { + // clang-format off CYCLES(1), INVALID, CYCLES(1), CYCLES(1), CYCLES(13), CYCLES(14), CYCLES(16), CYCLES(19) + // clang-format on }; -static uint32_t opcode_timings_f7[8] = -{ +static uint32_t opcode_timings_f7[8] = { + // clang-format off CYCLES(2), INVALID, CYCLES(2), CYCLES(2), CYCLES(21), CYCLES2(22,38), CYCLES2(24,40), CYCLES2(27,43) + // clang-format on }; -static uint32_t opcode_timings_f7_mod3[8] = -{ +static uint32_t opcode_timings_f7_mod3[8] = { + // clang-format off CYCLES(1), INVALID, CYCLES(1), CYCLES(1), CYCLES(21), CYCLES2(22,38), CYCLES2(24,40), CYCLES2(27,43) + // clang-format on }; -static uint32_t opcode_timings_ff[8] = -{ +static uint32_t opcode_timings_ff[8] = { + // clang-format off CYCLES(2), CYCLES(2), CYCLES(5), CYCLES(0), CYCLES(5), CYCLES(0), CYCLES(5), INVALID + // clang-format on }; -static uint32_t opcode_timings_ff_mod3[8] = -{ +static uint32_t opcode_timings_ff_mod3[8] = { + // clang-format off CYCLES(1), CYCLES(1), CYCLES(5), CYCLES(0), CYCLES(5), CYCLES(0), CYCLES(5), INVALID + // clang-format on }; -static uint32_t opcode_timings_d8[8] = -{ +static uint32_t opcode_timings_d8[8] = { + // clang-format off /* FADDs FMULs FCOMs FCOMPs*/ FPU_CYCLES(3,2,2), FPU_CYCLES(3,2,2), FPU_CYCLES(1,0,0), FPU_CYCLES(1,0,0), /* FSUBs FSUBRs FDIVs FDIVRs*/ FPU_CYCLES(3,2,2), FPU_CYCLES(3,2,2), FPU_CYCLES(39,38,2), FPU_CYCLES(39,38,2) + // clang-format on }; -static uint32_t opcode_timings_d8_mod3[8] = -{ +static uint32_t opcode_timings_d8_mod3[8] = { + // clang-format off /* FADD FMUL FCOM FCOMP*/ FPU_CYCLES(3,2,2), FPU_CYCLES(3,2,2), FPU_CYCLES(1,0,0), FPU_CYCLES(1,0,0), /* FSUB FSUBR FDIV FDIVR*/ FPU_CYCLES(3,2,2), FPU_CYCLES(3,2,2), FPU_CYCLES(39,38,2), FPU_CYCLES(39,38,2) + // clang-format on }; -static uint32_t opcode_timings_d9[8] = -{ +static uint32_t opcode_timings_d9[8] = { + // clang-format off /* FLDs FSTs FSTPs*/ FPU_CYCLES(1,0,0), INVALID, FPU_CYCLES(2,0,0), FPU_CYCLES(2,0,0), /* FLDENV FLDCW FSTENV FSTCW*/ FPU_CYCLES(32,0,0), FPU_CYCLES(8,0,0), FPU_CYCLES(48,0,0), FPU_CYCLES(2,0,0) + // clang-format on }; -static uint32_t opcode_timings_d9_mod3[64] = -{ +static uint32_t opcode_timings_d9_mod3[64] = { + // clang-format off /*FLD*/ FPU_CYCLES(1,0,0), FPU_CYCLES(1,0,0), FPU_CYCLES(1,0,0), FPU_CYCLES(1,0,0), FPU_CYCLES(1,0,0), FPU_CYCLES(1,0,0), FPU_CYCLES(1,0,0), FPU_CYCLES(1,0,0), @@ -238,32 +254,35 @@ static uint32_t opcode_timings_d9_mod3[64] = FPU_CYCLES(64,2,2), INVALID, FPU_CYCLES(70,69,2),FPU_CYCLES(89,2,2), /* opFRNDINT opFSCALE opFSIN opFCOS*/ FPU_CYCLES(9,0,0), FPU_CYCLES(20,5,0), FPU_CYCLES(65,2,2), FPU_CYCLES(65,2,2) + // clang-format on }; -static uint32_t opcode_timings_da[8] = -{ +static uint32_t opcode_timings_da[8] = { + // clang-format off /* FIADDl FIMULl FICOMl FICOMPl*/ FPU_CYCLES(6,2,2), FPU_CYCLES(6,2,2), FPU_CYCLES(4,0,0), FPU_CYCLES(4,0,0), /* FISUBl FISUBRl FIDIVl FIDIVRl*/ FPU_CYCLES(6,2,2), FPU_CYCLES(6,2,2), FPU_CYCLES(42,38,2), FPU_CYCLES(42,38,2) + // clang-format on }; -static uint32_t opcode_timings_da_mod3[8] = -{ +static uint32_t opcode_timings_da_mod3[8] = { + // clang-format off INVALID, INVALID, INVALID, INVALID, /* FCOMPP*/ INVALID, FPU_CYCLES(1,0,0), INVALID, INVALID + // clang-format on }; - -static uint32_t opcode_timings_db[8] = -{ +static uint32_t opcode_timings_db[8] = { + // clang-format off /* FLDil FSTil FSTPil*/ FPU_CYCLES(3,2,2), INVALID, FPU_CYCLES(6,0,0), FPU_CYCLES(6,0,0), /* FLDe FSTPe*/ INVALID, FPU_CYCLES(3,0,0), INVALID, FPU_CYCLES(3,0,0) + // clang-format on }; -static uint32_t opcode_timings_db_mod3[64] = -{ +static uint32_t opcode_timings_db_mod3[64] = { + // clang-format off INVALID, INVALID, INVALID, INVALID, INVALID, INVALID, INVALID, INVALID, @@ -289,455 +308,469 @@ static uint32_t opcode_timings_db_mod3[64] = INVALID, INVALID, INVALID, INVALID, INVALID, INVALID, INVALID, INVALID, + // clang-format on }; -static uint32_t opcode_timings_dc[8] = -{ +static uint32_t opcode_timings_dc[8] = { + // clang-format off /* FADDd FMULd FCOMd FCOMPd*/ FPU_CYCLES(3,2,2), FPU_CYCLES(3,2,2), FPU_CYCLES(1,0,0), FPU_CYCLES(1,0,0), /* FSUBd FSUBRd FDIVd FDIVRd*/ FPU_CYCLES(3,2,2), FPU_CYCLES(3,2,2), FPU_CYCLES(39,38,2), FPU_CYCLES(39,38,2) + // clang-format on }; -static uint32_t opcode_timings_dc_mod3[8] = -{ +static uint32_t opcode_timings_dc_mod3[8] = { + // clang-format off /* opFADDr opFMULr*/ FPU_CYCLES(3,2,2), FPU_CYCLES(3,2,2),INVALID, INVALID, /* opFSUBRr opFSUBr opFDIVRr opFDIVr*/ FPU_CYCLES(3,2,2), FPU_CYCLES(3,2,2),FPU_CYCLES(39,38,2), FPU_CYCLES(39,38,2) + // clang-format on }; -static uint32_t opcode_timings_dd[8] = -{ +static uint32_t opcode_timings_dd[8] = { + // clang-format off /* FLDd FSTd FSTPd*/ FPU_CYCLES(1,0,0), INVALID, FPU_CYCLES(2,0,0), FPU_CYCLES(2,0,0), /* FRSTOR FSAVE FSTSW*/ FPU_CYCLES(70,0,0), INVALID, FPU_CYCLES(127,0,0), FPU_CYCLES(6,0,0) + // clang-format on }; -static uint32_t opcode_timings_dd_mod3[8] = -{ +static uint32_t opcode_timings_dd_mod3[8] = { + // clang-format off /* FFFREE FST FSTP*/ FPU_CYCLES(2,0,0), INVALID, FPU_CYCLES(1,0,0), FPU_CYCLES(1,0,0), /* FUCOM FUCOMP*/ FPU_CYCLES(1,0,0), FPU_CYCLES(1,0,0),INVALID, INVALID + // clang-format on }; -static uint32_t opcode_timings_de[8] = -{ +static uint32_t opcode_timings_de[8] = { + // clang-format off /* FIADDw FIMULw FICOMw FICOMPw*/ FPU_CYCLES(6,2,2), FPU_CYCLES(6,2,2), FPU_CYCLES(4,0,0), FPU_CYCLES(4,0,0), /* FISUBw FISUBRw FIDIVw FIDIVRw*/ FPU_CYCLES(6,2,2), FPU_CYCLES(6,2,2), FPU_CYCLES(42,38,2), FPU_CYCLES(42,38,2) + // clang-format on }; -static uint32_t opcode_timings_de_mod3[8] = -{ +static uint32_t opcode_timings_de_mod3[8] = { + // clang-format off /* FADDP FMULP FCOMPP*/ FPU_CYCLES(3,2,2), FPU_CYCLES(3,2,2), INVALID, FPU_CYCLES(1,0,0), /* FSUBP FSUBRP FDIVP FDIVRP*/ FPU_CYCLES(3,2,2), FPU_CYCLES(3,2,2), FPU_CYCLES(39,38,2), FPU_CYCLES(39,38,2) + // clang-format on }; -static uint32_t opcode_timings_df[8] = -{ +static uint32_t opcode_timings_df[8] = { + // clang-format off /* FILDiw FISTiw FISTPiw*/ FPU_CYCLES(3,2,2), INVALID, FPU_CYCLES(6,0,0), FPU_CYCLES(6,0,0), /* FILDiq FBSTP FISTPiq*/ INVALID, FPU_CYCLES(3,2,2), FPU_CYCLES(148,0,0), FPU_CYCLES(6,0,0) + // clang-format on }; -static uint32_t opcode_timings_df_mod3[8] = -{ +static uint32_t opcode_timings_df_mod3[8] = { + // clang-format off INVALID, INVALID, INVALID, INVALID, /* FSTSW AX*/ FPU_CYCLES(6,0,0), INVALID, INVALID, INVALID + // clang-format on }; -static uint32_t opcode_timings_8x[8] = -{ +static uint32_t opcode_timings_8x[8] = { + // clang-format off CYCLES(2), CYCLES(2), CYCLES(2), CYCLES(2), CYCLES(2), CYCLES(2), CYCLES(2), CYCLES(2) + // clang-format on }; -static uint32_t opcode_timings_8x_mod3[8] = -{ +static uint32_t opcode_timings_8x_mod3[8] = { + // clang-format off CYCLES(2), CYCLES(2), CYCLES(2), CYCLES(2), CYCLES(2), CYCLES(2), CYCLES(2), CYCLES(2) + // clang-format on }; -static uint32_t opcode_timings_81[8] = -{ +static uint32_t opcode_timings_81[8] = { + // clang-format off CYCLES(2), CYCLES(2), CYCLES(2), CYCLES(2), CYCLES(2), CYCLES(2), CYCLES(2), CYCLES(2) + // clang-format on }; -static uint32_t opcode_timings_81_mod3[8] = -{ +static uint32_t opcode_timings_81_mod3[8] = { + // clang-format off CYCLES(2), CYCLES(2), CYCLES(2), CYCLES(2), CYCLES(2), CYCLES(2), CYCLES(2), CYCLES(2) + // clang-format on }; -static int timing_count; -static uint8_t last_prefix; +static int timing_count; +static uint8_t last_prefix; static uint32_t regmask_modified; -static int decode_delay, decode_delay_offset; -static int fpu_latency; -static int fpu_st_latency[8]; +static int decode_delay; +static int decode_delay_offset; +static int fpu_latency; +static int fpu_st_latency[8]; -static int u_pipe_full; -static uint32_t u_pipe_opcode; +static int u_pipe_full; +static uint32_t u_pipe_opcode; static uint32_t *u_pipe_timings; -static uint32_t u_pipe_op_32; -static uint32_t u_pipe_regmask; -static uint32_t u_pipe_fetchdat; -static int u_pipe_decode_delay_offset; +static uint32_t u_pipe_op_32; +static uint32_t u_pipe_regmask; +static uint32_t u_pipe_fetchdat; +static int u_pipe_decode_delay_offset; static uint64_t *u_pipe_deps; -int can_pair(uint32_t timing_a, uint32_t timing_b, uint8_t regmask_b) +int +can_pair(uint32_t timing_a, uint32_t timing_b, uint8_t regmask_b) { - /*Only MMX/3DNow instructions can pair*/ - if (!(timing_b & CYCLES_IS_MMX)) - return 0; - /*Only one MMX multiply per cycle*/ - if ((timing_a & CYCLES_IS_MMX_MUL) && (timing_b & CYCLES_IS_MMX_MUL)) - return 0; - /*Only one MMX shift/pack per cycle*/ - if ((timing_a & CYCLES_IS_MMX_SHIFT) && (timing_b & CYCLES_IS_MMX_SHIFT)) - return 0; - /*Second instruction can not access registers written by first*/ - if (u_pipe_regmask & regmask_b) - return 0; - /*Must have had enough time to decode prefixes*/ - if ((decode_delay+decode_delay_offset+u_pipe_decode_delay_offset) > 0) - return 0; + /*Only MMX/3DNow instructions can pair*/ + if (!(timing_b & CYCLES_IS_MMX)) + return 0; + /*Only one MMX multiply per cycle*/ + if ((timing_a & CYCLES_IS_MMX_MUL) && (timing_b & CYCLES_IS_MMX_MUL)) + return 0; + /*Only one MMX shift/pack per cycle*/ + if ((timing_a & CYCLES_IS_MMX_SHIFT) && (timing_b & CYCLES_IS_MMX_SHIFT)) + return 0; + /*Second instruction can not access registers written by first*/ + if (u_pipe_regmask & regmask_b) + return 0; + /*Must have had enough time to decode prefixes*/ + if ((decode_delay + decode_delay_offset + u_pipe_decode_delay_offset) > 0) + return 0; - return 1; + return 1; } -static inline int COUNT(uint32_t c, int op_32) +static inline int +COUNT(uint32_t c, int op_32) { - if (c & CYCLES_FPU) - return FPU_I_LATENCY(c); - if (c & CYCLES_HAS_MULTI) - { - if (op_32 & 0x100) - return (c >> 8) & 0xff; - return c & 0xff; - } - return GET_CYCLES(c); + if (c & CYCLES_FPU) + return FPU_I_LATENCY(c); + if (c & CYCLES_HAS_MULTI) { + if (op_32 & 0x100) + return (c >> 8) & 0xff; + return c & 0xff; + } + return GET_CYCLES(c); } -static int check_agi(uint64_t *deps, uint8_t opcode, uint32_t fetchdat, int op_32) +static int +check_agi(uint64_t *deps, uint8_t opcode, uint32_t fetchdat, int op_32) { - uint32_t addr_regmask = get_addr_regmask(deps[opcode], fetchdat, op_32); + uint32_t addr_regmask = get_addr_regmask(deps[opcode], fetchdat, op_32); - /*Instructions that use ESP implicitly (eg PUSH, POP, CALL etc) do not - cause AGIs with each other, but do with instructions that use it explicitly*/ - if ((addr_regmask & REGMASK_IMPL_ESP) && (regmask_modified & (1 << REG_ESP)) && !(regmask_modified & REGMASK_IMPL_ESP)) - addr_regmask |= (1 << REG_ESP); + /*Instructions that use ESP implicitly (eg PUSH, POP, CALL etc) do not + cause AGIs with each other, but do with instructions that use it explicitly*/ + if ((addr_regmask & REGMASK_IMPL_ESP) && (regmask_modified & (1 << REG_ESP)) && !(regmask_modified & REGMASK_IMPL_ESP)) + addr_regmask |= (1 << REG_ESP); - return (regmask_modified & addr_regmask) & ~REGMASK_IMPL_ESP; + return (regmask_modified & addr_regmask) & ~REGMASK_IMPL_ESP; } -static int codegen_fpu_latencies(uint64_t deps, int reg) +static int +codegen_fpu_latencies(uint64_t deps, int reg) { - int latency = fpu_latency; + int latency = fpu_latency; - if ((deps & FPU_RW_ST0) && fpu_st_latency[0] && fpu_st_latency[0] > latency) - latency = fpu_st_latency[0]; - if ((deps & FPU_RW_ST1) && fpu_st_latency[1] && fpu_st_latency[1] > latency) - latency = fpu_st_latency[1]; - if ((deps & FPU_RW_STREG) && fpu_st_latency[reg] && fpu_st_latency[reg] > latency) - latency = fpu_st_latency[reg]; + if ((deps & FPU_RW_ST0) && fpu_st_latency[0] && fpu_st_latency[0] > latency) + latency = fpu_st_latency[0]; + if ((deps & FPU_RW_ST1) && fpu_st_latency[1] && fpu_st_latency[1] > latency) + latency = fpu_st_latency[1]; + if ((deps & FPU_RW_STREG) && fpu_st_latency[reg] && fpu_st_latency[reg] > latency) + latency = fpu_st_latency[reg]; - return latency; + return latency; } -#define SUB_AND_CLAMP(latency, count) \ - latency -= count; \ - if (latency < 0) \ - latency = 0 +#define SUB_AND_CLAMP(latency, count) \ + latency -= count; \ + if (latency < 0) \ + latency = 0 -static void codegen_fpu_latency_clock(int count) +static void +codegen_fpu_latency_clock(int count) { - SUB_AND_CLAMP(fpu_latency, count); - SUB_AND_CLAMP(fpu_st_latency[0], count); - SUB_AND_CLAMP(fpu_st_latency[1], count); - SUB_AND_CLAMP(fpu_st_latency[2], count); - SUB_AND_CLAMP(fpu_st_latency[3], count); - SUB_AND_CLAMP(fpu_st_latency[4], count); - SUB_AND_CLAMP(fpu_st_latency[5], count); - SUB_AND_CLAMP(fpu_st_latency[6], count); - SUB_AND_CLAMP(fpu_st_latency[7], count); + SUB_AND_CLAMP(fpu_latency, count); + SUB_AND_CLAMP(fpu_st_latency[0], count); + SUB_AND_CLAMP(fpu_st_latency[1], count); + SUB_AND_CLAMP(fpu_st_latency[2], count); + SUB_AND_CLAMP(fpu_st_latency[3], count); + SUB_AND_CLAMP(fpu_st_latency[4], count); + SUB_AND_CLAMP(fpu_st_latency[5], count); + SUB_AND_CLAMP(fpu_st_latency[6], count); + SUB_AND_CLAMP(fpu_st_latency[7], count); } -static void codegen_instruction(uint32_t *timings, uint64_t *deps, uint8_t opcode, uint32_t fetchdat, int decode_delay_offset, int op_32, int exec_delay) +static void +codegen_instruction(uint32_t *timings, uint64_t *deps, uint8_t opcode, uint32_t fetchdat, int decode_delay_offset, int op_32, int exec_delay) { - int instr_cycles, latency = 0; + int instr_cycles; + int latency = 0; - if ((timings[opcode] & CYCLES_FPU) && !(deps[opcode] & FPU_FXCH)) - instr_cycles = latency = codegen_fpu_latencies(deps[opcode], fetchdat & 7); - else - instr_cycles = 0; + if ((timings[opcode] & CYCLES_FPU) && !(deps[opcode] & FPU_FXCH)) + instr_cycles = latency = codegen_fpu_latencies(deps[opcode], fetchdat & 7); + else + instr_cycles = 0; - if ((decode_delay + decode_delay_offset) > 0) - codegen_fpu_latency_clock(decode_delay + decode_delay_offset + instr_cycles); - else - codegen_fpu_latency_clock(instr_cycles); - instr_cycles += COUNT(timings[opcode], op_32); - instr_cycles += exec_delay; - if ((decode_delay + decode_delay_offset) > 0) - codegen_block_cycles += instr_cycles + decode_delay + decode_delay_offset; - else - codegen_block_cycles += instr_cycles; - decode_delay = (-instr_cycles) + 1; + if ((decode_delay + decode_delay_offset) > 0) + codegen_fpu_latency_clock(decode_delay + decode_delay_offset + instr_cycles); + else + codegen_fpu_latency_clock(instr_cycles); + instr_cycles += COUNT(timings[opcode], op_32); + instr_cycles += exec_delay; + if ((decode_delay + decode_delay_offset) > 0) + codegen_block_cycles += instr_cycles + decode_delay + decode_delay_offset; + else + codegen_block_cycles += instr_cycles; + decode_delay = (-instr_cycles) + 1; + if (deps[opcode] & FPU_POP) { + for (uint8_t c = 0; c < 7; c++) + fpu_st_latency[c] = fpu_st_latency[c + 1]; + fpu_st_latency[7] = 0; + } + if (deps[opcode] & FPU_POP2) { + for (uint8_t c = 0; c < 6; c++) + fpu_st_latency[c] = fpu_st_latency[c + 2]; + fpu_st_latency[6] = fpu_st_latency[7] = 0; + } + if (timings[opcode] & CYCLES_FPU) { +#if 0 + if (fpu_latency) + fatal("Bad latency FPU\n");*/ +#endif + fpu_latency = FPU_F_LATENCY(timings[opcode]); + } + + if (deps[opcode] & FPU_PUSH) { + for (uint8_t c = 0; c < 7; c++) + fpu_st_latency[c + 1] = fpu_st_latency[c]; + fpu_st_latency[0] = 0; + } + if (deps[opcode] & FPU_WRITE_ST0) { +#if 0 + if (fpu_st_latency[0]) + fatal("Bad latency ST0\n");*/ +#endif + fpu_st_latency[0] = FPU_RESULT_LATENCY(timings[opcode]); + } + if (deps[opcode] & FPU_WRITE_ST1) { +#if 0 + if (fpu_st_latency[1]) + fatal("Bad latency ST1\n");*/ +#endif + fpu_st_latency[1] = FPU_RESULT_LATENCY(timings[opcode]); + } + if (deps[opcode] & FPU_WRITE_STREG) { + int reg = fetchdat & 7; if (deps[opcode] & FPU_POP) - { - int c; - - for (c = 0; c < 7; c++) - fpu_st_latency[c] = fpu_st_latency[c+1]; - fpu_st_latency[7] = 0; - } - if (deps[opcode] & FPU_POP2) - { - int c; - - for (c = 0; c < 6; c++) - fpu_st_latency[c] = fpu_st_latency[c+2]; - fpu_st_latency[6] = fpu_st_latency[7] = 0; - } - if (timings[opcode] & CYCLES_FPU) - { - /* if (fpu_latency) - fatal("Bad latency FPU\n");*/ - fpu_latency = FPU_F_LATENCY(timings[opcode]); - } - - if (deps[opcode] & FPU_PUSH) - { - int c; - - for (c = 0; c < 7; c++) - fpu_st_latency[c+1] = fpu_st_latency[c]; - fpu_st_latency[0] = 0; - } - if (deps[opcode] & FPU_WRITE_ST0) - { -/* if (fpu_st_latency[0]) - fatal("Bad latency ST0\n");*/ - fpu_st_latency[0] = FPU_RESULT_LATENCY(timings[opcode]); - } - if (deps[opcode] & FPU_WRITE_ST1) - { -/* if (fpu_st_latency[1]) - fatal("Bad latency ST1\n");*/ - fpu_st_latency[1] = FPU_RESULT_LATENCY(timings[opcode]); - } - if (deps[opcode] & FPU_WRITE_STREG) - { - int reg = fetchdat & 7; - if (deps[opcode] & FPU_POP) - reg--; - if (reg >= 0 && - !(reg == 0 && (deps[opcode] & FPU_WRITE_ST0)) && - !(reg == 1 && (deps[opcode] & FPU_WRITE_ST1))) - { -/* if (fpu_st_latency[reg]) - fatal("Bad latency STREG %i %08x %i %016llx %02x\n",fpu_st_latency[reg], fetchdat, reg, timings[opcode], opcode);*/ - fpu_st_latency[reg] = FPU_RESULT_LATENCY(timings[opcode]); - } + reg--; + if (reg >= 0 && !(reg == 0 && (deps[opcode] & FPU_WRITE_ST0)) && !(reg == 1 && (deps[opcode] & FPU_WRITE_ST1))) { +#if 0 + if (fpu_st_latency[reg]) + fatal("Bad latency STREG %i %08x %i %016llx %02x\n",fpu_st_latency[reg], fetchdat, reg, timings[opcode], opcode);*/ +#endif + fpu_st_latency[reg] = FPU_RESULT_LATENCY(timings[opcode]); } + } } -static void codegen_timing_winchip2_block_start() +static void +codegen_timing_winchip2_block_start(void) { - regmask_modified = 0; - decode_delay = decode_delay_offset = 0; - u_pipe_full = 0; + regmask_modified = 0; + decode_delay = decode_delay_offset = 0; + u_pipe_full = 0; } -static void codegen_timing_winchip2_start() +static void +codegen_timing_winchip2_start(void) { - timing_count = 0; - last_prefix = 0; + timing_count = 0; + last_prefix = 0; } -static void codegen_timing_winchip2_prefix(uint8_t prefix, uint32_t fetchdat) +static void +codegen_timing_winchip2_prefix(uint8_t prefix, uint32_t fetchdat) { - if (prefix == 0x0f) - { - /*0fh prefix is 'free'*/ - last_prefix = prefix; - return; - } - /*On WinChip all prefixes take 1 cycle to decode. Decode may be shadowed - by execution of previous instructions*/ - decode_delay_offset++; + if (prefix == 0x0f) { + /*0fh prefix is 'free'*/ last_prefix = prefix; + return; + } + /*On WinChip all prefixes take 1 cycle to decode. Decode may be shadowed + by execution of previous instructions*/ + decode_delay_offset++; + last_prefix = prefix; } -static void codegen_timing_winchip2_opcode(uint8_t opcode, uint32_t fetchdat, int op_32, uint32_t op_pc) +static void +codegen_timing_winchip2_opcode(uint8_t opcode, uint32_t fetchdat, int op_32, UNUSED(uint32_t op_pc)) { - uint32_t *timings; - uint64_t *deps; - int mod3 = ((fetchdat & 0xc0) == 0xc0); - int bit8 = !(opcode & 1); - int agi_stall = 0; + uint32_t *timings; + uint64_t *deps; + int mod3 = ((fetchdat & 0xc0) == 0xc0); + int bit8 = !(opcode & 1); + int agi_stall = 0; - switch (last_prefix) - { - case 0x0f: - timings = mod3 ? opcode_timings_0f_mod3 : opcode_timings_0f; - deps = mod3 ? opcode_deps_0f_mod3 : opcode_deps_0f; - break; - - case 0xd8: - timings = mod3 ? opcode_timings_d8_mod3 : opcode_timings_d8; - deps = mod3 ? opcode_deps_d8_mod3 : opcode_deps_d8; - opcode = (opcode >> 3) & 7; - break; - case 0xd9: - timings = mod3 ? opcode_timings_d9_mod3 : opcode_timings_d9; - deps = mod3 ? opcode_deps_d9_mod3 : opcode_deps_d9; - opcode = mod3 ? opcode & 0x3f : (opcode >> 3) & 7; - break; - case 0xda: - timings = mod3 ? opcode_timings_da_mod3 : opcode_timings_da; - deps = mod3 ? opcode_deps_da_mod3 : opcode_deps_da; - opcode = (opcode >> 3) & 7; - break; - case 0xdb: - timings = mod3 ? opcode_timings_db_mod3 : opcode_timings_db; - deps = mod3 ? opcode_deps_db_mod3 : opcode_deps_db; - opcode = mod3 ? opcode & 0x3f : (opcode >> 3) & 7; - break; - case 0xdc: - timings = mod3 ? opcode_timings_dc_mod3 : opcode_timings_dc; - deps = mod3 ? opcode_deps_dc_mod3 : opcode_deps_dc; - opcode = (opcode >> 3) & 7; - break; - case 0xdd: - timings = mod3 ? opcode_timings_dd_mod3 : opcode_timings_dd; - deps = mod3 ? opcode_deps_dd_mod3 : opcode_deps_dd; - opcode = (opcode >> 3) & 7; - break; - case 0xde: - timings = mod3 ? opcode_timings_de_mod3 : opcode_timings_de; - deps = mod3 ? opcode_deps_de_mod3 : opcode_deps_de; - opcode = (opcode >> 3) & 7; - break; - case 0xdf: - timings = mod3 ? opcode_timings_df_mod3 : opcode_timings_df; - deps = mod3 ? opcode_deps_df_mod3 : opcode_deps_df; - opcode = (opcode >> 3) & 7; - break; + switch (last_prefix) { + case 0x0f: + timings = mod3 ? opcode_timings_0f_mod3 : opcode_timings_0f; + deps = mod3 ? opcode_deps_0f_mod3 : opcode_deps_0f; + break; + + case 0xd8: + timings = mod3 ? opcode_timings_d8_mod3 : opcode_timings_d8; + deps = mod3 ? opcode_deps_d8_mod3 : opcode_deps_d8; + opcode = (opcode >> 3) & 7; + break; + case 0xd9: + timings = mod3 ? opcode_timings_d9_mod3 : opcode_timings_d9; + deps = mod3 ? opcode_deps_d9_mod3 : opcode_deps_d9; + opcode = mod3 ? opcode & 0x3f : (opcode >> 3) & 7; + break; + case 0xda: + timings = mod3 ? opcode_timings_da_mod3 : opcode_timings_da; + deps = mod3 ? opcode_deps_da_mod3 : opcode_deps_da; + opcode = (opcode >> 3) & 7; + break; + case 0xdb: + timings = mod3 ? opcode_timings_db_mod3 : opcode_timings_db; + deps = mod3 ? opcode_deps_db_mod3 : opcode_deps_db; + opcode = mod3 ? opcode & 0x3f : (opcode >> 3) & 7; + break; + case 0xdc: + timings = mod3 ? opcode_timings_dc_mod3 : opcode_timings_dc; + deps = mod3 ? opcode_deps_dc_mod3 : opcode_deps_dc; + opcode = (opcode >> 3) & 7; + break; + case 0xdd: + timings = mod3 ? opcode_timings_dd_mod3 : opcode_timings_dd; + deps = mod3 ? opcode_deps_dd_mod3 : opcode_deps_dd; + opcode = (opcode >> 3) & 7; + break; + case 0xde: + timings = mod3 ? opcode_timings_de_mod3 : opcode_timings_de; + deps = mod3 ? opcode_deps_de_mod3 : opcode_deps_de; + opcode = (opcode >> 3) & 7; + break; + case 0xdf: + timings = mod3 ? opcode_timings_df_mod3 : opcode_timings_df; + deps = mod3 ? opcode_deps_df_mod3 : opcode_deps_df; + opcode = (opcode >> 3) & 7; + break; + + default: + switch (opcode) { + case 0x80: + case 0x82: + case 0x83: + timings = mod3 ? opcode_timings_8x_mod3 : opcode_timings_8x; + deps = mod3 ? opcode_deps_8x_mod3 : opcode_deps_8x; + opcode = (fetchdat >> 3) & 7; + break; + case 0x81: + timings = mod3 ? opcode_timings_81_mod3 : opcode_timings_81; + deps = mod3 ? opcode_deps_81_mod3 : opcode_deps_81; + opcode = (fetchdat >> 3) & 7; + break; + + case 0xc0: + case 0xc1: + case 0xd0: + case 0xd1: + case 0xd2: + case 0xd3: + timings = mod3 ? opcode_timings_shift_mod3 : opcode_timings_shift; + deps = mod3 ? opcode_deps_shift_mod3 : opcode_deps_shift; + opcode = (fetchdat >> 3) & 7; + break; + + case 0xf6: + timings = mod3 ? opcode_timings_f6_mod3 : opcode_timings_f6; + deps = mod3 ? opcode_deps_f6_mod3 : opcode_deps_f6; + opcode = (fetchdat >> 3) & 7; + break; + case 0xf7: + timings = mod3 ? opcode_timings_f7_mod3 : opcode_timings_f7; + deps = mod3 ? opcode_deps_f7_mod3 : opcode_deps_f7; + opcode = (fetchdat >> 3) & 7; + break; + case 0xff: + timings = mod3 ? opcode_timings_ff_mod3 : opcode_timings_ff; + deps = mod3 ? opcode_deps_ff_mod3 : opcode_deps_ff; + opcode = (fetchdat >> 3) & 7; + break; default: - switch (opcode) - { - case 0x80: case 0x82: case 0x83: - timings = mod3 ? opcode_timings_8x_mod3 : opcode_timings_8x; - deps = mod3 ? opcode_deps_8x_mod3 : opcode_deps_8x; - opcode = (fetchdat >> 3) & 7; - break; - case 0x81: - timings = mod3 ? opcode_timings_81_mod3 : opcode_timings_81; - deps = mod3 ? opcode_deps_81_mod3 : opcode_deps_81; - opcode = (fetchdat >> 3) & 7; - break; - - case 0xc0: case 0xc1: case 0xd0: case 0xd1: case 0xd2: case 0xd3: - timings = mod3 ? opcode_timings_shift_mod3 : opcode_timings_shift; - deps = mod3 ? opcode_deps_shift_mod3 : opcode_deps_shift; - opcode = (fetchdat >> 3) & 7; - break; - - case 0xf6: - timings = mod3 ? opcode_timings_f6_mod3 : opcode_timings_f6; - deps = mod3 ? opcode_deps_f6_mod3 : opcode_deps_f6; - opcode = (fetchdat >> 3) & 7; - break; - case 0xf7: - timings = mod3 ? opcode_timings_f7_mod3 : opcode_timings_f7; - deps = mod3 ? opcode_deps_f7_mod3 : opcode_deps_f7; - opcode = (fetchdat >> 3) & 7; - break; - case 0xff: - timings = mod3 ? opcode_timings_ff_mod3 : opcode_timings_ff; - deps = mod3 ? opcode_deps_ff_mod3 : opcode_deps_ff; - opcode = (fetchdat >> 3) & 7; - break; + timings = mod3 ? opcode_timings_mod3 : opcode_timings; + deps = mod3 ? opcode_deps_mod3 : opcode_deps; + break; + } + } - default: - timings = mod3 ? opcode_timings_mod3 : opcode_timings; - deps = mod3 ? opcode_deps_mod3 : opcode_deps; - break; - } - } - - if (u_pipe_full) - { - uint8_t regmask = get_srcdep_mask(deps[opcode], fetchdat, bit8, u_pipe_op_32); - - if (can_pair(u_pipe_timings[u_pipe_opcode], timings[opcode], regmask)) - { - int cycles_a = u_pipe_timings[u_pipe_opcode] & 0xff; - int cycles_b = timings[opcode] & 0xff; - uint32_t timing = (cycles_a > cycles_b) ? u_pipe_timings[u_pipe_opcode] : timings[opcode]; - uint64_t temp_deps = 0; + if (u_pipe_full) { + uint8_t regmask = get_srcdep_mask(deps[opcode], fetchdat, bit8, u_pipe_op_32); - if (check_agi(deps, opcode, fetchdat, op_32) || check_agi(u_pipe_deps, u_pipe_opcode, u_pipe_fetchdat, u_pipe_op_32)) - agi_stall = 1; + if (can_pair(u_pipe_timings[u_pipe_opcode], timings[opcode], regmask)) { + int cycles_a = u_pipe_timings[u_pipe_opcode] & 0xff; + int cycles_b = timings[opcode] & 0xff; + uint32_t timing = (cycles_a > cycles_b) ? u_pipe_timings[u_pipe_opcode] : timings[opcode]; + uint64_t temp_deps = 0; - codegen_instruction(&timing, &temp_deps, 0, 0, 0, 0, agi_stall); - u_pipe_full = 0; - decode_delay_offset = 0; - regmask_modified = get_dstdep_mask(deps[opcode], fetchdat, bit8) | u_pipe_regmask; - return; - } - else - { - /*No pairing, run first instruction now*/ - if (check_agi(u_pipe_deps, u_pipe_opcode, u_pipe_fetchdat, u_pipe_op_32)) - agi_stall = 1; - codegen_instruction(u_pipe_timings, u_pipe_deps, u_pipe_opcode, u_pipe_fetchdat, u_pipe_decode_delay_offset, u_pipe_op_32, agi_stall); - u_pipe_full = 0; - regmask_modified = u_pipe_regmask; - } - } - if (timings[opcode] & CYCLES_IS_MMX) - { - /*Might pair with next instruction*/ - u_pipe_full = 1; - u_pipe_opcode = opcode; - u_pipe_timings = timings; - u_pipe_op_32 = op_32; - u_pipe_regmask = get_dstdep_mask(deps[opcode], fetchdat, bit8); - u_pipe_fetchdat = fetchdat; - u_pipe_decode_delay_offset = decode_delay_offset; - u_pipe_deps = deps; - decode_delay_offset = 0; - return; - } - - if (check_agi(deps, opcode, fetchdat, op_32)) + if (check_agi(deps, opcode, fetchdat, op_32) || check_agi(u_pipe_deps, u_pipe_opcode, u_pipe_fetchdat, u_pipe_op_32)) agi_stall = 1; - codegen_instruction(timings, deps, opcode, fetchdat, decode_delay_offset, op_32, agi_stall); - decode_delay_offset = 0; - regmask_modified = get_dstdep_mask(deps[opcode], fetchdat, bit8); -} -static void codegen_timing_winchip2_block_end() -{ - if (u_pipe_full) - { - int agi_stall = 0; - - if (check_agi(u_pipe_deps, u_pipe_opcode, u_pipe_fetchdat, u_pipe_op_32)) - agi_stall = 1; - codegen_instruction(u_pipe_timings, u_pipe_deps, u_pipe_opcode, u_pipe_fetchdat, u_pipe_decode_delay_offset, u_pipe_op_32, agi_stall); - u_pipe_full = 0; + codegen_instruction(&timing, &temp_deps, 0, 0, 0, 0, agi_stall); + u_pipe_full = 0; + decode_delay_offset = 0; + regmask_modified = get_dstdep_mask(deps[opcode], fetchdat, bit8) | u_pipe_regmask; + return; + } else { + /*No pairing, run first instruction now*/ + if (check_agi(u_pipe_deps, u_pipe_opcode, u_pipe_fetchdat, u_pipe_op_32)) + agi_stall = 1; + codegen_instruction(u_pipe_timings, u_pipe_deps, u_pipe_opcode, u_pipe_fetchdat, u_pipe_decode_delay_offset, u_pipe_op_32, agi_stall); + u_pipe_full = 0; + regmask_modified = u_pipe_regmask; } + } + if (timings[opcode] & CYCLES_IS_MMX) { + /*Might pair with next instruction*/ + u_pipe_full = 1; + u_pipe_opcode = opcode; + u_pipe_timings = timings; + u_pipe_op_32 = op_32; + u_pipe_regmask = get_dstdep_mask(deps[opcode], fetchdat, bit8); + u_pipe_fetchdat = fetchdat; + u_pipe_decode_delay_offset = decode_delay_offset; + u_pipe_deps = deps; + decode_delay_offset = 0; + return; + } + + if (check_agi(deps, opcode, fetchdat, op_32)) + agi_stall = 1; + codegen_instruction(timings, deps, opcode, fetchdat, decode_delay_offset, op_32, agi_stall); + decode_delay_offset = 0; + regmask_modified = get_dstdep_mask(deps[opcode], fetchdat, bit8); } -codegen_timing_t codegen_timing_winchip2 = +static void +codegen_timing_winchip2_block_end(void) { - codegen_timing_winchip2_start, - codegen_timing_winchip2_prefix, - codegen_timing_winchip2_opcode, - codegen_timing_winchip2_block_start, - codegen_timing_winchip2_block_end, - NULL + if (u_pipe_full) { + int agi_stall = 0; + + if (check_agi(u_pipe_deps, u_pipe_opcode, u_pipe_fetchdat, u_pipe_op_32)) + agi_stall = 1; + codegen_instruction(u_pipe_timings, u_pipe_deps, u_pipe_opcode, u_pipe_fetchdat, u_pipe_decode_delay_offset, u_pipe_op_32, agi_stall); + u_pipe_full = 0; + } +} + +codegen_timing_t codegen_timing_winchip2 = { + codegen_timing_winchip2_start, + codegen_timing_winchip2_prefix, + codegen_timing_winchip2_opcode, + codegen_timing_winchip2_block_start, + codegen_timing_winchip2_block_end, + NULL }; diff --git a/src/cpu/cpu.c b/src/cpu/cpu.c index 09d26cf25..75ad191f6 100644 --- a/src/cpu/cpu.c +++ b/src/cpu/cpu.c @@ -1,23 +1,24 @@ /* - * 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. + * 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. + * This file is part of the 86Box distribution. * - * CPU type handler. + * CPU type handler. * - * Authors: Sarah Walker, - * leilei, - * Miran Grca, - * Fred N. van Kempen, + * Authors: Sarah Walker, + * leilei, + * Miran Grca, + * Fred N. van Kempen, * - * Copyright 2008-2018 Sarah Walker. - * Copyright 2016-2018 leilei. - * Copyright 2016-2018 Miran Grca. - * Copyright 2018 Fred N. van Kempen. + * Copyright 2008-2020 Sarah Walker. + * Copyright 2016-2018 leilei. + * Copyright 2016-2020 Miran Grca. + * Copyright 2018-2021 Fred N. van Kempen. */ +#include #include #include #include @@ -32,12 +33,17 @@ #include <86box/machine.h> #include <86box/io.h> #include "x86_ops.h" +#include "x86seg_common.h" #include <86box/mem.h> #include <86box/nmi.h> #include <86box/pic.h> #include <86box/pci.h> +#include <86box/gdbstub.h> +#include <86box/plat_fallthrough.h> +#include <86box/plat_unused.h> + #ifdef USE_DYNAREC -# include "codegen.h" +# include "codegen.h" #endif #include "x87_timings.h" @@ -48,310 +54,430 @@ #define CCR3_SMI_LOCK (1 << 0) #define CCR3_NMI_EN (1 << 1) - enum { - CPUID_FPU = (1 << 0), - CPUID_VME = (1 << 1), - CPUID_PSE = (1 << 3), - CPUID_TSC = (1 << 4), - CPUID_MSR = (1 << 5), - CPUID_PAE = (1 << 6), - CPUID_MCE = (1 << 7), - CPUID_CMPXCHG8B = (1 << 8), - CPUID_AMDSEP = (1 << 10), - CPUID_SEP = (1 << 11), - CPUID_MTRR = (1 << 12), - CPUID_MCA = (1 << 14), - CPUID_CMOV = (1 << 15), - CPUID_MMX = (1 << 23), - CPUID_FXSR = (1 << 24) + CPUID_FPU = (1 << 0), + CPUID_VME = (1 << 1), + CPUID_PSE = (1 << 3), + CPUID_TSC = (1 << 4), + CPUID_MSR = (1 << 5), + CPUID_PAE = (1 << 6), + CPUID_MCE = (1 << 7), + CPUID_CMPXCHG8B = (1 << 8), + CPUID_AMDSEP = (1 << 10), + CPUID_SEP = (1 << 11), + CPUID_MTRR = (1 << 12), + CPUID_PGE = (1 << 13), + CPUID_MCA = (1 << 14), + CPUID_CMOV = (1 << 15), + CPUID_MMX = (1 << 23), + CPUID_FXSR = (1 << 24) }; /*Addition flags returned by CPUID function 0x80000001*/ -#define CPUID_3DNOW (1UL << 31UL) - +#define CPUID_3DNOW (1UL << 31UL) +#define CPUID_3DNOWE (1UL << 30UL) /* Make sure this is as low as possible. */ -cpu_state_t cpu_state; +cpu_state_t cpu_state; +fpu_state_t fpu_state; + +/* Place this immediately after. */ +uint32_t abrt_error; #ifdef USE_DYNAREC -const OpFn *x86_dynarec_opcodes, *x86_dynarec_opcodes_0f, - *x86_dynarec_opcodes_d8_a16, *x86_dynarec_opcodes_d8_a32, - *x86_dynarec_opcodes_d9_a16, *x86_dynarec_opcodes_d9_a32, - *x86_dynarec_opcodes_da_a16, *x86_dynarec_opcodes_da_a32, - *x86_dynarec_opcodes_db_a16, *x86_dynarec_opcodes_db_a32, - *x86_dynarec_opcodes_dc_a16, *x86_dynarec_opcodes_dc_a32, - *x86_dynarec_opcodes_dd_a16, *x86_dynarec_opcodes_dd_a32, - *x86_dynarec_opcodes_de_a16, *x86_dynarec_opcodes_de_a32, - *x86_dynarec_opcodes_df_a16, *x86_dynarec_opcodes_df_a32, - *x86_dynarec_opcodes_REPE, *x86_dynarec_opcodes_REPNE, - *x86_dynarec_opcodes_3DNOW; +const OpFn *x86_dynarec_opcodes; +const OpFn *x86_dynarec_opcodes_0f; +const OpFn *x86_dynarec_opcodes_d8_a16; +const OpFn *x86_dynarec_opcodes_d8_a32; +const OpFn *x86_dynarec_opcodes_d9_a16; +const OpFn *x86_dynarec_opcodes_d9_a32; +const OpFn *x86_dynarec_opcodes_da_a16; +const OpFn *x86_dynarec_opcodes_da_a32; +const OpFn *x86_dynarec_opcodes_db_a16; +const OpFn *x86_dynarec_opcodes_db_a32; +const OpFn *x86_dynarec_opcodes_dc_a16; +const OpFn *x86_dynarec_opcodes_dc_a32; +const OpFn *x86_dynarec_opcodes_dd_a16; +const OpFn *x86_dynarec_opcodes_dd_a32; +const OpFn *x86_dynarec_opcodes_de_a16; +const OpFn *x86_dynarec_opcodes_de_a32; +const OpFn *x86_dynarec_opcodes_df_a16; +const OpFn *x86_dynarec_opcodes_df_a32; +const OpFn *x86_dynarec_opcodes_REPE; +const OpFn *x86_dynarec_opcodes_REPNE; +const OpFn *x86_dynarec_opcodes_3DNOW; #endif -const OpFn *x86_opcodes, *x86_opcodes_0f, - *x86_opcodes_d8_a16, *x86_opcodes_d8_a32, - *x86_opcodes_d9_a16, *x86_opcodes_d9_a32, - *x86_opcodes_da_a16, *x86_opcodes_da_a32, - *x86_opcodes_db_a16, *x86_opcodes_db_a32, - *x86_opcodes_dc_a16, *x86_opcodes_dc_a32, - *x86_opcodes_dd_a16, *x86_opcodes_dd_a32, - *x86_opcodes_de_a16, *x86_opcodes_de_a32, - *x86_opcodes_df_a16, *x86_opcodes_df_a32, - *x86_opcodes_REPE, *x86_opcodes_REPNE, - *x86_opcodes_3DNOW; +const OpFn *x86_opcodes; +const OpFn *x86_opcodes_0f; +const OpFn *x86_opcodes_d8_a16; +const OpFn *x86_opcodes_d8_a32; +const OpFn *x86_opcodes_d9_a16; +const OpFn *x86_opcodes_d9_a32; +const OpFn *x86_opcodes_da_a16; +const OpFn *x86_opcodes_da_a32; +const OpFn *x86_opcodes_db_a16; +const OpFn *x86_opcodes_db_a32; +const OpFn *x86_opcodes_dc_a16; +const OpFn *x86_opcodes_dc_a32; +const OpFn *x86_opcodes_dd_a16; +const OpFn *x86_opcodes_dd_a32; +const OpFn *x86_opcodes_de_a16; +const OpFn *x86_opcodes_de_a32; +const OpFn *x86_opcodes_df_a16; +const OpFn *x86_opcodes_df_a32; +const OpFn *x86_opcodes_REPE; +const OpFn *x86_opcodes_REPNE; +const OpFn *x86_opcodes_3DNOW; -uint16_t cpu_fast_off_count, cpu_fast_off_val; -uint16_t temp_seg_data[4] = {0, 0, 0, 0}; +const OpFn *x86_2386_opcodes; +const OpFn *x86_2386_opcodes_0f; +const OpFn *x86_2386_opcodes_d8_a16; +const OpFn *x86_2386_opcodes_d8_a32; +const OpFn *x86_2386_opcodes_d9_a16; +const OpFn *x86_2386_opcodes_d9_a32; +const OpFn *x86_2386_opcodes_da_a16; +const OpFn *x86_2386_opcodes_da_a32; +const OpFn *x86_2386_opcodes_db_a16; +const OpFn *x86_2386_opcodes_db_a32; +const OpFn *x86_2386_opcodes_dc_a16; +const OpFn *x86_2386_opcodes_dc_a32; +const OpFn *x86_2386_opcodes_dd_a16; +const OpFn *x86_2386_opcodes_dd_a32; +const OpFn *x86_2386_opcodes_de_a16; +const OpFn *x86_2386_opcodes_de_a32; +const OpFn *x86_2386_opcodes_df_a16; +const OpFn *x86_2386_opcodes_df_a32; +const OpFn *x86_2386_opcodes_REPE; +const OpFn *x86_2386_opcodes_REPNE; -int isa_cycles, cpu_inited, +uint16_t cpu_fast_off_count; +uint16_t cpu_fast_off_val; +uint16_t temp_seg_data[4] = { 0, 0, 0, 0 }; - cpu_cycles_read, cpu_cycles_read_l, cpu_cycles_write, cpu_cycles_write_l, - cpu_prefetch_cycles, cpu_prefetch_width, cpu_mem_prefetch_cycles, cpu_rom_prefetch_cycles, - cpu_waitstates, cpu_cache_int_enabled, cpu_cache_ext_enabled, - cpu_isa_speed, cpu_pci_speed, cpu_isa_pci_div, cpu_agp_speed, cpu_alt_reset, +int isa_cycles; +int cpu_inited; - cpu_override, cpu_effective, cpu_multi, cpu_16bitbus, cpu_64bitbus, cpu_busspeed, - cpu_cyrix_alignment, CPUID, +int cpu_cycles_read; +int cpu_cycles_read_l; +int cpu_cycles_write; +int cpu_cycles_write_l; +int cpu_prefetch_cycles; +int cpu_prefetch_width; +int cpu_mem_prefetch_cycles; +int cpu_rom_prefetch_cycles; +int cpu_waitstates; +int cpu_cache_int_enabled; +int cpu_cache_ext_enabled; +int cpu_isa_speed; +int cpu_pci_speed; +int cpu_isa_pci_div; +int cpu_agp_speed; +int cpu_alt_reset; - is286, is386, is486 = 1, - cpu_isintel, cpu_iscyrix, hascache, isibm486, israpidcad, is_vpc, - is_am486, is_am486dxl, is_pentium, is_k5, is_k6, is_p6, is_cxsmm, hasfpu, +int cpu_override; +int cpu_effective; +int cpu_multi; +int cpu_16bitbus; +int cpu_64bitbus; +int cpu_cyrix_alignment; +int CPUID; - timing_rr, timing_mr, timing_mrl, timing_rm, timing_rml, - timing_mm, timing_mml, timing_bt, timing_bnt, - timing_int, timing_int_rm, timing_int_v86, timing_int_pm, - timing_int_pm_outer, timing_iret_rm, timing_iret_v86, timing_iret_pm, - timing_iret_pm_outer, timing_call_rm, timing_call_pm, timing_call_pm_gate, - timing_call_pm_gate_inner, timing_retf_rm, timing_retf_pm, timing_retf_pm_outer, - timing_jmp_rm, timing_jmp_pm, timing_jmp_pm_gate, timing_misaligned; -uint32_t cpu_features, cpu_fast_off_flags; +int is186; +int is_nec; +int is286; +int is386; +int is6117; +int is486 = 1; +int cpu_isintel; +int cpu_iscyrix; +int hascache; +int isibm486; +int israpidcad; +int is_vpc; +int is_am486; +int is_am486dxl; +int is_pentium; +int is_k5; +int is_k6; +int is_p6; +int is_cxsmm; +int hasfpu; -uint32_t _tr[8] = {0, 0, 0, 0, 0, 0, 0, 0}; -uint32_t cache_index = 0; -uint8_t _cache[2048]; +int timing_rr; +int timing_mr; +int timing_mrl; +int timing_rm; +int timing_rml; +int timing_mm; +int timing_mml; +int timing_bt; +int timing_bnt; +int timing_int; +int timing_int_rm; +int timing_int_v86; +int timing_int_pm; +int timing_int_pm_outer; +int timing_iret_rm; +int timing_iret_v86; +int timing_iret_pm; +int timing_iret_pm_outer; +int timing_call_rm; +int timing_call_pm; +int timing_call_pm_gate; +int timing_call_pm_gate_inner; +int timing_retf_rm; +int timing_retf_pm; +int timing_retf_pm_outer; +int timing_jmp_rm; +int timing_jmp_pm; +int timing_jmp_pm_gate; +int timing_misaligned; -uint64_t cpu_CR4_mask, tsc = 0; -uint64_t pmc[2] = {0, 0}; +uint32_t cpu_features; +uint32_t cpu_fast_off_flags; -double cpu_dmulti; +uint32_t _tr[8] = { 0, 0, 0, 0, 0, 0, 0, 0 }; +uint32_t cache_index = 0; +uint8_t _cache[2048]; -msr_t msr; +uint64_t cpu_CR4_mask; +uint64_t tsc = 0; +uint64_t pmc[2] = { 0, 0 }; -cyrix_t cyrix; +double cpu_dmulti; +double cpu_busspeed; -cpu_family_t *cpu_f; -CPU *cpu_s; +msr_t msr; -uint8_t do_translate = 0, do_translate2 = 0; +cyrix_t cyrix; -void (*cpu_exec)(int cycs); +cpu_family_t *cpu_f; +CPU *cpu_s; +uint8_t do_translate = 0; +uint8_t do_translate2 = 0; -static uint8_t ccr0, ccr1, ccr2, ccr3, ccr4, ccr5, ccr6; +void (*cpu_exec)(int32_t cycs); -static int cyrix_addr; +static uint8_t ccr0; +static uint8_t ccr1; +static uint8_t ccr2; +static uint8_t ccr3; +static uint8_t ccr4; +static uint8_t ccr5; +static uint8_t ccr6; +static int cyrix_addr; -static void cpu_write(uint16_t addr, uint8_t val, void *priv); -static uint8_t cpu_read(uint16_t addr, void *priv); - +static void cpu_write(uint16_t addr, uint8_t val, void *priv); +static uint8_t cpu_read(uint16_t addr, void *priv); #ifdef ENABLE_CPU_LOG int cpu_do_log = ENABLE_CPU_LOG; - void cpu_log(const char *fmt, ...) { va_list ap; if (cpu_do_log) { - va_start(ap, fmt); - pclog_ex(fmt, ap); - va_end(ap); + va_start(ap, fmt); + pclog_ex(fmt, ap); + va_end(ap); } } #else -#define cpu_log(fmt, ...) +# define cpu_log(fmt, ...) #endif - int cpu_has_feature(int feature) { return cpu_features & feature; } - void cpu_dynamic_switch(int new_cpu) { int c; if (cpu_effective == new_cpu) - return; + return; - c = cpu; + c = cpu; cpu = new_cpu; cpu_set(); pc_speed_changed(); cpu = c; } - void cpu_set_edx(void) { EDX = cpu_s->edx_reset; + if (fpu_softfloat) + SF_FPU_reset(); } - cpu_family_t * cpu_get_family(const char *internal_name) { int c = 0; while (cpu_families[c].package) { - if (!strcmp(internal_name, cpu_families[c].internal_name)) - return (cpu_family_t *) &cpu_families[c]; - c++; + if (!strcmp(internal_name, cpu_families[c].internal_name)) + return (cpu_family_t *) &cpu_families[c]; + c++; } return NULL; } - uint8_t cpu_is_eligible(const cpu_family_t *cpu_family, int cpu, int machine) { const machine_t *machine_s = &machines[machine]; - const CPU *cpu_s = &cpu_family->cpus[cpu]; - uint32_t packages, bus_speed; - uint8_t i; - double multi; + const CPU *cpu_s = &cpu_family->cpus[cpu]; + uint32_t packages; + uint32_t bus_speed; + uint8_t i; + double multi; /* Full override. */ if (cpu_override > 1) - return 1; + return 1; /* Add implicit CPU package compatibility. */ - packages = machine_s->cpu_package; + packages = machine_s->cpu.package; if (packages & CPU_PKG_SOCKET3) - packages |= CPU_PKG_SOCKET1; + packages |= CPU_PKG_SOCKET1; else if (packages & CPU_PKG_SLOT1) - packages |= CPU_PKG_SOCKET370; + packages |= CPU_PKG_SOCKET370 | CPU_PKG_SOCKET8; /* Package type. */ if (!(cpu_family->package & packages)) - return 0; + return 0; /* Partial override. */ if (cpu_override) - return 1; + return 1; /* Check CPU blocklist. */ - if (machine_s->cpu_block) { - i = 0; + if (machine_s->cpu.block) { + i = 0; - while (machine_s->cpu_block[i]) { - if (machine_s->cpu_block[i++] == cpu_s->cpu_type) - return 0; - } + while (machine_s->cpu.block[i]) { + if (machine_s->cpu.block[i++] == cpu_s->cpu_type) + return 0; + } } bus_speed = cpu_s->rspeed / cpu_s->multi; /* Minimum bus speed with ~0.84 MHz (for 8086) tolerance. */ - if (machine_s->cpu_min_bus && (bus_speed < (machine_s->cpu_min_bus - 840907))) - return 0; + if (machine_s->cpu.min_bus && (bus_speed < (machine_s->cpu.min_bus - 840907))) + return 0; /* Maximum bus speed with ~0.84 MHz (for 8086) tolerance. */ - if (machine_s->cpu_max_bus && (bus_speed > (machine_s->cpu_max_bus + 840907))) - return 0; + if (machine_s->cpu.max_bus && (bus_speed > (machine_s->cpu.max_bus + 840907))) + return 0; /* Minimum voltage with 0.1V tolerance. */ - if (machine_s->cpu_min_voltage && (cpu_s->voltage < (machine_s->cpu_min_voltage - 100))) - return 0; + if (machine_s->cpu.min_voltage && (cpu_s->voltage < (machine_s->cpu.min_voltage - 100))) + return 0; /* Maximum voltage with 0.1V tolerance. */ - if (machine_s->cpu_max_voltage && (cpu_s->voltage > (machine_s->cpu_max_voltage + 100))) - return 0; + if (machine_s->cpu.max_voltage && (cpu_s->voltage > (machine_s->cpu.max_voltage + 100))) + return 0; /* Account for CPUs which use a different internal multiplier than specified by jumpers. */ multi = cpu_s->multi; /* Don't care about multiplier compatibility on fixed multiplier CPUs. */ if (cpu_s->cpu_flags & CPU_FIXED_MULTIPLIER) - return 1; + return 1; else if (cpu_family->package & CPU_PKG_SOCKET5_7) { - if ((multi == 1.5) && (cpu_s->cpu_type == CPU_5K86) && (machine_s->cpu_min_multi > 1.5)) /* K5 5k86 */ - multi = 2.0; - else if (multi == 1.75) /* K5 5k86 */ - multi = 2.5; - else if (multi == 2.0) { - if (cpu_s->cpu_type == CPU_5K86) /* K5 5k86 */ - multi = 3.0; - /* K6-2+ / K6-3+ */ - else if ((cpu_s->cpu_type == CPU_K6_2P) || (cpu_s->cpu_type == CPU_K6_3P)) - multi = 2.5; - else if (((cpu_s->cpu_type == CPU_WINCHIP) || (cpu_s->cpu_type == CPU_WINCHIP2)) && - (machine_s->cpu_min_multi > 2.0)) /* WinChip (2) */ - multi = 2.5; - } - else if (multi == (7.0 / 3.0)) /* WinChip 2A - 2.33x */ - multi = 5.0; - else if (multi == (8.0 / 3.0)) /* WinChip 2A - 2.66x */ - multi = 5.5; - else if ((multi == 3.0) && (cpu_s->cpu_type == CPU_Cx6x86 || cpu_s->cpu_type == CPU_Cx6x86L)) /* 6x86(L) */ - multi = 1.5; - else if (multi == (10.0 / 3.0)) /* WinChip 2A - 3.33x */ - multi = 2.0; - else if (multi == 3.5) /* standard set by the Pentium MMX */ - multi = 1.5; - else if (multi == 4.0) { - /* WinChip (2) */ - if ((cpu_s->cpu_type == CPU_WINCHIP) || (cpu_s->cpu_type == CPU_WINCHIP2)) { - if (machine_s->cpu_min_multi >= 1.5) - multi = 1.5; - else if (machine_s->cpu_min_multi >= 3.5) - multi = 3.5; - else if (machine_s->cpu_min_multi >= 4.5) - multi = 4.5; - } else if ((cpu_s->cpu_type == CPU_Cx6x86) || (cpu_s->cpu_type == CPU_Cx6x86L)) /* 6x86(L) */ - multi = 3.0; - } else if ((multi == 5.0) && ((cpu_s->cpu_type == CPU_WINCHIP) || (cpu_s->cpu_type == CPU_WINCHIP2)) && - (machine_s->cpu_min_multi > 5.0)) /* WinChip (2) */ - multi = 5.5; - else if (multi == 6.0) /* K6-2(+) / K6-3(+) */ - multi = 2.0; + if ((multi == 1.5) && (cpu_s->cpu_type == CPU_5K86) && (machine_s->cpu.min_multi > 1.5)) /* K5 5k86 */ + multi = 2.0; + else if (multi == 1.75) /* K5 5k86 */ + multi = 2.5; + else if (multi == 2.0) { + if (cpu_s->cpu_type == CPU_5K86) /* K5 5k86 */ + multi = 3.0; + /* K6-2+ / K6-3+ */ + else if ((cpu_s->cpu_type == CPU_K6_2P) || (cpu_s->cpu_type == CPU_K6_3P)) + multi = 2.5; + else if (((cpu_s->cpu_type == CPU_WINCHIP) || (cpu_s->cpu_type == CPU_WINCHIP2)) && (machine_s->cpu.min_multi > 2.0)) /* WinChip (2) */ + multi = 2.5; + } else if (multi == (7.0 / 3.0)) /* WinChip 2A - 2.33x */ + multi = 5.0; + else if (multi == (8.0 / 3.0)) /* WinChip 2A - 2.66x */ + multi = 5.5; + else if ((multi == 3.0) && (cpu_s->cpu_type == CPU_Cx6x86 || cpu_s->cpu_type == CPU_Cx6x86L)) /* 6x86(L) */ + multi = 1.5; + else if (multi == (10.0 / 3.0)) /* WinChip 2A - 3.33x */ + multi = 2.0; + else if (multi == 3.5) /* standard set by the Pentium MMX */ + multi = 1.5; + else if (multi == 4.0) { + /* WinChip (2) */ + if ((cpu_s->cpu_type == CPU_WINCHIP) || (cpu_s->cpu_type == CPU_WINCHIP2)) { + if (machine_s->cpu.min_multi >= 1.5) + multi = 1.5; + else if (machine_s->cpu.min_multi >= 3.5) + multi = 3.5; + else if (machine_s->cpu.min_multi >= 4.5) + multi = 4.5; + } else if ((cpu_s->cpu_type == CPU_Cx6x86) || (cpu_s->cpu_type == CPU_Cx6x86L)) /* 6x86(L) */ + multi = 3.0; + } else if ((multi == 5.0) && ((cpu_s->cpu_type == CPU_WINCHIP) || (cpu_s->cpu_type == CPU_WINCHIP2)) && (machine_s->cpu.min_multi > 5.0)) /* WinChip (2) */ + multi = 5.5; + else if (multi == 6.0) /* K6-2(+) / K6-3(+) */ + multi = 2.0; } /* Minimum multiplier, */ - if (multi < machine_s->cpu_min_multi) - return 0; + if (multi < machine_s->cpu.min_multi) + return 0; /* Maximum multiplier. */ - if (machine_s->cpu_max_multi && (multi > machine_s->cpu_max_multi)) - return 0; + if (machine_s->cpu.max_multi && (multi > machine_s->cpu.max_multi)) + return 0; return 1; } - uint8_t cpu_family_is_eligible(const cpu_family_t *cpu_family, int machine) { int c = 0; while (cpu_family->cpus[c].cpu_type) { - if (cpu_is_eligible(cpu_family, c, machine)) - return 1; - c++; + if (cpu_is_eligible(cpu_family, c, machine)) + return 1; + c++; } return 0; } +void +SF_FPU_reset(void) +{ + if (fpu_type != FPU_NONE) { + fpu_state.cwd = 0x0040; + fpu_state.swd = 0; + fpu_state.tos = 0; + fpu_state.tag = 0x5555; + fpu_state.foo = 0; + fpu_state.fip = 0; + fpu_state.fcs = 0; + fpu_state.fds = 0; + fpu_state.fdp = 0; + memset(fpu_state.st_space, 0, sizeof(floatx80) * 8); + } +} void cpu_set(void) @@ -359,7 +485,7 @@ cpu_set(void) cpu_inited = 1; cpu_effective = cpu; - cpu_s = (CPU *) &cpu_f->cpus[cpu_effective]; + cpu_s = (CPU *) &cpu_f->cpus[cpu_effective]; #ifdef USE_ACYCS acycs = 0; @@ -367,48 +493,48 @@ cpu_set(void) soft_reset_pci = 0; - cpu_alt_reset = 0; + cpu_alt_reset = 0; unmask_a20_in_smm = 0; - CPUID = cpu_s->cpuid_model; - is8086 = (cpu_s->cpu_type > CPU_8088); - is286 = (cpu_s->cpu_type >= CPU_286); - is386 = (cpu_s->cpu_type >= CPU_386SX); - israpidcad = (cpu_s->cpu_type == CPU_RAPIDCAD); - isibm486 = (cpu_s->cpu_type == CPU_IBM386SLC) || (cpu_s->cpu_type == CPU_IBM486SLC) || - (cpu_s->cpu_type == CPU_IBM486BL); - is486 = (cpu_s->cpu_type >= CPU_RAPIDCAD); - is_am486 = (cpu_s->cpu_type == CPU_ENH_Am486DX); - is_am486dxl = (cpu_s->cpu_type == CPU_Am486DXL); + CPUID = cpu_s->cpuid_model; + is8086 = (cpu_s->cpu_type > CPU_8088) && (cpu_s->cpu_type != CPU_V20) && (cpu_s->cpu_type != CPU_188); + is_nec = (cpu_s->cpu_type == CPU_V20) || (cpu_s->cpu_type == CPU_V30); + is186 = (cpu_s->cpu_type == CPU_186) || (cpu_s->cpu_type == CPU_188) || (cpu_s->cpu_type == CPU_V20) || (cpu_s->cpu_type == CPU_V30); + is286 = (cpu_s->cpu_type >= CPU_286); + is386 = (cpu_s->cpu_type >= CPU_386SX); + israpidcad = (cpu_s->cpu_type == CPU_RAPIDCAD); + isibm486 = (cpu_s->cpu_type == CPU_IBM386SLC) || (cpu_s->cpu_type == CPU_IBM486SLC) || (cpu_s->cpu_type == CPU_IBM486BL); + is486 = (cpu_s->cpu_type >= CPU_RAPIDCAD); + is_am486 = (cpu_s->cpu_type == CPU_ENH_Am486DX); + is_am486dxl = (cpu_s->cpu_type == CPU_Am486DXL); + + is6117 = !strcmp(cpu_f->manufacturer, "ALi"); cpu_isintel = !strcmp(cpu_f->manufacturer, "Intel"); cpu_iscyrix = !strcmp(cpu_f->manufacturer, "Cyrix") || !strcmp(cpu_f->manufacturer, "ST"); /* SL-Enhanced Intel 486s have the same SMM save state table layout as Pentiums, and the WinChip datasheet claims those are Pentium-compatible as well. AMD Am486DXL/DXL2 also has compatible SMM, or would if not for it's different SMBase*/ - is_pentium = (cpu_isintel && (cpu_s->cpu_type >= CPU_i486SX_SLENH) && (cpu_s->cpu_type < CPU_PENTIUMPRO)) || - !strcmp(cpu_f->manufacturer, "IDT") || (cpu_s->cpu_type == CPU_Am486DXL); - is_k5 = !strcmp(cpu_f->manufacturer, "AMD") && (cpu_s->cpu_type > CPU_ENH_Am486DX) && (cpu_s->cpu_type < CPU_K6); - is_k6 = (cpu_s->cpu_type >= CPU_K6) && !strcmp(cpu_f->manufacturer, "AMD"); + is_pentium = (cpu_isintel && (cpu_s->cpu_type >= CPU_i486SX_SLENH) && (cpu_s->cpu_type < CPU_PENTIUMPRO)) || !strcmp(cpu_f->manufacturer, "IDT") || (cpu_s->cpu_type == CPU_Am486DXL); + is_k5 = !strcmp(cpu_f->manufacturer, "AMD") && (cpu_s->cpu_type > CPU_ENH_Am486DX) && (cpu_s->cpu_type < CPU_K6); + is_k6 = (cpu_s->cpu_type >= CPU_K6) && !strcmp(cpu_f->manufacturer, "AMD"); /* The Samuel 2 datasheet claims it's Celeron-compatible. */ - is_p6 = (cpu_isintel && (cpu_s->cpu_type >= CPU_PENTIUMPRO)) || !strcmp(cpu_f->manufacturer, "VIA"); - is_cxsmm = (!strcmp(cpu_f->manufacturer, "Cyrix") || !strcmp(cpu_f->manufacturer, "ST")) && - (cpu_s->cpu_type >= CPU_Cx486S); + is_p6 = (cpu_isintel && (cpu_s->cpu_type >= CPU_PENTIUMPRO)) || !strcmp(cpu_f->manufacturer, "VIA"); + is_cxsmm = (!strcmp(cpu_f->manufacturer, "Cyrix") || !strcmp(cpu_f->manufacturer, "ST")) && (cpu_s->cpu_type >= CPU_Cx486S); - hasfpu = (fpu_type != FPU_NONE); - hascache = (cpu_s->cpu_type >= CPU_486SLC) || (cpu_s->cpu_type == CPU_IBM386SLC) || - (cpu_s->cpu_type == CPU_IBM486SLC) || (cpu_s->cpu_type == CPU_IBM486BL); + cpu_isintel = cpu_isintel || !strcmp(cpu_f->manufacturer, "AMD"); - cpu_16bitbus = (cpu_s->cpu_type == CPU_286) || (cpu_s->cpu_type == CPU_386SX) || - (cpu_s->cpu_type == CPU_486SLC) || (cpu_s->cpu_type == CPU_IBM386SLC) || - (cpu_s->cpu_type == CPU_IBM486SLC); + hasfpu = (fpu_type != FPU_NONE); + hascache = (cpu_s->cpu_type >= CPU_486SLC) || (cpu_s->cpu_type == CPU_IBM386SLC) || (cpu_s->cpu_type == CPU_IBM486SLC) || (cpu_s->cpu_type == CPU_IBM486BL); + + cpu_16bitbus = (cpu_s->cpu_type == CPU_286) || (cpu_s->cpu_type == CPU_386SX) || (cpu_s->cpu_type == CPU_486SLC) || (cpu_s->cpu_type == CPU_IBM386SLC) || (cpu_s->cpu_type == CPU_IBM486SLC); cpu_64bitbus = (cpu_s->cpu_type >= CPU_WINCHIP); if (cpu_s->multi) - cpu_busspeed = cpu_s->rspeed / cpu_s->multi; + cpu_busspeed = cpu_s->rspeed / cpu_s->multi; else - cpu_busspeed = cpu_s->rspeed; - cpu_multi = (int) ceil(cpu_s->multi); + cpu_busspeed = cpu_s->rspeed; + cpu_multi = (int) ceil(cpu_s->multi); cpu_dmulti = cpu_s->multi; ccr0 = ccr1 = ccr2 = ccr3 = ccr4 = ccr5 = ccr6 = 0; @@ -417,9 +543,9 @@ cpu_set(void) isa_cycles = cpu_s->atclk_div; if (cpu_s->rspeed <= 8000000) - cpu_rom_prefetch_cycles = cpu_mem_prefetch_cycles; + cpu_rom_prefetch_cycles = cpu_mem_prefetch_cycles; else - cpu_rom_prefetch_cycles = cpu_s->rspeed / 1000000; + cpu_rom_prefetch_cycles = cpu_s->rspeed / 1000000; cpu_set_isa_pci_div(0); cpu_set_pci_speed(0); @@ -435,85 +561,177 @@ cpu_set(void) #else x86_setopcodes(ops_386, ops_386_0f); #endif - x86_opcodes_REPE = ops_REPE; - x86_opcodes_REPNE = ops_REPNE; - x86_opcodes_3DNOW = ops_3DNOW; + x86_setopcodes_2386(ops_2386_386, ops_2386_386_0f); + x86_opcodes_REPE = ops_REPE; + x86_opcodes_REPNE = ops_REPNE; + x86_2386_opcodes_REPE = ops_2386_REPE; + x86_2386_opcodes_REPNE = ops_2386_REPNE; + x86_opcodes_3DNOW = ops_3DNOW; #ifdef USE_DYNAREC - x86_dynarec_opcodes_REPE = dynarec_ops_REPE; + x86_dynarec_opcodes_REPE = dynarec_ops_REPE; x86_dynarec_opcodes_REPNE = dynarec_ops_REPNE; x86_dynarec_opcodes_3DNOW = dynarec_ops_3DNOW; #endif if (hasfpu) { #ifdef USE_DYNAREC - x86_dynarec_opcodes_d8_a16 = dynarec_ops_fpu_d8_a16; - x86_dynarec_opcodes_d8_a32 = dynarec_ops_fpu_d8_a32; - x86_dynarec_opcodes_d9_a16 = dynarec_ops_fpu_d9_a16; - x86_dynarec_opcodes_d9_a32 = dynarec_ops_fpu_d9_a32; - x86_dynarec_opcodes_da_a16 = dynarec_ops_fpu_da_a16; - x86_dynarec_opcodes_da_a32 = dynarec_ops_fpu_da_a32; - x86_dynarec_opcodes_db_a16 = dynarec_ops_fpu_db_a16; - x86_dynarec_opcodes_db_a32 = dynarec_ops_fpu_db_a32; - x86_dynarec_opcodes_dc_a16 = dynarec_ops_fpu_dc_a16; - x86_dynarec_opcodes_dc_a32 = dynarec_ops_fpu_dc_a32; - x86_dynarec_opcodes_dd_a16 = dynarec_ops_fpu_dd_a16; - x86_dynarec_opcodes_dd_a32 = dynarec_ops_fpu_dd_a32; - x86_dynarec_opcodes_de_a16 = dynarec_ops_fpu_de_a16; - x86_dynarec_opcodes_de_a32 = dynarec_ops_fpu_de_a32; - x86_dynarec_opcodes_df_a16 = dynarec_ops_fpu_df_a16; - x86_dynarec_opcodes_df_a32 = dynarec_ops_fpu_df_a32; + if (fpu_softfloat) { + x86_dynarec_opcodes_d8_a16 = dynarec_ops_sf_fpu_d8_a16; + x86_dynarec_opcodes_d8_a32 = dynarec_ops_sf_fpu_d8_a32; + x86_dynarec_opcodes_d9_a16 = dynarec_ops_sf_fpu_d9_a16; + x86_dynarec_opcodes_d9_a32 = dynarec_ops_sf_fpu_d9_a32; + x86_dynarec_opcodes_da_a16 = dynarec_ops_sf_fpu_da_a16; + x86_dynarec_opcodes_da_a32 = dynarec_ops_sf_fpu_da_a32; + x86_dynarec_opcodes_db_a16 = dynarec_ops_sf_fpu_db_a16; + x86_dynarec_opcodes_db_a32 = dynarec_ops_sf_fpu_db_a32; + x86_dynarec_opcodes_dc_a16 = dynarec_ops_sf_fpu_dc_a16; + x86_dynarec_opcodes_dc_a32 = dynarec_ops_sf_fpu_dc_a32; + x86_dynarec_opcodes_dd_a16 = dynarec_ops_sf_fpu_dd_a16; + x86_dynarec_opcodes_dd_a32 = dynarec_ops_sf_fpu_dd_a32; + x86_dynarec_opcodes_de_a16 = dynarec_ops_sf_fpu_de_a16; + x86_dynarec_opcodes_de_a32 = dynarec_ops_sf_fpu_de_a32; + x86_dynarec_opcodes_df_a16 = dynarec_ops_sf_fpu_df_a16; + x86_dynarec_opcodes_df_a32 = dynarec_ops_sf_fpu_df_a32; + } else { + x86_dynarec_opcodes_d8_a16 = dynarec_ops_fpu_d8_a16; + x86_dynarec_opcodes_d8_a32 = dynarec_ops_fpu_d8_a32; + x86_dynarec_opcodes_d9_a16 = dynarec_ops_fpu_d9_a16; + x86_dynarec_opcodes_d9_a32 = dynarec_ops_fpu_d9_a32; + x86_dynarec_opcodes_da_a16 = dynarec_ops_fpu_da_a16; + x86_dynarec_opcodes_da_a32 = dynarec_ops_fpu_da_a32; + x86_dynarec_opcodes_db_a16 = dynarec_ops_fpu_db_a16; + x86_dynarec_opcodes_db_a32 = dynarec_ops_fpu_db_a32; + x86_dynarec_opcodes_dc_a16 = dynarec_ops_fpu_dc_a16; + x86_dynarec_opcodes_dc_a32 = dynarec_ops_fpu_dc_a32; + x86_dynarec_opcodes_dd_a16 = dynarec_ops_fpu_dd_a16; + x86_dynarec_opcodes_dd_a32 = dynarec_ops_fpu_dd_a32; + x86_dynarec_opcodes_de_a16 = dynarec_ops_fpu_de_a16; + x86_dynarec_opcodes_de_a32 = dynarec_ops_fpu_de_a32; + x86_dynarec_opcodes_df_a16 = dynarec_ops_fpu_df_a16; + x86_dynarec_opcodes_df_a32 = dynarec_ops_fpu_df_a32; + } #endif - x86_opcodes_d8_a16 = ops_fpu_d8_a16; - x86_opcodes_d8_a32 = ops_fpu_d8_a32; - x86_opcodes_d9_a16 = ops_fpu_d9_a16; - x86_opcodes_d9_a32 = ops_fpu_d9_a32; - x86_opcodes_da_a16 = ops_fpu_da_a16; - x86_opcodes_da_a32 = ops_fpu_da_a32; - x86_opcodes_db_a16 = ops_fpu_db_a16; - x86_opcodes_db_a32 = ops_fpu_db_a32; - x86_opcodes_dc_a16 = ops_fpu_dc_a16; - x86_opcodes_dc_a32 = ops_fpu_dc_a32; - x86_opcodes_dd_a16 = ops_fpu_dd_a16; - x86_opcodes_dd_a32 = ops_fpu_dd_a32; - x86_opcodes_de_a16 = ops_fpu_de_a16; - x86_opcodes_de_a32 = ops_fpu_de_a32; - x86_opcodes_df_a16 = ops_fpu_df_a16; - x86_opcodes_df_a32 = ops_fpu_df_a32; + if (fpu_softfloat) { + x86_opcodes_d8_a16 = ops_sf_fpu_d8_a16; + x86_opcodes_d8_a32 = ops_sf_fpu_d8_a32; + x86_opcodes_d9_a16 = ops_sf_fpu_d9_a16; + x86_opcodes_d9_a32 = ops_sf_fpu_d9_a32; + x86_opcodes_da_a16 = ops_sf_fpu_da_a16; + x86_opcodes_da_a32 = ops_sf_fpu_da_a32; + x86_opcodes_db_a16 = ops_sf_fpu_db_a16; + x86_opcodes_db_a32 = ops_sf_fpu_db_a32; + x86_opcodes_dc_a16 = ops_sf_fpu_dc_a16; + x86_opcodes_dc_a32 = ops_sf_fpu_dc_a32; + x86_opcodes_dd_a16 = ops_sf_fpu_dd_a16; + x86_opcodes_dd_a32 = ops_sf_fpu_dd_a32; + x86_opcodes_de_a16 = ops_sf_fpu_de_a16; + x86_opcodes_de_a32 = ops_sf_fpu_de_a32; + x86_opcodes_df_a16 = ops_sf_fpu_df_a16; + x86_opcodes_df_a32 = ops_sf_fpu_df_a32; + + x86_2386_opcodes_d8_a16 = ops_2386_sf_fpu_d8_a16; + x86_2386_opcodes_d8_a32 = ops_2386_sf_fpu_d8_a32; + x86_2386_opcodes_d9_a16 = ops_2386_sf_fpu_d9_a16; + x86_2386_opcodes_d9_a32 = ops_2386_sf_fpu_d9_a32; + x86_2386_opcodes_da_a16 = ops_2386_sf_fpu_da_a16; + x86_2386_opcodes_da_a32 = ops_2386_sf_fpu_da_a32; + x86_2386_opcodes_db_a16 = ops_2386_sf_fpu_db_a16; + x86_2386_opcodes_db_a32 = ops_2386_sf_fpu_db_a32; + x86_2386_opcodes_dc_a16 = ops_2386_sf_fpu_dc_a16; + x86_2386_opcodes_dc_a32 = ops_2386_sf_fpu_dc_a32; + x86_2386_opcodes_dd_a16 = ops_2386_sf_fpu_dd_a16; + x86_2386_opcodes_dd_a32 = ops_2386_sf_fpu_dd_a32; + x86_2386_opcodes_de_a16 = ops_2386_sf_fpu_de_a16; + x86_2386_opcodes_de_a32 = ops_2386_sf_fpu_de_a32; + x86_2386_opcodes_df_a16 = ops_2386_sf_fpu_df_a16; + x86_2386_opcodes_df_a32 = ops_2386_sf_fpu_df_a32; + } else { + x86_opcodes_d8_a16 = ops_fpu_d8_a16; + x86_opcodes_d8_a32 = ops_fpu_d8_a32; + x86_opcodes_d9_a16 = ops_fpu_d9_a16; + x86_opcodes_d9_a32 = ops_fpu_d9_a32; + x86_opcodes_da_a16 = ops_fpu_da_a16; + x86_opcodes_da_a32 = ops_fpu_da_a32; + x86_opcodes_db_a16 = ops_fpu_db_a16; + x86_opcodes_db_a32 = ops_fpu_db_a32; + x86_opcodes_dc_a16 = ops_fpu_dc_a16; + x86_opcodes_dc_a32 = ops_fpu_dc_a32; + x86_opcodes_dd_a16 = ops_fpu_dd_a16; + x86_opcodes_dd_a32 = ops_fpu_dd_a32; + x86_opcodes_de_a16 = ops_fpu_de_a16; + x86_opcodes_de_a32 = ops_fpu_de_a32; + x86_opcodes_df_a16 = ops_fpu_df_a16; + x86_opcodes_df_a32 = ops_fpu_df_a32; + + x86_2386_opcodes_d8_a16 = ops_2386_fpu_d8_a16; + x86_2386_opcodes_d8_a32 = ops_2386_fpu_d8_a32; + x86_2386_opcodes_d9_a16 = ops_2386_fpu_d9_a16; + x86_2386_opcodes_d9_a32 = ops_2386_fpu_d9_a32; + x86_2386_opcodes_da_a16 = ops_2386_fpu_da_a16; + x86_2386_opcodes_da_a32 = ops_2386_fpu_da_a32; + x86_2386_opcodes_db_a16 = ops_2386_fpu_db_a16; + x86_2386_opcodes_db_a32 = ops_2386_fpu_db_a32; + x86_2386_opcodes_dc_a16 = ops_2386_fpu_dc_a16; + x86_2386_opcodes_dc_a32 = ops_2386_fpu_dc_a32; + x86_2386_opcodes_dd_a16 = ops_2386_fpu_dd_a16; + x86_2386_opcodes_dd_a32 = ops_2386_fpu_dd_a32; + x86_2386_opcodes_de_a16 = ops_2386_fpu_de_a16; + x86_2386_opcodes_de_a32 = ops_2386_fpu_de_a32; + x86_2386_opcodes_df_a16 = ops_2386_fpu_df_a16; + x86_2386_opcodes_df_a32 = ops_2386_fpu_df_a32; + } } else { #ifdef USE_DYNAREC - x86_dynarec_opcodes_d8_a16 = dynarec_ops_nofpu_a16; - x86_dynarec_opcodes_d8_a32 = dynarec_ops_nofpu_a32; - x86_dynarec_opcodes_d9_a16 = dynarec_ops_nofpu_a16; - x86_dynarec_opcodes_d9_a32 = dynarec_ops_nofpu_a32; - x86_dynarec_opcodes_da_a16 = dynarec_ops_nofpu_a16; - x86_dynarec_opcodes_da_a32 = dynarec_ops_nofpu_a32; - x86_dynarec_opcodes_db_a16 = dynarec_ops_nofpu_a16; - x86_dynarec_opcodes_db_a32 = dynarec_ops_nofpu_a32; - x86_dynarec_opcodes_dc_a16 = dynarec_ops_nofpu_a16; - x86_dynarec_opcodes_dc_a32 = dynarec_ops_nofpu_a32; - x86_dynarec_opcodes_dd_a16 = dynarec_ops_nofpu_a16; - x86_dynarec_opcodes_dd_a32 = dynarec_ops_nofpu_a32; - x86_dynarec_opcodes_de_a16 = dynarec_ops_nofpu_a16; - x86_dynarec_opcodes_de_a32 = dynarec_ops_nofpu_a32; - x86_dynarec_opcodes_df_a16 = dynarec_ops_nofpu_a16; - x86_dynarec_opcodes_df_a32 = dynarec_ops_nofpu_a32; + x86_dynarec_opcodes_d8_a16 = dynarec_ops_nofpu_a16; + x86_dynarec_opcodes_d8_a32 = dynarec_ops_nofpu_a32; + x86_dynarec_opcodes_d9_a16 = dynarec_ops_nofpu_a16; + x86_dynarec_opcodes_d9_a32 = dynarec_ops_nofpu_a32; + x86_dynarec_opcodes_da_a16 = dynarec_ops_nofpu_a16; + x86_dynarec_opcodes_da_a32 = dynarec_ops_nofpu_a32; + x86_dynarec_opcodes_db_a16 = dynarec_ops_nofpu_a16; + x86_dynarec_opcodes_db_a32 = dynarec_ops_nofpu_a32; + x86_dynarec_opcodes_dc_a16 = dynarec_ops_nofpu_a16; + x86_dynarec_opcodes_dc_a32 = dynarec_ops_nofpu_a32; + x86_dynarec_opcodes_dd_a16 = dynarec_ops_nofpu_a16; + x86_dynarec_opcodes_dd_a32 = dynarec_ops_nofpu_a32; + x86_dynarec_opcodes_de_a16 = dynarec_ops_nofpu_a16; + x86_dynarec_opcodes_de_a32 = dynarec_ops_nofpu_a32; + x86_dynarec_opcodes_df_a16 = dynarec_ops_nofpu_a16; + x86_dynarec_opcodes_df_a32 = dynarec_ops_nofpu_a32; #endif - x86_opcodes_d8_a16 = ops_nofpu_a16; - x86_opcodes_d8_a32 = ops_nofpu_a32; - x86_opcodes_d9_a16 = ops_nofpu_a16; - x86_opcodes_d9_a32 = ops_nofpu_a32; - x86_opcodes_da_a16 = ops_nofpu_a16; - x86_opcodes_da_a32 = ops_nofpu_a32; - x86_opcodes_db_a16 = ops_nofpu_a16; - x86_opcodes_db_a32 = ops_nofpu_a32; - x86_opcodes_dc_a16 = ops_nofpu_a16; - x86_opcodes_dc_a32 = ops_nofpu_a32; - x86_opcodes_dd_a16 = ops_nofpu_a16; - x86_opcodes_dd_a32 = ops_nofpu_a32; - x86_opcodes_de_a16 = ops_nofpu_a16; - x86_opcodes_de_a32 = ops_nofpu_a32; - x86_opcodes_df_a16 = ops_nofpu_a16; - x86_opcodes_df_a32 = ops_nofpu_a32; + x86_opcodes_d8_a16 = ops_nofpu_a16; + x86_opcodes_d8_a32 = ops_nofpu_a32; + x86_opcodes_d9_a16 = ops_nofpu_a16; + x86_opcodes_d9_a32 = ops_nofpu_a32; + x86_opcodes_da_a16 = ops_nofpu_a16; + x86_opcodes_da_a32 = ops_nofpu_a32; + x86_opcodes_db_a16 = ops_nofpu_a16; + x86_opcodes_db_a32 = ops_nofpu_a32; + x86_opcodes_dc_a16 = ops_nofpu_a16; + x86_opcodes_dc_a32 = ops_nofpu_a32; + x86_opcodes_dd_a16 = ops_nofpu_a16; + x86_opcodes_dd_a32 = ops_nofpu_a32; + x86_opcodes_de_a16 = ops_nofpu_a16; + x86_opcodes_de_a32 = ops_nofpu_a32; + x86_opcodes_df_a16 = ops_nofpu_a16; + x86_opcodes_df_a32 = ops_nofpu_a32; + + x86_2386_opcodes_d8_a16 = ops_2386_nofpu_a16; + x86_2386_opcodes_d8_a32 = ops_2386_nofpu_a32; + x86_2386_opcodes_d9_a16 = ops_2386_nofpu_a16; + x86_2386_opcodes_d9_a32 = ops_2386_nofpu_a32; + x86_2386_opcodes_da_a16 = ops_2386_nofpu_a16; + x86_2386_opcodes_da_a32 = ops_2386_nofpu_a32; + x86_2386_opcodes_db_a16 = ops_2386_nofpu_a16; + x86_2386_opcodes_db_a32 = ops_2386_nofpu_a32; + x86_2386_opcodes_dc_a16 = ops_2386_nofpu_a16; + x86_2386_opcodes_dc_a32 = ops_2386_nofpu_a32; + x86_2386_opcodes_dd_a16 = ops_2386_nofpu_a16; + x86_2386_opcodes_dd_a32 = ops_2386_nofpu_a32; + x86_2386_opcodes_de_a16 = ops_2386_nofpu_a16; + x86_2386_opcodes_de_a32 = ops_2386_nofpu_a32; + x86_2386_opcodes_df_a16 = ops_2386_nofpu_a16; + x86_2386_opcodes_df_a32 = ops_2386_nofpu_a32; } #ifdef USE_DYNAREC @@ -522,918 +740,1113 @@ cpu_set(void) memset(&msr, 0, sizeof(msr)); - timing_misaligned = 0; + timing_misaligned = 0; cpu_cyrix_alignment = 0; - cpu_CR4_mask = 0; + cpu_CR4_mask = 0; switch (cpu_s->cpu_type) { - case CPU_8088: - case CPU_8086: - break; + case CPU_8088: + case CPU_8086: + break; - case CPU_286: + case CPU_V20: + case CPU_V30: + case CPU_186: + case CPU_188: #ifdef USE_DYNAREC - x86_setopcodes(ops_286, ops_286_0f, dynarec_ops_286, dynarec_ops_286_0f); + x86_setopcodes(ops_186, ops_186_0f, dynarec_ops_186, dynarec_ops_186_0f); #else - x86_setopcodes(ops_286, ops_286_0f); + x86_setopcodes(ops_186, ops_186_0f); #endif + x86_setopcodes_2386(ops_2386_186, ops_2386_186_0f); + break; - if (fpu_type == FPU_287) { + case CPU_286: #ifdef USE_DYNAREC - x86_dynarec_opcodes_d9_a16 = dynarec_ops_fpu_287_d9_a16; - x86_dynarec_opcodes_d9_a32 = dynarec_ops_fpu_287_d9_a32; - x86_dynarec_opcodes_da_a16 = dynarec_ops_fpu_287_da_a16; - x86_dynarec_opcodes_da_a32 = dynarec_ops_fpu_287_da_a32; - x86_dynarec_opcodes_db_a16 = dynarec_ops_fpu_287_db_a16; - x86_dynarec_opcodes_db_a32 = dynarec_ops_fpu_287_db_a32; - x86_dynarec_opcodes_dc_a16 = dynarec_ops_fpu_287_dc_a16; - x86_dynarec_opcodes_dc_a32 = dynarec_ops_fpu_287_dc_a32; - x86_dynarec_opcodes_dd_a16 = dynarec_ops_fpu_287_dd_a16; - x86_dynarec_opcodes_dd_a32 = dynarec_ops_fpu_287_dd_a32; - x86_dynarec_opcodes_de_a16 = dynarec_ops_fpu_287_de_a16; - x86_dynarec_opcodes_de_a32 = dynarec_ops_fpu_287_de_a32; - x86_dynarec_opcodes_df_a16 = dynarec_ops_fpu_287_df_a16; - x86_dynarec_opcodes_df_a32 = dynarec_ops_fpu_287_df_a32; -#endif - x86_opcodes_d9_a16 = ops_fpu_287_d9_a16; - x86_opcodes_d9_a32 = ops_fpu_287_d9_a32; - x86_opcodes_da_a16 = ops_fpu_287_da_a16; - x86_opcodes_da_a32 = ops_fpu_287_da_a32; - x86_opcodes_db_a16 = ops_fpu_287_db_a16; - x86_opcodes_db_a32 = ops_fpu_287_db_a32; - x86_opcodes_dc_a16 = ops_fpu_287_dc_a16; - x86_opcodes_dc_a32 = ops_fpu_287_dc_a32; - x86_opcodes_dd_a16 = ops_fpu_287_dd_a16; - x86_opcodes_dd_a32 = ops_fpu_287_dd_a32; - x86_opcodes_de_a16 = ops_fpu_287_de_a16; - x86_opcodes_de_a32 = ops_fpu_287_de_a32; - x86_opcodes_df_a16 = ops_fpu_287_df_a16; - x86_opcodes_df_a32 = ops_fpu_287_df_a32; - } - - timing_rr = 2; /* register dest - register src */ - timing_rm = 7; /* register dest - memory src */ - timing_mr = 7; /* memory dest - register src */ - timing_mm = 7; /* memory dest - memory src */ - timing_rml = 9; /* register dest - memory src long */ - timing_mrl = 11; /* memory dest - register src long */ - timing_mml = 11; /* memory dest - memory src */ - timing_bt = 4; /* branch taken */ - timing_bnt = 3; /* branch not taken */ - - timing_int = 0; - timing_int_rm = 23; - timing_int_v86 = 0; - timing_int_pm = 40; - timing_int_pm_outer = 78; - timing_iret_rm = 17; - timing_iret_v86 = 0; - timing_iret_pm = 31; - timing_iret_pm_outer = 55; - timing_call_rm = 13; - timing_call_pm = 26; - timing_call_pm_gate = 52; - timing_call_pm_gate_inner = 82; - timing_retf_rm = 15; - timing_retf_pm = 25; - timing_retf_pm_outer = 55; - timing_jmp_rm = 11; - timing_jmp_pm = 23; - timing_jmp_pm_gate = 38; - break; - - case CPU_IBM486SLC: - case CPU_IBM386SLC: - case CPU_IBM486BL: -#ifdef USE_DYNAREC - x86_setopcodes(ops_386, ops_ibm486_0f, dynarec_ops_386, dynarec_ops_ibm486_0f); + x86_setopcodes(ops_286, ops_286_0f, dynarec_ops_286, dynarec_ops_286_0f); #else - x86_setopcodes(ops_386, ops_ibm486_0f); + x86_setopcodes(ops_286, ops_286_0f); #endif - cpu_features = CPU_FEATURE_MSR; - /* FALLTHROUGH */ - case CPU_386SX: - case CPU_386DX: - if (fpu_type == FPU_287) { /* In case we get Deskpro 386 emulation */ + x86_setopcodes_2386(ops_2386_286, ops_2386_286_0f); + + if (fpu_type == FPU_287) { #ifdef USE_DYNAREC - x86_dynarec_opcodes_d9_a16 = dynarec_ops_fpu_287_d9_a16; - x86_dynarec_opcodes_d9_a32 = dynarec_ops_fpu_287_d9_a32; - x86_dynarec_opcodes_da_a16 = dynarec_ops_fpu_287_da_a16; - x86_dynarec_opcodes_da_a32 = dynarec_ops_fpu_287_da_a32; - x86_dynarec_opcodes_db_a16 = dynarec_ops_fpu_287_db_a16; - x86_dynarec_opcodes_db_a32 = dynarec_ops_fpu_287_db_a32; - x86_dynarec_opcodes_dc_a16 = dynarec_ops_fpu_287_dc_a16; - x86_dynarec_opcodes_dc_a32 = dynarec_ops_fpu_287_dc_a32; - x86_dynarec_opcodes_dd_a16 = dynarec_ops_fpu_287_dd_a16; - x86_dynarec_opcodes_dd_a32 = dynarec_ops_fpu_287_dd_a32; - x86_dynarec_opcodes_de_a16 = dynarec_ops_fpu_287_de_a16; - x86_dynarec_opcodes_de_a32 = dynarec_ops_fpu_287_de_a32; - x86_dynarec_opcodes_df_a16 = dynarec_ops_fpu_287_df_a16; - x86_dynarec_opcodes_df_a32 = dynarec_ops_fpu_287_df_a32; + if (fpu_softfloat) { + x86_dynarec_opcodes_d9_a16 = dynarec_ops_sf_fpu_287_d9_a16; + x86_dynarec_opcodes_d9_a32 = dynarec_ops_sf_fpu_287_d9_a32; + x86_dynarec_opcodes_da_a16 = dynarec_ops_sf_fpu_287_da_a16; + x86_dynarec_opcodes_da_a32 = dynarec_ops_sf_fpu_287_da_a32; + x86_dynarec_opcodes_db_a16 = dynarec_ops_sf_fpu_287_db_a16; + x86_dynarec_opcodes_db_a32 = dynarec_ops_sf_fpu_287_db_a32; + x86_dynarec_opcodes_dc_a16 = dynarec_ops_sf_fpu_287_dc_a16; + x86_dynarec_opcodes_dc_a32 = dynarec_ops_sf_fpu_287_dc_a32; + x86_dynarec_opcodes_dd_a16 = dynarec_ops_sf_fpu_287_dd_a16; + x86_dynarec_opcodes_dd_a32 = dynarec_ops_sf_fpu_287_dd_a32; + x86_dynarec_opcodes_de_a16 = dynarec_ops_sf_fpu_287_de_a16; + x86_dynarec_opcodes_de_a32 = dynarec_ops_sf_fpu_287_de_a32; + x86_dynarec_opcodes_df_a16 = dynarec_ops_sf_fpu_287_df_a16; + x86_dynarec_opcodes_df_a32 = dynarec_ops_sf_fpu_287_df_a32; + } else { + x86_dynarec_opcodes_d9_a16 = dynarec_ops_fpu_287_d9_a16; + x86_dynarec_opcodes_d9_a32 = dynarec_ops_fpu_287_d9_a32; + x86_dynarec_opcodes_da_a16 = dynarec_ops_fpu_287_da_a16; + x86_dynarec_opcodes_da_a32 = dynarec_ops_fpu_287_da_a32; + x86_dynarec_opcodes_db_a16 = dynarec_ops_fpu_287_db_a16; + x86_dynarec_opcodes_db_a32 = dynarec_ops_fpu_287_db_a32; + x86_dynarec_opcodes_dc_a16 = dynarec_ops_fpu_287_dc_a16; + x86_dynarec_opcodes_dc_a32 = dynarec_ops_fpu_287_dc_a32; + x86_dynarec_opcodes_dd_a16 = dynarec_ops_fpu_287_dd_a16; + x86_dynarec_opcodes_dd_a32 = dynarec_ops_fpu_287_dd_a32; + x86_dynarec_opcodes_de_a16 = dynarec_ops_fpu_287_de_a16; + x86_dynarec_opcodes_de_a32 = dynarec_ops_fpu_287_de_a32; + x86_dynarec_opcodes_df_a16 = dynarec_ops_fpu_287_df_a16; + x86_dynarec_opcodes_df_a32 = dynarec_ops_fpu_287_df_a32; + } #endif - x86_opcodes_d9_a16 = ops_fpu_287_d9_a16; - x86_opcodes_d9_a32 = ops_fpu_287_d9_a32; - x86_opcodes_da_a16 = ops_fpu_287_da_a16; - x86_opcodes_da_a32 = ops_fpu_287_da_a32; - x86_opcodes_db_a16 = ops_fpu_287_db_a16; - x86_opcodes_db_a32 = ops_fpu_287_db_a32; - x86_opcodes_dc_a16 = ops_fpu_287_dc_a16; - x86_opcodes_dc_a32 = ops_fpu_287_dc_a32; - x86_opcodes_dd_a16 = ops_fpu_287_dd_a16; - x86_opcodes_dd_a32 = ops_fpu_287_dd_a32; - x86_opcodes_de_a16 = ops_fpu_287_de_a16; - x86_opcodes_de_a32 = ops_fpu_287_de_a32; - x86_opcodes_df_a16 = ops_fpu_287_df_a16; - x86_opcodes_df_a32 = ops_fpu_287_df_a32; - } + if (fpu_softfloat) { + x86_opcodes_d9_a16 = ops_sf_fpu_287_d9_a16; + x86_opcodes_d9_a32 = ops_sf_fpu_287_d9_a32; + x86_opcodes_da_a16 = ops_sf_fpu_287_da_a16; + x86_opcodes_da_a32 = ops_sf_fpu_287_da_a32; + x86_opcodes_db_a16 = ops_sf_fpu_287_db_a16; + x86_opcodes_db_a32 = ops_sf_fpu_287_db_a32; + x86_opcodes_dc_a16 = ops_sf_fpu_287_dc_a16; + x86_opcodes_dc_a32 = ops_sf_fpu_287_dc_a32; + x86_opcodes_dd_a16 = ops_sf_fpu_287_dd_a16; + x86_opcodes_dd_a32 = ops_sf_fpu_287_dd_a32; + x86_opcodes_de_a16 = ops_sf_fpu_287_de_a16; + x86_opcodes_de_a32 = ops_sf_fpu_287_de_a32; + x86_opcodes_df_a16 = ops_sf_fpu_287_df_a16; + x86_opcodes_df_a32 = ops_sf_fpu_287_df_a32; - timing_rr = 2; /* register dest - register src */ - timing_rm = 6; /* register dest - memory src */ - timing_mr = 7; /* memory dest - register src */ - timing_mm = 6; /* memory dest - memory src */ - if (cpu_s->cpu_type >= CPU_386DX) { - timing_rml = 6; /* register dest - memory src long */ - timing_mrl = 7; /* memory dest - register src long */ - timing_mml = 6; /* memory dest - memory src */ - } else { - timing_rml = 8; /* register dest - memory src long */ - timing_mrl = 11; /* memory dest - register src long */ - timing_mml = 10; /* memory dest - memory src */ - } - timing_bt = 4; /* branch taken */ - timing_bnt = 3; /* branch not taken */ + x86_2386_opcodes_d9_a16 = ops_2386_sf_fpu_287_d9_a16; + x86_2386_opcodes_d9_a32 = ops_2386_sf_fpu_287_d9_a32; + x86_2386_opcodes_da_a16 = ops_2386_sf_fpu_287_da_a16; + x86_2386_opcodes_da_a32 = ops_2386_sf_fpu_287_da_a32; + x86_2386_opcodes_db_a16 = ops_2386_sf_fpu_287_db_a16; + x86_2386_opcodes_db_a32 = ops_2386_sf_fpu_287_db_a32; + x86_2386_opcodes_dc_a16 = ops_2386_sf_fpu_287_dc_a16; + x86_2386_opcodes_dc_a32 = ops_2386_sf_fpu_287_dc_a32; + x86_2386_opcodes_dd_a16 = ops_2386_sf_fpu_287_dd_a16; + x86_2386_opcodes_dd_a32 = ops_2386_sf_fpu_287_dd_a32; + x86_2386_opcodes_de_a16 = ops_2386_sf_fpu_287_de_a16; + x86_2386_opcodes_de_a32 = ops_2386_sf_fpu_287_de_a32; + x86_2386_opcodes_df_a16 = ops_2386_sf_fpu_287_df_a16; + x86_2386_opcodes_df_a32 = ops_2386_sf_fpu_287_df_a32; + } else { + x86_opcodes_d9_a16 = ops_fpu_287_d9_a16; + x86_opcodes_d9_a32 = ops_fpu_287_d9_a32; + x86_opcodes_da_a16 = ops_fpu_287_da_a16; + x86_opcodes_da_a32 = ops_fpu_287_da_a32; + x86_opcodes_db_a16 = ops_fpu_287_db_a16; + x86_opcodes_db_a32 = ops_fpu_287_db_a32; + x86_opcodes_dc_a16 = ops_fpu_287_dc_a16; + x86_opcodes_dc_a32 = ops_fpu_287_dc_a32; + x86_opcodes_dd_a16 = ops_fpu_287_dd_a16; + x86_opcodes_dd_a32 = ops_fpu_287_dd_a32; + x86_opcodes_de_a16 = ops_fpu_287_de_a16; + x86_opcodes_de_a32 = ops_fpu_287_de_a32; + x86_opcodes_df_a16 = ops_fpu_287_df_a16; + x86_opcodes_df_a32 = ops_fpu_287_df_a32; - timing_int = 0; - timing_int_rm = 37; - timing_int_v86 = 59; - timing_int_pm = 99; - timing_int_pm_outer = 119; - timing_iret_rm = 22; - timing_iret_v86 = 60; - timing_iret_pm = 38; - timing_iret_pm_outer = 82; - timing_call_rm = 17; - timing_call_pm = 34; - timing_call_pm_gate = 52; - timing_call_pm_gate_inner = 86; - timing_retf_rm = 18; - timing_retf_pm = 32; - timing_retf_pm_outer = 68; - timing_jmp_rm = 12; - timing_jmp_pm = 27; - timing_jmp_pm_gate = 45; - break; + x86_2386_opcodes_d9_a16 = ops_2386_fpu_287_d9_a16; + x86_2386_opcodes_d9_a32 = ops_2386_fpu_287_d9_a32; + x86_2386_opcodes_da_a16 = ops_2386_fpu_287_da_a16; + x86_2386_opcodes_da_a32 = ops_2386_fpu_287_da_a32; + x86_2386_opcodes_db_a16 = ops_2386_fpu_287_db_a16; + x86_2386_opcodes_db_a32 = ops_2386_fpu_287_db_a32; + x86_2386_opcodes_dc_a16 = ops_2386_fpu_287_dc_a16; + x86_2386_opcodes_dc_a32 = ops_2386_fpu_287_dc_a32; + x86_2386_opcodes_dd_a16 = ops_2386_fpu_287_dd_a16; + x86_2386_opcodes_dd_a32 = ops_2386_fpu_287_dd_a32; + x86_2386_opcodes_de_a16 = ops_2386_fpu_287_de_a16; + x86_2386_opcodes_de_a32 = ops_2386_fpu_287_de_a32; + x86_2386_opcodes_df_a16 = ops_2386_fpu_287_df_a16; + x86_2386_opcodes_df_a32 = ops_2386_fpu_287_df_a32; + } + } - case CPU_486SLC: + timing_rr = 2; /* register dest - register src */ + timing_rm = 7; /* register dest - memory src */ + timing_mr = 7; /* memory dest - register src */ + timing_mm = 7; /* memory dest - memory src */ + timing_rml = 9; /* register dest - memory src long */ + timing_mrl = 11; /* memory dest - register src long */ + timing_mml = 11; /* memory dest - memory src */ + timing_bt = 4; /* branch taken */ + timing_bnt = 3; /* branch not taken */ + + timing_int = 0; + timing_int_rm = 23; + timing_int_v86 = 0; + timing_int_pm = 40; + timing_int_pm_outer = 78; + timing_iret_rm = 17; + timing_iret_v86 = 0; + timing_iret_pm = 31; + timing_iret_pm_outer = 55; + timing_call_rm = 13; + timing_call_pm = 26; + timing_call_pm_gate = 52; + timing_call_pm_gate_inner = 82; + timing_retf_rm = 15; + timing_retf_pm = 25; + timing_retf_pm_outer = 55; + timing_jmp_rm = 11; + timing_jmp_pm = 23; + timing_jmp_pm_gate = 38; + break; + + case CPU_IBM486SLC: + case CPU_IBM386SLC: + case CPU_IBM486BL: #ifdef USE_DYNAREC - x86_setopcodes(ops_386, ops_486_0f, dynarec_ops_386, dynarec_ops_486_0f); + x86_setopcodes(ops_386, ops_ibm486_0f, dynarec_ops_386, dynarec_ops_ibm486_0f); #else - x86_setopcodes(ops_386, ops_486_0f); + x86_setopcodes(ops_386, ops_ibm486_0f); #endif - - timing_rr = 1; /* register dest - register src */ - timing_rm = 3; /* register dest - memory src */ - timing_mr = 5; /* memory dest - register src */ - timing_mm = 3; - timing_rml = 5; /* register dest - memory src long */ - timing_mrl = 7; /* memory dest - register src long */ - timing_mml = 7; - timing_bt = 5; /* branch taken */ - timing_bnt = 1; /* branch not taken */ - - timing_int = 4; /* unknown */ - timing_int_rm = 14; - timing_int_v86 = 82; - timing_int_pm = 49; - timing_int_pm_outer = 77; - timing_iret_rm = 14; - timing_iret_v86 = 66; - timing_iret_pm = 31; - timing_iret_pm_outer = 66; - timing_call_rm = 12; - timing_call_pm = 30; - timing_call_pm_gate = 41; - timing_call_pm_gate_inner = 83; - timing_retf_rm = 13; - timing_retf_pm = 26; - timing_retf_pm_outer = 61; - timing_jmp_rm = 9; - timing_jmp_pm = 26; - timing_jmp_pm_gate = 37; - timing_misaligned = 3; - break; - - case CPU_486DLC: + x86_setopcodes_2386(ops_2386_386, ops_2386_ibm486_0f); + cpu_features = CPU_FEATURE_MSR; + fallthrough; + case CPU_386SX: + case CPU_386DX: + /* In case we get Deskpro 386 emulation */ + if (fpu_type == FPU_287) { #ifdef USE_DYNAREC - x86_setopcodes(ops_386, ops_486_0f, dynarec_ops_386, dynarec_ops_486_0f); + if (fpu_softfloat) { + x86_dynarec_opcodes_d9_a16 = dynarec_ops_sf_fpu_287_d9_a16; + x86_dynarec_opcodes_d9_a32 = dynarec_ops_sf_fpu_287_d9_a32; + x86_dynarec_opcodes_da_a16 = dynarec_ops_sf_fpu_287_da_a16; + x86_dynarec_opcodes_da_a32 = dynarec_ops_sf_fpu_287_da_a32; + x86_dynarec_opcodes_db_a16 = dynarec_ops_sf_fpu_287_db_a16; + x86_dynarec_opcodes_db_a32 = dynarec_ops_sf_fpu_287_db_a32; + x86_dynarec_opcodes_dc_a16 = dynarec_ops_sf_fpu_287_dc_a16; + x86_dynarec_opcodes_dc_a32 = dynarec_ops_sf_fpu_287_dc_a32; + x86_dynarec_opcodes_dd_a16 = dynarec_ops_sf_fpu_287_dd_a16; + x86_dynarec_opcodes_dd_a32 = dynarec_ops_sf_fpu_287_dd_a32; + x86_dynarec_opcodes_de_a16 = dynarec_ops_sf_fpu_287_de_a16; + x86_dynarec_opcodes_de_a32 = dynarec_ops_sf_fpu_287_de_a32; + x86_dynarec_opcodes_df_a16 = dynarec_ops_sf_fpu_287_df_a16; + x86_dynarec_opcodes_df_a32 = dynarec_ops_sf_fpu_287_df_a32; + } else { + x86_dynarec_opcodes_d9_a16 = dynarec_ops_fpu_287_d9_a16; + x86_dynarec_opcodes_d9_a32 = dynarec_ops_fpu_287_d9_a32; + x86_dynarec_opcodes_da_a16 = dynarec_ops_fpu_287_da_a16; + x86_dynarec_opcodes_da_a32 = dynarec_ops_fpu_287_da_a32; + x86_dynarec_opcodes_db_a16 = dynarec_ops_fpu_287_db_a16; + x86_dynarec_opcodes_db_a32 = dynarec_ops_fpu_287_db_a32; + x86_dynarec_opcodes_dc_a16 = dynarec_ops_fpu_287_dc_a16; + x86_dynarec_opcodes_dc_a32 = dynarec_ops_fpu_287_dc_a32; + x86_dynarec_opcodes_dd_a16 = dynarec_ops_fpu_287_dd_a16; + x86_dynarec_opcodes_dd_a32 = dynarec_ops_fpu_287_dd_a32; + x86_dynarec_opcodes_de_a16 = dynarec_ops_fpu_287_de_a16; + x86_dynarec_opcodes_de_a32 = dynarec_ops_fpu_287_de_a32; + x86_dynarec_opcodes_df_a16 = dynarec_ops_fpu_287_df_a16; + x86_dynarec_opcodes_df_a32 = dynarec_ops_fpu_287_df_a32; + } +#endif + if (fpu_softfloat) { + x86_opcodes_d9_a16 = ops_sf_fpu_287_d9_a16; + x86_opcodes_d9_a32 = ops_sf_fpu_287_d9_a32; + x86_opcodes_da_a16 = ops_sf_fpu_287_da_a16; + x86_opcodes_da_a32 = ops_sf_fpu_287_da_a32; + x86_opcodes_db_a16 = ops_sf_fpu_287_db_a16; + x86_opcodes_db_a32 = ops_sf_fpu_287_db_a32; + x86_opcodes_dc_a16 = ops_sf_fpu_287_dc_a16; + x86_opcodes_dc_a32 = ops_sf_fpu_287_dc_a32; + x86_opcodes_dd_a16 = ops_sf_fpu_287_dd_a16; + x86_opcodes_dd_a32 = ops_sf_fpu_287_dd_a32; + x86_opcodes_de_a16 = ops_sf_fpu_287_de_a16; + x86_opcodes_de_a32 = ops_sf_fpu_287_de_a32; + x86_opcodes_df_a16 = ops_sf_fpu_287_df_a16; + x86_opcodes_df_a32 = ops_sf_fpu_287_df_a32; + + x86_2386_opcodes_d9_a16 = ops_2386_sf_fpu_287_d9_a16; + x86_2386_opcodes_d9_a32 = ops_2386_sf_fpu_287_d9_a32; + x86_2386_opcodes_da_a16 = ops_2386_sf_fpu_287_da_a16; + x86_2386_opcodes_da_a32 = ops_2386_sf_fpu_287_da_a32; + x86_2386_opcodes_db_a16 = ops_2386_sf_fpu_287_db_a16; + x86_2386_opcodes_db_a32 = ops_2386_sf_fpu_287_db_a32; + x86_2386_opcodes_dc_a16 = ops_2386_sf_fpu_287_dc_a16; + x86_2386_opcodes_dc_a32 = ops_2386_sf_fpu_287_dc_a32; + x86_2386_opcodes_dd_a16 = ops_2386_sf_fpu_287_dd_a16; + x86_2386_opcodes_dd_a32 = ops_2386_sf_fpu_287_dd_a32; + x86_2386_opcodes_de_a16 = ops_2386_sf_fpu_287_de_a16; + x86_2386_opcodes_de_a32 = ops_2386_sf_fpu_287_de_a32; + x86_2386_opcodes_df_a16 = ops_2386_sf_fpu_287_df_a16; + x86_2386_opcodes_df_a32 = ops_2386_sf_fpu_287_df_a32; + } else { + x86_opcodes_d9_a16 = ops_fpu_287_d9_a16; + x86_opcodes_d9_a32 = ops_fpu_287_d9_a32; + x86_opcodes_da_a16 = ops_fpu_287_da_a16; + x86_opcodes_da_a32 = ops_fpu_287_da_a32; + x86_opcodes_db_a16 = ops_fpu_287_db_a16; + x86_opcodes_db_a32 = ops_fpu_287_db_a32; + x86_opcodes_dc_a16 = ops_fpu_287_dc_a16; + x86_opcodes_dc_a32 = ops_fpu_287_dc_a32; + x86_opcodes_dd_a16 = ops_fpu_287_dd_a16; + x86_opcodes_dd_a32 = ops_fpu_287_dd_a32; + x86_opcodes_de_a16 = ops_fpu_287_de_a16; + x86_opcodes_de_a32 = ops_fpu_287_de_a32; + x86_opcodes_df_a16 = ops_fpu_287_df_a16; + x86_opcodes_df_a32 = ops_fpu_287_df_a32; + + x86_2386_opcodes_d9_a16 = ops_2386_fpu_287_d9_a16; + x86_2386_opcodes_d9_a32 = ops_2386_fpu_287_d9_a32; + x86_2386_opcodes_da_a16 = ops_2386_fpu_287_da_a16; + x86_2386_opcodes_da_a32 = ops_2386_fpu_287_da_a32; + x86_2386_opcodes_db_a16 = ops_2386_fpu_287_db_a16; + x86_2386_opcodes_db_a32 = ops_2386_fpu_287_db_a32; + x86_2386_opcodes_dc_a16 = ops_2386_fpu_287_dc_a16; + x86_2386_opcodes_dc_a32 = ops_2386_fpu_287_dc_a32; + x86_2386_opcodes_dd_a16 = ops_2386_fpu_287_dd_a16; + x86_2386_opcodes_dd_a32 = ops_2386_fpu_287_dd_a32; + x86_2386_opcodes_de_a16 = ops_2386_fpu_287_de_a16; + x86_2386_opcodes_de_a32 = ops_2386_fpu_287_de_a32; + x86_2386_opcodes_df_a16 = ops_2386_fpu_287_df_a16; + x86_2386_opcodes_df_a32 = ops_2386_fpu_287_df_a32; + } + } + + timing_rr = 2; /* register dest - register src */ + timing_rm = 6; /* register dest - memory src */ + timing_mr = 7; /* memory dest - register src */ + timing_mm = 6; /* memory dest - memory src */ + if (cpu_s->cpu_type >= CPU_386DX) { + timing_rml = 6; /* register dest - memory src long */ + timing_mrl = 7; /* memory dest - register src long */ + timing_mml = 6; /* memory dest - memory src */ + } else { + timing_rml = 8; /* register dest - memory src long */ + timing_mrl = 11; /* memory dest - register src long */ + timing_mml = 10; /* memory dest - memory src */ + } + timing_bt = 4; /* branch taken */ + timing_bnt = 3; /* branch not taken */ + + timing_int = 0; + timing_int_rm = 37; + timing_int_v86 = 59; + timing_int_pm = 99; + timing_int_pm_outer = 119; + timing_iret_rm = 22; + timing_iret_v86 = 60; + timing_iret_pm = 38; + timing_iret_pm_outer = 82; + timing_call_rm = 17; + timing_call_pm = 34; + timing_call_pm_gate = 52; + timing_call_pm_gate_inner = 86; + timing_retf_rm = 18; + timing_retf_pm = 32; + timing_retf_pm_outer = 68; + timing_jmp_rm = 12; + timing_jmp_pm = 27; + timing_jmp_pm_gate = 45; + break; + + case CPU_486SLC: +#ifdef USE_DYNAREC + x86_setopcodes(ops_386, ops_486_0f, dynarec_ops_386, dynarec_ops_486_0f); #else - x86_setopcodes(ops_386, ops_486_0f); + x86_setopcodes(ops_386, ops_486_0f); #endif + x86_setopcodes_2386(ops_2386_386, ops_2386_486_0f); - timing_rr = 1; /* register dest - register src */ - timing_rm = 3; /* register dest - memory src */ - timing_mr = 3; /* memory dest - register src */ - timing_mm = 3; - timing_rml = 3; /* register dest - memory src long */ - timing_mrl = 3; /* memory dest - register src long */ - timing_mml = 3; - timing_bt = 5; /* branch taken */ - timing_bnt = 1; /* branch not taken */ + timing_rr = 1; /* register dest - register src */ + timing_rm = 3; /* register dest - memory src */ + timing_mr = 5; /* memory dest - register src */ + timing_mm = 3; + timing_rml = 5; /* register dest - memory src long */ + timing_mrl = 7; /* memory dest - register src long */ + timing_mml = 7; + timing_bt = 5; /* branch taken */ + timing_bnt = 1; /* branch not taken */ - timing_int = 4; /* unknown */ - timing_int_rm = 14; - timing_int_v86 = 82; - timing_int_pm = 49; - timing_int_pm_outer = 77; - timing_iret_rm = 14; - timing_iret_v86 = 66; - timing_iret_pm = 31; - timing_iret_pm_outer = 66; - timing_call_rm = 12; - timing_call_pm = 30; - timing_call_pm_gate = 41; - timing_call_pm_gate_inner = 83; - timing_retf_rm = 13; - timing_retf_pm = 26; - timing_retf_pm_outer = 61; - timing_jmp_rm = 9; - timing_jmp_pm = 26; - timing_jmp_pm_gate = 37; + timing_int = 4; /* unknown */ + timing_int_rm = 14; + timing_int_v86 = 82; + timing_int_pm = 49; + timing_int_pm_outer = 77; + timing_iret_rm = 14; + timing_iret_v86 = 66; + timing_iret_pm = 31; + timing_iret_pm_outer = 66; + timing_call_rm = 12; + timing_call_pm = 30; + timing_call_pm_gate = 41; + timing_call_pm_gate_inner = 83; + timing_retf_rm = 13; + timing_retf_pm = 26; + timing_retf_pm_outer = 61; + timing_jmp_rm = 9; + timing_jmp_pm = 26; + timing_jmp_pm_gate = 37; + timing_misaligned = 3; + break; - timing_misaligned = 3; - break; - - case CPU_i486SX_SLENH: - case CPU_i486DX_SLENH: - cpu_features = CPU_FEATURE_CR4 | CPU_FEATURE_VME; - cpu_CR4_mask = CR4_VME | CR4_PVI | CR4_VME; - /* FALLTHROUGH */ - case CPU_RAPIDCAD: - case CPU_i486SX: - case CPU_i486DX: - case CPU_Am486SX: - case CPU_Am486DX: - case CPU_Am486DXL: - case CPU_ENH_Am486DX: - /*AMD timing identical to Intel*/ + case CPU_486DLC: #ifdef USE_DYNAREC - x86_setopcodes(ops_386, ops_486_0f, dynarec_ops_386, dynarec_ops_486_0f); + x86_setopcodes(ops_386, ops_486_0f, dynarec_ops_386, dynarec_ops_486_0f); #else - x86_setopcodes(ops_386, ops_486_0f); + x86_setopcodes(ops_386, ops_486_0f); #endif + x86_setopcodes_2386(ops_2386_386, ops_2386_486_0f); - timing_rr = 1; /* register dest - register src */ - timing_rm = 2; /* register dest - memory src */ - timing_mr = 3; /* memory dest - register src */ - timing_mm = 3; - timing_rml = 2; /* register dest - memory src long */ - timing_mrl = 3; /* memory dest - register src long */ - timing_mml = 3; - timing_bt = 2; /* branch taken */ - timing_bnt = 1; /* branch not taken */ + timing_rr = 1; /* register dest - register src */ + timing_rm = 3; /* register dest - memory src */ + timing_mr = 3; /* memory dest - register src */ + timing_mm = 3; + timing_rml = 3; /* register dest - memory src long */ + timing_mrl = 3; /* memory dest - register src long */ + timing_mml = 3; + timing_bt = 5; /* branch taken */ + timing_bnt = 1; /* branch not taken */ - timing_int = 4; - timing_int_rm = 26; - timing_int_v86 = 82; - timing_int_pm = 44; - timing_int_pm_outer = 71; - timing_iret_rm = 15; - timing_iret_v86 = 36; /* unknown */ - timing_iret_pm = 20; - timing_iret_pm_outer = 36; - timing_call_rm = 18; - timing_call_pm = 20; - timing_call_pm_gate = 35; - timing_call_pm_gate_inner = 69; - timing_retf_rm = 13; - timing_retf_pm = 17; - timing_retf_pm_outer = 35; - timing_jmp_rm = 17; - timing_jmp_pm = 19; - timing_jmp_pm_gate = 32; + timing_int = 4; /* unknown */ + timing_int_rm = 14; + timing_int_v86 = 82; + timing_int_pm = 49; + timing_int_pm_outer = 77; + timing_iret_rm = 14; + timing_iret_v86 = 66; + timing_iret_pm = 31; + timing_iret_pm_outer = 66; + timing_call_rm = 12; + timing_call_pm = 30; + timing_call_pm_gate = 41; + timing_call_pm_gate_inner = 83; + timing_retf_rm = 13; + timing_retf_pm = 26; + timing_retf_pm_outer = 61; + timing_jmp_rm = 9; + timing_jmp_pm = 26; + timing_jmp_pm_gate = 37; - timing_misaligned = 3; - break; + timing_misaligned = 3; + break; - case CPU_Cx486S: - case CPU_Cx486DX: - case CPU_STPC: + case CPU_i486SX_SLENH: + case CPU_i486DX_SLENH: + cpu_features = CPU_FEATURE_CR4 | CPU_FEATURE_VME; + cpu_CR4_mask = CR4_VME | CR4_PVI | CR4_VME; + fallthrough; + case CPU_RAPIDCAD: + case CPU_i486SX: + case CPU_i486DX: + case CPU_Am486SX: + case CPU_Am486DX: + case CPU_Am486DXL: + case CPU_ENH_Am486DX: + /*AMD timing identical to Intel*/ #ifdef USE_DYNAREC - if (cpu_s->cpu_type == CPU_STPC) - x86_setopcodes(ops_386, ops_stpc_0f, dynarec_ops_386, dynarec_ops_stpc_0f); - else - x86_setopcodes(ops_386, ops_c486_0f, dynarec_ops_386, dynarec_ops_c486_0f); + x86_setopcodes(ops_386, ops_486_0f, dynarec_ops_386, dynarec_ops_486_0f); #else - if (cpu_s->cpu_type == CPU_STPC) - x86_setopcodes(ops_386, ops_stpc_0f); - else - x86_setopcodes(ops_386, ops_c486_0f); + x86_setopcodes(ops_386, ops_486_0f); #endif + x86_setopcodes_2386(ops_2386_386, ops_2386_486_0f); - timing_rr = 1; /* register dest - register src */ - timing_rm = 3; /* register dest - memory src */ - timing_mr = 3; /* memory dest - register src */ - timing_mm = 3; - timing_rml = 3; /* register dest - memory src long */ - timing_mrl = 3; /* memory dest - register src long */ - timing_mml = 3; - timing_bt = 3; /* branch taken */ - timing_bnt = 1; /* branch not taken */ + timing_rr = 1; /* register dest - register src */ + timing_rm = 2; /* register dest - memory src */ + timing_mr = 3; /* memory dest - register src */ + timing_mm = 3; + timing_rml = 2; /* register dest - memory src long */ + timing_mrl = 3; /* memory dest - register src long */ + timing_mml = 3; + timing_bt = 2; /* branch taken */ + timing_bnt = 1; /* branch not taken */ - timing_int = 4; - timing_int_rm = 14; - timing_int_v86 = 82; - timing_int_pm = 49; - timing_int_pm_outer = 77; - timing_iret_rm = 14; - timing_iret_v86 = 66; /* unknown */ - timing_iret_pm = 31; - timing_iret_pm_outer = 66; - timing_call_rm = 12; - timing_call_pm = 30; - timing_call_pm_gate = 41; - timing_call_pm_gate_inner = 83; - timing_retf_rm = 13; - timing_retf_pm = 26; - timing_retf_pm_outer = 61; - timing_jmp_rm = 9; - timing_jmp_pm = 26; - timing_jmp_pm_gate = 37; + timing_int = 4; + timing_int_rm = 26; + timing_int_v86 = 82; + timing_int_pm = 44; + timing_int_pm_outer = 71; + timing_iret_rm = 15; + timing_iret_v86 = 36; /* unknown */ + timing_iret_pm = 20; + timing_iret_pm_outer = 36; + timing_call_rm = 18; + timing_call_pm = 20; + timing_call_pm_gate = 35; + timing_call_pm_gate_inner = 69; + timing_retf_rm = 13; + timing_retf_pm = 17; + timing_retf_pm_outer = 35; + timing_jmp_rm = 17; + timing_jmp_pm = 19; + timing_jmp_pm_gate = 32; - timing_misaligned = 3; + timing_misaligned = 3; + break; - if (cpu_s->cpu_type == CPU_STPC) - cpu_features = CPU_FEATURE_RDTSC; - break; - - case CPU_Cx5x86: + case CPU_Cx486S: + case CPU_Cx486DX: + case CPU_STPC: #ifdef USE_DYNAREC - x86_setopcodes(ops_386, ops_c486_0f, dynarec_ops_386, dynarec_ops_c486_0f); + if (cpu_s->cpu_type == CPU_STPC) + x86_setopcodes(ops_386, ops_stpc_0f, dynarec_ops_386, dynarec_ops_stpc_0f); + else + x86_setopcodes(ops_386, ops_c486_0f, dynarec_ops_386, dynarec_ops_c486_0f); #else - x86_setopcodes(ops_386, ops_c486_0f); + if (cpu_s->cpu_type == CPU_STPC) + x86_setopcodes(ops_386, ops_stpc_0f); + else + x86_setopcodes(ops_386, ops_c486_0f); #endif - timing_rr = 1; /* register dest - register src */ - timing_rm = 1; /* register dest - memory src */ - timing_mr = 2; /* memory dest - register src */ - timing_mm = 2; - timing_rml = 1; /* register dest - memory src long */ - timing_mrl = 2; /* memory dest - register src long */ - timing_mml = 2; - timing_bt = 4; /* branch taken */ - timing_bnt = 1; /* branch not taken */ + timing_rr = 1; /* register dest - register src */ + timing_rm = 3; /* register dest - memory src */ + timing_mr = 3; /* memory dest - register src */ + timing_mm = 3; + timing_rml = 3; /* register dest - memory src long */ + timing_mrl = 3; /* memory dest - register src long */ + timing_mml = 3; + timing_bt = 3; /* branch taken */ + timing_bnt = 1; /* branch not taken */ - timing_int = 0; - timing_int_rm = 9; - timing_int_v86 = 82; /* unknown */ - timing_int_pm = 21; - timing_int_pm_outer = 32; - timing_iret_rm = 7; - timing_iret_v86 = 26; /* unknown */ - timing_iret_pm = 10; - timing_iret_pm_outer = 26; - timing_call_rm = 4; - timing_call_pm = 15; - timing_call_pm_gate = 26; - timing_call_pm_gate_inner = 35; - timing_retf_rm = 4; - timing_retf_pm = 7; - timing_retf_pm_outer = 23; - timing_jmp_rm = 5; - timing_jmp_pm = 7; - timing_jmp_pm_gate = 17; + timing_int = 4; + timing_int_rm = 14; + timing_int_v86 = 82; + timing_int_pm = 49; + timing_int_pm_outer = 77; + timing_iret_rm = 14; + timing_iret_v86 = 66; /* unknown */ + timing_iret_pm = 31; + timing_iret_pm_outer = 66; + timing_call_rm = 12; + timing_call_pm = 30; + timing_call_pm_gate = 41; + timing_call_pm_gate_inner = 83; + timing_retf_rm = 13; + timing_retf_pm = 26; + timing_retf_pm_outer = 61; + timing_jmp_rm = 9; + timing_jmp_pm = 26; + timing_jmp_pm_gate = 37; - timing_misaligned = 2; + timing_misaligned = 3; - cpu_cyrix_alignment = 1; - break; + if (cpu_s->cpu_type == CPU_STPC) + cpu_features = CPU_FEATURE_RDTSC; + break; - case CPU_WINCHIP: - case CPU_WINCHIP2: + case CPU_Cx5x86: #ifdef USE_DYNAREC - if (cpu_s->cpu_type == CPU_WINCHIP2) - x86_setopcodes(ops_386, ops_winchip2_0f, dynarec_ops_386, dynarec_ops_winchip2_0f); - else - x86_setopcodes(ops_386, ops_winchip_0f, dynarec_ops_386, dynarec_ops_winchip_0f); + x86_setopcodes(ops_386, ops_c486_0f, dynarec_ops_386, dynarec_ops_c486_0f); #else - if (cpu_s->cpu_type == CPU_WINCHIP2) - x86_setopcodes(ops_386, ops_winchip2_0f); - else - x86_setopcodes(ops_386, ops_winchip_0f); + x86_setopcodes(ops_386, ops_c486_0f); #endif - timing_rr = 1; /* register dest - register src */ - timing_rm = 2; /* register dest - memory src */ - timing_mr = 2; /* memory dest - register src */ - timing_mm = 3; - timing_rml = 2; /* register dest - memory src long */ - timing_mrl = 2; /* memory dest - register src long */ - timing_mml = 3; - timing_bt = 2; /* branch taken */ - timing_bnt = 1; /* branch not taken */ + timing_rr = 1; /* register dest - register src */ + timing_rm = 1; /* register dest - memory src */ + timing_mr = 2; /* memory dest - register src */ + timing_mm = 2; + timing_rml = 1; /* register dest - memory src long */ + timing_mrl = 2; /* memory dest - register src long */ + timing_mml = 2; + timing_bt = 4; /* branch taken */ + timing_bnt = 1; /* branch not taken */ - /*unknown*/ - timing_int_rm = 26; - timing_int_v86 = 82; - timing_int_pm = 44; - timing_int_pm_outer = 71; - timing_iret_rm = 7; - timing_iret_v86 = 26; - timing_iret_pm = 10; - timing_iret_pm_outer = 26; - timing_call_rm = 4; - timing_call_pm = 15; - timing_call_pm_gate = 26; - timing_call_pm_gate_inner = 35; - timing_retf_rm = 4; - timing_retf_pm = 7; - timing_retf_pm_outer = 23; - timing_jmp_rm = 5; - timing_jmp_pm = 7; - timing_jmp_pm_gate = 17; + timing_int = 0; + timing_int_rm = 9; + timing_int_v86 = 82; /* unknown */ + timing_int_pm = 21; + timing_int_pm_outer = 32; + timing_iret_rm = 7; + timing_iret_v86 = 26; /* unknown */ + timing_iret_pm = 10; + timing_iret_pm_outer = 26; + timing_call_rm = 4; + timing_call_pm = 15; + timing_call_pm_gate = 26; + timing_call_pm_gate_inner = 35; + timing_retf_rm = 4; + timing_retf_pm = 7; + timing_retf_pm_outer = 23; + timing_jmp_rm = 5; + timing_jmp_pm = 7; + timing_jmp_pm_gate = 17; - timing_misaligned = 2; + timing_misaligned = 2; - cpu_cyrix_alignment = 1; + cpu_cyrix_alignment = 1; + break; - cpu_features = CPU_FEATURE_RDTSC | CPU_FEATURE_MMX | CPU_FEATURE_MSR | CPU_FEATURE_CR4; - if (cpu_s->cpu_type == CPU_WINCHIP2) - cpu_features |= CPU_FEATURE_3DNOW; - msr.fcr = (1 << 8) | (1 << 9) | (1 << 12) | (1 << 16) | (1 << 19) | (1 << 21); - if (cpu_s->cpu_type == CPU_WINCHIP2) - msr.fcr |= (1 << 18) | (1 << 20); - cpu_CR4_mask = CR4_TSD | CR4_DE | CR4_MCE | CR4_PCE; - -#ifdef USE_DYNAREC - if (cpu_s->cpu_type == CPU_WINCHIP2) - codegen_timing_set(&codegen_timing_winchip2); - else - codegen_timing_set(&codegen_timing_winchip); -#endif - break; - - case CPU_P24T: - case CPU_PENTIUM: - case CPU_PENTIUMMMX: + case CPU_WINCHIP: + case CPU_WINCHIP2: #ifdef USE_DYNAREC - if (cpu_s->cpu_type == CPU_PENTIUMMMX) - x86_setopcodes(ops_386, ops_pentiummmx_0f, dynarec_ops_386, dynarec_ops_pentiummmx_0f); - else - x86_setopcodes(ops_386, ops_pentium_0f, dynarec_ops_386, dynarec_ops_pentium_0f); + if (cpu_s->cpu_type == CPU_WINCHIP2) + x86_setopcodes(ops_386, ops_winchip2_0f, dynarec_ops_386, dynarec_ops_winchip2_0f); + else + x86_setopcodes(ops_386, ops_winchip_0f, dynarec_ops_386, dynarec_ops_winchip_0f); #else - if (cpu_s->cpu_type == CPU_PENTIUMMMX) - x86_setopcodes(ops_386, ops_pentiummmx_0f); - else - x86_setopcodes(ops_386, ops_pentium_0f); + if (cpu_s->cpu_type == CPU_WINCHIP2) + x86_setopcodes(ops_386, ops_winchip2_0f); + else + x86_setopcodes(ops_386, ops_winchip_0f); #endif - timing_rr = 1; /* register dest - register src */ - timing_rm = 2; /* register dest - memory src */ - timing_mr = 3; /* memory dest - register src */ - timing_mm = 3; - timing_rml = 2; /* register dest - memory src long */ - timing_mrl = 3; /* memory dest - register src long */ - timing_mml = 3; - timing_bt = 0; /* branch taken */ - if (cpu_s->cpu_type == CPU_PENTIUMMMX) - timing_bnt = 1; /* branch not taken */ - else - timing_bnt = 2; /* branch not taken */ + timing_rr = 1; /* register dest - register src */ + timing_rm = 2; /* register dest - memory src */ + timing_mr = 2; /* memory dest - register src */ + timing_mm = 3; + timing_rml = 2; /* register dest - memory src long */ + timing_mrl = 2; /* memory dest - register src long */ + timing_mml = 3; + timing_bt = 2; /* branch taken */ + timing_bnt = 1; /* branch not taken */ - timing_int = 6; - timing_int_rm = 11; - timing_int_v86 = 54; - timing_int_pm = 25; - timing_int_pm_outer = 42; - timing_iret_rm = 7; - timing_iret_v86 = 27; /* unknown */ - timing_iret_pm = 10; - timing_iret_pm_outer = 27; - timing_call_rm = 4; - timing_call_pm = 4; - timing_call_pm_gate = 22; - timing_call_pm_gate_inner = 44; - timing_retf_rm = 4; - timing_retf_pm = 4; - timing_retf_pm_outer = 23; - timing_jmp_rm = 3; - timing_jmp_pm = 3; - timing_jmp_pm_gate = 18; + /*unknown*/ + timing_int_rm = 26; + timing_int_v86 = 82; + timing_int_pm = 44; + timing_int_pm_outer = 71; + timing_iret_rm = 7; + timing_iret_v86 = 26; + timing_iret_pm = 10; + timing_iret_pm_outer = 26; + timing_call_rm = 4; + timing_call_pm = 15; + timing_call_pm_gate = 26; + timing_call_pm_gate_inner = 35; + timing_retf_rm = 4; + timing_retf_pm = 7; + timing_retf_pm_outer = 23; + timing_jmp_rm = 5; + timing_jmp_pm = 7; + timing_jmp_pm_gate = 17; - timing_misaligned = 3; + timing_misaligned = 2; + + cpu_cyrix_alignment = 1; + + cpu_features = CPU_FEATURE_RDTSC | CPU_FEATURE_MMX | CPU_FEATURE_MSR | CPU_FEATURE_CR4; + if (cpu_s->cpu_type == CPU_WINCHIP2) + cpu_features |= CPU_FEATURE_3DNOW; + msr.fcr = (1 << 8) | (1 << 9) | (1 << 12) | (1 << 16) | (1 << 19) | (1 << 21); + if (cpu_s->cpu_type == CPU_WINCHIP2) + msr.fcr |= (1 << 18) | (1 << 20); + cpu_CR4_mask = CR4_TSD | CR4_DE | CR4_MCE | CR4_PCE; - cpu_features = CPU_FEATURE_RDTSC | CPU_FEATURE_MSR | CPU_FEATURE_CR4 | CPU_FEATURE_VME; - if (cpu_s->cpu_type == CPU_PENTIUMMMX) - cpu_features |= CPU_FEATURE_MMX; - msr.fcr = (1 << 8) | (1 << 9) | (1 << 12) | (1 << 16) | (1 << 19) | (1 << 21); - cpu_CR4_mask = CR4_VME | CR4_PVI | CR4_TSD | CR4_DE | CR4_PSE | CR4_MCE | CR4_PCE; #ifdef USE_DYNAREC - codegen_timing_set(&codegen_timing_pentium); + if (cpu_s->cpu_type == CPU_WINCHIP2) + codegen_timing_set(&codegen_timing_winchip2); + else + codegen_timing_set(&codegen_timing_winchip); #endif - break; + break; + + case CPU_P24T: + case CPU_PENTIUM: + case CPU_PENTIUMMMX: +#ifdef USE_DYNAREC + if (cpu_s->cpu_type == CPU_PENTIUMMMX) + x86_setopcodes(ops_386, ops_pentiummmx_0f, dynarec_ops_386, dynarec_ops_pentiummmx_0f); + else + x86_setopcodes(ops_386, ops_pentium_0f, dynarec_ops_386, dynarec_ops_pentium_0f); +#else + if (cpu_s->cpu_type == CPU_PENTIUMMMX) + x86_setopcodes(ops_386, ops_pentiummmx_0f); + else + x86_setopcodes(ops_386, ops_pentium_0f); +#endif + + timing_rr = 1; /* register dest - register src */ + timing_rm = 2; /* register dest - memory src */ + timing_mr = 3; /* memory dest - register src */ + timing_mm = 3; + timing_rml = 2; /* register dest - memory src long */ + timing_mrl = 3; /* memory dest - register src long */ + timing_mml = 3; + timing_bt = 0; /* branch taken */ + if (cpu_s->cpu_type == CPU_PENTIUMMMX) + timing_bnt = 1; /* branch not taken */ + else + timing_bnt = 2; /* branch not taken */ + + timing_int = 6; + timing_int_rm = 11; + timing_int_v86 = 54; + timing_int_pm = 25; + timing_int_pm_outer = 42; + timing_iret_rm = 7; + timing_iret_v86 = 27; /* unknown */ + timing_iret_pm = 10; + timing_iret_pm_outer = 27; + timing_call_rm = 4; + timing_call_pm = 4; + timing_call_pm_gate = 22; + timing_call_pm_gate_inner = 44; + timing_retf_rm = 4; + timing_retf_pm = 4; + timing_retf_pm_outer = 23; + timing_jmp_rm = 3; + timing_jmp_pm = 3; + timing_jmp_pm_gate = 18; + + timing_misaligned = 3; + + cpu_features = CPU_FEATURE_RDTSC | CPU_FEATURE_MSR | CPU_FEATURE_CR4 | CPU_FEATURE_VME; + if (cpu_s->cpu_type == CPU_PENTIUMMMX) + cpu_features |= CPU_FEATURE_MMX; + cpu_CR4_mask = CR4_VME | CR4_PVI | CR4_TSD | CR4_DE | CR4_PSE | CR4_MCE | CR4_PCE; +#ifdef USE_DYNAREC + codegen_timing_set(&codegen_timing_pentium); +#endif + break; #if defined(DEV_BRANCH) && defined(USE_CYRIX_6X86) - case CPU_Cx6x86: - case CPU_Cx6x86L: - case CPU_CxGX1: - case CPU_Cx6x86MX: - if (cpu_s->cpu_type == CPU_Cx6x86MX) { -#ifdef USE_DYNAREC - x86_dynarec_opcodes_da_a16 = dynarec_ops_fpu_686_da_a16; - x86_dynarec_opcodes_da_a32 = dynarec_ops_fpu_686_da_a32; - x86_dynarec_opcodes_db_a16 = dynarec_ops_fpu_686_db_a16; - x86_dynarec_opcodes_db_a32 = dynarec_ops_fpu_686_db_a32; - x86_dynarec_opcodes_df_a16 = dynarec_ops_fpu_686_df_a16; - x86_dynarec_opcodes_df_a32 = dynarec_ops_fpu_686_df_a32; -#endif - x86_opcodes_da_a16 = ops_fpu_686_da_a16; - x86_opcodes_da_a32 = ops_fpu_686_da_a32; - x86_opcodes_db_a16 = ops_fpu_686_db_a16; - x86_opcodes_db_a32 = ops_fpu_686_db_a32; - x86_opcodes_df_a16 = ops_fpu_686_df_a16; - x86_opcodes_df_a32 = ops_fpu_686_df_a32; - } + case CPU_Cx6x86: + case CPU_Cx6x86L: + case CPU_CxGX1: + case CPU_Cx6x86MX: + if (cpu_s->cpu_type == CPU_Cx6x86MX) { +# ifdef USE_DYNAREC + if (fpu_softfloat) { + x86_dynarec_opcodes_da_a16 = dynarec_ops_sf_fpu_686_da_a16; + x86_dynarec_opcodes_da_a32 = dynarec_ops_sf_fpu_686_da_a32; + x86_dynarec_opcodes_db_a16 = dynarec_ops_sf_fpu_686_db_a16; + x86_dynarec_opcodes_db_a32 = dynarec_ops_sf_fpu_686_db_a32; + x86_dynarec_opcodes_df_a16 = dynarec_ops_sf_fpu_686_df_a16; + x86_dynarec_opcodes_df_a32 = dynarec_ops_sf_fpu_686_df_a32; + } else { + x86_dynarec_opcodes_da_a16 = dynarec_ops_fpu_686_da_a16; + x86_dynarec_opcodes_da_a32 = dynarec_ops_fpu_686_da_a32; + x86_dynarec_opcodes_db_a16 = dynarec_ops_fpu_686_db_a16; + x86_dynarec_opcodes_db_a32 = dynarec_ops_fpu_686_db_a32; + x86_dynarec_opcodes_df_a16 = dynarec_ops_fpu_686_df_a16; + x86_dynarec_opcodes_df_a32 = dynarec_ops_fpu_686_df_a32; + } +# endif + if (fpu_softfloat) { + x86_opcodes_da_a16 = ops_sf_fpu_686_da_a16; + x86_opcodes_da_a32 = ops_sf_fpu_686_da_a32; + x86_opcodes_db_a16 = ops_sf_fpu_686_db_a16; + x86_opcodes_db_a32 = ops_sf_fpu_686_db_a32; + x86_opcodes_df_a16 = ops_sf_fpu_686_df_a16; + x86_opcodes_df_a32 = ops_sf_fpu_686_df_a32; + } else { + x86_opcodes_da_a16 = ops_fpu_686_da_a16; + x86_opcodes_da_a32 = ops_fpu_686_da_a32; + x86_opcodes_db_a16 = ops_fpu_686_db_a16; + x86_opcodes_db_a32 = ops_fpu_686_db_a32; + x86_opcodes_df_a16 = ops_fpu_686_df_a16; + x86_opcodes_df_a32 = ops_fpu_686_df_a32; + } + } -#ifdef USE_DYNAREC - if (cpu_s->cpu_type == CPU_Cx6x86MX) - x86_setopcodes(ops_386, ops_c6x86mx_0f, dynarec_ops_386, dynarec_ops_c6x86mx_0f); - else if (cpu_s->cpu_type == CPU_Cx6x86L) - x86_setopcodes(ops_386, ops_pentium_0f, dynarec_ops_386, dynarec_ops_pentium_0f); - else - x86_setopcodes(ops_386, ops_c6x86mx_0f, dynarec_ops_386, dynarec_ops_c6x86mx_0f); - // x86_setopcodes(ops_386, ops_c6x86_0f, dynarec_ops_386, dynarec_ops_c6x86_0f); -#else - if (cpu_s->cpu_type == CPU_Cx6x86MX) - x86_setopcodes(ops_386, ops_c6x86mx_0f); - else if (cpu_s->cpu_type == CPU_Cx6x86L) - x86_setopcodes(ops_386, ops_pentium_0f); - else - x86_setopcodes(ops_386, ops_c6x86_0f); -#endif +# ifdef USE_DYNAREC + if (cpu_s->cpu_type == CPU_Cx6x86MX) + x86_setopcodes(ops_386, ops_c6x86mx_0f, dynarec_ops_386, dynarec_ops_c6x86mx_0f); + else if (cpu_s->cpu_type == CPU_Cx6x86L) + x86_setopcodes(ops_386, ops_pentium_0f, dynarec_ops_386, dynarec_ops_pentium_0f); + else + x86_setopcodes(ops_386, ops_c6x86mx_0f, dynarec_ops_386, dynarec_ops_c6x86mx_0f); +# if 0 + x86_setopcodes(ops_386, ops_c6x86_0f, dynarec_ops_386, dynarec_ops_c6x86_0f); +# endif +# else + if (cpu_s->cpu_type == CPU_Cx6x86MX) + x86_setopcodes(ops_386, ops_c6x86mx_0f); + else if (cpu_s->cpu_type == CPU_Cx6x86L) + x86_setopcodes(ops_386, ops_pentium_0f); + else + x86_setopcodes(ops_386, ops_c6x86mx_0f); +# if 0 + x86_setopcodes(ops_386, ops_c6x86_0f); +# endif +# endif - timing_rr = 1; /* register dest - register src */ - timing_rm = 1; /* register dest - memory src */ - timing_mr = 2; /* memory dest - register src */ - timing_mm = 2; - timing_rml = 1; /* register dest - memory src long */ - timing_mrl = 2; /* memory dest - register src long */ - timing_mml = 2; - if (cpu_s->cpu_type == CPU_CxGX1) { - timing_bt = 4; /* branch taken */ - timing_bnt = 1; /* branch not taken */ - } else { - timing_bt = 0; /* branch taken */ - timing_bnt = 2; /* branch not taken */ - } + timing_rr = 1; /* register dest - register src */ + timing_rm = 1; /* register dest - memory src */ + timing_mr = 2; /* memory dest - register src */ + timing_mm = 2; + timing_rml = 1; /* register dest - memory src long */ + timing_mrl = 2; /* memory dest - register src long */ + timing_mml = 2; + if (cpu_s->cpu_type == CPU_CxGX1) { + timing_bt = 4; /* branch taken */ + timing_bnt = 1; /* branch not taken */ + } else { + timing_bt = 0; /* branch taken */ + timing_bnt = 2; /* branch not taken */ + } - /* Make the CxGX1 share the timings with most other Cyrix C6x86's due to the real - ones still being unknown. */ - timing_int_rm = 9; - timing_int_v86 = 46; - timing_int_pm = 21; - timing_int_pm_outer = 32; - timing_iret_rm = 7; - timing_iret_v86 = 26; - timing_iret_pm = 10; - timing_iret_pm_outer = 26; - timing_call_rm = 3; - timing_call_pm = 4; - timing_call_pm_gate = 15; - timing_call_pm_gate_inner = 26; - timing_retf_rm = 4; - timing_retf_pm = 4; - timing_retf_pm_outer = 23; - timing_jmp_rm = 1; - timing_jmp_pm = 4; - timing_jmp_pm_gate = 14; + /* Make the CxGX1 share the timings with most other Cyrix C6x86's due to the real + ones still being unknown. */ + timing_int_rm = 9; + timing_int_v86 = 46; + timing_int_pm = 21; + timing_int_pm_outer = 32; + timing_iret_rm = 7; + timing_iret_v86 = 26; + timing_iret_pm = 10; + timing_iret_pm_outer = 26; + timing_call_rm = 3; + timing_call_pm = 4; + timing_call_pm_gate = 15; + timing_call_pm_gate_inner = 26; + timing_retf_rm = 4; + timing_retf_pm = 4; + timing_retf_pm_outer = 23; + timing_jmp_rm = 1; + timing_jmp_pm = 4; + timing_jmp_pm_gate = 14; - timing_misaligned = 2; + timing_misaligned = 2; - cpu_cyrix_alignment = 1; + cpu_cyrix_alignment = 1; - cpu_features = CPU_FEATURE_RDTSC; - if (cpu_s->cpu_type >= CPU_CxGX1) - cpu_features |= CPU_FEATURE_MSR | CPU_FEATURE_CR4; - if (cpu_s->cpu_type == CPU_Cx6x86MX) - cpu_features |= CPU_FEATURE_MMX; - msr.fcr = (1 << 8) | (1 << 9) | (1 << 12) | (1 << 16) | (1 << 19) | (1 << 21); - if (cpu_s->cpu_type >= CPU_CxGX1) - cpu_CR4_mask = CR4_TSD | CR4_DE | CR4_PCE; + cpu_features = CPU_FEATURE_RDTSC; + if (cpu_s->cpu_type >= CPU_CxGX1) + cpu_features |= CPU_FEATURE_MSR | CPU_FEATURE_CR4; + if (cpu_s->cpu_type == CPU_Cx6x86MX) + cpu_features |= CPU_FEATURE_MMX; + if (cpu_s->cpu_type >= CPU_CxGX1) + cpu_CR4_mask = CR4_TSD | CR4_DE | CR4_PCE; -#ifdef USE_DYNAREC - codegen_timing_set(&codegen_timing_686); -#endif +# ifdef USE_DYNAREC + codegen_timing_set(&codegen_timing_686); +# endif - if ((cpu_s->cpu_type == CPU_Cx6x86L) || (cpu_s->cpu_type == CPU_Cx6x86MX)) - ccr4 = 0x80; - else if (CPU_Cx6x86) - CPUID = 0; /* Disabled on powerup by default */ - break; + if ((cpu_s->cpu_type == CPU_Cx6x86L) || (cpu_s->cpu_type == CPU_Cx6x86MX)) + ccr4 = 0x80; + else if (CPU_Cx6x86) + CPUID = 0; /* Disabled on powerup by default */ + break; #endif #if defined(DEV_BRANCH) && defined(USE_AMD_K5) - case CPU_K5: - case CPU_5K86: + case CPU_K5: + case CPU_5K86: #endif - case CPU_K6: - case CPU_K6_2: - case CPU_K6_2C: - case CPU_K6_3: - case CPU_K6_2P: - case CPU_K6_3P: + case CPU_K6: + case CPU_K6_2: + case CPU_K6_2C: + case CPU_K6_3: + case CPU_K6_2P: + case CPU_K6_3P: #ifdef USE_DYNAREC - if (cpu_s->cpu_type >= CPU_K6_2) - x86_setopcodes(ops_386, ops_k62_0f, dynarec_ops_386, dynarec_ops_k62_0f); -#if defined(DEV_BRANCH) && defined(USE_AMD_K5) - else if (cpu_s->cpu_type == CPU_K6) - x86_setopcodes(ops_386, ops_k6_0f, dynarec_ops_386, dynarec_ops_k6_0f); - else - x86_setopcodes(ops_386, ops_pentiummmx_0f, dynarec_ops_386, dynarec_ops_pentiummmx_0f); + if (cpu_s->cpu_type >= CPU_K6_2) + x86_setopcodes(ops_386, ops_k62_0f, dynarec_ops_386, dynarec_ops_k62_0f); +# if defined(DEV_BRANCH) && defined(USE_AMD_K5) + else if (cpu_s->cpu_type == CPU_K6) + x86_setopcodes(ops_386, ops_k6_0f, dynarec_ops_386, dynarec_ops_k6_0f); + else + x86_setopcodes(ops_386, ops_pentiummmx_0f, dynarec_ops_386, dynarec_ops_pentiummmx_0f); +# else + else + x86_setopcodes(ops_386, ops_k6_0f, dynarec_ops_386, dynarec_ops_k6_0f); +# endif #else - else - x86_setopcodes(ops_386, ops_k6_0f, dynarec_ops_386, dynarec_ops_k6_0f); -#endif -#else - if (cpu_s->cpu_type >= CPU_K6_2) - x86_setopcodes(ops_386, ops_k62_0f); -#if defined(DEV_BRANCH) && defined(USE_AMD_K5) - else if (cpu_s->cpu_type = CPU_K6) - x86_setopcodes(ops_386, ops_k6_0f); - else - x86_setopcodes(ops_386, ops_pentiummmx_0f); -#else - else - x86_setopcodes(ops_386, ops_k6_0f); -#endif + if (cpu_s->cpu_type >= CPU_K6_2) + x86_setopcodes(ops_386, ops_k62_0f); +# if defined(DEV_BRANCH) && defined(USE_AMD_K5) + else if (cpu_s->cpu_type == CPU_K6) + x86_setopcodes(ops_386, ops_k6_0f); + else + x86_setopcodes(ops_386, ops_pentiummmx_0f); +# else + else + x86_setopcodes(ops_386, ops_k6_0f); +# endif #endif - timing_rr = 1; /* register dest - register src */ - timing_rm = 2; /* register dest - memory src */ - timing_mr = 3; /* memory dest - register src */ - timing_mm = 3; - timing_rml = 2; /* register dest - memory src long */ - timing_mrl = 3; /* memory dest - register src long */ - timing_mml = 3; - timing_bt = 0; /* branch taken */ - timing_bnt = 1; /* branch not taken */ + if ((cpu_s->cpu_type == CPU_K6_2P) || (cpu_s->cpu_type == CPU_K6_3P)) { + x86_opcodes_3DNOW = ops_3DNOWE; +#ifdef USE_DYNAREC + x86_dynarec_opcodes_3DNOW = dynarec_ops_3DNOWE; +#endif + } - timing_int = 6; - timing_int_rm = 11; - timing_int_v86 = 54; - timing_int_pm = 25; - timing_int_pm_outer = 42; - timing_iret_rm = 7; - timing_iret_v86 = 27; /* unknown */ - timing_iret_pm = 10; - timing_iret_pm_outer = 27; - timing_call_rm = 4; - timing_call_pm = 4; - timing_call_pm_gate = 22; - timing_call_pm_gate_inner = 44; - timing_retf_rm = 4; - timing_retf_pm = 4; - timing_retf_pm_outer = 23; - timing_jmp_rm = 3; - timing_jmp_pm = 3; - timing_jmp_pm_gate = 18; + timing_rr = 1; /* register dest - register src */ + timing_rm = 2; /* register dest - memory src */ + timing_mr = 3; /* memory dest - register src */ + timing_mm = 3; + timing_rml = 2; /* register dest - memory src long */ + timing_mrl = 3; /* memory dest - register src long */ + timing_mml = 3; + timing_bt = 0; /* branch taken */ + timing_bnt = 1; /* branch not taken */ - timing_misaligned = 3; + timing_int = 6; + timing_int_rm = 11; + timing_int_v86 = 54; + timing_int_pm = 25; + timing_int_pm_outer = 42; + timing_iret_rm = 7; + timing_iret_v86 = 27; /* unknown */ + timing_iret_pm = 10; + timing_iret_pm_outer = 27; + timing_call_rm = 4; + timing_call_pm = 4; + timing_call_pm_gate = 22; + timing_call_pm_gate_inner = 44; + timing_retf_rm = 4; + timing_retf_pm = 4; + timing_retf_pm_outer = 23; + timing_jmp_rm = 3; + timing_jmp_pm = 3; + timing_jmp_pm_gate = 18; - cpu_features = CPU_FEATURE_RDTSC | CPU_FEATURE_MSR | CPU_FEATURE_CR4 | CPU_FEATURE_VME | CPU_FEATURE_MMX; - if (cpu_s->cpu_type >= CPU_K6_2) - cpu_features |= CPU_FEATURE_3DNOW; - msr.fcr = (1 << 8) | (1 << 9) | (1 << 12) | (1 << 16) | (1 << 19) | (1 << 21); + timing_misaligned = 3; + + cpu_features = CPU_FEATURE_RDTSC | CPU_FEATURE_MSR | CPU_FEATURE_CR4 | CPU_FEATURE_VME | CPU_FEATURE_MMX; + if (cpu_s->cpu_type >= CPU_K6_2) + cpu_features |= CPU_FEATURE_3DNOW; + if ((cpu_s->cpu_type == CPU_K6_2P) || (cpu_s->cpu_type == CPU_K6_3P)) + cpu_features |= CPU_FEATURE_3DNOWE; #if defined(DEV_BRANCH) && defined(USE_AMD_K5) - cpu_CR4_mask = CR4_TSD | CR4_DE | CR4_MCE; - if (cpu_s->cpu_type >= CPU_K6) { - cpu_CR4_mask |= (CR4_VME | CR4_PVI | CR4_PSE); - if (cpu_s->cpu_type <= CPU_K6) - cpu_CR4_mask |= CR4_PCE; - } + cpu_CR4_mask = CR4_TSD | CR4_DE | CR4_MCE; + if (cpu_s->cpu_type >= CPU_K6) { + cpu_CR4_mask |= (CR4_VME | CR4_PVI | CR4_PSE); + if (cpu_s->cpu_type <= CPU_K6) + cpu_CR4_mask |= CR4_PCE; + } #else - cpu_CR4_mask = CR4_VME | CR4_PVI | CR4_TSD | CR4_DE | CR4_PSE | CR4_MCE; - if (cpu_s->cpu_type == CPU_K6) - cpu_CR4_mask |= CR4_PCE; + cpu_CR4_mask = CR4_VME | CR4_PVI | CR4_TSD | CR4_DE | CR4_PSE | CR4_MCE; + if (cpu_s->cpu_type == CPU_K6) + cpu_CR4_mask |= CR4_PCE; #endif #ifdef USE_DYNAREC - codegen_timing_set(&codegen_timing_k6); + codegen_timing_set(&codegen_timing_k6); #endif - break; + break; - case CPU_PENTIUMPRO: - case CPU_PENTIUM2: - case CPU_PENTIUM2D: + case CPU_PENTIUMPRO: + case CPU_PENTIUM2: + case CPU_PENTIUM2D: #ifdef USE_DYNAREC - /* TODO: Perhaps merge the three opcode tables with some instructions UD#'ing depending on - CPU type. */ - if (cpu_s->cpu_type == CPU_PENTIUM2D) - x86_setopcodes(ops_386, ops_pentium2d_0f, dynarec_ops_386, dynarec_ops_pentium2d_0f); - else if (cpu_s->cpu_type == CPU_PENTIUM2) - x86_setopcodes(ops_386, ops_pentium2_0f, dynarec_ops_386, dynarec_ops_pentium2_0f); - else - x86_setopcodes(ops_386, ops_pentiumpro_0f, dynarec_ops_386, dynarec_ops_pentiumpro_0f); + /* TODO: Perhaps merge the three opcode tables with some instructions UD#'ing depending on + CPU type. */ + if (cpu_s->cpu_type == CPU_PENTIUM2D) + x86_setopcodes(ops_386, ops_pentium2d_0f, dynarec_ops_386, dynarec_ops_pentium2d_0f); + else if (cpu_s->cpu_type == CPU_PENTIUM2) + x86_setopcodes(ops_386, ops_pentium2_0f, dynarec_ops_386, dynarec_ops_pentium2_0f); + else + x86_setopcodes(ops_386, ops_pentiumpro_0f, dynarec_ops_386, dynarec_ops_pentiumpro_0f); + if (fpu_softfloat) { + x86_dynarec_opcodes_da_a16 = dynarec_ops_sf_fpu_686_da_a16; + x86_dynarec_opcodes_da_a32 = dynarec_ops_sf_fpu_686_da_a32; + x86_dynarec_opcodes_db_a16 = dynarec_ops_sf_fpu_686_db_a16; + x86_dynarec_opcodes_db_a32 = dynarec_ops_sf_fpu_686_db_a32; + x86_dynarec_opcodes_df_a16 = dynarec_ops_sf_fpu_686_df_a16; + x86_dynarec_opcodes_df_a32 = dynarec_ops_sf_fpu_686_df_a32; + } else { x86_dynarec_opcodes_da_a16 = dynarec_ops_fpu_686_da_a16; x86_dynarec_opcodes_da_a32 = dynarec_ops_fpu_686_da_a32; x86_dynarec_opcodes_db_a16 = dynarec_ops_fpu_686_db_a16; x86_dynarec_opcodes_db_a32 = dynarec_ops_fpu_686_db_a32; x86_dynarec_opcodes_df_a16 = dynarec_ops_fpu_686_df_a16; x86_dynarec_opcodes_df_a32 = dynarec_ops_fpu_686_df_a32; + } #else - if (cpu_s->cpu_type == CPU_PENTIUM2D) - x86_setopcodes(ops_386, ops_pentium2d_0f); - else - x86_setopcodes(ops_386, ops_pentium2_0f); + if (cpu_s->cpu_type == CPU_PENTIUM2D) + x86_setopcodes(ops_386, ops_pentium2d_0f); + else + x86_setopcodes(ops_386, ops_pentium2_0f); #endif - x86_opcodes_da_a16 = ops_fpu_686_da_a16; - x86_opcodes_da_a32 = ops_fpu_686_da_a32; - x86_opcodes_db_a16 = ops_fpu_686_db_a16; - x86_opcodes_db_a32 = ops_fpu_686_db_a32; - x86_opcodes_df_a16 = ops_fpu_686_df_a16; - x86_opcodes_df_a32 = ops_fpu_686_df_a32; + if (fpu_softfloat) { + x86_opcodes_da_a16 = ops_sf_fpu_686_da_a16; + x86_opcodes_da_a32 = ops_sf_fpu_686_da_a32; + x86_opcodes_db_a16 = ops_sf_fpu_686_db_a16; + x86_opcodes_db_a32 = ops_sf_fpu_686_db_a32; + x86_opcodes_df_a16 = ops_sf_fpu_686_df_a16; + x86_opcodes_df_a32 = ops_sf_fpu_686_df_a32; + } else { + x86_opcodes_da_a16 = ops_fpu_686_da_a16; + x86_opcodes_da_a32 = ops_fpu_686_da_a32; + x86_opcodes_db_a16 = ops_fpu_686_db_a16; + x86_opcodes_db_a32 = ops_fpu_686_db_a32; + x86_opcodes_df_a16 = ops_fpu_686_df_a16; + x86_opcodes_df_a32 = ops_fpu_686_df_a32; + } - timing_rr = 1; /* register dest - register src */ - timing_rm = 2; /* register dest - memory src */ - timing_mr = 3; /* memory dest - register src */ - timing_mm = 3; - timing_rml = 2; /* register dest - memory src long */ - timing_mrl = 3; /* memory dest - register src long */ - timing_mml = 3; - timing_bt = 0; /* branch taken */ - timing_bnt = 1; /* branch not taken */ + timing_rr = 1; /* register dest - register src */ + timing_rm = 2; /* register dest - memory src */ + timing_mr = 3; /* memory dest - register src */ + timing_mm = 3; + timing_rml = 2; /* register dest - memory src long */ + timing_mrl = 3; /* memory dest - register src long */ + timing_mml = 3; + timing_bt = 0; /* branch taken */ + timing_bnt = 1; /* branch not taken */ - timing_int = 6; - timing_int_rm = 11; - timing_int_v86 = 54; - timing_int_pm = 25; - timing_int_pm_outer = 42; - timing_iret_rm = 7; - timing_iret_v86 = 27; /* unknown */ - timing_iret_pm = 10; - timing_iret_pm_outer = 27; - timing_call_rm = 4; - timing_call_pm = 4; - timing_call_pm_gate = 22; - timing_call_pm_gate_inner = 44; - timing_retf_rm = 4; - timing_retf_pm = 4; - timing_retf_pm_outer = 23; - timing_jmp_rm = 3; - timing_jmp_pm = 3; - timing_jmp_pm_gate = 18; + timing_int = 6; + timing_int_rm = 11; + timing_int_v86 = 54; + timing_int_pm = 25; + timing_int_pm_outer = 42; + timing_iret_rm = 7; + timing_iret_v86 = 27; /* unknown */ + timing_iret_pm = 10; + timing_iret_pm_outer = 27; + timing_call_rm = 4; + timing_call_pm = 4; + timing_call_pm_gate = 22; + timing_call_pm_gate_inner = 44; + timing_retf_rm = 4; + timing_retf_pm = 4; + timing_retf_pm_outer = 23; + timing_jmp_rm = 3; + timing_jmp_pm = 3; + timing_jmp_pm_gate = 18; - timing_misaligned = 3; + timing_misaligned = 3; - cpu_features = CPU_FEATURE_RDTSC | CPU_FEATURE_MSR | CPU_FEATURE_CR4 | CPU_FEATURE_VME; - if (cpu_s->cpu_type >= CPU_PENTIUM2) - cpu_features |= CPU_FEATURE_MMX; - msr.fcr = (1 << 8) | (1 << 9) | (1 << 12) | (1 << 16) | (1 << 19) | (1 << 21); - cpu_CR4_mask = CR4_VME | CR4_PVI | CR4_TSD | CR4_DE | CR4_PSE | CR4_MCE | CR4_PAE | CR4_PCE; - if (cpu_s->cpu_type == CPU_PENTIUM2D) - cpu_CR4_mask |= CR4_OSFXSR; + cpu_features = CPU_FEATURE_RDTSC | CPU_FEATURE_MSR | CPU_FEATURE_CR4 | CPU_FEATURE_VME; + if (cpu_s->cpu_type >= CPU_PENTIUM2) + cpu_features |= CPU_FEATURE_MMX; + cpu_CR4_mask = CR4_VME | CR4_PVI | CR4_TSD | CR4_DE | CR4_PSE | CR4_MCE | CR4_PAE | CR4_PCE | CR4_PGE; + if (cpu_s->cpu_type == CPU_PENTIUM2D) + cpu_CR4_mask |= CR4_OSFXSR; #ifdef USE_DYNAREC - codegen_timing_set(&codegen_timing_p6); + codegen_timing_set(&codegen_timing_p6); #endif - break; + break; - case CPU_CYRIX3S: + case CPU_CYRIX3S: #ifdef USE_DYNAREC - x86_setopcodes(ops_386, ops_winchip2_0f, dynarec_ops_386, dynarec_ops_winchip2_0f); + x86_setopcodes(ops_386, ops_winchip2_0f, dynarec_ops_386, dynarec_ops_winchip2_0f); #else - x86_setopcodes(ops_386, ops_winchip2_0f); + x86_setopcodes(ops_386, ops_winchip2_0f); #endif - timing_rr = 1; /* register dest - register src */ - timing_rm = 2; /* register dest - memory src */ - timing_mr = 2; /* memory dest - register src */ - timing_mm = 3; - timing_rml = 2; /* register dest - memory src long */ - timing_mrl = 2; /* memory dest - register src long */ - timing_mml = 3; - timing_bt = 2; /* branch taken */ - timing_bnt = 1; /* branch not taken */ + timing_rr = 1; /* register dest - register src */ + timing_rm = 2; /* register dest - memory src */ + timing_mr = 2; /* memory dest - register src */ + timing_mm = 3; + timing_rml = 2; /* register dest - memory src long */ + timing_mrl = 2; /* memory dest - register src long */ + timing_mml = 3; + timing_bt = 2; /* branch taken */ + timing_bnt = 1; /* branch not taken */ - timing_int_rm = 26; /* unknown */ - timing_int_v86 = 82; - timing_int_pm = 44; - timing_int_pm_outer = 71; - timing_iret_rm = 7; - timing_iret_v86 = 26; - timing_iret_pm = 10; - timing_iret_pm_outer = 26; - timing_call_rm = 4; - timing_call_pm = 15; - timing_call_pm_gate = 26; - timing_call_pm_gate_inner = 35; - timing_retf_rm = 4; - timing_retf_pm = 7; - timing_retf_pm_outer = 23; - timing_jmp_rm = 5; - timing_jmp_pm = 7; - timing_jmp_pm_gate = 17; + timing_int_rm = 26; /* unknown */ + timing_int_v86 = 82; + timing_int_pm = 44; + timing_int_pm_outer = 71; + timing_iret_rm = 7; + timing_iret_v86 = 26; + timing_iret_pm = 10; + timing_iret_pm_outer = 26; + timing_call_rm = 4; + timing_call_pm = 15; + timing_call_pm_gate = 26; + timing_call_pm_gate_inner = 35; + timing_retf_rm = 4; + timing_retf_pm = 7; + timing_retf_pm_outer = 23; + timing_jmp_rm = 5; + timing_jmp_pm = 7; + timing_jmp_pm_gate = 17; - timing_misaligned = 2; + timing_misaligned = 2; - cpu_features = CPU_FEATURE_RDTSC | CPU_FEATURE_MMX | CPU_FEATURE_MSR | CPU_FEATURE_CR4 | CPU_FEATURE_3DNOW; - msr.fcr = (1 << 8) | (1 << 9) | (1 << 12) | (1 << 16) | (1 << 18) | (1 << 19) | (1 << 20) | (1 << 21); - cpu_CR4_mask = CR4_TSD | CR4_DE | CR4_MCE | CR4_PCE; + cpu_features = CPU_FEATURE_RDTSC | CPU_FEATURE_MMX | CPU_FEATURE_MSR | CPU_FEATURE_CR4 | CPU_FEATURE_3DNOW; + msr.fcr = (1 << 7) | (1 << 8) | (1 << 9) | (1 << 12) | (1 << 16) | (1 << 18) | (1 << 19) | (1 << 20) | (1 << 21); + cpu_CR4_mask = CR4_TSD | CR4_DE | CR4_MCE | CR4_PCE | CR4_PGE; - cpu_cyrix_alignment = 1; + cpu_cyrix_alignment = 1; #ifdef USE_DYNAREC - codegen_timing_set(&codegen_timing_winchip); + codegen_timing_set(&codegen_timing_winchip); #endif - break; + break; - default: - fatal("cpu_set : unknown CPU type %i\n", cpu_s->cpu_type); + default: + fatal("cpu_set : unknown CPU type %" PRIu64 "\n", cpu_s->cpu_type); } switch (fpu_type) { - case FPU_NONE: - break; + case FPU_NONE: + break; - case FPU_8087: - x87_timings = x87_timings_8087; - break; + case FPU_8087: + x87_timings = x87_timings_8087; + break; - case FPU_287: - x87_timings = x87_timings_287; - break; + case FPU_287: + x87_timings = x87_timings_287; + break; - case FPU_287XL: - case FPU_387: - x87_timings = x87_timings_387; - break; + case FPU_287XL: + case FPU_387: + x87_timings = x87_timings_387; + break; - case FPU_487SX: - default: - x87_timings = x87_timings_486; - x87_concurrency = x87_concurrency_486; + case FPU_487SX: + default: + x87_timings = x87_timings_486; + x87_concurrency = x87_concurrency_486; } if (is386) { -#ifdef USE_DYNAREC - if (cpu_use_dynarec) - cpu_exec = exec386_dynarec; - else +#if defined(USE_DYNAREC) && !defined(USE_GDBSTUB) + if (cpu_use_dynarec) + cpu_exec = exec386_dynarec; + else #endif - cpu_exec = exec386; + /* Use exec386 for CPU_IBM486SLC because it can reach 100 MHz. */ + if ((cpu_s->cpu_type == CPU_IBM486SLC) || (cpu_s->cpu_type > CPU_486DLC)) + cpu_exec = exec386; + else + cpu_exec = exec386_2386; } else if (cpu_s->cpu_type >= CPU_286) - cpu_exec = exec386; + cpu_exec = exec386_2386; else - cpu_exec = execx86; + cpu_exec = execx86; + mmx_init(); + gdbstub_cpu_init(); } - void cpu_close(void) { cpu_inited = 0; } - void cpu_set_isa_speed(int speed) { if (speed) { - cpu_isa_speed = speed; - pc_speed_changed(); + cpu_isa_speed = speed; } else if (cpu_busspeed >= 8000000) - cpu_isa_speed = 8000000; + cpu_isa_speed = 8000000; else - cpu_isa_speed = cpu_busspeed; + cpu_isa_speed = cpu_busspeed; + + pc_speed_changed(); cpu_log("cpu_set_isa_speed(%d) = %d\n", speed, cpu_isa_speed); } - void cpu_set_pci_speed(int speed) { if (speed) - cpu_pci_speed = speed; + cpu_pci_speed = speed; else if (cpu_busspeed < 42500000) - cpu_pci_speed = cpu_busspeed; + cpu_pci_speed = cpu_busspeed; else if (cpu_busspeed < 84000000) - cpu_pci_speed = cpu_busspeed / 2; + cpu_pci_speed = cpu_busspeed / 2; else if (cpu_busspeed < 120000000) - cpu_pci_speed = cpu_busspeed / 3; + cpu_pci_speed = cpu_busspeed / 3; else - cpu_pci_speed = cpu_busspeed / 4; + cpu_pci_speed = cpu_busspeed / 4; if (cpu_isa_pci_div) - cpu_set_isa_pci_div(cpu_isa_pci_div); + cpu_set_isa_pci_div(cpu_isa_pci_div); else if (speed) - pc_speed_changed(); + pc_speed_changed(); - pci_burst_time = cpu_s->rspeed / cpu_pci_speed; + pci_burst_time = cpu_s->rspeed / cpu_pci_speed; pci_nonburst_time = 4 * pci_burst_time; cpu_log("cpu_set_pci_speed(%d) = %d\n", speed, cpu_pci_speed); } - void cpu_set_isa_pci_div(int div) { @@ -1442,1082 +1855,1170 @@ cpu_set_isa_pci_div(int div) cpu_log("cpu_set_isa_pci_div(%d)\n", cpu_isa_pci_div); if (cpu_isa_pci_div) - cpu_set_isa_speed(cpu_pci_speed / cpu_isa_pci_div); + cpu_set_isa_speed(cpu_pci_speed / cpu_isa_pci_div); else - cpu_set_isa_speed(0); + cpu_set_isa_speed(0); } - void cpu_set_agp_speed(int speed) { if (speed) { - cpu_agp_speed = speed; - pc_speed_changed(); - } - else if (cpu_busspeed < 84000000) - cpu_agp_speed = cpu_busspeed; + cpu_agp_speed = speed; + pc_speed_changed(); + } else if (cpu_busspeed < 84000000) + cpu_agp_speed = cpu_busspeed; else if (cpu_busspeed < 120000000) - cpu_agp_speed = cpu_busspeed / 1.5; + cpu_agp_speed = cpu_busspeed / 1.5; else - cpu_agp_speed = cpu_busspeed / 2; + cpu_agp_speed = cpu_busspeed / 2; - agp_burst_time = cpu_s->rspeed / cpu_agp_speed; + agp_burst_time = cpu_s->rspeed / cpu_agp_speed; agp_nonburst_time = 4 * agp_burst_time; cpu_log("cpu_set_agp_speed(%d) = %d\n", speed, cpu_agp_speed); } - char * cpu_current_pc(char *bufp) { static char buff[10]; if (bufp == NULL) - bufp = buff; + bufp = buff; sprintf(bufp, "%04X:%04X", CS, cpu_state.pc); - return(bufp); + return bufp; } - void cpu_CPUID(void) { switch (cpu_s->cpu_type) { - case CPU_i486SX_SLENH: - if (!EAX) { - EAX = 0x00000001; - EBX = 0x756e6547; - EDX = 0x49656e69; - ECX = 0x6c65746e; - } else if (EAX == 1) { - EAX = CPUID; - EBX = ECX = 0; - EDX = CPUID_VME; - } else - EAX = EBX = ECX = EDX = 0; - break; + case CPU_i486SX_SLENH: + if (!EAX) { + EAX = 0x00000001; + EBX = 0x756e6547; + EDX = 0x49656e69; + ECX = 0x6c65746e; + } else if (EAX == 1) { + EAX = CPUID; + EBX = ECX = 0; + EDX = CPUID_VME; + } else + EAX = EBX = ECX = EDX = 0; + break; - case CPU_i486DX_SLENH: - if (!EAX) { - EAX = 0x00000001; - EBX = 0x756e6547; - EDX = 0x49656e69; - ECX = 0x6c65746e; - } else if (EAX == 1) { - EAX = CPUID; - EBX = ECX = 0; - EDX = CPUID_FPU | CPUID_VME; - } else - EAX = EBX = ECX = EDX = 0; - break; - - case CPU_ENH_Am486DX: - if (!EAX) { - EAX = 1; - EBX = 0x68747541; - ECX = 0x444D4163; - EDX = 0x69746E65; - } else if (EAX == 1) { - EAX = CPUID; - EBX = ECX = 0; - EDX = CPUID_FPU; /*FPU*/ - } else - EAX = EBX = ECX = EDX = 0; - break; + case CPU_i486DX_SLENH: + if (!EAX) { + EAX = 0x00000001; + EBX = 0x756e6547; + EDX = 0x49656e69; + ECX = 0x6c65746e; + } else if (EAX == 1) { + if ((CPUID == 0x0436) && (cr0 & (1 << 29))) + EAX = 0x0470; + else + EAX = CPUID; + EBX = ECX = 0; + EDX = CPUID_FPU | CPUID_VME; + } else + EAX = EBX = ECX = EDX = 0; + break; - case CPU_WINCHIP: - if (!EAX) { - EAX = 1; - if (msr.fcr2 & (1 << 14)) { - EBX = msr.fcr3 >> 32; - ECX = msr.fcr3 & 0xffffffff; - EDX = msr.fcr2 >> 32; - } else { - EBX = 0x746e6543; /* CentaurHauls */ - ECX = 0x736c7561; - EDX = 0x48727561; - } - } else if (EAX == 1) { - EAX = 0x540; - EBX = ECX = 0; - EDX = CPUID_FPU | CPUID_TSC | CPUID_MSR; - if (cpu_has_feature(CPU_FEATURE_CX8)) - EDX |= CPUID_CMPXCHG8B; - if (msr.fcr & (1 << 9)) - EDX |= CPUID_MMX; - } else - EAX = EBX = ECX = EDX = 0; - break; + case CPU_ENH_Am486DX: + if (!EAX) { + EAX = 1; + EBX = 0x68747541; + ECX = 0x444D4163; + EDX = 0x69746E65; + } else if (EAX == 1) { + EAX = CPUID; + EBX = ECX = 0; + EDX = CPUID_FPU; /*FPU*/ + } else + EAX = EBX = ECX = EDX = 0; + break; - case CPU_WINCHIP2: - switch (EAX) { - case 0: - EAX = 1; - if (msr.fcr2 & (1 << 14)) { - EBX = msr.fcr3 >> 32; - ECX = msr.fcr3 & 0xffffffff; - EDX = msr.fcr2 >> 32; - } else { - EBX = 0x746e6543; /* CentaurHauls */ - ECX = 0x736c7561; - EDX = 0x48727561; - } - break; - case 1: - EAX = CPUID; - EBX = ECX = 0; - EDX = CPUID_FPU | CPUID_TSC | CPUID_MSR; - if (cpu_has_feature(CPU_FEATURE_CX8)) - EDX |= CPUID_CMPXCHG8B; - if (msr.fcr & (1 << 9)) - EDX |= CPUID_MMX; - break; - case 0x80000000: - EAX = 0x80000005; - break; - case 0x80000001: - EAX = CPUID; - EDX = CPUID_FPU | CPUID_TSC | CPUID_MSR; - if (cpu_has_feature(CPU_FEATURE_CX8)) - EDX |= CPUID_CMPXCHG8B; - if (msr.fcr & (1 << 9)) - EDX |= CPUID_MMX; - if (cpu_has_feature(CPU_FEATURE_3DNOW)) - EDX |= CPUID_3DNOW; - break; + case CPU_WINCHIP: + if (!EAX) { + EAX = 1; + if (msr.fcr2 & (1 << 14)) { + EBX = msr.fcr3 >> 32; + ECX = msr.fcr3 & 0xffffffff; + EDX = msr.fcr2 >> 32; + } else { + EBX = 0x746e6543; /* CentaurHauls */ + ECX = 0x736c7561; + EDX = 0x48727561; + } + } else if (EAX == 1) { + EAX = 0x540; + EBX = ECX = 0; + EDX = CPUID_FPU | CPUID_TSC | CPUID_MSR; + if (cpu_has_feature(CPU_FEATURE_CX8)) + EDX |= CPUID_CMPXCHG8B; + if (msr.fcr & (1 << 9)) + EDX |= CPUID_MMX; + } else + EAX = EBX = ECX = EDX = 0; + break; - case 0x80000002: /* Processor name string */ - EAX = 0x20544449; /* IDT WinChip 2-3D */ - EBX = 0x436e6957; - ECX = 0x20706968; - EDX = 0x44332d32; - break; + case CPU_WINCHIP2: + switch (EAX) { + case 0: + EAX = 1; + if (msr.fcr2 & (1 << 14)) { + EBX = msr.fcr3 >> 32; + ECX = msr.fcr3 & 0xffffffff; + EDX = msr.fcr2 >> 32; + } else { + EBX = 0x746e6543; /* CentaurHauls */ + ECX = 0x736c7561; + EDX = 0x48727561; + } + break; + case 1: + EAX = CPUID; + EBX = ECX = 0; + EDX = CPUID_FPU | CPUID_TSC | CPUID_MSR; + if (cpu_has_feature(CPU_FEATURE_CX8)) + EDX |= CPUID_CMPXCHG8B; + if (msr.fcr & (1 << 9)) + EDX |= CPUID_MMX; + break; + case 0x80000000: + EAX = 0x80000005; + break; + case 0x80000001: + EAX = CPUID; + EDX = CPUID_FPU | CPUID_TSC | CPUID_MSR; + if (cpu_has_feature(CPU_FEATURE_CX8)) + EDX |= CPUID_CMPXCHG8B; + if (msr.fcr & (1 << 9)) + EDX |= CPUID_MMX; + if (cpu_has_feature(CPU_FEATURE_3DNOW)) + EDX |= CPUID_3DNOW; + break; - case 0x80000005: /*Cache information*/ - EBX = 0x08800880; /*TLBs*/ - ECX = 0x20040120; /*L1 data cache*/ - EDX = 0x20020120; /*L1 instruction cache*/ - break; + case 0x80000002: /* Processor name string */ + EAX = 0x20544449; /* IDT WinChip 2-3D */ + EBX = 0x436e6957; + ECX = 0x20706968; + EDX = 0x44332d32; + break; - default: - EAX = EBX = ECX = EDX = 0; - break; - } - break; + case 0x80000005: /*Cache information*/ + EBX = 0x08800880; /*TLBs*/ + ECX = 0x20040120; /*L1 data cache*/ + EDX = 0x20020120; /*L1 instruction cache*/ + break; - case CPU_P24T: - case CPU_PENTIUM: - if (!EAX) { - EAX = 0x00000001; - EBX = 0x756e6547; - EDX = 0x49656e69; - ECX = 0x6c65746e; - } else if (EAX == 1) { - EAX = CPUID; - EBX = ECX = 0; - EDX = CPUID_FPU | CPUID_VME | CPUID_PSE | CPUID_TSC | CPUID_MSR | CPUID_MCE | CPUID_CMPXCHG8B; - } else - EAX = EBX = ECX = EDX = 0; - break; + default: + EAX = EBX = ECX = EDX = 0; + break; + } + break; + + case CPU_P24T: + case CPU_PENTIUM: + if (!EAX) { + EAX = 0x00000001; + EBX = 0x756e6547; + EDX = 0x49656e69; + ECX = 0x6c65746e; + } else if (EAX == 1) { + EAX = CPUID; + EBX = ECX = 0; + EDX = CPUID_FPU | CPUID_VME | CPUID_PSE | CPUID_TSC | CPUID_MSR | CPUID_MCE | CPUID_CMPXCHG8B; + } else + EAX = EBX = ECX = EDX = 0; + break; #if defined(DEV_BRANCH) && defined(USE_AMD_K5) - case CPU_K5: - if (!EAX) { - EAX = 0x00000001; - EBX = 0x68747541; - EDX = 0x69746E65; - ECX = 0x444D4163; - } else if (EAX == 1) { - EAX = CPUID; - EBX = ECX = 0; - EDX = CPUID_FPU | CPUID_TSC | CPUID_MSR | CPUID_MCE | CPUID_CMPXCHG8B; - } else - EAX = EBX = ECX = EDX = 0; - break; + case CPU_K5: + if (!EAX) { + EAX = 0x00000001; + EBX = 0x68747541; + EDX = 0x69746E65; + ECX = 0x444D4163; + } else if (EAX == 1) { + EAX = CPUID; + EBX = ECX = 0; + EDX = CPUID_FPU | CPUID_TSC | CPUID_MSR | CPUID_MCE | CPUID_CMPXCHG8B; + } else + EAX = EBX = ECX = EDX = 0; + break; - case CPU_5K86: - if (!EAX) { - EAX = 0x00000001; - EBX = 0x68747541; - EDX = 0x69746E65; - ECX = 0x444D4163; - } else if (EAX == 1) { - EAX = CPUID; - EBX = ECX = 0; - EDX = CPUID_FPU | CPUID_TSC | CPUID_MSR | CPUID_MCE | CPUID_CMPXCHG8B; - } else if (EAX == 0x80000000) { - EAX = 0x80000005; - EBX = ECX = EDX = 0; - } else if (EAX == 0x80000001) { - EAX = CPUID; - EBX = ECX = 0; - EDX = CPUID_FPU | CPUID_TSC | CPUID_MSR | CPUID_MCE | CPUID_CMPXCHG8B; - } else if (EAX == 0x80000002) { - EAX = 0x2D444D41; - EBX = 0x7428354B; - ECX = 0x5020296D; - EDX = 0x65636F72; - } else if (EAX == 0x80000003) { - EAX = 0x726F7373; - EBX = ECX = EDX = 0; - } else if (EAX == 0x80000004) - EAX = EBX = ECX = EDX = 0; - else if (EAX == 0x80000005) { - EAX = 0; - EBX = 0x04800000; - ECX = 0x08040120; - EDX = 0x10040120; - } else - EAX = EBX = ECX = EDX = 0; - break; + case CPU_5K86: + if (!EAX) { + EAX = 0x00000001; + EBX = 0x68747541; + EDX = 0x69746E65; + ECX = 0x444D4163; + } else if (EAX == 1) { + EAX = CPUID; + EBX = ECX = 0; + EDX = CPUID_FPU | CPUID_TSC | CPUID_MSR | CPUID_MCE | CPUID_CMPXCHG8B; + } else if (EAX == 0x80000000) { + EAX = 0x80000005; + EBX = ECX = EDX = 0; + } else if (EAX == 0x80000001) { + EAX = CPUID; + EBX = ECX = 0; + EDX = CPUID_FPU | CPUID_TSC | CPUID_MSR | CPUID_MCE | CPUID_CMPXCHG8B; + } else if (EAX == 0x80000002) { + EAX = 0x2D444D41; + EBX = 0x7428354B; + ECX = 0x5020296D; + EDX = 0x65636F72; + } else if (EAX == 0x80000003) { + EAX = 0x726F7373; + EBX = ECX = EDX = 0; + } else if (EAX == 0x80000004) + EAX = EBX = ECX = EDX = 0; + else if (EAX == 0x80000005) { + EAX = 0; + EBX = 0x04800000; + ECX = 0x08040120; + EDX = 0x10040120; + } else + EAX = EBX = ECX = EDX = 0; + break; #endif - case CPU_K6: - if (!EAX) { - EAX = 0x00000001; - EBX = 0x68747541; - EDX = 0x69746E65; - ECX = 0x444D4163; - } else if (EAX == 1) { - EAX = CPUID; - EBX = ECX = 0; - EDX = CPUID_FPU | CPUID_VME | CPUID_PSE | CPUID_TSC | CPUID_MSR | CPUID_MCE | CPUID_CMPXCHG8B | CPUID_MMX; - } else if (EAX == 0x80000000) { - EAX = 0x80000005; - EBX = ECX = EDX = 0; - } else if (EAX == 0x80000001) { - EAX = CPUID + 0x100; - EBX = ECX = 0; - EDX = CPUID_FPU | CPUID_VME | CPUID_PSE | CPUID_TSC | CPUID_MSR | CPUID_MCE | CPUID_CMPXCHG8B | CPUID_AMDSEP | CPUID_MMX; - } else if (EAX == 0x80000002) { - EAX = 0x2D444D41; - EBX = 0x6D74364B; - ECX = 0x202F7720; - EDX = 0x746C756D; - } else if (EAX == 0x80000003) { - EAX = 0x64656D69; - EBX = 0x65206169; - ECX = 0x6E657478; - EDX = 0x6E6F6973; - } else if (EAX == 0x80000004) { - EAX = 0x73; - EBX = ECX = EDX = 0; - } else if (EAX == 0x80000005) { - EAX = 0; - EBX = 0x02800140; - ECX = 0x20020220; - EDX = 0x20020220; - } else if (EAX == 0x8FFFFFFF) { - EAX = 0x4778654E; - EBX = 0x72656E65; - ECX = 0x6F697461; - EDX = 0x444D416E; - } else - EAX = EBX = ECX = EDX = 0; - break; + case CPU_K6: + if (!EAX) { + EAX = 0x00000001; + EBX = 0x68747541; + EDX = 0x69746E65; + ECX = 0x444D4163; + } else if (EAX == 1) { + EAX = CPUID; + EBX = ECX = 0; + EDX = CPUID_FPU | CPUID_VME | CPUID_PSE | CPUID_TSC | CPUID_MSR | CPUID_MCE | CPUID_CMPXCHG8B | CPUID_MMX; + } else if (EAX == 0x80000000) { + EAX = 0x80000005; + EBX = ECX = EDX = 0; + } else if (EAX == 0x80000001) { + EAX = CPUID + 0x100; + EBX = ECX = 0; + EDX = CPUID_FPU | CPUID_VME | CPUID_PSE | CPUID_TSC | CPUID_MSR | CPUID_MCE | CPUID_CMPXCHG8B | CPUID_AMDSEP | CPUID_MMX; + } else if (EAX == 0x80000002) { + EAX = 0x2D444D41; + EBX = 0x6D74364B; + ECX = 0x202F7720; + EDX = 0x746C756D; + } else if (EAX == 0x80000003) { + EAX = 0x64656D69; + EBX = 0x65206169; + ECX = 0x6E657478; + EDX = 0x6E6F6973; + } else if (EAX == 0x80000004) { + EAX = 0x73; + EBX = ECX = EDX = 0; + } else if (EAX == 0x80000005) { + EAX = 0; + EBX = 0x02800140; + ECX = 0x20020220; + EDX = 0x20020220; + } else if (EAX == 0x8FFFFFFF) { + EAX = 0x4778654E; + EBX = 0x72656E65; + ECX = 0x6F697461; + EDX = 0x444D416E; + } else + EAX = EBX = ECX = EDX = 0; + break; - case CPU_K6_2: - case CPU_K6_2C: - switch (EAX) { - case 0: - EAX = 1; - EBX = 0x68747541; /* AuthenticAMD */ - ECX = 0x444d4163; - EDX = 0x69746e65; - break; - case 1: - EAX = CPUID; - EBX = ECX = 0; - EDX = CPUID_FPU | CPUID_VME | CPUID_PSE | CPUID_TSC | CPUID_MSR | CPUID_MCE | CPUID_CMPXCHG8B | CPUID_MMX; - break; - case 0x80000000: - EAX = 0x80000005; - break; - case 0x80000001: - EAX = CPUID + 0x100; - EDX = CPUID_FPU | CPUID_VME | CPUID_PSE | CPUID_TSC | CPUID_MSR | CPUID_MCE | CPUID_CMPXCHG8B | CPUID_AMDSEP | CPUID_MMX | CPUID_3DNOW; - break; - case 0x80000002: /* Processor name string */ - EAX = 0x2d444d41; /* AMD-K6(tm) 3D pr */ - EBX = 0x7428364b; - ECX = 0x3320296d; - EDX = 0x72702044; - break; - case 0x80000003: /* Processor name string */ - EAX = 0x7365636f; /* ocessor */ - EBX = 0x00726f73; - ECX = 0x00000000; - EDX = 0x00000000; - break; - case 0x80000005: /*Cache information*/ - EBX = 0x02800140; /*TLBs*/ - ECX = 0x20020220; /*L1 data cache*/ - EDX = 0x20020220; /*L1 instruction cache*/ - break; - default: - EAX = EBX = ECX = EDX = 0; - break; - } - break; + case CPU_K6_2: + case CPU_K6_2C: + switch (EAX) { + case 0: + EAX = 1; + EBX = 0x68747541; /* AuthenticAMD */ + ECX = 0x444d4163; + EDX = 0x69746e65; + break; + case 1: + EAX = CPUID; + EBX = ECX = 0; + EDX = CPUID_FPU | CPUID_VME | CPUID_PSE | CPUID_TSC | CPUID_MSR | CPUID_MCE | CPUID_CMPXCHG8B | CPUID_MMX; + break; + case 0x80000000: + EAX = 0x80000005; + EBX = ECX = EDX = 0; + break; + case 0x80000001: + EAX = CPUID + 0x100; + EBX = ECX = 0; + EDX = CPUID_FPU | CPUID_VME | CPUID_PSE | CPUID_TSC | CPUID_MSR | CPUID_MCE | CPUID_CMPXCHG8B | CPUID_AMDSEP | CPUID_MMX | CPUID_3DNOW; + break; + case 0x80000002: /* Processor name string */ + EAX = 0x2d444d41; /* AMD-K6(tm) 3D pr */ + EBX = 0x7428364b; + ECX = 0x3320296d; + EDX = 0x72702044; + break; + case 0x80000003: /* Processor name string */ + EAX = 0x7365636f; /* ocessor */ + EBX = 0x00726f73; + ECX = 0x00000000; + EDX = 0x00000000; + break; + case 0x80000005: /*Cache information*/ + EAX = 0; + EBX = 0x02800140; /*TLBs*/ + ECX = 0x20020220; /*L1 data cache*/ + EDX = 0x20020220; /*L1 instruction cache*/ + break; + default: + EAX = EBX = ECX = EDX = 0; + break; + } + break; - case CPU_K6_3: - switch (EAX) { - case 0: - EAX = 1; - EBX = 0x68747541; /* AuthenticAMD */ - ECX = 0x444d4163; - EDX = 0x69746e65; - break; - case 1: - EAX = CPUID; - EBX = ECX = 0; - EDX = CPUID_FPU | CPUID_VME | CPUID_PSE | CPUID_TSC | CPUID_MSR | CPUID_MCE | CPUID_CMPXCHG8B | CPUID_MMX; - break; - case 0x80000000: - EAX = 0x80000006; - break; - case 0x80000001: - EAX = CPUID + 0x100; - EDX = CPUID_FPU | CPUID_VME | CPUID_PSE | CPUID_TSC | CPUID_MSR | CPUID_MCE | CPUID_CMPXCHG8B | CPUID_AMDSEP | CPUID_MMX | CPUID_3DNOW; - break; - case 0x80000002: /* Processor name string */ - EAX = 0x2d444d41; /* AMD-K6(tm) 3D+ P */ - EBX = 0x7428364b; - ECX = 0x3320296d; - EDX = 0x50202b44; - break; - case 0x80000003: /* Processor name string */ - EAX = 0x65636f72; /* rocessor */ - EBX = 0x726f7373; - ECX = 0x00000000; - EDX = 0x00000000; - break; - case 0x80000005: /* Cache information */ - EBX = 0x02800140; /* TLBs */ - ECX = 0x20020220; /*L1 data cache*/ - EDX = 0x20020220; /*L1 instruction cache*/ - break; - case 0x80000006: /* L2 Cache information */ - ECX = 0x01004220; - break; - default: - EAX = EBX = ECX = EDX = 0; - break; - } - break; + case CPU_K6_3: + switch (EAX) { + case 0: + EAX = 1; + EBX = 0x68747541; /* AuthenticAMD */ + ECX = 0x444d4163; + EDX = 0x69746e65; + break; + case 1: + EAX = CPUID; + EBX = ECX = 0; + EDX = CPUID_FPU | CPUID_VME | CPUID_PSE | CPUID_TSC | CPUID_MSR | CPUID_MCE | CPUID_CMPXCHG8B | CPUID_MMX; + break; + case 0x80000000: + EAX = 0x80000006; + EBX = ECX = EDX = 0; + break; + case 0x80000001: + EAX = CPUID + 0x100; + EBX = ECX = 0; + EDX = CPUID_FPU | CPUID_VME | CPUID_PSE | CPUID_TSC | CPUID_MSR | CPUID_MCE | CPUID_CMPXCHG8B | CPUID_AMDSEP | CPUID_MMX | CPUID_3DNOW; + break; + case 0x80000002: /* Processor name string */ + EAX = 0x2d444d41; /* AMD-K6(tm) 3D+ P */ + EBX = 0x7428364b; + ECX = 0x3320296d; + EDX = 0x50202b44; + break; + case 0x80000003: /* Processor name string */ + EAX = 0x65636f72; /* rocessor */ + EBX = 0x726f7373; + ECX = 0x00000000; + EDX = 0x00000000; + break; + case 0x80000005: /* Cache information */ + EAX = 0; + EBX = 0x02800140; /* TLBs */ + ECX = 0x20020220; /*L1 data cache*/ + EDX = 0x20020220; /*L1 instruction cache*/ + break; + case 0x80000006: /* L2 Cache information */ + EAX = EBX = EDX = 0; + ECX = 0x01004220; + break; + default: + EAX = EBX = ECX = EDX = 0; + break; + } + break; - case CPU_K6_2P: - case CPU_K6_3P: - switch (EAX) { - case 0: - EAX = 1; - EBX = 0x68747541; /* AuthenticAMD */ - ECX = 0x444d4163; - EDX = 0x69746e65; - break; - case 1: - EAX = CPUID; - EBX = ECX = 0; - EDX = CPUID_FPU | CPUID_VME | CPUID_PSE | CPUID_TSC | CPUID_MSR | CPUID_MCE | CPUID_CMPXCHG8B | CPUID_MMX; - break; - case 0x80000000: - EAX = 0x80000007; - break; - case 0x80000001: - EAX = CPUID + 0x100; - EDX = CPUID_FPU | CPUID_VME | CPUID_PSE | CPUID_TSC | CPUID_MSR | CPUID_MCE | CPUID_CMPXCHG8B | CPUID_AMDSEP | CPUID_MMX | CPUID_3DNOW; - break; - case 0x80000002: /* Processor name string */ - EAX = 0x2d444d41; /* AMD-K6(tm)-III P */ - EBX = 0x7428364b; - ECX = 0x492d296d; - EDX = 0x50204949; - break; - case 0x80000003: /* Processor name string */ - EAX = 0x65636f72; /* rocessor */ - EBX = 0x726f7373; - ECX = 0x00000000; - EDX = 0x00000000; - break; - case 0x80000005: /* Cache information */ - EBX = 0x02800140; /* TLBs */ - ECX = 0x20020220; /* L1 data cache */ - EDX = 0x20020220; /* L1 instruction cache */ - break; - case 0x80000006: /* L2 Cache information */ - if (cpu_s->cpu_type == CPU_K6_3P) - ECX = 0x01004220; - else - ECX = 0x00804220; - break; - case 0x80000007: /* PowerNow information */ - EDX = 7; - break; - default: - EAX = EBX = ECX = EDX = 0; - break; - } - break; + case CPU_K6_2P: + case CPU_K6_3P: + switch (EAX) { + case 0: + EAX = 1; + EBX = 0x68747541; /* AuthenticAMD */ + ECX = 0x444d4163; + EDX = 0x69746e65; + break; + case 1: + EAX = CPUID; + EBX = ECX = 0; + EDX = CPUID_FPU | CPUID_VME | CPUID_PSE | CPUID_TSC | CPUID_MSR | CPUID_MCE | CPUID_CMPXCHG8B | CPUID_MMX; + break; + case 0x80000000: + EAX = 0x80000007; + EBX = ECX = EDX = 0; + break; + case 0x80000001: + EAX = CPUID + 0x100; + EBX = ECX = 0; + EDX = CPUID_FPU | CPUID_VME | CPUID_PSE | CPUID_TSC | CPUID_MSR | CPUID_MCE | CPUID_CMPXCHG8B | CPUID_AMDSEP | CPUID_MMX | CPUID_3DNOW | CPUID_3DNOWE; + break; + case 0x80000002: /* Processor name string */ + EAX = 0x2d444d41; /* AMD-K6(tm)-III P */ + EBX = 0x7428364b; + ECX = 0x492d296d; + EDX = 0x50204949; + break; + case 0x80000003: /* Processor name string */ + EAX = 0x65636f72; /* rocessor */ + EBX = 0x726f7373; + ECX = 0x00000000; + EDX = 0x00000000; + break; + case 0x80000005: /* Cache information */ + EAX = 0; + EBX = 0x02800140; /* TLBs */ + ECX = 0x20020220; /* L1 data cache */ + EDX = 0x20020220; /* L1 instruction cache */ + break; + case 0x80000006: /* L2 Cache information */ + EAX = EBX = EDX = 0; + if (cpu_s->cpu_type == CPU_K6_3P) + ECX = 0x01004220; + else + ECX = 0x00804220; + break; + case 0x80000007: /* PowerNow information */ + EAX = EBX = ECX = 0; + EDX = 7; + break; + default: + EAX = EBX = ECX = EDX = 0; + break; + } + break; - case CPU_PENTIUMMMX: - if (!EAX) { - EAX = 0x00000001; - EBX = 0x756e6547; - EDX = 0x49656e69; - ECX = 0x6c65746e; - } else if (EAX == 1) { - EAX = CPUID; - EBX = ECX = 0; - EDX = CPUID_FPU | CPUID_VME | CPUID_PSE | CPUID_TSC | CPUID_MSR | CPUID_MCE | CPUID_CMPXCHG8B | CPUID_MMX; - } else - EAX = EBX = ECX = EDX = 0; - break; + case CPU_PENTIUMMMX: + if (!EAX) { + EAX = 0x00000001; + EBX = 0x756e6547; + EDX = 0x49656e69; + ECX = 0x6c65746e; + } else if (EAX == 1) { + EAX = CPUID; + EBX = ECX = 0; + EDX = CPUID_FPU | CPUID_VME | CPUID_PSE | CPUID_TSC | CPUID_MSR | CPUID_MCE | CPUID_CMPXCHG8B | CPUID_MMX; + } else + EAX = EBX = ECX = EDX = 0; + break; #if defined(DEV_BRANCH) && defined(USE_CYRIX_6X86) - case CPU_Cx6x86: - if (!EAX) { - EAX = 0x00000001; - EBX = 0x69727943; - EDX = 0x736e4978; - ECX = 0x64616574; - } else if (EAX == 1) { - EAX = CPUID; - EBX = ECX = 0; - EDX = CPUID_FPU; - } else - EAX = EBX = ECX = EDX = 0; - break; + case CPU_Cx6x86: + if (!EAX) { + EAX = 0x00000001; + EBX = 0x69727943; + EDX = 0x736e4978; + ECX = 0x64616574; + } else if (EAX == 1) { + EAX = CPUID; + EBX = ECX = 0; + EDX = CPUID_FPU; + } else + EAX = EBX = ECX = EDX = 0; + break; - case CPU_Cx6x86L: - if (!EAX) { - EAX = 0x00000001; - EBX = 0x69727943; - EDX = 0x736e4978; - ECX = 0x64616574; - } else if (EAX == 1) { - EAX = CPUID; - EBX = ECX = 0; - EDX = CPUID_FPU | CPUID_CMPXCHG8B; - } else - EAX = EBX = ECX = EDX = 0; - break; + case CPU_Cx6x86L: + if (!EAX) { + EAX = 0x00000001; + EBX = 0x69727943; + EDX = 0x736e4978; + ECX = 0x64616574; + } else if (EAX == 1) { + EAX = CPUID; + EBX = ECX = 0; + EDX = CPUID_FPU | CPUID_CMPXCHG8B; + } else + EAX = EBX = ECX = EDX = 0; + break; - case CPU_CxGX1: - if (!EAX) { - EAX = 0x00000001; - EBX = 0x69727943; - EDX = 0x736e4978; - ECX = 0x64616574; - } else if (EAX == 1) { - EAX = CPUID; - EBX = ECX = 0; - EDX = CPUID_FPU | CPUID_TSC | CPUID_MSR | CPUID_CMPXCHG8B; - } else - EAX = EBX = ECX = EDX = 0; - break; + case CPU_CxGX1: + if (!EAX) { + EAX = 0x00000001; + EBX = 0x69727943; + EDX = 0x736e4978; + ECX = 0x64616574; + } else if (EAX == 1) { + EAX = CPUID; + EBX = ECX = 0; + EDX = CPUID_FPU | CPUID_TSC | CPUID_MSR | CPUID_CMPXCHG8B; + } else + EAX = EBX = ECX = EDX = 0; + break; - case CPU_Cx6x86MX: - if (!EAX) { - EAX = 0x00000001; - EBX = 0x69727943; - EDX = 0x736e4978; - ECX = 0x64616574; - } else if (EAX == 1) { - EAX = CPUID; - EBX = ECX = 0; - EDX = CPUID_FPU | CPUID_TSC | CPUID_MSR | CPUID_CMPXCHG8B | CPUID_CMOV | CPUID_MMX; - } else - EAX = EBX = ECX = EDX = 0; - break; + case CPU_Cx6x86MX: + if (!EAX) { + EAX = 0x00000001; + EBX = 0x69727943; + EDX = 0x736e4978; + ECX = 0x64616574; + } else if (EAX == 1) { + EAX = CPUID; + EBX = ECX = 0; + EDX = CPUID_FPU | CPUID_TSC | CPUID_MSR | CPUID_CMPXCHG8B | CPUID_CMOV | CPUID_MMX; + } else + EAX = EBX = ECX = EDX = 0; + break; #endif - case CPU_PENTIUMPRO: - if (!EAX) { - EAX = 0x00000002; - EBX = 0x756e6547; - EDX = 0x49656e69; - ECX = 0x6c65746e; - } else if (EAX == 1) { - EAX = CPUID; - EBX = ECX = 0; - EDX = CPUID_FPU | CPUID_VME | CPUID_PSE | CPUID_TSC | CPUID_MSR | CPUID_PAE | CPUID_MCE | CPUID_CMPXCHG8B | CPUID_MTRR | CPUID_MCA | CPUID_SEP | CPUID_CMOV; - } else if (EAX == 2) { - EAX = 0x00000001; - EBX = ECX = 0; - EDX = 0x00000000; - } else - EAX = EBX = ECX = EDX = 0; - break; + case CPU_PENTIUMPRO: + if (!EAX) { + EAX = 0x00000002; + EBX = 0x756e6547; + EDX = 0x49656e69; + ECX = 0x6c65746e; + } else if (EAX == 1) { + EAX = CPUID; + EBX = ECX = 0; + EDX = CPUID_FPU | CPUID_VME | CPUID_PSE | CPUID_TSC | CPUID_MSR | CPUID_PAE | CPUID_MCE | CPUID_CMPXCHG8B | CPUID_MTRR | CPUID_PGE | CPUID_MCA | CPUID_SEP | CPUID_CMOV; + } else if (EAX == 2) { + EAX = 0x00000001; + EBX = ECX = 0; + EDX = 0x00000000; + } else + EAX = EBX = ECX = EDX = 0; + break; - case CPU_PENTIUM2: - if (!EAX) { - EAX = 0x00000002; - EBX = 0x756e6547; - EDX = 0x49656e69; - ECX = 0x6c65746e; - } else if (EAX == 1) { - EAX = CPUID; - EBX = ECX = 0; - EDX = CPUID_FPU | CPUID_VME | CPUID_PSE | CPUID_TSC | CPUID_MSR | CPUID_PAE | CPUID_MCE | CPUID_CMPXCHG8B | CPUID_MMX | CPUID_MTRR | CPUID_MCA | CPUID_SEP | CPUID_CMOV; - } else if (EAX == 2) { - EAX = 0x00000001; - EBX = ECX = 0; - EDX = 0x00000000; - } else - EAX = EBX = ECX = EDX = 0; - break; + case CPU_PENTIUM2: + if (!EAX) { + EAX = 0x00000002; + EBX = 0x756e6547; + EDX = 0x49656e69; + ECX = 0x6c65746e; + } else if (EAX == 1) { + EAX = CPUID; + EBX = ECX = 0; + EDX = CPUID_FPU | CPUID_VME | CPUID_PSE | CPUID_TSC | CPUID_MSR | CPUID_PAE | CPUID_MCE | CPUID_CMPXCHG8B | CPUID_MMX | CPUID_MTRR | CPUID_PGE | CPUID_MCA | CPUID_SEP | CPUID_CMOV; + } else if (EAX == 2) { + EAX = 0x00000001; + EBX = ECX = 0; + EDX = 0x00000000; + } else + EAX = EBX = ECX = EDX = 0; + break; - case CPU_PENTIUM2D: - if (!EAX) { - EAX = 0x00000002; - EBX = 0x756e6547; - EDX = 0x49656e69; - ECX = 0x6c65746e; - } else if (EAX == 1) { - EAX = CPUID; - EBX = ECX = 0; - EDX = CPUID_FPU | CPUID_VME | CPUID_PSE | CPUID_TSC | CPUID_MSR | CPUID_PAE | CPUID_MCE | CPUID_CMPXCHG8B | CPUID_MMX | CPUID_MTRR | CPUID_MCA | CPUID_SEP | CPUID_FXSR | CPUID_CMOV; - } else if (EAX == 2) { - EAX = 0x00000001; - EBX = ECX = 0; - EDX = 0x00000000; - } else - EAX = EBX = ECX = EDX = 0; - break; + case CPU_PENTIUM2D: + if (!EAX) { + EAX = 0x00000002; + EBX = 0x756e6547; + EDX = 0x49656e69; + ECX = 0x6c65746e; + } else if (EAX == 1) { + EAX = CPUID; + EBX = ECX = 0; + EDX = CPUID_FPU | CPUID_VME | CPUID_PSE | CPUID_TSC | CPUID_MSR | CPUID_PAE | CPUID_MCE | CPUID_CMPXCHG8B | CPUID_MMX | CPUID_MTRR | CPUID_PGE | CPUID_MCA | CPUID_SEP | CPUID_FXSR | CPUID_CMOV; + } else if (EAX == 2) { + EAX = 0x00000001; + EBX = ECX = 0; + EDX = 0x00000000; + } else + EAX = EBX = ECX = EDX = 0; + break; - case CPU_CYRIX3S: - switch (EAX) { - case 0: - EAX = 1; - if (msr.fcr2 & (1 << 14)) { - EBX = msr.fcr3 >> 32; - ECX = msr.fcr3 & 0xffffffff; - EDX = msr.fcr2 >> 32; - } else { - EBX = 0x746e6543; /* CentaurHauls */ - ECX = 0x736c7561; - EDX = 0x48727561; - } - break; - case 1: - EAX = CPUID; - EBX = ECX = 0; - EDX = CPUID_FPU | CPUID_TSC | CPUID_MSR | CPUID_MCE | CPUID_MMX | CPUID_MTRR; - if (cpu_has_feature(CPU_FEATURE_CX8)) - EDX |= CPUID_CMPXCHG8B; - break; - case 0x80000000: - EAX = 0x80000005; - break; - case 0x80000001: - EAX = CPUID; - EDX = CPUID_FPU | CPUID_TSC | CPUID_MSR | CPUID_MCE | CPUID_MMX | CPUID_MTRR | CPUID_3DNOW; - if (cpu_has_feature(CPU_FEATURE_CX8)) - EDX |= CPUID_CMPXCHG8B; - break; - case 0x80000002: /* Processor name string */ - EAX = 0x20414956; /* VIA Samuel */ - EBX = 0x756d6153; - ECX = 0x00006c65; - EDX = 0x00000000; - break; - case 0x80000005: /* Cache information */ - EBX = 0x08800880; /* TLBs */ - ECX = 0x40040120; /* L1 data cache */ - EDX = 0x40020120; /* L1 instruction cache */ - break; - default: - EAX = EBX = ECX = EDX = 0; - break; - } - break; + case CPU_CYRIX3S: + switch (EAX) { + case 0: + EAX = 1; + if (msr.fcr2 & (1 << 14)) { + EBX = msr.fcr3 >> 32; + ECX = msr.fcr3 & 0xffffffff; + EDX = msr.fcr2 >> 32; + } else { + EBX = 0x746e6543; /* CentaurHauls */ + ECX = 0x736c7561; + EDX = 0x48727561; + } + break; + case 1: + EAX = CPUID; + EBX = ECX = 0; + EDX = CPUID_FPU | CPUID_TSC | CPUID_MSR | CPUID_MCE | CPUID_MMX | CPUID_MTRR; + if (cpu_has_feature(CPU_FEATURE_CX8)) + EDX |= CPUID_CMPXCHG8B; + if (msr.fcr & (1 << 7)) + EDX |= CPUID_PGE; + break; + case 0x80000000: + EAX = 0x80000005; + break; + case 0x80000001: + EAX = CPUID; + EDX = CPUID_FPU | CPUID_TSC | CPUID_MSR | CPUID_MCE | CPUID_MMX | CPUID_MTRR | CPUID_3DNOW; + if (cpu_has_feature(CPU_FEATURE_CX8)) + EDX |= CPUID_CMPXCHG8B; + if (msr.fcr & (1 << 7)) + EDX |= CPUID_PGE; + break; + case 0x80000002: /* Processor name string */ + EAX = 0x20414956; /* VIA Samuel */ + EBX = 0x756d6153; + ECX = 0x00006c65; + EDX = 0x00000000; + break; + case 0x80000005: /* Cache information */ + EBX = 0x08800880; /* TLBs */ + ECX = 0x40040120; /* L1 data cache */ + EDX = 0x40020120; /* L1 instruction cache */ + break; + default: + EAX = EBX = ECX = EDX = 0; + break; + } + break; } } - void cpu_ven_reset(void) { memset(&msr, 0, sizeof(msr)); switch (cpu_s->cpu_type) { - case CPU_K6_2P: - case CPU_K6_3P: - case CPU_K6_3: - case CPU_K6_2C: - msr.amd_psor = (cpu_s->cpu_type >= CPU_K6_3) ? 0x008cULL : 0x018cULL; - /* FALLTHROUGH */ - case CPU_K6_2: -#if defined(DEV_BRANCH) && defined(USE_AMD_K5) - case CPU_K5: - case CPU_5K86: -#endif - case CPU_K6: - msr.amd_efer = (cpu_s->cpu_type >= CPU_K6_2C) ? 2ULL : 0ULL; - break; + case CPU_WINCHIP: + case CPU_WINCHIP2: + msr.fcr = (1 << 8) | (1 << 9) | (1 << 12) | (1 << 16) | (1 << 19) | (1 << 21); + if (cpu_s->cpu_type == CPU_WINCHIP2) + msr.fcr |= (1 << 18) | (1 << 20); + break; - case CPU_PENTIUMPRO: - case CPU_PENTIUM2: - case CPU_PENTIUM2D: - msr.mtrr_cap = 0x00000508ULL; - /* FALLTHROUGH */ - break; + case CPU_K6_2P: + case CPU_K6_3P: + case CPU_K6_3: + case CPU_K6_2C: + msr.amd_psor = (cpu_s->cpu_type >= CPU_K6_3) ? 0x008cULL : 0x018cULL; + fallthrough; + case CPU_K6_2: +#if defined(DEV_BRANCH) && defined(USE_AMD_K5) + case CPU_K5: + case CPU_5K86: +#endif + case CPU_K6: + msr.amd_efer = (cpu_s->cpu_type >= CPU_K6_2C) ? 2ULL : 0ULL; + break; + + case CPU_PENTIUMPRO: + case CPU_PENTIUM2: + case CPU_PENTIUM2D: + msr.mtrr_cap = 0x00000508ULL; + break; + + case CPU_CYRIX3S: + msr.fcr = (1 << 7) | (1 << 8) | (1 << 9) | (1 << 12) | (1 << 16) | (1 << 18) | (1 << 19) | + (1 << 20) | (1 << 21); + break; } } - void cpu_RDMSR(void) { switch (cpu_s->cpu_type) { - case CPU_IBM386SLC: - case CPU_IBM486SLC: - case CPU_IBM486BL: - EAX = EDX = 0; - switch (ECX) { - case 0x1000: - EAX = msr.ibm_por & ((cpu_s->cpu_type > CPU_IBM386SLC) ? 0xffeff : 0xfeff); - break; + case CPU_IBM386SLC: + case CPU_IBM486SLC: + case CPU_IBM486BL: + EAX = EDX = 0; + switch (ECX) { + case 0x1000: + EAX = msr.ibm_por & ((cpu_s->cpu_type > CPU_IBM386SLC) ? 0xffeff : 0xfeff); + break; - case 0x1001: - EAX = msr.ibm_crcr & 0xffffffffff; - break; + case 0x1001: + EAX = msr.ibm_crcr & 0xffffffffff; + break; - case 0x1002: - if ((cpu_s->cpu_type > CPU_IBM386SLC) && cpu_s->multi) - EAX = msr.ibm_por2 & 0x3f000000; - break; - } - break; + case 0x1002: + if ((cpu_s->cpu_type > CPU_IBM386SLC) && cpu_s->multi) + EAX = msr.ibm_por2 & 0x3f000000; + break; + } + break; - case CPU_WINCHIP: - case CPU_WINCHIP2: - EAX = EDX = 0; - switch (ECX) { - case 0x02: - EAX = msr.tr1; - break; - case 0x0e: - EAX = msr.tr12; - break; - case 0x10: - EAX = tsc & 0xffffffff; - EDX = tsc >> 32; - break; - case 0x11: - EAX = msr.cesr; - break; - case 0x107: - EAX = msr.fcr; - break; - case 0x108: - EAX = msr.fcr2 & 0xffffffff; - EDX = msr.fcr2 >> 32; - break; - case 0x10a: - EAX = cpu_multi & 3; - break; - } - break; + case CPU_WINCHIP: + case CPU_WINCHIP2: + EAX = EDX = 0; + switch (ECX) { + case 0x02: + EAX = msr.tr1; + break; + case 0x0e: + EAX = msr.tr12; + break; + case 0x10: + EAX = tsc & 0xffffffff; + EDX = tsc >> 32; + break; + case 0x11: + EAX = msr.cesr; + break; + case 0x107: + EAX = msr.fcr; + break; + case 0x108: + EAX = msr.fcr2 & 0xffffffff; + EDX = msr.fcr2 >> 32; + break; + case 0x10a: + EAX = cpu_multi & 3; + break; + } + break; - case CPU_CYRIX3S: - EAX = EDX = 0; - switch (ECX) { - case 0x00: case 0x01: - break; - case 0x10: - EAX = tsc & 0xffffffff; - EDX = tsc >> 32; - break; - case 0x2a: - EAX = 0xc4000000; - EDX = 0; - if (cpu_dmulti == 3) - EAX |= ((0 << 25) | (0 << 24) | (0 << 23) | (1 << 22)); - else if (cpu_dmulti == 3.5) - EAX |= ((0 << 25) | (1 << 24) | (0 << 23) | (1 << 22)); - else if (cpu_dmulti == 4) - EAX |= ((0 << 25) | (0 << 24) | (1 << 23) | (0 << 22)); - else if (cpu_dmulti == 4.5) - EAX |= ((0 << 25) | (1 << 24) | (1 << 23) | (0 << 22)); - else if (cpu_dmulti == 5) - EAX |= 0; - else if (cpu_dmulti == 5.5) - EAX |= ((0 << 25) | (1 << 24) | (0 << 23) | (0 << 22)); - else if (cpu_dmulti == 6) - EAX |= ((1 << 25) | (0 << 24) | (1 << 23) | (1 << 22)); - else if (cpu_dmulti == 6.5) - EAX |= ((1 << 25) | (1 << 24) | (1 << 23) | (1 << 22)); - else if (cpu_dmulti == 7) - EAX |= ((1 << 25) | (0 << 24) | (0 << 23) | (1 << 22)); - else - EAX |= ((0 << 25) | (0 << 24) | (0 << 23) | (1 << 22)); - if (cpu_busspeed >= 84000000) - EAX |= (1 << 19); - break; - case 0x1107: - EAX = msr.fcr; - break; - case 0x1108: - EAX = msr.fcr2 & 0xffffffff; - EDX = msr.fcr2 >> 32; - break; - case 0x200: case 0x201: case 0x202: case 0x203: - case 0x204: case 0x205: case 0x206: case 0x207: - case 0x208: case 0x209: case 0x20a: case 0x20b: - case 0x20c: case 0x20d: case 0x20e: case 0x20f: - if (ECX & 1) { - EAX = msr.mtrr_physmask[(ECX - 0x200) >> 1] & 0xffffffff; - EDX = msr.mtrr_physmask[(ECX - 0x200) >> 1] >> 32; - } else { - EAX = msr.mtrr_physbase[(ECX - 0x200) >> 1] & 0xffffffff; - EDX = msr.mtrr_physbase[(ECX - 0x200) >> 1] >> 32; - } - break; - case 0x250: - EAX = msr.mtrr_fix64k_8000 & 0xffffffff; - EDX = msr.mtrr_fix64k_8000 >> 32; - break; - case 0x258: - EAX = msr.mtrr_fix16k_8000 & 0xffffffff; - EDX = msr.mtrr_fix16k_8000 >> 32; - break; - case 0x259: - EAX = msr.mtrr_fix16k_a000 & 0xffffffff; - EDX = msr.mtrr_fix16k_a000 >> 32; - break; - case 0x268: case 0x269: case 0x26a: case 0x26b: - case 0x26c: case 0x26d: case 0x26e: case 0x26f: - EAX = msr.mtrr_fix4k[ECX - 0x268] & 0xffffffff; - EDX = msr.mtrr_fix4k[ECX - 0x268] >> 32; - break; - case 0x2ff: - EAX = msr.mtrr_deftype & 0xffffffff; - EDX = msr.mtrr_deftype >> 32; - break; - } - break; + case CPU_CYRIX3S: + EAX = EDX = 0; + switch (ECX) { + case 0x00: + case 0x01: + break; + case 0x10: + EAX = tsc & 0xffffffff; + EDX = tsc >> 32; + break; + case 0x2a: + EAX = 0xc4000000; + EDX = 0; + if (cpu_dmulti == 3) + EAX |= ((0 << 25) | (0 << 24) | (0 << 23) | (1 << 22)); + else if (cpu_dmulti == 3.5) + EAX |= ((0 << 25) | (1 << 24) | (0 << 23) | (1 << 22)); + else if (cpu_dmulti == 4) + EAX |= ((0 << 25) | (0 << 24) | (1 << 23) | (0 << 22)); + else if (cpu_dmulti == 4.5) + EAX |= ((0 << 25) | (1 << 24) | (1 << 23) | (0 << 22)); + else if (cpu_dmulti == 5) + EAX |= 0; + else if (cpu_dmulti == 5.5) + EAX |= ((0 << 25) | (1 << 24) | (0 << 23) | (0 << 22)); + else if (cpu_dmulti == 6) + EAX |= ((1 << 25) | (0 << 24) | (1 << 23) | (1 << 22)); + else if (cpu_dmulti == 6.5) + EAX |= ((1 << 25) | (1 << 24) | (1 << 23) | (1 << 22)); + else if (cpu_dmulti == 7) + EAX |= ((1 << 25) | (0 << 24) | (0 << 23) | (1 << 22)); + else + EAX |= ((0 << 25) | (0 << 24) | (0 << 23) | (1 << 22)); + if (cpu_busspeed >= 84000000) + EAX |= (1 << 19); + break; + case 0x1107: + EAX = msr.fcr; + break; + case 0x1108: + EAX = msr.fcr2 & 0xffffffff; + EDX = msr.fcr2 >> 32; + break; + case 0x200: + case 0x201: + case 0x202: + case 0x203: + case 0x204: + case 0x205: + case 0x206: + case 0x207: + case 0x208: + case 0x209: + case 0x20a: + case 0x20b: + case 0x20c: + case 0x20d: + case 0x20e: + case 0x20f: + if (ECX & 1) { + EAX = msr.mtrr_physmask[(ECX - 0x200) >> 1] & 0xffffffff; + EDX = msr.mtrr_physmask[(ECX - 0x200) >> 1] >> 32; + } else { + EAX = msr.mtrr_physbase[(ECX - 0x200) >> 1] & 0xffffffff; + EDX = msr.mtrr_physbase[(ECX - 0x200) >> 1] >> 32; + } + break; + case 0x250: + EAX = msr.mtrr_fix64k_8000 & 0xffffffff; + EDX = msr.mtrr_fix64k_8000 >> 32; + break; + case 0x258: + EAX = msr.mtrr_fix16k_8000 & 0xffffffff; + EDX = msr.mtrr_fix16k_8000 >> 32; + break; + case 0x259: + EAX = msr.mtrr_fix16k_a000 & 0xffffffff; + EDX = msr.mtrr_fix16k_a000 >> 32; + break; + case 0x268: + case 0x269: + case 0x26a: + case 0x26b: + case 0x26c: + case 0x26d: + case 0x26e: + case 0x26f: + EAX = msr.mtrr_fix4k[ECX - 0x268] & 0xffffffff; + EDX = msr.mtrr_fix4k[ECX - 0x268] >> 32; + break; + case 0x2ff: + EAX = msr.mtrr_deftype & 0xffffffff; + EDX = msr.mtrr_deftype >> 32; + break; + } + break; #if defined(DEV_BRANCH) && defined(USE_AMD_K5) - case CPU_K5: - case CPU_5K86: + case CPU_K5: + case CPU_5K86: #endif - case CPU_K6: - case CPU_K6_2: - case CPU_K6_2C: - case CPU_K6_3: - case CPU_K6_2P: - case CPU_K6_3P: - EAX = EDX = 0; - switch (ECX) { - case 0x00000000: - case 0x00000001: - break; - case 0x0000000e: - EAX = msr.tr12; - break; - case 0x00000010: - EAX = tsc & 0xffffffff; - EDX = tsc >> 32; - break; - case 0x00000083: - EAX = msr.ecx83 & 0xffffffff; - EDX = msr.ecx83 >> 32; - break; - case 0xc0000080: - EAX = msr.amd_efer & 0xffffffff; - EDX = msr.amd_efer >> 32; - break; - case 0xc0000081: - if (cpu_s->cpu_type < CPU_K6_2) - goto amd_k_invalid_rdmsr; + case CPU_K6: + case CPU_K6_2: + case CPU_K6_2C: + case CPU_K6_3: + case CPU_K6_2P: + case CPU_K6_3P: + EAX = EDX = 0; + switch (ECX) { + case 0x00000000: + case 0x00000001: + break; + case 0x0000000e: + EAX = msr.tr12; + break; + case 0x00000010: + EAX = tsc & 0xffffffff; + EDX = tsc >> 32; + break; + case 0x00000083: + EAX = msr.ecx83 & 0xffffffff; + EDX = msr.ecx83 >> 32; + break; + case 0xc0000080: + EAX = msr.amd_efer & 0xffffffff; + EDX = msr.amd_efer >> 32; + break; + case 0xc0000081: + if (cpu_s->cpu_type < CPU_K6_2) + goto amd_k_invalid_rdmsr; - EAX = msr.star & 0xffffffff; - EDX = msr.star >> 32; - break; - case 0xc0000082: - EAX = msr.amd_whcr & 0xffffffff; - EDX = msr.amd_whcr >> 32; - break; - case 0xc0000085: - if (cpu_s->cpu_type < CPU_K6_2C) - goto amd_k_invalid_rdmsr; + EAX = msr.star & 0xffffffff; + EDX = msr.star >> 32; + break; + case 0xc0000082: + EAX = msr.amd_whcr & 0xffffffff; + EDX = msr.amd_whcr >> 32; + break; + case 0xc0000085: + if (cpu_s->cpu_type < CPU_K6_2C) + goto amd_k_invalid_rdmsr; - EAX = msr.amd_uwccr & 0xffffffff; - EDX = msr.amd_uwccr >> 32; - break; - case 0xc0000086: - if (cpu_s->cpu_type < CPU_K6_2P) - goto amd_k_invalid_rdmsr; + EAX = msr.amd_uwccr & 0xffffffff; + EDX = msr.amd_uwccr >> 32; + break; + case 0xc0000086: + if (cpu_s->cpu_type < CPU_K6_2P) + goto amd_k_invalid_rdmsr; - EAX = msr.amd_epmr & 0xffffffff; - EDX = msr.amd_epmr >> 32; - break; - case 0xc0000087: - if (cpu_s->cpu_type < CPU_K6_2C) - goto amd_k_invalid_rdmsr; + EAX = msr.amd_epmr & 0xffffffff; + EDX = msr.amd_epmr >> 32; + break; + case 0xc0000087: + if (cpu_s->cpu_type < CPU_K6_2C) + goto amd_k_invalid_rdmsr; - EAX = msr.amd_psor & 0xffffffff; - EDX = msr.amd_psor >> 32; - break; - case 0xc0000088: - if (cpu_s->cpu_type < CPU_K6_2C) - goto amd_k_invalid_rdmsr; + EAX = msr.amd_psor & 0xffffffff; + EDX = msr.amd_psor >> 32; + break; + case 0xc0000088: + if (cpu_s->cpu_type < CPU_K6_2C) + goto amd_k_invalid_rdmsr; - EAX = msr.amd_pfir & 0xffffffff; - EDX = msr.amd_pfir >> 32; - break; - case 0xc0000089: - if (cpu_s->cpu_type < CPU_K6_3) - goto amd_k_invalid_rdmsr; + EAX = msr.amd_pfir & 0xffffffff; + EDX = msr.amd_pfir >> 32; + break; + case 0xc0000089: + if (cpu_s->cpu_type < CPU_K6_3) + goto amd_k_invalid_rdmsr; - EAX = msr.amd_l2aar & 0xffffffff; - EDX = msr.amd_l2aar >> 32; - break; - default: + EAX = msr.amd_l2aar & 0xffffffff; + EDX = msr.amd_l2aar >> 32; + break; + default: amd_k_invalid_rdmsr: - x86gpf(NULL, 0); - break; - } - break; + x86gpf(NULL, 0); + break; + } + break; - case CPU_P24T: - case CPU_PENTIUM: - case CPU_PENTIUMMMX: + case CPU_P24T: + case CPU_PENTIUM: + case CPU_PENTIUMMMX: #if defined(DEV_BRANCH) && defined(USE_CYRIX_6X86) - case CPU_Cx6x86: - case CPU_Cx6x86L: - case CPU_CxGX1: - case CPU_Cx6x86MX: - if (cpu_s->cpu_type < CPU_Cx6x86) + case CPU_Cx6x86: + case CPU_Cx6x86L: + case CPU_CxGX1: + case CPU_Cx6x86MX: + if (cpu_s->cpu_type < CPU_Cx6x86) #endif - EAX = EDX = 0; - switch (ECX) { - case 0x00: case 0x01: - break; - case 0x10: - EAX = tsc & 0xffffffff; - EDX = tsc >> 32; - break; - } - cpu_log("RDMSR: ECX = %08X, val = %08X%08X\n", ECX, EDX, EAX); - break; + EAX = EDX = 0; + switch (ECX) { + case 0x00: + case 0x01: + break; + case 0x10: + EAX = tsc & 0xffffffff; + EDX = tsc >> 32; + break; + } + cpu_log("RDMSR: ECX = %08X, val = %08X%08X\n", ECX, EDX, EAX); + break; - case CPU_PENTIUMPRO: - case CPU_PENTIUM2: - case CPU_PENTIUM2D: - EAX = EDX = 0; - switch (ECX) { - case 0x00: case 0x01: - break; - case 0x10: - EAX = tsc & 0xffffffff; - EDX = tsc >> 32; - break; - case 0x17: - if (cpu_s->cpu_type != CPU_PENTIUM2D) - goto i686_invalid_rdmsr; + case CPU_PENTIUMPRO: + case CPU_PENTIUM2: + case CPU_PENTIUM2D: + EAX = EDX = 0; + switch (ECX) { + case 0x00: + case 0x01: + break; + case 0x10: + EAX = tsc & 0xffffffff; + EDX = tsc >> 32; + break; + case 0x17: + if (cpu_s->cpu_type != CPU_PENTIUM2D) + goto i686_invalid_rdmsr; - if (cpu_f->package == CPU_PKG_SLOT2) - EDX |= 0x80000; - else if (cpu_f->package == CPU_PKG_SOCKET370) - EDX |= 0x100000; - break; - case 0x1B: - EAX = msr.apic_base & 0xffffffff; - EDX = msr.apic_base >> 32; - cpu_log("APIC_BASE read : %08X%08X\n", EDX, EAX); - break; - case 0x2a: - EAX = 0xc4000000; - EDX = 0; - if (cpu_dmulti == 2.5) - EAX |= ((0 << 25) | (1 << 24) | (1 << 23) | (1 << 22)); - else if (cpu_dmulti == 3) - EAX |= ((0 << 25) | (0 << 24) | (0 << 23) | (1 << 22)); - else if (cpu_dmulti == 3.5) - EAX |= ((0 << 25) | (1 << 24) | (0 << 23) | (1 << 22)); - else if (cpu_dmulti == 4) - EAX |= ((0 << 25) | (0 << 24) | (1 << 23) | (0 << 22)); - else if (cpu_dmulti == 4.5) - EAX |= ((0 << 25) | (1 << 24) | (1 << 23) | (0 << 22)); - else if (cpu_dmulti == 5) - EAX |= 0; - else if (cpu_dmulti == 5.5) - EAX |= ((0 << 25) | (1 << 24) | (0 << 23) | (0 << 22)); - else if (cpu_dmulti == 6) - EAX |= ((1 << 25) | (0 << 24) | (1 << 23) | (1 << 22)); - else if (cpu_dmulti == 6.5) - EAX |= ((1 << 25) | (1 << 24) | (1 << 23) | (1 << 22)); - else if (cpu_dmulti == 7) - EAX |= ((1 << 25) | (0 << 24) | (0 << 23) | (1 << 22)); - else if (cpu_dmulti == 7.5) - EAX |= ((1 << 25) | (1 << 24) | (0 << 23) | (1 << 22)); - else if (cpu_dmulti == 8) - EAX |= ((1 << 25) | (0 << 24) | (1 << 23) | (0 << 22)); - else - EAX |= ((0 << 25) | (1 << 24) | (1 << 23) | (1 << 22)); - if (cpu_s->cpu_type != CPU_PENTIUMPRO) { - if (cpu_busspeed >= 84000000) - EAX |= (1 << 19); - } - break; - case 0x79: - EAX = msr.ecx79 & 0xffffffff; - EDX = msr.ecx79 >> 32; - break; - case 0x88: case 0x89: case 0x8a: case 0x8b: - EAX = msr.ecx8x[ECX - 0x88] & 0xffffffff; - EDX = msr.ecx8x[ECX - 0x88] >> 32; - break; - case 0xc1: case 0xc2: case 0xc3: case 0xc4: - case 0xc5: case 0xc6: case 0xc7: case 0xc8: - EAX = msr.ia32_pmc[ECX - 0xC1] & 0xffffffff; - EDX = msr.ia32_pmc[ECX - 0xC1] >> 32; - break; - case 0xfe: - EAX = msr.mtrr_cap & 0xffffffff; - EDX = msr.mtrr_cap >> 32; - break; - case 0x116: - EAX = msr.ecx116 & 0xffffffff; - EDX = msr.ecx116 >> 32; - break; - case 0x118: case 0x119: case 0x11a: case 0x11b: - EAX = msr.ecx11x[ECX - 0x118] & 0xffffffff; - EDX = msr.ecx11x[ECX - 0x118] >> 32; - break; - case 0x11e: - EAX = msr.ecx11e & 0xffffffff; - EDX = msr.ecx11e >> 32; - break; - case 0x174: - if (cpu_s->cpu_type == CPU_PENTIUMPRO) - goto i686_invalid_rdmsr; + if (cpu_f->package == CPU_PKG_SLOT2) + EDX |= 0x80000; + else if (cpu_f->package == CPU_PKG_SOCKET370) + EDX |= 0x100000; + break; + case 0x1B: + EAX = msr.apic_base & 0xffffffff; + EDX = msr.apic_base >> 32; + cpu_log("APIC_BASE read : %08X%08X\n", EDX, EAX); + break; + case 0x2a: + EAX = 0xc4000000; + EDX = 0; + if (cpu_dmulti == 2.5) + EAX |= ((0 << 25) | (1 << 24) | (1 << 23) | (1 << 22)); + else if (cpu_dmulti == 3) + EAX |= ((0 << 25) | (0 << 24) | (0 << 23) | (1 << 22)); + else if (cpu_dmulti == 3.5) + EAX |= ((0 << 25) | (1 << 24) | (0 << 23) | (1 << 22)); + else if (cpu_dmulti == 4) + EAX |= ((0 << 25) | (0 << 24) | (1 << 23) | (0 << 22)); + else if (cpu_dmulti == 4.5) + EAX |= ((0 << 25) | (1 << 24) | (1 << 23) | (0 << 22)); + else if (cpu_dmulti == 5) + EAX |= 0; + else if (cpu_dmulti == 5.5) + EAX |= ((0 << 25) | (1 << 24) | (0 << 23) | (0 << 22)); + else if (cpu_dmulti == 6) + EAX |= ((1 << 25) | (0 << 24) | (1 << 23) | (1 << 22)); + else if (cpu_dmulti == 6.5) + EAX |= ((1 << 25) | (1 << 24) | (1 << 23) | (1 << 22)); + else if (cpu_dmulti == 7) + EAX |= ((1 << 25) | (0 << 24) | (0 << 23) | (1 << 22)); + else if (cpu_dmulti == 7.5) + EAX |= ((1 << 25) | (1 << 24) | (0 << 23) | (1 << 22)); + else if (cpu_dmulti == 8) + EAX |= ((1 << 25) | (0 << 24) | (1 << 23) | (0 << 22)); + else + EAX |= ((0 << 25) | (1 << 24) | (1 << 23) | (1 << 22)); + if (cpu_s->cpu_type != CPU_PENTIUMPRO) { + if (cpu_busspeed >= 84000000) + EAX |= (1 << 19); + } + break; + case 0x79: + EAX = msr.ecx79 & 0xffffffff; + EDX = msr.ecx79 >> 32; + break; + case 0x88: + case 0x89: + case 0x8a: + case 0x8b: + EAX = msr.ecx8x[ECX - 0x88] & 0xffffffff; + EDX = msr.ecx8x[ECX - 0x88] >> 32; + break; + case 0xc1: + case 0xc2: + case 0xc3: + case 0xc4: + case 0xc5: + case 0xc6: + case 0xc7: + case 0xc8: + EAX = msr.ia32_pmc[ECX - 0xC1] & 0xffffffff; + EDX = msr.ia32_pmc[ECX - 0xC1] >> 32; + break; + case 0xfe: + EAX = msr.mtrr_cap & 0xffffffff; + EDX = msr.mtrr_cap >> 32; + break; + case 0x116: + EAX = msr.ecx116 & 0xffffffff; + EDX = msr.ecx116 >> 32; + break; + case 0x118: + case 0x119: + case 0x11a: + case 0x11b: + EAX = msr.ecx11x[ECX - 0x118] & 0xffffffff; + EDX = msr.ecx11x[ECX - 0x118] >> 32; + break; + case 0x11e: + EAX = msr.ecx11e & 0xffffffff; + EDX = msr.ecx11e >> 32; + break; + case 0x174: + if (cpu_s->cpu_type == CPU_PENTIUMPRO) + goto i686_invalid_rdmsr; - EAX &= 0xffff0000; - EAX |= msr.sysenter_cs; - EDX = 0x00000000; - break; - case 0x175: - if (cpu_s->cpu_type == CPU_PENTIUMPRO) - goto i686_invalid_rdmsr; + EAX &= 0xffff0000; + EAX |= msr.sysenter_cs; + EDX = 0x00000000; + break; + case 0x175: + if (cpu_s->cpu_type == CPU_PENTIUMPRO) + goto i686_invalid_rdmsr; - EAX = msr.sysenter_esp; - EDX = 0x00000000; - break; - case 0x176: - if (cpu_s->cpu_type == CPU_PENTIUMPRO) - goto i686_invalid_rdmsr; + EAX = msr.sysenter_esp; + EDX = 0x00000000; + break; + case 0x176: + if (cpu_s->cpu_type == CPU_PENTIUMPRO) + goto i686_invalid_rdmsr; - EAX = msr.sysenter_eip; - EDX = 0x00000000; - break; - case 0x179: - EAX = 0x00000105; - EDX = 0x00000000; - break; - case 0x17a: - break; - case 0x17b: - EAX = msr.mcg_ctl & 0xffffffff; - EDX = msr.mcg_ctl >> 32; - break; - case 0x186: - EAX = msr.ecx186 & 0xffffffff; - EDX = msr.ecx186 >> 32; - break; - case 0x187: - EAX = msr.ecx187 & 0xffffffff; - EDX = msr.ecx187 >> 32; - break; - case 0x1e0: - EAX = msr.ecx1e0 & 0xffffffff; - EDX = msr.ecx1e0 >> 32; - break; - case 0x200: case 0x201: case 0x202: case 0x203: - case 0x204: case 0x205: case 0x206: case 0x207: - case 0x208: case 0x209: case 0x20a: case 0x20b: - case 0x20c: case 0x20d: case 0x20e: case 0x20f: - if (ECX & 1) { - EAX = msr.mtrr_physmask[(ECX - 0x200) >> 1] & 0xffffffff; - EDX = msr.mtrr_physmask[(ECX - 0x200) >> 1] >> 32; - } else { - EAX = msr.mtrr_physbase[(ECX - 0x200) >> 1] & 0xffffffff; - EDX = msr.mtrr_physbase[(ECX - 0x200) >> 1] >> 32; - } - break; - case 0x250: - EAX = msr.mtrr_fix64k_8000 & 0xffffffff; - EDX = msr.mtrr_fix64k_8000 >> 32; - break; - case 0x258: - EAX = msr.mtrr_fix16k_8000 & 0xffffffff; - EDX = msr.mtrr_fix16k_8000 >> 32; - break; - case 0x259: - EAX = msr.mtrr_fix16k_a000 & 0xffffffff; - EDX = msr.mtrr_fix16k_a000 >> 32; - break; - case 0x268: case 0x269: case 0x26a: case 0x26b: - case 0x26c: case 0x26d: case 0x26e: case 0x26f: - EAX = msr.mtrr_fix4k[ECX - 0x268] & 0xffffffff; - EDX = msr.mtrr_fix4k[ECX - 0x268] >> 32; - break; - case 0x277: - EAX = msr.pat & 0xffffffff; - EDX = msr.pat >> 32; - break; - case 0x2ff: - EAX = msr.mtrr_deftype & 0xffffffff; - EDX = msr.mtrr_deftype >> 32; - break; - case 0x400: case 0x404: case 0x408: case 0x40c: - case 0x410: - EAX = msr.mca_ctl[(ECX - 0x400) >> 2] & 0xffffffff; - EDX = msr.mca_ctl[(ECX - 0x400) >> 2] >> 32; - break; - case 0x401: case 0x402: case 0x405: case 0x406: - case 0x407: case 0x409: case 0x40d: case 0x40e: - case 0x411: case 0x412: - break; - case 0x570: - EAX = msr.ecx570 & 0xffffffff; - EDX = msr.ecx570 >> 32; - break; - case 0x1002ff: - EAX = msr.ecx1002ff & 0xffffffff; - EDX = msr.ecx1002ff >> 32; - break; - case 0xf0f00250: - EAX = msr.ecxf0f00250 & 0xffffffff; - EDX = msr.ecxf0f00250 >> 32; - break; - case 0xf0f00258: - EAX = msr.ecxf0f00258 & 0xffffffff; - EDX = msr.ecxf0f00258 >> 32; - break; - case 0xf0f00259: - EAX = msr.ecxf0f00259 & 0xffffffff; - EDX = msr.ecxf0f00259 >> 32; - break; - default: + EAX = msr.sysenter_eip; + EDX = 0x00000000; + break; + case 0x179: + EAX = 0x00000105; + EDX = 0x00000000; + break; + case 0x17a: + break; + case 0x17b: + EAX = msr.mcg_ctl & 0xffffffff; + EDX = msr.mcg_ctl >> 32; + break; + case 0x186: + EAX = msr.ecx186 & 0xffffffff; + EDX = msr.ecx186 >> 32; + break; + case 0x187: + EAX = msr.ecx187 & 0xffffffff; + EDX = msr.ecx187 >> 32; + break; + case 0x1d9: + EAX = msr.debug_ctl & 0xffffffff; + EDX = msr.debug_ctl >> 32; + break; + case 0x1e0: + EAX = msr.ecx1e0 & 0xffffffff; + EDX = msr.ecx1e0 >> 32; + break; + case 0x200: + case 0x201: + case 0x202: + case 0x203: + case 0x204: + case 0x205: + case 0x206: + case 0x207: + case 0x208: + case 0x209: + case 0x20a: + case 0x20b: + case 0x20c: + case 0x20d: + case 0x20e: + case 0x20f: + if (ECX & 1) { + EAX = msr.mtrr_physmask[(ECX - 0x200) >> 1] & 0xffffffff; + EDX = msr.mtrr_physmask[(ECX - 0x200) >> 1] >> 32; + } else { + EAX = msr.mtrr_physbase[(ECX - 0x200) >> 1] & 0xffffffff; + EDX = msr.mtrr_physbase[(ECX - 0x200) >> 1] >> 32; + } + break; + case 0x250: + EAX = msr.mtrr_fix64k_8000 & 0xffffffff; + EDX = msr.mtrr_fix64k_8000 >> 32; + break; + case 0x258: + EAX = msr.mtrr_fix16k_8000 & 0xffffffff; + EDX = msr.mtrr_fix16k_8000 >> 32; + break; + case 0x259: + EAX = msr.mtrr_fix16k_a000 & 0xffffffff; + EDX = msr.mtrr_fix16k_a000 >> 32; + break; + case 0x268: + case 0x269: + case 0x26a: + case 0x26b: + case 0x26c: + case 0x26d: + case 0x26e: + case 0x26f: + EAX = msr.mtrr_fix4k[ECX - 0x268] & 0xffffffff; + EDX = msr.mtrr_fix4k[ECX - 0x268] >> 32; + break; + case 0x277: + EAX = msr.pat & 0xffffffff; + EDX = msr.pat >> 32; + break; + case 0x2ff: + EAX = msr.mtrr_deftype & 0xffffffff; + EDX = msr.mtrr_deftype >> 32; + break; + case 0x400: + case 0x404: + case 0x408: + case 0x40c: + case 0x410: + EAX = msr.mca_ctl[(ECX - 0x400) >> 2] & 0xffffffff; + EDX = msr.mca_ctl[(ECX - 0x400) >> 2] >> 32; + break; + case 0x401: + case 0x402: + case 0x405: + case 0x406: + case 0x407: + case 0x409: + case 0x40d: + case 0x40e: + case 0x411: + case 0x412: + break; + case 0x570: + EAX = msr.ecx570 & 0xffffffff; + EDX = msr.ecx570 >> 32; + break; + case 0x1002ff: + EAX = msr.ecx1002ff & 0xffffffff; + EDX = msr.ecx1002ff >> 32; + break; + case 0xf0f00250: + EAX = msr.ecxf0f00250 & 0xffffffff; + EDX = msr.ecxf0f00250 >> 32; + break; + case 0xf0f00258: + EAX = msr.ecxf0f00258 & 0xffffffff; + EDX = msr.ecxf0f00258 >> 32; + break; + case 0xf0f00259: + EAX = msr.ecxf0f00259 & 0xffffffff; + EDX = msr.ecxf0f00259 >> 32; + break; + default: i686_invalid_rdmsr: - cpu_log("RDMSR: Invalid MSR: %08X\n", ECX); - x86gpf(NULL, 0); - break; - } - break; + cpu_log("RDMSR: Invalid MSR: %08X\n", ECX); + x86gpf(NULL, 0); + break; + } + break; } cpu_log("RDMSR %08X %08X%08X\n", ECX, EDX, EAX); } - void cpu_WRMSR(void) { @@ -2526,499 +3027,578 @@ cpu_WRMSR(void) cpu_log("WRMSR %08X %08X%08X\n", ECX, EDX, EAX); switch (cpu_s->cpu_type) { - case CPU_IBM386SLC: - case CPU_IBM486BL: - case CPU_IBM486SLC: - switch (ECX) { - case 0x1000: - msr.ibm_por = EAX & ((cpu_s->cpu_type > CPU_IBM386SLC) ? 0xffeff : 0xfeff); - cpu_cache_int_enabled = (EAX & (1 << 7)); - break; - case 0x1001: - msr.ibm_crcr = EAX & 0xffffffffff; - break; - case 0x1002: - if ((cpu_s->cpu_type > CPU_IBM386SLC) && cpu_s->multi) - msr.ibm_por2 = EAX & 0x3f000000; - break; - } - break; + case CPU_IBM386SLC: + case CPU_IBM486BL: + case CPU_IBM486SLC: + switch (ECX) { + case 0x1000: + msr.ibm_por = EAX & ((cpu_s->cpu_type > CPU_IBM386SLC) ? 0xffeff : 0xfeff); + cpu_cache_int_enabled = (EAX & (1 << 7)); + break; + case 0x1001: + msr.ibm_crcr = EAX & 0xffffffffff; + break; + case 0x1002: + if ((cpu_s->cpu_type > CPU_IBM386SLC) && cpu_s->multi) + msr.ibm_por2 = EAX & 0x3f000000; + break; + } + break; - case CPU_WINCHIP: - case CPU_WINCHIP2: - switch (ECX) { - case 0x02: - msr.tr1 = EAX & 2; - break; - case 0x0e: - msr.tr12 = EAX & 0x228; - break; - case 0x10: - tsc = EAX | ((uint64_t)EDX << 32); - break; - case 0x11: - msr.cesr = EAX & 0xff00ff; - break; - case 0x107: - msr.fcr = EAX; - if (EAX & (1 << 9)) - cpu_features |= CPU_FEATURE_MMX; - else - cpu_features &= ~CPU_FEATURE_MMX; - if (EAX & (1 << 1)) - cpu_features |= CPU_FEATURE_CX8; - else - cpu_features &= ~CPU_FEATURE_CX8; - if ((EAX & (1 << 20)) && cpu_s->cpu_type >= CPU_WINCHIP2) - cpu_features |= CPU_FEATURE_3DNOW; - else - cpu_features &= ~CPU_FEATURE_3DNOW; - if (EAX & (1 << 29)) - CPUID = 0; - else - CPUID = cpu_s->cpuid_model; - break; - case 0x108: - msr.fcr2 = EAX | ((uint64_t)EDX << 32); - break; - case 0x109: - msr.fcr3 = EAX | ((uint64_t)EDX << 32); - break; - } - break; + case CPU_WINCHIP: + case CPU_WINCHIP2: + switch (ECX) { + case 0x02: + msr.tr1 = EAX & 2; + break; + case 0x0e: + msr.tr12 = EAX & 0x228; + break; + case 0x10: + tsc = EAX | ((uint64_t) EDX << 32); + break; + case 0x11: + msr.cesr = EAX & 0xff00ff; + break; + case 0x107: + msr.fcr = EAX; + if (EAX & (1 << 9)) + cpu_features |= CPU_FEATURE_MMX; + else + cpu_features &= ~CPU_FEATURE_MMX; + if (EAX & (1 << 1)) + cpu_features |= CPU_FEATURE_CX8; + else + cpu_features &= ~CPU_FEATURE_CX8; + if ((EAX & (1 << 20)) && cpu_s->cpu_type >= CPU_WINCHIP2) + cpu_features |= CPU_FEATURE_3DNOW; + else + cpu_features &= ~CPU_FEATURE_3DNOW; + if (EAX & (1 << 29)) + CPUID = 0; + else + CPUID = cpu_s->cpuid_model; + break; + case 0x108: + msr.fcr2 = EAX | ((uint64_t) EDX << 32); + break; + case 0x109: + msr.fcr3 = EAX | ((uint64_t) EDX << 32); + break; + } + break; - case CPU_CYRIX3S: - switch (ECX) { - case 0x00: case 0x01: - break; - case 0x10: - tsc = EAX | ((uint64_t)EDX << 32); - break; - case 0x1107: - msr.fcr = EAX; - if (EAX & (1 << 1)) - cpu_features |= CPU_FEATURE_CX8; - else - cpu_features &= ~CPU_FEATURE_CX8; - break; - case 0x1108: - msr.fcr2 = EAX | ((uint64_t)EDX << 32); - break; - case 0x1109: - msr.fcr3 = EAX | ((uint64_t)EDX << 32); - break; - case 0x200: case 0x201: case 0x202: case 0x203: - case 0x204: case 0x205: case 0x206: case 0x207: - case 0x208: case 0x209: case 0x20a: case 0x20b: - case 0x20c: case 0x20d: case 0x20e: case 0x20f: - if (ECX & 1) - msr.mtrr_physmask[(ECX - 0x200) >> 1] = EAX | ((uint64_t)EDX << 32); - else - msr.mtrr_physbase[(ECX - 0x200) >> 1] = EAX | ((uint64_t)EDX << 32); - break; - case 0x250: - msr.mtrr_fix64k_8000 = EAX | ((uint64_t)EDX << 32); - break; - case 0x258: - msr.mtrr_fix16k_8000 = EAX | ((uint64_t)EDX << 32); - break; - case 0x259: - msr.mtrr_fix16k_a000 = EAX | ((uint64_t)EDX << 32); - break; - case 0x268: case 0x269: case 0x26A: case 0x26B: case 0x26C: case 0x26D: case 0x26E: case 0x26F: - msr.mtrr_fix4k[ECX - 0x268] = EAX | ((uint64_t)EDX << 32); - break; - case 0x2ff: - msr.mtrr_deftype = EAX | ((uint64_t)EDX << 32); - break; - } - break; + case CPU_CYRIX3S: + switch (ECX) { + case 0x00: + case 0x01: + break; + case 0x10: + tsc = EAX | ((uint64_t) EDX << 32); + break; + case 0x1107: + msr.fcr = EAX; + if (EAX & (1 << 1)) + cpu_features |= CPU_FEATURE_CX8; + else + cpu_features &= ~CPU_FEATURE_CX8; + if (EAX & (1 << 7)) + cpu_CR4_mask |= CR4_PGE; + else + cpu_CR4_mask &= ~CR4_PGE; + break; + case 0x1108: + msr.fcr2 = EAX | ((uint64_t) EDX << 32); + break; + case 0x1109: + msr.fcr3 = EAX | ((uint64_t) EDX << 32); + break; + case 0x200: + case 0x201: + case 0x202: + case 0x203: + case 0x204: + case 0x205: + case 0x206: + case 0x207: + case 0x208: + case 0x209: + case 0x20a: + case 0x20b: + case 0x20c: + case 0x20d: + case 0x20e: + case 0x20f: + if (ECX & 1) + msr.mtrr_physmask[(ECX - 0x200) >> 1] = EAX | ((uint64_t) EDX << 32); + else + msr.mtrr_physbase[(ECX - 0x200) >> 1] = EAX | ((uint64_t) EDX << 32); + break; + case 0x250: + msr.mtrr_fix64k_8000 = EAX | ((uint64_t) EDX << 32); + break; + case 0x258: + msr.mtrr_fix16k_8000 = EAX | ((uint64_t) EDX << 32); + break; + case 0x259: + msr.mtrr_fix16k_a000 = EAX | ((uint64_t) EDX << 32); + break; + case 0x268: + case 0x269: + case 0x26A: + case 0x26B: + case 0x26C: + case 0x26D: + case 0x26E: + case 0x26F: + msr.mtrr_fix4k[ECX - 0x268] = EAX | ((uint64_t) EDX << 32); + break; + case 0x2ff: + msr.mtrr_deftype = EAX | ((uint64_t) EDX << 32); + break; + } + break; #if defined(DEV_BRANCH) && defined(USE_AMD_K5) - case CPU_K5: - case CPU_5K86: + case CPU_K5: + case CPU_5K86: #endif - case CPU_K6: - case CPU_K6_2: - case CPU_K6_2C: - case CPU_K6_3: - case CPU_K6_2P: - case CPU_K6_3P: - switch (ECX) { - case 0x00: case 0x01: - break; - case 0x0e: - msr.tr12 = EAX & 0x228; - break; - case 0x10: - tsc = EAX | ((uint64_t)EDX << 32); - break; - case 0x83: - msr.ecx83 = EAX | ((uint64_t)EDX << 32); - break; - case 0xc0000080: - temp = EAX | ((uint64_t)EDX << 32); - if (temp & ~1ULL) - x86gpf(NULL, 0); - else - msr.amd_efer = temp; - break; - case 0xc0000081: - if (cpu_s->cpu_type < CPU_K6_2) - goto amd_k_invalid_wrmsr; + case CPU_K6: + case CPU_K6_2: + case CPU_K6_2C: + case CPU_K6_3: + case CPU_K6_2P: + case CPU_K6_3P: + switch (ECX) { + case 0x00: + case 0x01: + break; + case 0x0e: + msr.tr12 = EAX & 0x228; + break; + case 0x10: + tsc = EAX | ((uint64_t) EDX << 32); + break; + case 0x83: + msr.ecx83 = EAX | ((uint64_t) EDX << 32); + break; + case 0xc0000080: + temp = EAX | ((uint64_t) EDX << 32); + if (temp & ~1ULL) + x86gpf(NULL, 0); + else + msr.amd_efer = temp; + break; + case 0xc0000081: + if (cpu_s->cpu_type < CPU_K6_2) + goto amd_k_invalid_wrmsr; - msr.star = EAX | ((uint64_t)EDX << 32); - break; - case 0xc0000082: - msr.amd_whcr = EAX | ((uint64_t)EDX << 32); - break; - case 0xc0000085: - if (cpu_s->cpu_type < CPU_K6_2C) - goto amd_k_invalid_wrmsr; + msr.star = EAX | ((uint64_t) EDX << 32); + break; + case 0xc0000082: + msr.amd_whcr = EAX | ((uint64_t) EDX << 32); + break; + case 0xc0000085: + if (cpu_s->cpu_type < CPU_K6_2C) + goto amd_k_invalid_wrmsr; - msr.amd_uwccr = EAX | ((uint64_t)EDX << 32); - break; - case 0xc0000086: - if (cpu_s->cpu_type < CPU_K6_2P) - goto amd_k_invalid_wrmsr; + msr.amd_uwccr = EAX | ((uint64_t) EDX << 32); + break; + case 0xc0000086: + if (cpu_s->cpu_type < CPU_K6_2P) + goto amd_k_invalid_wrmsr; - msr.amd_epmr = EAX | ((uint64_t)EDX << 32); - break; - case 0xc0000087: - if (cpu_s->cpu_type < CPU_K6_2C) - goto amd_k_invalid_wrmsr; + msr.amd_epmr = EAX | ((uint64_t) EDX << 32); + break; + case 0xc0000087: + if (cpu_s->cpu_type < CPU_K6_2C) + goto amd_k_invalid_wrmsr; - msr.amd_psor = EAX | ((uint64_t)EDX << 32); - break; - case 0xc0000088: - if (cpu_s->cpu_type < CPU_K6_2C) - goto amd_k_invalid_wrmsr; + msr.amd_psor = EAX | ((uint64_t) EDX << 32); + break; + case 0xc0000088: + if (cpu_s->cpu_type < CPU_K6_2C) + goto amd_k_invalid_wrmsr; - msr.amd_pfir = EAX | ((uint64_t)EDX << 32); - break; - case 0xc0000089: - if (cpu_s->cpu_type < CPU_K6_3) - goto amd_k_invalid_wrmsr; + msr.amd_pfir = EAX | ((uint64_t) EDX << 32); + break; + case 0xc0000089: + if (cpu_s->cpu_type < CPU_K6_3) + goto amd_k_invalid_wrmsr; - msr.amd_l2aar = EAX | ((uint64_t)EDX << 32); - break; - default: + msr.amd_l2aar = EAX | ((uint64_t) EDX << 32); + break; + default: amd_k_invalid_wrmsr: - x86gpf(NULL, 0); - break; - } - break; + x86gpf(NULL, 0); + break; + } + break; - case CPU_P24T: - case CPU_PENTIUM: - case CPU_PENTIUMMMX: + case CPU_P24T: + case CPU_PENTIUM: + case CPU_PENTIUMMMX: #if defined(DEV_BRANCH) && defined(USE_CYRIX_6X86) - case CPU_Cx6x86: - case CPU_Cx6x86L: - case CPU_CxGX1: - case CPU_Cx6x86MX: + case CPU_Cx6x86: + case CPU_Cx6x86L: + case CPU_CxGX1: + case CPU_Cx6x86MX: #endif - cpu_log("WRMSR: ECX = %08X, val = %08X%08X\n", ECX, EDX, EAX); - switch (ECX) { - case 0x00: case 0x01: - break; - case 0x10: - tsc = EAX | ((uint64_t)EDX << 32); - break; - case 0x8b: + cpu_log("WRMSR: ECX = %08X, val = %08X%08X\n", ECX, EDX, EAX); + switch (ECX) { + case 0x00: + case 0x01: + break; + case 0x10: + tsc = EAX | ((uint64_t) EDX << 32); + break; + case 0x8b: #if defined(DEV_BRANCH) && defined(USE_CYRIX_6X86) - if (cpu_s->cpu_type < CPU_Cx6x86) { + if (cpu_s->cpu_type < CPU_Cx6x86) { #endif - cpu_log("WRMSR: Invalid MSR: 0x8B\n"); - x86gpf(NULL, 0); /* Needed for Vista to correctly break on Pentium */ + cpu_log("WRMSR: Invalid MSR: 0x8B\n"); + x86gpf(NULL, 0); /* Needed for Vista to correctly break on Pentium */ #if defined(DEV_BRANCH) && defined(USE_CYRIX_6X86) - } + } #endif - break; - } - break; + break; + } + break; - case CPU_PENTIUMPRO: - case CPU_PENTIUM2: - case CPU_PENTIUM2D: - switch (ECX) { - case 0x00: case 0x01: - if (EAX || EDX) - x86gpf(NULL, 0); - break; - case 0x10: - tsc = EAX | ((uint64_t)EDX << 32); - break; - case 0x1b: - cpu_log("APIC_BASE write: %08X%08X\n", EDX, EAX); - // msr.apic_base = EAX | ((uint64_t)EDX << 32); - break; - case 0x2a: - break; - case 0x79: - msr.ecx79 = EAX | ((uint64_t)EDX << 32); - break; - case 0x88: case 0x89: case 0x8a: case 0x8b: - msr.ecx8x[ECX - 0x88] = EAX | ((uint64_t)EDX << 32); - break; - case 0xc1: case 0xc2: case 0xc3: case 0xc4: - case 0xc5: case 0xc6: case 0xc7: case 0xc8: - msr.ia32_pmc[ECX - 0xC1] = EAX | ((uint64_t)EDX << 32); - break; - case 0xfe: - msr.mtrr_cap = EAX | ((uint64_t)EDX << 32); - break; - case 0x116: - msr.ecx116 = EAX | ((uint64_t)EDX << 32); - break; - case 0x118: case 0x119: case 0x11a: case 0x11b: - msr.ecx11x[ECX - 0x118] = EAX | ((uint64_t)EDX << 32); - break; - case 0x11e: - msr.ecx11e = EAX | ((uint64_t)EDX << 32); - break; - case 0x174: - if (cpu_s->cpu_type == CPU_PENTIUMPRO) - goto i686_invalid_wrmsr; + case CPU_PENTIUMPRO: + case CPU_PENTIUM2: + case CPU_PENTIUM2D: + switch (ECX) { + case 0x00: + case 0x01: + if (EAX || EDX) + x86gpf(NULL, 0); + break; + case 0x10: + tsc = EAX | ((uint64_t) EDX << 32); + break; + case 0x1b: + cpu_log("APIC_BASE write: %08X%08X\n", EDX, EAX); +#if 0 + msr.apic_base = EAX | ((uint64_t) EDX << 32); +#endif + break; + case 0x2a: + break; + case 0x79: + msr.ecx79 = EAX | ((uint64_t) EDX << 32); + break; + case 0x88: + case 0x89: + case 0x8a: + case 0x8b: + msr.ecx8x[ECX - 0x88] = EAX | ((uint64_t) EDX << 32); + break; + case 0xc1: + case 0xc2: + case 0xc3: + case 0xc4: + case 0xc5: + case 0xc6: + case 0xc7: + case 0xc8: + msr.ia32_pmc[ECX - 0xC1] = EAX | ((uint64_t) EDX << 32); + break; + case 0xfe: + msr.mtrr_cap = EAX | ((uint64_t) EDX << 32); + break; + case 0x116: + msr.ecx116 = EAX | ((uint64_t) EDX << 32); + break; + case 0x118: + case 0x119: + case 0x11a: + case 0x11b: + msr.ecx11x[ECX - 0x118] = EAX | ((uint64_t) EDX << 32); + break; + case 0x11e: + msr.ecx11e = EAX | ((uint64_t) EDX << 32); + break; + case 0x174: + if (cpu_s->cpu_type == CPU_PENTIUMPRO) + goto i686_invalid_wrmsr; - msr.sysenter_cs = EAX & 0xFFFF; - break; - case 0x175: - if (cpu_s->cpu_type == CPU_PENTIUMPRO) - goto i686_invalid_wrmsr; + msr.sysenter_cs = EAX & 0xFFFF; + break; + case 0x175: + if (cpu_s->cpu_type == CPU_PENTIUMPRO) + goto i686_invalid_wrmsr; - msr.sysenter_esp = EAX; - break; - case 0x176: - if (cpu_s->cpu_type == CPU_PENTIUMPRO) - goto i686_invalid_wrmsr; + msr.sysenter_esp = EAX; + break; + case 0x176: + if (cpu_s->cpu_type == CPU_PENTIUMPRO) + goto i686_invalid_wrmsr; - msr.sysenter_eip = EAX; - break; - case 0x179: - break; - case 0x17a: - if (EAX || EDX) - x86gpf(NULL, 0); - break; - case 0x17b: - msr.mcg_ctl = EAX | ((uint64_t)EDX << 32); - break; - case 0x186: - msr.ecx186 = EAX | ((uint64_t)EDX << 32); - break; - case 0x187: - msr.ecx187 = EAX | ((uint64_t)EDX << 32); - break; - case 0x1e0: - msr.ecx1e0 = EAX | ((uint64_t)EDX << 32); - break; - case 0x200: case 0x201: case 0x202: case 0x203: - case 0x204: case 0x205: case 0x206: case 0x207: - case 0x208: case 0x209: case 0x20a: case 0x20b: - case 0x20c: case 0x20d: case 0x20e: case 0x20f: - if (ECX & 1) - msr.mtrr_physmask[(ECX - 0x200) >> 1] = EAX | ((uint64_t)EDX << 32); - else - msr.mtrr_physbase[(ECX - 0x200) >> 1] = EAX | ((uint64_t)EDX << 32); - break; - case 0x250: - msr.mtrr_fix64k_8000 = EAX | ((uint64_t)EDX << 32); - break; - case 0x258: - msr.mtrr_fix16k_8000 = EAX | ((uint64_t)EDX << 32); - break; - case 0x259: - msr.mtrr_fix16k_a000 = EAX | ((uint64_t)EDX << 32); - break; - case 0x268: case 0x269: case 0x26a: case 0x26b: - case 0x26c: case 0x26d: case 0x26e: case 0x26f: - msr.mtrr_fix4k[ECX - 0x268] = EAX | ((uint64_t)EDX << 32); - break; - case 0x277: - msr.pat = EAX | ((uint64_t)EDX << 32); - break; - case 0x2ff: - msr.mtrr_deftype = EAX | ((uint64_t)EDX << 32); - break; - case 0x400: case 0x404: case 0x408: case 0x40c: - case 0x410: - msr.mca_ctl[(ECX - 0x400) >> 2] = EAX | ((uint64_t)EDX << 32); - break; - case 0x401: case 0x402: case 0x405: case 0x406: - case 0x407: case 0x409: case 0x40d: case 0x40e: - case 0x411: case 0x412: - if (EAX || EDX) - x86gpf(NULL, 0); - break; - case 0x570: - msr.ecx570 = EAX | ((uint64_t)EDX << 32); - break; - case 0x1002ff: - msr.ecx1002ff = EAX | ((uint64_t)EDX << 32); - break; - case 0xf0f00250: - msr.ecxf0f00250 = EAX | ((uint64_t)EDX << 32); - break; - case 0xf0f00258: - msr.ecxf0f00258 = EAX | ((uint64_t)EDX << 32); - break; - case 0xf0f00259: - msr.ecxf0f00259 = EAX | ((uint64_t)EDX << 32); - break; - default: + msr.sysenter_eip = EAX; + break; + case 0x179: + break; + case 0x17a: + if (EAX || EDX) + x86gpf(NULL, 0); + break; + case 0x17b: + msr.mcg_ctl = EAX | ((uint64_t) EDX << 32); + break; + case 0x186: + msr.ecx186 = EAX | ((uint64_t) EDX << 32); + break; + case 0x187: + msr.ecx187 = EAX | ((uint64_t) EDX << 32); + break; + case 0x1d9: + msr.debug_ctl = EAX | ((uint64_t) EDX << 32); + break; + case 0x1e0: + msr.ecx1e0 = EAX | ((uint64_t) EDX << 32); + break; + case 0x200: + case 0x201: + case 0x202: + case 0x203: + case 0x204: + case 0x205: + case 0x206: + case 0x207: + case 0x208: + case 0x209: + case 0x20a: + case 0x20b: + case 0x20c: + case 0x20d: + case 0x20e: + case 0x20f: + if (ECX & 1) + msr.mtrr_physmask[(ECX - 0x200) >> 1] = EAX | ((uint64_t) EDX << 32); + else + msr.mtrr_physbase[(ECX - 0x200) >> 1] = EAX | ((uint64_t) EDX << 32); + break; + case 0x250: + msr.mtrr_fix64k_8000 = EAX | ((uint64_t) EDX << 32); + break; + case 0x258: + msr.mtrr_fix16k_8000 = EAX | ((uint64_t) EDX << 32); + break; + case 0x259: + msr.mtrr_fix16k_a000 = EAX | ((uint64_t) EDX << 32); + break; + case 0x268: + case 0x269: + case 0x26a: + case 0x26b: + case 0x26c: + case 0x26d: + case 0x26e: + case 0x26f: + msr.mtrr_fix4k[ECX - 0x268] = EAX | ((uint64_t) EDX << 32); + break; + case 0x277: + msr.pat = EAX | ((uint64_t) EDX << 32); + break; + case 0x2ff: + msr.mtrr_deftype = EAX | ((uint64_t) EDX << 32); + break; + case 0x400: + case 0x404: + case 0x408: + case 0x40c: + case 0x410: + msr.mca_ctl[(ECX - 0x400) >> 2] = EAX | ((uint64_t) EDX << 32); + break; + case 0x401: + case 0x402: + case 0x405: + case 0x406: + case 0x407: + case 0x409: + case 0x40d: + case 0x40e: + case 0x411: + case 0x412: + if (EAX || EDX) + x86gpf(NULL, 0); + break; + case 0x570: + msr.ecx570 = EAX | ((uint64_t) EDX << 32); + break; + case 0x1002ff: + msr.ecx1002ff = EAX | ((uint64_t) EDX << 32); + break; + case 0xf0f00250: + msr.ecxf0f00250 = EAX | ((uint64_t) EDX << 32); + break; + case 0xf0f00258: + msr.ecxf0f00258 = EAX | ((uint64_t) EDX << 32); + break; + case 0xf0f00259: + msr.ecxf0f00259 = EAX | ((uint64_t) EDX << 32); + break; + default: i686_invalid_wrmsr: - cpu_log("WRMSR: Invalid MSR: %08X\n", ECX); - x86gpf(NULL, 0); - break; - } - break; + cpu_log("WRMSR: Invalid MSR: %08X\n", ECX); + x86gpf(NULL, 0); + break; + } + break; } } - static void -cpu_write(uint16_t addr, uint8_t val, void *priv) +cpu_write(uint16_t addr, uint8_t val, UNUSED(void *priv)) { if (addr == 0xf0) { - /* Writes to F0 clear FPU error and deassert the interrupt. */ - if (is286) - picintc(1 << 13); - else - nmi = 0; - return; + /* Writes to F0 clear FPU error and deassert the interrupt. */ + if (is286) + picintc(1 << 13); + else + nmi = 0; + return; } else if (addr >= 0xf1) - return; /* FPU stuff */ + return; /* FPU stuff */ if (!(addr & 1)) - cyrix_addr = val; - else switch (cyrix_addr) { - case 0xc0: /* CCR0 */ - ccr0 = val; - break; - case 0xc1: /* CCR1 */ - if ((ccr3 & CCR3_SMI_LOCK) && !in_smm) - val = (val & ~(CCR1_USE_SMI | CCR1_SMAC | CCR1_SM3)) | (ccr1 & (CCR1_USE_SMI | CCR1_SMAC | CCR1_SM3)); - ccr1 = val; - break; - case 0xc2: /* CCR2 */ - ccr2 = val; - break; - case 0xc3: /* CCR3 */ - if ((ccr3 & CCR3_SMI_LOCK) && !in_smm) - val = (val & ~(CCR3_NMI_EN)) | (ccr3 & CCR3_NMI_EN) | CCR3_SMI_LOCK; - ccr3 = val; - break; - case 0xcd: - if (!(ccr3 & CCR3_SMI_LOCK) || in_smm) { - cyrix.arr[3].base = (cyrix.arr[3].base & ~0xff000000) | (val << 24); - cyrix.smhr &= ~SMHR_VALID; - } - break; - case 0xce: - if (!(ccr3 & CCR3_SMI_LOCK) || in_smm) { - cyrix.arr[3].base = (cyrix.arr[3].base & ~0x00ff0000) | (val << 16); - cyrix.smhr &= ~SMHR_VALID; - } - break; - case 0xcf: - if (!(ccr3 & CCR3_SMI_LOCK) || in_smm) { - cyrix.arr[3].base = (cyrix.arr[3].base & ~0x0000f000) | ((val & 0xf0) << 8); - if ((val & 0xf) == 0xf) - cyrix.arr[3].size = 1ull << 32; /* 4 GB */ - else if (val & 0xf) - cyrix.arr[3].size = 2048 << (val & 0xf); - else - cyrix.arr[3].size = 0; /* Disabled */ - cyrix.smhr &= ~SMHR_VALID; - } - break; + cyrix_addr = val; + else + switch (cyrix_addr) { + case 0xc0: /* CCR0 */ + ccr0 = val; + break; + case 0xc1: /* CCR1 */ + if ((ccr3 & CCR3_SMI_LOCK) && !in_smm) + val = (val & ~(CCR1_USE_SMI | CCR1_SMAC | CCR1_SM3)) | (ccr1 & (CCR1_USE_SMI | CCR1_SMAC | CCR1_SM3)); + ccr1 = val; + break; + case 0xc2: /* CCR2 */ + ccr2 = val; + break; + case 0xc3: /* CCR3 */ + if ((ccr3 & CCR3_SMI_LOCK) && !in_smm) + val = (val & ~(CCR3_NMI_EN)) | (ccr3 & CCR3_NMI_EN) | CCR3_SMI_LOCK; + ccr3 = val; + break; + case 0xcd: + if (!(ccr3 & CCR3_SMI_LOCK) || in_smm) { + cyrix.arr[3].base = (cyrix.arr[3].base & ~0xff000000) | (val << 24); + cyrix.smhr &= ~SMHR_VALID; + } + break; + case 0xce: + if (!(ccr3 & CCR3_SMI_LOCK) || in_smm) { + cyrix.arr[3].base = (cyrix.arr[3].base & ~0x00ff0000) | (val << 16); + cyrix.smhr &= ~SMHR_VALID; + } + break; + case 0xcf: + if (!(ccr3 & CCR3_SMI_LOCK) || in_smm) { + cyrix.arr[3].base = (cyrix.arr[3].base & ~0x0000f000) | ((val & 0xf0) << 8); + if ((val & 0xf) == 0xf) + cyrix.arr[3].size = 1ULL << 32; /* 4 GB */ + else if (val & 0xf) + cyrix.arr[3].size = 2048 << (val & 0xf); + else + cyrix.arr[3].size = 0; /* Disabled */ + cyrix.smhr &= ~SMHR_VALID; + } + break; - case 0xe8: /* CCR4 */ - if ((ccr3 & 0xf0) == 0x10) { - ccr4 = val; + case 0xe8: /* CCR4 */ + if ((ccr3 & 0xf0) == 0x10) { + ccr4 = val; #if defined(DEV_BRANCH) && defined(USE_CYRIX_6X86) - if (cpu_s->cpu_type >= CPU_Cx6x86) { - if (val & 0x80) - CPUID = cpu_s->cpuid_model; - else - CPUID = 0; - } + if (cpu_s->cpu_type >= CPU_Cx6x86) { + if (val & 0x80) + CPUID = cpu_s->cpuid_model; + else + CPUID = 0; + } #endif - } - break; - case 0xe9: /* CCR5 */ - if ((ccr3 & 0xf0) == 0x10) - ccr5 = val; - break; - case 0xea: /* CCR6 */ - if ((ccr3 & 0xf0) == 0x10) - ccr6 = val; - break; - } + } + break; + case 0xe9: /* CCR5 */ + if ((ccr3 & 0xf0) == 0x10) + ccr5 = val; + break; + case 0xea: /* CCR6 */ + if ((ccr3 & 0xf0) == 0x10) + ccr6 = val; + break; + } } - static uint8_t -cpu_read(uint16_t addr, void *priv) +cpu_read(uint16_t addr, UNUSED(void *priv)) { if (addr == 0xf007) - return 0x7f; + return 0x7f; if (addr >= 0xf0) - return 0xff; /* FPU stuff */ + return 0xff; /* FPU stuff */ if (addr & 1) { - switch (cyrix_addr) { - case 0xc0: - return ccr0; - case 0xc1: - return ccr1; - case 0xc2: - return ccr2; - case 0xc3: - return ccr3; - case 0xe8: - return ((ccr3 & 0xf0) == 0x10) ? ccr4 : 0xff; - case 0xe9: - return ((ccr3 & 0xf0) == 0x10) ? ccr5 : 0xff; - case 0xea: - return ((ccr3 & 0xf0) == 0x10) ? ccr6 : 0xff; - case 0xfe: - return cpu_s->cyrix_id & 0xff; - case 0xff: - return cpu_s->cyrix_id >> 8; - } + switch (cyrix_addr) { + case 0xc0: + return ccr0; + case 0xc1: + return ccr1; + case 0xc2: + return ccr2; + case 0xc3: + return ccr3; + case 0xe8: + return ((ccr3 & 0xf0) == 0x10) ? ccr4 : 0xff; + case 0xe9: + return ((ccr3 & 0xf0) == 0x10) ? ccr5 : 0xff; + case 0xea: + return ((ccr3 & 0xf0) == 0x10) ? ccr6 : 0xff; + case 0xfe: + return cpu_s->cyrix_id & 0xff; + case 0xff: + return cpu_s->cyrix_id >> 8; - if ((cyrix_addr & 0xf0) == 0xc0) - return 0xff; + default: + break; + } - if (cyrix_addr == 0x20 && (cpu_s->cpu_type == CPU_Cx5x86)) - return 0xff; + if ((cyrix_addr & 0xf0) == 0xc0) + return 0xff; + + if (cyrix_addr == 0x20 && (cpu_s->cpu_type == CPU_Cx5x86)) + return 0xff; } return 0xff; } - void #ifdef USE_DYNAREC x86_setopcodes(const OpFn *opcodes, const OpFn *opcodes_0f, - const OpFn *dynarec_opcodes, const OpFn *dynarec_opcodes_0f) + const OpFn *dynarec_opcodes, const OpFn *dynarec_opcodes_0f) { - x86_opcodes = opcodes; - x86_opcodes_0f = opcodes_0f; - x86_dynarec_opcodes = dynarec_opcodes; + x86_opcodes = opcodes; + x86_opcodes_0f = opcodes_0f; + x86_dynarec_opcodes = dynarec_opcodes; x86_dynarec_opcodes_0f = dynarec_opcodes_0f; } #else x86_setopcodes(const OpFn *opcodes, const OpFn *opcodes_0f) { - x86_opcodes = opcodes; + x86_opcodes = opcodes; x86_opcodes_0f = opcodes_0f; } #endif +void +x86_setopcodes_2386(const OpFn *opcodes, const OpFn *opcodes_0f) +{ + x86_2386_opcodes = opcodes; + x86_2386_opcodes_0f = opcodes_0f; +} void cpu_update_waitstates(void) @@ -3026,41 +3606,41 @@ cpu_update_waitstates(void) cpu_s = (CPU *) &cpu_f->cpus[cpu_effective]; if (is486) - cpu_prefetch_width = 16; + cpu_prefetch_width = 16; else - cpu_prefetch_width = cpu_16bitbus ? 2 : 4; + cpu_prefetch_width = cpu_16bitbus ? 2 : 4; if (cpu_cache_int_enabled) { - /* Disable prefetch emulation */ - cpu_prefetch_cycles = 0; + /* Disable prefetch emulation */ + cpu_prefetch_cycles = 0; } else if (cpu_waitstates && (cpu_s->cpu_type >= CPU_286 && cpu_s->cpu_type <= CPU_386DX)) { - /* Waitstates override */ - cpu_prefetch_cycles = cpu_waitstates+1; - cpu_cycles_read = cpu_waitstates+1; - cpu_cycles_read_l = (cpu_16bitbus ? 2 : 1) * (cpu_waitstates+1); - cpu_cycles_write = cpu_waitstates+1; - cpu_cycles_write_l = (cpu_16bitbus ? 2 : 1) * (cpu_waitstates+1); + /* Waitstates override */ + cpu_prefetch_cycles = cpu_waitstates + 1; + cpu_cycles_read = cpu_waitstates + 1; + cpu_cycles_read_l = (cpu_16bitbus ? 2 : 1) * (cpu_waitstates + 1); + cpu_cycles_write = cpu_waitstates + 1; + cpu_cycles_write_l = (cpu_16bitbus ? 2 : 1) * (cpu_waitstates + 1); } else if (cpu_cache_ext_enabled) { - /* Use cache timings */ - cpu_prefetch_cycles = cpu_s->cache_read_cycles; - cpu_cycles_read = cpu_s->cache_read_cycles; - cpu_cycles_read_l = (cpu_16bitbus ? 2 : 1) * cpu_s->cache_read_cycles; - cpu_cycles_write = cpu_s->cache_write_cycles; - cpu_cycles_write_l = (cpu_16bitbus ? 2 : 1) * cpu_s->cache_write_cycles; + /* Use cache timings */ + cpu_prefetch_cycles = cpu_s->cache_read_cycles; + cpu_cycles_read = cpu_s->cache_read_cycles; + cpu_cycles_read_l = (cpu_16bitbus ? 2 : 1) * cpu_s->cache_read_cycles; + cpu_cycles_write = cpu_s->cache_write_cycles; + cpu_cycles_write_l = (cpu_16bitbus ? 2 : 1) * cpu_s->cache_write_cycles; } else { - /* Use memory timings */ - cpu_prefetch_cycles = cpu_s->mem_read_cycles; - cpu_cycles_read = cpu_s->mem_read_cycles; - cpu_cycles_read_l = (cpu_16bitbus ? 2 : 1) * cpu_s->mem_read_cycles; - cpu_cycles_write = cpu_s->mem_write_cycles; - cpu_cycles_write_l = (cpu_16bitbus ? 2 : 1) * cpu_s->mem_write_cycles; + /* Use memory timings */ + cpu_prefetch_cycles = cpu_s->mem_read_cycles; + cpu_cycles_read = cpu_s->mem_read_cycles; + cpu_cycles_read_l = (cpu_16bitbus ? 2 : 1) * cpu_s->mem_read_cycles; + cpu_cycles_write = cpu_s->mem_write_cycles; + cpu_cycles_write_l = (cpu_16bitbus ? 2 : 1) * cpu_s->mem_write_cycles; } if (is486) - cpu_prefetch_cycles = (cpu_prefetch_cycles * 11) / 16; + cpu_prefetch_cycles = (cpu_prefetch_cycles * 11) / 16; cpu_mem_prefetch_cycles = cpu_prefetch_cycles; if (cpu_s->rspeed <= 8000000) - cpu_rom_prefetch_cycles = cpu_mem_prefetch_cycles; + cpu_rom_prefetch_cycles = cpu_mem_prefetch_cycles; } diff --git a/src/cpu/cpu.h b/src/cpu/cpu.h index c140cb7db..9bdcca84c 100644 --- a/src/cpu/cpu.h +++ b/src/cpu/cpu.h @@ -1,45 +1,48 @@ /* - * 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. + * 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. + * This file is part of the 86Box distribution. * - * CPU type handler. + * CPU type handler. * * * - * Authors: Sarah Walker, - * leilei, - * Miran Grca, + * Authors: Sarah Walker, + * leilei, + * Miran Grca, * - * Copyright 2008-2018 Sarah Walker. - * Copyright 2016-2018 leilei. - * Copyright 2016,2018 Miran Grca. + * Copyright 2008-2020 Sarah Walker. + * Copyright 2016-2018 leilei. + * Copyright 2016-2020 Miran Grca. */ #ifndef EMU_CPU_H -# define EMU_CPU_H +#define EMU_CPU_H + +#include "softfloat/softfloat.h" enum { - FPU_NONE, - FPU_8087, - FPU_287, - FPU_287XL, - FPU_387, - FPU_487SX, - FPU_INTERNAL + FPU_NONE, + FPU_8087, + FPU_80187, + FPU_287, + FPU_287XL, + FPU_387, + FPU_487SX, + FPU_INTERNAL }; enum { - CPU_8088 = 1, /* 808x class CPUs */ + CPU_8088 = 1, /* 808x class CPUs */ CPU_8086, -#ifdef USE_NEC_808X - CPU_V20, /* NEC 808x class CPUs - future proofing */ + CPU_V20, /* NEC 808x class CPUs */ CPU_V30, -#endif - CPU_286, /* 286 class CPUs */ - CPU_386SX, /* 386 class CPUs */ + CPU_188, /* 18x class CPUs */ + CPU_186, + CPU_286, /* 286 class CPUs */ + CPU_386SX, /* 386 class CPUs */ CPU_IBM386SLC, CPU_IBM486SLC, CPU_386DX, @@ -47,7 +50,7 @@ enum { CPU_RAPIDCAD, CPU_486SLC, CPU_486DLC, - CPU_i486SX, /* 486 class CPUs */ + CPU_i486SX, /* 486 class CPUs */ CPU_Am486SX, CPU_Cx486S, CPU_i486DX, @@ -60,7 +63,7 @@ enum { CPU_ENH_Am486DX, CPU_Cx5x86, CPU_P24T, - CPU_WINCHIP, /* 586 class CPUs */ + CPU_WINCHIP, /* 586 class CPUs */ CPU_WINCHIP2, CPU_PENTIUM, CPU_PENTIUMMMX, @@ -77,43 +80,47 @@ enum { CPU_K6_2P, CPU_K6_3P, CPU_CYRIX3S, - CPU_PENTIUMPRO, /* 686 class CPUs */ + CPU_PENTIUMPRO, /* 686 class CPUs */ CPU_PENTIUM2, CPU_PENTIUM2D }; enum { - CPU_PKG_8088 = (1 << 0), - CPU_PKG_8088_EUROPC = (1 << 1), - CPU_PKG_8086 = (1 << 2), - CPU_PKG_286 = (1 << 3), - CPU_PKG_386SX = (1 << 4), - CPU_PKG_386DX = (1 << 5), - CPU_PKG_M6117 = (1 << 6), - CPU_PKG_386SLC_IBM = (1 << 7), - CPU_PKG_486SLC = (1 << 8), - CPU_PKG_486SLC_IBM = (1 << 9), - CPU_PKG_486BL = (1 << 10), - CPU_PKG_486DLC = (1 << 11), - CPU_PKG_SOCKET1 = (1 << 12), - CPU_PKG_SOCKET3 = (1 << 13), - CPU_PKG_SOCKET3_PC330 = (1 << 14), - CPU_PKG_STPC = (1 << 15), - CPU_PKG_SOCKET4 = (1 << 16), - CPU_PKG_SOCKET5_7 = (1 << 17), - CPU_PKG_SOCKET8 = (1 << 18), - CPU_PKG_SLOT1 = (1 << 19), - CPU_PKG_SLOT2 = (1 << 20), - CPU_PKG_SOCKET370 = (1 << 21), - CPU_PKG_EBGA368 = (1 << 22) + CPU_PKG_8088 = (1 << 0), + CPU_PKG_8088_EUROPC = (1 << 1), + CPU_PKG_8086 = (1 << 2), + CPU_PKG_188 = (1 << 3), + CPU_PKG_186 = (1 << 4), + CPU_PKG_286 = (1 << 5), + CPU_PKG_386SX = (1 << 6), + CPU_PKG_386DX = (1 << 7), + CPU_PKG_M6117 = (1 << 8), + CPU_PKG_386SLC_IBM = (1 << 9), + CPU_PKG_486SLC = (1 << 10), + CPU_PKG_486SLC_IBM = (1 << 11), + CPU_PKG_486BL = (1 << 12), + CPU_PKG_486DLC = (1 << 13), + CPU_PKG_SOCKET1 = (1 << 14), + CPU_PKG_SOCKET3 = (1 << 15), + CPU_PKG_SOCKET3_PC330 = (1 << 16), + CPU_PKG_STPC = (1 << 17), + CPU_PKG_SOCKET4 = (1 << 18), + CPU_PKG_SOCKET5_7 = (1 << 19), + CPU_PKG_SOCKET8 = (1 << 20), + CPU_PKG_SLOT1 = (1 << 21), + CPU_PKG_SLOT2 = (1 << 22), + CPU_PKG_SLOTA = (1 << 23), + CPU_PKG_SOCKET370 = (1 << 24), + CPU_PKG_SOCKETA = (1 << 25), + CPU_PKG_EBGA368 = (1 << 26) }; - -#define MANU_INTEL 0 -#define MANU_AMD 1 -#define MANU_CYRIX 2 -#define MANU_IDT 3 -#define MANU_NEC 4 +#define MANU_INTEL 0 +#define MANU_AMD 1 +#define MANU_CYRIX 2 +#define MANU_IDT 3 +#define MANU_NEC 4 +#define MANU_IBM 5 #define CPU_SUPPORTS_DYNAREC 1 #define CPU_REQUIRES_DYNAREC 2 @@ -121,284 +128,329 @@ enum { #define CPU_FIXED_MULTIPLIER 8 #if (defined __amd64__ || defined _M_X64) -#define LOOKUP_INV -1LL +# define LOOKUP_INV -1LL #else -#define LOOKUP_INV -1 +# define LOOKUP_INV -1 #endif - -typedef struct { - const char *name; - const char *internal_name; - const int type; +typedef struct fpu_t { + const char *name; + const char *internal_name; + const int type; } FPU; -typedef struct { +typedef struct cpu_t { const char *name; - uint64_t cpu_type; + uint64_t cpu_type; const FPU *fpus; - int rspeed; - double multi; - uint16_t voltage; - uint32_t edx_reset; - uint32_t cpuid_model; - uint16_t cyrix_id; - uint8_t cpu_flags; - int8_t mem_read_cycles, mem_write_cycles; - int8_t cache_read_cycles, cache_write_cycles; - int8_t atclk_div; + uint32_t rspeed; + double multi; + uint16_t voltage; + uint32_t edx_reset; + uint32_t cpuid_model; + uint16_t cyrix_id; + uint8_t cpu_flags; + int8_t mem_read_cycles; + int8_t mem_write_cycles; + int8_t cache_read_cycles; + int8_t cache_write_cycles; + int8_t atclk_div; } CPU; typedef struct { - const uint32_t package; - const char *manufacturer; - const char *name; - const char *internal_name; - const CPU *cpus; + const uint32_t package; + const char *manufacturer; + const char *name; + const char *internal_name; + const CPU *cpus; } cpu_family_t; typedef struct { - const char *family; - const int rspeed; - const double multi; + const char *family; + const uint32_t rspeed; + const double multi; } cpu_legacy_table_t; typedef struct { - const char *machine; + const char *machine; const cpu_legacy_table_t **tables; } cpu_legacy_machine_t; +#define C_FLAG 0x0001 +#define P_FLAG 0x0004 +#define A_FLAG 0x0010 +#define Z_FLAG 0x0040 +#define N_FLAG 0x0080 +#define T_FLAG 0x0100 +#define I_FLAG 0x0200 +#define D_FLAG 0x0400 +#define V_FLAG 0x0800 +#define NT_FLAG 0x4000 +#define MD_FLAG 0x8000 +#define RF_FLAG 0x0001 /* in EFLAGS */ +#define VM_FLAG 0x0002 /* in EFLAGS */ +#define VIF_FLAG 0x0008 /* in EFLAGS */ +#define VIP_FLAG 0x0010 /* in EFLAGS */ +#define VID_FLAG 0x0020 /* in EFLAGS */ -#define C_FLAG 0x0001 -#define P_FLAG 0x0004 -#define A_FLAG 0x0010 -#define Z_FLAG 0x0040 -#define N_FLAG 0x0080 -#define T_FLAG 0x0100 -#define I_FLAG 0x0200 -#define D_FLAG 0x0400 -#define V_FLAG 0x0800 -#define NT_FLAG 0x4000 +#define WP_FLAG 0x10000 /* in CR0 */ -#define RF_FLAG 0x0001 /* in EFLAGS */ -#define VM_FLAG 0x0002 /* in EFLAGS */ -#define VIF_FLAG 0x0008 /* in EFLAGS */ -#define VIP_FLAG 0x0010 /* in EFLAGS */ -#define VID_FLAG 0x0020 /* in EFLAGS */ +#define CR4_VME (1 << 0) /* Virtual 8086 Mode Extensions */ +#define CR4_PVI (1 << 1) /* Protected-mode Virtual Interrupts */ +#define CR4_TSD (1 << 2) /* Time Stamp Disable */ +#define CR4_DE (1 << 3) /* Debugging Extensions */ +#define CR4_PSE (1 << 4) /* Page Size Extension */ +#define CR4_PAE (1 << 5) /* Physical Address Extension */ +#define CR4_MCE (1 << 6) /* Machine Check Exception */ +#define CR4_PGE (1 << 7) /* Page Global Enabled */ +#define CR4_PCE (1 << 8) /* Performance-Monitoring Counter enable */ +#define CR4_OSFXSR (1 << 9) /* Operating system support for FXSAVE and FXRSTOR instructions */ -#define WP_FLAG 0x10000 /* in CR0 */ -#define CR4_VME (1 << 0) -#define CR4_PVI (1 << 1) -#define CR4_PSE (1 << 4) -#define CR4_PAE (1 << 5) +#define CPL ((cpu_state.seg_cs.access >> 5) & 3) -#define CPL ((cpu_state.seg_cs.access>>5)&3) - -#define IOPL ((cpu_state.flags>>12)&3) - -#define IOPLp ((!(msw&1)) || (CPL<=IOPL)) +#define IOPL ((cpu_state.flags >> 12) & 3) +#define IOPLp ((!(msw & 1)) || (CPL <= IOPL)) typedef union { - uint32_t l; - uint16_t w; + uint32_t l; + uint16_t w; struct { - uint8_t l, - h; - } b; + uint8_t l; + uint8_t h; + } b; } x86reg; typedef struct { - uint32_t base; - uint32_t limit; - uint8_t access, ar_high; - uint16_t seg; - uint32_t limit_low, limit_high; - int checked; /*Non-zero if selector is known to be valid*/ + uint32_t base; + uint32_t limit; + uint8_t access; + uint8_t ar_high; + uint16_t seg; + uint32_t limit_low; + uint32_t limit_high; + int checked; /*Non-zero if selector is known to be valid*/ } x86seg; typedef union { - uint64_t q; - int64_t sq; - uint32_t l[2]; - int32_t sl[2]; - uint16_t w[4]; - int16_t sw[4]; - uint8_t b[8]; - int8_t sb[8]; - float f[2]; + uint64_t q; + int64_t sq; + uint32_t l[2]; + int32_t sl[2]; + uint16_t w[4]; + int16_t sw[4]; + uint8_t b[8]; + int8_t sb[8]; + float f[2]; } MMX_REG; typedef struct { /* IDT WinChip and WinChip 2 MSR's */ - uint32_t tr1, tr12; /* 0x00000002, 0x0000000e */ - uint32_t cesr; /* 0x00000011 */ + uint32_t tr1; /* 0x00000002, 0x0000000e */ + uint32_t tr12; /* 0x00000002, 0x0000000e */ + uint32_t cesr; /* 0x00000011 */ /* Pentium Pro, Pentium II Klamath, and Pentium II Deschutes MSR's */ - uint64_t apic_base; /* 0x0000001b - Should the Pentium not also have this? */ - uint64_t ecx79; /* 0x00000079 */ + uint64_t apic_base; /* 0x0000001b - Should the Pentium not also have this? */ + uint64_t ecx79; /* 0x00000079 */ /* AMD K5, 5k86, K6, K6-2, K6-2C, K6-3, K6-2P, and K6-3P MSR's */ - uint64_t ecx83; /* 0x00000083 - AMD K5 and K6 MSR's. */ + uint64_t ecx83; /* 0x00000083 - AMD K5 and K6 MSR's. */ /* Pentium Pro, Pentium II Klamath, and Pentium II Deschutes MSR's */ - uint64_t ecx8x[4]; /* 0x00000088 - 0x0000008b */ - uint64_t ia32_pmc[8]; /* 0x000000c1 - 0x000000c8 */ - uint64_t mtrr_cap; /* 0x000000fe */ + uint64_t ecx8x[4]; /* 0x00000088 - 0x0000008b */ + uint64_t ia32_pmc[8]; /* 0x000000c1 - 0x000000c8 */ + uint64_t mtrr_cap; /* 0x000000fe */ /* IDT WinChip and WinChip 2 MSR's that are also on the VIA Cyrix III */ - uint32_t fcr; /* 0x00000107 (IDT), 0x00001107 (VIA) */ - uint64_t fcr2, fcr3; /* 0x00000108 (IDT), 0x00001108 (VIA) */ + uint32_t fcr; /* 0x00000107 (IDT), 0x00001107 (VIA) */ + uint64_t fcr2; /* 0x00000108 (IDT), 0x00001108 (VIA) */ + uint64_t fcr3; /* 0x00000108 (IDT), 0x00001108 (VIA) */ /* Pentium Pro, Pentium II Klamath, and Pentium II Deschutes MSR's */ - uint64_t ecx116; /* 0x00000116 */ - uint64_t ecx11x[4]; /* 0x00000118 - 0x0000011b */ - uint64_t ecx11e; /* 0x0000011e */ + uint64_t ecx116; /* 0x00000116 */ + uint64_t ecx11x[4]; /* 0x00000118 - 0x0000011b */ + uint64_t ecx11e; /* 0x0000011e */ /* Pentium II Klamath and Pentium II Deschutes MSR's */ - uint16_t sysenter_cs; /* 0x00000174 - SYSENTER/SYSEXIT MSR's */ - uint32_t sysenter_esp; /* 0x00000175 - SYSENTER/SYSEXIT MSR's */ - uint32_t sysenter_eip; /* 0x00000176 - SYSENTER/SYSEXIT MSR's */ + uint16_t sysenter_cs; /* 0x00000174 - SYSENTER/SYSEXIT MSR's */ + uint32_t sysenter_esp; /* 0x00000175 - SYSENTER/SYSEXIT MSR's */ + uint32_t sysenter_eip; /* 0x00000176 - SYSENTER/SYSEXIT MSR's */ /* Pentium Pro, Pentium II Klamath, and Pentium II Deschutes MSR's */ - uint64_t mcg_ctl; /* 0x0000017b - Machine Check Architecture */ + uint64_t mcg_ctl; /* 0x0000017b - Machine Check Architecture */ + uint64_t ecx186; /* 0x00000186, 0x00000187 */ + uint64_t ecx187; /* 0x00000186, 0x00000187 */ /* Pentium Pro, Pentium II Klamath, and Pentium II Deschutes MSR's */ - uint64_t ecx186, ecx187; /* 0x00000186, 0x00000187 */ - uint64_t ecx1e0; /* 0x000001e0 */ + uint64_t debug_ctl; /* 0x000001d9 - Debug Registers Control */ + uint64_t ecx1e0; /* 0x000001e0 */ /* Pentium Pro, Pentium II Klamath, and Pentium II Deschutes MSR's that are also on the VIA Cyrix III */ - uint64_t mtrr_physbase[8]; /* 0x00000200 - 0x0000020f */ - uint64_t mtrr_physmask[8]; /* 0x00000200 - 0x0000020f (ECX & 1) */ - uint64_t mtrr_fix64k_8000; /* 0x00000250 */ - uint64_t mtrr_fix16k_8000; /* 0x00000258 */ - uint64_t mtrr_fix16k_a000; /* 0x00000259 */ - uint64_t mtrr_fix4k[8]; /* 0x00000268 - 0x0000026f */ + uint64_t mtrr_physbase[8]; /* 0x00000200 - 0x0000020f */ + uint64_t mtrr_physmask[8]; /* 0x00000200 - 0x0000020f (ECX & 1) */ + uint64_t mtrr_fix64k_8000; /* 0x00000250 */ + uint64_t mtrr_fix16k_8000; /* 0x00000258 */ + uint64_t mtrr_fix16k_a000; /* 0x00000259 */ + uint64_t mtrr_fix4k[8]; /* 0x00000268 - 0x0000026f */ /* Pentium Pro, Pentium II Klamath, and Pentium II Deschutes MSR's */ - uint64_t pat; /* 0x00000277 */ + uint64_t pat; /* 0x00000277 */ /* Pentium Pro, Pentium II Klamath, and Pentium II Deschutes MSR's that are also on the VIA Cyrix III */ - uint64_t mtrr_deftype; /* 0x000002ff */ + uint64_t mtrr_deftype; /* 0x000002ff */ /* Pentium Pro, Pentium II Klamath, and Pentium II Deschutes MSR's */ - uint64_t mca_ctl[5]; /* 0x00000400, 0x00000404, 0x00000408, 0x0000040c, 0x00000410 - Machine Check Architecture */ - uint64_t ecx570; /* 0x00000570 */ + uint64_t mca_ctl[5]; /* 0x00000400, 0x00000404, 0x00000408, 0x0000040c, 0x00000410 - Machine Check Architecture */ + uint64_t ecx570; /* 0x00000570 */ /* IBM 386SLC, 486SLC, and 486BL MSR's */ - uint64_t ibm_por; /* 0x00001000 - Processor Operation Register */ - uint64_t ibm_crcr; /* 0x00001001 - Cache Region Control Register */ + uint64_t ibm_por; /* 0x00001000 - Processor Operation Register */ + uint64_t ibm_crcr; /* 0x00001001 - Cache Region Control Register */ /* IBM 486SLC and 486BL MSR's */ - uint64_t ibm_por2; /* 0x00001002 - Processor Operation Register */ + uint64_t ibm_por2; /* 0x00001002 - Processor Operation Register */ /* Pentium Pro, Pentium II Klamath, and Pentium II Deschutes MSR's */ - uint64_t ecx1002ff; /* 0x001002ff - MSR used by some Intel AMI boards */ + uint64_t ecx1002ff; /* 0x001002ff - MSR used by some Intel AMI boards */ /* AMD K5, 5k86, K6, K6-2, K6-2C, K6-3, K6-2P, and K6-3P MSR's */ - uint64_t amd_efer; /* 0xc0000080 */ + uint64_t amd_efer; /* 0xc0000080 */ /* AMD K6-2, K6-2C, K6-3, K6-2P, and K6-3P MSR's */ - uint64_t star; /* 0xc0000081 */ + uint64_t star; /* 0xc0000081 */ /* AMD K5, 5k86, K6, K6-2, K6-2C, K6-3, K6-2P, and K6-3P MSR's */ - uint64_t amd_whcr; /* 0xc0000082 */ + uint64_t amd_whcr; /* 0xc0000082 */ /* AMD K6-2C, K6-3, K6-2P, and K6-3P MSR's */ - uint64_t amd_uwccr; /* 0xc0000085 */ + uint64_t amd_uwccr; /* 0xc0000085 */ /* AMD K6-2P and K6-3P MSR's */ - uint64_t amd_epmr; /* 0xc0000086 */ + uint64_t amd_epmr; /* 0xc0000086 */ /* AMD K6-2C, K6-3, K6-2P, and K6-3P MSR's */ - uint64_t amd_psor, amd_pfir; /* 0xc0000087, 0xc0000088 */ + uint64_t amd_psor; /* 0xc0000087, 0xc0000088 */ + uint64_t amd_pfir; /* 0xc0000087, 0xc0000088 */ /* K6-3, K6-2P, and K6-3P MSR's */ - uint64_t amd_l2aar; /* 0xc0000089 */ + uint64_t amd_l2aar; /* 0xc0000089 */ /* Pentium Pro, Pentium II Klamath, and Pentium II Deschutes MSR's */ - uint64_t ecxf0f00250; /* 0xf0f00250 - Some weird long MSR's used by i686 AMI & some Phoenix BIOSes */ - uint64_t ecxf0f00258; /* 0xf0f00258 */ - uint64_t ecxf0f00259; /* 0xf0f00259 */ + uint64_t ecxf0f00250; /* 0xf0f00250 - Some weird long MSR's used by i686 AMI & some Phoenix BIOSes */ + uint64_t ecxf0f00258; /* 0xf0f00258 */ + uint64_t ecxf0f00259; /* 0xf0f00259 */ } msr_t; typedef struct { - x86reg regs[8]; + x86reg regs[8]; - uint8_t tag[8]; + uint8_t tag[8]; - x86seg *ea_seg; - uint32_t eaaddr; + x86seg *ea_seg; + uint32_t eaaddr; - int flags_op; - uint32_t flags_res, - flags_op1, flags_op2; + int flags_op; + uint32_t flags_res; + uint32_t flags_op1; + uint32_t flags_op2; - uint32_t pc, - oldpc, op32; + uint32_t pc; + uint32_t oldpc; + uint32_t op32; - int TOP; + int TOP; union { - struct { - int8_t rm, - mod, - reg; - } rm_mod_reg; - int32_t rm_mod_reg_data; - } rm_data; + struct { + int8_t rm; + int8_t mod; + int8_t reg; + } rm_mod_reg; + int32_t rm_mod_reg_data; + } rm_data; - uint8_t ssegs, ismmx, - abrt, _smi_line; + uint8_t ssegs; + uint8_t ismmx; + uint8_t abrt; + uint8_t _smi_line; + int _cycles; #ifdef FPU_CYCLES - int _cycles, _fpu_cycles, _in_smm; -#else - int _cycles, _in_smm; + int _fpu_cycles; #endif + int _in_smm; - uint16_t npxs, npxc; + uint16_t npxs; + uint16_t npxc; - double ST[8]; + double ST[8]; - uint16_t MM_w4[8]; + uint16_t MM_w4[8]; - MMX_REG MM[8]; + MMX_REG MM[8]; #ifdef USE_NEW_DYNAREC - uint32_t old_fp_control, new_fp_control; -#if defined i386 || defined __i386 || defined __i386__ || defined _X86_ || defined _M_IX86 - uint16_t old_fp_control2, new_fp_control2; -#endif -#if defined i386 || defined __i386 || defined __i386__ || defined _X86_ || defined _M_IX86 || defined __amd64__ || defined _M_X64 - uint32_t trunc_fp_control; -#endif +# if defined(__APPLE__) && defined(__aarch64__) + uint64_t old_fp_control; + uint64_t new_fp_control; +# else + uint32_t old_fp_control; + uint32_t new_fp_control; +# endif +# if defined i386 || defined __i386 || defined __i386__ || defined _X86_ || defined _M_IX86 + uint16_t old_fp_control2; + uint16_t new_fp_control2; +# endif +# if defined i386 || defined __i386 || defined __i386__ || defined _X86_ || defined _M_IX86 || defined __amd64__ || defined _M_X64 + uint32_t trunc_fp_control; +# endif #else - uint16_t old_npxc, new_npxc; + uint16_t old_npxc; + uint16_t new_npxc; #endif - x86seg seg_cs, seg_ds, seg_es, seg_ss, - seg_fs, seg_gs; + x86seg seg_cs; + x86seg seg_ds; + x86seg seg_es; + x86seg seg_ss; + x86seg seg_fs; + x86seg seg_gs; union { - uint32_t l; - uint16_t w; - } CR0; + uint32_t l; + uint16_t w; + } CR0; - uint16_t flags, eflags; + uint16_t flags; + uint16_t eflags; - uint32_t _smbase; + uint32_t _smbase; } cpu_state_t; +typedef struct { + uint16_t cwd; + uint16_t swd; + uint16_t tag; + uint16_t foo; + uint32_t fip; + uint32_t fdp; + uint16_t fcs; + uint16_t fds; + floatx80 st_space[8]; + unsigned char tos; + unsigned char align1; + unsigned char align2; + unsigned char align3; +} fpu_state_t; -#define in_smm cpu_state._in_smm -#define smi_line cpu_state._smi_line - -#define smbase cpu_state._smbase +#define in_smm cpu_state._in_smm +#define smi_line cpu_state._smi_line +#define smbase cpu_state._smbase /*The cpu_state.flags below must match in both cpu_cur_status and block->status for a block to be valid*/ @@ -407,330 +459,384 @@ typedef struct { #define CPU_STATUS_PMODE (1 << 2) #define CPU_STATUS_V86 (1 << 3) #define CPU_STATUS_SMM (1 << 4) -#define CPU_STATUS_FLAGS 0xffff +#ifdef USE_NEW_DYNAREC +# define CPU_STATUS_FLAGS 0xff +#else +# define CPU_STATUS_FLAGS 0xffff +#endif /*If the cpu_state.flags below are set in cpu_cur_status, they must be set in block->status. Otherwise they are ignored*/ #ifdef USE_NEW_DYNAREC -#define CPU_STATUS_NOTFLATDS (1 << 8) -#define CPU_STATUS_NOTFLATSS (1 << 9) -#define CPU_STATUS_MASK 0xff00 +# define CPU_STATUS_NOTFLATDS (1 << 8) +# define CPU_STATUS_NOTFLATSS (1 << 9) +# define CPU_STATUS_MASK 0xff00 #else -#define CPU_STATUS_NOTFLATDS (1 << 16) -#define CPU_STATUS_NOTFLATSS (1 << 17) -#define CPU_STATUS_MASK 0xffff0000 +# define CPU_STATUS_NOTFLATDS (1 << 16) +# define CPU_STATUS_NOTFLATSS (1 << 17) +# define CPU_STATUS_MASK 0xffff0000 #endif #ifdef _MSC_VER -# define COMPILE_TIME_ASSERT(expr) /*nada*/ +# define COMPILE_TIME_ASSERT(expr) /*nada*/ #else -# ifdef EXTREME_DEBUG -# define COMPILE_TIME_ASSERT(expr) typedef char COMP_TIME_ASSERT[(expr) ? 1 : 0]; -# else -# define COMPILE_TIME_ASSERT(expr) /*nada*/ -# endif +# ifdef EXTREME_DEBUG +# define COMPILE_TIME_ASSERT(expr) typedef char COMP_TIME_ASSERT[(expr) ? 1 : 0]; +# else +# define COMPILE_TIME_ASSERT(expr) /*nada*/ +# endif #endif COMPILE_TIME_ASSERT(sizeof(cpu_state_t) <= 128) -#define cpu_state_offset(MEMBER) ((uint8_t)((uintptr_t)&cpu_state.MEMBER - (uintptr_t)&cpu_state - 128)) +#define cpu_state_offset(MEMBER) ((uint8_t) ((uintptr_t) &cpu_state.MEMBER - (uintptr_t) &cpu_state - 128)) -#define EAX cpu_state.regs[0].l -#define AX cpu_state.regs[0].w -#define AL cpu_state.regs[0].b.l -#define AH cpu_state.regs[0].b.h -#define ECX cpu_state.regs[1].l -#define CX cpu_state.regs[1].w -#define CL cpu_state.regs[1].b.l -#define CH cpu_state.regs[1].b.h -#define EDX cpu_state.regs[2].l -#define DX cpu_state.regs[2].w -#define DL cpu_state.regs[2].b.l -#define DH cpu_state.regs[2].b.h -#define EBX cpu_state.regs[3].l -#define BX cpu_state.regs[3].w -#define BL cpu_state.regs[3].b.l -#define BH cpu_state.regs[3].b.h -#define ESP cpu_state.regs[4].l -#define EBP cpu_state.regs[5].l -#define ESI cpu_state.regs[6].l -#define EDI cpu_state.regs[7].l -#define SP cpu_state.regs[4].w -#define BP cpu_state.regs[5].w -#define SI cpu_state.regs[6].w -#define DI cpu_state.regs[7].w +#define EAX cpu_state.regs[0].l +#define AX cpu_state.regs[0].w +#define AL cpu_state.regs[0].b.l +#define AH cpu_state.regs[0].b.h +#define ECX cpu_state.regs[1].l +#define CX cpu_state.regs[1].w +#define CL cpu_state.regs[1].b.l +#define CH cpu_state.regs[1].b.h +#define EDX cpu_state.regs[2].l +#define DX cpu_state.regs[2].w +#define DL cpu_state.regs[2].b.l +#define DH cpu_state.regs[2].b.h +#define EBX cpu_state.regs[3].l +#define BX cpu_state.regs[3].w +#define BL cpu_state.regs[3].b.l +#define BH cpu_state.regs[3].b.h +#define ESP cpu_state.regs[4].l +#define EBP cpu_state.regs[5].l +#define ESI cpu_state.regs[6].l +#define EDI cpu_state.regs[7].l +#define SP cpu_state.regs[4].w +#define BP cpu_state.regs[5].w +#define SI cpu_state.regs[6].w +#define DI cpu_state.regs[7].w -#define cycles cpu_state._cycles +#define cycles cpu_state._cycles #ifdef FPU_CYCLES -#define fpu_cycles cpu_state._fpu_cycles +# define fpu_cycles cpu_state._fpu_cycles #endif -#define cpu_rm cpu_state.rm_data.rm_mod_reg.rm -#define cpu_mod cpu_state.rm_data.rm_mod_reg.mod -#define cpu_reg cpu_state.rm_data.rm_mod_reg.reg - -#define CR4_TSD (1 << 2) -#define CR4_DE (1 << 3) -#define CR4_MCE (1 << 6) -#define CR4_PCE (1 << 8) -#define CR4_OSFXSR (1 << 9) - +#define cpu_rm cpu_state.rm_data.rm_mod_reg.rm +#define cpu_mod cpu_state.rm_data.rm_mod_reg.mod +#define cpu_reg cpu_state.rm_data.rm_mod_reg.reg /* Global variables. */ -extern cpu_state_t cpu_state; +extern cpu_state_t cpu_state; +extern fpu_state_t fpu_state; -extern const cpu_family_t cpu_families[]; +extern const cpu_family_t cpu_families[]; extern const cpu_legacy_machine_t cpu_legacy_table[]; -extern cpu_family_t *cpu_f; -extern CPU *cpu_s; -extern int cpu_override; +extern cpu_family_t *cpu_f; +extern CPU *cpu_s; +extern int cpu_override; -extern int cpu_isintel; -extern int cpu_iscyrix; -extern int cpu_16bitbus, cpu_64bitbus; -extern int cpu_busspeed, cpu_pci_speed; -extern int cpu_multi; -extern double cpu_dmulti; -extern double fpu_multi; -extern int cpu_cyrix_alignment; /*Cyrix 5x86/6x86 only has data misalignment - penalties when crossing 8-byte boundaries*/ +extern int cpu_isintel; +extern int cpu_iscyrix; +extern int cpu_16bitbus; +extern int cpu_64bitbus; +extern int cpu_pci_speed; +extern int cpu_multi; +extern double cpu_dmulti; +extern double fpu_multi; +extern double cpu_busspeed; +extern int cpu_cyrix_alignment; /*Cyrix 5x86/6x86 only has data misalignment + penalties when crossing 8-byte boundaries*/ -extern int is8086, is286, is386, is486; -extern int is_am486, is_am486dxl, is_pentium, is_k5, is_k6, is_p6, is_cxsmm; -extern int hascache; -extern int isibm486; -extern int is_rapidcad; -extern int hasfpu; -#define CPU_FEATURE_RDTSC (1 << 0) -#define CPU_FEATURE_MSR (1 << 1) -#define CPU_FEATURE_MMX (1 << 2) -#define CPU_FEATURE_CR4 (1 << 3) -#define CPU_FEATURE_VME (1 << 4) -#define CPU_FEATURE_CX8 (1 << 5) -#define CPU_FEATURE_3DNOW (1 << 6) +extern int is8086; +extern int is186; +extern int is286; +extern int is386; +extern int is6117; +extern int is486; +extern int is_am486; +extern int is_am486dxl; +extern int is_pentium; +extern int is_k5; +extern int is_k6; +extern int is_p6; +extern int is_cxsmm; +extern int hascache; +extern int isibm486; +extern int is_nec; +extern int is_rapidcad; +extern int hasfpu; +#define CPU_FEATURE_RDTSC (1 << 0) +#define CPU_FEATURE_MSR (1 << 1) +#define CPU_FEATURE_MMX (1 << 2) +#define CPU_FEATURE_CR4 (1 << 3) +#define CPU_FEATURE_VME (1 << 4) +#define CPU_FEATURE_CX8 (1 << 5) +#define CPU_FEATURE_3DNOW (1 << 6) +#define CPU_FEATURE_SYSCALL (1 << 7) +#define CPU_FEATURE_3DNOWE (1 << 8) -extern uint32_t cpu_features; +extern uint32_t cpu_features; -extern int smi_latched, smm_in_hlt; -extern int smi_block; +extern int smi_latched; +extern int smm_in_hlt; +extern int smi_block; #ifdef USE_NEW_DYNAREC -extern uint16_t cpu_cur_status; +extern uint16_t cpu_cur_status; #else -extern uint32_t cpu_cur_status; +extern uint32_t cpu_cur_status; #endif -extern uint64_t cpu_CR4_mask; -extern uint64_t tsc; -extern msr_t msr; -extern uint8_t opcode; -extern int cgate16; -extern int cpl_override; -extern int CPUID; -extern uint64_t xt_cpu_multi; -extern int isa_cycles, cpu_inited; -extern uint32_t oldds,oldss,olddslimit,oldsslimit,olddslimitw,oldsslimitw; -extern uint32_t pccache; -extern uint8_t *pccache2; +extern uint64_t cpu_CR4_mask; +extern uint64_t tsc; +extern msr_t msr; +extern uint8_t opcode; +extern int cpl_override; +extern int CPUID; +extern uint64_t xt_cpu_multi; +extern int isa_cycles; +extern int cpu_inited; +extern uint32_t oldds; +extern uint32_t oldss; +extern uint32_t olddslimit; +extern uint32_t oldsslimit; +extern uint32_t olddslimitw; +extern uint32_t oldsslimitw; +extern uint32_t pccache; +extern uint8_t *pccache2; -extern double bus_timing, isa_timing, pci_timing, agp_timing; -extern uint64_t pmc[2]; -extern uint16_t temp_seg_data[4]; -extern uint16_t cs_msr; -extern uint32_t esp_msr; -extern uint32_t eip_msr; +extern double bus_timing; +extern double isa_timing; +extern double pci_timing; +extern double agp_timing; +extern uint64_t pmc[2]; +extern uint16_t temp_seg_data[4]; +extern uint16_t cs_msr; +extern uint32_t esp_msr; +extern uint32_t eip_msr; /* For the AMD K6. */ -extern uint64_t amd_efer, star; +extern uint64_t amd_efer; +extern uint64_t star; #define FPU_CW_Reserved_Bits (0xe0c0) -#define cr0 cpu_state.CR0.l -#define msw cpu_state.CR0.w -extern uint32_t cr2, cr3, cr4; -extern uint32_t dr[8]; -extern uint32_t _tr[8]; -extern uint32_t cache_index; -extern uint8_t _cache[2048]; - +#define cr0 cpu_state.CR0.l +#define msw cpu_state.CR0.w +extern uint32_t cr2; +extern uint32_t cr3; +extern uint32_t cr4; +extern uint32_t dr[8]; +extern uint32_t _tr[8]; +extern uint32_t cache_index; +extern uint8_t _cache[2048]; /*Segments - _cs,_ds,_es,_ss are the segment structures CS,DS,ES,SS is the 16-bit data cs,ds,es,ss are defines to the bases*/ -extern x86seg gdt,ldt,idt,tr; -extern x86seg _oldds; -#define CS cpu_state.seg_cs.seg -#define DS cpu_state.seg_ds.seg -#define ES cpu_state.seg_es.seg -#define SS cpu_state.seg_ss.seg -#define FS cpu_state.seg_fs.seg -#define GS cpu_state.seg_gs.seg -#define cs cpu_state.seg_cs.base -#define ds cpu_state.seg_ds.base -#define es cpu_state.seg_es.base -#define ss cpu_state.seg_ss.base -#define fs_seg cpu_state.seg_fs.base -#define gs cpu_state.seg_gs.base +extern x86seg gdt; +extern x86seg ldt; +extern x86seg idt; +extern x86seg tr; +extern x86seg _oldds; +#define CS cpu_state.seg_cs.seg +#define DS cpu_state.seg_ds.seg +#define ES cpu_state.seg_es.seg +#define SS cpu_state.seg_ss.seg +#define FS cpu_state.seg_fs.seg +#define GS cpu_state.seg_gs.seg +#define cs cpu_state.seg_cs.base +#define ds cpu_state.seg_ds.base +#define es cpu_state.seg_es.base +#define ss cpu_state.seg_ss.base +#define fs_seg cpu_state.seg_fs.base +#define gs cpu_state.seg_gs.base +#define ISA_CYCLES(x) (x * isa_cycles) -#define ISA_CYCLES(x) (x * isa_cycles) +extern int cpu_cycles_read; +extern int cpu_cycles_read_l; +extern int cpu_cycles_write; +extern int cpu_cycles_write_l; +extern int cpu_prefetch_cycles; +extern int cpu_prefetch_width; +extern int cpu_mem_prefetch_cycles; +extern int cpu_rom_prefetch_cycles; +extern int cpu_waitstates; +extern int cpu_cache_int_enabled; +extern int cpu_cache_ext_enabled; +extern int cpu_isa_speed; +extern int cpu_pci_speed; +extern int cpu_agp_speed; -extern int cpu_cycles_read, cpu_cycles_read_l, cpu_cycles_write, cpu_cycles_write_l; -extern int cpu_prefetch_cycles, cpu_prefetch_width, cpu_mem_prefetch_cycles, cpu_rom_prefetch_cycles; -extern int cpu_waitstates; -extern int cpu_cache_int_enabled, cpu_cache_ext_enabled; -extern int cpu_isa_speed, cpu_pci_speed, cpu_agp_speed; +extern int timing_rr; +extern int timing_mr; +extern int timing_mrl; +extern int timing_rm; +extern int timing_rml; +extern int timing_mm; +extern int timing_mml; +extern int timing_bt; +extern int timing_bnt; +extern int timing_int; +extern int timing_int_rm; +extern int timing_int_v86; +extern int timing_int_pm; +extern int timing_int_pm_outer; +extern int timing_iret_rm; +extern int timing_iret_v86; +extern int timing_iret_pm; +extern int timing_iret_pm_outer; +extern int timing_call_rm; +extern int timing_call_pm; +extern int timing_call_pm_gate; +extern int timing_call_pm_gate_inner; +extern int timing_retf_rm; +extern int timing_retf_pm; +extern int timing_retf_pm_outer; +extern int timing_jmp_rm; +extern int timing_jmp_pm; +extern int timing_jmp_pm_gate; +extern int timing_misaligned; -extern int timing_rr; -extern int timing_mr, timing_mrl; -extern int timing_rm, timing_rml; -extern int timing_mm, timing_mml; -extern int timing_bt, timing_bnt; -extern int timing_int, timing_int_rm, timing_int_v86, timing_int_pm; -extern int timing_int_pm_outer, timing_iret_rm, timing_iret_v86, timing_iret_pm; -extern int timing_iret_pm_outer, timing_call_rm, timing_call_pm; -extern int timing_call_pm_gate, timing_call_pm_gate_inner; -extern int timing_retf_rm, timing_retf_pm, timing_retf_pm_outer; -extern int timing_jmp_rm, timing_jmp_pm, timing_jmp_pm_gate; -extern int timing_misaligned; - -extern int in_sys, unmask_a20_in_smm; -extern int cycles_main; -extern uint32_t old_rammask; +extern int in_sys; +extern int unmask_a20_in_smm; +extern int cycles_main; +extern uint32_t old_rammask; #ifdef USE_ACYCS -extern int acycs; +extern int acycs; #endif -extern int pic_pending, is_vpc; -extern int soft_reset_mask, alt_access; -extern int cpu_end_block_after_ins; - -extern uint16_t cpu_fast_off_count, cpu_fast_off_val; -extern uint32_t cpu_fast_off_flags; +extern int pic_pending; +extern int is_vpc; +extern int soft_reset_mask; +extern int alt_access; +extern int cpu_end_block_after_ins; +extern uint16_t cpu_fast_off_count; +extern uint16_t cpu_fast_off_val; +extern uint32_t cpu_fast_off_flags; /* Functions. */ extern int cpu_has_feature(int feature); -#ifdef USE_NEW_DYNAREC -extern void loadseg_dynarec(uint16_t seg, x86seg *s); -extern int loadseg(uint16_t seg, x86seg *s); -extern void loadcs(uint16_t seg); -#else -extern void loadseg(uint16_t seg, x86seg *s); -extern void loadcs(uint16_t seg); -#endif +extern char *cpu_current_pc(char *bufp); -extern char *cpu_current_pc(char *bufp); +extern void cpu_update_waitstates(void); +extern void cpu_set(void); +extern void cpu_close(void); +extern void cpu_set_isa_speed(int speed); +extern void cpu_set_pci_speed(int speed); +extern void cpu_set_isa_pci_div(int div); +extern void cpu_set_agp_speed(int speed); -extern void cpu_update_waitstates(void); -extern void cpu_set(void); -extern void cpu_close(void); -extern void cpu_set_isa_speed(int speed); -extern void cpu_set_pci_speed(int speed); -extern void cpu_set_isa_pci_div(int div); -extern void cpu_set_agp_speed(int speed); +extern void cpu_CPUID(void); +extern void cpu_RDMSR(void); +extern void cpu_WRMSR(void); -extern void cpu_CPUID(void); -extern void cpu_RDMSR(void); -extern void cpu_WRMSR(void); - -extern int checkio(uint32_t port); -extern void codegen_block_end(void); -extern void codegen_reset(void); -extern void cpu_set_edx(void); -extern int divl(uint32_t val); -extern void execx86(int cycs); -extern void enter_smm(int in_hlt); -extern void enter_smm_check(int in_hlt); -extern void leave_smm(void); -extern void exec386(int cycs); -extern void exec386_dynarec(int cycs); -extern int idivl(int32_t val); -#ifdef USE_NEW_DYNAREC -extern void loadcscall(uint16_t seg, uint32_t old_pc); -extern void loadcsjmp(uint16_t seg, uint32_t old_pc); -extern void pmodeint(int num, int soft); -extern void pmoderetf(int is32, uint16_t off); -extern void pmodeiret(int is32); -#else -extern void loadcscall(uint16_t seg); -extern void loadcsjmp(uint16_t seg, uint32_t old_pc); -extern void pmodeint(int num, int soft); -extern void pmoderetf(int is32, uint16_t off); -extern void pmodeiret(int is32); -#endif -extern void resetmcr(void); -extern void resetx86(void); -extern void refreshread(void); -extern void resetreadlookup(void); -extern void softresetx86(void); -extern void hardresetx86(void); -extern void x86_int(int num); -extern void x86_int_sw(int num); -extern int x86_int_sw_rm(int num); -extern void x86gpf(char *s, uint16_t error); -extern void x86np(char *s, uint16_t error); -extern void x86ss(char *s, uint16_t error); -extern void x86ts(char *s, uint16_t error); +extern int checkio(uint32_t port, int mask); +extern void codegen_block_end(void); +extern void codegen_reset(void); +extern void cpu_set_edx(void); +extern int divl(uint32_t val); +extern void execx86(int32_t cycs); +extern void enter_smm(int in_hlt); +extern void enter_smm_check(int in_hlt); +extern void leave_smm(void); +extern void exec386_2386(int32_t cycs); +extern void exec386(int32_t cycs); +extern void exec386_dynarec(int32_t cycs); +extern int idivl(int32_t val); +extern void resetmcr(void); +extern void resetx86(void); +extern void refreshread(void); +extern void resetreadlookup(void); +extern void softresetx86(void); +extern void hardresetx86(void); +extern void x86_int(int num); +extern void x86_int_sw(int num); +extern int x86_int_sw_rm(int num); #ifdef ENABLE_808X_LOG -extern void dumpregs(int __force); -extern void x87_dumpregs(void); -extern void x87_reset(void); +extern void dumpregs(int __force); +extern void x87_dumpregs(void); +extern void x87_reset(void); #endif -extern int cpu_effective, cpu_alt_reset; -extern void cpu_dynamic_switch(int new_cpu); +extern int cpu_effective; +extern int cpu_alt_reset; +extern void cpu_dynamic_switch(int new_cpu); -extern void cpu_ven_reset(void); -extern void update_tsc(void); +extern void cpu_ven_reset(void); +extern void update_tsc(void); -extern int sysenter(uint32_t fetchdat); -extern int sysexit(uint32_t fetchdat); -extern int syscall_op(uint32_t fetchdat); -extern int sysret(uint32_t fetchdat); +extern int sysenter(uint32_t fetchdat); +extern int sysexit(uint32_t fetchdat); +extern int syscall_op(uint32_t fetchdat); +extern int sysret(uint32_t fetchdat); extern cpu_family_t *cpu_get_family(const char *internal_name); -extern uint8_t cpu_is_eligible(const cpu_family_t *cpu_family, int cpu, int machine); -extern uint8_t cpu_family_is_eligible(const cpu_family_t *cpu_family, int machine); -extern int fpu_get_type(const cpu_family_t *cpu_family, int cpu, const char *internal_name); -extern const char *fpu_get_internal_name(const cpu_family_t *cpu_family, int cpu, int type); -extern const char *fpu_get_name_from_index(const cpu_family_t *cpu_family, int cpu, int c); -extern int fpu_get_type_from_index(const cpu_family_t *cpu_family, int cpu, int c); +extern uint8_t cpu_is_eligible(const cpu_family_t *cpu_family, int cpu, int machine); +extern uint8_t cpu_family_is_eligible(const cpu_family_t *cpu_family, int machine); +extern int fpu_get_type(const cpu_family_t *cpu_family, int cpu, const char *internal_name); +extern const char *fpu_get_internal_name(const cpu_family_t *cpu_family, int cpu, int type); +extern const char *fpu_get_name_from_index(const cpu_family_t *cpu_family, int cpu, int c); +extern int fpu_get_type_from_index(const cpu_family_t *cpu_family, int cpu, int c); void cyrix_load_seg_descriptor(uint32_t addr, x86seg *seg); void cyrix_write_seg_descriptor(uint32_t addr, x86seg *seg); -#define SMHR_VALID (1 << 0) +#define SMHR_VALID (1 << 0) #define SMHR_ADDR_MASK (0xfffffffc) -typedef struct -{ - struct - { - uint32_t base; - uint64_t size; - } arr[8]; - uint32_t smhr; +typedef struct { + struct { + uint32_t base; + uint64_t size; + } arr[8]; + uint32_t smhr; } cyrix_t; +extern uint32_t addr64; +extern uint32_t addr64_2; +extern uint32_t addr64a[8]; +extern uint32_t addr64a_2[8]; -extern uint32_t addr64, addr64_2; -extern uint32_t addr64a[8], addr64a_2[8]; +extern int soft_reset_pci; -extern int soft_reset_pci; +extern int reset_on_hlt; +extern int hlt_reset_pending; -extern int reset_on_hlt, hlt_reset_pending; +extern cyrix_t cyrix; -extern cyrix_t cyrix; +extern int prefetch_prefixes; -extern uint8_t use_custom_nmi_vector; -extern uint32_t custom_nmi_vector; +extern uint8_t use_custom_nmi_vector; +extern uint32_t custom_nmi_vector; -extern void (*cpu_exec)(int cycs); -extern uint8_t do_translate, do_translate2; +extern void (*cpu_exec)(int32_t cycs); +extern uint8_t do_translate; +extern uint8_t do_translate2; -extern void reset_808x(int hard); +extern void SF_FPU_reset(void); -#endif /*EMU_CPU_H*/ +extern void reset_808x(int hard); +extern void interrupt_808x(uint16_t addr); + +extern void cpu_register_fast_off_handler(void *timer); +extern void cpu_fast_off_advance(void); +extern void cpu_fast_off_period_set(uint16_t vla, double period); +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); +extern void prefetch_flush(void); + +extern void prefetch_run(int instr_cycles, int bytes, int modrm, int reads, int reads_l, int writes, int writes_l, int ea32); + +#endif /*EMU_CPU_H*/ diff --git a/src/cpu/cpu_table.c b/src/cpu/cpu_table.c index bb0e04637..0b37ce2d6 100644 --- a/src/cpu/cpu_table.c +++ b/src/cpu/cpu_table.c @@ -1,28 +1,28 @@ /* - * 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. + * 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. + * This file is part of the 86Box distribution. * - * Define all known processor types. + * Define all known processor types. * * * - * Authors: Sarah Walker, - * leilei, - * Miran Grca, - * Fred N. van Kempen, - * RichardG, - * dob205, + * Authors: Sarah Walker, + * leilei, + * Miran Grca, + * Fred N. van Kempen, + * RichardG, + * dob205, * - * Copyright 2008-2019 Sarah Walker. - * Copyright 2016-2019 leilei. - * Copyright 2016-2019 Miran Grca. - * Copyright 2017-2019 Fred N. van Kempen. - * Copyright 2020 RichardG. - * Copyright 2021 dob205. + * Copyright 2008-2019 Sarah Walker. + * Copyright 2016-2019 leilei. + * Copyright 2016-2019 Miran Grca. + * Copyright 2017-2020 Fred N. van Kempen. + * Copyright 2020 RichardG. + * Copyright 2021 dob205. */ #include #include @@ -32,2004 +32,2896 @@ #include "cpu.h" #include <86box/machine.h> -FPU fpus_none[] = -{ - {"None", "none", FPU_NONE}, - {NULL, NULL, 0} +FPU fpus_none[] = { + { .name = "None", .internal_name = "none", .type = FPU_NONE }, + { .name = NULL, .internal_name = NULL, .type = 0 } }; -FPU fpus_8088[] = -{ - {"None", "none", FPU_NONE}, - {"8087", "8087", FPU_8087}, - {NULL, NULL, 0} +FPU fpus_8088[] = { + { .name = "None", .internal_name = "none", .type = FPU_NONE }, + { .name = "8087", .internal_name = "8087", .type = FPU_8087 }, + { .name = NULL, .internal_name = NULL, .type = 0 } }; -FPU fpus_80286[] = -{ - {"None", "none", FPU_NONE}, - {"287", "287", FPU_287}, - {"287XL","287xl", FPU_287XL}, - {NULL, NULL, 0} +FPU fpus_80186[] = { + { .name = "None", .internal_name = "none", .type = FPU_NONE }, + { .name = "8087", .internal_name = "8087", .type = FPU_8087 }, + { .name = "80187", .internal_name = "80187", .type = FPU_80187 }, + { .name = NULL, .internal_name = NULL, .type = 0 } }; -FPU fpus_80386[] = -{ - {"None", "none", FPU_NONE}, - {"387", "387", FPU_387}, - {NULL, NULL, 0} +FPU fpus_80286[] = { + { .name = "None", .internal_name = "none", .type = FPU_NONE }, + { .name = "287", .internal_name = "287", .type = FPU_287 }, + { .name = "287XL", .internal_name = "287xl", .type = FPU_287XL }, + { .name = NULL, .internal_name = NULL, .type = 0 } }; -FPU fpus_486sx[] = -{ - {"None", "none", FPU_NONE}, - {"487SX","487sx", FPU_487SX}, - {NULL, NULL, 0} +FPU fpus_80386[] = { + { .name = "None", .internal_name = "none", .type = FPU_NONE }, + { .name = "387", .internal_name = "387", .type = FPU_387 }, + { .name = NULL, .internal_name = NULL, .type = 0 } }; -FPU fpus_internal[] = -{ - {"Internal", "internal", FPU_INTERNAL}, - {NULL, NULL, 0} +FPU fpus_486sx[] = { + { .name = "None", .internal_name = "none", .type = FPU_NONE }, + { .name = "487SX", .internal_name = "487sx", .type = FPU_487SX }, + { .name = NULL, .internal_name = NULL, .type = 0 } +}; +FPU fpus_internal[] = { + { .name = "Internal", .internal_name = "internal", .type = FPU_INTERNAL }, + { .name = NULL, .internal_name = NULL, .type = 0 } }; - const cpu_family_t cpu_families[] = { + // clang-format off { - .package = CPU_PKG_8088, - .manufacturer = "Intel", - .name = "8088", - .internal_name = "8088", - .cpus = (const CPU[]) { - {"4.77", CPU_8088, fpus_8088, 4772728, 1, 5000, 0, 0, 0, 0, 0,0,0,0, 1}, - {"7.16", CPU_8088, fpus_8088, 7159092, 1, 5000, 0, 0, 0, 0, 0,0,0,0, 1}, - {"8", CPU_8088, fpus_8088, 8000000, 1, 5000, 0, 0, 0, 0, 0,0,0,0, 1}, - {"10", CPU_8088, fpus_8088, 10000000, 1, 5000, 0, 0, 0, 0, 0,0,0,0, 1}, - {"12", CPU_8088, fpus_8088, 12000000, 1, 5000, 0, 0, 0, 0, 0,0,0,0, 1}, - {"16", CPU_8088, fpus_8088, 16000000, 1, 5000, 0, 0, 0, 0, 0,0,0,0, 1}, - {"", 0} - } + .package = CPU_PKG_8088, + .manufacturer = "Intel", + .name = "8088", + .internal_name = "8088", + .cpus = (const CPU[]) { + { + .name = "4.77", + .cpu_type = CPU_8088, + .fpus = fpus_8088, + .rspeed = 4772728, + .multi = 1, + .voltage = 5000, + .edx_reset = 0, + .cpuid_model = 0, + .cyrix_id = 0, + .cpu_flags = 0, + .mem_read_cycles = 0, + .mem_write_cycles = 0, + .cache_read_cycles = 0, + .cache_write_cycles = 0, + .atclk_div = 1 + }, + { + .name = "7.16", + .cpu_type = CPU_8088, + .fpus = fpus_8088, + .rspeed = 7159092, + .multi = 1, + .voltage = 5000, + .edx_reset = 0, + .cpuid_model = 0, + .cyrix_id = 0, + .cpu_flags = 0, + .mem_read_cycles = 0, + .mem_write_cycles = 0, + .cache_read_cycles = 0, + .cache_write_cycles = 0, + .atclk_div = 1 + }, + { + .name = "8", + .cpu_type = CPU_8088, + .fpus = fpus_8088, + .rspeed = 8000000, + .multi = 1, + .voltage = 5000, + .edx_reset = 0, + .cpuid_model = 0, + .cyrix_id = 0, + .cpu_flags = 0, + .mem_read_cycles = 0, + .mem_write_cycles = 0, + .cache_read_cycles = 0, + .cache_write_cycles = 0, + .atclk_div = 1 + }, +#if 0 + { + .name = "9.54", + .cpu_type = CPU_8088, + .fpus = fpus_8088, + .rspeed = 9545456, + .multi = 1, + .voltage = 5000, + .edx_reset = 0, + .cpuid_model = 0, + .cyrix_id = 0, + .cpu_flags = 0, + .mem_read_cycles = 0, + .mem_write_cycles = 0, + .cache_read_cycles = 0, + .cache_write_cycles = 0, + .atclk_div = 1 + }, +#endif + { + .name = "10", + .cpu_type = CPU_8088, + .fpus = fpus_8088, + .rspeed = 10000000, + .multi = 1, + .voltage = 5000, + .edx_reset = 0, + .cpuid_model = 0, + .cyrix_id = 0, + .cpu_flags = 0, + .mem_read_cycles = 0, + .mem_write_cycles = 0, + .cache_read_cycles = 0, + .cache_write_cycles = 0, + .atclk_div = 1 + }, + { + .name = "12", + .cpu_type = CPU_8088, + .fpus = fpus_8088, + .rspeed = 12000000, + .multi = 1, + .voltage = 5000, + .edx_reset = 0, + .cpuid_model = 0, + .cyrix_id = 0, + .cpu_flags = 0, + .mem_read_cycles = 0, + .mem_write_cycles = 0, + .cache_read_cycles = 0, + .cache_write_cycles = 0, + .atclk_div = 1 + }, + { + .name = "16", + .cpu_type = CPU_8088, + .fpus = fpus_8088, + .rspeed = 16000000, + .multi = 1, + .voltage = 5000, + .edx_reset = 0, + .cpuid_model = 0, + .cyrix_id = 0, + .cpu_flags = 0, + .mem_read_cycles = 0, + .mem_write_cycles = 0, + .cache_read_cycles = 0, + .cache_write_cycles = 0, + .atclk_div = 1 + }, + { .name = "", 0 } + } }, { - .package = CPU_PKG_8088_EUROPC, - .manufacturer = "Intel", - .name = "8088", - .internal_name = "8088_europc", - .cpus = (const CPU[]) { - {"4.77", CPU_8088, fpus_8088, 4772728, 1, 5000, 0, 0, 0, CPU_ALTERNATE_XTAL, 0,0,0,0, 1}, - {"7.16", CPU_8088, fpus_8088, 7159092, 1, 5000, 0, 0, 0, CPU_ALTERNATE_XTAL, 0,0,0,0, 1}, - {"9.54", CPU_8088, fpus_8088, 9545456, 1, 5000, 0, 0, 0, 0, 0,0,0,0, 1}, - {"", 0} - } + .package = CPU_PKG_8088_EUROPC, + .manufacturer = "Intel", + .name = "8088", + .internal_name = "8088_europc", + .cpus = (const CPU[]) { + { + .name = "4.77", + .cpu_type = CPU_8088, + .fpus = fpus_8088, + .rspeed = 4772728, + .multi = 1, + .voltage = 5000, + .edx_reset = 0, + .cpuid_model = 0, + .cyrix_id = 0, + .cpu_flags = CPU_ALTERNATE_XTAL, + .mem_read_cycles = 0, + .mem_write_cycles = 0, + .cache_read_cycles = 0, + .cache_write_cycles = 0, + .atclk_div = 1 + }, + { + .name = "7.16", + .cpu_type = CPU_8088, + .fpus = fpus_8088, + .rspeed = 7159092, + .multi = 1, + .voltage = 5000, + .edx_reset = 0, + .cpuid_model = 0, + .cyrix_id = 0, + .cpu_flags = CPU_ALTERNATE_XTAL, + .mem_read_cycles = 0, + .mem_write_cycles = 0, + .cache_read_cycles = 0, + .cache_write_cycles = 0, + .atclk_div = 1 + }, + { + .name = "9.54", + .cpu_type = CPU_8088, + .fpus = fpus_8088, + .rspeed = 9545456, + .multi = 1, + .voltage = 5000, + .edx_reset = 0, + .cpuid_model = 0, + .cyrix_id = 0, + .cpu_flags = 0, + .mem_read_cycles = 0, + .mem_write_cycles = 0, + .cache_read_cycles = 0, + .cache_write_cycles = 0, + .atclk_div = 1 + }, + { .name = "", 0 } + } }, { - .package = CPU_PKG_8086, - .manufacturer = "Intel", - .name = "8086", - .internal_name = "8086", - .cpus = (const CPU[]) { - {"7.16", CPU_8086, fpus_8088, 7159092, 1, 5000, 0, 0, 0, CPU_ALTERNATE_XTAL, 0,0,0,0, 1}, - {"8", CPU_8086, fpus_8088, 8000000, 1, 5000, 0, 0, 0, 0, 0,0,0,0, 1}, - {"9.54", CPU_8086, fpus_8088, 9545456, 1, 5000, 0, 0, 0, CPU_ALTERNATE_XTAL, 0,0,0,0, 1}, - {"10", CPU_8086, fpus_8088, 10000000, 1, 5000, 0, 0, 0, 0, 0,0,0,0, 1}, - {"12", CPU_8086, fpus_8088, 12000000, 1, 5000, 0, 0, 0, 0, 0,0,0,0, 1}, - {"16", CPU_8086, fpus_8088, 16000000, 1, 5000, 0, 0, 0, 0, 0,0,0,0, 2}, - {"", 0} - } + .package = CPU_PKG_8086, + .manufacturer = "Intel", + .name = "8086", + .internal_name = "8086", + .cpus = (const CPU[]) { + { + .name = "7.16", + .cpu_type = CPU_8086, + .fpus = fpus_8088, + .rspeed = 7159092, + .multi = 1, + .voltage = 5000, + .edx_reset = 0, + .cpuid_model = 0, + .cyrix_id = 0, + .cpu_flags = CPU_ALTERNATE_XTAL, + .mem_read_cycles = 0, + .mem_write_cycles = 0, + .cache_read_cycles = 0, + .cache_write_cycles = 0, + .atclk_div = 1 + }, + { + .name = "8", + .cpu_type = CPU_8086, + .fpus = fpus_8088, + .rspeed = 8000000, + .multi = 1, + .voltage = 5000, + .edx_reset = 0, + .cpuid_model = 0, + .cyrix_id = 0, + .cpu_flags = 0, + .mem_read_cycles = 0, + .mem_write_cycles = 0, + .cache_read_cycles = 0, + .cache_write_cycles = 0, + .atclk_div = 1 + }, + { + .name = "9.54", + .cpu_type = CPU_8086, + .fpus = fpus_8088, + .rspeed = 9545456, + .multi = 1, + .voltage = 5000, + .edx_reset = 0, + .cpuid_model = 0, + .cyrix_id = 0, + .cpu_flags = CPU_ALTERNATE_XTAL, + .mem_read_cycles = 0, + .mem_write_cycles = 0, + .cache_read_cycles = 0, + .cache_write_cycles = 0, + .atclk_div = 1 + }, + { + .name = "10", + .cpu_type = CPU_8086, + .fpus = fpus_8088, + .rspeed = 10000000, + .multi = 1, + .voltage = 5000, + .edx_reset = 0, + .cpuid_model = 0, + .cyrix_id = 0, + .cpu_flags = 0, + .mem_read_cycles = 0, + .mem_write_cycles = 0, + .cache_read_cycles = 0, + .cache_write_cycles = 0, + .atclk_div = 1 + }, + { + .name = "12", + .cpu_type = CPU_8086, + .fpus = fpus_8088, + .rspeed = 12000000, + .multi = 1, + .voltage = 5000, + .edx_reset = 0, + .cpuid_model = 0, + .cyrix_id = 0, + .cpu_flags = 0, + .mem_read_cycles = 0, + .mem_write_cycles = 0, + .cache_read_cycles = 0, + .cache_write_cycles = 0, + .atclk_div = 1 + }, + { + .name = "16", + .cpu_type = CPU_8086, + .fpus = fpus_8088, + .rspeed = 16000000, + .multi = 1, + .voltage = 5000, + .edx_reset = 0, + .cpuid_model = 0, + .cyrix_id = 0, + .cpu_flags = 0, + .mem_read_cycles = 0, + .mem_write_cycles = 0, + .cache_read_cycles = 0, + .cache_write_cycles = 0, + .atclk_div = 2 + }, + { .name = "", 0 } + } }, { - .package = CPU_PKG_286, - .manufacturer = "Intel", - .name = "80286", - .internal_name = "286", - .cpus = (const CPU[]) { - {"6", CPU_286, fpus_80286, 6000000, 1, 5000, 0, 0, 0, 0, 2,2,2,2, 1}, - {"8", CPU_286, fpus_80286, 8000000, 1, 5000, 0, 0, 0, 0, 2,2,2,2, 1}, - {"10", CPU_286, fpus_80286, 10000000, 1, 5000, 0, 0, 0, 0, 2,2,2,2, 1}, - {"12", CPU_286, fpus_80286, 12500000, 1, 5000, 0, 0, 0, 0, 3,3,3,3, 2}, - {"16", CPU_286, fpus_80286, 16000000, 1, 5000, 0, 0, 0, 0, 3,3,3,3, 2}, - {"20", CPU_286, fpus_80286, 20000000, 1, 5000, 0, 0, 0, 0, 4,4,4,4, 3}, - {"25", CPU_286, fpus_80286, 25000000, 1, 5000, 0, 0, 0, 0, 4,4,4,4, 3}, - {"", 0} - } + .package = CPU_PKG_188, + .manufacturer = "Intel", + .name = "80188", + .internal_name = "80188", + .cpus = (const CPU[]) { + { + .name = "6", + .cpu_type = CPU_188, + .fpus = fpus_8088, + .rspeed = 6000000, + .multi = 1, + .voltage = 5000, + .edx_reset = 0, + .cpuid_model = 0, + .cyrix_id = 0, + .cpu_flags = 0, + .mem_read_cycles = 0, + .mem_write_cycles = 0, + .cache_read_cycles = 0, + .cache_write_cycles = 0, + .atclk_div = 1 + }, + { + .name = "7.16", + .cpu_type = CPU_188, + .fpus = fpus_8088, + .rspeed = 7159092, + .multi = 1, + .voltage = 5000, + .edx_reset = 0, + .cpuid_model = 0, + .cyrix_id = 0, + .cpu_flags = CPU_ALTERNATE_XTAL, + .mem_read_cycles = 0, + .mem_write_cycles = 0, + .cache_read_cycles = 0, + .cache_write_cycles = 0, + .atclk_div = 1 + }, + { + .name = "8", + .cpu_type = CPU_188, + .fpus = fpus_8088, + .rspeed = 8000000, + .multi = 1, + .voltage = 5000, + .edx_reset = 0, + .cpuid_model = 0, + .cyrix_id = 0, + .cpu_flags = 0, + .mem_read_cycles = 0, + .mem_write_cycles = 0, + .cache_read_cycles = 0, + .cache_write_cycles = 0, + .atclk_div = 1 + }, + { + .name = "9.54", + .cpu_type = CPU_188, + .fpus = fpus_8088, + .rspeed = 9545456, + .multi = 1, + .voltage = 5000, + .edx_reset = 0, + .cpuid_model = 0, + .cyrix_id = 0, + .cpu_flags = CPU_ALTERNATE_XTAL, + .mem_read_cycles = 0, + .mem_write_cycles = 0, + .cache_read_cycles = 0, + .cache_write_cycles = 0, + .atclk_div = 1 + }, + { + .name = "10", + .cpu_type = CPU_188, + .fpus = fpus_8088, + .rspeed = 10000000, + .multi = 1, + .voltage = 5000, + .edx_reset = 0, + .cpuid_model = 0, + .cyrix_id = 0, + .cpu_flags = 0, + .mem_read_cycles = 0, + .mem_write_cycles = 0, + .cache_read_cycles = 0, + .cache_write_cycles = 0, + .atclk_div = 1 + }, + { + .name = "12", + .cpu_type = CPU_188, + .fpus = fpus_8088, + .rspeed = 12000000, + .multi = 1, + .voltage = 5000, + .edx_reset = 0, + .cpuid_model = 0, + .cyrix_id = 0, + .cpu_flags = 0, + .mem_read_cycles = 0, + .mem_write_cycles = 0, + .cache_read_cycles = 0, + .cache_write_cycles = 0, + .atclk_div = 1 + }, + { + .name = "16", + .cpu_type = CPU_188, + .fpus = fpus_8088, + .rspeed = 16000000, + .multi = 1, + .voltage = 5000, + .edx_reset = 0, + .cpuid_model = 0, + .cyrix_id = 0, + .cpu_flags = 0, + .mem_read_cycles = 0, + .mem_write_cycles = 0, + .cache_read_cycles = 0, + .cache_write_cycles = 0, + .atclk_div = 2 + }, + { + .name = "20", + .cpu_type = CPU_188, + .fpus = fpus_8088, + .rspeed = 20000000, + .multi = 1, + .voltage = 5000, + .edx_reset = 0, + .cpuid_model = 0, + .cyrix_id = 0, + .cpu_flags = 0, + .mem_read_cycles = 0, + .mem_write_cycles = 0, + .cache_read_cycles = 0, + .cache_write_cycles = 0, + .atclk_div = 3 + }, + { + .name = "25", + .cpu_type = CPU_188, + .fpus = fpus_8088, + .rspeed = 25000000, + .multi = 1, + .voltage = 5000, + .edx_reset = 0, + .cpuid_model = 0, + .cyrix_id = 0, + .cpu_flags = 0, + .mem_read_cycles = 0, + .mem_write_cycles = 0, + .cache_read_cycles = 0, + .cache_write_cycles = 0, + .atclk_div = 3 + }, + { .name = "", 0 } + } }, { - .package = CPU_PKG_386SX, - .manufacturer = "Intel", - .name = "i386SX", - .internal_name = "i386sx", - .cpus = (const CPU[]) { - {"16", CPU_386SX, fpus_80386, 16000000, 1, 5000, 0x2308, 0, 0, 0, 3,3,3,3, 2}, - {"20", CPU_386SX, fpus_80386, 20000000, 1, 5000, 0x2308, 0, 0, 0, 4,4,3,3, 3}, - {"25", CPU_386SX, fpus_80386, 25000000, 1, 5000, 0x2308, 0, 0, 0, 4,4,3,3, 3}, - {"33", CPU_386SX, fpus_80386, 33333333, 1, 5000, 0x2308, 0, 0, 0, 6,6,3,3, 4}, - {"40", CPU_386SX, fpus_80386, 40000000, 1, 5000, 0x2308, 0, 0, 0, 7,7,3,3, 5}, - {"", 0} - } + .package = CPU_PKG_8088, + .manufacturer = "NEC", + .name = "V20", + .internal_name = "necv20", + .cpus = (const CPU[]) { + { + .name = "4.77", + .cpu_type = CPU_V20, + .fpus = fpus_8088, + .rspeed = 4772728, + .multi = 1, + .voltage = 5000, + .edx_reset = 0, + .cpuid_model = 0, + .cyrix_id = 0, + .cpu_flags = 0, + .mem_read_cycles = 0, + .mem_write_cycles = 0, + .cache_read_cycles = 0, + .cache_write_cycles = 0, + .atclk_div = 1 + }, + { + .name = "7.16", + .cpu_type = CPU_V20, + .fpus = fpus_8088, + .rspeed = 7159092, + .multi = 1, + .voltage = 5000, + .edx_reset = 0, + .cpuid_model = 0, + .cyrix_id = 0, + .cpu_flags = 0, + .mem_read_cycles = 0, + .mem_write_cycles = 0, + .cache_read_cycles = 0, + .cache_write_cycles = 0, + .atclk_div = 1 + }, + { + .name = "10", + .cpu_type = CPU_V20, + .fpus = fpus_8088, + .rspeed = 10000000, + .multi = 1, + .voltage = 5000, + .edx_reset = 0, + .cpuid_model = 0, + .cyrix_id = 0, + .cpu_flags = 0, + .mem_read_cycles = 0, + .mem_write_cycles = 0, + .cache_read_cycles = 0, + .cache_write_cycles = 0, + .atclk_div = 1 + }, + { + .name = "12", + .cpu_type = CPU_V20, + .fpus = fpus_8088, + .rspeed = 12000000, + .multi = 1, + .voltage = 5000, + .edx_reset = 0, + .cpuid_model = 0, + .cyrix_id = 0, + .cpu_flags = 0, + .mem_read_cycles = 0, + .mem_write_cycles = 0, + .cache_read_cycles = 0, + .cache_write_cycles = 0, + .atclk_div = 1 + }, + { + .name = "16", + .cpu_type = CPU_V20, + .fpus = fpus_8088, + .rspeed = 16000000, + .multi = 1, + .voltage = 5000, + .edx_reset = 0, + .cpuid_model = 0, + .cyrix_id = 0, + .cpu_flags = 0, + .mem_read_cycles = 0, + .mem_write_cycles = 0, + .cache_read_cycles = 0, + .cache_write_cycles = 0, + .atclk_div = 2 + }, + { .name = "", 0 } + } }, { - .package = CPU_PKG_386SX, - .manufacturer = "AMD", - .name = "Am386SX", - .internal_name = "am386sx", - .cpus = (const CPU[]) { - {"16", CPU_386SX, fpus_80386, 16000000, 1, 5000, 0x2308, 0, 0, 0, 3,3,3,3, 2}, - {"20", CPU_386SX, fpus_80386, 20000000, 1, 5000, 0x2308, 0, 0, 0, 4,4,3,3, 3}, - {"25", CPU_386SX, fpus_80386, 25000000, 1, 5000, 0x2308, 0, 0, 0, 4,4,3,3, 3}, - {"33", CPU_386SX, fpus_80386, 33333333, 1, 5000, 0x2308, 0, 0, 0, 6,6,3,3, 4}, - {"40", CPU_386SX, fpus_80386, 40000000, 1, 5000, 0x2308, 0, 0, 0, 7,7,3,3, 5}, - {"", 0} - } + .package = CPU_PKG_186, + .manufacturer = "Intel", + .name = "80186", + .internal_name = "80186", + .cpus = (const CPU[]) { + { + .name = "6", + .cpu_type = CPU_186, + .fpus = fpus_80186, + .rspeed = 6000000, + .multi = 1, + .voltage = 0, + .edx_reset = 0, + .cpuid_model = 0, + .cyrix_id = 0, + .cpu_flags = 0, + .mem_read_cycles = 0, + .mem_write_cycles = 0, + .cache_read_cycles = 0, + .cache_write_cycles = 0, + .atclk_div = 1 + }, + { + .name = "7.16", + .cpu_type = CPU_186, + .fpus = fpus_80186, + .rspeed = 7159092, + .multi = 1, + .voltage = 0, + .edx_reset = 0, + .cpuid_model = 0, + .cyrix_id = 0, + .cpu_flags = CPU_ALTERNATE_XTAL, + .mem_read_cycles = 0, + .mem_write_cycles = 0, + .cache_read_cycles = 0, + .cache_write_cycles = 0, + .atclk_div = 1 + }, + { + .name = "8", + .cpu_type = CPU_186, + .fpus = fpus_80186, + .rspeed = 8000000, + .multi = 1, + .voltage = 0, + .edx_reset = 0, + .cpuid_model = 0, + .cyrix_id = 0, + .cpu_flags = 0, + .mem_read_cycles = 0, + .mem_write_cycles = 0, + .cache_read_cycles = 0, + .cache_write_cycles = 0, + .atclk_div = 1 + }, + { + .name = "9.54", + .cpu_type = CPU_186, + .fpus = fpus_80186, + .rspeed = 9545456, + .multi = 1, + .voltage = 0, + .edx_reset = 0, + .cpuid_model = 0, + .cyrix_id = 0, + .cpu_flags = CPU_ALTERNATE_XTAL, + .mem_read_cycles = 0, + .mem_write_cycles = 0, + .cache_read_cycles = 0, + .cache_write_cycles = 0, + .atclk_div = 1 + }, + { + .name = "10", + .cpu_type = CPU_186, + .fpus = fpus_80186, + .rspeed = 10000000, + .multi = 1, + .voltage = 0, + .edx_reset = 0, + .cpuid_model = 0, + .cyrix_id = 0, + .cpu_flags = 0, + .mem_read_cycles = 0, + .mem_write_cycles = 0, + .cache_read_cycles = 0, + .cache_write_cycles = 0, + .atclk_div = 1 + }, + { + .name = "12", + .cpu_type = CPU_186, + .fpus = fpus_80186, + .rspeed = 12000000, + .multi = 1, + .voltage = 0, + .edx_reset = 0, + .cpuid_model = 0, + .cyrix_id = 0, + .cpu_flags = 0, + .mem_read_cycles = 0, + .mem_write_cycles = 0, + .cache_read_cycles = 0, + .cache_write_cycles = 0, + .atclk_div = 1 + }, + { + .name = "16", + .cpu_type = CPU_186, + .fpus = fpus_80186, + .rspeed = 16000000, + .multi = 1, + .voltage = 0, + .edx_reset = 0, + .cpuid_model = 0, + .cyrix_id = 0, + .cpu_flags = 0, + .mem_read_cycles = 0, + .mem_write_cycles = 0, + .cache_read_cycles = 0, + .cache_write_cycles = 0, + .atclk_div = 2 + }, + { + .name = "20", + .cpu_type = CPU_186, + .fpus = fpus_80186, + .rspeed = 20000000, + .multi = 1, + .voltage = 0, + .edx_reset = 0, + .cpuid_model = 0, + .cyrix_id = 0, + .cpu_flags = 0, + .mem_read_cycles = 0, + .mem_write_cycles = 0, + .cache_read_cycles = 0, + .cache_write_cycles = 0, + .atclk_div = 3 + }, + { + .name = "25", + .cpu_type = CPU_186, + .fpus = fpus_80186, + .rspeed = 25000000, + .multi = 1, + .voltage = 0, + .edx_reset = 0, + .cpuid_model = 0, + .cyrix_id = 0, + .cpu_flags = 0, + .mem_read_cycles = 0, + .mem_write_cycles = 0, + .cache_read_cycles = 0, + .cache_write_cycles = 0, + .atclk_div = 3 + }, + { .name = "", 0 } + } }, { - .package = CPU_PKG_386DX, - .manufacturer = "Intel", - .name = "i386DX", - .internal_name = "i386dx", - .cpus = (const CPU[]) { - {"16", CPU_386DX, fpus_80386, 16000000, 1, 5000, 0x0308, 0, 0, 0, 3,3,3,3, 2}, - {"20", CPU_386DX, fpus_80386, 20000000, 1, 5000, 0x0308, 0, 0, 0, 4,4,3,3, 3}, - {"25", CPU_386DX, fpus_80386, 25000000, 1, 5000, 0x0308, 0, 0, 0, 4,4,3,3, 3}, - {"33", CPU_386DX, fpus_80386, 33333333, 1, 5000, 0x0308, 0, 0, 0, 6,6,3,3, 4}, - {"40", CPU_386DX, fpus_80386, 40000000, 1, 5000, 0x0308, 0, 0, 0, 7,7,3,3, 5}, - {"", 0} - } + .package = CPU_PKG_8086, + .manufacturer = "NEC", + .name = "V30", + .internal_name = "necv30", + .cpus = (const CPU[]) { + { + .name = "5", + .cpu_type = CPU_V30, + .fpus = fpus_80186, + .rspeed = 5000000, + .multi = 1, + .voltage = 5000, + .edx_reset = 0, + .cpuid_model = 0, + .cyrix_id = 0, + .cpu_flags = 0, + .mem_read_cycles = 0, + .mem_write_cycles = 0, + .cache_read_cycles = 0, + .cache_write_cycles = 0, + .atclk_div = 1 + }, + { + .name = "8", + .cpu_type = CPU_V30, + .fpus = fpus_80186, + .rspeed = 8000000, + .multi = 1, + .voltage = 5000, + .edx_reset = 0, + .cpuid_model = 0, + .cyrix_id = 0, + .cpu_flags = 0, + .mem_read_cycles = 0, + .mem_write_cycles = 0, + .cache_read_cycles = 0, + .cache_write_cycles = 0, + .atclk_div = 1 + }, + { + .name = "10", + .cpu_type = CPU_V30, + .fpus = fpus_80186, + .rspeed = 10000000, + .multi = 1, + .voltage = 5000, + .edx_reset = 0, + .cpuid_model = 0, + .cyrix_id = 0, + .cpu_flags = 0, + .mem_read_cycles = 0, + .mem_write_cycles = 0, + .cache_read_cycles = 0, + .cache_write_cycles = 0, + .atclk_div = 1 + }, + { + .name = "12", + .cpu_type = CPU_V30, + .fpus = fpus_80186, + .rspeed = 12000000, + .multi = 1, + .voltage = 5000, + .edx_reset = 0, + .cpuid_model = 0, + .cyrix_id = 0, + .cpu_flags = 0, + .mem_read_cycles = 0, + .mem_write_cycles = 0, + .cache_read_cycles = 0, + .cache_write_cycles = 0, + .atclk_div = 1 + }, + { + .name = "16", + .cpu_type = CPU_V30, + .fpus = fpus_80186, + .rspeed = 16000000, + .multi = 1, + .voltage = 5000, + .edx_reset = 0, + .cpuid_model = 0, + .cyrix_id = 0, + .cpu_flags = 0, + .mem_read_cycles = 0, + .mem_write_cycles = 0, + .cache_read_cycles = 0, + .cache_write_cycles = 0, + .atclk_div = 2 + }, + { .name = "", 0 } + } }, { - .package = CPU_PKG_386DX, - .manufacturer = "Intel", - .name = "RapidCAD", - .internal_name = "rapidcad", - .cpus = (const CPU[]) { - {"25", CPU_RAPIDCAD, fpus_internal, 25000000, 1, 5000, 0x0340, 0, 0, CPU_SUPPORTS_DYNAREC, 4,4,3,3, 3}, - {"33", CPU_RAPIDCAD, fpus_internal, 33333333, 1, 5000, 0x0340, 0, 0, CPU_SUPPORTS_DYNAREC, 6,6,3,3, 4}, - {"40", CPU_RAPIDCAD, fpus_internal, 40000000, 1, 5000, 0x0340, 0, 0, CPU_SUPPORTS_DYNAREC, 7,7,3,3, 5}, - {"", 0} - } + .package = CPU_PKG_286, + .manufacturer = "Intel", + .name = "80286", + .internal_name = "286", + .cpus = (const CPU[]) { + { + .name = "6", + .cpu_type = CPU_286, + .fpus = fpus_80286, + .rspeed = 6000000, + .multi = 1, + .voltage = 5000, + .edx_reset = 0, + .cpuid_model = 0, + .cyrix_id = 0, + .cpu_flags = 0, + .mem_read_cycles = 2, + .mem_write_cycles = 2, + .cache_read_cycles = 2, + .cache_write_cycles = 2, + .atclk_div = 1 + }, + { + .name = "8", + .cpu_type = CPU_286, + .fpus = fpus_80286, + .rspeed = 8000000, + .multi = 1, + .voltage = 5000, + .edx_reset = 0, + .cpuid_model = 0, + .cyrix_id = 0, + .cpu_flags = 0, + .mem_read_cycles = 2, + .mem_write_cycles = 2, + .cache_read_cycles = 2, + .cache_write_cycles = 2, + .atclk_div = 1 + }, + { + .name = "10", + .cpu_type = CPU_286, + .fpus = fpus_80286, + .rspeed = 10000000, + .multi = 1, + .voltage = 5000, + .edx_reset = 0, + .cpuid_model = 0, + .cyrix_id = 0, + .cpu_flags = 0, + .mem_read_cycles = 2, + .mem_write_cycles = 2, + .cache_read_cycles = 2, + .cache_write_cycles = 2, + .atclk_div = 1 + }, + { + .name = "12", + .cpu_type = CPU_286, + .fpus = fpus_80286, + .rspeed = 12500000, + .multi = 1, + .voltage = 5000, + .edx_reset = 0, + .cpuid_model = 0, + .cyrix_id = 0, + .cpu_flags = 0, + .mem_read_cycles = 3, + .mem_write_cycles = 3, + .cache_read_cycles = 3, + .cache_write_cycles = 3, + .atclk_div = 2 + }, + { + .name = "16", + .cpu_type = CPU_286, + .fpus = fpus_80286, + .rspeed = 16000000, + .multi = 1, + .voltage = 5000, + .edx_reset = 0, + .cpuid_model = 0, + .cyrix_id = 0, + .cpu_flags = 0, + .mem_read_cycles = 3, + .mem_write_cycles = 3, + .cache_read_cycles = 3, + .cache_write_cycles = 3, + .atclk_div = 2 + }, + { + .name = "20", + .cpu_type = CPU_286, + .fpus = fpus_80286, + .rspeed = 20000000, + .multi = 1, + .voltage = 5000, + .edx_reset = 0, + .cpuid_model = 0, + .cyrix_id = 0, + .cpu_flags = 0, + .mem_read_cycles = 4, + .mem_write_cycles = 4, + .cache_read_cycles = 4, + .cache_write_cycles = 4, + .atclk_div = 3 + }, + { + .name = "25", + .cpu_type = CPU_286, + .fpus = fpus_80286, + .rspeed = 25000000, + .multi = 1, + .voltage = 5000, + .edx_reset = 0, + .cpuid_model = 0, + .cyrix_id = 0, + .cpu_flags = 0, + .mem_read_cycles = 4, + .mem_write_cycles = 4, + .cache_read_cycles = 4, + .cache_write_cycles = 4, + .atclk_div = 3 + }, + { .name = "", 0 } + } }, { - .package = CPU_PKG_386DX, - .manufacturer = "AMD", - .name = "Am386DX", - .internal_name = "am386dx", - .cpus = (const CPU[]) { - {"25", CPU_386DX, fpus_80386, 25000000, 1, 5000, 0x0308, 0, 0, 0, 4,4,3,3, 3}, - {"33", CPU_386DX, fpus_80386, 33333333, 1, 5000, 0x0308, 0, 0, 0, 6,6,3,3, 4}, - {"40", CPU_386DX, fpus_80386, 40000000, 1, 5000, 0x0308, 0, 0, 0, 7,7,3,3, 5}, - {"", 0} - } - }, - { - .package = CPU_PKG_M6117, - .manufacturer = "ALi", - .name = "M6117", - .internal_name = "m6117", - .cpus = (const CPU[]) { /* All timings and edx_reset values assumed. */ - {"33", CPU_386SX, fpus_none, 33333333, 1, 5000, 0x2308, 0, 0, 0, 6,6,3,3, 4}, - {"40", CPU_386SX, fpus_none, 40000000, 1, 5000, 0x2308, 0, 0, 0, 7,7,3,3, 5}, - {"", 0} - } - }, - { - .package = CPU_PKG_386SLC_IBM, - .manufacturer = "IBM", - .name = "386SLC", - .internal_name = "ibm386slc", - .cpus = (const CPU[]) { - {"16", CPU_IBM386SLC, fpus_80386, 16000000, 1, 5000, 0xA301, 0, 0, 0, 3,3,3,3, 2}, - {"20", CPU_IBM386SLC, fpus_80386, 20000000, 1, 5000, 0xA301, 0, 0, 0, 4,4,3,3, 3}, - {"25", CPU_IBM386SLC, fpus_80386, 25000000, 1, 5000, 0xA301, 0, 0, 0, 4,4,3,3, 3}, - {"", 0} - } + .package = CPU_PKG_386SX, + .manufacturer = "Intel", + .name = "i386SX", + .internal_name = "i386sx", + .cpus = (const CPU[]) { + {"16", CPU_386SX, fpus_80386, 16000000, 1, 5000, 0x2308, 0, 0, 0, 3,3,3,3, 2}, + {"20", CPU_386SX, fpus_80386, 20000000, 1, 5000, 0x2308, 0, 0, 0, 4,4,3,3, 3}, + {"25", CPU_386SX, fpus_80386, 25000000, 1, 5000, 0x2308, 0, 0, 0, 4,4,3,3, 3}, + {"33", CPU_386SX, fpus_80386, 33333333, 1, 5000, 0x2308, 0, 0, 0, 6,6,3,3, 4}, + {"40", CPU_386SX, fpus_80386, 40000000, 1, 5000, 0x2308, 0, 0, 0, 7,7,3,3, 5}, + {"", 0} + } }, { - .package = CPU_PKG_386SX, - .manufacturer = "Cyrix", - .name = "Cx486SLC", - .internal_name = "cx486slc", - .cpus = (const CPU[]) { - {"20", CPU_486SLC, fpus_80386, 20000000, 1, 5000, 0x400, 0, 0x0000, 0, 4,4,3,3, 3}, - {"25", CPU_486SLC, fpus_80386, 25000000, 1, 5000, 0x400, 0, 0x0000, 0, 4,4,3,3, 3}, - {"33", CPU_486SLC, fpus_80386, 33333333, 1, 5000, 0x400, 0, 0x0000, 0, 6,6,3,3, 4}, - {"", 0} - } + .package = CPU_PKG_386SX, + .manufacturer = "AMD", + .name = "Am386SX", + .internal_name = "am386sx", + .cpus = (const CPU[]) { + {"16", CPU_386SX, fpus_80386, 16000000, 1, 5000, 0x2308, 0, 0, 0, 3,3,3,3, 2}, + {"20", CPU_386SX, fpus_80386, 20000000, 1, 5000, 0x2308, 0, 0, 0, 4,4,3,3, 3}, + {"25", CPU_386SX, fpus_80386, 25000000, 1, 5000, 0x2308, 0, 0, 0, 4,4,3,3, 3}, + {"33", CPU_386SX, fpus_80386, 33333333, 1, 5000, 0x2308, 0, 0, 0, 6,6,3,3, 4}, + {"40", CPU_386SX, fpus_80386, 40000000, 1, 5000, 0x2308, 0, 0, 0, 7,7,3,3, 5}, + {"", 0} + } }, { - .package = CPU_PKG_386SX, - .manufacturer = "Cyrix", - .name = "Cx486SRx2", - .internal_name = "cx486srx2", - .cpus = (const CPU[]) { - {"32", CPU_486SLC, fpus_80386, 32000000, 2, 5000, 0x406, 0, 0x0006, 0, 6,6,6,6, 4}, - {"40", CPU_486SLC, fpus_80386, 40000000, 2, 5000, 0x406, 0, 0x0006, 0, 8,8,6,6, 6}, - {"50", CPU_486SLC, fpus_80386, 50000000, 2, 5000, 0x406, 0, 0x0006, 0, 8,8,6,6, 6}, - {"", 0} - } + .package = CPU_PKG_386DX, + .manufacturer = "Intel", + .name = "i386DX", + .internal_name = "i386dx", + .cpus = (const CPU[]) { + {"16", CPU_386DX, fpus_80386, 16000000, 1, 5000, 0x0308, 0, 0, 0, 3,3,3,3, 2}, + {"20", CPU_386DX, fpus_80386, 20000000, 1, 5000, 0x0308, 0, 0, 0, 4,4,3,3, 3}, + {"25", CPU_386DX, fpus_80386, 25000000, 1, 5000, 0x0308, 0, 0, 0, 4,4,3,3, 3}, + {"33", CPU_386DX, fpus_80386, 33333333, 1, 5000, 0x0308, 0, 0, 0, 6,6,3,3, 4}, + {"40", CPU_386DX, fpus_80386, 40000000, 1, 5000, 0x0308, 0, 0, 0, 7,7,3,3, 5}, + {"", 0} + } }, { - .package = CPU_PKG_486SLC_IBM, - .manufacturer = "IBM", - .name = "486SLC", - .internal_name = "ibm486slc", - .cpus = (const CPU[]) { - {"33", CPU_IBM486SLC, fpus_80386, 33333333, 1, 5000, 0xA401, 0, 0, 0, 6,6,3,3, 4}, - {"", 0} - } + .package = CPU_PKG_386DX, + .manufacturer = "Intel", + .name = "RapidCAD", + .internal_name = "rapidcad", + .cpus = (const CPU[]) { + {"25", CPU_RAPIDCAD, fpus_internal, 25000000, 1, 5000, 0x0340, 0, 0, CPU_SUPPORTS_DYNAREC, 4,4,3,3, 3}, + {"33", CPU_RAPIDCAD, fpus_internal, 33333333, 1, 5000, 0x0340, 0, 0, CPU_SUPPORTS_DYNAREC, 6,6,3,3, 4}, + {"40", CPU_RAPIDCAD, fpus_internal, 40000000, 1, 5000, 0x0340, 0, 0, CPU_SUPPORTS_DYNAREC, 7,7,3,3, 5}, + {"", 0} + } }, { - .package = CPU_PKG_486SLC_IBM, - .manufacturer = "IBM", - .name = "486SLC2", - .internal_name = "ibm486slc2", - .cpus = (const CPU[]) { - {"40", CPU_IBM486SLC, fpus_80386, 40000000, 2, 5000, 0xA421, 0, 0, 0, 7,7,6,6, 5}, - {"50", CPU_IBM486SLC, fpus_80386, 50000000, 2, 5000, 0xA421, 0, 0, 0, 8,8,6,6, 6}, - {"66", CPU_IBM486SLC, fpus_80386, 66666666, 2, 5000, 0xA421, 0, 0, 0, 12,12,6,6, 8}, - {"", 0} - } + .package = CPU_PKG_386DX, + .manufacturer = "AMD", + .name = "Am386DX", + .internal_name = "am386dx", + .cpus = (const CPU[]) { + {"25", CPU_386DX, fpus_80386, 25000000, 1, 5000, 0x0308, 0, 0, 0, 4,4,3,3, 3}, + {"33", CPU_386DX, fpus_80386, 33333333, 1, 5000, 0x0308, 0, 0, 0, 6,6,3,3, 4}, + {"40", CPU_386DX, fpus_80386, 40000000, 1, 5000, 0x0308, 0, 0, 0, 7,7,3,3, 5}, + {"", 0} + } }, { - .package = CPU_PKG_486SLC_IBM, - .manufacturer = "IBM", - .name = "486SLC3", - .internal_name = "ibm486slc3", - .cpus = (const CPU[]) { - {"60", CPU_IBM486SLC, fpus_80386, 60000000, 3, 5000, 0xA439, 0, 0, 0, 12,12,9,9, 7}, - {"75", CPU_IBM486SLC, fpus_80386, 75000000, 3, 5000, 0xA439, 0, 0, 0, 12,12,9,9, 9}, - {"100", CPU_IBM486SLC, fpus_80386, 100000000, 3, 5000, 0xA439, 0, 0, 0, 18,18,9,9, 12}, - {"", 0} - } + .package = CPU_PKG_M6117, + .manufacturer = "ALi", + .name = "M6117", + .internal_name = "m6117", + .cpus = (const CPU[]) { /* All timings and edx_reset values assumed. */ + {"33", CPU_386SX, fpus_none, 33333333, 1, 5000, 0x2308, 0, 0, 0, 6,6,3,3, 4}, + {"40", CPU_386SX, fpus_none, 40000000, 1, 5000, 0x2308, 0, 0, 0, 7,7,3,3, 5}, + {"", 0} + } }, { - .package = CPU_PKG_486BL, - .manufacturer = "IBM", - .name = "486BL2", - .internal_name = "ibm486bl2", - .cpus = (const CPU[]) { - {"50", CPU_IBM486BL, fpus_80386, 50000000, 2, 5000, 0xA439, 0, 0, 0, 8,8,6,6, 6}, - {"66", CPU_IBM486BL, fpus_80386, 66666666, 2, 5000, 0xA439, 0, 0, 0, 12,12,6,6, 8}, - {"", 0} - } + .package = CPU_PKG_386SLC_IBM, + .manufacturer = "IBM", + .name = "386SLC", + .internal_name = "ibm386slc", + .cpus = (const CPU[]) { + {"16", CPU_IBM386SLC, fpus_80386, 16000000, 1, 5000, 0xA301, 0, 0, 0, 3,3,3,3, 2}, + {"20", CPU_IBM386SLC, fpus_80386, 20000000, 1, 5000, 0xA301, 0, 0, 0, 4,4,3,3, 3}, + {"25", CPU_IBM386SLC, fpus_80386, 25000000, 1, 5000, 0xA301, 0, 0, 0, 4,4,3,3, 3}, + {"", 0} + } }, { - .package = CPU_PKG_486BL, - .manufacturer = "IBM", - .name = "486BL3", - .internal_name = "ibm486bl3", - .cpus = (const CPU[]) { - {"75", CPU_IBM486BL, fpus_80386, 75000000, 3, 5000, 0xA439, 0, 0, 0, 12,12,9,9, 9}, - {"100", CPU_IBM486BL, fpus_80386, 100000000, 3, 5000, 0xA439, 0, 0, 0, 18,18,9,9, 12}, - {"", 0} - } + .package = CPU_PKG_386SX, + .manufacturer = "Cyrix", + .name = "Cx486SLC", + .internal_name = "cx486slc", + .cpus = (const CPU[]) { + {"20", CPU_486SLC, fpus_80386, 20000000, 1, 5000, 0x400, 0, 0x0000, 0, 4,4,3,3, 3}, + {"25", CPU_486SLC, fpus_80386, 25000000, 1, 5000, 0x400, 0, 0x0000, 0, 4,4,3,3, 3}, + {"33", CPU_486SLC, fpus_80386, 33333333, 1, 5000, 0x400, 0, 0x0000, 0, 6,6,3,3, 4}, + {"", 0} + } }, { - .package = CPU_PKG_386DX, - .manufacturer = "Cyrix", - .name = "Cx486DLC", - .internal_name = "cx486dlc", - .cpus = (const CPU[]) { - {"25", CPU_486DLC, fpus_80386, 25000000, 1, 5000, 0x401, 0, 0x0001, 0, 4, 4,3,3, 3}, - {"33", CPU_486DLC, fpus_80386, 33333333, 1, 5000, 0x401, 0, 0x0001, 0, 6, 6,3,3, 4}, - {"40", CPU_486DLC, fpus_80386, 40000000, 1, 5000, 0x401, 0, 0x0001, 0, 7, 7,3,3, 5}, - {"", 0} - } + .package = CPU_PKG_386SX, + .manufacturer = "Cyrix", + .name = "Cx486SRx2", + .internal_name = "cx486srx2", + .cpus = (const CPU[]) { + {"32", CPU_486SLC, fpus_80386, 32000000, 2, 5000, 0x406, 0, 0x0006, 0, 6,6,6,6, 4}, + {"40", CPU_486SLC, fpus_80386, 40000000, 2, 5000, 0x406, 0, 0x0006, 0, 8,8,6,6, 6}, + {"50", CPU_486SLC, fpus_80386, 50000000, 2, 5000, 0x406, 0, 0x0006, 0, 8,8,6,6, 6}, + {"", 0} + } }, { - .package = CPU_PKG_386DX, - .manufacturer = "Cyrix", - .name = "Cx486DRx2", - .internal_name = "cx486drx2", - .cpus = (const CPU[]) { - {"32", CPU_486DLC, fpus_80386, 32000000, 2, 5000, 0x407, 0, 0x0007, 0, 6, 6,6,6, 4}, - {"40", CPU_486DLC, fpus_80386, 40000000, 2, 5000, 0x407, 0, 0x0007, 0, 8, 8,6,6, 6}, - {"50", CPU_486DLC, fpus_80386, 50000000, 2, 5000, 0x407, 0, 0x0007, 0, 8, 8,6,6, 6}, - {"66", CPU_486DLC, fpus_80386, 66666666, 2, 5000, 0x407, 0, 0x0007, 0, 12,12,6,6, 8}, - {"", 0} - } + .package = CPU_PKG_486SLC_IBM, + .manufacturer = "IBM", + .name = "486SLC", + .internal_name = "ibm486slc", + .cpus = (const CPU[]) { + {"33", CPU_IBM486SLC, fpus_80386, 33333333, 1, 5000, 0xA401, 0, 0, 0, 6,6,3,3, 4}, + {"", 0} + } }, { - .package = CPU_PKG_SOCKET1, - .manufacturer = "Intel", - .name = "i486SX", - .internal_name = "i486sx", - .cpus = (const CPU[]) { - {"16", CPU_i486SX, fpus_486sx, 16000000, 1, 5000, 0x420, 0, 0, CPU_SUPPORTS_DYNAREC, 3, 3,3,3, 2}, - {"20", CPU_i486SX, fpus_486sx, 20000000, 1, 5000, 0x420, 0, 0, CPU_SUPPORTS_DYNAREC, 4, 4,3,3, 3}, - {"25", CPU_i486SX, fpus_486sx, 25000000, 1, 5000, 0x422, 0, 0, CPU_SUPPORTS_DYNAREC, 4, 4,3,3, 3}, - {"33", CPU_i486SX, fpus_486sx, 33333333, 1, 5000, 0x422, 0, 0, CPU_SUPPORTS_DYNAREC, 6, 6,3,3, 4}, - {"", 0} - } + .package = CPU_PKG_486SLC_IBM, + .manufacturer = "IBM", + .name = "486SLC2", + .internal_name = "ibm486slc2", + .cpus = (const CPU[]) { + {"40", CPU_IBM486SLC, fpus_80386, 40000000, 2, 5000, 0xA421, 0, 0, 0, 7,7,6,6, 5}, + {"50", CPU_IBM486SLC, fpus_80386, 50000000, 2, 5000, 0xA421, 0, 0, 0, 8,8,6,6, 6}, + {"66", CPU_IBM486SLC, fpus_80386, 66666666, 2, 5000, 0xA421, 0, 0, 0, 12,12,6,6, 8}, + {"", 0} + } }, { - .package = CPU_PKG_SOCKET1, - .manufacturer = "Intel", - .name = "i486SX (SL-Enhanced)", - .internal_name = "i486sx_slenh", - .cpus = (const CPU[]) { - {"25", CPU_i486SX_SLENH, fpus_486sx, 25000000, 1, 5000, 0x423, 0x423, 0, CPU_SUPPORTS_DYNAREC, 4, 4,3,3, 3}, - {"33", CPU_i486SX_SLENH, fpus_486sx, 33333333, 1, 5000, 0x42a, 0x42a, 0, CPU_SUPPORTS_DYNAREC, 6, 6,3,3, 4}, - {"", 0} - } + .package = CPU_PKG_486SLC_IBM, + .manufacturer = "IBM", + .name = "486SLC3", + .internal_name = "ibm486slc3", + .cpus = (const CPU[]) { + {"60", CPU_IBM486SLC, fpus_80386, 60000000, 3, 5000, 0xA439, 0, 0, 0, 12,12,9,9, 7}, + {"75", CPU_IBM486SLC, fpus_80386, 75000000, 3, 5000, 0xA439, 0, 0, 0, 12,12,9,9, 9}, + {"100", CPU_IBM486SLC, fpus_80386, 100000000, 3, 5000, 0xA439, 0, 0, 0, 18,18,9,9, 12}, + {"", 0} + } }, { - .package = CPU_PKG_SOCKET1, - .manufacturer = "Intel", - .name = "i486SX2", - .internal_name = "i486sx2", - .cpus = (const CPU[]) { - {"50", CPU_i486SX_SLENH, fpus_486sx, 50000000, 2, 5000, 0x45b, 0x45b, 0, CPU_SUPPORTS_DYNAREC, 8, 8,6,6, 6}, - {"66 (Q0569)", CPU_i486SX_SLENH, fpus_486sx, 66666666, 2, 5000, 0x45b, 0x45b, 0, CPU_SUPPORTS_DYNAREC, 8, 8,6,6, 8}, - {"", 0} - } + .package = CPU_PKG_486BL, + .manufacturer = "IBM", + .name = "486BL2", + .internal_name = "ibm486bl2", + .cpus = (const CPU[]) { + {"50", CPU_IBM486BL, fpus_80386, 50000000, 2, 5000, 0xA439, 0, 0, 0, 8,8,6,6, 6}, + {"66", CPU_IBM486BL, fpus_80386, 66666666, 2, 5000, 0xA439, 0, 0, 0, 12,12,6,6, 8}, + {"", 0} + } }, { - .package = CPU_PKG_SOCKET1, - .manufacturer = "Intel", - .name = "i486DX", - .internal_name = "i486dx", - .cpus = (const CPU[]) { - {"25", CPU_i486DX, fpus_internal, 25000000, 1, 5000, 0x404, 0, 0, CPU_SUPPORTS_DYNAREC, 4, 4,3,3, 3}, - {"33", CPU_i486DX, fpus_internal, 33333333, 1, 5000, 0x404, 0, 0, CPU_SUPPORTS_DYNAREC, 6, 6,3,3, 4}, - {"50", CPU_i486DX, fpus_internal, 50000000, 1, 5000, 0x411, 0, 0, CPU_SUPPORTS_DYNAREC, 8, 8,4,4, 6}, - {"", 0} - } + .package = CPU_PKG_486BL, + .manufacturer = "IBM", + .name = "486BL3", + .internal_name = "ibm486bl3", + .cpus = (const CPU[]) { + {"75", CPU_IBM486BL, fpus_80386, 75000000, 3, 5000, 0xA439, 0, 0, 0, 12,12,9,9, 9}, + {"100", CPU_IBM486BL, fpus_80386, 100000000, 3, 5000, 0xA439, 0, 0, 0, 18,18,9,9, 12}, + {"", 0} + } }, { - .package = CPU_PKG_SOCKET1, - .manufacturer = "Intel", - .name = "i486DX (SL-Enhanced)", - .internal_name = "i486dx_slenh", - .cpus = (const CPU[]) { - {"33", CPU_i486DX_SLENH, fpus_internal, 33333333, 1, 5000, 0x414, 0x414, 0, CPU_SUPPORTS_DYNAREC, 6, 6,3,3, 4}, - {"50", CPU_i486DX_SLENH, fpus_internal, 50000000, 1, 5000, 0x414, 0x414, 0, CPU_SUPPORTS_DYNAREC, 8, 8,4,4, 6}, - {"", 0} - } + .package = CPU_PKG_386DX, + .manufacturer = "Cyrix", + .name = "Cx486DLC", + .internal_name = "cx486dlc", + .cpus = (const CPU[]) { + {"25", CPU_486DLC, fpus_80386, 25000000, 1, 5000, 0x401, 0, 0x0001, 0, 4, 4,3,3, 3}, + {"33", CPU_486DLC, fpus_80386, 33333333, 1, 5000, 0x401, 0, 0x0001, 0, 6, 6,3,3, 4}, + {"40", CPU_486DLC, fpus_80386, 40000000, 1, 5000, 0x401, 0, 0x0001, 0, 7, 7,3,3, 5}, + {"", 0} + } }, { - .package = CPU_PKG_SOCKET1, - .manufacturer = "Intel", - .name = "i486DX2", - .internal_name = "i486dx2", - .cpus = (const CPU[]) { - {"40", CPU_i486DX, fpus_internal, 40000000, 2, 5000, 0x430, 0, 0, CPU_SUPPORTS_DYNAREC, 7, 7,6,6, 5}, - {"50", CPU_i486DX, fpus_internal, 50000000, 2, 5000, 0x433, 0, 0, CPU_SUPPORTS_DYNAREC, 8, 8,6,6, 6}, - {"66", CPU_i486DX, fpus_internal, 66666666, 2, 5000, 0x433, 0, 0, CPU_SUPPORTS_DYNAREC, 12,12,6,6, 8}, - {"", 0} - } + .package = CPU_PKG_386DX, + .manufacturer = "Cyrix", + .name = "Cx486DRx2", + .internal_name = "cx486drx2", + .cpus = (const CPU[]) { + {"32", CPU_486DLC, fpus_80386, 32000000, 2, 5000, 0x407, 0, 0x0007, 0, 6, 6,6,6, 4}, + {"40", CPU_486DLC, fpus_80386, 40000000, 2, 5000, 0x407, 0, 0x0007, 0, 8, 8,6,6, 6}, + {"50", CPU_486DLC, fpus_80386, 50000000, 2, 5000, 0x407, 0, 0x0007, 0, 8, 8,6,6, 6}, + {"66", CPU_486DLC, fpus_80386, 66666666, 2, 5000, 0x407, 0, 0x0007, 0, 12,12,6,6, 8}, + {"", 0} + } }, { - .package = CPU_PKG_SOCKET1, - .manufacturer = "Intel", - .name = "i486DX2 (SL-Enhanced)", - .internal_name = "i486dx2_slenh", - .cpus = (const CPU[]) { - {"40", CPU_i486DX_SLENH, fpus_internal, 40000000, 2, 5000, 0x435, 0x435, 0, CPU_SUPPORTS_DYNAREC, 7, 7,6,6, 5}, - {"50", CPU_i486DX_SLENH, fpus_internal, 50000000, 2, 5000, 0x435, 0x435, 0, CPU_SUPPORTS_DYNAREC, 8, 8,6,6, 6}, - {"66", CPU_i486DX_SLENH, fpus_internal, 66666666, 2, 5000, 0x435, 0x435, 0, CPU_SUPPORTS_DYNAREC, 12,12,6,6, 8}, - {"", 0} - } + .package = CPU_PKG_SOCKET1, + .manufacturer = "Intel", + .name = "i486SX", + .internal_name = "i486sx", + .cpus = (const CPU[]) { + {"16", CPU_i486SX, fpus_486sx, 16000000, 1, 5000, 0x420, 0, 0, CPU_SUPPORTS_DYNAREC, 3, 3,3,3, 2}, + {"20", CPU_i486SX, fpus_486sx, 20000000, 1, 5000, 0x420, 0, 0, CPU_SUPPORTS_DYNAREC, 4, 4,3,3, 3}, + {"25", CPU_i486SX, fpus_486sx, 25000000, 1, 5000, 0x422, 0, 0, CPU_SUPPORTS_DYNAREC, 4, 4,3,3, 3}, + {"33", CPU_i486SX, fpus_486sx, 33333333, 1, 5000, 0x422, 0, 0, CPU_SUPPORTS_DYNAREC, 6, 6,3,3, 4}, + {"", 0} + } }, { - .package = CPU_PKG_SOCKET3_PC330, - .manufacturer = "Intel", - .name = "i486DX2", - .internal_name = "i486dx2_pc330", - .cpus = (const CPU[]) { - {"50", CPU_i486DX_SLENH, fpus_internal, 50000000, 2, 5000, 0x470, 0x470, 0, CPU_SUPPORTS_DYNAREC, 8, 8,6,6, 6}, - {"66", CPU_i486DX_SLENH, fpus_internal, 66666666, 2, 5000, 0x470, 0x470, 0, CPU_SUPPORTS_DYNAREC, 12,12,6,6, 8}, - {"", 0} - } + .package = CPU_PKG_SOCKET1, + .manufacturer = "Intel", + .name = "i486SX-S", + .internal_name = "i486sx_slenh", + .cpus = (const CPU[]) { + {"25", CPU_i486SX_SLENH, fpus_486sx, 25000000, 1, 5000, 0x423, 0x423, 0, CPU_SUPPORTS_DYNAREC, 4, 4,3,3, 3}, + {"33", CPU_i486SX_SLENH, fpus_486sx, 33333333, 1, 5000, 0x42a, 0x42a, 0, CPU_SUPPORTS_DYNAREC, 6, 6,3,3, 4}, + {"", 0} + } }, { - .package = CPU_PKG_SOCKET1 | CPU_PKG_SOCKET3_PC330, /*OEM versions are 3.3V, Retail versions are 3.3V with a 5V regulator for installation in older boards. hey are functionally identical*/ - .manufacturer = "Intel", - .name = "iDX4", - .internal_name = "idx4", - .cpus = (const CPU[]) { - {"75", CPU_i486DX_SLENH, fpus_internal, 75000000, 3.0, 5000, 0x480, 0x480, 0x0000, CPU_SUPPORTS_DYNAREC, 12,12, 9, 9, 9}, - {"100", CPU_i486DX_SLENH, fpus_internal, 100000000, 3.0, 5000, 0x483, 0x483, 0x0000, CPU_SUPPORTS_DYNAREC, 18,18, 9, 9, 12}, - {"", 0} - } + .package = CPU_PKG_SOCKET1, + .manufacturer = "Intel", + .name = "i486SX2", + .internal_name = "i486sx2", + .cpus = (const CPU[]) { + {"50", CPU_i486SX_SLENH, fpus_486sx, 50000000, 2, 5000, 0x45b, 0x45b, 0, CPU_SUPPORTS_DYNAREC, 8, 8,6,6, 6}, + {"66 (Q0569)", CPU_i486SX_SLENH, fpus_486sx, 66666666, 2, 5000, 0x45b, 0x45b, 0, CPU_SUPPORTS_DYNAREC, 8, 8,6,6, 8}, + {"", 0} + } }, { - .package = CPU_PKG_SOCKET3 | CPU_PKG_SOCKET3_PC330, - .manufacturer = "Intel", - .name = "Pentium OverDrive", - .internal_name = "pentium_p24t", - .cpus = (const CPU[]) { - {"63", CPU_P24T, fpus_internal, 62500000, 2.5, 5000, 0x1531, 0x1531, 0x0000, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 10,10,7,7, 15/2}, - {"83", CPU_P24T, fpus_internal, 83333333, 2.5, 5000, 0x1532, 0x1532, 0x0000, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 15,15,8,8, 10}, - {"", 0} - } + .package = CPU_PKG_SOCKET1, + .manufacturer = "Intel", + .name = "i486DX", + .internal_name = "i486dx", + .cpus = (const CPU[]) { + {"25", CPU_i486DX, fpus_internal, 25000000, 1, 5000, 0x404, 0, 0, CPU_SUPPORTS_DYNAREC, 4, 4,3,3, 3}, + {"33", CPU_i486DX, fpus_internal, 33333333, 1, 5000, 0x404, 0, 0, CPU_SUPPORTS_DYNAREC, 6, 6,3,3, 4}, + {"50", CPU_i486DX, fpus_internal, 50000000, 1, 5000, 0x411, 0, 0, CPU_SUPPORTS_DYNAREC, 8, 8,4,4, 6}, + {"", 0} + } }, { - .package = CPU_PKG_SOCKET1, - .manufacturer = "AMD", - .name = "Am486SX", - .internal_name = "am486sx", - .cpus = (const CPU[]) { - {"33", CPU_Am486SX, fpus_486sx, 33333333, 1, 5000, 0x422, 0, 0, CPU_SUPPORTS_DYNAREC, 6, 6, 3, 3, 4}, - {"40", CPU_Am486SX, fpus_486sx, 40000000, 1, 5000, 0x422, 0, 0, CPU_SUPPORTS_DYNAREC, 7, 7, 3, 3, 5}, - {"", 0} - } + .package = CPU_PKG_SOCKET1, + .manufacturer = "Intel", + .name = "i486DX-S", + .internal_name = "i486dx_slenh", + .cpus = (const CPU[]) { + {"33", CPU_i486DX_SLENH, fpus_internal, 33333333, 1, 5000, 0x414, 0x414, 0, CPU_SUPPORTS_DYNAREC, 6, 6,3,3, 4}, + {"50", CPU_i486DX_SLENH, fpus_internal, 50000000, 1, 5000, 0x414, 0x414, 0, CPU_SUPPORTS_DYNAREC, 8, 8,4,4, 6}, + {"", 0} + } }, { - .package = CPU_PKG_SOCKET1, - .manufacturer = "AMD", - .name = "Am486SX2", - .internal_name = "am486sx2", - .cpus = (const CPU[]) { - {"50", CPU_Am486SX, fpus_486sx, 50000000, 2, 5000, 0x45b, 0, 0, CPU_SUPPORTS_DYNAREC, 8, 8, 6, 6, 6}, - {"66", CPU_Am486SX, fpus_486sx, 66666666, 2, 5000, 0x45b, 0, 0, CPU_SUPPORTS_DYNAREC, 12,12, 6, 6, 8}, - {"", 0} - } + .package = CPU_PKG_SOCKET1, + .manufacturer = "Intel", + .name = "i486DX2", + .internal_name = "i486dx2", + .cpus = (const CPU[]) { + {"40", CPU_i486DX, fpus_internal, 40000000, 2, 5000, 0x430, 0, 0, CPU_SUPPORTS_DYNAREC, 7, 7,6,6, 5}, + {"50", CPU_i486DX, fpus_internal, 50000000, 2, 5000, 0x433, 0, 0, CPU_SUPPORTS_DYNAREC, 8, 8,6,6, 6}, + {"66", CPU_i486DX, fpus_internal, 66666666, 2, 5000, 0x433, 0, 0, CPU_SUPPORTS_DYNAREC, 12,12,6,6, 8}, + {"", 0} + } }, { - .package = CPU_PKG_SOCKET1, - .manufacturer = "AMD", - .name = "Am486DX", - .internal_name = "am486dx", - .cpus = (const CPU[]) { - {"33", CPU_Am486DX, fpus_internal, 33333333, 1, 5000, 0x412, 0, 0, CPU_SUPPORTS_DYNAREC, 6, 6, 3, 3, 4}, - {"40", CPU_Am486DX, fpus_internal, 40000000, 1, 5000, 0x412, 0, 0, CPU_SUPPORTS_DYNAREC, 7, 7, 3, 3, 5}, - {"", 0} - } + .package = CPU_PKG_SOCKET1, + .manufacturer = "Intel", + .name = "i486DX2-S", + .internal_name = "i486dx2_slenh", + .cpus = (const CPU[]) { + {"40", CPU_i486DX_SLENH, fpus_internal, 40000000, 2, 5000, 0x435, 0x435, 0, CPU_SUPPORTS_DYNAREC, 7, 7,6,6, 5}, + {"50", CPU_i486DX_SLENH, fpus_internal, 50000000, 2, 5000, 0x435, 0x435, 0, CPU_SUPPORTS_DYNAREC, 8, 8,6,6, 6}, + {"66", CPU_i486DX_SLENH, fpus_internal, 66666666, 2, 5000, 0x435, 0x435, 0, CPU_SUPPORTS_DYNAREC, 12,12,6,6, 8}, + {"", 0} + } }, { - .package = CPU_PKG_SOCKET1, - .manufacturer = "AMD", - .name = "Am486DX2", - .internal_name = "am486dx2", - .cpus = (const CPU[]) { - {"50", CPU_Am486DX, fpus_internal, 50000000, 2, 5000, 0x432, 0, 0, CPU_SUPPORTS_DYNAREC, 8, 8, 6, 6, 6}, - {"66", CPU_Am486DX, fpus_internal, 66666666, 2, 5000, 0x432, 0, 0, CPU_SUPPORTS_DYNAREC, 12,12, 6, 6, 8}, - {"80", CPU_Am486DX, fpus_internal, 80000000, 2, 5000, 0x432, 0, 0, CPU_SUPPORTS_DYNAREC, 14,14, 6, 6, 10}, - {"", 0} - } + .package = CPU_PKG_SOCKET1 | CPU_PKG_SOCKET3_PC330, + .manufacturer = "Intel", + .name = "i486DX2 WB", + .internal_name = "i486dx2_pc330", + .cpus = (const CPU[]) { + {"50", CPU_i486DX_SLENH, fpus_internal, 50000000, 2, 5000, 0x436, 0x436, 0, CPU_SUPPORTS_DYNAREC, 8, 8,6,6, 6}, + {"66", CPU_i486DX_SLENH, fpus_internal, 66666666, 2, 5000, 0x436, 0x436, 0, CPU_SUPPORTS_DYNAREC, 12,12,6,6, 8}, + {"", 0} + } }, { - .package = CPU_PKG_SOCKET1, - .manufacturer = "AMD", - .name = "Am486DXL", - .internal_name = "am486dxl", - .cpus = (const CPU[]) { - {"33", CPU_Am486DXL, fpus_internal, 33333333, 1, 5000, 0x422, 0, 0, CPU_SUPPORTS_DYNAREC, 6, 6, 3, 3, 4}, - {"40", CPU_Am486DXL, fpus_internal, 40000000, 1, 5000, 0x422, 0, 0, CPU_SUPPORTS_DYNAREC, 7, 7, 3, 3, 5}, - {"", 0} - } + .package = CPU_PKG_SOCKET1 | CPU_PKG_SOCKET3_PC330, /*OEM versions are 3.3V, Retail versions are 3.3V with a 5V regulator for installation in older boards. They are functionally identical*/ + .manufacturer = "Intel", + .name = "iDX4", + .internal_name = "idx4", + .cpus = (const CPU[]) { + {"75", CPU_i486DX_SLENH, fpus_internal, 75000000, 3.0, 5000, 0x480, 0x480, 0x0000, CPU_SUPPORTS_DYNAREC, 12,12, 9, 9, 9}, + {"100", CPU_i486DX_SLENH, fpus_internal, 100000000, 3.0, 5000, 0x483, 0x483, 0x0000, CPU_SUPPORTS_DYNAREC, 18,18, 9, 9, 12}, + {"", 0} + } }, { - .package = CPU_PKG_SOCKET1, - .manufacturer = "AMD", - .name = "Am486DXL2", - .internal_name = "am486dxl2", - .cpus = (const CPU[]) { - {"50", CPU_Am486DXL, fpus_internal, 50000000, 2, 5000, 0x432, 0, 0, CPU_SUPPORTS_DYNAREC, 8, 8, 6, 6, 6}, - {"66", CPU_Am486DXL, fpus_internal, 66666666, 2, 5000, 0x432, 0, 0, CPU_SUPPORTS_DYNAREC, 12,12, 6, 6, 8}, - {"80", CPU_Am486DXL, fpus_internal, 80000000, 2, 5000, 0x432, 0, 0, CPU_SUPPORTS_DYNAREC, 14,14, 6, 6, 10}, - {"", 0} - } - }, { - .package = CPU_PKG_SOCKET3, - .manufacturer = "AMD", - .name = "Am486DX4", - .internal_name = "am486dx4", - .cpus = (const CPU[]) { - {"75", CPU_Am486DX, fpus_internal, 75000000, 3.0, 5000, 0x432, 0, 0, CPU_SUPPORTS_DYNAREC, 12,12, 9, 9, 9}, - {"90", CPU_Am486DX, fpus_internal, 90000000, 3.0, 5000, 0x432, 0, 0, CPU_SUPPORTS_DYNAREC, 15,15, 9, 9, 12}, - {"100", CPU_Am486DX, fpus_internal, 100000000, 3.0, 5000, 0x432, 0, 0, CPU_SUPPORTS_DYNAREC, 15,15, 9, 9, 12}, - {"120", CPU_Am486DX, fpus_internal, 120000000, 3.0, 5000, 0x432, 0, 0, CPU_SUPPORTS_DYNAREC, 21,21, 9, 9, 15}, - {"", 0} - } - }, - { - .package = CPU_PKG_SOCKET3, - .manufacturer = "AMD", - .name = "Am486DX2 (Enhanced)", - .internal_name = "am486dx2_slenh", - .cpus = (const CPU[]) { - {"66", CPU_ENH_Am486DX, fpus_internal, 66666666, 2, 5000, 0x435, 0x435, 0, CPU_SUPPORTS_DYNAREC, 12,12, 6, 6, 8}, - {"80", CPU_ENH_Am486DX, fpus_internal, 80000000, 2, 5000, 0x435, 0x435, 0, CPU_SUPPORTS_DYNAREC, 14,14, 6, 6, 10}, - {"", 0} - } + .package = CPU_PKG_SOCKET3 | CPU_PKG_SOCKET3_PC330, + .manufacturer = "Intel", + .name = "Pentium OverDrive", + .internal_name = "pentium_p24t", + .cpus = (const CPU[]) { + {"63", CPU_P24T, fpus_internal, 62500000, 2.5, 5000, 0x1531, 0x1531, 0x0000, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 10,10,7,7, 15/2}, + {"83", CPU_P24T, fpus_internal, 83333333, 2.5, 5000, 0x1532, 0x1532, 0x0000, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 15,15,8,8, 10}, + {"", 0} + } }, { - .package = CPU_PKG_SOCKET3, - .manufacturer = "AMD", - .name = "Am486DX4 (Enhanced)", - .internal_name = "am486dx4_slenh", - .cpus = (const CPU[]) { - {"75", CPU_ENH_Am486DX, fpus_internal, 75000000, 3.0, 5000, 0x482, 0x482, 0, CPU_SUPPORTS_DYNAREC, 12,12, 9, 9, 9}, - {"100", CPU_ENH_Am486DX, fpus_internal, 100000000, 3.0, 5000, 0x482, 0x482, 0, CPU_SUPPORTS_DYNAREC, 15,15, 9, 9, 12}, - {"120", CPU_ENH_Am486DX, fpus_internal, 120000000, 3.0, 5000, 0x482, 0x482, 0, CPU_SUPPORTS_DYNAREC, 21,21, 9, 9, 15}, - {"", 0} - } + .package = CPU_PKG_SOCKET1, + .manufacturer = "AMD", + .name = "Am486SX", + .internal_name = "am486sx", + .cpus = (const CPU[]) { + {"33", CPU_Am486SX, fpus_486sx, 33333333, 1, 5000, 0x422, 0, 0, CPU_SUPPORTS_DYNAREC, 6, 6, 3, 3, 4}, + {"40", CPU_Am486SX, fpus_486sx, 40000000, 1, 5000, 0x422, 0, 0, CPU_SUPPORTS_DYNAREC, 7, 7, 3, 3, 5}, + {"", 0} + } }, { - .package = CPU_PKG_SOCKET3, - .manufacturer = "AMD", - .name = "Am5x86", - .internal_name = "am5x86", - .cpus = (const CPU[]) { - {"P75", CPU_ENH_Am486DX, fpus_internal, 133333333, 4.0, 5000, 0x4e0, 0x4e0, 0, CPU_SUPPORTS_DYNAREC, 24,24,12,12, 16}, - {"P75+", CPU_ENH_Am486DX, fpus_internal, 150000000, 3.0, 5000, 0x482, 0x482, 0, CPU_SUPPORTS_DYNAREC, 28,28,12,12, 20},/*The rare P75+ was indeed a triple-clocked 150 MHz according to research*/ - {"P90", CPU_ENH_Am486DX, fpus_internal, 160000000, 4.0, 5000, 0x4e0, 0x4e0, 0, CPU_SUPPORTS_DYNAREC, 28,28,12,12, 20},/*160 MHz on a 40 MHz bus was a common overclock and "5x86/P90" was used by a number of BIOSes to refer to that configuration*/ - {"", 0} - } + .package = CPU_PKG_SOCKET1, + .manufacturer = "AMD", + .name = "Am486SX2", + .internal_name = "am486sx2", + .cpus = (const CPU[]) { + {"50", CPU_Am486SX, fpus_486sx, 50000000, 2, 5000, 0x45b, 0, 0, CPU_SUPPORTS_DYNAREC, 8, 8, 6, 6, 6}, + {"66", CPU_Am486SX, fpus_486sx, 66666666, 2, 5000, 0x45b, 0, 0, CPU_SUPPORTS_DYNAREC, 12,12, 6, 6, 8}, + {"", 0} + } }, { - .package = CPU_PKG_SOCKET1, - .manufacturer = "Cyrix", - .name = "Cx486S", - .internal_name = "cx486s", - .cpus = (const CPU[]) { - {"25", CPU_Cx486S, fpus_486sx, 25000000, 1.0, 5000, 0x420, 0, 0x0010, CPU_SUPPORTS_DYNAREC, 4, 4, 3, 3, 3}, - {"33", CPU_Cx486S, fpus_486sx, 33333333, 1.0, 5000, 0x420, 0, 0x0010, CPU_SUPPORTS_DYNAREC, 6, 6, 3, 3, 4}, - {"40", CPU_Cx486S, fpus_486sx, 40000000, 1.0, 5000, 0x420, 0, 0x0010, CPU_SUPPORTS_DYNAREC, 7, 7, 3, 3, 5}, - {"", 0} - } + .package = CPU_PKG_SOCKET1, + .manufacturer = "AMD", + .name = "Am486DX", + .internal_name = "am486dx", + .cpus = (const CPU[]) { + {"33", CPU_Am486DX, fpus_internal, 33333333, 1, 5000, 0x412, 0, 0, CPU_SUPPORTS_DYNAREC, 6, 6, 3, 3, 4}, + {"40", CPU_Am486DX, fpus_internal, 40000000, 1, 5000, 0x412, 0, 0, CPU_SUPPORTS_DYNAREC, 7, 7, 3, 3, 5}, + {"", 0} + } }, { - .package = CPU_PKG_SOCKET1, - .manufacturer = "Cyrix", - .name = "Cx486DX", - .internal_name = "cx486dx", - .cpus = (const CPU[]) { - {"33", CPU_Cx486DX, fpus_internal, 33333333, 1.0, 5000, 0x430, 0, 0x051a, CPU_SUPPORTS_DYNAREC, 6, 6, 3, 3, 4}, - {"40", CPU_Cx486DX, fpus_internal, 40000000, 1.0, 5000, 0x430, 0, 0x051a, CPU_SUPPORTS_DYNAREC, 7, 7, 3, 3, 5}, - {"", 0} - } + .package = CPU_PKG_SOCKET1, + .manufacturer = "AMD", + .name = "Am486DX2", + .internal_name = "am486dx2", + .cpus = (const CPU[]) { + {"50", CPU_Am486DX, fpus_internal, 50000000, 2, 5000, 0x432, 0, 0, CPU_SUPPORTS_DYNAREC, 8, 8, 6, 6, 6}, + {"66", CPU_Am486DX, fpus_internal, 66666666, 2, 5000, 0x432, 0, 0, CPU_SUPPORTS_DYNAREC, 12,12, 6, 6, 8}, + {"80", CPU_Am486DX, fpus_internal, 80000000, 2, 5000, 0x432, 0, 0, CPU_SUPPORTS_DYNAREC, 14,14, 6, 6, 10}, + {"", 0} + } }, { - .package = CPU_PKG_SOCKET1, - .manufacturer = "Cyrix", - .name = "Cx486DX2", - .internal_name = "cx486dx2", - .cpus = (const CPU[]) { - {"50", CPU_Cx486DX, fpus_internal, 50000000, 2.0, 5000, 0x430, 0, 0x081b, CPU_SUPPORTS_DYNAREC, 8, 8, 6, 6, 6}, - {"66", CPU_Cx486DX, fpus_internal, 66666666, 2.0, 5000, 0x430, 0, 0x0b1b, CPU_SUPPORTS_DYNAREC, 12,12, 6, 6, 8}, - {"80", CPU_Cx486DX, fpus_internal, 80000000, 2.0, 5000, 0x430, 0, 0x311b, CPU_SUPPORTS_DYNAREC, 14,14, 6, 6, 10}, - {"", 0} - } + .package = CPU_PKG_SOCKET1, + .manufacturer = "AMD", + .name = "Am486DXL", + .internal_name = "am486dxl", + .cpus = (const CPU[]) { + {"33", CPU_Am486DXL, fpus_internal, 33333333, 1, 5000, 0x422, 0, 0, CPU_SUPPORTS_DYNAREC, 6, 6, 3, 3, 4}, + {"40", CPU_Am486DXL, fpus_internal, 40000000, 1, 5000, 0x422, 0, 0, CPU_SUPPORTS_DYNAREC, 7, 7, 3, 3, 5}, + {"", 0} + } }, { - .package = CPU_PKG_SOCKET3, - .manufacturer = "Cyrix", - .name = "Cx486DX4", - .internal_name = "cx486dx4", - .cpus = (const CPU[]) { - {"75", CPU_Cx486DX, fpus_internal, 75000000, 3.0, 5000, 0x480, 0, 0x361f, CPU_SUPPORTS_DYNAREC, 12,12, 9, 9, 9}, - {"100", CPU_Cx486DX, fpus_internal, 100000000, 3.0, 5000, 0x480, 0, 0x361f, CPU_SUPPORTS_DYNAREC, 15,15, 9, 9, 12}, - {"", 0} - } + .package = CPU_PKG_SOCKET1, + .manufacturer = "AMD", + .name = "Am486DXL2", + .internal_name = "am486dxl2", + .cpus = (const CPU[]) { + {"50", CPU_Am486DXL, fpus_internal, 50000000, 2, 5000, 0x432, 0, 0, CPU_SUPPORTS_DYNAREC, 8, 8, 6, 6, 6}, + {"66", CPU_Am486DXL, fpus_internal, 66666666, 2, 5000, 0x432, 0, 0, CPU_SUPPORTS_DYNAREC, 12,12, 6, 6, 8}, + {"80", CPU_Am486DXL, fpus_internal, 80000000, 2, 5000, 0x432, 0, 0, CPU_SUPPORTS_DYNAREC, 14,14, 6, 6, 10}, + {"", 0} + } }, { - .package = CPU_PKG_SOCKET3, - .manufacturer = "Cyrix", - .name = "Cx5x86", - .internal_name = "cx5x86", - .cpus = (const CPU[]) { - {"80", CPU_Cx5x86, fpus_internal, 80000000, 2.0, 5000, 0x480, 0, 0x002f, CPU_SUPPORTS_DYNAREC, 14,14, 6, 6, 10}, /*If we're including the Pentium 50, might as well include this*/ - {"100", CPU_Cx5x86, fpus_internal, 100000000, 3.0, 5000, 0x480, 0, 0x002f, CPU_SUPPORTS_DYNAREC, 15,15, 9, 9, 12}, - {"120", CPU_Cx5x86, fpus_internal, 120000000, 3.0, 5000, 0x480, 0, 0x002f, CPU_SUPPORTS_DYNAREC, 21,21, 9, 9, 15}, - {"133", CPU_Cx5x86, fpus_internal, 133333333, 4.0, 5000, 0x480, 0, 0x002f, CPU_SUPPORTS_DYNAREC, 24,24,12,12, 16}, - {"", 0} - } + .package = CPU_PKG_SOCKET3, + .manufacturer = "AMD", + .name = "Am486DX4", + .internal_name = "am486dx4", + .cpus = (const CPU[]) { + {"75", CPU_Am486DX, fpus_internal, 75000000, 3.0, 5000, 0x432, 0, 0, CPU_SUPPORTS_DYNAREC, 12,12, 9, 9, 9}, + {"90", CPU_Am486DX, fpus_internal, 90000000, 3.0, 5000, 0x432, 0, 0, CPU_SUPPORTS_DYNAREC, 15,15, 9, 9, 12}, + {"100", CPU_Am486DX, fpus_internal, 100000000, 3.0, 5000, 0x432, 0, 0, CPU_SUPPORTS_DYNAREC, 15,15, 9, 9, 12}, + {"120", CPU_Am486DX, fpus_internal, 120000000, 3.0, 5000, 0x432, 0, 0, CPU_SUPPORTS_DYNAREC, 21,21, 9, 9, 15}, + {"", 0} + } }, { - .package = CPU_PKG_STPC, - .manufacturer = "ST", - .name = "STPC-DX", - .internal_name = "stpc_dx", - .cpus = (const CPU[]) { - {"66", CPU_STPC, fpus_internal, 66666666, 1.0, 3300, 0x430, 0, 0x051a, CPU_SUPPORTS_DYNAREC, 7, 7, 3, 3, 5}, - {"75", CPU_STPC, fpus_internal, 75000000, 1.0, 3300, 0x430, 0, 0x051a, CPU_SUPPORTS_DYNAREC, 7, 7, 3, 3, 5}, - {"", 0} - } + .package = CPU_PKG_SOCKET3, + .manufacturer = "AMD", + .name = "Am486DX2 (Enhanced)", + .internal_name = "am486dx2_slenh", + .cpus = (const CPU[]) { + {"66", CPU_ENH_Am486DX, fpus_internal, 66666666, 2, 5000, 0x435, 0x435, 0, CPU_SUPPORTS_DYNAREC, 12,12, 6, 6, 8}, + {"80", CPU_ENH_Am486DX, fpus_internal, 80000000, 2, 5000, 0x435, 0x435, 0, CPU_SUPPORTS_DYNAREC, 14,14, 6, 6, 10}, + {"", 0} + } }, { - .package = CPU_PKG_STPC, - .manufacturer = "ST", - .name = "STPC-DX2", - .internal_name = "stpc_dx2", - .cpus = (const CPU[]) { - {"133", CPU_STPC, fpus_internal, 133333333, 2.0, 3300, 0x430, 0, 0x0b1b, CPU_SUPPORTS_DYNAREC, 14,14, 6, 6, 10}, - {"", 0} - } + .package = CPU_PKG_SOCKET3, + .manufacturer = "AMD", + .name = "Am486DX4 (Enhanced)", + .internal_name = "am486dx4_slenh", + .cpus = (const CPU[]) { + {"75", CPU_ENH_Am486DX, fpus_internal, 75000000, 3.0, 5000, 0x482, 0x482, 0, CPU_SUPPORTS_DYNAREC, 12,12, 9, 9, 9}, + {"100", CPU_ENH_Am486DX, fpus_internal, 100000000, 3.0, 5000, 0x482, 0x482, 0, CPU_SUPPORTS_DYNAREC, 15,15, 9, 9, 12}, + {"120", CPU_ENH_Am486DX, fpus_internal, 120000000, 3.0, 5000, 0x482, 0x482, 0, CPU_SUPPORTS_DYNAREC, 21,21, 9, 9, 15}, + {"", 0} + } }, { - .package = CPU_PKG_SOCKET4, - .manufacturer = "Intel", - .name = "Pentium", - .internal_name = "pentium_p5", - .cpus = (const CPU[]) { - {"50 (Q0399)", CPU_PENTIUM, fpus_internal, 50000000, 1, 5000, 0x513, 0x513, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC | CPU_FIXED_MULTIPLIER, 4, 4,3,3, 6}, - {"60", CPU_PENTIUM, fpus_internal, 60000000, 1, 5000, 0x517, 0x517, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC | CPU_FIXED_MULTIPLIER, 6, 6,3,3, 7}, - {"66", CPU_PENTIUM, fpus_internal, 66666666, 1, 5000, 0x517, 0x517, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC | CPU_FIXED_MULTIPLIER, 6, 6,3,3, 8}, - {"", 0} - } + .package = CPU_PKG_SOCKET3, + .manufacturer = "AMD", + .name = "Am5x86", + .internal_name = "am5x86", + .cpus = (const CPU[]) { + {"P75", CPU_ENH_Am486DX, fpus_internal, 133333333, 4.0, 5000, 0x4e0, 0x4e0, 0, CPU_SUPPORTS_DYNAREC, 24,24,12,12, 16}, + {"P75+", CPU_ENH_Am486DX, fpus_internal, 150000000, 3.0, 5000, 0x482, 0x482, 0, CPU_SUPPORTS_DYNAREC, 28,28,12,12, 20},/*The rare P75+ was indeed a triple-clocked 150 MHz according to research*/ + {"P90", CPU_ENH_Am486DX, fpus_internal, 160000000, 4.0, 5000, 0x4e0, 0x4e0, 0, CPU_SUPPORTS_DYNAREC, 28,28,12,12, 20},/*160 MHz on a 40 MHz bus was a common overclock and "5x86/P90" was used by a number of BIOSes to refer to that configuration*/ + {"", 0} + } }, { - .package = CPU_PKG_SOCKET4, - .manufacturer = "Intel", - .name = "Pentium OverDrive", - .internal_name = "pentium_p54c_od5v", - .cpus = (const CPU[]) { - {"100", CPU_PENTIUM, fpus_internal, 100000000, 2, 5000, 0x51A, 0x51A, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC | CPU_FIXED_MULTIPLIER, 8, 8,6,6, 12}, - {"120", CPU_PENTIUM, fpus_internal, 120000000, 2, 5000, 0x51A, 0x51A, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC | CPU_FIXED_MULTIPLIER, 12,12,6,6, 14}, - {"133", CPU_PENTIUM, fpus_internal, 133333333, 2, 5000, 0x51A, 0x51A, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC | CPU_FIXED_MULTIPLIER, 12,12,6,6, 16}, - {"", 0} - } + .package = CPU_PKG_SOCKET1, + .manufacturer = "Cyrix", + .name = "Cx486S", + .internal_name = "cx486s", + .cpus = (const CPU[]) { + {"25", CPU_Cx486S, fpus_486sx, 25000000, 1.0, 5000, 0x420, 0, 0x0010, CPU_SUPPORTS_DYNAREC, 4, 4, 3, 3, 3}, + {"33", CPU_Cx486S, fpus_486sx, 33333333, 1.0, 5000, 0x420, 0, 0x0010, CPU_SUPPORTS_DYNAREC, 6, 6, 3, 3, 4}, + {"40", CPU_Cx486S, fpus_486sx, 40000000, 1.0, 5000, 0x420, 0, 0x0010, CPU_SUPPORTS_DYNAREC, 7, 7, 3, 3, 5}, + {"", 0} + } }, { - .package = CPU_PKG_SOCKET5_7, - .manufacturer = "Intel", - .name = "Pentium", - .internal_name = "pentium_p54c", - .cpus = (const CPU[]) { - {"75", CPU_PENTIUM, fpus_internal, 75000000, 1.5, 3520, 0x522, 0x522, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 7, 7,4,4, 9}, - {"90", CPU_PENTIUM, fpus_internal, 90000000, 1.5, 3520, 0x524, 0x524, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 9, 9,4,4, 21/2}, - {"100/50", CPU_PENTIUM, fpus_internal, 100000000, 2.0, 3520, 0x524, 0x524, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 10,10,6,6, 12}, - {"100/66", CPU_PENTIUM, fpus_internal, 100000000, 1.5, 3520, 0x526, 0x526, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 9, 9,4,4, 12}, - {"120", CPU_PENTIUM, fpus_internal, 120000000, 2.0, 3520, 0x526, 0x526, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 12,12,6,6, 14}, - {"133", CPU_PENTIUM, fpus_internal, 133333333, 2.0, 3520, 0x52c, 0x52c, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 12,12,6,6, 16}, - {"150", CPU_PENTIUM, fpus_internal, 150000000, 2.5, 3520, 0x52c, 0x52c, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 15,15, 7, 7, 35/2}, - {"166", CPU_PENTIUM, fpus_internal, 166666666, 2.5, 3520, 0x52c, 0x52c, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 15,15, 7, 7, 20}, - {"200", CPU_PENTIUM, fpus_internal, 200000000, 3.0, 3520, 0x52c, 0x52c, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 18,18, 9, 9, 24}, - {"", 0} - } + .package = CPU_PKG_SOCKET1, + .manufacturer = "Cyrix", + .name = "Cx486DX", + .internal_name = "cx486dx", + .cpus = (const CPU[]) { + {"33", CPU_Cx486DX, fpus_internal, 33333333, 1.0, 5000, 0x430, 0, 0x051a, CPU_SUPPORTS_DYNAREC, 6, 6, 3, 3, 4}, + {"40", CPU_Cx486DX, fpus_internal, 40000000, 1.0, 5000, 0x430, 0, 0x051a, CPU_SUPPORTS_DYNAREC, 7, 7, 3, 3, 5}, + {"", 0} + } }, { - .package = CPU_PKG_SOCKET5_7, - .manufacturer = "Intel", - .name = "Pentium MMX", - .internal_name = "pentium_p55c", - .cpus = (const CPU[]) { - {"166", CPU_PENTIUMMMX, fpus_internal, 166666666, 2.5, 2800, 0x543, 0x543, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 15,15, 7, 7, 20}, - {"200", CPU_PENTIUMMMX, fpus_internal, 200000000, 3.0, 2800, 0x543, 0x543, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 18,18, 9, 9, 24}, - {"233", CPU_PENTIUMMMX, fpus_internal, 233333333, 3.5, 2800, 0x543, 0x543, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 21,21,10,10, 28}, - {"", 0} - } + .package = CPU_PKG_SOCKET1, + .manufacturer = "Cyrix", + .name = "Cx486DX2", + .internal_name = "cx486dx2", + .cpus = (const CPU[]) { + {"50", CPU_Cx486DX, fpus_internal, 50000000, 2.0, 5000, 0x430, 0, 0x081b, CPU_SUPPORTS_DYNAREC, 8, 8, 6, 6, 6}, + {"66", CPU_Cx486DX, fpus_internal, 66666666, 2.0, 5000, 0x430, 0, 0x0b1b, CPU_SUPPORTS_DYNAREC, 12,12, 6, 6, 8}, + {"80", CPU_Cx486DX, fpus_internal, 80000000, 2.0, 5000, 0x430, 0, 0x311b, CPU_SUPPORTS_DYNAREC, 14,14, 6, 6, 10}, + {"", 0} + } }, { - .package = CPU_PKG_SOCKET5_7, - .manufacturer = "Intel", - .name = "Mobile Pentium MMX", - .internal_name = "pentium_tillamook", - .cpus = (const CPU[]) { - {"120", CPU_PENTIUMMMX, fpus_internal, 120000000, 2.0, 2800, 0x543, 0x543, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 12,12, 6, 6, 14}, - {"133", CPU_PENTIUMMMX, fpus_internal, 133333333, 2.0, 2800, 0x543, 0x543, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 12,12, 6, 6, 16}, - {"150", CPU_PENTIUMMMX, fpus_internal, 150000000, 2.5, 2800, 0x544, 0x544, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 15,15, 7, 7, 35/2}, - {"166", CPU_PENTIUMMMX, fpus_internal, 166666666, 2.5, 2800, 0x544, 0x544, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 15,15, 7, 7, 20}, - {"200", CPU_PENTIUMMMX, fpus_internal, 200000000, 3.0, 2800, 0x581, 0x581, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 18,18, 9, 9, 24}, - {"233", CPU_PENTIUMMMX, fpus_internal, 233333333, 3.5, 2800, 0x581, 0x581, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 21,21,10,10, 28}, - {"266", CPU_PENTIUMMMX, fpus_internal, 266666666, 4.0, 2800, 0x582, 0x582, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 24,24,12,12, 32}, - {"300", CPU_PENTIUMMMX, fpus_internal, 300000000, 4.5, 2800, 0x582, 0x582, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 27,27,13,13, 36}, - {"", 0} - } + .package = CPU_PKG_SOCKET3, + .manufacturer = "Cyrix", + .name = "Cx486DX4", + .internal_name = "cx486dx4", + .cpus = (const CPU[]) { + {"75", CPU_Cx486DX, fpus_internal, 75000000, 3.0, 5000, 0x480, 0, 0x361f, CPU_SUPPORTS_DYNAREC, 12,12, 9, 9, 9}, + {"100", CPU_Cx486DX, fpus_internal, 100000000, 3.0, 5000, 0x480, 0, 0x361f, CPU_SUPPORTS_DYNAREC, 15,15, 9, 9, 12}, + {"", 0} + } }, { - .package = CPU_PKG_SOCKET5_7, - .manufacturer = "Intel", - .name = "Pentium OverDrive", - .internal_name = "pentium_p54c_od3v", - .cpus = (const CPU[]) { - {"125", CPU_PENTIUM, fpus_internal, 125000000, 3.0, 3520, 0x52c, 0x52c, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC | CPU_FIXED_MULTIPLIER, 12,12,7,7, 15}, - {"150", CPU_PENTIUM, fpus_internal, 150000000, 2.5, 3520, 0x52c, 0x52c, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC | CPU_FIXED_MULTIPLIER, 15,15,7,7, 35/2}, - {"166", CPU_PENTIUM, fpus_internal, 166666666, 2.5, 3520, 0x52c, 0x52c, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC | CPU_FIXED_MULTIPLIER, 15,15,7,7, 20}, - {"", 0} - } + .package = CPU_PKG_SOCKET3, + .manufacturer = "Cyrix", + .name = "Cx5x86", + .internal_name = "cx5x86", + .cpus = (const CPU[]) { + {"80", CPU_Cx5x86, fpus_internal, 80000000, 2.0, 5000, 0x480, 0, 0x002f, CPU_SUPPORTS_DYNAREC, 14,14, 6, 6, 10}, /*If we're including the Pentium 50, might as well include this*/ + {"100", CPU_Cx5x86, fpus_internal, 100000000, 3.0, 5000, 0x480, 0, 0x002f, CPU_SUPPORTS_DYNAREC, 15,15, 9, 9, 12}, + {"120", CPU_Cx5x86, fpus_internal, 120000000, 3.0, 5000, 0x480, 0, 0x002f, CPU_SUPPORTS_DYNAREC, 21,21, 9, 9, 15}, + {"133", CPU_Cx5x86, fpus_internal, 133333333, 4.0, 5000, 0x480, 0, 0x002f, CPU_SUPPORTS_DYNAREC, 24,24,12,12, 16}, + {"", 0} + } }, { - .package = CPU_PKG_SOCKET5_7, - .manufacturer = "Intel", - .name = "Pentium OverDrive MMX", - .internal_name = "pentium_p55c_od", - .cpus = (const CPU[]) { - {"75", CPU_PENTIUMMMX, fpus_internal, 75000000, 1.5, 3520, 0x1542, 0x1542, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC | CPU_FIXED_MULTIPLIER, 7, 7,4,4, 9}, - {"125", CPU_PENTIUMMMX, fpus_internal, 125000000, 2.5, 3520, 0x1542, 0x1542, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC | CPU_FIXED_MULTIPLIER, 12,12,7,7, 15}, - {"150/60", CPU_PENTIUMMMX, fpus_internal, 150000000, 2.5, 3520, 0x1542, 0x1542, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC | CPU_FIXED_MULTIPLIER, 15,15,7,7, 35/2}, - {"166", CPU_PENTIUMMMX, fpus_internal, 166000000, 2.5, 3520, 0x1542, 0x1542, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC | CPU_FIXED_MULTIPLIER, 15,15,7,7, 20}, - {"180", CPU_PENTIUMMMX, fpus_internal, 180000000, 3.0, 3520, 0x1542, 0x1542, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC | CPU_FIXED_MULTIPLIER, 18,18,9,9, 21}, - {"200", CPU_PENTIUMMMX, fpus_internal, 200000000, 3.0, 3520, 0x1542, 0x1542, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC | CPU_FIXED_MULTIPLIER, 18,18,9,9, 24}, - {"", 0} - } + .package = CPU_PKG_STPC, + .manufacturer = "ST", + .name = "STPC-DX", + .internal_name = "stpc_dx", + .cpus = (const CPU[]) { + {"66", CPU_STPC, fpus_internal, 66666666, 1.0, 3300, 0x430, 0, 0x051a, CPU_SUPPORTS_DYNAREC, 7, 7, 3, 3, 5}, + {"75", CPU_STPC, fpus_internal, 75000000, 1.0, 3300, 0x430, 0, 0x051a, CPU_SUPPORTS_DYNAREC, 7, 7, 3, 3, 5}, + {"", 0} + } }, { - .package = CPU_PKG_SOCKET5_7, - .manufacturer = "IDT", - .name = "WinChip", - .internal_name = "winchip", - .cpus = (const CPU[]) { - {"75", CPU_WINCHIP, fpus_internal, 75000000, 1.5, 3520, 0x540, 0x540, 0, CPU_SUPPORTS_DYNAREC, 8, 8, 4, 4, 9}, - {"90", CPU_WINCHIP, fpus_internal, 90000000, 1.5, 3520, 0x540, 0x540, 0, CPU_SUPPORTS_DYNAREC, 9, 9, 4, 4, 21/2}, - {"100", CPU_WINCHIP, fpus_internal, 100000000, 1.5, 3520, 0x540, 0x540, 0, CPU_SUPPORTS_DYNAREC, 9, 9, 4, 4, 12}, - {"120", CPU_WINCHIP, fpus_internal, 120000000, 2.0, 3520, 0x540, 0x540, 0, CPU_SUPPORTS_DYNAREC, 12, 12, 6, 6, 14}, - {"133", CPU_WINCHIP, fpus_internal, 133333333, 2.0, 3520, 0x540, 0x540, 0, CPU_SUPPORTS_DYNAREC, 12, 12, 6, 6, 16}, - {"150", CPU_WINCHIP, fpus_internal, 150000000, 2.5, 3520, 0x540, 0x540, 0, CPU_SUPPORTS_DYNAREC, 15, 15, 7, 7, 35/2}, - {"166", CPU_WINCHIP, fpus_internal, 166666666, 2.5, 3520, 0x540, 0x540, 0, CPU_SUPPORTS_DYNAREC, 15, 15, 7, 7, 40}, - {"180", CPU_WINCHIP, fpus_internal, 180000000, 3.0, 3520, 0x540, 0x540, 0, CPU_SUPPORTS_DYNAREC, 18, 18, 9, 9, 21}, - {"200", CPU_WINCHIP, fpus_internal, 200000000, 3.0, 3520, 0x540, 0x540, 0, CPU_SUPPORTS_DYNAREC, 18, 18, 9, 9, 24}, - {"225", CPU_WINCHIP, fpus_internal, 225000000, 3.0, 3520, 0x540, 0x540, 0, CPU_SUPPORTS_DYNAREC, 18, 18, 9, 9, 27}, - {"240", CPU_WINCHIP, fpus_internal, 240000000, 4.0, 3520, 0x540, 0x540, 0, CPU_SUPPORTS_DYNAREC, 24, 24, 12, 12, 28}, - {"", 0} - } + .package = CPU_PKG_STPC, + .manufacturer = "ST", + .name = "STPC-DX2", + .internal_name = "stpc_dx2", + .cpus = (const CPU[]) { + {"133", CPU_STPC, fpus_internal, 133333333, 2.0, 3300, 0x430, 0, 0x0b1b, CPU_SUPPORTS_DYNAREC, 14,14, 6, 6, 10}, + {"", 0} + } }, { - .package = CPU_PKG_SOCKET5_7, - .manufacturer = "IDT", - .name = "WinChip 2", - .internal_name = "winchip2", - .cpus = (const CPU[]) { - {"200", CPU_WINCHIP2, fpus_internal, 200000000, 3.0, 3520, 0x580, 0x580, 0, CPU_SUPPORTS_DYNAREC, 18, 18, 9, 9, 3*8}, - {"225", CPU_WINCHIP2, fpus_internal, 225000000, 3.0, 3520, 0x580, 0x580, 0, CPU_SUPPORTS_DYNAREC, 18, 18, 9, 9, 3*9}, - {"240", CPU_WINCHIP2, fpus_internal, 240000000, 4.0, 3520, 0x580, 0x580, 0, CPU_SUPPORTS_DYNAREC, 24, 24, 12, 12, 30}, - {"250", CPU_WINCHIP2, fpus_internal, 250000000, 3.0, 3520, 0x580, 0x580, 0, CPU_SUPPORTS_DYNAREC, 24, 24, 12, 12, 30}, - {"", 0} - } + .package = CPU_PKG_SOCKET4, + .manufacturer = "Intel", + .name = "Pentium", + .internal_name = "pentium_p5", + .cpus = (const CPU[]) { + {"50 (Q0399)", CPU_PENTIUM, fpus_internal, 50000000, 1, 5000, 0x513, 0x513, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC | CPU_FIXED_MULTIPLIER, 4, 4,3,3, 6}, + {"60", CPU_PENTIUM, fpus_internal, 60000000, 1, 5000, 0x517, 0x517, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC | CPU_FIXED_MULTIPLIER, 6, 6,3,3, 7}, + {"66", CPU_PENTIUM, fpus_internal, 66666666, 1, 5000, 0x517, 0x517, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC | CPU_FIXED_MULTIPLIER, 6, 6,3,3, 8}, + {"", 0} + } }, { - .package = CPU_PKG_SOCKET5_7, - .manufacturer = "IDT", - .name = "WinChip 2A", - .internal_name = "winchip2a", - .cpus = (const CPU[]) { - {"200", CPU_WINCHIP2, fpus_internal, 200000000, 3.0, 3520, 0x587, 0x587, 0, CPU_SUPPORTS_DYNAREC, 18, 18, 9, 9, 3*8}, - {"233", CPU_WINCHIP2, fpus_internal, 233333333, 3.5, 3520, 0x587, 0x587, 0, CPU_SUPPORTS_DYNAREC, 21, 21, 9, 9, (7*8)/2}, - {"266", CPU_WINCHIP2, fpus_internal, 233333333, 7.0/3.0, 3520, 0x587, 0x587, 0, CPU_SUPPORTS_DYNAREC, 21, 21, 7, 7, 28}, - {"300", CPU_WINCHIP2, fpus_internal, 250000000, 2.5, 3520, 0x587, 0x587, 0, CPU_SUPPORTS_DYNAREC, 24, 24, 8, 8, 30}, - {"", 0} - } + .package = CPU_PKG_SOCKET4, + .manufacturer = "Intel", + .name = "Pentium OverDrive", + .internal_name = "pentium_p54c_od5v", + .cpus = (const CPU[]) { + {"100", CPU_PENTIUM, fpus_internal, 100000000, 2, 5000, 0x51A, 0x51A, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC | CPU_FIXED_MULTIPLIER, 8, 8,6,6, 12}, + {"120", CPU_PENTIUM, fpus_internal, 120000000, 2, 5000, 0x51A, 0x51A, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC | CPU_FIXED_MULTIPLIER, 12,12,6,6, 14}, + {"133", CPU_PENTIUM, fpus_internal, 133333333, 2, 5000, 0x51A, 0x51A, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC | CPU_FIXED_MULTIPLIER, 12,12,6,6, 16}, + {"", 0} + } + }, { + .package = CPU_PKG_SOCKET5_7, + .manufacturer = "Intel", + .name = "Pentium", + .internal_name = "pentium_p54c", + .cpus = (const CPU[]) { + {"75", CPU_PENTIUM, fpus_internal, 75000000, 1.5, 3520, 0x522, 0x522, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 7, 7,4,4, 9}, + {"90", CPU_PENTIUM, fpus_internal, 90000000, 1.5, 3520, 0x524, 0x524, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 9, 9,4,4, 21/2}, + {"100/50", CPU_PENTIUM, fpus_internal, 100000000, 2.0, 3520, 0x524, 0x524, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 10,10,6,6, 12}, + {"100/66", CPU_PENTIUM, fpus_internal, 100000000, 1.5, 3520, 0x526, 0x526, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 9, 9,4,4, 12}, + {"120", CPU_PENTIUM, fpus_internal, 120000000, 2.0, 3520, 0x526, 0x526, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 12,12,6,6, 14}, + {"133", CPU_PENTIUM, fpus_internal, 133333333, 2.0, 3520, 0x52c, 0x52c, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 12,12,6,6, 16}, + {"150", CPU_PENTIUM, fpus_internal, 150000000, 2.5, 3520, 0x52c, 0x52c, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 15,15, 7, 7, 35/2}, + {"166", CPU_PENTIUM, fpus_internal, 166666666, 2.5, 3520, 0x52c, 0x52c, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 15,15, 7, 7, 20}, + {"200", CPU_PENTIUM, fpus_internal, 200000000, 3.0, 3520, 0x52c, 0x52c, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 18,18, 9, 9, 24}, + {"", 0} + } + }, { + .package = CPU_PKG_SOCKET5_7, + .manufacturer = "Intel", + .name = "Pentium MMX", + .internal_name = "pentium_p55c", + .cpus = (const CPU[]) { + {"166", CPU_PENTIUMMMX, fpus_internal, 166666666, 2.5, 2800, 0x543, 0x543, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 15,15, 7, 7, 20}, + {"200", CPU_PENTIUMMMX, fpus_internal, 200000000, 3.0, 2800, 0x543, 0x543, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 18,18, 9, 9, 24}, + {"233", CPU_PENTIUMMMX, fpus_internal, 233333333, 3.5, 2800, 0x543, 0x543, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 21,21,10,10, 28}, + {"", 0} + } + }, { + .package = CPU_PKG_SOCKET5_7, + .manufacturer = "Intel", + .name = "Mobile Pentium MMX", + .internal_name = "pentium_tillamook", + .cpus = (const CPU[]) { + {"120", CPU_PENTIUMMMX, fpus_internal, 120000000, 2.0, 2800, 0x543, 0x543, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 12,12, 6, 6, 14}, + {"133", CPU_PENTIUMMMX, fpus_internal, 133333333, 2.0, 2800, 0x543, 0x543, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 12,12, 6, 6, 16}, + {"150", CPU_PENTIUMMMX, fpus_internal, 150000000, 2.5, 2800, 0x544, 0x544, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 15,15, 7, 7, 35/2}, + {"166", CPU_PENTIUMMMX, fpus_internal, 166666666, 2.5, 2800, 0x544, 0x544, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 15,15, 7, 7, 20}, + {"200", CPU_PENTIUMMMX, fpus_internal, 200000000, 3.0, 2800, 0x581, 0x581, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 18,18, 9, 9, 24}, + {"233", CPU_PENTIUMMMX, fpus_internal, 233333333, 3.5, 2800, 0x581, 0x581, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 21,21,10,10, 28}, + {"266", CPU_PENTIUMMMX, fpus_internal, 266666666, 4.0, 2800, 0x582, 0x582, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 24,24,12,12, 32}, + {"300", CPU_PENTIUMMMX, fpus_internal, 300000000, 4.5, 2800, 0x582, 0x582, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 27,27,13,13, 36}, + {"", 0} + } + }, { + .package = CPU_PKG_SOCKET5_7, + .manufacturer = "Intel", + .name = "Pentium OverDrive", + .internal_name = "pentium_p54c_od3v", + .cpus = (const CPU[]) { + {"125", CPU_PENTIUM, fpus_internal, 125000000, 3.0, 3520, 0x52c, 0x52c, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC | CPU_FIXED_MULTIPLIER, 12,12,7,7, 15}, + {"150", CPU_PENTIUM, fpus_internal, 150000000, 2.5, 3520, 0x52c, 0x52c, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC | CPU_FIXED_MULTIPLIER, 15,15,7,7, 35/2}, + {"166", CPU_PENTIUM, fpus_internal, 166666666, 2.5, 3520, 0x52c, 0x52c, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC | CPU_FIXED_MULTIPLIER, 15,15,7,7, 20}, + {"", 0} + } + }, { + .package = CPU_PKG_SOCKET5_7, + .manufacturer = "Intel", + .name = "Pentium OverDrive MMX", + .internal_name = "pentium_p55c_od", + .cpus = (const CPU[]) { + {"75", CPU_PENTIUMMMX, fpus_internal, 75000000, 1.5, 3520, 0x1542, 0x1542, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC | CPU_FIXED_MULTIPLIER, 7, 7,4,4, 9}, + {"125", CPU_PENTIUMMMX, fpus_internal, 125000000, 2.5, 3520, 0x1542, 0x1542, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC | CPU_FIXED_MULTIPLIER, 12,12,7,7, 15}, + {"150/60", CPU_PENTIUMMMX, fpus_internal, 150000000, 2.5, 3520, 0x1542, 0x1542, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC | CPU_FIXED_MULTIPLIER, 15,15,7,7, 35/2}, + {"166", CPU_PENTIUMMMX, fpus_internal, 166000000, 2.5, 3520, 0x1542, 0x1542, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC | CPU_FIXED_MULTIPLIER, 15,15,7,7, 20}, + {"180", CPU_PENTIUMMMX, fpus_internal, 180000000, 3.0, 3520, 0x1542, 0x1542, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC | CPU_FIXED_MULTIPLIER, 18,18,9,9, 21}, + {"200", CPU_PENTIUMMMX, fpus_internal, 200000000, 3.0, 3520, 0x1542, 0x1542, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC | CPU_FIXED_MULTIPLIER, 18,18,9,9, 24}, + {"", 0} + } + }, { + .package = CPU_PKG_SOCKET5_7, + .manufacturer = "IDT", + .name = "WinChip", + .internal_name = "winchip", + .cpus = (const CPU[]) { + {"75", CPU_WINCHIP, fpus_internal, 75000000, 1.5, 3520, 0x540, 0x540, 0, CPU_SUPPORTS_DYNAREC, 8, 8, 4, 4, 9}, + {"90", CPU_WINCHIP, fpus_internal, 90000000, 1.5, 3520, 0x540, 0x540, 0, CPU_SUPPORTS_DYNAREC, 9, 9, 4, 4, 21/2}, + {"100", CPU_WINCHIP, fpus_internal, 100000000, 1.5, 3520, 0x540, 0x540, 0, CPU_SUPPORTS_DYNAREC, 9, 9, 4, 4, 12}, + {"120", CPU_WINCHIP, fpus_internal, 120000000, 2.0, 3520, 0x540, 0x540, 0, CPU_SUPPORTS_DYNAREC, 12, 12, 6, 6, 14}, + {"133", CPU_WINCHIP, fpus_internal, 133333333, 2.0, 3520, 0x540, 0x540, 0, CPU_SUPPORTS_DYNAREC, 12, 12, 6, 6, 16}, + {"150", CPU_WINCHIP, fpus_internal, 150000000, 2.5, 3520, 0x540, 0x540, 0, CPU_SUPPORTS_DYNAREC, 15, 15, 7, 7, 35/2}, + {"166", CPU_WINCHIP, fpus_internal, 166666666, 2.5, 3520, 0x540, 0x540, 0, CPU_SUPPORTS_DYNAREC, 15, 15, 7, 7, 40}, + {"180", CPU_WINCHIP, fpus_internal, 180000000, 3.0, 3520, 0x540, 0x540, 0, CPU_SUPPORTS_DYNAREC, 18, 18, 9, 9, 21}, + {"200", CPU_WINCHIP, fpus_internal, 200000000, 3.0, 3520, 0x540, 0x540, 0, CPU_SUPPORTS_DYNAREC, 18, 18, 9, 9, 24}, + {"225", CPU_WINCHIP, fpus_internal, 225000000, 3.0, 3520, 0x540, 0x540, 0, CPU_SUPPORTS_DYNAREC, 18, 18, 9, 9, 27}, + {"240", CPU_WINCHIP, fpus_internal, 240000000, 4.0, 3520, 0x540, 0x540, 0, CPU_SUPPORTS_DYNAREC, 24, 24, 12, 12, 28}, + {"", 0} + } + }, { + .package = CPU_PKG_SOCKET5_7, + .manufacturer = "IDT", + .name = "WinChip 2", + .internal_name = "winchip2", + .cpus = (const CPU[]) { + {"200", CPU_WINCHIP2, fpus_internal, 200000000, 3.0, 3520, 0x580, 0x580, 0, CPU_SUPPORTS_DYNAREC, 18, 18, 9, 9, 3*8}, + {"225", CPU_WINCHIP2, fpus_internal, 225000000, 3.0, 3520, 0x580, 0x580, 0, CPU_SUPPORTS_DYNAREC, 18, 18, 9, 9, 3*9}, + {"240", CPU_WINCHIP2, fpus_internal, 240000000, 4.0, 3520, 0x580, 0x580, 0, CPU_SUPPORTS_DYNAREC, 24, 24, 12, 12, 30}, + {"250", CPU_WINCHIP2, fpus_internal, 250000000, 3.0, 3520, 0x580, 0x580, 0, CPU_SUPPORTS_DYNAREC, 24, 24, 12, 12, 30}, + {"", 0} + } + }, { + .package = CPU_PKG_SOCKET5_7, + .manufacturer = "IDT", + .name = "WinChip 2A", + .internal_name = "winchip2a", + .cpus = (const CPU[]) { + {"200", CPU_WINCHIP2, fpus_internal, 200000000, 3.0, 3520, 0x587, 0x587, 0, CPU_SUPPORTS_DYNAREC, 18, 18, 9, 9, 3*8}, + {"233", CPU_WINCHIP2, fpus_internal, 233333333, 3.5, 3520, 0x587, 0x587, 0, CPU_SUPPORTS_DYNAREC, 21, 21, 9, 9, (7*8)/2}, + {"266", CPU_WINCHIP2, fpus_internal, 233333333, 7.0/3.0, 3520, 0x587, 0x587, 0, CPU_SUPPORTS_DYNAREC, 21, 21, 7, 7, 28}, + {"300", CPU_WINCHIP2, fpus_internal, 250000000, 2.5, 3520, 0x587, 0x587, 0, CPU_SUPPORTS_DYNAREC, 24, 24, 8, 8, 30}, + {"", 0} + } }, #if defined(DEV_BRANCH) && defined(USE_AMD_K5) { - .package = CPU_PKG_SOCKET5_7, - .manufacturer = "AMD", - .name = "K5 (5k86)", - .internal_name = "k5_5k86", - .cpus = (const CPU[]) { - {"75 (P75)", CPU_K5, fpus_internal, 75000000, 1.5, 3520, 0x500, 0x500, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 7, 7,4,4, 9}, - {"90 (P90)", CPU_K5, fpus_internal, 90000000, 1.5, 3520, 0x500, 0x500, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 9, 9,4,4, 21/2}, - {"100 (P100)", CPU_K5, fpus_internal, 100000000, 1.5, 3520, 0x500, 0x500, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 9, 9,4,4, 12}, - {"90 (PR120)", CPU_5K86, fpus_internal, 120000000, 2.0, 3520, 0x511, 0x511, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 12,12,6,6, 14}, - {"100 (PR133)", CPU_5K86, fpus_internal, 133333333, 2.0, 3520, 0x514, 0x514, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 12,12,6,6, 16}, - {"105 (PR150)", CPU_5K86, fpus_internal, 150000000, 2.5, 3520, 0x524, 0x524, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 15,15,7,7, 35/2}, - {"116.5 (PR166)", CPU_5K86, fpus_internal, 166666666, 2.5, 3520, 0x524, 0x524, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 15,15,7,7, 20}, - {"133 (PR200)", CPU_5K86, fpus_internal, 200000000, 3.0, 3520, 0x534, 0x534, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 18,18,9,9, 24}, - {"", 0} - } + .package = CPU_PKG_SOCKET5_7, + .manufacturer = "AMD", + .name = "K5 (5k86)", + .internal_name = "k5_5k86", + .cpus = (const CPU[]) { + {"75 (P75)", CPU_K5, fpus_internal, 75000000, 1.5, 3520, 0x500, 0x500, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 7, 7,4,4, 9}, + {"90 (P90)", CPU_K5, fpus_internal, 90000000, 1.5, 3520, 0x500, 0x500, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 9, 9,4,4, 21/2}, + {"100 (P100)", CPU_K5, fpus_internal, 100000000, 1.5, 3520, 0x500, 0x500, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 9, 9,4,4, 12}, + {"90 (PR120)", CPU_5K86, fpus_internal, 120000000, 2.0, 3520, 0x511, 0x511, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 12,12,6,6, 14}, + {"100 (PR133)", CPU_5K86, fpus_internal, 133333333, 2.0, 3520, 0x514, 0x514, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 12,12,6,6, 16}, + {"105 (PR150)", CPU_5K86, fpus_internal, 150000000, 2.5, 3520, 0x524, 0x524, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 15,15,7,7, 35/2}, + {"116.5 (PR166)", CPU_5K86, fpus_internal, 166666666, 2.5, 3520, 0x524, 0x524, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 15,15,7,7, 20}, + {"133 (PR200)", CPU_5K86, fpus_internal, 200000000, 3.0, 3520, 0x534, 0x534, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 18,18,9,9, 24}, + {"", 0} + } }, { - .package = CPU_PKG_SOCKET5_7, - .manufacturer = "AMD", - .name = "K5 (SSA/5)", - .internal_name = "k5_ssa5", - .cpus = (const CPU[]) { - {"75 (PR75)", CPU_K5, fpus_internal, 75000000, 1.5, 3520, 0x501, 0x501, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 7, 7,4,4, 9}, - {"90 (PR90)", CPU_K5, fpus_internal, 90000000, 1.5, 3520, 0x501, 0x501, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 9, 9,4,4, 21/2}, - {"100 (PR100)", CPU_K5, fpus_internal, 100000000, 1.5, 3520, 0x501, 0x501, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 9, 9,4,4, 12}, - {"", 0} - } + .package = CPU_PKG_SOCKET5_7, + .manufacturer = "AMD", + .name = "K5 (SSA/5)", + .internal_name = "k5_ssa5", + .cpus = (const CPU[]) { + {"75 (PR75)", CPU_K5, fpus_internal, 75000000, 1.5, 3520, 0x501, 0x501, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 7, 7,4,4, 9}, + {"90 (PR90)", CPU_K5, fpus_internal, 90000000, 1.5, 3520, 0x501, 0x501, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 9, 9,4,4, 21/2}, + {"100 (PR100)", CPU_K5, fpus_internal, 100000000, 1.5, 3520, 0x501, 0x501, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 9, 9,4,4, 12}, + {"", 0} + } }, #endif { - .package = CPU_PKG_SOCKET5_7, - .manufacturer = "AMD", - .name = "K6 (Model 6)", - .internal_name = "k6_m6", - .cpus = (const CPU[]) { - {"66", CPU_K6, fpus_internal, 66666666, 1.0, 2900, 0x561, 0x561, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 6, 6, 3, 3, 8}, /* out of spec */ - {"100", CPU_K6, fpus_internal, 100000000, 1.5, 2900, 0x561, 0x561, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 9, 9, 4, 4, 12}, /* out of spec */ - {"133", CPU_K6, fpus_internal, 133333333, 2.0, 2900, 0x561, 0x561, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 12,12, 6, 6, 16}, /* out of spec */ - {"166", CPU_K6, fpus_internal, 166666666, 2.5, 2900, 0x561, 0x561, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 15,15, 7, 7, 20}, - {"200", CPU_K6, fpus_internal, 200000000, 3.0, 2900, 0x561, 0x561, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 18,18, 9, 9, 24}, - {"233", CPU_K6, fpus_internal, 233333333, 3.5, 3200, 0x561, 0x561, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 21,21,10,10, 28}, - {"", 0} - } + .package = CPU_PKG_SOCKET5_7, + .manufacturer = "AMD", + .name = "K6 (Model 6)", + .internal_name = "k6_m6", + .cpus = (const CPU[]) { + {"66", CPU_K6, fpus_internal, 66666666, 1.0, 2900, 0x561, 0x561, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 6, 6, 3, 3, 8}, /* out of spec */ + {"100", CPU_K6, fpus_internal, 100000000, 1.5, 2900, 0x561, 0x561, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 9, 9, 4, 4, 12}, /* out of spec */ + {"133", CPU_K6, fpus_internal, 133333333, 2.0, 2900, 0x561, 0x561, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 12,12, 6, 6, 16}, /* out of spec */ + {"166", CPU_K6, fpus_internal, 166666666, 2.5, 2900, 0x561, 0x561, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 15,15, 7, 7, 20}, + {"200", CPU_K6, fpus_internal, 200000000, 3.0, 2900, 0x561, 0x561, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 18,18, 9, 9, 24}, + {"233", CPU_K6, fpus_internal, 233333333, 3.5, 3200, 0x561, 0x561, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 21,21,10,10, 28}, + {"", 0} + } }, { - .package = CPU_PKG_SOCKET5_7, - .manufacturer = "AMD", - .name = "K6 (Model 7)", - .internal_name = "k6_m7", - .cpus = (const CPU[]) { - {"100", CPU_K6, fpus_internal, 100000000, 1.5, 2200, 0x570, 0x570, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 9, 9, 4, 4, 12}, /* out of spec */ - {"133", CPU_K6, fpus_internal, 133333333, 2.0, 2200, 0x570, 0x570, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 12,12, 6, 6, 16}, /* out of spec */ - {"166", CPU_K6, fpus_internal, 166666666, 2.5, 2200, 0x570, 0x570, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 15,15, 7, 7, 20}, /* out of spec */ - {"200", CPU_K6, fpus_internal, 200000000, 3.0, 2200, 0x570, 0x570, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 18,18, 9, 9, 24}, - {"233", CPU_K6, fpus_internal, 233333333, 3.5, 2200, 0x570, 0x570, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 21,21,10,10, 28}, - {"266", CPU_K6, fpus_internal, 266666666, 4.0, 2200, 0x570, 0x570, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 24,24,12,12, 32}, - {"300", CPU_K6, fpus_internal, 300000000, 4.5, 2200, 0x570, 0x570, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 27,27,13,13, 36}, - {"", 0} - } + .package = CPU_PKG_SOCKET5_7, + .manufacturer = "AMD", + .name = "K6 (Model 7)", + .internal_name = "k6_m7", + .cpus = (const CPU[]) { + {"100", CPU_K6, fpus_internal, 100000000, 1.5, 2200, 0x570, 0x570, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 9, 9, 4, 4, 12}, /* out of spec */ + {"133", CPU_K6, fpus_internal, 133333333, 2.0, 2200, 0x570, 0x570, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 12,12, 6, 6, 16}, /* out of spec */ + {"166", CPU_K6, fpus_internal, 166666666, 2.5, 2200, 0x570, 0x570, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 15,15, 7, 7, 20}, /* out of spec */ + {"200", CPU_K6, fpus_internal, 200000000, 3.0, 2200, 0x570, 0x570, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 18,18, 9, 9, 24}, + {"233", CPU_K6, fpus_internal, 233333333, 3.5, 2200, 0x570, 0x570, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 21,21,10,10, 28}, + {"266", CPU_K6, fpus_internal, 266666666, 4.0, 2200, 0x570, 0x570, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 24,24,12,12, 32}, + {"300", CPU_K6, fpus_internal, 300000000, 4.5, 2200, 0x570, 0x570, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 27,27,13,13, 36}, + {"", 0} + } }, { - .package = CPU_PKG_SOCKET5_7, - .manufacturer = "AMD", - .name = "K6-2", - .internal_name = "k6_2", - .cpus = (const CPU[]) { - {"100", CPU_K6_2, fpus_internal, 100000000, 1.5, 2200, 0x580, 0x580, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 9, 9, 4, 4, 12}, /* out of spec */ - {"133", CPU_K6_2, fpus_internal, 133333333, 2.0, 2200, 0x580, 0x580, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 12, 12, 6, 6, 16}, /* out of spec */ - {"166", CPU_K6_2, fpus_internal, 166666666, 2.5, 2200, 0x580, 0x580, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 15, 15, 7, 7, 20}, /* out of spec */ - {"200", CPU_K6_2, fpus_internal, 200000000, 3.0, 2200, 0x580, 0x580, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 18, 18, 9, 9, 24}, /* out of spec */ - {"233", CPU_K6_2, fpus_internal, 233333333, 3.5, 2200, 0x580, 0x580, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 21, 21, 10, 10, 28}, - {"266", CPU_K6_2, fpus_internal, 266666666, 4.0, 2200, 0x580, 0x580, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 24, 24, 12, 12, 32}, - {"300", CPU_K6_2, fpus_internal, 300000000, 3.0, 2200, 0x580, 0x580, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 27, 27, 9, 9, 36}, - {"333", CPU_K6_2, fpus_internal, 332500000, 3.5, 2200, 0x580, 0x580, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 30, 30, 11, 11, 40}, - {"350", CPU_K6_2C, fpus_internal, 350000000, 3.5, 2200, 0x58c, 0x58c, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 32, 32, 11, 11, 42}, - {"366", CPU_K6_2C, fpus_internal, 366666666, 5.5, 2200, 0x58c, 0x58c, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 33, 33, 17, 17, 44}, - {"380", CPU_K6_2C, fpus_internal, 380000000, 4.0, 2200, 0x58c, 0x58c, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 34, 34, 12, 12, 46}, - {"400/66", CPU_K6_2C, fpus_internal, 400000000, 6.0, 2200, 0x58c, 0x58c, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 36, 36, 12, 12, 48}, - {"400/100", CPU_K6_2C, fpus_internal, 400000000, 4.0, 2200, 0x58c, 0x58c, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 36, 36, 12, 12, 48}, - {"450", CPU_K6_2C, fpus_internal, 450000000, 4.5, 2200, 0x58c, 0x58c, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 41, 41, 14, 14, 54}, - {"475", CPU_K6_2C, fpus_internal, 475000000, 5.0, 2400, 0x58c, 0x58c, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 43, 43, 15, 15, 57}, - {"500", CPU_K6_2C, fpus_internal, 500000000, 5.0, 2400, 0x58c, 0x58c, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 45, 45, 15, 15, 60}, - {"533", CPU_K6_2C, fpus_internal, 533333333, 5.5, 2200, 0x58c, 0x58c, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 48, 48, 17, 17, 64}, - {"550", CPU_K6_2C, fpus_internal, 550000000, 5.5, 2300, 0x58c, 0x58c, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 50, 50, 17, 17, 66}, - {"", 0} - } + .package = CPU_PKG_SOCKET5_7, + .manufacturer = "AMD", + .name = "K6-2", + .internal_name = "k6_2", + .cpus = (const CPU[]) { + {"100", CPU_K6_2, fpus_internal, 100000000, 1.5, 2200, 0x580, 0x580, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 9, 9, 4, 4, 12}, /* out of spec */ + {"133", CPU_K6_2, fpus_internal, 133333333, 2.0, 2200, 0x580, 0x580, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 12, 12, 6, 6, 16}, /* out of spec */ + {"166", CPU_K6_2, fpus_internal, 166666666, 2.5, 2200, 0x580, 0x580, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 15, 15, 7, 7, 20}, /* out of spec */ + {"200", CPU_K6_2, fpus_internal, 200000000, 3.0, 2200, 0x580, 0x580, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 18, 18, 9, 9, 24}, /* out of spec */ + {"233", CPU_K6_2, fpus_internal, 233333333, 3.5, 2200, 0x580, 0x580, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 21, 21, 10, 10, 28}, + {"266", CPU_K6_2, fpus_internal, 266666666, 4.0, 2200, 0x580, 0x580, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 24, 24, 12, 12, 32}, + {"300", CPU_K6_2, fpus_internal, 300000000, 3.0, 2200, 0x580, 0x580, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 27, 27, 9, 9, 36}, + {"333", CPU_K6_2, fpus_internal, 332500000, 3.5, 2200, 0x580, 0x580, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 30, 30, 11, 11, 40}, + {"350", CPU_K6_2C, fpus_internal, 350000000, 3.5, 2200, 0x58c, 0x58c, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 32, 32, 11, 11, 42}, + {"366", CPU_K6_2C, fpus_internal, 366666666, 5.5, 2200, 0x58c, 0x58c, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 33, 33, 17, 17, 44}, + {"380", CPU_K6_2C, fpus_internal, 380000000, 4.0, 2200, 0x58c, 0x58c, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 34, 34, 12, 12, 46}, + {"400/66", CPU_K6_2C, fpus_internal, 400000000, 6.0, 2200, 0x58c, 0x58c, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 36, 36, 12, 12, 48}, + {"400/100", CPU_K6_2C, fpus_internal, 400000000, 4.0, 2200, 0x58c, 0x58c, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 36, 36, 12, 12, 48}, + {"450", CPU_K6_2C, fpus_internal, 450000000, 4.5, 2200, 0x58c, 0x58c, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 41, 41, 14, 14, 54}, + {"475", CPU_K6_2C, fpus_internal, 475000000, 5.0, 2400, 0x58c, 0x58c, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 43, 43, 15, 15, 57}, + {"500", CPU_K6_2C, fpus_internal, 500000000, 5.0, 2400, 0x58c, 0x58c, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 45, 45, 15, 15, 60}, + {"533", CPU_K6_2C, fpus_internal, 533333333, 5.5, 2200, 0x58c, 0x58c, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 48, 48, 17, 17, 64}, + {"550", CPU_K6_2C, fpus_internal, 550000000, 5.5, 2300, 0x58c, 0x58c, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 50, 50, 17, 17, 66}, + {"", 0} + } }, { - .package = CPU_PKG_SOCKET5_7, - .manufacturer = "AMD", - .name = "K6-2+", - .internal_name = "k6_2p", - .cpus = (const CPU[]) { - {"100", CPU_K6_2P, fpus_internal, 100000000, 1.5, 2000, 0x5d4, 0x5d4, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 9, 9, 4, 4, 12}, /* out of spec */ - {"133", CPU_K6_2P, fpus_internal, 133333333, 2.0, 2000, 0x5d4, 0x5d4, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 12, 12, 6, 6, 16}, /* out of spec */ - {"166", CPU_K6_2P, fpus_internal, 166666666, 2.5, 2000, 0x5d4, 0x5d4, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 15, 15, 7, 7, 20}, /* out of spec */ - {"200", CPU_K6_2P, fpus_internal, 200000000, 3.0, 2000, 0x5d4, 0x5d4, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 18, 18, 9, 9, 24}, /* out of spec */ - {"233", CPU_K6_2P, fpus_internal, 233333333, 3.5, 2000, 0x5d4, 0x5d4, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 21, 21, 10, 10, 28}, /* out of spec */ - {"266", CPU_K6_2P, fpus_internal, 266666666, 4.0, 2000, 0x5d4, 0x5d4, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 24, 24, 12, 12, 32}, /* out of spec */ - {"300", CPU_K6_2P, fpus_internal, 300000000, 3.0, 2000, 0x5d4, 0x5d4, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 27, 27, 9, 9, 36}, /* out of spec */ - {"333", CPU_K6_2P, fpus_internal, 332500000, 3.5, 2000, 0x5d4, 0x5d4, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 30, 30, 11, 11, 40}, /* out of spec */ - {"350", CPU_K6_2P, fpus_internal, 350000000, 3.5, 2000, 0x5d4, 0x5d4, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 32, 32, 11, 11, 42}, /* out of spec */ - {"366", CPU_K6_2P, fpus_internal, 366666666, 5.5, 2000, 0x5d4, 0x5d4, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 33, 33, 17, 17, 44}, /* out of spec */ - {"380", CPU_K6_2P, fpus_internal, 380000000, 4.0, 2000, 0x5d4, 0x5d4, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 34, 34, 12, 12, 46}, /* out of spec */ - {"400/66", CPU_K6_2P, fpus_internal, 400000000, 6.0, 2000, 0x5d4, 0x5d4, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 36, 36, 12, 12, 48}, /* out of spec */ - {"400/100", CPU_K6_2P, fpus_internal, 400000000, 4.0, 2000, 0x5d4, 0x5d4, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 36, 36, 12, 12, 48}, /* out of spec */ - {"450", CPU_K6_2P, fpus_internal, 450000000, 4.5, 2000, 0x5d4, 0x5d4, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 41, 41, 14, 14, 54}, - {"475", CPU_K6_2P, fpus_internal, 475000000, 5.0, 2000, 0x5d4, 0x5d4, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 43, 43, 15, 15, 57}, - {"500", CPU_K6_2P, fpus_internal, 500000000, 5.0, 2000, 0x5d4, 0x5d4, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 45, 45, 15, 15, 60}, - {"533", CPU_K6_2P, fpus_internal, 533333333, 5.5, 2000, 0x5d4, 0x5d4, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 48, 48, 17, 17, 64}, - {"550", CPU_K6_2P, fpus_internal, 550000000, 5.5, 2000, 0x5d4, 0x5d4, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 50, 50, 17, 17, 66}, - {"", 0} - } + .package = CPU_PKG_SOCKET5_7, + .manufacturer = "AMD", + .name = "K6-2+", + .internal_name = "k6_2p", + .cpus = (const CPU[]) { + {"100", CPU_K6_2P, fpus_internal, 100000000, 1.5, 2000, 0x5d4, 0x5d4, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 9, 9, 4, 4, 12}, /* out of spec */ + {"133", CPU_K6_2P, fpus_internal, 133333333, 2.0, 2000, 0x5d4, 0x5d4, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 12, 12, 6, 6, 16}, /* out of spec */ + {"166", CPU_K6_2P, fpus_internal, 166666666, 2.5, 2000, 0x5d4, 0x5d4, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 15, 15, 7, 7, 20}, /* out of spec */ + {"200", CPU_K6_2P, fpus_internal, 200000000, 3.0, 2000, 0x5d4, 0x5d4, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 18, 18, 9, 9, 24}, /* out of spec */ + {"233", CPU_K6_2P, fpus_internal, 233333333, 3.5, 2000, 0x5d4, 0x5d4, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 21, 21, 10, 10, 28}, /* out of spec */ + {"266", CPU_K6_2P, fpus_internal, 266666666, 4.0, 2000, 0x5d4, 0x5d4, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 24, 24, 12, 12, 32}, /* out of spec */ + {"300", CPU_K6_2P, fpus_internal, 300000000, 3.0, 2000, 0x5d4, 0x5d4, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 27, 27, 9, 9, 36}, /* out of spec */ + {"333", CPU_K6_2P, fpus_internal, 332500000, 3.5, 2000, 0x5d4, 0x5d4, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 30, 30, 11, 11, 40}, /* out of spec */ + {"350", CPU_K6_2P, fpus_internal, 350000000, 3.5, 2000, 0x5d4, 0x5d4, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 32, 32, 11, 11, 42}, /* out of spec */ + {"366", CPU_K6_2P, fpus_internal, 366666666, 5.5, 2000, 0x5d4, 0x5d4, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 33, 33, 17, 17, 44}, /* out of spec */ + {"380", CPU_K6_2P, fpus_internal, 380000000, 4.0, 2000, 0x5d4, 0x5d4, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 34, 34, 12, 12, 46}, /* out of spec */ + {"400/66", CPU_K6_2P, fpus_internal, 400000000, 6.0, 2000, 0x5d4, 0x5d4, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 36, 36, 12, 12, 48}, /* out of spec */ + {"400/100", CPU_K6_2P, fpus_internal, 400000000, 4.0, 2000, 0x5d4, 0x5d4, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 36, 36, 12, 12, 48}, /* out of spec */ + {"450", CPU_K6_2P, fpus_internal, 450000000, 4.5, 2000, 0x5d4, 0x5d4, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 41, 41, 14, 14, 54}, + {"475", CPU_K6_2P, fpus_internal, 475000000, 5.0, 2000, 0x5d4, 0x5d4, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 43, 43, 15, 15, 57}, + {"500", CPU_K6_2P, fpus_internal, 500000000, 5.0, 2000, 0x5d4, 0x5d4, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 45, 45, 15, 15, 60}, + {"533", CPU_K6_2P, fpus_internal, 533333333, 5.5, 2000, 0x5d4, 0x5d4, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 48, 48, 17, 17, 64}, + {"550", CPU_K6_2P, fpus_internal, 550000000, 5.5, 2000, 0x5d4, 0x5d4, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 50, 50, 17, 17, 66}, + {"", 0} + } }, { - .package = CPU_PKG_SOCKET5_7, - .manufacturer = "AMD", - .name = "K6-III", - .internal_name = "k6_3", - .cpus = (const CPU[]) { - {"100", CPU_K6_3, fpus_internal, 100000000, 1.5, 2200, 0x591, 0x591, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 9, 9, 4, 4, 12}, /* out of spec */ - {"133", CPU_K6_3, fpus_internal, 133333333, 2.0, 2200, 0x591, 0x591, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 12, 12, 6, 6, 16}, /* out of spec */ - {"166", CPU_K6_3, fpus_internal, 166666666, 2.5, 2200, 0x591, 0x591, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 15, 15, 7, 7, 20}, /* out of spec */ - {"200", CPU_K6_3, fpus_internal, 200000000, 3.0, 2200, 0x591, 0x591, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 18, 18, 9, 9, 24}, /* out of spec */ - {"233", CPU_K6_3, fpus_internal, 233333333, 3.5, 2200, 0x591, 0x591, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 21, 21, 10, 10, 28}, /* out of spec */ - {"266", CPU_K6_3, fpus_internal, 266666666, 4.0, 2200, 0x591, 0x591, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 24, 24, 12, 12, 32}, /* out of spec */ - {"300", CPU_K6_3, fpus_internal, 300000000, 3.0, 2200, 0x591, 0x591, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 27, 27, 9, 9, 36}, /* out of spec */ - {"333", CPU_K6_3, fpus_internal, 332500000, 3.5, 2200, 0x591, 0x591, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 30, 30, 11, 11, 40}, /* out of spec */ - {"350", CPU_K6_3, fpus_internal, 350000000, 3.5, 2200, 0x591, 0x591, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 32, 32, 11, 11, 42}, /* out of spec */ - {"366", CPU_K6_3, fpus_internal, 366666666, 5.5, 2200, 0x591, 0x591, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 33, 33, 17, 17, 44}, /* out of spec */ - {"380", CPU_K6_3, fpus_internal, 380000000, 4.0, 2200, 0x591, 0x591, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 34, 34, 12, 12, 46}, /* out of spec */ - {"400", CPU_K6_3, fpus_internal, 400000000, 4.0, 2200, 0x591, 0x591, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 36, 36, 12, 12, 48}, - {"450", CPU_K6_3, fpus_internal, 450000000, 4.5, 2200, 0x591, 0x591, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 41, 41, 14, 14, 54}, - {"", 0} - } + .package = CPU_PKG_SOCKET5_7, + .manufacturer = "AMD", + .name = "K6-III", + .internal_name = "k6_3", + .cpus = (const CPU[]) { + {"100", CPU_K6_3, fpus_internal, 100000000, 1.5, 2200, 0x591, 0x591, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 9, 9, 4, 4, 12}, /* out of spec */ + {"133", CPU_K6_3, fpus_internal, 133333333, 2.0, 2200, 0x591, 0x591, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 12, 12, 6, 6, 16}, /* out of spec */ + {"166", CPU_K6_3, fpus_internal, 166666666, 2.5, 2200, 0x591, 0x591, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 15, 15, 7, 7, 20}, /* out of spec */ + {"200", CPU_K6_3, fpus_internal, 200000000, 3.0, 2200, 0x591, 0x591, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 18, 18, 9, 9, 24}, /* out of spec */ + {"233", CPU_K6_3, fpus_internal, 233333333, 3.5, 2200, 0x591, 0x591, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 21, 21, 10, 10, 28}, /* out of spec */ + {"266", CPU_K6_3, fpus_internal, 266666666, 4.0, 2200, 0x591, 0x591, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 24, 24, 12, 12, 32}, /* out of spec */ + {"300", CPU_K6_3, fpus_internal, 300000000, 3.0, 2200, 0x591, 0x591, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 27, 27, 9, 9, 36}, /* out of spec */ + {"333", CPU_K6_3, fpus_internal, 332500000, 3.5, 2200, 0x591, 0x591, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 30, 30, 11, 11, 40}, /* out of spec */ + {"350", CPU_K6_3, fpus_internal, 350000000, 3.5, 2200, 0x591, 0x591, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 32, 32, 11, 11, 42}, /* out of spec */ + {"366", CPU_K6_3, fpus_internal, 366666666, 5.5, 2200, 0x591, 0x591, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 33, 33, 17, 17, 44}, /* out of spec */ + {"380", CPU_K6_3, fpus_internal, 380000000, 4.0, 2200, 0x591, 0x591, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 34, 34, 12, 12, 46}, /* out of spec */ + {"400", CPU_K6_3, fpus_internal, 400000000, 4.0, 2200, 0x591, 0x591, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 36, 36, 12, 12, 48}, + {"450", CPU_K6_3, fpus_internal, 450000000, 4.5, 2200, 0x591, 0x591, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 41, 41, 14, 14, 54}, + {"", 0} + } }, { - .package = CPU_PKG_SOCKET5_7, - .manufacturer = "AMD", - .name = "K6-III+", - .internal_name = "k6_3p", - .cpus = (const CPU[]) { - {"100", CPU_K6_3P, fpus_internal, 100000000, 1.5, 2000, 0x5d0, 0x5d0, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 7, 7, 4, 4, 9}, /* out of spec */ - {"133", CPU_K6_3P, fpus_internal, 133333333, 2.0, 2000, 0x5d0, 0x5d0, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 12, 12, 6, 6, 16}, /* out of spec */ - {"166", CPU_K6_3P, fpus_internal, 166666666, 2.5, 2000, 0x5d0, 0x5d0, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 15, 15, 7, 7, 20}, /* out of spec */ - {"200", CPU_K6_3P, fpus_internal, 200000000, 3.0, 2000, 0x5d0, 0x5d0, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 18, 18, 9, 9, 24}, /* out of spec */ - {"233", CPU_K6_3P, fpus_internal, 233333333, 3.5, 2000, 0x5d0, 0x5d0, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 21, 21, 10, 10, 28}, /* out of spec */ - {"266", CPU_K6_3P, fpus_internal, 266666666, 4.0, 2000, 0x5d0, 0x5d0, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 24, 24, 12, 12, 32}, /* out of spec */ - {"300", CPU_K6_3P, fpus_internal, 300000000, 3.0, 2000, 0x5d0, 0x5d0, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 27, 27, 9, 9, 36}, /* out of spec */ - {"333", CPU_K6_3P, fpus_internal, 332500000, 3.5, 2000, 0x5d0, 0x5d0, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 30, 30, 11, 11, 40}, /* out of spec */ - {"350", CPU_K6_3P, fpus_internal, 350000000, 3.5, 2000, 0x5d0, 0x5d0, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 32, 32, 11, 11, 42}, /* out of spec */ - {"366", CPU_K6_3P, fpus_internal, 366666666, 5.5, 2000, 0x5d0, 0x5d0, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 33, 33, 17, 17, 44}, /* out of spec */ - {"380", CPU_K6_3P, fpus_internal, 380000000, 4.0, 2000, 0x5d0, 0x5d0, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 34, 34, 12, 12, 46}, /* out of spec */ - {"400", CPU_K6_3P, fpus_internal, 400000000, 4.0, 2000, 0x5d0, 0x5d0, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 36, 36, 12, 12, 48}, - {"450", CPU_K6_3P, fpus_internal, 450000000, 4.5, 2000, 0x5d0, 0x5d0, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 41, 41, 14, 14, 54}, - {"475", CPU_K6_3P, fpus_internal, 475000000, 5.0, 2000, 0x5d0, 0x5d0, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 43, 43, 15, 15, 57}, - {"500", CPU_K6_3P, fpus_internal, 500000000, 5.0, 2000, 0x5d0, 0x5d0, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 45, 45, 15, 15, 60}, - {"", 0} - } + .package = CPU_PKG_SOCKET5_7, + .manufacturer = "AMD", + .name = "K6-III+", + .internal_name = "k6_3p", + .cpus = (const CPU[]) { + {"100", CPU_K6_3P, fpus_internal, 100000000, 1.5, 2000, 0x5d0, 0x5d0, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 7, 7, 4, 4, 9}, /* out of spec */ + {"133", CPU_K6_3P, fpus_internal, 133333333, 2.0, 2000, 0x5d0, 0x5d0, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 12, 12, 6, 6, 16}, /* out of spec */ + {"166", CPU_K6_3P, fpus_internal, 166666666, 2.5, 2000, 0x5d0, 0x5d0, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 15, 15, 7, 7, 20}, /* out of spec */ + {"200", CPU_K6_3P, fpus_internal, 200000000, 3.0, 2000, 0x5d0, 0x5d0, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 18, 18, 9, 9, 24}, /* out of spec */ + {"233", CPU_K6_3P, fpus_internal, 233333333, 3.5, 2000, 0x5d0, 0x5d0, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 21, 21, 10, 10, 28}, /* out of spec */ + {"266", CPU_K6_3P, fpus_internal, 266666666, 4.0, 2000, 0x5d0, 0x5d0, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 24, 24, 12, 12, 32}, /* out of spec */ + {"300", CPU_K6_3P, fpus_internal, 300000000, 3.0, 2000, 0x5d0, 0x5d0, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 27, 27, 9, 9, 36}, /* out of spec */ + {"333", CPU_K6_3P, fpus_internal, 332500000, 3.5, 2000, 0x5d0, 0x5d0, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 30, 30, 11, 11, 40}, /* out of spec */ + {"350", CPU_K6_3P, fpus_internal, 350000000, 3.5, 2000, 0x5d0, 0x5d0, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 32, 32, 11, 11, 42}, /* out of spec */ + {"366", CPU_K6_3P, fpus_internal, 366666666, 5.5, 2000, 0x5d0, 0x5d0, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 33, 33, 17, 17, 44}, /* out of spec */ + {"380", CPU_K6_3P, fpus_internal, 380000000, 4.0, 2000, 0x5d0, 0x5d0, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 34, 34, 12, 12, 46}, /* out of spec */ + {"400", CPU_K6_3P, fpus_internal, 400000000, 4.0, 2000, 0x5d0, 0x5d0, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 36, 36, 12, 12, 48}, + {"450", CPU_K6_3P, fpus_internal, 450000000, 4.5, 2000, 0x5d0, 0x5d0, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 41, 41, 14, 14, 54}, + {"475", CPU_K6_3P, fpus_internal, 475000000, 5.0, 2000, 0x5d0, 0x5d0, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 43, 43, 15, 15, 57}, + {"500", CPU_K6_3P, fpus_internal, 500000000, 5.0, 2000, 0x5d0, 0x5d0, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 45, 45, 15, 15, 60}, + {"", 0} + } }, #if defined(DEV_BRANCH) && defined(USE_CYRIX_6X86) { - .package = CPU_PKG_SOCKET5_7, - .manufacturer = "Cyrix", - .name = "Cx6x86", - .internal_name = "cx6x86", - .cpus = (const CPU[]) { - {"P90", CPU_Cx6x86, fpus_internal, 80000000, 2.0, 3520, 0x520, 0x520, 0x1731, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 8, 8, 6, 6, 10}, - {"PR120+", CPU_Cx6x86, fpus_internal, 100000000, 2.0, 3520, 0x520, 0x520, 0x1731, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 10,10, 6, 6, 12}, - {"PR133+", CPU_Cx6x86, fpus_internal, 110000000, 2.0, 3520, 0x520, 0x520, 0x1731, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 10,10, 6, 6, 14}, - {"PR150+", CPU_Cx6x86, fpus_internal, 120000000, 2.0, 3520, 0x520, 0x520, 0x1731, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 12,12, 6, 6, 14}, - {"PR166+", CPU_Cx6x86, fpus_internal, 133333333, 2.0, 3520, 0x520, 0x520, 0x1731, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 12,12, 6, 6, 16}, - {"PR200+", CPU_Cx6x86, fpus_internal, 150000000, 2.0, 3520, 0x520, 0x520, 0x1731, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 12,12, 6, 6, 18}, - {"", 0} - } + .package = CPU_PKG_SOCKET5_7, + .manufacturer = "Cyrix", + .name = "Cx6x86", + .internal_name = "cx6x86", + .cpus = (const CPU[]) { + {"P90", CPU_Cx6x86, fpus_internal, 80000000, 2.0, 3520, 0x520, 0x520, 0x1731, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 8, 8, 6, 6, 10}, + {"PR120+", CPU_Cx6x86, fpus_internal, 100000000, 2.0, 3520, 0x520, 0x520, 0x1731, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 10,10, 6, 6, 12}, + {"PR133+", CPU_Cx6x86, fpus_internal, 110000000, 2.0, 3520, 0x520, 0x520, 0x1731, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 10,10, 6, 6, 14}, + {"PR150+", CPU_Cx6x86, fpus_internal, 120000000, 2.0, 3520, 0x520, 0x520, 0x1731, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 12,12, 6, 6, 14}, + {"PR166+", CPU_Cx6x86, fpus_internal, 133333333, 2.0, 3520, 0x520, 0x520, 0x1731, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 12,12, 6, 6, 16}, + {"PR200+", CPU_Cx6x86, fpus_internal, 150000000, 2.0, 3520, 0x520, 0x520, 0x1731, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 12,12, 6, 6, 18}, + {"", 0} + } }, { - .package = CPU_PKG_SOCKET5_7, - .manufacturer = "Cyrix", - .name = "Cx6x86L", - .internal_name = "cx6x86l", - .cpus = (const CPU[]) { - {"PR133+", CPU_Cx6x86L, fpus_internal, 110000000, 2.0, 2800, 0x540, 0x540, 0x2231, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 10,10, 6, 6, 14}, - {"PR150+", CPU_Cx6x86L, fpus_internal, 120000000, 2.0, 2800, 0x540, 0x540, 0x2231, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 12,12, 6, 6, 14}, - {"PR166+", CPU_Cx6x86L, fpus_internal, 133333333, 2.0, 2800, 0x540, 0x540, 0x2231, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 12,12, 6, 6, 16}, - {"PR200+", CPU_Cx6x86L, fpus_internal, 150000000, 2.0, 2800, 0x540, 0x540, 0x2231, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 12,12, 6, 6, 18}, - {"", 0} - } + .package = CPU_PKG_SOCKET5_7, + .manufacturer = "Cyrix", + .name = "Cx6x86L", + .internal_name = "cx6x86l", + .cpus = (const CPU[]) { + {"PR133+", CPU_Cx6x86L, fpus_internal, 110000000, 2.0, 2800, 0x540, 0x540, 0x2231, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 10,10, 6, 6, 14}, + {"PR150+", CPU_Cx6x86L, fpus_internal, 120000000, 2.0, 2800, 0x540, 0x540, 0x2231, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 12,12, 6, 6, 14}, + {"PR166+", CPU_Cx6x86L, fpus_internal, 133333333, 2.0, 2800, 0x540, 0x540, 0x2231, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 12,12, 6, 6, 16}, + {"PR200+", CPU_Cx6x86L, fpus_internal, 150000000, 2.0, 2800, 0x540, 0x540, 0x2231, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 12,12, 6, 6, 18}, + {"", 0} + } }, { - .package = CPU_PKG_SOCKET5_7, - .manufacturer = "Cyrix", - .name = "Cx6x86MX", - .internal_name = "cx6x86mx", - .cpus = (const CPU[]) { - {"PR166", CPU_Cx6x86MX, fpus_internal, 133333333, 2.0, 2900, 0x600, 0x600, 0x0451, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 12,12, 6, 6, 16}, - {"PR200", CPU_Cx6x86MX, fpus_internal, 166666666, 2.5, 2900, 0x600, 0x600, 0x0452, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 15,15, 7, 7, 20}, - {"PR233", CPU_Cx6x86MX, fpus_internal, 187500000, 2.5, 2900, 0x600, 0x600, 0x0452, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 15,15, 7, 7, 45/2}, - {"PR266", CPU_Cx6x86MX, fpus_internal, 208333333, 2.5, 2700, 0x600, 0x600, 0x0452, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 17,17, 7, 7, 25}, - {"", 0} - } + .package = CPU_PKG_SOCKET5_7, + .manufacturer = "Cyrix", + .name = "Cx6x86MX", + .internal_name = "cx6x86mx", + .cpus = (const CPU[]) { + {"PR166", CPU_Cx6x86MX, fpus_internal, 133333333, 2.0, 2900, 0x600, 0x600, 0x0451, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 12,12, 6, 6, 16}, + {"PR200", CPU_Cx6x86MX, fpus_internal, 166666666, 2.5, 2900, 0x600, 0x600, 0x0452, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 15,15, 7, 7, 20}, + {"PR233", CPU_Cx6x86MX, fpus_internal, 187500000, 2.5, 2900, 0x600, 0x600, 0x0452, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 15,15, 7, 7, 45/2}, + {"PR266", CPU_Cx6x86MX, fpus_internal, 208333333, 2.5, 2700, 0x600, 0x600, 0x0452, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 17,17, 7, 7, 25}, + {"", 0} + } }, { - .package = CPU_PKG_SOCKET5_7, - .manufacturer = "Cyrix", - .name = "MII", - .internal_name = "mii", - .cpus = (const CPU[]) { - {"PR300", CPU_Cx6x86MX, fpus_internal, 233333333, 3.5, 2900, 0x601, 0x601, 0x0852, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 21,21,11,11, 28}, - {"PR333", CPU_Cx6x86MX, fpus_internal, 250000000, 3.0, 2900, 0x601, 0x601, 0x0853, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 23,23, 9, 9, 30}, - {"PR366", CPU_Cx6x86MX, fpus_internal, 250000000, 2.5, 2900, 0x601, 0x601, 0x0853, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 23,23, 7, 7, 30}, - {"PR400", CPU_Cx6x86MX, fpus_internal, 285000000, 3.0, 2900, 0x601, 0x601, 0x0853, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 27,27, 9, 9, 34}, - {"PR433", CPU_Cx6x86MX, fpus_internal, 300000000, 3.0, 2900, 0x601, 0x601, 0x0853, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 27,27, 9, 9, 36}, - {"", 0} - } + .package = CPU_PKG_SOCKET5_7, + .manufacturer = "Cyrix", + .name = "MII", + .internal_name = "mii", + .cpus = (const CPU[]) { + {"PR300", CPU_Cx6x86MX, fpus_internal, 233333333, 3.5, 2900, 0x601, 0x601, 0x0852, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 21,21,11,11, 28}, + {"PR333", CPU_Cx6x86MX, fpus_internal, 250000000, 3.0, 2900, 0x601, 0x601, 0x0853, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 23,23, 9, 9, 30}, + {"PR366", CPU_Cx6x86MX, fpus_internal, 250000000, 2.5, 2900, 0x601, 0x601, 0x0853, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 23,23, 7, 7, 30}, + {"PR400", CPU_Cx6x86MX, fpus_internal, 285000000, 3.0, 2900, 0x601, 0x601, 0x0853, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 27,27, 9, 9, 34}, + {"PR433", CPU_Cx6x86MX, fpus_internal, 300000000, 3.0, 2900, 0x601, 0x601, 0x0853, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 27,27, 9, 9, 36}, + {"", 0} + } }, #endif { - .package = CPU_PKG_SOCKET8, - .manufacturer = "Intel", - .name = "Pentium Pro", - .internal_name = "pentiumpro", - .cpus = (const CPU[]) { - {"60", CPU_PENTIUMPRO, fpus_internal, 60000000, 1.0, 3100, 0x612, 0x612, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 6, 6, 1, 1, 7}, /* out of spec */ - {"66", CPU_PENTIUMPRO, fpus_internal, 66666666, 1.0, 3300, 0x617, 0x617, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 6, 6, 1, 1, 8}, /* out of spec */ - {"90", CPU_PENTIUMPRO, fpus_internal, 90000000, 1.5, 3100, 0x612, 0x612, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 9, 9, 3, 3, 11}, /* out of spec */ - {"100", CPU_PENTIUMPRO, fpus_internal, 100000000, 1.5, 3300, 0x617, 0x617, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 9, 9, 3, 3, 12}, /* out of spec */ - {"120", CPU_PENTIUMPRO, fpus_internal, 120000000, 2.0, 3100, 0x612, 0x612, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 12,12, 5, 5, 14}, /* out of spec */ - {"133", CPU_PENTIUMPRO, fpus_internal, 133333333, 2.0, 3300, 0x617, 0x617, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 12,12, 5, 5, 16}, /* out of spec */ - {"150", CPU_PENTIUMPRO, fpus_internal, 150000000, 2.5, 3100, 0x612, 0x612, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 15,15, 7, 7, 35/2}, - {"166", CPU_PENTIUMPRO, fpus_internal, 166666666, 2.5, 3300, 0x617, 0x617, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 15,15, 7, 7, 20}, - {"180", CPU_PENTIUMPRO, fpus_internal, 180000000, 3.0, 3300, 0x617, 0x617, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 18,18, 9, 9, 21}, - {"200", CPU_PENTIUMPRO, fpus_internal, 200000000, 3.0, 3300, 0x617, 0x617, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 18,18, 9, 9, 24}, - {"", 0} - } - }, { - .package = CPU_PKG_SOCKET8, - .manufacturer = "Intel", - .name = "Pentium II OverDrive", - .internal_name = "pentium2_od", - .cpus = (const CPU[]) { - {"66", CPU_PENTIUM2D, fpus_internal, 66666666, 1.0, 3300, 0x1632, 0x1632, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC | CPU_FIXED_MULTIPLIER, 6, 6, 3, 3, 8}, /* out of spec */ - {"100", CPU_PENTIUM2D, fpus_internal, 100000000, 1.5, 3300, 0x1632, 0x1632, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC | CPU_FIXED_MULTIPLIER, 9, 9, 4, 4, 12}, /* out of spec */ - {"133", CPU_PENTIUM2D, fpus_internal, 133333333, 2.0, 3300, 0x1632, 0x1632, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC | CPU_FIXED_MULTIPLIER, 12,12, 6, 6, 16}, /* out of spec */ - {"166", CPU_PENTIUM2D, fpus_internal, 166666666, 2.5, 3300, 0x1632, 0x1632, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC | CPU_FIXED_MULTIPLIER, 15,15, 7, 7, 20}, /* out of spec */ - {"200", CPU_PENTIUM2D, fpus_internal, 200000000, 3.0, 3300, 0x1632, 0x1632, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC | CPU_FIXED_MULTIPLIER, 18,18, 9, 9, 24}, /* out of spec */ - {"233", CPU_PENTIUM2D, fpus_internal, 233333333, 3.5, 3300, 0x1632, 0x1632, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC | CPU_FIXED_MULTIPLIER, 21,21,10,10, 28}, /* out of spec */ - {"266", CPU_PENTIUM2D, fpus_internal, 266666666, 4.0, 3300, 0x1632, 0x1632, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC | CPU_FIXED_MULTIPLIER, 24,24,12,12, 32}, /* out of spec */ - {"300", CPU_PENTIUM2D, fpus_internal, 300000000, 5.0, 3300, 0x1632, 0x1632, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC | CPU_FIXED_MULTIPLIER, 27,27,13,13, 36}, - {"333", CPU_PENTIUM2D, fpus_internal, 333333333, 5.0, 3300, 0x1632, 0x1632, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC | CPU_FIXED_MULTIPLIER, 27,27,13,13, 40}, - {"", 0} - } - }, { - .package = CPU_PKG_SLOT1, - .manufacturer = "Intel", - .name = "Pentium II (Klamath)", - .internal_name = "pentium2_klamath", - .cpus = (const CPU[]) { - {"66", CPU_PENTIUM2, fpus_internal, 66666666, 1.0, 2800, 0x634, 0x634, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 6, 6, 3, 3, 8}, /* out of spec */ - {"100", CPU_PENTIUM2, fpus_internal, 100000000, 1.5, 2800, 0x634, 0x634, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 9, 9, 4, 4, 12}, /* out of spec */ - {"133", CPU_PENTIUM2, fpus_internal, 133333333, 2.0, 2800, 0x634, 0x634, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 12,12, 6, 6, 16}, /* out of spec */ - {"166", CPU_PENTIUM2, fpus_internal, 166666666, 2.5, 2800, 0x634, 0x634, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 15,15, 7, 7, 20}, /* out of spec */ - {"200", CPU_PENTIUM2, fpus_internal, 200000000, 3.0, 2800, 0x634, 0x634, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 18,18, 9, 9, 24}, /* out of spec */ - {"233", CPU_PENTIUM2, fpus_internal, 233333333, 3.5, 2800, 0x634, 0x634, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 21,21,10,10, 28}, - {"266", CPU_PENTIUM2, fpus_internal, 266666666, 4.0, 2800, 0x634, 0x634, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 24,24,12,12, 32}, - {"300", CPU_PENTIUM2, fpus_internal, 300000000, 4.5, 2800, 0x634, 0x634, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 25,25,12,12, 36}, - {"", 0} - } - }, { - .package = CPU_PKG_SLOT1, - .manufacturer = "Intel", - .name = "Pentium II (Deschutes)", - .internal_name = "pentium2_deschutes", - .cpus = (const CPU[]) { - {"66", CPU_PENTIUM2D, fpus_internal, 66666666, 1.0, 2050, 0x652, 0x652, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 6, 6, 3, 3, 8}, /* out of spec */ - {"100", CPU_PENTIUM2D, fpus_internal, 100000000, 1.5, 2050, 0x652, 0x652, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 9, 9, 5, 5, 12}, /* out of spec */ - {"133", CPU_PENTIUM2D, fpus_internal, 133333333, 2.0, 2050, 0x652, 0x652, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 12,12, 6, 6, 16}, /* out of spec */ - {"166", CPU_PENTIUM2D, fpus_internal, 166666666, 2.5, 2050, 0x652, 0x652, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 15,15, 7, 7, 20}, /* out of spec */ - {"200", CPU_PENTIUM2D, fpus_internal, 200000000, 3.0, 2050, 0x652, 0x652, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 18,18, 9, 9, 24}, /* out of spec */ - {"233", CPU_PENTIUM2D, fpus_internal, 233333333, 3.5, 2050, 0x652, 0x652, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 21,21,11,11, 28}, /* out of spec */ - {"266", CPU_PENTIUM2D, fpus_internal, 266666666, 4.0, 2050, 0x652, 0x652, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 24,24,12,12, 32}, - {"300", CPU_PENTIUM2D, fpus_internal, 300000000, 4.5, 2050, 0x651, 0x651, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 25,25,12,12, 36}, - {"333", CPU_PENTIUM2D, fpus_internal, 333333333, 5.0, 2050, 0x651, 0x651, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 27,27,13,13, 40}, - {"350", CPU_PENTIUM2D, fpus_internal, 350000000, 3.5, 2050, 0x651, 0x651, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 32,32,11,11, 42}, - {"400", CPU_PENTIUM2D, fpus_internal, 400000000, 4.0, 2050, 0x652, 0x652, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 36,36,12,12, 48}, - {"450", CPU_PENTIUM2D, fpus_internal, 450000000, 4.5, 2050, 0x652, 0x652, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 41,41,14,14, 54}, - {"", 0} - } - }, { - .package = CPU_PKG_SLOT2, - .manufacturer = "Intel", - .name = "Pentium II Xeon", - .internal_name = "pentium2_xeon", - .cpus = (const CPU[]) { - {"100", CPU_PENTIUM2D, fpus_internal, 100000000, 1.0, 2050, 0x652, 0x652, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 9, 9, 3, 3, 12}, /* out of spec */ - {"150", CPU_PENTIUM2D, fpus_internal, 150000000, 1.5, 2050, 0x652, 0x652, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 14,14, 4, 4, 18}, /* out of spec */ - {"200", CPU_PENTIUM2D, fpus_internal, 200000000, 2.0, 2050, 0x652, 0x652, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 18,18, 6, 6, 24}, /* out of spec */ - {"250", CPU_PENTIUM2D, fpus_internal, 250000000, 2.5, 2050, 0x652, 0x652, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 22,22, 7, 7, 30}, /* out of spec */ - {"300", CPU_PENTIUM2D, fpus_internal, 300000000, 3.0, 2050, 0x652, 0x652, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 27,27, 9, 9, 36}, /* out of spec */ - {"350", CPU_PENTIUM2D, fpus_internal, 350000000, 3.5, 2050, 0x652, 0x652, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 32,32,10,10, 42}, /* out of spec */ - {"400", CPU_PENTIUM2D, fpus_internal, 400000000, 4.0, 2050, 0x652, 0x652, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 36,36,12,12, 48}, - {"450", CPU_PENTIUM2D, fpus_internal, 450000000, 4.5, 2050, 0x652, 0x652, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 41,41,14,14, 54}, - {"", 0} - } - }, { - .package = CPU_PKG_SOCKET370, - .manufacturer = "Intel", - .name = "Celeron (Mendocino)", - .internal_name = "celeron_mendocino", - .cpus = (const CPU[]) { - {"66", CPU_PENTIUM2D, fpus_internal, 66666666, 1.0, 2050, 0x665, 0x665, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC | CPU_FIXED_MULTIPLIER, 6, 6, 3, 3, 8}, /* out of spec */ - {"100", CPU_PENTIUM2D, fpus_internal, 100000000, 1.5, 2050, 0x665, 0x665, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC | CPU_FIXED_MULTIPLIER, 8, 8, 4, 4, 12}, /* out of spec */ - {"133", CPU_PENTIUM2D, fpus_internal, 133333333, 2.0, 2050, 0x665, 0x665, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC | CPU_FIXED_MULTIPLIER, 11,11, 5, 5, 16}, /* out of spec */ - {"166", CPU_PENTIUM2D, fpus_internal, 166666666, 2.5, 2050, 0x665, 0x665, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC | CPU_FIXED_MULTIPLIER, 14,14, 7, 7, 20}, /* out of spec */ - {"200", CPU_PENTIUM2D, fpus_internal, 200000000, 3.0, 2050, 0x665, 0x665, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC | CPU_FIXED_MULTIPLIER, 17,17, 8, 8, 24}, /* out of spec */ - {"233", CPU_PENTIUM2D, fpus_internal, 233333333, 3.5, 2050, 0x665, 0x665, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC | CPU_FIXED_MULTIPLIER, 19,19, 9, 9, 28}, /* out of spec */ - {"266", CPU_PENTIUM2D, fpus_internal, 266666666, 4.0, 2050, 0x665, 0x665, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC | CPU_FIXED_MULTIPLIER, 22,22,11,11, 32}, /* out of spec */ - {"300A", CPU_PENTIUM2D, fpus_internal, 300000000, 4.5, 2050, 0x665, 0x665, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC | CPU_FIXED_MULTIPLIER, 25,25,12,12, 36}, - {"333", CPU_PENTIUM2D, fpus_internal, 333333333, 5.0, 2050, 0x665, 0x665, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC | CPU_FIXED_MULTIPLIER, 27,27,13,13, 40}, - {"366", CPU_PENTIUM2D, fpus_internal, 366666666, 5.5, 2050, 0x665, 0x665, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC | CPU_FIXED_MULTIPLIER, 33,33,17,17, 44}, - {"400", CPU_PENTIUM2D, fpus_internal, 400000000, 6.0, 2050, 0x665, 0x665, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC | CPU_FIXED_MULTIPLIER, 36,36,12,12, 48}, - {"433", CPU_PENTIUM2D, fpus_internal, 433333333, 6.5, 2050, 0x665, 0x665, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC | CPU_FIXED_MULTIPLIER, 39,39,13,13, 51}, - {"466", CPU_PENTIUM2D, fpus_internal, 466666666, 7.0, 2050, 0x665, 0x665, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC | CPU_FIXED_MULTIPLIER, 42,42,14,14, 56}, - {"500", CPU_PENTIUM2D, fpus_internal, 500000000, 7.5, 2050, 0x665, 0x665, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC | CPU_FIXED_MULTIPLIER, 45,45,15,15, 60}, - {"533", CPU_PENTIUM2D, fpus_internal, 533333333, 8.0, 2050, 0x665, 0x665, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC | CPU_FIXED_MULTIPLIER, 48,48,17,17, 64}, - {"", 0} - } - }, { - .package = CPU_PKG_SOCKET370, - .manufacturer = "VIA", - .name = "Cyrix III", - .internal_name = "c3_samuel", - .cpus = (const CPU[]) { - {"66", CPU_CYRIX3S, fpus_internal, 66666666, 1.0, 2050, 0x660, 0x660, 0, CPU_SUPPORTS_DYNAREC | CPU_FIXED_MULTIPLIER, 6, 6, 3, 3, 8}, /* out of multiplier range */ - {"100", CPU_CYRIX3S, fpus_internal, 100000000, 1.5, 2050, 0x660, 0x660, 0, CPU_SUPPORTS_DYNAREC | CPU_FIXED_MULTIPLIER, 9, 9, 4, 4, 12}, /* out of multiplier range */ - {"133", CPU_CYRIX3S, fpus_internal, 133333333, 2.0, 2050, 0x660, 0x660, 0, CPU_SUPPORTS_DYNAREC | CPU_FIXED_MULTIPLIER, 12, 12, 6, 6, 16}, /* out of multiplier range */ - {"166", CPU_CYRIX3S, fpus_internal, 166666666, 2.5, 2050, 0x660, 0x660, 0, CPU_SUPPORTS_DYNAREC | CPU_FIXED_MULTIPLIER, 15, 15, 7, 7, 20}, /* out of multiplier range */ - {"200", CPU_CYRIX3S, fpus_internal, 200000000, 3.0, 2050, 0x660, 0x660, 0, CPU_SUPPORTS_DYNAREC | CPU_FIXED_MULTIPLIER, 18, 18, 8, 8, 24}, /* out of multiplier range */ - {"233", CPU_CYRIX3S, fpus_internal, 233333333, 3.5, 2050, 0x660, 0x660, 0, CPU_SUPPORTS_DYNAREC | CPU_FIXED_MULTIPLIER, 21, 21, 9, 9, 28}, /* out of multiplier range */ - {"266", CPU_CYRIX3S, fpus_internal, 266666666, 4.0, 2050, 0x660, 0x660, 0, CPU_SUPPORTS_DYNAREC | CPU_FIXED_MULTIPLIER, 24, 24, 12, 12, 32}, /* out of multiplier range */ - {"300", CPU_CYRIX3S, fpus_internal, 300000000, 4.5, 2050, 0x660, 0x660, 0, CPU_SUPPORTS_DYNAREC | CPU_FIXED_MULTIPLIER, 27, 27, 13, 13, 36}, /* out of spec */ - {"333", CPU_CYRIX3S, fpus_internal, 333333333, 5.0, 2050, 0x662, 0x662, 0, CPU_SUPPORTS_DYNAREC | CPU_FIXED_MULTIPLIER, 30, 30, 15, 15, 40}, /* out of spec */ - {"366", CPU_CYRIX3S, fpus_internal, 366666666, 5.5, 2050, 0x662, 0x662, 0, CPU_SUPPORTS_DYNAREC | CPU_FIXED_MULTIPLIER, 33, 33, 16, 16, 44}, /* out of spec */ - {"400", CPU_CYRIX3S, fpus_internal, 400000000, 6.0, 2050, 0x660, 0x660, 0, CPU_SUPPORTS_DYNAREC | CPU_FIXED_MULTIPLIER, 36, 36, 17, 17, 48}, - {"433", CPU_CYRIX3S, fpus_internal, 433333333, 6.5, 2050, 0x660, 0x660, 0, CPU_SUPPORTS_DYNAREC | CPU_FIXED_MULTIPLIER, 39, 39, 18, 18, 52}, /* out of spec */ - {"450", CPU_CYRIX3S, fpus_internal, 450000000, 4.5, 2050, 0x660, 0x660, 0, CPU_SUPPORTS_DYNAREC | CPU_FIXED_MULTIPLIER, 41, 41, 14, 14, 54}, - {"466", CPU_CYRIX3S, fpus_internal, 466666666, 6.5, 2050, 0x660, 0x660, 0, CPU_SUPPORTS_DYNAREC | CPU_FIXED_MULTIPLIER, 42, 42, 14, 14, 56}, /* out of spec */ - {"500", CPU_CYRIX3S, fpus_internal, 500000000, 5.0, 2050, 0x662, 0x662, 0, CPU_SUPPORTS_DYNAREC | CPU_FIXED_MULTIPLIER, 45, 45, 15, 15, 60}, - {"533", CPU_CYRIX3S, fpus_internal, 533333333, 8.0, 2050, 0x660, 0x660, 0, CPU_SUPPORTS_DYNAREC | CPU_FIXED_MULTIPLIER, 48, 48, 15, 15, 64}, /* out of spec */ - {"550", CPU_CYRIX3S, fpus_internal, 550000000, 5.5, 2050, 0x662, 0x662, 0, CPU_SUPPORTS_DYNAREC | CPU_FIXED_MULTIPLIER, 50, 50, 17, 17, 66}, - {"600/100", CPU_CYRIX3S, fpus_internal, 600000000, 6.0, 2050, 0x662, 0x662, 0, CPU_SUPPORTS_DYNAREC | CPU_FIXED_MULTIPLIER, 54, 54, 18, 18, 72}, - {"600/133", CPU_CYRIX3S, fpus_internal, 600000000, 4.5, 2050, 0x663, 0x663, 0, CPU_SUPPORTS_DYNAREC | CPU_FIXED_MULTIPLIER, 54, 54, 13, 13, 72}, - {"650", CPU_CYRIX3S, fpus_internal, 650000000, 6.5, 2050, 0x663, 0x663, 0, CPU_SUPPORTS_DYNAREC | CPU_FIXED_MULTIPLIER, 58, 58, 20, 20, 78}, - {"667", CPU_CYRIX3S, fpus_internal, 666666667, 5.0, 2050, 0x663, 0x663, 0, CPU_SUPPORTS_DYNAREC | CPU_FIXED_MULTIPLIER, 60, 60, 16, 16, 80}, - {"700", CPU_CYRIX3S, fpus_internal, 700000000, 7.0, 2050, 0x663, 0x663, 0, CPU_SUPPORTS_DYNAREC | CPU_FIXED_MULTIPLIER, 63, 63, 21, 21, 84}, - {"733", CPU_CYRIX3S, fpus_internal, 733333333, 5.5, 2050, 0x663, 0x663, 0, CPU_SUPPORTS_DYNAREC | CPU_FIXED_MULTIPLIER, 66, 66, 18, 18, 88}, - {"", 0} - } - }, { - .package = 0, + .package = CPU_PKG_SOCKET8, + .manufacturer = "Intel", + .name = "Pentium Pro", + .internal_name = "pentiumpro", + .cpus = (const CPU[]) { + {"60", CPU_PENTIUMPRO, fpus_internal, 60000000, 1.0, 3100, 0x612, 0x612, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 6, 6, 1, 1, 7}, /* out of spec */ + {"66", CPU_PENTIUMPRO, fpus_internal, 66666666, 1.0, 3300, 0x617, 0x617, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 6, 6, 1, 1, 8}, /* out of spec */ + {"90", CPU_PENTIUMPRO, fpus_internal, 90000000, 1.5, 3100, 0x612, 0x612, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 9, 9, 3, 3, 11}, /* out of spec */ + {"100", CPU_PENTIUMPRO, fpus_internal, 100000000, 1.5, 3300, 0x617, 0x617, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 9, 9, 3, 3, 12}, /* out of spec */ + {"120", CPU_PENTIUMPRO, fpus_internal, 120000000, 2.0, 3100, 0x612, 0x612, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 12,12, 5, 5, 14}, /* out of spec */ + {"133", CPU_PENTIUMPRO, fpus_internal, 133333333, 2.0, 3300, 0x617, 0x617, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 12,12, 5, 5, 16}, /* out of spec */ + {"150", CPU_PENTIUMPRO, fpus_internal, 150000000, 2.5, 3100, 0x612, 0x612, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 15,15, 7, 7, 35/2}, + {"166", CPU_PENTIUMPRO, fpus_internal, 166666666, 2.5, 3300, 0x617, 0x617, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 15,15, 7, 7, 20}, + {"180", CPU_PENTIUMPRO, fpus_internal, 180000000, 3.0, 3300, 0x617, 0x617, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 18,18, 9, 9, 21}, + {"200", CPU_PENTIUMPRO, fpus_internal, 200000000, 3.0, 3300, 0x617, 0x617, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 18,18, 9, 9, 24}, + {"", 0} } + }, { + .package = CPU_PKG_SOCKET8, + .manufacturer = "Intel", + .name = "Pentium II OverDrive", + .internal_name = "pentium2_od", + .cpus = (const CPU[]) { + {"66", CPU_PENTIUM2D, fpus_internal, 66666666, 1.0, 3300, 0x1632, 0x1632, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC | CPU_FIXED_MULTIPLIER, 6, 6, 3, 3, 8}, /* out of spec */ + {"100", CPU_PENTIUM2D, fpus_internal, 100000000, 1.5, 3300, 0x1632, 0x1632, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC | CPU_FIXED_MULTIPLIER, 9, 9, 4, 4, 12}, /* out of spec */ + {"133", CPU_PENTIUM2D, fpus_internal, 133333333, 2.0, 3300, 0x1632, 0x1632, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC | CPU_FIXED_MULTIPLIER, 12,12, 6, 6, 16}, /* out of spec */ + {"166", CPU_PENTIUM2D, fpus_internal, 166666666, 2.5, 3300, 0x1632, 0x1632, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC | CPU_FIXED_MULTIPLIER, 15,15, 7, 7, 20}, /* out of spec */ + {"200", CPU_PENTIUM2D, fpus_internal, 200000000, 3.0, 3300, 0x1632, 0x1632, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC | CPU_FIXED_MULTIPLIER, 18,18, 9, 9, 24}, /* out of spec */ + {"233", CPU_PENTIUM2D, fpus_internal, 233333333, 3.5, 3300, 0x1632, 0x1632, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC | CPU_FIXED_MULTIPLIER, 21,21,10,10, 28}, /* out of spec */ + {"266", CPU_PENTIUM2D, fpus_internal, 266666666, 4.0, 3300, 0x1632, 0x1632, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC | CPU_FIXED_MULTIPLIER, 24,24,12,12, 32}, /* out of spec */ + {"300", CPU_PENTIUM2D, fpus_internal, 300000000, 5.0, 3300, 0x1632, 0x1632, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC | CPU_FIXED_MULTIPLIER, 27,27,13,13, 36}, + {"333", CPU_PENTIUM2D, fpus_internal, 333333333, 5.0, 3300, 0x1632, 0x1632, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC | CPU_FIXED_MULTIPLIER, 27,27,13,13, 40}, + {"", 0} + } + }, { + .package = CPU_PKG_SLOT1, + .manufacturer = "Intel", + .name = "Pentium II (Klamath)", + .internal_name = "pentium2_klamath", + .cpus = (const CPU[]) { + {"66", CPU_PENTIUM2, fpus_internal, 66666666, 1.0, 2800, 0x634, 0x634, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 6, 6, 3, 3, 8}, /* out of spec */ + {"100", CPU_PENTIUM2, fpus_internal, 100000000, 1.5, 2800, 0x634, 0x634, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 9, 9, 4, 4, 12}, /* out of spec */ + {"133", CPU_PENTIUM2, fpus_internal, 133333333, 2.0, 2800, 0x634, 0x634, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 12,12, 6, 6, 16}, /* out of spec */ + {"166", CPU_PENTIUM2, fpus_internal, 166666666, 2.5, 2800, 0x634, 0x634, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 15,15, 7, 7, 20}, /* out of spec */ + {"200", CPU_PENTIUM2, fpus_internal, 200000000, 3.0, 2800, 0x634, 0x634, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 18,18, 9, 9, 24}, /* out of spec */ + {"233", CPU_PENTIUM2, fpus_internal, 233333333, 3.5, 2800, 0x634, 0x634, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 21,21,10,10, 28}, + {"266", CPU_PENTIUM2, fpus_internal, 266666666, 4.0, 2800, 0x634, 0x634, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 24,24,12,12, 32}, + {"300", CPU_PENTIUM2, fpus_internal, 300000000, 4.5, 2800, 0x634, 0x634, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 25,25,12,12, 36}, + {"", 0} + } + }, { + .package = CPU_PKG_SLOT1, + .manufacturer = "Intel", + .name = "Pentium II (Deschutes)", + .internal_name = "pentium2_deschutes", + .cpus = (const CPU[]) { + {"66", CPU_PENTIUM2D, fpus_internal, 66666666, 1.0, 2050, 0x652, 0x652, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 6, 6, 3, 3, 8}, /* out of spec */ + {"100", CPU_PENTIUM2D, fpus_internal, 100000000, 1.5, 2050, 0x652, 0x652, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 9, 9, 5, 5, 12}, /* out of spec */ + {"133", CPU_PENTIUM2D, fpus_internal, 133333333, 2.0, 2050, 0x652, 0x652, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 12,12, 6, 6, 16}, /* out of spec */ + {"166", CPU_PENTIUM2D, fpus_internal, 166666666, 2.5, 2050, 0x652, 0x652, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 15,15, 7, 7, 20}, /* out of spec */ + {"200", CPU_PENTIUM2D, fpus_internal, 200000000, 3.0, 2050, 0x652, 0x652, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 18,18, 9, 9, 24}, /* out of spec */ + {"233", CPU_PENTIUM2D, fpus_internal, 233333333, 3.5, 2050, 0x652, 0x652, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 21,21,11,11, 28}, /* out of spec */ + {"266", CPU_PENTIUM2D, fpus_internal, 266666666, 4.0, 2050, 0x652, 0x652, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 24,24,12,12, 32}, + {"300", CPU_PENTIUM2D, fpus_internal, 300000000, 4.5, 2050, 0x651, 0x651, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 25,25,12,12, 36}, + {"333", CPU_PENTIUM2D, fpus_internal, 333333333, 5.0, 2050, 0x651, 0x651, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 27,27,13,13, 40}, + {"350", CPU_PENTIUM2D, fpus_internal, 350000000, 3.5, 2050, 0x651, 0x651, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 32,32,11,11, 42}, + {"400", CPU_PENTIUM2D, fpus_internal, 400000000, 4.0, 2050, 0x652, 0x652, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 36,36,12,12, 48}, + {"450", CPU_PENTIUM2D, fpus_internal, 450000000, 4.5, 2050, 0x652, 0x652, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 41,41,14,14, 54}, + {"", 0} + } + }, { + .package = CPU_PKG_SLOT1, + .manufacturer = "Intel", + .name = "Celeron (Covington)", + .internal_name = "celeron_covington", + .cpus = (const CPU[]) { + {"66", CPU_PENTIUM2D, fpus_internal, 66666666, 1.0, 2050, 0x652, 0x652, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 6, 6, 6, 6, 8}, /* out of spec */ + {"100", CPU_PENTIUM2D, fpus_internal, 100000000, 1.5, 2050, 0x652, 0x652, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 9, 9, 9, 9, 12}, /* out of spec */ + {"133", CPU_PENTIUM2D, fpus_internal, 133333333, 2.0, 2050, 0x652, 0x652, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 12,12,12,12, 16}, /* out of spec */ + {"166", CPU_PENTIUM2D, fpus_internal, 166666666, 2.5, 2050, 0x652, 0x652, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 15,15,15,15, 20}, /* out of spec */ + {"200", CPU_PENTIUM2D, fpus_internal, 200000000, 3.0, 2050, 0x652, 0x652, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 18,18,18,18, 24}, /* out of spec */ + {"233", CPU_PENTIUM2D, fpus_internal, 233333333, 3.5, 2050, 0x652, 0x652, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 21,21,21,21, 28}, /* out of spec */ + {"266", CPU_PENTIUM2D, fpus_internal, 266666666, 4.0, 2050, 0x650, 0x650, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 24,24,24,24, 32}, + {"300", CPU_PENTIUM2D, fpus_internal, 300000000, 4.5, 2050, 0x651, 0x651, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 25,25,25,25, 36}, + {"", 0} + } + }, { + .package = CPU_PKG_SLOT2, + .manufacturer = "Intel", + .name = "Pentium II Xeon", + .internal_name = "pentium2_xeon", + .cpus = (const CPU[]) { + {"100", CPU_PENTIUM2D, fpus_internal, 100000000, 1.0, 2050, 0x652, 0x652, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 9, 9, 3, 3, 12}, /* out of spec */ + {"150", CPU_PENTIUM2D, fpus_internal, 150000000, 1.5, 2050, 0x652, 0x652, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 14,14, 4, 4, 18}, /* out of spec */ + {"200", CPU_PENTIUM2D, fpus_internal, 200000000, 2.0, 2050, 0x652, 0x652, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 18,18, 6, 6, 24}, /* out of spec */ + {"250", CPU_PENTIUM2D, fpus_internal, 250000000, 2.5, 2050, 0x652, 0x652, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 22,22, 7, 7, 30}, /* out of spec */ + {"300", CPU_PENTIUM2D, fpus_internal, 300000000, 3.0, 2050, 0x652, 0x652, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 27,27, 9, 9, 36}, /* out of spec */ + {"350", CPU_PENTIUM2D, fpus_internal, 350000000, 3.5, 2050, 0x652, 0x652, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 32,32,10,10, 42}, /* out of spec */ + {"400", CPU_PENTIUM2D, fpus_internal, 400000000, 4.0, 2050, 0x652, 0x652, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 36,36,12,12, 48}, + {"450", CPU_PENTIUM2D, fpus_internal, 450000000, 4.5, 2050, 0x652, 0x652, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 41,41,14,14, 54}, + {"", 0} + } + }, { + .package = CPU_PKG_SOCKET370, + .manufacturer = "Intel", + .name = "Celeron (Mendocino)", + .internal_name = "celeron_mendocino", + .cpus = (const CPU[]) { + {"66", CPU_PENTIUM2D, fpus_internal, 66666666, 1.0, 2050, 0x665, 0x665, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC | CPU_FIXED_MULTIPLIER, 6, 6, 3, 3, 8}, /* out of spec */ + {"100", CPU_PENTIUM2D, fpus_internal, 100000000, 1.5, 2050, 0x665, 0x665, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC | CPU_FIXED_MULTIPLIER, 8, 8, 4, 4, 12}, /* out of spec */ + {"133", CPU_PENTIUM2D, fpus_internal, 133333333, 2.0, 2050, 0x665, 0x665, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC | CPU_FIXED_MULTIPLIER, 11,11, 5, 5, 16}, /* out of spec */ + {"166", CPU_PENTIUM2D, fpus_internal, 166666666, 2.5, 2050, 0x665, 0x665, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC | CPU_FIXED_MULTIPLIER, 14,14, 7, 7, 20}, /* out of spec */ + {"200", CPU_PENTIUM2D, fpus_internal, 200000000, 3.0, 2050, 0x665, 0x665, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC | CPU_FIXED_MULTIPLIER, 17,17, 8, 8, 24}, /* out of spec */ + {"233", CPU_PENTIUM2D, fpus_internal, 233333333, 3.5, 2050, 0x665, 0x665, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC | CPU_FIXED_MULTIPLIER, 19,19, 9, 9, 28}, /* out of spec */ + {"266", CPU_PENTIUM2D, fpus_internal, 266666666, 4.0, 2050, 0x665, 0x665, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC | CPU_FIXED_MULTIPLIER, 22,22,11,11, 32}, /* out of spec */ + {"300A", CPU_PENTIUM2D, fpus_internal, 300000000, 4.5, 2050, 0x665, 0x665, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC | CPU_FIXED_MULTIPLIER, 25,25,12,12, 36}, + {"333", CPU_PENTIUM2D, fpus_internal, 333333333, 5.0, 2050, 0x665, 0x665, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC | CPU_FIXED_MULTIPLIER, 27,27,13,13, 40}, + {"366", CPU_PENTIUM2D, fpus_internal, 366666666, 5.5, 2050, 0x665, 0x665, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC | CPU_FIXED_MULTIPLIER, 33,33,17,17, 44}, + {"400", CPU_PENTIUM2D, fpus_internal, 400000000, 6.0, 2050, 0x665, 0x665, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC | CPU_FIXED_MULTIPLIER, 36,36,12,12, 48}, + {"433", CPU_PENTIUM2D, fpus_internal, 433333333, 6.5, 2050, 0x665, 0x665, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC | CPU_FIXED_MULTIPLIER, 39,39,13,13, 51}, + {"466", CPU_PENTIUM2D, fpus_internal, 466666666, 7.0, 2050, 0x665, 0x665, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC | CPU_FIXED_MULTIPLIER, 42,42,14,14, 56}, + {"500", CPU_PENTIUM2D, fpus_internal, 500000000, 7.5, 2050, 0x665, 0x665, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC | CPU_FIXED_MULTIPLIER, 45,45,15,15, 60}, + {"533", CPU_PENTIUM2D, fpus_internal, 533333333, 8.0, 2050, 0x665, 0x665, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC | CPU_FIXED_MULTIPLIER, 48,48,17,17, 64}, + {"", 0} + } + }, { + .package = CPU_PKG_SOCKET370, + .manufacturer = "VIA", + .name = "Cyrix III", + .internal_name = "c3_samuel", + .cpus = (const CPU[]) { + {"66", CPU_CYRIX3S, fpus_internal, 66666666, 1.0, 2050, 0x660, 0x660, 0, CPU_SUPPORTS_DYNAREC | CPU_FIXED_MULTIPLIER, 6, 6, 3, 3, 8}, /* out of multiplier range */ + {"100", CPU_CYRIX3S, fpus_internal, 100000000, 1.5, 2050, 0x660, 0x660, 0, CPU_SUPPORTS_DYNAREC | CPU_FIXED_MULTIPLIER, 9, 9, 4, 4, 12}, /* out of multiplier range */ + {"133", CPU_CYRIX3S, fpus_internal, 133333333, 2.0, 2050, 0x660, 0x660, 0, CPU_SUPPORTS_DYNAREC | CPU_FIXED_MULTIPLIER, 12, 12, 6, 6, 16}, /* out of multiplier range */ + {"166", CPU_CYRIX3S, fpus_internal, 166666666, 2.5, 2050, 0x660, 0x660, 0, CPU_SUPPORTS_DYNAREC | CPU_FIXED_MULTIPLIER, 15, 15, 7, 7, 20}, /* out of multiplier range */ + {"200", CPU_CYRIX3S, fpus_internal, 200000000, 3.0, 2050, 0x660, 0x660, 0, CPU_SUPPORTS_DYNAREC | CPU_FIXED_MULTIPLIER, 18, 18, 8, 8, 24}, /* out of multiplier range */ + {"233", CPU_CYRIX3S, fpus_internal, 233333333, 3.5, 2050, 0x660, 0x660, 0, CPU_SUPPORTS_DYNAREC | CPU_FIXED_MULTIPLIER, 21, 21, 9, 9, 28}, /* out of multiplier range */ + {"266", CPU_CYRIX3S, fpus_internal, 266666666, 4.0, 2050, 0x660, 0x660, 0, CPU_SUPPORTS_DYNAREC | CPU_FIXED_MULTIPLIER, 24, 24, 12, 12, 32}, /* out of multiplier range */ + {"300", CPU_CYRIX3S, fpus_internal, 300000000, 4.5, 2050, 0x660, 0x660, 0, CPU_SUPPORTS_DYNAREC | CPU_FIXED_MULTIPLIER, 27, 27, 13, 13, 36}, /* out of spec */ + {"333", CPU_CYRIX3S, fpus_internal, 333333333, 5.0, 2050, 0x662, 0x662, 0, CPU_SUPPORTS_DYNAREC | CPU_FIXED_MULTIPLIER, 30, 30, 15, 15, 40}, /* out of spec */ + {"366", CPU_CYRIX3S, fpus_internal, 366666666, 5.5, 2050, 0x662, 0x662, 0, CPU_SUPPORTS_DYNAREC | CPU_FIXED_MULTIPLIER, 33, 33, 16, 16, 44}, /* out of spec */ + {"400", CPU_CYRIX3S, fpus_internal, 400000000, 6.0, 2050, 0x660, 0x660, 0, CPU_SUPPORTS_DYNAREC | CPU_FIXED_MULTIPLIER, 36, 36, 17, 17, 48}, + {"433", CPU_CYRIX3S, fpus_internal, 433333333, 6.5, 2050, 0x660, 0x660, 0, CPU_SUPPORTS_DYNAREC | CPU_FIXED_MULTIPLIER, 39, 39, 18, 18, 52}, /* out of spec */ + {"450", CPU_CYRIX3S, fpus_internal, 450000000, 4.5, 2050, 0x660, 0x660, 0, CPU_SUPPORTS_DYNAREC | CPU_FIXED_MULTIPLIER, 41, 41, 14, 14, 54}, + {"466", CPU_CYRIX3S, fpus_internal, 466666666, 6.5, 2050, 0x660, 0x660, 0, CPU_SUPPORTS_DYNAREC | CPU_FIXED_MULTIPLIER, 42, 42, 14, 14, 56}, /* out of spec */ + {"500", CPU_CYRIX3S, fpus_internal, 500000000, 5.0, 2050, 0x662, 0x662, 0, CPU_SUPPORTS_DYNAREC | CPU_FIXED_MULTIPLIER, 45, 45, 15, 15, 60}, + {"533", CPU_CYRIX3S, fpus_internal, 533333333, 8.0, 2050, 0x660, 0x660, 0, CPU_SUPPORTS_DYNAREC | CPU_FIXED_MULTIPLIER, 48, 48, 15, 15, 64}, /* out of spec */ + {"550", CPU_CYRIX3S, fpus_internal, 550000000, 5.5, 2050, 0x662, 0x662, 0, CPU_SUPPORTS_DYNAREC | CPU_FIXED_MULTIPLIER, 50, 50, 17, 17, 66}, + {"600/100", CPU_CYRIX3S, fpus_internal, 600000000, 6.0, 2050, 0x662, 0x662, 0, CPU_SUPPORTS_DYNAREC | CPU_FIXED_MULTIPLIER, 54, 54, 18, 18, 72}, + {"600/133", CPU_CYRIX3S, fpus_internal, 600000000, 4.5, 2050, 0x663, 0x663, 0, CPU_SUPPORTS_DYNAREC | CPU_FIXED_MULTIPLIER, 54, 54, 13, 13, 72}, + {"650", CPU_CYRIX3S, fpus_internal, 650000000, 6.5, 2050, 0x663, 0x663, 0, CPU_SUPPORTS_DYNAREC | CPU_FIXED_MULTIPLIER, 58, 58, 20, 20, 78}, + {"667", CPU_CYRIX3S, fpus_internal, 666666667, 5.0, 2050, 0x663, 0x663, 0, CPU_SUPPORTS_DYNAREC | CPU_FIXED_MULTIPLIER, 60, 60, 16, 16, 80}, + {"700", CPU_CYRIX3S, fpus_internal, 700000000, 7.0, 2050, 0x663, 0x663, 0, CPU_SUPPORTS_DYNAREC | CPU_FIXED_MULTIPLIER, 63, 63, 21, 21, 84}, + {"733", CPU_CYRIX3S, fpus_internal, 733333333, 5.5, 2050, 0x663, 0x663, 0, CPU_SUPPORTS_DYNAREC | CPU_FIXED_MULTIPLIER, 66, 66, 18, 18, 88}, + {"", 0} + } + }, { + .package = 0, + } + // clang-format on }; /* Legacy CPU tables for backwards compatibility. */ static const cpu_legacy_table_t cpus_8088[] = { - {"8088", 4772728, 1}, - {"8088", 7159092, 1}, - {"8088", 8000000, 1}, - {"8088", 10000000, 1}, - {"8088", 12000000, 1}, - {"8088", 16000000, 1}, - {NULL, 0, 0} + {"8088", 4772728, 1}, + { "8088", 7159092, 1}, + { "8088", 8000000, 1}, + { "8088", 10000000, 1}, + { "8088", 12000000, 1}, + { "8088", 16000000, 1}, + { NULL, 0, 0} }; static const cpu_legacy_table_t cpus_pcjr[] = { {"8088", 4772728, 1}, - {NULL, 0, 0} + { NULL, 0, 0} }; static const cpu_legacy_table_t cpus_europc[] = { - {"8088_europc", 4772728, 1}, - {"8088_europc", 7159092, 1}, - {"8088_europc", 9545456, 1}, - {NULL, 0, 0} + {"8088_europc", 4772728, 1}, + { "8088_europc", 7159092, 1}, + { "8088_europc", 9545456, 1}, + { NULL, 0, 0} }; static const cpu_legacy_table_t cpus_8086[] = { - {"8086", 7159092, 1}, - {"8086", 8000000, 1}, - {"8086", 9545456, 1}, - {"8086", 10000000, 1}, - {"8086", 12000000, 1}, - {"8086", 16000000, 1}, - {NULL, 0, 0} + {"8086", 7159092, 1}, + { "8086", 8000000, 1}, + { "8086", 9545456, 1}, + { "8086", 10000000, 1}, + { "8086", 12000000, 1}, + { "8086", 16000000, 1}, + { NULL, 0, 0} }; static const cpu_legacy_table_t cpus_pc1512[] = { {"8086", 8000000, 1}, - {NULL, 0, 0} + { NULL, 0, 0} }; static const cpu_legacy_table_t cpus_286[] = { - {"286", 6000000, 1}, - {"286", 8000000, 1}, - {"286", 10000000, 1}, - {"286", 12500000, 1}, - {"286", 16000000, 1}, - {"286", 20000000, 1}, - {"286", 25000000, 1}, - {NULL, 0, 0} + {"286", 6000000, 1}, + { "286", 8000000, 1}, + { "286", 10000000, 1}, + { "286", 12500000, 1}, + { "286", 16000000, 1}, + { "286", 20000000, 1}, + { "286", 25000000, 1}, + { NULL, 0, 0} }; static const cpu_legacy_table_t cpus_ibmat[] = { - {"286", 6000000, 1}, - {"286", 8000000, 1}, - {NULL, 0, 0} + {"286", 6000000, 1}, + { "286", 8000000, 1}, + { NULL, 0, 0} }; static const cpu_legacy_table_t cpus_ibmxt286[] = { {"286", 6000000, 1}, - {NULL, 0, 0} + { NULL, 0, 0} }; static const cpu_legacy_table_t cpus_ps1_m2011[] = { {"286", 10000000, 1}, - {NULL, 0, 0} + { NULL, 0, 0} }; static const cpu_legacy_table_t cpus_ps2_m30_286[] = { - {"286", 10000000, 1}, - {"286", 12500000, 1}, - {"286", 16000000, 1}, - {"286", 20000000, 1}, - {"286", 25000000, 1}, - {NULL, 0, 0} + {"286", 10000000, 1}, + { "286", 12500000, 1}, + { "286", 16000000, 1}, + { "286", 20000000, 1}, + { "286", 25000000, 1}, + { NULL, 0, 0} }; static const cpu_legacy_table_t cpus_i386SX[] = { - {"i386sx", 16000000, 1}, - {"i386sx", 20000000, 1}, - {"i386sx", 25000000, 1}, - {"i386sx", 33333333, 1}, - {"i386sx", 40000000, 1}, - {NULL, 0, 0} + {"i386sx", 16000000, 1}, + { "i386sx", 20000000, 1}, + { "i386sx", 25000000, 1}, + { "i386sx", 33333333, 1}, + { "i386sx", 40000000, 1}, + { NULL, 0, 0} }; static const cpu_legacy_table_t cpus_i386DX[] = { - {"i386dx", 16000000, 1}, - {"i386dx", 20000000, 1}, - {"i386dx", 25000000, 1}, - {"i386dx", 33333333, 1}, - {"i386dx", 40000000, 1}, - {"rapidcad", 25000000, 1}, - {"rapidcad", 33333333, 1}, - {"rapidcad", 40000000, 1}, - {NULL, 0, 0} + {"i386dx", 16000000, 1}, + { "i386dx", 20000000, 1}, + { "i386dx", 25000000, 1}, + { "i386dx", 33333333, 1}, + { "i386dx", 40000000, 1}, + { "rapidcad", 25000000, 1}, + { "rapidcad", 33333333, 1}, + { "rapidcad", 40000000, 1}, + { NULL, 0, 0} }; static const cpu_legacy_table_t cpus_Am386SX[] = { - {"am386sx", 16000000, 1}, - {"am386sx", 20000000, 1}, - {"am386sx", 25000000, 1}, - {"am386sx", 33333333, 1}, - {"am386sx", 40000000, 1}, - {NULL, 0, 0} + {"am386sx", 16000000, 1}, + { "am386sx", 20000000, 1}, + { "am386sx", 25000000, 1}, + { "am386sx", 33333333, 1}, + { "am386sx", 40000000, 1}, + { NULL, 0, 0} }; static const cpu_legacy_table_t cpus_Am386DX[] = { - {"am386dx", 25000000, 1}, - {"am386dx", 33333333, 1}, - {"am386dx", 40000000, 1}, - {NULL, 0, 0} + {"am386dx", 25000000, 1}, + { "am386dx", 33333333, 1}, + { "am386dx", 40000000, 1}, + { NULL, 0, 0} }; static const cpu_legacy_table_t cpus_ALiM6117[] = { - {"m6117", 33333333, 1}, - {"m6117", 40000000, 1}, - {NULL, 0, 0} + {"m6117", 33333333, 1}, + { "m6117", 40000000, 1}, + { NULL, 0, 0} }; static const cpu_legacy_table_t cpus_486SLC[] = { - {"cx486slc", 20000000, 1}, - {"cx486slc", 25000000, 1}, - {"cx486slc", 33333333, 1}, - {"cx486srx2", 32000000, 2}, - {"cx486srx2", 40000000, 2}, - {"cx486srx2", 50000000, 2}, - {NULL, 0, 0} + {"cx486slc", 20000000, 1}, + { "cx486slc", 25000000, 1}, + { "cx486slc", 33333333, 1}, + { "cx486srx2", 32000000, 2}, + { "cx486srx2", 40000000, 2}, + { "cx486srx2", 50000000, 2}, + { NULL, 0, 0} }; static const cpu_legacy_table_t cpus_IBM486SLC[] = { - {"ibm486slc", 33333333, 1}, - {"ibm486slc2", 40000000, 2}, - {"ibm486slc2", 50000000, 2}, - {"ibm486slc2", 66666666, 2}, - {"ibm486slc3", 60000000, 3}, - {"ibm486slc3", 75000000, 3}, - {"ibm486slc3", 100000000, 3}, - {NULL, 0, 0} + {"ibm486slc", 33333333, 1}, + { "ibm486slc2", 40000000, 2}, + { "ibm486slc2", 50000000, 2}, + { "ibm486slc2", 66666666, 2}, + { "ibm486slc3", 60000000, 3}, + { "ibm486slc3", 75000000, 3}, + { "ibm486slc3", 100000000, 3}, + { NULL, 0, 0} }; -static const cpu_legacy_table_t cpus_IBM486BL[] = { - {"ibm486bl2", 50000000, 2}, - {"ibm486bl2", 66666666, 2}, - {"ibm486bl3", 75000000, 3}, - {"ibm486bl3", 100000000, 3}, - {NULL, 0, 0} +static const cpu_legacy_table_t cpus_IBM486BL[] = { + {"ibm486bl2", 50000000, 2}, + { "ibm486bl2", 66666666, 2}, + { "ibm486bl3", 75000000, 3}, + { "ibm486bl3", 100000000, 3}, + { NULL, 0, 0} }; static const cpu_legacy_table_t cpus_486DLC[] = { - {"cx486dlc", 25000000, 1}, - {"cx486dlc", 33333333, 1}, - {"cx486dlc", 40000000, 1}, - {"cx486drx2", 32000000, 2}, - {"cx486drx2", 40000000, 2}, - {"cx486drx2", 50000000, 2}, - {"cx486drx2", 66666666, 2}, - {NULL, 0, 0} + {"cx486dlc", 25000000, 1}, + { "cx486dlc", 33333333, 1}, + { "cx486dlc", 40000000, 1}, + { "cx486drx2", 32000000, 2}, + { "cx486drx2", 40000000, 2}, + { "cx486drx2", 50000000, 2}, + { "cx486drx2", 66666666, 2}, + { NULL, 0, 0} }; static const cpu_legacy_table_t cpus_i486S1[] = { - {"i486sx", 16000000, 1}, - {"i486sx", 20000000, 1}, - {"i486sx", 25000000, 1}, - {"i486sx", 33333333, 1}, - {"i486sx2", 50000000, 2}, - {"i486sx2", 66666666, 2}, - {"i486dx", 25000000, 1}, - {"i486dx", 33333333, 1}, - {"i486dx", 50000000, 1}, - {"i486dx2", 40000000, 2}, - {"i486dx2", 50000000, 2}, - {"i486dx2", 66666666, 2}, - {"idx4_od", 75000000, 3}, - {"idx4_od", 100000000, 3}, - {NULL, 0, 0} + {"i486sx", 16000000, 1}, + { "i486sx", 20000000, 1}, + { "i486sx", 25000000, 1}, + { "i486sx", 33333333, 1}, + { "i486sx2", 50000000, 2}, + { "i486sx2", 66666666, 2}, + { "i486dx", 25000000, 1}, + { "i486dx", 33333333, 1}, + { "i486dx", 50000000, 1}, + { "i486dx2", 40000000, 2}, + { "i486dx2", 50000000, 2}, + { "i486dx2", 66666666, 2}, + { "idx4_od", 75000000, 3}, + { "idx4_od", 100000000, 3}, + { NULL, 0, 0} }; static const cpu_legacy_table_t cpus_Am486S1[] = { - {"am486sx", 33333333, 1}, - {"am486sx", 40000000, 1}, - {"am486sx2", 50000000, 2}, - {"am486sx2", 66666666, 2}, - {"am486dx", 33333333, 1}, - {"am486dx", 40000000, 1}, - {"am486dx2", 50000000, 2}, - {"am486dx2", 66666666, 2}, - {"am486dx2", 80000000, 2}, - {NULL, 0, 0} + {"am486sx", 33333333, 1}, + { "am486sx", 40000000, 1}, + { "am486sx2", 50000000, 2}, + { "am486sx2", 66666666, 2}, + { "am486dx", 33333333, 1}, + { "am486dx", 40000000, 1}, + { "am486dx2", 50000000, 2}, + { "am486dx2", 66666666, 2}, + { "am486dx2", 80000000, 2}, + { NULL, 0, 0} }; static const cpu_legacy_table_t cpus_Cx486S1[] = { - {"cx486s", 25000000, 1.0}, - {"cx486s", 33333333, 1.0}, - {"cx486s", 40000000, 1.0}, - {"cx486dx", 33333333, 1.0}, - {"cx486dx", 40000000, 1.0}, - {"cx486dx2", 50000000, 2.0}, - {"cx486dx2", 66666666, 2.0}, - {"cx486dx2", 80000000, 2.0}, - {NULL, 0, 0} + {"cx486s", 25000000, 1.0}, + { "cx486s", 33333333, 1.0}, + { "cx486s", 40000000, 1.0}, + { "cx486dx", 33333333, 1.0}, + { "cx486dx", 40000000, 1.0}, + { "cx486dx2", 50000000, 2.0}, + { "cx486dx2", 66666666, 2.0}, + { "cx486dx2", 80000000, 2.0}, + { NULL, 0, 0 } }; static const cpu_legacy_table_t cpus_i486[] = { - {"i486sx", 16000000, 1.0}, - {"i486sx", 20000000, 1.0}, - {"i486sx", 25000000, 1.0}, - {"i486sx", 33333333, 1.0}, - {"i486sx2", 50000000, 2.0}, - {"i486sx2", 66666666, 2.0}, - {"i486dx", 25000000, 1.0}, - {"i486dx", 33333333, 1.0}, - {"i486dx", 50000000, 1.0}, - {"i486dx2", 40000000, 2.0}, - {"i486dx2", 50000000, 2.0}, - {"i486dx2", 66666666, 2.0}, - {"idx4", 75000000, 3.0}, - {"idx4", 100000000, 3.0}, - {"idx4_od", 75000000, 3.0}, - {"idx4_od", 100000000, 3.0}, - {"pentium_p24t", 62500000, 2.5}, - {"pentium_p24t", 83333333, 2.5}, - {NULL, 0, 0} + {"i486sx", 16000000, 1.0}, + { "i486sx", 20000000, 1.0}, + { "i486sx", 25000000, 1.0}, + { "i486sx", 33333333, 1.0}, + { "i486sx2", 50000000, 2.0}, + { "i486sx2", 66666666, 2.0}, + { "i486dx", 25000000, 1.0}, + { "i486dx", 33333333, 1.0}, + { "i486dx", 50000000, 1.0}, + { "i486dx2", 40000000, 2.0}, + { "i486dx2", 50000000, 2.0}, + { "i486dx2", 66666666, 2.0}, + { "idx4", 75000000, 3.0}, + { "idx4", 100000000, 3.0}, + { "idx4_od", 75000000, 3.0}, + { "idx4_od", 100000000, 3.0}, + { "pentium_p24t", 62500000, 2.5}, + { "pentium_p24t", 83333333, 2.5}, + { NULL, 0, 0 } }; static const cpu_legacy_table_t cpus_i486_PC330[] = { - {"i486dx2", 50000000, 2.0}, - {"i486dx2", 66666666, 2.0}, - {"idx4", 75000000, 3.0}, - {"idx4", 100000000, 3.0}, - {"pentium_p24t", 62500000, 2.5}, - {"pentium_p24t", 83333333, 2.5}, - {NULL, 0, 0} + {"i486dx2", 50000000, 2.0}, + { "i486dx2", 66666666, 2.0}, + { "idx4", 75000000, 3.0}, + { "idx4", 100000000, 3.0}, + { "pentium_p24t", 62500000, 2.5}, + { "pentium_p24t", 83333333, 2.5}, + { NULL, 0, 0 } }; static const cpu_legacy_table_t cpus_Am486[] = { - {"am486sx", 33333333, 1.0}, - {"am486sx", 40000000, 1.0}, - {"am486sx2", 50000000, 2.0}, - {"am486sx2", 66666666, 2.0}, - {"am486dx", 33333333, 1.0}, - {"am486dx", 40000000, 1.0}, - {"am486dx2", 50000000, 2.0}, - {"am486dx2", 66666666, 2.0}, - {"am486dx2", 80000000, 2.0}, - {"am486dx4", 75000000, 3.0}, - {"am486dx4", 90000000, 3.0}, - {"am486dx4", 100000000, 3.0}, - {"am486dx4", 120000000, 3.0}, - {"am5x86", 133333333, 4.0}, - {"am5x86", 150000000, 3.0}, - {"am5x86", 160000000, 4.0}, - {NULL, 0, 0} + {"am486sx", 33333333, 1.0}, + { "am486sx", 40000000, 1.0}, + { "am486sx2", 50000000, 2.0}, + { "am486sx2", 66666666, 2.0}, + { "am486dx", 33333333, 1.0}, + { "am486dx", 40000000, 1.0}, + { "am486dx2", 50000000, 2.0}, + { "am486dx2", 66666666, 2.0}, + { "am486dx2", 80000000, 2.0}, + { "am486dx4", 75000000, 3.0}, + { "am486dx4", 90000000, 3.0}, + { "am486dx4", 100000000, 3.0}, + { "am486dx4", 120000000, 3.0}, + { "am5x86", 133333333, 4.0}, + { "am5x86", 150000000, 3.0}, + { "am5x86", 160000000, 4.0}, + { NULL, 0, 0 } }; static const cpu_legacy_table_t cpus_Cx486[] = { - {"cx486s", 25000000, 1.0}, - {"cx486s", 33333333, 1.0}, - {"cx486s", 40000000, 1.0}, - {"cx486dx", 33333333, 1.0}, - {"cx486dx", 40000000, 1.0}, - {"cx486dx2", 50000000, 2.0}, - {"cx486dx2", 66666666, 2.0}, - {"cx486dx2", 80000000, 2.0}, - {"cx486dx4", 75000000, 3.0}, - {"cx486dx4", 100000000, 3.0}, - {"cx5x86", 80000000, 2.0}, - {"cx5x86", 100000000, 3.0}, - {"cx5x86", 120000000, 3.0}, - {"cx5x86", 133333333, 4.0}, - {NULL, 0, 0} + {"cx486s", 25000000, 1.0}, + { "cx486s", 33333333, 1.0}, + { "cx486s", 40000000, 1.0}, + { "cx486dx", 33333333, 1.0}, + { "cx486dx", 40000000, 1.0}, + { "cx486dx2", 50000000, 2.0}, + { "cx486dx2", 66666666, 2.0}, + { "cx486dx2", 80000000, 2.0}, + { "cx486dx4", 75000000, 3.0}, + { "cx486dx4", 100000000, 3.0}, + { "cx5x86", 80000000, 2.0}, + { "cx5x86", 100000000, 3.0}, + { "cx5x86", 120000000, 3.0}, + { "cx5x86", 133333333, 4.0}, + { NULL, 0, 0 } }; static const cpu_legacy_table_t cpus_STPCDX[] = { - {"stpc_dx", 66666666, 1.0}, - {"stpc_dx", 75000000, 1.0}, - {NULL, 0, 0} + {"stpc_dx", 66666666, 1.0}, + { "stpc_dx", 75000000, 1.0}, + { NULL, 0, 0 } }; static const cpu_legacy_table_t cpus_STPCDX2[] = { {"stpc_dx2", 133333333, 2.0}, - {NULL, 0, 0} + { NULL, 0, 0 } }; static const cpu_legacy_table_t cpus_6x863V[] = { - {"cx6x86", 80000000, 2.0}, - {"cx6x86", 100000000, 2.0}, - {"cx6x86", 110000000, 2.0}, - {"cx6x86", 120000000, 2.0}, - {"cx6x86", 133333333, 2.0}, - {"cx6x86", 150000000, 2.0}, - {NULL, 0, 0} + {"cx6x86", 80000000, 2.0}, + { "cx6x86", 100000000, 2.0}, + { "cx6x86", 110000000, 2.0}, + { "cx6x86", 120000000, 2.0}, + { "cx6x86", 133333333, 2.0}, + { "cx6x86", 150000000, 2.0}, + { NULL, 0, 0 } }; static const cpu_legacy_table_t cpus_6x86[] = { - {"cx6x86", 80000000, 2.0}, - {"cx6x86", 100000000, 2.0}, - {"cx6x86", 110000000, 2.0}, - {"cx6x86", 120000000, 2.0}, - {"cx6x86", 133333333, 2.0}, - {"cx6x86", 150000000, 2.0}, - {"cx6x86l", 110000000, 2.0}, - {"cx6x86l", 120000000, 2.0}, - {"cx6x86l", 133333333, 2.0}, - {"cx6x86l", 150000000, 2.0}, - {"cx6x86mx", 133333333, 2.0}, - {"cx6x86mx", 166666666, 2.5}, - {"cx6x86mx", 187500000, 2.5}, - {"cx6x86mx", 208333333, 2.5}, - {"mii", 233333333, 3.5}, - {"mii", 250000000, 3.0}, - {NULL, 0, 0} + {"cx6x86", 80000000, 2.0}, + { "cx6x86", 100000000, 2.0}, + { "cx6x86", 110000000, 2.0}, + { "cx6x86", 120000000, 2.0}, + { "cx6x86", 133333333, 2.0}, + { "cx6x86", 150000000, 2.0}, + { "cx6x86l", 110000000, 2.0}, + { "cx6x86l", 120000000, 2.0}, + { "cx6x86l", 133333333, 2.0}, + { "cx6x86l", 150000000, 2.0}, + { "cx6x86mx", 133333333, 2.0}, + { "cx6x86mx", 166666666, 2.5}, + { "cx6x86mx", 187500000, 2.5}, + { "cx6x86mx", 208333333, 2.5}, + { "mii", 233333333, 3.5}, + { "mii", 250000000, 3.0}, + { NULL, 0, 0 } }; static const cpu_legacy_table_t cpus_6x86SS7[] = { - {"cx6x86", 80000000, 2.0}, - {"cx6x86", 100000000, 2.0}, - {"cx6x86", 110000000, 2.0}, - {"cx6x86", 120000000, 2.0}, - {"cx6x86", 133333333, 2.0}, - {"cx6x86", 150000000, 2.0}, - {"cx6x86l", 110000000, 2.0}, - {"cx6x86l", 120000000, 2.0}, - {"cx6x86l", 133333333, 2.0}, - {"cx6x86l", 150000000, 2.0}, - {"cx6x86mx", 133333333, 2.0}, - {"cx6x86mx", 166666666, 2.5}, - {"cx6x86mx", 187500000, 2.5}, - {"cx6x86mx", 208333333, 2.5}, - {"mii", 233333333, 3.5}, - {"mii", 250000000, 3.0}, - {"mii", 250000000, 2.5}, - {"mii", 285000000, 3.0}, - {"mii", 300000000, 3.0}, - {NULL, 0, 0} + {"cx6x86", 80000000, 2.0}, + { "cx6x86", 100000000, 2.0}, + { "cx6x86", 110000000, 2.0}, + { "cx6x86", 120000000, 2.0}, + { "cx6x86", 133333333, 2.0}, + { "cx6x86", 150000000, 2.0}, + { "cx6x86l", 110000000, 2.0}, + { "cx6x86l", 120000000, 2.0}, + { "cx6x86l", 133333333, 2.0}, + { "cx6x86l", 150000000, 2.0}, + { "cx6x86mx", 133333333, 2.0}, + { "cx6x86mx", 166666666, 2.5}, + { "cx6x86mx", 187500000, 2.5}, + { "cx6x86mx", 208333333, 2.5}, + { "mii", 233333333, 3.5}, + { "mii", 250000000, 3.0}, + { "mii", 250000000, 2.5}, + { "mii", 285000000, 3.0}, + { "mii", 300000000, 3.0}, + { NULL, 0, 0 } }; static const cpu_legacy_table_t cpus_WinChip[] = { - {"winchip", 75000000, 1.5}, - {"winchip", 90000000, 1.5}, - {"winchip", 100000000, 1.5}, - {"winchip", 120000000, 2.0}, - {"winchip", 133333333, 2.0}, - {"winchip", 150000000, 2.5}, - {"winchip", 166666666, 2.5}, - {"winchip", 180000000, 3.0}, - {"winchip", 200000000, 3.0}, - {"winchip", 225000000, 3.0}, - {"winchip", 240000000, 4.0}, - {"winchip2", 200000000, 3.0}, - {"winchip2", 225000000, 3.0}, - {"winchip2", 240000000, 4.0}, - {"winchip2", 250000000, 3.0}, - {"winchip2a", 200000000, 3.0}, - {"winchip2a", 233333333, 3.5}, - {NULL, 0, 0} + {"winchip", 75000000, 1.5}, + { "winchip", 90000000, 1.5}, + { "winchip", 100000000, 1.5}, + { "winchip", 120000000, 2.0}, + { "winchip", 133333333, 2.0}, + { "winchip", 150000000, 2.5}, + { "winchip", 166666666, 2.5}, + { "winchip", 180000000, 3.0}, + { "winchip", 200000000, 3.0}, + { "winchip", 225000000, 3.0}, + { "winchip", 240000000, 4.0}, + { "winchip2", 200000000, 3.0}, + { "winchip2", 225000000, 3.0}, + { "winchip2", 240000000, 4.0}, + { "winchip2", 250000000, 3.0}, + { "winchip2a", 200000000, 3.0}, + { "winchip2a", 233333333, 3.5}, + { NULL, 0, 0 } }; static const cpu_legacy_table_t cpus_WinChip_SS7[] = { - {"winchip", 75000000, 1.5}, - {"winchip", 90000000, 1.5}, - {"winchip", 100000000, 1.5}, - {"winchip", 120000000, 2.0}, - {"winchip", 133333333, 2.0}, - {"winchip", 150000000, 2.5}, - {"winchip", 166666666, 2.5}, - {"winchip", 180000000, 3.0}, - {"winchip", 200000000, 3.0}, - {"winchip", 225000000, 3.0}, - {"winchip", 240000000, 4.0}, - {"winchip2", 200000000, 3.0}, - {"winchip2", 225000000, 3.0}, - {"winchip2", 240000000, 4.0}, - {"winchip2", 250000000, 3.0}, - {"winchip2a", 200000000, 3.0}, - {"winchip2a", 233333333, 3.5}, - {"winchip2a", 233333333, 7.0}, - {"winchip2a", 250000000, 2.5}, - {NULL, 0, 0} + {"winchip", 75000000, 1.5}, + { "winchip", 90000000, 1.5}, + { "winchip", 100000000, 1.5}, + { "winchip", 120000000, 2.0}, + { "winchip", 133333333, 2.0}, + { "winchip", 150000000, 2.5}, + { "winchip", 166666666, 2.5}, + { "winchip", 180000000, 3.0}, + { "winchip", 200000000, 3.0}, + { "winchip", 225000000, 3.0}, + { "winchip", 240000000, 4.0}, + { "winchip2", 200000000, 3.0}, + { "winchip2", 225000000, 3.0}, + { "winchip2", 240000000, 4.0}, + { "winchip2", 250000000, 3.0}, + { "winchip2a", 200000000, 3.0}, + { "winchip2a", 233333333, 3.5}, + { "winchip2a", 233333333, 7.0}, + { "winchip2a", 250000000, 2.5}, + { NULL, 0, 0 } }; static const cpu_legacy_table_t cpus_Pentium5V[] = { - {"pentium_p5", 60000000, 1}, - {"pentium_p5", 66666666, 1}, - {"pentium_p54c_od5v", 120000000, 2}, - {"pentium_p54c_od5v", 133333333, 2}, - {NULL, 0, 0} + {"pentium_p5", 60000000, 1}, + { "pentium_p5", 66666666, 1}, + { "pentium_p54c_od5v", 120000000, 2}, + { "pentium_p54c_od5v", 133333333, 2}, + { NULL, 0, 0} }; static const cpu_legacy_table_t cpus_PentiumS5[] = { - {"pentium_p54c", 75000000, 1.5}, - {"pentium_p55c_od", 75000000, 1.5}, - {"pentium_p54c", 90000000, 1.5}, - {"pentium_p54c", 100000000, 2.0}, - {"pentium_p54c", 100000000, 1.5}, - {"pentium_p54c", 120000000, 2.0}, - {"pentium_p54c", 133333333, 2.0}, - {"pentium_p54c_od3v", 125000000, 3.0}, - {"pentium_p54c_od3v", 150000000, 2.5}, - {"pentium_p54c_od3v", 166666666, 2.5}, - {"pentium_p55c_od", 125000000, 2.5}, - {"pentium_p55c_od", 150000000, 2.5}, - {"pentium_p55c_od", 166000000, 2.5}, - {"pentium_p55c_od", 180000000, 3.0}, - {"pentium_p55c_od", 200000000, 3.0}, - {NULL, 0, 0} + {"pentium_p54c", 75000000, 1.5}, + { "pentium_p55c_od", 75000000, 1.5}, + { "pentium_p54c", 90000000, 1.5}, + { "pentium_p54c", 100000000, 2.0}, + { "pentium_p54c", 100000000, 1.5}, + { "pentium_p54c", 120000000, 2.0}, + { "pentium_p54c", 133333333, 2.0}, + { "pentium_p54c_od3v", 125000000, 3.0}, + { "pentium_p54c_od3v", 150000000, 2.5}, + { "pentium_p54c_od3v", 166666666, 2.5}, + { "pentium_p55c_od", 125000000, 2.5}, + { "pentium_p55c_od", 150000000, 2.5}, + { "pentium_p55c_od", 166000000, 2.5}, + { "pentium_p55c_od", 180000000, 3.0}, + { "pentium_p55c_od", 200000000, 3.0}, + { NULL, 0, 0 } }; static const cpu_legacy_table_t cpus_Pentium3V[] = { - {"pentium_p54c", 75000000, 1.5}, - {"pentium_p55c_od", 75000000, 1.5}, - {"pentium_p54c", 90000000, 1.5}, - {"pentium_p54c", 100000000, 2.0}, - {"pentium_p54c", 100000000, 1.5}, - {"pentium_p54c", 120000000, 2.0}, - {"pentium_p54c", 133333333, 2.0}, - {"pentium_p54c", 150000000, 2.5}, - {"pentium_p54c", 166666666, 2.5}, - {"pentium_p54c", 200000000, 3.0}, - {"pentium_p54c_od3v", 125000000, 2.5}, - {"pentium_p54c_od3v", 150000000, 2.5}, - {"pentium_p54c_od3v", 166666666, 2.5}, - {"pentium_p55c_od", 125000000, 2.5}, - {"pentium_p55c_od", 150000000, 2.5}, - {"pentium_p55c_od", 166000000, 2.5}, - {"pentium_p55c_od", 180000000, 3.0}, - {"pentium_p55c_od", 200000000, 3.0}, - {NULL, 0, 0} + {"pentium_p54c", 75000000, 1.5}, + { "pentium_p55c_od", 75000000, 1.5}, + { "pentium_p54c", 90000000, 1.5}, + { "pentium_p54c", 100000000, 2.0}, + { "pentium_p54c", 100000000, 1.5}, + { "pentium_p54c", 120000000, 2.0}, + { "pentium_p54c", 133333333, 2.0}, + { "pentium_p54c", 150000000, 2.5}, + { "pentium_p54c", 166666666, 2.5}, + { "pentium_p54c", 200000000, 3.0}, + { "pentium_p54c_od3v", 125000000, 2.5}, + { "pentium_p54c_od3v", 150000000, 2.5}, + { "pentium_p54c_od3v", 166666666, 2.5}, + { "pentium_p55c_od", 125000000, 2.5}, + { "pentium_p55c_od", 150000000, 2.5}, + { "pentium_p55c_od", 166000000, 2.5}, + { "pentium_p55c_od", 180000000, 3.0}, + { "pentium_p55c_od", 200000000, 3.0}, + { NULL, 0, 0 } }; static const cpu_legacy_table_t cpus_Pentium[] = { - {"pentium_p54c", 75000000, 1.5}, - {"pentium_p55c_od", 75000000, 1.5}, - {"pentium_p54c", 90000000, 1.5}, - {"pentium_p54c", 100000000, 2.0}, - {"pentium_p54c", 100000000, 1.5}, - {"pentium_p54c", 120000000, 2.0}, - {"pentium_p54c", 133333333, 2.0}, - {"pentium_p54c", 150000000, 2.5}, - {"pentium_p54c", 166666666, 2.5}, - {"pentium_p54c", 200000000, 3.0}, - {"pentium_p55c", 166666666, 2.5}, - {"pentium_p55c", 200000000, 3.0}, - {"pentium_p55c", 233333333, 3.5}, - {"pentium_tillamook", 120000000, 2.0}, - {"pentium_tillamook", 133333333, 2.0}, - {"pentium_tillamook", 150000000, 2.5}, - {"pentium_tillamook", 166666666, 2.5}, - {"pentium_tillamook", 200000000, 3.0}, - {"pentium_tillamook", 233333333, 3.5}, - {"pentium_tillamook", 266666666, 4.0}, - {"pentium_tillamook", 300000000, 4.5}, - {"pentium_p54c_od3v", 125000000, 2.5}, - {"pentium_p54c_od3v", 150000000, 2.5}, - {"pentium_p54c_od3v", 166666666, 2.5}, - {"pentium_p55c_od", 125000000, 2.5}, - {"pentium_p55c_od", 150000000, 2.5}, - {"pentium_p55c_od", 166000000, 2.5}, - {"pentium_p55c_od", 180000000, 3.0}, - {"pentium_p55c_od", 200000000, 3.0}, - {NULL, 0, 0} + {"pentium_p54c", 75000000, 1.5}, + { "pentium_p55c_od", 75000000, 1.5}, + { "pentium_p54c", 90000000, 1.5}, + { "pentium_p54c", 100000000, 2.0}, + { "pentium_p54c", 100000000, 1.5}, + { "pentium_p54c", 120000000, 2.0}, + { "pentium_p54c", 133333333, 2.0}, + { "pentium_p54c", 150000000, 2.5}, + { "pentium_p54c", 166666666, 2.5}, + { "pentium_p54c", 200000000, 3.0}, + { "pentium_p55c", 166666666, 2.5}, + { "pentium_p55c", 200000000, 3.0}, + { "pentium_p55c", 233333333, 3.5}, + { "pentium_tillamook", 120000000, 2.0}, + { "pentium_tillamook", 133333333, 2.0}, + { "pentium_tillamook", 150000000, 2.5}, + { "pentium_tillamook", 166666666, 2.5}, + { "pentium_tillamook", 200000000, 3.0}, + { "pentium_tillamook", 233333333, 3.5}, + { "pentium_tillamook", 266666666, 4.0}, + { "pentium_tillamook", 300000000, 4.5}, + { "pentium_p54c_od3v", 125000000, 2.5}, + { "pentium_p54c_od3v", 150000000, 2.5}, + { "pentium_p54c_od3v", 166666666, 2.5}, + { "pentium_p55c_od", 125000000, 2.5}, + { "pentium_p55c_od", 150000000, 2.5}, + { "pentium_p55c_od", 166000000, 2.5}, + { "pentium_p55c_od", 180000000, 3.0}, + { "pentium_p55c_od", 200000000, 3.0}, + { NULL, 0, 0 } }; static const cpu_legacy_table_t cpus_K5[] = { - {"k5_5k86", 75000000, 1.5}, - {"k5_ssa5", 75000000, 1.5}, - {"k5_5k86", 90000000, 1.5}, - {"k5_ssa5", 90000000, 1.5}, - {"k5_5k86", 100000000, 1.5}, - {"k5_ssa5", 100000000, 1.5}, - {"k5_5k86", 120000000, 2.0}, - {"k5_5k86", 133333333, 2.0}, - {"k5_5k86", 150000000, 2.5}, - {"k5_5k86", 166666666, 2.5}, - {"k5_5k86", 200000000, 3.0}, - {NULL, 0, 0} + {"k5_5k86", 75000000, 1.5}, + { "k5_ssa5", 75000000, 1.5}, + { "k5_5k86", 90000000, 1.5}, + { "k5_ssa5", 90000000, 1.5}, + { "k5_5k86", 100000000, 1.5}, + { "k5_ssa5", 100000000, 1.5}, + { "k5_5k86", 120000000, 2.0}, + { "k5_5k86", 133333333, 2.0}, + { "k5_5k86", 150000000, 2.5}, + { "k5_5k86", 166666666, 2.5}, + { "k5_5k86", 200000000, 3.0}, + { NULL, 0, 0 } }; static const cpu_legacy_table_t cpus_K56[] = { - {"k6_m6", 66666666, 1.0}, - {"k6_m6", 100000000, 1.5}, - {"k6_m6", 133333333, 2.0}, - {"k6_m6", 166666666, 2.5}, - {"k6_m6", 200000000, 3.0}, - {"k6_m6", 233333333, 3.5}, - {"k6_m7", 100000000, 1.5}, - {"k6_m7", 133333333, 2.0}, - {"k6_m7", 166666666, 2.5}, - {"k6_m7", 200000000, 3.0}, - {"k6_m7", 233333333, 3.5}, - {"k6_m7", 266666666, 4.0}, - {"k6_m7", 300000000, 4.5}, - {"k6_2", 100000000, 1.5}, - {"k6_2", 133333333, 2.0}, - {"k6_2", 166666666, 2.5}, - {"k6_2", 200000000, 3.0}, - {"k6_2", 233333333, 3.5}, - {"k6_2", 266666666, 4.0}, - {"k6_2", 300000000, 4.5}, - {"k6_2", 366666666, 5.5}, - {NULL, 0, 0} + {"k6_m6", 66666666, 1.0}, + { "k6_m6", 100000000, 1.5}, + { "k6_m6", 133333333, 2.0}, + { "k6_m6", 166666666, 2.5}, + { "k6_m6", 200000000, 3.0}, + { "k6_m6", 233333333, 3.5}, + { "k6_m7", 100000000, 1.5}, + { "k6_m7", 133333333, 2.0}, + { "k6_m7", 166666666, 2.5}, + { "k6_m7", 200000000, 3.0}, + { "k6_m7", 233333333, 3.5}, + { "k6_m7", 266666666, 4.0}, + { "k6_m7", 300000000, 4.5}, + { "k6_2", 100000000, 1.5}, + { "k6_2", 133333333, 2.0}, + { "k6_2", 166666666, 2.5}, + { "k6_2", 200000000, 3.0}, + { "k6_2", 233333333, 3.5}, + { "k6_2", 266666666, 4.0}, + { "k6_2", 300000000, 4.5}, + { "k6_2", 366666666, 5.5}, + { NULL, 0, 0 } }; static const cpu_legacy_table_t cpus_K56_SS7[] = { - {"k6_m6", 66666666, 1.0}, - {"k6_m6", 100000000, 1.5}, - {"k6_m6", 133333333, 2.0}, - {"k6_m6", 166666666, 2.5}, - {"k6_m6", 200000000, 3.0}, - {"k6_m6", 233333333, 3.5}, - {"k6_m7", 100000000, 1.5}, - {"k6_m7", 133333333, 2.0}, - {"k6_m7", 166666666, 2.5}, - {"k6_m7", 200000000, 3.0}, - {"k6_m7", 233333333, 3.5}, - {"k6_m7", 266666666, 4.0}, - {"k6_m7", 300000000, 4.5}, - {"k6_2", 100000000, 1.5}, - {"k6_2", 133333333, 2.0}, - {"k6_2", 166666666, 2.5}, - {"k6_2", 200000000, 3.0}, - {"k6_2", 233333333, 3.5}, - {"k6_2", 266666666, 4.0}, - {"k6_2", 300000000, 3.0}, - {"k6_2", 332500000, 3.5}, - {"k6_2", 350000000, 3.5}, - {"k6_2", 366666666, 5.5}, - {"k6_2", 380000000, 4.0}, - {"k6_2", 400000000, 4.0}, - {"k6_2", 450000000, 4.5}, - {"k6_2", 475000000, 5.0}, - {"k6_2", 500000000, 5.0}, - {"k6_2", 533333333, 5.5}, - {"k6_2", 550000000, 5.5}, - {"k6_2p", 100000000, 1.5}, - {"k6_2p", 133333333, 2.0}, - {"k6_2p", 166666666, 2.5}, - {"k6_2p", 200000000, 3.0}, - {"k6_2p", 233333333, 3.5}, - {"k6_2p", 266666666, 4.0}, - {"k6_2p", 300000000, 3.0}, - {"k6_2p", 332500000, 3.5}, - {"k6_2p", 350000000, 3.5}, - {"k6_2p", 366666666, 5.5}, - {"k6_2p", 380000000, 4.0}, - {"k6_2p", 400000000, 4.0}, - {"k6_2p", 450000000, 4.5}, - {"k6_2p", 475000000, 5.0}, - {"k6_2p", 500000000, 5.0}, - {"k6_2p", 533333333, 5.5}, - {"k6_2p", 550000000, 5.5}, - {"k6_3", 100000000, 1.5}, - {"k6_3", 133333333, 2.0}, - {"k6_3", 166666666, 2.5}, - {"k6_3", 200000000, 3.0}, - {"k6_3", 233333333, 3.5}, - {"k6_3", 266666666, 4.0}, - {"k6_3", 300000000, 3.0}, - {"k6_3", 332500000, 3.5}, - {"k6_3", 350000000, 3.5}, - {"k6_3", 366666666, 5.5}, - {"k6_3", 380000000, 4.0}, - {"k6_3", 400000000, 4.0}, - {"k6_3", 450000000, 4.5}, - {"k6_3p", 75000000, 1.5}, - {"k6_3p", 100000000, 1.5}, - {"k6_3p", 133333333, 2.0}, - {"k6_3p", 166666666, 2.5}, - {"k6_3p", 200000000, 3.0}, - {"k6_3p", 233333333, 3.5}, - {"k6_3p", 266666666, 4.0}, - {"k6_3p", 300000000, 3.0}, - {"k6_3p", 332500000, 3.5}, - {"k6_3p", 350000000, 3.5}, - {"k6_3p", 366666666, 5.5}, - {"k6_3p", 380000000, 4.0}, - {"k6_3p", 400000000, 4.0}, - {"k6_3p", 450000000, 4.5}, - {"k6_3p", 475000000, 5.0}, - {"k6_3p", 500000000, 5.0}, - {NULL, 0, 0} + {"k6_m6", 66666666, 1.0}, + { "k6_m6", 100000000, 1.5}, + { "k6_m6", 133333333, 2.0}, + { "k6_m6", 166666666, 2.5}, + { "k6_m6", 200000000, 3.0}, + { "k6_m6", 233333333, 3.5}, + { "k6_m7", 100000000, 1.5}, + { "k6_m7", 133333333, 2.0}, + { "k6_m7", 166666666, 2.5}, + { "k6_m7", 200000000, 3.0}, + { "k6_m7", 233333333, 3.5}, + { "k6_m7", 266666666, 4.0}, + { "k6_m7", 300000000, 4.5}, + { "k6_2", 100000000, 1.5}, + { "k6_2", 133333333, 2.0}, + { "k6_2", 166666666, 2.5}, + { "k6_2", 200000000, 3.0}, + { "k6_2", 233333333, 3.5}, + { "k6_2", 266666666, 4.0}, + { "k6_2", 300000000, 3.0}, + { "k6_2", 332500000, 3.5}, + { "k6_2", 350000000, 3.5}, + { "k6_2", 366666666, 5.5}, + { "k6_2", 380000000, 4.0}, + { "k6_2", 400000000, 4.0}, + { "k6_2", 450000000, 4.5}, + { "k6_2", 475000000, 5.0}, + { "k6_2", 500000000, 5.0}, + { "k6_2", 533333333, 5.5}, + { "k6_2", 550000000, 5.5}, + { "k6_2p", 100000000, 1.5}, + { "k6_2p", 133333333, 2.0}, + { "k6_2p", 166666666, 2.5}, + { "k6_2p", 200000000, 3.0}, + { "k6_2p", 233333333, 3.5}, + { "k6_2p", 266666666, 4.0}, + { "k6_2p", 300000000, 3.0}, + { "k6_2p", 332500000, 3.5}, + { "k6_2p", 350000000, 3.5}, + { "k6_2p", 366666666, 5.5}, + { "k6_2p", 380000000, 4.0}, + { "k6_2p", 400000000, 4.0}, + { "k6_2p", 450000000, 4.5}, + { "k6_2p", 475000000, 5.0}, + { "k6_2p", 500000000, 5.0}, + { "k6_2p", 533333333, 5.5}, + { "k6_2p", 550000000, 5.5}, + { "k6_3", 100000000, 1.5}, + { "k6_3", 133333333, 2.0}, + { "k6_3", 166666666, 2.5}, + { "k6_3", 200000000, 3.0}, + { "k6_3", 233333333, 3.5}, + { "k6_3", 266666666, 4.0}, + { "k6_3", 300000000, 3.0}, + { "k6_3", 332500000, 3.5}, + { "k6_3", 350000000, 3.5}, + { "k6_3", 366666666, 5.5}, + { "k6_3", 380000000, 4.0}, + { "k6_3", 400000000, 4.0}, + { "k6_3", 450000000, 4.5}, + { "k6_3p", 75000000, 1.5}, + { "k6_3p", 100000000, 1.5}, + { "k6_3p", 133333333, 2.0}, + { "k6_3p", 166666666, 2.5}, + { "k6_3p", 200000000, 3.0}, + { "k6_3p", 233333333, 3.5}, + { "k6_3p", 266666666, 4.0}, + { "k6_3p", 300000000, 3.0}, + { "k6_3p", 332500000, 3.5}, + { "k6_3p", 350000000, 3.5}, + { "k6_3p", 366666666, 5.5}, + { "k6_3p", 380000000, 4.0}, + { "k6_3p", 400000000, 4.0}, + { "k6_3p", 450000000, 4.5}, + { "k6_3p", 475000000, 5.0}, + { "k6_3p", 500000000, 5.0}, + { NULL, 0, 0 } }; static const cpu_legacy_table_t cpus_PentiumPro[] = { - {"pentiumpro", 50000000, 1.0}, - {"pentiumpro", 60000000, 1.0}, - {"pentiumpro", 66666666, 1.0}, - {"pentiumpro", 75000000, 1.5}, - {"pentiumpro", 150000000, 2.5}, - {"pentiumpro", 166666666, 2.5}, - {"pentiumpro", 180000000, 3.0}, - {"pentiumpro", 200000000, 3.0}, - {"pentium2_od", 50000000, 1.0}, - {"pentium2_od", 60000000, 1.0}, - {"pentium2_od", 66666666, 1.0}, - {"pentium2_od", 75000000, 1.5}, - {"pentium2_od", 210000000, 3.5}, - {"pentium2_od", 233333333, 3.5}, - {"pentium2_od", 240000000, 4.0}, - {"pentium2_od", 266666666, 4.0}, - {"pentium2_od", 270000000, 4.5}, - {"pentium2_od", 300000000, 4.5}, - {"pentium2_od", 300000000, 5.0}, - {"pentium2_od", 333333333, 5.0}, - {NULL, 0, 0} + {"pentiumpro", 50000000, 1.0}, + { "pentiumpro", 60000000, 1.0}, + { "pentiumpro", 66666666, 1.0}, + { "pentiumpro", 75000000, 1.5}, + { "pentiumpro", 150000000, 2.5}, + { "pentiumpro", 166666666, 2.5}, + { "pentiumpro", 180000000, 3.0}, + { "pentiumpro", 200000000, 3.0}, + { "pentium2_od", 50000000, 1.0}, + { "pentium2_od", 60000000, 1.0}, + { "pentium2_od", 66666666, 1.0}, + { "pentium2_od", 75000000, 1.5}, + { "pentium2_od", 210000000, 3.5}, + { "pentium2_od", 233333333, 3.5}, + { "pentium2_od", 240000000, 4.0}, + { "pentium2_od", 266666666, 4.0}, + { "pentium2_od", 270000000, 4.5}, + { "pentium2_od", 300000000, 4.5}, + { "pentium2_od", 300000000, 5.0}, + { "pentium2_od", 333333333, 5.0}, + { NULL, 0, 0 } }; static const cpu_legacy_table_t cpus_PentiumII66[] = { - {"pentium2_klamath", 50000000, 1.0}, - {"pentium2_klamath", 60000000, 1.0}, - {"pentium2_klamath", 66666666, 1.0}, - {"pentium2_klamath", 75000000, 1.5}, - {"pentium2_klamath", 233333333, 3.5}, - {"pentium2_klamath", 266666666, 4.0}, - {"pentium2_klamath", 300000000, 4.5}, - {"pentium2_deschutes", 50000000, 1.0}, - {"pentium2_deschutes", 60000000, 1.0}, - {"pentium2_deschutes", 66666666, 1.0}, - {"pentium2_deschutes", 75000000, 1.5}, - {"pentium2_deschutes", 266666666, 4.0}, - {"pentium2_deschutes", 300000000, 4.5}, - {"pentium2_deschutes", 333333333, 5.0}, - {NULL, 0, 0} - + {"pentium2_klamath", 50000000, 1.0}, + { "pentium2_klamath", 60000000, 1.0}, + { "pentium2_klamath", 66666666, 1.0}, + { "pentium2_klamath", 75000000, 1.5}, + { "pentium2_klamath", 233333333, 3.5}, + { "pentium2_klamath", 266666666, 4.0}, + { "pentium2_klamath", 300000000, 4.5}, + { "pentium2_deschutes", 50000000, 1.0}, + { "pentium2_deschutes", 60000000, 1.0}, + { "pentium2_deschutes", 66666666, 1.0}, + { "pentium2_deschutes", 75000000, 1.5}, + { "pentium2_deschutes", 266666666, 4.0}, + { "pentium2_deschutes", 300000000, 4.5}, + { "pentium2_deschutes", 333333333, 5.0}, + { NULL, 0, 0 } }; static const cpu_legacy_table_t cpus_PentiumII[] = { - {"pentium2_klamath", 50000000, 1.0}, - {"pentium2_klamath", 60000000, 1.0}, - {"pentium2_klamath", 66666666, 1.0}, - {"pentium2_klamath", 75000000, 1.5}, - {"pentium2_klamath", 233333333, 3.5}, - {"pentium2_klamath", 266666666, 4.0}, - {"pentium2_klamath", 300000000, 4.5}, - {"pentium2_deschutes", 50000000, 1.0}, - {"pentium2_deschutes", 60000000, 1.0}, - {"pentium2_deschutes", 66666666, 1.0}, - {"pentium2_deschutes", 75000000, 1.5}, - {"pentium2_deschutes", 266666666, 4.0}, - {"pentium2_deschutes", 300000000, 4.5}, - {"pentium2_deschutes", 333333333, 5.0}, - {"pentium2_deschutes", 350000000, 3.5}, - {"pentium2_deschutes", 400000000, 4.0}, - {"pentium2_deschutes", 450000000, 4.5}, - {NULL, 0, 0} + {"pentium2_klamath", 50000000, 1.0}, + { "pentium2_klamath", 60000000, 1.0}, + { "pentium2_klamath", 66666666, 1.0}, + { "pentium2_klamath", 75000000, 1.5}, + { "pentium2_klamath", 233333333, 3.5}, + { "pentium2_klamath", 266666666, 4.0}, + { "pentium2_klamath", 300000000, 4.5}, + { "pentium2_deschutes", 50000000, 1.0}, + { "pentium2_deschutes", 60000000, 1.0}, + { "pentium2_deschutes", 66666666, 1.0}, + { "pentium2_deschutes", 75000000, 1.5}, + { "pentium2_deschutes", 266666666, 4.0}, + { "pentium2_deschutes", 300000000, 4.5}, + { "pentium2_deschutes", 333333333, 5.0}, + { "pentium2_deschutes", 350000000, 3.5}, + { "pentium2_deschutes", 400000000, 4.0}, + { "pentium2_deschutes", 450000000, 4.5}, + { NULL, 0, 0 } }; static const cpu_legacy_table_t cpus_Xeon[] = { - {"pentium2_xeon", 75000000, 1.5}, - {"pentium2_xeon", 100000000, 1.5}, - {"pentium2_xeon", 133333333, 2.0}, - {"pentium2_xeon", 166666666, 2.5}, - {"pentium2_xeon", 400000000, 4.0}, - {"pentium2_xeon", 450000000, 4.5}, - {NULL, 0, 0} + {"pentium2_xeon", 75000000, 1.5}, + { "pentium2_xeon", 100000000, 1.5}, + { "pentium2_xeon", 133333333, 2.0}, + { "pentium2_xeon", 166666666, 2.5}, + { "pentium2_xeon", 400000000, 4.0}, + { "pentium2_xeon", 450000000, 4.5}, + { NULL, 0, 0 } }; static const cpu_legacy_table_t cpus_Celeron[] = { - {"celeron_mendocino", 66666666, 1.0}, - {"celeron_mendocino", 100000000, 1.5}, - {"celeron_mendocino", 133333333, 2.0}, - {"celeron_mendocino", 166666666, 2.5}, - {"celeron_mendocino", 300000000, 4.5}, - {"celeron_mendocino", 333333333, 5.0}, - {"celeron_mendocino", 366666666, 5.5}, - {"celeron_mendocino", 400000000, 6.0}, - {"celeron_mendocino", 433333333, 6.5}, - {"celeron_mendocino", 466666666, 7.0}, - {"celeron_mendocino", 500000000, 7.5}, - {"celeron_mendocino", 533333333, 8.0}, - {NULL, 0, 0} + {"celeron_mendocino", 66666666, 1.0}, + { "celeron_mendocino", 100000000, 1.5}, + { "celeron_mendocino", 133333333, 2.0}, + { "celeron_mendocino", 166666666, 2.5}, + { "celeron_mendocino", 300000000, 4.5}, + { "celeron_mendocino", 333333333, 5.0}, + { "celeron_mendocino", 366666666, 5.5}, + { "celeron_mendocino", 400000000, 6.0}, + { "celeron_mendocino", 433333333, 6.5}, + { "celeron_mendocino", 466666666, 7.0}, + { "celeron_mendocino", 500000000, 7.5}, + { "celeron_mendocino", 533333333, 8.0}, + { NULL, 0, 0 } }; static const cpu_legacy_table_t cpus_PentiumIID[] = { - {"pentium2_deschutes", 50000000, 1.0}, - {"pentium2_deschutes", 60000000, 1.0}, - {"pentium2_deschutes", 66666666, 1.0}, - {"pentium2_deschutes", 75000000, 1.5}, - {"pentium2_deschutes", 266666666, 4.0}, - {"pentium2_deschutes", 300000000, 4.5}, - {"pentium2_deschutes", 333333333, 5.0}, - {"pentium2_deschutes", 350000000, 3.5}, - {"pentium2_deschutes", 400000000, 4.0}, - {"pentium2_deschutes", 450000000, 4.5}, - {NULL, 0, 0} + {"pentium2_deschutes", 50000000, 1.0}, + { "pentium2_deschutes", 60000000, 1.0}, + { "pentium2_deschutes", 66666666, 1.0}, + { "pentium2_deschutes", 75000000, 1.5}, + { "pentium2_deschutes", 266666666, 4.0}, + { "pentium2_deschutes", 300000000, 4.5}, + { "pentium2_deschutes", 333333333, 5.0}, + { "pentium2_deschutes", 350000000, 3.5}, + { "pentium2_deschutes", 400000000, 4.0}, + { "pentium2_deschutes", 450000000, 4.5}, + { NULL, 0, 0 } }; static const cpu_legacy_table_t cpus_Cyrix3[] = { - {"c3_samuel", 66666666, 1.0}, - {"c3_samuel", 233333333, 3.5}, - {"c3_samuel", 266666666, 4.0}, - {"c3_samuel", 300000000, 4.5}, - {"c3_samuel", 333333333, 5.0}, - {"c3_samuel", 350000000, 3.5}, - {"c3_samuel", 400000000, 4.0}, - {"c3_samuel", 450000000, 4.5}, - {"c3_samuel", 500000000, 5.0}, - {"c3_samuel", 550000000, 5.5}, - {"c3_samuel", 600000000, 6.0}, - {"c3_samuel", 650000000, 6.5}, - {"c3_samuel", 700000000, 7.0}, - {NULL, 0, 0} + {"c3_samuel", 66666666, 1.0}, + { "c3_samuel", 233333333, 3.5}, + { "c3_samuel", 266666666, 4.0}, + { "c3_samuel", 300000000, 4.5}, + { "c3_samuel", 333333333, 5.0}, + { "c3_samuel", 350000000, 3.5}, + { "c3_samuel", 400000000, 4.0}, + { "c3_samuel", 450000000, 4.5}, + { "c3_samuel", 500000000, 5.0}, + { "c3_samuel", 550000000, 5.5}, + { "c3_samuel", 600000000, 6.0}, + { "c3_samuel", 650000000, 6.5}, + { "c3_samuel", 700000000, 7.0}, + { NULL, 0, 0 } }; -static const cpu_legacy_table_t *cputables_8088[4] = {cpus_8088}; -static const cpu_legacy_table_t *cputables_pcjr[4] = {cpus_pcjr}; -static const cpu_legacy_table_t *cputables_europc[4] = {cpus_europc}; -static const cpu_legacy_table_t *cputables_pc1512[4] = {cpus_pc1512}; -static const cpu_legacy_table_t *cputables_8086[4] = {cpus_8086}; -static const cpu_legacy_table_t *cputables_286[4] = {cpus_286}; -static const cpu_legacy_table_t *cputables_ibmat[4] = {cpus_ibmat}; -static const cpu_legacy_table_t *cputables_ps1_m2011[4] = {cpus_ps1_m2011}; -static const cpu_legacy_table_t *cputables_ps2_m30_286_IBM486SLC[4] = {cpus_ps2_m30_286, cpus_IBM486SLC}; -static const cpu_legacy_table_t *cputables_ibmxt286[4] = {cpus_ibmxt286}; -static const cpu_legacy_table_t *cputables_i386SX_Am386SX_486SLC[4] = {cpus_i386SX, cpus_Am386SX, cpus_486SLC}; -static const cpu_legacy_table_t *cputables_ALiM6117[4] = {cpus_ALiM6117}; -static const cpu_legacy_table_t *cputables_i386SX_Am386SX_486SLC_IBM486SLC[4] = {cpus_i386SX, cpus_Am386SX, cpus_486SLC, cpus_IBM486SLC}; -static const cpu_legacy_table_t *cputables_i386DX_Am386DX_486DLC[4] = {cpus_i386DX, cpus_Am386DX, cpus_486DLC}; -static const cpu_legacy_table_t *cputables_i386DX_Am386DX_486DLC_IBM486BL[4] = {cpus_i386DX, cpus_Am386DX, cpus_486DLC, cpus_IBM486BL}; -static const cpu_legacy_table_t *cputables_i486_Am486_Cx486[4] = {cpus_i486, cpus_Am486, cpus_Cx486}; -static const cpu_legacy_table_t *cputables_i486S1_Am486S1_Cx486S1[4] = {cpus_i486S1, cpus_Am486S1, cpus_Cx486S1}; -static const cpu_legacy_table_t *cputables_IBM486SLC[4] = {cpus_IBM486SLC}; -static const cpu_legacy_table_t *cputables_i486_PC330[4] = {cpus_i486_PC330}; -static const cpu_legacy_table_t *cputables_STPCDX[4] = {cpus_STPCDX}; -static const cpu_legacy_table_t *cputables_STPCDX2[4] = {cpus_STPCDX2}; -static const cpu_legacy_table_t *cputables_Pentium5V[4] = {cpus_Pentium5V}; -static const cpu_legacy_table_t *cputables_PentiumS5_WinChip_K5[4] = {cpus_PentiumS5, cpus_WinChip, cpus_K5}; -static const cpu_legacy_table_t *cputables_Pentium3V_WinChip_K5_6x863V[4] = {cpus_Pentium3V, cpus_WinChip, cpus_K5, cpus_6x863V}; -static const cpu_legacy_table_t *cputables_Pentium3V_K5[4] = {cpus_Pentium3V, cpus_K5}; -static const cpu_legacy_table_t *cputables_Pentium_WinChip_K56_6x86[4] = {cpus_Pentium, cpus_WinChip, cpus_K56, cpus_6x86}; -static const cpu_legacy_table_t *cputables_Pentium_WinChip_SS7_K56_SS7_6x86SS7[4] = {cpus_Pentium, cpus_WinChip_SS7, cpus_K56_SS7, cpus_6x86SS7}; -static const cpu_legacy_table_t *cputables_PentiumPro[4] = {cpus_PentiumPro}; -static const cpu_legacy_table_t *cputables_PentiumII66[4] = {cpus_PentiumII66}; -static const cpu_legacy_table_t *cputables_PentiumII_Celeron_Cyrix3[4] = {cpus_PentiumII, cpus_Celeron, cpus_Cyrix3}; -static const cpu_legacy_table_t *cputables_Xeon[4] = {cpus_Xeon}; -static const cpu_legacy_table_t *cputables_Celeron_Cyrix3[4] = {cpus_Celeron, cpus_Cyrix3}; -static const cpu_legacy_table_t *cputables_Celeron[4] = {cpus_Celeron}; -static const cpu_legacy_table_t *cputables_PentiumIID_Celeron[4] = {cpus_PentiumIID, cpus_Celeron}; +static const cpu_legacy_table_t *cputables_8088[4] = { cpus_8088 }; +static const cpu_legacy_table_t *cputables_pcjr[4] = { cpus_pcjr }; +static const cpu_legacy_table_t *cputables_europc[4] = { cpus_europc }; +static const cpu_legacy_table_t *cputables_pc1512[4] = { cpus_pc1512 }; +static const cpu_legacy_table_t *cputables_8086[4] = { cpus_8086 }; +static const cpu_legacy_table_t *cputables_286[4] = { cpus_286 }; +static const cpu_legacy_table_t *cputables_ibmat[4] = { cpus_ibmat }; +static const cpu_legacy_table_t *cputables_ps1_m2011[4] = { cpus_ps1_m2011 }; +static const cpu_legacy_table_t *cputables_ps2_m30_286_IBM486SLC[4] = { cpus_ps2_m30_286, cpus_IBM486SLC }; +static const cpu_legacy_table_t *cputables_ibmxt286[4] = { cpus_ibmxt286 }; +static const cpu_legacy_table_t *cputables_i386SX_Am386SX_486SLC[4] = { cpus_i386SX, cpus_Am386SX, cpus_486SLC }; +static const cpu_legacy_table_t *cputables_ALiM6117[4] = { cpus_ALiM6117 }; +static const cpu_legacy_table_t *cputables_i386SX_Am386SX_486SLC_IBM486SLC[4] = { cpus_i386SX, cpus_Am386SX, cpus_486SLC, cpus_IBM486SLC }; +static const cpu_legacy_table_t *cputables_i386DX_Am386DX_486DLC[4] = { cpus_i386DX, cpus_Am386DX, cpus_486DLC }; +static const cpu_legacy_table_t *cputables_i386DX_Am386DX_486DLC_IBM486BL[4] = { cpus_i386DX, cpus_Am386DX, cpus_486DLC, cpus_IBM486BL }; +static const cpu_legacy_table_t *cputables_i486_Am486_Cx486[4] = { cpus_i486, cpus_Am486, cpus_Cx486 }; +static const cpu_legacy_table_t *cputables_i486S1_Am486S1_Cx486S1[4] = { cpus_i486S1, cpus_Am486S1, cpus_Cx486S1 }; +static const cpu_legacy_table_t *cputables_IBM486SLC[4] = { cpus_IBM486SLC }; +static const cpu_legacy_table_t *cputables_i486_PC330[4] = { cpus_i486_PC330 }; +static const cpu_legacy_table_t *cputables_STPCDX[4] = { cpus_STPCDX }; +static const cpu_legacy_table_t *cputables_STPCDX2[4] = { cpus_STPCDX2 }; +static const cpu_legacy_table_t *cputables_Pentium5V[4] = { cpus_Pentium5V }; +static const cpu_legacy_table_t *cputables_PentiumS5_WinChip_K5[4] = { cpus_PentiumS5, cpus_WinChip, cpus_K5 }; +static const cpu_legacy_table_t *cputables_Pentium3V_WinChip_K5_6x863V[4] = { cpus_Pentium3V, cpus_WinChip, cpus_K5, cpus_6x863V }; +static const cpu_legacy_table_t *cputables_Pentium3V_K5[4] = { cpus_Pentium3V, cpus_K5 }; +static const cpu_legacy_table_t *cputables_Pentium_WinChip_K56_6x86[4] = { cpus_Pentium, cpus_WinChip, cpus_K56, cpus_6x86 }; +static const cpu_legacy_table_t *cputables_Pentium_WinChip_SS7_K56_SS7_6x86SS7[4] = { cpus_Pentium, cpus_WinChip_SS7, cpus_K56_SS7, cpus_6x86SS7 }; +static const cpu_legacy_table_t *cputables_PentiumPro[4] = { cpus_PentiumPro }; +static const cpu_legacy_table_t *cputables_PentiumII66[4] = { cpus_PentiumII66 }; +static const cpu_legacy_table_t *cputables_PentiumII_Celeron_Cyrix3[4] = { cpus_PentiumII, cpus_Celeron, cpus_Cyrix3 }; +static const cpu_legacy_table_t *cputables_Xeon[4] = { cpus_Xeon }; +static const cpu_legacy_table_t *cputables_Celeron_Cyrix3[4] = { cpus_Celeron, cpus_Cyrix3 }; +static const cpu_legacy_table_t *cputables_Celeron[4] = { cpus_Celeron }; +static const cpu_legacy_table_t *cputables_PentiumIID_Celeron[4] = { cpus_PentiumIID, cpus_Celeron }; const cpu_legacy_machine_t cpu_legacy_table[] = { - {"ibmpc", cputables_8088}, - {"ibmpc82", cputables_8088}, - {"ibmpcjr", cputables_pcjr}, - {"ibmxt", cputables_8088}, - {"ibmxt86", cputables_8088}, - {"americxt", cputables_8088}, - {"amixt", cputables_8088}, - {"portable", cputables_8088}, - {"dtk", cputables_8088}, - {"genxt", cputables_8088}, - {"jukopc", cputables_8088}, - {"openxt", cputables_8088}, - {"pxxt", cputables_8088}, - {"europc", cputables_europc}, - {"tandy", cputables_europc}, - {"tandy1000hx", cputables_europc}, - {"t1000", cputables_8088}, - {"ltxt", cputables_8088}, - {"xi8088", cputables_8088}, - {"zdsupers", cputables_8088}, - {"pc1512", cputables_pc1512}, - {"pc1640", cputables_8086}, - {"pc2086", cputables_8086}, - {"pc3086", cputables_8086}, - {"pc200", cputables_8086}, - {"ppc512", cputables_8086}, - {"deskpro", cputables_8086}, - {"m24", cputables_8086}, - {"iskra3104", cputables_8086}, - {"tandy1000sl2", cputables_8086}, - {"t1200", cputables_8086}, - {"lxt3", cputables_8086}, - {"hed919", cputables_286}, - {"ibmat", cputables_ibmat}, - {"ibmps1es", cputables_ps1_m2011}, - {"ibmps2_m30_286", cputables_ps2_m30_286_IBM486SLC}, - {"ibmxt286", cputables_ibmxt286}, - {"ibmatami", cputables_ibmat}, - {"cmdpc30", cputables_286}, - {"portableii", cputables_286}, - {"portableiii", cputables_286}, - {"mr286", cputables_286}, - {"open_at", cputables_286}, - {"ibmatpx", cputables_ibmat}, - {"ibmatquadtel", cputables_ibmat}, - {"siemens", cputables_286}, - {"t3100e", cputables_286}, - {"quadt286", cputables_286}, - {"tg286m", cputables_286}, - {"ami286", cputables_286}, - {"px286", cputables_286}, - {"award286", cputables_286}, - {"gw286ct", cputables_286}, - {"gdc212m", cputables_286}, - {"super286tr", cputables_286}, - {"spc4200p", cputables_286}, - {"spc4216p", cputables_286}, - {"deskmaster286", cputables_286}, - {"ibmps2_m50", cputables_ps2_m30_286_IBM486SLC}, - {"ibmps1_2121", cputables_i386SX_Am386SX_486SLC}, - {"ibmps1_2121_isa", cputables_i386SX_Am386SX_486SLC}, - {"arb1375", cputables_ALiM6117}, - {"pja511m", cputables_ALiM6117}, - {"ama932j", cputables_i386SX_Am386SX_486SLC}, - {"adi386sx", cputables_i386SX_Am386SX_486SLC}, - {"shuttle386sx", cputables_i386SX_Am386SX_486SLC}, - {"dtk386", cputables_i386SX_Am386SX_486SLC}, - {"awardsx", cputables_i386SX_Am386SX_486SLC}, - {"cmdsl386sx25", cputables_i386SX_Am386SX_486SLC}, - {"kmxc02", cputables_i386SX_Am386SX_486SLC}, - {"megapc", cputables_i386SX_Am386SX_486SLC}, - {"ibmps2_m55sx", cputables_i386SX_Am386SX_486SLC_IBM486SLC}, - {"acc386", cputables_i386DX_Am386DX_486DLC}, - {"ecs386", cputables_i386DX_Am386DX_486DLC}, - {"portableiii386", cputables_i386DX_Am386DX_486DLC}, - {"micronics386", cputables_i386DX_Am386DX_486DLC}, - {"asus386", cputables_i386DX_Am386DX_486DLC}, - {"ustechnologies386", cputables_i386DX_Am386DX_486DLC}, - {"award386dx", cputables_i386DX_Am386DX_486DLC}, - {"ibmps2_m70_type3", cputables_i386DX_Am386DX_486DLC_IBM486BL}, - {"ibmps2_m80", cputables_i386DX_Am386DX_486DLC_IBM486BL}, - {"pb410a", cputables_i486_Am486_Cx486}, - {"acera1g", cputables_i486_Am486_Cx486}, - {"win486", cputables_i486_Am486_Cx486}, - {"ali1429", cputables_i486S1_Am486S1_Cx486S1}, - {"cs4031", cputables_i486S1_Am486S1_Cx486S1}, - {"rycleopardlx", cputables_IBM486SLC}, - {"award486", cputables_i486S1_Am486S1_Cx486S1}, - {"ami486", cputables_i486S1_Am486S1_Cx486S1}, - {"mr486", cputables_i486_Am486_Cx486}, - {"pc330_6571", cputables_i486_PC330}, - {"403tg", cputables_i486_Am486_Cx486}, - {"sis401", cputables_i486_Am486_Cx486}, - {"valuepoint433", cputables_i486_Am486_Cx486}, - {"ami471", cputables_i486_Am486_Cx486}, - {"win471", cputables_i486_Am486_Cx486}, - {"vi15g", cputables_i486_Am486_Cx486}, - {"vli486sv2g", cputables_i486_Am486_Cx486}, - {"dtk486", cputables_i486_Am486_Cx486}, - {"px471", cputables_i486_Am486_Cx486}, - {"486vchd", cputables_i486S1_Am486S1_Cx486S1}, - {"ibmps1_2133", cputables_i486S1_Am486S1_Cx486S1}, - {"vect486vl", cputables_i486S1_Am486S1_Cx486S1}, - {"ibmps2_m70_type4", cputables_i486S1_Am486S1_Cx486S1}, - {"abpb4", cputables_i486_Am486_Cx486}, - {"486ap4", cputables_i486_Am486_Cx486}, - {"486sp3g", cputables_i486_Am486_Cx486}, - {"alfredo", cputables_i486_Am486_Cx486}, - {"ls486e", cputables_i486_Am486_Cx486}, - {"m4li", cputables_i486_Am486_Cx486}, - {"r418", cputables_i486_Am486_Cx486}, - {"4sa2", cputables_i486_Am486_Cx486}, - {"4dps", cputables_i486_Am486_Cx486}, - {"itoxstar", cputables_STPCDX}, - {"arb1479", cputables_STPCDX2}, - {"pcm9340", cputables_STPCDX2}, - {"pcm5330", cputables_STPCDX2}, - {"486vipio2", cputables_i486_Am486_Cx486}, - {"p5mp3", cputables_Pentium5V}, - {"dellxp60", cputables_Pentium5V}, - {"opti560l", cputables_Pentium5V}, - {"ambradp60", cputables_Pentium5V}, - {"valuepointp60", cputables_Pentium5V}, - {"revenge", cputables_Pentium5V}, - {"586mc1", cputables_Pentium5V}, - {"pb520r", cputables_Pentium5V}, - {"excalibur", cputables_Pentium5V}, - {"plato", cputables_PentiumS5_WinChip_K5}, - {"ambradp90", cputables_PentiumS5_WinChip_K5}, - {"430nx", cputables_PentiumS5_WinChip_K5}, - {"acerv30", cputables_PentiumS5_WinChip_K5}, - {"apollo", cputables_PentiumS5_WinChip_K5}, - {"vectra54", cputables_PentiumS5_WinChip_K5}, - {"zappa", cputables_PentiumS5_WinChip_K5}, - {"powermate_v", cputables_PentiumS5_WinChip_K5}, - {"mb500n", cputables_PentiumS5_WinChip_K5}, - {"p54tp4xe", cputables_Pentium3V_WinChip_K5_6x863V}, - {"mr586", cputables_Pentium3V_WinChip_K5_6x863V}, - {"gw2katx", cputables_Pentium3V_WinChip_K5_6x863V}, - {"thor", cputables_Pentium3V_WinChip_K5_6x863V}, - {"mrthor", cputables_Pentium3V_WinChip_K5_6x863V}, - {"endeavor", cputables_Pentium3V_WinChip_K5_6x863V}, - {"pb640", cputables_Pentium3V_WinChip_K5_6x863V}, - {"chariot", cputables_Pentium3V_K5}, - {"acerm3a", cputables_Pentium3V_WinChip_K5_6x863V}, - {"ap53", cputables_Pentium3V_WinChip_K5_6x863V}, - {"8500tuc", cputables_Pentium3V_WinChip_K5_6x863V}, - {"p55t2s", cputables_Pentium3V_WinChip_K5_6x863V}, - {"acerv35n", cputables_Pentium_WinChip_K56_6x86}, - {"p55t2p4", cputables_Pentium_WinChip_K56_6x86}, - {"m7shi", cputables_Pentium_WinChip_K56_6x86}, - {"tc430hx", cputables_Pentium_WinChip_K56_6x86}, - {"equium5200", cputables_Pentium_WinChip_K56_6x86}, - {"pcv240", cputables_Pentium_WinChip_K56_6x86}, - {"p65up5_cp55t2d", cputables_Pentium_WinChip_K56_6x86}, - {"p55tvp4", cputables_Pentium_WinChip_K56_6x86}, - {"8500tvxa", cputables_Pentium_WinChip_K56_6x86}, - {"presario4500", cputables_Pentium_WinChip_K56_6x86}, - {"p55va", cputables_Pentium_WinChip_K56_6x86}, - {"gw2kte", cputables_Pentium_WinChip_K56_6x86}, - {"brio80xx", cputables_Pentium_WinChip_K56_6x86}, - {"pb680", cputables_Pentium_WinChip_K56_6x86}, - {"430vx", cputables_Pentium_WinChip_K56_6x86}, - {"nupro592", cputables_Pentium_WinChip_K56_6x86}, - {"tx97", cputables_Pentium_WinChip_K56_6x86}, - {"an430tx", cputables_Pentium_WinChip_K56_6x86}, - {"ym430tx", cputables_Pentium_WinChip_K56_6x86}, - {"mb540n", cputables_Pentium_WinChip_K56_6x86}, - {"p5mms98", cputables_Pentium_WinChip_K56_6x86}, - {"ficva502", cputables_Pentium_WinChip_K56_6x86}, - {"ficpa2012", cputables_Pentium_WinChip_K56_6x86}, - {"ax59pro", cputables_Pentium_WinChip_SS7_K56_SS7_6x86SS7}, - {"ficva503p", cputables_Pentium_WinChip_SS7_K56_SS7_6x86SS7}, - {"ficva503a", cputables_Pentium_WinChip_SS7_K56_SS7_6x86SS7}, - {"v60n", cputables_PentiumPro}, - {"p65up5_cp6nd", cputables_PentiumPro}, - {"8600ttc", cputables_PentiumPro}, - {"686nx", cputables_PentiumPro}, - {"ap440fx", cputables_PentiumPro}, - {"vs440fx", cputables_PentiumPro}, - {"m6mi", cputables_PentiumPro}, - {"mb600n", cputables_PentiumPro}, - {"p65up5_cpknd", cputables_PentiumII66}, - {"kn97", cputables_PentiumII66}, - {"lx6", cputables_PentiumII66}, - {"spitfire", cputables_PentiumII66}, - {"p6i440e2", cputables_PentiumII66}, - {"p2bls", cputables_PentiumII_Celeron_Cyrix3}, - {"p3bf", cputables_PentiumII_Celeron_Cyrix3}, - {"bf6", cputables_PentiumII_Celeron_Cyrix3}, - {"ax6bc", cputables_PentiumII_Celeron_Cyrix3}, - {"atc6310bxii", cputables_PentiumII_Celeron_Cyrix3}, - {"686bx", cputables_PentiumII_Celeron_Cyrix3}, - {"tsunamiatx", cputables_PentiumII_Celeron_Cyrix3}, - {"p6sba", cputables_PentiumII_Celeron_Cyrix3}, - {"ergox365", cputables_PentiumII_Celeron_Cyrix3}, - {"ficka6130", cputables_PentiumII_Celeron_Cyrix3}, - {"6gxu", cputables_Xeon}, - {"fw6400gx", cputables_Xeon}, - {"s2dge", cputables_Xeon}, - {"s370slm", cputables_Celeron_Cyrix3}, - {"awo671r", cputables_Celeron_Cyrix3}, - {"cubx", cputables_Celeron_Cyrix3}, - {"atc7020bxii", cputables_Celeron_Cyrix3}, - {"ambx133", cputables_Celeron_Cyrix3}, - {"trinity371", cputables_Celeron}, - {"63a", cputables_Celeron_Cyrix3}, - {"apas3", cputables_Celeron_Cyrix3}, - {"wcf681", cputables_Celeron_Cyrix3}, - {"6via90ap", cputables_Celeron_Cyrix3}, - {"p6bap", cputables_Celeron_Cyrix3}, - {"603tcf", cputables_Celeron_Cyrix3}, - {"vpc2007", cputables_PentiumIID_Celeron}, - {NULL, NULL} + {"ibmpc", cputables_8088 }, + { "ibmpc82", cputables_8088 }, + { "ibmpcjr", cputables_pcjr }, + { "ibmxt", cputables_8088 }, + { "ibmxt86", cputables_8088 }, + { "americxt", cputables_8088 }, + { "amixt", cputables_8088 }, + { "portable", cputables_8088 }, + { "dtk", cputables_8088 }, + { "genxt", cputables_8088 }, + { "jukopc", cputables_8088 }, + { "openxt", cputables_8088 }, + { "pxxt", cputables_8088 }, + { "europc", cputables_europc }, + { "tandy", cputables_europc }, + { "tandy1000hx", cputables_europc }, + { "t1000", cputables_8088 }, + { "ltxt", cputables_8088 }, + { "xi8088", cputables_8088 }, + { "zdsupers", cputables_8088 }, + { "pc1512", cputables_pc1512 }, + { "pc1640", cputables_8086 }, + { "pc2086", cputables_8086 }, + { "pc3086", cputables_8086 }, + { "pc200", cputables_8086 }, + { "ppc512", cputables_8086 }, + { "deskpro", cputables_8086 }, + { "m24", cputables_8086 }, + { "iskra3104", cputables_8086 }, + { "tandy1000sl2", cputables_8086 }, + { "t1200", cputables_8086 }, + { "lxt3", cputables_8086 }, + { "hed919", cputables_286 }, + { "ibmat", cputables_ibmat }, + { "ibmps1es", cputables_ps1_m2011 }, + { "ibmps2_m30_286", cputables_ps2_m30_286_IBM486SLC }, + { "ibmxt286", cputables_ibmxt286 }, + { "ibmatami", cputables_ibmat }, + { "cmdpc30", cputables_286 }, + { "portableii", cputables_286 }, + { "portableiii", cputables_286 }, + { "mr286", cputables_286 }, + { "open_at", cputables_286 }, + { "ibmatpx", cputables_ibmat }, + { "ibmatquadtel", cputables_ibmat }, + { "siemens", cputables_286 }, + { "t3100e", cputables_286 }, + { "quadt286", cputables_286 }, + { "tg286m", cputables_286 }, + { "ami286", cputables_286 }, + { "px286", cputables_286 }, + { "award286", cputables_286 }, + { "gw286ct", cputables_286 }, + { "gdc212m", cputables_286 }, + { "super286tr", cputables_286 }, + { "spc4200p", cputables_286 }, + { "spc4216p", cputables_286 }, + { "deskmaster286", cputables_286 }, + { "ibmps2_m50", cputables_ps2_m30_286_IBM486SLC }, + { "ibmps1_2121", cputables_i386SX_Am386SX_486SLC }, + { "ibmps1_2121_isa", cputables_i386SX_Am386SX_486SLC }, + { "arb1375", cputables_ALiM6117 }, + { "pja511m", cputables_ALiM6117 }, + { "ama932j", cputables_i386SX_Am386SX_486SLC }, + { "adi386sx", cputables_i386SX_Am386SX_486SLC }, + { "shuttle386sx", cputables_i386SX_Am386SX_486SLC }, + { "dtk386", cputables_i386SX_Am386SX_486SLC }, + { "awardsx", cputables_i386SX_Am386SX_486SLC }, + { "cmdsl386sx25", cputables_i386SX_Am386SX_486SLC }, + { "kmxc02", cputables_i386SX_Am386SX_486SLC }, + { "megapc", cputables_i386SX_Am386SX_486SLC }, + { "ibmps2_m55sx", cputables_i386SX_Am386SX_486SLC_IBM486SLC }, + { "acc386", cputables_i386DX_Am386DX_486DLC }, + { "ecs386", cputables_i386DX_Am386DX_486DLC }, + { "portableiii386", cputables_i386DX_Am386DX_486DLC }, + { "micronics386", cputables_i386DX_Am386DX_486DLC }, + { "asus386", cputables_i386DX_Am386DX_486DLC }, + { "ustechnologies386", cputables_i386DX_Am386DX_486DLC }, + { "award386dx", cputables_i386DX_Am386DX_486DLC }, + { "ibmps2_m70_type3", cputables_i386DX_Am386DX_486DLC_IBM486BL }, + { "ibmps2_m80", cputables_i386DX_Am386DX_486DLC_IBM486BL }, + { "pb410a", cputables_i486_Am486_Cx486 }, + { "acera1g", cputables_i486_Am486_Cx486 }, + { "win486", cputables_i486_Am486_Cx486 }, + { "ali1429", cputables_i486S1_Am486S1_Cx486S1 }, + { "cs4031", cputables_i486S1_Am486S1_Cx486S1 }, + { "rycleopardlx", cputables_IBM486SLC }, + { "award486", cputables_i486S1_Am486S1_Cx486S1 }, + { "ami486", cputables_i486S1_Am486S1_Cx486S1 }, + { "mr486", cputables_i486_Am486_Cx486 }, + { "pc330_6571", cputables_i486_PC330 }, + { "403tg", cputables_i486_Am486_Cx486 }, + { "sis401", cputables_i486_Am486_Cx486 }, + { "valuepoint433", cputables_i486_Am486_Cx486 }, + { "ami471", cputables_i486_Am486_Cx486 }, + { "win471", cputables_i486_Am486_Cx486 }, + { "vi15g", cputables_i486_Am486_Cx486 }, + { "vli486sv2g", cputables_i486_Am486_Cx486 }, + { "dtk486", cputables_i486_Am486_Cx486 }, + { "px471", cputables_i486_Am486_Cx486 }, + { "486vchd", cputables_i486S1_Am486S1_Cx486S1 }, + { "ibmps1_2133", cputables_i486S1_Am486S1_Cx486S1 }, + { "vect486vl", cputables_i486S1_Am486S1_Cx486S1 }, + { "ibmps2_m70_type4", cputables_i486S1_Am486S1_Cx486S1 }, + { "abpb4", cputables_i486_Am486_Cx486 }, + { "486ap4", cputables_i486_Am486_Cx486 }, + { "486sp3g", cputables_i486_Am486_Cx486 }, + { "alfredo", cputables_i486_Am486_Cx486 }, + { "ls486e", cputables_i486_Am486_Cx486 }, + { "m4li", cputables_i486_Am486_Cx486 }, + { "r418", cputables_i486_Am486_Cx486 }, + { "4sa2", cputables_i486_Am486_Cx486 }, + { "4dps", cputables_i486_Am486_Cx486 }, + { "itoxstar", cputables_STPCDX }, + { "arb1479", cputables_STPCDX2 }, + { "pcm9340", cputables_STPCDX2 }, + { "pcm5330", cputables_STPCDX2 }, + { "486vipio2", cputables_i486_Am486_Cx486 }, + { "p5mp3", cputables_Pentium5V }, + { "dellxp60", cputables_Pentium5V }, + { "opti560l", cputables_Pentium5V }, + { "ambradp60", cputables_Pentium5V }, + { "valuepointp60", cputables_Pentium5V }, + { "revenge", cputables_Pentium5V }, + { "586mc1", cputables_Pentium5V }, + { "pb520r", cputables_Pentium5V }, + { "excalibur", cputables_Pentium5V }, + { "plato", cputables_PentiumS5_WinChip_K5 }, + { "ambradp90", cputables_PentiumS5_WinChip_K5 }, + { "430nx", cputables_PentiumS5_WinChip_K5 }, + { "acerv30", cputables_PentiumS5_WinChip_K5 }, + { "apollo", cputables_PentiumS5_WinChip_K5 }, + { "vectra54", cputables_PentiumS5_WinChip_K5 }, + { "zappa", cputables_PentiumS5_WinChip_K5 }, + { "powermate_v", cputables_PentiumS5_WinChip_K5 }, + { "mb500n", cputables_PentiumS5_WinChip_K5 }, + { "p54tp4xe", cputables_Pentium3V_WinChip_K5_6x863V }, + { "mr586", cputables_Pentium3V_WinChip_K5_6x863V }, + { "gw2katx", cputables_Pentium3V_WinChip_K5_6x863V }, + { "thor", cputables_Pentium3V_WinChip_K5_6x863V }, + { "mrthor", cputables_Pentium3V_WinChip_K5_6x863V }, + { "endeavor", cputables_Pentium3V_WinChip_K5_6x863V }, + { "pb640", cputables_Pentium3V_WinChip_K5_6x863V }, + { "chariot", cputables_Pentium3V_K5 }, + { "acerm3a", cputables_Pentium3V_WinChip_K5_6x863V }, + { "ap53", cputables_Pentium3V_WinChip_K5_6x863V }, + { "8500tuc", cputables_Pentium3V_WinChip_K5_6x863V }, + { "p55t2s", cputables_Pentium3V_WinChip_K5_6x863V }, + { "acerv35n", cputables_Pentium_WinChip_K56_6x86 }, + { "p55t2p4", cputables_Pentium_WinChip_K56_6x86 }, + { "m7shi", cputables_Pentium_WinChip_K56_6x86 }, + { "tc430hx", cputables_Pentium_WinChip_K56_6x86 }, + { "equium5200", cputables_Pentium_WinChip_K56_6x86 }, + { "pcv240", cputables_Pentium_WinChip_K56_6x86 }, + { "p65up5_cp55t2d", cputables_Pentium_WinChip_K56_6x86 }, + { "p55tvp4", cputables_Pentium_WinChip_K56_6x86 }, + { "8500tvxa", cputables_Pentium_WinChip_K56_6x86 }, + { "presario4500", cputables_Pentium_WinChip_K56_6x86 }, + { "p55va", cputables_Pentium_WinChip_K56_6x86 }, + { "gw2kte", cputables_Pentium_WinChip_K56_6x86 }, + { "brio80xx", cputables_Pentium_WinChip_K56_6x86 }, + { "pb680", cputables_Pentium_WinChip_K56_6x86 }, + { "430vx", cputables_Pentium_WinChip_K56_6x86 }, + { "nupro592", cputables_Pentium_WinChip_K56_6x86 }, + { "tx97", cputables_Pentium_WinChip_K56_6x86 }, + { "an430tx", cputables_Pentium_WinChip_K56_6x86 }, + { "ym430tx", cputables_Pentium_WinChip_K56_6x86 }, + { "mb540n", cputables_Pentium_WinChip_K56_6x86 }, + { "p5mms98", cputables_Pentium_WinChip_K56_6x86 }, + { "ficva502", cputables_Pentium_WinChip_K56_6x86 }, + { "ficpa2012", cputables_Pentium_WinChip_K56_6x86 }, + { "ax59pro", cputables_Pentium_WinChip_SS7_K56_SS7_6x86SS7}, + { "ficva503p", cputables_Pentium_WinChip_SS7_K56_SS7_6x86SS7}, + { "ficva503a", cputables_Pentium_WinChip_SS7_K56_SS7_6x86SS7}, + { "v60n", cputables_PentiumPro }, + { "p65up5_cp6nd", cputables_PentiumPro }, + { "8600ttc", cputables_PentiumPro }, + { "686nx", cputables_PentiumPro }, + { "ap440fx", cputables_PentiumPro }, + { "vs440fx", cputables_PentiumPro }, + { "m6mi", cputables_PentiumPro }, + { "mb600n", cputables_PentiumPro }, + { "p65up5_cpknd", cputables_PentiumII66 }, + { "kn97", cputables_PentiumII66 }, + { "lx6", cputables_PentiumII66 }, + { "spitfire", cputables_PentiumII66 }, + { "p6i440e2", cputables_PentiumII66 }, + { "p2bls", cputables_PentiumII_Celeron_Cyrix3 }, + { "p3bf", cputables_PentiumII_Celeron_Cyrix3 }, + { "bf6", cputables_PentiumII_Celeron_Cyrix3 }, + { "ax6bc", cputables_PentiumII_Celeron_Cyrix3 }, + { "atc6310bxii", cputables_PentiumII_Celeron_Cyrix3 }, + { "686bx", cputables_PentiumII_Celeron_Cyrix3 }, + { "tsunamiatx", cputables_PentiumII_Celeron_Cyrix3 }, + { "p6sba", cputables_PentiumII_Celeron_Cyrix3 }, + { "ergox365", cputables_PentiumII_Celeron_Cyrix3 }, + { "ficka6130", cputables_PentiumII_Celeron_Cyrix3 }, + { "6gxu", cputables_Xeon }, + { "fw6400gx", cputables_Xeon }, + { "s2dge", cputables_Xeon }, + { "s370slm", cputables_Celeron_Cyrix3 }, + { "awo671r", cputables_Celeron_Cyrix3 }, + { "cubx", cputables_Celeron_Cyrix3 }, + { "atc7020bxii", cputables_Celeron_Cyrix3 }, + { "ambx133", cputables_Celeron_Cyrix3 }, + { "trinity371", cputables_Celeron }, + { "63a", cputables_Celeron_Cyrix3 }, + { "apas3", cputables_Celeron_Cyrix3 }, + { "wcf681", cputables_Celeron_Cyrix3 }, + { "6via90ap", cputables_Celeron_Cyrix3 }, + { "p6bap", cputables_Celeron_Cyrix3 }, + { "603tcf", cputables_Celeron_Cyrix3 }, + { "vpc2007", cputables_PentiumIID_Celeron }, + { NULL, NULL } }; diff --git a/src/cpu/fpu.c b/src/cpu/fpu.c index 2d74b256a..0af010760 100644 --- a/src/cpu/fpu.c +++ b/src/cpu/fpu.c @@ -1,18 +1,18 @@ /* - * 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. + * 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. + * This file is part of the 86Box distribution. * - * FPU type handler. + * FPU type handler. * - * Authors: Sarah Walker, - * Miran Grca, + * Authors: Sarah Walker, + * Miran Grca, * - * Copyright 2008-2018 Sarah Walker. - * Copyright 2016-2018 Miran Grca. + * Copyright 2008-2018 Sarah Walker. + * Copyright 2016-2018 Miran Grca. */ #include #include @@ -25,77 +25,71 @@ #include <86box/86box.h> #include "cpu.h" - #ifdef ENABLE_FPU_LOG int fpu_do_log = ENABLE_FPU_LOG; - void fpu_log(const char *fmt, ...) { va_list ap; if (fpu_do_log) { - va_start(ap, fmt); - pclog_ex(fmt, ap); - va_end(ap); + va_start(ap, fmt); + pclog_ex(fmt, ap); + va_end(ap); } } #else -#define fpu_log(fmt, ...) +# define fpu_log(fmt, ...) #endif - int fpu_get_type(const cpu_family_t *cpu_family, int cpu, const char *internal_name) { - const CPU *cpu_s = &cpu_family->cpus[cpu]; - const FPU *fpus = cpu_s->fpus; - int fpu_type = fpus[0].type; - int c = 0; + const CPU *cpu_s = &cpu_family->cpus[cpu]; + const FPU *fpus = cpu_s->fpus; + int fpu_type = fpus[0].type; + int c = 0; while (fpus[c].internal_name) { - if (!strcmp(internal_name, fpus[c].internal_name)) - fpu_type = fpus[c].type; - c++; + if (!strcmp(internal_name, fpus[c].internal_name)) + fpu_type = fpus[c].type; + c++; } return fpu_type; } - const char * fpu_get_internal_name(const cpu_family_t *cpu_family, int cpu, int type) { const CPU *cpu_s = &cpu_family->cpus[cpu]; - const FPU *fpus = cpu_s->fpus; - int c = 0; + const FPU *fpus = cpu_s->fpus; + int c = 0; while (fpus[c].internal_name) { - if (fpus[c].type == type) - return fpus[c].internal_name; - c++; + if (fpus[c].type == type) + return fpus[c].internal_name; + c++; } return fpus[0].internal_name; } - const char * fpu_get_name_from_index(const cpu_family_t *cpu_family, int cpu, int c) { const CPU *cpu_s = &cpu_family->cpus[cpu]; - const FPU *fpus = cpu_s->fpus; + const FPU *fpus = cpu_s->fpus; return fpus[c].name; } - int fpu_get_type_from_index(const cpu_family_t *cpu_family, int cpu, int c) { const CPU *cpu_s = &cpu_family->cpus[cpu]; - const FPU *fpus = cpu_s->fpus; + const FPU *fpus = cpu_s->fpus; return fpus[c].type; } diff --git a/src/cpu/softfloat/CMakeLists.txt b/src/cpu/softfloat/CMakeLists.txt new file mode 100644 index 000000000..936157185 --- /dev/null +++ b/src/cpu/softfloat/CMakeLists.txt @@ -0,0 +1,17 @@ +# +# 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(softfloat OBJECT f2xm1.cc fpatan.cc fprem.cc fsincos.cc fyl2x.cc softfloat_poly.cc softfloat.cc softfloat16.cc + softfloat-muladd.cc softfloat-round-pack.cc softfloat-specialize.cc softfloatx80.cc) diff --git a/src/cpu/softfloat/config.h b/src/cpu/softfloat/config.h new file mode 100644 index 000000000..9e39c2d29 --- /dev/null +++ b/src/cpu/softfloat/config.h @@ -0,0 +1,51 @@ +#ifndef EMU_SF_CONFIG_H +#define EMU_SF_CONFIG_H + +#include + +typedef int8_t flag; +typedef uint8_t uint8; +typedef int8_t int8; +typedef uint16_t uint16; +typedef int16_t int16; +typedef uint32_t uint32; +typedef int32_t int32; +typedef uint64_t uint64; +typedef int64_t int64; + +/*---------------------------------------------------------------------------- +| Each of the following `typedef's defines a type that holds integers +| of _exactly_ the number of bits specified. For instance, for most +| implementation of C, `bits16' and `sbits16' should be `typedef'ed to +| `unsigned short int' and `signed short int' (or `short int'), respectively. +*----------------------------------------------------------------------------*/ +typedef uint8_t bits8; +typedef int8_t sbits8; +typedef uint16_t bits16; +typedef int16_t sbits16; +typedef uint32_t bits32; +typedef int32_t sbits32; +typedef uint64_t bits64; +typedef int64_t sbits64; + +typedef uint8_t Bit8u; +typedef int8_t Bit8s; +typedef uint16_t Bit16u; +typedef int16_t Bit16s; +typedef uint32_t Bit32u; +typedef int32_t Bit32s; +typedef uint64_t Bit64u; +typedef int64_t Bit64s; + +/*---------------------------------------------------------------------------- +| The `LIT64' macro takes as its argument a textual integer literal and +| if necessary ``marks'' the literal as having a 64-bit integer type. +| For example, the GNU C Compiler (`gcc') requires that 64-bit literals be +| appended with the letters `LL' standing for `long long', which is `gcc's +| name for the 64-bit integer type. Some compilers may allow `LIT64' to be +| defined as the identity macro: `#define LIT64( a ) a'. +*----------------------------------------------------------------------------*/ +#define BX_CONST64(a) a##LL +#define BX_CPP_INLINE static __inline + +#endif /*EMU_SF_CONFIG_H*/ diff --git a/src/cpu/softfloat/f2xm1.cc b/src/cpu/softfloat/f2xm1.cc new file mode 100644 index 000000000..ed4af1d12 --- /dev/null +++ b/src/cpu/softfloat/f2xm1.cc @@ -0,0 +1,182 @@ +/*============================================================================ +This source file is an extension to the SoftFloat IEC/IEEE Floating-point +Arithmetic Package, Release 2b, written for Bochs (x86 achitecture simulator) +floating point emulation. + +THIS SOFTWARE IS DISTRIBUTED AS IS, FOR FREE. Although reasonable effort has +been made to avoid it, THIS SOFTWARE MAY CONTAIN FAULTS THAT WILL AT TIMES +RESULT IN INCORRECT BEHAVIOR. USE OF THIS SOFTWARE IS RESTRICTED TO PERSONS +AND ORGANIZATIONS WHO CAN AND WILL TAKE FULL RESPONSIBILITY FOR ALL LOSSES, +COSTS, OR OTHER PROBLEMS THEY INCUR DUE TO THE SOFTWARE, AND WHO FURTHERMORE +EFFECTIVELY INDEMNIFY JOHN HAUSER AND THE INTERNATIONAL COMPUTER SCIENCE +INSTITUTE (possibly via similar legal warning) AGAINST ALL LOSSES, COSTS, OR +OTHER PROBLEMS INCURRED BY THEIR CUSTOMERS AND CLIENTS DUE TO THE SOFTWARE. + +Derivative works are acceptable, even for commercial purposes, so long as +(1) the source code for the derivative work includes prominent notice that +the work is derivative, and (2) the source code includes prominent notice with +these four paragraphs for those parts of this code that are retained. +=============================================================================*/ + +/*============================================================================ + * Written for Bochs (x86 achitecture simulator) by + * Stanislav Shwartsman [sshwarts at sourceforge net] + * ==========================================================================*/ + +#define FLOAT128 + +#include "softfloatx80.h" +#include "softfloat-round-pack.h" + +static const floatx80 floatx80_negone = packFloatx80(1, 0x3fff, BX_CONST64(0x8000000000000000)); +static const floatx80 floatx80_neghalf = packFloatx80(1, 0x3ffe, BX_CONST64(0x8000000000000000)); +static const float128 float128_ln2 = + packFloat128(BX_CONST64(0x3ffe62e42fefa39e), BX_CONST64(0xf35793c7673007e6)); + +#ifdef BETTER_THAN_PENTIUM + +#define LN2_SIG_HI BX_CONST64(0xb17217f7d1cf79ab) +#define LN2_SIG_LO BX_CONST64(0xc9e3b39800000000) /* 96 bit precision */ + +#else + +#define LN2_SIG_HI BX_CONST64(0xb17217f7d1cf79ab) +#define LN2_SIG_LO BX_CONST64(0xc000000000000000) /* 67-bit precision */ + +#endif + +#define EXP_ARR_SIZE 15 + +static float128 exp_arr[EXP_ARR_SIZE] = +{ + PACK_FLOAT_128(0x3fff000000000000, 0x0000000000000000), /* 1 */ + PACK_FLOAT_128(0x3ffe000000000000, 0x0000000000000000), /* 2 */ + PACK_FLOAT_128(0x3ffc555555555555, 0x5555555555555555), /* 3 */ + PACK_FLOAT_128(0x3ffa555555555555, 0x5555555555555555), /* 4 */ + PACK_FLOAT_128(0x3ff8111111111111, 0x1111111111111111), /* 5 */ + PACK_FLOAT_128(0x3ff56c16c16c16c1, 0x6c16c16c16c16c17), /* 6 */ + PACK_FLOAT_128(0x3ff2a01a01a01a01, 0xa01a01a01a01a01a), /* 7 */ + PACK_FLOAT_128(0x3fefa01a01a01a01, 0xa01a01a01a01a01a), /* 8 */ + PACK_FLOAT_128(0x3fec71de3a556c73, 0x38faac1c88e50017), /* 9 */ + PACK_FLOAT_128(0x3fe927e4fb7789f5, 0xc72ef016d3ea6679), /* 10 */ + PACK_FLOAT_128(0x3fe5ae64567f544e, 0x38fe747e4b837dc7), /* 11 */ + PACK_FLOAT_128(0x3fe21eed8eff8d89, 0x7b544da987acfe85), /* 12 */ + PACK_FLOAT_128(0x3fde6124613a86d0, 0x97ca38331d23af68), /* 13 */ + PACK_FLOAT_128(0x3fda93974a8c07c9, 0xd20badf145dfa3e5), /* 14 */ + PACK_FLOAT_128(0x3fd6ae7f3e733b81, 0xf11d8656b0ee8cb0) /* 15 */ +}; + +extern float128 EvalPoly(float128 x, float128 *arr, int n, struct float_status_t *status); + +/* required -1 < x < 1 */ +static float128 poly_exp(float128 x, struct float_status_t *status) +{ +/* + // 2 3 4 5 6 7 8 9 + // x x x x x x x x x + // e - 1 ~ x + --- + --- + --- + --- + --- + --- + --- + --- + ... + // 2! 3! 4! 5! 6! 7! 8! 9! + // + // 2 3 4 5 6 7 8 + // x x x x x x x x + // = x [ 1 + --- + --- + --- + --- + --- + --- + --- + --- + ... ] + // 2! 3! 4! 5! 6! 7! 8! 9! + // + // 8 8 + // -- 2k -- 2k+1 + // p(x) = > C * x q(x) = > C * x + // -- 2k -- 2k+1 + // k=0 k=0 + // + // x + // e - 1 ~ x * [ p(x) + x * q(x) ] + // +*/ + float128 t = EvalPoly(x, exp_arr, EXP_ARR_SIZE, status); + return float128_mul(t, x, status); +} + +// ================================================= +// x +// FX2M1 Compute 2 - 1 +// ================================================= + +// +// Uses the following identities: +// +// 1. ---------------------------------------------------------- +// x x*ln(2) +// 2 = e +// +// 2. ---------------------------------------------------------- +// 2 3 4 5 n +// x x x x x x x +// e = 1 + --- + --- + --- + --- + --- + ... + --- + ... +// 1! 2! 3! 4! 5! n! +// + +floatx80 f2xm1(floatx80 a, struct float_status_t *status) +{ +/*---------------------------------------------------------------------------- +| The pattern for a default generated extended double-precision NaN. +*----------------------------------------------------------------------------*/ + const floatx80 floatx80_default_nan = packFloatx80(0, floatx80_default_nan_exp, floatx80_default_nan_fraction); + Bit64u zSig0, zSig1, zSig2; + + // handle unsupported extended double-precision floating encodings + if (floatx80_is_unsupported(a)) + { + float_raise(status, float_flag_invalid); + return floatx80_default_nan; + } + + Bit64u aSig = extractFloatx80Frac(a); + Bit32s aExp = extractFloatx80Exp(a); + int aSign = extractFloatx80Sign(a); + + if (aExp == 0x7FFF) { + if ((Bit64u) (aSig<<1)) + return propagateFloatx80NaNOne(a, status); + + return (aSign) ? floatx80_negone : a; + } + + if (aExp == 0) { + if (aSig == 0) return a; + float_raise(status, float_flag_denormal | float_flag_inexact); + normalizeFloatx80Subnormal(aSig, &aExp, &aSig); + + tiny_argument: + mul128By64To192(LN2_SIG_HI, LN2_SIG_LO, aSig, &zSig0, &zSig1, &zSig2); + if (0 < (Bit64s) zSig0) { + shortShift128Left(zSig0, zSig1, 1, &zSig0, &zSig1); + --aExp; + } + return + roundAndPackFloatx80(80, aSign, aExp, zSig0, zSig1, status); + } + + float_raise(status, float_flag_inexact); + + if (aExp < 0x3FFF) + { + if (aExp < FLOATX80_EXP_BIAS-68) + goto tiny_argument; + + /* ******************************** */ + /* using float128 for approximation */ + /* ******************************** */ + + float128 x = floatx80_to_float128(a, status); + x = float128_mul(x, float128_ln2, status); + x = poly_exp(x, status); + return float128_to_floatx80(x, status); + } + else + { + if (a.exp == 0xBFFF && ! (aSig<<1)) + return floatx80_neghalf; + + return a; + } +} diff --git a/src/cpu/softfloat/fpatan.cc b/src/cpu/softfloat/fpatan.cc new file mode 100644 index 000000000..f33a3ff66 --- /dev/null +++ b/src/cpu/softfloat/fpatan.cc @@ -0,0 +1,288 @@ +/*============================================================================ +This source file is an extension to the SoftFloat IEC/IEEE Floating-point +Arithmetic Package, Release 2b, written for Bochs (x86 achitecture simulator) +floating point emulation. + +THIS SOFTWARE IS DISTRIBUTED AS IS, FOR FREE. Although reasonable effort has +been made to avoid it, THIS SOFTWARE MAY CONTAIN FAULTS THAT WILL AT TIMES +RESULT IN INCORRECT BEHAVIOR. USE OF THIS SOFTWARE IS RESTRICTED TO PERSONS +AND ORGANIZATIONS WHO CAN AND WILL TAKE FULL RESPONSIBILITY FOR ALL LOSSES, +COSTS, OR OTHER PROBLEMS THEY INCUR DUE TO THE SOFTWARE, AND WHO FURTHERMORE +EFFECTIVELY INDEMNIFY JOHN HAUSER AND THE INTERNATIONAL COMPUTER SCIENCE +INSTITUTE (possibly via similar legal warning) AGAINST ALL LOSSES, COSTS, OR +OTHER PROBLEMS INCURRED BY THEIR CUSTOMERS AND CLIENTS DUE TO THE SOFTWARE. + +Derivative works are acceptable, even for commercial purposes, so long as +(1) the source code for the derivative work includes prominent notice that +the work is derivative, and (2) the source code includes prominent notice with +these four paragraphs for those parts of this code that are retained. +=============================================================================*/ + +/*============================================================================ + * Written for Bochs (x86 achitecture simulator) by + * Stanislav Shwartsman [sshwarts at sourceforge net] + * ==========================================================================*/ + +#define FLOAT128 + +#include "softfloatx80.h" +#include "softfloat-round-pack.h" +#include "fpu_constant.h" + +#define FPATAN_ARR_SIZE 11 + +static const float128 float128_one = + packFloat128(BX_CONST64(0x3fff000000000000), BX_CONST64(0x0000000000000000)); +static const float128 float128_sqrt3 = + packFloat128(BX_CONST64(0x3fffbb67ae8584ca), BX_CONST64(0xa73b25742d7078b8)); +static const floatx80 floatx80_pi = + packFloatx80(0, 0x4000, BX_CONST64(0xc90fdaa22168c235)); + +static const float128 float128_pi2 = + packFloat128(BX_CONST64(0x3fff921fb54442d1), BX_CONST64(0x8469898CC5170416)); +static const float128 float128_pi4 = + packFloat128(BX_CONST64(0x3ffe921fb54442d1), BX_CONST64(0x8469898CC5170416)); +static const float128 float128_pi6 = + packFloat128(BX_CONST64(0x3ffe0c152382d736), BX_CONST64(0x58465BB32E0F580F)); + +static float128 atan_arr[FPATAN_ARR_SIZE] = +{ + PACK_FLOAT_128(0x3fff000000000000, 0x0000000000000000), /* 1 */ + PACK_FLOAT_128(0xbffd555555555555, 0x5555555555555555), /* 3 */ + PACK_FLOAT_128(0x3ffc999999999999, 0x999999999999999a), /* 5 */ + PACK_FLOAT_128(0xbffc249249249249, 0x2492492492492492), /* 7 */ + PACK_FLOAT_128(0x3ffbc71c71c71c71, 0xc71c71c71c71c71c), /* 9 */ + PACK_FLOAT_128(0xbffb745d1745d174, 0x5d1745d1745d1746), /* 11 */ + PACK_FLOAT_128(0x3ffb3b13b13b13b1, 0x3b13b13b13b13b14), /* 13 */ + PACK_FLOAT_128(0xbffb111111111111, 0x1111111111111111), /* 15 */ + PACK_FLOAT_128(0x3ffae1e1e1e1e1e1, 0xe1e1e1e1e1e1e1e2), /* 17 */ + PACK_FLOAT_128(0xbffaaf286bca1af2, 0x86bca1af286bca1b), /* 19 */ + PACK_FLOAT_128(0x3ffa861861861861, 0x8618618618618618) /* 21 */ +}; + +extern float128 OddPoly(float128 x, float128 *arr, int n, struct float_status_t *status); + +/* |x| < 1/4 */ +static float128 poly_atan(float128 x1, struct float_status_t *status) +{ +/* + // 3 5 7 9 11 13 15 17 + // x x x x x x x x + // atan(x) ~ x - --- + --- - --- + --- - ---- + ---- - ---- + ---- + // 3 5 7 9 11 13 15 17 + // + // 2 4 6 8 10 12 14 16 + // x x x x x x x x + // = x * [ 1 - --- + --- - --- + --- - ---- + ---- - ---- + ---- ] + // 3 5 7 9 11 13 15 17 + // + // 5 5 + // -- 4k -- 4k+2 + // p(x) = > C * x q(x) = > C * x + // -- 2k -- 2k+1 + // k=0 k=0 + // + // 2 + // atan(x) ~ x * [ p(x) + x * q(x) ] + // +*/ + return OddPoly(x1, atan_arr, FPATAN_ARR_SIZE, status); +} + +// ================================================= +// FPATAN Compute y * log (x) +// 2 +// ================================================= + +// +// Uses the following identities: +// +// 1. ---------------------------------------------------------- +// +// atan(-x) = -atan(x) +// +// 2. ---------------------------------------------------------- +// +// x + y +// atan(x) + atan(y) = atan -------, xy < 1 +// 1-xy +// +// x + y +// atan(x) + atan(y) = atan ------- + PI, x > 0, xy > 1 +// 1-xy +// +// x + y +// atan(x) + atan(y) = atan ------- - PI, x < 0, xy > 1 +// 1-xy +// +// 3. ---------------------------------------------------------- +// +// atan(x) = atan(INF) + atan(- 1/x) +// +// x-1 +// atan(x) = PI/4 + atan( ----- ) +// x+1 +// +// x * sqrt(3) - 1 +// atan(x) = PI/6 + atan( ----------------- ) +// x + sqrt(3) +// +// 4. ---------------------------------------------------------- +// 3 5 7 9 2n+1 +// x x x x n x +// atan(x) = x - --- + --- - --- + --- - ... + (-1) ------ + ... +// 3 5 7 9 2n+1 +// + +floatx80 fpatan(floatx80 a, floatx80 b, struct float_status_t *status) +{ +/*---------------------------------------------------------------------------- +| The pattern for a default generated extended double-precision NaN. +*----------------------------------------------------------------------------*/ + const floatx80 floatx80_default_nan = packFloatx80(0, floatx80_default_nan_exp, floatx80_default_nan_fraction); + + // handle unsupported extended double-precision floating encodings + if (floatx80_is_unsupported(a) || floatx80_is_unsupported(b)) { + float_raise(status, float_flag_invalid); + return floatx80_default_nan; + } + + Bit64u aSig = extractFloatx80Frac(a); + Bit32s aExp = extractFloatx80Exp(a); + int aSign = extractFloatx80Sign(a); + Bit64u bSig = extractFloatx80Frac(b); + Bit32s bExp = extractFloatx80Exp(b); + int bSign = extractFloatx80Sign(b); + + int zSign = aSign ^ bSign; + + if (bExp == 0x7FFF) + { + if ((Bit64u) (bSig<<1)) + return propagateFloatx80NaN(a, b, status); + + if (aExp == 0x7FFF) { + if ((Bit64u) (aSig<<1)) + return propagateFloatx80NaN(a, b, status); + + if (aSign) { /* return 3PI/4 */ + return roundAndPackFloatx80(80, bSign, + FLOATX80_3PI4_EXP, FLOAT_3PI4_HI, FLOAT_3PI4_LO, status); + } + else { /* return PI/4 */ + return roundAndPackFloatx80(80, bSign, + FLOATX80_PI4_EXP, FLOAT_PI_HI, FLOAT_PI_LO, status); + } + } + + if (aSig && (aExp == 0)) + float_raise(status, float_flag_denormal); + + /* return PI/2 */ + return roundAndPackFloatx80(80, bSign, FLOATX80_PI2_EXP, FLOAT_PI_HI, FLOAT_PI_LO, status); + } + if (aExp == 0x7FFF) + { + if ((Bit64u) (aSig<<1)) + return propagateFloatx80NaN(a, b, status); + + if (bSig && (bExp == 0)) + float_raise(status, float_flag_denormal); + +return_PI_or_ZERO: + + if (aSign) { /* return PI */ + return roundAndPackFloatx80(80, bSign, FLOATX80_PI_EXP, FLOAT_PI_HI, FLOAT_PI_LO, status); + } else { /* return 0 */ + return packFloatx80(bSign, 0, 0); + } + } + if (bExp == 0) + { + if (bSig == 0) { + if (aSig && (aExp == 0)) float_raise(status, float_flag_denormal); + goto return_PI_or_ZERO; + } + + float_raise(status, float_flag_denormal); + normalizeFloatx80Subnormal(bSig, &bExp, &bSig); + } + if (aExp == 0) + { + if (aSig == 0) /* return PI/2 */ + return roundAndPackFloatx80(80, bSign, FLOATX80_PI2_EXP, FLOAT_PI_HI, FLOAT_PI_LO, status); + + float_raise(status, float_flag_denormal); + normalizeFloatx80Subnormal(aSig, &aExp, &aSig); + } + + float_raise(status, float_flag_inexact); + + /* |a| = |b| ==> return PI/4 */ + if (aSig == bSig && aExp == bExp) + return roundAndPackFloatx80(80, bSign, FLOATX80_PI4_EXP, FLOAT_PI_HI, FLOAT_PI_LO, status); + + /* ******************************** */ + /* using float128 for approximation */ + /* ******************************** */ + + float128 a128 = normalizeRoundAndPackFloat128(0, aExp-0x10, aSig, 0, status); + float128 b128 = normalizeRoundAndPackFloat128(0, bExp-0x10, bSig, 0, status); + float128 x; + int swap = 0, add_pi6 = 0, add_pi4 = 0; + + if (aExp > bExp || (aExp == bExp && aSig > bSig)) + { + x = float128_div(b128, a128, status); + } + else { + x = float128_div(a128, b128, status); + swap = 1; + } + + Bit32s xExp = extractFloat128Exp(x); + + if (xExp <= FLOATX80_EXP_BIAS-40) + goto approximation_completed; + + if (x.hi >= BX_CONST64(0x3ffe800000000000)) // 3/4 < x < 1 + { + /* + arctan(x) = arctan((x-1)/(x+1)) + pi/4 + */ + float128 t1 = float128_sub(x, float128_one, status); + float128 t2 = float128_add(x, float128_one, status); + x = float128_div(t1, t2, status); + add_pi4 = 1; + } + else + { + /* argument correction */ + if (xExp >= 0x3FFD) // 1/4 < x < 3/4 + { + /* + arctan(x) = arctan((x*sqrt(3)-1)/(x+sqrt(3))) + pi/6 + */ + float128 t1 = float128_mul(x, float128_sqrt3, status); + float128 t2 = float128_add(x, float128_sqrt3, status); + x = float128_sub(t1, float128_one, status); + x = float128_div(x, t2, status); + add_pi6 = 1; + } + } + + x = poly_atan(x, status); + if (add_pi6) x = float128_add(x, float128_pi6, status); + if (add_pi4) x = float128_add(x, float128_pi4, status); + +approximation_completed: + if (swap) x = float128_sub(float128_pi2, x, status); + floatx80 result = float128_to_floatx80(x, status); + if (zSign) floatx80_chs(result); + int rSign = extractFloatx80Sign(result); + if (!bSign && rSign) + return floatx80_add(result, floatx80_pi, status); + if (bSign && !rSign) + return floatx80_sub(result, floatx80_pi, status); + return result; +} diff --git a/src/cpu/softfloat/fprem.cc b/src/cpu/softfloat/fprem.cc new file mode 100644 index 000000000..26637c5c5 --- /dev/null +++ b/src/cpu/softfloat/fprem.cc @@ -0,0 +1,196 @@ +/*============================================================================ +This source file is an extension to the SoftFloat IEC/IEEE Floating-point +Arithmetic Package, Release 2b, written for Bochs (x86 achitecture simulator) +floating point emulation. + +THIS SOFTWARE IS DISTRIBUTED AS IS, FOR FREE. Although reasonable effort has +been made to avoid it, THIS SOFTWARE MAY CONTAIN FAULTS THAT WILL AT TIMES +RESULT IN INCORRECT BEHAVIOR. USE OF THIS SOFTWARE IS RESTRICTED TO PERSONS +AND ORGANIZATIONS WHO CAN AND WILL TAKE FULL RESPONSIBILITY FOR ALL LOSSES, +COSTS, OR OTHER PROBLEMS THEY INCUR DUE TO THE SOFTWARE, AND WHO FURTHERMORE +EFFECTIVELY INDEMNIFY JOHN HAUSER AND THE INTERNATIONAL COMPUTER SCIENCE +INSTITUTE (possibly via similar legal warning) AGAINST ALL LOSSES, COSTS, OR +OTHER PROBLEMS INCURRED BY THEIR CUSTOMERS AND CLIENTS DUE TO THE SOFTWARE. + +Derivative works are acceptable, even for commercial purposes, so long as +(1) the source code for the derivative work includes prominent notice that +the work is derivative, and (2) the source code includes prominent notice with +these four paragraphs for those parts of this code that are retained. +=============================================================================*/ + +/*============================================================================ + * Written for Bochs (x86 achitecture simulator) by + * Stanislav Shwartsman [sshwarts at sourceforge net] + * ==========================================================================*/ + +#include "softfloatx80.h" +#include "softfloat-round-pack.h" +#define USE_estimateDiv128To64 +#include "softfloat-macros.h" + +/* executes single exponent reduction cycle */ +static Bit64u remainder_kernel(Bit64u aSig0, Bit64u bSig, int expDiff, Bit64u *zSig0, Bit64u *zSig1) +{ + Bit64u term0, term1; + Bit64u aSig1 = 0; + + shortShift128Left(aSig1, aSig0, expDiff, &aSig1, &aSig0); + Bit64u q = estimateDiv128To64(aSig1, aSig0, bSig); + mul64To128(bSig, q, &term0, &term1); + sub128(aSig1, aSig0, term0, term1, zSig1, zSig0); + while ((Bit64s)(*zSig1) < 0) { + --q; + add128(*zSig1, *zSig0, 0, bSig, zSig1, zSig0); + } + return q; +} + +static int do_fprem(floatx80 a, floatx80 b, floatx80 *r, Bit64u *q, int rounding_mode, struct float_status_t *status) +{ +/*---------------------------------------------------------------------------- +| The pattern for a default generated extended double-precision NaN. +*----------------------------------------------------------------------------*/ + const floatx80 floatx80_default_nan = packFloatx80(0, floatx80_default_nan_exp, floatx80_default_nan_fraction); + + Bit32s aExp, bExp, zExp, expDiff; + Bit64u aSig0, aSig1, bSig; + int aSign; + *q = 0; + + // handle unsupported extended double-precision floating encodings + if (floatx80_is_unsupported(a) || floatx80_is_unsupported(b)) + { + float_raise(status, float_flag_invalid); + *r = floatx80_default_nan; + return -1; + } + + aSig0 = extractFloatx80Frac(a); + aExp = extractFloatx80Exp(a); + aSign = extractFloatx80Sign(a); + bSig = extractFloatx80Frac(b); + bExp = extractFloatx80Exp(b); + + if (aExp == 0x7FFF) { + if ((Bit64u) (aSig0<<1) || ((bExp == 0x7FFF) && (Bit64u) (bSig<<1))) { + *r = propagateFloatx80NaN(a, b, status); + return -1; + } + float_raise(status, float_flag_invalid); + *r = floatx80_default_nan; + return -1; + } + if (bExp == 0x7FFF) { + if ((Bit64u) (bSig<<1)) { + *r = propagateFloatx80NaN(a, b, status); + return -1; + } + if (aExp == 0 && aSig0) { + float_raise(status, float_flag_denormal); + normalizeFloatx80Subnormal(aSig0, &aExp, &aSig0); + *r = (a.fraction & BX_CONST64(0x8000000000000000)) ? + packFloatx80(aSign, aExp, aSig0) : a; + return 0; + } + *r = a; + return 0; + + } + if (bExp == 0) { + if (bSig == 0) { + float_raise(status, float_flag_invalid); + *r = floatx80_default_nan; + return -1; + } + float_raise(status, float_flag_denormal); + normalizeFloatx80Subnormal(bSig, &bExp, &bSig); + } + if (aExp == 0) { + if (aSig0 == 0) { + *r = a; + return 0; + } + float_raise(status, float_flag_denormal); + normalizeFloatx80Subnormal(aSig0, &aExp, &aSig0); + } + expDiff = aExp - bExp; + aSig1 = 0; + + Bit32u overflow = 0; + + if (expDiff >= 64) { + int n = (expDiff & 0x1f) | 0x20; + remainder_kernel(aSig0, bSig, n, &aSig0, &aSig1); + zExp = aExp - n; + overflow = 1; + } + else { + zExp = bExp; + + if (expDiff < 0) { + if (expDiff < -1) { + *r = (a.fraction & BX_CONST64(0x8000000000000000)) ? + packFloatx80(aSign, aExp, aSig0) : a; + return 0; + } + shift128Right(aSig0, 0, 1, &aSig0, &aSig1); + expDiff = 0; + } + + if (expDiff > 0) { + *q = remainder_kernel(aSig0, bSig, expDiff, &aSig0, &aSig1); + } + else { + if (bSig <= aSig0) { + aSig0 -= bSig; + *q = 1; + } + } + + if (rounding_mode == float_round_nearest_even) + { + Bit64u term0, term1; + shift128Right(bSig, 0, 1, &term0, &term1); + + if (! lt128(aSig0, aSig1, term0, term1)) + { + int lt = lt128(term0, term1, aSig0, aSig1); + int eq = eq128(aSig0, aSig1, term0, term1); + + if ((eq && ((*q) & 1)) || lt) { + aSign = !aSign; + ++(*q); + } + if (lt) sub128(bSig, 0, aSig0, aSig1, &aSig0, &aSig1); + } + } + } + + *r = normalizeRoundAndPackFloatx80(80, aSign, zExp, aSig0, aSig1, status); + return overflow; +} + +/*---------------------------------------------------------------------------- +| Returns the remainder of the extended double-precision floating-point value +| `a' with respect to the corresponding value `b'. The operation is performed +| according to the IEC/IEEE Standard for Binary Floating-Point Arithmetic. +*----------------------------------------------------------------------------*/ + +int floatx80_ieee754_remainder(floatx80 a, floatx80 b, floatx80 *r, Bit64u *q, struct float_status_t *status) +{ + return do_fprem(a, b, r, q, float_round_nearest_even, status); +} + +/*---------------------------------------------------------------------------- +| Returns the remainder of the extended double-precision floating-point value +| `a' with respect to the corresponding value `b'. Unlike previous function +| the function does not compute the remainder specified in the IEC/IEEE +| Standard for Binary Floating-Point Arithmetic. This function operates +| differently from the previous function in the way that it rounds the +| quotient of 'a' divided by 'b' to an integer. +*----------------------------------------------------------------------------*/ + +int floatx80_remainder(floatx80 a, floatx80 b, floatx80 *r, Bit64u *q, struct float_status_t *status) +{ + return do_fprem(a, b, r, q, float_round_to_zero, status); +} diff --git a/src/cpu/softfloat/fpu_constant.h b/src/cpu/softfloat/fpu_constant.h new file mode 100644 index 000000000..7a7fc6f1a --- /dev/null +++ b/src/cpu/softfloat/fpu_constant.h @@ -0,0 +1,82 @@ +/*============================================================================ +This source file is an extension to the SoftFloat IEC/IEEE Floating-point +Arithmetic Package, Release 2b, written for Bochs (x86 achitecture simulator) +floating point emulation. + +THIS SOFTWARE IS DISTRIBUTED AS IS, FOR FREE. Although reasonable effort has +been made to avoid it, THIS SOFTWARE MAY CONTAIN FAULTS THAT WILL AT TIMES +RESULT IN INCORRECT BEHAVIOR. USE OF THIS SOFTWARE IS RESTRICTED TO PERSONS +AND ORGANIZATIONS WHO CAN AND WILL TAKE FULL RESPONSIBILITY FOR ALL LOSSES, +COSTS, OR OTHER PROBLEMS THEY INCUR DUE TO THE SOFTWARE, AND WHO FURTHERMORE +EFFECTIVELY INDEMNIFY JOHN HAUSER AND THE INTERNATIONAL COMPUTER SCIENCE +INSTITUTE (possibly via similar legal warning) AGAINST ALL LOSSES, COSTS, OR +OTHER PROBLEMS INCURRED BY THEIR CUSTOMERS AND CLIENTS DUE TO THE SOFTWARE. + +Derivative works are acceptable, even for commercial purposes, so long as +(1) the source code for the derivative work includes prominent notice that +the work is derivative, and (2) the source code includes prominent notice with +these four paragraphs for those parts of this code that are retained. +=============================================================================*/ + +#ifndef _FPU_CONSTANTS_H_ +#define _FPU_CONSTANTS_H_ + +#include "config.h" + +// Pentium CPU uses only 68-bit precision M_PI approximation +//#define BETTER_THAN_PENTIUM + +/*============================================================================ + * Written for Bochs (x86 achitecture simulator) by + * Stanislav Shwartsman [sshwarts at sourceforge net] + * ==========================================================================*/ + +////////////////////////////// +// PI, PI/2, PI/4 constants +////////////////////////////// + +#define FLOATX80_PI_EXP (0x4000) + +// 128-bit PI fraction +#ifdef BETTER_THAN_PENTIUM +#define FLOAT_PI_HI (BX_CONST64(0xc90fdaa22168c234)) +#define FLOAT_PI_LO (BX_CONST64(0xc4c6628b80dc1cd1)) +#else +#define FLOAT_PI_HI (BX_CONST64(0xc90fdaa22168c234)) +#define FLOAT_PI_LO (BX_CONST64(0xC000000000000000)) +#endif + +#define FLOATX80_PI2_EXP (0x3FFF) +#define FLOATX80_PI4_EXP (0x3FFE) + +////////////////////////////// +// 3PI/4 constant +////////////////////////////// + +#define FLOATX80_3PI4_EXP (0x4000) + +// 128-bit 3PI/4 fraction +#ifdef BETTER_THAN_PENTIUM +#define FLOAT_3PI4_HI (BX_CONST64(0x96cbe3f9990e91a7)) +#define FLOAT_3PI4_LO (BX_CONST64(0x9394c9e8a0a5159c)) +#else +#define FLOAT_3PI4_HI (BX_CONST64(0x96cbe3f9990e91a7)) +#define FLOAT_3PI4_LO (BX_CONST64(0x9000000000000000)) +#endif + +////////////////////////////// +// 1/LN2 constant +////////////////////////////// + +#define FLOAT_LN2INV_EXP (0x3FFF) + +// 128-bit 1/LN2 fraction +#ifdef BETTER_THAN_PENTIUM +#define FLOAT_LN2INV_HI (BX_CONST64(0xb8aa3b295c17f0bb)) +#define FLOAT_LN2INV_LO (BX_CONST64(0xbe87fed0691d3e89)) +#else +#define FLOAT_LN2INV_HI (BX_CONST64(0xb8aa3b295c17f0bb)) +#define FLOAT_LN2INV_LO (BX_CONST64(0xC000000000000000)) +#endif + +#endif diff --git a/src/cpu/softfloat/fsincos.cc b/src/cpu/softfloat/fsincos.cc new file mode 100644 index 000000000..f5b33a823 --- /dev/null +++ b/src/cpu/softfloat/fsincos.cc @@ -0,0 +1,441 @@ +/*============================================================================ +This source file is an extension to the SoftFloat IEC/IEEE Floating-point +Arithmetic Package, Release 2b, written for Bochs (x86 achitecture simulator) +floating point emulation. + +THIS SOFTWARE IS DISTRIBUTED AS IS, FOR FREE. Although reasonable effort has +been made to avoid it, THIS SOFTWARE MAY CONTAIN FAULTS THAT WILL AT TIMES +RESULT IN INCORRECT BEHAVIOR. USE OF THIS SOFTWARE IS RESTRICTED TO PERSONS +AND ORGANIZATIONS WHO CAN AND WILL TAKE FULL RESPONSIBILITY FOR ALL LOSSES, +COSTS, OR OTHER PROBLEMS THEY INCUR DUE TO THE SOFTWARE, AND WHO FURTHERMORE +EFFECTIVELY INDEMNIFY JOHN HAUSER AND THE INTERNATIONAL COMPUTER SCIENCE +INSTITUTE (possibly via similar legal warning) AGAINST ALL LOSSES, COSTS, OR +OTHER PROBLEMS INCURRED BY THEIR CUSTOMERS AND CLIENTS DUE TO THE SOFTWARE. + +Derivative works are acceptable, even for commercial purposes, so long as +(1) the source code for the derivative work includes prominent notice that +the work is derivative, and (2) the source code includes prominent notice with +these four paragraphs for those parts of this code that are retained. +=============================================================================*/ + +/*============================================================================ + * Written for Bochs (x86 achitecture simulator) by + * Stanislav Shwartsman [sshwarts at sourceforge net] + * ==========================================================================*/ + +#define FLOAT128 + +#define USE_estimateDiv128To64 +#include "softfloatx80.h" +#include "softfloat-round-pack.h" +#include "fpu_constant.h" + +static const floatx80 floatx80_one = packFloatx80(0, 0x3fff, BX_CONST64(0x8000000000000000)); + +/* reduce trigonometric function argument using 128-bit precision + M_PI approximation */ +static Bit64u argument_reduction_kernel(Bit64u aSig0, int Exp, Bit64u *zSig0, Bit64u *zSig1) +{ + Bit64u term0, term1, term2; + Bit64u aSig1 = 0; + + shortShift128Left(aSig1, aSig0, Exp, &aSig1, &aSig0); + Bit64u q = estimateDiv128To64(aSig1, aSig0, FLOAT_PI_HI); + mul128By64To192(FLOAT_PI_HI, FLOAT_PI_LO, q, &term0, &term1, &term2); + sub128(aSig1, aSig0, term0, term1, zSig1, zSig0); + while ((Bit64s)(*zSig1) < 0) { + --q; + add192(*zSig1, *zSig0, term2, 0, FLOAT_PI_HI, FLOAT_PI_LO, zSig1, zSig0, &term2); + } + *zSig1 = term2; + return q; +} + +static int reduce_trig_arg(int expDiff, int *zSign, Bit64u *aSig0, Bit64u *aSig1) +{ + Bit64u term0, term1, q = 0; + + if (expDiff < 0) { + shift128Right(*aSig0, 0, 1, aSig0, aSig1); + expDiff = 0; + } + if (expDiff > 0) { + q = argument_reduction_kernel(*aSig0, expDiff, aSig0, aSig1); + } + else { + if (FLOAT_PI_HI <= *aSig0) { + *aSig0 -= FLOAT_PI_HI; + q = 1; + } + } + + shift128Right(FLOAT_PI_HI, FLOAT_PI_LO, 1, &term0, &term1); + if (! lt128(*aSig0, *aSig1, term0, term1)) + { + int lt = lt128(term0, term1, *aSig0, *aSig1); + int eq = eq128(*aSig0, *aSig1, term0, term1); + + if ((eq && (q & 1)) || lt) { + *zSign = !(*zSign); + ++q; + } + if (lt) sub128(FLOAT_PI_HI, FLOAT_PI_LO, *aSig0, *aSig1, aSig0, aSig1); + } + + return (int)(q & 3); +} + +#define SIN_ARR_SIZE 11 +#define COS_ARR_SIZE 11 + +static float128 sin_arr[SIN_ARR_SIZE] = +{ + PACK_FLOAT_128(0x3fff000000000000, 0x0000000000000000), /* 1 */ + PACK_FLOAT_128(0xbffc555555555555, 0x5555555555555555), /* 3 */ + PACK_FLOAT_128(0x3ff8111111111111, 0x1111111111111111), /* 5 */ + PACK_FLOAT_128(0xbff2a01a01a01a01, 0xa01a01a01a01a01a), /* 7 */ + PACK_FLOAT_128(0x3fec71de3a556c73, 0x38faac1c88e50017), /* 9 */ + PACK_FLOAT_128(0xbfe5ae64567f544e, 0x38fe747e4b837dc7), /* 11 */ + PACK_FLOAT_128(0x3fde6124613a86d0, 0x97ca38331d23af68), /* 13 */ + PACK_FLOAT_128(0xbfd6ae7f3e733b81, 0xf11d8656b0ee8cb0), /* 15 */ + PACK_FLOAT_128(0x3fce952c77030ad4, 0xa6b2605197771b00), /* 17 */ + PACK_FLOAT_128(0xbfc62f49b4681415, 0x724ca1ec3b7b9675), /* 19 */ + PACK_FLOAT_128(0x3fbd71b8ef6dcf57, 0x18bef146fcee6e45) /* 21 */ +}; + +static float128 cos_arr[COS_ARR_SIZE] = +{ + PACK_FLOAT_128(0x3fff000000000000, 0x0000000000000000), /* 0 */ + PACK_FLOAT_128(0xbffe000000000000, 0x0000000000000000), /* 2 */ + PACK_FLOAT_128(0x3ffa555555555555, 0x5555555555555555), /* 4 */ + PACK_FLOAT_128(0xbff56c16c16c16c1, 0x6c16c16c16c16c17), /* 6 */ + PACK_FLOAT_128(0x3fefa01a01a01a01, 0xa01a01a01a01a01a), /* 8 */ + PACK_FLOAT_128(0xbfe927e4fb7789f5, 0xc72ef016d3ea6679), /* 10 */ + PACK_FLOAT_128(0x3fe21eed8eff8d89, 0x7b544da987acfe85), /* 12 */ + PACK_FLOAT_128(0xbfda93974a8c07c9, 0xd20badf145dfa3e5), /* 14 */ + PACK_FLOAT_128(0x3fd2ae7f3e733b81, 0xf11d8656b0ee8cb0), /* 16 */ + PACK_FLOAT_128(0xbfca6827863b97d9, 0x77bb004886a2c2ab), /* 18 */ + PACK_FLOAT_128(0x3fc1e542ba402022, 0x507a9cad2bf8f0bb) /* 20 */ +}; + +extern float128 OddPoly (float128 x, float128 *arr, int n, struct float_status_t *status); + +/* 0 <= x <= pi/4 */ +BX_CPP_INLINE float128 poly_sin(float128 x, struct float_status_t *status) +{ + // 3 5 7 9 11 13 15 + // x x x x x x x + // sin (x) ~ x - --- + --- - --- + --- - ---- + ---- - ---- = + // 3! 5! 7! 9! 11! 13! 15! + // + // 2 4 6 8 10 12 14 + // x x x x x x x + // = x * [ 1 - --- + --- - --- + --- - ---- + ---- - ---- ] = + // 3! 5! 7! 9! 11! 13! 15! + // + // 3 3 + // -- 4k -- 4k+2 + // p(x) = > C * x > 0 q(x) = > C * x < 0 + // -- 2k -- 2k+1 + // k=0 k=0 + // + // 2 + // sin(x) ~ x * [ p(x) + x * q(x) ] + // + + return OddPoly(x, sin_arr, SIN_ARR_SIZE, status); +} + +extern float128 EvenPoly(float128 x, float128 *arr, int n, struct float_status_t *status); + +/* 0 <= x <= pi/4 */ +BX_CPP_INLINE float128 poly_cos(float128 x, struct float_status_t *status) +{ + // 2 4 6 8 10 12 14 + // x x x x x x x + // cos (x) ~ 1 - --- + --- - --- + --- - ---- + ---- - ---- + // 2! 4! 6! 8! 10! 12! 14! + // + // 3 3 + // -- 4k -- 4k+2 + // p(x) = > C * x > 0 q(x) = > C * x < 0 + // -- 2k -- 2k+1 + // k=0 k=0 + // + // 2 + // cos(x) ~ [ p(x) + x * q(x) ] + // + + return EvenPoly(x, cos_arr, COS_ARR_SIZE, status); +} + +BX_CPP_INLINE void sincos_invalid(floatx80 *sin_a, floatx80 *cos_a, floatx80 a) +{ + if (sin_a) *sin_a = a; + if (cos_a) *cos_a = a; +} + +BX_CPP_INLINE void sincos_tiny_argument(floatx80 *sin_a, floatx80 *cos_a, floatx80 a) +{ + if (sin_a) *sin_a = a; + if (cos_a) *cos_a = floatx80_one; +} + +static floatx80 sincos_approximation(int neg, float128 r, Bit64u quotient, struct float_status_t *status) +{ + if (quotient & 0x1) { + r = poly_cos(r, status); + neg = 0; + } else { + r = poly_sin(r, status); + } + + floatx80 result = float128_to_floatx80(r, status); + if (quotient & 0x2) + neg = ! neg; + + if (neg) + floatx80_chs(result); + + return result; +} + +// ================================================= +// FSINCOS Compute sin(x) and cos(x) +// ================================================= + +// +// Uses the following identities: +// ---------------------------------------------------------- +// +// sin(-x) = -sin(x) +// cos(-x) = cos(x) +// +// sin(x+y) = sin(x)*cos(y)+cos(x)*sin(y) +// cos(x+y) = sin(x)*sin(y)+cos(x)*cos(y) +// +// sin(x+ pi/2) = cos(x) +// sin(x+ pi) = -sin(x) +// sin(x+3pi/2) = -cos(x) +// sin(x+2pi) = sin(x) +// + +int fsincos(floatx80 a, floatx80 *sin_a, floatx80 *cos_a, struct float_status_t *status) +{ +/*---------------------------------------------------------------------------- +| The pattern for a default generated extended double-precision NaN. +*----------------------------------------------------------------------------*/ + const floatx80 floatx80_default_nan = packFloatx80(0, floatx80_default_nan_exp, floatx80_default_nan_fraction); + + Bit64u aSig0, aSig1 = 0; + Bit32s aExp, zExp, expDiff; + int aSign, zSign; + int q = 0; + + // handle unsupported extended double-precision floating encodings + if (floatx80_is_unsupported(a)) { + goto invalid; + } + + aSig0 = extractFloatx80Frac(a); + aExp = extractFloatx80Exp(a); + aSign = extractFloatx80Sign(a); + + /* invalid argument */ + if (aExp == 0x7FFF) { + if ((Bit64u) (aSig0<<1)) { + sincos_invalid(sin_a, cos_a, propagateFloatx80NaNOne(a, status)); + return 0; + } + + invalid: + float_raise(status, float_flag_invalid); + sincos_invalid(sin_a, cos_a, floatx80_default_nan); + return 0; + } + + if (aExp == 0) { + if (aSig0 == 0) { + sincos_tiny_argument(sin_a, cos_a, a); + return 0; + } + + float_raise(status, float_flag_denormal); + + /* handle pseudo denormals */ + if (! (aSig0 & BX_CONST64(0x8000000000000000))) + { + float_raise(status, float_flag_inexact); + if (sin_a) + float_raise(status, float_flag_underflow); + sincos_tiny_argument(sin_a, cos_a, a); + return 0; + } + + normalizeFloatx80Subnormal(aSig0, &aExp, &aSig0); + } + + zSign = aSign; + zExp = FLOATX80_EXP_BIAS; + expDiff = aExp - zExp; + + /* argument is out-of-range */ + if (expDiff >= 63) + return -1; + + float_raise(status, float_flag_inexact); + + if (expDiff < -1) { // doesn't require reduction + if (expDiff <= -68) { + a = packFloatx80(aSign, aExp, aSig0); + sincos_tiny_argument(sin_a, cos_a, a); + return 0; + } + zExp = aExp; + } + else { + q = reduce_trig_arg(expDiff, &zSign, &aSig0, &aSig1); + } + + /* **************************** */ + /* argument reduction completed */ + /* **************************** */ + + /* using float128 for approximation */ + float128 r = normalizeRoundAndPackFloat128(0, zExp-0x10, aSig0, aSig1, status); + + if (aSign) q = -q; + if (sin_a) *sin_a = sincos_approximation(zSign, r, q, status); + if (cos_a) *cos_a = sincos_approximation(zSign, r, q+1, status); + + return 0; +} + +int fsin(floatx80 *a, struct float_status_t *status) +{ + return fsincos(*a, a, 0, status); +} + +int fcos(floatx80 *a, struct float_status_t *status) +{ + return fsincos(*a, 0, a, status); +} + +// ================================================= +// FPTAN Compute tan(x) +// ================================================= + +// +// Uses the following identities: +// +// 1. ---------------------------------------------------------- +// +// sin(-x) = -sin(x) +// cos(-x) = cos(x) +// +// sin(x+y) = sin(x)*cos(y)+cos(x)*sin(y) +// cos(x+y) = sin(x)*sin(y)+cos(x)*cos(y) +// +// sin(x+ pi/2) = cos(x) +// sin(x+ pi) = -sin(x) +// sin(x+3pi/2) = -cos(x) +// sin(x+2pi) = sin(x) +// +// 2. ---------------------------------------------------------- +// +// sin(x) +// tan(x) = ------ +// cos(x) +// + +int ftan(floatx80 *a, struct float_status_t *status) +{ +/*---------------------------------------------------------------------------- +| The pattern for a default generated extended double-precision NaN. +*----------------------------------------------------------------------------*/ + const floatx80 floatx80_default_nan = packFloatx80(0, floatx80_default_nan_exp, floatx80_default_nan_fraction); + + Bit64u aSig0, aSig1 = 0; + Bit32s aExp, zExp, expDiff; + int aSign, zSign; + int q = 0; + + // handle unsupported extended double-precision floating encodings + if (floatx80_is_unsupported(*a)) { + goto invalid; + } + + aSig0 = extractFloatx80Frac(*a); + aExp = extractFloatx80Exp(*a); + aSign = extractFloatx80Sign(*a); + + /* invalid argument */ + if (aExp == 0x7FFF) { + if ((Bit64u) (aSig0<<1)) + { + *a = propagateFloatx80NaNOne(*a, status); + return 0; + } + + invalid: + float_raise(status, float_flag_invalid); + *a = floatx80_default_nan; + return 0; + } + + if (aExp == 0) { + if (aSig0 == 0) return 0; + float_raise(status, float_flag_denormal); + /* handle pseudo denormals */ + if (! (aSig0 & BX_CONST64(0x8000000000000000))) + { + float_raise(status, float_flag_inexact | float_flag_underflow); + return 0; + } + normalizeFloatx80Subnormal(aSig0, &aExp, &aSig0); + } + + zSign = aSign; + zExp = FLOATX80_EXP_BIAS; + expDiff = aExp - zExp; + + /* argument is out-of-range */ + if (expDiff >= 63) + return -1; + + float_raise(status, float_flag_inexact); + + if (expDiff < -1) { // doesn't require reduction + if (expDiff <= -68) { + *a = packFloatx80(aSign, aExp, aSig0); + return 0; + } + zExp = aExp; + } + else { + q = reduce_trig_arg(expDiff, &zSign, &aSig0, &aSig1); + } + + /* **************************** */ + /* argument reduction completed */ + /* **************************** */ + + /* using float128 for approximation */ + float128 r = normalizeRoundAndPackFloat128(0, zExp-0x10, aSig0, aSig1, status); + + float128 sin_r = poly_sin(r, status); + float128 cos_r = poly_cos(r, status); + + if (q & 0x1) { + r = float128_div(cos_r, sin_r, status); + zSign = ! zSign; + } else { + r = float128_div(sin_r, cos_r, status); + } + + *a = float128_to_floatx80(r, status); + if (zSign) + floatx80_chs(*a); + + return 0; +} diff --git a/src/cpu/softfloat/fyl2x.cc b/src/cpu/softfloat/fyl2x.cc new file mode 100644 index 000000000..875f866a9 --- /dev/null +++ b/src/cpu/softfloat/fyl2x.cc @@ -0,0 +1,363 @@ +/*============================================================================ +This source file is an extension to the SoftFloat IEC/IEEE Floating-point +Arithmetic Package, Release 2b, written for Bochs (x86 achitecture simulator) +floating point emulation. + +THIS SOFTWARE IS DISTRIBUTED AS IS, FOR FREE. Although reasonable effort has +been made to avoid it, THIS SOFTWARE MAY CONTAIN FAULTS THAT WILL AT TIMES +RESULT IN INCORRECT BEHAVIOR. USE OF THIS SOFTWARE IS RESTRICTED TO PERSONS +AND ORGANIZATIONS WHO CAN AND WILL TAKE FULL RESPONSIBILITY FOR ALL LOSSES, +COSTS, OR OTHER PROBLEMS THEY INCUR DUE TO THE SOFTWARE, AND WHO FURTHERMORE +EFFECTIVELY INDEMNIFY JOHN HAUSER AND THE INTERNATIONAL COMPUTER SCIENCE +INSTITUTE (possibly via similar legal warning) AGAINST ALL LOSSES, COSTS, OR +OTHER PROBLEMS INCURRED BY THEIR CUSTOMERS AND CLIENTS DUE TO THE SOFTWARE. + +Derivative works are acceptable, even for commercial purposes, so long as +(1) the source code for the derivative work includes prominent notice that +the work is derivative, and (2) the source code includes prominent notice with +these four paragraphs for those parts of this code that are retained. +=============================================================================*/ + +/*============================================================================ + * Written for Bochs (x86 achitecture simulator) by + * Stanislav Shwartsman [sshwarts at sourceforge net] + * ==========================================================================*/ + +#define FLOAT128 + +#include "softfloatx80.h" +#include "softfloat-round-pack.h" +#include "fpu_constant.h" + +static const floatx80 floatx80_one = + packFloatx80(0, 0x3fff, BX_CONST64(0x8000000000000000)); + +static const float128 float128_one = + packFloat128(BX_CONST64(0x3fff000000000000), BX_CONST64(0x0000000000000000)); +static const float128 float128_two = + packFloat128(BX_CONST64(0x4000000000000000), BX_CONST64(0x0000000000000000)); + +static const float128 float128_ln2inv2 = + packFloat128(BX_CONST64(0x400071547652b82f), BX_CONST64(0xe1777d0ffda0d23a)); + +#define SQRT2_HALF_SIG BX_CONST64(0xb504f333f9de6484) + +extern float128 OddPoly(float128 x, float128 *arr, int n, struct float_status_t *status); + +#define L2_ARR_SIZE 9 + +static float128 ln_arr[L2_ARR_SIZE] = +{ + PACK_FLOAT_128(0x3fff000000000000, 0x0000000000000000), /* 1 */ + PACK_FLOAT_128(0x3ffd555555555555, 0x5555555555555555), /* 3 */ + PACK_FLOAT_128(0x3ffc999999999999, 0x999999999999999a), /* 5 */ + PACK_FLOAT_128(0x3ffc249249249249, 0x2492492492492492), /* 7 */ + PACK_FLOAT_128(0x3ffbc71c71c71c71, 0xc71c71c71c71c71c), /* 9 */ + PACK_FLOAT_128(0x3ffb745d1745d174, 0x5d1745d1745d1746), /* 11 */ + PACK_FLOAT_128(0x3ffb3b13b13b13b1, 0x3b13b13b13b13b14), /* 13 */ + PACK_FLOAT_128(0x3ffb111111111111, 0x1111111111111111), /* 15 */ + PACK_FLOAT_128(0x3ffae1e1e1e1e1e1, 0xe1e1e1e1e1e1e1e2) /* 17 */ +}; + +static float128 poly_ln(float128 x1, struct float_status_t *status) +{ +/* + // + // 3 5 7 9 11 13 15 + // 1+u u u u u u u u + // 1/2 ln --- ~ u + --- + --- + --- + --- + ---- + ---- + ---- = + // 1-u 3 5 7 9 11 13 15 + // + // 2 4 6 8 10 12 14 + // u u u u u u u + // = u * [ 1 + --- + --- + --- + --- + ---- + ---- + ---- ] = + // 3 5 7 9 11 13 15 + // + // 3 3 + // -- 4k -- 4k+2 + // p(u) = > C * u q(u) = > C * u + // -- 2k -- 2k+1 + // k=0 k=0 + // + // 1+u 2 + // 1/2 ln --- ~ u * [ p(u) + u * q(u) ] + // 1-u + // +*/ + return OddPoly(x1, ln_arr, L2_ARR_SIZE, status); +} + +/* required sqrt(2)/2 < x < sqrt(2) */ +static float128 poly_l2(float128 x, struct float_status_t *status) +{ + /* using float128 for approximation */ + float128 x_p1 = float128_add(x, float128_one, status); + float128 x_m1 = float128_sub(x, float128_one, status); + x = float128_div(x_m1, x_p1, status); + x = poly_ln(x, status); + x = float128_mul(x, float128_ln2inv2, status); + return x; +} + +static float128 poly_l2p1(float128 x, struct float_status_t *status) +{ + /* using float128 for approximation */ + float128 x_p2 = float128_add(x, float128_two, status); + x = float128_div(x, x_p2, status); + x = poly_ln(x, status); + x = float128_mul(x, float128_ln2inv2, status); + return x; +} + +// ================================================= +// FYL2X Compute y * log (x) +// 2 +// ================================================= + +// +// Uses the following identities: +// +// 1. ---------------------------------------------------------- +// ln(x) +// log (x) = -------, ln (x*y) = ln(x) + ln(y) +// 2 ln(2) +// +// 2. ---------------------------------------------------------- +// 1+u x-1 +// ln (x) = ln -----, when u = ----- +// 1-u x+1 +// +// 3. ---------------------------------------------------------- +// 3 5 7 2n+1 +// 1+u u u u u +// ln ----- = 2 [ u + --- + --- + --- + ... + ------ + ... ] +// 1-u 3 5 7 2n+1 +// + +floatx80 fyl2x(floatx80 a, floatx80 b, struct float_status_t *status) +{ +/*---------------------------------------------------------------------------- +| The pattern for a default generated extended double-precision NaN. +*----------------------------------------------------------------------------*/ + const floatx80 floatx80_default_nan = packFloatx80(0, floatx80_default_nan_exp, floatx80_default_nan_fraction); + + // handle unsupported extended double-precision floating encodings + if (floatx80_is_unsupported(a) || floatx80_is_unsupported(b)) { +invalid: + float_raise(status, float_flag_invalid); + return floatx80_default_nan; + } + + Bit64u aSig = extractFloatx80Frac(a); + Bit32s aExp = extractFloatx80Exp(a); + int aSign = extractFloatx80Sign(a); + Bit64u bSig = extractFloatx80Frac(b); + Bit32s bExp = extractFloatx80Exp(b); + int bSign = extractFloatx80Sign(b); + + int zSign = bSign ^ 1; + + if (aExp == 0x7FFF) { + if ((Bit64u) (aSig<<1) + || ((bExp == 0x7FFF) && (Bit64u) (bSig<<1))) + { + return propagateFloatx80NaN(a, b, status); + } + if (aSign) goto invalid; + else { + if (bExp == 0) { + if (bSig == 0) goto invalid; + float_raise(status, float_flag_denormal); + } + return packFloatx80(bSign, 0x7FFF, BX_CONST64(0x8000000000000000)); + } + } + if (bExp == 0x7FFF) + { + if ((Bit64u) (bSig<<1)) return propagateFloatx80NaN(a, b, status); + if (aSign && (Bit64u)(aExp | aSig)) goto invalid; + if (aSig && (aExp == 0)) + float_raise(status, float_flag_denormal); + if (aExp < 0x3FFF) { + return packFloatx80(zSign, 0x7FFF, BX_CONST64(0x8000000000000000)); + } + if (aExp == 0x3FFF && ((Bit64u) (aSig<<1) == 0)) goto invalid; + return packFloatx80(bSign, 0x7FFF, BX_CONST64(0x8000000000000000)); + } + if (aExp == 0) { + if (aSig == 0) { + if ((bExp | bSig) == 0) goto invalid; + float_raise(status, float_flag_divbyzero); + return packFloatx80(zSign, 0x7FFF, BX_CONST64(0x8000000000000000)); + } + if (aSign) goto invalid; + float_raise(status, float_flag_denormal); + normalizeFloatx80Subnormal(aSig, &aExp, &aSig); + } + if (aSign) goto invalid; + if (bExp == 0) { + if (bSig == 0) { + if (aExp < 0x3FFF) return packFloatx80(zSign, 0, 0); + return packFloatx80(bSign, 0, 0); + } + float_raise(status, float_flag_denormal); + normalizeFloatx80Subnormal(bSig, &bExp, &bSig); + } + if (aExp == 0x3FFF && ((Bit64u) (aSig<<1) == 0)) + return packFloatx80(bSign, 0, 0); + + float_raise(status, float_flag_inexact); + + int ExpDiff = aExp - 0x3FFF; + aExp = 0; + if (aSig >= SQRT2_HALF_SIG) { + ExpDiff++; + aExp--; + } + + /* ******************************** */ + /* using float128 for approximation */ + /* ******************************** */ + + Bit64u zSig0, zSig1; + shift128Right(aSig<<1, 0, 16, &zSig0, &zSig1); + float128 x = packFloat128Four(0, aExp+0x3FFF, zSig0, zSig1); + x = poly_l2(x, status); + x = float128_add(x, int64_to_float128((Bit64s) ExpDiff), status); + return floatx80_128_mul(b, x, status); +} + +// ================================================= +// FYL2XP1 Compute y * log (x + 1) +// 2 +// ================================================= + +// +// Uses the following identities: +// +// 1. ---------------------------------------------------------- +// ln(x) +// log (x) = ------- +// 2 ln(2) +// +// 2. ---------------------------------------------------------- +// 1+u x +// ln (x+1) = ln -----, when u = ----- +// 1-u x+2 +// +// 3. ---------------------------------------------------------- +// 3 5 7 2n+1 +// 1+u u u u u +// ln ----- = 2 [ u + --- + --- + --- + ... + ------ + ... ] +// 1-u 3 5 7 2n+1 +// + +floatx80 fyl2xp1(floatx80 a, floatx80 b, struct float_status_t *status) +{ +/*---------------------------------------------------------------------------- +| The pattern for a default generated extended double-precision NaN. +*----------------------------------------------------------------------------*/ + const floatx80 floatx80_default_nan = packFloatx80(0, floatx80_default_nan_exp, floatx80_default_nan_fraction); + + Bit32s aExp, bExp; + Bit64u aSig, bSig, zSig0, zSig1, zSig2; + int aSign, bSign; + + // handle unsupported extended double-precision floating encodings + if (floatx80_is_unsupported(a) || floatx80_is_unsupported(b)) { +invalid: + float_raise(status, float_flag_invalid); + return floatx80_default_nan; + } + + aSig = extractFloatx80Frac(a); + aExp = extractFloatx80Exp(a); + aSign = extractFloatx80Sign(a); + bSig = extractFloatx80Frac(b); + bExp = extractFloatx80Exp(b); + bSign = extractFloatx80Sign(b); + int zSign = aSign ^ bSign; + + if (aExp == 0x7FFF) { + if ((Bit64u) (aSig<<1) + || ((bExp == 0x7FFF) && (Bit64u) (bSig<<1))) + { + return propagateFloatx80NaN(a, b, status); + } + if (aSign) goto invalid; + else { + if (bExp == 0) { + if (bSig == 0) goto invalid; + float_raise(status, float_flag_denormal); + } + return packFloatx80(bSign, 0x7FFF, BX_CONST64(0x8000000000000000)); + } + } + if (bExp == 0x7FFF) + { + if ((Bit64u) (bSig<<1)) + return propagateFloatx80NaN(a, b, status); + + if (aExp == 0) { + if (aSig == 0) goto invalid; + float_raise(status, float_flag_denormal); + } + + return packFloatx80(zSign, 0x7FFF, BX_CONST64(0x8000000000000000)); + } + if (aExp == 0) { + if (aSig == 0) { + if (bSig && (bExp == 0)) float_raise(status, float_flag_denormal); + return packFloatx80(zSign, 0, 0); + } + float_raise(status, float_flag_denormal); + normalizeFloatx80Subnormal(aSig, &aExp, &aSig); + } + if (bExp == 0) { + if (bSig == 0) return packFloatx80(zSign, 0, 0); + float_raise(status, float_flag_denormal); + normalizeFloatx80Subnormal(bSig, &bExp, &bSig); + } + + float_raise(status, float_flag_inexact); + + if (aSign && aExp >= 0x3FFF) + return a; + + if (aExp >= 0x3FFC) // big argument + { + return fyl2x(floatx80_add(a, floatx80_one, status), b, status); + } + + // handle tiny argument + if (aExp < FLOATX80_EXP_BIAS-70) + { + // first order approximation, return (a*b)/ln(2) + Bit32s zExp = aExp + FLOAT_LN2INV_EXP - 0x3FFE; + + mul128By64To192(FLOAT_LN2INV_HI, FLOAT_LN2INV_LO, aSig, &zSig0, &zSig1, &zSig2); + if (0 < (Bit64s) zSig0) { + shortShift128Left(zSig0, zSig1, 1, &zSig0, &zSig1); + --zExp; + } + + zExp = zExp + bExp - 0x3FFE; + mul128By64To192(zSig0, zSig1, bSig, &zSig0, &zSig1, &zSig2); + if (0 < (Bit64s) zSig0) { + shortShift128Left(zSig0, zSig1, 1, &zSig0, &zSig1); + --zExp; + } + + return + roundAndPackFloatx80(80, aSign ^ bSign, zExp, zSig0, zSig1, status); + } + + /* ******************************** */ + /* using float128 for approximation */ + /* ******************************** */ + + shift128Right(aSig<<1, 0, 16, &zSig0, &zSig1); + float128 x = packFloat128Four(aSign, aExp, zSig0, zSig1); + x = poly_l2p1(x, status); + return floatx80_128_mul(b, x, status); +} diff --git a/src/cpu/softfloat/softfloat-compare.h b/src/cpu/softfloat/softfloat-compare.h new file mode 100644 index 000000000..8b9821460 --- /dev/null +++ b/src/cpu/softfloat/softfloat-compare.h @@ -0,0 +1,496 @@ +/*============================================================================ +This C header file is part of the SoftFloat IEC/IEEE Floating-point Arithmetic +Package, Release 2b. + +Written by John R. Hauser. This work was made possible in part by the +International Computer Science Institute, located at Suite 600, 1947 Center +Street, Berkeley, California 94704. Funding was partially provided by the +National Science Foundation under grant MIP-9311980. The original version +of this code was written as part of a project to build a fixed-point vector +processor in collaboration with the University of California at Berkeley, +overseen by Profs. Nelson Morgan and John Wawrzynek. More information +is available through the Web page `http://www.cs.berkeley.edu/~jhauser/ +arithmetic/SoftFloat.html'. + +THIS SOFTWARE IS DISTRIBUTED AS IS, FOR FREE. Although reasonable effort has +been made to avoid it, THIS SOFTWARE MAY CONTAIN FAULTS THAT WILL AT TIMES +RESULT IN INCORRECT BEHAVIOR. USE OF THIS SOFTWARE IS RESTRICTED TO PERSONS +AND ORGANIZATIONS WHO CAN AND WILL TAKE FULL RESPONSIBILITY FOR ALL LOSSES, +COSTS, OR OTHER PROBLEMS THEY INCUR DUE TO THE SOFTWARE, AND WHO FURTHERMORE +EFFECTIVELY INDEMNIFY JOHN HAUSER AND THE INTERNATIONAL COMPUTER SCIENCE +INSTITUTE (possibly via similar legal warning) AGAINST ALL LOSSES, COSTS, OR +OTHER PROBLEMS INCURRED BY THEIR CUSTOMERS AND CLIENTS DUE TO THE SOFTWARE. + +Derivative works are acceptable, even for commercial purposes, so long as +(1) the source code for the derivative work includes prominent notice that +the work is derivative, and (2) the source code includes prominent notice with +these four paragraphs for those parts of this code that are retained. +=============================================================================*/ + +/*============================================================================ + * Adapted for Bochs (x86 achitecture simulator) by + * Stanislav Shwartsman [sshwarts at sourceforge net] + * ==========================================================================*/ + +#ifndef _SOFTFLOAT_COMPARE_H_ +#define _SOFTFLOAT_COMPARE_H_ + +#include "softfloat.h" + +// ======= float32 ======= // + +typedef int (*float32_compare_method)(float32, float32, struct float_status_t *status); + +// 0x00 +BX_CPP_INLINE int float32_eq_ordered_quiet(float32 a, float32 b, struct float_status_t *status) +{ + int relation = float32_compare_quiet(a, b, status); + return (relation == float_relation_equal); +} + +// 0x01 +BX_CPP_INLINE int float32_lt_ordered_signalling(float32 a, float32 b, struct float_status_t *status) +{ + int relation = float32_compare_two(a, b, status); + return (relation == float_relation_less); +} + +// 0x02 +BX_CPP_INLINE int float32_le_ordered_signalling(float32 a, float32 b, struct float_status_t *status) +{ + int relation = float32_compare_two(a, b, status); + return (relation == float_relation_less) || (relation == float_relation_equal); +} + +// 0x03 +BX_CPP_INLINE int float32_unordered_quiet(float32 a, float32 b, struct float_status_t *status) +{ + int relation = float32_compare_quiet(a, b, status); + return (relation == float_relation_unordered); +} + +// 0x04 +BX_CPP_INLINE int float32_neq_unordered_quiet(float32 a, float32 b, struct float_status_t *status) +{ + int relation = float32_compare_quiet(a, b, status); + return (relation != float_relation_equal); +} + +// 0x05 +BX_CPP_INLINE int float32_nlt_unordered_signalling(float32 a, float32 b, struct float_status_t *status) +{ + int relation = float32_compare_two(a, b, status); + return (relation != float_relation_less); +} + +// 0x06 +BX_CPP_INLINE int float32_nle_unordered_signalling(float32 a, float32 b, struct float_status_t *status) +{ + int relation = float32_compare_two(a, b, status); + return (relation != float_relation_less) && (relation != float_relation_equal); +} + +// 0x07 +BX_CPP_INLINE int float32_ordered_quiet(float32 a, float32 b, struct float_status_t *status) +{ + int relation = float32_compare_quiet(a, b, status); + return (relation != float_relation_unordered); +} + +// 0x08 +BX_CPP_INLINE int float32_eq_unordered_quiet(float32 a, float32 b, struct float_status_t *status) +{ + int relation = float32_compare_quiet(a, b, status); + return (relation == float_relation_equal) || (relation == float_relation_unordered); +} + +// 0x09 +BX_CPP_INLINE int float32_nge_unordered_signalling(float32 a, float32 b, struct float_status_t *status) +{ + int relation = float32_compare_two(a, b, status); + return (relation == float_relation_less) || (relation == float_relation_unordered); +} + +// 0x0a +BX_CPP_INLINE int float32_ngt_unordered_signalling(float32 a, float32 b, struct float_status_t *status) +{ + int relation = float32_compare_two(a, b, status); + return (relation != float_relation_greater); +} + +// 0x0b +BX_CPP_INLINE int float32_false_quiet(float32 a, float32 b, struct float_status_t *status) +{ + float32_compare_quiet(a, b, status); + return 0; +} + +// 0x0c +BX_CPP_INLINE int float32_neq_ordered_quiet(float32 a, float32 b, struct float_status_t *status) +{ + int relation = float32_compare_quiet(a, b, status); + return (relation != float_relation_equal) && (relation != float_relation_unordered); +} + +// 0x0d +BX_CPP_INLINE int float32_ge_ordered_signalling(float32 a, float32 b, struct float_status_t *status) +{ + int relation = float32_compare_two(a, b, status); + return (relation == float_relation_greater) || (relation == float_relation_equal); +} + +// 0x0e +BX_CPP_INLINE int float32_gt_ordered_signalling(float32 a, float32 b, struct float_status_t *status) +{ + int relation = float32_compare_two(a, b, status); + return (relation == float_relation_greater); +} + +// 0x0f +BX_CPP_INLINE int float32_true_quiet(float32 a, float32 b, struct float_status_t *status) +{ + float32_compare_quiet(a, b, status); + return 1; +} + +// 0x10 +BX_CPP_INLINE int float32_eq_ordered_signalling(float32 a, float32 b, struct float_status_t *status) +{ + int relation = float32_compare_two(a, b, status); + return (relation == float_relation_equal); +} + +// 0x11 +BX_CPP_INLINE int float32_lt_ordered_quiet(float32 a, float32 b, struct float_status_t *status) +{ + int relation = float32_compare_quiet(a, b, status); + return (relation == float_relation_less); +} + +// 0x12 +BX_CPP_INLINE int float32_le_ordered_quiet(float32 a, float32 b, struct float_status_t *status) +{ + int relation = float32_compare_quiet(a, b, status); + return (relation == float_relation_less) || (relation == float_relation_equal); +} + +// 0x13 +BX_CPP_INLINE int float32_unordered_signalling(float32 a, float32 b, struct float_status_t *status) +{ + int relation = float32_compare_two(a, b, status); + return (relation == float_relation_unordered); +} + +// 0x14 +BX_CPP_INLINE int float32_neq_unordered_signalling(float32 a, float32 b, struct float_status_t *status) +{ + int relation = float32_compare_two(a, b, status); + return (relation != float_relation_equal); +} + +// 0x15 +BX_CPP_INLINE int float32_nlt_unordered_quiet(float32 a, float32 b, struct float_status_t *status) +{ + int relation = float32_compare_quiet(a, b, status); + return (relation != float_relation_less); +} + +// 0x16 +BX_CPP_INLINE int float32_nle_unordered_quiet(float32 a, float32 b, struct float_status_t *status) +{ + int relation = float32_compare_quiet(a, b, status); + return (relation != float_relation_less) && (relation != float_relation_equal); +} + +// 0x17 +BX_CPP_INLINE int float32_ordered_signalling(float32 a, float32 b, struct float_status_t *status) +{ + int relation = float32_compare_two(a, b, status); + return (relation != float_relation_unordered); +} + +// 0x18 +BX_CPP_INLINE int float32_eq_unordered_signalling(float32 a, float32 b, struct float_status_t *status) +{ + int relation = float32_compare_two(a, b, status); + return (relation == float_relation_equal) || (relation == float_relation_unordered); +} + +// 0x19 +BX_CPP_INLINE int float32_nge_unordered_quiet(float32 a, float32 b, struct float_status_t *status) +{ + int relation = float32_compare_quiet(a, b, status); + return (relation == float_relation_less) || (relation == float_relation_unordered); +} + +// 0x1a +BX_CPP_INLINE int float32_ngt_unordered_quiet(float32 a, float32 b, struct float_status_t *status) +{ + int relation = float32_compare_quiet(a, b, status); + return (relation != float_relation_greater); +} + +// 0x1b +BX_CPP_INLINE int float32_false_signalling(float32 a, float32 b, struct float_status_t *status) +{ + float32_compare_two(a, b, status); + return 0; +} + +// 0x1c +BX_CPP_INLINE int float32_neq_ordered_signalling(float32 a, float32 b, struct float_status_t *status) +{ + int relation = float32_compare_two(a, b, status); + return (relation != float_relation_equal) && (relation != float_relation_unordered); +} + +// 0x1d +BX_CPP_INLINE int float32_ge_ordered_quiet(float32 a, float32 b, struct float_status_t *status) +{ + int relation = float32_compare_quiet(a, b, status); + return (relation == float_relation_greater) || (relation == float_relation_equal); +} + +// 0x1e +BX_CPP_INLINE int float32_gt_ordered_quiet(float32 a, float32 b, struct float_status_t *status) +{ + int relation = float32_compare_quiet(a, b, status); + return (relation == float_relation_greater); +} + +// 0x1f +BX_CPP_INLINE int float32_true_signalling(float32 a, float32 b, struct float_status_t *status) +{ + float32_compare_two(a, b, status); + return 1; +} + +// ======= float64 ======= // + +typedef int (*float64_compare_method)(float64, float64, struct float_status_t *status); + +// 0x00 +BX_CPP_INLINE int float64_eq_ordered_quiet(float64 a, float64 b, struct float_status_t *status) +{ + int relation = float64_compare_quiet(a, b, status); + return (relation == float_relation_equal); +} + +// 0x01 +BX_CPP_INLINE int float64_lt_ordered_signalling(float64 a, float64 b, struct float_status_t *status) +{ + int relation = float64_compare_two(a, b, status); + return (relation == float_relation_less); +} + +// 0x02 +BX_CPP_INLINE int float64_le_ordered_signalling(float64 a, float64 b, struct float_status_t *status) +{ + int relation = float64_compare_two(a, b, status); + return (relation == float_relation_less) || (relation == float_relation_equal); +} + +// 0x03 +BX_CPP_INLINE int float64_unordered_quiet(float64 a, float64 b, struct float_status_t *status) +{ + int relation = float64_compare_quiet(a, b, status); + return (relation == float_relation_unordered); +} + +// 0x04 +BX_CPP_INLINE int float64_neq_unordered_quiet(float64 a, float64 b, struct float_status_t *status) +{ + int relation = float64_compare_quiet(a, b, status); + return (relation != float_relation_equal); +} + +// 0x05 +BX_CPP_INLINE int float64_nlt_unordered_signalling(float64 a, float64 b, struct float_status_t *status) +{ + int relation = float64_compare_two(a, b, status); + return (relation != float_relation_less); +} + +// 0x06 +BX_CPP_INLINE int float64_nle_unordered_signalling(float64 a, float64 b, struct float_status_t *status) +{ + int relation = float64_compare_two(a, b, status); + return (relation != float_relation_less) && (relation != float_relation_equal); +} + +// 0x07 +BX_CPP_INLINE int float64_ordered_quiet(float64 a, float64 b, struct float_status_t *status) +{ + int relation = float64_compare_quiet(a, b, status); + return (relation != float_relation_unordered); +} + +// 0x08 +BX_CPP_INLINE int float64_eq_unordered_quiet(float64 a, float64 b, struct float_status_t *status) +{ + int relation = float64_compare_quiet(a, b, status); + return (relation == float_relation_equal) || (relation == float_relation_unordered); +} + +// 0x09 +BX_CPP_INLINE int float64_nge_unordered_signalling(float64 a, float64 b, struct float_status_t *status) +{ + int relation = float64_compare_two(a, b, status); + return (relation == float_relation_less) || (relation == float_relation_unordered); +} + +// 0x0a +BX_CPP_INLINE int float64_ngt_unordered_signalling(float64 a, float64 b, struct float_status_t *status) +{ + int relation = float64_compare_two(a, b, status); + return (relation != float_relation_greater); +} + +// 0x0b +BX_CPP_INLINE int float64_false_quiet(float64 a, float64 b, struct float_status_t *status) +{ + float64_compare_quiet(a, b, status); + return 0; +} + +// 0x0c +BX_CPP_INLINE int float64_neq_ordered_quiet(float64 a, float64 b, struct float_status_t *status) +{ + int relation = float64_compare_quiet(a, b, status); + return (relation != float_relation_equal) && (relation != float_relation_unordered); +} + +// 0x0d +BX_CPP_INLINE int float64_ge_ordered_signalling(float64 a, float64 b, struct float_status_t *status) +{ + int relation = float64_compare_two(a, b, status); + return (relation == float_relation_greater) || (relation == float_relation_equal); +} + +// 0x0e +BX_CPP_INLINE int float64_gt_ordered_signalling(float64 a, float64 b, struct float_status_t *status) +{ + int relation = float64_compare_two(a, b, status); + return (relation == float_relation_greater); +} + +// 0x0f +BX_CPP_INLINE int float64_true_quiet(float64 a, float64 b, struct float_status_t *status) +{ + float64_compare_quiet(a, b, status); + return 1; +} + +// 0x10 +BX_CPP_INLINE int float64_eq_ordered_signalling(float64 a, float64 b, struct float_status_t *status) +{ + int relation = float64_compare_two(a, b, status); + return (relation == float_relation_equal); +} + +// 0x11 +BX_CPP_INLINE int float64_lt_ordered_quiet(float64 a, float64 b, struct float_status_t *status) +{ + int relation = float64_compare_quiet(a, b, status); + return (relation == float_relation_less); +} + +// 0x12 +BX_CPP_INLINE int float64_le_ordered_quiet(float64 a, float64 b, struct float_status_t *status) +{ + int relation = float64_compare_quiet(a, b, status); + return (relation == float_relation_less) || (relation == float_relation_equal); +} + +// 0x13 +BX_CPP_INLINE int float64_unordered_signalling(float64 a, float64 b, struct float_status_t *status) +{ + int relation = float64_compare_two(a, b, status); + return (relation == float_relation_unordered); +} + +// 0x14 +BX_CPP_INLINE int float64_neq_unordered_signalling(float64 a, float64 b, struct float_status_t *status) +{ + int relation = float64_compare_two(a, b, status); + return (relation != float_relation_equal); +} + +// 0x15 +BX_CPP_INLINE int float64_nlt_unordered_quiet(float64 a, float64 b, struct float_status_t *status) +{ + int relation = float64_compare_quiet(a, b, status); + return (relation != float_relation_less); +} + +// 0x16 +BX_CPP_INLINE int float64_nle_unordered_quiet(float64 a, float64 b, struct float_status_t *status) +{ + int relation = float64_compare_quiet(a, b, status); + return (relation != float_relation_less) && (relation != float_relation_equal); +} + +// 0x17 +BX_CPP_INLINE int float64_ordered_signalling(float64 a, float64 b, struct float_status_t *status) +{ + int relation = float64_compare_two(a, b, status); + return (relation != float_relation_unordered); +} + +// 0x18 +BX_CPP_INLINE int float64_eq_unordered_signalling(float64 a, float64 b, struct float_status_t *status) +{ + int relation = float64_compare_two(a, b, status); + return (relation == float_relation_equal) || (relation == float_relation_unordered); +} + +// 0x19 +BX_CPP_INLINE int float64_nge_unordered_quiet(float64 a, float64 b, struct float_status_t *status) +{ + int relation = float64_compare_quiet(a, b, status); + return (relation == float_relation_less) || (relation == float_relation_unordered); +} + +// 0x1a +BX_CPP_INLINE int float64_ngt_unordered_quiet(float64 a, float64 b, struct float_status_t *status) +{ + int relation = float64_compare_quiet(a, b, status); + return (relation != float_relation_greater); +} + +// 0x1b +BX_CPP_INLINE int float64_false_signalling(float64 a, float64 b, struct float_status_t *status) +{ + float64_compare_two(a, b, status); + return 0; +} + +// 0x1c +BX_CPP_INLINE int float64_neq_ordered_signalling(float64 a, float64 b, struct float_status_t *status) +{ + int relation = float64_compare_two(a, b, status); + return (relation != float_relation_equal) && (relation != float_relation_unordered); +} + +// 0x1d +BX_CPP_INLINE int float64_ge_ordered_quiet(float64 a, float64 b, struct float_status_t *status) +{ + int relation = float64_compare_quiet(a, b, status); + return (relation == float_relation_greater) || (relation == float_relation_equal); +} + +// 0x1e +BX_CPP_INLINE int float64_gt_ordered_quiet(float64 a, float64 b, struct float_status_t *status) +{ + int relation = float64_compare_quiet(a, b, status); + return (relation == float_relation_greater); +} + +// 0x1f +BX_CPP_INLINE int float64_true_signalling(float64 a, float64 b, struct float_status_t *status) +{ + float64_compare_two(a, b, status); + return 1; +} + +#endif diff --git a/src/cpu/softfloat/softfloat-macros.h b/src/cpu/softfloat/softfloat-macros.h new file mode 100644 index 000000000..cb867bf5d --- /dev/null +++ b/src/cpu/softfloat/softfloat-macros.h @@ -0,0 +1,686 @@ +/*============================================================================ +This C source fragment is part of the SoftFloat IEC/IEEE Floating-point +Arithmetic Package, Release 2b. + +Written by John R. Hauser. This work was made possible in part by the +International Computer Science Institute, located at Suite 600, 1947 Center +Street, Berkeley, California 94704. Funding was partially provided by the +National Science Foundation under grant MIP-9311980. The original version +of this code was written as part of a project to build a fixed-point vector +processor in collaboration with the University of California at Berkeley, +overseen by Profs. Nelson Morgan and John Wawrzynek. More information +is available through the Web page `http://www.cs.berkeley.edu/~jhauser/ +arithmetic/SoftFloat.html'. + +THIS SOFTWARE IS DISTRIBUTED AS IS, FOR FREE. Although reasonable effort has +been made to avoid it, THIS SOFTWARE MAY CONTAIN FAULTS THAT WILL AT TIMES +RESULT IN INCORRECT BEHAVIOR. USE OF THIS SOFTWARE IS RESTRICTED TO PERSONS +AND ORGANIZATIONS WHO CAN AND WILL TAKE FULL RESPONSIBILITY FOR ALL LOSSES, +COSTS, OR OTHER PROBLEMS THEY INCUR DUE TO THE SOFTWARE, AND WHO FURTHERMORE +EFFECTIVELY INDEMNIFY JOHN HAUSER AND THE INTERNATIONAL COMPUTER SCIENCE +INSTITUTE (possibly via similar legal notice) AGAINST ALL LOSSES, COSTS, OR +OTHER PROBLEMS INCURRED BY THEIR CUSTOMERS AND CLIENTS DUE TO THE SOFTWARE. + +Derivative works are acceptable, even for commercial purposes, so long as +(1) the source code for the derivative work includes prominent notice that +the work is derivative, and (2) the source code includes prominent notice with +these four paragraphs for those parts of this code that are retained. +=============================================================================*/ + +/*============================================================================ + * Adapted for Bochs (x86 achitecture simulator) by + * Stanislav Shwartsman [sshwarts at sourceforge net] + * ==========================================================================*/ + +#ifndef _SOFTFLOAT_MACROS_H_ +#define _SOFTFLOAT_MACROS_H_ + +/*---------------------------------------------------------------------------- +| Shifts `a' right by the number of bits given in `count'. If any nonzero +| bits are shifted off, they are ``jammed'' into the least significant bit of +| the result by setting the least significant bit to 1. The value of `count' +| can be arbitrarily large; in particular, if `count' is greater than 16, the +| result will be either 0 or 1, depending on whether `a' is zero or nonzero. +*----------------------------------------------------------------------------*/ + +BX_CPP_INLINE Bit16u shift16RightJamming(Bit16u a, int count) +{ + Bit16u z; + + if (count == 0) { + z = a; + } + else if (count < 16) { + z = (a>>count) | ((a<<((-count) & 15)) != 0); + } + else { + z = (a != 0); + } + + return z; +} + +/*---------------------------------------------------------------------------- +| Shifts `a' right by the number of bits given in `count'. If any nonzero +| bits are shifted off, they are ``jammed'' into the least significant bit of +| the result by setting the least significant bit to 1. The value of `count' +| can be arbitrarily large; in particular, if `count' is greater than 32, the +| result will be either 0 or 1, depending on whether `a' is zero or nonzero. +*----------------------------------------------------------------------------*/ + +BX_CPP_INLINE Bit32u shift32RightJamming(Bit32u a, int count) +{ + Bit32u z; + + if (count == 0) { + z = a; + } + else if (count < 32) { + z = (a>>count) | ((a<<((-count) & 31)) != 0); + } + else { + z = (a != 0); + } + + return z; +} + +/*---------------------------------------------------------------------------- +| Shifts `a' right by the number of bits given in `count'. If any nonzero +| bits are shifted off, they are ``jammed'' into the least significant bit of +| the result by setting the least significant bit to 1. The value of `count' +| can be arbitrarily large; in particular, if `count' is greater than 64, the +| result will be either 0 or 1, depending on whether `a' is zero or nonzero. +*----------------------------------------------------------------------------*/ + +BX_CPP_INLINE Bit64u shift64RightJamming(Bit64u a, int count) +{ + Bit64u z; + + if (count == 0) { + z = a; + } + else if (count < 64) { + z = (a>>count) | ((a << ((-count) & 63)) != 0); + } + else { + z = (a != 0); + } + + return z; +} + +/*---------------------------------------------------------------------------- +| Shifts the 128-bit value formed by concatenating `a0' and `a1' right by 64 +| _plus_ the number of bits given in `count'. The shifted result is at most +| 64 nonzero bits; this is stored at the location pointed to by `z0Ptr'. The +| bits shifted off form a second 64-bit result as follows: The _last_ bit +| shifted off is the most-significant bit of the extra result, and the other +| 63 bits of the extra result are all zero if and only if _all_but_the_last_ +| bits shifted off were all zero. This extra result is stored in the location +| pointed to by `z1Ptr'. The value of `count' can be arbitrarily large. +| (This routine makes more sense if `a0' and `a1' are considered to form +| a fixed-point value with binary point between `a0' and `a1'. This fixed- +| point value is shifted right by the number of bits given in `count', and +| the integer part of the result is returned at the location pointed to by +| `z0Ptr'. The fractional part of the result may be slightly corrupted as +| described above, and is returned at the location pointed to by `z1Ptr'.) +*----------------------------------------------------------------------------*/ + +BX_CPP_INLINE void shift64ExtraRightJamming(Bit64u a0, Bit64u a1, int count, Bit64u *z0Ptr, Bit64u *z1Ptr) +{ + Bit64u z0, z1; + int negCount = (-count) & 63; + + if (count == 0) { + z1 = a1; + z0 = a0; + } + else if (count < 64) { + z1 = (a0<>count; + } + else { + if (count == 64) { + z1 = a0 | (a1 != 0); + } + else { + z1 = ((a0 | a1) != 0); + } + z0 = 0; + } + *z1Ptr = z1; + *z0Ptr = z0; +} + +/*---------------------------------------------------------------------------- +| Adds the 128-bit value formed by concatenating `a0' and `a1' to the 128-bit +| value formed by concatenating `b0' and `b1'. Addition is modulo 2^128, so +| any carry out is lost. The result is broken into two 64-bit pieces which +| are stored at the locations pointed to by `z0Ptr' and `z1Ptr'. +*----------------------------------------------------------------------------*/ + +BX_CPP_INLINE void add128(Bit64u a0, Bit64u a1, Bit64u b0, Bit64u b1, Bit64u *z0Ptr, Bit64u *z1Ptr) +{ + Bit64u z1 = a1 + b1; + *z1Ptr = z1; + *z0Ptr = a0 + b0 + (z1 < a1); +} + +/*---------------------------------------------------------------------------- +| Subtracts the 128-bit value formed by concatenating `b0' and `b1' from the +| 128-bit value formed by concatenating `a0' and `a1'. Subtraction is modulo +| 2^128, so any borrow out (carry out) is lost. The result is broken into two +| 64-bit pieces which are stored at the locations pointed to by `z0Ptr' and +| `z1Ptr'. +*----------------------------------------------------------------------------*/ + +BX_CPP_INLINE void + sub128(Bit64u a0, Bit64u a1, Bit64u b0, Bit64u b1, Bit64u *z0Ptr, Bit64u *z1Ptr) +{ + *z1Ptr = a1 - b1; + *z0Ptr = a0 - b0 - (a1 < b1); +} + +/*---------------------------------------------------------------------------- +| Multiplies `a' by `b' to obtain a 128-bit product. The product is broken +| into two 64-bit pieces which are stored at the locations pointed to by +| `z0Ptr' and `z1Ptr'. +*----------------------------------------------------------------------------*/ + +BX_CPP_INLINE void mul64To128(Bit64u a, Bit64u b, Bit64u *z0Ptr, Bit64u *z1Ptr) +{ + Bit32u aHigh, aLow, bHigh, bLow; + Bit64u z0, zMiddleA, zMiddleB, z1; + + aLow = (Bit32u) a; + aHigh = (Bit32u)(a>>32); + bLow = (Bit32u) b; + bHigh = (Bit32u)(b>>32); + z1 = ((Bit64u) aLow) * bLow; + zMiddleA = ((Bit64u) aLow) * bHigh; + zMiddleB = ((Bit64u) aHigh) * bLow; + z0 = ((Bit64u) aHigh) * bHigh; + zMiddleA += zMiddleB; + z0 += (((Bit64u) (zMiddleA < zMiddleB))<<32) + (zMiddleA>>32); + zMiddleA <<= 32; + z1 += zMiddleA; + z0 += (z1 < zMiddleA); + *z1Ptr = z1; + *z0Ptr = z0; +} + +/*---------------------------------------------------------------------------- +| Returns an approximation to the 64-bit integer quotient obtained by dividing +| `b' into the 128-bit value formed by concatenating `a0' and `a1'. The +| divisor `b' must be at least 2^63. If q is the exact quotient truncated +| toward zero, the approximation returned lies between q and q + 2 inclusive. +| If the exact quotient q is larger than 64 bits, the maximum positive 64-bit +| unsigned integer is returned. +*----------------------------------------------------------------------------*/ + +#ifdef USE_estimateDiv128To64 +static Bit64u estimateDiv128To64(Bit64u a0, Bit64u a1, Bit64u b) +{ + Bit64u b0, b1; + Bit64u rem0, rem1, term0, term1; + Bit64u z; + + if (b <= a0) return BX_CONST64(0xFFFFFFFFFFFFFFFF); + b0 = b>>32; + z = (b0<<32 <= a0) ? BX_CONST64(0xFFFFFFFF00000000) : (a0 / b0)<<32; + mul64To128(b, z, &term0, &term1); + sub128(a0, a1, term0, term1, &rem0, &rem1); + while (((Bit64s) rem0) < 0) { + z -= BX_CONST64(0x100000000); + b1 = b<<32; + add128(rem0, rem1, b0, b1, &rem0, &rem1); + } + rem0 = (rem0<<32) | (rem1>>32); + z |= (b0<<32 <= rem0) ? 0xFFFFFFFF : rem0 / b0; + return z; +} +#endif + +/*---------------------------------------------------------------------------- +| Returns an approximation to the square root of the 32-bit significand given +| by `a'. Considered as an integer, `a' must be at least 2^31. If bit 0 of +| `aExp' (the least significant bit) is 1, the integer returned approximates +| 2^31*sqrt(`a'/2^31), where `a' is considered an integer. If bit 0 of `aExp' +| is 0, the integer returned approximates 2^31*sqrt(`a'/2^30). In either +| case, the approximation returned lies strictly within +/-2 of the exact +| value. +*----------------------------------------------------------------------------*/ + +#ifdef USE_estimateSqrt32 +static Bit32u estimateSqrt32(Bit16s aExp, Bit32u a) +{ + static const Bit16u sqrtOddAdjustments[] = { + 0x0004, 0x0022, 0x005D, 0x00B1, 0x011D, 0x019F, 0x0236, 0x02E0, + 0x039C, 0x0468, 0x0545, 0x0631, 0x072B, 0x0832, 0x0946, 0x0A67 + }; + static const Bit16u sqrtEvenAdjustments[] = { + 0x0A2D, 0x08AF, 0x075A, 0x0629, 0x051A, 0x0429, 0x0356, 0x029E, + 0x0200, 0x0179, 0x0109, 0x00AF, 0x0068, 0x0034, 0x0012, 0x0002 + }; + Bit32u z; + + int index = (a>>27) & 15; + if (aExp & 1) { + z = 0x4000 + (a>>17) - sqrtOddAdjustments[index]; + z = ((a / z)<<14) + (z<<15); + a >>= 1; + } + else { + z = 0x8000 + (a>>17) - sqrtEvenAdjustments[index]; + z = a / z + z; + z = (0x20000 <= z) ? 0xFFFF8000 : (z<<15); + if (z <= a) return (Bit32u) (((Bit32s) a)>>1); + } + return ((Bit32u) ((((Bit64u) a)<<31) / z)) + (z>>1); +} +#endif + +static const int countLeadingZeros8[] = { + 8, 7, 6, 6, 5, 5, 5, 5, 4, 4, 4, 4, 4, 4, 4, 4, + 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 +}; + +#ifdef FLOAT16 + +/*---------------------------------------------------------------------------- +| Returns the number of leading 0 bits before the most-significant 1 bit of +| `a'. If `a' is zero, 16 is returned. +*----------------------------------------------------------------------------*/ + +BX_CPP_INLINE int countLeadingZeros16(Bit16u a) +{ + int shiftCount = 0; + if (a < 0x100) { + shiftCount += 8; + a <<= 8; + } + shiftCount += countLeadingZeros8[a>>8]; + return shiftCount; +} + +#endif + +/*---------------------------------------------------------------------------- +| Returns the number of leading 0 bits before the most-significant 1 bit of +| `a'. If `a' is zero, 32 is returned. +*----------------------------------------------------------------------------*/ + +BX_CPP_INLINE int countLeadingZeros32(Bit32u a) +{ + int shiftCount = 0; + if (a < 0x10000) { + shiftCount += 16; + a <<= 16; + } + if (a < 0x1000000) { + shiftCount += 8; + a <<= 8; + } + shiftCount += countLeadingZeros8[a>>24]; + return shiftCount; +} + +/*---------------------------------------------------------------------------- +| Returns the number of leading 0 bits before the most-significant 1 bit of +| `a'. If `a' is zero, 64 is returned. +*----------------------------------------------------------------------------*/ + +BX_CPP_INLINE int countLeadingZeros64(Bit64u a) +{ + int shiftCount = 0; + if (a < BX_CONST64(0x100000000)) { + shiftCount += 32; + } + else { + a >>= 32; + } + shiftCount += countLeadingZeros32((Bit32u)(a)); + return shiftCount; +} + +#ifdef FLOATX80 + +/*---------------------------------------------------------------------------- +| Shifts the 128-bit value formed by concatenating `a0' and `a1' right by the +| number of bits given in `count'. Any bits shifted off are lost. The value +| of `count' can be arbitrarily large; in particular, if `count' is greater +| than 128, the result will be 0. The result is broken into two 64-bit pieces +| which are stored at the locations pointed to by `z0Ptr' and `z1Ptr'. +*----------------------------------------------------------------------------*/ + +BX_CPP_INLINE void shift128Right(Bit64u a0, Bit64u a1, int count, Bit64u *z0Ptr, Bit64u *z1Ptr) +{ + Bit64u z0, z1; + int negCount = (-count) & 63; + + if (count == 0) { + z1 = a1; + z0 = a0; + } + else if (count < 64) { + z1 = (a0<>count); + z0 = a0>>count; + } + else { + z1 = (count < 128) ? (a0>>(count & 63)) : 0; + z0 = 0; + } + *z1Ptr = z1; + *z0Ptr = z0; +} + +/*---------------------------------------------------------------------------- +| Shifts the 128-bit value formed by concatenating `a0' and `a1' right by the +| number of bits given in `count'. If any nonzero bits are shifted off, they +| are ``jammed'' into the least significant bit of the result by setting the +| least significant bit to 1. The value of `count' can be arbitrarily large; +| in particular, if `count' is greater than 128, the result will be either +| 0 or 1, depending on whether the concatenation of `a0' and `a1' is zero or +| nonzero. The result is broken into two 64-bit pieces which are stored at +| the locations pointed to by `z0Ptr' and `z1Ptr'. +*----------------------------------------------------------------------------*/ + +BX_CPP_INLINE void shift128RightJamming(Bit64u a0, Bit64u a1, int count, Bit64u *z0Ptr, Bit64u *z1Ptr) +{ + Bit64u z0, z1; + int negCount = (-count) & 63; + + if (count == 0) { + z1 = a1; + z0 = a0; + } + else if (count < 64) { + z1 = (a0<>count) | ((a1<>count; + } + else { + if (count == 64) { + z1 = a0 | (a1 != 0); + } + else if (count < 128) { + z1 = (a0>>(count & 63)) | (((a0<>((-count) & 63)); +} + +/*---------------------------------------------------------------------------- +| Adds the 192-bit value formed by concatenating `a0', `a1', and `a2' to the +| 192-bit value formed by concatenating `b0', `b1', and `b2'. Addition is +| modulo 2^192, so any carry out is lost. The result is broken into three +| 64-bit pieces which are stored at the locations pointed to by `z0Ptr', +| `z1Ptr', and `z2Ptr'. +*----------------------------------------------------------------------------*/ + +BX_CPP_INLINE void add192( + Bit64u a0, + Bit64u a1, + Bit64u a2, + Bit64u b0, + Bit64u b1, + Bit64u b2, + Bit64u *z0Ptr, + Bit64u *z1Ptr, + Bit64u *z2Ptr +) +{ + Bit64u z0, z1, z2; + unsigned carry0, carry1; + + z2 = a2 + b2; + carry1 = (z2 < a2); + z1 = a1 + b1; + carry0 = (z1 < a1); + z0 = a0 + b0; + z1 += carry1; + z0 += (z1 < carry1); + z0 += carry0; + *z2Ptr = z2; + *z1Ptr = z1; + *z0Ptr = z0; +} + +/*---------------------------------------------------------------------------- +| Subtracts the 192-bit value formed by concatenating `b0', `b1', and `b2' +| from the 192-bit value formed by concatenating `a0', `a1', and `a2'. +| Subtraction is modulo 2^192, so any borrow out (carry out) is lost. The +| result is broken into three 64-bit pieces which are stored at the locations +| pointed to by `z0Ptr', `z1Ptr', and `z2Ptr'. +*----------------------------------------------------------------------------*/ + +BX_CPP_INLINE void sub192( + Bit64u a0, + Bit64u a1, + Bit64u a2, + Bit64u b0, + Bit64u b1, + Bit64u b2, + Bit64u *z0Ptr, + Bit64u *z1Ptr, + Bit64u *z2Ptr +) +{ + Bit64u z0, z1, z2; + unsigned borrow0, borrow1; + + z2 = a2 - b2; + borrow1 = (a2 < b2); + z1 = a1 - b1; + borrow0 = (a1 < b1); + z0 = a0 - b0; + z0 -= (z1 < borrow1); + z1 -= borrow1; + z0 -= borrow0; + *z2Ptr = z2; + *z1Ptr = z1; + *z0Ptr = z0; +} + +/*---------------------------------------------------------------------------- +| Returns 1 if the 128-bit value formed by concatenating `a0' and `a1' +| is equal to the 128-bit value formed by concatenating `b0' and `b1'. +| Otherwise, returns 0. +*----------------------------------------------------------------------------*/ + +BX_CPP_INLINE int eq128(Bit64u a0, Bit64u a1, Bit64u b0, Bit64u b1) +{ + return (a0 == b0) && (a1 == b1); +} + +/*---------------------------------------------------------------------------- +| Returns 1 if the 128-bit value formed by concatenating `a0' and `a1' is less +| than or equal to the 128-bit value formed by concatenating `b0' and `b1'. +| Otherwise, returns 0. +*----------------------------------------------------------------------------*/ + +BX_CPP_INLINE int le128(Bit64u a0, Bit64u a1, Bit64u b0, Bit64u b1) +{ + return (a0 < b0) || ((a0 == b0) && (a1 <= b1)); +} + +/*---------------------------------------------------------------------------- +| Returns 1 if the 128-bit value formed by concatenating `a0' and `a1' is less +| than the 128-bit value formed by concatenating `b0' and `b1'. Otherwise, +| returns 0. +*----------------------------------------------------------------------------*/ + +BX_CPP_INLINE int lt128(Bit64u a0, Bit64u a1, Bit64u b0, Bit64u b1) +{ + return (a0 < b0) || ((a0 == b0) && (a1 < b1)); +} + +#endif /* FLOATX80 */ + +/*---------------------------------------------------------------------------- +| Multiplies the 128-bit value formed by concatenating `a0' and `a1' by +| `b' to obtain a 192-bit product. The product is broken into three 64-bit +| pieces which are stored at the locations pointed to by `z0Ptr', `z1Ptr', and +| `z2Ptr'. +*----------------------------------------------------------------------------*/ + +BX_CPP_INLINE void mul128By64To192( + Bit64u a0, + Bit64u a1, + Bit64u b, + Bit64u *z0Ptr, + Bit64u *z1Ptr, + Bit64u *z2Ptr +) +{ + Bit64u z0, z1, z2, more1; + + mul64To128(a1, b, &z1, &z2); + mul64To128(a0, b, &z0, &more1); + add128(z0, more1, 0, z1, &z0, &z1); + *z2Ptr = z2; + *z1Ptr = z1; + *z0Ptr = z0; +} + +#ifdef FLOAT128 + +/*---------------------------------------------------------------------------- +| Multiplies the 128-bit value formed by concatenating `a0' and `a1' to the +| 128-bit value formed by concatenating `b0' and `b1' to obtain a 256-bit +| product. The product is broken into four 64-bit pieces which are stored at +| the locations pointed to by `z0Ptr', `z1Ptr', `z2Ptr', and `z3Ptr'. +*----------------------------------------------------------------------------*/ + +BX_CPP_INLINE void mul128To256( + Bit64u a0, + Bit64u a1, + Bit64u b0, + Bit64u b1, + Bit64u *z0Ptr, + Bit64u *z1Ptr, + Bit64u *z2Ptr, + Bit64u *z3Ptr +) +{ + Bit64u z0, z1, z2, z3; + Bit64u more1, more2; + + mul64To128(a1, b1, &z2, &z3); + mul64To128(a1, b0, &z1, &more2); + add128(z1, more2, 0, z2, &z1, &z2); + mul64To128(a0, b0, &z0, &more1); + add128(z0, more1, 0, z1, &z0, &z1); + mul64To128(a0, b1, &more1, &more2); + add128(more1, more2, 0, z2, &more1, &z2); + add128(z0, z1, 0, more1, &z0, &z1); + *z3Ptr = z3; + *z2Ptr = z2; + *z1Ptr = z1; + *z0Ptr = z0; +} + + +/*---------------------------------------------------------------------------- +| Shifts the 192-bit value formed by concatenating `a0', `a1', and `a2' right +| by 64 _plus_ the number of bits given in `count'. The shifted result is +| at most 128 nonzero bits; these are broken into two 64-bit pieces which are +| stored at the locations pointed to by `z0Ptr' and `z1Ptr'. The bits shifted +| off form a third 64-bit result as follows: The _last_ bit shifted off is +| the most-significant bit of the extra result, and the other 63 bits of the +| extra result are all zero if and only if _all_but_the_last_ bits shifted off +| were all zero. This extra result is stored in the location pointed to by +| `z2Ptr'. The value of `count' can be arbitrarily large. +| (This routine makes more sense if `a0', `a1', and `a2' are considered +| to form a fixed-point value with binary point between `a1' and `a2'. This +| fixed-point value is shifted right by the number of bits given in `count', +| and the integer part of the result is returned at the locations pointed to +| by `z0Ptr' and `z1Ptr'. The fractional part of the result may be slightly +| corrupted as described above, and is returned at the location pointed to by +| `z2Ptr'.) +*----------------------------------------------------------------------------*/ + +BX_CPP_INLINE void shift128ExtraRightJamming( + Bit64u a0, + Bit64u a1, + Bit64u a2, + int count, + Bit64u *z0Ptr, + Bit64u *z1Ptr, + Bit64u *z2Ptr +) +{ + Bit64u z0, z1, z2; + int negCount = (-count) & 63; + + if (count == 0) { + z2 = a2; + z1 = a1; + z0 = a0; + } + else { + if (count < 64) { + z2 = a1<>count); + z0 = a0>>count; + } + else { + if (count == 64) { + z2 = a1; + z1 = a0; + } + else { + a2 |= a1; + if (count < 128) { + z2 = a0<>(count & 63); + } + else { + z2 = (count == 128) ? a0 : (a0 != 0); + z1 = 0; + } + } + z0 = 0; + } + z2 |= (a2 != 0); + } + *z2Ptr = z2; + *z1Ptr = z1; + *z0Ptr = z0; +} + +#endif /* FLOAT128 */ + +#endif diff --git a/src/cpu/softfloat/softfloat-muladd.cc b/src/cpu/softfloat/softfloat-muladd.cc new file mode 100644 index 000000000..7c9fec70e --- /dev/null +++ b/src/cpu/softfloat/softfloat-muladd.cc @@ -0,0 +1,558 @@ +/*============================================================================ +This C source file is part of the SoftFloat IEC/IEEE Floating-point Arithmetic +Package, Release 2b. + +Written by John R. Hauser. This work was made possible in part by the +International Computer Science Institute, located at Suite 600, 1947 Center +Street, Berkeley, California 94704. Funding was partially provided by the +National Science Foundation under grant MIP-9311980. The original version +of this code was written as part of a project to build a fixed-point vector +processor in collaboration with the University of California at Berkeley, +overseen by Profs. Nelson Morgan and John Wawrzynek. More information +is available through the Web page `http://www.cs.berkeley.edu/~jhauser/ +arithmetic/SoftFloat.html'. + +THIS SOFTWARE IS DISTRIBUTED AS IS, FOR FREE. Although reasonable effort has +been made to avoid it, THIS SOFTWARE MAY CONTAIN FAULTS THAT WILL AT TIMES +RESULT IN INCORRECT BEHAVIOR. USE OF THIS SOFTWARE IS RESTRICTED TO PERSONS +AND ORGANIZATIONS WHO CAN AND WILL TAKE FULL RESPONSIBILITY FOR ALL LOSSES, +COSTS, OR OTHER PROBLEMS THEY INCUR DUE TO THE SOFTWARE, AND WHO FURTHERMORE +EFFECTIVELY INDEMNIFY JOHN HAUSER AND THE INTERNATIONAL COMPUTER SCIENCE +INSTITUTE (possibly via similar legal warning) AGAINST ALL LOSSES, COSTS, OR +OTHER PROBLEMS INCURRED BY THEIR CUSTOMERS AND CLIENTS DUE TO THE SOFTWARE. + +Derivative works are acceptable, even for commercial purposes, so long as +(1) the source code for the derivative work includes prominent notice that +the work is derivative, and (2) the source code includes prominent notice with +these four paragraphs for those parts of this code that are retained. +=============================================================================*/ + +/*============================================================================ + * This code is based on QEMU patch by Peter Maydell + * Adapted for Bochs (x86 achitecture simulator) by + * Stanislav Shwartsman [sshwarts at sourceforge net] + * ==========================================================================*/ + +#include "softfloat.h" +#include "softfloat-round-pack.h" + +/*---------------------------------------------------------------------------- +| Primitive arithmetic functions, including multi-word arithmetic, and +| division and square root approximations. (Can be specialized to target +| if desired). +*----------------------------------------------------------------------------*/ +#include "softfloat-macros.h" + +/*---------------------------------------------------------------------------- +| Functions and definitions to determine: (1) whether tininess for underflow +| is detected before or after rounding by default, (2) what (if anything) +| happens when exceptions are raised, (3) how signaling NaNs are distinguished +| from quiet NaNs, (4) the default generated quiet NaNs, and (5) how NaNs +| are propagated from function inputs to output. These details are target- +| specific. +*----------------------------------------------------------------------------*/ +#include "softfloat-specialize.h" + +/*---------------------------------------------------------------------------- +| Takes three single-precision floating-point values `a', `b' and `c', one of +| which is a NaN, and returns the appropriate NaN result. If any of `a', +| `b' or `c' is a signaling NaN, the invalid exception is raised. +| The input infzero indicates whether a*b was 0*inf or inf*0 (in which case +| obviously c is a NaN, and whether to propagate c or some other NaN is +| implementation defined). +*----------------------------------------------------------------------------*/ + +static float32 propagateFloat32MulAddNaN(float32 a, float32 b, float32 c, struct float_status_t *status) +{ + int aIsNaN = float32_is_nan(a); + int bIsNaN = float32_is_nan(b); + + int aIsSignalingNaN = float32_is_signaling_nan(a); + int bIsSignalingNaN = float32_is_signaling_nan(b); + int cIsSignalingNaN = float32_is_signaling_nan(c); + + a |= 0x00400000; + b |= 0x00400000; + c |= 0x00400000; + + if (aIsSignalingNaN | bIsSignalingNaN | cIsSignalingNaN) + float_raise(status, float_flag_invalid); + + // operate according to float_first_operand_nan mode + if (aIsSignalingNaN | aIsNaN) { + return a; + } + else { + return (bIsSignalingNaN | bIsNaN) ? b : c; + } +} + +/*---------------------------------------------------------------------------- +| Takes three double-precision floating-point values `a', `b' and `c', one of +| which is a NaN, and returns the appropriate NaN result. If any of `a', +| `b' or `c' is a signaling NaN, the invalid exception is raised. +| The input infzero indicates whether a*b was 0*inf or inf*0 (in which case +| obviously c is a NaN, and whether to propagate c or some other NaN is +| implementation defined). +*----------------------------------------------------------------------------*/ + +static float64 propagateFloat64MulAddNaN(float64 a, float64 b, float64 c, struct float_status_t *status) +{ + int aIsNaN = float64_is_nan(a); + int bIsNaN = float64_is_nan(b); + + int aIsSignalingNaN = float64_is_signaling_nan(a); + int bIsSignalingNaN = float64_is_signaling_nan(b); + int cIsSignalingNaN = float64_is_signaling_nan(c); + + a |= BX_CONST64(0x0008000000000000); + b |= BX_CONST64(0x0008000000000000); + c |= BX_CONST64(0x0008000000000000); + + if (aIsSignalingNaN | bIsSignalingNaN | cIsSignalingNaN) + float_raise(status, float_flag_invalid); + + // operate according to float_first_operand_nan mode + if (aIsSignalingNaN | aIsNaN) { + return a; + } + else { + return (bIsSignalingNaN | bIsNaN) ? b : c; + } +} + +/*---------------------------------------------------------------------------- +| Returns the result of multiplying the single-precision floating-point values +| `a' and `b' then adding 'c', with no intermediate rounding step after the +| multiplication. The operation is performed according to the IEC/IEEE +| Standard for Binary Floating-Point Arithmetic 754-2008. +| The flags argument allows the caller to select negation of the +| addend, the intermediate product, or the final result. (The difference +| between this and having the caller do a separate negation is that negating +| externally will flip the sign bit on NaNs.) +*----------------------------------------------------------------------------*/ + +float32 float32_muladd(float32 a, float32 b, float32 c, int flags, struct float_status_t *status) +{ + int aSign, bSign, cSign, zSign; + Bit16s aExp, bExp, cExp, pExp, zExp; + Bit32u aSig, bSig, cSig; + int pInf, pZero, pSign; + Bit64u pSig64, cSig64, zSig64; + Bit32u pSig; + int shiftcount; + + aSig = extractFloat32Frac(a); + aExp = extractFloat32Exp(a); + aSign = extractFloat32Sign(a); + bSig = extractFloat32Frac(b); + bExp = extractFloat32Exp(b); + bSign = extractFloat32Sign(b); + cSig = extractFloat32Frac(c); + cExp = extractFloat32Exp(c); + cSign = extractFloat32Sign(c); + + /* It is implementation-defined whether the cases of (0,inf,qnan) + * and (inf,0,qnan) raise InvalidOperation or not (and what QNaN + * they return if they do), so we have to hand this information + * off to the target-specific pick-a-NaN routine. + */ + if (((aExp == 0xff) && aSig) || + ((bExp == 0xff) && bSig) || + ((cExp == 0xff) && cSig)) { + return propagateFloat32MulAddNaN(a, b, c, status); + } + + if (get_denormals_are_zeros(status)) { + if (aExp == 0) aSig = 0; + if (bExp == 0) bSig = 0; + if (cExp == 0) cSig = 0; + } + + int infzero = ((aExp == 0 && aSig == 0 && bExp == 0xff && bSig == 0) || + (aExp == 0xff && aSig == 0 && bExp == 0 && bSig == 0)); + + if (infzero) { + float_raise(status, float_flag_invalid); + return float32_default_nan; + } + + if (flags & float_muladd_negate_c) { + cSign ^= 1; + } + + /* Work out the sign and type of the product */ + pSign = aSign ^ bSign; + if (flags & float_muladd_negate_product) { + pSign ^= 1; + } + pInf = (aExp == 0xff) || (bExp == 0xff); + pZero = ((aExp | aSig) == 0) || ((bExp | bSig) == 0); + + if (cExp == 0xff) { + if (pInf && (pSign ^ cSign)) { + /* addition of opposite-signed infinities => InvalidOperation */ + float_raise(status, float_flag_invalid); + return float32_default_nan; + } + /* Otherwise generate an infinity of the same sign */ + if ((aSig && aExp == 0) || (bSig && bExp == 0)) { + float_raise(status, float_flag_denormal); + } + return packFloat32(cSign, 0xff, 0); + } + + if (pInf) { + if ((aSig && aExp == 0) || (bSig && bExp == 0) || (cSig && cExp == 0)) { + float_raise(status, float_flag_denormal); + } + return packFloat32(pSign, 0xff, 0); + } + + if (pZero) { + if (cExp == 0) { + if (cSig == 0) { + /* Adding two exact zeroes */ + if (pSign == cSign) { + zSign = pSign; + } else if (get_float_rounding_mode(status) == float_round_down) { + zSign = 1; + } else { + zSign = 0; + } + return packFloat32(zSign, 0, 0); + } + /* Exact zero plus a denormal */ + float_raise(status, float_flag_denormal); + if (get_flush_underflow_to_zero(status)) { + float_raise(status, float_flag_underflow | float_flag_inexact); + return packFloat32(cSign, 0, 0); + } + } + /* Zero plus something non-zero */ + return packFloat32(cSign, cExp, cSig); + } + + if (aExp == 0) { + float_raise(status, float_flag_denormal); + normalizeFloat32Subnormal(aSig, &aExp, &aSig); + } + if (bExp == 0) { + float_raise(status, float_flag_denormal); + normalizeFloat32Subnormal(bSig, &bExp, &bSig); + } + + /* Calculate the actual result a * b + c */ + + /* Multiply first; this is easy. */ + /* NB: we subtract 0x7e where float32_mul() subtracts 0x7f + * because we want the true exponent, not the "one-less-than" + * flavour that roundAndPackFloat32() takes. + */ + pExp = aExp + bExp - 0x7e; + aSig = (aSig | 0x00800000) << 7; + bSig = (bSig | 0x00800000) << 8; + pSig64 = (Bit64u)aSig * bSig; + if ((Bit64s)(pSig64 << 1) >= 0) { + pSig64 <<= 1; + pExp--; + } + + zSign = pSign; + + /* Now pSig64 is the significand of the multiply, with the explicit bit in + * position 62. + */ + if (cExp == 0) { + if (!cSig) { + /* Throw out the special case of c being an exact zero now */ + pSig = (Bit32u) shift64RightJamming(pSig64, 32); + return roundAndPackFloat32(zSign, pExp - 1, pSig, status); + } + float_raise(status, float_flag_denormal); + normalizeFloat32Subnormal(cSig, &cExp, &cSig); + } + + cSig64 = (Bit64u)cSig << 39; + cSig64 |= BX_CONST64(0x4000000000000000); + int expDiff = pExp - cExp; + + if (pSign == cSign) { + /* Addition */ + if (expDiff > 0) { + /* scale c to match p */ + cSig64 = shift64RightJamming(cSig64, expDiff); + zExp = pExp; + } else if (expDiff < 0) { + /* scale p to match c */ + pSig64 = shift64RightJamming(pSig64, -expDiff); + zExp = cExp; + } else { + /* no scaling needed */ + zExp = cExp; + } + /* Add significands and make sure explicit bit ends up in posn 62 */ + zSig64 = pSig64 + cSig64; + if ((Bit64s)zSig64 < 0) { + zSig64 = shift64RightJamming(zSig64, 1); + } else { + zExp--; + } + zSig64 = shift64RightJamming(zSig64, 32); + return roundAndPackFloat32(zSign, zExp, zSig64, status); + } else { + /* Subtraction */ + if (expDiff > 0) { + cSig64 = shift64RightJamming(cSig64, expDiff); + zSig64 = pSig64 - cSig64; + zExp = pExp; + } else if (expDiff < 0) { + pSig64 = shift64RightJamming(pSig64, -expDiff); + zSig64 = cSig64 - pSig64; + zExp = cExp; + zSign ^= 1; + } else { + zExp = pExp; + if (cSig64 < pSig64) { + zSig64 = pSig64 - cSig64; + } else if (pSig64 < cSig64) { + zSig64 = cSig64 - pSig64; + zSign ^= 1; + } else { + /* Exact zero */ + return packFloat32(get_float_rounding_mode(status) == float_round_down, 0, 0); + } + } + --zExp; + /* Do the equivalent of normalizeRoundAndPackFloat32() but + * starting with the significand in a Bit64u. + */ + shiftcount = countLeadingZeros64(zSig64) - 1; + zSig64 <<= shiftcount; + zExp -= shiftcount; + zSig64 = shift64RightJamming(zSig64, 32); + return roundAndPackFloat32(zSign, zExp, zSig64, status); + } +} + +/*---------------------------------------------------------------------------- +| Returns the result of multiplying the double-precision floating-point values +| `a' and `b' then adding 'c', with no intermediate rounding step after the +| multiplication. The operation is performed according to the IEC/IEEE +| Standard for Binary Floating-Point Arithmetic 754-2008. +| The flags argument allows the caller to select negation of the +| addend, the intermediate product, or the final result. (The difference +| between this and having the caller do a separate negation is that negating +| externally will flip the sign bit on NaNs.) +*----------------------------------------------------------------------------*/ + +float64 float64_muladd(float64 a, float64 b, float64 c, int flags, struct float_status_t *status) +{ + int aSign, bSign, cSign, zSign; + Bit16s aExp, bExp, cExp, pExp, zExp; + Bit64u aSig, bSig, cSig; + int pInf, pZero, pSign; + Bit64u pSig0, pSig1, cSig0, cSig1, zSig0, zSig1; + int shiftcount; + + aSig = extractFloat64Frac(a); + aExp = extractFloat64Exp(a); + aSign = extractFloat64Sign(a); + bSig = extractFloat64Frac(b); + bExp = extractFloat64Exp(b); + bSign = extractFloat64Sign(b); + cSig = extractFloat64Frac(c); + cExp = extractFloat64Exp(c); + cSign = extractFloat64Sign(c); + + /* It is implementation-defined whether the cases of (0,inf,qnan) + * and (inf,0,qnan) raise InvalidOperation or not (and what QNaN + * they return if they do), so we have to hand this information + * off to the target-specific pick-a-NaN routine. + */ + if (((aExp == 0x7ff) && aSig) || + ((bExp == 0x7ff) && bSig) || + ((cExp == 0x7ff) && cSig)) { + return propagateFloat64MulAddNaN(a, b, c, status); + } + + if (get_denormals_are_zeros(status)) { + if (aExp == 0) aSig = 0; + if (bExp == 0) bSig = 0; + if (cExp == 0) cSig = 0; + } + + int infzero = ((aExp == 0 && aSig == 0 && bExp == 0x7ff && bSig == 0) || + (aExp == 0x7ff && aSig == 0 && bExp == 0 && bSig == 0)); + + if (infzero) { + float_raise(status, float_flag_invalid); + return float64_default_nan; + } + + if (flags & float_muladd_negate_c) { + cSign ^= 1; + } + + /* Work out the sign and type of the product */ + pSign = aSign ^ bSign; + if (flags & float_muladd_negate_product) { + pSign ^= 1; + } + pInf = (aExp == 0x7ff) || (bExp == 0x7ff); + pZero = ((aExp | aSig) == 0) || ((bExp | bSig) == 0); + + if (cExp == 0x7ff) { + if (pInf && (pSign ^ cSign)) { + /* addition of opposite-signed infinities => InvalidOperation */ + float_raise(status, float_flag_invalid); + return float64_default_nan; + } + /* Otherwise generate an infinity of the same sign */ + if ((aSig && aExp == 0) || (bSig && bExp == 0)) { + float_raise(status, float_flag_denormal); + } + return packFloat64(cSign, 0x7ff, 0); + } + + if (pInf) { + if ((aSig && aExp == 0) || (bSig && bExp == 0) || (cSig && cExp == 0)) { + float_raise(status, float_flag_denormal); + } + return packFloat64(pSign, 0x7ff, 0); + } + + if (pZero) { + if (cExp == 0) { + if (cSig == 0) { + /* Adding two exact zeroes */ + if (pSign == cSign) { + zSign = pSign; + } else if (get_float_rounding_mode(status) == float_round_down) { + zSign = 1; + } else { + zSign = 0; + } + return packFloat64(zSign, 0, 0); + } + /* Exact zero plus a denormal */ + float_raise(status, float_flag_denormal); + if (get_flush_underflow_to_zero(status)) { + float_raise(status, float_flag_underflow | float_flag_inexact); + return packFloat64(cSign, 0, 0); + } + } + /* Zero plus something non-zero */ + return packFloat64(cSign, cExp, cSig); + } + + if (aExp == 0) { + float_raise(status, float_flag_denormal); + normalizeFloat64Subnormal(aSig, &aExp, &aSig); + } + if (bExp == 0) { + float_raise(status, float_flag_denormal); + normalizeFloat64Subnormal(bSig, &bExp, &bSig); + } + + /* Calculate the actual result a * b + c */ + + /* Multiply first; this is easy. */ + /* NB: we subtract 0x3fe where float64_mul() subtracts 0x3ff + * because we want the true exponent, not the "one-less-than" + * flavour that roundAndPackFloat64() takes. + */ + pExp = aExp + bExp - 0x3fe; + aSig = (aSig | BX_CONST64(0x0010000000000000))<<10; + bSig = (bSig | BX_CONST64(0x0010000000000000))<<11; + mul64To128(aSig, bSig, &pSig0, &pSig1); + if ((Bit64s)(pSig0 << 1) >= 0) { + shortShift128Left(pSig0, pSig1, 1, &pSig0, &pSig1); + pExp--; + } + + zSign = pSign; + + /* Now [pSig0:pSig1] is the significand of the multiply, with the explicit + * bit in position 126. + */ + if (cExp == 0) { + if (!cSig) { + /* Throw out the special case of c being an exact zero now */ + shift128RightJamming(pSig0, pSig1, 64, &pSig0, &pSig1); + return roundAndPackFloat64(zSign, pExp - 1, pSig1, status); + } + float_raise(status, float_flag_denormal); + normalizeFloat64Subnormal(cSig, &cExp, &cSig); + } + + cSig0 = cSig << 10; + cSig1 = 0; + cSig0 |= BX_CONST64(0x4000000000000000); + int expDiff = pExp - cExp; + + if (pSign == cSign) { + /* Addition */ + if (expDiff > 0) { + /* scale c to match p */ + shift128RightJamming(cSig0, cSig1, expDiff, &cSig0, &cSig1); + zExp = pExp; + } else if (expDiff < 0) { + /* scale p to match c */ + shift128RightJamming(pSig0, pSig1, -expDiff, &pSig0, &pSig1); + zExp = cExp; + } else { + /* no scaling needed */ + zExp = cExp; + } + /* Add significands and make sure explicit bit ends up in posn 126 */ + add128(pSig0, pSig1, cSig0, cSig1, &zSig0, &zSig1); + if ((Bit64s)zSig0 < 0) { + shift128RightJamming(zSig0, zSig1, 1, &zSig0, &zSig1); + } else { + zExp--; + } + shift128RightJamming(zSig0, zSig1, 64, &zSig0, &zSig1); + return roundAndPackFloat64(zSign, zExp, zSig1, status); + } else { + /* Subtraction */ + if (expDiff > 0) { + shift128RightJamming(cSig0, cSig1, expDiff, &cSig0, &cSig1); + sub128(pSig0, pSig1, cSig0, cSig1, &zSig0, &zSig1); + zExp = pExp; + } else if (expDiff < 0) { + shift128RightJamming(pSig0, pSig1, -expDiff, &pSig0, &pSig1); + sub128(cSig0, cSig1, pSig0, pSig1, &zSig0, &zSig1); + zExp = cExp; + zSign ^= 1; + } else { + zExp = pExp; + if (lt128(cSig0, cSig1, pSig0, pSig1)) { + sub128(pSig0, pSig1, cSig0, cSig1, &zSig0, &zSig1); + } else if (lt128(pSig0, pSig1, cSig0, cSig1)) { + sub128(cSig0, cSig1, pSig0, pSig1, &zSig0, &zSig1); + zSign ^= 1; + } else { + /* Exact zero */ + return packFloat64(get_float_rounding_mode(status) == float_round_down, 0, 0); + } + } + --zExp; + /* Do the equivalent of normalizeRoundAndPackFloat64() but + * starting with the significand in a pair of Bit64u. + */ + if (zSig0) { + shiftcount = countLeadingZeros64(zSig0) - 1; + shortShift128Left(zSig0, zSig1, shiftcount, &zSig0, &zSig1); + if (zSig1) { + zSig0 |= 1; + } + zExp -= shiftcount; + } else { + shiftcount = countLeadingZeros64(zSig1) - 1; + zSig0 = zSig1 << shiftcount; + zExp -= (shiftcount + 64); + } + return roundAndPackFloat64(zSign, zExp, zSig0, status); + } +} diff --git a/src/cpu/softfloat/softfloat-round-pack.cc b/src/cpu/softfloat/softfloat-round-pack.cc new file mode 100644 index 000000000..2b3965840 --- /dev/null +++ b/src/cpu/softfloat/softfloat-round-pack.cc @@ -0,0 +1,896 @@ +/*============================================================================ +This C source file is part of the SoftFloat IEC/IEEE Floating-point Arithmetic +Package, Release 2b. + +Written by John R. Hauser. This work was made possible in part by the +International Computer Science Institute, located at Suite 600, 1947 Center +Street, Berkeley, California 94704. Funding was partially provided by the +National Science Foundation under grant MIP-9311980. The original version +of this code was written as part of a project to build a fixed-point vector +processor in collaboration with the University of California at Berkeley, +overseen by Profs. Nelson Morgan and John Wawrzynek. More information +is available through the Web page `http://www.cs.berkeley.edu/~jhauser/ +arithmetic/SoftFloat.html'. + +THIS SOFTWARE IS DISTRIBUTED AS IS, FOR FREE. Although reasonable effort has +been made to avoid it, THIS SOFTWARE MAY CONTAIN FAULTS THAT WILL AT TIMES +RESULT IN INCORRECT BEHAVIOR. USE OF THIS SOFTWARE IS RESTRICTED TO PERSONS +AND ORGANIZATIONS WHO CAN AND WILL TAKE FULL RESPONSIBILITY FOR ALL LOSSES, +COSTS, OR OTHER PROBLEMS THEY INCUR DUE TO THE SOFTWARE, AND WHO FURTHERMORE +EFFECTIVELY INDEMNIFY JOHN HAUSER AND THE INTERNATIONAL COMPUTER SCIENCE +INSTITUTE (possibly via similar legal warning) AGAINST ALL LOSSES, COSTS, OR +OTHER PROBLEMS INCURRED BY THEIR CUSTOMERS AND CLIENTS DUE TO THE SOFTWARE. + +Derivative works are acceptable, even for commercial purposes, so long as +(1) the source code for the derivative work includes prominent notice that +the work is derivative, and (2) the source code includes prominent notice with +these four paragraphs for those parts of this code that are retained. +=============================================================================*/ + +#define FLOAT128 + +/*============================================================================ + * Adapted for Bochs (x86 achitecture simulator) by + * Stanislav Shwartsman [sshwarts at sourceforge net] + * ==========================================================================*/ + +#include "softfloat.h" +#include "softfloat-round-pack.h" + +/*---------------------------------------------------------------------------- +| Primitive arithmetic functions, including multi-word arithmetic, and +| division and square root approximations. (Can be specialized to target +| if desired). +*----------------------------------------------------------------------------*/ +#include "softfloat-macros.h" + +/*---------------------------------------------------------------------------- +| Functions and definitions to determine: (1) whether tininess for underflow +| is detected before or after rounding by default, (2) what (if anything) +| happens when exceptions are raised, (3) how signaling NaNs are distinguished +| from quiet NaNs, (4) the default generated quiet NaNs, and (5) how NaNs +| are propagated from function inputs to output. These details are target- +| specific. +*----------------------------------------------------------------------------*/ +#include "softfloat-specialize.h" + +/*---------------------------------------------------------------------------- +| Takes a 64-bit fixed-point value `absZ' with binary point between bits 6 +| and 7, and returns the properly rounded 32-bit integer corresponding to the +| input. If `zSign' is 1, the input is negated before being converted to an +| integer. Bit 63 of `absZ' must be zero. Ordinarily, the fixed-point input +| is simply rounded to an integer, with the inexact exception raised if the +| input cannot be represented exactly as an integer. However, if the fixed- +| point input is too large, the invalid exception is raised and the integer +| indefinite value is returned. +*----------------------------------------------------------------------------*/ + +Bit32s roundAndPackInt32(int zSign, Bit64u exactAbsZ, struct float_status_t *status) +{ + int roundingMode = get_float_rounding_mode(status); + int roundNearestEven = (roundingMode == float_round_nearest_even); + int roundIncrement = 0x40; + if (! roundNearestEven) { + if (roundingMode == float_round_to_zero) roundIncrement = 0; + else { + roundIncrement = 0x7F; + if (zSign) { + if (roundingMode == float_round_up) roundIncrement = 0; + } + else { + if (roundingMode == float_round_down) roundIncrement = 0; + } + } + } + int roundBits = (int)(exactAbsZ & 0x7F); + Bit64u absZ = (exactAbsZ + roundIncrement)>>7; + absZ &= ~(((roundBits ^ 0x40) == 0) & roundNearestEven); + Bit32s z = (Bit32s) absZ; + if (zSign) z = -z; + if ((absZ>>32) || (z && ((z < 0) ^ zSign))) { + float_raise(status, float_flag_invalid); + return (Bit32s)(int32_indefinite); + } + if (roundBits) { + float_raise(status, float_flag_inexact); + if ((absZ << 7) > exactAbsZ) + set_float_rounding_up(status); + } + return z; +} + +/*---------------------------------------------------------------------------- +| Takes the 128-bit fixed-point value formed by concatenating `absZ0' and +| `absZ1', with binary point between bits 63 and 64 (between the input words), +| and returns the properly rounded 64-bit integer corresponding to the input. +| If `zSign' is 1, the input is negated before being converted to an integer. +| Ordinarily, the fixed-point input is simply rounded to an integer, with +| the inexact exception raised if the input cannot be represented exactly as +| an integer. However, if the fixed-point input is too large, the invalid +| exception is raised and the integer indefinite value is returned. +*----------------------------------------------------------------------------*/ + +Bit64s roundAndPackInt64(int zSign, Bit64u absZ0, Bit64u absZ1, struct float_status_t *status) +{ + Bit64s z; + int roundingMode = get_float_rounding_mode(status); + int roundNearestEven = (roundingMode == float_round_nearest_even); + int increment = ((Bit64s) absZ1 < 0); + if (! roundNearestEven) { + if (roundingMode == float_round_to_zero) increment = 0; + else { + if (zSign) { + increment = (roundingMode == float_round_down) && absZ1; + } + else { + increment = (roundingMode == float_round_up) && absZ1; + } + } + } + Bit64u exactAbsZ0 = absZ0; + if (increment) { + ++absZ0; + if (absZ0 == 0) goto overflow; + absZ0 &= ~(((Bit64u) (absZ1<<1) == 0) & roundNearestEven); + } + z = absZ0; + if (zSign) z = -z; + if (z && ((z < 0) ^ zSign)) { + overflow: + float_raise(status, float_flag_invalid); + return (Bit64s)(int64_indefinite); + } + if (absZ1) { + float_raise(status, float_flag_inexact); + if (absZ0 > exactAbsZ0) + set_float_rounding_up(status); + } + return z; +} + +/*---------------------------------------------------------------------------- +| Takes the 128-bit fixed-point value formed by concatenating `absZ0' and +| `absZ1', with binary point between bits 63 and 64 (between the input words), +| and returns the properly rounded 64-bit unsigned integer corresponding to the +| input. Ordinarily, the fixed-point input is simply rounded to an integer, +| with the inexact exception raised if the input cannot be represented exactly +| as an integer. However, if the fixed-point input is too large, the invalid +| exception is raised and the largest unsigned integer is returned. +*----------------------------------------------------------------------------*/ + +Bit64u roundAndPackUint64(int zSign, Bit64u absZ0, Bit64u absZ1, struct float_status_t *status) +{ + int roundingMode = get_float_rounding_mode(status); + int roundNearestEven = (roundingMode == float_round_nearest_even); + int increment = ((Bit64s) absZ1 < 0); + if (!roundNearestEven) { + if (roundingMode == float_round_to_zero) { + increment = 0; + } else if (absZ1) { + if (zSign) { + increment = (roundingMode == float_round_down) && absZ1; + } else { + increment = (roundingMode == float_round_up) && absZ1; + } + } + } + if (increment) { + ++absZ0; + if (absZ0 == 0) { + float_raise(status, float_flag_invalid); + return uint64_indefinite; + } + absZ0 &= ~(((Bit64u) (absZ1<<1) == 0) & roundNearestEven); + } + + if (zSign && absZ0) { + float_raise(status, float_flag_invalid); + return uint64_indefinite; + } + + if (absZ1) { + float_raise(status, float_flag_inexact); + } + return absZ0; +} + +#ifdef FLOAT16 + +/*---------------------------------------------------------------------------- +| Normalizes the subnormal half-precision floating-point value represented +| by the denormalized significand `aSig'. The normalized exponent and +| significand are stored at the locations pointed to by `zExpPtr' and +| `zSigPtr', respectively. +*----------------------------------------------------------------------------*/ + +void normalizeFloat16Subnormal(Bit16u aSig, Bit16s *zExpPtr, Bit16u *zSigPtr) +{ + int shiftCount = countLeadingZeros16(aSig) - 5; + *zSigPtr = aSig<> 4; + zSigRound &= ~(((roundBits ^ 0x10) == 0) & roundNearestEven); + if (zSigRound == 0) zExp = 0; + return packFloat16(zSign, zExp, zSigRound); +} + +#endif + +/*---------------------------------------------------------------------------- +| Normalizes the subnormal single-precision floating-point value represented +| by the denormalized significand `aSig'. The normalized exponent and +| significand are stored at the locations pointed to by `zExpPtr' and +| `zSigPtr', respectively. +*----------------------------------------------------------------------------*/ + +void normalizeFloat32Subnormal(Bit32u aSig, Bit16s *zExpPtr, Bit32u *zSigPtr) +{ + int shiftCount = countLeadingZeros32(aSig) - 8; + *zSigPtr = aSig<> 7; + zSigRound &= ~(((roundBits ^ 0x40) == 0) & roundNearestEven); + if (zSigRound == 0) zExp = 0; + if (roundBits) { + float_raise(status, float_flag_inexact); + if ((zSigRound << 7) > zSig) set_float_rounding_up(status); + } + return packFloat32(zSign, zExp, zSigRound); +} + +/*---------------------------------------------------------------------------- +| Takes an abstract floating-point value having sign `zSign', exponent `zExp', +| and significand `zSig', and returns the proper single-precision floating- +| point value corresponding to the abstract input. This routine is just like +| `roundAndPackFloat32' except that `zSig' does not have to be normalized. +| Bit 31 of `zSig' must be zero, and `zExp' must be 1 less than the ``true'' +| floating-point exponent. +*----------------------------------------------------------------------------*/ + +float32 normalizeRoundAndPackFloat32(int zSign, Bit16s zExp, Bit32u zSig, struct float_status_t *status) +{ + int shiftCount = countLeadingZeros32(zSig) - 1; + return roundAndPackFloat32(zSign, zExp - shiftCount, zSig<>10; + zSigRound &= ~(((roundBits ^ 0x200) == 0) & roundNearestEven); + if (zSigRound == 0) zExp = 0; + if (roundBits) { + float_raise(status, float_flag_inexact); + if ((zSigRound << 10) > zSig) set_float_rounding_up(status); + } + return packFloat64(zSign, zExp, zSigRound); +} + +/*---------------------------------------------------------------------------- +| Takes an abstract floating-point value having sign `zSign', exponent `zExp', +| and significand `zSig', and returns the proper double-precision floating- +| point value corresponding to the abstract input. This routine is just like +| `roundAndPackFloat64' except that `zSig' does not have to be normalized. +| Bit 63 of `zSig' must be zero, and `zExp' must be 1 less than the ``true'' +| floating-point exponent. +*----------------------------------------------------------------------------*/ + +float64 normalizeRoundAndPackFloat64(int zSign, Bit16s zExp, Bit64u zSig, struct float_status_t *status) +{ + int shiftCount = countLeadingZeros64(zSig) - 1; + return roundAndPackFloat64(zSign, zExp - shiftCount, zSig< zSigExact) set_float_rounding_up(status); + } + return packFloatx80(zSign, zExp, zSig0); + } + } + if (roundBits) float_raise(status, float_flag_inexact); + zSigExact = zSig0; + zSig0 += roundIncrement; + if (zSig0 < roundIncrement) { + // Basically scale by shifting right and keep overflow + ++zExp; + zSig0 = BX_CONST64(0x8000000000000000); + zSigExact >>= 1; // must scale also, or else later tests will fail + } + roundIncrement = roundMask + 1; + if (roundNearestEven && (roundBits<<1 == roundIncrement)) + roundMask |= roundIncrement; + zSig0 &= ~roundMask; + if (zSig0 > zSigExact) set_float_rounding_up(status); + if (zSig0 == 0) zExp = 0; + return packFloatx80(zSign, zExp, zSig0); + precision80: + increment = ((Bit64s) zSig1 < 0); + if (! roundNearestEven) { + if (roundingMode == float_round_to_zero) increment = 0; + else { + if (zSign) { + increment = (roundingMode == float_round_down) && zSig1; + } + else { + increment = (roundingMode == float_round_up) && zSig1; + } + } + } + if (0x7FFD <= (Bit32u) (zExp - 1)) { + if ((0x7FFE < zExp) + || ((zExp == 0x7FFE) + && (zSig0 == BX_CONST64(0xFFFFFFFFFFFFFFFF)) + && increment)) + { + roundMask = 0; + overflow: + float_raise(status, float_flag_overflow | float_flag_inexact); + if ((roundingMode == float_round_to_zero) + || (zSign && (roundingMode == float_round_up)) + || (! zSign && (roundingMode == float_round_down))) + { + return packFloatx80(zSign, 0x7FFE, ~roundMask); + } + set_float_rounding_up(status); + return packFloatx80(zSign, 0x7FFF, BX_CONST64(0x8000000000000000)); + } + if (zExp <= 0) { + int isTiny = (zExp < 0) || (! increment) + || (zSig0 < BX_CONST64(0xFFFFFFFFFFFFFFFF)); + shift64ExtraRightJamming(zSig0, zSig1, 1 - zExp, &zSig0, &zSig1); + zExp = 0; + if (isTiny) { + if (zSig1 || (zSig0 && !float_exception_masked(status, float_flag_underflow))) + float_raise(status, float_flag_underflow); + } + if (zSig1) float_raise(status, float_flag_inexact); + if (roundNearestEven) increment = ((Bit64s) zSig1 < 0); + else { + if (zSign) { + increment = (roundingMode == float_round_down) && zSig1; + } else { + increment = (roundingMode == float_round_up) && zSig1; + } + } + if (increment) { + zSigExact = zSig0++; + zSig0 &= ~(((Bit64u) (zSig1<<1) == 0) & roundNearestEven); + if (zSig0 > zSigExact) set_float_rounding_up(status); + if ((Bit64s) zSig0 < 0) zExp = 1; + } + return packFloatx80(zSign, zExp, zSig0); + } + } + if (zSig1) float_raise(status, float_flag_inexact); + if (increment) { + zSigExact = zSig0++; + if (zSig0 == 0) { + zExp++; + zSig0 = BX_CONST64(0x8000000000000000); + zSigExact >>= 1; // must scale also, or else later tests will fail + } + else { + zSig0 &= ~(((Bit64u) (zSig1<<1) == 0) & roundNearestEven); + } + if (zSig0 > zSigExact) set_float_rounding_up(status); + } + else { + if (zSig0 == 0) zExp = 0; + } + return packFloatx80(zSign, zExp, zSig0); +} + +floatx80 roundAndPackFloatx80(int roundingPrecision, + int zSign, Bit32s zExp, Bit64u zSig0, Bit64u zSig1, struct float_status_t *status) +{ + struct float_status_t *round_status = status; + floatx80 result = SoftFloatRoundAndPackFloatx80(roundingPrecision, zSign, zExp, zSig0, zSig1, status); + + // bias unmasked undeflow + if (status->float_exception_flags & ~status->float_exception_masks & float_flag_underflow) { + float_raise(round_status, float_flag_underflow); + return SoftFloatRoundAndPackFloatx80(roundingPrecision, zSign, zExp + 0x6000, zSig0, zSig1, status = round_status); + } + + // bias unmasked overflow + if (status->float_exception_flags & ~status->float_exception_masks & float_flag_overflow) { + float_raise(round_status, float_flag_overflow); + return SoftFloatRoundAndPackFloatx80(roundingPrecision, zSign, zExp - 0x6000, zSig0, zSig1, status = round_status); + } + + return result; +} + +/*---------------------------------------------------------------------------- +| Takes an abstract floating-point value having sign `zSign', exponent +| `zExp', and significand formed by the concatenation of `zSig0' and `zSig1', +| and returns the proper extended double-precision floating-point value +| corresponding to the abstract input. This routine is just like +| `roundAndPackFloatx80' except that the input significand does not have to be +| normalized. +*----------------------------------------------------------------------------*/ + +floatx80 normalizeRoundAndPackFloatx80(int roundingPrecision, + int zSign, Bit32s zExp, Bit64u zSig0, Bit64u zSig1, struct float_status_t *status) +{ + if (zSig0 == 0) { + zSig0 = zSig1; + zSig1 = 0; + zExp -= 64; + } + int shiftCount = countLeadingZeros64(zSig0); + shortShift128Left(zSig0, zSig1, shiftCount, &zSig0, &zSig1); + zExp -= shiftCount; + return + roundAndPackFloatx80(roundingPrecision, zSign, zExp, zSig0, zSig1, status); +} + +#endif + +#ifdef FLOAT128 + +/*---------------------------------------------------------------------------- +| Normalizes the subnormal quadruple-precision floating-point value +| represented by the denormalized significand formed by the concatenation of +| `aSig0' and `aSig1'. The normalized exponent is stored at the location +| pointed to by `zExpPtr'. The most significant 49 bits of the normalized +| significand are stored at the location pointed to by `zSig0Ptr', and the +| least significant 64 bits of the normalized significand are stored at the +| location pointed to by `zSig1Ptr'. +*----------------------------------------------------------------------------*/ + +void normalizeFloat128Subnormal( + Bit64u aSig0, Bit64u aSig1, Bit32s *zExpPtr, Bit64u *zSig0Ptr, Bit64u *zSig1Ptr) +{ + int shiftCount; + + if (aSig0 == 0) { + shiftCount = countLeadingZeros64(aSig1) - 15; + if (shiftCount < 0) { + *zSig0Ptr = aSig1 >>(-shiftCount); + *zSig1Ptr = aSig1 << (shiftCount & 63); + } + else { + *zSig0Ptr = aSig1 << shiftCount; + *zSig1Ptr = 0; + } + *zExpPtr = - shiftCount - 63; + } + else { + shiftCount = countLeadingZeros64(aSig0) - 15; + shortShift128Left(aSig0, aSig1, shiftCount, zSig0Ptr, zSig1Ptr); + *zExpPtr = 1 - shiftCount; + } +} + +/*---------------------------------------------------------------------------- +| Takes an abstract floating-point value having sign `zSign', exponent `zExp', +| and extended significand formed by the concatenation of `zSig0', `zSig1', +| and `zSig2', and returns the proper quadruple-precision floating-point value +| corresponding to the abstract input. Ordinarily, the abstract value is +| simply rounded and packed into the quadruple-precision format, with the +| inexact exception raised if the abstract input cannot be represented +| exactly. However, if the abstract value is too large, the overflow and +| inexact exceptions are raised and an infinity or maximal finite value is +| returned. If the abstract value is too small, the input value is rounded to +| a subnormal number, and the underflow and inexact exceptions are raised if +| the abstract input cannot be represented exactly as a subnormal quadruple- +| precision floating-point number. +| The input significand must be normalized or smaller. If the input +| significand is not normalized, `zExp' must be 0; in that case, the result +| returned is a subnormal number, and it must not require rounding. In the +| usual case that the input significand is normalized, `zExp' must be 1 less +| than the ``true'' floating-point exponent. The handling of underflow and +| overflow follows the IEC/IEEE Standard for Binary Floating-Point Arithmetic. +*----------------------------------------------------------------------------*/ + +float128 roundAndPackFloat128( + int zSign, Bit32s zExp, Bit64u zSig0, Bit64u zSig1, Bit64u zSig2, struct float_status_t *status) +{ + int increment = ((Bit64s) zSig2 < 0); + if (0x7FFD <= (Bit32u) zExp) { + if ((0x7FFD < zExp) + || ((zExp == 0x7FFD) + && eq128(BX_CONST64(0x0001FFFFFFFFFFFF), + BX_CONST64(0xFFFFFFFFFFFFFFFF), zSig0, zSig1) + && increment)) + { + float_raise(status, float_flag_overflow | float_flag_inexact); + return packFloat128Four(zSign, 0x7FFF, 0, 0); + } + if (zExp < 0) { + int isTiny = (zExp < -1) + || ! increment + || lt128(zSig0, zSig1, + BX_CONST64(0x0001FFFFFFFFFFFF), + BX_CONST64(0xFFFFFFFFFFFFFFFF)); + shift128ExtraRightJamming( + zSig0, zSig1, zSig2, -zExp, &zSig0, &zSig1, &zSig2); + zExp = 0; + if (isTiny && zSig2) float_raise(status, float_flag_underflow); + increment = ((Bit64s) zSig2 < 0); + } + } + if (zSig2) float_raise(status, float_flag_inexact); + if (increment) { + add128(zSig0, zSig1, 0, 1, &zSig0, &zSig1); + zSig1 &= ~((zSig2 + zSig2 == 0) & 1); + } + else { + if ((zSig0 | zSig1) == 0) zExp = 0; + } + return packFloat128Four(zSign, zExp, zSig0, zSig1); +} + +/*---------------------------------------------------------------------------- +| Takes an abstract floating-point value having sign `zSign', exponent `zExp', +| and significand formed by the concatenation of `zSig0' and `zSig1', and +| returns the proper quadruple-precision floating-point value corresponding +| to the abstract input. This routine is just like `roundAndPackFloat128' +| except that the input significand has fewer bits and does not have to be +| normalized. In all cases, `zExp' must be 1 less than the ``true'' floating- +| point exponent. +*----------------------------------------------------------------------------*/ + +float128 normalizeRoundAndPackFloat128( + int zSign, Bit32s zExp, Bit64u zSig0, Bit64u zSig1, struct float_status_t *status) +{ + Bit64u zSig2; + + if (zSig0 == 0) { + zSig0 = zSig1; + zSig1 = 0; + zExp -= 64; + } + int shiftCount = countLeadingZeros64(zSig0) - 15; + if (0 <= shiftCount) { + zSig2 = 0; + shortShift128Left(zSig0, zSig1, shiftCount, &zSig0, &zSig1); + } + else { + shift128ExtraRightJamming( + zSig0, zSig1, 0, -shiftCount, &zSig0, &zSig1, &zSig2); + } + zExp -= shiftCount; + return roundAndPackFloat128(zSign, zExp, zSig0, zSig1, zSig2, status); +} + +#endif diff --git a/src/cpu/softfloat/softfloat-round-pack.h b/src/cpu/softfloat/softfloat-round-pack.h new file mode 100644 index 000000000..1422aaea6 --- /dev/null +++ b/src/cpu/softfloat/softfloat-round-pack.h @@ -0,0 +1,309 @@ +/*============================================================================ +This C source file is part of the SoftFloat IEC/IEEE Floating-point Arithmetic +Package, Release 2b. + +Written by John R. Hauser. This work was made possible in part by the +International Computer Science Institute, located at Suite 600, 1947 Center +Street, Berkeley, California 94704. Funding was partially provided by the +National Science Foundation under grant MIP-9311980. The original version +of this code was written as part of a project to build a fixed-point vector +processor in collaboration with the University of California at Berkeley, +overseen by Profs. Nelson Morgan and John Wawrzynek. More information +is available through the Web page `http://www.cs.berkeley.edu/~jhauser/ +arithmetic/SoftFloat.html'. + +THIS SOFTWARE IS DISTRIBUTED AS IS, FOR FREE. Although reasonable effort has +been made to avoid it, THIS SOFTWARE MAY CONTAIN FAULTS THAT WILL AT TIMES +RESULT IN INCORRECT BEHAVIOR. USE OF THIS SOFTWARE IS RESTRICTED TO PERSONS +AND ORGANIZATIONS WHO CAN AND WILL TAKE FULL RESPONSIBILITY FOR ALL LOSSES, +COSTS, OR OTHER PROBLEMS THEY INCUR DUE TO THE SOFTWARE, AND WHO FURTHERMORE +EFFECTIVELY INDEMNIFY JOHN HAUSER AND THE INTERNATIONAL COMPUTER SCIENCE +INSTITUTE (possibly via similar legal warning) AGAINST ALL LOSSES, COSTS, OR +OTHER PROBLEMS INCURRED BY THEIR CUSTOMERS AND CLIENTS DUE TO THE SOFTWARE. + +Derivative works are acceptable, even for commercial purposes, so long as +(1) the source code for the derivative work includes prominent notice that +the work is derivative, and (2) the source code includes prominent notice with +these four paragraphs for those parts of this code that are retained. +=============================================================================*/ + +/*============================================================================ + * Adapted for Bochs (x86 achitecture simulator) by + * Stanislav Shwartsman [sshwarts at sourceforge net] + * ==========================================================================*/ + +#ifndef _SOFTFLOAT_ROUND_PACK_H_ +#define _SOFTFLOAT_ROUND_PACK_H_ + +#include "softfloat.h" + +/*---------------------------------------------------------------------------- +| Takes a 64-bit fixed-point value `absZ' with binary point between bits 6 +| and 7, and returns the properly rounded 32-bit integer corresponding to the +| input. If `zSign' is 1, the input is negated before being converted to an +| integer. Bit 63 of `absZ' must be zero. Ordinarily, the fixed-point input +| is simply rounded to an integer, with the inexact exception raised if the +| input cannot be represented exactly as an integer. However, if the fixed- +| point input is too large, the invalid exception is raised and the integer +| indefinite value is returned. +*----------------------------------------------------------------------------*/ + +Bit32s roundAndPackInt32(int zSign, Bit64u absZ, struct float_status_t *status); + +/*---------------------------------------------------------------------------- +| Takes the 128-bit fixed-point value formed by concatenating `absZ0' and +| `absZ1', with binary point between bits 63 and 64 (between the input words), +| and returns the properly rounded 64-bit integer corresponding to the input. +| If `zSign' is 1, the input is negated before being converted to an integer. +| Ordinarily, the fixed-point input is simply rounded to an integer, with +| the inexact exception raised if the input cannot be represented exactly as +| an integer. However, if the fixed-point input is too large, the invalid +| exception is raised and the integer indefinite value is returned. +*----------------------------------------------------------------------------*/ + +Bit64s roundAndPackInt64(int zSign, Bit64u absZ0, Bit64u absZ1, struct float_status_t *status); + +/*---------------------------------------------------------------------------- +| Takes the 128-bit fixed-point value formed by concatenating `absZ0' and +| `absZ1', with binary point between bits 63 and 64 (between the input words), +| and returns the properly rounded 64-bit unsigned integer corresponding to the +| input. Ordinarily, the fixed-point input is simply rounded to an integer, +| with the inexact exception raised if the input cannot be represented exactly +| as an integer. However, if the fixed-point input is too large, the invalid +| exception is raised and the largest unsigned integer is returned. +*----------------------------------------------------------------------------*/ + +Bit64u roundAndPackUint64(int zSign, Bit64u absZ0, Bit64u absZ1, struct float_status_t *status); + +#ifdef FLOAT16 + +/*---------------------------------------------------------------------------- +| Normalizes the subnormal half-precision floating-point value represented +| by the denormalized significand `aSig'. The normalized exponent and +| significand are stored at the locations pointed to by `zExpPtr' and +| `zSigPtr', respectively. +*----------------------------------------------------------------------------*/ + +void normalizeFloat16Subnormal(Bit16u aSig, Bit16s *zExpPtr, Bit16u *zSigPtr); + +/*---------------------------------------------------------------------------- +| Takes an abstract floating-point value having sign `zSign', exponent `zExp', +| and significand `zSig', and returns the proper half-precision floating- +| point value corresponding to the abstract input. Ordinarily, the abstract +| value is simply rounded and packed into the half-precision format, with +| the inexact exception raised if the abstract input cannot be represented +| exactly. However, if the abstract value is too large, the overflow and +| inexact exceptions are raised and an infinity or maximal finite value is +| returned. If the abstract value is too small, the input value is rounded to +| a subnormal number, and the underflow and inexact exceptions are raised if +| the abstract input cannot be represented exactly as a subnormal single- +| precision floating-point number. +| The input significand `zSig' has its binary point between bits 14 +| and 13, which is 4 bits to the left of the usual location. This shifted +| significand must be normalized or smaller. If `zSig' is not normalized, +| `zExp' must be 0; in that case, the result returned is a subnormal number, +| and it must not require rounding. In the usual case that `zSig' is +| normalized, `zExp' must be 1 less than the ``true'' floating-point exponent. +| The handling of underflow and overflow follows the IEC/IEEE Standard for +| Binary Floating-Point Arithmetic. +*----------------------------------------------------------------------------*/ + +float16 roundAndPackFloat16(int zSign, Bit16s zExp, Bit16u zSig, struct float_status_t *status); + +#endif + +/*---------------------------------------------------------------------------- +| Normalizes the subnormal single-precision floating-point value represented +| by the denormalized significand `aSig'. The normalized exponent and +| significand are stored at the locations pointed to by `zExpPtr' and +| `zSigPtr', respectively. +*----------------------------------------------------------------------------*/ + +void normalizeFloat32Subnormal(Bit32u aSig, Bit16s *zExpPtr, Bit32u *zSigPtr); + +/*---------------------------------------------------------------------------- +| Takes an abstract floating-point value having sign `zSign', exponent `zExp', +| and significand `zSig', and returns the proper single-precision floating- +| point value corresponding to the abstract input. Ordinarily, the abstract +| value is simply rounded and packed into the single-precision format, with +| the inexact exception raised if the abstract input cannot be represented +| exactly. However, if the abstract value is too large, the overflow and +| inexact exceptions are raised and an infinity or maximal finite value is +| returned. If the abstract value is too small, the input value is rounded to +| a subnormal number, and the underflow and inexact exceptions are raised if +| the abstract input cannot be represented exactly as a subnormal single- +| precision floating-point number. +| The input significand `zSig' has its binary point between bits 30 +| and 29, which is 7 bits to the left of the usual location. This shifted +| significand must be normalized or smaller. If `zSig' is not normalized, +| `zExp' must be 0; in that case, the result returned is a subnormal number, +| and it must not require rounding. In the usual case that `zSig' is +| normalized, `zExp' must be 1 less than the ``true'' floating-point exponent. +| The handling of underflow and overflow follows the IEC/IEEE Standard for +| Binary Floating-Point Arithmetic. +*----------------------------------------------------------------------------*/ + +float32 roundAndPackFloat32(int zSign, Bit16s zExp, Bit32u zSig, struct float_status_t *status); + +/*---------------------------------------------------------------------------- +| Takes an abstract floating-point value having sign `zSign', exponent `zExp', +| and significand `zSig', and returns the proper single-precision floating- +| point value corresponding to the abstract input. This routine is just like +| `roundAndPackFloat32' except that `zSig' does not have to be normalized. +| Bit 31 of `zSig' must be zero, and `zExp' must be 1 less than the ``true'' +| floating-point exponent. +*----------------------------------------------------------------------------*/ + +float32 normalizeRoundAndPackFloat32(int zSign, Bit16s zExp, Bit32u zSig, struct float_status_t *status); + +/*---------------------------------------------------------------------------- +| Normalizes the subnormal double-precision floating-point value represented +| by the denormalized significand `aSig'. The normalized exponent and +| significand are stored at the locations pointed to by `zExpPtr' and +| `zSigPtr', respectively. +*----------------------------------------------------------------------------*/ + +void normalizeFloat64Subnormal(Bit64u aSig, Bit16s *zExpPtr, Bit64u *zSigPtr); + +/*---------------------------------------------------------------------------- +| Takes an abstract floating-point value having sign `zSign', exponent `zExp', +| and significand `zSig', and returns the proper double-precision floating- +| point value corresponding to the abstract input. Ordinarily, the abstract +| value is simply rounded and packed into the double-precision format, with +| the inexact exception raised if the abstract input cannot be represented +| exactly. However, if the abstract value is too large, the overflow and +| inexact exceptions are raised and an infinity or maximal finite value is +| returned. If the abstract value is too small, the input value is rounded +| to a subnormal number, and the underflow and inexact exceptions are raised +| if the abstract input cannot be represented exactly as a subnormal double- +| precision floating-point number. +| The input significand `zSig' has its binary point between bits 62 +| and 61, which is 10 bits to the left of the usual location. This shifted +| significand must be normalized or smaller. If `zSig' is not normalized, +| `zExp' must be 0; in that case, the result returned is a subnormal number, +| and it must not require rounding. In the usual case that `zSig' is +| normalized, `zExp' must be 1 less than the ``true'' floating-point exponent. +| The handling of underflow and overflow follows the IEC/IEEE Standard for +| Binary Floating-Point Arithmetic. +*----------------------------------------------------------------------------*/ + +float64 roundAndPackFloat64(int zSign, Bit16s zExp, Bit64u zSig, struct float_status_t *status); + +/*---------------------------------------------------------------------------- +| Takes an abstract floating-point value having sign `zSign', exponent `zExp', +| and significand `zSig', and returns the proper double-precision floating- +| point value corresponding to the abstract input. This routine is just like +| `roundAndPackFloat64' except that `zSig' does not have to be normalized. +| Bit 63 of `zSig' must be zero, and `zExp' must be 1 less than the ``true'' +| floating-point exponent. +*----------------------------------------------------------------------------*/ + +float64 normalizeRoundAndPackFloat64(int zSign, Bit16s zExp, Bit64u zSig, struct float_status_t *status); + +#ifdef FLOATX80 + +/*---------------------------------------------------------------------------- +| Normalizes the subnormal extended double-precision floating-point value +| represented by the denormalized significand `aSig'. The normalized exponent +| and significand are stored at the locations pointed to by `zExpPtr' and +| `zSigPtr', respectively. +*----------------------------------------------------------------------------*/ + +void normalizeFloatx80Subnormal(Bit64u aSig, Bit32s *zExpPtr, Bit64u *zSigPtr); + +/*---------------------------------------------------------------------------- +| Takes an abstract floating-point value having sign `zSign', exponent `zExp', +| and extended significand formed by the concatenation of `zSig0' and `zSig1', +| and returns the proper extended double-precision floating-point value +| corresponding to the abstract input. Ordinarily, the abstract value is +| rounded and packed into the extended double-precision format, with the +| inexact exception raised if the abstract input cannot be represented +| exactly. However, if the abstract value is too large, the overflow and +| inexact exceptions are raised and an infinity or maximal finite value is +| returned. If the abstract value is too small, the input value is rounded to +| a subnormal number, and the underflow and inexact exceptions are raised if +| the abstract input cannot be represented exactly as a subnormal extended +| double-precision floating-point number. +| If `roundingPrecision' is 32 or 64, the result is rounded to the same +| number of bits as single or double precision, respectively. Otherwise, the +| result is rounded to the full precision of the extended double-precision +| format. +| The input significand must be normalized or smaller. If the input +| significand is not normalized, `zExp' must be 0; in that case, the result +| returned is a subnormal number, and it must not require rounding. The +| handling of underflow and overflow follows the IEC/IEEE Standard for Binary +| Floating-Point Arithmetic. +*----------------------------------------------------------------------------*/ + +floatx80 roundAndPackFloatx80(int roundingPrecision, + int zSign, Bit32s zExp, Bit64u zSig0, Bit64u zSig1, struct float_status_t *status); + +/*---------------------------------------------------------------------------- +| Takes an abstract floating-point value having sign `zSign', exponent +| `zExp', and significand formed by the concatenation of `zSig0' and `zSig1', +| and returns the proper extended double-precision floating-point value +| corresponding to the abstract input. This routine is just like +| `roundAndPackFloatx80' except that the input significand does not have to be +| normalized. +*----------------------------------------------------------------------------*/ + +floatx80 normalizeRoundAndPackFloatx80(int roundingPrecision, + int zSign, Bit32s zExp, Bit64u zSig0, Bit64u zSig1, struct float_status_t *status); + +#endif // FLOATX80 + +#ifdef FLOAT128 + +/*---------------------------------------------------------------------------- +| Normalizes the subnormal quadruple-precision floating-point value +| represented by the denormalized significand formed by the concatenation of +| `aSig0' and `aSig1'. The normalized exponent is stored at the location +| pointed to by `zExpPtr'. The most significant 49 bits of the normalized +| significand are stored at the location pointed to by `zSig0Ptr', and the +| least significant 64 bits of the normalized significand are stored at the +| location pointed to by `zSig1Ptr'. +*----------------------------------------------------------------------------*/ + +void normalizeFloat128Subnormal( + Bit64u aSig0, Bit64u aSig1, Bit32s *zExpPtr, Bit64u *zSig0Ptr, Bit64u *zSig1Ptr); + +/*---------------------------------------------------------------------------- +| Takes an abstract floating-point value having sign `zSign', exponent `zExp', +| and extended significand formed by the concatenation of `zSig0', `zSig1', +| and `zSig2', and returns the proper quadruple-precision floating-point value +| corresponding to the abstract input. Ordinarily, the abstract value is +| simply rounded and packed into the quadruple-precision format, with the +| inexact exception raised if the abstract input cannot be represented +| exactly. However, if the abstract value is too large, the overflow and +| inexact exceptions are raised and an infinity or maximal finite value is +| returned. If the abstract value is too small, the input value is rounded to +| a subnormal number, and the underflow and inexact exceptions are raised if +| the abstract input cannot be represented exactly as a subnormal quadruple- +| precision floating-point number. +| The input significand must be normalized or smaller. If the input +| significand is not normalized, `zExp' must be 0; in that case, the result +| returned is a subnormal number, and it must not require rounding. In the +| usual case that the input significand is normalized, `zExp' must be 1 less +| than the ``true'' floating-point exponent. The handling of underflow and +| overflow follows the IEC/IEEE Standard for Binary Floating-Point Arithmetic. +*----------------------------------------------------------------------------*/ + +float128 roundAndPackFloat128( + int zSign, Bit32s zExp, Bit64u zSig0, Bit64u zSig1, Bit64u zSig2, struct float_status_t *status); + +/*---------------------------------------------------------------------------- +| Takes an abstract floating-point value having sign `zSign', exponent `zExp', +| and significand formed by the concatenation of `zSig0' and `zSig1', and +| returns the proper quadruple-precision floating-point value corresponding +| to the abstract input. This routine is just like `roundAndPackFloat128' +| except that the input significand has fewer bits and does not have to be +| normalized. In all cases, `zExp' must be 1 less than the ``true'' floating- +| point exponent. +*----------------------------------------------------------------------------*/ + +float128 normalizeRoundAndPackFloat128( + int zSign, Bit32s zExp, Bit64u zSig0, Bit64u zSig1, struct float_status_t *status); + +#endif // FLOAT128 + +#endif diff --git a/src/cpu/softfloat/softfloat-specialize.cc b/src/cpu/softfloat/softfloat-specialize.cc new file mode 100644 index 000000000..bf0d11144 --- /dev/null +++ b/src/cpu/softfloat/softfloat-specialize.cc @@ -0,0 +1,187 @@ +/*============================================================================ +This C source fragment is part of the SoftFloat IEC/IEEE Floating-point +Arithmetic Package, Release 2b. + +Written by John R. Hauser. This work was made possible in part by the +International Computer Science Institute, located at Suite 600, 1947 Center +Street, Berkeley, California 94704. Funding was partially provided by the +National Science Foundation under grant MIP-9311980. The original version +of this code was written as part of a project to build a fixed-point vector +processor in collaboration with the University of California at Berkeley, +overseen by Profs. Nelson Morgan and John Wawrzynek. More information +is available through the Web page `http://www.cs.berkeley.edu/~jhauser/ +arithmetic/SoftFloat.html'. + +THIS SOFTWARE IS DISTRIBUTED AS IS, FOR FREE. Although reasonable effort has +been made to avoid it, THIS SOFTWARE MAY CONTAIN FAULTS THAT WILL AT TIMES +RESULT IN INCORRECT BEHAVIOR. USE OF THIS SOFTWARE IS RESTRICTED TO PERSONS +AND ORGANIZATIONS WHO CAN AND WILL TAKE FULL RESPONSIBILITY FOR ALL LOSSES, +COSTS, OR OTHER PROBLEMS THEY INCUR DUE TO THE SOFTWARE, AND WHO FURTHERMORE +EFFECTIVELY INDEMNIFY JOHN HAUSER AND THE INTERNATIONAL COMPUTER SCIENCE +INSTITUTE (possibly via similar legal warning) AGAINST ALL LOSSES, COSTS, OR +OTHER PROBLEMS INCURRED BY THEIR CUSTOMERS AND CLIENTS DUE TO THE SOFTWARE. + +Derivative works are acceptable, even for commercial purposes, so long as +(1) the source code for the derivative work includes prominent notice that +the work is derivative, and (2) the source code includes prominent notice with +these four paragraphs for those parts of this code that are retained. +=============================================================================*/ + +#define FLOAT128 + +/*============================================================================ + * Adapted for Bochs (x86 achitecture simulator) by + * Stanislav Shwartsman [sshwarts at sourceforge net] + * ==========================================================================*/ + +#include "softfloat.h" +#include "softfloat-specialize.h" + +/*---------------------------------------------------------------------------- +| Takes two single-precision floating-point values `a' and `b', one of which +| is a NaN, and returns the appropriate NaN result. If either `a' or `b' is a +| signaling NaN, the invalid exception is raised. +*----------------------------------------------------------------------------*/ + +float32 propagateFloat32NaN(float32 a, float32 b, struct float_status_t *status) +{ + int aIsNaN, aIsSignalingNaN, bIsNaN, bIsSignalingNaN; + + aIsNaN = float32_is_nan(a); + aIsSignalingNaN = float32_is_signaling_nan(a); + bIsNaN = float32_is_nan(b); + bIsSignalingNaN = float32_is_signaling_nan(b); + a |= 0x00400000; + b |= 0x00400000; + if (aIsSignalingNaN | bIsSignalingNaN) float_raise(status, float_flag_invalid); + if (get_float_nan_handling_mode(status) == float_larger_significand_nan) { + if (aIsSignalingNaN) { + if (bIsSignalingNaN) goto returnLargerSignificand; + return bIsNaN ? b : a; + } + else if (aIsNaN) { + if (bIsSignalingNaN | ! bIsNaN) return a; + returnLargerSignificand: + if ((Bit32u) (a<<1) < (Bit32u) (b<<1)) return b; + if ((Bit32u) (b<<1) < (Bit32u) (a<<1)) return a; + return (a < b) ? a : b; + } + else { + return b; + } + } else { + return (aIsSignalingNaN | aIsNaN) ? a : b; + } +} + +/*---------------------------------------------------------------------------- +| Takes two double-precision floating-point values `a' and `b', one of which +| is a NaN, and returns the appropriate NaN result. If either `a' or `b' is a +| signaling NaN, the invalid exception is raised. +*----------------------------------------------------------------------------*/ + +float64 propagateFloat64NaN(float64 a, float64 b, struct float_status_t *status) +{ + int aIsNaN = float64_is_nan(a); + int aIsSignalingNaN = float64_is_signaling_nan(a); + int bIsNaN = float64_is_nan(b); + int bIsSignalingNaN = float64_is_signaling_nan(b); + a |= BX_CONST64(0x0008000000000000); + b |= BX_CONST64(0x0008000000000000); + if (aIsSignalingNaN | bIsSignalingNaN) float_raise(status, float_flag_invalid); + if (get_float_nan_handling_mode(status) == float_larger_significand_nan) { + if (aIsSignalingNaN) { + if (bIsSignalingNaN) goto returnLargerSignificand; + return bIsNaN ? b : a; + } + else if (aIsNaN) { + if (bIsSignalingNaN | ! bIsNaN) return a; + returnLargerSignificand: + if ((Bit64u) (a<<1) < (Bit64u) (b<<1)) return b; + if ((Bit64u) (b<<1) < (Bit64u) (a<<1)) return a; + return (a < b) ? a : b; + } + else { + return b; + } + } else { + return (aIsSignalingNaN | aIsNaN) ? a : b; + } +} + +#ifdef FLOATX80 + +/*---------------------------------------------------------------------------- +| Takes two extended double-precision floating-point values `a' and `b', one +| of which is a NaN, and returns the appropriate NaN result. If either `a' or +| `b' is a signaling NaN, the invalid exception is raised. +*----------------------------------------------------------------------------*/ + +floatx80 propagateFloatx80NaN(floatx80 a, floatx80 b, struct float_status_t *status) +{ + int aIsNaN = floatx80_is_nan(a); + int aIsSignalingNaN = floatx80_is_signaling_nan(a); + int bIsNaN = floatx80_is_nan(b); + int bIsSignalingNaN = floatx80_is_signaling_nan(b); + a.fraction |= BX_CONST64(0xC000000000000000); + b.fraction |= BX_CONST64(0xC000000000000000); + if (aIsSignalingNaN | bIsSignalingNaN) float_raise(status, float_flag_invalid); + if (aIsSignalingNaN) { + if (bIsSignalingNaN) goto returnLargerSignificand; + return bIsNaN ? b : a; + } + else if (aIsNaN) { + if (bIsSignalingNaN | ! bIsNaN) return a; + returnLargerSignificand: + if (a.fraction < b.fraction) return b; + if (b.fraction < a.fraction) return a; + return (a.exp < b.exp) ? a : b; + } + else { + return b; + } +} + +#endif /* FLOATX80 */ + +#ifdef FLOAT128 + +/*---------------------------------------------------------------------------- +| Takes two quadruple-precision floating-point values `a' and `b', one of +| which is a NaN, and returns the appropriate NaN result. If either `a' or +| `b' is a signaling NaN, the invalid exception is raised. +*----------------------------------------------------------------------------*/ + +float128 propagateFloat128NaN(float128 a, float128 b, struct float_status_t *status) +{ + int aIsNaN, aIsSignalingNaN, bIsNaN, bIsSignalingNaN; + aIsNaN = float128_is_nan(a); + aIsSignalingNaN = float128_is_signaling_nan(a); + bIsNaN = float128_is_nan(b); + bIsSignalingNaN = float128_is_signaling_nan(b); + a.hi |= BX_CONST64(0x0000800000000000); + b.hi |= BX_CONST64(0x0000800000000000); + if (aIsSignalingNaN | bIsSignalingNaN) float_raise(status, float_flag_invalid); + if (aIsSignalingNaN) { + if (bIsSignalingNaN) goto returnLargerSignificand; + return bIsNaN ? b : a; + } + else if (aIsNaN) { + if (bIsSignalingNaN | !bIsNaN) return a; + returnLargerSignificand: + if (lt128(a.hi<<1, a.lo, b.hi<<1, b.lo)) return b; + if (lt128(b.hi<<1, b.lo, a.hi<<1, a.lo)) return a; + return (a.hi < b.hi) ? a : b; + } + else { + return b; + } +} + +/*---------------------------------------------------------------------------- +| The pattern for a default generated quadruple-precision NaN. +*----------------------------------------------------------------------------*/ +const float128 float128_default_nan = + packFloat128(float128_default_nan_hi, float128_default_nan_lo); + +#endif /* FLOAT128 */ diff --git a/src/cpu/softfloat/softfloat-specialize.h b/src/cpu/softfloat/softfloat-specialize.h new file mode 100644 index 000000000..302ce53e4 --- /dev/null +++ b/src/cpu/softfloat/softfloat-specialize.h @@ -0,0 +1,789 @@ +/*============================================================================ +This C source fragment is part of the SoftFloat IEC/IEEE Floating-point +Arithmetic Package, Release 2b. + +Written by John R. Hauser. This work was made possible in part by the +International Computer Science Institute, located at Suite 600, 1947 Center +Street, Berkeley, California 94704. Funding was partially provided by the +National Science Foundation under grant MIP-9311980. The original version +of this code was written as part of a project to build a fixed-point vector +processor in collaboration with the University of California at Berkeley, +overseen by Profs. Nelson Morgan and John Wawrzynek. More information +is available through the Web page `http://www.cs.berkeley.edu/~jhauser/ +arithmetic/SoftFloat.html'. + +THIS SOFTWARE IS DISTRIBUTED AS IS, FOR FREE. Although reasonable effort has +been made to avoid it, THIS SOFTWARE MAY CONTAIN FAULTS THAT WILL AT TIMES +RESULT IN INCORRECT BEHAVIOR. USE OF THIS SOFTWARE IS RESTRICTED TO PERSONS +AND ORGANIZATIONS WHO CAN AND WILL TAKE FULL RESPONSIBILITY FOR ALL LOSSES, +COSTS, OR OTHER PROBLEMS THEY INCUR DUE TO THE SOFTWARE, AND WHO FURTHERMORE +EFFECTIVELY INDEMNIFY JOHN HAUSER AND THE INTERNATIONAL COMPUTER SCIENCE +INSTITUTE (possibly via similar legal warning) AGAINST ALL LOSSES, COSTS, OR +OTHER PROBLEMS INCURRED BY THEIR CUSTOMERS AND CLIENTS DUE TO THE SOFTWARE. + +Derivative works are acceptable, even for commercial purposes, so long as +(1) the source code for the derivative work includes prominent notice that +the work is derivative, and (2) the source code includes prominent notice with +these four paragraphs for those parts of this code that are retained. +=============================================================================*/ + +#ifndef _SOFTFLOAT_SPECIALIZE_H_ +#define _SOFTFLOAT_SPECIALIZE_H_ + +#include "softfloat.h" + +/*============================================================================ + * Adapted for Bochs (x86 achitecture simulator) by + * Stanislav Shwartsman [sshwarts at sourceforge net] + * ==========================================================================*/ + +#define int16_indefinite ((Bit16s)0x8000) +#define int32_indefinite ((Bit32s)0x80000000) +#define int64_indefinite BX_CONST64(0x8000000000000000) + +#define uint16_indefinite (0xffff) +#define uint32_indefinite (0xffffffff) +#define uint64_indefinite BX_CONST64(0xffffffffffffffff) + +/*---------------------------------------------------------------------------- +| Internal canonical NaN format. +*----------------------------------------------------------------------------*/ + +typedef struct { + int sign; + Bit64u hi, lo; +} commonNaNT; + +#ifdef FLOAT16 + +/*---------------------------------------------------------------------------- +| The pattern for a default generated half-precision NaN. +*----------------------------------------------------------------------------*/ +extern const float16 float16_default_nan; + +#define float16_fraction extractFloat16Frac +#define float16_exp extractFloat16Exp +#define float16_sign extractFloat16Sign + +/*---------------------------------------------------------------------------- +| Returns the fraction bits of the half-precision floating-point value `a'. +*----------------------------------------------------------------------------*/ + +BX_CPP_INLINE Bit16u extractFloat16Frac(float16 a) +{ + return a & 0x3FF; +} + +/*---------------------------------------------------------------------------- +| Returns the exponent bits of the half-precision floating-point value `a'. +*----------------------------------------------------------------------------*/ + +BX_CPP_INLINE Bit16s extractFloat16Exp(float16 a) +{ + return (a>>10) & 0x1F; +} + +/*---------------------------------------------------------------------------- +| Returns the sign bit of the half-precision floating-point value `a'. +*----------------------------------------------------------------------------*/ + +BX_CPP_INLINE int extractFloat16Sign(float16 a) +{ + return a>>15; +} + +/*---------------------------------------------------------------------------- +| Packs the sign `zSign', exponent `zExp', and significand `zSig' into a +| single-precision floating-point value, returning the result. After being +| shifted into the proper positions, the three fields are simply added +| together to form the result. This means that any integer portion of `zSig' +| will be added into the exponent. Since a properly normalized significand +| will have an integer portion equal to 1, the `zExp' input should be 1 less +| than the desired result exponent whenever `zSig' is a complete, normalized +| significand. +*----------------------------------------------------------------------------*/ + +BX_CPP_INLINE float16 packFloat16(int zSign, int zExp, Bit16u zSig) +{ + return (((Bit16u) zSign)<<15) + (((Bit16u) zExp)<<10) + zSig; +} + +/*---------------------------------------------------------------------------- +| Returns 1 if the half-precision floating-point value `a' is a NaN; +| otherwise returns 0. +*----------------------------------------------------------------------------*/ + +BX_CPP_INLINE int float16_is_nan(float16 a) +{ + return (0xF800 < (Bit16u) (a<<1)); +} + +/*---------------------------------------------------------------------------- +| Returns 1 if the half-precision floating-point value `a' is a signaling +| NaN; otherwise returns 0. +*----------------------------------------------------------------------------*/ + +BX_CPP_INLINE int float16_is_signaling_nan(float16 a) +{ + return (((a>>9) & 0x3F) == 0x3E) && (a & 0x1FF); +} + +/*---------------------------------------------------------------------------- +| Returns 1 if the half-precision floating-point value `a' is denormal; +| otherwise returns 0. +*----------------------------------------------------------------------------*/ + +BX_CPP_INLINE int float16_is_denormal(float16 a) +{ + return (extractFloat16Exp(a) == 0) && (extractFloat16Frac(a) != 0); +} + +/*---------------------------------------------------------------------------- +| Convert float16 denormals to zero. +*----------------------------------------------------------------------------*/ + +BX_CPP_INLINE float16 float16_denormal_to_zero(float16 a) +{ + if (float16_is_denormal(a)) a &= 0x8000; + return a; +} + +/*---------------------------------------------------------------------------- +| Returns the result of converting the half-precision floating-point NaN +| `a' to the canonical NaN format. If `a' is a signaling NaN, the invalid +| exception is raised. +*----------------------------------------------------------------------------*/ + +BX_CPP_INLINE commonNaNT float16ToCommonNaN(float16 a, struct float_status_t *status) +{ + commonNaNT z; + if (float16_is_signaling_nan(a)) float_raise(status, float_flag_invalid); + z.sign = a>>15; + z.lo = 0; + z.hi = ((Bit64u) a)<<54; + return z; +} + +/*---------------------------------------------------------------------------- +| Returns the result of converting the canonical NaN `a' to the half- +| precision floating-point format. +*----------------------------------------------------------------------------*/ + +BX_CPP_INLINE float16 commonNaNToFloat16(commonNaNT a) +{ + return (((Bit16u) a.sign)<<15) | 0x7E00 | (Bit16u)(a.hi>>54); +} + +#endif + +/*---------------------------------------------------------------------------- +| Commonly used single-precision floating point constants +*----------------------------------------------------------------------------*/ +extern const float32 float32_negative_inf; +extern const float32 float32_positive_inf; +extern const float32 float32_negative_zero; +extern const float32 float32_positive_zero; +extern const float32 float32_negative_one; +extern const float32 float32_positive_one; +extern const float32 float32_max_float; +extern const float32 float32_min_float; + +/*---------------------------------------------------------------------------- +| The pattern for a default generated single-precision NaN. +*----------------------------------------------------------------------------*/ +extern const float32 float32_default_nan; + +#define float32_fraction extractFloat32Frac +#define float32_exp extractFloat32Exp +#define float32_sign extractFloat32Sign + +#define FLOAT32_EXP_BIAS 0x7F + +/*---------------------------------------------------------------------------- +| Returns the fraction bits of the single-precision floating-point value `a'. +*----------------------------------------------------------------------------*/ + +BX_CPP_INLINE Bit32u extractFloat32Frac(float32 a) +{ + return a & 0x007FFFFF; +} + +/*---------------------------------------------------------------------------- +| Returns the exponent bits of the single-precision floating-point value `a'. +*----------------------------------------------------------------------------*/ + +BX_CPP_INLINE Bit16s extractFloat32Exp(float32 a) +{ + return (a>>23) & 0xFF; +} + +/*---------------------------------------------------------------------------- +| Returns the sign bit of the single-precision floating-point value `a'. +*----------------------------------------------------------------------------*/ + +BX_CPP_INLINE int extractFloat32Sign(float32 a) +{ + return a>>31; +} + +/*---------------------------------------------------------------------------- +| Packs the sign `zSign', exponent `zExp', and significand `zSig' into a +| single-precision floating-point value, returning the result. After being +| shifted into the proper positions, the three fields are simply added +| together to form the result. This means that any integer portion of `zSig' +| will be added into the exponent. Since a properly normalized significand +| will have an integer portion equal to 1, the `zExp' input should be 1 less +| than the desired result exponent whenever `zSig' is a complete, normalized +| significand. +*----------------------------------------------------------------------------*/ + +BX_CPP_INLINE float32 packFloat32(int zSign, Bit16s zExp, Bit32u zSig) +{ + return (((Bit32u) zSign)<<31) + (((Bit32u) zExp)<<23) + zSig; +} + +/*---------------------------------------------------------------------------- +| Returns 1 if the single-precision floating-point value `a' is a NaN; +| otherwise returns 0. +*----------------------------------------------------------------------------*/ + +BX_CPP_INLINE int float32_is_nan(float32 a) +{ + return (0xFF000000 < (Bit32u) (a<<1)); +} + +/*---------------------------------------------------------------------------- +| Returns 1 if the single-precision floating-point value `a' is a signaling +| NaN; otherwise returns 0. +*----------------------------------------------------------------------------*/ + +BX_CPP_INLINE int float32_is_signaling_nan(float32 a) +{ + return (((a>>22) & 0x1FF) == 0x1FE) && (a & 0x003FFFFF); +} + +/*---------------------------------------------------------------------------- +| Returns 1 if the single-precision floating-point value `a' is denormal; +| otherwise returns 0. +*----------------------------------------------------------------------------*/ + +BX_CPP_INLINE int float32_is_denormal(float32 a) +{ + return (extractFloat32Exp(a) == 0) && (extractFloat32Frac(a) != 0); +} + +/*---------------------------------------------------------------------------- +| Convert float32 denormals to zero. +*----------------------------------------------------------------------------*/ + +BX_CPP_INLINE float32 float32_denormal_to_zero(float32 a) +{ + if (float32_is_denormal(a)) a &= 0x80000000; + return a; +} + +/*---------------------------------------------------------------------------- +| Returns the result of converting the single-precision floating-point NaN +| `a' to the canonical NaN format. If `a' is a signaling NaN, the invalid +| exception is raised. +*----------------------------------------------------------------------------*/ + +BX_CPP_INLINE commonNaNT float32ToCommonNaN(float32 a, struct float_status_t *status) +{ + commonNaNT z; + if (float32_is_signaling_nan(a)) float_raise(status, float_flag_invalid); + z.sign = a>>31; + z.lo = 0; + z.hi = ((Bit64u) a)<<41; + return z; +} + +/*---------------------------------------------------------------------------- +| Returns the result of converting the canonical NaN `a' to the single- +| precision floating-point format. +*----------------------------------------------------------------------------*/ + +BX_CPP_INLINE float32 commonNaNToFloat32(commonNaNT a) +{ + return (((Bit32u) a.sign)<<31) | 0x7FC00000 | (Bit32u)(a.hi>>41); +} + +/*---------------------------------------------------------------------------- +| Takes two single-precision floating-point values `a' and `b', one of which +| is a NaN, and returns the appropriate NaN result. If either `a' or `b' is a +| signaling NaN, the invalid exception is raised. +*----------------------------------------------------------------------------*/ + +float32 propagateFloat32NaN(float32 a, float32 b, struct float_status_t *status); + +/*---------------------------------------------------------------------------- +| Takes single-precision floating-point NaN `a' and returns the appropriate +| NaN result. If `a' is a signaling NaN, the invalid exception is raised. +*----------------------------------------------------------------------------*/ + +BX_CPP_INLINE float32 propagateFloat32NaNOne(float32 a, struct float_status_t *status) +{ + if (float32_is_signaling_nan(a)) + float_raise(status, float_flag_invalid); + + return a | 0x00400000; +} + +/*---------------------------------------------------------------------------- +| Commonly used single-precision floating point constants +*----------------------------------------------------------------------------*/ +extern const float64 float64_negative_inf; +extern const float64 float64_positive_inf; +extern const float64 float64_negative_zero; +extern const float64 float64_positive_zero; +extern const float64 float64_negative_one; +extern const float64 float64_positive_one; +extern const float64 float64_max_float; +extern const float64 float64_min_float; + +/*---------------------------------------------------------------------------- +| The pattern for a default generated double-precision NaN. +*----------------------------------------------------------------------------*/ +extern const float64 float64_default_nan; + +#define float64_fraction extractFloat64Frac +#define float64_exp extractFloat64Exp +#define float64_sign extractFloat64Sign + +#define FLOAT64_EXP_BIAS 0x3FF + +/*---------------------------------------------------------------------------- +| Returns the fraction bits of the double-precision floating-point value `a'. +*----------------------------------------------------------------------------*/ + +BX_CPP_INLINE Bit64u extractFloat64Frac(float64 a) +{ + return a & BX_CONST64(0x000FFFFFFFFFFFFF); +} + +/*---------------------------------------------------------------------------- +| Returns the exponent bits of the double-precision floating-point value `a'. +*----------------------------------------------------------------------------*/ + +BX_CPP_INLINE Bit16s extractFloat64Exp(float64 a) +{ + return (Bit16s)(a>>52) & 0x7FF; +} + +/*---------------------------------------------------------------------------- +| Returns the sign bit of the double-precision floating-point value `a'. +*----------------------------------------------------------------------------*/ + +BX_CPP_INLINE int extractFloat64Sign(float64 a) +{ + return (int)(a>>63); +} + +/*---------------------------------------------------------------------------- +| Packs the sign `zSign', exponent `zExp', and significand `zSig' into a +| double-precision floating-point value, returning the result. After being +| shifted into the proper positions, the three fields are simply added +| together to form the result. This means that any integer portion of `zSig' +| will be added into the exponent. Since a properly normalized significand +| will have an integer portion equal to 1, the `zExp' input should be 1 less +| than the desired result exponent whenever `zSig' is a complete, normalized +| significand. +*----------------------------------------------------------------------------*/ + +BX_CPP_INLINE float64 packFloat64(int zSign, Bit16s zExp, Bit64u zSig) +{ + return (((Bit64u) zSign)<<63) + (((Bit64u) zExp)<<52) + zSig; +} + +/*---------------------------------------------------------------------------- +| Returns 1 if the double-precision floating-point value `a' is a NaN; +| otherwise returns 0. +*----------------------------------------------------------------------------*/ + +BX_CPP_INLINE int float64_is_nan(float64 a) +{ + return (BX_CONST64(0xFFE0000000000000) < (Bit64u) (a<<1)); +} + +/*---------------------------------------------------------------------------- +| Returns 1 if the double-precision floating-point value `a' is a signaling +| NaN; otherwise returns 0. +*----------------------------------------------------------------------------*/ + +BX_CPP_INLINE int float64_is_signaling_nan(float64 a) +{ + return (((a>>51) & 0xFFF) == 0xFFE) && (a & BX_CONST64(0x0007FFFFFFFFFFFF)); +} + +/*---------------------------------------------------------------------------- +| Returns 1 if the double-precision floating-point value `a' is denormal; +| otherwise returns 0. +*----------------------------------------------------------------------------*/ + +BX_CPP_INLINE int float64_is_denormal(float64 a) +{ + return (extractFloat64Exp(a) == 0) && (extractFloat64Frac(a) != 0); +} + +/*---------------------------------------------------------------------------- +| Convert float64 denormals to zero. +*----------------------------------------------------------------------------*/ + +BX_CPP_INLINE float64 float64_denormal_to_zero(float64 a) +{ + if (float64_is_denormal(a)) a &= ((Bit64u)(1) << 63); + return a; +} + +/*---------------------------------------------------------------------------- +| Returns the result of converting the double-precision floating-point NaN +| `a' to the canonical NaN format. If `a' is a signaling NaN, the invalid +| exception is raised. +*----------------------------------------------------------------------------*/ + +BX_CPP_INLINE commonNaNT float64ToCommonNaN(float64 a, struct float_status_t *status) +{ + commonNaNT z; + if (float64_is_signaling_nan(a)) float_raise(status, float_flag_invalid); + z.sign = (int)(a>>63); + z.lo = 0; + z.hi = a<<12; + return z; +} + +/*---------------------------------------------------------------------------- +| Returns the result of converting the canonical NaN `a' to the double- +| precision floating-point format. +*----------------------------------------------------------------------------*/ + +BX_CPP_INLINE float64 commonNaNToFloat64(commonNaNT a) +{ + return (((Bit64u) a.sign)<<63) | BX_CONST64(0x7FF8000000000000) | (a.hi>>12); +} + +/*---------------------------------------------------------------------------- +| Takes two double-precision floating-point values `a' and `b', one of which +| is a NaN, and returns the appropriate NaN result. If either `a' or `b' is a +| signaling NaN, the invalid exception is raised. +*----------------------------------------------------------------------------*/ + +float64 propagateFloat64NaN(float64 a, float64 b, struct float_status_t *status); + +/*---------------------------------------------------------------------------- +| Takes double-precision floating-point NaN `a' and returns the appropriate +| NaN result. If `a' is a signaling NaN, the invalid exception is raised. +*----------------------------------------------------------------------------*/ + +BX_CPP_INLINE float64 propagateFloat64NaNOne(float64 a, struct float_status_t *status) +{ + if (float64_is_signaling_nan(a)) + float_raise(status, float_flag_invalid); + + return a | BX_CONST64(0x0008000000000000); +} + +#ifdef FLOATX80 + +/*---------------------------------------------------------------------------- +| The pattern for a default generated extended double-precision NaN. The +| `high' and `low' values hold the most- and least-significant bits, +| respectively. +*----------------------------------------------------------------------------*/ +#define floatx80_default_nan_exp 0xFFFF +#define floatx80_default_nan_fraction BX_CONST64(0xC000000000000000) + +#define floatx80_fraction extractFloatx80Frac +#define floatx80_exp extractFloatx80Exp +#define floatx80_sign extractFloatx80Sign + +#define FLOATX80_EXP_BIAS 0x3FFF + +/*---------------------------------------------------------------------------- +| Returns the fraction bits of the extended double-precision floating-point +| value `a'. +*----------------------------------------------------------------------------*/ + +BX_CPP_INLINE Bit64u extractFloatx80Frac(floatx80 a) +{ + return a.fraction; +} + +/*---------------------------------------------------------------------------- +| Returns the exponent bits of the extended double-precision floating-point +| value `a'. +*----------------------------------------------------------------------------*/ + +BX_CPP_INLINE Bit32s extractFloatx80Exp(floatx80 a) +{ + return a.exp & 0x7FFF; +} + +/*---------------------------------------------------------------------------- +| Returns the sign bit of the extended double-precision floating-point value +| `a'. +*----------------------------------------------------------------------------*/ + +BX_CPP_INLINE int extractFloatx80Sign(floatx80 a) +{ + return a.exp>>15; +} + +/*---------------------------------------------------------------------------- +| Packs the sign `zSign', exponent `zExp', and significand `zSig' into an +| extended double-precision floating-point value, returning the result. +*----------------------------------------------------------------------------*/ + +BX_CPP_INLINE floatx80 packFloatx80(int zSign, Bit32s zExp, Bit64u zSig) +{ + floatx80 z; + z.fraction = zSig; + z.exp = (zSign << 15) + zExp; + return z; +} + +/*---------------------------------------------------------------------------- +| Returns 1 if the extended double-precision floating-point value `a' is a +| NaN; otherwise returns 0. +*----------------------------------------------------------------------------*/ + +BX_CPP_INLINE int floatx80_is_nan(floatx80 a) +{ + // return ((a.exp & 0x7FFF) == 0x7FFF) && (Bit64s) (a.fraction<<1); + return ((a.exp & 0x7FFF) == 0x7FFF) && (((Bit64s) (a.fraction<<1)) != 0); +} + +/*---------------------------------------------------------------------------- +| Returns 1 if the extended double-precision floating-point value `a' is a +| signaling NaN; otherwise returns 0. +*----------------------------------------------------------------------------*/ + +BX_CPP_INLINE int floatx80_is_signaling_nan(floatx80 a) +{ + Bit64u aLow = a.fraction & ~BX_CONST64(0x4000000000000000); + return ((a.exp & 0x7FFF) == 0x7FFF) && + ((Bit64u) (aLow<<1)) && (a.fraction == aLow); +} + +/*---------------------------------------------------------------------------- +| Returns 1 if the extended double-precision floating-point value `a' is an +| unsupported; otherwise returns 0. +*----------------------------------------------------------------------------*/ + +BX_CPP_INLINE int floatx80_is_unsupported(floatx80 a) +{ + return ((a.exp & 0x7FFF) && !(a.fraction & BX_CONST64(0x8000000000000000))); +} + +/*---------------------------------------------------------------------------- +| Returns the result of converting the extended double-precision floating- +| point NaN `a' to the canonical NaN format. If `a' is a signaling NaN, the +| invalid exception is raised. +*----------------------------------------------------------------------------*/ + +BX_CPP_INLINE commonNaNT floatx80ToCommonNaN(floatx80 a, struct float_status_t *status) +{ + commonNaNT z; + if (floatx80_is_signaling_nan(a)) float_raise(status, float_flag_invalid); + z.sign = a.exp >> 15; + z.lo = 0; + z.hi = a.fraction << 1; + return z; +} + +/*---------------------------------------------------------------------------- +| Returns the result of converting the canonical NaN `a' to the extended +| double-precision floating-point format. +*----------------------------------------------------------------------------*/ + +BX_CPP_INLINE floatx80 commonNaNToFloatx80(commonNaNT a) +{ + floatx80 z; + z.fraction = BX_CONST64(0xC000000000000000) | (a.hi>>1); + z.exp = (((Bit16u) a.sign)<<15) | 0x7FFF; + return z; +} + +/*---------------------------------------------------------------------------- +| Takes two extended double-precision floating-point values `a' and `b', one +| of which is a NaN, and returns the appropriate NaN result. If either `a' or +| `b' is a signaling NaN, the invalid exception is raised. +*----------------------------------------------------------------------------*/ + +floatx80 propagateFloatx80NaN(floatx80 a, floatx80 b, struct float_status_t *status); + +/*---------------------------------------------------------------------------- +| Takes extended double-precision floating-point NaN `a' and returns the +| appropriate NaN result. If `a' is a signaling NaN, the invalid exception +| is raised. +*----------------------------------------------------------------------------*/ + +BX_CPP_INLINE floatx80 propagateFloatx80NaNOne(floatx80 a, struct float_status_t *status) +{ + if (floatx80_is_signaling_nan(a)) + float_raise(status, float_flag_invalid); + + a.fraction |= BX_CONST64(0xC000000000000000); + + return a; +} + +#endif /* FLOATX80 */ + +#ifdef FLOAT128 + +#include "softfloat-macros.h" + +/*---------------------------------------------------------------------------- +| The pattern for a default generated quadruple-precision NaN. The `high' and +| `low' values hold the most- and least-significant bits, respectively. +*----------------------------------------------------------------------------*/ +#define float128_default_nan_hi BX_CONST64(0xFFFF800000000000) +#define float128_default_nan_lo BX_CONST64(0x0000000000000000) + +#define float128_exp extractFloat128Exp + +/*---------------------------------------------------------------------------- +| Returns the least-significant 64 fraction bits of the quadruple-precision +| floating-point value `a'. +*----------------------------------------------------------------------------*/ + +BX_CPP_INLINE Bit64u extractFloat128Frac1(float128 a) +{ + return a.lo; +} + +/*---------------------------------------------------------------------------- +| Returns the most-significant 48 fraction bits of the quadruple-precision +| floating-point value `a'. +*----------------------------------------------------------------------------*/ + +BX_CPP_INLINE Bit64u extractFloat128Frac0(float128 a) +{ + return a.hi & BX_CONST64(0x0000FFFFFFFFFFFF); +} + +/*---------------------------------------------------------------------------- +| Returns the exponent bits of the quadruple-precision floating-point value +| `a'. +*----------------------------------------------------------------------------*/ + +BX_CPP_INLINE Bit32s extractFloat128Exp(float128 a) +{ + return ((Bit32s)(a.hi>>48)) & 0x7FFF; +} + +/*---------------------------------------------------------------------------- +| Returns the sign bit of the quadruple-precision floating-point value `a'. +*----------------------------------------------------------------------------*/ + +BX_CPP_INLINE int extractFloat128Sign(float128 a) +{ + return (int)(a.hi >> 63); +} + +/*---------------------------------------------------------------------------- +| Packs the sign `zSign', the exponent `zExp', and the significand formed +| by the concatenation of `zSig0' and `zSig1' into a quadruple-precision +| floating-point value, returning the result. After being shifted into the +| proper positions, the three fields `zSign', `zExp', and `zSig0' are simply +| added together to form the most significant 32 bits of the result. This +| means that any integer portion of `zSig0' will be added into the exponent. +| Since a properly normalized significand will have an integer portion equal +| to 1, the `zExp' input should be 1 less than the desired result exponent +| whenever `zSig0' and `zSig1' concatenated form a complete, normalized +| significand. +*----------------------------------------------------------------------------*/ + +BX_CPP_INLINE float128 packFloat128Four(int zSign, Bit32s zExp, Bit64u zSig0, Bit64u zSig1) +{ + float128 z; + z.lo = zSig1; + z.hi = (((Bit64u) zSign)<<63) + (((Bit64u) zExp)<<48) + zSig0; + return z; +} + +/*---------------------------------------------------------------------------- +| Packs two 64-bit precision integers into into the quadruple-precision +| floating-point value, returning the result. +*----------------------------------------------------------------------------*/ + +BX_CPP_INLINE float128 packFloat128(Bit64u zHi, Bit64u zLo) +{ + float128 z; + z.lo = zLo; + z.hi = zHi; + return z; +} + +#ifdef _MSC_VER +#define PACK_FLOAT_128(hi,lo) { lo, hi } +#else +#define PACK_FLOAT_128(hi,lo) packFloat128(BX_CONST64(hi),BX_CONST64(lo)) +#endif + +/*---------------------------------------------------------------------------- +| Returns 1 if the quadruple-precision floating-point value `a' is a NaN; +| otherwise returns 0. +*----------------------------------------------------------------------------*/ + +BX_CPP_INLINE int float128_is_nan(float128 a) +{ + return (BX_CONST64(0xFFFE000000000000) <= (Bit64u) (a.hi<<1)) + && (a.lo || (a.hi & BX_CONST64(0x0000FFFFFFFFFFFF))); +} + +/*---------------------------------------------------------------------------- +| Returns 1 if the quadruple-precision floating-point value `a' is a +| signaling NaN; otherwise returns 0. +*----------------------------------------------------------------------------*/ + +BX_CPP_INLINE int float128_is_signaling_nan(float128 a) +{ + return (((a.hi>>47) & 0xFFFF) == 0xFFFE) + && (a.lo || (a.hi & BX_CONST64(0x00007FFFFFFFFFFF))); +} + +/*---------------------------------------------------------------------------- +| Returns the result of converting the quadruple-precision floating-point NaN +| `a' to the canonical NaN format. If `a' is a signaling NaN, the invalid +| exception is raised. +*----------------------------------------------------------------------------*/ + +BX_CPP_INLINE commonNaNT float128ToCommonNaN(float128 a, struct float_status_t *status) +{ + commonNaNT z; + if (float128_is_signaling_nan(a)) float_raise(status, float_flag_invalid); + z.sign = (int)(a.hi>>63); + shortShift128Left(a.hi, a.lo, 16, &z.hi, &z.lo); + return z; +} + +/*---------------------------------------------------------------------------- +| Returns the result of converting the canonical NaN `a' to the quadruple- +| precision floating-point format. +*----------------------------------------------------------------------------*/ + +BX_CPP_INLINE float128 commonNaNToFloat128(commonNaNT a) +{ + float128 z; + shift128Right(a.hi, a.lo, 16, &z.hi, &z.lo); + z.hi |= (((Bit64u) a.sign)<<63) | BX_CONST64(0x7FFF800000000000); + return z; +} + +/*---------------------------------------------------------------------------- +| Takes two quadruple-precision floating-point values `a' and `b', one of +| which is a NaN, and returns the appropriate NaN result. If either `a' or +| `b' is a signaling NaN, the invalid exception is raised. +*----------------------------------------------------------------------------*/ + +float128 propagateFloat128NaN(float128 a, float128 b, struct float_status_t *status); + +/*---------------------------------------------------------------------------- +| The pattern for a default generated quadruple-precision NaN. +*----------------------------------------------------------------------------*/ +extern const float128 float128_default_nan; + +#endif /* FLOAT128 */ + +#endif diff --git a/src/cpu/softfloat/softfloat.cc b/src/cpu/softfloat/softfloat.cc new file mode 100644 index 000000000..0802089b9 --- /dev/null +++ b/src/cpu/softfloat/softfloat.cc @@ -0,0 +1,4012 @@ +/*============================================================================ +This C source file is part of the SoftFloat IEC/IEEE Floating-point Arithmetic +Package, Release 2b. + +Written by John R. Hauser. This work was made possible in part by the +International Computer Science Institute, located at Suite 600, 1947 Center +Street, Berkeley, California 94704. Funding was partially provided by the +National Science Foundation under grant MIP-9311980. The original version +of this code was written as part of a project to build a fixed-point vector +processor in collaboration with the University of California at Berkeley, +overseen by Profs. Nelson Morgan and John Wawrzynek. More information +is available through the Web page `http://www.cs.berkeley.edu/~jhauser/ +arithmetic/SoftFloat.html'. + +THIS SOFTWARE IS DISTRIBUTED AS IS, FOR FREE. Although reasonable effort has +been made to avoid it, THIS SOFTWARE MAY CONTAIN FAULTS THAT WILL AT TIMES +RESULT IN INCORRECT BEHAVIOR. USE OF THIS SOFTWARE IS RESTRICTED TO PERSONS +AND ORGANIZATIONS WHO CAN AND WILL TAKE FULL RESPONSIBILITY FOR ALL LOSSES, +COSTS, OR OTHER PROBLEMS THEY INCUR DUE TO THE SOFTWARE, AND WHO FURTHERMORE +EFFECTIVELY INDEMNIFY JOHN HAUSER AND THE INTERNATIONAL COMPUTER SCIENCE +INSTITUTE (possibly via similar legal warning) AGAINST ALL LOSSES, COSTS, OR +OTHER PROBLEMS INCURRED BY THEIR CUSTOMERS AND CLIENTS DUE TO THE SOFTWARE. + +Derivative works are acceptable, even for commercial purposes, so long as +(1) the source code for the derivative work includes prominent notice that +the work is derivative, and (2) the source code includes prominent notice with +these four paragraphs for those parts of this code that are retained. +=============================================================================*/ + +#define FLOAT128 + +/*============================================================================ + * Adapted for Bochs (x86 achitecture simulator) by + * Stanislav Shwartsman [sshwarts at sourceforge net] + * ==========================================================================*/ + +#include "softfloat.h" +#include "softfloat-round-pack.h" + +/*---------------------------------------------------------------------------- +| Primitive arithmetic functions, including multi-word arithmetic, and +| division and square root approximations. (Can be specialized to target +| if desired). +*----------------------------------------------------------------------------*/ +#define USE_estimateDiv128To64 +#define USE_estimateSqrt32 +#include "softfloat-macros.h" + +/*---------------------------------------------------------------------------- +| Functions and definitions to determine: (1) whether tininess for underflow +| is detected before or after rounding by default, (2) what (if anything) +| happens when exceptions are raised, (3) how signaling NaNs are distinguished +| from quiet NaNs, (4) the default generated quiet NaNs, and (5) how NaNs +| are propagated from function inputs to output. These details are target- +| specific. +*----------------------------------------------------------------------------*/ +#include "softfloat-specialize.h" + +/*---------------------------------------------------------------------------- +| Returns the result of converting the 32-bit two's complement integer `a' +| to the single-precision floating-point format. The conversion is performed +| according to the IEC/IEEE Standard for Binary Floating-Point Arithmetic. +*----------------------------------------------------------------------------*/ + +const unsigned float_all_exceptions_mask = 0x3f; + +float32 int32_to_float32(Bit32s a, struct float_status_t *status) +{ + if (a == 0) return 0; + if (a == (Bit32s) 0x80000000) return packFloat32(1, 0x9E, 0); + int zSign = (a < 0); + return normalizeRoundAndPackFloat32(zSign, 0x9C, zSign ? -a : a, status); +} + +/*---------------------------------------------------------------------------- +| Returns the result of converting the 32-bit two's complement integer `a' +| to the double-precision floating-point format. The conversion is performed +| according to the IEC/IEEE Standard for Binary Floating-Point Arithmetic. +*----------------------------------------------------------------------------*/ + +float64 int32_to_float64(Bit32s a) +{ + if (a == 0) return 0; + int zSign = (a < 0); + Bit32u absA = zSign ? -a : a; + int shiftCount = countLeadingZeros32(absA) + 21; + Bit64u zSig = absA; + return packFloat64(zSign, 0x432 - shiftCount, zSig<> 1, status); + return normalizeRoundAndPackFloat32(0, 0x9C, a, status); +} + +/*---------------------------------------------------------------------------- +| Returns the result of converting the 32-bit unsigned integer `a' to the +| double-precision floating-point format. The conversion is performed +| according to the IEC/IEEE Standard for Binary Floating-Point Arithmetic. +*----------------------------------------------------------------------------*/ + +float64 uint32_to_float64(Bit32u a) +{ + if (a == 0) return 0; + int shiftCount = countLeadingZeros32(a) + 21; + Bit64u zSig = a; + return packFloat64(0, 0x432 - shiftCount, zSig<> 1, status); + return normalizeRoundAndPackFloat64(0, 0x43C, a, status); +} + +/*---------------------------------------------------------------------------- +| Returns the result of converting the single-precision floating-point value +| `a' to the 32-bit two's complement integer format. The conversion is +| performed according to the IEC/IEEE Standard for Binary Floating-Point +| Arithmetic - which means in particular that the conversion is rounded +| according to the current rounding mode. If `a' is a NaN or the +| conversion overflows the integer indefinite value is returned. +*----------------------------------------------------------------------------*/ + +Bit32s float32_to_int32(float32 a, struct float_status_t *status) +{ + Bit32u aSig = extractFloat32Frac(a); + Bit16s aExp = extractFloat32Exp(a); + int aSign = extractFloat32Sign(a); + if ((aExp == 0xFF) && aSig) aSign = 0; + if (aExp) aSig |= 0x00800000; + else { + if (get_denormals_are_zeros(status)) aSig = 0; + } + int shiftCount = 0xAF - aExp; + Bit64u aSig64 = Bit64u(aSig) << 32; + if (0 < shiftCount) aSig64 = shift64RightJamming(aSig64, shiftCount); + return roundAndPackInt32(aSign, aSig64, status); +} + +/*---------------------------------------------------------------------------- +| Returns the result of converting the single-precision floating-point value +| `a' to the 32-bit two's complement integer format. The conversion is +| performed according to the IEC/IEEE Standard for Binary Floating-Point +| Arithmetic, except that the conversion is always rounded toward zero. +| If `a' is a NaN or the conversion overflows, the integer indefinite +| value is returned. +*----------------------------------------------------------------------------*/ + +Bit32s float32_to_int32_round_to_zero(float32 a, struct float_status_t *status) +{ + int aSign; + Bit16s aExp; + Bit32u aSig; + Bit32s z; + + aSig = extractFloat32Frac(a); + aExp = extractFloat32Exp(a); + aSign = extractFloat32Sign(a); + int shiftCount = aExp - 0x9E; + if (0 <= shiftCount) { + if (a != 0xCF000000) { + float_raise(status, float_flag_invalid); + } + return (Bit32s)(int32_indefinite); + } + else if (aExp <= 0x7E) { + if (get_denormals_are_zeros(status) && aExp == 0) aSig = 0; + if (aExp | aSig) float_raise(status, float_flag_inexact); + return 0; + } + aSig = (aSig | 0x800000)<<8; + z = aSig>>(-shiftCount); + if ((Bit32u) (aSig<<(shiftCount & 31))) { + float_raise(status, float_flag_inexact); + } + if (aSign) z = -z; + return z; +} + +/*---------------------------------------------------------------------------- +| Returns the result of converting the single-precision floating-point value +| `a' to the 32-bit unsigned integer format. The conversion is performed +| according to the IEC/IEEE Standard for Binary Floating-point Arithmetic, +| except that the conversion is always rounded toward zero. If `a' is a NaN +| or conversion overflows, the largest positive integer is returned. +*----------------------------------------------------------------------------*/ + +Bit32u float32_to_uint32_round_to_zero(float32 a, struct float_status_t *status) +{ + int aSign; + Bit16s aExp; + Bit32u aSig; + + aSig = extractFloat32Frac(a); + aExp = extractFloat32Exp(a); + aSign = extractFloat32Sign(a); + int shiftCount = aExp - 0x9E; + + if (aExp <= 0x7E) { + if (get_denormals_are_zeros(status) && aExp == 0) aSig = 0; + if (aExp | aSig) float_raise(status, float_flag_inexact); + return 0; + } + else if (0 < shiftCount || aSign) { + float_raise(status, float_flag_invalid); + return uint32_indefinite; + } + + aSig = (aSig | 0x800000)<<8; + Bit32u z = aSig >> (-shiftCount); + if (aSig << (shiftCount & 31)) { + float_raise(status, float_flag_inexact); + } + return z; +} + +/*---------------------------------------------------------------------------- +| Returns the result of converting the single-precision floating-point value +| `a' to the 64-bit two's complement integer format. The conversion is +| performed according to the IEC/IEEE Standard for Binary Floating-Point +| Arithmetic - which means in particular that the conversion is rounded +| according to the current rounding mode. If `a' is a NaN or the +| conversion overflows, the integer indefinite value is returned. +*----------------------------------------------------------------------------*/ + +Bit64s float32_to_int64(float32 a, struct float_status_t *status) +{ + Bit64u aSig64, aSigExtra; + + Bit32u aSig = extractFloat32Frac(a); + Bit16s aExp = extractFloat32Exp(a); + int aSign = extractFloat32Sign(a); + + int shiftCount = 0xBE - aExp; + if (shiftCount < 0) { + float_raise(status, float_flag_invalid); + return (Bit64s)(int64_indefinite); + } + if (aExp) aSig |= 0x00800000; + else { + if (get_denormals_are_zeros(status)) aSig = 0; + } + aSig64 = aSig; + aSig64 <<= 40; + shift64ExtraRightJamming(aSig64, 0, shiftCount, &aSig64, &aSigExtra); + return roundAndPackInt64(aSign, aSig64, aSigExtra, status); +} + +/*---------------------------------------------------------------------------- +| Returns the result of converting the single-precision floating-point value +| `a' to the 64-bit two's complement integer format. The conversion is +| performed according to the IEC/IEEE Standard for Binary Floating-Point +| Arithmetic, except that the conversion is always rounded toward zero. +| If `a' is a NaN or the conversion overflows, the integer indefinite +| value is returned. +*----------------------------------------------------------------------------*/ + +Bit64s float32_to_int64_round_to_zero(float32 a, struct float_status_t *status) +{ + int aSign; + Bit16s aExp; + Bit32u aSig; + Bit64u aSig64; + Bit64s z; + + aSig = extractFloat32Frac(a); + aExp = extractFloat32Exp(a); + aSign = extractFloat32Sign(a); + int shiftCount = aExp - 0xBE; + if (0 <= shiftCount) { + if (a != 0xDF000000) { + float_raise(status, float_flag_invalid); + } + return (Bit64s)(int64_indefinite); + } + else if (aExp <= 0x7E) { + if (get_denormals_are_zeros(status) && aExp == 0) aSig = 0; + if (aExp | aSig) float_raise(status, float_flag_inexact); + return 0; + } + aSig64 = aSig | 0x00800000; + aSig64 <<= 40; + z = aSig64>>(-shiftCount); + if ((Bit64u) (aSig64<<(shiftCount & 63))) { + float_raise(status, float_flag_inexact); + } + if (aSign) z = -z; + return z; +} + +/*---------------------------------------------------------------------------- +| Returns the result of converting the single-precision floating-point value +| `a' to the 64-bit unsigned integer format. The conversion is performed +| according to the IEC/IEEE Standard for Binary Floating-Point Arithmetic, +| except that the conversion is always rounded toward zero. If `a' is a NaN +| or the conversion overflows, the largest unsigned integer is returned. +*----------------------------------------------------------------------------*/ + +Bit64u float32_to_uint64_round_to_zero(float32 a, struct float_status_t *status) +{ + int aSign; + Bit16s aExp; + Bit32u aSig; + Bit64u aSig64; + + aSig = extractFloat32Frac(a); + aExp = extractFloat32Exp(a); + aSign = extractFloat32Sign(a); + int shiftCount = aExp - 0xBE; + + if (aExp <= 0x7E) { + if (get_denormals_are_zeros(status) && aExp == 0) aSig = 0; + if (aExp | aSig) float_raise(status, float_flag_inexact); + return 0; + } + else if (0 < shiftCount || aSign) { + float_raise(status, float_flag_invalid); + return uint64_indefinite; + } + + aSig64 = aSig | 0x00800000; + aSig64 <<= 40; + Bit64u z = aSig64>>(-shiftCount); + if ((Bit64u) (aSig64<<(shiftCount & 63))) { + float_raise(status, float_flag_inexact); + } + return z; +} + +/*---------------------------------------------------------------------------- +| Returns the result of converting the single-precision floating-point value +| `a' to the 64-bit unsigned integer format. The conversion is +| performed according to the IEC/IEEE Standard for Binary Floating-Point +| Arithmetic---which means in particular that the conversion is rounded +| according to the current rounding mode. If `a' is a NaN or the conversion +| overflows, the largest unsigned integer is returned. +*----------------------------------------------------------------------------*/ + +Bit64u float32_to_uint64(float32 a, struct float_status_t *status) +{ + int aSign; + Bit16s aExp, shiftCount; + Bit32u aSig; + Bit64u aSig64, aSigExtra; + + aSig = extractFloat32Frac(a); + aExp = extractFloat32Exp(a); + aSign = extractFloat32Sign(a); + + if (get_denormals_are_zeros(status)) { + if (aExp == 0) aSig = 0; + } + + if ((aSign) && (aExp > 0x7E)) { + float_raise(status, float_flag_invalid); + return uint64_indefinite; + } + + shiftCount = 0xBE - aExp; + if (aExp) aSig |= 0x00800000; + + if (shiftCount < 0) { + float_raise(status, float_flag_invalid); + return uint64_indefinite; + } + + aSig64 = aSig; + aSig64 <<= 40; + shift64ExtraRightJamming(aSig64, 0, shiftCount, &aSig64, &aSigExtra); + return roundAndPackUint64(aSign, aSig64, aSigExtra, status); +} + +/*---------------------------------------------------------------------------- +| Returns the result of converting the single-precision floating-point value +| `a' to the 32-bit unsigned integer format. The conversion is +| performed according to the IEC/IEEE Standard for Binary Floating-Point +| Arithmetic---which means in particular that the conversion is rounded +| according to the current rounding mode. If `a' is a NaN or the conversion +| overflows, the largest unsigned integer is returned. +*----------------------------------------------------------------------------*/ + +Bit32u float32_to_uint32(float32 a, struct float_status_t *status) +{ + Bit64u val_64 = float32_to_uint64(a, status); + + if (val_64 > 0xffffffff) { + status->float_exception_flags = float_flag_invalid; // throw away other flags + return uint32_indefinite; + } + + return (Bit32u) val_64; +} + +/*---------------------------------------------------------------------------- +| Returns the result of converting the single-precision floating-point value +| `a' to the double-precision floating-point format. The conversion is +| performed according to the IEC/IEEE Standard for Binary Floating-Point +| Arithmetic. +*----------------------------------------------------------------------------*/ + +float64 float32_to_float64(float32 a, struct float_status_t *status) +{ + Bit32u aSig = extractFloat32Frac(a); + Bit16s aExp = extractFloat32Exp(a); + int aSign = extractFloat32Sign(a); + + if (aExp == 0xFF) { + if (aSig) return commonNaNToFloat64(float32ToCommonNaN(a, status)); + return packFloat64(aSign, 0x7FF, 0); + } + if (aExp == 0) { + if (aSig == 0 || get_denormals_are_zeros(status)) + return packFloat64(aSign, 0, 0); + + float_raise(status, float_flag_denormal); + normalizeFloat32Subnormal(aSig, &aExp, &aSig); + --aExp; + } + return packFloat64(aSign, aExp + 0x380, ((Bit64u) aSig)<<29); +} + +/*---------------------------------------------------------------------------- +| Rounds the single-precision floating-point value `a' to an integer, and +| returns the result as a single-precision floating-point value. The +| operation is performed according to the IEC/IEEE Standard for Binary +| Floating-Point Arithmetic. +*----------------------------------------------------------------------------*/ + +float32 float32_round_to_int(float32 a, Bit8u scale, struct float_status_t *status) +{ + Bit32u lastBitMask, roundBitsMask; + int roundingMode = get_float_rounding_mode(status); + Bit16s aExp = extractFloat32Exp(a); + scale &= 0xf; + + if ((aExp == 0xFF) && extractFloat32Frac(a)) { + return propagateFloat32NaNOne(a, status); + } + + aExp += scale; // scale the exponent + + if (0x96 <= aExp) { + return a; + } + + if (get_denormals_are_zeros(status)) { + a = float32_denormal_to_zero(a); + } + + if (aExp <= 0x7E) { + if ((Bit32u) (a<<1) == 0) return a; + float_raise(status, float_flag_inexact); + int aSign = extractFloat32Sign(a); + switch (roundingMode) { + case float_round_nearest_even: + if ((aExp == 0x7E) && extractFloat32Frac(a)) { + return packFloat32(aSign, 0x7F - scale, 0); + } + break; + case float_round_down: + return aSign ? packFloat32(1, 0x7F - scale, 0) : float32_positive_zero; + case float_round_up: + return aSign ? float32_negative_zero : packFloat32(0, 0x7F - scale, 0); + } + return packFloat32(aSign, 0, 0); + } + + lastBitMask = 1; + lastBitMask <<= 0x96 - aExp; + roundBitsMask = lastBitMask - 1; + float32 z = a; + if (roundingMode == float_round_nearest_even) { + z += lastBitMask>>1; + if ((z & roundBitsMask) == 0) z &= ~lastBitMask; + } + else if (roundingMode != float_round_to_zero) { + if (extractFloat32Sign(z) ^ (roundingMode == float_round_up)) { + z += roundBitsMask; + } + } + z &= ~roundBitsMask; + if (z != a) float_raise(status, float_flag_inexact); + return z; +} + +/*---------------------------------------------------------------------------- +| Extracts the fractional portion of single-precision floating-point value `a', +| and returns the result as a single-precision floating-point value. The +| fractional results are precise. The operation is performed according to the +| IEC/IEEE Standard for Binary Floating-Point Arithmetic. +*----------------------------------------------------------------------------*/ + +float32 float32_frc(float32 a, struct float_status_t *status) +{ + int roundingMode = get_float_rounding_mode(status); + + Bit16s aExp = extractFloat32Exp(a); + Bit32u aSig = extractFloat32Frac(a); + int aSign = extractFloat32Sign(a); + + if (aExp == 0xFF) { + if (aSig) return propagateFloat32NaNOne(a, status); + float_raise(status, float_flag_invalid); + return float32_default_nan; + } + + if (aExp >= 0x96) { + return packFloat32(roundingMode == float_round_down, 0, 0); + } + + if (aExp < 0x7F) { + if (aExp == 0) { + if (aSig == 0 || get_denormals_are_zeros(status)) + return packFloat32(roundingMode == float_round_down, 0, 0); + + float_raise(status, float_flag_denormal); + if (! float_exception_masked(status, float_flag_underflow)) + float_raise(status, float_flag_underflow); + + if(get_flush_underflow_to_zero(status)) { + float_raise(status, float_flag_underflow | float_flag_inexact); + return packFloat32(aSign, 0, 0); + } + } + return a; + } + + Bit32u lastBitMask = 1 << (0x96 - aExp); + Bit32u roundBitsMask = lastBitMask - 1; + + aSig &= roundBitsMask; + aSig <<= 7; + aExp--; + + if (aSig == 0) + return packFloat32(roundingMode == float_round_down, 0, 0); + + return normalizeRoundAndPackFloat32(aSign, aExp, aSig, status); +} + +/*---------------------------------------------------------------------------- +| Extracts the exponent portion of single-precision floating-point value 'a', +| and returns the result as a single-precision floating-point value +| representing unbiased integer exponent. The operation is performed according +| to the IEC/IEEE Standard for Binary Floating-Point Arithmetic. +*----------------------------------------------------------------------------*/ + +float32 float32_getexp(float32 a, struct float_status_t *status) +{ + Bit16s aExp = extractFloat32Exp(a); + Bit32u aSig = extractFloat32Frac(a); + + if (aExp == 0xFF) { + if (aSig) return propagateFloat32NaNOne(a, status); + return float32_positive_inf; + } + + if (aExp == 0) { + if (aSig == 0 || get_denormals_are_zeros(status)) + return float32_negative_inf; + + float_raise(status, float_flag_denormal); + normalizeFloat32Subnormal(aSig, &aExp, &aSig); + } + + return int32_to_float32(aExp - 0x7F, status); +} + +/*---------------------------------------------------------------------------- +| Extracts the mantissa of single-precision floating-point value 'a' and +| returns the result as a single-precision floating-point after applying +| the mantissa interval normalization and sign control. The operation is +| performed according to the IEC/IEEE Standard for Binary Floating-Point +| Arithmetic. +*----------------------------------------------------------------------------*/ + +float32 float32_getmant(float32 a, struct float_status_t *status, int sign_ctrl, int interv) +{ + Bit16s aExp = extractFloat32Exp(a); + Bit32u aSig = extractFloat32Frac(a); + int aSign = extractFloat32Sign(a); + + if (aExp == 0xFF) { + if (aSig) return propagateFloat32NaNOne(a, status); + if (aSign) { + if (sign_ctrl & 0x2) { + float_raise(status, float_flag_invalid); + return float32_default_nan; + } + } + return packFloat32(~sign_ctrl & aSign, 0x7F, 0); + } + + if (aExp == 0 && (aSig == 0 || get_denormals_are_zeros(status))) { + return packFloat32(~sign_ctrl & aSign, 0x7F, 0); + } + + if (aSign) { + if (sign_ctrl & 0x2) { + float_raise(status, float_flag_invalid); + return float32_default_nan; + } + } + + if (aExp == 0) { + float_raise(status, float_flag_denormal); + normalizeFloat32Subnormal(aSig, &aExp, &aSig); +// aExp += 0x7E; + aSig &= 0x7FFFFF; + } + + switch(interv) { + case 0x0: // interval [1,2) + aExp = 0x7F; + break; + case 0x1: // interval [1/2,2) + aExp -= 0x7F; + aExp = 0x7F - (aExp & 0x1); + break; + case 0x2: // interval [1/2,1) + aExp = 0x7E; + break; + case 0x3: // interval [3/4,3/2) + aExp = 0x7F - ((aSig >> 22) & 0x1); + break; + } + + return packFloat32(~sign_ctrl & aSign, aExp, aSig); +} + +/*---------------------------------------------------------------------------- +| Return the result of a floating point scale of the single-precision floating +| point value `a' by multiplying it by 2 power of the single-precision +| floating point value 'b' converted to integral value. If the result cannot +| be represented in single precision, then the proper overflow response (for +| positive scaling operand), or the proper underflow response (for negative +| scaling operand) is issued. The operation is performed according to the +| IEC/IEEE Standard for Binary Floating-Point Arithmetic. +*----------------------------------------------------------------------------*/ + +float32 float32_scalef(float32 a, float32 b, struct float_status_t *status) +{ + Bit32u aSig = extractFloat32Frac(a); + Bit16s aExp = extractFloat32Exp(a); + int aSign = extractFloat32Sign(a); + Bit32u bSig = extractFloat32Frac(b); + Bit16s bExp = extractFloat32Exp(b); + int bSign = extractFloat32Sign(b); + + if (get_denormals_are_zeros(status)) { + if (aExp == 0) aSig = 0; + if (bExp == 0) bSig = 0; + } + + if (bExp == 0xFF) { + if (bSig) return propagateFloat32NaN(a, b, status); + } + + if (aExp == 0xFF) { + if (aSig) { + int aIsSignalingNaN = (aSig & 0x00400000) == 0; + if (aIsSignalingNaN || bExp != 0xFF || bSig) + return propagateFloat32NaN(a, b, status); + + return bSign ? 0 : float32_positive_inf; + } + + if (bExp == 0xFF && bSign) { + float_raise(status, float_flag_invalid); + return float32_default_nan; + } + return a; + } + + if (aExp == 0) { + if (aSig == 0) { + if (bExp == 0xFF && ! bSign) { + float_raise(status, float_flag_invalid); + return float32_default_nan; + } + return a; + } + float_raise(status, float_flag_denormal); + } + + if ((bExp | bSig) == 0) return a; + + if (bExp == 0xFF) { + if (bSign) return packFloat32(aSign, 0, 0); + return packFloat32(aSign, 0xFF, 0); + } + + if (bExp >= 0x8E) { + // handle obvious overflow/underflow result + return roundAndPackFloat32(aSign, bSign ? -0x7F : 0xFF, aSig, status); + } + + int scale = 0; + + if (bExp <= 0x7E) { + if (bExp == 0) + float_raise(status, float_flag_denormal); + scale = -bSign; + } + else { + int shiftCount = bExp - 0x9E; + bSig = (bSig | 0x800000)<<8; + scale = bSig>>(-shiftCount); + + if (bSign) { + if ((Bit32u) (bSig<<(shiftCount & 31))) scale++; + scale = -scale; + } + + if (scale > 0x200) scale = 0x200; + if (scale < -0x200) scale = -0x200; + } + + if (aExp != 0) { + aSig |= 0x00800000; + } else { + aExp++; + } + + aExp += scale - 1; + aSig <<= 7; + return normalizeRoundAndPackFloat32(aSign, aExp, aSig, status); +} + +/*---------------------------------------------------------------------------- +| Returns the result of adding the absolute values of the single-precision +| floating-point values `a' and `b'. If `zSign' is 1, the sum is negated +| before being returned. `zSign' is ignored if the result is a NaN. +| The addition is performed according to the IEC/IEEE Standard for Binary +| Floating-Point Arithmetic. +*----------------------------------------------------------------------------*/ + +static float32 addFloat32Sigs(float32 a, float32 b, int zSign, struct float_status_t *status) +{ + Bit16s aExp, bExp, zExp; + Bit32u aSig, bSig, zSig; + Bit16s expDiff; + + aSig = extractFloat32Frac(a); + aExp = extractFloat32Exp(a); + bSig = extractFloat32Frac(b); + bExp = extractFloat32Exp(b); + + if (get_denormals_are_zeros(status)) { + if (aExp == 0) aSig = 0; + if (bExp == 0) bSig = 0; + } + + expDiff = aExp - bExp; + aSig <<= 6; + bSig <<= 6; + + if (0 < expDiff) { + if (aExp == 0xFF) { + if (aSig) return propagateFloat32NaN(a, b, status); + if (bSig && (bExp == 0)) float_raise(status, float_flag_denormal); + return a; + } + if ((aExp == 0) && aSig) + float_raise(status, float_flag_denormal); + + if (bExp == 0) { + if (bSig) float_raise(status, float_flag_denormal); + --expDiff; + } + else bSig |= 0x20000000; + + bSig = shift32RightJamming(bSig, expDiff); + zExp = aExp; + } + else if (expDiff < 0) { + if (bExp == 0xFF) { + if (bSig) return propagateFloat32NaN(a, b, status); + if (aSig && (aExp == 0)) float_raise(status, float_flag_denormal); + return packFloat32(zSign, 0xFF, 0); + } + if ((bExp == 0) && bSig) + float_raise(status, float_flag_denormal); + + if (aExp == 0) { + if (aSig) float_raise(status, float_flag_denormal); + ++expDiff; + } + else aSig |= 0x20000000; + + aSig = shift32RightJamming(aSig, -expDiff); + zExp = bExp; + } + else { + if (aExp == 0xFF) { + if (aSig | bSig) return propagateFloat32NaN(a, b, status); + return a; + } + if (aExp == 0) { + zSig = (aSig + bSig) >> 6; + if (aSig | bSig) { + float_raise(status, float_flag_denormal); + if (get_flush_underflow_to_zero(status) && (extractFloat32Frac(zSig) == zSig)) { + float_raise(status, float_flag_underflow | float_flag_inexact); + return packFloat32(zSign, 0, 0); + } + if (! float_exception_masked(status, float_flag_underflow)) { + if (extractFloat32Frac(zSig) == zSig) + float_raise(status, float_flag_underflow); + } + } + return packFloat32(zSign, 0, zSig); + } + zSig = 0x40000000 + aSig + bSig; + return roundAndPackFloat32(zSign, aExp, zSig, status); + } + aSig |= 0x20000000; + zSig = (aSig + bSig)<<1; + --zExp; + if ((Bit32s) zSig < 0) { + zSig = aSig + bSig; + ++zExp; + } + return roundAndPackFloat32(zSign, zExp, zSig, status); +} + +/*---------------------------------------------------------------------------- +| Returns the result of subtracting the absolute values of the single- +| precision floating-point values `a' and `b'. If `zSign' is 1, the +| difference is negated before being returned. `zSign' is ignored if the +| result is a NaN. The subtraction is performed according to the IEC/IEEE +| Standard for Binary Floating-Point Arithmetic. +*----------------------------------------------------------------------------*/ + +static float32 subFloat32Sigs(float32 a, float32 b, int zSign, struct float_status_t *status) +{ + Bit16s aExp, bExp, zExp; + Bit32u aSig, bSig, zSig; + Bit16s expDiff; + + aSig = extractFloat32Frac(a); + aExp = extractFloat32Exp(a); + bSig = extractFloat32Frac(b); + bExp = extractFloat32Exp(b); + + if (get_denormals_are_zeros(status)) { + if (aExp == 0) aSig = 0; + if (bExp == 0) bSig = 0; + } + + expDiff = aExp - bExp; + aSig <<= 7; + bSig <<= 7; + if (0 < expDiff) goto aExpBigger; + if (expDiff < 0) goto bExpBigger; + if (aExp == 0xFF) { + if (aSig | bSig) return propagateFloat32NaN(a, b, status); + float_raise(status, float_flag_invalid); + return float32_default_nan; + } + if (aExp == 0) { + if (aSig | bSig) float_raise(status, float_flag_denormal); + aExp = 1; + bExp = 1; + } + if (bSig < aSig) goto aBigger; + if (aSig < bSig) goto bBigger; + return packFloat32(get_float_rounding_mode(status) == float_round_down, 0, 0); + bExpBigger: + if (bExp == 0xFF) { + if (bSig) return propagateFloat32NaN(a, b, status); + if (aSig && (aExp == 0)) float_raise(status, float_flag_denormal); + return packFloat32(zSign ^ 1, 0xFF, 0); + } + if ((bExp == 0) && bSig) + float_raise(status, float_flag_denormal); + + if (aExp == 0) { + if (aSig) float_raise(status, float_flag_denormal); + ++expDiff; + } + else aSig |= 0x40000000; + + aSig = shift32RightJamming(aSig, -expDiff); + bSig |= 0x40000000; + bBigger: + zSig = bSig - aSig; + zExp = bExp; + zSign ^= 1; + goto normalizeRoundAndPack; + aExpBigger: + if (aExp == 0xFF) { + if (aSig) return propagateFloat32NaN(a, b, status); + if (bSig && (bExp == 0)) float_raise(status, float_flag_denormal); + return a; + } + if ((aExp == 0) && aSig) + float_raise(status, float_flag_denormal); + + if (bExp == 0) { + if (bSig) float_raise(status, float_flag_denormal); + --expDiff; + } + else bSig |= 0x40000000; + + bSig = shift32RightJamming(bSig, expDiff); + aSig |= 0x40000000; + aBigger: + zSig = aSig - bSig; + zExp = aExp; + normalizeRoundAndPack: + --zExp; + return normalizeRoundAndPackFloat32(zSign, zExp, zSig, status); +} + +/*---------------------------------------------------------------------------- +| Returns the result of adding the single-precision floating-point values `a' +| and `b'. The operation is performed according to the IEC/IEEE Standard for +| Binary Floating-Point Arithmetic. +*----------------------------------------------------------------------------*/ + +float32 float32_add(float32 a, float32 b, struct float_status_t *status) +{ + int aSign = extractFloat32Sign(a); + int bSign = extractFloat32Sign(b); + + if (aSign == bSign) { + return addFloat32Sigs(a, b, aSign, status); + } + else { + return subFloat32Sigs(a, b, aSign, status); + } +} + +/*---------------------------------------------------------------------------- +| Returns the result of subtracting the single-precision floating-point values +| `a' and `b'. The operation is performed according to the IEC/IEEE Standard +| for Binary Floating-Point Arithmetic. +*----------------------------------------------------------------------------*/ + +float32 float32_sub(float32 a, float32 b, struct float_status_t *status) +{ + int aSign = extractFloat32Sign(a); + int bSign = extractFloat32Sign(b); + + if (aSign == bSign) { + return subFloat32Sigs(a, b, aSign, status); + } + else { + return addFloat32Sigs(a, b, aSign, status); + } +} + +/*---------------------------------------------------------------------------- +| Returns the result of multiplying the single-precision floating-point values +| `a' and `b'. The operation is performed according to the IEC/IEEE Standard +| for Binary Floating-Point Arithmetic. +*----------------------------------------------------------------------------*/ + +float32 float32_mul(float32 a, float32 b, struct float_status_t *status) +{ + int aSign, bSign, zSign; + Bit16s aExp, bExp, zExp; + Bit32u aSig, bSig; + Bit64u zSig64; + Bit32u zSig; + + aSig = extractFloat32Frac(a); + aExp = extractFloat32Exp(a); + aSign = extractFloat32Sign(a); + bSig = extractFloat32Frac(b); + bExp = extractFloat32Exp(b); + bSign = extractFloat32Sign(b); + zSign = aSign ^ bSign; + + if (get_denormals_are_zeros(status)) { + if (aExp == 0) aSig = 0; + if (bExp == 0) bSig = 0; + } + + if (aExp == 0xFF) { + if (aSig || ((bExp == 0xFF) && bSig)) + return propagateFloat32NaN(a, b, status); + + if ((bExp | bSig) == 0) { + float_raise(status, float_flag_invalid); + return float32_default_nan; + } + if (bSig && (bExp == 0)) float_raise(status, float_flag_denormal); + return packFloat32(zSign, 0xFF, 0); + } + if (bExp == 0xFF) { + if (bSig) return propagateFloat32NaN(a, b, status); + if ((aExp | aSig) == 0) { + float_raise(status, float_flag_invalid); + return float32_default_nan; + } + if (aSig && (aExp == 0)) float_raise(status, float_flag_denormal); + return packFloat32(zSign, 0xFF, 0); + } + if (aExp == 0) { + if (aSig == 0) { + if (bSig && (bExp == 0)) float_raise(status, float_flag_denormal); + return packFloat32(zSign, 0, 0); + } + float_raise(status, float_flag_denormal); + normalizeFloat32Subnormal(aSig, &aExp, &aSig); + } + if (bExp == 0) { + if (bSig == 0) return packFloat32(zSign, 0, 0); + float_raise(status, float_flag_denormal); + normalizeFloat32Subnormal(bSig, &bExp, &bSig); + } + zExp = aExp + bExp - 0x7F; + aSig = (aSig | 0x00800000)<<7; + bSig = (bSig | 0x00800000)<<8; + zSig64 = shift64RightJamming(((Bit64u) aSig) * bSig, 32); + zSig = (Bit32u) zSig64; + if (0 <= (Bit32s) (zSig<<1)) { + zSig <<= 1; + --zExp; + } + return roundAndPackFloat32(zSign, zExp, zSig, status); +} + +/*---------------------------------------------------------------------------- +| Returns the result of dividing the single-precision floating-point value `a' +| by the corresponding value `b'. The operation is performed according to the +| IEC/IEEE Standard for Binary Floating-Point Arithmetic. +*----------------------------------------------------------------------------*/ + +float32 float32_div(float32 a, float32 b, struct float_status_t *status) +{ + int aSign, bSign, zSign; + Bit16s aExp, bExp, zExp; + Bit32u aSig, bSig, zSig; + + aSig = extractFloat32Frac(a); + aExp = extractFloat32Exp(a); + aSign = extractFloat32Sign(a); + bSig = extractFloat32Frac(b); + bExp = extractFloat32Exp(b); + bSign = extractFloat32Sign(b); + zSign = aSign ^ bSign; + + if (get_denormals_are_zeros(status)) { + if (aExp == 0) aSig = 0; + if (bExp == 0) bSig = 0; + } + + if (aExp == 0xFF) { + if (aSig) return propagateFloat32NaN(a, b, status); + if (bExp == 0xFF) { + if (bSig) return propagateFloat32NaN(a, b, status); + float_raise(status, float_flag_invalid); + return float32_default_nan; + } + if (bSig && (bExp == 0)) float_raise(status, float_flag_denormal); + return packFloat32(zSign, 0xFF, 0); + } + if (bExp == 0xFF) { + if (bSig) return propagateFloat32NaN(a, b, status); + if (aSig && (aExp == 0)) float_raise(status, float_flag_denormal); + return packFloat32(zSign, 0, 0); + } + if (bExp == 0) { + if (bSig == 0) { + if ((aExp | aSig) == 0) { + float_raise(status, float_flag_invalid); + return float32_default_nan; + } + float_raise(status, float_flag_divbyzero); + return packFloat32(zSign, 0xFF, 0); + } + float_raise(status, float_flag_denormal); + normalizeFloat32Subnormal(bSig, &bExp, &bSig); + } + if (aExp == 0) { + if (aSig == 0) return packFloat32(zSign, 0, 0); + float_raise(status, float_flag_denormal); + normalizeFloat32Subnormal(aSig, &aExp, &aSig); + } + zExp = aExp - bExp + 0x7D; + aSig = (aSig | 0x00800000)<<7; + bSig = (bSig | 0x00800000)<<8; + if (bSig <= (aSig + aSig)) { + aSig >>= 1; + ++zExp; + } + zSig = (((Bit64u) aSig)<<32) / bSig; + if ((zSig & 0x3F) == 0) { + zSig |= ((Bit64u) bSig * zSig != ((Bit64u) aSig)<<32); + } + return roundAndPackFloat32(zSign, zExp, zSig, status); +} + +/*---------------------------------------------------------------------------- +| Returns the square root of the single-precision floating-point value `a'. +| The operation is performed according to the IEC/IEEE Standard for Binary +| Floating-Point Arithmetic. +*----------------------------------------------------------------------------*/ + +float32 float32_sqrt(float32 a, struct float_status_t *status) +{ + int aSign; + Bit16s aExp, zExp; + Bit32u aSig, zSig; + Bit64u rem, term; + + aSig = extractFloat32Frac(a); + aExp = extractFloat32Exp(a); + aSign = extractFloat32Sign(a); + + if (aExp == 0xFF) { + if (aSig) return propagateFloat32NaNOne(a, status); + if (! aSign) return a; + float_raise(status, float_flag_invalid); + return float32_default_nan; + } + + if (get_denormals_are_zeros(status)) { + if (aExp == 0) aSig = 0; + } + + if (aSign) { + if ((aExp | aSig) == 0) return packFloat32(aSign, 0, 0); + float_raise(status, float_flag_invalid); + return float32_default_nan; + } + if (aExp == 0) { + if (aSig == 0) return 0; + float_raise(status, float_flag_denormal); + normalizeFloat32Subnormal(aSig, &aExp, &aSig); + } + zExp = ((aExp - 0x7F)>>1) + 0x7E; + aSig = (aSig | 0x00800000)<<8; + zSig = estimateSqrt32(aExp, aSig) + 2; + if ((zSig & 0x7F) <= 5) { + if (zSig < 2) { + zSig = 0x7FFFFFFF; + goto roundAndPack; + } + aSig >>= aExp & 1; + term = ((Bit64u) zSig) * zSig; + rem = (((Bit64u) aSig)<<32) - term; + while ((Bit64s) rem < 0) { + --zSig; + rem += (((Bit64u) zSig)<<1) | 1; + } + zSig |= (rem != 0); + } + zSig = shift32RightJamming(zSig, 1); + roundAndPack: + return roundAndPackFloat32(0, zExp, zSig, status); +} + +/*---------------------------------------------------------------------------- +| Determine single-precision floating-point number class. +*----------------------------------------------------------------------------*/ + +float_class_t float32_class(float32 a) +{ + Bit16s aExp = extractFloat32Exp(a); + Bit32u aSig = extractFloat32Frac(a); + int aSign = extractFloat32Sign(a); + + if(aExp == 0xFF) { + if (aSig == 0) + return (aSign) ? float_negative_inf : float_positive_inf; + + return (aSig & 0x00400000) ? float_QNaN : float_SNaN; + } + + if(aExp == 0) { + if (aSig == 0) return float_zero; + return float_denormal; + } + + return float_normalized; +} + +/*---------------------------------------------------------------------------- +| Compare between two single precision floating point numbers. Returns +| 'float_relation_equal' if the operands are equal, 'float_relation_less' if +| the value 'a' is less than the corresponding value `b', +| 'float_relation_greater' if the value 'a' is greater than the corresponding +| value `b', or 'float_relation_unordered' otherwise. +*----------------------------------------------------------------------------*/ + +int float32_compare(float32 a, float32 b, int quiet, struct float_status_t *status) +{ + if (get_denormals_are_zeros(status)) { + a = float32_denormal_to_zero(a); + b = float32_denormal_to_zero(b); + } + + float_class_t aClass = float32_class(a); + float_class_t bClass = float32_class(b); + + if (aClass == float_SNaN || bClass == float_SNaN) { + float_raise(status, float_flag_invalid); + return float_relation_unordered; + } + + if (aClass == float_QNaN || bClass == float_QNaN) { + if (! quiet) float_raise(status, float_flag_invalid); + return float_relation_unordered; + } + + if (aClass == float_denormal || bClass == float_denormal) { + float_raise(status, float_flag_denormal); + } + + if ((a == b) || ((Bit32u) ((a | b)<<1) == 0)) return float_relation_equal; + + int aSign = extractFloat32Sign(a); + int bSign = extractFloat32Sign(b); + if (aSign != bSign) + return (aSign) ? float_relation_less : float_relation_greater; + + if (aSign ^ (a < b)) return float_relation_less; + return float_relation_greater; +} + +/*---------------------------------------------------------------------------- +| Compare between two single precision floating point numbers and return the +| smaller of them. +*----------------------------------------------------------------------------*/ + +float32 float32_min(float32 a, float32 b, struct float_status_t *status) +{ + if (get_denormals_are_zeros(status)) { + a = float32_denormal_to_zero(a); + b = float32_denormal_to_zero(b); + } + + return (float32_compare_two(a, b, status) == float_relation_less) ? a : b; +} + +/*---------------------------------------------------------------------------- +| Compare between two single precision floating point numbers and return the +| larger of them. +*----------------------------------------------------------------------------*/ + +float32 float32_max(float32 a, float32 b, struct float_status_t *status) +{ + if (get_denormals_are_zeros(status)) { + a = float32_denormal_to_zero(a); + b = float32_denormal_to_zero(b); + } + + return (float32_compare_two(a, b, status) == float_relation_greater) ? a : b; +} + +/*---------------------------------------------------------------------------- +| Compare between two single precision floating point numbers and return the +| smaller/larger of them. The operation is performed according to the IEC/IEEE +| Standard for Binary Floating-Point Arithmetic. +*----------------------------------------------------------------------------*/ + +float32 float32_minmax(float32 a, float32 b, int is_max, int is_abs, struct float_status_t *status) +{ + if (get_denormals_are_zeros(status)) { + a = float32_denormal_to_zero(a); + b = float32_denormal_to_zero(b); + } + + if (float32_is_nan(a) || float32_is_nan(b)) { + if (float32_is_signaling_nan(a)) { + return propagateFloat32NaNOne(a, status); + } + if (float32_is_signaling_nan(b) ) { + return propagateFloat32NaNOne(b, status); + } + if (! float32_is_nan(b)) { + if (float32_is_denormal(b)) + float_raise(status, float_flag_denormal); + return b; + } + if (! float32_is_nan(a)) { + if (float32_is_denormal(a)) + float_raise(status, float_flag_denormal); + return a; + } + return propagateFloat32NaN(a, b, status); + } + + float32 tmp_a = a, tmp_b = b; + if (is_abs) { + tmp_a &= ~0x80000000; // clear the sign bit + tmp_b &= ~0x80000000; + } + + int aSign = extractFloat32Sign(tmp_a); + int bSign = extractFloat32Sign(tmp_b); + + if (float32_is_denormal(a) || float32_is_denormal(b)) + float_raise(status, float_flag_denormal); + + if (aSign != bSign) { + if (! is_max) { + return aSign ? a : b; + } else { + return aSign ? b : a; + } + } else { + if (! is_max) { + return (aSign ^ (tmp_a < tmp_b)) ? a : b; + } else { + return (aSign ^ (tmp_a < tmp_b)) ? b : a; + } + } +} + +/*---------------------------------------------------------------------------- +| Returns the result of converting the double-precision floating-point value +| `a' to the 32-bit two's complement integer format. The conversion is +| performed according to the IEC/IEEE Standard for Binary Floating-Point +| Arithmetic - which means in particular that the conversion is rounded +| according to the current rounding mode. If `a' is a NaN or the +| conversion overflows, the integer indefinite value is returned. +*----------------------------------------------------------------------------*/ + +Bit32s float64_to_int32(float64 a, struct float_status_t *status) +{ + Bit64u aSig = extractFloat64Frac(a); + Bit16s aExp = extractFloat64Exp(a); + int aSign = extractFloat64Sign(a); + if ((aExp == 0x7FF) && aSig) aSign = 0; + if (aExp) aSig |= BX_CONST64(0x0010000000000000); + else { + if (get_denormals_are_zeros(status)) aSig = 0; + } + int shiftCount = 0x42C - aExp; + if (0 < shiftCount) aSig = shift64RightJamming(aSig, shiftCount); + return roundAndPackInt32(aSign, aSig, status); +} + +/*---------------------------------------------------------------------------- +| Returns the result of converting the double-precision floating-point value +| `a' to the 32-bit two's complement integer format. The conversion is +| performed according to the IEC/IEEE Standard for Binary Floating-Point +| Arithmetic, except that the conversion is always rounded toward zero. +| If `a' is a NaN or the conversion overflows, the integer indefinite +| value is returned. +*----------------------------------------------------------------------------*/ + +Bit32s float64_to_int32_round_to_zero(float64 a, struct float_status_t *status) +{ + int aSign; + Bit16s aExp; + Bit64u aSig, savedASig; + Bit32s z; + int shiftCount; + + aSig = extractFloat64Frac(a); + aExp = extractFloat64Exp(a); + aSign = extractFloat64Sign(a); + if (0x41E < aExp) { + float_raise(status, float_flag_invalid); + return (Bit32s)(int32_indefinite); + } + else if (aExp < 0x3FF) { + if (get_denormals_are_zeros(status) && aExp == 0) aSig = 0; + if (aExp || aSig) float_raise(status, float_flag_inexact); + return 0; + } + aSig |= BX_CONST64(0x0010000000000000); + shiftCount = 0x433 - aExp; + savedASig = aSig; + aSig >>= shiftCount; + z = (Bit32s) aSig; + if (aSign) z = -z; + if ((z < 0) ^ aSign) { + float_raise(status, float_flag_invalid); + return (Bit32s)(int32_indefinite); + } + if ((aSig<>= shiftCount; + if ((aSig<>(-shiftCount); + if ((Bit64u) (aSig<<(shiftCount & 63))) { + float_raise(status, float_flag_inexact); + } + } + if (aSign) z = -z; + return z; +} + +/*---------------------------------------------------------------------------- +| Returns the result of converting the double-precision floating-point value +| `a' to the 64-bit unsigned integer format. The conversion is performed +| according to the IEC/IEEE Standard for Binary Floating-Point Arithmetic, +| except that the conversion is always rounded toward zero. If `a' is a NaN +| or the conversion overflows, the largest unsigned integer is returned. +*----------------------------------------------------------------------------*/ + +Bit64u float64_to_uint64_round_to_zero(float64 a, struct float_status_t *status) +{ + int aSign; + Bit16s aExp; + Bit64u aSig, z; + + aSig = extractFloat64Frac(a); + aExp = extractFloat64Exp(a); + aSign = extractFloat64Sign(a); + + if (aExp < 0x3FE) { + if (get_denormals_are_zeros(status) && aExp == 0) aSig = 0; + if (aExp | aSig) float_raise(status, float_flag_inexact); + return 0; + } + + if (0x43E <= aExp || aSign) { + float_raise(status, float_flag_invalid); + return uint64_indefinite; + } + + if (aExp) aSig |= BX_CONST64(0x0010000000000000); + int shiftCount = aExp - 0x433; + + if (0 <= shiftCount) { + z = aSig<>(-shiftCount); + if ((Bit64u) (aSig<<(shiftCount & 63))) { + float_raise(status, float_flag_inexact); + } + } + return z; +} + +/*---------------------------------------------------------------------------- +| Returns the result of converting the double-precision floating-point value +| `a' to the 32-bit unsigned integer format. The conversion is +| performed according to the IEC/IEEE Standard for Binary Floating-Point +| Arithmetic---which means in particular that the conversion is rounded +| according to the current rounding mode. If `a' is a NaN or the conversion +| overflows, the largest unsigned integer is returned. +*----------------------------------------------------------------------------*/ + +Bit32u float64_to_uint32(float64 a, struct float_status_t *status) +{ + Bit64u val_64 = float64_to_uint64(a, status); + + if (val_64 > 0xffffffff) { + status->float_exception_flags = float_flag_invalid; // throw away other flags + return uint32_indefinite; + } + + return (Bit32u) val_64; +} + +/*---------------------------------------------------------------------------- +| Returns the result of converting the double-precision floating-point value +| `a' to the 64-bit unsigned integer format. The conversion is +| performed according to the IEC/IEEE Standard for Binary Floating-Point +| Arithmetic---which means in particular that the conversion is rounded +| according to the current rounding mode. If `a' is a NaN or the conversion +| overflows, the largest unsigned integer is returned. +*----------------------------------------------------------------------------*/ + +Bit64u float64_to_uint64(float64 a, struct float_status_t *status) +{ + int aSign; + Bit16s aExp, shiftCount; + Bit64u aSig, aSigExtra; + + aSig = extractFloat64Frac(a); + aExp = extractFloat64Exp(a); + aSign = extractFloat64Sign(a); + + if (get_denormals_are_zeros(status)) { + if (aExp == 0) aSig = 0; + } + + if (aSign && (aExp > 0x3FE)) { + float_raise(status, float_flag_invalid); + return uint64_indefinite; + } + + if (aExp) { + aSig |= BX_CONST64(0x0010000000000000); + } + shiftCount = 0x433 - aExp; + if (shiftCount <= 0) { + if (0x43E < aExp) { + float_raise(status, float_flag_invalid); + return uint64_indefinite; + } + aSigExtra = 0; + aSig <<= -shiftCount; + } else { + shift64ExtraRightJamming(aSig, 0, shiftCount, &aSig, &aSigExtra); + } + + return roundAndPackUint64(aSign, aSig, aSigExtra, status); +} + +/*---------------------------------------------------------------------------- +| Returns the result of converting the double-precision floating-point value +| `a' to the single-precision floating-point format. The conversion is +| performed according to the IEC/IEEE Standard for Binary Floating-Point +| Arithmetic. +*----------------------------------------------------------------------------*/ + +float32 float64_to_float32(float64 a, struct float_status_t *status) +{ + int aSign; + Bit16s aExp; + Bit64u aSig; + Bit32u zSig; + + aSig = extractFloat64Frac(a); + aExp = extractFloat64Exp(a); + aSign = extractFloat64Sign(a); + if (aExp == 0x7FF) { + if (aSig) return commonNaNToFloat32(float64ToCommonNaN(a, status)); + return packFloat32(aSign, 0xFF, 0); + } + if (aExp == 0) { + if (aSig == 0 || get_denormals_are_zeros(status)) + return packFloat32(aSign, 0, 0); + float_raise(status, float_flag_denormal); + } + aSig = shift64RightJamming(aSig, 22); + zSig = (Bit32u) aSig; + if (aExp || zSig) { + zSig |= 0x40000000; + aExp -= 0x381; + } + return roundAndPackFloat32(aSign, aExp, zSig, status); +} + +/*---------------------------------------------------------------------------- +| Rounds the double-precision floating-point value `a' to an integer, and +| returns the result as a double-precision floating-point value. The +| operation is performed according to the IEC/IEEE Standard for Binary +| Floating-Point Arithmetic. +*----------------------------------------------------------------------------*/ + +float64 float64_round_to_int(float64 a, Bit8u scale, struct float_status_t *status) +{ + Bit64u lastBitMask, roundBitsMask; + int roundingMode = get_float_rounding_mode(status); + Bit16s aExp = extractFloat64Exp(a); + scale &= 0xf; + + if ((aExp == 0x7FF) && extractFloat64Frac(a)) { + return propagateFloat64NaNOne(a, status); + } + + aExp += scale; // scale the exponent + + if (0x433 <= aExp) { + return a; + } + + if (get_denormals_are_zeros(status)) { + a = float64_denormal_to_zero(a); + } + + if (aExp < 0x3FF) { + if ((Bit64u) (a<<1) == 0) return a; + float_raise(status, float_flag_inexact); + int aSign = extractFloat64Sign(a); + switch (roundingMode) { + case float_round_nearest_even: + if ((aExp == 0x3FE) && extractFloat64Frac(a)) { + return packFloat64(aSign, 0x3FF - scale, 0); + } + break; + case float_round_down: + return aSign ? packFloat64(1, 0x3FF - scale, 0) : float64_positive_zero; + case float_round_up: + return aSign ? float64_negative_zero : packFloat64(0, 0x3FF - scale, 0); + } + return packFloat64(aSign, 0, 0); + } + + lastBitMask = 1; + lastBitMask <<= 0x433 - aExp; + roundBitsMask = lastBitMask - 1; + float64 z = a; + if (roundingMode == float_round_nearest_even) { + z += lastBitMask>>1; + if ((z & roundBitsMask) == 0) z &= ~lastBitMask; + } + else if (roundingMode != float_round_to_zero) { + if (extractFloat64Sign(z) ^ (roundingMode == float_round_up)) { + z += roundBitsMask; + } + } + z &= ~roundBitsMask; + if (z != a) float_raise(status, float_flag_inexact); + return z; +} + +/*---------------------------------------------------------------------------- +| Extracts the fractional portion of double-precision floating-point value `a', +| and returns the result as a double-precision floating-point value. The +| fractional results are precise. The operation is performed according to the +| IEC/IEEE Standard for Binary Floating-Point Arithmetic. +*----------------------------------------------------------------------------*/ + +float64 float64_frc(float64 a, struct float_status_t *status) +{ + int roundingMode = get_float_rounding_mode(status); + + Bit64u aSig = extractFloat64Frac(a); + Bit16s aExp = extractFloat64Exp(a); + int aSign = extractFloat64Sign(a); + + if (aExp == 0x7FF) { + if (aSig) return propagateFloat64NaNOne(a, status); + float_raise(status, float_flag_invalid); + return float64_default_nan; + } + + if (aExp >= 0x433) { + return packFloat64(roundingMode == float_round_down, 0, 0); + } + + if (aExp < 0x3FF) { + if (aExp == 0) { + if (aSig == 0 || get_denormals_are_zeros(status)) + return packFloat64(roundingMode == float_round_down, 0, 0); + + float_raise(status, float_flag_denormal); + if (! float_exception_masked(status, float_flag_underflow)) + float_raise(status, float_flag_underflow); + + if(get_flush_underflow_to_zero(status)) { + float_raise(status, float_flag_underflow | float_flag_inexact); + return packFloat64(aSign, 0, 0); + } + } + return a; + } + + Bit64u lastBitMask = BX_CONST64(1) << (0x433 - aExp); + Bit64u roundBitsMask = lastBitMask - 1; + + aSig &= roundBitsMask; + aSig <<= 10; + aExp--; + + if (aSig == 0) + return packFloat64(roundingMode == float_round_down, 0, 0); + + return normalizeRoundAndPackFloat64(aSign, aExp, aSig, status); +} + +/*---------------------------------------------------------------------------- +| Extracts the exponent portion of double-precision floating-point value 'a', +| and returns the result as a double-precision floating-point value +| representing unbiased integer exponent. The operation is performed according +| to the IEC/IEEE Standard for Binary Floating-Point Arithmetic. +*----------------------------------------------------------------------------*/ + +float64 float64_getexp(float64 a, struct float_status_t *status) +{ + Bit16s aExp = extractFloat64Exp(a); + Bit64u aSig = extractFloat64Frac(a); + + if (aExp == 0x7FF) { + if (aSig) return propagateFloat64NaNOne(a, status); + return float64_positive_inf; + } + + if (aExp == 0) { + if (aSig == 0 || get_denormals_are_zeros(status)) + return float64_negative_inf; + + float_raise(status, float_flag_denormal); + normalizeFloat64Subnormal(aSig, &aExp, &aSig); + } + + return int32_to_float64(aExp - 0x3FF); +} + +/*---------------------------------------------------------------------------- +| Extracts the mantissa of double-precision floating-point value 'a' and +| returns the result as a double-precision floating-point after applying +| the mantissa interval normalization and sign control. The operation is +| performed according to the IEC/IEEE Standard for Binary Floating-Point +| Arithmetic. +*----------------------------------------------------------------------------*/ + +float64 float64_getmant(float64 a, struct float_status_t *status, int sign_ctrl, int interv) +{ + Bit16s aExp = extractFloat64Exp(a); + Bit64u aSig = extractFloat64Frac(a); + int aSign = extractFloat64Sign(a); + + if (aExp == 0x7FF) { + if (aSig) return propagateFloat64NaNOne(a, status); + if (aSign) { + if (sign_ctrl & 0x2) { + float_raise(status, float_flag_invalid); + return float64_default_nan; + } + } + return packFloat64(~sign_ctrl & aSign, 0x3FF, 0); + } + + if (aExp == 0 && (aSig == 0 || get_denormals_are_zeros(status))) { + return packFloat64(~sign_ctrl & aSign, 0x3FF, 0); + } + + if (aSign) { + if (sign_ctrl & 0x2) { + float_raise(status, float_flag_invalid); + return float64_default_nan; + } + } + + if (aExp == 0) { + float_raise(status, float_flag_denormal); + normalizeFloat64Subnormal(aSig, &aExp, &aSig); +// aExp += 0x3FE; + aSig &= BX_CONST64(0xFFFFFFFFFFFFFFFF); + } + + switch(interv) { + case 0x0: // interval [1,2) + aExp = 0x3FF; + break; + case 0x1: // interval [1/2,2) + aExp -= 0x3FF; + aExp = 0x3FF - (aExp & 0x1); + break; + case 0x2: // interval [1/2,1) + aExp = 0x3FE; + break; + case 0x3: // interval [3/4,3/2) + aExp = 0x3FF - ((aSig >> 51) & 0x1); + break; + } + + return packFloat64(~sign_ctrl & aSign, aExp, aSig); +} + +/*---------------------------------------------------------------------------- +| Return the result of a floating point scale of the double-precision floating +| point value `a' by multiplying it by 2 power of the double-precision +| floating point value 'b' converted to integral value. If the result cannot +| be represented in double precision, then the proper overflow response (for +| positive scaling operand), or the proper underflow response (for negative +| scaling operand) is issued. The operation is performed according to the +| IEC/IEEE Standard for Binary Floating-Point Arithmetic. +*----------------------------------------------------------------------------*/ + +float64 float64_scalef(float64 a, float64 b, struct float_status_t *status) +{ + Bit64u aSig = extractFloat64Frac(a); + Bit16s aExp = extractFloat64Exp(a); + int aSign = extractFloat64Sign(a); + Bit64u bSig = extractFloat64Frac(b); + Bit16s bExp = extractFloat64Exp(b); + int bSign = extractFloat64Sign(b); + + if (get_denormals_are_zeros(status)) { + if (aExp == 0) aSig = 0; + if (bExp == 0) bSig = 0; + } + + if (bExp == 0x7FF) { + if (bSig) return propagateFloat64NaN(a, b, status); + } + + if (aExp == 0x7FF) { + if (aSig) { + int aIsSignalingNaN = (aSig & BX_CONST64(0x0008000000000000)) == 0; + if (aIsSignalingNaN || bExp != 0x7FF || bSig) + return propagateFloat64NaN(a, b, status); + + return bSign ? 0 : float64_positive_inf; + } + + if (bExp == 0x7FF && bSign) { + float_raise(status, float_flag_invalid); + return float64_default_nan; + } + return a; + } + + if (aExp == 0) { + if (aSig == 0) { + if (bExp == 0x7FF && ! bSign) { + float_raise(status, float_flag_invalid); + return float64_default_nan; + } + return a; + } + float_raise(status, float_flag_denormal); + } + + if ((bExp | bSig) == 0) return a; + + if (bExp == 0x7FF) { + if (bSign) return packFloat64(aSign, 0, 0); + return packFloat64(aSign, 0x7FF, 0); + } + + if (0x40F <= bExp) { + // handle obvious overflow/underflow result + return roundAndPackFloat64(aSign, bSign ? -0x3FF : 0x7FF, aSig, status); + } + + int scale = 0; + + if (bExp < 0x3FF) { + if (bExp == 0) + float_raise(status, float_flag_denormal); + scale = -bSign; + } + else { + bSig |= BX_CONST64(0x0010000000000000); + int shiftCount = 0x433 - bExp; + Bit64u savedBSig = bSig; + bSig >>= shiftCount; + scale = (Bit32s) bSig; + if (bSign) { + if ((bSig< 0x1000) scale = 0x1000; + if (scale < -0x1000) scale = -0x1000; + } + + if (aExp != 0) { + aSig |= BX_CONST64(0x0010000000000000); + } else { + aExp++; + } + + aExp += scale - 1; + aSig <<= 10; + return normalizeRoundAndPackFloat64(aSign, aExp, aSig, status); +} + +/*---------------------------------------------------------------------------- +| Returns the result of adding the absolute values of the double-precision +| floating-point values `a' and `b'. If `zSign' is 1, the sum is negated +| before being returned. `zSign' is ignored if the result is a NaN. +| The addition is performed according to the IEC/IEEE Standard for Binary +| Floating-Point Arithmetic. +*----------------------------------------------------------------------------*/ + +static float64 addFloat64Sigs(float64 a, float64 b, int zSign, struct float_status_t *status) +{ + Bit16s aExp, bExp, zExp; + Bit64u aSig, bSig, zSig; + Bit16s expDiff; + + aSig = extractFloat64Frac(a); + aExp = extractFloat64Exp(a); + bSig = extractFloat64Frac(b); + bExp = extractFloat64Exp(b); + + if (get_denormals_are_zeros(status)) { + if (aExp == 0) aSig = 0; + if (bExp == 0) bSig = 0; + } + + expDiff = aExp - bExp; + aSig <<= 9; + bSig <<= 9; + if (0 < expDiff) { + if (aExp == 0x7FF) { + if (aSig) return propagateFloat64NaN(a, b, status); + if (bSig && (bExp == 0)) float_raise(status, float_flag_denormal); + return a; + } + if ((aExp == 0) && aSig) + float_raise(status, float_flag_denormal); + + if (bExp == 0) { + if (bSig) float_raise(status, float_flag_denormal); + --expDiff; + } + else bSig |= BX_CONST64(0x2000000000000000); + + bSig = shift64RightJamming(bSig, expDiff); + zExp = aExp; + } + else if (expDiff < 0) { + if (bExp == 0x7FF) { + if (bSig) return propagateFloat64NaN(a, b, status); + if (aSig && (aExp == 0)) float_raise(status, float_flag_denormal); + return packFloat64(zSign, 0x7FF, 0); + } + if ((bExp == 0) && bSig) + float_raise(status, float_flag_denormal); + + if (aExp == 0) { + if (aSig) float_raise(status, float_flag_denormal); + ++expDiff; + } + else aSig |= BX_CONST64(0x2000000000000000); + + aSig = shift64RightJamming(aSig, -expDiff); + zExp = bExp; + } + else { + if (aExp == 0x7FF) { + if (aSig | bSig) return propagateFloat64NaN(a, b, status); + return a; + } + if (aExp == 0) { + zSig = (aSig + bSig) >> 9; + if (aSig | bSig) { + float_raise(status, float_flag_denormal); + if (get_flush_underflow_to_zero(status) && (extractFloat64Frac(zSig) == zSig)) { + float_raise(status, float_flag_underflow | float_flag_inexact); + return packFloat64(zSign, 0, 0); + } + if (! float_exception_masked(status, float_flag_underflow)) { + if (extractFloat64Frac(zSig) == zSig) + float_raise(status, float_flag_underflow); + } + } + return packFloat64(zSign, 0, zSig); + } + zSig = BX_CONST64(0x4000000000000000) + aSig + bSig; + return roundAndPackFloat64(zSign, aExp, zSig, status); + } + aSig |= BX_CONST64(0x2000000000000000); + zSig = (aSig + bSig)<<1; + --zExp; + if ((Bit64s) zSig < 0) { + zSig = aSig + bSig; + ++zExp; + } + return roundAndPackFloat64(zSign, zExp, zSig, status); +} + +/*---------------------------------------------------------------------------- +| Returns the result of subtracting the absolute values of the double- +| precision floating-point values `a' and `b'. If `zSign' is 1, the +| difference is negated before being returned. `zSign' is ignored if the +| result is a NaN. The subtraction is performed according to the IEC/IEEE +| Standard for Binary Floating-Point Arithmetic. +*----------------------------------------------------------------------------*/ + +static float64 subFloat64Sigs(float64 a, float64 b, int zSign, struct float_status_t *status) +{ + Bit16s aExp, bExp, zExp; + Bit64u aSig, bSig, zSig; + Bit16s expDiff; + + aSig = extractFloat64Frac(a); + aExp = extractFloat64Exp(a); + bSig = extractFloat64Frac(b); + bExp = extractFloat64Exp(b); + + if (get_denormals_are_zeros(status)) { + if (aExp == 0) aSig = 0; + if (bExp == 0) bSig = 0; + } + + expDiff = aExp - bExp; + aSig <<= 10; + bSig <<= 10; + if (0 < expDiff) goto aExpBigger; + if (expDiff < 0) goto bExpBigger; + if (aExp == 0x7FF) { + if (aSig | bSig) return propagateFloat64NaN(a, b, status); + float_raise(status, float_flag_invalid); + return float64_default_nan; + } + if (aExp == 0) { + if (aSig | bSig) float_raise(status, float_flag_denormal); + aExp = 1; + bExp = 1; + } + if (bSig < aSig) goto aBigger; + if (aSig < bSig) goto bBigger; + return packFloat64(get_float_rounding_mode(status) == float_round_down, 0, 0); + bExpBigger: + if (bExp == 0x7FF) { + if (bSig) return propagateFloat64NaN(a, b, status); + if (aSig && (aExp == 0)) float_raise(status, float_flag_denormal); + return packFloat64(zSign ^ 1, 0x7FF, 0); + } + if ((bExp == 0) && bSig) + float_raise(status, float_flag_denormal); + + if (aExp == 0) { + if (aSig) float_raise(status, float_flag_denormal); + ++expDiff; + } + else aSig |= BX_CONST64(0x4000000000000000); + + aSig = shift64RightJamming(aSig, -expDiff); + bSig |= BX_CONST64(0x4000000000000000); + bBigger: + zSig = bSig - aSig; + zExp = bExp; + zSign ^= 1; + goto normalizeRoundAndPack; + aExpBigger: + if (aExp == 0x7FF) { + if (aSig) return propagateFloat64NaN(a, b, status); + if (bSig && (bExp == 0)) float_raise(status, float_flag_denormal); + return a; + } + if ((aExp == 0) && aSig) + float_raise(status, float_flag_denormal); + + if (bExp == 0) { + if (bSig) float_raise(status, float_flag_denormal); + --expDiff; + } + else bSig |= BX_CONST64(0x4000000000000000); + + bSig = shift64RightJamming(bSig, expDiff); + aSig |= BX_CONST64(0x4000000000000000); + aBigger: + zSig = aSig - bSig; + zExp = aExp; + normalizeRoundAndPack: + --zExp; + return normalizeRoundAndPackFloat64(zSign, zExp, zSig, status); +} + +/*---------------------------------------------------------------------------- +| Returns the result of adding the double-precision floating-point values `a' +| and `b'. The operation is performed according to the IEC/IEEE Standard for +| Binary Floating-Point Arithmetic. +*----------------------------------------------------------------------------*/ + +float64 float64_add(float64 a, float64 b, struct float_status_t *status) +{ + int aSign = extractFloat64Sign(a); + int bSign = extractFloat64Sign(b); + + if (aSign == bSign) { + return addFloat64Sigs(a, b, aSign, status); + } + else { + return subFloat64Sigs(a, b, aSign, status); + } +} + +/*---------------------------------------------------------------------------- +| Returns the result of subtracting the double-precision floating-point values +| `a' and `b'. The operation is performed according to the IEC/IEEE Standard +| for Binary Floating-Point Arithmetic. +*----------------------------------------------------------------------------*/ + +float64 float64_sub(float64 a, float64 b, struct float_status_t *status) +{ + int aSign = extractFloat64Sign(a); + int bSign = extractFloat64Sign(b); + + if (aSign == bSign) { + return subFloat64Sigs(a, b, aSign, status); + } + else { + return addFloat64Sigs(a, b, aSign, status); + } +} + +/*---------------------------------------------------------------------------- +| Returns the result of multiplying the double-precision floating-point values +| `a' and `b'. The operation is performed according to the IEC/IEEE Standard +| for Binary Floating-Point Arithmetic. +*----------------------------------------------------------------------------*/ + +float64 float64_mul(float64 a, float64 b, struct float_status_t *status) +{ + int aSign, bSign, zSign; + Bit16s aExp, bExp, zExp; + Bit64u aSig, bSig, zSig0, zSig1; + + aSig = extractFloat64Frac(a); + aExp = extractFloat64Exp(a); + aSign = extractFloat64Sign(a); + bSig = extractFloat64Frac(b); + bExp = extractFloat64Exp(b); + bSign = extractFloat64Sign(b); + zSign = aSign ^ bSign; + + if (get_denormals_are_zeros(status)) { + if (aExp == 0) aSig = 0; + if (bExp == 0) bSig = 0; + } + + if (aExp == 0x7FF) { + if (aSig || ((bExp == 0x7FF) && bSig)) { + return propagateFloat64NaN(a, b, status); + } + if ((bExp | bSig) == 0) { + float_raise(status, float_flag_invalid); + return float64_default_nan; + } + if (bSig && (bExp == 0)) float_raise(status, float_flag_denormal); + return packFloat64(zSign, 0x7FF, 0); + } + if (bExp == 0x7FF) { + if (bSig) return propagateFloat64NaN(a, b, status); + if ((aExp | aSig) == 0) { + float_raise(status, float_flag_invalid); + return float64_default_nan; + } + if (aSig && (aExp == 0)) float_raise(status, float_flag_denormal); + return packFloat64(zSign, 0x7FF, 0); + } + if (aExp == 0) { + if (aSig == 0) { + if (bSig && (bExp == 0)) float_raise(status, float_flag_denormal); + return packFloat64(zSign, 0, 0); + } + float_raise(status, float_flag_denormal); + normalizeFloat64Subnormal(aSig, &aExp, &aSig); + } + if (bExp == 0) { + if (bSig == 0) return packFloat64(zSign, 0, 0); + float_raise(status, float_flag_denormal); + normalizeFloat64Subnormal(bSig, &bExp, &bSig); + } + zExp = aExp + bExp - 0x3FF; + aSig = (aSig | BX_CONST64(0x0010000000000000))<<10; + bSig = (bSig | BX_CONST64(0x0010000000000000))<<11; + mul64To128(aSig, bSig, &zSig0, &zSig1); + zSig0 |= (zSig1 != 0); + if (0 <= (Bit64s) (zSig0<<1)) { + zSig0 <<= 1; + --zExp; + } + return roundAndPackFloat64(zSign, zExp, zSig0, status); +} + +/*---------------------------------------------------------------------------- +| Returns the result of dividing the double-precision floating-point value `a' +| by the corresponding value `b'. The operation is performed according to +| the IEC/IEEE Standard for Binary Floating-Point Arithmetic. +*----------------------------------------------------------------------------*/ + +float64 float64_div(float64 a, float64 b, struct float_status_t *status) +{ + int aSign, bSign, zSign; + Bit16s aExp, bExp, zExp; + Bit64u aSig, bSig, zSig; + Bit64u rem0, rem1; + Bit64u term0, term1; + + aSig = extractFloat64Frac(a); + aExp = extractFloat64Exp(a); + aSign = extractFloat64Sign(a); + bSig = extractFloat64Frac(b); + bExp = extractFloat64Exp(b); + bSign = extractFloat64Sign(b); + zSign = aSign ^ bSign; + + if (get_denormals_are_zeros(status)) { + if (aExp == 0) aSig = 0; + if (bExp == 0) bSig = 0; + } + + if (aExp == 0x7FF) { + if (aSig) return propagateFloat64NaN(a, b, status); + if (bExp == 0x7FF) { + if (bSig) return propagateFloat64NaN(a, b, status); + float_raise(status, float_flag_invalid); + return float64_default_nan; + } + if (bSig && (bExp == 0)) float_raise(status, float_flag_denormal); + return packFloat64(zSign, 0x7FF, 0); + } + if (bExp == 0x7FF) { + if (bSig) return propagateFloat64NaN(a, b, status); + if (aSig && (aExp == 0)) float_raise(status, float_flag_denormal); + return packFloat64(zSign, 0, 0); + } + if (bExp == 0) { + if (bSig == 0) { + if ((aExp | aSig) == 0) { + float_raise(status, float_flag_invalid); + return float64_default_nan; + } + float_raise(status, float_flag_divbyzero); + return packFloat64(zSign, 0x7FF, 0); + } + float_raise(status, float_flag_denormal); + normalizeFloat64Subnormal(bSig, &bExp, &bSig); + } + if (aExp == 0) { + if (aSig == 0) return packFloat64(zSign, 0, 0); + float_raise(status, float_flag_denormal); + normalizeFloat64Subnormal(aSig, &aExp, &aSig); + } + zExp = aExp - bExp + 0x3FD; + aSig = (aSig | BX_CONST64(0x0010000000000000))<<10; + bSig = (bSig | BX_CONST64(0x0010000000000000))<<11; + if (bSig <= (aSig + aSig)) { + aSig >>= 1; + ++zExp; + } + zSig = estimateDiv128To64(aSig, 0, bSig); + if ((zSig & 0x1FF) <= 2) { + mul64To128(bSig, zSig, &term0, &term1); + sub128(aSig, 0, term0, term1, &rem0, &rem1); + while ((Bit64s) rem0 < 0) { + --zSig; + add128(rem0, rem1, 0, bSig, &rem0, &rem1); + } + zSig |= (rem1 != 0); + } + return roundAndPackFloat64(zSign, zExp, zSig, status); +} + +/*---------------------------------------------------------------------------- +| Returns the square root of the double-precision floating-point value `a'. +| The operation is performed according to the IEC/IEEE Standard for Binary +| Floating-Point Arithmetic. +*----------------------------------------------------------------------------*/ + +float64 float64_sqrt(float64 a, struct float_status_t *status) +{ + int aSign; + Bit16s aExp, zExp; + Bit64u aSig, zSig, doubleZSig; + Bit64u rem0, rem1, term0, term1; + + aSig = extractFloat64Frac(a); + aExp = extractFloat64Exp(a); + aSign = extractFloat64Sign(a); + + if (aExp == 0x7FF) { + if (aSig) return propagateFloat64NaNOne(a, status); + if (! aSign) return a; + float_raise(status, float_flag_invalid); + return float64_default_nan; + } + + if (get_denormals_are_zeros(status)) { + if (aExp == 0) aSig = 0; + } + + if (aSign) { + if ((aExp | aSig) == 0) return packFloat64(aSign, 0, 0); + float_raise(status, float_flag_invalid); + return float64_default_nan; + } + if (aExp == 0) { + if (aSig == 0) return 0; + float_raise(status, float_flag_denormal); + normalizeFloat64Subnormal(aSig, &aExp, &aSig); + } + zExp = ((aExp - 0x3FF)>>1) + 0x3FE; + aSig |= BX_CONST64(0x0010000000000000); + zSig = estimateSqrt32(aExp, (Bit32u)(aSig>>21)); + aSig <<= 9 - (aExp & 1); + zSig = estimateDiv128To64(aSig, 0, zSig<<32) + (zSig<<30); + if ((zSig & 0x1FF) <= 5) { + doubleZSig = zSig<<1; + mul64To128(zSig, zSig, &term0, &term1); + sub128(aSig, 0, term0, term1, &rem0, &rem1); + while ((Bit64s) rem0 < 0) { + --zSig; + doubleZSig -= 2; + add128(rem0, rem1, zSig>>63, doubleZSig | 1, &rem0, &rem1); + } + zSig |= ((rem0 | rem1) != 0); + } + return roundAndPackFloat64(0, zExp, zSig, status); +} + +/*---------------------------------------------------------------------------- +| Determine double-precision floating-point number class +*----------------------------------------------------------------------------*/ + +float_class_t float64_class(float64 a) +{ + Bit16s aExp = extractFloat64Exp(a); + Bit64u aSig = extractFloat64Frac(a); + int aSign = extractFloat64Sign(a); + + if(aExp == 0x7FF) { + if (aSig == 0) + return (aSign) ? float_negative_inf : float_positive_inf; + + return (aSig & BX_CONST64(0x0008000000000000)) ? float_QNaN : float_SNaN; + } + + if(aExp == 0) { + if (aSig == 0) + return float_zero; + return float_denormal; + } + + return float_normalized; +} + +/*---------------------------------------------------------------------------- +| Compare between two double precision floating point numbers. Returns +| 'float_relation_equal' if the operands are equal, 'float_relation_less' if +| the value 'a' is less than the corresponding value `b', +| 'float_relation_greater' if the value 'a' is greater than the corresponding +| value `b', or 'float_relation_unordered' otherwise. +*----------------------------------------------------------------------------*/ + +int float64_compare(float64 a, float64 b, int quiet, struct float_status_t *status) +{ + if (get_denormals_are_zeros(status)) { + a = float64_denormal_to_zero(a); + b = float64_denormal_to_zero(b); + } + + float_class_t aClass = float64_class(a); + float_class_t bClass = float64_class(b); + + if (aClass == float_SNaN || bClass == float_SNaN) { + float_raise(status, float_flag_invalid); + return float_relation_unordered; + } + + if (aClass == float_QNaN || bClass == float_QNaN) { + if (! quiet) float_raise(status, float_flag_invalid); + return float_relation_unordered; + } + + if (aClass == float_denormal || bClass == float_denormal) { + float_raise(status, float_flag_denormal); + } + + if ((a == b) || ((Bit64u) ((a | b)<<1) == 0)) return float_relation_equal; + + int aSign = extractFloat64Sign(a); + int bSign = extractFloat64Sign(b); + if (aSign != bSign) + return (aSign) ? float_relation_less : float_relation_greater; + + if (aSign ^ (a < b)) return float_relation_less; + return float_relation_greater; +} + +/*---------------------------------------------------------------------------- +| Compare between two double precision floating point numbers and return the +| smaller of them. +*----------------------------------------------------------------------------*/ + +float64 float64_min(float64 a, float64 b, struct float_status_t *status) +{ + if (get_denormals_are_zeros(status)) { + a = float64_denormal_to_zero(a); + b = float64_denormal_to_zero(b); + } + + return (float64_compare_two(a, b, status) == float_relation_less) ? a : b; +} + +/*---------------------------------------------------------------------------- +| Compare between two double precision floating point numbers and return the +| larger of them. +*----------------------------------------------------------------------------*/ + +float64 float64_max(float64 a, float64 b, struct float_status_t *status) +{ + if (get_denormals_are_zeros(status)) { + a = float64_denormal_to_zero(a); + b = float64_denormal_to_zero(b); + } + + return (float64_compare_two(a, b, status) == float_relation_greater) ? a : b; +} + +/*---------------------------------------------------------------------------- +| Compare between two double precision floating point numbers and return the +| smaller/larger of them. The operation is performed according to the IEC/IEEE +| Standard for Binary Floating-Point Arithmetic. +*----------------------------------------------------------------------------*/ + +float64 float64_minmax(float64 a, float64 b, int is_max, int is_abs, struct float_status_t *status) +{ + if (get_denormals_are_zeros(status)) { + a = float64_denormal_to_zero(a); + b = float64_denormal_to_zero(b); + } + + if (float64_is_nan(a) || float64_is_nan(b)) { + if (float64_is_signaling_nan(a)) { + return propagateFloat64NaNOne(a, status); + } + if (float64_is_signaling_nan(b)) { + return propagateFloat64NaNOne(b, status); + } + if (! float64_is_nan(b)) { + if (float64_is_denormal(b)) + float_raise(status, float_flag_denormal); + return b; + } + if (! float64_is_nan(a)) { + if (float64_is_denormal(a)) + float_raise(status, float_flag_denormal); + return a; + } + return propagateFloat64NaN(a, b, status); + } + + float64 tmp_a = a, tmp_b = b; + if (is_abs) { + tmp_a &= ~BX_CONST64(0x8000000000000000); // clear the sign bit + tmp_b &= ~BX_CONST64(0x8000000000000000); + } + + int aSign = extractFloat64Sign(tmp_a); + int bSign = extractFloat64Sign(tmp_b); + + if (float64_is_denormal(a) || float64_is_denormal(b)) + float_raise(status, float_flag_denormal); + + if (aSign != bSign) { + if (! is_max) { + return aSign ? a : b; + } else { + return aSign ? b : a; + } + } else { + if (! is_max) { + return (aSign ^ (tmp_a < tmp_b)) ? a : b; + } else { + return (aSign ^ (tmp_a < tmp_b)) ? b : a; + } + } +} + +#ifdef FLOATX80 + +/*---------------------------------------------------------------------------- +| Returns the result of converting the 32-bit two's complement integer `a' +| to the extended double-precision floating-point format. The conversion +| is performed according to the IEC/IEEE Standard for Binary Floating-Point +| Arithmetic. +*----------------------------------------------------------------------------*/ + +floatx80 int32_to_floatx80(Bit32s a) +{ + if (a == 0) return packFloatx80(0, 0, 0); + int zSign = (a < 0); + Bit32u absA = zSign ? -a : a; + int shiftCount = countLeadingZeros32(absA) + 32; + Bit64u zSig = absA; + return packFloatx80(zSign, 0x403E - shiftCount, zSig< 0x401E) { + float_raise(status, float_flag_invalid); + return (Bit32s)(int32_indefinite); + } + if (aExp < 0x3FFF) { + if (aExp || aSig) float_raise(status, float_flag_inexact); + return 0; + } + shiftCount = 0x403E - aExp; + savedASig = aSig; + aSig >>= shiftCount; + z = (Bit32s) aSig; + if (aSign) z = -z; + if ((z < 0) ^ aSign) { + float_raise(status, float_flag_invalid); + return (Bit32s)(int32_indefinite); + } + if ((aSig<>(-shiftCount); + if ((Bit64u) (aSig<<(shiftCount & 63))) { + float_raise(status, float_flag_inexact); + } + if (aSign) z = -z; + return z; +} + +/*---------------------------------------------------------------------------- +| Returns the result of converting the extended double-precision floating- +| point value `a' to the single-precision floating-point format. The +| conversion is performed according to the IEC/IEEE Standard for Binary +| Floating-Point Arithmetic. +*----------------------------------------------------------------------------*/ + +float32 floatx80_to_float32(floatx80 a, struct float_status_t *status) +{ + Bit64u aSig = extractFloatx80Frac(a); + Bit32s aExp = extractFloatx80Exp(a); + int aSign = extractFloatx80Sign(a); + + // handle unsupported extended double-precision floating encodings + if (floatx80_is_unsupported(a)) + { + float_raise(status, float_flag_invalid); + return float32_default_nan; + } + + if (aExp == 0x7FFF) { + if ((Bit64u) (aSig<<1)) + return commonNaNToFloat32(floatx80ToCommonNaN(a, status)); + + return packFloat32(aSign, 0xFF, 0); + } + aSig = shift64RightJamming(aSig, 33); + if (aExp || aSig) aExp -= 0x3F81; + return roundAndPackFloat32(aSign, aExp, (Bit32u) aSig, status); +} + +/*---------------------------------------------------------------------------- +| Returns the result of converting the extended double-precision floating- +| point value `a' to the double-precision floating-point format. The +| conversion is performed according to the IEC/IEEE Standard for Binary +| Floating-Point Arithmetic. +*----------------------------------------------------------------------------*/ + +float64 floatx80_to_float64(floatx80 a, struct float_status_t *status) +{ + Bit32s aExp; + Bit64u aSig, zSig; + + // handle unsupported extended double-precision floating encodings + if (floatx80_is_unsupported(a)) + { + float_raise(status, float_flag_invalid); + return float64_default_nan; + } + + aSig = extractFloatx80Frac(a); + aExp = extractFloatx80Exp(a); + int aSign = extractFloatx80Sign(a); + + if (aExp == 0x7FFF) { + if ((Bit64u) (aSig<<1)) { + return commonNaNToFloat64(floatx80ToCommonNaN(a, status)); + } + return packFloat64(aSign, 0x7FF, 0); + } + zSig = shift64RightJamming(aSig, 1); + if (aExp || aSig) aExp -= 0x3C01; + return roundAndPackFloat64(aSign, aExp, zSig, status); +} + +/*---------------------------------------------------------------------------- +| Rounds the extended double-precision floating-point value `a' to an integer, +| and returns the result as an extended double-precision floating-point +| value. The operation is performed according to the IEC/IEEE Standard for +| Binary Floating-Point Arithmetic. +*----------------------------------------------------------------------------*/ + +floatx80 floatx80_round_to_int(floatx80 a, struct float_status_t *status) +{ +/*---------------------------------------------------------------------------- +| The pattern for a default generated extended double-precision NaN. +*----------------------------------------------------------------------------*/ + const floatx80 floatx80_default_nan = packFloatx80(0, floatx80_default_nan_exp, floatx80_default_nan_fraction); + + int aSign; + Bit64u lastBitMask, roundBitsMask; + int roundingMode = get_float_rounding_mode(status); + floatx80 z; + + // handle unsupported extended double-precision floating encodings + if (floatx80_is_unsupported(a)) + { + float_raise(status, float_flag_invalid); + return floatx80_default_nan; + } + + Bit32s aExp = extractFloatx80Exp(a); + Bit64u aSig = extractFloatx80Frac(a); + if (0x403E <= aExp) { + if ((aExp == 0x7FFF) && (Bit64u) (aSig<<1)) { + return propagateFloatx80NaNOne(a, status); + } + return a; + } + if (aExp < 0x3FFF) { + if (aExp == 0) { + if ((aSig<<1) == 0) return a; + float_raise(status, float_flag_denormal); + } + float_raise(status, float_flag_inexact); + aSign = extractFloatx80Sign(a); + switch (roundingMode) { + case float_round_nearest_even: + if ((aExp == 0x3FFE) && (Bit64u) (aSig<<1)) { + set_float_rounding_up(status); + return packFloatx80(aSign, 0x3FFF, BX_CONST64(0x8000000000000000)); + } + break; + case float_round_down: + if (aSign) { + set_float_rounding_up(status); + return packFloatx80(1, 0x3FFF, BX_CONST64(0x8000000000000000)); + } + else { + return packFloatx80(0, 0, 0); + } + case float_round_up: + if (aSign) { + return packFloatx80(1, 0, 0); + } + else { + set_float_rounding_up(status); + return packFloatx80(0, 0x3FFF, BX_CONST64(0x8000000000000000)); + } + } + return packFloatx80(aSign, 0, 0); + } + lastBitMask = 1; + lastBitMask <<= 0x403E - aExp; + roundBitsMask = lastBitMask - 1; + z = a; + if (roundingMode == float_round_nearest_even) { + z.fraction += lastBitMask>>1; + if ((z.fraction & roundBitsMask) == 0) z.fraction &= ~lastBitMask; + } + else if (roundingMode != float_round_to_zero) { + if (extractFloatx80Sign(z) ^ (roundingMode == float_round_up)) + z.fraction += roundBitsMask; + } + z.fraction &= ~roundBitsMask; + if (z.fraction == 0) { + z.exp++; + z.fraction = BX_CONST64(0x8000000000000000); + } + if (z.fraction != a.fraction) { + float_raise(status, float_flag_inexact); + if (z.fraction > a.fraction || z.exp > a.exp) + set_float_rounding_up(status); + } + return z; +} + +/*---------------------------------------------------------------------------- +| Returns the result of adding the absolute values of the extended double- +| precision floating-point values `a' and `b'. If `zSign' is 1, the sum is +| negated before being returned. `zSign' is ignored if the result is a NaN. +| The addition is performed according to the IEC/IEEE Standard for Binary +| Floating-Point Arithmetic. +*----------------------------------------------------------------------------*/ + +static floatx80 addFloatx80Sigs(floatx80 a, floatx80 b, int zSign, struct float_status_t *status) +{ +/*---------------------------------------------------------------------------- +| The pattern for a default generated extended double-precision NaN. +*----------------------------------------------------------------------------*/ + const floatx80 floatx80_default_nan = packFloatx80(0, floatx80_default_nan_exp, floatx80_default_nan_fraction); + + Bit32s aExp, bExp, zExp; + Bit64u aSig, bSig, zSig0, zSig1; + + // handle unsupported extended double-precision floating encodings + if (floatx80_is_unsupported(a) || floatx80_is_unsupported(b)) + { + float_raise(status, float_flag_invalid); + return floatx80_default_nan; + } + + aSig = extractFloatx80Frac(a); + aExp = extractFloatx80Exp(a); + bSig = extractFloatx80Frac(b); + bExp = extractFloatx80Exp(b); + + if (aExp == 0x7FFF) { + if ((Bit64u) (aSig<<1) || ((bExp == 0x7FFF) && (Bit64u) (bSig<<1))) + return propagateFloatx80NaN(a, b, status); + if (bSig && (bExp == 0)) float_raise(status, float_flag_denormal); + return a; + } + if (bExp == 0x7FFF) { + if ((Bit64u) (bSig<<1)) return propagateFloatx80NaN(a, b, status); + if (aSig && (aExp == 0)) float_raise(status, float_flag_denormal); + return packFloatx80(zSign, 0x7FFF, BX_CONST64(0x8000000000000000)); + } + if (aExp == 0) { + if (aSig == 0) { + if ((bExp == 0) && bSig) { + float_raise(status, float_flag_denormal); + normalizeFloatx80Subnormal(bSig, &bExp, &bSig); + } + return roundAndPackFloatx80(get_float_rounding_precision(status), + zSign, bExp, bSig, 0, status); + } + float_raise(status, float_flag_denormal); + normalizeFloatx80Subnormal(aSig, &aExp, &aSig); + } + if (bExp == 0) { + if (bSig == 0) + return roundAndPackFloatx80(get_float_rounding_precision(status), + zSign, aExp, aSig, 0, status); + + float_raise(status, float_flag_denormal); + normalizeFloatx80Subnormal(bSig, &bExp, &bSig); + } + Bit32s expDiff = aExp - bExp; + zExp = aExp; + if (0 < expDiff) { + shift64ExtraRightJamming(bSig, 0, expDiff, &bSig, &zSig1); + } + else if (expDiff < 0) { + shift64ExtraRightJamming(aSig, 0, -expDiff, &aSig, &zSig1); + zExp = bExp; + } + else { + zSig0 = aSig + bSig; + zSig1 = 0; + goto shiftRight1; + } + zSig0 = aSig + bSig; + if ((Bit64s) zSig0 < 0) goto roundAndPack; + shiftRight1: + shift64ExtraRightJamming(zSig0, zSig1, 1, &zSig0, &zSig1); + zSig0 |= BX_CONST64(0x8000000000000000); + zExp++; + roundAndPack: + return + roundAndPackFloatx80(get_float_rounding_precision(status), + zSign, zExp, zSig0, zSig1, status); +} + +/*---------------------------------------------------------------------------- +| Returns the result of subtracting the absolute values of the extended +| double-precision floating-point values `a' and `b'. If `zSign' is 1, the +| difference is negated before being returned. `zSign' is ignored if the +| result is a NaN. The subtraction is performed according to the IEC/IEEE +| Standard for Binary Floating-Point Arithmetic. +*----------------------------------------------------------------------------*/ + +static floatx80 subFloatx80Sigs(floatx80 a, floatx80 b, int zSign, struct float_status_t *status) +{ +/*---------------------------------------------------------------------------- +| The pattern for a default generated extended double-precision NaN. +*----------------------------------------------------------------------------*/ + const floatx80 floatx80_default_nan = packFloatx80(0, floatx80_default_nan_exp, floatx80_default_nan_fraction); + + Bit32s aExp, bExp, zExp; + Bit64u aSig, bSig, zSig0, zSig1; + + // handle unsupported extended double-precision floating encodings + if (floatx80_is_unsupported(a) || floatx80_is_unsupported(b)) + { + float_raise(status, float_flag_invalid); + return floatx80_default_nan; + } + + aSig = extractFloatx80Frac(a); + aExp = extractFloatx80Exp(a); + bSig = extractFloatx80Frac(b); + bExp = extractFloatx80Exp(b); + + if (aExp == 0x7FFF) { + if ((Bit64u) (aSig<<1)) return propagateFloatx80NaN(a, b, status); + if (bExp == 0x7FFF) { + if ((Bit64u) (bSig<<1)) return propagateFloatx80NaN(a, b, status); + float_raise(status, float_flag_invalid); + return floatx80_default_nan; + } + if (bSig && (bExp == 0)) float_raise(status, float_flag_denormal); + return a; + } + if (bExp == 0x7FFF) { + if ((Bit64u) (bSig<<1)) return propagateFloatx80NaN(a, b, status); + if (aSig && (aExp == 0)) float_raise(status, float_flag_denormal); + return packFloatx80(zSign ^ 1, 0x7FFF, BX_CONST64(0x8000000000000000)); + } + if (aExp == 0) { + if (aSig == 0) { + if (bExp == 0) { + if (bSig) { + float_raise(status, float_flag_denormal); + normalizeFloatx80Subnormal(bSig, &bExp, &bSig); + return roundAndPackFloatx80(get_float_rounding_precision(status), + zSign ^ 1, bExp, bSig, 0, status); + } + return packFloatx80(get_float_rounding_mode(status) == float_round_down, 0, 0); + } + return roundAndPackFloatx80(get_float_rounding_precision(status), + zSign ^ 1, bExp, bSig, 0, status); + } + float_raise(status, float_flag_denormal); + normalizeFloatx80Subnormal(aSig, &aExp, &aSig); + } + if (bExp == 0) { + if (bSig == 0) + return roundAndPackFloatx80(get_float_rounding_precision(status), + zSign, aExp, aSig, 0, status); + + float_raise(status, float_flag_denormal); + normalizeFloatx80Subnormal(bSig, &bExp, &bSig); + } + Bit32s expDiff = aExp - bExp; + if (0 < expDiff) { + shift128RightJamming(bSig, 0, expDiff, &bSig, &zSig1); + goto aBigger; + } + if (expDiff < 0) { + shift128RightJamming(aSig, 0, -expDiff, &aSig, &zSig1); + goto bBigger; + } + zSig1 = 0; + if (bSig < aSig) goto aBigger; + if (aSig < bSig) goto bBigger; + return packFloatx80(get_float_rounding_mode(status) == float_round_down, 0, 0); + bBigger: + sub128(bSig, 0, aSig, zSig1, &zSig0, &zSig1); + zExp = bExp; + zSign ^= 1; + goto normalizeRoundAndPack; + aBigger: + sub128(aSig, 0, bSig, zSig1, &zSig0, &zSig1); + zExp = aExp; + normalizeRoundAndPack: + return + normalizeRoundAndPackFloatx80(get_float_rounding_precision(status), + zSign, zExp, zSig0, zSig1, status); +} + +/*---------------------------------------------------------------------------- +| Returns the result of adding the extended double-precision floating-point +| values `a' and `b'. The operation is performed according to the IEC/IEEE +| Standard for Binary Floating-Point Arithmetic. +*----------------------------------------------------------------------------*/ + +floatx80 floatx80_add(floatx80 a, floatx80 b, struct float_status_t *status) +{ + int aSign = extractFloatx80Sign(a); + int bSign = extractFloatx80Sign(b); + + if (aSign == bSign) + return addFloatx80Sigs(a, b, aSign, status); + else + return subFloatx80Sigs(a, b, aSign, status); +} + +/*---------------------------------------------------------------------------- +| Returns the result of subtracting the extended double-precision floating- +| point values `a' and `b'. The operation is performed according to the +| IEC/IEEE Standard for Binary Floating-Point Arithmetic. +*----------------------------------------------------------------------------*/ + +floatx80 floatx80_sub(floatx80 a, floatx80 b, struct float_status_t *status) +{ + int aSign = extractFloatx80Sign(a); + int bSign = extractFloatx80Sign(b); + + if (aSign == bSign) + return subFloatx80Sigs(a, b, aSign, status); + else + return addFloatx80Sigs(a, b, aSign, status); +} + +/*---------------------------------------------------------------------------- +| Returns the result of multiplying the extended double-precision floating- +| point values `a' and `b'. The operation is performed according to the +| IEC/IEEE Standard for Binary Floating-Point Arithmetic. +*----------------------------------------------------------------------------*/ + +floatx80 floatx80_mul(floatx80 a, floatx80 b, struct float_status_t *status) +{ +/*---------------------------------------------------------------------------- +| The pattern for a default generated extended double-precision NaN. +*----------------------------------------------------------------------------*/ + const floatx80 floatx80_default_nan = packFloatx80(0, floatx80_default_nan_exp, floatx80_default_nan_fraction); + + int aSign, bSign, zSign; + Bit32s aExp, bExp, zExp; + Bit64u aSig, bSig, zSig0, zSig1; + + // handle unsupported extended double-precision floating encodings + if (floatx80_is_unsupported(a) || floatx80_is_unsupported(b)) + { + invalid: + float_raise(status, float_flag_invalid); + return floatx80_default_nan; + } + + aSig = extractFloatx80Frac(a); + aExp = extractFloatx80Exp(a); + aSign = extractFloatx80Sign(a); + bSig = extractFloatx80Frac(b); + bExp = extractFloatx80Exp(b); + bSign = extractFloatx80Sign(b); + zSign = aSign ^ bSign; + + if (aExp == 0x7FFF) { + if ((Bit64u) (aSig<<1) || ((bExp == 0x7FFF) && (Bit64u) (bSig<<1))) { + return propagateFloatx80NaN(a, b, status); + } + if (bExp == 0) { + if (bSig == 0) goto invalid; + float_raise(status, float_flag_denormal); + } + return packFloatx80(zSign, 0x7FFF, BX_CONST64(0x8000000000000000)); + } + if (bExp == 0x7FFF) { + if ((Bit64u) (bSig<<1)) return propagateFloatx80NaN(a, b, status); + if (aExp == 0) { + if (aSig == 0) goto invalid; + float_raise(status, float_flag_denormal); + } + return packFloatx80(zSign, 0x7FFF, BX_CONST64(0x8000000000000000)); + } + if (aExp == 0) { + if (aSig == 0) { + if (bSig && (bExp == 0)) float_raise(status, float_flag_denormal); + return packFloatx80(zSign, 0, 0); + } + float_raise(status, float_flag_denormal); + normalizeFloatx80Subnormal(aSig, &aExp, &aSig); + } + if (bExp == 0) { + if (bSig == 0) return packFloatx80(zSign, 0, 0); + float_raise(status, float_flag_denormal); + normalizeFloatx80Subnormal(bSig, &bExp, &bSig); + } + zExp = aExp + bExp - 0x3FFE; + mul64To128(aSig, bSig, &zSig0, &zSig1); + if (0 < (Bit64s) zSig0) { + shortShift128Left(zSig0, zSig1, 1, &zSig0, &zSig1); + --zExp; + } + return + roundAndPackFloatx80(get_float_rounding_precision(status), + zSign, zExp, zSig0, zSig1, status); +} + +/*---------------------------------------------------------------------------- +| Returns the result of dividing the extended double-precision floating-point +| value `a' by the corresponding value `b'. The operation is performed +| according to the IEC/IEEE Standard for Binary Floating-Point Arithmetic. +*----------------------------------------------------------------------------*/ + +floatx80 floatx80_div(floatx80 a, floatx80 b, struct float_status_t *status) +{ +/*---------------------------------------------------------------------------- +| The pattern for a default generated extended double-precision NaN. +*----------------------------------------------------------------------------*/ + const floatx80 floatx80_default_nan = packFloatx80(0, floatx80_default_nan_exp, floatx80_default_nan_fraction); + + int aSign, bSign, zSign; + Bit32s aExp, bExp, zExp; + Bit64u aSig, bSig, zSig0, zSig1; + Bit64u rem0, rem1, rem2, term0, term1, term2; + + // handle unsupported extended double-precision floating encodings + if (floatx80_is_unsupported(a) || floatx80_is_unsupported(b)) + { + float_raise(status, float_flag_invalid); + return floatx80_default_nan; + } + + aSig = extractFloatx80Frac(a); + aExp = extractFloatx80Exp(a); + aSign = extractFloatx80Sign(a); + bSig = extractFloatx80Frac(b); + bExp = extractFloatx80Exp(b); + bSign = extractFloatx80Sign(b); + + zSign = aSign ^ bSign; + if (aExp == 0x7FFF) { + if ((Bit64u) (aSig<<1)) return propagateFloatx80NaN(a, b, status); + if (bExp == 0x7FFF) { + if ((Bit64u) (bSig<<1)) return propagateFloatx80NaN(a, b, status); + float_raise(status, float_flag_invalid); + return floatx80_default_nan; + } + if (bSig && (bExp == 0)) float_raise(status, float_flag_denormal); + return packFloatx80(zSign, 0x7FFF, BX_CONST64(0x8000000000000000)); + } + if (bExp == 0x7FFF) { + if ((Bit64u) (bSig<<1)) return propagateFloatx80NaN(a, b, status); + if (aSig && (aExp == 0)) float_raise(status, float_flag_denormal); + return packFloatx80(zSign, 0, 0); + } + if (bExp == 0) { + if (bSig == 0) { + if ((aExp | aSig) == 0) { + float_raise(status, float_flag_invalid); + return floatx80_default_nan; + } + float_raise(status, float_flag_divbyzero); + return packFloatx80(zSign, 0x7FFF, BX_CONST64(0x8000000000000000)); + } + float_raise(status, float_flag_denormal); + normalizeFloatx80Subnormal(bSig, &bExp, &bSig); + } + if (aExp == 0) { + if (aSig == 0) return packFloatx80(zSign, 0, 0); + float_raise(status, float_flag_denormal); + normalizeFloatx80Subnormal(aSig, &aExp, &aSig); + } + zExp = aExp - bExp + 0x3FFE; + rem1 = 0; + if (bSig <= aSig) { + shift128Right(aSig, 0, 1, &aSig, &rem1); + ++zExp; + } + zSig0 = estimateDiv128To64(aSig, rem1, bSig); + mul64To128(bSig, zSig0, &term0, &term1); + sub128(aSig, rem1, term0, term1, &rem0, &rem1); + while ((Bit64s) rem0 < 0) { + --zSig0; + add128(rem0, rem1, 0, bSig, &rem0, &rem1); + } + zSig1 = estimateDiv128To64(rem1, 0, bSig); + if ((Bit64u) (zSig1<<1) <= 8) { + mul64To128(bSig, zSig1, &term1, &term2); + sub128(rem1, 0, term1, term2, &rem1, &rem2); + while ((Bit64s) rem1 < 0) { + --zSig1; + add128(rem1, rem2, 0, bSig, &rem1, &rem2); + } + zSig1 |= ((rem1 | rem2) != 0); + } + return + roundAndPackFloatx80(get_float_rounding_precision(status), + zSign, zExp, zSig0, zSig1, status); +} + +/*---------------------------------------------------------------------------- +| Returns the square root of the extended double-precision floating-point +| value `a'. The operation is performed according to the IEC/IEEE Standard +| for Binary Floating-Point Arithmetic. +*----------------------------------------------------------------------------*/ + +floatx80 floatx80_sqrt(floatx80 a, struct float_status_t *status) +{ +/*---------------------------------------------------------------------------- +| The pattern for a default generated extended double-precision NaN. +*----------------------------------------------------------------------------*/ + const floatx80 floatx80_default_nan = packFloatx80(0, floatx80_default_nan_exp, floatx80_default_nan_fraction); + + int aSign; + Bit32s aExp, zExp; + Bit64u aSig0, aSig1, zSig0, zSig1, doubleZSig0; + Bit64u rem0, rem1, rem2, rem3, term0, term1, term2, term3; + + // handle unsupported extended double-precision floating encodings + if (floatx80_is_unsupported(a)) + { + float_raise(status, float_flag_invalid); + return floatx80_default_nan; + } + + aSig0 = extractFloatx80Frac(a); + aExp = extractFloatx80Exp(a); + aSign = extractFloatx80Sign(a); + if (aExp == 0x7FFF) { + if ((Bit64u) (aSig0<<1)) return propagateFloatx80NaNOne(a, status); + if (! aSign) return a; + float_raise(status, float_flag_invalid); + return floatx80_default_nan; + } + if (aSign) { + if ((aExp | aSig0) == 0) return a; + float_raise(status, float_flag_invalid); + return floatx80_default_nan; + } + if (aExp == 0) { + if (aSig0 == 0) return packFloatx80(0, 0, 0); + float_raise(status, float_flag_denormal); + normalizeFloatx80Subnormal(aSig0, &aExp, &aSig0); + } + zExp = ((aExp - 0x3FFF)>>1) + 0x3FFF; + zSig0 = estimateSqrt32(aExp, aSig0>>32); + shift128Right(aSig0, 0, 2 + (aExp & 1), &aSig0, &aSig1); + zSig0 = estimateDiv128To64(aSig0, aSig1, zSig0<<32) + (zSig0<<30); + doubleZSig0 = zSig0<<1; + mul64To128(zSig0, zSig0, &term0, &term1); + sub128(aSig0, aSig1, term0, term1, &rem0, &rem1); + while ((Bit64s) rem0 < 0) { + --zSig0; + doubleZSig0 -= 2; + add128(rem0, rem1, zSig0>>63, doubleZSig0 | 1, &rem0, &rem1); + } + zSig1 = estimateDiv128To64(rem1, 0, doubleZSig0); + if ((zSig1 & BX_CONST64(0x3FFFFFFFFFFFFFFF)) <= 5) { + if (zSig1 == 0) zSig1 = 1; + mul64To128(doubleZSig0, zSig1, &term1, &term2); + sub128(rem1, 0, term1, term2, &rem1, &rem2); + mul64To128(zSig1, zSig1, &term2, &term3); + sub192(rem1, rem2, 0, 0, term2, term3, &rem1, &rem2, &rem3); + while ((Bit64s) rem1 < 0) { + --zSig1; + shortShift128Left(0, zSig1, 1, &term2, &term3); + term3 |= 1; + term2 |= doubleZSig0; + add192(rem1, rem2, rem3, 0, term2, term3, &rem1, &rem2, &rem3); + } + zSig1 |= ((rem1 | rem2 | rem3) != 0); + } + shortShift128Left(0, zSig1, 1, &zSig0, &zSig1); + zSig0 |= doubleZSig0; + return + roundAndPackFloatx80(get_float_rounding_precision(status), + 0, zExp, zSig0, zSig1, status); +} + +#endif + +#ifdef FLOAT128 + +/*---------------------------------------------------------------------------- +| Returns the result of converting the extended double-precision floating- +| point value `a' to the quadruple-precision floating-point format. The +| conversion is performed according to the IEC/IEEE Standard for Binary +| Floating-Point Arithmetic. +*----------------------------------------------------------------------------*/ + +float128 floatx80_to_float128(floatx80 a, struct float_status_t *status) +{ + Bit64u zSig0, zSig1; + + Bit64u aSig = extractFloatx80Frac(a); + Bit32s aExp = extractFloatx80Exp(a); + int aSign = extractFloatx80Sign(a); + + if ((aExp == 0x7FFF) && (Bit64u) (aSig<<1)) + return commonNaNToFloat128(floatx80ToCommonNaN(a, status)); + + shift128Right(aSig<<1, 0, 16, &zSig0, &zSig1); + return packFloat128Four(aSign, aExp, zSig0, zSig1); +} + +/*---------------------------------------------------------------------------- +| Returns the result of converting the quadruple-precision floating-point +| value `a' to the extended double-precision floating-point format. The +| conversion is performed according to the IEC/IEEE Standard for Binary +| Floating-Point Arithmetic. +*----------------------------------------------------------------------------*/ + +floatx80 float128_to_floatx80(float128 a, struct float_status_t *status) +{ + Bit32s aExp; + Bit64u aSig0, aSig1; + + aSig1 = extractFloat128Frac1(a); + aSig0 = extractFloat128Frac0(a); + aExp = extractFloat128Exp(a); + int aSign = extractFloat128Sign(a); + + if (aExp == 0x7FFF) { + if (aSig0 | aSig1) + return commonNaNToFloatx80(float128ToCommonNaN(a, status)); + + return packFloatx80(aSign, 0x7FFF, BX_CONST64(0x8000000000000000)); + } + + if (aExp == 0) { + if ((aSig0 | aSig1) == 0) return packFloatx80(aSign, 0, 0); + float_raise(status, float_flag_denormal); + normalizeFloat128Subnormal(aSig0, aSig1, &aExp, &aSig0, &aSig1); + } + else aSig0 |= BX_CONST64(0x0001000000000000); + + shortShift128Left(aSig0, aSig1, 15, &aSig0, &aSig1); + return roundAndPackFloatx80(80, aSign, aExp, aSig0, aSig1, status); +} + +/*---------------------------------------------------------------------------- +| Returns the result of multiplying the extended double-precision floating- +| point value `a' and quadruple-precision floating point value `b'. The +| operation is performed according to the IEC/IEEE Standard for Binary +| Floating-Point Arithmetic. +*----------------------------------------------------------------------------*/ + +floatx80 floatx80_128_mul(floatx80 a, float128 b, struct float_status_t *status) +{ +/*---------------------------------------------------------------------------- +| The pattern for a default generated extended double-precision NaN. +*----------------------------------------------------------------------------*/ + const floatx80 floatx80_default_nan = packFloatx80(0, floatx80_default_nan_exp, floatx80_default_nan_fraction); + + Bit32s aExp, bExp, zExp; + Bit64u aSig, bSig0, bSig1, zSig0, zSig1, zSig2; + int aSign, bSign, zSign; + + // handle unsupported extended double-precision floating encodings + if (floatx80_is_unsupported(a)) + { + invalid: + float_raise(status, float_flag_invalid); + return floatx80_default_nan; + } + + aSig = extractFloatx80Frac(a); + aExp = extractFloatx80Exp(a); + aSign = extractFloatx80Sign(a); + bSig0 = extractFloat128Frac0(b); + bSig1 = extractFloat128Frac1(b); + bExp = extractFloat128Exp(b); + bSign = extractFloat128Sign(b); + + zSign = aSign ^ bSign; + + if (aExp == 0x7FFF) { + if ((Bit64u) (aSig<<1) + || ((bExp == 0x7FFF) && (bSig0 | bSig1))) + { + floatx80 r = commonNaNToFloatx80(float128ToCommonNaN(b, status)); + return propagateFloatx80NaN(a, r, status); + } + if (bExp == 0) { + if ((bSig0 | bSig1) == 0) goto invalid; + float_raise(status, float_flag_denormal); + } + return packFloatx80(zSign, 0x7FFF, BX_CONST64(0x8000000000000000)); + } + if (bExp == 0x7FFF) { + if (bSig0 | bSig1) { + floatx80 r = commonNaNToFloatx80(float128ToCommonNaN(b, status)); + return propagateFloatx80NaN(a, r, status); + } + if (aExp == 0) { + if (aSig == 0) goto invalid; + float_raise(status, float_flag_denormal); + } + return packFloatx80(zSign, 0x7FFF, BX_CONST64(0x8000000000000000)); + } + if (aExp == 0) { + if (aSig == 0) { + if ((bExp == 0) && (bSig0 | bSig1)) float_raise(status, float_flag_denormal); + return packFloatx80(zSign, 0, 0); + } + float_raise(status, float_flag_denormal); + normalizeFloatx80Subnormal(aSig, &aExp, &aSig); + } + if (bExp == 0) { + if ((bSig0 | bSig1) == 0) return packFloatx80(zSign, 0, 0); + float_raise(status, float_flag_denormal); + normalizeFloat128Subnormal(bSig0, bSig1, &bExp, &bSig0, &bSig1); + } + else bSig0 |= BX_CONST64(0x0001000000000000); + + zExp = aExp + bExp - 0x3FFE; + shortShift128Left(bSig0, bSig1, 15, &bSig0, &bSig1); + mul128By64To192(bSig0, bSig1, aSig, &zSig0, &zSig1, &zSig2); + if (0 < (Bit64s) zSig0) { + shortShift128Left(zSig0, zSig1, 1, &zSig0, &zSig1); + --zExp; + } + return + roundAndPackFloatx80(get_float_rounding_precision(status), + zSign, zExp, zSig0, zSig1, status); +} + +/*---------------------------------------------------------------------------- +| Returns the result of adding the absolute values of the quadruple-precision +| floating-point values `a' and `b'. If `zSign' is 1, the sum is negated +| before being returned. `zSign' is ignored if the result is a NaN. +| The addition is performed according to the IEC/IEEE Standard for Binary +| Floating-Point Arithmetic. +*----------------------------------------------------------------------------*/ + +static float128 addFloat128Sigs(float128 a, float128 b, int zSign, struct float_status_t *status) +{ + Bit32s aExp, bExp, zExp; + Bit64u aSig0, aSig1, bSig0, bSig1, zSig0, zSig1, zSig2; + Bit32s expDiff; + + aSig1 = extractFloat128Frac1(a); + aSig0 = extractFloat128Frac0(a); + aExp = extractFloat128Exp(a); + bSig1 = extractFloat128Frac1(b); + bSig0 = extractFloat128Frac0(b); + bExp = extractFloat128Exp(b); + expDiff = aExp - bExp; + + if (0 < expDiff) { + if (aExp == 0x7FFF) { + if (aSig0 | aSig1) return propagateFloat128NaN(a, b, status); + return a; + } + if (bExp == 0) --expDiff; + else bSig0 |= BX_CONST64(0x0001000000000000); + shift128ExtraRightJamming(bSig0, bSig1, 0, expDiff, &bSig0, &bSig1, &zSig2); + zExp = aExp; + } + else if (expDiff < 0) { + if (bExp == 0x7FFF) { + if (bSig0 | bSig1) return propagateFloat128NaN(a, b, status); + return packFloat128Four(zSign, 0x7FFF, 0, 0); + } + if (aExp == 0) ++expDiff; + else aSig0 |= BX_CONST64(0x0001000000000000); + shift128ExtraRightJamming(aSig0, aSig1, 0, -expDiff, &aSig0, &aSig1, &zSig2); + zExp = bExp; + } + else { + if (aExp == 0x7FFF) { + if (aSig0 | aSig1 | bSig0 | bSig1) + return propagateFloat128NaN(a, b, status); + + return a; + } + add128(aSig0, aSig1, bSig0, bSig1, &zSig0, &zSig1); + if (aExp == 0) return packFloat128Four(zSign, 0, zSig0, zSig1); + zSig2 = 0; + zSig0 |= BX_CONST64(0x0002000000000000); + zExp = aExp; + goto shiftRight1; + } + aSig0 |= BX_CONST64(0x0001000000000000); + add128(aSig0, aSig1, bSig0, bSig1, &zSig0, &zSig1); + --zExp; + if (zSig0 < BX_CONST64(0x0002000000000000)) goto roundAndPack; + ++zExp; + shiftRight1: + shift128ExtraRightJamming(zSig0, zSig1, zSig2, 1, &zSig0, &zSig1, &zSig2); + roundAndPack: + return roundAndPackFloat128(zSign, zExp, zSig0, zSig1, zSig2, status); +} + +/*---------------------------------------------------------------------------- +| Returns the result of subtracting the absolute values of the quadruple- +| precision floating-point values `a' and `b'. If `zSign' is 1, the +| difference is negated before being returned. `zSign' is ignored if the +| result is a NaN. The subtraction is performed according to the IEC/IEEE +| Standard for Binary Floating-Point Arithmetic. +*----------------------------------------------------------------------------*/ + +static float128 subFloat128Sigs(float128 a, float128 b, int zSign, struct float_status_t *status) +{ + Bit32s aExp, bExp, zExp; + Bit64u aSig0, aSig1, bSig0, bSig1, zSig0, zSig1; + Bit32s expDiff; + + aSig1 = extractFloat128Frac1(a); + aSig0 = extractFloat128Frac0(a); + aExp = extractFloat128Exp(a); + bSig1 = extractFloat128Frac1(b); + bSig0 = extractFloat128Frac0(b); + bExp = extractFloat128Exp(b); + + expDiff = aExp - bExp; + shortShift128Left(aSig0, aSig1, 14, &aSig0, &aSig1); + shortShift128Left(bSig0, bSig1, 14, &bSig0, &bSig1); + if (0 < expDiff) goto aExpBigger; + if (expDiff < 0) goto bExpBigger; + if (aExp == 0x7FFF) { + if (aSig0 | aSig1 | bSig0 | bSig1) + return propagateFloat128NaN(a, b, status); + + float_raise(status, float_flag_invalid); + return float128_default_nan; + } + if (aExp == 0) { + aExp = 1; + bExp = 1; + } + if (bSig0 < aSig0) goto aBigger; + if (aSig0 < bSig0) goto bBigger; + if (bSig1 < aSig1) goto aBigger; + if (aSig1 < bSig1) goto bBigger; + return packFloat128(0, 0); + + bExpBigger: + if (bExp == 0x7FFF) { + if (bSig0 | bSig1) return propagateFloat128NaN(a, b, status); + return packFloat128Four(zSign ^ 1, 0x7FFF, 0, 0); + } + if (aExp == 0) ++expDiff; + else { + aSig0 |= BX_CONST64(0x4000000000000000); + } + shift128RightJamming(aSig0, aSig1, - expDiff, &aSig0, &aSig1); + bSig0 |= BX_CONST64(0x4000000000000000); + bBigger: + sub128(bSig0, bSig1, aSig0, aSig1, &zSig0, &zSig1); + zExp = bExp; + zSign ^= 1; + goto normalizeRoundAndPack; + aExpBigger: + if (aExp == 0x7FFF) { + if (aSig0 | aSig1) return propagateFloat128NaN(a, b, status); + return a; + } + if (bExp == 0) --expDiff; + else { + bSig0 |= BX_CONST64(0x4000000000000000); + } + shift128RightJamming(bSig0, bSig1, expDiff, &bSig0, &bSig1); + aSig0 |= BX_CONST64(0x4000000000000000); + aBigger: + sub128(aSig0, aSig1, bSig0, bSig1, &zSig0, &zSig1); + zExp = aExp; + normalizeRoundAndPack: + --zExp; + return normalizeRoundAndPackFloat128(zSign, zExp - 14, zSig0, zSig1, status); +} + +/*---------------------------------------------------------------------------- +| Returns the result of adding the quadruple-precision floating-point values +| `a' and `b'. The operation is performed according to the IEC/IEEE Standard +| for Binary Floating-Point Arithmetic. +*----------------------------------------------------------------------------*/ + +float128 float128_add(float128 a, float128 b, struct float_status_t *status) +{ + int aSign = extractFloat128Sign(a); + int bSign = extractFloat128Sign(b); + + if (aSign == bSign) { + return addFloat128Sigs(a, b, aSign, status); + } + else { + return subFloat128Sigs(a, b, aSign, status); + } +} + +/*---------------------------------------------------------------------------- +| Returns the result of subtracting the quadruple-precision floating-point +| values `a' and `b'. The operation is performed according to the IEC/IEEE +| Standard for Binary Floating-Point Arithmetic. +*----------------------------------------------------------------------------*/ + +float128 float128_sub(float128 a, float128 b, struct float_status_t *status) +{ + int aSign = extractFloat128Sign(a); + int bSign = extractFloat128Sign(b); + + if (aSign == bSign) { + return subFloat128Sigs(a, b, aSign, status); + } + else { + return addFloat128Sigs(a, b, aSign, status); + } +} + +/*---------------------------------------------------------------------------- +| Returns the result of multiplying the quadruple-precision floating-point +| values `a' and `b'. The operation is performed according to the IEC/IEEE +| Standard for Binary Floating-Point Arithmetic. +*----------------------------------------------------------------------------*/ + +float128 float128_mul(float128 a, float128 b, struct float_status_t *status) +{ + int aSign, bSign, zSign; + Bit32s aExp, bExp, zExp; + Bit64u aSig0, aSig1, bSig0, bSig1, zSig0, zSig1, zSig2, zSig3; + + aSig1 = extractFloat128Frac1(a); + aSig0 = extractFloat128Frac0(a); + aExp = extractFloat128Exp(a); + aSign = extractFloat128Sign(a); + bSig1 = extractFloat128Frac1(b); + bSig0 = extractFloat128Frac0(b); + bExp = extractFloat128Exp(b); + bSign = extractFloat128Sign(b); + + zSign = aSign ^ bSign; + if (aExp == 0x7FFF) { + if ((aSig0 | aSig1) || ((bExp == 0x7FFF) && (bSig0 | bSig1))) { + return propagateFloat128NaN(a, b, status); + } + if ((bExp | bSig0 | bSig1) == 0) { + float_raise(status, float_flag_invalid); + return float128_default_nan; + } + return packFloat128Four(zSign, 0x7FFF, 0, 0); + } + if (bExp == 0x7FFF) { + if (bSig0 | bSig1) return propagateFloat128NaN(a, b, status); + if ((aExp | aSig0 | aSig1) == 0) { + float_raise(status, float_flag_invalid); + return float128_default_nan; + } + return packFloat128Four(zSign, 0x7FFF, 0, 0); + } + if (aExp == 0) { + if ((aSig0 | aSig1) == 0) return packFloat128Four(zSign, 0, 0, 0); + float_raise(status, float_flag_denormal); + normalizeFloat128Subnormal(aSig0, aSig1, &aExp, &aSig0, &aSig1); + } + if (bExp == 0) { + if ((bSig0 | bSig1) == 0) return packFloat128Four(zSign, 0, 0, 0); + float_raise(status, float_flag_denormal); + normalizeFloat128Subnormal(bSig0, bSig1, &bExp, &bSig0, &bSig1); + } + zExp = aExp + bExp - 0x4000; + aSig0 |= BX_CONST64(0x0001000000000000); + shortShift128Left(bSig0, bSig1, 16, &bSig0, &bSig1); + mul128To256(aSig0, aSig1, bSig0, bSig1, &zSig0, &zSig1, &zSig2, &zSig3); + add128(zSig0, zSig1, aSig0, aSig1, &zSig0, &zSig1); + zSig2 |= (zSig3 != 0); + if (BX_CONST64(0x0002000000000000) <= zSig0) { + shift128ExtraRightJamming(zSig0, zSig1, zSig2, 1, &zSig0, &zSig1, &zSig2); + ++zExp; + } + return roundAndPackFloat128(zSign, zExp, zSig0, zSig1, zSig2, status); +} + +/*---------------------------------------------------------------------------- +| Returns the result of dividing the quadruple-precision floating-point value +| `a' by the corresponding value `b'. The operation is performed according to +| the IEC/IEEE Standard for Binary Floating-Point Arithmetic. +*----------------------------------------------------------------------------*/ + +float128 float128_div(float128 a, float128 b, struct float_status_t *status) +{ + int aSign, bSign, zSign; + Bit32s aExp, bExp, zExp; + Bit64u aSig0, aSig1, bSig0, bSig1, zSig0, zSig1, zSig2; + Bit64u rem0, rem1, rem2, rem3, term0, term1, term2, term3; + + aSig1 = extractFloat128Frac1(a); + aSig0 = extractFloat128Frac0(a); + aExp = extractFloat128Exp(a); + aSign = extractFloat128Sign(a); + bSig1 = extractFloat128Frac1(b); + bSig0 = extractFloat128Frac0(b); + bExp = extractFloat128Exp(b); + bSign = extractFloat128Sign(b); + + zSign = aSign ^ bSign; + if (aExp == 0x7FFF) { + if (aSig0 | aSig1) return propagateFloat128NaN(a, b, status); + if (bExp == 0x7FFF) { + if (bSig0 | bSig1) return propagateFloat128NaN(a, b, status); + float_raise(status, float_flag_invalid); + return float128_default_nan; + } + return packFloat128Four(zSign, 0x7FFF, 0, 0); + } + if (bExp == 0x7FFF) { + if (bSig0 | bSig1) return propagateFloat128NaN(a, b, status); + return packFloat128Four(zSign, 0, 0, 0); + } + if (bExp == 0) { + if ((bSig0 | bSig1) == 0) { + if ((aExp | aSig0 | aSig1) == 0) { + float_raise(status, float_flag_invalid); + return float128_default_nan; + } + float_raise(status, float_flag_divbyzero); + return packFloat128Four(zSign, 0x7FFF, 0, 0); + } + float_raise(status, float_flag_denormal); + normalizeFloat128Subnormal(bSig0, bSig1, &bExp, &bSig0, &bSig1); + } + if (aExp == 0) { + if ((aSig0 | aSig1) == 0) return packFloat128Four(zSign, 0, 0, 0); + float_raise(status, float_flag_denormal); + normalizeFloat128Subnormal(aSig0, aSig1, &aExp, &aSig0, &aSig1); + } + zExp = aExp - bExp + 0x3FFD; + shortShift128Left( + aSig0 | BX_CONST64(0x0001000000000000), aSig1, 15, &aSig0, &aSig1); + shortShift128Left( + bSig0 | BX_CONST64(0x0001000000000000), bSig1, 15, &bSig0, &bSig1); + if (le128(bSig0, bSig1, aSig0, aSig1)) { + shift128Right(aSig0, aSig1, 1, &aSig0, &aSig1); + ++zExp; + } + zSig0 = estimateDiv128To64(aSig0, aSig1, bSig0); + mul128By64To192(bSig0, bSig1, zSig0, &term0, &term1, &term2); + sub192(aSig0, aSig1, 0, term0, term1, term2, &rem0, &rem1, &rem2); + while ((Bit64s) rem0 < 0) { + --zSig0; + add192(rem0, rem1, rem2, 0, bSig0, bSig1, &rem0, &rem1, &rem2); + } + zSig1 = estimateDiv128To64(rem1, rem2, bSig0); + if ((zSig1 & 0x3FFF) <= 4) { + mul128By64To192(bSig0, bSig1, zSig1, &term1, &term2, &term3); + sub192(rem1, rem2, 0, term1, term2, term3, &rem1, &rem2, &rem3); + while ((Bit64s) rem1 < 0) { + --zSig1; + add192(rem1, rem2, rem3, 0, bSig0, bSig1, &rem1, &rem2, &rem3); + } + zSig1 |= ((rem1 | rem2 | rem3) != 0); + } + shift128ExtraRightJamming(zSig0, zSig1, 0, 15, &zSig0, &zSig1, &zSig2); + return roundAndPackFloat128(zSign, zExp, zSig0, zSig1, zSig2, status); +} + +/*---------------------------------------------------------------------------- +| Returns the result of converting the 64-bit two's complement integer `a' to +| the quadruple-precision floating-point format. The conversion is performed +| according to the IEC/IEEE Standard for Binary Floating-Point Arithmetic. +*----------------------------------------------------------------------------*/ + +float128 int64_to_float128(Bit64s a) +{ + Bit64u zSig0, zSig1; + + if (a == 0) return packFloat128Four(0, 0, 0, 0); + int zSign = (a < 0); + Bit64u absA = zSign ? - a : a; + Bit8u shiftCount = countLeadingZeros64(absA) + 49; + Bit32s zExp = 0x406E - shiftCount; + if (64 <= shiftCount) { + zSig1 = 0; + zSig0 = absA; + shiftCount -= 64; + } + else { + zSig1 = absA; + zSig0 = 0; + } + shortShift128Left(zSig0, zSig1, shiftCount, &zSig0, &zSig1); + return packFloat128Four(zSign, zExp, zSig0, zSig1); +} + +#endif diff --git a/src/cpu/softfloat/softfloat.h b/src/cpu/softfloat/softfloat.h new file mode 100644 index 000000000..1d1b0f08f --- /dev/null +++ b/src/cpu/softfloat/softfloat.h @@ -0,0 +1,488 @@ +/*============================================================================ +This C header file is part of the SoftFloat IEC/IEEE Floating-point Arithmetic +Package, Release 2b. + +Written by John R. Hauser. This work was made possible in part by the +International Computer Science Institute, located at Suite 600, 1947 Center +Street, Berkeley, California 94704. Funding was partially provided by the +National Science Foundation under grant MIP-9311980. The original version +of this code was written as part of a project to build a fixed-point vector +processor in collaboration with the University of California at Berkeley, +overseen by Profs. Nelson Morgan and John Wawrzynek. More information +is available through the Web page `http://www.cs.berkeley.edu/~jhauser/ +arithmetic/SoftFloat.html'. + +THIS SOFTWARE IS DISTRIBUTED AS IS, FOR FREE. Although reasonable effort has +been made to avoid it, THIS SOFTWARE MAY CONTAIN FAULTS THAT WILL AT TIMES +RESULT IN INCORRECT BEHAVIOR. USE OF THIS SOFTWARE IS RESTRICTED TO PERSONS +AND ORGANIZATIONS WHO CAN AND WILL TAKE FULL RESPONSIBILITY FOR ALL LOSSES, +COSTS, OR OTHER PROBLEMS THEY INCUR DUE TO THE SOFTWARE, AND WHO FURTHERMORE +EFFECTIVELY INDEMNIFY JOHN HAUSER AND THE INTERNATIONAL COMPUTER SCIENCE +INSTITUTE (possibly via similar legal warning) AGAINST ALL LOSSES, COSTS, OR +OTHER PROBLEMS INCURRED BY THEIR CUSTOMERS AND CLIENTS DUE TO THE SOFTWARE. + +Derivative works are acceptable, even for commercial purposes, so long as +(1) the source code for the derivative work includes prominent notice that +the work is derivative, and (2) the source code includes prominent notice with +these four paragraphs for those parts of this code that are retained. +=============================================================================*/ + +/*============================================================================ + * Adapted for Bochs (x86 achitecture simulator) by + * Stanislav Shwartsman [sshwarts at sourceforge net] + * ==========================================================================*/ + +#include "config.h" /* generated by configure script from config.h.in */ + +#ifndef _SOFTFLOAT_H_ +#define _SOFTFLOAT_H_ + +#define FLOAT16 +#define FLOATX80 + +/*---------------------------------------------------------------------------- +| Software IEC/IEEE floating-point types. +*----------------------------------------------------------------------------*/ +#ifdef FLOAT16 +typedef Bit16u float16; +#endif +typedef Bit32u float32; +typedef Bit64u float64; + +/*---------------------------------------------------------------------------- +| Software IEC/IEEE floating-point class. +*----------------------------------------------------------------------------*/ +typedef enum { + float_zero, + float_SNaN, + float_QNaN, + float_negative_inf, + float_positive_inf, + float_denormal, + float_normalized +} float_class_t; + +/*---------------------------------------------------------------------------- +| Software IEC/IEEE floating-point NaN operands handling mode. +*----------------------------------------------------------------------------*/ +enum float_nan_handling_mode_t { + float_larger_significand_nan = 0, // this mode used by x87 FPU + float_first_operand_nan = 1 // this mode used by SSE +}; + +/*---------------------------------------------------------------------------- +| Software IEC/IEEE floating-point rounding mode. +*----------------------------------------------------------------------------*/ +enum float_round_t { + float_round_nearest_even = 0, + float_round_down = 1, + float_round_up = 2, + float_round_to_zero = 3 +}; + +/*---------------------------------------------------------------------------- +| Software IEC/IEEE floating-point exception flags. +*----------------------------------------------------------------------------*/ +enum float_exception_flag_t { + float_flag_invalid = 0x01, + float_flag_denormal = 0x02, + float_flag_divbyzero = 0x04, + float_flag_overflow = 0x08, + float_flag_underflow = 0x10, + float_flag_inexact = 0x20 +}; + +extern const unsigned float_all_exceptions_mask; + +#ifdef FLOATX80 +#define RAISE_SW_C1 0x0200 +#endif + +/*---------------------------------------------------------------------------- +| Software IEC/IEEE floating-point ordering relations +*----------------------------------------------------------------------------*/ +enum { + float_relation_less = -1, + float_relation_equal = 0, + float_relation_greater = 1, + float_relation_unordered = 2 +}; + +/*---------------------------------------------------------------------------- +| Options to indicate which negations to perform in float*_muladd() +| Using these differs from negating an input or output before calling +| the muladd function in that this means that a NaN doesn't have its +| sign bit inverted before it is propagated. +*----------------------------------------------------------------------------*/ +enum { + float_muladd_negate_c = 1, + float_muladd_negate_product = 2, + float_muladd_negate_result = float_muladd_negate_c | float_muladd_negate_product +}; + +/*---------------------------------------------------------------------------- +| Software IEC/IEEE floating-point status structure. +*----------------------------------------------------------------------------*/ +struct float_status_t +{ +#ifdef FLOATX80 + int float_rounding_precision; /* floatx80 only */ +#endif + int float_rounding_mode; + int float_exception_flags; + int float_exception_masks; + int float_suppress_exception; + int float_nan_handling_mode; /* flag register */ + int flush_underflow_to_zero; /* flag register */ + int denormals_are_zeros; /* flag register */ +}; + +/*---------------------------------------------------------------------------- +| Routine to raise any or all of the software IEC/IEEE floating-point +| exception flags. +*----------------------------------------------------------------------------*/ + +BX_CPP_INLINE void float_raise(struct float_status_t *status, int flags) +{ + status->float_exception_flags |= flags; +} + +/*---------------------------------------------------------------------------- +| Returns raised IEC/IEEE floating-point exception flags. +*----------------------------------------------------------------------------*/ + +BX_CPP_INLINE int get_exception_flags(const struct float_status_t *status) +{ + return status->float_exception_flags & ~status->float_suppress_exception; +} + +/*---------------------------------------------------------------------------- +| Routine to check if any or all of the software IEC/IEEE floating-point +| exceptions are masked. +*----------------------------------------------------------------------------*/ + +BX_CPP_INLINE int float_exception_masked(const struct float_status_t *status, int flag) +{ + return status->float_exception_masks & flag; +} + +/*---------------------------------------------------------------------------- +| Returns current floating point rounding mode specified by status word. +*----------------------------------------------------------------------------*/ + +BX_CPP_INLINE int get_float_rounding_mode(const struct float_status_t *status) +{ + return status->float_rounding_mode; +} + +/*---------------------------------------------------------------------------- +| Returns current floating point precision (floatx80 only). +*----------------------------------------------------------------------------*/ + +#ifdef FLOATX80 +BX_CPP_INLINE int get_float_rounding_precision(const struct float_status_t *status) +{ + return status->float_rounding_precision; +} +#endif + +/*---------------------------------------------------------------------------- +| Returns current floating point NaN operands handling mode specified +| by status word. +*----------------------------------------------------------------------------*/ + +BX_CPP_INLINE int get_float_nan_handling_mode(const struct float_status_t *status) +{ + return status->float_nan_handling_mode; +} + +/*---------------------------------------------------------------------------- +| Raise floating point precision lost up flag (floatx80 only). +*----------------------------------------------------------------------------*/ + +#ifdef FLOATX80 +BX_CPP_INLINE void set_float_rounding_up(struct float_status_t *status) +{ + status->float_exception_flags |= RAISE_SW_C1; +} +#endif + +/*---------------------------------------------------------------------------- +| Returns 1 if the feature is supported; +| otherwise returns 0. +*----------------------------------------------------------------------------*/ + +BX_CPP_INLINE int get_denormals_are_zeros(const struct float_status_t *status) +{ + return status->denormals_are_zeros; +} + +/*---------------------------------------------------------------------------- +| Returns 1 if the feature is supported; +| otherwise returns 0. +*----------------------------------------------------------------------------*/ + +BX_CPP_INLINE int get_flush_underflow_to_zero(const struct float_status_t *status) +{ + return status->flush_underflow_to_zero; +} + +/*---------------------------------------------------------------------------- +| Software IEC/IEEE integer-to-floating-point conversion routines. +*----------------------------------------------------------------------------*/ +float32 int32_to_float32(Bit32s, struct float_status_t *status); +float64 int32_to_float64(Bit32s); +float32 int64_to_float32(Bit64s, struct float_status_t *status); +float64 int64_to_float64(Bit64s, struct float_status_t *status); + +float32 uint32_to_float32(Bit32u, struct float_status_t *status); +float64 uint32_to_float64(Bit32u); +float32 uint64_to_float32(Bit64u, struct float_status_t *status); +float64 uint64_to_float64(Bit64u, struct float_status_t *status); + +/*---------------------------------------------------------------------------- +| Software IEC/IEEE single-precision conversion routines. +*----------------------------------------------------------------------------*/ +Bit32s float32_to_int32(float32, struct float_status_t *status); +Bit32s float32_to_int32_round_to_zero(float32, struct float_status_t *status); +Bit64s float32_to_int64(float32, struct float_status_t *status); +Bit64s float32_to_int64_round_to_zero(float32, struct float_status_t *status); +Bit32u float32_to_uint32(float32, struct float_status_t *status); +Bit32u float32_to_uint32_round_to_zero(float32, struct float_status_t *status); +Bit64u float32_to_uint64(float32, struct float_status_t *status); +Bit64u float32_to_uint64_round_to_zero(float32, struct float_status_t *status); +float64 float32_to_float64(float32, struct float_status_t *status); + +/*---------------------------------------------------------------------------- +| Software IEC/IEEE single-precision operations. +*----------------------------------------------------------------------------*/ +float32 float32_round_to_int(float32, Bit8u scale, struct float_status_t *status); +float32 float32_add(float32, float32, struct float_status_t *status); +float32 float32_sub(float32, float32, struct float_status_t *status); +float32 float32_mul(float32, float32, struct float_status_t *status); +float32 float32_div(float32, float32, struct float_status_t *status); +float32 float32_sqrt(float32, struct float_status_t *status); +float32 float32_frc(float32, struct float_status_t *status); +float32 float32_muladd(float32, float32, float32, int flags, struct float_status_t *status); +float32 float32_scalef(float32, float32, struct float_status_t *status); +int float32_compare(float32, float32, int quiet, struct float_status_t *status); + +BX_CPP_INLINE float32 float32_round_to_int_one(float32 a, struct float_status_t *status) +{ + return float32_round_to_int(a, 0, status); +} + +BX_CPP_INLINE float32 float32_fmadd(float32 a, float32 b, float32 c, struct float_status_t *status) +{ + return float32_muladd(a, b, c, 0, status); +} + +BX_CPP_INLINE float32 float32_fmsub(float32 a, float32 b, float32 c, struct float_status_t *status) +{ + return float32_muladd(a, b, c, float_muladd_negate_c, status); +} + +BX_CPP_INLINE float32 float32_fnmadd(float32 a, float32 b, float32 c, struct float_status_t *status) +{ + return float32_muladd(a, b, c, float_muladd_negate_product, status); +} + +BX_CPP_INLINE float32 float32_fnmsub(float32 a, float32 b, float32 c, struct float_status_t *status) +{ + return float32_muladd(a, b, c, float_muladd_negate_result, status); +} + +BX_CPP_INLINE int float32_compare_two(float32 a, float32 b, struct float_status_t *status) +{ + return float32_compare(a, b, 0, status); +} + +BX_CPP_INLINE int float32_compare_quiet(float32 a, float32 b, struct float_status_t *status) +{ + return float32_compare(a, b, 1, status); +} + +float_class_t float32_class(float32); + +float32 float32_min(float32 a, float32 b, struct float_status_t *status); +float32 float32_max(float32 a, float32 b, struct float_status_t *status); + +float32 float32_minmax(float32 a, float32 b, int is_max, int is_abs, struct float_status_t *status); +float32 float32_getexp(float32 a, struct float_status_t *status); +float32 float32_getmant(float32 a, struct float_status_t *status, int sign_ctrl, int interv); + +/*---------------------------------------------------------------------------- +| Software IEC/IEEE double-precision conversion routines. +*----------------------------------------------------------------------------*/ +Bit32s float64_to_int32(float64, struct float_status_t *status); +Bit32s float64_to_int32_round_to_zero(float64, struct float_status_t *status); +Bit64s float64_to_int64(float64, struct float_status_t *status); +Bit64s float64_to_int64_round_to_zero(float64, struct float_status_t *status); +Bit32u float64_to_uint32(float64, struct float_status_t *status); +Bit32u float64_to_uint32_round_to_zero(float64, struct float_status_t *status); +Bit64u float64_to_uint64(float64, struct float_status_t *status); +Bit64u float64_to_uint64_round_to_zero(float64, struct float_status_t *status); +float32 float64_to_float32(float64, struct float_status_t *status); + +/*---------------------------------------------------------------------------- +| Software IEC/IEEE double-precision operations. +*----------------------------------------------------------------------------*/ +float64 float64_round_to_int(float64, Bit8u scale, struct float_status_t *status); +float64 float64_add(float64, float64, struct float_status_t *status); +float64 float64_sub(float64, float64, struct float_status_t *status); +float64 float64_mul(float64, float64, struct float_status_t *status); +float64 float64_div(float64, float64, struct float_status_t *status); +float64 float64_sqrt(float64, struct float_status_t *status); +float64 float64_frc(float64, struct float_status_t *status); +float64 float64_muladd(float64, float64, float64, int flags, struct float_status_t *status); +float64 float64_scalef(float64, float64, struct float_status_t *status); +int float64_compare(float64, float64, int quiet, struct float_status_t *status); + +BX_CPP_INLINE float64 float64_round_to_int_one(float64 a, struct float_status_t *status) +{ + return float64_round_to_int(a, 0, status); +} + +BX_CPP_INLINE float64 float64_fmadd(float64 a, float64 b, float64 c, struct float_status_t *status) +{ + return float64_muladd(a, b, c, 0, status); +} + +BX_CPP_INLINE float64 float64_fmsub(float64 a, float64 b, float64 c, struct float_status_t *status) +{ + return float64_muladd(a, b, c, float_muladd_negate_c, status); +} + +BX_CPP_INLINE float64 float64_fnmadd(float64 a, float64 b, float64 c, struct float_status_t *status) +{ + return float64_muladd(a, b, c, float_muladd_negate_product, status); +} + +BX_CPP_INLINE float64 float64_fnmsub(float64 a, float64 b, float64 c, struct float_status_t *status) +{ + return float64_muladd(a, b, c, float_muladd_negate_result, status); +} + +BX_CPP_INLINE int float64_compare_two(float64 a, float64 b, struct float_status_t *status) +{ + return float64_compare(a, b, 0, status); +} + +BX_CPP_INLINE int float64_compare_quiet(float64 a, float64 b, struct float_status_t *status) +{ + return float64_compare(a, b, 1, status); +} + +float_class_t float64_class(float64); + +float64 float64_min(float64 a, float64 b, struct float_status_t *status); +float64 float64_max(float64 a, float64 b, struct float_status_t *status); + +float64 float64_minmax(float64 a, float64 b, int is_max, int is_abs, struct float_status_t *status); +float64 float64_getexp(float64 a, struct float_status_t *status); +float64 float64_getmant(float64 a, struct float_status_t *status, int sign_ctrl, int interv); + +#ifdef FLOAT16 +float32 float16_to_float32(float16, struct float_status_t *status); +float16 float32_to_float16(float32, struct float_status_t *status); + +float_class_t float16_class(float16); +#endif + +#ifdef FLOATX80 +/*---------------------------------------------------------------------------- +| Software IEC/IEEE floating-point types. +*----------------------------------------------------------------------------*/ + +#ifdef BX_BIG_ENDIAN +typedef struct floatx80 { // leave alignment to compiler + Bit16u exp; + Bit64u fraction; +}; floatx80 +#else +typedef struct floatx80 { + Bit64u fraction; + Bit16u exp; +} floatx80; +#endif + +#ifdef __cplusplus +extern "C" { +#endif +/*---------------------------------------------------------------------------- +| Software IEC/IEEE integer-to-floating-point conversion routines. +*----------------------------------------------------------------------------*/ +floatx80 int32_to_floatx80(Bit32s); +floatx80 int64_to_floatx80(Bit64s); + +/*---------------------------------------------------------------------------- +| Software IEC/IEEE extended double-precision conversion routines. +*----------------------------------------------------------------------------*/ +floatx80 float32_to_floatx80(float32, struct float_status_t *status); +floatx80 float64_to_floatx80(float64, struct float_status_t *status); + +Bit32s floatx80_to_int32(floatx80, struct float_status_t *status); +Bit32s floatx80_to_int32_round_to_zero(floatx80, struct float_status_t *status); +Bit64s floatx80_to_int64(floatx80, struct float_status_t *status); +Bit64s floatx80_to_int64_round_to_zero(floatx80, struct float_status_t *status); + +float32 floatx80_to_float32(floatx80, struct float_status_t *status); +float64 floatx80_to_float64(floatx80, struct float_status_t *status); + +/*---------------------------------------------------------------------------- +| Software IEC/IEEE extended double-precision operations. +*----------------------------------------------------------------------------*/ +floatx80 floatx80_round_to_int(floatx80, struct float_status_t *status); +floatx80 floatx80_add(floatx80, floatx80, struct float_status_t *status); +floatx80 floatx80_sub(floatx80, floatx80, struct float_status_t *status); +floatx80 floatx80_mul(floatx80, floatx80, struct float_status_t *status); +floatx80 floatx80_div(floatx80, floatx80, struct float_status_t *status); +floatx80 floatx80_sqrt(floatx80, struct float_status_t *status); + +float_class_t floatx80_class(floatx80); +#ifdef __cplusplus +} +#endif +#endif /* FLOATX80 */ + +#ifdef FLOAT128 + +#ifdef BX_BIG_ENDIAN +typedef struct float128 { + Bit64u hi, lo; +} float128; +#else +typedef struct float128 { + Bit64u lo, hi; +} float128; +#endif + +#ifdef __cplusplus +extern "C" { +#endif +/*---------------------------------------------------------------------------- +| Software IEC/IEEE quadruple-precision conversion routines. +*----------------------------------------------------------------------------*/ +float128 floatx80_to_float128(floatx80 a, struct float_status_t *status); +floatx80 float128_to_floatx80(float128 a, struct float_status_t *status); + +float128 int64_to_float128(Bit64s a); + +/*---------------------------------------------------------------------------- +| Software IEC/IEEE extended double-precision operations. +*----------------------------------------------------------------------------*/ +floatx80 floatx80_128_mul(floatx80 a, float128 b, struct float_status_t *status); + +/*---------------------------------------------------------------------------- +| Software IEC/IEEE quadruple-precision operations. +*----------------------------------------------------------------------------*/ +float128 float128_add(float128 a, float128 b, struct float_status_t *status); +float128 float128_sub(float128 a, float128 b, struct float_status_t *status); +float128 float128_mul(float128 a, float128 b, struct float_status_t *status); +float128 float128_div(float128 a, float128 b, struct float_status_t *status); +#ifdef __cplusplus +} +#endif +#endif /* FLOAT128 */ + +#endif diff --git a/src/cpu/softfloat/softfloat16.cc b/src/cpu/softfloat/softfloat16.cc new file mode 100644 index 000000000..8c17d3a86 --- /dev/null +++ b/src/cpu/softfloat/softfloat16.cc @@ -0,0 +1,129 @@ +/*============================================================================ +This C source file is part of the SoftFloat IEC/IEEE Floating-point Arithmetic +Package, Release 2b. + +Written by John R. Hauser. This work was made possible in part by the +International Computer Science Institute, located at Suite 600, 1947 Center +Street, Berkeley, California 94704. Funding was partially provided by the +National Science Foundation under grant MIP-9311980. The original version +of this code was written as part of a project to build a fixed-point vector +processor in collaboration with the University of California at Berkeley, +overseen by Profs. Nelson Morgan and John Wawrzynek. More information +is available through the Web page `http://www.cs.berkeley.edu/~jhauser/ +arithmetic/SoftFloat.html'. + +THIS SOFTWARE IS DISTRIBUTED AS IS, FOR FREE. Although reasonable effort has +been made to avoid it, THIS SOFTWARE MAY CONTAIN FAULTS THAT WILL AT TIMES +RESULT IN INCORRECT BEHAVIOR. USE OF THIS SOFTWARE IS RESTRICTED TO PERSONS +AND ORGANIZATIONS WHO CAN AND WILL TAKE FULL RESPONSIBILITY FOR ALL LOSSES, +COSTS, OR OTHER PROBLEMS THEY INCUR DUE TO THE SOFTWARE, AND WHO FURTHERMORE +EFFECTIVELY INDEMNIFY JOHN HAUSER AND THE INTERNATIONAL COMPUTER SCIENCE +INSTITUTE (possibly via similar legal warning) AGAINST ALL LOSSES, COSTS, OR +OTHER PROBLEMS INCURRED BY THEIR CUSTOMERS AND CLIENTS DUE TO THE SOFTWARE. + +Derivative works are acceptable, even for commercial purposes, so long as +(1) the source code for the derivative work includes prominent notice that +the work is derivative, and (2) the source code includes prominent notice with +these four paragraphs for those parts of this code that are retained. +=============================================================================*/ + +/*============================================================================ + * Adapted for Bochs (x86 achitecture simulator) by + * Stanislav Shwartsman [sshwarts at sourceforge net] + * ==========================================================================*/ + +#include "softfloat.h" + +#ifdef FLOAT16 + +#include "softfloat-round-pack.h" +#include "softfloat-specialize.h" +#include "softfloat-macros.h" + +/*---------------------------------------------------------------------------- +| Determine half-precision floating-point number class +*----------------------------------------------------------------------------*/ + +float_class_t float16_class(float16 a) +{ + Bit16s aExp = extractFloat16Exp(a); + Bit16u aSig = extractFloat16Frac(a); + int aSign = extractFloat16Sign(a); + + if(aExp == 0x1F) { + if (aSig == 0) + return (aSign) ? float_negative_inf : float_positive_inf; + + return (aSig & 0x200) ? float_QNaN : float_SNaN; + } + + if(aExp == 0) { + if (aSig == 0) return float_zero; + return float_denormal; + } + + return float_normalized; +} + +/*---------------------------------------------------------------------------- +| Returns the result of converting the half-precision floating-point value +| `a' to the single-precision floating-point format. The conversion is +| performed according to the IEC/IEEE Standard for Binary Floating-Point +| Arithmetic. +*----------------------------------------------------------------------------*/ + +float32 float16_to_float32(float16 a, struct float_status_t *status) +{ + Bit16u aSig = extractFloat16Frac(a); + Bit16s aExp = extractFloat16Exp(a); + int aSign = extractFloat16Sign(a); + + if (aExp == 0x1F) { + if (aSig) return commonNaNToFloat32(float16ToCommonNaN(a, status)); + return packFloat32(aSign, 0xFF, 0); + } + if (aExp == 0) { + // ignore denormals_are_zeros flag + if (aSig == 0) return packFloat32(aSign, 0, 0); + float_raise(status, float_flag_denormal); + normalizeFloat16Subnormal(aSig, &aExp, &aSig); + --aExp; + } + + return packFloat32(aSign, aExp + 0x70, ((Bit32u) aSig)<<13); +} + +/*---------------------------------------------------------------------------- +| Returns the result of converting the single-precision floating-point value +| `a' to the half-precision floating-point format. The conversion is +| performed according to the IEC/IEEE Standard for Binary Floating-Point +| Arithmetic. +*----------------------------------------------------------------------------*/ + +float16 float32_to_float16(float32 a, struct float_status_t *status) +{ + Bit32u aSig = extractFloat32Frac(a); + Bit16s aExp = extractFloat32Exp(a); + int aSign = extractFloat32Sign(a); + + if (aExp == 0xFF) { + if (aSig) return commonNaNToFloat16(float32ToCommonNaN(a, status)); + return packFloat16(aSign, 0x1F, 0); + } + if (aExp == 0) { + if (get_denormals_are_zeros(status)) aSig = 0; + if (aSig == 0) return packFloat16(aSign, 0, 0); + float_raise(status, float_flag_denormal); + } + + aSig = shift32RightJamming(aSig, 9); + Bit16u zSig = (Bit16u) aSig; + if (aExp || zSig) { + zSig |= 0x4000; + aExp -= 0x71; + } + + return roundAndPackFloat16(aSign, aExp, zSig, status); +} + +#endif diff --git a/src/cpu/softfloat/softfloat_poly.cc b/src/cpu/softfloat/softfloat_poly.cc new file mode 100644 index 000000000..5c7079353 --- /dev/null +++ b/src/cpu/softfloat/softfloat_poly.cc @@ -0,0 +1,89 @@ +/*============================================================================ +This source file is an extension to the SoftFloat IEC/IEEE Floating-point +Arithmetic Package, Release 2b, written for Bochs (x86 achitecture simulator) +floating point emulation. + +THIS SOFTWARE IS DISTRIBUTED AS IS, FOR FREE. Although reasonable effort has +been made to avoid it, THIS SOFTWARE MAY CONTAIN FAULTS THAT WILL AT TIMES +RESULT IN INCORRECT BEHAVIOR. USE OF THIS SOFTWARE IS RESTRICTED TO PERSONS +AND ORGANIZATIONS WHO CAN AND WILL TAKE FULL RESPONSIBILITY FOR ALL LOSSES, +COSTS, OR OTHER PROBLEMS THEY INCUR DUE TO THE SOFTWARE, AND WHO FURTHERMORE +EFFECTIVELY INDEMNIFY JOHN HAUSER AND THE INTERNATIONAL COMPUTER SCIENCE +INSTITUTE (possibly via similar legal warning) AGAINST ALL LOSSES, COSTS, OR +OTHER PROBLEMS INCURRED BY THEIR CUSTOMERS AND CLIENTS DUE TO THE SOFTWARE. + +Derivative works are acceptable, even for commercial purposes, so long as +(1) the source code for the derivative work includes prominent notice that +the work is derivative, and (2) the source code includes prominent notice with +these four paragraphs for those parts of this code that are retained. +=============================================================================*/ + +/*============================================================================ + * Written for Bochs (x86 achitecture simulator) by + * Stanislav Shwartsman [sshwarts at sourceforge net] + * ==========================================================================*/ + +#define FLOAT128 + +#include +#include "softfloat.h" + +// 2 3 4 n +// f(x) ~ C + (C * x) + (C * x) + (C * x) + (C * x) + ... + (C * x) +// 0 1 2 3 4 n +// +// -- 2k -- 2k+1 +// p(x) = > C * x q(x) = > C * x +// -- 2k -- 2k+1 +// +// f(x) ~ [ p(x) + x * q(x) ] +// + +float128 EvalPoly(float128 x, float128 *arr, int n, struct float_status_t *status) +{ + float128 r = arr[--n]; + + do { + r = float128_mul(r, x, status); + r = float128_add(r, arr[--n], status); + } while (n > 0); + + return r; +} + +// 2 4 6 8 2n +// f(x) ~ C + (C * x) + (C * x) + (C * x) + (C * x) + ... + (C * x) +// 0 1 2 3 4 n +// +// -- 4k -- 4k+2 +// p(x) = > C * x q(x) = > C * x +// -- 2k -- 2k+1 +// +// 2 +// f(x) ~ [ p(x) + x * q(x) ] +// + +float128 EvenPoly(float128 x, float128 *arr, int n, struct float_status_t *status) +{ + return EvalPoly(float128_mul(x, x, status), arr, n, status); +} + +// 3 5 7 9 2n+1 +// f(x) ~ (C * x) + (C * x) + (C * x) + (C * x) + (C * x) + ... + (C * x) +// 0 1 2 3 4 n +// 2 4 6 8 2n +// = x * [ C + (C * x) + (C * x) + (C * x) + (C * x) + ... + (C * x) +// 0 1 2 3 4 n +// +// -- 4k -- 4k+2 +// p(x) = > C * x q(x) = > C * x +// -- 2k -- 2k+1 +// +// 2 +// f(x) ~ x * [ p(x) + x * q(x) ] +// + +float128 OddPoly(float128 x, float128 *arr, int n, struct float_status_t *status) +{ + return float128_mul(x, EvenPoly(x, arr, n, status), status); +} diff --git a/src/cpu/softfloat/softfloatx80.cc b/src/cpu/softfloat/softfloatx80.cc new file mode 100644 index 000000000..3ac3e61b3 --- /dev/null +++ b/src/cpu/softfloat/softfloatx80.cc @@ -0,0 +1,367 @@ +/*============================================================================ +This source file is an extension to the SoftFloat IEC/IEEE Floating-point +Arithmetic Package, Release 2b, written for Bochs (x86 achitecture simulator) +floating point emulation. + +THIS SOFTWARE IS DISTRIBUTED AS IS, FOR FREE. Although reasonable effort has +been made to avoid it, THIS SOFTWARE MAY CONTAIN FAULTS THAT WILL AT TIMES +RESULT IN INCORRECT BEHAVIOR. USE OF THIS SOFTWARE IS RESTRICTED TO PERSONS +AND ORGANIZATIONS WHO CAN AND WILL TAKE FULL RESPONSIBILITY FOR ALL LOSSES, +COSTS, OR OTHER PROBLEMS THEY INCUR DUE TO THE SOFTWARE, AND WHO FURTHERMORE +EFFECTIVELY INDEMNIFY JOHN HAUSER AND THE INTERNATIONAL COMPUTER SCIENCE +INSTITUTE (possibly via similar legal warning) AGAINST ALL LOSSES, COSTS, OR +OTHER PROBLEMS INCURRED BY THEIR CUSTOMERS AND CLIENTS DUE TO THE SOFTWARE. + +Derivative works are acceptable, even for commercial purposes, so long as +(1) the source code for the derivative work includes prominent notice that +the work is derivative, and (2) the source code includes prominent notice with +these four paragraphs for those parts of this code that are retained. +=============================================================================*/ + +/*============================================================================ + * Written for Bochs (x86 achitecture simulator) by + * Stanislav Shwartsman [sshwarts at sourceforge net] + * ==========================================================================*/ + +#include "softfloatx80.h" +#include "softfloat-round-pack.h" +#include "softfloat-macros.h" + +const floatx80 Const_QNaN = packFloatx80(0, floatx80_default_nan_exp, floatx80_default_nan_fraction); +const floatx80 Const_Z = packFloatx80(0, 0x0000, 0); +const floatx80 Const_1 = packFloatx80(0, 0x3fff, BX_CONST64(0x8000000000000000)); +const floatx80 Const_L2T = packFloatx80(0, 0x4000, BX_CONST64(0xd49a784bcd1b8afe)); +const floatx80 Const_L2E = packFloatx80(0, 0x3fff, BX_CONST64(0xb8aa3b295c17f0bc)); +const floatx80 Const_PI = packFloatx80(0, 0x4000, BX_CONST64(0xc90fdaa22168c235)); +const floatx80 Const_LG2 = packFloatx80(0, 0x3ffd, BX_CONST64(0x9a209a84fbcff799)); +const floatx80 Const_LN2 = packFloatx80(0, 0x3ffe, BX_CONST64(0xb17217f7d1cf79ac)); +const floatx80 Const_INF = packFloatx80(0, 0x7fff, BX_CONST64(0x8000000000000000)); + +/*---------------------------------------------------------------------------- +| Commonly used single-precision floating point constants +*----------------------------------------------------------------------------*/ +const float32 float32_negative_inf = 0xff800000; +const float32 float32_positive_inf = 0x7f800000; +const float32 float32_negative_zero = 0x80000000; +const float32 float32_positive_zero = 0x00000000; +const float32 float32_negative_one = 0xbf800000; +const float32 float32_positive_one = 0x3f800000; +const float32 float32_max_float = 0x7f7fffff; +const float32 float32_min_float = 0xff7fffff; + +/*---------------------------------------------------------------------------- +| The pattern for a default generated single-precision NaN. +*----------------------------------------------------------------------------*/ +const float32 float32_default_nan = 0xffc00000; + +/*---------------------------------------------------------------------------- +| Commonly used single-precision floating point constants +*----------------------------------------------------------------------------*/ +const float64 float64_negative_inf = BX_CONST64(0xfff0000000000000); +const float64 float64_positive_inf = BX_CONST64(0x7ff0000000000000); +const float64 float64_negative_zero = BX_CONST64(0x8000000000000000); +const float64 float64_positive_zero = BX_CONST64(0x0000000000000000); +const float64 float64_negative_one = BX_CONST64(0xbff0000000000000); +const float64 float64_positive_one = BX_CONST64(0x3ff0000000000000); +const float64 float64_max_float = BX_CONST64(0x7fefffffffffffff); +const float64 float64_min_float = BX_CONST64(0xffefffffffffffff); + +/*---------------------------------------------------------------------------- +| The pattern for a default generated double-precision NaN. +*----------------------------------------------------------------------------*/ +const float64 float64_default_nan = BX_CONST64(0xFFF8000000000000); + +/*---------------------------------------------------------------------------- +| Returns the result of converting the extended double-precision floating- +| point value `a' to the 16-bit two's complement integer format. The +| conversion is performed according to the IEC/IEEE Standard for Binary +| Floating-Point Arithmetic - which means in particular that the conversion +| is rounded according to the current rounding mode. If `a' is a NaN or the +| conversion overflows, the integer indefinite value is returned. +*----------------------------------------------------------------------------*/ + +Bit16s floatx80_to_int16(floatx80 a, struct float_status_t *status) +{ + if (floatx80_is_unsupported(a)) { + float_raise(status, float_flag_invalid); + return int16_indefinite; + } + + Bit32s v32 = floatx80_to_int32(a, status); + + if ((v32 > 32767) || (v32 < -32768)) { + status->float_exception_flags = float_flag_invalid; // throw away other flags + return int16_indefinite; + } + + return (Bit16s) v32; +} + +/*---------------------------------------------------------------------------- +| Returns the result of converting the extended double-precision floating- +| point value `a' to the 16-bit two's complement integer format. The +| conversion is performed according to the IEC/IEEE Standard for Binary +| Floating-Point Arithmetic, except that the conversion is always rounded +| toward zero. If `a' is a NaN or the conversion overflows, the integer +| indefinite value is returned. +*----------------------------------------------------------------------------*/ + +Bit16s floatx80_to_int16_round_to_zero(floatx80 a, struct float_status_t *status) +{ + if (floatx80_is_unsupported(a)) { + float_raise(status, float_flag_invalid); + return int16_indefinite; + } + + Bit32s v32 = floatx80_to_int32_round_to_zero(a, status); + + if ((v32 > 32767) || (v32 < -32768)) { + status->float_exception_flags = float_flag_invalid; // throw away other flags + return int16_indefinite; + } + + return (Bit16s) v32; +} + +/*---------------------------------------------------------------------------- +| Separate the source extended double-precision floating point value `a' +| into its exponent and significand, store the significant back to the +| 'a' and return the exponent. The operation performed is a superset of +| the IEC/IEEE recommended logb(x) function. +*----------------------------------------------------------------------------*/ + +floatx80 floatx80_extract(floatx80 *a, struct float_status_t *status) +{ +/*---------------------------------------------------------------------------- +| The pattern for a default generated extended double-precision NaN. +*----------------------------------------------------------------------------*/ + const floatx80 floatx80_default_nan = packFloatx80(0, floatx80_default_nan_exp, floatx80_default_nan_fraction); + + Bit64u aSig = extractFloatx80Frac(*a); + Bit32s aExp = extractFloatx80Exp(*a); + int aSign = extractFloatx80Sign(*a); + + if (floatx80_is_unsupported(*a)) + { + float_raise(status, float_flag_invalid); + *a = floatx80_default_nan; + return *a; + } + + if (aExp == 0x7FFF) { + if ((Bit64u) (aSig<<1)) + { + *a = propagateFloatx80NaNOne(*a, status); + return *a; + } + return packFloatx80(0, 0x7FFF, BX_CONST64(0x8000000000000000)); + } + if (aExp == 0) + { + if (aSig == 0) { + float_raise(status, float_flag_divbyzero); + *a = packFloatx80(aSign, 0, 0); + return packFloatx80(1, 0x7FFF, BX_CONST64(0x8000000000000000)); + } + float_raise(status, float_flag_denormal); + normalizeFloatx80Subnormal(aSig, &aExp, &aSig); + } + + a->exp = (aSign << 15) + 0x3FFF; + a->fraction = aSig; + return int32_to_floatx80(aExp - 0x3FFF); +} + +/*---------------------------------------------------------------------------- +| Scales extended double-precision floating-point value in operand `a' by +| value `b'. The function truncates the value in the second operand 'b' to +| an integral value and adds that value to the exponent of the operand 'a'. +| The operation performed according to the IEC/IEEE Standard for Binary +| Floating-Point Arithmetic. +*----------------------------------------------------------------------------*/ + +floatx80 floatx80_scale(floatx80 a, floatx80 b, struct float_status_t *status) +{ +/*---------------------------------------------------------------------------- +| The pattern for a default generated extended double-precision NaN. +*----------------------------------------------------------------------------*/ + const floatx80 floatx80_default_nan = packFloatx80(0, floatx80_default_nan_exp, floatx80_default_nan_fraction); + + Bit32s aExp, bExp; + Bit64u aSig, bSig; + + // handle unsupported extended double-precision floating encodings + if (floatx80_is_unsupported(a) || floatx80_is_unsupported(b)) + { + float_raise(status, float_flag_invalid); + return floatx80_default_nan; + } + + aSig = extractFloatx80Frac(a); + aExp = extractFloatx80Exp(a); + int aSign = extractFloatx80Sign(a); + bSig = extractFloatx80Frac(b); + bExp = extractFloatx80Exp(b); + int bSign = extractFloatx80Sign(b); + + if (aExp == 0x7FFF) { + if ((Bit64u) (aSig<<1) || ((bExp == 0x7FFF) && (Bit64u) (bSig<<1))) + { + return propagateFloatx80NaN(a, b, status); + } + if ((bExp == 0x7FFF) && bSign) { + float_raise(status, float_flag_invalid); + return floatx80_default_nan; + } + if (bSig && (bExp == 0)) float_raise(status, float_flag_denormal); + return a; + } + if (bExp == 0x7FFF) { + if ((Bit64u) (bSig<<1)) return propagateFloatx80NaN(a, b, status); + if ((aExp | aSig) == 0) { + if (! bSign) { + float_raise(status, float_flag_invalid); + return floatx80_default_nan; + } + return a; + } + if (aSig && (aExp == 0)) float_raise(status, float_flag_denormal); + if (bSign) return packFloatx80(aSign, 0, 0); + return packFloatx80(aSign, 0x7FFF, BX_CONST64(0x8000000000000000)); + } + if (aExp == 0) { + if (bSig && (bExp == 0)) float_raise(status, float_flag_denormal); + if (aSig == 0) return a; + float_raise(status, float_flag_denormal); + normalizeFloatx80Subnormal(aSig, &aExp, &aSig); + if (bExp < 0x3FFF) + return normalizeRoundAndPackFloatx80(80, aSign, aExp, aSig, 0, status); + } + if (bExp == 0) { + if (bSig == 0) return a; + float_raise(status, float_flag_denormal); + normalizeFloatx80Subnormal(bSig, &bExp, &bSig); + } + + if (bExp > 0x400E) { + /* generate appropriate overflow/underflow */ + return roundAndPackFloatx80(80, aSign, + bSign ? -0x3FFF : 0x7FFF, aSig, 0, status); + } + + if (bExp < 0x3FFF) return a; + + int shiftCount = 0x403E - bExp; + bSig >>= shiftCount; + Bit32s scale = (Bit32s) bSig; + if (bSign) scale = -scale; /* -32768..32767 */ + return + roundAndPackFloatx80(80, aSign, aExp+scale, aSig, 0, status); +} + +/*---------------------------------------------------------------------------- +| Determine extended-precision floating-point number class. +*----------------------------------------------------------------------------*/ + +float_class_t floatx80_class(floatx80 a) +{ + Bit32s aExp = extractFloatx80Exp(a); + Bit64u aSig = extractFloatx80Frac(a); + + if(aExp == 0) { + if (aSig == 0) + return float_zero; + + /* denormal or pseudo-denormal */ + return float_denormal; + } + + /* valid numbers have the MS bit set */ + if (!(aSig & BX_CONST64(0x8000000000000000))) + return float_SNaN; /* report unsupported as SNaNs */ + + if(aExp == 0x7fff) { + int aSign = extractFloatx80Sign(a); + + if (((Bit64u) (aSig<< 1)) == 0) + return (aSign) ? float_negative_inf : float_positive_inf; + + return (aSig & BX_CONST64(0x4000000000000000)) ? float_QNaN : float_SNaN; + } + + return float_normalized; +} + +/*---------------------------------------------------------------------------- +| Compare between two extended precision floating point numbers. Returns +| 'float_relation_equal' if the operands are equal, 'float_relation_less' if +| the value 'a' is less than the corresponding value `b', +| 'float_relation_greater' if the value 'a' is greater than the corresponding +| value `b', or 'float_relation_unordered' otherwise. +*----------------------------------------------------------------------------*/ + +int floatx80_compare(floatx80 a, floatx80 b, int quiet, struct float_status_t *status) +{ + float_class_t aClass = floatx80_class(a); + float_class_t bClass = floatx80_class(b); + + if (aClass == float_SNaN || bClass == float_SNaN) + { + /* unsupported reported as SNaN */ + float_raise(status, float_flag_invalid); + return float_relation_unordered; + } + + if (aClass == float_QNaN || bClass == float_QNaN) { + if (! quiet) float_raise(status, float_flag_invalid); + return float_relation_unordered; + } + + if (aClass == float_denormal || bClass == float_denormal) { + float_raise(status, float_flag_denormal); + } + + int aSign = extractFloatx80Sign(a); + int bSign = extractFloatx80Sign(b); + + if (aClass == float_zero) { + if (bClass == float_zero) return float_relation_equal; + return bSign ? float_relation_greater : float_relation_less; + } + + if (bClass == float_zero || aSign != bSign) { + return aSign ? float_relation_less : float_relation_greater; + } + + Bit64u aSig = extractFloatx80Frac(a); + Bit32s aExp = extractFloatx80Exp(a); + Bit64u bSig = extractFloatx80Frac(b); + Bit32s bExp = extractFloatx80Exp(b); + + if (aClass == float_denormal) + normalizeFloatx80Subnormal(aSig, &aExp, &aSig); + + if (bClass == float_denormal) + normalizeFloatx80Subnormal(bSig, &bExp, &bSig); + + if (aExp == bExp && aSig == bSig) + return float_relation_equal; + + int less_than = + aSign ? ((bExp < aExp) || ((bExp == aExp) && (bSig < aSig))) + : ((aExp < bExp) || ((aExp == bExp) && (aSig < bSig))); + + if (less_than) return float_relation_less; + return float_relation_greater; +} + + +int floatx80_compare_two(floatx80 a, floatx80 b, struct float_status_t *status) +{ + return floatx80_compare(a, b, 0, status); +} + +int floatx80_compare_quiet(floatx80 a, floatx80 b, struct float_status_t *status) +{ + return floatx80_compare(a, b, 1, status); +} diff --git a/src/cpu/softfloat/softfloatx80.h b/src/cpu/softfloat/softfloatx80.h new file mode 100644 index 000000000..1f96141b4 --- /dev/null +++ b/src/cpu/softfloat/softfloatx80.h @@ -0,0 +1,121 @@ +/*============================================================================ +This source file is an extension to the SoftFloat IEC/IEEE Floating-point +Arithmetic Package, Release 2b, written for Bochs (x86 achitecture simulator) +floating point emulation. + +THIS SOFTWARE IS DISTRIBUTED AS IS, FOR FREE. Although reasonable effort has +been made to avoid it, THIS SOFTWARE MAY CONTAIN FAULTS THAT WILL AT TIMES +RESULT IN INCORRECT BEHAVIOR. USE OF THIS SOFTWARE IS RESTRICTED TO PERSONS +AND ORGANIZATIONS WHO CAN AND WILL TAKE FULL RESPONSIBILITY FOR ALL LOSSES, +COSTS, OR OTHER PROBLEMS THEY INCUR DUE TO THE SOFTWARE, AND WHO FURTHERMORE +EFFECTIVELY INDEMNIFY JOHN HAUSER AND THE INTERNATIONAL COMPUTER SCIENCE +INSTITUTE (possibly via similar legal warning) AGAINST ALL LOSSES, COSTS, OR +OTHER PROBLEMS INCURRED BY THEIR CUSTOMERS AND CLIENTS DUE TO THE SOFTWARE. + +Derivative works are acceptable, even for commercial purposes, so long as +(1) the source code for the derivative work includes prominent notice that +the work is derivative, and (2) the source code includes prominent notice with +these four paragraphs for those parts of this code that are retained. +=============================================================================*/ + +/*============================================================================ + * Written for Bochs (x86 achitecture simulator) by + * Stanislav Shwartsman [sshwarts at sourceforge net] + * ==========================================================================*/ + +#ifndef _SOFTFLOATX80_EXTENSIONS_H_ +#define _SOFTFLOATX80_EXTENSIONS_H_ + +#include "softfloat.h" +#include "softfloat-specialize.h" + +/*---------------------------------------------------------------------------- +| Software IEC/IEEE integer-to-floating-point conversion routines. +*----------------------------------------------------------------------------*/ + +#ifdef __cplusplus +extern "C" { +#endif + +Bit16s floatx80_to_int16(floatx80, struct float_status_t *status); +Bit16s floatx80_to_int16_round_to_zero(floatx80, struct float_status_t *status); + +/*---------------------------------------------------------------------------- +| Software IEC/IEEE extended double-precision operations. +*----------------------------------------------------------------------------*/ + +floatx80 floatx80_extract(floatx80 *a, struct float_status_t *status); +floatx80 floatx80_scale(floatx80 a, floatx80 b, struct float_status_t *status); +int floatx80_remainder(floatx80 a, floatx80 b, floatx80 *r, Bit64u *q, struct float_status_t *status); +int floatx80_ieee754_remainder(floatx80 a, floatx80 b, floatx80 *r, Bit64u *q, struct float_status_t *status); +floatx80 f2xm1(floatx80 a, struct float_status_t *status); +floatx80 fyl2x(floatx80 a, floatx80 b, struct float_status_t *status); +floatx80 fyl2xp1(floatx80 a, floatx80 b, struct float_status_t *status); +floatx80 fpatan(floatx80 a, floatx80 b, struct float_status_t *status); + +/*---------------------------------------------------------------------------- +| Software IEC/IEEE extended double-precision trigonometric functions. +*----------------------------------------------------------------------------*/ + +int fsincos(floatx80 a, floatx80 *sin_a, floatx80 *cos_a, struct float_status_t *status); +int fsin(floatx80 *a, struct float_status_t *status); +int fcos(floatx80 *a, struct float_status_t *status); +int ftan(floatx80 *a, struct float_status_t *status); + +/*---------------------------------------------------------------------------- +| Software IEC/IEEE extended double-precision compare. +*----------------------------------------------------------------------------*/ + +int floatx80_compare(floatx80, floatx80, int quiet, struct float_status_t *status); +int floatx80_compare_two(floatx80 a, floatx80 b, struct float_status_t *status); +int floatx80_compare_quiet(floatx80 a, floatx80 b, struct float_status_t *status); + +#ifdef __cplusplus +} +#endif + +/*----------------------------------------------------------------------------- +| Calculates the absolute value of the extended double-precision floating-point +| value `a'. The operation is performed according to the IEC/IEEE Standard +| for Binary Floating-Point Arithmetic. +*----------------------------------------------------------------------------*/ + +#ifdef __cplusplus +BX_CPP_INLINE floatx80& floatx80_abs(floatx80 ®) +#else +BX_CPP_INLINE floatx80 floatx80_abs(floatx80 reg) +#endif +{ + reg.exp &= 0x7FFF; + return reg; +} + +/*----------------------------------------------------------------------------- +| Changes the sign of the extended double-precision floating-point value 'a'. +| The operation is performed according to the IEC/IEEE Standard for Binary +| Floating-Point Arithmetic. +*----------------------------------------------------------------------------*/ + +#ifdef __cplusplus +BX_CPP_INLINE floatx80& floatx80_chs(floatx80 ®) +#else +BX_CPP_INLINE floatx80 floatx80_chs(floatx80 reg) +#endif +{ + reg.exp ^= 0x8000; + return reg; +} + +/*----------------------------------------------------------------------------- +| Commonly used extended double-precision floating-point constants. +*----------------------------------------------------------------------------*/ + +extern const floatx80 Const_Z; +extern const floatx80 Const_1; +extern const floatx80 Const_L2T; +extern const floatx80 Const_L2E; +extern const floatx80 Const_PI; +extern const floatx80 Const_LG2; +extern const floatx80 Const_LN2; +extern const floatx80 Const_INF; +#endif diff --git a/src/cpu/x86.c b/src/cpu/x86.c index 94b2294dd..93674ae5c 100644 --- a/src/cpu/x86.c +++ b/src/cpu/x86.c @@ -1,18 +1,18 @@ -/* - * 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. +/* + * 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. + * This file is part of the 86Box distribution. * - * Functions common to all emulated x86 CPU's. + * Functions common to all emulated x86 CPU's. * - * Authors: Andrew Jenner, - * Miran Grca, + * Authors: Andrew Jenner, + * Miran Grca, * - * Copyright 2015-2020 Andrew Jenner. - * Copyright 2016-2020 Miran Grca. + * Copyright 2015-2020 Andrew Jenner. + * Copyright 2016-2020 Miran Grca. */ #include #include @@ -25,10 +25,13 @@ #include <86box/86box.h> #include "cpu.h" #include "x86.h" +#include "x86seg_common.h" +#include "x86seg.h" #include <86box/machine.h> #include <86box/device.h> #include <86box/dma.h> #include <86box/io.h> +#include <86box/keyboard.h> #include <86box/mem.h> #include <86box/rom.h> #include <86box/nmi.h> @@ -36,12 +39,14 @@ #include <86box/pci.h> #include <86box/ppi.h> #include <86box/timer.h> +#include <86box/video.h> +#include <86box/vid_svga.h> /* The opcode of the instruction currently being executed. */ uint8_t opcode; /* The tables to speed up the setting of the Z, N, and P cpu_state.flags. */ -uint8_t znptable8[256]; +uint8_t znptable8[256]; uint16_t znptable16[65536]; /* A 16-bit zero, needed because some speed-up arrays contain pointers to it. */ @@ -50,16 +55,18 @@ uint16_t zero = 0; /* MOD and R/M stuff. */ uint16_t *mod1add[2][8]; uint32_t *mod1seg[8]; -uint32_t rmdat; +uint32_t rmdat; /* XT CPU multiplier. */ uint64_t xt_cpu_multi; /* Variables for handling the non-maskable interrupts. */ -int nmi = 0, nmi_auto_clear = 0; +int nmi = 0; +int nmi_auto_clear = 0; /* Was the CPU ever reset? */ -int x86_was_reset = 0, soft_reset_pci = 0; +int x86_was_reset = 0; +int soft_reset_pci = 0; /* Is the TRAP flag on? */ int trap = 0; @@ -68,76 +75,77 @@ int trap = 0; uint32_t easeg; /* This is for the OPTI 283 special reset handling mode. */ -int reset_on_hlt, hlt_reset_pending; +int reset_on_hlt; +int hlt_reset_pending; +int fpu_cycles = 0; #ifdef ENABLE_X86_LOG -void dumpregs(int); +void dumpregs(int); int x86_do_log = ENABLE_X86_LOG; -int indump = 0; - +int indump = 0; static void -x808x_log(const char *fmt, ...) +x86_log(const char *fmt, ...) { va_list ap; if (x808x_do_log) { - va_start(ap, fmt); - pclog_ex(fmt, ap); - va_end(ap); + va_start(ap, fmt); + pclog_ex(fmt, ap); + va_end(ap); } } - void dumpregs(int force) { - int c; + int c; char *seg_names[4] = { "ES", "CS", "SS", "DS" }; /* Only dump when needed, and only once.. */ if (indump || (!force && !dump_on_exit)) - return; + return; - x808x_log("EIP=%08X CS=%04X DS=%04X ES=%04X SS=%04X FLAGS=%04X\n", - cpu_state.pc, CS, DS, ES, SS, cpu_state.flags); - x808x_log("Old CS:EIP: %04X:%08X; %i ins\n", oldcs, cpu_state.oldpc, ins); + x86_log("EIP=%08X CS=%04X DS=%04X ES=%04X SS=%04X FLAGS=%04X\n", + cpu_state.pc, CS, DS, ES, SS, cpu_state.flags); + x85_log("Old CS:EIP: %04X:%08X; %i ins\n", oldcs, cpu_state.oldpc, ins); for (c = 0; c < 4; c++) { - x808x_log("%s : base=%06X limit=%08X access=%02X limit_low=%08X limit_high=%08X\n", - seg_names[c], _opseg[c]->base, _opseg[c]->limit, - _opseg[c]->access, _opseg[c]->limit_low, _opseg[c]->limit_high); + x86_log("%s : base=%06X limit=%08X access=%02X limit_low=%08X limit_high=%08X\n", + seg_names[c], _opseg[c]->base, _opseg[c]->limit, + _opseg[c]->access, _opseg[c]->limit_low, _opseg[c]->limit_high); } if (is386) { - x808x_log("FS : base=%06X limit=%08X access=%02X limit_low=%08X limit_high=%08X\n", - seg_fs, cpu_state.seg_fs.limit, cpu_state.seg_fs.access, cpu_state.seg_fs.limit_low, cpu_state.seg_fs.limit_high); - x808x_log("GS : base=%06X limit=%08X access=%02X limit_low=%08X limit_high=%08X\n", - gs, cpu_state.seg_gs.limit, cpu_state.seg_gs.access, cpu_state.seg_gs.limit_low, cpu_state.seg_gs.limit_high); - x808x_log("GDT : base=%06X limit=%04X\n", gdt.base, gdt.limit); - x808x_log("LDT : base=%06X limit=%04X\n", ldt.base, ldt.limit); - x808x_log("IDT : base=%06X limit=%04X\n", idt.base, idt.limit); - x808x_log("TR : base=%06X limit=%04X\n", tr.base, tr.limit); - x808x_log("386 in %s mode: %i-bit data, %-i-bit stack\n", - (msw & 1) ? ((cpu_state.eflags & VM_FLAG) ? "V86" : "protected") : "real", - (use32) ? 32 : 16, (stack32) ? 32 : 16); - x808x_log("CR0=%08X CR2=%08X CR3=%08X CR4=%08x\n", cr0, cr2, cr3, cr4); - x808x_log("EAX=%08X EBX=%08X ECX=%08X EDX=%08X\nEDI=%08X ESI=%08X EBP=%08X ESP=%08X\n", - EAX, EBX, ECX, EDX, EDI, ESI, EBP, ESP); + x86_log("FS : base=%06X limit=%08X access=%02X limit_low=%08X limit_high=%08X\n", + seg_fs, cpu_state.seg_fs.limit, cpu_state.seg_fs.access, cpu_state.seg_fs.limit_low, + cpu_state.seg_fs.limit_high); + x86_log("GS : base=%06X limit=%08X access=%02X limit_low=%08X limit_high=%08X\n", + gs, cpu_state.seg_gs.limit, cpu_state.seg_gs.access, cpu_state.seg_gs.limit_low, + cpu_state.seg_gs.limit_high); + x86_log("GDT : base=%06X limit=%04X\n", gdt.base, gdt.limit); + x86_log("LDT : base=%06X limit=%04X\n", ldt.base, ldt.limit); + x86_log("IDT : base=%06X limit=%04X\n", idt.base, idt.limit); + x86_log("TR : base=%06X limit=%04X\n", tr.base, tr.limit); + x86_log("386 in %s mode: %i-bit data, %-i-bit stack\n", + (msw & 1) ? ((cpu_state.eflags & VM_FLAG) ? "V86" : "protected") : "real", + (use32) ? 32 : 16, (stack32) ? 32 : 16); + x86_log("CR0=%08X CR2=%08X CR3=%08X CR4=%08x\n", cr0, cr2, cr3, cr4); + x86_log("EAX=%08X EBX=%08X ECX=%08X EDX=%08X\nEDI=%08X ESI=%08X EBP=%08X ESP=%08X\n", + EAX, EBX, ECX, EDX, EDI, ESI, EBP, ESP); } else { - x808x_log("808x/286 in %s mode\n", (msw & 1) ? "protected" : "real"); - x808x_log("AX=%04X BX=%04X CX=%04X DX=%04X DI=%04X SI=%04X BP=%04X SP=%04X\n", - AX, BX, CX, DX, DI, SI, BP, SP); + x86_log("808x/286 in %s mode\n", (msw & 1) ? "protected" : "real"); + x86_log("AX=%04X BX=%04X CX=%04X DX=%04X DI=%04X SI=%04X BP=%04X SP=%04X\n", + AX, BX, CX, DX, DI, SI, BP, SP); } - x808x_log("Entries in readlookup : %i writelookup : %i\n", readlnum, writelnum); + x86_log("Entries in readlookup : %i writelookup : %i\n", readlnum, writelnum); x87_dumpregs(); indump = 0; } #else -#define x808x_log(fmt, ...) +# define x86_log(fmt, ...) #endif - /* Preparation of the various arrays needed to speed up the MOD and R/M work. */ static void makemod1table(void) @@ -158,141 +166,150 @@ makemod1table(void) mod1add[1][5] = &zero; mod1add[1][6] = &zero; mod1add[1][7] = &zero; - mod1seg[0] = &ds; - mod1seg[1] = &ds; - mod1seg[2] = &ss; - mod1seg[3] = &ss; - mod1seg[4] = &ds; - mod1seg[5] = &ds; - mod1seg[6] = &ss; - mod1seg[7] = &ds; + mod1seg[0] = &ds; + mod1seg[1] = &ds; + mod1seg[2] = &ss; + mod1seg[3] = &ss; + mod1seg[4] = &ds; + mod1seg[5] = &ds; + mod1seg[6] = &ss; + mod1seg[7] = &ds; } - /* Prepare the ZNP table needed to speed up the setting of the Z, N, and P cpu_state.flags. */ static void makeznptable(void) { - int c, d, e; + int c; + int d; + int e; + for (c = 0; c < 256; c++) { - d = 0; - for (e = 0; e < 8; e++) { - if (c & (1 << e)) - d++; - } - if (d & 1) - znptable8[c] = 0; - else - znptable8[c] = P_FLAG; -#ifdef ENABLE_808X_LOG - if (c == 0xb1) - x808x_log("znp8 b1 = %i %02X\n", d, znptable8[c]); + d = 0; + for (e = 0; e < 8; e++) { + if (c & (1 << e)) + d++; + } + if (d & 1) + znptable8[c] = 0; + else + znptable8[c] = P_FLAG; +#ifdef ENABLE_X86_LOG + if (c == 0xb1) + x86_log("znp8 b1 = %i %02X\n", d, znptable8[c]); #endif - if (!c) - znptable8[c] |= Z_FLAG; - if (c & 0x80) - znptable8[c] |= N_FLAG; + if (!c) + znptable8[c] |= Z_FLAG; + if (c & 0x80) + znptable8[c] |= N_FLAG; } for (c = 0; c < 65536; c++) { - d = 0; - for (e = 0; e < 8; e++) { - if (c & (1 << e)) - d++; - } - if (d & 1) - znptable16[c] = 0; - else - znptable16[c] = P_FLAG; -#ifdef ENABLE_808X_LOG - if (c == 0xb1) - x808x_log("znp16 b1 = %i %02X\n", d, znptable16[c]); - if (c == 0x65b1) - x808x_log("znp16 65b1 = %i %02X\n", d, znptable16[c]); + d = 0; + for (e = 0; e < 8; e++) { + if (c & (1 << e)) + d++; + } + if (d & 1) + znptable16[c] = 0; + else + znptable16[c] = P_FLAG; +#ifdef ENABLE_X86_LOG + if (c == 0xb1) + x86_log("znp16 b1 = %i %02X\n", d, znptable16[c]); + if (c == 0x65b1) + x86_log("znp16 65b1 = %i %02X\n", d, znptable16[c]); #endif - if (!c) - znptable16[c] |= Z_FLAG; - if (c & 0x8000) - znptable16[c] |= N_FLAG; + if (!c) + znptable16[c] |= Z_FLAG; + if (c & 0x8000) + znptable16[c] |= N_FLAG; } } - /* Common reset function. */ static void reset_common(int hard) { -#ifdef ENABLE_808X_LOG +#ifdef ENABLE_X86_LOG if (hard) - x808x_log("x86 reset\n"); + x86_log("x86 reset\n"); #endif if (!hard && reset_on_hlt) { - hlt_reset_pending++; - pclog("hlt_reset_pending = %i\n", hlt_reset_pending); - if (hlt_reset_pending == 2) - hlt_reset_pending = 0; - else - return; + hlt_reset_pending++; + pclog("hlt_reset_pending = %i\n", hlt_reset_pending); + if (hlt_reset_pending == 2) + hlt_reset_pending = 0; + else + return; } /* Make sure to gracefully leave SMM. */ if (in_smm) - leave_smm(); + leave_smm(); /* Needed for the ALi M1533. */ if (is486 && (hard || soft_reset_pci)) { - pci_reset(); - if (!hard && soft_reset_pci) { - dma_reset(); - /* TODO: Hack, but will do for time being, because all AT machines currently are 286+, - and vice-versa. */ - dma_set_at(is286); - device_reset_all(); - } + pci_reset(); + if (!hard && soft_reset_pci) { + dma_reset(); + /* TODO: Hack, but will do for time being, because all AT machines currently are 286+, + and vice-versa. */ + dma_set_at(is286); + device_reset_all(DEVICE_ALL); + } } - use32 = 0; + use32 = 0; cpu_cur_status = 0; - stack32 = 0; - msr.fcr = (1 << 8) | (1 << 9) | (1 << 12) | (1 << 16) | (1 << 19) | (1 << 21); - msw = 0; + stack32 = 0; + msr.fcr = (1 << 8) | (1 << 9) | (1 << 12) | (1 << 16) | (1 << 19) | (1 << 21); + msw = 0; if (hascache) - cr0 = 1 << 30; + cr0 = 1 << 30; else - cr0 = 0; + cr0 = 0; cpu_cache_int_enabled = 0; cpu_update_waitstates(); - cr4 = 0; + cr4 = 0; cpu_state.eflags = 0; - cgate32 = 0; + cgate32 = 0; if (is286) { - loadcs(0xF000); - cpu_state.pc = 0xFFF0; - rammask = cpu_16bitbus ? 0xFFFFFF : 0xFFFFFFFF; + if (is486) + loadcs(0xF000); + else + loadcs_2386(0xF000); + cpu_state.pc = 0xFFF0; + if (hard) { + rammask = cpu_16bitbus ? 0xFFFFFF : 0xFFFFFFFF; + if (is6117) + rammask |= 0x03000000; + mem_a20_key = mem_a20_alt = mem_a20_state = 0; + } } - idt.base = 0; + idt.base = 0; cpu_state.flags = 2; - trap = 0; + trap = 0; idt.limit = is386 ? 0x03ff : 0xffff; if (is386 || hard) - EAX = EBX = ECX = EDX = ESI = EDI = EBP = ESP = 0; + EAX = EBX = ECX = EDX = ESI = EDI = EBP = ESP = 0; if (hard) { - makeznptable(); - resetreadlookup(); - makemod1table(); - cpu_set_edx(); - mmu_perm = 4; + makeznptable(); + resetreadlookup(); + makemod1table(); + cpu_set_edx(); + mmu_perm = 4; } x86seg_reset(); #ifdef USE_DYNAREC if (hard) - codegen_reset(); + codegen_reset(); #endif if (!hard) - flushmmucache(); + flushmmucache(); x86_was_reset = 1; cpu_alt_reset = 0; @@ -300,12 +317,12 @@ reset_common(int hard) in_smm = smi_latched = 0; smi_line = smm_in_hlt = 0; - smi_block = 0; + smi_block = 0; if (hard) { - if (is486) - smbase = is_am486dxl ? 0x00060000 : 0x00030000; - ppi_reset(); + if (is486) + smbase = is_am486dxl ? 0x00060000 : 0x00030000; + ppi_reset(); } in_sys = 0; @@ -313,17 +330,20 @@ reset_common(int hard) alt_access = cpu_end_block_after_ins = 0; if (hard) { - reset_on_hlt = hlt_reset_pending = 0; - cache_index = 0; - memset(_tr, 0x00, sizeof(_tr)); - memset(_cache, 0x00, sizeof(_cache)); + reset_on_hlt = hlt_reset_pending = 0; + cache_index = 0; + memset(_tr, 0x00, sizeof(_tr)); + memset(_cache, 0x00, sizeof(_cache)); + + /* If we have an AT or PS/2 keyboard controller, make sure the A20 state + is correct. */ + device_reset_all(DEVICE_KBC); } if (!is286) - reset_808x(hard); + reset_808x(hard); } - /* Hard reset. */ void resetx86(void) @@ -333,18 +353,19 @@ resetx86(void) soft_reset_mask = 0; } - /* Soft reset. */ void softresetx86(void) { if (soft_reset_mask) - return; + return; + + if (ibm8514_active || xga_active) + vga_on = 1; reset_common(0); } - /* Actual hard reset. */ void hardresetx86(void) @@ -353,7 +374,7 @@ hardresetx86(void) /* TODO: Hack, but will do for time being, because all AT machines currently are 286+, and vice-versa. */ dma_set_at(is286); - device_reset_all(); + device_reset_all(DEVICE_ALL); cpu_alt_reset = 0; diff --git a/src/cpu/x86.h b/src/cpu/x86.h index c5e59551f..f52e430ac 100644 --- a/src/cpu/x86.h +++ b/src/cpu/x86.h @@ -1,82 +1,104 @@ -#define ABRT_MASK 0x7f +/* + * 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. + * + * Second CPU header. + * + * + * + * Authors: Sarah Walker, + * leilei, + * Miran Grca, + * + * Copyright 2008-2020 Sarah Walker. + * Copyright 2016-2018 leilei. + * Copyright 2016-2020 Miran Grca. + */ +#ifndef EMU_X86_H +#define EMU_X86_H + +#define ABRT_MASK 0x3f /*An 'expected' exception is one that would be expected to occur on every execution of this code path; eg a GPF due to being in v86 mode. An 'unexpected' exception is one that would be unlikely to occur on the next exception, eg a page fault may be fixed up by the exception handler and the next execution would not hit it. - + This distinction is used by the dynarec; a block that hits an 'expected' exception would be compiled, a block that hits an 'unexpected' exception would be rejected so that we don't end up with an unnecessarily short block*/ -#define ABRT_EXPECTED 0x80 +#define ABRT_EXPECTED 0x80 -extern uint8_t opcode, opcode2; -extern uint8_t flags_p; -extern uint8_t znptable8[256]; +extern uint8_t opcode; -extern uint16_t zero, oldcs; -extern uint16_t lastcs, lastpc; +extern uint8_t flags_p; +extern uint8_t znptable8[256]; + +extern uint16_t zero; +extern uint16_t oldcs; +extern uint16_t lastcs; +extern uint16_t lastpc; extern uint16_t *mod1add[2][8]; -extern uint16_t znptable16[65536]; +extern uint16_t znptable16[65536]; -extern int x86_was_reset, trap; -extern int codegen_flat_ss, codegen_flat_ds; -extern int timetolive, keyboardtimer, trap; -extern int optype, stack32; -extern int oldcpl, cgate32, cpl_override; -extern int nmi_enable; -extern int oddeven, inttype; +extern int x86_was_reset; +extern int trap; +extern int codegen_flat_ss; +extern int codegen_flat_ds; +extern int timetolive; +extern int keyboardtimer; +extern int trap; +extern int optype; +extern int stack32; +extern int oldcpl; +extern int cpl_override; +extern int nmi_enable; +extern int oddeven; +extern int inttype; -extern uint32_t use32; -extern uint32_t rmdat, easeg; -extern uint32_t oxpc, flags_zn; -extern uint32_t abrt_error; -extern uint32_t backupregs[16]; +extern uint32_t use32; +extern uint32_t rmdat; +extern uint32_t easeg; +extern uint32_t oxpc; +extern uint32_t flags_zn; +extern uint32_t abrt_error; +extern uint32_t backupregs[16]; extern uint32_t *mod1seg[8]; -extern uint32_t *eal_r, *eal_w; +extern uint32_t *eal_r; +extern uint32_t *eal_w; -#define fetchdat rmdat +extern int fpu_cycles; + +#define fetchdat rmdat #define setznp168 setznp16 -#define getr8(r) ((r&4)?cpu_state.regs[r&3].b.h:cpu_state.regs[r&3].b.l) -#define getr16(r) cpu_state.regs[r].w -#define getr32(r) cpu_state.regs[r].l +#define getr8(r) ((r & 4) ? cpu_state.regs[r & 3].b.h : cpu_state.regs[r & 3].b.l) +#define getr16(r) cpu_state.regs[r].w +#define getr32(r) cpu_state.regs[r].l -#define setr8(r,v) if (r&4) cpu_state.regs[r&3].b.h=v; \ - else cpu_state.regs[r&3].b.l=v; -#define setr16(r,v) cpu_state.regs[r].w=v -#define setr32(r,v) cpu_state.regs[r].l=v +#define setr8(r, v) \ + if (r & 4) \ + cpu_state.regs[r & 3].b.h = v; \ + else \ + cpu_state.regs[r & 3].b.l = v; +#define setr16(r, v) cpu_state.regs[r].w = v +#define setr32(r, v) cpu_state.regs[r].l = v -#define fetchea() { \ - rmdat = readmemb(cs + pc); \ - pc++; \ - reg = (rmdat >> 3) & 7; \ - mod = (rmdat >> 6) & 3; \ - rm = rmdat & 7; \ - if (mod!=3) \ - fetcheal(); \ - } +#define fetchea() \ + { \ + rmdat = readmemb(cs + pc); \ + pc++; \ + reg = (rmdat >> 3) & 7; \ + mod = (rmdat >> 6) & 3; \ + rm = rmdat & 7; \ + if (mod != 3) \ + fetcheal(); \ + } -#define JMP 1 -#define CALL 2 -#define IRET 3 -#define OPTYPE_INT 4 +extern void x86illegal(void); - -enum -{ - ABRT_NONE = 0, - ABRT_GEN, - ABRT_TS = 0xA, - ABRT_NP = 0xB, - ABRT_SS = 0xC, - ABRT_GPF = 0xD, - ABRT_PF = 0xE -}; - - -extern void x86_doabrt(int x86_abrt); -extern void x86illegal(); -extern void x86seg_reset(); -extern void x86gpf(char *s, uint16_t error); -extern void x86gpf_expected(char *s, uint16_t error); +#endif /*EMU_X86_H*/ diff --git a/src/cpu/x86_flags.h b/src/cpu/x86_flags.h index bf160390c..e82041783 100644 --- a/src/cpu/x86_flags.h +++ b/src/cpu/x86_flags.h @@ -1,783 +1,825 @@ extern int tempc; -enum -{ - FLAGS_UNKNOWN, - - FLAGS_ZN8, - FLAGS_ZN16, - FLAGS_ZN32, - - FLAGS_ADD8, - FLAGS_ADD16, - FLAGS_ADD32, - - FLAGS_SUB8, - FLAGS_SUB16, - FLAGS_SUB32, - - FLAGS_SHL8, - FLAGS_SHL16, - FLAGS_SHL32, +enum { + FLAGS_UNKNOWN, - FLAGS_SHR8, - FLAGS_SHR16, - FLAGS_SHR32, + FLAGS_ZN8, + FLAGS_ZN16, + FLAGS_ZN32, - FLAGS_SAR8, - FLAGS_SAR16, - FLAGS_SAR32, + FLAGS_ADD8, + FLAGS_ADD16, + FLAGS_ADD32, + + FLAGS_SUB8, + FLAGS_SUB16, + FLAGS_SUB32, + + FLAGS_SHL8, + FLAGS_SHL16, + FLAGS_SHL32, + + FLAGS_SHR8, + FLAGS_SHR16, + FLAGS_SHR32, + + FLAGS_SAR8, + FLAGS_SAR16, + FLAGS_SAR32, #ifdef USE_NEW_DYNAREC - FLAGS_ROL8, - FLAGS_ROL16, - FLAGS_ROL32, + FLAGS_ROL8, + FLAGS_ROL16, + FLAGS_ROL32, - FLAGS_ROR8, - FLAGS_ROR16, - FLAGS_ROR32, + FLAGS_ROR8, + FLAGS_ROR16, + FLAGS_ROR32, #endif - FLAGS_INC8, - FLAGS_INC16, - FLAGS_INC32, - - FLAGS_DEC8, - FLAGS_DEC16, - FLAGS_DEC32 + FLAGS_INC8, + FLAGS_INC16, + FLAGS_INC32, + + FLAGS_DEC8, + FLAGS_DEC16, + FLAGS_DEC32 #ifdef USE_NEW_DYNAREC -, + , - FLAGS_ADC8, - FLAGS_ADC16, - FLAGS_ADC32, + FLAGS_ADC8, + FLAGS_ADC16, + FLAGS_ADC32, - FLAGS_SBC8, - FLAGS_SBC16, - FLAGS_SBC32 + FLAGS_SBC8, + FLAGS_SBC16, + FLAGS_SBC32 #endif }; -static __inline int ZF_SET() +static __inline int +ZF_SET(void) { - switch (cpu_state.flags_op) - { - case FLAGS_ZN8: - case FLAGS_ZN16: - case FLAGS_ZN32: - case FLAGS_ADD8: - case FLAGS_ADD16: - case FLAGS_ADD32: - case FLAGS_SUB8: - case FLAGS_SUB16: - case FLAGS_SUB32: - case FLAGS_SHL8: - case FLAGS_SHL16: - case FLAGS_SHL32: - case FLAGS_SHR8: - case FLAGS_SHR16: - case FLAGS_SHR32: - case FLAGS_SAR8: - case FLAGS_SAR16: - case FLAGS_SAR32: - case FLAGS_INC8: - case FLAGS_INC16: - case FLAGS_INC32: - case FLAGS_DEC8: - case FLAGS_DEC16: - case FLAGS_DEC32: + switch (cpu_state.flags_op) { + case FLAGS_ZN8: + case FLAGS_ZN16: + case FLAGS_ZN32: + case FLAGS_ADD8: + case FLAGS_ADD16: + case FLAGS_ADD32: + case FLAGS_SUB8: + case FLAGS_SUB16: + case FLAGS_SUB32: + case FLAGS_SHL8: + case FLAGS_SHL16: + case FLAGS_SHL32: + case FLAGS_SHR8: + case FLAGS_SHR16: + case FLAGS_SHR32: + case FLAGS_SAR8: + case FLAGS_SAR16: + case FLAGS_SAR32: + case FLAGS_INC8: + case FLAGS_INC16: + case FLAGS_INC32: + case FLAGS_DEC8: + case FLAGS_DEC16: + case FLAGS_DEC32: #ifdef USE_NEW_DYNAREC - case FLAGS_ADC8: - case FLAGS_ADC16: - case FLAGS_ADC32: - case FLAGS_SBC8: - case FLAGS_SBC16: - case FLAGS_SBC32: + case FLAGS_ADC8: + case FLAGS_ADC16: + case FLAGS_ADC32: + case FLAGS_SBC8: + case FLAGS_SBC16: + case FLAGS_SBC32: #endif - return !cpu_state.flags_res; - + return !cpu_state.flags_res; + #ifdef USE_NEW_DYNAREC - case FLAGS_ROL8: - case FLAGS_ROL16: - case FLAGS_ROL32: - case FLAGS_ROR8: - case FLAGS_ROR16: - case FLAGS_ROR32: + case FLAGS_ROL8: + case FLAGS_ROL16: + case FLAGS_ROL32: + case FLAGS_ROR8: + case FLAGS_ROR16: + case FLAGS_ROR32: #endif - case FLAGS_UNKNOWN: - return cpu_state.flags & Z_FLAG; + case FLAGS_UNKNOWN: + return cpu_state.flags & Z_FLAG; #ifndef USE_NEW_DYNAREC - default: - return 0; + default: + return 0; #endif - } + } #ifdef USE_NEW_DYNAREC - return 0; + return 0; #endif } -static __inline int NF_SET() +static __inline int +NF_SET(void) { - switch (cpu_state.flags_op) - { - case FLAGS_ZN8: - case FLAGS_ADD8: - case FLAGS_SUB8: - case FLAGS_SHL8: - case FLAGS_SHR8: - case FLAGS_SAR8: - case FLAGS_INC8: - case FLAGS_DEC8: + switch (cpu_state.flags_op) { + case FLAGS_ZN8: + case FLAGS_ADD8: + case FLAGS_SUB8: + case FLAGS_SHL8: + case FLAGS_SHR8: + case FLAGS_SAR8: + case FLAGS_INC8: + case FLAGS_DEC8: #ifdef USE_NEW_DYNAREC - case FLAGS_ADC8: - case FLAGS_SBC8: + case FLAGS_ADC8: + case FLAGS_SBC8: #endif - return cpu_state.flags_res & 0x80; - - case FLAGS_ZN16: - case FLAGS_ADD16: - case FLAGS_SUB16: - case FLAGS_SHL16: - case FLAGS_SHR16: - case FLAGS_SAR16: - case FLAGS_INC16: - case FLAGS_DEC16: + return cpu_state.flags_res & 0x80; + + case FLAGS_ZN16: + case FLAGS_ADD16: + case FLAGS_SUB16: + case FLAGS_SHL16: + case FLAGS_SHR16: + case FLAGS_SAR16: + case FLAGS_INC16: + case FLAGS_DEC16: #ifdef USE_NEW_DYNAREC - case FLAGS_ADC16: - case FLAGS_SBC16: + case FLAGS_ADC16: + case FLAGS_SBC16: #endif - return cpu_state.flags_res & 0x8000; - - case FLAGS_ZN32: - case FLAGS_ADD32: - case FLAGS_SUB32: - case FLAGS_SHL32: - case FLAGS_SHR32: - case FLAGS_SAR32: - case FLAGS_INC32: - case FLAGS_DEC32: + return cpu_state.flags_res & 0x8000; + + case FLAGS_ZN32: + case FLAGS_ADD32: + case FLAGS_SUB32: + case FLAGS_SHL32: + case FLAGS_SHR32: + case FLAGS_SAR32: + case FLAGS_INC32: + case FLAGS_DEC32: #ifdef USE_NEW_DYNAREC - case FLAGS_ADC32: - case FLAGS_SBC32: + case FLAGS_ADC32: + case FLAGS_SBC32: #endif - return cpu_state.flags_res & 0x80000000; - + return cpu_state.flags_res & 0x80000000; + #ifdef USE_NEW_DYNAREC - case FLAGS_ROL8: - case FLAGS_ROL16: - case FLAGS_ROL32: - case FLAGS_ROR8: - case FLAGS_ROR16: - case FLAGS_ROR32: + case FLAGS_ROL8: + case FLAGS_ROL16: + case FLAGS_ROL32: + case FLAGS_ROR8: + case FLAGS_ROR16: + case FLAGS_ROR32: #endif - case FLAGS_UNKNOWN: - return cpu_state.flags & N_FLAG; + case FLAGS_UNKNOWN: + return cpu_state.flags & N_FLAG; #ifndef USE_NEW_DYNAREC - default: - return 0; + default: + return 0; #endif - } + } #ifdef USE_NEW_DYNAREC - return 0; + return 0; #endif } -static __inline int PF_SET() +static __inline int +PF_SET(void) { - switch (cpu_state.flags_op) - { - case FLAGS_ZN8: - case FLAGS_ZN16: - case FLAGS_ZN32: - case FLAGS_ADD8: - case FLAGS_ADD16: - case FLAGS_ADD32: - case FLAGS_SUB8: - case FLAGS_SUB16: - case FLAGS_SUB32: - case FLAGS_SHL8: - case FLAGS_SHL16: - case FLAGS_SHL32: - case FLAGS_SHR8: - case FLAGS_SHR16: - case FLAGS_SHR32: - case FLAGS_SAR8: - case FLAGS_SAR16: - case FLAGS_SAR32: - case FLAGS_INC8: - case FLAGS_INC16: - case FLAGS_INC32: - case FLAGS_DEC8: - case FLAGS_DEC16: - case FLAGS_DEC32: + switch (cpu_state.flags_op) { + case FLAGS_ZN8: + case FLAGS_ZN16: + case FLAGS_ZN32: + case FLAGS_ADD8: + case FLAGS_ADD16: + case FLAGS_ADD32: + case FLAGS_SUB8: + case FLAGS_SUB16: + case FLAGS_SUB32: + case FLAGS_SHL8: + case FLAGS_SHL16: + case FLAGS_SHL32: + case FLAGS_SHR8: + case FLAGS_SHR16: + case FLAGS_SHR32: + case FLAGS_SAR8: + case FLAGS_SAR16: + case FLAGS_SAR32: + case FLAGS_INC8: + case FLAGS_INC16: + case FLAGS_INC32: + case FLAGS_DEC8: + case FLAGS_DEC16: + case FLAGS_DEC32: #ifdef USE_NEW_DYNAREC - case FLAGS_ADC8: - case FLAGS_ADC16: - case FLAGS_ADC32: - case FLAGS_SBC8: - case FLAGS_SBC16: - case FLAGS_SBC32: + case FLAGS_ADC8: + case FLAGS_ADC16: + case FLAGS_ADC32: + case FLAGS_SBC8: + case FLAGS_SBC16: + case FLAGS_SBC32: #endif - return znptable8[cpu_state.flags_res & 0xff] & P_FLAG; - + return znptable8[cpu_state.flags_res & 0xff] & P_FLAG; + #ifdef USE_NEW_DYNAREC - case FLAGS_ROL8: - case FLAGS_ROL16: - case FLAGS_ROL32: - case FLAGS_ROR8: - case FLAGS_ROR16: - case FLAGS_ROR32: + case FLAGS_ROL8: + case FLAGS_ROL16: + case FLAGS_ROL32: + case FLAGS_ROR8: + case FLAGS_ROR16: + case FLAGS_ROR32: #endif - case FLAGS_UNKNOWN: - return cpu_state.flags & P_FLAG; + case FLAGS_UNKNOWN: + return cpu_state.flags & P_FLAG; #ifndef USE_NEW_DYNAREC - default: - return 0; + default: + return 0; #endif - } + } #ifdef USE_NEW_DYNAREC - return 0; + return 0; #endif } -static __inline int VF_SET() +static __inline int +VF_SET(void) { - switch (cpu_state.flags_op) - { - case FLAGS_ZN8: - case FLAGS_ZN16: - case FLAGS_ZN32: - case FLAGS_SAR8: - case FLAGS_SAR16: - case FLAGS_SAR32: - return 0; - -#ifdef USE_NEW_DYNAREC - case FLAGS_ADC8: -#endif - case FLAGS_ADD8: - case FLAGS_INC8: - return !((cpu_state.flags_op1 ^ cpu_state.flags_op2) & 0x80) && ((cpu_state.flags_op1 ^ cpu_state.flags_res) & 0x80); -#ifdef USE_NEW_DYNAREC - case FLAGS_ADC16: -#endif - case FLAGS_ADD16: - case FLAGS_INC16: - return !((cpu_state.flags_op1 ^ cpu_state.flags_op2) & 0x8000) && ((cpu_state.flags_op1 ^ cpu_state.flags_res) & 0x8000); -#ifdef USE_NEW_DYNAREC - case FLAGS_ADC32: -#endif - case FLAGS_ADD32: - case FLAGS_INC32: - return !((cpu_state.flags_op1 ^ cpu_state.flags_op2) & 0x80000000) && ((cpu_state.flags_op1 ^ cpu_state.flags_res) & 0x80000000); + switch (cpu_state.flags_op) { + case FLAGS_ZN8: + case FLAGS_ZN16: + case FLAGS_ZN32: + case FLAGS_SAR8: + case FLAGS_SAR16: + case FLAGS_SAR32: + return 0; #ifdef USE_NEW_DYNAREC - case FLAGS_SBC8: + case FLAGS_ADC8: #endif - case FLAGS_SUB8: - case FLAGS_DEC8: - return ((cpu_state.flags_op1 ^ cpu_state.flags_op2) & (cpu_state.flags_op1 ^ cpu_state.flags_res) & 0x80); + case FLAGS_ADD8: + case FLAGS_INC8: + return !((cpu_state.flags_op1 ^ cpu_state.flags_op2) & 0x80) && ((cpu_state.flags_op1 ^ cpu_state.flags_res) & 0x80); #ifdef USE_NEW_DYNAREC - case FLAGS_SBC16: + case FLAGS_ADC16: #endif - case FLAGS_SUB16: - case FLAGS_DEC16: - return ((cpu_state.flags_op1 ^ cpu_state.flags_op2) & (cpu_state.flags_op1 ^ cpu_state.flags_res) & 0x8000); + case FLAGS_ADD16: + case FLAGS_INC16: + return !((cpu_state.flags_op1 ^ cpu_state.flags_op2) & 0x8000) && ((cpu_state.flags_op1 ^ cpu_state.flags_res) & 0x8000); #ifdef USE_NEW_DYNAREC - case FLAGS_SBC32: + case FLAGS_ADC32: #endif - case FLAGS_SUB32: - case FLAGS_DEC32: - return ((cpu_state.flags_op1 ^ cpu_state.flags_op2) & (cpu_state.flags_op1 ^ cpu_state.flags_res) & 0x80000000); - - case FLAGS_SHL8: - return (((cpu_state.flags_op1 << cpu_state.flags_op2) ^ (cpu_state.flags_op1 << (cpu_state.flags_op2 - 1))) & 0x80); - case FLAGS_SHL16: - return (((cpu_state.flags_op1 << cpu_state.flags_op2) ^ (cpu_state.flags_op1 << (cpu_state.flags_op2 - 1))) & 0x8000); - case FLAGS_SHL32: - return (((cpu_state.flags_op1 << cpu_state.flags_op2) ^ (cpu_state.flags_op1 << (cpu_state.flags_op2 - 1))) & 0x80000000); - - case FLAGS_SHR8: - return ((cpu_state.flags_op2 == 1) && (cpu_state.flags_op1 & 0x80)); - case FLAGS_SHR16: - return ((cpu_state.flags_op2 == 1) && (cpu_state.flags_op1 & 0x8000)); - case FLAGS_SHR32: - return ((cpu_state.flags_op2 == 1) && (cpu_state.flags_op1 & 0x80000000)); + case FLAGS_ADD32: + case FLAGS_INC32: + return !((cpu_state.flags_op1 ^ cpu_state.flags_op2) & 0x80000000) && ((cpu_state.flags_op1 ^ cpu_state.flags_res) & 0x80000000); #ifdef USE_NEW_DYNAREC - case FLAGS_ROL8: - return (cpu_state.flags_res ^ (cpu_state.flags_res >> 7)) & 1; - case FLAGS_ROL16: - return (cpu_state.flags_res ^ (cpu_state.flags_res >> 15)) & 1; - case FLAGS_ROL32: - return (cpu_state.flags_res ^ (cpu_state.flags_res >> 31)) & 1; + case FLAGS_SBC8: +#endif + case FLAGS_SUB8: + case FLAGS_DEC8: + return ((cpu_state.flags_op1 ^ cpu_state.flags_op2) & (cpu_state.flags_op1 ^ cpu_state.flags_res) & 0x80); +#ifdef USE_NEW_DYNAREC + case FLAGS_SBC16: +#endif + case FLAGS_SUB16: + case FLAGS_DEC16: + return ((cpu_state.flags_op1 ^ cpu_state.flags_op2) & (cpu_state.flags_op1 ^ cpu_state.flags_res) & 0x8000); +#ifdef USE_NEW_DYNAREC + case FLAGS_SBC32: +#endif + case FLAGS_SUB32: + case FLAGS_DEC32: + return ((cpu_state.flags_op1 ^ cpu_state.flags_op2) & (cpu_state.flags_op1 ^ cpu_state.flags_res) & 0x80000000); - case FLAGS_ROR8: - return (cpu_state.flags_res ^ (cpu_state.flags_res >> 1)) & 0x40; - case FLAGS_ROR16: - return (cpu_state.flags_res ^ (cpu_state.flags_res >> 1)) & 0x4000; - case FLAGS_ROR32: - return (cpu_state.flags_res ^ (cpu_state.flags_res >> 1)) & 0x40000000; + case FLAGS_SHL8: + return (((cpu_state.flags_op1 << cpu_state.flags_op2) ^ (cpu_state.flags_op1 << (cpu_state.flags_op2 - 1))) & 0x80); + case FLAGS_SHL16: + return (((cpu_state.flags_op1 << cpu_state.flags_op2) ^ (cpu_state.flags_op1 << (cpu_state.flags_op2 - 1))) & 0x8000); + case FLAGS_SHL32: + return (((cpu_state.flags_op1 << cpu_state.flags_op2) ^ (cpu_state.flags_op1 << (cpu_state.flags_op2 - 1))) & 0x80000000); + + case FLAGS_SHR8: + return ((cpu_state.flags_op2 == 1) && (cpu_state.flags_op1 & 0x80)); + case FLAGS_SHR16: + return ((cpu_state.flags_op2 == 1) && (cpu_state.flags_op1 & 0x8000)); + case FLAGS_SHR32: + return ((cpu_state.flags_op2 == 1) && (cpu_state.flags_op1 & 0x80000000)); + +#ifdef USE_NEW_DYNAREC + case FLAGS_ROL8: + return (cpu_state.flags_res ^ (cpu_state.flags_res >> 7)) & 1; + case FLAGS_ROL16: + return (cpu_state.flags_res ^ (cpu_state.flags_res >> 15)) & 1; + case FLAGS_ROL32: + return (cpu_state.flags_res ^ (cpu_state.flags_res >> 31)) & 1; + + case FLAGS_ROR8: + return (cpu_state.flags_res ^ (cpu_state.flags_res >> 1)) & 0x40; + case FLAGS_ROR16: + return (cpu_state.flags_res ^ (cpu_state.flags_res >> 1)) & 0x4000; + case FLAGS_ROR32: + return (cpu_state.flags_res ^ (cpu_state.flags_res >> 1)) & 0x40000000; #endif - case FLAGS_UNKNOWN: - return cpu_state.flags & V_FLAG; + case FLAGS_UNKNOWN: + return cpu_state.flags & V_FLAG; #ifndef USE_NEW_DYNAREC - default: - return 0; + default: + return 0; #endif - } + } #ifdef USE_NEW_DYNAREC - return 0; + return 0; #endif } -static __inline int AF_SET() +static __inline int +AF_SET(void) { - switch (cpu_state.flags_op) - { - case FLAGS_ZN8: - case FLAGS_ZN16: - case FLAGS_ZN32: - case FLAGS_SHL8: - case FLAGS_SHL16: - case FLAGS_SHL32: - case FLAGS_SHR8: - case FLAGS_SHR16: - case FLAGS_SHR32: - case FLAGS_SAR8: - case FLAGS_SAR16: - case FLAGS_SAR32: - return 0; - - case FLAGS_ADD8: - case FLAGS_ADD16: - case FLAGS_ADD32: - case FLAGS_INC8: - case FLAGS_INC16: - case FLAGS_INC32: - return ((cpu_state.flags_op1 & 0xF) + (cpu_state.flags_op2 & 0xF)) & 0x10; + switch (cpu_state.flags_op) { + case FLAGS_ZN8: + case FLAGS_ZN16: + case FLAGS_ZN32: + case FLAGS_SHL8: + case FLAGS_SHL16: + case FLAGS_SHL32: + case FLAGS_SHR8: + case FLAGS_SHR16: + case FLAGS_SHR32: + case FLAGS_SAR8: + case FLAGS_SAR16: + case FLAGS_SAR32: + return 0; + + case FLAGS_ADD8: + case FLAGS_ADD16: + case FLAGS_ADD32: + case FLAGS_INC8: + case FLAGS_INC16: + case FLAGS_INC32: + return ((cpu_state.flags_op1 & 0xF) + (cpu_state.flags_op2 & 0xF)) & 0x10; #ifdef USE_NEW_DYNAREC - case FLAGS_ADC8: - return ((cpu_state.flags_res & 0xf) < (cpu_state.flags_op1 & 0xf)) || - ((cpu_state.flags_res & 0xf) == (cpu_state.flags_op1 & 0xf) && cpu_state.flags_op2 == 0xff); - case FLAGS_ADC16: - return ((cpu_state.flags_res & 0xf) < (cpu_state.flags_op1 & 0xf)) || - ((cpu_state.flags_res & 0xf) == (cpu_state.flags_op1 & 0xf) && cpu_state.flags_op2 == 0xffff); - case FLAGS_ADC32: - return ((cpu_state.flags_res & 0xf) < (cpu_state.flags_op1 & 0xf)) || - ((cpu_state.flags_res & 0xf) == (cpu_state.flags_op1 & 0xf) && cpu_state.flags_op2 == 0xffffffff); + case FLAGS_ADC8: + return ((cpu_state.flags_res & 0xf) < (cpu_state.flags_op1 & 0xf)) || ((cpu_state.flags_res & 0xf) == (cpu_state.flags_op1 & 0xf) && cpu_state.flags_op2 == 0xff); + case FLAGS_ADC16: + return ((cpu_state.flags_res & 0xf) < (cpu_state.flags_op1 & 0xf)) || ((cpu_state.flags_res & 0xf) == (cpu_state.flags_op1 & 0xf) && cpu_state.flags_op2 == 0xffff); + case FLAGS_ADC32: + return ((cpu_state.flags_res & 0xf) < (cpu_state.flags_op1 & 0xf)) || ((cpu_state.flags_res & 0xf) == (cpu_state.flags_op1 & 0xf) && cpu_state.flags_op2 == 0xffffffff); #endif - case FLAGS_SUB8: - case FLAGS_SUB16: - case FLAGS_SUB32: - case FLAGS_DEC8: - case FLAGS_DEC16: - case FLAGS_DEC32: - return ((cpu_state.flags_op1 & 0xF) - (cpu_state.flags_op2 & 0xF)) & 0x10; + case FLAGS_SUB8: + case FLAGS_SUB16: + case FLAGS_SUB32: + case FLAGS_DEC8: + case FLAGS_DEC16: + case FLAGS_DEC32: + return ((cpu_state.flags_op1 & 0xF) - (cpu_state.flags_op2 & 0xF)) & 0x10; #ifdef USE_NEW_DYNAREC - case FLAGS_SBC8: - case FLAGS_SBC16: - case FLAGS_SBC32: - return ((cpu_state.flags_op1 & 0xf) < (cpu_state.flags_op2 & 0xf)) || - ((cpu_state.flags_op1 & 0xf) == (cpu_state.flags_op2 & 0xf) && (cpu_state.flags_res & 0xf) != 0); - - case FLAGS_ROL8: - case FLAGS_ROL16: - case FLAGS_ROL32: - case FLAGS_ROR8: - case FLAGS_ROR16: - case FLAGS_ROR32: + case FLAGS_SBC8: + case FLAGS_SBC16: + case FLAGS_SBC32: + return ((cpu_state.flags_op1 & 0xf) < (cpu_state.flags_op2 & 0xf)) || ((cpu_state.flags_op1 & 0xf) == (cpu_state.flags_op2 & 0xf) && (cpu_state.flags_res & 0xf) != 0); + + case FLAGS_ROL8: + case FLAGS_ROL16: + case FLAGS_ROL32: + case FLAGS_ROR8: + case FLAGS_ROR16: + case FLAGS_ROR32: #endif - case FLAGS_UNKNOWN: - return cpu_state.flags & A_FLAG; + case FLAGS_UNKNOWN: + return cpu_state.flags & A_FLAG; #ifndef USE_NEW_DYNAREC - default: - return 0; + default: + return 0; #endif - } + } #ifdef USE_NEW_DYNAREC - return 0; + return 0; #endif } -static __inline int CF_SET() +static __inline int +CF_SET(void) { - switch (cpu_state.flags_op) - { - case FLAGS_ADD8: - return ((cpu_state.flags_op1 + cpu_state.flags_op2) & 0x100) ? 1 : 0; - case FLAGS_ADD16: - return ((cpu_state.flags_op1 + cpu_state.flags_op2) & 0x10000) ? 1 : 0; - case FLAGS_ADD32: - return (cpu_state.flags_res < cpu_state.flags_op1); + switch (cpu_state.flags_op) { + case FLAGS_ADD8: + return ((cpu_state.flags_op1 + cpu_state.flags_op2) & 0x100) ? 1 : 0; + case FLAGS_ADD16: + return ((cpu_state.flags_op1 + cpu_state.flags_op2) & 0x10000) ? 1 : 0; + case FLAGS_ADD32: + return (cpu_state.flags_res < cpu_state.flags_op1); #ifdef USE_NEW_DYNAREC - case FLAGS_ADC8: - return (cpu_state.flags_res < cpu_state.flags_op1) || - (cpu_state.flags_res == cpu_state.flags_op1 && cpu_state.flags_op2 == 0xff); - case FLAGS_ADC16: - return (cpu_state.flags_res < cpu_state.flags_op1) || - (cpu_state.flags_res == cpu_state.flags_op1 && cpu_state.flags_op2 == 0xffff); - case FLAGS_ADC32: - return (cpu_state.flags_res < cpu_state.flags_op1) || - (cpu_state.flags_res == cpu_state.flags_op1 && cpu_state.flags_op2 == 0xffffffff); + case FLAGS_ADC8: + return (cpu_state.flags_res < cpu_state.flags_op1) || (cpu_state.flags_res == cpu_state.flags_op1 && cpu_state.flags_op2 == 0xff); + case FLAGS_ADC16: + return (cpu_state.flags_res < cpu_state.flags_op1) || (cpu_state.flags_res == cpu_state.flags_op1 && cpu_state.flags_op2 == 0xffff); + case FLAGS_ADC32: + return (cpu_state.flags_res < cpu_state.flags_op1) || (cpu_state.flags_res == cpu_state.flags_op1 && cpu_state.flags_op2 == 0xffffffff); #endif - case FLAGS_SUB8: - case FLAGS_SUB16: - case FLAGS_SUB32: - return (cpu_state.flags_op1 < cpu_state.flags_op2); + case FLAGS_SUB8: + case FLAGS_SUB16: + case FLAGS_SUB32: + return (cpu_state.flags_op1 < cpu_state.flags_op2); #ifdef USE_NEW_DYNAREC - case FLAGS_SBC8: - case FLAGS_SBC16: - case FLAGS_SBC32: - return (cpu_state.flags_op1 < cpu_state.flags_op2) || - (cpu_state.flags_op1 == cpu_state.flags_op2 && cpu_state.flags_res != 0); + case FLAGS_SBC8: + case FLAGS_SBC16: + case FLAGS_SBC32: + return (cpu_state.flags_op1 < cpu_state.flags_op2) || (cpu_state.flags_op1 == cpu_state.flags_op2 && cpu_state.flags_res != 0); #endif - case FLAGS_SHL8: - return ((cpu_state.flags_op1 << (cpu_state.flags_op2 - 1)) & 0x80) ? 1 : 0; - case FLAGS_SHL16: - return ((cpu_state.flags_op1 << (cpu_state.flags_op2 - 1)) & 0x8000) ? 1 : 0; - case FLAGS_SHL32: - return ((cpu_state.flags_op1 << (cpu_state.flags_op2 - 1)) & 0x80000000) ? 1 : 0; + case FLAGS_SHL8: + return ((cpu_state.flags_op1 << (cpu_state.flags_op2 - 1)) & 0x80) ? 1 : 0; + case FLAGS_SHL16: + return ((cpu_state.flags_op1 << (cpu_state.flags_op2 - 1)) & 0x8000) ? 1 : 0; + case FLAGS_SHL32: + return ((cpu_state.flags_op1 << (cpu_state.flags_op2 - 1)) & 0x80000000) ? 1 : 0; - case FLAGS_SHR8: - case FLAGS_SHR16: - case FLAGS_SHR32: - return (cpu_state.flags_op1 >> (cpu_state.flags_op2 - 1)) & 1; + case FLAGS_SHR8: + case FLAGS_SHR16: + case FLAGS_SHR32: + return (cpu_state.flags_op1 >> (cpu_state.flags_op2 - 1)) & 1; - case FLAGS_SAR8: - return ((int8_t)cpu_state.flags_op1 >> (cpu_state.flags_op2 - 1)) & 1; - case FLAGS_SAR16: - return ((int16_t)cpu_state.flags_op1 >> (cpu_state.flags_op2 - 1)) & 1; - case FLAGS_SAR32: - return ((int32_t)cpu_state.flags_op1 >> (cpu_state.flags_op2 - 1)) & 1; + case FLAGS_SAR8: + return ((int8_t) cpu_state.flags_op1 >> (cpu_state.flags_op2 - 1)) & 1; + case FLAGS_SAR16: + return ((int16_t) cpu_state.flags_op1 >> (cpu_state.flags_op2 - 1)) & 1; + case FLAGS_SAR32: + return ((int32_t) cpu_state.flags_op1 >> (cpu_state.flags_op2 - 1)) & 1; - case FLAGS_ZN8: - case FLAGS_ZN16: - case FLAGS_ZN32: - return 0; + case FLAGS_ZN8: + case FLAGS_ZN16: + case FLAGS_ZN32: + return 0; #ifdef USE_NEW_DYNAREC - case FLAGS_ROL8: - case FLAGS_ROL16: - case FLAGS_ROL32: - return cpu_state.flags_res & 1; - - case FLAGS_ROR8: - return (cpu_state.flags_res & 0x80) ? 1 : 0; - case FLAGS_ROR16: - return (cpu_state.flags_res & 0x8000) ? 1 :0; - case FLAGS_ROR32: - return (cpu_state.flags_res & 0x80000000) ? 1 : 0; + case FLAGS_ROL8: + case FLAGS_ROL16: + case FLAGS_ROL32: + return cpu_state.flags_res & 1; + + case FLAGS_ROR8: + return (cpu_state.flags_res & 0x80) ? 1 : 0; + case FLAGS_ROR16: + return (cpu_state.flags_res & 0x8000) ? 1 : 0; + case FLAGS_ROR32: + return (cpu_state.flags_res & 0x80000000) ? 1 : 0; #endif - case FLAGS_DEC8: - case FLAGS_DEC16: - case FLAGS_DEC32: - case FLAGS_INC8: - case FLAGS_INC16: - case FLAGS_INC32: - case FLAGS_UNKNOWN: - return cpu_state.flags & C_FLAG; + case FLAGS_DEC8: + case FLAGS_DEC16: + case FLAGS_DEC32: + case FLAGS_INC8: + case FLAGS_INC16: + case FLAGS_INC32: + case FLAGS_UNKNOWN: + return cpu_state.flags & C_FLAG; #ifndef USE_NEW_DYNAREC - default: - return 0; + default: + return 0; #endif - } + } #ifdef USE_NEW_DYNAREC - return 0; + return 0; #endif } -static __inline void flags_rebuild() -{ - if (cpu_state.flags_op != FLAGS_UNKNOWN) - { - uint16_t tempf = 0; - if (CF_SET()) tempf |= C_FLAG; - if (PF_SET()) tempf |= P_FLAG; - if (AF_SET()) tempf |= A_FLAG; - if (ZF_SET()) tempf |= Z_FLAG; - if (NF_SET()) tempf |= N_FLAG; - if (VF_SET()) tempf |= V_FLAG; - cpu_state.flags = (cpu_state.flags & ~0x8d5) | tempf; - cpu_state.flags_op = FLAGS_UNKNOWN; - } -} - -static __inline void flags_extract() +static __inline void +flags_rebuild(void) { + if (cpu_state.flags_op != FLAGS_UNKNOWN) { + uint16_t tempf = 0; + if (CF_SET()) + tempf |= C_FLAG; + if (PF_SET()) + tempf |= P_FLAG; + if (AF_SET()) + tempf |= A_FLAG; + if (ZF_SET()) + tempf |= Z_FLAG; + if (NF_SET()) + tempf |= N_FLAG; + if (VF_SET()) + tempf |= V_FLAG; + cpu_state.flags = (cpu_state.flags & ~0x8d5) | tempf; cpu_state.flags_op = FLAGS_UNKNOWN; + } } -static __inline void flags_rebuild_c() +static __inline void +flags_extract(void) { - if (cpu_state.flags_op != FLAGS_UNKNOWN) - { - if (CF_SET()) - cpu_state.flags |= C_FLAG; - else - cpu_state.flags &= ~C_FLAG; - } + cpu_state.flags_op = FLAGS_UNKNOWN; +} + +static __inline void +flags_rebuild_c(void) +{ + if (cpu_state.flags_op != FLAGS_UNKNOWN) { + if (CF_SET()) + cpu_state.flags |= C_FLAG; + else + cpu_state.flags &= ~C_FLAG; + } } #ifdef USE_NEW_DYNAREC -static __inline int flags_res_valid() +static __inline int +flags_res_valid(void) { - if (cpu_state.flags_op == FLAGS_UNKNOWN || - (cpu_state.flags_op >= FLAGS_ROL8 && cpu_state.flags_op <= FLAGS_ROR32)) - return 0; + if ((cpu_state.flags_op == FLAGS_UNKNOWN) || ((cpu_state.flags_op >= FLAGS_ROL8) && (cpu_state.flags_op <= FLAGS_ROR32))) + return 0; - return 1; + return 1; } #endif -static __inline void setznp8(uint8_t val) +static __inline void +setznp8(uint8_t val) { - cpu_state.flags_op = FLAGS_ZN8; - cpu_state.flags_res = val; + cpu_state.flags_op = FLAGS_ZN8; + cpu_state.flags_res = val; } -static __inline void setznp16(uint16_t val) +static __inline void +setznp16(uint16_t val) { - cpu_state.flags_op = FLAGS_ZN16; - cpu_state.flags_res = val; + cpu_state.flags_op = FLAGS_ZN16; + cpu_state.flags_res = val; } -static __inline void setznp32(uint32_t val) +static __inline void +setznp32(uint32_t val) { - cpu_state.flags_op = FLAGS_ZN32; - cpu_state.flags_res = val; + cpu_state.flags_op = FLAGS_ZN32; + cpu_state.flags_res = val; } #define set_flags_shift(op, orig, shift, res) \ - cpu_state.flags_op = op; \ - cpu_state.flags_res = res; \ - cpu_state.flags_op1 = orig; \ - cpu_state.flags_op2 = shift; + cpu_state.flags_op = op; \ + cpu_state.flags_res = res; \ + cpu_state.flags_op1 = orig; \ + cpu_state.flags_op2 = shift; #ifdef USE_NEW_DYNAREC -#define set_flags_rotate(op, res) \ - cpu_state.flags_op = op; \ +# define set_flags_rotate(op, res) \ + cpu_state.flags_op = op; \ cpu_state.flags_res = res; #endif -static __inline void setadd8(uint8_t a, uint8_t b) +static __inline void +setadd8(uint8_t a, uint8_t b) { - cpu_state.flags_op1 = a; - cpu_state.flags_op2 = b; - cpu_state.flags_res = (a + b) & 0xff; - cpu_state.flags_op = FLAGS_ADD8; + cpu_state.flags_op1 = a; + cpu_state.flags_op2 = b; + cpu_state.flags_res = (a + b) & 0xff; + cpu_state.flags_op = FLAGS_ADD8; } -static __inline void setadd16(uint16_t a, uint16_t b) +static __inline void +setadd16(uint16_t a, uint16_t b) { - cpu_state.flags_op1 = a; - cpu_state.flags_op2 = b; - cpu_state.flags_res = (a + b) & 0xffff; - cpu_state.flags_op = FLAGS_ADD16; + cpu_state.flags_op1 = a; + cpu_state.flags_op2 = b; + cpu_state.flags_res = (a + b) & 0xffff; + cpu_state.flags_op = FLAGS_ADD16; } -static __inline void setadd32(uint32_t a, uint32_t b) +static __inline void +setadd32(uint32_t a, uint32_t b) { - cpu_state.flags_op1 = a; - cpu_state.flags_op2 = b; - cpu_state.flags_res = a + b; - cpu_state.flags_op = FLAGS_ADD32; + cpu_state.flags_op1 = a; + cpu_state.flags_op2 = b; + cpu_state.flags_res = a + b; + cpu_state.flags_op = FLAGS_ADD32; } -static __inline void setadd8nc(uint8_t a, uint8_t b) +static __inline void +setadd8nc(uint8_t a, uint8_t b) { - flags_rebuild_c(); - cpu_state.flags_op1 = a; - cpu_state.flags_op2 = b; - cpu_state.flags_res = (a + b) & 0xff; - cpu_state.flags_op = FLAGS_INC8; + flags_rebuild_c(); + cpu_state.flags_op1 = a; + cpu_state.flags_op2 = b; + cpu_state.flags_res = (a + b) & 0xff; + cpu_state.flags_op = FLAGS_INC8; } -static __inline void setadd16nc(uint16_t a, uint16_t b) +static __inline void +setadd16nc(uint16_t a, uint16_t b) { - flags_rebuild_c(); - cpu_state.flags_op1 = a; - cpu_state.flags_op2 = b; - cpu_state.flags_res = (a + b) & 0xffff; - cpu_state.flags_op = FLAGS_INC16; + flags_rebuild_c(); + cpu_state.flags_op1 = a; + cpu_state.flags_op2 = b; + cpu_state.flags_res = (a + b) & 0xffff; + cpu_state.flags_op = FLAGS_INC16; } -static __inline void setadd32nc(uint32_t a, uint32_t b) +static __inline void +setadd32nc(uint32_t a, uint32_t b) { - flags_rebuild_c(); - cpu_state.flags_op1 = a; - cpu_state.flags_op2 = b; - cpu_state.flags_res = a + b; - cpu_state.flags_op = FLAGS_INC32; + flags_rebuild_c(); + cpu_state.flags_op1 = a; + cpu_state.flags_op2 = b; + cpu_state.flags_res = a + b; + cpu_state.flags_op = FLAGS_INC32; } -static __inline void setsub8(uint8_t a, uint8_t b) +static __inline void +setsub8(uint8_t a, uint8_t b) { - cpu_state.flags_op1 = a; - cpu_state.flags_op2 = b; - cpu_state.flags_res = (a - b) & 0xff; - cpu_state.flags_op = FLAGS_SUB8; + cpu_state.flags_op1 = a; + cpu_state.flags_op2 = b; + cpu_state.flags_res = (a - b) & 0xff; + cpu_state.flags_op = FLAGS_SUB8; } -static __inline void setsub16(uint16_t a, uint16_t b) +static __inline void +setsub16(uint16_t a, uint16_t b) { - cpu_state.flags_op1 = a; - cpu_state.flags_op2 = b; - cpu_state.flags_res = (a - b) & 0xffff; - cpu_state.flags_op = FLAGS_SUB16; + cpu_state.flags_op1 = a; + cpu_state.flags_op2 = b; + cpu_state.flags_res = (a - b) & 0xffff; + cpu_state.flags_op = FLAGS_SUB16; } -static __inline void setsub32(uint32_t a, uint32_t b) +static __inline void +setsub32(uint32_t a, uint32_t b) { - cpu_state.flags_op1 = a; - cpu_state.flags_op2 = b; - cpu_state.flags_res = a - b; - cpu_state.flags_op = FLAGS_SUB32; + cpu_state.flags_op1 = a; + cpu_state.flags_op2 = b; + cpu_state.flags_res = a - b; + cpu_state.flags_op = FLAGS_SUB32; } -static __inline void setsub8nc(uint8_t a, uint8_t b) +static __inline void +setsub8nc(uint8_t a, uint8_t b) { - flags_rebuild_c(); - cpu_state.flags_op1 = a; - cpu_state.flags_op2 = b; - cpu_state.flags_res = (a - b) & 0xff; - cpu_state.flags_op = FLAGS_DEC8; + flags_rebuild_c(); + cpu_state.flags_op1 = a; + cpu_state.flags_op2 = b; + cpu_state.flags_res = (a - b) & 0xff; + cpu_state.flags_op = FLAGS_DEC8; } -static __inline void setsub16nc(uint16_t a, uint16_t b) +static __inline void +setsub16nc(uint16_t a, uint16_t b) { - flags_rebuild_c(); - cpu_state.flags_op1 = a; - cpu_state.flags_op2 = b; - cpu_state.flags_res = (a - b) & 0xffff; - cpu_state.flags_op = FLAGS_DEC16; + flags_rebuild_c(); + cpu_state.flags_op1 = a; + cpu_state.flags_op2 = b; + cpu_state.flags_res = (a - b) & 0xffff; + cpu_state.flags_op = FLAGS_DEC16; } -static __inline void setsub32nc(uint32_t a, uint32_t b) +static __inline void +setsub32nc(uint32_t a, uint32_t b) { - flags_rebuild_c(); - cpu_state.flags_op1 = a; - cpu_state.flags_op2 = b; - cpu_state.flags_res = a - b; - cpu_state.flags_op = FLAGS_DEC32; + flags_rebuild_c(); + cpu_state.flags_op1 = a; + cpu_state.flags_op2 = b; + cpu_state.flags_res = a - b; + cpu_state.flags_op = FLAGS_DEC32; } #ifdef USE_NEW_DYNAREC -static __inline void setadc8(uint8_t a, uint8_t b) +static __inline void +setadc8(uint8_t a, uint8_t b) { - cpu_state.flags_op1 = a; - cpu_state.flags_op2 = b; - cpu_state.flags_res = (a + b + tempc) & 0xff; - cpu_state.flags_op = FLAGS_ADC8; + cpu_state.flags_op1 = a; + cpu_state.flags_op2 = b; + cpu_state.flags_res = (a + b + tempc) & 0xff; + cpu_state.flags_op = FLAGS_ADC8; } -static __inline void setadc16(uint16_t a, uint16_t b) +static __inline void +setadc16(uint16_t a, uint16_t b) { - cpu_state.flags_op1 = a; - cpu_state.flags_op2 = b; - cpu_state.flags_res = (a + b + tempc) & 0xffff; - cpu_state.flags_op = FLAGS_ADC16; + cpu_state.flags_op1 = a; + cpu_state.flags_op2 = b; + cpu_state.flags_res = (a + b + tempc) & 0xffff; + cpu_state.flags_op = FLAGS_ADC16; } -static __inline void setadc32(uint32_t a, uint32_t b) +static __inline void +setadc32(uint32_t a, uint32_t b) { - cpu_state.flags_op1 = a; - cpu_state.flags_op2 = b; - cpu_state.flags_res = a + b + tempc; - cpu_state.flags_op = FLAGS_ADC32; + cpu_state.flags_op1 = a; + cpu_state.flags_op2 = b; + cpu_state.flags_res = a + b + tempc; + cpu_state.flags_op = FLAGS_ADC32; } -static __inline void setsbc8(uint8_t a, uint8_t b) +static __inline void +setsbc8(uint8_t a, uint8_t b) { - cpu_state.flags_op1 = a; - cpu_state.flags_op2 = b; - cpu_state.flags_res = (a - (b + tempc)) & 0xff; - cpu_state.flags_op = FLAGS_SBC8; + cpu_state.flags_op1 = a; + cpu_state.flags_op2 = b; + cpu_state.flags_res = (a - (b + tempc)) & 0xff; + cpu_state.flags_op = FLAGS_SBC8; } -static __inline void setsbc16(uint16_t a, uint16_t b) +static __inline void +setsbc16(uint16_t a, uint16_t b) { - cpu_state.flags_op1 = a; - cpu_state.flags_op2 = b; - cpu_state.flags_res = (a - (b + tempc)) & 0xffff; - cpu_state.flags_op = FLAGS_SBC16; + cpu_state.flags_op1 = a; + cpu_state.flags_op2 = b; + cpu_state.flags_res = (a - (b + tempc)) & 0xffff; + cpu_state.flags_op = FLAGS_SBC16; } -static __inline void setsbc32(uint32_t a, uint32_t b) +static __inline void +setsbc32(uint32_t a, uint32_t b) { - cpu_state.flags_op1 = a; - cpu_state.flags_op2 = b; - cpu_state.flags_res = a - (b + tempc); - cpu_state.flags_op = FLAGS_SBC32; + cpu_state.flags_op1 = a; + cpu_state.flags_op2 = b; + cpu_state.flags_res = a - (b + tempc); + cpu_state.flags_op = FLAGS_SBC32; } #else -static __inline void setadc8(uint8_t a, uint8_t b) +static __inline void +setadc8(uint8_t a, uint8_t b) { - uint16_t c=(uint16_t)a+(uint16_t)b+tempc; - cpu_state.flags_op = FLAGS_UNKNOWN; - cpu_state.flags&=~0x8D5; - cpu_state.flags|=znptable8[c&0xFF]; - if (c&0x100) cpu_state.flags|=C_FLAG; - if (!((a^b)&0x80)&&((a^c)&0x80)) cpu_state.flags|=V_FLAG; - if (((a&0xF)+(b&0xF))&0x10) cpu_state.flags|=A_FLAG; + uint16_t c = (uint16_t) a + (uint16_t) b + tempc; + cpu_state.flags_op = FLAGS_UNKNOWN; + cpu_state.flags &= ~0x8D5; + cpu_state.flags |= znptable8[c & 0xFF]; + if (c & 0x100) + cpu_state.flags |= C_FLAG; + if (!((a ^ b) & 0x80) && ((a ^ c) & 0x80)) + cpu_state.flags |= V_FLAG; + if (((a & 0xF) + (b & 0xF)) & 0x10) + cpu_state.flags |= A_FLAG; } -static __inline void setadc16(uint16_t a, uint16_t b) +static __inline void +setadc16(uint16_t a, uint16_t b) { - uint32_t c=(uint32_t)a+(uint32_t)b+tempc; - cpu_state.flags_op = FLAGS_UNKNOWN; - cpu_state.flags&=~0x8D5; - cpu_state.flags|=znptable16[c&0xFFFF]; - if (c&0x10000) cpu_state.flags|=C_FLAG; - if (!((a^b)&0x8000)&&((a^c)&0x8000)) cpu_state.flags|=V_FLAG; - if (((a&0xF)+(b&0xF))&0x10) cpu_state.flags|=A_FLAG; + uint32_t c = (uint32_t) a + (uint32_t) b + tempc; + cpu_state.flags_op = FLAGS_UNKNOWN; + cpu_state.flags &= ~0x8D5; + cpu_state.flags |= znptable16[c & 0xFFFF]; + if (c & 0x10000) + cpu_state.flags |= C_FLAG; + if (!((a ^ b) & 0x8000) && ((a ^ c) & 0x8000)) + cpu_state.flags |= V_FLAG; + if (((a & 0xF) + (b & 0xF)) & 0x10) + cpu_state.flags |= A_FLAG; } -static __inline void setadc32(uint32_t a, uint32_t b) +static __inline void +setadc32(uint32_t a, uint32_t b) { - uint32_t c=(uint32_t)a+(uint32_t)b+tempc; - cpu_state.flags_op = FLAGS_UNKNOWN; - cpu_state.flags&=~0x8D5; - cpu_state.flags|=((c&0x80000000)?N_FLAG:((!c)?Z_FLAG:0)); - cpu_state.flags|=(znptable8[c&0xFF]&P_FLAG); - if ((ca) || (c==a && tempc)) cpu_state.flags|=C_FLAG; - if ((a^b)&(a^c)&0x80000000) cpu_state.flags|=V_FLAG; - if (((a&0xF)-((b&0xF)+tempc))&0x10) cpu_state.flags|=A_FLAG; + uint32_t c = (uint32_t) a - (((uint32_t) b) + tempc); + cpu_state.flags_op = FLAGS_UNKNOWN; + cpu_state.flags &= ~0x8D5; + cpu_state.flags |= ((c & 0x80000000) ? N_FLAG : ((!c) ? Z_FLAG : 0)); + cpu_state.flags |= (znptable8[c & 0xFF] & P_FLAG); + if ((c > a) || (c == a && tempc)) + cpu_state.flags |= C_FLAG; + if ((a ^ b) & (a ^ c) & 0x80000000) + cpu_state.flags |= V_FLAG; + if (((a & 0xF) - ((b & 0xF) + tempc)) & 0x10) + cpu_state.flags |= A_FLAG; } #endif -extern void cpu_386_flags_extract(); -extern void cpu_386_flags_rebuild(); +extern void cpu_386_flags_extract(void); +extern void cpu_386_flags_rebuild(void); diff --git a/src/cpu/x86_ops.h b/src/cpu/x86_ops.h index 2c8812570..6fb9b7a22 100644 --- a/src/cpu/x86_ops.h +++ b/src/cpu/x86_ops.h @@ -1,22 +1,22 @@ /* - * VARCem Virtual ARchaeological Computer EMulator. - * An emulator of (mostly) x86-based PC systems and devices, - * using the ISA,EISA,VLB,MCA and PCI system buses, roughly - * spanning the era between 1981 and 1995. + * 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 VARCem Project. + * This file is part of the 86Box distribution. * - * Miscellaneous x86 CPU Instructions. + * Miscellaneous x86 CPU Instructions. * * * - * Authors: Fred N. van Kempen, - * Sarah Walker, - * Miran Grca, + * Authors: Fred N. van Kempen, + * Sarah Walker, + * Miran Grca, * - * Copyright 2018 Fred N. van Kempen. - * Copyright 2008-2018 Sarah Walker. - * Copyright 2016-2018 Miran Grca. + * Copyright 2018 Fred N. van Kempen. + * Copyright 2008-2018 Sarah Walker. + * Copyright 2016-2018 Miran Grca. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -39,16 +39,14 @@ #ifndef _X86_OPS_H #define _X86_OPS_H - -#define UN_USED(x) (void)(x) - +#define UN_USED(x) (void) (x) typedef int (*OpFn)(uint32_t fetchdat); #ifdef USE_DYNAREC -void x86_setopcodes(const OpFn *opcodes, const OpFn *opcodes_0f, - const OpFn *dynarec_opcodes, - const OpFn *dynarec_opcodes_0f); +extern void x86_setopcodes(const OpFn *opcodes, const OpFn *opcodes_0f, + const OpFn *dynarec_opcodes, + const OpFn *dynarec_opcodes_0f); extern const OpFn *x86_dynarec_opcodes; extern const OpFn *x86_dynarec_opcodes_0f; @@ -72,6 +70,9 @@ extern const OpFn *x86_dynarec_opcodes_REPE; extern const OpFn *x86_dynarec_opcodes_REPNE; extern const OpFn *x86_dynarec_opcodes_3DNOW; +extern const OpFn dynarec_ops_186[1024]; +extern const OpFn dynarec_ops_186_0f[1024]; + extern const OpFn dynarec_ops_286[1024]; extern const OpFn dynarec_ops_286_0f[1024]; @@ -89,10 +90,10 @@ extern const OpFn dynarec_ops_winchip2_0f[1024]; extern const OpFn dynarec_ops_pentium_0f[1024]; extern const OpFn dynarec_ops_pentiummmx_0f[1024]; -#if defined(DEV_BRANCH) && defined(USE_CYRIX_6X86) +# if defined(DEV_BRANCH) && defined(USE_CYRIX_6X86) extern const OpFn dynarec_ops_c6x86_0f[1024]; extern const OpFn dynarec_ops_c6x86mx_0f[1024]; -#endif +# endif extern const OpFn dynarec_ops_k6_0f[1024]; extern const OpFn dynarec_ops_k62_0f[1024]; @@ -101,6 +102,38 @@ extern const OpFn dynarec_ops_pentiumpro_0f[1024]; extern const OpFn dynarec_ops_pentium2_0f[1024]; extern const OpFn dynarec_ops_pentium2d_0f[1024]; +extern const OpFn dynarec_ops_sf_fpu_287_d9_a16[256]; +extern const OpFn dynarec_ops_sf_fpu_287_d9_a32[256]; +extern const OpFn dynarec_ops_sf_fpu_287_da_a16[256]; +extern const OpFn dynarec_ops_sf_fpu_287_da_a32[256]; +extern const OpFn dynarec_ops_sf_fpu_287_db_a16[256]; +extern const OpFn dynarec_ops_sf_fpu_287_db_a32[256]; +extern const OpFn dynarec_ops_sf_fpu_287_dc_a16[32]; +extern const OpFn dynarec_ops_sf_fpu_287_dc_a32[32]; +extern const OpFn dynarec_ops_sf_fpu_287_dd_a16[256]; +extern const OpFn dynarec_ops_sf_fpu_287_dd_a32[256]; +extern const OpFn dynarec_ops_sf_fpu_287_de_a16[256]; +extern const OpFn dynarec_ops_sf_fpu_287_de_a32[256]; +extern const OpFn dynarec_ops_sf_fpu_287_df_a16[256]; +extern const OpFn dynarec_ops_sf_fpu_287_df_a32[256]; + +extern const OpFn dynarec_ops_sf_fpu_d8_a16[32]; +extern const OpFn dynarec_ops_sf_fpu_d8_a32[32]; +extern const OpFn dynarec_ops_sf_fpu_d9_a16[256]; +extern const OpFn dynarec_ops_sf_fpu_d9_a32[256]; +extern const OpFn dynarec_ops_sf_fpu_da_a16[256]; +extern const OpFn dynarec_ops_sf_fpu_da_a32[256]; +extern const OpFn dynarec_ops_sf_fpu_db_a16[256]; +extern const OpFn dynarec_ops_sf_fpu_db_a32[256]; +extern const OpFn dynarec_ops_sf_fpu_dc_a16[32]; +extern const OpFn dynarec_ops_sf_fpu_dc_a32[32]; +extern const OpFn dynarec_ops_sf_fpu_dd_a16[256]; +extern const OpFn dynarec_ops_sf_fpu_dd_a32[256]; +extern const OpFn dynarec_ops_sf_fpu_de_a16[256]; +extern const OpFn dynarec_ops_sf_fpu_de_a32[256]; +extern const OpFn dynarec_ops_sf_fpu_df_a16[256]; +extern const OpFn dynarec_ops_sf_fpu_df_a32[256]; + extern const OpFn dynarec_ops_fpu_287_d9_a16[256]; extern const OpFn dynarec_ops_fpu_287_d9_a32[256]; extern const OpFn dynarec_ops_fpu_287_da_a16[256]; @@ -135,6 +168,13 @@ extern const OpFn dynarec_ops_fpu_df_a32[256]; extern const OpFn dynarec_ops_nofpu_a16[256]; extern const OpFn dynarec_ops_nofpu_a32[256]; +extern const OpFn dynarec_ops_sf_fpu_686_da_a16[256]; +extern const OpFn dynarec_ops_sf_fpu_686_da_a32[256]; +extern const OpFn dynarec_ops_sf_fpu_686_db_a16[256]; +extern const OpFn dynarec_ops_sf_fpu_686_db_a32[256]; +extern const OpFn dynarec_ops_sf_fpu_686_df_a16[256]; +extern const OpFn dynarec_ops_sf_fpu_686_df_a32[256]; + extern const OpFn dynarec_ops_fpu_686_da_a16[256]; extern const OpFn dynarec_ops_fpu_686_da_a32[256]; extern const OpFn dynarec_ops_fpu_686_db_a16[256]; @@ -145,8 +185,9 @@ extern const OpFn dynarec_ops_fpu_686_df_a32[256]; extern const OpFn dynarec_ops_REPE[1024]; extern const OpFn dynarec_ops_REPNE[1024]; extern const OpFn dynarec_ops_3DNOW[256]; +extern const OpFn dynarec_ops_3DNOWE[256]; #else -void x86_setopcodes(const OpFn *opcodes, const OpFn *opcodes_0f); +extern void x86_setopcodes(const OpFn *opcodes, const OpFn *opcodes_0f); #endif extern const OpFn *x86_opcodes; @@ -171,6 +212,9 @@ extern const OpFn *x86_opcodes_REPE; extern const OpFn *x86_opcodes_REPNE; extern const OpFn *x86_opcodes_3DNOW; +extern const OpFn ops_186[1024]; +extern const OpFn ops_186_0f[1024]; + extern const OpFn ops_286[1024]; extern const OpFn ops_286_0f[1024]; @@ -200,6 +244,38 @@ extern const OpFn ops_pentiumpro_0f[1024]; extern const OpFn ops_pentium2_0f[1024]; extern const OpFn ops_pentium2d_0f[1024]; +extern const OpFn ops_sf_fpu_287_d9_a16[256]; +extern const OpFn ops_sf_fpu_287_d9_a32[256]; +extern const OpFn ops_sf_fpu_287_da_a16[256]; +extern const OpFn ops_sf_fpu_287_da_a32[256]; +extern const OpFn ops_sf_fpu_287_db_a16[256]; +extern const OpFn ops_sf_fpu_287_db_a32[256]; +extern const OpFn ops_sf_fpu_287_dc_a16[32]; +extern const OpFn ops_sf_fpu_287_dc_a32[32]; +extern const OpFn ops_sf_fpu_287_dd_a16[256]; +extern const OpFn ops_sf_fpu_287_dd_a32[256]; +extern const OpFn ops_sf_fpu_287_de_a16[256]; +extern const OpFn ops_sf_fpu_287_de_a32[256]; +extern const OpFn ops_sf_fpu_287_df_a16[256]; +extern const OpFn ops_sf_fpu_287_df_a32[256]; + +extern const OpFn ops_sf_fpu_d8_a16[32]; +extern const OpFn ops_sf_fpu_d8_a32[32]; +extern const OpFn ops_sf_fpu_d9_a16[256]; +extern const OpFn ops_sf_fpu_d9_a32[256]; +extern const OpFn ops_sf_fpu_da_a16[256]; +extern const OpFn ops_sf_fpu_da_a32[256]; +extern const OpFn ops_sf_fpu_db_a16[256]; +extern const OpFn ops_sf_fpu_db_a32[256]; +extern const OpFn ops_sf_fpu_dc_a16[32]; +extern const OpFn ops_sf_fpu_dc_a32[32]; +extern const OpFn ops_sf_fpu_dd_a16[256]; +extern const OpFn ops_sf_fpu_dd_a32[256]; +extern const OpFn ops_sf_fpu_de_a16[256]; +extern const OpFn ops_sf_fpu_de_a32[256]; +extern const OpFn ops_sf_fpu_df_a16[256]; +extern const OpFn ops_sf_fpu_df_a32[256]; + extern const OpFn ops_fpu_287_d9_a16[256]; extern const OpFn ops_fpu_287_d9_a32[256]; extern const OpFn ops_fpu_287_da_a16[256]; @@ -234,6 +310,13 @@ extern const OpFn ops_fpu_df_a32[256]; extern const OpFn ops_nofpu_a16[256]; extern const OpFn ops_nofpu_a32[256]; +extern const OpFn ops_sf_fpu_686_da_a16[256]; +extern const OpFn ops_sf_fpu_686_da_a32[256]; +extern const OpFn ops_sf_fpu_686_db_a16[256]; +extern const OpFn ops_sf_fpu_686_db_a32[256]; +extern const OpFn ops_sf_fpu_686_df_a16[256]; +extern const OpFn ops_sf_fpu_686_df_a32[256]; + extern const OpFn ops_fpu_686_da_a16[256]; extern const OpFn ops_fpu_686_da_a32[256]; extern const OpFn ops_fpu_686_db_a16[256]; @@ -244,10 +327,116 @@ extern const OpFn ops_fpu_686_df_a32[256]; extern const OpFn ops_REPE[1024]; extern const OpFn ops_REPNE[1024]; extern const OpFn ops_3DNOW[256]; +extern const OpFn ops_3DNOWE[256]; -#define C0 (1<<8) -#define C1 (1<<9) -#define C2 (1<<10) -#define C3 (1<<14) +extern void x86_setopcodes_2386(const OpFn *opcodes, const OpFn *opcodes_0f); + +extern const OpFn *x86_2386_opcodes; +extern const OpFn *x86_2386_opcodes_0f; +extern const OpFn *x86_2386_opcodes_d8_a16; +extern const OpFn *x86_2386_opcodes_d8_a32; +extern const OpFn *x86_2386_opcodes_d9_a16; +extern const OpFn *x86_2386_opcodes_d9_a32; +extern const OpFn *x86_2386_opcodes_da_a16; +extern const OpFn *x86_2386_opcodes_da_a32; +extern const OpFn *x86_2386_opcodes_db_a16; +extern const OpFn *x86_2386_opcodes_db_a32; +extern const OpFn *x86_2386_opcodes_dc_a16; +extern const OpFn *x86_2386_opcodes_dc_a32; +extern const OpFn *x86_2386_opcodes_dd_a16; +extern const OpFn *x86_2386_opcodes_dd_a32; +extern const OpFn *x86_2386_opcodes_de_a16; +extern const OpFn *x86_2386_opcodes_de_a32; +extern const OpFn *x86_2386_opcodes_df_a16; +extern const OpFn *x86_2386_opcodes_df_a32; +extern const OpFn *x86_2386_opcodes_REPE; +extern const OpFn *x86_2386_opcodes_REPNE; + +extern const OpFn ops_2386_186[1024]; +extern const OpFn ops_2386_186_0f[1024]; + +extern const OpFn ops_2386_286[1024]; +extern const OpFn ops_2386_286_0f[1024]; + +extern const OpFn ops_2386_386[1024]; +extern const OpFn ops_2386_386_0f[1024]; + +extern const OpFn ops_2386_486_0f[1024]; +extern const OpFn ops_2386_ibm486_0f[1024]; + +extern const OpFn ops_2386_sf_fpu_287_d9_a16[256]; +extern const OpFn ops_2386_sf_fpu_287_d9_a32[256]; +extern const OpFn ops_2386_sf_fpu_287_da_a16[256]; +extern const OpFn ops_2386_sf_fpu_287_da_a32[256]; +extern const OpFn ops_2386_sf_fpu_287_db_a16[256]; +extern const OpFn ops_2386_sf_fpu_287_db_a32[256]; +extern const OpFn ops_2386_sf_fpu_287_dc_a16[32]; +extern const OpFn ops_2386_sf_fpu_287_dc_a32[32]; +extern const OpFn ops_2386_sf_fpu_287_dd_a16[256]; +extern const OpFn ops_2386_sf_fpu_287_dd_a32[256]; +extern const OpFn ops_2386_sf_fpu_287_de_a16[256]; +extern const OpFn ops_2386_sf_fpu_287_de_a32[256]; +extern const OpFn ops_2386_sf_fpu_287_df_a16[256]; +extern const OpFn ops_2386_sf_fpu_287_df_a32[256]; + +extern const OpFn ops_2386_sf_fpu_d8_a16[32]; +extern const OpFn ops_2386_sf_fpu_d8_a32[32]; +extern const OpFn ops_2386_sf_fpu_d9_a16[256]; +extern const OpFn ops_2386_sf_fpu_d9_a32[256]; +extern const OpFn ops_2386_sf_fpu_da_a16[256]; +extern const OpFn ops_2386_sf_fpu_da_a32[256]; +extern const OpFn ops_2386_sf_fpu_db_a16[256]; +extern const OpFn ops_2386_sf_fpu_db_a32[256]; +extern const OpFn ops_2386_sf_fpu_dc_a16[32]; +extern const OpFn ops_2386_sf_fpu_dc_a32[32]; +extern const OpFn ops_2386_sf_fpu_dd_a16[256]; +extern const OpFn ops_2386_sf_fpu_dd_a32[256]; +extern const OpFn ops_2386_sf_fpu_de_a16[256]; +extern const OpFn ops_2386_sf_fpu_de_a32[256]; +extern const OpFn ops_2386_sf_fpu_df_a16[256]; +extern const OpFn ops_2386_sf_fpu_df_a32[256]; + +extern const OpFn ops_2386_fpu_287_d9_a16[256]; +extern const OpFn ops_2386_fpu_287_d9_a32[256]; +extern const OpFn ops_2386_fpu_287_da_a16[256]; +extern const OpFn ops_2386_fpu_287_da_a32[256]; +extern const OpFn ops_2386_fpu_287_db_a16[256]; +extern const OpFn ops_2386_fpu_287_db_a32[256]; +extern const OpFn ops_2386_fpu_287_dc_a16[32]; +extern const OpFn ops_2386_fpu_287_dc_a32[32]; +extern const OpFn ops_2386_fpu_287_dd_a16[256]; +extern const OpFn ops_2386_fpu_287_dd_a32[256]; +extern const OpFn ops_2386_fpu_287_de_a16[256]; +extern const OpFn ops_2386_fpu_287_de_a32[256]; +extern const OpFn ops_2386_fpu_287_df_a16[256]; +extern const OpFn ops_2386_fpu_287_df_a32[256]; + +extern const OpFn ops_2386_fpu_d8_a16[32]; +extern const OpFn ops_2386_fpu_d8_a32[32]; +extern const OpFn ops_2386_fpu_d9_a16[256]; +extern const OpFn ops_2386_fpu_d9_a32[256]; +extern const OpFn ops_2386_fpu_da_a16[256]; +extern const OpFn ops_2386_fpu_da_a32[256]; +extern const OpFn ops_2386_fpu_db_a16[256]; +extern const OpFn ops_2386_fpu_db_a32[256]; +extern const OpFn ops_2386_fpu_dc_a16[32]; +extern const OpFn ops_2386_fpu_dc_a32[32]; +extern const OpFn ops_2386_fpu_dd_a16[256]; +extern const OpFn ops_2386_fpu_dd_a32[256]; +extern const OpFn ops_2386_fpu_de_a16[256]; +extern const OpFn ops_2386_fpu_de_a32[256]; +extern const OpFn ops_2386_fpu_df_a16[256]; +extern const OpFn ops_2386_fpu_df_a32[256]; +extern const OpFn ops_2386_nofpu_a16[256]; +extern const OpFn ops_2386_nofpu_a32[256]; + +extern const OpFn ops_2386_REPE[1024]; +extern const OpFn ops_2386_REPNE[1024]; +extern const OpFn ops_2386_3DNOW[256]; + +#define C0 (1 << 8) +#define C1 (1 << 9) +#define C2 (1 << 10) +#define C3 (1 << 14) #endif /*_X86_OPS_H*/ diff --git a/src/cpu/x86_ops_3dnow.h b/src/cpu/x86_ops_3dnow.h index c578c400a..b72cbc06c 100644 --- a/src/cpu/x86_ops_3dnow.h +++ b/src/cpu/x86_ops_3dnow.h @@ -1,301 +1,460 @@ #include -static int opPREFETCH_a16(uint32_t fetchdat) +static int +opPREFETCH_a16(uint32_t fetchdat) { - fetch_ea_16(fetchdat); - ILLEGAL_ON(cpu_mod == 3); + fetch_ea_16(fetchdat); + ILLEGAL_ON(cpu_mod == 3); + CLOCK_CYCLES(1); + return 0; +} +static int +opPREFETCH_a32(uint32_t fetchdat) +{ + fetch_ea_32(fetchdat); + ILLEGAL_ON(cpu_mod == 3); + + CLOCK_CYCLES(1); + return 0; +} + +static int +opFEMMS(uint32_t fetchdat) +{ + ILLEGAL_ON(!cpu_has_feature(CPU_FEATURE_MMX)); + if (cr0 & 0xc) { + x86_int(7); + return 1; + } + x87_emms(); + CLOCK_CYCLES(1); + return 0; +} + +static int +opPAVGUSB(uint32_t fetchdat) +{ + MMX_REG src; + MMX_REG *dst = MMX_GETREGP(cpu_reg); + + MMX_GETSRC(); + + 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; +} +static int +opPF2ID(uint32_t fetchdat) +{ + MMX_REG src; + MMX_REG *dst = MMX_GETREGP(cpu_reg); + + MMX_GETSRC(); + + dst->sl[0] = (int32_t) src.f[0]; + dst->sl[1] = (int32_t) src.f[1]; + + MMX_SETEXP(cpu_reg); + + return 0; +} +static int +opPF2IW(uint32_t fetchdat) +{ + MMX_REG src; + MMX_REG *dst = MMX_GETREGP(cpu_reg); + + MMX_GETSRC(); + + dst->sw[0] = (int32_t) src.f[0]; + dst->sw[1] = (int32_t) src.f[1]; + + MMX_SETEXP(cpu_reg); + + return 0; +} +static int +opPFACC(uint32_t fetchdat) +{ + MMX_REG src; + MMX_REG *dst = MMX_GETREGP(cpu_reg); + float tempf; + + MMX_GETSRC(); + + 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; +} +static int +opPFNACC(uint32_t fetchdat) +{ + MMX_REG src; + MMX_REG *dst = MMX_GETREGP(cpu_reg); + float tempf; + + MMX_GETSRC(); + + 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; +} +static int +opPFPNACC(uint32_t fetchdat) +{ + MMX_REG src; + MMX_REG *dst = MMX_GETREGP(cpu_reg); + float tempf; + + MMX_GETSRC(); + + 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; +} +static int +opPSWAPD(uint32_t fetchdat) +{ + MMX_REG src; + MMX_REG *dst = MMX_GETREGP(cpu_reg); + float tempf; + float tempf2; + + MMX_GETSRC(); + + /* We have to do this in case source and destination overlap. */ + tempf = src.f[0]; + tempf2 = src.f[1]; + dst->f[1] = tempf; + dst->f[0] = tempf2; + + MMX_SETEXP(cpu_reg); + + return 0; +} +static int +opPFADD(uint32_t fetchdat) +{ + MMX_REG src; + MMX_REG *dst = MMX_GETREGP(cpu_reg); + + MMX_GETSRC(); + + dst->f[0] += src.f[0]; + dst->f[1] += src.f[1]; + + MMX_SETEXP(cpu_reg); + + return 0; +} +static int +opPFCMPEQ(uint32_t fetchdat) +{ + MMX_REG src; + MMX_REG *dst = MMX_GETREGP(cpu_reg); + + MMX_GETSRC(); + + 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; +} +static int +opPFCMPGE(uint32_t fetchdat) +{ + MMX_REG src; + MMX_REG *dst = MMX_GETREGP(cpu_reg); + + MMX_GETSRC(); + + 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; +} +static int +opPFCMPGT(uint32_t fetchdat) +{ + MMX_REG src; + MMX_REG *dst = MMX_GETREGP(cpu_reg); + + MMX_GETSRC(); + + 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; +} +static int +opPFMAX(uint32_t fetchdat) +{ + MMX_REG src; + MMX_REG *dst = MMX_GETREGP(cpu_reg); + + MMX_GETSRC(); + + 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; +} +static int +opPFMIN(uint32_t fetchdat) +{ + MMX_REG src; + MMX_REG *dst = MMX_GETREGP(cpu_reg); + + MMX_GETSRC(); + + 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; +} +static int +opPFMUL(uint32_t fetchdat) +{ + MMX_REG src; + MMX_REG *dst = MMX_GETREGP(cpu_reg); + + MMX_GETSRC(); + + 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 = (MMX_GETREG(cpu_rm)).f[0]; CLOCK_CYCLES(1); - return 0; -} -static int opPREFETCH_a32(uint32_t fetchdat) -{ - fetch_ea_32(fetchdat); - ILLEGAL_ON(cpu_mod == 3); + } else { + SEG_CHECK_READ(cpu_state.ea_seg); + src.i = readmeml(easeg, cpu_state.eaaddr); + if (cpu_state.abrt) + return 1; + CLOCK_CYCLES(2); + } - CLOCK_CYCLES(1); - return 0; -} + dst->f[0] = 1.0 / src.f; + dst->f[1] = dst->f[0]; -static int opFEMMS(uint32_t fetchdat) -{ - ILLEGAL_ON(!cpu_has_feature(CPU_FEATURE_MMX)); - if (cr0 & 0xc) - { - x86_int(7); - return 1; - } - x87_emms(); - CLOCK_CYCLES(1); - return 0; -} + MMX_SETEXP(cpu_reg); -static int opPAVGUSB(uint32_t fetchdat) -{ - MMX_REG src; - - 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; - - return 0; -} -static int opPF2ID(uint32_t fetchdat) -{ - MMX_REG src; - - 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]; - - return 0; -} -static int opPFACC(uint32_t fetchdat) -{ - MMX_REG src; - 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; - - return 0; -} -static int opPFADD(uint32_t fetchdat) -{ - MMX_REG src; - - MMX_GETSRC(); - - cpu_state.MM[cpu_reg].f[0] += src.f[0]; - cpu_state.MM[cpu_reg].f[1] += src.f[1]; - - return 0; -} -static int opPFCMPEQ(uint32_t fetchdat) -{ - MMX_REG src; - - 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; - - return 0; -} -static int opPFCMPGE(uint32_t fetchdat) -{ - MMX_REG src; - - 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; - - return 0; -} -static int opPFCMPGT(uint32_t fetchdat) -{ - MMX_REG src; - - 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; - - return 0; -} -static int opPFMAX(uint32_t fetchdat) -{ - MMX_REG src; - - 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]; - - return 0; -} -static int opPFMIN(uint32_t fetchdat) -{ - MMX_REG src; - - 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]; - - return 0; -} -static int opPFMUL(uint32_t fetchdat) -{ - MMX_REG src; - - MMX_GETSRC(); - - cpu_state.MM[cpu_reg].f[0] *= src.f[0]; - cpu_state.MM[cpu_reg].f[1] *= src.f[1]; - - return 0; -} -static int opPFRCP(uint32_t fetchdat) -{ - union - { - uint32_t i; - float f; - } src; - - if (cpu_mod == 3) - { - src.f = cpu_state.MM[cpu_rm].f[0]; - CLOCK_CYCLES(1); - } - else - { - SEG_CHECK_READ(cpu_state.ea_seg); - src.i = readmeml(easeg, cpu_state.eaaddr); if (cpu_state.abrt) return 1; - 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]; - - return 0; + return 0; } /*Since opPFRCP() calculates a full precision reciprocal, treat the followup iterations as MOVs*/ -static int opPFRCPIT1(uint32_t fetchdat) +static int +opPFRCPIT1(uint32_t fetchdat) { - MMX_REG src; + MMX_REG src; + MMX_REG *dst = MMX_GETREGP(cpu_reg); - MMX_GETSRC(); + 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]; - return 0; + MMX_SETEXP(cpu_reg); + + return 0; } -static int opPFRCPIT2(uint32_t fetchdat) +static int +opPFRCPIT2(uint32_t fetchdat) { - MMX_REG src; + MMX_REG src; + MMX_REG *dst = MMX_GETREGP(cpu_reg); - MMX_GETSRC(); + 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]; - return 0; + MMX_SETEXP(cpu_reg); + + return 0; } -static int opPFRSQRT(uint32_t fetchdat) +static int +opPFRSQRT(uint32_t fetchdat) { - union - { - uint32_t i; - float f; - } src; + MMX_REG *dst = MMX_GETREGP(cpu_reg); - if (cpu_mod == 3) - { - src.f = cpu_state.MM[cpu_rm].f[0]; - CLOCK_CYCLES(1); - } - else - { - SEG_CHECK_READ(cpu_state.ea_seg); - src.i = readmeml(easeg, cpu_state.eaaddr); if (cpu_state.abrt) return 1; - CLOCK_CYCLES(2); - } + union { + uint32_t i; + float f; + } src; - 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]; + if (cpu_mod == 3) { + src.f = (MMX_GETREG(cpu_rm)).f[0]; + CLOCK_CYCLES(1); + } else { + SEG_CHECK_READ(cpu_state.ea_seg); + src.i = readmeml(easeg, cpu_state.eaaddr); + if (cpu_state.abrt) + return 1; + CLOCK_CYCLES(2); + } - return 0; + dst->f[0] = 1.0 / sqrt(src.f); + dst->f[1] = dst->f[0]; + + MMX_SETEXP(cpu_reg); + + return 0; } /*Since opPFRSQRT() calculates a full precision inverse square root, treat the followup iteration as a NOP*/ -static int opPFRSQIT1(uint32_t fetchdat) +static int +opPFRSQIT1(uint32_t fetchdat) { - MMX_REG src; + MMX_REG src; - MMX_GETSRC(); - UN_USED(src); + MMX_GETSRC(); + UN_USED(src); - return 0; + return 0; } -static int opPFSUB(uint32_t fetchdat) +static int +opPFSUB(uint32_t fetchdat) { - MMX_REG src; + MMX_REG src; + MMX_REG *dst = MMX_GETREGP(cpu_reg); - MMX_GETSRC(); + 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]; - return 0; + MMX_SETEXP(cpu_reg); + + return 0; } -static int opPFSUBR(uint32_t fetchdat) +static int +opPFSUBR(uint32_t fetchdat) { - MMX_REG src; + MMX_REG src; + MMX_REG *dst = MMX_GETREGP(cpu_reg); - MMX_GETSRC(); + 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]; - return 0; + MMX_SETEXP(cpu_reg); + + return 0; } -static int opPI2FD(uint32_t fetchdat) +static int +opPI2FD(uint32_t fetchdat) { - MMX_REG src; + MMX_REG src; + MMX_REG *dst = MMX_GETREGP(cpu_reg); - MMX_GETSRC(); + 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]; - return 0; + MMX_SETEXP(cpu_reg); + + return 0; } -static int opPMULHRW(uint32_t fetchdat) +static int +opPI2FW(uint32_t 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]) + 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; - CLOCK_CYCLES(1); - } - else - { - MMX_REG src; + MMX_REG src; + MMX_REG *dst = MMX_GETREGP(cpu_reg); - 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; - CLOCK_CYCLES(2); - } - return 0; + MMX_GETSRC(); + + 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) { + 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 { + 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; + 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; } -const OpFn OP_TABLE(3DNOW)[256] = -{ +const OpFn OP_TABLE(3DNOW)[256] = { + // clang-format off /* 00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f*/ /*00*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, opPI2FD, ILLEGAL, ILLEGAL, /*10*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, opPF2ID, ILLEGAL, ILLEGAL, @@ -316,31 +475,61 @@ const OpFn OP_TABLE(3DNOW)[256] = /*d0*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, /*e0*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, /*f0*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, + // clang-format on }; -static int op3DNOW_a16(uint32_t fetchdat) +const OpFn OP_TABLE(3DNOWE)[256] = { + // clang-format off +/* 00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f*/ +/*00*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, opPI2FW, opPI2FD, ILLEGAL, ILLEGAL, +/*10*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, opPF2IW, opPF2ID, ILLEGAL, ILLEGAL, +/*20*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, +/*30*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, + +/*40*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, +/*50*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, +/*60*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, +/*70*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, + +/*80*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, opPFNACC, ILLEGAL, ILLEGAL, ILLEGAL, opPFPNACC, ILLEGAL, +/*90*/ opPFCMPGE, ILLEGAL, ILLEGAL, ILLEGAL, opPFMIN, ILLEGAL, opPFRCP, opPFRSQRT, ILLEGAL, ILLEGAL, opPFSUB, ILLEGAL, ILLEGAL, ILLEGAL, opPFADD, ILLEGAL, +/*a0*/ opPFCMPGT, ILLEGAL, ILLEGAL, ILLEGAL, opPFMAX, ILLEGAL, opPFRCPIT1, opPFRSQIT1, ILLEGAL, ILLEGAL, opPFSUBR, ILLEGAL, ILLEGAL, ILLEGAL, opPFACC, ILLEGAL, +/*b0*/ opPFCMPEQ, ILLEGAL, ILLEGAL, ILLEGAL, opPFMUL, ILLEGAL, opPFRCPIT2, opPMULHRW, ILLEGAL, ILLEGAL, ILLEGAL, opPSWAPD, ILLEGAL, ILLEGAL, ILLEGAL, opPAVGUSB, + +/*c0*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, +/*d0*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, +/*e0*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, +/*f0*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, + // clang-format on +}; + +static int +op3DNOW_a16(uint32_t fetchdat) { - uint8_t opcode; + uint8_t opcode; - MMX_ENTER(); + MMX_ENTER(); - fetch_ea_16(fetchdat); - opcode = fastreadb(cs + cpu_state.pc); - if (cpu_state.abrt) return 1; - cpu_state.pc++; + fetch_ea_16(fetchdat); + opcode = fastreadb(cs + cpu_state.pc); + if (cpu_state.abrt) + return 1; + cpu_state.pc++; - return x86_opcodes_3DNOW[opcode](0); + return x86_opcodes_3DNOW[opcode](0); } -static int op3DNOW_a32(uint32_t fetchdat) +static int +op3DNOW_a32(uint32_t fetchdat) { - uint8_t opcode; - - MMX_ENTER(); + uint8_t opcode; - fetch_ea_32(fetchdat); - opcode = fastreadb(cs + cpu_state.pc); - if (cpu_state.abrt) return 1; - cpu_state.pc++; - - return x86_opcodes_3DNOW[opcode](0); + MMX_ENTER(); + + fetch_ea_32(fetchdat); + opcode = fastreadb(cs + cpu_state.pc); + if (cpu_state.abrt) + return 1; + cpu_state.pc++; + + return x86_opcodes_3DNOW[opcode](0); } diff --git a/src/cpu/x86_ops_amd.h b/src/cpu/x86_ops_amd.h index a378b9fe9..9e6bcce55 100644 --- a/src/cpu/x86_ops_amd.h +++ b/src/cpu/x86_ops_amd.h @@ -1,17 +1,17 @@ /* - * 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. + * 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. + * This file is part of the 86Box distribution. * - * AMD SYSCALL and SYSRET CPU Instructions. + * AMD SYSCALL and SYSRET CPU Instructions. * * * - * Author: Miran Grca, - * Copyright 2016-2018 Miran Grca. + * Authors: Miran Grca, + * Copyright 2016-2018 Miran Grca. */ static int opSYSCALL(uint32_t fetchdat) @@ -23,16 +23,15 @@ opSYSCALL(uint32_t fetchdat) ret = syscall_op(fetchdat); if (ret <= 1) { - CLOCK_CYCLES(20); - PREFETCH_RUN(20, 7, -1, 0,0,0,0, 0); - PREFETCH_FLUSH(); - CPU_BLOCK_END(); + CLOCK_CYCLES(20); + PREFETCH_RUN(20, 7, -1, 0, 0, 0, 0, 0); + PREFETCH_FLUSH(); + CPU_BLOCK_END(); } return ret; } - static int opSYSRET(uint32_t fetchdat) { @@ -43,10 +42,10 @@ opSYSRET(uint32_t fetchdat) ret = sysret(fetchdat); if (ret <= 1) { - CLOCK_CYCLES(20); - PREFETCH_RUN(20, 7, -1, 0,0,0,0, 0); - PREFETCH_FLUSH(); - CPU_BLOCK_END(); + CLOCK_CYCLES(20); + PREFETCH_RUN(20, 7, -1, 0, 0, 0, 0, 0); + PREFETCH_FLUSH(); + CPU_BLOCK_END(); } return ret; diff --git a/src/cpu/x86_ops_arith.h b/src/cpu/x86_ops_arith.h index d837d3a64..4e3f74e36 100644 --- a/src/cpu/x86_ops_arith.h +++ b/src/cpu/x86_ops_arith.h @@ -1,828 +1,1049 @@ -#define OP_ARITH(name, operation, setflags, flagops, gettempc) \ - static int op ## name ## _b_rmw_a16(uint32_t fetchdat) \ - { \ - uint8_t dst; \ - uint8_t src; \ - if (gettempc) tempc = CF_SET() ? 1 : 0; \ - fetch_ea_16(fetchdat); \ - if (cpu_mod == 3) \ - { \ - dst = getr8(cpu_rm); \ - src = getr8(cpu_reg); \ - setflags ## 8 flagops; \ - setr8(cpu_rm, operation); \ - CLOCK_CYCLES(timing_rr); \ - PREFETCH_RUN(timing_rr, 2, rmdat, 0,0,0,0, 0); \ - } \ - else \ - { \ - SEG_CHECK_WRITE(cpu_state.ea_seg); \ - dst = geteab(); if (cpu_state.abrt) return 1; \ - src = getr8(cpu_reg); \ - seteab(operation); if (cpu_state.abrt) return 1; \ - setflags ## 8 flagops; \ - CLOCK_CYCLES(timing_mr); \ - PREFETCH_RUN(timing_mr, 2, rmdat, 1,0,1,0, 0); \ - } \ - return 0; \ - } \ - static int op ## name ## _b_rmw_a32(uint32_t fetchdat) \ - { \ - uint8_t dst; \ - uint8_t src; \ - if (gettempc) tempc = CF_SET() ? 1 : 0; \ - fetch_ea_32(fetchdat); \ - if (cpu_mod == 3) \ - { \ - dst = getr8(cpu_rm); \ - src = getr8(cpu_reg); \ - setflags ## 8 flagops; \ - setr8(cpu_rm, operation); \ - CLOCK_CYCLES(timing_rr); \ - PREFETCH_RUN(timing_rr, 2, rmdat, 0,0,0,0, 1); \ - } \ - else \ - { \ - SEG_CHECK_WRITE(cpu_state.ea_seg); \ - dst = geteab(); if (cpu_state.abrt) return 1; \ - src = getr8(cpu_reg); \ - seteab(operation); if (cpu_state.abrt) return 1; \ - setflags ## 8 flagops; \ - CLOCK_CYCLES(timing_mr); \ - PREFETCH_RUN(timing_mr, 2, rmdat, 1,0,1,0, 1); \ - } \ - return 0; \ - } \ - \ - static int op ## name ## _w_rmw_a16(uint32_t fetchdat) \ - { \ - uint16_t dst; \ - uint16_t src; \ - if (gettempc) tempc = CF_SET() ? 1 : 0; \ - fetch_ea_16(fetchdat); \ - if (cpu_mod == 3) \ - { \ - dst = cpu_state.regs[cpu_rm].w; \ - src = cpu_state.regs[cpu_reg].w; \ - setflags ## 16 flagops; \ - cpu_state.regs[cpu_rm].w = operation; \ - CLOCK_CYCLES(timing_rr); \ - PREFETCH_RUN(timing_rr, 2, rmdat, 0,0,0,0, 0); \ - } \ - else \ - { \ - SEG_CHECK_WRITE(cpu_state.ea_seg); \ - dst = geteaw(); if (cpu_state.abrt) return 1; \ - src = cpu_state.regs[cpu_reg].w; \ - seteaw(operation); if (cpu_state.abrt) return 1; \ - setflags ## 16 flagops; \ - CLOCK_CYCLES(timing_mr); \ - PREFETCH_RUN(timing_rr, 2, rmdat, 1,0,1,0, 0); \ - } \ - return 0; \ - } \ - static int op ## name ## _w_rmw_a32(uint32_t fetchdat) \ - { \ - uint16_t dst; \ - uint16_t src; \ - if (gettempc) tempc = CF_SET() ? 1 : 0; \ - fetch_ea_32(fetchdat); \ - if (cpu_mod == 3) \ - { \ - dst = cpu_state.regs[cpu_rm].w; \ - src = cpu_state.regs[cpu_reg].w; \ - setflags ## 16 flagops; \ - cpu_state.regs[cpu_rm].w = operation; \ - CLOCK_CYCLES(timing_rr); \ - PREFETCH_RUN(timing_rr, 2, rmdat, 0,0,0,0, 1); \ - } \ - else \ - { \ - SEG_CHECK_WRITE(cpu_state.ea_seg); \ - dst = geteaw(); if (cpu_state.abrt) return 1; \ - src = cpu_state.regs[cpu_reg].w; \ - seteaw(operation); if (cpu_state.abrt) return 1; \ - setflags ## 16 flagops; \ - CLOCK_CYCLES(timing_mr); \ - PREFETCH_RUN(timing_rr, 2, rmdat, 1,0,1,0, 1); \ - } \ - return 0; \ - } \ - \ - static int op ## name ## _l_rmw_a16(uint32_t fetchdat) \ - { \ - uint32_t dst; \ - uint32_t src; \ - if (gettempc) tempc = CF_SET() ? 1 : 0; \ - fetch_ea_16(fetchdat); \ - if (cpu_mod == 3) \ - { \ - dst = cpu_state.regs[cpu_rm].l; \ - src = cpu_state.regs[cpu_reg].l; \ - setflags ## 32 flagops; \ - cpu_state.regs[cpu_rm].l = operation; \ - CLOCK_CYCLES(timing_rr); \ - PREFETCH_RUN(timing_rr, 2, rmdat, 0,0,0,0, 0); \ - } \ - else \ - { \ - SEG_CHECK_WRITE(cpu_state.ea_seg); \ - dst = geteal(); if (cpu_state.abrt) return 1; \ - src = cpu_state.regs[cpu_reg].l; \ - seteal(operation); if (cpu_state.abrt) return 1; \ - setflags ## 32 flagops; \ - CLOCK_CYCLES(timing_mr); \ - PREFETCH_RUN(timing_rr, 2, rmdat, 0,1,0,1, 0); \ - } \ - return 0; \ - } \ - static int op ## name ## _l_rmw_a32(uint32_t fetchdat) \ - { \ - uint32_t dst; \ - uint32_t src; \ - if (gettempc) tempc = CF_SET() ? 1 : 0; \ - fetch_ea_32(fetchdat); \ - if (cpu_mod == 3) \ - { \ - dst = cpu_state.regs[cpu_rm].l; \ - src = cpu_state.regs[cpu_reg].l; \ - setflags ## 32 flagops; \ - cpu_state.regs[cpu_rm].l = operation; \ - CLOCK_CYCLES(timing_rr); \ - PREFETCH_RUN(timing_rr, 2, rmdat, 0,0,0,0, 1); \ - } \ - else \ - { \ - SEG_CHECK_WRITE(cpu_state.ea_seg); \ - dst = geteal(); if (cpu_state.abrt) return 1; \ - src = cpu_state.regs[cpu_reg].l; \ - seteal(operation); if (cpu_state.abrt) return 1; \ - setflags ## 32 flagops; \ - CLOCK_CYCLES(timing_mr); \ - PREFETCH_RUN(timing_rr, 2, rmdat, 0,1,0,1, 1); \ - } \ - return 0; \ - } \ - \ - static int op ## name ## _b_rm_a16(uint32_t fetchdat) \ - { \ - uint8_t dst, src; \ - if (gettempc) tempc = CF_SET() ? 1 : 0; \ - fetch_ea_16(fetchdat); \ - if (cpu_mod != 3) \ - SEG_CHECK_READ(cpu_state.ea_seg); \ - dst = getr8(cpu_reg); \ - src = geteab(); if (cpu_state.abrt) return 1; \ - setflags ## 8 flagops; \ - setr8(cpu_reg, operation); \ - CLOCK_CYCLES((cpu_mod == 3) ? timing_rr : timing_rm); \ - PREFETCH_RUN((cpu_mod == 3) ? timing_rr : timing_rm, 2, rmdat, (cpu_mod == 3) ? 0 : 1,0,0,0, 0); \ - return 0; \ - } \ - static int op ## name ## _b_rm_a32(uint32_t fetchdat) \ - { \ - uint8_t dst, src; \ - if (gettempc) tempc = CF_SET() ? 1 : 0; \ - fetch_ea_32(fetchdat); \ - if (cpu_mod != 3) \ - SEG_CHECK_READ(cpu_state.ea_seg); \ - dst = getr8(cpu_reg); \ - src = geteab(); if (cpu_state.abrt) return 1; \ - setflags ## 8 flagops; \ - setr8(cpu_reg, operation); \ - CLOCK_CYCLES((cpu_mod == 3) ? timing_rr : timing_rm); \ - PREFETCH_RUN((cpu_mod == 3) ? timing_rr : timing_rm, 2, rmdat, (cpu_mod == 3) ? 0 : 1,0,0,0, 1); \ - return 0; \ - } \ - \ - static int op ## name ## _w_rm_a16(uint32_t fetchdat) \ - { \ - uint16_t dst, src; \ - if (gettempc) tempc = CF_SET() ? 1 : 0; \ - fetch_ea_16(fetchdat); \ - if (cpu_mod != 3) \ - SEG_CHECK_READ(cpu_state.ea_seg); \ - dst = cpu_state.regs[cpu_reg].w; \ - src = geteaw(); if (cpu_state.abrt) return 1; \ - setflags ## 16 flagops; \ - cpu_state.regs[cpu_reg].w = operation; \ - CLOCK_CYCLES((cpu_mod == 3) ? timing_rr : timing_rm); \ - PREFETCH_RUN((cpu_mod == 3) ? timing_rr : timing_rm, 2, rmdat, (cpu_mod == 3) ? 0 : 1,0,0,0, 0); \ - return 0; \ - } \ - static int op ## name ## _w_rm_a32(uint32_t fetchdat) \ - { \ - uint16_t dst, src; \ - if (gettempc) tempc = CF_SET() ? 1 : 0; \ - fetch_ea_32(fetchdat); \ - if (cpu_mod != 3) \ - SEG_CHECK_READ(cpu_state.ea_seg); \ - dst = cpu_state.regs[cpu_reg].w; \ - src = geteaw(); if (cpu_state.abrt) return 1; \ - setflags ## 16 flagops; \ - cpu_state.regs[cpu_reg].w = operation; \ - CLOCK_CYCLES((cpu_mod == 3) ? timing_rr : timing_rm); \ - PREFETCH_RUN((cpu_mod == 3) ? timing_rr : timing_rm, 2, rmdat, (cpu_mod == 3) ? 0 : 1,0,0,0, 1); \ - return 0; \ - } \ - \ - static int op ## name ## _l_rm_a16(uint32_t fetchdat) \ - { \ - uint32_t dst, src; \ - if (gettempc) tempc = CF_SET() ? 1 : 0; \ - fetch_ea_16(fetchdat); \ - if (cpu_mod != 3) \ - SEG_CHECK_READ(cpu_state.ea_seg); \ - dst = cpu_state.regs[cpu_reg].l; \ - src = geteal(); if (cpu_state.abrt) return 1; \ - setflags ## 32 flagops; \ - cpu_state.regs[cpu_reg].l = operation; \ - CLOCK_CYCLES((cpu_mod == 3) ? timing_rr : timing_rml); \ - PREFETCH_RUN((cpu_mod == 3) ? timing_rr : timing_rm, 2, rmdat, 0, (cpu_mod == 3) ? 0 : 1,0,0, 0); \ - return 0; \ - } \ - static int op ## name ## _l_rm_a32(uint32_t fetchdat) \ - { \ - uint32_t dst, src; \ - if (gettempc) tempc = CF_SET() ? 1 : 0; \ - fetch_ea_32(fetchdat); \ - if (cpu_mod != 3) \ - SEG_CHECK_READ(cpu_state.ea_seg); \ - dst = cpu_state.regs[cpu_reg].l; \ - src = geteal(); if (cpu_state.abrt) return 1; \ - setflags ## 32 flagops; \ - cpu_state.regs[cpu_reg].l = operation; \ - CLOCK_CYCLES((cpu_mod == 3) ? timing_rr : timing_rml); \ - PREFETCH_RUN((cpu_mod == 3) ? timing_rr : timing_rm, 2, rmdat, 0, (cpu_mod == 3) ? 0 : 1,0,0, 1); \ - return 0; \ - } \ - \ - static int op ## name ## _AL_imm(uint32_t fetchdat) \ - { \ - uint8_t dst = AL; \ - uint8_t src = getbytef(); \ - if (gettempc) tempc = CF_SET() ? 1 : 0; \ - setflags ## 8 flagops; \ - AL = operation; \ - CLOCK_CYCLES(timing_rr); \ - PREFETCH_RUN(timing_rr, 2, -1, 0,0,0,0, 0); \ - return 0; \ - } \ - \ - static int op ## name ## _AX_imm(uint32_t fetchdat) \ - { \ - uint16_t dst = AX; \ - uint16_t src = getwordf(); \ - if (gettempc) tempc = CF_SET() ? 1 : 0; \ - setflags ## 16 flagops; \ - AX = operation; \ - CLOCK_CYCLES(timing_rr); \ - PREFETCH_RUN(timing_rr, 3, -1, 0,0,0,0, 0); \ - return 0; \ - } \ - \ - static int op ## name ## _EAX_imm(uint32_t fetchdat) \ - { \ - uint32_t dst = EAX; \ - uint32_t src = getlong(); if (cpu_state.abrt) return 1; \ - if (gettempc) tempc = CF_SET() ? 1 : 0; \ - setflags ## 32 flagops; \ - EAX = operation; \ - CLOCK_CYCLES(timing_rr); \ - PREFETCH_RUN(timing_rr, 5, -1, 0,0,0,0, 0); \ - return 0; \ - } +#define OP_ARITH(name, operation, setflags, flagops, gettempc) \ + static int op##name##_b_rmw_a16(uint32_t fetchdat) \ + { \ + uint8_t dst; \ + uint8_t src; \ + if (gettempc) \ + tempc = CF_SET() ? 1 : 0; \ + fetch_ea_16(fetchdat); \ + if (cpu_mod == 3) { \ + dst = getr8(cpu_rm); \ + src = getr8(cpu_reg); \ + setflags##8 flagops; \ + setr8(cpu_rm, operation); \ + CLOCK_CYCLES(timing_rr); \ + PREFETCH_RUN(timing_rr, 2, rmdat, 0, 0, 0, 0, 0); \ + } else { \ + SEG_CHECK_WRITE(cpu_state.ea_seg); \ + dst = geteab(); \ + if (cpu_state.abrt) \ + return 1; \ + src = getr8(cpu_reg); \ + seteab(operation); \ + if (cpu_state.abrt) \ + return 1; \ + setflags##8 flagops; \ + CLOCK_CYCLES(timing_mr); \ + PREFETCH_RUN(timing_mr, 2, rmdat, 1, 0, 1, 0, 0); \ + } \ + return 0; \ + } \ + static int op##name##_b_rmw_a32(uint32_t fetchdat) \ + { \ + uint8_t dst; \ + uint8_t src; \ + if (gettempc) \ + tempc = CF_SET() ? 1 : 0; \ + fetch_ea_32(fetchdat); \ + if (cpu_mod == 3) { \ + dst = getr8(cpu_rm); \ + src = getr8(cpu_reg); \ + setflags##8 flagops; \ + setr8(cpu_rm, operation); \ + CLOCK_CYCLES(timing_rr); \ + PREFETCH_RUN(timing_rr, 2, rmdat, 0, 0, 0, 0, 1); \ + } else { \ + SEG_CHECK_WRITE(cpu_state.ea_seg); \ + dst = geteab(); \ + if (cpu_state.abrt) \ + return 1; \ + src = getr8(cpu_reg); \ + seteab(operation); \ + if (cpu_state.abrt) \ + return 1; \ + setflags##8 flagops; \ + CLOCK_CYCLES(timing_mr); \ + PREFETCH_RUN(timing_mr, 2, rmdat, 1, 0, 1, 0, 1); \ + } \ + return 0; \ + } \ + \ + static int op##name##_w_rmw_a16(uint32_t fetchdat) \ + { \ + uint16_t dst; \ + uint16_t src; \ + if (gettempc) \ + tempc = CF_SET() ? 1 : 0; \ + fetch_ea_16(fetchdat); \ + if (cpu_mod == 3) { \ + dst = cpu_state.regs[cpu_rm].w; \ + src = cpu_state.regs[cpu_reg].w; \ + setflags##16 flagops; \ + cpu_state.regs[cpu_rm].w = operation; \ + CLOCK_CYCLES(timing_rr); \ + PREFETCH_RUN(timing_rr, 2, rmdat, 0, 0, 0, 0, 0); \ + } else { \ + SEG_CHECK_WRITE(cpu_state.ea_seg); \ + dst = geteaw(); \ + if (cpu_state.abrt) \ + return 1; \ + src = cpu_state.regs[cpu_reg].w; \ + seteaw(operation); \ + if (cpu_state.abrt) \ + return 1; \ + setflags##16 flagops; \ + CLOCK_CYCLES(timing_mr); \ + PREFETCH_RUN(timing_rr, 2, rmdat, 1, 0, 1, 0, 0); \ + } \ + return 0; \ + } \ + static int op##name##_w_rmw_a32(uint32_t fetchdat) \ + { \ + uint16_t dst; \ + uint16_t src; \ + if (gettempc) \ + tempc = CF_SET() ? 1 : 0; \ + fetch_ea_32(fetchdat); \ + if (cpu_mod == 3) { \ + dst = cpu_state.regs[cpu_rm].w; \ + src = cpu_state.regs[cpu_reg].w; \ + setflags##16 flagops; \ + cpu_state.regs[cpu_rm].w = operation; \ + CLOCK_CYCLES(timing_rr); \ + PREFETCH_RUN(timing_rr, 2, rmdat, 0, 0, 0, 0, 1); \ + } else { \ + SEG_CHECK_WRITE(cpu_state.ea_seg); \ + dst = geteaw(); \ + if (cpu_state.abrt) \ + return 1; \ + src = cpu_state.regs[cpu_reg].w; \ + seteaw(operation); \ + if (cpu_state.abrt) \ + return 1; \ + setflags##16 flagops; \ + CLOCK_CYCLES(timing_mr); \ + PREFETCH_RUN(timing_rr, 2, rmdat, 1, 0, 1, 0, 1); \ + } \ + return 0; \ + } \ + \ + static int op##name##_l_rmw_a16(uint32_t fetchdat) \ + { \ + uint32_t dst; \ + uint32_t src; \ + if (gettempc) \ + tempc = CF_SET() ? 1 : 0; \ + fetch_ea_16(fetchdat); \ + if (cpu_mod == 3) { \ + dst = cpu_state.regs[cpu_rm].l; \ + src = cpu_state.regs[cpu_reg].l; \ + setflags##32 flagops; \ + cpu_state.regs[cpu_rm].l = operation; \ + CLOCK_CYCLES(timing_rr); \ + PREFETCH_RUN(timing_rr, 2, rmdat, 0, 0, 0, 0, 0); \ + } else { \ + SEG_CHECK_WRITE(cpu_state.ea_seg); \ + dst = geteal(); \ + if (cpu_state.abrt) \ + return 1; \ + src = cpu_state.regs[cpu_reg].l; \ + seteal(operation); \ + if (cpu_state.abrt) \ + return 1; \ + setflags##32 flagops; \ + CLOCK_CYCLES(timing_mr); \ + PREFETCH_RUN(timing_rr, 2, rmdat, 0, 1, 0, 1, 0); \ + } \ + return 0; \ + } \ + static int op##name##_l_rmw_a32(uint32_t fetchdat) \ + { \ + uint32_t dst; \ + uint32_t src; \ + if (gettempc) \ + tempc = CF_SET() ? 1 : 0; \ + fetch_ea_32(fetchdat); \ + if (cpu_mod == 3) { \ + dst = cpu_state.regs[cpu_rm].l; \ + src = cpu_state.regs[cpu_reg].l; \ + setflags##32 flagops; \ + cpu_state.regs[cpu_rm].l = operation; \ + CLOCK_CYCLES(timing_rr); \ + PREFETCH_RUN(timing_rr, 2, rmdat, 0, 0, 0, 0, 1); \ + } else { \ + SEG_CHECK_WRITE(cpu_state.ea_seg); \ + dst = geteal(); \ + if (cpu_state.abrt) \ + return 1; \ + src = cpu_state.regs[cpu_reg].l; \ + seteal(operation); \ + if (cpu_state.abrt) \ + return 1; \ + setflags##32 flagops; \ + CLOCK_CYCLES(timing_mr); \ + PREFETCH_RUN(timing_rr, 2, rmdat, 0, 1, 0, 1, 1); \ + } \ + return 0; \ + } \ + \ + static int op##name##_b_rm_a16(uint32_t fetchdat) \ + { \ + uint8_t dst, src; \ + if (gettempc) \ + tempc = CF_SET() ? 1 : 0; \ + fetch_ea_16(fetchdat); \ + if (cpu_mod != 3) \ + SEG_CHECK_READ(cpu_state.ea_seg); \ + dst = getr8(cpu_reg); \ + src = geteab(); \ + if (cpu_state.abrt) \ + return 1; \ + setflags##8 flagops; \ + setr8(cpu_reg, operation); \ + CLOCK_CYCLES((cpu_mod == 3) ? timing_rr : timing_rm); \ + PREFETCH_RUN((cpu_mod == 3) ? timing_rr : timing_rm, 2, rmdat, (cpu_mod == 3) ? 0 : 1, 0, 0, 0, 0); \ + return 0; \ + } \ + static int op##name##_b_rm_a32(uint32_t fetchdat) \ + { \ + uint8_t dst, src; \ + if (gettempc) \ + tempc = CF_SET() ? 1 : 0; \ + fetch_ea_32(fetchdat); \ + if (cpu_mod != 3) \ + SEG_CHECK_READ(cpu_state.ea_seg); \ + dst = getr8(cpu_reg); \ + src = geteab(); \ + if (cpu_state.abrt) \ + return 1; \ + setflags##8 flagops; \ + setr8(cpu_reg, operation); \ + CLOCK_CYCLES((cpu_mod == 3) ? timing_rr : timing_rm); \ + PREFETCH_RUN((cpu_mod == 3) ? timing_rr : timing_rm, 2, rmdat, (cpu_mod == 3) ? 0 : 1, 0, 0, 0, 1); \ + return 0; \ + } \ + \ + static int op##name##_w_rm_a16(uint32_t fetchdat) \ + { \ + uint16_t dst, src; \ + if (gettempc) \ + tempc = CF_SET() ? 1 : 0; \ + fetch_ea_16(fetchdat); \ + if (cpu_mod != 3) \ + SEG_CHECK_READ(cpu_state.ea_seg); \ + dst = cpu_state.regs[cpu_reg].w; \ + src = geteaw(); \ + if (cpu_state.abrt) \ + return 1; \ + setflags##16 flagops; \ + cpu_state.regs[cpu_reg].w = operation; \ + CLOCK_CYCLES((cpu_mod == 3) ? timing_rr : timing_rm); \ + PREFETCH_RUN((cpu_mod == 3) ? timing_rr : timing_rm, 2, rmdat, (cpu_mod == 3) ? 0 : 1, 0, 0, 0, 0); \ + return 0; \ + } \ + static int op##name##_w_rm_a32(uint32_t fetchdat) \ + { \ + uint16_t dst, src; \ + if (gettempc) \ + tempc = CF_SET() ? 1 : 0; \ + fetch_ea_32(fetchdat); \ + if (cpu_mod != 3) \ + SEG_CHECK_READ(cpu_state.ea_seg); \ + dst = cpu_state.regs[cpu_reg].w; \ + src = geteaw(); \ + if (cpu_state.abrt) \ + return 1; \ + setflags##16 flagops; \ + cpu_state.regs[cpu_reg].w = operation; \ + CLOCK_CYCLES((cpu_mod == 3) ? timing_rr : timing_rm); \ + PREFETCH_RUN((cpu_mod == 3) ? timing_rr : timing_rm, 2, rmdat, (cpu_mod == 3) ? 0 : 1, 0, 0, 0, 1); \ + return 0; \ + } \ + \ + static int op##name##_l_rm_a16(uint32_t fetchdat) \ + { \ + uint32_t dst, src; \ + if (gettempc) \ + tempc = CF_SET() ? 1 : 0; \ + fetch_ea_16(fetchdat); \ + if (cpu_mod != 3) \ + SEG_CHECK_READ(cpu_state.ea_seg); \ + dst = cpu_state.regs[cpu_reg].l; \ + src = geteal(); \ + if (cpu_state.abrt) \ + return 1; \ + setflags##32 flagops; \ + cpu_state.regs[cpu_reg].l = operation; \ + CLOCK_CYCLES((cpu_mod == 3) ? timing_rr : timing_rml); \ + PREFETCH_RUN((cpu_mod == 3) ? timing_rr : timing_rm, 2, rmdat, 0, (cpu_mod == 3) ? 0 : 1, 0, 0, 0); \ + return 0; \ + } \ + static int op##name##_l_rm_a32(uint32_t fetchdat) \ + { \ + uint32_t dst, src; \ + if (gettempc) \ + tempc = CF_SET() ? 1 : 0; \ + fetch_ea_32(fetchdat); \ + if (cpu_mod != 3) \ + SEG_CHECK_READ(cpu_state.ea_seg); \ + dst = cpu_state.regs[cpu_reg].l; \ + src = geteal(); \ + if (cpu_state.abrt) \ + return 1; \ + setflags##32 flagops; \ + cpu_state.regs[cpu_reg].l = operation; \ + CLOCK_CYCLES((cpu_mod == 3) ? timing_rr : timing_rml); \ + PREFETCH_RUN((cpu_mod == 3) ? timing_rr : timing_rm, 2, rmdat, 0, (cpu_mod == 3) ? 0 : 1, 0, 0, 1); \ + return 0; \ + } \ + \ + static int op##name##_AL_imm(uint32_t fetchdat) \ + { \ + uint8_t dst = AL; \ + uint8_t src = getbytef(); \ + if (gettempc) \ + tempc = CF_SET() ? 1 : 0; \ + setflags##8 flagops; \ + AL = operation; \ + CLOCK_CYCLES(timing_rr); \ + PREFETCH_RUN(timing_rr, 2, -1, 0, 0, 0, 0, 0); \ + return 0; \ + } \ + \ + static int op##name##_AX_imm(uint32_t fetchdat) \ + { \ + uint16_t dst = AX; \ + uint16_t src = getwordf(); \ + if (gettempc) \ + tempc = CF_SET() ? 1 : 0; \ + setflags##16 flagops; \ + AX = operation; \ + CLOCK_CYCLES(timing_rr); \ + PREFETCH_RUN(timing_rr, 3, -1, 0, 0, 0, 0, 0); \ + return 0; \ + } \ + \ + static int op##name##_EAX_imm(uint32_t fetchdat) \ + { \ + uint32_t dst = EAX; \ + uint32_t src = getlong(); \ + if (cpu_state.abrt) \ + return 1; \ + if (gettempc) \ + tempc = CF_SET() ? 1 : 0; \ + setflags##32 flagops; \ + EAX = operation; \ + CLOCK_CYCLES(timing_rr); \ + PREFETCH_RUN(timing_rr, 5, -1, 0, 0, 0, 0, 0); \ + return 0; \ + } -OP_ARITH(ADD, dst + src, setadd, (dst, src), 0) -OP_ARITH(ADC, dst + src + tempc, setadc, (dst, src), 1) -OP_ARITH(SUB, dst - src, setsub, (dst, src), 0) +OP_ARITH(ADD, dst + src, setadd, (dst, src), 0) +OP_ARITH(ADC, dst + src + tempc, setadc, (dst, src), 1) +OP_ARITH(SUB, dst - src, setsub, (dst, src), 0) OP_ARITH(SBB, dst - (src + tempc), setsbc, (dst, src), 1) -OP_ARITH(OR, dst | src, setznp, (dst | src), 0) -OP_ARITH(AND, dst & src, setznp, (dst & src), 0) -OP_ARITH(XOR, dst ^ src, setznp, (dst ^ src), 0) +OP_ARITH(OR, dst | src, setznp, (dst | src), 0) +OP_ARITH(AND, dst &src, setznp, (dst & src), 0) +OP_ARITH(XOR, dst ^ src, setznp, (dst ^ src), 0) -static int opCMP_b_rmw_a16(uint32_t fetchdat) +static int +opCMP_b_rmw_a16(uint32_t fetchdat) { - uint8_t dst; - fetch_ea_16(fetchdat); - if (cpu_mod != 3) - SEG_CHECK_READ(cpu_state.ea_seg); - dst = geteab(); if (cpu_state.abrt) return 1; - setsub8(dst, getr8(cpu_reg)); - if (is486) { CLOCK_CYCLES((cpu_mod == 3) ? 1 : 2); } - else { CLOCK_CYCLES((cpu_mod == 3) ? 2 : 5); } - PREFETCH_RUN((cpu_mod == 3) ? timing_rr : timing_rm, 2, rmdat, (cpu_mod == 3) ? 0 : 1,0,0,0, 0); - return 0; + uint8_t dst; + + fetch_ea_16(fetchdat); + if (cpu_mod != 3) + SEG_CHECK_READ(cpu_state.ea_seg); + dst = geteab(); + if (cpu_state.abrt) + return 1; + setsub8(dst, getr8(cpu_reg)); + if (is486) { + CLOCK_CYCLES((cpu_mod == 3) ? 1 : 2); + } else { + CLOCK_CYCLES((cpu_mod == 3) ? 2 : 5); + } + PREFETCH_RUN((cpu_mod == 3) ? timing_rr : timing_rm, 2, rmdat, (cpu_mod == 3) ? 0 : 1, 0, 0, 0, 0); + return 0; } -static int opCMP_b_rmw_a32(uint32_t fetchdat) -{ - uint8_t dst; - fetch_ea_32(fetchdat); - if (cpu_mod != 3) - SEG_CHECK_READ(cpu_state.ea_seg); - dst = geteab(); if (cpu_state.abrt) return 1; - setsub8(dst, getr8(cpu_reg)); - if (is486) { CLOCK_CYCLES((cpu_mod == 3) ? 1 : 2); } - else { CLOCK_CYCLES((cpu_mod == 3) ? 2 : 5); } - PREFETCH_RUN((cpu_mod == 3) ? timing_rr : timing_rm, 2, rmdat, (cpu_mod == 3) ? 0 : 1,0,0,0, 1); - return 0; -} - -static int opCMP_w_rmw_a16(uint32_t fetchdat) -{ - uint16_t dst; - fetch_ea_16(fetchdat); - if (cpu_mod != 3) - SEG_CHECK_READ(cpu_state.ea_seg); - dst = geteaw(); if (cpu_state.abrt) return 1; - setsub16(dst, cpu_state.regs[cpu_reg].w); - if (is486) { CLOCK_CYCLES((cpu_mod == 3) ? 1 : 2); } - else { CLOCK_CYCLES((cpu_mod == 3) ? 2 : 5); } - PREFETCH_RUN((cpu_mod == 3) ? timing_rr : timing_rm, 2, rmdat, (cpu_mod == 3) ? 0 : 1,0,0,0, 0); - return 0; -} -static int opCMP_w_rmw_a32(uint32_t fetchdat) -{ - uint16_t dst; - fetch_ea_32(fetchdat); - if (cpu_mod != 3) - SEG_CHECK_READ(cpu_state.ea_seg); - dst = geteaw(); if (cpu_state.abrt) return 1; - setsub16(dst, cpu_state.regs[cpu_reg].w); - if (is486) { CLOCK_CYCLES((cpu_mod == 3) ? 1 : 2); } - else { CLOCK_CYCLES((cpu_mod == 3) ? 2 : 5); } - PREFETCH_RUN((cpu_mod == 3) ? timing_rr : timing_rm, 2, rmdat, (cpu_mod == 3) ? 0 : 1,0,0,0, 1); - return 0; -} - -static int opCMP_l_rmw_a16(uint32_t fetchdat) -{ - uint32_t dst; - fetch_ea_16(fetchdat); - if (cpu_mod != 3) - SEG_CHECK_READ(cpu_state.ea_seg); - dst = geteal(); if (cpu_state.abrt) return 1; - setsub32(dst, cpu_state.regs[cpu_reg].l); - if (is486) { CLOCK_CYCLES((cpu_mod == 3) ? 1 : 2); } - else { CLOCK_CYCLES((cpu_mod == 3) ? 2 : 5); } - PREFETCH_RUN((cpu_mod == 3) ? timing_rr : timing_rm, 2, rmdat, 0, (cpu_mod == 3) ? 0 : 1,0,0, 0); - return 0; -} -static int opCMP_l_rmw_a32(uint32_t fetchdat) -{ - uint32_t dst; - fetch_ea_32(fetchdat); - if (cpu_mod != 3) - SEG_CHECK_READ(cpu_state.ea_seg); - dst = geteal(); if (cpu_state.abrt) return 1; - setsub32(dst, cpu_state.regs[cpu_reg].l); - if (is486) { CLOCK_CYCLES((cpu_mod == 3) ? 1 : 2); } - else { CLOCK_CYCLES((cpu_mod == 3) ? 2 : 5); } - PREFETCH_RUN((cpu_mod == 3) ? timing_rr : timing_rm, 2, rmdat, 0, (cpu_mod == 3) ? 0 : 1,0,0, 1); - return 0; -} - -static int opCMP_b_rm_a16(uint32_t fetchdat) -{ - uint8_t src; - fetch_ea_16(fetchdat); - if (cpu_mod != 3) - SEG_CHECK_READ(cpu_state.ea_seg); - src = geteab(); if (cpu_state.abrt) return 1; - setsub8(getr8(cpu_reg), src); - CLOCK_CYCLES((cpu_mod == 3) ? timing_rr : timing_rm); - PREFETCH_RUN((cpu_mod == 3) ? timing_rr : timing_rm, 2, rmdat, (cpu_mod == 3) ? 0 : 1,0,0,0, 0); - return 0; -} -static int opCMP_b_rm_a32(uint32_t fetchdat) -{ - uint8_t src; - fetch_ea_32(fetchdat); - if (cpu_mod != 3) - SEG_CHECK_READ(cpu_state.ea_seg); - src = geteab(); if (cpu_state.abrt) return 1; - setsub8(getr8(cpu_reg), src); - CLOCK_CYCLES((cpu_mod == 3) ? timing_rr : timing_rm); - PREFETCH_RUN((cpu_mod == 3) ? timing_rr : timing_rm, 2, rmdat, (cpu_mod == 3) ? 0 : 1,0,0,0, 1); - return 0; -} - -static int opCMP_w_rm_a16(uint32_t fetchdat) -{ - uint16_t src; - fetch_ea_16(fetchdat); - if (cpu_mod != 3) - SEG_CHECK_READ(cpu_state.ea_seg); - src = geteaw(); if (cpu_state.abrt) return 1; - setsub16(cpu_state.regs[cpu_reg].w, src); - CLOCK_CYCLES((cpu_mod == 3) ? timing_rr : timing_rm); - PREFETCH_RUN((cpu_mod == 3) ? timing_rr : timing_rm, 2, rmdat, (cpu_mod == 3) ? 0 : 1,0,0,0, 0); - return 0; -} -static int opCMP_w_rm_a32(uint32_t fetchdat) -{ - uint16_t src; - fetch_ea_32(fetchdat); - if (cpu_mod != 3) - SEG_CHECK_READ(cpu_state.ea_seg); - src = geteaw(); if (cpu_state.abrt) return 1; - setsub16(cpu_state.regs[cpu_reg].w, src); - CLOCK_CYCLES((cpu_mod == 3) ? timing_rr : timing_rm); - PREFETCH_RUN((cpu_mod == 3) ? timing_rr : timing_rm, 2, rmdat, (cpu_mod == 3) ? 0 : 1,0,0,0, 1); - return 0; -} - -static int opCMP_l_rm_a16(uint32_t fetchdat) +static int +opCMP_b_rmw_a32(uint32_t fetchdat) { - uint32_t src; - fetch_ea_16(fetchdat); - if (cpu_mod != 3) - SEG_CHECK_READ(cpu_state.ea_seg); - src = geteal(); if (cpu_state.abrt) return 1; - setsub32(cpu_state.regs[cpu_reg].l, src); - CLOCK_CYCLES((cpu_mod == 3) ? timing_rr : timing_rml); - PREFETCH_RUN((cpu_mod == 3) ? timing_rr : timing_rm, 2, rmdat, 0, (cpu_mod == 3) ? 0 : 1,0,0, 0); - return 0; -} -static int opCMP_l_rm_a32(uint32_t fetchdat) -{ - uint32_t src; - fetch_ea_32(fetchdat); - if (cpu_mod != 3) - SEG_CHECK_READ(cpu_state.ea_seg); - src = geteal(); if (cpu_state.abrt) return 1; - setsub32(cpu_state.regs[cpu_reg].l, src); - CLOCK_CYCLES((cpu_mod == 3) ? timing_rr : timing_rml); - PREFETCH_RUN((cpu_mod == 3) ? timing_rr : timing_rm, 2, rmdat, 0, (cpu_mod == 3) ? 0 : 1,0,0, 1); - return 0; -} - -static int opCMP_AL_imm(uint32_t fetchdat) -{ - uint8_t src = getbytef(); - setsub8(AL, src); - CLOCK_CYCLES(timing_rr); - PREFETCH_RUN(timing_rr, 2, -1, 0,0,0,0, 0); - return 0; -} - -static int opCMP_AX_imm(uint32_t fetchdat) -{ - uint16_t src = getwordf(); - setsub16(AX, src); - CLOCK_CYCLES(timing_rr); - PREFETCH_RUN(timing_rr, 3, -1, 0,0,0,0, 0); - return 0; -} - -static int opCMP_EAX_imm(uint32_t fetchdat) -{ - uint32_t src = getlong(); if (cpu_state.abrt) return 1; - setsub32(EAX, src); - CLOCK_CYCLES(timing_rr); - PREFETCH_RUN(timing_rr, 5, -1, 0,0,0,0, 0); - return 0; + uint8_t dst; + + fetch_ea_32(fetchdat); + if (cpu_mod != 3) + SEG_CHECK_READ(cpu_state.ea_seg); + dst = geteab(); + if (cpu_state.abrt) + return 1; + setsub8(dst, getr8(cpu_reg)); + if (is486) { + CLOCK_CYCLES((cpu_mod == 3) ? 1 : 2); + } else { + CLOCK_CYCLES((cpu_mod == 3) ? 2 : 5); + } + PREFETCH_RUN((cpu_mod == 3) ? timing_rr : timing_rm, 2, rmdat, (cpu_mod == 3) ? 0 : 1, 0, 0, 0, 1); + return 0; } -static int opTEST_b_a16(uint32_t fetchdat) +static int +opCMP_w_rmw_a16(uint32_t fetchdat) { - uint8_t temp, temp2; - fetch_ea_16(fetchdat); - if (cpu_mod != 3) - SEG_CHECK_READ(cpu_state.ea_seg); - temp = geteab(); if (cpu_state.abrt) return 1; - temp2 = getr8(cpu_reg); - setznp8(temp & temp2); - if (is486) { CLOCK_CYCLES((cpu_mod == 3) ? 1 : 2); } - else { CLOCK_CYCLES((cpu_mod == 3) ? 2 : 5); } - PREFETCH_RUN((cpu_mod == 3) ? timing_rr : timing_rm, 2, rmdat, (cpu_mod == 3) ? 0 : 1,0,0,0, 0); - return 0; + uint16_t dst; + + fetch_ea_16(fetchdat); + if (cpu_mod != 3) + SEG_CHECK_READ(cpu_state.ea_seg); + dst = geteaw(); + if (cpu_state.abrt) + return 1; + setsub16(dst, cpu_state.regs[cpu_reg].w); + if (is486) { + CLOCK_CYCLES((cpu_mod == 3) ? 1 : 2); + } else { + CLOCK_CYCLES((cpu_mod == 3) ? 2 : 5); + } + PREFETCH_RUN((cpu_mod == 3) ? timing_rr : timing_rm, 2, rmdat, (cpu_mod == 3) ? 0 : 1, 0, 0, 0, 0); + return 0; } -static int opTEST_b_a32(uint32_t fetchdat) +static int +opCMP_w_rmw_a32(uint32_t fetchdat) { - uint8_t temp, temp2; - fetch_ea_32(fetchdat); - if (cpu_mod != 3) - SEG_CHECK_READ(cpu_state.ea_seg); - temp = geteab(); if (cpu_state.abrt) return 1; - temp2 = getr8(cpu_reg); - setznp8(temp & temp2); - if (is486) { CLOCK_CYCLES((cpu_mod == 3) ? 1 : 2); } - else { CLOCK_CYCLES((cpu_mod == 3) ? 2 : 5); } - PREFETCH_RUN((cpu_mod == 3) ? timing_rr : timing_rm, 2, rmdat, (cpu_mod == 3) ? 0 : 1,0,0,0, 1); - return 0; + uint16_t dst; + + fetch_ea_32(fetchdat); + if (cpu_mod != 3) + SEG_CHECK_READ(cpu_state.ea_seg); + dst = geteaw(); + if (cpu_state.abrt) + return 1; + setsub16(dst, cpu_state.regs[cpu_reg].w); + if (is486) { + CLOCK_CYCLES((cpu_mod == 3) ? 1 : 2); + } else { + CLOCK_CYCLES((cpu_mod == 3) ? 2 : 5); + } + PREFETCH_RUN((cpu_mod == 3) ? timing_rr : timing_rm, 2, rmdat, (cpu_mod == 3) ? 0 : 1, 0, 0, 0, 1); + return 0; } -static int opTEST_w_a16(uint32_t fetchdat) +static int +opCMP_l_rmw_a16(uint32_t fetchdat) { - uint16_t temp, temp2; - fetch_ea_16(fetchdat); - if (cpu_mod != 3) - SEG_CHECK_READ(cpu_state.ea_seg); - temp = geteaw(); if (cpu_state.abrt) return 1; - temp2 = cpu_state.regs[cpu_reg].w; - setznp16(temp & temp2); - if (is486) { CLOCK_CYCLES((cpu_mod == 3) ? 1 : 2); } - else { CLOCK_CYCLES((cpu_mod == 3) ? 2 : 5); } - PREFETCH_RUN((cpu_mod == 3) ? timing_rr : timing_rm, 2, rmdat, (cpu_mod == 3) ? 0 : 1,0,0,0, 0); - return 0; + uint32_t dst; + + fetch_ea_16(fetchdat); + if (cpu_mod != 3) + SEG_CHECK_READ(cpu_state.ea_seg); + dst = geteal(); + if (cpu_state.abrt) + return 1; + setsub32(dst, cpu_state.regs[cpu_reg].l); + if (is486) { + CLOCK_CYCLES((cpu_mod == 3) ? 1 : 2); + } else { + CLOCK_CYCLES((cpu_mod == 3) ? 2 : 5); + } + PREFETCH_RUN((cpu_mod == 3) ? timing_rr : timing_rm, 2, rmdat, 0, (cpu_mod == 3) ? 0 : 1, 0, 0, 0); + return 0; } -static int opTEST_w_a32(uint32_t fetchdat) +static int +opCMP_l_rmw_a32(uint32_t fetchdat) { - uint16_t temp, temp2; - fetch_ea_32(fetchdat); - if (cpu_mod != 3) - SEG_CHECK_READ(cpu_state.ea_seg); - temp = geteaw(); if (cpu_state.abrt) return 1; - temp2 = cpu_state.regs[cpu_reg].w; - setznp16(temp & temp2); - if (is486) { CLOCK_CYCLES((cpu_mod == 3) ? 1 : 2); } - else { CLOCK_CYCLES((cpu_mod == 3) ? 2 : 5); } - PREFETCH_RUN((cpu_mod == 3) ? timing_rr : timing_rm, 2, rmdat, (cpu_mod == 3) ? 0 : 1,0,0,0, 1); - return 0; + uint32_t dst; + + fetch_ea_32(fetchdat); + if (cpu_mod != 3) + SEG_CHECK_READ(cpu_state.ea_seg); + dst = geteal(); + if (cpu_state.abrt) + return 1; + setsub32(dst, cpu_state.regs[cpu_reg].l); + if (is486) { + CLOCK_CYCLES((cpu_mod == 3) ? 1 : 2); + } else { + CLOCK_CYCLES((cpu_mod == 3) ? 2 : 5); + } + PREFETCH_RUN((cpu_mod == 3) ? timing_rr : timing_rm, 2, rmdat, 0, (cpu_mod == 3) ? 0 : 1, 0, 0, 1); + return 0; } -static int opTEST_l_a16(uint32_t fetchdat) +static int +opCMP_b_rm_a16(uint32_t fetchdat) { - uint32_t temp, temp2; - fetch_ea_16(fetchdat); - if (cpu_mod != 3) - SEG_CHECK_READ(cpu_state.ea_seg); - temp = geteal(); if (cpu_state.abrt) return 1; - temp2 = cpu_state.regs[cpu_reg].l; - setznp32(temp & temp2); - if (is486) { CLOCK_CYCLES((cpu_mod == 3) ? 1 : 2); } - else { CLOCK_CYCLES((cpu_mod == 3) ? 2 : 5); } - PREFETCH_RUN((cpu_mod == 3) ? timing_rr : timing_rm, 2, rmdat, 0,(cpu_mod == 3) ? 0 : 1,0,0, 0); - return 0; + uint8_t src; + + fetch_ea_16(fetchdat); + if (cpu_mod != 3) + SEG_CHECK_READ(cpu_state.ea_seg); + src = geteab(); + if (cpu_state.abrt) + return 1; + setsub8(getr8(cpu_reg), src); + CLOCK_CYCLES((cpu_mod == 3) ? timing_rr : timing_rm); + PREFETCH_RUN((cpu_mod == 3) ? timing_rr : timing_rm, 2, rmdat, (cpu_mod == 3) ? 0 : 1, 0, 0, 0, 0); + return 0; } -static int opTEST_l_a32(uint32_t fetchdat) +static int +opCMP_b_rm_a32(uint32_t fetchdat) { - uint32_t temp, temp2; - fetch_ea_32(fetchdat); - if (cpu_mod != 3) - SEG_CHECK_READ(cpu_state.ea_seg); - temp = geteal(); if (cpu_state.abrt) return 1; - temp2 = cpu_state.regs[cpu_reg].l; - setznp32(temp & temp2); - if (is486) { CLOCK_CYCLES((cpu_mod == 3) ? 1 : 2); } - else { CLOCK_CYCLES((cpu_mod == 3) ? 2 : 5); } - PREFETCH_RUN((cpu_mod == 3) ? timing_rr : timing_rm, 2, rmdat, 0,(cpu_mod == 3) ? 0 : 1,0,0, 1); - return 0; + uint8_t src; + + fetch_ea_32(fetchdat); + if (cpu_mod != 3) + SEG_CHECK_READ(cpu_state.ea_seg); + src = geteab(); + if (cpu_state.abrt) + return 1; + setsub8(getr8(cpu_reg), src); + CLOCK_CYCLES((cpu_mod == 3) ? timing_rr : timing_rm); + PREFETCH_RUN((cpu_mod == 3) ? timing_rr : timing_rm, 2, rmdat, (cpu_mod == 3) ? 0 : 1, 0, 0, 0, 1); + return 0; } -static int opTEST_AL(uint32_t fetchdat) +static int +opCMP_w_rm_a16(uint32_t fetchdat) { - uint8_t temp = getbytef(); - setznp8(AL & temp); - CLOCK_CYCLES(timing_rr); - PREFETCH_RUN(timing_rr, 2, -1, 0,0,0,0, 0); - return 0; + uint16_t src; + + fetch_ea_16(fetchdat); + if (cpu_mod != 3) + SEG_CHECK_READ(cpu_state.ea_seg); + src = geteaw(); + if (cpu_state.abrt) + return 1; + setsub16(cpu_state.regs[cpu_reg].w, src); + CLOCK_CYCLES((cpu_mod == 3) ? timing_rr : timing_rm); + PREFETCH_RUN((cpu_mod == 3) ? timing_rr : timing_rm, 2, rmdat, (cpu_mod == 3) ? 0 : 1, 0, 0, 0, 0); + return 0; } -static int opTEST_AX(uint32_t fetchdat) +static int +opCMP_w_rm_a32(uint32_t fetchdat) { - uint16_t temp = getwordf(); - setznp16(AX & temp); - CLOCK_CYCLES(timing_rr); - PREFETCH_RUN(timing_rr, 3, -1, 0,0,0,0, 0); - return 0; -} -static int opTEST_EAX(uint32_t fetchdat) -{ - uint32_t temp = getlong(); if (cpu_state.abrt) return 1; - setznp32(EAX & temp); - CLOCK_CYCLES(timing_rr); - PREFETCH_RUN(timing_rr, 5, -1, 0,0,0,0, 0); - return 0; + uint16_t src; + + fetch_ea_32(fetchdat); + if (cpu_mod != 3) + SEG_CHECK_READ(cpu_state.ea_seg); + src = geteaw(); + if (cpu_state.abrt) + return 1; + setsub16(cpu_state.regs[cpu_reg].w, src); + CLOCK_CYCLES((cpu_mod == 3) ? timing_rr : timing_rm); + PREFETCH_RUN((cpu_mod == 3) ? timing_rr : timing_rm, 2, rmdat, (cpu_mod == 3) ? 0 : 1, 0, 0, 0, 1); + return 0; } +static int +opCMP_l_rm_a16(uint32_t fetchdat) +{ + uint32_t src; -#define ARITH_MULTI(ea_width, flag_width) \ - dst = getea ## ea_width(); if (cpu_state.abrt) return 1; \ - switch (rmdat&0x38) \ - { \ - case 0x00: /*ADD ea, #*/ \ - setea ## ea_width(dst + src); if (cpu_state.abrt) return 1; \ - setadd ## flag_width(dst, src); \ - CLOCK_CYCLES((cpu_mod == 3) ? timing_rr : timing_mr); \ - break; \ - case 0x08: /*OR ea, #*/ \ - dst |= src; \ - setea ## ea_width(dst); if (cpu_state.abrt) return 1; \ - setznp ## flag_width(dst); \ - CLOCK_CYCLES((cpu_mod == 3) ? timing_rr : timing_mr); \ - break; \ - case 0x10: /*ADC ea, #*/ \ - tempc = CF_SET() ? 1 : 0; \ - setea ## ea_width(dst + src + tempc); if (cpu_state.abrt) return 1; \ - setadc ## flag_width(dst, src); \ - CLOCK_CYCLES((cpu_mod == 3) ? timing_rr : timing_mr); \ - break; \ - case 0x18: /*SBB ea, #*/ \ - tempc = CF_SET() ? 1 : 0; \ - setea ## ea_width(dst - (src + tempc)); if (cpu_state.abrt) return 1; \ - setsbc ## flag_width(dst, src); \ - CLOCK_CYCLES((cpu_mod == 3) ? timing_rr : timing_mr); \ - break; \ - case 0x20: /*AND ea, #*/ \ - dst &= src; \ - setea ## ea_width(dst); if (cpu_state.abrt) return 1; \ - setznp ## flag_width(dst); \ - CLOCK_CYCLES((cpu_mod == 3) ? timing_rr : timing_mr); \ - break; \ - case 0x28: /*SUB ea, #*/ \ - setea ## ea_width(dst - src); if (cpu_state.abrt) return 1; \ - setsub ## flag_width(dst, src); \ - CLOCK_CYCLES((cpu_mod == 3) ? timing_rr : timing_mr); \ - break; \ - case 0x30: /*XOR ea, #*/ \ - dst ^= src; \ - setea ## ea_width(dst); if (cpu_state.abrt) return 1; \ - setznp ## flag_width(dst); \ - CLOCK_CYCLES((cpu_mod == 3) ? timing_rr : timing_mr); \ - break; \ - case 0x38: /*CMP ea, #*/ \ - setsub ## flag_width(dst, src); \ - if (is486) { CLOCK_CYCLES((cpu_mod == 3) ? 1 : 2); } \ - else { CLOCK_CYCLES((cpu_mod == 3) ? 2 : 7); } \ - break; \ - } + fetch_ea_16(fetchdat); + if (cpu_mod != 3) + SEG_CHECK_READ(cpu_state.ea_seg); + src = geteal(); + if (cpu_state.abrt) + return 1; + setsub32(cpu_state.regs[cpu_reg].l, src); + CLOCK_CYCLES((cpu_mod == 3) ? timing_rr : timing_rml); + PREFETCH_RUN((cpu_mod == 3) ? timing_rr : timing_rm, 2, rmdat, 0, (cpu_mod == 3) ? 0 : 1, 0, 0, 0); + return 0; +} +static int +opCMP_l_rm_a32(uint32_t fetchdat) +{ + uint32_t src; - -static int op80_a16(uint32_t fetchdat) -{ - uint8_t src, dst; - - fetch_ea_16(fetchdat); - if (cpu_mod != 3) - SEG_CHECK_WRITE(cpu_state.ea_seg); - src = getbyte(); if (cpu_state.abrt) return 1; - ARITH_MULTI(b, 8); - if ((rmdat & 0x38) == 0x38) { - PREFETCH_RUN((cpu_mod == 3) ? timing_rr : timing_mr, 3, rmdat, (cpu_mod == 3) ? 0:1,0,0,0, 0); - } else { - PREFETCH_RUN((cpu_mod == 3) ? timing_rr : timing_rm, 3, rmdat, (cpu_mod == 3) ? 0:1,0,(cpu_mod == 3) ? 0:1,0, 0); - } - - return 0; -} -static int op80_a32(uint32_t fetchdat) -{ - uint8_t src, dst; - - fetch_ea_32(fetchdat); - if (cpu_mod != 3) - SEG_CHECK_WRITE(cpu_state.ea_seg); - src = getbyte(); if (cpu_state.abrt) return 1; - ARITH_MULTI(b, 8); - if ((rmdat & 0x38) == 0x38) { - PREFETCH_RUN((cpu_mod == 3) ? timing_rr : timing_mr, 3, rmdat, (cpu_mod == 3) ? 0:1,0,0,0, 1); - } else { - PREFETCH_RUN((cpu_mod == 3) ? timing_rr : timing_rm, 3, rmdat, (cpu_mod == 3) ? 0:1,0,(cpu_mod == 3) ? 0:1,0, 1); - } - - return 0; -} -static int op81_w_a16(uint32_t fetchdat) -{ - uint16_t src, dst; - - fetch_ea_16(fetchdat); - if (cpu_mod != 3) - SEG_CHECK_WRITE(cpu_state.ea_seg); - src = getword(); if (cpu_state.abrt) return 1; - ARITH_MULTI(w, 16); - if ((rmdat & 0x38) == 0x38) { - PREFETCH_RUN((cpu_mod == 3) ? timing_rr : timing_mr, 4, rmdat, (cpu_mod == 3) ? 0:1,0,0,0, 0); - } else { - PREFETCH_RUN((cpu_mod == 3) ? timing_rr : timing_rm, 4, rmdat, (cpu_mod == 3) ? 0:1,0,(cpu_mod == 3) ? 0:1,0, 0); - } - - return 0; -} -static int op81_w_a32(uint32_t fetchdat) -{ - uint16_t src, dst; - - fetch_ea_32(fetchdat); - if (cpu_mod != 3) - SEG_CHECK_WRITE(cpu_state.ea_seg); - src = getword(); if (cpu_state.abrt) return 1; - ARITH_MULTI(w, 16); - if ((rmdat & 0x38) == 0x38) { - PREFETCH_RUN((cpu_mod == 3) ? timing_rr : timing_mr, 4, rmdat, (cpu_mod == 3) ? 0:1,0,0,0, 1); - } else { - PREFETCH_RUN((cpu_mod == 3) ? timing_rr : timing_rm, 4, rmdat, (cpu_mod == 3) ? 0:1,0,(cpu_mod == 3) ? 0:1,0, 1); - } - - return 0; -} -static int op81_l_a16(uint32_t fetchdat) -{ - uint32_t src, dst; - - fetch_ea_16(fetchdat); - if (cpu_mod != 3) - SEG_CHECK_WRITE(cpu_state.ea_seg); - src = getlong(); if (cpu_state.abrt) return 1; - ARITH_MULTI(l, 32); - if ((rmdat & 0x38) == 0x38) { - PREFETCH_RUN((cpu_mod == 3) ? timing_rr : timing_mr, 6, rmdat, 0,(cpu_mod == 3) ? 0:1,0,0, 0); - } else { - PREFETCH_RUN((cpu_mod == 3) ? timing_rr : timing_rm, 6, rmdat, 0,(cpu_mod == 3) ? 0:1,0,(cpu_mod == 3) ? 0:1, 0); - } - - return 0; -} -static int op81_l_a32(uint32_t fetchdat) -{ - uint32_t src, dst; - - fetch_ea_32(fetchdat); - if (cpu_mod != 3) - SEG_CHECK_WRITE(cpu_state.ea_seg); - src = getlong(); if (cpu_state.abrt) return 1; - ARITH_MULTI(l, 32); - if ((rmdat & 0x38) == 0x38) { - PREFETCH_RUN((cpu_mod == 3) ? timing_rr : timing_mr, 6, rmdat, 0,(cpu_mod == 3) ? 0:1,0,0, 1); - } else { - PREFETCH_RUN((cpu_mod == 3) ? timing_rr : timing_rm, 6, rmdat, 0,(cpu_mod == 3) ? 0:1,0,(cpu_mod == 3) ? 0:1, 1); - } - - return 0; + fetch_ea_32(fetchdat); + if (cpu_mod != 3) + SEG_CHECK_READ(cpu_state.ea_seg); + src = geteal(); + if (cpu_state.abrt) + return 1; + setsub32(cpu_state.regs[cpu_reg].l, src); + CLOCK_CYCLES((cpu_mod == 3) ? timing_rr : timing_rml); + PREFETCH_RUN((cpu_mod == 3) ? timing_rr : timing_rm, 2, rmdat, 0, (cpu_mod == 3) ? 0 : 1, 0, 0, 1); + return 0; } -static int op83_w_a16(uint32_t fetchdat) +static int +opCMP_AL_imm(uint32_t fetchdat) { - uint16_t src, dst; - - fetch_ea_16(fetchdat); - if (cpu_mod != 3) - SEG_CHECK_WRITE(cpu_state.ea_seg); - src = getbyte(); if (cpu_state.abrt) return 1; - if (src & 0x80) src |= 0xff00; - ARITH_MULTI(w, 16); - if ((rmdat & 0x38) == 0x38) { - PREFETCH_RUN((cpu_mod == 3) ? timing_rr : timing_mr, 3, rmdat, (cpu_mod == 3) ? 0:1,0,0,0, 0); - } else { - PREFETCH_RUN((cpu_mod == 3) ? timing_rr : timing_rm, 3, rmdat, (cpu_mod == 3) ? 0:1,0,(cpu_mod == 3) ? 0:1,0, 0); - } - - return 0; -} -static int op83_w_a32(uint32_t fetchdat) -{ - uint16_t src, dst; - - fetch_ea_32(fetchdat); - if (cpu_mod != 3) - SEG_CHECK_WRITE(cpu_state.ea_seg); - src = getbyte(); if (cpu_state.abrt) return 1; - if (src & 0x80) src |= 0xff00; - ARITH_MULTI(w, 16); - if ((rmdat & 0x38) == 0x38) { - PREFETCH_RUN((cpu_mod == 3) ? timing_rr : timing_mr, 3, rmdat, (cpu_mod == 3) ? 0:1,0,0,0, 1); - } else { - PREFETCH_RUN((cpu_mod == 3) ? timing_rr : timing_rm, 3, rmdat, (cpu_mod == 3) ? 0:1,0,(cpu_mod == 3) ? 0:1,0, 1); - } - - return 0; + uint8_t src = getbytef(); + + setsub8(AL, src); + CLOCK_CYCLES(timing_rr); + PREFETCH_RUN(timing_rr, 2, -1, 0, 0, 0, 0, 0); + return 0; } -static int op83_l_a16(uint32_t fetchdat) +static int +opCMP_AX_imm(uint32_t fetchdat) { - uint32_t src, dst; - - fetch_ea_16(fetchdat); - if (cpu_mod != 3) - SEG_CHECK_WRITE(cpu_state.ea_seg); - src = getbyte(); if (cpu_state.abrt) return 1; - if (src & 0x80) src |= 0xffffff00; - ARITH_MULTI(l, 32); - if ((rmdat & 0x38) == 0x38) { - PREFETCH_RUN((cpu_mod == 3) ? timing_rr : timing_mr, 3, rmdat, 0,(cpu_mod == 3) ? 0:1,0,0, 0); - } else { - PREFETCH_RUN((cpu_mod == 3) ? timing_rr : timing_rm, 3, rmdat, 0,(cpu_mod == 3) ? 0:1,0,(cpu_mod == 3) ? 0:1, 0); - } - - return 0; -} -static int op83_l_a32(uint32_t fetchdat) -{ - uint32_t src, dst; - - fetch_ea_32(fetchdat); - if (cpu_mod != 3) - SEG_CHECK_WRITE(cpu_state.ea_seg); - src = getbyte(); if (cpu_state.abrt) return 1; - if (src & 0x80) src |= 0xffffff00; - ARITH_MULTI(l, 32); - if ((rmdat & 0x38) == 0x38) { - PREFETCH_RUN((cpu_mod == 3) ? timing_rr : timing_mr, 3, rmdat, 0,(cpu_mod == 3) ? 0:1,0,0, 1); - } else { - PREFETCH_RUN((cpu_mod == 3) ? timing_rr : timing_rm, 3, rmdat, 0,(cpu_mod == 3) ? 0:1,0,(cpu_mod == 3) ? 0:1, 1); - } - - return 0; + uint16_t src = getwordf(); + + setsub16(AX, src); + CLOCK_CYCLES(timing_rr); + PREFETCH_RUN(timing_rr, 3, -1, 0, 0, 0, 0, 0); + return 0; } +static int +opCMP_EAX_imm(uint32_t fetchdat) +{ + uint32_t src = getlong(); + + if (cpu_state.abrt) + return 1; + setsub32(EAX, src); + CLOCK_CYCLES(timing_rr); + PREFETCH_RUN(timing_rr, 5, -1, 0, 0, 0, 0, 0); + return 0; +} + +static int +opTEST_b_a16(uint32_t fetchdat) +{ + uint8_t temp; + uint8_t temp2; + + fetch_ea_16(fetchdat); + if (cpu_mod != 3) + SEG_CHECK_READ(cpu_state.ea_seg); + temp = geteab(); + if (cpu_state.abrt) + return 1; + temp2 = getr8(cpu_reg); + setznp8(temp & temp2); + if (is486) { + CLOCK_CYCLES((cpu_mod == 3) ? 1 : 2); + } else { + CLOCK_CYCLES((cpu_mod == 3) ? 2 : 5); + } + PREFETCH_RUN((cpu_mod == 3) ? timing_rr : timing_rm, 2, rmdat, (cpu_mod == 3) ? 0 : 1, 0, 0, 0, 0); + return 0; +} +static int +opTEST_b_a32(uint32_t fetchdat) +{ + uint8_t temp; + uint8_t temp2; + + fetch_ea_32(fetchdat); + if (cpu_mod != 3) + SEG_CHECK_READ(cpu_state.ea_seg); + temp = geteab(); + if (cpu_state.abrt) + return 1; + temp2 = getr8(cpu_reg); + setznp8(temp & temp2); + if (is486) { + CLOCK_CYCLES((cpu_mod == 3) ? 1 : 2); + } else { + CLOCK_CYCLES((cpu_mod == 3) ? 2 : 5); + } + PREFETCH_RUN((cpu_mod == 3) ? timing_rr : timing_rm, 2, rmdat, (cpu_mod == 3) ? 0 : 1, 0, 0, 0, 1); + return 0; +} + +static int +opTEST_w_a16(uint32_t fetchdat) +{ + uint16_t temp; + uint16_t temp2; + + fetch_ea_16(fetchdat); + if (cpu_mod != 3) + SEG_CHECK_READ(cpu_state.ea_seg); + temp = geteaw(); + if (cpu_state.abrt) + return 1; + temp2 = cpu_state.regs[cpu_reg].w; + setznp16(temp & temp2); + if (is486) { + CLOCK_CYCLES((cpu_mod == 3) ? 1 : 2); + } else { + CLOCK_CYCLES((cpu_mod == 3) ? 2 : 5); + } + PREFETCH_RUN((cpu_mod == 3) ? timing_rr : timing_rm, 2, rmdat, (cpu_mod == 3) ? 0 : 1, 0, 0, 0, 0); + return 0; +} +static int +opTEST_w_a32(uint32_t fetchdat) +{ + uint16_t temp; + uint16_t temp2; + + fetch_ea_32(fetchdat); + if (cpu_mod != 3) + SEG_CHECK_READ(cpu_state.ea_seg); + temp = geteaw(); + if (cpu_state.abrt) + return 1; + temp2 = cpu_state.regs[cpu_reg].w; + setznp16(temp & temp2); + if (is486) { + CLOCK_CYCLES((cpu_mod == 3) ? 1 : 2); + } else { + CLOCK_CYCLES((cpu_mod == 3) ? 2 : 5); + } + PREFETCH_RUN((cpu_mod == 3) ? timing_rr : timing_rm, 2, rmdat, (cpu_mod == 3) ? 0 : 1, 0, 0, 0, 1); + return 0; +} + +static int +opTEST_l_a16(uint32_t fetchdat) +{ + uint32_t temp; + uint32_t temp2; + + fetch_ea_16(fetchdat); + if (cpu_mod != 3) + SEG_CHECK_READ(cpu_state.ea_seg); + temp = geteal(); + if (cpu_state.abrt) + return 1; + temp2 = cpu_state.regs[cpu_reg].l; + setznp32(temp & temp2); + if (is486) { + CLOCK_CYCLES((cpu_mod == 3) ? 1 : 2); + } else { + CLOCK_CYCLES((cpu_mod == 3) ? 2 : 5); + } + PREFETCH_RUN((cpu_mod == 3) ? timing_rr : timing_rm, 2, rmdat, 0, (cpu_mod == 3) ? 0 : 1, 0, 0, 0); + return 0; +} +static int +opTEST_l_a32(uint32_t fetchdat) +{ + uint32_t temp; + uint32_t temp2; + + fetch_ea_32(fetchdat); + if (cpu_mod != 3) + SEG_CHECK_READ(cpu_state.ea_seg); + temp = geteal(); + if (cpu_state.abrt) + return 1; + temp2 = cpu_state.regs[cpu_reg].l; + setznp32(temp & temp2); + if (is486) { + CLOCK_CYCLES((cpu_mod == 3) ? 1 : 2); + } else { + CLOCK_CYCLES((cpu_mod == 3) ? 2 : 5); + } + PREFETCH_RUN((cpu_mod == 3) ? timing_rr : timing_rm, 2, rmdat, 0, (cpu_mod == 3) ? 0 : 1, 0, 0, 1); + return 0; +} + +static int +opTEST_AL(uint32_t fetchdat) +{ + uint8_t temp = getbytef(); + setznp8(AL & temp); + CLOCK_CYCLES(timing_rr); + PREFETCH_RUN(timing_rr, 2, -1, 0, 0, 0, 0, 0); + return 0; +} +static int +opTEST_AX(uint32_t fetchdat) +{ + uint16_t temp = getwordf(); + setznp16(AX & temp); + CLOCK_CYCLES(timing_rr); + PREFETCH_RUN(timing_rr, 3, -1, 0, 0, 0, 0, 0); + return 0; +} +static int +opTEST_EAX(uint32_t fetchdat) +{ + uint32_t temp = getlong(); + if (cpu_state.abrt) + return 1; + setznp32(EAX & temp); + CLOCK_CYCLES(timing_rr); + PREFETCH_RUN(timing_rr, 5, -1, 0, 0, 0, 0, 0); + return 0; +} + +#define ARITH_MULTI(ea_width, flag_width) \ + dst = getea##ea_width(); \ + if (cpu_state.abrt) \ + return 1; \ + switch (rmdat & 0x38) { \ + case 0x00: /*ADD ea, #*/ \ + setea##ea_width(dst + src); \ + if (cpu_state.abrt) \ + return 1; \ + setadd##flag_width(dst, src); \ + CLOCK_CYCLES((cpu_mod == 3) ? timing_rr : timing_mr); \ + break; \ + case 0x08: /*OR ea, #*/ \ + dst |= src; \ + setea##ea_width(dst); \ + if (cpu_state.abrt) \ + return 1; \ + setznp##flag_width(dst); \ + CLOCK_CYCLES((cpu_mod == 3) ? timing_rr : timing_mr); \ + break; \ + case 0x10: /*ADC ea, #*/ \ + tempc = CF_SET() ? 1 : 0; \ + setea##ea_width(dst + src + tempc); \ + if (cpu_state.abrt) \ + return 1; \ + setadc##flag_width(dst, src); \ + CLOCK_CYCLES((cpu_mod == 3) ? timing_rr : timing_mr); \ + break; \ + case 0x18: /*SBB ea, #*/ \ + tempc = CF_SET() ? 1 : 0; \ + setea##ea_width(dst - (src + tempc)); \ + if (cpu_state.abrt) \ + return 1; \ + setsbc##flag_width(dst, src); \ + CLOCK_CYCLES((cpu_mod == 3) ? timing_rr : timing_mr); \ + break; \ + case 0x20: /*AND ea, #*/ \ + dst &= src; \ + setea##ea_width(dst); \ + if (cpu_state.abrt) \ + return 1; \ + setznp##flag_width(dst); \ + CLOCK_CYCLES((cpu_mod == 3) ? timing_rr : timing_mr); \ + break; \ + case 0x28: /*SUB ea, #*/ \ + setea##ea_width(dst - src); \ + if (cpu_state.abrt) \ + return 1; \ + setsub##flag_width(dst, src); \ + CLOCK_CYCLES((cpu_mod == 3) ? timing_rr : timing_mr); \ + break; \ + case 0x30: /*XOR ea, #*/ \ + dst ^= src; \ + setea##ea_width(dst); \ + if (cpu_state.abrt) \ + return 1; \ + setznp##flag_width(dst); \ + CLOCK_CYCLES((cpu_mod == 3) ? timing_rr : timing_mr); \ + break; \ + case 0x38: /*CMP ea, #*/ \ + setsub##flag_width(dst, src); \ + if (is486) { \ + CLOCK_CYCLES((cpu_mod == 3) ? 1 : 2); \ + } else { \ + CLOCK_CYCLES((cpu_mod == 3) ? 2 : 7); \ + } \ + break; \ + } + +static int +op80_a16(uint32_t fetchdat) +{ + uint8_t src; + uint8_t dst; + + fetch_ea_16(fetchdat); + if (cpu_mod != 3) + SEG_CHECK_WRITE(cpu_state.ea_seg); + src = getbyte(); + if (cpu_state.abrt) + return 1; + ARITH_MULTI(b, 8); + if ((rmdat & 0x38) == 0x38) { + PREFETCH_RUN((cpu_mod == 3) ? timing_rr : timing_mr, 3, rmdat, (cpu_mod == 3) ? 0 : 1, 0, 0, 0, 0); + } else { + PREFETCH_RUN((cpu_mod == 3) ? timing_rr : timing_rm, 3, rmdat, (cpu_mod == 3) ? 0 : 1, 0, (cpu_mod == 3) ? 0 : 1, 0, 0); + } + + return 0; +} +static int +op80_a32(uint32_t fetchdat) +{ + uint8_t src; + uint8_t dst; + + fetch_ea_32(fetchdat); + if (cpu_mod != 3) + SEG_CHECK_WRITE(cpu_state.ea_seg); + src = getbyte(); + if (cpu_state.abrt) + return 1; + ARITH_MULTI(b, 8); + if ((rmdat & 0x38) == 0x38) { + PREFETCH_RUN((cpu_mod == 3) ? timing_rr : timing_mr, 3, rmdat, (cpu_mod == 3) ? 0 : 1, 0, 0, 0, 1); + } else { + PREFETCH_RUN((cpu_mod == 3) ? timing_rr : timing_rm, 3, rmdat, (cpu_mod == 3) ? 0 : 1, 0, (cpu_mod == 3) ? 0 : 1, 0, 1); + } + + return 0; +} +static int +op81_w_a16(uint32_t fetchdat) +{ + uint16_t src; + uint16_t dst; + + fetch_ea_16(fetchdat); + if (cpu_mod != 3) + SEG_CHECK_WRITE(cpu_state.ea_seg); + src = getword(); + if (cpu_state.abrt) + return 1; + ARITH_MULTI(w, 16); + if ((rmdat & 0x38) == 0x38) { + PREFETCH_RUN((cpu_mod == 3) ? timing_rr : timing_mr, 4, rmdat, (cpu_mod == 3) ? 0 : 1, 0, 0, 0, 0); + } else { + PREFETCH_RUN((cpu_mod == 3) ? timing_rr : timing_rm, 4, rmdat, (cpu_mod == 3) ? 0 : 1, 0, (cpu_mod == 3) ? 0 : 1, 0, 0); + } + + return 0; +} +static int +op81_w_a32(uint32_t fetchdat) +{ + uint16_t src; + uint16_t dst; + + fetch_ea_32(fetchdat); + if (cpu_mod != 3) + SEG_CHECK_WRITE(cpu_state.ea_seg); + src = getword(); + if (cpu_state.abrt) + return 1; + ARITH_MULTI(w, 16); + if ((rmdat & 0x38) == 0x38) { + PREFETCH_RUN((cpu_mod == 3) ? timing_rr : timing_mr, 4, rmdat, (cpu_mod == 3) ? 0 : 1, 0, 0, 0, 1); + } else { + PREFETCH_RUN((cpu_mod == 3) ? timing_rr : timing_rm, 4, rmdat, (cpu_mod == 3) ? 0 : 1, 0, (cpu_mod == 3) ? 0 : 1, 0, 1); + } + + return 0; +} +static int +op81_l_a16(uint32_t fetchdat) +{ + uint32_t src; + uint32_t dst; + + fetch_ea_16(fetchdat); + if (cpu_mod != 3) + SEG_CHECK_WRITE(cpu_state.ea_seg); + src = getlong(); + if (cpu_state.abrt) + return 1; + ARITH_MULTI(l, 32); + if ((rmdat & 0x38) == 0x38) { + PREFETCH_RUN((cpu_mod == 3) ? timing_rr : timing_mr, 6, rmdat, 0, (cpu_mod == 3) ? 0 : 1, 0, 0, 0); + } else { + PREFETCH_RUN((cpu_mod == 3) ? timing_rr : timing_rm, 6, rmdat, 0, (cpu_mod == 3) ? 0 : 1, 0, (cpu_mod == 3) ? 0 : 1, 0); + } + + return 0; +} +static int +op81_l_a32(uint32_t fetchdat) +{ + uint32_t src; + uint32_t dst; + + fetch_ea_32(fetchdat); + if (cpu_mod != 3) + SEG_CHECK_WRITE(cpu_state.ea_seg); + src = getlong(); + if (cpu_state.abrt) + return 1; + ARITH_MULTI(l, 32); + if ((rmdat & 0x38) == 0x38) { + PREFETCH_RUN((cpu_mod == 3) ? timing_rr : timing_mr, 6, rmdat, 0, (cpu_mod == 3) ? 0 : 1, 0, 0, 1); + } else { + PREFETCH_RUN((cpu_mod == 3) ? timing_rr : timing_rm, 6, rmdat, 0, (cpu_mod == 3) ? 0 : 1, 0, (cpu_mod == 3) ? 0 : 1, 1); + } + + return 0; +} + +static int +op83_w_a16(uint32_t fetchdat) +{ + uint16_t src; + uint16_t dst; + + fetch_ea_16(fetchdat); + if (cpu_mod != 3) + SEG_CHECK_WRITE(cpu_state.ea_seg); + src = getbyte(); + if (cpu_state.abrt) + return 1; + if (src & 0x80) + src |= 0xff00; + ARITH_MULTI(w, 16); + if ((rmdat & 0x38) == 0x38) { + PREFETCH_RUN((cpu_mod == 3) ? timing_rr : timing_mr, 3, rmdat, (cpu_mod == 3) ? 0 : 1, 0, 0, 0, 0); + } else { + PREFETCH_RUN((cpu_mod == 3) ? timing_rr : timing_rm, 3, rmdat, (cpu_mod == 3) ? 0 : 1, 0, (cpu_mod == 3) ? 0 : 1, 0, 0); + } + + return 0; +} +static int +op83_w_a32(uint32_t fetchdat) +{ + uint16_t src; + uint16_t dst; + + fetch_ea_32(fetchdat); + if (cpu_mod != 3) + SEG_CHECK_WRITE(cpu_state.ea_seg); + src = getbyte(); + if (cpu_state.abrt) + return 1; + if (src & 0x80) + src |= 0xff00; + ARITH_MULTI(w, 16); + if ((rmdat & 0x38) == 0x38) { + PREFETCH_RUN((cpu_mod == 3) ? timing_rr : timing_mr, 3, rmdat, (cpu_mod == 3) ? 0 : 1, 0, 0, 0, 1); + } else { + PREFETCH_RUN((cpu_mod == 3) ? timing_rr : timing_rm, 3, rmdat, (cpu_mod == 3) ? 0 : 1, 0, (cpu_mod == 3) ? 0 : 1, 0, 1); + } + + return 0; +} + +static int +op83_l_a16(uint32_t fetchdat) +{ + uint32_t src; + uint32_t dst; + + fetch_ea_16(fetchdat); + if (cpu_mod != 3) + SEG_CHECK_WRITE(cpu_state.ea_seg); + src = getbyte(); + if (cpu_state.abrt) + return 1; + if (src & 0x80) + src |= 0xffffff00; + ARITH_MULTI(l, 32); + if ((rmdat & 0x38) == 0x38) { + PREFETCH_RUN((cpu_mod == 3) ? timing_rr : timing_mr, 3, rmdat, 0, (cpu_mod == 3) ? 0 : 1, 0, 0, 0); + } else { + PREFETCH_RUN((cpu_mod == 3) ? timing_rr : timing_rm, 3, rmdat, 0, (cpu_mod == 3) ? 0 : 1, 0, (cpu_mod == 3) ? 0 : 1, 0); + } + + return 0; +} +static int +op83_l_a32(uint32_t fetchdat) +{ + uint32_t src; + uint32_t dst; + + fetch_ea_32(fetchdat); + if (cpu_mod != 3) + SEG_CHECK_WRITE(cpu_state.ea_seg); + src = getbyte(); + if (cpu_state.abrt) + return 1; + if (src & 0x80) + src |= 0xffffff00; + ARITH_MULTI(l, 32); + if ((rmdat & 0x38) == 0x38) { + PREFETCH_RUN((cpu_mod == 3) ? timing_rr : timing_mr, 3, rmdat, 0, (cpu_mod == 3) ? 0 : 1, 0, 0, 1); + } else { + PREFETCH_RUN((cpu_mod == 3) ? timing_rr : timing_rm, 3, rmdat, 0, (cpu_mod == 3) ? 0 : 1, 0, (cpu_mod == 3) ? 0 : 1, 1); + } + + return 0; +} diff --git a/src/cpu/x86_ops_atomic.h b/src/cpu/x86_ops_atomic.h index 13b672e31..43a3708e0 100644 --- a/src/cpu/x86_ops_atomic.h +++ b/src/cpu/x86_ops_atomic.h @@ -1,227 +1,329 @@ -static int opCMPXCHG_b_a16(uint32_t fetchdat) +static int +opCMPXCHG_b_a16(uint32_t fetchdat) { - uint8_t temp, temp2 = AL; - fetch_ea_16(fetchdat); - SEG_CHECK_WRITE(cpu_state.ea_seg); - temp = geteab(); if (cpu_state.abrt) return 1; - if (AL == temp) seteab(getr8(cpu_reg)); - else AL = temp; - if (cpu_state.abrt) return 1; - setsub8(temp2, temp); - CLOCK_CYCLES((cpu_mod == 3) ? 6 : 10); - return 0; + uint8_t temp; + uint8_t temp2 = AL; + + fetch_ea_16(fetchdat); + SEG_CHECK_WRITE(cpu_state.ea_seg); + temp = geteab(); + if (cpu_state.abrt) + return 1; + if (AL == temp) + seteab(getr8(cpu_reg)); + else + AL = temp; + if (cpu_state.abrt) + return 1; + setsub8(temp2, temp); + CLOCK_CYCLES((cpu_mod == 3) ? 6 : 10); + return 0; } -static int opCMPXCHG_b_a32(uint32_t fetchdat) +static int +opCMPXCHG_b_a32(uint32_t fetchdat) { - uint8_t temp, temp2 = AL; - fetch_ea_32(fetchdat); - SEG_CHECK_WRITE(cpu_state.ea_seg); - temp = geteab(); if (cpu_state.abrt) return 1; - if (AL == temp) seteab(getr8(cpu_reg)); - else AL = temp; - if (cpu_state.abrt) return 1; - setsub8(temp2, temp); - CLOCK_CYCLES((cpu_mod == 3) ? 6 : 10); - return 0; + uint8_t temp; + uint8_t temp2 = AL; + + fetch_ea_32(fetchdat); + SEG_CHECK_WRITE(cpu_state.ea_seg); + temp = geteab(); + if (cpu_state.abrt) + return 1; + if (AL == temp) + seteab(getr8(cpu_reg)); + else + AL = temp; + if (cpu_state.abrt) + return 1; + setsub8(temp2, temp); + CLOCK_CYCLES((cpu_mod == 3) ? 6 : 10); + return 0; } -static int opCMPXCHG_w_a16(uint32_t fetchdat) +static int +opCMPXCHG_w_a16(uint32_t fetchdat) { - uint16_t temp, temp2 = AX; - fetch_ea_16(fetchdat); - SEG_CHECK_WRITE(cpu_state.ea_seg); - temp = geteaw(); if (cpu_state.abrt) return 1; - if (AX == temp) seteaw(cpu_state.regs[cpu_reg].w); - else AX = temp; - if (cpu_state.abrt) return 1; - setsub16(temp2, temp); - CLOCK_CYCLES((cpu_mod == 3) ? 6 : 10); - return 0; + uint16_t temp; + uint16_t temp2 = AX; + + fetch_ea_16(fetchdat); + SEG_CHECK_WRITE(cpu_state.ea_seg); + temp = geteaw(); + if (cpu_state.abrt) + return 1; + if (AX == temp) + seteaw(cpu_state.regs[cpu_reg].w); + else + AX = temp; + if (cpu_state.abrt) + return 1; + setsub16(temp2, temp); + CLOCK_CYCLES((cpu_mod == 3) ? 6 : 10); + return 0; } -static int opCMPXCHG_w_a32(uint32_t fetchdat) +static int +opCMPXCHG_w_a32(uint32_t fetchdat) { - uint16_t temp, temp2 = AX; - fetch_ea_32(fetchdat); - SEG_CHECK_WRITE(cpu_state.ea_seg); - temp = geteaw(); if (cpu_state.abrt) return 1; - if (AX == temp) seteaw(cpu_state.regs[cpu_reg].w); - else AX = temp; - if (cpu_state.abrt) return 1; - setsub16(temp2, temp); - CLOCK_CYCLES((cpu_mod == 3) ? 6 : 10); - return 0; + uint16_t temp; + uint16_t temp2 = AX; + + fetch_ea_32(fetchdat); + SEG_CHECK_WRITE(cpu_state.ea_seg); + temp = geteaw(); + if (cpu_state.abrt) + return 1; + if (AX == temp) + seteaw(cpu_state.regs[cpu_reg].w); + else + AX = temp; + if (cpu_state.abrt) + return 1; + setsub16(temp2, temp); + CLOCK_CYCLES((cpu_mod == 3) ? 6 : 10); + return 0; } -static int opCMPXCHG_l_a16(uint32_t fetchdat) +static int +opCMPXCHG_l_a16(uint32_t fetchdat) { - uint32_t temp, temp2 = EAX; - fetch_ea_16(fetchdat); - SEG_CHECK_WRITE(cpu_state.ea_seg); - temp = geteal(); if (cpu_state.abrt) return 1; - if (EAX == temp) seteal(cpu_state.regs[cpu_reg].l); - else EAX = temp; - if (cpu_state.abrt) return 1; - setsub32(temp2, temp); - CLOCK_CYCLES((cpu_mod == 3) ? 6 : 10); - return 0; + uint32_t temp; + uint32_t temp2 = EAX; + + fetch_ea_16(fetchdat); + SEG_CHECK_WRITE(cpu_state.ea_seg); + temp = geteal(); + if (cpu_state.abrt) + return 1; + if (EAX == temp) + seteal(cpu_state.regs[cpu_reg].l); + else + EAX = temp; + if (cpu_state.abrt) + return 1; + setsub32(temp2, temp); + CLOCK_CYCLES((cpu_mod == 3) ? 6 : 10); + return 0; } -static int opCMPXCHG_l_a32(uint32_t fetchdat) +static int +opCMPXCHG_l_a32(uint32_t fetchdat) { - uint32_t temp, temp2 = EAX; - fetch_ea_32(fetchdat); - SEG_CHECK_WRITE(cpu_state.ea_seg); - temp = geteal(); if (cpu_state.abrt) return 1; - if (EAX == temp) seteal(cpu_state.regs[cpu_reg].l); - else EAX = temp; - if (cpu_state.abrt) return 1; - setsub32(temp2, temp); - CLOCK_CYCLES((cpu_mod == 3) ? 6 : 10); - return 0; + uint32_t temp; + uint32_t temp2 = EAX; + + fetch_ea_32(fetchdat); + SEG_CHECK_WRITE(cpu_state.ea_seg); + temp = geteal(); + if (cpu_state.abrt) + return 1; + if (EAX == temp) + seteal(cpu_state.regs[cpu_reg].l); + else + EAX = temp; + if (cpu_state.abrt) + return 1; + setsub32(temp2, temp); + CLOCK_CYCLES((cpu_mod == 3) ? 6 : 10); + return 0; } -static int opCMPXCHG8B_a16(uint32_t fetchdat) +#ifndef OPS_286_386 +static int +opCMPXCHG8B_a16(uint32_t fetchdat) { - uint32_t temp, temp_hi, temp2 = EAX, temp2_hi = EDX; - fetch_ea_16(fetchdat); - SEG_CHECK_WRITE(cpu_state.ea_seg); - temp = geteal(); - temp_hi = readmeml(easeg, cpu_state.eaaddr + 4); if (cpu_state.abrt) return 0; - if (EAX == temp && EDX == temp_hi) - { - seteal(EBX); - writememl(easeg, cpu_state.eaaddr+4, ECX); - } - else - { - EAX = temp; - EDX = temp_hi; - } - if (cpu_state.abrt) return 0; - flags_rebuild(); - if (temp == temp2 && temp_hi == temp2_hi) - cpu_state.flags |= Z_FLAG; - else - cpu_state.flags &= ~Z_FLAG; - cycles -= (cpu_mod == 3) ? 6 : 10; + uint32_t temp; + uint32_t temp_hi; + uint32_t temp2 = EAX; + uint32_t temp2_hi = EDX; + + fetch_ea_16(fetchdat); + SEG_CHECK_WRITE(cpu_state.ea_seg); + temp = geteal(); + temp_hi = readmeml(easeg, cpu_state.eaaddr + 4); + if (cpu_state.abrt) return 0; + if (EAX == temp && EDX == temp_hi) { + seteal(EBX); + writememl(easeg, cpu_state.eaaddr + 4, ECX); + } else { + EAX = temp; + EDX = temp_hi; + } + if (cpu_state.abrt) + return 0; + flags_rebuild(); + if (temp == temp2 && temp_hi == temp2_hi) + cpu_state.flags |= Z_FLAG; + else + cpu_state.flags &= ~Z_FLAG; + cycles -= (cpu_mod == 3) ? 6 : 10; + return 0; } -static int opCMPXCHG8B_a32(uint32_t fetchdat) +static int +opCMPXCHG8B_a32(uint32_t fetchdat) { - uint32_t temp, temp_hi, temp2 = EAX, temp2_hi = EDX; - fetch_ea_32(fetchdat); - SEG_CHECK_WRITE(cpu_state.ea_seg); - temp = geteal(); - temp_hi = readmeml(easeg, cpu_state.eaaddr + 4); if (cpu_state.abrt) return 0; - if (EAX == temp && EDX == temp_hi) - { - seteal(EBX); - writememl(easeg, cpu_state.eaaddr+4, ECX); - } - else - { - EAX = temp; - EDX = temp_hi; - } - if (cpu_state.abrt) return 0; - flags_rebuild(); - if (temp == temp2 && temp_hi == temp2_hi) - cpu_state.flags |= Z_FLAG; - else - cpu_state.flags &= ~Z_FLAG; - cycles -= (cpu_mod == 3) ? 6 : 10; + uint32_t temp; + uint32_t temp_hi; + uint32_t temp2 = EAX; + uint32_t temp2_hi = EDX; + + fetch_ea_32(fetchdat); + SEG_CHECK_WRITE(cpu_state.ea_seg); + temp = geteal(); + temp_hi = readmeml(easeg, cpu_state.eaaddr + 4); + if (cpu_state.abrt) return 0; + if (EAX == temp && EDX == temp_hi) { + seteal(EBX); + writememl(easeg, cpu_state.eaaddr + 4, ECX); + } else { + EAX = temp; + EDX = temp_hi; + } + if (cpu_state.abrt) + return 0; + flags_rebuild(); + if (temp == temp2 && temp_hi == temp2_hi) + cpu_state.flags |= Z_FLAG; + else + cpu_state.flags &= ~Z_FLAG; + cycles -= (cpu_mod == 3) ? 6 : 10; + return 0; } +#endif /* dest = eab, src = r8 */ -static int opXADD_b_a16(uint32_t fetchdat) +static int +opXADD_b_a16(uint32_t fetchdat) { - uint8_t temp; - uint8_t src, dest; - fetch_ea_16(fetchdat); - SEG_CHECK_WRITE(cpu_state.ea_seg); - src = getr8(cpu_reg); - dest = geteab(); if (cpu_state.abrt) return 1; - temp = src + dest; - seteab(temp); if (cpu_state.abrt) return 1; - setadd8(src, dest); - setr8(cpu_reg, dest); - CLOCK_CYCLES((cpu_mod == 3) ? 3 : 4); - return 0; + uint8_t temp; + uint8_t src; + uint8_t dest; + + fetch_ea_16(fetchdat); + SEG_CHECK_WRITE(cpu_state.ea_seg); + src = getr8(cpu_reg); + dest = geteab(); + if (cpu_state.abrt) + return 1; + temp = src + dest; + seteab(temp); + if (cpu_state.abrt) + return 1; + setadd8(src, dest); + setr8(cpu_reg, dest); + CLOCK_CYCLES((cpu_mod == 3) ? 3 : 4); + return 0; } -static int opXADD_b_a32(uint32_t fetchdat) +static int +opXADD_b_a32(uint32_t fetchdat) { - uint8_t temp; - uint8_t src, dest; - fetch_ea_32(fetchdat); - SEG_CHECK_WRITE(cpu_state.ea_seg); - src = getr8(cpu_reg); - dest = geteab(); if (cpu_state.abrt) return 1; - temp = src + dest; - seteab(temp); if (cpu_state.abrt) return 1; - setadd8(src, dest); - setr8(cpu_reg, dest); - CLOCK_CYCLES((cpu_mod == 3) ? 3 : 4); - return 0; + uint8_t temp; + uint8_t src; + uint8_t dest; + + fetch_ea_32(fetchdat); + SEG_CHECK_WRITE(cpu_state.ea_seg); + src = getr8(cpu_reg); + dest = geteab(); + if (cpu_state.abrt) + return 1; + temp = src + dest; + seteab(temp); + if (cpu_state.abrt) + return 1; + setadd8(src, dest); + setr8(cpu_reg, dest); + CLOCK_CYCLES((cpu_mod == 3) ? 3 : 4); + return 0; } -static int opXADD_w_a16(uint32_t fetchdat) +static int +opXADD_w_a16(uint32_t fetchdat) { - uint16_t temp; - uint16_t src, dest; - fetch_ea_16(fetchdat); - SEG_CHECK_WRITE(cpu_state.ea_seg); - src = cpu_state.regs[cpu_reg].w; - dest = geteaw(); if (cpu_state.abrt) return 1; - temp = src + dest; - seteaw(temp); if (cpu_state.abrt) return 1; - setadd16(src, dest); - cpu_state.regs[cpu_reg].w = dest; - CLOCK_CYCLES((cpu_mod == 3) ? 3 : 4); - return 0; + uint16_t temp; + uint16_t src; + uint16_t dest; + + fetch_ea_16(fetchdat); + SEG_CHECK_WRITE(cpu_state.ea_seg); + src = cpu_state.regs[cpu_reg].w; + dest = geteaw(); + if (cpu_state.abrt) + return 1; + temp = src + dest; + seteaw(temp); + if (cpu_state.abrt) + return 1; + setadd16(src, dest); + cpu_state.regs[cpu_reg].w = dest; + CLOCK_CYCLES((cpu_mod == 3) ? 3 : 4); + return 0; } -static int opXADD_w_a32(uint32_t fetchdat) +static int +opXADD_w_a32(uint32_t fetchdat) { - uint16_t temp; - uint16_t src, dest; - fetch_ea_32(fetchdat); - SEG_CHECK_WRITE(cpu_state.ea_seg); - src = cpu_state.regs[cpu_reg].w; - dest = geteaw(); if (cpu_state.abrt) return 1; - temp = src + dest; - seteaw(temp); if (cpu_state.abrt) return 1; - setadd16(src, dest); - cpu_state.regs[cpu_reg].w = dest; - CLOCK_CYCLES((cpu_mod == 3) ? 3 : 4); - return 0; + uint16_t temp; + uint16_t src; + uint16_t dest; + + fetch_ea_32(fetchdat); + SEG_CHECK_WRITE(cpu_state.ea_seg); + src = cpu_state.regs[cpu_reg].w; + dest = geteaw(); + if (cpu_state.abrt) + return 1; + temp = src + dest; + seteaw(temp); + if (cpu_state.abrt) + return 1; + setadd16(src, dest); + cpu_state.regs[cpu_reg].w = dest; + CLOCK_CYCLES((cpu_mod == 3) ? 3 : 4); + return 0; } -static int opXADD_l_a16(uint32_t fetchdat) +static int +opXADD_l_a16(uint32_t fetchdat) { - uint32_t temp; - uint32_t src, dest; - fetch_ea_16(fetchdat); - SEG_CHECK_WRITE(cpu_state.ea_seg); - src = cpu_state.regs[cpu_reg].l; - dest = geteal(); if (cpu_state.abrt) return 1; - temp = src + dest; - seteal(temp); if (cpu_state.abrt) return 1; - setadd32(src, dest); - cpu_state.regs[cpu_reg].l = dest; - CLOCK_CYCLES((cpu_mod == 3) ? 3 : 4); - return 0; + uint32_t temp; + uint32_t src; + uint32_t dest; + + fetch_ea_16(fetchdat); + SEG_CHECK_WRITE(cpu_state.ea_seg); + src = cpu_state.regs[cpu_reg].l; + dest = geteal(); + if (cpu_state.abrt) + return 1; + temp = src + dest; + seteal(temp); + if (cpu_state.abrt) + return 1; + setadd32(src, dest); + cpu_state.regs[cpu_reg].l = dest; + CLOCK_CYCLES((cpu_mod == 3) ? 3 : 4); + return 0; } -static int opXADD_l_a32(uint32_t fetchdat) +static int +opXADD_l_a32(uint32_t fetchdat) { - uint32_t temp; - uint32_t src, dest; - fetch_ea_32(fetchdat); - SEG_CHECK_WRITE(cpu_state.ea_seg); - src = cpu_state.regs[cpu_reg].l; - dest = geteal(); if (cpu_state.abrt) return 1; - temp = src + dest; - seteal(temp); if (cpu_state.abrt) return 1; - setadd32(src, dest); - cpu_state.regs[cpu_reg].l = dest; - CLOCK_CYCLES((cpu_mod == 3) ? 3 : 4); - return 0; + uint32_t temp; + uint32_t src; + uint32_t dest; + + fetch_ea_32(fetchdat); + SEG_CHECK_WRITE(cpu_state.ea_seg); + src = cpu_state.regs[cpu_reg].l; + dest = geteal(); + if (cpu_state.abrt) + return 1; + temp = src + dest; + seteal(temp); + if (cpu_state.abrt) + return 1; + setadd32(src, dest); + cpu_state.regs[cpu_reg].l = dest; + CLOCK_CYCLES((cpu_mod == 3) ? 3 : 4); + return 0; } diff --git a/src/cpu/x86_ops_bcd.h b/src/cpu/x86_ops_bcd.h index 7749e9f1b..b4779ab3e 100644 --- a/src/cpu/x86_ops_bcd.h +++ b/src/cpu/x86_ops_bcd.h @@ -1,129 +1,136 @@ -static int opAAA(uint32_t fetchdat) +static int +opAAA(uint32_t fetchdat) { - flags_rebuild(); - if ((cpu_state.flags & A_FLAG) || ((AL & 0xF) > 9)) - { - /* On 286, it's indeed AX - behavior difference from 808x. */ - AX += 6; - AH++; - cpu_state.flags |= (A_FLAG | C_FLAG); - } - else - cpu_state.flags &= ~(A_FLAG | C_FLAG); - AL &= 0xF; - CLOCK_CYCLES(is486 ? 3 : 4); - PREFETCH_RUN(is486 ? 3 : 4, 1, -1, 0,0,0,0, 0); - return 0; + flags_rebuild(); + if ((cpu_state.flags & A_FLAG) || ((AL & 0xF) > 9)) { + /* On 286, it's indeed AX - behavior difference from 808x. */ + AX += 6; + AH++; + cpu_state.flags |= (A_FLAG | C_FLAG); + } else + cpu_state.flags &= ~(A_FLAG | C_FLAG); + AL &= 0xF; + CLOCK_CYCLES(is486 ? 3 : 4); + PREFETCH_RUN(is486 ? 3 : 4, 1, -1, 0, 0, 0, 0, 0); + return 0; } -static int opAAD(uint32_t fetchdat) +static int +opAAD(uint32_t fetchdat) { - int base = getbytef(); - if (!cpu_isintel) base = 10; - AL = (AH * base) + AL; - AH = 0; - setznp16(AX); - CLOCK_CYCLES((is486) ? 14 : 19); - PREFETCH_RUN(is486 ? 14 : 19, 2, -1, 0,0,0,0, 0); - return 0; + int base = getbytef(); + + if (!cpu_isintel) + base = 10; + AL = (AH * base) + AL; + AH = 0; + setznp16(AX); + CLOCK_CYCLES((is486) ? 14 : 19); + PREFETCH_RUN(is486 ? 14 : 19, 2, -1, 0, 0, 0, 0, 0); + return 0; } -static int opAAM(uint32_t fetchdat) +static int +opAAM(uint32_t fetchdat) { - int base = getbytef(); - if (!base || !cpu_isintel) base = 10; - AH = AL / base; - AL %= base; - setznp16(AX); - CLOCK_CYCLES((is486) ? 15 : 17); - PREFETCH_RUN(is486 ? 15 : 17, 2, -1, 0,0,0,0, 0); - return 0; + int base = getbytef(); + + if (!base || !cpu_isintel) + base = 10; + AH = AL / base; + AL %= base; + setznp16(AX); + CLOCK_CYCLES((is486) ? 15 : 17); + PREFETCH_RUN(is486 ? 15 : 17, 2, -1, 0, 0, 0, 0, 0); + return 0; } -static int opAAS(uint32_t fetchdat) +static int +opAAS(uint32_t fetchdat) { - flags_rebuild(); - if ((cpu_state.flags & A_FLAG) || ((AL & 0xF) > 9)) - { - /* On 286, it's indeed AX - behavior difference from 808x. */ - AX -= 6; - AH--; - cpu_state.flags |= (A_FLAG | C_FLAG); - } - else - cpu_state.flags &= ~(A_FLAG | C_FLAG); - AL &= 0xF; - CLOCK_CYCLES(is486 ? 3 : 4); - PREFETCH_RUN(is486 ? 3 : 4, 1, -1, 0,0,0,0, 0); - return 0; + flags_rebuild(); + if ((cpu_state.flags & A_FLAG) || ((AL & 0xF) > 9)) { + /* On 286, it's indeed AX - behavior difference from 808x. */ + AX -= 6; + AH--; + cpu_state.flags |= (A_FLAG | C_FLAG); + } else + cpu_state.flags &= ~(A_FLAG | C_FLAG); + AL &= 0xF; + CLOCK_CYCLES(is486 ? 3 : 4); + PREFETCH_RUN(is486 ? 3 : 4, 1, -1, 0, 0, 0, 0, 0); + return 0; } -static int opDAA(uint32_t fetchdat) +static int +opDAA(uint32_t fetchdat) { - uint16_t tempw, old_AL, old_CF; - - flags_rebuild(); - old_AL = AL; - old_CF = cpu_state.flags & C_FLAG; - cpu_state.flags &= ~C_FLAG; + uint16_t tempw; + uint16_t old_AL; + uint16_t old_CF; - if (((AL & 0xf) > 9) || (cpu_state.flags & A_FLAG)) { - int tempi = ((uint16_t)AL) + 6; - AL += 6; - if (old_CF || (tempi & 0x100)) - cpu_state.flags |= C_FLAG; - cpu_state.flags |= A_FLAG; - } else - cpu_state.flags &= ~A_FLAG; + flags_rebuild(); + old_AL = AL; + old_CF = cpu_state.flags & C_FLAG; + cpu_state.flags &= ~C_FLAG; - if ((old_AL > 0x99) || old_CF) - { - AL += 0x60; - cpu_state.flags |= C_FLAG; - } else - cpu_state.flags &= ~C_FLAG; + if (((AL & 0xf) > 9) || (cpu_state.flags & A_FLAG)) { + int tempi = ((uint16_t) AL) + 6; + AL += 6; + if (old_CF || (tempi & 0x100)) + cpu_state.flags |= C_FLAG; + cpu_state.flags |= A_FLAG; + } else + cpu_state.flags &= ~A_FLAG; - tempw = cpu_state.flags & (C_FLAG | A_FLAG); - setznp8(AL); - flags_rebuild(); - cpu_state.flags = (cpu_state.flags & ~(C_FLAG | A_FLAG)) | tempw; - CLOCK_CYCLES(4); - PREFETCH_RUN(4, 1, -1, 0,0,0,0, 0); - - return 0; + if ((old_AL > 0x99) || old_CF) { + AL += 0x60; + cpu_state.flags |= C_FLAG; + } else + cpu_state.flags &= ~C_FLAG; + + tempw = cpu_state.flags & (C_FLAG | A_FLAG); + setznp8(AL); + flags_rebuild(); + cpu_state.flags = (cpu_state.flags & ~(C_FLAG | A_FLAG)) | tempw; + CLOCK_CYCLES(4); + PREFETCH_RUN(4, 1, -1, 0, 0, 0, 0, 0); + + return 0; } -static int opDAS(uint32_t fetchdat) +static int +opDAS(uint32_t fetchdat) { - uint16_t tempw, old_AL, old_CF; + uint16_t tempw; + uint16_t old_AL; + uint16_t old_CF; - flags_rebuild(); - old_AL = AL; - old_CF = cpu_state.flags & C_FLAG; - cpu_state.flags &= ~C_FLAG; + flags_rebuild(); + old_AL = AL; + old_CF = cpu_state.flags & C_FLAG; + cpu_state.flags &= ~C_FLAG; - if (((AL & 0xf) > 9) || (cpu_state.flags & A_FLAG)) - { - int tempi = ((uint16_t)AL) - 6; - AL -= 6; - if (old_CF || (tempi & 0x100)) - cpu_state.flags |= C_FLAG; - cpu_state.flags |= A_FLAG; - } else - cpu_state.flags &= ~A_FLAG; + if (((AL & 0xf) > 9) || (cpu_state.flags & A_FLAG)) { + int tempi = ((uint16_t) AL) - 6; + AL -= 6; + if (old_CF || (tempi & 0x100)) + cpu_state.flags |= C_FLAG; + cpu_state.flags |= A_FLAG; + } else + cpu_state.flags &= ~A_FLAG; - if ((old_AL > 0x99) || old_CF) - { - AL -= 0x60; - cpu_state.flags |= C_FLAG; - } + if ((old_AL > 0x99) || old_CF) { + AL -= 0x60; + cpu_state.flags |= C_FLAG; + } - tempw = cpu_state.flags & (C_FLAG | A_FLAG); - setznp8(AL); - flags_rebuild(); - cpu_state.flags = (cpu_state.flags & ~(C_FLAG | A_FLAG)) | tempw; - CLOCK_CYCLES(4); - PREFETCH_RUN(4, 1, -1, 0,0,0,0, 0); - - return 0; + tempw = cpu_state.flags & (C_FLAG | A_FLAG); + setznp8(AL); + flags_rebuild(); + cpu_state.flags = (cpu_state.flags & ~(C_FLAG | A_FLAG)) | tempw; + CLOCK_CYCLES(4); + PREFETCH_RUN(4, 1, -1, 0, 0, 0, 0, 0); + + return 0; } diff --git a/src/cpu/x86_ops_bit.h b/src/cpu/x86_ops_bit.h index df2d48619..b72142b5a 100644 --- a/src/cpu/x86_ops_bit.h +++ b/src/cpu/x86_ops_bit.h @@ -1,328 +1,418 @@ -static int opBT_w_r_a16(uint32_t fetchdat) +static int +opBT_w_r_a16(uint32_t fetchdat) { - uint16_t temp; - - fetch_ea_16(fetchdat); - SEG_CHECK_READ(cpu_state.ea_seg); - cpu_state.eaaddr += ((cpu_state.regs[cpu_reg].w / 16) * 2); eal_r = 0; - temp = geteaw(); if (cpu_state.abrt) return 1; - flags_rebuild(); - if (temp & (1 << (cpu_state.regs[cpu_reg].w & 15))) cpu_state.flags |= C_FLAG; - else cpu_state.flags &= ~C_FLAG; - - CLOCK_CYCLES(3); - PREFETCH_RUN(3, 2, rmdat, 1,0,0,0, 0); - return 0; + uint16_t temp; + + fetch_ea_16(fetchdat); + SEG_CHECK_READ(cpu_state.ea_seg); + cpu_state.eaaddr += ((cpu_state.regs[cpu_reg].w / 16) * 2); + eal_r = 0; + temp = geteaw(); + if (cpu_state.abrt) + return 1; + flags_rebuild(); + if (temp & (1 << (cpu_state.regs[cpu_reg].w & 15))) + cpu_state.flags |= C_FLAG; + else + cpu_state.flags &= ~C_FLAG; + + CLOCK_CYCLES(3); + PREFETCH_RUN(3, 2, rmdat, 1, 0, 0, 0, 0); + return 0; } -static int opBT_w_r_a32(uint32_t fetchdat) +static int +opBT_w_r_a32(uint32_t fetchdat) { - uint16_t temp; - - fetch_ea_32(fetchdat); - SEG_CHECK_READ(cpu_state.ea_seg); - cpu_state.eaaddr += ((cpu_state.regs[cpu_reg].w / 16) * 2); eal_r = 0; - temp = geteaw(); if (cpu_state.abrt) return 1; - flags_rebuild(); - if (temp & (1 << (cpu_state.regs[cpu_reg].w & 15))) cpu_state.flags |= C_FLAG; - else cpu_state.flags &= ~C_FLAG; - - CLOCK_CYCLES(3); - PREFETCH_RUN(3, 2, rmdat, 1,0,0,0, 1); - return 0; + uint16_t temp; + + fetch_ea_32(fetchdat); + SEG_CHECK_READ(cpu_state.ea_seg); + cpu_state.eaaddr += ((cpu_state.regs[cpu_reg].w / 16) * 2); + eal_r = 0; + temp = geteaw(); + if (cpu_state.abrt) + return 1; + flags_rebuild(); + if (temp & (1 << (cpu_state.regs[cpu_reg].w & 15))) + cpu_state.flags |= C_FLAG; + else + cpu_state.flags &= ~C_FLAG; + + CLOCK_CYCLES(3); + PREFETCH_RUN(3, 2, rmdat, 1, 0, 0, 0, 1); + return 0; } -static int opBT_l_r_a16(uint32_t fetchdat) +static int +opBT_l_r_a16(uint32_t fetchdat) { - uint32_t temp; - - fetch_ea_16(fetchdat); - SEG_CHECK_READ(cpu_state.ea_seg); - cpu_state.eaaddr += ((cpu_state.regs[cpu_reg].l / 32) * 4); eal_r = 0; - temp = geteal(); if (cpu_state.abrt) return 1; - flags_rebuild(); - if (temp & (1 << (cpu_state.regs[cpu_reg].l & 31))) cpu_state.flags |= C_FLAG; - else cpu_state.flags &= ~C_FLAG; - - CLOCK_CYCLES(3); - PREFETCH_RUN(3, 2, rmdat, 0,1,0,0, 0); - return 0; + uint32_t temp; + + fetch_ea_16(fetchdat); + SEG_CHECK_READ(cpu_state.ea_seg); + cpu_state.eaaddr += ((cpu_state.regs[cpu_reg].l / 32) * 4); + eal_r = 0; + temp = geteal(); + if (cpu_state.abrt) + return 1; + flags_rebuild(); + if (temp & (1 << (cpu_state.regs[cpu_reg].l & 31))) + cpu_state.flags |= C_FLAG; + else + cpu_state.flags &= ~C_FLAG; + + CLOCK_CYCLES(3); + PREFETCH_RUN(3, 2, rmdat, 0, 1, 0, 0, 0); + return 0; } -static int opBT_l_r_a32(uint32_t fetchdat) +static int +opBT_l_r_a32(uint32_t fetchdat) { - uint32_t temp; - - fetch_ea_32(fetchdat); - SEG_CHECK_READ(cpu_state.ea_seg); - cpu_state.eaaddr += ((cpu_state.regs[cpu_reg].l / 32) * 4); eal_r = 0; - temp = geteal(); if (cpu_state.abrt) return 1; - flags_rebuild(); - if (temp & (1 << (cpu_state.regs[cpu_reg].l & 31))) cpu_state.flags |= C_FLAG; - else cpu_state.flags &= ~C_FLAG; - - CLOCK_CYCLES(3); - PREFETCH_RUN(3, 2, rmdat, 0,1,0,0, 1); - return 0; + uint32_t temp; + + fetch_ea_32(fetchdat); + SEG_CHECK_READ(cpu_state.ea_seg); + cpu_state.eaaddr += ((cpu_state.regs[cpu_reg].l / 32) * 4); + eal_r = 0; + temp = geteal(); + if (cpu_state.abrt) + return 1; + flags_rebuild(); + if (temp & (1 << (cpu_state.regs[cpu_reg].l & 31))) + cpu_state.flags |= C_FLAG; + else + cpu_state.flags &= ~C_FLAG; + + CLOCK_CYCLES(3); + PREFETCH_RUN(3, 2, rmdat, 0, 1, 0, 0, 1); + return 0; } -#define opBT(name, operation) \ - static int opBT ## name ## _w_r_a16(uint32_t fetchdat) \ - { \ - int tempc; \ - uint16_t temp; \ - \ - fetch_ea_16(fetchdat); \ - if (cpu_mod != 3) \ - SEG_CHECK_WRITE(cpu_state.ea_seg); \ - cpu_state.eaaddr += ((cpu_state.regs[cpu_reg].w / 16) * 2); eal_r = eal_w = 0; \ - temp = geteaw(); if (cpu_state.abrt) return 1; \ - tempc = (temp & (1 << (cpu_state.regs[cpu_reg].w & 15))) ? 1 : 0; \ - temp operation (1 << (cpu_state.regs[cpu_reg].w & 15)); \ - seteaw(temp); if (cpu_state.abrt) return 1; \ - flags_rebuild(); \ - if (tempc) cpu_state.flags |= C_FLAG; \ - else cpu_state.flags &= ~C_FLAG; \ - \ - CLOCK_CYCLES(6); \ - PREFETCH_RUN(6, 2, rmdat, 1,0,1,0, 0); \ - return 0; \ - } \ - static int opBT ## name ## _w_r_a32(uint32_t fetchdat) \ - { \ - int tempc; \ - uint16_t temp; \ - \ - fetch_ea_32(fetchdat); \ - if (cpu_mod != 3) \ - SEG_CHECK_WRITE(cpu_state.ea_seg); \ - cpu_state.eaaddr += ((cpu_state.regs[cpu_reg].w / 16) * 2); eal_r = eal_w = 0; \ - temp = geteaw(); if (cpu_state.abrt) return 1; \ - tempc = (temp & (1 << (cpu_state.regs[cpu_reg].w & 15))) ? 1 : 0; \ - temp operation (1 << (cpu_state.regs[cpu_reg].w & 15)); \ - seteaw(temp); if (cpu_state.abrt) return 1; \ - flags_rebuild(); \ - if (tempc) cpu_state.flags |= C_FLAG; \ - else cpu_state.flags &= ~C_FLAG; \ - \ - CLOCK_CYCLES(6); \ - PREFETCH_RUN(6, 2, rmdat, 1,0,1,0, 1); \ - return 0; \ - } \ - static int opBT ## name ## _l_r_a16(uint32_t fetchdat) \ - { \ - int tempc; \ - uint32_t temp; \ - \ - fetch_ea_16(fetchdat); \ - if (cpu_mod != 3) \ - SEG_CHECK_WRITE(cpu_state.ea_seg); \ - cpu_state.eaaddr += ((cpu_state.regs[cpu_reg].l / 32) * 4); eal_r = eal_w = 0; \ - temp = geteal(); if (cpu_state.abrt) return 1; \ - tempc = (temp & (1 << (cpu_state.regs[cpu_reg].l & 31))) ? 1 : 0; \ - temp operation (1 << (cpu_state.regs[cpu_reg].l & 31)); \ - seteal(temp); if (cpu_state.abrt) return 1; \ - flags_rebuild(); \ - if (tempc) cpu_state.flags |= C_FLAG; \ - else cpu_state.flags &= ~C_FLAG; \ - \ - CLOCK_CYCLES(6); \ - PREFETCH_RUN(6, 2, rmdat, 0,1,0,1, 0); \ - return 0; \ - } \ - static int opBT ## name ## _l_r_a32(uint32_t fetchdat) \ - { \ - int tempc; \ - uint32_t temp; \ - \ - fetch_ea_32(fetchdat); \ - if (cpu_mod != 3) \ - SEG_CHECK_WRITE(cpu_state.ea_seg); \ - cpu_state.eaaddr += ((cpu_state.regs[cpu_reg].l / 32) * 4); eal_r = eal_w = 0; \ - temp = geteal(); if (cpu_state.abrt) return 1; \ - tempc = (temp & (1 << (cpu_state.regs[cpu_reg].l & 31))) ? 1 : 0; \ - temp operation (1 << (cpu_state.regs[cpu_reg].l & 31)); \ - seteal(temp); if (cpu_state.abrt) return 1; \ - flags_rebuild(); \ - if (tempc) cpu_state.flags |= C_FLAG; \ - else cpu_state.flags &= ~C_FLAG; \ - \ - CLOCK_CYCLES(6); \ - PREFETCH_RUN(6, 2, rmdat, 0,1,0,1, 1); \ - return 0; \ - } +#define opBT(name, operation) \ + static int opBT##name##_w_r_a16(uint32_t fetchdat) \ + { \ + int tempc; \ + uint16_t temp; \ + \ + fetch_ea_16(fetchdat); \ + if (cpu_mod != 3) \ + SEG_CHECK_WRITE(cpu_state.ea_seg); \ + cpu_state.eaaddr += ((cpu_state.regs[cpu_reg].w / 16) * 2); \ + eal_r = eal_w = 0; \ + temp = geteaw(); \ + if (cpu_state.abrt) \ + return 1; \ + tempc = (temp & (1 << (cpu_state.regs[cpu_reg].w & 15))) ? 1 : 0; \ + temp operation(1 << (cpu_state.regs[cpu_reg].w & 15)); \ + seteaw(temp); \ + if (cpu_state.abrt) \ + return 1; \ + flags_rebuild(); \ + if (tempc) \ + cpu_state.flags |= C_FLAG; \ + else \ + cpu_state.flags &= ~C_FLAG; \ + \ + CLOCK_CYCLES(6); \ + PREFETCH_RUN(6, 2, rmdat, 1, 0, 1, 0, 0); \ + return 0; \ + } \ + static int opBT##name##_w_r_a32(uint32_t fetchdat) \ + { \ + int tempc; \ + uint16_t temp; \ + \ + fetch_ea_32(fetchdat); \ + if (cpu_mod != 3) \ + SEG_CHECK_WRITE(cpu_state.ea_seg); \ + cpu_state.eaaddr += ((cpu_state.regs[cpu_reg].w / 16) * 2); \ + eal_r = eal_w = 0; \ + temp = geteaw(); \ + if (cpu_state.abrt) \ + return 1; \ + tempc = (temp & (1 << (cpu_state.regs[cpu_reg].w & 15))) ? 1 : 0; \ + temp operation(1 << (cpu_state.regs[cpu_reg].w & 15)); \ + seteaw(temp); \ + if (cpu_state.abrt) \ + return 1; \ + flags_rebuild(); \ + if (tempc) \ + cpu_state.flags |= C_FLAG; \ + else \ + cpu_state.flags &= ~C_FLAG; \ + \ + CLOCK_CYCLES(6); \ + PREFETCH_RUN(6, 2, rmdat, 1, 0, 1, 0, 1); \ + return 0; \ + } \ + static int opBT##name##_l_r_a16(uint32_t fetchdat) \ + { \ + int tempc; \ + uint32_t temp; \ + \ + fetch_ea_16(fetchdat); \ + if (cpu_mod != 3) \ + SEG_CHECK_WRITE(cpu_state.ea_seg); \ + cpu_state.eaaddr += ((cpu_state.regs[cpu_reg].l / 32) * 4); \ + eal_r = eal_w = 0; \ + temp = geteal(); \ + if (cpu_state.abrt) \ + return 1; \ + tempc = (temp & (1 << (cpu_state.regs[cpu_reg].l & 31))) ? 1 : 0; \ + temp operation(1 << (cpu_state.regs[cpu_reg].l & 31)); \ + seteal(temp); \ + if (cpu_state.abrt) \ + return 1; \ + flags_rebuild(); \ + if (tempc) \ + cpu_state.flags |= C_FLAG; \ + else \ + cpu_state.flags &= ~C_FLAG; \ + \ + CLOCK_CYCLES(6); \ + PREFETCH_RUN(6, 2, rmdat, 0, 1, 0, 1, 0); \ + return 0; \ + } \ + static int opBT##name##_l_r_a32(uint32_t fetchdat) \ + { \ + int tempc; \ + uint32_t temp; \ + \ + fetch_ea_32(fetchdat); \ + if (cpu_mod != 3) \ + SEG_CHECK_WRITE(cpu_state.ea_seg); \ + cpu_state.eaaddr += ((cpu_state.regs[cpu_reg].l / 32) * 4); \ + eal_r = eal_w = 0; \ + temp = geteal(); \ + if (cpu_state.abrt) \ + return 1; \ + tempc = (temp & (1 << (cpu_state.regs[cpu_reg].l & 31))) ? 1 : 0; \ + temp operation(1 << (cpu_state.regs[cpu_reg].l & 31)); \ + seteal(temp); \ + if (cpu_state.abrt) \ + return 1; \ + flags_rebuild(); \ + if (tempc) \ + cpu_state.flags |= C_FLAG; \ + else \ + cpu_state.flags &= ~C_FLAG; \ + \ + CLOCK_CYCLES(6); \ + PREFETCH_RUN(6, 2, rmdat, 0, 1, 0, 1, 1); \ + return 0; \ + } +// clang-format off opBT(C, ^=) -opBT(R, &=~) +opBT(R, &= ~) opBT(S, |=) + // clang-format on -static int opBA_w_a16(uint32_t fetchdat) +static int +opBA_w_a16(uint32_t fetchdat) { - int tempc, count; - uint16_t temp; + int tempc; + int count; + uint16_t temp; - fetch_ea_16(fetchdat); - if (cpu_mod != 3) - SEG_CHECK_WRITE(cpu_state.ea_seg); + fetch_ea_16(fetchdat); + if (cpu_mod != 3) + SEG_CHECK_WRITE(cpu_state.ea_seg); - temp = geteaw(); - count = getbyte(); if (cpu_state.abrt) return 1; - tempc = temp & (1 << count); - flags_rebuild(); - switch (rmdat & 0x38) - { - case 0x20: /*BT w,imm*/ - if (tempc) cpu_state.flags |= C_FLAG; - else cpu_state.flags &= ~C_FLAG; - CLOCK_CYCLES(3); - PREFETCH_RUN(3, 3, rmdat, (cpu_mod == 3) ? 0:1,0,0,0, 0); - return 0; - case 0x28: /*BTS w,imm*/ - temp |= (1 << count); - break; - case 0x30: /*BTR w,imm*/ - temp &= ~(1 << count); - break; - case 0x38: /*BTC w,imm*/ - temp ^= (1 << count); - break; + temp = geteaw(); + count = getbyte(); + if (cpu_state.abrt) + return 1; + tempc = temp & (1 << count); + flags_rebuild(); + switch (rmdat & 0x38) { + case 0x20: /*BT w,imm*/ + if (tempc) + cpu_state.flags |= C_FLAG; + else + cpu_state.flags &= ~C_FLAG; + CLOCK_CYCLES(3); + PREFETCH_RUN(3, 3, rmdat, (cpu_mod == 3) ? 0 : 1, 0, 0, 0, 0); + return 0; + case 0x28: /*BTS w,imm*/ + temp |= (1 << count); + break; + case 0x30: /*BTR w,imm*/ + temp &= ~(1 << count); + break; + case 0x38: /*BTC w,imm*/ + temp ^= (1 << count); + break; - default: - cpu_state.pc = cpu_state.oldpc; - x86illegal(); - break; - } - seteaw(temp); if (cpu_state.abrt) return 1; - if (tempc) cpu_state.flags |= C_FLAG; - else cpu_state.flags &= ~C_FLAG; - CLOCK_CYCLES(6); - PREFETCH_RUN(6, 3, rmdat, (cpu_mod == 3) ? 0:1,0,(cpu_mod == 3) ? 0:1,0, 0); - return 0; + default: + cpu_state.pc = cpu_state.oldpc; + x86illegal(); + break; + } + seteaw(temp); + if (cpu_state.abrt) + return 1; + if (tempc) + cpu_state.flags |= C_FLAG; + else + cpu_state.flags &= ~C_FLAG; + CLOCK_CYCLES(6); + PREFETCH_RUN(6, 3, rmdat, (cpu_mod == 3) ? 0 : 1, 0, (cpu_mod == 3) ? 0 : 1, 0, 0); + return 0; } -static int opBA_w_a32(uint32_t fetchdat) +static int +opBA_w_a32(uint32_t fetchdat) { - int tempc, count; - uint16_t temp; + int tempc; + int count; + uint16_t temp; - fetch_ea_32(fetchdat); - if (cpu_mod != 3) - SEG_CHECK_WRITE(cpu_state.ea_seg); + fetch_ea_32(fetchdat); + if (cpu_mod != 3) + SEG_CHECK_WRITE(cpu_state.ea_seg); - temp = geteaw(); - count = getbyte(); if (cpu_state.abrt) return 1; - tempc = temp & (1 << count); - flags_rebuild(); - switch (rmdat & 0x38) - { - case 0x20: /*BT w,imm*/ - if (tempc) cpu_state.flags |= C_FLAG; - else cpu_state.flags &= ~C_FLAG; - CLOCK_CYCLES(3); - PREFETCH_RUN(3, 3, rmdat, (cpu_mod == 3) ? 0:1,0,0,0, 1); - return 0; - case 0x28: /*BTS w,imm*/ - temp |= (1 << count); - break; - case 0x30: /*BTR w,imm*/ - temp &= ~(1 << count); - break; - case 0x38: /*BTC w,imm*/ - temp ^= (1 << count); - break; + temp = geteaw(); + count = getbyte(); + if (cpu_state.abrt) + return 1; + tempc = temp & (1 << count); + flags_rebuild(); + switch (rmdat & 0x38) { + case 0x20: /*BT w,imm*/ + if (tempc) + cpu_state.flags |= C_FLAG; + else + cpu_state.flags &= ~C_FLAG; + CLOCK_CYCLES(3); + PREFETCH_RUN(3, 3, rmdat, (cpu_mod == 3) ? 0 : 1, 0, 0, 0, 1); + return 0; + case 0x28: /*BTS w,imm*/ + temp |= (1 << count); + break; + case 0x30: /*BTR w,imm*/ + temp &= ~(1 << count); + break; + case 0x38: /*BTC w,imm*/ + temp ^= (1 << count); + break; - default: - cpu_state.pc = cpu_state.oldpc; - x86illegal(); - break; - } - seteaw(temp); if (cpu_state.abrt) return 1; - if (tempc) cpu_state.flags |= C_FLAG; - else cpu_state.flags &= ~C_FLAG; - CLOCK_CYCLES(6); - PREFETCH_RUN(6, 3, rmdat, (cpu_mod == 3) ? 0:1,0,(cpu_mod == 3) ? 0:1,0, 0); - return 0; + default: + cpu_state.pc = cpu_state.oldpc; + x86illegal(); + break; + } + seteaw(temp); + if (cpu_state.abrt) + return 1; + if (tempc) + cpu_state.flags |= C_FLAG; + else + cpu_state.flags &= ~C_FLAG; + CLOCK_CYCLES(6); + PREFETCH_RUN(6, 3, rmdat, (cpu_mod == 3) ? 0 : 1, 0, (cpu_mod == 3) ? 0 : 1, 0, 0); + return 0; } -static int opBA_l_a16(uint32_t fetchdat) +static int +opBA_l_a16(uint32_t fetchdat) { - int tempc, count; - uint32_t temp; + int tempc; + int count; + uint32_t temp; - fetch_ea_16(fetchdat); - if (cpu_mod != 3) - SEG_CHECK_WRITE(cpu_state.ea_seg); + fetch_ea_16(fetchdat); + if (cpu_mod != 3) + SEG_CHECK_WRITE(cpu_state.ea_seg); - temp = geteal(); - count = getbyte(); if (cpu_state.abrt) return 1; - tempc = temp & (1 << count); - flags_rebuild(); - switch (rmdat & 0x38) - { - case 0x20: /*BT w,imm*/ - if (tempc) cpu_state.flags |= C_FLAG; - else cpu_state.flags &= ~C_FLAG; - CLOCK_CYCLES(3); - PREFETCH_RUN(3, 3, rmdat, 0,(cpu_mod == 3) ? 0:1,0,0, 0); - return 0; - case 0x28: /*BTS w,imm*/ - temp |= (1 << count); - break; - case 0x30: /*BTR w,imm*/ - temp &= ~(1 << count); - break; - case 0x38: /*BTC w,imm*/ - temp ^= (1 << count); - break; + temp = geteal(); + count = getbyte(); + if (cpu_state.abrt) + return 1; + tempc = temp & (1 << count); + flags_rebuild(); + switch (rmdat & 0x38) { + case 0x20: /*BT w,imm*/ + if (tempc) + cpu_state.flags |= C_FLAG; + else + cpu_state.flags &= ~C_FLAG; + CLOCK_CYCLES(3); + PREFETCH_RUN(3, 3, rmdat, 0, (cpu_mod == 3) ? 0 : 1, 0, 0, 0); + return 0; + case 0x28: /*BTS w,imm*/ + temp |= (1 << count); + break; + case 0x30: /*BTR w,imm*/ + temp &= ~(1 << count); + break; + case 0x38: /*BTC w,imm*/ + temp ^= (1 << count); + break; - default: - cpu_state.pc = cpu_state.oldpc; - x86illegal(); - break; - } - seteal(temp); if (cpu_state.abrt) return 1; - if (tempc) cpu_state.flags |= C_FLAG; - else cpu_state.flags &= ~C_FLAG; - CLOCK_CYCLES(6); - PREFETCH_RUN(6, 3, rmdat, 0,(cpu_mod == 3) ? 0:1,0,(cpu_mod == 3) ? 0:1, 0); - return 0; + default: + cpu_state.pc = cpu_state.oldpc; + x86illegal(); + break; + } + seteal(temp); + if (cpu_state.abrt) + return 1; + if (tempc) + cpu_state.flags |= C_FLAG; + else + cpu_state.flags &= ~C_FLAG; + CLOCK_CYCLES(6); + PREFETCH_RUN(6, 3, rmdat, 0, (cpu_mod == 3) ? 0 : 1, 0, (cpu_mod == 3) ? 0 : 1, 0); + return 0; } -static int opBA_l_a32(uint32_t fetchdat) +static int +opBA_l_a32(uint32_t fetchdat) { - int tempc, count; - uint32_t temp; + int tempc; + int count; + uint32_t temp; - fetch_ea_32(fetchdat); - if (cpu_mod != 3) - SEG_CHECK_WRITE(cpu_state.ea_seg); + fetch_ea_32(fetchdat); + if (cpu_mod != 3) + SEG_CHECK_WRITE(cpu_state.ea_seg); - temp = geteal(); - count = getbyte(); if (cpu_state.abrt) return 1; - tempc = temp & (1 << count); - flags_rebuild(); - switch (rmdat & 0x38) - { - case 0x20: /*BT w,imm*/ - if (tempc) cpu_state.flags |= C_FLAG; - else cpu_state.flags &= ~C_FLAG; - CLOCK_CYCLES(3); - PREFETCH_RUN(3, 3, rmdat, 0,(cpu_mod == 3) ? 0:1,0,0, 1); - return 0; - case 0x28: /*BTS w,imm*/ - temp |= (1 << count); - break; - case 0x30: /*BTR w,imm*/ - temp &= ~(1 << count); - break; - case 0x38: /*BTC w,imm*/ - temp ^= (1 << count); - break; + temp = geteal(); + count = getbyte(); + if (cpu_state.abrt) + return 1; + tempc = temp & (1 << count); + flags_rebuild(); + switch (rmdat & 0x38) { + case 0x20: /*BT w,imm*/ + if (tempc) + cpu_state.flags |= C_FLAG; + else + cpu_state.flags &= ~C_FLAG; + CLOCK_CYCLES(3); + PREFETCH_RUN(3, 3, rmdat, 0, (cpu_mod == 3) ? 0 : 1, 0, 0, 1); + return 0; + case 0x28: /*BTS w,imm*/ + temp |= (1 << count); + break; + case 0x30: /*BTR w,imm*/ + temp &= ~(1 << count); + break; + case 0x38: /*BTC w,imm*/ + temp ^= (1 << count); + break; - default: - cpu_state.pc = cpu_state.oldpc; - x86illegal(); - break; - } - seteal(temp); if (cpu_state.abrt) return 1; - if (tempc) cpu_state.flags |= C_FLAG; - else cpu_state.flags &= ~C_FLAG; - CLOCK_CYCLES(6); - PREFETCH_RUN(6, 3, rmdat, 0,(cpu_mod == 3) ? 0:1,0,(cpu_mod == 3) ? 0:1, 1); - return 0; + default: + cpu_state.pc = cpu_state.oldpc; + x86illegal(); + break; + } + seteal(temp); + if (cpu_state.abrt) + return 1; + if (tempc) + cpu_state.flags |= C_FLAG; + else + cpu_state.flags &= ~C_FLAG; + CLOCK_CYCLES(6); + PREFETCH_RUN(6, 3, rmdat, 0, (cpu_mod == 3) ? 0 : 1, 0, (cpu_mod == 3) ? 0 : 1, 1); + return 0; } diff --git a/src/cpu/x86_ops_bitscan.h b/src/cpu/x86_ops_bitscan.h index 46f0fc605..358131c1e 100644 --- a/src/cpu/x86_ops_bitscan.h +++ b/src/cpu/x86_ops_bitscan.h @@ -1,159 +1,227 @@ -#define BS_common(start, end, dir, dest, time) \ - flags_rebuild(); \ - instr_cycles = 0; \ - if (temp) \ - { \ - int c; \ - cpu_state.flags &= ~Z_FLAG; \ - for (c = start; c != end; c += dir) \ - { \ - CLOCK_CYCLES(time); \ - instr_cycles += time; \ - if (temp & (1 << c)) \ - { \ - dest = c; \ - break; \ - } \ - } \ - } \ - else \ - cpu_state.flags |= Z_FLAG; +#ifdef IS_DYNAREC +# define BS_common(start, end, dir, dest, time) \ + flags_rebuild(); \ + if (temp) { \ + int c; \ + cpu_state.flags &= ~Z_FLAG; \ + for (c = start; c != end; c += dir) { \ + CLOCK_CYCLES(time); \ + if (temp & (1 << c)) { \ + dest = c; \ + break; \ + } \ + } \ + } else \ + cpu_state.flags |= Z_FLAG; +#else +# define BS_common(start, end, dir, dest, time) \ + flags_rebuild(); \ + instr_cycles = 0; \ + if (temp) { \ + int c; \ + cpu_state.flags &= ~Z_FLAG; \ + for (c = start; c != end; c += dir) { \ + CLOCK_CYCLES(time); \ + instr_cycles += time; \ + if (temp & (1 << c)) { \ + dest = c; \ + break; \ + } \ + } \ + } else \ + cpu_state.flags |= Z_FLAG; +#endif -static int opBSF_w_a16(uint32_t fetchdat) +static int +opBSF_w_a16(uint32_t fetchdat) { - uint16_t temp; - int instr_cycles = 0; - - fetch_ea_16(fetchdat); - if (cpu_mod != 3) - SEG_CHECK_READ(cpu_state.ea_seg); - temp = geteaw(); if (cpu_state.abrt) return 1; - - BS_common(0, 16, 1, cpu_state.regs[cpu_reg].w, (is486) ? 1 : 3); - - CLOCK_CYCLES((is486) ? 6 : 10); - instr_cycles += ((is486) ? 6 : 10); - PREFETCH_RUN(instr_cycles, 2, rmdat, (cpu_mod == 3) ? 0:1,0,0,0, 0); - return 0; -} -static int opBSF_w_a32(uint32_t fetchdat) -{ - uint16_t temp; - int instr_cycles = 0; - - fetch_ea_32(fetchdat); - if (cpu_mod != 3) - SEG_CHECK_READ(cpu_state.ea_seg); - temp = geteaw(); if (cpu_state.abrt) return 1; - - BS_common(0, 16, 1, cpu_state.regs[cpu_reg].w, (is486) ? 1 : 3); - - CLOCK_CYCLES((is486) ? 6 : 10); - instr_cycles += ((is486) ? 6 : 10); - PREFETCH_RUN(instr_cycles, 2, rmdat, (cpu_mod == 3) ? 0:1,0,0,0, 1); - return 0; -} -static int opBSF_l_a16(uint32_t fetchdat) -{ - uint32_t temp; - int instr_cycles = 0; - - fetch_ea_16(fetchdat); - if (cpu_mod != 3) - SEG_CHECK_READ(cpu_state.ea_seg); - temp = geteal(); if (cpu_state.abrt) return 1; - - BS_common(0, 32, 1, cpu_state.regs[cpu_reg].l, (is486) ? 1 : 3); - - CLOCK_CYCLES((is486) ? 6 : 10); - instr_cycles += ((is486) ? 6 : 10); - PREFETCH_RUN(instr_cycles, 2, rmdat, 0,(cpu_mod == 3) ? 0:1,0,0, 0); - return 0; -} -static int opBSF_l_a32(uint32_t fetchdat) -{ - uint32_t temp; - int instr_cycles = 0; + uint16_t temp; +#ifndef IS_DYNAREC + int instr_cycles = 0; +#endif - fetch_ea_32(fetchdat); - if (cpu_mod != 3) - SEG_CHECK_READ(cpu_state.ea_seg); - temp = geteal(); if (cpu_state.abrt) return 1; - - BS_common(0, 32, 1, cpu_state.regs[cpu_reg].l, (is486) ? 1 : 3); - - CLOCK_CYCLES((is486) ? 6 : 10); - instr_cycles += ((is486) ? 6 : 10); - PREFETCH_RUN(instr_cycles, 2, rmdat, 0,(cpu_mod == 3) ? 0:1,0,0, 1); - return 0; + fetch_ea_16(fetchdat); + if (cpu_mod != 3) + SEG_CHECK_READ(cpu_state.ea_seg); + temp = geteaw(); + if (cpu_state.abrt) + return 1; + + BS_common(0, 16, 1, cpu_state.regs[cpu_reg].w, (is486) ? 1 : 3); + + CLOCK_CYCLES((is486) ? 6 : 10); +#ifndef IS_DYNAREC + instr_cycles += ((is486) ? 6 : 10); + PREFETCH_RUN(instr_cycles, 2, rmdat, (cpu_mod == 3) ? 0 : 1, 0, 0, 0, 0); +#endif + return 0; +} +static int +opBSF_w_a32(uint32_t fetchdat) +{ + uint16_t temp; +#ifndef IS_DYNAREC + int instr_cycles = 0; +#endif + + fetch_ea_32(fetchdat); + if (cpu_mod != 3) + SEG_CHECK_READ(cpu_state.ea_seg); + temp = geteaw(); + if (cpu_state.abrt) + return 1; + + BS_common(0, 16, 1, cpu_state.regs[cpu_reg].w, (is486) ? 1 : 3); + + CLOCK_CYCLES((is486) ? 6 : 10); +#ifndef IS_DYNAREC + instr_cycles += ((is486) ? 6 : 10); + PREFETCH_RUN(instr_cycles, 2, rmdat, (cpu_mod == 3) ? 0 : 1, 0, 0, 0, 1); +#endif + return 0; +} +static int +opBSF_l_a16(uint32_t fetchdat) +{ + uint32_t temp; +#ifndef IS_DYNAREC + int instr_cycles = 0; +#endif + + fetch_ea_16(fetchdat); + if (cpu_mod != 3) + SEG_CHECK_READ(cpu_state.ea_seg); + temp = geteal(); + if (cpu_state.abrt) + return 1; + + BS_common(0, 32, 1, cpu_state.regs[cpu_reg].l, (is486) ? 1 : 3); + + CLOCK_CYCLES((is486) ? 6 : 10); +#ifndef IS_DYNAREC + instr_cycles += ((is486) ? 6 : 10); + PREFETCH_RUN(instr_cycles, 2, rmdat, 0, (cpu_mod == 3) ? 0 : 1, 0, 0, 0); +#endif + return 0; +} +static int +opBSF_l_a32(uint32_t fetchdat) +{ + uint32_t temp; +#ifndef IS_DYNAREC + int instr_cycles = 0; +#endif + + fetch_ea_32(fetchdat); + if (cpu_mod != 3) + SEG_CHECK_READ(cpu_state.ea_seg); + temp = geteal(); + if (cpu_state.abrt) + return 1; + + BS_common(0, 32, 1, cpu_state.regs[cpu_reg].l, (is486) ? 1 : 3); + + CLOCK_CYCLES((is486) ? 6 : 10); +#ifndef IS_DYNAREC + instr_cycles += ((is486) ? 6 : 10); + PREFETCH_RUN(instr_cycles, 2, rmdat, 0, (cpu_mod == 3) ? 0 : 1, 0, 0, 1); +#endif + return 0; } -static int opBSR_w_a16(uint32_t fetchdat) +static int +opBSR_w_a16(uint32_t fetchdat) { - uint16_t temp; - int instr_cycles = 0; - - fetch_ea_16(fetchdat); - if (cpu_mod != 3) - SEG_CHECK_READ(cpu_state.ea_seg); - temp = geteaw(); if (cpu_state.abrt) return 1; - - BS_common(15, -1, -1, cpu_state.regs[cpu_reg].w, 3); - - CLOCK_CYCLES((is486) ? 6 : 10); - instr_cycles += ((is486) ? 6 : 10); - PREFETCH_RUN(instr_cycles, 2, rmdat, (cpu_mod == 3) ? 0:1,0,0,0, 0); - return 0; -} -static int opBSR_w_a32(uint32_t fetchdat) -{ - uint16_t temp; - int instr_cycles = 0; - - fetch_ea_32(fetchdat); - if (cpu_mod != 3) - SEG_CHECK_READ(cpu_state.ea_seg); - temp = geteaw(); if (cpu_state.abrt) return 1; - - BS_common(15, -1, -1, cpu_state.regs[cpu_reg].w, 3); - - CLOCK_CYCLES((is486) ? 6 : 10); - instr_cycles += ((is486) ? 6 : 10); - PREFETCH_RUN(instr_cycles, 2, rmdat, (cpu_mod == 3) ? 0:1,0,0,0, 1); - return 0; -} -static int opBSR_l_a16(uint32_t fetchdat) -{ - uint32_t temp; - int instr_cycles = 0; - - fetch_ea_16(fetchdat); - if (cpu_mod != 3) - SEG_CHECK_READ(cpu_state.ea_seg); - temp = geteal(); if (cpu_state.abrt) return 1; - - BS_common(31, -1, -1, cpu_state.regs[cpu_reg].l, 3); - - CLOCK_CYCLES((is486) ? 6 : 10); - instr_cycles += ((is486) ? 6 : 10); - PREFETCH_RUN(instr_cycles, 2, rmdat, 0,(cpu_mod == 3) ? 0:1,0,0, 0); - return 0; -} -static int opBSR_l_a32(uint32_t fetchdat) -{ - uint32_t temp; - int instr_cycles = 0; - - fetch_ea_32(fetchdat); - if (cpu_mod != 3) - SEG_CHECK_READ(cpu_state.ea_seg); - temp = geteal(); if (cpu_state.abrt) return 1; - - BS_common(31, -1, -1, cpu_state.regs[cpu_reg].l, 3); - - CLOCK_CYCLES((is486) ? 6 : 10); - instr_cycles += ((is486) ? 6 : 10); - PREFETCH_RUN(instr_cycles, 2, rmdat, 0,(cpu_mod == 3) ? 0:1,0,0, 1); - return 0; -} + uint16_t temp; +#ifndef IS_DYNAREC + int instr_cycles = 0; +#endif + fetch_ea_16(fetchdat); + if (cpu_mod != 3) + SEG_CHECK_READ(cpu_state.ea_seg); + temp = geteaw(); + if (cpu_state.abrt) + return 1; + + BS_common(15, -1, -1, cpu_state.regs[cpu_reg].w, 3); + + CLOCK_CYCLES((is486) ? 6 : 10); +#ifndef IS_DYNAREC + instr_cycles += ((is486) ? 6 : 10); + PREFETCH_RUN(instr_cycles, 2, rmdat, (cpu_mod == 3) ? 0 : 1, 0, 0, 0, 0); +#endif + return 0; +} +static int +opBSR_w_a32(uint32_t fetchdat) +{ + uint16_t temp; +#ifndef IS_DYNAREC + int instr_cycles = 0; +#endif + + fetch_ea_32(fetchdat); + if (cpu_mod != 3) + SEG_CHECK_READ(cpu_state.ea_seg); + temp = geteaw(); + if (cpu_state.abrt) + return 1; + + BS_common(15, -1, -1, cpu_state.regs[cpu_reg].w, 3); + + CLOCK_CYCLES((is486) ? 6 : 10); +#ifndef IS_DYNAREC + instr_cycles += ((is486) ? 6 : 10); + PREFETCH_RUN(instr_cycles, 2, rmdat, (cpu_mod == 3) ? 0 : 1, 0, 0, 0, 1); +#endif + return 0; +} +static int +opBSR_l_a16(uint32_t fetchdat) +{ + uint32_t temp; +#ifndef IS_DYNAREC + int instr_cycles = 0; +#endif + + fetch_ea_16(fetchdat); + if (cpu_mod != 3) + SEG_CHECK_READ(cpu_state.ea_seg); + temp = geteal(); + if (cpu_state.abrt) + return 1; + + BS_common(31, -1, -1, cpu_state.regs[cpu_reg].l, 3); + + CLOCK_CYCLES((is486) ? 6 : 10); +#ifndef IS_DYNAREC + instr_cycles += ((is486) ? 6 : 10); + PREFETCH_RUN(instr_cycles, 2, rmdat, 0, (cpu_mod == 3) ? 0 : 1, 0, 0, 0); +#endif + return 0; +} +static int +opBSR_l_a32(uint32_t fetchdat) +{ + uint32_t temp; +#ifndef IS_DYNAREC + int instr_cycles = 0; +#endif + + fetch_ea_32(fetchdat); + if (cpu_mod != 3) + SEG_CHECK_READ(cpu_state.ea_seg); + temp = geteal(); + if (cpu_state.abrt) + return 1; + + BS_common(31, -1, -1, cpu_state.regs[cpu_reg].l, 3); + + CLOCK_CYCLES((is486) ? 6 : 10); +#ifndef IS_DYNAREC + instr_cycles += ((is486) ? 6 : 10); + PREFETCH_RUN(instr_cycles, 2, rmdat, 0, (cpu_mod == 3) ? 0 : 1, 0, 0, 1); +#endif + return 0; +} diff --git a/src/cpu/x86_ops_call.h b/src/cpu/x86_ops_call.h index 427d504fc..9d52a2764 100644 --- a/src/cpu/x86_ops_call.h +++ b/src/cpu/x86_ops_call.h @@ -1,547 +1,883 @@ #ifdef USE_NEW_DYNAREC -#define CALL_FAR_w(new_seg, new_pc) \ - old_cs = CS; \ - old_pc = cpu_state.pc; \ - cpu_state.pc = new_pc; \ - optype = CALL; \ - cgate16 = cgate32 = 0; \ - if (msw & 1) loadcscall(new_seg, old_pc); \ - else \ - { \ - loadcs(new_seg); \ - cycles -= timing_call_rm; \ - } \ - optype = 0; \ - if (cpu_state.abrt) { cgate16 = cgate32 = 0; return 1; } \ - oldss = ss; \ - if (cgate32) \ - { \ - uint32_t old_esp = ESP; \ - PUSH_L(old_cs); if (cpu_state.abrt) { CS = old_cs; cgate16 = cgate32 = 0; return 1; } \ - PUSH_L(old_pc); if (cpu_state.abrt) { CS = old_cs; ESP = old_esp; return 1; } \ - } \ - else \ - { \ - uint32_t old_esp = ESP; \ - PUSH_W(old_cs); if (cpu_state.abrt) { CS = old_cs; cgate16 = cgate32 = 0; return 1; } \ - PUSH_W(old_pc); if (cpu_state.abrt) { CS = old_cs; ESP = old_esp; return 1; } \ +# define CALL_FAR_w(new_seg, new_pc) \ + old_cs = CS; \ + old_pc = cpu_state.pc; \ + cpu_state.pc = new_pc; \ + optype = CALL; \ + cgate16 = cgate32 = 0; \ + if (msw & 1) \ + op_loadcscall(new_seg, old_pc); \ + else { \ + op_loadcs(new_seg); \ + cycles -= timing_call_rm; \ + } \ + optype = 0; \ + if (cpu_state.abrt) { \ + cgate16 = cgate32 = 0; \ + return 1; \ + } \ + oldss = ss; \ + if (cgate32) { \ + uint32_t old_esp = ESP; \ + PUSH_L(old_cs); \ + if (cpu_state.abrt) { \ + CS = old_cs; \ + cgate16 = cgate32 = 0; \ + return 1; \ + } \ + PUSH_L(old_pc); \ + if (cpu_state.abrt) { \ + CS = old_cs; \ + ESP = old_esp; \ + return 1; \ + } \ + } else { \ + uint32_t old_esp = ESP; \ + PUSH_W(old_cs); \ + if (cpu_state.abrt) { \ + CS = old_cs; \ + cgate16 = cgate32 = 0; \ + return 1; \ + } \ + PUSH_W(old_pc); \ + if (cpu_state.abrt) { \ + CS = old_cs; \ + ESP = old_esp; \ + return 1; \ + } \ } - -#define CALL_FAR_l(new_seg, new_pc) \ - old_cs = CS; \ - old_pc = cpu_state.pc; \ - cpu_state.pc = new_pc; \ - optype = CALL; \ - cgate16 = cgate32 = 0; \ - if (msw & 1) loadcscall(new_seg, old_pc); \ - else \ - { \ - loadcs(new_seg); \ - cycles -= timing_call_rm; \ - } \ - optype = 0; \ - if (cpu_state.abrt) { cgate16 = cgate32 = 0; return 1; } \ - oldss = ss; \ - if (cgate16) \ - { \ - uint32_t old_esp = ESP; \ - PUSH_W(old_cs); if (cpu_state.abrt) { CS = old_cs; cgate16 = cgate32 = 0; return 1; } \ - PUSH_W(old_pc); if (cpu_state.abrt) { CS = old_cs; ESP = old_esp; return 1; } \ - } \ - else \ - { \ - uint32_t old_esp = ESP; \ - PUSH_L(old_cs); if (cpu_state.abrt) { CS = old_cs; cgate16 = cgate32 = 0; return 1; } \ - PUSH_L(old_pc); if (cpu_state.abrt) { CS = old_cs; ESP = old_esp; return 1; } \ + +# define CALL_FAR_l(new_seg, new_pc) \ + old_cs = CS; \ + old_pc = cpu_state.pc; \ + cpu_state.pc = new_pc; \ + optype = CALL; \ + cgate16 = cgate32 = 0; \ + if (msw & 1) \ + op_loadcscall(new_seg, old_pc); \ + else { \ + op_loadcs(new_seg); \ + cycles -= timing_call_rm; \ + } \ + optype = 0; \ + if (cpu_state.abrt) { \ + cgate16 = cgate32 = 0; \ + return 1; \ + } \ + oldss = ss; \ + if (cgate16) { \ + uint32_t old_esp = ESP; \ + PUSH_W(old_cs); \ + if (cpu_state.abrt) { \ + CS = old_cs; \ + cgate16 = cgate32 = 0; \ + return 1; \ + } \ + PUSH_W(old_pc); \ + if (cpu_state.abrt) { \ + CS = old_cs; \ + ESP = old_esp; \ + return 1; \ + } \ + } else { \ + uint32_t old_esp = ESP; \ + PUSH_L(old_cs); \ + if (cpu_state.abrt) { \ + CS = old_cs; \ + cgate16 = cgate32 = 0; \ + return 1; \ + } \ + PUSH_L(old_pc); \ + if (cpu_state.abrt) { \ + CS = old_cs; \ + ESP = old_esp; \ + return 1; \ + } \ } #else -#define CALL_FAR_w(new_seg, new_pc) \ - old_cs = CS; \ - old_pc = cpu_state.pc; \ - oxpc = cpu_state.pc; \ - cpu_state.pc = new_pc; \ - optype = CALL; \ - cgate16 = cgate32 = 0; \ - if (msw & 1) loadcscall(new_seg); \ - else \ - { \ - loadcs(new_seg); \ - cycles -= timing_call_rm; \ - } \ - optype = 0; \ - if (cpu_state.abrt) { cgate16 = cgate32 = 0; return 1; } \ - oldss = ss; \ - if (cgate32) \ - { \ - uint32_t old_esp = ESP; \ - PUSH_L(old_cs); if (cpu_state.abrt) { cgate16 = cgate32 = 0; return 1; } \ - PUSH_L(old_pc); if (cpu_state.abrt) { ESP = old_esp; return 1; } \ - } \ - else \ - { \ - uint32_t old_esp = ESP; \ - PUSH_W(old_cs); if (cpu_state.abrt) { cgate16 = cgate32 = 0; return 1; } \ - PUSH_W(old_pc); if (cpu_state.abrt) { ESP = old_esp; return 1; } \ +# define CALL_FAR_w(new_seg, new_pc) \ + old_cs = CS; \ + old_pc = cpu_state.pc; \ + oxpc = cpu_state.pc; \ + cpu_state.pc = new_pc; \ + optype = CALL; \ + cgate16 = cgate32 = 0; \ + if (msw & 1) \ + op_loadcscall(new_seg); \ + else { \ + op_loadcs(new_seg); \ + cycles -= timing_call_rm; \ + } \ + optype = 0; \ + if (cpu_state.abrt) { \ + cgate16 = cgate32 = 0; \ + return 1; \ + } \ + oldss = ss; \ + if (cgate32) { \ + uint32_t old_esp = ESP; \ + PUSH_L(old_cs); \ + if (cpu_state.abrt) { \ + cgate16 = cgate32 = 0; \ + return 1; \ + } \ + PUSH_L(old_pc); \ + if (cpu_state.abrt) { \ + ESP = old_esp; \ + return 1; \ + } \ + } else { \ + uint32_t old_esp = ESP; \ + PUSH_W(old_cs); \ + if (cpu_state.abrt) { \ + cgate16 = cgate32 = 0; \ + return 1; \ + } \ + PUSH_W(old_pc); \ + if (cpu_state.abrt) { \ + ESP = old_esp; \ + return 1; \ + } \ } - -#define CALL_FAR_l(new_seg, new_pc) \ - old_cs = CS; \ - old_pc = cpu_state.pc; \ - oxpc = cpu_state.pc; \ - cpu_state.pc = new_pc; \ - optype = CALL; \ - cgate16 = cgate32 = 0; \ - if (msw & 1) loadcscall(new_seg); \ - else \ - { \ - loadcs(new_seg); \ - cycles -= timing_call_rm; \ - } \ - optype = 0; \ - if (cpu_state.abrt) { cgate16 = cgate32 = 0; return 1; } \ - oldss = ss; \ - if (cgate16) \ - { \ - uint32_t old_esp = ESP; \ - PUSH_W(old_cs); if (cpu_state.abrt) { cgate16 = cgate32 = 0; return 1; } \ - PUSH_W(old_pc); if (cpu_state.abrt) { ESP = old_esp; return 1; } \ - } \ - else \ - { \ - uint32_t old_esp = ESP; \ - PUSH_L(old_cs); if (cpu_state.abrt) { cgate16 = cgate32 = 0; return 1; } \ - PUSH_L(old_pc); if (cpu_state.abrt) { ESP = old_esp; return 1; } \ + +# define CALL_FAR_l(new_seg, new_pc) \ + old_cs = CS; \ + old_pc = cpu_state.pc; \ + oxpc = cpu_state.pc; \ + cpu_state.pc = new_pc; \ + optype = CALL; \ + cgate16 = cgate32 = 0; \ + if (msw & 1) \ + op_loadcscall(new_seg); \ + else { \ + op_loadcs(new_seg); \ + cycles -= timing_call_rm; \ + } \ + optype = 0; \ + if (cpu_state.abrt) { \ + cgate16 = cgate32 = 0; \ + return 1; \ + } \ + oldss = ss; \ + if (cgate16) { \ + uint32_t old_esp = ESP; \ + PUSH_W(old_cs); \ + if (cpu_state.abrt) { \ + cgate16 = cgate32 = 0; \ + return 1; \ + } \ + PUSH_W(old_pc); \ + if (cpu_state.abrt) { \ + ESP = old_esp; \ + return 1; \ + } \ + } else { \ + uint32_t old_esp = ESP; \ + PUSH_L(old_cs); \ + if (cpu_state.abrt) { \ + cgate16 = cgate32 = 0; \ + return 1; \ + } \ + PUSH_L(old_pc); \ + if (cpu_state.abrt) { \ + ESP = old_esp; \ + return 1; \ + } \ } #endif - - -static int opCALL_far_w(uint32_t fetchdat) + +static int +opCALL_far_w(uint32_t fetchdat) { - uint32_t old_cs, old_pc; - uint16_t new_cs, new_pc; - int cycles_old = cycles; UN_USED(cycles_old); - - new_pc = getwordf(); - new_cs = getword(); if (cpu_state.abrt) return 1; - - CALL_FAR_w(new_cs, new_pc); - CPU_BLOCK_END(); - PREFETCH_RUN(cycles_old-cycles, 5, -1, 0,0,cgate16 ? 2:0,cgate16 ? 0:2, 0); - PREFETCH_FLUSH(); - - return 0; + uint32_t old_cs; + uint32_t old_pc; + uint16_t new_cs; + uint16_t new_pc; + int cycles_old = cycles; + UN_USED(cycles_old); + + new_pc = getwordf(); + new_cs = getword(); + if (cpu_state.abrt) + return 1; + + CALL_FAR_w(new_cs, new_pc); + CPU_BLOCK_END(); + PREFETCH_RUN(cycles_old - cycles, 5, -1, 0, 0, cgate16 ? 2 : 0, cgate16 ? 0 : 2, 0); + PREFETCH_FLUSH(); + + return 0; } -static int opCALL_far_l(uint32_t fetchdat) +static int +opCALL_far_l(uint32_t fetchdat) { - uint32_t old_cs, old_pc; - uint32_t new_cs, new_pc; - int cycles_old = cycles; UN_USED(cycles_old); - - new_pc = getlong(); - new_cs = getword(); if (cpu_state.abrt) return 1; - - CALL_FAR_l(new_cs, new_pc); - CPU_BLOCK_END(); - PREFETCH_RUN(cycles_old-cycles, 7, -1, 0,0,cgate16 ? 2:0,cgate16 ? 0:2, 0); - PREFETCH_FLUSH(); - - return 0; + uint32_t old_cs; + uint32_t old_pc; + uint32_t new_cs; + uint32_t new_pc; + int cycles_old = cycles; + UN_USED(cycles_old); + + new_pc = getlong(); + new_cs = getword(); + if (cpu_state.abrt) + return 1; + + CALL_FAR_l(new_cs, new_pc); + CPU_BLOCK_END(); + PREFETCH_RUN(cycles_old - cycles, 7, -1, 0, 0, cgate16 ? 2 : 0, cgate16 ? 0 : 2, 0); + PREFETCH_FLUSH(); + + return 0; } - -static int opFF_w_a16(uint32_t fetchdat) +static int +opFF_w_a16(uint32_t fetchdat) { - uint16_t old_cs, new_cs; - uint32_t old_pc, new_pc; - int cycles_old = cycles; UN_USED(cycles_old); - - uint16_t temp; - - fetch_ea_16(fetchdat); - - switch (rmdat & 0x38) - { - case 0x00: /*INC w*/ - if (cpu_mod != 3) - SEG_CHECK_WRITE(cpu_state.ea_seg); - temp = geteaw(); if (cpu_state.abrt) return 1; - seteaw(temp + 1); if (cpu_state.abrt) return 1; - setadd16nc(temp, 1); - CLOCK_CYCLES((cpu_mod == 3) ? timing_rr : timing_mm); - PREFETCH_RUN((cpu_mod == 3) ? timing_rr : timing_mm, 2, rmdat, (cpu_mod == 3) ? 0:1,0,(cpu_mod == 3) ? 0:1,0, 0); - break; - case 0x08: /*DEC w*/ - if (cpu_mod != 3) - SEG_CHECK_WRITE(cpu_state.ea_seg); - temp = geteaw(); if (cpu_state.abrt) return 1; - seteaw(temp - 1); if (cpu_state.abrt) return 1; - setsub16nc(temp, 1); - CLOCK_CYCLES((cpu_mod == 3) ? timing_rr : timing_mm); - PREFETCH_RUN((cpu_mod == 3) ? timing_rr : timing_mm, 2, rmdat, (cpu_mod == 3) ? 0:1,0,(cpu_mod == 3) ? 0:1,0, 0); - break; - case 0x10: /*CALL*/ - if (cpu_mod != 3) - SEG_CHECK_READ(cpu_state.ea_seg); - new_pc = geteaw(); if (cpu_state.abrt) return 1; - PUSH_W(cpu_state.pc); - cpu_state.pc = new_pc; - CPU_BLOCK_END(); - if (is486) { CLOCK_CYCLES(5); } - else { CLOCK_CYCLES((cpu_mod == 3) ? 7 : 10); } - PREFETCH_RUN((cpu_mod == 3) ? 7 : 10, 2, rmdat, (cpu_mod == 3) ? 0:1,0,1,0, 0); - PREFETCH_FLUSH(); - break; - case 0x18: /*CALL far*/ - if (cpu_mod != 3) - SEG_CHECK_READ(cpu_state.ea_seg); - new_pc = readmemw(easeg, cpu_state.eaaddr); - new_cs = readmemw(easeg, (cpu_state.eaaddr + 2)); if (cpu_state.abrt) return 1; - - CALL_FAR_w(new_cs, new_pc); - CPU_BLOCK_END(); - PREFETCH_RUN(cycles_old-cycles, 2, rmdat, 2,0,cgate16 ? 2:0,cgate16 ? 0:2, 0); - PREFETCH_FLUSH(); - break; - case 0x20: /*JMP*/ - if (cpu_mod != 3) - SEG_CHECK_READ(cpu_state.ea_seg); - new_pc = geteaw(); if (cpu_state.abrt) return 1; - cpu_state.pc = new_pc; - CPU_BLOCK_END(); - if (is486) { CLOCK_CYCLES(5); } - else { CLOCK_CYCLES((cpu_mod == 3) ? 7 : 10); } - PREFETCH_RUN((cpu_mod == 3) ? 7 : 10, 2, rmdat, (cpu_mod == 3) ? 0:1,0,0,0, 0); - PREFETCH_FLUSH(); - break; - case 0x28: /*JMP far*/ - if (cpu_mod != 3) - SEG_CHECK_READ(cpu_state.ea_seg); -#ifdef USE_NEW_DYNAREC - old_pc = cpu_state.pc; -#else - oxpc = cpu_state.pc; -#endif - new_pc = readmemw(easeg, cpu_state.eaaddr); - new_cs = readmemw(easeg, cpu_state.eaaddr + 2); if (cpu_state.abrt) return 1; - cpu_state.pc = new_pc; -#ifdef USE_NEW_DYNAREC - loadcsjmp(new_cs, old_pc); if (cpu_state.abrt) return 1; -#else - loadcsjmp(new_cs, oxpc); if (cpu_state.abrt) return 1; -#endif - CPU_BLOCK_END(); - PREFETCH_RUN(cycles_old-cycles, 2, rmdat, 2,0,0,0, 0); - PREFETCH_FLUSH(); - break; - case 0x30: /*PUSH w*/ - if (cpu_mod != 3) - SEG_CHECK_READ(cpu_state.ea_seg); - temp = geteaw(); if (cpu_state.abrt) return 1; - PUSH_W(temp); - CLOCK_CYCLES((cpu_mod == 3) ? 2 : 5); - PREFETCH_RUN((cpu_mod == 3) ? 2 : 5, 2, rmdat, (cpu_mod == 3) ? 0:1,0,1,0, 0); - break; + uint16_t old_cs; + uint16_t new_cs; + uint32_t old_pc; + uint32_t new_pc; + int cycles_old = cycles; + UN_USED(cycles_old); - default: -// fatal("Bad FF opcode %02X\n",rmdat&0x38); - x86illegal(); - } - return cpu_state.abrt; + uint16_t temp; + + fetch_ea_16(fetchdat); + + switch (rmdat & 0x38) { + case 0x00: /*INC w*/ + if (cpu_mod != 3) { + SEG_CHECK_READ(cpu_state.ea_seg); + if (cpu_state.abrt) + return 1; + CHECK_READ(cpu_state.ea_seg, cpu_state.eaaddr, cpu_state.eaaddr + 1UL); + } + temp = geteaw(); + if (cpu_state.abrt) + return 1; + if (cpu_mod != 3) { + CHECK_WRITE(cpu_state.ea_seg, cpu_state.eaaddr, cpu_state.eaaddr + 1UL); + } + seteaw(temp + 1); + if (cpu_state.abrt) + return 1; + setadd16nc(temp, 1); + CLOCK_CYCLES((cpu_mod == 3) ? timing_rr : timing_mm); + PREFETCH_RUN((cpu_mod == 3) ? timing_rr : timing_mm, 2, rmdat, (cpu_mod == 3) ? 0 : 1, 0, (cpu_mod == 3) ? 0 : 1, 0, 0); + break; + case 0x08: /*DEC w*/ + if (cpu_mod != 3) { + SEG_CHECK_READ(cpu_state.ea_seg); + if (cpu_state.abrt) + return 1; + CHECK_READ(cpu_state.ea_seg, cpu_state.eaaddr, cpu_state.eaaddr + 1UL); + } + temp = geteaw(); + if (cpu_state.abrt) + return 1; + if (cpu_mod != 3) { + CHECK_WRITE(cpu_state.ea_seg, cpu_state.eaaddr, cpu_state.eaaddr + 1UL); + } + seteaw(temp - 1); + if (cpu_state.abrt) + return 1; + setsub16nc(temp, 1); + CLOCK_CYCLES((cpu_mod == 3) ? timing_rr : timing_mm); + PREFETCH_RUN((cpu_mod == 3) ? timing_rr : timing_mm, 2, rmdat, (cpu_mod == 3) ? 0 : 1, 0, (cpu_mod == 3) ? 0 : 1, 0, 0); + break; + case 0x10: /*CALL*/ + if (cpu_mod != 3) { + SEG_CHECK_READ(cpu_state.ea_seg); + if (cpu_state.abrt) + return 1; + CHECK_READ(cpu_state.ea_seg, cpu_state.eaaddr, cpu_state.eaaddr + 1UL); + } + new_pc = geteaw(); + if (cpu_state.abrt) + return 1; + PUSH_W(cpu_state.pc); + cpu_state.pc = new_pc; + CPU_BLOCK_END(); + if (is486) { + CLOCK_CYCLES(5); + } else { + CLOCK_CYCLES((cpu_mod == 3) ? 7 : 10); + } + PREFETCH_RUN((cpu_mod == 3) ? 7 : 10, 2, rmdat, (cpu_mod == 3) ? 0 : 1, 0, 1, 0, 0); + PREFETCH_FLUSH(); + break; + case 0x18: /*CALL far*/ + if (cpu_mod != 3) { + SEG_CHECK_READ(cpu_state.ea_seg); + if (cpu_state.abrt) + return 1; + CHECK_READ(cpu_state.ea_seg, cpu_state.eaaddr, cpu_state.eaaddr + 3UL); + } + new_pc = readmemw(easeg, cpu_state.eaaddr); + new_cs = readmemw(easeg, (cpu_state.eaaddr + 2)); + if (cpu_state.abrt) + return 1; + + CALL_FAR_w(new_cs, new_pc); + CPU_BLOCK_END(); + PREFETCH_RUN(cycles_old - cycles, 2, rmdat, 2, 0, cgate16 ? 2 : 0, cgate16 ? 0 : 2, 0); + PREFETCH_FLUSH(); + break; + case 0x20: /*JMP*/ + if (cpu_mod != 3) { + SEG_CHECK_READ(cpu_state.ea_seg); + if (cpu_state.abrt) + return 1; + CHECK_READ(cpu_state.ea_seg, cpu_state.eaaddr, cpu_state.eaaddr + 1UL); + } + new_pc = geteaw(); + if (cpu_state.abrt) + return 1; + cpu_state.pc = new_pc; + CPU_BLOCK_END(); + if (is486) { + CLOCK_CYCLES(5); + } else { + CLOCK_CYCLES((cpu_mod == 3) ? 7 : 10); + } + PREFETCH_RUN((cpu_mod == 3) ? 7 : 10, 2, rmdat, (cpu_mod == 3) ? 0 : 1, 0, 0, 0, 0); + PREFETCH_FLUSH(); + break; + case 0x28: /*JMP far*/ + if (cpu_mod != 3) { + SEG_CHECK_READ(cpu_state.ea_seg); + if (cpu_state.abrt) + return 1; + CHECK_READ(cpu_state.ea_seg, cpu_state.eaaddr, cpu_state.eaaddr + 3UL); + } +#ifdef USE_NEW_DYNAREC + old_pc = cpu_state.pc; +#else + oxpc = cpu_state.pc; +#endif + new_pc = readmemw(easeg, cpu_state.eaaddr); + new_cs = readmemw(easeg, cpu_state.eaaddr + 2); + if (cpu_state.abrt) + return 1; + cpu_state.pc = new_pc; +#ifdef USE_NEW_DYNAREC + op_loadcsjmp(new_cs, old_pc); +#else + op_loadcsjmp(new_cs, oxpc); +#endif + if (cpu_state.abrt) + return 1; + CPU_BLOCK_END(); + PREFETCH_RUN(cycles_old - cycles, 2, rmdat, 2, 0, 0, 0, 0); + PREFETCH_FLUSH(); + break; + case 0x30: /*PUSH w*/ + if (cpu_mod != 3) { + SEG_CHECK_READ(cpu_state.ea_seg); + if (cpu_state.abrt) + return 1; + CHECK_READ(cpu_state.ea_seg, cpu_state.eaaddr, cpu_state.eaaddr + 1UL); + } + temp = geteaw(); + if (cpu_state.abrt) + return 1; + PUSH_W(temp); + CLOCK_CYCLES((cpu_mod == 3) ? 2 : 5); + PREFETCH_RUN((cpu_mod == 3) ? 2 : 5, 2, rmdat, (cpu_mod == 3) ? 0 : 1, 0, 1, 0, 0); + break; + + default: + // fatal("Bad FF opcode %02X\n",rmdat&0x38); + x86illegal(); + } + return cpu_state.abrt; } -static int opFF_w_a32(uint32_t fetchdat) +static int +opFF_w_a32(uint32_t fetchdat) { - uint16_t old_cs, new_cs; - uint32_t old_pc, new_pc; - int cycles_old = cycles; UN_USED(cycles_old); - - uint16_t temp; - - fetch_ea_32(fetchdat); - - switch (rmdat & 0x38) - { - case 0x00: /*INC w*/ - if (cpu_mod != 3) - SEG_CHECK_WRITE(cpu_state.ea_seg); - temp = geteaw(); if (cpu_state.abrt) return 1; - seteaw(temp + 1); if (cpu_state.abrt) return 1; - setadd16nc(temp, 1); - CLOCK_CYCLES((cpu_mod == 3) ? timing_rr : timing_mm); - PREFETCH_RUN((cpu_mod == 3) ? timing_rr : timing_mm, 2, rmdat, (cpu_mod == 3) ? 0:1,0,(cpu_mod == 3) ? 0:1,0, 1); - break; - case 0x08: /*DEC w*/ - if (cpu_mod != 3) - SEG_CHECK_WRITE(cpu_state.ea_seg); - temp = geteaw(); if (cpu_state.abrt) return 1; - seteaw(temp - 1); if (cpu_state.abrt) return 1; - setsub16nc(temp, 1); - CLOCK_CYCLES((cpu_mod == 3) ? timing_rr : timing_mm); - PREFETCH_RUN((cpu_mod == 3) ? timing_rr : timing_mm, 2, rmdat, (cpu_mod == 3) ? 0:1,0,(cpu_mod == 3) ? 0:1,0, 1); - break; - case 0x10: /*CALL*/ - if (cpu_mod != 3) - SEG_CHECK_READ(cpu_state.ea_seg); - new_pc = geteaw(); if (cpu_state.abrt) return 1; - PUSH_W(cpu_state.pc); - cpu_state.pc = new_pc; - CPU_BLOCK_END(); - if (is486) { CLOCK_CYCLES(5); } - else { CLOCK_CYCLES((cpu_mod == 3) ? 7 : 10); } - PREFETCH_RUN((cpu_mod == 3) ? 7 : 10, 2, rmdat, (cpu_mod == 3) ? 0:1,0,1,0, 1); - PREFETCH_FLUSH(); - break; - case 0x18: /*CALL far*/ - if (cpu_mod != 3) - SEG_CHECK_READ(cpu_state.ea_seg); - new_pc = readmemw(easeg, cpu_state.eaaddr); - new_cs = readmemw(easeg, (cpu_state.eaaddr + 2)); if (cpu_state.abrt) return 1; - - CALL_FAR_w(new_cs, new_pc); - CPU_BLOCK_END(); - PREFETCH_RUN(cycles_old-cycles, 2, rmdat, 2,0,cgate16 ? 2:0,cgate16 ? 0:2, 1); - PREFETCH_FLUSH(); - break; - case 0x20: /*JMP*/ - if (cpu_mod != 3) - SEG_CHECK_READ(cpu_state.ea_seg); - new_pc = geteaw(); if (cpu_state.abrt) return 1; - cpu_state.pc = new_pc; - CPU_BLOCK_END(); - if (is486) { CLOCK_CYCLES(5); } - else { CLOCK_CYCLES((cpu_mod == 3) ? 7 : 10); } - PREFETCH_RUN(cycles_old-cycles, 2, rmdat, 1,0,0,0, 1); - PREFETCH_FLUSH(); - break; - case 0x28: /*JMP far*/ - if (cpu_mod != 3) - SEG_CHECK_READ(cpu_state.ea_seg); -#ifdef USE_NEW_DYNAREC - old_pc = cpu_state.pc; -#else - oxpc = cpu_state.pc; -#endif - new_pc = readmemw(easeg, cpu_state.eaaddr); - new_cs = readmemw(easeg, cpu_state.eaaddr + 2); if (cpu_state.abrt) return 1; - cpu_state.pc = new_pc; -#ifdef USE_NEW_DYNAREC - loadcsjmp(new_cs, old_pc); if (cpu_state.abrt) return 1; -#else - loadcsjmp(new_cs, oxpc); if (cpu_state.abrt) return 1; -#endif - CPU_BLOCK_END(); - PREFETCH_RUN(cycles_old-cycles, 2, rmdat, 2,0,0,0, 1); - PREFETCH_FLUSH(); - break; - case 0x30: /*PUSH w*/ - if (cpu_mod != 3) - SEG_CHECK_READ(cpu_state.ea_seg); - temp = geteaw(); if (cpu_state.abrt) return 1; - PUSH_W(temp); - CLOCK_CYCLES((cpu_mod == 3) ? 2 : 5); - PREFETCH_RUN((cpu_mod == 3) ? 2 : 5, 2, rmdat, (cpu_mod == 3) ? 0:1,0,1,0, 1); - break; + uint16_t old_cs; + uint16_t new_cs; + uint32_t old_pc; + uint32_t new_pc; + int cycles_old = cycles; + UN_USED(cycles_old); - default: -// fatal("Bad FF opcode %02X\n",rmdat&0x38); - x86illegal(); - } - return cpu_state.abrt; + uint16_t temp; + + fetch_ea_32(fetchdat); + + switch (rmdat & 0x38) { + case 0x00: /*INC w*/ + if (cpu_mod != 3) { + SEG_CHECK_READ(cpu_state.ea_seg); + if (cpu_state.abrt) + return 1; + CHECK_READ(cpu_state.ea_seg, cpu_state.eaaddr, cpu_state.eaaddr + 1UL); + } + temp = geteaw(); + if (cpu_state.abrt) + return 1; + if (cpu_mod != 3) { + CHECK_WRITE(cpu_state.ea_seg, cpu_state.eaaddr, cpu_state.eaaddr + 1UL); + } + seteaw(temp + 1); + if (cpu_state.abrt) + return 1; + setadd16nc(temp, 1); + CLOCK_CYCLES((cpu_mod == 3) ? timing_rr : timing_mm); + PREFETCH_RUN((cpu_mod == 3) ? timing_rr : timing_mm, 2, rmdat, (cpu_mod == 3) ? 0 : 1, 0, (cpu_mod == 3) ? 0 : 1, 0, 1); + break; + case 0x08: /*DEC w*/ + if (cpu_mod != 3) { + SEG_CHECK_READ(cpu_state.ea_seg); + if (cpu_state.abrt) + return 1; + CHECK_READ(cpu_state.ea_seg, cpu_state.eaaddr, cpu_state.eaaddr + 1UL); + } + temp = geteaw(); + if (cpu_state.abrt) + return 1; + if (cpu_mod != 3) { + CHECK_WRITE(cpu_state.ea_seg, cpu_state.eaaddr, cpu_state.eaaddr + 1UL); + } + seteaw(temp - 1); + if (cpu_state.abrt) + return 1; + setsub16nc(temp, 1); + CLOCK_CYCLES((cpu_mod == 3) ? timing_rr : timing_mm); + PREFETCH_RUN((cpu_mod == 3) ? timing_rr : timing_mm, 2, rmdat, (cpu_mod == 3) ? 0 : 1, 0, (cpu_mod == 3) ? 0 : 1, 0, 1); + break; + case 0x10: /*CALL*/ + if (cpu_mod != 3) { + SEG_CHECK_READ(cpu_state.ea_seg); + if (cpu_state.abrt) + return 1; + CHECK_READ(cpu_state.ea_seg, cpu_state.eaaddr, cpu_state.eaaddr + 1UL); + } + new_pc = geteaw(); + if (cpu_state.abrt) + return 1; + PUSH_W(cpu_state.pc); + cpu_state.pc = new_pc; + CPU_BLOCK_END(); + if (is486) { + CLOCK_CYCLES(5); + } else { + CLOCK_CYCLES((cpu_mod == 3) ? 7 : 10); + } + PREFETCH_RUN((cpu_mod == 3) ? 7 : 10, 2, rmdat, (cpu_mod == 3) ? 0 : 1, 0, 1, 0, 1); + PREFETCH_FLUSH(); + break; + case 0x18: /*CALL far*/ + if (cpu_mod != 3) { + SEG_CHECK_READ(cpu_state.ea_seg); + if (cpu_state.abrt) + return 1; + CHECK_READ(cpu_state.ea_seg, cpu_state.eaaddr, cpu_state.eaaddr + 3UL); + } + new_pc = readmemw(easeg, cpu_state.eaaddr); + new_cs = readmemw(easeg, (cpu_state.eaaddr + 2)); + if (cpu_state.abrt) + return 1; + + CALL_FAR_w(new_cs, new_pc); + CPU_BLOCK_END(); + PREFETCH_RUN(cycles_old - cycles, 2, rmdat, 2, 0, cgate16 ? 2 : 0, cgate16 ? 0 : 2, 1); + PREFETCH_FLUSH(); + break; + case 0x20: /*JMP*/ + if (cpu_mod != 3) { + SEG_CHECK_READ(cpu_state.ea_seg); + if (cpu_state.abrt) + return 1; + CHECK_READ(cpu_state.ea_seg, cpu_state.eaaddr, cpu_state.eaaddr + 1UL); + } + new_pc = geteaw(); + if (cpu_state.abrt) + return 1; + cpu_state.pc = new_pc; + CPU_BLOCK_END(); + if (is486) { + CLOCK_CYCLES(5); + } else { + CLOCK_CYCLES((cpu_mod == 3) ? 7 : 10); + } + PREFETCH_RUN(cycles_old - cycles, 2, rmdat, 1, 0, 0, 0, 1); + PREFETCH_FLUSH(); + break; + case 0x28: /*JMP far*/ + if (cpu_mod != 3) { + SEG_CHECK_READ(cpu_state.ea_seg); + if (cpu_state.abrt) + return 1; + CHECK_READ(cpu_state.ea_seg, cpu_state.eaaddr, cpu_state.eaaddr + 3UL); + } +#ifdef USE_NEW_DYNAREC + old_pc = cpu_state.pc; +#else + oxpc = cpu_state.pc; +#endif + new_pc = readmemw(easeg, cpu_state.eaaddr); + new_cs = readmemw(easeg, cpu_state.eaaddr + 2); + if (cpu_state.abrt) + return 1; + cpu_state.pc = new_pc; +#ifdef USE_NEW_DYNAREC + op_loadcsjmp(new_cs, old_pc); +#else + op_loadcsjmp(new_cs, oxpc); +#endif + if (cpu_state.abrt) + return 1; + CPU_BLOCK_END(); + PREFETCH_RUN(cycles_old - cycles, 2, rmdat, 2, 0, 0, 0, 1); + PREFETCH_FLUSH(); + break; + case 0x30: /*PUSH w*/ + if (cpu_mod != 3) { + SEG_CHECK_READ(cpu_state.ea_seg); + if (cpu_state.abrt) + return 1; + CHECK_READ(cpu_state.ea_seg, cpu_state.eaaddr, cpu_state.eaaddr + 1UL); + } + temp = geteaw(); + if (cpu_state.abrt) + return 1; + PUSH_W(temp); + CLOCK_CYCLES((cpu_mod == 3) ? 2 : 5); + PREFETCH_RUN((cpu_mod == 3) ? 2 : 5, 2, rmdat, (cpu_mod == 3) ? 0 : 1, 0, 1, 0, 1); + break; + + default: + // fatal("Bad FF opcode %02X\n",rmdat&0x38); + x86illegal(); + } + return cpu_state.abrt; } -static int opFF_l_a16(uint32_t fetchdat) +static int +opFF_l_a16(uint32_t fetchdat) { - uint16_t old_cs, new_cs; - uint32_t old_pc, new_pc; - int cycles_old = cycles; UN_USED(cycles_old); - - uint32_t temp; - - fetch_ea_16(fetchdat); - - switch (rmdat & 0x38) - { - case 0x00: /*INC l*/ - if (cpu_mod != 3) - SEG_CHECK_WRITE(cpu_state.ea_seg); - temp = geteal(); if (cpu_state.abrt) return 1; - seteal(temp + 1); if (cpu_state.abrt) return 1; - setadd32nc(temp, 1); - CLOCK_CYCLES((cpu_mod == 3) ? timing_rr : timing_mm); - PREFETCH_RUN((cpu_mod == 3) ? timing_rr : timing_mm, 2, rmdat, 0,(cpu_mod == 3) ? 0:1,0,(cpu_mod == 3) ? 0:1, 0); - break; - case 0x08: /*DEC l*/ - if (cpu_mod != 3) - SEG_CHECK_WRITE(cpu_state.ea_seg); - temp = geteal(); if (cpu_state.abrt) return 1; - seteal(temp - 1); if (cpu_state.abrt) return 1; - setsub32nc(temp, 1); - CLOCK_CYCLES((cpu_mod == 3) ? timing_rr : timing_mm); - PREFETCH_RUN((cpu_mod == 3) ? timing_rr : timing_mm, 2, rmdat, 0,(cpu_mod == 3) ? 0:1,0,(cpu_mod == 3) ? 0:1, 0); - break; - case 0x10: /*CALL*/ - if (cpu_mod != 3) - SEG_CHECK_READ(cpu_state.ea_seg); - new_pc = geteal(); if (cpu_state.abrt) return 1; - PUSH_L(cpu_state.pc); - cpu_state.pc = new_pc; - CPU_BLOCK_END(); - if (is486) { CLOCK_CYCLES(5); } - else { CLOCK_CYCLES((cpu_mod == 3) ? 7 : 10); } - PREFETCH_RUN((cpu_mod == 3) ? 7 : 10, 2, rmdat, 0,(cpu_mod == 3) ? 0:1,0,1, 0); - PREFETCH_FLUSH(); - break; - case 0x18: /*CALL far*/ - if (cpu_mod != 3) - SEG_CHECK_READ(cpu_state.ea_seg); - new_pc = readmeml(easeg, cpu_state.eaaddr); - new_cs = readmemw(easeg, (cpu_state.eaaddr + 4)); if (cpu_state.abrt) return 1; - - CALL_FAR_l(new_cs, new_pc); - CPU_BLOCK_END(); - PREFETCH_RUN(cycles_old-cycles, 2, rmdat, 1,1,cgate16 ? 2:0,cgate16 ? 0:2, 0); - PREFETCH_FLUSH(); - break; - case 0x20: /*JMP*/ - if (cpu_mod != 3) - SEG_CHECK_READ(cpu_state.ea_seg); - new_pc = geteal(); if (cpu_state.abrt) return 1; - cpu_state.pc = new_pc; - CPU_BLOCK_END(); - if (is486) { CLOCK_CYCLES(5); } - else { CLOCK_CYCLES((cpu_mod == 3) ? 7 : 10); } - PREFETCH_RUN(cycles_old-cycles, 2, rmdat, 0,1,0,0, 0); - PREFETCH_FLUSH(); - break; - case 0x28: /*JMP far*/ - if (cpu_mod != 3) - SEG_CHECK_READ(cpu_state.ea_seg); -#ifdef USE_NEW_DYNAREC - old_pc = cpu_state.pc; -#else - oxpc = cpu_state.pc; -#endif - new_pc = readmeml(easeg, cpu_state.eaaddr); - new_cs = readmemw(easeg, cpu_state.eaaddr + 4); if (cpu_state.abrt) return 1; - cpu_state.pc = new_pc; -#ifdef USE_NEW_DYNAREC - loadcsjmp(new_cs, old_pc); if (cpu_state.abrt) return 1; -#else - loadcsjmp(new_cs, oxpc); if (cpu_state.abrt) return 1; -#endif - CPU_BLOCK_END(); - PREFETCH_RUN(cycles_old-cycles, 2, rmdat, 1,1,0,0, 0); - PREFETCH_FLUSH(); - break; - case 0x30: /*PUSH l*/ - if (cpu_mod != 3) - SEG_CHECK_READ(cpu_state.ea_seg); - temp = geteal(); if (cpu_state.abrt) return 1; - PUSH_L(temp); - CLOCK_CYCLES((cpu_mod == 3) ? 2 : 5); - PREFETCH_RUN((cpu_mod == 3) ? 2 : 5, 2, rmdat, 0,(cpu_mod == 3) ? 0:1,0,1, 0); - break; + uint16_t old_cs; + uint16_t new_cs; + uint32_t old_pc; + uint32_t new_pc; + int cycles_old = cycles; + UN_USED(cycles_old); - default: -// fatal("Bad FF opcode %02X\n",rmdat&0x38); - x86illegal(); - } - return cpu_state.abrt; + uint32_t temp; + + fetch_ea_16(fetchdat); + + switch (rmdat & 0x38) { + case 0x00: /*INC l*/ + if (cpu_mod != 3) { + SEG_CHECK_READ(cpu_state.ea_seg); + if (cpu_state.abrt) + return 1; + CHECK_READ(cpu_state.ea_seg, cpu_state.eaaddr, cpu_state.eaaddr + 3UL); + } + temp = geteal(); + if (cpu_state.abrt) + return 1; + if (cpu_mod != 3) { + CHECK_WRITE(cpu_state.ea_seg, cpu_state.eaaddr, cpu_state.eaaddr + 3UL); + } + seteal(temp + 1); + if (cpu_state.abrt) + return 1; + setadd32nc(temp, 1); + CLOCK_CYCLES((cpu_mod == 3) ? timing_rr : timing_mm); + PREFETCH_RUN((cpu_mod == 3) ? timing_rr : timing_mm, 2, rmdat, 0, (cpu_mod == 3) ? 0 : 1, 0, (cpu_mod == 3) ? 0 : 1, 0); + break; + case 0x08: /*DEC l*/ + if (cpu_mod != 3) { + SEG_CHECK_READ(cpu_state.ea_seg); + if (cpu_state.abrt) + return 1; + CHECK_READ(cpu_state.ea_seg, cpu_state.eaaddr, cpu_state.eaaddr + 3UL); + } + temp = geteal(); + if (cpu_state.abrt) + return 1; + if (cpu_mod != 3) { + CHECK_WRITE(cpu_state.ea_seg, cpu_state.eaaddr, cpu_state.eaaddr + 3UL); + } + seteal(temp - 1); + if (cpu_state.abrt) + return 1; + setsub32nc(temp, 1); + CLOCK_CYCLES((cpu_mod == 3) ? timing_rr : timing_mm); + PREFETCH_RUN((cpu_mod == 3) ? timing_rr : timing_mm, 2, rmdat, 0, (cpu_mod == 3) ? 0 : 1, 0, (cpu_mod == 3) ? 0 : 1, 0); + break; + case 0x10: /*CALL*/ + if (cpu_mod != 3) { + SEG_CHECK_READ(cpu_state.ea_seg); + if (cpu_state.abrt) + return 1; + CHECK_READ(cpu_state.ea_seg, cpu_state.eaaddr, cpu_state.eaaddr + 3UL); + } + new_pc = geteal(); + if (cpu_state.abrt) + return 1; + PUSH_L(cpu_state.pc); + cpu_state.pc = new_pc; + CPU_BLOCK_END(); + if (is486) { + CLOCK_CYCLES(5); + } else { + CLOCK_CYCLES((cpu_mod == 3) ? 7 : 10); + } + PREFETCH_RUN((cpu_mod == 3) ? 7 : 10, 2, rmdat, 0, (cpu_mod == 3) ? 0 : 1, 0, 1, 0); + PREFETCH_FLUSH(); + break; + case 0x18: /*CALL far*/ + if (cpu_mod != 3) { + SEG_CHECK_READ(cpu_state.ea_seg); + if (cpu_state.abrt) + return 1; + CHECK_READ(cpu_state.ea_seg, cpu_state.eaaddr, cpu_state.eaaddr + 5UL); + } + new_pc = readmeml(easeg, cpu_state.eaaddr); + new_cs = readmemw(easeg, (cpu_state.eaaddr + 4)); + if (cpu_state.abrt) + return 1; + + CALL_FAR_l(new_cs, new_pc); + CPU_BLOCK_END(); + PREFETCH_RUN(cycles_old - cycles, 2, rmdat, 1, 1, cgate16 ? 2 : 0, cgate16 ? 0 : 2, 0); + PREFETCH_FLUSH(); + break; + case 0x20: /*JMP*/ + if (cpu_mod != 3) { + SEG_CHECK_READ(cpu_state.ea_seg); + if (cpu_state.abrt) + return 1; + CHECK_READ(cpu_state.ea_seg, cpu_state.eaaddr, cpu_state.eaaddr + 3UL); + } + new_pc = geteal(); + if (cpu_state.abrt) + return 1; + cpu_state.pc = new_pc; + CPU_BLOCK_END(); + if (is486) { + CLOCK_CYCLES(5); + } else { + CLOCK_CYCLES((cpu_mod == 3) ? 7 : 10); + } + PREFETCH_RUN(cycles_old - cycles, 2, rmdat, 0, 1, 0, 0, 0); + PREFETCH_FLUSH(); + break; + case 0x28: /*JMP far*/ + if (cpu_mod != 3) { + SEG_CHECK_READ(cpu_state.ea_seg); + if (cpu_state.abrt) + return 1; + CHECK_READ(cpu_state.ea_seg, cpu_state.eaaddr, cpu_state.eaaddr + 5UL); + } +#ifdef USE_NEW_DYNAREC + old_pc = cpu_state.pc; +#else + oxpc = cpu_state.pc; +#endif + new_pc = readmeml(easeg, cpu_state.eaaddr); + new_cs = readmemw(easeg, cpu_state.eaaddr + 4); + if (cpu_state.abrt) + return 1; + cpu_state.pc = new_pc; +#ifdef USE_NEW_DYNAREC + op_loadcsjmp(new_cs, old_pc); +#else + op_loadcsjmp(new_cs, oxpc); +#endif + if (cpu_state.abrt) + return 1; + CPU_BLOCK_END(); + PREFETCH_RUN(cycles_old - cycles, 2, rmdat, 1, 1, 0, 0, 0); + PREFETCH_FLUSH(); + break; + case 0x30: /*PUSH l*/ + if (cpu_mod != 3) { + SEG_CHECK_READ(cpu_state.ea_seg); + if (cpu_state.abrt) + return 1; + CHECK_READ(cpu_state.ea_seg, cpu_state.eaaddr, cpu_state.eaaddr + 3UL); + } + temp = geteal(); + if (cpu_state.abrt) + return 1; + PUSH_L(temp); + CLOCK_CYCLES((cpu_mod == 3) ? 2 : 5); + PREFETCH_RUN((cpu_mod == 3) ? 2 : 5, 2, rmdat, 0, (cpu_mod == 3) ? 0 : 1, 0, 1, 0); + break; + + default: + // fatal("Bad FF opcode %02X\n",rmdat&0x38); + x86illegal(); + } + return cpu_state.abrt; } -static int opFF_l_a32(uint32_t fetchdat) +static int +opFF_l_a32(uint32_t fetchdat) { - uint16_t old_cs, new_cs; - uint32_t old_pc, new_pc; - int cycles_old = cycles; UN_USED(cycles_old); - - uint32_t temp; - - fetch_ea_32(fetchdat); - - switch (rmdat & 0x38) - { - case 0x00: /*INC l*/ - if (cpu_mod != 3) - SEG_CHECK_WRITE(cpu_state.ea_seg); - temp = geteal(); if (cpu_state.abrt) return 1; - seteal(temp + 1); if (cpu_state.abrt) return 1; - setadd32nc(temp, 1); - CLOCK_CYCLES((cpu_mod == 3) ? timing_rr : timing_mm); - PREFETCH_RUN((cpu_mod == 3) ? timing_rr : timing_mm, 2, rmdat, 0,(cpu_mod == 3) ? 0:1,0,(cpu_mod == 3) ? 0:1, 1); - break; - case 0x08: /*DEC l*/ - if (cpu_mod != 3) - SEG_CHECK_WRITE(cpu_state.ea_seg); - temp = geteal(); if (cpu_state.abrt) return 1; - seteal(temp - 1); if (cpu_state.abrt) return 1; - setsub32nc(temp, 1); - CLOCK_CYCLES((cpu_mod == 3) ? timing_rr : timing_mm); - PREFETCH_RUN((cpu_mod == 3) ? timing_rr : timing_mm, 2, rmdat, 0,(cpu_mod == 3) ? 0:1,0,(cpu_mod == 3) ? 0:1, 1); - break; - case 0x10: /*CALL*/ - if (cpu_mod != 3) - SEG_CHECK_READ(cpu_state.ea_seg); - new_pc = geteal(); if (cpu_state.abrt) return 1; - PUSH_L(cpu_state.pc); if (cpu_state.abrt) return 1; - cpu_state.pc = new_pc; - CPU_BLOCK_END(); - if (is486) { CLOCK_CYCLES(5); } - else { CLOCK_CYCLES((cpu_mod == 3) ? 7 : 10); } - PREFETCH_RUN((cpu_mod == 3) ? 7 : 10, 2, rmdat, 0,(cpu_mod == 3) ? 0:1,0,1, 1); - PREFETCH_FLUSH(); - break; - case 0x18: /*CALL far*/ - if (cpu_mod != 3) - SEG_CHECK_READ(cpu_state.ea_seg); - new_pc = readmeml(easeg, cpu_state.eaaddr); - new_cs = readmemw(easeg, (cpu_state.eaaddr + 4)); if (cpu_state.abrt) return 1; - - CALL_FAR_l(new_cs, new_pc); - CPU_BLOCK_END(); - PREFETCH_RUN(cycles_old-cycles, 2, rmdat, 1,1,cgate16 ? 2:0,cgate16 ? 0:2, 1); - PREFETCH_FLUSH(); - break; - case 0x20: /*JMP*/ - if (cpu_mod != 3) - SEG_CHECK_READ(cpu_state.ea_seg); - new_pc = geteal(); if (cpu_state.abrt) return 1; - cpu_state.pc = new_pc; - CPU_BLOCK_END(); - if (is486) { CLOCK_CYCLES(5); } - else { CLOCK_CYCLES((cpu_mod == 3) ? 7 : 10); } - PREFETCH_RUN(cycles_old-cycles, 2, rmdat, 1,1,0,0, 1); - PREFETCH_FLUSH(); - break; - case 0x28: /*JMP far*/ - if (cpu_mod != 3) - SEG_CHECK_READ(cpu_state.ea_seg); -#ifdef USE_NEW_DYNAREC - old_pc = cpu_state.pc; -#else - oxpc = cpu_state.pc; -#endif - new_pc = readmeml(easeg, cpu_state.eaaddr); - new_cs = readmemw(easeg, cpu_state.eaaddr + 4); if (cpu_state.abrt) return 1; - cpu_state.pc = new_pc; -#ifdef USE_NEW_DYNAREC - loadcsjmp(new_cs, old_pc); if (cpu_state.abrt) return 1; -#else - loadcsjmp(new_cs, oxpc); if (cpu_state.abrt) return 1; -#endif - CPU_BLOCK_END(); - PREFETCH_RUN(cycles_old-cycles, 2, rmdat, 1,1,0,0, 1); - PREFETCH_FLUSH(); - break; - case 0x30: /*PUSH l*/ - if (cpu_mod != 3) - SEG_CHECK_READ(cpu_state.ea_seg); - temp = geteal(); if (cpu_state.abrt) return 1; - PUSH_L(temp); - PREFETCH_RUN((cpu_mod == 3) ? 2 : 5, 2, rmdat, 0,(cpu_mod == 3) ? 0:1,0,1, 1); - break; + uint16_t old_cs; + uint16_t new_cs; + uint32_t old_pc; + uint32_t new_pc; + int cycles_old = cycles; + UN_USED(cycles_old); - default: -// fatal("Bad FF opcode %02X\n",rmdat&0x38); - x86illegal(); - } - return cpu_state.abrt; + uint32_t temp; + + fetch_ea_32(fetchdat); + + switch (rmdat & 0x38) { + case 0x00: /*INC l*/ + if (cpu_mod != 3) { + SEG_CHECK_READ(cpu_state.ea_seg); + if (cpu_state.abrt) + return 1; + CHECK_READ(cpu_state.ea_seg, cpu_state.eaaddr, cpu_state.eaaddr + 3UL); + } + temp = geteal(); + if (cpu_state.abrt) + return 1; + if (cpu_mod != 3) { + CHECK_WRITE(cpu_state.ea_seg, cpu_state.eaaddr, cpu_state.eaaddr + 3UL); + } + seteal(temp + 1); + if (cpu_state.abrt) + return 1; + setadd32nc(temp, 1); + CLOCK_CYCLES((cpu_mod == 3) ? timing_rr : timing_mm); + PREFETCH_RUN((cpu_mod == 3) ? timing_rr : timing_mm, 2, rmdat, 0, (cpu_mod == 3) ? 0 : 1, 0, (cpu_mod == 3) ? 0 : 1, 1); + break; + case 0x08: /*DEC l*/ + if (cpu_mod != 3) { + SEG_CHECK_READ(cpu_state.ea_seg); + if (cpu_state.abrt) + return 1; + CHECK_READ(cpu_state.ea_seg, cpu_state.eaaddr, cpu_state.eaaddr + 3UL); + } + temp = geteal(); + if (cpu_state.abrt) + return 1; + if (cpu_mod != 3) { + CHECK_WRITE(cpu_state.ea_seg, cpu_state.eaaddr, cpu_state.eaaddr + 3UL); + } + seteal(temp - 1); + if (cpu_state.abrt) + return 1; + setsub32nc(temp, 1); + CLOCK_CYCLES((cpu_mod == 3) ? timing_rr : timing_mm); + PREFETCH_RUN((cpu_mod == 3) ? timing_rr : timing_mm, 2, rmdat, 0, (cpu_mod == 3) ? 0 : 1, 0, (cpu_mod == 3) ? 0 : 1, 1); + break; + case 0x10: /*CALL*/ + if (cpu_mod != 3) { + SEG_CHECK_READ(cpu_state.ea_seg); + if (cpu_state.abrt) + return 1; + CHECK_READ(cpu_state.ea_seg, cpu_state.eaaddr, cpu_state.eaaddr + 3UL); + } + new_pc = geteal(); + if (cpu_state.abrt) + return 1; + PUSH_L(cpu_state.pc); + if (cpu_state.abrt) + return 1; + cpu_state.pc = new_pc; + CPU_BLOCK_END(); + if (is486) { + CLOCK_CYCLES(5); + } else { + CLOCK_CYCLES((cpu_mod == 3) ? 7 : 10); + } + PREFETCH_RUN((cpu_mod == 3) ? 7 : 10, 2, rmdat, 0, (cpu_mod == 3) ? 0 : 1, 0, 1, 1); + PREFETCH_FLUSH(); + break; + case 0x18: /*CALL far*/ + if (cpu_mod != 3) { + SEG_CHECK_READ(cpu_state.ea_seg); + if (cpu_state.abrt) + return 1; + CHECK_READ(cpu_state.ea_seg, cpu_state.eaaddr, cpu_state.eaaddr + 5UL); + } + new_pc = readmeml(easeg, cpu_state.eaaddr); + new_cs = readmemw(easeg, (cpu_state.eaaddr + 4)); + if (cpu_state.abrt) + return 1; + + CALL_FAR_l(new_cs, new_pc); + CPU_BLOCK_END(); + PREFETCH_RUN(cycles_old - cycles, 2, rmdat, 1, 1, cgate16 ? 2 : 0, cgate16 ? 0 : 2, 1); + PREFETCH_FLUSH(); + break; + case 0x20: /*JMP*/ + if (cpu_mod != 3) { + SEG_CHECK_READ(cpu_state.ea_seg); + if (cpu_state.abrt) + return 1; + CHECK_READ(cpu_state.ea_seg, cpu_state.eaaddr, cpu_state.eaaddr + 3UL); + } + new_pc = geteal(); + if (cpu_state.abrt) + return 1; + cpu_state.pc = new_pc; + CPU_BLOCK_END(); + if (is486) { + CLOCK_CYCLES(5); + } else { + CLOCK_CYCLES((cpu_mod == 3) ? 7 : 10); + } + PREFETCH_RUN(cycles_old - cycles, 2, rmdat, 1, 1, 0, 0, 1); + PREFETCH_FLUSH(); + break; + case 0x28: /*JMP far*/ + if (cpu_mod != 3) { + SEG_CHECK_READ(cpu_state.ea_seg); + if (cpu_state.abrt) + return 1; + CHECK_READ(cpu_state.ea_seg, cpu_state.eaaddr, cpu_state.eaaddr + 5UL); + } +#ifdef USE_NEW_DYNAREC + old_pc = cpu_state.pc; +#else + oxpc = cpu_state.pc; +#endif + new_pc = readmeml(easeg, cpu_state.eaaddr); + new_cs = readmemw(easeg, cpu_state.eaaddr + 4); + if (cpu_state.abrt) + return 1; + cpu_state.pc = new_pc; +#ifdef USE_NEW_DYNAREC + op_loadcsjmp(new_cs, old_pc); +#else + op_loadcsjmp(new_cs, oxpc); +#endif + if (cpu_state.abrt) + return 1; + CPU_BLOCK_END(); + PREFETCH_RUN(cycles_old - cycles, 2, rmdat, 1, 1, 0, 0, 1); + PREFETCH_FLUSH(); + break; + case 0x30: /*PUSH l*/ + if (cpu_mod != 3) { + SEG_CHECK_READ(cpu_state.ea_seg); + if (cpu_state.abrt) + return 1; + CHECK_READ(cpu_state.ea_seg, cpu_state.eaaddr, cpu_state.eaaddr + 3UL); + } + temp = geteal(); + if (cpu_state.abrt) + return 1; + PUSH_L(temp); + PREFETCH_RUN((cpu_mod == 3) ? 2 : 5, 2, rmdat, 0, (cpu_mod == 3) ? 0 : 1, 0, 1, 1); + break; + + default: + // fatal("Bad FF opcode %02X\n",rmdat&0x38); + x86illegal(); + } + return cpu_state.abrt; } diff --git a/src/cpu/x86_ops_cyrix.h b/src/cpu/x86_ops_cyrix.h index 500b119fb..672ebd08e 100644 --- a/src/cpu/x86_ops_cyrix.h +++ b/src/cpu/x86_ops_cyrix.h @@ -1,272 +1,265 @@ /*Cyrix-only instructions*/ /*System Management Mode*/ -static void opSVDC_common(uint32_t fetchdat) +static void +opSVDC_common(uint32_t fetchdat) { - switch (rmdat & 0x38) - { - case 0x00: /*ES*/ - cyrix_write_seg_descriptor(easeg+cpu_state.eaaddr, &cpu_state.seg_es); - writememw(0, easeg+cpu_state.eaaddr+8, ES); - break; - case 0x08: /*CS*/ - cyrix_write_seg_descriptor(easeg+cpu_state.eaaddr, &cpu_state.seg_cs); - writememw(0, easeg+cpu_state.eaaddr+8, CS); - break; - case 0x18: /*DS*/ - cyrix_write_seg_descriptor(easeg+cpu_state.eaaddr, &cpu_state.seg_ds); - writememw(0, easeg+cpu_state.eaaddr+8, DS); - break; - case 0x10: /*SS*/ - cyrix_write_seg_descriptor(easeg+cpu_state.eaaddr, &cpu_state.seg_ss); - writememw(0, easeg+cpu_state.eaaddr+8, SS); - break; - case 0x20: /*FS*/ - cyrix_write_seg_descriptor(easeg+cpu_state.eaaddr, &cpu_state.seg_fs); - writememw(0, easeg+cpu_state.eaaddr+8, FS); - break; - case 0x28: /*GS*/ - cyrix_write_seg_descriptor(easeg+cpu_state.eaaddr, &cpu_state.seg_gs); - writememw(0, easeg+cpu_state.eaaddr+8, GS); - break; - default: - x86illegal(); - } + switch (rmdat & 0x38) { + case 0x00: /*ES*/ + cyrix_write_seg_descriptor(easeg + cpu_state.eaaddr, &cpu_state.seg_es); + writememw(0, easeg + cpu_state.eaaddr + 8, ES); + break; + case 0x08: /*CS*/ + cyrix_write_seg_descriptor(easeg + cpu_state.eaaddr, &cpu_state.seg_cs); + writememw(0, easeg + cpu_state.eaaddr + 8, CS); + break; + case 0x18: /*DS*/ + cyrix_write_seg_descriptor(easeg + cpu_state.eaaddr, &cpu_state.seg_ds); + writememw(0, easeg + cpu_state.eaaddr + 8, DS); + break; + case 0x10: /*SS*/ + cyrix_write_seg_descriptor(easeg + cpu_state.eaaddr, &cpu_state.seg_ss); + writememw(0, easeg + cpu_state.eaaddr + 8, SS); + break; + case 0x20: /*FS*/ + cyrix_write_seg_descriptor(easeg + cpu_state.eaaddr, &cpu_state.seg_fs); + writememw(0, easeg + cpu_state.eaaddr + 8, FS); + break; + case 0x28: /*GS*/ + cyrix_write_seg_descriptor(easeg + cpu_state.eaaddr, &cpu_state.seg_gs); + writememw(0, easeg + cpu_state.eaaddr + 8, GS); + break; + default: + x86illegal(); + } } -static int opSVDC_a16(uint32_t fetchdat) +static int +opSVDC_a16(uint32_t fetchdat) { - if (in_smm) - { - fetch_ea_16(fetchdat); - SEG_CHECK_WRITE(cpu_state.ea_seg); - opSVDC_common(fetchdat); - } - else - x86illegal(); + if (in_smm) { + fetch_ea_16(fetchdat); + SEG_CHECK_WRITE(cpu_state.ea_seg); + opSVDC_common(fetchdat); + } else + x86illegal(); - return cpu_state.abrt; + return cpu_state.abrt; } -static int opSVDC_a32(uint32_t fetchdat) +static int +opSVDC_a32(uint32_t fetchdat) { - if (in_smm) - { - fetch_ea_32(fetchdat); - SEG_CHECK_WRITE(cpu_state.ea_seg); - opSVDC_common(fetchdat); - } - else - x86illegal(); + if (in_smm) { + fetch_ea_32(fetchdat); + SEG_CHECK_WRITE(cpu_state.ea_seg); + opSVDC_common(fetchdat); + } else + x86illegal(); - return cpu_state.abrt; + return cpu_state.abrt; } -static void opRSDC_common(uint32_t fetchdat) +static void +opRSDC_common(uint32_t fetchdat) { - switch (rmdat & 0x38) - { - case 0x00: /*ES*/ - cyrix_load_seg_descriptor(easeg+cpu_state.eaaddr, &cpu_state.seg_es); - break; - case 0x18: /*DS*/ - cyrix_load_seg_descriptor(easeg+cpu_state.eaaddr, &cpu_state.seg_ds); - break; - case 0x10: /*SS*/ - cyrix_load_seg_descriptor(easeg+cpu_state.eaaddr, &cpu_state.seg_ss); - break; - case 0x20: /*FS*/ - cyrix_load_seg_descriptor(easeg+cpu_state.eaaddr, &cpu_state.seg_fs); - break; - case 0x28: /*GS*/ - cyrix_load_seg_descriptor(easeg+cpu_state.eaaddr, &cpu_state.seg_gs); - break; - default: - x86illegal(); - } + switch (rmdat & 0x38) { + case 0x00: /*ES*/ + cyrix_load_seg_descriptor(easeg + cpu_state.eaaddr, &cpu_state.seg_es); + break; + case 0x18: /*DS*/ + cyrix_load_seg_descriptor(easeg + cpu_state.eaaddr, &cpu_state.seg_ds); + break; + case 0x10: /*SS*/ + cyrix_load_seg_descriptor(easeg + cpu_state.eaaddr, &cpu_state.seg_ss); + break; + case 0x20: /*FS*/ + cyrix_load_seg_descriptor(easeg + cpu_state.eaaddr, &cpu_state.seg_fs); + break; + case 0x28: /*GS*/ + cyrix_load_seg_descriptor(easeg + cpu_state.eaaddr, &cpu_state.seg_gs); + break; + default: + x86illegal(); + } } -static int opRSDC_a16(uint32_t fetchdat) +static int +opRSDC_a16(uint32_t fetchdat) { - if (in_smm) - { - fetch_ea_16(fetchdat); - SEG_CHECK_READ(cpu_state.ea_seg); - opRSDC_common(fetchdat); - } - else - x86illegal(); + if (in_smm) { + fetch_ea_16(fetchdat); + SEG_CHECK_READ(cpu_state.ea_seg); + opRSDC_common(fetchdat); + } else + x86illegal(); - return cpu_state.abrt; + return cpu_state.abrt; } -static int opRSDC_a32(uint32_t fetchdat) +static int +opRSDC_a32(uint32_t fetchdat) { - if (in_smm) - { - fetch_ea_32(fetchdat); - SEG_CHECK_READ(cpu_state.ea_seg); - opRSDC_common(fetchdat); - } - else - x86illegal(); + if (in_smm) { + fetch_ea_32(fetchdat); + SEG_CHECK_READ(cpu_state.ea_seg); + opRSDC_common(fetchdat); + } else + x86illegal(); - return cpu_state.abrt; + return cpu_state.abrt; } -static int opSVLDT_a16(uint32_t fetchdat) +static int +opSVLDT_a16(uint32_t fetchdat) { - if (in_smm) - { - fetch_ea_16(fetchdat); - SEG_CHECK_WRITE(cpu_state.ea_seg); - cyrix_write_seg_descriptor(easeg+cpu_state.eaaddr, &ldt); - writememw(0, easeg+cpu_state.eaaddr+8, ldt.seg); - } - else - x86illegal(); + if (in_smm) { + fetch_ea_16(fetchdat); + SEG_CHECK_WRITE(cpu_state.ea_seg); + cyrix_write_seg_descriptor(easeg + cpu_state.eaaddr, &ldt); + writememw(0, easeg + cpu_state.eaaddr + 8, ldt.seg); + } else + x86illegal(); - return cpu_state.abrt; + return cpu_state.abrt; } -static int opSVLDT_a32(uint32_t fetchdat) +static int +opSVLDT_a32(uint32_t fetchdat) { - if (in_smm) - { - fetch_ea_32(fetchdat); - SEG_CHECK_WRITE(cpu_state.ea_seg); - cyrix_write_seg_descriptor(easeg+cpu_state.eaaddr, &ldt); - writememw(0, easeg+cpu_state.eaaddr+8, ldt.seg); - } - else - x86illegal(); + if (in_smm) { + fetch_ea_32(fetchdat); + SEG_CHECK_WRITE(cpu_state.ea_seg); + cyrix_write_seg_descriptor(easeg + cpu_state.eaaddr, &ldt); + writememw(0, easeg + cpu_state.eaaddr + 8, ldt.seg); + } else + x86illegal(); - return cpu_state.abrt; + return cpu_state.abrt; } -static int opRSLDT_a16(uint32_t fetchdat) +static int +opRSLDT_a16(uint32_t fetchdat) { - if (in_smm) - { - fetch_ea_16(fetchdat); - SEG_CHECK_READ(cpu_state.ea_seg); - cyrix_load_seg_descriptor(easeg+cpu_state.eaaddr, &ldt); - } - else - x86illegal(); + if (in_smm) { + fetch_ea_16(fetchdat); + SEG_CHECK_READ(cpu_state.ea_seg); + cyrix_load_seg_descriptor(easeg + cpu_state.eaaddr, &ldt); + } else + x86illegal(); - return cpu_state.abrt; + return cpu_state.abrt; } -static int opRSLDT_a32(uint32_t fetchdat) +static int +opRSLDT_a32(uint32_t fetchdat) { - if (in_smm) - { - fetch_ea_32(fetchdat); - SEG_CHECK_READ(cpu_state.ea_seg); - cyrix_load_seg_descriptor(easeg+cpu_state.eaaddr, &ldt); - } - else - x86illegal(); + if (in_smm) { + fetch_ea_32(fetchdat); + SEG_CHECK_READ(cpu_state.ea_seg); + cyrix_load_seg_descriptor(easeg + cpu_state.eaaddr, &ldt); + } else + x86illegal(); - return cpu_state.abrt; + return cpu_state.abrt; } -static int opSVTS_a16(uint32_t fetchdat) +static int +opSVTS_a16(uint32_t fetchdat) { - if (in_smm) - { - fetch_ea_16(fetchdat); - SEG_CHECK_WRITE(cpu_state.ea_seg); - cyrix_write_seg_descriptor(easeg+cpu_state.eaaddr, &tr); - writememw(0, easeg+cpu_state.eaaddr+8, tr.seg); - } - else - x86illegal(); + if (in_smm) { + fetch_ea_16(fetchdat); + SEG_CHECK_WRITE(cpu_state.ea_seg); + cyrix_write_seg_descriptor(easeg + cpu_state.eaaddr, &tr); + writememw(0, easeg + cpu_state.eaaddr + 8, tr.seg); + } else + x86illegal(); - return cpu_state.abrt; + return cpu_state.abrt; } -static int opSVTS_a32(uint32_t fetchdat) +static int +opSVTS_a32(uint32_t fetchdat) { - if (in_smm) - { - fetch_ea_32(fetchdat); - SEG_CHECK_WRITE(cpu_state.ea_seg); - cyrix_write_seg_descriptor(easeg+cpu_state.eaaddr, &tr); - writememw(0, easeg+cpu_state.eaaddr+8, tr.seg); - } - else - x86illegal(); + if (in_smm) { + fetch_ea_32(fetchdat); + SEG_CHECK_WRITE(cpu_state.ea_seg); + cyrix_write_seg_descriptor(easeg + cpu_state.eaaddr, &tr); + writememw(0, easeg + cpu_state.eaaddr + 8, tr.seg); + } else + x86illegal(); - return cpu_state.abrt; + return cpu_state.abrt; } -static int opRSTS_a16(uint32_t fetchdat) +static int +opRSTS_a16(uint32_t fetchdat) { - if (in_smm) - { - fetch_ea_16(fetchdat); - SEG_CHECK_WRITE(cpu_state.ea_seg); - cyrix_write_seg_descriptor(easeg+cpu_state.eaaddr, &tr); - writememw(0, easeg+cpu_state.eaaddr+8, tr.seg); - } - else - x86illegal(); + if (in_smm) { + fetch_ea_16(fetchdat); + SEG_CHECK_WRITE(cpu_state.ea_seg); + cyrix_write_seg_descriptor(easeg + cpu_state.eaaddr, &tr); + writememw(0, easeg + cpu_state.eaaddr + 8, tr.seg); + } else + x86illegal(); - return cpu_state.abrt; + return cpu_state.abrt; } -static int opRSTS_a32(uint32_t fetchdat) +static int +opRSTS_a32(uint32_t fetchdat) { - if (in_smm) - { - fetch_ea_32(fetchdat); - SEG_CHECK_WRITE(cpu_state.ea_seg); - cyrix_write_seg_descriptor(easeg+cpu_state.eaaddr, &tr); - writememw(0, easeg+cpu_state.eaaddr+8, tr.seg); - } - else - x86illegal(); + if (in_smm) { + fetch_ea_32(fetchdat); + SEG_CHECK_WRITE(cpu_state.ea_seg); + cyrix_write_seg_descriptor(easeg + cpu_state.eaaddr, &tr); + writememw(0, easeg + cpu_state.eaaddr + 8, tr.seg); + } else + x86illegal(); - return cpu_state.abrt; + return cpu_state.abrt; } -static int opSMINT(uint32_t fetchdat) +static int +opSMINT(uint32_t fetchdat) { - if (in_smm) - fatal("opSMINT\n"); - else - x86illegal(); + if (in_smm) + fatal("opSMINT\n"); + else + x86illegal(); - return 1; + return 1; } -static int opRDSHR_a16(uint32_t fetchdat) +static int +opRDSHR_a16(uint32_t fetchdat) { - if (in_smm) - fatal("opRDSHR_a16\n"); - else - x86illegal(); + if (in_smm) + fatal("opRDSHR_a16\n"); + else + x86illegal(); - return 1; + return 1; } -static int opRDSHR_a32(uint32_t fetchdat) +static int +opRDSHR_a32(uint32_t fetchdat) { - if (in_smm) - fatal("opRDSHR_a32\n"); - else - x86illegal(); + if (in_smm) + fatal("opRDSHR_a32\n"); + else + x86illegal(); - return 1; + return 1; } -static int opWRSHR_a16(uint32_t fetchdat) +static int +opWRSHR_a16(uint32_t fetchdat) { - if (in_smm) - fatal("opWRSHR_a16\n"); - else - x86illegal(); + if (in_smm) + fatal("opWRSHR_a16\n"); + else + x86illegal(); - return 1; + return 1; } -static int opWRSHR_a32(uint32_t fetchdat) +static int +opWRSHR_a32(uint32_t fetchdat) { - if (in_smm) - fatal("opWRSHR_a32\n"); - else - x86illegal(); + if (in_smm) + fatal("opWRSHR_a32\n"); + else + x86illegal(); - return 1; + return 1; } diff --git a/src/cpu/x86_ops_flag.h b/src/cpu/x86_ops_flag.h index b5e16ee0e..f08b30fce 100644 --- a/src/cpu/x86_ops_flag.h +++ b/src/cpu/x86_ops_flag.h @@ -1,286 +1,319 @@ -static int opCMC(uint32_t fetchdat) +static int +opCMC(uint32_t fetchdat) { - flags_rebuild(); - cpu_state.flags ^= C_FLAG; - CLOCK_CYCLES(2); - PREFETCH_RUN(2, 1, -1, 0,0,0,0, 0); - return 0; + flags_rebuild(); + cpu_state.flags ^= C_FLAG; + CLOCK_CYCLES(2); + PREFETCH_RUN(2, 1, -1, 0, 0, 0, 0, 0); + return 0; } - -static int opCLC(uint32_t fetchdat) +static int +opCLC(uint32_t fetchdat) { - flags_rebuild(); - cpu_state.flags &= ~C_FLAG; - CLOCK_CYCLES(2); - PREFETCH_RUN(2, 1, -1, 0,0,0,0, 0); - return 0; + flags_rebuild(); + cpu_state.flags &= ~C_FLAG; + CLOCK_CYCLES(2); + PREFETCH_RUN(2, 1, -1, 0, 0, 0, 0, 0); + return 0; } -static int opCLD(uint32_t fetchdat) +static int +opCLD(uint32_t fetchdat) { - cpu_state.flags &= ~D_FLAG; - CLOCK_CYCLES(2); - PREFETCH_RUN(2, 1, -1, 0,0,0,0, 0); - return 0; + cpu_state.flags &= ~D_FLAG; + CLOCK_CYCLES(2); + PREFETCH_RUN(2, 1, -1, 0, 0, 0, 0, 0); + return 0; } -static int opCLI(uint32_t fetchdat) +static int +opCLI(uint32_t fetchdat) { - if (!IOPLp) - { - if ((!(cpu_state.eflags & VM_FLAG) && (cr4 & CR4_PVI)) || - ((cpu_state.eflags & VM_FLAG) && (cr4 & CR4_VME))) - { - cpu_state.eflags &= ~VIF_FLAG; - } - else - { - x86gpf(NULL,0); - return 1; - } + if (!IOPLp) { + if ((!(cpu_state.eflags & VM_FLAG) && (cr4 & CR4_PVI)) || ((cpu_state.eflags & VM_FLAG) && (cr4 & CR4_VME))) { + cpu_state.eflags &= ~VIF_FLAG; + } else { + x86gpf(NULL, 0); + return 1; } - else - cpu_state.flags &= ~I_FLAG; - - CLOCK_CYCLES(3); - PREFETCH_RUN(3, 1, -1, 0,0,0,0, 0); - return 0; + } else + cpu_state.flags &= ~I_FLAG; + + CLOCK_CYCLES(3); + PREFETCH_RUN(3, 1, -1, 0, 0, 0, 0, 0); + return 0; } -static int opSTC(uint32_t fetchdat) +static int +opSTC(uint32_t fetchdat) { - flags_rebuild(); - cpu_state.flags |= C_FLAG; - CLOCK_CYCLES(2); - PREFETCH_RUN(2, 1, -1, 0,0,0,0, 0); - return 0; + flags_rebuild(); + cpu_state.flags |= C_FLAG; + CLOCK_CYCLES(2); + PREFETCH_RUN(2, 1, -1, 0, 0, 0, 0, 0); + return 0; } -static int opSTD(uint32_t fetchdat) +static int +opSTD(uint32_t fetchdat) { - cpu_state.flags |= D_FLAG; - CLOCK_CYCLES(2); - PREFETCH_RUN(2, 1, -1, 0,0,0,0, 0); - return 0; + cpu_state.flags |= D_FLAG; + CLOCK_CYCLES(2); + PREFETCH_RUN(2, 1, -1, 0, 0, 0, 0, 0); + return 0; } -static int opSTI(uint32_t fetchdat) +static int +opSTI(uint32_t fetchdat) { - if (!IOPLp) - { - if ((!(cpu_state.eflags & VM_FLAG) && (cr4 & CR4_PVI)) || - ((cpu_state.eflags & VM_FLAG) && (cr4 & CR4_VME))) - { - if (cpu_state.eflags & VIP_FLAG) - { - x86gpf(NULL,0); - return 1; - } - else - cpu_state.eflags |= VIF_FLAG; - } - else - { - x86gpf(NULL,0); - return 1; - } - } - else - cpu_state.flags |= I_FLAG; - - /*First instruction after STI will always execute, regardless of whether - there is a pending interrupt*/ - cpu_end_block_after_ins = 2; - - CLOCK_CYCLES(2); - PREFETCH_RUN(2, 1, -1, 0,0,0,0, 0); - return 0; -} - -static int opSAHF(uint32_t fetchdat) -{ - flags_rebuild(); - cpu_state.flags = (cpu_state.flags & 0xff00) | (AH & 0xd5) | 2; - CLOCK_CYCLES(3); - PREFETCH_RUN(3, 1, -1, 0,0,0,0, 0); - -#if (defined(USE_DYNAREC) && defined(USE_NEW_DYNAREC)) - codegen_flags_changed = 0; -#endif - - return 0; -} -static int opLAHF(uint32_t fetchdat) -{ - flags_rebuild(); - AH = cpu_state.flags & 0xff; - CLOCK_CYCLES(3); - PREFETCH_RUN(3, 1, -1, 0,0,0,0, 0); - return 0; -} - -static int opPUSHF(uint32_t fetchdat) -{ - if ((cpu_state.eflags & VM_FLAG) && (IOPL < 3)) - { - if (cr4 & CR4_VME) - { - uint16_t temp; - - flags_rebuild(); - temp = (cpu_state.flags & ~I_FLAG) | 0x3000; - if (cpu_state.eflags & VIF_FLAG) - temp |= I_FLAG; - PUSH_W(temp); - } - else - { - x86gpf(NULL,0); - return 1; - } - } - else - { - flags_rebuild(); - PUSH_W(cpu_state.flags); - } - CLOCK_CYCLES(4); - PREFETCH_RUN(4, 1, -1, 0,0,1,0, 0); - return cpu_state.abrt; -} -static int opPUSHFD(uint32_t fetchdat) -{ - uint16_t tempw; - if ((cpu_state.eflags & VM_FLAG) && (IOPL < 3)) - { + if (!IOPLp) { + if ((!(cpu_state.eflags & VM_FLAG) && (cr4 & CR4_PVI)) || ((cpu_state.eflags & VM_FLAG) && (cr4 & CR4_VME))) { + if (cpu_state.eflags & VIP_FLAG) { x86gpf(NULL, 0); return 1; + } else + cpu_state.eflags |= VIF_FLAG; + } else { + x86gpf(NULL, 0); + return 1; } - if (cpu_CR4_mask & CR4_VME) tempw = cpu_state.eflags & 0x3c; - else if (CPUID) tempw = cpu_state.eflags & 0x24; - else tempw = cpu_state.eflags & 4; + } else + cpu_state.flags |= I_FLAG; + + /*First instruction after STI will always execute, regardless of whether + there is a pending interrupt*/ + cpu_end_block_after_ins = 2; + + CLOCK_CYCLES(2); + PREFETCH_RUN(2, 1, -1, 0, 0, 0, 0, 0); + return 0; +} + +static int +opSAHF(uint32_t fetchdat) +{ + flags_rebuild(); + cpu_state.flags = (cpu_state.flags & 0xff00) | (AH & 0xd5) | 2; + CLOCK_CYCLES(3); + PREFETCH_RUN(3, 1, -1, 0, 0, 0, 0, 0); + +#if (defined(USE_DYNAREC) && defined(USE_NEW_DYNAREC)) + codegen_flags_changed = 0; +#endif + + return 0; +} +static int +opLAHF(uint32_t fetchdat) +{ + flags_rebuild(); + AH = cpu_state.flags & 0xff; + CLOCK_CYCLES(3); + PREFETCH_RUN(3, 1, -1, 0, 0, 0, 0, 0); + return 0; +} + +static int +opPUSHF(uint32_t fetchdat) +{ + if ((cpu_state.eflags & VM_FLAG) && (IOPL < 3)) { + if (cr4 & CR4_VME) { + uint16_t temp; + + flags_rebuild(); + temp = (cpu_state.flags & ~I_FLAG) | 0x3000; + if (cpu_state.eflags & VIF_FLAG) + temp |= I_FLAG; + PUSH_W(temp); + } else { + x86gpf(NULL, 0); + return 1; + } + } else { flags_rebuild(); - PUSH_L(cpu_state.flags | (tempw << 16)); - CLOCK_CYCLES(4); - PREFETCH_RUN(4, 1, -1, 0,0,0,1, 0); - return cpu_state.abrt; + PUSH_W(cpu_state.flags); + } + CLOCK_CYCLES(4); + PREFETCH_RUN(4, 1, -1, 0, 0, 1, 0, 0); + return cpu_state.abrt; +} +static int +opPUSHFD(uint32_t fetchdat) +{ + uint16_t tempw; + if ((cpu_state.eflags & VM_FLAG) && (IOPL < 3)) { + x86gpf(NULL, 0); + return 1; + } + if (cpu_CR4_mask & CR4_VME) + tempw = cpu_state.eflags & 0x3c; + else if (CPUID) + tempw = cpu_state.eflags & 0x24; + else + tempw = cpu_state.eflags & 4; + flags_rebuild(); + PUSH_L(cpu_state.flags | (tempw << 16)); + CLOCK_CYCLES(4); + PREFETCH_RUN(4, 1, -1, 0, 0, 0, 1, 0); + return cpu_state.abrt; } -static int opPOPF_286(uint32_t fetchdat) +static int +opPOPF_186(uint32_t fetchdat) { - uint16_t tempw; - - if ((cpu_state.eflags & VM_FLAG) && (IOPL < 3)) - { - x86gpf(NULL, 0); - return 1; - } - - tempw = POP_W(); if (cpu_state.abrt) return 1; + uint16_t tempw; - if (!(msw & 1)) cpu_state.flags = (cpu_state.flags & 0x7000) | (tempw & 0x0fd5) | 2; - else if (!(CPL)) cpu_state.flags = (tempw & 0x7fd5) | 2; - else if (IOPLp) cpu_state.flags = (cpu_state.flags & 0x3000) | (tempw & 0x4fd5) | 2; - else cpu_state.flags = (cpu_state.flags & 0x3200) | (tempw & 0x4dd5) | 2; - flags_extract(); + if ((cpu_state.eflags & VM_FLAG) && (IOPL < 3)) { + x86gpf(NULL, 0); + return 1; + } + + tempw = POP_W(); + if (cpu_state.abrt) + return 1; + + if (!(msw & 1)) + cpu_state.flags = (cpu_state.flags & 0x7000) | (tempw & 0x0fd5) | 2; + else if (!(CPL)) + cpu_state.flags = (tempw & 0x7fd5) | 2; + else if (IOPLp) + cpu_state.flags = (cpu_state.flags & 0x3000) | (tempw & 0x4fd5) | 2; + else + cpu_state.flags = (cpu_state.flags & 0x3200) | (tempw & 0x4dd5) | 2; + flags_extract(); + + CLOCK_CYCLES(5); + PREFETCH_RUN(5, 1, -1, 1, 0, 0, 0, 0); - CLOCK_CYCLES(5); - PREFETCH_RUN(5, 1, -1, 1,0,0,0, 0); - #if (defined(USE_DYNAREC) && defined(USE_NEW_DYNAREC)) - codegen_flags_changed = 0; + codegen_flags_changed = 0; #endif - return 0; + return 0; } -static int opPOPF(uint32_t fetchdat) +static int +opPOPF_286(uint32_t fetchdat) { - uint16_t tempw; - - if ((cpu_state.eflags & VM_FLAG) && (IOPL < 3)) - { - if (cr4 & CR4_VME) - { - uint32_t old_esp = ESP; + uint16_t tempw; - tempw = POP_W(); - if (cpu_state.abrt) - { + if ((cpu_state.eflags & VM_FLAG) && (IOPL < 3)) { + x86gpf(NULL, 0); + return 1; + } - ESP = old_esp; - return 1; - } + tempw = POP_W(); + if (cpu_state.abrt) + return 1; - if ((tempw & T_FLAG) || ((tempw & I_FLAG) && (cpu_state.eflags & VIP_FLAG))) - { - ESP = old_esp; - x86gpf(NULL, 0); - return 1; - } - if (tempw & I_FLAG) - cpu_state.eflags |= VIF_FLAG; - else - cpu_state.eflags &= ~VIF_FLAG; - cpu_state.flags = (cpu_state.flags & 0x3200) | (tempw & 0x4dd5) | 2; - } - else - { - x86gpf(NULL, 0); - return 1; - } + if (!(msw & 1)) + cpu_state.flags = (cpu_state.flags & 0x7000) | (tempw & 0x0fd5) | 2; + else if (!(CPL)) + cpu_state.flags = (tempw & 0x7fd5) | 2; + else if (IOPLp) + cpu_state.flags = (cpu_state.flags & 0x3000) | (tempw & 0x4fd5) | 2; + else + cpu_state.flags = (cpu_state.flags & 0x3200) | (tempw & 0x4dd5) | 2; + flags_extract(); + + CLOCK_CYCLES(5); + PREFETCH_RUN(5, 1, -1, 1, 0, 0, 0, 0); + +#if (defined(USE_DYNAREC) && defined(USE_NEW_DYNAREC)) + codegen_flags_changed = 0; +#endif + + return 0; +} +static int +opPOPF(uint32_t fetchdat) +{ + uint16_t tempw; + + if ((cpu_state.eflags & VM_FLAG) && (IOPL < 3)) { + if (cr4 & CR4_VME) { + uint32_t old_esp = ESP; + + tempw = POP_W(); + if (cpu_state.abrt) { + + ESP = old_esp; + return 1; + } + + if ((tempw & T_FLAG) || ((tempw & I_FLAG) && (cpu_state.eflags & VIP_FLAG))) { + ESP = old_esp; + x86gpf(NULL, 0); + return 1; + } + if (tempw & I_FLAG) + cpu_state.eflags |= VIF_FLAG; + else + cpu_state.eflags &= ~VIF_FLAG; + cpu_state.flags = (cpu_state.flags & 0x3200) | (tempw & 0x4dd5) | 2; + } else { + x86gpf(NULL, 0); + return 1; } + } else { + tempw = POP_W(); + if (cpu_state.abrt) + return 1; + + if (!(CPL) || !(msw & 1)) + cpu_state.flags = (tempw & 0x7fd5) | 2; + else if (IOPLp) + cpu_state.flags = (cpu_state.flags & 0x3000) | (tempw & 0x4fd5) | 2; else - { - tempw = POP_W(); - if (cpu_state.abrt) - return 1; + cpu_state.flags = (cpu_state.flags & 0x3200) | (tempw & 0x4dd5) | 2; + } + flags_extract(); - if (!(CPL) || !(msw & 1)) - cpu_state.flags = (tempw & 0x7fd5) | 2; - else if (IOPLp) - cpu_state.flags = (cpu_state.flags & 0x3000) | (tempw & 0x4fd5) | 2; - else - cpu_state.flags = (cpu_state.flags & 0x3200) | (tempw & 0x4dd5) | 2; - } - flags_extract(); + CLOCK_CYCLES(5); + PREFETCH_RUN(5, 1, -1, 1, 0, 0, 0, 0); - CLOCK_CYCLES(5); - PREFETCH_RUN(5, 1, -1, 1,0,0,0, 0); - #if (defined(USE_DYNAREC) && defined(USE_NEW_DYNAREC)) - codegen_flags_changed = 0; + codegen_flags_changed = 0; #endif - return 0; + return 0; } -static int opPOPFD(uint32_t fetchdat) +static int +opPOPFD(uint32_t fetchdat) { - uint32_t templ; - - if ((cpu_state.eflags & VM_FLAG) && (IOPL < 3)) - { - x86gpf(NULL, 0); - return 1; - } - - templ = POP_L(); if (cpu_state.abrt) return 1; + uint32_t templ; - if (!(CPL) || !(msw & 1)) cpu_state.flags = (templ & 0x7fd5) | 2; - else if (IOPLp) cpu_state.flags = (cpu_state.flags & 0x3000) | (templ & 0x4fd5) | 2; - else cpu_state.flags = (cpu_state.flags & 0x3200) | (templ & 0x4dd5) | 2; - - templ &= (is486 || isibm486) ? 0x3c0000 : 0; - templ |= ((cpu_state.eflags&3) << 16); - if (cpu_CR4_mask & CR4_VME) cpu_state.eflags = (templ >> 16) & 0x3f; - else if (CPUID) cpu_state.eflags = (templ >> 16) & 0x27; - else if (is486 || isibm486) cpu_state.eflags = (templ >> 16) & 7; - else cpu_state.eflags = (templ >> 16) & 3; - - flags_extract(); + if ((cpu_state.eflags & VM_FLAG) && (IOPL < 3)) { + x86gpf(NULL, 0); + return 1; + } + + templ = POP_L(); + if (cpu_state.abrt) + return 1; + + if (!(CPL) || !(msw & 1)) + cpu_state.flags = (templ & 0x7fd5) | 2; + else if (IOPLp) + cpu_state.flags = (cpu_state.flags & 0x3000) | (templ & 0x4fd5) | 2; + else + cpu_state.flags = (cpu_state.flags & 0x3200) | (templ & 0x4dd5) | 2; + + templ &= (is486 || isibm486) ? 0x3c0000 : 0; + templ |= ((cpu_state.eflags & 3) << 16); + if (cpu_CR4_mask & CR4_VME) + cpu_state.eflags = (templ >> 16) & 0x3f; + else if (CPUID) + cpu_state.eflags = (templ >> 16) & 0x27; + else if (is486 || isibm486) + cpu_state.eflags = (templ >> 16) & 7; + else + cpu_state.eflags = (templ >> 16) & 3; + + flags_extract(); + + CLOCK_CYCLES(5); + PREFETCH_RUN(5, 1, -1, 0, 1, 0, 0, 0); - CLOCK_CYCLES(5); - PREFETCH_RUN(5, 1, -1, 0,1,0,0, 0); - #if (defined(USE_DYNAREC) && defined(USE_NEW_DYNAREC)) - codegen_flags_changed = 0; + codegen_flags_changed = 0; #endif - return 0; + return 0; } diff --git a/src/cpu/x86_ops_fpu.h b/src/cpu/x86_ops_fpu.h index a1976f268..849e24e3d 100644 --- a/src/cpu/x86_ops_fpu.h +++ b/src/cpu/x86_ops_fpu.h @@ -1,85 +1,113 @@ /* Copyright holders: Sarah Walker see COPYING for more details */ -static int opESCAPE_d8_a16(uint32_t fetchdat) +static int +opESCAPE_d8_a16(uint32_t fetchdat) { - return x86_opcodes_d8_a16[(fetchdat >> 3) & 0x1f](fetchdat); + return x86_opcodes_d8_a16[(fetchdat >> 3) & 0x1f](fetchdat); } -static int opESCAPE_d8_a32(uint32_t fetchdat) +static int +opESCAPE_d8_a32(uint32_t fetchdat) { - return x86_opcodes_d8_a32[(fetchdat >> 3) & 0x1f](fetchdat); + return x86_opcodes_d8_a32[(fetchdat >> 3) & 0x1f](fetchdat); } -static int opESCAPE_d9_a16(uint32_t fetchdat) +static int +opESCAPE_d9_a16(uint32_t fetchdat) { - return x86_opcodes_d9_a16[fetchdat & 0xff](fetchdat); + return x86_opcodes_d9_a16[fetchdat & 0xff](fetchdat); } -static int opESCAPE_d9_a32(uint32_t fetchdat) +static int +opESCAPE_d9_a32(uint32_t fetchdat) { - return x86_opcodes_d9_a32[fetchdat & 0xff](fetchdat); + return x86_opcodes_d9_a32[fetchdat & 0xff](fetchdat); } -static int opESCAPE_da_a16(uint32_t fetchdat) +static int +opESCAPE_da_a16(uint32_t fetchdat) { - return x86_opcodes_da_a16[fetchdat & 0xff](fetchdat); + return x86_opcodes_da_a16[fetchdat & 0xff](fetchdat); } -static int opESCAPE_da_a32(uint32_t fetchdat) +static int +opESCAPE_da_a32(uint32_t fetchdat) { - return x86_opcodes_da_a32[fetchdat & 0xff](fetchdat); + return x86_opcodes_da_a32[fetchdat & 0xff](fetchdat); } -static int opESCAPE_db_a16(uint32_t fetchdat) +static int +opESCAPE_db_a16(uint32_t fetchdat) { - return x86_opcodes_db_a16[fetchdat & 0xff](fetchdat); + return x86_opcodes_db_a16[fetchdat & 0xff](fetchdat); } -static int opESCAPE_db_a32(uint32_t fetchdat) +static int +opESCAPE_db_a32(uint32_t fetchdat) { - return x86_opcodes_db_a32[fetchdat & 0xff](fetchdat); + return x86_opcodes_db_a32[fetchdat & 0xff](fetchdat); } -static int opESCAPE_dc_a16(uint32_t fetchdat) +static int +opESCAPE_dc_a16(uint32_t fetchdat) { - return x86_opcodes_dc_a16[(fetchdat >> 3) & 0x1f](fetchdat); + return x86_opcodes_dc_a16[(fetchdat >> 3) & 0x1f](fetchdat); } -static int opESCAPE_dc_a32(uint32_t fetchdat) +static int +opESCAPE_dc_a32(uint32_t fetchdat) { - return x86_opcodes_dc_a32[(fetchdat >> 3) & 0x1f](fetchdat); + return x86_opcodes_dc_a32[(fetchdat >> 3) & 0x1f](fetchdat); } -static int opESCAPE_dd_a16(uint32_t fetchdat) +static int +opESCAPE_dd_a16(uint32_t fetchdat) { - return x86_opcodes_dd_a16[fetchdat & 0xff](fetchdat); + return x86_opcodes_dd_a16[fetchdat & 0xff](fetchdat); } -static int opESCAPE_dd_a32(uint32_t fetchdat) +static int +opESCAPE_dd_a32(uint32_t fetchdat) { - return x86_opcodes_dd_a32[fetchdat & 0xff](fetchdat); + return x86_opcodes_dd_a32[fetchdat & 0xff](fetchdat); } -static int opESCAPE_de_a16(uint32_t fetchdat) +static int +opESCAPE_de_a16(uint32_t fetchdat) { - return x86_opcodes_de_a16[fetchdat & 0xff](fetchdat); + return x86_opcodes_de_a16[fetchdat & 0xff](fetchdat); } -static int opESCAPE_de_a32(uint32_t fetchdat) +static int +opESCAPE_de_a32(uint32_t fetchdat) { - return x86_opcodes_de_a32[fetchdat & 0xff](fetchdat); + return x86_opcodes_de_a32[fetchdat & 0xff](fetchdat); } -static int opESCAPE_df_a16(uint32_t fetchdat) +static int +opESCAPE_df_a16(uint32_t fetchdat) { - return x86_opcodes_df_a16[fetchdat & 0xff](fetchdat); + return x86_opcodes_df_a16[fetchdat & 0xff](fetchdat); } -static int opESCAPE_df_a32(uint32_t fetchdat) +static int +opESCAPE_df_a32(uint32_t fetchdat) { - return x86_opcodes_df_a32[fetchdat & 0xff](fetchdat); + return x86_opcodes_df_a32[fetchdat & 0xff](fetchdat); } -static int opWAIT(uint32_t fetchdat) +static int +opWAIT(uint32_t fetchdat) { - if ((cr0 & 0xa) == 0xa) - { - x86_int(7); + if ((cr0 & 0xa) == 0xa) { + x86_int(7); + return 1; + } + +#if 0 + if (!cpu_use_dynarec && fpu_softfloat) { +#endif + if (fpu_softfloat) { + if (fpu_state.swd & FPU_SW_Summary) { + if (cr0 & 0x20) { + x86_int(16); return 1; + } } - CLOCK_CYCLES(4); - return 0; + } + CLOCK_CYCLES(4); + return 0; } diff --git a/src/cpu/x86_ops_i686.h b/src/cpu/x86_ops_i686.h index 3f2d85766..ab9d02d25 100644 --- a/src/cpu/x86_ops_i686.h +++ b/src/cpu/x86_ops_i686.h @@ -1,17 +1,17 @@ /* - * 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. + * 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. + * This file is part of the 86Box distribution. * - * x86 i686 (Pentium Pro/Pentium II) CPU Instructions. + * x86 i686 (Pentium Pro/Pentium II) CPU Instructions. * * * - * Author: Miran Grca, - * Copyright 2016-2020 Miran Grca. + * Authors: Miran Grca, + * Copyright 2016-2020 Miran Grca. */ static int opSYSENTER(uint32_t fetchdat) @@ -19,65 +19,248 @@ opSYSENTER(uint32_t fetchdat) int ret = sysenter(fetchdat); if (ret <= 1) { - CLOCK_CYCLES(20); - PREFETCH_RUN(20, 7, -1, 0,0,0,0, 0); - PREFETCH_FLUSH(); - CPU_BLOCK_END(); + CLOCK_CYCLES(20); + PREFETCH_RUN(20, 7, -1, 0, 0, 0, 0, 0); + PREFETCH_FLUSH(); + CPU_BLOCK_END(); } return ret; } - static int opSYSEXIT(uint32_t fetchdat) { int ret = sysexit(fetchdat); if (ret <= 1) { - CLOCK_CYCLES(20); - PREFETCH_RUN(20, 7, -1, 0,0,0,0, 0); - PREFETCH_FLUSH(); - CPU_BLOCK_END(); + CLOCK_CYCLES(20); + PREFETCH_RUN(20, 7, -1, 0, 0, 0, 0, 0); + PREFETCH_FLUSH(); + CPU_BLOCK_END(); } return ret; } - static int -fx_save_stor_common(uint32_t fetchdat, int bits) +sf_fx_save_stor_common(uint32_t fetchdat, int bits) { - uint8_t fxinst = 0; - uint16_t twd = x87_gettag(); - uint32_t old_eaaddr = 0; - uint8_t ftwb = 0; - uint16_t rec_ftw = 0; - uint16_t fpus = 0; - uint64_t *p; + uint8_t fxinst = 0; + uint32_t tag_byte; + unsigned index; + floatx80 reg; if (CPUID < 0x650) - return ILLEGAL(fetchdat); + return ILLEGAL(fetchdat); FP_ENTER(); if (bits == 32) { - fetch_ea_32(fetchdat); + fetch_ea_32(fetchdat); } else { - fetch_ea_16(fetchdat); + 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; + 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; + 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) +{ + uint8_t fxinst = 0; + uint16_t twd = x87_gettag(); + uint32_t old_eaaddr = 0; + uint8_t ftwb = 0; + uint16_t rec_ftw = 0; + uint16_t fpus = 0; + int i; + int mmx_tags = 0; + uint16_t exp = 0x0000; + uint64_t mant = 0x0000000000000000ULL; + uint64_t fraction; + uint8_t jm; + uint8_t valid; + /* Exp_all_1 Exp_all_0 Frac_all_0 J M FTW_Valid | Ent + ----------------------------------------------+------ */ + uint8_t ftw_table_idx; + uint8_t ftw_table[48] = { 0x03, /* 0 0 0 0 0 0 | 0x00 */ + 0x02, /* 0 0 0 0 0 1 | 0x01 */ + 0x03, /* 0 0 0 0 0 0 | 0x02 */ + 0x02, /* 0 0 0 0 1 1 | 0x03 */ + 0x03, /* 0 0 0 1 0 0 | 0x04 */ + 0x00, /* 0 0 0 1 0 1 | 0x05 */ + 0x03, /* 0 0 0 1 1 0 | 0x06 */ + 0x00, /* 0 0 0 1 1 1 | 0x07 */ + 0x03, /* 0 0 1 0 0 0 | 0x08 */ + 0x02, /* 0 0 1 0 0 1 | 0x09 */ + 0x03, /* 0 0 1 0 1 0 | 0x0a - Impossible */ + 0x03, /* 0 0 1 0 1 1 | 0x0b - Impossible */ + 0x03, /* 0 0 1 1 0 0 | 0x0c */ + 0x02, /* 0 0 1 1 0 1 | 0x0d */ + 0x03, /* 0 0 1 1 1 0 | 0x0e - Impossible */ + 0x03, /* 0 0 1 1 1 1 | 0x0f - Impossible */ + 0x03, /* 0 1 0 0 0 0 | 0x10 */ + 0x02, /* 0 1 0 0 0 1 | 0x11 */ + 0x03, /* 0 1 0 0 1 0 | 0x12 */ + 0x02, /* 0 1 0 0 1 1 | 0x13 */ + 0x03, /* 0 1 0 1 0 0 | 0x14 */ + 0x02, /* 0 1 0 1 0 1 | 0x15 */ + 0x03, /* 0 1 0 1 1 0 | 0x16 */ + 0x02, /* 0 1 0 1 1 1 | 0x17 */ + 0x03, /* 0 1 1 0 0 0 | 0x18 */ + 0x01, /* 0 1 1 0 0 1 | 0x19 */ + 0x03, /* 0 1 1 0 1 0 | 0x1a - Impossible */ + 0x03, /* 0 1 1 0 1 1 | 0x1b - Impossible */ + 0x03, /* 0 1 1 1 0 0 | 0x1c */ + 0x01, /* 0 1 1 1 0 1 | 0x1d */ + 0x03, /* 0 1 1 1 1 0 | 0x1e - Impossible */ + 0x03, /* 0 1 1 1 1 1 | 0x1f - Impossible */ + 0x03, /* 1 0 0 0 0 0 | 0x20 */ + 0x02, /* 1 0 0 0 0 1 | 0x21 */ + 0x03, /* 1 0 0 0 1 0 | 0x22 */ + 0x02, /* 1 0 0 0 1 1 | 0x23 */ + 0x03, /* 1 0 0 1 0 0 | 0x24 */ + 0x02, /* 1 0 0 1 0 1 | 0x25 */ + 0x03, /* 1 0 0 1 1 0 | 0x26 */ + 0x02, /* 1 0 0 1 1 1 | 0x27 */ + 0x03, /* 1 0 1 0 0 0 | 0x28 */ + 0x02, /* 1 0 1 0 0 1 | 0x29 */ + 0x03, /* 1 0 1 0 1 0 | 0x2a - Impossible */ + 0x03, /* 1 0 1 0 1 1 | 0x2b - Impossible */ + 0x03, /* 1 0 1 1 0 0 | 0x2c */ + 0x02, /* 1 0 1 1 0 1 | 0x2d */ + 0x03, /* 1 0 1 1 1 0 | 0x2e - Impossible */ + 0x03 }; /* 1 0 1 1 1 1 | 0x2f - Impossible */ + /* M is the most significant bit of the franction, so it is impossible + for M to o be 1 when the fraction is all 0's. */ + + 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(); @@ -85,170 +268,148 @@ fx_save_stor_common(uint32_t fetchdat, int bits) old_eaaddr = cpu_state.eaaddr; if (fxinst == 1) { - /* FXRSTOR */ - cpu_state.npxc = readmemw(easeg, cpu_state.eaaddr); - fpus = readmemw(easeg, cpu_state.eaaddr + 2); - cpu_state.npxc = (cpu_state.npxc & ~FPU_CW_Reserved_Bits) | 0x0040; - codegen_set_rounding_mode((cpu_state.npxc >> 10) & 3); - cpu_state.TOP = (fpus >> 11) & 7; - cpu_state.npxs &= fpus & ~0x3800; + /* FXRSTOR */ + cpu_state.npxc = readmemw(easeg, cpu_state.eaaddr); + fpus = readmemw(easeg, cpu_state.eaaddr + 2); + cpu_state.npxc = (cpu_state.npxc & ~FPU_CW_Reserved_Bits) | 0x0040; + codegen_set_rounding_mode((cpu_state.npxc >> 10) & 3); + cpu_state.TOP = (fpus >> 11) & 7; + cpu_state.npxs &= fpus & ~0x3800; - x87_pc_off = readmeml(easeg, cpu_state.eaaddr+8); - x87_pc_seg = readmemw(easeg, cpu_state.eaaddr+12); + x87_pc_off = readmeml(easeg, cpu_state.eaaddr + 8); + x87_pc_seg = readmemw(easeg, cpu_state.eaaddr + 12); - ftwb = readmemb(easeg, cpu_state.eaaddr + 4); + ftwb = readmemb(easeg, cpu_state.eaaddr + 4); - if (ftwb & 0x01) rec_ftw |= 0x0003; - if (ftwb & 0x02) rec_ftw |= 0x000C; - if (ftwb & 0x04) rec_ftw |= 0x0030; - if (ftwb & 0x08) rec_ftw |= 0x00C0; - if (ftwb & 0x10) rec_ftw |= 0x0300; - if (ftwb & 0x20) rec_ftw |= 0x0C00; - if (ftwb & 0x40) rec_ftw |= 0x3000; - if (ftwb & 0x80) rec_ftw |= 0xC000; + x87_op_off = readmeml(easeg, cpu_state.eaaddr + 16); + x87_op_off |= (readmemw(easeg, cpu_state.eaaddr + 6) >> 12) << 16; + x87_op_seg = readmemw(easeg, cpu_state.eaaddr + 20); - x87_op_off = readmeml(easeg, cpu_state.eaaddr+16); - x87_op_off |= (readmemw(easeg, cpu_state.eaaddr + 6) >> 12) << 16; - x87_op_seg = readmemw(easeg, cpu_state.eaaddr+20); + for (i = 0; i <= 7; i++) { + cpu_state.eaaddr = old_eaaddr + 32 + (i << 4); + mant = readmemq(easeg, cpu_state.eaaddr); + fraction = mant & 0x7fffffffffffffffULL; + exp = readmemw(easeg, cpu_state.eaaddr + 8); + jm = (mant >> 62) & 0x03; + valid = !(ftwb & (1 << i)); - cpu_state.eaaddr = old_eaaddr + 32; - x87_ldmmx(&(cpu_state.MM[0]), &(cpu_state.MM_w4[0])); x87_ld_frstor(0); + ftw_table_idx = (!!(exp == 0x1111)) << 5; + ftw_table_idx |= (!!(exp == 0x0000)) << 4; + ftw_table_idx |= (!!(fraction == 0x0000000000000000ULL)) << 3; + ftw_table_idx |= (jm << 1); + ftw_table_idx |= valid; - cpu_state.eaaddr = old_eaaddr + 48; - x87_ldmmx(&(cpu_state.MM[1]), &(cpu_state.MM_w4[1])); x87_ld_frstor(1); + rec_ftw |= (ftw_table[ftw_table_idx] << (i << 1)); - cpu_state.eaaddr = old_eaaddr + 64; - x87_ldmmx(&(cpu_state.MM[2]), &(cpu_state.MM_w4[2])); x87_ld_frstor(2); + if (exp == 0xffff) + mmx_tags++; + } - cpu_state.eaaddr = old_eaaddr + 80; - x87_ldmmx(&(cpu_state.MM[3]), &(cpu_state.MM_w4[3])); x87_ld_frstor(3); + cpu_state.ismmx = 0; + /* Determine, whether or not the saved state is x87 or MMX based on a heuristic, + because we do not keep the internal state in 64-bit precision. - cpu_state.eaaddr = old_eaaddr + 96; - x87_ldmmx(&(cpu_state.MM[4]), &(cpu_state.MM_w4[4])); x87_ld_frstor(4); + TODO: Is there no way to unify the whole lot? */ + if ((mmx_tags == 8) && !cpu_state.TOP) + cpu_state.ismmx = 1; - cpu_state.eaaddr = old_eaaddr + 112; - x87_ldmmx(&(cpu_state.MM[5]), &(cpu_state.MM_w4[5])); x87_ld_frstor(5); + x87_settag(rec_ftw); - cpu_state.eaaddr = old_eaaddr + 128; - x87_ldmmx(&(cpu_state.MM[6]), &(cpu_state.MM_w4[6])); x87_ld_frstor(6); + if (cpu_state.ismmx) { + for (i = 0; i <= 7; i++) { + cpu_state.eaaddr = old_eaaddr + 32 + (i << 4); + x87_ldmmx(&(cpu_state.MM[i]), &(cpu_state.MM_w4[i])); + } + } else { + for (i = 0; i <= 7; i++) { + cpu_state.eaaddr = old_eaaddr + 32 + (i << 4); + x87_ld_frstor(i); + } + } - cpu_state.eaaddr = old_eaaddr + 144; - x87_ldmmx(&(cpu_state.MM[7]), &(cpu_state.MM_w4[7])); x87_ld_frstor(7); - - cpu_state.ismmx = 0; - /*Horrible hack, but as 86Box doesn't keep the FPU stack in 80-bit precision at all times - something like this is needed*/ - p = (uint64_t *) cpu_state.tag; -#ifdef USE_NEW_DYNAREC - if (cpu_state.MM_w4[0] == 0xffff && cpu_state.MM_w4[1] == 0xffff && cpu_state.MM_w4[2] == 0xffff && cpu_state.MM_w4[3] == 0xffff && - cpu_state.MM_w4[4] == 0xffff && cpu_state.MM_w4[5] == 0xffff && cpu_state.MM_w4[6] == 0xffff && cpu_state.MM_w4[7] == 0xffff && - !cpu_state.TOP && (*p == 0x0101010101010101ull)) -#else - if (cpu_state.MM_w4[0] == 0xffff && cpu_state.MM_w4[1] == 0xffff && cpu_state.MM_w4[2] == 0xffff && cpu_state.MM_w4[3] == 0xffff && - cpu_state.MM_w4[4] == 0xffff && cpu_state.MM_w4[5] == 0xffff && cpu_state.MM_w4[6] == 0xffff && cpu_state.MM_w4[7] == 0xffff && - !cpu_state.TOP && !(*p)) -#endif - cpu_state.ismmx = 1; - - x87_settag(rec_ftw); - - CLOCK_CYCLES((cr0 & 1) ? 34 : 44); + CLOCK_CYCLES((cr0 & 1) ? 34 : 44); } else { - /* FXSAVE */ - if ((twd & 0x0003) == 0x0003) ftwb |= 0x01; - if ((twd & 0x000C) == 0x000C) ftwb |= 0x02; - if ((twd & 0x0030) == 0x0030) ftwb |= 0x04; - if ((twd & 0x00C0) == 0x00C0) ftwb |= 0x08; - if ((twd & 0x0300) == 0x0300) ftwb |= 0x10; - if ((twd & 0x0C00) == 0x0C00) ftwb |= 0x20; - if ((twd & 0x3000) == 0x3000) ftwb |= 0x40; - if ((twd & 0xC000) == 0xC000) ftwb |= 0x80; + /* FXSAVE */ + if ((twd & 0x0003) != 0x0003) + ftwb |= 0x01; + if ((twd & 0x000c) != 0x000c) + ftwb |= 0x02; + if ((twd & 0x0030) != 0x0030) + ftwb |= 0x04; + if ((twd & 0x00c0) != 0x00c0) + ftwb |= 0x08; + if ((twd & 0x0300) != 0x0300) + ftwb |= 0x10; + if ((twd & 0x0c00) != 0x0c00) + ftwb |= 0x20; + if ((twd & 0x3000) != 0x3000) + ftwb |= 0x40; + if ((twd & 0xc000) != 0xc000) + ftwb |= 0x80; - writememw(easeg,cpu_state.eaaddr,cpu_state.npxc); - writememw(easeg,cpu_state.eaaddr+2,cpu_state.npxs); - writememb(easeg,cpu_state.eaaddr+4,ftwb); + writememw(easeg, cpu_state.eaaddr, cpu_state.npxc); + writememw(easeg, cpu_state.eaaddr + 2, cpu_state.npxs); + writememb(easeg, cpu_state.eaaddr + 4, ftwb); - writememw(easeg,cpu_state.eaaddr+6,(x87_op_off>>16)<<12); - writememl(easeg,cpu_state.eaaddr+8,x87_pc_off); - writememw(easeg,cpu_state.eaaddr+12,x87_pc_seg); + writememw(easeg, cpu_state.eaaddr + 6, (x87_op_off >> 16) << 12); + writememl(easeg, cpu_state.eaaddr + 8, x87_pc_off); + writememw(easeg, cpu_state.eaaddr + 12, x87_pc_seg); - writememl(easeg,cpu_state.eaaddr+16,x87_op_off); - writememw(easeg,cpu_state.eaaddr+20,x87_op_seg); + writememl(easeg, cpu_state.eaaddr + 16, x87_op_off); + writememw(easeg, cpu_state.eaaddr + 20, x87_op_seg); - cpu_state.eaaddr = old_eaaddr + 32; - cpu_state.ismmx ? x87_stmmx(cpu_state.MM[0]) : x87_st_fsave(0); + if (cpu_state.ismmx) { + for (i = 0; i <= 7; i++) { + cpu_state.eaaddr = old_eaaddr + 32 + (i << 4); + x87_stmmx(cpu_state.MM[i]); + } + } else { + for (i = 0; i <= 7; i++) { + cpu_state.eaaddr = old_eaaddr + 32 + (i << 4); + x87_st_fsave(i); + } + } - cpu_state.eaaddr = old_eaaddr + 48; - cpu_state.ismmx ? x87_stmmx(cpu_state.MM[1]) : x87_st_fsave(1); + cpu_state.eaaddr = old_eaaddr; - cpu_state.eaaddr = old_eaaddr + 64; - cpu_state.ismmx ? x87_stmmx(cpu_state.MM[2]) : x87_st_fsave(2); - - cpu_state.eaaddr = old_eaaddr + 80; - cpu_state.ismmx ? x87_stmmx(cpu_state.MM[3]) : x87_st_fsave(3); - - cpu_state.eaaddr = old_eaaddr + 96; - cpu_state.ismmx ? x87_stmmx(cpu_state.MM[4]) : x87_st_fsave(4); - - cpu_state.eaaddr = old_eaaddr + 112; - cpu_state.ismmx ? x87_stmmx(cpu_state.MM[5]) : x87_st_fsave(5); - - cpu_state.eaaddr = old_eaaddr + 128; - cpu_state.ismmx ? x87_stmmx(cpu_state.MM[6]) : x87_st_fsave(6); - - cpu_state.eaaddr = old_eaaddr + 144; - cpu_state.ismmx ? x87_stmmx(cpu_state.MM[7]) : x87_st_fsave(7); - - cpu_state.eaaddr = old_eaaddr; - - cpu_state.npxc = 0x37F; - codegen_set_rounding_mode(X87_ROUNDING_NEAREST); - cpu_state.npxs = 0; - p = (uint64_t *)cpu_state.tag; -#ifdef USE_NEW_DYNAREC - *p = 0; -#else - *p = 0x0303030303030303ll; -#endif - cpu_state.TOP = 0; - cpu_state.ismmx = 0; - - CLOCK_CYCLES((cr0 & 1) ? 56 : 67); + CLOCK_CYCLES((cr0 & 1) ? 56 : 67); } return cpu_state.abrt; } - 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); } - static int opHINT_NOP_a16(uint32_t fetchdat) { fetch_ea_16(fetchdat); CLOCK_CYCLES((is486) ? 1 : 3); - PREFETCH_RUN(3, 1, -1, 0,0,0,0, 0); + PREFETCH_RUN(3, 1, -1, 0, 0, 0, 0, 0); return 0; } - static int opHINT_NOP_a32(uint32_t fetchdat) { fetch_ea_32(fetchdat); CLOCK_CYCLES((is486) ? 1 : 3); - PREFETCH_RUN(3, 1, -1, 0,0,0,0, 0); + PREFETCH_RUN(3, 1, -1, 0, 0, 0, 0, 0); return 0; } diff --git a/src/cpu/x86_ops_inc_dec.h b/src/cpu/x86_ops_inc_dec.h index ff4a4ab73..3eb908c57 100644 --- a/src/cpu/x86_ops_inc_dec.h +++ b/src/cpu/x86_ops_inc_dec.h @@ -1,12 +1,12 @@ -#define INC_DEC_OP(name, reg, inc, setflags) \ - static int op ## name (uint32_t fetchdat) \ - { \ - setflags(reg, 1); \ - reg += inc; \ - CLOCK_CYCLES(timing_rr); \ - PREFETCH_RUN(timing_rr, 1, -1, 0,0,0,0, 0); \ - return 0; \ - } +#define INC_DEC_OP(name, reg, inc, setflags) \ + static int op##name(uint32_t fetchdat) \ + { \ + setflags(reg, 1); \ + reg += inc; \ + CLOCK_CYCLES(timing_rr); \ + PREFETCH_RUN(timing_rr, 1, -1, 0, 0, 0, 0, 0); \ + return 0; \ + } INC_DEC_OP(INC_AX, AX, 1, setadd16nc) INC_DEC_OP(INC_BX, BX, 1, setadd16nc) @@ -44,50 +44,57 @@ INC_DEC_OP(DEC_EDI, EDI, -1, setsub32nc) INC_DEC_OP(DEC_EBP, EBP, -1, setsub32nc) INC_DEC_OP(DEC_ESP, ESP, -1, setsub32nc) - -static int opINCDEC_b_a16(uint32_t fetchdat) +static int +opINCDEC_b_a16(uint32_t fetchdat) { - uint8_t temp; - - fetch_ea_16(fetchdat); - if (cpu_mod != 3) - SEG_CHECK_WRITE(cpu_state.ea_seg); - temp=geteab(); if (cpu_state.abrt) return 1; + uint8_t temp; - if (rmdat&0x38) - { - seteab(temp - 1); if (cpu_state.abrt) return 1; - setsub8nc(temp, 1); - } - else - { - seteab(temp + 1); if (cpu_state.abrt) return 1; - setadd8nc(temp, 1); - } - CLOCK_CYCLES((cpu_mod == 3) ? timing_rr : timing_mm); - PREFETCH_RUN((cpu_mod == 3) ? timing_rr : timing_mm, 2, rmdat, (cpu_mod == 3) ? 0:1,0,(cpu_mod == 3) ? 0:1,0, 0); - return 0; + fetch_ea_16(fetchdat); + if (cpu_mod != 3) + SEG_CHECK_WRITE(cpu_state.ea_seg); + temp = geteab(); + if (cpu_state.abrt) + return 1; + + if (rmdat & 0x38) { + seteab(temp - 1); + if (cpu_state.abrt) + return 1; + setsub8nc(temp, 1); + } else { + seteab(temp + 1); + if (cpu_state.abrt) + return 1; + setadd8nc(temp, 1); + } + CLOCK_CYCLES((cpu_mod == 3) ? timing_rr : timing_mm); + PREFETCH_RUN((cpu_mod == 3) ? timing_rr : timing_mm, 2, rmdat, (cpu_mod == 3) ? 0 : 1, 0, (cpu_mod == 3) ? 0 : 1, 0, 0); + return 0; } -static int opINCDEC_b_a32(uint32_t fetchdat) +static int +opINCDEC_b_a32(uint32_t fetchdat) { - uint8_t temp; - - fetch_ea_32(fetchdat); - if (cpu_mod != 3) - SEG_CHECK_WRITE(cpu_state.ea_seg); - temp=geteab(); if (cpu_state.abrt) return 1; + uint8_t temp; - if (rmdat&0x38) - { - seteab(temp - 1); if (cpu_state.abrt) return 1; - setsub8nc(temp, 1); - } - else - { - seteab(temp + 1); if (cpu_state.abrt) return 1; - setadd8nc(temp, 1); - } - CLOCK_CYCLES((cpu_mod == 3) ? timing_rr : timing_mm); - PREFETCH_RUN((cpu_mod == 3) ? timing_rr : timing_mm, 2, rmdat, (cpu_mod == 3) ? 0:1,0,(cpu_mod == 3) ? 0:1,0, 1); - return 0; + fetch_ea_32(fetchdat); + if (cpu_mod != 3) + SEG_CHECK_WRITE(cpu_state.ea_seg); + temp = geteab(); + if (cpu_state.abrt) + return 1; + + if (rmdat & 0x38) { + seteab(temp - 1); + if (cpu_state.abrt) + return 1; + setsub8nc(temp, 1); + } else { + seteab(temp + 1); + if (cpu_state.abrt) + return 1; + setadd8nc(temp, 1); + } + CLOCK_CYCLES((cpu_mod == 3) ? timing_rr : timing_mm); + PREFETCH_RUN((cpu_mod == 3) ? timing_rr : timing_mm, 2, rmdat, (cpu_mod == 3) ? 0 : 1, 0, (cpu_mod == 3) ? 0 : 1, 0, 1); + return 0; } diff --git a/src/cpu/x86_ops_int.h b/src/cpu/x86_ops_int.h index 4e18e6f4b..a73ed62e0 100644 --- a/src/cpu/x86_ops_int.h +++ b/src/cpu/x86_ops_int.h @@ -1,91 +1,96 @@ -static int opINT3(uint32_t fetchdat) +static int +opINT3(uint32_t fetchdat) { - int cycles_old = cycles; UN_USED(cycles_old); - if ((cr0 & 1) && (cpu_state.eflags & VM_FLAG) && (IOPL != 3)) - { - x86gpf(NULL,0); - return 1; - } - x86_int_sw(3); - CLOCK_CYCLES((is486) ? 44 : 59); - PREFETCH_RUN(cycles_old-cycles, 1, -1, 0,0,0,0, 0); + int cycles_old = cycles; + UN_USED(cycles_old); +#ifdef USE_GDBSTUB + if (gdbstub_int3()) return 1; +#endif + if ((cr0 & 1) && (cpu_state.eflags & VM_FLAG) && (IOPL != 3)) { + x86gpf(NULL, 0); + return 1; + } + x86_int_sw(3); + CLOCK_CYCLES((is486) ? 44 : 59); + PREFETCH_RUN(cycles_old - cycles, 1, -1, 0, 0, 0, 0, 0); + return 1; } -static int opINT1(uint32_t fetchdat) +static int +opINT1(uint32_t fetchdat) { - int cycles_old = cycles; UN_USED(cycles_old); - if ((cr0 & 1) && (cpu_state.eflags & VM_FLAG) && (IOPL != 3)) - { - x86gpf(NULL,0); - return 1; - } - x86_int_sw(1); - CLOCK_CYCLES((is486) ? 44 : 59); - PREFETCH_RUN(cycles_old-cycles, 1, -1, 0,0,0,0, 0); + int cycles_old = cycles; + UN_USED(cycles_old); + if ((cr0 & 1) && (cpu_state.eflags & VM_FLAG) && (IOPL != 3)) { + x86gpf(NULL, 0); return 1; + } + x86_int_sw(1); + CLOCK_CYCLES((is486) ? 44 : 59); + PREFETCH_RUN(cycles_old - cycles, 1, -1, 0, 0, 0, 0, 0); + return 1; } -static int opINT(uint32_t fetchdat) +static int +opINT(uint32_t fetchdat) { - int cycles_old = cycles; UN_USED(cycles_old); - uint8_t temp = getbytef(); + int cycles_old = cycles; + UN_USED(cycles_old); + uint8_t temp = getbytef(); - if ((cr0 & 1) && (cpu_state.eflags & VM_FLAG) && (IOPL != 3)) - { - if (cr4 & CR4_VME) - { - uint16_t t; - uint8_t d; + if ((cr0 & 1) && (cpu_state.eflags & VM_FLAG) && (IOPL != 3)) { + if (cr4 & CR4_VME) { + uint16_t t; + uint8_t d; - cpl_override = 1; - t = readmemw(tr.base, 0x66) - 32; - cpl_override = 0; - if (cpu_state.abrt) return 1; + cpl_override = 1; + t = readmemw(tr.base, 0x66) - 32; + cpl_override = 0; + if (cpu_state.abrt) + return 1; - t += (temp >> 3); - if (t <= tr.limit) - { - cpl_override = 1; - d = readmemb(tr.base, t);// + (temp >> 3)); - cpl_override = 0; - if (cpu_state.abrt) return 1; + t += (temp >> 3); + if (t <= tr.limit) { + cpl_override = 1; + d = readmemb(tr.base, t); // + (temp >> 3)); + cpl_override = 0; + if (cpu_state.abrt) + return 1; - if (!(d & (1 << (temp & 7)))) - { - x86_int_sw_rm(temp); - PREFETCH_RUN(cycles_old-cycles, 2, -1, 0,0,0,0, 0); - return 1; - } - } + if (!(d & (1 << (temp & 7)))) { + x86_int_sw_rm(temp); + PREFETCH_RUN(cycles_old - cycles, 2, -1, 0, 0, 0, 0, 0); + return 1; } - x86gpf_expected(NULL,0); - return 1; + } } - - x86_int_sw(temp); - PREFETCH_RUN(cycles_old-cycles, 2, -1, 0,0,0,0, 0); + x86gpf_expected(NULL, 0); return 1; + } + + x86_int_sw(temp); + PREFETCH_RUN(cycles_old - cycles, 2, -1, 0, 0, 0, 0, 0); + return 1; } -static int opINTO(uint32_t fetchdat) +static int +opINTO(uint32_t fetchdat) { - int cycles_old = cycles; UN_USED(cycles_old); - - if ((cr0 & 1) && (cpu_state.eflags & VM_FLAG) && (IOPL != 3)) - { - x86gpf(NULL,0); - return 1; - } - if (VF_SET()) - { - cpu_state.oldpc = cpu_state.pc; - x86_int_sw(4); - PREFETCH_RUN(cycles_old-cycles, 1, -1, 0,0,0,0, 0); - return 1; - } - CLOCK_CYCLES(3); - PREFETCH_RUN(3, 1, -1, 0,0,0,0, 0); - return 0; -} + int cycles_old = cycles; + UN_USED(cycles_old); + if ((cr0 & 1) && (cpu_state.eflags & VM_FLAG) && (IOPL != 3)) { + x86gpf(NULL, 0); + return 1; + } + if (VF_SET()) { + cpu_state.oldpc = cpu_state.pc; + x86_int_sw(4); + PREFETCH_RUN(cycles_old - cycles, 1, -1, 0, 0, 0, 0, 0); + return 1; + } + CLOCK_CYCLES(3); + PREFETCH_RUN(3, 1, -1, 0, 0, 0, 0, 0); + return 0; +} diff --git a/src/cpu/x86_ops_io.h b/src/cpu/x86_ops_io.h index 9fa91a215..8a99b8668 100644 --- a/src/cpu/x86_ops_io.h +++ b/src/cpu/x86_ops_io.h @@ -1,146 +1,142 @@ -static int opIN_AL_imm(uint32_t fetchdat) -{ - uint16_t port = (uint16_t)getbytef(); - check_io_perm(port); - AL = inb(port); - CLOCK_CYCLES(12); - PREFETCH_RUN(12, 2, -1, 1,0,0,0, 0); - if (nmi && nmi_enable && nmi_mask) - return 1; - return 0; -} -static int opIN_AX_imm(uint32_t fetchdat) +static int +opIN_AL_imm(uint32_t fetchdat) { - uint16_t port = (uint16_t)getbytef(); - check_io_perm(port); - check_io_perm(port + 1); - AX = inw(port); - CLOCK_CYCLES(12); - PREFETCH_RUN(12, 2, -1, 1,0,0,0, 0); - if (nmi && nmi_enable && nmi_mask) - return 1; - return 0; + uint16_t port = (uint16_t) getbytef(); + check_io_perm(port, 1); + AL = inb(port); + CLOCK_CYCLES(12); + PREFETCH_RUN(12, 2, -1, 1, 0, 0, 0, 0); + if (nmi && nmi_enable && nmi_mask) + return 1; + return 0; } -static int opIN_EAX_imm(uint32_t fetchdat) +static int +opIN_AX_imm(uint32_t fetchdat) { - uint16_t port = (uint16_t)getbytef(); - check_io_perm(port); - check_io_perm(port + 1); - check_io_perm(port + 2); - check_io_perm(port + 3); - EAX = inl(port); - CLOCK_CYCLES(12); - PREFETCH_RUN(12, 2, -1, 0,1,0,0, 0); - if (nmi && nmi_enable && nmi_mask) - return 1; - return 0; + uint16_t port = (uint16_t) getbytef(); + check_io_perm(port, 2); + AX = inw(port); + CLOCK_CYCLES(12); + PREFETCH_RUN(12, 2, -1, 1, 0, 0, 0, 0); + if (nmi && nmi_enable && nmi_mask) + return 1; + return 0; +} +static int +opIN_EAX_imm(uint32_t fetchdat) +{ + uint16_t port = (uint16_t) getbytef(); + check_io_perm(port, 4); + EAX = inl(port); + CLOCK_CYCLES(12); + PREFETCH_RUN(12, 2, -1, 0, 1, 0, 0, 0); + if (nmi && nmi_enable && nmi_mask) + return 1; + return 0; } -static int opOUT_AL_imm(uint32_t fetchdat) +static int +opOUT_AL_imm(uint32_t fetchdat) { - uint16_t port = (uint16_t)getbytef(); - check_io_perm(port); - outb(port, AL); - CLOCK_CYCLES(10); - PREFETCH_RUN(10, 2, -1, 0,0,1,0, 0); - if (port == 0x64) - return x86_was_reset; - if (nmi && nmi_enable && nmi_mask) - return 1; - return 0; -} -static int opOUT_AX_imm(uint32_t fetchdat) -{ - uint16_t port = (uint16_t)getbytef(); - check_io_perm(port); - check_io_perm(port + 1); - outw(port, AX); - CLOCK_CYCLES(10); - PREFETCH_RUN(10, 2, -1, 0,0,1,0, 0); - if (nmi && nmi_enable && nmi_mask) - return 1; - return 0; -} -static int opOUT_EAX_imm(uint32_t fetchdat) -{ - uint16_t port = (uint16_t)getbytef(); - check_io_perm(port); - check_io_perm(port + 1); - check_io_perm(port + 2); - check_io_perm(port + 3); - outl(port, EAX); - CLOCK_CYCLES(10); - PREFETCH_RUN(10, 2, -1, 0,0,0,1, 0); - if (nmi && nmi_enable && nmi_mask) - return 1; - return 0; -} - -static int opIN_AL_DX(uint32_t fetchdat) -{ - check_io_perm(DX); - AL = inb(DX); - CLOCK_CYCLES(12); - PREFETCH_RUN(12, 1, -1, 1,0,0,0, 0); - if (nmi && nmi_enable && nmi_mask) - return 1; - return 0; -} -static int opIN_AX_DX(uint32_t fetchdat) -{ - check_io_perm(DX); - check_io_perm(DX + 1); - AX = inw(DX); - CLOCK_CYCLES(12); - PREFETCH_RUN(12, 1, -1, 1,0,0,0, 0); - if (nmi && nmi_enable && nmi_mask) - return 1; - return 0; -} -static int opIN_EAX_DX(uint32_t fetchdat) -{ - check_io_perm(DX); - check_io_perm(DX + 1); - check_io_perm(DX + 2); - check_io_perm(DX + 3); - EAX = inl(DX); - CLOCK_CYCLES(12); - PREFETCH_RUN(12, 1, -1, 0,1,0,0, 0); - if (nmi && nmi_enable && nmi_mask) - return 1; - return 0; -} - -static int opOUT_AL_DX(uint32_t fetchdat) -{ - check_io_perm(DX); - outb(DX, AL); - CLOCK_CYCLES(11); - PREFETCH_RUN(11, 1, -1, 0,0,1,0, 0); - if (nmi && nmi_enable && nmi_mask) - return 1; + uint16_t port = (uint16_t) getbytef(); + check_io_perm(port, 1); + outb(port, AL); + CLOCK_CYCLES(10); + PREFETCH_RUN(10, 2, -1, 0, 0, 1, 0, 0); + if (port == 0x64) return x86_was_reset; + if (nmi && nmi_enable && nmi_mask) + return 1; + return 0; } -static int opOUT_AX_DX(uint32_t fetchdat) +static int +opOUT_AX_imm(uint32_t fetchdat) { - check_io_perm(DX); - check_io_perm(DX + 1); - outw(DX, AX); - CLOCK_CYCLES(11); - PREFETCH_RUN(11, 1, -1, 0,0,1,0, 0); - if (nmi && nmi_enable && nmi_mask) - return 1; - return 0; + uint16_t port = (uint16_t) getbytef(); + check_io_perm(port, 2); + outw(port, AX); + CLOCK_CYCLES(10); + PREFETCH_RUN(10, 2, -1, 0, 0, 1, 0, 0); + if (nmi && nmi_enable && nmi_mask) + return 1; + return 0; } -static int opOUT_EAX_DX(uint32_t fetchdat) +static int +opOUT_EAX_imm(uint32_t fetchdat) { - check_io_perm(DX); - check_io_perm(DX + 1); - check_io_perm(DX + 2); - check_io_perm(DX + 3); - outl(DX, EAX); - PREFETCH_RUN(11, 1, -1, 0,0,0,1, 0); - if (nmi && nmi_enable && nmi_mask) - return 1; - return 0; + uint16_t port = (uint16_t) getbytef(); + check_io_perm(port, 4); + outl(port, EAX); + CLOCK_CYCLES(10); + PREFETCH_RUN(10, 2, -1, 0, 0, 0, 1, 0); + if (nmi && nmi_enable && nmi_mask) + return 1; + return 0; +} + +static int +opIN_AL_DX(uint32_t fetchdat) +{ + check_io_perm(DX, 1); + AL = inb(DX); + CLOCK_CYCLES(12); + PREFETCH_RUN(12, 1, -1, 1, 0, 0, 0, 0); + if (nmi && nmi_enable && nmi_mask) + return 1; + return 0; +} +static int +opIN_AX_DX(uint32_t fetchdat) +{ + check_io_perm(DX, 2); + AX = inw(DX); + CLOCK_CYCLES(12); + PREFETCH_RUN(12, 1, -1, 1, 0, 0, 0, 0); + if (nmi && nmi_enable && nmi_mask) + return 1; + return 0; +} +static int +opIN_EAX_DX(uint32_t fetchdat) +{ + check_io_perm(DX, 4); + EAX = inl(DX); + CLOCK_CYCLES(12); + PREFETCH_RUN(12, 1, -1, 0, 1, 0, 0, 0); + if (nmi && nmi_enable && nmi_mask) + return 1; + return 0; +} + +static int +opOUT_AL_DX(uint32_t fetchdat) +{ + check_io_perm(DX, 1); + outb(DX, AL); + CLOCK_CYCLES(11); + PREFETCH_RUN(11, 1, -1, 0, 0, 1, 0, 0); + if (nmi && nmi_enable && nmi_mask) + return 1; + return x86_was_reset; +} +static int +opOUT_AX_DX(uint32_t fetchdat) +{ + check_io_perm(DX, 2); + outw(DX, AX); + CLOCK_CYCLES(11); + PREFETCH_RUN(11, 1, -1, 0, 0, 1, 0, 0); + if (nmi && nmi_enable && nmi_mask) + return 1; + return 0; +} +static int +opOUT_EAX_DX(uint32_t fetchdat) +{ + check_io_perm(DX, 4); + outl(DX, EAX); + PREFETCH_RUN(11, 1, -1, 0, 0, 0, 1, 0); + if (nmi && nmi_enable && nmi_mask) + return 1; + return 0; } diff --git a/src/cpu/x86_ops_jump.h b/src/cpu/x86_ops_jump.h index c227939a3..97ca673d7 100644 --- a/src/cpu/x86_ops_jump.h +++ b/src/cpu/x86_ops_jump.h @@ -1,75 +1,75 @@ -#define cond_O ( VF_SET()) +#define cond_O (VF_SET()) #define cond_NO (!VF_SET()) -#define cond_B ( CF_SET()) +#define cond_B (CF_SET()) #define cond_NB (!CF_SET()) -#define cond_E ( ZF_SET()) +#define cond_E (ZF_SET()) #define cond_NE (!ZF_SET()) -#define cond_BE ( CF_SET() || ZF_SET()) +#define cond_BE (CF_SET() || ZF_SET()) #define cond_NBE (!CF_SET() && !ZF_SET()) -#define cond_S ( NF_SET()) +#define cond_S (NF_SET()) #define cond_NS (!NF_SET()) -#define cond_P ( PF_SET()) +#define cond_P (PF_SET()) #define cond_NP (!PF_SET()) #define cond_L (((NF_SET()) ? 1 : 0) != ((VF_SET()) ? 1 : 0)) #define cond_NL (((NF_SET()) ? 1 : 0) == ((VF_SET()) ? 1 : 0)) -#define cond_LE (((NF_SET()) ? 1 : 0) != ((VF_SET()) ? 1 : 0) || (ZF_SET())) +#define cond_LE (((NF_SET()) ? 1 : 0) != ((VF_SET()) ? 1 : 0) || (ZF_SET())) #define cond_NLE (((NF_SET()) ? 1 : 0) == ((VF_SET()) ? 1 : 0) && (!ZF_SET())) -#define opJ(condition) \ - static int opJ ## condition(uint32_t fetchdat) \ - { \ - int8_t offset = (int8_t)getbytef(); \ - CLOCK_CYCLES(timing_bnt); \ - if (cond_ ## condition) \ - { \ - cpu_state.pc += offset; \ - if (!(cpu_state.op32 & 0x100)) \ - cpu_state.pc &= 0xffff; \ - CLOCK_CYCLES_ALWAYS(timing_bt); \ - CPU_BLOCK_END(); \ - PREFETCH_RUN(timing_bt+timing_bnt, 2, -1, 0,0,0,0, 0); \ - PREFETCH_FLUSH(); \ - return 1; \ - } \ - PREFETCH_RUN(timing_bnt, 2, -1, 0,0,0,0, 0); \ - return 0; \ - } \ - \ - static int opJ ## condition ## _w(uint32_t fetchdat) \ - { \ - int16_t offset = (int16_t)getwordf(); \ - CLOCK_CYCLES(timing_bnt); \ - if (cond_ ## condition) \ - { \ - cpu_state.pc += offset; \ - cpu_state.pc &= 0xffff; \ - CLOCK_CYCLES_ALWAYS(timing_bt); \ - CPU_BLOCK_END(); \ - PREFETCH_RUN(timing_bt+timing_bnt, 3, -1, 0,0,0,0, 0); \ - PREFETCH_FLUSH(); \ - return 1; \ - } \ - PREFETCH_RUN(timing_bnt, 3, -1, 0,0,0,0, 0); \ - return 0; \ - } \ - \ - static int opJ ## condition ## _l(uint32_t fetchdat) \ - { \ - uint32_t offset = getlong(); if (cpu_state.abrt) return 1; \ - CLOCK_CYCLES(timing_bnt); \ - if (cond_ ## condition) \ - { \ - cpu_state.pc += offset; \ - CLOCK_CYCLES_ALWAYS(timing_bt); \ - CPU_BLOCK_END(); \ - PREFETCH_RUN(timing_bt+timing_bnt, 5, -1, 0,0,0,0, 0); \ - PREFETCH_FLUSH(); \ - return 1; \ - } \ - PREFETCH_RUN(timing_bnt, 5, -1, 0,0,0,0, 0); \ - return 0; \ - } \ - +#define opJ(condition) \ + static int opJ##condition(uint32_t fetchdat) \ + { \ + int8_t offset = (int8_t) getbytef(); \ + CLOCK_CYCLES(timing_bnt); \ + if (cond_##condition) { \ + cpu_state.pc += offset; \ + if (!(cpu_state.op32 & 0x100)) \ + cpu_state.pc &= 0xffff; \ + CLOCK_CYCLES_ALWAYS(timing_bt); \ + CPU_BLOCK_END(); \ + PREFETCH_RUN(timing_bt + timing_bnt, 2, -1, 0, 0, 0, 0, 0); \ + PREFETCH_FLUSH(); \ + return 1; \ + } \ + PREFETCH_RUN(timing_bnt, 2, -1, 0, 0, 0, 0, 0); \ + return 0; \ + } \ + \ + static int opJ##condition##_w(uint32_t fetchdat) \ + { \ + int16_t offset = (int16_t) getwordf(); \ + CLOCK_CYCLES(timing_bnt); \ + if (cond_##condition) { \ + cpu_state.pc += offset; \ + cpu_state.pc &= 0xffff; \ + CLOCK_CYCLES_ALWAYS(timing_bt); \ + CPU_BLOCK_END(); \ + PREFETCH_RUN(timing_bt + timing_bnt, 3, -1, 0, 0, 0, 0, 0); \ + PREFETCH_FLUSH(); \ + return 1; \ + } \ + PREFETCH_RUN(timing_bnt, 3, -1, 0, 0, 0, 0, 0); \ + return 0; \ + } \ + \ + static int opJ##condition##_l(uint32_t fetchdat) \ + { \ + uint32_t offset = getlong(); \ + if (cpu_state.abrt) \ + return 1; \ + CLOCK_CYCLES(timing_bnt); \ + if (cond_##condition) { \ + cpu_state.pc += offset; \ + CLOCK_CYCLES_ALWAYS(timing_bt); \ + CPU_BLOCK_END(); \ + PREFETCH_RUN(timing_bt + timing_bnt, 5, -1, 0, 0, 0, 0, 0); \ + PREFETCH_FLUSH(); \ + return 1; \ + } \ + PREFETCH_RUN(timing_bnt, 5, -1, 0, 0, 0, 0, 0); \ + return 0; \ + } + +// clang-format off opJ(O) opJ(NO) opJ(B) @@ -86,296 +86,330 @@ opJ(L) opJ(NL) opJ(LE) opJ(NLE) + // clang-format on - - -static int opLOOPNE_w(uint32_t fetchdat) +static int +opLOOPNE_w(uint32_t fetchdat) { - int8_t offset = (int8_t)getbytef(); - CX--; - CLOCK_CYCLES((is486) ? 7 : 11); - PREFETCH_RUN(11, 2, -1, 0,0,0,0, 0); - if (CX && !ZF_SET()) - { - cpu_state.pc += offset; - if (!(cpu_state.op32 & 0x100)) - cpu_state.pc &= 0xffff; - CPU_BLOCK_END(); - PREFETCH_FLUSH(); - return 1; - } - return 0; -} -static int opLOOPNE_l(uint32_t fetchdat) -{ - int8_t offset = (int8_t)getbytef(); - ECX--; - CLOCK_CYCLES((is486) ? 7 : 11); - PREFETCH_RUN(11, 2, -1, 0,0,0,0, 0); - if (ECX && !ZF_SET()) - { - cpu_state.pc += offset; - if (!(cpu_state.op32 & 0x100)) - cpu_state.pc &= 0xffff; - CPU_BLOCK_END(); - PREFETCH_FLUSH(); - return 1; - } - return 0; -} - -static int opLOOPE_w(uint32_t fetchdat) -{ - int8_t offset = (int8_t)getbytef(); - CX--; - CLOCK_CYCLES((is486) ? 7 : 11); - PREFETCH_RUN(11, 2, -1, 0,0,0,0, 0); - if (CX && ZF_SET()) - { - cpu_state.pc += offset; - if (!(cpu_state.op32 & 0x100)) - cpu_state.pc &= 0xffff; - CPU_BLOCK_END(); - PREFETCH_FLUSH(); - return 1; - } - return 0; -} -static int opLOOPE_l(uint32_t fetchdat) -{ - int8_t offset = (int8_t)getbytef(); - ECX--; - CLOCK_CYCLES((is486) ? 7 : 11); - PREFETCH_RUN(11, 2, -1, 0,0,0,0, 0); - if (ECX && ZF_SET()) - { - cpu_state.pc += offset; - if (!(cpu_state.op32 & 0x100)) - cpu_state.pc &= 0xffff; - CPU_BLOCK_END(); - PREFETCH_FLUSH(); - return 1; - } - return 0; -} - -static int opLOOP_w(uint32_t fetchdat) -{ - int8_t offset = (int8_t)getbytef(); - CX--; - CLOCK_CYCLES((is486) ? 7 : 11); - PREFETCH_RUN(11, 2, -1, 0,0,0,0, 0); - if (CX) - { - cpu_state.pc += offset; - if (!(cpu_state.op32 & 0x100)) - cpu_state.pc &= 0xffff; - CPU_BLOCK_END(); - PREFETCH_FLUSH(); - return 1; - } - return 0; -} -static int opLOOP_l(uint32_t fetchdat) -{ - int8_t offset = (int8_t)getbytef(); - ECX--; - CLOCK_CYCLES((is486) ? 7 : 11); - PREFETCH_RUN(11, 2, -1, 0,0,0,0, 0); - if (ECX) - { - cpu_state.pc += offset; - if (!(cpu_state.op32 & 0x100)) - cpu_state.pc &= 0xffff; - CPU_BLOCK_END(); - PREFETCH_FLUSH(); - return 1; - } - return 0; -} - -static int opJCXZ(uint32_t fetchdat) -{ - int8_t offset = (int8_t)getbytef(); - CLOCK_CYCLES(5); - if (!CX) - { - cpu_state.pc += offset; - if (!(cpu_state.op32 & 0x100)) - cpu_state.pc &= 0xffff; - CLOCK_CYCLES(4); - CPU_BLOCK_END(); - PREFETCH_RUN(9, 2, -1, 0,0,0,0, 0); - PREFETCH_FLUSH(); - return 1; - } - PREFETCH_RUN(5, 2, -1, 0,0,0,0, 0); - return 0; -} -static int opJECXZ(uint32_t fetchdat) -{ - int8_t offset = (int8_t)getbytef(); - CLOCK_CYCLES(5); - if (!ECX) - { - cpu_state.pc += offset; - if (!(cpu_state.op32 & 0x100)) - cpu_state.pc &= 0xffff; - CLOCK_CYCLES(4); - CPU_BLOCK_END(); - PREFETCH_RUN(9, 2, -1, 0,0,0,0, 0); - PREFETCH_FLUSH(); - return 1; - } - PREFETCH_RUN(5, 2, -1, 0,0,0,0, 0); - return 0; -} - - -static int opJMP_r8(uint32_t fetchdat) -{ - int8_t offset = (int8_t)getbytef(); + int8_t offset = (int8_t) getbytef(); + CX--; + CLOCK_CYCLES((is486) ? 7 : 11); + PREFETCH_RUN(11, 2, -1, 0, 0, 0, 0, 0); + if (CX && !ZF_SET()) { cpu_state.pc += offset; if (!(cpu_state.op32 & 0x100)) - cpu_state.pc &= 0xffff; + cpu_state.pc &= 0xffff; CPU_BLOCK_END(); - CLOCK_CYCLES((is486) ? 3 : 7); - PREFETCH_RUN(7, 2, -1, 0,0,0,0, 0); PREFETCH_FLUSH(); - return 0; + return 1; + } + return 0; } -static int opJMP_r16(uint32_t fetchdat) +static int +opLOOPNE_l(uint32_t fetchdat) { - int16_t offset = (int16_t)getwordf(); + int8_t offset = (int8_t) getbytef(); + ECX--; + CLOCK_CYCLES((is486) ? 7 : 11); + PREFETCH_RUN(11, 2, -1, 0, 0, 0, 0, 0); + if (ECX && !ZF_SET()) { cpu_state.pc += offset; - cpu_state.pc &= 0xffff; + if (!(cpu_state.op32 & 0x100)) + cpu_state.pc &= 0xffff; CPU_BLOCK_END(); - CLOCK_CYCLES((is486) ? 3 : 7); - PREFETCH_RUN(7, 3, -1, 0,0,0,0, 0); PREFETCH_FLUSH(); - return 0; + return 1; + } + return 0; } -static int opJMP_r32(uint32_t fetchdat) + +static int +opLOOPE_w(uint32_t fetchdat) { - int32_t offset = (int32_t)getlong(); if (cpu_state.abrt) return 1; + int8_t offset = (int8_t) getbytef(); + CX--; + CLOCK_CYCLES((is486) ? 7 : 11); + PREFETCH_RUN(11, 2, -1, 0, 0, 0, 0, 0); + if (CX && ZF_SET()) { cpu_state.pc += offset; + if (!(cpu_state.op32 & 0x100)) + cpu_state.pc &= 0xffff; CPU_BLOCK_END(); - CLOCK_CYCLES((is486) ? 3 : 7); - PREFETCH_RUN(7, 5, -1, 0,0,0,0, 0); PREFETCH_FLUSH(); - return 0; + return 1; + } + return 0; +} +static int +opLOOPE_l(uint32_t fetchdat) +{ + int8_t offset = (int8_t) getbytef(); + ECX--; + CLOCK_CYCLES((is486) ? 7 : 11); + PREFETCH_RUN(11, 2, -1, 0, 0, 0, 0, 0); + if (ECX && ZF_SET()) { + cpu_state.pc += offset; + if (!(cpu_state.op32 & 0x100)) + cpu_state.pc &= 0xffff; + CPU_BLOCK_END(); + PREFETCH_FLUSH(); + return 1; + } + return 0; } -static int opJMP_far_a16(uint32_t fetchdat) +static int +opLOOP_w(uint32_t fetchdat) { - uint16_t addr, seg; - uint32_t old_pc; - addr = getwordf(); - seg = getword(); if (cpu_state.abrt) return 1; - old_pc = cpu_state.pc; - cpu_state.pc = addr; - loadcsjmp(seg, old_pc); + int8_t offset = (int8_t) getbytef(); + CX--; + CLOCK_CYCLES((is486) ? 7 : 11); + PREFETCH_RUN(11, 2, -1, 0, 0, 0, 0, 0); + if (CX) { + cpu_state.pc += offset; + if (!(cpu_state.op32 & 0x100)) + cpu_state.pc &= 0xffff; CPU_BLOCK_END(); - PREFETCH_RUN(11, 5, -1, 0,0,0,0, 0); PREFETCH_FLUSH(); - return 0; + return 1; + } + return 0; } -static int opJMP_far_a32(uint32_t fetchdat) +static int +opLOOP_l(uint32_t fetchdat) { - uint16_t seg; - uint32_t addr, old_pc; - addr = getlong(); - seg = getword(); if (cpu_state.abrt) return 1; - old_pc = cpu_state.pc; - cpu_state.pc = addr; - loadcsjmp(seg, old_pc); + int8_t offset = (int8_t) getbytef(); + ECX--; + CLOCK_CYCLES((is486) ? 7 : 11); + PREFETCH_RUN(11, 2, -1, 0, 0, 0, 0, 0); + if (ECX) { + cpu_state.pc += offset; + if (!(cpu_state.op32 & 0x100)) + cpu_state.pc &= 0xffff; CPU_BLOCK_END(); - PREFETCH_RUN(11, 7, -1, 0,0,0,0, 0); PREFETCH_FLUSH(); - return 0; + return 1; + } + return 0; } -static int opCALL_r16(uint32_t fetchdat) +static int +opJCXZ(uint32_t fetchdat) { - int16_t addr = (int16_t)getwordf(); - PUSH_W(cpu_state.pc); - cpu_state.pc += addr; + int8_t offset = (int8_t) getbytef(); + CLOCK_CYCLES(5); + if (!CX) { + cpu_state.pc += offset; + if (!(cpu_state.op32 & 0x100)) + cpu_state.pc &= 0xffff; + CLOCK_CYCLES(4); + CPU_BLOCK_END(); + PREFETCH_RUN(9, 2, -1, 0, 0, 0, 0, 0); + PREFETCH_FLUSH(); + return 1; + } + PREFETCH_RUN(5, 2, -1, 0, 0, 0, 0, 0); + return 0; +} +static int +opJECXZ(uint32_t fetchdat) +{ + int8_t offset = (int8_t) getbytef(); + CLOCK_CYCLES(5); + if (!ECX) { + cpu_state.pc += offset; + if (!(cpu_state.op32 & 0x100)) + cpu_state.pc &= 0xffff; + CLOCK_CYCLES(4); + CPU_BLOCK_END(); + PREFETCH_RUN(9, 2, -1, 0, 0, 0, 0, 0); + PREFETCH_FLUSH(); + return 1; + } + PREFETCH_RUN(5, 2, -1, 0, 0, 0, 0, 0); + return 0; +} + +static int +opJMP_r8(uint32_t fetchdat) +{ + int8_t offset = (int8_t) getbytef(); + cpu_state.pc += offset; + if (!(cpu_state.op32 & 0x100)) cpu_state.pc &= 0xffff; - CPU_BLOCK_END(); - CLOCK_CYCLES((is486) ? 3 : 7); - PREFETCH_RUN(7, 3, -1, 0,0,1,0, 0); - PREFETCH_FLUSH(); - return 0; + CPU_BLOCK_END(); + CLOCK_CYCLES((is486) ? 3 : 7); + PREFETCH_RUN(7, 2, -1, 0, 0, 0, 0, 0); + PREFETCH_FLUSH(); + return 0; } -static int opCALL_r32(uint32_t fetchdat) +static int +opJMP_r16(uint32_t fetchdat) { - int32_t addr = getlong(); if (cpu_state.abrt) return 1; - PUSH_L(cpu_state.pc); - cpu_state.pc += addr; - CPU_BLOCK_END(); - CLOCK_CYCLES((is486) ? 3 : 7); - PREFETCH_RUN(7, 5, -1, 0,0,0,1, 0); - PREFETCH_FLUSH(); - return 0; + int16_t offset = (int16_t) getwordf(); + cpu_state.pc += offset; + cpu_state.pc &= 0xffff; + CPU_BLOCK_END(); + CLOCK_CYCLES((is486) ? 3 : 7); + PREFETCH_RUN(7, 3, -1, 0, 0, 0, 0, 0); + PREFETCH_FLUSH(); + return 0; } - -static int opRET_w(uint32_t fetchdat) +static int +opJMP_r32(uint32_t fetchdat) { - uint16_t ret; - - ret = POP_W(); if (cpu_state.abrt) return 1; - cpu_state.pc = ret; - CPU_BLOCK_END(); - - CLOCK_CYCLES((is486) ? 5 : 10); - PREFETCH_RUN(10, 1, -1, 1,0,0,0, 0); - PREFETCH_FLUSH(); - return 0; + int32_t offset = (int32_t) getlong(); + if (cpu_state.abrt) + return 1; + cpu_state.pc += offset; + CPU_BLOCK_END(); + CLOCK_CYCLES((is486) ? 3 : 7); + PREFETCH_RUN(7, 5, -1, 0, 0, 0, 0, 0); + PREFETCH_FLUSH(); + return 0; } -static int opRET_l(uint32_t fetchdat) + +static int +opJMP_far_a16(uint32_t fetchdat) { - uint32_t ret; + uint16_t addr; + uint16_t seg; + uint32_t old_pc; - ret = POP_L(); if (cpu_state.abrt) return 1; - cpu_state.pc = ret; - CPU_BLOCK_END(); - - CLOCK_CYCLES((is486) ? 5 : 10); - PREFETCH_RUN(10, 1, -1, 0,1,0,0, 0); - PREFETCH_FLUSH(); - return 0; + addr = getwordf(); + seg = getword(); + if (cpu_state.abrt) + return 1; + old_pc = cpu_state.pc; + cpu_state.pc = addr; + op_loadcsjmp(seg, old_pc); + CPU_BLOCK_END(); + PREFETCH_RUN(11, 5, -1, 0, 0, 0, 0, 0); + PREFETCH_FLUSH(); + return 0; } - -static int opRET_w_imm(uint32_t fetchdat) +static int +opJMP_far_a32(uint32_t fetchdat) { - uint16_t ret; - uint16_t offset = getwordf(); + uint16_t seg; + uint32_t addr; + uint32_t old_pc; - ret = POP_W(); if (cpu_state.abrt) return 1; - if (stack32) ESP += offset; - else SP += offset; - cpu_state.pc = ret; - CPU_BLOCK_END(); - - CLOCK_CYCLES((is486) ? 5 : 10); - PREFETCH_RUN(10, 5, -1, 1,0,0,0, 0); - PREFETCH_FLUSH(); - return 0; + addr = getlong(); + seg = getword(); + if (cpu_state.abrt) + return 1; + old_pc = cpu_state.pc; + cpu_state.pc = addr; + op_loadcsjmp(seg, old_pc); + CPU_BLOCK_END(); + PREFETCH_RUN(11, 7, -1, 0, 0, 0, 0, 0); + PREFETCH_FLUSH(); + return 0; } -static int opRET_l_imm(uint32_t fetchdat) + +static int +opCALL_r16(uint32_t fetchdat) { - uint32_t ret; - uint16_t offset = getwordf(); + int16_t addr = (int16_t) getwordf(); - ret = POP_L(); if (cpu_state.abrt) return 1; - if (stack32) ESP += offset; - else SP += offset; - cpu_state.pc = ret; - CPU_BLOCK_END(); - - CLOCK_CYCLES((is486) ? 5 : 10); - PREFETCH_RUN(10, 5, -1, 0,1,0,0, 0); - PREFETCH_FLUSH(); - return 0; + PUSH_W(cpu_state.pc); + cpu_state.pc += addr; + cpu_state.pc &= 0xffff; + CPU_BLOCK_END(); + CLOCK_CYCLES((is486) ? 3 : 7); + PREFETCH_RUN(7, 3, -1, 0, 0, 1, 0, 0); + PREFETCH_FLUSH(); + return 0; +} +static int +opCALL_r32(uint32_t fetchdat) +{ + int32_t addr = getlong(); + + if (cpu_state.abrt) + return 1; + PUSH_L(cpu_state.pc); + cpu_state.pc += addr; + CPU_BLOCK_END(); + CLOCK_CYCLES((is486) ? 3 : 7); + PREFETCH_RUN(7, 5, -1, 0, 0, 0, 1, 0); + PREFETCH_FLUSH(); + return 0; } +static int +opRET_w(uint32_t fetchdat) +{ + uint16_t ret; + + ret = POP_W(); + if (cpu_state.abrt) + return 1; + cpu_state.pc = ret; + CPU_BLOCK_END(); + + CLOCK_CYCLES((is486) ? 5 : 10); + PREFETCH_RUN(10, 1, -1, 1, 0, 0, 0, 0); + PREFETCH_FLUSH(); + return 0; +} +static int +opRET_l(uint32_t fetchdat) +{ + uint32_t ret; + + ret = POP_L(); + if (cpu_state.abrt) + return 1; + cpu_state.pc = ret; + CPU_BLOCK_END(); + + CLOCK_CYCLES((is486) ? 5 : 10); + PREFETCH_RUN(10, 1, -1, 0, 1, 0, 0, 0); + PREFETCH_FLUSH(); + return 0; +} + +static int +opRET_w_imm(uint32_t fetchdat) +{ + uint16_t ret; + uint16_t offset = getwordf(); + + ret = POP_W(); + if (cpu_state.abrt) + return 1; + if (stack32) + ESP += offset; + else + SP += offset; + cpu_state.pc = ret; + CPU_BLOCK_END(); + + CLOCK_CYCLES((is486) ? 5 : 10); + PREFETCH_RUN(10, 5, -1, 1, 0, 0, 0, 0); + PREFETCH_FLUSH(); + return 0; +} +static int +opRET_l_imm(uint32_t fetchdat) +{ + uint32_t ret; + uint16_t offset = getwordf(); + + ret = POP_L(); + if (cpu_state.abrt) + return 1; + if (stack32) + ESP += offset; + else + SP += offset; + cpu_state.pc = ret; + CPU_BLOCK_END(); + + CLOCK_CYCLES((is486) ? 5 : 10); + PREFETCH_RUN(10, 5, -1, 0, 1, 0, 0, 0); + PREFETCH_FLUSH(); + return 0; +} diff --git a/src/cpu/x86_ops_misc.h b/src/cpu/x86_ops_misc.h index a6e7e9193..e36fa4800 100644 --- a/src/cpu/x86_ops_misc.h +++ b/src/cpu/x86_ops_misc.h @@ -1,971 +1,1076 @@ -static int opCBW(uint32_t fetchdat) +static int +opCBW(uint32_t fetchdat) { - AH = (AL & 0x80) ? 0xff : 0; - CLOCK_CYCLES(3); - PREFETCH_RUN(3, 1, -1, 0,0,0,0, 0); - return 0; + AH = (AL & 0x80) ? 0xff : 0; + CLOCK_CYCLES(3); + PREFETCH_RUN(3, 1, -1, 0, 0, 0, 0, 0); + return 0; } -static int opCWDE(uint32_t fetchdat) +static int +opCWDE(uint32_t fetchdat) { - EAX = (AX & 0x8000) ? (0xffff0000 | AX) : AX; - CLOCK_CYCLES(3); - PREFETCH_RUN(3, 1, -1, 0,0,0,0, 0); - return 0; + EAX = (AX & 0x8000) ? (0xffff0000 | AX) : AX; + CLOCK_CYCLES(3); + PREFETCH_RUN(3, 1, -1, 0, 0, 0, 0, 0); + return 0; } -static int opCWD(uint32_t fetchdat) +static int +opCWD(uint32_t fetchdat) { - DX = (AX & 0x8000) ? 0xFFFF : 0; - CLOCK_CYCLES(2); - PREFETCH_RUN(2, 1, -1, 0,0,0,0, 0); - return 0; + DX = (AX & 0x8000) ? 0xFFFF : 0; + CLOCK_CYCLES(2); + PREFETCH_RUN(2, 1, -1, 0, 0, 0, 0, 0); + return 0; } -static int opCDQ(uint32_t fetchdat) +static int +opCDQ(uint32_t fetchdat) { - EDX = (EAX & 0x80000000) ? 0xffffffff : 0; - CLOCK_CYCLES(2); - PREFETCH_RUN(2, 1, -1, 0,0,0,0, 0); - return 0; + EDX = (EAX & 0x80000000) ? 0xffffffff : 0; + CLOCK_CYCLES(2); + PREFETCH_RUN(2, 1, -1, 0, 0, 0, 0, 0); + return 0; } -static int opNOP(uint32_t fetchdat) +static int +opNOP(uint32_t fetchdat) { - CLOCK_CYCLES((is486) ? 1 : 3); - PREFETCH_RUN(3, 1, -1, 0,0,0,0, 0); - return 0; + CLOCK_CYCLES((is486) ? 1 : 3); + PREFETCH_RUN(3, 1, -1, 0, 0, 0, 0, 0); + return 0; } -static int opSETALC(uint32_t fetchdat) +static int +opSETALC(uint32_t fetchdat) { - AL = (CF_SET()) ? 0xff : 0; - CLOCK_CYCLES(timing_rr); - PREFETCH_RUN(timing_rr, 1, -1, 0,0,0,0, 0); - return 0; + AL = (CF_SET()) ? 0xff : 0; + CLOCK_CYCLES(timing_rr); + PREFETCH_RUN(timing_rr, 1, -1, 0, 0, 0, 0, 0); + return 0; } - - -static int opF6_a16(uint32_t fetchdat) +static int +opF6_a16(uint32_t fetchdat) { - int tempws, tempws2 = 0; - uint16_t tempw, src16; - uint8_t src, dst; - int8_t temps; - - fetch_ea_16(fetchdat); - if (cpu_mod != 3) { - SEG_CHECK_READ(cpu_state.ea_seg); - CHECK_READ(cpu_state.ea_seg, cpu_state.eaaddr, cpu_state.eaaddr); - } - dst = geteab(); if (cpu_state.abrt) return 1; - switch (rmdat & 0x38) - { - case 0x00: /*TEST b,#8*/ - case 0x08: - src = readmemb(cs, cpu_state.pc); cpu_state.pc++; if (cpu_state.abrt) return 1; - setznp8(src & dst); - if (is486) { CLOCK_CYCLES((cpu_mod == 3) ? 1 : 2); } - else { CLOCK_CYCLES((cpu_mod == 3) ? 2 : 5); } - PREFETCH_RUN((cpu_mod == 3) ? 2 : 5, 3, rmdat, (cpu_mod == 3) ? 0:1,0,0,0, 0); - break; - case 0x10: /*NOT b*/ - if (cpu_mod != 3) - SEG_CHECK_WRITE(cpu_state.ea_seg); - seteab(~dst); if (cpu_state.abrt) return 1; - CLOCK_CYCLES((cpu_mod == 3) ? timing_rr : timing_mm); - PREFETCH_RUN((cpu_mod == 3) ? timing_rr : timing_mm, 2, rmdat, (cpu_mod == 3) ? 0:1,0,(cpu_mod == 3) ? 0:1,0, 0); - break; - case 0x18: /*NEG b*/ - if (cpu_mod != 3) - SEG_CHECK_WRITE(cpu_state.ea_seg); - seteab(0 - dst); if (cpu_state.abrt) return 1; - setsub8(0, dst); - CLOCK_CYCLES((cpu_mod == 3) ? timing_rr : timing_mm); - PREFETCH_RUN((cpu_mod == 3) ? timing_rr : timing_mm, 2, rmdat, (cpu_mod == 3) ? 0:1,0,(cpu_mod == 3) ? 0:1,0, 0); - break; - case 0x20: /*MUL AL,b*/ - AX = AL * dst; - flags_rebuild(); - if (AH) cpu_state.flags |= (C_FLAG | V_FLAG); - else cpu_state.flags &= ~(C_FLAG | V_FLAG); - CLOCK_CYCLES(13); - PREFETCH_RUN(13, 2, rmdat, (cpu_mod == 3) ? 0:1,0,0,0, 0); - break; - case 0x28: /*IMUL AL,b*/ - tempws = (int)((int8_t)AL) * (int)((int8_t)dst); - AX = tempws & 0xffff; - flags_rebuild(); - if (((int16_t)AX >> 7) != 0 && ((int16_t)AX >> 7) != -1) cpu_state.flags |= (C_FLAG | V_FLAG); - else cpu_state.flags &= ~(C_FLAG | V_FLAG); - CLOCK_CYCLES(14); - PREFETCH_RUN(14, 2, rmdat, (cpu_mod == 3) ? 0:1,0,0,0, 0); - break; - case 0x30: /*DIV AL,b*/ - src16 = AX; - if (dst) tempw = src16 / dst; - if (dst && !(tempw & 0xff00)) - { - AH = src16 % dst; - AL = (src16 / dst) &0xff; - if (!cpu_iscyrix) - { - flags_rebuild(); - cpu_state.flags |= 0x8D5; /*Not a Cyrix*/ - cpu_state.flags &= ~1; - } - } - else - { - x86_int(0); - return 1; - } - CLOCK_CYCLES((is486 && !cpu_iscyrix) ? 16 : 14); - PREFETCH_RUN((is486 && !cpu_iscyrix) ? 16 : 14, 2, rmdat, (cpu_mod == 3) ? 0:1,0,0,0, 0); - break; - case 0x38: /*IDIV AL,b*/ - tempws = (int)(int16_t)AX; - if (dst != 0) tempws2 = tempws / (int)((int8_t)dst); - temps = tempws2 & 0xff; - if (dst && ((int)temps == tempws2)) - { - AH = (tempws % (int)((int8_t)dst)) & 0xff; - AL = tempws2 & 0xff; - if (!cpu_iscyrix) - { - flags_rebuild(); - cpu_state.flags|=0x8D5; /*Not a Cyrix*/ - cpu_state.flags &= ~1; - } - } - else - { - x86_int(0); - return 1; - } - CLOCK_CYCLES(19); - PREFETCH_RUN(19, 2, rmdat, (cpu_mod == 3) ? 0:1,0,0,0, 0); - break; + int tempws = 0; + int tempws2 = 0; + uint16_t tempw = 0; + uint16_t src16; + uint8_t src; + uint8_t dst; + int8_t temps; - default: - x86illegal(); - } - return 0; -} -static int opF6_a32(uint32_t fetchdat) -{ - int tempws, tempws2 = 0; - uint16_t tempw, src16; - uint8_t src, dst; - int8_t temps; - - fetch_ea_32(fetchdat); - if (cpu_mod != 3) - SEG_CHECK_READ(cpu_state.ea_seg); - dst = geteab(); if (cpu_state.abrt) return 1; - switch (rmdat & 0x38) - { - case 0x00: /*TEST b,#8*/ - case 0x08: - src = readmemb(cs, cpu_state.pc); cpu_state.pc++; if (cpu_state.abrt) return 1; - setznp8(src & dst); - if (is486) { CLOCK_CYCLES((cpu_mod == 3) ? 1 : 2); } - else { CLOCK_CYCLES((cpu_mod == 3) ? 2 : 5); } - PREFETCH_RUN((cpu_mod == 3) ? 2 : 5, 3, rmdat, (cpu_mod == 3) ? 0:1,0,0,0, 1); - break; - case 0x10: /*NOT b*/ - if (cpu_mod != 3) - SEG_CHECK_WRITE(cpu_state.ea_seg); - seteab(~dst); if (cpu_state.abrt) return 1; - CLOCK_CYCLES((cpu_mod == 3) ? timing_rr : timing_mm); - PREFETCH_RUN((cpu_mod == 3) ? timing_rr : timing_mm, 2, rmdat, (cpu_mod == 3) ? 0:1,0,(cpu_mod == 3) ? 0:1,0, 1); - break; - case 0x18: /*NEG b*/ - if (cpu_mod != 3) - SEG_CHECK_WRITE(cpu_state.ea_seg); - seteab(0 - dst); if (cpu_state.abrt) return 1; - setsub8(0, dst); - CLOCK_CYCLES((cpu_mod == 3) ? timing_rr : timing_mm); - PREFETCH_RUN((cpu_mod == 3) ? timing_rr : timing_mm, 2, rmdat, (cpu_mod == 3) ? 0:1,0,(cpu_mod == 3) ? 0:1,0, 1); - break; - case 0x20: /*MUL AL,b*/ - AX = AL * dst; - flags_rebuild(); - if (AH) cpu_state.flags |= (C_FLAG | V_FLAG); - else cpu_state.flags &= ~(C_FLAG | V_FLAG); - CLOCK_CYCLES(13); - PREFETCH_RUN(13, 2, rmdat, (cpu_mod == 3) ? 0:1,0,0,0, 1); - break; - case 0x28: /*IMUL AL,b*/ - tempws = (int)((int8_t)AL) * (int)((int8_t)dst); - AX = tempws & 0xffff; - flags_rebuild(); - if (((int16_t)AX >> 7) != 0 && ((int16_t)AX >> 7) != -1) cpu_state.flags |= (C_FLAG | V_FLAG); - else cpu_state.flags &= ~(C_FLAG | V_FLAG); - CLOCK_CYCLES(14); - PREFETCH_RUN(14, 2, rmdat, (cpu_mod == 3) ? 0:1,0,0,0, 1); - break; - case 0x30: /*DIV AL,b*/ - src16 = AX; - if (dst) tempw = src16 / dst; - if (dst && !(tempw & 0xff00)) - { - AH = src16 % dst; - AL = (src16 / dst) &0xff; - if (!cpu_iscyrix) - { - flags_rebuild(); - cpu_state.flags |= 0x8D5; /*Not a Cyrix*/ - cpu_state.flags &= ~1; - } - } - else - { - x86_int(0); - return 1; - } - CLOCK_CYCLES((is486 && !cpu_iscyrix) ? 16 : 14); - PREFETCH_RUN((is486 && !cpu_iscyrix) ? 16 : 14, 2, rmdat, (cpu_mod == 3) ? 0:1,0,0,0, 1); - break; - case 0x38: /*IDIV AL,b*/ - tempws = (int)(int16_t)AX; - if (dst != 0) tempws2 = tempws / (int)((int8_t)dst); - temps = tempws2 & 0xff; - if (dst && ((int)temps == tempws2)) - { - AH = (tempws % (int)((int8_t)dst)) & 0xff; - AL = tempws2 & 0xff; - if (!cpu_iscyrix) - { - flags_rebuild(); - cpu_state.flags |= 0x8D5; /*Not a Cyrix*/ - cpu_state.flags &= ~1; - } - } - else - { - x86_int(0); - return 1; - } - CLOCK_CYCLES(19); - PREFETCH_RUN(19, 2, rmdat, (cpu_mod == 3) ? 0:1,0,0,0, 1); - break; - - default: - x86illegal(); - } - return 0; -} - - - -static int opF7_w_a16(uint32_t fetchdat) -{ - uint32_t templ, templ2; - int tempws, tempws2 = 0; - int16_t temps16; - uint16_t src, dst; - - fetch_ea_16(fetchdat); - if (cpu_mod != 3) - SEG_CHECK_READ(cpu_state.ea_seg); - dst = geteaw(); if (cpu_state.abrt) return 1; - switch (rmdat & 0x38) - { - case 0x00: /*TEST w*/ - case 0x08: - src = getword(); if (cpu_state.abrt) return 1; - setznp16(src & dst); - if (is486) { CLOCK_CYCLES((cpu_mod == 3) ? 1 : 2); } - else { CLOCK_CYCLES((cpu_mod == 3) ? 2 : 5); } - PREFETCH_RUN((cpu_mod == 3) ? 2 : 5, 4, rmdat, (cpu_mod == 3) ? 0:1,0,0,0, 0); - break; - case 0x10: /*NOT w*/ - if (cpu_mod != 3) - SEG_CHECK_WRITE(cpu_state.ea_seg); - seteaw(~dst); if (cpu_state.abrt) return 1; - CLOCK_CYCLES((cpu_mod == 3) ? timing_rr : timing_mm); - PREFETCH_RUN((cpu_mod == 3) ? timing_rr : timing_mm, 2, rmdat, (cpu_mod == 3) ? 0:1,0,(cpu_mod == 3) ? 0:1,0, 0); - break; - case 0x18: /*NEG w*/ - if (cpu_mod != 3) - SEG_CHECK_WRITE(cpu_state.ea_seg); - seteaw(0 - dst); if (cpu_state.abrt) return 1; - setsub16(0, dst); - CLOCK_CYCLES((cpu_mod == 3) ? timing_rr : timing_mm); - PREFETCH_RUN((cpu_mod == 3) ? timing_rr : timing_mm, 2, rmdat, (cpu_mod == 3) ? 0:1,0,(cpu_mod == 3) ? 0:1,0, 0); - break; - case 0x20: /*MUL AX,w*/ - templ = AX * dst; - AX = templ & 0xFFFF; - DX = templ >> 16; - flags_rebuild(); - if (DX) cpu_state.flags |= (C_FLAG | V_FLAG); - else cpu_state.flags &= ~(C_FLAG | V_FLAG); - CLOCK_CYCLES(21); - PREFETCH_RUN(21, 2, rmdat, (cpu_mod == 3) ? 0:1,0,0,0, 0); - break; - case 0x28: /*IMUL AX,w*/ - templ = (int)((int16_t)AX) * (int)((int16_t)dst); - AX = templ & 0xFFFF; - DX = templ >> 16; - flags_rebuild(); - if (((int32_t)templ >> 15) != 0 && ((int32_t)templ >> 15) != -1) cpu_state.flags |= (C_FLAG | V_FLAG); - else cpu_state.flags &= ~(C_FLAG | V_FLAG); - CLOCK_CYCLES(22); - PREFETCH_RUN(22, 2, rmdat, (cpu_mod == 3) ? 0:1,0,0,0, 0); - break; - case 0x30: /*DIV AX,w*/ - templ = (DX << 16) | AX; - if (dst) templ2 = templ / dst; - if (dst && !(templ2 & 0xffff0000)) - { - DX = templ % dst; - AX = (templ / dst) & 0xffff; - if (!cpu_iscyrix) setznp16(AX); /*Not a Cyrix*/ - } - else - { - x86_int(0); - return 1; - } - CLOCK_CYCLES((is486 && !cpu_iscyrix) ? 24 : 22); - PREFETCH_RUN((is486 && !cpu_iscyrix) ? 24 : 22, 2, rmdat, (cpu_mod == 3) ? 0:1,0,0,0, 0); - break; - case 0x38: /*IDIV AX,w*/ - tempws = (int)((DX << 16)|AX); - if (dst) tempws2 = tempws / (int)((int16_t)dst); - temps16 = tempws2 & 0xffff; - if ((dst != 0) && ((int)temps16 == tempws2)) - { - DX = tempws % (int)((int16_t)dst); - AX = tempws2 & 0xffff; - if (!cpu_iscyrix) setznp16(AX); /*Not a Cyrix*/ - } - else - { - x86_int(0); - return 1; - } - CLOCK_CYCLES(27); - PREFETCH_RUN(27, 2, rmdat, (cpu_mod == 3) ? 0:1,0,0,0, 0); - break; - - default: - x86illegal(); - } - return 0; -} -static int opF7_w_a32(uint32_t fetchdat) -{ - uint32_t templ, templ2; - int tempws, tempws2 = 1; - int16_t temps16; - uint16_t src, dst; - - fetch_ea_32(fetchdat); - if (cpu_mod != 3) - SEG_CHECK_READ(cpu_state.ea_seg); - dst = geteaw(); if (cpu_state.abrt) return 1; - switch (rmdat & 0x38) - { - case 0x00: /*TEST w*/ - case 0x08: - src = getword(); if (cpu_state.abrt) return 1; - setznp16(src & dst); - if (is486) { CLOCK_CYCLES((cpu_mod == 3) ? 1 : 2); } - else { CLOCK_CYCLES((cpu_mod == 3) ? 2 : 5); } - PREFETCH_RUN((cpu_mod == 3) ? 2 : 5, 4, rmdat, (cpu_mod == 3) ? 0:1,0,0,0, 1); - break; - case 0x10: /*NOT w*/ - if (cpu_mod != 3) - SEG_CHECK_WRITE(cpu_state.ea_seg); - seteaw(~dst); if (cpu_state.abrt) return 1; - CLOCK_CYCLES((cpu_mod == 3) ? timing_rr : timing_mm); - PREFETCH_RUN((cpu_mod == 3) ? timing_rr : timing_mm, 2, rmdat, (cpu_mod == 3) ? 0:1,0,(cpu_mod == 3) ? 0:1,0, 1); - break; - case 0x18: /*NEG w*/ - if (cpu_mod != 3) - SEG_CHECK_WRITE(cpu_state.ea_seg); - seteaw(0 - dst); if (cpu_state.abrt) return 1; - setsub16(0, dst); - CLOCK_CYCLES((cpu_mod == 3) ? timing_rr : timing_mm); - PREFETCH_RUN((cpu_mod == 3) ? timing_rr : timing_mm, 2, rmdat, (cpu_mod == 3) ? 0:1,0,(cpu_mod == 3) ? 0:1,0, 1); - break; - case 0x20: /*MUL AX,w*/ - templ = AX * dst; - AX = templ & 0xFFFF; - DX = templ >> 16; - flags_rebuild(); - if (DX) cpu_state.flags |= (C_FLAG | V_FLAG); - else cpu_state.flags &= ~(C_FLAG | V_FLAG); - CLOCK_CYCLES(21); - PREFETCH_RUN(21, 2, rmdat, (cpu_mod == 3) ? 0:1,0,0,0, 1); - break; - case 0x28: /*IMUL AX,w*/ - templ = (int)((int16_t)AX) * (int)((int16_t)dst); - AX = templ & 0xFFFF; - DX = templ >> 16; - flags_rebuild(); - if (((int32_t)templ >> 15) != 0 && ((int32_t)templ >> 15) != -1) cpu_state.flags |= (C_FLAG | V_FLAG); - else cpu_state.flags &= ~(C_FLAG | V_FLAG); - CLOCK_CYCLES(22); - PREFETCH_RUN(22, 2, rmdat, (cpu_mod == 3) ? 0:1,0,0,0, 1); - break; - case 0x30: /*DIV AX,w*/ - templ = (DX << 16) | AX; - if (dst) templ2 = templ / dst; - if (dst && !(templ2 & 0xffff0000)) - { - DX = templ % dst; - AX = (templ / dst) & 0xffff; - if (!cpu_iscyrix) setznp16(AX); /*Not a Cyrix*/ - } - else - { -// fatal("DIVw BY 0 %04X:%04X %i\n",cs>>4,pc,ins); - x86_int(0); - return 1; - } - CLOCK_CYCLES((is486 && !cpu_iscyrix) ? 24 : 22); - PREFETCH_RUN((is486 && !cpu_iscyrix) ? 24 : 22, 2, rmdat, (cpu_mod == 3) ? 0:1,0,0,0, 1); - break; - case 0x38: /*IDIV AX,w*/ - tempws = (int)((DX << 16)|AX); - if (dst) tempws2 = tempws / (int)((int16_t)dst); - temps16 = tempws2 & 0xffff; - if ((dst != 0) && ((int)temps16 == tempws2)) - { - DX = tempws % (int)((int16_t)dst); - AX = tempws2 & 0xffff; - if (!cpu_iscyrix) setznp16(AX); /*Not a Cyrix*/ - } - else - { - x86_int(0); - return 1; - } - CLOCK_CYCLES(27); - PREFETCH_RUN(27, 2, rmdat, (cpu_mod == 3) ? 0:1,0,0,0, 1); - break; - - default: - x86illegal(); - } - return 0; -} - -static int opF7_l_a16(uint32_t fetchdat) -{ - uint64_t temp64; - uint32_t src, dst; - - fetch_ea_16(fetchdat); - if (cpu_mod != 3) - SEG_CHECK_READ(cpu_state.ea_seg); - dst = geteal(); if (cpu_state.abrt) return 1; - - switch (rmdat & 0x38) - { - case 0x00: /*TEST l*/ - case 0x08: - src = getlong(); if (cpu_state.abrt) return 1; - setznp32(src & dst); - if (is486) { CLOCK_CYCLES((cpu_mod == 3) ? 1 : 2); } - else { CLOCK_CYCLES((cpu_mod == 3) ? 2 : 5); } - PREFETCH_RUN((cpu_mod == 3) ? 2 : 5, 5, rmdat, 0,(cpu_mod == 3) ? 0:1,0,0, 0); - break; - case 0x10: /*NOT l*/ - if (cpu_mod != 3) - SEG_CHECK_WRITE(cpu_state.ea_seg); - seteal(~dst); if (cpu_state.abrt) return 1; - CLOCK_CYCLES((cpu_mod == 3) ? timing_rr : timing_mml); - PREFETCH_RUN((cpu_mod == 3) ? timing_rr : timing_mm, 2, rmdat, 0,(cpu_mod == 3) ? 0:1,0,(cpu_mod == 3) ? 0:1, 0); - break; - case 0x18: /*NEG l*/ - if (cpu_mod != 3) - SEG_CHECK_WRITE(cpu_state.ea_seg); - seteal(0 - dst); if (cpu_state.abrt) return 1; - setsub32(0, dst); - CLOCK_CYCLES((cpu_mod == 3) ? timing_rr : timing_mml); - PREFETCH_RUN((cpu_mod == 3) ? timing_rr : timing_mm, 2, rmdat, 0,(cpu_mod == 3) ? 0:1,0,(cpu_mod == 3) ? 0:1, 0); - break; - case 0x20: /*MUL EAX,l*/ - temp64 = (uint64_t)EAX * (uint64_t)dst; - EAX = temp64 & 0xffffffff; - EDX = temp64 >> 32; - flags_rebuild(); - if (EDX) cpu_state.flags |= (C_FLAG|V_FLAG); - else cpu_state.flags &= ~(C_FLAG|V_FLAG); - CLOCK_CYCLES(21); - PREFETCH_RUN(21, 2, rmdat, 0,(cpu_mod == 3) ? 0:1,0,0, 0); - break; - case 0x28: /*IMUL EAX,l*/ - temp64 = (int64_t)(int32_t)EAX * (int64_t)(int32_t)dst; - EAX = temp64 & 0xffffffff; - EDX = temp64 >> 32; - flags_rebuild(); - if (((int64_t)temp64 >> 31) != 0 && ((int64_t)temp64 >> 31) != -1) cpu_state.flags |= (C_FLAG | V_FLAG); - else cpu_state.flags &= ~(C_FLAG | V_FLAG); - CLOCK_CYCLES(38); - PREFETCH_RUN(38, 2, rmdat, 0,(cpu_mod == 3) ? 0:1,0,0, 0); - break; - case 0x30: /*DIV EAX,l*/ - if (divl(dst)) - return 1; - if (!cpu_iscyrix) setznp32(EAX); /*Not a Cyrix*/ - CLOCK_CYCLES((is486) ? 40 : 38); - PREFETCH_RUN(is486 ? 40:38, 2, rmdat, 0,(cpu_mod == 3) ? 0:1,0,0, 0); - break; - case 0x38: /*IDIV EAX,l*/ - if (idivl((int32_t)dst)) - return 1; - if (!cpu_iscyrix) setznp32(EAX); /*Not a Cyrix*/ - CLOCK_CYCLES(43); - PREFETCH_RUN(43, 2, rmdat, 0,(cpu_mod == 3) ? 0:1,0,0, 0); - break; - - default: - x86illegal(); - } - return 0; -} -static int opF7_l_a32(uint32_t fetchdat) -{ - uint64_t temp64; - uint32_t src, dst; - - fetch_ea_32(fetchdat); - if (cpu_mod != 3) - SEG_CHECK_READ(cpu_state.ea_seg); - dst = geteal(); if (cpu_state.abrt) return 1; - - switch (rmdat & 0x38) - { - case 0x00: /*TEST l*/ - case 0x08: - src = getlong(); if (cpu_state.abrt) return 1; - setznp32(src & dst); - if (is486) { CLOCK_CYCLES((cpu_mod == 3) ? 1 : 2); } - else { CLOCK_CYCLES((cpu_mod == 3) ? 2 : 5); } - PREFETCH_RUN((cpu_mod == 3) ? 2 : 5, 5, rmdat, 0,(cpu_mod == 3) ? 0:1,0,0, 1); - break; - case 0x10: /*NOT l*/ - if (cpu_mod != 3) - SEG_CHECK_WRITE(cpu_state.ea_seg); - seteal(~dst); if (cpu_state.abrt) return 1; - CLOCK_CYCLES((cpu_mod == 3) ? timing_rr : timing_mml); - PREFETCH_RUN((cpu_mod == 3) ? timing_rr : timing_mm, 2, rmdat, 0,(cpu_mod == 3) ? 0:1,0,(cpu_mod == 3) ? 0:1, 1); - break; - case 0x18: /*NEG l*/ - if (cpu_mod != 3) - SEG_CHECK_WRITE(cpu_state.ea_seg); - seteal(0 - dst); if (cpu_state.abrt) return 1; - setsub32(0, dst); - CLOCK_CYCLES((cpu_mod == 3) ? timing_rr : timing_mml); - PREFETCH_RUN((cpu_mod == 3) ? timing_rr : timing_mm, 2, rmdat, 0,(cpu_mod == 3) ? 0:1,0,(cpu_mod == 3) ? 0:1, 1); - break; - case 0x20: /*MUL EAX,l*/ - temp64 = (uint64_t)EAX * (uint64_t)dst; - EAX = temp64 & 0xffffffff; - EDX = temp64 >> 32; - flags_rebuild(); - if (EDX) cpu_state.flags |= (C_FLAG|V_FLAG); - else cpu_state.flags &= ~(C_FLAG|V_FLAG); - CLOCK_CYCLES(21); - PREFETCH_RUN(21, 2, rmdat, 0,(cpu_mod == 3) ? 0:1,0,0, 1); - break; - case 0x28: /*IMUL EAX,l*/ - temp64 = (int64_t)(int32_t)EAX * (int64_t)(int32_t)dst; - EAX = temp64 & 0xffffffff; - EDX = temp64 >> 32; - flags_rebuild(); - if (((int64_t)temp64 >> 31) != 0 && ((int64_t)temp64 >> 31) != -1) cpu_state.flags |= (C_FLAG | V_FLAG); - else cpu_state.flags &= ~(C_FLAG | V_FLAG); - CLOCK_CYCLES(38); - PREFETCH_RUN(38, 2, rmdat, 0,(cpu_mod == 3) ? 0:1,0,0, 1); - break; - case 0x30: /*DIV EAX,l*/ - if (divl(dst)) - return 1; - if (!cpu_iscyrix) setznp32(EAX); /*Not a Cyrix*/ - CLOCK_CYCLES((is486) ? 40 : 38); - PREFETCH_RUN(is486 ? 40 : 38, 2, rmdat, 0,(cpu_mod == 3) ? 0:1,0,0, 1); - break; - case 0x38: /*IDIV EAX,l*/ - if (idivl((int32_t)dst)) - return 1; - if (!cpu_iscyrix) setznp32(EAX); /*Not a Cyrix*/ - CLOCK_CYCLES(43); - PREFETCH_RUN(43, 2, rmdat, 0,(cpu_mod == 3) ? 0:1,0,0, 1); - break; - - default: - x86illegal(); - } - return 0; -} - - -static int opHLT(uint32_t fetchdat) -{ - if ((CPL || (cpu_state.eflags&VM_FLAG)) && (cr0&1)) - { - x86gpf(NULL,0); - return 1; - } - if (smi_line) - enter_smm_check(1); - else if (!((cpu_state.flags & I_FLAG) && pic.int_pending)) - { - CLOCK_CYCLES_ALWAYS(100); - if (!((cpu_state.flags & I_FLAG) && pic.int_pending)) - cpu_state.pc--; - } - else { - CLOCK_CYCLES(5); - } - - CPU_BLOCK_END(); - PREFETCH_RUN(100, 1, -1, 0,0,0,0, 0); - - if (hlt_reset_pending) - softresetx86(); - - return 0; -} - - -static int opLOCK(uint32_t fetchdat) -{ - fetchdat = fastreadl(cs + cpu_state.pc); - if (cpu_state.abrt) return 0; - cpu_state.pc++; - - ILLEGAL_ON((fetchdat & 0xff) == 0x90); - - CLOCK_CYCLES(4); - PREFETCH_PREFIX(); - return x86_opcodes[(fetchdat & 0xff) | cpu_state.op32](fetchdat >> 8); -} - - - -static int opBOUND_w_a16(uint32_t fetchdat) -{ - int16_t low, high; - - fetch_ea_16(fetchdat); - ILLEGAL_ON(cpu_mod == 3); + fetch_ea_16(fetchdat); + if (cpu_mod != 3) { SEG_CHECK_READ(cpu_state.ea_seg); - low = geteaw(); - high = readmemw(easeg, cpu_state.eaaddr + 2); if (cpu_state.abrt) return 1; - - if (((int16_t)cpu_state.regs[cpu_reg].w < low) || ((int16_t)cpu_state.regs[cpu_reg].w > high)) - { - x86_int(5); + CHECK_READ(cpu_state.ea_seg, cpu_state.eaaddr, cpu_state.eaaddr); + } + dst = geteab(); + if (cpu_state.abrt) + return 1; + switch (rmdat & 0x38) { + case 0x00: /*TEST b,#8*/ + case 0x08: + src = readmemb(cs, cpu_state.pc); + cpu_state.pc++; + if (cpu_state.abrt) return 1; - } - - CLOCK_CYCLES(is486 ? 7 : 10); - PREFETCH_RUN(is486 ? 7 : 10, 2, rmdat, 2,0,0,0, 0); - return 0; -} -static int opBOUND_w_a32(uint32_t fetchdat) -{ - int16_t low, high; - - fetch_ea_32(fetchdat); - ILLEGAL_ON(cpu_mod == 3); - SEG_CHECK_READ(cpu_state.ea_seg); - low = geteaw(); - high = readmemw(easeg, cpu_state.eaaddr + 2); if (cpu_state.abrt) return 1; - - if (((int16_t)cpu_state.regs[cpu_reg].w < low) || ((int16_t)cpu_state.regs[cpu_reg].w > high)) - { - x86_int(5); + setznp8(src & dst); + if (is486) { + CLOCK_CYCLES((cpu_mod == 3) ? 1 : 2); + } else { + CLOCK_CYCLES((cpu_mod == 3) ? 2 : 5); + } + PREFETCH_RUN((cpu_mod == 3) ? 2 : 5, 3, rmdat, (cpu_mod == 3) ? 0 : 1, 0, 0, 0, 0); + break; + case 0x10: /*NOT b*/ + if (cpu_mod != 3) + SEG_CHECK_WRITE(cpu_state.ea_seg); + seteab(~dst); + if (cpu_state.abrt) return 1; - } - - CLOCK_CYCLES(is486 ? 7 : 10); - PREFETCH_RUN(is486 ? 7 : 10, 2, rmdat, 2,0,0,0, 1); - return 0; -} + CLOCK_CYCLES((cpu_mod == 3) ? timing_rr : timing_mm); + PREFETCH_RUN((cpu_mod == 3) ? timing_rr : timing_mm, 2, rmdat, (cpu_mod == 3) ? 0 : 1, 0, (cpu_mod == 3) ? 0 : 1, 0, 0); + break; + case 0x18: /*NEG b*/ + if (cpu_mod != 3) + SEG_CHECK_WRITE(cpu_state.ea_seg); + seteab(0 - dst); + if (cpu_state.abrt) + return 1; + setsub8(0, dst); + CLOCK_CYCLES((cpu_mod == 3) ? timing_rr : timing_mm); + PREFETCH_RUN((cpu_mod == 3) ? timing_rr : timing_mm, 2, rmdat, (cpu_mod == 3) ? 0 : 1, 0, (cpu_mod == 3) ? 0 : 1, 0, 0); + break; + case 0x20: /*MUL AL,b*/ + AX = AL * dst; + flags_rebuild(); + if (AH) + cpu_state.flags |= (C_FLAG | V_FLAG); + else + cpu_state.flags &= ~(C_FLAG | V_FLAG); + CLOCK_CYCLES(13); + PREFETCH_RUN(13, 2, rmdat, (cpu_mod == 3) ? 0 : 1, 0, 0, 0, 0); + break; + case 0x28: /*IMUL AL,b*/ + tempws = (int) ((int8_t) AL) * (int) ((int8_t) dst); + AX = tempws & 0xffff; + flags_rebuild(); + if (((int16_t) AX >> 7) != 0 && ((int16_t) AX >> 7) != -1) + cpu_state.flags |= (C_FLAG | V_FLAG); + else + cpu_state.flags &= ~(C_FLAG | V_FLAG); + CLOCK_CYCLES(14); + PREFETCH_RUN(14, 2, rmdat, (cpu_mod == 3) ? 0 : 1, 0, 0, 0, 0); + break; + case 0x30: /*DIV AL,b*/ + src16 = AX; + if (dst) + tempw = src16 / dst; + if (dst && !(tempw & 0xff00)) { + AH = src16 % dst; + AL = (src16 / dst) & 0xff; + if (!cpu_iscyrix) { + flags_rebuild(); + cpu_state.flags |= 0x8D5; /*Not a Cyrix*/ + cpu_state.flags &= ~1; + } + } else { + x86_int(0); + return 1; + } + CLOCK_CYCLES((is486 && !cpu_iscyrix) ? 16 : 14); + PREFETCH_RUN((is486 && !cpu_iscyrix) ? 16 : 14, 2, rmdat, (cpu_mod == 3) ? 0 : 1, 0, 0, 0, 0); + break; + case 0x38: /*IDIV AL,b*/ + tempws = (int) (int16_t) AX; + if (dst != 0) + tempws2 = tempws / (int) ((int8_t) dst); + temps = tempws2 & 0xff; + if (dst && ((int) temps == tempws2)) { + AH = (tempws % (int) ((int8_t) dst)) & 0xff; + AL = tempws2 & 0xff; + if (!cpu_iscyrix) { + flags_rebuild(); + cpu_state.flags |= 0x8D5; /*Not a Cyrix*/ + cpu_state.flags &= ~1; + } + } else { + x86_int(0); + return 1; + } + CLOCK_CYCLES(19); + PREFETCH_RUN(19, 2, rmdat, (cpu_mod == 3) ? 0 : 1, 0, 0, 0, 0); + break; -static int opBOUND_l_a16(uint32_t fetchdat) -{ - int32_t low, high; - - fetch_ea_16(fetchdat); - ILLEGAL_ON(cpu_mod == 3); - SEG_CHECK_READ(cpu_state.ea_seg); - low = geteal(); - high = readmeml(easeg, cpu_state.eaaddr + 4); if (cpu_state.abrt) return 1; - - if (((int32_t)cpu_state.regs[cpu_reg].l < low) || ((int32_t)cpu_state.regs[cpu_reg].l > high)) - { - x86_int(5); - return 1; - } - - CLOCK_CYCLES(is486 ? 7 : 10); - PREFETCH_RUN(is486 ? 7 : 10, 2, rmdat, 1,1,0,0, 0); - return 0; + default: + x86illegal(); + } + return 0; } -static int opBOUND_l_a32(uint32_t fetchdat) -{ - int32_t low, high; - - fetch_ea_32(fetchdat); - ILLEGAL_ON(cpu_mod == 3); - SEG_CHECK_READ(cpu_state.ea_seg); - low = geteal(); - high = readmeml(easeg, cpu_state.eaaddr + 4); if (cpu_state.abrt) return 1; - - if (((int32_t)cpu_state.regs[cpu_reg].l < low) || ((int32_t)cpu_state.regs[cpu_reg].l > high)) - { - x86_int(5); - return 1; - } - - CLOCK_CYCLES(is486 ? 7 : 10); - PREFETCH_RUN(is486 ? 7 : 10, 2, rmdat, 1,1,0,0, 1); - return 0; -} - - -static int opCLTS(uint32_t fetchdat) +static int +opF6_a32(uint32_t fetchdat) { - if ((CPL || (cpu_state.eflags&VM_FLAG)) && (cr0&1)) - { - x86gpf(NULL,0); + int tempws = 0; + int tempws2 = 0; + uint16_t tempw = 0; + uint16_t src16; + uint8_t src; + uint8_t dst; + int8_t temps; + + fetch_ea_32(fetchdat); + if (cpu_mod != 3) + SEG_CHECK_READ(cpu_state.ea_seg); + dst = geteab(); + if (cpu_state.abrt) + return 1; + switch (rmdat & 0x38) { + case 0x00: /*TEST b,#8*/ + case 0x08: + src = readmemb(cs, cpu_state.pc); + cpu_state.pc++; + if (cpu_state.abrt) return 1; - } - cr0 &= ~8; + setznp8(src & dst); + if (is486) { + CLOCK_CYCLES((cpu_mod == 3) ? 1 : 2); + } else { + CLOCK_CYCLES((cpu_mod == 3) ? 2 : 5); + } + PREFETCH_RUN((cpu_mod == 3) ? 2 : 5, 3, rmdat, (cpu_mod == 3) ? 0 : 1, 0, 0, 0, 1); + break; + case 0x10: /*NOT b*/ + if (cpu_mod != 3) + SEG_CHECK_WRITE(cpu_state.ea_seg); + seteab(~dst); + if (cpu_state.abrt) + return 1; + CLOCK_CYCLES((cpu_mod == 3) ? timing_rr : timing_mm); + PREFETCH_RUN((cpu_mod == 3) ? timing_rr : timing_mm, 2, rmdat, (cpu_mod == 3) ? 0 : 1, 0, (cpu_mod == 3) ? 0 : 1, 0, 1); + break; + case 0x18: /*NEG b*/ + if (cpu_mod != 3) + SEG_CHECK_WRITE(cpu_state.ea_seg); + seteab(0 - dst); + if (cpu_state.abrt) + return 1; + setsub8(0, dst); + CLOCK_CYCLES((cpu_mod == 3) ? timing_rr : timing_mm); + PREFETCH_RUN((cpu_mod == 3) ? timing_rr : timing_mm, 2, rmdat, (cpu_mod == 3) ? 0 : 1, 0, (cpu_mod == 3) ? 0 : 1, 0, 1); + break; + case 0x20: /*MUL AL,b*/ + AX = AL * dst; + flags_rebuild(); + if (AH) + cpu_state.flags |= (C_FLAG | V_FLAG); + else + cpu_state.flags &= ~(C_FLAG | V_FLAG); + CLOCK_CYCLES(13); + PREFETCH_RUN(13, 2, rmdat, (cpu_mod == 3) ? 0 : 1, 0, 0, 0, 1); + break; + case 0x28: /*IMUL AL,b*/ + tempws = (int) ((int8_t) AL) * (int) ((int8_t) dst); + AX = tempws & 0xffff; + flags_rebuild(); + if (((int16_t) AX >> 7) != 0 && ((int16_t) AX >> 7) != -1) + cpu_state.flags |= (C_FLAG | V_FLAG); + else + cpu_state.flags &= ~(C_FLAG | V_FLAG); + CLOCK_CYCLES(14); + PREFETCH_RUN(14, 2, rmdat, (cpu_mod == 3) ? 0 : 1, 0, 0, 0, 1); + break; + case 0x30: /*DIV AL,b*/ + src16 = AX; + if (dst) + tempw = src16 / dst; + if (dst && !(tempw & 0xff00)) { + AH = src16 % dst; + AL = (src16 / dst) & 0xff; + if (!cpu_iscyrix) { + flags_rebuild(); + cpu_state.flags |= 0x8D5; /*Not a Cyrix*/ + cpu_state.flags &= ~1; + } + } else { + x86_int(0); + return 1; + } + CLOCK_CYCLES((is486 && !cpu_iscyrix) ? 16 : 14); + PREFETCH_RUN((is486 && !cpu_iscyrix) ? 16 : 14, 2, rmdat, (cpu_mod == 3) ? 0 : 1, 0, 0, 0, 1); + break; + case 0x38: /*IDIV AL,b*/ + tempws = (int) (int16_t) AX; + if (dst != 0) + tempws2 = tempws / (int) ((int8_t) dst); + temps = tempws2 & 0xff; + if (dst && ((int) temps == tempws2)) { + AH = (tempws % (int) ((int8_t) dst)) & 0xff; + AL = tempws2 & 0xff; + if (!cpu_iscyrix) { + flags_rebuild(); + cpu_state.flags |= 0x8D5; /*Not a Cyrix*/ + cpu_state.flags &= ~1; + } + } else { + x86_int(0); + return 1; + } + CLOCK_CYCLES(19); + PREFETCH_RUN(19, 2, rmdat, (cpu_mod == 3) ? 0 : 1, 0, 0, 0, 1); + break; + + default: + x86illegal(); + } + return 0; +} + +static int +opF7_w_a16(uint32_t fetchdat) +{ + uint32_t templ; + uint32_t templ2 = 0; + int tempws; + int tempws2 = 0; + int16_t temps16; + uint16_t src; + uint16_t dst; + + fetch_ea_16(fetchdat); + if (cpu_mod != 3) + SEG_CHECK_READ(cpu_state.ea_seg); + dst = geteaw(); + if (cpu_state.abrt) + return 1; + switch (rmdat & 0x38) { + case 0x00: /*TEST w*/ + case 0x08: + src = getword(); + if (cpu_state.abrt) + return 1; + setznp16(src & dst); + if (is486) { + CLOCK_CYCLES((cpu_mod == 3) ? 1 : 2); + } else { + CLOCK_CYCLES((cpu_mod == 3) ? 2 : 5); + } + PREFETCH_RUN((cpu_mod == 3) ? 2 : 5, 4, rmdat, (cpu_mod == 3) ? 0 : 1, 0, 0, 0, 0); + break; + case 0x10: /*NOT w*/ + if (cpu_mod != 3) + SEG_CHECK_WRITE(cpu_state.ea_seg); + seteaw(~dst); + if (cpu_state.abrt) + return 1; + CLOCK_CYCLES((cpu_mod == 3) ? timing_rr : timing_mm); + PREFETCH_RUN((cpu_mod == 3) ? timing_rr : timing_mm, 2, rmdat, (cpu_mod == 3) ? 0 : 1, 0, (cpu_mod == 3) ? 0 : 1, 0, 0); + break; + case 0x18: /*NEG w*/ + if (cpu_mod != 3) + SEG_CHECK_WRITE(cpu_state.ea_seg); + seteaw(0 - dst); + if (cpu_state.abrt) + return 1; + setsub16(0, dst); + CLOCK_CYCLES((cpu_mod == 3) ? timing_rr : timing_mm); + PREFETCH_RUN((cpu_mod == 3) ? timing_rr : timing_mm, 2, rmdat, (cpu_mod == 3) ? 0 : 1, 0, (cpu_mod == 3) ? 0 : 1, 0, 0); + break; + case 0x20: /*MUL AX,w*/ + templ = AX * dst; + AX = templ & 0xFFFF; + DX = templ >> 16; + flags_rebuild(); + if (DX) + cpu_state.flags |= (C_FLAG | V_FLAG); + else + cpu_state.flags &= ~(C_FLAG | V_FLAG); + CLOCK_CYCLES(21); + PREFETCH_RUN(21, 2, rmdat, (cpu_mod == 3) ? 0 : 1, 0, 0, 0, 0); + break; + case 0x28: /*IMUL AX,w*/ + templ = (int) ((int16_t) AX) * (int) ((int16_t) dst); + AX = templ & 0xFFFF; + DX = templ >> 16; + flags_rebuild(); + if (((int32_t) templ >> 15) != 0 && ((int32_t) templ >> 15) != -1) + cpu_state.flags |= (C_FLAG | V_FLAG); + else + cpu_state.flags &= ~(C_FLAG | V_FLAG); + CLOCK_CYCLES(22); + PREFETCH_RUN(22, 2, rmdat, (cpu_mod == 3) ? 0 : 1, 0, 0, 0, 0); + break; + case 0x30: /*DIV AX,w*/ + templ = (DX << 16) | AX; + if (dst) + templ2 = templ / dst; + if (dst && !(templ2 & 0xffff0000)) { + DX = templ % dst; + AX = (templ / dst) & 0xffff; + if (!cpu_iscyrix) + setznp16(AX); /*Not a Cyrix*/ + } else { + x86_int(0); + return 1; + } + CLOCK_CYCLES((is486 && !cpu_iscyrix) ? 24 : 22); + PREFETCH_RUN((is486 && !cpu_iscyrix) ? 24 : 22, 2, rmdat, (cpu_mod == 3) ? 0 : 1, 0, 0, 0, 0); + break; + case 0x38: /*IDIV AX,w*/ + tempws = (int) ((DX << 16) | AX); + if (dst) + tempws2 = tempws / (int) ((int16_t) dst); + temps16 = tempws2 & 0xffff; + if ((dst != 0) && ((int) temps16 == tempws2)) { + DX = tempws % (int) ((int16_t) dst); + AX = tempws2 & 0xffff; + if (!cpu_iscyrix) + setznp16(AX); /*Not a Cyrix*/ + } else { + x86_int(0); + return 1; + } + CLOCK_CYCLES(27); + PREFETCH_RUN(27, 2, rmdat, (cpu_mod == 3) ? 0 : 1, 0, 0, 0, 0); + break; + + default: + x86illegal(); + } + return 0; +} +static int +opF7_w_a32(uint32_t fetchdat) +{ + uint32_t templ; + uint32_t templ2 = 0; + int tempws; + int tempws2 = 1; + int16_t temps16; + uint16_t src; + uint16_t dst; + + fetch_ea_32(fetchdat); + if (cpu_mod != 3) + SEG_CHECK_READ(cpu_state.ea_seg); + dst = geteaw(); + if (cpu_state.abrt) + return 1; + switch (rmdat & 0x38) { + case 0x00: /*TEST w*/ + case 0x08: + src = getword(); + if (cpu_state.abrt) + return 1; + setznp16(src & dst); + if (is486) { + CLOCK_CYCLES((cpu_mod == 3) ? 1 : 2); + } else { + CLOCK_CYCLES((cpu_mod == 3) ? 2 : 5); + } + PREFETCH_RUN((cpu_mod == 3) ? 2 : 5, 4, rmdat, (cpu_mod == 3) ? 0 : 1, 0, 0, 0, 1); + break; + case 0x10: /*NOT w*/ + if (cpu_mod != 3) + SEG_CHECK_WRITE(cpu_state.ea_seg); + seteaw(~dst); + if (cpu_state.abrt) + return 1; + CLOCK_CYCLES((cpu_mod == 3) ? timing_rr : timing_mm); + PREFETCH_RUN((cpu_mod == 3) ? timing_rr : timing_mm, 2, rmdat, (cpu_mod == 3) ? 0 : 1, 0, (cpu_mod == 3) ? 0 : 1, 0, 1); + break; + case 0x18: /*NEG w*/ + if (cpu_mod != 3) + SEG_CHECK_WRITE(cpu_state.ea_seg); + seteaw(0 - dst); + if (cpu_state.abrt) + return 1; + setsub16(0, dst); + CLOCK_CYCLES((cpu_mod == 3) ? timing_rr : timing_mm); + PREFETCH_RUN((cpu_mod == 3) ? timing_rr : timing_mm, 2, rmdat, (cpu_mod == 3) ? 0 : 1, 0, (cpu_mod == 3) ? 0 : 1, 0, 1); + break; + case 0x20: /*MUL AX,w*/ + templ = AX * dst; + AX = templ & 0xFFFF; + DX = templ >> 16; + flags_rebuild(); + if (DX) + cpu_state.flags |= (C_FLAG | V_FLAG); + else + cpu_state.flags &= ~(C_FLAG | V_FLAG); + CLOCK_CYCLES(21); + PREFETCH_RUN(21, 2, rmdat, (cpu_mod == 3) ? 0 : 1, 0, 0, 0, 1); + break; + case 0x28: /*IMUL AX,w*/ + templ = (int) ((int16_t) AX) * (int) ((int16_t) dst); + AX = templ & 0xFFFF; + DX = templ >> 16; + flags_rebuild(); + if (((int32_t) templ >> 15) != 0 && ((int32_t) templ >> 15) != -1) + cpu_state.flags |= (C_FLAG | V_FLAG); + else + cpu_state.flags &= ~(C_FLAG | V_FLAG); + CLOCK_CYCLES(22); + PREFETCH_RUN(22, 2, rmdat, (cpu_mod == 3) ? 0 : 1, 0, 0, 0, 1); + break; + case 0x30: /*DIV AX,w*/ + templ = (DX << 16) | AX; + if (dst) + templ2 = templ / dst; + if (dst && !(templ2 & 0xffff0000)) { + DX = templ % dst; + AX = (templ / dst) & 0xffff; + if (!cpu_iscyrix) + setznp16(AX); /*Not a Cyrix*/ + } else { + // fatal("DIVw BY 0 %04X:%04X %i\n",cs>>4,pc,ins); + x86_int(0); + return 1; + } + CLOCK_CYCLES((is486 && !cpu_iscyrix) ? 24 : 22); + PREFETCH_RUN((is486 && !cpu_iscyrix) ? 24 : 22, 2, rmdat, (cpu_mod == 3) ? 0 : 1, 0, 0, 0, 1); + break; + case 0x38: /*IDIV AX,w*/ + tempws = (int) ((DX << 16) | AX); + if (dst) + tempws2 = tempws / (int) ((int16_t) dst); + temps16 = tempws2 & 0xffff; + if ((dst != 0) && ((int) temps16 == tempws2)) { + DX = tempws % (int) ((int16_t) dst); + AX = tempws2 & 0xffff; + if (!cpu_iscyrix) + setznp16(AX); /*Not a Cyrix*/ + } else { + x86_int(0); + return 1; + } + CLOCK_CYCLES(27); + PREFETCH_RUN(27, 2, rmdat, (cpu_mod == 3) ? 0 : 1, 0, 0, 0, 1); + break; + + default: + x86illegal(); + } + return 0; +} + +static int +opF7_l_a16(uint32_t fetchdat) +{ + uint64_t temp64; + uint32_t src; + uint32_t dst; + + fetch_ea_16(fetchdat); + if (cpu_mod != 3) + SEG_CHECK_READ(cpu_state.ea_seg); + dst = geteal(); + if (cpu_state.abrt) + return 1; + + switch (rmdat & 0x38) { + case 0x00: /*TEST l*/ + case 0x08: + src = getlong(); + if (cpu_state.abrt) + return 1; + setznp32(src & dst); + if (is486) { + CLOCK_CYCLES((cpu_mod == 3) ? 1 : 2); + } else { + CLOCK_CYCLES((cpu_mod == 3) ? 2 : 5); + } + PREFETCH_RUN((cpu_mod == 3) ? 2 : 5, 5, rmdat, 0, (cpu_mod == 3) ? 0 : 1, 0, 0, 0); + break; + case 0x10: /*NOT l*/ + if (cpu_mod != 3) + SEG_CHECK_WRITE(cpu_state.ea_seg); + seteal(~dst); + if (cpu_state.abrt) + return 1; + CLOCK_CYCLES((cpu_mod == 3) ? timing_rr : timing_mml); + PREFETCH_RUN((cpu_mod == 3) ? timing_rr : timing_mm, 2, rmdat, 0, (cpu_mod == 3) ? 0 : 1, 0, (cpu_mod == 3) ? 0 : 1, 0); + break; + case 0x18: /*NEG l*/ + if (cpu_mod != 3) + SEG_CHECK_WRITE(cpu_state.ea_seg); + seteal(0 - dst); + if (cpu_state.abrt) + return 1; + setsub32(0, dst); + CLOCK_CYCLES((cpu_mod == 3) ? timing_rr : timing_mml); + PREFETCH_RUN((cpu_mod == 3) ? timing_rr : timing_mm, 2, rmdat, 0, (cpu_mod == 3) ? 0 : 1, 0, (cpu_mod == 3) ? 0 : 1, 0); + break; + case 0x20: /*MUL EAX,l*/ + temp64 = (uint64_t) EAX * (uint64_t) dst; + EAX = temp64 & 0xffffffff; + EDX = temp64 >> 32; + flags_rebuild(); + if (EDX) + cpu_state.flags |= (C_FLAG | V_FLAG); + else + cpu_state.flags &= ~(C_FLAG | V_FLAG); + CLOCK_CYCLES(21); + PREFETCH_RUN(21, 2, rmdat, 0, (cpu_mod == 3) ? 0 : 1, 0, 0, 0); + break; + case 0x28: /*IMUL EAX,l*/ + temp64 = (int64_t) (int32_t) EAX * (int64_t) (int32_t) dst; + EAX = temp64 & 0xffffffff; + EDX = temp64 >> 32; + flags_rebuild(); + if (((int64_t) temp64 >> 31) != 0 && ((int64_t) temp64 >> 31) != -1) + cpu_state.flags |= (C_FLAG | V_FLAG); + else + cpu_state.flags &= ~(C_FLAG | V_FLAG); + CLOCK_CYCLES(38); + PREFETCH_RUN(38, 2, rmdat, 0, (cpu_mod == 3) ? 0 : 1, 0, 0, 0); + break; + case 0x30: /*DIV EAX,l*/ + if (divl(dst)) + return 1; + if (!cpu_iscyrix) + setznp32(EAX); /*Not a Cyrix*/ + CLOCK_CYCLES((is486) ? 40 : 38); + PREFETCH_RUN(is486 ? 40 : 38, 2, rmdat, 0, (cpu_mod == 3) ? 0 : 1, 0, 0, 0); + break; + case 0x38: /*IDIV EAX,l*/ + if (idivl((int32_t) dst)) + return 1; + if (!cpu_iscyrix) + setznp32(EAX); /*Not a Cyrix*/ + CLOCK_CYCLES(43); + PREFETCH_RUN(43, 2, rmdat, 0, (cpu_mod == 3) ? 0 : 1, 0, 0, 0); + break; + + default: + x86illegal(); + } + return 0; +} +static int +opF7_l_a32(uint32_t fetchdat) +{ + uint64_t temp64; + uint32_t src; + uint32_t dst; + + fetch_ea_32(fetchdat); + if (cpu_mod != 3) + SEG_CHECK_READ(cpu_state.ea_seg); + dst = geteal(); + if (cpu_state.abrt) + return 1; + + switch (rmdat & 0x38) { + case 0x00: /*TEST l*/ + case 0x08: + src = getlong(); + if (cpu_state.abrt) + return 1; + setznp32(src & dst); + if (is486) { + CLOCK_CYCLES((cpu_mod == 3) ? 1 : 2); + } else { + CLOCK_CYCLES((cpu_mod == 3) ? 2 : 5); + } + PREFETCH_RUN((cpu_mod == 3) ? 2 : 5, 5, rmdat, 0, (cpu_mod == 3) ? 0 : 1, 0, 0, 1); + break; + case 0x10: /*NOT l*/ + if (cpu_mod != 3) + SEG_CHECK_WRITE(cpu_state.ea_seg); + seteal(~dst); + if (cpu_state.abrt) + return 1; + CLOCK_CYCLES((cpu_mod == 3) ? timing_rr : timing_mml); + PREFETCH_RUN((cpu_mod == 3) ? timing_rr : timing_mm, 2, rmdat, 0, (cpu_mod == 3) ? 0 : 1, 0, (cpu_mod == 3) ? 0 : 1, 1); + break; + case 0x18: /*NEG l*/ + if (cpu_mod != 3) + SEG_CHECK_WRITE(cpu_state.ea_seg); + seteal(0 - dst); + if (cpu_state.abrt) + return 1; + setsub32(0, dst); + CLOCK_CYCLES((cpu_mod == 3) ? timing_rr : timing_mml); + PREFETCH_RUN((cpu_mod == 3) ? timing_rr : timing_mm, 2, rmdat, 0, (cpu_mod == 3) ? 0 : 1, 0, (cpu_mod == 3) ? 0 : 1, 1); + break; + case 0x20: /*MUL EAX,l*/ + temp64 = (uint64_t) EAX * (uint64_t) dst; + EAX = temp64 & 0xffffffff; + EDX = temp64 >> 32; + flags_rebuild(); + if (EDX) + cpu_state.flags |= (C_FLAG | V_FLAG); + else + cpu_state.flags &= ~(C_FLAG | V_FLAG); + CLOCK_CYCLES(21); + PREFETCH_RUN(21, 2, rmdat, 0, (cpu_mod == 3) ? 0 : 1, 0, 0, 1); + break; + case 0x28: /*IMUL EAX,l*/ + temp64 = (int64_t) (int32_t) EAX * (int64_t) (int32_t) dst; + EAX = temp64 & 0xffffffff; + EDX = temp64 >> 32; + flags_rebuild(); + if (((int64_t) temp64 >> 31) != 0 && ((int64_t) temp64 >> 31) != -1) + cpu_state.flags |= (C_FLAG | V_FLAG); + else + cpu_state.flags &= ~(C_FLAG | V_FLAG); + CLOCK_CYCLES(38); + PREFETCH_RUN(38, 2, rmdat, 0, (cpu_mod == 3) ? 0 : 1, 0, 0, 1); + break; + case 0x30: /*DIV EAX,l*/ + if (divl(dst)) + return 1; + if (!cpu_iscyrix) + setznp32(EAX); /*Not a Cyrix*/ + CLOCK_CYCLES((is486) ? 40 : 38); + PREFETCH_RUN(is486 ? 40 : 38, 2, rmdat, 0, (cpu_mod == 3) ? 0 : 1, 0, 0, 1); + break; + case 0x38: /*IDIV EAX,l*/ + if (idivl((int32_t) dst)) + return 1; + if (!cpu_iscyrix) + setznp32(EAX); /*Not a Cyrix*/ + CLOCK_CYCLES(43); + PREFETCH_RUN(43, 2, rmdat, 0, (cpu_mod == 3) ? 0 : 1, 0, 0, 1); + break; + + default: + x86illegal(); + } + return 0; +} + +static int +opHLT(uint32_t fetchdat) +{ + if ((CPL || (cpu_state.eflags & VM_FLAG)) && (cr0 & 1)) { + x86gpf(NULL, 0); + return 1; + } + if (smi_line) + enter_smm_check(1); + else if (!((cpu_state.flags & I_FLAG) && pic.int_pending)) { + CLOCK_CYCLES_ALWAYS(100); + if (!((cpu_state.flags & I_FLAG) && pic.int_pending)) + cpu_state.pc--; + } else { CLOCK_CYCLES(5); - PREFETCH_RUN(5, 1, -1, 0,0,0,0, 0); - return 0; + } + + CPU_BLOCK_END(); + PREFETCH_RUN(100, 1, -1, 0, 0, 0, 0, 0); + + if (hlt_reset_pending) + softresetx86(); + + return 0; } -static int opINVD(uint32_t fetchdat) +static int +opLOCK(uint32_t fetchdat) { - CLOCK_CYCLES(1000); + fetchdat = fastreadl(cs + cpu_state.pc); + if (cpu_state.abrt) + return 0; + cpu_state.pc++; + + ILLEGAL_ON((fetchdat & 0xff) == 0x90); + + CLOCK_CYCLES(4); + PREFETCH_PREFIX(); + return x86_opcodes[(fetchdat & 0xff) | cpu_state.op32](fetchdat >> 8); +} + +static int +opBOUND_w_a16(uint32_t fetchdat) +{ + int16_t low; + int16_t high; + + fetch_ea_16(fetchdat); + ILLEGAL_ON(cpu_mod == 3); + SEG_CHECK_READ(cpu_state.ea_seg); + low = geteaw(); + high = readmemw(easeg, cpu_state.eaaddr + 2); + if (cpu_state.abrt) + return 1; + + if (((int16_t) cpu_state.regs[cpu_reg].w < low) || ((int16_t) cpu_state.regs[cpu_reg].w > high)) { + x86_int(5); + return 1; + } + + CLOCK_CYCLES(is486 ? 7 : 10); + PREFETCH_RUN(is486 ? 7 : 10, 2, rmdat, 2, 0, 0, 0, 0); + return 0; +} +static int +opBOUND_w_a32(uint32_t fetchdat) +{ + int16_t low; + int16_t high; + + fetch_ea_32(fetchdat); + ILLEGAL_ON(cpu_mod == 3); + SEG_CHECK_READ(cpu_state.ea_seg); + low = geteaw(); + high = readmemw(easeg, cpu_state.eaaddr + 2); + if (cpu_state.abrt) + return 1; + + if (((int16_t) cpu_state.regs[cpu_reg].w < low) || ((int16_t) cpu_state.regs[cpu_reg].w > high)) { + x86_int(5); + return 1; + } + + CLOCK_CYCLES(is486 ? 7 : 10); + PREFETCH_RUN(is486 ? 7 : 10, 2, rmdat, 2, 0, 0, 0, 1); + return 0; +} + +static int +opBOUND_l_a16(uint32_t fetchdat) +{ + int32_t low; + int32_t high; + + fetch_ea_16(fetchdat); + ILLEGAL_ON(cpu_mod == 3); + SEG_CHECK_READ(cpu_state.ea_seg); + low = geteal(); + high = readmeml(easeg, cpu_state.eaaddr + 4); + if (cpu_state.abrt) + return 1; + + if (((int32_t) cpu_state.regs[cpu_reg].l < low) || ((int32_t) cpu_state.regs[cpu_reg].l > high)) { + x86_int(5); + return 1; + } + + CLOCK_CYCLES(is486 ? 7 : 10); + PREFETCH_RUN(is486 ? 7 : 10, 2, rmdat, 1, 1, 0, 0, 0); + return 0; +} +static int +opBOUND_l_a32(uint32_t fetchdat) +{ + int32_t low; + int32_t high; + + fetch_ea_32(fetchdat); + ILLEGAL_ON(cpu_mod == 3); + SEG_CHECK_READ(cpu_state.ea_seg); + low = geteal(); + high = readmeml(easeg, cpu_state.eaaddr + 4); + if (cpu_state.abrt) + return 1; + + if (((int32_t) cpu_state.regs[cpu_reg].l < low) || ((int32_t) cpu_state.regs[cpu_reg].l > high)) { + x86_int(5); + return 1; + } + + CLOCK_CYCLES(is486 ? 7 : 10); + PREFETCH_RUN(is486 ? 7 : 10, 2, rmdat, 1, 1, 0, 0, 1); + return 0; +} + +static int +opCLTS(uint32_t fetchdat) +{ + if ((CPL || (cpu_state.eflags & VM_FLAG)) && (cr0 & 1)) { + x86gpf(NULL, 0); + return 1; + } + cr0 &= ~8; + CLOCK_CYCLES(5); + PREFETCH_RUN(5, 1, -1, 0, 0, 0, 0, 0); + return 0; +} + +static int +opINVD(uint32_t fetchdat) +{ + CLOCK_CYCLES(1000); + CPU_BLOCK_END(); + return 0; +} +static int +opWBINVD(uint32_t fetchdat) +{ + CLOCK_CYCLES(10000); + CPU_BLOCK_END(); + return 0; +} + +static int +opLOADALL(uint32_t fetchdat) +{ + if (CPL && (cr0 & 1)) { + x86gpf(NULL, 0); + return 1; + } + msw = (msw & 1) | readmemw(0, 0x806); + cpu_state.flags = (readmemw(0, 0x818) & 0xffd5) | 2; + flags_extract(); + tr.seg = readmemw(0, 0x816); + cpu_state.pc = readmemw(0, 0x81A); + ldt.seg = readmemw(0, 0x81C); + DS = readmemw(0, 0x81E); + SS = readmemw(0, 0x820); + CS = readmemw(0, 0x822); + ES = readmemw(0, 0x824); + DI = readmemw(0, 0x826); + SI = readmemw(0, 0x828); + BP = readmemw(0, 0x82A); + SP = readmemw(0, 0x82C); + BX = readmemw(0, 0x82E); + DX = readmemw(0, 0x830); + CX = readmemw(0, 0x832); + AX = readmemw(0, 0x834); + es = readmemw(0, 0x836) | (readmemb(0, 0x838) << 16); + cpu_state.seg_es.access = readmemb(0, 0x839); + cpu_state.seg_es.limit = readmemw(0, 0x83A); + cs = readmemw(0, 0x83C) | (readmemb(0, 0x83E) << 16); + cpu_state.seg_cs.access = readmemb(0, 0x83F); + cpu_state.seg_cs.limit = readmemw(0, 0x840); + ss = readmemw(0, 0x842) | (readmemb(0, 0x844) << 16); + cpu_state.seg_ss.access = readmemb(0, 0x845); + cpu_state.seg_ss.limit = readmemw(0, 0x846); + if (cpu_state.seg_ss.base == 0 && cpu_state.seg_ss.limit_low == 0 && cpu_state.seg_ss.limit_high == 0xffffffff) + cpu_cur_status &= ~CPU_STATUS_NOTFLATSS; + else + cpu_cur_status |= CPU_STATUS_NOTFLATSS; + ds = readmemw(0, 0x848) | (readmemb(0, 0x84A) << 16); + cpu_state.seg_ds.access = readmemb(0, 0x84B); + cpu_state.seg_ds.limit = readmemw(0, 0x84C); + if (cpu_state.seg_ds.base == 0 && cpu_state.seg_ds.limit_low == 0 && cpu_state.seg_ds.limit_high == 0xffffffff) + cpu_cur_status &= ~CPU_STATUS_NOTFLATDS; + else + cpu_cur_status |= CPU_STATUS_NOTFLATDS; + gdt.base = readmemw(0, 0x84E) | (readmemb(0, 0x850) << 16); + gdt.limit = readmemw(0, 0x852); + ldt.base = readmemw(0, 0x854) | (readmemb(0, 0x856) << 16); + ldt.access = readmemb(0, 0x857); + ldt.limit = readmemw(0, 0x858); + idt.base = readmemw(0, 0x85A) | (readmemb(0, 0x85C) << 16); + idt.limit = readmemw(0, 0x85E); + tr.base = readmemw(0, 0x860) | (readmemb(0, 0x862) << 16); + tr.access = readmemb(0, 0x863); + tr.limit = readmemw(0, 0x864); + CLOCK_CYCLES(195); + PREFETCH_RUN(195, 1, -1, 51, 0, 0, 0, 0); + return 0; +} + +static void +set_segment_limit(x86seg *s, uint8_t segdat3) +{ + if ((s->access & 0x18) != 0x10 || !(s->access & (1 << 2))) /*expand-down*/ + { + s->limit_high = s->limit; + s->limit_low = 0; + } else { + s->limit_high = (segdat3 & 0x40) ? 0xffffffff : 0xffff; + s->limit_low = s->limit + 1; + } +} + +static void +loadall_load_segment(uint32_t addr, x86seg *s) +{ + uint32_t attrib = readmeml(0, addr); + uint32_t segdat3 = (attrib >> 16) & 0xff; + s->access = (attrib >> 8) & 0xff; + s->ar_high = segdat3; + s->base = readmeml(0, addr + 4); + s->limit = readmeml(0, addr + 8); + + if (s == &cpu_state.seg_cs) + use32 = (segdat3 & 0x40) ? 0x300 : 0; + if (s == &cpu_state.seg_ss) + stack32 = (segdat3 & 0x40) ? 1 : 0; + + cpu_cur_status &= ~(CPU_STATUS_USE32 | CPU_STATUS_STACK32); + if (use32) + cpu_cur_status |= CPU_STATUS_USE32; + if (stack32) + cpu_cur_status |= CPU_STATUS_STACK32; + + set_segment_limit(s, segdat3); + + if (s == &cpu_state.seg_ds) { + if (s->base == 0 && s->limit_low == 0 && s->limit_high == 0xffffffff) + cpu_cur_status &= ~CPU_STATUS_NOTFLATDS; + else + cpu_cur_status |= CPU_STATUS_NOTFLATDS; + } + if (s == &cpu_state.seg_ss) { + if (s->base == 0 && s->limit_low == 0 && s->limit_high == 0xffffffff) + cpu_cur_status &= ~CPU_STATUS_NOTFLATSS; + else + cpu_cur_status |= CPU_STATUS_NOTFLATSS; + } +} + +static int +opLOADALL386(uint32_t fetchdat) +{ + uint32_t la_addr = es + EDI; + + cr0 = readmeml(0, la_addr); + cpu_state.flags = readmemw(0, la_addr + 4); + cpu_state.eflags = readmemw(0, la_addr + 6); + flags_extract(); + cpu_state.pc = readmeml(0, la_addr + 8); + EDI = readmeml(0, la_addr + 0xC); + ESI = readmeml(0, la_addr + 0x10); + EBP = readmeml(0, la_addr + 0x14); + ESP = readmeml(0, la_addr + 0x18); + EBX = readmeml(0, la_addr + 0x1C); + EDX = readmeml(0, la_addr + 0x20); + ECX = readmeml(0, la_addr + 0x24); + EAX = readmeml(0, la_addr + 0x28); + dr[6] = readmeml(0, la_addr + 0x2C); + dr[7] = readmeml(0, la_addr + 0x30); + tr.seg = readmemw(0, la_addr + 0x34); + ldt.seg = readmemw(0, la_addr + 0x38); + GS = readmemw(0, la_addr + 0x3C); + FS = readmemw(0, la_addr + 0x40); + DS = readmemw(0, la_addr + 0x44); + SS = readmemw(0, la_addr + 0x48); + CS = readmemw(0, la_addr + 0x4C); + ES = readmemw(0, la_addr + 0x50); + + loadall_load_segment(la_addr + 0x54, &tr); + loadall_load_segment(la_addr + 0x60, &idt); + loadall_load_segment(la_addr + 0x6c, &gdt); + loadall_load_segment(la_addr + 0x78, &ldt); + loadall_load_segment(la_addr + 0x84, &cpu_state.seg_gs); + loadall_load_segment(la_addr + 0x90, &cpu_state.seg_fs); + loadall_load_segment(la_addr + 0x9c, &cpu_state.seg_ds); + loadall_load_segment(la_addr + 0xa8, &cpu_state.seg_ss); + loadall_load_segment(la_addr + 0xb4, &cpu_state.seg_cs); + loadall_load_segment(la_addr + 0xc0, &cpu_state.seg_es); + + if (CPL == 3 && oldcpl != 3) + flushmmucache_nopc(); + oldcpl = CPL; + + CLOCK_CYCLES(350); + return 0; +} + +static int +opCPUID(uint32_t fetchdat) +{ + if (CPUID) { + cpu_CPUID(); + CLOCK_CYCLES(9); + return 0; + } + cpu_state.pc = cpu_state.oldpc; + x86illegal(); + return 1; +} + +static int +opRDMSR(uint32_t fetchdat) +{ + if (cpu_has_feature(CPU_FEATURE_MSR)) { + cpu_RDMSR(); + CLOCK_CYCLES(9); + return 0; + } + cpu_state.pc = cpu_state.oldpc; + x86illegal(); + return 1; +} + +static int +opWRMSR(uint32_t fetchdat) +{ + if (cpu_has_feature(CPU_FEATURE_MSR)) { + cpu_WRMSR(); + CLOCK_CYCLES(9); + return 0; + } + cpu_state.pc = cpu_state.oldpc; + x86illegal(); + return 1; +} + +static int +opRSM(uint32_t fetchdat) +{ + if (in_smm) { + leave_smm(); + if (smi_latched) + enter_smm(smm_in_hlt); CPU_BLOCK_END(); return 0; + } + cpu_state.pc = cpu_state.oldpc; + x86illegal(); + return 1; } -static int opWBINVD(uint32_t fetchdat) -{ - CLOCK_CYCLES(10000); - CPU_BLOCK_END(); - return 0; -} - -static int opLOADALL(uint32_t fetchdat) -{ - if (CPL && (cr0&1)) - { - x86gpf(NULL,0); - return 1; - } - msw = (msw & 1) | readmemw(0, 0x806); - cpu_state.flags = (readmemw(0, 0x818) & 0xffd5) | 2; - flags_extract(); - tr.seg = readmemw(0, 0x816); - cpu_state.pc = readmemw(0, 0x81A); - ldt.seg = readmemw(0, 0x81C); - DS = readmemw(0, 0x81E); - SS = readmemw(0, 0x820); - CS = readmemw(0, 0x822); - ES = readmemw(0, 0x824); - DI = readmemw(0, 0x826); - SI = readmemw(0, 0x828); - BP = readmemw(0, 0x82A); - SP = readmemw(0, 0x82C); - BX = readmemw(0, 0x82E); - DX = readmemw(0, 0x830); - CX = readmemw(0, 0x832); - AX = readmemw(0, 0x834); - es = readmemw(0, 0x836) | (readmemb(0, 0x838) << 16); - cpu_state.seg_es.access = readmemb(0, 0x839); - cpu_state.seg_es.limit = readmemw(0, 0x83A); - cs = readmemw(0, 0x83C) | (readmemb(0, 0x83E) << 16); - cpu_state.seg_cs.access = readmemb(0, 0x83F); - cpu_state.seg_cs.limit = readmemw(0, 0x840); - ss = readmemw(0, 0x842) | (readmemb(0, 0x844) << 16); - cpu_state.seg_ss.access = readmemb(0, 0x845); - cpu_state.seg_ss.limit = readmemw(0, 0x846); - if (cpu_state.seg_ss.base == 0 && cpu_state.seg_ss.limit_low == 0 && cpu_state.seg_ss.limit_high == 0xffffffff) - cpu_cur_status &= ~CPU_STATUS_NOTFLATSS; - else - cpu_cur_status |= CPU_STATUS_NOTFLATSS; - ds = readmemw(0, 0x848) | (readmemb(0, 0x84A) << 16); - cpu_state.seg_ds.access = readmemb(0, 0x84B); - cpu_state.seg_ds.limit = readmemw(0, 0x84C); - if (cpu_state.seg_ds.base == 0 && cpu_state.seg_ds.limit_low == 0 && cpu_state.seg_ds.limit_high == 0xffffffff) - cpu_cur_status &= ~CPU_STATUS_NOTFLATDS; - else - cpu_cur_status |= CPU_STATUS_NOTFLATDS; - gdt.base = readmemw(0, 0x84E) | (readmemb(0, 0x850) << 16); - gdt.limit = readmemw(0, 0x852); - ldt.base = readmemw(0, 0x854) | (readmemb(0, 0x856) << 16); - ldt.access = readmemb(0, 0x857); - ldt.limit = readmemw(0, 0x858); - idt.base = readmemw(0, 0x85A) | (readmemb(0, 0x85C) << 16); - idt.limit = readmemw(0, 0x85E); - tr.base = readmemw(0, 0x860) | (readmemb(0, 0x862) << 16); - tr.access = readmemb(0, 0x863); - tr.limit = readmemw(0, 0x864); - CLOCK_CYCLES(195); - PREFETCH_RUN(195, 1, -1, 51,0,0,0, 0); - return 0; -} - -static void set_segment_limit(x86seg *s, uint8_t segdat3) -{ - if ((s->access & 0x18) != 0x10 || !(s->access & (1 << 2))) /*expand-down*/ - { - s->limit_high = s->limit; - s->limit_low = 0; - } - else - { - s->limit_high = (segdat3 & 0x40) ? 0xffffffff : 0xffff; - s->limit_low = s->limit + 1; - } -} - -static void loadall_load_segment(uint32_t addr, x86seg *s) -{ - uint32_t attrib = readmeml(0, addr); - uint32_t segdat3 = (attrib >> 16) & 0xff; - s->access = (attrib >> 8) & 0xff; - s->ar_high = segdat3; - s->base = readmeml(0, addr + 4); - s->limit = readmeml(0, addr + 8); - - if (s == &cpu_state.seg_cs) - use32 = (segdat3 & 0x40) ? 0x300 : 0; - if (s == &cpu_state.seg_ss) - stack32 = (segdat3 & 0x40) ? 1 : 0; - - cpu_cur_status &= ~(CPU_STATUS_USE32 | CPU_STATUS_STACK32); - if (use32) - cpu_cur_status |= CPU_STATUS_USE32; - if (stack32) - cpu_cur_status |= CPU_STATUS_STACK32; - - set_segment_limit(s, segdat3); - - if (s == &cpu_state.seg_ds) - { - if (s->base == 0 && s->limit_low == 0 && s->limit_high == 0xffffffff) - cpu_cur_status &= ~CPU_STATUS_NOTFLATDS; - else - cpu_cur_status |= CPU_STATUS_NOTFLATDS; - } - if (s == &cpu_state.seg_ss) - { - if (s->base == 0 && s->limit_low == 0 && s->limit_high == 0xffffffff) - cpu_cur_status &= ~CPU_STATUS_NOTFLATSS; - else - cpu_cur_status |= CPU_STATUS_NOTFLATSS; - } -} - -static int opLOADALL386(uint32_t fetchdat) -{ - uint32_t la_addr = es + EDI; - - cr0 = readmeml(0, la_addr); - cpu_state.flags = readmemw(0, la_addr + 4); - cpu_state.eflags = readmemw(0, la_addr + 6); - flags_extract(); - cpu_state.pc = readmeml(0, la_addr + 8); - EDI = readmeml(0, la_addr + 0xC); - ESI = readmeml(0, la_addr + 0x10); - EBP = readmeml(0, la_addr + 0x14); - ESP = readmeml(0, la_addr + 0x18); - EBX = readmeml(0, la_addr + 0x1C); - EDX = readmeml(0, la_addr + 0x20); - ECX = readmeml(0, la_addr + 0x24); - EAX = readmeml(0, la_addr + 0x28); - dr[6] = readmeml(0, la_addr + 0x2C); - dr[7] = readmeml(0, la_addr + 0x30); - tr.seg = readmemw(0, la_addr + 0x34); - ldt.seg = readmemw(0, la_addr + 0x38); - GS = readmemw(0, la_addr + 0x3C); - FS = readmemw(0, la_addr + 0x40); - DS = readmemw(0, la_addr + 0x44); - SS = readmemw(0, la_addr + 0x48); - CS = readmemw(0, la_addr + 0x4C); - ES = readmemw(0, la_addr + 0x50); - - loadall_load_segment(la_addr + 0x54, &tr); - loadall_load_segment(la_addr + 0x60, &idt); - loadall_load_segment(la_addr + 0x6c, &gdt); - loadall_load_segment(la_addr + 0x78, &ldt); - loadall_load_segment(la_addr + 0x84, &cpu_state.seg_gs); - loadall_load_segment(la_addr + 0x90, &cpu_state.seg_fs); - loadall_load_segment(la_addr + 0x9c, &cpu_state.seg_ds); - loadall_load_segment(la_addr + 0xa8, &cpu_state.seg_ss); - loadall_load_segment(la_addr + 0xb4, &cpu_state.seg_cs); - loadall_load_segment(la_addr + 0xc0, &cpu_state.seg_es); - - if (CPL==3 && oldcpl!=3) flushmmucache_cr3(); - oldcpl = CPL; - - CLOCK_CYCLES(350); - return 0; -} - -static int opCPUID(uint32_t fetchdat) -{ - if (CPUID) - { - cpu_CPUID(); - CLOCK_CYCLES(9); - return 0; - } - cpu_state.pc = cpu_state.oldpc; - x86illegal(); - return 1; -} - -static int opRDMSR(uint32_t fetchdat) -{ - if (cpu_has_feature(CPU_FEATURE_MSR)) - { - cpu_RDMSR(); - CLOCK_CYCLES(9); - return 0; - } - cpu_state.pc = cpu_state.oldpc; - x86illegal(); - return 1; -} - -static int opWRMSR(uint32_t fetchdat) -{ - if (cpu_has_feature(CPU_FEATURE_MSR)) - { - cpu_WRMSR(); - CLOCK_CYCLES(9); - return 0; - } - cpu_state.pc = cpu_state.oldpc; - x86illegal(); - return 1; -} - -static int opRSM(uint32_t fetchdat) -{ - if (in_smm) - { - leave_smm(); - if (smi_latched) - enter_smm(smm_in_hlt); - CPU_BLOCK_END(); - return 0; - } - cpu_state.pc = cpu_state.oldpc; - x86illegal(); - return 1; -} \ No newline at end of file diff --git a/src/cpu/x86_ops_mmx.c b/src/cpu/x86_ops_mmx.c new file mode 100644 index 000000000..f26c903f9 --- /dev/null +++ b/src/cpu/x86_ops_mmx.c @@ -0,0 +1,51 @@ +#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 "x86seg_common.h" +#include "x86seg.h" +#include "386_common.h" +#include "x86_flags.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 f9a7f9357..ab5e19762 100644 --- a/src/cpu/x86_ops_mmx.h +++ b/src/cpu/x86_ops_mmx.h @@ -1,49 +1,51 @@ -#define SSATB(val) (((val) < -128) ? -128 : (((val) > 127) ? 127 : (val))) -#define SSATW(val) (((val) < -32768) ? -32768 : (((val) > 32767) ? 32767 : (val))) -#define USATB(val) (((val) < 0) ? 0 : (((val) > 255) ? 255 : (val))) -#define USATW(val) (((val) < 0) ? 0 : (((val) > 65535) ? 65535 : (val))) +#define SSATB(val) (((val) < -128) ? -128 : (((val) > 127) ? 127 : (val))) +#define SSATW(val) (((val) < -32768) ? -32768 : (((val) > 32767) ? 32767 : (val))) +#define USATB(val) (((val) < 0) ? 0 : (((val) > 255) ? 255 : (val))) +#define USATW(val) (((val) < 0) ? 0 : (((val) > 65535) ? 65535 : (val))) -#define MMX_GETSRC() \ - if (cpu_mod == 3) \ - { \ - src = cpu_state.MM[cpu_rm]; \ - CLOCK_CYCLES(1); \ - } \ - else \ - { \ - SEG_CHECK_READ(cpu_state.ea_seg); \ - src.q = readmemq(easeg, cpu_state.eaaddr); if (cpu_state.abrt) return 1; \ - CLOCK_CYCLES(2); \ - } +#define MMX_GETREGP(r) MMP[r] +#define MMX_GETREG(r) *(MMP[r]) -#define MMX_ENTER() \ - if (!cpu_has_feature(CPU_FEATURE_MMX)) \ - { \ - cpu_state.pc = cpu_state.oldpc; \ - x86illegal(); \ - return 1; \ - } \ - if (cr0 & 0xc) \ - { \ - x86_int(7); \ - return 1; \ - } \ - x87_set_mmx() +#define MMX_SETEXP(r) \ + *(MMEP[r]) = 0xffff -static int opEMMS(uint32_t fetchdat) +#define MMX_GETSRC() \ + if (cpu_mod == 3) { \ + src = MMX_GETREG(cpu_rm); \ + CLOCK_CYCLES(1); \ + } else { \ + SEG_CHECK_READ(cpu_state.ea_seg); \ + src.q = readmemq(easeg, cpu_state.eaaddr); \ + if (cpu_state.abrt) \ + return 1; \ + CLOCK_CYCLES(2); \ + } + +#define MMX_ENTER() \ + if (!cpu_has_feature(CPU_FEATURE_MMX)) { \ + cpu_state.pc = cpu_state.oldpc; \ + x86illegal(); \ + return 1; \ + } \ + if (cr0 & 0xc) { \ + x86_int(7); \ + return 1; \ + } \ + x87_set_mmx() + +static int +opEMMS(uint32_t fetchdat) { - if (!cpu_has_feature(CPU_FEATURE_MMX)) - { - cpu_state.pc = cpu_state.oldpc; - x86illegal(); - return 1; - } - if (cr0 & 0xc) - { - x86_int(7); - return 1; - } - x87_emms(); - CLOCK_CYCLES(100); /*Guess*/ - return 0; + if (!cpu_has_feature(CPU_FEATURE_MMX)) { + cpu_state.pc = cpu_state.oldpc; + x86illegal(); + return 1; + } + if (cr0 & 0xc) { + x86_int(7); + return 1; + } + x87_emms(); + CLOCK_CYCLES(100); /*Guess*/ + return 0; } diff --git a/src/cpu/x86_ops_mmx_arith.h b/src/cpu/x86_ops_mmx_arith.h index 3b9e2066c..099789970 100644 --- a/src/cpu/x86_ops_mmx_arith.h +++ b/src/cpu/x86_ops_mmx_arith.h @@ -1,631 +1,850 @@ -static int opPADDB_a16(uint32_t fetchdat) +static int +opPADDB_a16(uint32_t fetchdat) { - MMX_REG src; - MMX_ENTER(); - - fetch_ea_16(fetchdat); - 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]; + MMX_REG src; + MMX_REG *dst; + MMX_ENTER(); - return 0; + fetch_ea_16(fetchdat); + + dst = MMX_GETREGP(cpu_reg); + + MMX_GETSRC(); + + 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; } -static int opPADDB_a32(uint32_t fetchdat) +static int +opPADDB_a32(uint32_t fetchdat) { - MMX_REG src; - MMX_ENTER(); - - fetch_ea_32(fetchdat); - 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]; + MMX_REG src; + MMX_REG *dst; + MMX_ENTER(); - return 0; + fetch_ea_32(fetchdat); + + dst = MMX_GETREGP(cpu_reg); + + MMX_GETSRC(); + + 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; } -static int opPADDW_a16(uint32_t fetchdat) +static int +opPADDW_a16(uint32_t fetchdat) { - MMX_REG src; - MMX_ENTER(); - - fetch_ea_16(fetchdat); - 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]; + MMX_REG src; + MMX_REG *dst; + MMX_ENTER(); - return 0; + fetch_ea_16(fetchdat); + + dst = MMX_GETREGP(cpu_reg); + + MMX_GETSRC(); + + 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; } -static int opPADDW_a32(uint32_t fetchdat) +static int +opPADDW_a32(uint32_t fetchdat) { - MMX_REG src; - MMX_ENTER(); - - fetch_ea_32(fetchdat); - 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]; + MMX_REG src; + MMX_REG *dst; + MMX_ENTER(); - return 0; + fetch_ea_32(fetchdat); + + dst = MMX_GETREGP(cpu_reg); + + MMX_GETSRC(); + + 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; } -static int opPADDD_a16(uint32_t fetchdat) +static int +opPADDD_a16(uint32_t fetchdat) { - MMX_REG src; - MMX_ENTER(); - - fetch_ea_16(fetchdat); - MMX_GETSRC(); - - cpu_state.MM[cpu_reg].l[0] += src.l[0]; - cpu_state.MM[cpu_reg].l[1] += src.l[1]; + MMX_REG src; + MMX_REG *dst; + MMX_ENTER(); - return 0; + fetch_ea_16(fetchdat); + + dst = MMX_GETREGP(cpu_reg); + + MMX_GETSRC(); + + dst->l[0] += src.l[0]; + dst->l[1] += src.l[1]; + + MMX_SETEXP(cpu_reg); + + return 0; } -static int opPADDD_a32(uint32_t fetchdat) +static int +opPADDD_a32(uint32_t fetchdat) { - MMX_REG src; - MMX_ENTER(); - - fetch_ea_32(fetchdat); - MMX_GETSRC(); + MMX_REG src; + MMX_REG *dst; + MMX_ENTER(); - cpu_state.MM[cpu_reg].l[0] += src.l[0]; - cpu_state.MM[cpu_reg].l[1] += src.l[1]; + fetch_ea_32(fetchdat); - return 0; + dst = MMX_GETREGP(cpu_reg); + + MMX_GETSRC(); + + dst->l[0] += src.l[0]; + dst->l[1] += src.l[1]; + + MMX_SETEXP(cpu_reg); + + return 0; } -static int opPADDSB_a16(uint32_t fetchdat) +static int +opPADDSB_a16(uint32_t fetchdat) { - MMX_REG src; - MMX_ENTER(); - - fetch_ea_16(fetchdat); - 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]); + MMX_REG src; + MMX_REG *dst; + MMX_ENTER(); - return 0; + fetch_ea_16(fetchdat); + + dst = MMX_GETREGP(cpu_reg); + + MMX_GETSRC(); + + 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; } -static int opPADDSB_a32(uint32_t fetchdat) +static int +opPADDSB_a32(uint32_t fetchdat) { - MMX_REG src; - MMX_ENTER(); - - fetch_ea_32(fetchdat); - MMX_GETSRC(); + MMX_REG src; + MMX_REG *dst; + MMX_ENTER(); - 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]); + fetch_ea_32(fetchdat); - return 0; + dst = MMX_GETREGP(cpu_reg); + + MMX_GETSRC(); + + 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; } -static int opPADDUSB_a16(uint32_t fetchdat) +static int +opPADDUSB_a16(uint32_t fetchdat) { - MMX_REG src; - MMX_ENTER(); - - fetch_ea_16(fetchdat); - 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]); + MMX_REG src; + MMX_REG *dst; + MMX_ENTER(); - return 0; + fetch_ea_16(fetchdat); + + dst = MMX_GETREGP(cpu_reg); + + MMX_GETSRC(); + + 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; } -static int opPADDUSB_a32(uint32_t fetchdat) +static int +opPADDUSB_a32(uint32_t fetchdat) { - MMX_REG src; - MMX_ENTER(); - - fetch_ea_32(fetchdat); - 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]); + MMX_REG src; + MMX_REG *dst; + MMX_ENTER(); - return 0; + fetch_ea_32(fetchdat); + + dst = MMX_GETREGP(cpu_reg); + + MMX_GETSRC(); + + 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; } -static int opPADDSW_a16(uint32_t fetchdat) +static int +opPADDSW_a16(uint32_t fetchdat) { - MMX_REG src; - MMX_ENTER(); - - fetch_ea_16(fetchdat); - 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]); + MMX_REG src; + MMX_REG *dst; + MMX_ENTER(); - return 0; + fetch_ea_16(fetchdat); + + dst = MMX_GETREGP(cpu_reg); + + MMX_GETSRC(); + + 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; } -static int opPADDSW_a32(uint32_t fetchdat) +static int +opPADDSW_a32(uint32_t fetchdat) { - MMX_REG src; - MMX_ENTER(); - - fetch_ea_32(fetchdat); - MMX_GETSRC(); + MMX_REG src; + MMX_REG *dst; + MMX_ENTER(); - 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]); + fetch_ea_32(fetchdat); - return 0; + dst = MMX_GETREGP(cpu_reg); + + MMX_GETSRC(); + + 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; } -static int opPADDUSW_a16(uint32_t fetchdat) +static int +opPADDUSW_a16(uint32_t fetchdat) { - MMX_REG src; - MMX_ENTER(); - - fetch_ea_16(fetchdat); - 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]); + MMX_REG src; + MMX_REG *dst; + MMX_ENTER(); - return 0; + fetch_ea_16(fetchdat); + + dst = MMX_GETREGP(cpu_reg); + + MMX_GETSRC(); + + 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; } -static int opPADDUSW_a32(uint32_t fetchdat) +static int +opPADDUSW_a32(uint32_t fetchdat) { - MMX_REG src; - MMX_ENTER(); - - fetch_ea_32(fetchdat); - 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]); + MMX_REG src; + MMX_REG *dst; + MMX_ENTER(); - return 0; + fetch_ea_32(fetchdat); + + dst = MMX_GETREGP(cpu_reg); + + MMX_GETSRC(); + + 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; } -static int opPMADDWD_a16(uint32_t fetchdat) +static int +opPMADDWD_a16(uint32_t fetchdat) { - MMX_REG src; - MMX_ENTER(); - - fetch_ea_16(fetchdat); - MMX_GETSRC(); + MMX_REG src; + MMX_REG *dst; + MMX_ENTER(); - if (cpu_state.MM[cpu_reg].l[0] == 0x80008000 && src.l[0] == 0x80008000) - cpu_state.MM[cpu_reg].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]); + fetch_ea_16(fetchdat); - if (cpu_state.MM[cpu_reg].l[1] == 0x80008000 && src.l[1] == 0x80008000) - cpu_state.MM[cpu_reg].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]); - - return 0; + dst = MMX_GETREGP(cpu_reg); + + MMX_GETSRC(); + + if (dst->l[0] == 0x80008000 && src.l[0] == 0x80008000) + dst->l[0] = 0x80000000; + else + dst->sl[0] = ((int32_t) dst->sw[0] * (int32_t) src.sw[0]) + ((int32_t) dst->sw[1] * (int32_t) src.sw[1]); + + if (dst->l[1] == 0x80008000 && src.l[1] == 0x80008000) + dst->l[1] = 0x80000000; + else + 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; } -static int opPMADDWD_a32(uint32_t fetchdat) +static int +opPMADDWD_a32(uint32_t fetchdat) { - MMX_REG src; - MMX_ENTER(); - - fetch_ea_32(fetchdat); - MMX_GETSRC(); + MMX_REG src; + MMX_REG *dst; + MMX_ENTER(); - if (cpu_state.MM[cpu_reg].l[0] == 0x80008000 && src.l[0] == 0x80008000) - cpu_state.MM[cpu_reg].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]); + fetch_ea_32(fetchdat); - if (cpu_state.MM[cpu_reg].l[1] == 0x80008000 && src.l[1] == 0x80008000) - cpu_state.MM[cpu_reg].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]); - - return 0; + dst = MMX_GETREGP(cpu_reg); + + MMX_GETSRC(); + + if (dst->l[0] == 0x80008000 && src.l[0] == 0x80008000) + dst->l[0] = 0x80000000; + else + dst->sl[0] = ((int32_t) dst->sw[0] * (int32_t) src.sw[0]) + ((int32_t) dst->sw[1] * (int32_t) src.sw[1]); + + if (dst->l[1] == 0x80008000 && src.l[1] == 0x80008000) + dst->l[1] = 0x80000000; + else + 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; } - -static int opPMULLW_a16(uint32_t fetchdat) +static int +opPMULLW_a16(uint32_t fetchdat) { - 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; + MMX_REG src; + MMX_REG *dst; + MMX_ENTER(); - 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); - } - return 0; + fetch_ea_16(fetchdat); + + 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; + 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) +static int +opPMULLW_a32(uint32_t fetchdat) { - 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; - - 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); - } - return 0; + MMX_REG src; + MMX_REG *dst; + MMX_ENTER(); + + fetch_ea_32(fetchdat); + + 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; + 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) +static int +opPMULHW_a16(uint32_t fetchdat) { - 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; - - 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); - } - return 0; + MMX_REG src; + MMX_REG *dst; + MMX_ENTER(); + + fetch_ea_16(fetchdat); + + 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; + 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) +static int +opPMULHW_a32(uint32_t fetchdat) { - 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; - - 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); - } - return 0; + MMX_REG src; + MMX_REG *dst; + MMX_ENTER(); + + fetch_ea_32(fetchdat); + + 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; + 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 opPSUBB_a16(uint32_t fetchdat) +static int +opPSUBB_a16(uint32_t fetchdat) { - MMX_REG src; - MMX_ENTER(); - - fetch_ea_16(fetchdat); - 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]; + MMX_REG src; + MMX_REG *dst; + MMX_ENTER(); - return 0; + fetch_ea_16(fetchdat); + + dst = MMX_GETREGP(cpu_reg); + + MMX_GETSRC(); + + 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; } -static int opPSUBB_a32(uint32_t fetchdat) +static int +opPSUBB_a32(uint32_t fetchdat) { - MMX_REG src; - MMX_ENTER(); - - fetch_ea_32(fetchdat); - 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]; + MMX_REG src; + MMX_REG *dst; + MMX_ENTER(); - return 0; + fetch_ea_32(fetchdat); + + dst = MMX_GETREGP(cpu_reg); + + MMX_GETSRC(); + + 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; } -static int opPSUBW_a16(uint32_t fetchdat) +static int +opPSUBW_a16(uint32_t fetchdat) { - MMX_REG src; - MMX_ENTER(); - - fetch_ea_16(fetchdat); - 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]; + MMX_REG src; + MMX_REG *dst; + MMX_ENTER(); - return 0; + fetch_ea_16(fetchdat); + + dst = MMX_GETREGP(cpu_reg); + + MMX_GETSRC(); + + 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; } -static int opPSUBW_a32(uint32_t fetchdat) +static int +opPSUBW_a32(uint32_t fetchdat) { - MMX_REG src; - MMX_ENTER(); - - fetch_ea_32(fetchdat); - 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]; + MMX_REG src; + MMX_REG *dst; + MMX_ENTER(); - return 0; + fetch_ea_32(fetchdat); + + dst = MMX_GETREGP(cpu_reg); + + MMX_GETSRC(); + + 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; } -static int opPSUBD_a16(uint32_t fetchdat) +static int +opPSUBD_a16(uint32_t fetchdat) { - MMX_REG src; - MMX_ENTER(); - - fetch_ea_16(fetchdat); - MMX_GETSRC(); - - cpu_state.MM[cpu_reg].l[0] -= src.l[0]; - cpu_state.MM[cpu_reg].l[1] -= src.l[1]; + MMX_REG src; + MMX_REG *dst; + MMX_ENTER(); - return 0; + fetch_ea_16(fetchdat); + + dst = MMX_GETREGP(cpu_reg); + + MMX_GETSRC(); + + dst->l[0] -= src.l[0]; + dst->l[1] -= src.l[1]; + + MMX_SETEXP(cpu_reg); + + return 0; } -static int opPSUBD_a32(uint32_t fetchdat) +static int +opPSUBD_a32(uint32_t fetchdat) { - MMX_REG src; - MMX_ENTER(); - - fetch_ea_32(fetchdat); - MMX_GETSRC(); - - cpu_state.MM[cpu_reg].l[0] -= src.l[0]; - cpu_state.MM[cpu_reg].l[1] -= src.l[1]; + MMX_REG src; + MMX_REG *dst; + MMX_ENTER(); - return 0; + fetch_ea_32(fetchdat); + + dst = MMX_GETREGP(cpu_reg); + + MMX_GETSRC(); + + dst->l[0] -= src.l[0]; + dst->l[1] -= src.l[1]; + + MMX_SETEXP(cpu_reg); + + return 0; } -static int opPSUBSB_a16(uint32_t fetchdat) +static int +opPSUBSB_a16(uint32_t fetchdat) { - MMX_REG src; - pclog("opPSUBSB_a16(%08X)\n", fetchdat); - MMX_ENTER(); - - fetch_ea_16(fetchdat); - 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]); + MMX_REG src; + MMX_REG *dst; + MMX_ENTER(); - return 0; + fetch_ea_16(fetchdat); + + dst = MMX_GETREGP(cpu_reg); + + MMX_GETSRC(); + + 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; } -static int opPSUBSB_a32(uint32_t fetchdat) +static int +opPSUBSB_a32(uint32_t fetchdat) { - MMX_REG src; - pclog("opPSUBSB_a32(%08X)\n", fetchdat); - MMX_ENTER(); - - fetch_ea_32(fetchdat); - 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]); + MMX_REG src; + MMX_REG *dst; + MMX_ENTER(); - return 0; + fetch_ea_32(fetchdat); + + dst = MMX_GETREGP(cpu_reg); + + MMX_GETSRC(); + + 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; } -static int opPSUBUSB_a16(uint32_t fetchdat) +static int +opPSUBUSB_a16(uint32_t fetchdat) { - MMX_REG src; - MMX_ENTER(); - - fetch_ea_16(fetchdat); - 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]); + MMX_REG src; + MMX_REG *dst; + MMX_ENTER(); - return 0; + fetch_ea_16(fetchdat); + + dst = MMX_GETREGP(cpu_reg); + + MMX_GETSRC(); + + 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; } -static int opPSUBUSB_a32(uint32_t fetchdat) +static int +opPSUBUSB_a32(uint32_t fetchdat) { - MMX_REG src; - MMX_ENTER(); - - fetch_ea_32(fetchdat); - 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]); + MMX_REG src; + MMX_REG *dst; + MMX_ENTER(); - return 0; + fetch_ea_32(fetchdat); + + dst = MMX_GETREGP(cpu_reg); + + MMX_GETSRC(); + + 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; } -static int opPSUBSW_a16(uint32_t fetchdat) +static int +opPSUBSW_a16(uint32_t fetchdat) { - MMX_REG src; - MMX_ENTER(); - - fetch_ea_16(fetchdat); - 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]); + MMX_REG src; + MMX_REG *dst; + MMX_ENTER(); - return 0; + fetch_ea_16(fetchdat); + + dst = MMX_GETREGP(cpu_reg); + + MMX_GETSRC(); + + 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; } -static int opPSUBSW_a32(uint32_t fetchdat) +static int +opPSUBSW_a32(uint32_t fetchdat) { - MMX_REG src; - MMX_ENTER(); - - fetch_ea_32(fetchdat); - 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]); + MMX_REG src; + MMX_REG *dst; + MMX_ENTER(); - return 0; + fetch_ea_32(fetchdat); + + dst = MMX_GETREGP(cpu_reg); + + MMX_GETSRC(); + + 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; } -static int opPSUBUSW_a16(uint32_t fetchdat) +static int +opPSUBUSW_a16(uint32_t fetchdat) { - MMX_REG src; - MMX_ENTER(); - - fetch_ea_16(fetchdat); - 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]); + MMX_REG src; + MMX_REG *dst; + MMX_ENTER(); - return 0; + fetch_ea_16(fetchdat); + + dst = MMX_GETREGP(cpu_reg); + + MMX_GETSRC(); + + 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; } -static int opPSUBUSW_a32(uint32_t fetchdat) +static int +opPSUBUSW_a32(uint32_t fetchdat) { - MMX_REG src; - MMX_ENTER(); - - fetch_ea_32(fetchdat); - 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]); + MMX_REG src; + MMX_REG *dst; + MMX_ENTER(); - return 0; + fetch_ea_32(fetchdat); + + dst = MMX_GETREGP(cpu_reg); + + MMX_GETSRC(); + + 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 0fee95923..141dba6bc 100644 --- a/src/cpu/x86_ops_mmx_cmp.h +++ b/src/cpu/x86_ops_mmx_cmp.h @@ -1,205 +1,277 @@ -static int opPCMPEQB_a16(uint32_t fetchdat) +static int +opPCMPEQB_a16(uint32_t fetchdat) { - MMX_REG src; - - MMX_ENTER(); - - fetch_ea_16(fetchdat); - MMX_GETSRC(); + MMX_REG src; + MMX_REG *dst; + MMX_ENTER(); - 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; - - return 0; + fetch_ea_16(fetchdat); + + dst = MMX_GETREGP(cpu_reg); + + MMX_GETSRC(); + + 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; } -static int opPCMPEQB_a32(uint32_t fetchdat) +static int +opPCMPEQB_a32(uint32_t fetchdat) { - MMX_REG src; - - MMX_ENTER(); - - fetch_ea_32(fetchdat); - MMX_GETSRC(); + MMX_REG src; + MMX_REG *dst; + MMX_ENTER(); - 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; - - return 0; + fetch_ea_32(fetchdat); + + dst = MMX_GETREGP(cpu_reg); + + MMX_GETSRC(); + + 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; } -static int opPCMPGTB_a16(uint32_t fetchdat) +static int +opPCMPGTB_a16(uint32_t fetchdat) { - MMX_REG src; - - MMX_ENTER(); - - fetch_ea_16(fetchdat); - MMX_GETSRC(); + MMX_REG src; + MMX_REG *dst; + MMX_ENTER(); - 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; - - return 0; + fetch_ea_16(fetchdat); + + dst = MMX_GETREGP(cpu_reg); + + MMX_GETSRC(); + + 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; } -static int opPCMPGTB_a32(uint32_t fetchdat) +static int +opPCMPGTB_a32(uint32_t fetchdat) { - MMX_REG src; - - MMX_ENTER(); - - fetch_ea_32(fetchdat); - MMX_GETSRC(); + MMX_REG src; + MMX_REG *dst; + MMX_ENTER(); - 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; - - return 0; + fetch_ea_32(fetchdat); + + dst = MMX_GETREGP(cpu_reg); + + MMX_GETSRC(); + + 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; } -static int opPCMPEQW_a16(uint32_t fetchdat) +static int +opPCMPEQW_a16(uint32_t fetchdat) { - MMX_REG src; - - MMX_ENTER(); - - fetch_ea_16(fetchdat); - MMX_GETSRC(); + MMX_REG src; + MMX_REG *dst; + MMX_ENTER(); - 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; - - return 0; + fetch_ea_16(fetchdat); + + dst = MMX_GETREGP(cpu_reg); + + MMX_GETSRC(); + + 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; } -static int opPCMPEQW_a32(uint32_t fetchdat) +static int +opPCMPEQW_a32(uint32_t fetchdat) { - MMX_REG src; - - MMX_ENTER(); - - fetch_ea_32(fetchdat); - MMX_GETSRC(); + MMX_REG src; + MMX_REG *dst; + MMX_ENTER(); - 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; - - return 0; + fetch_ea_32(fetchdat); + + dst = MMX_GETREGP(cpu_reg); + + MMX_GETSRC(); + + 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; } -static int opPCMPGTW_a16(uint32_t fetchdat) +static int +opPCMPGTW_a16(uint32_t fetchdat) { - MMX_REG src; - - MMX_ENTER(); - - fetch_ea_16(fetchdat); - MMX_GETSRC(); + MMX_REG src; + MMX_REG *dst; + MMX_ENTER(); - 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; - - return 0; + fetch_ea_16(fetchdat); + + dst = MMX_GETREGP(cpu_reg); + + MMX_GETSRC(); + + 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; } -static int opPCMPGTW_a32(uint32_t fetchdat) +static int +opPCMPGTW_a32(uint32_t fetchdat) { - MMX_REG src; - - MMX_ENTER(); - - fetch_ea_32(fetchdat); - MMX_GETSRC(); + MMX_REG src; + MMX_REG *dst; + MMX_ENTER(); - 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; - - return 0; + fetch_ea_32(fetchdat); + + dst = MMX_GETREGP(cpu_reg); + + MMX_GETSRC(); + + 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; } -static int opPCMPEQD_a16(uint32_t fetchdat) +static int +opPCMPEQD_a16(uint32_t fetchdat) { - MMX_REG src; - - MMX_ENTER(); - - fetch_ea_16(fetchdat); - MMX_GETSRC(); + MMX_REG src; + MMX_REG *dst; + MMX_ENTER(); - 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; - - return 0; + fetch_ea_16(fetchdat); + + dst = MMX_GETREGP(cpu_reg); + + MMX_GETSRC(); + + 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; } -static int opPCMPEQD_a32(uint32_t fetchdat) +static int +opPCMPEQD_a32(uint32_t fetchdat) { - MMX_REG src; - - MMX_ENTER(); - - fetch_ea_32(fetchdat); - MMX_GETSRC(); + MMX_REG src; + MMX_REG *dst; + MMX_ENTER(); - 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; - - return 0; + fetch_ea_32(fetchdat); + + dst = MMX_GETREGP(cpu_reg); + + MMX_GETSRC(); + + 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; } -static int opPCMPGTD_a16(uint32_t fetchdat) +static int +opPCMPGTD_a16(uint32_t fetchdat) { - MMX_REG src; - - MMX_ENTER(); - - fetch_ea_16(fetchdat); - MMX_GETSRC(); + MMX_REG src; + MMX_REG *dst; + MMX_ENTER(); - 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; - - return 0; + fetch_ea_16(fetchdat); + + dst = MMX_GETREGP(cpu_reg); + + MMX_GETSRC(); + + 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; } -static int opPCMPGTD_a32(uint32_t fetchdat) +static int +opPCMPGTD_a32(uint32_t fetchdat) { - MMX_REG src; - - MMX_ENTER(); - - fetch_ea_32(fetchdat); - MMX_GETSRC(); + MMX_REG src; + MMX_REG *dst; + MMX_ENTER(); - 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; - - return 0; + fetch_ea_32(fetchdat); + + dst = MMX_GETREGP(cpu_reg); + + MMX_GETSRC(); + + 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 be5132e85..617219845 100644 --- a/src/cpu/x86_ops_mmx_logic.h +++ b/src/cpu/x86_ops_mmx_logic.h @@ -1,91 +1,155 @@ -static int opPAND_a16(uint32_t fetchdat) +static int +opPAND_a16(uint32_t fetchdat) { - MMX_REG src; - MMX_ENTER(); - - fetch_ea_16(fetchdat); - MMX_GETSRC(); - - cpu_state.MM[cpu_reg].q &= src.q; - return 0; + MMX_REG src; + MMX_REG *dst; + MMX_ENTER(); + + fetch_ea_16(fetchdat); + + dst = MMX_GETREGP(cpu_reg); + + MMX_GETSRC(); + + dst->q &= src.q; + + MMX_SETEXP(cpu_reg); + + return 0; } -static int opPAND_a32(uint32_t fetchdat) +static int +opPAND_a32(uint32_t fetchdat) { - MMX_REG src; - MMX_ENTER(); - - fetch_ea_32(fetchdat); - MMX_GETSRC(); - - cpu_state.MM[cpu_reg].q &= src.q; - return 0; + MMX_REG src; + MMX_REG *dst; + MMX_ENTER(); + + fetch_ea_32(fetchdat); + + dst = MMX_GETREGP(cpu_reg); + + MMX_GETSRC(); + + dst->q &= src.q; + + MMX_SETEXP(cpu_reg); + + return 0; } -static int opPANDN_a16(uint32_t fetchdat) +static int +opPANDN_a16(uint32_t fetchdat) { - MMX_REG src; - MMX_ENTER(); - - fetch_ea_16(fetchdat); - MMX_GETSRC(); - - cpu_state.MM[cpu_reg].q = ~cpu_state.MM[cpu_reg].q & src.q; - return 0; + MMX_REG src; + MMX_REG *dst; + MMX_ENTER(); + + fetch_ea_16(fetchdat); + + dst = MMX_GETREGP(cpu_reg); + + MMX_GETSRC(); + + dst->q = ~dst->q & src.q; + + MMX_SETEXP(cpu_reg); + + return 0; } -static int opPANDN_a32(uint32_t fetchdat) +static int +opPANDN_a32(uint32_t fetchdat) { - MMX_REG src; - MMX_ENTER(); - - fetch_ea_32(fetchdat); - MMX_GETSRC(); - - cpu_state.MM[cpu_reg].q = ~cpu_state.MM[cpu_reg].q & src.q; - return 0; + MMX_REG src; + MMX_REG *dst; + MMX_ENTER(); + + fetch_ea_32(fetchdat); + + dst = MMX_GETREGP(cpu_reg); + + MMX_GETSRC(); + + dst->q = ~dst->q & src.q; + + MMX_SETEXP(cpu_reg); + + return 0; } -static int opPOR_a16(uint32_t fetchdat) +static int +opPOR_a16(uint32_t fetchdat) { - MMX_REG src; - MMX_ENTER(); - - fetch_ea_16(fetchdat); - MMX_GETSRC(); - - cpu_state.MM[cpu_reg].q |= src.q; - return 0; + MMX_REG src; + MMX_REG *dst; + MMX_ENTER(); + + fetch_ea_16(fetchdat); + + dst = MMX_GETREGP(cpu_reg); + + MMX_GETSRC(); + + dst->q |= src.q; + + MMX_SETEXP(cpu_reg); + + return 0; } -static int opPOR_a32(uint32_t fetchdat) +static int +opPOR_a32(uint32_t fetchdat) { - MMX_REG src; - MMX_ENTER(); - - fetch_ea_32(fetchdat); - MMX_GETSRC(); - - cpu_state.MM[cpu_reg].q |= src.q; - return 0; + MMX_REG src; + MMX_REG *dst; + MMX_ENTER(); + + fetch_ea_32(fetchdat); + + dst = MMX_GETREGP(cpu_reg); + + MMX_GETSRC(); + + dst->q |= src.q; + + MMX_SETEXP(cpu_reg); + + return 0; } -static int opPXOR_a16(uint32_t fetchdat) +static int +opPXOR_a16(uint32_t fetchdat) { - MMX_REG src; - MMX_ENTER(); - - fetch_ea_16(fetchdat); - MMX_GETSRC(); - - cpu_state.MM[cpu_reg].q ^= src.q; - return 0; + MMX_REG src; + MMX_REG *dst; + MMX_ENTER(); + + fetch_ea_16(fetchdat); + + dst = MMX_GETREGP(cpu_reg); + + MMX_GETSRC(); + + dst->q ^= src.q; + + MMX_SETEXP(cpu_reg); + + return 0; } -static int opPXOR_a32(uint32_t fetchdat) +static int +opPXOR_a32(uint32_t fetchdat) { - MMX_REG src; - MMX_ENTER(); - - fetch_ea_32(fetchdat); - MMX_GETSRC(); - - cpu_state.MM[cpu_reg].q ^= src.q; - return 0; + MMX_REG src; + MMX_REG *dst; + MMX_ENTER(); + + fetch_ea_32(fetchdat); + + dst = MMX_GETREGP(cpu_reg); + + MMX_GETSRC(); + + 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 07d21d418..c72c8143d 100644 --- a/src/cpu/x86_ops_mmx_mov.h +++ b/src/cpu/x86_ops_mmx_mov.h @@ -1,217 +1,295 @@ -static int opMOVD_l_mm_a16(uint32_t fetchdat) +static int +opMOVD_l_mm_a16(uint32_t fetchdat) { - MMX_ENTER(); - - fetch_ea_16(fetchdat); - 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; - CLOCK_CYCLES(1); - } - else - { - uint32_t dst; + uint32_t dst; + MMX_REG *op; + MMX_ENTER(); - 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; + fetch_ea_16(fetchdat); - CLOCK_CYCLES(2); - } - return 0; + op = MMX_GETREGP(cpu_reg); + + if (cpu_mod == 3) { + op->l[0] = cpu_state.regs[cpu_rm].l; + op->l[1] = 0; + CLOCK_CYCLES(1); + } else { + SEG_CHECK_READ(cpu_state.ea_seg); + dst = readmeml(easeg, cpu_state.eaaddr); + if (cpu_state.abrt) + return 1; + + 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) +static int +opMOVD_l_mm_a32(uint32_t fetchdat) { - MMX_ENTER(); - - fetch_ea_32(fetchdat); - 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; - CLOCK_CYCLES(1); - } - else - { - uint32_t dst; + uint32_t dst; + MMX_REG *op; + MMX_ENTER(); - 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; + fetch_ea_32(fetchdat); - CLOCK_CYCLES(2); - } - return 0; + op = MMX_GETREGP(cpu_reg); + + if (cpu_mod == 3) { + op->l[0] = cpu_state.regs[cpu_rm].l; + op->l[1] = 0; + CLOCK_CYCLES(1); + } else { + SEG_CHECK_READ(cpu_state.ea_seg); + dst = readmeml(easeg, cpu_state.eaaddr); + if (cpu_state.abrt) + return 1; + + 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) +static int +opMOVD_mm_l_a16(uint32_t fetchdat) { - MMX_ENTER(); + MMX_REG *op; + MMX_ENTER(); - fetch_ea_16(fetchdat); - if (cpu_mod == 3) - { - cpu_state.regs[cpu_rm].l = cpu_state.MM[cpu_reg].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]); if (cpu_state.abrt) return 1; - CLOCK_CYCLES(2); - } - return 0; + fetch_ea_16(fetchdat); + + op = MMX_GETREGP(cpu_reg); + + if (cpu_mod == 3) { + 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, op->l[0]); + if (cpu_state.abrt) + return 1; + + CLOCK_CYCLES(2); + } + + return 0; } -static int opMOVD_mm_l_a32(uint32_t fetchdat) +static int +opMOVD_mm_l_a32(uint32_t fetchdat) { - MMX_ENTER(); + MMX_REG *op; + MMX_ENTER(); - fetch_ea_32(fetchdat); - if (cpu_mod == 3) - { - cpu_state.regs[cpu_rm].l = cpu_state.MM[cpu_reg].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]); if (cpu_state.abrt) return 1; - CLOCK_CYCLES(2); - } - return 0; + fetch_ea_32(fetchdat); + + op = MMX_GETREGP(cpu_reg); + + if (cpu_mod == 3) { + 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, op->l[0]); + if (cpu_state.abrt) + return 1; + + CLOCK_CYCLES(2); + } + + return 0; } #if defined(DEV_BRANCH) && defined(USE_CYRIX_6X86) /*Cyrix maps both MOVD and SMINT to the same opcode*/ -static int opMOVD_mm_l_a16_cx(uint32_t fetchdat) +static int +opMOVD_mm_l_a16_cx(uint32_t fetchdat) { - if (in_smm) - return opSMINT(fetchdat); + const MMX_REG *op; - MMX_ENTER(); + if (in_smm) + return opSMINT(fetchdat); - fetch_ea_16(fetchdat); - if (cpu_mod == 3) - { - cpu_state.regs[cpu_rm].l = cpu_state.MM[cpu_reg].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]); if (cpu_state.abrt) return 1; - CLOCK_CYCLES(2); - } - return 0; + MMX_ENTER(); + + fetch_ea_16(fetchdat); + + op = MMX_GETREGP(cpu_reg); + + if (cpu_mod == 3) { + 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, op->l[0]); + if (cpu_state.abrt) + return 1; + + CLOCK_CYCLES(2); + } + + return 0; } -static int opMOVD_mm_l_a32_cx(uint32_t fetchdat) +static int +opMOVD_mm_l_a32_cx(uint32_t fetchdat) { - if (in_smm) - return opSMINT(fetchdat); + const MMX_REG *op; - MMX_ENTER(); - - fetch_ea_32(fetchdat); - if (cpu_mod == 3) - { - cpu_state.regs[cpu_rm].l = cpu_state.MM[cpu_reg].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]); if (cpu_state.abrt) return 1; - CLOCK_CYCLES(2); - } - return 0; + 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 = 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, op->l[0]); + if (cpu_state.abrt) + return 1; + + CLOCK_CYCLES(2); + } + + return 0; } #endif -static int opMOVQ_q_mm_a16(uint32_t fetchdat) +static int +opMOVQ_q_mm_a16(uint32_t fetchdat) { - MMX_ENTER(); - - fetch_ea_16(fetchdat); - if (cpu_mod == 3) - { - cpu_state.MM[cpu_reg].q = cpu_state.MM[cpu_rm].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; - CLOCK_CYCLES(2); - } - return 0; + 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) { + op->q = src.q; + CLOCK_CYCLES(1); + } else { + SEG_CHECK_READ(cpu_state.ea_seg); + dst = readmemq(easeg, cpu_state.eaaddr); + if (cpu_state.abrt) + return 1; + + op->q = dst; + CLOCK_CYCLES(2); + } + + MMX_SETEXP(cpu_reg); + + return 0; } -static int opMOVQ_q_mm_a32(uint32_t fetchdat) +static int +opMOVQ_q_mm_a32(uint32_t fetchdat) { - MMX_ENTER(); - - fetch_ea_32(fetchdat); - if (cpu_mod == 3) - { - cpu_state.MM[cpu_reg].q = cpu_state.MM[cpu_rm].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; - CLOCK_CYCLES(2); - } - return 0; + 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) { + op->q = src.q; + CLOCK_CYCLES(1); + } else { + SEG_CHECK_READ(cpu_state.ea_seg); + dst = readmemq(easeg, cpu_state.eaaddr); + if (cpu_state.abrt) + return 1; + + op->q = dst; + CLOCK_CYCLES(2); + } + + MMX_SETEXP(cpu_reg); + + return 0; } -static int opMOVQ_mm_q_a16(uint32_t fetchdat) +static int +opMOVQ_mm_q_a16(uint32_t fetchdat) { - MMX_ENTER(); - - fetch_ea_16(fetchdat); - if (cpu_mod == 3) - { - cpu_state.MM[cpu_rm].q = cpu_state.MM[cpu_reg].q; - CLOCK_CYCLES(1); - } - 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); if (cpu_state.abrt) return 1; - CLOCK_CYCLES(2); - } - return 0; + 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) { + 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, src.q); + if (cpu_state.abrt) + return 1; + + CLOCK_CYCLES(2); + } + + return 0; } -static int opMOVQ_mm_q_a32(uint32_t fetchdat) +static int +opMOVQ_mm_q_a32(uint32_t fetchdat) { - MMX_ENTER(); - - fetch_ea_32(fetchdat); - if (cpu_mod == 3) - { - cpu_state.MM[cpu_rm].q = cpu_state.MM[cpu_reg].q; - CLOCK_CYCLES(1); - } - 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); if (cpu_state.abrt) return 1; - CLOCK_CYCLES(2); - } - return 0; + 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) { + 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, 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 b03ef842e..90ed1b6d2 100644 --- a/src/cpu/x86_ops_mmx_pack.h +++ b/src/cpu/x86_ops_mmx_pack.h @@ -1,326 +1,452 @@ -static int opPUNPCKLDQ_a16(uint32_t fetchdat) +static int +opPUNPCKLDQ_a16(uint32_t fetchdat) { - MMX_ENTER(); - - fetch_ea_16(fetchdat); - if (cpu_mod == 3) - { - cpu_state.MM[cpu_reg].l[1] = cpu_state.MM[cpu_rm].l[0]; - CLOCK_CYCLES(1); - } - else - { - uint32_t src; - - SEG_CHECK_READ(cpu_state.ea_seg); - src = readmeml(easeg, cpu_state.eaaddr); if (cpu_state.abrt) return 0; - cpu_state.MM[cpu_reg].l[1] = src; + uint32_t usrc; + MMX_REG src; + MMX_REG *dst; + MMX_ENTER(); - CLOCK_CYCLES(2); - } - return 0; + fetch_ea_16(fetchdat); + + src = MMX_GETREG(cpu_rm); + dst = MMX_GETREGP(cpu_reg); + + if (cpu_mod == 3) { + dst->l[1] = src.l[0]; + CLOCK_CYCLES(1); + } else { + SEG_CHECK_READ(cpu_state.ea_seg); + usrc = readmeml(easeg, cpu_state.eaaddr); + if (cpu_state.abrt) + return 0; + dst->l[1] = usrc; + + CLOCK_CYCLES(2); + } + + MMX_SETEXP(cpu_reg); + + return 0; } -static int opPUNPCKLDQ_a32(uint32_t fetchdat) +static int +opPUNPCKLDQ_a32(uint32_t fetchdat) { - MMX_ENTER(); - - fetch_ea_32(fetchdat); - if (cpu_mod == 3) - { - cpu_state.MM[cpu_reg].l[1] = cpu_state.MM[cpu_rm].l[0]; - CLOCK_CYCLES(1); - } - else - { - uint32_t src; + uint32_t usrc; + MMX_REG src; + MMX_REG *dst; + MMX_ENTER(); - SEG_CHECK_READ(cpu_state.ea_seg); - src = readmeml(easeg, cpu_state.eaaddr); if (cpu_state.abrt) return 0; - cpu_state.MM[cpu_reg].l[1] = src; + fetch_ea_32(fetchdat); - CLOCK_CYCLES(2); - } - return 0; + src = MMX_GETREG(cpu_rm); + dst = MMX_GETREGP(cpu_reg); + + if (cpu_mod == 3) { + dst->l[1] = src.l[0]; + CLOCK_CYCLES(1); + } else { + SEG_CHECK_READ(cpu_state.ea_seg); + usrc = readmeml(easeg, cpu_state.eaaddr); + if (cpu_state.abrt) + return 0; + dst->l[1] = usrc; + + CLOCK_CYCLES(2); + } + + MMX_SETEXP(cpu_reg); + + return 0; } -static int opPUNPCKHDQ_a16(uint32_t fetchdat) +static int +opPUNPCKHDQ_a16(uint32_t fetchdat) { - MMX_REG src; - MMX_ENTER(); - - fetch_ea_16(fetchdat); - 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]; + MMX_REG src; + MMX_REG *dst; + MMX_ENTER(); - return 0; + fetch_ea_16(fetchdat); + + dst = MMX_GETREGP(cpu_reg); + + MMX_GETSRC(); + + dst->l[0] = dst->l[1]; + dst->l[1] = src.l[1]; + + MMX_SETEXP(cpu_reg); + + return 0; } -static int opPUNPCKHDQ_a32(uint32_t fetchdat) +static int +opPUNPCKHDQ_a32(uint32_t fetchdat) { - MMX_REG src; - MMX_ENTER(); - - fetch_ea_32(fetchdat); - MMX_GETSRC(); + MMX_REG src; + MMX_REG *dst; + MMX_ENTER(); - cpu_state.MM[cpu_reg].l[0] = cpu_state.MM[cpu_reg].l[1]; - cpu_state.MM[cpu_reg].l[1] = src.l[1]; + fetch_ea_32(fetchdat); - return 0; + dst = MMX_GETREGP(cpu_reg); + + MMX_GETSRC(); + + dst->l[0] = dst->l[1]; + dst->l[1] = src.l[1]; + + MMX_SETEXP(cpu_reg); + + return 0; } -static int opPUNPCKLBW_a16(uint32_t fetchdat) +static int +opPUNPCKLBW_a16(uint32_t fetchdat) { - MMX_REG src; - MMX_ENTER(); - - fetch_ea_16(fetchdat); - MMX_GETSRC(); + MMX_REG src; + MMX_REG *dst; + MMX_ENTER(); - 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]; + fetch_ea_16(fetchdat); - return 0; + dst = MMX_GETREGP(cpu_reg); + + MMX_GETSRC(); + + 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; } -static int opPUNPCKLBW_a32(uint32_t fetchdat) +static int +opPUNPCKLBW_a32(uint32_t fetchdat) { - MMX_REG src; - MMX_ENTER(); - - fetch_ea_32(fetchdat); - MMX_GETSRC(); + MMX_REG src; + MMX_REG *dst; + MMX_ENTER(); - 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]; + fetch_ea_32(fetchdat); - return 0; + dst = MMX_GETREGP(cpu_reg); + + MMX_GETSRC(); + + 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; } -static int opPUNPCKHBW_a16(uint32_t fetchdat) +static int +opPUNPCKHBW_a16(uint32_t fetchdat) { - MMX_REG src; - MMX_ENTER(); - - fetch_ea_16(fetchdat); - MMX_GETSRC(); + MMX_REG src; + MMX_REG *dst; + MMX_ENTER(); - 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]; - - return 0; + fetch_ea_16(fetchdat); + + dst = MMX_GETREGP(cpu_reg); + + MMX_GETSRC(); + + 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; } -static int opPUNPCKHBW_a32(uint32_t fetchdat) +static int +opPUNPCKHBW_a32(uint32_t fetchdat) { - MMX_REG src; - MMX_ENTER(); - - fetch_ea_32(fetchdat); - MMX_GETSRC(); + MMX_REG src; + MMX_REG *dst; + MMX_ENTER(); - 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]; - - return 0; + fetch_ea_32(fetchdat); + + dst = MMX_GETREGP(cpu_reg); + + MMX_GETSRC(); + + 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; } -static int opPUNPCKLWD_a16(uint32_t fetchdat) +static int +opPUNPCKLWD_a16(uint32_t fetchdat) { - MMX_REG src; - MMX_ENTER(); - - fetch_ea_16(fetchdat); - MMX_GETSRC(); + MMX_REG src; + MMX_REG *dst; + MMX_ENTER(); - 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]; + fetch_ea_16(fetchdat); - return 0; + dst = MMX_GETREGP(cpu_reg); + + MMX_GETSRC(); + + 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; } -static int opPUNPCKLWD_a32(uint32_t fetchdat) +static int +opPUNPCKLWD_a32(uint32_t fetchdat) { - MMX_REG src; - MMX_ENTER(); - - fetch_ea_32(fetchdat); - MMX_GETSRC(); + MMX_REG src; + MMX_REG *dst; + MMX_ENTER(); - 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]; + fetch_ea_32(fetchdat); - return 0; + dst = MMX_GETREGP(cpu_reg); + + MMX_GETSRC(); + + 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; } -static int opPUNPCKHWD_a16(uint32_t fetchdat) +static int +opPUNPCKHWD_a16(uint32_t fetchdat) { - MMX_REG src; - MMX_ENTER(); - - fetch_ea_16(fetchdat); - MMX_GETSRC(); + MMX_REG src; + MMX_REG *dst; + MMX_ENTER(); - 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]; + fetch_ea_16(fetchdat); - return 0; + dst = MMX_GETREGP(cpu_reg); + + MMX_GETSRC(); + + 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; } -static int opPUNPCKHWD_a32(uint32_t fetchdat) +static int +opPUNPCKHWD_a32(uint32_t fetchdat) { - MMX_REG src; - MMX_ENTER(); - - fetch_ea_32(fetchdat); - MMX_GETSRC(); + MMX_REG src; + MMX_REG *dst; + MMX_ENTER(); - 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]; + fetch_ea_32(fetchdat); - return 0; + dst = MMX_GETREGP(cpu_reg); + + MMX_GETSRC(); + + 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; } -static int opPACKSSWB_a16(uint32_t fetchdat) +static int +opPACKSSWB_a16(uint32_t fetchdat) { - MMX_REG src, dst; - MMX_ENTER(); - - fetch_ea_16(fetchdat); - MMX_GETSRC(); - dst = cpu_state.MM[cpu_reg]; + MMX_REG src; + MMX_REG *dst; + MMX_ENTER(); - 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]); - - return 0; + fetch_ea_16(fetchdat); + + 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) +static int +opPACKSSWB_a32(uint32_t fetchdat) { - MMX_REG src, dst; - MMX_ENTER(); - - fetch_ea_32(fetchdat); - MMX_GETSRC(); - dst = cpu_state.MM[cpu_reg]; + MMX_REG src; + MMX_REG *dst; + MMX_ENTER(); - 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]); - - return 0; + fetch_ea_32(fetchdat); + + 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 opPACKUSWB_a16(uint32_t fetchdat) +static int +opPACKUSWB_a16(uint32_t fetchdat) { - MMX_REG src, dst; - MMX_ENTER(); - - fetch_ea_16(fetchdat); - MMX_GETSRC(); - dst = cpu_state.MM[cpu_reg]; + MMX_REG src; + MMX_REG *dst; + MMX_ENTER(); - 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]); - - return 0; + fetch_ea_16(fetchdat); + + 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) +static int +opPACKUSWB_a32(uint32_t fetchdat) { - MMX_REG src, dst; - MMX_ENTER(); - - fetch_ea_32(fetchdat); - MMX_GETSRC(); - dst = cpu_state.MM[cpu_reg]; + MMX_REG src; + MMX_REG *dst; + MMX_ENTER(); - 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]); + fetch_ea_32(fetchdat); - return 0; + 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 opPACKSSDW_a16(uint32_t fetchdat) +static int +opPACKSSDW_a16(uint32_t fetchdat) { - MMX_REG src, dst; - 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]); - - return 0; + MMX_REG src; + MMX_REG *dst; + MMX_REG dst2; + MMX_ENTER(); + + fetch_ea_16(fetchdat); + + 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) +static int +opPACKSSDW_a32(uint32_t fetchdat) { - MMX_REG src, dst; - 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]); - - return 0; + MMX_REG src; + MMX_REG *dst; + MMX_REG dst2; + MMX_ENTER(); + + fetch_ea_32(fetchdat); + + 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 a0a4d90c1..04aeb8a9a 100644 --- a/src/cpu/x86_ops_mmx_shift.h +++ b/src/cpu/x86_ops_mmx_shift.h @@ -1,450 +1,565 @@ -#define MMX_GETSHIFT() \ - if (cpu_mod == 3) \ - { \ - shift = cpu_state.MM[cpu_rm].b[0]; \ - CLOCK_CYCLES(1); \ - } \ - else \ - { \ - SEG_CHECK_READ(cpu_state.ea_seg); \ - shift = readmemb(easeg, cpu_state.eaaddr); if (cpu_state.abrt) return 0; \ - CLOCK_CYCLES(2); \ - } +#define MMX_GETSHIFT() \ + if (cpu_mod == 3) { \ + shift = (MMX_GETREG(cpu_rm)).b[0]; \ + CLOCK_CYCLES(1); \ + } else { \ + SEG_CHECK_READ(cpu_state.ea_seg); \ + shift = readmemb(easeg, cpu_state.eaaddr); \ + if (cpu_state.abrt) \ + return 0; \ + CLOCK_CYCLES(2); \ + } -static int opPSxxW_imm(uint32_t fetchdat) +static int +opPSxxW_imm(uint32_t fetchdat) { - int reg = fetchdat & 7; - int op = fetchdat & 0x38; - int shift = (fetchdat >> 8) & 0xff; - - cpu_state.pc += 2; - MMX_ENTER(); + int reg = fetchdat & 7; + int op = fetchdat & 0x38; + int shift = (fetchdat >> 8) & 0xff; + MMX_REG *dst; - switch (op) - { - case 0x10: /*PSRLW*/ - if (shift > 15) - cpu_state.MM[reg].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; - } - 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; - break; - case 0x30: /*PSLLW*/ - if (shift > 15) - cpu_state.MM[reg].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; - } - break; - default: - cpu_state.pc = cpu_state.oldpc; - x86illegal(); - return 0; - } + cpu_state.pc += 2; + MMX_ENTER(); + dst = MMX_GETREGP(reg); - CLOCK_CYCLES(1); - return 0; -} - -static int opPSLLW_a16(uint32_t fetchdat) -{ - int shift; - - MMX_ENTER(); - - fetch_ea_16(fetchdat); - MMX_GETSHIFT(); - - if (shift > 15) - cpu_state.MM[cpu_reg].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; - } - - return 0; -} -static int opPSLLW_a32(uint32_t fetchdat) -{ - int shift; - - MMX_ENTER(); - - fetch_ea_32(fetchdat); - MMX_GETSHIFT(); - - if (shift > 15) - cpu_state.MM[cpu_reg].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; - } - - return 0; -} - -static int opPSRLW_a16(uint32_t fetchdat) -{ - int shift; - - MMX_ENTER(); - - fetch_ea_16(fetchdat); - MMX_GETSHIFT(); - - if (shift > 15) - cpu_state.MM[cpu_reg].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; - } - - return 0; -} -static int opPSRLW_a32(uint32_t fetchdat) -{ - int shift; - - MMX_ENTER(); - - fetch_ea_32(fetchdat); - MMX_GETSHIFT(); - - if (shift > 15) - cpu_state.MM[cpu_reg].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; - } - - return 0; -} - -static int opPSRAW_a16(uint32_t fetchdat) -{ - int shift; - - MMX_ENTER(); - - fetch_ea_16(fetchdat); - MMX_GETSHIFT(); - - if (shift > 15) + switch (op) { + case 0x10: /*PSRLW*/ + if (shift > 15) + dst->q = 0; + else { + 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; + dst->sw[0] >>= shift; + dst->sw[1] >>= shift; + dst->sw[2] >>= shift; + dst->sw[3] >>= shift; + break; + case 0x30: /*PSLLW*/ + if (shift > 15) + dst->q = 0; + else { + dst->w[0] <<= shift; + dst->w[1] <<= shift; + dst->w[2] <<= shift; + dst->w[3] <<= shift; + } + break; + default: + cpu_state.pc = cpu_state.oldpc; + x86illegal(); + return 0; + } - 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; - - return 0; -} -static int opPSRAW_a32(uint32_t fetchdat) -{ - int shift; - - MMX_ENTER(); - - fetch_ea_32(fetchdat); - MMX_GETSHIFT(); + MMX_SETEXP(reg); - 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; - - return 0; + CLOCK_CYCLES(1); + return 0; } -static int opPSxxD_imm(uint32_t fetchdat) +static int +opPSLLW_a16(uint32_t fetchdat) { - int reg = fetchdat & 7; - int op = fetchdat & 0x38; - int shift = (fetchdat >> 8) & 0xff; - - cpu_state.pc += 2; - MMX_ENTER(); + MMX_REG *dst; + int shift; - switch (op) - { - case 0x10: /*PSRLD*/ - if (shift > 31) - cpu_state.MM[reg].q = 0; - else - { - cpu_state.MM[reg].l[0] >>= shift; - cpu_state.MM[reg].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; - break; - case 0x30: /*PSLLD*/ - if (shift > 31) - cpu_state.MM[reg].q = 0; - else - { - cpu_state.MM[reg].l[0] <<= shift; - cpu_state.MM[reg].l[1] <<= shift; - } - break; - default: - cpu_state.pc = cpu_state.oldpc; - x86illegal(); - return 0; - } + MMX_ENTER(); - CLOCK_CYCLES(1); - return 0; + fetch_ea_16(fetchdat); + + dst = MMX_GETREGP(cpu_reg); + + MMX_GETSHIFT(); + + if (shift > 15) + dst->q = 0; + else { + 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) + dst->q = 0; + else { + dst->w[0] <<= shift; + dst->w[1] <<= shift; + dst->w[2] <<= shift; + dst->w[3] <<= shift; + } + + MMX_SETEXP(cpu_reg); + + return 0; } -static int opPSLLD_a16(uint32_t fetchdat) +static int +opPSRLW_a16(uint32_t fetchdat) { - int shift; - - MMX_ENTER(); - - fetch_ea_16(fetchdat); - MMX_GETSHIFT(); + MMX_REG *dst; + int shift; - if (shift > 31) - cpu_state.MM[cpu_reg].q = 0; - else - { - cpu_state.MM[cpu_reg].l[0] <<= shift; - cpu_state.MM[cpu_reg].l[1] <<= shift; - } + MMX_ENTER(); - return 0; + fetch_ea_16(fetchdat); + + dst = MMX_GETREGP(cpu_reg); + + MMX_GETSHIFT(); + + if (shift > 15) + dst->q = 0; + else { + dst->w[0] >>= shift; + dst->w[1] >>= shift; + dst->w[2] >>= shift; + dst->w[3] >>= shift; + } + + MMX_SETEXP(cpu_reg); + + return 0; } -static int opPSLLD_a32(uint32_t fetchdat) +static int +opPSRLW_a32(uint32_t fetchdat) { - int shift; - - MMX_ENTER(); - - fetch_ea_32(fetchdat); - MMX_GETSHIFT(); + MMX_REG *dst; + int shift; - if (shift > 31) - cpu_state.MM[cpu_reg].q = 0; - else - { - cpu_state.MM[cpu_reg].l[0] <<= shift; - cpu_state.MM[cpu_reg].l[1] <<= shift; - } + MMX_ENTER(); - return 0; + fetch_ea_32(fetchdat); + + dst = MMX_GETREGP(cpu_reg); + + MMX_GETSHIFT(); + + if (shift > 15) + dst->q = 0; + else { + dst->w[0] >>= shift; + dst->w[1] >>= shift; + dst->w[2] >>= shift; + dst->w[3] >>= shift; + } + + MMX_SETEXP(cpu_reg); + + return 0; } -static int opPSRLD_a16(uint32_t fetchdat) +static int +opPSRAW_a16(uint32_t fetchdat) { - int shift; - - MMX_ENTER(); - - fetch_ea_16(fetchdat); - MMX_GETSHIFT(); + MMX_REG *dst; + int shift; - if (shift > 31) - cpu_state.MM[cpu_reg].q = 0; - else - { - cpu_state.MM[cpu_reg].l[0] >>= shift; - cpu_state.MM[cpu_reg].l[1] >>= shift; - } + MMX_ENTER(); - return 0; + fetch_ea_16(fetchdat); + + dst = MMX_GETREGP(cpu_reg); + + MMX_GETSHIFT(); + + if (shift > 15) + shift = 15; + + dst->sw[0] >>= shift; + dst->sw[1] >>= shift; + dst->sw[2] >>= shift; + dst->sw[3] >>= shift; + + MMX_SETEXP(cpu_reg); + + return 0; } -static int opPSRLD_a32(uint32_t fetchdat) +static int +opPSRAW_a32(uint32_t fetchdat) { - int shift; - - MMX_ENTER(); - - fetch_ea_32(fetchdat); - MMX_GETSHIFT(); + MMX_REG *dst; + int shift; - if (shift > 31) - cpu_state.MM[cpu_reg].q = 0; - else - { - cpu_state.MM[cpu_reg].l[0] >>= shift; - cpu_state.MM[cpu_reg].l[1] >>= shift; - } + MMX_ENTER(); - return 0; + fetch_ea_32(fetchdat); + + dst = MMX_GETREGP(cpu_reg); + + MMX_GETSHIFT(); + + if (shift > 15) + shift = 15; + + dst->sw[0] >>= shift; + dst->sw[1] >>= shift; + dst->sw[2] >>= shift; + dst->sw[3] >>= shift; + + MMX_SETEXP(cpu_reg); + + return 0; } -static int opPSRAD_a16(uint32_t fetchdat) +static int +opPSxxD_imm(uint32_t fetchdat) { - int shift; - - MMX_ENTER(); - - fetch_ea_16(fetchdat); - MMX_GETSHIFT(); + int reg = fetchdat & 7; + int op = fetchdat & 0x38; + int shift = (fetchdat >> 8) & 0xff; + MMX_REG *dst; - if (shift > 31) + cpu_state.pc += 2; + MMX_ENTER(); + + dst = MMX_GETREGP(reg); + + switch (op) { + case 0x10: /*PSRLD*/ + if (shift > 31) + dst->q = 0; + else { + dst->l[0] >>= shift; + dst->l[1] >>= shift; + } + break; + case 0x20: /*PSRAD*/ + if (shift > 31) shift = 31; + dst->sl[0] >>= shift; + dst->sl[1] >>= shift; + break; + case 0x30: /*PSLLD*/ + if (shift > 31) + dst->q = 0; + else { + dst->l[0] <<= shift; + dst->l[1] <<= shift; + } + break; + default: + cpu_state.pc = cpu_state.oldpc; + x86illegal(); + return 0; + } - cpu_state.MM[cpu_reg].sl[0] >>= shift; - cpu_state.MM[cpu_reg].sl[1] >>= shift; - - return 0; + MMX_SETEXP(reg); + + CLOCK_CYCLES(1); + return 0; } -static int opPSRAD_a32(uint32_t fetchdat) + +static int +opPSLLD_a16(uint32_t fetchdat) { - int shift; - - MMX_ENTER(); - - fetch_ea_32(fetchdat); - MMX_GETSHIFT(); + MMX_REG *dst; + int shift; - if (shift > 31) - shift = 31; + MMX_ENTER(); - cpu_state.MM[cpu_reg].sl[0] >>= shift; - cpu_state.MM[cpu_reg].sl[1] >>= shift; + fetch_ea_16(fetchdat); - return 0; + dst = MMX_GETREGP(cpu_reg); + + MMX_GETSHIFT(); + + if (shift > 31) + dst->q = 0; + else { + dst->l[0] <<= shift; + dst->l[1] <<= shift; + } + + MMX_SETEXP(cpu_reg); + + return 0; } - -static int opPSxxQ_imm(uint32_t fetchdat) +static int +opPSLLD_a32(uint32_t fetchdat) { - int reg = fetchdat & 7; - int op = fetchdat & 0x38; - int shift = (fetchdat >> 8) & 0xff; - - cpu_state.pc += 2; - MMX_ENTER(); + MMX_REG *dst; + int shift; - switch (op) - { - case 0x10: /*PSRLW*/ - if (shift > 63) - cpu_state.MM[reg].q = 0; - else - cpu_state.MM[reg].q >>= shift; - break; - case 0x20: /*PSRAW*/ - if (shift > 63) - shift = 63; - cpu_state.MM[reg].sq >>= shift; - break; - case 0x30: /*PSLLW*/ - if (shift > 63) - cpu_state.MM[reg].q = 0; - else - cpu_state.MM[reg].q <<= shift; - break; - default: - cpu_state.pc = cpu_state.oldpc; - x86illegal(); - return 0; - } + MMX_ENTER(); - CLOCK_CYCLES(1); - return 0; + fetch_ea_32(fetchdat); + + dst = MMX_GETREGP(cpu_reg); + + MMX_GETSHIFT(); + + if (shift > 31) + dst->q = 0; + else { + dst->l[0] <<= shift; + dst->l[1] <<= shift; + } + + MMX_SETEXP(cpu_reg); + + return 0; } -static int opPSLLQ_a16(uint32_t fetchdat) +static int +opPSRLD_a16(uint32_t fetchdat) { - int shift; - - MMX_ENTER(); - - fetch_ea_16(fetchdat); - MMX_GETSHIFT(); + MMX_REG *dst; + int shift; - if (shift > 63) - cpu_state.MM[cpu_reg].q = 0; - else - cpu_state.MM[cpu_reg].q <<= shift; + MMX_ENTER(); - return 0; + fetch_ea_16(fetchdat); + + dst = MMX_GETREGP(cpu_reg); + + MMX_GETSHIFT(); + + if (shift > 31) + dst->q = 0; + else { + dst->l[0] >>= shift; + dst->l[1] >>= shift; + } + + MMX_SETEXP(cpu_reg); + + return 0; } -static int opPSLLQ_a32(uint32_t fetchdat) +static int +opPSRLD_a32(uint32_t fetchdat) { - int shift; - - MMX_ENTER(); - - fetch_ea_32(fetchdat); - MMX_GETSHIFT(); + MMX_REG *dst; + int shift; - if (shift > 63) - cpu_state.MM[cpu_reg].q = 0; - else - cpu_state.MM[cpu_reg].q <<= shift; + MMX_ENTER(); - return 0; + fetch_ea_32(fetchdat); + + dst = MMX_GETREGP(cpu_reg); + + MMX_GETSHIFT(); + + if (shift > 31) + dst->q = 0; + else { + dst->l[0] >>= shift; + dst->l[1] >>= shift; + } + + MMX_SETEXP(cpu_reg); + + return 0; } -static int opPSRLQ_a16(uint32_t fetchdat) +static int +opPSRAD_a16(uint32_t fetchdat) { - int shift; - - MMX_ENTER(); - - fetch_ea_16(fetchdat); - MMX_GETSHIFT(); + MMX_REG *dst; + int shift; - if (shift > 63) - cpu_state.MM[cpu_reg].q = 0; - else - cpu_state.MM[cpu_reg].q >>= shift; + MMX_ENTER(); - return 0; + fetch_ea_16(fetchdat); + + dst = MMX_GETREGP(cpu_reg); + + MMX_GETSHIFT(); + + if (shift > 31) + shift = 31; + + dst->sl[0] >>= shift; + dst->sl[1] >>= shift; + + MMX_SETEXP(cpu_reg); + + return 0; } -static int opPSRLQ_a32(uint32_t fetchdat) +static int +opPSRAD_a32(uint32_t fetchdat) { - int shift; - - MMX_ENTER(); - - fetch_ea_32(fetchdat); - MMX_GETSHIFT(); + MMX_REG *dst; + int shift; - if (shift > 63) - cpu_state.MM[cpu_reg].q = 0; - else - cpu_state.MM[cpu_reg].q >>= shift; + MMX_ENTER(); - return 0; + fetch_ea_32(fetchdat); + + dst = MMX_GETREGP(cpu_reg); + + MMX_GETSHIFT(); + + if (shift > 31) + shift = 31; + + dst->sl[0] >>= shift; + dst->sl[1] >>= shift; + + MMX_SETEXP(cpu_reg); + + return 0; +} + +static int +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) + dst->q = 0; + else + dst->q >>= shift; + break; + case 0x20: /*PSRAW*/ + if (shift > 63) + shift = 63; + + dst->sq >>= shift; + break; + case 0x30: /*PSLLW*/ + if (shift > 63) + dst->q = 0; + else + dst->q <<= shift; + break; + default: + cpu_state.pc = cpu_state.oldpc; + x86illegal(); + return 0; + } + + MMX_SETEXP(reg); + + CLOCK_CYCLES(1); + return 0; +} + +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) + dst->q = 0; + else + 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) + dst->q = 0; + else + dst->q <<= shift; + + MMX_SETEXP(cpu_reg); + + return 0; +} + +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) + dst->q = 0; + else + 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) + dst->q = 0; + else + dst->q >>= shift; + + MMX_SETEXP(cpu_reg); + + return 0; } diff --git a/src/cpu/x86_ops_mov.h b/src/cpu/x86_ops_mov.h index 8702578b1..e77876d5c 100644 --- a/src/cpu/x86_ops_mov.h +++ b/src/cpu/x86_ops_mov.h @@ -1,771 +1,854 @@ -static int opMOV_AL_imm(uint32_t fetchdat) +static int +opMOV_AL_imm(uint32_t fetchdat) { - AL = getbytef(); - CLOCK_CYCLES(timing_rr); - PREFETCH_RUN(timing_rr, 2, -1, 0,0,0,0, 0); - return 0; + AL = getbytef(); + CLOCK_CYCLES(timing_rr); + PREFETCH_RUN(timing_rr, 2, -1, 0, 0, 0, 0, 0); + return 0; } -static int opMOV_AH_imm(uint32_t fetchdat) +static int +opMOV_AH_imm(uint32_t fetchdat) { - AH = getbytef(); - CLOCK_CYCLES(timing_rr); - PREFETCH_RUN(timing_rr, 2, -1, 0,0,0,0, 0); - return 0; + AH = getbytef(); + CLOCK_CYCLES(timing_rr); + PREFETCH_RUN(timing_rr, 2, -1, 0, 0, 0, 0, 0); + return 0; } -static int opMOV_BL_imm(uint32_t fetchdat) +static int +opMOV_BL_imm(uint32_t fetchdat) { - BL = getbytef(); - CLOCK_CYCLES(timing_rr); - PREFETCH_RUN(timing_rr, 2, -1, 0,0,0,0, 0); - return 0; + BL = getbytef(); + CLOCK_CYCLES(timing_rr); + PREFETCH_RUN(timing_rr, 2, -1, 0, 0, 0, 0, 0); + return 0; } -static int opMOV_BH_imm(uint32_t fetchdat) +static int +opMOV_BH_imm(uint32_t fetchdat) { - BH = getbytef(); - CLOCK_CYCLES(timing_rr); - PREFETCH_RUN(timing_rr, 2, -1, 0,0,0,0, 0); - return 0; + BH = getbytef(); + CLOCK_CYCLES(timing_rr); + PREFETCH_RUN(timing_rr, 2, -1, 0, 0, 0, 0, 0); + return 0; } -static int opMOV_CL_imm(uint32_t fetchdat) +static int +opMOV_CL_imm(uint32_t fetchdat) { - CL = getbytef(); - CLOCK_CYCLES(timing_rr); - PREFETCH_RUN(timing_rr, 2, -1, 0,0,0,0, 0); - return 0; + CL = getbytef(); + CLOCK_CYCLES(timing_rr); + PREFETCH_RUN(timing_rr, 2, -1, 0, 0, 0, 0, 0); + return 0; } -static int opMOV_CH_imm(uint32_t fetchdat) +static int +opMOV_CH_imm(uint32_t fetchdat) { - CH = getbytef(); - CLOCK_CYCLES(timing_rr); - PREFETCH_RUN(timing_rr, 2, -1, 0,0,0,0, 0); - return 0; + CH = getbytef(); + CLOCK_CYCLES(timing_rr); + PREFETCH_RUN(timing_rr, 2, -1, 0, 0, 0, 0, 0); + return 0; } -static int opMOV_DL_imm(uint32_t fetchdat) +static int +opMOV_DL_imm(uint32_t fetchdat) { - DL = getbytef(); - CLOCK_CYCLES(timing_rr); - PREFETCH_RUN(timing_rr, 2, -1, 0,0,0,0, 0); - return 0; + DL = getbytef(); + CLOCK_CYCLES(timing_rr); + PREFETCH_RUN(timing_rr, 2, -1, 0, 0, 0, 0, 0); + return 0; } -static int opMOV_DH_imm(uint32_t fetchdat) +static int +opMOV_DH_imm(uint32_t fetchdat) { - DH = getbytef(); - CLOCK_CYCLES(timing_rr); - PREFETCH_RUN(timing_rr, 2, -1, 0,0,0,0, 0); - return 0; + DH = getbytef(); + CLOCK_CYCLES(timing_rr); + PREFETCH_RUN(timing_rr, 2, -1, 0, 0, 0, 0, 0); + return 0; } -static int opMOV_AX_imm(uint32_t fetchdat) +static int +opMOV_AX_imm(uint32_t fetchdat) { - AX = getwordf(); - CLOCK_CYCLES(timing_rr); - PREFETCH_RUN(timing_rr, 3, -1, 0,0,0,0, 0); - return 0; + AX = getwordf(); + CLOCK_CYCLES(timing_rr); + PREFETCH_RUN(timing_rr, 3, -1, 0, 0, 0, 0, 0); + return 0; } -static int opMOV_BX_imm(uint32_t fetchdat) +static int +opMOV_BX_imm(uint32_t fetchdat) { - BX = getwordf(); - CLOCK_CYCLES(timing_rr); - PREFETCH_RUN(timing_rr, 3, -1, 0,0,0,0, 0); - return 0; + BX = getwordf(); + CLOCK_CYCLES(timing_rr); + PREFETCH_RUN(timing_rr, 3, -1, 0, 0, 0, 0, 0); + return 0; } -static int opMOV_CX_imm(uint32_t fetchdat) +static int +opMOV_CX_imm(uint32_t fetchdat) { - CX = getwordf(); - CLOCK_CYCLES(timing_rr); - PREFETCH_RUN(timing_rr, 3, -1, 0,0,0,0, 0); - return 0; + CX = getwordf(); + CLOCK_CYCLES(timing_rr); + PREFETCH_RUN(timing_rr, 3, -1, 0, 0, 0, 0, 0); + return 0; } -static int opMOV_DX_imm(uint32_t fetchdat) +static int +opMOV_DX_imm(uint32_t fetchdat) { - DX = getwordf(); - CLOCK_CYCLES(timing_rr); - PREFETCH_RUN(timing_rr, 3, -1, 0,0,0,0, 0); - return 0; + DX = getwordf(); + CLOCK_CYCLES(timing_rr); + PREFETCH_RUN(timing_rr, 3, -1, 0, 0, 0, 0, 0); + return 0; } -static int opMOV_SI_imm(uint32_t fetchdat) +static int +opMOV_SI_imm(uint32_t fetchdat) { - SI = getwordf(); - CLOCK_CYCLES(timing_rr); - PREFETCH_RUN(timing_rr, 3, -1, 0,0,0,0, 0); - return 0; + SI = getwordf(); + CLOCK_CYCLES(timing_rr); + PREFETCH_RUN(timing_rr, 3, -1, 0, 0, 0, 0, 0); + return 0; } -static int opMOV_DI_imm(uint32_t fetchdat) +static int +opMOV_DI_imm(uint32_t fetchdat) { - DI = getwordf(); - CLOCK_CYCLES(timing_rr); - PREFETCH_RUN(timing_rr, 3, -1, 0,0,0,0, 0); - return 0; + DI = getwordf(); + CLOCK_CYCLES(timing_rr); + PREFETCH_RUN(timing_rr, 3, -1, 0, 0, 0, 0, 0); + return 0; } -static int opMOV_BP_imm(uint32_t fetchdat) +static int +opMOV_BP_imm(uint32_t fetchdat) { - BP = getwordf(); - CLOCK_CYCLES(timing_rr); - PREFETCH_RUN(timing_rr, 3, -1, 0,0,0,0, 0); - return 0; + BP = getwordf(); + CLOCK_CYCLES(timing_rr); + PREFETCH_RUN(timing_rr, 3, -1, 0, 0, 0, 0, 0); + return 0; } -static int opMOV_SP_imm(uint32_t fetchdat) +static int +opMOV_SP_imm(uint32_t fetchdat) { - SP = getwordf(); - CLOCK_CYCLES(timing_rr); - PREFETCH_RUN(timing_rr, 3, -1, 0,0,0,0, 0); - return 0; + SP = getwordf(); + CLOCK_CYCLES(timing_rr); + PREFETCH_RUN(timing_rr, 3, -1, 0, 0, 0, 0, 0); + return 0; } -static int opMOV_EAX_imm(uint32_t fetchdat) +static int +opMOV_EAX_imm(uint32_t fetchdat) { - uint32_t templ = getlong(); if (cpu_state.abrt) return 1; - EAX = templ; - CLOCK_CYCLES(timing_rr); - PREFETCH_RUN(timing_rr, 5, -1, 0,0,0,0, 0); - return 0; + uint32_t templ = getlong(); + if (cpu_state.abrt) + return 1; + EAX = templ; + CLOCK_CYCLES(timing_rr); + PREFETCH_RUN(timing_rr, 5, -1, 0, 0, 0, 0, 0); + return 0; } -static int opMOV_EBX_imm(uint32_t fetchdat) +static int +opMOV_EBX_imm(uint32_t fetchdat) { - uint32_t templ = getlong(); if (cpu_state.abrt) return 1; - EBX = templ; - CLOCK_CYCLES(timing_rr); - PREFETCH_RUN(timing_rr, 5, -1, 0,0,0,0, 0); - return 0; + uint32_t templ = getlong(); + if (cpu_state.abrt) + return 1; + EBX = templ; + CLOCK_CYCLES(timing_rr); + PREFETCH_RUN(timing_rr, 5, -1, 0, 0, 0, 0, 0); + return 0; } -static int opMOV_ECX_imm(uint32_t fetchdat) +static int +opMOV_ECX_imm(uint32_t fetchdat) { - uint32_t templ = getlong(); if (cpu_state.abrt) return 1; - ECX = templ; - CLOCK_CYCLES(timing_rr); - PREFETCH_RUN(timing_rr, 5, -1, 0,0,0,0, 0); - return 0; + uint32_t templ = getlong(); + if (cpu_state.abrt) + return 1; + ECX = templ; + CLOCK_CYCLES(timing_rr); + PREFETCH_RUN(timing_rr, 5, -1, 0, 0, 0, 0, 0); + return 0; } -static int opMOV_EDX_imm(uint32_t fetchdat) +static int +opMOV_EDX_imm(uint32_t fetchdat) { - uint32_t templ = getlong(); if (cpu_state.abrt) return 1; - EDX = templ; - CLOCK_CYCLES(timing_rr); - PREFETCH_RUN(timing_rr, 5, -1, 0,0,0,0, 0); - return 0; + uint32_t templ = getlong(); + if (cpu_state.abrt) + return 1; + EDX = templ; + CLOCK_CYCLES(timing_rr); + PREFETCH_RUN(timing_rr, 5, -1, 0, 0, 0, 0, 0); + return 0; } -static int opMOV_ESI_imm(uint32_t fetchdat) +static int +opMOV_ESI_imm(uint32_t fetchdat) { - uint32_t templ = getlong(); if (cpu_state.abrt) return 1; - ESI = templ; - CLOCK_CYCLES(timing_rr); - PREFETCH_RUN(timing_rr, 5, -1, 0,0,0,0, 0); - return 0; + uint32_t templ = getlong(); + if (cpu_state.abrt) + return 1; + ESI = templ; + CLOCK_CYCLES(timing_rr); + PREFETCH_RUN(timing_rr, 5, -1, 0, 0, 0, 0, 0); + return 0; } -static int opMOV_EDI_imm(uint32_t fetchdat) +static int +opMOV_EDI_imm(uint32_t fetchdat) { - uint32_t templ = getlong(); if (cpu_state.abrt) return 1; - EDI = templ; - CLOCK_CYCLES(timing_rr); - PREFETCH_RUN(timing_rr, 5, -1, 0,0,0,0, 0); - return 0; + uint32_t templ = getlong(); + if (cpu_state.abrt) + return 1; + EDI = templ; + CLOCK_CYCLES(timing_rr); + PREFETCH_RUN(timing_rr, 5, -1, 0, 0, 0, 0, 0); + return 0; } -static int opMOV_EBP_imm(uint32_t fetchdat) +static int +opMOV_EBP_imm(uint32_t fetchdat) { - uint32_t templ = getlong(); if (cpu_state.abrt) return 1; - EBP = templ; - CLOCK_CYCLES(timing_rr); - PREFETCH_RUN(timing_rr, 5, -1, 0,0,0,0, 0); - return 0; + uint32_t templ = getlong(); + if (cpu_state.abrt) + return 1; + EBP = templ; + CLOCK_CYCLES(timing_rr); + PREFETCH_RUN(timing_rr, 5, -1, 0, 0, 0, 0, 0); + return 0; } -static int opMOV_ESP_imm(uint32_t fetchdat) +static int +opMOV_ESP_imm(uint32_t fetchdat) { - uint32_t templ = getlong(); if (cpu_state.abrt) return 1; - ESP = templ; - CLOCK_CYCLES(timing_rr); - PREFETCH_RUN(timing_rr, 5, -1, 0,0,0,0, 0); - return 0; + uint32_t templ = getlong(); + if (cpu_state.abrt) + return 1; + ESP = templ; + CLOCK_CYCLES(timing_rr); + PREFETCH_RUN(timing_rr, 5, -1, 0, 0, 0, 0, 0); + return 0; } -static int opMOV_b_imm_a16(uint32_t fetchdat) +static int +opMOV_b_imm_a16(uint32_t fetchdat) { - uint8_t temp; - fetch_ea_16(fetchdat); - ILLEGAL_ON((rmdat & 0x38) != 0); + uint8_t temp; + fetch_ea_16(fetchdat); + ILLEGAL_ON((rmdat & 0x38) != 0); + SEG_CHECK_WRITE(cpu_state.ea_seg); + temp = readmemb(cs, cpu_state.pc); + cpu_state.pc++; + if (cpu_state.abrt) + return 1; + seteab(temp); + CLOCK_CYCLES(timing_rr); + PREFETCH_RUN(timing_rr, 3, rmdat, 0, 0, (cpu_mod == 3) ? 1 : 0, 0, 0); + return cpu_state.abrt; +} +static int +opMOV_b_imm_a32(uint32_t fetchdat) +{ + uint8_t temp; + fetch_ea_32(fetchdat); + ILLEGAL_ON((rmdat & 0x38) != 0); + SEG_CHECK_WRITE(cpu_state.ea_seg); + temp = getbyte(); + if (cpu_state.abrt) + return 1; + seteab(temp); + CLOCK_CYCLES(timing_rr); + PREFETCH_RUN(timing_rr, 3, rmdat, 0, 0, (cpu_mod == 3) ? 1 : 0, 0, 1); + return cpu_state.abrt; +} + +static int +opMOV_w_imm_a16(uint32_t fetchdat) +{ + uint16_t temp; + fetch_ea_16(fetchdat); + ILLEGAL_ON((rmdat & 0x38) != 0); + SEG_CHECK_WRITE(cpu_state.ea_seg); + temp = getword(); + if (cpu_state.abrt) + return 1; + seteaw(temp); + CLOCK_CYCLES(timing_rr); + PREFETCH_RUN(timing_rr, 4, rmdat, 0, 0, (cpu_mod == 3) ? 1 : 0, 0, 0); + return cpu_state.abrt; +} +static int +opMOV_w_imm_a32(uint32_t fetchdat) +{ + uint16_t temp; + fetch_ea_32(fetchdat); + ILLEGAL_ON((rmdat & 0x38) != 0); + SEG_CHECK_WRITE(cpu_state.ea_seg); + temp = getword(); + if (cpu_state.abrt) + return 1; + seteaw(temp); + CLOCK_CYCLES(timing_rr); + PREFETCH_RUN(timing_rr, 4, rmdat, 0, 0, (cpu_mod == 3) ? 1 : 0, 0, 1); + return cpu_state.abrt; +} +static int +opMOV_l_imm_a16(uint32_t fetchdat) +{ + uint32_t temp; + fetch_ea_16(fetchdat); + ILLEGAL_ON((rmdat & 0x38) != 0); + SEG_CHECK_WRITE(cpu_state.ea_seg); + temp = getlong(); + if (cpu_state.abrt) + return 1; + seteal(temp); + CLOCK_CYCLES(timing_rr); + PREFETCH_RUN(timing_rr, 6, rmdat, 0, 0, 0, (cpu_mod == 3) ? 1 : 0, 0); + return cpu_state.abrt; +} +static int +opMOV_l_imm_a32(uint32_t fetchdat) +{ + uint32_t temp; + fetch_ea_32(fetchdat); + ILLEGAL_ON((rmdat & 0x38) != 0); + SEG_CHECK_WRITE(cpu_state.ea_seg); + temp = getlong(); + if (cpu_state.abrt) + return 1; + seteal(temp); + CLOCK_CYCLES(timing_rr); + PREFETCH_RUN(timing_rr, 6, rmdat, 0, 0, 0, (cpu_mod == 3) ? 1 : 0, 1); + return cpu_state.abrt; +} + +static int +opMOV_AL_a16(uint32_t fetchdat) +{ + uint8_t temp; + uint16_t addr = getwordf(); + SEG_CHECK_READ(cpu_state.ea_seg); + CHECK_READ(cpu_state.ea_seg, addr, addr); + temp = readmemb(cpu_state.ea_seg->base, addr); + if (cpu_state.abrt) + return 1; + AL = temp; + CLOCK_CYCLES((is486) ? 1 : 4); + PREFETCH_RUN(4, 3, -1, 1, 0, 0, 0, 0); + return 0; +} +static int +opMOV_AL_a32(uint32_t fetchdat) +{ + uint8_t temp; + uint32_t addr = getlong(); + SEG_CHECK_READ(cpu_state.ea_seg); + CHECK_READ(cpu_state.ea_seg, addr, addr); + temp = readmemb(cpu_state.ea_seg->base, addr); + if (cpu_state.abrt) + return 1; + AL = temp; + CLOCK_CYCLES((is486) ? 1 : 4); + PREFETCH_RUN(4, 5, -1, 1, 0, 0, 0, 1); + return 0; +} +static int +opMOV_AX_a16(uint32_t fetchdat) +{ + uint16_t temp; + uint16_t addr = getwordf(); + SEG_CHECK_READ(cpu_state.ea_seg); + CHECK_READ(cpu_state.ea_seg, addr, addr + 1UL); + temp = readmemw(cpu_state.ea_seg->base, addr); + if (cpu_state.abrt) + return 1; + AX = temp; + CLOCK_CYCLES((is486) ? 1 : 4); + PREFETCH_RUN(4, 3, -1, 1, 0, 0, 0, 0); + return 0; +} +static int +opMOV_AX_a32(uint32_t fetchdat) +{ + uint16_t temp; + uint32_t addr = getlong(); + SEG_CHECK_READ(cpu_state.ea_seg); + CHECK_READ(cpu_state.ea_seg, addr, addr + 1); + temp = readmemw(cpu_state.ea_seg->base, addr); + if (cpu_state.abrt) + return 1; + AX = temp; + CLOCK_CYCLES((is486) ? 1 : 4); + PREFETCH_RUN(4, 5, -1, 1, 0, 0, 0, 1); + return 0; +} +static int +opMOV_EAX_a16(uint32_t fetchdat) +{ + uint32_t temp; + uint16_t addr = getwordf(); + SEG_CHECK_READ(cpu_state.ea_seg); + CHECK_READ(cpu_state.ea_seg, addr, addr + 3UL); + temp = readmeml(cpu_state.ea_seg->base, addr); + if (cpu_state.abrt) + return 1; + EAX = temp; + CLOCK_CYCLES((is486) ? 1 : 4); + PREFETCH_RUN(4, 3, -1, 0, 1, 0, 0, 0); + return 0; +} +static int +opMOV_EAX_a32(uint32_t fetchdat) +{ + uint32_t temp; + uint32_t addr = getlong(); + SEG_CHECK_READ(cpu_state.ea_seg); + CHECK_READ(cpu_state.ea_seg, addr, addr + 3); + temp = readmeml(cpu_state.ea_seg->base, addr); + if (cpu_state.abrt) + return 1; + EAX = temp; + CLOCK_CYCLES((is486) ? 1 : 4); + PREFETCH_RUN(4, 5, -1, 0, 1, 0, 0, 1); + return 0; +} + +static int +opMOV_a16_AL(uint32_t fetchdat) +{ + uint16_t addr = getwordf(); + SEG_CHECK_WRITE(cpu_state.ea_seg); + CHECK_WRITE_COMMON(cpu_state.ea_seg, addr, addr); + writememb(cpu_state.ea_seg->base, addr, AL); + CLOCK_CYCLES((is486) ? 1 : 2); + PREFETCH_RUN(2, 3, -1, 0, 0, 1, 0, 0); + return cpu_state.abrt; +} +static int +opMOV_a32_AL(uint32_t fetchdat) +{ + uint32_t addr = getlong(); + SEG_CHECK_WRITE(cpu_state.ea_seg); + CHECK_WRITE_COMMON(cpu_state.ea_seg, addr, addr); + writememb(cpu_state.ea_seg->base, addr, AL); + CLOCK_CYCLES((is486) ? 1 : 2); + PREFETCH_RUN(2, 5, -1, 0, 0, 1, 0, 1); + return cpu_state.abrt; +} +static int +opMOV_a16_AX(uint32_t fetchdat) +{ + uint16_t addr = getwordf(); + SEG_CHECK_WRITE(cpu_state.ea_seg); + CHECK_WRITE_COMMON(cpu_state.ea_seg, addr, addr + 1UL); + writememw(cpu_state.ea_seg->base, addr, AX); + CLOCK_CYCLES((is486) ? 1 : 2); + PREFETCH_RUN(2, 3, -1, 0, 0, 1, 0, 0); + return cpu_state.abrt; +} +static int +opMOV_a32_AX(uint32_t fetchdat) +{ + uint32_t addr = getlong(); + if (cpu_state.abrt) + return 1; + SEG_CHECK_WRITE(cpu_state.ea_seg); + CHECK_WRITE_COMMON(cpu_state.ea_seg, addr, addr + 1); + writememw(cpu_state.ea_seg->base, addr, AX); + CLOCK_CYCLES((is486) ? 1 : 2); + PREFETCH_RUN(2, 5, -1, 0, 0, 1, 0, 1); + return cpu_state.abrt; +} +static int +opMOV_a16_EAX(uint32_t fetchdat) +{ + uint16_t addr = getwordf(); + SEG_CHECK_WRITE(cpu_state.ea_seg); + CHECK_WRITE_COMMON(cpu_state.ea_seg, addr, addr + 3UL); + writememl(cpu_state.ea_seg->base, addr, EAX); + CLOCK_CYCLES((is486) ? 1 : 2); + PREFETCH_RUN(2, 3, -1, 0, 0, 0, 1, 0); + return cpu_state.abrt; +} +static int +opMOV_a32_EAX(uint32_t fetchdat) +{ + uint32_t addr = getlong(); + if (cpu_state.abrt) + return 1; + SEG_CHECK_WRITE(cpu_state.ea_seg); + CHECK_WRITE_COMMON(cpu_state.ea_seg, addr, addr + 3); + writememl(cpu_state.ea_seg->base, addr, EAX); + CLOCK_CYCLES((is486) ? 1 : 2); + PREFETCH_RUN(2, 5, -1, 0, 0, 0, 1, 1); + return cpu_state.abrt; +} + +static int +opLEA_w_a16(uint32_t fetchdat) +{ + fetch_ea_16(fetchdat); + ILLEGAL_ON(cpu_mod == 3); + cpu_state.regs[cpu_reg].w = cpu_state.eaaddr; + CLOCK_CYCLES(timing_rr); + PREFETCH_RUN(timing_rr, 2, rmdat, 0, 0, 0, 0, 0); + return 0; +} +static int +opLEA_w_a32(uint32_t fetchdat) +{ + fetch_ea_32(fetchdat); + ILLEGAL_ON(cpu_mod == 3); + cpu_state.regs[cpu_reg].w = cpu_state.eaaddr; + CLOCK_CYCLES(timing_rr); + PREFETCH_RUN(timing_rr, 2, rmdat, 0, 0, 0, 0, 1); + return 0; +} + +static int +opLEA_l_a16(uint32_t fetchdat) +{ + fetch_ea_16(fetchdat); + ILLEGAL_ON(cpu_mod == 3); + cpu_state.regs[cpu_reg].l = cpu_state.eaaddr & 0xffff; + CLOCK_CYCLES(timing_rr); + PREFETCH_RUN(timing_rr, 2, rmdat, 0, 0, 0, 0, 0); + return 0; +} +static int +opLEA_l_a32(uint32_t fetchdat) +{ + fetch_ea_32(fetchdat); + ILLEGAL_ON(cpu_mod == 3); + cpu_state.regs[cpu_reg].l = cpu_state.eaaddr; + CLOCK_CYCLES(timing_rr); + PREFETCH_RUN(timing_rr, 2, rmdat, 0, 0, 0, 0, 1); + return 0; +} + +static int +opXLAT_a16(uint32_t fetchdat) +{ + uint32_t addr = (BX + AL) & 0xFFFF; + uint8_t temp; + + SEG_CHECK_READ(cpu_state.ea_seg); + temp = readmemb(cpu_state.ea_seg->base, addr); + if (cpu_state.abrt) + return 1; + AL = temp; + CLOCK_CYCLES(5); + PREFETCH_RUN(5, 1, -1, 1, 0, 0, 0, 0); + return 0; +} +static int +opXLAT_a32(uint32_t fetchdat) +{ + uint32_t addr = EBX + AL; + uint8_t temp; + + SEG_CHECK_READ(cpu_state.ea_seg); + temp = readmemb(cpu_state.ea_seg->base, addr); + if (cpu_state.abrt) + return 1; + AL = temp; + CLOCK_CYCLES(5); + PREFETCH_RUN(5, 1, -1, 1, 0, 0, 0, 1); + return 0; +} + +static int +opMOV_b_r_a16(uint32_t fetchdat) +{ + fetch_ea_16(fetchdat); + if (cpu_mod == 3) { + setr8(cpu_rm, getr8(cpu_reg)); + CLOCK_CYCLES(timing_rr); + PREFETCH_RUN(timing_rr, 2, rmdat, 0, 0, 0, 0, 0); + } else { SEG_CHECK_WRITE(cpu_state.ea_seg); - temp = readmemb(cs,cpu_state.pc); cpu_state.pc++; if (cpu_state.abrt) return 1; - seteab(temp); - CLOCK_CYCLES(timing_rr); - PREFETCH_RUN(timing_rr, 3, rmdat, 0,0,(cpu_mod == 3) ? 1:0,0, 0); - return cpu_state.abrt; + seteab(getr8(cpu_reg)); + CLOCK_CYCLES(is486 ? 1 : 2); + PREFETCH_RUN(2, 2, rmdat, 0, 0, 1, 0, 0); + } + return cpu_state.abrt; } -static int opMOV_b_imm_a32(uint32_t fetchdat) +static int +opMOV_b_r_a32(uint32_t fetchdat) { - uint8_t temp; - fetch_ea_32(fetchdat); - ILLEGAL_ON((rmdat & 0x38) != 0); - SEG_CHECK_WRITE(cpu_state.ea_seg); - temp = getbyte(); if (cpu_state.abrt) return 1; - seteab(temp); + fetch_ea_32(fetchdat); + if (cpu_mod == 3) { + setr8(cpu_rm, getr8(cpu_reg)); CLOCK_CYCLES(timing_rr); - PREFETCH_RUN(timing_rr, 3, rmdat, 0,0,(cpu_mod == 3) ? 1:0,0, 1); - return cpu_state.abrt; + PREFETCH_RUN(timing_rr, 2, rmdat, 0, 0, 0, 0, 1); + } else { + SEG_CHECK_WRITE(cpu_state.ea_seg); + seteab(getr8(cpu_reg)); + CLOCK_CYCLES(is486 ? 1 : 2); + PREFETCH_RUN(2, 2, rmdat, 0, 0, 1, 0, 1); + } + return cpu_state.abrt; +} +static int +opMOV_w_r_a16(uint32_t fetchdat) +{ + fetch_ea_16(fetchdat); + if (cpu_mod == 3) { + cpu_state.regs[cpu_rm].w = cpu_state.regs[cpu_reg].w; + CLOCK_CYCLES(timing_rr); + PREFETCH_RUN(timing_rr, 2, rmdat, 0, 0, 0, 0, 0); + } else { + SEG_CHECK_WRITE(cpu_state.ea_seg); + seteaw(cpu_state.regs[cpu_reg].w); + CLOCK_CYCLES(is486 ? 1 : 2); + PREFETCH_RUN(2, 2, rmdat, 0, 0, 1, 0, 0); + } + return cpu_state.abrt; +} +static int +opMOV_w_r_a32(uint32_t fetchdat) +{ + fetch_ea_32(fetchdat); + if (cpu_mod == 3) { + cpu_state.regs[cpu_rm].w = cpu_state.regs[cpu_reg].w; + CLOCK_CYCLES(timing_rr); + PREFETCH_RUN(timing_rr, 2, rmdat, 0, 0, 0, 0, 1); + } else { + SEG_CHECK_WRITE(cpu_state.ea_seg); + seteaw(cpu_state.regs[cpu_reg].w); + CLOCK_CYCLES(is486 ? 1 : 2); + PREFETCH_RUN(2, 2, rmdat, 0, 0, 1, 0, 1); + } + return cpu_state.abrt; +} +static int +opMOV_l_r_a16(uint32_t fetchdat) +{ + fetch_ea_16(fetchdat); + if (cpu_mod == 3) { + cpu_state.regs[cpu_rm].l = cpu_state.regs[cpu_reg].l; + CLOCK_CYCLES(timing_rr); + PREFETCH_RUN(timing_rr, 2, rmdat, 0, 0, 0, 0, 0); + } else { + SEG_CHECK_WRITE(cpu_state.ea_seg); + seteal(cpu_state.regs[cpu_reg].l); + CLOCK_CYCLES(is486 ? 1 : 2); + PREFETCH_RUN(2, 2, rmdat, 0, 0, 0, 1, 0); + } + return cpu_state.abrt; +} +static int +opMOV_l_r_a32(uint32_t fetchdat) +{ + fetch_ea_32(fetchdat); + if (cpu_mod == 3) { + cpu_state.regs[cpu_rm].l = cpu_state.regs[cpu_reg].l; + CLOCK_CYCLES(timing_rr); + PREFETCH_RUN(timing_rr, 2, rmdat, 0, 0, 0, 0, 1); + } else { + SEG_CHECK_WRITE(cpu_state.ea_seg); + seteal(cpu_state.regs[cpu_reg].l); + CLOCK_CYCLES(is486 ? 1 : 2); + PREFETCH_RUN(2, 2, rmdat, 0, 0, 0, 1, 1); + } + return cpu_state.abrt; } -static int opMOV_w_imm_a16(uint32_t fetchdat) +static int +opMOV_r_b_a16(uint32_t fetchdat) { + fetch_ea_16(fetchdat); + if (cpu_mod == 3) { + setr8(cpu_reg, getr8(cpu_rm)); + CLOCK_CYCLES(timing_rr); + PREFETCH_RUN(timing_rr, 2, rmdat, 0, 0, 0, 0, 0); + } else { + uint8_t temp; + SEG_CHECK_READ(cpu_state.ea_seg); + CHECK_READ(cpu_state.ea_seg, cpu_state.eaaddr, cpu_state.eaaddr); + temp = geteab(); + if (cpu_state.abrt) + return 1; + setr8(cpu_reg, temp); + CLOCK_CYCLES(is486 ? 1 : 4); + PREFETCH_RUN(4, 2, rmdat, 1, 0, 0, 0, 0); + } + return 0; +} +static int +opMOV_r_b_a32(uint32_t fetchdat) +{ + fetch_ea_32(fetchdat); + if (cpu_mod == 3) { + setr8(cpu_reg, getr8(cpu_rm)); + CLOCK_CYCLES(timing_rr); + PREFETCH_RUN(timing_rr, 2, rmdat, 0, 0, 0, 0, 1); + } else { + uint8_t temp; + SEG_CHECK_READ(cpu_state.ea_seg); + CHECK_READ(cpu_state.ea_seg, cpu_state.eaaddr, cpu_state.eaaddr); + temp = geteab(); + if (cpu_state.abrt) + return 1; + setr8(cpu_reg, temp); + CLOCK_CYCLES(is486 ? 1 : 4); + PREFETCH_RUN(4, 2, rmdat, 1, 0, 0, 0, 1); + } + return 0; +} +static int +opMOV_r_w_a16(uint32_t fetchdat) +{ + fetch_ea_16(fetchdat); + if (cpu_mod == 3) { + cpu_state.regs[cpu_reg].w = cpu_state.regs[cpu_rm].w; + CLOCK_CYCLES(timing_rr); + PREFETCH_RUN(timing_rr, 2, rmdat, 0, 0, 0, 0, 0); + } else { uint16_t temp; - fetch_ea_16(fetchdat); - ILLEGAL_ON((rmdat & 0x38) != 0); - SEG_CHECK_WRITE(cpu_state.ea_seg); - temp = getword(); if (cpu_state.abrt) return 1; - seteaw(temp); - CLOCK_CYCLES(timing_rr); - PREFETCH_RUN(timing_rr, 4, rmdat, 0,0,(cpu_mod == 3) ? 1:0,0, 0); - return cpu_state.abrt; + SEG_CHECK_READ(cpu_state.ea_seg); + CHECK_READ(cpu_state.ea_seg, cpu_state.eaaddr, cpu_state.eaaddr + 1); + temp = geteaw(); + if (cpu_state.abrt) + return 1; + cpu_state.regs[cpu_reg].w = temp; + CLOCK_CYCLES((is486) ? 1 : 4); + PREFETCH_RUN(4, 2, rmdat, 1, 0, 0, 0, 0); + } + return 0; } -static int opMOV_w_imm_a32(uint32_t fetchdat) +static int +opMOV_r_w_a32(uint32_t fetchdat) { + fetch_ea_32(fetchdat); + if (cpu_mod == 3) { + cpu_state.regs[cpu_reg].w = cpu_state.regs[cpu_rm].w; + CLOCK_CYCLES(timing_rr); + PREFETCH_RUN(timing_rr, 2, rmdat, 0, 0, 0, 0, 1); + } else { uint16_t temp; - fetch_ea_32(fetchdat); - ILLEGAL_ON((rmdat & 0x38) != 0); - SEG_CHECK_WRITE(cpu_state.ea_seg); - temp = getword(); if (cpu_state.abrt) return 1; - seteaw(temp); - CLOCK_CYCLES(timing_rr); - PREFETCH_RUN(timing_rr, 4, rmdat, 0,0,(cpu_mod == 3) ? 1:0,0, 1); - return cpu_state.abrt; + SEG_CHECK_READ(cpu_state.ea_seg); + CHECK_READ(cpu_state.ea_seg, cpu_state.eaaddr, cpu_state.eaaddr + 1); + temp = geteaw(); + if (cpu_state.abrt) + return 1; + cpu_state.regs[cpu_reg].w = temp; + CLOCK_CYCLES((is486) ? 1 : 4); + PREFETCH_RUN(4, 2, rmdat, 1, 0, 0, 0, 1); + } + return 0; } -static int opMOV_l_imm_a16(uint32_t fetchdat) +static int +opMOV_r_l_a16(uint32_t fetchdat) { + fetch_ea_16(fetchdat); + if (cpu_mod == 3) { + cpu_state.regs[cpu_reg].l = cpu_state.regs[cpu_rm].l; + CLOCK_CYCLES(timing_rr); + PREFETCH_RUN(timing_rr, 2, rmdat, 0, 0, 0, 0, 0); + } else { uint32_t temp; - fetch_ea_16(fetchdat); - ILLEGAL_ON((rmdat & 0x38) != 0); - SEG_CHECK_WRITE(cpu_state.ea_seg); - temp = getlong(); if (cpu_state.abrt) return 1; - seteal(temp); - CLOCK_CYCLES(timing_rr); - PREFETCH_RUN(timing_rr, 6, rmdat, 0,0,0,(cpu_mod == 3) ? 1:0, 0); - return cpu_state.abrt; + SEG_CHECK_READ(cpu_state.ea_seg); + CHECK_READ(cpu_state.ea_seg, cpu_state.eaaddr, cpu_state.eaaddr + 3); + temp = geteal(); + if (cpu_state.abrt) + return 1; + cpu_state.regs[cpu_reg].l = temp; + CLOCK_CYCLES(is486 ? 1 : 4); + PREFETCH_RUN(4, 2, rmdat, 0, 1, 0, 0, 0); + } + return 0; } -static int opMOV_l_imm_a32(uint32_t fetchdat) +static int +opMOV_r_l_a32(uint32_t fetchdat) { + fetch_ea_32(fetchdat); + if (cpu_mod == 3) { + cpu_state.regs[cpu_reg].l = cpu_state.regs[cpu_rm].l; + CLOCK_CYCLES(timing_rr); + PREFETCH_RUN(timing_rr, 2, rmdat, 0, 0, 0, 0, 1); + } else { uint32_t temp; - fetch_ea_32(fetchdat); - ILLEGAL_ON((rmdat & 0x38) != 0); - SEG_CHECK_WRITE(cpu_state.ea_seg); - temp = getlong(); if (cpu_state.abrt) return 1; - seteal(temp); - CLOCK_CYCLES(timing_rr); - PREFETCH_RUN(timing_rr, 6, rmdat, 0,0,0,(cpu_mod == 3) ? 1:0, 1); - return cpu_state.abrt; -} - - -static int opMOV_AL_a16(uint32_t fetchdat) -{ - uint8_t temp; - uint16_t addr = getwordf(); SEG_CHECK_READ(cpu_state.ea_seg); - CHECK_READ(cpu_state.ea_seg, addr, addr); - temp = readmemb(cpu_state.ea_seg->base, addr); if (cpu_state.abrt) return 1; - AL = temp; - CLOCK_CYCLES((is486) ? 1 : 4); - PREFETCH_RUN(4, 3, -1, 1,0,0,0, 0); - return 0; -} -static int opMOV_AL_a32(uint32_t fetchdat) -{ - uint8_t temp; - uint32_t addr = getlong(); - SEG_CHECK_READ(cpu_state.ea_seg); - CHECK_READ(cpu_state.ea_seg, addr, addr); - temp = readmemb(cpu_state.ea_seg->base, addr); if (cpu_state.abrt) return 1; - AL = temp; - CLOCK_CYCLES((is486) ? 1 : 4); - PREFETCH_RUN(4, 5, -1, 1,0,0,0, 1); - return 0; -} -static int opMOV_AX_a16(uint32_t fetchdat) -{ - uint16_t temp; - uint16_t addr = getwordf(); - SEG_CHECK_READ(cpu_state.ea_seg); - CHECK_READ(cpu_state.ea_seg, addr, addr + 1UL); - temp = readmemw(cpu_state.ea_seg->base, addr); if (cpu_state.abrt) return 1; - AX = temp; - CLOCK_CYCLES((is486) ? 1 : 4); - PREFETCH_RUN(4, 3, -1, 1,0,0,0, 0); - return 0; -} -static int opMOV_AX_a32(uint32_t fetchdat) -{ - uint16_t temp; - uint32_t addr = getlong(); - SEG_CHECK_READ(cpu_state.ea_seg); - CHECK_READ(cpu_state.ea_seg, addr, addr+1); - temp = readmemw(cpu_state.ea_seg->base, addr); if (cpu_state.abrt) return 1; - AX = temp; - CLOCK_CYCLES((is486) ? 1 : 4); - PREFETCH_RUN(4, 5, -1, 1,0,0,0, 1); - return 0; -} -static int opMOV_EAX_a16(uint32_t fetchdat) -{ - uint32_t temp; - uint16_t addr = getwordf(); - SEG_CHECK_READ(cpu_state.ea_seg); - CHECK_READ(cpu_state.ea_seg, addr, addr + 3UL); - temp = readmeml(cpu_state.ea_seg->base, addr); if (cpu_state.abrt) return 1; - EAX = temp; - CLOCK_CYCLES((is486) ? 1 : 4); - PREFETCH_RUN(4, 3, -1, 0,1,0,0, 0); - return 0; -} -static int opMOV_EAX_a32(uint32_t fetchdat) -{ - uint32_t temp; - uint32_t addr = getlong(); - SEG_CHECK_READ(cpu_state.ea_seg); - CHECK_READ(cpu_state.ea_seg, addr, addr+3); - temp = readmeml(cpu_state.ea_seg->base, addr); if (cpu_state.abrt) return 1; - EAX = temp; - CLOCK_CYCLES((is486) ? 1 : 4); - PREFETCH_RUN(4, 5, -1, 0,1,0,0, 1); - return 0; + CHECK_READ(cpu_state.ea_seg, cpu_state.eaaddr, cpu_state.eaaddr + 3); + temp = geteal(); + if (cpu_state.abrt) + return 1; + cpu_state.regs[cpu_reg].l = temp; + CLOCK_CYCLES(is486 ? 1 : 4); + PREFETCH_RUN(4, 2, rmdat, 0, 1, 0, 0, 1); + } + return 0; } -static int opMOV_a16_AL(uint32_t fetchdat) -{ - uint16_t addr = getwordf(); - SEG_CHECK_WRITE(cpu_state.ea_seg); - CHECK_WRITE_COMMON(cpu_state.ea_seg, addr, addr); - writememb(cpu_state.ea_seg->base, addr, AL); - CLOCK_CYCLES((is486) ? 1 : 2); - PREFETCH_RUN(2, 3, -1, 0,0,1,0, 0); - return cpu_state.abrt; -} -static int opMOV_a32_AL(uint32_t fetchdat) -{ - uint32_t addr = getlong(); - SEG_CHECK_WRITE(cpu_state.ea_seg); - CHECK_WRITE_COMMON(cpu_state.ea_seg, addr, addr); - writememb(cpu_state.ea_seg->base, addr, AL); - CLOCK_CYCLES((is486) ? 1 : 2); - PREFETCH_RUN(2, 5, -1, 0,0,1,0, 1); - return cpu_state.abrt; -} -static int opMOV_a16_AX(uint32_t fetchdat) -{ - uint16_t addr = getwordf(); - SEG_CHECK_WRITE(cpu_state.ea_seg); - CHECK_WRITE_COMMON(cpu_state.ea_seg, addr, addr + 1UL); - writememw(cpu_state.ea_seg->base, addr, AX); - CLOCK_CYCLES((is486) ? 1 : 2); - PREFETCH_RUN(2, 3, -1, 0,0,1,0, 0); - return cpu_state.abrt; -} -static int opMOV_a32_AX(uint32_t fetchdat) -{ - uint32_t addr = getlong(); if (cpu_state.abrt) return 1; - SEG_CHECK_WRITE(cpu_state.ea_seg); - CHECK_WRITE_COMMON(cpu_state.ea_seg, addr, addr + 1); - writememw(cpu_state.ea_seg->base, addr, AX); - CLOCK_CYCLES((is486) ? 1 : 2); - PREFETCH_RUN(2, 5, -1, 0,0,1,0, 1); - return cpu_state.abrt; -} -static int opMOV_a16_EAX(uint32_t fetchdat) -{ - uint16_t addr = getwordf(); - SEG_CHECK_WRITE(cpu_state.ea_seg); - CHECK_WRITE_COMMON(cpu_state.ea_seg, addr, addr + 3UL); - writememl(cpu_state.ea_seg->base, addr, EAX); - CLOCK_CYCLES((is486) ? 1 : 2); - PREFETCH_RUN(2, 3, -1, 0,0,0,1, 0); - return cpu_state.abrt; -} -static int opMOV_a32_EAX(uint32_t fetchdat) -{ - uint32_t addr = getlong(); if (cpu_state.abrt) return 1; - SEG_CHECK_WRITE(cpu_state.ea_seg); - CHECK_WRITE_COMMON(cpu_state.ea_seg, addr, addr + 3); - writememl(cpu_state.ea_seg->base, addr, EAX); - CLOCK_CYCLES((is486) ? 1 : 2); - PREFETCH_RUN(2, 5, -1, 0,0,0,1, 1); - return cpu_state.abrt; -} - - -static int opLEA_w_a16(uint32_t fetchdat) -{ - fetch_ea_16(fetchdat); - ILLEGAL_ON(cpu_mod == 3); - cpu_state.regs[cpu_reg].w = cpu_state.eaaddr; - CLOCK_CYCLES(timing_rr); - PREFETCH_RUN(timing_rr, 2, rmdat, 0,0,0,0, 0); - return 0; -} -static int opLEA_w_a32(uint32_t fetchdat) -{ - fetch_ea_32(fetchdat); - ILLEGAL_ON(cpu_mod == 3); - cpu_state.regs[cpu_reg].w = cpu_state.eaaddr; - CLOCK_CYCLES(timing_rr); - PREFETCH_RUN(timing_rr, 2, rmdat, 0,0,0,0, 1); - return 0; -} - -static int opLEA_l_a16(uint32_t fetchdat) -{ - fetch_ea_16(fetchdat); - ILLEGAL_ON(cpu_mod == 3); - cpu_state.regs[cpu_reg].l = cpu_state.eaaddr & 0xffff; - CLOCK_CYCLES(timing_rr); - PREFETCH_RUN(timing_rr, 2, rmdat, 0,0,0,0, 0); - return 0; -} -static int opLEA_l_a32(uint32_t fetchdat) -{ - fetch_ea_32(fetchdat); - ILLEGAL_ON(cpu_mod == 3); - cpu_state.regs[cpu_reg].l = cpu_state.eaaddr; - CLOCK_CYCLES(timing_rr); - PREFETCH_RUN(timing_rr, 2, rmdat, 0,0,0,0, 1); - return 0; -} - - - -static int opXLAT_a16(uint32_t fetchdat) -{ - uint32_t addr = (BX + AL)&0xFFFF; - uint8_t temp; - - SEG_CHECK_READ(cpu_state.ea_seg); - temp = readmemb(cpu_state.ea_seg->base, addr); if (cpu_state.abrt) return 1; - AL = temp; - CLOCK_CYCLES(5); - PREFETCH_RUN(5, 1, -1, 1,0,0,0, 0); - return 0; -} -static int opXLAT_a32(uint32_t fetchdat) -{ - uint32_t addr = EBX + AL; - uint8_t temp; - - SEG_CHECK_READ(cpu_state.ea_seg); - temp = readmemb(cpu_state.ea_seg->base, addr); if (cpu_state.abrt) return 1; - AL = temp; - CLOCK_CYCLES(5); - PREFETCH_RUN(5, 1, -1, 1,0,0,0, 1); - return 0; -} - -static int opMOV_b_r_a16(uint32_t fetchdat) -{ - fetch_ea_16(fetchdat); - if (cpu_mod == 3) - { - setr8(cpu_rm, getr8(cpu_reg)); - CLOCK_CYCLES(timing_rr); - PREFETCH_RUN(timing_rr, 2, rmdat, 0,0,0,0, 0); - } - else - { - SEG_CHECK_WRITE(cpu_state.ea_seg); - seteab(getr8(cpu_reg)); - CLOCK_CYCLES(is486 ? 1 : 2); - PREFETCH_RUN(2, 2, rmdat, 0,0,1,0, 0); - } - return cpu_state.abrt; -} -static int opMOV_b_r_a32(uint32_t fetchdat) -{ - fetch_ea_32(fetchdat); - if (cpu_mod == 3) - { - setr8(cpu_rm, getr8(cpu_reg)); - CLOCK_CYCLES(timing_rr); - PREFETCH_RUN(timing_rr, 2, rmdat, 0,0,0,0, 1); - } - else - { - SEG_CHECK_WRITE(cpu_state.ea_seg); - seteab(getr8(cpu_reg)); - CLOCK_CYCLES(is486 ? 1 : 2); - PREFETCH_RUN(2, 2, rmdat, 0,0,1,0, 1); - } - return cpu_state.abrt; -} -static int opMOV_w_r_a16(uint32_t fetchdat) -{ - fetch_ea_16(fetchdat); - if (cpu_mod == 3) - { - cpu_state.regs[cpu_rm].w = cpu_state.regs[cpu_reg].w; - CLOCK_CYCLES(timing_rr); - PREFETCH_RUN(timing_rr, 2, rmdat, 0,0,0,0, 0); - } - else - { - SEG_CHECK_WRITE(cpu_state.ea_seg); - seteaw(cpu_state.regs[cpu_reg].w); - CLOCK_CYCLES(is486 ? 1 : 2); - PREFETCH_RUN(2, 2, rmdat, 0,0,1,0, 0); - } - return cpu_state.abrt; -} -static int opMOV_w_r_a32(uint32_t fetchdat) -{ - fetch_ea_32(fetchdat); - if (cpu_mod == 3) - { - cpu_state.regs[cpu_rm].w = cpu_state.regs[cpu_reg].w; - CLOCK_CYCLES(timing_rr); - PREFETCH_RUN(timing_rr, 2, rmdat, 0,0,0,0, 1); - } - else - { - SEG_CHECK_WRITE(cpu_state.ea_seg); - seteaw(cpu_state.regs[cpu_reg].w); - CLOCK_CYCLES(is486 ? 1 : 2); - PREFETCH_RUN(2, 2, rmdat, 0,0,1,0, 1); - } - return cpu_state.abrt; -} -static int opMOV_l_r_a16(uint32_t fetchdat) -{ - fetch_ea_16(fetchdat); - if (cpu_mod == 3) - { - cpu_state.regs[cpu_rm].l = cpu_state.regs[cpu_reg].l; - CLOCK_CYCLES(timing_rr); - PREFETCH_RUN(timing_rr, 2, rmdat, 0,0,0,0, 0); - } - else - { - SEG_CHECK_WRITE(cpu_state.ea_seg); - seteal(cpu_state.regs[cpu_reg].l); - CLOCK_CYCLES(is486 ? 1 : 2); - PREFETCH_RUN(2, 2, rmdat, 0,0,0,1, 0); - } - return cpu_state.abrt; -} -static int opMOV_l_r_a32(uint32_t fetchdat) -{ - fetch_ea_32(fetchdat); - if (cpu_mod == 3) - { - cpu_state.regs[cpu_rm].l = cpu_state.regs[cpu_reg].l; - CLOCK_CYCLES(timing_rr); - PREFETCH_RUN(timing_rr, 2, rmdat, 0,0,0,0, 1); - } - else - { - SEG_CHECK_WRITE(cpu_state.ea_seg); - seteal(cpu_state.regs[cpu_reg].l); - CLOCK_CYCLES(is486 ? 1 : 2); - PREFETCH_RUN(2, 2, rmdat, 0,0,0,1, 1); - } - return cpu_state.abrt; -} - -static int opMOV_r_b_a16(uint32_t fetchdat) -{ - fetch_ea_16(fetchdat); - if (cpu_mod == 3) - { - setr8(cpu_reg, getr8(cpu_rm)); - CLOCK_CYCLES(timing_rr); - PREFETCH_RUN(timing_rr, 2, rmdat, 0,0,0,0, 0); - } - else - { - uint8_t temp; - SEG_CHECK_READ(cpu_state.ea_seg); - CHECK_READ(cpu_state.ea_seg, cpu_state.eaaddr, cpu_state.eaaddr); - temp = geteab(); if (cpu_state.abrt) return 1; - setr8(cpu_reg, temp); - CLOCK_CYCLES(is486 ? 1 : 4); - PREFETCH_RUN(4, 2, rmdat, 1,0,0,0, 0); - } - return 0; -} -static int opMOV_r_b_a32(uint32_t fetchdat) -{ - fetch_ea_32(fetchdat); - if (cpu_mod == 3) - { - setr8(cpu_reg, getr8(cpu_rm)); - CLOCK_CYCLES(timing_rr); - PREFETCH_RUN(timing_rr, 2, rmdat, 0,0,0,0, 1); - } - else - { - uint8_t temp; - SEG_CHECK_READ(cpu_state.ea_seg); - CHECK_READ(cpu_state.ea_seg, cpu_state.eaaddr, cpu_state.eaaddr); - temp = geteab(); if (cpu_state.abrt) return 1; - setr8(cpu_reg, temp); - CLOCK_CYCLES(is486 ? 1 : 4); - PREFETCH_RUN(4, 2, rmdat, 1,0,0,0, 1); - } - return 0; -} -static int opMOV_r_w_a16(uint32_t fetchdat) -{ - fetch_ea_16(fetchdat); - if (cpu_mod == 3) - { - cpu_state.regs[cpu_reg].w = cpu_state.regs[cpu_rm].w; - CLOCK_CYCLES(timing_rr); - PREFETCH_RUN(timing_rr, 2, rmdat, 0,0,0,0, 0); - } - else - { - uint16_t temp; - SEG_CHECK_READ(cpu_state.ea_seg); - CHECK_READ(cpu_state.ea_seg, cpu_state.eaaddr, cpu_state.eaaddr+1); - temp = geteaw(); if (cpu_state.abrt) return 1; - cpu_state.regs[cpu_reg].w = temp; - CLOCK_CYCLES((is486) ? 1 : 4); - PREFETCH_RUN(4, 2, rmdat, 1,0,0,0, 0); - } - return 0; -} -static int opMOV_r_w_a32(uint32_t fetchdat) -{ - fetch_ea_32(fetchdat); - if (cpu_mod == 3) - { - cpu_state.regs[cpu_reg].w = cpu_state.regs[cpu_rm].w; - CLOCK_CYCLES(timing_rr); - PREFETCH_RUN(timing_rr, 2, rmdat, 0,0,0,0, 1); - } - else - { - uint16_t temp; - SEG_CHECK_READ(cpu_state.ea_seg); - CHECK_READ(cpu_state.ea_seg, cpu_state.eaaddr, cpu_state.eaaddr+1); - temp = geteaw(); if (cpu_state.abrt) return 1; - cpu_state.regs[cpu_reg].w = temp; - CLOCK_CYCLES((is486) ? 1 : 4); - PREFETCH_RUN(4, 2, rmdat, 1,0,0,0, 1); - } - return 0; -} -static int opMOV_r_l_a16(uint32_t fetchdat) -{ - fetch_ea_16(fetchdat); - if (cpu_mod == 3) - { - cpu_state.regs[cpu_reg].l = cpu_state.regs[cpu_rm].l; - CLOCK_CYCLES(timing_rr); - PREFETCH_RUN(timing_rr, 2, rmdat, 0,0,0,0, 0); - } - else - { - uint32_t temp; - SEG_CHECK_READ(cpu_state.ea_seg); - CHECK_READ(cpu_state.ea_seg, cpu_state.eaaddr, cpu_state.eaaddr+3); - temp = geteal(); if (cpu_state.abrt) return 1; - cpu_state.regs[cpu_reg].l = temp; - CLOCK_CYCLES(is486 ? 1 : 4); - PREFETCH_RUN(4, 2, rmdat, 0,1,0,0, 0); - } - return 0; -} -static int opMOV_r_l_a32(uint32_t fetchdat) -{ - fetch_ea_32(fetchdat); - if (cpu_mod == 3) - { - cpu_state.regs[cpu_reg].l = cpu_state.regs[cpu_rm].l; - CLOCK_CYCLES(timing_rr); - PREFETCH_RUN(timing_rr, 2, rmdat, 0,0,0,0, 1); - } - else - { - uint32_t temp; - SEG_CHECK_READ(cpu_state.ea_seg); - CHECK_READ(cpu_state.ea_seg, cpu_state.eaaddr, cpu_state.eaaddr+3); - temp = geteal(); if (cpu_state.abrt) return 1; - cpu_state.regs[cpu_reg].l = temp; - CLOCK_CYCLES(is486 ? 1 : 4); - PREFETCH_RUN(4, 2, rmdat, 0,1,0,0, 1); - } - return 0; -} - -#define opCMOV(condition) \ - static int opCMOV ## condition ## _w_a16(uint32_t fetchdat) \ - { \ - fetch_ea_16(fetchdat); \ - if (cond_ ## condition) \ - { \ - if (cpu_mod == 3) \ - cpu_state.regs[cpu_reg].w = cpu_state.regs[cpu_rm].w; \ - else \ - { \ - uint16_t temp; \ - SEG_CHECK_READ(cpu_state.ea_seg); \ - CHECK_READ(cpu_state.ea_seg, cpu_state.eaaddr, cpu_state.eaaddr+1); \ - temp = geteaw(); if (cpu_state.abrt) return 1; \ - cpu_state.regs[cpu_reg].w = temp; \ - } \ - } \ - CLOCK_CYCLES(1); \ - return 0; \ - } \ - static int opCMOV ## condition ## _w_a32(uint32_t fetchdat) \ - { \ - fetch_ea_32(fetchdat); \ - if (cond_ ## condition) \ - { \ - if (cpu_mod == 3) \ - cpu_state.regs[cpu_reg].w = cpu_state.regs[cpu_rm].w; \ - else \ - { \ - uint16_t temp; \ - SEG_CHECK_READ(cpu_state.ea_seg); \ - CHECK_READ(cpu_state.ea_seg, cpu_state.eaaddr, cpu_state.eaaddr+1); \ - temp = geteaw(); if (cpu_state.abrt) return 1; \ - cpu_state.regs[cpu_reg].w = temp; \ - } \ - } \ - CLOCK_CYCLES(1); \ - return 0; \ - } \ - static int opCMOV ## condition ## _l_a16(uint32_t fetchdat) \ - { \ - fetch_ea_16(fetchdat); \ - if (cond_ ## condition) \ - { \ - if (cpu_mod == 3) \ - cpu_state.regs[cpu_reg].l = cpu_state.regs[cpu_rm].l; \ - else \ - { \ - uint32_t temp; \ - SEG_CHECK_READ(cpu_state.ea_seg); \ - CHECK_READ(cpu_state.ea_seg, cpu_state.eaaddr, cpu_state.eaaddr+3); \ - temp = geteal(); if (cpu_state.abrt) return 1; \ - cpu_state.regs[cpu_reg].l = temp; \ - } \ - } \ - CLOCK_CYCLES(1); \ - return 0; \ - } \ - static int opCMOV ## condition ## _l_a32(uint32_t fetchdat) \ - { \ - fetch_ea_32(fetchdat); \ - if (cond_ ## condition) \ - { \ - if (cpu_mod == 3) \ - cpu_state.regs[cpu_reg].l = cpu_state.regs[cpu_rm].l; \ - else \ - { \ - uint32_t temp; \ - CHECK_READ(cpu_state.ea_seg, cpu_state.eaaddr, cpu_state.eaaddr+3); \ - SEG_CHECK_READ(cpu_state.ea_seg); \ - temp = geteal(); if (cpu_state.abrt) return 1; \ - cpu_state.regs[cpu_reg].l = temp; \ - } \ - } \ - CLOCK_CYCLES(1); \ - return 0; \ +#ifndef OPS_286_386 +# define opCMOV(condition) \ + static int opCMOV##condition##_w_a16(uint32_t fetchdat) \ + { \ + fetch_ea_16(fetchdat); \ + if (cond_##condition) { \ + if (cpu_mod == 3) \ + cpu_state.regs[cpu_reg].w = cpu_state.regs[cpu_rm].w; \ + else { \ + uint16_t temp; \ + SEG_CHECK_READ(cpu_state.ea_seg); \ + CHECK_READ(cpu_state.ea_seg, cpu_state.eaaddr, cpu_state.eaaddr + 1); \ + temp = geteaw(); \ + if (cpu_state.abrt) \ + return 1; \ + cpu_state.regs[cpu_reg].w = temp; \ + } \ + } \ + CLOCK_CYCLES(1); \ + return 0; \ + } \ + static int opCMOV##condition##_w_a32(uint32_t fetchdat) \ + { \ + fetch_ea_32(fetchdat); \ + if (cond_##condition) { \ + if (cpu_mod == 3) \ + cpu_state.regs[cpu_reg].w = cpu_state.regs[cpu_rm].w; \ + else { \ + uint16_t temp; \ + SEG_CHECK_READ(cpu_state.ea_seg); \ + CHECK_READ(cpu_state.ea_seg, cpu_state.eaaddr, cpu_state.eaaddr + 1); \ + temp = geteaw(); \ + if (cpu_state.abrt) \ + return 1; \ + cpu_state.regs[cpu_reg].w = temp; \ + } \ + } \ + CLOCK_CYCLES(1); \ + return 0; \ + } \ + static int opCMOV##condition##_l_a16(uint32_t fetchdat) \ + { \ + fetch_ea_16(fetchdat); \ + if (cond_##condition) { \ + if (cpu_mod == 3) \ + cpu_state.regs[cpu_reg].l = cpu_state.regs[cpu_rm].l; \ + else { \ + uint32_t temp; \ + SEG_CHECK_READ(cpu_state.ea_seg); \ + CHECK_READ(cpu_state.ea_seg, cpu_state.eaaddr, cpu_state.eaaddr + 3); \ + temp = geteal(); \ + if (cpu_state.abrt) \ + return 1; \ + cpu_state.regs[cpu_reg].l = temp; \ + } \ + } \ + CLOCK_CYCLES(1); \ + return 0; \ + } \ + static int opCMOV##condition##_l_a32(uint32_t fetchdat) \ + { \ + fetch_ea_32(fetchdat); \ + if (cond_##condition) { \ + if (cpu_mod == 3) \ + cpu_state.regs[cpu_reg].l = cpu_state.regs[cpu_rm].l; \ + else { \ + uint32_t temp; \ + CHECK_READ(cpu_state.ea_seg, cpu_state.eaaddr, cpu_state.eaaddr + 3); \ + SEG_CHECK_READ(cpu_state.ea_seg); \ + temp = geteal(); \ + if (cpu_state.abrt) \ + return 1; \ + cpu_state.regs[cpu_reg].l = temp; \ + } \ + } \ + CLOCK_CYCLES(1); \ + return 0; \ } +// clang-format off opCMOV(O) opCMOV(NO) opCMOV(B) @@ -782,3 +865,5 @@ opCMOV(L) opCMOV(NL) opCMOV(LE) opCMOV(NLE) +// clang-format on +#endif diff --git a/src/cpu/x86_ops_mov_ctrl.h b/src/cpu/x86_ops_mov_ctrl.h index 28504890c..b0c841f83 100644 --- a/src/cpu/x86_ops_mov_ctrl.h +++ b/src/cpu/x86_ops_mov_ctrl.h @@ -1,369 +1,382 @@ -static int opMOV_r_CRx_a16(uint32_t fetchdat) +static int +opMOV_r_CRx_a16(uint32_t fetchdat) { - if ((CPL || (cpu_state.eflags&VM_FLAG)) && (cr0&1)) - { - x86gpf(NULL, 0); - return 1; - } - fetch_ea_16(fetchdat); - switch (cpu_reg) - { - case 0: - cpu_state.regs[cpu_rm].l = cr0; - if (is486 || isibm486) - cpu_state.regs[cpu_rm].l |= 0x10; /*ET hardwired on 486*/ - else { - if (is386) - cpu_state.regs[cpu_rm].l |=0x7fffffe0; - else - cpu_state.regs[cpu_rm].l |=0x7ffffff0; - } - break; - case 2: - cpu_state.regs[cpu_rm].l = cr2; - break; - case 3: - cpu_state.regs[cpu_rm].l = cr3; - break; - case 4: - if (cpu_has_feature(CPU_FEATURE_CR4)) - { - cpu_state.regs[cpu_rm].l = cr4; - break; - } - default: - cpu_state.pc = cpu_state.oldpc; - x86illegal(); - break; - } - CLOCK_CYCLES(6); - PREFETCH_RUN(6, 2, rmdat, 0,0,0,0, 0); - return 0; -} -static int opMOV_r_CRx_a32(uint32_t fetchdat) -{ - if ((CPL || (cpu_state.eflags&VM_FLAG)) && (cr0&1)) - { - x86gpf(NULL, 0); - return 1; - } - fetch_ea_32(fetchdat); - switch (cpu_reg) - { - case 0: - cpu_state.regs[cpu_rm].l = cr0; - if (is486 || isibm486) - cpu_state.regs[cpu_rm].l |= 0x10; /*ET hardwired on 486*/ - else { - if (is386) - cpu_state.regs[cpu_rm].l |=0x7fffffe0; - else - cpu_state.regs[cpu_rm].l |=0x7ffffff0; - } - break; - case 2: - cpu_state.regs[cpu_rm].l = cr2; - break; - case 3: - cpu_state.regs[cpu_rm].l = cr3; - break; - case 4: - if (cpu_has_feature(CPU_FEATURE_CR4)) - { - cpu_state.regs[cpu_rm].l = cr4; - break; - } - default: - cpu_state.pc = cpu_state.oldpc; - x86illegal(); - break; - } - CLOCK_CYCLES(6); - PREFETCH_RUN(6, 2, rmdat, 0,0,0,0, 1); - return 0; -} - -static int opMOV_r_DRx_a16(uint32_t fetchdat) -{ - if ((CPL || (cpu_state.eflags&VM_FLAG)) && (cr0&1)) - { - x86gpf(NULL, 0); - return 1; - } - fetch_ea_16(fetchdat); - cpu_state.regs[cpu_rm].l = dr[cpu_reg]; - CLOCK_CYCLES(6); - PREFETCH_RUN(6, 2, rmdat, 0,0,0,0, 0); - return 0; -} -static int opMOV_r_DRx_a32(uint32_t fetchdat) -{ - if ((CPL || (cpu_state.eflags&VM_FLAG)) && (cr0&1)) - { - x86gpf(NULL, 0); - return 1; - } - fetch_ea_32(fetchdat); - cpu_state.regs[cpu_rm].l = dr[cpu_reg]; - CLOCK_CYCLES(6); - PREFETCH_RUN(6, 2, rmdat, 0,0,0,0, 1); - return 0; -} - -static int opMOV_CRx_r_a16(uint32_t fetchdat) -{ - uint32_t old_cr0 = cr0; - - if ((CPL || (cpu_state.eflags&VM_FLAG)) && (cr0&1)) - { - x86gpf(NULL,0); - return 1; - } - fetch_ea_16(fetchdat); - switch (cpu_reg) - { - case 0: - if ((cpu_state.regs[cpu_rm].l ^ cr0) & 0x80000001) - flushmmucache(); - /* Make sure CPL = 0 when switching from real mode to protected mode. */ - if ((cpu_state.regs[cpu_rm].l & 0x01) && !(cr0 & 0x01)) - cpu_state.seg_cs.access &= 0x9f; - cr0 = cpu_state.regs[cpu_rm].l; - if (cpu_16bitbus) - cr0 |= 0x10; - if (!(cr0 & 0x80000000)) - mmu_perm=4; - if (hascache && !(cr0 & (1 << 30))) - cpu_cache_int_enabled = 1; - else - cpu_cache_int_enabled = 0; - if (hascache && ((cr0 ^ old_cr0) & (1 << 30))) - cpu_update_waitstates(); - if (cr0 & 1) - cpu_cur_status |= CPU_STATUS_PMODE; + if ((CPL || (cpu_state.eflags & VM_FLAG)) && (cr0 & 1)) { + x86gpf(NULL, 0); + return 1; + } + fetch_ea_16(fetchdat); + switch (cpu_reg) { + case 0: + cpu_state.regs[cpu_rm].l = cr0; + if (is486 || isibm486) + cpu_state.regs[cpu_rm].l |= 0x10; /*ET hardwired on 486*/ + else { + if (is386) + cpu_state.regs[cpu_rm].l |= 0x7fffffe0; else - cpu_cur_status &= ~CPU_STATUS_PMODE; + cpu_state.regs[cpu_rm].l |= 0x7ffffff0; + } + break; + case 2: + cpu_state.regs[cpu_rm].l = cr2; + break; + case 3: + cpu_state.regs[cpu_rm].l = cr3; + break; + case 4: + if (cpu_has_feature(CPU_FEATURE_CR4)) { + cpu_state.regs[cpu_rm].l = cr4; break; - case 2: - cr2 = cpu_state.regs[cpu_rm].l; + } + default: + cpu_state.pc = cpu_state.oldpc; + x86illegal(); + break; + } + CLOCK_CYCLES(6); + PREFETCH_RUN(6, 2, rmdat, 0, 0, 0, 0, 0); + return 0; +} +static int +opMOV_r_CRx_a32(uint32_t fetchdat) +{ + if ((CPL || (cpu_state.eflags & VM_FLAG)) && (cr0 & 1)) { + x86gpf(NULL, 0); + return 1; + } + fetch_ea_32(fetchdat); + switch (cpu_reg) { + case 0: + cpu_state.regs[cpu_rm].l = cr0; + if (is486 || isibm486) + cpu_state.regs[cpu_rm].l |= 0x10; /*ET hardwired on 486*/ + else { + if (is386) + cpu_state.regs[cpu_rm].l |= 0x7fffffe0; + else + cpu_state.regs[cpu_rm].l |= 0x7ffffff0; + } + break; + case 2: + cpu_state.regs[cpu_rm].l = cr2; + break; + case 3: + cpu_state.regs[cpu_rm].l = cr3; + break; + case 4: + if (cpu_has_feature(CPU_FEATURE_CR4)) { + cpu_state.regs[cpu_rm].l = cr4; break; - case 3: - cr3 = cpu_state.regs[cpu_rm].l; + } + default: + cpu_state.pc = cpu_state.oldpc; + x86illegal(); + break; + } + CLOCK_CYCLES(6); + PREFETCH_RUN(6, 2, rmdat, 0, 0, 0, 0, 1); + return 0; +} + +static int +opMOV_r_DRx_a16(uint32_t fetchdat) +{ + if ((CPL || (cpu_state.eflags & VM_FLAG)) && (cr0 & 1)) { + x86gpf(NULL, 0); + return 1; + } + fetch_ea_16(fetchdat); + cpu_state.regs[cpu_rm].l = dr[cpu_reg] | (cpu_reg == 6 ? 0xffff0ff0u : 0); + CLOCK_CYCLES(6); + PREFETCH_RUN(6, 2, rmdat, 0, 0, 0, 0, 0); + return 0; +} +static int +opMOV_r_DRx_a32(uint32_t fetchdat) +{ + if ((CPL || (cpu_state.eflags & VM_FLAG)) && (cr0 & 1)) { + x86gpf(NULL, 0); + return 1; + } + fetch_ea_32(fetchdat); + cpu_state.regs[cpu_rm].l = dr[cpu_reg] | (cpu_reg == 6 ? 0xffff0ff0u : 0); + CLOCK_CYCLES(6); + PREFETCH_RUN(6, 2, rmdat, 0, 0, 0, 0, 1); + return 0; +} + +static int +opMOV_CRx_r_a16(uint32_t fetchdat) +{ + uint32_t old_cr0 = cr0; + + if ((CPL || (cpu_state.eflags & VM_FLAG)) && (cr0 & 1)) { + x86gpf(NULL, 0); + return 1; + } + fetch_ea_16(fetchdat); + switch (cpu_reg) { + case 0: + if ((cpu_state.regs[cpu_rm].l ^ cr0) & 0x80000001) flushmmucache(); + /* Make sure CPL = 0 when switching from real mode to protected mode. */ + if ((cpu_state.regs[cpu_rm].l & 0x01) && !(cr0 & 0x01)) + cpu_state.seg_cs.access &= 0x9f; + cr0 = cpu_state.regs[cpu_rm].l; + if (cpu_16bitbus) + cr0 |= 0x10; + if (!(cr0 & 0x80000000)) + mmu_perm = 4; + if (hascache && !(cr0 & (1 << 30))) + cpu_cache_int_enabled = 1; + else + cpu_cache_int_enabled = 0; + if (hascache && ((cr0 ^ old_cr0) & (1 << 30))) + cpu_update_waitstates(); + if (cr0 & 1) + cpu_cur_status |= CPU_STATUS_PMODE; + else + cpu_cur_status &= ~CPU_STATUS_PMODE; + break; + case 2: + cr2 = cpu_state.regs[cpu_rm].l; + break; + case 3: + cr3 = cpu_state.regs[cpu_rm].l; + flushmmucache(); + break; + case 4: + if (cpu_has_feature(CPU_FEATURE_CR4)) { + if (((cpu_state.regs[cpu_rm].l ^ cr4) & cpu_CR4_mask) & (CR4_PAE | CR4_PGE)) + flushmmucache(); + cr4 = cpu_state.regs[cpu_rm].l & cpu_CR4_mask; break; - case 4: - if (cpu_has_feature(CPU_FEATURE_CR4)) - { - if (((cpu_state.regs[cpu_rm].l ^ cr4) & cpu_CR4_mask) & CR4_PAE) - flushmmucache(); - cr4 = cpu_state.regs[cpu_rm].l & cpu_CR4_mask; - break; - } + } - default: - cpu_state.pc = cpu_state.oldpc; - x86illegal(); - break; - } - CLOCK_CYCLES(10); - PREFETCH_RUN(10, 2, rmdat, 0,0,0,0, 0); - return 0; + default: + cpu_state.pc = cpu_state.oldpc; + x86illegal(); + break; + } + CLOCK_CYCLES(10); + PREFETCH_RUN(10, 2, rmdat, 0, 0, 0, 0, 0); + return 0; } -static int opMOV_CRx_r_a32(uint32_t fetchdat) +static int +opMOV_CRx_r_a32(uint32_t fetchdat) { - uint32_t old_cr0 = cr0; - - if ((CPL || (cpu_state.eflags&VM_FLAG)) && (cr0&1)) - { - x86gpf(NULL,0); - return 1; - } - fetch_ea_32(fetchdat); - switch (cpu_reg) - { - case 0: - if ((cpu_state.regs[cpu_rm].l ^ cr0) & 0x80000001) - flushmmucache(); - /* Make sure CPL = 0 when switching from real mode to protected mode. */ - if ((cpu_state.regs[cpu_rm].l & 0x01) && !(cr0 & 0x01)) - cpu_state.seg_cs.access &= 0x9f; - cr0 = cpu_state.regs[cpu_rm].l; - if (cpu_16bitbus) - cr0 |= 0x10; - if (!(cr0 & 0x80000000)) - mmu_perm=4; - if (hascache && !(cr0 & (1 << 30))) - cpu_cache_int_enabled = 1; - else - cpu_cache_int_enabled = 0; - if (hascache && ((cr0 ^ old_cr0) & (1 << 30))) - cpu_update_waitstates(); - if (cr0 & 1) - cpu_cur_status |= CPU_STATUS_PMODE; - else - cpu_cur_status &= ~CPU_STATUS_PMODE; - break; - case 2: - cr2 = cpu_state.regs[cpu_rm].l; - break; - case 3: - cr3 = cpu_state.regs[cpu_rm].l; + uint32_t old_cr0 = cr0; + + if ((CPL || (cpu_state.eflags & VM_FLAG)) && (cr0 & 1)) { + x86gpf(NULL, 0); + return 1; + } + fetch_ea_32(fetchdat); + switch (cpu_reg) { + case 0: + if ((cpu_state.regs[cpu_rm].l ^ cr0) & 0x80000001) flushmmucache(); + /* Make sure CPL = 0 when switching from real mode to protected mode. */ + if ((cpu_state.regs[cpu_rm].l & 0x01) && !(cr0 & 0x01)) + cpu_state.seg_cs.access &= 0x9f; + cr0 = cpu_state.regs[cpu_rm].l; + if (cpu_16bitbus) + cr0 |= 0x10; + if (!(cr0 & 0x80000000)) + mmu_perm = 4; + if (hascache && !(cr0 & (1 << 30))) + cpu_cache_int_enabled = 1; + else + cpu_cache_int_enabled = 0; + if (hascache && ((cr0 ^ old_cr0) & (1 << 30))) + cpu_update_waitstates(); + if (cr0 & 1) + cpu_cur_status |= CPU_STATUS_PMODE; + else + cpu_cur_status &= ~CPU_STATUS_PMODE; + break; + case 2: + cr2 = cpu_state.regs[cpu_rm].l; + break; + case 3: + cr3 = cpu_state.regs[cpu_rm].l; + flushmmucache(); + break; + case 4: + if (cpu_has_feature(CPU_FEATURE_CR4)) { + if (((cpu_state.regs[cpu_rm].l ^ cr4) & cpu_CR4_mask) & (CR4_PAE | CR4_PGE)) + flushmmucache(); + cr4 = cpu_state.regs[cpu_rm].l & cpu_CR4_mask; break; - case 4: - if (cpu_has_feature(CPU_FEATURE_CR4)) - { - if (((cpu_state.regs[cpu_rm].l ^ cr4) & cpu_CR4_mask) & CR4_PAE) - flushmmucache(); - cr4 = cpu_state.regs[cpu_rm].l & cpu_CR4_mask; + } + + default: + cpu_state.pc = cpu_state.oldpc; + x86illegal(); + break; + } + CLOCK_CYCLES(10); + PREFETCH_RUN(10, 2, rmdat, 0, 0, 0, 0, 1); + return 0; +} + +static int +opMOV_DRx_r_a16(uint32_t fetchdat) +{ + if ((CPL || (cpu_state.eflags & VM_FLAG)) && (cr0 & 1)) { + x86gpf(NULL, 0); + return 1; + } + fetch_ea_16(fetchdat); + dr[cpu_reg] = cpu_state.regs[cpu_rm].l; + CLOCK_CYCLES(6); + PREFETCH_RUN(6, 2, rmdat, 0, 0, 0, 0, 0); + return 0; +} +static int +opMOV_DRx_r_a32(uint32_t fetchdat) +{ + if ((CPL || (cpu_state.eflags & VM_FLAG)) && (cr0 & 1)) { + x86gpf(NULL, 0); + return 1; + } + fetch_ea_16(fetchdat); + dr[cpu_reg] = cpu_state.regs[cpu_rm].l; + CLOCK_CYCLES(6); + PREFETCH_RUN(6, 2, rmdat, 0, 0, 0, 0, 1); + return 0; +} + +static void +opMOV_r_TRx(void) +{ +#if 0 + uint32_t base; + + base = _tr[4] & 0xfffff800; +#endif + + switch (cpu_reg) { + case 3: +#if 0 + pclog("[R] %08X cache = %08X\n", base + cache_index, _tr[3]); +#endif + _tr[3] = *(uint32_t *) &(_cache[cache_index]); + cache_index = (cache_index + 4) & 0xf; + break; + } + cpu_state.regs[cpu_rm].l = _tr[cpu_reg]; + CLOCK_CYCLES(6); +} +static int +opMOV_r_TRx_a16(uint32_t fetchdat) +{ + if ((cpu_s->cpu_type == CPU_PENTIUM) || ((CPL || (cpu_state.eflags & VM_FLAG)) && (cr0 & 1))) { + x86gpf(NULL, 0); + return 1; + } + fetch_ea_16(fetchdat); + opMOV_r_TRx(); + PREFETCH_RUN(6, 2, rmdat, 0, 0, 0, 0, 0); + return 0; +} +static int +opMOV_r_TRx_a32(uint32_t fetchdat) +{ + if ((cpu_s->cpu_type == CPU_PENTIUM) || ((CPL || (cpu_state.eflags & VM_FLAG)) && (cr0 & 1))) { + x86gpf(NULL, 0); + return 1; + } + fetch_ea_32(fetchdat); + opMOV_r_TRx(); + PREFETCH_RUN(6, 2, rmdat, 0, 0, 0, 0, 1); + return 0; +} + +static void +opMOV_TRx_r(void) +{ + uint32_t base; + int i; + int ctl; + + _tr[cpu_reg] = cpu_state.regs[cpu_rm].l; + base = _tr[4] & 0xfffff800; + ctl = _tr[5] & 3; + switch (cpu_reg) { + case 3: +#if 0 + pclog("[W] %08X cache = %08X\n", base + cache_index, _tr[3]); +#endif + *(uint32_t *) &(_cache[cache_index]) = _tr[3]; + cache_index = (cache_index + 4) & 0xf; + break; + case 4: +#if 0 + if (!(cr0 & 1) && !(_tr[5] & (1 << 19))) + pclog("TAG = %08X, DEST = %08X\n", base, base + cache_index - 16); +#endif + break; + case 5: +#if 0 + pclog("[16] EXT = %i (%i), SET = %04X\n", !!(_tr[5] & (1 << 19)), _tr[5] & 0x03, _tr[5] & 0x7f0); +#endif + if (!(_tr[5] & (1 << 19))) { + switch (ctl) { + case 0: +#if 0 + pclog(" Cache fill or read...\n", base); +#endif + break; + case 1: + base += (_tr[5] & 0x7f0); +#if 0 + pclog(" Writing 16 bytes to %08X...\n", base); +#endif + for (i = 0; i < 16; i += 4) + mem_writel_phys(base + i, *(uint32_t *) &(_cache[i])); + break; + case 2: + base += (_tr[5] & 0x7f0); +#if 0 + pclog(" Reading 16 bytes from %08X...\n", base); +#endif + for (i = 0; i < 16; i += 4) + *(uint32_t *) &(_cache[i]) = mem_readl_phys(base + i); + break; + case 3: +#if 0 + pclog(" Cache invalidate/flush...\n", base); +#endif break; } - - default: - cpu_state.pc = cpu_state.oldpc; - x86illegal(); - break; - } - CLOCK_CYCLES(10); - PREFETCH_RUN(10, 2, rmdat, 0,0,0,0, 1); - return 0; + } + break; + } + CLOCK_CYCLES(6); } - -static int opMOV_DRx_r_a16(uint32_t fetchdat) +static int +opMOV_TRx_r_a16(uint32_t fetchdat) { - if ((CPL || (cpu_state.eflags&VM_FLAG)) && (cr0&1)) - { - x86gpf(NULL, 0); - return 1; - } - fetch_ea_16(fetchdat); - dr[cpu_reg] = cpu_state.regs[cpu_rm].l; - CLOCK_CYCLES(6); - PREFETCH_RUN(6, 2, rmdat, 0,0,0,0, 0); - return 0; + if ((cpu_s->cpu_type == CPU_PENTIUM) || ((CPL || (cpu_state.eflags & VM_FLAG)) && (cr0 & 1))) { + x86gpf(NULL, 0); + return 1; + } + fetch_ea_16(fetchdat); + opMOV_TRx_r(); + PREFETCH_RUN(6, 2, rmdat, 0, 0, 0, 0, 0); + return 0; } -static int opMOV_DRx_r_a32(uint32_t fetchdat) +static int +opMOV_TRx_r_a32(uint32_t fetchdat) { - if ((CPL || (cpu_state.eflags&VM_FLAG)) && (cr0&1)) - { - x86gpf(NULL, 0); - return 1; - } - fetch_ea_16(fetchdat); - dr[cpu_reg] = cpu_state.regs[cpu_rm].l; - CLOCK_CYCLES(6); - PREFETCH_RUN(6, 2, rmdat, 0,0,0,0, 1); - return 0; + if ((cpu_s->cpu_type == CPU_PENTIUM) || ((CPL || (cpu_state.eflags & VM_FLAG)) && (cr0 & 1))) { + x86gpf(NULL, 0); + return 1; + } + fetch_ea_32(fetchdat); + opMOV_TRx_r(); + PREFETCH_RUN(6, 2, rmdat, 0, 0, 0, 0, 1); + return 0; } - -static void opMOV_r_TRx(void) -{ - uint32_t base; - - base = _tr[4] & 0xfffff800; - switch (cpu_reg) { - case 3: - pclog("[R] %08X cache = %08X\n", base + cache_index, _tr[3]); - _tr[3] = *(uint32_t *) &(_cache[cache_index]); - cache_index = (cache_index + 4) & 0xf; - break; - } - cpu_state.regs[cpu_rm].l = _tr[cpu_reg]; - CLOCK_CYCLES(6); -} -static int opMOV_r_TRx_a16(uint32_t fetchdat) -{ - if ((cpu_s->cpu_type == CPU_PENTIUM) || ((CPL || (cpu_state.eflags&VM_FLAG)) && (cr0&1))) - { - x86gpf(NULL, 0); - return 1; - } - fetch_ea_16(fetchdat); - opMOV_r_TRx(); - PREFETCH_RUN(6, 2, rmdat, 0,0,0,0, 0); - return 0; -} -static int opMOV_r_TRx_a32(uint32_t fetchdat) -{ - if ((cpu_s->cpu_type == CPU_PENTIUM) || ((CPL || (cpu_state.eflags&VM_FLAG)) && (cr0&1))) - { - x86gpf(NULL, 0); - return 1; - } - fetch_ea_32(fetchdat); - opMOV_r_TRx(); - PREFETCH_RUN(6, 2, rmdat, 0,0,0,0, 1); - return 0; -} - -static void opMOV_TRx_r(void) -{ - uint32_t base; - int i, ctl; - - _tr[cpu_reg] = cpu_state.regs[cpu_rm].l; - base = _tr[4] & 0xfffff800; - ctl = _tr[5] & 3; - switch (cpu_reg) { - case 3: - pclog("[W] %08X cache = %08X\n", base + cache_index, _tr[3]); - *(uint32_t *) &(_cache[cache_index]) = _tr[3]; - cache_index = (cache_index + 4) & 0xf; - break; - case 4: - if (!(cr0 & 1) && !(_tr[5] & (1 << 19))) - pclog("TAG = %08X, DEST = %08X\n", base, base + cache_index - 16); - break; - case 5: - pclog("[16] EXT = %i (%i), SET = %04X\n", !!(_tr[5] & (1 << 19)), _tr[5] & 0x03, _tr[5] & 0x7f0); - if (!(_tr[5] & (1 << 19))) { - switch(ctl) { - case 0: - pclog(" Cache fill or read...\n", base); - break; - case 1: - base += (_tr[5] & 0x7f0); - pclog(" Writing 16 bytes to %08X...\n", base); - for (i = 0; i < 16; i += 4) - mem_writel_phys(base + i, *(uint32_t *) &(_cache[i])); - break; - case 2: - base += (_tr[5] & 0x7f0); - pclog(" Reading 16 bytes from %08X...\n", base); - for (i = 0; i < 16; i += 4) - *(uint32_t *) &(_cache[i]) = mem_readl_phys(base + i); - break; - case 3: - pclog(" Cache invalidate/flush...\n", base); - break; - } - } - break; - } - CLOCK_CYCLES(6); -} -static int opMOV_TRx_r_a16(uint32_t fetchdat) -{ - if ((cpu_s->cpu_type == CPU_PENTIUM) || ((CPL || (cpu_state.eflags&VM_FLAG)) && (cr0&1))) - { - x86gpf(NULL, 0); - return 1; - } - fetch_ea_16(fetchdat); - opMOV_TRx_r(); - PREFETCH_RUN(6, 2, rmdat, 0,0,0,0, 0); - return 0; -} -static int opMOV_TRx_r_a32(uint32_t fetchdat) -{ - if ((cpu_s->cpu_type == CPU_PENTIUM) || ((CPL || (cpu_state.eflags&VM_FLAG)) && (cr0&1))) - { - x86gpf(NULL, 0); - return 1; - } - fetch_ea_32(fetchdat); - opMOV_TRx_r(); - PREFETCH_RUN(6, 2, rmdat, 0,0,0,0, 1); - return 0; -} - diff --git a/src/cpu/x86_ops_mov_seg.h b/src/cpu/x86_ops_mov_seg.h index 02a74eb9c..2a798db5c 100644 --- a/src/cpu/x86_ops_mov_seg.h +++ b/src/cpu/x86_ops_mov_seg.h @@ -1,446 +1,539 @@ -static int opMOV_w_seg_a16(uint32_t fetchdat) +static int +opMOV_w_seg_a16(uint32_t fetchdat) { - fetch_ea_16(fetchdat); - if (cpu_mod != 3) - SEG_CHECK_WRITE(cpu_state.ea_seg); + fetch_ea_16(fetchdat); + if (cpu_mod != 3) + SEG_CHECK_WRITE(cpu_state.ea_seg); - switch (rmdat & 0x38) - { - case 0x00: /*ES*/ + switch (rmdat & 0x38) { + case 0x00: /*ES*/ + seteaw(ES); + break; + case 0x08: /*CS*/ + seteaw(CS); + break; + case 0x18: /*DS*/ + seteaw(DS); + break; + case 0x10: /*SS*/ + seteaw(SS); + break; + case 0x20: /*FS*/ + seteaw(FS); + break; + case 0x28: /*GS*/ + seteaw(GS); + break; + } + + CLOCK_CYCLES((cpu_mod == 3) ? 2 : 3); + PREFETCH_RUN((cpu_mod == 3) ? 2 : 3, 2, rmdat, 0, (cpu_mod == 3) ? 0 : 1, 0, 0, 0); + return cpu_state.abrt; +} +static int +opMOV_w_seg_a32(uint32_t fetchdat) +{ + fetch_ea_32(fetchdat); + if (cpu_mod != 3) + SEG_CHECK_WRITE(cpu_state.ea_seg); + + switch (rmdat & 0x38) { + case 0x00: /*ES*/ + seteaw(ES); + break; + case 0x08: /*CS*/ + seteaw(CS); + break; + case 0x18: /*DS*/ + seteaw(DS); + break; + case 0x10: /*SS*/ + seteaw(SS); + break; + case 0x20: /*FS*/ + seteaw(FS); + break; + case 0x28: /*GS*/ + seteaw(GS); + break; + } + + CLOCK_CYCLES((cpu_mod == 3) ? 2 : 3); + PREFETCH_RUN((cpu_mod == 3) ? 2 : 3, 2, rmdat, 0, (cpu_mod == 3) ? 0 : 1, 0, 0, 1); + return cpu_state.abrt; +} + +static int +opMOV_l_seg_a16(uint32_t fetchdat) +{ + fetch_ea_16(fetchdat); + if (cpu_mod != 3) + SEG_CHECK_WRITE(cpu_state.ea_seg); + + switch (rmdat & 0x38) { + case 0x00: /*ES*/ + if (cpu_mod == 3) + cpu_state.regs[cpu_rm].l = ES; + else seteaw(ES); - break; - case 0x08: /*CS*/ + break; + case 0x08: /*CS*/ + if (cpu_mod == 3) + cpu_state.regs[cpu_rm].l = CS; + else seteaw(CS); - break; - case 0x18: /*DS*/ + break; + case 0x18: /*DS*/ + if (cpu_mod == 3) + cpu_state.regs[cpu_rm].l = DS; + else seteaw(DS); - break; - case 0x10: /*SS*/ + break; + case 0x10: /*SS*/ + if (cpu_mod == 3) + cpu_state.regs[cpu_rm].l = SS; + else seteaw(SS); - break; - case 0x20: /*FS*/ + break; + case 0x20: /*FS*/ + if (cpu_mod == 3) + cpu_state.regs[cpu_rm].l = FS; + else seteaw(FS); - break; - case 0x28: /*GS*/ + break; + case 0x28: /*GS*/ + if (cpu_mod == 3) + cpu_state.regs[cpu_rm].l = GS; + else seteaw(GS); - break; - } - - CLOCK_CYCLES((cpu_mod == 3) ? 2 : 3); - PREFETCH_RUN((cpu_mod == 3) ? 2 : 3, 2, rmdat, 0,(cpu_mod == 3) ? 0:1,0,0, 0); - return cpu_state.abrt; -} -static int opMOV_w_seg_a32(uint32_t fetchdat) -{ - fetch_ea_32(fetchdat); - if (cpu_mod != 3) - SEG_CHECK_WRITE(cpu_state.ea_seg); + break; + } - switch (rmdat & 0x38) - { - case 0x00: /*ES*/ + CLOCK_CYCLES((cpu_mod == 3) ? 2 : 3); + PREFETCH_RUN((cpu_mod == 3) ? 2 : 3, 2, rmdat, 0, (cpu_mod == 3) ? 0 : 1, 0, 0, 0); + return cpu_state.abrt; +} +static int +opMOV_l_seg_a32(uint32_t fetchdat) +{ + fetch_ea_32(fetchdat); + if (cpu_mod != 3) + SEG_CHECK_WRITE(cpu_state.ea_seg); + + switch (rmdat & 0x38) { + case 0x00: /*ES*/ + if (cpu_mod == 3) + cpu_state.regs[cpu_rm].l = ES; + else seteaw(ES); - break; - case 0x08: /*CS*/ + break; + case 0x08: /*CS*/ + if (cpu_mod == 3) + cpu_state.regs[cpu_rm].l = CS; + else seteaw(CS); - break; - case 0x18: /*DS*/ + break; + case 0x18: /*DS*/ + if (cpu_mod == 3) + cpu_state.regs[cpu_rm].l = DS; + else seteaw(DS); - break; - case 0x10: /*SS*/ + break; + case 0x10: /*SS*/ + if (cpu_mod == 3) + cpu_state.regs[cpu_rm].l = SS; + else seteaw(SS); - break; - case 0x20: /*FS*/ + break; + case 0x20: /*FS*/ + if (cpu_mod == 3) + cpu_state.regs[cpu_rm].l = FS; + else seteaw(FS); - break; - case 0x28: /*GS*/ + break; + case 0x28: /*GS*/ + if (cpu_mod == 3) + cpu_state.regs[cpu_rm].l = GS; + else seteaw(GS); - break; - } - - CLOCK_CYCLES((cpu_mod == 3) ? 2 : 3); - PREFETCH_RUN((cpu_mod == 3) ? 2 : 3, 2, rmdat, 0,(cpu_mod == 3) ? 0:1,0,0, 1); - return cpu_state.abrt; + break; + } + + CLOCK_CYCLES((cpu_mod == 3) ? 2 : 3); + PREFETCH_RUN((cpu_mod == 3) ? 2 : 3, 2, rmdat, 0, (cpu_mod == 3) ? 0 : 1, 0, 0, 1); + return cpu_state.abrt; } -static int opMOV_l_seg_a16(uint32_t fetchdat) +static int +opMOV_seg_w_a16(uint32_t fetchdat) { - fetch_ea_16(fetchdat); - if (cpu_mod != 3) - SEG_CHECK_WRITE(cpu_state.ea_seg); + uint16_t new_seg; - switch (rmdat & 0x38) - { - case 0x00: /*ES*/ - if (cpu_mod == 3) cpu_state.regs[cpu_rm].l = ES; - else seteaw(ES); - break; - case 0x08: /*CS*/ - if (cpu_mod == 3) cpu_state.regs[cpu_rm].l = CS; - else seteaw(CS); - break; - case 0x18: /*DS*/ - if (cpu_mod == 3) cpu_state.regs[cpu_rm].l = DS; - else seteaw(DS); - break; - case 0x10: /*SS*/ - if (cpu_mod == 3) cpu_state.regs[cpu_rm].l = SS; - else seteaw(SS); - break; - case 0x20: /*FS*/ - if (cpu_mod == 3) cpu_state.regs[cpu_rm].l = FS; - else seteaw(FS); - break; - case 0x28: /*GS*/ - if (cpu_mod == 3) cpu_state.regs[cpu_rm].l = GS; - else seteaw(GS); - break; - } - - CLOCK_CYCLES((cpu_mod == 3) ? 2 : 3); - PREFETCH_RUN((cpu_mod == 3) ? 2 : 3, 2, rmdat, 0,(cpu_mod == 3) ? 0:1,0,0, 0); - return cpu_state.abrt; -} -static int opMOV_l_seg_a32(uint32_t fetchdat) -{ - fetch_ea_32(fetchdat); - if (cpu_mod != 3) - SEG_CHECK_WRITE(cpu_state.ea_seg); + fetch_ea_16(fetchdat); + if (cpu_mod != 3) + SEG_CHECK_READ(cpu_state.ea_seg); + new_seg = geteaw(); + if (cpu_state.abrt) + return 1; - switch (rmdat & 0x38) - { - case 0x00: /*ES*/ - if (cpu_mod == 3) cpu_state.regs[cpu_rm].l = ES; - else seteaw(ES); - break; - case 0x08: /*CS*/ - if (cpu_mod == 3) cpu_state.regs[cpu_rm].l = CS; - else seteaw(CS); - break; - case 0x18: /*DS*/ - if (cpu_mod == 3) cpu_state.regs[cpu_rm].l = DS; - else seteaw(DS); - break; - case 0x10: /*SS*/ - if (cpu_mod == 3) cpu_state.regs[cpu_rm].l = SS; - else seteaw(SS); - break; - case 0x20: /*FS*/ - if (cpu_mod == 3) cpu_state.regs[cpu_rm].l = FS; - else seteaw(FS); - break; - case 0x28: /*GS*/ - if (cpu_mod == 3) cpu_state.regs[cpu_rm].l = GS; - else seteaw(GS); - break; - } - - CLOCK_CYCLES((cpu_mod == 3) ? 2 : 3); - PREFETCH_RUN((cpu_mod == 3) ? 2 : 3, 2, rmdat, 0,(cpu_mod == 3) ? 0:1,0,0, 1); - return cpu_state.abrt; -} - -static int opMOV_seg_w_a16(uint32_t fetchdat) -{ - uint16_t new_seg; - - fetch_ea_16(fetchdat); - if (cpu_mod != 3) - SEG_CHECK_READ(cpu_state.ea_seg); - new_seg=geteaw(); if (cpu_state.abrt) return 1; - - switch (rmdat & 0x38) - { - case 0x00: /*ES*/ - loadseg(new_seg, &cpu_state.seg_es); - break; - case 0x18: /*DS*/ - loadseg(new_seg, &cpu_state.seg_ds); - break; - case 0x10: /*SS*/ - loadseg(new_seg, &cpu_state.seg_ss); - if (cpu_state.abrt) return 1; - cpu_state.oldpc = cpu_state.pc; - cpu_state.op32 = use32; - cpu_state.ssegs = 0; - cpu_state.ea_seg = &cpu_state.seg_ds; - fetchdat = fastreadl(cs + cpu_state.pc); - cpu_state.pc++; - if (cpu_state.abrt) return 1; - x86_opcodes[(fetchdat & 0xff) | cpu_state.op32](fetchdat >> 8); + switch (rmdat & 0x38) { + case 0x00: /*ES*/ + op_loadseg(new_seg, &cpu_state.seg_es); + break; + case 0x18: /*DS*/ + op_loadseg(new_seg, &cpu_state.seg_ds); + break; + case 0x10: /*SS*/ + op_loadseg(new_seg, &cpu_state.seg_ss); + if (cpu_state.abrt) return 1; - case 0x20: /*FS*/ - loadseg(new_seg, &cpu_state.seg_fs); - break; - case 0x28: /*GS*/ - loadseg(new_seg, &cpu_state.seg_gs); - break; - } - - CLOCK_CYCLES((cpu_mod == 3) ? 2 : 5); - PREFETCH_RUN((cpu_mod == 3) ? 2 : 5, 2, rmdat, 0,(cpu_mod == 3) ? 0:1,0,0, 0); - return cpu_state.abrt; -} -static int opMOV_seg_w_a32(uint32_t fetchdat) -{ - uint16_t new_seg; - - fetch_ea_32(fetchdat); - if (cpu_mod != 3) - SEG_CHECK_READ(cpu_state.ea_seg); - new_seg=geteaw(); if (cpu_state.abrt) return 1; - - switch (rmdat & 0x38) - { - case 0x00: /*ES*/ - loadseg(new_seg, &cpu_state.seg_es); - break; - case 0x18: /*DS*/ - loadseg(new_seg, &cpu_state.seg_ds); - break; - case 0x10: /*SS*/ - loadseg(new_seg, &cpu_state.seg_ss); - if (cpu_state.abrt) return 1; - cpu_state.oldpc = cpu_state.pc; - cpu_state.op32 = use32; - cpu_state.ssegs = 0; - cpu_state.ea_seg = &cpu_state.seg_ds; - fetchdat = fastreadl(cs + cpu_state.pc); - cpu_state.pc++; - if (cpu_state.abrt) return 1; - x86_opcodes[(fetchdat & 0xff) | cpu_state.op32](fetchdat >> 8); + cpu_state.oldpc = cpu_state.pc; + cpu_state.op32 = use32; + cpu_state.ssegs = 0; + cpu_state.ea_seg = &cpu_state.seg_ds; + fetchdat = fastreadl(cs + cpu_state.pc); + cpu_state.pc++; + if (cpu_state.abrt) return 1; - case 0x20: /*FS*/ - loadseg(new_seg, &cpu_state.seg_fs); - break; - case 0x28: /*GS*/ - loadseg(new_seg, &cpu_state.seg_gs); - break; - } - - CLOCK_CYCLES((cpu_mod == 3) ? 2 : 5); - PREFETCH_RUN((cpu_mod == 3) ? 2 : 5, 2, rmdat, 0,(cpu_mod == 3) ? 0:1,0,0, 1); - return cpu_state.abrt; + x86_opcodes[(fetchdat & 0xff) | cpu_state.op32](fetchdat >> 8); + return 1; + case 0x20: /*FS*/ + op_loadseg(new_seg, &cpu_state.seg_fs); + break; + case 0x28: /*GS*/ + op_loadseg(new_seg, &cpu_state.seg_gs); + break; + } + + CLOCK_CYCLES((cpu_mod == 3) ? 2 : 5); + PREFETCH_RUN((cpu_mod == 3) ? 2 : 5, 2, rmdat, 0, (cpu_mod == 3) ? 0 : 1, 0, 0, 0); + return cpu_state.abrt; } - - -static int opLDS_w_a16(uint32_t fetchdat) +static int +opMOV_seg_w_a32(uint32_t fetchdat) { - uint16_t addr, seg; + uint16_t new_seg; - fetch_ea_16(fetchdat); - ILLEGAL_ON(cpu_mod == 3); + fetch_ea_32(fetchdat); + if (cpu_mod != 3) SEG_CHECK_READ(cpu_state.ea_seg); - CHECK_READ(cpu_state.ea_seg, cpu_state.eaaddr, cpu_state. eaaddr + 3); - addr = readmemw(easeg, cpu_state.eaaddr); - seg = readmemw(easeg, cpu_state.eaaddr + 2); if (cpu_state.abrt) return 1; - loadseg(seg, &cpu_state.seg_ds); if (cpu_state.abrt) return 1; - cpu_state.regs[cpu_reg].w = addr; - - CLOCK_CYCLES(7); - PREFETCH_RUN(7, 2, rmdat, 2,0,0,0, 0); - return 0; -} -static int opLDS_w_a32(uint32_t fetchdat) -{ - uint16_t addr, seg; - - fetch_ea_32(fetchdat); - ILLEGAL_ON(cpu_mod == 3); - SEG_CHECK_READ(cpu_state.ea_seg); - CHECK_READ(cpu_state.ea_seg, cpu_state.eaaddr, cpu_state. eaaddr + 3); - addr = readmemw(easeg, cpu_state.eaaddr); - seg = readmemw(easeg, cpu_state.eaaddr + 2); if (cpu_state.abrt) return 1; - loadseg(seg, &cpu_state.seg_ds); if (cpu_state.abrt) return 1; - cpu_state.regs[cpu_reg].w = addr; - - CLOCK_CYCLES(7); - PREFETCH_RUN(7, 2, rmdat, 2,0,0,0, 1); - return 0; -} -static int opLDS_l_a16(uint32_t fetchdat) -{ - uint32_t addr; - uint16_t seg; - - fetch_ea_16(fetchdat); - ILLEGAL_ON(cpu_mod == 3); - SEG_CHECK_READ(cpu_state.ea_seg); - CHECK_READ(cpu_state.ea_seg, cpu_state.eaaddr, cpu_state. eaaddr + 5); - addr = readmeml(easeg, cpu_state.eaaddr); - seg = readmemw(easeg, cpu_state.eaaddr + 4); if (cpu_state.abrt) return 1; - loadseg(seg, &cpu_state.seg_ds); if (cpu_state.abrt) return 1; - cpu_state.regs[cpu_reg].l = addr; - - CLOCK_CYCLES(7); - PREFETCH_RUN(7, 2, rmdat, 1,1,0,0, 0); - return 0; -} -static int opLDS_l_a32(uint32_t fetchdat) -{ - uint32_t addr; - uint16_t seg; - - fetch_ea_32(fetchdat); - ILLEGAL_ON(cpu_mod == 3); - SEG_CHECK_READ(cpu_state.ea_seg); - CHECK_READ(cpu_state.ea_seg, cpu_state.eaaddr, cpu_state. eaaddr + 5); - addr = readmeml(easeg, cpu_state.eaaddr); - seg = readmemw(easeg, cpu_state.eaaddr + 4); if (cpu_state.abrt) return 1; - loadseg(seg, &cpu_state.seg_ds); if (cpu_state.abrt) return 1; - cpu_state.regs[cpu_reg].l = addr; - - CLOCK_CYCLES(7); - PREFETCH_RUN(7, 2, rmdat, 1,1,0,0, 1); - return 0; -} - -static int opLSS_w_a16(uint32_t fetchdat) -{ - uint16_t addr, seg; - - fetch_ea_16(fetchdat); - ILLEGAL_ON(cpu_mod == 3); - SEG_CHECK_READ(cpu_state.ea_seg); - CHECK_READ(cpu_state.ea_seg, cpu_state.eaaddr, cpu_state.eaaddr + 3); - addr = readmemw(easeg, cpu_state.eaaddr); - seg = readmemw(easeg, cpu_state.eaaddr + 2); if (cpu_state.abrt) return 1; - loadseg(seg, &cpu_state.seg_ss); if (cpu_state.abrt) return 1; - cpu_state.regs[cpu_reg].w = addr; - - CLOCK_CYCLES(7); - PREFETCH_RUN(7, 2, rmdat, 2,0,0,0, 0); + new_seg = geteaw(); + if (cpu_state.abrt) return 1; + + switch (rmdat & 0x38) { + case 0x00: /*ES*/ + op_loadseg(new_seg, &cpu_state.seg_es); + break; + case 0x18: /*DS*/ + op_loadseg(new_seg, &cpu_state.seg_ds); + break; + case 0x10: /*SS*/ + op_loadseg(new_seg, &cpu_state.seg_ss); + if (cpu_state.abrt) + return 1; + cpu_state.oldpc = cpu_state.pc; + cpu_state.op32 = use32; + cpu_state.ssegs = 0; + cpu_state.ea_seg = &cpu_state.seg_ds; + fetchdat = fastreadl(cs + cpu_state.pc); + cpu_state.pc++; + if (cpu_state.abrt) + return 1; + x86_opcodes[(fetchdat & 0xff) | cpu_state.op32](fetchdat >> 8); + return 1; + case 0x20: /*FS*/ + op_loadseg(new_seg, &cpu_state.seg_fs); + break; + case 0x28: /*GS*/ + op_loadseg(new_seg, &cpu_state.seg_gs); + break; + } + + CLOCK_CYCLES((cpu_mod == 3) ? 2 : 5); + PREFETCH_RUN((cpu_mod == 3) ? 2 : 5, 2, rmdat, 0, (cpu_mod == 3) ? 0 : 1, 0, 0, 1); + return cpu_state.abrt; } -static int opLSS_w_a32(uint32_t fetchdat) + +static int +opLDS_w_a16(uint32_t fetchdat) { - uint16_t addr, seg; + uint16_t addr; + uint16_t seg; - fetch_ea_32(fetchdat); - ILLEGAL_ON(cpu_mod == 3); - SEG_CHECK_READ(cpu_state.ea_seg); - CHECK_READ(cpu_state.ea_seg, cpu_state.eaaddr, cpu_state.eaaddr + 3); - addr = readmemw(easeg, cpu_state.eaaddr); - seg = readmemw(easeg, cpu_state.eaaddr + 2); if (cpu_state.abrt) return 1; - loadseg(seg, &cpu_state.seg_ss); if (cpu_state.abrt) return 1; - cpu_state.regs[cpu_reg].w = addr; - - CLOCK_CYCLES(7); - PREFETCH_RUN(7, 2, rmdat, 2,0,0,0, 1); + fetch_ea_16(fetchdat); + ILLEGAL_ON(cpu_mod == 3); + SEG_CHECK_READ(cpu_state.ea_seg); + CHECK_READ(cpu_state.ea_seg, cpu_state.eaaddr, cpu_state.eaaddr + 3); + addr = readmemw(easeg, cpu_state.eaaddr); + seg = readmemw(easeg, cpu_state.eaaddr + 2); + if (cpu_state.abrt) return 1; + op_loadseg(seg, &cpu_state.seg_ds); + if (cpu_state.abrt) + return 1; + cpu_state.regs[cpu_reg].w = addr; + + CLOCK_CYCLES(7); + PREFETCH_RUN(7, 2, rmdat, 2, 0, 0, 0, 0); + return 0; } -static int opLSS_l_a16(uint32_t fetchdat) +static int +opLDS_w_a32(uint32_t fetchdat) { - uint32_t addr; - uint16_t seg; + uint16_t addr; + uint16_t seg; - fetch_ea_16(fetchdat); - ILLEGAL_ON(cpu_mod == 3); - SEG_CHECK_READ(cpu_state.ea_seg); - CHECK_READ(cpu_state.ea_seg, cpu_state.eaaddr, cpu_state.eaaddr + 5); - addr = readmeml(easeg, cpu_state.eaaddr); - seg = readmemw(easeg, cpu_state.eaaddr + 4); if (cpu_state.abrt) return 1; - loadseg(seg, &cpu_state.seg_ss); if (cpu_state.abrt) return 1; - cpu_state.regs[cpu_reg].l = addr; - - CLOCK_CYCLES(7); - PREFETCH_RUN(7, 2, rmdat, 2,0,0,0, 0); + fetch_ea_32(fetchdat); + ILLEGAL_ON(cpu_mod == 3); + SEG_CHECK_READ(cpu_state.ea_seg); + CHECK_READ(cpu_state.ea_seg, cpu_state.eaaddr, cpu_state.eaaddr + 3); + addr = readmemw(easeg, cpu_state.eaaddr); + seg = readmemw(easeg, cpu_state.eaaddr + 2); + if (cpu_state.abrt) return 1; + op_loadseg(seg, &cpu_state.seg_ds); + if (cpu_state.abrt) + return 1; + cpu_state.regs[cpu_reg].w = addr; + + CLOCK_CYCLES(7); + PREFETCH_RUN(7, 2, rmdat, 2, 0, 0, 0, 1); + return 0; } -static int opLSS_l_a32(uint32_t fetchdat) +static int +opLDS_l_a16(uint32_t fetchdat) { - uint32_t addr; - uint16_t seg; + uint32_t addr; + uint16_t seg; - fetch_ea_32(fetchdat); - ILLEGAL_ON(cpu_mod == 3); - SEG_CHECK_READ(cpu_state.ea_seg); - CHECK_READ(cpu_state.ea_seg, cpu_state.eaaddr, cpu_state.eaaddr + 5); - addr = readmeml(easeg, cpu_state.eaaddr); - seg = readmemw(easeg, cpu_state.eaaddr + 4); if (cpu_state.abrt) return 1; - loadseg(seg, &cpu_state.seg_ss); if (cpu_state.abrt) return 1; - cpu_state.regs[cpu_reg].l = addr; - - CLOCK_CYCLES(7); - PREFETCH_RUN(7, 2, rmdat, 2,0,0,0, 1); + fetch_ea_16(fetchdat); + ILLEGAL_ON(cpu_mod == 3); + SEG_CHECK_READ(cpu_state.ea_seg); + CHECK_READ(cpu_state.ea_seg, cpu_state.eaaddr, cpu_state.eaaddr + 5); + addr = readmeml(easeg, cpu_state.eaaddr); + seg = readmemw(easeg, cpu_state.eaaddr + 4); + if (cpu_state.abrt) return 1; + op_loadseg(seg, &cpu_state.seg_ds); + if (cpu_state.abrt) + return 1; + cpu_state.regs[cpu_reg].l = addr; + + CLOCK_CYCLES(7); + PREFETCH_RUN(7, 2, rmdat, 1, 1, 0, 0, 0); + return 0; +} +static int +opLDS_l_a32(uint32_t fetchdat) +{ + uint32_t addr; + uint16_t seg; + + fetch_ea_32(fetchdat); + ILLEGAL_ON(cpu_mod == 3); + SEG_CHECK_READ(cpu_state.ea_seg); + CHECK_READ(cpu_state.ea_seg, cpu_state.eaaddr, cpu_state.eaaddr + 5); + addr = readmeml(easeg, cpu_state.eaaddr); + seg = readmemw(easeg, cpu_state.eaaddr + 4); + if (cpu_state.abrt) + return 1; + op_loadseg(seg, &cpu_state.seg_ds); + if (cpu_state.abrt) + return 1; + cpu_state.regs[cpu_reg].l = addr; + + CLOCK_CYCLES(7); + PREFETCH_RUN(7, 2, rmdat, 1, 1, 0, 0, 1); + return 0; } -#define opLsel(name, sel) \ - static int opL ## name ## _w_a16(uint32_t fetchdat) \ - { \ - uint16_t addr, seg; \ - \ - fetch_ea_16(fetchdat); \ - SEG_CHECK_READ(cpu_state.ea_seg); \ - ILLEGAL_ON(cpu_mod == 3); \ - CHECK_READ(cpu_state.ea_seg, cpu_state.eaaddr, cpu_state.eaaddr + 3); \ - addr = readmemw(easeg, cpu_state.eaaddr); \ - seg = readmemw(easeg, cpu_state.eaaddr + 2); if (cpu_state.abrt) return 1; \ - loadseg(seg, &sel); if (cpu_state.abrt) return 1; \ - cpu_state.regs[cpu_reg].w = addr; \ - \ - CLOCK_CYCLES(7); \ - PREFETCH_RUN(7, 2, rmdat, 2,0,0,0, 0); \ - return 0; \ - } \ - \ - static int opL ## name ## _w_a32(uint32_t fetchdat) \ - { \ - uint16_t addr, seg; \ - \ - fetch_ea_32(fetchdat); \ - SEG_CHECK_READ(cpu_state.ea_seg); \ - ILLEGAL_ON(cpu_mod == 3); \ - CHECK_READ(cpu_state.ea_seg, cpu_state.eaaddr, cpu_state.eaaddr + 3); \ - addr = readmemw(easeg, cpu_state.eaaddr); \ - seg = readmemw(easeg, cpu_state.eaaddr + 2); if (cpu_state.abrt) return 1; \ - loadseg(seg, &sel); if (cpu_state.abrt) return 1; \ - cpu_state.regs[cpu_reg].w = addr; \ - \ - CLOCK_CYCLES(7); \ - PREFETCH_RUN(7, 2, rmdat, 2,0,0,0, 1); \ - return 0; \ - } \ - \ - static int opL ## name ## _l_a16(uint32_t fetchdat) \ - { \ - uint32_t addr; \ - uint16_t seg; \ - \ - fetch_ea_16(fetchdat); \ - SEG_CHECK_READ(cpu_state.ea_seg); \ - ILLEGAL_ON(cpu_mod == 3); \ - CHECK_READ(cpu_state.ea_seg, cpu_state.eaaddr, cpu_state.eaaddr + 5); \ - addr = readmeml(easeg, cpu_state.eaaddr); \ - seg = readmemw(easeg, cpu_state.eaaddr + 4); if (cpu_state.abrt) return 1; \ - loadseg(seg, &sel); if (cpu_state.abrt) return 1; \ - cpu_state.regs[cpu_reg].l = addr; \ - \ - CLOCK_CYCLES(7); \ - PREFETCH_RUN(7, 2, rmdat, 1,1,0,0, 0); \ - return 0; \ - } \ - \ - static int opL ## name ## _l_a32(uint32_t fetchdat) \ - { \ - uint32_t addr; \ - uint16_t seg; \ - \ - fetch_ea_32(fetchdat); \ - SEG_CHECK_READ(cpu_state.ea_seg); \ - ILLEGAL_ON(cpu_mod == 3); \ - CHECK_READ(cpu_state.ea_seg, cpu_state.eaaddr, cpu_state.eaaddr + 5); \ - addr = readmeml(easeg, cpu_state.eaaddr); \ - seg = readmemw(easeg, cpu_state.eaaddr + 4); if (cpu_state.abrt) return 1; \ - loadseg(seg, &sel); if (cpu_state.abrt) return 1; \ - cpu_state.regs[cpu_reg].l = addr; \ - \ - CLOCK_CYCLES(7); \ - PREFETCH_RUN(7, 2, rmdat, 1,1,0,0, 1); \ - return 0; \ - } - +static int +opLSS_w_a16(uint32_t fetchdat) +{ + uint16_t addr; + uint16_t seg; + + fetch_ea_16(fetchdat); + ILLEGAL_ON(cpu_mod == 3); + SEG_CHECK_READ(cpu_state.ea_seg); + CHECK_READ(cpu_state.ea_seg, cpu_state.eaaddr, cpu_state.eaaddr + 3); + addr = readmemw(easeg, cpu_state.eaaddr); + seg = readmemw(easeg, cpu_state.eaaddr + 2); + if (cpu_state.abrt) + return 1; + op_loadseg(seg, &cpu_state.seg_ss); + if (cpu_state.abrt) + return 1; + cpu_state.regs[cpu_reg].w = addr; + + CLOCK_CYCLES(7); + PREFETCH_RUN(7, 2, rmdat, 2, 0, 0, 0, 0); + return 1; +} +static int +opLSS_w_a32(uint32_t fetchdat) +{ + uint16_t addr; + uint16_t seg; + + fetch_ea_32(fetchdat); + ILLEGAL_ON(cpu_mod == 3); + SEG_CHECK_READ(cpu_state.ea_seg); + CHECK_READ(cpu_state.ea_seg, cpu_state.eaaddr, cpu_state.eaaddr + 3); + addr = readmemw(easeg, cpu_state.eaaddr); + seg = readmemw(easeg, cpu_state.eaaddr + 2); + if (cpu_state.abrt) + return 1; + op_loadseg(seg, &cpu_state.seg_ss); + if (cpu_state.abrt) + return 1; + cpu_state.regs[cpu_reg].w = addr; + + CLOCK_CYCLES(7); + PREFETCH_RUN(7, 2, rmdat, 2, 0, 0, 0, 1); + return 1; +} +static int +opLSS_l_a16(uint32_t fetchdat) +{ + uint32_t addr; + uint16_t seg; + + fetch_ea_16(fetchdat); + ILLEGAL_ON(cpu_mod == 3); + SEG_CHECK_READ(cpu_state.ea_seg); + CHECK_READ(cpu_state.ea_seg, cpu_state.eaaddr, cpu_state.eaaddr + 5); + addr = readmeml(easeg, cpu_state.eaaddr); + seg = readmemw(easeg, cpu_state.eaaddr + 4); + if (cpu_state.abrt) + return 1; + op_loadseg(seg, &cpu_state.seg_ss); + if (cpu_state.abrt) + return 1; + cpu_state.regs[cpu_reg].l = addr; + + CLOCK_CYCLES(7); + PREFETCH_RUN(7, 2, rmdat, 2, 0, 0, 0, 0); + return 1; +} +static int +opLSS_l_a32(uint32_t fetchdat) +{ + uint32_t addr; + uint16_t seg; + + fetch_ea_32(fetchdat); + ILLEGAL_ON(cpu_mod == 3); + SEG_CHECK_READ(cpu_state.ea_seg); + CHECK_READ(cpu_state.ea_seg, cpu_state.eaaddr, cpu_state.eaaddr + 5); + addr = readmeml(easeg, cpu_state.eaaddr); + seg = readmemw(easeg, cpu_state.eaaddr + 4); + if (cpu_state.abrt) + return 1; + op_loadseg(seg, &cpu_state.seg_ss); + if (cpu_state.abrt) + return 1; + cpu_state.regs[cpu_reg].l = addr; + + CLOCK_CYCLES(7); + PREFETCH_RUN(7, 2, rmdat, 2, 0, 0, 0, 1); + return 1; +} + +#define opLsel(name, sel) \ + static int opL##name##_w_a16(uint32_t fetchdat) \ + { \ + uint16_t addr, seg; \ + \ + fetch_ea_16(fetchdat); \ + SEG_CHECK_READ(cpu_state.ea_seg); \ + ILLEGAL_ON(cpu_mod == 3); \ + CHECK_READ(cpu_state.ea_seg, cpu_state.eaaddr, cpu_state.eaaddr + 3); \ + addr = readmemw(easeg, cpu_state.eaaddr); \ + seg = readmemw(easeg, cpu_state.eaaddr + 2); \ + if (cpu_state.abrt) \ + return 1; \ + op_loadseg(seg, &sel); \ + if (cpu_state.abrt) \ + return 1; \ + cpu_state.regs[cpu_reg].w = addr; \ + \ + CLOCK_CYCLES(7); \ + PREFETCH_RUN(7, 2, rmdat, 2, 0, 0, 0, 0); \ + return 0; \ + } \ + \ + static int opL##name##_w_a32(uint32_t fetchdat) \ + { \ + uint16_t addr, seg; \ + \ + fetch_ea_32(fetchdat); \ + SEG_CHECK_READ(cpu_state.ea_seg); \ + ILLEGAL_ON(cpu_mod == 3); \ + CHECK_READ(cpu_state.ea_seg, cpu_state.eaaddr, cpu_state.eaaddr + 3); \ + addr = readmemw(easeg, cpu_state.eaaddr); \ + seg = readmemw(easeg, cpu_state.eaaddr + 2); \ + if (cpu_state.abrt) \ + return 1; \ + op_loadseg(seg, &sel); \ + if (cpu_state.abrt) \ + return 1; \ + cpu_state.regs[cpu_reg].w = addr; \ + \ + CLOCK_CYCLES(7); \ + PREFETCH_RUN(7, 2, rmdat, 2, 0, 0, 0, 1); \ + return 0; \ + } \ + \ + static int opL##name##_l_a16(uint32_t fetchdat) \ + { \ + uint32_t addr; \ + uint16_t seg; \ + \ + fetch_ea_16(fetchdat); \ + SEG_CHECK_READ(cpu_state.ea_seg); \ + ILLEGAL_ON(cpu_mod == 3); \ + CHECK_READ(cpu_state.ea_seg, cpu_state.eaaddr, cpu_state.eaaddr + 5); \ + addr = readmeml(easeg, cpu_state.eaaddr); \ + seg = readmemw(easeg, cpu_state.eaaddr + 4); \ + if (cpu_state.abrt) \ + return 1; \ + op_loadseg(seg, &sel); \ + if (cpu_state.abrt) \ + return 1; \ + cpu_state.regs[cpu_reg].l = addr; \ + \ + CLOCK_CYCLES(7); \ + PREFETCH_RUN(7, 2, rmdat, 1, 1, 0, 0, 0); \ + return 0; \ + } \ + \ + static int opL##name##_l_a32(uint32_t fetchdat) \ + { \ + uint32_t addr; \ + uint16_t seg; \ + \ + fetch_ea_32(fetchdat); \ + SEG_CHECK_READ(cpu_state.ea_seg); \ + ILLEGAL_ON(cpu_mod == 3); \ + CHECK_READ(cpu_state.ea_seg, cpu_state.eaaddr, cpu_state.eaaddr + 5); \ + addr = readmeml(easeg, cpu_state.eaaddr); \ + seg = readmemw(easeg, cpu_state.eaaddr + 4); \ + if (cpu_state.abrt) \ + return 1; \ + op_loadseg(seg, &sel); \ + if (cpu_state.abrt) \ + return 1; \ + cpu_state.regs[cpu_reg].l = addr; \ + \ + CLOCK_CYCLES(7); \ + PREFETCH_RUN(7, 2, rmdat, 1, 1, 0, 0, 1); \ + return 0; \ + } + +// clang-format off opLsel(ES, cpu_state.seg_es) opLsel(FS, cpu_state.seg_fs) opLsel(GS, cpu_state.seg_gs) + // clang-format on diff --git a/src/cpu/x86_ops_movx.h b/src/cpu/x86_ops_movx.h index 2e4fa2001..1b607fb8b 100644 --- a/src/cpu/x86_ops_movx.h +++ b/src/cpu/x86_ops_movx.h @@ -1,209 +1,251 @@ -static int opMOVZX_w_b_a16(uint32_t fetchdat) +static int +opMOVZX_w_b_a16(uint32_t fetchdat) { - uint8_t temp; - - fetch_ea_16(fetchdat); - if (cpu_mod != 3) - SEG_CHECK_READ(cpu_state.ea_seg); - temp = geteab(); if (cpu_state.abrt) return 1; - cpu_state.regs[cpu_reg].w = (uint16_t)temp; - - CLOCK_CYCLES(3); - PREFETCH_RUN(3, 2, rmdat, (cpu_mod == 3) ? 0:1,0,0,0, 0); - return 0; + uint8_t temp; + + fetch_ea_16(fetchdat); + if (cpu_mod != 3) + SEG_CHECK_READ(cpu_state.ea_seg); + temp = geteab(); + if (cpu_state.abrt) + return 1; + cpu_state.regs[cpu_reg].w = (uint16_t) temp; + + CLOCK_CYCLES(3); + PREFETCH_RUN(3, 2, rmdat, (cpu_mod == 3) ? 0 : 1, 0, 0, 0, 0); + return 0; } -static int opMOVZX_w_b_a32(uint32_t fetchdat) +static int +opMOVZX_w_b_a32(uint32_t fetchdat) { - uint8_t temp; - - fetch_ea_32(fetchdat); - if (cpu_mod != 3) - SEG_CHECK_READ(cpu_state.ea_seg); - temp = geteab(); if (cpu_state.abrt) return 1; - cpu_state.regs[cpu_reg].w = (uint16_t)temp; - - CLOCK_CYCLES(3); - PREFETCH_RUN(3, 2, rmdat, (cpu_mod == 3) ? 0:1,0,0,0, 1); - return 0; + uint8_t temp; + + fetch_ea_32(fetchdat); + if (cpu_mod != 3) + SEG_CHECK_READ(cpu_state.ea_seg); + temp = geteab(); + if (cpu_state.abrt) + return 1; + cpu_state.regs[cpu_reg].w = (uint16_t) temp; + + CLOCK_CYCLES(3); + PREFETCH_RUN(3, 2, rmdat, (cpu_mod == 3) ? 0 : 1, 0, 0, 0, 1); + return 0; } -static int opMOVZX_l_b_a16(uint32_t fetchdat) +static int +opMOVZX_l_b_a16(uint32_t fetchdat) { - uint8_t temp; - - fetch_ea_16(fetchdat); - if (cpu_mod != 3) - SEG_CHECK_READ(cpu_state.ea_seg); - temp = geteab(); if (cpu_state.abrt) return 1; - cpu_state.regs[cpu_reg].l = (uint32_t)temp; - - CLOCK_CYCLES(3); - PREFETCH_RUN(3, 2, rmdat, (cpu_mod == 3) ? 0:1,0,0,0, 0); - return 0; + uint8_t temp; + + fetch_ea_16(fetchdat); + if (cpu_mod != 3) + SEG_CHECK_READ(cpu_state.ea_seg); + temp = geteab(); + if (cpu_state.abrt) + return 1; + cpu_state.regs[cpu_reg].l = (uint32_t) temp; + + CLOCK_CYCLES(3); + PREFETCH_RUN(3, 2, rmdat, (cpu_mod == 3) ? 0 : 1, 0, 0, 0, 0); + return 0; } -static int opMOVZX_l_b_a32(uint32_t fetchdat) +static int +opMOVZX_l_b_a32(uint32_t fetchdat) { - uint8_t temp; - - fetch_ea_32(fetchdat); - if (cpu_mod != 3) - SEG_CHECK_READ(cpu_state.ea_seg); - temp = geteab(); if (cpu_state.abrt) return 1; - cpu_state.regs[cpu_reg].l = (uint32_t)temp; - - CLOCK_CYCLES(3); - PREFETCH_RUN(3, 2, rmdat, (cpu_mod == 3) ? 0:1,0,0,0, 1); - return 0; + uint8_t temp; + + fetch_ea_32(fetchdat); + if (cpu_mod != 3) + SEG_CHECK_READ(cpu_state.ea_seg); + temp = geteab(); + if (cpu_state.abrt) + return 1; + cpu_state.regs[cpu_reg].l = (uint32_t) temp; + + CLOCK_CYCLES(3); + PREFETCH_RUN(3, 2, rmdat, (cpu_mod == 3) ? 0 : 1, 0, 0, 0, 1); + return 0; } -static int opMOVZX_w_w_a16(uint32_t fetchdat) +static int +opMOVZX_w_w_a16(uint32_t fetchdat) { - uint16_t temp; - - fetch_ea_16(fetchdat); - if (cpu_mod != 3) - SEG_CHECK_READ(cpu_state.ea_seg); - temp = geteaw(); if (cpu_state.abrt) return 1; - cpu_state.regs[cpu_reg].w = temp; - - CLOCK_CYCLES(3); - PREFETCH_RUN(3, 2, rmdat, (cpu_mod == 3) ? 0:1,0,0,0, 0); - return 0; + uint16_t temp; + + fetch_ea_16(fetchdat); + if (cpu_mod != 3) + SEG_CHECK_READ(cpu_state.ea_seg); + temp = geteaw(); + if (cpu_state.abrt) + return 1; + cpu_state.regs[cpu_reg].w = temp; + + CLOCK_CYCLES(3); + PREFETCH_RUN(3, 2, rmdat, (cpu_mod == 3) ? 0 : 1, 0, 0, 0, 0); + return 0; } -static int opMOVZX_w_w_a32(uint32_t fetchdat) +static int +opMOVZX_w_w_a32(uint32_t fetchdat) { - uint16_t temp; - - fetch_ea_32(fetchdat); - if (cpu_mod != 3) - SEG_CHECK_READ(cpu_state.ea_seg); - temp = geteaw(); if (cpu_state.abrt) return 1; - cpu_state.regs[cpu_reg].w = temp; - - CLOCK_CYCLES(3); - PREFETCH_RUN(3, 2, rmdat, (cpu_mod == 3) ? 0:1,0,0,0, 1); - return 0; + uint16_t temp; + + fetch_ea_32(fetchdat); + if (cpu_mod != 3) + SEG_CHECK_READ(cpu_state.ea_seg); + temp = geteaw(); + if (cpu_state.abrt) + return 1; + cpu_state.regs[cpu_reg].w = temp; + + CLOCK_CYCLES(3); + PREFETCH_RUN(3, 2, rmdat, (cpu_mod == 3) ? 0 : 1, 0, 0, 0, 1); + return 0; } -static int opMOVZX_l_w_a16(uint32_t fetchdat) +static int +opMOVZX_l_w_a16(uint32_t fetchdat) { - uint16_t temp; - - fetch_ea_16(fetchdat); - if (cpu_mod != 3) - SEG_CHECK_READ(cpu_state.ea_seg); - temp = geteaw(); if (cpu_state.abrt) return 1; - cpu_state.regs[cpu_reg].l = (uint32_t)temp; - - CLOCK_CYCLES(3); - PREFETCH_RUN(3, 2, rmdat, (cpu_mod == 3) ? 0:1,0,0,0, 0); - return 0; + uint16_t temp; + + fetch_ea_16(fetchdat); + if (cpu_mod != 3) + SEG_CHECK_READ(cpu_state.ea_seg); + temp = geteaw(); + if (cpu_state.abrt) + return 1; + cpu_state.regs[cpu_reg].l = (uint32_t) temp; + + CLOCK_CYCLES(3); + PREFETCH_RUN(3, 2, rmdat, (cpu_mod == 3) ? 0 : 1, 0, 0, 0, 0); + return 0; } -static int opMOVZX_l_w_a32(uint32_t fetchdat) +static int +opMOVZX_l_w_a32(uint32_t fetchdat) { - uint16_t temp; - - fetch_ea_32(fetchdat); - if (cpu_mod != 3) - SEG_CHECK_READ(cpu_state.ea_seg); - temp = geteaw(); if (cpu_state.abrt) return 1; - cpu_state.regs[cpu_reg].l = (uint32_t)temp; - - CLOCK_CYCLES(3); - PREFETCH_RUN(3, 2, rmdat, (cpu_mod == 3) ? 0:1,0,0,0, 1); - return 0; + uint16_t temp; + + fetch_ea_32(fetchdat); + if (cpu_mod != 3) + SEG_CHECK_READ(cpu_state.ea_seg); + temp = geteaw(); + if (cpu_state.abrt) + return 1; + cpu_state.regs[cpu_reg].l = (uint32_t) temp; + + CLOCK_CYCLES(3); + PREFETCH_RUN(3, 2, rmdat, (cpu_mod == 3) ? 0 : 1, 0, 0, 0, 1); + return 0; } -static int opMOVSX_w_b_a16(uint32_t fetchdat) +static int +opMOVSX_w_b_a16(uint32_t fetchdat) { - uint8_t temp; - - fetch_ea_16(fetchdat); - if (cpu_mod != 3) - SEG_CHECK_READ(cpu_state.ea_seg); - temp = geteab(); if (cpu_state.abrt) return 1; - cpu_state.regs[cpu_reg].w = (uint16_t)temp; - if (temp & 0x80) - cpu_state.regs[cpu_reg].w |= 0xff00; - - CLOCK_CYCLES(3); - PREFETCH_RUN(3, 2, rmdat, (cpu_mod == 3) ? 0:1,0,0,0, 0); - return 0; + uint8_t temp; + + fetch_ea_16(fetchdat); + if (cpu_mod != 3) + SEG_CHECK_READ(cpu_state.ea_seg); + temp = geteab(); + if (cpu_state.abrt) + return 1; + cpu_state.regs[cpu_reg].w = (uint16_t) temp; + if (temp & 0x80) + cpu_state.regs[cpu_reg].w |= 0xff00; + + CLOCK_CYCLES(3); + PREFETCH_RUN(3, 2, rmdat, (cpu_mod == 3) ? 0 : 1, 0, 0, 0, 0); + return 0; } -static int opMOVSX_w_b_a32(uint32_t fetchdat) +static int +opMOVSX_w_b_a32(uint32_t fetchdat) { - uint8_t temp; - - fetch_ea_32(fetchdat); - if (cpu_mod != 3) - SEG_CHECK_READ(cpu_state.ea_seg); - temp = geteab(); if (cpu_state.abrt) return 1; - cpu_state.regs[cpu_reg].w = (uint16_t)temp; - if (temp & 0x80) - cpu_state.regs[cpu_reg].w |= 0xff00; - - CLOCK_CYCLES(3); - PREFETCH_RUN(3, 2, rmdat, (cpu_mod == 3) ? 0:1,0,0,0, 1); - return 0; + uint8_t temp; + + fetch_ea_32(fetchdat); + if (cpu_mod != 3) + SEG_CHECK_READ(cpu_state.ea_seg); + temp = geteab(); + if (cpu_state.abrt) + return 1; + cpu_state.regs[cpu_reg].w = (uint16_t) temp; + if (temp & 0x80) + cpu_state.regs[cpu_reg].w |= 0xff00; + + CLOCK_CYCLES(3); + PREFETCH_RUN(3, 2, rmdat, (cpu_mod == 3) ? 0 : 1, 0, 0, 0, 1); + return 0; } -static int opMOVSX_l_b_a16(uint32_t fetchdat) +static int +opMOVSX_l_b_a16(uint32_t fetchdat) { - uint8_t temp; - - fetch_ea_16(fetchdat); - if (cpu_mod != 3) - SEG_CHECK_READ(cpu_state.ea_seg); - temp = geteab(); if (cpu_state.abrt) return 1; - cpu_state.regs[cpu_reg].l = (uint32_t)temp; - if (temp & 0x80) - cpu_state.regs[cpu_reg].l |= 0xffffff00; - - CLOCK_CYCLES(3); - PREFETCH_RUN(3, 2, rmdat, (cpu_mod == 3) ? 0:1,0,0,0, 0); - return 0; + uint8_t temp; + + fetch_ea_16(fetchdat); + if (cpu_mod != 3) + SEG_CHECK_READ(cpu_state.ea_seg); + temp = geteab(); + if (cpu_state.abrt) + return 1; + cpu_state.regs[cpu_reg].l = (uint32_t) temp; + if (temp & 0x80) + cpu_state.regs[cpu_reg].l |= 0xffffff00; + + CLOCK_CYCLES(3); + PREFETCH_RUN(3, 2, rmdat, (cpu_mod == 3) ? 0 : 1, 0, 0, 0, 0); + return 0; } -static int opMOVSX_l_b_a32(uint32_t fetchdat) +static int +opMOVSX_l_b_a32(uint32_t fetchdat) { - uint8_t temp; - - fetch_ea_32(fetchdat); - if (cpu_mod != 3) - SEG_CHECK_READ(cpu_state.ea_seg); - temp = geteab(); if (cpu_state.abrt) return 1; - cpu_state.regs[cpu_reg].l = (uint32_t)temp; - if (temp & 0x80) - cpu_state.regs[cpu_reg].l |= 0xffffff00; - - CLOCK_CYCLES(3); - PREFETCH_RUN(3, 2, rmdat, (cpu_mod == 3) ? 0:1,0,0,0, 1); - return 0; + uint8_t temp; + + fetch_ea_32(fetchdat); + if (cpu_mod != 3) + SEG_CHECK_READ(cpu_state.ea_seg); + temp = geteab(); + if (cpu_state.abrt) + return 1; + cpu_state.regs[cpu_reg].l = (uint32_t) temp; + if (temp & 0x80) + cpu_state.regs[cpu_reg].l |= 0xffffff00; + + CLOCK_CYCLES(3); + PREFETCH_RUN(3, 2, rmdat, (cpu_mod == 3) ? 0 : 1, 0, 0, 0, 1); + return 0; } -static int opMOVSX_l_w_a16(uint32_t fetchdat) +static int +opMOVSX_l_w_a16(uint32_t fetchdat) { - uint16_t temp; - - fetch_ea_16(fetchdat); - if (cpu_mod != 3) - SEG_CHECK_READ(cpu_state.ea_seg); - temp = geteaw(); if (cpu_state.abrt) return 1; - cpu_state.regs[cpu_reg].l = (uint32_t)temp; - if (temp & 0x8000) - cpu_state.regs[cpu_reg].l |= 0xffff0000; - - CLOCK_CYCLES(3); - PREFETCH_RUN(3, 2, rmdat, (cpu_mod == 3) ? 0:1,0,0,0, 0); - return 0; + uint16_t temp; + + fetch_ea_16(fetchdat); + if (cpu_mod != 3) + SEG_CHECK_READ(cpu_state.ea_seg); + temp = geteaw(); + if (cpu_state.abrt) + return 1; + cpu_state.regs[cpu_reg].l = (uint32_t) temp; + if (temp & 0x8000) + cpu_state.regs[cpu_reg].l |= 0xffff0000; + + CLOCK_CYCLES(3); + PREFETCH_RUN(3, 2, rmdat, (cpu_mod == 3) ? 0 : 1, 0, 0, 0, 0); + return 0; } -static int opMOVSX_l_w_a32(uint32_t fetchdat) +static int +opMOVSX_l_w_a32(uint32_t fetchdat) { - uint16_t temp; - - fetch_ea_32(fetchdat); - if (cpu_mod != 3) - SEG_CHECK_READ(cpu_state.ea_seg); - temp = geteaw(); if (cpu_state.abrt) return 1; - cpu_state.regs[cpu_reg].l = (uint32_t)temp; - if (temp & 0x8000) - cpu_state.regs[cpu_reg].l |= 0xffff0000; - - CLOCK_CYCLES(3); - PREFETCH_RUN(3, 2, rmdat, (cpu_mod == 3) ? 0:1,0,0,0, 1); - return 0; + uint16_t temp; + + fetch_ea_32(fetchdat); + if (cpu_mod != 3) + SEG_CHECK_READ(cpu_state.ea_seg); + temp = geteaw(); + if (cpu_state.abrt) + return 1; + cpu_state.regs[cpu_reg].l = (uint32_t) temp; + if (temp & 0x8000) + cpu_state.regs[cpu_reg].l |= 0xffff0000; + + CLOCK_CYCLES(3); + PREFETCH_RUN(3, 2, rmdat, (cpu_mod == 3) ? 0 : 1, 0, 0, 0, 1); + return 0; } diff --git a/src/cpu/x86_ops_msr.h b/src/cpu/x86_ops_msr.h index 6624218e4..daae01d84 100644 --- a/src/cpu/x86_ops_msr.h +++ b/src/cpu/x86_ops_msr.h @@ -1,34 +1,33 @@ -static int opRDTSC(uint32_t fetchdat) +static int +opRDTSC(uint32_t fetchdat) { - if (!cpu_has_feature(CPU_FEATURE_RDTSC)) - { - cpu_state.pc = cpu_state.oldpc; - x86illegal(); - return 1; - } - if ((cr4 & CR4_TSD) && CPL) - { - x86gpf("RDTSC when TSD set and CPL != 0", 0); - return 1; - } - EAX = tsc & 0xffffffff; - EDX = tsc >> 32; - CLOCK_CYCLES(1); + if (!cpu_has_feature(CPU_FEATURE_RDTSC)) { + cpu_state.pc = cpu_state.oldpc; + x86illegal(); + return 1; + } + if ((cr4 & CR4_TSD) && CPL) { + x86gpf("RDTSC when TSD set and CPL != 0", 0); + return 1; + } + EAX = tsc & 0xffffffff; + EDX = tsc >> 32; + CLOCK_CYCLES(1); #ifdef USE_DYNAREC - if (cpu_use_dynarec) - update_tsc(); + if (cpu_use_dynarec) + update_tsc(); #endif - return 0; + return 0; } -static int opRDPMC(uint32_t fetchdat) +static int +opRDPMC(uint32_t fetchdat) { - if (ECX > 1 || (!(cr4 & CR4_PCE) && (cr0 & 1) && CPL)) - { - x86gpf("RDPMC not allowed", 0); - return 1; - } - EAX = EDX = 0; - CLOCK_CYCLES(1); - return 0; + if (ECX > 1 || (!(cr4 & CR4_PCE) && (cr0 & 1) && CPL)) { + x86gpf("RDPMC not allowed", 0); + return 1; + } + EAX = EDX = 0; + CLOCK_CYCLES(1); + return 0; } diff --git a/src/cpu/x86_ops_mul.h b/src/cpu/x86_ops_mul.h index a96ce54a2..aa7526e75 100644 --- a/src/cpu/x86_ops_mul.h +++ b/src/cpu/x86_ops_mul.h @@ -1,264 +1,345 @@ -static int opIMUL_w_iw_a16(uint32_t fetchdat) +static int +opIMUL_w_iw_a16(uint32_t fetchdat) { - int32_t templ; - int16_t tempw, tempw2; - - fetch_ea_16(fetchdat); - if (cpu_mod != 3) - SEG_CHECK_READ(cpu_state.ea_seg); - - tempw = geteaw(); if (cpu_state.abrt) return 1; - tempw2 = getword(); if (cpu_state.abrt) return 1; - - templ = ((int)tempw) * ((int)tempw2); - flags_rebuild(); - if ((templ >> 15) != 0 && (templ >> 15) != -1) cpu_state.flags |= C_FLAG | V_FLAG; - else cpu_state.flags &= ~(C_FLAG | V_FLAG); - cpu_state.regs[cpu_reg].w = templ & 0xffff; + int32_t templ; + int16_t tempw; + int16_t tempw2; - CLOCK_CYCLES((cpu_mod == 3) ? 14 : 17); - PREFETCH_RUN((cpu_mod == 3) ? 14 : 17, 4, rmdat, 1,0,0,0, 0); - return 0; + fetch_ea_16(fetchdat); + if (cpu_mod != 3) + SEG_CHECK_READ(cpu_state.ea_seg); + + tempw = geteaw(); + if (cpu_state.abrt) + return 1; + tempw2 = getword(); + if (cpu_state.abrt) + return 1; + + templ = ((int) tempw) * ((int) tempw2); + flags_rebuild(); + if ((templ >> 15) != 0 && (templ >> 15) != -1) + cpu_state.flags |= C_FLAG | V_FLAG; + else + cpu_state.flags &= ~(C_FLAG | V_FLAG); + cpu_state.regs[cpu_reg].w = templ & 0xffff; + + CLOCK_CYCLES((cpu_mod == 3) ? 14 : 17); + PREFETCH_RUN((cpu_mod == 3) ? 14 : 17, 4, rmdat, 1, 0, 0, 0, 0); + return 0; } -static int opIMUL_w_iw_a32(uint32_t fetchdat) +static int +opIMUL_w_iw_a32(uint32_t fetchdat) { - int32_t templ; - int16_t tempw, tempw2; - - fetch_ea_32(fetchdat); - if (cpu_mod != 3) - SEG_CHECK_READ(cpu_state.ea_seg); - - tempw = geteaw(); if (cpu_state.abrt) return 1; - tempw2 = getword(); if (cpu_state.abrt) return 1; - - templ = ((int)tempw) * ((int)tempw2); - flags_rebuild(); - if ((templ >> 15) != 0 && (templ >> 15) != -1) cpu_state.flags |= C_FLAG | V_FLAG; - else cpu_state.flags &= ~(C_FLAG | V_FLAG); - cpu_state.regs[cpu_reg].w = templ & 0xffff; + int32_t templ; + int16_t tempw; + int16_t tempw2; - CLOCK_CYCLES((cpu_mod == 3) ? 14 : 17); - PREFETCH_RUN((cpu_mod == 3) ? 14 : 17, 4, rmdat, 1,0,0,0, 1); - return 0; + fetch_ea_32(fetchdat); + if (cpu_mod != 3) + SEG_CHECK_READ(cpu_state.ea_seg); + + tempw = geteaw(); + if (cpu_state.abrt) + return 1; + tempw2 = getword(); + if (cpu_state.abrt) + return 1; + + templ = ((int) tempw) * ((int) tempw2); + flags_rebuild(); + if ((templ >> 15) != 0 && (templ >> 15) != -1) + cpu_state.flags |= C_FLAG | V_FLAG; + else + cpu_state.flags &= ~(C_FLAG | V_FLAG); + cpu_state.regs[cpu_reg].w = templ & 0xffff; + + CLOCK_CYCLES((cpu_mod == 3) ? 14 : 17); + PREFETCH_RUN((cpu_mod == 3) ? 14 : 17, 4, rmdat, 1, 0, 0, 0, 1); + return 0; } -static int opIMUL_l_il_a16(uint32_t fetchdat) +static int +opIMUL_l_il_a16(uint32_t fetchdat) { - int64_t temp64; - int32_t templ, templ2; - - fetch_ea_16(fetchdat); - if (cpu_mod != 3) - SEG_CHECK_READ(cpu_state.ea_seg); - - templ = geteal(); if (cpu_state.abrt) return 1; - templ2 = getlong(); if (cpu_state.abrt) return 1; - - temp64 = ((int64_t)templ) * ((int64_t)templ2); - flags_rebuild(); - if ((temp64 >> 31) != 0 && (temp64 >> 31) != -1) cpu_state.flags |= C_FLAG | V_FLAG; - else cpu_state.flags &= ~(C_FLAG | V_FLAG); - cpu_state.regs[cpu_reg].l = temp64 & 0xffffffff; - - CLOCK_CYCLES(25); - PREFETCH_RUN(25, 6, rmdat, 0,1,0,0, 0); - return 0; + int64_t temp64; + int32_t templ; + int32_t templ2; + + fetch_ea_16(fetchdat); + if (cpu_mod != 3) + SEG_CHECK_READ(cpu_state.ea_seg); + + templ = geteal(); + if (cpu_state.abrt) + return 1; + templ2 = getlong(); + if (cpu_state.abrt) + return 1; + + temp64 = ((int64_t) templ) * ((int64_t) templ2); + flags_rebuild(); + if ((temp64 >> 31) != 0 && (temp64 >> 31) != -1) + cpu_state.flags |= C_FLAG | V_FLAG; + else + cpu_state.flags &= ~(C_FLAG | V_FLAG); + cpu_state.regs[cpu_reg].l = temp64 & 0xffffffff; + + CLOCK_CYCLES(25); + PREFETCH_RUN(25, 6, rmdat, 0, 1, 0, 0, 0); + return 0; } -static int opIMUL_l_il_a32(uint32_t fetchdat) +static int +opIMUL_l_il_a32(uint32_t fetchdat) { - int64_t temp64; - int32_t templ, templ2; - - fetch_ea_32(fetchdat); - if (cpu_mod != 3) - SEG_CHECK_READ(cpu_state.ea_seg); - - templ = geteal(); if (cpu_state.abrt) return 1; - templ2 = getlong(); if (cpu_state.abrt) return 1; - - temp64 = ((int64_t)templ) * ((int64_t)templ2); - flags_rebuild(); - if ((temp64 >> 31) != 0 && (temp64 >> 31) != -1) cpu_state.flags |= C_FLAG | V_FLAG; - else cpu_state.flags &= ~(C_FLAG | V_FLAG); - cpu_state.regs[cpu_reg].l = temp64 & 0xffffffff; - - CLOCK_CYCLES(25); - PREFETCH_RUN(25, 6, rmdat, 0,1,0,0, 1); - return 0; + int64_t temp64; + int32_t templ; + int32_t templ2; + + fetch_ea_32(fetchdat); + if (cpu_mod != 3) + SEG_CHECK_READ(cpu_state.ea_seg); + + templ = geteal(); + if (cpu_state.abrt) + return 1; + templ2 = getlong(); + if (cpu_state.abrt) + return 1; + + temp64 = ((int64_t) templ) * ((int64_t) templ2); + flags_rebuild(); + if ((temp64 >> 31) != 0 && (temp64 >> 31) != -1) + cpu_state.flags |= C_FLAG | V_FLAG; + else + cpu_state.flags &= ~(C_FLAG | V_FLAG); + cpu_state.regs[cpu_reg].l = temp64 & 0xffffffff; + + CLOCK_CYCLES(25); + PREFETCH_RUN(25, 6, rmdat, 0, 1, 0, 0, 1); + return 0; } -static int opIMUL_w_ib_a16(uint32_t fetchdat) +static int +opIMUL_w_ib_a16(uint32_t fetchdat) { - int32_t templ; - int16_t tempw, tempw2; - - fetch_ea_16(fetchdat); - if (cpu_mod != 3) - SEG_CHECK_READ(cpu_state.ea_seg); - - tempw = geteaw(); if (cpu_state.abrt) return 1; - tempw2 = getbyte(); if (cpu_state.abrt) return 1; - if (tempw2 & 0x80) tempw2 |= 0xff00; - - templ = ((int)tempw) * ((int)tempw2); - flags_rebuild(); - if ((templ >> 15) != 0 && (templ >> 15) != -1) cpu_state.flags |= C_FLAG | V_FLAG; - else cpu_state.flags &= ~(C_FLAG | V_FLAG); - cpu_state.regs[cpu_reg].w = templ & 0xffff; - - CLOCK_CYCLES((cpu_mod == 3) ? 14 : 17); - PREFETCH_RUN((cpu_mod == 3) ? 14 : 17, 3, rmdat, 1,0,0,0, 0); - return 0; + int32_t templ; + int16_t tempw; + int16_t tempw2; + + fetch_ea_16(fetchdat); + if (cpu_mod != 3) + SEG_CHECK_READ(cpu_state.ea_seg); + + tempw = geteaw(); + if (cpu_state.abrt) + return 1; + tempw2 = getbyte(); + if (cpu_state.abrt) + return 1; + if (tempw2 & 0x80) + tempw2 |= 0xff00; + + templ = ((int) tempw) * ((int) tempw2); + flags_rebuild(); + if ((templ >> 15) != 0 && (templ >> 15) != -1) + cpu_state.flags |= C_FLAG | V_FLAG; + else + cpu_state.flags &= ~(C_FLAG | V_FLAG); + cpu_state.regs[cpu_reg].w = templ & 0xffff; + + CLOCK_CYCLES((cpu_mod == 3) ? 14 : 17); + PREFETCH_RUN((cpu_mod == 3) ? 14 : 17, 3, rmdat, 1, 0, 0, 0, 0); + return 0; } -static int opIMUL_w_ib_a32(uint32_t fetchdat) +static int +opIMUL_w_ib_a32(uint32_t fetchdat) { - int32_t templ; - int16_t tempw, tempw2; - - fetch_ea_32(fetchdat); - if (cpu_mod != 3) - SEG_CHECK_READ(cpu_state.ea_seg); - - tempw = geteaw(); if (cpu_state.abrt) return 1; - tempw2 = getbyte(); if (cpu_state.abrt) return 1; - if (tempw2 & 0x80) tempw2 |= 0xff00; - - templ = ((int)tempw) * ((int)tempw2); - flags_rebuild(); - if ((templ >> 15) != 0 && (templ >> 15) != -1) cpu_state.flags |= C_FLAG | V_FLAG; - else cpu_state.flags &= ~(C_FLAG | V_FLAG); - cpu_state.regs[cpu_reg].w = templ & 0xffff; - - CLOCK_CYCLES((cpu_mod == 3) ? 14 : 17); - PREFETCH_RUN((cpu_mod == 3) ? 14 : 17, 3, rmdat, 1,0,0,0, 1); - return 0; + int32_t templ; + int16_t tempw; + int16_t tempw2; + + fetch_ea_32(fetchdat); + if (cpu_mod != 3) + SEG_CHECK_READ(cpu_state.ea_seg); + + tempw = geteaw(); + if (cpu_state.abrt) + return 1; + tempw2 = getbyte(); + if (cpu_state.abrt) + return 1; + if (tempw2 & 0x80) + tempw2 |= 0xff00; + + templ = ((int) tempw) * ((int) tempw2); + flags_rebuild(); + if ((templ >> 15) != 0 && (templ >> 15) != -1) + cpu_state.flags |= C_FLAG | V_FLAG; + else + cpu_state.flags &= ~(C_FLAG | V_FLAG); + cpu_state.regs[cpu_reg].w = templ & 0xffff; + + CLOCK_CYCLES((cpu_mod == 3) ? 14 : 17); + PREFETCH_RUN((cpu_mod == 3) ? 14 : 17, 3, rmdat, 1, 0, 0, 0, 1); + return 0; } -static int opIMUL_l_ib_a16(uint32_t fetchdat) +static int +opIMUL_l_ib_a16(uint32_t fetchdat) { - int64_t temp64; - int32_t templ, templ2; + int64_t temp64; + int32_t templ; + int32_t templ2; - fetch_ea_16(fetchdat); - if (cpu_mod != 3) - SEG_CHECK_READ(cpu_state.ea_seg); - - templ = geteal(); if (cpu_state.abrt) return 1; - templ2 = getbyte(); if (cpu_state.abrt) return 1; - if (templ2 & 0x80) templ2 |= 0xffffff00; - - temp64 = ((int64_t)templ)*((int64_t)templ2); - flags_rebuild(); - if ((temp64 >> 31) != 0 && (temp64 >> 31) != -1) cpu_state.flags |= C_FLAG | V_FLAG; - else cpu_state.flags &= ~(C_FLAG | V_FLAG); - cpu_state.regs[cpu_reg].l = temp64 & 0xffffffff; - - CLOCK_CYCLES(20); - PREFETCH_RUN(20, 3, rmdat, 0,1,0,0, 0); - return 0; + fetch_ea_16(fetchdat); + if (cpu_mod != 3) + SEG_CHECK_READ(cpu_state.ea_seg); + + templ = geteal(); + if (cpu_state.abrt) + return 1; + templ2 = getbyte(); + if (cpu_state.abrt) + return 1; + if (templ2 & 0x80) + templ2 |= 0xffffff00; + + temp64 = ((int64_t) templ) * ((int64_t) templ2); + flags_rebuild(); + if ((temp64 >> 31) != 0 && (temp64 >> 31) != -1) + cpu_state.flags |= C_FLAG | V_FLAG; + else + cpu_state.flags &= ~(C_FLAG | V_FLAG); + cpu_state.regs[cpu_reg].l = temp64 & 0xffffffff; + + CLOCK_CYCLES(20); + PREFETCH_RUN(20, 3, rmdat, 0, 1, 0, 0, 0); + return 0; } -static int opIMUL_l_ib_a32(uint32_t fetchdat) +static int +opIMUL_l_ib_a32(uint32_t fetchdat) { - int64_t temp64; - int32_t templ, templ2; + int64_t temp64; + int32_t templ; + int32_t templ2; - fetch_ea_32(fetchdat); - if (cpu_mod != 3) - SEG_CHECK_READ(cpu_state.ea_seg); - - templ = geteal(); if (cpu_state.abrt) return 1; - templ2 = getbyte(); if (cpu_state.abrt) return 1; - if (templ2 & 0x80) templ2 |= 0xffffff00; - - temp64 = ((int64_t)templ)*((int64_t)templ2); - flags_rebuild(); - if ((temp64 >> 31) != 0 && (temp64 >> 31) != -1) cpu_state.flags |= C_FLAG | V_FLAG; - else cpu_state.flags &= ~(C_FLAG | V_FLAG); - cpu_state.regs[cpu_reg].l = temp64 & 0xffffffff; - - CLOCK_CYCLES(20); - PREFETCH_RUN(20, 3, rmdat, 0,1,0,0, 1); - return 0; + fetch_ea_32(fetchdat); + if (cpu_mod != 3) + SEG_CHECK_READ(cpu_state.ea_seg); + + templ = geteal(); + if (cpu_state.abrt) + return 1; + templ2 = getbyte(); + if (cpu_state.abrt) + return 1; + if (templ2 & 0x80) + templ2 |= 0xffffff00; + + temp64 = ((int64_t) templ) * ((int64_t) templ2); + flags_rebuild(); + if ((temp64 >> 31) != 0 && (temp64 >> 31) != -1) + cpu_state.flags |= C_FLAG | V_FLAG; + else + cpu_state.flags &= ~(C_FLAG | V_FLAG); + cpu_state.regs[cpu_reg].l = temp64 & 0xffffffff; + + CLOCK_CYCLES(20); + PREFETCH_RUN(20, 3, rmdat, 0, 1, 0, 0, 1); + return 0; } - - -static int opIMUL_w_w_a16(uint32_t fetchdat) +static int +opIMUL_w_w_a16(uint32_t fetchdat) { - int32_t templ; - - fetch_ea_16(fetchdat); - if (cpu_mod != 3) - SEG_CHECK_READ(cpu_state.ea_seg); + int32_t templ; - templ = (int32_t)(int16_t)cpu_state.regs[cpu_reg].w * (int32_t)(int16_t)geteaw(); - if (cpu_state.abrt) return 1; - cpu_state.regs[cpu_reg].w = templ & 0xFFFF; - flags_rebuild(); - if ((templ >> 15) != 0 && (templ >> 15) != -1) cpu_state.flags |= C_FLAG | V_FLAG; - else cpu_state.flags &= ~(C_FLAG | V_FLAG); - - CLOCK_CYCLES(18); - PREFETCH_RUN(18, 2, rmdat, 1,0,0,0, 0); - return 0; + fetch_ea_16(fetchdat); + if (cpu_mod != 3) + SEG_CHECK_READ(cpu_state.ea_seg); + + templ = (int32_t) (int16_t) cpu_state.regs[cpu_reg].w * (int32_t) (int16_t) geteaw(); + if (cpu_state.abrt) + return 1; + cpu_state.regs[cpu_reg].w = templ & 0xFFFF; + flags_rebuild(); + if ((templ >> 15) != 0 && (templ >> 15) != -1) + cpu_state.flags |= C_FLAG | V_FLAG; + else + cpu_state.flags &= ~(C_FLAG | V_FLAG); + + CLOCK_CYCLES(18); + PREFETCH_RUN(18, 2, rmdat, 1, 0, 0, 0, 0); + return 0; } -static int opIMUL_w_w_a32(uint32_t fetchdat) +static int +opIMUL_w_w_a32(uint32_t fetchdat) { - int32_t templ; - - fetch_ea_32(fetchdat); - if (cpu_mod != 3) - SEG_CHECK_READ(cpu_state.ea_seg); - - templ = (int32_t)(int16_t)cpu_state.regs[cpu_reg].w * (int32_t)(int16_t)geteaw(); - if (cpu_state.abrt) return 1; - cpu_state.regs[cpu_reg].w = templ & 0xFFFF; - flags_rebuild(); - if ((templ >> 15) != 0 && (templ >> 15) != -1) cpu_state.flags |= C_FLAG | V_FLAG; - else cpu_state.flags &= ~(C_FLAG | V_FLAG); - - CLOCK_CYCLES(18); - PREFETCH_RUN(18, 2, rmdat, 1,0,0,0, 1); - return 0; + int32_t templ; + + fetch_ea_32(fetchdat); + if (cpu_mod != 3) + SEG_CHECK_READ(cpu_state.ea_seg); + + templ = (int32_t) (int16_t) cpu_state.regs[cpu_reg].w * (int32_t) (int16_t) geteaw(); + if (cpu_state.abrt) + return 1; + cpu_state.regs[cpu_reg].w = templ & 0xFFFF; + flags_rebuild(); + if ((templ >> 15) != 0 && (templ >> 15) != -1) + cpu_state.flags |= C_FLAG | V_FLAG; + else + cpu_state.flags &= ~(C_FLAG | V_FLAG); + + CLOCK_CYCLES(18); + PREFETCH_RUN(18, 2, rmdat, 1, 0, 0, 0, 1); + return 0; } -static int opIMUL_l_l_a16(uint32_t fetchdat) +static int +opIMUL_l_l_a16(uint32_t fetchdat) { - int64_t temp64; + int64_t temp64; - fetch_ea_16(fetchdat); - if (cpu_mod != 3) - SEG_CHECK_READ(cpu_state.ea_seg); - - temp64 = (int64_t)(int32_t)cpu_state.regs[cpu_reg].l * (int64_t)(int32_t)geteal(); - if (cpu_state.abrt) return 1; - cpu_state.regs[cpu_reg].l = temp64 & 0xFFFFFFFF; - flags_rebuild(); - if ((temp64 >> 31) != 0 && (temp64 >> 31) != -1) cpu_state.flags |= C_FLAG | V_FLAG; - else cpu_state.flags &= ~(C_FLAG | V_FLAG); - - CLOCK_CYCLES(30); - PREFETCH_RUN(30, 2, rmdat, 0,1,0,0, 0); - return 0; + fetch_ea_16(fetchdat); + if (cpu_mod != 3) + SEG_CHECK_READ(cpu_state.ea_seg); + + temp64 = (int64_t) (int32_t) cpu_state.regs[cpu_reg].l * (int64_t) (int32_t) geteal(); + if (cpu_state.abrt) + return 1; + cpu_state.regs[cpu_reg].l = temp64 & 0xFFFFFFFF; + flags_rebuild(); + if ((temp64 >> 31) != 0 && (temp64 >> 31) != -1) + cpu_state.flags |= C_FLAG | V_FLAG; + else + cpu_state.flags &= ~(C_FLAG | V_FLAG); + + CLOCK_CYCLES(30); + PREFETCH_RUN(30, 2, rmdat, 0, 1, 0, 0, 0); + return 0; } -static int opIMUL_l_l_a32(uint32_t fetchdat) +static int +opIMUL_l_l_a32(uint32_t fetchdat) { - int64_t temp64; + int64_t temp64; - fetch_ea_32(fetchdat); - if (cpu_mod != 3) - SEG_CHECK_READ(cpu_state.ea_seg); - - temp64 = (int64_t)(int32_t)cpu_state.regs[cpu_reg].l * (int64_t)(int32_t)geteal(); - if (cpu_state.abrt) return 1; - cpu_state.regs[cpu_reg].l = temp64 & 0xFFFFFFFF; - flags_rebuild(); - if ((temp64 >> 31) != 0 && (temp64 >> 31) != -1) cpu_state.flags |= C_FLAG | V_FLAG; - else cpu_state.flags &= ~(C_FLAG | V_FLAG); - - CLOCK_CYCLES(30); - PREFETCH_RUN(30, 2, rmdat, 0,1,0,0, 1); - return 0; + fetch_ea_32(fetchdat); + if (cpu_mod != 3) + SEG_CHECK_READ(cpu_state.ea_seg); + + temp64 = (int64_t) (int32_t) cpu_state.regs[cpu_reg].l * (int64_t) (int32_t) geteal(); + if (cpu_state.abrt) + return 1; + cpu_state.regs[cpu_reg].l = temp64 & 0xFFFFFFFF; + flags_rebuild(); + if ((temp64 >> 31) != 0 && (temp64 >> 31) != -1) + cpu_state.flags |= C_FLAG | V_FLAG; + else + cpu_state.flags &= ~(C_FLAG | V_FLAG); + + CLOCK_CYCLES(30); + PREFETCH_RUN(30, 2, rmdat, 0, 1, 0, 0, 1); + return 0; } - diff --git a/src/cpu/x86_ops_pmode.h b/src/cpu/x86_ops_pmode.h index b031fac22..1254d7289 100644 --- a/src/cpu/x86_ops_pmode.h +++ b/src/cpu/x86_ops_pmode.h @@ -1,460 +1,521 @@ -static int opARPL_a16(uint32_t fetchdat) +static int +opARPL_a16(uint32_t fetchdat) { - uint16_t temp_seg; - - NOTRM - fetch_ea_16(fetchdat); - if (cpu_mod != 3) - SEG_CHECK_WRITE(cpu_state.ea_seg); - temp_seg = geteaw(); if (cpu_state.abrt) return 1; - - flags_rebuild(); - if ((temp_seg & 3) < (cpu_state.regs[cpu_reg].w & 3)) - { - temp_seg = (temp_seg & 0xfffc) | (cpu_state.regs[cpu_reg].w & 3); - seteaw(temp_seg); if (cpu_state.abrt) return 1; - cpu_state.flags |= Z_FLAG; - } - else - cpu_state.flags &= ~Z_FLAG; - - CLOCK_CYCLES(is486 ? 9 : 20); - PREFETCH_RUN(is486 ? 9 : 20, 2, rmdat, 1,0,1,0, 0); - return 0; + uint16_t temp_seg; + + NOTRM + fetch_ea_16(fetchdat); + if (cpu_mod != 3) + SEG_CHECK_WRITE(cpu_state.ea_seg); + temp_seg = geteaw(); + if (cpu_state.abrt) + return 1; + + flags_rebuild(); + if ((temp_seg & 3) < (cpu_state.regs[cpu_reg].w & 3)) { + temp_seg = (temp_seg & 0xfffc) | (cpu_state.regs[cpu_reg].w & 3); + seteaw(temp_seg); + if (cpu_state.abrt) + return 1; + cpu_state.flags |= Z_FLAG; + } else + cpu_state.flags &= ~Z_FLAG; + + CLOCK_CYCLES(is486 ? 9 : 20); + PREFETCH_RUN(is486 ? 9 : 20, 2, rmdat, 1, 0, 1, 0, 0); + return 0; } -static int opARPL_a32(uint32_t fetchdat) +static int +opARPL_a32(uint32_t fetchdat) { - uint16_t temp_seg; - - NOTRM - fetch_ea_32(fetchdat); - if (cpu_mod != 3) - SEG_CHECK_WRITE(cpu_state.ea_seg); - temp_seg = geteaw(); if (cpu_state.abrt) return 1; - - flags_rebuild(); - if ((temp_seg & 3) < (cpu_state.regs[cpu_reg].w & 3)) - { - temp_seg = (temp_seg & 0xfffc) | (cpu_state.regs[cpu_reg].w & 3); - seteaw(temp_seg); if (cpu_state.abrt) return 1; - cpu_state.flags |= Z_FLAG; - } - else - cpu_state.flags &= ~Z_FLAG; - - CLOCK_CYCLES(is486 ? 9 : 20); - PREFETCH_RUN(is486 ? 9 : 20, 2, rmdat, 1,0,1,0, 1); - return 0; + uint16_t temp_seg; + + NOTRM + fetch_ea_32(fetchdat); + if (cpu_mod != 3) + SEG_CHECK_WRITE(cpu_state.ea_seg); + temp_seg = geteaw(); + if (cpu_state.abrt) + return 1; + + flags_rebuild(); + if ((temp_seg & 3) < (cpu_state.regs[cpu_reg].w & 3)) { + temp_seg = (temp_seg & 0xfffc) | (cpu_state.regs[cpu_reg].w & 3); + seteaw(temp_seg); + if (cpu_state.abrt) + return 1; + cpu_state.flags |= Z_FLAG; + } else + cpu_state.flags &= ~Z_FLAG; + + CLOCK_CYCLES(is486 ? 9 : 20); + PREFETCH_RUN(is486 ? 9 : 20, 2, rmdat, 1, 0, 1, 0, 1); + return 0; } -#define opLAR(name, fetch_ea, is32, ea32) \ - static int opLAR_ ## name(uint32_t fetchdat) \ - { \ - int valid; \ - uint16_t sel, desc = 0; \ - \ - NOTRM \ - fetch_ea(fetchdat); \ - if (cpu_mod != 3) \ - SEG_CHECK_READ(cpu_state.ea_seg); \ - \ - sel = geteaw(); if (cpu_state.abrt) return 1; \ - \ - flags_rebuild(); \ - if (!(sel & 0xfffc)) { cpu_state.flags &= ~Z_FLAG; return 0; } /*Null selector*/ \ - valid = (sel & ~7) < ((sel & 4) ? ldt.limit : gdt.limit); \ - if (valid) \ - { \ - cpl_override = 1; \ - desc = readmemw(0, ((sel & 4) ? ldt.base : gdt.base) + (sel & ~7) + 4); \ - cpl_override = 0; if (cpu_state.abrt) return 1; \ - } \ - cpu_state.flags &= ~Z_FLAG; \ - if ((desc & 0x1f00) == 0x000) valid = 0; \ - if ((desc & 0x1f00) == 0x800) valid = 0; \ - if ((desc & 0x1f00) == 0xa00) valid = 0; \ - if ((desc & 0x1f00) == 0xd00) valid = 0; \ - if ((desc & 0x1c00) < 0x1c00) /*Exclude conforming code segments*/ \ - { \ - int dpl = (desc >> 13) & 3; \ - if (dpl < CPL || dpl < (sel & 3)) valid = 0; \ - } \ - if (valid) \ - { \ - cpu_state.flags |= Z_FLAG; \ - cpl_override = 1; \ - if (is32) \ - cpu_state.regs[cpu_reg].l = readmeml(0, ((sel & 4) ? ldt.base : gdt.base) + (sel & ~7) + 4) & 0xffff00; \ - else \ - cpu_state.regs[cpu_reg].w = readmemw(0, ((sel & 4) ? ldt.base : gdt.base) + (sel & ~7) + 4) & 0xff00; \ - cpl_override = 0; \ - } \ - CLOCK_CYCLES(11); \ - PREFETCH_RUN(11, 2, rmdat, 2,0,0,0, ea32); \ - return cpu_state.abrt; \ - } +#define opLAR(name, fetch_ea, is32, ea32) \ + static int opLAR_##name(uint32_t fetchdat) \ + { \ + int valid; \ + uint16_t sel, desc = 0; \ + \ + NOTRM \ + fetch_ea(fetchdat); \ + if (cpu_mod != 3) \ + SEG_CHECK_READ(cpu_state.ea_seg); \ + \ + sel = geteaw(); \ + if (cpu_state.abrt) \ + return 1; \ + \ + flags_rebuild(); \ + if (!(sel & 0xfffc)) { \ + cpu_state.flags &= ~Z_FLAG; \ + return 0; \ + } /*Null selector*/ \ + valid = (sel & ~7) < ((sel & 4) ? ldt.limit : gdt.limit); \ + if (valid) { \ + cpl_override = 1; \ + desc = readmemw(0, ((sel & 4) ? ldt.base : gdt.base) + (sel & ~7) + 4); \ + cpl_override = 0; \ + if (cpu_state.abrt) \ + return 1; \ + } \ + cpu_state.flags &= ~Z_FLAG; \ + if ((desc & 0x1f00) == 0x000) \ + valid = 0; \ + if ((desc & 0x1f00) == 0x800) \ + valid = 0; \ + if ((desc & 0x1f00) == 0xa00) \ + valid = 0; \ + if ((desc & 0x1f00) == 0xd00) \ + valid = 0; \ + if ((desc & 0x1c00) < 0x1c00) /*Exclude conforming code segments*/ \ + { \ + int dpl = (desc >> 13) & 3; \ + if (dpl < CPL || dpl < (sel & 3)) \ + valid = 0; \ + } \ + if (valid) { \ + cpu_state.flags |= Z_FLAG; \ + cpl_override = 1; \ + if (is32) \ + cpu_state.regs[cpu_reg].l = readmeml(0, ((sel & 4) ? ldt.base : gdt.base) + (sel & ~7) + 4) & 0xffff00; \ + else \ + cpu_state.regs[cpu_reg].w = readmemw(0, ((sel & 4) ? ldt.base : gdt.base) + (sel & ~7) + 4) & 0xff00; \ + cpl_override = 0; \ + } \ + CLOCK_CYCLES(11); \ + PREFETCH_RUN(11, 2, rmdat, 2, 0, 0, 0, ea32); \ + return cpu_state.abrt; \ + } opLAR(w_a16, fetch_ea_16, 0, 0) -opLAR(w_a32, fetch_ea_32, 0, 1) -opLAR(l_a16, fetch_ea_16, 1, 0) -opLAR(l_a32, fetch_ea_32, 1, 1) + opLAR(w_a32, fetch_ea_32, 0, 1) + opLAR(l_a16, fetch_ea_16, 1, 0) + opLAR(l_a32, fetch_ea_32, 1, 1) -#define opLSL(name, fetch_ea, is32, ea32) \ - static int opLSL_ ## name(uint32_t fetchdat) \ - { \ - int valid; \ - uint16_t sel, desc = 0; \ - \ - NOTRM \ - fetch_ea(fetchdat); \ - if (cpu_mod != 3) \ - SEG_CHECK_READ(cpu_state.ea_seg); \ - \ - sel = geteaw(); if (cpu_state.abrt) return 1; \ - flags_rebuild(); \ - cpu_state.flags &= ~Z_FLAG; \ - if (!(sel & 0xfffc)) return 0; /*Null selector*/ \ - valid = (sel & ~7) < ((sel & 4) ? ldt.limit : gdt.limit); \ - if (valid) \ - { \ - cpl_override = 1; \ - desc = readmemw(0, ((sel & 4) ? ldt.base : gdt.base) + (sel & ~7) + 4); \ - cpl_override = 0; if (cpu_state.abrt) return 1; \ - } \ - if ((desc & 0x1400) == 0x400) valid = 0; /*Interrupt or trap or call gate*/ \ - if ((desc & 0x1f00) == 0x000) valid = 0; /*Invalid*/ \ - if ((desc & 0x1f00) == 0xa00) valid = 0; /*Invalid*/ \ - if ((desc & 0x1c00) != 0x1c00) /*Exclude conforming code segments*/ \ - { \ - int rpl = (desc >> 13) & 3; \ - if (rpl < CPL || rpl < (sel & 3)) valid = 0; \ - } \ - if (valid) \ - { \ - cpu_state.flags |= Z_FLAG; \ - cpl_override = 1; \ - if (is32) \ - { \ - cpu_state.regs[cpu_reg].l = readmemw(0, ((sel & 4) ? ldt.base : gdt.base) + (sel & ~7)); \ - cpu_state.regs[cpu_reg].l |= (readmemb(0, ((sel & 4) ? ldt.base : gdt.base) + (sel & ~7) + 6) & 0xF) << 16; \ - if (readmemb(0, ((sel & 4) ? ldt.base : gdt.base) + (sel & ~7) + 6) & 0x80) \ - { \ - cpu_state.regs[cpu_reg].l <<= 12; \ - cpu_state.regs[cpu_reg].l |= 0xFFF; \ - } \ - } \ - else \ - cpu_state.regs[cpu_reg].w = readmemw(0, ((sel & 4) ? ldt.base : gdt.base) + (sel & ~7)); \ - cpl_override = 0; \ - } \ - CLOCK_CYCLES(10); \ - PREFETCH_RUN(10, 2, rmdat, 4,0,0,0, ea32); \ - return cpu_state.abrt; \ - } +#define opLSL(name, fetch_ea, is32, ea32) \ + static int opLSL_##name(uint32_t fetchdat) \ + { \ + int valid; \ + uint16_t sel, desc = 0; \ + \ + NOTRM \ + fetch_ea(fetchdat); \ + if (cpu_mod != 3) \ + SEG_CHECK_READ(cpu_state.ea_seg); \ + \ + sel = geteaw(); \ + if (cpu_state.abrt) \ + return 1; \ + flags_rebuild(); \ + cpu_state.flags &= ~Z_FLAG; \ + if (!(sel & 0xfffc)) \ + return 0; /*Null selector*/ \ + valid = (sel & ~7) < ((sel & 4) ? ldt.limit : gdt.limit); \ + if (valid) { \ + cpl_override = 1; \ + desc = readmemw(0, ((sel & 4) ? ldt.base : gdt.base) + (sel & ~7) + 4); \ + cpl_override = 0; \ + if (cpu_state.abrt) \ + return 1; \ + } \ + if ((desc & 0x1400) == 0x400) \ + valid = 0; /*Interrupt or trap or call gate*/ \ + if ((desc & 0x1f00) == 0x000) \ + valid = 0; /*Invalid*/ \ + if ((desc & 0x1f00) == 0xa00) \ + valid = 0; /*Invalid*/ \ + if ((desc & 0x1c00) != 0x1c00) /*Exclude conforming code segments*/ \ + { \ + int rpl = (desc >> 13) & 3; \ + if (rpl < CPL || rpl < (sel & 3)) \ + valid = 0; \ + } \ + if (valid) { \ + cpu_state.flags |= Z_FLAG; \ + cpl_override = 1; \ + if (is32) { \ + cpu_state.regs[cpu_reg].l = readmemw(0, ((sel & 4) ? ldt.base : gdt.base) + (sel & ~7)); \ + cpu_state.regs[cpu_reg].l |= (readmemb(0, ((sel & 4) ? ldt.base : gdt.base) + (sel & ~7) + 6) & 0xF) << 16; \ + if (readmemb(0, ((sel & 4) ? ldt.base : gdt.base) + (sel & ~7) + 6) & 0x80) { \ + cpu_state.regs[cpu_reg].l <<= 12; \ + cpu_state.regs[cpu_reg].l |= 0xFFF; \ + } \ + } else \ + cpu_state.regs[cpu_reg].w = readmemw(0, ((sel & 4) ? ldt.base : gdt.base) + (sel & ~7)); \ + cpl_override = 0; \ + } \ + CLOCK_CYCLES(10); \ + PREFETCH_RUN(10, 2, rmdat, 4, 0, 0, 0, ea32); \ + return cpu_state.abrt; \ + } -opLSL(w_a16, fetch_ea_16, 0, 0) -opLSL(w_a32, fetch_ea_32, 0, 1) -opLSL(l_a16, fetch_ea_16, 1, 0) -opLSL(l_a32, fetch_ea_32, 1, 1) + opLSL(w_a16, fetch_ea_16, 0, 0) + opLSL(w_a32, fetch_ea_32, 0, 1) + opLSL(l_a16, fetch_ea_16, 1, 0) + opLSL(l_a32, fetch_ea_32, 1, 1) - -static int op0F00_common(uint32_t fetchdat, int ea32) + static int op0F00_common(uint32_t fetchdat, int ea32) { - int dpl, valid, granularity; - uint32_t addr, base, limit; - uint16_t desc, sel; - uint8_t access, ar_high; + int dpl; + int valid; + int granularity; + uint32_t addr; + uint32_t base; + uint32_t limit; + uint16_t desc; + uint16_t sel; + uint8_t access; + uint8_t ar_high; - switch (rmdat & 0x38) - { - case 0x00: /*SLDT*/ - if (cpu_mod != 3) - SEG_CHECK_WRITE(cpu_state.ea_seg); - seteaw(ldt.seg); - CLOCK_CYCLES(4); - PREFETCH_RUN(4, 2, rmdat, 0,0,(cpu_mod == 3) ? 0:1,0, ea32); + switch (rmdat & 0x38) { + case 0x00: /*SLDT*/ + if (cpu_mod != 3) + SEG_CHECK_WRITE(cpu_state.ea_seg); + seteaw(ldt.seg); + CLOCK_CYCLES(4); + PREFETCH_RUN(4, 2, rmdat, 0, 0, (cpu_mod == 3) ? 0 : 1, 0, ea32); + break; + case 0x08: /*STR*/ + if (cpu_mod != 3) + SEG_CHECK_WRITE(cpu_state.ea_seg); + seteaw(tr.seg); + CLOCK_CYCLES(4); + PREFETCH_RUN(4, 2, rmdat, 0, 0, (cpu_mod == 3) ? 0 : 1, 0, ea32); + break; + case 0x10: /*LLDT*/ + if ((CPL || cpu_state.eflags & VM_FLAG) && (cr0 & 1)) { + x86gpf(NULL, 0); + return 1; + } + if (cpu_mod != 3) + SEG_CHECK_READ(cpu_state.ea_seg); + sel = geteaw(); + if (cpu_state.abrt) + return 1; + addr = (sel & ~7) + gdt.base; + limit = readmemw(0, addr) + ((readmemb(0, addr + 6) & 0xf) << 16); + base = (readmemw(0, addr + 2)) | (readmemb(0, addr + 4) << 16) | (readmemb(0, addr + 7) << 24); + access = readmemb(0, addr + 5); + ar_high = readmemb(0, addr + 6); + granularity = readmemb(0, addr + 6) & 0x80; + if (cpu_state.abrt) + return 1; + ldt.limit = limit; + ldt.access = access; + ldt.ar_high = ar_high; + if (granularity) { + ldt.limit <<= 12; + ldt.limit |= 0xfff; + } + ldt.base = base; + ldt.seg = sel; + CLOCK_CYCLES(20); + PREFETCH_RUN(20, 2, rmdat, (cpu_mod == 3) ? 0 : 1, 2, 0, 0, ea32); + break; + case 0x18: /*LTR*/ + if ((CPL || cpu_state.eflags & VM_FLAG) && (cr0 & 1)) { + x86gpf(NULL, 0); break; - case 0x08: /*STR*/ - if (cpu_mod != 3) - SEG_CHECK_WRITE(cpu_state.ea_seg); - seteaw(tr.seg); - CLOCK_CYCLES(4); - PREFETCH_RUN(4, 2, rmdat, 0,0,(cpu_mod == 3) ? 0:1,0, ea32); - break; - case 0x10: /*LLDT*/ - if ((CPL || cpu_state.eflags&VM_FLAG) && (cr0&1)) - { - x86gpf(NULL,0); - return 1; - } - if (cpu_mod != 3) - SEG_CHECK_READ(cpu_state.ea_seg); - sel = geteaw(); if (cpu_state.abrt) return 1; - addr = (sel & ~7) + gdt.base; - limit = readmemw(0, addr) + ((readmemb(0, addr + 6) & 0xf) << 16); - base = (readmemw(0, addr + 2)) | (readmemb(0, addr + 4) << 16) | (readmemb(0, addr + 7) << 24); - access = readmemb(0, addr + 5); - ar_high = readmemb(0, addr + 6); - granularity = readmemb(0, addr + 6) & 0x80; - if (cpu_state.abrt) return 1; - ldt.limit = limit; - ldt.access = access; - ldt.ar_high = ar_high; - if (granularity) - { - ldt.limit <<= 12; - ldt.limit |= 0xfff; - } - ldt.base = base; - ldt.seg = sel; - CLOCK_CYCLES(20); - PREFETCH_RUN(20, 2, rmdat, (cpu_mod == 3) ? 0:1,2,0,0, ea32); - break; - case 0x18: /*LTR*/ - if ((CPL || cpu_state.eflags&VM_FLAG) && (cr0&1)) - { - x86gpf(NULL,0); - break; - } - if (cpu_mod != 3) - SEG_CHECK_READ(cpu_state.ea_seg); - sel = geteaw(); if (cpu_state.abrt) return 1; - addr = (sel & ~7) + gdt.base; - limit = readmemw(0, addr) + ((readmemb(0, addr + 6) & 0xf) << 16); - base = (readmemw(0, addr + 2)) | (readmemb(0, addr + 4) << 16) | (readmemb(0, addr + 7) << 24); - access = readmemb(0, addr + 5); - ar_high = readmemb(0, addr + 6); - granularity = readmemb(0, addr + 6) & 0x80; - if (cpu_state.abrt) return 1; - access |= 2; - writememb(0, addr + 5, access); - if (cpu_state.abrt) return 1; - tr.seg = sel; - tr.limit = limit; - tr.access = access; - tr.ar_high = ar_high; - if (granularity) - { - tr.limit <<= 12; - tr.limit |= 0xFFF; - } - tr.base = base; - CLOCK_CYCLES(20); - PREFETCH_RUN(20, 2, rmdat, (cpu_mod == 3) ? 0:1,2,0,0, ea32); - break; - case 0x20: /*VERR*/ - if (cpu_mod != 3) - SEG_CHECK_READ(cpu_state.ea_seg); - sel = geteaw(); if (cpu_state.abrt) return 1; - flags_rebuild(); - cpu_state.flags &= ~Z_FLAG; - if (!(sel & 0xfffc)) return 0; /*Null selector*/ - cpl_override = 1; - valid = (sel & ~7) < ((sel & 4) ? ldt.limit : gdt.limit); - desc = readmemw(0, ((sel & 4) ? ldt.base : gdt.base) + (sel & ~7) + 4); - cpl_override = 0; if (cpu_state.abrt) return 1; - if (!(desc & 0x1000)) valid = 0; - if ((desc & 0xC00) != 0xC00) /*Exclude conforming code segments*/ - { - dpl = (desc >> 13) & 3; /*Check permissions*/ - if (dpl < CPL || dpl < (sel & 3)) valid = 0; - } - if ((desc & 0x0800) && !(desc & 0x0200)) valid = 0; /*Non-readable code*/ - if (valid) cpu_state.flags |= Z_FLAG; - CLOCK_CYCLES(20); - PREFETCH_RUN(20, 2, rmdat, (cpu_mod == 3) ? 1:2,0,0,0, ea32); - break; - case 0x28: /*VERW*/ - if (cpu_mod != 3) - SEG_CHECK_READ(cpu_state.ea_seg); - sel = geteaw(); if (cpu_state.abrt) return 1; - flags_rebuild(); - cpu_state.flags &= ~Z_FLAG; - if (!(sel & 0xfffc)) return 0; /*Null selector*/ - cpl_override = 1; - valid = (sel & ~7) < ((sel & 4) ? ldt.limit : gdt.limit); - desc = readmemw(0, ((sel & 4) ? ldt.base : gdt.base) + (sel & ~7) + 4); - cpl_override = 0; if (cpu_state.abrt) return 1; - if (!(desc & 0x1000)) valid = 0; + } + if (cpu_mod != 3) + SEG_CHECK_READ(cpu_state.ea_seg); + sel = geteaw(); + if (cpu_state.abrt) + return 1; + addr = (sel & ~7) + gdt.base; + limit = readmemw(0, addr) + ((readmemb(0, addr + 6) & 0xf) << 16); + base = (readmemw(0, addr + 2)) | (readmemb(0, addr + 4) << 16) | (readmemb(0, addr + 7) << 24); + access = readmemb(0, addr + 5); + ar_high = readmemb(0, addr + 6); + granularity = readmemb(0, addr + 6) & 0x80; + if (cpu_state.abrt) + return 1; + access |= 2; + writememb(0, addr + 5, access); + if (cpu_state.abrt) + return 1; + tr.seg = sel; + tr.limit = limit; + tr.access = access; + tr.ar_high = ar_high; + if (granularity) { + tr.limit <<= 12; + tr.limit |= 0xFFF; + } + tr.base = base; + CLOCK_CYCLES(20); + PREFETCH_RUN(20, 2, rmdat, (cpu_mod == 3) ? 0 : 1, 2, 0, 0, ea32); + break; + case 0x20: /*VERR*/ + if (cpu_mod != 3) + SEG_CHECK_READ(cpu_state.ea_seg); + sel = geteaw(); + if (cpu_state.abrt) + return 1; + flags_rebuild(); + cpu_state.flags &= ~Z_FLAG; + if (!(sel & 0xfffc)) + return 0; /*Null selector*/ + cpl_override = 1; + valid = (sel & ~7) < ((sel & 4) ? ldt.limit : gdt.limit); + desc = readmemw(0, ((sel & 4) ? ldt.base : gdt.base) + (sel & ~7) + 4); + cpl_override = 0; + if (cpu_state.abrt) + return 1; + if (!(desc & 0x1000)) + valid = 0; + if ((desc & 0xC00) != 0xC00) /*Exclude conforming code segments*/ + { dpl = (desc >> 13) & 3; /*Check permissions*/ - if (dpl < CPL || dpl < (sel & 3)) valid = 0; - if (desc & 0x0800) valid = 0; /*Code*/ - if (!(desc & 0x0200)) valid = 0; /*Read-only data*/ - if (valid) cpu_state.flags |= Z_FLAG; - CLOCK_CYCLES(20); - PREFETCH_RUN(20, 2, rmdat, (cpu_mod == 3) ? 1:2,0,0,0, ea32); - break; + if (dpl < CPL || dpl < (sel & 3)) + valid = 0; + } + if ((desc & 0x0800) && !(desc & 0x0200)) + valid = 0; /*Non-readable code*/ + if (valid) + cpu_state.flags |= Z_FLAG; + CLOCK_CYCLES(20); + PREFETCH_RUN(20, 2, rmdat, (cpu_mod == 3) ? 1 : 2, 0, 0, 0, ea32); + break; + case 0x28: /*VERW*/ + if (cpu_mod != 3) + SEG_CHECK_READ(cpu_state.ea_seg); + sel = geteaw(); + if (cpu_state.abrt) + return 1; + flags_rebuild(); + cpu_state.flags &= ~Z_FLAG; + if (!(sel & 0xfffc)) + return 0; /*Null selector*/ + cpl_override = 1; + valid = (sel & ~7) < ((sel & 4) ? ldt.limit : gdt.limit); + desc = readmemw(0, ((sel & 4) ? ldt.base : gdt.base) + (sel & ~7) + 4); + cpl_override = 0; + if (cpu_state.abrt) + return 1; + if (!(desc & 0x1000)) + valid = 0; + dpl = (desc >> 13) & 3; /*Check permissions*/ + if (dpl < CPL || dpl < (sel & 3)) + valid = 0; + if (desc & 0x0800) + valid = 0; /*Code*/ + if (!(desc & 0x0200)) + valid = 0; /*Read-only data*/ + if (valid) + cpu_state.flags |= Z_FLAG; + CLOCK_CYCLES(20); + PREFETCH_RUN(20, 2, rmdat, (cpu_mod == 3) ? 1 : 2, 0, 0, 0, ea32); + break; - default: - cpu_state.pc -= 3; - x86illegal(); - break; - } - return cpu_state.abrt; + default: + cpu_state.pc -= 3; + x86illegal(); + break; + } + return cpu_state.abrt; } -static int op0F00_a16(uint32_t fetchdat) +static int +op0F00_a16(uint32_t fetchdat) { - NOTRM + NOTRM - fetch_ea_16(fetchdat); - - return op0F00_common(fetchdat, 0); + fetch_ea_16(fetchdat); + + return op0F00_common(fetchdat, 0); } -static int op0F00_a32(uint32_t fetchdat) +static int +op0F00_a32(uint32_t fetchdat) { - NOTRM + NOTRM - fetch_ea_32(fetchdat); - - return op0F00_common(fetchdat, 1); + fetch_ea_32(fetchdat); + + return op0F00_common(fetchdat, 1); } -static int op0F01_common(uint32_t fetchdat, int is32, int is286, int ea32) +static int +op0F01_common(uint32_t fetchdat, int is32, int is286, int ea32) { - uint32_t base; - uint16_t limit, tempw; - switch (rmdat & 0x38) - { - case 0x00: /*SGDT*/ - if (cpu_mod != 3) - SEG_CHECK_WRITE(cpu_state.ea_seg); - seteaw(gdt.limit); - base = gdt.base; //is32 ? gdt.base : (gdt.base & 0xffffff); - if (is286) - base |= 0xff000000; - writememl(easeg, cpu_state.eaaddr + 2, base); - CLOCK_CYCLES(7); - PREFETCH_RUN(7, 2, rmdat, 0,0,1,1, ea32); + uint32_t base; + uint16_t limit; + uint16_t tempw; + + switch (rmdat & 0x38) { + case 0x00: /*SGDT*/ + if (cpu_mod != 3) + SEG_CHECK_WRITE(cpu_state.ea_seg); + seteaw(gdt.limit); + base = gdt.base; // is32 ? gdt.base : (gdt.base & 0xffffff); + if (is286) + base |= 0xff000000; + writememl(easeg, cpu_state.eaaddr + 2, base); + CLOCK_CYCLES(7); + PREFETCH_RUN(7, 2, rmdat, 0, 0, 1, 1, ea32); + break; + case 0x08: /*SIDT*/ + if (cpu_mod != 3) + SEG_CHECK_WRITE(cpu_state.ea_seg); + seteaw(idt.limit); + base = idt.base; + if (is286) + base |= 0xff000000; + writememl(easeg, cpu_state.eaaddr + 2, base); + CLOCK_CYCLES(7); + PREFETCH_RUN(7, 2, rmdat, 0, 0, 1, 1, ea32); + break; + case 0x10: /*LGDT*/ + if ((CPL || cpu_state.eflags & VM_FLAG) && (cr0 & 1)) { + x86gpf(NULL, 0); break; - case 0x08: /*SIDT*/ - if (cpu_mod != 3) - SEG_CHECK_WRITE(cpu_state.ea_seg); - seteaw(idt.limit); - base = idt.base; - if (is286) - base |= 0xff000000; - writememl(easeg, cpu_state.eaaddr + 2, base); - CLOCK_CYCLES(7); - PREFETCH_RUN(7, 2, rmdat, 0,0,1,1, ea32); + } + if (cpu_mod != 3) + SEG_CHECK_READ(cpu_state.ea_seg); + limit = geteaw(); + base = readmeml(0, easeg + cpu_state.eaaddr + 2); + if (cpu_state.abrt) + return 1; + gdt.limit = limit; + gdt.base = base; + if (!is32) + gdt.base &= 0xffffff; + CLOCK_CYCLES(11); + PREFETCH_RUN(11, 2, rmdat, 1, 1, 0, 0, ea32); + break; + case 0x18: /*LIDT*/ + if ((CPL || cpu_state.eflags & VM_FLAG) && (cr0 & 1)) { + x86gpf(NULL, 0); break; - case 0x10: /*LGDT*/ - if ((CPL || cpu_state.eflags&VM_FLAG) && (cr0&1)) - { - x86gpf(NULL,0); - break; + } + if (cpu_mod != 3) + SEG_CHECK_READ(cpu_state.ea_seg); + limit = geteaw(); + base = readmeml(0, easeg + cpu_state.eaaddr + 2); + if (cpu_state.abrt) + return 1; + idt.limit = limit; + idt.base = base; + if (!is32) + idt.base &= 0xffffff; + CLOCK_CYCLES(11); + PREFETCH_RUN(11, 2, rmdat, 1, 1, 0, 0, ea32); + break; + + case 0x20: /*SMSW*/ + if (cpu_mod != 3) + SEG_CHECK_WRITE(cpu_state.ea_seg); + if (is486 || isibm486) + seteaw(msw); + else if (is386) + seteaw(msw | /* 0xFF00 */ 0xFFE0); + else + seteaw(msw | 0xFFF0); + CLOCK_CYCLES(2); + PREFETCH_RUN(2, 2, rmdat, 0, 0, (cpu_mod == 3) ? 0 : 1, 0, ea32); + break; + case 0x30: /*LMSW*/ + if ((CPL || cpu_state.eflags & VM_FLAG) && (msw & 1)) { + x86gpf(NULL, 0); + break; + } + if (cpu_mod != 3) + SEG_CHECK_READ(cpu_state.ea_seg); + tempw = geteaw(); + if (cpu_state.abrt) + return 1; + if (msw & 1) + tempw |= 1; + if (is386) { + tempw &= ~0x10; + tempw |= (msw & 0x10); + } else + tempw &= 0xF; + msw = tempw; + if (msw & 1) + cpu_cur_status |= CPU_STATUS_PMODE; + else + cpu_cur_status &= ~CPU_STATUS_PMODE; + PREFETCH_RUN(2, 2, rmdat, 0, 0, (cpu_mod == 3) ? 0 : 1, 0, ea32); + break; + + case 0x38: /*INVLPG*/ + if (is486 || isibm486) { + if ((CPL || cpu_state.eflags & VM_FLAG) && (cr0 & 1)) { + x86gpf(NULL, 0); + break; } - if (cpu_mod != 3) - SEG_CHECK_READ(cpu_state.ea_seg); - limit = geteaw(); - base = readmeml(0, easeg + cpu_state.eaaddr + 2); if (cpu_state.abrt) return 1; - gdt.limit = limit; - gdt.base = base; - if (!is32) gdt.base &= 0xffffff; - CLOCK_CYCLES(11); - PREFETCH_RUN(11, 2, rmdat, 1,1,0,0, ea32); - break; - case 0x18: /*LIDT*/ - if ((CPL || cpu_state.eflags&VM_FLAG) && (cr0&1)) - { - x86gpf(NULL,0); - break; - } - if (cpu_mod != 3) - SEG_CHECK_READ(cpu_state.ea_seg); - limit = geteaw(); - base = readmeml(0, easeg + cpu_state.eaaddr + 2); if (cpu_state.abrt) return 1; - idt.limit = limit; - idt.base = base; - if (!is32) idt.base &= 0xffffff; - CLOCK_CYCLES(11); - PREFETCH_RUN(11, 2, rmdat, 1,1,0,0, ea32); + SEG_CHECK_READ(cpu_state.ea_seg); + flushmmucache_nopc(); + CLOCK_CYCLES(12); + PREFETCH_RUN(12, 2, rmdat, 0, 0, 0, 0, ea32); break; + } - case 0x20: /*SMSW*/ - if (cpu_mod != 3) - SEG_CHECK_WRITE(cpu_state.ea_seg); - if (is486 || isibm486) seteaw(msw); - else if (is386) seteaw(msw | /* 0xFF00 */ 0xFFE0); - else seteaw(msw | 0xFFF0); - CLOCK_CYCLES(2); - PREFETCH_RUN(2, 2, rmdat, 0,0,(cpu_mod == 3) ? 0:1,0, ea32); - break; - case 0x30: /*LMSW*/ - if ((CPL || cpu_state.eflags&VM_FLAG) && (msw&1)) - { - x86gpf(NULL, 0); - break; - } - if (cpu_mod != 3) - SEG_CHECK_READ(cpu_state.ea_seg); - tempw = geteaw(); if (cpu_state.abrt) return 1; - if (msw & 1) tempw |= 1; - if (is386) - { - tempw &= ~0x10; - tempw |= (msw & 0x10); - } - else tempw &= 0xF; - msw = tempw; - if (msw & 1) - cpu_cur_status |= CPU_STATUS_PMODE; - else - cpu_cur_status &= ~CPU_STATUS_PMODE; - PREFETCH_RUN(2, 2, rmdat, 0,0,(cpu_mod == 3) ? 0:1,0, ea32); - break; - - case 0x38: /*INVLPG*/ - if (is486 || isibm486) - { - if ((CPL || cpu_state.eflags&VM_FLAG) && (cr0&1)) - { - x86gpf(NULL, 0); - break; - } - SEG_CHECK_READ(cpu_state.ea_seg); - mmu_invalidate(ds + cpu_state.eaaddr); - CLOCK_CYCLES(12); - PREFETCH_RUN(12, 2, rmdat, 0,0,0,0, ea32); - break; - } - - default: - cpu_state.pc -= 3; - x86illegal(); - break; - } - return cpu_state.abrt; + default: + cpu_state.pc -= 3; + x86illegal(); + break; + } + return cpu_state.abrt; } -static int op0F01_w_a16(uint32_t fetchdat) +static int +op0F01_w_a16(uint32_t fetchdat) { - fetch_ea_16(fetchdat); - - return op0F01_common(fetchdat, 0, 0, 0); + fetch_ea_16(fetchdat); + + return op0F01_common(fetchdat, 0, 0, 0); } -static int op0F01_w_a32(uint32_t fetchdat) +static int +op0F01_w_a32(uint32_t fetchdat) { - fetch_ea_32(fetchdat); - - return op0F01_common(fetchdat, 0, 0, 1); + fetch_ea_32(fetchdat); + + return op0F01_common(fetchdat, 0, 0, 1); } -static int op0F01_l_a16(uint32_t fetchdat) +static int +op0F01_l_a16(uint32_t fetchdat) { - fetch_ea_16(fetchdat); - - return op0F01_common(fetchdat, 1, 0, 0); + fetch_ea_16(fetchdat); + + return op0F01_common(fetchdat, 1, 0, 0); } -static int op0F01_l_a32(uint32_t fetchdat) +static int +op0F01_l_a32(uint32_t fetchdat) { - fetch_ea_32(fetchdat); - - return op0F01_common(fetchdat, 1, 0, 1); + fetch_ea_32(fetchdat); + + return op0F01_common(fetchdat, 1, 0, 1); } -static int op0F01_286(uint32_t fetchdat) +static int +op0F01_286(uint32_t fetchdat) { - fetch_ea_16(fetchdat); - - return op0F01_common(fetchdat, 0, 1, 0); + fetch_ea_16(fetchdat); + + return op0F01_common(fetchdat, 0, 1, 0); } diff --git a/src/cpu/x86_ops_prefix.h b/src/cpu/x86_ops_prefix.h index 8d191103d..8a7357386 100644 --- a/src/cpu/x86_ops_prefix.h +++ b/src/cpu/x86_ops_prefix.h @@ -1,68 +1,73 @@ -#define op_seg(name, seg, opcode_table, normal_opcode_table) \ -static int op ## name ## _w_a16(uint32_t fetchdat) \ -{ \ - fetchdat = fastreadl(cs + cpu_state.pc); \ - if (cpu_state.abrt) return 1; \ - cpu_state.pc++; \ - \ - cpu_state.ea_seg = &seg; \ - cpu_state.ssegs = 1; \ - CLOCK_CYCLES(4); \ - PREFETCH_PREFIX(); \ - \ - if (opcode_table[fetchdat & 0xff]) \ - return opcode_table[fetchdat & 0xff](fetchdat >> 8); \ - return normal_opcode_table[fetchdat & 0xff](fetchdat >> 8); \ -} \ - \ -static int op ## name ## _l_a16(uint32_t fetchdat) \ -{ \ - fetchdat = fastreadl(cs + cpu_state.pc); \ - if (cpu_state.abrt) return 1; \ - cpu_state.pc++; \ - \ - cpu_state.ea_seg = &seg; \ - cpu_state.ssegs = 1; \ - CLOCK_CYCLES(4); \ - PREFETCH_PREFIX(); \ - \ - if (opcode_table[(fetchdat & 0xff) | 0x100]) \ - return opcode_table[(fetchdat & 0xff) | 0x100](fetchdat >> 8); \ +#define op_seg(name, seg, opcode_table, normal_opcode_table) \ + static int op##name##_w_a16(uint32_t fetchdat) \ + { \ + fetchdat = fastreadl(cs + cpu_state.pc); \ + if (cpu_state.abrt) \ + return 1; \ + cpu_state.pc++; \ + \ + cpu_state.ea_seg = &seg; \ + cpu_state.ssegs = 1; \ + CLOCK_CYCLES(4); \ + PREFETCH_PREFIX(); \ + \ + if (opcode_table[fetchdat & 0xff]) \ + return opcode_table[fetchdat & 0xff](fetchdat >> 8); \ + return normal_opcode_table[fetchdat & 0xff](fetchdat >> 8); \ + } \ + \ + static int op##name##_l_a16(uint32_t fetchdat) \ + { \ + fetchdat = fastreadl(cs + cpu_state.pc); \ + if (cpu_state.abrt) \ + return 1; \ + cpu_state.pc++; \ + \ + cpu_state.ea_seg = &seg; \ + cpu_state.ssegs = 1; \ + CLOCK_CYCLES(4); \ + PREFETCH_PREFIX(); \ + \ + if (opcode_table[(fetchdat & 0xff) | 0x100]) \ + return opcode_table[(fetchdat & 0xff) | 0x100](fetchdat >> 8); \ return normal_opcode_table[(fetchdat & 0xff) | 0x100](fetchdat >> 8); \ -} \ - \ -static int op ## name ## _w_a32(uint32_t fetchdat) \ -{ \ - fetchdat = fastreadl(cs + cpu_state.pc); \ - if (cpu_state.abrt) return 1; \ - cpu_state.pc++; \ - \ - cpu_state.ea_seg = &seg; \ - cpu_state.ssegs = 1; \ - CLOCK_CYCLES(4); \ - PREFETCH_PREFIX(); \ - \ - if (opcode_table[(fetchdat & 0xff) | 0x200]) \ - return opcode_table[(fetchdat & 0xff) | 0x200](fetchdat >> 8); \ + } \ + \ + static int op##name##_w_a32(uint32_t fetchdat) \ + { \ + fetchdat = fastreadl(cs + cpu_state.pc); \ + if (cpu_state.abrt) \ + return 1; \ + cpu_state.pc++; \ + \ + cpu_state.ea_seg = &seg; \ + cpu_state.ssegs = 1; \ + CLOCK_CYCLES(4); \ + PREFETCH_PREFIX(); \ + \ + if (opcode_table[(fetchdat & 0xff) | 0x200]) \ + return opcode_table[(fetchdat & 0xff) | 0x200](fetchdat >> 8); \ return normal_opcode_table[(fetchdat & 0xff) | 0x200](fetchdat >> 8); \ -} \ - \ -static int op ## name ## _l_a32(uint32_t fetchdat) \ -{ \ - fetchdat = fastreadl(cs + cpu_state.pc); \ - if (cpu_state.abrt) return 1; \ - cpu_state.pc++; \ - \ - cpu_state.ea_seg = &seg; \ - cpu_state.ssegs = 1; \ - CLOCK_CYCLES(4); \ - PREFETCH_PREFIX(); \ - \ - if (opcode_table[(fetchdat & 0xff) | 0x300]) \ - return opcode_table[(fetchdat & 0xff) | 0x300](fetchdat >> 8); \ + } \ + \ + static int op##name##_l_a32(uint32_t fetchdat) \ + { \ + fetchdat = fastreadl(cs + cpu_state.pc); \ + if (cpu_state.abrt) \ + return 1; \ + cpu_state.pc++; \ + \ + cpu_state.ea_seg = &seg; \ + cpu_state.ssegs = 1; \ + CLOCK_CYCLES(4); \ + PREFETCH_PREFIX(); \ + \ + if (opcode_table[(fetchdat & 0xff) | 0x300]) \ + return opcode_table[(fetchdat & 0xff) | 0x300](fetchdat >> 8); \ return normal_opcode_table[(fetchdat & 0xff) | 0x300](fetchdat >> 8); \ -} + } +// clang-format off op_seg(CS, cpu_state.seg_cs, x86_opcodes, x86_opcodes) op_seg(DS, cpu_state.seg_ds, x86_opcodes, x86_opcodes) op_seg(ES, cpu_state.seg_es, x86_opcodes, x86_opcodes) @@ -83,79 +88,92 @@ op_seg(ES_REPNE, cpu_state.seg_es, x86_opcodes_REPNE, x86_opcodes) op_seg(FS_REPNE, cpu_state.seg_fs, x86_opcodes_REPNE, x86_opcodes) op_seg(GS_REPNE, cpu_state.seg_gs, x86_opcodes_REPNE, x86_opcodes) op_seg(SS_REPNE, cpu_state.seg_ss, x86_opcodes_REPNE, x86_opcodes) + // clang-format on -static int op_66(uint32_t fetchdat) /*Data size select*/ +static int +op_66(uint32_t fetchdat) /*Data size select*/ { - fetchdat = fastreadl(cs + cpu_state.pc); - if (cpu_state.abrt) return 1; - cpu_state.pc++; + fetchdat = fastreadl(cs + cpu_state.pc); + if (cpu_state.abrt) + return 1; + cpu_state.pc++; - cpu_state.op32 = ((use32 & 0x100) ^ 0x100) | (cpu_state.op32 & 0x200); - CLOCK_CYCLES(2); - PREFETCH_PREFIX(); - return x86_opcodes[(fetchdat & 0xff) | cpu_state.op32](fetchdat >> 8); + cpu_state.op32 = ((use32 & 0x100) ^ 0x100) | (cpu_state.op32 & 0x200); + CLOCK_CYCLES(2); + PREFETCH_PREFIX(); + return x86_opcodes[(fetchdat & 0xff) | cpu_state.op32](fetchdat >> 8); } -static int op_67(uint32_t fetchdat) /*Address size select*/ +static int +op_67(uint32_t fetchdat) /*Address size select*/ { - fetchdat = fastreadl(cs + cpu_state.pc); - if (cpu_state.abrt) return 1; - cpu_state.pc++; + fetchdat = fastreadl(cs + cpu_state.pc); + if (cpu_state.abrt) + return 1; + cpu_state.pc++; - cpu_state.op32 = ((use32 & 0x200) ^ 0x200) | (cpu_state.op32 & 0x100); - CLOCK_CYCLES(2); - PREFETCH_PREFIX(); - return x86_opcodes[(fetchdat & 0xff) | cpu_state.op32](fetchdat >> 8); + cpu_state.op32 = ((use32 & 0x200) ^ 0x200) | (cpu_state.op32 & 0x100); + CLOCK_CYCLES(2); + PREFETCH_PREFIX(); + return x86_opcodes[(fetchdat & 0xff) | cpu_state.op32](fetchdat >> 8); } -static int op_66_REPE(uint32_t fetchdat) /*Data size select*/ +static int +op_66_REPE(uint32_t fetchdat) /*Data size select*/ { - fetchdat = fastreadl(cs + cpu_state.pc); - if (cpu_state.abrt) return 1; - cpu_state.pc++; + fetchdat = fastreadl(cs + cpu_state.pc); + if (cpu_state.abrt) + return 1; + cpu_state.pc++; - cpu_state.op32 = ((use32 & 0x100) ^ 0x100) | (cpu_state.op32 & 0x200); - CLOCK_CYCLES(2); - PREFETCH_PREFIX(); - if (x86_opcodes_REPE[(fetchdat & 0xff) | cpu_state.op32]) - return x86_opcodes_REPE[(fetchdat & 0xff) | cpu_state.op32](fetchdat >> 8); - return x86_opcodes[(fetchdat & 0xff) | cpu_state.op32](fetchdat >> 8); + cpu_state.op32 = ((use32 & 0x100) ^ 0x100) | (cpu_state.op32 & 0x200); + CLOCK_CYCLES(2); + PREFETCH_PREFIX(); + if (x86_opcodes_REPE[(fetchdat & 0xff) | cpu_state.op32]) + return x86_opcodes_REPE[(fetchdat & 0xff) | cpu_state.op32](fetchdat >> 8); + return x86_opcodes[(fetchdat & 0xff) | cpu_state.op32](fetchdat >> 8); } -static int op_67_REPE(uint32_t fetchdat) /*Address size select*/ +static int +op_67_REPE(uint32_t fetchdat) /*Address size select*/ { - fetchdat = fastreadl(cs + cpu_state.pc); - if (cpu_state.abrt) return 1; - cpu_state.pc++; + fetchdat = fastreadl(cs + cpu_state.pc); + if (cpu_state.abrt) + return 1; + cpu_state.pc++; - cpu_state.op32 = ((use32 & 0x200) ^ 0x200) | (cpu_state.op32 & 0x100); - CLOCK_CYCLES(2); - PREFETCH_PREFIX(); - if (x86_opcodes_REPE[(fetchdat & 0xff) | cpu_state.op32]) - return x86_opcodes_REPE[(fetchdat & 0xff) | cpu_state.op32](fetchdat >> 8); - return x86_opcodes[(fetchdat & 0xff) | cpu_state.op32](fetchdat >> 8); + cpu_state.op32 = ((use32 & 0x200) ^ 0x200) | (cpu_state.op32 & 0x100); + CLOCK_CYCLES(2); + PREFETCH_PREFIX(); + if (x86_opcodes_REPE[(fetchdat & 0xff) | cpu_state.op32]) + return x86_opcodes_REPE[(fetchdat & 0xff) | cpu_state.op32](fetchdat >> 8); + return x86_opcodes[(fetchdat & 0xff) | cpu_state.op32](fetchdat >> 8); } -static int op_66_REPNE(uint32_t fetchdat) /*Data size select*/ +static int +op_66_REPNE(uint32_t fetchdat) /*Data size select*/ { - fetchdat = fastreadl(cs + cpu_state.pc); - if (cpu_state.abrt) return 1; - cpu_state.pc++; + fetchdat = fastreadl(cs + cpu_state.pc); + if (cpu_state.abrt) + return 1; + cpu_state.pc++; - cpu_state.op32 = ((use32 & 0x100) ^ 0x100) | (cpu_state.op32 & 0x200); - CLOCK_CYCLES(2); - PREFETCH_PREFIX(); - if (x86_opcodes_REPNE[(fetchdat & 0xff) | cpu_state.op32]) - return x86_opcodes_REPNE[(fetchdat & 0xff) | cpu_state.op32](fetchdat >> 8); - return x86_opcodes[(fetchdat & 0xff) | cpu_state.op32](fetchdat >> 8); + cpu_state.op32 = ((use32 & 0x100) ^ 0x100) | (cpu_state.op32 & 0x200); + CLOCK_CYCLES(2); + PREFETCH_PREFIX(); + if (x86_opcodes_REPNE[(fetchdat & 0xff) | cpu_state.op32]) + return x86_opcodes_REPNE[(fetchdat & 0xff) | cpu_state.op32](fetchdat >> 8); + return x86_opcodes[(fetchdat & 0xff) | cpu_state.op32](fetchdat >> 8); } -static int op_67_REPNE(uint32_t fetchdat) /*Address size select*/ +static int +op_67_REPNE(uint32_t fetchdat) /*Address size select*/ { - fetchdat = fastreadl(cs + cpu_state.pc); - if (cpu_state.abrt) return 1; - cpu_state.pc++; + fetchdat = fastreadl(cs + cpu_state.pc); + if (cpu_state.abrt) + return 1; + cpu_state.pc++; - cpu_state.op32 = ((use32 & 0x200) ^ 0x200) | (cpu_state.op32 & 0x100); - CLOCK_CYCLES(2); - PREFETCH_PREFIX(); - if (x86_opcodes_REPNE[(fetchdat & 0xff) | cpu_state.op32]) - return x86_opcodes_REPNE[(fetchdat & 0xff) | cpu_state.op32](fetchdat >> 8); - return x86_opcodes[(fetchdat & 0xff) | cpu_state.op32](fetchdat >> 8); + cpu_state.op32 = ((use32 & 0x200) ^ 0x200) | (cpu_state.op32 & 0x100); + CLOCK_CYCLES(2); + PREFETCH_PREFIX(); + if (x86_opcodes_REPNE[(fetchdat & 0xff) | cpu_state.op32]) + return x86_opcodes_REPNE[(fetchdat & 0xff) | cpu_state.op32](fetchdat >> 8); + return x86_opcodes[(fetchdat & 0xff) | cpu_state.op32](fetchdat >> 8); } diff --git a/src/cpu/x86_ops_rep.h b/src/cpu/x86_ops_rep.h index d76613151..a49db7e81 100644 --- a/src/cpu/x86_ops_rep.h +++ b/src/cpu/x86_ops_rep.h @@ -1,768 +1,875 @@ -#define REP_OPS(size, CNT_REG, SRC_REG, DEST_REG) \ -static int opREP_INSB_ ## size(uint32_t fetchdat) \ -{ \ - int reads = 0, writes = 0, total_cycles = 0; \ - \ - addr64 = 0x00000000; \ - \ - if (CNT_REG > 0) \ - { \ - uint8_t temp; \ - \ - SEG_CHECK_WRITE(&cpu_state.seg_es); \ - check_io_perm(DX); \ - CHECK_WRITE(&cpu_state.seg_es, DEST_REG, DEST_REG); \ - high_page = 0; \ - do_mmut_wb(es, DEST_REG, &addr64); \ - if (cpu_state.abrt) return 1; \ - temp = inb(DX); \ - writememb_n(es, DEST_REG, addr64, temp); if (cpu_state.abrt) return 1; \ - \ - if (cpu_state.flags & D_FLAG) DEST_REG--; \ - else DEST_REG++; \ - CNT_REG--; \ - cycles -= 15; \ - reads++; writes++; total_cycles += 15; \ - } \ - PREFETCH_RUN(total_cycles, 1, -1, reads, 0, writes, 0, 0); \ - if (CNT_REG > 0) \ - { \ - CPU_BLOCK_END(); \ - cpu_state.pc = cpu_state.oldpc; \ - return 1; \ - } \ - return cpu_state.abrt; \ -} \ -static int opREP_INSW_ ## size(uint32_t fetchdat) \ -{ \ - int reads = 0, writes = 0, total_cycles = 0; \ - \ - addr64a[0] = addr64a[1] = 0x00000000; \ - \ - if (CNT_REG > 0) \ - { \ - uint16_t temp; \ - \ - SEG_CHECK_WRITE(&cpu_state.seg_es); \ - check_io_perm(DX); \ - check_io_perm(DX+1); \ - CHECK_WRITE(&cpu_state.seg_es, DEST_REG, DEST_REG + 1UL); \ - high_page = 0; \ - do_mmut_ww(es, DEST_REG, addr64a); \ - if (cpu_state.abrt) return 1; \ - temp = inw(DX); \ - writememw_n(es, DEST_REG, addr64a, temp); if (cpu_state.abrt) return 1; \ - \ - if (cpu_state.flags & D_FLAG) DEST_REG -= 2; \ - else DEST_REG += 2; \ - CNT_REG--; \ - cycles -= 15; \ - reads++; writes++; total_cycles += 15; \ - } \ - PREFETCH_RUN(total_cycles, 1, -1, reads, 0, writes, 0, 0); \ - if (CNT_REG > 0) \ - { \ - CPU_BLOCK_END(); \ - cpu_state.pc = cpu_state.oldpc; \ - return 1; \ - } \ - return cpu_state.abrt; \ -} \ -static int opREP_INSL_ ## size(uint32_t fetchdat) \ -{ \ - int reads = 0, writes = 0, total_cycles = 0; \ - \ - addr64a[0] = addr64a[1] = addr64a[2] = addr64a[3] = 0x00000000; \ - \ - if (CNT_REG > 0) \ - { \ - uint32_t temp; \ - \ - SEG_CHECK_WRITE(&cpu_state.seg_es); \ - check_io_perm(DX); \ - check_io_perm(DX+1); \ - check_io_perm(DX+2); \ - check_io_perm(DX+3); \ - CHECK_WRITE(&cpu_state.seg_es, DEST_REG, DEST_REG + 3UL); \ - high_page = 0; \ - do_mmut_wl(es, DEST_REG, addr64a); \ - if (cpu_state.abrt) return 1; \ - temp = inl(DX); \ - writememl_n(es, DEST_REG, addr64a, temp); if (cpu_state.abrt) return 1; \ - \ - if (cpu_state.flags & D_FLAG) DEST_REG -= 4; \ - else DEST_REG += 4; \ - CNT_REG--; \ - cycles -= 15; \ - reads++; writes++; total_cycles += 15; \ - } \ - PREFETCH_RUN(total_cycles, 1, -1, 0, reads, 0, writes, 0); \ - if (CNT_REG > 0) \ - { \ - CPU_BLOCK_END(); \ - cpu_state.pc = cpu_state.oldpc; \ - return 1; \ - } \ - return cpu_state.abrt; \ -} \ - \ -static int opREP_OUTSB_ ## size(uint32_t fetchdat) \ -{ \ - int reads = 0, writes = 0, total_cycles = 0; \ - \ - if (CNT_REG > 0) \ - { \ - uint8_t temp; \ - SEG_CHECK_READ(cpu_state.ea_seg); \ - CHECK_READ(cpu_state.ea_seg, SRC_REG, SRC_REG); \ - temp = readmemb(cpu_state.ea_seg->base, SRC_REG); if (cpu_state.abrt) return 1; \ - check_io_perm(DX); \ - outb(DX, temp); \ - if (cpu_state.flags & D_FLAG) SRC_REG--; \ - else SRC_REG++; \ - CNT_REG--; \ - cycles -= 14; \ - reads++; writes++; total_cycles += 14; \ - } \ - PREFETCH_RUN(total_cycles, 1, -1, reads, 0, writes, 0, 0); \ - if (CNT_REG > 0) \ - { \ - CPU_BLOCK_END(); \ - cpu_state.pc = cpu_state.oldpc; \ - return 1; \ - } \ - return cpu_state.abrt; \ -} \ -static int opREP_OUTSW_ ## size(uint32_t fetchdat) \ -{ \ - int reads = 0, writes = 0, total_cycles = 0; \ - \ - if (CNT_REG > 0) \ - { \ - uint16_t temp; \ - SEG_CHECK_READ(cpu_state.ea_seg); \ - CHECK_READ(cpu_state.ea_seg, SRC_REG, SRC_REG + 1UL); \ - temp = readmemw(cpu_state.ea_seg->base, SRC_REG); if (cpu_state.abrt) return 1; \ - check_io_perm(DX); \ - check_io_perm(DX+1); \ - outw(DX, temp); \ - if (cpu_state.flags & D_FLAG) SRC_REG -= 2; \ - else SRC_REG += 2; \ - CNT_REG--; \ - cycles -= 14; \ - reads++; writes++; total_cycles += 14; \ - } \ - PREFETCH_RUN(total_cycles, 1, -1, reads, 0, writes, 0, 0); \ - if (CNT_REG > 0) \ - { \ - CPU_BLOCK_END(); \ - cpu_state.pc = cpu_state.oldpc; \ - return 1; \ - } \ - return cpu_state.abrt; \ -} \ -static int opREP_OUTSL_ ## size(uint32_t fetchdat) \ -{ \ - int reads = 0, writes = 0, total_cycles = 0; \ - \ - if (CNT_REG > 0) \ - { \ - uint32_t temp; \ - SEG_CHECK_READ(cpu_state.ea_seg); \ - CHECK_READ(cpu_state.ea_seg, SRC_REG, SRC_REG + 3UL); \ - temp = readmeml(cpu_state.ea_seg->base, SRC_REG); if (cpu_state.abrt) return 1; \ - check_io_perm(DX); \ - check_io_perm(DX+1); \ - check_io_perm(DX+2); \ - check_io_perm(DX+3); \ - outl(DX, temp); \ - if (cpu_state.flags & D_FLAG) SRC_REG -= 4; \ - else SRC_REG += 4; \ - CNT_REG--; \ - cycles -= 14; \ - reads++; writes++; total_cycles += 14; \ - } \ - PREFETCH_RUN(total_cycles, 1, -1, 0, reads, 0, writes, 0); \ - if (CNT_REG > 0) \ - { \ - CPU_BLOCK_END(); \ - cpu_state.pc = cpu_state.oldpc; \ - return 1; \ - } \ - return cpu_state.abrt; \ -} \ - \ -static int opREP_MOVSB_ ## size(uint32_t fetchdat) \ -{ \ - int reads = 0, writes = 0, total_cycles = 0; \ - int cycles_end = cycles - ((is386 && cpu_use_dynarec) ? 1000 : 100); \ - addr64 = addr64_2 = 0x00000000; \ - if (trap) \ - cycles_end = cycles+1; /*Force the instruction to end after only one iteration when trap flag set*/ \ - if (CNT_REG > 0) \ - { \ - SEG_CHECK_READ(cpu_state.ea_seg); \ - SEG_CHECK_WRITE(&cpu_state.seg_es); \ - } \ - while (CNT_REG > 0) \ - { \ - uint8_t temp; \ - \ - CHECK_READ_REP(cpu_state.ea_seg, SRC_REG, SRC_REG); \ - high_page = 0; \ - do_mmut_rb(cpu_state.ea_seg->base, SRC_REG, &addr64) ; \ - if (cpu_state.abrt) break; \ - CHECK_WRITE_REP(&cpu_state.seg_es, DEST_REG, DEST_REG); \ - do_mmut_wb(es, DEST_REG, &addr64_2); \ - if (cpu_state.abrt) break; \ - temp = readmemb_n(cpu_state.ea_seg->base, SRC_REG, addr64); if (cpu_state.abrt) return 1; \ - writememb_n(es, DEST_REG, addr64_2, temp); if (cpu_state.abrt) return 1; \ - \ - if (cpu_state.flags & D_FLAG) { DEST_REG--; SRC_REG--; } \ - else { DEST_REG++; SRC_REG++; } \ - CNT_REG--; \ - cycles -= is486 ? 3 : 4; \ - reads++; writes++; total_cycles += is486 ? 3 : 4; \ - if (cycles < cycles_end) \ - break; \ - } \ - PREFETCH_RUN(total_cycles, 1, -1, reads, 0, writes, 0, 0); \ - if (CNT_REG > 0) \ - { \ - CPU_BLOCK_END(); \ - cpu_state.pc = cpu_state.oldpc; \ - return 1; \ - } \ - return cpu_state.abrt; \ -} \ -static int opREP_MOVSW_ ## size(uint32_t fetchdat) \ -{ \ - int reads = 0, writes = 0, total_cycles = 0; \ - int cycles_end = cycles - ((is386 && cpu_use_dynarec) ? 1000 : 100); \ - addr64a[0] = addr64a[1] = 0x00000000; \ - addr64a_2[0] = addr64a_2[1] = 0x00000000; \ - if (trap) \ - cycles_end = cycles+1; /*Force the instruction to end after only one iteration when trap flag set*/ \ - if (CNT_REG > 0) \ - { \ - SEG_CHECK_READ(cpu_state.ea_seg); \ - SEG_CHECK_WRITE(&cpu_state.seg_es); \ - } \ - while (CNT_REG > 0) \ - { \ - uint16_t temp; \ - \ - CHECK_READ_REP(cpu_state.ea_seg, SRC_REG, SRC_REG + 1UL); \ - high_page = 0; \ - do_mmut_rw(cpu_state.ea_seg->base, SRC_REG, addr64a); \ - if (cpu_state.abrt) break; \ - CHECK_WRITE_REP(&cpu_state.seg_es, DEST_REG, DEST_REG + 1UL); \ - do_mmut_ww(es, DEST_REG, addr64a_2); \ - if (cpu_state.abrt) break; \ - temp = readmemw_n(cpu_state.ea_seg->base, SRC_REG, addr64a); if (cpu_state.abrt) return 1; \ - writememw_n(es, DEST_REG, addr64a_2, temp); if (cpu_state.abrt) return 1; \ - \ - if (cpu_state.flags & D_FLAG) { DEST_REG -= 2; SRC_REG -= 2; } \ - else { DEST_REG += 2; SRC_REG += 2; } \ - CNT_REG--; \ - cycles -= is486 ? 3 : 4; \ - reads++; writes++; total_cycles += is486 ? 3 : 4; \ - if (cycles < cycles_end) \ - break; \ - } \ - PREFETCH_RUN(total_cycles, 1, -1, reads, 0, writes, 0, 0); \ - if (CNT_REG > 0) \ - { \ - CPU_BLOCK_END(); \ - cpu_state.pc = cpu_state.oldpc; \ - return 1; \ - } \ - return cpu_state.abrt; \ -} \ -static int opREP_MOVSL_ ## size(uint32_t fetchdat) \ -{ \ - int reads = 0, writes = 0, total_cycles = 0; \ - int cycles_end = cycles - ((is386 && cpu_use_dynarec) ? 1000 : 100); \ - addr64a[0] = addr64a[1] = addr64a[2] = addr64a[3] = 0x00000000; \ - addr64a_2[0] = addr64a_2[1] = addr64a_2[2] = addr64a_2[3] = 0x00000000; \ - if (trap) \ - cycles_end = cycles+1; /*Force the instruction to end after only one iteration when trap flag set*/ \ - if (CNT_REG > 0) \ - { \ - SEG_CHECK_READ(cpu_state.ea_seg); \ - SEG_CHECK_WRITE(&cpu_state.seg_es); \ - } \ - while (CNT_REG > 0) \ - { \ - uint32_t temp; \ - \ - CHECK_READ_REP(cpu_state.ea_seg, SRC_REG, SRC_REG + 3UL); \ - high_page = 0; \ - do_mmut_rl(cpu_state.ea_seg->base, SRC_REG, addr64a); \ - if (cpu_state.abrt) break; \ - CHECK_WRITE_REP(&cpu_state.seg_es, DEST_REG, DEST_REG + 3UL); \ - do_mmut_wl(es, DEST_REG, addr64a_2); \ - if (cpu_state.abrt) break; \ - temp = readmeml_n(cpu_state.ea_seg->base, SRC_REG, addr64a); if (cpu_state.abrt) return 1; \ - writememl_n(es, DEST_REG, addr64a_2, temp); if (cpu_state.abrt) return 1; \ - \ - if (cpu_state.flags & D_FLAG) { DEST_REG -= 4; SRC_REG -= 4; } \ - else { DEST_REG += 4; SRC_REG += 4; } \ - CNT_REG--; \ - cycles -= is486 ? 3 : 4; \ - reads++; writes++; total_cycles += is486 ? 3 : 4; \ - if (cycles < cycles_end) \ - break; \ - } \ - PREFETCH_RUN(total_cycles, 1, -1, reads, 0, writes, 0, 0); \ - if (CNT_REG > 0) \ - { \ - CPU_BLOCK_END(); \ - cpu_state.pc = cpu_state.oldpc; \ - return 1; \ - } \ - return cpu_state.abrt; \ -} \ - \ - \ -static int opREP_STOSB_ ## size(uint32_t fetchdat) \ -{ \ - int writes = 0, total_cycles = 0; \ - int cycles_end = cycles - ((is386 && cpu_use_dynarec) ? 1000 : 100); \ - if (trap) \ - cycles_end = cycles+1; /*Force the instruction to end after only one iteration when trap flag set*/ \ - if (CNT_REG > 0) \ - SEG_CHECK_WRITE(&cpu_state.seg_es); \ - while (CNT_REG > 0) \ - { \ - CHECK_WRITE_REP(&cpu_state.seg_es, DEST_REG, DEST_REG); \ - writememb(es, DEST_REG, AL); if (cpu_state.abrt) return 1; \ - if (cpu_state.flags & D_FLAG) DEST_REG--; \ - else DEST_REG++; \ - CNT_REG--; \ - cycles -= is486 ? 4 : 5; \ - writes++; total_cycles += is486 ? 4 : 5; \ - if (cycles < cycles_end) \ - break; \ - } \ - PREFETCH_RUN(total_cycles, 1, -1, 0, 0, writes, 0, 0); \ - if (CNT_REG > 0) \ - { \ - CPU_BLOCK_END(); \ - cpu_state.pc = cpu_state.oldpc; \ - return 1; \ - } \ - return cpu_state.abrt; \ -} \ -static int opREP_STOSW_ ## size(uint32_t fetchdat) \ -{ \ - int writes = 0, total_cycles = 0; \ - int cycles_end = cycles - ((is386 && cpu_use_dynarec) ? 1000 : 100); \ - if (trap) \ - cycles_end = cycles+1; /*Force the instruction to end after only one iteration when trap flag set*/ \ - if (CNT_REG > 0) \ - SEG_CHECK_WRITE(&cpu_state.seg_es); \ - while (CNT_REG > 0) \ - { \ - CHECK_WRITE_REP(&cpu_state.seg_es, DEST_REG, DEST_REG + 1UL); \ - writememw(es, DEST_REG, AX); if (cpu_state.abrt) return 1; \ - if (cpu_state.flags & D_FLAG) DEST_REG -= 2; \ - else DEST_REG += 2; \ - CNT_REG--; \ - cycles -= is486 ? 4 : 5; \ - writes++; total_cycles += is486 ? 4 : 5; \ - if (cycles < cycles_end) \ - break; \ - } \ - PREFETCH_RUN(total_cycles, 1, -1, 0, 0, writes, 0, 0); \ - if (CNT_REG > 0) \ - { \ - CPU_BLOCK_END(); \ - cpu_state.pc = cpu_state.oldpc; \ - return 1; \ - } \ - return cpu_state.abrt; \ -} \ -static int opREP_STOSL_ ## size(uint32_t fetchdat) \ -{ \ - int writes = 0, total_cycles = 0; \ - int cycles_end = cycles - ((is386 && cpu_use_dynarec) ? 1000 : 100); \ - if (trap) \ - cycles_end = cycles+1; /*Force the instruction to end after only one iteration when trap flag set*/ \ - if (CNT_REG > 0) \ - SEG_CHECK_WRITE(&cpu_state.seg_es); \ - while (CNT_REG > 0) \ - { \ - CHECK_WRITE_REP(&cpu_state.seg_es, DEST_REG, DEST_REG + 3UL); \ - writememl(es, DEST_REG, EAX); if (cpu_state.abrt) return 1; \ - if (cpu_state.flags & D_FLAG) DEST_REG -= 4; \ - else DEST_REG += 4; \ - CNT_REG--; \ - cycles -= is486 ? 4 : 5; \ - writes++; total_cycles += is486 ? 4 : 5; \ - if (cycles < cycles_end) \ - break; \ - } \ - PREFETCH_RUN(total_cycles, 1, -1, 0, 0, 0, writes, 0); \ - if (CNT_REG > 0) \ - { \ - CPU_BLOCK_END(); \ - cpu_state.pc = cpu_state.oldpc; \ - return 1; \ - } \ - return cpu_state.abrt; \ -} \ - \ -static int opREP_LODSB_ ## size(uint32_t fetchdat) \ -{ \ - int reads = 0, total_cycles = 0; \ - int cycles_end = cycles - ((is386 && cpu_use_dynarec) ? 1000 : 100); \ - if (trap) \ - cycles_end = cycles+1; /*Force the instruction to end after only one iteration when trap flag set*/ \ - if (CNT_REG > 0) \ - SEG_CHECK_READ(cpu_state.ea_seg); \ - while (CNT_REG > 0) \ - { \ - CHECK_READ_REP(cpu_state.ea_seg, SRC_REG, SRC_REG); \ - AL = readmemb(cpu_state.ea_seg->base, SRC_REG); if (cpu_state.abrt) return 1; \ - if (cpu_state.flags & D_FLAG) SRC_REG--; \ - else SRC_REG++; \ - CNT_REG--; \ - cycles -= is486 ? 4 : 5; \ - reads++; total_cycles += is486 ? 4 : 5; \ - if (cycles < cycles_end) \ - break; \ - } \ - PREFETCH_RUN(total_cycles, 1, -1, reads, 0, 0, 0, 0); \ - if (CNT_REG > 0) \ - { \ - CPU_BLOCK_END(); \ - cpu_state.pc = cpu_state.oldpc; \ - return 1; \ - } \ - return cpu_state.abrt; \ -} \ -static int opREP_LODSW_ ## size(uint32_t fetchdat) \ -{ \ - int reads = 0, total_cycles = 0; \ - int cycles_end = cycles - ((is386 && cpu_use_dynarec) ? 1000 : 100); \ - if (trap) \ - cycles_end = cycles+1; /*Force the instruction to end after only one iteration when trap flag set*/ \ - if (CNT_REG > 0) \ - SEG_CHECK_READ(cpu_state.ea_seg); \ - while (CNT_REG > 0) \ - { \ - CHECK_READ_REP(cpu_state.ea_seg, SRC_REG, SRC_REG + 1UL); \ - AX = readmemw(cpu_state.ea_seg->base, SRC_REG); if (cpu_state.abrt) return 1; \ - if (cpu_state.flags & D_FLAG) SRC_REG -= 2; \ - else SRC_REG += 2; \ - CNT_REG--; \ - cycles -= is486 ? 4 : 5; \ - reads++; total_cycles += is486 ? 4 : 5; \ - if (cycles < cycles_end) \ - break; \ - } \ - PREFETCH_RUN(total_cycles, 1, -1, reads, 0, 0, 0, 0); \ - if (CNT_REG > 0) \ - { \ - CPU_BLOCK_END(); \ - cpu_state.pc = cpu_state.oldpc; \ - return 1; \ - } \ - return cpu_state.abrt; \ -} \ -static int opREP_LODSL_ ## size(uint32_t fetchdat) \ -{ \ - int reads = 0, total_cycles = 0; \ - int cycles_end = cycles - ((is386 && cpu_use_dynarec) ? 1000 : 100); \ - if (trap) \ - cycles_end = cycles+1; /*Force the instruction to end after only one iteration when trap flag set*/ \ - if (CNT_REG > 0) \ - SEG_CHECK_READ(cpu_state.ea_seg); \ - while (CNT_REG > 0) \ - { \ - CHECK_READ_REP(cpu_state.ea_seg, SRC_REG, SRC_REG + 3UL); \ - EAX = readmeml(cpu_state.ea_seg->base, SRC_REG); if (cpu_state.abrt) return 1; \ - if (cpu_state.flags & D_FLAG) SRC_REG -= 4; \ - else SRC_REG += 4; \ - CNT_REG--; \ - cycles -= is486 ? 4 : 5; \ - reads++; total_cycles += is486 ? 4 : 5; \ - if (cycles < cycles_end) \ - break; \ - } \ - PREFETCH_RUN(total_cycles, 1, -1, 0, reads, 0, 0, 0); \ - if (CNT_REG > 0) \ - { \ - CPU_BLOCK_END(); \ - cpu_state.pc = cpu_state.oldpc; \ - return 1; \ - } \ - return cpu_state.abrt; \ -} \ - +#define REP_OPS(size, CNT_REG, SRC_REG, DEST_REG) \ + static int opREP_INSB_##size(uint32_t fetchdat) \ + { \ + int reads = 0, writes = 0, total_cycles = 0; \ + \ + addr64 = 0x00000000; \ + \ + if (CNT_REG > 0) { \ + uint8_t temp; \ + \ + SEG_CHECK_WRITE(&cpu_state.seg_es); \ + check_io_perm(DX, 1); \ + CHECK_WRITE(&cpu_state.seg_es, DEST_REG, DEST_REG); \ + high_page = 0; \ + do_mmut_wb(es, DEST_REG, &addr64); \ + if (cpu_state.abrt) \ + return 1; \ + temp = inb(DX); \ + writememb_n(es, DEST_REG, addr64, temp); \ + if (cpu_state.abrt) \ + return 1; \ + \ + if (cpu_state.flags & D_FLAG) \ + DEST_REG--; \ + else \ + DEST_REG++; \ + CNT_REG--; \ + cycles -= 15; \ + reads++; \ + writes++; \ + total_cycles += 15; \ + } \ + PREFETCH_RUN(total_cycles, 1, -1, reads, 0, writes, 0, 0); \ + if (CNT_REG > 0) { \ + CPU_BLOCK_END(); \ + cpu_state.pc = cpu_state.oldpc; \ + return 1; \ + } \ + return cpu_state.abrt; \ + } \ + static int opREP_INSW_##size(uint32_t fetchdat) \ + { \ + int reads = 0, writes = 0, total_cycles = 0; \ + \ + addr64a[0] = addr64a[1] = 0x00000000; \ + \ + if (CNT_REG > 0) { \ + uint16_t temp; \ + \ + SEG_CHECK_WRITE(&cpu_state.seg_es); \ + check_io_perm(DX, 2); \ + CHECK_WRITE(&cpu_state.seg_es, DEST_REG, DEST_REG + 1UL); \ + high_page = 0; \ + do_mmut_ww(es, DEST_REG, addr64a); \ + if (cpu_state.abrt) \ + return 1; \ + temp = inw(DX); \ + writememw_n(es, DEST_REG, addr64a, temp); \ + if (cpu_state.abrt) \ + return 1; \ + \ + if (cpu_state.flags & D_FLAG) \ + DEST_REG -= 2; \ + else \ + DEST_REG += 2; \ + CNT_REG--; \ + cycles -= 15; \ + reads++; \ + writes++; \ + total_cycles += 15; \ + } \ + PREFETCH_RUN(total_cycles, 1, -1, reads, 0, writes, 0, 0); \ + if (CNT_REG > 0) { \ + CPU_BLOCK_END(); \ + cpu_state.pc = cpu_state.oldpc; \ + return 1; \ + } \ + return cpu_state.abrt; \ + } \ + static int opREP_INSL_##size(uint32_t fetchdat) \ + { \ + int reads = 0, writes = 0, total_cycles = 0; \ + \ + addr64a[0] = addr64a[1] = addr64a[2] = addr64a[3] = 0x00000000; \ + \ + if (CNT_REG > 0) { \ + uint32_t temp; \ + \ + SEG_CHECK_WRITE(&cpu_state.seg_es); \ + check_io_perm(DX, 4); \ + CHECK_WRITE(&cpu_state.seg_es, DEST_REG, DEST_REG + 3UL); \ + high_page = 0; \ + do_mmut_wl(es, DEST_REG, addr64a); \ + if (cpu_state.abrt) \ + return 1; \ + temp = inl(DX); \ + writememl_n(es, DEST_REG, addr64a, temp); \ + if (cpu_state.abrt) \ + return 1; \ + \ + if (cpu_state.flags & D_FLAG) \ + DEST_REG -= 4; \ + else \ + DEST_REG += 4; \ + CNT_REG--; \ + cycles -= 15; \ + reads++; \ + writes++; \ + total_cycles += 15; \ + } \ + PREFETCH_RUN(total_cycles, 1, -1, 0, reads, 0, writes, 0); \ + if (CNT_REG > 0) { \ + CPU_BLOCK_END(); \ + cpu_state.pc = cpu_state.oldpc; \ + return 1; \ + } \ + return cpu_state.abrt; \ + } \ + \ + static int opREP_OUTSB_##size(uint32_t fetchdat) \ + { \ + int reads = 0, writes = 0, total_cycles = 0; \ + \ + if (CNT_REG > 0) { \ + uint8_t temp; \ + SEG_CHECK_READ(cpu_state.ea_seg); \ + CHECK_READ(cpu_state.ea_seg, SRC_REG, SRC_REG); \ + temp = readmemb(cpu_state.ea_seg->base, SRC_REG); \ + if (cpu_state.abrt) \ + return 1; \ + check_io_perm(DX, 1); \ + outb(DX, temp); \ + if (cpu_state.flags & D_FLAG) \ + SRC_REG--; \ + else \ + SRC_REG++; \ + CNT_REG--; \ + cycles -= 14; \ + reads++; \ + writes++; \ + total_cycles += 14; \ + } \ + PREFETCH_RUN(total_cycles, 1, -1, reads, 0, writes, 0, 0); \ + if (CNT_REG > 0) { \ + CPU_BLOCK_END(); \ + cpu_state.pc = cpu_state.oldpc; \ + return 1; \ + } \ + return cpu_state.abrt; \ + } \ + static int opREP_OUTSW_##size(uint32_t fetchdat) \ + { \ + int reads = 0, writes = 0, total_cycles = 0; \ + \ + if (CNT_REG > 0) { \ + uint16_t temp; \ + SEG_CHECK_READ(cpu_state.ea_seg); \ + CHECK_READ(cpu_state.ea_seg, SRC_REG, SRC_REG + 1UL); \ + temp = readmemw(cpu_state.ea_seg->base, SRC_REG); \ + if (cpu_state.abrt) \ + return 1; \ + check_io_perm(DX, 2); \ + outw(DX, temp); \ + if (cpu_state.flags & D_FLAG) \ + SRC_REG -= 2; \ + else \ + SRC_REG += 2; \ + CNT_REG--; \ + cycles -= 14; \ + reads++; \ + writes++; \ + total_cycles += 14; \ + } \ + PREFETCH_RUN(total_cycles, 1, -1, reads, 0, writes, 0, 0); \ + if (CNT_REG > 0) { \ + CPU_BLOCK_END(); \ + cpu_state.pc = cpu_state.oldpc; \ + return 1; \ + } \ + return cpu_state.abrt; \ + } \ + static int opREP_OUTSL_##size(uint32_t fetchdat) \ + { \ + int reads = 0, writes = 0, total_cycles = 0; \ + \ + if (CNT_REG > 0) { \ + uint32_t temp; \ + SEG_CHECK_READ(cpu_state.ea_seg); \ + CHECK_READ(cpu_state.ea_seg, SRC_REG, SRC_REG + 3UL); \ + temp = readmeml(cpu_state.ea_seg->base, SRC_REG); \ + if (cpu_state.abrt) \ + return 1; \ + check_io_perm(DX, 4); \ + outl(DX, temp); \ + if (cpu_state.flags & D_FLAG) \ + SRC_REG -= 4; \ + else \ + SRC_REG += 4; \ + CNT_REG--; \ + cycles -= 14; \ + reads++; \ + writes++; \ + total_cycles += 14; \ + } \ + PREFETCH_RUN(total_cycles, 1, -1, 0, reads, 0, writes, 0); \ + if (CNT_REG > 0) { \ + CPU_BLOCK_END(); \ + cpu_state.pc = cpu_state.oldpc; \ + return 1; \ + } \ + return cpu_state.abrt; \ + } \ + \ + static int opREP_MOVSB_##size(uint32_t fetchdat) \ + { \ + int reads = 0, writes = 0, total_cycles = 0; \ + int cycles_end = cycles - ((is386 && cpu_use_dynarec) ? 1000 : 100); \ + addr64 = addr64_2 = 0x00000000; \ + if (trap) \ + cycles_end = cycles + 1; /*Force the instruction to end after only one iteration when trap flag set*/ \ + if (CNT_REG > 0) { \ + SEG_CHECK_READ(cpu_state.ea_seg); \ + SEG_CHECK_WRITE(&cpu_state.seg_es); \ + } \ + while (CNT_REG > 0) { \ + uint8_t temp; \ + \ + CHECK_READ_REP(cpu_state.ea_seg, SRC_REG, SRC_REG); \ + CHECK_WRITE_REP(&cpu_state.seg_es, DEST_REG, DEST_REG); \ + high_page = 0; \ + do_mmut_rb(cpu_state.ea_seg->base, SRC_REG, &addr64); \ + if (cpu_state.abrt) \ + break; \ + do_mmut_wb(es, DEST_REG, &addr64_2); \ + if (cpu_state.abrt) \ + break; \ + temp = readmemb_n(cpu_state.ea_seg->base, SRC_REG, addr64); \ + if (cpu_state.abrt) \ + return 1; \ + writememb_n(es, DEST_REG, addr64_2, temp); \ + if (cpu_state.abrt) \ + return 1; \ + \ + if (cpu_state.flags & D_FLAG) { \ + DEST_REG--; \ + SRC_REG--; \ + } else { \ + DEST_REG++; \ + SRC_REG++; \ + } \ + CNT_REG--; \ + cycles -= is486 ? 3 : 4; \ + reads++; \ + writes++; \ + total_cycles += is486 ? 3 : 4; \ + if (cycles < cycles_end) \ + break; \ + } \ + PREFETCH_RUN(total_cycles, 1, -1, reads, 0, writes, 0, 0); \ + if (CNT_REG > 0) { \ + CPU_BLOCK_END(); \ + cpu_state.pc = cpu_state.oldpc; \ + return 1; \ + } \ + return cpu_state.abrt; \ + } \ + static int opREP_MOVSW_##size(uint32_t fetchdat) \ + { \ + int reads = 0, writes = 0, total_cycles = 0; \ + int cycles_end = cycles - ((is386 && cpu_use_dynarec) ? 1000 : 100); \ + addr64a[0] = addr64a[1] = 0x00000000; \ + addr64a_2[0] = addr64a_2[1] = 0x00000000; \ + if (trap) \ + cycles_end = cycles + 1; /*Force the instruction to end after only one iteration when trap flag set*/ \ + if (CNT_REG > 0) { \ + SEG_CHECK_READ(cpu_state.ea_seg); \ + SEG_CHECK_WRITE(&cpu_state.seg_es); \ + } \ + while (CNT_REG > 0) { \ + uint16_t temp; \ + \ + CHECK_READ_REP(cpu_state.ea_seg, SRC_REG, SRC_REG + 1UL); \ + CHECK_WRITE_REP(&cpu_state.seg_es, DEST_REG, DEST_REG + 1UL); \ + high_page = 0; \ + do_mmut_rw(cpu_state.ea_seg->base, SRC_REG, addr64a); \ + if (cpu_state.abrt) \ + break; \ + do_mmut_ww(es, DEST_REG, addr64a_2); \ + if (cpu_state.abrt) \ + break; \ + temp = readmemw_n(cpu_state.ea_seg->base, SRC_REG, addr64a); \ + if (cpu_state.abrt) \ + return 1; \ + writememw_n(es, DEST_REG, addr64a_2, temp); \ + if (cpu_state.abrt) \ + return 1; \ + \ + if (cpu_state.flags & D_FLAG) { \ + DEST_REG -= 2; \ + SRC_REG -= 2; \ + } else { \ + DEST_REG += 2; \ + SRC_REG += 2; \ + } \ + CNT_REG--; \ + cycles -= is486 ? 3 : 4; \ + reads++; \ + writes++; \ + total_cycles += is486 ? 3 : 4; \ + if (cycles < cycles_end) \ + break; \ + } \ + PREFETCH_RUN(total_cycles, 1, -1, reads, 0, writes, 0, 0); \ + if (CNT_REG > 0) { \ + CPU_BLOCK_END(); \ + cpu_state.pc = cpu_state.oldpc; \ + return 1; \ + } \ + return cpu_state.abrt; \ + } \ + static int opREP_MOVSL_##size(uint32_t fetchdat) \ + { \ + int reads = 0, writes = 0, total_cycles = 0; \ + int cycles_end = cycles - ((is386 && cpu_use_dynarec) ? 1000 : 100); \ + addr64a[0] = addr64a[1] = addr64a[2] = addr64a[3] = 0x00000000; \ + addr64a_2[0] = addr64a_2[1] = addr64a_2[2] = addr64a_2[3] = 0x00000000; \ + if (trap) \ + cycles_end = cycles + 1; /*Force the instruction to end after only one iteration when trap flag set*/ \ + if (CNT_REG > 0) { \ + SEG_CHECK_READ(cpu_state.ea_seg); \ + SEG_CHECK_WRITE(&cpu_state.seg_es); \ + } \ + while (CNT_REG > 0) { \ + uint32_t temp; \ + \ + CHECK_READ_REP(cpu_state.ea_seg, SRC_REG, SRC_REG + 3UL); \ + CHECK_WRITE_REP(&cpu_state.seg_es, DEST_REG, DEST_REG + 3UL); \ + high_page = 0; \ + do_mmut_rl(cpu_state.ea_seg->base, SRC_REG, addr64a); \ + if (cpu_state.abrt) \ + break; \ + do_mmut_wl(es, DEST_REG, addr64a_2); \ + if (cpu_state.abrt) \ + break; \ + temp = readmeml_n(cpu_state.ea_seg->base, SRC_REG, addr64a); \ + if (cpu_state.abrt) \ + return 1; \ + writememl_n(es, DEST_REG, addr64a_2, temp); \ + if (cpu_state.abrt) \ + return 1; \ + \ + if (cpu_state.flags & D_FLAG) { \ + DEST_REG -= 4; \ + SRC_REG -= 4; \ + } else { \ + DEST_REG += 4; \ + SRC_REG += 4; \ + } \ + CNT_REG--; \ + cycles -= is486 ? 3 : 4; \ + reads++; \ + writes++; \ + total_cycles += is486 ? 3 : 4; \ + if (cycles < cycles_end) \ + break; \ + } \ + PREFETCH_RUN(total_cycles, 1, -1, reads, 0, writes, 0, 0); \ + if (CNT_REG > 0) { \ + CPU_BLOCK_END(); \ + cpu_state.pc = cpu_state.oldpc; \ + return 1; \ + } \ + return cpu_state.abrt; \ + } \ + \ + static int opREP_STOSB_##size(uint32_t fetchdat) \ + { \ + int writes = 0, total_cycles = 0; \ + int cycles_end = cycles - ((is386 && cpu_use_dynarec) ? 1000 : 100); \ + if (trap) \ + cycles_end = cycles + 1; /*Force the instruction to end after only one iteration when trap flag set*/ \ + if (CNT_REG > 0) \ + SEG_CHECK_WRITE(&cpu_state.seg_es); \ + while (CNT_REG > 0) { \ + CHECK_WRITE_REP(&cpu_state.seg_es, DEST_REG, DEST_REG); \ + writememb(es, DEST_REG, AL); \ + if (cpu_state.abrt) \ + return 1; \ + if (cpu_state.flags & D_FLAG) \ + DEST_REG--; \ + else \ + DEST_REG++; \ + CNT_REG--; \ + cycles -= is486 ? 4 : 5; \ + writes++; \ + total_cycles += is486 ? 4 : 5; \ + if (cycles < cycles_end) \ + break; \ + } \ + PREFETCH_RUN(total_cycles, 1, -1, 0, 0, writes, 0, 0); \ + if (CNT_REG > 0) { \ + CPU_BLOCK_END(); \ + cpu_state.pc = cpu_state.oldpc; \ + return 1; \ + } \ + return cpu_state.abrt; \ + } \ + static int opREP_STOSW_##size(uint32_t fetchdat) \ + { \ + int writes = 0, total_cycles = 0; \ + int cycles_end = cycles - ((is386 && cpu_use_dynarec) ? 1000 : 100); \ + if (trap) \ + cycles_end = cycles + 1; /*Force the instruction to end after only one iteration when trap flag set*/ \ + if (CNT_REG > 0) \ + SEG_CHECK_WRITE(&cpu_state.seg_es); \ + while (CNT_REG > 0) { \ + CHECK_WRITE_REP(&cpu_state.seg_es, DEST_REG, DEST_REG + 1UL); \ + writememw(es, DEST_REG, AX); \ + if (cpu_state.abrt) \ + return 1; \ + if (cpu_state.flags & D_FLAG) \ + DEST_REG -= 2; \ + else \ + DEST_REG += 2; \ + CNT_REG--; \ + cycles -= is486 ? 4 : 5; \ + writes++; \ + total_cycles += is486 ? 4 : 5; \ + if (cycles < cycles_end) \ + break; \ + } \ + PREFETCH_RUN(total_cycles, 1, -1, 0, 0, writes, 0, 0); \ + if (CNT_REG > 0) { \ + CPU_BLOCK_END(); \ + cpu_state.pc = cpu_state.oldpc; \ + return 1; \ + } \ + return cpu_state.abrt; \ + } \ + static int opREP_STOSL_##size(uint32_t fetchdat) \ + { \ + int writes = 0, total_cycles = 0; \ + int cycles_end = cycles - ((is386 && cpu_use_dynarec) ? 1000 : 100); \ + if (trap) \ + cycles_end = cycles + 1; /*Force the instruction to end after only one iteration when trap flag set*/ \ + if (CNT_REG > 0) \ + SEG_CHECK_WRITE(&cpu_state.seg_es); \ + while (CNT_REG > 0) { \ + CHECK_WRITE_REP(&cpu_state.seg_es, DEST_REG, DEST_REG + 3UL); \ + writememl(es, DEST_REG, EAX); \ + if (cpu_state.abrt) \ + return 1; \ + if (cpu_state.flags & D_FLAG) \ + DEST_REG -= 4; \ + else \ + DEST_REG += 4; \ + CNT_REG--; \ + cycles -= is486 ? 4 : 5; \ + writes++; \ + total_cycles += is486 ? 4 : 5; \ + if (cycles < cycles_end) \ + break; \ + } \ + PREFETCH_RUN(total_cycles, 1, -1, 0, 0, 0, writes, 0); \ + if (CNT_REG > 0) { \ + CPU_BLOCK_END(); \ + cpu_state.pc = cpu_state.oldpc; \ + return 1; \ + } \ + return cpu_state.abrt; \ + } \ + \ + static int opREP_LODSB_##size(uint32_t fetchdat) \ + { \ + int reads = 0, total_cycles = 0; \ + int cycles_end = cycles - ((is386 && cpu_use_dynarec) ? 1000 : 100); \ + if (trap) \ + cycles_end = cycles + 1; /*Force the instruction to end after only one iteration when trap flag set*/ \ + if (CNT_REG > 0) \ + SEG_CHECK_READ(cpu_state.ea_seg); \ + while (CNT_REG > 0) { \ + CHECK_READ_REP(cpu_state.ea_seg, SRC_REG, SRC_REG); \ + AL = readmemb(cpu_state.ea_seg->base, SRC_REG); \ + if (cpu_state.abrt) \ + return 1; \ + if (cpu_state.flags & D_FLAG) \ + SRC_REG--; \ + else \ + SRC_REG++; \ + CNT_REG--; \ + cycles -= is486 ? 4 : 5; \ + reads++; \ + total_cycles += is486 ? 4 : 5; \ + if (cycles < cycles_end) \ + break; \ + } \ + PREFETCH_RUN(total_cycles, 1, -1, reads, 0, 0, 0, 0); \ + if (CNT_REG > 0) { \ + CPU_BLOCK_END(); \ + cpu_state.pc = cpu_state.oldpc; \ + return 1; \ + } \ + return cpu_state.abrt; \ + } \ + static int opREP_LODSW_##size(uint32_t fetchdat) \ + { \ + int reads = 0, total_cycles = 0; \ + int cycles_end = cycles - ((is386 && cpu_use_dynarec) ? 1000 : 100); \ + if (trap) \ + cycles_end = cycles + 1; /*Force the instruction to end after only one iteration when trap flag set*/ \ + if (CNT_REG > 0) \ + SEG_CHECK_READ(cpu_state.ea_seg); \ + while (CNT_REG > 0) { \ + CHECK_READ_REP(cpu_state.ea_seg, SRC_REG, SRC_REG + 1UL); \ + AX = readmemw(cpu_state.ea_seg->base, SRC_REG); \ + if (cpu_state.abrt) \ + return 1; \ + if (cpu_state.flags & D_FLAG) \ + SRC_REG -= 2; \ + else \ + SRC_REG += 2; \ + CNT_REG--; \ + cycles -= is486 ? 4 : 5; \ + reads++; \ + total_cycles += is486 ? 4 : 5; \ + if (cycles < cycles_end) \ + break; \ + } \ + PREFETCH_RUN(total_cycles, 1, -1, reads, 0, 0, 0, 0); \ + if (CNT_REG > 0) { \ + CPU_BLOCK_END(); \ + cpu_state.pc = cpu_state.oldpc; \ + return 1; \ + } \ + return cpu_state.abrt; \ + } \ + static int opREP_LODSL_##size(uint32_t fetchdat) \ + { \ + int reads = 0, total_cycles = 0; \ + int cycles_end = cycles - ((is386 && cpu_use_dynarec) ? 1000 : 100); \ + if (trap) \ + cycles_end = cycles + 1; /*Force the instruction to end after only one iteration when trap flag set*/ \ + if (CNT_REG > 0) \ + SEG_CHECK_READ(cpu_state.ea_seg); \ + while (CNT_REG > 0) { \ + CHECK_READ_REP(cpu_state.ea_seg, SRC_REG, SRC_REG + 3UL); \ + EAX = readmeml(cpu_state.ea_seg->base, SRC_REG); \ + if (cpu_state.abrt) \ + return 1; \ + if (cpu_state.flags & D_FLAG) \ + SRC_REG -= 4; \ + else \ + SRC_REG += 4; \ + CNT_REG--; \ + cycles -= is486 ? 4 : 5; \ + reads++; \ + total_cycles += is486 ? 4 : 5; \ + if (cycles < cycles_end) \ + break; \ + } \ + PREFETCH_RUN(total_cycles, 1, -1, 0, reads, 0, 0, 0); \ + if (CNT_REG > 0) { \ + CPU_BLOCK_END(); \ + cpu_state.pc = cpu_state.oldpc; \ + return 1; \ + } \ + return cpu_state.abrt; \ + } #define CHEK_READ(a, b, c) - -#define REP_OPS_CMPS_SCAS(size, CNT_REG, SRC_REG, DEST_REG, FV) \ -static int opREP_CMPSB_ ## size(uint32_t fetchdat) \ -{ \ - int reads = 0, total_cycles = 0, tempz; \ - \ - addr64 = addr64_2 = 0x00000000; \ - \ - tempz = FV; \ - if ((CNT_REG > 0) && (FV == tempz)) \ - { \ - uint8_t temp, temp2; \ - SEG_CHECK_READ(cpu_state.ea_seg); \ - SEG_CHECK_READ(&cpu_state.seg_es); \ - CHECK_READ(cpu_state.ea_seg, SRC_REG, SRC_REG); \ - high_page = uncached = 0; \ - do_mmut_rb(cpu_state.ea_seg->base, SRC_REG, &addr64); \ - if (cpu_state.abrt) return 1; \ - CHECK_READ(&cpu_state.seg_es, DEST_REG, DEST_REG); \ - do_mmut_rb2(es, DEST_REG, &addr64_2); \ - if (cpu_state.abrt) return 1; \ - temp = readmemb_n(cpu_state.ea_seg->base, SRC_REG, addr64); if (cpu_state.abrt) return 1; \ - if (uncached) \ - readlookup2[(uint32_t)(es+DEST_REG)>>12] = old_rl2; \ - temp2 = readmemb_n(es, DEST_REG, addr64_2); if (cpu_state.abrt) return 1; \ - if (uncached) \ - readlookup2[(uint32_t)(es+DEST_REG)>>12] = (uintptr_t) LOOKUP_INV; \ - \ - if (cpu_state.flags & D_FLAG) { DEST_REG--; SRC_REG--; } \ - else { DEST_REG++; SRC_REG++; } \ - CNT_REG--; \ - cycles -= is486 ? 7 : 9; \ - reads += 2; total_cycles += is486 ? 7 : 9; \ - setsub8(temp, temp2); \ - tempz = (ZF_SET()) ? 1 : 0; \ - } \ - PREFETCH_RUN(total_cycles, 1, -1, reads, 0, 0, 0, 0); \ - if ((CNT_REG > 0) && (FV == tempz)) \ - { \ - CPU_BLOCK_END(); \ - cpu_state.pc = cpu_state.oldpc; \ - return 1; \ - } \ - return cpu_state.abrt; \ -} \ -static int opREP_CMPSW_ ## size(uint32_t fetchdat) \ -{ \ - int reads = 0, total_cycles = 0, tempz; \ - \ - addr64a[0] = addr64a[1] = 0x00000000; \ - addr64a_2[0] = addr64a_2[1] = 0x00000000; \ - \ - tempz = FV; \ - if ((CNT_REG > 0) && (FV == tempz)) \ - { \ - uint16_t temp, temp2; \ - SEG_CHECK_READ(cpu_state.ea_seg); \ - SEG_CHECK_READ(&cpu_state.seg_es); \ - CHECK_READ(cpu_state.ea_seg, SRC_REG, SRC_REG + 1UL); \ - high_page = uncached = 0; \ - do_mmut_rw(cpu_state.ea_seg->base, SRC_REG, addr64a); \ - if (cpu_state.abrt) return 1; \ - CHECK_READ(&cpu_state.seg_es, DEST_REG, DEST_REG + 1UL); \ - do_mmut_rw2(es, DEST_REG, addr64a_2); \ - if (cpu_state.abrt) return 1; \ - temp = readmemw_n(cpu_state.ea_seg->base, SRC_REG, addr64a); if (cpu_state.abrt) return 1; \ - if (uncached) \ - readlookup2[(uint32_t)(es+DEST_REG)>>12] = old_rl2; \ - temp2 = readmemw_n(es, DEST_REG, addr64a_2); if (cpu_state.abrt) return 1; \ - if (uncached) \ - readlookup2[(uint32_t)(es+DEST_REG)>>12] = (uintptr_t) LOOKUP_INV; \ - \ - if (cpu_state.flags & D_FLAG) { DEST_REG -= 2; SRC_REG -= 2; } \ - else { DEST_REG += 2; SRC_REG += 2; } \ - CNT_REG--; \ - cycles -= is486 ? 7 : 9; \ - reads += 2; total_cycles += is486 ? 7 : 9; \ - setsub16(temp, temp2); \ - tempz = (ZF_SET()) ? 1 : 0; \ - } \ - PREFETCH_RUN(total_cycles, 1, -1, reads, 0, 0, 0, 0); \ - if ((CNT_REG > 0) && (FV == tempz)) \ - { \ - CPU_BLOCK_END(); \ - cpu_state.pc = cpu_state.oldpc; \ - return 1; \ - } \ - return cpu_state.abrt; \ -} \ -static int opREP_CMPSL_ ## size(uint32_t fetchdat) \ -{ \ - int reads = 0, total_cycles = 0, tempz; \ - \ - addr64a[0] = addr64a[1] = addr64a[2] = addr64a[3] = 0x00000000; \ - addr64a_2[0] = addr64a_2[1] = addr64a_2[2] = addr64a_2[3] = 0x00000000; \ - \ - tempz = FV; \ - if ((CNT_REG > 0) && (FV == tempz)) \ - { \ - uint32_t temp, temp2; \ - SEG_CHECK_READ(cpu_state.ea_seg); \ - SEG_CHECK_READ(&cpu_state.seg_es); \ - CHECK_READ(cpu_state.ea_seg, SRC_REG, SRC_REG + 3UL); \ - high_page = uncached = 0; \ - do_mmut_rl(cpu_state.ea_seg->base, SRC_REG, addr64a); \ - if (cpu_state.abrt) return 1; \ - CHECK_READ(&cpu_state.seg_es, DEST_REG, DEST_REG + 3UL); \ - do_mmut_rl2(es, DEST_REG, addr64a_2); \ - if (cpu_state.abrt) return 1; \ - temp = readmeml_n(cpu_state.ea_seg->base, SRC_REG, addr64a); if (cpu_state.abrt) return 1; \ - if (uncached) \ - readlookup2[(uint32_t)(es+DEST_REG)>>12] = old_rl2; \ - temp2 = readmeml_n(es, DEST_REG, addr64a_2); if (cpu_state.abrt) return 1; \ - if (uncached) \ - readlookup2[(uint32_t)(es+DEST_REG)>>12] = (uintptr_t) LOOKUP_INV; \ - \ - if (cpu_state.flags & D_FLAG) { DEST_REG -= 4; SRC_REG -= 4; } \ - else { DEST_REG += 4; SRC_REG += 4; } \ - CNT_REG--; \ - cycles -= is486 ? 7 : 9; \ - reads += 2; total_cycles += is486 ? 7 : 9; \ - setsub32(temp, temp2); \ - tempz = (ZF_SET()) ? 1 : 0; \ - } \ - PREFETCH_RUN(total_cycles, 1, -1, 0, reads, 0, 0, 0); \ - if ((CNT_REG > 0) && (FV == tempz)) \ - { \ - CPU_BLOCK_END(); \ - cpu_state.pc = cpu_state.oldpc; \ - return 1; \ - } \ - return cpu_state.abrt; \ -} \ - \ -static int opREP_SCASB_ ## size(uint32_t fetchdat) \ -{ \ - int reads = 0, total_cycles = 0, tempz; \ - int cycles_end = cycles - ((is386 && cpu_use_dynarec) ? 1000 : 100); \ - if (trap) \ - cycles_end = cycles+1; /*Force the instruction to end after only one iteration when trap flag set*/ \ - tempz = FV; \ - if ((CNT_REG > 0) && (FV == tempz)) \ - SEG_CHECK_READ(&cpu_state.seg_es); \ - while ((CNT_REG > 0) && (FV == tempz)) \ - { \ - CHECK_READ_REP(&cpu_state.seg_es, DEST_REG, DEST_REG); \ - uint8_t temp = readmemb(es, DEST_REG); if (cpu_state.abrt) break;\ - setsub8(AL, temp); \ - tempz = (ZF_SET()) ? 1 : 0; \ - if (cpu_state.flags & D_FLAG) DEST_REG--; \ - else DEST_REG++; \ - CNT_REG--; \ - cycles -= is486 ? 5 : 8; \ - reads++; total_cycles += is486 ? 5 : 8; \ - if (cycles < cycles_end) \ - break; \ - } \ - PREFETCH_RUN(total_cycles, 1, -1, reads, 0, 0, 0, 0); \ - if ((CNT_REG > 0) && (FV == tempz)) \ - { \ - CPU_BLOCK_END(); \ - cpu_state.pc = cpu_state.oldpc; \ - return 1; \ - } \ - return cpu_state.abrt; \ -} \ -static int opREP_SCASW_ ## size(uint32_t fetchdat) \ -{ \ - int reads = 0, total_cycles = 0, tempz; \ - int cycles_end = cycles - ((is386 && cpu_use_dynarec) ? 1000 : 100); \ - if (trap) \ - cycles_end = cycles+1; /*Force the instruction to end after only one iteration when trap flag set*/ \ - tempz = FV; \ - if ((CNT_REG > 0) && (FV == tempz)) \ - SEG_CHECK_READ(&cpu_state.seg_es); \ - while ((CNT_REG > 0) && (FV == tempz)) \ - { \ - CHECK_READ_REP(&cpu_state.seg_es, DEST_REG, DEST_REG + 1UL); \ - uint16_t temp = readmemw(es, DEST_REG); if (cpu_state.abrt) break;\ - setsub16(AX, temp); \ - tempz = (ZF_SET()) ? 1 : 0; \ - if (cpu_state.flags & D_FLAG) DEST_REG -= 2; \ - else DEST_REG += 2; \ - CNT_REG--; \ - cycles -= is486 ? 5 : 8; \ - reads++; total_cycles += is486 ? 5 : 8; \ - if (cycles < cycles_end) \ - break; \ - } \ - PREFETCH_RUN(total_cycles, 1, -1, reads, 0, 0, 0, 0); \ - if ((CNT_REG > 0) && (FV == tempz)) \ - { \ - CPU_BLOCK_END(); \ - cpu_state.pc = cpu_state.oldpc; \ - return 1; \ - } \ - return cpu_state.abrt; \ -} \ -static int opREP_SCASL_ ## size(uint32_t fetchdat) \ -{ \ - int reads = 0, total_cycles = 0, tempz; \ - int cycles_end = cycles - ((is386 && cpu_use_dynarec) ? 1000 : 100); \ - if (trap) \ - cycles_end = cycles+1; /*Force the instruction to end after only one iteration when trap flag set*/ \ - tempz = FV; \ - if ((CNT_REG > 0) && (FV == tempz)) \ - SEG_CHECK_READ(&cpu_state.seg_es); \ - while ((CNT_REG > 0) && (FV == tempz)) \ - { \ - CHECK_READ_REP(&cpu_state.seg_es, DEST_REG, DEST_REG + 3UL); \ - uint32_t temp = readmeml(es, DEST_REG); if (cpu_state.abrt) break;\ - setsub32(EAX, temp); \ - tempz = (ZF_SET()) ? 1 : 0; \ - if (cpu_state.flags & D_FLAG) DEST_REG -= 4; \ - else DEST_REG += 4; \ - CNT_REG--; \ - cycles -= is486 ? 5 : 8; \ - reads++; total_cycles += is486 ? 5 : 8; \ - if (cycles < cycles_end) \ - break; \ - } \ - PREFETCH_RUN(total_cycles, 1, -1, 0, reads, 0, 0, 0); \ - if ((CNT_REG > 0) && (FV == tempz)) \ - { \ - CPU_BLOCK_END(); \ - cpu_state.pc = cpu_state.oldpc; \ - return 1; \ - } \ - return cpu_state.abrt; \ -} +#define REP_OPS_CMPS_SCAS(size, CNT_REG, SRC_REG, DEST_REG, FV) \ + static int opREP_CMPSB_##size(uint32_t fetchdat) \ + { \ + int reads = 0, total_cycles = 0, tempz; \ + \ + addr64 = addr64_2 = 0x00000000; \ + \ + tempz = FV; \ + if ((CNT_REG > 0) && (FV == tempz)) { \ + uint8_t temp, temp2; \ + SEG_CHECK_READ(cpu_state.ea_seg); \ + SEG_CHECK_READ(&cpu_state.seg_es); \ + CHECK_READ(cpu_state.ea_seg, SRC_REG, SRC_REG); \ + CHECK_READ(&cpu_state.seg_es, DEST_REG, DEST_REG); \ + high_page = uncached = 0; \ + do_mmut_rb(cpu_state.ea_seg->base, SRC_REG, &addr64); \ + if (cpu_state.abrt) \ + return 1; \ + do_mmut_rb2(es, DEST_REG, &addr64_2); \ + if (cpu_state.abrt) \ + return 1; \ + temp = readmemb_n(cpu_state.ea_seg->base, SRC_REG, addr64); \ + if (cpu_state.abrt) \ + return 1; \ + if (uncached) \ + readlookup2[(uint32_t) (es + DEST_REG) >> 12] = old_rl2; \ + temp2 = readmemb_n(es, DEST_REG, addr64_2); \ + if (cpu_state.abrt) \ + return 1; \ + if (uncached) \ + readlookup2[(uint32_t) (es + DEST_REG) >> 12] = (uintptr_t) LOOKUP_INV; \ + \ + if (cpu_state.flags & D_FLAG) { \ + DEST_REG--; \ + SRC_REG--; \ + } else { \ + DEST_REG++; \ + SRC_REG++; \ + } \ + CNT_REG--; \ + cycles -= is486 ? 7 : 9; \ + reads += 2; \ + total_cycles += is486 ? 7 : 9; \ + setsub8(temp, temp2); \ + tempz = (ZF_SET()) ? 1 : 0; \ + } \ + PREFETCH_RUN(total_cycles, 1, -1, reads, 0, 0, 0, 0); \ + if ((CNT_REG > 0) && (FV == tempz)) { \ + CPU_BLOCK_END(); \ + cpu_state.pc = cpu_state.oldpc; \ + return 1; \ + } \ + return cpu_state.abrt; \ + } \ + static int opREP_CMPSW_##size(uint32_t fetchdat) \ + { \ + int reads = 0, total_cycles = 0, tempz; \ + \ + addr64a[0] = addr64a[1] = 0x00000000; \ + addr64a_2[0] = addr64a_2[1] = 0x00000000; \ + \ + tempz = FV; \ + if ((CNT_REG > 0) && (FV == tempz)) { \ + uint16_t temp, temp2; \ + SEG_CHECK_READ(cpu_state.ea_seg); \ + SEG_CHECK_READ(&cpu_state.seg_es); \ + CHECK_READ(cpu_state.ea_seg, SRC_REG, SRC_REG + 1UL); \ + CHECK_READ(&cpu_state.seg_es, DEST_REG, DEST_REG + 1UL); \ + high_page = uncached = 0; \ + do_mmut_rw(cpu_state.ea_seg->base, SRC_REG, addr64a); \ + if (cpu_state.abrt) \ + return 1; \ + do_mmut_rw2(es, DEST_REG, addr64a_2); \ + if (cpu_state.abrt) \ + return 1; \ + temp = readmemw_n(cpu_state.ea_seg->base, SRC_REG, addr64a); \ + if (cpu_state.abrt) \ + return 1; \ + if (uncached) \ + readlookup2[(uint32_t) (es + DEST_REG) >> 12] = old_rl2; \ + temp2 = readmemw_n(es, DEST_REG, addr64a_2); \ + if (cpu_state.abrt) \ + return 1; \ + if (uncached) \ + readlookup2[(uint32_t) (es + DEST_REG) >> 12] = (uintptr_t) LOOKUP_INV; \ + \ + if (cpu_state.flags & D_FLAG) { \ + DEST_REG -= 2; \ + SRC_REG -= 2; \ + } else { \ + DEST_REG += 2; \ + SRC_REG += 2; \ + } \ + CNT_REG--; \ + cycles -= is486 ? 7 : 9; \ + reads += 2; \ + total_cycles += is486 ? 7 : 9; \ + setsub16(temp, temp2); \ + tempz = (ZF_SET()) ? 1 : 0; \ + } \ + PREFETCH_RUN(total_cycles, 1, -1, reads, 0, 0, 0, 0); \ + if ((CNT_REG > 0) && (FV == tempz)) { \ + CPU_BLOCK_END(); \ + cpu_state.pc = cpu_state.oldpc; \ + return 1; \ + } \ + return cpu_state.abrt; \ + } \ + static int opREP_CMPSL_##size(uint32_t fetchdat) \ + { \ + int reads = 0, total_cycles = 0, tempz; \ + \ + addr64a[0] = addr64a[1] = addr64a[2] = addr64a[3] = 0x00000000; \ + addr64a_2[0] = addr64a_2[1] = addr64a_2[2] = addr64a_2[3] = 0x00000000; \ + \ + tempz = FV; \ + if ((CNT_REG > 0) && (FV == tempz)) { \ + uint32_t temp, temp2; \ + SEG_CHECK_READ(cpu_state.ea_seg); \ + SEG_CHECK_READ(&cpu_state.seg_es); \ + CHECK_READ(cpu_state.ea_seg, SRC_REG, SRC_REG + 3UL); \ + CHECK_READ(&cpu_state.seg_es, DEST_REG, DEST_REG + 3UL); \ + high_page = uncached = 0; \ + do_mmut_rl(cpu_state.ea_seg->base, SRC_REG, addr64a); \ + if (cpu_state.abrt) \ + return 1; \ + do_mmut_rl2(es, DEST_REG, addr64a_2); \ + if (cpu_state.abrt) \ + return 1; \ + temp = readmeml_n(cpu_state.ea_seg->base, SRC_REG, addr64a); \ + if (cpu_state.abrt) \ + return 1; \ + if (uncached) \ + readlookup2[(uint32_t) (es + DEST_REG) >> 12] = old_rl2; \ + temp2 = readmeml_n(es, DEST_REG, addr64a_2); \ + if (cpu_state.abrt) \ + return 1; \ + if (uncached) \ + readlookup2[(uint32_t) (es + DEST_REG) >> 12] = (uintptr_t) LOOKUP_INV; \ + \ + if (cpu_state.flags & D_FLAG) { \ + DEST_REG -= 4; \ + SRC_REG -= 4; \ + } else { \ + DEST_REG += 4; \ + SRC_REG += 4; \ + } \ + CNT_REG--; \ + cycles -= is486 ? 7 : 9; \ + reads += 2; \ + total_cycles += is486 ? 7 : 9; \ + setsub32(temp, temp2); \ + tempz = (ZF_SET()) ? 1 : 0; \ + } \ + PREFETCH_RUN(total_cycles, 1, -1, 0, reads, 0, 0, 0); \ + if ((CNT_REG > 0) && (FV == tempz)) { \ + CPU_BLOCK_END(); \ + cpu_state.pc = cpu_state.oldpc; \ + return 1; \ + } \ + return cpu_state.abrt; \ + } \ + \ + static int opREP_SCASB_##size(uint32_t fetchdat) \ + { \ + int reads = 0, total_cycles = 0, tempz; \ + int cycles_end = cycles - ((is386 && cpu_use_dynarec) ? 1000 : 100); \ + if (trap) \ + cycles_end = cycles + 1; /*Force the instruction to end after only one iteration when trap flag set*/ \ + tempz = FV; \ + if ((CNT_REG > 0) && (FV == tempz)) \ + SEG_CHECK_READ(&cpu_state.seg_es); \ + while ((CNT_REG > 0) && (FV == tempz)) { \ + CHECK_READ_REP(&cpu_state.seg_es, DEST_REG, DEST_REG); \ + uint8_t temp = readmemb(es, DEST_REG); \ + if (cpu_state.abrt) \ + break; \ + setsub8(AL, temp); \ + tempz = (ZF_SET()) ? 1 : 0; \ + if (cpu_state.flags & D_FLAG) \ + DEST_REG--; \ + else \ + DEST_REG++; \ + CNT_REG--; \ + cycles -= is486 ? 5 : 8; \ + reads++; \ + total_cycles += is486 ? 5 : 8; \ + if (cycles < cycles_end) \ + break; \ + } \ + PREFETCH_RUN(total_cycles, 1, -1, reads, 0, 0, 0, 0); \ + if ((CNT_REG > 0) && (FV == tempz)) { \ + CPU_BLOCK_END(); \ + cpu_state.pc = cpu_state.oldpc; \ + return 1; \ + } \ + return cpu_state.abrt; \ + } \ + static int opREP_SCASW_##size(uint32_t fetchdat) \ + { \ + int reads = 0, total_cycles = 0, tempz; \ + int cycles_end = cycles - ((is386 && cpu_use_dynarec) ? 1000 : 100); \ + if (trap) \ + cycles_end = cycles + 1; /*Force the instruction to end after only one iteration when trap flag set*/ \ + tempz = FV; \ + if ((CNT_REG > 0) && (FV == tempz)) \ + SEG_CHECK_READ(&cpu_state.seg_es); \ + while ((CNT_REG > 0) && (FV == tempz)) { \ + CHECK_READ_REP(&cpu_state.seg_es, DEST_REG, DEST_REG + 1UL); \ + uint16_t temp = readmemw(es, DEST_REG); \ + if (cpu_state.abrt) \ + break; \ + setsub16(AX, temp); \ + tempz = (ZF_SET()) ? 1 : 0; \ + if (cpu_state.flags & D_FLAG) \ + DEST_REG -= 2; \ + else \ + DEST_REG += 2; \ + CNT_REG--; \ + cycles -= is486 ? 5 : 8; \ + reads++; \ + total_cycles += is486 ? 5 : 8; \ + if (cycles < cycles_end) \ + break; \ + } \ + PREFETCH_RUN(total_cycles, 1, -1, reads, 0, 0, 0, 0); \ + if ((CNT_REG > 0) && (FV == tempz)) { \ + CPU_BLOCK_END(); \ + cpu_state.pc = cpu_state.oldpc; \ + return 1; \ + } \ + return cpu_state.abrt; \ + } \ + static int opREP_SCASL_##size(uint32_t fetchdat) \ + { \ + int reads = 0, total_cycles = 0, tempz; \ + int cycles_end = cycles - ((is386 && cpu_use_dynarec) ? 1000 : 100); \ + if (trap) \ + cycles_end = cycles + 1; /*Force the instruction to end after only one iteration when trap flag set*/ \ + tempz = FV; \ + if ((CNT_REG > 0) && (FV == tempz)) \ + SEG_CHECK_READ(&cpu_state.seg_es); \ + while ((CNT_REG > 0) && (FV == tempz)) { \ + CHECK_READ_REP(&cpu_state.seg_es, DEST_REG, DEST_REG + 3UL); \ + uint32_t temp = readmeml(es, DEST_REG); \ + if (cpu_state.abrt) \ + break; \ + setsub32(EAX, temp); \ + tempz = (ZF_SET()) ? 1 : 0; \ + if (cpu_state.flags & D_FLAG) \ + DEST_REG -= 4; \ + else \ + DEST_REG += 4; \ + CNT_REG--; \ + cycles -= is486 ? 5 : 8; \ + reads++; \ + total_cycles += is486 ? 5 : 8; \ + if (cycles < cycles_end) \ + break; \ + } \ + PREFETCH_RUN(total_cycles, 1, -1, 0, reads, 0, 0, 0); \ + if ((CNT_REG > 0) && (FV == tempz)) { \ + CPU_BLOCK_END(); \ + cpu_state.pc = cpu_state.oldpc; \ + return 1; \ + } \ + return cpu_state.abrt; \ + } REP_OPS(a16, CX, SI, DI) REP_OPS(a32, ECX, ESI, EDI) REP_OPS_CMPS_SCAS(a16_NE, CX, SI, DI, 0) -REP_OPS_CMPS_SCAS(a16_E, CX, SI, DI, 1) +REP_OPS_CMPS_SCAS(a16_E, CX, SI, DI, 1) REP_OPS_CMPS_SCAS(a32_NE, ECX, ESI, EDI, 0) -REP_OPS_CMPS_SCAS(a32_E, ECX, ESI, EDI, 1) +REP_OPS_CMPS_SCAS(a32_E, ECX, ESI, EDI, 1) -static int opREPNE(uint32_t fetchdat) +static int +opREPNE(uint32_t fetchdat) { - fetchdat = fastreadl(cs + cpu_state.pc); - if (cpu_state.abrt) return 1; - cpu_state.pc++; + fetchdat = fastreadl(cs + cpu_state.pc); + if (cpu_state.abrt) + return 1; + cpu_state.pc++; - CLOCK_CYCLES(2); - PREFETCH_PREFIX(); - if (x86_opcodes_REPNE[(fetchdat & 0xff) | cpu_state.op32]) - return x86_opcodes_REPNE[(fetchdat & 0xff) | cpu_state.op32](fetchdat >> 8); - return x86_opcodes[(fetchdat & 0xff) | cpu_state.op32](fetchdat >> 8); + CLOCK_CYCLES(2); + PREFETCH_PREFIX(); + if (x86_opcodes_REPNE[(fetchdat & 0xff) | cpu_state.op32]) + return x86_opcodes_REPNE[(fetchdat & 0xff) | cpu_state.op32](fetchdat >> 8); + return x86_opcodes[(fetchdat & 0xff) | cpu_state.op32](fetchdat >> 8); } -static int opREPE(uint32_t fetchdat) -{ - fetchdat = fastreadl(cs + cpu_state.pc); - if (cpu_state.abrt) return 1; - cpu_state.pc++; +static int +opREPE(uint32_t fetchdat) +{ + fetchdat = fastreadl(cs + cpu_state.pc); + if (cpu_state.abrt) + return 1; + cpu_state.pc++; - CLOCK_CYCLES(2); - PREFETCH_PREFIX(); - if (x86_opcodes_REPE[(fetchdat & 0xff) | cpu_state.op32]) - return x86_opcodes_REPE[(fetchdat & 0xff) | cpu_state.op32](fetchdat >> 8); - return x86_opcodes[(fetchdat & 0xff) | cpu_state.op32](fetchdat >> 8); + CLOCK_CYCLES(2); + PREFETCH_PREFIX(); + if (x86_opcodes_REPE[(fetchdat & 0xff) | cpu_state.op32]) + return x86_opcodes_REPE[(fetchdat & 0xff) | cpu_state.op32](fetchdat >> 8); + return x86_opcodes[(fetchdat & 0xff) | cpu_state.op32](fetchdat >> 8); } diff --git a/src/cpu/x86_ops_rep_2386.h b/src/cpu/x86_ops_rep_2386.h new file mode 100644 index 000000000..b6f64e90d --- /dev/null +++ b/src/cpu/x86_ops_rep_2386.h @@ -0,0 +1,863 @@ +#define REP_OPS(size, CNT_REG, SRC_REG, DEST_REG) \ + static int opREP_INSB_##size(uint32_t fetchdat) \ + { \ + int reads = 0, writes = 0, total_cycles = 0; \ + \ + addr64 = 0x00000000; \ + \ + if (CNT_REG > 0) { \ + uint8_t temp; \ + \ + SEG_CHECK_WRITE(&cpu_state.seg_es); \ + check_io_perm(DX, 1); \ + CHECK_WRITE(&cpu_state.seg_es, DEST_REG, DEST_REG); \ + high_page = 0; \ + do_mmut_wb(es, DEST_REG, &addr64); \ + if (cpu_state.abrt) \ + return 1; \ + temp = inb(DX); \ + writememb_n(es, DEST_REG, addr64, temp); \ + if (cpu_state.abrt) \ + return 1; \ + \ + if (cpu_state.flags & D_FLAG) \ + DEST_REG--; \ + else \ + DEST_REG++; \ + CNT_REG--; \ + cycles -= 15; \ + reads++; \ + writes++; \ + total_cycles += 15; \ + } \ + PREFETCH_RUN(total_cycles, 1, -1, reads, 0, writes, 0, 0); \ + if (CNT_REG > 0) { \ + CPU_BLOCK_END(); \ + cpu_state.pc = cpu_state.oldpc; \ + return 1; \ + } \ + return cpu_state.abrt; \ + } \ + static int opREP_INSW_##size(uint32_t fetchdat) \ + { \ + int reads = 0, writes = 0, total_cycles = 0; \ + \ + addr64a[0] = addr64a[1] = 0x00000000; \ + \ + if (CNT_REG > 0) { \ + uint16_t temp; \ + \ + SEG_CHECK_WRITE(&cpu_state.seg_es); \ + check_io_perm(DX, 2); \ + CHECK_WRITE(&cpu_state.seg_es, DEST_REG, DEST_REG + 1UL); \ + high_page = 0; \ + do_mmut_ww(es, DEST_REG, addr64a); \ + if (cpu_state.abrt) \ + return 1; \ + temp = inw(DX); \ + writememw_n(es, DEST_REG, addr64a, temp); \ + if (cpu_state.abrt) \ + return 1; \ + \ + if (cpu_state.flags & D_FLAG) \ + DEST_REG -= 2; \ + else \ + DEST_REG += 2; \ + CNT_REG--; \ + cycles -= 15; \ + reads++; \ + writes++; \ + total_cycles += 15; \ + } \ + PREFETCH_RUN(total_cycles, 1, -1, reads, 0, writes, 0, 0); \ + if (CNT_REG > 0) { \ + CPU_BLOCK_END(); \ + cpu_state.pc = cpu_state.oldpc; \ + return 1; \ + } \ + return cpu_state.abrt; \ + } \ + static int opREP_INSL_##size(uint32_t fetchdat) \ + { \ + int reads = 0, writes = 0, total_cycles = 0; \ + \ + addr64a[0] = addr64a[1] = addr64a[2] = addr64a[3] = 0x00000000; \ + \ + if (CNT_REG > 0) { \ + uint32_t temp; \ + \ + SEG_CHECK_WRITE(&cpu_state.seg_es); \ + check_io_perm(DX, 4); \ + CHECK_WRITE(&cpu_state.seg_es, DEST_REG, DEST_REG + 3UL); \ + high_page = 0; \ + do_mmut_wl(es, DEST_REG, addr64a); \ + if (cpu_state.abrt) \ + return 1; \ + temp = inl(DX); \ + writememl_n(es, DEST_REG, addr64a, temp); \ + if (cpu_state.abrt) \ + return 1; \ + \ + if (cpu_state.flags & D_FLAG) \ + DEST_REG -= 4; \ + else \ + DEST_REG += 4; \ + CNT_REG--; \ + cycles -= 15; \ + reads++; \ + writes++; \ + total_cycles += 15; \ + } \ + PREFETCH_RUN(total_cycles, 1, -1, 0, reads, 0, writes, 0); \ + if (CNT_REG > 0) { \ + CPU_BLOCK_END(); \ + cpu_state.pc = cpu_state.oldpc; \ + return 1; \ + } \ + return cpu_state.abrt; \ + } \ + \ + static int opREP_OUTSB_##size(uint32_t fetchdat) \ + { \ + int reads = 0, writes = 0, total_cycles = 0; \ + \ + if (CNT_REG > 0) { \ + uint8_t temp; \ + SEG_CHECK_READ(cpu_state.ea_seg); \ + CHECK_READ(cpu_state.ea_seg, SRC_REG, SRC_REG); \ + temp = readmemb(cpu_state.ea_seg->base, SRC_REG); \ + if (cpu_state.abrt) \ + return 1; \ + check_io_perm(DX, 1); \ + outb(DX, temp); \ + if (cpu_state.flags & D_FLAG) \ + SRC_REG--; \ + else \ + SRC_REG++; \ + CNT_REG--; \ + cycles -= 14; \ + reads++; \ + writes++; \ + total_cycles += 14; \ + } \ + PREFETCH_RUN(total_cycles, 1, -1, reads, 0, writes, 0, 0); \ + if (CNT_REG > 0) { \ + CPU_BLOCK_END(); \ + cpu_state.pc = cpu_state.oldpc; \ + return 1; \ + } \ + return cpu_state.abrt; \ + } \ + static int opREP_OUTSW_##size(uint32_t fetchdat) \ + { \ + int reads = 0, writes = 0, total_cycles = 0; \ + \ + if (CNT_REG > 0) { \ + uint16_t temp; \ + SEG_CHECK_READ(cpu_state.ea_seg); \ + CHECK_READ(cpu_state.ea_seg, SRC_REG, SRC_REG + 1UL); \ + temp = readmemw(cpu_state.ea_seg->base, SRC_REG); \ + if (cpu_state.abrt) \ + return 1; \ + check_io_perm(DX, 2); \ + outw(DX, temp); \ + if (cpu_state.flags & D_FLAG) \ + SRC_REG -= 2; \ + else \ + SRC_REG += 2; \ + CNT_REG--; \ + cycles -= 14; \ + reads++; \ + writes++; \ + total_cycles += 14; \ + } \ + PREFETCH_RUN(total_cycles, 1, -1, reads, 0, writes, 0, 0); \ + if (CNT_REG > 0) { \ + CPU_BLOCK_END(); \ + cpu_state.pc = cpu_state.oldpc; \ + return 1; \ + } \ + return cpu_state.abrt; \ + } \ + static int opREP_OUTSL_##size(uint32_t fetchdat) \ + { \ + int reads = 0, writes = 0, total_cycles = 0; \ + \ + if (CNT_REG > 0) { \ + uint32_t temp; \ + SEG_CHECK_READ(cpu_state.ea_seg); \ + CHECK_READ(cpu_state.ea_seg, SRC_REG, SRC_REG + 3UL); \ + temp = readmeml(cpu_state.ea_seg->base, SRC_REG); \ + if (cpu_state.abrt) \ + return 1; \ + check_io_perm(DX, 4); \ + outl(DX, temp); \ + if (cpu_state.flags & D_FLAG) \ + SRC_REG -= 4; \ + else \ + SRC_REG += 4; \ + CNT_REG--; \ + cycles -= 14; \ + reads++; \ + writes++; \ + total_cycles += 14; \ + } \ + PREFETCH_RUN(total_cycles, 1, -1, 0, reads, 0, writes, 0); \ + if (CNT_REG > 0) { \ + CPU_BLOCK_END(); \ + cpu_state.pc = cpu_state.oldpc; \ + return 1; \ + } \ + return cpu_state.abrt; \ + } \ + \ + static int opREP_MOVSB_##size(uint32_t fetchdat) \ + { \ + int reads = 0, writes = 0, total_cycles = 0; \ + int cycles_end = cycles - ((is386 && cpu_use_dynarec) ? 1000 : 100); \ + addr64 = addr64_2 = 0x00000000; \ + if (trap) \ + cycles_end = cycles + 1; /*Force the instruction to end after only one iteration when trap flag set*/ \ + if (CNT_REG > 0) { \ + SEG_CHECK_READ(cpu_state.ea_seg); \ + SEG_CHECK_WRITE(&cpu_state.seg_es); \ + } \ + while (CNT_REG > 0) { \ + uint8_t temp; \ + \ + CHECK_READ_REP(cpu_state.ea_seg, SRC_REG, SRC_REG); \ + CHECK_WRITE_REP(&cpu_state.seg_es, DEST_REG, DEST_REG); \ + high_page = 0; \ + do_mmut_rb(cpu_state.ea_seg->base, SRC_REG, &addr64); \ + if (cpu_state.abrt) \ + break; \ + do_mmut_wb(es, DEST_REG, &addr64_2); \ + if (cpu_state.abrt) \ + break; \ + temp = readmemb_n(cpu_state.ea_seg->base, SRC_REG, addr64); \ + if (cpu_state.abrt) \ + return 1; \ + writememb_n(es, DEST_REG, addr64_2, temp); \ + if (cpu_state.abrt) \ + return 1; \ + \ + if (cpu_state.flags & D_FLAG) { \ + DEST_REG--; \ + SRC_REG--; \ + } else { \ + DEST_REG++; \ + SRC_REG++; \ + } \ + CNT_REG--; \ + cycles -= is486 ? 3 : 4; \ + reads++; \ + writes++; \ + total_cycles += is486 ? 3 : 4; \ + if (cycles < cycles_end) \ + break; \ + } \ + PREFETCH_RUN(total_cycles, 1, -1, reads, 0, writes, 0, 0); \ + if (CNT_REG > 0) { \ + CPU_BLOCK_END(); \ + cpu_state.pc = cpu_state.oldpc; \ + return 1; \ + } \ + return cpu_state.abrt; \ + } \ + static int opREP_MOVSW_##size(uint32_t fetchdat) \ + { \ + int reads = 0, writes = 0, total_cycles = 0; \ + int cycles_end = cycles - ((is386 && cpu_use_dynarec) ? 1000 : 100); \ + addr64a[0] = addr64a[1] = 0x00000000; \ + addr64a_2[0] = addr64a_2[1] = 0x00000000; \ + if (trap) \ + cycles_end = cycles + 1; /*Force the instruction to end after only one iteration when trap flag set*/ \ + if (CNT_REG > 0) { \ + SEG_CHECK_READ(cpu_state.ea_seg); \ + SEG_CHECK_WRITE(&cpu_state.seg_es); \ + } \ + while (CNT_REG > 0) { \ + uint16_t temp; \ + \ + CHECK_READ_REP(cpu_state.ea_seg, SRC_REG, SRC_REG + 1UL); \ + CHECK_WRITE_REP(&cpu_state.seg_es, DEST_REG, DEST_REG + 1UL); \ + high_page = 0; \ + do_mmut_rw(cpu_state.ea_seg->base, SRC_REG, addr64a); \ + if (cpu_state.abrt) \ + break; \ + do_mmut_ww(es, DEST_REG, addr64a_2); \ + if (cpu_state.abrt) \ + break; \ + temp = readmemw_n(cpu_state.ea_seg->base, SRC_REG, addr64a); \ + if (cpu_state.abrt) \ + return 1; \ + writememw_n(es, DEST_REG, addr64a_2, temp); \ + if (cpu_state.abrt) \ + return 1; \ + \ + if (cpu_state.flags & D_FLAG) { \ + DEST_REG -= 2; \ + SRC_REG -= 2; \ + } else { \ + DEST_REG += 2; \ + SRC_REG += 2; \ + } \ + CNT_REG--; \ + cycles -= is486 ? 3 : 4; \ + reads++; \ + writes++; \ + total_cycles += is486 ? 3 : 4; \ + if (cycles < cycles_end) \ + break; \ + } \ + PREFETCH_RUN(total_cycles, 1, -1, reads, 0, writes, 0, 0); \ + if (CNT_REG > 0) { \ + CPU_BLOCK_END(); \ + cpu_state.pc = cpu_state.oldpc; \ + return 1; \ + } \ + return cpu_state.abrt; \ + } \ + static int opREP_MOVSL_##size(uint32_t fetchdat) \ + { \ + int reads = 0, writes = 0, total_cycles = 0; \ + int cycles_end = cycles - ((is386 && cpu_use_dynarec) ? 1000 : 100); \ + addr64a[0] = addr64a[1] = addr64a[2] = addr64a[3] = 0x00000000; \ + addr64a_2[0] = addr64a_2[1] = addr64a_2[2] = addr64a_2[3] = 0x00000000; \ + if (trap) \ + cycles_end = cycles + 1; /*Force the instruction to end after only one iteration when trap flag set*/ \ + if (CNT_REG > 0) { \ + SEG_CHECK_READ(cpu_state.ea_seg); \ + SEG_CHECK_WRITE(&cpu_state.seg_es); \ + } \ + while (CNT_REG > 0) { \ + uint32_t temp; \ + \ + CHECK_READ_REP(cpu_state.ea_seg, SRC_REG, SRC_REG + 3UL); \ + CHECK_WRITE_REP(&cpu_state.seg_es, DEST_REG, DEST_REG + 3UL); \ + high_page = 0; \ + do_mmut_rl(cpu_state.ea_seg->base, SRC_REG, addr64a); \ + if (cpu_state.abrt) \ + break; \ + do_mmut_wl(es, DEST_REG, addr64a_2); \ + if (cpu_state.abrt) \ + break; \ + temp = readmeml_n(cpu_state.ea_seg->base, SRC_REG, addr64a); \ + if (cpu_state.abrt) \ + return 1; \ + writememl_n(es, DEST_REG, addr64a_2, temp); \ + if (cpu_state.abrt) \ + return 1; \ + \ + if (cpu_state.flags & D_FLAG) { \ + DEST_REG -= 4; \ + SRC_REG -= 4; \ + } else { \ + DEST_REG += 4; \ + SRC_REG += 4; \ + } \ + CNT_REG--; \ + cycles -= is486 ? 3 : 4; \ + reads++; \ + writes++; \ + total_cycles += is486 ? 3 : 4; \ + if (cycles < cycles_end) \ + break; \ + } \ + PREFETCH_RUN(total_cycles, 1, -1, reads, 0, writes, 0, 0); \ + if (CNT_REG > 0) { \ + CPU_BLOCK_END(); \ + cpu_state.pc = cpu_state.oldpc; \ + return 1; \ + } \ + return cpu_state.abrt; \ + } \ + \ + static int opREP_STOSB_##size(uint32_t fetchdat) \ + { \ + int writes = 0, total_cycles = 0; \ + int cycles_end = cycles - ((is386 && cpu_use_dynarec) ? 1000 : 100); \ + if (trap) \ + cycles_end = cycles + 1; /*Force the instruction to end after only one iteration when trap flag set*/ \ + if (CNT_REG > 0) \ + SEG_CHECK_WRITE(&cpu_state.seg_es); \ + while (CNT_REG > 0) { \ + CHECK_WRITE_REP(&cpu_state.seg_es, DEST_REG, DEST_REG); \ + writememb(es, DEST_REG, AL); \ + if (cpu_state.abrt) \ + return 1; \ + if (cpu_state.flags & D_FLAG) \ + DEST_REG--; \ + else \ + DEST_REG++; \ + CNT_REG--; \ + cycles -= is486 ? 4 : 5; \ + writes++; \ + total_cycles += is486 ? 4 : 5; \ + if (cycles < cycles_end) \ + break; \ + } \ + PREFETCH_RUN(total_cycles, 1, -1, 0, 0, writes, 0, 0); \ + if (CNT_REG > 0) { \ + CPU_BLOCK_END(); \ + cpu_state.pc = cpu_state.oldpc; \ + return 1; \ + } \ + return cpu_state.abrt; \ + } \ + static int opREP_STOSW_##size(uint32_t fetchdat) \ + { \ + int writes = 0, total_cycles = 0; \ + int cycles_end = cycles - ((is386 && cpu_use_dynarec) ? 1000 : 100); \ + if (trap) \ + cycles_end = cycles + 1; /*Force the instruction to end after only one iteration when trap flag set*/ \ + if (CNT_REG > 0) \ + SEG_CHECK_WRITE(&cpu_state.seg_es); \ + while (CNT_REG > 0) { \ + CHECK_WRITE_REP(&cpu_state.seg_es, DEST_REG, DEST_REG + 1UL); \ + writememw(es, DEST_REG, AX); \ + if (cpu_state.abrt) \ + return 1; \ + if (cpu_state.flags & D_FLAG) \ + DEST_REG -= 2; \ + else \ + DEST_REG += 2; \ + CNT_REG--; \ + cycles -= is486 ? 4 : 5; \ + writes++; \ + total_cycles += is486 ? 4 : 5; \ + if (cycles < cycles_end) \ + break; \ + } \ + PREFETCH_RUN(total_cycles, 1, -1, 0, 0, writes, 0, 0); \ + if (CNT_REG > 0) { \ + CPU_BLOCK_END(); \ + cpu_state.pc = cpu_state.oldpc; \ + return 1; \ + } \ + return cpu_state.abrt; \ + } \ + static int opREP_STOSL_##size(uint32_t fetchdat) \ + { \ + int writes = 0, total_cycles = 0; \ + int cycles_end = cycles - ((is386 && cpu_use_dynarec) ? 1000 : 100); \ + if (trap) \ + cycles_end = cycles + 1; /*Force the instruction to end after only one iteration when trap flag set*/ \ + if (CNT_REG > 0) \ + SEG_CHECK_WRITE(&cpu_state.seg_es); \ + while (CNT_REG > 0) { \ + CHECK_WRITE_REP(&cpu_state.seg_es, DEST_REG, DEST_REG + 3UL); \ + writememl(es, DEST_REG, EAX); \ + if (cpu_state.abrt) \ + return 1; \ + if (cpu_state.flags & D_FLAG) \ + DEST_REG -= 4; \ + else \ + DEST_REG += 4; \ + CNT_REG--; \ + cycles -= is486 ? 4 : 5; \ + writes++; \ + total_cycles += is486 ? 4 : 5; \ + if (cycles < cycles_end) \ + break; \ + } \ + PREFETCH_RUN(total_cycles, 1, -1, 0, 0, 0, writes, 0); \ + if (CNT_REG > 0) { \ + CPU_BLOCK_END(); \ + cpu_state.pc = cpu_state.oldpc; \ + return 1; \ + } \ + return cpu_state.abrt; \ + } \ + \ + static int opREP_LODSB_##size(uint32_t fetchdat) \ + { \ + int reads = 0, total_cycles = 0; \ + int cycles_end = cycles - ((is386 && cpu_use_dynarec) ? 1000 : 100); \ + if (trap) \ + cycles_end = cycles + 1; /*Force the instruction to end after only one iteration when trap flag set*/ \ + if (CNT_REG > 0) \ + SEG_CHECK_READ(cpu_state.ea_seg); \ + while (CNT_REG > 0) { \ + CHECK_READ_REP(cpu_state.ea_seg, SRC_REG, SRC_REG); \ + AL = readmemb(cpu_state.ea_seg->base, SRC_REG); \ + if (cpu_state.abrt) \ + return 1; \ + if (cpu_state.flags & D_FLAG) \ + SRC_REG--; \ + else \ + SRC_REG++; \ + CNT_REG--; \ + cycles -= is486 ? 4 : 5; \ + reads++; \ + total_cycles += is486 ? 4 : 5; \ + if (cycles < cycles_end) \ + break; \ + } \ + PREFETCH_RUN(total_cycles, 1, -1, reads, 0, 0, 0, 0); \ + if (CNT_REG > 0) { \ + CPU_BLOCK_END(); \ + cpu_state.pc = cpu_state.oldpc; \ + return 1; \ + } \ + return cpu_state.abrt; \ + } \ + static int opREP_LODSW_##size(uint32_t fetchdat) \ + { \ + int reads = 0, total_cycles = 0; \ + int cycles_end = cycles - ((is386 && cpu_use_dynarec) ? 1000 : 100); \ + if (trap) \ + cycles_end = cycles + 1; /*Force the instruction to end after only one iteration when trap flag set*/ \ + if (CNT_REG > 0) \ + SEG_CHECK_READ(cpu_state.ea_seg); \ + while (CNT_REG > 0) { \ + CHECK_READ_REP(cpu_state.ea_seg, SRC_REG, SRC_REG + 1UL); \ + AX = readmemw(cpu_state.ea_seg->base, SRC_REG); \ + if (cpu_state.abrt) \ + return 1; \ + if (cpu_state.flags & D_FLAG) \ + SRC_REG -= 2; \ + else \ + SRC_REG += 2; \ + CNT_REG--; \ + cycles -= is486 ? 4 : 5; \ + reads++; \ + total_cycles += is486 ? 4 : 5; \ + if (cycles < cycles_end) \ + break; \ + } \ + PREFETCH_RUN(total_cycles, 1, -1, reads, 0, 0, 0, 0); \ + if (CNT_REG > 0) { \ + CPU_BLOCK_END(); \ + cpu_state.pc = cpu_state.oldpc; \ + return 1; \ + } \ + return cpu_state.abrt; \ + } \ + static int opREP_LODSL_##size(uint32_t fetchdat) \ + { \ + int reads = 0, total_cycles = 0; \ + int cycles_end = cycles - ((is386 && cpu_use_dynarec) ? 1000 : 100); \ + if (trap) \ + cycles_end = cycles + 1; /*Force the instruction to end after only one iteration when trap flag set*/ \ + if (CNT_REG > 0) \ + SEG_CHECK_READ(cpu_state.ea_seg); \ + while (CNT_REG > 0) { \ + CHECK_READ_REP(cpu_state.ea_seg, SRC_REG, SRC_REG + 3UL); \ + EAX = readmeml(cpu_state.ea_seg->base, SRC_REG); \ + if (cpu_state.abrt) \ + return 1; \ + if (cpu_state.flags & D_FLAG) \ + SRC_REG -= 4; \ + else \ + SRC_REG += 4; \ + CNT_REG--; \ + cycles -= is486 ? 4 : 5; \ + reads++; \ + total_cycles += is486 ? 4 : 5; \ + if (cycles < cycles_end) \ + break; \ + } \ + PREFETCH_RUN(total_cycles, 1, -1, 0, reads, 0, 0, 0); \ + if (CNT_REG > 0) { \ + CPU_BLOCK_END(); \ + cpu_state.pc = cpu_state.oldpc; \ + return 1; \ + } \ + return cpu_state.abrt; \ + } + +#define CHEK_READ(a, b, c) + +#define REP_OPS_CMPS_SCAS(size, CNT_REG, SRC_REG, DEST_REG, FV) \ + static int opREP_CMPSB_##size(uint32_t fetchdat) \ + { \ + int reads = 0, total_cycles = 0, tempz; \ + \ + addr64 = addr64_2 = 0x00000000; \ + \ + tempz = FV; \ + if ((CNT_REG > 0) && (FV == tempz)) { \ + uint8_t temp, temp2; \ + SEG_CHECK_READ(cpu_state.ea_seg); \ + SEG_CHECK_READ(&cpu_state.seg_es); \ + CHECK_READ(cpu_state.ea_seg, SRC_REG, SRC_REG); \ + CHECK_READ(&cpu_state.seg_es, DEST_REG, DEST_REG); \ + high_page = uncached = 0; \ + do_mmut_rb(cpu_state.ea_seg->base, SRC_REG, &addr64); \ + if (cpu_state.abrt) \ + return 1; \ + do_mmut_rb2(es, DEST_REG, &addr64_2); \ + if (cpu_state.abrt) \ + return 1; \ + temp = readmemb_n(cpu_state.ea_seg->base, SRC_REG, addr64); \ + if (cpu_state.abrt) \ + return 1; \ + temp2 = readmemb_n(es, DEST_REG, addr64_2); \ + if (cpu_state.abrt) \ + return 1; \ + \ + if (cpu_state.flags & D_FLAG) { \ + DEST_REG--; \ + SRC_REG--; \ + } else { \ + DEST_REG++; \ + SRC_REG++; \ + } \ + CNT_REG--; \ + cycles -= is486 ? 7 : 9; \ + reads += 2; \ + total_cycles += is486 ? 7 : 9; \ + setsub8(temp, temp2); \ + tempz = (ZF_SET()) ? 1 : 0; \ + } \ + PREFETCH_RUN(total_cycles, 1, -1, reads, 0, 0, 0, 0); \ + if ((CNT_REG > 0) && (FV == tempz)) { \ + CPU_BLOCK_END(); \ + cpu_state.pc = cpu_state.oldpc; \ + return 1; \ + } \ + return cpu_state.abrt; \ + } \ + static int opREP_CMPSW_##size(uint32_t fetchdat) \ + { \ + int reads = 0, total_cycles = 0, tempz; \ + \ + addr64a[0] = addr64a[1] = 0x00000000; \ + addr64a_2[0] = addr64a_2[1] = 0x00000000; \ + \ + tempz = FV; \ + if ((CNT_REG > 0) && (FV == tempz)) { \ + uint16_t temp, temp2; \ + SEG_CHECK_READ(cpu_state.ea_seg); \ + SEG_CHECK_READ(&cpu_state.seg_es); \ + CHECK_READ(cpu_state.ea_seg, SRC_REG, SRC_REG + 1UL); \ + CHECK_READ(&cpu_state.seg_es, DEST_REG, DEST_REG + 1UL); \ + high_page = uncached = 0; \ + do_mmut_rw(cpu_state.ea_seg->base, SRC_REG, addr64a); \ + if (cpu_state.abrt) \ + return 1; \ + do_mmut_rw2(es, DEST_REG, addr64a_2); \ + if (cpu_state.abrt) \ + return 1; \ + temp = readmemw_n(cpu_state.ea_seg->base, SRC_REG, addr64a); \ + if (cpu_state.abrt) \ + return 1; \ + temp2 = readmemw_n(es, DEST_REG, addr64a_2); \ + if (cpu_state.abrt) \ + return 1; \ + \ + if (cpu_state.flags & D_FLAG) { \ + DEST_REG -= 2; \ + SRC_REG -= 2; \ + } else { \ + DEST_REG += 2; \ + SRC_REG += 2; \ + } \ + CNT_REG--; \ + cycles -= is486 ? 7 : 9; \ + reads += 2; \ + total_cycles += is486 ? 7 : 9; \ + setsub16(temp, temp2); \ + tempz = (ZF_SET()) ? 1 : 0; \ + } \ + PREFETCH_RUN(total_cycles, 1, -1, reads, 0, 0, 0, 0); \ + if ((CNT_REG > 0) && (FV == tempz)) { \ + CPU_BLOCK_END(); \ + cpu_state.pc = cpu_state.oldpc; \ + return 1; \ + } \ + return cpu_state.abrt; \ + } \ + static int opREP_CMPSL_##size(uint32_t fetchdat) \ + { \ + int reads = 0, total_cycles = 0, tempz; \ + \ + addr64a[0] = addr64a[1] = addr64a[2] = addr64a[3] = 0x00000000; \ + addr64a_2[0] = addr64a_2[1] = addr64a_2[2] = addr64a_2[3] = 0x00000000; \ + \ + tempz = FV; \ + if ((CNT_REG > 0) && (FV == tempz)) { \ + uint32_t temp, temp2; \ + SEG_CHECK_READ(cpu_state.ea_seg); \ + SEG_CHECK_READ(&cpu_state.seg_es); \ + CHECK_READ(cpu_state.ea_seg, SRC_REG, SRC_REG + 3UL); \ + CHECK_READ(&cpu_state.seg_es, DEST_REG, DEST_REG + 3UL); \ + high_page = uncached = 0; \ + do_mmut_rl(cpu_state.ea_seg->base, SRC_REG, addr64a); \ + if (cpu_state.abrt) \ + return 1; \ + do_mmut_rl2(es, DEST_REG, addr64a_2); \ + if (cpu_state.abrt) \ + return 1; \ + temp = readmeml_n(cpu_state.ea_seg->base, SRC_REG, addr64a); \ + if (cpu_state.abrt) \ + return 1; \ + temp2 = readmeml_n(es, DEST_REG, addr64a_2); \ + if (cpu_state.abrt) \ + return 1; \ + \ + if (cpu_state.flags & D_FLAG) { \ + DEST_REG -= 4; \ + SRC_REG -= 4; \ + } else { \ + DEST_REG += 4; \ + SRC_REG += 4; \ + } \ + CNT_REG--; \ + cycles -= is486 ? 7 : 9; \ + reads += 2; \ + total_cycles += is486 ? 7 : 9; \ + setsub32(temp, temp2); \ + tempz = (ZF_SET()) ? 1 : 0; \ + } \ + PREFETCH_RUN(total_cycles, 1, -1, 0, reads, 0, 0, 0); \ + if ((CNT_REG > 0) && (FV == tempz)) { \ + CPU_BLOCK_END(); \ + cpu_state.pc = cpu_state.oldpc; \ + return 1; \ + } \ + return cpu_state.abrt; \ + } \ + \ + static int opREP_SCASB_##size(uint32_t fetchdat) \ + { \ + int reads = 0, total_cycles = 0, tempz; \ + int cycles_end = cycles - ((is386 && cpu_use_dynarec) ? 1000 : 100); \ + if (trap) \ + cycles_end = cycles + 1; /*Force the instruction to end after only one iteration when trap flag set*/ \ + tempz = FV; \ + if ((CNT_REG > 0) && (FV == tempz)) \ + SEG_CHECK_READ(&cpu_state.seg_es); \ + while ((CNT_REG > 0) && (FV == tempz)) { \ + CHECK_READ_REP(&cpu_state.seg_es, DEST_REG, DEST_REG); \ + uint8_t temp = readmemb(es, DEST_REG); \ + if (cpu_state.abrt) \ + break; \ + setsub8(AL, temp); \ + tempz = (ZF_SET()) ? 1 : 0; \ + if (cpu_state.flags & D_FLAG) \ + DEST_REG--; \ + else \ + DEST_REG++; \ + CNT_REG--; \ + cycles -= is486 ? 5 : 8; \ + reads++; \ + total_cycles += is486 ? 5 : 8; \ + if (cycles < cycles_end) \ + break; \ + } \ + PREFETCH_RUN(total_cycles, 1, -1, reads, 0, 0, 0, 0); \ + if ((CNT_REG > 0) && (FV == tempz)) { \ + CPU_BLOCK_END(); \ + cpu_state.pc = cpu_state.oldpc; \ + return 1; \ + } \ + return cpu_state.abrt; \ + } \ + static int opREP_SCASW_##size(uint32_t fetchdat) \ + { \ + int reads = 0, total_cycles = 0, tempz; \ + int cycles_end = cycles - ((is386 && cpu_use_dynarec) ? 1000 : 100); \ + if (trap) \ + cycles_end = cycles + 1; /*Force the instruction to end after only one iteration when trap flag set*/ \ + tempz = FV; \ + if ((CNT_REG > 0) && (FV == tempz)) \ + SEG_CHECK_READ(&cpu_state.seg_es); \ + while ((CNT_REG > 0) && (FV == tempz)) { \ + CHECK_READ_REP(&cpu_state.seg_es, DEST_REG, DEST_REG + 1UL); \ + uint16_t temp = readmemw(es, DEST_REG); \ + if (cpu_state.abrt) \ + break; \ + setsub16(AX, temp); \ + tempz = (ZF_SET()) ? 1 : 0; \ + if (cpu_state.flags & D_FLAG) \ + DEST_REG -= 2; \ + else \ + DEST_REG += 2; \ + CNT_REG--; \ + cycles -= is486 ? 5 : 8; \ + reads++; \ + total_cycles += is486 ? 5 : 8; \ + if (cycles < cycles_end) \ + break; \ + } \ + PREFETCH_RUN(total_cycles, 1, -1, reads, 0, 0, 0, 0); \ + if ((CNT_REG > 0) && (FV == tempz)) { \ + CPU_BLOCK_END(); \ + cpu_state.pc = cpu_state.oldpc; \ + return 1; \ + } \ + return cpu_state.abrt; \ + } \ + static int opREP_SCASL_##size(uint32_t fetchdat) \ + { \ + int reads = 0, total_cycles = 0, tempz; \ + int cycles_end = cycles - ((is386 && cpu_use_dynarec) ? 1000 : 100); \ + if (trap) \ + cycles_end = cycles + 1; /*Force the instruction to end after only one iteration when trap flag set*/ \ + tempz = FV; \ + if ((CNT_REG > 0) && (FV == tempz)) \ + SEG_CHECK_READ(&cpu_state.seg_es); \ + while ((CNT_REG > 0) && (FV == tempz)) { \ + CHECK_READ_REP(&cpu_state.seg_es, DEST_REG, DEST_REG + 3UL); \ + uint32_t temp = readmeml(es, DEST_REG); \ + if (cpu_state.abrt) \ + break; \ + setsub32(EAX, temp); \ + tempz = (ZF_SET()) ? 1 : 0; \ + if (cpu_state.flags & D_FLAG) \ + DEST_REG -= 4; \ + else \ + DEST_REG += 4; \ + CNT_REG--; \ + cycles -= is486 ? 5 : 8; \ + reads++; \ + total_cycles += is486 ? 5 : 8; \ + if (cycles < cycles_end) \ + break; \ + } \ + PREFETCH_RUN(total_cycles, 1, -1, 0, reads, 0, 0, 0); \ + if ((CNT_REG > 0) && (FV == tempz)) { \ + CPU_BLOCK_END(); \ + cpu_state.pc = cpu_state.oldpc; \ + return 1; \ + } \ + return cpu_state.abrt; \ + } + +REP_OPS(a16, CX, SI, DI) +REP_OPS(a32, ECX, ESI, EDI) +REP_OPS_CMPS_SCAS(a16_NE, CX, SI, DI, 0) +REP_OPS_CMPS_SCAS(a16_E, CX, SI, DI, 1) +REP_OPS_CMPS_SCAS(a32_NE, ECX, ESI, EDI, 0) +REP_OPS_CMPS_SCAS(a32_E, ECX, ESI, EDI, 1) + +static int +opREPNE(uint32_t fetchdat) +{ + fetchdat = fastreadl(cs + cpu_state.pc); + if (cpu_state.abrt) + return 1; + cpu_state.pc++; + + CLOCK_CYCLES(2); + PREFETCH_PREFIX(); + if (x86_2386_opcodes_REPNE[(fetchdat & 0xff) | cpu_state.op32]) + return x86_2386_opcodes_REPNE[(fetchdat & 0xff) | cpu_state.op32](fetchdat >> 8); + return x86_2386_opcodes[(fetchdat & 0xff) | cpu_state.op32](fetchdat >> 8); +} +static int +opREPE(uint32_t fetchdat) +{ + fetchdat = fastreadl(cs + cpu_state.pc); + if (cpu_state.abrt) + return 1; + cpu_state.pc++; + + CLOCK_CYCLES(2); + PREFETCH_PREFIX(); + if (x86_2386_opcodes_REPE[(fetchdat & 0xff) | cpu_state.op32]) + return x86_2386_opcodes_REPE[(fetchdat & 0xff) | cpu_state.op32](fetchdat >> 8); + return x86_2386_opcodes[(fetchdat & 0xff) | cpu_state.op32](fetchdat >> 8); +} diff --git a/src/cpu/x86_ops_rep_dyn.h b/src/cpu/x86_ops_rep_dyn.h new file mode 100644 index 000000000..cf32209cc --- /dev/null +++ b/src/cpu/x86_ops_rep_dyn.h @@ -0,0 +1,780 @@ +#define REP_OPS(size, CNT_REG, SRC_REG, DEST_REG) \ + static int opREP_INSB_##size(uint32_t fetchdat) \ + { \ + addr64 = 0x00000000; \ + \ + if (CNT_REG > 0) { \ + uint8_t temp; \ + \ + SEG_CHECK_WRITE(&cpu_state.seg_es); \ + check_io_perm(DX, 1); \ + CHECK_WRITE(&cpu_state.seg_es, DEST_REG, DEST_REG); \ + high_page = 0; \ + do_mmut_wb(es, DEST_REG, &addr64); \ + if (cpu_state.abrt) \ + return 1; \ + temp = inb(DX); \ + writememb_n(es, DEST_REG, addr64, temp); \ + if (cpu_state.abrt) \ + return 1; \ + \ + if (cpu_state.flags & D_FLAG) \ + DEST_REG--; \ + else \ + DEST_REG++; \ + CNT_REG--; \ + cycles -= 15; \ + } \ + if (CNT_REG > 0) { \ + CPU_BLOCK_END(); \ + cpu_state.pc = cpu_state.oldpc; \ + return 1; \ + } \ + return cpu_state.abrt; \ + } \ + static int opREP_INSW_##size(uint32_t fetchdat) \ + { \ + addr64a[0] = addr64a[1] = 0x00000000; \ + \ + if (CNT_REG > 0) { \ + uint16_t temp; \ + \ + SEG_CHECK_WRITE(&cpu_state.seg_es); \ + check_io_perm(DX, 2); \ + CHECK_WRITE(&cpu_state.seg_es, DEST_REG, DEST_REG + 1UL); \ + high_page = 0; \ + do_mmut_ww(es, DEST_REG, addr64a); \ + if (cpu_state.abrt) \ + return 1; \ + temp = inw(DX); \ + writememw_n(es, DEST_REG, addr64a, temp); \ + if (cpu_state.abrt) \ + return 1; \ + \ + if (cpu_state.flags & D_FLAG) \ + DEST_REG -= 2; \ + else \ + DEST_REG += 2; \ + CNT_REG--; \ + cycles -= 15; \ + } \ + if (CNT_REG > 0) { \ + CPU_BLOCK_END(); \ + cpu_state.pc = cpu_state.oldpc; \ + return 1; \ + } \ + return cpu_state.abrt; \ + } \ + static int opREP_INSL_##size(uint32_t fetchdat) \ + { \ + addr64a[0] = addr64a[1] = addr64a[2] = addr64a[3] = 0x00000000; \ + \ + if (CNT_REG > 0) { \ + uint32_t temp; \ + \ + SEG_CHECK_WRITE(&cpu_state.seg_es); \ + check_io_perm(DX, 4); \ + CHECK_WRITE(&cpu_state.seg_es, DEST_REG, DEST_REG + 3UL); \ + high_page = 0; \ + do_mmut_wl(es, DEST_REG, addr64a); \ + if (cpu_state.abrt) \ + return 1; \ + temp = inl(DX); \ + writememl_n(es, DEST_REG, addr64a, temp); \ + if (cpu_state.abrt) \ + return 1; \ + \ + if (cpu_state.flags & D_FLAG) \ + DEST_REG -= 4; \ + else \ + DEST_REG += 4; \ + CNT_REG--; \ + cycles -= 15; \ + } \ + if (CNT_REG > 0) { \ + CPU_BLOCK_END(); \ + cpu_state.pc = cpu_state.oldpc; \ + return 1; \ + } \ + return cpu_state.abrt; \ + } \ + \ + static int opREP_OUTSB_##size(uint32_t fetchdat) \ + { \ + if (CNT_REG > 0) { \ + uint8_t temp; \ + SEG_CHECK_READ(cpu_state.ea_seg); \ + CHECK_READ(cpu_state.ea_seg, SRC_REG, SRC_REG); \ + temp = readmemb(cpu_state.ea_seg->base, SRC_REG); \ + if (cpu_state.abrt) \ + return 1; \ + check_io_perm(DX, 1); \ + outb(DX, temp); \ + if (cpu_state.flags & D_FLAG) \ + SRC_REG--; \ + else \ + SRC_REG++; \ + CNT_REG--; \ + cycles -= 14; \ + } \ + if (CNT_REG > 0) { \ + CPU_BLOCK_END(); \ + cpu_state.pc = cpu_state.oldpc; \ + return 1; \ + } \ + return cpu_state.abrt; \ + } \ + static int opREP_OUTSW_##size(uint32_t fetchdat) \ + { \ + if (CNT_REG > 0) { \ + uint16_t temp; \ + SEG_CHECK_READ(cpu_state.ea_seg); \ + CHECK_READ(cpu_state.ea_seg, SRC_REG, SRC_REG + 1UL); \ + temp = readmemw(cpu_state.ea_seg->base, SRC_REG); \ + if (cpu_state.abrt) \ + return 1; \ + check_io_perm(DX, 2); \ + outw(DX, temp); \ + if (cpu_state.flags & D_FLAG) \ + SRC_REG -= 2; \ + else \ + SRC_REG += 2; \ + CNT_REG--; \ + cycles -= 14; \ + } \ + if (CNT_REG > 0) { \ + CPU_BLOCK_END(); \ + cpu_state.pc = cpu_state.oldpc; \ + return 1; \ + } \ + return cpu_state.abrt; \ + } \ + static int opREP_OUTSL_##size(uint32_t fetchdat) \ + { \ + if (CNT_REG > 0) { \ + uint32_t temp; \ + SEG_CHECK_READ(cpu_state.ea_seg); \ + CHECK_READ(cpu_state.ea_seg, SRC_REG, SRC_REG + 3UL); \ + temp = readmeml(cpu_state.ea_seg->base, SRC_REG); \ + if (cpu_state.abrt) \ + return 1; \ + check_io_perm(DX, 4); \ + outl(DX, temp); \ + if (cpu_state.flags & D_FLAG) \ + SRC_REG -= 4; \ + else \ + SRC_REG += 4; \ + CNT_REG--; \ + cycles -= 14; \ + } \ + if (CNT_REG > 0) { \ + CPU_BLOCK_END(); \ + cpu_state.pc = cpu_state.oldpc; \ + return 1; \ + } \ + return cpu_state.abrt; \ + } \ + \ + static int opREP_MOVSB_##size(uint32_t fetchdat) \ + { \ + int cycles_end = cycles - ((is386 && cpu_use_dynarec) ? 1000 : 100); \ + addr64 = addr64_2 = 0x00000000; \ + if (trap) \ + cycles_end = cycles + 1; /*Force the instruction to end after only one iteration when trap flag set*/ \ + if (CNT_REG > 0) { \ + SEG_CHECK_READ(cpu_state.ea_seg); \ + SEG_CHECK_WRITE(&cpu_state.seg_es); \ + } \ + while (CNT_REG > 0) { \ + uint8_t temp; \ + \ + CHECK_READ_REP(cpu_state.ea_seg, SRC_REG, SRC_REG); \ + CHECK_WRITE_REP(&cpu_state.seg_es, DEST_REG, DEST_REG); \ + high_page = 0; \ + do_mmut_rb(cpu_state.ea_seg->base, SRC_REG, &addr64); \ + if (cpu_state.abrt) \ + break; \ + do_mmut_wb(es, DEST_REG, &addr64_2); \ + if (cpu_state.abrt) \ + break; \ + temp = readmemb_n(cpu_state.ea_seg->base, SRC_REG, addr64); \ + if (cpu_state.abrt) \ + return 1; \ + writememb_n(es, DEST_REG, addr64_2, temp); \ + if (cpu_state.abrt) \ + return 1; \ + \ + if (cpu_state.flags & D_FLAG) { \ + DEST_REG--; \ + SRC_REG--; \ + } else { \ + DEST_REG++; \ + SRC_REG++; \ + } \ + CNT_REG--; \ + cycles -= is486 ? 3 : 4; \ + if (cycles < cycles_end) \ + break; \ + } \ + if (CNT_REG > 0) { \ + CPU_BLOCK_END(); \ + cpu_state.pc = cpu_state.oldpc; \ + return 1; \ + } \ + return cpu_state.abrt; \ + } \ + static int opREP_MOVSW_##size(uint32_t fetchdat) \ + { \ + int cycles_end = cycles - ((is386 && cpu_use_dynarec) ? 1000 : 100); \ + addr64a[0] = addr64a[1] = 0x00000000; \ + addr64a_2[0] = addr64a_2[1] = 0x00000000; \ + if (trap) \ + cycles_end = cycles + 1; /*Force the instruction to end after only one iteration when trap flag set*/ \ + if (CNT_REG > 0) { \ + SEG_CHECK_READ(cpu_state.ea_seg); \ + SEG_CHECK_WRITE(&cpu_state.seg_es); \ + } \ + while (CNT_REG > 0) { \ + uint16_t temp; \ + \ + CHECK_READ_REP(cpu_state.ea_seg, SRC_REG, SRC_REG + 1UL); \ + CHECK_WRITE_REP(&cpu_state.seg_es, DEST_REG, DEST_REG + 1UL); \ + high_page = 0; \ + do_mmut_rw(cpu_state.ea_seg->base, SRC_REG, addr64a); \ + if (cpu_state.abrt) \ + break; \ + do_mmut_ww(es, DEST_REG, addr64a_2); \ + if (cpu_state.abrt) \ + break; \ + temp = readmemw_n(cpu_state.ea_seg->base, SRC_REG, addr64a); \ + if (cpu_state.abrt) \ + return 1; \ + writememw_n(es, DEST_REG, addr64a_2, temp); \ + if (cpu_state.abrt) \ + return 1; \ + \ + if (cpu_state.flags & D_FLAG) { \ + DEST_REG -= 2; \ + SRC_REG -= 2; \ + } else { \ + DEST_REG += 2; \ + SRC_REG += 2; \ + } \ + CNT_REG--; \ + cycles -= is486 ? 3 : 4; \ + if (cycles < cycles_end) \ + break; \ + } \ + if (CNT_REG > 0) { \ + CPU_BLOCK_END(); \ + cpu_state.pc = cpu_state.oldpc; \ + return 1; \ + } \ + return cpu_state.abrt; \ + } \ + static int opREP_MOVSL_##size(uint32_t fetchdat) \ + { \ + int cycles_end = cycles - ((is386 && cpu_use_dynarec) ? 1000 : 100); \ + addr64a[0] = addr64a[1] = addr64a[2] = addr64a[3] = 0x00000000; \ + addr64a_2[0] = addr64a_2[1] = addr64a_2[2] = addr64a_2[3] = 0x00000000; \ + if (trap) \ + cycles_end = cycles + 1; /*Force the instruction to end after only one iteration when trap flag set*/ \ + if (CNT_REG > 0) { \ + SEG_CHECK_READ(cpu_state.ea_seg); \ + SEG_CHECK_WRITE(&cpu_state.seg_es); \ + } \ + while (CNT_REG > 0) { \ + uint32_t temp; \ + \ + CHECK_READ_REP(cpu_state.ea_seg, SRC_REG, SRC_REG + 3UL); \ + CHECK_WRITE_REP(&cpu_state.seg_es, DEST_REG, DEST_REG + 3UL); \ + high_page = 0; \ + do_mmut_rl(cpu_state.ea_seg->base, SRC_REG, addr64a); \ + if (cpu_state.abrt) \ + break; \ + do_mmut_wl(es, DEST_REG, addr64a_2); \ + if (cpu_state.abrt) \ + break; \ + temp = readmeml_n(cpu_state.ea_seg->base, SRC_REG, addr64a); \ + if (cpu_state.abrt) \ + return 1; \ + writememl_n(es, DEST_REG, addr64a_2, temp); \ + if (cpu_state.abrt) \ + return 1; \ + \ + if (cpu_state.flags & D_FLAG) { \ + DEST_REG -= 4; \ + SRC_REG -= 4; \ + } else { \ + DEST_REG += 4; \ + SRC_REG += 4; \ + } \ + CNT_REG--; \ + cycles -= is486 ? 3 : 4; \ + if (cycles < cycles_end) \ + break; \ + } \ + if (CNT_REG > 0) { \ + CPU_BLOCK_END(); \ + cpu_state.pc = cpu_state.oldpc; \ + return 1; \ + } \ + return cpu_state.abrt; \ + } \ + \ + static int opREP_STOSB_##size(uint32_t fetchdat) \ + { \ + int cycles_end = cycles - ((is386 && cpu_use_dynarec) ? 1000 : 100); \ + if (trap) \ + cycles_end = cycles + 1; /*Force the instruction to end after only one iteration when trap flag set*/ \ + if (CNT_REG > 0) \ + SEG_CHECK_WRITE(&cpu_state.seg_es); \ + while (CNT_REG > 0) { \ + CHECK_WRITE_REP(&cpu_state.seg_es, DEST_REG, DEST_REG); \ + writememb(es, DEST_REG, AL); \ + if (cpu_state.abrt) \ + return 1; \ + if (cpu_state.flags & D_FLAG) \ + DEST_REG--; \ + else \ + DEST_REG++; \ + CNT_REG--; \ + cycles -= is486 ? 4 : 5; \ + if (cycles < cycles_end) \ + break; \ + } \ + if (CNT_REG > 0) { \ + CPU_BLOCK_END(); \ + cpu_state.pc = cpu_state.oldpc; \ + return 1; \ + } \ + return cpu_state.abrt; \ + } \ + static int opREP_STOSW_##size(uint32_t fetchdat) \ + { \ + int cycles_end = cycles - ((is386 && cpu_use_dynarec) ? 1000 : 100); \ + if (trap) \ + cycles_end = cycles + 1; /*Force the instruction to end after only one iteration when trap flag set*/ \ + if (CNT_REG > 0) \ + SEG_CHECK_WRITE(&cpu_state.seg_es); \ + while (CNT_REG > 0) { \ + CHECK_WRITE_REP(&cpu_state.seg_es, DEST_REG, DEST_REG + 1UL); \ + writememw(es, DEST_REG, AX); \ + if (cpu_state.abrt) \ + return 1; \ + if (cpu_state.flags & D_FLAG) \ + DEST_REG -= 2; \ + else \ + DEST_REG += 2; \ + CNT_REG--; \ + cycles -= is486 ? 4 : 5; \ + if (cycles < cycles_end) \ + break; \ + } \ + if (CNT_REG > 0) { \ + CPU_BLOCK_END(); \ + cpu_state.pc = cpu_state.oldpc; \ + return 1; \ + } \ + return cpu_state.abrt; \ + } \ + static int opREP_STOSL_##size(uint32_t fetchdat) \ + { \ + int cycles_end = cycles - ((is386 && cpu_use_dynarec) ? 1000 : 100); \ + if (trap) \ + cycles_end = cycles + 1; /*Force the instruction to end after only one iteration when trap flag set*/ \ + if (CNT_REG > 0) \ + SEG_CHECK_WRITE(&cpu_state.seg_es); \ + while (CNT_REG > 0) { \ + CHECK_WRITE_REP(&cpu_state.seg_es, DEST_REG, DEST_REG + 3UL); \ + writememl(es, DEST_REG, EAX); \ + if (cpu_state.abrt) \ + return 1; \ + if (cpu_state.flags & D_FLAG) \ + DEST_REG -= 4; \ + else \ + DEST_REG += 4; \ + CNT_REG--; \ + cycles -= is486 ? 4 : 5; \ + if (cycles < cycles_end) \ + break; \ + } \ + if (CNT_REG > 0) { \ + CPU_BLOCK_END(); \ + cpu_state.pc = cpu_state.oldpc; \ + return 1; \ + } \ + return cpu_state.abrt; \ + } \ + \ + static int opREP_LODSB_##size(uint32_t fetchdat) \ + { \ + int cycles_end = cycles - ((is386 && cpu_use_dynarec) ? 1000 : 100); \ + if (trap) \ + cycles_end = cycles + 1; /*Force the instruction to end after only one iteration when trap flag set*/ \ + if (CNT_REG > 0) \ + SEG_CHECK_READ(cpu_state.ea_seg); \ + while (CNT_REG > 0) { \ + CHECK_READ_REP(cpu_state.ea_seg, SRC_REG, SRC_REG); \ + AL = readmemb(cpu_state.ea_seg->base, SRC_REG); \ + if (cpu_state.abrt) \ + return 1; \ + if (cpu_state.flags & D_FLAG) \ + SRC_REG--; \ + else \ + SRC_REG++; \ + CNT_REG--; \ + cycles -= is486 ? 4 : 5; \ + if (cycles < cycles_end) \ + break; \ + } \ + if (CNT_REG > 0) { \ + CPU_BLOCK_END(); \ + cpu_state.pc = cpu_state.oldpc; \ + return 1; \ + } \ + return cpu_state.abrt; \ + } \ + static int opREP_LODSW_##size(uint32_t fetchdat) \ + { \ + int cycles_end = cycles - ((is386 && cpu_use_dynarec) ? 1000 : 100); \ + if (trap) \ + cycles_end = cycles + 1; /*Force the instruction to end after only one iteration when trap flag set*/ \ + if (CNT_REG > 0) \ + SEG_CHECK_READ(cpu_state.ea_seg); \ + while (CNT_REG > 0) { \ + CHECK_READ_REP(cpu_state.ea_seg, SRC_REG, SRC_REG + 1UL); \ + AX = readmemw(cpu_state.ea_seg->base, SRC_REG); \ + if (cpu_state.abrt) \ + return 1; \ + if (cpu_state.flags & D_FLAG) \ + SRC_REG -= 2; \ + else \ + SRC_REG += 2; \ + CNT_REG--; \ + cycles -= is486 ? 4 : 5; \ + if (cycles < cycles_end) \ + break; \ + } \ + if (CNT_REG > 0) { \ + CPU_BLOCK_END(); \ + cpu_state.pc = cpu_state.oldpc; \ + return 1; \ + } \ + return cpu_state.abrt; \ + } \ + static int opREP_LODSL_##size(uint32_t fetchdat) \ + { \ + int cycles_end = cycles - ((is386 && cpu_use_dynarec) ? 1000 : 100); \ + if (trap) \ + cycles_end = cycles + 1; /*Force the instruction to end after only one iteration when trap flag set*/ \ + if (CNT_REG > 0) \ + SEG_CHECK_READ(cpu_state.ea_seg); \ + while (CNT_REG > 0) { \ + CHECK_READ_REP(cpu_state.ea_seg, SRC_REG, SRC_REG + 3UL); \ + EAX = readmeml(cpu_state.ea_seg->base, SRC_REG); \ + if (cpu_state.abrt) \ + return 1; \ + if (cpu_state.flags & D_FLAG) \ + SRC_REG -= 4; \ + else \ + SRC_REG += 4; \ + CNT_REG--; \ + cycles -= is486 ? 4 : 5; \ + if (cycles < cycles_end) \ + break; \ + } \ + if (CNT_REG > 0) { \ + CPU_BLOCK_END(); \ + cpu_state.pc = cpu_state.oldpc; \ + return 1; \ + } \ + return cpu_state.abrt; \ + } + +#define CHEK_READ(a, b, c) + +#define REP_OPS_CMPS_SCAS(size, CNT_REG, SRC_REG, DEST_REG, FV) \ + static int opREP_CMPSB_##size(uint32_t fetchdat) \ + { \ + int tempz; \ + \ + addr64 = addr64_2 = 0x00000000; \ + \ + tempz = FV; \ + if ((CNT_REG > 0) && (FV == tempz)) { \ + uint8_t temp, temp2; \ + SEG_CHECK_READ(cpu_state.ea_seg); \ + SEG_CHECK_READ(&cpu_state.seg_es); \ + CHECK_READ(cpu_state.ea_seg, SRC_REG, SRC_REG); \ + CHECK_READ(&cpu_state.seg_es, DEST_REG, DEST_REG); \ + high_page = uncached = 0; \ + do_mmut_rb(cpu_state.ea_seg->base, SRC_REG, &addr64); \ + if (cpu_state.abrt) \ + return 1; \ + do_mmut_rb2(es, DEST_REG, &addr64_2); \ + if (cpu_state.abrt) \ + return 1; \ + temp = readmemb_n(cpu_state.ea_seg->base, SRC_REG, addr64); \ + if (cpu_state.abrt) \ + return 1; \ + if (uncached) \ + readlookup2[(uint32_t) (es + DEST_REG) >> 12] = old_rl2; \ + temp2 = readmemb_n(es, DEST_REG, addr64_2); \ + if (cpu_state.abrt) \ + return 1; \ + if (uncached) \ + readlookup2[(uint32_t) (es + DEST_REG) >> 12] = (uintptr_t) LOOKUP_INV; \ + \ + if (cpu_state.flags & D_FLAG) { \ + DEST_REG--; \ + SRC_REG--; \ + } else { \ + DEST_REG++; \ + SRC_REG++; \ + } \ + CNT_REG--; \ + cycles -= is486 ? 7 : 9; \ + setsub8(temp, temp2); \ + tempz = (ZF_SET()) ? 1 : 0; \ + } \ + if ((CNT_REG > 0) && (FV == tempz)) { \ + CPU_BLOCK_END(); \ + cpu_state.pc = cpu_state.oldpc; \ + return 1; \ + } \ + return cpu_state.abrt; \ + } \ + static int opREP_CMPSW_##size(uint32_t fetchdat) \ + { \ + int tempz; \ + \ + addr64a[0] = addr64a[1] = 0x00000000; \ + addr64a_2[0] = addr64a_2[1] = 0x00000000; \ + \ + tempz = FV; \ + if ((CNT_REG > 0) && (FV == tempz)) { \ + uint16_t temp, temp2; \ + SEG_CHECK_READ(cpu_state.ea_seg); \ + SEG_CHECK_READ(&cpu_state.seg_es); \ + CHECK_READ(cpu_state.ea_seg, SRC_REG, SRC_REG + 1UL); \ + CHECK_READ(&cpu_state.seg_es, DEST_REG, DEST_REG + 1UL); \ + high_page = uncached = 0; \ + do_mmut_rw(cpu_state.ea_seg->base, SRC_REG, addr64a); \ + if (cpu_state.abrt) \ + return 1; \ + do_mmut_rw2(es, DEST_REG, addr64a_2); \ + if (cpu_state.abrt) \ + return 1; \ + temp = readmemw_n(cpu_state.ea_seg->base, SRC_REG, addr64a); \ + if (cpu_state.abrt) \ + return 1; \ + if (uncached) \ + readlookup2[(uint32_t) (es + DEST_REG) >> 12] = old_rl2; \ + temp2 = readmemw_n(es, DEST_REG, addr64a_2); \ + if (cpu_state.abrt) \ + return 1; \ + if (uncached) \ + readlookup2[(uint32_t) (es + DEST_REG) >> 12] = (uintptr_t) LOOKUP_INV; \ + \ + if (cpu_state.flags & D_FLAG) { \ + DEST_REG -= 2; \ + SRC_REG -= 2; \ + } else { \ + DEST_REG += 2; \ + SRC_REG += 2; \ + } \ + CNT_REG--; \ + cycles -= is486 ? 7 : 9; \ + setsub16(temp, temp2); \ + tempz = (ZF_SET()) ? 1 : 0; \ + } \ + if ((CNT_REG > 0) && (FV == tempz)) { \ + CPU_BLOCK_END(); \ + cpu_state.pc = cpu_state.oldpc; \ + return 1; \ + } \ + return cpu_state.abrt; \ + } \ + static int opREP_CMPSL_##size(uint32_t fetchdat) \ + { \ + int tempz; \ + \ + addr64a[0] = addr64a[1] = addr64a[2] = addr64a[3] = 0x00000000; \ + addr64a_2[0] = addr64a_2[1] = addr64a_2[2] = addr64a_2[3] = 0x00000000; \ + \ + tempz = FV; \ + if ((CNT_REG > 0) && (FV == tempz)) { \ + uint32_t temp, temp2; \ + SEG_CHECK_READ(cpu_state.ea_seg); \ + SEG_CHECK_READ(&cpu_state.seg_es); \ + CHECK_READ(cpu_state.ea_seg, SRC_REG, SRC_REG + 3UL); \ + CHECK_READ(&cpu_state.seg_es, DEST_REG, DEST_REG + 3UL); \ + high_page = uncached = 0; \ + do_mmut_rl(cpu_state.ea_seg->base, SRC_REG, addr64a); \ + if (cpu_state.abrt) \ + return 1; \ + do_mmut_rl2(es, DEST_REG, addr64a_2); \ + if (cpu_state.abrt) \ + return 1; \ + temp = readmeml_n(cpu_state.ea_seg->base, SRC_REG, addr64a); \ + if (cpu_state.abrt) \ + return 1; \ + if (uncached) \ + readlookup2[(uint32_t) (es + DEST_REG) >> 12] = old_rl2; \ + temp2 = readmeml_n(es, DEST_REG, addr64a_2); \ + if (cpu_state.abrt) \ + return 1; \ + if (uncached) \ + readlookup2[(uint32_t) (es + DEST_REG) >> 12] = (uintptr_t) LOOKUP_INV; \ + \ + if (cpu_state.flags & D_FLAG) { \ + DEST_REG -= 4; \ + SRC_REG -= 4; \ + } else { \ + DEST_REG += 4; \ + SRC_REG += 4; \ + } \ + CNT_REG--; \ + cycles -= is486 ? 7 : 9; \ + setsub32(temp, temp2); \ + tempz = (ZF_SET()) ? 1 : 0; \ + } \ + if ((CNT_REG > 0) && (FV == tempz)) { \ + CPU_BLOCK_END(); \ + cpu_state.pc = cpu_state.oldpc; \ + return 1; \ + } \ + return cpu_state.abrt; \ + } \ + \ + static int opREP_SCASB_##size(uint32_t fetchdat) \ + { \ + int tempz; \ + int cycles_end = cycles - 1000; \ + if (trap) \ + cycles_end = cycles + 1; /*Force the instruction to end after only one iteration when trap flag set*/ \ + tempz = FV; \ + if ((CNT_REG > 0) && (FV == tempz)) \ + SEG_CHECK_READ(&cpu_state.seg_es); \ + while ((CNT_REG > 0) && (FV == tempz)) { \ + CHECK_READ_REP(&cpu_state.seg_es, DEST_REG, DEST_REG); \ + uint8_t temp = readmemb(es, DEST_REG); \ + if (cpu_state.abrt) \ + break; \ + setsub8(AL, temp); \ + tempz = (ZF_SET()) ? 1 : 0; \ + if (cpu_state.flags & D_FLAG) \ + DEST_REG--; \ + else \ + DEST_REG++; \ + CNT_REG--; \ + cycles -= is486 ? 5 : 8; \ + if (cycles < cycles_end) \ + break; \ + } \ + if ((CNT_REG > 0) && (FV == tempz)) { \ + CPU_BLOCK_END(); \ + cpu_state.pc = cpu_state.oldpc; \ + return 1; \ + } \ + return cpu_state.abrt; \ + } \ + static int opREP_SCASW_##size(uint32_t fetchdat) \ + { \ + int tempz; \ + int cycles_end = cycles - 1000; \ + if (trap) \ + cycles_end = cycles + 1; /*Force the instruction to end after only one iteration when trap flag set*/ \ + tempz = FV; \ + if ((CNT_REG > 0) && (FV == tempz)) \ + SEG_CHECK_READ(&cpu_state.seg_es); \ + while ((CNT_REG > 0) && (FV == tempz)) { \ + CHECK_READ_REP(&cpu_state.seg_es, DEST_REG, DEST_REG + 1UL); \ + uint16_t temp = readmemw(es, DEST_REG); \ + if (cpu_state.abrt) \ + break; \ + setsub16(AX, temp); \ + tempz = (ZF_SET()) ? 1 : 0; \ + if (cpu_state.flags & D_FLAG) \ + DEST_REG -= 2; \ + else \ + DEST_REG += 2; \ + CNT_REG--; \ + cycles -= is486 ? 5 : 8; \ + if (cycles < cycles_end) \ + break; \ + } \ + if ((CNT_REG > 0) && (FV == tempz)) { \ + CPU_BLOCK_END(); \ + cpu_state.pc = cpu_state.oldpc; \ + return 1; \ + } \ + return cpu_state.abrt; \ + } \ + static int opREP_SCASL_##size(uint32_t fetchdat) \ + { \ + int tempz; \ + int cycles_end = cycles - 1000; \ + if (trap) \ + cycles_end = cycles + 1; /*Force the instruction to end after only one iteration when trap flag set*/ \ + tempz = FV; \ + if ((CNT_REG > 0) && (FV == tempz)) \ + SEG_CHECK_READ(&cpu_state.seg_es); \ + while ((CNT_REG > 0) && (FV == tempz)) { \ + CHECK_READ_REP(&cpu_state.seg_es, DEST_REG, DEST_REG + 3UL); \ + uint32_t temp = readmeml(es, DEST_REG); \ + if (cpu_state.abrt) \ + break; \ + setsub32(EAX, temp); \ + tempz = (ZF_SET()) ? 1 : 0; \ + if (cpu_state.flags & D_FLAG) \ + DEST_REG -= 4; \ + else \ + DEST_REG += 4; \ + CNT_REG--; \ + cycles -= is486 ? 5 : 8; \ + if (cycles < cycles_end) \ + break; \ + } \ + if ((CNT_REG > 0) && (FV == tempz)) { \ + CPU_BLOCK_END(); \ + cpu_state.pc = cpu_state.oldpc; \ + return 1; \ + } \ + return cpu_state.abrt; \ + } + +REP_OPS(a16, CX, SI, DI) +REP_OPS(a32, ECX, ESI, EDI) +REP_OPS_CMPS_SCAS(a16_NE, CX, SI, DI, 0) +REP_OPS_CMPS_SCAS(a16_E, CX, SI, DI, 1) +REP_OPS_CMPS_SCAS(a32_NE, ECX, ESI, EDI, 0) +REP_OPS_CMPS_SCAS(a32_E, ECX, ESI, EDI, 1) + +static int +opREPNE(uint32_t fetchdat) +{ + fetchdat = fastreadl(cs + cpu_state.pc); + if (cpu_state.abrt) + return 1; + cpu_state.pc++; + + CLOCK_CYCLES(2); + if (x86_opcodes_REPNE[(fetchdat & 0xff) | cpu_state.op32]) + return x86_opcodes_REPNE[(fetchdat & 0xff) | cpu_state.op32](fetchdat >> 8); + return x86_opcodes[(fetchdat & 0xff) | cpu_state.op32](fetchdat >> 8); +} +static int +opREPE(uint32_t fetchdat) +{ + fetchdat = fastreadl(cs + cpu_state.pc); + if (cpu_state.abrt) + return 1; + cpu_state.pc++; + + CLOCK_CYCLES(2); + if (x86_opcodes_REPE[(fetchdat & 0xff) | cpu_state.op32]) + return x86_opcodes_REPE[(fetchdat & 0xff) | cpu_state.op32](fetchdat >> 8); + return x86_opcodes[(fetchdat & 0xff) | cpu_state.op32](fetchdat >> 8); +} diff --git a/src/cpu/x86_ops_ret.h b/src/cpu/x86_ops_ret.h index 3d6386956..0d9a6370b 100644 --- a/src/cpu/x86_ops_ret.h +++ b/src/cpu/x86_ops_ret.h @@ -1,267 +1,293 @@ #ifdef USE_NEW_DYNAREC -#define CPU_SET_OXPC +# define CPU_SET_OXPC #else -#define CPU_SET_OXPC oxpc = cpu_state.pc; +# define CPU_SET_OXPC oxpc = cpu_state.pc; #endif -#define RETF_a16(stack_offset) \ - if ((msw&1) && !(cpu_state.eflags&VM_FLAG)) \ - { \ - pmoderetf(0, stack_offset); \ - return 1; \ - } \ - CPU_SET_OXPC \ - if (stack32) \ - { \ - cpu_state.pc = readmemw(ss, ESP); \ - loadcs(readmemw(ss, ESP + 2)); \ - } \ - else \ - { \ - cpu_state.pc = readmemw(ss, SP); \ - loadcs(readmemw(ss, SP + 2)); \ - } \ - if (cpu_state.abrt) return 1; \ - if (stack32) ESP += 4 + stack_offset; \ - else SP += 4 + stack_offset; \ - cycles -= timing_retf_rm; +#define RETF_a16(stack_offset) \ + if ((msw & 1) && !(cpu_state.eflags & VM_FLAG)) { \ + op_pmoderetf(0, stack_offset); \ + return 1; \ + } \ + CPU_SET_OXPC \ + if (stack32) { \ + cpu_state.pc = readmemw(ss, ESP); \ + op_loadcs(readmemw(ss, ESP + 2)); \ + } else { \ + cpu_state.pc = readmemw(ss, SP); \ + op_loadcs(readmemw(ss, SP + 2)); \ + } \ + if (cpu_state.abrt) \ + return 1; \ + if (stack32) \ + ESP += 4 + stack_offset; \ + else \ + SP += 4 + stack_offset; \ + cycles -= timing_retf_rm; -#define RETF_a32(stack_offset) \ - if ((msw&1) && !(cpu_state.eflags&VM_FLAG)) \ - { \ - pmoderetf(1, stack_offset); \ - return 1; \ - } \ - CPU_SET_OXPC \ - if (stack32) \ - { \ - cpu_state.pc = readmeml(ss, ESP); \ - loadcs(readmeml(ss, ESP + 4) & 0xffff); \ - } \ - else \ - { \ - cpu_state.pc = readmeml(ss, SP); \ - loadcs(readmeml(ss, SP + 4) & 0xffff); \ - } \ - if (cpu_state.abrt) return 1; \ - if (stack32) ESP += 8 + stack_offset; \ - else SP += 8 + stack_offset; \ - cycles -= timing_retf_rm; +#define RETF_a32(stack_offset) \ + if ((msw & 1) && !(cpu_state.eflags & VM_FLAG)) { \ + op_pmoderetf(1, stack_offset); \ + return 1; \ + } \ + CPU_SET_OXPC \ + if (stack32) { \ + cpu_state.pc = readmeml(ss, ESP); \ + op_loadcs(readmeml(ss, ESP + 4) & 0xffff); \ + } else { \ + cpu_state.pc = readmeml(ss, SP); \ + op_loadcs(readmeml(ss, SP + 4) & 0xffff); \ + } \ + if (cpu_state.abrt) \ + return 1; \ + if (stack32) \ + ESP += 8 + stack_offset; \ + else \ + SP += 8 + stack_offset; \ + cycles -= timing_retf_rm; -static int opRETF_a16(uint32_t fetchdat) +static int +opRETF_a16(uint32_t fetchdat) { - int cycles_old = cycles; UN_USED(cycles_old); - - CPU_BLOCK_END(); - RETF_a16(0); - - PREFETCH_RUN(cycles_old-cycles, 1, -1, 2,0,0,0, 0); - PREFETCH_FLUSH(); - return 0; + int cycles_old = cycles; + UN_USED(cycles_old); + + CPU_BLOCK_END(); + RETF_a16(0); + + PREFETCH_RUN(cycles_old - cycles, 1, -1, 2, 0, 0, 0, 0); + PREFETCH_FLUSH(); + return 0; } -static int opRETF_a32(uint32_t fetchdat) +static int +opRETF_a32(uint32_t fetchdat) { - int cycles_old = cycles; UN_USED(cycles_old); - - CPU_BLOCK_END(); - RETF_a32(0); + int cycles_old = cycles; + UN_USED(cycles_old); - PREFETCH_RUN(cycles_old-cycles, 1, -1, 0,2,0,0, 1); - PREFETCH_FLUSH(); - return 0; + CPU_BLOCK_END(); + RETF_a32(0); + + PREFETCH_RUN(cycles_old - cycles, 1, -1, 0, 2, 0, 0, 1); + PREFETCH_FLUSH(); + return 0; } -static int opRETF_a16_imm(uint32_t fetchdat) +static int +opRETF_a16_imm(uint32_t fetchdat) { - uint16_t offset = getwordf(); - int cycles_old = cycles; UN_USED(cycles_old); + uint16_t offset = getwordf(); + int cycles_old = cycles; + UN_USED(cycles_old); - CPU_BLOCK_END(); - RETF_a16(offset); + CPU_BLOCK_END(); + RETF_a16(offset); - PREFETCH_RUN(cycles_old-cycles, 3, -1, 2,0,0,0, 0); - PREFETCH_FLUSH(); - return 0; + PREFETCH_RUN(cycles_old - cycles, 3, -1, 2, 0, 0, 0, 0); + PREFETCH_FLUSH(); + return 0; } -static int opRETF_a32_imm(uint32_t fetchdat) +static int +opRETF_a32_imm(uint32_t fetchdat) { - uint16_t offset = getwordf(); - int cycles_old = cycles; UN_USED(cycles_old); + uint16_t offset = getwordf(); + int cycles_old = cycles; + UN_USED(cycles_old); - CPU_BLOCK_END(); - RETF_a32(offset); + CPU_BLOCK_END(); + RETF_a32(offset); - PREFETCH_RUN(cycles_old-cycles, 3, -1, 0,2,0,0, 1); - PREFETCH_FLUSH(); - return 0; + PREFETCH_RUN(cycles_old - cycles, 3, -1, 0, 2, 0, 0, 1); + PREFETCH_FLUSH(); + return 0; } -static int opIRET_286(uint32_t fetchdat) +static int +opIRET_186(uint32_t fetchdat) { - int cycles_old = cycles; UN_USED(cycles_old); - - if ((cr0 & 1) && (cpu_state.eflags & VM_FLAG) && (IOPL != 3)) - { - x86gpf(NULL,0); + int cycles_old = cycles; + UN_USED(cycles_old); + + if ((cr0 & 1) && (cpu_state.eflags & VM_FLAG) && (IOPL != 3)) { + x86gpf(NULL, 0); + return 1; + } + if (msw & 1) { + optype = IRET; + op_pmodeiret(0); + optype = 0; + } else { + uint16_t new_cs; + CPU_SET_OXPC + if (stack32) { + cpu_state.pc = readmemw(ss, ESP); + new_cs = readmemw(ss, ESP + 2); + cpu_state.flags = (cpu_state.flags & 0x7000) | (readmemw(ss, ESP + 4) & 0xffd5) | 2; + ESP += 6; + } else { + cpu_state.pc = readmemw(ss, SP); + new_cs = readmemw(ss, ((SP + 2) & 0xffff)); + cpu_state.flags = (cpu_state.flags & 0x7000) | (readmemw(ss, ((SP + 4) & 0xffff)) & 0x0fd5) | 2; + SP += 6; + } + op_loadcs(new_cs); + cycles -= timing_iret_rm; + } + flags_extract(); + nmi_enable = 1; + CPU_BLOCK_END(); + + PREFETCH_RUN(cycles_old - cycles, 1, -1, 2, 0, 0, 0, 0); + PREFETCH_FLUSH(); + return cpu_state.abrt; +} + +static int +opIRET_286(uint32_t fetchdat) +{ + int cycles_old = cycles; + UN_USED(cycles_old); + + if ((cr0 & 1) && (cpu_state.eflags & VM_FLAG) && (IOPL != 3)) { + x86gpf(NULL, 0); + return 1; + } + if (msw & 1) { + optype = IRET; + op_pmodeiret(0); + optype = 0; + } else { + uint16_t new_cs; + CPU_SET_OXPC + if (stack32) { + cpu_state.pc = readmemw(ss, ESP); + new_cs = readmemw(ss, ESP + 2); + cpu_state.flags = (cpu_state.flags & 0x7000) | (readmemw(ss, ESP + 4) & 0xffd5) | 2; + ESP += 6; + } else { + cpu_state.pc = readmemw(ss, SP); + new_cs = readmemw(ss, ((SP + 2) & 0xffff)); + cpu_state.flags = (cpu_state.flags & 0x7000) | (readmemw(ss, ((SP + 4) & 0xffff)) & 0x0fd5) | 2; + SP += 6; + } + op_loadcs(new_cs); + cycles -= timing_iret_rm; + } + flags_extract(); + nmi_enable = 1; + CPU_BLOCK_END(); + + PREFETCH_RUN(cycles_old - cycles, 1, -1, 2, 0, 0, 0, 0); + PREFETCH_FLUSH(); + return cpu_state.abrt; +} + +static int +opIRET(uint32_t fetchdat) +{ + int cycles_old = cycles; + UN_USED(cycles_old); + + if ((cr0 & 1) && (cpu_state.eflags & VM_FLAG) && (IOPL != 3)) { + if (cr4 & CR4_VME) { + uint16_t new_pc; + uint16_t new_cs; + uint16_t new_flags; + + new_pc = readmemw(ss, SP); + new_cs = readmemw(ss, ((SP + 2) & 0xffff)); + new_flags = readmemw(ss, ((SP + 4) & 0xffff)); + if (cpu_state.abrt) return 1; - } - if (msw&1) - { - optype = IRET; - pmodeiret(0); - optype = 0; - } - else - { - uint16_t new_cs; - CPU_SET_OXPC - if (stack32) - { - cpu_state.pc = readmemw(ss, ESP); - new_cs = readmemw(ss, ESP + 2); - cpu_state.flags = (cpu_state.flags & 0x7000) | (readmemw(ss, ESP + 4) & 0xffd5) | 2; - ESP += 6; - } - else - { - cpu_state.pc = readmemw(ss, SP); - new_cs = readmemw(ss, ((SP + 2) & 0xffff)); - cpu_state.flags = (cpu_state.flags & 0x7000) | (readmemw(ss, ((SP + 4) & 0xffff)) & 0x0fd5) | 2; - SP += 6; - } - loadcs(new_cs); - cycles -= timing_iret_rm; - } - flags_extract(); - nmi_enable = 1; - CPU_BLOCK_END(); - PREFETCH_RUN(cycles_old-cycles, 1, -1, 2,0,0,0, 0); - PREFETCH_FLUSH(); - return cpu_state.abrt; -} - -static int opIRET(uint32_t fetchdat) -{ - int cycles_old = cycles; UN_USED(cycles_old); - - if ((cr0 & 1) && (cpu_state.eflags & VM_FLAG) && (IOPL != 3)) - { - if (cr4 & CR4_VME) - { - uint16_t new_pc, new_cs, new_flags; - - new_pc = readmemw(ss, SP); - new_cs = readmemw(ss, ((SP + 2) & 0xffff)); - new_flags = readmemw(ss, ((SP + 4) & 0xffff)); - if (cpu_state.abrt) - return 1; - - if ((new_flags & T_FLAG) || ((new_flags & I_FLAG) && (cpu_state.eflags & VIP_FLAG))) - { - x86gpf(NULL, 0); - return 1; - } - SP += 6; - if (new_flags & I_FLAG) - cpu_state.eflags |= VIF_FLAG; - else - cpu_state.eflags &= ~VIF_FLAG; - cpu_state.flags = (cpu_state.flags & 0x3300) | (new_flags & 0x4cd5) | 2; - loadcs(new_cs); - cpu_state.pc = new_pc; - - cycles -= timing_iret_rm; - } - else - { - x86gpf_expected(NULL,0); - return 1; - } - } - else - { - if (msw&1) - { - optype = IRET; - pmodeiret(0); - optype = 0; - } - else - { - uint16_t new_cs; - CPU_SET_OXPC - if (stack32) - { - cpu_state.pc = readmemw(ss, ESP); - new_cs = readmemw(ss, ESP + 2); - cpu_state.flags = (readmemw(ss, ESP + 4) & 0xffd5) | 2; - ESP += 6; - } - else - { - cpu_state.pc = readmemw(ss, SP); - new_cs = readmemw(ss, ((SP + 2) & 0xffff)); - cpu_state.flags = (readmemw(ss, ((SP + 4) & 0xffff)) & 0xffd5) | 2; - SP += 6; - } - loadcs(new_cs); - cycles -= timing_iret_rm; - } - } - flags_extract(); - nmi_enable = 1; - CPU_BLOCK_END(); - - PREFETCH_RUN(cycles_old-cycles, 1, -1, 2,0,0,0, 0); - PREFETCH_FLUSH(); - return cpu_state.abrt; -} - -static int opIRETD(uint32_t fetchdat) -{ - int cycles_old = cycles; UN_USED(cycles_old); - - if ((cr0 & 1) && (cpu_state.eflags & VM_FLAG) && (IOPL != 3)) - { - x86gpf_expected(NULL,0); + if ((new_flags & T_FLAG) || ((new_flags & I_FLAG) && (cpu_state.eflags & VIP_FLAG))) { + x86gpf(NULL, 0); return 1; - } - if (msw & 1) - { - optype = IRET; - pmodeiret(1); - optype = 0; - } - else - { - uint16_t new_cs; - CPU_SET_OXPC - if (stack32) - { - cpu_state.pc = readmeml(ss, ESP); - new_cs = readmemw(ss, ESP + 4); - cpu_state.flags = (readmemw(ss, ESP + 8) & 0xffd5) | 2; - cpu_state.eflags = readmemw(ss, ESP + 10); - ESP += 12; - } - else - { - cpu_state.pc = readmeml(ss, SP); - new_cs = readmemw(ss, ((SP + 4) & 0xffff)); - cpu_state.flags = (readmemw(ss,(SP + 8) & 0xffff) & 0xffd5) | 2; - cpu_state.eflags = readmemw(ss, (SP + 10) & 0xffff); - SP += 12; - } - loadcs(new_cs); - cycles -= timing_iret_rm; - } - flags_extract(); - nmi_enable = 1; - CPU_BLOCK_END(); + } + SP += 6; + if (new_flags & I_FLAG) + cpu_state.eflags |= VIF_FLAG; + else + cpu_state.eflags &= ~VIF_FLAG; + cpu_state.flags = (cpu_state.flags & 0x3300) | (new_flags & 0x4cd5) | 2; + op_loadcs(new_cs); + cpu_state.pc = new_pc; - PREFETCH_RUN(cycles_old-cycles, 1, -1, 0,2,0,0, 1); - PREFETCH_FLUSH(); - return cpu_state.abrt; + cycles -= timing_iret_rm; + } else { + x86gpf_expected(NULL, 0); + return 1; + } + } else { + if (msw & 1) { + optype = IRET; + op_pmodeiret(0); + optype = 0; + } else { + uint16_t new_cs; + CPU_SET_OXPC + if (stack32) { + cpu_state.pc = readmemw(ss, ESP); + new_cs = readmemw(ss, ESP + 2); + cpu_state.flags = (readmemw(ss, ESP + 4) & 0xffd5) | 2; + ESP += 6; + } else { + cpu_state.pc = readmemw(ss, SP); + new_cs = readmemw(ss, ((SP + 2) & 0xffff)); + cpu_state.flags = (readmemw(ss, ((SP + 4) & 0xffff)) & 0xffd5) | 2; + SP += 6; + } + op_loadcs(new_cs); + cycles -= timing_iret_rm; + } + } + flags_extract(); + nmi_enable = 1; + CPU_BLOCK_END(); + + PREFETCH_RUN(cycles_old - cycles, 1, -1, 2, 0, 0, 0, 0); + PREFETCH_FLUSH(); + return cpu_state.abrt; +} + +static int +opIRETD(uint32_t fetchdat) +{ + int cycles_old = cycles; + UN_USED(cycles_old); + + if ((cr0 & 1) && (cpu_state.eflags & VM_FLAG) && (IOPL != 3)) { + x86gpf_expected(NULL, 0); + return 1; + } + if (msw & 1) { + optype = IRET; + op_pmodeiret(1); + optype = 0; + } else { + uint16_t new_cs; + CPU_SET_OXPC + if (stack32) { + cpu_state.pc = readmeml(ss, ESP); + new_cs = readmemw(ss, ESP + 4); + cpu_state.flags = (readmemw(ss, ESP + 8) & 0xffd5) | 2; + cpu_state.eflags = readmemw(ss, ESP + 10); + ESP += 12; + } else { + cpu_state.pc = readmeml(ss, SP); + new_cs = readmemw(ss, ((SP + 4) & 0xffff)); + cpu_state.flags = (readmemw(ss, (SP + 8) & 0xffff) & 0xffd5) | 2; + cpu_state.eflags = readmemw(ss, (SP + 10) & 0xffff); + SP += 12; + } + op_loadcs(new_cs); + cycles -= timing_iret_rm; + } + flags_extract(); + nmi_enable = 1; + CPU_BLOCK_END(); + + PREFETCH_RUN(cycles_old - cycles, 1, -1, 0, 2, 0, 0, 1); + PREFETCH_FLUSH(); + return cpu_state.abrt; } - diff --git a/src/cpu/x86_ops_set.h b/src/cpu/x86_ops_set.h index f6fd50e69..75caa4491 100644 --- a/src/cpu/x86_ops_set.h +++ b/src/cpu/x86_ops_set.h @@ -1,24 +1,25 @@ -#define opSET(condition) \ - static int opSET ## condition ## _a16(uint32_t fetchdat) \ - { \ - fetch_ea_16(fetchdat); \ - if (cpu_mod != 3) \ - SEG_CHECK_READ(cpu_state.ea_seg); \ - seteab((cond_ ## condition) ? 1 : 0); \ - CLOCK_CYCLES(4); \ - return cpu_state.abrt; \ - } \ - \ - static int opSET ## condition ## _a32(uint32_t fetchdat) \ - { \ - fetch_ea_32(fetchdat); \ - if (cpu_mod != 3) \ - SEG_CHECK_READ(cpu_state.ea_seg); \ - seteab((cond_ ## condition) ? 1 : 0); \ - CLOCK_CYCLES(4); \ - return cpu_state.abrt; \ - } +#define opSET(condition) \ + static int opSET##condition##_a16(uint32_t fetchdat) \ + { \ + fetch_ea_16(fetchdat); \ + if (cpu_mod != 3) \ + SEG_CHECK_READ(cpu_state.ea_seg); \ + seteab((cond_##condition) ? 1 : 0); \ + CLOCK_CYCLES(4); \ + return cpu_state.abrt; \ + } \ + \ + static int opSET##condition##_a32(uint32_t fetchdat) \ + { \ + fetch_ea_32(fetchdat); \ + if (cpu_mod != 3) \ + SEG_CHECK_READ(cpu_state.ea_seg); \ + seteab((cond_##condition) ? 1 : 0); \ + CLOCK_CYCLES(4); \ + return cpu_state.abrt; \ + } +// clang-format off opSET(O) opSET(NO) opSET(B) @@ -35,3 +36,4 @@ opSET(L) opSET(NL) opSET(LE) opSET(NLE) + // clang-format on diff --git a/src/cpu/x86_ops_shift.h b/src/cpu/x86_ops_shift.h index b2812d8a7..1394cf420 100644 --- a/src/cpu/x86_ops_shift.h +++ b/src/cpu/x86_ops_shift.h @@ -1,852 +1,1074 @@ #ifdef USE_NEW_DYNAREC -#define OP_SHIFT_b(c, ea32) \ - { \ - uint8_t temp_orig = temp; \ - if (!c) return 0; \ - flags_rebuild(); \ - switch (rmdat & 0x38) \ - { \ - case 0x00: /*ROL b, c*/ \ - temp = (temp << (c & 7)) | (temp >> (8-(c & 7))); \ - seteab(temp); if (cpu_state.abrt) return 1; \ - set_flags_rotate(FLAGS_ROL8, temp); \ - CLOCK_CYCLES((cpu_mod == 3) ? 3 : 7); \ - PREFETCH_RUN((cpu_mod == 3) ? 3 : 7, 2, rmdat, (cpu_mod == 3) ? 0:1,0,(cpu_mod == 3) ? 0:1,0, ea32); \ - break; \ - case 0x08: /*ROR b,CL*/ \ - temp = (temp >> (c & 7)) | (temp << (8-(c & 7))); \ - seteab(temp); if (cpu_state.abrt) return 1; \ - set_flags_rotate(FLAGS_ROR8, temp); \ - CLOCK_CYCLES((cpu_mod == 3) ? 3 : 7); \ - PREFETCH_RUN((cpu_mod == 3) ? 3 : 7, 2, rmdat, (cpu_mod == 3) ? 0:1,0,(cpu_mod == 3) ? 0:1,0, ea32); \ - break; \ - case 0x10: /*RCL b,CL*/ \ - temp2 = cpu_state.flags & C_FLAG; \ - if (is486) CLOCK_CYCLES_ALWAYS(c); \ - while (c > 0) \ - { \ - tempc = temp2 ? 1 : 0; \ - temp2 = temp & 0x80; \ - temp = (temp << 1) | tempc; \ - c--; \ - } \ - seteab(temp); if (cpu_state.abrt) return 1; \ - cpu_state.flags &= ~(C_FLAG | V_FLAG); \ - if (temp2) cpu_state.flags |= C_FLAG; \ - if ((cpu_state.flags & C_FLAG) ^ (temp >> 7)) cpu_state.flags |= V_FLAG; \ - CLOCK_CYCLES((cpu_mod == 3) ? 9 : 10); \ - PREFETCH_RUN((cpu_mod == 3) ? 9 : 10, 2, rmdat, (cpu_mod == 3) ? 0:1,0,(cpu_mod == 3) ? 0:1,0, ea32); \ - break; \ - case 0x18: /*RCR b,CL*/ \ - temp2 = cpu_state.flags & C_FLAG; \ - if (is486) CLOCK_CYCLES_ALWAYS(c); \ - while (c > 0) \ - { \ - tempc = temp2 ? 0x80 : 0; \ - temp2 = temp & 1; \ - temp = (temp >> 1) | tempc; \ - c--; \ - } \ - seteab(temp); if (cpu_state.abrt) return 1; \ - cpu_state.flags &= ~(C_FLAG | V_FLAG); \ - if (temp2) cpu_state.flags |= C_FLAG; \ - if ((temp ^ (temp >> 1)) & 0x40) cpu_state.flags |= V_FLAG; \ - CLOCK_CYCLES((cpu_mod == 3) ? 9 : 10); \ - PREFETCH_RUN((cpu_mod == 3) ? 9 : 10, 2, rmdat, (cpu_mod == 3) ? 0:1,0,(cpu_mod == 3) ? 0:1,0, ea32); \ - break; \ - case 0x20: case 0x30: /*SHL b,CL*/ \ - seteab(temp << c); if (cpu_state.abrt) return 1; \ - set_flags_shift(FLAGS_SHL8, temp_orig, c, (temp << c) & 0xff); \ - CLOCK_CYCLES((cpu_mod == 3) ? 3 : 7); \ - PREFETCH_RUN((cpu_mod == 3) ? 3 : 7, 2, rmdat, (cpu_mod == 3) ? 0:1,0,(cpu_mod == 3) ? 0:1,0, ea32); \ - break; \ - case 0x28: /*SHR b,CL*/ \ - seteab(temp >> c); if (cpu_state.abrt) return 1; \ - set_flags_shift(FLAGS_SHR8, temp_orig, c, temp >> c); \ - CLOCK_CYCLES((cpu_mod == 3) ? 3 : 7); \ - PREFETCH_RUN((cpu_mod == 3) ? 3 : 7, 2, rmdat, (cpu_mod == 3) ? 0:1,0,(cpu_mod == 3) ? 0:1,0, ea32); \ - break; \ - case 0x38: /*SAR b,CL*/ \ - temp = (int8_t)temp >> c; \ - seteab(temp); if (cpu_state.abrt) return 1; \ - set_flags_shift(FLAGS_SAR8, temp_orig, c, temp); \ - CLOCK_CYCLES((cpu_mod == 3) ? 3 : 7); \ - PREFETCH_RUN((cpu_mod == 3) ? 3 : 7, 2, rmdat, (cpu_mod == 3) ? 0:1,0,(cpu_mod == 3) ? 0:1,0, ea32); \ - break; \ - } \ +# define OP_SHIFT_b(c, ea32) \ + { \ + uint8_t temp_orig = temp; \ + if (!c) \ + return 0; \ + flags_rebuild(); \ + switch (rmdat & 0x38) { \ + case 0x00: /*ROL b, c*/ \ + temp = (temp << (c & 7)) | (temp >> (8 - (c & 7))); \ + seteab(temp); \ + if (cpu_state.abrt) \ + return 1; \ + set_flags_rotate(FLAGS_ROL8, temp); \ + CLOCK_CYCLES((cpu_mod == 3) ? 3 : 7); \ + PREFETCH_RUN((cpu_mod == 3) ? 3 : 7, 2, rmdat, (cpu_mod == 3) ? 0 : 1, 0, (cpu_mod == 3) ? 0 : 1, 0, ea32); \ + break; \ + case 0x08: /*ROR b,CL*/ \ + temp = (temp >> (c & 7)) | (temp << (8 - (c & 7))); \ + seteab(temp); \ + if (cpu_state.abrt) \ + return 1; \ + set_flags_rotate(FLAGS_ROR8, temp); \ + CLOCK_CYCLES((cpu_mod == 3) ? 3 : 7); \ + PREFETCH_RUN((cpu_mod == 3) ? 3 : 7, 2, rmdat, (cpu_mod == 3) ? 0 : 1, 0, (cpu_mod == 3) ? 0 : 1, 0, ea32); \ + break; \ + case 0x10: /*RCL b,CL*/ \ + temp2 = cpu_state.flags & C_FLAG; \ + if (is486) \ + CLOCK_CYCLES_ALWAYS(c); \ + while (c > 0) { \ + tempc = temp2 ? 1 : 0; \ + temp2 = temp & 0x80; \ + temp = (temp << 1) | tempc; \ + c--; \ + } \ + seteab(temp); \ + if (cpu_state.abrt) \ + return 1; \ + cpu_state.flags &= ~(C_FLAG | V_FLAG); \ + if (temp2) \ + cpu_state.flags |= C_FLAG; \ + if ((cpu_state.flags & C_FLAG) ^ (temp >> 7)) \ + cpu_state.flags |= V_FLAG; \ + CLOCK_CYCLES((cpu_mod == 3) ? 9 : 10); \ + PREFETCH_RUN((cpu_mod == 3) ? 9 : 10, 2, rmdat, (cpu_mod == 3) ? 0 : 1, 0, (cpu_mod == 3) ? 0 : 1, 0, ea32); \ + break; \ + case 0x18: /*RCR b,CL*/ \ + temp2 = cpu_state.flags & C_FLAG; \ + if (is486) \ + CLOCK_CYCLES_ALWAYS(c); \ + while (c > 0) { \ + tempc = temp2 ? 0x80 : 0; \ + temp2 = temp & 1; \ + temp = (temp >> 1) | tempc; \ + c--; \ + } \ + seteab(temp); \ + if (cpu_state.abrt) \ + return 1; \ + cpu_state.flags &= ~(C_FLAG | V_FLAG); \ + if (temp2) \ + cpu_state.flags |= C_FLAG; \ + if ((temp ^ (temp >> 1)) & 0x40) \ + cpu_state.flags |= V_FLAG; \ + CLOCK_CYCLES((cpu_mod == 3) ? 9 : 10); \ + PREFETCH_RUN((cpu_mod == 3) ? 9 : 10, 2, rmdat, (cpu_mod == 3) ? 0 : 1, 0, (cpu_mod == 3) ? 0 : 1, 0, ea32); \ + break; \ + case 0x20: \ + case 0x30: /*SHL b,CL*/ \ + seteab(temp << c); \ + if (cpu_state.abrt) \ + return 1; \ + set_flags_shift(FLAGS_SHL8, temp_orig, c, (temp << c) & 0xff); \ + CLOCK_CYCLES((cpu_mod == 3) ? 3 : 7); \ + PREFETCH_RUN((cpu_mod == 3) ? 3 : 7, 2, rmdat, (cpu_mod == 3) ? 0 : 1, 0, (cpu_mod == 3) ? 0 : 1, 0, ea32); \ + break; \ + case 0x28: /*SHR b,CL*/ \ + seteab(temp >> c); \ + if (cpu_state.abrt) \ + return 1; \ + set_flags_shift(FLAGS_SHR8, temp_orig, c, temp >> c); \ + CLOCK_CYCLES((cpu_mod == 3) ? 3 : 7); \ + PREFETCH_RUN((cpu_mod == 3) ? 3 : 7, 2, rmdat, (cpu_mod == 3) ? 0 : 1, 0, (cpu_mod == 3) ? 0 : 1, 0, ea32); \ + break; \ + case 0x38: /*SAR b,CL*/ \ + temp = (int8_t) temp >> c; \ + seteab(temp); \ + if (cpu_state.abrt) \ + return 1; \ + set_flags_shift(FLAGS_SAR8, temp_orig, c, temp); \ + CLOCK_CYCLES((cpu_mod == 3) ? 3 : 7); \ + PREFETCH_RUN((cpu_mod == 3) ? 3 : 7, 2, rmdat, (cpu_mod == 3) ? 0 : 1, 0, (cpu_mod == 3) ? 0 : 1, 0, ea32); \ + break; \ + } \ } -#define OP_SHIFT_w(c, ea32) \ - { \ - uint16_t temp_orig = temp; \ - if (!c) return 0; \ - flags_rebuild(); \ - switch (rmdat & 0x38) \ - { \ - case 0x00: /*ROL w, c*/ \ - temp = (temp << (c & 15)) | (temp >> (16-(c & 15))); \ - seteaw(temp); if (cpu_state.abrt) return 1; \ - set_flags_rotate(FLAGS_ROL16, temp); \ - CLOCK_CYCLES((cpu_mod == 3) ? 3 : 7); \ - PREFETCH_RUN((cpu_mod == 3) ? 3 : 7, 2, rmdat, (cpu_mod == 3) ? 0:1,0,(cpu_mod == 3) ? 0:1,0, ea32); \ - break; \ - case 0x08: /*ROR w,CL*/ \ - temp = (temp >> (c & 15)) | (temp << (16-(c & 15))); \ - seteaw(temp); if (cpu_state.abrt) return 1; \ - set_flags_rotate(FLAGS_ROR16, temp); \ - CLOCK_CYCLES((cpu_mod == 3) ? 3 : 7); \ - PREFETCH_RUN((cpu_mod == 3) ? 3 : 7, 2, rmdat, (cpu_mod == 3) ? 0:1,0,(cpu_mod == 3) ? 0:1,0, ea32); \ - break; \ - case 0x10: /*RCL w, c*/ \ - temp2 = cpu_state.flags & C_FLAG; \ - if (is486) CLOCK_CYCLES_ALWAYS(c); \ - while (c > 0) \ - { \ - tempc = temp2 ? 1 : 0; \ - temp2 = temp & 0x8000; \ - temp = (temp << 1) | tempc; \ - c--; \ - } \ - seteaw(temp); if (cpu_state.abrt) return 1; \ - cpu_state.flags &= ~(C_FLAG | V_FLAG); \ - if (temp2) cpu_state.flags |= C_FLAG; \ - if ((cpu_state.flags & C_FLAG) ^ (temp >> 15)) cpu_state.flags |= V_FLAG; \ - CLOCK_CYCLES((cpu_mod == 3) ? 9 : 10); \ - PREFETCH_RUN((cpu_mod == 3) ? 9 : 10, 2, rmdat, (cpu_mod == 3) ? 0:1,0,(cpu_mod == 3) ? 0:1,0, ea32); \ - break; \ - case 0x18: /*RCR w, c*/ \ - temp2 = cpu_state.flags & C_FLAG; \ - if (is486) CLOCK_CYCLES_ALWAYS(c); \ - while (c > 0) \ - { \ - tempc = temp2 ? 0x8000 : 0; \ - temp2 = temp & 1; \ - temp = (temp >> 1) | tempc; \ - c--; \ - } \ - seteaw(temp); if (cpu_state.abrt) return 1; \ - cpu_state.flags &= ~(C_FLAG | V_FLAG); \ - if (temp2) cpu_state.flags |= C_FLAG; \ - if ((temp ^ (temp >> 1)) & 0x4000) cpu_state.flags |= V_FLAG; \ - CLOCK_CYCLES((cpu_mod == 3) ? 9 : 10); \ - PREFETCH_RUN((cpu_mod == 3) ? 9 : 10, 2, rmdat, (cpu_mod == 3) ? 0:1,0,(cpu_mod == 3) ? 0:1,0, ea32); \ - break; \ - case 0x20: case 0x30: /*SHL w, c*/ \ - seteaw(temp << c); if (cpu_state.abrt) return 1; \ - set_flags_shift(FLAGS_SHL16, temp_orig, c, (temp << c) & 0xffff); \ - CLOCK_CYCLES((cpu_mod == 3) ? 3 : 7); \ - PREFETCH_RUN((cpu_mod == 3) ? 3 : 7, 2, rmdat, (cpu_mod == 3) ? 0:1,0,(cpu_mod == 3) ? 0:1,0, ea32); \ - break; \ - case 0x28: /*SHR w, c*/ \ - seteaw(temp >> c); if (cpu_state.abrt) return 1; \ - set_flags_shift(FLAGS_SHR16, temp_orig, c, temp >> c); \ - CLOCK_CYCLES((cpu_mod == 3) ? 3 : 7); \ - PREFETCH_RUN((cpu_mod == 3) ? 3 : 7, 2, rmdat, (cpu_mod == 3) ? 0:1,0,(cpu_mod == 3) ? 0:1,0, ea32); \ - break; \ - case 0x38: /*SAR w, c*/ \ - temp = (int16_t)temp >> c; \ - seteaw(temp); if (cpu_state.abrt) return 1; \ - set_flags_shift(FLAGS_SAR16, temp_orig, c, temp); \ - CLOCK_CYCLES((cpu_mod == 3) ? 3 : 7); \ - PREFETCH_RUN((cpu_mod == 3) ? 3 : 7, 2, rmdat, (cpu_mod == 3) ? 0:1,0,(cpu_mod == 3) ? 0:1,0, ea32); \ - break; \ - } \ +# define OP_SHIFT_w(c, ea32) \ + { \ + uint16_t temp_orig = temp; \ + if (!c) \ + return 0; \ + flags_rebuild(); \ + switch (rmdat & 0x38) { \ + case 0x00: /*ROL w, c*/ \ + temp = (temp << (c & 15)) | (temp >> (16 - (c & 15))); \ + seteaw(temp); \ + if (cpu_state.abrt) \ + return 1; \ + set_flags_rotate(FLAGS_ROL16, temp); \ + CLOCK_CYCLES((cpu_mod == 3) ? 3 : 7); \ + PREFETCH_RUN((cpu_mod == 3) ? 3 : 7, 2, rmdat, (cpu_mod == 3) ? 0 : 1, 0, (cpu_mod == 3) ? 0 : 1, 0, ea32); \ + break; \ + case 0x08: /*ROR w,CL*/ \ + temp = (temp >> (c & 15)) | (temp << (16 - (c & 15))); \ + seteaw(temp); \ + if (cpu_state.abrt) \ + return 1; \ + set_flags_rotate(FLAGS_ROR16, temp); \ + CLOCK_CYCLES((cpu_mod == 3) ? 3 : 7); \ + PREFETCH_RUN((cpu_mod == 3) ? 3 : 7, 2, rmdat, (cpu_mod == 3) ? 0 : 1, 0, (cpu_mod == 3) ? 0 : 1, 0, ea32); \ + break; \ + case 0x10: /*RCL w, c*/ \ + temp2 = cpu_state.flags & C_FLAG; \ + if (is486) \ + CLOCK_CYCLES_ALWAYS(c); \ + while (c > 0) { \ + tempc = temp2 ? 1 : 0; \ + temp2 = temp & 0x8000; \ + temp = (temp << 1) | tempc; \ + c--; \ + } \ + seteaw(temp); \ + if (cpu_state.abrt) \ + return 1; \ + cpu_state.flags &= ~(C_FLAG | V_FLAG); \ + if (temp2) \ + cpu_state.flags |= C_FLAG; \ + if ((cpu_state.flags & C_FLAG) ^ (temp >> 15)) \ + cpu_state.flags |= V_FLAG; \ + CLOCK_CYCLES((cpu_mod == 3) ? 9 : 10); \ + PREFETCH_RUN((cpu_mod == 3) ? 9 : 10, 2, rmdat, (cpu_mod == 3) ? 0 : 1, 0, (cpu_mod == 3) ? 0 : 1, 0, ea32); \ + break; \ + case 0x18: /*RCR w, c*/ \ + temp2 = cpu_state.flags & C_FLAG; \ + if (is486) \ + CLOCK_CYCLES_ALWAYS(c); \ + while (c > 0) { \ + tempc = temp2 ? 0x8000 : 0; \ + temp2 = temp & 1; \ + temp = (temp >> 1) | tempc; \ + c--; \ + } \ + seteaw(temp); \ + if (cpu_state.abrt) \ + return 1; \ + cpu_state.flags &= ~(C_FLAG | V_FLAG); \ + if (temp2) \ + cpu_state.flags |= C_FLAG; \ + if ((temp ^ (temp >> 1)) & 0x4000) \ + cpu_state.flags |= V_FLAG; \ + CLOCK_CYCLES((cpu_mod == 3) ? 9 : 10); \ + PREFETCH_RUN((cpu_mod == 3) ? 9 : 10, 2, rmdat, (cpu_mod == 3) ? 0 : 1, 0, (cpu_mod == 3) ? 0 : 1, 0, ea32); \ + break; \ + case 0x20: \ + case 0x30: /*SHL w, c*/ \ + seteaw(temp << c); \ + if (cpu_state.abrt) \ + return 1; \ + set_flags_shift(FLAGS_SHL16, temp_orig, c, (temp << c) & 0xffff); \ + CLOCK_CYCLES((cpu_mod == 3) ? 3 : 7); \ + PREFETCH_RUN((cpu_mod == 3) ? 3 : 7, 2, rmdat, (cpu_mod == 3) ? 0 : 1, 0, (cpu_mod == 3) ? 0 : 1, 0, ea32); \ + break; \ + case 0x28: /*SHR w, c*/ \ + seteaw(temp >> c); \ + if (cpu_state.abrt) \ + return 1; \ + set_flags_shift(FLAGS_SHR16, temp_orig, c, temp >> c); \ + CLOCK_CYCLES((cpu_mod == 3) ? 3 : 7); \ + PREFETCH_RUN((cpu_mod == 3) ? 3 : 7, 2, rmdat, (cpu_mod == 3) ? 0 : 1, 0, (cpu_mod == 3) ? 0 : 1, 0, ea32); \ + break; \ + case 0x38: /*SAR w, c*/ \ + temp = (int16_t) temp >> c; \ + seteaw(temp); \ + if (cpu_state.abrt) \ + return 1; \ + set_flags_shift(FLAGS_SAR16, temp_orig, c, temp); \ + CLOCK_CYCLES((cpu_mod == 3) ? 3 : 7); \ + PREFETCH_RUN((cpu_mod == 3) ? 3 : 7, 2, rmdat, (cpu_mod == 3) ? 0 : 1, 0, (cpu_mod == 3) ? 0 : 1, 0, ea32); \ + break; \ + } \ } -#define OP_SHIFT_l(c, ea32) \ - { \ - uint32_t temp_orig = temp; \ - if (!c) return 0; \ - flags_rebuild(); \ - switch (rmdat & 0x38) \ - { \ - case 0x00: /*ROL l, c*/ \ - temp = (temp << c) | (temp >> (32-c)); \ - seteal(temp); if (cpu_state.abrt) return 1; \ - set_flags_rotate(FLAGS_ROL32, temp); \ - CLOCK_CYCLES((cpu_mod == 3) ? 3 : 7); \ - PREFETCH_RUN((cpu_mod == 3) ? 3 : 7, 2, rmdat, (cpu_mod == 3) ? 0:1,0,(cpu_mod == 3) ? 0:1,0, ea32); \ - break; \ - case 0x08: /*ROR l,CL*/ \ - temp = (temp >> c) | (temp << (32-c)); \ - seteal(temp); if (cpu_state.abrt) return 1; \ - set_flags_rotate(FLAGS_ROR32, temp); \ - CLOCK_CYCLES((cpu_mod == 3) ? 3 : 7); \ - PREFETCH_RUN((cpu_mod == 3) ? 3 : 7, 2, rmdat, (cpu_mod == 3) ? 0:1,0,(cpu_mod == 3) ? 0:1,0, ea32); \ - break; \ - case 0x10: /*RCL l, c*/ \ - temp2 = CF_SET(); \ - if (is486) CLOCK_CYCLES_ALWAYS(c); \ - while (c > 0) \ - { \ - tempc = temp2 ? 1 : 0; \ - temp2 = temp & 0x80000000; \ - temp = (temp << 1) | tempc; \ - c--; \ - } \ - seteal(temp); if (cpu_state.abrt) return 1; \ - cpu_state.flags &= ~(C_FLAG | V_FLAG); \ - if (temp2) cpu_state.flags |= C_FLAG; \ - if ((cpu_state.flags & C_FLAG) ^ (temp >> 31)) cpu_state.flags |= V_FLAG; \ - CLOCK_CYCLES((cpu_mod == 3) ? 9 : 10); \ - PREFETCH_RUN((cpu_mod == 3) ? 9 : 10, 2, rmdat, 0,(cpu_mod == 3) ? 0:1,0,(cpu_mod == 3) ? 0:1, ea32); \ - break; \ - case 0x18: /*RCR l, c*/ \ - temp2 = cpu_state.flags & C_FLAG; \ - if (is486) CLOCK_CYCLES_ALWAYS(c); \ - while (c > 0) \ - { \ - tempc = temp2 ? 0x80000000 : 0; \ - temp2 = temp & 1; \ - temp = (temp >> 1) | tempc; \ - c--; \ - } \ - seteal(temp); if (cpu_state.abrt) return 1; \ - cpu_state.flags &= ~(C_FLAG | V_FLAG); \ - if (temp2) cpu_state.flags |= C_FLAG; \ - if ((temp ^ (temp >> 1)) & 0x40000000) cpu_state.flags |= V_FLAG; \ - CLOCK_CYCLES((cpu_mod == 3) ? 9 : 10); \ - PREFETCH_RUN((cpu_mod == 3) ? 9 : 10, 2, rmdat, 0,(cpu_mod == 3) ? 0:1,0,(cpu_mod == 3) ? 0:1, ea32); \ - break; \ - case 0x20: case 0x30: /*SHL l, c*/ \ - seteal(temp << c); if (cpu_state.abrt) return 1; \ - set_flags_shift(FLAGS_SHL32, temp_orig, c, temp << c); \ - CLOCK_CYCLES((cpu_mod == 3) ? 3 : 7); \ - PREFETCH_RUN((cpu_mod == 3) ? 3 : 7, 2, rmdat, 0,(cpu_mod == 3) ? 0:1,0,(cpu_mod == 3) ? 0:1, ea32); \ - break; \ - case 0x28: /*SHR l, c*/ \ - seteal(temp >> c); if (cpu_state.abrt) return 1; \ - set_flags_shift(FLAGS_SHR32, temp_orig, c, temp >> c); \ - CLOCK_CYCLES((cpu_mod == 3) ? 3 : 7); \ - PREFETCH_RUN((cpu_mod == 3) ? 3 : 7, 2, rmdat, 0,(cpu_mod == 3) ? 0:1,0,(cpu_mod == 3) ? 0:1, ea32); \ - break; \ - case 0x38: /*SAR l, c*/ \ - temp = (int32_t)temp >> c; \ - seteal(temp); if (cpu_state.abrt) return 1; \ - set_flags_shift(FLAGS_SAR32, temp_orig, c, temp); \ - CLOCK_CYCLES((cpu_mod == 3) ? 3 : 7); \ - PREFETCH_RUN((cpu_mod == 3) ? 3 : 7, 2, rmdat, 0,(cpu_mod == 3) ? 0:1,0,(cpu_mod == 3) ? 0:1, ea32); \ - break; \ - } \ +# define OP_SHIFT_l(c, ea32) \ + { \ + uint32_t temp_orig = temp; \ + if (!c) \ + return 0; \ + flags_rebuild(); \ + switch (rmdat & 0x38) { \ + case 0x00: /*ROL l, c*/ \ + temp = (temp << c) | (temp >> (32 - c)); \ + seteal(temp); \ + if (cpu_state.abrt) \ + return 1; \ + set_flags_rotate(FLAGS_ROL32, temp); \ + CLOCK_CYCLES((cpu_mod == 3) ? 3 : 7); \ + PREFETCH_RUN((cpu_mod == 3) ? 3 : 7, 2, rmdat, (cpu_mod == 3) ? 0 : 1, 0, (cpu_mod == 3) ? 0 : 1, 0, ea32); \ + break; \ + case 0x08: /*ROR l,CL*/ \ + temp = (temp >> c) | (temp << (32 - c)); \ + seteal(temp); \ + if (cpu_state.abrt) \ + return 1; \ + set_flags_rotate(FLAGS_ROR32, temp); \ + CLOCK_CYCLES((cpu_mod == 3) ? 3 : 7); \ + PREFETCH_RUN((cpu_mod == 3) ? 3 : 7, 2, rmdat, (cpu_mod == 3) ? 0 : 1, 0, (cpu_mod == 3) ? 0 : 1, 0, ea32); \ + break; \ + case 0x10: /*RCL l, c*/ \ + temp2 = CF_SET(); \ + if (is486) \ + CLOCK_CYCLES_ALWAYS(c); \ + while (c > 0) { \ + tempc = temp2 ? 1 : 0; \ + temp2 = temp & 0x80000000; \ + temp = (temp << 1) | tempc; \ + c--; \ + } \ + seteal(temp); \ + if (cpu_state.abrt) \ + return 1; \ + cpu_state.flags &= ~(C_FLAG | V_FLAG); \ + if (temp2) \ + cpu_state.flags |= C_FLAG; \ + if ((cpu_state.flags & C_FLAG) ^ (temp >> 31)) \ + cpu_state.flags |= V_FLAG; \ + CLOCK_CYCLES((cpu_mod == 3) ? 9 : 10); \ + PREFETCH_RUN((cpu_mod == 3) ? 9 : 10, 2, rmdat, 0, (cpu_mod == 3) ? 0 : 1, 0, (cpu_mod == 3) ? 0 : 1, ea32); \ + break; \ + case 0x18: /*RCR l, c*/ \ + temp2 = cpu_state.flags & C_FLAG; \ + if (is486) \ + CLOCK_CYCLES_ALWAYS(c); \ + while (c > 0) { \ + tempc = temp2 ? 0x80000000 : 0; \ + temp2 = temp & 1; \ + temp = (temp >> 1) | tempc; \ + c--; \ + } \ + seteal(temp); \ + if (cpu_state.abrt) \ + return 1; \ + cpu_state.flags &= ~(C_FLAG | V_FLAG); \ + if (temp2) \ + cpu_state.flags |= C_FLAG; \ + if ((temp ^ (temp >> 1)) & 0x40000000) \ + cpu_state.flags |= V_FLAG; \ + CLOCK_CYCLES((cpu_mod == 3) ? 9 : 10); \ + PREFETCH_RUN((cpu_mod == 3) ? 9 : 10, 2, rmdat, 0, (cpu_mod == 3) ? 0 : 1, 0, (cpu_mod == 3) ? 0 : 1, ea32); \ + break; \ + case 0x20: \ + case 0x30: /*SHL l, c*/ \ + seteal(temp << c); \ + if (cpu_state.abrt) \ + return 1; \ + set_flags_shift(FLAGS_SHL32, temp_orig, c, temp << c); \ + CLOCK_CYCLES((cpu_mod == 3) ? 3 : 7); \ + PREFETCH_RUN((cpu_mod == 3) ? 3 : 7, 2, rmdat, 0, (cpu_mod == 3) ? 0 : 1, 0, (cpu_mod == 3) ? 0 : 1, ea32); \ + break; \ + case 0x28: /*SHR l, c*/ \ + seteal(temp >> c); \ + if (cpu_state.abrt) \ + return 1; \ + set_flags_shift(FLAGS_SHR32, temp_orig, c, temp >> c); \ + CLOCK_CYCLES((cpu_mod == 3) ? 3 : 7); \ + PREFETCH_RUN((cpu_mod == 3) ? 3 : 7, 2, rmdat, 0, (cpu_mod == 3) ? 0 : 1, 0, (cpu_mod == 3) ? 0 : 1, ea32); \ + break; \ + case 0x38: /*SAR l, c*/ \ + temp = (int32_t) temp >> c; \ + seteal(temp); \ + if (cpu_state.abrt) \ + return 1; \ + set_flags_shift(FLAGS_SAR32, temp_orig, c, temp); \ + CLOCK_CYCLES((cpu_mod == 3) ? 3 : 7); \ + PREFETCH_RUN((cpu_mod == 3) ? 3 : 7, 2, rmdat, 0, (cpu_mod == 3) ? 0 : 1, 0, (cpu_mod == 3) ? 0 : 1, ea32); \ + break; \ + } \ } #else -#define OP_SHIFT_b(c, ea32) \ - { \ - uint8_t temp_orig = temp; \ - if (!c) return 0; \ - flags_rebuild(); \ - switch (rmdat & 0x38) \ - { \ - case 0x00: /*ROL b, c*/ \ - temp = (temp << (c & 7)) | (temp >> (8-(c & 7))); \ - seteab(temp); if (cpu_state.abrt) return 1; \ - cpu_state.flags &= ~(C_FLAG | V_FLAG); \ - if (temp & 1) cpu_state.flags |= C_FLAG; \ - if ((temp ^ (temp >> 7)) & 1) cpu_state.flags |= V_FLAG; \ - CLOCK_CYCLES((cpu_mod == 3) ? 3 : 7); \ - PREFETCH_RUN((cpu_mod == 3) ? 3 : 7, 2, rmdat, (cpu_mod == 3) ? 0:1,0,(cpu_mod == 3) ? 0:1,0, ea32); \ - break; \ - case 0x08: /*ROR b,CL*/ \ - temp = (temp >> (c & 7)) | (temp << (8-(c & 7))); \ - seteab(temp); if (cpu_state.abrt) return 1; \ - cpu_state.flags &= ~(C_FLAG | V_FLAG); \ - if (temp & 0x80) cpu_state.flags |= C_FLAG; \ - if ((temp ^ (temp >> 1)) & 0x40) cpu_state.flags |= V_FLAG; \ - CLOCK_CYCLES((cpu_mod == 3) ? 3 : 7); \ - PREFETCH_RUN((cpu_mod == 3) ? 3 : 7, 2, rmdat, (cpu_mod == 3) ? 0:1,0,(cpu_mod == 3) ? 0:1,0, ea32); \ - break; \ - case 0x10: /*RCL b,CL*/ \ - temp2 = cpu_state.flags & C_FLAG; \ - if (is486) CLOCK_CYCLES_ALWAYS(c); \ - while (c > 0) \ - { \ - tempc = temp2 ? 1 : 0; \ - temp2 = temp & 0x80; \ - temp = (temp << 1) | tempc; \ - c--; \ - } \ - seteab(temp); if (cpu_state.abrt) return 1; \ - cpu_state.flags &= ~(C_FLAG | V_FLAG); \ - if (temp2) cpu_state.flags |= C_FLAG; \ - if ((cpu_state.flags & C_FLAG) ^ (temp >> 7)) cpu_state.flags |= V_FLAG; \ - CLOCK_CYCLES((cpu_mod == 3) ? 9 : 10); \ - PREFETCH_RUN((cpu_mod == 3) ? 9 : 10, 2, rmdat, (cpu_mod == 3) ? 0:1,0,(cpu_mod == 3) ? 0:1,0, ea32); \ - break; \ - case 0x18: /*RCR b,CL*/ \ - temp2 = cpu_state.flags & C_FLAG; \ - if (is486) CLOCK_CYCLES_ALWAYS(c); \ - while (c > 0) \ - { \ - tempc = temp2 ? 0x80 : 0; \ - temp2 = temp & 1; \ - temp = (temp >> 1) | tempc; \ - c--; \ - } \ - seteab(temp); if (cpu_state.abrt) return 1; \ - cpu_state.flags &= ~(C_FLAG | V_FLAG); \ - if (temp2) cpu_state.flags |= C_FLAG; \ - if ((temp ^ (temp >> 1)) & 0x40) cpu_state.flags |= V_FLAG; \ - CLOCK_CYCLES((cpu_mod == 3) ? 9 : 10); \ - PREFETCH_RUN((cpu_mod == 3) ? 9 : 10, 2, rmdat, (cpu_mod == 3) ? 0:1,0,(cpu_mod == 3) ? 0:1,0, ea32); \ - break; \ - case 0x20: case 0x30: /*SHL b,CL*/ \ - seteab(temp << c); if (cpu_state.abrt) return 1; \ - set_flags_shift(FLAGS_SHL8, temp_orig, c, (temp << c) & 0xff); \ - CLOCK_CYCLES((cpu_mod == 3) ? 3 : 7); \ - PREFETCH_RUN((cpu_mod == 3) ? 3 : 7, 2, rmdat, (cpu_mod == 3) ? 0:1,0,(cpu_mod == 3) ? 0:1,0, ea32); \ - break; \ - case 0x28: /*SHR b,CL*/ \ - seteab(temp >> c); if (cpu_state.abrt) return 1; \ - set_flags_shift(FLAGS_SHR8, temp_orig, c, temp >> c); \ - CLOCK_CYCLES((cpu_mod == 3) ? 3 : 7); \ - PREFETCH_RUN((cpu_mod == 3) ? 3 : 7, 2, rmdat, (cpu_mod == 3) ? 0:1,0,(cpu_mod == 3) ? 0:1,0, ea32); \ - break; \ - case 0x38: /*SAR b,CL*/ \ - temp = (int8_t)temp >> c; \ - seteab(temp); if (cpu_state.abrt) return 1; \ - set_flags_shift(FLAGS_SAR8, temp_orig, c, temp); \ - CLOCK_CYCLES((cpu_mod == 3) ? 3 : 7); \ - PREFETCH_RUN((cpu_mod == 3) ? 3 : 7, 2, rmdat, (cpu_mod == 3) ? 0:1,0,(cpu_mod == 3) ? 0:1,0, ea32); \ - break; \ - } \ +# define OP_SHIFT_b(c, ea32) \ + { \ + uint8_t temp_orig = temp; \ + if (!c) \ + return 0; \ + flags_rebuild(); \ + switch (rmdat & 0x38) { \ + case 0x00: /*ROL b, c*/ \ + temp = (temp << (c & 7)) | (temp >> (8 - (c & 7))); \ + seteab(temp); \ + if (cpu_state.abrt) \ + return 1; \ + cpu_state.flags &= ~(C_FLAG | V_FLAG); \ + if (temp & 1) \ + cpu_state.flags |= C_FLAG; \ + if ((temp ^ (temp >> 7)) & 1) \ + cpu_state.flags |= V_FLAG; \ + CLOCK_CYCLES((cpu_mod == 3) ? 3 : 7); \ + PREFETCH_RUN((cpu_mod == 3) ? 3 : 7, 2, rmdat, (cpu_mod == 3) ? 0 : 1, 0, (cpu_mod == 3) ? 0 : 1, 0, ea32); \ + break; \ + case 0x08: /*ROR b,CL*/ \ + temp = (temp >> (c & 7)) | (temp << (8 - (c & 7))); \ + seteab(temp); \ + if (cpu_state.abrt) \ + return 1; \ + cpu_state.flags &= ~(C_FLAG | V_FLAG); \ + if (temp & 0x80) \ + cpu_state.flags |= C_FLAG; \ + if ((temp ^ (temp >> 1)) & 0x40) \ + cpu_state.flags |= V_FLAG; \ + CLOCK_CYCLES((cpu_mod == 3) ? 3 : 7); \ + PREFETCH_RUN((cpu_mod == 3) ? 3 : 7, 2, rmdat, (cpu_mod == 3) ? 0 : 1, 0, (cpu_mod == 3) ? 0 : 1, 0, ea32); \ + break; \ + case 0x10: /*RCL b,CL*/ \ + temp2 = cpu_state.flags & C_FLAG; \ + if (is486) \ + CLOCK_CYCLES_ALWAYS(c); \ + while (c > 0) { \ + tempc = temp2 ? 1 : 0; \ + temp2 = temp & 0x80; \ + temp = (temp << 1) | tempc; \ + c--; \ + } \ + seteab(temp); \ + if (cpu_state.abrt) \ + return 1; \ + cpu_state.flags &= ~(C_FLAG | V_FLAG); \ + if (temp2) \ + cpu_state.flags |= C_FLAG; \ + if ((cpu_state.flags & C_FLAG) ^ (temp >> 7)) \ + cpu_state.flags |= V_FLAG; \ + CLOCK_CYCLES((cpu_mod == 3) ? 9 : 10); \ + PREFETCH_RUN((cpu_mod == 3) ? 9 : 10, 2, rmdat, (cpu_mod == 3) ? 0 : 1, 0, (cpu_mod == 3) ? 0 : 1, 0, ea32); \ + break; \ + case 0x18: /*RCR b,CL*/ \ + temp2 = cpu_state.flags & C_FLAG; \ + if (is486) \ + CLOCK_CYCLES_ALWAYS(c); \ + while (c > 0) { \ + tempc = temp2 ? 0x80 : 0; \ + temp2 = temp & 1; \ + temp = (temp >> 1) | tempc; \ + c--; \ + } \ + seteab(temp); \ + if (cpu_state.abrt) \ + return 1; \ + cpu_state.flags &= ~(C_FLAG | V_FLAG); \ + if (temp2) \ + cpu_state.flags |= C_FLAG; \ + if ((temp ^ (temp >> 1)) & 0x40) \ + cpu_state.flags |= V_FLAG; \ + CLOCK_CYCLES((cpu_mod == 3) ? 9 : 10); \ + PREFETCH_RUN((cpu_mod == 3) ? 9 : 10, 2, rmdat, (cpu_mod == 3) ? 0 : 1, 0, (cpu_mod == 3) ? 0 : 1, 0, ea32); \ + break; \ + case 0x20: \ + case 0x30: /*SHL b,CL*/ \ + seteab(temp << c); \ + if (cpu_state.abrt) \ + return 1; \ + set_flags_shift(FLAGS_SHL8, temp_orig, c, (temp << c) & 0xff); \ + CLOCK_CYCLES((cpu_mod == 3) ? 3 : 7); \ + PREFETCH_RUN((cpu_mod == 3) ? 3 : 7, 2, rmdat, (cpu_mod == 3) ? 0 : 1, 0, (cpu_mod == 3) ? 0 : 1, 0, ea32); \ + break; \ + case 0x28: /*SHR b,CL*/ \ + seteab(temp >> c); \ + if (cpu_state.abrt) \ + return 1; \ + set_flags_shift(FLAGS_SHR8, temp_orig, c, temp >> c); \ + CLOCK_CYCLES((cpu_mod == 3) ? 3 : 7); \ + PREFETCH_RUN((cpu_mod == 3) ? 3 : 7, 2, rmdat, (cpu_mod == 3) ? 0 : 1, 0, (cpu_mod == 3) ? 0 : 1, 0, ea32); \ + break; \ + case 0x38: /*SAR b,CL*/ \ + temp = (int8_t) temp >> c; \ + seteab(temp); \ + if (cpu_state.abrt) \ + return 1; \ + set_flags_shift(FLAGS_SAR8, temp_orig, c, temp); \ + CLOCK_CYCLES((cpu_mod == 3) ? 3 : 7); \ + PREFETCH_RUN((cpu_mod == 3) ? 3 : 7, 2, rmdat, (cpu_mod == 3) ? 0 : 1, 0, (cpu_mod == 3) ? 0 : 1, 0, ea32); \ + break; \ + } \ } -#define OP_SHIFT_w(c, ea32) \ - { \ - uint16_t temp_orig = temp; \ - if (!c) return 0; \ - flags_rebuild(); \ - switch (rmdat & 0x38) \ - { \ - case 0x00: /*ROL w, c*/ \ - temp = (temp << (c & 15)) | (temp >> (16-(c & 15))); \ - seteaw(temp); if (cpu_state.abrt) return 1; \ - cpu_state.flags &= ~(C_FLAG | V_FLAG); \ - if (temp & 1) cpu_state.flags |= C_FLAG; \ - if ((temp ^ (temp >> 15)) & 1) cpu_state.flags |= V_FLAG; \ - CLOCK_CYCLES((cpu_mod == 3) ? 3 : 7); \ - PREFETCH_RUN((cpu_mod == 3) ? 3 : 7, 2, rmdat, (cpu_mod == 3) ? 0:1,0,(cpu_mod == 3) ? 0:1,0, ea32); \ - break; \ - case 0x08: /*ROR w,CL*/ \ - temp = (temp >> (c & 15)) | (temp << (16-(c & 15))); \ - seteaw(temp); if (cpu_state.abrt) return 1; \ - cpu_state.flags &= ~(C_FLAG | V_FLAG); \ - if (temp & 0x8000) cpu_state.flags |= C_FLAG; \ - if ((temp ^ (temp >> 1)) & 0x4000) cpu_state.flags |= V_FLAG; \ - CLOCK_CYCLES((cpu_mod == 3) ? 3 : 7); \ - PREFETCH_RUN((cpu_mod == 3) ? 3 : 7, 2, rmdat, (cpu_mod == 3) ? 0:1,0,(cpu_mod == 3) ? 0:1,0, ea32); \ - break; \ - case 0x10: /*RCL w, c*/ \ - temp2 = cpu_state.flags & C_FLAG; \ - if (is486) CLOCK_CYCLES_ALWAYS(c); \ - while (c > 0) \ - { \ - tempc = temp2 ? 1 : 0; \ - temp2 = temp & 0x8000; \ - temp = (temp << 1) | tempc; \ - c--; \ - } \ - seteaw(temp); if (cpu_state.abrt) return 1; \ - cpu_state.flags &= ~(C_FLAG | V_FLAG); \ - if (temp2) cpu_state.flags |= C_FLAG; \ - if ((cpu_state.flags & C_FLAG) ^ (temp >> 15)) cpu_state.flags |= V_FLAG; \ - CLOCK_CYCLES((cpu_mod == 3) ? 9 : 10); \ - PREFETCH_RUN((cpu_mod == 3) ? 9 : 10, 2, rmdat, (cpu_mod == 3) ? 0:1,0,(cpu_mod == 3) ? 0:1,0, ea32); \ - break; \ - case 0x18: /*RCR w, c*/ \ - temp2 = cpu_state.flags & C_FLAG; \ - if (is486) CLOCK_CYCLES_ALWAYS(c); \ - while (c > 0) \ - { \ - tempc = temp2 ? 0x8000 : 0; \ - temp2 = temp & 1; \ - temp = (temp >> 1) | tempc; \ - c--; \ - } \ - seteaw(temp); if (cpu_state.abrt) return 1; \ - cpu_state.flags &= ~(C_FLAG | V_FLAG); \ - if (temp2) cpu_state.flags |= C_FLAG; \ - if ((temp ^ (temp >> 1)) & 0x4000) cpu_state.flags |= V_FLAG; \ - CLOCK_CYCLES((cpu_mod == 3) ? 9 : 10); \ - PREFETCH_RUN((cpu_mod == 3) ? 9 : 10, 2, rmdat, (cpu_mod == 3) ? 0:1,0,(cpu_mod == 3) ? 0:1,0, ea32); \ - break; \ - case 0x20: case 0x30: /*SHL w, c*/ \ - seteaw(temp << c); if (cpu_state.abrt) return 1; \ - set_flags_shift(FLAGS_SHL16, temp_orig, c, (temp << c) & 0xffff); \ - CLOCK_CYCLES((cpu_mod == 3) ? 3 : 7); \ - PREFETCH_RUN((cpu_mod == 3) ? 3 : 7, 2, rmdat, (cpu_mod == 3) ? 0:1,0,(cpu_mod == 3) ? 0:1,0, ea32); \ - break; \ - case 0x28: /*SHR w, c*/ \ - seteaw(temp >> c); if (cpu_state.abrt) return 1; \ - set_flags_shift(FLAGS_SHR16, temp_orig, c, temp >> c); \ - CLOCK_CYCLES((cpu_mod == 3) ? 3 : 7); \ - PREFETCH_RUN((cpu_mod == 3) ? 3 : 7, 2, rmdat, (cpu_mod == 3) ? 0:1,0,(cpu_mod == 3) ? 0:1,0, ea32); \ - break; \ - case 0x38: /*SAR w, c*/ \ - temp = (int16_t)temp >> c; \ - seteaw(temp); if (cpu_state.abrt) return 1; \ - set_flags_shift(FLAGS_SAR16, temp_orig, c, temp); \ - CLOCK_CYCLES((cpu_mod == 3) ? 3 : 7); \ - PREFETCH_RUN((cpu_mod == 3) ? 3 : 7, 2, rmdat, (cpu_mod == 3) ? 0:1,0,(cpu_mod == 3) ? 0:1,0, ea32); \ - break; \ - } \ +# define OP_SHIFT_w(c, ea32) \ + { \ + uint16_t temp_orig = temp; \ + if (!c) \ + return 0; \ + flags_rebuild(); \ + switch (rmdat & 0x38) { \ + case 0x00: /*ROL w, c*/ \ + temp = (temp << (c & 15)) | (temp >> (16 - (c & 15))); \ + seteaw(temp); \ + if (cpu_state.abrt) \ + return 1; \ + cpu_state.flags &= ~(C_FLAG | V_FLAG); \ + if (temp & 1) \ + cpu_state.flags |= C_FLAG; \ + if ((temp ^ (temp >> 15)) & 1) \ + cpu_state.flags |= V_FLAG; \ + CLOCK_CYCLES((cpu_mod == 3) ? 3 : 7); \ + PREFETCH_RUN((cpu_mod == 3) ? 3 : 7, 2, rmdat, (cpu_mod == 3) ? 0 : 1, 0, (cpu_mod == 3) ? 0 : 1, 0, ea32); \ + break; \ + case 0x08: /*ROR w,CL*/ \ + temp = (temp >> (c & 15)) | (temp << (16 - (c & 15))); \ + seteaw(temp); \ + if (cpu_state.abrt) \ + return 1; \ + cpu_state.flags &= ~(C_FLAG | V_FLAG); \ + if (temp & 0x8000) \ + cpu_state.flags |= C_FLAG; \ + if ((temp ^ (temp >> 1)) & 0x4000) \ + cpu_state.flags |= V_FLAG; \ + CLOCK_CYCLES((cpu_mod == 3) ? 3 : 7); \ + PREFETCH_RUN((cpu_mod == 3) ? 3 : 7, 2, rmdat, (cpu_mod == 3) ? 0 : 1, 0, (cpu_mod == 3) ? 0 : 1, 0, ea32); \ + break; \ + case 0x10: /*RCL w, c*/ \ + temp2 = cpu_state.flags & C_FLAG; \ + if (is486) \ + CLOCK_CYCLES_ALWAYS(c); \ + while (c > 0) { \ + tempc = temp2 ? 1 : 0; \ + temp2 = temp & 0x8000; \ + temp = (temp << 1) | tempc; \ + c--; \ + } \ + seteaw(temp); \ + if (cpu_state.abrt) \ + return 1; \ + cpu_state.flags &= ~(C_FLAG | V_FLAG); \ + if (temp2) \ + cpu_state.flags |= C_FLAG; \ + if ((cpu_state.flags & C_FLAG) ^ (temp >> 15)) \ + cpu_state.flags |= V_FLAG; \ + CLOCK_CYCLES((cpu_mod == 3) ? 9 : 10); \ + PREFETCH_RUN((cpu_mod == 3) ? 9 : 10, 2, rmdat, (cpu_mod == 3) ? 0 : 1, 0, (cpu_mod == 3) ? 0 : 1, 0, ea32); \ + break; \ + case 0x18: /*RCR w, c*/ \ + temp2 = cpu_state.flags & C_FLAG; \ + if (is486) \ + CLOCK_CYCLES_ALWAYS(c); \ + while (c > 0) { \ + tempc = temp2 ? 0x8000 : 0; \ + temp2 = temp & 1; \ + temp = (temp >> 1) | tempc; \ + c--; \ + } \ + seteaw(temp); \ + if (cpu_state.abrt) \ + return 1; \ + cpu_state.flags &= ~(C_FLAG | V_FLAG); \ + if (temp2) \ + cpu_state.flags |= C_FLAG; \ + if ((temp ^ (temp >> 1)) & 0x4000) \ + cpu_state.flags |= V_FLAG; \ + CLOCK_CYCLES((cpu_mod == 3) ? 9 : 10); \ + PREFETCH_RUN((cpu_mod == 3) ? 9 : 10, 2, rmdat, (cpu_mod == 3) ? 0 : 1, 0, (cpu_mod == 3) ? 0 : 1, 0, ea32); \ + break; \ + case 0x20: \ + case 0x30: /*SHL w, c*/ \ + seteaw(temp << c); \ + if (cpu_state.abrt) \ + return 1; \ + set_flags_shift(FLAGS_SHL16, temp_orig, c, (temp << c) & 0xffff); \ + CLOCK_CYCLES((cpu_mod == 3) ? 3 : 7); \ + PREFETCH_RUN((cpu_mod == 3) ? 3 : 7, 2, rmdat, (cpu_mod == 3) ? 0 : 1, 0, (cpu_mod == 3) ? 0 : 1, 0, ea32); \ + break; \ + case 0x28: /*SHR w, c*/ \ + seteaw(temp >> c); \ + if (cpu_state.abrt) \ + return 1; \ + set_flags_shift(FLAGS_SHR16, temp_orig, c, temp >> c); \ + CLOCK_CYCLES((cpu_mod == 3) ? 3 : 7); \ + PREFETCH_RUN((cpu_mod == 3) ? 3 : 7, 2, rmdat, (cpu_mod == 3) ? 0 : 1, 0, (cpu_mod == 3) ? 0 : 1, 0, ea32); \ + break; \ + case 0x38: /*SAR w, c*/ \ + temp = (int16_t) temp >> c; \ + seteaw(temp); \ + if (cpu_state.abrt) \ + return 1; \ + set_flags_shift(FLAGS_SAR16, temp_orig, c, temp); \ + CLOCK_CYCLES((cpu_mod == 3) ? 3 : 7); \ + PREFETCH_RUN((cpu_mod == 3) ? 3 : 7, 2, rmdat, (cpu_mod == 3) ? 0 : 1, 0, (cpu_mod == 3) ? 0 : 1, 0, ea32); \ + break; \ + } \ } -#define OP_SHIFT_l(c, ea32) \ - { \ - uint32_t temp_orig = temp; \ - if (!c) return 0; \ - flags_rebuild(); \ - switch (rmdat & 0x38) \ - { \ - case 0x00: /*ROL l, c*/ \ - temp = (temp << c) | (temp >> (32-c)); \ - seteal(temp); if (cpu_state.abrt) return 1; \ - cpu_state.flags &= ~(C_FLAG | V_FLAG); \ - if (temp & 1) cpu_state.flags |= C_FLAG; \ - if ((temp ^ (temp >> 31)) & 1) cpu_state.flags |= V_FLAG; \ - CLOCK_CYCLES((cpu_mod == 3) ? 3 : 7); \ - PREFETCH_RUN((cpu_mod == 3) ? 3 : 7, 2, rmdat, (cpu_mod == 3) ? 0:1,0,(cpu_mod == 3) ? 0:1,0, ea32); \ - break; \ - case 0x08: /*ROR l,CL*/ \ - temp = (temp >> c) | (temp << (32-c)); \ - seteal(temp); if (cpu_state.abrt) return 1; \ - cpu_state.flags &= ~(C_FLAG | V_FLAG); \ - if (temp & 0x80000000) cpu_state.flags |= C_FLAG; \ - if ((temp ^ (temp >> 1)) & 0x40000000) cpu_state.flags |= V_FLAG; \ - CLOCK_CYCLES((cpu_mod == 3) ? 3 : 7); \ - PREFETCH_RUN((cpu_mod == 3) ? 3 : 7, 2, rmdat, (cpu_mod == 3) ? 0:1,0,(cpu_mod == 3) ? 0:1,0, ea32); \ - break; \ - case 0x10: /*RCL l, c*/ \ - temp2 = CF_SET(); \ - if (is486) CLOCK_CYCLES_ALWAYS(c); \ - while (c > 0) \ - { \ - tempc = temp2 ? 1 : 0; \ - temp2 = temp & 0x80000000; \ - temp = (temp << 1) | tempc; \ - c--; \ - } \ - seteal(temp); if (cpu_state.abrt) return 1; \ - cpu_state.flags &= ~(C_FLAG | V_FLAG); \ - if (temp2) cpu_state.flags |= C_FLAG; \ - if ((cpu_state.flags & C_FLAG) ^ (temp >> 31)) cpu_state.flags |= V_FLAG; \ - CLOCK_CYCLES((cpu_mod == 3) ? 9 : 10); \ - PREFETCH_RUN((cpu_mod == 3) ? 9 : 10, 2, rmdat, 0,(cpu_mod == 3) ? 0:1,0,(cpu_mod == 3) ? 0:1, ea32); \ - break; \ - case 0x18: /*RCR l, c*/ \ - temp2 = cpu_state.flags & C_FLAG; \ - if (is486) CLOCK_CYCLES_ALWAYS(c); \ - while (c > 0) \ - { \ - tempc = temp2 ? 0x80000000 : 0; \ - temp2 = temp & 1; \ - temp = (temp >> 1) | tempc; \ - c--; \ - } \ - seteal(temp); if (cpu_state.abrt) return 1; \ - cpu_state.flags &= ~(C_FLAG | V_FLAG); \ - if (temp2) cpu_state.flags |= C_FLAG; \ - if ((temp ^ (temp >> 1)) & 0x40000000) cpu_state.flags |= V_FLAG; \ - CLOCK_CYCLES((cpu_mod == 3) ? 9 : 10); \ - PREFETCH_RUN((cpu_mod == 3) ? 9 : 10, 2, rmdat, 0,(cpu_mod == 3) ? 0:1,0,(cpu_mod == 3) ? 0:1, ea32); \ - break; \ - case 0x20: case 0x30: /*SHL l, c*/ \ - seteal(temp << c); if (cpu_state.abrt) return 1; \ - set_flags_shift(FLAGS_SHL32, temp_orig, c, temp << c); \ - CLOCK_CYCLES((cpu_mod == 3) ? 3 : 7); \ - PREFETCH_RUN((cpu_mod == 3) ? 3 : 7, 2, rmdat, 0,(cpu_mod == 3) ? 0:1,0,(cpu_mod == 3) ? 0:1, ea32); \ - break; \ - case 0x28: /*SHR l, c*/ \ - seteal(temp >> c); if (cpu_state.abrt) return 1; \ - set_flags_shift(FLAGS_SHR32, temp_orig, c, temp >> c); \ - CLOCK_CYCLES((cpu_mod == 3) ? 3 : 7); \ - PREFETCH_RUN((cpu_mod == 3) ? 3 : 7, 2, rmdat, 0,(cpu_mod == 3) ? 0:1,0,(cpu_mod == 3) ? 0:1, ea32); \ - break; \ - case 0x38: /*SAR l, c*/ \ - temp = (int32_t)temp >> c; \ - seteal(temp); if (cpu_state.abrt) return 1; \ - set_flags_shift(FLAGS_SAR32, temp_orig, c, temp); \ - CLOCK_CYCLES((cpu_mod == 3) ? 3 : 7); \ - PREFETCH_RUN((cpu_mod == 3) ? 3 : 7, 2, rmdat, 0,(cpu_mod == 3) ? 0:1,0,(cpu_mod == 3) ? 0:1, ea32); \ - break; \ - } \ +# define OP_SHIFT_l(c, ea32) \ + { \ + uint32_t temp_orig = temp; \ + if (!c) \ + return 0; \ + flags_rebuild(); \ + switch (rmdat & 0x38) { \ + case 0x00: /*ROL l, c*/ \ + temp = (temp << c) | (temp >> (32 - c)); \ + seteal(temp); \ + if (cpu_state.abrt) \ + return 1; \ + cpu_state.flags &= ~(C_FLAG | V_FLAG); \ + if (temp & 1) \ + cpu_state.flags |= C_FLAG; \ + if ((temp ^ (temp >> 31)) & 1) \ + cpu_state.flags |= V_FLAG; \ + CLOCK_CYCLES((cpu_mod == 3) ? 3 : 7); \ + PREFETCH_RUN((cpu_mod == 3) ? 3 : 7, 2, rmdat, (cpu_mod == 3) ? 0 : 1, 0, (cpu_mod == 3) ? 0 : 1, 0, ea32); \ + break; \ + case 0x08: /*ROR l,CL*/ \ + temp = (temp >> c) | (temp << (32 - c)); \ + seteal(temp); \ + if (cpu_state.abrt) \ + return 1; \ + cpu_state.flags &= ~(C_FLAG | V_FLAG); \ + if (temp & 0x80000000) \ + cpu_state.flags |= C_FLAG; \ + if ((temp ^ (temp >> 1)) & 0x40000000) \ + cpu_state.flags |= V_FLAG; \ + CLOCK_CYCLES((cpu_mod == 3) ? 3 : 7); \ + PREFETCH_RUN((cpu_mod == 3) ? 3 : 7, 2, rmdat, (cpu_mod == 3) ? 0 : 1, 0, (cpu_mod == 3) ? 0 : 1, 0, ea32); \ + break; \ + case 0x10: /*RCL l, c*/ \ + temp2 = CF_SET(); \ + if (is486) \ + CLOCK_CYCLES_ALWAYS(c); \ + while (c > 0) { \ + tempc = temp2 ? 1 : 0; \ + temp2 = temp & 0x80000000; \ + temp = (temp << 1) | tempc; \ + c--; \ + } \ + seteal(temp); \ + if (cpu_state.abrt) \ + return 1; \ + cpu_state.flags &= ~(C_FLAG | V_FLAG); \ + if (temp2) \ + cpu_state.flags |= C_FLAG; \ + if ((cpu_state.flags & C_FLAG) ^ (temp >> 31)) \ + cpu_state.flags |= V_FLAG; \ + CLOCK_CYCLES((cpu_mod == 3) ? 9 : 10); \ + PREFETCH_RUN((cpu_mod == 3) ? 9 : 10, 2, rmdat, 0, (cpu_mod == 3) ? 0 : 1, 0, (cpu_mod == 3) ? 0 : 1, ea32); \ + break; \ + case 0x18: /*RCR l, c*/ \ + temp2 = cpu_state.flags & C_FLAG; \ + if (is486) \ + CLOCK_CYCLES_ALWAYS(c); \ + while (c > 0) { \ + tempc = temp2 ? 0x80000000 : 0; \ + temp2 = temp & 1; \ + temp = (temp >> 1) | tempc; \ + c--; \ + } \ + seteal(temp); \ + if (cpu_state.abrt) \ + return 1; \ + cpu_state.flags &= ~(C_FLAG | V_FLAG); \ + if (temp2) \ + cpu_state.flags |= C_FLAG; \ + if ((temp ^ (temp >> 1)) & 0x40000000) \ + cpu_state.flags |= V_FLAG; \ + CLOCK_CYCLES((cpu_mod == 3) ? 9 : 10); \ + PREFETCH_RUN((cpu_mod == 3) ? 9 : 10, 2, rmdat, 0, (cpu_mod == 3) ? 0 : 1, 0, (cpu_mod == 3) ? 0 : 1, ea32); \ + break; \ + case 0x20: \ + case 0x30: /*SHL l, c*/ \ + seteal(temp << c); \ + if (cpu_state.abrt) \ + return 1; \ + set_flags_shift(FLAGS_SHL32, temp_orig, c, temp << c); \ + CLOCK_CYCLES((cpu_mod == 3) ? 3 : 7); \ + PREFETCH_RUN((cpu_mod == 3) ? 3 : 7, 2, rmdat, 0, (cpu_mod == 3) ? 0 : 1, 0, (cpu_mod == 3) ? 0 : 1, ea32); \ + break; \ + case 0x28: /*SHR l, c*/ \ + seteal(temp >> c); \ + if (cpu_state.abrt) \ + return 1; \ + set_flags_shift(FLAGS_SHR32, temp_orig, c, temp >> c); \ + CLOCK_CYCLES((cpu_mod == 3) ? 3 : 7); \ + PREFETCH_RUN((cpu_mod == 3) ? 3 : 7, 2, rmdat, 0, (cpu_mod == 3) ? 0 : 1, 0, (cpu_mod == 3) ? 0 : 1, ea32); \ + break; \ + case 0x38: /*SAR l, c*/ \ + temp = (int32_t) temp >> c; \ + seteal(temp); \ + if (cpu_state.abrt) \ + return 1; \ + set_flags_shift(FLAGS_SAR32, temp_orig, c, temp); \ + CLOCK_CYCLES((cpu_mod == 3) ? 3 : 7); \ + PREFETCH_RUN((cpu_mod == 3) ? 3 : 7, 2, rmdat, 0, (cpu_mod == 3) ? 0 : 1, 0, (cpu_mod == 3) ? 0 : 1, ea32); \ + break; \ + } \ } #endif -static int opC0_a16(uint32_t fetchdat) +static int +opC0_a16(uint32_t fetchdat) { - int c; - int tempc; - uint8_t temp, temp2 = 0; - - fetch_ea_16(fetchdat); - if (cpu_mod != 3) - SEG_CHECK_WRITE(cpu_state.ea_seg); - c = readmemb(cs, cpu_state.pc) & 31; cpu_state.pc++; - PREFETCH_PREFIX(); - temp = geteab(); if (cpu_state.abrt) return 1; - OP_SHIFT_b(c, 0); - return 0; + int c; + int tempc; + uint8_t temp; + uint8_t temp2 = 0; + + fetch_ea_16(fetchdat); + if (cpu_mod != 3) + SEG_CHECK_WRITE(cpu_state.ea_seg); + c = readmemb(cs, cpu_state.pc) & 31; + cpu_state.pc++; + PREFETCH_PREFIX(); + temp = geteab(); + if (cpu_state.abrt) + return 1; + OP_SHIFT_b(c, 0); + return 0; } -static int opC0_a32(uint32_t fetchdat) +static int +opC0_a32(uint32_t fetchdat) { - int c; - int tempc; - uint8_t temp, temp2 = 0; - - fetch_ea_32(fetchdat); - if (cpu_mod != 3) - SEG_CHECK_WRITE(cpu_state.ea_seg); - c = readmemb(cs, cpu_state.pc) & 31; cpu_state.pc++; - PREFETCH_PREFIX(); - temp = geteab(); if (cpu_state.abrt) return 1; - OP_SHIFT_b(c, 1); - return 0; + int c; + int tempc; + uint8_t temp; + uint8_t temp2 = 0; + + fetch_ea_32(fetchdat); + if (cpu_mod != 3) + SEG_CHECK_WRITE(cpu_state.ea_seg); + c = readmemb(cs, cpu_state.pc) & 31; + cpu_state.pc++; + PREFETCH_PREFIX(); + temp = geteab(); + if (cpu_state.abrt) + return 1; + OP_SHIFT_b(c, 1); + return 0; } -static int opC1_w_a16(uint32_t fetchdat) +static int +opC1_w_a16(uint32_t fetchdat) { - int c; - int tempc; - uint16_t temp, temp2 = 0; - - fetch_ea_16(fetchdat); - if (cpu_mod != 3) - SEG_CHECK_WRITE(cpu_state.ea_seg); - c = readmemb(cs, cpu_state.pc) & 31; cpu_state.pc++; - PREFETCH_PREFIX(); - temp = geteaw(); if (cpu_state.abrt) return 1; - OP_SHIFT_w(c, 0); - return 0; + int c; + int tempc; + uint16_t temp; + uint16_t temp2 = 0; + + fetch_ea_16(fetchdat); + if (cpu_mod != 3) + SEG_CHECK_WRITE(cpu_state.ea_seg); + c = readmemb(cs, cpu_state.pc) & 31; + cpu_state.pc++; + PREFETCH_PREFIX(); + temp = geteaw(); + if (cpu_state.abrt) + return 1; + OP_SHIFT_w(c, 0); + return 0; } -static int opC1_w_a32(uint32_t fetchdat) +static int +opC1_w_a32(uint32_t fetchdat) { - int c; - int tempc; - uint16_t temp, temp2 = 0; - - fetch_ea_32(fetchdat); - if (cpu_mod != 3) - SEG_CHECK_WRITE(cpu_state.ea_seg); - c = readmemb(cs, cpu_state.pc) & 31; cpu_state.pc++; - PREFETCH_PREFIX(); - temp = geteaw(); if (cpu_state.abrt) return 1; - OP_SHIFT_w(c, 1); - return 0; + int c; + int tempc; + uint16_t temp; + uint16_t temp2 = 0; + + fetch_ea_32(fetchdat); + if (cpu_mod != 3) + SEG_CHECK_WRITE(cpu_state.ea_seg); + c = readmemb(cs, cpu_state.pc) & 31; + cpu_state.pc++; + PREFETCH_PREFIX(); + temp = geteaw(); + if (cpu_state.abrt) + return 1; + OP_SHIFT_w(c, 1); + return 0; } -static int opC1_l_a16(uint32_t fetchdat) +static int +opC1_l_a16(uint32_t fetchdat) { - int c; - int tempc; - uint32_t temp, temp2 = 0; - - fetch_ea_16(fetchdat); - if (cpu_mod != 3) - SEG_CHECK_WRITE(cpu_state.ea_seg); - c = readmemb(cs, cpu_state.pc) & 31; cpu_state.pc++; - PREFETCH_PREFIX(); - temp = geteal(); if (cpu_state.abrt) return 1; - OP_SHIFT_l(c, 0); - return 0; + int c; + int tempc; + uint32_t temp; + uint32_t temp2 = 0; + + fetch_ea_16(fetchdat); + if (cpu_mod != 3) + SEG_CHECK_WRITE(cpu_state.ea_seg); + c = readmemb(cs, cpu_state.pc) & 31; + cpu_state.pc++; + PREFETCH_PREFIX(); + temp = geteal(); + if (cpu_state.abrt) + return 1; + OP_SHIFT_l(c, 0); + return 0; } -static int opC1_l_a32(uint32_t fetchdat) +static int +opC1_l_a32(uint32_t fetchdat) { - int c; - int tempc; - uint32_t temp, temp2 = 0; - - fetch_ea_32(fetchdat); - if (cpu_mod != 3) - SEG_CHECK_WRITE(cpu_state.ea_seg); - c = readmemb(cs, cpu_state.pc) & 31; cpu_state.pc++; - PREFETCH_PREFIX(); - temp = geteal(); if (cpu_state.abrt) return 1; - OP_SHIFT_l(c, 1); - return 0; + int c; + int tempc; + uint32_t temp; + uint32_t temp2 = 0; + + fetch_ea_32(fetchdat); + if (cpu_mod != 3) + SEG_CHECK_WRITE(cpu_state.ea_seg); + c = readmemb(cs, cpu_state.pc) & 31; + cpu_state.pc++; + PREFETCH_PREFIX(); + temp = geteal(); + if (cpu_state.abrt) + return 1; + OP_SHIFT_l(c, 1); + return 0; } -static int opD0_a16(uint32_t fetchdat) +static int +opD0_a16(uint32_t fetchdat) { - int c = 1; - int tempc; - uint8_t temp, temp2 = 0; - - fetch_ea_16(fetchdat); - if (cpu_mod != 3) - SEG_CHECK_WRITE(cpu_state.ea_seg); - temp = geteab(); if (cpu_state.abrt) return 1; - OP_SHIFT_b(c, 0); - return 0; + int c = 1; + int tempc; + uint8_t temp; + uint8_t temp2 = 0; + + fetch_ea_16(fetchdat); + if (cpu_mod != 3) + SEG_CHECK_WRITE(cpu_state.ea_seg); + temp = geteab(); + if (cpu_state.abrt) + return 1; + OP_SHIFT_b(c, 0); + return 0; } -static int opD0_a32(uint32_t fetchdat) +static int +opD0_a32(uint32_t fetchdat) { - int c = 1; - int tempc; - uint8_t temp, temp2 = 0; - - fetch_ea_32(fetchdat); - if (cpu_mod != 3) - SEG_CHECK_WRITE(cpu_state.ea_seg); - temp = geteab(); if (cpu_state.abrt) return 1; - OP_SHIFT_b(c, 1); - return 0; + int c = 1; + int tempc; + uint8_t temp; + uint8_t temp2 = 0; + + fetch_ea_32(fetchdat); + if (cpu_mod != 3) + SEG_CHECK_WRITE(cpu_state.ea_seg); + temp = geteab(); + if (cpu_state.abrt) + return 1; + OP_SHIFT_b(c, 1); + return 0; } -static int opD1_w_a16(uint32_t fetchdat) +static int +opD1_w_a16(uint32_t fetchdat) { - int c = 1; - int tempc; - uint16_t temp, temp2 = 0; - - fetch_ea_16(fetchdat); - if (cpu_mod != 3) - SEG_CHECK_WRITE(cpu_state.ea_seg); - temp = geteaw(); if (cpu_state.abrt) return 1; - OP_SHIFT_w(c, 0); - return 0; + int c = 1; + int tempc; + uint16_t temp; + uint16_t temp2 = 0; + + fetch_ea_16(fetchdat); + if (cpu_mod != 3) + SEG_CHECK_WRITE(cpu_state.ea_seg); + temp = geteaw(); + if (cpu_state.abrt) + return 1; + OP_SHIFT_w(c, 0); + return 0; } -static int opD1_w_a32(uint32_t fetchdat) +static int +opD1_w_a32(uint32_t fetchdat) { - int c = 1; - int tempc; - uint16_t temp, temp2 = 0; - - fetch_ea_32(fetchdat); - if (cpu_mod != 3) - SEG_CHECK_WRITE(cpu_state.ea_seg); - temp = geteaw(); if (cpu_state.abrt) return 1; - OP_SHIFT_w(c, 1); - return 0; + int c = 1; + int tempc; + uint16_t temp; + uint16_t temp2 = 0; + + fetch_ea_32(fetchdat); + if (cpu_mod != 3) + SEG_CHECK_WRITE(cpu_state.ea_seg); + temp = geteaw(); + if (cpu_state.abrt) + return 1; + OP_SHIFT_w(c, 1); + return 0; } -static int opD1_l_a16(uint32_t fetchdat) +static int +opD1_l_a16(uint32_t fetchdat) { - int c = 1; - int tempc; - uint32_t temp, temp2 = 0; - - fetch_ea_16(fetchdat); - if (cpu_mod != 3) - SEG_CHECK_WRITE(cpu_state.ea_seg); - temp = geteal(); if (cpu_state.abrt) return 1; - OP_SHIFT_l(c, 0); - return 0; + int c = 1; + int tempc; + uint32_t temp; + uint32_t temp2 = 0; + + fetch_ea_16(fetchdat); + if (cpu_mod != 3) + SEG_CHECK_WRITE(cpu_state.ea_seg); + temp = geteal(); + if (cpu_state.abrt) + return 1; + OP_SHIFT_l(c, 0); + return 0; } -static int opD1_l_a32(uint32_t fetchdat) +static int +opD1_l_a32(uint32_t fetchdat) { - int c = 1; - int tempc; - uint32_t temp, temp2 = 0; - - fetch_ea_32(fetchdat); - if (cpu_mod != 3) - SEG_CHECK_WRITE(cpu_state.ea_seg); - temp = geteal(); if (cpu_state.abrt) return 1; - OP_SHIFT_l(c, 1); - return 0; + int c = 1; + int tempc; + uint32_t temp; + uint32_t temp2 = 0; + + fetch_ea_32(fetchdat); + if (cpu_mod != 3) + SEG_CHECK_WRITE(cpu_state.ea_seg); + temp = geteal(); + if (cpu_state.abrt) + return 1; + OP_SHIFT_l(c, 1); + return 0; } -static int opD2_a16(uint32_t fetchdat) +static int +opD2_a16(uint32_t fetchdat) { - int c; - int tempc; - uint8_t temp, temp2 = 0; - - fetch_ea_16(fetchdat); - if (cpu_mod != 3) - SEG_CHECK_WRITE(cpu_state.ea_seg); - c = CL & 31; - temp = geteab(); if (cpu_state.abrt) return 1; - OP_SHIFT_b(c, 0); - return 0; + int c; + int tempc; + uint8_t temp; + uint8_t temp2 = 0; + + fetch_ea_16(fetchdat); + if (cpu_mod != 3) + SEG_CHECK_WRITE(cpu_state.ea_seg); + c = CL & 31; + temp = geteab(); + if (cpu_state.abrt) + return 1; + OP_SHIFT_b(c, 0); + return 0; } -static int opD2_a32(uint32_t fetchdat) +static int +opD2_a32(uint32_t fetchdat) { - int c; - int tempc; - uint8_t temp, temp2 = 0; - - fetch_ea_32(fetchdat); - if (cpu_mod != 3) - SEG_CHECK_WRITE(cpu_state.ea_seg); - c = CL & 31; - temp = geteab(); if (cpu_state.abrt) return 1; - OP_SHIFT_b(c, 1); - return 0; + int c; + int tempc; + uint8_t temp; + uint8_t temp2 = 0; + + fetch_ea_32(fetchdat); + if (cpu_mod != 3) + SEG_CHECK_WRITE(cpu_state.ea_seg); + c = CL & 31; + temp = geteab(); + if (cpu_state.abrt) + return 1; + OP_SHIFT_b(c, 1); + return 0; } -static int opD3_w_a16(uint32_t fetchdat) +static int +opD3_w_a16(uint32_t fetchdat) { - int c; - int tempc; - uint16_t temp, temp2 = 0; - - fetch_ea_16(fetchdat); - if (cpu_mod != 3) - SEG_CHECK_WRITE(cpu_state.ea_seg); - c = CL & 31; - temp = geteaw(); if (cpu_state.abrt) return 1; - OP_SHIFT_w(c, 0); - return 0; + int c; + int tempc; + uint16_t temp; + uint16_t temp2 = 0; + + fetch_ea_16(fetchdat); + if (cpu_mod != 3) + SEG_CHECK_WRITE(cpu_state.ea_seg); + c = CL & 31; + temp = geteaw(); + if (cpu_state.abrt) + return 1; + OP_SHIFT_w(c, 0); + return 0; } -static int opD3_w_a32(uint32_t fetchdat) +static int +opD3_w_a32(uint32_t fetchdat) { - int c; - int tempc; - uint16_t temp, temp2 = 0; - - fetch_ea_32(fetchdat); - if (cpu_mod != 3) - SEG_CHECK_WRITE(cpu_state.ea_seg); - c = CL & 31; - temp = geteaw(); if (cpu_state.abrt) return 1; - OP_SHIFT_w(c, 1); - return 0; + int c; + int tempc; + uint16_t temp; + uint16_t temp2 = 0; + + fetch_ea_32(fetchdat); + if (cpu_mod != 3) + SEG_CHECK_WRITE(cpu_state.ea_seg); + c = CL & 31; + temp = geteaw(); + if (cpu_state.abrt) + return 1; + OP_SHIFT_w(c, 1); + return 0; } -static int opD3_l_a16(uint32_t fetchdat) +static int +opD3_l_a16(uint32_t fetchdat) { - int c; - int tempc; - uint32_t temp, temp2 = 0; - - fetch_ea_16(fetchdat); - if (cpu_mod != 3) - SEG_CHECK_WRITE(cpu_state.ea_seg); - c = CL & 31; - temp = geteal(); if (cpu_state.abrt) return 1; - OP_SHIFT_l(c, 0); - return 0; + int c; + int tempc; + uint32_t temp; + uint32_t temp2 = 0; + + fetch_ea_16(fetchdat); + if (cpu_mod != 3) + SEG_CHECK_WRITE(cpu_state.ea_seg); + c = CL & 31; + temp = geteal(); + if (cpu_state.abrt) + return 1; + OP_SHIFT_l(c, 0); + return 0; } -static int opD3_l_a32(uint32_t fetchdat) +static int +opD3_l_a32(uint32_t fetchdat) { - int c; - int tempc; - uint32_t temp, temp2 = 0; - - fetch_ea_32(fetchdat); - if (cpu_mod != 3) - SEG_CHECK_WRITE(cpu_state.ea_seg); - c = CL & 31; - temp = geteal(); if (cpu_state.abrt) return 1; - OP_SHIFT_l(c, 1); - return 0; + int c; + int tempc; + uint32_t temp; + uint32_t temp2 = 0; + + fetch_ea_32(fetchdat); + if (cpu_mod != 3) + SEG_CHECK_WRITE(cpu_state.ea_seg); + c = CL & 31; + temp = geteal(); + if (cpu_state.abrt) + return 1; + OP_SHIFT_l(c, 1); + return 0; } - -#define SHLD_w() \ - if (count) \ - { \ - int tempc; \ - uint32_t templ; \ - uint16_t tempw = geteaw(); if (cpu_state.abrt) return 1; \ - tempc = ((tempw << (count - 1)) & (1 << 15)) ? 1 : 0; \ - templ = (tempw << 16) | cpu_state.regs[cpu_reg].w; \ - if (count <= 16) tempw = templ >> (16 - count); \ - else tempw = (templ << count) >> 16; \ - seteaw(tempw); if (cpu_state.abrt) return 1; \ - setznp16(tempw); \ - flags_rebuild(); \ - if (tempc) cpu_state.flags |= C_FLAG; \ - } +#define SHLD_w() \ + if (count) { \ + int tempc; \ + uint32_t templ; \ + uint16_t tempw = geteaw(); \ + if (cpu_state.abrt) \ + return 1; \ + tempc = ((tempw << (count - 1)) & (1 << 15)) ? 1 : 0; \ + templ = (tempw << 16) | cpu_state.regs[cpu_reg].w; \ + if (count <= 16) \ + tempw = templ >> (16 - count); \ + else \ + tempw = (templ << count) >> 16; \ + seteaw(tempw); \ + if (cpu_state.abrt) \ + return 1; \ + setznp16(tempw); \ + flags_rebuild(); \ + if (tempc) \ + cpu_state.flags |= C_FLAG; \ + } #define SHLD_l() \ - if (count) \ - { \ - int tempc; \ - uint32_t templ = geteal(); if (cpu_state.abrt) return 1; \ - tempc = ((templ << (count - 1)) & (1 << 31)) ? 1 : 0; \ - templ = (templ << count) | (cpu_state.regs[cpu_reg].l >> (32 - count)); \ - seteal(templ); if (cpu_state.abrt) return 1; \ - setznp32(templ); \ - flags_rebuild(); \ - if (tempc) cpu_state.flags |= C_FLAG; \ - } + if (count) { \ + int tempc; \ + uint32_t templ = geteal(); \ + if (cpu_state.abrt) \ + return 1; \ + tempc = ((templ << (count - 1)) & (1 << 31)) ? 1 : 0; \ + templ = (templ << count) | (cpu_state.regs[cpu_reg].l >> (32 - count)); \ + seteal(templ); \ + if (cpu_state.abrt) \ + return 1; \ + setznp32(templ); \ + flags_rebuild(); \ + if (tempc) \ + cpu_state.flags |= C_FLAG; \ + } - -#define SHRD_w() \ - if (count) \ - { \ - int tempc; \ - uint32_t templ; \ - uint16_t tempw = geteaw(); if (cpu_state.abrt) return 1; \ - tempc = (tempw >> (count - 1)) & 1; \ - templ = tempw | (cpu_state.regs[cpu_reg].w << 16); \ - tempw = templ >> count; \ - seteaw(tempw); if (cpu_state.abrt) return 1; \ - setznp16(tempw); \ - flags_rebuild(); \ - if (tempc) cpu_state.flags |= C_FLAG; \ - } +#define SHRD_w() \ + if (count) { \ + int tempc; \ + uint32_t templ; \ + uint16_t tempw = geteaw(); \ + if (cpu_state.abrt) \ + return 1; \ + tempc = (tempw >> (count - 1)) & 1; \ + templ = tempw | (cpu_state.regs[cpu_reg].w << 16); \ + tempw = templ >> count; \ + seteaw(tempw); \ + if (cpu_state.abrt) \ + return 1; \ + setznp16(tempw); \ + flags_rebuild(); \ + if (tempc) \ + cpu_state.flags |= C_FLAG; \ + } #define SHRD_l() \ - if (count) \ - { \ - int tempc; \ - uint32_t templ = geteal(); if (cpu_state.abrt) return 1; \ - tempc = (templ >> (count - 1)) & 1; \ - templ = (templ >> count) | (cpu_state.regs[cpu_reg].l << (32 - count)); \ - seteal(templ); if (cpu_state.abrt) return 1; \ - setznp32(templ); \ - flags_rebuild(); \ - if (tempc) cpu_state.flags |= C_FLAG; \ - } + if (count) { \ + int tempc; \ + uint32_t templ = geteal(); \ + if (cpu_state.abrt) \ + return 1; \ + tempc = (templ >> (count - 1)) & 1; \ + templ = (templ >> count) | (cpu_state.regs[cpu_reg].l << (32 - count)); \ + seteal(templ); \ + if (cpu_state.abrt) \ + return 1; \ + setznp32(templ); \ + flags_rebuild(); \ + if (tempc) \ + cpu_state.flags |= C_FLAG; \ + } -#define opSHxD(operation) \ - static int op ## operation ## _i_a16(uint32_t fetchdat) \ - { \ - int count; \ - \ - fetch_ea_16(fetchdat); \ - if (cpu_mod != 3) \ - SEG_CHECK_WRITE(cpu_state.ea_seg); \ - count = getbyte() & 31; \ - operation(); \ - \ - CLOCK_CYCLES(3); \ - PREFETCH_RUN(3, 3, rmdat, 0,(cpu_mod == 3) ? 0:1,0,(cpu_mod == 3) ? 0:1, 0); \ - return 0; \ - } \ - static int op ## operation ## _CL_a16(uint32_t fetchdat) \ - { \ - int count; \ - \ - fetch_ea_16(fetchdat); \ - if (cpu_mod != 3) \ - SEG_CHECK_WRITE(cpu_state.ea_seg); \ - count = CL & 31; \ - operation(); \ - \ - CLOCK_CYCLES(3); \ - PREFETCH_RUN(3, 3, rmdat, 0,(cpu_mod == 3) ? 0:1,0,(cpu_mod == 3) ? 0:1, 0); \ - return 0; \ - } \ - static int op ## operation ## _i_a32(uint32_t fetchdat) \ - { \ - int count; \ - \ - fetch_ea_32(fetchdat); \ - if (cpu_mod != 3) \ - SEG_CHECK_WRITE(cpu_state.ea_seg); \ - count = getbyte() & 31; \ - operation(); \ - \ - CLOCK_CYCLES(3); \ - PREFETCH_RUN(3, 3, rmdat, 0,(cpu_mod == 3) ? 0:1,0,(cpu_mod == 3) ? 0:1, 1); \ - return 0; \ - } \ - static int op ## operation ## _CL_a32(uint32_t fetchdat) \ - { \ - int count; \ - \ - fetch_ea_32(fetchdat); \ - if (cpu_mod != 3) \ - SEG_CHECK_WRITE(cpu_state.ea_seg); \ - count = CL & 31; \ - operation(); \ - \ - CLOCK_CYCLES(3); \ - PREFETCH_RUN(3, 3, rmdat, 0,(cpu_mod == 3) ? 0:1,0,(cpu_mod == 3) ? 0:1, 1); \ - return 0; \ - } - +#define opSHxD(operation) \ + static int op##operation##_i_a16(uint32_t fetchdat) \ + { \ + int count; \ + \ + fetch_ea_16(fetchdat); \ + if (cpu_mod != 3) \ + SEG_CHECK_WRITE(cpu_state.ea_seg); \ + count = getbyte() & 31; \ + operation(); \ + \ + CLOCK_CYCLES(3); \ + PREFETCH_RUN(3, 3, rmdat, 0, (cpu_mod == 3) ? 0 : 1, 0, (cpu_mod == 3) ? 0 : 1, 0); \ + return 0; \ + } \ + static int op##operation##_CL_a16(uint32_t fetchdat) \ + { \ + int count; \ + \ + fetch_ea_16(fetchdat); \ + if (cpu_mod != 3) \ + SEG_CHECK_WRITE(cpu_state.ea_seg); \ + count = CL & 31; \ + operation(); \ + \ + CLOCK_CYCLES(3); \ + PREFETCH_RUN(3, 3, rmdat, 0, (cpu_mod == 3) ? 0 : 1, 0, (cpu_mod == 3) ? 0 : 1, 0); \ + return 0; \ + } \ + static int op##operation##_i_a32(uint32_t fetchdat) \ + { \ + int count; \ + \ + fetch_ea_32(fetchdat); \ + if (cpu_mod != 3) \ + SEG_CHECK_WRITE(cpu_state.ea_seg); \ + count = getbyte() & 31; \ + operation(); \ + \ + CLOCK_CYCLES(3); \ + PREFETCH_RUN(3, 3, rmdat, 0, (cpu_mod == 3) ? 0 : 1, 0, (cpu_mod == 3) ? 0 : 1, 1); \ + return 0; \ + } \ + static int op##operation##_CL_a32(uint32_t fetchdat) \ + { \ + int count; \ + \ + fetch_ea_32(fetchdat); \ + if (cpu_mod != 3) \ + SEG_CHECK_WRITE(cpu_state.ea_seg); \ + count = CL & 31; \ + operation(); \ + \ + CLOCK_CYCLES(3); \ + PREFETCH_RUN(3, 3, rmdat, 0, (cpu_mod == 3) ? 0 : 1, 0, (cpu_mod == 3) ? 0 : 1, 1); \ + return 0; \ + } + +// clang-format off opSHxD(SHLD_w) opSHxD(SHLD_l) opSHxD(SHRD_w) opSHxD(SHRD_l) + // clang-format on diff --git a/src/cpu/x86_ops_stack.h b/src/cpu/x86_ops_stack.h index 5bed0b741..13eb883d3 100644 --- a/src/cpu/x86_ops_stack.h +++ b/src/cpu/x86_ops_stack.h @@ -1,38 +1,38 @@ -#define PUSH_W_OP(reg) \ - static int opPUSH_ ## reg (uint32_t fetchdat) \ - { \ - PUSH_W(reg); \ - CLOCK_CYCLES((is486) ? 1 : 2); \ - PREFETCH_RUN(2, 1, -1, 0,0,1,0, 0); \ - return cpu_state.abrt; \ - } +#define PUSH_W_OP(reg) \ + static int opPUSH_##reg(uint32_t fetchdat) \ + { \ + PUSH_W(reg); \ + CLOCK_CYCLES((is486) ? 1 : 2); \ + PREFETCH_RUN(2, 1, -1, 0, 0, 1, 0, 0); \ + return cpu_state.abrt; \ + } -#define PUSH_L_OP(reg) \ - static int opPUSH_ ## reg (uint32_t fetchdat) \ - { \ - PUSH_L(reg); \ - CLOCK_CYCLES((is486) ? 1 : 2); \ - PREFETCH_RUN(2, 1, -1, 0,0,0,1, 0); \ - return cpu_state.abrt; \ - } +#define PUSH_L_OP(reg) \ + static int opPUSH_##reg(uint32_t fetchdat) \ + { \ + PUSH_L(reg); \ + CLOCK_CYCLES((is486) ? 1 : 2); \ + PREFETCH_RUN(2, 1, -1, 0, 0, 0, 1, 0); \ + return cpu_state.abrt; \ + } -#define POP_W_OP(reg) \ - static int opPOP_ ## reg (uint32_t fetchdat) \ - { \ - reg = POP_W(); \ - CLOCK_CYCLES((is486) ? 1 : 4); \ - PREFETCH_RUN(4, 1, -1, 1,0,0,0, 0); \ - return cpu_state.abrt; \ - } +#define POP_W_OP(reg) \ + static int opPOP_##reg(uint32_t fetchdat) \ + { \ + reg = POP_W(); \ + CLOCK_CYCLES((is486) ? 1 : 4); \ + PREFETCH_RUN(4, 1, -1, 1, 0, 0, 0, 0); \ + return cpu_state.abrt; \ + } -#define POP_L_OP(reg) \ - static int opPOP_ ## reg (uint32_t fetchdat) \ - { \ - reg = POP_L(); \ - CLOCK_CYCLES((is486) ? 1 : 4); \ - PREFETCH_RUN(4, 1, -1, 0,1,0,0, 0); \ - return cpu_state.abrt; \ - } +#define POP_L_OP(reg) \ + static int opPOP_##reg(uint32_t fetchdat) \ + { \ + reg = POP_L(); \ + CLOCK_CYCLES((is486) ? 1 : 4); \ + PREFETCH_RUN(4, 1, -1, 0, 1, 0, 0, 0); \ + return cpu_state.abrt; \ + } PUSH_W_OP(AX) PUSH_W_OP(BX) @@ -70,406 +70,568 @@ POP_L_OP(EDI) POP_L_OP(EBP) POP_L_OP(ESP) - -static int opPUSHA_w(uint32_t fetchdat) +static int +opPUSHA_w(uint32_t fetchdat) { - if (stack32) - { - writememw(ss, ESP - 2, AX); - writememw(ss, ESP - 4, CX); - writememw(ss, ESP - 6, DX); - writememw(ss, ESP - 8, BX); - writememw(ss, ESP - 10, SP); - writememw(ss, ESP - 12, BP); - writememw(ss, ESP - 14, SI); - writememw(ss, ESP - 16, DI); - if (!cpu_state.abrt) ESP -= 16; - } - else - { - writememw(ss, ((SP - 2) & 0xFFFF), AX); - writememw(ss, ((SP - 4) & 0xFFFF), CX); - writememw(ss, ((SP - 6) & 0xFFFF), DX); - writememw(ss, ((SP - 8) & 0xFFFF), BX); - writememw(ss, ((SP - 10) & 0xFFFF), SP); - writememw(ss, ((SP - 12) & 0xFFFF), BP); - writememw(ss, ((SP - 14) & 0xFFFF), SI); - writememw(ss, ((SP - 16) & 0xFFFF), DI); - if (!cpu_state.abrt) SP -= 16; - } - CLOCK_CYCLES((is486) ? 11 : 18); - PREFETCH_RUN(18, 1, -1, 0,0,8,0, 0); - return cpu_state.abrt; + if (stack32) { + writememw(ss, ESP - 2, AX); + writememw(ss, ESP - 4, CX); + writememw(ss, ESP - 6, DX); + writememw(ss, ESP - 8, BX); + writememw(ss, ESP - 10, SP); + writememw(ss, ESP - 12, BP); + writememw(ss, ESP - 14, SI); + writememw(ss, ESP - 16, DI); + if (!cpu_state.abrt) + ESP -= 16; + } else { + writememw(ss, ((SP - 2) & 0xFFFF), AX); + writememw(ss, ((SP - 4) & 0xFFFF), CX); + writememw(ss, ((SP - 6) & 0xFFFF), DX); + writememw(ss, ((SP - 8) & 0xFFFF), BX); + writememw(ss, ((SP - 10) & 0xFFFF), SP); + writememw(ss, ((SP - 12) & 0xFFFF), BP); + writememw(ss, ((SP - 14) & 0xFFFF), SI); + writememw(ss, ((SP - 16) & 0xFFFF), DI); + if (!cpu_state.abrt) + SP -= 16; + } + CLOCK_CYCLES((is486) ? 11 : 18); + PREFETCH_RUN(18, 1, -1, 0, 0, 8, 0, 0); + return cpu_state.abrt; } -static int opPUSHA_l(uint32_t fetchdat) +static int +opPUSHA_l(uint32_t fetchdat) { - if (stack32) - { - writememl(ss, ESP - 4, EAX); - writememl(ss, ESP - 8, ECX); - writememl(ss, ESP - 12, EDX); - writememl(ss, ESP - 16, EBX); - writememl(ss, ESP - 20, ESP); - writememl(ss, ESP - 24, EBP); - writememl(ss, ESP - 28, ESI); - writememl(ss, ESP - 32, EDI); - if (!cpu_state.abrt) ESP -= 32; - } - else - { - writememl(ss, ((SP - 4) & 0xFFFF), EAX); - writememl(ss, ((SP - 8) & 0xFFFF), ECX); - writememl(ss, ((SP - 12) & 0xFFFF), EDX); - writememl(ss, ((SP - 16) & 0xFFFF), EBX); - writememl(ss, ((SP - 20) & 0xFFFF), ESP); - writememl(ss, ((SP - 24) & 0xFFFF), EBP); - writememl(ss, ((SP - 28) & 0xFFFF), ESI); - writememl(ss, ((SP - 32) & 0xFFFF), EDI); - if (!cpu_state.abrt) SP -= 32; - } - CLOCK_CYCLES((is486) ? 11 : 18); - PREFETCH_RUN(18, 1, -1, 0,0,0,8, 0); - return cpu_state.abrt; + if (stack32) { + writememl(ss, ESP - 4, EAX); + writememl(ss, ESP - 8, ECX); + writememl(ss, ESP - 12, EDX); + writememl(ss, ESP - 16, EBX); + writememl(ss, ESP - 20, ESP); + writememl(ss, ESP - 24, EBP); + writememl(ss, ESP - 28, ESI); + writememl(ss, ESP - 32, EDI); + if (!cpu_state.abrt) + ESP -= 32; + } else { + writememl(ss, ((SP - 4) & 0xFFFF), EAX); + writememl(ss, ((SP - 8) & 0xFFFF), ECX); + writememl(ss, ((SP - 12) & 0xFFFF), EDX); + writememl(ss, ((SP - 16) & 0xFFFF), EBX); + writememl(ss, ((SP - 20) & 0xFFFF), ESP); + writememl(ss, ((SP - 24) & 0xFFFF), EBP); + writememl(ss, ((SP - 28) & 0xFFFF), ESI); + writememl(ss, ((SP - 32) & 0xFFFF), EDI); + if (!cpu_state.abrt) + SP -= 32; + } + CLOCK_CYCLES((is486) ? 11 : 18); + PREFETCH_RUN(18, 1, -1, 0, 0, 0, 8, 0); + return cpu_state.abrt; } -static int opPOPA_w(uint32_t fetchdat) +static int +opPOPA_w(uint32_t fetchdat) { - if (stack32) - { - DI = readmemw(ss, ESP); if (cpu_state.abrt) return 1; - SI = readmemw(ss, ESP + 2); if (cpu_state.abrt) return 1; - BP = readmemw(ss, ESP + 4); if (cpu_state.abrt) return 1; - BX = readmemw(ss, ESP + 8); if (cpu_state.abrt) return 1; - DX = readmemw(ss, ESP + 10); if (cpu_state.abrt) return 1; - CX = readmemw(ss, ESP + 12); if (cpu_state.abrt) return 1; - AX = readmemw(ss, ESP + 14); if (cpu_state.abrt) return 1; - ESP += 16; - } - else - { - DI = readmemw(ss, ((SP) & 0xFFFF)); if (cpu_state.abrt) return 1; - SI = readmemw(ss, ((SP + 2) & 0xFFFF)); if (cpu_state.abrt) return 1; - BP = readmemw(ss, ((SP + 4) & 0xFFFF)); if (cpu_state.abrt) return 1; - BX = readmemw(ss, ((SP + 8) & 0xFFFF)); if (cpu_state.abrt) return 1; - DX = readmemw(ss, ((SP + 10) & 0xFFFF)); if (cpu_state.abrt) return 1; - CX = readmemw(ss, ((SP + 12) & 0xFFFF)); if (cpu_state.abrt) return 1; - AX = readmemw(ss, ((SP + 14) & 0xFFFF)); if (cpu_state.abrt) return 1; - SP += 16; - } - CLOCK_CYCLES((is486) ? 9 : 24); - PREFETCH_RUN(24, 1, -1, 7,0,0,0, 0); - return 0; -} -static int opPOPA_l(uint32_t fetchdat) -{ - if (stack32) - { - EDI = readmeml(ss, ESP); if (cpu_state.abrt) return 1; - ESI = readmeml(ss, ESP + 4); if (cpu_state.abrt) return 1; - EBP = readmeml(ss, ESP + 8); if (cpu_state.abrt) return 1; - EBX = readmeml(ss, ESP + 16); if (cpu_state.abrt) return 1; - EDX = readmeml(ss, ESP + 20); if (cpu_state.abrt) return 1; - ECX = readmeml(ss, ESP + 24); if (cpu_state.abrt) return 1; - EAX = readmeml(ss, ESP + 28); if (cpu_state.abrt) return 1; - ESP += 32; - } - else - { - EDI = readmeml(ss, ((SP) & 0xFFFF)); if (cpu_state.abrt) return 1; - ESI = readmeml(ss, ((SP + 4) & 0xFFFF)); if (cpu_state.abrt) return 1; - EBP = readmeml(ss, ((SP + 8) & 0xFFFF)); if (cpu_state.abrt) return 1; - EBX = readmeml(ss, ((SP + 16) & 0xFFFF)); if (cpu_state.abrt) return 1; - EDX = readmeml(ss, ((SP + 20) & 0xFFFF)); if (cpu_state.abrt) return 1; - ECX = readmeml(ss, ((SP + 24) & 0xFFFF)); if (cpu_state.abrt) return 1; - EAX = readmeml(ss, ((SP + 28) & 0xFFFF)); if (cpu_state.abrt) return 1; - SP += 32; - } - CLOCK_CYCLES((is486) ? 9 : 24); - PREFETCH_RUN(24, 1, -1, 0,7,0,0, 0); - return 0; -} - -static int opPUSH_imm_w(uint32_t fetchdat) -{ - uint16_t val = getwordf(); - PUSH_W(val); - CLOCK_CYCLES(2); - PREFETCH_RUN(2, 3, -1, 0,0,1,0, 0); - return cpu_state.abrt; -} -static int opPUSH_imm_l(uint32_t fetchdat) -{ - uint32_t val = getlong(); if (cpu_state.abrt) return 1; - PUSH_L(val); - CLOCK_CYCLES(2); - PREFETCH_RUN(2, 3, -1, 0,0,0,1, 0); - return cpu_state.abrt; -} - -static int opPUSH_imm_bw(uint32_t fetchdat) -{ - uint16_t tempw = getbytef(); - - if (tempw & 0x80) tempw |= 0xFF00; - PUSH_W(tempw); - - CLOCK_CYCLES(2); - PREFETCH_RUN(2, 2, -1, 0,0,1,0, 0); - return cpu_state.abrt; -} -static int opPUSH_imm_bl(uint32_t fetchdat) -{ - uint32_t templ = getbytef(); - - if (templ & 0x80) templ |= 0xFFFFFF00; - PUSH_L(templ); - - CLOCK_CYCLES(2); - PREFETCH_RUN(2, 2, -1, 0,0,0,1, 0); - return cpu_state.abrt; -} - -static int opPOPW_a16(uint32_t fetchdat) -{ - uint16_t temp; - - temp = POP_W(); if (cpu_state.abrt) return 1; - - fetch_ea_16(fetchdat); - if (cpu_mod != 3) - SEG_CHECK_WRITE(cpu_state.ea_seg); - seteaw(temp); + if (stack32) { + DI = readmemw(ss, ESP); if (cpu_state.abrt) - { - if (stack32) ESP -= 2; - else SP -= 2; - } - - if (is486) { CLOCK_CYCLES((cpu_mod == 3) ? 1 : 6); } - else { CLOCK_CYCLES((cpu_mod == 3) ? 4 : 5); } - PREFETCH_RUN((cpu_mod == 3) ? 4 : 5, 2, rmdat, 1,0,(cpu_mod == 3) ? 0:1,0, 0); - return cpu_state.abrt; -} -static int opPOPW_a32(uint32_t fetchdat) -{ - uint16_t temp; - - temp = POP_W(); if (cpu_state.abrt) return 1; - - fetch_ea_32(fetchdat); - if (cpu_mod != 3) - SEG_CHECK_WRITE(cpu_state.ea_seg); - seteaw(temp); + return 1; + SI = readmemw(ss, ESP + 2); if (cpu_state.abrt) - { - if (stack32) ESP -= 2; - else SP -= 2; - } - - if (is486) { CLOCK_CYCLES((cpu_mod == 3) ? 1 : 6); } - else { CLOCK_CYCLES((cpu_mod == 3) ? 4 : 5); } - PREFETCH_RUN((cpu_mod == 3) ? 4 : 5, 2, rmdat, 1,0,(cpu_mod == 3) ? 0:1,0, 1); - return cpu_state.abrt; -} - -static int opPOPL_a16(uint32_t fetchdat) -{ - uint32_t temp; - - temp = POP_L(); if (cpu_state.abrt) return 1; - - fetch_ea_16(fetchdat); - if (cpu_mod != 3) - SEG_CHECK_WRITE(cpu_state.ea_seg); - seteal(temp); + return 1; + BP = readmemw(ss, ESP + 4); if (cpu_state.abrt) - { - if (stack32) ESP -= 4; - else SP -= 4; - } - - if (is486) { CLOCK_CYCLES((cpu_mod == 3) ? 1 : 6); } - else { CLOCK_CYCLES((cpu_mod == 3) ? 4 : 5); } - PREFETCH_RUN((cpu_mod == 3) ? 4 : 5, 2, rmdat, 0,1,0,(cpu_mod == 3) ? 0:1, 0); - return cpu_state.abrt; -} -static int opPOPL_a32(uint32_t fetchdat) -{ - uint32_t temp; - - temp = POP_L(); if (cpu_state.abrt) return 1; - - fetch_ea_32(fetchdat); - if (cpu_mod != 3) - SEG_CHECK_WRITE(cpu_state.ea_seg); - seteal(temp); + return 1; + BX = readmemw(ss, ESP + 8); if (cpu_state.abrt) - { - if (stack32) ESP -= 4; - else SP -= 4; - } - - if (is486) { CLOCK_CYCLES((cpu_mod == 3) ? 1 : 6); } - else { CLOCK_CYCLES((cpu_mod == 3) ? 4 : 5); } - PREFETCH_RUN((cpu_mod == 3) ? 4 : 5, 2, rmdat, 0,1,0,(cpu_mod == 3) ? 0:1, 1); - return cpu_state.abrt; + return 1; + DX = readmemw(ss, ESP + 10); + if (cpu_state.abrt) + return 1; + CX = readmemw(ss, ESP + 12); + if (cpu_state.abrt) + return 1; + AX = readmemw(ss, ESP + 14); + if (cpu_state.abrt) + return 1; + ESP += 16; + } else { + DI = readmemw(ss, ((SP) &0xFFFF)); + if (cpu_state.abrt) + return 1; + SI = readmemw(ss, ((SP + 2) & 0xFFFF)); + if (cpu_state.abrt) + return 1; + BP = readmemw(ss, ((SP + 4) & 0xFFFF)); + if (cpu_state.abrt) + return 1; + BX = readmemw(ss, ((SP + 8) & 0xFFFF)); + if (cpu_state.abrt) + return 1; + DX = readmemw(ss, ((SP + 10) & 0xFFFF)); + if (cpu_state.abrt) + return 1; + CX = readmemw(ss, ((SP + 12) & 0xFFFF)); + if (cpu_state.abrt) + return 1; + AX = readmemw(ss, ((SP + 14) & 0xFFFF)); + if (cpu_state.abrt) + return 1; + SP += 16; + } + CLOCK_CYCLES((is486) ? 9 : 24); + PREFETCH_RUN(24, 1, -1, 7, 0, 0, 0, 0); + return 0; } - - -static int opENTER_w(uint32_t fetchdat) +static int +opPOPA_l(uint32_t fetchdat) { - uint16_t offset; - int count; - uint32_t tempEBP, tempESP, frame_ptr; - int reads = 0, writes = 1, instr_cycles = 0; - uint16_t tempw; - - offset = getwordf(); - count = (fetchdat >> 16) & 0xff; cpu_state.pc++; - tempEBP = EBP; - tempESP = ESP; - - PUSH_W(BP); if (cpu_state.abrt) return 1; - frame_ptr = ESP; - - if (count > 0) - { - while (--count) - { - BP -= 2; - tempw = readmemw(ss, BP); - if (cpu_state.abrt) { ESP = tempESP; EBP = tempEBP; return 1; } - PUSH_W(tempw); - if (cpu_state.abrt) { ESP = tempESP; EBP = tempEBP; return 1; } - CLOCK_CYCLES((is486) ? 3 : 4); - reads++; writes++; instr_cycles += (is486) ? 3 : 4; - } - PUSH_W(frame_ptr); - if (cpu_state.abrt) { ESP = tempESP; EBP = tempEBP; return 1; } - CLOCK_CYCLES((is486) ? 3 : 5); - writes++; instr_cycles += (is486) ? 3 : 5; - } - BP = frame_ptr; - - if (stack32) ESP -= offset; - else SP -= offset; - CLOCK_CYCLES((is486) ? 14 : 10); - instr_cycles += (is486) ? 14 : 10; - PREFETCH_RUN(instr_cycles, 3, -1, reads,0,writes,0, 0); - return 0; + if (stack32) { + EDI = readmeml(ss, ESP); + if (cpu_state.abrt) + return 1; + ESI = readmeml(ss, ESP + 4); + if (cpu_state.abrt) + return 1; + EBP = readmeml(ss, ESP + 8); + if (cpu_state.abrt) + return 1; + EBX = readmeml(ss, ESP + 16); + if (cpu_state.abrt) + return 1; + EDX = readmeml(ss, ESP + 20); + if (cpu_state.abrt) + return 1; + ECX = readmeml(ss, ESP + 24); + if (cpu_state.abrt) + return 1; + EAX = readmeml(ss, ESP + 28); + if (cpu_state.abrt) + return 1; + ESP += 32; + } else { + EDI = readmeml(ss, ((SP) &0xFFFF)); + if (cpu_state.abrt) + return 1; + ESI = readmeml(ss, ((SP + 4) & 0xFFFF)); + if (cpu_state.abrt) + return 1; + EBP = readmeml(ss, ((SP + 8) & 0xFFFF)); + if (cpu_state.abrt) + return 1; + EBX = readmeml(ss, ((SP + 16) & 0xFFFF)); + if (cpu_state.abrt) + return 1; + EDX = readmeml(ss, ((SP + 20) & 0xFFFF)); + if (cpu_state.abrt) + return 1; + ECX = readmeml(ss, ((SP + 24) & 0xFFFF)); + if (cpu_state.abrt) + return 1; + EAX = readmeml(ss, ((SP + 28) & 0xFFFF)); + if (cpu_state.abrt) + return 1; + SP += 32; + } + CLOCK_CYCLES((is486) ? 9 : 24); + PREFETCH_RUN(24, 1, -1, 0, 7, 0, 0, 0); + return 0; } -static int opENTER_l(uint32_t fetchdat) + +static int +opPUSH_imm_w(uint32_t fetchdat) { - uint16_t offset; - int count; - uint32_t tempEBP, tempESP, frame_ptr; - int reads = 0, writes = 1, instr_cycles = 0; - uint32_t templ; - - offset = getwordf(); - count = (fetchdat >> 16) & 0xff; cpu_state.pc++; - tempEBP = EBP; tempESP = ESP; - - PUSH_L(EBP); if (cpu_state.abrt) return 1; - frame_ptr = ESP; - - if (count > 0) - { - while (--count) - { - EBP -= 4; - templ = readmeml(ss, EBP); - if (cpu_state.abrt) { ESP = tempESP; EBP = tempEBP; return 1; } - PUSH_L(templ); - if (cpu_state.abrt) { ESP = tempESP; EBP = tempEBP; return 1; } - CLOCK_CYCLES((is486) ? 3 : 4); - reads++; writes++; instr_cycles += (is486) ? 3 : 4; - } - PUSH_L(frame_ptr); - if (cpu_state.abrt) { ESP = tempESP; EBP = tempEBP; return 1; } - CLOCK_CYCLES((is486) ? 3 : 5); - writes++; instr_cycles += (is486) ? 3 : 5; - } - EBP = frame_ptr; - - if (stack32) ESP -= offset; - else SP -= offset; - CLOCK_CYCLES((is486) ? 14 : 10); - instr_cycles += (is486) ? 14 : 10; - PREFETCH_RUN(instr_cycles, 3, -1, reads,0,writes,0, 0); - return 0; + uint16_t val = getwordf(); + PUSH_W(val); + CLOCK_CYCLES(2); + PREFETCH_RUN(2, 3, -1, 0, 0, 1, 0, 0); + return cpu_state.abrt; } - - -static int opLEAVE_w(uint32_t fetchdat) +static int +opPUSH_imm_l(uint32_t fetchdat) { - uint32_t tempESP = ESP; - uint16_t temp; - - SP = BP; - temp = POP_W(); - if (cpu_state.abrt) { ESP = tempESP; return 1; } - BP = temp; - - CLOCK_CYCLES(4); - PREFETCH_RUN(4, 1, -1, 1,0,0,0, 0); - return 0; + uint32_t val = getlong(); + if (cpu_state.abrt) + return 1; + PUSH_L(val); + CLOCK_CYCLES(2); + PREFETCH_RUN(2, 3, -1, 0, 0, 0, 1, 0); + return cpu_state.abrt; } -static int opLEAVE_l(uint32_t fetchdat) + +static int +opPUSH_imm_bw(uint32_t fetchdat) { - uint32_t tempESP = ESP; - uint32_t temp; + uint16_t tempw = getbytef(); - ESP = EBP; - temp = POP_L(); - if (cpu_state.abrt) { ESP = tempESP; return 1; } - EBP = temp; - - CLOCK_CYCLES(4); - PREFETCH_RUN(4, 1, -1, 0,1,0,0, 0); - return 0; + if (tempw & 0x80) + tempw |= 0xFF00; + PUSH_W(tempw); + + CLOCK_CYCLES(2); + PREFETCH_RUN(2, 2, -1, 0, 0, 1, 0, 0); + return cpu_state.abrt; +} +static int +opPUSH_imm_bl(uint32_t fetchdat) +{ + uint32_t templ = getbytef(); + + if (templ & 0x80) + templ |= 0xFFFFFF00; + PUSH_L(templ); + + CLOCK_CYCLES(2); + PREFETCH_RUN(2, 2, -1, 0, 0, 0, 1, 0); + return cpu_state.abrt; } +static int +opPOPW_a16(uint32_t fetchdat) +{ + uint16_t temp; -#define PUSH_SEG_OPS(seg) \ - static int opPUSH_ ## seg ## _w(uint32_t fetchdat) \ - { \ - PUSH_W(seg); \ - CLOCK_CYCLES(2); \ - PREFETCH_RUN(2, 1, -1, 0,0,1,0, 0); \ - return cpu_state.abrt; \ - } \ - static int opPUSH_ ## seg ## _l(uint32_t fetchdat) \ - { \ - PUSH_L(seg); \ - CLOCK_CYCLES(2); \ - PREFETCH_RUN(2, 1, -1, 0,0,0,1, 0); \ - return cpu_state.abrt; \ - } - -#define POP_SEG_OPS(seg, realseg) \ - static int opPOP_ ## seg ## _w(uint32_t fetchdat) \ - { \ - uint16_t temp_seg; \ - uint32_t temp_esp = ESP; \ - temp_seg = POP_W(); if (cpu_state.abrt) return 1; \ - loadseg(temp_seg, realseg); if (cpu_state.abrt) ESP = temp_esp; \ - CLOCK_CYCLES(is486 ? 3 : 7); \ - PREFETCH_RUN(is486 ? 3 : 7, 1, -1, 0,0,1,0, 0); \ - return cpu_state.abrt; \ - } \ - static int opPOP_ ## seg ## _l(uint32_t fetchdat) \ - { \ - uint32_t temp_seg; \ - uint32_t temp_esp = ESP; \ - temp_seg = POP_L(); if (cpu_state.abrt) return 1; \ - loadseg(temp_seg & 0xffff, realseg); if (cpu_state.abrt) ESP = temp_esp; \ - CLOCK_CYCLES(is486 ? 3 : 7); \ - PREFETCH_RUN(is486 ? 3 : 7, 1, -1, 0,0,1,0, 0); \ - return cpu_state.abrt; \ - } + temp = POP_W(); + if (cpu_state.abrt) + return 1; + + fetch_ea_16(fetchdat); + if (cpu_mod != 3) + SEG_CHECK_WRITE(cpu_state.ea_seg); + seteaw(temp); + if (cpu_state.abrt) { + if (stack32) + ESP -= 2; + else + SP -= 2; + } + + if (is486) { + CLOCK_CYCLES((cpu_mod == 3) ? 1 : 6); + } else { + CLOCK_CYCLES((cpu_mod == 3) ? 4 : 5); + } + PREFETCH_RUN((cpu_mod == 3) ? 4 : 5, 2, rmdat, 1, 0, (cpu_mod == 3) ? 0 : 1, 0, 0); + return cpu_state.abrt; +} +static int +opPOPW_a32(uint32_t fetchdat) +{ + uint16_t temp; + + temp = POP_W(); + if (cpu_state.abrt) + return 1; + + fetch_ea_32(fetchdat); + if (cpu_mod != 3) + SEG_CHECK_WRITE(cpu_state.ea_seg); + seteaw(temp); + if (cpu_state.abrt) { + if (stack32) + ESP -= 2; + else + SP -= 2; + } + + if (is486) { + CLOCK_CYCLES((cpu_mod == 3) ? 1 : 6); + } else { + CLOCK_CYCLES((cpu_mod == 3) ? 4 : 5); + } + PREFETCH_RUN((cpu_mod == 3) ? 4 : 5, 2, rmdat, 1, 0, (cpu_mod == 3) ? 0 : 1, 0, 1); + return cpu_state.abrt; +} + +static int +opPOPL_a16(uint32_t fetchdat) +{ + uint32_t temp; + + temp = POP_L(); + if (cpu_state.abrt) + return 1; + + fetch_ea_16(fetchdat); + if (cpu_mod != 3) + SEG_CHECK_WRITE(cpu_state.ea_seg); + seteal(temp); + if (cpu_state.abrt) { + if (stack32) + ESP -= 4; + else + SP -= 4; + } + + if (is486) { + CLOCK_CYCLES((cpu_mod == 3) ? 1 : 6); + } else { + CLOCK_CYCLES((cpu_mod == 3) ? 4 : 5); + } + PREFETCH_RUN((cpu_mod == 3) ? 4 : 5, 2, rmdat, 0, 1, 0, (cpu_mod == 3) ? 0 : 1, 0); + return cpu_state.abrt; +} +static int +opPOPL_a32(uint32_t fetchdat) +{ + uint32_t temp; + + temp = POP_L(); + if (cpu_state.abrt) + return 1; + + fetch_ea_32(fetchdat); + if (cpu_mod != 3) + SEG_CHECK_WRITE(cpu_state.ea_seg); + seteal(temp); + if (cpu_state.abrt) { + if (stack32) + ESP -= 4; + else + SP -= 4; + } + + if (is486) { + CLOCK_CYCLES((cpu_mod == 3) ? 1 : 6); + } else { + CLOCK_CYCLES((cpu_mod == 3) ? 4 : 5); + } + PREFETCH_RUN((cpu_mod == 3) ? 4 : 5, 2, rmdat, 0, 1, 0, (cpu_mod == 3) ? 0 : 1, 1); + return cpu_state.abrt; +} + +static int +opENTER_w(uint32_t fetchdat) +{ + uint16_t offset; + int count; + uint32_t tempEBP; + uint32_t tempESP; + uint32_t frame_ptr; +#ifndef IS_DYNAREC + int reads = 0; + int writes = 1; + int instr_cycles = 0; +#endif + uint16_t tempw; + + offset = getwordf(); + count = (fetchdat >> 16) & 0xff; + cpu_state.pc++; + tempEBP = EBP; + tempESP = ESP; + + PUSH_W(BP); + if (cpu_state.abrt) + return 1; + frame_ptr = ESP; + + if (count > 0) { + while (--count) { + BP -= 2; + tempw = readmemw(ss, BP); + if (cpu_state.abrt) { + ESP = tempESP; + EBP = tempEBP; + return 1; + } + PUSH_W(tempw); + if (cpu_state.abrt) { + ESP = tempESP; + EBP = tempEBP; + return 1; + } + CLOCK_CYCLES((is486) ? 3 : 4); +#ifndef IS_DYNAREC + reads++; + writes++; + instr_cycles += (is486) ? 3 : 4; +#endif + } + PUSH_W(frame_ptr); + if (cpu_state.abrt) { + ESP = tempESP; + EBP = tempEBP; + return 1; + } + CLOCK_CYCLES((is486) ? 3 : 5); +#ifndef IS_DYNAREC + writes++; + instr_cycles += (is486) ? 3 : 5; +#endif + } + BP = frame_ptr; + + if (stack32) + ESP -= offset; + else + SP -= offset; + CLOCK_CYCLES((is486) ? 14 : 10); +#ifndef IS_DYNAREC + instr_cycles += (is486) ? 14 : 10; + PREFETCH_RUN(instr_cycles, 3, -1, reads, 0, writes, 0, 0); +#endif + return 0; +} +static int +opENTER_l(uint32_t fetchdat) +{ + uint16_t offset; + int count; + uint32_t tempEBP; + uint32_t tempESP; + uint32_t frame_ptr; +#ifndef IS_DYNAREC + int reads = 0; + int writes = 1; + int instr_cycles = 0; +#endif + uint32_t templ; + + offset = getwordf(); + count = (fetchdat >> 16) & 0xff; + cpu_state.pc++; + tempEBP = EBP; + tempESP = ESP; + + PUSH_L(EBP); + if (cpu_state.abrt) + return 1; + frame_ptr = ESP; + + if (count > 0) { + while (--count) { + EBP -= 4; + templ = readmeml(ss, EBP); + if (cpu_state.abrt) { + ESP = tempESP; + EBP = tempEBP; + return 1; + } + PUSH_L(templ); + if (cpu_state.abrt) { + ESP = tempESP; + EBP = tempEBP; + return 1; + } + CLOCK_CYCLES((is486) ? 3 : 4); +#ifndef IS_DYNAREC + reads++; + writes++; + instr_cycles += (is486) ? 3 : 4; +#endif + } + PUSH_L(frame_ptr); + if (cpu_state.abrt) { + ESP = tempESP; + EBP = tempEBP; + return 1; + } + CLOCK_CYCLES((is486) ? 3 : 5); +#ifndef IS_DYNAREC + writes++; + instr_cycles += (is486) ? 3 : 5; +#endif + } + EBP = frame_ptr; + + if (stack32) + ESP -= offset; + else + SP -= offset; + CLOCK_CYCLES((is486) ? 14 : 10); +#ifndef IS_DYNAREC + instr_cycles += (is486) ? 14 : 10; + PREFETCH_RUN(instr_cycles, 3, -1, reads, 0, writes, 0, 0); +#endif + return 0; +} + +static int +opLEAVE_w(uint32_t fetchdat) +{ + uint32_t tempESP = ESP; + uint16_t temp; + + SP = BP; + temp = POP_W(); + if (cpu_state.abrt) { + ESP = tempESP; + return 1; + } + BP = temp; + + CLOCK_CYCLES(4); + PREFETCH_RUN(4, 1, -1, 1, 0, 0, 0, 0); + return 0; +} +static int +opLEAVE_l(uint32_t fetchdat) +{ + uint32_t tempESP = ESP; + uint32_t temp; + + ESP = EBP; + temp = POP_L(); + if (cpu_state.abrt) { + ESP = tempESP; + return 1; + } + EBP = temp; + + CLOCK_CYCLES(4); + PREFETCH_RUN(4, 1, -1, 0, 1, 0, 0, 0); + return 0; +} + +#define PUSH_SEG_OPS(seg) \ + static int opPUSH_##seg##_w(uint32_t fetchdat) \ + { \ + PUSH_W(seg); \ + CLOCK_CYCLES(2); \ + PREFETCH_RUN(2, 1, -1, 0, 0, 1, 0, 0); \ + return cpu_state.abrt; \ + } \ + static int opPUSH_##seg##_l(uint32_t fetchdat) \ + { \ + PUSH_L(seg); \ + CLOCK_CYCLES(2); \ + PREFETCH_RUN(2, 1, -1, 0, 0, 0, 1, 0); \ + return cpu_state.abrt; \ + } + +#define POP_SEG_OPS(seg, realseg) \ + static int opPOP_##seg##_w(uint32_t fetchdat) \ + { \ + uint16_t temp_seg; \ + uint32_t temp_esp = ESP; \ + temp_seg = POP_W(); \ + if (cpu_state.abrt) \ + return 1; \ + op_loadseg(temp_seg, realseg); \ + if (cpu_state.abrt) \ + ESP = temp_esp; \ + CLOCK_CYCLES(is486 ? 3 : 7); \ + PREFETCH_RUN(is486 ? 3 : 7, 1, -1, 0, 0, 1, 0, 0); \ + return cpu_state.abrt; \ + } \ + static int opPOP_##seg##_l(uint32_t fetchdat) \ + { \ + uint32_t temp_seg; \ + uint32_t temp_esp = ESP; \ + temp_seg = POP_L(); \ + if (cpu_state.abrt) \ + return 1; \ + op_loadseg(temp_seg & 0xffff, realseg); \ + if (cpu_state.abrt) \ + ESP = temp_esp; \ + CLOCK_CYCLES(is486 ? 3 : 7); \ + PREFETCH_RUN(is486 ? 3 : 7, 1, -1, 0, 0, 1, 0, 0); \ + return cpu_state.abrt; \ + } - PUSH_SEG_OPS(CS) PUSH_SEG_OPS(DS) PUSH_SEG_OPS(ES) @@ -481,44 +643,59 @@ POP_SEG_OPS(ES, &cpu_state.seg_es) POP_SEG_OPS(FS, &cpu_state.seg_fs) POP_SEG_OPS(GS, &cpu_state.seg_gs) - -static int opPOP_SS_w(uint32_t fetchdat) +static int +opPOP_SS_w(uint32_t fetchdat) { - uint16_t temp_seg; - uint32_t temp_esp = ESP; - temp_seg = POP_W(); if (cpu_state.abrt) return 1; - loadseg(temp_seg, &cpu_state.seg_ss); if (cpu_state.abrt) { ESP = temp_esp; return 1; } - CLOCK_CYCLES(is486 ? 3 : 7); - PREFETCH_RUN(is486 ? 3 : 7, 1, -1, 0,0,1,0, 0); - - cpu_state.oldpc = cpu_state.pc; - cpu_state.op32 = use32; - cpu_state.ssegs = 0; - cpu_state.ea_seg = &cpu_state.seg_ds; - fetchdat = fastreadl(cs + cpu_state.pc); - cpu_state.pc++; - if (cpu_state.abrt) return 1; - x86_opcodes[(fetchdat & 0xff) | cpu_state.op32](fetchdat >> 8); - + uint16_t temp_seg; + uint32_t temp_esp = ESP; + temp_seg = POP_W(); + if (cpu_state.abrt) return 1; + op_loadseg(temp_seg, &cpu_state.seg_ss); + if (cpu_state.abrt) { + ESP = temp_esp; + return 1; + } + CLOCK_CYCLES(is486 ? 3 : 7); + PREFETCH_RUN(is486 ? 3 : 7, 1, -1, 0, 0, 1, 0, 0); + + cpu_state.oldpc = cpu_state.pc; + cpu_state.op32 = use32; + cpu_state.ssegs = 0; + cpu_state.ea_seg = &cpu_state.seg_ds; + fetchdat = fastreadl(cs + cpu_state.pc); + cpu_state.pc++; + if (cpu_state.abrt) + return 1; + x86_opcodes[(fetchdat & 0xff) | cpu_state.op32](fetchdat >> 8); + + return 1; } -static int opPOP_SS_l(uint32_t fetchdat) +static int +opPOP_SS_l(uint32_t fetchdat) { - uint32_t temp_seg; - uint32_t temp_esp = ESP; - temp_seg = POP_L(); if (cpu_state.abrt) return 1; - loadseg(temp_seg & 0xffff, &cpu_state.seg_ss); if (cpu_state.abrt) { ESP = temp_esp; return 1; } - CLOCK_CYCLES(is486 ? 3 : 7); - PREFETCH_RUN(is486 ? 3 : 7, 1, -1, 0,0,1,0, 0); - - cpu_state.oldpc = cpu_state.pc; - cpu_state.op32 = use32; - cpu_state.ssegs = 0; - cpu_state.ea_seg = &cpu_state.seg_ds; - fetchdat = fastreadl(cs + cpu_state.pc); - cpu_state.pc++; - if (cpu_state.abrt) return 1; - x86_opcodes[(fetchdat & 0xff) | cpu_state.op32](fetchdat >> 8); - + uint32_t temp_seg; + uint32_t temp_esp = ESP; + temp_seg = POP_L(); + if (cpu_state.abrt) return 1; + op_loadseg(temp_seg & 0xffff, &cpu_state.seg_ss); + if (cpu_state.abrt) { + ESP = temp_esp; + return 1; + } + CLOCK_CYCLES(is486 ? 3 : 7); + PREFETCH_RUN(is486 ? 3 : 7, 1, -1, 0, 0, 1, 0, 0); + + cpu_state.oldpc = cpu_state.pc; + cpu_state.op32 = use32; + cpu_state.ssegs = 0; + cpu_state.ea_seg = &cpu_state.seg_ds; + fetchdat = fastreadl(cs + cpu_state.pc); + cpu_state.pc++; + if (cpu_state.abrt) + return 1; + x86_opcodes[(fetchdat & 0xff) | cpu_state.op32](fetchdat >> 8); + + return 1; } diff --git a/src/cpu/x86_ops_string.h b/src/cpu/x86_ops_string.h index 54a22d4b8..619386fcb 100644 --- a/src/cpu/x86_ops_string.h +++ b/src/cpu/x86_ops_string.h @@ -1,792 +1,1085 @@ -static int opMOVSB_a16(uint32_t fetchdat) +static int +opMOVSB_a16(uint32_t fetchdat) { - uint8_t temp; + uint8_t temp; - addr64 = addr64_2 = 0x00000000; + addr64 = addr64_2 = 0x00000000; - SEG_CHECK_READ(cpu_state.ea_seg); - CHECK_READ(cpu_state.ea_seg, SI, SI); - high_page = 0; - do_mmut_rb(cpu_state.ea_seg->base, SI, &addr64); - if (cpu_state.abrt) return 1; - SEG_CHECK_WRITE(&cpu_state.seg_es); - CHECK_WRITE(&cpu_state.seg_es, DI, DI); + SEG_CHECK_READ(cpu_state.ea_seg); + SEG_CHECK_WRITE(&cpu_state.seg_es); + CHECK_READ(cpu_state.ea_seg, SI, SI); + CHECK_WRITE(&cpu_state.seg_es, DI, DI); + high_page = 0; + do_mmut_rb(cpu_state.ea_seg->base, SI, &addr64); + if (cpu_state.abrt) + return 1; - do_mmut_wb(es, DI, &addr64_2); - if (cpu_state.abrt) return 1; - temp = readmemb_n(cpu_state.ea_seg->base, SI, addr64); if (cpu_state.abrt) return 1; - writememb_n(es, DI, addr64_2, temp); if (cpu_state.abrt) return 1; - if (cpu_state.flags & D_FLAG) { DI--; SI--; } - else { DI++; SI++; } - CLOCK_CYCLES(7); - PREFETCH_RUN(7, 1, -1, 1,0,1,0, 0); - return 0; + do_mmut_wb(es, DI, &addr64_2); + if (cpu_state.abrt) + return 1; + temp = readmemb_n(cpu_state.ea_seg->base, SI, addr64); + if (cpu_state.abrt) + return 1; + writememb_n(es, DI, addr64_2, temp); + if (cpu_state.abrt) + return 1; + if (cpu_state.flags & D_FLAG) { + DI--; + SI--; + } else { + DI++; + SI++; + } + CLOCK_CYCLES(7); + PREFETCH_RUN(7, 1, -1, 1, 0, 1, 0, 0); + return 0; } -static int opMOVSB_a32(uint32_t fetchdat) +static int +opMOVSB_a32(uint32_t fetchdat) { - uint8_t temp; + uint8_t temp; - addr64 = addr64_2 = 0x00000000; + addr64 = addr64_2 = 0x00000000; - SEG_CHECK_READ(cpu_state.ea_seg); - CHECK_READ(cpu_state.ea_seg, ESI, ESI); - high_page = 0; - do_mmut_rb(cpu_state.ea_seg->base, ESI, &addr64); - if (cpu_state.abrt) return 1; - SEG_CHECK_WRITE(&cpu_state.seg_es); - CHECK_WRITE(&cpu_state.seg_es, EDI, EDI); - do_mmut_wb(es, EDI, &addr64_2); - if (cpu_state.abrt) return 1; - temp = readmemb_n(cpu_state.ea_seg->base, ESI, addr64); if (cpu_state.abrt) return 1; - writememb_n(es, EDI, addr64_2, temp); if (cpu_state.abrt) return 1; - if (cpu_state.flags & D_FLAG) { EDI--; ESI--; } - else { EDI++; ESI++; } - CLOCK_CYCLES(7); - PREFETCH_RUN(7, 1, -1, 1,0,1,0, 1); - return 0; + SEG_CHECK_READ(cpu_state.ea_seg); + SEG_CHECK_WRITE(&cpu_state.seg_es); + CHECK_READ(cpu_state.ea_seg, ESI, ESI); + CHECK_WRITE(&cpu_state.seg_es, EDI, EDI); + high_page = 0; + do_mmut_rb(cpu_state.ea_seg->base, ESI, &addr64); + if (cpu_state.abrt) + return 1; + do_mmut_wb(es, EDI, &addr64_2); + if (cpu_state.abrt) + return 1; + temp = readmemb_n(cpu_state.ea_seg->base, ESI, addr64); + if (cpu_state.abrt) + return 1; + writememb_n(es, EDI, addr64_2, temp); + if (cpu_state.abrt) + return 1; + if (cpu_state.flags & D_FLAG) { + EDI--; + ESI--; + } else { + EDI++; + ESI++; + } + CLOCK_CYCLES(7); + PREFETCH_RUN(7, 1, -1, 1, 0, 1, 0, 1); + return 0; } -static int opMOVSW_a16(uint32_t fetchdat) +static int +opMOVSW_a16(uint32_t fetchdat) { - uint16_t temp; + uint16_t temp; - addr64a[0] = addr64a[1] = 0x00000000; - addr64a_2[0] = addr64a_2[1] = 0x00000000; + addr64a[0] = addr64a[1] = 0x00000000; + addr64a_2[0] = addr64a_2[1] = 0x00000000; - SEG_CHECK_READ(cpu_state.ea_seg); - CHECK_READ(cpu_state.ea_seg, SI, SI + 1UL); - high_page = 0; - do_mmut_rw(cpu_state.ea_seg->base, SI, addr64a); - if (cpu_state.abrt) return 1; - SEG_CHECK_WRITE(&cpu_state.seg_es); - CHECK_WRITE(&cpu_state.seg_es, DI, DI + 1UL); - do_mmut_ww(es, DI, addr64a_2); - if (cpu_state.abrt) return 1; - temp = readmemw_n(cpu_state.ea_seg->base, SI, addr64a); if (cpu_state.abrt) return 1; - writememw_n(es, DI, addr64a_2, temp); if (cpu_state.abrt) return 1; - if (cpu_state.flags & D_FLAG) { DI -= 2; SI -= 2; } - else { DI += 2; SI += 2; } - CLOCK_CYCLES(7); - PREFETCH_RUN(7, 1, -1, 1,0,1,0, 0); - return 0; + SEG_CHECK_READ(cpu_state.ea_seg); + SEG_CHECK_WRITE(&cpu_state.seg_es); + CHECK_READ(cpu_state.ea_seg, SI, SI + 1UL); + CHECK_WRITE(&cpu_state.seg_es, DI, DI + 1UL); + high_page = 0; + do_mmut_rw(cpu_state.ea_seg->base, SI, addr64a); + if (cpu_state.abrt) + return 1; + do_mmut_ww(es, DI, addr64a_2); + if (cpu_state.abrt) + return 1; + temp = readmemw_n(cpu_state.ea_seg->base, SI, addr64a); + if (cpu_state.abrt) + return 1; + writememw_n(es, DI, addr64a_2, temp); + if (cpu_state.abrt) + return 1; + if (cpu_state.flags & D_FLAG) { + DI -= 2; + SI -= 2; + } else { + DI += 2; + SI += 2; + } + CLOCK_CYCLES(7); + PREFETCH_RUN(7, 1, -1, 1, 0, 1, 0, 0); + return 0; } -static int opMOVSW_a32(uint32_t fetchdat) +static int +opMOVSW_a32(uint32_t fetchdat) { - uint16_t temp; + uint16_t temp; - addr64a[0] = addr64a[1] = 0x00000000; - addr64a_2[0] = addr64a_2[1] = 0x00000000; + addr64a[0] = addr64a[1] = 0x00000000; + addr64a_2[0] = addr64a_2[1] = 0x00000000; - SEG_CHECK_READ(cpu_state.ea_seg); - CHECK_READ(cpu_state.ea_seg, ESI, ESI + 1UL); - high_page = 0; - do_mmut_rw(cpu_state.ea_seg->base, ESI, addr64a); - if (cpu_state.abrt) return 1; - SEG_CHECK_WRITE(&cpu_state.seg_es); - CHECK_WRITE(&cpu_state.seg_es, EDI, EDI + 1UL); - do_mmut_ww(es, EDI, addr64a_2); - if (cpu_state.abrt) return 1; - temp = readmemw_n(cpu_state.ea_seg->base, ESI, addr64a); if (cpu_state.abrt) return 1; - writememw_n(es, EDI, addr64a_2, temp); if (cpu_state.abrt) return 1; - if (cpu_state.flags & D_FLAG) { EDI -= 2; ESI -= 2; } - else { EDI += 2; ESI += 2; } - CLOCK_CYCLES(7); - PREFETCH_RUN(7, 1, -1, 1,0,1,0, 1); - return 0; + SEG_CHECK_READ(cpu_state.ea_seg); + SEG_CHECK_WRITE(&cpu_state.seg_es); + CHECK_READ(cpu_state.ea_seg, ESI, ESI + 1UL); + CHECK_WRITE(&cpu_state.seg_es, EDI, EDI + 1UL); + high_page = 0; + do_mmut_rw(cpu_state.ea_seg->base, ESI, addr64a); + if (cpu_state.abrt) + return 1; + do_mmut_ww(es, EDI, addr64a_2); + if (cpu_state.abrt) + return 1; + temp = readmemw_n(cpu_state.ea_seg->base, ESI, addr64a); + if (cpu_state.abrt) + return 1; + writememw_n(es, EDI, addr64a_2, temp); + if (cpu_state.abrt) + return 1; + if (cpu_state.flags & D_FLAG) { + EDI -= 2; + ESI -= 2; + } else { + EDI += 2; + ESI += 2; + } + CLOCK_CYCLES(7); + PREFETCH_RUN(7, 1, -1, 1, 0, 1, 0, 1); + return 0; } -static int opMOVSL_a16(uint32_t fetchdat) +static int +opMOVSL_a16(uint32_t fetchdat) { - uint32_t temp; + uint32_t temp; - addr64a[0] = addr64a[1] = addr64a[2] = addr64a[3] = 0x00000000; - addr64a_2[0] = addr64a_2[1] = addr64a_2[2] = addr64a_2[3] = 0x00000000; + addr64a[0] = addr64a[1] = addr64a[2] = addr64a[3] = 0x00000000; + addr64a_2[0] = addr64a_2[1] = addr64a_2[2] = addr64a_2[3] = 0x00000000; - SEG_CHECK_READ(cpu_state.ea_seg); - CHECK_READ(cpu_state.ea_seg, SI, SI + 3UL); - high_page = 0; - do_mmut_rl(cpu_state.ea_seg->base, SI, addr64a); - if (cpu_state.abrt) return 1; - SEG_CHECK_WRITE(&cpu_state.seg_es); - CHECK_WRITE(&cpu_state.seg_es, DI, DI + 3UL); - do_mmut_wl(es, DI, addr64a_2); - if (cpu_state.abrt) return 1; - temp = readmeml_n(cpu_state.ea_seg->base, SI, addr64a); if (cpu_state.abrt) return 1; - writememl_n(es, DI, addr64a_2, temp); if (cpu_state.abrt) return 1; - if (cpu_state.flags & D_FLAG) { DI -= 4; SI -= 4; } - else { DI += 4; SI += 4; } - CLOCK_CYCLES(7); - PREFETCH_RUN(7, 1, -1, 0,1,0,1, 0); - return 0; + SEG_CHECK_READ(cpu_state.ea_seg); + SEG_CHECK_WRITE(&cpu_state.seg_es); + CHECK_READ(cpu_state.ea_seg, SI, SI + 3UL); + CHECK_WRITE(&cpu_state.seg_es, DI, DI + 3UL); + high_page = 0; + do_mmut_rl(cpu_state.ea_seg->base, SI, addr64a); + if (cpu_state.abrt) + return 1; + do_mmut_wl(es, DI, addr64a_2); + if (cpu_state.abrt) + return 1; + temp = readmeml_n(cpu_state.ea_seg->base, SI, addr64a); + if (cpu_state.abrt) + return 1; + writememl_n(es, DI, addr64a_2, temp); + if (cpu_state.abrt) + return 1; + if (cpu_state.flags & D_FLAG) { + DI -= 4; + SI -= 4; + } else { + DI += 4; + SI += 4; + } + CLOCK_CYCLES(7); + PREFETCH_RUN(7, 1, -1, 0, 1, 0, 1, 0); + return 0; } -static int opMOVSL_a32(uint32_t fetchdat) +static int +opMOVSL_a32(uint32_t fetchdat) { - uint32_t temp; + uint32_t temp; - addr64a[0] = addr64a[1] = addr64a[2] = addr64a[3] = 0x00000000; - addr64a_2[0] = addr64a_2[1] = addr64a_2[2] = addr64a_2[3] = 0x00000000; + addr64a[0] = addr64a[1] = addr64a[2] = addr64a[3] = 0x00000000; + addr64a_2[0] = addr64a_2[1] = addr64a_2[2] = addr64a_2[3] = 0x00000000; - SEG_CHECK_READ(cpu_state.ea_seg); - CHECK_READ(cpu_state.ea_seg, ESI, ESI + 3UL); - high_page = 0; - do_mmut_rl(cpu_state.ea_seg->base, ESI, addr64a); - if (cpu_state.abrt) return 1; - SEG_CHECK_WRITE(&cpu_state.seg_es); - CHECK_WRITE(&cpu_state.seg_es, EDI, EDI + 3UL); - do_mmut_wl(es, EDI, addr64a_2); - if (cpu_state.abrt) return 1; - temp = readmeml_n(cpu_state.ea_seg->base, ESI, addr64a); if (cpu_state.abrt) return 1; - writememl_n(es, EDI, addr64a_2, temp); if (cpu_state.abrt) return 1; - if (cpu_state.flags & D_FLAG) { EDI -= 4; ESI -= 4; } - else { EDI += 4; ESI += 4; } - CLOCK_CYCLES(7); - PREFETCH_RUN(7, 1, -1, 0,1,0,1, 1); - return 0; + SEG_CHECK_READ(cpu_state.ea_seg); + SEG_CHECK_WRITE(&cpu_state.seg_es); + CHECK_READ(cpu_state.ea_seg, ESI, ESI + 3UL); + CHECK_WRITE(&cpu_state.seg_es, EDI, EDI + 3UL); + high_page = 0; + do_mmut_rl(cpu_state.ea_seg->base, ESI, addr64a); + if (cpu_state.abrt) + return 1; + do_mmut_wl(es, EDI, addr64a_2); + if (cpu_state.abrt) + return 1; + temp = readmeml_n(cpu_state.ea_seg->base, ESI, addr64a); + if (cpu_state.abrt) + return 1; + writememl_n(es, EDI, addr64a_2, temp); + if (cpu_state.abrt) + return 1; + if (cpu_state.flags & D_FLAG) { + EDI -= 4; + ESI -= 4; + } else { + EDI += 4; + ESI += 4; + } + CLOCK_CYCLES(7); + PREFETCH_RUN(7, 1, -1, 0, 1, 0, 1, 1); + return 0; } - -static int opCMPSB_a16(uint32_t fetchdat) +static int +opCMPSB_a16(uint32_t fetchdat) { - uint8_t src, dst; + uint8_t src; + uint8_t dst; - addr64 = addr64_2 = 0x00000000; + addr64 = addr64_2 = 0x00000000; - SEG_CHECK_READ(cpu_state.ea_seg); - CHECK_READ(cpu_state.ea_seg, SI, SI); - high_page = uncached = 0; - do_mmut_rb(cpu_state.ea_seg->base, SI, &addr64); - if (cpu_state.abrt) return 1; - SEG_CHECK_READ(&cpu_state.seg_es); - CHECK_READ(&cpu_state.seg_es, DI, DI); - do_mmut_rb2(es, DI, &addr64_2); - if (cpu_state.abrt) return 1; - src = readmemb_n(cpu_state.ea_seg->base, SI, addr64); if (cpu_state.abrt) return 1; - if (uncached) - readlookup2[(uint32_t)(es+DI)>>12] = old_rl2; - dst = readmemb_n(es, DI, addr64_2); if (cpu_state.abrt) return 1; - if (uncached) - readlookup2[(uint32_t)(es+DI)>>12] = (uintptr_t) LOOKUP_INV; - setsub8(src, dst); - if (cpu_state.flags & D_FLAG) { DI--; SI--; } - else { DI++; SI++; } - CLOCK_CYCLES((is486) ? 8 : 10); - PREFETCH_RUN((is486) ? 8 : 10, 1, -1, 2,0,0,0, 0); - return 0; + SEG_CHECK_READ(cpu_state.ea_seg); + SEG_CHECK_READ(&cpu_state.seg_es); + CHECK_READ(cpu_state.ea_seg, SI, SI); + CHECK_READ(&cpu_state.seg_es, DI, DI); + high_page = uncached = 0; + do_mmut_rb(cpu_state.ea_seg->base, SI, &addr64); + if (cpu_state.abrt) + return 1; + do_mmut_rb2(es, DI, &addr64_2); + if (cpu_state.abrt) + return 1; + src = readmemb_n(cpu_state.ea_seg->base, SI, addr64); + if (cpu_state.abrt) + return 1; + if (uncached) + readlookup2[(uint32_t) (es + DI) >> 12] = old_rl2; + dst = readmemb_n(es, DI, addr64_2); + if (cpu_state.abrt) + return 1; + if (uncached) + readlookup2[(uint32_t) (es + DI) >> 12] = (uintptr_t) LOOKUP_INV; + setsub8(src, dst); + if (cpu_state.flags & D_FLAG) { + DI--; + SI--; + } else { + DI++; + SI++; + } + CLOCK_CYCLES((is486) ? 8 : 10); + PREFETCH_RUN((is486) ? 8 : 10, 1, -1, 2, 0, 0, 0, 0); + return 0; } -static int opCMPSB_a32(uint32_t fetchdat) +static int +opCMPSB_a32(uint32_t fetchdat) { - uint8_t src, dst; + uint8_t src; + uint8_t dst; - addr64 = addr64_2 = 0x00000000; + addr64 = addr64_2 = 0x00000000; - SEG_CHECK_READ(cpu_state.ea_seg); - CHECK_READ(cpu_state.ea_seg, ESI, ESI); - high_page = uncached = 0; - do_mmut_rb(cpu_state.ea_seg->base, ESI, &addr64); - if (cpu_state.abrt) return 1; - SEG_CHECK_READ(&cpu_state.seg_es); - CHECK_READ(&cpu_state.seg_es, EDI, EDI); - do_mmut_rb2(es, EDI, &addr64_2); - if (cpu_state.abrt) return 1; - src = readmemb_n(cpu_state.ea_seg->base, ESI, addr64); if (cpu_state.abrt) return 1; - if (uncached) - readlookup2[(uint32_t)(es+EDI)>>12] = old_rl2; - dst = readmemb_n(es, EDI, addr64_2); if (cpu_state.abrt) return 1; - if (uncached) - readlookup2[(uint32_t)(es+EDI)>>12] = (uintptr_t) LOOKUP_INV; - setsub8(src, dst); - if (cpu_state.flags & D_FLAG) { EDI--; ESI--; } - else { EDI++; ESI++; } - CLOCK_CYCLES((is486) ? 8 : 10); - PREFETCH_RUN((is486) ? 8 : 10, 1, -1, 2,0,0,0, 1); - return 0; + SEG_CHECK_READ(cpu_state.ea_seg); + SEG_CHECK_READ(&cpu_state.seg_es); + CHECK_READ(cpu_state.ea_seg, ESI, ESI); + CHECK_READ(&cpu_state.seg_es, EDI, EDI); + high_page = uncached = 0; + do_mmut_rb(cpu_state.ea_seg->base, ESI, &addr64); + if (cpu_state.abrt) + return 1; + do_mmut_rb2(es, EDI, &addr64_2); + if (cpu_state.abrt) + return 1; + src = readmemb_n(cpu_state.ea_seg->base, ESI, addr64); + if (cpu_state.abrt) + return 1; + if (uncached) + readlookup2[(uint32_t) (es + EDI) >> 12] = old_rl2; + dst = readmemb_n(es, EDI, addr64_2); + if (cpu_state.abrt) + return 1; + if (uncached) + readlookup2[(uint32_t) (es + EDI) >> 12] = (uintptr_t) LOOKUP_INV; + setsub8(src, dst); + if (cpu_state.flags & D_FLAG) { + EDI--; + ESI--; + } else { + EDI++; + ESI++; + } + CLOCK_CYCLES((is486) ? 8 : 10); + PREFETCH_RUN((is486) ? 8 : 10, 1, -1, 2, 0, 0, 0, 1); + return 0; } -static int opCMPSW_a16(uint32_t fetchdat) +static int +opCMPSW_a16(uint32_t fetchdat) { - uint16_t src, dst; + uint16_t src; + uint16_t dst; - addr64a[0] = addr64a[1] = 0x00000000; - addr64a_2[0] = addr64a_2[1] = 0x00000000; + addr64a[0] = addr64a[1] = 0x00000000; + addr64a_2[0] = addr64a_2[1] = 0x00000000; - SEG_CHECK_READ(cpu_state.ea_seg); - CHECK_READ(cpu_state.ea_seg, SI, SI + 1UL); - high_page = uncached = 0; - do_mmut_rw(cpu_state.ea_seg->base, SI, addr64a); - if (cpu_state.abrt) return 1; - SEG_CHECK_READ(&cpu_state.seg_es); - CHECK_READ(&cpu_state.seg_es, DI, DI + 1UL); - do_mmut_rw2(es, DI, addr64a_2); - if (cpu_state.abrt) return 1; - src = readmemw_n(cpu_state.ea_seg->base, SI, addr64a); if (cpu_state.abrt) return 1; - if (uncached) - readlookup2[(uint32_t)(es+DI)>>12] = old_rl2; - dst = readmemw_n(es, DI, addr64a_2); if (cpu_state.abrt) return 1; - if (uncached) - readlookup2[(uint32_t)(es+DI)>>12] = (uintptr_t) LOOKUP_INV; - setsub16(src, dst); - if (cpu_state.flags & D_FLAG) { DI -= 2; SI -= 2; } - else { DI += 2; SI += 2; } - CLOCK_CYCLES((is486) ? 8 : 10); - PREFETCH_RUN((is486) ? 8 : 10, 1, -1, 2,0,0,0, 0); - return 0; + SEG_CHECK_READ(cpu_state.ea_seg); + SEG_CHECK_READ(&cpu_state.seg_es); + CHECK_READ(cpu_state.ea_seg, SI, SI + 1UL); + CHECK_READ(&cpu_state.seg_es, DI, DI + 1UL); + high_page = uncached = 0; + do_mmut_rw(cpu_state.ea_seg->base, SI, addr64a); + if (cpu_state.abrt) + return 1; + do_mmut_rw2(es, DI, addr64a_2); + if (cpu_state.abrt) + return 1; + src = readmemw_n(cpu_state.ea_seg->base, SI, addr64a); + if (cpu_state.abrt) + return 1; + if (uncached) + readlookup2[(uint32_t) (es + DI) >> 12] = old_rl2; + dst = readmemw_n(es, DI, addr64a_2); + if (cpu_state.abrt) + return 1; + if (uncached) + readlookup2[(uint32_t) (es + DI) >> 12] = (uintptr_t) LOOKUP_INV; + setsub16(src, dst); + if (cpu_state.flags & D_FLAG) { + DI -= 2; + SI -= 2; + } else { + DI += 2; + SI += 2; + } + CLOCK_CYCLES((is486) ? 8 : 10); + PREFETCH_RUN((is486) ? 8 : 10, 1, -1, 2, 0, 0, 0, 0); + return 0; } -static int opCMPSW_a32(uint32_t fetchdat) +static int +opCMPSW_a32(uint32_t fetchdat) { - uint16_t src, dst; + uint16_t src; + uint16_t dst; - addr64a[0] = addr64a[1] = 0x00000000; - addr64a_2[0] = addr64a_2[1] = 0x00000000; + addr64a[0] = addr64a[1] = 0x00000000; + addr64a_2[0] = addr64a_2[1] = 0x00000000; - SEG_CHECK_READ(cpu_state.ea_seg); - CHECK_READ(cpu_state.ea_seg, ESI, ESI + 1UL); - high_page = uncached = 0; - do_mmut_rw(cpu_state.ea_seg->base, ESI, addr64a); - if (cpu_state.abrt) return 1; - SEG_CHECK_READ(&cpu_state.seg_es); - CHECK_READ(&cpu_state.seg_es, EDI, EDI + 1UL); - do_mmut_rw2(es, EDI, addr64a_2); - if (cpu_state.abrt) return 1; - src = readmemw_n(cpu_state.ea_seg->base, ESI, addr64a); if (cpu_state.abrt) return 1; - if (uncached) - readlookup2[(uint32_t)(es+EDI)>>12] = old_rl2; - dst = readmemw_n(es, EDI, addr64a_2); if (cpu_state.abrt) return 1; - if (uncached) - readlookup2[(uint32_t)(es+EDI)>>12] = (uintptr_t) LOOKUP_INV; - setsub16(src, dst); - if (cpu_state.flags & D_FLAG) { EDI -= 2; ESI -= 2; } - else { EDI += 2; ESI += 2; } - CLOCK_CYCLES((is486) ? 8 : 10); - PREFETCH_RUN((is486) ? 8 : 10, 1, -1, 2,0,0,0, 1); - return 0; + SEG_CHECK_READ(cpu_state.ea_seg); + SEG_CHECK_READ(&cpu_state.seg_es); + CHECK_READ(cpu_state.ea_seg, ESI, ESI + 1UL); + CHECK_READ(&cpu_state.seg_es, EDI, EDI + 1UL); + high_page = uncached = 0; + do_mmut_rw(cpu_state.ea_seg->base, ESI, addr64a); + if (cpu_state.abrt) + return 1; + do_mmut_rw2(es, EDI, addr64a_2); + if (cpu_state.abrt) + return 1; + src = readmemw_n(cpu_state.ea_seg->base, ESI, addr64a); + if (cpu_state.abrt) + return 1; + if (uncached) + readlookup2[(uint32_t) (es + EDI) >> 12] = old_rl2; + dst = readmemw_n(es, EDI, addr64a_2); + if (cpu_state.abrt) + return 1; + if (uncached) + readlookup2[(uint32_t) (es + EDI) >> 12] = (uintptr_t) LOOKUP_INV; + setsub16(src, dst); + if (cpu_state.flags & D_FLAG) { + EDI -= 2; + ESI -= 2; + } else { + EDI += 2; + ESI += 2; + } + CLOCK_CYCLES((is486) ? 8 : 10); + PREFETCH_RUN((is486) ? 8 : 10, 1, -1, 2, 0, 0, 0, 1); + return 0; } -static int opCMPSL_a16(uint32_t fetchdat) +static int +opCMPSL_a16(uint32_t fetchdat) { - uint32_t src, dst; + uint32_t src; + uint32_t dst; - addr64a[0] = addr64a[1] = addr64a[2] = addr64a[3] = 0x00000000; - addr64a_2[0] = addr64a_2[1] = addr64a_2[2] = addr64a_2[3] = 0x00000000; + addr64a[0] = addr64a[1] = addr64a[2] = addr64a[3] = 0x00000000; + addr64a_2[0] = addr64a_2[1] = addr64a_2[2] = addr64a_2[3] = 0x00000000; - SEG_CHECK_READ(cpu_state.ea_seg); - CHECK_READ(cpu_state.ea_seg, SI, SI + 3UL); - high_page = uncached = 0; - do_mmut_rl(cpu_state.ea_seg->base, SI, addr64a); - if (cpu_state.abrt) return 1; - SEG_CHECK_READ(&cpu_state.seg_es); - CHECK_READ(&cpu_state.seg_es, DI, DI + 3UL); - do_mmut_rl2(es, DI, addr64a_2); - if (cpu_state.abrt) return 1; - src = readmeml_n(cpu_state.ea_seg->base, SI, addr64a); if (cpu_state.abrt) return 1; - if (uncached) - readlookup2[(uint32_t)(es+DI)>>12] = old_rl2; - dst = readmeml_n(es, DI, addr64a_2); if (cpu_state.abrt) return 1; - if (uncached) - readlookup2[(uint32_t)(es+DI)>>12] = (uintptr_t) LOOKUP_INV; - setsub32(src, dst); - if (cpu_state.flags & D_FLAG) { DI -= 4; SI -= 4; } - else { DI += 4; SI += 4; } - CLOCK_CYCLES((is486) ? 8 : 10); - PREFETCH_RUN((is486) ? 8 : 10, 1, -1, 0,2,0,0, 0); - return 0; + SEG_CHECK_READ(cpu_state.ea_seg); + SEG_CHECK_READ(&cpu_state.seg_es); + CHECK_READ(cpu_state.ea_seg, SI, SI + 3UL); + CHECK_READ(&cpu_state.seg_es, DI, DI + 3UL); + high_page = uncached = 0; + do_mmut_rl(cpu_state.ea_seg->base, SI, addr64a); + if (cpu_state.abrt) + return 1; + do_mmut_rl2(es, DI, addr64a_2); + if (cpu_state.abrt) + return 1; + src = readmeml_n(cpu_state.ea_seg->base, SI, addr64a); + if (cpu_state.abrt) + return 1; + if (uncached) + readlookup2[(uint32_t) (es + DI) >> 12] = old_rl2; + dst = readmeml_n(es, DI, addr64a_2); + if (cpu_state.abrt) + return 1; + if (uncached) + readlookup2[(uint32_t) (es + DI) >> 12] = (uintptr_t) LOOKUP_INV; + setsub32(src, dst); + if (cpu_state.flags & D_FLAG) { + DI -= 4; + SI -= 4; + } else { + DI += 4; + SI += 4; + } + CLOCK_CYCLES((is486) ? 8 : 10); + PREFETCH_RUN((is486) ? 8 : 10, 1, -1, 0, 2, 0, 0, 0); + return 0; } -static int opCMPSL_a32(uint32_t fetchdat) +static int +opCMPSL_a32(uint32_t fetchdat) { - uint32_t src, dst; + uint32_t src; + uint32_t dst; - addr64a[0] = addr64a[1] = addr64a[2] = addr64a[3] = 0x00000000; - addr64a_2[0] = addr64a_2[1] = addr64a_2[2] = addr64a_2[3] = 0x00000000; + addr64a[0] = addr64a[1] = addr64a[2] = addr64a[3] = 0x00000000; + addr64a_2[0] = addr64a_2[1] = addr64a_2[2] = addr64a_2[3] = 0x00000000; - SEG_CHECK_READ(cpu_state.ea_seg); - CHECK_READ(cpu_state.ea_seg, ESI, ESI + 3UL); - high_page = uncached = 0; - do_mmut_rl(cpu_state.ea_seg->base, ESI, addr64a); - if (cpu_state.abrt) return 1; - SEG_CHECK_READ(&cpu_state.seg_es); - CHECK_READ(&cpu_state.seg_es, EDI, EDI + 3UL); - do_mmut_rl2(es, EDI, addr64a_2); - if (cpu_state.abrt) return 1; - src = readmeml_n(cpu_state.ea_seg->base, ESI, addr64a); if (cpu_state.abrt) return 1; - if (uncached) - readlookup2[(uint32_t)(es+EDI)>>12] = old_rl2; - dst = readmeml_n(es, EDI, addr64a_2); if (cpu_state.abrt) return 1; - if (uncached) - readlookup2[(uint32_t)(es+EDI)>>12] = (uintptr_t) LOOKUP_INV; - setsub32(src, dst); - if (cpu_state.flags & D_FLAG) { EDI -= 4; ESI -= 4; } - else { EDI += 4; ESI += 4; } - CLOCK_CYCLES((is486) ? 8 : 10); - PREFETCH_RUN((is486) ? 8 : 10, 1, -1, 0,2,0,0, 1); - return 0; + SEG_CHECK_READ(cpu_state.ea_seg); + SEG_CHECK_READ(&cpu_state.seg_es); + CHECK_READ(cpu_state.ea_seg, ESI, ESI + 3UL); + CHECK_READ(&cpu_state.seg_es, EDI, EDI + 3UL); + high_page = uncached = 0; + do_mmut_rl(cpu_state.ea_seg->base, ESI, addr64a); + if (cpu_state.abrt) + return 1; + do_mmut_rl2(es, EDI, addr64a_2); + if (cpu_state.abrt) + return 1; + src = readmeml_n(cpu_state.ea_seg->base, ESI, addr64a); + if (cpu_state.abrt) + return 1; + if (uncached) + readlookup2[(uint32_t) (es + EDI) >> 12] = old_rl2; + dst = readmeml_n(es, EDI, addr64a_2); + if (cpu_state.abrt) + return 1; + if (uncached) + readlookup2[(uint32_t) (es + EDI) >> 12] = (uintptr_t) LOOKUP_INV; + setsub32(src, dst); + if (cpu_state.flags & D_FLAG) { + EDI -= 4; + ESI -= 4; + } else { + EDI += 4; + ESI += 4; + } + CLOCK_CYCLES((is486) ? 8 : 10); + PREFETCH_RUN((is486) ? 8 : 10, 1, -1, 0, 2, 0, 0, 1); + return 0; } -static int opSTOSB_a16(uint32_t fetchdat) +static int +opSTOSB_a16(uint32_t fetchdat) { - SEG_CHECK_WRITE(&cpu_state.seg_es); - CHECK_WRITE(&cpu_state.seg_es, DI, DI); - writememb(es, DI, AL); if (cpu_state.abrt) return 1; - if (cpu_state.flags & D_FLAG) DI--; - else DI++; - CLOCK_CYCLES(4); - PREFETCH_RUN(4, 1, -1, 0,0,1,0, 0); - return 0; + SEG_CHECK_WRITE(&cpu_state.seg_es); + CHECK_WRITE(&cpu_state.seg_es, DI, DI); + writememb(es, DI, AL); + if (cpu_state.abrt) + return 1; + if (cpu_state.flags & D_FLAG) + DI--; + else + DI++; + CLOCK_CYCLES(4); + PREFETCH_RUN(4, 1, -1, 0, 0, 1, 0, 0); + return 0; } -static int opSTOSB_a32(uint32_t fetchdat) +static int +opSTOSB_a32(uint32_t fetchdat) { - SEG_CHECK_WRITE(&cpu_state.seg_es); - CHECK_WRITE(&cpu_state.seg_es, EDI, EDI); - writememb(es, EDI, AL); if (cpu_state.abrt) return 1; - if (cpu_state.flags & D_FLAG) EDI--; - else EDI++; - CLOCK_CYCLES(4); - PREFETCH_RUN(4, 1, -1, 0,0,1,0, 1); - return 0; + SEG_CHECK_WRITE(&cpu_state.seg_es); + CHECK_WRITE(&cpu_state.seg_es, EDI, EDI); + writememb(es, EDI, AL); + if (cpu_state.abrt) + return 1; + if (cpu_state.flags & D_FLAG) + EDI--; + else + EDI++; + CLOCK_CYCLES(4); + PREFETCH_RUN(4, 1, -1, 0, 0, 1, 0, 1); + return 0; } -static int opSTOSW_a16(uint32_t fetchdat) +static int +opSTOSW_a16(uint32_t fetchdat) { - SEG_CHECK_WRITE(&cpu_state.seg_es); - CHECK_WRITE(&cpu_state.seg_es, DI, DI + 1UL); - writememw(es, DI, AX); if (cpu_state.abrt) return 1; - if (cpu_state.flags & D_FLAG) DI -= 2; - else DI += 2; - CLOCK_CYCLES(4); - PREFETCH_RUN(4, 1, -1, 0,0,1,0, 0); - return 0; + SEG_CHECK_WRITE(&cpu_state.seg_es); + CHECK_WRITE(&cpu_state.seg_es, DI, DI + 1UL); + writememw(es, DI, AX); + if (cpu_state.abrt) + return 1; + if (cpu_state.flags & D_FLAG) + DI -= 2; + else + DI += 2; + CLOCK_CYCLES(4); + PREFETCH_RUN(4, 1, -1, 0, 0, 1, 0, 0); + return 0; } -static int opSTOSW_a32(uint32_t fetchdat) +static int +opSTOSW_a32(uint32_t fetchdat) { - SEG_CHECK_WRITE(&cpu_state.seg_es); - CHECK_WRITE(&cpu_state.seg_es, EDI, EDI + 1UL); - writememw(es, EDI, AX); if (cpu_state.abrt) return 1; - if (cpu_state.flags & D_FLAG) EDI -= 2; - else EDI += 2; - CLOCK_CYCLES(4); - PREFETCH_RUN(4, 1, -1, 0,0,1,0, 1); - return 0; + SEG_CHECK_WRITE(&cpu_state.seg_es); + CHECK_WRITE(&cpu_state.seg_es, EDI, EDI + 1UL); + writememw(es, EDI, AX); + if (cpu_state.abrt) + return 1; + if (cpu_state.flags & D_FLAG) + EDI -= 2; + else + EDI += 2; + CLOCK_CYCLES(4); + PREFETCH_RUN(4, 1, -1, 0, 0, 1, 0, 1); + return 0; } -static int opSTOSL_a16(uint32_t fetchdat) +static int +opSTOSL_a16(uint32_t fetchdat) { - SEG_CHECK_WRITE(&cpu_state.seg_es); - CHECK_WRITE(&cpu_state.seg_es, DI, DI + 3UL); - writememl(es, DI, EAX); if (cpu_state.abrt) return 1; - if (cpu_state.flags & D_FLAG) DI -= 4; - else DI += 4; - CLOCK_CYCLES(4); - PREFETCH_RUN(4, 1, -1, 0,0,0,1, 0); - return 0; + SEG_CHECK_WRITE(&cpu_state.seg_es); + CHECK_WRITE(&cpu_state.seg_es, DI, DI + 3UL); + writememl(es, DI, EAX); + if (cpu_state.abrt) + return 1; + if (cpu_state.flags & D_FLAG) + DI -= 4; + else + DI += 4; + CLOCK_CYCLES(4); + PREFETCH_RUN(4, 1, -1, 0, 0, 0, 1, 0); + return 0; } -static int opSTOSL_a32(uint32_t fetchdat) +static int +opSTOSL_a32(uint32_t fetchdat) { - SEG_CHECK_WRITE(&cpu_state.seg_es); - CHECK_WRITE(&cpu_state.seg_es, EDI, EDI + 3UL); - writememl(es, EDI, EAX); if (cpu_state.abrt) return 1; - if (cpu_state.flags & D_FLAG) EDI -= 4; - else EDI += 4; - CLOCK_CYCLES(4); - PREFETCH_RUN(4, 1, -1, 0,0,0,1, 1); - return 0; + SEG_CHECK_WRITE(&cpu_state.seg_es); + CHECK_WRITE(&cpu_state.seg_es, EDI, EDI + 3UL); + writememl(es, EDI, EAX); + if (cpu_state.abrt) + return 1; + if (cpu_state.flags & D_FLAG) + EDI -= 4; + else + EDI += 4; + CLOCK_CYCLES(4); + PREFETCH_RUN(4, 1, -1, 0, 0, 0, 1, 1); + return 0; } - -static int opLODSB_a16(uint32_t fetchdat) +static int +opLODSB_a16(uint32_t fetchdat) { - uint8_t temp; + uint8_t temp; - SEG_CHECK_READ(cpu_state.ea_seg); - CHECK_READ(cpu_state.ea_seg, SI, SI); - temp = readmemb(cpu_state.ea_seg->base, SI); if (cpu_state.abrt) return 1; - AL = temp; - if (cpu_state.flags & D_FLAG) SI--; - else SI++; - CLOCK_CYCLES(5); - PREFETCH_RUN(5, 1, -1, 1,0,0,0, 0); - return 0; + SEG_CHECK_READ(cpu_state.ea_seg); + CHECK_READ(cpu_state.ea_seg, SI, SI); + temp = readmemb(cpu_state.ea_seg->base, SI); + if (cpu_state.abrt) + return 1; + AL = temp; + if (cpu_state.flags & D_FLAG) + SI--; + else + SI++; + CLOCK_CYCLES(5); + PREFETCH_RUN(5, 1, -1, 1, 0, 0, 0, 0); + return 0; } -static int opLODSB_a32(uint32_t fetchdat) +static int +opLODSB_a32(uint32_t fetchdat) { - uint8_t temp; + uint8_t temp; - SEG_CHECK_READ(cpu_state.ea_seg); - CHECK_READ(cpu_state.ea_seg, ESI, ESI); - temp = readmemb(cpu_state.ea_seg->base, ESI); if (cpu_state.abrt) return 1; - AL = temp; - if (cpu_state.flags & D_FLAG) ESI--; - else ESI++; - CLOCK_CYCLES(5); - PREFETCH_RUN(5, 1, -1, 1,0,0,0, 1); - return 0; + SEG_CHECK_READ(cpu_state.ea_seg); + CHECK_READ(cpu_state.ea_seg, ESI, ESI); + temp = readmemb(cpu_state.ea_seg->base, ESI); + if (cpu_state.abrt) + return 1; + AL = temp; + if (cpu_state.flags & D_FLAG) + ESI--; + else + ESI++; + CLOCK_CYCLES(5); + PREFETCH_RUN(5, 1, -1, 1, 0, 0, 0, 1); + return 0; } -static int opLODSW_a16(uint32_t fetchdat) +static int +opLODSW_a16(uint32_t fetchdat) { - uint16_t temp; + uint16_t temp; - SEG_CHECK_READ(cpu_state.ea_seg); - CHECK_READ(cpu_state.ea_seg, SI, SI + 1UL); - temp = readmemw(cpu_state.ea_seg->base, SI); if (cpu_state.abrt) return 1; - AX = temp; - if (cpu_state.flags & D_FLAG) SI -= 2; - else SI += 2; - CLOCK_CYCLES(5); - PREFETCH_RUN(5, 1, -1, 1,0,0,0, 0); - return 0; + SEG_CHECK_READ(cpu_state.ea_seg); + CHECK_READ(cpu_state.ea_seg, SI, SI + 1UL); + temp = readmemw(cpu_state.ea_seg->base, SI); + if (cpu_state.abrt) + return 1; + AX = temp; + if (cpu_state.flags & D_FLAG) + SI -= 2; + else + SI += 2; + CLOCK_CYCLES(5); + PREFETCH_RUN(5, 1, -1, 1, 0, 0, 0, 0); + return 0; } -static int opLODSW_a32(uint32_t fetchdat) +static int +opLODSW_a32(uint32_t fetchdat) { - uint16_t temp; + uint16_t temp; - SEG_CHECK_READ(cpu_state.ea_seg); - CHECK_READ(cpu_state.ea_seg, ESI, ESI + 1UL); - temp = readmemw(cpu_state.ea_seg->base, ESI); if (cpu_state.abrt) return 1; - AX = temp; - if (cpu_state.flags & D_FLAG) ESI -= 2; - else ESI += 2; - CLOCK_CYCLES(5); - PREFETCH_RUN(5, 1, -1, 1,0,0,0, 1); - return 0; + SEG_CHECK_READ(cpu_state.ea_seg); + CHECK_READ(cpu_state.ea_seg, ESI, ESI + 1UL); + temp = readmemw(cpu_state.ea_seg->base, ESI); + if (cpu_state.abrt) + return 1; + AX = temp; + if (cpu_state.flags & D_FLAG) + ESI -= 2; + else + ESI += 2; + CLOCK_CYCLES(5); + PREFETCH_RUN(5, 1, -1, 1, 0, 0, 0, 1); + return 0; } -static int opLODSL_a16(uint32_t fetchdat) +static int +opLODSL_a16(uint32_t fetchdat) { - uint32_t temp; + uint32_t temp; - SEG_CHECK_READ(cpu_state.ea_seg); - CHECK_READ(cpu_state.ea_seg, SI, SI + 3UL); - temp = readmeml(cpu_state.ea_seg->base, SI); if (cpu_state.abrt) return 1; - EAX = temp; - if (cpu_state.flags & D_FLAG) SI -= 4; - else SI += 4; - CLOCK_CYCLES(5); - PREFETCH_RUN(5, 1, -1, 0,1,0,0, 0); - return 0; + SEG_CHECK_READ(cpu_state.ea_seg); + CHECK_READ(cpu_state.ea_seg, SI, SI + 3UL); + temp = readmeml(cpu_state.ea_seg->base, SI); + if (cpu_state.abrt) + return 1; + EAX = temp; + if (cpu_state.flags & D_FLAG) + SI -= 4; + else + SI += 4; + CLOCK_CYCLES(5); + PREFETCH_RUN(5, 1, -1, 0, 1, 0, 0, 0); + return 0; } -static int opLODSL_a32(uint32_t fetchdat) +static int +opLODSL_a32(uint32_t fetchdat) { - uint32_t temp; + uint32_t temp; - SEG_CHECK_READ(cpu_state.ea_seg); - CHECK_READ(cpu_state.ea_seg, ESI, ESI + 3UL); - temp = readmeml(cpu_state.ea_seg->base, ESI); if (cpu_state.abrt) return 1; - EAX = temp; - if (cpu_state.flags & D_FLAG) ESI -= 4; - else ESI += 4; - CLOCK_CYCLES(5); - PREFETCH_RUN(5, 1, -1, 0,1,0,0, 1); - return 0; + SEG_CHECK_READ(cpu_state.ea_seg); + CHECK_READ(cpu_state.ea_seg, ESI, ESI + 3UL); + temp = readmeml(cpu_state.ea_seg->base, ESI); + if (cpu_state.abrt) + return 1; + EAX = temp; + if (cpu_state.flags & D_FLAG) + ESI -= 4; + else + ESI += 4; + CLOCK_CYCLES(5); + PREFETCH_RUN(5, 1, -1, 0, 1, 0, 0, 1); + return 0; } - -static int opSCASB_a16(uint32_t fetchdat) +static int +opSCASB_a16(uint32_t fetchdat) { - uint8_t temp; + uint8_t temp; - SEG_CHECK_READ(&cpu_state.seg_es); - CHECK_READ(&cpu_state.seg_es, DI, DI); - temp = readmemb(es, DI); if (cpu_state.abrt) return 1; - setsub8(AL, temp); - if (cpu_state.flags & D_FLAG) DI--; - else DI++; - CLOCK_CYCLES(7); - PREFETCH_RUN(7, 1, -1, 1,0,0,0, 0); - return 0; + SEG_CHECK_READ(&cpu_state.seg_es); + CHECK_READ(&cpu_state.seg_es, DI, DI); + temp = readmemb(es, DI); + if (cpu_state.abrt) + return 1; + setsub8(AL, temp); + if (cpu_state.flags & D_FLAG) + DI--; + else + DI++; + CLOCK_CYCLES(7); + PREFETCH_RUN(7, 1, -1, 1, 0, 0, 0, 0); + return 0; } -static int opSCASB_a32(uint32_t fetchdat) +static int +opSCASB_a32(uint32_t fetchdat) { - uint8_t temp; + uint8_t temp; - SEG_CHECK_READ(&cpu_state.seg_es); - CHECK_READ(&cpu_state.seg_es, EDI, EDI); - temp = readmemb(es, EDI); if (cpu_state.abrt) return 1; - setsub8(AL, temp); - if (cpu_state.flags & D_FLAG) EDI--; - else EDI++; - CLOCK_CYCLES(7); - PREFETCH_RUN(7, 1, -1, 1,0,0,0, 1); - return 0; + SEG_CHECK_READ(&cpu_state.seg_es); + CHECK_READ(&cpu_state.seg_es, EDI, EDI); + temp = readmemb(es, EDI); + if (cpu_state.abrt) + return 1; + setsub8(AL, temp); + if (cpu_state.flags & D_FLAG) + EDI--; + else + EDI++; + CLOCK_CYCLES(7); + PREFETCH_RUN(7, 1, -1, 1, 0, 0, 0, 1); + return 0; } -static int opSCASW_a16(uint32_t fetchdat) +static int +opSCASW_a16(uint32_t fetchdat) { - uint16_t temp; + uint16_t temp; - SEG_CHECK_READ(&cpu_state.seg_es); - CHECK_READ(&cpu_state.seg_es, DI, DI + 1UL); - temp = readmemw(es, DI); if (cpu_state.abrt) return 1; - setsub16(AX, temp); - if (cpu_state.flags & D_FLAG) DI -= 2; - else DI += 2; - CLOCK_CYCLES(7); - PREFETCH_RUN(7, 1, -1, 1,0,0,0, 0); - return 0; + SEG_CHECK_READ(&cpu_state.seg_es); + CHECK_READ(&cpu_state.seg_es, DI, DI + 1UL); + temp = readmemw(es, DI); + if (cpu_state.abrt) + return 1; + setsub16(AX, temp); + if (cpu_state.flags & D_FLAG) + DI -= 2; + else + DI += 2; + CLOCK_CYCLES(7); + PREFETCH_RUN(7, 1, -1, 1, 0, 0, 0, 0); + return 0; } -static int opSCASW_a32(uint32_t fetchdat) +static int +opSCASW_a32(uint32_t fetchdat) { - uint16_t temp; + uint16_t temp; - SEG_CHECK_READ(&cpu_state.seg_es); - CHECK_READ(&cpu_state.seg_es, EDI, EDI + 1UL); - temp = readmemw(es, EDI); if (cpu_state.abrt) return 1; - setsub16(AX, temp); - if (cpu_state.flags & D_FLAG) EDI -= 2; - else EDI += 2; - CLOCK_CYCLES(7); - PREFETCH_RUN(7, 1, -1, 1,0,0,0, 1); - return 0; + SEG_CHECK_READ(&cpu_state.seg_es); + CHECK_READ(&cpu_state.seg_es, EDI, EDI + 1UL); + temp = readmemw(es, EDI); + if (cpu_state.abrt) + return 1; + setsub16(AX, temp); + if (cpu_state.flags & D_FLAG) + EDI -= 2; + else + EDI += 2; + CLOCK_CYCLES(7); + PREFETCH_RUN(7, 1, -1, 1, 0, 0, 0, 1); + return 0; } -static int opSCASL_a16(uint32_t fetchdat) +static int +opSCASL_a16(uint32_t fetchdat) { - uint32_t temp; + uint32_t temp; - SEG_CHECK_READ(&cpu_state.seg_es); - CHECK_READ(&cpu_state.seg_es, DI, DI + 3UL); - temp = readmeml(es, DI); if (cpu_state.abrt) return 1; - setsub32(EAX, temp); - if (cpu_state.flags & D_FLAG) DI -= 4; - else DI += 4; - CLOCK_CYCLES(7); - PREFETCH_RUN(7, 1, -1, 0,1,0,0, 0); - return 0; + SEG_CHECK_READ(&cpu_state.seg_es); + CHECK_READ(&cpu_state.seg_es, DI, DI + 3UL); + temp = readmeml(es, DI); + if (cpu_state.abrt) + return 1; + setsub32(EAX, temp); + if (cpu_state.flags & D_FLAG) + DI -= 4; + else + DI += 4; + CLOCK_CYCLES(7); + PREFETCH_RUN(7, 1, -1, 0, 1, 0, 0, 0); + return 0; } -static int opSCASL_a32(uint32_t fetchdat) +static int +opSCASL_a32(uint32_t fetchdat) { - uint32_t temp; + uint32_t temp; - SEG_CHECK_READ(&cpu_state.seg_es); - CHECK_READ(&cpu_state.seg_es, EDI, EDI + 3UL); - temp = readmeml(es, EDI); if (cpu_state.abrt) return 1; - setsub32(EAX, temp); - if (cpu_state.flags & D_FLAG) EDI -= 4; - else EDI += 4; - CLOCK_CYCLES(7); - PREFETCH_RUN(7, 1, -1, 0,1,0,0, 1); - return 0; + SEG_CHECK_READ(&cpu_state.seg_es); + CHECK_READ(&cpu_state.seg_es, EDI, EDI + 3UL); + temp = readmeml(es, EDI); + if (cpu_state.abrt) + return 1; + setsub32(EAX, temp); + if (cpu_state.flags & D_FLAG) + EDI -= 4; + else + EDI += 4; + CLOCK_CYCLES(7); + PREFETCH_RUN(7, 1, -1, 0, 1, 0, 0, 1); + return 0; } -static int opINSB_a16(uint32_t fetchdat) +static int +opINSB_a16(uint32_t fetchdat) { - uint8_t temp; + uint8_t temp; - addr64 = 0x00000000; + addr64 = 0x00000000; - SEG_CHECK_WRITE(&cpu_state.seg_es); - check_io_perm(DX); - CHECK_WRITE(&cpu_state.seg_es, DI, DI); - high_page = 0; - do_mmut_wb(es, DI, &addr64); if (cpu_state.abrt) return 1; - temp = inb(DX); - writememb_n(es, DI, addr64, temp); if (cpu_state.abrt) return 1; - if (cpu_state.flags & D_FLAG) DI--; - else DI++; - CLOCK_CYCLES(15); - PREFETCH_RUN(15, 1, -1, 1,0,1,0, 0); - return 0; + SEG_CHECK_WRITE(&cpu_state.seg_es); + check_io_perm(DX, 1); + CHECK_WRITE(&cpu_state.seg_es, DI, DI); + high_page = 0; + do_mmut_wb(es, DI, &addr64); + if (cpu_state.abrt) + return 1; + temp = inb(DX); + writememb_n(es, DI, addr64, temp); + if (cpu_state.abrt) + return 1; + if (cpu_state.flags & D_FLAG) + DI--; + else + DI++; + CLOCK_CYCLES(15); + PREFETCH_RUN(15, 1, -1, 1, 0, 1, 0, 0); + return 0; } -static int opINSB_a32(uint32_t fetchdat) +static int +opINSB_a32(uint32_t fetchdat) { - uint8_t temp; + uint8_t temp; - addr64 = 0x00000000; + addr64 = 0x00000000; - SEG_CHECK_WRITE(&cpu_state.seg_es); - check_io_perm(DX); - high_page = 0; - CHECK_WRITE(&cpu_state.seg_es, EDI, EDI); - do_mmut_wb(es, EDI, &addr64); if (cpu_state.abrt) return 1; - temp = inb(DX); - writememb_n(es, EDI, addr64, temp); if (cpu_state.abrt) return 1; - if (cpu_state.flags & D_FLAG) EDI--; - else EDI++; - CLOCK_CYCLES(15); - PREFETCH_RUN(15, 1, -1, 1,0,1,0, 1); - return 0; + SEG_CHECK_WRITE(&cpu_state.seg_es); + check_io_perm(DX, 1); + high_page = 0; + CHECK_WRITE(&cpu_state.seg_es, EDI, EDI); + do_mmut_wb(es, EDI, &addr64); + if (cpu_state.abrt) + return 1; + temp = inb(DX); + writememb_n(es, EDI, addr64, temp); + if (cpu_state.abrt) + return 1; + if (cpu_state.flags & D_FLAG) + EDI--; + else + EDI++; + CLOCK_CYCLES(15); + PREFETCH_RUN(15, 1, -1, 1, 0, 1, 0, 1); + return 0; } -static int opINSW_a16(uint32_t fetchdat) +static int +opINSW_a16(uint32_t fetchdat) { - uint16_t temp; + uint16_t temp; - addr64a[0] = addr64a[1] = 0x00000000; + addr64a[0] = addr64a[1] = 0x00000000; - SEG_CHECK_WRITE(&cpu_state.seg_es); - check_io_perm(DX); - check_io_perm(DX + 1); - CHECK_WRITE(&cpu_state.seg_es, DI, DI + 1UL); - high_page = 0; - do_mmut_ww(es, DI, addr64a); if (cpu_state.abrt) return 1; - temp = inw(DX); - writememw_n(es, DI, addr64a, temp); if (cpu_state.abrt) return 1; - if (cpu_state.flags & D_FLAG) DI -= 2; - else DI += 2; - CLOCK_CYCLES(15); - PREFETCH_RUN(15, 1, -1, 1,0,1,0, 0); - return 0; + SEG_CHECK_WRITE(&cpu_state.seg_es); + check_io_perm(DX, 2); + CHECK_WRITE(&cpu_state.seg_es, DI, DI + 1UL); + high_page = 0; + do_mmut_ww(es, DI, addr64a); + if (cpu_state.abrt) + return 1; + temp = inw(DX); + writememw_n(es, DI, addr64a, temp); + if (cpu_state.abrt) + return 1; + if (cpu_state.flags & D_FLAG) + DI -= 2; + else + DI += 2; + CLOCK_CYCLES(15); + PREFETCH_RUN(15, 1, -1, 1, 0, 1, 0, 0); + return 0; } -static int opINSW_a32(uint32_t fetchdat) +static int +opINSW_a32(uint32_t fetchdat) { - uint16_t temp; + uint16_t temp; - addr64a[0] = addr64a[1] = 0x00000000; + addr64a[0] = addr64a[1] = 0x00000000; - SEG_CHECK_WRITE(&cpu_state.seg_es); - high_page = 0; - check_io_perm(DX); - check_io_perm(DX + 1); - CHECK_WRITE(&cpu_state.seg_es, EDI, EDI + 1UL); - do_mmut_ww(es, EDI, addr64a); if (cpu_state.abrt) return 1; - temp = inw(DX); - writememw_n(es, EDI, addr64a, temp); if (cpu_state.abrt) return 1; - if (cpu_state.flags & D_FLAG) EDI -= 2; - else EDI += 2; - CLOCK_CYCLES(15); - PREFETCH_RUN(15, 1, -1, 1,0,1,0, 1); - return 0; + SEG_CHECK_WRITE(&cpu_state.seg_es); + high_page = 0; + check_io_perm(DX, 2); + CHECK_WRITE(&cpu_state.seg_es, EDI, EDI + 1UL); + do_mmut_ww(es, EDI, addr64a); + if (cpu_state.abrt) + return 1; + temp = inw(DX); + writememw_n(es, EDI, addr64a, temp); + if (cpu_state.abrt) + return 1; + if (cpu_state.flags & D_FLAG) + EDI -= 2; + else + EDI += 2; + CLOCK_CYCLES(15); + PREFETCH_RUN(15, 1, -1, 1, 0, 1, 0, 1); + return 0; } -static int opINSL_a16(uint32_t fetchdat) +static int +opINSL_a16(uint32_t fetchdat) { - uint32_t temp; + uint32_t temp; - addr64a[0] = addr64a[1] = addr64a[2] = addr64a[3] = 0x00000000; + addr64a[0] = addr64a[1] = addr64a[2] = addr64a[3] = 0x00000000; - SEG_CHECK_WRITE(&cpu_state.seg_es); - check_io_perm(DX); - check_io_perm(DX + 1); - check_io_perm(DX + 2); - check_io_perm(DX + 3); - CHECK_WRITE(&cpu_state.seg_es, DI, DI + 3UL); - high_page = 0; - do_mmut_wl(es, DI, addr64a); if (cpu_state.abrt) return 1; - temp = inl(DX); - writememl_n(es, DI, addr64a, temp); if (cpu_state.abrt) return 1; - if (cpu_state.flags & D_FLAG) DI -= 4; - else DI += 4; - CLOCK_CYCLES(15); - PREFETCH_RUN(15, 1, -1, 0,1,0,1, 0); - return 0; + SEG_CHECK_WRITE(&cpu_state.seg_es); + check_io_perm(DX, 4); + CHECK_WRITE(&cpu_state.seg_es, DI, DI + 3UL); + high_page = 0; + do_mmut_wl(es, DI, addr64a); + if (cpu_state.abrt) + return 1; + temp = inl(DX); + writememl_n(es, DI, addr64a, temp); + if (cpu_state.abrt) + return 1; + if (cpu_state.flags & D_FLAG) + DI -= 4; + else + DI += 4; + CLOCK_CYCLES(15); + PREFETCH_RUN(15, 1, -1, 0, 1, 0, 1, 0); + return 0; } -static int opINSL_a32(uint32_t fetchdat) +static int +opINSL_a32(uint32_t fetchdat) { - uint32_t temp; + uint32_t temp; - addr64a[0] = addr64a[1] = addr64a[2] = addr64a[3] = 0x00000000; + addr64a[0] = addr64a[1] = addr64a[2] = addr64a[3] = 0x00000000; - SEG_CHECK_WRITE(&cpu_state.seg_es); - check_io_perm(DX); - check_io_perm(DX + 1); - check_io_perm(DX + 2); - check_io_perm(DX + 3); - CHECK_WRITE(&cpu_state.seg_es, EDI, EDI + 3UL); - high_page = 0; - do_mmut_wl(es, DI, addr64a); if (cpu_state.abrt) return 1; - temp = inl(DX); - writememl_n(es, EDI, addr64a, temp); if (cpu_state.abrt) return 1; - if (cpu_state.flags & D_FLAG) EDI -= 4; - else EDI += 4; - CLOCK_CYCLES(15); - PREFETCH_RUN(15, 1, -1, 0,1,0,1, 1); - return 0; + SEG_CHECK_WRITE(&cpu_state.seg_es); + check_io_perm(DX, 4); + CHECK_WRITE(&cpu_state.seg_es, EDI, EDI + 3UL); + high_page = 0; + do_mmut_wl(es, DI, addr64a); + if (cpu_state.abrt) + return 1; + temp = inl(DX); + writememl_n(es, EDI, addr64a, temp); + if (cpu_state.abrt) + return 1; + if (cpu_state.flags & D_FLAG) + EDI -= 4; + else + EDI += 4; + CLOCK_CYCLES(15); + PREFETCH_RUN(15, 1, -1, 0, 1, 0, 1, 1); + return 0; } -static int opOUTSB_a16(uint32_t fetchdat) +static int +opOUTSB_a16(uint32_t fetchdat) { - uint8_t temp; + uint8_t temp; - SEG_CHECK_READ(cpu_state.ea_seg); - CHECK_READ(cpu_state.ea_seg, SI, SI); - temp = readmemb(cpu_state.ea_seg->base, SI); if (cpu_state.abrt) return 1; - check_io_perm(DX); - if (cpu_state.flags & D_FLAG) SI--; - else SI++; - outb(DX, temp); - CLOCK_CYCLES(14); - PREFETCH_RUN(14, 1, -1, 1,0,1,0, 0); - return 0; + SEG_CHECK_READ(cpu_state.ea_seg); + CHECK_READ(cpu_state.ea_seg, SI, SI); + temp = readmemb(cpu_state.ea_seg->base, SI); + if (cpu_state.abrt) + return 1; + check_io_perm(DX, 1); + if (cpu_state.flags & D_FLAG) + SI--; + else + SI++; + outb(DX, temp); + CLOCK_CYCLES(14); + PREFETCH_RUN(14, 1, -1, 1, 0, 1, 0, 0); + return 0; } -static int opOUTSB_a32(uint32_t fetchdat) +static int +opOUTSB_a32(uint32_t fetchdat) { - uint8_t temp; + uint8_t temp; - SEG_CHECK_READ(cpu_state.ea_seg); - CHECK_READ(cpu_state.ea_seg, ESI, ESI); - temp = readmemb(cpu_state.ea_seg->base, ESI); if (cpu_state.abrt) return 1; - check_io_perm(DX); - if (cpu_state.flags & D_FLAG) ESI--; - else ESI++; - outb(DX, temp); - CLOCK_CYCLES(14); - PREFETCH_RUN(14, 1, -1, 1,0,1,0, 1); - return 0; + SEG_CHECK_READ(cpu_state.ea_seg); + CHECK_READ(cpu_state.ea_seg, ESI, ESI); + temp = readmemb(cpu_state.ea_seg->base, ESI); + if (cpu_state.abrt) + return 1; + check_io_perm(DX, 1); + if (cpu_state.flags & D_FLAG) + ESI--; + else + ESI++; + outb(DX, temp); + CLOCK_CYCLES(14); + PREFETCH_RUN(14, 1, -1, 1, 0, 1, 0, 1); + return 0; } -static int opOUTSW_a16(uint32_t fetchdat) +static int +opOUTSW_a16(uint32_t fetchdat) { - uint16_t temp; + uint16_t temp; - SEG_CHECK_READ(cpu_state.ea_seg); - CHECK_READ(cpu_state.ea_seg, SI, SI + 1UL); - temp = readmemw(cpu_state.ea_seg->base, SI); if (cpu_state.abrt) return 1; - check_io_perm(DX); - check_io_perm(DX + 1); - if (cpu_state.flags & D_FLAG) SI -= 2; - else SI += 2; - outw(DX, temp); - CLOCK_CYCLES(14); - PREFETCH_RUN(14, 1, -1, 1,0,1,0, 0); - return 0; + SEG_CHECK_READ(cpu_state.ea_seg); + CHECK_READ(cpu_state.ea_seg, SI, SI + 1UL); + temp = readmemw(cpu_state.ea_seg->base, SI); + if (cpu_state.abrt) + return 1; + check_io_perm(DX, 2); + if (cpu_state.flags & D_FLAG) + SI -= 2; + else + SI += 2; + outw(DX, temp); + CLOCK_CYCLES(14); + PREFETCH_RUN(14, 1, -1, 1, 0, 1, 0, 0); + return 0; } -static int opOUTSW_a32(uint32_t fetchdat) +static int +opOUTSW_a32(uint32_t fetchdat) { - uint16_t temp; + uint16_t temp; - SEG_CHECK_READ(cpu_state.ea_seg); - CHECK_READ(cpu_state.ea_seg, ESI, ESI + 1UL); - temp = readmemw(cpu_state.ea_seg->base, ESI); if (cpu_state.abrt) return 1; - check_io_perm(DX); - check_io_perm(DX + 1); - if (cpu_state.flags & D_FLAG) ESI -= 2; - else ESI += 2; - outw(DX, temp); - CLOCK_CYCLES(14); - PREFETCH_RUN(14, 1, -1, 1,0,1,0, 1); - return 0; + SEG_CHECK_READ(cpu_state.ea_seg); + CHECK_READ(cpu_state.ea_seg, ESI, ESI + 1UL); + temp = readmemw(cpu_state.ea_seg->base, ESI); + if (cpu_state.abrt) + return 1; + check_io_perm(DX, 2); + if (cpu_state.flags & D_FLAG) + ESI -= 2; + else + ESI += 2; + outw(DX, temp); + CLOCK_CYCLES(14); + PREFETCH_RUN(14, 1, -1, 1, 0, 1, 0, 1); + return 0; } -static int opOUTSL_a16(uint32_t fetchdat) +static int +opOUTSL_a16(uint32_t fetchdat) { - uint32_t temp; + uint32_t temp; - SEG_CHECK_READ(cpu_state.ea_seg); - CHECK_READ(cpu_state.ea_seg, SI, SI + 3UL); - temp = readmeml(cpu_state.ea_seg->base, SI); if (cpu_state.abrt) return 1; - check_io_perm(DX); - check_io_perm(DX + 1); - check_io_perm(DX + 2); - check_io_perm(DX + 3); - if (cpu_state.flags & D_FLAG) SI -= 4; - else SI += 4; - outl(EDX, temp); - CLOCK_CYCLES(14); - PREFETCH_RUN(14, 1, -1, 0,1,0,1, 0); - return 0; + SEG_CHECK_READ(cpu_state.ea_seg); + CHECK_READ(cpu_state.ea_seg, SI, SI + 3UL); + temp = readmeml(cpu_state.ea_seg->base, SI); + if (cpu_state.abrt) + return 1; + check_io_perm(DX, 4); + if (cpu_state.flags & D_FLAG) + SI -= 4; + else + SI += 4; + outl(EDX, temp); + CLOCK_CYCLES(14); + PREFETCH_RUN(14, 1, -1, 0, 1, 0, 1, 0); + return 0; } -static int opOUTSL_a32(uint32_t fetchdat) +static int +opOUTSL_a32(uint32_t fetchdat) { - uint32_t temp; + uint32_t temp; - SEG_CHECK_READ(cpu_state.ea_seg); - CHECK_READ(cpu_state.ea_seg, ESI, ESI + 3UL); - temp = readmeml(cpu_state.ea_seg->base, ESI); if (cpu_state.abrt) return 1; - check_io_perm(DX); - check_io_perm(DX + 1); - check_io_perm(DX + 2); - check_io_perm(DX + 3); - if (cpu_state.flags & D_FLAG) ESI -= 4; - else ESI += 4; - outl(EDX, temp); - CLOCK_CYCLES(14); - PREFETCH_RUN(14, 1, -1, 0,1,0,1, 1); - return 0; + SEG_CHECK_READ(cpu_state.ea_seg); + CHECK_READ(cpu_state.ea_seg, ESI, ESI + 3UL); + temp = readmeml(cpu_state.ea_seg->base, ESI); + if (cpu_state.abrt) + return 1; + check_io_perm(DX, 4); + if (cpu_state.flags & D_FLAG) + ESI -= 4; + else + ESI += 4; + outl(EDX, temp); + CLOCK_CYCLES(14); + PREFETCH_RUN(14, 1, -1, 0, 1, 0, 1, 1); + return 0; } diff --git a/src/cpu/x86_ops_string_2386.h b/src/cpu/x86_ops_string_2386.h new file mode 100644 index 000000000..98875e54f --- /dev/null +++ b/src/cpu/x86_ops_string_2386.h @@ -0,0 +1,1061 @@ +static int +opMOVSB_a16(uint32_t fetchdat) +{ + uint8_t temp; + + addr64 = addr64_2 = 0x00000000; + + SEG_CHECK_READ(cpu_state.ea_seg); + SEG_CHECK_WRITE(&cpu_state.seg_es); + CHECK_READ(cpu_state.ea_seg, SI, SI); + CHECK_WRITE(&cpu_state.seg_es, DI, DI); + high_page = 0; + do_mmut_rb(cpu_state.ea_seg->base, SI, &addr64); + if (cpu_state.abrt) + return 1; + + do_mmut_wb(es, DI, &addr64_2); + if (cpu_state.abrt) + return 1; + temp = readmemb_n(cpu_state.ea_seg->base, SI, addr64); + if (cpu_state.abrt) + return 1; + writememb_n(es, DI, addr64_2, temp); + if (cpu_state.abrt) + return 1; + if (cpu_state.flags & D_FLAG) { + DI--; + SI--; + } else { + DI++; + SI++; + } + CLOCK_CYCLES(7); + PREFETCH_RUN(7, 1, -1, 1, 0, 1, 0, 0); + return 0; +} +static int +opMOVSB_a32(uint32_t fetchdat) +{ + uint8_t temp; + + addr64 = addr64_2 = 0x00000000; + + SEG_CHECK_READ(cpu_state.ea_seg); + SEG_CHECK_WRITE(&cpu_state.seg_es); + CHECK_READ(cpu_state.ea_seg, ESI, ESI); + CHECK_WRITE(&cpu_state.seg_es, EDI, EDI); + high_page = 0; + do_mmut_rb(cpu_state.ea_seg->base, ESI, &addr64); + if (cpu_state.abrt) + return 1; + do_mmut_wb(es, EDI, &addr64_2); + if (cpu_state.abrt) + return 1; + temp = readmemb_n(cpu_state.ea_seg->base, ESI, addr64); + if (cpu_state.abrt) + return 1; + writememb_n(es, EDI, addr64_2, temp); + if (cpu_state.abrt) + return 1; + if (cpu_state.flags & D_FLAG) { + EDI--; + ESI--; + } else { + EDI++; + ESI++; + } + CLOCK_CYCLES(7); + PREFETCH_RUN(7, 1, -1, 1, 0, 1, 0, 1); + return 0; +} + +static int +opMOVSW_a16(uint32_t fetchdat) +{ + uint16_t temp; + + addr64a[0] = addr64a[1] = 0x00000000; + addr64a_2[0] = addr64a_2[1] = 0x00000000; + + SEG_CHECK_READ(cpu_state.ea_seg); + SEG_CHECK_WRITE(&cpu_state.seg_es); + CHECK_READ(cpu_state.ea_seg, SI, SI + 1UL); + CHECK_WRITE(&cpu_state.seg_es, DI, DI + 1UL); + high_page = 0; + do_mmut_rw(cpu_state.ea_seg->base, SI, addr64a); + if (cpu_state.abrt) + return 1; + do_mmut_ww(es, DI, addr64a_2); + if (cpu_state.abrt) + return 1; + temp = readmemw_n(cpu_state.ea_seg->base, SI, addr64a); + if (cpu_state.abrt) + return 1; + writememw_n(es, DI, addr64a_2, temp); + if (cpu_state.abrt) + return 1; + if (cpu_state.flags & D_FLAG) { + DI -= 2; + SI -= 2; + } else { + DI += 2; + SI += 2; + } + CLOCK_CYCLES(7); + PREFETCH_RUN(7, 1, -1, 1, 0, 1, 0, 0); + return 0; +} +static int +opMOVSW_a32(uint32_t fetchdat) +{ + uint16_t temp; + + addr64a[0] = addr64a[1] = 0x00000000; + addr64a_2[0] = addr64a_2[1] = 0x00000000; + + SEG_CHECK_READ(cpu_state.ea_seg); + SEG_CHECK_WRITE(&cpu_state.seg_es); + CHECK_READ(cpu_state.ea_seg, ESI, ESI + 1UL); + CHECK_WRITE(&cpu_state.seg_es, EDI, EDI + 1UL); + high_page = 0; + do_mmut_rw(cpu_state.ea_seg->base, ESI, addr64a); + if (cpu_state.abrt) + return 1; + do_mmut_ww(es, EDI, addr64a_2); + if (cpu_state.abrt) + return 1; + temp = readmemw_n(cpu_state.ea_seg->base, ESI, addr64a); + if (cpu_state.abrt) + return 1; + writememw_n(es, EDI, addr64a_2, temp); + if (cpu_state.abrt) + return 1; + if (cpu_state.flags & D_FLAG) { + EDI -= 2; + ESI -= 2; + } else { + EDI += 2; + ESI += 2; + } + CLOCK_CYCLES(7); + PREFETCH_RUN(7, 1, -1, 1, 0, 1, 0, 1); + return 0; +} + +static int +opMOVSL_a16(uint32_t fetchdat) +{ + uint32_t temp; + + addr64a[0] = addr64a[1] = addr64a[2] = addr64a[3] = 0x00000000; + addr64a_2[0] = addr64a_2[1] = addr64a_2[2] = addr64a_2[3] = 0x00000000; + + SEG_CHECK_READ(cpu_state.ea_seg); + SEG_CHECK_WRITE(&cpu_state.seg_es); + CHECK_READ(cpu_state.ea_seg, SI, SI + 3UL); + CHECK_WRITE(&cpu_state.seg_es, DI, DI + 3UL); + high_page = 0; + do_mmut_rl(cpu_state.ea_seg->base, SI, addr64a); + if (cpu_state.abrt) + return 1; + do_mmut_wl(es, DI, addr64a_2); + if (cpu_state.abrt) + return 1; + temp = readmeml_n(cpu_state.ea_seg->base, SI, addr64a); + if (cpu_state.abrt) + return 1; + writememl_n(es, DI, addr64a_2, temp); + if (cpu_state.abrt) + return 1; + if (cpu_state.flags & D_FLAG) { + DI -= 4; + SI -= 4; + } else { + DI += 4; + SI += 4; + } + CLOCK_CYCLES(7); + PREFETCH_RUN(7, 1, -1, 0, 1, 0, 1, 0); + return 0; +} +static int +opMOVSL_a32(uint32_t fetchdat) +{ + uint32_t temp; + + addr64a[0] = addr64a[1] = addr64a[2] = addr64a[3] = 0x00000000; + addr64a_2[0] = addr64a_2[1] = addr64a_2[2] = addr64a_2[3] = 0x00000000; + + SEG_CHECK_READ(cpu_state.ea_seg); + SEG_CHECK_WRITE(&cpu_state.seg_es); + CHECK_READ(cpu_state.ea_seg, ESI, ESI + 3UL); + CHECK_WRITE(&cpu_state.seg_es, EDI, EDI + 3UL); + high_page = 0; + do_mmut_rl(cpu_state.ea_seg->base, ESI, addr64a); + if (cpu_state.abrt) + return 1; + do_mmut_wl(es, EDI, addr64a_2); + if (cpu_state.abrt) + return 1; + temp = readmeml_n(cpu_state.ea_seg->base, ESI, addr64a); + if (cpu_state.abrt) + return 1; + writememl_n(es, EDI, addr64a_2, temp); + if (cpu_state.abrt) + return 1; + if (cpu_state.flags & D_FLAG) { + EDI -= 4; + ESI -= 4; + } else { + EDI += 4; + ESI += 4; + } + CLOCK_CYCLES(7); + PREFETCH_RUN(7, 1, -1, 0, 1, 0, 1, 1); + return 0; +} + +static int +opCMPSB_a16(uint32_t fetchdat) +{ + uint8_t src; + uint8_t dst; + + addr64 = addr64_2 = 0x00000000; + + SEG_CHECK_READ(cpu_state.ea_seg); + SEG_CHECK_READ(&cpu_state.seg_es); + CHECK_READ(cpu_state.ea_seg, SI, SI); + CHECK_READ(&cpu_state.seg_es, DI, DI); + high_page = uncached = 0; + do_mmut_rb(cpu_state.ea_seg->base, SI, &addr64); + if (cpu_state.abrt) + return 1; + do_mmut_rb2(es, DI, &addr64_2); + if (cpu_state.abrt) + return 1; + src = readmemb_n(cpu_state.ea_seg->base, SI, addr64); + if (cpu_state.abrt) + return 1; + dst = readmemb_n(es, DI, addr64_2); + if (cpu_state.abrt) + return 1; + setsub8(src, dst); + if (cpu_state.flags & D_FLAG) { + DI--; + SI--; + } else { + DI++; + SI++; + } + CLOCK_CYCLES((is486) ? 8 : 10); + PREFETCH_RUN((is486) ? 8 : 10, 1, -1, 2, 0, 0, 0, 0); + return 0; +} +static int +opCMPSB_a32(uint32_t fetchdat) +{ + uint8_t src; + uint8_t dst; + + addr64 = addr64_2 = 0x00000000; + + SEG_CHECK_READ(cpu_state.ea_seg); + SEG_CHECK_READ(&cpu_state.seg_es); + CHECK_READ(cpu_state.ea_seg, ESI, ESI); + CHECK_READ(&cpu_state.seg_es, EDI, EDI); + high_page = uncached = 0; + do_mmut_rb(cpu_state.ea_seg->base, ESI, &addr64); + if (cpu_state.abrt) + return 1; + do_mmut_rb2(es, EDI, &addr64_2); + if (cpu_state.abrt) + return 1; + src = readmemb_n(cpu_state.ea_seg->base, ESI, addr64); + if (cpu_state.abrt) + return 1; + dst = readmemb_n(es, EDI, addr64_2); + if (cpu_state.abrt) + return 1; + setsub8(src, dst); + if (cpu_state.flags & D_FLAG) { + EDI--; + ESI--; + } else { + EDI++; + ESI++; + } + CLOCK_CYCLES((is486) ? 8 : 10); + PREFETCH_RUN((is486) ? 8 : 10, 1, -1, 2, 0, 0, 0, 1); + return 0; +} + +static int +opCMPSW_a16(uint32_t fetchdat) +{ + uint16_t src; + uint16_t dst; + + addr64a[0] = addr64a[1] = 0x00000000; + addr64a_2[0] = addr64a_2[1] = 0x00000000; + + SEG_CHECK_READ(cpu_state.ea_seg); + SEG_CHECK_READ(&cpu_state.seg_es); + CHECK_READ(cpu_state.ea_seg, SI, SI + 1UL); + CHECK_READ(&cpu_state.seg_es, DI, DI + 1UL); + high_page = uncached = 0; + do_mmut_rw(cpu_state.ea_seg->base, SI, addr64a); + if (cpu_state.abrt) + return 1; + do_mmut_rw2(es, DI, addr64a_2); + if (cpu_state.abrt) + return 1; + src = readmemw_n(cpu_state.ea_seg->base, SI, addr64a); + if (cpu_state.abrt) + return 1; + dst = readmemw_n(es, DI, addr64a_2); + if (cpu_state.abrt) + return 1; + setsub16(src, dst); + if (cpu_state.flags & D_FLAG) { + DI -= 2; + SI -= 2; + } else { + DI += 2; + SI += 2; + } + CLOCK_CYCLES((is486) ? 8 : 10); + PREFETCH_RUN((is486) ? 8 : 10, 1, -1, 2, 0, 0, 0, 0); + return 0; +} +static int +opCMPSW_a32(uint32_t fetchdat) +{ + uint16_t src; + uint16_t dst; + + addr64a[0] = addr64a[1] = 0x00000000; + addr64a_2[0] = addr64a_2[1] = 0x00000000; + + SEG_CHECK_READ(cpu_state.ea_seg); + SEG_CHECK_READ(&cpu_state.seg_es); + CHECK_READ(cpu_state.ea_seg, ESI, ESI + 1UL); + CHECK_READ(&cpu_state.seg_es, EDI, EDI + 1UL); + high_page = uncached = 0; + do_mmut_rw(cpu_state.ea_seg->base, ESI, addr64a); + if (cpu_state.abrt) + return 1; + do_mmut_rw2(es, EDI, addr64a_2); + if (cpu_state.abrt) + return 1; + src = readmemw_n(cpu_state.ea_seg->base, ESI, addr64a); + if (cpu_state.abrt) + return 1; + dst = readmemw_n(es, EDI, addr64a_2); + if (cpu_state.abrt) + return 1; + setsub16(src, dst); + if (cpu_state.flags & D_FLAG) { + EDI -= 2; + ESI -= 2; + } else { + EDI += 2; + ESI += 2; + } + CLOCK_CYCLES((is486) ? 8 : 10); + PREFETCH_RUN((is486) ? 8 : 10, 1, -1, 2, 0, 0, 0, 1); + return 0; +} + +static int +opCMPSL_a16(uint32_t fetchdat) +{ + uint32_t src; + uint32_t dst; + + addr64a[0] = addr64a[1] = addr64a[2] = addr64a[3] = 0x00000000; + addr64a_2[0] = addr64a_2[1] = addr64a_2[2] = addr64a_2[3] = 0x00000000; + + SEG_CHECK_READ(cpu_state.ea_seg); + SEG_CHECK_READ(&cpu_state.seg_es); + CHECK_READ(cpu_state.ea_seg, SI, SI + 3UL); + CHECK_READ(&cpu_state.seg_es, DI, DI + 3UL); + high_page = uncached = 0; + do_mmut_rl(cpu_state.ea_seg->base, SI, addr64a); + if (cpu_state.abrt) + return 1; + do_mmut_rl2(es, DI, addr64a_2); + if (cpu_state.abrt) + return 1; + src = readmeml_n(cpu_state.ea_seg->base, SI, addr64a); + if (cpu_state.abrt) + return 1; + dst = readmeml_n(es, DI, addr64a_2); + if (cpu_state.abrt) + return 1; + setsub32(src, dst); + if (cpu_state.flags & D_FLAG) { + DI -= 4; + SI -= 4; + } else { + DI += 4; + SI += 4; + } + CLOCK_CYCLES((is486) ? 8 : 10); + PREFETCH_RUN((is486) ? 8 : 10, 1, -1, 0, 2, 0, 0, 0); + return 0; +} +static int +opCMPSL_a32(uint32_t fetchdat) +{ + uint32_t src; + uint32_t dst; + + addr64a[0] = addr64a[1] = addr64a[2] = addr64a[3] = 0x00000000; + addr64a_2[0] = addr64a_2[1] = addr64a_2[2] = addr64a_2[3] = 0x00000000; + + SEG_CHECK_READ(cpu_state.ea_seg); + SEG_CHECK_READ(&cpu_state.seg_es); + CHECK_READ(cpu_state.ea_seg, ESI, ESI + 3UL); + CHECK_READ(&cpu_state.seg_es, EDI, EDI + 3UL); + high_page = uncached = 0; + do_mmut_rl(cpu_state.ea_seg->base, ESI, addr64a); + if (cpu_state.abrt) + return 1; + do_mmut_rl2(es, EDI, addr64a_2); + if (cpu_state.abrt) + return 1; + src = readmeml_n(cpu_state.ea_seg->base, ESI, addr64a); + if (cpu_state.abrt) + return 1; + dst = readmeml_n(es, EDI, addr64a_2); + if (cpu_state.abrt) + return 1; + setsub32(src, dst); + if (cpu_state.flags & D_FLAG) { + EDI -= 4; + ESI -= 4; + } else { + EDI += 4; + ESI += 4; + } + CLOCK_CYCLES((is486) ? 8 : 10); + PREFETCH_RUN((is486) ? 8 : 10, 1, -1, 0, 2, 0, 0, 1); + return 0; +} + +static int +opSTOSB_a16(uint32_t fetchdat) +{ + SEG_CHECK_WRITE(&cpu_state.seg_es); + CHECK_WRITE(&cpu_state.seg_es, DI, DI); + writememb(es, DI, AL); + if (cpu_state.abrt) + return 1; + if (cpu_state.flags & D_FLAG) + DI--; + else + DI++; + CLOCK_CYCLES(4); + PREFETCH_RUN(4, 1, -1, 0, 0, 1, 0, 0); + return 0; +} +static int +opSTOSB_a32(uint32_t fetchdat) +{ + SEG_CHECK_WRITE(&cpu_state.seg_es); + CHECK_WRITE(&cpu_state.seg_es, EDI, EDI); + writememb(es, EDI, AL); + if (cpu_state.abrt) + return 1; + if (cpu_state.flags & D_FLAG) + EDI--; + else + EDI++; + CLOCK_CYCLES(4); + PREFETCH_RUN(4, 1, -1, 0, 0, 1, 0, 1); + return 0; +} + +static int +opSTOSW_a16(uint32_t fetchdat) +{ + SEG_CHECK_WRITE(&cpu_state.seg_es); + CHECK_WRITE(&cpu_state.seg_es, DI, DI + 1UL); + writememw(es, DI, AX); + if (cpu_state.abrt) + return 1; + if (cpu_state.flags & D_FLAG) + DI -= 2; + else + DI += 2; + CLOCK_CYCLES(4); + PREFETCH_RUN(4, 1, -1, 0, 0, 1, 0, 0); + return 0; +} +static int +opSTOSW_a32(uint32_t fetchdat) +{ + SEG_CHECK_WRITE(&cpu_state.seg_es); + CHECK_WRITE(&cpu_state.seg_es, EDI, EDI + 1UL); + writememw(es, EDI, AX); + if (cpu_state.abrt) + return 1; + if (cpu_state.flags & D_FLAG) + EDI -= 2; + else + EDI += 2; + CLOCK_CYCLES(4); + PREFETCH_RUN(4, 1, -1, 0, 0, 1, 0, 1); + return 0; +} + +static int +opSTOSL_a16(uint32_t fetchdat) +{ + SEG_CHECK_WRITE(&cpu_state.seg_es); + CHECK_WRITE(&cpu_state.seg_es, DI, DI + 3UL); + writememl(es, DI, EAX); + if (cpu_state.abrt) + return 1; + if (cpu_state.flags & D_FLAG) + DI -= 4; + else + DI += 4; + CLOCK_CYCLES(4); + PREFETCH_RUN(4, 1, -1, 0, 0, 0, 1, 0); + return 0; +} +static int +opSTOSL_a32(uint32_t fetchdat) +{ + SEG_CHECK_WRITE(&cpu_state.seg_es); + CHECK_WRITE(&cpu_state.seg_es, EDI, EDI + 3UL); + writememl(es, EDI, EAX); + if (cpu_state.abrt) + return 1; + if (cpu_state.flags & D_FLAG) + EDI -= 4; + else + EDI += 4; + CLOCK_CYCLES(4); + PREFETCH_RUN(4, 1, -1, 0, 0, 0, 1, 1); + return 0; +} + +static int +opLODSB_a16(uint32_t fetchdat) +{ + uint8_t temp; + + SEG_CHECK_READ(cpu_state.ea_seg); + CHECK_READ(cpu_state.ea_seg, SI, SI); + temp = readmemb(cpu_state.ea_seg->base, SI); + if (cpu_state.abrt) + return 1; + AL = temp; + if (cpu_state.flags & D_FLAG) + SI--; + else + SI++; + CLOCK_CYCLES(5); + PREFETCH_RUN(5, 1, -1, 1, 0, 0, 0, 0); + return 0; +} +static int +opLODSB_a32(uint32_t fetchdat) +{ + uint8_t temp; + + SEG_CHECK_READ(cpu_state.ea_seg); + CHECK_READ(cpu_state.ea_seg, ESI, ESI); + temp = readmemb(cpu_state.ea_seg->base, ESI); + if (cpu_state.abrt) + return 1; + AL = temp; + if (cpu_state.flags & D_FLAG) + ESI--; + else + ESI++; + CLOCK_CYCLES(5); + PREFETCH_RUN(5, 1, -1, 1, 0, 0, 0, 1); + return 0; +} + +static int +opLODSW_a16(uint32_t fetchdat) +{ + uint16_t temp; + + SEG_CHECK_READ(cpu_state.ea_seg); + CHECK_READ(cpu_state.ea_seg, SI, SI + 1UL); + temp = readmemw(cpu_state.ea_seg->base, SI); + if (cpu_state.abrt) + return 1; + AX = temp; + if (cpu_state.flags & D_FLAG) + SI -= 2; + else + SI += 2; + CLOCK_CYCLES(5); + PREFETCH_RUN(5, 1, -1, 1, 0, 0, 0, 0); + return 0; +} +static int +opLODSW_a32(uint32_t fetchdat) +{ + uint16_t temp; + + SEG_CHECK_READ(cpu_state.ea_seg); + CHECK_READ(cpu_state.ea_seg, ESI, ESI + 1UL); + temp = readmemw(cpu_state.ea_seg->base, ESI); + if (cpu_state.abrt) + return 1; + AX = temp; + if (cpu_state.flags & D_FLAG) + ESI -= 2; + else + ESI += 2; + CLOCK_CYCLES(5); + PREFETCH_RUN(5, 1, -1, 1, 0, 0, 0, 1); + return 0; +} + +static int +opLODSL_a16(uint32_t fetchdat) +{ + uint32_t temp; + + SEG_CHECK_READ(cpu_state.ea_seg); + CHECK_READ(cpu_state.ea_seg, SI, SI + 3UL); + temp = readmeml(cpu_state.ea_seg->base, SI); + if (cpu_state.abrt) + return 1; + EAX = temp; + if (cpu_state.flags & D_FLAG) + SI -= 4; + else + SI += 4; + CLOCK_CYCLES(5); + PREFETCH_RUN(5, 1, -1, 0, 1, 0, 0, 0); + return 0; +} +static int +opLODSL_a32(uint32_t fetchdat) +{ + uint32_t temp; + + SEG_CHECK_READ(cpu_state.ea_seg); + CHECK_READ(cpu_state.ea_seg, ESI, ESI + 3UL); + temp = readmeml(cpu_state.ea_seg->base, ESI); + if (cpu_state.abrt) + return 1; + EAX = temp; + if (cpu_state.flags & D_FLAG) + ESI -= 4; + else + ESI += 4; + CLOCK_CYCLES(5); + PREFETCH_RUN(5, 1, -1, 0, 1, 0, 0, 1); + return 0; +} + +static int +opSCASB_a16(uint32_t fetchdat) +{ + uint8_t temp; + + SEG_CHECK_READ(&cpu_state.seg_es); + CHECK_READ(&cpu_state.seg_es, DI, DI); + temp = readmemb(es, DI); + if (cpu_state.abrt) + return 1; + setsub8(AL, temp); + if (cpu_state.flags & D_FLAG) + DI--; + else + DI++; + CLOCK_CYCLES(7); + PREFETCH_RUN(7, 1, -1, 1, 0, 0, 0, 0); + return 0; +} +static int +opSCASB_a32(uint32_t fetchdat) +{ + uint8_t temp; + + SEG_CHECK_READ(&cpu_state.seg_es); + CHECK_READ(&cpu_state.seg_es, EDI, EDI); + temp = readmemb(es, EDI); + if (cpu_state.abrt) + return 1; + setsub8(AL, temp); + if (cpu_state.flags & D_FLAG) + EDI--; + else + EDI++; + CLOCK_CYCLES(7); + PREFETCH_RUN(7, 1, -1, 1, 0, 0, 0, 1); + return 0; +} + +static int +opSCASW_a16(uint32_t fetchdat) +{ + uint16_t temp; + + SEG_CHECK_READ(&cpu_state.seg_es); + CHECK_READ(&cpu_state.seg_es, DI, DI + 1UL); + temp = readmemw(es, DI); + if (cpu_state.abrt) + return 1; + setsub16(AX, temp); + if (cpu_state.flags & D_FLAG) + DI -= 2; + else + DI += 2; + CLOCK_CYCLES(7); + PREFETCH_RUN(7, 1, -1, 1, 0, 0, 0, 0); + return 0; +} +static int +opSCASW_a32(uint32_t fetchdat) +{ + uint16_t temp; + + SEG_CHECK_READ(&cpu_state.seg_es); + CHECK_READ(&cpu_state.seg_es, EDI, EDI + 1UL); + temp = readmemw(es, EDI); + if (cpu_state.abrt) + return 1; + setsub16(AX, temp); + if (cpu_state.flags & D_FLAG) + EDI -= 2; + else + EDI += 2; + CLOCK_CYCLES(7); + PREFETCH_RUN(7, 1, -1, 1, 0, 0, 0, 1); + return 0; +} + +static int +opSCASL_a16(uint32_t fetchdat) +{ + uint32_t temp; + + SEG_CHECK_READ(&cpu_state.seg_es); + CHECK_READ(&cpu_state.seg_es, DI, DI + 3UL); + temp = readmeml(es, DI); + if (cpu_state.abrt) + return 1; + setsub32(EAX, temp); + if (cpu_state.flags & D_FLAG) + DI -= 4; + else + DI += 4; + CLOCK_CYCLES(7); + PREFETCH_RUN(7, 1, -1, 0, 1, 0, 0, 0); + return 0; +} +static int +opSCASL_a32(uint32_t fetchdat) +{ + uint32_t temp; + + SEG_CHECK_READ(&cpu_state.seg_es); + CHECK_READ(&cpu_state.seg_es, EDI, EDI + 3UL); + temp = readmeml(es, EDI); + if (cpu_state.abrt) + return 1; + setsub32(EAX, temp); + if (cpu_state.flags & D_FLAG) + EDI -= 4; + else + EDI += 4; + CLOCK_CYCLES(7); + PREFETCH_RUN(7, 1, -1, 0, 1, 0, 0, 1); + return 0; +} + +static int +opINSB_a16(uint32_t fetchdat) +{ + uint8_t temp; + + addr64 = 0x00000000; + + SEG_CHECK_WRITE(&cpu_state.seg_es); + check_io_perm(DX, 1); + CHECK_WRITE(&cpu_state.seg_es, DI, DI); + high_page = 0; + do_mmut_wb(es, DI, &addr64); + if (cpu_state.abrt) + return 1; + temp = inb(DX); + writememb_n(es, DI, addr64, temp); + if (cpu_state.abrt) + return 1; + if (cpu_state.flags & D_FLAG) + DI--; + else + DI++; + CLOCK_CYCLES(15); + PREFETCH_RUN(15, 1, -1, 1, 0, 1, 0, 0); + return 0; +} +static int +opINSB_a32(uint32_t fetchdat) +{ + uint8_t temp; + + addr64 = 0x00000000; + + SEG_CHECK_WRITE(&cpu_state.seg_es); + check_io_perm(DX, 1); + high_page = 0; + CHECK_WRITE(&cpu_state.seg_es, EDI, EDI); + do_mmut_wb(es, EDI, &addr64); + if (cpu_state.abrt) + return 1; + temp = inb(DX); + writememb_n(es, EDI, addr64, temp); + if (cpu_state.abrt) + return 1; + if (cpu_state.flags & D_FLAG) + EDI--; + else + EDI++; + CLOCK_CYCLES(15); + PREFETCH_RUN(15, 1, -1, 1, 0, 1, 0, 1); + return 0; +} + +static int +opINSW_a16(uint32_t fetchdat) +{ + uint16_t temp; + + addr64a[0] = addr64a[1] = 0x00000000; + + SEG_CHECK_WRITE(&cpu_state.seg_es); + check_io_perm(DX, 2); + CHECK_WRITE(&cpu_state.seg_es, DI, DI + 1UL); + high_page = 0; + do_mmut_ww(es, DI, addr64a); + if (cpu_state.abrt) + return 1; + temp = inw(DX); + writememw_n(es, DI, addr64a, temp); + if (cpu_state.abrt) + return 1; + if (cpu_state.flags & D_FLAG) + DI -= 2; + else + DI += 2; + CLOCK_CYCLES(15); + PREFETCH_RUN(15, 1, -1, 1, 0, 1, 0, 0); + return 0; +} +static int +opINSW_a32(uint32_t fetchdat) +{ + uint16_t temp; + + addr64a[0] = addr64a[1] = 0x00000000; + + SEG_CHECK_WRITE(&cpu_state.seg_es); + high_page = 0; + check_io_perm(DX, 2); + CHECK_WRITE(&cpu_state.seg_es, EDI, EDI + 1UL); + do_mmut_ww(es, EDI, addr64a); + if (cpu_state.abrt) + return 1; + temp = inw(DX); + writememw_n(es, EDI, addr64a, temp); + if (cpu_state.abrt) + return 1; + if (cpu_state.flags & D_FLAG) + EDI -= 2; + else + EDI += 2; + CLOCK_CYCLES(15); + PREFETCH_RUN(15, 1, -1, 1, 0, 1, 0, 1); + return 0; +} + +static int +opINSL_a16(uint32_t fetchdat) +{ + uint32_t temp; + + addr64a[0] = addr64a[1] = addr64a[2] = addr64a[3] = 0x00000000; + + SEG_CHECK_WRITE(&cpu_state.seg_es); + check_io_perm(DX, 4); + CHECK_WRITE(&cpu_state.seg_es, DI, DI + 3UL); + high_page = 0; + do_mmut_wl(es, DI, addr64a); + if (cpu_state.abrt) + return 1; + temp = inl(DX); + writememl_n(es, DI, addr64a, temp); + if (cpu_state.abrt) + return 1; + if (cpu_state.flags & D_FLAG) + DI -= 4; + else + DI += 4; + CLOCK_CYCLES(15); + PREFETCH_RUN(15, 1, -1, 0, 1, 0, 1, 0); + return 0; +} +static int +opINSL_a32(uint32_t fetchdat) +{ + uint32_t temp; + + addr64a[0] = addr64a[1] = addr64a[2] = addr64a[3] = 0x00000000; + + SEG_CHECK_WRITE(&cpu_state.seg_es); + check_io_perm(DX, 4); + CHECK_WRITE(&cpu_state.seg_es, EDI, EDI + 3UL); + high_page = 0; + do_mmut_wl(es, DI, addr64a); + if (cpu_state.abrt) + return 1; + temp = inl(DX); + writememl_n(es, EDI, addr64a, temp); + if (cpu_state.abrt) + return 1; + if (cpu_state.flags & D_FLAG) + EDI -= 4; + else + EDI += 4; + CLOCK_CYCLES(15); + PREFETCH_RUN(15, 1, -1, 0, 1, 0, 1, 1); + return 0; +} + +static int +opOUTSB_a16(uint32_t fetchdat) +{ + uint8_t temp; + + SEG_CHECK_READ(cpu_state.ea_seg); + CHECK_READ(cpu_state.ea_seg, SI, SI); + temp = readmemb(cpu_state.ea_seg->base, SI); + if (cpu_state.abrt) + return 1; + check_io_perm(DX, 1); + if (cpu_state.flags & D_FLAG) + SI--; + else + SI++; + outb(DX, temp); + CLOCK_CYCLES(14); + PREFETCH_RUN(14, 1, -1, 1, 0, 1, 0, 0); + return 0; +} +static int +opOUTSB_a32(uint32_t fetchdat) +{ + uint8_t temp; + + SEG_CHECK_READ(cpu_state.ea_seg); + CHECK_READ(cpu_state.ea_seg, ESI, ESI); + temp = readmemb(cpu_state.ea_seg->base, ESI); + if (cpu_state.abrt) + return 1; + check_io_perm(DX, 1); + if (cpu_state.flags & D_FLAG) + ESI--; + else + ESI++; + outb(DX, temp); + CLOCK_CYCLES(14); + PREFETCH_RUN(14, 1, -1, 1, 0, 1, 0, 1); + return 0; +} + +static int +opOUTSW_a16(uint32_t fetchdat) +{ + uint16_t temp; + + SEG_CHECK_READ(cpu_state.ea_seg); + CHECK_READ(cpu_state.ea_seg, SI, SI + 1UL); + temp = readmemw(cpu_state.ea_seg->base, SI); + if (cpu_state.abrt) + return 1; + check_io_perm(DX, 2); + if (cpu_state.flags & D_FLAG) + SI -= 2; + else + SI += 2; + outw(DX, temp); + CLOCK_CYCLES(14); + PREFETCH_RUN(14, 1, -1, 1, 0, 1, 0, 0); + return 0; +} +static int +opOUTSW_a32(uint32_t fetchdat) +{ + uint16_t temp; + + SEG_CHECK_READ(cpu_state.ea_seg); + CHECK_READ(cpu_state.ea_seg, ESI, ESI + 1UL); + temp = readmemw(cpu_state.ea_seg->base, ESI); + if (cpu_state.abrt) + return 1; + check_io_perm(DX, 2); + if (cpu_state.flags & D_FLAG) + ESI -= 2; + else + ESI += 2; + outw(DX, temp); + CLOCK_CYCLES(14); + PREFETCH_RUN(14, 1, -1, 1, 0, 1, 0, 1); + return 0; +} + +static int +opOUTSL_a16(uint32_t fetchdat) +{ + uint32_t temp; + + SEG_CHECK_READ(cpu_state.ea_seg); + CHECK_READ(cpu_state.ea_seg, SI, SI + 3UL); + temp = readmeml(cpu_state.ea_seg->base, SI); + if (cpu_state.abrt) + return 1; + check_io_perm(DX, 4); + if (cpu_state.flags & D_FLAG) + SI -= 4; + else + SI += 4; + outl(EDX, temp); + CLOCK_CYCLES(14); + PREFETCH_RUN(14, 1, -1, 0, 1, 0, 1, 0); + return 0; +} +static int +opOUTSL_a32(uint32_t fetchdat) +{ + uint32_t temp; + + SEG_CHECK_READ(cpu_state.ea_seg); + CHECK_READ(cpu_state.ea_seg, ESI, ESI + 3UL); + temp = readmeml(cpu_state.ea_seg->base, ESI); + if (cpu_state.abrt) + return 1; + check_io_perm(DX, 4); + if (cpu_state.flags & D_FLAG) + ESI -= 4; + else + ESI += 4; + outl(EDX, temp); + CLOCK_CYCLES(14); + PREFETCH_RUN(14, 1, -1, 0, 1, 0, 1, 1); + return 0; +} diff --git a/src/cpu/x86_ops_xchg.h b/src/cpu/x86_ops_xchg.h index 6a787273e..70e7be58c 100644 --- a/src/cpu/x86_ops_xchg.h +++ b/src/cpu/x86_ops_xchg.h @@ -1,229 +1,272 @@ -static int opXCHG_b_a16(uint32_t fetchdat) +static int +opXCHG_b_a16(uint32_t fetchdat) { - uint8_t temp; - - fetch_ea_16(fetchdat); - if (cpu_mod != 3) - SEG_CHECK_WRITE(cpu_state.ea_seg); - temp = geteab(); if (cpu_state.abrt) return 1; - seteab(getr8(cpu_reg)); if (cpu_state.abrt) return 1; - setr8(cpu_reg, temp); - CLOCK_CYCLES((cpu_mod == 3) ? 3 : 5); - PREFETCH_RUN((cpu_mod == 3) ? 3 : 5, 2, rmdat, (cpu_mod == 3) ? 0:1,0,(cpu_mod == 3) ? 0:1,0, 0); - return 0; -} -static int opXCHG_b_a32(uint32_t fetchdat) -{ - uint8_t temp; + uint8_t temp; - fetch_ea_32(fetchdat); - if (cpu_mod != 3) - SEG_CHECK_WRITE(cpu_state.ea_seg); - temp = geteab(); if (cpu_state.abrt) return 1; - seteab(getr8(cpu_reg)); if (cpu_state.abrt) return 1; - setr8(cpu_reg, temp); - CLOCK_CYCLES((cpu_mod == 3) ? 3 : 5); - PREFETCH_RUN((cpu_mod == 3) ? 3 : 5, 2, rmdat, (cpu_mod == 3) ? 0:1,0,(cpu_mod == 3) ? 0:1,0, 1); - return 0; + fetch_ea_16(fetchdat); + if (cpu_mod != 3) + SEG_CHECK_WRITE(cpu_state.ea_seg); + temp = geteab(); + if (cpu_state.abrt) + return 1; + seteab(getr8(cpu_reg)); + if (cpu_state.abrt) + return 1; + setr8(cpu_reg, temp); + CLOCK_CYCLES((cpu_mod == 3) ? 3 : 5); + PREFETCH_RUN((cpu_mod == 3) ? 3 : 5, 2, rmdat, (cpu_mod == 3) ? 0 : 1, 0, (cpu_mod == 3) ? 0 : 1, 0, 0); + return 0; +} +static int +opXCHG_b_a32(uint32_t fetchdat) +{ + uint8_t temp; + + fetch_ea_32(fetchdat); + if (cpu_mod != 3) + SEG_CHECK_WRITE(cpu_state.ea_seg); + temp = geteab(); + if (cpu_state.abrt) + return 1; + seteab(getr8(cpu_reg)); + if (cpu_state.abrt) + return 1; + setr8(cpu_reg, temp); + CLOCK_CYCLES((cpu_mod == 3) ? 3 : 5); + PREFETCH_RUN((cpu_mod == 3) ? 3 : 5, 2, rmdat, (cpu_mod == 3) ? 0 : 1, 0, (cpu_mod == 3) ? 0 : 1, 0, 1); + return 0; } -static int opXCHG_w_a16(uint32_t fetchdat) +static int +opXCHG_w_a16(uint32_t fetchdat) { - uint16_t temp; + uint16_t temp; - fetch_ea_16(fetchdat); - if (cpu_mod != 3) - SEG_CHECK_WRITE(cpu_state.ea_seg); - temp = geteaw(); if (cpu_state.abrt) return 1; - seteaw(cpu_state.regs[cpu_reg].w); if (cpu_state.abrt) return 1; - cpu_state.regs[cpu_reg].w = temp; - CLOCK_CYCLES((cpu_mod == 3) ? 3 : 5); - PREFETCH_RUN((cpu_mod == 3) ? 3 : 5, 2, rmdat, (cpu_mod == 3) ? 0:1,0,(cpu_mod == 3) ? 0:1,0, 0); - return 0; + fetch_ea_16(fetchdat); + if (cpu_mod != 3) + SEG_CHECK_WRITE(cpu_state.ea_seg); + temp = geteaw(); + if (cpu_state.abrt) + return 1; + seteaw(cpu_state.regs[cpu_reg].w); + if (cpu_state.abrt) + return 1; + cpu_state.regs[cpu_reg].w = temp; + CLOCK_CYCLES((cpu_mod == 3) ? 3 : 5); + PREFETCH_RUN((cpu_mod == 3) ? 3 : 5, 2, rmdat, (cpu_mod == 3) ? 0 : 1, 0, (cpu_mod == 3) ? 0 : 1, 0, 0); + return 0; } -static int opXCHG_w_a32(uint32_t fetchdat) +static int +opXCHG_w_a32(uint32_t fetchdat) { - uint16_t temp; + uint16_t temp; - fetch_ea_32(fetchdat); - if (cpu_mod != 3) - SEG_CHECK_WRITE(cpu_state.ea_seg); - temp = geteaw(); if (cpu_state.abrt) return 1; - seteaw(cpu_state.regs[cpu_reg].w); if (cpu_state.abrt) return 1; - cpu_state.regs[cpu_reg].w = temp; - CLOCK_CYCLES((cpu_mod == 3) ? 3 : 5); - PREFETCH_RUN((cpu_mod == 3) ? 3 : 5, 2, rmdat, (cpu_mod == 3) ? 0:1,0,(cpu_mod == 3) ? 0:1,0, 1); - return 0; + fetch_ea_32(fetchdat); + if (cpu_mod != 3) + SEG_CHECK_WRITE(cpu_state.ea_seg); + temp = geteaw(); + if (cpu_state.abrt) + return 1; + seteaw(cpu_state.regs[cpu_reg].w); + if (cpu_state.abrt) + return 1; + cpu_state.regs[cpu_reg].w = temp; + CLOCK_CYCLES((cpu_mod == 3) ? 3 : 5); + PREFETCH_RUN((cpu_mod == 3) ? 3 : 5, 2, rmdat, (cpu_mod == 3) ? 0 : 1, 0, (cpu_mod == 3) ? 0 : 1, 0, 1); + return 0; } -static int opXCHG_l_a16(uint32_t fetchdat) +static int +opXCHG_l_a16(uint32_t fetchdat) { - uint32_t temp; + uint32_t temp; - fetch_ea_16(fetchdat); - if (cpu_mod != 3) - SEG_CHECK_WRITE(cpu_state.ea_seg); - temp = geteal(); if (cpu_state.abrt) return 1; - seteal(cpu_state.regs[cpu_reg].l); if (cpu_state.abrt) return 1; - cpu_state.regs[cpu_reg].l = temp; - CLOCK_CYCLES((cpu_mod == 3) ? 3 : 5); - PREFETCH_RUN((cpu_mod == 3) ? 3 : 5, 2, rmdat, 0,(cpu_mod == 3) ? 0:1,0,(cpu_mod == 3) ? 0:1, 0); - return 0; + fetch_ea_16(fetchdat); + if (cpu_mod != 3) + SEG_CHECK_WRITE(cpu_state.ea_seg); + temp = geteal(); + if (cpu_state.abrt) + return 1; + seteal(cpu_state.regs[cpu_reg].l); + if (cpu_state.abrt) + return 1; + cpu_state.regs[cpu_reg].l = temp; + CLOCK_CYCLES((cpu_mod == 3) ? 3 : 5); + PREFETCH_RUN((cpu_mod == 3) ? 3 : 5, 2, rmdat, 0, (cpu_mod == 3) ? 0 : 1, 0, (cpu_mod == 3) ? 0 : 1, 0); + return 0; } -static int opXCHG_l_a32(uint32_t fetchdat) +static int +opXCHG_l_a32(uint32_t fetchdat) { - uint32_t temp; + uint32_t temp; - fetch_ea_32(fetchdat); - if (cpu_mod != 3) - SEG_CHECK_WRITE(cpu_state.ea_seg); - temp = geteal(); if (cpu_state.abrt) return 1; - seteal(cpu_state.regs[cpu_reg].l); if (cpu_state.abrt) return 1; - cpu_state.regs[cpu_reg].l = temp; - CLOCK_CYCLES((cpu_mod == 3) ? 3 : 5); - PREFETCH_RUN((cpu_mod == 3) ? 3 : 5, 2, rmdat, 0,(cpu_mod == 3) ? 0:1,0,(cpu_mod == 3) ? 0:1, 1); - return 0; + fetch_ea_32(fetchdat); + if (cpu_mod != 3) + SEG_CHECK_WRITE(cpu_state.ea_seg); + temp = geteal(); + if (cpu_state.abrt) + return 1; + seteal(cpu_state.regs[cpu_reg].l); + if (cpu_state.abrt) + return 1; + cpu_state.regs[cpu_reg].l = temp; + CLOCK_CYCLES((cpu_mod == 3) ? 3 : 5); + PREFETCH_RUN((cpu_mod == 3) ? 3 : 5, 2, rmdat, 0, (cpu_mod == 3) ? 0 : 1, 0, (cpu_mod == 3) ? 0 : 1, 1); + return 0; } - -static int opXCHG_AX_BX(uint32_t fetchdat) +static int +opXCHG_AX_BX(uint32_t fetchdat) { - uint16_t temp = AX; - AX = BX; - BX = temp; - CLOCK_CYCLES(3); - PREFETCH_RUN(3, 1, -1, 0,0,0,0, 0); - return 0; + uint16_t temp = AX; + AX = BX; + BX = temp; + CLOCK_CYCLES(3); + PREFETCH_RUN(3, 1, -1, 0, 0, 0, 0, 0); + return 0; } -static int opXCHG_AX_CX(uint32_t fetchdat) +static int +opXCHG_AX_CX(uint32_t fetchdat) { - uint16_t temp = AX; - AX = CX; - CX = temp; - CLOCK_CYCLES(3); - PREFETCH_RUN(3, 1, -1, 0,0,0,0, 0); - return 0; + uint16_t temp = AX; + AX = CX; + CX = temp; + CLOCK_CYCLES(3); + PREFETCH_RUN(3, 1, -1, 0, 0, 0, 0, 0); + return 0; } -static int opXCHG_AX_DX(uint32_t fetchdat) +static int +opXCHG_AX_DX(uint32_t fetchdat) { - uint16_t temp = AX; - AX = DX; - DX = temp; - CLOCK_CYCLES(3); - PREFETCH_RUN(3, 1, -1, 0,0,0,0, 0); - return 0; + uint16_t temp = AX; + AX = DX; + DX = temp; + CLOCK_CYCLES(3); + PREFETCH_RUN(3, 1, -1, 0, 0, 0, 0, 0); + return 0; } -static int opXCHG_AX_SI(uint32_t fetchdat) +static int +opXCHG_AX_SI(uint32_t fetchdat) { - uint16_t temp = AX; - AX = SI; - SI = temp; - CLOCK_CYCLES(3); - PREFETCH_RUN(3, 1, -1, 0,0,0,0, 0); - return 0; + uint16_t temp = AX; + AX = SI; + SI = temp; + CLOCK_CYCLES(3); + PREFETCH_RUN(3, 1, -1, 0, 0, 0, 0, 0); + return 0; } -static int opXCHG_AX_DI(uint32_t fetchdat) +static int +opXCHG_AX_DI(uint32_t fetchdat) { - uint16_t temp = AX; - AX = DI; - DI = temp; - CLOCK_CYCLES(3); - PREFETCH_RUN(3, 1, -1, 0,0,0,0, 0); - return 0; + uint16_t temp = AX; + AX = DI; + DI = temp; + CLOCK_CYCLES(3); + PREFETCH_RUN(3, 1, -1, 0, 0, 0, 0, 0); + return 0; } -static int opXCHG_AX_BP(uint32_t fetchdat) +static int +opXCHG_AX_BP(uint32_t fetchdat) { - uint16_t temp = AX; - AX = BP; - BP = temp; - CLOCK_CYCLES(3); - PREFETCH_RUN(3, 1, -1, 0,0,0,0, 0); - return 0; + uint16_t temp = AX; + AX = BP; + BP = temp; + CLOCK_CYCLES(3); + PREFETCH_RUN(3, 1, -1, 0, 0, 0, 0, 0); + return 0; } -static int opXCHG_AX_SP(uint32_t fetchdat) +static int +opXCHG_AX_SP(uint32_t fetchdat) { - uint16_t temp = AX; - AX = SP; - SP = temp; - CLOCK_CYCLES(3); - PREFETCH_RUN(3, 1, -1, 0,0,0,0, 0); - return 0; + uint16_t temp = AX; + AX = SP; + SP = temp; + CLOCK_CYCLES(3); + PREFETCH_RUN(3, 1, -1, 0, 0, 0, 0, 0); + return 0; } -static int opXCHG_EAX_EBX(uint32_t fetchdat) +static int +opXCHG_EAX_EBX(uint32_t fetchdat) { - uint32_t temp = EAX; - EAX = EBX; - EBX = temp; - CLOCK_CYCLES(3); - PREFETCH_RUN(3, 1, -1, 0,0,0,0, 0); - return 0; + uint32_t temp = EAX; + EAX = EBX; + EBX = temp; + CLOCK_CYCLES(3); + PREFETCH_RUN(3, 1, -1, 0, 0, 0, 0, 0); + return 0; } -static int opXCHG_EAX_ECX(uint32_t fetchdat) +static int +opXCHG_EAX_ECX(uint32_t fetchdat) { - uint32_t temp = EAX; - EAX = ECX; - ECX = temp; - CLOCK_CYCLES(3); - PREFETCH_RUN(3, 1, -1, 0,0,0,0, 0); - return 0; + uint32_t temp = EAX; + EAX = ECX; + ECX = temp; + CLOCK_CYCLES(3); + PREFETCH_RUN(3, 1, -1, 0, 0, 0, 0, 0); + return 0; } -static int opXCHG_EAX_EDX(uint32_t fetchdat) +static int +opXCHG_EAX_EDX(uint32_t fetchdat) { - uint32_t temp = EAX; - EAX = EDX; - EDX = temp; - CLOCK_CYCLES(3); - PREFETCH_RUN(3, 1, -1, 0,0,0,0, 0); - return 0; + uint32_t temp = EAX; + EAX = EDX; + EDX = temp; + CLOCK_CYCLES(3); + PREFETCH_RUN(3, 1, -1, 0, 0, 0, 0, 0); + return 0; } -static int opXCHG_EAX_ESI(uint32_t fetchdat) +static int +opXCHG_EAX_ESI(uint32_t fetchdat) { - uint32_t temp = EAX; - EAX = ESI; - ESI = temp; - CLOCK_CYCLES(3); - PREFETCH_RUN(3, 1, -1, 0,0,0,0, 0); - return 0; + uint32_t temp = EAX; + EAX = ESI; + ESI = temp; + CLOCK_CYCLES(3); + PREFETCH_RUN(3, 1, -1, 0, 0, 0, 0, 0); + return 0; } -static int opXCHG_EAX_EDI(uint32_t fetchdat) +static int +opXCHG_EAX_EDI(uint32_t fetchdat) { - uint32_t temp = EAX; - EAX = EDI; - EDI = temp; - CLOCK_CYCLES(3); - PREFETCH_RUN(3, 1, -1, 0,0,0,0, 0); - return 0; + uint32_t temp = EAX; + EAX = EDI; + EDI = temp; + CLOCK_CYCLES(3); + PREFETCH_RUN(3, 1, -1, 0, 0, 0, 0, 0); + return 0; } -static int opXCHG_EAX_EBP(uint32_t fetchdat) +static int +opXCHG_EAX_EBP(uint32_t fetchdat) { - uint32_t temp = EAX; - EAX = EBP; - EBP = temp; - CLOCK_CYCLES(3); - PREFETCH_RUN(3, 1, -1, 0,0,0,0, 0); - return 0; + uint32_t temp = EAX; + EAX = EBP; + EBP = temp; + CLOCK_CYCLES(3); + PREFETCH_RUN(3, 1, -1, 0, 0, 0, 0, 0); + return 0; } -static int opXCHG_EAX_ESP(uint32_t fetchdat) +static int +opXCHG_EAX_ESP(uint32_t fetchdat) { - uint32_t temp = EAX; - EAX = ESP; - ESP = temp; - CLOCK_CYCLES(3); - PREFETCH_RUN(3, 1, -1, 0,0,0,0, 0); - return 0; + uint32_t temp = EAX; + EAX = ESP; + ESP = temp; + CLOCK_CYCLES(3); + PREFETCH_RUN(3, 1, -1, 0, 0, 0, 0, 0); + return 0; } +#define opBSWAP(reg) \ + static int opBSWAP_##reg(uint32_t fetchdat) \ + { \ + reg = (reg >> 24) | ((reg >> 8) & 0xff00) | ((reg << 8) & 0xff0000) | ((reg << 24) & 0xff000000); \ + CLOCK_CYCLES(1); \ + PREFETCH_RUN(1, 1, -1, 0, 0, 0, 0, 0); \ + return 0; \ + } -#define opBSWAP(reg) \ - static int opBSWAP_ ## reg(uint32_t fetchdat) \ - { \ - reg = (reg >> 24) | ((reg >> 8) & 0xff00) | ((reg << 8) & 0xff0000) | ((reg << 24) & 0xff000000); \ - CLOCK_CYCLES(1); \ - PREFETCH_RUN(1, 1, -1, 0,0,0,0, 0); \ - return 0; \ - } - +// clang-format off opBSWAP(EAX) opBSWAP(EBX) opBSWAP(ECX) @@ -232,3 +275,4 @@ opBSWAP(ESI) opBSWAP(EDI) opBSWAP(EBP) opBSWAP(ESP) + // clang-format on diff --git a/src/cpu/x86seg.c b/src/cpu/x86seg.c index 7fab0869c..96061d3fa 100644 --- a/src/cpu/x86seg.c +++ b/src/cpu/x86seg.c @@ -1,20 +1,20 @@ /* - * 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. + * 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. + * This file is part of the 86Box distribution. * - * x86 CPU segment emulation. + * x86 CPU segment emulation. * * * - * Authors: Sarah Walker, - * Miran Grca, + * Authors: Sarah Walker, + * Miran Grca, * - * Copyright 2008-2018 Sarah Walker. - * Copyright 2016-2018 Miran Grca. + * Copyright 2008-2018 Sarah Walker. + * Copyright 2016-2018 Miran Grca. */ #include #include @@ -31,485 +31,440 @@ #include <86box/machine.h> #include <86box/mem.h> #include <86box/nvr.h> +#include <86box/plat_fallthrough.h> +#include <86box/plat_unused.h> + #include "x86.h" #include "x86_flags.h" +#include "x86seg.h" +#include "x86seg_common.h" #include "386_common.h" +#ifdef OPS_286_386 +#define seg_readmembl readmembl_2386 +#define seg_readmemwl readmemwl_2386 +#define seg_readmemll readmemll_2386 +#define seg_writemembl writemembl_2386 +#define seg_writememwl writememwl_2386 +#define seg_writememll writememll_2386 +#else +#define seg_readmembl readmembl_2386 +#define seg_readmemwl readmemwl_2386 +#define seg_readmemll readmemll_2386 +#define seg_writemembl writemembl_2386 +#define seg_writememwl writememwl_2386 +#define seg_writememll writememll_2386 +#endif -uint8_t opcode2; - -int cgate16, cgate32; -int intgatesize; - -uint32_t abrt_error; - -void taskswitch286(uint16_t seg, uint16_t *segdat, int is32); - -void pmodeint(int num, int soft); - -#define DPL ((segdat[2] >> 13) & 3) +#define DPL ((segdat[2] >> 13) & 3) #define DPL2 ((segdat2[2] >> 13) & 3) #define DPL3 ((segdat3[2] >> 13) & 3) - #ifdef ENABLE_X86SEG_LOG int x86seg_do_log = ENABLE_X86SEG_LOG; - static void x86seg_log(const char *fmt, ...) { va_list ap; if (x86seg_do_log) { - va_start(ap, fmt); - pclog_ex(fmt, ap); - va_end(ap); + va_start(ap, fmt); + pclog_ex(fmt, ap); + va_end(ap); } } #else -#define x86seg_log(fmt, ...) +# define x86seg_log(fmt, ...) #endif - -static void -seg_reset(x86seg *s) -{ - s->access = 0x82; - s->ar_high = 0x10; - s->limit = 0xffff; - s->limit_low = 0; - s->limit_high = 0xffff; - if (s == &cpu_state.seg_cs) { - if (!cpu_inited) - fatal("seg_reset(&cpu_state.seg.cs) without an initialized CPU\n"); - s->base = is286 ? (cpu_16bitbus ? 0x00ff0000 : 0xffff0000) : 0x000ffff0; - s->seg = is286 ? 0xf000 : 0xffff; - } else { - s->base = 0; - s->seg = 0; - } -} - - -void -x86seg_reset() -{ - seg_reset(&cpu_state.seg_cs); - seg_reset(&cpu_state.seg_ds); - seg_reset(&cpu_state.seg_es); - seg_reset(&cpu_state.seg_fs); - seg_reset(&cpu_state.seg_gs); - seg_reset(&cpu_state.seg_ss); -} - - void +#ifdef OPS_286_386 +x86_doabrt_2386(int x86_abrt) +#else x86_doabrt(int x86_abrt) +#endif { #ifndef USE_NEW_DYNAREC CS = oldcs; #endif - cpu_state.pc = cpu_state.oldpc; - cpu_state.seg_cs.access = (oldcpl << 5) | 0x80; + cpu_state.pc = cpu_state.oldpc; + cpu_state.seg_cs.access = (oldcpl << 5) | 0x80; cpu_state.seg_cs.ar_high = 0x10; if (msw & 1) - pmodeint(x86_abrt, 0); + op_pmodeint(x86_abrt, 0); else { - uint32_t addr = (x86_abrt << 2) + idt.base; - if (stack32) { - writememw(ss, ESP - 2, cpu_state.flags); - writememw(ss, ESP - 4, CS); - writememw(ss, ESP - 6, cpu_state.pc); - ESP -= 6; - } else { - writememw(ss, ((SP - 2) & 0xffff), cpu_state.flags); - writememw(ss, ((SP - 4) & 0xffff), CS); - writememw(ss, ((SP - 6) & 0xffff), cpu_state.pc); - SP -= 6; - } + uint32_t addr = (x86_abrt << 2) + idt.base; + if (stack32) { + writememw(ss, ESP - 2, cpu_state.flags); + writememw(ss, ESP - 4, CS); + writememw(ss, ESP - 6, cpu_state.pc); + ESP -= 6; + } else { + writememw(ss, ((SP - 2) & 0xffff), cpu_state.flags); + writememw(ss, ((SP - 4) & 0xffff), CS); + writememw(ss, ((SP - 6) & 0xffff), cpu_state.pc); + SP -= 6; + } - cpu_state.flags &= ~(I_FLAG | T_FLAG); + cpu_state.flags &= ~(I_FLAG | T_FLAG); #ifndef USE_NEW_DYNAREC - oxpc = cpu_state.pc; + oxpc = cpu_state.pc; #endif - cpu_state.pc = readmemw(0, addr); - loadcs(readmemw(0, addr + 2)); - return; + cpu_state.pc = readmemw(0, addr); + op_loadcs(readmemw(0, addr + 2)); + return; } if (cpu_state.abrt || x86_was_reset) - return; + return; if (intgatesize == 16) { - if (stack32) { - writememw(ss, ESP - 2, abrt_error); - ESP -= 2; - } else { - writememw(ss, ((SP - 2) & 0xffff), abrt_error); - SP -= 2; - } + if (stack32) { + writememw(ss, ESP - 2, abrt_error); + ESP -= 2; + } else { + writememw(ss, ((SP - 2) & 0xffff), abrt_error); + SP -= 2; + } } else { - if (stack32) { - writememl(ss, ESP - 4, abrt_error); - ESP -= 4; - } else { - writememl(ss, ((SP - 4) & 0xffff), abrt_error); - SP -= 4; - } + if (stack32) { + writememl(ss, ESP - 4, abrt_error); + ESP -= 4; + } else { + writememl(ss, ((SP - 4) & 0xffff), abrt_error); + SP -= 4; + } } } - -void -x86gpf(char *s, uint16_t error) -{ - cpu_state.abrt = ABRT_GPF; - abrt_error = error; -} - - -void -x86gpf_expected(char *s, uint16_t error) -{ - cpu_state.abrt = ABRT_GPF | ABRT_EXPECTED; - abrt_error = error; -} - - -void -x86ss(char *s, uint16_t error) -{ - cpu_state.abrt = ABRT_SS; - abrt_error = error; -} - - -void x86ts(char *s, uint16_t error) -{ - cpu_state.abrt = ABRT_TS; - abrt_error = error; -} - - -void -x86np(char *s, uint16_t error) -{ - cpu_state.abrt = ABRT_NP; - abrt_error = error; -} - - static void set_stack32(int s) { stack32 = s; if (stack32) - cpu_cur_status |= CPU_STATUS_STACK32; + cpu_cur_status |= CPU_STATUS_STACK32; else - cpu_cur_status &= ~CPU_STATUS_STACK32; + cpu_cur_status &= ~CPU_STATUS_STACK32; } - static void set_use32(int u) { use32 = u ? 0x300 : 0; if (u) - cpu_cur_status |= CPU_STATUS_USE32; + cpu_cur_status |= CPU_STATUS_USE32; else - cpu_cur_status &= ~CPU_STATUS_USE32; + cpu_cur_status &= ~CPU_STATUS_USE32; } - +#ifndef OPS_286_386 void do_seg_load(x86seg *s, uint16_t *segdat) { s->limit = segdat[0] | ((segdat[3] & 0x000f) << 16); if (segdat[3] & 0x0080) - s->limit = (s->limit << 12) | 0xfff; + s->limit = (s->limit << 12) | 0xfff; s->base = segdat[1] | ((segdat[2] & 0x00ff) << 16); if (is386) - s->base |= ((segdat[3] >> 8) << 24); - s->access = segdat[2] >> 8; + s->base |= ((segdat[3] >> 8) << 24); + s->access = segdat[2] >> 8; s->ar_high = segdat[3] & 0xff; if (((segdat[2] & 0x1800) != 0x1000) || !(segdat[2] & (1 << 10))) { - /* Expand-down */ - s->limit_high = s->limit; - s->limit_low = 0; + /* Expand-down */ + s->limit_high = s->limit; + s->limit_low = 0; } else { - s->limit_high = (segdat[3] & 0x40) ? 0xffffffff : 0xffff; - s->limit_low = s->limit + 1; + s->limit_high = (segdat[3] & 0x40) ? 0xffffffff : 0xffff; + s->limit_low = s->limit + 1; } if (s == &cpu_state.seg_ds) { - if ((s->base == 0) && (s->limit_low == 0) && (s->limit_high == 0xffffffff)) - cpu_cur_status &= ~CPU_STATUS_NOTFLATDS; - else - cpu_cur_status |= CPU_STATUS_NOTFLATDS; + if ((s->base == 0) && (s->limit_low == 0) && (s->limit_high == 0xffffffff)) + cpu_cur_status &= ~CPU_STATUS_NOTFLATDS; + else + cpu_cur_status |= CPU_STATUS_NOTFLATDS; } if (s == &cpu_state.seg_ss) { - if ((s->base == 0) && (s->limit_low == 0) && (s->limit_high == 0xffffffff)) - cpu_cur_status &= ~CPU_STATUS_NOTFLATSS; - else - cpu_cur_status |= CPU_STATUS_NOTFLATSS; + if ((s->base == 0) && (s->limit_low == 0) && (s->limit_high == 0xffffffff)) + cpu_cur_status &= ~CPU_STATUS_NOTFLATSS; + else + cpu_cur_status |= CPU_STATUS_NOTFLATSS; } - - if (s->base == 0xffffffff) - fatal("do_seg_load(): %04X%04X%04X%04X\n", segdat[3], segdat[2], segdat[1], segdat[0]); } - +#endif static void do_seg_v86_init(x86seg *s) { - s->access = 0xe2; - s->ar_high = 0x10; - s->limit = 0xffff; - s->limit_low = 0; + s->access = 0xe2; + s->ar_high = 0x10; + s->limit = 0xffff; + s->limit_low = 0; s->limit_high = 0xffff; } - static void check_seg_valid(x86seg *s) { - int dpl = (s->access >> 5) & 3; - int valid = 1; - x86seg *dt = (s->seg & 0x0004) ? &ldt : &gdt; + int dpl = (s->access >> 5) & 3; + int valid = 1; + const x86seg *dt = (s->seg & 0x0004) ? &ldt : &gdt; if (((s->seg & 0xfff8UL) + 7UL) > dt->limit) - valid = 0; + valid = 0; switch (s->access & 0x1f) { - case 0x10: case 0x11: case 0x12: case 0x13: /* Data segments */ - case 0x14: case 0x15: case 0x16: case 0x17: - case 0x1a: case 0x1b: /* Readable non-conforming code */ - if (((s->seg & 3) > dpl) || ((CPL) > dpl)) { - valid = 0; - break; - } - break; + case 0x10: + case 0x11: + case 0x12: + case 0x13: /* Data segments */ + case 0x14: + case 0x15: + case 0x16: + case 0x17: + case 0x1a: + case 0x1b: /* Readable non-conforming code */ + if (((s->seg & 3) > dpl) || ((CPL) > dpl)) { + valid = 0; + break; + } + break; - case 0x1e: case 0x1f: /* Readable conforming code */ - break; + case 0x1e: + case 0x1f: /* Readable conforming code */ + break; - default: - valid = 0; - break; + default: + valid = 0; + break; } if (!valid) - loadseg(0, s); + op_loadseg(0, s); } - static void read_descriptor(uint32_t addr, uint16_t *segdat, uint32_t *segdat32, int override) { if (override) - cpl_override = 1; + cpl_override = 1; if (cpu_16bitbus) { - segdat[0] = readmemw(0, addr); - segdat[1] = readmemw(0, addr + 2); - segdat[2] = readmemw(0, addr + 4); - segdat[3] = readmemw(0, addr + 6); + segdat[0] = readmemw(0, addr); + segdat[1] = readmemw(0, addr + 2); + segdat[2] = readmemw(0, addr + 4); + segdat[3] = readmemw(0, addr + 6); } else { - segdat32[0] = readmeml(0, addr); - segdat32[1] = readmeml(0, addr + 4); + segdat32[0] = readmeml(0, addr); + segdat32[1] = readmeml(0, addr + 4); } if (override) - cpl_override = 0; + cpl_override = 0; } - #ifdef USE_NEW_DYNAREC int #else void #endif +#ifdef OPS_286_386 +loadseg_2386(uint16_t seg, x86seg *s) +#else loadseg(uint16_t seg, x86seg *s) +#endif { - uint16_t segdat[4]; - uint32_t addr, *segdat32 = (uint32_t *) segdat; - int dpl; - x86seg *dt; + uint16_t segdat[4]; + uint32_t addr; + uint32_t *segdat32 = (uint32_t *) segdat; + int dpl; + const x86seg *dt; if ((msw & 1) && !(cpu_state.eflags & VM_FLAG)) { - if (!(seg & 0xfffc)) { - if (s == &cpu_state.seg_ss) { - x86ss(NULL,0); + if (!(seg & 0xfffc)) { + if (s == &cpu_state.seg_ss) { + x86ss(NULL, 0); #ifdef USE_NEW_DYNAREC - return 1; + return 1; #else - return; + return; #endif - } - s->seg = 0; - s->access = 0x80; - s->ar_high = 0x10; - s->base = -1; - if (s == &cpu_state.seg_ds) - cpu_cur_status |= CPU_STATUS_NOTFLATDS; + } + s->seg = 0; + s->access = 0x80; + s->ar_high = 0x10; + s->base = -1; + if (s == &cpu_state.seg_ds) + cpu_cur_status |= CPU_STATUS_NOTFLATDS; #ifdef USE_NEW_DYNAREC - return 0; + return 0; #else - return; + return; #endif - } - addr = seg & 0xfff8; - dt = (seg & 0x0004) ? &ldt : &gdt; - if ((addr + 7) > dt->limit) { - x86gpf("loadseg(): Bigger than LDT limit", seg & 0xfffc); + } + addr = seg & 0xfff8; + dt = (seg & 0x0004) ? &ldt : &gdt; + if ((addr + 7) > dt->limit) { + x86gpf("loadseg(): Bigger than LDT limit", seg & 0xfffc); #ifdef USE_NEW_DYNAREC - return 1; + return 1; #else - return; + return; #endif - } - addr += dt->base; - read_descriptor(addr, segdat, segdat32, 1); - if (cpu_state.abrt) + } + addr += dt->base; + read_descriptor(addr, segdat, segdat32, 1); + if (cpu_state.abrt) #ifdef USE_NEW_DYNAREC - return 1; + return 1; #else - return; + return; #endif - dpl = (segdat[2] >> 13) & 3; - if (s == &cpu_state.seg_ss) { - if (!(seg & 0xfffc)) { - x86gpf("loadseg(): Zero stack segment", seg & 0xfffc); + dpl = (segdat[2] >> 13) & 3; + if (s == &cpu_state.seg_ss) { + if (!(seg & 0xfffc)) { + x86gpf("loadseg(): Zero stack segment", seg & 0xfffc); #ifdef USE_NEW_DYNAREC - return 1; + return 1; #else - return; + return; #endif - } - if ((seg & 0x0003) != CPL) { - x86gpf("loadseg(): Stack segment RPL != CPL", seg & 0xfffc); + } + if ((seg & 0x0003) != CPL) { + x86gpf("loadseg(): Stack segment RPL != CPL", seg & 0xfffc); #ifdef USE_NEW_DYNAREC - return 1; + return 1; #else - return; + return; #endif - } - if (dpl != CPL) { - x86gpf("loadseg(): Stack segment DPL != CPL", seg & 0xfffc); + } + if (dpl != CPL) { + x86gpf("loadseg(): Stack segment DPL != CPL", seg & 0xfffc); #ifdef USE_NEW_DYNAREC - return 1; + return 1; #else - return; + return; #endif - } - switch ((segdat[2] >> 8) & 0x1f) { - case 0x12: case 0x13: case 0x16: case 0x17: - /* R/W */ - break; - default: - x86gpf("loadseg(): Unknown stack segment type", seg & ~3); + } + switch ((segdat[2] >> 8) & 0x1f) { + case 0x12: + case 0x13: + case 0x16: + case 0x17: + /* R/W */ + break; + default: + x86gpf("loadseg(): Unknown stack segment type", seg & ~3); #ifdef USE_NEW_DYNAREC - return 1; + return 1; #else - return; + return; #endif - } - if (!(segdat[2] & 0x8000)) { - x86ss(NULL, seg & 0xfffc); + } + if (!(segdat[2] & 0x8000)) { + x86ss(NULL, seg & 0xfffc); #ifdef USE_NEW_DYNAREC - return 1; + return 1; #else - return; + return; #endif - } - set_stack32((segdat[3] & 0x40) ? 1 : 0); - } else if (s != &cpu_state.seg_cs) { - x86seg_log("Seg data %04X %04X %04X %04X\n", segdat[0], segdat[1], segdat[2], segdat[3]); - x86seg_log("Seg type %03X\n",segdat[2] & 0x1f00); - switch ((segdat[2] >> 8) & 0x1f) { - case 0x10: case 0x11: case 0x12: case 0x13: /* Data segments */ - case 0x14: case 0x15: case 0x16: case 0x17: - case 0x1a: case 0x1b: /* Readable non-conforming code */ - if ((seg & 0x0003) > dpl) { - x86gpf("loadseg(): Normal segment RPL > DPL", seg & 0xfffc); + } + set_stack32((segdat[3] & 0x40) ? 1 : 0); + } else if (s != &cpu_state.seg_cs) { + x86seg_log("Seg data %04X %04X %04X %04X\n", segdat[0], segdat[1], segdat[2], segdat[3]); + x86seg_log("Seg type %03X\n", segdat[2] & 0x1f00); + switch ((segdat[2] >> 8) & 0x1f) { + case 0x10: + case 0x11: + case 0x12: + case 0x13: /* Data segments */ + case 0x14: + case 0x15: + case 0x16: + case 0x17: + case 0x1a: + case 0x1b: /* Readable non-conforming code */ + if ((seg & 0x0003) > dpl) { + x86gpf("loadseg(): Normal segment RPL > DPL", seg & 0xfffc); #ifdef USE_NEW_DYNAREC - return 1; + return 1; #else - return; + return; #endif - } - if ((CPL) > dpl) { - x86gpf("loadseg(): Normal segment DPL < CPL", seg& 0xfffc); + } + if ((CPL) > dpl) { + x86gpf("loadseg(): Normal segment DPL < CPL", seg & 0xfffc); #ifdef USE_NEW_DYNAREC - return 1; + return 1; #else - return; + return; #endif - } - break; - case 0x1e: case 0x1f: /* Readable conforming code */ - break; - default: - x86gpf("loadseg(): Unknown normal segment type", seg & 0xfffc); + } + break; + case 0x1e: + case 0x1f: /* Readable conforming code */ + break; + default: + x86gpf("loadseg(): Unknown normal segment type", seg & 0xfffc); #ifdef USE_NEW_DYNAREC - return 1; + return 1; #else - return; + return; #endif - } - } + } + } - if (!(segdat[2] & 0x8000)) { - x86np("Load data seg not present", seg & 0xfffc); + if (!(segdat[2] & 0x8000)) { + x86np("Load data seg not present", seg & 0xfffc); #ifdef USE_NEW_DYNAREC - return 1; + return 1; #else - return; + return; #endif - } - s->seg = seg; - do_seg_load(s, segdat); + } + s->seg = seg; + do_seg_load(s, segdat); - cpl_override = 1; - writememw(0, addr + 4, segdat[2] | 0x100); /* Set accessed bit */ - cpl_override = 0; - s->checked = 0; + cpl_override = 1; + writememw(0, addr + 4, segdat[2] | 0x100); /* Set accessed bit */ + cpl_override = 0; + s->checked = 0; #ifdef USE_DYNAREC - if (s == &cpu_state.seg_ds) - codegen_flat_ds = 0; - if (s == &cpu_state.seg_ss) - codegen_flat_ss = 0; + if (s == &cpu_state.seg_ds) + codegen_flat_ds = 0; + if (s == &cpu_state.seg_ss) + codegen_flat_ss = 0; #endif } else { - s->access = 0xe2; - s->ar_high = 0x10; - s->base = seg << 4; - s->seg = seg; - s->checked = 1; + s->access = 0xe2; + s->ar_high = 0x10; + s->base = seg << 4; + s->seg = seg; + s->checked = 1; #ifdef USE_DYNAREC - if (s == &cpu_state.seg_ds) - codegen_flat_ds = 0; - if (s == &cpu_state.seg_ss) - codegen_flat_ss = 0; + if (s == &cpu_state.seg_ds) + codegen_flat_ds = 0; + if (s == &cpu_state.seg_ss) + codegen_flat_ss = 0; #endif - if (s == &cpu_state.seg_ss && (cpu_state.eflags & VM_FLAG)) - set_stack32(0); + if (s == &cpu_state.seg_ss && (cpu_state.eflags & VM_FLAG)) + set_stack32(0); } if (s == &cpu_state.seg_ds) { - if (s->base == 0 && s->limit_low == 0 && s->limit_high == 0xffffffff) - cpu_cur_status &= ~CPU_STATUS_NOTFLATDS; - else - cpu_cur_status |= CPU_STATUS_NOTFLATDS; + if (s->base == 0 && s->limit_low == 0 && s->limit_high == 0xffffffff) + cpu_cur_status &= ~CPU_STATUS_NOTFLATDS; + else + cpu_cur_status |= CPU_STATUS_NOTFLATDS; } if (s == &cpu_state.seg_ss) { - if (s->base == 0 && s->limit_low == 0 && s->limit_high == 0xffffffff) - cpu_cur_status &= ~CPU_STATUS_NOTFLATSS; - else - cpu_cur_status |= CPU_STATUS_NOTFLATSS; + if (s->base == 0 && s->limit_low == 0 && s->limit_high == 0xffffffff) + cpu_cur_status &= ~CPU_STATUS_NOTFLATSS; + else + cpu_cur_status |= CPU_STATUS_NOTFLATSS; } #ifdef USE_NEW_DYNAREC @@ -517,1917 +472,2044 @@ loadseg(uint16_t seg, x86seg *s) #endif } - void +#ifdef OPS_286_386 +loadcs_2386(uint16_t seg) +#else loadcs(uint16_t seg) +#endif { - uint16_t segdat[4]; - uint32_t addr, *segdat32 = (uint32_t *) segdat; - x86seg *dt; + uint16_t segdat[4]; + uint32_t addr; + uint32_t *segdat32 = (uint32_t *) segdat; + const x86seg *dt; x86seg_log("Load CS %04X\n", seg); if ((msw & 1) && !(cpu_state.eflags & VM_FLAG)) { - if (!(seg & 0xfffc)) { - x86gpf("loadcs(): Protected mode selector is zero", 0); - return; - } + if (!(seg & 0xfffc)) { + x86gpf("loadcs(): Protected mode selector is zero", 0); + return; + } - addr = seg & 0xfff8; - dt = (seg & 0x0004)? &ldt : &gdt; - if ((addr + 7) > dt->limit) { - x86gpf("loadcs(): Protected mode selector > DT limit", seg & 0xfffc); - return; - } - addr += dt->base; + addr = seg & 0xfff8; + dt = (seg & 0x0004) ? &ldt : &gdt; + if ((addr + 7) > dt->limit) { + x86gpf("loadcs(): Protected mode selector > DT limit", seg & 0xfffc); + return; + } + addr += dt->base; - read_descriptor(addr, segdat, segdat32, 1); - if (cpu_state.abrt) - return; - if (segdat[2] & 0x1000) { - /* Normal code segment */ - if (!(segdat[2] & 0x0400)) { - /* Not conforming */ - if ((seg & 3) > CPL) { - x86gpf("loadcs(): Non-conforming RPL > CPL", seg & 0xfffc); - return; - } - if (CPL != DPL) { - x86gpf("loadcs(): Non-conforming CPL != DPL", seg & 0xfffc); - return; - } - } - if (CPL < DPL) { - x86gpf("loadcs(): CPL < DPL", seg & ~3); - return; - } - if (!(segdat[2] & 0x8000)) { - x86np("Load CS not present", seg & 0xfffc); - return; - } - set_use32(segdat[3] & 0x40); - CS = (seg & 0xfffc) | CPL; - do_seg_load(&cpu_state.seg_cs, segdat); - use32 = (segdat[3] & 0x40) ? 0x300 : 0; - if ((CPL == 3) && (oldcpl != 3)) - flushmmucache_cr3(); + read_descriptor(addr, segdat, segdat32, 1); + if (cpu_state.abrt) + return; + if (segdat[2] & 0x1000) { + /* Normal code segment */ + if (!(segdat[2] & 0x0400)) { + /* Not conforming */ + if ((seg & 3) > CPL) { + x86gpf("loadcs(): Non-conforming RPL > CPL", seg & 0xfffc); + return; + } + if (CPL != DPL) { + x86gpf("loadcs(): Non-conforming CPL != DPL", seg & 0xfffc); + return; + } + } + if (CPL < DPL) { + x86gpf("loadcs(): CPL < DPL", seg & ~3); + return; + } + if (!(segdat[2] & 0x8000)) { + x86np("Load CS not present", seg & 0xfffc); + return; + } + set_use32(segdat[3] & 0x40); + CS = (seg & 0xfffc) | CPL; + do_seg_load(&cpu_state.seg_cs, segdat); + use32 = (segdat[3] & 0x40) ? 0x300 : 0; + if ((CPL == 3) && (oldcpl != 3)) + flushmmucache_nopc(); #ifdef USE_NEW_DYNAREC - oldcpl = CPL; + oldcpl = CPL; #endif - cpl_override = 1; - writememw(0, addr + 4, segdat[2] | 0x0100); /* Set accessed bit */ - cpl_override = 0; - } else { - /* System segment */ - if (!(segdat[2] & 0x8000)) { - x86np("Load CS system seg not present", seg & 0xfffc); - return; - } - switch (segdat[2] & 0x0f00) { - default: - x86gpf("Load CS system segment has bits 0-3 of access rights set", seg & 0xfffc); - return; - } - } + cpl_override = 1; + writememw(0, addr + 4, segdat[2] | 0x0100); /* Set accessed bit */ + cpl_override = 0; + } else { + /* System segment */ + if (!(segdat[2] & 0x8000)) { + x86np("Load CS system seg not present", seg & 0xfffc); + return; + } + switch (segdat[2] & 0x0f00) { + default: + x86gpf("Load CS system segment has bits 0-3 of access rights set", seg & 0xfffc); + return; + } + } } else { - cpu_state.seg_cs.base = (seg << 4); - cpu_state.seg_cs.limit = 0xffff; - cpu_state.seg_cs.limit_low = 0; - cpu_state.seg_cs.limit_high = 0xffff; - cpu_state.seg_cs.seg = seg & 0xffff; - cpu_state.seg_cs.access = (cpu_state.eflags & VM_FLAG) ? 0xe2 : 0x82; - cpu_state.seg_cs.ar_high = 0x10; - if ((CPL == 3) && (oldcpl != 3)) - flushmmucache_cr3(); + cpu_state.seg_cs.base = (seg << 4); + cpu_state.seg_cs.limit = 0xffff; + cpu_state.seg_cs.limit_low = 0; + cpu_state.seg_cs.limit_high = 0xffff; + cpu_state.seg_cs.seg = seg & 0xffff; + cpu_state.seg_cs.access = (cpu_state.eflags & VM_FLAG) ? 0xe2 : 0x82; + cpu_state.seg_cs.ar_high = 0x10; + if ((CPL == 3) && (oldcpl != 3)) + flushmmucache_nopc(); #ifdef USE_NEW_DYNAREC - oldcpl = CPL; + oldcpl = CPL; #endif } } - void +#ifdef OPS_286_386 +loadcsjmp_2386(uint16_t seg, uint32_t old_pc) +#else loadcsjmp(uint16_t seg, uint32_t old_pc) +#endif { - uint16_t type, seg2; - uint16_t segdat[4]; - uint32_t addr, newpc; - uint32_t *segdat32 = (uint32_t *) segdat; - x86seg *dt; + uint16_t type; + uint16_t seg2; + uint16_t segdat[4]; + uint32_t addr; + uint32_t newpc; + uint32_t *segdat32 = (uint32_t *) segdat; + const x86seg *dt; if ((msw & 1) && !(cpu_state.eflags & VM_FLAG)) { - if (!(seg & 0xfffc)) { - x86gpf("loadcsjmp(): Selector is zero", 0); - return; - } - addr = seg & 0xfff8; - dt = (seg & 0x0004) ? &ldt : &gdt; - if ((addr + 7) > dt->limit) { - x86gpf("loacsjmp(): Selector > DT limit", seg & 0xfffc); - return; - } - addr += dt->base; - read_descriptor(addr, segdat, segdat32, 1); - if (cpu_state.abrt) - return; - x86seg_log("%04X %04X %04X %04X\n", segdat[0], segdat[1], segdat[2], segdat[3]); - if (segdat[2] & 0x1000) { - /* Normal code segment */ - if (!(segdat[2] & 0x0400)) { - /* Not conforming */ - if ((seg & 0x0003) > CPL) { - x86gpf("loadcsjmp(): segment PL > CPL", seg & 0xfffc); - return; - } - if (CPL != DPL) { - x86gpf("loadcsjmp(): CPL != DPL", seg & 0xfffc); - return; - } - } - if (CPL < DPL) { - x86gpf("loadcsjmp(): CPL < DPL",seg & 0xfffc); - return; - } - if (!(segdat[2] & 0x8000)) { - x86np("Load CS JMP not present", seg & 0xfffc); - return; - } - set_use32(segdat[3] & 0x0040); + if (!(seg & 0xfffc)) { + x86gpf("loadcsjmp(): Selector is zero", 0); + return; + } + addr = seg & 0xfff8; + dt = (seg & 0x0004) ? &ldt : &gdt; + if ((addr + 7) > dt->limit) { + x86gpf("loacsjmp(): Selector > DT limit", seg & 0xfffc); + return; + } + addr += dt->base; + read_descriptor(addr, segdat, segdat32, 1); + if (cpu_state.abrt) + return; + x86seg_log("%04X %04X %04X %04X\n", segdat[0], segdat[1], segdat[2], segdat[3]); + if (segdat[2] & 0x1000) { + /* Normal code segment */ + if (!(segdat[2] & 0x0400)) { + /* Not conforming */ + if ((seg & 0x0003) > CPL) { + x86gpf("loadcsjmp(): segment PL > CPL", seg & 0xfffc); + return; + } + if (CPL != DPL) { + x86gpf("loadcsjmp(): CPL != DPL", seg & 0xfffc); + return; + } + } + if (CPL < DPL) { + x86gpf("loadcsjmp(): CPL < DPL", seg & 0xfffc); + return; + } + if (!(segdat[2] & 0x8000)) { + x86np("Load CS JMP not present", seg & 0xfffc); + return; + } + set_use32(segdat[3] & 0x0040); - cpl_override = 1; - writememw(0, addr + 4, segdat[2] | 0x0100); /* Set accessed bit */ - cpl_override = 0; + cpl_override = 1; + writememw(0, addr + 4, segdat[2] | 0x0100); /* Set accessed bit */ + cpl_override = 0; - CS = (seg & 0xfffc) | CPL; - segdat[2] = (segdat[2] & ~(3 << 13)) | (CPL << 13); + CS = (seg & 0xfffc) | CPL; + segdat[2] = (segdat[2] & ~(3 << 13)) | (CPL << 13); - do_seg_load(&cpu_state.seg_cs, segdat); - if ((CPL == 3) && (oldcpl != 3)) - flushmmucache_cr3(); + do_seg_load(&cpu_state.seg_cs, segdat); + if ((CPL == 3) && (oldcpl != 3)) + flushmmucache_nopc(); #ifdef USE_NEW_DYNAREC - oldcpl = CPL; + oldcpl = CPL; #endif - cycles -= timing_jmp_pm; - } else { /* System segment */ - if (!(segdat[2] & 0x8000)) { - x86np("Load CS JMP system selector not present", seg & 0xfffc); - return; - } - type = segdat[2] & 0x0f00; - newpc = segdat[0]; - if (type & 0x0800) - newpc |= (segdat[3] << 16); - switch (type) { - case 0x0400: /* Call gate */ - case 0x0c00: - cgate32 = (type & 0x0800); - cgate16 = !cgate32; + cycles -= timing_jmp_pm; + } else { /* System segment */ + if (!(segdat[2] & 0x8000)) { + x86np("Load CS JMP system selector not present", seg & 0xfffc); + return; + } + type = segdat[2] & 0x0f00; + newpc = segdat[0]; + if (type & 0x0800) + newpc |= (segdat[3] << 16); + switch (type) { + case 0x0400: /* Call gate */ + case 0x0c00: + cgate32 = (type & 0x0800); + cgate16 = !cgate32; #ifndef USE_NEW_DYNAREC - oldcs=CS; + oldcs = CS; #endif - cpu_state.oldpc = cpu_state.pc; - if (DPL < CPL) { - x86gpf("loadcsjmp(): Call gate DPL < CPL",seg & 0xfffc); - return; - } - if (DPL < (seg & 0x0003)) { - x86gpf("loadcsjmp(): Call gate DPL< RPL",seg&~3); - return; - } - if (!(segdat[2] & 0x8000)) { - x86np("Load CS JMP call gate not present", seg & 0xfffc); - return; - } - seg2 = segdat[1]; + cpu_state.oldpc = cpu_state.pc; + if (DPL < CPL) { + x86gpf("loadcsjmp(): Call gate DPL < CPL", seg & 0xfffc); + return; + } + if (DPL < (seg & 0x0003)) { + x86gpf("loadcsjmp(): Call gate DPL< RPL", seg & ~3); + return; + } + if (!(segdat[2] & 0x8000)) { + x86np("Load CS JMP call gate not present", seg & 0xfffc); + return; + } + seg2 = segdat[1]; - if (!(seg2 & 0xfffc)) { - x86gpf("Load CS JMP call gate selector is NULL", 0); - return; - } - addr = seg2 & 0xfff8; - dt = (seg2 & 0x0004) ? &ldt : &gdt; - if ((addr + 7) > dt->limit) { - x86gpf("loadcsjmp(): Call gate selector > DT limit", seg2 & 0xfffc); - return; - } - addr += dt->base; - read_descriptor(addr, segdat, segdat32, 1); - if (cpu_state.abrt) - return; + if (!(seg2 & 0xfffc)) { + x86gpf("Load CS JMP call gate selector is NULL", 0); + return; + } + addr = seg2 & 0xfff8; + dt = (seg2 & 0x0004) ? &ldt : &gdt; + if ((addr + 7) > dt->limit) { + x86gpf("loadcsjmp(): Call gate selector > DT limit", seg2 & 0xfffc); + return; + } + addr += dt->base; + read_descriptor(addr, segdat, segdat32, 1); + if (cpu_state.abrt) + return; - if (DPL > CPL) { - x86gpf("loadcsjmp(): ex DPL > CPL",seg2 & 0xfffc); - return; - } - if (!(segdat[2] & 0x8000)) { - x86np("Load CS JMP from call gate not present", seg2 & 0xfffc); - return; - } + if (DPL > CPL) { + x86gpf("loadcsjmp(): ex DPL > CPL", seg2 & 0xfffc); + return; + } + if (!(segdat[2] & 0x8000)) { + x86np("Load CS JMP from call gate not present", seg2 & 0xfffc); + return; + } - switch (segdat[2] & 0x1f00) { - case 0x1800: case 0x1900: case 0x1a00: case 0x1b00: /* Non-conforming code */ - if (DPL > CPL) { - x86gpf("loadcsjmp(): Non-conforming DPL > CPL", seg2 & 0xfffc); - return; - } - /*FALLTHROUGH*/ - case 0x1c00: case 0x1d00: case 0x1e00: case 0x1f00: /* Conforming */ - CS = seg2; - do_seg_load(&cpu_state.seg_cs, segdat); - if ((CPL == 3) && (oldcpl != 3)) - flushmmucache_cr3(); + switch (segdat[2] & 0x1f00) { + case 0x1800: + case 0x1900: + case 0x1a00: + case 0x1b00: /* Non-conforming code */ + if (DPL > CPL) { + x86gpf("loadcsjmp(): Non-conforming DPL > CPL", seg2 & 0xfffc); + return; + } + fallthrough; + case 0x1c00: + case 0x1d00: + case 0x1e00: + case 0x1f00: /* Conforming */ + CS = seg2; + do_seg_load(&cpu_state.seg_cs, segdat); + if ((CPL == 3) && (oldcpl != 3)) + flushmmucache_nopc(); #ifdef USE_NEW_DYNAREC - oldcpl = CPL; + oldcpl = CPL; #endif - set_use32(segdat[3]&0x40); - cpu_state.pc=newpc; + set_use32(segdat[3] & 0x40); + cpu_state.pc = newpc; - cpl_override = 1; - writememw(0, addr + 4, segdat[2] | 0x100); /* Set accessed bit */ - cpl_override = 0; - break; + cpl_override = 1; + writememw(0, addr + 4, segdat[2] | 0x100); /* Set accessed bit */ + cpl_override = 0; + break; - default: - x86gpf("loadcsjmp(): Unknown type", seg2 & 0xfffc); - return; - } - cycles -= timing_jmp_pm_gate; - break; + default: + x86gpf("loadcsjmp(): Unknown type", seg2 & 0xfffc); + return; + } + cycles -= timing_jmp_pm_gate; + break; - case 0x100: /* 286 Task gate */ - case 0x900: /* 386 Task gate */ - cpu_state.pc = old_pc; - optype = JMP; - cpl_override = 1; - taskswitch286(seg,segdat,segdat[2] & 0x800); - cpu_state.flags &= ~NT_FLAG; - cpl_override=0; - return; + case 0x100: /* 286 Task gate */ + case 0x900: /* 386 Task gate */ + cpu_state.pc = old_pc; + optype = JMP; + cpl_override = 1; + op_taskswitch286(seg, segdat, segdat[2] & 0x800); + cpu_state.flags &= ~NT_FLAG; + cpl_override = 0; + return; - default: - x86gpf("Load CS JMP call gate selector unknown type", 0); - return; - } - } + default: + x86gpf("Load CS JMP call gate selector unknown type", 0); + return; + } + } } else { - cpu_state.seg_cs.base = seg << 4; - cpu_state.seg_cs.limit = 0xffff; - cpu_state.seg_cs.limit_low = 0; - cpu_state.seg_cs.limit_high = 0xffff; - cpu_state.seg_cs.seg = seg; - cpu_state.seg_cs.access = (cpu_state.eflags & VM_FLAG) ? 0xe2 : 0x82; - cpu_state.seg_cs.ar_high = 0x10; - if ((CPL == 3) && (oldcpl != 3)) - flushmmucache_cr3(); + cpu_state.seg_cs.base = seg << 4; + cpu_state.seg_cs.limit = 0xffff; + cpu_state.seg_cs.limit_low = 0; + cpu_state.seg_cs.limit_high = 0xffff; + cpu_state.seg_cs.seg = seg; + cpu_state.seg_cs.access = (cpu_state.eflags & VM_FLAG) ? 0xe2 : 0x82; + cpu_state.seg_cs.ar_high = 0x10; + if ((CPL == 3) && (oldcpl != 3)) + flushmmucache_nopc(); #ifdef USE_NEW_DYNAREC - oldcpl = CPL; + oldcpl = CPL; #endif - cycles -= timing_jmp_rm; + cycles -= timing_jmp_rm; } } - -void +static void PUSHW(uint16_t v) { if (stack32) { - writememw(ss, ESP - 2, v); - if (cpu_state.abrt) - return; - ESP -= 2; + writememw(ss, ESP - 2, v); + if (cpu_state.abrt) + return; + ESP -= 2; } else { - writememw(ss, ((SP - 2) & 0xffff), v); - if (cpu_state.abrt) - return; - SP -= 2; + writememw(ss, ((SP - 2) & 0xffff), v); + if (cpu_state.abrt) + return; + SP -= 2; } } - -void +static void PUSHL(uint32_t v) { if (cpu_16bitbus) { - PUSHW(v >> 16); - PUSHW(v & 0xffff); + PUSHW(v >> 16); + PUSHW(v & 0xffff); } else { - if (stack32) { - writememl(ss, ESP - 4, v); - if (cpu_state.abrt) - return; - ESP -= 4; - } else { - writememl(ss, ((SP - 4) & 0xffff), v); - if (cpu_state.abrt) - return; - SP -= 4; - } + if (stack32) { + writememl(ss, ESP - 4, v); + if (cpu_state.abrt) + return; + ESP -= 4; + } else { + writememl(ss, ((SP - 4) & 0xffff), v); + if (cpu_state.abrt) + return; + SP -= 4; + } } } - -uint16_t -POPW() +static uint16_t +POPW(void) { uint16_t tempw; if (stack32) { - tempw = readmemw(ss, ESP); - if (cpu_state.abrt) - return 0; - ESP += 2; + tempw = readmemw(ss, ESP); + if (cpu_state.abrt) + return 0; + ESP += 2; } else { - tempw = readmemw(ss, SP); - if (cpu_state.abrt) - return 0; - SP += 2; + tempw = readmemw(ss, SP); + if (cpu_state.abrt) + return 0; + SP += 2; } return tempw; } - -uint32_t -POPL() +static uint32_t +POPL(void) { uint32_t templ; if (cpu_16bitbus) { - templ = POPW(); - templ |= (POPW() << 16); + templ = POPW(); + templ |= (POPW() << 16); } else { - if (stack32) { - templ = readmeml(ss, ESP); - if (cpu_state.abrt) - return 0; - ESP += 4; - } else { - templ = readmeml(ss, SP); - if (cpu_state.abrt) - return 0; - SP += 4; - } + if (stack32) { + templ = readmeml(ss, ESP); + if (cpu_state.abrt) + return 0; + ESP += 4; + } else { + templ = readmeml(ss, SP); + if (cpu_state.abrt) + return 0; + SP += 4; + } } return templ; } - +#ifdef OPS_286_386 #ifdef USE_NEW_DYNAREC -void loadcscall(uint16_t seg, uint32_t old_pc) +void +loadcscall_2386(uint16_t seg, uint32_t old_pc) #else -void loadcscall(uint16_t seg) +void +loadcscall_2386(uint16_t seg) +#endif +#else +#ifdef USE_NEW_DYNAREC +void +loadcscall(uint16_t seg, uint32_t old_pc) +#else +void +loadcscall(uint16_t seg) +#endif #endif { - uint16_t seg2, newss; - uint16_t segdat[4], segdat2[4]; - uint32_t addr, oldssbase = ss; - uint32_t oaddr, newpc; - uint32_t *segdat32 = (uint32_t *) segdat; - uint32_t *segdat232 = (uint32_t *) segdat2; - int count, type; - uint32_t oldss, oldsp, newsp, oldsp2; - uint16_t tempw; - x86seg *dt; + uint16_t seg2; + uint16_t newss; + uint16_t segdat[4]; + uint16_t segdat2[4]; + uint32_t addr; + uint32_t oldssbase = ss; + uint32_t oaddr; + uint32_t newpc; + uint32_t *segdat32 = (uint32_t *) segdat; + uint32_t *segdat232 = (uint32_t *) segdat2; + int count; + int type; + uint32_t oldss; + uint32_t oldsp; + uint32_t newsp; + uint32_t oldsp2; + uint16_t tempw; + const x86seg *dt; if ((msw & 1) && !(cpu_state.eflags & VM_FLAG)) { - x86seg_log("Protected mode CS load! %04X\n", seg); - if (!(seg & 0xfffc)) { - x86gpf("loadcscall(): Protected mode selector is zero",0); - return; - } - addr = seg & 0xfff8; - dt = (seg & 0x0004) ? &ldt : &gdt; - if ((addr + 7) > dt->limit) { - x86gpf("loadcscall(): Selector > DT limit", seg & 0xfffc); - return; - } - addr += dt->base; - read_descriptor(addr, segdat, segdat32, 1); - if (cpu_state.abrt) - return; - type = segdat[2] & 0x0f00; - newpc = segdat[0]; - if (type & 0x0800) - newpc |= segdat[3] << 16; + x86seg_log("Protected mode CS load! %04X\n", seg); + if (!(seg & 0xfffc)) { + x86gpf("loadcscall(): Protected mode selector is zero", 0); + return; + } + addr = seg & 0xfff8; + dt = (seg & 0x0004) ? &ldt : &gdt; + if ((addr + 7) > dt->limit) { + x86gpf("loadcscall(): Selector > DT limit", seg & 0xfffc); + return; + } + addr += dt->base; + read_descriptor(addr, segdat, segdat32, 1); + if (cpu_state.abrt) + return; + type = segdat[2] & 0x0f00; + newpc = segdat[0]; + if (type & 0x0800) + newpc |= segdat[3] << 16; - x86seg_log("Code seg call - %04X - %04X %04X %04X\n", seg, segdat[0], segdat[1], segdat[2]); - if (segdat[2] & 0x1000) { - if (!(segdat[2] & 0x0400)) { /* Not conforming */ - if ((seg & 0x0003) > CPL) { - x86gpf("loadcscall(): Non-conforming RPL > CPL", seg & 0xfffc); - return; - } - if (CPL != DPL) { - x86gpf("loadcscall(): Non-conforming CPL != DPL", seg & 0xfffc); - return; - } - } - if (CPL < DPL) { - x86gpf("loadcscall(): CPL < DPL", seg & 0xfffc); - return; - } - if (!(segdat[2] & 0x8000)) { - x86np("Load CS call not present", seg & 0xfffc); - return; - } - set_use32(segdat[3] & 0x0040); + x86seg_log("Code seg call - %04X - %04X %04X %04X\n", seg, segdat[0], segdat[1], segdat[2]); + if (segdat[2] & 0x1000) { + if (!(segdat[2] & 0x0400)) { /* Not conforming */ + if ((seg & 0x0003) > CPL) { + x86gpf("loadcscall(): Non-conforming RPL > CPL", seg & 0xfffc); + return; + } + if (CPL != DPL) { + x86gpf("loadcscall(): Non-conforming CPL != DPL", seg & 0xfffc); + return; + } + } + if (CPL < DPL) { + x86gpf("loadcscall(): CPL < DPL", seg & 0xfffc); + return; + } + if (!(segdat[2] & 0x8000)) { + x86np("Load CS call not present", seg & 0xfffc); + return; + } + set_use32(segdat[3] & 0x0040); - cpl_override = 1; - writememw(0, addr + 4, segdat[2] | 0x100); /* Set accessed bit */ - cpl_override = 0; + cpl_override = 1; + writememw(0, addr + 4, segdat[2] | 0x100); /* Set accessed bit */ + cpl_override = 0; - /* Conforming segments don't change CPL, so preserve existing CPL */ - if (segdat[2] & 0x0400) { - seg = (seg & 0xfffc) | CPL; - segdat[2] = (segdat[2] & ~(3 << (5+8))) | (CPL << (5+8)); - } else /* On non-conforming segments, set RPL = CPL */ - seg = (seg & 0xfffc) | CPL; - CS = seg; - do_seg_load(&cpu_state.seg_cs, segdat); - if ((CPL == 3) && (oldcpl != 3)) - flushmmucache_cr3(); + /* Conforming segments don't change CPL, so preserve existing CPL */ + if (segdat[2] & 0x0400) { + seg = (seg & 0xfffc) | CPL; + segdat[2] = (segdat[2] & ~(3 << (5 + 8))) | (CPL << (5 + 8)); + } else /* On non-conforming segments, set RPL = CPL */ + seg = (seg & 0xfffc) | CPL; + CS = seg; + do_seg_load(&cpu_state.seg_cs, segdat); + if ((CPL == 3) && (oldcpl != 3)) + flushmmucache_nopc(); #ifdef USE_NEW_DYNAREC - oldcpl = CPL; + oldcpl = CPL; #endif #ifdef ENABLE_X86SEG_LOG - x86seg_log("Complete\n"); + x86seg_log("Complete\n"); #endif - cycles -= timing_call_pm; - } else { - type = segdat[2] & 0x0f00; - x86seg_log("Type %03X\n", type); - switch (type) { - case 0x0400: /* Call gate */ - case 0x0c00: /* 386 Call gate */ - x86seg_log("Callgate %08X\n", cpu_state.pc); - cgate32 = (type & 0x0800); - cgate16 = !cgate32; + cycles -= timing_call_pm; + } else { + type = segdat[2] & 0x0f00; + x86seg_log("Type %03X\n", type); + switch (type) { + case 0x0400: /* Call gate */ + case 0x0c00: /* 386 Call gate */ + x86seg_log("Callgate %08X\n", cpu_state.pc); + cgate32 = (type & 0x0800); + cgate16 = !cgate32; #ifndef USE_NEW_DYNAREC - oldcs = CS; + oldcs = CS; #endif - count = segdat[2] & 0x001f; - if (DPL < CPL) { - x86gpf("loadcscall(): ex DPL < CPL",seg & 0xfffc); - return; - } - if (DPL < (seg & 0x0003)) { - x86gpf("loadcscall(): ex DPL < RPL", seg & 0xfffc); - return; - } - if (!(segdat[2] & 0x8000)) { - x86np("Call gate not present", seg & 0xfffc); - return; - } - seg2 = segdat[1]; + count = segdat[2] & 0x001f; + if (DPL < CPL) { + x86gpf("loadcscall(): ex DPL < CPL", seg & 0xfffc); + return; + } + if (DPL < (seg & 0x0003)) { + x86gpf("loadcscall(): ex DPL < RPL", seg & 0xfffc); + return; + } + if (!(segdat[2] & 0x8000)) { + x86np("Call gate not present", seg & 0xfffc); + return; + } + seg2 = segdat[1]; - x86seg_log("New address : %04X:%08X\n", seg2, newpc); + x86seg_log("New address : %04X:%08X\n", seg2, newpc); - if (!(seg2 & 0xfffc)) { - x86gpf("loadcscall(): ex selector is NULL", 0); - return; - } - addr = seg2 & 0xfff8; - dt = (seg2 & 0x0004) ? &ldt : &gdt; - if ((addr + 7) > dt->limit) { - x86gpf("loadcscall(): ex Selector > DT limit", seg2 & 0xfff8); - return; - } - addr += dt->base; - read_descriptor(addr, segdat, segdat32, 1); - if (cpu_state.abrt) - return; + if (!(seg2 & 0xfffc)) { + x86gpf("loadcscall(): ex selector is NULL", 0); + return; + } + addr = seg2 & 0xfff8; + dt = (seg2 & 0x0004) ? &ldt : &gdt; + if ((addr + 7) > dt->limit) { + x86gpf("loadcscall(): ex Selector > DT limit", seg2 & 0xfff8); + return; + } + addr += dt->base; + read_descriptor(addr, segdat, segdat32, 1); + if (cpu_state.abrt) + return; - x86seg_log("Code seg2 call - %04X - %04X %04X %04X\n", seg2, segdat[0], segdat[1], segdat[2]); + x86seg_log("Code seg2 call - %04X - %04X %04X %04X\n", seg2, segdat[0], segdat[1], segdat[2]); - if (DPL > CPL) { - x86gpf("loadcscall(): ex DPL > CPL", seg2 & 0xfffc); - return; - } - if (!(segdat[2] & 0x8000)) { - x86seg_log("Call gate CS not present %04X\n", seg2); - x86np("Call gate CS not present", seg2 & 0xfffc); - return; - } + if (DPL > CPL) { + x86gpf("loadcscall(): ex DPL > CPL", seg2 & 0xfffc); + return; + } + if (!(segdat[2] & 0x8000)) { + x86seg_log("Call gate CS not present %04X\n", seg2); + x86np("Call gate CS not present", seg2 & 0xfffc); + return; + } - switch (segdat[2] & 0x1f00) { - case 0x1800: case 0x1900: case 0x1a00: case 0x1b00: /* Non-conforming code */ - if (DPL < CPL) { + switch (segdat[2] & 0x1f00) { + case 0x1800: + case 0x1900: + case 0x1a00: + case 0x1b00: /* Non-conforming code */ + if (DPL < CPL) { #ifdef USE_NEW_DYNAREC - uint16_t oldcs = CS; + uint16_t oldcs = CS; #endif - oaddr = addr; - /* Load new stack */ - oldss = SS; - oldsp = oldsp2 = ESP; - cpl_override = 1; - if (tr.access & 8) { - addr = 4 + tr.base + (DPL << 3); - newss = readmemw(0, addr + 4); - if (cpu_16bitbus) { - newsp = readmemw(0, addr); - newsp |= (readmemw(0, addr + 2) << 16); - } else - newsp = readmeml(0, addr); - } else { - addr = 2 + tr.base + (DPL * 4); - newss = readmemw(0, addr + 2); - newsp = readmemw(0, addr); - } - cpl_override = 0; - if (cpu_state.abrt) - return; - x86seg_log("New stack %04X:%08X\n", newss, newsp); - if (!(newss & 0xfffc)) { - x86ts(NULL, newss & 0xfffc); - return; - } - addr = newss & 0xfff8; - dt = (newss & 0x0004) ? &ldt : &gdt; - if ((addr + 7) > dt->limit) { - fatal("Bigger than DT limit %04X %08X %04X CSC SS\n", newss, addr, dt->limit); - x86ts(NULL, newss & ~3); - return; - } - addr += dt->base; - x86seg_log("Read stack seg\n"); - read_descriptor(addr, segdat2, segdat232, 1); - if (cpu_state.abrt) - return; - x86seg_log("Read stack seg done!\n"); - if (((newss & 0x0003) != DPL) || (DPL2 != DPL)) { - x86ts(NULL, newss & 0xfffc); - return; - } - if ((segdat2[2] & 0x1a00) != 0x1200) { - x86ts("Call gate loading SS unknown type", newss & 0xfffc); - return; - } - if (!(segdat2[2] & 0x8000)) { - x86ss("Call gate loading SS not present", newss & 0xfffc); - return; - } - if (!stack32) - oldsp &= 0xffff; - SS = newss; - set_stack32((segdat2[3] & 0x0040) ? 1 : 0); - if (stack32) - ESP = newsp; - else - SP = newsp; + oaddr = addr; + /* Load new stack */ + oldss = SS; + oldsp = oldsp2 = ESP; + cpl_override = 1; + if (tr.access & 8) { + addr = 4 + tr.base + (DPL << 3); + newss = readmemw(0, addr + 4); + if (cpu_16bitbus) { + newsp = readmemw(0, addr); + newsp |= (readmemw(0, addr + 2) << 16); + } else + newsp = readmeml(0, addr); + } else { + addr = 2 + tr.base + (DPL * 4); + newss = readmemw(0, addr + 2); + newsp = readmemw(0, addr); + } + cpl_override = 0; + if (cpu_state.abrt) + return; + x86seg_log("New stack %04X:%08X\n", newss, newsp); + if (!(newss & 0xfffc)) { + x86ts(NULL, newss & 0xfffc); + return; + } + addr = newss & 0xfff8; + dt = (newss & 0x0004) ? &ldt : &gdt; + if ((addr + 7) > dt->limit) { + fatal("Bigger than DT limit %04X %08X %04X CSC SS\n", newss, addr, dt->limit); + x86ts(NULL, newss & ~3); + return; + } + addr += dt->base; + x86seg_log("Read stack seg\n"); + read_descriptor(addr, segdat2, segdat232, 1); + if (cpu_state.abrt) + return; + x86seg_log("Read stack seg done!\n"); + if (((newss & 0x0003) != DPL) || (DPL2 != DPL)) { + x86ts(NULL, newss & 0xfffc); + return; + } + if ((segdat2[2] & 0x1a00) != 0x1200) { + x86ts("Call gate loading SS unknown type", newss & 0xfffc); + return; + } + if (!(segdat2[2] & 0x8000)) { + x86ss("Call gate loading SS not present", newss & 0xfffc); + return; + } + if (!stack32) + oldsp &= 0xffff; + SS = newss; + set_stack32((segdat2[3] & 0x0040) ? 1 : 0); + if (stack32) + ESP = newsp; + else + SP = newsp; - do_seg_load(&cpu_state.seg_ss, segdat2); + do_seg_load(&cpu_state.seg_ss, segdat2); - x86seg_log("Set access 1\n"); - cpl_override = 1; - writememw(0, addr + 4, segdat2[2] | 0x100); /* Set accessed bit */ - cpl_override = 0; + x86seg_log("Set access 1\n"); + cpl_override = 1; + writememw(0, addr + 4, segdat2[2] | 0x100); /* Set accessed bit */ + cpl_override = 0; - CS = seg2; - do_seg_load(&cpu_state.seg_cs, segdat); - if ((CPL == 3) && (oldcpl != 3)) - flushmmucache_cr3(); + CS = seg2; + do_seg_load(&cpu_state.seg_cs, segdat); + if ((CPL == 3) && (oldcpl != 3)) + flushmmucache_nopc(); #ifdef USE_NEW_DYNAREC - oldcpl = CPL; + oldcpl = CPL; #endif - set_use32(segdat[3] & 0x0040); - cpu_state.pc = newpc; + set_use32(segdat[3] & 0x0040); + cpu_state.pc = newpc; - x86seg_log("Set access 2\n"); + x86seg_log("Set access 2\n"); - cpl_override = 1; - writememw(0, oaddr + 4, segdat[2] | 0x100); /* Set accessed bit */ - cpl_override = 0; + cpl_override = 1; + writememw(0, oaddr + 4, segdat[2] | 0x100); /* Set accessed bit */ + cpl_override = 0; - x86seg_log("Type %04X\n", type); - if (type == 0x0c00) { - PUSHL(oldss); - PUSHL(oldsp2); - if (cpu_state.abrt) { - SS = oldss; - ESP = oldsp2; + x86seg_log("Type %04X\n", type); + if (type == 0x0c00) { + PUSHL(oldss); + PUSHL(oldsp2); + if (cpu_state.abrt) { + SS = oldss; + ESP = oldsp2; #ifdef USE_NEW_DYNAREC - CS = oldcs; + CS = oldcs; #endif - return; - } - if (count) { - while (count--) { - PUSHL(readmeml(oldssbase, oldsp + (count << 2))); - if (cpu_state.abrt) { - SS = oldss; - ESP = oldsp2; + return; + } + if (count) { + while (count--) { + PUSHL(readmeml(oldssbase, oldsp + (count << 2))); + if (cpu_state.abrt) { + SS = oldss; + ESP = oldsp2; #ifdef USE_NEW_DYNAREC - CS = oldcs; + CS = oldcs; #endif - return; - } - } - } - } else { - x86seg_log("Stack %04X\n", SP); - PUSHW(oldss); - x86seg_log("Write SS to %04X:%04X\n", SS, SP); - PUSHW(oldsp2); - if (cpu_state.abrt) { - SS = oldss; - ESP = oldsp2; + return; + } + } + } + } else { + x86seg_log("Stack %04X\n", SP); + PUSHW(oldss); + x86seg_log("Write SS to %04X:%04X\n", SS, SP); + PUSHW(oldsp2); + if (cpu_state.abrt) { + SS = oldss; + ESP = oldsp2; #ifdef USE_NEW_DYNAREC - CS = oldcs; + CS = oldcs; #endif - return; - } - x86seg_log("Write SP to %04X:%04X\n", SS, SP); - if (count) { - while (count--) { - tempw = readmemw(oldssbase, (oldsp & 0xffff) + (count << 1)); - x86seg_log("PUSH %04X\n", tempw); - PUSHW(tempw); - if (cpu_state.abrt) { - SS = oldss; - ESP = oldsp2; + return; + } + x86seg_log("Write SP to %04X:%04X\n", SS, SP); + if (count) { + while (count--) { + tempw = readmemw(oldssbase, (oldsp & 0xffff) + (count << 1)); + x86seg_log("PUSH %04X\n", tempw); + PUSHW(tempw); + if (cpu_state.abrt) { + SS = oldss; + ESP = oldsp2; #ifdef USE_NEW_DYNAREC - CS = oldcs; + CS = oldcs; #endif - return; - } - } - } - } - cycles -= timing_call_pm_gate_inner; - break; - } else if (DPL > CPL) { - x86gpf("loadcscall(): Call PM Gate Inner DPL > CPL",seg2 & 0xfffc); - return; - } - /*FALLTHROUGH*/ - case 0x1c00: case 0x1d00: case 0x1e00: case 0x1f00: /* Conforming */ - CS = seg2; - do_seg_load(&cpu_state.seg_cs, segdat); - if ((CPL == 3) && (oldcpl != 3)) - flushmmucache_cr3(); + return; + } + } + } + } + cycles -= timing_call_pm_gate_inner; + break; + } else if (DPL > CPL) { + x86gpf("loadcscall(): Call PM Gate Inner DPL > CPL", seg2 & 0xfffc); + return; + } + fallthrough; + case 0x1c00: + case 0x1d00: + case 0x1e00: + case 0x1f00: /* Conforming */ + CS = seg2; + do_seg_load(&cpu_state.seg_cs, segdat); + if ((CPL == 3) && (oldcpl != 3)) + flushmmucache_nopc(); #ifdef USE_NEW_DYNAREC - oldcpl = CPL; + oldcpl = CPL; #endif - set_use32(segdat[3] & 0x0040); - cpu_state.pc = newpc; + set_use32(segdat[3] & 0x0040); + cpu_state.pc = newpc; - cpl_override = 1; - writememw(0, addr + 4, segdat[2] | 0x100); /* Set accessed bit */ - cpl_override = 0; - cycles -= timing_call_pm_gate; - break; + cpl_override = 1; + writememw(0, addr + 4, segdat[2] | 0x100); /* Set accessed bit */ + cpl_override = 0; + cycles -= timing_call_pm_gate; + break; - default: - x86gpf("loadcscall(): Unknown subtype", seg2 & 0xfffc); - return; - } - break; + default: + x86gpf("loadcscall(): Unknown subtype", seg2 & 0xfffc); + return; + } + break; - case 0x0100: /* 286 Task gate */ - case 0x0900: /* 386 Task gate */ + case 0x0100: /* 286 Task gate */ + case 0x0900: /* 386 Task gate */ #ifdef USE_NEW_DYNAREC - cpu_state.pc = old_pc; + cpu_state.pc = old_pc; #else - cpu_state.pc = oxpc; + cpu_state.pc = oxpc; #endif - cpl_override = 1; - taskswitch286(seg, segdat, segdat[2] & 0x0800); - cpl_override = 0; - break; + cpl_override = 1; + op_taskswitch286(seg, segdat, segdat[2] & 0x0800); + cpl_override = 0; + break; - default: - x86gpf("loadcscall(): Unknown type", seg & 0xfffc); - return; - } - } + default: + x86gpf("loadcscall(): Unknown type", seg & 0xfffc); + return; + } + } } else { - cpu_state.seg_cs.base = seg << 4; - cpu_state.seg_cs.limit = 0xffff; - cpu_state.seg_cs.limit_low = 0; - cpu_state.seg_cs.limit_high = 0xffff; - cpu_state.seg_cs.seg = seg; - cpu_state.seg_cs.access = (cpu_state.eflags & VM_FLAG) ? 0xe2 : 0x82; - cpu_state.seg_cs.ar_high = 0x10; - if ((CPL == 3) && (oldcpl != 3)) - flushmmucache_cr3(); + cpu_state.seg_cs.base = seg << 4; + cpu_state.seg_cs.limit = 0xffff; + cpu_state.seg_cs.limit_low = 0; + cpu_state.seg_cs.limit_high = 0xffff; + cpu_state.seg_cs.seg = seg; + cpu_state.seg_cs.access = (cpu_state.eflags & VM_FLAG) ? 0xe2 : 0x82; + cpu_state.seg_cs.ar_high = 0x10; + if ((CPL == 3) && (oldcpl != 3)) + flushmmucache_nopc(); #ifdef USE_NEW_DYNAREC - oldcpl = CPL; + oldcpl = CPL; #endif } } - void +#ifdef OPS_286_386 +pmoderetf_2386(int is32, uint16_t off) +#else pmoderetf(int is32, uint16_t off) +#endif { - uint16_t segdat[4], segdat2[4], seg,newss; - uint32_t newpc, newsp, addr, oaddr; - uint32_t oldsp = ESP; - uint32_t *segdat32 = (uint32_t *) segdat; - uint32_t *segdat232 = (uint32_t *) segdat2; - x86seg *dt; + uint16_t segdat[4]; + uint16_t segdat2[4]; + uint16_t seg; + uint16_t newss; + uint32_t newpc; + uint32_t newsp; + uint32_t addr; + uint32_t oaddr; + uint32_t oldsp = ESP; + uint32_t *segdat32 = (uint32_t *) segdat; + uint32_t *segdat232 = (uint32_t *) segdat2; + const x86seg *dt; x86seg_log("RETF %i %04X:%04X %08X %04X\n", is32, CS, cpu_state.pc, cr0, cpu_state.eflags); if (is32) { - newpc = POPL(); - seg = POPL(); + newpc = POPL(); + seg = POPL(); } else { - x86seg_log("PC read from %04X:%04X\n", SS, SP); - newpc = POPW(); - x86seg_log("CS read from %04X:%04X\n", SS, SP); - seg = POPW(); + x86seg_log("PC read from %04X:%04X\n", SS, SP); + newpc = POPW(); + x86seg_log("CS read from %04X:%04X\n", SS, SP); + seg = POPW(); } if (cpu_state.abrt) - return; + return; x86seg_log("Return to %04X:%08X\n", seg, newpc); if ((seg & 0x0003) < CPL) { - ESP = oldsp; - x86gpf("pmoderetf(): seg < CPL", seg & 0xfffc); - return; + ESP = oldsp; + x86gpf("pmoderetf(): seg < CPL", seg & 0xfffc); + return; } if (!(seg & 0xfffc)) { - x86gpf("pmoderetf(): seg is NULL", 0); - return; + x86gpf("pmoderetf(): seg is NULL", 0); + return; } addr = seg & 0xfff8; - dt = (seg & 0x0004) ? &ldt : &gdt; + dt = (seg & 0x0004) ? &ldt : &gdt; if ((addr + 7) > dt->limit) { - x86gpf("pmoderetf(): Selector > DT limit", seg & 0xfffc); - return; + x86gpf("pmoderetf(): Selector > DT limit", seg & 0xfffc); + return; } addr += dt->base; read_descriptor(addr, segdat, segdat32, 1); if (cpu_state.abrt) { - ESP = oldsp; - return; + ESP = oldsp; + return; } oaddr = addr; x86seg_log("CPL %i RPL %i %i\n", CPL, seg & 0x0003, is32); if (stack32) - ESP += off; + ESP += off; else - SP += off; + SP += off; if (CPL == (seg & 0x0003)) { - x86seg_log("RETF CPL = RPL %04X\n", segdat[2]); - switch (segdat[2] & 0x1f00) { - case 0x1800: case 0x1900: case 0x1a00: case 0x1b00: /* Non-conforming */ - if (CPL != DPL) { - ESP = oldsp; - x86gpf("pmoderetf(): Non-conforming CPL != DPL", seg & 0xfffc); - return; - } - break; - case 0x1c00: case 0x1d00: case 0x1e00: case 0x1f00: /* Conforming */ - if (CPL < DPL) { - ESP = oldsp; - x86gpf("pmoderetf(): Conforming CPL < DPL", seg & 0xfffc); - return; - } - break; - default: - x86gpf("pmoderetf(): Unknown type", seg & 0xfffc); - return; - } - if (!(segdat[2] & 0x8000)) { - ESP = oldsp; - x86np("RETF CS not present", seg & 0xfffc); - return; - } + x86seg_log("RETF CPL = RPL %04X\n", segdat[2]); + switch (segdat[2] & 0x1f00) { + case 0x1800: + case 0x1900: + case 0x1a00: + case 0x1b00: /* Non-conforming */ + if (CPL != DPL) { + ESP = oldsp; + x86gpf("pmoderetf(): Non-conforming CPL != DPL", seg & 0xfffc); + return; + } + break; + case 0x1c00: + case 0x1d00: + case 0x1e00: + case 0x1f00: /* Conforming */ + if (CPL < DPL) { + ESP = oldsp; + x86gpf("pmoderetf(): Conforming CPL < DPL", seg & 0xfffc); + return; + } + break; + default: + x86gpf("pmoderetf(): Unknown type", seg & 0xfffc); + return; + } + if (!(segdat[2] & 0x8000)) { + ESP = oldsp; + x86np("RETF CS not present", seg & 0xfffc); + return; + } - cpl_override = 1; - writememw(0, addr + 4, segdat[2] | 0x100); /* Set accessed bit */ - cpl_override = 0; + cpl_override = 1; + writememw(0, addr + 4, segdat[2] | 0x100); /* Set accessed bit */ + cpl_override = 0; - cpu_state.pc = newpc; - if (segdat[2] & 0x0400) - segdat[2] = (segdat[2] & ~(3 << 13)) | ((seg & 3) << 13); - CS = seg; - do_seg_load(&cpu_state.seg_cs, segdat); - cpu_state.seg_cs.access = (cpu_state.seg_cs.access & ~(3 << 5)) | ((CS & 3) << 5); - if ((CPL == 3) && (oldcpl != 3)) - flushmmucache_cr3(); + cpu_state.pc = newpc; + if (segdat[2] & 0x0400) + segdat[2] = (segdat[2] & ~(3 << 13)) | ((seg & 3) << 13); + CS = seg; + do_seg_load(&cpu_state.seg_cs, segdat); + cpu_state.seg_cs.access = (cpu_state.seg_cs.access & ~(3 << 5)) | ((CS & 3) << 5); + if ((CPL == 3) && (oldcpl != 3)) + flushmmucache_nopc(); #ifdef USE_NEW_DYNAREC - oldcpl = CPL; + oldcpl = CPL; #endif - set_use32(segdat[3] & 0x0040); + set_use32(segdat[3] & 0x0040); - cycles -= timing_retf_pm; + cycles -= timing_retf_pm; } else { - switch (segdat[2] & 0x1f00) { - case 0x1800: case 0x1900: case 0x1a00: case 0x1b00: /* Non-conforming */ - if ((seg & 0x0003) != DPL) { - ESP = oldsp; - x86gpf("pmoderetf(): Non-conforming RPL != DPL", seg & 0xfffc); - return; - } - x86seg_log("RETF non-conforming, %i %i\n", seg & 0x0003, DPL); - break; - case 0x1c00: case 0x1d00: case 0x1e00: case 0x1f00: /* Conforming */ - if ((seg & 0x0003) < DPL) { - ESP = oldsp; - x86gpf("pmoderetf(): Conforming RPL < DPL", seg & 0xfffc); - return; - } - x86seg_log("RETF conforming, %i %i\n", seg & 0x0003, DPL); - break; - default: - ESP = oldsp; - x86gpf("pmoderetf(): Unknown type", seg & 0xfffc); - return; - } - if (!(segdat[2] & 0x8000)) { - ESP = oldsp; - x86np("RETF CS not present", seg & 0xfffc); - return; - } - if (is32) { - newsp = POPL(); - newss = POPL(); - if (cpu_state.abrt) - return; - } else { - x86seg_log("SP read from %04X:%04X\n", SS, SP); - newsp = POPW(); - x86seg_log("SS read from %04X:%04X\n", SS, SP); - newss = POPW(); - if (cpu_state.abrt) - return; - } - x86seg_log("Read new stack : %04X:%04X (%08X)\n", newss, newsp, ldt.base); - if (!(newss & 0xfffc)) { - ESP = oldsp; - x86gpf("pmoderetf(): New SS selector is zero",newss&~3); - return; - } - addr = newss & 0xfff8; - dt = (newss & 0x0004) ? &ldt : &gdt; - if ((addr + 7) > dt->limit) { - ESP = oldsp; - x86gpf("pmoderetf(): New SS selector > DT limit", newss & 0xfffc); - return; - } - addr += dt->base; - read_descriptor(addr, segdat2, segdat232, 1); - if (cpu_state.abrt) { - ESP = oldsp; - return; - } - x86seg_log("Segment data %04X %04X %04X %04X\n", segdat2[0], segdat2[1], segdat2[2], segdat2[3]); - if ((newss & 0x0003) != (seg & 0x0003)) { - ESP = oldsp; - x86gpf("pmoderetf(): New SS RPL > CS RPL", newss & 0xfffc); - return; - } - if ((segdat2[2] & 0x1a00) != 0x1200) { - ESP = oldsp; - x86gpf("pmoderetf(): New SS unknown type", newss & 0xfffc); - return; - } - if (!(segdat2[2] & 0x8000)) { - ESP = oldsp; - x86np("RETF loading SS not present", newss & 0xfffc); - return; - } - if (DPL2 != (seg & 3)) { - ESP = oldsp; - x86gpf("pmoderetf(): New SS DPL != CS RPL",newss & 0xfffc); - return; - } - SS = newss; - set_stack32((segdat2[3] & 0x0040) ? 1 : 0); - if (stack32) - ESP = newsp; - else - SP = newsp; - do_seg_load(&cpu_state.seg_ss, segdat2); + switch (segdat[2] & 0x1f00) { + case 0x1800: + case 0x1900: + case 0x1a00: + case 0x1b00: /* Non-conforming */ + if ((seg & 0x0003) != DPL) { + ESP = oldsp; + x86gpf("pmoderetf(): Non-conforming RPL != DPL", seg & 0xfffc); + return; + } + x86seg_log("RETF non-conforming, %i %i\n", seg & 0x0003, DPL); + break; + case 0x1c00: + case 0x1d00: + case 0x1e00: + case 0x1f00: /* Conforming */ + if ((seg & 0x0003) < DPL) { + ESP = oldsp; + x86gpf("pmoderetf(): Conforming RPL < DPL", seg & 0xfffc); + return; + } + x86seg_log("RETF conforming, %i %i\n", seg & 0x0003, DPL); + break; + default: + ESP = oldsp; + x86gpf("pmoderetf(): Unknown type", seg & 0xfffc); + return; + } + if (!(segdat[2] & 0x8000)) { + ESP = oldsp; + x86np("RETF CS not present", seg & 0xfffc); + return; + } + if (is32) { + newsp = POPL(); + newss = POPL(); + if (cpu_state.abrt) + return; + } else { + x86seg_log("SP read from %04X:%04X\n", SS, SP); + newsp = POPW(); + x86seg_log("SS read from %04X:%04X\n", SS, SP); + newss = POPW(); + if (cpu_state.abrt) + return; + } + x86seg_log("Read new stack : %04X:%04X (%08X)\n", newss, newsp, ldt.base); + if (!(newss & 0xfffc)) { + ESP = oldsp; + x86gpf("pmoderetf(): New SS selector is zero", newss & ~3); + return; + } + addr = newss & 0xfff8; + dt = (newss & 0x0004) ? &ldt : &gdt; + if ((addr + 7) > dt->limit) { + ESP = oldsp; + x86gpf("pmoderetf(): New SS selector > DT limit", newss & 0xfffc); + return; + } + addr += dt->base; + read_descriptor(addr, segdat2, segdat232, 1); + if (cpu_state.abrt) { + ESP = oldsp; + return; + } + x86seg_log("Segment data %04X %04X %04X %04X\n", segdat2[0], segdat2[1], segdat2[2], segdat2[3]); + if ((newss & 0x0003) != (seg & 0x0003)) { + ESP = oldsp; + x86gpf("pmoderetf(): New SS RPL > CS RPL", newss & 0xfffc); + return; + } + if ((segdat2[2] & 0x1a00) != 0x1200) { + ESP = oldsp; + x86gpf("pmoderetf(): New SS unknown type", newss & 0xfffc); + return; + } + if (!(segdat2[2] & 0x8000)) { + ESP = oldsp; + x86np("RETF loading SS not present", newss & 0xfffc); + return; + } + if (DPL2 != (seg & 3)) { + ESP = oldsp; + x86gpf("pmoderetf(): New SS DPL != CS RPL", newss & 0xfffc); + return; + } + SS = newss; + set_stack32((segdat2[3] & 0x0040) ? 1 : 0); + if (stack32) + ESP = newsp; + else + SP = newsp; + do_seg_load(&cpu_state.seg_ss, segdat2); - cpl_override = 1; - writememw(0, addr + 4, segdat2[2] | 0x100); /* Set accessed bit */ - writememw(0, oaddr + 4, segdat[2] | 0x100); /* Set accessed bit */ - cpl_override = 0; - /* Conforming segments don't change CPL, so CPL = RPL */ - if (segdat[2] & 0x0400) - segdat[2] = (segdat[2] & ~(3 << 13)) | ((seg & 3) << 13); - cpu_state.pc = newpc; - CS = seg; - do_seg_load(&cpu_state.seg_cs, segdat); - if ((CPL == 3) && (oldcpl != 3)) - flushmmucache_cr3(); + cpl_override = 1; + writememw(0, addr + 4, segdat2[2] | 0x100); /* Set accessed bit */ + writememw(0, oaddr + 4, segdat[2] | 0x100); /* Set accessed bit */ + cpl_override = 0; + /* Conforming segments don't change CPL, so CPL = RPL */ + if (segdat[2] & 0x0400) + segdat[2] = (segdat[2] & ~(3 << 13)) | ((seg & 3) << 13); + cpu_state.pc = newpc; + CS = seg; + do_seg_load(&cpu_state.seg_cs, segdat); + if ((CPL == 3) && (oldcpl != 3)) + flushmmucache_nopc(); #ifdef USE_NEW_DYNAREC - oldcpl = CPL; + oldcpl = CPL; #endif - set_use32(segdat[3] & 0x0040); + set_use32(segdat[3] & 0x0040); - if (stack32) - ESP += off; - else - SP += off; + if (stack32) + ESP += off; + else + SP += off; - check_seg_valid(&cpu_state.seg_ds); - check_seg_valid(&cpu_state.seg_es); - check_seg_valid(&cpu_state.seg_fs); - check_seg_valid(&cpu_state.seg_gs); - cycles -= timing_retf_pm_outer; + check_seg_valid(&cpu_state.seg_ds); + check_seg_valid(&cpu_state.seg_es); + check_seg_valid(&cpu_state.seg_fs); + check_seg_valid(&cpu_state.seg_gs); + cycles -= timing_retf_pm_outer; } } - void +#ifdef OPS_286_386 +pmodeint_2386(int num, int soft) +#else pmodeint(int num, int soft) +#endif { - uint16_t segdat[4], segdat2[4]; - uint16_t segdat3[4]; - uint16_t newss, seg = 0; - int type, new_cpl; - uint32_t addr, oaddr; - uint32_t oldss, oldsp; - uint32_t newsp; - uint32_t *segdat32 = (uint32_t *) segdat; - uint32_t *segdat232 = (uint32_t *) segdat2; - uint32_t *segdat332 = (uint32_t *) segdat3; - x86seg *dt; + uint16_t segdat[4]; + uint16_t segdat2[4]; + uint16_t segdat3[4]; + uint16_t newss; + uint16_t seg = 0; + int type; + int new_cpl; + uint32_t addr; + uint32_t oaddr; + uint32_t oldss; + uint32_t oldsp; + uint32_t newsp; + uint32_t *segdat32 = (uint32_t *) segdat; + uint32_t *segdat232 = (uint32_t *) segdat2; + uint32_t *segdat332 = (uint32_t *) segdat3; + const x86seg *dt; if ((cpu_state.eflags & VM_FLAG) && (IOPL != 3) && soft) { - x86seg_log("V86 banned int\n"); - x86gpf("pmodeint(): V86 banned int", 0); - return; + x86seg_log("V86 banned int\n"); + x86gpf("pmodeint(): V86 banned int", 0); + return; } addr = (num << 3); if ((addr + 7) > idt.limit) { - if (num == 0x08) { - /* Triple fault - reset! */ - softresetx86(); - cpu_set_edx(); - } else if (num == 0x0d) - pmodeint(8, 0); - else - x86gpf("pmodeint(): Vector > IDT limit", (num << 3) + 2 + !soft); - x86seg_log("addr >= IDT.limit\n"); - return; + if (num == 0x08) { + /* Triple fault - reset! */ + softresetx86(); + cpu_set_edx(); + } else if (num == 0x0d) + op_pmodeint(8, 0); + else + x86gpf("pmodeint(): Vector > IDT limit", (num << 3) + 2 + !soft); + x86seg_log("addr >= IDT.limit\n"); + return; } addr += idt.base; read_descriptor(addr, segdat, segdat32, 1); if (cpu_state.abrt) { - x86seg_log("Abrt reading from %08X\n", addr); - return; + x86seg_log("Abrt reading from %08X\n", addr); + return; } oaddr = addr; x86seg_log("Addr %08X seg %04X %04X %04X %04X\n", addr, segdat[0], segdat[1], segdat[2], segdat[3]); if (!(segdat[2] & 0x1f00)) { - /* This fires on all V86 interrupts in EMM386. Mark as expected to prevent code churn */ - if (cpu_state.eflags & VM_FLAG) - x86gpf_expected("pmodeint(): Expected vector descriptor with bad type", (num << 3) + 2); - else - x86gpf("pmodeint(): Vector descriptor with bad type", (num << 3) + 2); - return; + /* This fires on all V86 interrupts in EMM386. Mark as expected to prevent code churn */ + if (cpu_state.eflags & VM_FLAG) + x86gpf_expected("pmodeint(): Expected vector descriptor with bad type", (num << 3) + 2); + else + x86gpf("pmodeint(): Vector descriptor with bad type", (num << 3) + 2); + return; } if ((DPL < CPL) && soft) { - x86gpf("pmodeint(): Vector DPL < CPL", (num << 3) + 2); - return; + x86gpf("pmodeint(): Vector DPL < CPL", (num << 3) + 2); + return; } type = segdat[2] & 0x1f00; if (((type == 0x0e00) || (type == 0x0f00)) && !is386) { - x86gpf("pmodeint(): Gate type illegal on 286", seg & 0xfffc); - return; + x86gpf("pmodeint(): Gate type illegal on 286", seg & 0xfffc); + return; } switch (type) { - case 0x0600: case 0x0700: case 0x0e00: case 0x0f00: /* Interrupt and trap gates */ - intgatesize = (type >= 0x0800) ? 32 : 16; - if (!(segdat[2] & 0x8000)) { - x86np("Int gate not present", (num << 3) | 2); - return; - } - seg = segdat[1]; - new_cpl = seg & 0x0003; + case 0x0600: + case 0x0700: + case 0x0e00: + case 0x0f00: /* Interrupt and trap gates */ + intgatesize = (type >= 0x0800) ? 32 : 16; + if (!(segdat[2] & 0x8000)) { + x86np("Int gate not present", (num << 3) | 2); + return; + } + seg = segdat[1]; + new_cpl = seg & 0x0003; - addr = seg & 0xfff8; - dt = (seg & 0x0004) ? &ldt : &gdt; - if ((addr + 7) > dt->limit) { - x86gpf("pmodeint(): Interrupt or trap gate selector > DT limit", seg & 0xfffc); - return; - } - addr += dt->base; - read_descriptor(addr, segdat2, segdat232, 1); - if (cpu_state.abrt) - return; - oaddr = addr; - - if (DPL2 > CPL) { - x86gpf("pmodeint(): Interrupt or trap gate DPL > CPL", seg & 0xfffc); - return; - } - switch (segdat2[2] & 0x1f00) { - case 0x1800: case 0x1900: case 0x1a00: case 0x1b00: /* Non-conforming */ - if (DPL2 < CPL) { - if (!(segdat2[2] & 0x8000)) { - x86np("Int gate CS not present", segdat[1] & 0xfffc); - return; - } - if ((cpu_state.eflags & VM_FLAG) && DPL2) { - x86gpf("pmodeint(): Interrupt or trap gate non-zero DPL in V86 mode", segdat[1] & 0xfffc); - return; - } - /* Load new stack */ - oldss = SS; - oldsp = ESP; - cpl_override = 1; - if (tr.access & 8) { - addr = 4 + tr.base + (DPL2 << 3); - newss = readmemw(0, addr + 4); - newsp = readmeml(0, addr); - } else { - addr = 2 + tr.base + (DPL2 << 2); - newss = readmemw(0, addr + 2); - newsp = readmemw(0, addr); - } - cpl_override = 0; - if (!(newss & 0xfffc)) { - x86ss("pmodeint(): Interrupt or trap gate stack segment is NULL", newss & 0xfffc); - return; - } - addr = newss & 0xfff8; - dt = (newss & 0x0004) ? &ldt : &gdt; - if ((addr + 7) > dt->limit) { - x86ss("pmodeint(): Interrupt or trap gate stack segment > DT", newss & 0xfffc); - return; - } - addr += dt->base; - read_descriptor(addr, segdat3, segdat332, 1); - if (cpu_state.abrt) - return; - if ((newss & 3) != DPL2) { - x86ss("pmodeint(): Interrupt or trap gate tack segment RPL > DPL",newss & 0xfffc); - return; - } - if (DPL3 != DPL2) { - x86ss("pmodeint(): Interrupt or trap gate tack segment DPL > DPL",newss & 0xfffc); - return; - } - if ((segdat3[2] & 0x1a00) != 0x1200) { - x86ss("pmodeint(): Interrupt or trap gate stack segment bad type", newss & 0xfffc); - return; - } - if (!(segdat3[2] & 0x8000)) { - x86np("Int gate loading SS not present", newss & 0xfffc); - return; - } - SS = newss; - set_stack32((segdat3[3] & 0x0040) ? 1 : 0); - if (stack32) - ESP = newsp; - else - SP = newsp; - do_seg_load(&cpu_state.seg_ss, segdat3); + addr = seg & 0xfff8; + dt = (seg & 0x0004) ? &ldt : &gdt; + if ((addr + 7) > dt->limit) { + x86gpf("pmodeint(): Interrupt or trap gate selector > DT limit", seg & 0xfffc); + return; + } + addr += dt->base; + read_descriptor(addr, segdat2, segdat232, 1); + if (cpu_state.abrt) + return; + oaddr = addr; - cpl_override = 1; - writememw(0, addr + 4, segdat3[2] | 0x100); /* Set accessed bit */ - cpl_override = 0; + if (DPL2 > CPL) { + x86gpf("pmodeint(): Interrupt or trap gate DPL > CPL", seg & 0xfffc); + return; + } + switch (segdat2[2] & 0x1f00) { + case 0x1800: + case 0x1900: + case 0x1a00: + case 0x1b00: /* Non-conforming */ + if (DPL2 < CPL) { + if (!(segdat2[2] & 0x8000)) { + x86np("Int gate CS not present", segdat[1] & 0xfffc); + return; + } + if ((cpu_state.eflags & VM_FLAG) && DPL2) { + x86gpf("pmodeint(): Interrupt or trap gate non-zero DPL in V86 mode", segdat[1] & 0xfffc); + return; + } + /* Load new stack */ + oldss = SS; + oldsp = ESP; + cpl_override = 1; + if (tr.access & 8) { + addr = 4 + tr.base + (DPL2 << 3); + newss = readmemw(0, addr + 4); + newsp = readmeml(0, addr); + } else { + addr = 2 + tr.base + (DPL2 << 2); + newss = readmemw(0, addr + 2); + newsp = readmemw(0, addr); + } + cpl_override = 0; + if (!(newss & 0xfffc)) { + x86ss("pmodeint(): Interrupt or trap gate stack segment is NULL", newss & 0xfffc); + return; + } + addr = newss & 0xfff8; + dt = (newss & 0x0004) ? &ldt : &gdt; + if ((addr + 7) > dt->limit) { + x86ss("pmodeint(): Interrupt or trap gate stack segment > DT", newss & 0xfffc); + return; + } + addr += dt->base; + read_descriptor(addr, segdat3, segdat332, 1); + if (cpu_state.abrt) + return; + if ((newss & 3) != DPL2) { + x86ss("pmodeint(): Interrupt or trap gate tack segment RPL > DPL", newss & 0xfffc); + return; + } + if (DPL3 != DPL2) { + x86ss("pmodeint(): Interrupt or trap gate tack segment DPL > DPL", newss & 0xfffc); + return; + } + if ((segdat3[2] & 0x1a00) != 0x1200) { + x86ss("pmodeint(): Interrupt or trap gate stack segment bad type", newss & 0xfffc); + return; + } + if (!(segdat3[2] & 0x8000)) { + x86np("Int gate loading SS not present", newss & 0xfffc); + return; + } + SS = newss; + set_stack32((segdat3[3] & 0x0040) ? 1 : 0); + if (stack32) + ESP = newsp; + else + SP = newsp; + do_seg_load(&cpu_state.seg_ss, segdat3); - x86seg_log("New stack %04X:%08X\n", SS, ESP); - cpl_override = 1; - if (type >= 0x0800) { - if (cpu_state.eflags & VM_FLAG) { - PUSHL(GS); - PUSHL(FS); - PUSHL(DS); - PUSHL(ES); - if (cpu_state.abrt) - return; - loadseg(0, &cpu_state.seg_ds); - loadseg(0, &cpu_state.seg_es); - loadseg(0, &cpu_state.seg_fs); - loadseg(0, &cpu_state.seg_gs); - } - PUSHL(oldss); - PUSHL(oldsp); - PUSHL(cpu_state.flags | (cpu_state.eflags << 16)); - PUSHL(CS); - PUSHL(cpu_state.pc); - if (cpu_state.abrt) - return; - } else { - PUSHW(oldss); - PUSHW(oldsp); - PUSHW(cpu_state.flags); - PUSHW(CS); - PUSHW(cpu_state.pc); - if (cpu_state.abrt) - return; - } - cpl_override = 0; - cpu_state.seg_cs.access = 0x80; - cycles -= timing_int_pm_outer - timing_int_pm; - break; - } else if (DPL2 != CPL) { - x86gpf("pmodeint(): DPL != CPL", seg & 0xfffc); - return; - } - /*FALLTHROUGH*/ - case 0x1c00: case 0x1d00: case 0x1e00: case 0x1f00: /* Conforming */ - if (!(segdat2[2] & 0x8000)) { - x86np("Int gate CS not present", segdat[1] & 0xfffc); - return; - } - if ((cpu_state.eflags & VM_FLAG) && (DPL2 < CPL)) { - x86gpf("pmodeint(): DPL < CPL in V86 mode", seg &~ 0xfffc); - return; - } - if (type > 0x0800) { - PUSHL(cpu_state.flags | (cpu_state.eflags << 16)); - PUSHL(CS); - PUSHL(cpu_state.pc); - if (cpu_state.abrt) - return; - } else { - PUSHW(cpu_state.flags); - PUSHW(CS); - PUSHW(cpu_state.pc); - if (cpu_state.abrt) - return; - } - new_cpl = CS & 3; - break; - default: - x86gpf("pmodeint(): Unknown type", seg & 0xfffc); - return; - } - do_seg_load(&cpu_state.seg_cs, segdat2); - CS = (seg & 0xfffc) | new_cpl; - cpu_state.seg_cs.access = (cpu_state.seg_cs.access & ~0x60) | (new_cpl << 5); - if ((CPL == 3) && (oldcpl != 3)) - flushmmucache_cr3(); + cpl_override = 1; + writememw(0, addr + 4, segdat3[2] | 0x100); /* Set accessed bit */ + cpl_override = 0; + + x86seg_log("New stack %04X:%08X\n", SS, ESP); + cpl_override = 1; + if (type >= 0x0800) { + if (cpu_state.eflags & VM_FLAG) { + PUSHL(GS); + PUSHL(FS); + PUSHL(DS); + PUSHL(ES); + if (cpu_state.abrt) + return; + op_loadseg(0, &cpu_state.seg_ds); + op_loadseg(0, &cpu_state.seg_es); + op_loadseg(0, &cpu_state.seg_fs); + op_loadseg(0, &cpu_state.seg_gs); + } + PUSHL(oldss); + PUSHL(oldsp); + PUSHL(cpu_state.flags | (cpu_state.eflags << 16)); + PUSHL(CS); + PUSHL(cpu_state.pc); + if (cpu_state.abrt) + return; + } else { + PUSHW(oldss); + PUSHW(oldsp); + PUSHW(cpu_state.flags); + PUSHW(CS); + PUSHW(cpu_state.pc); + if (cpu_state.abrt) + return; + } + cpl_override = 0; + cpu_state.seg_cs.access = 0x80; + cycles -= timing_int_pm_outer - timing_int_pm; + break; + } else if (DPL2 != CPL) { + x86gpf("pmodeint(): DPL != CPL", seg & 0xfffc); + return; + } + fallthrough; + case 0x1c00: + case 0x1d00: + case 0x1e00: + case 0x1f00: /* Conforming */ + if (!(segdat2[2] & 0x8000)) { + x86np("Int gate CS not present", segdat[1] & 0xfffc); + return; + } + if ((cpu_state.eflags & VM_FLAG) && (DPL2 < CPL)) { + x86gpf("pmodeint(): DPL < CPL in V86 mode", seg & ~0xfffc); + return; + } + if (type > 0x0800) { + PUSHL(cpu_state.flags | (cpu_state.eflags << 16)); + PUSHL(CS); + PUSHL(cpu_state.pc); + if (cpu_state.abrt) + return; + } else { + PUSHW(cpu_state.flags); + PUSHW(CS); + PUSHW(cpu_state.pc); + if (cpu_state.abrt) + return; + } + new_cpl = CS & 3; + break; + default: + x86gpf("pmodeint(): Unknown type", seg & 0xfffc); + return; + } + do_seg_load(&cpu_state.seg_cs, segdat2); + CS = (seg & 0xfffc) | new_cpl; + cpu_state.seg_cs.access = (cpu_state.seg_cs.access & ~0x60) | (new_cpl << 5); + if ((CPL == 3) && (oldcpl != 3)) + flushmmucache_nopc(); #ifdef USE_NEW_DYNAREC - oldcpl = CPL; + oldcpl = CPL; #endif - if (type > 0x0800) - cpu_state.pc = segdat[0] | (segdat[3] << 16); - else - cpu_state.pc = segdat[0]; - set_use32(segdat2[3] & 0x40); + if (type > 0x0800) + cpu_state.pc = segdat[0] | (segdat[3] << 16); + else + cpu_state.pc = segdat[0]; + set_use32(segdat2[3] & 0x40); - cpl_override = 1; - writememw(0, oaddr + 4, segdat2[2] | 0x100); /* Set accessed bit */ - cpl_override = 0; + cpl_override = 1; + writememw(0, oaddr + 4, segdat2[2] | 0x100); /* Set accessed bit */ + cpl_override = 0; - cpu_state.eflags &= ~VM_FLAG; - cpu_cur_status &= ~CPU_STATUS_V86; - if (!(type & 0x100)) - cpu_state.flags &= ~I_FLAG; - cpu_state.flags &= ~(T_FLAG | NT_FLAG); - cycles -= timing_int_pm; - break; + cpu_state.eflags &= ~VM_FLAG; + cpu_cur_status &= ~CPU_STATUS_V86; + if (!(type & 0x100)) + cpu_state.flags &= ~I_FLAG; + cpu_state.flags &= ~(T_FLAG | NT_FLAG); + cycles -= timing_int_pm; + break; - case 0x500: /* Task gate */ - seg = segdat[1]; - addr = seg & 0xfff8; - dt = (seg & 0x0004) ? &ldt : &gdt; - if ((addr + 7) > dt->limit) { - x86gpf("pmodeint(): Task gate selector > DT limit", seg & 0xfffc); - return; - } - addr += dt->base; - read_descriptor(addr, segdat2, segdat232, 1); - if (cpu_state.abrt) - return; - if (!(segdat2[2] & 0x8000)) { - x86np("Int task gate not present", segdat[1] & 0xfffc); - return; - } - optype = OPTYPE_INT; - cpl_override = 1; - taskswitch286(seg, segdat2, segdat2[2] & 0x0800); - cpl_override = 0; - break; + case 0x500: /* Task gate */ + seg = segdat[1]; + addr = seg & 0xfff8; + dt = (seg & 0x0004) ? &ldt : &gdt; + if ((addr + 7) > dt->limit) { + x86gpf("pmodeint(): Task gate selector > DT limit", seg & 0xfffc); + return; + } + addr += dt->base; + read_descriptor(addr, segdat2, segdat232, 1); + if (cpu_state.abrt) + return; + if (!(segdat2[2] & 0x8000)) { + x86np("Int task gate not present", segdat[1] & 0xfffc); + return; + } + optype = OPTYPE_INT; + cpl_override = 1; + op_taskswitch286(seg, segdat2, segdat2[2] & 0x0800); + cpl_override = 0; + break; - default: - x86gpf("Protected mode interrupt unknown type", seg & 0xfffc); - return; + default: + x86gpf("Protected mode interrupt unknown type", seg & 0xfffc); + return; } } - void +#ifdef OPS_286_386 +pmodeiret_2386(int is32) +#else pmodeiret(int is32) +#endif { - uint16_t newss, seg = 0; - uint16_t segdat[4],segdat2[4]; - uint16_t segs[4]; - uint32_t tempflags, flagmask; - uint32_t newpc, newsp; - uint32_t addr, oaddr; - uint32_t oldsp = ESP; - uint32_t *segdat32 = (uint32_t *) segdat; - uint32_t *segdat232 = (uint32_t *) segdat2; - x86seg *dt; + uint16_t newss; + uint16_t seg = 0; + uint16_t segdat[4]; + uint16_t segdat2[4]; + uint16_t segs[4]; + uint32_t tempflags; + uint32_t flagmask; + uint32_t newpc; + uint32_t newsp; + uint32_t addr; + uint32_t oaddr; + uint32_t oldsp = ESP; + uint32_t *segdat32 = (uint32_t *) segdat; + uint32_t *segdat232 = (uint32_t *) segdat2; + const x86seg *dt; if (is386 && (cpu_state.eflags & VM_FLAG)) { - if (IOPL != 3) { - x86gpf("Protected mode IRET: IOPL != 3", 0); - return; - } + if (IOPL != 3) { + x86gpf("Protected mode IRET: IOPL != 3", 0); + return; + } #ifndef USE_NEW_DYNAREC - oxpc = cpu_state.pc; + oxpc = cpu_state.pc; #endif - if (is32) { - newpc = POPL(); - seg = POPL(); - tempflags = POPL(); - } else { - newpc = POPW(); - seg = POPW(); - tempflags = POPW(); - } - if (cpu_state.abrt) - return; + if (is32) { + newpc = POPL(); + seg = POPL(); + tempflags = POPL(); + } else { + newpc = POPW(); + seg = POPW(); + tempflags = POPW(); + } + if (cpu_state.abrt) + return; - cpu_state.pc = newpc; - cpu_state.seg_cs.base= seg << 4; - cpu_state.seg_cs.limit = 0xffff; - cpu_state.seg_cs.limit_low = 0; - cpu_state.seg_cs.limit_high = 0xffff; - cpu_state.seg_cs.access |= 0x80; - cpu_state.seg_cs.ar_high = 0x10; - CS = seg; - cpu_state.flags = (cpu_state.flags & 0x3000) | (tempflags & 0xcfd5) | 2; - cycles -= timing_iret_rm; - return; + cpu_state.pc = newpc; + cpu_state.seg_cs.base = seg << 4; + cpu_state.seg_cs.limit = 0xffff; + cpu_state.seg_cs.limit_low = 0; + cpu_state.seg_cs.limit_high = 0xffff; + cpu_state.seg_cs.access |= 0x80; + cpu_state.seg_cs.ar_high = 0x10; + CS = seg; + cpu_state.flags = (cpu_state.flags & 0x3000) | (tempflags & 0xcfd5) | 2; + cycles -= timing_iret_rm; + return; } if (cpu_state.flags & NT_FLAG) { - seg = readmemw(tr.base, 0); - addr = seg & 0xfff8; - if (seg & 0x0004) { - x86seg_log("TS LDT %04X %04X IRET\n", seg, gdt.limit); - x86ts("pmodeiret(): Selector points to LDT", seg & 0xfffc); - return; - } else { - if ((addr + 7) > gdt.limit) { - x86ts(NULL,seg & 0xfffc); - return; - } - addr += gdt.base; - } - cpl_override = 1; - read_descriptor(addr, segdat, segdat32, 1); - taskswitch286(seg, segdat,segdat[2] & 0x0800); - cpl_override = 0; - return; + cpl_override = 1; + seg = readmemw(tr.base, 0); + cpl_override = 0; + addr = seg & 0xfff8; + if (seg & 0x0004) { + x86seg_log("TS LDT %04X %04X IRET\n", seg, gdt.limit); + x86ts("pmodeiret(): Selector points to LDT", seg & 0xfffc); + return; + } else { + if ((addr + 7) > gdt.limit) { + x86ts(NULL, seg & 0xfffc); + return; + } + addr += gdt.base; + } + read_descriptor(addr, segdat, segdat32, 1); + cpl_override = 1; + op_taskswitch286(seg, segdat, segdat[2] & 0x0800); + cpl_override = 0; + return; } #ifndef USE_NEW_DYNAREC - oxpc=cpu_state.pc; + oxpc = cpu_state.pc; #endif flagmask = 0xffff; if (CPL != 0) - flagmask &= ~0x3000; + flagmask &= ~0x3000; if (IOPL < CPL) - flagmask &= ~0x200; + flagmask &= ~0x200; if (is32) { - newpc = POPL(); - seg = POPL(); - tempflags = POPL(); - if (cpu_state.abrt) { - ESP = oldsp; - return; - } - if (is386 && ((tempflags >> 16) & VM_FLAG)) { - newsp = POPL(); - newss = POPL(); - segs[0] = POPL(); - segs[1] = POPL(); - segs[2] = POPL(); - segs[3] = POPL(); - if (cpu_state.abrt) { - ESP = oldsp; - return; - } - cpu_state.eflags = tempflags >> 16; - cpu_cur_status |= CPU_STATUS_V86; - loadseg(segs[0], &cpu_state.seg_es); - do_seg_v86_init(&cpu_state.seg_es); - loadseg(segs[1], &cpu_state.seg_ds); - do_seg_v86_init(&cpu_state.seg_ds); - cpu_cur_status |= CPU_STATUS_NOTFLATDS; - loadseg(segs[2], &cpu_state.seg_fs); - do_seg_v86_init(&cpu_state.seg_fs); - loadseg(segs[3], &cpu_state.seg_gs); - do_seg_v86_init(&cpu_state.seg_gs); + newpc = POPL(); + seg = POPL(); + tempflags = POPL(); + if (cpu_state.abrt) { + ESP = oldsp; + return; + } + if (is386 && ((tempflags >> 16) & VM_FLAG)) { + newsp = POPL(); + newss = POPL(); + segs[0] = POPL(); + segs[1] = POPL(); + segs[2] = POPL(); + segs[3] = POPL(); + if (cpu_state.abrt) { + ESP = oldsp; + return; + } + cpu_state.eflags = tempflags >> 16; + cpu_cur_status |= CPU_STATUS_V86; + op_loadseg(segs[0], &cpu_state.seg_es); + do_seg_v86_init(&cpu_state.seg_es); + op_loadseg(segs[1], &cpu_state.seg_ds); + do_seg_v86_init(&cpu_state.seg_ds); + cpu_cur_status |= CPU_STATUS_NOTFLATDS; + op_loadseg(segs[2], &cpu_state.seg_fs); + do_seg_v86_init(&cpu_state.seg_fs); + op_loadseg(segs[3], &cpu_state.seg_gs); + do_seg_v86_init(&cpu_state.seg_gs); - cpu_state.pc = newpc & 0xffff; - cpu_state.seg_cs.base = seg << 4; - cpu_state.seg_cs.limit = 0xffff; - cpu_state.seg_cs.limit_low = 0; - cpu_state.seg_cs.limit_high = 0xffff; - CS = seg; - cpu_state.seg_cs.access = 0xe2; - cpu_state.seg_cs.ar_high = 0x10; - if ((CPL == 3) && (oldcpl != 3)) - flushmmucache_cr3(); + cpu_state.pc = newpc & 0xffff; + cpu_state.seg_cs.base = seg << 4; + cpu_state.seg_cs.limit = 0xffff; + cpu_state.seg_cs.limit_low = 0; + cpu_state.seg_cs.limit_high = 0xffff; + CS = seg; + cpu_state.seg_cs.access = 0xe2; + cpu_state.seg_cs.ar_high = 0x10; + if ((CPL == 3) && (oldcpl != 3)) + flushmmucache_nopc(); #ifdef USE_NEW_DYNAREC - oldcpl = CPL; + oldcpl = CPL; #endif - ESP = newsp; - loadseg(newss, &cpu_state.seg_ss); - do_seg_v86_init(&cpu_state.seg_ss); - cpu_cur_status |= CPU_STATUS_NOTFLATSS; - use32 = 0; - cpu_cur_status &= ~CPU_STATUS_USE32; - cpu_state.flags = (tempflags & 0xffd5) | 2; - cycles -= timing_iret_v86; - return; - } + ESP = newsp; + op_loadseg(newss, &cpu_state.seg_ss); + do_seg_v86_init(&cpu_state.seg_ss); + cpu_cur_status |= CPU_STATUS_NOTFLATSS; + use32 = 0; + cpu_cur_status &= ~CPU_STATUS_USE32; + cpu_state.flags = (tempflags & 0xffd5) | 2; + cycles -= timing_iret_v86; + return; + } } else { - newpc = POPW(); - seg = POPW(); - tempflags = POPW(); - if (cpu_state.abrt) { - ESP = oldsp; - return; - } + newpc = POPW(); + seg = POPW(); + tempflags = POPW(); + if (cpu_state.abrt) { + ESP = oldsp; + return; + } } if (!(seg & 0xfffc)) { - ESP = oldsp; - x86gpf("pmodeiret(): Selector is NULL", 0); - return; + ESP = oldsp; + x86gpf("pmodeiret(): Selector is NULL", 0); + return; } addr = seg & 0xfff8; - dt = (seg & 0x0004) ? & ldt : &gdt; + dt = (seg & 0x0004) ? &ldt : &gdt; if ((addr + 7) > dt->limit) { - ESP = oldsp; - x86gpf("pmodeiret(): Selector > DT limit", seg & 0xfffc); - return; + ESP = oldsp; + x86gpf("pmodeiret(): Selector > DT limit", seg & 0xfffc); + return; } addr += dt->base; if ((seg & 0x0003) < CPL) { - ESP = oldsp; - x86gpf("pmodeiret(): RPL < CPL", seg & 0xfffc); - return; + ESP = oldsp; + x86gpf("pmodeiret(): RPL < CPL", seg & 0xfffc); + return; } read_descriptor(addr, segdat, segdat32, 1); if (cpu_state.abrt) { - ESP = oldsp; - return; + ESP = oldsp; + return; } switch (segdat[2] & 0x1f00) { - case 0x1800: case 0x1900: case 0x1a00: case 0x1b00: /* Non-conforming code */ - if ((seg & 0x0003) != DPL) { - ESP = oldsp; - x86gpf("pmodeiret(): Non-conforming RPL != DPL", seg & 0xfffc); - return; - } - break; - case 0x1C00: case 0x1D00: case 0x1E00: case 0x1F00: /* Conforming code */ - if ((seg & 0x0003) < DPL) { - ESP = oldsp; - x86gpf("pmodeiret(): Conforming RPL < DPL",seg&~3); - return; - } - break; - default: - ESP = oldsp; - x86gpf("pmodeiret(): Unknown type", seg & 0xfffc); - return; + case 0x1800: + case 0x1900: + case 0x1a00: + case 0x1b00: /* Non-conforming code */ + if ((seg & 0x0003) != DPL) { + ESP = oldsp; + x86gpf("pmodeiret(): Non-conforming RPL != DPL", seg & 0xfffc); + return; + } + break; + case 0x1C00: + case 0x1D00: + case 0x1E00: + case 0x1F00: /* Conforming code */ + if ((seg & 0x0003) < DPL) { + ESP = oldsp; + x86gpf("pmodeiret(): Conforming RPL < DPL", seg & ~3); + return; + } + break; + default: + ESP = oldsp; + x86gpf("pmodeiret(): Unknown type", seg & 0xfffc); + return; } if (!(segdat[2] & 0x8000)) { - ESP = oldsp; - x86np("IRET CS not present", seg & 0xfffc); - return; + ESP = oldsp; + x86np("IRET CS not present", seg & 0xfffc); + return; } if ((seg & 0x0003) == CPL) { - CS = seg; - do_seg_load(&cpu_state.seg_cs, segdat); - cpu_state.seg_cs.access = (cpu_state.seg_cs.access & ~0x60) | ((CS & 0x0003) << 5); - if ((CPL == 3) && (oldcpl != 3)) - flushmmucache_cr3(); + CS = seg; + do_seg_load(&cpu_state.seg_cs, segdat); + cpu_state.seg_cs.access = (cpu_state.seg_cs.access & ~0x60) | ((CS & 0x0003) << 5); + if ((CPL == 3) && (oldcpl != 3)) + flushmmucache_nopc(); #ifdef USE_NEW_DYNAREC - oldcpl = CPL; + oldcpl = CPL; #endif - set_use32(segdat[3] & 0x0040); + set_use32(segdat[3] & 0x0040); - cpl_override = 1; - writememw(0, addr + 4, segdat[2] | 0x100); /* Set accessed bit */ - cpl_override = 0; - cycles -= timing_iret_pm; - } else { /* Return to outer level */ - oaddr = addr; - x86seg_log("Outer level\n"); - if (is32) { - newsp = POPL(); - newss = POPL(); - if (cpu_state.abrt) { - ESP = oldsp; - return; - } - } else { - newsp = POPW(); - newss = POPW(); - if (cpu_state.abrt) { - ESP = oldsp; - return; - } - } + cpl_override = 1; + writememw(0, addr + 4, segdat[2] | 0x100); /* Set accessed bit */ + cpl_override = 0; + cycles -= timing_iret_pm; + } else { /* Return to outer level */ + oaddr = addr; + x86seg_log("Outer level\n"); + if (is32) { + newsp = POPL(); + newss = POPL(); + if (cpu_state.abrt) { + ESP = oldsp; + return; + } + } else { + newsp = POPW(); + newss = POPW(); + if (cpu_state.abrt) { + ESP = oldsp; + return; + } + } - x86seg_log("IRET load stack %04X:%04X\n", newss, newsp); + x86seg_log("IRET load stack %04X:%04X\n", newss, newsp); - if (!(newss & 0xfffc)) { - ESP = oldsp; - x86gpf("pmodeiret(): New SS selector is zero", newss & 0xfffc); - return; - } - addr = newss & 0xfff8; - dt = (newss & 0x0004) ? &ldt : &gdt; - if ((addr + 7) > dt->limit) { - ESP = oldsp; - x86gpf("pmodeiret(): New SS selector > DT limit", newss & 0xfffc); - return; - } - addr += dt->base; - read_descriptor(addr, segdat2, segdat232, 1); - if (cpu_state.abrt) { - ESP = oldsp; - return; - } - if ((newss & 3) != (seg & 3)) { - SP = oldsp; - x86gpf("pmodeiret(): New SS RPL > CS RPL",newss & 0xfffc); - return; - } - if ((segdat2[2] & 0x1a00) != 0x1200) { - ESP = oldsp; - x86gpf("pmodeiret(): New SS bad type", newss & 0xfffc); - return; - } - if (DPL2 != (seg & 0x0003)) { - ESP = oldsp; - x86gpf("pmodeiret(): New SS DPL != CS RPL",newss & 0xfffc); - return; - } - if (!(segdat2[2] & 0x8000)) { - ESP = oldsp; - x86np("IRET loading SS not present", newss & 0xfffc); - return; - } - SS = newss; - set_stack32((segdat2[3] & 0x40) ? 1 : 0); - if (stack32) - ESP = newsp; - else - SP = newsp; - do_seg_load(&cpu_state.seg_ss, segdat2); + if (!(newss & 0xfffc)) { + ESP = oldsp; + x86gpf("pmodeiret(): New SS selector is zero", newss & 0xfffc); + return; + } + addr = newss & 0xfff8; + dt = (newss & 0x0004) ? &ldt : &gdt; + if ((addr + 7) > dt->limit) { + ESP = oldsp; + x86gpf("pmodeiret(): New SS selector > DT limit", newss & 0xfffc); + return; + } + addr += dt->base; + read_descriptor(addr, segdat2, segdat232, 1); + if (cpu_state.abrt) { + ESP = oldsp; + return; + } + if ((newss & 3) != (seg & 3)) { + SP = oldsp; + x86gpf("pmodeiret(): New SS RPL > CS RPL", newss & 0xfffc); + return; + } + if ((segdat2[2] & 0x1a00) != 0x1200) { + ESP = oldsp; + x86gpf("pmodeiret(): New SS bad type", newss & 0xfffc); + return; + } + if (DPL2 != (seg & 0x0003)) { + ESP = oldsp; + x86gpf("pmodeiret(): New SS DPL != CS RPL", newss & 0xfffc); + return; + } + if (!(segdat2[2] & 0x8000)) { + ESP = oldsp; + x86np("IRET loading SS not present", newss & 0xfffc); + return; + } + SS = newss; + set_stack32((segdat2[3] & 0x40) ? 1 : 0); + if (stack32) + ESP = newsp; + else + SP = newsp; + do_seg_load(&cpu_state.seg_ss, segdat2); - cpl_override = 1; - writememw(0, addr + 4, segdat2[2] | 0x100); /* Set accessed bit */ - writememw(0, oaddr + 4, segdat[2] | 0x100); /* Set accessed bit */ - cpl_override = 0; - /* Conforming segments don't change CPL, so CPL = RPL */ - if (segdat[2] & 0x0400) - segdat[2] = (segdat[2] & ~(3 << 13)) | ((seg & 3) << 13); + cpl_override = 1; + writememw(0, addr + 4, segdat2[2] | 0x100); /* Set accessed bit */ + writememw(0, oaddr + 4, segdat[2] | 0x100); /* Set accessed bit */ + cpl_override = 0; + /* Conforming segments don't change CPL, so CPL = RPL */ + if (segdat[2] & 0x0400) + segdat[2] = (segdat[2] & ~(3 << 13)) | ((seg & 3) << 13); - CS = seg; - do_seg_load(&cpu_state.seg_cs, segdat); - cpu_state.seg_cs.access = (cpu_state.seg_cs.access & ~0x60) | ((CS & 3) << 5); - if ((CPL == 3) && (oldcpl != 3)) - flushmmucache_cr3(); + CS = seg; + do_seg_load(&cpu_state.seg_cs, segdat); + cpu_state.seg_cs.access = (cpu_state.seg_cs.access & ~0x60) | ((CS & 3) << 5); + if ((CPL == 3) && (oldcpl != 3)) + flushmmucache_nopc(); #ifdef USE_NEW_DYNAREC - oldcpl = CPL; + oldcpl = CPL; #endif - set_use32(segdat[3] & 0x40); + set_use32(segdat[3] & 0x40); - check_seg_valid(&cpu_state.seg_ds); - check_seg_valid(&cpu_state.seg_es); - check_seg_valid(&cpu_state.seg_fs); - check_seg_valid(&cpu_state.seg_gs); - cycles -= timing_iret_pm_outer; + check_seg_valid(&cpu_state.seg_ds); + check_seg_valid(&cpu_state.seg_es); + check_seg_valid(&cpu_state.seg_fs); + check_seg_valid(&cpu_state.seg_gs); + cycles -= timing_iret_pm_outer; } - cpu_state.pc = newpc; - cpu_state.flags = (cpu_state.flags &~ flagmask) | (tempflags & flagmask & 0xffd5) | 2; + cpu_state.pc = newpc; + cpu_state.flags = (cpu_state.flags & ~flagmask) | (tempflags & flagmask & 0xffd5) | 2; if (is32) - cpu_state.eflags = tempflags >> 16; + cpu_state.eflags = tempflags >> 16; } - void +#ifdef OPS_286_386 +taskswitch286_2386(uint16_t seg, uint16_t *segdat, int is32) +#else taskswitch286(uint16_t seg, uint16_t *segdat, int is32) +#endif { - uint16_t tempw, new_ldt; - uint16_t new_es, new_cs, new_ss, new_ds, new_fs, new_gs; - uint16_t segdat2[4]; - uint32_t base, limit; - uint32_t templ, new_cr3 = 0; - uint32_t new_eax, new_ebx, new_ecx, new_edx, new_esp, new_ebp; - uint32_t new_esi, new_edi, new_pc, new_flags, addr; - uint32_t *segdat232 = (uint32_t *) segdat2; - x86seg *dt; + uint16_t tempw; + uint16_t new_ldt; + uint16_t new_es; + uint16_t new_cs; + uint16_t new_ss; + uint16_t new_ds; + uint16_t new_fs; + uint16_t new_gs; + uint16_t segdat2[4]; + uint32_t base; + uint32_t limit; + uint32_t templ; + uint32_t new_cr3 = 0; + uint32_t new_eax; + uint32_t new_ebx; + uint32_t new_ecx; + uint32_t new_edx; + uint32_t new_esp; + uint32_t new_ebp; + uint32_t new_esi; + uint32_t new_edi; + uint32_t new_pc; + uint32_t new_flags; + uint32_t addr; + uint32_t *segdat232 = (uint32_t *) segdat2; + const x86seg *dt; - base = segdat[1] | ((segdat[2] & 0x00ff) << 16); + base = segdat[1] | ((segdat[2] & 0x00ff) << 16); limit = segdat[0]; if (is386) { - base |= (segdat[3] >> 8) << 24; - limit |= (segdat[3] & 0x000f) << 16; + base |= (segdat[3] >> 8) << 24; + limit |= (segdat[3] & 0x000f) << 16; } if (is32) { - if (limit < 103) { - x86ts("taskswitch286(): limit < 103", seg); - return; - } + if (limit < 103) { + x86ts("taskswitch286(): limit < 103", seg); + return; + } - if ((optype == JMP) || (optype == CALL) || (optype == OPTYPE_INT)) { - if (tr.seg & 0x0004) - tempw = readmemw(ldt.base, (seg & 0xfff8) + 4); - else - tempw = readmemw(gdt.base, (seg & 0xfff8) + 4); - if (cpu_state.abrt) - return; - tempw |= 0x0200; - if (tr.seg & 0x0004) - writememw(ldt.base, (seg & 0xfff8) + 4, tempw); - else - writememw(gdt.base, (seg & 0xfff8) + 4, tempw); - } - if (cpu_state.abrt) - return; + if ((optype == JMP) || (optype == CALL) || (optype == OPTYPE_INT)) { + if (tr.seg & 0x0004) + tempw = readmemw(ldt.base, (seg & 0xfff8) + 4); + else + tempw = readmemw(gdt.base, (seg & 0xfff8) + 4); + if (cpu_state.abrt) + return; + tempw |= 0x0200; + if (tr.seg & 0x0004) + writememw(ldt.base, (seg & 0xfff8) + 4, tempw); + else + writememw(gdt.base, (seg & 0xfff8) + 4, tempw); + } + if (cpu_state.abrt) + return; - if (optype == IRET) - cpu_state.flags &= ~NT_FLAG; + if (optype == IRET) + cpu_state.flags &= ~NT_FLAG; - cpu_386_flags_rebuild(); - writememl(tr.base, 0x1C, cr3); - writememl(tr.base, 0x20, cpu_state.pc); - writememl(tr.base, 0x24, cpu_state.flags | (cpu_state.eflags << 16)); + cpu_386_flags_rebuild(); + writememl(tr.base, 0x1C, cr3); + writememl(tr.base, 0x20, cpu_state.pc); + writememl(tr.base, 0x24, cpu_state.flags | (cpu_state.eflags << 16)); - writememl(tr.base, 0x28, EAX); - writememl(tr.base, 0x2C, ECX); - writememl(tr.base, 0x30, EDX); - writememl(tr.base, 0x34, EBX); - writememl(tr.base, 0x38, ESP); - writememl(tr.base, 0x3C, EBP); - writememl(tr.base, 0x40, ESI); - writememl(tr.base, 0x44, EDI); + writememl(tr.base, 0x28, EAX); + writememl(tr.base, 0x2C, ECX); + writememl(tr.base, 0x30, EDX); + writememl(tr.base, 0x34, EBX); + writememl(tr.base, 0x38, ESP); + writememl(tr.base, 0x3C, EBP); + writememl(tr.base, 0x40, ESI); + writememl(tr.base, 0x44, EDI); - writememl(tr.base, 0x48, ES); - writememl(tr.base, 0x4C, CS); - writememl(tr.base, 0x50, SS); - writememl(tr.base, 0x54, DS); - writememl(tr.base, 0x58, FS); - writememl(tr.base, 0x5C, GS); + writememl(tr.base, 0x48, ES); + writememl(tr.base, 0x4C, CS); + writememl(tr.base, 0x50, SS); + writememl(tr.base, 0x54, DS); + writememl(tr.base, 0x58, FS); + writememl(tr.base, 0x5C, GS); - if ((optype == JMP) || (optype == IRET)) { - if (tr.seg & 0x0004) - tempw = readmemw(ldt.base, (tr.seg & 0xfff8) + 4); - else - tempw = readmemw(gdt.base, (tr.seg & 0xfff8) + 4); - if (cpu_state.abrt) - return; - tempw &= ~0x0200; - if (tr.seg & 0x0004) - writememw(ldt.base, (tr.seg & 0xfff8) + 4, tempw); - else - writememw(gdt.base, (tr.seg & 0xfff8) + 4, tempw); - } - if (cpu_state.abrt) - return; + if ((optype == JMP) || (optype == IRET)) { + if (tr.seg & 0x0004) + tempw = readmemw(ldt.base, (tr.seg & 0xfff8) + 4); + else + tempw = readmemw(gdt.base, (tr.seg & 0xfff8) + 4); + if (cpu_state.abrt) + return; + tempw &= ~0x0200; + if (tr.seg & 0x0004) + writememw(ldt.base, (tr.seg & 0xfff8) + 4, tempw); + else + writememw(gdt.base, (tr.seg & 0xfff8) + 4, tempw); + } + if (cpu_state.abrt) + return; - if ((optype == OPTYPE_INT) || (optype == CALL)) { - writememl(base, 0, tr.seg); - if (cpu_state.abrt) - return; - } + if ((optype == OPTYPE_INT) || (optype == CALL)) { + writememl(base, 0, tr.seg); + if (cpu_state.abrt) + return; + } - new_cr3 = readmeml(base, 0x1C); - new_pc = readmeml(base, 0x20); - new_flags = readmeml(base, 0x24); - if ((optype == OPTYPE_INT) || (optype == CALL)) - new_flags |= NT_FLAG; + new_cr3 = readmeml(base, 0x1C); + new_pc = readmeml(base, 0x20); + new_flags = readmeml(base, 0x24); + if ((optype == OPTYPE_INT) || (optype == CALL)) + new_flags |= NT_FLAG; - new_eax = readmeml(base, 0x28); - new_ecx = readmeml(base, 0x2C); - new_edx = readmeml(base, 0x30); - new_ebx = readmeml(base, 0x34); - new_esp = readmeml(base, 0x38); - new_ebp = readmeml(base, 0x3C); - new_esi = readmeml(base, 0x40); - new_edi = readmeml(base, 0x44); + new_eax = readmeml(base, 0x28); + new_ecx = readmeml(base, 0x2C); + new_edx = readmeml(base, 0x30); + new_ebx = readmeml(base, 0x34); + new_esp = readmeml(base, 0x38); + new_ebp = readmeml(base, 0x3C); + new_esi = readmeml(base, 0x40); + new_edi = readmeml(base, 0x44); - new_es = readmemw(base, 0x48); - new_cs = readmemw(base, 0x4C); - new_ss = readmemw(base, 0x50); - new_ds = readmemw(base, 0x54); - new_fs = readmemw(base, 0x58); - new_gs = readmemw(base, 0x5C); - new_ldt = readmemw(base, 0x60); + new_es = readmemw(base, 0x48); + new_cs = readmemw(base, 0x4C); + new_ss = readmemw(base, 0x50); + new_ds = readmemw(base, 0x54); + new_fs = readmemw(base, 0x58); + new_gs = readmemw(base, 0x5C); + new_ldt = readmemw(base, 0x60); - cr0 |= 8; + cr0 |= 8; - cr3 = new_cr3; - flushmmucache(); + cr3 = new_cr3; + flushmmucache(); - cpu_state.pc = new_pc; - cpu_state.flags = new_flags; - cpu_state.eflags = new_flags >> 16; - cpu_386_flags_extract(); + cpu_state.pc = new_pc; + cpu_state.flags = new_flags; + cpu_state.eflags = new_flags >> 16; + cpu_386_flags_extract(); - ldt.seg = new_ldt; - templ = (ldt.seg & ~7) + gdt.base; - ldt.limit = readmemw(0, templ); - if (readmemb(0, templ + 6) & 0x80) { - ldt.limit <<= 12; - ldt.limit |= 0xfff; - } - ldt.base = (readmemw(0, templ + 2)) | (readmemb(0, templ + 4) << 16) | (readmemb(0, templ + 7) << 24); + ldt.seg = new_ldt; + templ = (ldt.seg & ~7) + gdt.base; + ldt.limit = readmemw(0, templ); + if (readmemb(0, templ + 6) & 0x80) { + ldt.limit <<= 12; + ldt.limit |= 0xfff; + } + ldt.base = (readmemw(0, templ + 2)) | (readmemb(0, templ + 4) << 16) | (readmemb(0, templ + 7) << 24); - if (cpu_state.eflags & VM_FLAG) { - loadcs(new_cs); - set_use32(0); - cpu_cur_status |= CPU_STATUS_V86; - } else { - if (!(new_cs & 0xfffc)) { - x86ts("taskswitch286(): New CS selector is null", 0); - return; - } - addr = new_cs & 0xfff8; - dt = (new_cs & 0x0004) ? &ldt : &gdt; - if ((addr + 7) > dt->limit) { - x86ts("taskswitch286(): New CS selector > DT limit", new_cs & 0xfffc); - return; - } - addr += dt->base; - read_descriptor(addr, segdat2, segdat232, 0); - if (!(segdat2[2] & 0x8000)) { - x86np("TS loading CS not present", new_cs & 0xfffc); - return; - } - switch (segdat2[2] & 0x1f00) { - case 0x1800: case 0x1900: case 0x1a00: case 0x1b00: /* Non-conforming */ - if ((new_cs & 0x0003) != DPL2) { - x86ts("TS loading CS RPL != DPL2", new_cs & 0xfffc); - return; - } - break; - case 0x1c00: case 0x1d00: case 0x1e00: case 0x1f00: /* Conforming */ - if ((new_cs & 0x0003) < DPL2) { - x86ts("TS loading CS RPL < DPL2", new_cs & 0xfffc); - return; - } - break; - default: - x86ts("TS loading CS unknown type", new_cs & 0xfffc); - return; - } + if (cpu_state.eflags & VM_FLAG) { + op_loadcs(new_cs); + set_use32(0); + cpu_cur_status |= CPU_STATUS_V86; + } else { + if (!(new_cs & 0xfffc)) { + x86ts("taskswitch286(): New CS selector is null", 0); + return; + } + addr = new_cs & 0xfff8; + dt = (new_cs & 0x0004) ? &ldt : &gdt; + if ((addr + 7) > dt->limit) { + x86ts("taskswitch286(): New CS selector > DT limit", new_cs & 0xfffc); + return; + } + addr += dt->base; + read_descriptor(addr, segdat2, segdat232, 0); + if (!(segdat2[2] & 0x8000)) { + x86np("TS loading CS not present", new_cs & 0xfffc); + return; + } + switch (segdat2[2] & 0x1f00) { + case 0x1800: + case 0x1900: + case 0x1a00: + case 0x1b00: /* Non-conforming */ + if ((new_cs & 0x0003) != DPL2) { + x86ts("TS loading CS RPL != DPL2", new_cs & 0xfffc); + return; + } + break; + case 0x1c00: + case 0x1d00: + case 0x1e00: + case 0x1f00: /* Conforming */ + if ((new_cs & 0x0003) < DPL2) { + x86ts("TS loading CS RPL < DPL2", new_cs & 0xfffc); + return; + } + break; + default: + x86ts("TS loading CS unknown type", new_cs & 0xfffc); + return; + } - CS = new_cs; - do_seg_load(&cpu_state.seg_cs, segdat2); - if ((CPL == 3) && (oldcpl != 3)) - flushmmucache_cr3(); + CS = new_cs; + do_seg_load(&cpu_state.seg_cs, segdat2); + if ((CPL == 3) && (oldcpl != 3)) + flushmmucache_nopc(); #ifdef USE_NEW_DYNAREC - oldcpl = CPL; + oldcpl = CPL; #endif - set_use32(segdat2[3] & 0x0040); - cpu_cur_status &= ~CPU_STATUS_V86; - } + set_use32(segdat2[3] & 0x0040); + cpu_cur_status &= ~CPU_STATUS_V86; + } - EAX = new_eax; - ECX = new_ecx; - EDX = new_edx; - EBX = new_ebx; - ESP = new_esp; - EBP = new_ebp; - ESI = new_esi; - EDI = new_edi; + EAX = new_eax; + ECX = new_ecx; + EDX = new_edx; + EBX = new_ebx; + ESP = new_esp; + EBP = new_ebp; + ESI = new_esi; + EDI = new_edi; - loadseg(new_es, &cpu_state.seg_es); - loadseg(new_ss, &cpu_state.seg_ss); - loadseg(new_ds, &cpu_state.seg_ds); - loadseg(new_fs, &cpu_state.seg_fs); - loadseg(new_gs, &cpu_state.seg_gs); + op_loadseg(new_es, &cpu_state.seg_es); + op_loadseg(new_ss, &cpu_state.seg_ss); + op_loadseg(new_ds, &cpu_state.seg_ds); + op_loadseg(new_fs, &cpu_state.seg_fs); + op_loadseg(new_gs, &cpu_state.seg_gs); } else { - if (limit < 43) { - x86ts(NULL, seg); - return; - } + if (limit < 43) { + x86ts(NULL, seg); + return; + } - if ((optype == JMP) || (optype == CALL) || (optype == OPTYPE_INT)) { - if (tr.seg & 0x0004) - tempw = readmemw(ldt.base, (seg & 0xfff8) + 4); - else - tempw = readmemw(gdt.base, (seg & 0xfff8) + 4); - if (cpu_state.abrt) - return; - tempw |= 0x200; - if (tr.seg & 0x0004) - writememw(ldt.base, (seg & 0xfff8) + 4, tempw); - else - writememw(gdt.base, (seg & 0xfff8) + 4, tempw); - } - if (cpu_state.abrt) - return; + if ((optype == JMP) || (optype == CALL) || (optype == OPTYPE_INT)) { + if (tr.seg & 0x0004) + tempw = readmemw(ldt.base, (seg & 0xfff8) + 4); + else + tempw = readmemw(gdt.base, (seg & 0xfff8) + 4); + if (cpu_state.abrt) + return; + tempw |= 0x200; + if (tr.seg & 0x0004) + writememw(ldt.base, (seg & 0xfff8) + 4, tempw); + else + writememw(gdt.base, (seg & 0xfff8) + 4, tempw); + } + if (cpu_state.abrt) + return; - if (optype == IRET) - cpu_state.flags &= ~NT_FLAG; + if (optype == IRET) + cpu_state.flags &= ~NT_FLAG; - cpu_386_flags_rebuild(); - writememw(tr.base, 0x0e, cpu_state.pc); - writememw(tr.base, 0x10, cpu_state.flags); + cpu_386_flags_rebuild(); + writememw(tr.base, 0x0e, cpu_state.pc); + writememw(tr.base, 0x10, cpu_state.flags); - writememw(tr.base, 0x12, AX); - writememw(tr.base, 0x14, CX); - writememw(tr.base, 0x16, DX); - writememw(tr.base, 0x18, BX); - writememw(tr.base, 0x1a, SP); - writememw(tr.base, 0x1c, BP); - writememw(tr.base, 0x1e, SI); - writememw(tr.base, 0x20, DI); + writememw(tr.base, 0x12, AX); + writememw(tr.base, 0x14, CX); + writememw(tr.base, 0x16, DX); + writememw(tr.base, 0x18, BX); + writememw(tr.base, 0x1a, SP); + writememw(tr.base, 0x1c, BP); + writememw(tr.base, 0x1e, SI); + writememw(tr.base, 0x20, DI); - writememw(tr.base, 0x22, ES); - writememw(tr.base, 0x24, CS); - writememw(tr.base, 0x26, SS); - writememw(tr.base, 0x28, DS); + writememw(tr.base, 0x22, ES); + writememw(tr.base, 0x24, CS); + writememw(tr.base, 0x26, SS); + writememw(tr.base, 0x28, DS); - if ((optype == JMP) || (optype == IRET)) { - if (tr.seg & 0x0004) - tempw = readmemw(ldt.base, (tr.seg & 0xfff8) + 4); - else - tempw = readmemw(gdt.base, (tr.seg & 0xfff8) + 4); - if (cpu_state.abrt) - return; - tempw &= ~0x200; - if (tr.seg & 0x0004) - writememw(ldt.base, (tr.seg & 0xfff8) + 4, tempw); - else - writememw(gdt.base, (tr.seg & 0xfff8) + 4, tempw); - } - if (cpu_state.abrt) - return; + if ((optype == JMP) || (optype == IRET)) { + if (tr.seg & 0x0004) + tempw = readmemw(ldt.base, (tr.seg & 0xfff8) + 4); + else + tempw = readmemw(gdt.base, (tr.seg & 0xfff8) + 4); + if (cpu_state.abrt) + return; + tempw &= ~0x200; + if (tr.seg & 0x0004) + writememw(ldt.base, (tr.seg & 0xfff8) + 4, tempw); + else + writememw(gdt.base, (tr.seg & 0xfff8) + 4, tempw); + } + if (cpu_state.abrt) + return; - if ((optype == OPTYPE_INT) || (optype == CALL)) { - writememw(base, 0, tr.seg); - if (cpu_state.abrt) - return; - } + if ((optype == OPTYPE_INT) || (optype == CALL)) { + writememw(base, 0, tr.seg); + if (cpu_state.abrt) + return; + } - new_pc = readmemw(base, 0x0e); - new_flags = readmemw(base, 0x10); - if ((optype == OPTYPE_INT) || (optype == CALL)) - new_flags |= NT_FLAG; + new_pc = readmemw(base, 0x0e); + new_flags = readmemw(base, 0x10); + if ((optype == OPTYPE_INT) || (optype == CALL)) + new_flags |= NT_FLAG; - new_eax = readmemw(base, 0x12); - new_ecx = readmemw(base, 0x14); - new_edx = readmemw(base, 0x16); - new_ebx = readmemw(base, 0x18); - new_esp = readmemw(base, 0x1a); - new_ebp = readmemw(base, 0x1c); - new_esi = readmemw(base, 0x1e); - new_edi = readmemw(base, 0x20); + new_eax = readmemw(base, 0x12); + new_ecx = readmemw(base, 0x14); + new_edx = readmemw(base, 0x16); + new_ebx = readmemw(base, 0x18); + new_esp = readmemw(base, 0x1a); + new_ebp = readmemw(base, 0x1c); + new_esi = readmemw(base, 0x1e); + new_edi = readmemw(base, 0x20); - new_es = readmemw(base, 0x22); - new_cs = readmemw(base, 0x24); - new_ss = readmemw(base, 0x26); - new_ds = readmemw(base, 0x28); - new_ldt = readmemw(base, 0x2a); + new_es = readmemw(base, 0x22); + new_cs = readmemw(base, 0x24); + new_ss = readmemw(base, 0x26); + new_ds = readmemw(base, 0x28); + new_ldt = readmemw(base, 0x2a); - msw |= 8; + msw |= 8; - cpu_state.pc = new_pc; - cpu_state.flags = new_flags; - cpu_386_flags_extract(); + cpu_state.pc = new_pc; + cpu_state.flags = new_flags; + cpu_386_flags_extract(); - ldt.seg = new_ldt; - templ = (ldt.seg & 0xfff8) + gdt.base; - ldt.limit = readmemw(0, templ); - ldt.base = (readmemw(0, templ + 2)) | (readmemb(0, templ + 4) << 16); - if (is386) { - if (readmemb(0, templ + 6) & 0x80) { - ldt.limit <<= 12; - ldt.limit |= 0xfff; - } - ldt.base |= (readmemb(0, templ + 7) << 24); - } + ldt.seg = new_ldt; + templ = (ldt.seg & 0xfff8) + gdt.base; + ldt.limit = readmemw(0, templ); + ldt.base = (readmemw(0, templ + 2)) | (readmemb(0, templ + 4) << 16); + if (is386) { + if (readmemb(0, templ + 6) & 0x80) { + ldt.limit <<= 12; + ldt.limit |= 0xfff; + } + ldt.base |= (readmemb(0, templ + 7) << 24); + } - if (!(new_cs & 0xfff8)) { - x86ts(NULL, 0); - return; - } - addr = new_cs & 0xfff8; - dt = (new_cs & 0x0004) ? &ldt : &gdt; - if ((addr + 7) > dt->limit) { - x86ts(NULL, new_cs & 0xfffc); - return; - } - addr += dt->base; - read_descriptor(addr, segdat2, segdat232, 0); - if (!(segdat2[2] & 0x8000)) { - x86np("TS loading CS not present", new_cs & 0xfffc); - return; - } - switch (segdat2[2] & 0x1f00) { - case 0x1800: case 0x1900: case 0x1a00: case 0x1b00: /* Non-conforming */ - if ((new_cs & 0x0003) != DPL2) { - x86ts(NULL,new_cs & 0xfffc); - return; - } - break; - case 0x1c00: case 0x1d00: case 0x1e00: case 0x1f00: /* Conforming */ - if ((new_cs & 0x0003) < DPL2) { - x86ts(NULL,new_cs & 0xfffc); - return; - } - break; - default: - x86ts(NULL, new_cs & 0xfffc); - return; - } + if (!(new_cs & 0xfff8)) { + x86ts(NULL, 0); + return; + } + addr = new_cs & 0xfff8; + dt = (new_cs & 0x0004) ? &ldt : &gdt; + if ((addr + 7) > dt->limit) { + x86ts(NULL, new_cs & 0xfffc); + return; + } + addr += dt->base; + read_descriptor(addr, segdat2, segdat232, 0); + if (!(segdat2[2] & 0x8000)) { + x86np("TS loading CS not present", new_cs & 0xfffc); + return; + } + switch (segdat2[2] & 0x1f00) { + case 0x1800: + case 0x1900: + case 0x1a00: + case 0x1b00: /* Non-conforming */ + if ((new_cs & 0x0003) != DPL2) { + x86ts(NULL, new_cs & 0xfffc); + return; + } + break; + case 0x1c00: + case 0x1d00: + case 0x1e00: + case 0x1f00: /* Conforming */ + if ((new_cs & 0x0003) < DPL2) { + x86ts(NULL, new_cs & 0xfffc); + return; + } + break; + default: + x86ts(NULL, new_cs & 0xfffc); + return; + } - CS = new_cs; - do_seg_load(&cpu_state.seg_cs, segdat2); - if ((CPL == 3) && (oldcpl != 3)) - flushmmucache_cr3(); + CS = new_cs; + do_seg_load(&cpu_state.seg_cs, segdat2); + if ((CPL == 3) && (oldcpl != 3)) + flushmmucache_nopc(); #ifdef USE_NEW_DYNAREC - oldcpl = CPL; + oldcpl = CPL; #endif - set_use32(0); + set_use32(0); - EAX = new_eax | 0xffff0000; - ECX = new_ecx | 0xffff0000; - EDX = new_edx | 0xffff0000; - EBX = new_ebx | 0xffff0000; - ESP = new_esp | 0xffff0000; - EBP = new_ebp | 0xffff0000; - ESI = new_esi | 0xffff0000; - EDI = new_edi | 0xffff0000; + EAX = new_eax | 0xffff0000; + ECX = new_ecx | 0xffff0000; + EDX = new_edx | 0xffff0000; + EBX = new_ebx | 0xffff0000; + ESP = new_esp | 0xffff0000; + EBP = new_ebp | 0xffff0000; + ESI = new_esi | 0xffff0000; + EDI = new_edi | 0xffff0000; - loadseg(new_es, &cpu_state.seg_es); - loadseg(new_ss, &cpu_state.seg_ss); - loadseg(new_ds, &cpu_state.seg_ds); - if (is386) { - loadseg(0, &cpu_state.seg_fs); - loadseg(0, &cpu_state.seg_gs); - } + op_loadseg(new_es, &cpu_state.seg_es); + op_loadseg(new_ss, &cpu_state.seg_ss); + op_loadseg(new_ds, &cpu_state.seg_ds); + if (is386) { + op_loadseg(0, &cpu_state.seg_fs); + op_loadseg(0, &cpu_state.seg_gs); + } } - tr.seg = seg; - tr.base = base; - tr.limit = limit; - tr.access = segdat[2] >> 8; + tr.seg = seg; + tr.base = base; + tr.limit = limit; + tr.access = segdat[2] >> 8; tr.ar_high = segdat[3] & 0xff; } - void +#ifdef OPS_286_386 +cyrix_write_seg_descriptor_2386(uint32_t addr, x86seg *seg) +#else cyrix_write_seg_descriptor(uint32_t addr, x86seg *seg) +#endif { uint32_t limit_raw = seg->limit; if (seg->ar_high & 0x80) - limit_raw >>= 12; + limit_raw >>= 12; writememl(0, addr, (limit_raw & 0xffff) | (seg->base << 16)); - writememl(0, addr + 4, ((seg->base >> 16) & 0xff) | (seg->access << 8) | - (limit_raw & 0xf0000) | (seg->ar_high << 16) | - (seg->base & 0xff000000)); + writememl(0, addr + 4, ((seg->base >> 16) & 0xff) | (seg->access << 8) | (limit_raw & 0xf0000) | (seg->ar_high << 16) | (seg->base & 0xff000000)); } - void +#ifdef OPS_286_386 +cyrix_load_seg_descriptor_2386(uint32_t addr, x86seg *seg) +#else cyrix_load_seg_descriptor(uint32_t addr, x86seg *seg) +#endif { - uint16_t segdat[4], selector; + uint16_t segdat[4]; + uint16_t selector; segdat[0] = readmemw(0, addr); segdat[1] = readmemw(0, addr + 2); segdat[2] = readmemw(0, addr + 4); segdat[3] = readmemw(0, addr + 6); - selector = readmemw(0, addr+8); + selector = readmemw(0, addr + 8); if (!cpu_state.abrt) { - do_seg_load(seg, segdat); - seg->seg = selector; - seg->checked = 0; - if (seg == &cpu_state.seg_ds) { - if (seg->base == 0 && seg->limit_low == 0 && seg->limit_high == 0xffffffff) - cpu_cur_status &= ~CPU_STATUS_NOTFLATDS; - else - cpu_cur_status |= CPU_STATUS_NOTFLATDS; + do_seg_load(seg, segdat); + seg->seg = selector; + seg->checked = 0; + if (seg == &cpu_state.seg_ds) { + if (seg->base == 0 && seg->limit_low == 0 && seg->limit_high == 0xffffffff) + cpu_cur_status &= ~CPU_STATUS_NOTFLATDS; + else + cpu_cur_status |= CPU_STATUS_NOTFLATDS; #ifdef USE_DYNAREC - codegen_flat_ds = 0; + codegen_flat_ds = 0; #endif - } - if (seg == &cpu_state.seg_ss) { - if (seg->base == 0 && seg->limit_low == 0 && seg->limit_high == 0xffffffff) - cpu_cur_status &= ~CPU_STATUS_NOTFLATSS; - else - cpu_cur_status |= CPU_STATUS_NOTFLATSS; - set_stack32((segdat[3] & 0x40) ? 1 : 0); + } + if (seg == &cpu_state.seg_ss) { + if (seg->base == 0 && seg->limit_low == 0 && seg->limit_high == 0xffffffff) + cpu_cur_status &= ~CPU_STATUS_NOTFLATSS; + else + cpu_cur_status |= CPU_STATUS_NOTFLATSS; + set_stack32((segdat[3] & 0x40) ? 1 : 0); #ifdef USE_DYNAREC - codegen_flat_ss = 0; + codegen_flat_ss = 0; #endif - } + } } } diff --git a/src/cpu/x86seg.h b/src/cpu/x86seg.h index d98db1586..dcc8c9ef8 100644 --- a/src/cpu/x86seg.h +++ b/src/cpu/x86seg.h @@ -1,21 +1,95 @@ /* - * 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. + * 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. + * This file is part of the 86Box distribution. * - * x86 CPU segment emulation. + * x86 CPU segment emulation header. * * * - * Author: Miran Grca, + * Authors: Miran Grca, * - * Copyright 2016-2017 Miran Grca. + * Copyright 2016-2017 Miran Grca. */ +#ifndef EMU_X86SEG_H +#define EMU_X86SEG_H -extern void do_seg_load(x86seg *s, uint16_t *segdat); +#ifdef OPS_286_386 + +extern void x86_doabrt_2386(int x86_abrt); +#ifdef USE_NEW_DYNAREC +extern int loadseg_2386(uint16_t seg, x86seg *s); +#else +extern void loadseg_2386(uint16_t seg, x86seg *s); +#endif +extern void loadcs_2386(uint16_t seg); +extern void loadcsjmp_2386(uint16_t seg, uint32_t old_pc); +#ifdef USE_NEW_DYNAREC +extern void loadcscall_2386(uint16_t seg, uint32_t old_pc); +#else +extern void loadcscall_2386(uint16_t seg); +#endif +extern void pmoderetf_2386(int is32, uint16_t off); +extern void pmodeint_2386(int num, int soft); +extern void pmodeiret_2386(int is32); +extern void taskswitch286_2386(uint16_t seg, uint16_t *segdat, int is32); + +/* #define's to avoid long #ifdef blocks in x86_ops_*.h. */ +#define op_doabrt x86_doabrt_2386 +#define op_loadseg loadseg_2386 +#define op_loadcs loadcs_2386 +#define op_loadcsjmp loadcsjmp_2386 +#define op_loadcscall loadcscall_2386 +#define op_pmoderetf pmoderetf_2386 +#define op_pmodeint pmodeint_2386 +#define op_pmodeiret pmodeiret_2386 +#define op_taskswitch taskswitch_2386 +#define op_taskswitch286 taskswitch286_2386 + +#else + +extern void x86_doabrt(int x86_abrt); +#ifdef USE_NEW_DYNAREC +extern int loadseg(uint16_t seg, x86seg *s); +#else +extern void loadseg(uint16_t seg, x86seg *s); +#endif +/* The prototype of loadcs_2386() is needed here for reset. */ +extern void loadcs_2386(uint16_t seg); +extern void loadcs(uint16_t seg); +extern void loadcsjmp(uint16_t seg, uint32_t old_pc); +#ifdef USE_NEW_DYNAREC +extern void loadcscall(uint16_t seg, uint32_t old_pc); +#else +extern void loadcscall(uint16_t seg); +#endif +extern void pmoderetf(int is32, uint16_t off); +/* The prototype of pmodeint_2386() is needed here for 386_common.c interrupts. */ +extern void pmodeint_2386(int num, int soft); +extern void pmodeint(int num, int soft); +extern void pmodeiret(int is32); +extern void taskswitch286(uint16_t seg, uint16_t *segdat, int is32); + +/* #define's to avoid long #ifdef blocks in x86_ops_*.h. */ +#define op_doabrt x86_doabrt +#define op_loadseg loadseg +#define op_loadcs loadcs +#define op_loadcsjmp loadcsjmp +#define op_loadcscall loadcscall +#define op_pmoderetf pmoderetf +#define op_pmodeint pmodeint +#define op_pmodeiret pmodeiret +#define op_taskswitch286 taskswitch286 + +#endif + +extern void cyrix_write_seg_descriptor_2386(uint32_t addr, x86seg *seg); +extern void cyrix_load_seg_descriptor_2386(uint32_t addr, x86seg *seg); extern void cyrix_write_seg_descriptor(uint32_t addr, x86seg *seg); extern void cyrix_load_seg_descriptor(uint32_t addr, x86seg *seg); + +#endif /*EMU_X86SEG_H*/ diff --git a/src/cpu/x86seg_2386.c b/src/cpu/x86seg_2386.c new file mode 100644 index 000000000..335c757e4 --- /dev/null +++ b/src/cpu/x86seg_2386.c @@ -0,0 +1,22 @@ +/* + * 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. + * + * x86 CPU segment emulation for the 286/386 interpreter. + * + * + * + * Authors: Sarah Walker, + * Miran Grca, + * + * Copyright 2008-2018 Sarah Walker. + * Copyright 2016-2018 Miran Grca. + */ +#ifndef OPS_286_386 +# define OPS_286_386 +#endif +#include "x86seg.c" diff --git a/src/cpu/x86seg_common.c b/src/cpu/x86seg_common.c new file mode 100644 index 000000000..8926af0d7 --- /dev/null +++ b/src/cpu/x86seg_common.c @@ -0,0 +1,123 @@ +/* + * 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. + * + * x86 CPU segment emulation commmon parts. + * + * + * + * Authors: Sarah Walker, + * Miran Grca, + * + * Copyright 2008-2018 Sarah Walker. + * Copyright 2016-2018 Miran Grca. + */ +#include +#include +#include +#include +#include +#include +#include +#define HAVE_STDARG_H +#include <86box/86box.h> +#include "cpu.h" +#include "x86.h" +#include "x86seg_common.h" +#include <86box/device.h> +#include <86box/timer.h> +#include <86box/machine.h> +#include <86box/mem.h> +#include <86box/nvr.h> +#include <86box/plat_fallthrough.h> +#include <86box/plat_unused.h> + +uint8_t opcode2; + +int cgate16; +int cgate32; + +int intgatesize; + +static void +seg_reset(x86seg *s) +{ + s->access = 0x82; + s->ar_high = 0x10; + s->limit = 0xffff; + s->limit_low = 0; + s->limit_high = 0xffff; + if (s == &cpu_state.seg_cs) { + if (!cpu_inited) + fatal("seg_reset(&cpu_state.seg.cs) without an initialized CPU\n"); + if (is6117) + s->base = 0x03ff0000; + else + s->base = is286 ? (cpu_16bitbus ? 0x00ff0000 : 0xffff0000) : 0x000ffff0; + s->seg = is286 ? 0xf000 : 0xffff; + } else { + s->base = 0; + s->seg = 0; + } +} + +void +x86seg_reset(void) +{ + seg_reset(&cpu_state.seg_cs); + seg_reset(&cpu_state.seg_ds); + seg_reset(&cpu_state.seg_es); + seg_reset(&cpu_state.seg_fs); + seg_reset(&cpu_state.seg_gs); + seg_reset(&cpu_state.seg_ss); +} + +void +x86de(UNUSED(char *s), UNUSED(uint16_t error)) +{ +#ifdef BAD_CODE + cpu_state.abrt = ABRT_DE; + abrt_error = error; +#else + x86_int(0); +#endif +} + +void +x86gpf(UNUSED(char *s), uint16_t error) +{ + cpu_state.abrt = ABRT_GPF; + abrt_error = error; +} + +void +x86gpf_expected(UNUSED(char *s), uint16_t error) +{ + cpu_state.abrt = ABRT_GPF | ABRT_EXPECTED; + abrt_error = error; +} + +void +x86ss(UNUSED(char *s), uint16_t error) +{ + cpu_state.abrt = ABRT_SS; + abrt_error = error; +} + +void +x86ts(UNUSED(char *s), uint16_t error) +{ + cpu_state.abrt = ABRT_TS; + abrt_error = error; +} + +void +x86np(UNUSED(char *s), uint16_t error) +{ + cpu_state.abrt = ABRT_NP; + abrt_error = error; +} diff --git a/src/cpu/x86seg_common.h b/src/cpu/x86seg_common.h new file mode 100644 index 000000000..f4bffed40 --- /dev/null +++ b/src/cpu/x86seg_common.h @@ -0,0 +1,52 @@ +/* + * 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. + * + * x86 CPU segment emulation common parts header. + * + * + * + * Authors: Miran Grca, + * + * Copyright 2016-2017 Miran Grca. + */ +#ifndef EMU_X86SEG_COMMON_H +#define EMU_X86SEG_COMMON_H + +#define JMP 1 +#define CALL 2 +#define IRET 3 +#define OPTYPE_INT 4 + +enum { + ABRT_NONE = 0, + ABRT_GEN = 1, + ABRT_TS = 0xA, + ABRT_NP = 0xB, + ABRT_SS = 0xC, + ABRT_GPF = 0xD, + ABRT_PF = 0xE, + ABRT_DE = 0x40 /* INT 0, but we have to distinguish it from ABRT_NONE. */ +}; + +extern uint8_t opcode2; + +extern int cgate16; +extern int cgate32; + +extern int intgatesize; + +extern void x86seg_reset(void); +extern void x86de(char *s, uint16_t error); +extern void x86gpf(char *s, uint16_t error); +extern void x86gpf_expected(char *s, uint16_t error); +extern void x86np(char *s, uint16_t error); +extern void x86ss(char *s, uint16_t error); +extern void x86ts(char *s, uint16_t error); +extern void do_seg_load(x86seg *s, uint16_t *segdat); + +#endif /*EMU_X86SEG_COMMON_H*/ diff --git a/src/cpu/x87.c b/src/cpu/x87.c index 47ab0c844..1f7643453 100644 --- a/src/cpu/x87.c +++ b/src/cpu/x87.c @@ -13,120 +13,531 @@ #include "x86.h" #include "x86_flags.h" #include "x86_ops.h" +#include "x86seg_common.h" #include "x87.h" #include "386_common.h" +#include "softfloat/softfloat-specialize.h" - -uint32_t x87_pc_off,x87_op_off; -uint16_t x87_pc_seg,x87_op_seg; - +uint32_t x87_pc_off; +uint32_t x87_op_off; +uint16_t x87_pc_seg; +uint16_t x87_op_seg; #ifdef ENABLE_FPU_LOG int fpu_do_log = ENABLE_FPU_LOG; - void fpu_log(const char *fmt, ...) { va_list ap; if (fpu_do_log) { - va_start(ap, fmt); - pclog_ex(fmt, ap); - va_end(ap); + va_start(ap, fmt); + pclog_ex(fmt, ap); + va_end(ap); } } #else -#define fpu_log(fmt, ...) +# define fpu_log(fmt, ...) #endif - -#define X87_TAG_VALID 0 -#define X87_TAG_ZERO 1 -#define X87_TAG_INVALID 2 -#define X87_TAG_EMPTY 3 - #ifdef USE_NEW_DYNAREC -uint16_t x87_gettag() +uint16_t +x87_gettag(void) { - uint16_t ret = 0; - int c; - - for (c = 0; c < 8; c++) - { - if (cpu_state.tag[c] == TAG_EMPTY) - ret |= X87_TAG_EMPTY << (c * 2); - else if (cpu_state.tag[c] & TAG_UINT64) - ret |= 2 << (c*2); - else if (cpu_state.ST[c] == 0.0 && !cpu_state.ismmx) - ret |= X87_TAG_ZERO << (c * 2); - else - ret |= X87_TAG_VALID << (c * 2); - } + uint16_t ret = 0; - return ret; + for (uint8_t c = 0; c < 8; c++) { + if (cpu_state.tag[c] == TAG_EMPTY) + ret |= X87_TAG_EMPTY << (c * 2); + else if (cpu_state.tag[c] & TAG_UINT64) + ret |= 2 << (c * 2); + else if (cpu_state.ST[c] == 0.0 && !cpu_state.ismmx) + ret |= X87_TAG_ZERO << (c * 2); + else + ret |= X87_TAG_VALID << (c * 2); + } + + return ret; } -void x87_settag(uint16_t new_tag) +void +x87_settag(uint16_t new_tag) { - int c; - - for (c = 0; c < 8; c++) - { - int tag = (new_tag >> (c * 2)) & 3; - - if (tag == X87_TAG_EMPTY) - cpu_state.tag[c] = TAG_EMPTY; - else if (tag == 2) - cpu_state.tag[c] = TAG_VALID | TAG_UINT64; - else - cpu_state.tag[c] = TAG_VALID; - } + for (uint8_t c = 0; c < 8; c++) { + int tag = (new_tag >> (c * 2)) & 3; + + if (tag == X87_TAG_EMPTY) + cpu_state.tag[c] = TAG_EMPTY; + else if (tag == 2) + cpu_state.tag[c] = TAG_VALID | TAG_UINT64; + else + cpu_state.tag[c] = TAG_VALID; + } } #else -uint16_t x87_gettag() +uint16_t +x87_gettag(void) { - uint16_t ret = 0; - int c; - - for (c = 0; c < 8; c++) - { - if (cpu_state.tag[c] & TAG_UINT64) - ret |= 2 << (c*2); - else - ret |= (cpu_state.tag[c] << (c*2)); - } + uint16_t ret = 0; + int c; - return ret; + for (c = 0; c < 8; c++) { + if (cpu_state.tag[c] & TAG_UINT64) + ret |= 2 << (c * 2); + else + ret |= (cpu_state.tag[c] << (c * 2)); + } + + return ret; } -void x87_settag(uint16_t new_tag) +void +x87_settag(uint16_t new_tag) { - cpu_state.tag[0] = new_tag & 3; - cpu_state.tag[1] = (new_tag >> 2) & 3; - cpu_state.tag[2] = (new_tag >> 4) & 3; - cpu_state.tag[3] = (new_tag >> 6) & 3; - cpu_state.tag[4] = (new_tag >> 8) & 3; - cpu_state.tag[5] = (new_tag >> 10) & 3; - cpu_state.tag[6] = (new_tag >> 12) & 3; - cpu_state.tag[7] = (new_tag >> 14) & 3; + cpu_state.tag[0] = new_tag & 3; + cpu_state.tag[1] = (new_tag >> 2) & 3; + cpu_state.tag[2] = (new_tag >> 4) & 3; + cpu_state.tag[3] = (new_tag >> 6) & 3; + cpu_state.tag[4] = (new_tag >> 8) & 3; + cpu_state.tag[5] = (new_tag >> 10) & 3; + cpu_state.tag[6] = (new_tag >> 12) & 3; + cpu_state.tag[7] = (new_tag >> 14) & 3; } #endif +static floatx80 +FPU_handle_NaN32_Func(floatx80 a, int aIsNaN, float32 b32, int bIsNaN, struct float_status_t *status) +{ + int aIsSignalingNaN = floatx80_is_signaling_nan(a); + int bIsSignalingNaN = float32_is_signaling_nan(b32); + + if (aIsSignalingNaN | bIsSignalingNaN) + float_raise(status, float_flag_invalid); + + // propagate QNaN to SNaN + a = propagateFloatx80NaNOne(a, status); + + if (aIsNaN & !bIsNaN) + return a; + + // float32 is NaN so conversion will propagate SNaN to QNaN and raise + // appropriate exception flags + floatx80 b = float32_to_floatx80(b32, status); + + if (aIsSignalingNaN) { + if (bIsSignalingNaN) + goto returnLargerSignificand; + return bIsNaN ? b : a; + } else if (aIsNaN) { + if (bIsSignalingNaN) + return a; +returnLargerSignificand: + if (a.fraction < b.fraction) + return b; + if (b.fraction < a.fraction) + return a; + return (a.exp < b.exp) ? a : b; + } else { + return b; + } +} + +int +FPU_handle_NaN32(floatx80 a, float32 b, floatx80 *r, struct float_status_t *status) +{ + const floatx80 floatx80_default_nan = packFloatx80(0, floatx80_default_nan_exp, floatx80_default_nan_fraction); + + if (floatx80_is_unsupported(a)) { + float_raise(status, float_flag_invalid); + *r = floatx80_default_nan; + return 1; + } + + int aIsNaN = floatx80_is_nan(a); + int bIsNaN = float32_is_nan(b); + if (aIsNaN | bIsNaN) { + *r = FPU_handle_NaN32_Func(a, aIsNaN, b, bIsNaN, status); + return 1; + } + return 0; +} + +static floatx80 +FPU_handle_NaN64_Func(floatx80 a, int aIsNaN, float64 b64, int bIsNaN, struct float_status_t *status) +{ + int aIsSignalingNaN = floatx80_is_signaling_nan(a); + int bIsSignalingNaN = float64_is_signaling_nan(b64); + + if (aIsSignalingNaN | bIsSignalingNaN) + float_raise(status, float_flag_invalid); + + // propagate QNaN to SNaN + a = propagateFloatx80NaNOne(a, status); + + if (aIsNaN & !bIsNaN) + return a; + + // float64 is NaN so conversion will propagate SNaN to QNaN and raise + // appropriate exception flags + floatx80 b = float64_to_floatx80(b64, status); + + if (aIsSignalingNaN) { + if (bIsSignalingNaN) + goto returnLargerSignificand; + return bIsNaN ? b : a; + } else if (aIsNaN) { + if (bIsSignalingNaN) + return a; +returnLargerSignificand: + if (a.fraction < b.fraction) + return b; + if (b.fraction < a.fraction) + return a; + return (a.exp < b.exp) ? a : b; + } else { + return b; + } +} + +int +FPU_handle_NaN64(floatx80 a, float64 b, floatx80 *r, struct float_status_t *status) +{ + const floatx80 floatx80_default_nan = packFloatx80(0, floatx80_default_nan_exp, floatx80_default_nan_fraction); + + if (floatx80_is_unsupported(a)) { + float_raise(status, float_flag_invalid); + *r = floatx80_default_nan; + return 1; + } + + int aIsNaN = floatx80_is_nan(a); + int bIsNaN = float64_is_nan(b); + if (aIsNaN | bIsNaN) { + *r = FPU_handle_NaN64_Func(a, aIsNaN, b, bIsNaN, status); + return 1; + } + return 0; +} + +struct float_status_t +i387cw_to_softfloat_status_word(uint16_t control_word) +{ + struct float_status_t status; + int precision = control_word & FPU_CW_PC; + + switch (precision) { + case FPU_PR_32_BITS: + status.float_rounding_precision = 32; + break; + case FPU_PR_64_BITS: + status.float_rounding_precision = 64; + break; + case FPU_PR_80_BITS: + status.float_rounding_precision = 80; + break; + default: + /* With the precision control bits set to 01 "(reserved)", a + real CPU behaves as if the precision control bits were + set to 11 "80 bits" */ + status.float_rounding_precision = 80; + break; + } + + status.float_exception_flags = 0; // clear exceptions before execution + status.float_nan_handling_mode = float_first_operand_nan; + status.float_rounding_mode = (control_word & FPU_CW_RC) >> 10; + status.flush_underflow_to_zero = 0; + status.float_suppress_exception = 0; + status.float_exception_masks = control_word & FPU_CW_Exceptions_Mask; + status.denormals_are_zeros = 0; + return status; +} + +int +FPU_status_word_flags_fpu_compare(int float_relation) +{ + switch (float_relation) { + case float_relation_unordered: + return (C0 | C2 | C3); + + case float_relation_greater: + return 0; + + case float_relation_less: + return C0; + + case float_relation_equal: + return C3; + } + + return (-1); // should never get here +} + +void +FPU_write_eflags_fpu_compare(int float_relation) +{ + switch (float_relation) { + case float_relation_unordered: + cpu_state.flags |= (Z_FLAG | P_FLAG | C_FLAG); + break; + + case float_relation_greater: + break; + + case float_relation_less: + cpu_state.flags |= C_FLAG; + break; + + case float_relation_equal: + cpu_state.flags |= Z_FLAG; + break; + + default: + break; + } +} + +uint16_t +FPU_exception(uint32_t fetchdat, uint16_t exceptions, int store) +{ + uint16_t status; + uint16_t unmasked; + + /* Extract only the bits which we use to set the status word */ + exceptions &= FPU_SW_Exceptions_Mask; + status = fpu_state.swd; + + unmasked = (exceptions & ~fpu_state.cwd) & FPU_CW_Exceptions_Mask; + + // if IE or DZ exception happen nothing else will be reported + if (exceptions & (FPU_EX_Invalid | FPU_EX_Zero_Div)) { + unmasked &= (FPU_EX_Invalid | FPU_EX_Zero_Div); + } + + /* Set summary bits if exception isn't masked */ + if (unmasked) { + fpu_state.swd |= (FPU_SW_Summary | FPU_SW_Backward); + } + + if (exceptions & FPU_EX_Invalid) { + // FPU_EX_Invalid cannot come with any other exception but x87 stack fault + fpu_state.swd |= exceptions; + if (exceptions & FPU_SW_Stack_Fault) { + if (!(exceptions & C1)) { + /* This bit distinguishes over- from underflow for a stack fault, + and roundup from round-down for precision loss. */ + fpu_state.swd &= ~C1; + } + } + return unmasked; + } + + if (exceptions & FPU_EX_Zero_Div) { + fpu_state.swd |= FPU_EX_Zero_Div; + if (!(fpu_state.cwd & FPU_EX_Zero_Div)) { +#ifdef FPU_8087 + if (!(fpu_state.cwd & FPU_SW_Summary)) { + fpu_state.cwd |= FPU_SW_Summary; + nmi = 1; + } +#else + picint(1 << 13); +#endif // FPU_8087 + } + return unmasked; + } + + if (exceptions & FPU_EX_Denormal) { + fpu_state.swd |= FPU_EX_Denormal; + if (unmasked & FPU_EX_Denormal) { + return (unmasked & FPU_EX_Denormal); + } + } + + /* Set the corresponding exception bits */ + fpu_state.swd |= exceptions; + + if (exceptions & FPU_EX_Precision) { + if (!(exceptions & C1)) { + /* This bit distinguishes over- from underflow for a stack fault, + and roundup from round-down for precision loss. */ + fpu_state.swd &= ~C1; + } + } + + // If #P unmasked exception occurred the result still has to be + // written to the destination. + unmasked &= ~FPU_EX_Precision; + + if (unmasked & (FPU_EX_Underflow | FPU_EX_Overflow)) { + // If unmasked over- or underflow occurs and dest is a memory location: + // - the TOS and destination operands remain unchanged + // - the inexact-result condition is not reported and C1 flag is cleared + // - no result is stored in the memory + // If the destination is in the register stack, adjusted resulting value + // is stored in the destination operand. + if (!store) + unmasked &= ~(FPU_EX_Underflow | FPU_EX_Overflow); + else { + fpu_state.swd &= ~C1; + if (!(status & FPU_EX_Precision)) + fpu_state.swd &= ~FPU_EX_Precision; + } + } + return unmasked; +} + +void +FPU_stack_overflow(uint32_t fetchdat) +{ + const floatx80 floatx80_default_nan = packFloatx80(0, floatx80_default_nan_exp, floatx80_default_nan_fraction); + + /* The masked response */ + if (is_IA_masked()) { + FPU_push(); + FPU_save_regi(floatx80_default_nan, 0); + } + FPU_exception(fetchdat, FPU_EX_Stack_Overflow, 0); +} + +void +FPU_stack_underflow(uint32_t fetchdat, int stnr, int pop_stack) +{ + const floatx80 floatx80_default_nan = packFloatx80(0, floatx80_default_nan_exp, floatx80_default_nan_fraction); + + /* The masked response */ + if (is_IA_masked()) { + FPU_save_regi(floatx80_default_nan, stnr); + if (pop_stack) + FPU_pop(); + } + FPU_exception(fetchdat, FPU_EX_Stack_Underflow, 0); +} + +/* ----------------------------------------------------------- + * Slimmed down version used to compile against a CPU simulator + * rather than a kernel (ported by Kevin Lawton) + * ------------------------------------------------------------ */ +int +FPU_tagof(const floatx80 reg) +{ + int32_t exp = floatx80_exp(reg); + if (exp == 0) { + if (!floatx80_fraction(reg)) + return X87_TAG_ZERO; + + /* The number is a de-normal or pseudodenormal. */ + return X87_TAG_INVALID; + } + + if (exp == 0x7fff) { + /* Is an Infinity, a NaN, or an unsupported data type. */ + return X87_TAG_INVALID; + } + + if (!(reg.fraction & BX_CONST64(0x8000000000000000))) { + /* Unsupported data type. */ + /* Valid numbers have the ms bit set to 1. */ + return X87_TAG_INVALID; + } + + 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 x87_dumpregs() +void +x87_dumpregs(void) { - if (cpu_state.ismmx) - { - fpu_log("MM0=%016llX\tMM1=%016llX\tMM2=%016llX\tMM3=%016llX\n", cpu_state.MM[0].q, cpu_state.MM[1].q, cpu_state.MM[2].q, cpu_state.MM[3].q); - fpu_log("MM4=%016llX\tMM5=%016llX\tMM6=%016llX\tMM7=%016llX\n", cpu_state.MM[4].q, cpu_state.MM[5].q, cpu_state.MM[6].q, cpu_state.MM[7].q); - } - else - { - fpu_log("ST(0)=%f\tST(1)=%f\tST(2)=%f\tST(3)=%f\t\n",cpu_state.ST[cpu_state.TOP],cpu_state.ST[(cpu_state.TOP+1)&7],cpu_state.ST[(cpu_state.TOP+2)&7],cpu_state.ST[(cpu_state.TOP+3)&7]); - fpu_log("ST(4)=%f\tST(5)=%f\tST(6)=%f\tST(7)=%f\t\n",cpu_state.ST[(cpu_state.TOP+4)&7],cpu_state.ST[(cpu_state.TOP+5)&7],cpu_state.ST[(cpu_state.TOP+6)&7],cpu_state.ST[(cpu_state.TOP+7)&7]); - } - fpu_log("Status = %04X Control = %04X Tag = %04X\n", cpu_state.npxs, cpu_state.npxc, x87_gettag()); + if (cpu_state.ismmx) { + fpu_log("MM0=%016llX\tMM1=%016llX\tMM2=%016llX\tMM3=%016llX\n", cpu_state.MM[0].q, cpu_state.MM[1].q, cpu_state.MM[2].q, cpu_state.MM[3].q); + fpu_log("MM4=%016llX\tMM5=%016llX\tMM6=%016llX\tMM7=%016llX\n", cpu_state.MM[4].q, cpu_state.MM[5].q, cpu_state.MM[6].q, cpu_state.MM[7].q); + } else { + fpu_log("ST(0)=%f\tST(1)=%f\tST(2)=%f\tST(3)=%f\t\n", cpu_state.ST[cpu_state.TOP], cpu_state.ST[(cpu_state.TOP + 1) & 7], cpu_state.ST[(cpu_state.TOP + 2) & 7], cpu_state.ST[(cpu_state.TOP + 3) & 7]); + fpu_log("ST(4)=%f\tST(5)=%f\tST(6)=%f\tST(7)=%f\t\n", cpu_state.ST[(cpu_state.TOP + 4) & 7], cpu_state.ST[(cpu_state.TOP + 5) & 7], cpu_state.ST[(cpu_state.TOP + 6) & 7], cpu_state.ST[(cpu_state.TOP + 7) & 7]); + } + fpu_log("Status = %04X Control = %04X Tag = %04X\n", cpu_state.npxs, cpu_state.npxc, x87_gettag()); } #endif diff --git a/src/cpu/x87.h b/src/cpu/x87.h index 9436d0447..f4e24f1ca 100644 --- a/src/cpu/x87.h +++ b/src/cpu/x87.h @@ -1,43 +1,56 @@ -#define C0 (1<<8) -#define C1 (1<<9) -#define C2 (1<<10) -#define C3 (1<<14) +#define X87_TAG_VALID 0 +#define X87_TAG_ZERO 1 +#define X87_TAG_INVALID 2 +#define X87_TAG_EMPTY 3 -extern uint32_t x87_pc_off,x87_op_off; -extern uint16_t x87_pc_seg,x87_op_seg; +extern uint32_t x87_pc_off; +extern uint32_t x87_op_off; +extern uint16_t x87_pc_seg; +extern uint16_t x87_op_seg; -static __inline void x87_set_mmx() +static __inline void +x87_set_mmx(void) { - uint64_t *p; + uint64_t *p; + 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; + p = (uint64_t *) cpu_state.tag; + *p = 0x0101010101010101ULL; + } + cpu_state.ismmx = 1; } -static __inline void x87_emms() +static __inline void +x87_emms(void) { - uint64_t *p; - p = (uint64_t *)cpu_state.tag; + uint64_t *p; + 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; + } + cpu_state.ismmx = 0; } +uint16_t x87_gettag(void); +void x87_settag(uint16_t new_tag); -uint16_t x87_gettag(); -void x87_settag(uint16_t new_tag); - -#define TAG_EMPTY 0 -#define TAG_VALID (1 << 0) +#define TAG_EMPTY 0 +#define TAG_VALID (1 << 0) /*Hack for FPU copy. If set then MM[].q contains the 64-bit integer loaded by FILD*/ #ifdef USE_NEW_DYNAREC -#define TAG_UINT64 (1 << 7) +# define TAG_UINT64 (1 << 7) #else -#define TAG_UINT64 (1 << 2) +# define TAG_UINT64 (1 << 2) #endif /*Old dynarec stuff.*/ -#define TAG_NOT_UINT64 0xfb +#define TAG_NOT_UINT64 0xfb #define X87_ROUNDING_NEAREST 0 #define X87_ROUNDING_DOWN 1 @@ -45,3 +58,191 @@ void x87_settag(uint16_t new_tag); #define X87_ROUNDING_CHOP 3 void codegen_set_rounding_mode(int mode); + +/* Status Word */ +#define FPU_SW_Backward (0x8000) /* backward compatibility */ +#define FPU_SW_C3 (0x4000) /* condition bit 3 */ +#define FPU_SW_Top (0x3800) /* top of stack */ +#define FPU_SW_C2 (0x0400) /* condition bit 2 */ +#define FPU_SW_C1 (0x0200) /* condition bit 1 */ +#define FPU_SW_C0 (0x0100) /* condition bit 0 */ +#define FPU_SW_Summary (0x0080) /* exception summary */ +#define FPU_SW_Stack_Fault (0x0040) /* stack fault */ +#define FPU_SW_Precision (0x0020) /* loss of precision */ +#define FPU_SW_Underflow (0x0010) /* underflow */ +#define FPU_SW_Overflow (0x0008) /* overflow */ +#define FPU_SW_Zero_Div (0x0004) /* divide by zero */ +#define FPU_SW_Denormal_Op (0x0002) /* denormalized operand */ +#define FPU_SW_Invalid (0x0001) /* invalid operation */ + +#define C0 (1 << 8) +#define C1 (1 << 9) +#define C2 (1 << 10) +#define C3 (1 << 14) + +#define FPU_SW_CC (C0 | C1 | C2 | C3) + +#define FPU_SW_Exceptions_Mask (0x027f) /* status word exceptions bit mask */ + +/* Exception flags: */ +#define FPU_EX_Precision (0x0020) /* loss of precision */ +#define FPU_EX_Underflow (0x0010) /* underflow */ +#define FPU_EX_Overflow (0x0008) /* overflow */ +#define FPU_EX_Zero_Div (0x0004) /* divide by zero */ +#define FPU_EX_Denormal (0x0002) /* denormalized operand */ +#define FPU_EX_Invalid (0x0001) /* invalid operation */ + +/* Special exceptions: */ +#define FPU_EX_Stack_Overflow (0x0041 | C1) /* stack overflow */ +#define FPU_EX_Stack_Underflow (0x0041) /* stack underflow */ + +/* precision control */ +#define FPU_EX_Precision_Lost_Up (EX_Precision | C1) +#define FPU_EX_Precision_Lost_Dn (EX_Precision) + +#define setcc(cc) \ + fpu_state.swd = (fpu_state.swd & ~(FPU_SW_CC)) | ((cc) &FPU_SW_CC) + +#define clear_C1() \ + { \ + fpu_state.swd &= ~C1; \ + } +#define clear_C2() \ + { \ + fpu_state.swd &= ~C2; \ + } + +/* ************ */ +/* Control Word */ +/* ************ */ + +#define FPU_CW_Inf (0x1000) /* infinity control, legacy */ + +#define FPU_CW_RC (0x0C00) /* rounding control */ +#define FPU_CW_PC (0x0300) /* precision control */ + +#define FPU_RC_RND (0x0000) /* rounding control */ +#define FPU_RC_DOWN (0x0400) +#define FPU_RC_UP (0x0800) +#define FPU_RC_CHOP (0x0C00) + +#define FPU_CW_Precision (0x0020) /* loss of precision mask */ +#define FPU_CW_Underflow (0x0010) /* underflow mask */ +#define FPU_CW_Overflow (0x0008) /* overflow mask */ +#define FPU_CW_Zero_Div (0x0004) /* divide by zero mask */ +#define FPU_CW_Denormal (0x0002) /* denormalized operand mask */ +#define FPU_CW_Invalid (0x0001) /* invalid operation mask */ + +#define FPU_CW_Exceptions_Mask (0x003f) /* all masks */ + +/* Precision control bits affect only the following: + ADD, SUB(R), MUL, DIV(R), and SQRT */ +#define FPU_PR_32_BITS (0x000) +#define FPU_PR_RESERVED_BITS (0x100) +#define FPU_PR_64_BITS (0x200) +#define FPU_PR_80_BITS (0x300) + +#include "softfloat/softfloatx80.h" + +static __inline int +is_IA_masked(void) +{ + return (fpu_state.cwd & FPU_CW_Invalid); +} + +struct float_status_t i387cw_to_softfloat_status_word(uint16_t control_word); +uint16_t FPU_exception(uint32_t fetchdat, uint16_t exceptions, int store); +int FPU_status_word_flags_fpu_compare(int float_relation); +void FPU_write_eflags_fpu_compare(int float_relation); +void FPU_stack_overflow(uint32_t fetchdat); +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) +{ + return (fpu_state.cwd); +} + +static __inline uint16_t +i387_get_status_word(void) +{ + return (fpu_state.swd & ~FPU_SW_Top & 0xFFFF) | ((fpu_state.tos << 11) & FPU_SW_Top); +} + +#define IS_TAG_EMPTY(i) \ + (FPU_gettagi(i) == X87_TAG_EMPTY) + +static __inline int +FPU_gettagi(int stnr) +{ + return (fpu_state.tag >> (((stnr + fpu_state.tos) & 7) * 2)) & 3; +} + +static __inline void +FPU_settagi_valid(int stnr) +{ + int regnr = (stnr + fpu_state.tos) & 7; + fpu_state.tag &= ~(3 << (regnr * 2)); // FPU_Tag_Valid == '00 +} + +static __inline void +FPU_settagi(int tag, int stnr) +{ + int regnr = (stnr + fpu_state.tos) & 7; + fpu_state.tag &= ~(3 << (regnr * 2)); + fpu_state.tag |= (tag & 3) << (regnr * 2); +} + +static __inline void +FPU_push(void) +{ + fpu_state.tos = (fpu_state.tos - 1) & 7; +} + +static __inline void +FPU_pop(void) +{ + fpu_state.tag |= 3 << (fpu_state.tos * 2); + fpu_state.tos = (fpu_state.tos + 1) & 7; +} + +static __inline floatx80 +FPU_read_regi(int stnr) +{ + return fpu_state.st_space[(stnr + fpu_state.tos) & 7]; +} + +// it is only possible to read FPU tag word through certain +// instructions like FNSAVE, and they update tag word to its +// real value anyway +static __inline void +FPU_save_regi(floatx80 reg, int stnr) +{ + fpu_state.st_space[(stnr + fpu_state.tos) & 7] = reg; + FPU_settagi_valid(stnr); +} + +static __inline void +FPU_save_regi_tag(floatx80 reg, int tag, int stnr) +{ + fpu_state.st_space[(stnr + fpu_state.tos) & 7] = reg; + FPU_settagi(tag, stnr); +} + +#define FPU_check_pending_exceptions() \ + do { \ + if (fpu_state.swd & FPU_SW_Summary) { \ + if (cr0 & 0x20) { \ + x86_int(16); \ + return 1; \ + } else { \ + picint(1 << 13); \ + return 1; \ + } \ + } \ + } while (0) diff --git a/src/cpu/x87_ops.h b/src/cpu/x87_ops.h index 9e06a343e..1d9220255 100644 --- a/src/cpu/x87_ops.h +++ b/src/cpu/x87_ops.h @@ -1,608 +1,852 @@ /* - * 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. + * 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. + * This file is part of the 86Box distribution. * - * x87 FPU instructions core. + * x87 FPU instructions core. * - * Version: @(#)x87_ops.h 1.0.8 2019/06/11 * - * Authors: Fred N. van Kempen, - * Sarah Walker, - * leilei, - * Miran Grca, * - * Copyright 2008-2019 Sarah Walker. - * Copyright 2016-2019 leilei. - * Copyright 2016-2019 Miran Grca. - * Copyright 2018,2019 Fred N. van Kempen. + * Authors: Fred N. van Kempen, + * Sarah Walker, + * leilei, + * Miran Grca, + * + * Copyright 2008-2019 Sarah Walker. + * Copyright 2016-2019 leilei. + * Copyright 2016-2019 Miran Grca. + * Copyright 2018-2019 Fred N. van Kempen. */ #include #include #include "x87_timings.h" #ifdef _MSC_VER -# include +# include #endif +#include "x87_ops_conv.h" #ifdef ENABLE_FPU_LOG -extern void fpu_log(const char *fmt, ...); +extern void fpu_log(const char *fmt, ...); #else -#ifndef fpu_log -#define fpu_log(fmt, ...) -#endif +# ifndef fpu_log +# define fpu_log(fmt, ...) +# endif #endif -static int rounding_modes[4] = {FE_TONEAREST, FE_DOWNWARD, FE_UPWARD, FE_TOWARDZERO}; +static int rounding_modes[4] = { FE_TONEAREST, FE_DOWNWARD, FE_UPWARD, FE_TOWARDZERO }; -#define ST(x) cpu_state.ST[((cpu_state.TOP+(x))&7)] +#define ST(x) cpu_state.ST[((cpu_state.TOP + (x)) & 7)] -#define C0 (1<<8) -#define C1 (1<<9) -#define C2 (1<<10) -#define C3 (1<<14) +#define C0 (1 << 8) +#define C1 (1 << 9) +#define C2 (1 << 10) +#define C3 (1 << 14) + +#define X87_TAG_VALID 0 +#define X87_TAG_ZERO 1 +#define X87_TAG_INVALID 2 +#define X87_TAG_EMPTY 3 #define STATUS_ZERODIVIDE 4 +typedef union { + double d; + + struct { + uint64_t mantissa : 52; + uint64_t exponent : 11; + uint64_t negative : 1; + }; +} double_decompose_t; + #if defined(_MSC_VER) && !defined(__clang__) -# if defined i386 || defined __i386 || defined __i386__ || defined _X86_ || defined _M_IX86 -# define X87_INLINE_ASM -# endif +# if defined i386 || defined __i386 || defined __i386__ || defined _X86_ || defined _M_IX86 +# define X87_INLINE_ASM +# endif #else -# if defined i386 || defined __i386 || defined __i386__ || defined _X86_ || defined _M_IX86 || defined _M_X64 || defined __amd64__ -# define X87_INLINE_ASM -# endif +# if defined i386 || defined __i386 || defined __i386__ || defined _X86_ || defined _M_IX86 || defined _M_X64 || defined __amd64__ +# define X87_INLINE_ASM +# endif #endif #ifdef FPU_8087 -#define x87_div(dst, src1, src2) do \ - { \ - if (((double)src2) == 0.0) \ - { \ - cpu_state.npxs |= STATUS_ZERODIVIDE; \ - if (cpu_state.npxc & STATUS_ZERODIVIDE) \ - dst = src1 / (double)src2; \ - else \ - { \ - fpu_log("FPU : divide by zero\n"); \ - if (!(cpu_state.npxc & 0x80)) { \ - cpu_state.npxs |= 0x80; \ - nmi = 1; \ - } \ - return 1; \ - } \ - } \ - else \ - dst = src1 / (double)src2; \ +# define x87_div(dst, src1, src2) \ + do { \ + if (((double) src2) == 0.0) { \ + cpu_state.npxs |= STATUS_ZERODIVIDE; \ + if (cpu_state.npxc & STATUS_ZERODIVIDE) \ + dst = src1 / (double) src2; \ + else { \ + fpu_log("FPU : divide by zero\n"); \ + if (!(cpu_state.npxc & 0x80)) { \ + cpu_state.npxs |= 0x80; \ + nmi = 1; \ + } \ + return 1; \ + } \ + } else \ + dst = src1 / (double) src2; \ } while (0) #else -#define x87_div(dst, src1, src2) do \ - { \ - if (((double)src2) == 0.0) \ - { \ - cpu_state.npxs |= STATUS_ZERODIVIDE; \ - if (cpu_state.npxc & STATUS_ZERODIVIDE) \ - dst = src1 / (double)src2; \ - else \ - { \ - fpu_log("FPU : divide by zero\n"); \ - picint(1 << 13); \ - return 1; \ - } \ - } \ - else \ - dst = src1 / (double)src2; \ +# define x87_div(dst, src1, src2) \ + do { \ + if (((double) src2) == 0.0) { \ + cpu_state.npxs |= STATUS_ZERODIVIDE; \ + if (cpu_state.npxc & STATUS_ZERODIVIDE) \ + dst = src1 / (double) src2; \ + else { \ + fpu_log("FPU : divide by zero\n"); \ + picint(1 << 13); \ + return 1; \ + } \ + } else \ + dst = src1 / (double) src2; \ } while (0) #endif - -static __inline void x87_checkexceptions() + +static __inline void +x87_checkexceptions(void) { + // } -static __inline void x87_push(double i) +static __inline void +x87_push(double i) { #ifdef USE_NEW_DYNAREC - cpu_state.TOP--; + cpu_state.TOP--; #else - cpu_state.TOP=(cpu_state.TOP-1)&7; + cpu_state.TOP = (cpu_state.TOP - 1) & 7; #endif - cpu_state.ST[cpu_state.TOP&7] = i; + cpu_state.ST[cpu_state.TOP & 7] = i; #ifdef USE_NEW_DYNAREC - cpu_state.tag[cpu_state.TOP&7] = TAG_VALID; + cpu_state.tag[cpu_state.TOP & 7] = TAG_VALID; #else - cpu_state.tag[cpu_state.TOP&7] = (i == 0.0) ? TAG_VALID : 0; + cpu_state.tag[cpu_state.TOP & 7] = (i == 0.0) ? TAG_VALID : 0; #endif } -static __inline void x87_push_u64(uint64_t i) +static __inline void +x87_push_u64(uint64_t i) { - union - { - double d; - uint64_t ll; - } td; - - td.ll = i; + union { + double d; + uint64_t ll; + } td; + + td.ll = i; #ifdef USE_NEW_DYNAREC - cpu_state.TOP--; + cpu_state.TOP--; #else - cpu_state.TOP=(cpu_state.TOP-1)&7; + cpu_state.TOP = (cpu_state.TOP - 1) & 7; #endif - cpu_state.ST[cpu_state.TOP&7] = td.d; + cpu_state.ST[cpu_state.TOP & 7] = td.d; #ifdef USE_NEW_DYNAREC - cpu_state.tag[cpu_state.TOP&7] = TAG_VALID; + cpu_state.tag[cpu_state.TOP & 7] = TAG_VALID; #else - cpu_state.tag[cpu_state.TOP&7] = (td.d == 0.0) ? TAG_VALID : 0; + cpu_state.tag[cpu_state.TOP & 7] = (td.d == 0.0) ? TAG_VALID : 0; #endif } -static __inline double x87_pop() +static __inline double +x87_pop(void) { - double t = cpu_state.ST[cpu_state.TOP&7]; - cpu_state.tag[cpu_state.TOP&7] = TAG_EMPTY; + double t = cpu_state.ST[cpu_state.TOP & 7]; + cpu_state.tag[cpu_state.TOP & 7] = TAG_EMPTY; #ifdef USE_NEW_DYNAREC - cpu_state.TOP++; + cpu_state.TOP++; #else - cpu_state.tag[cpu_state.TOP&7] |= TAG_UINT64; - cpu_state.TOP=(cpu_state.TOP+1)&7; + cpu_state.tag[cpu_state.TOP & 7] |= TAG_UINT64; + cpu_state.TOP = (cpu_state.TOP + 1) & 7; #endif - return t; + return t; } -static __inline int16_t x87_fround16(double b) +static __inline int16_t +x87_fround16(double b) { - int16_t a, c; + double da; + double dc; + int16_t a; + int16_t c; - switch ((cpu_state.npxc >> 10) & 3) - { - case 0: /*Nearest*/ - a = (int16_t)floor(b); - c = (int16_t)floor(b + 1.0); - if ((b - a) < (c - b)) - return a; - else if ((b - a) > (c - b)) - return c; - else - return (a & 1) ? c : a; - case 1: /*Down*/ - return (int16_t)floor(b); - case 2: /*Up*/ - return (int16_t)ceil(b); - case 3: /*Chop*/ - return (int16_t)b; - } + switch ((cpu_state.npxc >> 10) & 3) { + case 0: /*Nearest*/ + da = floor(b); + dc = floor(b + 1.0); + a = (int16_t) da; + c = (int16_t) dc; + if ((b - a) < (c - b)) + return a; + else if ((b - a) > (c - b)) + return c; + else + return (a & 1) ? c : a; + case 1: /*Down*/ + da = floor(b); + return (int16_t) da; + case 2: /*Up*/ + da = ceil(b); + return (int16_t) da; + case 3: /*Chop*/ + return (int16_t) b; + } - return 0; + return 0; } -static __inline int64_t x87_fround16_64(double b) +static __inline int64_t +x87_fround16_64(double b) { return (int64_t) x87_fround16(b); } -static __inline int32_t x87_fround32(double b) +static __inline int32_t +x87_fround32(double b) { - int32_t a, c; + double da; + double dc; + int32_t a; + int32_t c; - switch ((cpu_state.npxc >> 10) & 3) - { - case 0: /*Nearest*/ - a = (int32_t)floor(b); - c = (int32_t)floor(b + 1.0); - if ((b - a) < (c - b)) - return a; - else if ((b - a) > (c - b)) - return c; - else - return (a & 1) ? c : a; - case 1: /*Down*/ - return (int32_t)floor(b); - case 2: /*Up*/ - return (int32_t)ceil(b); - case 3: /*Chop*/ - return (int32_t)b; - } + switch ((cpu_state.npxc >> 10) & 3) { + case 0: /*Nearest*/ + da = floor(b); + dc = floor(b + 1.0); + a = (int32_t) da; + c = (int32_t) dc; + if ((b - a) < (c - b)) + return a; + else if ((b - a) > (c - b)) + return c; + else + return (a & 1) ? c : a; + case 1: /*Down*/ + da = floor(b); + return (int32_t) da; + case 2: /*Up*/ + da = ceil(b); + return (int32_t) da; + case 3: /*Chop*/ + return (int32_t) b; + } - return 0; + return 0; } -static __inline int64_t x87_fround32_64(double b) +static __inline int64_t +x87_fround32_64(double b) { return (int64_t) x87_fround32(b); } -static __inline int64_t x87_fround(double b) +static __inline int64_t +x87_fround(double b) { - int64_t a, c; + double da; + double dc; + int64_t a; + int64_t c; - switch ((cpu_state.npxc >> 10) & 3) - { - case 0: /*Nearest*/ - a = (int64_t)floor(b); - c = (int64_t)floor(b + 1.0); - if ((b - a) < (c - b)) - return a; - else if ((b - a) > (c - b)) - return c; - else - return (a & 1) ? c : a; - case 1: /*Down*/ - return (int64_t)floor(b); - case 2: /*Up*/ - return (int64_t)ceil(b); - case 3: /*Chop*/ - return (int64_t)b; - } + switch ((cpu_state.npxc >> 10) & 3) { + case 0: /*Nearest*/ + da = floor(b); + dc = floor(b + 1.0); + a = (int64_t) da; + c = (int64_t) dc; + if ((b - a) < (c - b)) + return a; + else if ((b - a) > (c - b)) + return c; + else + return (a & 1) ? c : a; + case 1: /*Down*/ + da = floor(b); + return (int64_t) da; + case 2: /*Up*/ + da = ceil(b); + return (int64_t) da; + case 3: /*Chop*/ + return (int64_t) b; + } - return 0LL; -} -#define BIAS80 16383 -#define BIAS64 1023 - -static __inline double x87_ld80() -{ - int64_t exp64; - int64_t blah; - int64_t exp64final; - int64_t mant64; - int64_t sign; - struct { - int16_t begin; - union - { - double d; - uint64_t ll; - } eind; - } test; - test.eind.ll = readmeml(easeg,cpu_state.eaaddr); - test.eind.ll |= (uint64_t)readmeml(easeg,cpu_state.eaaddr+4)<<32; - test.begin = readmemw(easeg,cpu_state.eaaddr+8); - - exp64 = (((test.begin&0x7fff) - BIAS80)); - blah = ((exp64 >0)?exp64:-exp64)&0x3ff; - exp64final = ((exp64 >0)?blah:-blah) +BIAS64; - - mant64 = (test.eind.ll >> 11) & (0xfffffffffffffll); - sign = (test.begin&0x8000)?1:0; - - if ((test.begin & 0x7fff) == 0x7fff) - exp64final = 0x7ff; - if ((test.begin & 0x7fff) == 0) - exp64final = 0; - if (test.eind.ll & 0x400) - mant64++; - - test.eind.ll = (sign <<63)|(exp64final << 52)| mant64; - - return test.eind.d; + return 0LL; } -static __inline void x87_st80(double d) +static __inline double +x87_ld80(void) { - int64_t sign80; - int64_t exp80; - int64_t exp80final; - int64_t mant80; - int64_t mant80final; - - struct { - int16_t begin; - union - { - double d; - uint64_t ll; - } eind; - } test; - - test.eind.d=d; - - sign80 = (test.eind.ll&(0x8000000000000000ll))?1:0; - exp80 = test.eind.ll&(0x7ff0000000000000ll); - exp80final = (exp80>>52); - mant80 = test.eind.ll&(0x000fffffffffffffll); - mant80final = (mant80 << 11); - - if (exp80final == 0x7ff) /*Infinity / Nan*/ - { - exp80final = 0x7fff; - mant80final |= (0x8000000000000000ll); - } - else if (d != 0){ /* Zero is a special case */ - /* Elvira wants the 8 and tcalc doesn't */ - mant80final |= (0x8000000000000000ll); - /* Ca-cyber doesn't like this when result is zero. */ - exp80final += (BIAS80 - BIAS64); - } - test.begin = (((int16_t)sign80)<<15)| (int16_t)exp80final; - test.eind.ll = mant80final; - - writememl(easeg,cpu_state.eaaddr,test.eind.ll & 0xffffffff); - writememl(easeg,cpu_state.eaaddr+4,test.eind.ll>>32); - writememw(easeg,cpu_state.eaaddr+8,test.begin); + x87_conv_t test; + test.eind.ll = readmeml(easeg, cpu_state.eaaddr); + test.eind.ll |= (uint64_t) readmeml(easeg, cpu_state.eaaddr + 4) << 32; + test.begin = readmemw(easeg, cpu_state.eaaddr + 8); + return x87_from80(&test); } -static __inline void x87_st_fsave(int reg) +static __inline void +x87_st80(double d) { - reg = (cpu_state.TOP + reg) & 7; - - if (cpu_state.tag[reg] & TAG_UINT64) - { - writememl(easeg, cpu_state.eaaddr, cpu_state.MM[reg].q & 0xffffffff); - writememl(easeg, cpu_state.eaaddr + 4, cpu_state.MM[reg].q >> 32); - writememw(easeg, cpu_state.eaaddr + 8, 0x5555); - } - else - x87_st80(cpu_state.ST[reg]); + x87_conv_t test; + x87_to80(d, &test); + writememl(easeg, cpu_state.eaaddr, test.eind.ll & 0xffffffff); + writememl(easeg, cpu_state.eaaddr + 4, test.eind.ll >> 32); + writememw(easeg, cpu_state.eaaddr + 8, test.begin); } -static __inline void x87_ld_frstor(int reg) +static __inline void +x87_st_fsave(int reg) { - reg = (cpu_state.TOP + reg) & 7; - - cpu_state.MM[reg].q = readmemq(easeg, cpu_state.eaaddr); - cpu_state.MM_w4[reg] = readmemw(easeg, cpu_state.eaaddr + 8); + reg = (cpu_state.TOP + reg) & 7; + + if (cpu_state.tag[reg] & TAG_UINT64) { + writememl(easeg, cpu_state.eaaddr, cpu_state.MM[reg].q & 0xffffffff); + writememl(easeg, cpu_state.eaaddr + 4, cpu_state.MM[reg].q >> 32); + writememw(easeg, cpu_state.eaaddr + 8, 0x5555); + } else + x87_st80(cpu_state.ST[reg]); +} + +static __inline void +x87_ld_frstor(int reg) +{ + reg = (cpu_state.TOP + reg) & 7; + + cpu_state.MM[reg].q = readmemq(easeg, cpu_state.eaaddr); + cpu_state.MM_w4[reg] = readmemw(easeg, cpu_state.eaaddr + 8); #ifdef USE_NEW_DYNAREC - if ((cpu_state.MM_w4[reg] == 0x5555) && (cpu_state.tag[reg] & TAG_UINT64)) + if ((cpu_state.MM_w4[reg] == 0x5555) && (cpu_state.tag[reg] & TAG_UINT64)) #else - if ((cpu_state.MM_w4[reg] == 0x5555) && (cpu_state.tag[reg] == 2)) + if ((cpu_state.MM_w4[reg] == 0x5555) && (cpu_state.tag[reg] == 2)) #endif - { + { #ifndef USE_NEW_DYNAREC - cpu_state.tag[reg] = TAG_UINT64; + cpu_state.tag[reg] = TAG_UINT64; #endif - cpu_state.ST[reg] = (double)cpu_state.MM[reg].q; - } - else - { + cpu_state.ST[reg] = (double) cpu_state.MM[reg].q; + } else { #ifdef USE_NEW_DYNAREC - cpu_state.tag[reg] &= ~TAG_UINT64; + cpu_state.tag[reg] &= ~TAG_UINT64; #endif - cpu_state.ST[reg] = x87_ld80(); - } + cpu_state.ST[reg] = x87_ld80(); + } } -static __inline void x87_ldmmx(MMX_REG *r, uint16_t *w4) +static __inline void +x87_ldmmx(MMX_REG *r, uint16_t *w4) { - r->l[0] = readmeml(easeg, cpu_state.eaaddr); - r->l[1] = readmeml(easeg, cpu_state.eaaddr + 4); - *w4 = readmemw(easeg, cpu_state.eaaddr + 8); + r->l[0] = readmeml(easeg, cpu_state.eaaddr); + r->l[1] = readmeml(easeg, cpu_state.eaaddr + 4); + *w4 = readmemw(easeg, cpu_state.eaaddr + 8); } -static __inline void x87_stmmx(MMX_REG r) +static __inline void +x87_stmmx(MMX_REG r) { - writememl(easeg, cpu_state.eaaddr, r.l[0]); - writememl(easeg, cpu_state.eaaddr + 4, r.l[1]); - writememw(easeg, cpu_state.eaaddr + 8, 0xffff); + writememl(easeg, cpu_state.eaaddr, r.l[0]); + writememl(easeg, cpu_state.eaaddr + 4, r.l[1]); + writememw(easeg, cpu_state.eaaddr + 8, 0xffff); } #include -static __inline uint16_t x87_compare(double a, double b) +static __inline uint16_t +x87_compare(double a, double b) { #ifdef X87_INLINE_ASM - uint32_t result; - double ea = a, eb = b; - const uint64_t ia = 0x3fec1a6ff866a936ull; - const uint64_t ib = 0x3fec1a6ff866a938ull; + uint32_t result; + double ea = a; + double eb = b; + const uint64_t ia = 0x3fec1a6ff866a936ULL; + const uint64_t ib = 0x3fec1a6ff866a938ULL; - /* Hack to make CHKCOP happy. */ - if (!memcmp(&ea, &ia, 8) && !memcmp(&eb, &ib, 8)) - return C3; + /* Hack to make CHKCOP happy. */ + if (!memcmp(&ea, &ia, 8) && !memcmp(&eb, &ib, 8)) + return C3; - if ((fpu_type < FPU_287XL) && !(cpu_state.npxc & 0x1000) && - ((a == INFINITY) || (a == -INFINITY)) && ((b == INFINITY) || (b == -INFINITY))) - eb = ea; + if ((fpu_type < FPU_287XL) && !(cpu_state.npxc & 0x1000) && ((a == INFINITY) || (a == -INFINITY)) && ((b == INFINITY) || (b == -INFINITY))) + eb = ea; -#if !defined(_MSC_VER) || defined(__clang__) - /* Memory barrier, to force GCC to write to the input parameters - * before the compare rather than after */ - __asm volatile ("" : : : "memory"); - - __asm( - "fldl %2\n" - "fldl %1\n" - "fclex\n" - "fcompp\n" - "fnstsw %0\n" - : "=m" (result) - : "m" (ea), "m" (eb) - ); -#else - _ReadWriteBarrier(); - _asm - { +# if !defined(_MSC_VER) || defined(__clang__) + /* Memory barrier, to force GCC to write to the input parameters + * before the compare rather than after */ + __asm volatile("" + : + : + : "memory"); + + __asm( + "fldl %2\n" + "fldl %1\n" + "fclex\n" + "fcompp\n" + "fnstsw %0\n" + : "=m"(result) + : "m"(ea), "m"(eb)); +# else + _ReadWriteBarrier(); + _asm + { fld eb fld ea fclex fcompp fnstsw result - } -#endif + } +# endif - return result & (C0|C2|C3); + return result & (C0 | C2 | C3); #else - /* Generic C version is known to give incorrect results in some - * situations, eg comparison of infinity (Unreal) */ - uint32_t result = 0; - double ea = a, eb = b; + /* Generic C version is known to give incorrect results in some + * situations, eg comparison of infinity (Unreal) */ + uint32_t result = 0; + double ea = a, eb = b; - if ((fpu_type < FPU_287XL) && !(cpu_state.npxc & 0x1000) && - ((a == INFINITY) || (a == -INFINITY)) && ((b == INFINITY) || (b == -INFINITY))) - eb = ea; + if ((fpu_type < FPU_287XL) && !(cpu_state.npxc & 0x1000) && ((a == INFINITY) || (a == -INFINITY)) && ((b == INFINITY) || (b == -INFINITY))) + eb = ea; - if (ea == eb) - result |= C3; - else if (ea < eb) - result |= C0; - - return result; + if (ea == eb) + result |= C3; + else if (ea < eb) + result |= C0; + + return result; #endif } -static __inline uint16_t x87_ucompare(double a, double b) +static __inline uint16_t +x87_ucompare(double a, double b) { #ifdef X87_INLINE_ASM - uint32_t result; - -#if !defined(_MSC_VER) || defined(__clang__) - /* Memory barrier, to force GCC to write to the input parameters - * before the compare rather than after */ - asm volatile ("" : : : "memory"); - - asm( - "fldl %2\n" - "fldl %1\n" - "fclex\n" - "fucompp\n" - "fnstsw %0\n" - : "=m" (result) - : "m" (a), "m" (b) - ); -#else - _ReadWriteBarrier(); - _asm - { + uint32_t result; + +# if !defined(_MSC_VER) || defined(__clang__) + /* Memory barrier, to force GCC to write to the input parameters + * before the compare rather than after */ + __asm volatile("" + : + : + : "memory"); + + __asm( + "fldl %2\n" + "fldl %1\n" + "fclex\n" + "fucompp\n" + "fnstsw %0\n" + : "=m"(result) + : "m"(a), "m"(b)); +# else + _ReadWriteBarrier(); + _asm + { fld b fld a fclex fcompp fnstsw result - } -#endif + } +# endif - return result & (C0|C2|C3); + return result & (C0 | C2 | C3); #else - /* Generic C version is known to give incorrect results in some - * situations, eg comparison of infinity (Unreal) */ - uint32_t result = 0; - - if (a == b) - result |= C3; - else if (a < b) - result |= C0; - - return result; + /* Generic C version is known to give incorrect results in some + * situations, eg comparison of infinity (Unreal) */ + uint32_t result = 0; + + if (a == b) + result |= C3; + else if (a < b) + result |= C0; + + return result; #endif } -typedef union -{ - float s; - uint32_t i; +typedef union { + float s; + uint32_t i; } x87_ts; -typedef union -{ - double d; - uint64_t i; +typedef union { + double d; + uint64_t i; } x87_td; #ifdef FPU_8087 -#define FP_ENTER() { \ - } +# define FP_ENTER() \ + { \ + } #else -#define FP_ENTER() do \ - { \ - if (cr0 & 0xc) \ - { \ - x86_int(7); \ - return 1; \ - } \ +# define FP_ENTER() \ + do { \ + if (cr0 & 0xc) { \ + x86_int(7); \ + return 1; \ + } \ } while (0) #endif #ifdef USE_NEW_DYNAREC -# define FP_TAG_VALID cpu_state.tag[cpu_state.TOP&7] = TAG_VALID -# define FP_TAG_VALID_F cpu_state.tag[(cpu_state.TOP + fetchdat) & 7] = TAG_VALID -# define FP_TAG_DEFAULT cpu_state.tag[cpu_state.TOP&7] = TAG_VALID | TAG_UINT64 -# define FP_TAG_VALID_N cpu_state.tag[(cpu_state.TOP + 1) & 7] = TAG_VALID +# define FP_TAG_VALID cpu_state.tag[cpu_state.TOP & 7] = TAG_VALID +# define FP_TAG_VALID_F cpu_state.tag[(cpu_state.TOP + fetchdat) & 7] = TAG_VALID +# define FP_TAG_DEFAULT cpu_state.tag[cpu_state.TOP & 7] = TAG_VALID | TAG_UINT64 +# define FP_TAG_VALID_N cpu_state.tag[(cpu_state.TOP + 1) & 7] = TAG_VALID #else -# define FP_TAG_VALID cpu_state.tag[cpu_state.TOP] &= ~TAG_UINT64 -# define FP_TAG_VALID_F cpu_state.tag[(cpu_state.TOP + fetchdat) & 7] &= ~TAG_UINT64 -# define FP_TAG_DEFAULT cpu_state.tag[cpu_state.TOP] |= TAG_UINT64; -# define FP_TAG_VALID_N cpu_state.tag[(cpu_state.TOP + 1) & 7] &= ~TAG_UINT64 +# define FP_TAG_VALID cpu_state.tag[cpu_state.TOP] &= ~TAG_UINT64 +# define FP_TAG_VALID_F cpu_state.tag[(cpu_state.TOP + fetchdat) & 7] &= ~TAG_UINT64 +# define FP_TAG_DEFAULT cpu_state.tag[cpu_state.TOP] |= TAG_UINT64; +# define FP_TAG_VALID_N cpu_state.tag[(cpu_state.TOP + 1) & 7] &= ~TAG_UINT64 #endif +#include "softfloat/softfloat-specialize.h" + +#include "x87_ops_sf_arith.h" +#include "x87_ops_sf_compare.h" +#include "x87_ops_sf_const.h" +#include "x87_ops_sf_load_store.h" +#include "x87_ops_sf_misc.h" +#include "x87_ops_sf_trans.h" +#include "x87_ops_sf.h" + #include "x87_ops_arith.h" #include "x87_ops_misc.h" #include "x87_ops_loadstore.h" #ifndef FPU_8087 -static int op_nofpu_a16(uint32_t fetchdat) +static int +op_nofpu_a16(uint32_t fetchdat) { - if (cr0 & 0xc) - { - x86_int(7); - return 1; - } - else - { - fetch_ea_16(fetchdat); - return 0; - } + if (cr0 & 0xc) { + x86_int(7); + return 1; + } else { + fetch_ea_16(fetchdat); + return 0; + } } -static int op_nofpu_a32(uint32_t fetchdat) +static int +op_nofpu_a32(uint32_t fetchdat) { - if (cr0 & 0xc) - { - x86_int(7); - return 1; - } - else - { - fetch_ea_32(fetchdat); - return 0; - } + if (cr0 & 0xc) { + x86_int(7); + return 1; + } else { + fetch_ea_32(fetchdat); + return 0; + } } #endif #ifdef FPU_8087 -static int FPU_ILLEGAL_a16(uint32_t fetchdat) +static int +FPU_ILLEGAL_a16(uint32_t fetchdat) { - geteaw(); - wait(timing_rr, 0); - return 0; + geteaw(); + wait(timing_rr, 0); + return 0; } #else -static int FPU_ILLEGAL_a16(uint32_t fetchdat) +static int +FPU_ILLEGAL_a16(uint32_t fetchdat) { - fetch_ea_16(fetchdat); - CLOCK_CYCLES(timing_rr); - PREFETCH_RUN(timing_rr, 2, rmdat, 0,0,0,0, 0); - return 0; + fetch_ea_16(fetchdat); + CLOCK_CYCLES(timing_rr); + PREFETCH_RUN(timing_rr, 2, rmdat, 0, 0, 0, 0, 0); + return 0; } -static int FPU_ILLEGAL_a32(uint32_t fetchdat) +static int +FPU_ILLEGAL_a32(uint32_t fetchdat) { - fetch_ea_32(fetchdat); - CLOCK_CYCLES(timing_rr); - PREFETCH_RUN(timing_rr, 2, rmdat, 0,0,0,0, 0); - return 0; + fetch_ea_32(fetchdat); + CLOCK_CYCLES(timing_rr); + PREFETCH_RUN(timing_rr, 2, rmdat, 0, 0, 0, 0, 0); + return 0; } #endif #define ILLEGAL_a16 FPU_ILLEGAL_a16 #ifdef FPU_8087 -const OpFn OP_TABLE(fpu_8087_d8)[32] = -{ +const OpFn OP_TABLE(sf_fpu_8087_d8)[32] = { + // clang-format off + sf_FADDs_a16, sf_FMULs_a16, sf_FCOMs_a16, sf_FCOMPs_a16, sf_FSUBs_a16, sf_FSUBRs_a16, sf_FDIVs_a16, sf_FDIVRs_a16, + sf_FADDs_a16, sf_FMULs_a16, sf_FCOMs_a16, sf_FCOMPs_a16, sf_FSUBs_a16, sf_FSUBRs_a16, sf_FDIVs_a16, sf_FDIVRs_a16, + sf_FADDs_a16, sf_FMULs_a16, sf_FCOMs_a16, sf_FCOMPs_a16, sf_FSUBs_a16, sf_FSUBRs_a16, sf_FDIVs_a16, sf_FDIVRs_a16, + sf_FADD_st0_stj, sf_FMUL_st0_stj, sf_FCOM_sti, sf_FCOMP_sti, sf_FSUB_st0_stj, sf_FSUBR_st0_stj, sf_FDIV_st0_stj, sf_FDIVR_st0_stj, + // clang-format on +}; + +const OpFn OP_TABLE(sf_fpu_8087_d9)[256] = { + // clang-format off + sf_FLDs_a16, sf_FLDs_a16, sf_FLDs_a16, sf_FLDs_a16, sf_FLDs_a16, sf_FLDs_a16, sf_FLDs_a16, sf_FLDs_a16, + ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, + sf_FSTs_a16, sf_FSTs_a16, sf_FSTs_a16, sf_FSTs_a16, sf_FSTs_a16, sf_FSTs_a16, sf_FSTs_a16, sf_FSTs_a16, + sf_FSTPs_a16, sf_FSTPs_a16, sf_FSTPs_a16, sf_FSTPs_a16, sf_FSTPs_a16, sf_FSTPs_a16, sf_FSTPs_a16, sf_FSTPs_a16, + sf_FLDENV_a16, sf_FLDENV_a16, sf_FLDENV_a16, sf_FLDENV_a16, sf_FLDENV_a16, sf_FLDENV_a16, sf_FLDENV_a16, sf_FLDENV_a16, + sf_FLDCW_a16, sf_FLDCW_a16, sf_FLDCW_a16, sf_FLDCW_a16, sf_FLDCW_a16, sf_FLDCW_a16, sf_FLDCW_a16, sf_FLDCW_a16, + sf_FNSTENV_a16, sf_FNSTENV_a16, sf_FNSTENV_a16, sf_FNSTENV_a16, sf_FNSTENV_a16, sf_FNSTENV_a16, sf_FNSTENV_a16, sf_FNSTENV_a16, + sf_FNSTCW_a16, sf_FNSTCW_a16, sf_FNSTCW_a16, sf_FNSTCW_a16, sf_FNSTCW_a16, sf_FNSTCW_a16, sf_FNSTCW_a16, sf_FNSTCW_a16, + + sf_FLDs_a16, sf_FLDs_a16, sf_FLDs_a16, sf_FLDs_a16, sf_FLDs_a16, sf_FLDs_a16, sf_FLDs_a16, sf_FLDs_a16, + ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, + sf_FSTs_a16, sf_FSTs_a16, sf_FSTs_a16, sf_FSTs_a16, sf_FSTs_a16, sf_FSTs_a16, sf_FSTs_a16, sf_FSTs_a16, + sf_FSTPs_a16, sf_FSTPs_a16, sf_FSTPs_a16, sf_FSTPs_a16, sf_FSTPs_a16, sf_FSTPs_a16, sf_FSTPs_a16, sf_FSTPs_a16, + sf_FLDENV_a16, sf_FLDENV_a16, sf_FLDENV_a16, sf_FLDENV_a16, sf_FLDENV_a16, sf_FLDENV_a16, sf_FLDENV_a16, sf_FLDENV_a16, + sf_FLDCW_a16, sf_FLDCW_a16, sf_FLDCW_a16, sf_FLDCW_a16, sf_FLDCW_a16, sf_FLDCW_a16, sf_FLDCW_a16, sf_FLDCW_a16, + sf_FNSTENV_a16, sf_FNSTENV_a16, sf_FNSTENV_a16, sf_FNSTENV_a16, sf_FNSTENV_a16, sf_FNSTENV_a16, sf_FNSTENV_a16, sf_FNSTENV_a16, + sf_FNSTCW_a16, sf_FNSTCW_a16, sf_FNSTCW_a16, sf_FNSTCW_a16, sf_FNSTCW_a16, sf_FNSTCW_a16, sf_FNSTCW_a16, sf_FNSTCW_a16, + + sf_FLDs_a16, sf_FLDs_a16, sf_FLDs_a16, sf_FLDs_a16, sf_FLDs_a16, sf_FLDs_a16, sf_FLDs_a16, sf_FLDs_a16, + ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, + sf_FSTs_a16, sf_FSTs_a16, sf_FSTs_a16, sf_FSTs_a16, sf_FSTs_a16, sf_FSTs_a16, sf_FSTs_a16, sf_FSTs_a16, + sf_FSTPs_a16, sf_FSTPs_a16, sf_FSTPs_a16, sf_FSTPs_a16, sf_FSTPs_a16, sf_FSTPs_a16, sf_FSTPs_a16, sf_FSTPs_a16, + sf_FLDENV_a16, sf_FLDENV_a16, sf_FLDENV_a16, sf_FLDENV_a16, sf_FLDENV_a16, sf_FLDENV_a16, sf_FLDENV_a16, sf_FLDENV_a16, + sf_FLDCW_a16, sf_FLDCW_a16, sf_FLDCW_a16, sf_FLDCW_a16, sf_FLDCW_a16, sf_FLDCW_a16, sf_FLDCW_a16, sf_FLDCW_a16, + sf_FNSTENV_a16, sf_FNSTENV_a16, sf_FNSTENV_a16, sf_FNSTENV_a16, sf_FNSTENV_a16, sf_FNSTENV_a16, sf_FNSTENV_a16, sf_FNSTENV_a16, + sf_FNSTCW_a16, sf_FNSTCW_a16, sf_FNSTCW_a16, sf_FNSTCW_a16, sf_FNSTCW_a16, sf_FNSTCW_a16, sf_FNSTCW_a16, sf_FNSTCW_a16, + + sf_FLD_sti, sf_FLD_sti, sf_FLD_sti, sf_FLD_sti, sf_FLD_sti, sf_FLD_sti, sf_FLD_sti, sf_FLD_sti, + sf_FXCH_sti, sf_FXCH_sti, sf_FXCH_sti, sf_FXCH_sti, sf_FXCH_sti, sf_FXCH_sti, sf_FXCH_sti, sf_FXCH_sti, + sf_FNOP, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, + ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, /*Invalid*/ + sf_FCHS, sf_FABS, ILLEGAL_a16, ILLEGAL_a16, sf_FTST, sf_FXAM, ILLEGAL_a16, ILLEGAL_a16, + sf_FLD1, sf_FLDL2T, sf_FLDL2E, sf_FLDPI, sf_FLDEG2, sf_FLDLN2, sf_FLDZ, ILLEGAL_a16, + sf_F2XM1, sf_FYL2X, sf_FPTAN, sf_FPATAN, sf_FXTRACT, sf_FPREM1, sf_FDECSTP, sf_FINCSTP, + sf_FPREM, sf_FYL2XP1, sf_FSQRT, ILLEGAL_a16, sf_FRNDINT, sf_FSCALE, ILLEGAL_a16, ILLEGAL_a16 + // clang-format on +}; + +const OpFn OP_TABLE(sf_fpu_8087_da)[256] = { + // clang-format off + sf_FADDil_a16, sf_FADDil_a16, sf_FADDil_a16, sf_FADDil_a16, sf_FADDil_a16, sf_FADDil_a16, sf_FADDil_a16, sf_FADDil_a16, + sf_FMULil_a16, sf_FMULil_a16, sf_FMULil_a16, sf_FMULil_a16, sf_FMULil_a16, sf_FMULil_a16, sf_FMULil_a16, sf_FMULil_a16, + sf_FCOMil_a16, sf_FCOMil_a16, sf_FCOMil_a16, sf_FCOMil_a16, sf_FCOMil_a16, sf_FCOMil_a16, sf_FCOMil_a16, sf_FCOMil_a16, + sf_FCOMPil_a16, sf_FCOMPil_a16, sf_FCOMPil_a16, sf_FCOMPil_a16, sf_FCOMPil_a16, sf_FCOMPil_a16, sf_FCOMPil_a16, sf_FCOMPil_a16, + sf_FSUBil_a16, sf_FSUBil_a16, sf_FSUBil_a16, sf_FSUBil_a16, sf_FSUBil_a16, sf_FSUBil_a16, sf_FSUBil_a16, sf_FSUBil_a16, + sf_FSUBRil_a16, sf_FSUBRil_a16, sf_FSUBRil_a16, sf_FSUBRil_a16, sf_FSUBRil_a16, sf_FSUBRil_a16, sf_FSUBRil_a16, sf_FSUBRil_a16, + sf_FDIVil_a16, sf_FDIVil_a16, sf_FDIVil_a16, sf_FDIVil_a16, sf_FDIVil_a16, sf_FDIVil_a16, sf_FDIVil_a16, sf_FDIVil_a16, + sf_FDIVRil_a16, sf_FDIVRil_a16, sf_FDIVRil_a16, sf_FDIVRil_a16, sf_FDIVRil_a16, sf_FDIVRil_a16, sf_FDIVRil_a16, sf_FDIVRil_a16, + + sf_FADDil_a16, sf_FADDil_a16, sf_FADDil_a16, sf_FADDil_a16, sf_FADDil_a16, sf_FADDil_a16, sf_FADDil_a16, sf_FADDil_a16, + sf_FMULil_a16, sf_FMULil_a16, sf_FMULil_a16, sf_FMULil_a16, sf_FMULil_a16, sf_FMULil_a16, sf_FMULil_a16, sf_FMULil_a16, + sf_FCOMil_a16, sf_FCOMil_a16, sf_FCOMil_a16, sf_FCOMil_a16, sf_FCOMil_a16, sf_FCOMil_a16, sf_FCOMil_a16, sf_FCOMil_a16, + sf_FCOMPil_a16, sf_FCOMPil_a16, sf_FCOMPil_a16, sf_FCOMPil_a16, sf_FCOMPil_a16, sf_FCOMPil_a16, sf_FCOMPil_a16, sf_FCOMPil_a16, + sf_FSUBil_a16, sf_FSUBil_a16, sf_FSUBil_a16, sf_FSUBil_a16, sf_FSUBil_a16, sf_FSUBil_a16, sf_FSUBil_a16, sf_FSUBil_a16, + sf_FSUBRil_a16, sf_FSUBRil_a16, sf_FSUBRil_a16, sf_FSUBRil_a16, sf_FSUBRil_a16, sf_FSUBRil_a16, sf_FSUBRil_a16, sf_FSUBRil_a16, + sf_FDIVil_a16, sf_FDIVil_a16, sf_FDIVil_a16, sf_FDIVil_a16, sf_FDIVil_a16, sf_FDIVil_a16, sf_FDIVil_a16, sf_FDIVil_a16, + sf_FDIVRil_a16, sf_FDIVRil_a16, sf_FDIVRil_a16, sf_FDIVRil_a16, sf_FDIVRil_a16, sf_FDIVRil_a16, sf_FDIVRil_a16, sf_FDIVRil_a16, + + sf_FADDil_a16, sf_FADDil_a16, sf_FADDil_a16, sf_FADDil_a16, sf_FADDil_a16, sf_FADDil_a16, sf_FADDil_a16, sf_FADDil_a16, + sf_FMULil_a16, sf_FMULil_a16, sf_FMULil_a16, sf_FMULil_a16, sf_FMULil_a16, sf_FMULil_a16, sf_FMULil_a16, sf_FMULil_a16, + sf_FCOMil_a16, sf_FCOMil_a16, sf_FCOMil_a16, sf_FCOMil_a16, sf_FCOMil_a16, sf_FCOMil_a16, sf_FCOMil_a16, sf_FCOMil_a16, + sf_FCOMPil_a16, sf_FCOMPil_a16, sf_FCOMPil_a16, sf_FCOMPil_a16, sf_FCOMPil_a16, sf_FCOMPil_a16, sf_FCOMPil_a16, sf_FCOMPil_a16, + sf_FSUBil_a16, sf_FSUBil_a16, sf_FSUBil_a16, sf_FSUBil_a16, sf_FSUBil_a16, sf_FSUBil_a16, sf_FSUBil_a16, sf_FSUBil_a16, + sf_FSUBRil_a16, sf_FSUBRil_a16, sf_FSUBRil_a16, sf_FSUBRil_a16, sf_FSUBRil_a16, sf_FSUBRil_a16, sf_FSUBRil_a16, sf_FSUBRil_a16, + sf_FDIVil_a16, sf_FDIVil_a16, sf_FDIVil_a16, sf_FDIVil_a16, sf_FDIVil_a16, sf_FDIVil_a16, sf_FDIVil_a16, sf_FDIVil_a16, + sf_FDIVRil_a16, sf_FDIVRil_a16, sf_FDIVRil_a16, sf_FDIVRil_a16, sf_FDIVRil_a16, sf_FDIVRil_a16, sf_FDIVRil_a16, sf_FDIVRil_a16, + + ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, + ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, + ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, + ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, + ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, + ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, + ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, + ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, + // clang-format on +}; + +const OpFn OP_TABLE(sf_fpu_8087_db)[256] = { + // clang-format off + sf_FILDil_a16, sf_FILDil_a16, sf_FILDil_a16, sf_FILDil_a16, sf_FILDil_a16, sf_FILDil_a16, sf_FILDil_a16, sf_FILDil_a16, + ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, + sf_FISTil_a16, sf_FISTil_a16, sf_FISTil_a16, sf_FISTil_a16, sf_FISTil_a16, sf_FISTil_a16, sf_FISTil_a16, sf_FISTil_a16, + sf_FISTPil_a16, sf_FISTPil_a16, sf_FISTPil_a16, sf_FISTPil_a16, sf_FISTPil_a16, sf_FISTPil_a16, sf_FISTPil_a16, sf_FISTPil_a16, + ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, + sf_FLDe_a16, sf_FLDe_a16, sf_FLDe_a16, sf_FLDe_a16, sf_FLDe_a16, sf_FLDe_a16, sf_FLDe_a16, sf_FLDe_a16, + ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, + sf_FSTPe_a16, sf_FSTPe_a16, sf_FSTPe_a16, sf_FSTPe_a16, sf_FSTPe_a16, sf_FSTPe_a16, sf_FSTPe_a16, sf_FSTPe_a16, + + sf_FILDil_a16, sf_FILDil_a16, sf_FILDil_a16, sf_FILDil_a16, sf_FILDil_a16, sf_FILDil_a16, sf_FILDil_a16, sf_FILDil_a16, + ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, + sf_FISTil_a16, sf_FISTil_a16, sf_FISTil_a16, sf_FISTil_a16, sf_FISTil_a16, sf_FISTil_a16, sf_FISTil_a16, sf_FISTil_a16, + sf_FISTPil_a16, sf_FISTPil_a16, sf_FISTPil_a16, sf_FISTPil_a16, sf_FISTPil_a16, sf_FISTPil_a16, sf_FISTPil_a16, sf_FISTPil_a16, + ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, + sf_FLDe_a16, sf_FLDe_a16, sf_FLDe_a16, sf_FLDe_a16, sf_FLDe_a16, sf_FLDe_a16, sf_FLDe_a16, sf_FLDe_a16, + ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, + sf_FSTPe_a16, sf_FSTPe_a16, sf_FSTPe_a16, sf_FSTPe_a16, sf_FSTPe_a16, sf_FSTPe_a16, sf_FSTPe_a16, sf_FSTPe_a16, + + sf_FILDil_a16, sf_FILDil_a16, sf_FILDil_a16, sf_FILDil_a16, sf_FILDil_a16, sf_FILDil_a16, sf_FILDil_a16, sf_FILDil_a16, + ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, + sf_FISTil_a16, sf_FISTil_a16, sf_FISTil_a16, sf_FISTil_a16, sf_FISTil_a16, sf_FISTil_a16, sf_FISTil_a16, sf_FISTil_a16, + sf_FISTPil_a16, sf_FISTPil_a16, sf_FISTPil_a16, sf_FISTPil_a16, sf_FISTPil_a16, sf_FISTPil_a16, sf_FISTPil_a16, sf_FISTPil_a16, + ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, + sf_FLDe_a16, sf_FLDe_a16, sf_FLDe_a16, sf_FLDe_a16, sf_FLDe_a16, sf_FLDe_a16, sf_FLDe_a16, sf_FLDe_a16, + ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, + sf_FSTPe_a16, sf_FSTPe_a16, sf_FSTPe_a16, sf_FSTPe_a16, sf_FSTPe_a16, sf_FSTPe_a16, sf_FSTPe_a16, sf_FSTPe_a16, + + ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, + ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, + ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, + ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, + sf_FI, sf_FI, sf_FNCLEX, sf_FNINIT, ILLEGAL_a16, sf_FNOP, ILLEGAL_a16, ILLEGAL_a16, + ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, + ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, + ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, + // clang-format on +}; + +const OpFn OP_TABLE(sf_fpu_8087_dc)[32] = { + // clang-format off + sf_FADDd_a16, sf_FMULd_a16, sf_FCOMd_a16, sf_FCOMPd_a16, sf_FSUBd_a16, sf_FSUBRd_a16, sf_FDIVd_a16, sf_FDIVRd_a16, + sf_FADDd_a16, sf_FMULd_a16, sf_FCOMd_a16, sf_FCOMPd_a16, sf_FSUBd_a16, sf_FSUBRd_a16, sf_FDIVd_a16, sf_FDIVRd_a16, + sf_FADDd_a16, sf_FMULd_a16, sf_FCOMd_a16, sf_FCOMPd_a16, sf_FSUBd_a16, sf_FSUBRd_a16, sf_FDIVd_a16, sf_FDIVRd_a16, + sf_FADD_sti_st0, sf_FMUL_sti_st0, ILLEGAL_a16, ILLEGAL_a16, sf_FSUBR_sti_st0, sf_FSUB_sti_st0, sf_FDIVR_sti_st0, sf_FDIV_sti_st0, + // clang-format on +}; + +const OpFn OP_TABLE(sf_fpu_8087_dd)[256] = { + // clang-format off + sf_FLDd_a16, sf_FLDd_a16, sf_FLDd_a16, sf_FLDd_a16, sf_FLDd_a16, sf_FLDd_a16, sf_FLDd_a16, sf_FLDd_a16, + ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, + sf_FSTd_a16, sf_FSTd_a16, sf_FSTd_a16, sf_FSTd_a16, sf_FSTd_a16, sf_FSTd_a16, sf_FSTd_a16, sf_FSTd_a16, + sf_FSTPd_a16, sf_FSTPd_a16, sf_FSTPd_a16, sf_FSTPd_a16, sf_FSTPd_a16, sf_FSTPd_a16, sf_FSTPd_a16, sf_FSTPd_a16, + sf_FRSTOR_a16, sf_FRSTOR_a16, sf_FRSTOR_a16, sf_FRSTOR_a16, sf_FRSTOR_a16, sf_FRSTOR_a16, sf_FRSTOR_a16, sf_FRSTOR_a16, + ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, + sf_FNSAVE_a16, sf_FNSAVE_a16, sf_FNSAVE_a16, sf_FNSAVE_a16, sf_FNSAVE_a16, sf_FNSAVE_a16, sf_FNSAVE_a16, sf_FNSAVE_a16, + sf_FNSTSW_a16, sf_FNSTSW_a16, sf_FNSTSW_a16, sf_FNSTSW_a16, sf_FNSTSW_a16, sf_FNSTSW_a16, sf_FNSTSW_a16, sf_FNSTSW_a16, + + sf_FLDd_a16, sf_FLDd_a16, sf_FLDd_a16, sf_FLDd_a16, sf_FLDd_a16, sf_FLDd_a16, sf_FLDd_a16, sf_FLDd_a16, + ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, + sf_FSTd_a16, sf_FSTd_a16, sf_FSTd_a16, sf_FSTd_a16, sf_FSTd_a16, sf_FSTd_a16, sf_FSTd_a16, sf_FSTd_a16, + sf_FSTPd_a16, sf_FSTPd_a16, sf_FSTPd_a16, sf_FSTPd_a16, sf_FSTPd_a16, sf_FSTPd_a16, sf_FSTPd_a16, sf_FSTPd_a16, + sf_FRSTOR_a16, sf_FRSTOR_a16, sf_FRSTOR_a16, sf_FRSTOR_a16, sf_FRSTOR_a16, sf_FRSTOR_a16, sf_FRSTOR_a16, sf_FRSTOR_a16, + ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, + sf_FNSAVE_a16, sf_FNSAVE_a16, sf_FNSAVE_a16, sf_FNSAVE_a16, sf_FNSAVE_a16, sf_FNSAVE_a16, sf_FNSAVE_a16, sf_FNSAVE_a16, + sf_FNSTSW_a16, sf_FNSTSW_a16, sf_FNSTSW_a16, sf_FNSTSW_a16, sf_FNSTSW_a16, sf_FNSTSW_a16, sf_FNSTSW_a16, sf_FNSTSW_a16, + + sf_FLDd_a16, sf_FLDd_a16, sf_FLDd_a16, sf_FLDd_a16, sf_FLDd_a16, sf_FLDd_a16, sf_FLDd_a16, sf_FLDd_a16, + ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, + sf_FSTd_a16, sf_FSTd_a16, sf_FSTd_a16, sf_FSTd_a16, sf_FSTd_a16, sf_FSTd_a16, sf_FSTd_a16, sf_FSTd_a16, + sf_FSTPd_a16, sf_FSTPd_a16, sf_FSTPd_a16, sf_FSTPd_a16, sf_FSTPd_a16, sf_FSTPd_a16, sf_FSTPd_a16, sf_FSTPd_a16, + sf_FRSTOR_a16, sf_FRSTOR_a16, sf_FRSTOR_a16, sf_FRSTOR_a16, sf_FRSTOR_a16, sf_FRSTOR_a16, sf_FRSTOR_a16, sf_FRSTOR_a16, + ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, + sf_FNSAVE_a16, sf_FNSAVE_a16, sf_FNSAVE_a16, sf_FNSAVE_a16, sf_FNSAVE_a16, sf_FNSAVE_a16, sf_FNSAVE_a16, sf_FNSAVE_a16, + sf_FNSTSW_a16, sf_FNSTSW_a16, sf_FNSTSW_a16, sf_FNSTSW_a16, sf_FNSTSW_a16, sf_FNSTSW_a16, sf_FNSTSW_a16, sf_FNSTSW_a16, + + sf_FFREE_sti, sf_FFREE_sti, sf_FFREE_sti, sf_FFREE_sti, sf_FFREE_sti, sf_FFREE_sti, sf_FFREE_sti, sf_FFREE_sti, + ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, + sf_FST_sti, sf_FST_sti, sf_FST_sti, sf_FST_sti, sf_FST_sti, sf_FST_sti, sf_FST_sti, sf_FST_sti, + sf_FSTP_sti, sf_FSTP_sti, sf_FSTP_sti, sf_FSTP_sti, sf_FSTP_sti, sf_FSTP_sti, sf_FSTP_sti, sf_FSTP_sti, + ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, + ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, + ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, + ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, + // clang-format on +}; + +const OpFn OP_TABLE(sf_fpu_8087_de)[256] = { + // clang-format off + sf_FADDiw_a16, sf_FADDiw_a16, sf_FADDiw_a16, sf_FADDiw_a16, sf_FADDiw_a16, sf_FADDiw_a16, sf_FADDiw_a16, sf_FADDiw_a16, + sf_FMULiw_a16, sf_FMULiw_a16, sf_FMULiw_a16, sf_FMULiw_a16, sf_FMULiw_a16, sf_FMULiw_a16, sf_FMULiw_a16, sf_FMULiw_a16, + sf_FCOMiw_a16, sf_FCOMiw_a16, sf_FCOMiw_a16, sf_FCOMiw_a16, sf_FCOMiw_a16, sf_FCOMiw_a16, sf_FCOMiw_a16, sf_FCOMiw_a16, + sf_FCOMPiw_a16, sf_FCOMPiw_a16, sf_FCOMPiw_a16, sf_FCOMPiw_a16, sf_FCOMPiw_a16, sf_FCOMPiw_a16, sf_FCOMPiw_a16, sf_FCOMPiw_a16, + sf_FSUBiw_a16, sf_FSUBiw_a16, sf_FSUBiw_a16, sf_FSUBiw_a16, sf_FSUBiw_a16, sf_FSUBiw_a16, sf_FSUBiw_a16, sf_FSUBiw_a16, + sf_FSUBRiw_a16, sf_FSUBRiw_a16, sf_FSUBRiw_a16, sf_FSUBRiw_a16, sf_FSUBRiw_a16, sf_FSUBRiw_a16, sf_FSUBRiw_a16, sf_FSUBRiw_a16, + sf_FDIViw_a16, sf_FDIViw_a16, sf_FDIViw_a16, sf_FDIViw_a16, sf_FDIViw_a16, sf_FDIViw_a16, sf_FDIViw_a16, sf_FDIViw_a16, + sf_FDIVRiw_a16, sf_FDIVRiw_a16, sf_FDIVRiw_a16, sf_FDIVRiw_a16, sf_FDIVRiw_a16, sf_FDIVRiw_a16, sf_FDIVRiw_a16, sf_FDIVRiw_a16, + + sf_FADDiw_a16, sf_FADDiw_a16, sf_FADDiw_a16, sf_FADDiw_a16, sf_FADDiw_a16, sf_FADDiw_a16, sf_FADDiw_a16, sf_FADDiw_a16, + sf_FMULiw_a16, sf_FMULiw_a16, sf_FMULiw_a16, sf_FMULiw_a16, sf_FMULiw_a16, sf_FMULiw_a16, sf_FMULiw_a16, sf_FMULiw_a16, + sf_FCOMiw_a16, sf_FCOMiw_a16, sf_FCOMiw_a16, sf_FCOMiw_a16, sf_FCOMiw_a16, sf_FCOMiw_a16, sf_FCOMiw_a16, sf_FCOMiw_a16, + sf_FCOMPiw_a16, sf_FCOMPiw_a16, sf_FCOMPiw_a16, sf_FCOMPiw_a16, sf_FCOMPiw_a16, sf_FCOMPiw_a16, sf_FCOMPiw_a16, sf_FCOMPiw_a16, + sf_FSUBiw_a16, sf_FSUBiw_a16, sf_FSUBiw_a16, sf_FSUBiw_a16, sf_FSUBiw_a16, sf_FSUBiw_a16, sf_FSUBiw_a16, sf_FSUBiw_a16, + sf_FSUBRiw_a16, sf_FSUBRiw_a16, sf_FSUBRiw_a16, sf_FSUBRiw_a16, sf_FSUBRiw_a16, sf_FSUBRiw_a16, sf_FSUBRiw_a16, sf_FSUBRiw_a16, + sf_FDIViw_a16, sf_FDIViw_a16, sf_FDIViw_a16, sf_FDIViw_a16, sf_FDIViw_a16, sf_FDIViw_a16, sf_FDIViw_a16, sf_FDIViw_a16, + sf_FDIVRiw_a16, sf_FDIVRiw_a16, sf_FDIVRiw_a16, sf_FDIVRiw_a16, sf_FDIVRiw_a16, sf_FDIVRiw_a16, sf_FDIVRiw_a16, sf_FDIVRiw_a16, + + sf_FADDiw_a16, sf_FADDiw_a16, sf_FADDiw_a16, sf_FADDiw_a16, sf_FADDiw_a16, sf_FADDiw_a16, sf_FADDiw_a16, sf_FADDiw_a16, + sf_FMULiw_a16, sf_FMULiw_a16, sf_FMULiw_a16, sf_FMULiw_a16, sf_FMULiw_a16, sf_FMULiw_a16, sf_FMULiw_a16, sf_FMULiw_a16, + sf_FCOMiw_a16, sf_FCOMiw_a16, sf_FCOMiw_a16, sf_FCOMiw_a16, sf_FCOMiw_a16, sf_FCOMiw_a16, sf_FCOMiw_a16, sf_FCOMiw_a16, + sf_FCOMPiw_a16, sf_FCOMPiw_a16, sf_FCOMPiw_a16, sf_FCOMPiw_a16, sf_FCOMPiw_a16, sf_FCOMPiw_a16, sf_FCOMPiw_a16, sf_FCOMPiw_a16, + sf_FSUBiw_a16, sf_FSUBiw_a16, sf_FSUBiw_a16, sf_FSUBiw_a16, sf_FSUBiw_a16, sf_FSUBiw_a16, sf_FSUBiw_a16, sf_FSUBiw_a16, + sf_FSUBRiw_a16, sf_FSUBRiw_a16, sf_FSUBRiw_a16, sf_FSUBRiw_a16, sf_FSUBRiw_a16, sf_FSUBRiw_a16, sf_FSUBRiw_a16, sf_FSUBRiw_a16, + sf_FDIViw_a16, sf_FDIViw_a16, sf_FDIViw_a16, sf_FDIViw_a16, sf_FDIViw_a16, sf_FDIViw_a16, sf_FDIViw_a16, sf_FDIViw_a16, + sf_FDIVRiw_a16, sf_FDIVRiw_a16, sf_FDIVRiw_a16, sf_FDIVRiw_a16, sf_FDIVRiw_a16, sf_FDIVRiw_a16, sf_FDIVRiw_a16, sf_FDIVRiw_a16, + + sf_FADDP_sti_st0, sf_FADDP_sti_st0, sf_FADDP_sti_st0, sf_FADDP_sti_st0, sf_FADDP_sti_st0, sf_FADDP_sti_st0, sf_FADDP_sti_st0, sf_FADDP_sti_st0, + sf_FMULP_sti_st0, sf_FMULP_sti_st0, sf_FMULP_sti_st0, sf_FMULP_sti_st0, sf_FMULP_sti_st0, sf_FMULP_sti_st0, sf_FMULP_sti_st0, sf_FMULP_sti_st0, + ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, + ILLEGAL_a16, sf_FCOMPP, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, + sf_FSUBRP_sti_st0, sf_FSUBRP_sti_st0, sf_FSUBRP_sti_st0, sf_FSUBRP_sti_st0, sf_FSUBRP_sti_st0, sf_FSUBRP_sti_st0, sf_FSUBRP_sti_st0, sf_FSUBRP_sti_st0, + sf_FSUBP_sti_st0, sf_FSUBP_sti_st0, sf_FSUBP_sti_st0, sf_FSUBP_sti_st0, sf_FSUBP_sti_st0, sf_FSUBP_sti_st0, sf_FSUBP_sti_st0, sf_FSUBP_sti_st0, + sf_FDIVRP_sti_st0, sf_FDIVRP_sti_st0, sf_FDIVRP_sti_st0, sf_FDIVRP_sti_st0, sf_FDIVRP_sti_st0, sf_FDIVRP_sti_st0, sf_FDIVRP_sti_st0, sf_FDIVRP_sti_st0, + sf_FDIVP_sti_st0, sf_FDIVP_sti_st0, sf_FDIVP_sti_st0, sf_FDIVP_sti_st0, sf_FDIVP_sti_st0, sf_FDIVP_sti_st0, sf_FDIVP_sti_st0, sf_FDIVP_sti_st0, + // clang-format on +}; + +const OpFn OP_TABLE(sf_fpu_8087_df)[256] = { + // clang-format off + sf_FILDiw_a16, sf_FILDiw_a16, sf_FILDiw_a16, sf_FILDiw_a16, sf_FILDiw_a16, sf_FILDiw_a16, sf_FILDiw_a16, sf_FILDiw_a16, + ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, + sf_FISTiw_a16, sf_FISTiw_a16, sf_FISTiw_a16, sf_FISTiw_a16, sf_FISTiw_a16, sf_FISTiw_a16, sf_FISTiw_a16, sf_FISTiw_a16, + sf_FISTPiw_a16, sf_FISTPiw_a16, sf_FISTPiw_a16, sf_FISTPiw_a16, sf_FISTPiw_a16, sf_FISTPiw_a16, sf_FISTPiw_a16, sf_FISTPiw_a16, + ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, + sf_FILDiq_a16, sf_FILDiq_a16, sf_FILDiq_a16, sf_FILDiq_a16, sf_FILDiq_a16, sf_FILDiq_a16, sf_FILDiq_a16, sf_FILDiq_a16, + sf_FBSTP_PACKED_BCD_a16, sf_FBSTP_PACKED_BCD_a16, sf_FBSTP_PACKED_BCD_a16, sf_FBSTP_PACKED_BCD_a16, sf_FBSTP_PACKED_BCD_a16, sf_FBSTP_PACKED_BCD_a16, sf_FBSTP_PACKED_BCD_a16, sf_FBSTP_PACKED_BCD_a16, + sf_FISTPiq_a16, sf_FISTPiq_a16, sf_FISTPiq_a16, sf_FISTPiq_a16, sf_FISTPiq_a16, sf_FISTPiq_a16, sf_FISTPiq_a16, sf_FISTPiq_a16, + + sf_FILDiw_a16, sf_FILDiw_a16, sf_FILDiw_a16, sf_FILDiw_a16, sf_FILDiw_a16, sf_FILDiw_a16, sf_FILDiw_a16, sf_FILDiw_a16, + ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, + sf_FISTiw_a16, sf_FISTiw_a16, sf_FISTiw_a16, sf_FISTiw_a16, sf_FISTiw_a16, sf_FISTiw_a16, sf_FISTiw_a16, sf_FISTiw_a16, + sf_FISTPiw_a16, sf_FISTPiw_a16, sf_FISTPiw_a16, sf_FISTPiw_a16, sf_FISTPiw_a16, sf_FISTPiw_a16, sf_FISTPiw_a16, sf_FISTPiw_a16, + ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, + sf_FILDiq_a16, sf_FILDiq_a16, sf_FILDiq_a16, sf_FILDiq_a16, sf_FILDiq_a16, sf_FILDiq_a16, sf_FILDiq_a16, sf_FILDiq_a16, + sf_FBSTP_PACKED_BCD_a16, sf_FBSTP_PACKED_BCD_a16, sf_FBSTP_PACKED_BCD_a16, sf_FBSTP_PACKED_BCD_a16, sf_FBSTP_PACKED_BCD_a16, sf_FBSTP_PACKED_BCD_a16, sf_FBSTP_PACKED_BCD_a16, sf_FBSTP_PACKED_BCD_a16, + sf_FISTPiq_a16, sf_FISTPiq_a16, sf_FISTPiq_a16, sf_FISTPiq_a16, sf_FISTPiq_a16, sf_FISTPiq_a16, sf_FISTPiq_a16, sf_FISTPiq_a16, + + sf_FILDiw_a16, sf_FILDiw_a16, sf_FILDiw_a16, sf_FILDiw_a16, sf_FILDiw_a16, sf_FILDiw_a16, sf_FILDiw_a16, sf_FILDiw_a16, + ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, + sf_FISTiw_a16, sf_FISTiw_a16, sf_FISTiw_a16, sf_FISTiw_a16, sf_FISTiw_a16, sf_FISTiw_a16, sf_FISTiw_a16, sf_FISTiw_a16, + sf_FISTPiw_a16, sf_FISTPiw_a16, sf_FISTPiw_a16, sf_FISTPiw_a16, sf_FISTPiw_a16, sf_FISTPiw_a16, sf_FISTPiw_a16, sf_FISTPiw_a16, + ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, + sf_FILDiq_a16, sf_FILDiq_a16, sf_FILDiq_a16, sf_FILDiq_a16, sf_FILDiq_a16, sf_FILDiq_a16, sf_FILDiq_a16, sf_FILDiq_a16, + sf_FBSTP_PACKED_BCD_a16, sf_FBSTP_PACKED_BCD_a16, sf_FBSTP_PACKED_BCD_a16, sf_FBSTP_PACKED_BCD_a16, sf_FBSTP_PACKED_BCD_a16, sf_FBSTP_PACKED_BCD_a16, sf_FBSTP_PACKED_BCD_a16, sf_FBSTP_PACKED_BCD_a16, + sf_FISTPiq_a16, sf_FISTPiq_a16, sf_FISTPiq_a16, sf_FISTPiq_a16, sf_FISTPiq_a16, sf_FISTPiq_a16, sf_FISTPiq_a16, sf_FISTPiq_a16, + + sf_FFREEP_sti, sf_FFREEP_sti, sf_FFREEP_sti, sf_FFREEP_sti, sf_FFREEP_sti, sf_FFREEP_sti, sf_FFREEP_sti, sf_FFREEP_sti, + ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, + ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, + ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, + ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, + ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, + ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, + ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, + // clang-format on +}; + +const OpFn OP_TABLE(fpu_8087_d8)[32] = { + // clang-format off opFADDs_a16, opFMULs_a16, opFCOMs_a16, opFCOMPs_a16, opFSUBs_a16, opFSUBRs_a16, opFDIVs_a16, opFDIVRs_a16, opFADDs_a16, opFMULs_a16, opFCOMs_a16, opFCOMPs_a16, opFSUBs_a16, opFSUBRs_a16, opFDIVs_a16, opFDIVRs_a16, opFADDs_a16, opFMULs_a16, opFCOMs_a16, opFCOMPs_a16, opFSUBs_a16, opFSUBRs_a16, opFDIVs_a16, opFDIVRs_a16, opFADD, opFMUL, opFCOM, opFCOMP, opFSUB, opFSUBR, opFDIV, opFDIVR + // clang-format on }; -const OpFn OP_TABLE(fpu_8087_d9)[256] = -{ +const OpFn OP_TABLE(fpu_8087_d9)[256] = { + // clang-format off opFLDs_a16, opFLDs_a16, opFLDs_a16, opFLDs_a16, opFLDs_a16, opFLDs_a16, opFLDs_a16, opFLDs_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, opFSTs_a16, opFSTs_a16, opFSTs_a16, opFSTs_a16, opFSTs_a16, opFSTs_a16, opFSTs_a16, opFSTs_a16, opFSTPs_a16, opFSTPs_a16, opFSTPs_a16, opFSTPs_a16, opFSTPs_a16, opFSTPs_a16, opFSTPs_a16, opFSTPs_a16, - opFLDENV_a16, opFLDENV_a16, opFLDENV_a16, opFLDENV_a16, opFLDENV_a16, opFLDENV_a16, opFLDENV_a16, opFLDENV_a16, + opFLDENV_a16, opFLDENV_a16, opFLDENV_a16, opFLDENV_a16, opFLDENV_a16, opFLDENV_a16, opFLDENV_a16, opFLDENV_a16, opFLDCW_a16, opFLDCW_a16, opFLDCW_a16, opFLDCW_a16, opFLDCW_a16, opFLDCW_a16, opFLDCW_a16, opFLDCW_a16, opFSTENV_a16, opFSTENV_a16, opFSTENV_a16, opFSTENV_a16, opFSTENV_a16, opFSTENV_a16, opFSTENV_a16, opFSTENV_a16, opFSTCW_a16, opFSTCW_a16, opFSTCW_a16, opFSTCW_a16, opFSTCW_a16, opFSTCW_a16, opFSTCW_a16, opFSTCW_a16, @@ -611,7 +855,7 @@ const OpFn OP_TABLE(fpu_8087_d9)[256] = ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, opFSTs_a16, opFSTs_a16, opFSTs_a16, opFSTs_a16, opFSTs_a16, opFSTs_a16, opFSTs_a16, opFSTs_a16, opFSTPs_a16, opFSTPs_a16, opFSTPs_a16, opFSTPs_a16, opFSTPs_a16, opFSTPs_a16, opFSTPs_a16, opFSTPs_a16, - opFLDENV_a16, opFLDENV_a16, opFLDENV_a16, opFLDENV_a16, opFLDENV_a16, opFLDENV_a16, opFLDENV_a16, opFLDENV_a16, + opFLDENV_a16, opFLDENV_a16, opFLDENV_a16, opFLDENV_a16, opFLDENV_a16, opFLDENV_a16, opFLDENV_a16, opFLDENV_a16, opFLDCW_a16, opFLDCW_a16, opFLDCW_a16, opFLDCW_a16, opFLDCW_a16, opFLDCW_a16, opFLDCW_a16, opFLDCW_a16, opFSTENV_a16, opFSTENV_a16, opFSTENV_a16, opFSTENV_a16, opFSTENV_a16, opFSTENV_a16, opFSTENV_a16, opFSTENV_a16, opFSTCW_a16, opFSTCW_a16, opFSTCW_a16, opFSTCW_a16, opFSTCW_a16, opFSTCW_a16, opFSTCW_a16, opFSTCW_a16, @@ -620,7 +864,7 @@ const OpFn OP_TABLE(fpu_8087_d9)[256] = ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, opFSTs_a16, opFSTs_a16, opFSTs_a16, opFSTs_a16, opFSTs_a16, opFSTs_a16, opFSTs_a16, opFSTs_a16, opFSTPs_a16, opFSTPs_a16, opFSTPs_a16, opFSTPs_a16, opFSTPs_a16, opFSTPs_a16, opFSTPs_a16, opFSTPs_a16, - opFLDENV_a16, opFLDENV_a16, opFLDENV_a16, opFLDENV_a16, opFLDENV_a16, opFLDENV_a16, opFLDENV_a16, opFLDENV_a16, + opFLDENV_a16, opFLDENV_a16, opFLDENV_a16, opFLDENV_a16, opFLDENV_a16, opFLDENV_a16, opFLDENV_a16, opFLDENV_a16, opFLDCW_a16, opFLDCW_a16, opFLDCW_a16, opFLDCW_a16, opFLDCW_a16, opFLDCW_a16, opFLDCW_a16, opFLDCW_a16, opFSTENV_a16, opFSTENV_a16, opFSTENV_a16, opFSTENV_a16, opFSTENV_a16, opFSTENV_a16, opFSTENV_a16, opFSTENV_a16, opFSTCW_a16, opFSTCW_a16, opFSTCW_a16, opFSTCW_a16, opFSTCW_a16, opFSTCW_a16, opFSTCW_a16, opFSTCW_a16, @@ -631,12 +875,13 @@ const OpFn OP_TABLE(fpu_8087_d9)[256] = ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, /*Invalid*/ opFCHS, opFABS, ILLEGAL_a16, ILLEGAL_a16, opFTST, opFXAM, ILLEGAL_a16, ILLEGAL_a16, opFLD1, opFLDL2T, opFLDL2E, opFLDPI, opFLDEG2, opFLDLN2, opFLDZ, ILLEGAL_a16, - opF2XM1, opFYL2X, opFPTAN, opFPATAN, ILLEGAL_a16, ILLEGAL_a16, opFDECSTP, opFINCSTP, - opFPREM, opFYL2XP1, opFSQRT, ILLEGAL_a16, opFRNDINT, opFSCALE, ILLEGAL_a16, ILLEGAL_a16 + opF2XM1, opFYL2X, opFPTAN, opFPATAN, opFXTRACT, opFPREM1, opFDECSTP, opFINCSTP, + opFPREM, opFYL2XP1, opFSQRT, ILLEGAL_a16, opFRNDINT, opFSCALE, ILLEGAL_a16, ILLEGAL_a16 + // clang-format on }; -const OpFn OP_TABLE(fpu_8087_da)[256] = -{ +const OpFn OP_TABLE(fpu_8087_da)[256] = { + // clang-format off opFADDil_a16, opFADDil_a16, opFADDil_a16, opFADDil_a16, opFADDil_a16, opFADDil_a16, opFADDil_a16, opFADDil_a16, opFMULil_a16, opFMULil_a16, opFMULil_a16, opFMULil_a16, opFMULil_a16, opFMULil_a16, opFMULil_a16, opFMULil_a16, opFCOMil_a16, opFCOMil_a16, opFCOMil_a16, opFCOMil_a16, opFCOMil_a16, opFCOMil_a16, opFCOMil_a16, opFCOMil_a16, @@ -672,10 +917,11 @@ const OpFn OP_TABLE(fpu_8087_da)[256] = ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, + // clang-format on }; -const OpFn OP_TABLE(fpu_8087_db)[256] = -{ +const OpFn OP_TABLE(fpu_8087_db)[256] = { + // clang-format off opFILDil_a16, opFILDil_a16, opFILDil_a16, opFILDil_a16, opFILDil_a16, opFILDil_a16, opFILDil_a16, opFILDil_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, opFISTil_a16, opFISTil_a16, opFISTil_a16, opFISTil_a16, opFISTil_a16, opFISTil_a16, opFISTil_a16, opFISTil_a16, @@ -711,18 +957,20 @@ const OpFn OP_TABLE(fpu_8087_db)[256] = ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, + // clang-format on }; -const OpFn OP_TABLE(fpu_8087_dc)[32] = -{ +const OpFn OP_TABLE(fpu_8087_dc)[32] = { + // clang-format off opFADDd_a16, opFMULd_a16, opFCOMd_a16, opFCOMPd_a16, opFSUBd_a16, opFSUBRd_a16, opFDIVd_a16, opFDIVRd_a16, opFADDd_a16, opFMULd_a16, opFCOMd_a16, opFCOMPd_a16, opFSUBd_a16, opFSUBRd_a16, opFDIVd_a16, opFDIVRd_a16, opFADDd_a16, opFMULd_a16, opFCOMd_a16, opFCOMPd_a16, opFSUBd_a16, opFSUBRd_a16, opFDIVd_a16, opFDIVRd_a16, opFADDr, opFMULr, ILLEGAL_a16, ILLEGAL_a16, opFSUBRr, opFSUBr, opFDIVRr, opFDIVr + // clang-format on }; -const OpFn OP_TABLE(fpu_8087_dd)[256] = -{ +const OpFn OP_TABLE(fpu_8087_dd)[256] = { + // clang-format off opFLDd_a16, opFLDd_a16, opFLDd_a16, opFLDd_a16, opFLDd_a16, opFLDd_a16, opFLDd_a16, opFLDd_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, opFSTd_a16, opFSTd_a16, opFSTd_a16, opFSTd_a16, opFSTd_a16, opFSTd_a16, opFSTd_a16, opFSTd_a16, @@ -758,10 +1006,11 @@ const OpFn OP_TABLE(fpu_8087_dd)[256] = ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, + // clang-format on }; -const OpFn OP_TABLE(fpu_8087_de)[256] = -{ +const OpFn OP_TABLE(fpu_8087_de)[256] = { + // clang-format off opFADDiw_a16, opFADDiw_a16, opFADDiw_a16, opFADDiw_a16, opFADDiw_a16, opFADDiw_a16, opFADDiw_a16, opFADDiw_a16, opFMULiw_a16, opFMULiw_a16, opFMULiw_a16, opFMULiw_a16, opFMULiw_a16, opFMULiw_a16, opFMULiw_a16, opFMULiw_a16, opFCOMiw_a16, opFCOMiw_a16, opFCOMiw_a16, opFCOMiw_a16, opFCOMiw_a16, opFCOMiw_a16, opFCOMiw_a16, opFCOMiw_a16, @@ -797,10 +1046,11 @@ const OpFn OP_TABLE(fpu_8087_de)[256] = opFSUBP, opFSUBP, opFSUBP, opFSUBP, opFSUBP, opFSUBP, opFSUBP, opFSUBP, opFDIVRP, opFDIVRP, opFDIVRP, opFDIVRP, opFDIVRP, opFDIVRP, opFDIVRP, opFDIVRP, opFDIVP, opFDIVP, opFDIVP, opFDIVP, opFDIVP, opFDIVP, opFDIVP, opFDIVP, + // clang-format on }; -const OpFn OP_TABLE(fpu_8087_df)[256] = -{ +const OpFn OP_TABLE(fpu_8087_df)[256] = { + // clang-format off opFILDiw_a16, opFILDiw_a16, opFILDiw_a16, opFILDiw_a16, opFILDiw_a16, opFILDiw_a16, opFILDiw_a16, opFILDiw_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, opFISTiw_a16, opFISTiw_a16, opFISTiw_a16, opFISTiw_a16, opFISTiw_a16, opFISTiw_a16, opFISTiw_a16, opFISTiw_a16, @@ -836,32 +1086,1295 @@ const OpFn OP_TABLE(fpu_8087_df)[256] = ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, + // clang-format on }; #else -#define ILLEGAL_a32 FPU_ILLEGAL_a32 +# define ILLEGAL_a32 FPU_ILLEGAL_a32 -const OpFn OP_TABLE(fpu_d8_a16)[32] = -{ +const OpFn OP_TABLE(sf_fpu_d8_a16)[32] = { + // clang-format off + sf_FADDs_a16, sf_FMULs_a16, sf_FCOMs_a16, sf_FCOMPs_a16, sf_FSUBs_a16, sf_FSUBRs_a16, sf_FDIVs_a16, sf_FDIVRs_a16, + sf_FADDs_a16, sf_FMULs_a16, sf_FCOMs_a16, sf_FCOMPs_a16, sf_FSUBs_a16, sf_FSUBRs_a16, sf_FDIVs_a16, sf_FDIVRs_a16, + sf_FADDs_a16, sf_FMULs_a16, sf_FCOMs_a16, sf_FCOMPs_a16, sf_FSUBs_a16, sf_FSUBRs_a16, sf_FDIVs_a16, sf_FDIVRs_a16, + sf_FADD_st0_stj, sf_FMUL_st0_stj, sf_FCOM_sti, sf_FCOMP_sti, sf_FSUB_st0_stj, sf_FSUBR_st0_stj, sf_FDIV_st0_stj, sf_FDIVR_st0_stj, + // clang-format on +}; + +const OpFn OP_TABLE(sf_fpu_d8_a32)[32] = { + // clang-format off + sf_FADDs_a32, sf_FMULs_a32, sf_FCOMs_a32, sf_FCOMPs_a32, sf_FSUBs_a32, sf_FSUBRs_a32, sf_FDIVs_a32, sf_FDIVRs_a32, + sf_FADDs_a32, sf_FMULs_a32, sf_FCOMs_a32, sf_FCOMPs_a32, sf_FSUBs_a32, sf_FSUBRs_a32, sf_FDIVs_a32, sf_FDIVRs_a32, + sf_FADDs_a32, sf_FMULs_a32, sf_FCOMs_a32, sf_FCOMPs_a32, sf_FSUBs_a32, sf_FSUBRs_a32, sf_FDIVs_a32, sf_FDIVRs_a32, + sf_FADD_st0_stj, sf_FMUL_st0_stj, sf_FCOM_sti, sf_FCOMP_sti, sf_FSUB_st0_stj, sf_FSUBR_st0_stj, sf_FDIV_st0_stj, sf_FDIVR_st0_stj, + // clang-format on +}; + +const OpFn OP_TABLE(sf_fpu_287_d9_a16)[256] = { + // clang-format off + sf_FLDs_a16, sf_FLDs_a16, sf_FLDs_a16, sf_FLDs_a16, sf_FLDs_a16, sf_FLDs_a16, sf_FLDs_a16, sf_FLDs_a16, + ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, + sf_FSTs_a16, sf_FSTs_a16, sf_FSTs_a16, sf_FSTs_a16, sf_FSTs_a16, sf_FSTs_a16, sf_FSTs_a16, sf_FSTs_a16, + sf_FSTPs_a16, sf_FSTPs_a16, sf_FSTPs_a16, sf_FSTPs_a16, sf_FSTPs_a16, sf_FSTPs_a16, sf_FSTPs_a16, sf_FSTPs_a16, + sf_FLDENV_a16, sf_FLDENV_a16, sf_FLDENV_a16, sf_FLDENV_a16, sf_FLDENV_a16, sf_FLDENV_a16, sf_FLDENV_a16, sf_FLDENV_a16, + sf_FLDCW_a16, sf_FLDCW_a16, sf_FLDCW_a16, sf_FLDCW_a16, sf_FLDCW_a16, sf_FLDCW_a16, sf_FLDCW_a16, sf_FLDCW_a16, + sf_FNSTENV_a16, sf_FNSTENV_a16, sf_FNSTENV_a16, sf_FNSTENV_a16, sf_FNSTENV_a16, sf_FNSTENV_a16, sf_FNSTENV_a16, sf_FNSTENV_a16, + sf_FNSTCW_a16, sf_FNSTCW_a16, sf_FNSTCW_a16, sf_FNSTCW_a16, sf_FNSTCW_a16, sf_FNSTCW_a16, sf_FNSTCW_a16, sf_FNSTCW_a16, + + sf_FLDs_a16, sf_FLDs_a16, sf_FLDs_a16, sf_FLDs_a16, sf_FLDs_a16, sf_FLDs_a16, sf_FLDs_a16, sf_FLDs_a16, + ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, + sf_FSTs_a16, sf_FSTs_a16, sf_FSTs_a16, sf_FSTs_a16, sf_FSTs_a16, sf_FSTs_a16, sf_FSTs_a16, sf_FSTs_a16, + sf_FSTPs_a16, sf_FSTPs_a16, sf_FSTPs_a16, sf_FSTPs_a16, sf_FSTPs_a16, sf_FSTPs_a16, sf_FSTPs_a16, sf_FSTPs_a16, + sf_FLDENV_a16, sf_FLDENV_a16, sf_FLDENV_a16, sf_FLDENV_a16, sf_FLDENV_a16, sf_FLDENV_a16, sf_FLDENV_a16, sf_FLDENV_a16, + sf_FLDCW_a16, sf_FLDCW_a16, sf_FLDCW_a16, sf_FLDCW_a16, sf_FLDCW_a16, sf_FLDCW_a16, sf_FLDCW_a16, sf_FLDCW_a16, + sf_FNSTENV_a16, sf_FNSTENV_a16, sf_FNSTENV_a16, sf_FNSTENV_a16, sf_FNSTENV_a16, sf_FNSTENV_a16, sf_FNSTENV_a16, sf_FNSTENV_a16, + sf_FNSTCW_a16, sf_FNSTCW_a16, sf_FNSTCW_a16, sf_FNSTCW_a16, sf_FNSTCW_a16, sf_FNSTCW_a16, sf_FNSTCW_a16, sf_FNSTCW_a16, + + sf_FLDs_a16, sf_FLDs_a16, sf_FLDs_a16, sf_FLDs_a16, sf_FLDs_a16, sf_FLDs_a16, sf_FLDs_a16, sf_FLDs_a16, + ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, + sf_FSTs_a16, sf_FSTs_a16, sf_FSTs_a16, sf_FSTs_a16, sf_FSTs_a16, sf_FSTs_a16, sf_FSTs_a16, sf_FSTs_a16, + sf_FSTPs_a16, sf_FSTPs_a16, sf_FSTPs_a16, sf_FSTPs_a16, sf_FSTPs_a16, sf_FSTPs_a16, sf_FSTPs_a16, sf_FSTPs_a16, + sf_FLDENV_a16, sf_FLDENV_a16, sf_FLDENV_a16, sf_FLDENV_a16, sf_FLDENV_a16, sf_FLDENV_a16, sf_FLDENV_a16, sf_FLDENV_a16, + sf_FLDCW_a16, sf_FLDCW_a16, sf_FLDCW_a16, sf_FLDCW_a16, sf_FLDCW_a16, sf_FLDCW_a16, sf_FLDCW_a16, sf_FLDCW_a16, + sf_FNSTENV_a16, sf_FNSTENV_a16, sf_FNSTENV_a16, sf_FNSTENV_a16, sf_FNSTENV_a16, sf_FNSTENV_a16, sf_FNSTENV_a16, sf_FNSTENV_a16, + sf_FNSTCW_a16, sf_FNSTCW_a16, sf_FNSTCW_a16, sf_FNSTCW_a16, sf_FNSTCW_a16, sf_FNSTCW_a16, sf_FNSTCW_a16, sf_FNSTCW_a16, + + sf_FLD_sti, sf_FLD_sti, sf_FLD_sti, sf_FLD_sti, sf_FLD_sti, sf_FLD_sti, sf_FLD_sti, sf_FLD_sti, + sf_FXCH_sti, sf_FXCH_sti, sf_FXCH_sti, sf_FXCH_sti, sf_FXCH_sti, sf_FXCH_sti, sf_FXCH_sti, sf_FXCH_sti, + sf_FNOP, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, + ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, /*Invalid*/ + sf_FCHS, sf_FABS, ILLEGAL_a16, ILLEGAL_a16, sf_FTST, sf_FXAM, ILLEGAL_a16, ILLEGAL_a16, + sf_FLD1, sf_FLDL2T, sf_FLDL2E, sf_FLDPI, sf_FLDEG2, sf_FLDLN2, sf_FLDZ, ILLEGAL_a16, + sf_F2XM1, sf_FYL2X, sf_FPTAN, sf_FPATAN, sf_FXTRACT, sf_FPREM1, sf_FDECSTP, sf_FINCSTP, + sf_FPREM, sf_FYL2XP1, sf_FSQRT, sf_FSINCOS, sf_FRNDINT, sf_FSCALE, sf_FSIN, sf_FCOS, + // clang-format on +}; + +const OpFn OP_TABLE(sf_fpu_287_d9_a32)[256] = { + // clang-format off + sf_FLDs_a32, sf_FLDs_a32, sf_FLDs_a32, sf_FLDs_a32, sf_FLDs_a32, sf_FLDs_a32, sf_FLDs_a32, sf_FLDs_a32, + ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, + sf_FSTs_a32, sf_FSTs_a32, sf_FSTs_a32, sf_FSTs_a32, sf_FSTs_a32, sf_FSTs_a32, sf_FSTs_a32, sf_FSTs_a32, + sf_FSTPs_a32, sf_FSTPs_a32, sf_FSTPs_a32, sf_FSTPs_a32, sf_FSTPs_a32, sf_FSTPs_a32, sf_FSTPs_a32, sf_FSTPs_a32, + sf_FLDENV_a32, sf_FLDENV_a32, sf_FLDENV_a32, sf_FLDENV_a32, sf_FLDENV_a32, sf_FLDENV_a32, sf_FLDENV_a32, sf_FLDENV_a32, + sf_FLDCW_a32, sf_FLDCW_a32, sf_FLDCW_a32, sf_FLDCW_a32, sf_FLDCW_a32, sf_FLDCW_a32, sf_FLDCW_a32, sf_FLDCW_a32, + sf_FNSTENV_a32, sf_FNSTENV_a32, sf_FNSTENV_a32, sf_FNSTENV_a32, sf_FNSTENV_a32, sf_FNSTENV_a32, sf_FNSTENV_a32, sf_FNSTENV_a32, + sf_FNSTCW_a32, sf_FNSTCW_a32, sf_FNSTCW_a32, sf_FNSTCW_a32, sf_FNSTCW_a32, sf_FNSTCW_a32, sf_FNSTCW_a32, sf_FNSTCW_a32, + + sf_FLDs_a32, sf_FLDs_a32, sf_FLDs_a32, sf_FLDs_a32, sf_FLDs_a32, sf_FLDs_a32, sf_FLDs_a32, sf_FLDs_a32, + ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, + sf_FSTs_a32, sf_FSTs_a32, sf_FSTs_a32, sf_FSTs_a32, sf_FSTs_a32, sf_FSTs_a32, sf_FSTs_a32, sf_FSTs_a32, + sf_FSTPs_a32, sf_FSTPs_a32, sf_FSTPs_a32, sf_FSTPs_a32, sf_FSTPs_a32, sf_FSTPs_a32, sf_FSTPs_a32, sf_FSTPs_a32, + sf_FLDENV_a32, sf_FLDENV_a32, sf_FLDENV_a32, sf_FLDENV_a32, sf_FLDENV_a32, sf_FLDENV_a32, sf_FLDENV_a32, sf_FLDENV_a32, + sf_FLDCW_a32, sf_FLDCW_a32, sf_FLDCW_a32, sf_FLDCW_a32, sf_FLDCW_a32, sf_FLDCW_a32, sf_FLDCW_a32, sf_FLDCW_a32, + sf_FNSTENV_a32, sf_FNSTENV_a32, sf_FNSTENV_a32, sf_FNSTENV_a32, sf_FNSTENV_a32, sf_FNSTENV_a32, sf_FNSTENV_a32, sf_FNSTENV_a32, + sf_FNSTCW_a32, sf_FNSTCW_a32, sf_FNSTCW_a32, sf_FNSTCW_a32, sf_FNSTCW_a32, sf_FNSTCW_a32, sf_FNSTCW_a32, sf_FNSTCW_a32, + + sf_FLDs_a32, sf_FLDs_a32, sf_FLDs_a32, sf_FLDs_a32, sf_FLDs_a32, sf_FLDs_a32, sf_FLDs_a32, sf_FLDs_a32, + ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, + sf_FSTs_a32, sf_FSTs_a32, sf_FSTs_a32, sf_FSTs_a32, sf_FSTs_a32, sf_FSTs_a32, sf_FSTs_a32, sf_FSTs_a32, + sf_FSTPs_a32, sf_FSTPs_a32, sf_FSTPs_a32, sf_FSTPs_a32, sf_FSTPs_a32, sf_FSTPs_a32, sf_FSTPs_a32, sf_FSTPs_a32, + sf_FLDENV_a32, sf_FLDENV_a32, sf_FLDENV_a32, sf_FLDENV_a32, sf_FLDENV_a32, sf_FLDENV_a32, sf_FLDENV_a32, sf_FLDENV_a32, + sf_FLDCW_a32, sf_FLDCW_a32, sf_FLDCW_a32, sf_FLDCW_a32, sf_FLDCW_a32, sf_FLDCW_a32, sf_FLDCW_a32, sf_FLDCW_a32, + sf_FNSTENV_a32, sf_FNSTENV_a32, sf_FNSTENV_a32, sf_FNSTENV_a32, sf_FNSTENV_a32, sf_FNSTENV_a32, sf_FNSTENV_a32, sf_FNSTENV_a32, + sf_FNSTCW_a32, sf_FNSTCW_a32, sf_FNSTCW_a32, sf_FNSTCW_a32, sf_FNSTCW_a32, sf_FNSTCW_a32, sf_FNSTCW_a32, sf_FNSTCW_a32, + + sf_FLD_sti, sf_FLD_sti, sf_FLD_sti, sf_FLD_sti, sf_FLD_sti, sf_FLD_sti, sf_FLD_sti, sf_FLD_sti, + sf_FXCH_sti, sf_FXCH_sti, sf_FXCH_sti, sf_FXCH_sti, sf_FXCH_sti, sf_FXCH_sti, sf_FXCH_sti, sf_FXCH_sti, + sf_FNOP, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, + ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, /*Invalid*/ + sf_FCHS, sf_FABS, ILLEGAL_a32, ILLEGAL_a32, sf_FTST, sf_FXAM, ILLEGAL_a32, ILLEGAL_a32, + sf_FLD1, sf_FLDL2T, sf_FLDL2E, sf_FLDPI, sf_FLDEG2, sf_FLDLN2, sf_FLDZ, ILLEGAL_a32, + sf_F2XM1, sf_FYL2X, sf_FPTAN, sf_FPATAN, sf_FXTRACT, sf_FPREM1, sf_FDECSTP, sf_FINCSTP, + sf_FPREM, sf_FYL2XP1, sf_FSQRT, sf_FSINCOS, sf_FRNDINT, sf_FSCALE, sf_FSIN, sf_FCOS, + // clang-format on +}; + +const OpFn OP_TABLE(sf_fpu_d9_a16)[256] = { + // clang-format off + sf_FLDs_a16, sf_FLDs_a16, sf_FLDs_a16, sf_FLDs_a16, sf_FLDs_a16, sf_FLDs_a16, sf_FLDs_a16, sf_FLDs_a16, + ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, + sf_FSTs_a16, sf_FSTs_a16, sf_FSTs_a16, sf_FSTs_a16, sf_FSTs_a16, sf_FSTs_a16, sf_FSTs_a16, sf_FSTs_a16, + sf_FSTPs_a16, sf_FSTPs_a16, sf_FSTPs_a16, sf_FSTPs_a16, sf_FSTPs_a16, sf_FSTPs_a16, sf_FSTPs_a16, sf_FSTPs_a16, + sf_FLDENV_a16, sf_FLDENV_a16, sf_FLDENV_a16, sf_FLDENV_a16, sf_FLDENV_a16, sf_FLDENV_a16, sf_FLDENV_a16, sf_FLDENV_a16, + sf_FLDCW_a16, sf_FLDCW_a16, sf_FLDCW_a16, sf_FLDCW_a16, sf_FLDCW_a16, sf_FLDCW_a16, sf_FLDCW_a16, sf_FLDCW_a16, + sf_FNSTENV_a16, sf_FNSTENV_a16, sf_FNSTENV_a16, sf_FNSTENV_a16, sf_FNSTENV_a16, sf_FNSTENV_a16, sf_FNSTENV_a16, sf_FNSTENV_a16, + sf_FNSTCW_a16, sf_FNSTCW_a16, sf_FNSTCW_a16, sf_FNSTCW_a16, sf_FNSTCW_a16, sf_FNSTCW_a16, sf_FNSTCW_a16, sf_FNSTCW_a16, + + sf_FLDs_a16, sf_FLDs_a16, sf_FLDs_a16, sf_FLDs_a16, sf_FLDs_a16, sf_FLDs_a16, sf_FLDs_a16, sf_FLDs_a16, + ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, + sf_FSTs_a16, sf_FSTs_a16, sf_FSTs_a16, sf_FSTs_a16, sf_FSTs_a16, sf_FSTs_a16, sf_FSTs_a16, sf_FSTs_a16, + sf_FSTPs_a16, sf_FSTPs_a16, sf_FSTPs_a16, sf_FSTPs_a16, sf_FSTPs_a16, sf_FSTPs_a16, sf_FSTPs_a16, sf_FSTPs_a16, + sf_FLDENV_a16, sf_FLDENV_a16, sf_FLDENV_a16, sf_FLDENV_a16, sf_FLDENV_a16, sf_FLDENV_a16, sf_FLDENV_a16, sf_FLDENV_a16, + sf_FLDCW_a16, sf_FLDCW_a16, sf_FLDCW_a16, sf_FLDCW_a16, sf_FLDCW_a16, sf_FLDCW_a16, sf_FLDCW_a16, sf_FLDCW_a16, + sf_FNSTENV_a16, sf_FNSTENV_a16, sf_FNSTENV_a16, sf_FNSTENV_a16, sf_FNSTENV_a16, sf_FNSTENV_a16, sf_FNSTENV_a16, sf_FNSTENV_a16, + sf_FNSTCW_a16, sf_FNSTCW_a16, sf_FNSTCW_a16, sf_FNSTCW_a16, sf_FNSTCW_a16, sf_FNSTCW_a16, sf_FNSTCW_a16, sf_FNSTCW_a16, + + sf_FLDs_a16, sf_FLDs_a16, sf_FLDs_a16, sf_FLDs_a16, sf_FLDs_a16, sf_FLDs_a16, sf_FLDs_a16, sf_FLDs_a16, + ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, + sf_FSTs_a16, sf_FSTs_a16, sf_FSTs_a16, sf_FSTs_a16, sf_FSTs_a16, sf_FSTs_a16, sf_FSTs_a16, sf_FSTs_a16, + sf_FSTPs_a16, sf_FSTPs_a16, sf_FSTPs_a16, sf_FSTPs_a16, sf_FSTPs_a16, sf_FSTPs_a16, sf_FSTPs_a16, sf_FSTPs_a16, + sf_FLDENV_a16, sf_FLDENV_a16, sf_FLDENV_a16, sf_FLDENV_a16, sf_FLDENV_a16, sf_FLDENV_a16, sf_FLDENV_a16, sf_FLDENV_a16, + sf_FLDCW_a16, sf_FLDCW_a16, sf_FLDCW_a16, sf_FLDCW_a16, sf_FLDCW_a16, sf_FLDCW_a16, sf_FLDCW_a16, sf_FLDCW_a16, + sf_FNSTENV_a16, sf_FNSTENV_a16, sf_FNSTENV_a16, sf_FNSTENV_a16, sf_FNSTENV_a16, sf_FNSTENV_a16, sf_FNSTENV_a16, sf_FNSTENV_a16, + sf_FNSTCW_a16, sf_FNSTCW_a16, sf_FNSTCW_a16, sf_FNSTCW_a16, sf_FNSTCW_a16, sf_FNSTCW_a16, sf_FNSTCW_a16, sf_FNSTCW_a16, + + sf_FLD_sti, sf_FLD_sti, sf_FLD_sti, sf_FLD_sti, sf_FLD_sti, sf_FLD_sti, sf_FLD_sti, sf_FLD_sti, + sf_FXCH_sti, sf_FXCH_sti, sf_FXCH_sti, sf_FXCH_sti, sf_FXCH_sti, sf_FXCH_sti, sf_FXCH_sti, sf_FXCH_sti, + sf_FNOP, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, + sf_FSTP_sti, sf_FSTP_sti, sf_FSTP_sti, sf_FSTP_sti, sf_FSTP_sti, sf_FSTP_sti, sf_FSTP_sti, sf_FSTP_sti, /*Invalid*/ + sf_FCHS, sf_FABS, ILLEGAL_a16, ILLEGAL_a16, sf_FTST, sf_FXAM, ILLEGAL_a16, ILLEGAL_a16, + sf_FLD1, sf_FLDL2T, sf_FLDL2E, sf_FLDPI, sf_FLDEG2, sf_FLDLN2, sf_FLDZ, ILLEGAL_a16, + sf_F2XM1, sf_FYL2X, sf_FPTAN, sf_FPATAN, sf_FXTRACT, sf_FPREM1, sf_FDECSTP, sf_FINCSTP, + sf_FPREM, sf_FYL2XP1, sf_FSQRT, sf_FSINCOS, sf_FRNDINT, sf_FSCALE, sf_FSIN, sf_FCOS, + // clang-format on +}; + +const OpFn OP_TABLE(sf_fpu_d9_a32)[256] = { + // clang-format off + sf_FLDs_a32, sf_FLDs_a32, sf_FLDs_a32, sf_FLDs_a32, sf_FLDs_a32, sf_FLDs_a32, sf_FLDs_a32, sf_FLDs_a32, + ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, + sf_FSTs_a32, sf_FSTs_a32, sf_FSTs_a32, sf_FSTs_a32, sf_FSTs_a32, sf_FSTs_a32, sf_FSTs_a32, sf_FSTs_a32, + sf_FSTPs_a32, sf_FSTPs_a32, sf_FSTPs_a32, sf_FSTPs_a32, sf_FSTPs_a32, sf_FSTPs_a32, sf_FSTPs_a32, sf_FSTPs_a32, + sf_FLDENV_a32, sf_FLDENV_a32, sf_FLDENV_a32, sf_FLDENV_a32, sf_FLDENV_a32, sf_FLDENV_a32, sf_FLDENV_a32, sf_FLDENV_a32, + sf_FLDCW_a32, sf_FLDCW_a32, sf_FLDCW_a32, sf_FLDCW_a32, sf_FLDCW_a32, sf_FLDCW_a32, sf_FLDCW_a32, sf_FLDCW_a32, + sf_FNSTENV_a32, sf_FNSTENV_a32, sf_FNSTENV_a32, sf_FNSTENV_a32, sf_FNSTENV_a32, sf_FNSTENV_a32, sf_FNSTENV_a32, sf_FNSTENV_a32, + sf_FNSTCW_a32, sf_FNSTCW_a32, sf_FNSTCW_a32, sf_FNSTCW_a32, sf_FNSTCW_a32, sf_FNSTCW_a32, sf_FNSTCW_a32, sf_FNSTCW_a32, + + sf_FLDs_a32, sf_FLDs_a32, sf_FLDs_a32, sf_FLDs_a32, sf_FLDs_a32, sf_FLDs_a32, sf_FLDs_a32, sf_FLDs_a32, + ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, + sf_FSTs_a32, sf_FSTs_a32, sf_FSTs_a32, sf_FSTs_a32, sf_FSTs_a32, sf_FSTs_a32, sf_FSTs_a32, sf_FSTs_a32, + sf_FSTPs_a32, sf_FSTPs_a32, sf_FSTPs_a32, sf_FSTPs_a32, sf_FSTPs_a32, sf_FSTPs_a32, sf_FSTPs_a32, sf_FSTPs_a32, + sf_FLDENV_a32, sf_FLDENV_a32, sf_FLDENV_a32, sf_FLDENV_a32, sf_FLDENV_a32, sf_FLDENV_a32, sf_FLDENV_a32, sf_FLDENV_a32, + sf_FLDCW_a32, sf_FLDCW_a32, sf_FLDCW_a32, sf_FLDCW_a32, sf_FLDCW_a32, sf_FLDCW_a32, sf_FLDCW_a32, sf_FLDCW_a32, + sf_FNSTENV_a32, sf_FNSTENV_a32, sf_FNSTENV_a32, sf_FNSTENV_a32, sf_FNSTENV_a32, sf_FNSTENV_a32, sf_FNSTENV_a32, sf_FNSTENV_a32, + sf_FNSTCW_a32, sf_FNSTCW_a32, sf_FNSTCW_a32, sf_FNSTCW_a32, sf_FNSTCW_a32, sf_FNSTCW_a32, sf_FNSTCW_a32, sf_FNSTCW_a32, + + sf_FLDs_a32, sf_FLDs_a32, sf_FLDs_a32, sf_FLDs_a32, sf_FLDs_a32, sf_FLDs_a32, sf_FLDs_a32, sf_FLDs_a32, + ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, + sf_FSTs_a32, sf_FSTs_a32, sf_FSTs_a32, sf_FSTs_a32, sf_FSTs_a32, sf_FSTs_a32, sf_FSTs_a32, sf_FSTs_a32, + sf_FSTPs_a32, sf_FSTPs_a32, sf_FSTPs_a32, sf_FSTPs_a32, sf_FSTPs_a32, sf_FSTPs_a32, sf_FSTPs_a32, sf_FSTPs_a32, + sf_FLDENV_a32, sf_FLDENV_a32, sf_FLDENV_a32, sf_FLDENV_a32, sf_FLDENV_a32, sf_FLDENV_a32, sf_FLDENV_a32, sf_FLDENV_a32, + sf_FLDCW_a32, sf_FLDCW_a32, sf_FLDCW_a32, sf_FLDCW_a32, sf_FLDCW_a32, sf_FLDCW_a32, sf_FLDCW_a32, sf_FLDCW_a32, + sf_FNSTENV_a32, sf_FNSTENV_a32, sf_FNSTENV_a32, sf_FNSTENV_a32, sf_FNSTENV_a32, sf_FNSTENV_a32, sf_FNSTENV_a32, sf_FNSTENV_a32, + sf_FNSTCW_a32, sf_FNSTCW_a32, sf_FNSTCW_a32, sf_FNSTCW_a32, sf_FNSTCW_a32, sf_FNSTCW_a32, sf_FNSTCW_a32, sf_FNSTCW_a32, + + sf_FLD_sti, sf_FLD_sti, sf_FLD_sti, sf_FLD_sti, sf_FLD_sti, sf_FLD_sti, sf_FLD_sti, sf_FLD_sti, + sf_FXCH_sti, sf_FXCH_sti, sf_FXCH_sti, sf_FXCH_sti, sf_FXCH_sti, sf_FXCH_sti, sf_FXCH_sti, sf_FXCH_sti, + sf_FNOP, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, + sf_FSTP_sti, sf_FSTP_sti, sf_FSTP_sti, sf_FSTP_sti, sf_FSTP_sti, sf_FSTP_sti, sf_FSTP_sti, sf_FSTP_sti, /*Invalid*/ + sf_FCHS, sf_FABS, ILLEGAL_a32, ILLEGAL_a32, sf_FTST, sf_FXAM, ILLEGAL_a32, ILLEGAL_a32, + sf_FLD1, sf_FLDL2T, sf_FLDL2E, sf_FLDPI, sf_FLDEG2, sf_FLDLN2, sf_FLDZ, ILLEGAL_a32, + sf_F2XM1, sf_FYL2X, sf_FPTAN, sf_FPATAN, sf_FXTRACT, sf_FPREM1, sf_FDECSTP, sf_FINCSTP, + sf_FPREM, sf_FYL2XP1, sf_FSQRT, sf_FSINCOS, sf_FRNDINT, sf_FSCALE, sf_FSIN, sf_FCOS, + // clang-format on +}; + +const OpFn OP_TABLE(sf_fpu_287_da_a16)[256] = { + // clang-format off + sf_FADDil_a16, sf_FADDil_a16, sf_FADDil_a16, sf_FADDil_a16, sf_FADDil_a16, sf_FADDil_a16, sf_FADDil_a16, sf_FADDil_a16, + sf_FMULil_a16, sf_FMULil_a16, sf_FMULil_a16, sf_FMULil_a16, sf_FMULil_a16, sf_FMULil_a16, sf_FMULil_a16, sf_FMULil_a16, + sf_FCOMil_a16, sf_FCOMil_a16, sf_FCOMil_a16, sf_FCOMil_a16, sf_FCOMil_a16, sf_FCOMil_a16, sf_FCOMil_a16, sf_FCOMil_a16, + sf_FCOMPil_a16, sf_FCOMPil_a16, sf_FCOMPil_a16, sf_FCOMPil_a16, sf_FCOMPil_a16, sf_FCOMPil_a16, sf_FCOMPil_a16, sf_FCOMPil_a16, + sf_FSUBil_a16, sf_FSUBil_a16, sf_FSUBil_a16, sf_FSUBil_a16, sf_FSUBil_a16, sf_FSUBil_a16, sf_FSUBil_a16, sf_FSUBil_a16, + sf_FSUBRil_a16, sf_FSUBRil_a16, sf_FSUBRil_a16, sf_FSUBRil_a16, sf_FSUBRil_a16, sf_FSUBRil_a16, sf_FSUBRil_a16, sf_FSUBRil_a16, + sf_FDIVil_a16, sf_FDIVil_a16, sf_FDIVil_a16, sf_FDIVil_a16, sf_FDIVil_a16, sf_FDIVil_a16, sf_FDIVil_a16, sf_FDIVil_a16, + sf_FDIVRil_a16, sf_FDIVRil_a16, sf_FDIVRil_a16, sf_FDIVRil_a16, sf_FDIVRil_a16, sf_FDIVRil_a16, sf_FDIVRil_a16, sf_FDIVRil_a16, + + sf_FADDil_a16, sf_FADDil_a16, sf_FADDil_a16, sf_FADDil_a16, sf_FADDil_a16, sf_FADDil_a16, sf_FADDil_a16, sf_FADDil_a16, + sf_FMULil_a16, sf_FMULil_a16, sf_FMULil_a16, sf_FMULil_a16, sf_FMULil_a16, sf_FMULil_a16, sf_FMULil_a16, sf_FMULil_a16, + sf_FCOMil_a16, sf_FCOMil_a16, sf_FCOMil_a16, sf_FCOMil_a16, sf_FCOMil_a16, sf_FCOMil_a16, sf_FCOMil_a16, sf_FCOMil_a16, + sf_FCOMPil_a16, sf_FCOMPil_a16, sf_FCOMPil_a16, sf_FCOMPil_a16, sf_FCOMPil_a16, sf_FCOMPil_a16, sf_FCOMPil_a16, sf_FCOMPil_a16, + sf_FSUBil_a16, sf_FSUBil_a16, sf_FSUBil_a16, sf_FSUBil_a16, sf_FSUBil_a16, sf_FSUBil_a16, sf_FSUBil_a16, sf_FSUBil_a16, + sf_FSUBRil_a16, sf_FSUBRil_a16, sf_FSUBRil_a16, sf_FSUBRil_a16, sf_FSUBRil_a16, sf_FSUBRil_a16, sf_FSUBRil_a16, sf_FSUBRil_a16, + sf_FDIVil_a16, sf_FDIVil_a16, sf_FDIVil_a16, sf_FDIVil_a16, sf_FDIVil_a16, sf_FDIVil_a16, sf_FDIVil_a16, sf_FDIVil_a16, + sf_FDIVRil_a16, sf_FDIVRil_a16, sf_FDIVRil_a16, sf_FDIVRil_a16, sf_FDIVRil_a16, sf_FDIVRil_a16, sf_FDIVRil_a16, sf_FDIVRil_a16, + + sf_FADDil_a16, sf_FADDil_a16, sf_FADDil_a16, sf_FADDil_a16, sf_FADDil_a16, sf_FADDil_a16, sf_FADDil_a16, sf_FADDil_a16, + sf_FMULil_a16, sf_FMULil_a16, sf_FMULil_a16, sf_FMULil_a16, sf_FMULil_a16, sf_FMULil_a16, sf_FMULil_a16, sf_FMULil_a16, + sf_FCOMil_a16, sf_FCOMil_a16, sf_FCOMil_a16, sf_FCOMil_a16, sf_FCOMil_a16, sf_FCOMil_a16, sf_FCOMil_a16, sf_FCOMil_a16, + sf_FCOMPil_a16, sf_FCOMPil_a16, sf_FCOMPil_a16, sf_FCOMPil_a16, sf_FCOMPil_a16, sf_FCOMPil_a16, sf_FCOMPil_a16, sf_FCOMPil_a16, + sf_FSUBil_a16, sf_FSUBil_a16, sf_FSUBil_a16, sf_FSUBil_a16, sf_FSUBil_a16, sf_FSUBil_a16, sf_FSUBil_a16, sf_FSUBil_a16, + sf_FSUBRil_a16, sf_FSUBRil_a16, sf_FSUBRil_a16, sf_FSUBRil_a16, sf_FSUBRil_a16, sf_FSUBRil_a16, sf_FSUBRil_a16, sf_FSUBRil_a16, + sf_FDIVil_a16, sf_FDIVil_a16, sf_FDIVil_a16, sf_FDIVil_a16, sf_FDIVil_a16, sf_FDIVil_a16, sf_FDIVil_a16, sf_FDIVil_a16, + sf_FDIVRil_a16, sf_FDIVRil_a16, sf_FDIVRil_a16, sf_FDIVRil_a16, sf_FDIVRil_a16, sf_FDIVRil_a16, sf_FDIVRil_a16, sf_FDIVRil_a16, + + ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, + ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, + ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, + ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, + ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, + ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, + ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, + ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, + // clang-format on +}; + +const OpFn OP_TABLE(sf_fpu_287_da_a32)[256] = { + // clang-format off + sf_FADDil_a32, sf_FADDil_a32, sf_FADDil_a32, sf_FADDil_a32, sf_FADDil_a32, sf_FADDil_a32, sf_FADDil_a32, sf_FADDil_a32, + sf_FMULil_a32, sf_FMULil_a32, sf_FMULil_a32, sf_FMULil_a32, sf_FMULil_a32, sf_FMULil_a32, sf_FMULil_a32, sf_FMULil_a32, + sf_FCOMil_a32, sf_FCOMil_a32, sf_FCOMil_a32, sf_FCOMil_a32, sf_FCOMil_a32, sf_FCOMil_a32, sf_FCOMil_a32, sf_FCOMil_a32, + sf_FCOMPil_a32, sf_FCOMPil_a32, sf_FCOMPil_a32, sf_FCOMPil_a32, sf_FCOMPil_a32, sf_FCOMPil_a32, sf_FCOMPil_a32, sf_FCOMPil_a32, + sf_FSUBil_a32, sf_FSUBil_a32, sf_FSUBil_a32, sf_FSUBil_a32, sf_FSUBil_a32, sf_FSUBil_a32, sf_FSUBil_a32, sf_FSUBil_a32, + sf_FSUBRil_a32, sf_FSUBRil_a32, sf_FSUBRil_a32, sf_FSUBRil_a32, sf_FSUBRil_a32, sf_FSUBRil_a32, sf_FSUBRil_a32, sf_FSUBRil_a32, + sf_FDIVil_a32, sf_FDIVil_a32, sf_FDIVil_a32, sf_FDIVil_a32, sf_FDIVil_a32, sf_FDIVil_a32, sf_FDIVil_a32, sf_FDIVil_a32, + sf_FDIVRil_a32, sf_FDIVRil_a32, sf_FDIVRil_a32, sf_FDIVRil_a32, sf_FDIVRil_a32, sf_FDIVRil_a32, sf_FDIVRil_a32, sf_FDIVRil_a32, + + sf_FADDil_a32, sf_FADDil_a32, sf_FADDil_a32, sf_FADDil_a32, sf_FADDil_a32, sf_FADDil_a32, sf_FADDil_a32, sf_FADDil_a32, + sf_FMULil_a32, sf_FMULil_a32, sf_FMULil_a32, sf_FMULil_a32, sf_FMULil_a32, sf_FMULil_a32, sf_FMULil_a32, sf_FMULil_a32, + sf_FCOMil_a32, sf_FCOMil_a32, sf_FCOMil_a32, sf_FCOMil_a32, sf_FCOMil_a32, sf_FCOMil_a32, sf_FCOMil_a32, sf_FCOMil_a32, + sf_FCOMPil_a32, sf_FCOMPil_a32, sf_FCOMPil_a32, sf_FCOMPil_a32, sf_FCOMPil_a32, sf_FCOMPil_a32, sf_FCOMPil_a32, sf_FCOMPil_a32, + sf_FSUBil_a32, sf_FSUBil_a32, sf_FSUBil_a32, sf_FSUBil_a32, sf_FSUBil_a32, sf_FSUBil_a32, sf_FSUBil_a32, sf_FSUBil_a32, + sf_FSUBRil_a32, sf_FSUBRil_a32, sf_FSUBRil_a32, sf_FSUBRil_a32, sf_FSUBRil_a32, sf_FSUBRil_a32, sf_FSUBRil_a32, sf_FSUBRil_a32, + sf_FDIVil_a32, sf_FDIVil_a32, sf_FDIVil_a32, sf_FDIVil_a32, sf_FDIVil_a32, sf_FDIVil_a32, sf_FDIVil_a32, sf_FDIVil_a32, + sf_FDIVRil_a32, sf_FDIVRil_a32, sf_FDIVRil_a32, sf_FDIVRil_a32, sf_FDIVRil_a32, sf_FDIVRil_a32, sf_FDIVRil_a32, sf_FDIVRil_a32, + + sf_FADDil_a32, sf_FADDil_a32, sf_FADDil_a32, sf_FADDil_a32, sf_FADDil_a32, sf_FADDil_a32, sf_FADDil_a32, sf_FADDil_a32, + sf_FMULil_a32, sf_FMULil_a32, sf_FMULil_a32, sf_FMULil_a32, sf_FMULil_a32, sf_FMULil_a32, sf_FMULil_a32, sf_FMULil_a32, + sf_FCOMil_a32, sf_FCOMil_a32, sf_FCOMil_a32, sf_FCOMil_a32, sf_FCOMil_a32, sf_FCOMil_a32, sf_FCOMil_a32, sf_FCOMil_a32, + sf_FCOMPil_a32, sf_FCOMPil_a32, sf_FCOMPil_a32, sf_FCOMPil_a32, sf_FCOMPil_a32, sf_FCOMPil_a32, sf_FCOMPil_a32, sf_FCOMPil_a32, + sf_FSUBil_a32, sf_FSUBil_a32, sf_FSUBil_a32, sf_FSUBil_a32, sf_FSUBil_a32, sf_FSUBil_a32, sf_FSUBil_a32, sf_FSUBil_a32, + sf_FSUBRil_a32, sf_FSUBRil_a32, sf_FSUBRil_a32, sf_FSUBRil_a32, sf_FSUBRil_a32, sf_FSUBRil_a32, sf_FSUBRil_a32, sf_FSUBRil_a32, + sf_FDIVil_a32, sf_FDIVil_a32, sf_FDIVil_a32, sf_FDIVil_a32, sf_FDIVil_a32, sf_FDIVil_a32, sf_FDIVil_a32, sf_FDIVil_a32, + sf_FDIVRil_a32, sf_FDIVRil_a32, sf_FDIVRil_a32, sf_FDIVRil_a32, sf_FDIVRil_a32, sf_FDIVRil_a32, sf_FDIVRil_a32, sf_FDIVRil_a32, + + ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, + ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, + ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, + ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, + ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, + ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, + ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, + ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, + // clang-format on +}; + +const OpFn OP_TABLE(sf_fpu_da_a16)[256] = { + // clang-format off + sf_FADDil_a16, sf_FADDil_a16, sf_FADDil_a16, sf_FADDil_a16, sf_FADDil_a16, sf_FADDil_a16, sf_FADDil_a16, sf_FADDil_a16, + sf_FMULil_a16, sf_FMULil_a16, sf_FMULil_a16, sf_FMULil_a16, sf_FMULil_a16, sf_FMULil_a16, sf_FMULil_a16, sf_FMULil_a16, + sf_FCOMil_a16, sf_FCOMil_a16, sf_FCOMil_a16, sf_FCOMil_a16, sf_FCOMil_a16, sf_FCOMil_a16, sf_FCOMil_a16, sf_FCOMil_a16, + sf_FCOMPil_a16, sf_FCOMPil_a16, sf_FCOMPil_a16, sf_FCOMPil_a16, sf_FCOMPil_a16, sf_FCOMPil_a16, sf_FCOMPil_a16, sf_FCOMPil_a16, + sf_FSUBil_a16, sf_FSUBil_a16, sf_FSUBil_a16, sf_FSUBil_a16, sf_FSUBil_a16, sf_FSUBil_a16, sf_FSUBil_a16, sf_FSUBil_a16, + sf_FSUBRil_a16, sf_FSUBRil_a16, sf_FSUBRil_a16, sf_FSUBRil_a16, sf_FSUBRil_a16, sf_FSUBRil_a16, sf_FSUBRil_a16, sf_FSUBRil_a16, + sf_FDIVil_a16, sf_FDIVil_a16, sf_FDIVil_a16, sf_FDIVil_a16, sf_FDIVil_a16, sf_FDIVil_a16, sf_FDIVil_a16, sf_FDIVil_a16, + sf_FDIVRil_a16, sf_FDIVRil_a16, sf_FDIVRil_a16, sf_FDIVRil_a16, sf_FDIVRil_a16, sf_FDIVRil_a16, sf_FDIVRil_a16, sf_FDIVRil_a16, + + sf_FADDil_a16, sf_FADDil_a16, sf_FADDil_a16, sf_FADDil_a16, sf_FADDil_a16, sf_FADDil_a16, sf_FADDil_a16, sf_FADDil_a16, + sf_FMULil_a16, sf_FMULil_a16, sf_FMULil_a16, sf_FMULil_a16, sf_FMULil_a16, sf_FMULil_a16, sf_FMULil_a16, sf_FMULil_a16, + sf_FCOMil_a16, sf_FCOMil_a16, sf_FCOMil_a16, sf_FCOMil_a16, sf_FCOMil_a16, sf_FCOMil_a16, sf_FCOMil_a16, sf_FCOMil_a16, + sf_FCOMPil_a16, sf_FCOMPil_a16, sf_FCOMPil_a16, sf_FCOMPil_a16, sf_FCOMPil_a16, sf_FCOMPil_a16, sf_FCOMPil_a16, sf_FCOMPil_a16, + sf_FSUBil_a16, sf_FSUBil_a16, sf_FSUBil_a16, sf_FSUBil_a16, sf_FSUBil_a16, sf_FSUBil_a16, sf_FSUBil_a16, sf_FSUBil_a16, + sf_FSUBRil_a16, sf_FSUBRil_a16, sf_FSUBRil_a16, sf_FSUBRil_a16, sf_FSUBRil_a16, sf_FSUBRil_a16, sf_FSUBRil_a16, sf_FSUBRil_a16, + sf_FDIVil_a16, sf_FDIVil_a16, sf_FDIVil_a16, sf_FDIVil_a16, sf_FDIVil_a16, sf_FDIVil_a16, sf_FDIVil_a16, sf_FDIVil_a16, + sf_FDIVRil_a16, sf_FDIVRil_a16, sf_FDIVRil_a16, sf_FDIVRil_a16, sf_FDIVRil_a16, sf_FDIVRil_a16, sf_FDIVRil_a16, sf_FDIVRil_a16, + + sf_FADDil_a16, sf_FADDil_a16, sf_FADDil_a16, sf_FADDil_a16, sf_FADDil_a16, sf_FADDil_a16, sf_FADDil_a16, sf_FADDil_a16, + sf_FMULil_a16, sf_FMULil_a16, sf_FMULil_a16, sf_FMULil_a16, sf_FMULil_a16, sf_FMULil_a16, sf_FMULil_a16, sf_FMULil_a16, + sf_FCOMil_a16, sf_FCOMil_a16, sf_FCOMil_a16, sf_FCOMil_a16, sf_FCOMil_a16, sf_FCOMil_a16, sf_FCOMil_a16, sf_FCOMil_a16, + sf_FCOMPil_a16, sf_FCOMPil_a16, sf_FCOMPil_a16, sf_FCOMPil_a16, sf_FCOMPil_a16, sf_FCOMPil_a16, sf_FCOMPil_a16, sf_FCOMPil_a16, + sf_FSUBil_a16, sf_FSUBil_a16, sf_FSUBil_a16, sf_FSUBil_a16, sf_FSUBil_a16, sf_FSUBil_a16, sf_FSUBil_a16, sf_FSUBil_a16, + sf_FSUBRil_a16, sf_FSUBRil_a16, sf_FSUBRil_a16, sf_FSUBRil_a16, sf_FSUBRil_a16, sf_FSUBRil_a16, sf_FSUBRil_a16, sf_FSUBRil_a16, + sf_FDIVil_a16, sf_FDIVil_a16, sf_FDIVil_a16, sf_FDIVil_a16, sf_FDIVil_a16, sf_FDIVil_a16, sf_FDIVil_a16, sf_FDIVil_a16, + sf_FDIVRil_a16, sf_FDIVRil_a16, sf_FDIVRil_a16, sf_FDIVRil_a16, sf_FDIVRil_a16, sf_FDIVRil_a16, sf_FDIVRil_a16, sf_FDIVRil_a16, + + ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, + ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, + ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, + ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, + ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, + ILLEGAL_a16, sf_FUCOMPP, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, + ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, + ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, + // clang-format on +}; + +const OpFn OP_TABLE(sf_fpu_da_a32)[256] = { + // clang-format off + sf_FADDil_a32, sf_FADDil_a32, sf_FADDil_a32, sf_FADDil_a32, sf_FADDil_a32, sf_FADDil_a32, sf_FADDil_a32, sf_FADDil_a32, + sf_FMULil_a32, sf_FMULil_a32, sf_FMULil_a32, sf_FMULil_a32, sf_FMULil_a32, sf_FMULil_a32, sf_FMULil_a32, sf_FMULil_a32, + sf_FCOMil_a32, sf_FCOMil_a32, sf_FCOMil_a32, sf_FCOMil_a32, sf_FCOMil_a32, sf_FCOMil_a32, sf_FCOMil_a32, sf_FCOMil_a32, + sf_FCOMPil_a32, sf_FCOMPil_a32, sf_FCOMPil_a32, sf_FCOMPil_a32, sf_FCOMPil_a32, sf_FCOMPil_a32, sf_FCOMPil_a32, sf_FCOMPil_a32, + sf_FSUBil_a32, sf_FSUBil_a32, sf_FSUBil_a32, sf_FSUBil_a32, sf_FSUBil_a32, sf_FSUBil_a32, sf_FSUBil_a32, sf_FSUBil_a32, + sf_FSUBRil_a32, sf_FSUBRil_a32, sf_FSUBRil_a32, sf_FSUBRil_a32, sf_FSUBRil_a32, sf_FSUBRil_a32, sf_FSUBRil_a32, sf_FSUBRil_a32, + sf_FDIVil_a32, sf_FDIVil_a32, sf_FDIVil_a32, sf_FDIVil_a32, sf_FDIVil_a32, sf_FDIVil_a32, sf_FDIVil_a32, sf_FDIVil_a32, + sf_FDIVRil_a32, sf_FDIVRil_a32, sf_FDIVRil_a32, sf_FDIVRil_a32, sf_FDIVRil_a32, sf_FDIVRil_a32, sf_FDIVRil_a32, sf_FDIVRil_a32, + + sf_FADDil_a32, sf_FADDil_a32, sf_FADDil_a32, sf_FADDil_a32, sf_FADDil_a32, sf_FADDil_a32, sf_FADDil_a32, sf_FADDil_a32, + sf_FMULil_a32, sf_FMULil_a32, sf_FMULil_a32, sf_FMULil_a32, sf_FMULil_a32, sf_FMULil_a32, sf_FMULil_a32, sf_FMULil_a32, + sf_FCOMil_a32, sf_FCOMil_a32, sf_FCOMil_a32, sf_FCOMil_a32, sf_FCOMil_a32, sf_FCOMil_a32, sf_FCOMil_a32, sf_FCOMil_a32, + sf_FCOMPil_a32, sf_FCOMPil_a32, sf_FCOMPil_a32, sf_FCOMPil_a32, sf_FCOMPil_a32, sf_FCOMPil_a32, sf_FCOMPil_a32, sf_FCOMPil_a32, + sf_FSUBil_a32, sf_FSUBil_a32, sf_FSUBil_a32, sf_FSUBil_a32, sf_FSUBil_a32, sf_FSUBil_a32, sf_FSUBil_a32, sf_FSUBil_a32, + sf_FSUBRil_a32, sf_FSUBRil_a32, sf_FSUBRil_a32, sf_FSUBRil_a32, sf_FSUBRil_a32, sf_FSUBRil_a32, sf_FSUBRil_a32, sf_FSUBRil_a32, + sf_FDIVil_a32, sf_FDIVil_a32, sf_FDIVil_a32, sf_FDIVil_a32, sf_FDIVil_a32, sf_FDIVil_a32, sf_FDIVil_a32, sf_FDIVil_a32, + sf_FDIVRil_a32, sf_FDIVRil_a32, sf_FDIVRil_a32, sf_FDIVRil_a32, sf_FDIVRil_a32, sf_FDIVRil_a32, sf_FDIVRil_a32, sf_FDIVRil_a32, + + sf_FADDil_a32, sf_FADDil_a32, sf_FADDil_a32, sf_FADDil_a32, sf_FADDil_a32, sf_FADDil_a32, sf_FADDil_a32, sf_FADDil_a32, + sf_FMULil_a32, sf_FMULil_a32, sf_FMULil_a32, sf_FMULil_a32, sf_FMULil_a32, sf_FMULil_a32, sf_FMULil_a32, sf_FMULil_a32, + sf_FCOMil_a32, sf_FCOMil_a32, sf_FCOMil_a32, sf_FCOMil_a32, sf_FCOMil_a32, sf_FCOMil_a32, sf_FCOMil_a32, sf_FCOMil_a32, + sf_FCOMPil_a32, sf_FCOMPil_a32, sf_FCOMPil_a32, sf_FCOMPil_a32, sf_FCOMPil_a32, sf_FCOMPil_a32, sf_FCOMPil_a32, sf_FCOMPil_a32, + sf_FSUBil_a32, sf_FSUBil_a32, sf_FSUBil_a32, sf_FSUBil_a32, sf_FSUBil_a32, sf_FSUBil_a32, sf_FSUBil_a32, sf_FSUBil_a32, + sf_FSUBRil_a32, sf_FSUBRil_a32, sf_FSUBRil_a32, sf_FSUBRil_a32, sf_FSUBRil_a32, sf_FSUBRil_a32, sf_FSUBRil_a32, sf_FSUBRil_a32, + sf_FDIVil_a32, sf_FDIVil_a32, sf_FDIVil_a32, sf_FDIVil_a32, sf_FDIVil_a32, sf_FDIVil_a32, sf_FDIVil_a32, sf_FDIVil_a32, + sf_FDIVRil_a32, sf_FDIVRil_a32, sf_FDIVRil_a32, sf_FDIVRil_a32, sf_FDIVRil_a32, sf_FDIVRil_a32, sf_FDIVRil_a32, sf_FDIVRil_a32, + + ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, + ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, + ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, + ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, + ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, + ILLEGAL_a32, sf_FUCOMPP, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, + ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, + ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, + // clang-format on +}; + +# ifndef OPS_286_386 +const OpFn OP_TABLE(sf_fpu_686_da_a16)[256] = { + // clang-format off + sf_FADDil_a16, sf_FADDil_a16, sf_FADDil_a16, sf_FADDil_a16, sf_FADDil_a16, sf_FADDil_a16, sf_FADDil_a16, sf_FADDil_a16, + sf_FMULil_a16, sf_FMULil_a16, sf_FMULil_a16, sf_FMULil_a16, sf_FMULil_a16, sf_FMULil_a16, sf_FMULil_a16, sf_FMULil_a16, + sf_FCOMil_a16, sf_FCOMil_a16, sf_FCOMil_a16, sf_FCOMil_a16, sf_FCOMil_a16, sf_FCOMil_a16, sf_FCOMil_a16, sf_FCOMil_a16, + sf_FCOMPil_a16, sf_FCOMPil_a16, sf_FCOMPil_a16, sf_FCOMPil_a16, sf_FCOMPil_a16, sf_FCOMPil_a16, sf_FCOMPil_a16, sf_FCOMPil_a16, + sf_FSUBil_a16, sf_FSUBil_a16, sf_FSUBil_a16, sf_FSUBil_a16, sf_FSUBil_a16, sf_FSUBil_a16, sf_FSUBil_a16, sf_FSUBil_a16, + sf_FSUBRil_a16, sf_FSUBRil_a16, sf_FSUBRil_a16, sf_FSUBRil_a16, sf_FSUBRil_a16, sf_FSUBRil_a16, sf_FSUBRil_a16, sf_FSUBRil_a16, + sf_FDIVil_a16, sf_FDIVil_a16, sf_FDIVil_a16, sf_FDIVil_a16, sf_FDIVil_a16, sf_FDIVil_a16, sf_FDIVil_a16, sf_FDIVil_a16, + sf_FDIVRil_a16, sf_FDIVRil_a16, sf_FDIVRil_a16, sf_FDIVRil_a16, sf_FDIVRil_a16, sf_FDIVRil_a16, sf_FDIVRil_a16, sf_FDIVRil_a16, + + sf_FADDil_a16, sf_FADDil_a16, sf_FADDil_a16, sf_FADDil_a16, sf_FADDil_a16, sf_FADDil_a16, sf_FADDil_a16, sf_FADDil_a16, + sf_FMULil_a16, sf_FMULil_a16, sf_FMULil_a16, sf_FMULil_a16, sf_FMULil_a16, sf_FMULil_a16, sf_FMULil_a16, sf_FMULil_a16, + sf_FCOMil_a16, sf_FCOMil_a16, sf_FCOMil_a16, sf_FCOMil_a16, sf_FCOMil_a16, sf_FCOMil_a16, sf_FCOMil_a16, sf_FCOMil_a16, + sf_FCOMPil_a16, sf_FCOMPil_a16, sf_FCOMPil_a16, sf_FCOMPil_a16, sf_FCOMPil_a16, sf_FCOMPil_a16, sf_FCOMPil_a16, sf_FCOMPil_a16, + sf_FSUBil_a16, sf_FSUBil_a16, sf_FSUBil_a16, sf_FSUBil_a16, sf_FSUBil_a16, sf_FSUBil_a16, sf_FSUBil_a16, sf_FSUBil_a16, + sf_FSUBRil_a16, sf_FSUBRil_a16, sf_FSUBRil_a16, sf_FSUBRil_a16, sf_FSUBRil_a16, sf_FSUBRil_a16, sf_FSUBRil_a16, sf_FSUBRil_a16, + sf_FDIVil_a16, sf_FDIVil_a16, sf_FDIVil_a16, sf_FDIVil_a16, sf_FDIVil_a16, sf_FDIVil_a16, sf_FDIVil_a16, sf_FDIVil_a16, + sf_FDIVRil_a16, sf_FDIVRil_a16, sf_FDIVRil_a16, sf_FDIVRil_a16, sf_FDIVRil_a16, sf_FDIVRil_a16, sf_FDIVRil_a16, sf_FDIVRil_a16, + + sf_FADDil_a16, sf_FADDil_a16, sf_FADDil_a16, sf_FADDil_a16, sf_FADDil_a16, sf_FADDil_a16, sf_FADDil_a16, sf_FADDil_a16, + sf_FMULil_a16, sf_FMULil_a16, sf_FMULil_a16, sf_FMULil_a16, sf_FMULil_a16, sf_FMULil_a16, sf_FMULil_a16, sf_FMULil_a16, + sf_FCOMil_a16, sf_FCOMil_a16, sf_FCOMil_a16, sf_FCOMil_a16, sf_FCOMil_a16, sf_FCOMil_a16, sf_FCOMil_a16, sf_FCOMil_a16, + sf_FCOMPil_a16, sf_FCOMPil_a16, sf_FCOMPil_a16, sf_FCOMPil_a16, sf_FCOMPil_a16, sf_FCOMPil_a16, sf_FCOMPil_a16, sf_FCOMPil_a16, + sf_FSUBil_a16, sf_FSUBil_a16, sf_FSUBil_a16, sf_FSUBil_a16, sf_FSUBil_a16, sf_FSUBil_a16, sf_FSUBil_a16, sf_FSUBil_a16, + sf_FSUBRil_a16, sf_FSUBRil_a16, sf_FSUBRil_a16, sf_FSUBRil_a16, sf_FSUBRil_a16, sf_FSUBRil_a16, sf_FSUBRil_a16, sf_FSUBRil_a16, + sf_FDIVil_a16, sf_FDIVil_a16, sf_FDIVil_a16, sf_FDIVil_a16, sf_FDIVil_a16, sf_FDIVil_a16, sf_FDIVil_a16, sf_FDIVil_a16, + sf_FDIVRil_a16, sf_FDIVRil_a16, sf_FDIVRil_a16, sf_FDIVRil_a16, sf_FDIVRil_a16, sf_FDIVRil_a16, sf_FDIVRil_a16, sf_FDIVRil_a16, + + sf_FCMOVB, sf_FCMOVB, sf_FCMOVB, sf_FCMOVB, sf_FCMOVB, sf_FCMOVB, sf_FCMOVB, sf_FCMOVB, + sf_FCMOVE, sf_FCMOVE, sf_FCMOVE, sf_FCMOVE, sf_FCMOVE, sf_FCMOVE, sf_FCMOVE, sf_FCMOVE, + sf_FCMOVBE, sf_FCMOVBE, sf_FCMOVBE, sf_FCMOVBE, sf_FCMOVBE, sf_FCMOVBE, sf_FCMOVBE, sf_FCMOVBE, + sf_FCMOVU, sf_FCMOVU, sf_FCMOVU, sf_FCMOVU, sf_FCMOVU, sf_FCMOVU, sf_FCMOVU, sf_FCMOVU, + ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, + ILLEGAL_a16, sf_FUCOMPP, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, + ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, + ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, + // clang-format on +}; + +const OpFn OP_TABLE(sf_fpu_686_da_a32)[256] = { + // clang-format off + sf_FADDil_a32, sf_FADDil_a32, sf_FADDil_a32, sf_FADDil_a32, sf_FADDil_a32, sf_FADDil_a32, sf_FADDil_a32, sf_FADDil_a32, + sf_FMULil_a32, sf_FMULil_a32, sf_FMULil_a32, sf_FMULil_a32, sf_FMULil_a32, sf_FMULil_a32, sf_FMULil_a32, sf_FMULil_a32, + sf_FCOMil_a32, sf_FCOMil_a32, sf_FCOMil_a32, sf_FCOMil_a32, sf_FCOMil_a32, sf_FCOMil_a32, sf_FCOMil_a32, sf_FCOMil_a32, + sf_FCOMPil_a32, sf_FCOMPil_a32, sf_FCOMPil_a32, sf_FCOMPil_a32, sf_FCOMPil_a32, sf_FCOMPil_a32, sf_FCOMPil_a32, sf_FCOMPil_a32, + sf_FSUBil_a32, sf_FSUBil_a32, sf_FSUBil_a32, sf_FSUBil_a32, sf_FSUBil_a32, sf_FSUBil_a32, sf_FSUBil_a32, sf_FSUBil_a32, + sf_FSUBRil_a32, sf_FSUBRil_a32, sf_FSUBRil_a32, sf_FSUBRil_a32, sf_FSUBRil_a32, sf_FSUBRil_a32, sf_FSUBRil_a32, sf_FSUBRil_a32, + sf_FDIVil_a32, sf_FDIVil_a32, sf_FDIVil_a32, sf_FDIVil_a32, sf_FDIVil_a32, sf_FDIVil_a32, sf_FDIVil_a32, sf_FDIVil_a32, + sf_FDIVRil_a32, sf_FDIVRil_a32, sf_FDIVRil_a32, sf_FDIVRil_a32, sf_FDIVRil_a32, sf_FDIVRil_a32, sf_FDIVRil_a32, sf_FDIVRil_a32, + + sf_FADDil_a32, sf_FADDil_a32, sf_FADDil_a32, sf_FADDil_a32, sf_FADDil_a32, sf_FADDil_a32, sf_FADDil_a32, sf_FADDil_a32, + sf_FMULil_a32, sf_FMULil_a32, sf_FMULil_a32, sf_FMULil_a32, sf_FMULil_a32, sf_FMULil_a32, sf_FMULil_a32, sf_FMULil_a32, + sf_FCOMil_a32, sf_FCOMil_a32, sf_FCOMil_a32, sf_FCOMil_a32, sf_FCOMil_a32, sf_FCOMil_a32, sf_FCOMil_a32, sf_FCOMil_a32, + sf_FCOMPil_a32, sf_FCOMPil_a32, sf_FCOMPil_a32, sf_FCOMPil_a32, sf_FCOMPil_a32, sf_FCOMPil_a32, sf_FCOMPil_a32, sf_FCOMPil_a32, + sf_FSUBil_a32, sf_FSUBil_a32, sf_FSUBil_a32, sf_FSUBil_a32, sf_FSUBil_a32, sf_FSUBil_a32, sf_FSUBil_a32, sf_FSUBil_a32, + sf_FSUBRil_a32, sf_FSUBRil_a32, sf_FSUBRil_a32, sf_FSUBRil_a32, sf_FSUBRil_a32, sf_FSUBRil_a32, sf_FSUBRil_a32, sf_FSUBRil_a32, + sf_FDIVil_a32, sf_FDIVil_a32, sf_FDIVil_a32, sf_FDIVil_a32, sf_FDIVil_a32, sf_FDIVil_a32, sf_FDIVil_a32, sf_FDIVil_a32, + sf_FDIVRil_a32, sf_FDIVRil_a32, sf_FDIVRil_a32, sf_FDIVRil_a32, sf_FDIVRil_a32, sf_FDIVRil_a32, sf_FDIVRil_a32, sf_FDIVRil_a32, + + sf_FADDil_a32, sf_FADDil_a32, sf_FADDil_a32, sf_FADDil_a32, sf_FADDil_a32, sf_FADDil_a32, sf_FADDil_a32, sf_FADDil_a32, + sf_FMULil_a32, sf_FMULil_a32, sf_FMULil_a32, sf_FMULil_a32, sf_FMULil_a32, sf_FMULil_a32, sf_FMULil_a32, sf_FMULil_a32, + sf_FCOMil_a32, sf_FCOMil_a32, sf_FCOMil_a32, sf_FCOMil_a32, sf_FCOMil_a32, sf_FCOMil_a32, sf_FCOMil_a32, sf_FCOMil_a32, + sf_FCOMPil_a32, sf_FCOMPil_a32, sf_FCOMPil_a32, sf_FCOMPil_a32, sf_FCOMPil_a32, sf_FCOMPil_a32, sf_FCOMPil_a32, sf_FCOMPil_a32, + sf_FSUBil_a32, sf_FSUBil_a32, sf_FSUBil_a32, sf_FSUBil_a32, sf_FSUBil_a32, sf_FSUBil_a32, sf_FSUBil_a32, sf_FSUBil_a32, + sf_FSUBRil_a32, sf_FSUBRil_a32, sf_FSUBRil_a32, sf_FSUBRil_a32, sf_FSUBRil_a32, sf_FSUBRil_a32, sf_FSUBRil_a32, sf_FSUBRil_a32, + sf_FDIVil_a32, sf_FDIVil_a32, sf_FDIVil_a32, sf_FDIVil_a32, sf_FDIVil_a32, sf_FDIVil_a32, sf_FDIVil_a32, sf_FDIVil_a32, + sf_FDIVRil_a32, sf_FDIVRil_a32, sf_FDIVRil_a32, sf_FDIVRil_a32, sf_FDIVRil_a32, sf_FDIVRil_a32, sf_FDIVRil_a32, sf_FDIVRil_a32, + + sf_FCMOVB, sf_FCMOVB, sf_FCMOVB, sf_FCMOVB, sf_FCMOVB, sf_FCMOVB, sf_FCMOVB, sf_FCMOVB, + sf_FCMOVE, sf_FCMOVE, sf_FCMOVE, sf_FCMOVE, sf_FCMOVE, sf_FCMOVE, sf_FCMOVE, sf_FCMOVE, + sf_FCMOVBE, sf_FCMOVBE, sf_FCMOVBE, sf_FCMOVBE, sf_FCMOVBE, sf_FCMOVBE, sf_FCMOVBE, sf_FCMOVBE, + sf_FCMOVU, sf_FCMOVU, sf_FCMOVU, sf_FCMOVU, sf_FCMOVU, sf_FCMOVU, sf_FCMOVU, sf_FCMOVU, + ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, + ILLEGAL_a32, sf_FUCOMPP, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, + ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, + ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, + // clang-format on +}; +# endif + +const OpFn OP_TABLE(sf_fpu_287_db_a16)[256] = { + // clang-format off + sf_FILDil_a16, sf_FILDil_a16, sf_FILDil_a16, sf_FILDil_a16, sf_FILDil_a16, sf_FILDil_a16, sf_FILDil_a16, sf_FILDil_a16, + ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, + sf_FISTil_a16, sf_FISTil_a16, sf_FISTil_a16, sf_FISTil_a16, sf_FISTil_a16, sf_FISTil_a16, sf_FISTil_a16, sf_FISTil_a16, + sf_FISTPil_a16, sf_FISTPil_a16, sf_FISTPil_a16, sf_FISTPil_a16, sf_FISTPil_a16, sf_FISTPil_a16, sf_FISTPil_a16, sf_FISTPil_a16, + ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, + sf_FLDe_a16, sf_FLDe_a16, sf_FLDe_a16, sf_FLDe_a16, sf_FLDe_a16, sf_FLDe_a16, sf_FLDe_a16, sf_FLDe_a16, + ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, + sf_FSTPe_a16, sf_FSTPe_a16, sf_FSTPe_a16, sf_FSTPe_a16, sf_FSTPe_a16, sf_FSTPe_a16, sf_FSTPe_a16, sf_FSTPe_a16, + + sf_FILDil_a16, sf_FILDil_a16, sf_FILDil_a16, sf_FILDil_a16, sf_FILDil_a16, sf_FILDil_a16, sf_FILDil_a16, sf_FILDil_a16, + ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, + sf_FISTil_a16, sf_FISTil_a16, sf_FISTil_a16, sf_FISTil_a16, sf_FISTil_a16, sf_FISTil_a16, sf_FISTil_a16, sf_FISTil_a16, + sf_FISTPil_a16, sf_FISTPil_a16, sf_FISTPil_a16, sf_FISTPil_a16, sf_FISTPil_a16, sf_FISTPil_a16, sf_FISTPil_a16, sf_FISTPil_a16, + ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, + sf_FLDe_a16, sf_FLDe_a16, sf_FLDe_a16, sf_FLDe_a16, sf_FLDe_a16, sf_FLDe_a16, sf_FLDe_a16, sf_FLDe_a16, + ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, + sf_FSTPe_a16, sf_FSTPe_a16, sf_FSTPe_a16, sf_FSTPe_a16, sf_FSTPe_a16, sf_FSTPe_a16, sf_FSTPe_a16, sf_FSTPe_a16, + + sf_FILDil_a16, sf_FILDil_a16, sf_FILDil_a16, sf_FILDil_a16, sf_FILDil_a16, sf_FILDil_a16, sf_FILDil_a16, sf_FILDil_a16, + ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, + sf_FISTil_a16, sf_FISTil_a16, sf_FISTil_a16, sf_FISTil_a16, sf_FISTil_a16, sf_FISTil_a16, sf_FISTil_a16, sf_FISTil_a16, + sf_FISTPil_a16, sf_FISTPil_a16, sf_FISTPil_a16, sf_FISTPil_a16, sf_FISTPil_a16, sf_FISTPil_a16, sf_FISTPil_a16, sf_FISTPil_a16, + ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, + sf_FLDe_a16, sf_FLDe_a16, sf_FLDe_a16, sf_FLDe_a16, sf_FLDe_a16, sf_FLDe_a16, sf_FLDe_a16, sf_FLDe_a16, + ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, + sf_FSTPe_a16, sf_FSTPe_a16, sf_FSTPe_a16, sf_FSTPe_a16, sf_FSTPe_a16, sf_FSTPe_a16, sf_FSTPe_a16, sf_FSTPe_a16, + + ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, + ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, + ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, + ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, + sf_FNOP, sf_FNOP, sf_FNCLEX, sf_FNINIT, sf_FNOP, sf_FNOP, ILLEGAL_a16, ILLEGAL_a16, + ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, + ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, + ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, + // clang-format on +}; + +const OpFn OP_TABLE(sf_fpu_287_db_a32)[256] = { + // clang-format off + sf_FILDil_a32, sf_FILDil_a32, sf_FILDil_a32, sf_FILDil_a32, sf_FILDil_a32, sf_FILDil_a32, sf_FILDil_a32, sf_FILDil_a32, + ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, + sf_FISTil_a32, sf_FISTil_a32, sf_FISTil_a32, sf_FISTil_a32, sf_FISTil_a32, sf_FISTil_a32, sf_FISTil_a32, sf_FISTil_a32, + sf_FISTPil_a32, sf_FISTPil_a32, sf_FISTPil_a32, sf_FISTPil_a32, sf_FISTPil_a32, sf_FISTPil_a32, sf_FISTPil_a32, sf_FISTPil_a32, + ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, + sf_FLDe_a32, sf_FLDe_a32, sf_FLDe_a32, sf_FLDe_a32, sf_FLDe_a32, sf_FLDe_a32, sf_FLDe_a32, sf_FLDe_a32, + ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, + sf_FSTPe_a32, sf_FSTPe_a32, sf_FSTPe_a32, sf_FSTPe_a32, sf_FSTPe_a32, sf_FSTPe_a32, sf_FSTPe_a32, sf_FSTPe_a32, + + sf_FILDil_a32, sf_FILDil_a32, sf_FILDil_a32, sf_FILDil_a32, sf_FILDil_a32, sf_FILDil_a32, sf_FILDil_a32, sf_FILDil_a32, + ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, + sf_FISTil_a32, sf_FISTil_a32, sf_FISTil_a32, sf_FISTil_a32, sf_FISTil_a32, sf_FISTil_a32, sf_FISTil_a32, sf_FISTil_a32, + sf_FISTPil_a32, sf_FISTPil_a32, sf_FISTPil_a32, sf_FISTPil_a32, sf_FISTPil_a32, sf_FISTPil_a32, sf_FISTPil_a32, sf_FISTPil_a32, + ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, + sf_FLDe_a32, sf_FLDe_a32, sf_FLDe_a32, sf_FLDe_a32, sf_FLDe_a32, sf_FLDe_a32, sf_FLDe_a32, sf_FLDe_a32, + ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, + sf_FSTPe_a32, sf_FSTPe_a32, sf_FSTPe_a32, sf_FSTPe_a32, sf_FSTPe_a32, sf_FSTPe_a32, sf_FSTPe_a32, sf_FSTPe_a32, + + sf_FILDil_a32, sf_FILDil_a32, sf_FILDil_a32, sf_FILDil_a32, sf_FILDil_a32, sf_FILDil_a32, sf_FILDil_a32, sf_FILDil_a32, + ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, + sf_FISTil_a32, sf_FISTil_a32, sf_FISTil_a32, sf_FISTil_a32, sf_FISTil_a32, sf_FISTil_a32, sf_FISTil_a32, sf_FISTil_a32, + sf_FISTPil_a32, sf_FISTPil_a32, sf_FISTPil_a32, sf_FISTPil_a32, sf_FISTPil_a32, sf_FISTPil_a32, sf_FISTPil_a32, sf_FISTPil_a32, + ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, + sf_FLDe_a32, sf_FLDe_a32, sf_FLDe_a32, sf_FLDe_a32, sf_FLDe_a32, sf_FLDe_a32, sf_FLDe_a32, sf_FLDe_a32, + ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, + sf_FSTPe_a32, sf_FSTPe_a32, sf_FSTPe_a32, sf_FSTPe_a32, sf_FSTPe_a32, sf_FSTPe_a32, sf_FSTPe_a32, sf_FSTPe_a32, + + ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, + ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, + ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, + ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, + sf_FNOP, sf_FNOP, sf_FNCLEX, sf_FNINIT, sf_FNOP, sf_FNOP, ILLEGAL_a32, ILLEGAL_a32, + ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, + ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, + ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, + // clang-format on +}; + +const OpFn OP_TABLE(sf_fpu_db_a16)[256] = { + // clang-format off + sf_FILDil_a16, sf_FILDil_a16, sf_FILDil_a16, sf_FILDil_a16, sf_FILDil_a16, sf_FILDil_a16, sf_FILDil_a16, sf_FILDil_a16, + ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, + sf_FISTil_a16, sf_FISTil_a16, sf_FISTil_a16, sf_FISTil_a16, sf_FISTil_a16, sf_FISTil_a16, sf_FISTil_a16, sf_FISTil_a16, + sf_FISTPil_a16, sf_FISTPil_a16, sf_FISTPil_a16, sf_FISTPil_a16, sf_FISTPil_a16, sf_FISTPil_a16, sf_FISTPil_a16, sf_FISTPil_a16, + ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, + sf_FLDe_a16, sf_FLDe_a16, sf_FLDe_a16, sf_FLDe_a16, sf_FLDe_a16, sf_FLDe_a16, sf_FLDe_a16, sf_FLDe_a16, + ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, + sf_FSTPe_a16, sf_FSTPe_a16, sf_FSTPe_a16, sf_FSTPe_a16, sf_FSTPe_a16, sf_FSTPe_a16, sf_FSTPe_a16, sf_FSTPe_a16, + + sf_FILDil_a16, sf_FILDil_a16, sf_FILDil_a16, sf_FILDil_a16, sf_FILDil_a16, sf_FILDil_a16, sf_FILDil_a16, sf_FILDil_a16, + ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, + sf_FISTil_a16, sf_FISTil_a16, sf_FISTil_a16, sf_FISTil_a16, sf_FISTil_a16, sf_FISTil_a16, sf_FISTil_a16, sf_FISTil_a16, + sf_FISTPil_a16, sf_FISTPil_a16, sf_FISTPil_a16, sf_FISTPil_a16, sf_FISTPil_a16, sf_FISTPil_a16, sf_FISTPil_a16, sf_FISTPil_a16, + ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, + sf_FLDe_a16, sf_FLDe_a16, sf_FLDe_a16, sf_FLDe_a16, sf_FLDe_a16, sf_FLDe_a16, sf_FLDe_a16, sf_FLDe_a16, + ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, + sf_FSTPe_a16, sf_FSTPe_a16, sf_FSTPe_a16, sf_FSTPe_a16, sf_FSTPe_a16, sf_FSTPe_a16, sf_FSTPe_a16, sf_FSTPe_a16, + + sf_FILDil_a16, sf_FILDil_a16, sf_FILDil_a16, sf_FILDil_a16, sf_FILDil_a16, sf_FILDil_a16, sf_FILDil_a16, sf_FILDil_a16, + ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, + sf_FISTil_a16, sf_FISTil_a16, sf_FISTil_a16, sf_FISTil_a16, sf_FISTil_a16, sf_FISTil_a16, sf_FISTil_a16, sf_FISTil_a16, + sf_FISTPil_a16, sf_FISTPil_a16, sf_FISTPil_a16, sf_FISTPil_a16, sf_FISTPil_a16, sf_FISTPil_a16, sf_FISTPil_a16, sf_FISTPil_a16, + ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, + sf_FLDe_a16, sf_FLDe_a16, sf_FLDe_a16, sf_FLDe_a16, sf_FLDe_a16, sf_FLDe_a16, sf_FLDe_a16, sf_FLDe_a16, + ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, + sf_FSTPe_a16, sf_FSTPe_a16, sf_FSTPe_a16, sf_FSTPe_a16, sf_FSTPe_a16, sf_FSTPe_a16, sf_FSTPe_a16, sf_FSTPe_a16, + + ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, + ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, + ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, + ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, + sf_FNOP, sf_FNOP, sf_FNCLEX, sf_FNINIT, sf_FNOP, sf_FNOP, ILLEGAL_a16, ILLEGAL_a16, + ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, + ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, + ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, + // clang-format on +}; + +const OpFn OP_TABLE(sf_fpu_db_a32)[256] = { + // clang-format off + sf_FILDil_a32, sf_FILDil_a32, sf_FILDil_a32, sf_FILDil_a32, sf_FILDil_a32, sf_FILDil_a32, sf_FILDil_a32, sf_FILDil_a32, + ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, + sf_FISTil_a32, sf_FISTil_a32, sf_FISTil_a32, sf_FISTil_a32, sf_FISTil_a32, sf_FISTil_a32, sf_FISTil_a32, sf_FISTil_a32, + sf_FISTPil_a32, sf_FISTPil_a32, sf_FISTPil_a32, sf_FISTPil_a32, sf_FISTPil_a32, sf_FISTPil_a32, sf_FISTPil_a32, sf_FISTPil_a32, + ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, + sf_FLDe_a32, sf_FLDe_a32, sf_FLDe_a32, sf_FLDe_a32, sf_FLDe_a32, sf_FLDe_a32, sf_FLDe_a32, sf_FLDe_a32, + ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, + sf_FSTPe_a32, sf_FSTPe_a32, sf_FSTPe_a32, sf_FSTPe_a32, sf_FSTPe_a32, sf_FSTPe_a32, sf_FSTPe_a32, sf_FSTPe_a32, + + sf_FILDil_a32, sf_FILDil_a32, sf_FILDil_a32, sf_FILDil_a32, sf_FILDil_a32, sf_FILDil_a32, sf_FILDil_a32, sf_FILDil_a32, + ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, + sf_FISTil_a32, sf_FISTil_a32, sf_FISTil_a32, sf_FISTil_a32, sf_FISTil_a32, sf_FISTil_a32, sf_FISTil_a32, sf_FISTil_a32, + sf_FISTPil_a32, sf_FISTPil_a32, sf_FISTPil_a32, sf_FISTPil_a32, sf_FISTPil_a32, sf_FISTPil_a32, sf_FISTPil_a32, sf_FISTPil_a32, + ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, + sf_FLDe_a32, sf_FLDe_a32, sf_FLDe_a32, sf_FLDe_a32, sf_FLDe_a32, sf_FLDe_a32, sf_FLDe_a32, sf_FLDe_a32, + ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, + sf_FSTPe_a32, sf_FSTPe_a32, sf_FSTPe_a32, sf_FSTPe_a32, sf_FSTPe_a32, sf_FSTPe_a32, sf_FSTPe_a32, sf_FSTPe_a32, + + sf_FILDil_a32, sf_FILDil_a32, sf_FILDil_a32, sf_FILDil_a32, sf_FILDil_a32, sf_FILDil_a32, sf_FILDil_a32, sf_FILDil_a32, + ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, + sf_FISTil_a32, sf_FISTil_a32, sf_FISTil_a32, sf_FISTil_a32, sf_FISTil_a32, sf_FISTil_a32, sf_FISTil_a32, sf_FISTil_a32, + sf_FISTPil_a32, sf_FISTPil_a32, sf_FISTPil_a32, sf_FISTPil_a32, sf_FISTPil_a32, sf_FISTPil_a32, sf_FISTPil_a32, sf_FISTPil_a32, + ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, + sf_FLDe_a32, sf_FLDe_a32, sf_FLDe_a32, sf_FLDe_a32, sf_FLDe_a32, sf_FLDe_a32, sf_FLDe_a32, sf_FLDe_a32, + ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, + sf_FSTPe_a32, sf_FSTPe_a32, sf_FSTPe_a32, sf_FSTPe_a32, sf_FSTPe_a32, sf_FSTPe_a32, sf_FSTPe_a32, sf_FSTPe_a32, + + ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, + ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, + ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, + ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, + sf_FNOP, sf_FNOP, sf_FNCLEX, sf_FNINIT, sf_FNOP, sf_FNOP, ILLEGAL_a32, ILLEGAL_a32, + ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, + ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, + ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, + // clang-format on +}; + +# ifndef OPS_286_386 +const OpFn OP_TABLE(sf_fpu_686_db_a16)[256] = { + // clang-format off + sf_FILDil_a16, sf_FILDil_a16, sf_FILDil_a16, sf_FILDil_a16, sf_FILDil_a16, sf_FILDil_a16, sf_FILDil_a16, sf_FILDil_a16, + ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, + sf_FISTil_a16, sf_FISTil_a16, sf_FISTil_a16, sf_FISTil_a16, sf_FISTil_a16, sf_FISTil_a16, sf_FISTil_a16, sf_FISTil_a16, + sf_FISTPil_a16, sf_FISTPil_a16, sf_FISTPil_a16, sf_FISTPil_a16, sf_FISTPil_a16, sf_FISTPil_a16, sf_FISTPil_a16, sf_FISTPil_a16, + ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, + sf_FLDe_a16, sf_FLDe_a16, sf_FLDe_a16, sf_FLDe_a16, sf_FLDe_a16, sf_FLDe_a16, sf_FLDe_a16, sf_FLDe_a16, + ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, + sf_FSTPe_a16, sf_FSTPe_a16, sf_FSTPe_a16, sf_FSTPe_a16, sf_FSTPe_a16, sf_FSTPe_a16, sf_FSTPe_a16, sf_FSTPe_a16, + + sf_FILDil_a16, sf_FILDil_a16, sf_FILDil_a16, sf_FILDil_a16, sf_FILDil_a16, sf_FILDil_a16, sf_FILDil_a16, sf_FILDil_a16, + ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, + sf_FISTil_a16, sf_FISTil_a16, sf_FISTil_a16, sf_FISTil_a16, sf_FISTil_a16, sf_FISTil_a16, sf_FISTil_a16, sf_FISTil_a16, + sf_FISTPil_a16, sf_FISTPil_a16, sf_FISTPil_a16, sf_FISTPil_a16, sf_FISTPil_a16, sf_FISTPil_a16, sf_FISTPil_a16, sf_FISTPil_a16, + ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, + sf_FLDe_a16, sf_FLDe_a16, sf_FLDe_a16, sf_FLDe_a16, sf_FLDe_a16, sf_FLDe_a16, sf_FLDe_a16, sf_FLDe_a16, + ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, + sf_FSTPe_a16, sf_FSTPe_a16, sf_FSTPe_a16, sf_FSTPe_a16, sf_FSTPe_a16, sf_FSTPe_a16, sf_FSTPe_a16, sf_FSTPe_a16, + + sf_FILDil_a16, sf_FILDil_a16, sf_FILDil_a16, sf_FILDil_a16, sf_FILDil_a16, sf_FILDil_a16, sf_FILDil_a16, sf_FILDil_a16, + ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, + sf_FISTil_a16, sf_FISTil_a16, sf_FISTil_a16, sf_FISTil_a16, sf_FISTil_a16, sf_FISTil_a16, sf_FISTil_a16, sf_FISTil_a16, + sf_FISTPil_a16, sf_FISTPil_a16, sf_FISTPil_a16, sf_FISTPil_a16, sf_FISTPil_a16, sf_FISTPil_a16, sf_FISTPil_a16, sf_FISTPil_a16, + ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, + sf_FLDe_a16, sf_FLDe_a16, sf_FLDe_a16, sf_FLDe_a16, sf_FLDe_a16, sf_FLDe_a16, sf_FLDe_a16, sf_FLDe_a16, + ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, + sf_FSTPe_a16, sf_FSTPe_a16, sf_FSTPe_a16, sf_FSTPe_a16, sf_FSTPe_a16, sf_FSTPe_a16, sf_FSTPe_a16, sf_FSTPe_a16, + + sf_FCMOVNB, sf_FCMOVNB, sf_FCMOVNB, sf_FCMOVNB, sf_FCMOVNB, sf_FCMOVNB, sf_FCMOVNB, sf_FCMOVNB, + sf_FCMOVNE, sf_FCMOVNE, sf_FCMOVNE, sf_FCMOVNE, sf_FCMOVNE, sf_FCMOVNE, sf_FCMOVNE, sf_FCMOVNE, + sf_FCMOVNBE, sf_FCMOVNBE, sf_FCMOVNBE, sf_FCMOVNBE, sf_FCMOVNBE, sf_FCMOVNBE, sf_FCMOVNBE, sf_FCMOVNBE, + sf_FCMOVNU, sf_FCMOVNU, sf_FCMOVNU, sf_FCMOVNU, sf_FCMOVNU, sf_FCMOVNU, sf_FCMOVNU, sf_FCMOVNU, + sf_FNOP, sf_FNOP, sf_FNCLEX, sf_FNINIT, sf_FNOP, sf_FNOP, ILLEGAL_a16, ILLEGAL_a16, + sf_FUCOMI_st0_stj, sf_FUCOMI_st0_stj, sf_FUCOMI_st0_stj, sf_FUCOMI_st0_stj, sf_FUCOMI_st0_stj, sf_FUCOMI_st0_stj, sf_FUCOMI_st0_stj, sf_FUCOMI_st0_stj, + sf_FCOMI_st0_stj, sf_FCOMI_st0_stj, sf_FCOMI_st0_stj, sf_FCOMI_st0_stj, sf_FCOMI_st0_stj, sf_FCOMI_st0_stj, sf_FCOMI_st0_stj, sf_FCOMI_st0_stj, + ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, + // clang-format on +}; +const OpFn OP_TABLE(sf_fpu_686_db_a32)[256] = { + // clang-format off + sf_FILDil_a32, sf_FILDil_a32, sf_FILDil_a32, sf_FILDil_a32, sf_FILDil_a32, sf_FILDil_a32, sf_FILDil_a32, sf_FILDil_a32, + ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, + sf_FISTil_a32, sf_FISTil_a32, sf_FISTil_a32, sf_FISTil_a32, sf_FISTil_a32, sf_FISTil_a32, sf_FISTil_a32, sf_FISTil_a32, + sf_FISTPil_a32, sf_FISTPil_a32, sf_FISTPil_a32, sf_FISTPil_a32, sf_FISTPil_a32, sf_FISTPil_a32, sf_FISTPil_a32, sf_FISTPil_a32, + ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, + sf_FLDe_a32, sf_FLDe_a32, sf_FLDe_a32, sf_FLDe_a32, sf_FLDe_a32, sf_FLDe_a32, sf_FLDe_a32, sf_FLDe_a32, + ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, + sf_FSTPe_a32, sf_FSTPe_a32, sf_FSTPe_a32, sf_FSTPe_a32, sf_FSTPe_a32, sf_FSTPe_a32, sf_FSTPe_a32, sf_FSTPe_a32, + + sf_FILDil_a32, sf_FILDil_a32, sf_FILDil_a32, sf_FILDil_a32, sf_FILDil_a32, sf_FILDil_a32, sf_FILDil_a32, sf_FILDil_a32, + ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, + sf_FISTil_a32, sf_FISTil_a32, sf_FISTil_a32, sf_FISTil_a32, sf_FISTil_a32, sf_FISTil_a32, sf_FISTil_a32, sf_FISTil_a32, + sf_FISTPil_a32, sf_FISTPil_a32, sf_FISTPil_a32, sf_FISTPil_a32, sf_FISTPil_a32, sf_FISTPil_a32, sf_FISTPil_a32, sf_FISTPil_a32, + ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, + sf_FLDe_a32, sf_FLDe_a32, sf_FLDe_a32, sf_FLDe_a32, sf_FLDe_a32, sf_FLDe_a32, sf_FLDe_a32, sf_FLDe_a32, + ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, + sf_FSTPe_a32, sf_FSTPe_a32, sf_FSTPe_a32, sf_FSTPe_a32, sf_FSTPe_a32, sf_FSTPe_a32, sf_FSTPe_a32, sf_FSTPe_a32, + + sf_FILDil_a32, sf_FILDil_a32, sf_FILDil_a32, sf_FILDil_a32, sf_FILDil_a32, sf_FILDil_a32, sf_FILDil_a32, sf_FILDil_a32, + ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, + sf_FISTil_a32, sf_FISTil_a32, sf_FISTil_a32, sf_FISTil_a32, sf_FISTil_a32, sf_FISTil_a32, sf_FISTil_a32, sf_FISTil_a32, + sf_FISTPil_a32, sf_FISTPil_a32, sf_FISTPil_a32, sf_FISTPil_a32, sf_FISTPil_a32, sf_FISTPil_a32, sf_FISTPil_a32, sf_FISTPil_a32, + ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, + sf_FLDe_a32, sf_FLDe_a32, sf_FLDe_a32, sf_FLDe_a32, sf_FLDe_a32, sf_FLDe_a32, sf_FLDe_a32, sf_FLDe_a32, + ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, + sf_FSTPe_a32, sf_FSTPe_a32, sf_FSTPe_a32, sf_FSTPe_a32, sf_FSTPe_a32, sf_FSTPe_a32, sf_FSTPe_a32, sf_FSTPe_a32, + + sf_FCMOVNB, sf_FCMOVNB, sf_FCMOVNB, sf_FCMOVNB, sf_FCMOVNB, sf_FCMOVNB, sf_FCMOVNB, sf_FCMOVNB, + sf_FCMOVNE, sf_FCMOVNE, sf_FCMOVNE, sf_FCMOVNE, sf_FCMOVNE, sf_FCMOVNE, sf_FCMOVNE, sf_FCMOVNE, + sf_FCMOVNBE, sf_FCMOVNBE, sf_FCMOVNBE, sf_FCMOVNBE, sf_FCMOVNBE, sf_FCMOVNBE, sf_FCMOVNBE, sf_FCMOVNBE, + sf_FCMOVNU, sf_FCMOVNU, sf_FCMOVNU, sf_FCMOVNU, sf_FCMOVNU, sf_FCMOVNU, sf_FCMOVNU, sf_FCMOVNU, + sf_FNOP, sf_FNOP, sf_FNCLEX, sf_FNINIT, sf_FNOP, sf_FNOP, ILLEGAL_a32, ILLEGAL_a32, + sf_FUCOMI_st0_stj, sf_FUCOMI_st0_stj, sf_FUCOMI_st0_stj, sf_FUCOMI_st0_stj, sf_FUCOMI_st0_stj, sf_FUCOMI_st0_stj, sf_FUCOMI_st0_stj, sf_FUCOMI_st0_stj, + sf_FCOMI_st0_stj, sf_FCOMI_st0_stj, sf_FCOMI_st0_stj, sf_FCOMI_st0_stj, sf_FCOMI_st0_stj, sf_FCOMI_st0_stj, sf_FCOMI_st0_stj, sf_FCOMI_st0_stj, + ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, + // clang-format on +}; +# endif + +const OpFn OP_TABLE(sf_fpu_287_dc_a16)[32] = { + // clang-format off + sf_FADDd_a16, sf_FMULd_a16, sf_FCOMd_a16, sf_FCOMPd_a16, sf_FSUBd_a16, sf_FSUBRd_a16, sf_FDIVd_a16, sf_FDIVRd_a16, + sf_FADDd_a16, sf_FMULd_a16, sf_FCOMd_a16, sf_FCOMPd_a16, sf_FSUBd_a16, sf_FSUBRd_a16, sf_FDIVd_a16, sf_FDIVRd_a16, + sf_FADDd_a16, sf_FMULd_a16, sf_FCOMd_a16, sf_FCOMPd_a16, sf_FSUBd_a16, sf_FSUBRd_a16, sf_FDIVd_a16, sf_FDIVRd_a16, + sf_FADD_sti_st0, sf_FMUL_sti_st0, ILLEGAL_a16, ILLEGAL_a16, sf_FSUBR_sti_st0, sf_FSUB_sti_st0, sf_FDIVR_sti_st0, sf_FDIV_sti_st0, + // clang-format on +}; + +const OpFn OP_TABLE(sf_fpu_287_dc_a32)[32] = { + // clang-format off + sf_FADDd_a32, sf_FMULd_a32, sf_FCOMd_a32, sf_FCOMPd_a32, sf_FSUBd_a32, sf_FSUBRd_a32, sf_FDIVd_a32, sf_FDIVRd_a32, + sf_FADDd_a32, sf_FMULd_a32, sf_FCOMd_a32, sf_FCOMPd_a32, sf_FSUBd_a32, sf_FSUBRd_a32, sf_FDIVd_a32, sf_FDIVRd_a32, + sf_FADDd_a32, sf_FMULd_a32, sf_FCOMd_a32, sf_FCOMPd_a32, sf_FSUBd_a32, sf_FSUBRd_a32, sf_FDIVd_a32, sf_FDIVRd_a32, + sf_FADD_sti_st0, sf_FMUL_sti_st0, ILLEGAL_a32, ILLEGAL_a32, sf_FSUBR_sti_st0, sf_FSUB_sti_st0, sf_FDIVR_sti_st0, sf_FDIV_sti_st0, + // clang-format on +}; + +const OpFn OP_TABLE(sf_fpu_dc_a16)[32] = { + // clang-format off + sf_FADDd_a16, sf_FMULd_a16, sf_FCOMd_a16, sf_FCOMPd_a16, sf_FSUBd_a16, sf_FSUBRd_a16, sf_FDIVd_a16, sf_FDIVRd_a16, + sf_FADDd_a16, sf_FMULd_a16, sf_FCOMd_a16, sf_FCOMPd_a16, sf_FSUBd_a16, sf_FSUBRd_a16, sf_FDIVd_a16, sf_FDIVRd_a16, + sf_FADDd_a16, sf_FMULd_a16, sf_FCOMd_a16, sf_FCOMPd_a16, sf_FSUBd_a16, sf_FSUBRd_a16, sf_FDIVd_a16, sf_FDIVRd_a16, + sf_FADD_sti_st0, sf_FMUL_sti_st0, sf_FCOM_sti, sf_FCOMP_sti, sf_FSUBR_sti_st0, sf_FSUB_sti_st0, sf_FDIVR_sti_st0, sf_FDIV_sti_st0, + // clang-format on +}; + +const OpFn OP_TABLE(sf_fpu_dc_a32)[32] = { + // clang-format off + sf_FADDd_a32, sf_FMULd_a32, sf_FCOMd_a32, sf_FCOMPd_a32, sf_FSUBd_a32, sf_FSUBRd_a32, sf_FDIVd_a32, sf_FDIVRd_a32, + sf_FADDd_a32, sf_FMULd_a32, sf_FCOMd_a32, sf_FCOMPd_a32, sf_FSUBd_a32, sf_FSUBRd_a32, sf_FDIVd_a32, sf_FDIVRd_a32, + sf_FADDd_a32, sf_FMULd_a32, sf_FCOMd_a32, sf_FCOMPd_a32, sf_FSUBd_a32, sf_FSUBRd_a32, sf_FDIVd_a32, sf_FDIVRd_a32, + sf_FADD_sti_st0, sf_FMUL_sti_st0, sf_FCOM_sti, sf_FCOMP_sti, sf_FSUBR_sti_st0, sf_FSUB_sti_st0, sf_FDIVR_sti_st0, sf_FDIV_sti_st0, + // clang-format on +}; + +const OpFn OP_TABLE(sf_fpu_287_dd_a16)[256] = { + // clang-format off + sf_FLDd_a16, sf_FLDd_a16, sf_FLDd_a16, sf_FLDd_a16, sf_FLDd_a16, sf_FLDd_a16, sf_FLDd_a16, sf_FLDd_a16, + ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, + sf_FSTd_a16, sf_FSTd_a16, sf_FSTd_a16, sf_FSTd_a16, sf_FSTd_a16, sf_FSTd_a16, sf_FSTd_a16, sf_FSTd_a16, + sf_FSTPd_a16, sf_FSTPd_a16, sf_FSTPd_a16, sf_FSTPd_a16, sf_FSTPd_a16, sf_FSTPd_a16, sf_FSTPd_a16, sf_FSTPd_a16, + sf_FRSTOR_a16, sf_FRSTOR_a16, sf_FRSTOR_a16, sf_FRSTOR_a16, sf_FRSTOR_a16, sf_FRSTOR_a16, sf_FRSTOR_a16, sf_FRSTOR_a16, + ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, + sf_FNSAVE_a16, sf_FNSAVE_a16, sf_FNSAVE_a16, sf_FNSAVE_a16, sf_FNSAVE_a16, sf_FNSAVE_a16, sf_FNSAVE_a16, sf_FNSAVE_a16, + sf_FNSTSW_a16, sf_FNSTSW_a16, sf_FNSTSW_a16, sf_FNSTSW_a16, sf_FNSTSW_a16, sf_FNSTSW_a16, sf_FNSTSW_a16, sf_FNSTSW_a16, + + sf_FLDd_a16, sf_FLDd_a16, sf_FLDd_a16, sf_FLDd_a16, sf_FLDd_a16, sf_FLDd_a16, sf_FLDd_a16, sf_FLDd_a16, + ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, + sf_FSTd_a16, sf_FSTd_a16, sf_FSTd_a16, sf_FSTd_a16, sf_FSTd_a16, sf_FSTd_a16, sf_FSTd_a16, sf_FSTd_a16, + sf_FSTPd_a16, sf_FSTPd_a16, sf_FSTPd_a16, sf_FSTPd_a16, sf_FSTPd_a16, sf_FSTPd_a16, sf_FSTPd_a16, sf_FSTPd_a16, + sf_FRSTOR_a16, sf_FRSTOR_a16, sf_FRSTOR_a16, sf_FRSTOR_a16, sf_FRSTOR_a16, sf_FRSTOR_a16, sf_FRSTOR_a16, sf_FRSTOR_a16, + ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, + sf_FNSAVE_a16, sf_FNSAVE_a16, sf_FNSAVE_a16, sf_FNSAVE_a16, sf_FNSAVE_a16, sf_FNSAVE_a16, sf_FNSAVE_a16, sf_FNSAVE_a16, + sf_FNSTSW_a16, sf_FNSTSW_a16, sf_FNSTSW_a16, sf_FNSTSW_a16, sf_FNSTSW_a16, sf_FNSTSW_a16, sf_FNSTSW_a16, sf_FNSTSW_a16, + + sf_FLDd_a16, sf_FLDd_a16, sf_FLDd_a16, sf_FLDd_a16, sf_FLDd_a16, sf_FLDd_a16, sf_FLDd_a16, sf_FLDd_a16, + ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, + sf_FSTd_a16, sf_FSTd_a16, sf_FSTd_a16, sf_FSTd_a16, sf_FSTd_a16, sf_FSTd_a16, sf_FSTd_a16, sf_FSTd_a16, + sf_FSTPd_a16, sf_FSTPd_a16, sf_FSTPd_a16, sf_FSTPd_a16, sf_FSTPd_a16, sf_FSTPd_a16, sf_FSTPd_a16, sf_FSTPd_a16, + sf_FRSTOR_a16, sf_FRSTOR_a16, sf_FRSTOR_a16, sf_FRSTOR_a16, sf_FRSTOR_a16, sf_FRSTOR_a16, sf_FRSTOR_a16, sf_FRSTOR_a16, + ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, + sf_FNSAVE_a16, sf_FNSAVE_a16, sf_FNSAVE_a16, sf_FNSAVE_a16, sf_FNSAVE_a16, sf_FNSAVE_a16, sf_FNSAVE_a16, sf_FNSAVE_a16, + sf_FNSTSW_a16, sf_FNSTSW_a16, sf_FNSTSW_a16, sf_FNSTSW_a16, sf_FNSTSW_a16, sf_FNSTSW_a16, sf_FNSTSW_a16, sf_FNSTSW_a16, + + sf_FFREE_sti, sf_FFREE_sti, sf_FFREE_sti, sf_FFREE_sti, sf_FFREE_sti, sf_FFREE_sti, sf_FFREE_sti, sf_FFREE_sti, + ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, + sf_FST_sti, sf_FST_sti, sf_FST_sti, sf_FST_sti, sf_FST_sti, sf_FST_sti, sf_FST_sti, sf_FST_sti, + sf_FSTP_sti, sf_FSTP_sti, sf_FSTP_sti, sf_FSTP_sti, sf_FSTP_sti, sf_FSTP_sti, sf_FSTP_sti, sf_FSTP_sti, + ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, + ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, + ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, + ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, + // clang-format on +}; + +const OpFn OP_TABLE(sf_fpu_287_dd_a32)[256] = { + // clang-format off + sf_FLDd_a32, sf_FLDd_a32, sf_FLDd_a32, sf_FLDd_a32, sf_FLDd_a32, sf_FLDd_a32, sf_FLDd_a32, sf_FLDd_a32, + ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, + sf_FSTd_a32, sf_FSTd_a32, sf_FSTd_a32, sf_FSTd_a32, sf_FSTd_a32, sf_FSTd_a32, sf_FSTd_a32, sf_FSTd_a32, + sf_FSTPd_a32, sf_FSTPd_a32, sf_FSTPd_a32, sf_FSTPd_a32, sf_FSTPd_a32, sf_FSTPd_a32, sf_FSTPd_a32, sf_FSTPd_a32, + sf_FRSTOR_a32, sf_FRSTOR_a32, sf_FRSTOR_a32, sf_FRSTOR_a32, sf_FRSTOR_a32, sf_FRSTOR_a32, sf_FRSTOR_a32, sf_FRSTOR_a32, + ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, + sf_FNSAVE_a32, sf_FNSAVE_a32, sf_FNSAVE_a32, sf_FNSAVE_a32, sf_FNSAVE_a32, sf_FNSAVE_a32, sf_FNSAVE_a32, sf_FNSAVE_a32, + sf_FNSTSW_a32, sf_FNSTSW_a32, sf_FNSTSW_a32, sf_FNSTSW_a32, sf_FNSTSW_a32, sf_FNSTSW_a32, sf_FNSTSW_a32, sf_FNSTSW_a32, + + sf_FLDd_a32, sf_FLDd_a32, sf_FLDd_a32, sf_FLDd_a32, sf_FLDd_a32, sf_FLDd_a32, sf_FLDd_a32, sf_FLDd_a32, + ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, + sf_FSTd_a32, sf_FSTd_a32, sf_FSTd_a32, sf_FSTd_a32, sf_FSTd_a32, sf_FSTd_a32, sf_FSTd_a32, sf_FSTd_a32, + sf_FSTPd_a32, sf_FSTPd_a32, sf_FSTPd_a32, sf_FSTPd_a32, sf_FSTPd_a32, sf_FSTPd_a32, sf_FSTPd_a32, sf_FSTPd_a32, + sf_FRSTOR_a32, sf_FRSTOR_a32, sf_FRSTOR_a32, sf_FRSTOR_a32, sf_FRSTOR_a32, sf_FRSTOR_a32, sf_FRSTOR_a32, sf_FRSTOR_a32, + ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, + sf_FNSAVE_a32, sf_FNSAVE_a32, sf_FNSAVE_a32, sf_FNSAVE_a32, sf_FNSAVE_a32, sf_FNSAVE_a32, sf_FNSAVE_a32, sf_FNSAVE_a32, + sf_FNSTSW_a32, sf_FNSTSW_a32, sf_FNSTSW_a32, sf_FNSTSW_a32, sf_FNSTSW_a32, sf_FNSTSW_a32, sf_FNSTSW_a32, sf_FNSTSW_a32, + + sf_FLDd_a32, sf_FLDd_a32, sf_FLDd_a32, sf_FLDd_a32, sf_FLDd_a32, sf_FLDd_a32, sf_FLDd_a32, sf_FLDd_a32, + ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, + sf_FSTd_a32, sf_FSTd_a32, sf_FSTd_a32, sf_FSTd_a32, sf_FSTd_a32, sf_FSTd_a32, sf_FSTd_a32, sf_FSTd_a32, + sf_FSTPd_a32, sf_FSTPd_a32, sf_FSTPd_a32, sf_FSTPd_a32, sf_FSTPd_a32, sf_FSTPd_a32, sf_FSTPd_a32, sf_FSTPd_a32, + sf_FRSTOR_a32, sf_FRSTOR_a32, sf_FRSTOR_a32, sf_FRSTOR_a32, sf_FRSTOR_a32, sf_FRSTOR_a32, sf_FRSTOR_a32, sf_FRSTOR_a32, + ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, + sf_FNSAVE_a32, sf_FNSAVE_a32, sf_FNSAVE_a32, sf_FNSAVE_a32, sf_FNSAVE_a32, sf_FNSAVE_a32, sf_FNSAVE_a32, sf_FNSAVE_a32, + sf_FNSTSW_a32, sf_FNSTSW_a32, sf_FNSTSW_a32, sf_FNSTSW_a32, sf_FNSTSW_a32, sf_FNSTSW_a32, sf_FNSTSW_a32, sf_FNSTSW_a32, + + sf_FFREE_sti, sf_FFREE_sti, sf_FFREE_sti, sf_FFREE_sti, sf_FFREE_sti, sf_FFREE_sti, sf_FFREE_sti, sf_FFREE_sti, + ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, + sf_FST_sti, sf_FST_sti, sf_FST_sti, sf_FST_sti, sf_FST_sti, sf_FST_sti, sf_FST_sti, sf_FST_sti, + sf_FSTP_sti, sf_FSTP_sti, sf_FSTP_sti, sf_FSTP_sti, sf_FSTP_sti, sf_FSTP_sti, sf_FSTP_sti, sf_FSTP_sti, + ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, + ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, + ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, + ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, + // clang-format on +}; + +const OpFn OP_TABLE(sf_fpu_dd_a16)[256] = { + // clang-format off + sf_FLDd_a16, sf_FLDd_a16, sf_FLDd_a16, sf_FLDd_a16, sf_FLDd_a16, sf_FLDd_a16, sf_FLDd_a16, sf_FLDd_a16, + ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, + sf_FSTd_a16, sf_FSTd_a16, sf_FSTd_a16, sf_FSTd_a16, sf_FSTd_a16, sf_FSTd_a16, sf_FSTd_a16, sf_FSTd_a16, + sf_FSTPd_a16, sf_FSTPd_a16, sf_FSTPd_a16, sf_FSTPd_a16, sf_FSTPd_a16, sf_FSTPd_a16, sf_FSTPd_a16, sf_FSTPd_a16, + sf_FRSTOR_a16, sf_FRSTOR_a16, sf_FRSTOR_a16, sf_FRSTOR_a16, sf_FRSTOR_a16, sf_FRSTOR_a16, sf_FRSTOR_a16, sf_FRSTOR_a16, + ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, + sf_FNSAVE_a16, sf_FNSAVE_a16, sf_FNSAVE_a16, sf_FNSAVE_a16, sf_FNSAVE_a16, sf_FNSAVE_a16, sf_FNSAVE_a16, sf_FNSAVE_a16, + sf_FNSTSW_a16, sf_FNSTSW_a16, sf_FNSTSW_a16, sf_FNSTSW_a16, sf_FNSTSW_a16, sf_FNSTSW_a16, sf_FNSTSW_a16, sf_FNSTSW_a16, + + sf_FLDd_a16, sf_FLDd_a16, sf_FLDd_a16, sf_FLDd_a16, sf_FLDd_a16, sf_FLDd_a16, sf_FLDd_a16, sf_FLDd_a16, + ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, + sf_FSTd_a16, sf_FSTd_a16, sf_FSTd_a16, sf_FSTd_a16, sf_FSTd_a16, sf_FSTd_a16, sf_FSTd_a16, sf_FSTd_a16, + sf_FSTPd_a16, sf_FSTPd_a16, sf_FSTPd_a16, sf_FSTPd_a16, sf_FSTPd_a16, sf_FSTPd_a16, sf_FSTPd_a16, sf_FSTPd_a16, + sf_FRSTOR_a16, sf_FRSTOR_a16, sf_FRSTOR_a16, sf_FRSTOR_a16, sf_FRSTOR_a16, sf_FRSTOR_a16, sf_FRSTOR_a16, sf_FRSTOR_a16, + ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, + sf_FNSAVE_a16, sf_FNSAVE_a16, sf_FNSAVE_a16, sf_FNSAVE_a16, sf_FNSAVE_a16, sf_FNSAVE_a16, sf_FNSAVE_a16, sf_FNSAVE_a16, + sf_FNSTSW_a16, sf_FNSTSW_a16, sf_FNSTSW_a16, sf_FNSTSW_a16, sf_FNSTSW_a16, sf_FNSTSW_a16, sf_FNSTSW_a16, sf_FNSTSW_a16, + + sf_FLDd_a16, sf_FLDd_a16, sf_FLDd_a16, sf_FLDd_a16, sf_FLDd_a16, sf_FLDd_a16, sf_FLDd_a16, sf_FLDd_a16, + ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, + sf_FSTd_a16, sf_FSTd_a16, sf_FSTd_a16, sf_FSTd_a16, sf_FSTd_a16, sf_FSTd_a16, sf_FSTd_a16, sf_FSTd_a16, + sf_FSTPd_a16, sf_FSTPd_a16, sf_FSTPd_a16, sf_FSTPd_a16, sf_FSTPd_a16, sf_FSTPd_a16, sf_FSTPd_a16, sf_FSTPd_a16, + sf_FRSTOR_a16, sf_FRSTOR_a16, sf_FRSTOR_a16, sf_FRSTOR_a16, sf_FRSTOR_a16, sf_FRSTOR_a16, sf_FRSTOR_a16, sf_FRSTOR_a16, + ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, + sf_FNSAVE_a16, sf_FNSAVE_a16, sf_FNSAVE_a16, sf_FNSAVE_a16, sf_FNSAVE_a16, sf_FNSAVE_a16, sf_FNSAVE_a16, sf_FNSAVE_a16, + sf_FNSTSW_a16, sf_FNSTSW_a16, sf_FNSTSW_a16, sf_FNSTSW_a16, sf_FNSTSW_a16, sf_FNSTSW_a16, sf_FNSTSW_a16, sf_FNSTSW_a16, + + sf_FFREE_sti, sf_FFREE_sti, sf_FFREE_sti, sf_FFREE_sti, sf_FFREE_sti, sf_FFREE_sti, sf_FFREE_sti, sf_FFREE_sti, + sf_FXCH_sti, sf_FXCH_sti, sf_FXCH_sti, sf_FXCH_sti, sf_FXCH_sti, sf_FXCH_sti, sf_FXCH_sti, sf_FXCH_sti, + sf_FST_sti, sf_FST_sti, sf_FST_sti, sf_FST_sti, sf_FST_sti, sf_FST_sti, sf_FST_sti, sf_FST_sti, + sf_FSTP_sti, sf_FSTP_sti, sf_FSTP_sti, sf_FSTP_sti, sf_FSTP_sti, sf_FSTP_sti, sf_FSTP_sti, sf_FSTP_sti, + sf_FUCOM_sti, sf_FUCOM_sti, sf_FUCOM_sti, sf_FUCOM_sti, sf_FUCOM_sti, sf_FUCOM_sti, sf_FUCOM_sti, sf_FUCOM_sti, + sf_FUCOMP_sti, sf_FUCOMP_sti, sf_FUCOMP_sti, sf_FUCOMP_sti, sf_FUCOMP_sti, sf_FUCOMP_sti, sf_FUCOMP_sti, sf_FUCOMP_sti, + ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, + ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, + // clang-format on +}; + +const OpFn OP_TABLE(sf_fpu_dd_a32)[256] = { + // clang-format off + sf_FLDd_a32, sf_FLDd_a32, sf_FLDd_a32, sf_FLDd_a32, sf_FLDd_a32, sf_FLDd_a32, sf_FLDd_a32, sf_FLDd_a32, + ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, + sf_FSTd_a32, sf_FSTd_a32, sf_FSTd_a32, sf_FSTd_a32, sf_FSTd_a32, sf_FSTd_a32, sf_FSTd_a32, sf_FSTd_a32, + sf_FSTPd_a32, sf_FSTPd_a32, sf_FSTPd_a32, sf_FSTPd_a32, sf_FSTPd_a32, sf_FSTPd_a32, sf_FSTPd_a32, sf_FSTPd_a32, + sf_FRSTOR_a32, sf_FRSTOR_a32, sf_FRSTOR_a32, sf_FRSTOR_a32, sf_FRSTOR_a32, sf_FRSTOR_a32, sf_FRSTOR_a32, sf_FRSTOR_a32, + ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, + sf_FNSAVE_a32, sf_FNSAVE_a32, sf_FNSAVE_a32, sf_FNSAVE_a32, sf_FNSAVE_a32, sf_FNSAVE_a32, sf_FNSAVE_a32, sf_FNSAVE_a32, + sf_FNSTSW_a32, sf_FNSTSW_a32, sf_FNSTSW_a32, sf_FNSTSW_a32, sf_FNSTSW_a32, sf_FNSTSW_a32, sf_FNSTSW_a32, sf_FNSTSW_a32, + + sf_FLDd_a32, sf_FLDd_a32, sf_FLDd_a32, sf_FLDd_a32, sf_FLDd_a32, sf_FLDd_a32, sf_FLDd_a32, sf_FLDd_a32, + ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, + sf_FSTd_a32, sf_FSTd_a32, sf_FSTd_a32, sf_FSTd_a32, sf_FSTd_a32, sf_FSTd_a32, sf_FSTd_a32, sf_FSTd_a32, + sf_FSTPd_a32, sf_FSTPd_a32, sf_FSTPd_a32, sf_FSTPd_a32, sf_FSTPd_a32, sf_FSTPd_a32, sf_FSTPd_a32, sf_FSTPd_a32, + sf_FRSTOR_a32, sf_FRSTOR_a32, sf_FRSTOR_a32, sf_FRSTOR_a32, sf_FRSTOR_a32, sf_FRSTOR_a32, sf_FRSTOR_a32, sf_FRSTOR_a32, + ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, + sf_FNSAVE_a32, sf_FNSAVE_a32, sf_FNSAVE_a32, sf_FNSAVE_a32, sf_FNSAVE_a32, sf_FNSAVE_a32, sf_FNSAVE_a32, sf_FNSAVE_a32, + sf_FNSTSW_a32, sf_FNSTSW_a32, sf_FNSTSW_a32, sf_FNSTSW_a32, sf_FNSTSW_a32, sf_FNSTSW_a32, sf_FNSTSW_a32, sf_FNSTSW_a32, + + sf_FLDd_a32, sf_FLDd_a32, sf_FLDd_a32, sf_FLDd_a32, sf_FLDd_a32, sf_FLDd_a32, sf_FLDd_a32, sf_FLDd_a32, + ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, + sf_FSTd_a32, sf_FSTd_a32, sf_FSTd_a32, sf_FSTd_a32, sf_FSTd_a32, sf_FSTd_a32, sf_FSTd_a32, sf_FSTd_a32, + sf_FSTPd_a32, sf_FSTPd_a32, sf_FSTPd_a32, sf_FSTPd_a32, sf_FSTPd_a32, sf_FSTPd_a32, sf_FSTPd_a32, sf_FSTPd_a32, + sf_FRSTOR_a32, sf_FRSTOR_a32, sf_FRSTOR_a32, sf_FRSTOR_a32, sf_FRSTOR_a32, sf_FRSTOR_a32, sf_FRSTOR_a32, sf_FRSTOR_a32, + ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, + sf_FNSAVE_a32, sf_FNSAVE_a32, sf_FNSAVE_a32, sf_FNSAVE_a32, sf_FNSAVE_a32, sf_FNSAVE_a32, sf_FNSAVE_a32, sf_FNSAVE_a32, + sf_FNSTSW_a32, sf_FNSTSW_a32, sf_FNSTSW_a32, sf_FNSTSW_a32, sf_FNSTSW_a32, sf_FNSTSW_a32, sf_FNSTSW_a32, sf_FNSTSW_a32, + + sf_FFREE_sti, sf_FFREE_sti, sf_FFREE_sti, sf_FFREE_sti, sf_FFREE_sti, sf_FFREE_sti, sf_FFREE_sti, sf_FFREE_sti, + sf_FXCH_sti, sf_FXCH_sti, sf_FXCH_sti, sf_FXCH_sti, sf_FXCH_sti, sf_FXCH_sti, sf_FXCH_sti, sf_FXCH_sti, + sf_FST_sti, sf_FST_sti, sf_FST_sti, sf_FST_sti, sf_FST_sti, sf_FST_sti, sf_FST_sti, sf_FST_sti, + sf_FSTP_sti, sf_FSTP_sti, sf_FSTP_sti, sf_FSTP_sti, sf_FSTP_sti, sf_FSTP_sti, sf_FSTP_sti, sf_FSTP_sti, + sf_FUCOM_sti, sf_FUCOM_sti, sf_FUCOM_sti, sf_FUCOM_sti, sf_FUCOM_sti, sf_FUCOM_sti, sf_FUCOM_sti, sf_FUCOM_sti, + sf_FUCOMP_sti, sf_FUCOMP_sti, sf_FUCOMP_sti, sf_FUCOMP_sti, sf_FUCOMP_sti, sf_FUCOMP_sti, sf_FUCOMP_sti, sf_FUCOMP_sti, + ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, + ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, + // clang-format on +}; + +const OpFn OP_TABLE(sf_fpu_287_de_a16)[256] = { + // clang-format off + sf_FADDiw_a16, sf_FADDiw_a16, sf_FADDiw_a16, sf_FADDiw_a16, sf_FADDiw_a16, sf_FADDiw_a16, sf_FADDiw_a16, sf_FADDiw_a16, + sf_FMULiw_a16, sf_FMULiw_a16, sf_FMULiw_a16, sf_FMULiw_a16, sf_FMULiw_a16, sf_FMULiw_a16, sf_FMULiw_a16, sf_FMULiw_a16, + sf_FCOMiw_a16, sf_FCOMiw_a16, sf_FCOMiw_a16, sf_FCOMiw_a16, sf_FCOMiw_a16, sf_FCOMiw_a16, sf_FCOMiw_a16, sf_FCOMiw_a16, + sf_FCOMPiw_a16, sf_FCOMPiw_a16, sf_FCOMPiw_a16, sf_FCOMPiw_a16, sf_FCOMPiw_a16, sf_FCOMPiw_a16, sf_FCOMPiw_a16, sf_FCOMPiw_a16, + sf_FSUBiw_a16, sf_FSUBiw_a16, sf_FSUBiw_a16, sf_FSUBiw_a16, sf_FSUBiw_a16, sf_FSUBiw_a16, sf_FSUBiw_a16, sf_FSUBiw_a16, + sf_FSUBRiw_a16, sf_FSUBRiw_a16, sf_FSUBRiw_a16, sf_FSUBRiw_a16, sf_FSUBRiw_a16, sf_FSUBRiw_a16, sf_FSUBRiw_a16, sf_FSUBRiw_a16, + sf_FDIViw_a16, sf_FDIViw_a16, sf_FDIViw_a16, sf_FDIViw_a16, sf_FDIViw_a16, sf_FDIViw_a16, sf_FDIViw_a16, sf_FDIViw_a16, + sf_FDIVRiw_a16, sf_FDIVRiw_a16, sf_FDIVRiw_a16, sf_FDIVRiw_a16, sf_FDIVRiw_a16, sf_FDIVRiw_a16, sf_FDIVRiw_a16, sf_FDIVRiw_a16, + + sf_FADDiw_a16, sf_FADDiw_a16, sf_FADDiw_a16, sf_FADDiw_a16, sf_FADDiw_a16, sf_FADDiw_a16, sf_FADDiw_a16, sf_FADDiw_a16, + sf_FMULiw_a16, sf_FMULiw_a16, sf_FMULiw_a16, sf_FMULiw_a16, sf_FMULiw_a16, sf_FMULiw_a16, sf_FMULiw_a16, sf_FMULiw_a16, + sf_FCOMiw_a16, sf_FCOMiw_a16, sf_FCOMiw_a16, sf_FCOMiw_a16, sf_FCOMiw_a16, sf_FCOMiw_a16, sf_FCOMiw_a16, sf_FCOMiw_a16, + sf_FCOMPiw_a16, sf_FCOMPiw_a16, sf_FCOMPiw_a16, sf_FCOMPiw_a16, sf_FCOMPiw_a16, sf_FCOMPiw_a16, sf_FCOMPiw_a16, sf_FCOMPiw_a16, + sf_FSUBiw_a16, sf_FSUBiw_a16, sf_FSUBiw_a16, sf_FSUBiw_a16, sf_FSUBiw_a16, sf_FSUBiw_a16, sf_FSUBiw_a16, sf_FSUBiw_a16, + sf_FSUBRiw_a16, sf_FSUBRiw_a16, sf_FSUBRiw_a16, sf_FSUBRiw_a16, sf_FSUBRiw_a16, sf_FSUBRiw_a16, sf_FSUBRiw_a16, sf_FSUBRiw_a16, + sf_FDIViw_a16, sf_FDIViw_a16, sf_FDIViw_a16, sf_FDIViw_a16, sf_FDIViw_a16, sf_FDIViw_a16, sf_FDIViw_a16, sf_FDIViw_a16, + sf_FDIVRiw_a16, sf_FDIVRiw_a16, sf_FDIVRiw_a16, sf_FDIVRiw_a16, sf_FDIVRiw_a16, sf_FDIVRiw_a16, sf_FDIVRiw_a16, sf_FDIVRiw_a16, + + sf_FADDiw_a16, sf_FADDiw_a16, sf_FADDiw_a16, sf_FADDiw_a16, sf_FADDiw_a16, sf_FADDiw_a16, sf_FADDiw_a16, sf_FADDiw_a16, + sf_FMULiw_a16, sf_FMULiw_a16, sf_FMULiw_a16, sf_FMULiw_a16, sf_FMULiw_a16, sf_FMULiw_a16, sf_FMULiw_a16, sf_FMULiw_a16, + sf_FCOMiw_a16, sf_FCOMiw_a16, sf_FCOMiw_a16, sf_FCOMiw_a16, sf_FCOMiw_a16, sf_FCOMiw_a16, sf_FCOMiw_a16, sf_FCOMiw_a16, + sf_FCOMPiw_a16, sf_FCOMPiw_a16, sf_FCOMPiw_a16, sf_FCOMPiw_a16, sf_FCOMPiw_a16, sf_FCOMPiw_a16, sf_FCOMPiw_a16, sf_FCOMPiw_a16, + sf_FSUBiw_a16, sf_FSUBiw_a16, sf_FSUBiw_a16, sf_FSUBiw_a16, sf_FSUBiw_a16, sf_FSUBiw_a16, sf_FSUBiw_a16, sf_FSUBiw_a16, + sf_FSUBRiw_a16, sf_FSUBRiw_a16, sf_FSUBRiw_a16, sf_FSUBRiw_a16, sf_FSUBRiw_a16, sf_FSUBRiw_a16, sf_FSUBRiw_a16, sf_FSUBRiw_a16, + sf_FDIViw_a16, sf_FDIViw_a16, sf_FDIViw_a16, sf_FDIViw_a16, sf_FDIViw_a16, sf_FDIViw_a16, sf_FDIViw_a16, sf_FDIViw_a16, + sf_FDIVRiw_a16, sf_FDIVRiw_a16, sf_FDIVRiw_a16, sf_FDIVRiw_a16, sf_FDIVRiw_a16, sf_FDIVRiw_a16, sf_FDIVRiw_a16, sf_FDIVRiw_a16, + + sf_FADDP_sti_st0, sf_FADDP_sti_st0, sf_FADDP_sti_st0, sf_FADDP_sti_st0, sf_FADDP_sti_st0, sf_FADDP_sti_st0, sf_FADDP_sti_st0, sf_FADDP_sti_st0, + sf_FMULP_sti_st0, sf_FMULP_sti_st0, sf_FMULP_sti_st0, sf_FMULP_sti_st0, sf_FMULP_sti_st0, sf_FMULP_sti_st0, sf_FMULP_sti_st0, sf_FMULP_sti_st0, + ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, + ILLEGAL_a16, sf_FCOMPP, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, + sf_FSUBRP_sti_st0, sf_FSUBRP_sti_st0, sf_FSUBRP_sti_st0, sf_FSUBRP_sti_st0, sf_FSUBRP_sti_st0, sf_FSUBRP_sti_st0, sf_FSUBRP_sti_st0, sf_FSUBRP_sti_st0, + sf_FSUBP_sti_st0, sf_FSUBP_sti_st0, sf_FSUBP_sti_st0, sf_FSUBP_sti_st0, sf_FSUBP_sti_st0, sf_FSUBP_sti_st0, sf_FSUBP_sti_st0, sf_FSUBP_sti_st0, + sf_FDIVRP_sti_st0, sf_FDIVRP_sti_st0, sf_FDIVRP_sti_st0, sf_FDIVRP_sti_st0, sf_FDIVRP_sti_st0, sf_FDIVRP_sti_st0, sf_FDIVRP_sti_st0, sf_FDIVRP_sti_st0, + sf_FDIVP_sti_st0, sf_FDIVP_sti_st0, sf_FDIVP_sti_st0, sf_FDIVP_sti_st0, sf_FDIVP_sti_st0, sf_FDIVP_sti_st0, sf_FDIVP_sti_st0, sf_FDIVP_sti_st0, + // clang-format on +}; + +const OpFn OP_TABLE(sf_fpu_287_de_a32)[256] = { + // clang-format off + sf_FADDiw_a32, sf_FADDiw_a32, sf_FADDiw_a32, sf_FADDiw_a32, sf_FADDiw_a32, sf_FADDiw_a32, sf_FADDiw_a32, sf_FADDiw_a32, + sf_FMULiw_a32, sf_FMULiw_a32, sf_FMULiw_a32, sf_FMULiw_a32, sf_FMULiw_a32, sf_FMULiw_a32, sf_FMULiw_a32, sf_FMULiw_a32, + sf_FCOMiw_a32, sf_FCOMiw_a32, sf_FCOMiw_a32, sf_FCOMiw_a32, sf_FCOMiw_a32, sf_FCOMiw_a32, sf_FCOMiw_a32, sf_FCOMiw_a32, + sf_FCOMPiw_a32, sf_FCOMPiw_a32, sf_FCOMPiw_a32, sf_FCOMPiw_a32, sf_FCOMPiw_a32, sf_FCOMPiw_a32, sf_FCOMPiw_a32, sf_FCOMPiw_a32, + sf_FSUBiw_a32, sf_FSUBiw_a32, sf_FSUBiw_a32, sf_FSUBiw_a32, sf_FSUBiw_a32, sf_FSUBiw_a32, sf_FSUBiw_a32, sf_FSUBiw_a32, + sf_FSUBRiw_a32, sf_FSUBRiw_a32, sf_FSUBRiw_a32, sf_FSUBRiw_a32, sf_FSUBRiw_a32, sf_FSUBRiw_a32, sf_FSUBRiw_a32, sf_FSUBRiw_a32, + sf_FDIViw_a32, sf_FDIViw_a32, sf_FDIViw_a32, sf_FDIViw_a32, sf_FDIViw_a32, sf_FDIViw_a32, sf_FDIViw_a32, sf_FDIViw_a32, + sf_FDIVRiw_a32, sf_FDIVRiw_a32, sf_FDIVRiw_a32, sf_FDIVRiw_a32, sf_FDIVRiw_a32, sf_FDIVRiw_a32, sf_FDIVRiw_a32, sf_FDIVRiw_a32, + + sf_FADDiw_a32, sf_FADDiw_a32, sf_FADDiw_a32, sf_FADDiw_a32, sf_FADDiw_a32, sf_FADDiw_a32, sf_FADDiw_a32, sf_FADDiw_a32, + sf_FMULiw_a32, sf_FMULiw_a32, sf_FMULiw_a32, sf_FMULiw_a32, sf_FMULiw_a32, sf_FMULiw_a32, sf_FMULiw_a32, sf_FMULiw_a32, + sf_FCOMiw_a32, sf_FCOMiw_a32, sf_FCOMiw_a32, sf_FCOMiw_a32, sf_FCOMiw_a32, sf_FCOMiw_a32, sf_FCOMiw_a32, sf_FCOMiw_a32, + sf_FCOMPiw_a32, sf_FCOMPiw_a32, sf_FCOMPiw_a32, sf_FCOMPiw_a32, sf_FCOMPiw_a32, sf_FCOMPiw_a32, sf_FCOMPiw_a32, sf_FCOMPiw_a32, + sf_FSUBiw_a32, sf_FSUBiw_a32, sf_FSUBiw_a32, sf_FSUBiw_a32, sf_FSUBiw_a32, sf_FSUBiw_a32, sf_FSUBiw_a32, sf_FSUBiw_a32, + sf_FSUBRiw_a32, sf_FSUBRiw_a32, sf_FSUBRiw_a32, sf_FSUBRiw_a32, sf_FSUBRiw_a32, sf_FSUBRiw_a32, sf_FSUBRiw_a32, sf_FSUBRiw_a32, + sf_FDIViw_a32, sf_FDIViw_a32, sf_FDIViw_a32, sf_FDIViw_a32, sf_FDIViw_a32, sf_FDIViw_a32, sf_FDIViw_a32, sf_FDIViw_a32, + sf_FDIVRiw_a32, sf_FDIVRiw_a32, sf_FDIVRiw_a32, sf_FDIVRiw_a32, sf_FDIVRiw_a32, sf_FDIVRiw_a32, sf_FDIVRiw_a32, sf_FDIVRiw_a32, + + sf_FADDiw_a32, sf_FADDiw_a32, sf_FADDiw_a32, sf_FADDiw_a32, sf_FADDiw_a32, sf_FADDiw_a32, sf_FADDiw_a32, sf_FADDiw_a32, + sf_FMULiw_a32, sf_FMULiw_a32, sf_FMULiw_a32, sf_FMULiw_a32, sf_FMULiw_a32, sf_FMULiw_a32, sf_FMULiw_a32, sf_FMULiw_a32, + sf_FCOMiw_a32, sf_FCOMiw_a32, sf_FCOMiw_a32, sf_FCOMiw_a32, sf_FCOMiw_a32, sf_FCOMiw_a32, sf_FCOMiw_a32, sf_FCOMiw_a32, + sf_FCOMPiw_a32, sf_FCOMPiw_a32, sf_FCOMPiw_a32, sf_FCOMPiw_a32, sf_FCOMPiw_a32, sf_FCOMPiw_a32, sf_FCOMPiw_a32, sf_FCOMPiw_a32, + sf_FSUBiw_a32, sf_FSUBiw_a32, sf_FSUBiw_a32, sf_FSUBiw_a32, sf_FSUBiw_a32, sf_FSUBiw_a32, sf_FSUBiw_a32, sf_FSUBiw_a32, + sf_FSUBRiw_a32, sf_FSUBRiw_a32, sf_FSUBRiw_a32, sf_FSUBRiw_a32, sf_FSUBRiw_a32, sf_FSUBRiw_a32, sf_FSUBRiw_a32, sf_FSUBRiw_a32, + sf_FDIViw_a32, sf_FDIViw_a32, sf_FDIViw_a32, sf_FDIViw_a32, sf_FDIViw_a32, sf_FDIViw_a32, sf_FDIViw_a32, sf_FDIViw_a32, + sf_FDIVRiw_a32, sf_FDIVRiw_a32, sf_FDIVRiw_a32, sf_FDIVRiw_a32, sf_FDIVRiw_a32, sf_FDIVRiw_a32, sf_FDIVRiw_a32, sf_FDIVRiw_a32, + + sf_FADDP_sti_st0, sf_FADDP_sti_st0, sf_FADDP_sti_st0, sf_FADDP_sti_st0, sf_FADDP_sti_st0, sf_FADDP_sti_st0, sf_FADDP_sti_st0, sf_FADDP_sti_st0, + sf_FMULP_sti_st0, sf_FMULP_sti_st0, sf_FMULP_sti_st0, sf_FMULP_sti_st0, sf_FMULP_sti_st0, sf_FMULP_sti_st0, sf_FMULP_sti_st0, sf_FMULP_sti_st0, + ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, + ILLEGAL_a32, sf_FCOMPP, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, + sf_FSUBRP_sti_st0, sf_FSUBRP_sti_st0, sf_FSUBRP_sti_st0, sf_FSUBRP_sti_st0, sf_FSUBRP_sti_st0, sf_FSUBRP_sti_st0, sf_FSUBRP_sti_st0, sf_FSUBRP_sti_st0, + sf_FSUBP_sti_st0, sf_FSUBP_sti_st0, sf_FSUBP_sti_st0, sf_FSUBP_sti_st0, sf_FSUBP_sti_st0, sf_FSUBP_sti_st0, sf_FSUBP_sti_st0, sf_FSUBP_sti_st0, + sf_FDIVRP_sti_st0, sf_FDIVRP_sti_st0, sf_FDIVRP_sti_st0, sf_FDIVRP_sti_st0, sf_FDIVRP_sti_st0, sf_FDIVRP_sti_st0, sf_FDIVRP_sti_st0, sf_FDIVRP_sti_st0, + sf_FDIVP_sti_st0, sf_FDIVP_sti_st0, sf_FDIVP_sti_st0, sf_FDIVP_sti_st0, sf_FDIVP_sti_st0, sf_FDIVP_sti_st0, sf_FDIVP_sti_st0, sf_FDIVP_sti_st0, + // clang-format on +}; + +const OpFn OP_TABLE(sf_fpu_de_a16)[256] = { + // clang-format off + sf_FADDiw_a16, sf_FADDiw_a16, sf_FADDiw_a16, sf_FADDiw_a16, sf_FADDiw_a16, sf_FADDiw_a16, sf_FADDiw_a16, sf_FADDiw_a16, + sf_FMULiw_a16, sf_FMULiw_a16, sf_FMULiw_a16, sf_FMULiw_a16, sf_FMULiw_a16, sf_FMULiw_a16, sf_FMULiw_a16, sf_FMULiw_a16, + sf_FCOMiw_a16, sf_FCOMiw_a16, sf_FCOMiw_a16, sf_FCOMiw_a16, sf_FCOMiw_a16, sf_FCOMiw_a16, sf_FCOMiw_a16, sf_FCOMiw_a16, + sf_FCOMPiw_a16, sf_FCOMPiw_a16, sf_FCOMPiw_a16, sf_FCOMPiw_a16, sf_FCOMPiw_a16, sf_FCOMPiw_a16, sf_FCOMPiw_a16, sf_FCOMPiw_a16, + sf_FSUBiw_a16, sf_FSUBiw_a16, sf_FSUBiw_a16, sf_FSUBiw_a16, sf_FSUBiw_a16, sf_FSUBiw_a16, sf_FSUBiw_a16, sf_FSUBiw_a16, + sf_FSUBRiw_a16, sf_FSUBRiw_a16, sf_FSUBRiw_a16, sf_FSUBRiw_a16, sf_FSUBRiw_a16, sf_FSUBRiw_a16, sf_FSUBRiw_a16, sf_FSUBRiw_a16, + sf_FDIViw_a16, sf_FDIViw_a16, sf_FDIViw_a16, sf_FDIViw_a16, sf_FDIViw_a16, sf_FDIViw_a16, sf_FDIViw_a16, sf_FDIViw_a16, + sf_FDIVRiw_a16, sf_FDIVRiw_a16, sf_FDIVRiw_a16, sf_FDIVRiw_a16, sf_FDIVRiw_a16, sf_FDIVRiw_a16, sf_FDIVRiw_a16, sf_FDIVRiw_a16, + + sf_FADDiw_a16, sf_FADDiw_a16, sf_FADDiw_a16, sf_FADDiw_a16, sf_FADDiw_a16, sf_FADDiw_a16, sf_FADDiw_a16, sf_FADDiw_a16, + sf_FMULiw_a16, sf_FMULiw_a16, sf_FMULiw_a16, sf_FMULiw_a16, sf_FMULiw_a16, sf_FMULiw_a16, sf_FMULiw_a16, sf_FMULiw_a16, + sf_FCOMiw_a16, sf_FCOMiw_a16, sf_FCOMiw_a16, sf_FCOMiw_a16, sf_FCOMiw_a16, sf_FCOMiw_a16, sf_FCOMiw_a16, sf_FCOMiw_a16, + sf_FCOMPiw_a16, sf_FCOMPiw_a16, sf_FCOMPiw_a16, sf_FCOMPiw_a16, sf_FCOMPiw_a16, sf_FCOMPiw_a16, sf_FCOMPiw_a16, sf_FCOMPiw_a16, + sf_FSUBiw_a16, sf_FSUBiw_a16, sf_FSUBiw_a16, sf_FSUBiw_a16, sf_FSUBiw_a16, sf_FSUBiw_a16, sf_FSUBiw_a16, sf_FSUBiw_a16, + sf_FSUBRiw_a16, sf_FSUBRiw_a16, sf_FSUBRiw_a16, sf_FSUBRiw_a16, sf_FSUBRiw_a16, sf_FSUBRiw_a16, sf_FSUBRiw_a16, sf_FSUBRiw_a16, + sf_FDIViw_a16, sf_FDIViw_a16, sf_FDIViw_a16, sf_FDIViw_a16, sf_FDIViw_a16, sf_FDIViw_a16, sf_FDIViw_a16, sf_FDIViw_a16, + sf_FDIVRiw_a16, sf_FDIVRiw_a16, sf_FDIVRiw_a16, sf_FDIVRiw_a16, sf_FDIVRiw_a16, sf_FDIVRiw_a16, sf_FDIVRiw_a16, sf_FDIVRiw_a16, + + sf_FADDiw_a16, sf_FADDiw_a16, sf_FADDiw_a16, sf_FADDiw_a16, sf_FADDiw_a16, sf_FADDiw_a16, sf_FADDiw_a16, sf_FADDiw_a16, + sf_FMULiw_a16, sf_FMULiw_a16, sf_FMULiw_a16, sf_FMULiw_a16, sf_FMULiw_a16, sf_FMULiw_a16, sf_FMULiw_a16, sf_FMULiw_a16, + sf_FCOMiw_a16, sf_FCOMiw_a16, sf_FCOMiw_a16, sf_FCOMiw_a16, sf_FCOMiw_a16, sf_FCOMiw_a16, sf_FCOMiw_a16, sf_FCOMiw_a16, + sf_FCOMPiw_a16, sf_FCOMPiw_a16, sf_FCOMPiw_a16, sf_FCOMPiw_a16, sf_FCOMPiw_a16, sf_FCOMPiw_a16, sf_FCOMPiw_a16, sf_FCOMPiw_a16, + sf_FSUBiw_a16, sf_FSUBiw_a16, sf_FSUBiw_a16, sf_FSUBiw_a16, sf_FSUBiw_a16, sf_FSUBiw_a16, sf_FSUBiw_a16, sf_FSUBiw_a16, + sf_FSUBRiw_a16, sf_FSUBRiw_a16, sf_FSUBRiw_a16, sf_FSUBRiw_a16, sf_FSUBRiw_a16, sf_FSUBRiw_a16, sf_FSUBRiw_a16, sf_FSUBRiw_a16, + sf_FDIViw_a16, sf_FDIViw_a16, sf_FDIViw_a16, sf_FDIViw_a16, sf_FDIViw_a16, sf_FDIViw_a16, sf_FDIViw_a16, sf_FDIViw_a16, + sf_FDIVRiw_a16, sf_FDIVRiw_a16, sf_FDIVRiw_a16, sf_FDIVRiw_a16, sf_FDIVRiw_a16, sf_FDIVRiw_a16, sf_FDIVRiw_a16, sf_FDIVRiw_a16, + + sf_FADDP_sti_st0, sf_FADDP_sti_st0, sf_FADDP_sti_st0, sf_FADDP_sti_st0, sf_FADDP_sti_st0, sf_FADDP_sti_st0, sf_FADDP_sti_st0, sf_FADDP_sti_st0, + sf_FMULP_sti_st0, sf_FMULP_sti_st0, sf_FMULP_sti_st0, sf_FMULP_sti_st0, sf_FMULP_sti_st0, sf_FMULP_sti_st0, sf_FMULP_sti_st0, sf_FMULP_sti_st0, + sf_FCOMP_sti, sf_FCOMP_sti, sf_FCOMP_sti, sf_FCOMP_sti, sf_FCOMP_sti, sf_FCOMP_sti, sf_FCOMP_sti, sf_FCOMP_sti, + ILLEGAL_a16, sf_FCOMPP, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, + sf_FSUBRP_sti_st0, sf_FSUBRP_sti_st0, sf_FSUBRP_sti_st0, sf_FSUBRP_sti_st0, sf_FSUBRP_sti_st0, sf_FSUBRP_sti_st0, sf_FSUBRP_sti_st0, sf_FSUBRP_sti_st0, + sf_FSUBP_sti_st0, sf_FSUBP_sti_st0, sf_FSUBP_sti_st0, sf_FSUBP_sti_st0, sf_FSUBP_sti_st0, sf_FSUBP_sti_st0, sf_FSUBP_sti_st0, sf_FSUBP_sti_st0, + sf_FDIVRP_sti_st0, sf_FDIVRP_sti_st0, sf_FDIVRP_sti_st0, sf_FDIVRP_sti_st0, sf_FDIVRP_sti_st0, sf_FDIVRP_sti_st0, sf_FDIVRP_sti_st0, sf_FDIVRP_sti_st0, + sf_FDIVP_sti_st0, sf_FDIVP_sti_st0, sf_FDIVP_sti_st0, sf_FDIVP_sti_st0, sf_FDIVP_sti_st0, sf_FDIVP_sti_st0, sf_FDIVP_sti_st0, sf_FDIVP_sti_st0, + // clang-format on +}; + +const OpFn OP_TABLE(sf_fpu_de_a32)[256] = { + // clang-format off + sf_FADDiw_a32, sf_FADDiw_a32, sf_FADDiw_a32, sf_FADDiw_a32, sf_FADDiw_a32, sf_FADDiw_a32, sf_FADDiw_a32, sf_FADDiw_a32, + sf_FMULiw_a32, sf_FMULiw_a32, sf_FMULiw_a32, sf_FMULiw_a32, sf_FMULiw_a32, sf_FMULiw_a32, sf_FMULiw_a32, sf_FMULiw_a32, + sf_FCOMiw_a32, sf_FCOMiw_a32, sf_FCOMiw_a32, sf_FCOMiw_a32, sf_FCOMiw_a32, sf_FCOMiw_a32, sf_FCOMiw_a32, sf_FCOMiw_a32, + sf_FCOMPiw_a32, sf_FCOMPiw_a32, sf_FCOMPiw_a32, sf_FCOMPiw_a32, sf_FCOMPiw_a32, sf_FCOMPiw_a32, sf_FCOMPiw_a32, sf_FCOMPiw_a32, + sf_FSUBiw_a32, sf_FSUBiw_a32, sf_FSUBiw_a32, sf_FSUBiw_a32, sf_FSUBiw_a32, sf_FSUBiw_a32, sf_FSUBiw_a32, sf_FSUBiw_a32, + sf_FSUBRiw_a32, sf_FSUBRiw_a32, sf_FSUBRiw_a32, sf_FSUBRiw_a32, sf_FSUBRiw_a32, sf_FSUBRiw_a32, sf_FSUBRiw_a32, sf_FSUBRiw_a32, + sf_FDIViw_a32, sf_FDIViw_a32, sf_FDIViw_a32, sf_FDIViw_a32, sf_FDIViw_a32, sf_FDIViw_a32, sf_FDIViw_a32, sf_FDIViw_a32, + sf_FDIVRiw_a32, sf_FDIVRiw_a32, sf_FDIVRiw_a32, sf_FDIVRiw_a32, sf_FDIVRiw_a32, sf_FDIVRiw_a32, sf_FDIVRiw_a32, sf_FDIVRiw_a32, + + sf_FADDiw_a32, sf_FADDiw_a32, sf_FADDiw_a32, sf_FADDiw_a32, sf_FADDiw_a32, sf_FADDiw_a32, sf_FADDiw_a32, sf_FADDiw_a32, + sf_FMULiw_a32, sf_FMULiw_a32, sf_FMULiw_a32, sf_FMULiw_a32, sf_FMULiw_a32, sf_FMULiw_a32, sf_FMULiw_a32, sf_FMULiw_a32, + sf_FCOMiw_a32, sf_FCOMiw_a32, sf_FCOMiw_a32, sf_FCOMiw_a32, sf_FCOMiw_a32, sf_FCOMiw_a32, sf_FCOMiw_a32, sf_FCOMiw_a32, + sf_FCOMPiw_a32, sf_FCOMPiw_a32, sf_FCOMPiw_a32, sf_FCOMPiw_a32, sf_FCOMPiw_a32, sf_FCOMPiw_a32, sf_FCOMPiw_a32, sf_FCOMPiw_a32, + sf_FSUBiw_a32, sf_FSUBiw_a32, sf_FSUBiw_a32, sf_FSUBiw_a32, sf_FSUBiw_a32, sf_FSUBiw_a32, sf_FSUBiw_a32, sf_FSUBiw_a32, + sf_FSUBRiw_a32, sf_FSUBRiw_a32, sf_FSUBRiw_a32, sf_FSUBRiw_a32, sf_FSUBRiw_a32, sf_FSUBRiw_a32, sf_FSUBRiw_a32, sf_FSUBRiw_a32, + sf_FDIViw_a32, sf_FDIViw_a32, sf_FDIViw_a32, sf_FDIViw_a32, sf_FDIViw_a32, sf_FDIViw_a32, sf_FDIViw_a32, sf_FDIViw_a32, + sf_FDIVRiw_a32, sf_FDIVRiw_a32, sf_FDIVRiw_a32, sf_FDIVRiw_a32, sf_FDIVRiw_a32, sf_FDIVRiw_a32, sf_FDIVRiw_a32, sf_FDIVRiw_a32, + + sf_FADDiw_a32, sf_FADDiw_a32, sf_FADDiw_a32, sf_FADDiw_a32, sf_FADDiw_a32, sf_FADDiw_a32, sf_FADDiw_a32, sf_FADDiw_a32, + sf_FMULiw_a32, sf_FMULiw_a32, sf_FMULiw_a32, sf_FMULiw_a32, sf_FMULiw_a32, sf_FMULiw_a32, sf_FMULiw_a32, sf_FMULiw_a32, + sf_FCOMiw_a32, sf_FCOMiw_a32, sf_FCOMiw_a32, sf_FCOMiw_a32, sf_FCOMiw_a32, sf_FCOMiw_a32, sf_FCOMiw_a32, sf_FCOMiw_a32, + sf_FCOMPiw_a32, sf_FCOMPiw_a32, sf_FCOMPiw_a32, sf_FCOMPiw_a32, sf_FCOMPiw_a32, sf_FCOMPiw_a32, sf_FCOMPiw_a32, sf_FCOMPiw_a32, + sf_FSUBiw_a32, sf_FSUBiw_a32, sf_FSUBiw_a32, sf_FSUBiw_a32, sf_FSUBiw_a32, sf_FSUBiw_a32, sf_FSUBiw_a32, sf_FSUBiw_a32, + sf_FSUBRiw_a32, sf_FSUBRiw_a32, sf_FSUBRiw_a32, sf_FSUBRiw_a32, sf_FSUBRiw_a32, sf_FSUBRiw_a32, sf_FSUBRiw_a32, sf_FSUBRiw_a32, + sf_FDIViw_a32, sf_FDIViw_a32, sf_FDIViw_a32, sf_FDIViw_a32, sf_FDIViw_a32, sf_FDIViw_a32, sf_FDIViw_a32, sf_FDIViw_a32, + sf_FDIVRiw_a32, sf_FDIVRiw_a32, sf_FDIVRiw_a32, sf_FDIVRiw_a32, sf_FDIVRiw_a32, sf_FDIVRiw_a32, sf_FDIVRiw_a32, sf_FDIVRiw_a32, + + sf_FADDP_sti_st0, sf_FADDP_sti_st0, sf_FADDP_sti_st0, sf_FADDP_sti_st0, sf_FADDP_sti_st0, sf_FADDP_sti_st0, sf_FADDP_sti_st0, sf_FADDP_sti_st0, + sf_FMULP_sti_st0, sf_FMULP_sti_st0, sf_FMULP_sti_st0, sf_FMULP_sti_st0, sf_FMULP_sti_st0, sf_FMULP_sti_st0, sf_FMULP_sti_st0, sf_FMULP_sti_st0, + sf_FCOMP_sti, sf_FCOMP_sti, sf_FCOMP_sti, sf_FCOMP_sti, sf_FCOMP_sti, sf_FCOMP_sti, sf_FCOMP_sti, sf_FCOMP_sti, + ILLEGAL_a32, sf_FCOMPP, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, + sf_FSUBRP_sti_st0, sf_FSUBRP_sti_st0, sf_FSUBRP_sti_st0, sf_FSUBRP_sti_st0, sf_FSUBRP_sti_st0, sf_FSUBRP_sti_st0, sf_FSUBRP_sti_st0, sf_FSUBRP_sti_st0, + sf_FSUBP_sti_st0, sf_FSUBP_sti_st0, sf_FSUBP_sti_st0, sf_FSUBP_sti_st0, sf_FSUBP_sti_st0, sf_FSUBP_sti_st0, sf_FSUBP_sti_st0, sf_FSUBP_sti_st0, + sf_FDIVRP_sti_st0, sf_FDIVRP_sti_st0, sf_FDIVRP_sti_st0, sf_FDIVRP_sti_st0, sf_FDIVRP_sti_st0, sf_FDIVRP_sti_st0, sf_FDIVRP_sti_st0, sf_FDIVRP_sti_st0, + sf_FDIVP_sti_st0, sf_FDIVP_sti_st0, sf_FDIVP_sti_st0, sf_FDIVP_sti_st0, sf_FDIVP_sti_st0, sf_FDIVP_sti_st0, sf_FDIVP_sti_st0, sf_FDIVP_sti_st0, + // clang-format on +}; + +const OpFn OP_TABLE(sf_fpu_287_df_a16)[256] = { + // clang-format off + sf_FILDiw_a16, sf_FILDiw_a16, sf_FILDiw_a16, sf_FILDiw_a16, sf_FILDiw_a16, sf_FILDiw_a16, sf_FILDiw_a16, sf_FILDiw_a16, + ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, + sf_FISTiw_a16, sf_FISTiw_a16, sf_FISTiw_a16, sf_FISTiw_a16, sf_FISTiw_a16, sf_FISTiw_a16, sf_FISTiw_a16, sf_FISTiw_a16, + sf_FISTPiw_a16, sf_FISTPiw_a16, sf_FISTPiw_a16, sf_FISTPiw_a16, sf_FISTPiw_a16, sf_FISTPiw_a16, sf_FISTPiw_a16, sf_FISTPiw_a16, + ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, + sf_FILDiq_a16, sf_FILDiq_a16, sf_FILDiq_a16, sf_FILDiq_a16, sf_FILDiq_a16, sf_FILDiq_a16, sf_FILDiq_a16, sf_FILDiq_a16, + sf_FBSTP_PACKED_BCD_a16, sf_FBSTP_PACKED_BCD_a16, sf_FBSTP_PACKED_BCD_a16, sf_FBSTP_PACKED_BCD_a16, sf_FBSTP_PACKED_BCD_a16, sf_FBSTP_PACKED_BCD_a16, sf_FBSTP_PACKED_BCD_a16, sf_FBSTP_PACKED_BCD_a16, + sf_FISTPiq_a16, sf_FISTPiq_a16, sf_FISTPiq_a16, sf_FISTPiq_a16, sf_FISTPiq_a16, sf_FISTPiq_a16, sf_FISTPiq_a16, sf_FISTPiq_a16, + + sf_FILDiw_a16, sf_FILDiw_a16, sf_FILDiw_a16, sf_FILDiw_a16, sf_FILDiw_a16, sf_FILDiw_a16, sf_FILDiw_a16, sf_FILDiw_a16, + ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, + sf_FISTiw_a16, sf_FISTiw_a16, sf_FISTiw_a16, sf_FISTiw_a16, sf_FISTiw_a16, sf_FISTiw_a16, sf_FISTiw_a16, sf_FISTiw_a16, + sf_FISTPiw_a16, sf_FISTPiw_a16, sf_FISTPiw_a16, sf_FISTPiw_a16, sf_FISTPiw_a16, sf_FISTPiw_a16, sf_FISTPiw_a16, sf_FISTPiw_a16, + ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, + sf_FILDiq_a16, sf_FILDiq_a16, sf_FILDiq_a16, sf_FILDiq_a16, sf_FILDiq_a16, sf_FILDiq_a16, sf_FILDiq_a16, sf_FILDiq_a16, + sf_FBSTP_PACKED_BCD_a16, sf_FBSTP_PACKED_BCD_a16, sf_FBSTP_PACKED_BCD_a16, sf_FBSTP_PACKED_BCD_a16, sf_FBSTP_PACKED_BCD_a16, sf_FBSTP_PACKED_BCD_a16, sf_FBSTP_PACKED_BCD_a16, sf_FBSTP_PACKED_BCD_a16, + sf_FISTPiq_a16, sf_FISTPiq_a16, sf_FISTPiq_a16, sf_FISTPiq_a16, sf_FISTPiq_a16, sf_FISTPiq_a16, sf_FISTPiq_a16, sf_FISTPiq_a16, + + sf_FILDiw_a16, sf_FILDiw_a16, sf_FILDiw_a16, sf_FILDiw_a16, sf_FILDiw_a16, sf_FILDiw_a16, sf_FILDiw_a16, sf_FILDiw_a16, + ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, + sf_FISTiw_a16, sf_FISTiw_a16, sf_FISTiw_a16, sf_FISTiw_a16, sf_FISTiw_a16, sf_FISTiw_a16, sf_FISTiw_a16, sf_FISTiw_a16, + sf_FISTPiw_a16, sf_FISTPiw_a16, sf_FISTPiw_a16, sf_FISTPiw_a16, sf_FISTPiw_a16, sf_FISTPiw_a16, sf_FISTPiw_a16, sf_FISTPiw_a16, + ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, + sf_FILDiq_a16, sf_FILDiq_a16, sf_FILDiq_a16, sf_FILDiq_a16, sf_FILDiq_a16, sf_FILDiq_a16, sf_FILDiq_a16, sf_FILDiq_a16, + sf_FBSTP_PACKED_BCD_a16, sf_FBSTP_PACKED_BCD_a16, sf_FBSTP_PACKED_BCD_a16, sf_FBSTP_PACKED_BCD_a16, sf_FBSTP_PACKED_BCD_a16, sf_FBSTP_PACKED_BCD_a16, sf_FBSTP_PACKED_BCD_a16, sf_FBSTP_PACKED_BCD_a16, + sf_FISTPiq_a16, sf_FISTPiq_a16, sf_FISTPiq_a16, sf_FISTPiq_a16, sf_FISTPiq_a16, sf_FISTPiq_a16, sf_FISTPiq_a16, sf_FISTPiq_a16, + + sf_FFREEP_sti, sf_FFREEP_sti, sf_FFREEP_sti, sf_FFREEP_sti, sf_FFREEP_sti, sf_FFREEP_sti, sf_FFREEP_sti, sf_FFREEP_sti, + ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, + ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, + ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, + sf_FNSTSW_AX, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, + ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, + ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, + ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, + // clang-format on +}; + +const OpFn OP_TABLE(sf_fpu_287_df_a32)[256] = { + // clang-format off + sf_FILDiw_a32, sf_FILDiw_a32, sf_FILDiw_a32, sf_FILDiw_a32, sf_FILDiw_a32, sf_FILDiw_a32, sf_FILDiw_a32, sf_FILDiw_a32, + ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, + sf_FISTiw_a32, sf_FISTiw_a32, sf_FISTiw_a32, sf_FISTiw_a32, sf_FISTiw_a32, sf_FISTiw_a32, sf_FISTiw_a32, sf_FISTiw_a32, + sf_FISTPiw_a32, sf_FISTPiw_a32, sf_FISTPiw_a32, sf_FISTPiw_a32, sf_FISTPiw_a32, sf_FISTPiw_a32, sf_FISTPiw_a32, sf_FISTPiw_a32, + ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, + sf_FILDiq_a32, sf_FILDiq_a32, sf_FILDiq_a32, sf_FILDiq_a32, sf_FILDiq_a32, sf_FILDiq_a32, sf_FILDiq_a32, sf_FILDiq_a32, + sf_FBSTP_PACKED_BCD_a32, sf_FBSTP_PACKED_BCD_a32, sf_FBSTP_PACKED_BCD_a32, sf_FBSTP_PACKED_BCD_a32, sf_FBSTP_PACKED_BCD_a32, sf_FBSTP_PACKED_BCD_a32, sf_FBSTP_PACKED_BCD_a32, sf_FBSTP_PACKED_BCD_a32, + sf_FISTPiq_a32, sf_FISTPiq_a32, sf_FISTPiq_a32, sf_FISTPiq_a32, sf_FISTPiq_a32, sf_FISTPiq_a32, sf_FISTPiq_a32, sf_FISTPiq_a32, + + sf_FILDiw_a32, sf_FILDiw_a32, sf_FILDiw_a32, sf_FILDiw_a32, sf_FILDiw_a32, sf_FILDiw_a32, sf_FILDiw_a32, sf_FILDiw_a32, + ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, + sf_FISTiw_a32, sf_FISTiw_a32, sf_FISTiw_a32, sf_FISTiw_a32, sf_FISTiw_a32, sf_FISTiw_a32, sf_FISTiw_a32, sf_FISTiw_a32, + sf_FISTPiw_a32, sf_FISTPiw_a32, sf_FISTPiw_a32, sf_FISTPiw_a32, sf_FISTPiw_a32, sf_FISTPiw_a32, sf_FISTPiw_a32, sf_FISTPiw_a32, + ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, + sf_FILDiq_a32, sf_FILDiq_a32, sf_FILDiq_a32, sf_FILDiq_a32, sf_FILDiq_a32, sf_FILDiq_a32, sf_FILDiq_a32, sf_FILDiq_a32, + sf_FBSTP_PACKED_BCD_a32, sf_FBSTP_PACKED_BCD_a32, sf_FBSTP_PACKED_BCD_a32, sf_FBSTP_PACKED_BCD_a32, sf_FBSTP_PACKED_BCD_a32, sf_FBSTP_PACKED_BCD_a32, sf_FBSTP_PACKED_BCD_a32, sf_FBSTP_PACKED_BCD_a32, + sf_FISTPiq_a32, sf_FISTPiq_a32, sf_FISTPiq_a32, sf_FISTPiq_a32, sf_FISTPiq_a32, sf_FISTPiq_a32, sf_FISTPiq_a32, sf_FISTPiq_a32, + + sf_FILDiw_a32, sf_FILDiw_a32, sf_FILDiw_a32, sf_FILDiw_a32, sf_FILDiw_a32, sf_FILDiw_a32, sf_FILDiw_a32, sf_FILDiw_a32, + ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, + sf_FISTiw_a32, sf_FISTiw_a32, sf_FISTiw_a32, sf_FISTiw_a32, sf_FISTiw_a32, sf_FISTiw_a32, sf_FISTiw_a32, sf_FISTiw_a32, + sf_FISTPiw_a32, sf_FISTPiw_a32, sf_FISTPiw_a32, sf_FISTPiw_a32, sf_FISTPiw_a32, sf_FISTPiw_a32, sf_FISTPiw_a32, sf_FISTPiw_a32, + ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, + sf_FILDiq_a32, sf_FILDiq_a32, sf_FILDiq_a32, sf_FILDiq_a32, sf_FILDiq_a32, sf_FILDiq_a32, sf_FILDiq_a32, sf_FILDiq_a32, + sf_FBSTP_PACKED_BCD_a32, sf_FBSTP_PACKED_BCD_a32, sf_FBSTP_PACKED_BCD_a32, sf_FBSTP_PACKED_BCD_a32, sf_FBSTP_PACKED_BCD_a32, sf_FBSTP_PACKED_BCD_a32, sf_FBSTP_PACKED_BCD_a32, sf_FBSTP_PACKED_BCD_a32, + sf_FISTPiq_a32, sf_FISTPiq_a32, sf_FISTPiq_a32, sf_FISTPiq_a32, sf_FISTPiq_a32, sf_FISTPiq_a32, sf_FISTPiq_a32, sf_FISTPiq_a32, + + sf_FFREEP_sti, sf_FFREEP_sti, sf_FFREEP_sti, sf_FFREEP_sti, sf_FFREEP_sti, sf_FFREEP_sti, sf_FFREEP_sti, sf_FFREEP_sti, + ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, + ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, + ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, + sf_FNSTSW_AX, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, + ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, + ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, + ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, + // clang-format on +}; + +const OpFn OP_TABLE(sf_fpu_df_a16)[256] = { + // clang-format off + sf_FILDiw_a16, sf_FILDiw_a16, sf_FILDiw_a16, sf_FILDiw_a16, sf_FILDiw_a16, sf_FILDiw_a16, sf_FILDiw_a16, sf_FILDiw_a16, + ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, + sf_FISTiw_a16, sf_FISTiw_a16, sf_FISTiw_a16, sf_FISTiw_a16, sf_FISTiw_a16, sf_FISTiw_a16, sf_FISTiw_a16, sf_FISTiw_a16, + sf_FISTPiw_a16, sf_FISTPiw_a16, sf_FISTPiw_a16, sf_FISTPiw_a16, sf_FISTPiw_a16, sf_FISTPiw_a16, sf_FISTPiw_a16, sf_FISTPiw_a16, + ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, + sf_FILDiq_a16, sf_FILDiq_a16, sf_FILDiq_a16, sf_FILDiq_a16, sf_FILDiq_a16, sf_FILDiq_a16, sf_FILDiq_a16, sf_FILDiq_a16, + sf_FBSTP_PACKED_BCD_a16, sf_FBSTP_PACKED_BCD_a16, sf_FBSTP_PACKED_BCD_a16, sf_FBSTP_PACKED_BCD_a16, sf_FBSTP_PACKED_BCD_a16, sf_FBSTP_PACKED_BCD_a16, sf_FBSTP_PACKED_BCD_a16, sf_FBSTP_PACKED_BCD_a16, + sf_FISTPiq_a16, sf_FISTPiq_a16, sf_FISTPiq_a16, sf_FISTPiq_a16, sf_FISTPiq_a16, sf_FISTPiq_a16, sf_FISTPiq_a16, sf_FISTPiq_a16, + + sf_FILDiw_a16, sf_FILDiw_a16, sf_FILDiw_a16, sf_FILDiw_a16, sf_FILDiw_a16, sf_FILDiw_a16, sf_FILDiw_a16, sf_FILDiw_a16, + ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, + sf_FISTiw_a16, sf_FISTiw_a16, sf_FISTiw_a16, sf_FISTiw_a16, sf_FISTiw_a16, sf_FISTiw_a16, sf_FISTiw_a16, sf_FISTiw_a16, + sf_FISTPiw_a16, sf_FISTPiw_a16, sf_FISTPiw_a16, sf_FISTPiw_a16, sf_FISTPiw_a16, sf_FISTPiw_a16, sf_FISTPiw_a16, sf_FISTPiw_a16, + ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, + sf_FILDiq_a16, sf_FILDiq_a16, sf_FILDiq_a16, sf_FILDiq_a16, sf_FILDiq_a16, sf_FILDiq_a16, sf_FILDiq_a16, sf_FILDiq_a16, + sf_FBSTP_PACKED_BCD_a16, sf_FBSTP_PACKED_BCD_a16, sf_FBSTP_PACKED_BCD_a16, sf_FBSTP_PACKED_BCD_a16, sf_FBSTP_PACKED_BCD_a16, sf_FBSTP_PACKED_BCD_a16, sf_FBSTP_PACKED_BCD_a16, sf_FBSTP_PACKED_BCD_a16, + sf_FISTPiq_a16, sf_FISTPiq_a16, sf_FISTPiq_a16, sf_FISTPiq_a16, sf_FISTPiq_a16, sf_FISTPiq_a16, sf_FISTPiq_a16, sf_FISTPiq_a16, + + sf_FILDiw_a16, sf_FILDiw_a16, sf_FILDiw_a16, sf_FILDiw_a16, sf_FILDiw_a16, sf_FILDiw_a16, sf_FILDiw_a16, sf_FILDiw_a16, + ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, + sf_FISTiw_a16, sf_FISTiw_a16, sf_FISTiw_a16, sf_FISTiw_a16, sf_FISTiw_a16, sf_FISTiw_a16, sf_FISTiw_a16, sf_FISTiw_a16, + sf_FISTPiw_a16, sf_FISTPiw_a16, sf_FISTPiw_a16, sf_FISTPiw_a16, sf_FISTPiw_a16, sf_FISTPiw_a16, sf_FISTPiw_a16, sf_FISTPiw_a16, + ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, + sf_FILDiq_a16, sf_FILDiq_a16, sf_FILDiq_a16, sf_FILDiq_a16, sf_FILDiq_a16, sf_FILDiq_a16, sf_FILDiq_a16, sf_FILDiq_a16, + sf_FBSTP_PACKED_BCD_a16, sf_FBSTP_PACKED_BCD_a16, sf_FBSTP_PACKED_BCD_a16, sf_FBSTP_PACKED_BCD_a16, sf_FBSTP_PACKED_BCD_a16, sf_FBSTP_PACKED_BCD_a16, sf_FBSTP_PACKED_BCD_a16, sf_FBSTP_PACKED_BCD_a16, + sf_FISTPiq_a16, sf_FISTPiq_a16, sf_FISTPiq_a16, sf_FISTPiq_a16, sf_FISTPiq_a16, sf_FISTPiq_a16, sf_FISTPiq_a16, sf_FISTPiq_a16, + + sf_FFREEP_sti, sf_FFREEP_sti, sf_FFREEP_sti, sf_FFREEP_sti, sf_FFREEP_sti, sf_FFREEP_sti, sf_FFREEP_sti, sf_FFREEP_sti, + sf_FXCH_sti, sf_FXCH_sti, sf_FXCH_sti, sf_FXCH_sti, sf_FXCH_sti, sf_FXCH_sti, sf_FXCH_sti, sf_FXCH_sti, + sf_FSTP_sti, sf_FSTP_sti, sf_FSTP_sti, sf_FSTP_sti, sf_FSTP_sti, sf_FSTP_sti, sf_FSTP_sti, sf_FSTP_sti, + sf_FSTP_sti, sf_FSTP_sti, sf_FSTP_sti, sf_FSTP_sti, sf_FSTP_sti, sf_FSTP_sti, sf_FSTP_sti, sf_FSTP_sti, + sf_FNSTSW_AX, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, + ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, + ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, + ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, + // clang-format on +}; + +const OpFn OP_TABLE(sf_fpu_df_a32)[256] = { + // clang-format off + sf_FILDiw_a32, sf_FILDiw_a32, sf_FILDiw_a32, sf_FILDiw_a32, sf_FILDiw_a32, sf_FILDiw_a32, sf_FILDiw_a32, sf_FILDiw_a32, + ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, + sf_FISTiw_a32, sf_FISTiw_a32, sf_FISTiw_a32, sf_FISTiw_a32, sf_FISTiw_a32, sf_FISTiw_a32, sf_FISTiw_a32, sf_FISTiw_a32, + sf_FISTPiw_a32, sf_FISTPiw_a32, sf_FISTPiw_a32, sf_FISTPiw_a32, sf_FISTPiw_a32, sf_FISTPiw_a32, sf_FISTPiw_a32, sf_FISTPiw_a32, + ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, + sf_FILDiq_a32, sf_FILDiq_a32, sf_FILDiq_a32, sf_FILDiq_a32, sf_FILDiq_a32, sf_FILDiq_a32, sf_FILDiq_a32, sf_FILDiq_a32, + sf_FBSTP_PACKED_BCD_a32, sf_FBSTP_PACKED_BCD_a32, sf_FBSTP_PACKED_BCD_a32, sf_FBSTP_PACKED_BCD_a32, sf_FBSTP_PACKED_BCD_a32, sf_FBSTP_PACKED_BCD_a32, sf_FBSTP_PACKED_BCD_a32, sf_FBSTP_PACKED_BCD_a32, + sf_FISTPiq_a32, sf_FISTPiq_a32, sf_FISTPiq_a32, sf_FISTPiq_a32, sf_FISTPiq_a32, sf_FISTPiq_a32, sf_FISTPiq_a32, sf_FISTPiq_a32, + + sf_FILDiw_a32, sf_FILDiw_a32, sf_FILDiw_a32, sf_FILDiw_a32, sf_FILDiw_a32, sf_FILDiw_a32, sf_FILDiw_a32, sf_FILDiw_a32, + ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, + sf_FISTiw_a32, sf_FISTiw_a32, sf_FISTiw_a32, sf_FISTiw_a32, sf_FISTiw_a32, sf_FISTiw_a32, sf_FISTiw_a32, sf_FISTiw_a32, + sf_FISTPiw_a32, sf_FISTPiw_a32, sf_FISTPiw_a32, sf_FISTPiw_a32, sf_FISTPiw_a32, sf_FISTPiw_a32, sf_FISTPiw_a32, sf_FISTPiw_a32, + ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, + sf_FILDiq_a32, sf_FILDiq_a32, sf_FILDiq_a32, sf_FILDiq_a32, sf_FILDiq_a32, sf_FILDiq_a32, sf_FILDiq_a32, sf_FILDiq_a32, + sf_FBSTP_PACKED_BCD_a32, sf_FBSTP_PACKED_BCD_a32, sf_FBSTP_PACKED_BCD_a32, sf_FBSTP_PACKED_BCD_a32, sf_FBSTP_PACKED_BCD_a32, sf_FBSTP_PACKED_BCD_a32, sf_FBSTP_PACKED_BCD_a32, sf_FBSTP_PACKED_BCD_a32, + sf_FISTPiq_a32, sf_FISTPiq_a32, sf_FISTPiq_a32, sf_FISTPiq_a32, sf_FISTPiq_a32, sf_FISTPiq_a32, sf_FISTPiq_a32, sf_FISTPiq_a32, + + sf_FILDiw_a32, sf_FILDiw_a32, sf_FILDiw_a32, sf_FILDiw_a32, sf_FILDiw_a32, sf_FILDiw_a32, sf_FILDiw_a32, sf_FILDiw_a32, + ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, + sf_FISTiw_a32, sf_FISTiw_a32, sf_FISTiw_a32, sf_FISTiw_a32, sf_FISTiw_a32, sf_FISTiw_a32, sf_FISTiw_a32, sf_FISTiw_a32, + sf_FISTPiw_a32, sf_FISTPiw_a32, sf_FISTPiw_a32, sf_FISTPiw_a32, sf_FISTPiw_a32, sf_FISTPiw_a32, sf_FISTPiw_a32, sf_FISTPiw_a32, + ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, + sf_FILDiq_a32, sf_FILDiq_a32, sf_FILDiq_a32, sf_FILDiq_a32, sf_FILDiq_a32, sf_FILDiq_a32, sf_FILDiq_a32, sf_FILDiq_a32, + sf_FBSTP_PACKED_BCD_a32, sf_FBSTP_PACKED_BCD_a32, sf_FBSTP_PACKED_BCD_a32, sf_FBSTP_PACKED_BCD_a32, sf_FBSTP_PACKED_BCD_a32, sf_FBSTP_PACKED_BCD_a32, sf_FBSTP_PACKED_BCD_a32, sf_FBSTP_PACKED_BCD_a32, + sf_FISTPiq_a32, sf_FISTPiq_a32, sf_FISTPiq_a32, sf_FISTPiq_a32, sf_FISTPiq_a32, sf_FISTPiq_a32, sf_FISTPiq_a32, sf_FISTPiq_a32, + + sf_FFREEP_sti, sf_FFREEP_sti, sf_FFREEP_sti, sf_FFREEP_sti, sf_FFREEP_sti, sf_FFREEP_sti, sf_FFREEP_sti, sf_FFREEP_sti, + sf_FXCH_sti, sf_FXCH_sti, sf_FXCH_sti, sf_FXCH_sti, sf_FXCH_sti, sf_FXCH_sti, sf_FXCH_sti, sf_FXCH_sti, + sf_FSTP_sti, sf_FSTP_sti, sf_FSTP_sti, sf_FSTP_sti, sf_FSTP_sti, sf_FSTP_sti, sf_FSTP_sti, sf_FSTP_sti, + sf_FSTP_sti, sf_FSTP_sti, sf_FSTP_sti, sf_FSTP_sti, sf_FSTP_sti, sf_FSTP_sti, sf_FSTP_sti, sf_FSTP_sti, + sf_FNSTSW_AX, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, + ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, + ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, + ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, + // clang-format on +}; + +# ifndef OPS_286_386 +const OpFn OP_TABLE(sf_fpu_686_df_a16)[256] = { + // clang-format off + sf_FILDiw_a16, sf_FILDiw_a16, sf_FILDiw_a16, sf_FILDiw_a16, sf_FILDiw_a16, sf_FILDiw_a16, sf_FILDiw_a16, sf_FILDiw_a16, + ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, + sf_FISTiw_a16, sf_FISTiw_a16, sf_FISTiw_a16, sf_FISTiw_a16, sf_FISTiw_a16, sf_FISTiw_a16, sf_FISTiw_a16, sf_FISTiw_a16, + sf_FISTPiw_a16, sf_FISTPiw_a16, sf_FISTPiw_a16, sf_FISTPiw_a16, sf_FISTPiw_a16, sf_FISTPiw_a16, sf_FISTPiw_a16, sf_FISTPiw_a16, + ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, + sf_FILDiq_a16, sf_FILDiq_a16, sf_FILDiq_a16, sf_FILDiq_a16, sf_FILDiq_a16, sf_FILDiq_a16, sf_FILDiq_a16, sf_FILDiq_a16, + sf_FBSTP_PACKED_BCD_a16, sf_FBSTP_PACKED_BCD_a16, sf_FBSTP_PACKED_BCD_a16, sf_FBSTP_PACKED_BCD_a16, sf_FBSTP_PACKED_BCD_a16, sf_FBSTP_PACKED_BCD_a16, sf_FBSTP_PACKED_BCD_a16, sf_FBSTP_PACKED_BCD_a16, + sf_FISTPiq_a16, sf_FISTPiq_a16, sf_FISTPiq_a16, sf_FISTPiq_a16, sf_FISTPiq_a16, sf_FISTPiq_a16, sf_FISTPiq_a16, sf_FISTPiq_a16, + + sf_FILDiw_a16, sf_FILDiw_a16, sf_FILDiw_a16, sf_FILDiw_a16, sf_FILDiw_a16, sf_FILDiw_a16, sf_FILDiw_a16, sf_FILDiw_a16, + ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, + sf_FISTiw_a16, sf_FISTiw_a16, sf_FISTiw_a16, sf_FISTiw_a16, sf_FISTiw_a16, sf_FISTiw_a16, sf_FISTiw_a16, sf_FISTiw_a16, + sf_FISTPiw_a16, sf_FISTPiw_a16, sf_FISTPiw_a16, sf_FISTPiw_a16, sf_FISTPiw_a16, sf_FISTPiw_a16, sf_FISTPiw_a16, sf_FISTPiw_a16, + ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, + sf_FILDiq_a16, sf_FILDiq_a16, sf_FILDiq_a16, sf_FILDiq_a16, sf_FILDiq_a16, sf_FILDiq_a16, sf_FILDiq_a16, sf_FILDiq_a16, + sf_FBSTP_PACKED_BCD_a16, sf_FBSTP_PACKED_BCD_a16, sf_FBSTP_PACKED_BCD_a16, sf_FBSTP_PACKED_BCD_a16, sf_FBSTP_PACKED_BCD_a16, sf_FBSTP_PACKED_BCD_a16, sf_FBSTP_PACKED_BCD_a16, sf_FBSTP_PACKED_BCD_a16, + sf_FISTPiq_a16, sf_FISTPiq_a16, sf_FISTPiq_a16, sf_FISTPiq_a16, sf_FISTPiq_a16, sf_FISTPiq_a16, sf_FISTPiq_a16, sf_FISTPiq_a16, + + sf_FILDiw_a16, sf_FILDiw_a16, sf_FILDiw_a16, sf_FILDiw_a16, sf_FILDiw_a16, sf_FILDiw_a16, sf_FILDiw_a16, sf_FILDiw_a16, + ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, + sf_FISTiw_a16, sf_FISTiw_a16, sf_FISTiw_a16, sf_FISTiw_a16, sf_FISTiw_a16, sf_FISTiw_a16, sf_FISTiw_a16, sf_FISTiw_a16, + sf_FISTPiw_a16, sf_FISTPiw_a16, sf_FISTPiw_a16, sf_FISTPiw_a16, sf_FISTPiw_a16, sf_FISTPiw_a16, sf_FISTPiw_a16, sf_FISTPiw_a16, + ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, + sf_FILDiq_a16, sf_FILDiq_a16, sf_FILDiq_a16, sf_FILDiq_a16, sf_FILDiq_a16, sf_FILDiq_a16, sf_FILDiq_a16, sf_FILDiq_a16, + sf_FBSTP_PACKED_BCD_a16, sf_FBSTP_PACKED_BCD_a16, sf_FBSTP_PACKED_BCD_a16, sf_FBSTP_PACKED_BCD_a16, sf_FBSTP_PACKED_BCD_a16, sf_FBSTP_PACKED_BCD_a16, sf_FBSTP_PACKED_BCD_a16, sf_FBSTP_PACKED_BCD_a16, + sf_FISTPiq_a16, sf_FISTPiq_a16, sf_FISTPiq_a16, sf_FISTPiq_a16, sf_FISTPiq_a16, sf_FISTPiq_a16, sf_FISTPiq_a16, sf_FISTPiq_a16, + + sf_FFREEP_sti, sf_FFREEP_sti, sf_FFREEP_sti, sf_FFREEP_sti, sf_FFREEP_sti, sf_FFREEP_sti, sf_FFREEP_sti, sf_FFREEP_sti, + sf_FXCH_sti, sf_FXCH_sti, sf_FXCH_sti, sf_FXCH_sti, sf_FXCH_sti, sf_FXCH_sti, sf_FXCH_sti, sf_FXCH_sti, + sf_FSTP_sti, sf_FSTP_sti, sf_FSTP_sti, sf_FSTP_sti, sf_FSTP_sti, sf_FSTP_sti, sf_FSTP_sti, sf_FSTP_sti, + sf_FSTP_sti, sf_FSTP_sti, sf_FSTP_sti, sf_FSTP_sti, sf_FSTP_sti, sf_FSTP_sti, sf_FSTP_sti, sf_FSTP_sti, + sf_FNSTSW_AX, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, + sf_FUCOMIP_st0_stj, sf_FUCOMIP_st0_stj, sf_FUCOMIP_st0_stj, sf_FUCOMIP_st0_stj, sf_FUCOMIP_st0_stj, sf_FUCOMIP_st0_stj, sf_FUCOMIP_st0_stj, sf_FUCOMIP_st0_stj, + sf_FCOMIP_st0_stj, sf_FCOMIP_st0_stj, sf_FCOMIP_st0_stj, sf_FCOMIP_st0_stj, sf_FCOMIP_st0_stj, sf_FCOMIP_st0_stj, sf_FCOMIP_st0_stj, sf_FCOMIP_st0_stj, + ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, + // clang-format on +}; + +const OpFn OP_TABLE(sf_fpu_686_df_a32)[256] = { + // clang-format off + sf_FILDiw_a32, sf_FILDiw_a32, sf_FILDiw_a32, sf_FILDiw_a32, sf_FILDiw_a32, sf_FILDiw_a32, sf_FILDiw_a32, sf_FILDiw_a32, + ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, + sf_FISTiw_a32, sf_FISTiw_a32, sf_FISTiw_a32, sf_FISTiw_a32, sf_FISTiw_a32, sf_FISTiw_a32, sf_FISTiw_a32, sf_FISTiw_a32, + sf_FISTPiw_a32, sf_FISTPiw_a32, sf_FISTPiw_a32, sf_FISTPiw_a32, sf_FISTPiw_a32, sf_FISTPiw_a32, sf_FISTPiw_a32, sf_FISTPiw_a32, + ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, + sf_FILDiq_a32, sf_FILDiq_a32, sf_FILDiq_a32, sf_FILDiq_a32, sf_FILDiq_a32, sf_FILDiq_a32, sf_FILDiq_a32, sf_FILDiq_a32, + sf_FBSTP_PACKED_BCD_a32, sf_FBSTP_PACKED_BCD_a32, sf_FBSTP_PACKED_BCD_a32, sf_FBSTP_PACKED_BCD_a32, sf_FBSTP_PACKED_BCD_a32, sf_FBSTP_PACKED_BCD_a32, sf_FBSTP_PACKED_BCD_a32, sf_FBSTP_PACKED_BCD_a32, + sf_FISTPiq_a32, sf_FISTPiq_a32, sf_FISTPiq_a32, sf_FISTPiq_a32, sf_FISTPiq_a32, sf_FISTPiq_a32, sf_FISTPiq_a32, sf_FISTPiq_a32, + + sf_FILDiw_a32, sf_FILDiw_a32, sf_FILDiw_a32, sf_FILDiw_a32, sf_FILDiw_a32, sf_FILDiw_a32, sf_FILDiw_a32, sf_FILDiw_a32, + ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, + sf_FISTiw_a32, sf_FISTiw_a32, sf_FISTiw_a32, sf_FISTiw_a32, sf_FISTiw_a32, sf_FISTiw_a32, sf_FISTiw_a32, sf_FISTiw_a32, + sf_FISTPiw_a32, sf_FISTPiw_a32, sf_FISTPiw_a32, sf_FISTPiw_a32, sf_FISTPiw_a32, sf_FISTPiw_a32, sf_FISTPiw_a32, sf_FISTPiw_a32, + ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, + sf_FILDiq_a32, sf_FILDiq_a32, sf_FILDiq_a32, sf_FILDiq_a32, sf_FILDiq_a32, sf_FILDiq_a32, sf_FILDiq_a32, sf_FILDiq_a32, + sf_FBSTP_PACKED_BCD_a32, sf_FBSTP_PACKED_BCD_a32, sf_FBSTP_PACKED_BCD_a32, sf_FBSTP_PACKED_BCD_a32, sf_FBSTP_PACKED_BCD_a32, sf_FBSTP_PACKED_BCD_a32, sf_FBSTP_PACKED_BCD_a32, sf_FBSTP_PACKED_BCD_a32, + sf_FISTPiq_a32, sf_FISTPiq_a32, sf_FISTPiq_a32, sf_FISTPiq_a32, sf_FISTPiq_a32, sf_FISTPiq_a32, sf_FISTPiq_a32, sf_FISTPiq_a32, + + sf_FILDiw_a32, sf_FILDiw_a32, sf_FILDiw_a32, sf_FILDiw_a32, sf_FILDiw_a32, sf_FILDiw_a32, sf_FILDiw_a32, sf_FILDiw_a32, + ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, + sf_FISTiw_a32, sf_FISTiw_a32, sf_FISTiw_a32, sf_FISTiw_a32, sf_FISTiw_a32, sf_FISTiw_a32, sf_FISTiw_a32, sf_FISTiw_a32, + sf_FISTPiw_a32, sf_FISTPiw_a32, sf_FISTPiw_a32, sf_FISTPiw_a32, sf_FISTPiw_a32, sf_FISTPiw_a32, sf_FISTPiw_a32, sf_FISTPiw_a32, + ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, + sf_FILDiq_a32, sf_FILDiq_a32, sf_FILDiq_a32, sf_FILDiq_a32, sf_FILDiq_a32, sf_FILDiq_a32, sf_FILDiq_a32, sf_FILDiq_a32, + sf_FBSTP_PACKED_BCD_a32, sf_FBSTP_PACKED_BCD_a32, sf_FBSTP_PACKED_BCD_a32, sf_FBSTP_PACKED_BCD_a32, sf_FBSTP_PACKED_BCD_a32, sf_FBSTP_PACKED_BCD_a32, sf_FBSTP_PACKED_BCD_a32, sf_FBSTP_PACKED_BCD_a32, + sf_FISTPiq_a32, sf_FISTPiq_a32, sf_FISTPiq_a32, sf_FISTPiq_a32, sf_FISTPiq_a32, sf_FISTPiq_a32, sf_FISTPiq_a32, sf_FISTPiq_a32, + + sf_FFREEP_sti, sf_FFREEP_sti, sf_FFREEP_sti, sf_FFREEP_sti, sf_FFREEP_sti, sf_FFREEP_sti, sf_FFREEP_sti, sf_FFREEP_sti, + sf_FXCH_sti, sf_FXCH_sti, sf_FXCH_sti, sf_FXCH_sti, sf_FXCH_sti, sf_FXCH_sti, sf_FXCH_sti, sf_FXCH_sti, + sf_FSTP_sti, sf_FSTP_sti, sf_FSTP_sti, sf_FSTP_sti, sf_FSTP_sti, sf_FSTP_sti, sf_FSTP_sti, sf_FSTP_sti, + sf_FSTP_sti, sf_FSTP_sti, sf_FSTP_sti, sf_FSTP_sti, sf_FSTP_sti, sf_FSTP_sti, sf_FSTP_sti, sf_FSTP_sti, + sf_FNSTSW_AX, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, + sf_FUCOMIP_st0_stj, sf_FUCOMIP_st0_stj, sf_FUCOMIP_st0_stj, sf_FUCOMIP_st0_stj, sf_FUCOMIP_st0_stj, sf_FUCOMIP_st0_stj, sf_FUCOMIP_st0_stj, sf_FUCOMIP_st0_stj, + sf_FCOMIP_st0_stj, sf_FCOMIP_st0_stj, sf_FCOMIP_st0_stj, sf_FCOMIP_st0_stj, sf_FCOMIP_st0_stj, sf_FCOMIP_st0_stj, sf_FCOMIP_st0_stj, sf_FCOMIP_st0_stj, + ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, + // clang-format on +}; +# endif + +const OpFn OP_TABLE(fpu_d8_a16)[32] = { + // clang-format off opFADDs_a16, opFMULs_a16, opFCOMs_a16, opFCOMPs_a16, opFSUBs_a16, opFSUBRs_a16, opFDIVs_a16, opFDIVRs_a16, opFADDs_a16, opFMULs_a16, opFCOMs_a16, opFCOMPs_a16, opFSUBs_a16, opFSUBRs_a16, opFDIVs_a16, opFDIVRs_a16, opFADDs_a16, opFMULs_a16, opFCOMs_a16, opFCOMPs_a16, opFSUBs_a16, opFSUBRs_a16, opFDIVs_a16, opFDIVRs_a16, opFADD, opFMUL, opFCOM, opFCOMP, opFSUB, opFSUBR, opFDIV, opFDIVR + // clang-format on }; -const OpFn OP_TABLE(fpu_d8_a32)[32] = -{ + +const OpFn OP_TABLE(fpu_d8_a32)[32] = { + // clang-format off opFADDs_a32, opFMULs_a32, opFCOMs_a32, opFCOMPs_a32, opFSUBs_a32, opFSUBRs_a32, opFDIVs_a32, opFDIVRs_a32, opFADDs_a32, opFMULs_a32, opFCOMs_a32, opFCOMPs_a32, opFSUBs_a32, opFSUBRs_a32, opFDIVs_a32, opFDIVRs_a32, opFADDs_a32, opFMULs_a32, opFCOMs_a32, opFCOMPs_a32, opFSUBs_a32, opFSUBRs_a32, opFDIVs_a32, opFDIVRs_a32, opFADD, opFMUL, opFCOM, opFCOMP, opFSUB, opFSUBR, opFDIV, opFDIVR + // clang-format on }; -const OpFn OP_TABLE(fpu_287_d9_a16)[256] = -{ +const OpFn OP_TABLE(fpu_287_d9_a16)[256] = { + // clang-format off opFLDs_a16, opFLDs_a16, opFLDs_a16, opFLDs_a16, opFLDs_a16, opFLDs_a16, opFLDs_a16, opFLDs_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, opFSTs_a16, opFSTs_a16, opFSTs_a16, opFSTs_a16, opFSTs_a16, opFSTs_a16, opFSTs_a16, opFSTs_a16, opFSTPs_a16, opFSTPs_a16, opFSTPs_a16, opFSTPs_a16, opFSTPs_a16, opFSTPs_a16, opFSTPs_a16, opFSTPs_a16, - opFLDENV_a16, opFLDENV_a16, opFLDENV_a16, opFLDENV_a16, opFLDENV_a16, opFLDENV_a16, opFLDENV_a16, opFLDENV_a16, + opFLDENV_a16, opFLDENV_a16, opFLDENV_a16, opFLDENV_a16, opFLDENV_a16, opFLDENV_a16, opFLDENV_a16, opFLDENV_a16, opFLDCW_a16, opFLDCW_a16, opFLDCW_a16, opFLDCW_a16, opFLDCW_a16, opFLDCW_a16, opFLDCW_a16, opFLDCW_a16, opFSTENV_a16, opFSTENV_a16, opFSTENV_a16, opFSTENV_a16, opFSTENV_a16, opFSTENV_a16, opFSTENV_a16, opFSTENV_a16, opFSTCW_a16, opFSTCW_a16, opFSTCW_a16, opFSTCW_a16, opFSTCW_a16, opFSTCW_a16, opFSTCW_a16, opFSTCW_a16, @@ -870,7 +2383,7 @@ const OpFn OP_TABLE(fpu_287_d9_a16)[256] = ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, opFSTs_a16, opFSTs_a16, opFSTs_a16, opFSTs_a16, opFSTs_a16, opFSTs_a16, opFSTs_a16, opFSTs_a16, opFSTPs_a16, opFSTPs_a16, opFSTPs_a16, opFSTPs_a16, opFSTPs_a16, opFSTPs_a16, opFSTPs_a16, opFSTPs_a16, - opFLDENV_a16, opFLDENV_a16, opFLDENV_a16, opFLDENV_a16, opFLDENV_a16, opFLDENV_a16, opFLDENV_a16, opFLDENV_a16, + opFLDENV_a16, opFLDENV_a16, opFLDENV_a16, opFLDENV_a16, opFLDENV_a16, opFLDENV_a16, opFLDENV_a16, opFLDENV_a16, opFLDCW_a16, opFLDCW_a16, opFLDCW_a16, opFLDCW_a16, opFLDCW_a16, opFLDCW_a16, opFLDCW_a16, opFLDCW_a16, opFSTENV_a16, opFSTENV_a16, opFSTENV_a16, opFSTENV_a16, opFSTENV_a16, opFSTENV_a16, opFSTENV_a16, opFSTENV_a16, opFSTCW_a16, opFSTCW_a16, opFSTCW_a16, opFSTCW_a16, opFSTCW_a16, opFSTCW_a16, opFSTCW_a16, opFSTCW_a16, @@ -879,7 +2392,7 @@ const OpFn OP_TABLE(fpu_287_d9_a16)[256] = ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, opFSTs_a16, opFSTs_a16, opFSTs_a16, opFSTs_a16, opFSTs_a16, opFSTs_a16, opFSTs_a16, opFSTs_a16, opFSTPs_a16, opFSTPs_a16, opFSTPs_a16, opFSTPs_a16, opFSTPs_a16, opFSTPs_a16, opFSTPs_a16, opFSTPs_a16, - opFLDENV_a16, opFLDENV_a16, opFLDENV_a16, opFLDENV_a16, opFLDENV_a16, opFLDENV_a16, opFLDENV_a16, opFLDENV_a16, + opFLDENV_a16, opFLDENV_a16, opFLDENV_a16, opFLDENV_a16, opFLDENV_a16, opFLDENV_a16, opFLDENV_a16, opFLDENV_a16, opFLDCW_a16, opFLDCW_a16, opFLDCW_a16, opFLDCW_a16, opFLDCW_a16, opFLDCW_a16, opFLDCW_a16, opFLDCW_a16, opFSTENV_a16, opFSTENV_a16, opFSTENV_a16, opFSTENV_a16, opFSTENV_a16, opFSTENV_a16, opFSTENV_a16, opFSTENV_a16, opFSTCW_a16, opFSTCW_a16, opFSTCW_a16, opFSTCW_a16, opFSTCW_a16, opFSTCW_a16, opFSTCW_a16, opFSTCW_a16, @@ -890,17 +2403,18 @@ const OpFn OP_TABLE(fpu_287_d9_a16)[256] = ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, /*Invalid*/ opFCHS, opFABS, ILLEGAL_a16, ILLEGAL_a16, opFTST, opFXAM, ILLEGAL_a16, ILLEGAL_a16, opFLD1, opFLDL2T, opFLDL2E, opFLDPI, opFLDEG2, opFLDLN2, opFLDZ, ILLEGAL_a16, - opF2XM1, opFYL2X, opFPTAN, opFPATAN, ILLEGAL_a16, opFPREM1, opFDECSTP, opFINCSTP, + opF2XM1, opFYL2X, opFPTAN, opFPATAN, opFXTRACT, opFPREM1, opFDECSTP, opFINCSTP, opFPREM, opFYL2XP1, opFSQRT, opFSINCOS, opFRNDINT, opFSCALE, opFSIN, opFCOS + // clang-format on }; -const OpFn OP_TABLE(fpu_287_d9_a32)[256] = -{ +const OpFn OP_TABLE(fpu_287_d9_a32)[256] = { + // clang-format off opFLDs_a32, opFLDs_a32, opFLDs_a32, opFLDs_a32, opFLDs_a32, opFLDs_a32, opFLDs_a32, opFLDs_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, opFSTs_a32, opFSTs_a32, opFSTs_a32, opFSTs_a32, opFSTs_a32, opFSTs_a32, opFSTs_a32, opFSTs_a32, opFSTPs_a32, opFSTPs_a32, opFSTPs_a32, opFSTPs_a32, opFSTPs_a32, opFSTPs_a32, opFSTPs_a32, opFSTPs_a32, - opFLDENV_a32, opFLDENV_a32, opFLDENV_a32, opFLDENV_a32, opFLDENV_a32, opFLDENV_a32, opFLDENV_a32, opFLDENV_a32, + opFLDENV_a32, opFLDENV_a32, opFLDENV_a32, opFLDENV_a32, opFLDENV_a32, opFLDENV_a32, opFLDENV_a32, opFLDENV_a32, opFLDCW_a32, opFLDCW_a32, opFLDCW_a32, opFLDCW_a32, opFLDCW_a32, opFLDCW_a32, opFLDCW_a32, opFLDCW_a32, opFSTENV_a32, opFSTENV_a32, opFSTENV_a32, opFSTENV_a32, opFSTENV_a32, opFSTENV_a32, opFSTENV_a32, opFSTENV_a32, opFSTCW_a32, opFSTCW_a32, opFSTCW_a32, opFSTCW_a32, opFSTCW_a32, opFSTCW_a32, opFSTCW_a32, opFSTCW_a32, @@ -909,7 +2423,7 @@ const OpFn OP_TABLE(fpu_287_d9_a32)[256] = ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, opFSTs_a32, opFSTs_a32, opFSTs_a32, opFSTs_a32, opFSTs_a32, opFSTs_a32, opFSTs_a32, opFSTs_a32, opFSTPs_a32, opFSTPs_a32, opFSTPs_a32, opFSTPs_a32, opFSTPs_a32, opFSTPs_a32, opFSTPs_a32, opFSTPs_a32, - opFLDENV_a32, opFLDENV_a32, opFLDENV_a32, opFLDENV_a32, opFLDENV_a32, opFLDENV_a32, opFLDENV_a32, opFLDENV_a32, + opFLDENV_a32, opFLDENV_a32, opFLDENV_a32, opFLDENV_a32, opFLDENV_a32, opFLDENV_a32, opFLDENV_a32, opFLDENV_a32, opFLDCW_a32, opFLDCW_a32, opFLDCW_a32, opFLDCW_a32, opFLDCW_a32, opFLDCW_a32, opFLDCW_a32, opFLDCW_a32, opFSTENV_a32, opFSTENV_a32, opFSTENV_a32, opFSTENV_a32, opFSTENV_a32, opFSTENV_a32, opFSTENV_a32, opFSTENV_a32, opFSTCW_a32, opFSTCW_a32, opFSTCW_a32, opFSTCW_a32, opFSTCW_a32, opFSTCW_a32, opFSTCW_a32, opFSTCW_a32, @@ -918,7 +2432,7 @@ const OpFn OP_TABLE(fpu_287_d9_a32)[256] = ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, opFSTs_a32, opFSTs_a32, opFSTs_a32, opFSTs_a32, opFSTs_a32, opFSTs_a32, opFSTs_a32, opFSTs_a32, opFSTPs_a32, opFSTPs_a32, opFSTPs_a32, opFSTPs_a32, opFSTPs_a32, opFSTPs_a32, opFSTPs_a32, opFSTPs_a32, - opFLDENV_a32, opFLDENV_a32, opFLDENV_a32, opFLDENV_a32, opFLDENV_a32, opFLDENV_a32, opFLDENV_a32, opFLDENV_a32, + opFLDENV_a32, opFLDENV_a32, opFLDENV_a32, opFLDENV_a32, opFLDENV_a32, opFLDENV_a32, opFLDENV_a32, opFLDENV_a32, opFLDCW_a32, opFLDCW_a32, opFLDCW_a32, opFLDCW_a32, opFLDCW_a32, opFLDCW_a32, opFLDCW_a32, opFLDCW_a32, opFSTENV_a32, opFSTENV_a32, opFSTENV_a32, opFSTENV_a32, opFSTENV_a32, opFSTENV_a32, opFSTENV_a32, opFSTENV_a32, opFSTCW_a32, opFSTCW_a32, opFSTCW_a32, opFSTCW_a32, opFSTCW_a32, opFSTCW_a32, opFSTCW_a32, opFSTCW_a32, @@ -929,17 +2443,18 @@ const OpFn OP_TABLE(fpu_287_d9_a32)[256] = ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, /*Invalid*/ opFCHS, opFABS, ILLEGAL_a32, ILLEGAL_a32, opFTST, opFXAM, ILLEGAL_a32, ILLEGAL_a32, opFLD1, opFLDL2T, opFLDL2E, opFLDPI, opFLDEG2, opFLDLN2, opFLDZ, ILLEGAL_a32, - opF2XM1, opFYL2X, opFPTAN, opFPATAN, ILLEGAL_a32, opFPREM1, opFDECSTP, opFINCSTP, + opF2XM1, opFYL2X, opFPTAN, opFPATAN, opFXTRACT, opFPREM1, opFDECSTP, opFINCSTP, opFPREM, opFYL2XP1, opFSQRT, opFSINCOS, opFRNDINT, opFSCALE, opFSIN, opFCOS + // clang-format on }; -const OpFn OP_TABLE(fpu_d9_a16)[256] = -{ +const OpFn OP_TABLE(fpu_d9_a16)[256] = { + // clang-format off opFLDs_a16, opFLDs_a16, opFLDs_a16, opFLDs_a16, opFLDs_a16, opFLDs_a16, opFLDs_a16, opFLDs_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, opFSTs_a16, opFSTs_a16, opFSTs_a16, opFSTs_a16, opFSTs_a16, opFSTs_a16, opFSTs_a16, opFSTs_a16, opFSTPs_a16, opFSTPs_a16, opFSTPs_a16, opFSTPs_a16, opFSTPs_a16, opFSTPs_a16, opFSTPs_a16, opFSTPs_a16, - opFLDENV_a16, opFLDENV_a16, opFLDENV_a16, opFLDENV_a16, opFLDENV_a16, opFLDENV_a16, opFLDENV_a16, opFLDENV_a16, + opFLDENV_a16, opFLDENV_a16, opFLDENV_a16, opFLDENV_a16, opFLDENV_a16, opFLDENV_a16, opFLDENV_a16, opFLDENV_a16, opFLDCW_a16, opFLDCW_a16, opFLDCW_a16, opFLDCW_a16, opFLDCW_a16, opFLDCW_a16, opFLDCW_a16, opFLDCW_a16, opFSTENV_a16, opFSTENV_a16, opFSTENV_a16, opFSTENV_a16, opFSTENV_a16, opFSTENV_a16, opFSTENV_a16, opFSTENV_a16, opFSTCW_a16, opFSTCW_a16, opFSTCW_a16, opFSTCW_a16, opFSTCW_a16, opFSTCW_a16, opFSTCW_a16, opFSTCW_a16, @@ -948,7 +2463,7 @@ const OpFn OP_TABLE(fpu_d9_a16)[256] = ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, opFSTs_a16, opFSTs_a16, opFSTs_a16, opFSTs_a16, opFSTs_a16, opFSTs_a16, opFSTs_a16, opFSTs_a16, opFSTPs_a16, opFSTPs_a16, opFSTPs_a16, opFSTPs_a16, opFSTPs_a16, opFSTPs_a16, opFSTPs_a16, opFSTPs_a16, - opFLDENV_a16, opFLDENV_a16, opFLDENV_a16, opFLDENV_a16, opFLDENV_a16, opFLDENV_a16, opFLDENV_a16, opFLDENV_a16, + opFLDENV_a16, opFLDENV_a16, opFLDENV_a16, opFLDENV_a16, opFLDENV_a16, opFLDENV_a16, opFLDENV_a16, opFLDENV_a16, opFLDCW_a16, opFLDCW_a16, opFLDCW_a16, opFLDCW_a16, opFLDCW_a16, opFLDCW_a16, opFLDCW_a16, opFLDCW_a16, opFSTENV_a16, opFSTENV_a16, opFSTENV_a16, opFSTENV_a16, opFSTENV_a16, opFSTENV_a16, opFSTENV_a16, opFSTENV_a16, opFSTCW_a16, opFSTCW_a16, opFSTCW_a16, opFSTCW_a16, opFSTCW_a16, opFSTCW_a16, opFSTCW_a16, opFSTCW_a16, @@ -957,7 +2472,7 @@ const OpFn OP_TABLE(fpu_d9_a16)[256] = ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, opFSTs_a16, opFSTs_a16, opFSTs_a16, opFSTs_a16, opFSTs_a16, opFSTs_a16, opFSTs_a16, opFSTs_a16, opFSTPs_a16, opFSTPs_a16, opFSTPs_a16, opFSTPs_a16, opFSTPs_a16, opFSTPs_a16, opFSTPs_a16, opFSTPs_a16, - opFLDENV_a16, opFLDENV_a16, opFLDENV_a16, opFLDENV_a16, opFLDENV_a16, opFLDENV_a16, opFLDENV_a16, opFLDENV_a16, + opFLDENV_a16, opFLDENV_a16, opFLDENV_a16, opFLDENV_a16, opFLDENV_a16, opFLDENV_a16, opFLDENV_a16, opFLDENV_a16, opFLDCW_a16, opFLDCW_a16, opFLDCW_a16, opFLDCW_a16, opFLDCW_a16, opFLDCW_a16, opFLDCW_a16, opFLDCW_a16, opFSTENV_a16, opFSTENV_a16, opFSTENV_a16, opFSTENV_a16, opFSTENV_a16, opFSTENV_a16, opFSTENV_a16, opFSTENV_a16, opFSTCW_a16, opFSTCW_a16, opFSTCW_a16, opFSTCW_a16, opFSTCW_a16, opFSTCW_a16, opFSTCW_a16, opFSTCW_a16, @@ -968,17 +2483,18 @@ const OpFn OP_TABLE(fpu_d9_a16)[256] = opFSTP, opFSTP, opFSTP, opFSTP, opFSTP, opFSTP, opFSTP, opFSTP, /*Invalid*/ opFCHS, opFABS, ILLEGAL_a16, ILLEGAL_a16, opFTST, opFXAM, ILLEGAL_a16, ILLEGAL_a16, opFLD1, opFLDL2T, opFLDL2E, opFLDPI, opFLDEG2, opFLDLN2, opFLDZ, ILLEGAL_a16, - opF2XM1, opFYL2X, opFPTAN, opFPATAN, ILLEGAL_a16, opFPREM1, opFDECSTP, opFINCSTP, + opF2XM1, opFYL2X, opFPTAN, opFPATAN, opFXTRACT, opFPREM1, opFDECSTP, opFINCSTP, opFPREM, opFYL2XP1, opFSQRT, opFSINCOS, opFRNDINT, opFSCALE, opFSIN, opFCOS + // clang-format on }; -const OpFn OP_TABLE(fpu_d9_a32)[256] = -{ +const OpFn OP_TABLE(fpu_d9_a32)[256] = { + // clang-format off opFLDs_a32, opFLDs_a32, opFLDs_a32, opFLDs_a32, opFLDs_a32, opFLDs_a32, opFLDs_a32, opFLDs_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, opFSTs_a32, opFSTs_a32, opFSTs_a32, opFSTs_a32, opFSTs_a32, opFSTs_a32, opFSTs_a32, opFSTs_a32, opFSTPs_a32, opFSTPs_a32, opFSTPs_a32, opFSTPs_a32, opFSTPs_a32, opFSTPs_a32, opFSTPs_a32, opFSTPs_a32, - opFLDENV_a32, opFLDENV_a32, opFLDENV_a32, opFLDENV_a32, opFLDENV_a32, opFLDENV_a32, opFLDENV_a32, opFLDENV_a32, + opFLDENV_a32, opFLDENV_a32, opFLDENV_a32, opFLDENV_a32, opFLDENV_a32, opFLDENV_a32, opFLDENV_a32, opFLDENV_a32, opFLDCW_a32, opFLDCW_a32, opFLDCW_a32, opFLDCW_a32, opFLDCW_a32, opFLDCW_a32, opFLDCW_a32, opFLDCW_a32, opFSTENV_a32, opFSTENV_a32, opFSTENV_a32, opFSTENV_a32, opFSTENV_a32, opFSTENV_a32, opFSTENV_a32, opFSTENV_a32, opFSTCW_a32, opFSTCW_a32, opFSTCW_a32, opFSTCW_a32, opFSTCW_a32, opFSTCW_a32, opFSTCW_a32, opFSTCW_a32, @@ -987,7 +2503,7 @@ const OpFn OP_TABLE(fpu_d9_a32)[256] = ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, opFSTs_a32, opFSTs_a32, opFSTs_a32, opFSTs_a32, opFSTs_a32, opFSTs_a32, opFSTs_a32, opFSTs_a32, opFSTPs_a32, opFSTPs_a32, opFSTPs_a32, opFSTPs_a32, opFSTPs_a32, opFSTPs_a32, opFSTPs_a32, opFSTPs_a32, - opFLDENV_a32, opFLDENV_a32, opFLDENV_a32, opFLDENV_a32, opFLDENV_a32, opFLDENV_a32, opFLDENV_a32, opFLDENV_a32, + opFLDENV_a32, opFLDENV_a32, opFLDENV_a32, opFLDENV_a32, opFLDENV_a32, opFLDENV_a32, opFLDENV_a32, opFLDENV_a32, opFLDCW_a32, opFLDCW_a32, opFLDCW_a32, opFLDCW_a32, opFLDCW_a32, opFLDCW_a32, opFLDCW_a32, opFLDCW_a32, opFSTENV_a32, opFSTENV_a32, opFSTENV_a32, opFSTENV_a32, opFSTENV_a32, opFSTENV_a32, opFSTENV_a32, opFSTENV_a32, opFSTCW_a32, opFSTCW_a32, opFSTCW_a32, opFSTCW_a32, opFSTCW_a32, opFSTCW_a32, opFSTCW_a32, opFSTCW_a32, @@ -996,7 +2512,7 @@ const OpFn OP_TABLE(fpu_d9_a32)[256] = ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, opFSTs_a32, opFSTs_a32, opFSTs_a32, opFSTs_a32, opFSTs_a32, opFSTs_a32, opFSTs_a32, opFSTs_a32, opFSTPs_a32, opFSTPs_a32, opFSTPs_a32, opFSTPs_a32, opFSTPs_a32, opFSTPs_a32, opFSTPs_a32, opFSTPs_a32, - opFLDENV_a32, opFLDENV_a32, opFLDENV_a32, opFLDENV_a32, opFLDENV_a32, opFLDENV_a32, opFLDENV_a32, opFLDENV_a32, + opFLDENV_a32, opFLDENV_a32, opFLDENV_a32, opFLDENV_a32, opFLDENV_a32, opFLDENV_a32, opFLDENV_a32, opFLDENV_a32, opFLDCW_a32, opFLDCW_a32, opFLDCW_a32, opFLDCW_a32, opFLDCW_a32, opFLDCW_a32, opFLDCW_a32, opFLDCW_a32, opFSTENV_a32, opFSTENV_a32, opFSTENV_a32, opFSTENV_a32, opFSTENV_a32, opFSTENV_a32, opFSTENV_a32, opFSTENV_a32, opFSTCW_a32, opFSTCW_a32, opFSTCW_a32, opFSTCW_a32, opFSTCW_a32, opFSTCW_a32, opFSTCW_a32, opFSTCW_a32, @@ -1007,12 +2523,13 @@ const OpFn OP_TABLE(fpu_d9_a32)[256] = opFSTP, opFSTP, opFSTP, opFSTP, opFSTP, opFSTP, opFSTP, opFSTP, /*Invalid*/ opFCHS, opFABS, ILLEGAL_a32, ILLEGAL_a32, opFTST, opFXAM, ILLEGAL_a32, ILLEGAL_a32, opFLD1, opFLDL2T, opFLDL2E, opFLDPI, opFLDEG2, opFLDLN2, opFLDZ, ILLEGAL_a32, - opF2XM1, opFYL2X, opFPTAN, opFPATAN, ILLEGAL_a32, opFPREM1, opFDECSTP, opFINCSTP, + opF2XM1, opFYL2X, opFPTAN, opFPATAN, opFXTRACT, opFPREM1, opFDECSTP, opFINCSTP, opFPREM, opFYL2XP1, opFSQRT, opFSINCOS, opFRNDINT, opFSCALE, opFSIN, opFCOS + // clang-format on }; -const OpFn OP_TABLE(fpu_287_da_a16)[256] = -{ +const OpFn OP_TABLE(fpu_287_da_a16)[256] = { + // clang-format off opFADDil_a16, opFADDil_a16, opFADDil_a16, opFADDil_a16, opFADDil_a16, opFADDil_a16, opFADDil_a16, opFADDil_a16, opFMULil_a16, opFMULil_a16, opFMULil_a16, opFMULil_a16, opFMULil_a16, opFMULil_a16, opFMULil_a16, opFMULil_a16, opFCOMil_a16, opFCOMil_a16, opFCOMil_a16, opFCOMil_a16, opFCOMil_a16, opFCOMil_a16, opFCOMil_a16, opFCOMil_a16, @@ -1048,48 +2565,51 @@ const OpFn OP_TABLE(fpu_287_da_a16)[256] = ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, -}; -const OpFn OP_TABLE(fpu_287_da_a32)[256] = -{ - opFADDil_a32, opFADDil_a32, opFADDil_a32, opFADDil_a32, opFADDil_a32, opFADDil_a32, opFADDil_a32, opFADDil_a32, - opFMULil_a32, opFMULil_a32, opFMULil_a32, opFMULil_a32, opFMULil_a32, opFMULil_a32, opFMULil_a32, opFMULil_a32, - opFCOMil_a32, opFCOMil_a32, opFCOMil_a32, opFCOMil_a32, opFCOMil_a32, opFCOMil_a32, opFCOMil_a32, opFCOMil_a32, - opFCOMPil_a32, opFCOMPil_a32, opFCOMPil_a32, opFCOMPil_a32, opFCOMPil_a32, opFCOMPil_a32, opFCOMPil_a32, opFCOMPil_a32, - opFSUBil_a32, opFSUBil_a32, opFSUBil_a32, opFSUBil_a32, opFSUBil_a32, opFSUBil_a32, opFSUBil_a32, opFSUBil_a32, - opFSUBRil_a32, opFSUBRil_a32, opFSUBRil_a32, opFSUBRil_a32, opFSUBRil_a32, opFSUBRil_a32, opFSUBRil_a32, opFSUBRil_a32, - opFDIVil_a32, opFDIVil_a32, opFDIVil_a32, opFDIVil_a32, opFDIVil_a32, opFDIVil_a32, opFDIVil_a32, opFDIVil_a32, - opFDIVRil_a32, opFDIVRil_a32, opFDIVRil_a32, opFDIVRil_a32, opFDIVRil_a32, opFDIVRil_a32, opFDIVRil_a32, opFDIVRil_a32, - - opFADDil_a32, opFADDil_a32, opFADDil_a32, opFADDil_a32, opFADDil_a32, opFADDil_a32, opFADDil_a32, opFADDil_a32, - opFMULil_a32, opFMULil_a32, opFMULil_a32, opFMULil_a32, opFMULil_a32, opFMULil_a32, opFMULil_a32, opFMULil_a32, - opFCOMil_a32, opFCOMil_a32, opFCOMil_a32, opFCOMil_a32, opFCOMil_a32, opFCOMil_a32, opFCOMil_a32, opFCOMil_a32, - opFCOMPil_a32, opFCOMPil_a32, opFCOMPil_a32, opFCOMPil_a32, opFCOMPil_a32, opFCOMPil_a32, opFCOMPil_a32, opFCOMPil_a32, - opFSUBil_a32, opFSUBil_a32, opFSUBil_a32, opFSUBil_a32, opFSUBil_a32, opFSUBil_a32, opFSUBil_a32, opFSUBil_a32, - opFSUBRil_a32, opFSUBRil_a32, opFSUBRil_a32, opFSUBRil_a32, opFSUBRil_a32, opFSUBRil_a32, opFSUBRil_a32, opFSUBRil_a32, - opFDIVil_a32, opFDIVil_a32, opFDIVil_a32, opFDIVil_a32, opFDIVil_a32, opFDIVil_a32, opFDIVil_a32, opFDIVil_a32, - opFDIVRil_a32, opFDIVRil_a32, opFDIVRil_a32, opFDIVRil_a32, opFDIVRil_a32, opFDIVRil_a32, opFDIVRil_a32, opFDIVRil_a32, - - opFADDil_a32, opFADDil_a32, opFADDil_a32, opFADDil_a32, opFADDil_a32, opFADDil_a32, opFADDil_a32, opFADDil_a32, - opFMULil_a32, opFMULil_a32, opFMULil_a32, opFMULil_a32, opFMULil_a32, opFMULil_a32, opFMULil_a32, opFMULil_a32, - opFCOMil_a32, opFCOMil_a32, opFCOMil_a32, opFCOMil_a32, opFCOMil_a32, opFCOMil_a32, opFCOMil_a32, opFCOMil_a32, - opFCOMPil_a32, opFCOMPil_a32, opFCOMPil_a32, opFCOMPil_a32, opFCOMPil_a32, opFCOMPil_a32, opFCOMPil_a32, opFCOMPil_a32, - opFSUBil_a32, opFSUBil_a32, opFSUBil_a32, opFSUBil_a32, opFSUBil_a32, opFSUBil_a32, opFSUBil_a32, opFSUBil_a32, - opFSUBRil_a32, opFSUBRil_a32, opFSUBRil_a32, opFSUBRil_a32, opFSUBRil_a32, opFSUBRil_a32, opFSUBRil_a32, opFSUBRil_a32, - opFDIVil_a32, opFDIVil_a32, opFDIVil_a32, opFDIVil_a32, opFDIVil_a32, opFDIVil_a32, opFDIVil_a32, opFDIVil_a32, - opFDIVRil_a32, opFDIVRil_a32, opFDIVRil_a32, opFDIVRil_a32, opFDIVRil_a32, opFDIVRil_a32, opFDIVRil_a32, opFDIVRil_a32, - - ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, - ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, - ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, - ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, - ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, - ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, - ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, - ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, + // clang-format on }; -const OpFn OP_TABLE(fpu_da_a16)[256] = -{ +const OpFn OP_TABLE(fpu_287_da_a32)[256] = { + // clang-format off + opFADDil_a32, opFADDil_a32, opFADDil_a32, opFADDil_a32, opFADDil_a32, opFADDil_a32, opFADDil_a32, opFADDil_a32, + opFMULil_a32, opFMULil_a32, opFMULil_a32, opFMULil_a32, opFMULil_a32, opFMULil_a32, opFMULil_a32, opFMULil_a32, + opFCOMil_a32, opFCOMil_a32, opFCOMil_a32, opFCOMil_a32, opFCOMil_a32, opFCOMil_a32, opFCOMil_a32, opFCOMil_a32, + opFCOMPil_a32, opFCOMPil_a32, opFCOMPil_a32, opFCOMPil_a32, opFCOMPil_a32, opFCOMPil_a32, opFCOMPil_a32, opFCOMPil_a32, + opFSUBil_a32, opFSUBil_a32, opFSUBil_a32, opFSUBil_a32, opFSUBil_a32, opFSUBil_a32, opFSUBil_a32, opFSUBil_a32, + opFSUBRil_a32, opFSUBRil_a32, opFSUBRil_a32, opFSUBRil_a32, opFSUBRil_a32, opFSUBRil_a32, opFSUBRil_a32, opFSUBRil_a32, + opFDIVil_a32, opFDIVil_a32, opFDIVil_a32, opFDIVil_a32, opFDIVil_a32, opFDIVil_a32, opFDIVil_a32, opFDIVil_a32, + opFDIVRil_a32, opFDIVRil_a32, opFDIVRil_a32, opFDIVRil_a32, opFDIVRil_a32, opFDIVRil_a32, opFDIVRil_a32, opFDIVRil_a32, + + opFADDil_a32, opFADDil_a32, opFADDil_a32, opFADDil_a32, opFADDil_a32, opFADDil_a32, opFADDil_a32, opFADDil_a32, + opFMULil_a32, opFMULil_a32, opFMULil_a32, opFMULil_a32, opFMULil_a32, opFMULil_a32, opFMULil_a32, opFMULil_a32, + opFCOMil_a32, opFCOMil_a32, opFCOMil_a32, opFCOMil_a32, opFCOMil_a32, opFCOMil_a32, opFCOMil_a32, opFCOMil_a32, + opFCOMPil_a32, opFCOMPil_a32, opFCOMPil_a32, opFCOMPil_a32, opFCOMPil_a32, opFCOMPil_a32, opFCOMPil_a32, opFCOMPil_a32, + opFSUBil_a32, opFSUBil_a32, opFSUBil_a32, opFSUBil_a32, opFSUBil_a32, opFSUBil_a32, opFSUBil_a32, opFSUBil_a32, + opFSUBRil_a32, opFSUBRil_a32, opFSUBRil_a32, opFSUBRil_a32, opFSUBRil_a32, opFSUBRil_a32, opFSUBRil_a32, opFSUBRil_a32, + opFDIVil_a32, opFDIVil_a32, opFDIVil_a32, opFDIVil_a32, opFDIVil_a32, opFDIVil_a32, opFDIVil_a32, opFDIVil_a32, + opFDIVRil_a32, opFDIVRil_a32, opFDIVRil_a32, opFDIVRil_a32, opFDIVRil_a32, opFDIVRil_a32, opFDIVRil_a32, opFDIVRil_a32, + + opFADDil_a32, opFADDil_a32, opFADDil_a32, opFADDil_a32, opFADDil_a32, opFADDil_a32, opFADDil_a32, opFADDil_a32, + opFMULil_a32, opFMULil_a32, opFMULil_a32, opFMULil_a32, opFMULil_a32, opFMULil_a32, opFMULil_a32, opFMULil_a32, + opFCOMil_a32, opFCOMil_a32, opFCOMil_a32, opFCOMil_a32, opFCOMil_a32, opFCOMil_a32, opFCOMil_a32, opFCOMil_a32, + opFCOMPil_a32, opFCOMPil_a32, opFCOMPil_a32, opFCOMPil_a32, opFCOMPil_a32, opFCOMPil_a32, opFCOMPil_a32, opFCOMPil_a32, + opFSUBil_a32, opFSUBil_a32, opFSUBil_a32, opFSUBil_a32, opFSUBil_a32, opFSUBil_a32, opFSUBil_a32, opFSUBil_a32, + opFSUBRil_a32, opFSUBRil_a32, opFSUBRil_a32, opFSUBRil_a32, opFSUBRil_a32, opFSUBRil_a32, opFSUBRil_a32, opFSUBRil_a32, + opFDIVil_a32, opFDIVil_a32, opFDIVil_a32, opFDIVil_a32, opFDIVil_a32, opFDIVil_a32, opFDIVil_a32, opFDIVil_a32, + opFDIVRil_a32, opFDIVRil_a32, opFDIVRil_a32, opFDIVRil_a32, opFDIVRil_a32, opFDIVRil_a32, opFDIVRil_a32, opFDIVRil_a32, + + ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, + ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, + ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, + ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, + ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, + ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, + ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, + ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, + // clang-format on +}; + +const OpFn OP_TABLE(fpu_da_a16)[256] = { + // clang-format off opFADDil_a16, opFADDil_a16, opFADDil_a16, opFADDil_a16, opFADDil_a16, opFADDil_a16, opFADDil_a16, opFADDil_a16, opFMULil_a16, opFMULil_a16, opFMULil_a16, opFMULil_a16, opFMULil_a16, opFMULil_a16, opFMULil_a16, opFMULil_a16, opFCOMil_a16, opFCOMil_a16, opFCOMil_a16, opFCOMil_a16, opFCOMil_a16, opFCOMil_a16, opFCOMil_a16, opFCOMil_a16, @@ -1125,9 +2645,11 @@ const OpFn OP_TABLE(fpu_da_a16)[256] = ILLEGAL_a16, opFUCOMPP, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, + // clang-format on }; -const OpFn OP_TABLE(fpu_da_a32)[256] = -{ + +const OpFn OP_TABLE(fpu_da_a32)[256] = { + // clang-format off opFADDil_a32, opFADDil_a32, opFADDil_a32, opFADDil_a32, opFADDil_a32, opFADDil_a32, opFADDil_a32, opFADDil_a32, opFMULil_a32, opFMULil_a32, opFMULil_a32, opFMULil_a32, opFMULil_a32, opFMULil_a32, opFMULil_a32, opFMULil_a32, opFCOMil_a32, opFCOMil_a32, opFCOMil_a32, opFCOMil_a32, opFCOMil_a32, opFCOMil_a32, opFCOMil_a32, opFCOMil_a32, @@ -1163,10 +2685,12 @@ const OpFn OP_TABLE(fpu_da_a32)[256] = ILLEGAL_a32, opFUCOMPP, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, + // clang-format on }; -const OpFn OP_TABLE(fpu_686_da_a16)[256] = -{ +# ifndef OPS_286_386 +const OpFn OP_TABLE(fpu_686_da_a16)[256] = { + // clang-format off opFADDil_a16, opFADDil_a16, opFADDil_a16, opFADDil_a16, opFADDil_a16, opFADDil_a16, opFADDil_a16, opFADDil_a16, opFMULil_a16, opFMULil_a16, opFMULil_a16, opFMULil_a16, opFMULil_a16, opFMULil_a16, opFMULil_a16, opFMULil_a16, opFCOMil_a16, opFCOMil_a16, opFCOMil_a16, opFCOMil_a16, opFCOMil_a16, opFCOMil_a16, opFCOMil_a16, opFCOMil_a16, @@ -1202,9 +2726,11 @@ const OpFn OP_TABLE(fpu_686_da_a16)[256] = ILLEGAL_a16, opFUCOMPP, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, + // clang-format on }; -const OpFn OP_TABLE(fpu_686_da_a32)[256] = -{ + +const OpFn OP_TABLE(fpu_686_da_a32)[256] = { + // clang-format off opFADDil_a32, opFADDil_a32, opFADDil_a32, opFADDil_a32, opFADDil_a32, opFADDil_a32, opFADDil_a32, opFADDil_a32, opFMULil_a32, opFMULil_a32, opFMULil_a32, opFMULil_a32, opFMULil_a32, opFMULil_a32, opFMULil_a32, opFMULil_a32, opFCOMil_a32, opFCOMil_a32, opFCOMil_a32, opFCOMil_a32, opFCOMil_a32, opFCOMil_a32, opFCOMil_a32, opFCOMil_a32, @@ -1240,10 +2766,12 @@ const OpFn OP_TABLE(fpu_686_da_a32)[256] = ILLEGAL_a32, opFUCOMPP, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, + // clang-format on }; +# endif -const OpFn OP_TABLE(fpu_287_db_a16)[256] = -{ +const OpFn OP_TABLE(fpu_287_db_a16)[256] = { + // clang-format off opFILDil_a16, opFILDil_a16, opFILDil_a16, opFILDil_a16, opFILDil_a16, opFILDil_a16, opFILDil_a16, opFILDil_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, opFISTil_a16, opFISTil_a16, opFISTil_a16, opFISTil_a16, opFISTil_a16, opFISTil_a16, opFISTil_a16, opFISTil_a16, @@ -1279,9 +2807,11 @@ const OpFn OP_TABLE(fpu_287_db_a16)[256] = ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, + // clang-format on }; -const OpFn OP_TABLE(fpu_287_db_a32)[256] = -{ + +const OpFn OP_TABLE(fpu_287_db_a32)[256] = { + // clang-format off opFILDil_a32, opFILDil_a32, opFILDil_a32, opFILDil_a32, opFILDil_a32, opFILDil_a32, opFILDil_a32, opFILDil_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, opFISTil_a32, opFISTil_a32, opFISTil_a32, opFISTil_a32, opFISTil_a32, opFISTil_a32, opFISTil_a32, opFISTil_a32, @@ -1317,10 +2847,11 @@ const OpFn OP_TABLE(fpu_287_db_a32)[256] = ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, + // clang-format on }; -const OpFn OP_TABLE(fpu_db_a16)[256] = -{ +const OpFn OP_TABLE(fpu_db_a16)[256] = { + // clang-format off opFILDil_a16, opFILDil_a16, opFILDil_a16, opFILDil_a16, opFILDil_a16, opFILDil_a16, opFILDil_a16, opFILDil_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, opFISTil_a16, opFISTil_a16, opFISTil_a16, opFISTil_a16, opFISTil_a16, opFISTil_a16, opFISTil_a16, opFISTil_a16, @@ -1356,9 +2887,11 @@ const OpFn OP_TABLE(fpu_db_a16)[256] = ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, + // clang-format on }; -const OpFn OP_TABLE(fpu_db_a32)[256] = -{ + +const OpFn OP_TABLE(fpu_db_a32)[256] = { + // clang-format off opFILDil_a32, opFILDil_a32, opFILDil_a32, opFILDil_a32, opFILDil_a32, opFILDil_a32, opFILDil_a32, opFILDil_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, opFISTil_a32, opFISTil_a32, opFISTil_a32, opFISTil_a32, opFISTil_a32, opFISTil_a32, opFISTil_a32, opFISTil_a32, @@ -1394,10 +2927,12 @@ const OpFn OP_TABLE(fpu_db_a32)[256] = ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, + // clang-format on }; -const OpFn OP_TABLE(fpu_686_db_a16)[256] = -{ +# ifndef OPS_286_386 +const OpFn OP_TABLE(fpu_686_db_a16)[256] = { + // clang-format off opFILDil_a16, opFILDil_a16, opFILDil_a16, opFILDil_a16, opFILDil_a16, opFILDil_a16, opFILDil_a16, opFILDil_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, opFISTil_a16, opFISTil_a16, opFISTil_a16, opFISTil_a16, opFISTil_a16, opFISTil_a16, opFISTil_a16, opFISTil_a16, @@ -1433,9 +2968,10 @@ const OpFn OP_TABLE(fpu_686_db_a16)[256] = opFUCOMI, opFUCOMI, opFUCOMI, opFUCOMI, opFUCOMI, opFUCOMI, opFUCOMI, opFUCOMI, opFCOMI, opFCOMI, opFCOMI, opFCOMI, opFCOMI, opFCOMI, opFCOMI, opFCOMI, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, + // clang-format on }; -const OpFn OP_TABLE(fpu_686_db_a32)[256] = -{ +const OpFn OP_TABLE(fpu_686_db_a32)[256] = { + // clang-format off opFILDil_a32, opFILDil_a32, opFILDil_a32, opFILDil_a32, opFILDil_a32, opFILDil_a32, opFILDil_a32, opFILDil_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, opFISTil_a32, opFISTil_a32, opFISTil_a32, opFISTil_a32, opFISTil_a32, opFISTil_a32, opFISTil_a32, opFISTil_a32, @@ -1471,40 +3007,48 @@ const OpFn OP_TABLE(fpu_686_db_a32)[256] = opFUCOMI, opFUCOMI, opFUCOMI, opFUCOMI, opFUCOMI, opFUCOMI, opFUCOMI, opFUCOMI, opFCOMI, opFCOMI, opFCOMI, opFCOMI, opFCOMI, opFCOMI, opFCOMI, opFCOMI, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, + // clang-format on }; +# endif -const OpFn OP_TABLE(fpu_287_dc_a16)[32] = -{ +const OpFn OP_TABLE(fpu_287_dc_a16)[32] = { + // clang-format off opFADDd_a16, opFMULd_a16, opFCOMd_a16, opFCOMPd_a16, opFSUBd_a16, opFSUBRd_a16, opFDIVd_a16, opFDIVRd_a16, opFADDd_a16, opFMULd_a16, opFCOMd_a16, opFCOMPd_a16, opFSUBd_a16, opFSUBRd_a16, opFDIVd_a16, opFDIVRd_a16, opFADDd_a16, opFMULd_a16, opFCOMd_a16, opFCOMPd_a16, opFSUBd_a16, opFSUBRd_a16, opFDIVd_a16, opFDIVRd_a16, opFADDr, opFMULr, ILLEGAL_a16, ILLEGAL_a16, opFSUBRr, opFSUBr, opFDIVRr, opFDIVr + // clang-format on }; -const OpFn OP_TABLE(fpu_287_dc_a32)[32] = -{ + +const OpFn OP_TABLE(fpu_287_dc_a32)[32] = { + // clang-format off opFADDd_a32, opFMULd_a32, opFCOMd_a32, opFCOMPd_a32, opFSUBd_a32, opFSUBRd_a32, opFDIVd_a32, opFDIVRd_a32, opFADDd_a32, opFMULd_a32, opFCOMd_a32, opFCOMPd_a32, opFSUBd_a32, opFSUBRd_a32, opFDIVd_a32, opFDIVRd_a32, opFADDd_a32, opFMULd_a32, opFCOMd_a32, opFCOMPd_a32, opFSUBd_a32, opFSUBRd_a32, opFDIVd_a32, opFDIVRd_a32, opFADDr, opFMULr, ILLEGAL_a32, ILLEGAL_a32, opFSUBRr, opFSUBr, opFDIVRr, opFDIVr + // clang-format on }; -const OpFn OP_TABLE(fpu_dc_a16)[32] = -{ +const OpFn OP_TABLE(fpu_dc_a16)[32] = { + // clang-format off opFADDd_a16, opFMULd_a16, opFCOMd_a16, opFCOMPd_a16, opFSUBd_a16, opFSUBRd_a16, opFDIVd_a16, opFDIVRd_a16, opFADDd_a16, opFMULd_a16, opFCOMd_a16, opFCOMPd_a16, opFSUBd_a16, opFSUBRd_a16, opFDIVd_a16, opFDIVRd_a16, opFADDd_a16, opFMULd_a16, opFCOMd_a16, opFCOMPd_a16, opFSUBd_a16, opFSUBRd_a16, opFDIVd_a16, opFDIVRd_a16, opFADDr, opFMULr, opFCOM, opFCOMP, opFSUBRr, opFSUBr, opFDIVRr, opFDIVr + // clang-format on }; -const OpFn OP_TABLE(fpu_dc_a32)[32] = -{ + +const OpFn OP_TABLE(fpu_dc_a32)[32] = { + // clang-format off opFADDd_a32, opFMULd_a32, opFCOMd_a32, opFCOMPd_a32, opFSUBd_a32, opFSUBRd_a32, opFDIVd_a32, opFDIVRd_a32, opFADDd_a32, opFMULd_a32, opFCOMd_a32, opFCOMPd_a32, opFSUBd_a32, opFSUBRd_a32, opFDIVd_a32, opFDIVRd_a32, opFADDd_a32, opFMULd_a32, opFCOMd_a32, opFCOMPd_a32, opFSUBd_a32, opFSUBRd_a32, opFDIVd_a32, opFDIVRd_a32, opFADDr, opFMULr, opFCOM, opFCOMP, opFSUBRr, opFSUBr, opFDIVRr, opFDIVr + // clang-format on }; -const OpFn OP_TABLE(fpu_287_dd_a16)[256] = -{ +const OpFn OP_TABLE(fpu_287_dd_a16)[256] = { + // clang-format off opFLDd_a16, opFLDd_a16, opFLDd_a16, opFLDd_a16, opFLDd_a16, opFLDd_a16, opFLDd_a16, opFLDd_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, opFSTd_a16, opFSTd_a16, opFSTd_a16, opFSTd_a16, opFSTd_a16, opFSTd_a16, opFSTd_a16, opFSTd_a16, @@ -1540,9 +3084,11 @@ const OpFn OP_TABLE(fpu_287_dd_a16)[256] = ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, + // clang-format on }; -const OpFn OP_TABLE(fpu_287_dd_a32)[256] = -{ + +const OpFn OP_TABLE(fpu_287_dd_a32)[256] = { + // clang-format off opFLDd_a32, opFLDd_a32, opFLDd_a32, opFLDd_a32, opFLDd_a32, opFLDd_a32, opFLDd_a32, opFLDd_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, opFSTd_a32, opFSTd_a32, opFSTd_a32, opFSTd_a32, opFSTd_a32, opFSTd_a32, opFSTd_a32, opFSTd_a32, @@ -1578,10 +3124,11 @@ const OpFn OP_TABLE(fpu_287_dd_a32)[256] = ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, + // clang-format on }; -const OpFn OP_TABLE(fpu_dd_a16)[256] = -{ +const OpFn OP_TABLE(fpu_dd_a16)[256] = { + // clang-format off opFLDd_a16, opFLDd_a16, opFLDd_a16, opFLDd_a16, opFLDd_a16, opFLDd_a16, opFLDd_a16, opFLDd_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, opFSTd_a16, opFSTd_a16, opFSTd_a16, opFSTd_a16, opFSTd_a16, opFSTd_a16, opFSTd_a16, opFSTd_a16, @@ -1617,9 +3164,11 @@ const OpFn OP_TABLE(fpu_dd_a16)[256] = opFUCOMP, opFUCOMP, opFUCOMP, opFUCOMP, opFUCOMP, opFUCOMP, opFUCOMP, opFUCOMP, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, + // clang-format on }; -const OpFn OP_TABLE(fpu_dd_a32)[256] = -{ + +const OpFn OP_TABLE(fpu_dd_a32)[256] = { + // clang-format off opFLDd_a32, opFLDd_a32, opFLDd_a32, opFLDd_a32, opFLDd_a32, opFLDd_a32, opFLDd_a32, opFLDd_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, opFSTd_a32, opFSTd_a32, opFSTd_a32, opFSTd_a32, opFSTd_a32, opFSTd_a32, opFSTd_a32, opFSTd_a32, @@ -1655,10 +3204,11 @@ const OpFn OP_TABLE(fpu_dd_a32)[256] = opFUCOMP, opFUCOMP, opFUCOMP, opFUCOMP, opFUCOMP, opFUCOMP, opFUCOMP, opFUCOMP, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, + // clang-format on }; -const OpFn OP_TABLE(fpu_287_de_a16)[256] = -{ +const OpFn OP_TABLE(fpu_287_de_a16)[256] = { + // clang-format off opFADDiw_a16, opFADDiw_a16, opFADDiw_a16, opFADDiw_a16, opFADDiw_a16, opFADDiw_a16, opFADDiw_a16, opFADDiw_a16, opFMULiw_a16, opFMULiw_a16, opFMULiw_a16, opFMULiw_a16, opFMULiw_a16, opFMULiw_a16, opFMULiw_a16, opFMULiw_a16, opFCOMiw_a16, opFCOMiw_a16, opFCOMiw_a16, opFCOMiw_a16, opFCOMiw_a16, opFCOMiw_a16, opFCOMiw_a16, opFCOMiw_a16, @@ -1694,10 +3244,11 @@ const OpFn OP_TABLE(fpu_287_de_a16)[256] = opFSUBP, opFSUBP, opFSUBP, opFSUBP, opFSUBP, opFSUBP, opFSUBP, opFSUBP, opFDIVRP, opFDIVRP, opFDIVRP, opFDIVRP, opFDIVRP, opFDIVRP, opFDIVRP, opFDIVRP, opFDIVP, opFDIVP, opFDIVP, opFDIVP, opFDIVP, opFDIVP, opFDIVP, opFDIVP, + // clang-format on }; -const OpFn OP_TABLE(fpu_287_de_a32)[256] = -{ +const OpFn OP_TABLE(fpu_287_de_a32)[256] = { + // clang-format off opFADDiw_a32, opFADDiw_a32, opFADDiw_a32, opFADDiw_a32, opFADDiw_a32, opFADDiw_a32, opFADDiw_a32, opFADDiw_a32, opFMULiw_a32, opFMULiw_a32, opFMULiw_a32, opFMULiw_a32, opFMULiw_a32, opFMULiw_a32, opFMULiw_a32, opFMULiw_a32, opFCOMiw_a32, opFCOMiw_a32, opFCOMiw_a32, opFCOMiw_a32, opFCOMiw_a32, opFCOMiw_a32, opFCOMiw_a32, opFCOMiw_a32, @@ -1733,10 +3284,11 @@ const OpFn OP_TABLE(fpu_287_de_a32)[256] = opFSUBP, opFSUBP, opFSUBP, opFSUBP, opFSUBP, opFSUBP, opFSUBP, opFSUBP, opFDIVRP, opFDIVRP, opFDIVRP, opFDIVRP, opFDIVRP, opFDIVRP, opFDIVRP, opFDIVRP, opFDIVP, opFDIVP, opFDIVP, opFDIVP, opFDIVP, opFDIVP, opFDIVP, opFDIVP, + // clang-format on }; -const OpFn OP_TABLE(fpu_de_a16)[256] = -{ +const OpFn OP_TABLE(fpu_de_a16)[256] = { + // clang-format off opFADDiw_a16, opFADDiw_a16, opFADDiw_a16, opFADDiw_a16, opFADDiw_a16, opFADDiw_a16, opFADDiw_a16, opFADDiw_a16, opFMULiw_a16, opFMULiw_a16, opFMULiw_a16, opFMULiw_a16, opFMULiw_a16, opFMULiw_a16, opFMULiw_a16, opFMULiw_a16, opFCOMiw_a16, opFCOMiw_a16, opFCOMiw_a16, opFCOMiw_a16, opFCOMiw_a16, opFCOMiw_a16, opFCOMiw_a16, opFCOMiw_a16, @@ -1772,10 +3324,11 @@ const OpFn OP_TABLE(fpu_de_a16)[256] = opFSUBP, opFSUBP, opFSUBP, opFSUBP, opFSUBP, opFSUBP, opFSUBP, opFSUBP, opFDIVRP, opFDIVRP, opFDIVRP, opFDIVRP, opFDIVRP, opFDIVRP, opFDIVRP, opFDIVRP, opFDIVP, opFDIVP, opFDIVP, opFDIVP, opFDIVP, opFDIVP, opFDIVP, opFDIVP, + // clang-format on }; -const OpFn OP_TABLE(fpu_de_a32)[256] = -{ +const OpFn OP_TABLE(fpu_de_a32)[256] = { + // clang-format off opFADDiw_a32, opFADDiw_a32, opFADDiw_a32, opFADDiw_a32, opFADDiw_a32, opFADDiw_a32, opFADDiw_a32, opFADDiw_a32, opFMULiw_a32, opFMULiw_a32, opFMULiw_a32, opFMULiw_a32, opFMULiw_a32, opFMULiw_a32, opFMULiw_a32, opFMULiw_a32, opFCOMiw_a32, opFCOMiw_a32, opFCOMiw_a32, opFCOMiw_a32, opFCOMiw_a32, opFCOMiw_a32, opFCOMiw_a32, opFCOMiw_a32, @@ -1811,10 +3364,11 @@ const OpFn OP_TABLE(fpu_de_a32)[256] = opFSUBP, opFSUBP, opFSUBP, opFSUBP, opFSUBP, opFSUBP, opFSUBP, opFSUBP, opFDIVRP, opFDIVRP, opFDIVRP, opFDIVRP, opFDIVRP, opFDIVRP, opFDIVRP, opFDIVRP, opFDIVP, opFDIVP, opFDIVP, opFDIVP, opFDIVP, opFDIVP, opFDIVP, opFDIVP, + // clang-format on }; -const OpFn OP_TABLE(fpu_287_df_a16)[256] = -{ +const OpFn OP_TABLE(fpu_287_df_a16)[256] = { + // clang-format off opFILDiw_a16, opFILDiw_a16, opFILDiw_a16, opFILDiw_a16, opFILDiw_a16, opFILDiw_a16, opFILDiw_a16, opFILDiw_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, opFISTiw_a16, opFISTiw_a16, opFISTiw_a16, opFISTiw_a16, opFISTiw_a16, opFISTiw_a16, opFISTiw_a16, opFISTiw_a16, @@ -1850,9 +3404,11 @@ const OpFn OP_TABLE(fpu_287_df_a16)[256] = ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, + // clang-format on }; -const OpFn OP_TABLE(fpu_287_df_a32)[256] = -{ + +const OpFn OP_TABLE(fpu_287_df_a32)[256] = { + // clang-format off opFILDiw_a32, opFILDiw_a32, opFILDiw_a32, opFILDiw_a32, opFILDiw_a32, opFILDiw_a32, opFILDiw_a32, opFILDiw_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, opFISTiw_a32, opFISTiw_a32, opFISTiw_a32, opFISTiw_a32, opFISTiw_a32, opFISTiw_a32, opFISTiw_a32, opFISTiw_a32, @@ -1888,10 +3444,11 @@ const OpFn OP_TABLE(fpu_287_df_a32)[256] = ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, + // clang-format on }; -const OpFn OP_TABLE(fpu_df_a16)[256] = -{ +const OpFn OP_TABLE(fpu_df_a16)[256] = { + // clang-format off opFILDiw_a16, opFILDiw_a16, opFILDiw_a16, opFILDiw_a16, opFILDiw_a16, opFILDiw_a16, opFILDiw_a16, opFILDiw_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, opFISTiw_a16, opFISTiw_a16, opFISTiw_a16, opFISTiw_a16, opFISTiw_a16, opFISTiw_a16, opFISTiw_a16, opFISTiw_a16, @@ -1927,9 +3484,11 @@ const OpFn OP_TABLE(fpu_df_a16)[256] = ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, + // clang-format on }; -const OpFn OP_TABLE(fpu_df_a32)[256] = -{ + +const OpFn OP_TABLE(fpu_df_a32)[256] = { + // clang-format off opFILDiw_a32, opFILDiw_a32, opFILDiw_a32, opFILDiw_a32, opFILDiw_a32, opFILDiw_a32, opFILDiw_a32, opFILDiw_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, opFISTiw_a32, opFISTiw_a32, opFISTiw_a32, opFISTiw_a32, opFISTiw_a32, opFISTiw_a32, opFISTiw_a32, opFISTiw_a32, @@ -1965,10 +3524,12 @@ const OpFn OP_TABLE(fpu_df_a32)[256] = ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, + // clang-format on }; -const OpFn OP_TABLE(fpu_686_df_a16)[256] = -{ +# ifndef OPS_286_386 +const OpFn OP_TABLE(fpu_686_df_a16)[256] = { + // clang-format off opFILDiw_a16, opFILDiw_a16, opFILDiw_a16, opFILDiw_a16, opFILDiw_a16, opFILDiw_a16, opFILDiw_a16, opFILDiw_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, opFISTiw_a16, opFISTiw_a16, opFISTiw_a16, opFISTiw_a16, opFISTiw_a16, opFISTiw_a16, opFISTiw_a16, opFISTiw_a16, @@ -2004,9 +3565,11 @@ const OpFn OP_TABLE(fpu_686_df_a16)[256] = opFUCOMIP, opFUCOMIP, opFUCOMIP, opFUCOMIP, opFUCOMIP, opFUCOMIP, opFUCOMIP, opFUCOMIP, opFCOMIP, opFCOMIP, opFCOMIP, opFCOMIP, opFCOMIP, opFCOMIP, opFCOMIP, opFCOMIP, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, + // clang-format on }; -const OpFn OP_TABLE(fpu_686_df_a32)[256] = -{ + +const OpFn OP_TABLE(fpu_686_df_a32)[256] = { + // clang-format off opFILDiw_a32, opFILDiw_a32, opFILDiw_a32, opFILDiw_a32, opFILDiw_a32, opFILDiw_a32, opFILDiw_a32, opFILDiw_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, opFISTiw_a32, opFISTiw_a32, opFISTiw_a32, opFISTiw_a32, opFISTiw_a32, opFISTiw_a32, opFISTiw_a32, opFISTiw_a32, @@ -2042,48 +3605,52 @@ const OpFn OP_TABLE(fpu_686_df_a32)[256] = opFUCOMIP, opFUCOMIP, opFUCOMIP, opFUCOMIP, opFUCOMIP, opFUCOMIP, opFUCOMIP, opFUCOMIP, opFCOMIP, opFCOMIP, opFCOMIP, opFCOMIP, opFCOMIP, opFCOMIP, opFCOMIP, opFCOMIP, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, + // clang-format on +}; +# endif + +const OpFn OP_TABLE(nofpu_a16)[256] = { + // clang-format off + op_nofpu_a16, op_nofpu_a16, op_nofpu_a16, op_nofpu_a16, op_nofpu_a16, op_nofpu_a16, op_nofpu_a16, op_nofpu_a16, + op_nofpu_a16, op_nofpu_a16, op_nofpu_a16, op_nofpu_a16, op_nofpu_a16, op_nofpu_a16, op_nofpu_a16, op_nofpu_a16, + op_nofpu_a16, op_nofpu_a16, op_nofpu_a16, op_nofpu_a16, op_nofpu_a16, op_nofpu_a16, op_nofpu_a16, op_nofpu_a16, + op_nofpu_a16, op_nofpu_a16, op_nofpu_a16, op_nofpu_a16, op_nofpu_a16, op_nofpu_a16, op_nofpu_a16, op_nofpu_a16, + op_nofpu_a16, op_nofpu_a16, op_nofpu_a16, op_nofpu_a16, op_nofpu_a16, op_nofpu_a16, op_nofpu_a16, op_nofpu_a16, + op_nofpu_a16, op_nofpu_a16, op_nofpu_a16, op_nofpu_a16, op_nofpu_a16, op_nofpu_a16, op_nofpu_a16, op_nofpu_a16, + op_nofpu_a16, op_nofpu_a16, op_nofpu_a16, op_nofpu_a16, op_nofpu_a16, op_nofpu_a16, op_nofpu_a16, op_nofpu_a16, + op_nofpu_a16, op_nofpu_a16, op_nofpu_a16, op_nofpu_a16, op_nofpu_a16, op_nofpu_a16, op_nofpu_a16, op_nofpu_a16, + + op_nofpu_a16, op_nofpu_a16, op_nofpu_a16, op_nofpu_a16, op_nofpu_a16, op_nofpu_a16, op_nofpu_a16, op_nofpu_a16, + op_nofpu_a16, op_nofpu_a16, op_nofpu_a16, op_nofpu_a16, op_nofpu_a16, op_nofpu_a16, op_nofpu_a16, op_nofpu_a16, + op_nofpu_a16, op_nofpu_a16, op_nofpu_a16, op_nofpu_a16, op_nofpu_a16, op_nofpu_a16, op_nofpu_a16, op_nofpu_a16, + op_nofpu_a16, op_nofpu_a16, op_nofpu_a16, op_nofpu_a16, op_nofpu_a16, op_nofpu_a16, op_nofpu_a16, op_nofpu_a16, + op_nofpu_a16, op_nofpu_a16, op_nofpu_a16, op_nofpu_a16, op_nofpu_a16, op_nofpu_a16, op_nofpu_a16, op_nofpu_a16, + op_nofpu_a16, op_nofpu_a16, op_nofpu_a16, op_nofpu_a16, op_nofpu_a16, op_nofpu_a16, op_nofpu_a16, op_nofpu_a16, + op_nofpu_a16, op_nofpu_a16, op_nofpu_a16, op_nofpu_a16, op_nofpu_a16, op_nofpu_a16, op_nofpu_a16, op_nofpu_a16, + op_nofpu_a16, op_nofpu_a16, op_nofpu_a16, op_nofpu_a16, op_nofpu_a16, op_nofpu_a16, op_nofpu_a16, op_nofpu_a16, + + op_nofpu_a16, op_nofpu_a16, op_nofpu_a16, op_nofpu_a16, op_nofpu_a16, op_nofpu_a16, op_nofpu_a16, op_nofpu_a16, + op_nofpu_a16, op_nofpu_a16, op_nofpu_a16, op_nofpu_a16, op_nofpu_a16, op_nofpu_a16, op_nofpu_a16, op_nofpu_a16, + op_nofpu_a16, op_nofpu_a16, op_nofpu_a16, op_nofpu_a16, op_nofpu_a16, op_nofpu_a16, op_nofpu_a16, op_nofpu_a16, + op_nofpu_a16, op_nofpu_a16, op_nofpu_a16, op_nofpu_a16, op_nofpu_a16, op_nofpu_a16, op_nofpu_a16, op_nofpu_a16, + op_nofpu_a16, op_nofpu_a16, op_nofpu_a16, op_nofpu_a16, op_nofpu_a16, op_nofpu_a16, op_nofpu_a16, op_nofpu_a16, + op_nofpu_a16, op_nofpu_a16, op_nofpu_a16, op_nofpu_a16, op_nofpu_a16, op_nofpu_a16, op_nofpu_a16, op_nofpu_a16, + op_nofpu_a16, op_nofpu_a16, op_nofpu_a16, op_nofpu_a16, op_nofpu_a16, op_nofpu_a16, op_nofpu_a16, op_nofpu_a16, + op_nofpu_a16, op_nofpu_a16, op_nofpu_a16, op_nofpu_a16, op_nofpu_a16, op_nofpu_a16, op_nofpu_a16, op_nofpu_a16, + + op_nofpu_a16, op_nofpu_a16, op_nofpu_a16, op_nofpu_a16, op_nofpu_a16, op_nofpu_a16, op_nofpu_a16, op_nofpu_a16, + op_nofpu_a16, op_nofpu_a16, op_nofpu_a16, op_nofpu_a16, op_nofpu_a16, op_nofpu_a16, op_nofpu_a16, op_nofpu_a16, + op_nofpu_a16, op_nofpu_a16, op_nofpu_a16, op_nofpu_a16, op_nofpu_a16, op_nofpu_a16, op_nofpu_a16, op_nofpu_a16, + op_nofpu_a16, op_nofpu_a16, op_nofpu_a16, op_nofpu_a16, op_nofpu_a16, op_nofpu_a16, op_nofpu_a16, op_nofpu_a16, + op_nofpu_a16, op_nofpu_a16, op_nofpu_a16, op_nofpu_a16, op_nofpu_a16, op_nofpu_a16, op_nofpu_a16, op_nofpu_a16, + op_nofpu_a16, op_nofpu_a16, op_nofpu_a16, op_nofpu_a16, op_nofpu_a16, op_nofpu_a16, op_nofpu_a16, op_nofpu_a16, + op_nofpu_a16, op_nofpu_a16, op_nofpu_a16, op_nofpu_a16, op_nofpu_a16, op_nofpu_a16, op_nofpu_a16, op_nofpu_a16, + op_nofpu_a16, op_nofpu_a16, op_nofpu_a16, op_nofpu_a16, op_nofpu_a16, op_nofpu_a16, op_nofpu_a16, op_nofpu_a16, + // clang-format on }; -const OpFn OP_TABLE(nofpu_a16)[256] = -{ - op_nofpu_a16, op_nofpu_a16, op_nofpu_a16, op_nofpu_a16, op_nofpu_a16, op_nofpu_a16, op_nofpu_a16, op_nofpu_a16, - op_nofpu_a16, op_nofpu_a16, op_nofpu_a16, op_nofpu_a16, op_nofpu_a16, op_nofpu_a16, op_nofpu_a16, op_nofpu_a16, - op_nofpu_a16, op_nofpu_a16, op_nofpu_a16, op_nofpu_a16, op_nofpu_a16, op_nofpu_a16, op_nofpu_a16, op_nofpu_a16, - op_nofpu_a16, op_nofpu_a16, op_nofpu_a16, op_nofpu_a16, op_nofpu_a16, op_nofpu_a16, op_nofpu_a16, op_nofpu_a16, - op_nofpu_a16, op_nofpu_a16, op_nofpu_a16, op_nofpu_a16, op_nofpu_a16, op_nofpu_a16, op_nofpu_a16, op_nofpu_a16, - op_nofpu_a16, op_nofpu_a16, op_nofpu_a16, op_nofpu_a16, op_nofpu_a16, op_nofpu_a16, op_nofpu_a16, op_nofpu_a16, - op_nofpu_a16, op_nofpu_a16, op_nofpu_a16, op_nofpu_a16, op_nofpu_a16, op_nofpu_a16, op_nofpu_a16, op_nofpu_a16, - op_nofpu_a16, op_nofpu_a16, op_nofpu_a16, op_nofpu_a16, op_nofpu_a16, op_nofpu_a16, op_nofpu_a16, op_nofpu_a16, - - op_nofpu_a16, op_nofpu_a16, op_nofpu_a16, op_nofpu_a16, op_nofpu_a16, op_nofpu_a16, op_nofpu_a16, op_nofpu_a16, - op_nofpu_a16, op_nofpu_a16, op_nofpu_a16, op_nofpu_a16, op_nofpu_a16, op_nofpu_a16, op_nofpu_a16, op_nofpu_a16, - op_nofpu_a16, op_nofpu_a16, op_nofpu_a16, op_nofpu_a16, op_nofpu_a16, op_nofpu_a16, op_nofpu_a16, op_nofpu_a16, - op_nofpu_a16, op_nofpu_a16, op_nofpu_a16, op_nofpu_a16, op_nofpu_a16, op_nofpu_a16, op_nofpu_a16, op_nofpu_a16, - op_nofpu_a16, op_nofpu_a16, op_nofpu_a16, op_nofpu_a16, op_nofpu_a16, op_nofpu_a16, op_nofpu_a16, op_nofpu_a16, - op_nofpu_a16, op_nofpu_a16, op_nofpu_a16, op_nofpu_a16, op_nofpu_a16, op_nofpu_a16, op_nofpu_a16, op_nofpu_a16, - op_nofpu_a16, op_nofpu_a16, op_nofpu_a16, op_nofpu_a16, op_nofpu_a16, op_nofpu_a16, op_nofpu_a16, op_nofpu_a16, - op_nofpu_a16, op_nofpu_a16, op_nofpu_a16, op_nofpu_a16, op_nofpu_a16, op_nofpu_a16, op_nofpu_a16, op_nofpu_a16, - - op_nofpu_a16, op_nofpu_a16, op_nofpu_a16, op_nofpu_a16, op_nofpu_a16, op_nofpu_a16, op_nofpu_a16, op_nofpu_a16, - op_nofpu_a16, op_nofpu_a16, op_nofpu_a16, op_nofpu_a16, op_nofpu_a16, op_nofpu_a16, op_nofpu_a16, op_nofpu_a16, - op_nofpu_a16, op_nofpu_a16, op_nofpu_a16, op_nofpu_a16, op_nofpu_a16, op_nofpu_a16, op_nofpu_a16, op_nofpu_a16, - op_nofpu_a16, op_nofpu_a16, op_nofpu_a16, op_nofpu_a16, op_nofpu_a16, op_nofpu_a16, op_nofpu_a16, op_nofpu_a16, - op_nofpu_a16, op_nofpu_a16, op_nofpu_a16, op_nofpu_a16, op_nofpu_a16, op_nofpu_a16, op_nofpu_a16, op_nofpu_a16, - op_nofpu_a16, op_nofpu_a16, op_nofpu_a16, op_nofpu_a16, op_nofpu_a16, op_nofpu_a16, op_nofpu_a16, op_nofpu_a16, - op_nofpu_a16, op_nofpu_a16, op_nofpu_a16, op_nofpu_a16, op_nofpu_a16, op_nofpu_a16, op_nofpu_a16, op_nofpu_a16, - op_nofpu_a16, op_nofpu_a16, op_nofpu_a16, op_nofpu_a16, op_nofpu_a16, op_nofpu_a16, op_nofpu_a16, op_nofpu_a16, - - op_nofpu_a16, op_nofpu_a16, op_nofpu_a16, op_nofpu_a16, op_nofpu_a16, op_nofpu_a16, op_nofpu_a16, op_nofpu_a16, - op_nofpu_a16, op_nofpu_a16, op_nofpu_a16, op_nofpu_a16, op_nofpu_a16, op_nofpu_a16, op_nofpu_a16, op_nofpu_a16, - op_nofpu_a16, op_nofpu_a16, op_nofpu_a16, op_nofpu_a16, op_nofpu_a16, op_nofpu_a16, op_nofpu_a16, op_nofpu_a16, - op_nofpu_a16, op_nofpu_a16, op_nofpu_a16, op_nofpu_a16, op_nofpu_a16, op_nofpu_a16, op_nofpu_a16, op_nofpu_a16, - op_nofpu_a16, op_nofpu_a16, op_nofpu_a16, op_nofpu_a16, op_nofpu_a16, op_nofpu_a16, op_nofpu_a16, op_nofpu_a16, - op_nofpu_a16, op_nofpu_a16, op_nofpu_a16, op_nofpu_a16, op_nofpu_a16, op_nofpu_a16, op_nofpu_a16, op_nofpu_a16, - op_nofpu_a16, op_nofpu_a16, op_nofpu_a16, op_nofpu_a16, op_nofpu_a16, op_nofpu_a16, op_nofpu_a16, op_nofpu_a16, - op_nofpu_a16, op_nofpu_a16, op_nofpu_a16, op_nofpu_a16, op_nofpu_a16, op_nofpu_a16, op_nofpu_a16, op_nofpu_a16, -}; -const OpFn OP_TABLE(nofpu_a32)[256] = -{ +const OpFn OP_TABLE(nofpu_a32)[256] = { + // clang-format off op_nofpu_a32, op_nofpu_a32, op_nofpu_a32, op_nofpu_a32, op_nofpu_a32, op_nofpu_a32, op_nofpu_a32, op_nofpu_a32, op_nofpu_a32, op_nofpu_a32, op_nofpu_a32, op_nofpu_a32, op_nofpu_a32, op_nofpu_a32, op_nofpu_a32, op_nofpu_a32, op_nofpu_a32, op_nofpu_a32, op_nofpu_a32, op_nofpu_a32, op_nofpu_a32, op_nofpu_a32, op_nofpu_a32, op_nofpu_a32, @@ -2119,6 +3686,7 @@ const OpFn OP_TABLE(nofpu_a32)[256] = op_nofpu_a32, op_nofpu_a32, op_nofpu_a32, op_nofpu_a32, op_nofpu_a32, op_nofpu_a32, op_nofpu_a32, op_nofpu_a32, op_nofpu_a32, op_nofpu_a32, op_nofpu_a32, op_nofpu_a32, op_nofpu_a32, op_nofpu_a32, op_nofpu_a32, op_nofpu_a32, op_nofpu_a32, op_nofpu_a32, op_nofpu_a32, op_nofpu_a32, op_nofpu_a32, op_nofpu_a32, op_nofpu_a32, op_nofpu_a32, + // clang-format on }; #endif diff --git a/src/cpu/x87_ops_arith.h b/src/cpu/x87_ops_arith.h index 5e4bfceab..808a15051 100644 --- a/src/cpu/x87_ops_arith.h +++ b/src/cpu/x87_ops_arith.h @@ -1,457 +1,514 @@ -#define opFPU(name, optype, a_size, load_var, get, use_var, cycle_postfix) \ -static int opFADD ## name ## _a ## a_size(uint32_t fetchdat) \ -{ \ - optype t; \ - FP_ENTER(); \ - fetch_ea_ ## a_size(fetchdat); \ - SEG_CHECK_READ(cpu_state.ea_seg); \ - load_var = get(); if (cpu_state.abrt) return 1; \ - if ((cpu_state.npxc >> 10) & 3) \ - fesetround(rounding_modes[(cpu_state.npxc >> 10) & 3]); \ - ST(0) += use_var; \ - if ((cpu_state.npxc >> 10) & 3) \ - fesetround(FE_TONEAREST); \ - FP_TAG_VALID; \ - CLOCK_CYCLES_FPU((fpu_type >= FPU_487SX) ? (x87_timings.fadd ## cycle_postfix) : ((x87_timings.fadd ## cycle_postfix) * cpu_multi)); \ - CONCURRENCY_CYCLES((fpu_type >= FPU_487SX) ? (x87_concurrency.fadd ## cycle_postfix) : ((x87_concurrency.fadd ## cycle_postfix) * cpu_multi)); \ - return 0; \ -} \ -static int opFCOM ## name ## _a ## a_size(uint32_t fetchdat) \ -{ \ - optype t; \ - FP_ENTER(); \ - fetch_ea_ ## a_size(fetchdat); \ - SEG_CHECK_READ(cpu_state.ea_seg); \ - load_var = get(); if (cpu_state.abrt) return 1; \ - cpu_state.npxs &= ~(C0|C2|C3); \ - cpu_state.npxs |= x87_compare(ST(0), (double)use_var); \ - CLOCK_CYCLES_FPU((fpu_type >= FPU_487SX) ? (x87_timings.fcom ## cycle_postfix) : ((x87_timings.fcom ## cycle_postfix) * cpu_multi)); \ - CONCURRENCY_CYCLES((fpu_type >= FPU_487SX) ? (x87_concurrency.fcom ## cycle_postfix) : ((x87_concurrency.fcom ## cycle_postfix) * cpu_multi)); \ - return 0; \ -} \ -static int opFCOMP ## name ## _a ## a_size(uint32_t fetchdat) \ -{ \ - optype t; \ - FP_ENTER(); \ - fetch_ea_ ## a_size(fetchdat); \ - SEG_CHECK_READ(cpu_state.ea_seg); \ - load_var = get(); if (cpu_state.abrt) return 1; \ - cpu_state.npxs &= ~(C0|C2|C3); \ - cpu_state.npxs |= x87_compare(ST(0), (double)use_var); \ - x87_pop(); \ - CLOCK_CYCLES_FPU((fpu_type >= FPU_487SX) ? (x87_timings.fcom ## cycle_postfix) : ((x87_timings.fcom ## cycle_postfix) * cpu_multi)); \ - CONCURRENCY_CYCLES((fpu_type >= FPU_487SX) ? (x87_concurrency.fcom ## cycle_postfix) : ((x87_concurrency.fcom ## cycle_postfix) * cpu_multi)); \ - return 0; \ -} \ -static int opFDIV ## name ## _a ## a_size(uint32_t fetchdat) \ -{ \ - optype t; \ - FP_ENTER(); \ - fetch_ea_ ## a_size(fetchdat); \ - SEG_CHECK_READ(cpu_state.ea_seg); \ - load_var = get(); if (cpu_state.abrt) return 1; \ - x87_div(ST(0), ST(0), use_var); \ - FP_TAG_VALID; \ - CLOCK_CYCLES_FPU((fpu_type >= FPU_487SX) ? (x87_timings.fdiv ## cycle_postfix) : ((x87_timings.fdiv ## cycle_postfix) * cpu_multi)); \ - CONCURRENCY_CYCLES((fpu_type >= FPU_487SX) ? (x87_concurrency.fadd ## cycle_postfix) : ((x87_concurrency.fadd ## cycle_postfix) * cpu_multi)); \ - return 0; \ -} \ -static int opFDIVR ## name ## _a ## a_size(uint32_t fetchdat) \ -{ \ - optype t; \ - FP_ENTER(); \ - fetch_ea_ ## a_size(fetchdat); \ - SEG_CHECK_READ(cpu_state.ea_seg); \ - load_var = get(); if (cpu_state.abrt) return 1; \ - x87_div(ST(0), use_var, ST(0)); \ - FP_TAG_VALID; \ - CLOCK_CYCLES_FPU((fpu_type >= FPU_487SX) ? (x87_timings.fdiv ## cycle_postfix) : ((x87_timings.fdiv ## cycle_postfix) * cpu_multi)); \ - CONCURRENCY_CYCLES((fpu_type >= FPU_487SX) ? (x87_concurrency.fdiv ## cycle_postfix) : ((x87_concurrency.fdiv ## cycle_postfix) * cpu_multi)); \ - return 0; \ -} \ -static int opFMUL ## name ## _a ## a_size(uint32_t fetchdat) \ -{ \ - optype t; \ - FP_ENTER(); \ - fetch_ea_ ## a_size(fetchdat); \ - SEG_CHECK_READ(cpu_state.ea_seg); \ - load_var = get(); if (cpu_state.abrt) return 1; \ - ST(0) *= use_var; \ - FP_TAG_VALID; \ - CLOCK_CYCLES_FPU((fpu_type >= FPU_487SX) ? (x87_timings.fmul ## cycle_postfix) : ((x87_timings.fmul ## cycle_postfix) * cpu_multi)); \ - CONCURRENCY_CYCLES((fpu_type >= FPU_487SX) ? (x87_concurrency.fmul ## cycle_postfix) : ((x87_concurrency.fmul ## cycle_postfix) * cpu_multi)); \ - return 0; \ -} \ -static int opFSUB ## name ## _a ## a_size(uint32_t fetchdat) \ -{ \ - optype t; \ - FP_ENTER(); \ - fetch_ea_ ## a_size(fetchdat); \ - SEG_CHECK_READ(cpu_state.ea_seg); \ - load_var = get(); if (cpu_state.abrt) return 1; \ - ST(0) -= use_var; \ - FP_TAG_VALID; \ - CLOCK_CYCLES_FPU((fpu_type >= FPU_487SX) ? (x87_timings.fadd ## cycle_postfix) : ((x87_timings.fadd ## cycle_postfix) * cpu_multi)); \ - CONCURRENCY_CYCLES((fpu_type >= FPU_487SX) ? (x87_concurrency.fadd ## cycle_postfix) : ((x87_concurrency.fadd ## cycle_postfix) * cpu_multi)); \ - return 0; \ -} \ -static int opFSUBR ## name ## _a ## a_size(uint32_t fetchdat) \ -{ \ - optype t; \ - FP_ENTER(); \ - fetch_ea_ ## a_size(fetchdat); \ - SEG_CHECK_READ(cpu_state.ea_seg); \ - load_var = get(); if (cpu_state.abrt) return 1; \ - ST(0) = use_var - ST(0); \ - FP_TAG_VALID; \ - CLOCK_CYCLES_FPU((fpu_type >= FPU_487SX) ? (x87_timings.fadd ## cycle_postfix) : ((x87_timings.fadd ## cycle_postfix) * cpu_multi)); \ - CONCURRENCY_CYCLES((fpu_type >= FPU_487SX) ? (x87_concurrency.fadd ## cycle_postfix) : ((x87_concurrency.fadd ## cycle_postfix) * cpu_multi)); \ - return 0; \ -} - +#define opFPU(name, optype, a_size, load_var, get, use_var, cycle_postfix) \ + static int opFADD##name##_a##a_size(uint32_t fetchdat) \ + { \ + optype t; \ + FP_ENTER(); \ + fetch_ea_##a_size(fetchdat); \ + SEG_CHECK_READ(cpu_state.ea_seg); \ + load_var = get(); \ + if (cpu_state.abrt) \ + return 1; \ + if ((cpu_state.npxc >> 10) & 3) \ + fesetround(rounding_modes[(cpu_state.npxc >> 10) & 3]); \ + ST(0) += use_var; \ + if ((cpu_state.npxc >> 10) & 3) \ + fesetround(FE_TONEAREST); \ + FP_TAG_VALID; \ + CLOCK_CYCLES_FPU((fpu_type >= FPU_487SX) ? (x87_timings.fadd##cycle_postfix) : ((x87_timings.fadd##cycle_postfix) * cpu_multi)); \ + CONCURRENCY_CYCLES((fpu_type >= FPU_487SX) ? (x87_concurrency.fadd##cycle_postfix) : ((x87_concurrency.fadd##cycle_postfix) * cpu_multi)); \ + return 0; \ + } \ + static int opFCOM##name##_a##a_size(uint32_t fetchdat) \ + { \ + optype t; \ + FP_ENTER(); \ + fetch_ea_##a_size(fetchdat); \ + SEG_CHECK_READ(cpu_state.ea_seg); \ + load_var = get(); \ + if (cpu_state.abrt) \ + return 1; \ + cpu_state.npxs &= ~(C0 | C2 | C3); \ + cpu_state.npxs |= x87_compare(ST(0), (double) use_var); \ + CLOCK_CYCLES_FPU((fpu_type >= FPU_487SX) ? (x87_timings.fcom##cycle_postfix) : ((x87_timings.fcom##cycle_postfix) * cpu_multi)); \ + CONCURRENCY_CYCLES((fpu_type >= FPU_487SX) ? (x87_concurrency.fcom##cycle_postfix) : ((x87_concurrency.fcom##cycle_postfix) * cpu_multi)); \ + return 0; \ + } \ + static int opFCOMP##name##_a##a_size(uint32_t fetchdat) \ + { \ + optype t; \ + FP_ENTER(); \ + fetch_ea_##a_size(fetchdat); \ + SEG_CHECK_READ(cpu_state.ea_seg); \ + load_var = get(); \ + if (cpu_state.abrt) \ + return 1; \ + cpu_state.npxs &= ~(C0 | C2 | C3); \ + cpu_state.npxs |= x87_compare(ST(0), (double) use_var); \ + x87_pop(); \ + CLOCK_CYCLES_FPU((fpu_type >= FPU_487SX) ? (x87_timings.fcom##cycle_postfix) : ((x87_timings.fcom##cycle_postfix) * cpu_multi)); \ + CONCURRENCY_CYCLES((fpu_type >= FPU_487SX) ? (x87_concurrency.fcom##cycle_postfix) : ((x87_concurrency.fcom##cycle_postfix) * cpu_multi)); \ + return 0; \ + } \ + static int opFDIV##name##_a##a_size(uint32_t fetchdat) \ + { \ + optype t; \ + FP_ENTER(); \ + fetch_ea_##a_size(fetchdat); \ + SEG_CHECK_READ(cpu_state.ea_seg); \ + load_var = get(); \ + if (cpu_state.abrt) \ + return 1; \ + x87_div(ST(0), ST(0), use_var); \ + FP_TAG_VALID; \ + CLOCK_CYCLES_FPU((fpu_type >= FPU_487SX) ? (x87_timings.fdiv##cycle_postfix) : ((x87_timings.fdiv##cycle_postfix) * cpu_multi)); \ + CONCURRENCY_CYCLES((fpu_type >= FPU_487SX) ? (x87_concurrency.fadd##cycle_postfix) : ((x87_concurrency.fadd##cycle_postfix) * cpu_multi)); \ + return 0; \ + } \ + static int opFDIVR##name##_a##a_size(uint32_t fetchdat) \ + { \ + optype t; \ + FP_ENTER(); \ + fetch_ea_##a_size(fetchdat); \ + SEG_CHECK_READ(cpu_state.ea_seg); \ + load_var = get(); \ + if (cpu_state.abrt) \ + return 1; \ + x87_div(ST(0), use_var, ST(0)); \ + FP_TAG_VALID; \ + CLOCK_CYCLES_FPU((fpu_type >= FPU_487SX) ? (x87_timings.fdiv##cycle_postfix) : ((x87_timings.fdiv##cycle_postfix) * cpu_multi)); \ + CONCURRENCY_CYCLES((fpu_type >= FPU_487SX) ? (x87_concurrency.fdiv##cycle_postfix) : ((x87_concurrency.fdiv##cycle_postfix) * cpu_multi)); \ + return 0; \ + } \ + static int opFMUL##name##_a##a_size(uint32_t fetchdat) \ + { \ + optype t; \ + FP_ENTER(); \ + fetch_ea_##a_size(fetchdat); \ + SEG_CHECK_READ(cpu_state.ea_seg); \ + load_var = get(); \ + if (cpu_state.abrt) \ + return 1; \ + ST(0) *= use_var; \ + FP_TAG_VALID; \ + CLOCK_CYCLES_FPU((fpu_type >= FPU_487SX) ? (x87_timings.fmul##cycle_postfix) : ((x87_timings.fmul##cycle_postfix) * cpu_multi)); \ + CONCURRENCY_CYCLES((fpu_type >= FPU_487SX) ? (x87_concurrency.fmul##cycle_postfix) : ((x87_concurrency.fmul##cycle_postfix) * cpu_multi)); \ + return 0; \ + } \ + static int opFSUB##name##_a##a_size(uint32_t fetchdat) \ + { \ + optype t; \ + FP_ENTER(); \ + fetch_ea_##a_size(fetchdat); \ + SEG_CHECK_READ(cpu_state.ea_seg); \ + load_var = get(); \ + if (cpu_state.abrt) \ + return 1; \ + ST(0) -= use_var; \ + FP_TAG_VALID; \ + CLOCK_CYCLES_FPU((fpu_type >= FPU_487SX) ? (x87_timings.fadd##cycle_postfix) : ((x87_timings.fadd##cycle_postfix) * cpu_multi)); \ + CONCURRENCY_CYCLES((fpu_type >= FPU_487SX) ? (x87_concurrency.fadd##cycle_postfix) : ((x87_concurrency.fadd##cycle_postfix) * cpu_multi)); \ + return 0; \ + } \ + static int opFSUBR##name##_a##a_size(uint32_t fetchdat) \ + { \ + optype t; \ + FP_ENTER(); \ + fetch_ea_##a_size(fetchdat); \ + SEG_CHECK_READ(cpu_state.ea_seg); \ + load_var = get(); \ + if (cpu_state.abrt) \ + return 1; \ + ST(0) = use_var - ST(0); \ + FP_TAG_VALID; \ + CLOCK_CYCLES_FPU((fpu_type >= FPU_487SX) ? (x87_timings.fadd##cycle_postfix) : ((x87_timings.fadd##cycle_postfix) * cpu_multi)); \ + CONCURRENCY_CYCLES((fpu_type >= FPU_487SX) ? (x87_concurrency.fadd##cycle_postfix) : ((x87_concurrency.fadd##cycle_postfix) * cpu_multi)); \ + return 0; \ + } +// clang-format off opFPU(s, x87_ts, 16, t.i, geteal, t.s, _32) #ifndef FPU_8087 -opFPU(s, x87_ts, 32, t.i, geteal, t.s, _32) + opFPU(s, x87_ts, 32, t.i, geteal, t.s, _32) #endif opFPU(d, x87_td, 16, t.i, geteaq, t.d, _64) #ifndef FPU_8087 -opFPU(d, x87_td, 32, t.i, geteaq, t.d, _64) + opFPU(d, x87_td, 32, t.i, geteaq, t.d, _64) #endif -opFPU(iw, uint16_t, 16, t, geteaw, (double)(int16_t)t, _i16) +opFPU(iw, uint16_t, 16, t, geteaw, (double) (int16_t) t, _i16) #ifndef FPU_8087 -opFPU(iw, uint16_t, 32, t, geteaw, (double)(int16_t)t, _i16) + opFPU(iw, uint16_t, 32, t, geteaw, (double) (int16_t) t, _i16) #endif -opFPU(il, uint32_t, 16, t, geteal, (double)(int32_t)t, _i32) +opFPU(il, uint32_t, 16, t, geteal, (double) (int32_t) t, _i32) #ifndef FPU_8087 -opFPU(il, uint32_t, 32, t, geteal, (double)(int32_t)t, _i32) + opFPU(il, uint32_t, 32, t, geteal, (double) (int32_t) t, _i32) #endif + // clang-format on - -static int opFADD(uint32_t fetchdat) + static int opFADD(uint32_t fetchdat) { - FP_ENTER(); - cpu_state.pc++; - ST(0) = ST(0) + ST(fetchdat & 7); - FP_TAG_VALID; - CLOCK_CYCLES_FPU((fpu_type >= FPU_487SX) ? (x87_timings.fadd) : (x87_timings.fadd * cpu_multi)); - CONCURRENCY_CYCLES((fpu_type >= FPU_487SX) ? (x87_concurrency.fadd) : (x87_concurrency.fadd * cpu_multi)); - return 0; + FP_ENTER(); + cpu_state.pc++; + ST(0) = ST(0) + ST(fetchdat & 7); + FP_TAG_VALID; + CLOCK_CYCLES_FPU((fpu_type >= FPU_487SX) ? (x87_timings.fadd) : (x87_timings.fadd * cpu_multi)); + CONCURRENCY_CYCLES((fpu_type >= FPU_487SX) ? (x87_concurrency.fadd) : (x87_concurrency.fadd * cpu_multi)); + return 0; } -static int opFADDr(uint32_t fetchdat) +static int +opFADDr(uint32_t fetchdat) { - FP_ENTER(); - cpu_state.pc++; - ST(fetchdat & 7) = ST(fetchdat & 7) + ST(0); - FP_TAG_VALID_F; - CLOCK_CYCLES_FPU((fpu_type >= FPU_487SX) ? (x87_timings.fadd) : (x87_timings.fadd * cpu_multi)); - CONCURRENCY_CYCLES((fpu_type >= FPU_487SX) ? (x87_concurrency.fadd) : (x87_concurrency.fadd * cpu_multi)); - return 0; + FP_ENTER(); + cpu_state.pc++; + ST(fetchdat & 7) = ST(fetchdat & 7) + ST(0); + FP_TAG_VALID_F; + CLOCK_CYCLES_FPU((fpu_type >= FPU_487SX) ? (x87_timings.fadd) : (x87_timings.fadd * cpu_multi)); + CONCURRENCY_CYCLES((fpu_type >= FPU_487SX) ? (x87_concurrency.fadd) : (x87_concurrency.fadd * cpu_multi)); + return 0; } -static int opFADDP(uint32_t fetchdat) +static int +opFADDP(uint32_t fetchdat) { - FP_ENTER(); - cpu_state.pc++; - ST(fetchdat & 7) = ST(fetchdat & 7) + ST(0); - FP_TAG_VALID_F; - x87_pop(); - CLOCK_CYCLES_FPU((fpu_type >= FPU_487SX) ? (x87_timings.fadd) : (x87_timings.fadd * cpu_multi)); - CONCURRENCY_CYCLES((fpu_type >= FPU_487SX) ? (x87_concurrency.fadd) : (x87_concurrency.fadd * cpu_multi)); - return 0; + FP_ENTER(); + cpu_state.pc++; + ST(fetchdat & 7) = ST(fetchdat & 7) + ST(0); + FP_TAG_VALID_F; + x87_pop(); + CLOCK_CYCLES_FPU((fpu_type >= FPU_487SX) ? (x87_timings.fadd) : (x87_timings.fadd * cpu_multi)); + CONCURRENCY_CYCLES((fpu_type >= FPU_487SX) ? (x87_concurrency.fadd) : (x87_concurrency.fadd * cpu_multi)); + return 0; } -static int opFCOM(uint32_t fetchdat) +static int +opFCOM(uint32_t fetchdat) { - FP_ENTER(); - cpu_state.pc++; - cpu_state.npxs &= ~(C0|C2|C3); - if (ST(0) == ST(fetchdat & 7)) cpu_state.npxs |= C3; - else if (ST(0) < ST(fetchdat & 7)) cpu_state.npxs |= C0; - CLOCK_CYCLES_FPU((fpu_type >= FPU_487SX) ? (x87_timings.fcom) : (x87_timings.fcom * cpu_multi)); - CONCURRENCY_CYCLES((fpu_type >= FPU_487SX) ? (x87_concurrency.fcom) : (x87_concurrency.fcom * cpu_multi)); - return 0; + FP_ENTER(); + cpu_state.pc++; + cpu_state.npxs &= ~(C0 | C2 | C3); + if (ST(0) == ST(fetchdat & 7)) + cpu_state.npxs |= C3; + else if (ST(0) < ST(fetchdat & 7)) + cpu_state.npxs |= C0; + CLOCK_CYCLES_FPU((fpu_type >= FPU_487SX) ? (x87_timings.fcom) : (x87_timings.fcom * cpu_multi)); + CONCURRENCY_CYCLES((fpu_type >= FPU_487SX) ? (x87_concurrency.fcom) : (x87_concurrency.fcom * cpu_multi)); + return 0; } -static int opFCOMP(uint32_t fetchdat) +static int +opFCOMP(uint32_t fetchdat) { - FP_ENTER(); - cpu_state.pc++; - cpu_state.npxs &= ~(C0|C2|C3); - cpu_state.npxs |= x87_compare(ST(0), ST(fetchdat & 7)); - x87_pop(); - CLOCK_CYCLES_FPU((fpu_type >= FPU_487SX) ? (x87_timings.fcom) : (x87_timings.fcom * cpu_multi)); - CONCURRENCY_CYCLES((fpu_type >= FPU_487SX) ? (x87_concurrency.fcom) : (x87_concurrency.fcom * cpu_multi)); - return 0; + FP_ENTER(); + cpu_state.pc++; + cpu_state.npxs &= ~(C0 | C2 | C3); + cpu_state.npxs |= x87_compare(ST(0), ST(fetchdat & 7)); + x87_pop(); + CLOCK_CYCLES_FPU((fpu_type >= FPU_487SX) ? (x87_timings.fcom) : (x87_timings.fcom * cpu_multi)); + CONCURRENCY_CYCLES((fpu_type >= FPU_487SX) ? (x87_concurrency.fcom) : (x87_concurrency.fcom * cpu_multi)); + return 0; } -static int opFCOMPP(uint32_t fetchdat) +static int +opFCOMPP(uint32_t fetchdat) { - uint64_t *p, *q; - FP_ENTER(); - cpu_state.pc++; - cpu_state.npxs &= ~(C0|C2|C3); - p = (uint64_t *)&ST(0); - q = (uint64_t *)&ST(1); - if ((*p == ((uint64_t)1 << 63) && *q == 0) && (fpu_type >= FPU_287XL)) - cpu_state.npxs |= C0; /*Nasty hack to fix 80387 detection*/ - else - cpu_state.npxs |= x87_compare(ST(0), ST(1)); + uint64_t *p, *q; + FP_ENTER(); + cpu_state.pc++; + cpu_state.npxs &= ~(C0 | C2 | C3); + p = (uint64_t *) &ST(0); + q = (uint64_t *) &ST(1); + if ((*p == ((uint64_t) 1 << 63) && *q == 0) && (fpu_type >= FPU_287XL)) + cpu_state.npxs |= C0; /*Nasty hack to fix 80387 detection*/ + else + cpu_state.npxs |= x87_compare(ST(0), ST(1)); - x87_pop(); - x87_pop(); - CLOCK_CYCLES_FPU((fpu_type >= FPU_487SX) ? (x87_timings.fcom) : (x87_timings.fcom * cpu_multi)); - CONCURRENCY_CYCLES((fpu_type >= FPU_487SX) ? (x87_concurrency.fcom) : (x87_concurrency.fcom * cpu_multi)); - return 0; + x87_pop(); + x87_pop(); + CLOCK_CYCLES_FPU((fpu_type >= FPU_487SX) ? (x87_timings.fcom) : (x87_timings.fcom * cpu_multi)); + CONCURRENCY_CYCLES((fpu_type >= FPU_487SX) ? (x87_concurrency.fcom) : (x87_concurrency.fcom * cpu_multi)); + return 0; } #ifndef FPU_8087 -static int opFUCOMPP(uint32_t fetchdat) +static int +opFUCOMPP(uint32_t fetchdat) { - FP_ENTER(); - cpu_state.pc++; - cpu_state.npxs &= ~(C0|C2|C3); - cpu_state.npxs |= x87_ucompare(ST(0), ST(1)); - x87_pop(); - x87_pop(); - CLOCK_CYCLES_FPU((fpu_type >= FPU_487SX) ? (x87_timings.fucom) : (x87_timings.fucom * cpu_multi)); - CONCURRENCY_CYCLES((fpu_type >= FPU_487SX) ? (x87_concurrency.fucom) : (x87_concurrency.fucom * cpu_multi)); - return 0; + FP_ENTER(); + cpu_state.pc++; + cpu_state.npxs &= ~(C0 | C2 | C3); + cpu_state.npxs |= x87_ucompare(ST(0), ST(1)); + x87_pop(); + x87_pop(); + CLOCK_CYCLES_FPU((fpu_type >= FPU_487SX) ? (x87_timings.fucom) : (x87_timings.fucom * cpu_multi)); + CONCURRENCY_CYCLES((fpu_type >= FPU_487SX) ? (x87_concurrency.fucom) : (x87_concurrency.fucom * cpu_multi)); + return 0; } -static int opFCOMI(uint32_t fetchdat) +# ifndef OPS_286_386 +static int +opFCOMI(uint32_t fetchdat) { - FP_ENTER(); - cpu_state.pc++; - flags_rebuild(); - cpu_state.flags &= ~(Z_FLAG | P_FLAG | C_FLAG); - if (ST(0) == ST(fetchdat & 7)) cpu_state.flags |= Z_FLAG; - else if (ST(0) < ST(fetchdat & 7)) cpu_state.flags |= C_FLAG; - CLOCK_CYCLES_FPU((fpu_type >= FPU_487SX) ? (x87_timings.fcom) : (x87_timings.fcom * cpu_multi)); - CONCURRENCY_CYCLES((fpu_type >= FPU_487SX) ? (x87_concurrency.fcom) : (x87_concurrency.fcom * cpu_multi)); - return 0; + FP_ENTER(); + cpu_state.pc++; + flags_rebuild(); + cpu_state.flags &= ~(Z_FLAG | P_FLAG | C_FLAG); + if (ST(0) == ST(fetchdat & 7)) + cpu_state.flags |= Z_FLAG; + else if (ST(0) < ST(fetchdat & 7)) + cpu_state.flags |= C_FLAG; + CLOCK_CYCLES_FPU((fpu_type >= FPU_487SX) ? (x87_timings.fcom) : (x87_timings.fcom * cpu_multi)); + CONCURRENCY_CYCLES((fpu_type >= FPU_487SX) ? (x87_concurrency.fcom) : (x87_concurrency.fcom * cpu_multi)); + return 0; } -static int opFCOMIP(uint32_t fetchdat) +static int +opFCOMIP(uint32_t fetchdat) { - FP_ENTER(); - cpu_state.pc++; - flags_rebuild(); - cpu_state.flags &= ~(Z_FLAG | P_FLAG | C_FLAG); - if (ST(0) == ST(fetchdat & 7)) cpu_state.flags |= Z_FLAG; - else if (ST(0) < ST(fetchdat & 7)) cpu_state.flags |= C_FLAG; - x87_pop(); - CLOCK_CYCLES_FPU((fpu_type >= FPU_487SX) ? (x87_timings.fcom) : (x87_timings.fcom * cpu_multi)); - CONCURRENCY_CYCLES((fpu_type >= FPU_487SX) ? (x87_concurrency.fcom) : (x87_concurrency.fcom * cpu_multi)); - return 0; + FP_ENTER(); + cpu_state.pc++; + flags_rebuild(); + cpu_state.flags &= ~(Z_FLAG | P_FLAG | C_FLAG); + if (ST(0) == ST(fetchdat & 7)) + cpu_state.flags |= Z_FLAG; + else if (ST(0) < ST(fetchdat & 7)) + cpu_state.flags |= C_FLAG; + x87_pop(); + CLOCK_CYCLES_FPU((fpu_type >= FPU_487SX) ? (x87_timings.fcom) : (x87_timings.fcom * cpu_multi)); + CONCURRENCY_CYCLES((fpu_type >= FPU_487SX) ? (x87_concurrency.fcom) : (x87_concurrency.fcom * cpu_multi)); + return 0; } +# endif #endif -static int opFDIV(uint32_t fetchdat) +static int +opFDIV(uint32_t fetchdat) { - FP_ENTER(); - cpu_state.pc++; - x87_div(ST(0), ST(0), ST(fetchdat & 7)); - FP_TAG_VALID; - CLOCK_CYCLES_FPU((fpu_type >= FPU_487SX) ? (x87_timings.fdiv) : (x87_timings.fdiv * cpu_multi)); - CONCURRENCY_CYCLES((fpu_type >= FPU_487SX) ? (x87_concurrency.fdiv) : (x87_concurrency.fdiv * cpu_multi)); - return 0; + FP_ENTER(); + cpu_state.pc++; + x87_div(ST(0), ST(0), ST(fetchdat & 7)); + FP_TAG_VALID; + CLOCK_CYCLES_FPU((fpu_type >= FPU_487SX) ? (x87_timings.fdiv) : (x87_timings.fdiv * cpu_multi)); + CONCURRENCY_CYCLES((fpu_type >= FPU_487SX) ? (x87_concurrency.fdiv) : (x87_concurrency.fdiv * cpu_multi)); + return 0; } -static int opFDIVr(uint32_t fetchdat) +static int +opFDIVr(uint32_t fetchdat) { - FP_ENTER(); - cpu_state.pc++; - x87_div(ST(fetchdat & 7), ST(fetchdat & 7), ST(0)); - FP_TAG_VALID_F; - CLOCK_CYCLES_FPU((fpu_type >= FPU_487SX) ? (x87_timings.fdiv) : (x87_timings.fdiv * cpu_multi)); - CONCURRENCY_CYCLES((fpu_type >= FPU_487SX) ? (x87_concurrency.fdiv) : (x87_concurrency.fdiv * cpu_multi)); - return 0; + FP_ENTER(); + cpu_state.pc++; + x87_div(ST(fetchdat & 7), ST(fetchdat & 7), ST(0)); + FP_TAG_VALID_F; + CLOCK_CYCLES_FPU((fpu_type >= FPU_487SX) ? (x87_timings.fdiv) : (x87_timings.fdiv * cpu_multi)); + CONCURRENCY_CYCLES((fpu_type >= FPU_487SX) ? (x87_concurrency.fdiv) : (x87_concurrency.fdiv * cpu_multi)); + return 0; } -static int opFDIVP(uint32_t fetchdat) +static int +opFDIVP(uint32_t fetchdat) { - FP_ENTER(); - cpu_state.pc++; - x87_div(ST(fetchdat & 7), ST(fetchdat & 7), ST(0)); - FP_TAG_VALID_F; - x87_pop(); - CLOCK_CYCLES_FPU((fpu_type >= FPU_487SX) ? (x87_timings.fdiv) : (x87_timings.fdiv * cpu_multi)); - CONCURRENCY_CYCLES((fpu_type >= FPU_487SX) ? (x87_concurrency.fdiv) : (x87_concurrency.fdiv * cpu_multi)); - return 0; + FP_ENTER(); + cpu_state.pc++; + x87_div(ST(fetchdat & 7), ST(fetchdat & 7), ST(0)); + FP_TAG_VALID_F; + x87_pop(); + CLOCK_CYCLES_FPU((fpu_type >= FPU_487SX) ? (x87_timings.fdiv) : (x87_timings.fdiv * cpu_multi)); + CONCURRENCY_CYCLES((fpu_type >= FPU_487SX) ? (x87_concurrency.fdiv) : (x87_concurrency.fdiv * cpu_multi)); + return 0; } -static int opFDIVR(uint32_t fetchdat) +static int +opFDIVR(uint32_t fetchdat) { - FP_ENTER(); - cpu_state.pc++; - x87_div(ST(0), ST(fetchdat&7), ST(0)); - FP_TAG_VALID; - CLOCK_CYCLES_FPU((fpu_type >= FPU_487SX) ? (x87_timings.fdiv) : (x87_timings.fdiv * cpu_multi)); - CONCURRENCY_CYCLES((fpu_type >= FPU_487SX) ? (x87_concurrency.fdiv) : (x87_concurrency.fdiv * cpu_multi)); - return 0; + FP_ENTER(); + cpu_state.pc++; + x87_div(ST(0), ST(fetchdat & 7), ST(0)); + FP_TAG_VALID; + CLOCK_CYCLES_FPU((fpu_type >= FPU_487SX) ? (x87_timings.fdiv) : (x87_timings.fdiv * cpu_multi)); + CONCURRENCY_CYCLES((fpu_type >= FPU_487SX) ? (x87_concurrency.fdiv) : (x87_concurrency.fdiv * cpu_multi)); + return 0; } -static int opFDIVRr(uint32_t fetchdat) +static int +opFDIVRr(uint32_t fetchdat) { - FP_ENTER(); - cpu_state.pc++; - x87_div(ST(fetchdat & 7), ST(0), ST(fetchdat & 7)); - FP_TAG_VALID_F; - CLOCK_CYCLES_FPU((fpu_type >= FPU_487SX) ? (x87_timings.fdiv) : (x87_timings.fdiv * cpu_multi)); - CONCURRENCY_CYCLES((fpu_type >= FPU_487SX) ? (x87_concurrency.fdiv) : (x87_concurrency.fdiv * cpu_multi)); - return 0; + FP_ENTER(); + cpu_state.pc++; + x87_div(ST(fetchdat & 7), ST(0), ST(fetchdat & 7)); + FP_TAG_VALID_F; + CLOCK_CYCLES_FPU((fpu_type >= FPU_487SX) ? (x87_timings.fdiv) : (x87_timings.fdiv * cpu_multi)); + CONCURRENCY_CYCLES((fpu_type >= FPU_487SX) ? (x87_concurrency.fdiv) : (x87_concurrency.fdiv * cpu_multi)); + return 0; } -static int opFDIVRP(uint32_t fetchdat) +static int +opFDIVRP(uint32_t fetchdat) { - FP_ENTER(); - cpu_state.pc++; - x87_div(ST(fetchdat & 7), ST(0), ST(fetchdat & 7)); - FP_TAG_VALID_F; - x87_pop(); - CLOCK_CYCLES_FPU((fpu_type >= FPU_487SX) ? (x87_timings.fdiv) : (x87_timings.fdiv * cpu_multi)); - CONCURRENCY_CYCLES((fpu_type >= FPU_487SX) ? (x87_concurrency.fdiv) : (x87_concurrency.fdiv * cpu_multi)); - return 0; + FP_ENTER(); + cpu_state.pc++; + x87_div(ST(fetchdat & 7), ST(0), ST(fetchdat & 7)); + FP_TAG_VALID_F; + x87_pop(); + CLOCK_CYCLES_FPU((fpu_type >= FPU_487SX) ? (x87_timings.fdiv) : (x87_timings.fdiv * cpu_multi)); + CONCURRENCY_CYCLES((fpu_type >= FPU_487SX) ? (x87_concurrency.fdiv) : (x87_concurrency.fdiv * cpu_multi)); + return 0; } -static int opFMUL(uint32_t fetchdat) +static int +opFMUL(uint32_t fetchdat) { - FP_ENTER(); - cpu_state.pc++; - ST(0) = ST(0) * ST(fetchdat & 7); - FP_TAG_VALID; - CLOCK_CYCLES_FPU((fpu_type >= FPU_487SX) ? (x87_timings.fmul) : (x87_timings.fmul * cpu_multi)); - CONCURRENCY_CYCLES((fpu_type >= FPU_487SX) ? (x87_concurrency.fmul) : (x87_concurrency.fmul * cpu_multi)); - return 0; + FP_ENTER(); + cpu_state.pc++; + ST(0) = ST(0) * ST(fetchdat & 7); + FP_TAG_VALID; + CLOCK_CYCLES_FPU((fpu_type >= FPU_487SX) ? (x87_timings.fmul) : (x87_timings.fmul * cpu_multi)); + CONCURRENCY_CYCLES((fpu_type >= FPU_487SX) ? (x87_concurrency.fmul) : (x87_concurrency.fmul * cpu_multi)); + return 0; } -static int opFMULr(uint32_t fetchdat) +static int +opFMULr(uint32_t fetchdat) { - FP_ENTER(); - cpu_state.pc++; - ST(fetchdat & 7) = ST(0) * ST(fetchdat & 7); - FP_TAG_VALID_F; - CLOCK_CYCLES_FPU((fpu_type >= FPU_487SX) ? (x87_timings.fmul) : (x87_timings.fmul * cpu_multi)); - CONCURRENCY_CYCLES((fpu_type >= FPU_487SX) ? (x87_concurrency.fmul) : (x87_concurrency.fmul * cpu_multi)); - return 0; + FP_ENTER(); + cpu_state.pc++; + ST(fetchdat & 7) = ST(0) * ST(fetchdat & 7); + FP_TAG_VALID_F; + CLOCK_CYCLES_FPU((fpu_type >= FPU_487SX) ? (x87_timings.fmul) : (x87_timings.fmul * cpu_multi)); + CONCURRENCY_CYCLES((fpu_type >= FPU_487SX) ? (x87_concurrency.fmul) : (x87_concurrency.fmul * cpu_multi)); + return 0; } -static int opFMULP(uint32_t fetchdat) +static int +opFMULP(uint32_t fetchdat) { - FP_ENTER(); - cpu_state.pc++; - ST(fetchdat & 7) = ST(0) * ST(fetchdat & 7); - FP_TAG_VALID_F; - x87_pop(); - CLOCK_CYCLES_FPU((fpu_type >= FPU_487SX) ? (x87_timings.fmul) : (x87_timings.fmul * cpu_multi)); - CONCURRENCY_CYCLES((fpu_type >= FPU_487SX) ? (x87_concurrency.fmul) : (x87_concurrency.fmul * cpu_multi)); - return 0; + FP_ENTER(); + cpu_state.pc++; + ST(fetchdat & 7) = ST(0) * ST(fetchdat & 7); + FP_TAG_VALID_F; + x87_pop(); + CLOCK_CYCLES_FPU((fpu_type >= FPU_487SX) ? (x87_timings.fmul) : (x87_timings.fmul * cpu_multi)); + CONCURRENCY_CYCLES((fpu_type >= FPU_487SX) ? (x87_concurrency.fmul) : (x87_concurrency.fmul * cpu_multi)); + return 0; } -static int opFSUB(uint32_t fetchdat) +static int +opFSUB(uint32_t fetchdat) { - FP_ENTER(); - cpu_state.pc++; - ST(0) = ST(0) - ST(fetchdat & 7); - FP_TAG_VALID; - CLOCK_CYCLES_FPU((fpu_type >= FPU_487SX) ? (x87_timings.fadd) : (x87_timings.fadd * cpu_multi)); - CONCURRENCY_CYCLES((fpu_type >= FPU_487SX) ? (x87_concurrency.fadd) : (x87_concurrency.fadd * cpu_multi)); - return 0; + FP_ENTER(); + cpu_state.pc++; + ST(0) = ST(0) - ST(fetchdat & 7); + FP_TAG_VALID; + CLOCK_CYCLES_FPU((fpu_type >= FPU_487SX) ? (x87_timings.fadd) : (x87_timings.fadd * cpu_multi)); + CONCURRENCY_CYCLES((fpu_type >= FPU_487SX) ? (x87_concurrency.fadd) : (x87_concurrency.fadd * cpu_multi)); + return 0; } -static int opFSUBr(uint32_t fetchdat) +static int +opFSUBr(uint32_t fetchdat) { - FP_ENTER(); - cpu_state.pc++; - ST(fetchdat & 7) = ST(fetchdat & 7) - ST(0); - FP_TAG_VALID_F; - CLOCK_CYCLES_FPU((fpu_type >= FPU_487SX) ? (x87_timings.fadd) : (x87_timings.fadd * cpu_multi)); - CONCURRENCY_CYCLES((fpu_type >= FPU_487SX) ? (x87_concurrency.fadd) : (x87_concurrency.fadd * cpu_multi)); - return 0; + FP_ENTER(); + cpu_state.pc++; + ST(fetchdat & 7) = ST(fetchdat & 7) - ST(0); + FP_TAG_VALID_F; + CLOCK_CYCLES_FPU((fpu_type >= FPU_487SX) ? (x87_timings.fadd) : (x87_timings.fadd * cpu_multi)); + CONCURRENCY_CYCLES((fpu_type >= FPU_487SX) ? (x87_concurrency.fadd) : (x87_concurrency.fadd * cpu_multi)); + return 0; } -static int opFSUBP(uint32_t fetchdat) +static int +opFSUBP(uint32_t fetchdat) { - FP_ENTER(); - cpu_state.pc++; - ST(fetchdat & 7) = ST(fetchdat & 7) - ST(0); - FP_TAG_VALID_F; - x87_pop(); - CLOCK_CYCLES_FPU((fpu_type >= FPU_487SX) ? (x87_timings.fadd) : (x87_timings.fadd * cpu_multi)); - CONCURRENCY_CYCLES((fpu_type >= FPU_487SX) ? (x87_concurrency.fadd) : (x87_concurrency.fadd * cpu_multi)); - return 0; + FP_ENTER(); + cpu_state.pc++; + ST(fetchdat & 7) = ST(fetchdat & 7) - ST(0); + FP_TAG_VALID_F; + x87_pop(); + CLOCK_CYCLES_FPU((fpu_type >= FPU_487SX) ? (x87_timings.fadd) : (x87_timings.fadd * cpu_multi)); + CONCURRENCY_CYCLES((fpu_type >= FPU_487SX) ? (x87_concurrency.fadd) : (x87_concurrency.fadd * cpu_multi)); + return 0; } -static int opFSUBR(uint32_t fetchdat) +static int +opFSUBR(uint32_t fetchdat) { - FP_ENTER(); - cpu_state.pc++; - ST(0) = ST(fetchdat & 7) - ST(0); - FP_TAG_VALID; - CLOCK_CYCLES_FPU((fpu_type >= FPU_487SX) ? (x87_timings.fadd) : (x87_timings.fadd * cpu_multi)); - CONCURRENCY_CYCLES((fpu_type >= FPU_487SX) ? (x87_concurrency.fadd) : (x87_concurrency.fadd * cpu_multi)); - return 0; + FP_ENTER(); + cpu_state.pc++; + ST(0) = ST(fetchdat & 7) - ST(0); + FP_TAG_VALID; + CLOCK_CYCLES_FPU((fpu_type >= FPU_487SX) ? (x87_timings.fadd) : (x87_timings.fadd * cpu_multi)); + CONCURRENCY_CYCLES((fpu_type >= FPU_487SX) ? (x87_concurrency.fadd) : (x87_concurrency.fadd * cpu_multi)); + return 0; } -static int opFSUBRr(uint32_t fetchdat) +static int +opFSUBRr(uint32_t fetchdat) { - FP_ENTER(); - cpu_state.pc++; - ST(fetchdat & 7) = ST(0) - ST(fetchdat & 7); - FP_TAG_VALID_F; - CLOCK_CYCLES_FPU((fpu_type >= FPU_487SX) ? (x87_timings.fadd) : (x87_timings.fadd * cpu_multi)); - CONCURRENCY_CYCLES((fpu_type >= FPU_487SX) ? (x87_concurrency.fadd) : (x87_concurrency.fadd * cpu_multi)); - return 0; + FP_ENTER(); + cpu_state.pc++; + ST(fetchdat & 7) = ST(0) - ST(fetchdat & 7); + FP_TAG_VALID_F; + CLOCK_CYCLES_FPU((fpu_type >= FPU_487SX) ? (x87_timings.fadd) : (x87_timings.fadd * cpu_multi)); + CONCURRENCY_CYCLES((fpu_type >= FPU_487SX) ? (x87_concurrency.fadd) : (x87_concurrency.fadd * cpu_multi)); + return 0; } -static int opFSUBRP(uint32_t fetchdat) +static int +opFSUBRP(uint32_t fetchdat) { - FP_ENTER(); - cpu_state.pc++; - ST(fetchdat & 7) = ST(0) - ST(fetchdat & 7); - FP_TAG_VALID_F; - x87_pop(); - CLOCK_CYCLES_FPU((fpu_type >= FPU_487SX) ? (x87_timings.fadd) : (x87_timings.fadd * cpu_multi)); - CONCURRENCY_CYCLES((fpu_type >= FPU_487SX) ? (x87_concurrency.fadd) : (x87_concurrency.fadd * cpu_multi)); - return 0; + FP_ENTER(); + cpu_state.pc++; + ST(fetchdat & 7) = ST(0) - ST(fetchdat & 7); + FP_TAG_VALID_F; + x87_pop(); + CLOCK_CYCLES_FPU((fpu_type >= FPU_487SX) ? (x87_timings.fadd) : (x87_timings.fadd * cpu_multi)); + CONCURRENCY_CYCLES((fpu_type >= FPU_487SX) ? (x87_concurrency.fadd) : (x87_concurrency.fadd * cpu_multi)); + return 0; } #ifndef FPU_8087 -static int opFUCOM(uint32_t fetchdat) +static int +opFUCOM(uint32_t fetchdat) { - FP_ENTER(); - cpu_state.pc++; - cpu_state.npxs &= ~(C0|C2|C3); - cpu_state.npxs |= x87_ucompare(ST(0), ST(fetchdat & 7)); - CLOCK_CYCLES_FPU((fpu_type >= FPU_487SX) ? (x87_timings.fucom) : (x87_timings.fucom * cpu_multi)); - CONCURRENCY_CYCLES((fpu_type >= FPU_487SX) ? (x87_concurrency.fucom) : (x87_concurrency.fucom * cpu_multi)); - return 0; + FP_ENTER(); + cpu_state.pc++; + cpu_state.npxs &= ~(C0 | C2 | C3); + cpu_state.npxs |= x87_ucompare(ST(0), ST(fetchdat & 7)); + CLOCK_CYCLES_FPU((fpu_type >= FPU_487SX) ? (x87_timings.fucom) : (x87_timings.fucom * cpu_multi)); + CONCURRENCY_CYCLES((fpu_type >= FPU_487SX) ? (x87_concurrency.fucom) : (x87_concurrency.fucom * cpu_multi)); + return 0; } -static int opFUCOMP(uint32_t fetchdat) +static int +opFUCOMP(uint32_t fetchdat) { - FP_ENTER(); - cpu_state.pc++; - cpu_state.npxs &= ~(C0|C2|C3); - cpu_state.npxs |= x87_ucompare(ST(0), ST(fetchdat & 7)); - x87_pop(); - CLOCK_CYCLES_FPU((fpu_type >= FPU_487SX) ? (x87_timings.fucom) : (x87_timings.fucom * cpu_multi)); - CONCURRENCY_CYCLES((fpu_type >= FPU_487SX) ? (x87_concurrency.fucom) : (x87_concurrency.fucom * cpu_multi)); - return 0; + FP_ENTER(); + cpu_state.pc++; + cpu_state.npxs &= ~(C0 | C2 | C3); + cpu_state.npxs |= x87_ucompare(ST(0), ST(fetchdat & 7)); + x87_pop(); + CLOCK_CYCLES_FPU((fpu_type >= FPU_487SX) ? (x87_timings.fucom) : (x87_timings.fucom * cpu_multi)); + CONCURRENCY_CYCLES((fpu_type >= FPU_487SX) ? (x87_concurrency.fucom) : (x87_concurrency.fucom * cpu_multi)); + return 0; } -static int opFUCOMI(uint32_t fetchdat) +# ifndef OPS_286_386 +static int +opFUCOMI(uint32_t fetchdat) { - FP_ENTER(); - cpu_state.pc++; - flags_rebuild(); - cpu_state.flags &= ~(Z_FLAG | P_FLAG | C_FLAG); - if (ST(0) == ST(fetchdat & 7)) cpu_state.flags |= Z_FLAG; - else if (ST(0) < ST(fetchdat & 7)) cpu_state.flags |= C_FLAG; - CLOCK_CYCLES_FPU((fpu_type >= FPU_487SX) ? (x87_timings.fucom) : (x87_timings.fucom * cpu_multi)); - CONCURRENCY_CYCLES((fpu_type >= FPU_487SX) ? (x87_concurrency.fucom) : (x87_concurrency.fucom * cpu_multi)); - return 0; + FP_ENTER(); + cpu_state.pc++; + flags_rebuild(); + cpu_state.flags &= ~(Z_FLAG | P_FLAG | C_FLAG); + if (ST(0) == ST(fetchdat & 7)) + cpu_state.flags |= Z_FLAG; + else if (ST(0) < ST(fetchdat & 7)) + cpu_state.flags |= C_FLAG; + CLOCK_CYCLES_FPU((fpu_type >= FPU_487SX) ? (x87_timings.fucom) : (x87_timings.fucom * cpu_multi)); + CONCURRENCY_CYCLES((fpu_type >= FPU_487SX) ? (x87_concurrency.fucom) : (x87_concurrency.fucom * cpu_multi)); + return 0; } -static int opFUCOMIP(uint32_t fetchdat) +static int +opFUCOMIP(uint32_t fetchdat) { - FP_ENTER(); - cpu_state.pc++; - flags_rebuild(); - cpu_state.flags &= ~(Z_FLAG | P_FLAG | C_FLAG); - if (ST(0) == ST(fetchdat & 7)) cpu_state.flags |= Z_FLAG; - else if (ST(0) < ST(fetchdat & 7)) cpu_state.flags |= C_FLAG; - x87_pop(); - CLOCK_CYCLES_FPU((fpu_type >= FPU_487SX) ? (x87_timings.fucom) : (x87_timings.fucom * cpu_multi)); - CONCURRENCY_CYCLES((fpu_type >= FPU_487SX) ? (x87_concurrency.fucom) : (x87_concurrency.fucom * cpu_multi)); - return 0; + FP_ENTER(); + cpu_state.pc++; + flags_rebuild(); + cpu_state.flags &= ~(Z_FLAG | P_FLAG | C_FLAG); + if (ST(0) == ST(fetchdat & 7)) + cpu_state.flags |= Z_FLAG; + else if (ST(0) < ST(fetchdat & 7)) + cpu_state.flags |= C_FLAG; + x87_pop(); + CLOCK_CYCLES_FPU((fpu_type >= FPU_487SX) ? (x87_timings.fucom) : (x87_timings.fucom * cpu_multi)); + CONCURRENCY_CYCLES((fpu_type >= FPU_487SX) ? (x87_concurrency.fucom) : (x87_concurrency.fucom * cpu_multi)); + return 0; } +# endif #endif diff --git a/src/cpu/x87_ops_conv.h b/src/cpu/x87_ops_conv.h new file mode 100644 index 000000000..7a949cfb2 --- /dev/null +++ b/src/cpu/x87_ops_conv.h @@ -0,0 +1,69 @@ +#define BIAS80 16383 +#define BIAS64 1023 + +typedef struct { + int16_t begin; + union { + double d; + uint64_t ll; + } eind; +} x87_conv_t; + +static __inline double +x87_from80(x87_conv_t *test) +{ + int64_t exp64; + int64_t blah; + int64_t exp64final; + int64_t mant64; + int64_t sign; + + exp64 = (((test->begin & 0x7fff) - BIAS80)); + blah = ((exp64 > 0) ? exp64 : -exp64) & 0x3ff; + exp64final = ((exp64 > 0) ? blah : -blah) + BIAS64; + + mant64 = (test->eind.ll >> 11) & (0xfffffffffffffLL); + sign = (test->begin & 0x8000) ? 1 : 0; + + if ((test->begin & 0x7fff) == 0x7fff) + exp64final = 0x7ff; + if ((test->begin & 0x7fff) == 0) + exp64final = 0; + if (test->eind.ll & 0x400) + mant64++; + + test->eind.ll = (sign << 63) | (exp64final << 52) | mant64; + + return test->eind.d; +} + +static __inline void +x87_to80(double d, x87_conv_t *test) +{ + int64_t sign80; + int64_t exp80; + int64_t exp80final; + int64_t mant80; + int64_t mant80final; + + test->eind.d = d; + + sign80 = (test->eind.ll & (0x8000000000000000LL)) ? 1 : 0; + exp80 = test->eind.ll & (0x7ff0000000000000LL); + exp80final = (exp80 >> 52); + mant80 = test->eind.ll & (0x000fffffffffffffLL); + mant80final = (mant80 << 11); + + if (exp80final == 0x7ff) /*Infinity / Nan*/ + { + exp80final = 0x7fff; + mant80final |= (0x8000000000000000LL); + } else if (d != 0) { /* Zero is a special case */ + /* Elvira wants the 8 and tcalc doesn't */ + mant80final |= (0x8000000000000000LL); + /* Ca-cyber doesn't like this when result is zero. */ + exp80final += (BIAS80 - BIAS64); + } + test->begin = (((int16_t) sign80) << 15) | (int16_t) exp80final; + test->eind.ll = mant80final; +} diff --git a/src/cpu/x87_ops_loadstore.h b/src/cpu/x87_ops_loadstore.h index 388e96011..d77c0ca2b 100644 --- a/src/cpu/x87_ops_loadstore.h +++ b/src/cpu/x87_ops_loadstore.h @@ -1,510 +1,601 @@ /* - * 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. + * 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. + * This file is part of the 86Box distribution. * - * x87 FPU instructions core. + * x87 FPU instructions core. * - * Version: @(#)x87_ops_loadstore.h 1.0.2 2019/06/11 * - * Author: Sarah Walker, - * Miran Grca, - * Copyright 2008-2019 Sarah Walker. - * Copyright 2016-2019 Miran Grca. + * + * Authors: Sarah Walker, + * Miran Grca, + * + * Copyright 2008-2019 Sarah Walker. + * Copyright 2016-2019 Miran Grca. */ -static int opFILDiw_a16(uint32_t fetchdat) +static int +opFILDiw_a16(uint32_t fetchdat) { - int16_t temp; - FP_ENTER(); - fetch_ea_16(fetchdat); - SEG_CHECK_READ(cpu_state.ea_seg); - temp = geteaw(); if (cpu_state.abrt) return 1; - x87_push((double)temp); - CLOCK_CYCLES_FPU((fpu_type >= FPU_487SX) ? (x87_timings.fild_16) : (x87_timings.fild_16 * cpu_multi)); - CONCURRENCY_CYCLES((fpu_type >= FPU_487SX) ? (x87_concurrency.fild_16) : (x87_concurrency.fild_16 * cpu_multi)); - return 0; + int16_t temp; + FP_ENTER(); + fetch_ea_16(fetchdat); + SEG_CHECK_READ(cpu_state.ea_seg); + temp = geteaw(); + if (cpu_state.abrt) + return 1; + x87_push((double) temp); + CLOCK_CYCLES_FPU((fpu_type >= FPU_487SX) ? (x87_timings.fild_16) : (x87_timings.fild_16 * cpu_multi)); + CONCURRENCY_CYCLES((fpu_type >= FPU_487SX) ? (x87_concurrency.fild_16) : (x87_concurrency.fild_16 * cpu_multi)); + return 0; } #ifndef FPU_8087 -static int opFILDiw_a32(uint32_t fetchdat) +static int +opFILDiw_a32(uint32_t fetchdat) { - int16_t temp; - FP_ENTER(); - fetch_ea_32(fetchdat); - SEG_CHECK_READ(cpu_state.ea_seg); - temp = geteaw(); if (cpu_state.abrt) return 1; - x87_push((double)temp); - CLOCK_CYCLES_FPU((fpu_type >= FPU_487SX) ? (x87_timings.fild_16) : (x87_timings.fild_16 * cpu_multi)); - CONCURRENCY_CYCLES((fpu_type >= FPU_487SX) ? (x87_concurrency.fild_16) : (x87_concurrency.fild_16 * cpu_multi)); - return 0; + int16_t temp; + FP_ENTER(); + fetch_ea_32(fetchdat); + SEG_CHECK_READ(cpu_state.ea_seg); + temp = geteaw(); + if (cpu_state.abrt) + return 1; + x87_push((double) temp); + CLOCK_CYCLES_FPU((fpu_type >= FPU_487SX) ? (x87_timings.fild_16) : (x87_timings.fild_16 * cpu_multi)); + CONCURRENCY_CYCLES((fpu_type >= FPU_487SX) ? (x87_concurrency.fild_16) : (x87_concurrency.fild_16 * cpu_multi)); + return 0; } #endif -static int opFISTiw_a16(uint32_t fetchdat) +static int +opFISTiw_a16(uint32_t fetchdat) { - FP_ENTER(); - fetch_ea_16(fetchdat); - SEG_CHECK_WRITE(cpu_state.ea_seg); - seteaw(x87_fround16(ST(0))); - CLOCK_CYCLES_FPU((fpu_type >= FPU_487SX) ? (x87_timings.fist_16) : (x87_timings.fist_16 * cpu_multi)); - CONCURRENCY_CYCLES((fpu_type >= FPU_487SX) ? (x87_concurrency.fist_16) : (x87_concurrency.fist_16 * cpu_multi)); - return cpu_state.abrt; + FP_ENTER(); + fetch_ea_16(fetchdat); + SEG_CHECK_WRITE(cpu_state.ea_seg); + seteaw(x87_fround16(ST(0))); + CLOCK_CYCLES_FPU((fpu_type >= FPU_487SX) ? (x87_timings.fist_16) : (x87_timings.fist_16 * cpu_multi)); + CONCURRENCY_CYCLES((fpu_type >= FPU_487SX) ? (x87_concurrency.fist_16) : (x87_concurrency.fist_16 * cpu_multi)); + return cpu_state.abrt; } #ifndef FPU_8087 -static int opFISTiw_a32(uint32_t fetchdat) +static int +opFISTiw_a32(uint32_t fetchdat) { - FP_ENTER(); - fetch_ea_32(fetchdat); - SEG_CHECK_WRITE(cpu_state.ea_seg); - seteaw(x87_fround16(ST(0))); - CLOCK_CYCLES_FPU((fpu_type >= FPU_487SX) ? (x87_timings.fist_16) : (x87_timings.fist_16 * cpu_multi)); - CONCURRENCY_CYCLES((fpu_type >= FPU_487SX) ? (x87_concurrency.fist_16) : (x87_concurrency.fist_16 * cpu_multi)); - return cpu_state.abrt; + FP_ENTER(); + fetch_ea_32(fetchdat); + SEG_CHECK_WRITE(cpu_state.ea_seg); + seteaw(x87_fround16(ST(0))); + CLOCK_CYCLES_FPU((fpu_type >= FPU_487SX) ? (x87_timings.fist_16) : (x87_timings.fist_16 * cpu_multi)); + CONCURRENCY_CYCLES((fpu_type >= FPU_487SX) ? (x87_concurrency.fist_16) : (x87_concurrency.fist_16 * cpu_multi)); + return cpu_state.abrt; } #endif -static int opFISTPiw_a16(uint32_t fetchdat) +static int +opFISTPiw_a16(uint32_t fetchdat) { - FP_ENTER(); - fetch_ea_16(fetchdat); - SEG_CHECK_WRITE(cpu_state.ea_seg); - seteaw(x87_fround16(ST(0))); if (cpu_state.abrt) return 1; - x87_pop(); - CLOCK_CYCLES_FPU((fpu_type >= FPU_487SX) ? (x87_timings.fist_16) : (x87_timings.fist_16 * cpu_multi)); - CONCURRENCY_CYCLES((fpu_type >= FPU_487SX) ? (x87_concurrency.fist_16) : (x87_concurrency.fist_16 * cpu_multi)); - return 0; + FP_ENTER(); + fetch_ea_16(fetchdat); + SEG_CHECK_WRITE(cpu_state.ea_seg); + seteaw(x87_fround16(ST(0))); + if (cpu_state.abrt) + return 1; + x87_pop(); + CLOCK_CYCLES_FPU((fpu_type >= FPU_487SX) ? (x87_timings.fist_16) : (x87_timings.fist_16 * cpu_multi)); + CONCURRENCY_CYCLES((fpu_type >= FPU_487SX) ? (x87_concurrency.fist_16) : (x87_concurrency.fist_16 * cpu_multi)); + return 0; } #ifndef FPU_8087 -static int opFISTPiw_a32(uint32_t fetchdat) +static int +opFISTPiw_a32(uint32_t fetchdat) { - FP_ENTER(); - fetch_ea_32(fetchdat); - SEG_CHECK_WRITE(cpu_state.ea_seg); - seteaw(x87_fround16(ST(0))); if (cpu_state.abrt) return 1; - x87_pop(); - CLOCK_CYCLES_FPU((fpu_type >= FPU_487SX) ? (x87_timings.fist_16) : (x87_timings.fist_16 * cpu_multi)); - CONCURRENCY_CYCLES((fpu_type >= FPU_487SX) ? (x87_concurrency.fist_16) : (x87_concurrency.fist_16 * cpu_multi)); - return 0; + FP_ENTER(); + fetch_ea_32(fetchdat); + SEG_CHECK_WRITE(cpu_state.ea_seg); + seteaw(x87_fround16(ST(0))); + if (cpu_state.abrt) + return 1; + x87_pop(); + CLOCK_CYCLES_FPU((fpu_type >= FPU_487SX) ? (x87_timings.fist_16) : (x87_timings.fist_16 * cpu_multi)); + CONCURRENCY_CYCLES((fpu_type >= FPU_487SX) ? (x87_concurrency.fist_16) : (x87_concurrency.fist_16 * cpu_multi)); + return 0; } #endif -static int opFILDiq_a16(uint32_t fetchdat) +static int +opFILDiq_a16(uint32_t fetchdat) { - int64_t temp64; - FP_ENTER(); - fetch_ea_16(fetchdat); - SEG_CHECK_READ(cpu_state.ea_seg); - temp64 = geteaq(); if (cpu_state.abrt) return 1; - x87_push((double)temp64); - cpu_state.MM[cpu_state.TOP&7].q = temp64; - FP_TAG_DEFAULT; + int64_t temp64; + FP_ENTER(); + fetch_ea_16(fetchdat); + SEG_CHECK_READ(cpu_state.ea_seg); + temp64 = geteaq(); + if (cpu_state.abrt) + return 1; + x87_push((double) temp64); + cpu_state.MM[cpu_state.TOP & 7].q = temp64; + FP_TAG_DEFAULT; - CLOCK_CYCLES_FPU((fpu_type >= FPU_487SX) ? (x87_timings.fild_64) : (x87_timings.fild_64 * cpu_multi)); - CONCURRENCY_CYCLES((fpu_type >= FPU_487SX) ? (x87_concurrency.fild_64) : (x87_concurrency.fild_64 * cpu_multi)); - return 0; + CLOCK_CYCLES_FPU((fpu_type >= FPU_487SX) ? (x87_timings.fild_64) : (x87_timings.fild_64 * cpu_multi)); + CONCURRENCY_CYCLES((fpu_type >= FPU_487SX) ? (x87_concurrency.fild_64) : (x87_concurrency.fild_64 * cpu_multi)); + return 0; } #ifndef FPU_8087 -static int opFILDiq_a32(uint32_t fetchdat) +static int +opFILDiq_a32(uint32_t fetchdat) { - int64_t temp64; - FP_ENTER(); - fetch_ea_32(fetchdat); - SEG_CHECK_READ(cpu_state.ea_seg); - temp64 = geteaq(); if (cpu_state.abrt) return 1; - x87_push((double)temp64); - cpu_state.MM[cpu_state.TOP&7].q = temp64; - FP_TAG_DEFAULT; + int64_t temp64; + FP_ENTER(); + fetch_ea_32(fetchdat); + SEG_CHECK_READ(cpu_state.ea_seg); + temp64 = geteaq(); + if (cpu_state.abrt) + return 1; + x87_push((double) temp64); + cpu_state.MM[cpu_state.TOP & 7].q = temp64; + FP_TAG_DEFAULT; - CLOCK_CYCLES_FPU((fpu_type >= FPU_487SX) ? (x87_timings.fild_64) : (x87_timings.fild_64 * cpu_multi)); - CONCURRENCY_CYCLES((fpu_type >= FPU_487SX) ? (x87_concurrency.fild_64) : (x87_concurrency.fild_64 * cpu_multi)); - return 0; + CLOCK_CYCLES_FPU((fpu_type >= FPU_487SX) ? (x87_timings.fild_64) : (x87_timings.fild_64 * cpu_multi)); + CONCURRENCY_CYCLES((fpu_type >= FPU_487SX) ? (x87_concurrency.fild_64) : (x87_concurrency.fild_64 * cpu_multi)); + return 0; } #endif -static int FBSTP_a16(uint32_t fetchdat) +static int +FBSTP_a16(uint32_t fetchdat) { - double tempd; - int c; - FP_ENTER(); - fetch_ea_16(fetchdat); - SEG_CHECK_WRITE(cpu_state.ea_seg); - tempd = ST(0); - if (tempd < 0.0) - tempd = -tempd; - for (c = 0; c < 9; c++) - { - uint8_t tempc = (uint8_t)floor(fmod(tempd, 10.0)); - tempd -= floor(fmod(tempd, 10.0)); - tempd /= 10.0; - tempc |= ((uint8_t)floor(fmod(tempd, 10.0))) << 4; - tempd -= floor(fmod(tempd, 10.0)); - tempd /= 10.0; - writememb(easeg, cpu_state.eaaddr + c, tempc); - } - tempc = (uint8_t)floor(fmod(tempd, 10.0)); - if (ST(0) < 0.0) tempc |= 0x80; - writememb(easeg, cpu_state.eaaddr + 9, tempc); if (cpu_state.abrt) return 1; - x87_pop(); - CLOCK_CYCLES_FPU((fpu_type >= FPU_487SX) ? (x87_timings.fbstp) : (x87_timings.fbstp * cpu_multi)); - CONCURRENCY_CYCLES((fpu_type >= FPU_487SX) ? (x87_concurrency.fbstp) : (x87_concurrency.fbstp * cpu_multi)); - return 0; + double dt; + double tempd; + int c; + FP_ENTER(); + fetch_ea_16(fetchdat); + SEG_CHECK_WRITE(cpu_state.ea_seg); + tempd = ST(0); + if (tempd < 0.0) + tempd = -tempd; + for (c = 0; c < 9; c++) { + dt = floor(fmod(tempd, 10.0)); + uint8_t tempc = (uint8_t) dt; + tempd -= floor(fmod(tempd, 10.0)); + tempd /= 10.0; + dt = floor(fmod(tempd, 10.0)); + tempc |= ((uint8_t) dt) << 4; + tempd -= floor(fmod(tempd, 10.0)); + tempd /= 10.0; + writememb(easeg, cpu_state.eaaddr + c, tempc); + } + dt = floor(fmod(tempd, 10.0)); + tempc = (uint8_t) dt; + if (ST(0) < 0.0) + tempc |= 0x80; + writememb(easeg, cpu_state.eaaddr + 9, tempc); + if (cpu_state.abrt) + return 1; + x87_pop(); + CLOCK_CYCLES_FPU((fpu_type >= FPU_487SX) ? (x87_timings.fbstp) : (x87_timings.fbstp * cpu_multi)); + CONCURRENCY_CYCLES((fpu_type >= FPU_487SX) ? (x87_concurrency.fbstp) : (x87_concurrency.fbstp * cpu_multi)); + return 0; } #ifndef FPU_8087 -static int FBSTP_a32(uint32_t fetchdat) +static int +FBSTP_a32(uint32_t fetchdat) { - double tempd; - int c; - FP_ENTER(); - fetch_ea_32(fetchdat); - SEG_CHECK_WRITE(cpu_state.ea_seg); - tempd = ST(0); - if (tempd < 0.0) - tempd = -tempd; - for (c = 0; c < 9; c++) - { - uint8_t tempc = (uint8_t)floor(fmod(tempd, 10.0)); - tempd -= floor(fmod(tempd, 10.0)); - tempd /= 10.0; - tempc |= ((uint8_t)floor(fmod(tempd, 10.0))) << 4; - tempd -= floor(fmod(tempd, 10.0)); - tempd /= 10.0; - writememb(easeg, cpu_state.eaaddr + c, tempc); - } - tempc = (uint8_t)floor(fmod(tempd, 10.0)); - if (ST(0) < 0.0) tempc |= 0x80; - writememb(easeg, cpu_state.eaaddr + 9, tempc); if (cpu_state.abrt) return 1; - x87_pop(); - CLOCK_CYCLES_FPU((fpu_type >= FPU_487SX) ? (x87_timings.fbstp) : (x87_timings.fbstp * cpu_multi)); - return 0; + double tempd; + int c; + FP_ENTER(); + fetch_ea_32(fetchdat); + SEG_CHECK_WRITE(cpu_state.ea_seg); + tempd = ST(0); + if (tempd < 0.0) + tempd = -tempd; + for (c = 0; c < 9; c++) { + uint8_t tempc = (uint8_t) floor(fmod(tempd, 10.0)); + tempd -= floor(fmod(tempd, 10.0)); + tempd /= 10.0; + tempc |= ((uint8_t) floor(fmod(tempd, 10.0))) << 4; + tempd -= floor(fmod(tempd, 10.0)); + tempd /= 10.0; + writememb(easeg, cpu_state.eaaddr + c, tempc); + } + tempc = (uint8_t) floor(fmod(tempd, 10.0)); + if (ST(0) < 0.0) + tempc |= 0x80; + writememb(easeg, cpu_state.eaaddr + 9, tempc); + if (cpu_state.abrt) + return 1; + x87_pop(); + CLOCK_CYCLES_FPU((fpu_type >= FPU_487SX) ? (x87_timings.fbstp) : (x87_timings.fbstp * cpu_multi)); + return 0; } #endif -static int FISTPiq_a16(uint32_t fetchdat) +static int +FISTPiq_a16(uint32_t fetchdat) { - int64_t temp64; - FP_ENTER(); - fetch_ea_16(fetchdat); - SEG_CHECK_WRITE(cpu_state.ea_seg); - if (cpu_state.tag[cpu_state.TOP&7] & TAG_UINT64) - temp64 = cpu_state.MM[cpu_state.TOP&7].q; - else - temp64 = x87_fround(ST(0)); - seteaq(temp64); if (cpu_state.abrt) return 1; - x87_pop(); - CLOCK_CYCLES_FPU((fpu_type >= FPU_487SX) ? (x87_timings.fist_64) : (x87_timings.fist_64 * cpu_multi)); - CONCURRENCY_CYCLES((fpu_type >= FPU_487SX) ? (x87_concurrency.fist_64) : (x87_concurrency.fist_64 * cpu_multi)); - return 0; + int64_t temp64; + FP_ENTER(); + fetch_ea_16(fetchdat); + SEG_CHECK_WRITE(cpu_state.ea_seg); + if (cpu_state.tag[cpu_state.TOP & 7] & TAG_UINT64) + temp64 = cpu_state.MM[cpu_state.TOP & 7].q; + else + temp64 = x87_fround(ST(0)); + seteaq(temp64); + if (cpu_state.abrt) + return 1; + x87_pop(); + CLOCK_CYCLES_FPU((fpu_type >= FPU_487SX) ? (x87_timings.fist_64) : (x87_timings.fist_64 * cpu_multi)); + CONCURRENCY_CYCLES((fpu_type >= FPU_487SX) ? (x87_concurrency.fist_64) : (x87_concurrency.fist_64 * cpu_multi)); + return 0; } #ifndef FPU_8087 -static int FISTPiq_a32(uint32_t fetchdat) +static int +FISTPiq_a32(uint32_t fetchdat) { - int64_t temp64; - FP_ENTER(); - fetch_ea_32(fetchdat); - SEG_CHECK_WRITE(cpu_state.ea_seg); - if (cpu_state.tag[cpu_state.TOP&7] & TAG_UINT64) - temp64 = cpu_state.MM[cpu_state.TOP&7].q; - else - temp64 = x87_fround(ST(0)); - seteaq(temp64); if (cpu_state.abrt) return 1; - x87_pop(); - CLOCK_CYCLES_FPU((fpu_type >= FPU_487SX) ? (x87_timings.fist_64) : (x87_timings.fist_64 * cpu_multi)); - CONCURRENCY_CYCLES((fpu_type >= FPU_487SX) ? (x87_concurrency.fist_64) : (x87_concurrency.fist_64 * cpu_multi)); - return 0; + int64_t temp64; + FP_ENTER(); + fetch_ea_32(fetchdat); + SEG_CHECK_WRITE(cpu_state.ea_seg); + if (cpu_state.tag[cpu_state.TOP & 7] & TAG_UINT64) + temp64 = cpu_state.MM[cpu_state.TOP & 7].q; + else + temp64 = x87_fround(ST(0)); + seteaq(temp64); + if (cpu_state.abrt) + return 1; + x87_pop(); + CLOCK_CYCLES_FPU((fpu_type >= FPU_487SX) ? (x87_timings.fist_64) : (x87_timings.fist_64 * cpu_multi)); + CONCURRENCY_CYCLES((fpu_type >= FPU_487SX) ? (x87_concurrency.fist_64) : (x87_concurrency.fist_64 * cpu_multi)); + return 0; } #endif -static int opFILDil_a16(uint32_t fetchdat) +static int +opFILDil_a16(uint32_t fetchdat) { - int32_t templ; - FP_ENTER(); - fetch_ea_16(fetchdat); - SEG_CHECK_READ(cpu_state.ea_seg); - templ = geteal(); if (cpu_state.abrt) return 1; - x87_push((double)templ); - CLOCK_CYCLES_FPU((fpu_type >= FPU_487SX) ? (x87_timings.fild_32) : (x87_timings.fild_32 * cpu_multi)); - CONCURRENCY_CYCLES((fpu_type >= FPU_487SX) ? (x87_concurrency.fild_32) : (x87_concurrency.fild_32 * cpu_multi)); - return 0; + int32_t templ; + FP_ENTER(); + fetch_ea_16(fetchdat); + SEG_CHECK_READ(cpu_state.ea_seg); + templ = geteal(); + if (cpu_state.abrt) + return 1; + x87_push((double) templ); + CLOCK_CYCLES_FPU((fpu_type >= FPU_487SX) ? (x87_timings.fild_32) : (x87_timings.fild_32 * cpu_multi)); + CONCURRENCY_CYCLES((fpu_type >= FPU_487SX) ? (x87_concurrency.fild_32) : (x87_concurrency.fild_32 * cpu_multi)); + return 0; } #ifndef FPU_8087 -static int opFILDil_a32(uint32_t fetchdat) +static int +opFILDil_a32(uint32_t fetchdat) { - int32_t templ; - FP_ENTER(); - fetch_ea_32(fetchdat); - SEG_CHECK_READ(cpu_state.ea_seg); - templ = geteal(); if (cpu_state.abrt) return 1; - x87_push((double)templ); - CLOCK_CYCLES_FPU((fpu_type >= FPU_487SX) ? (x87_timings.fild_32) : (x87_timings.fild_32 * cpu_multi)); - CONCURRENCY_CYCLES((fpu_type >= FPU_487SX) ? (x87_concurrency.fild_32) : (x87_concurrency.fild_32 * cpu_multi)); - return 0; + int32_t templ; + FP_ENTER(); + fetch_ea_32(fetchdat); + SEG_CHECK_READ(cpu_state.ea_seg); + templ = geteal(); + if (cpu_state.abrt) + return 1; + x87_push((double) templ); + CLOCK_CYCLES_FPU((fpu_type >= FPU_487SX) ? (x87_timings.fild_32) : (x87_timings.fild_32 * cpu_multi)); + CONCURRENCY_CYCLES((fpu_type >= FPU_487SX) ? (x87_concurrency.fild_32) : (x87_concurrency.fild_32 * cpu_multi)); + return 0; } #endif -static int opFISTil_a16(uint32_t fetchdat) +static int +opFISTil_a16(uint32_t fetchdat) { - FP_ENTER(); - fetch_ea_16(fetchdat); - SEG_CHECK_WRITE(cpu_state.ea_seg); - seteal(x87_fround32(ST(0))); - CLOCK_CYCLES_FPU((fpu_type >= FPU_487SX) ? (x87_timings.fist_32) : (x87_timings.fist_32 * cpu_multi)); - CONCURRENCY_CYCLES((fpu_type >= FPU_487SX) ? (x87_concurrency.fist_32) : (x87_concurrency.fist_32 * cpu_multi)); - return cpu_state.abrt; + FP_ENTER(); + fetch_ea_16(fetchdat); + SEG_CHECK_WRITE(cpu_state.ea_seg); + seteal(x87_fround32(ST(0))); + CLOCK_CYCLES_FPU((fpu_type >= FPU_487SX) ? (x87_timings.fist_32) : (x87_timings.fist_32 * cpu_multi)); + CONCURRENCY_CYCLES((fpu_type >= FPU_487SX) ? (x87_concurrency.fist_32) : (x87_concurrency.fist_32 * cpu_multi)); + return cpu_state.abrt; } #ifndef FPU_8087 -static int opFISTil_a32(uint32_t fetchdat) +static int +opFISTil_a32(uint32_t fetchdat) { - FP_ENTER(); - fetch_ea_32(fetchdat); - SEG_CHECK_WRITE(cpu_state.ea_seg); - seteal(x87_fround32(ST(0))); - CLOCK_CYCLES_FPU((fpu_type >= FPU_487SX) ? (x87_timings.fist_32) : (x87_timings.fist_32 * cpu_multi)); - CONCURRENCY_CYCLES((fpu_type >= FPU_487SX) ? (x87_concurrency.fist_32) : (x87_concurrency.fist_32 * cpu_multi)); - return cpu_state.abrt; + FP_ENTER(); + fetch_ea_32(fetchdat); + SEG_CHECK_WRITE(cpu_state.ea_seg); + seteal(x87_fround32(ST(0))); + CLOCK_CYCLES_FPU((fpu_type >= FPU_487SX) ? (x87_timings.fist_32) : (x87_timings.fist_32 * cpu_multi)); + CONCURRENCY_CYCLES((fpu_type >= FPU_487SX) ? (x87_concurrency.fist_32) : (x87_concurrency.fist_32 * cpu_multi)); + return cpu_state.abrt; } #endif -static int opFISTPil_a16(uint32_t fetchdat) +static int +opFISTPil_a16(uint32_t fetchdat) { - FP_ENTER(); - fetch_ea_16(fetchdat); - SEG_CHECK_WRITE(cpu_state.ea_seg); - seteal(x87_fround32(ST(0))); if (cpu_state.abrt) return 1; - x87_pop(); - CLOCK_CYCLES_FPU((fpu_type >= FPU_487SX) ? (x87_timings.fist_32) : (x87_timings.fist_32 * cpu_multi)); - CONCURRENCY_CYCLES((fpu_type >= FPU_487SX) ? (x87_concurrency.fist_32) : (x87_concurrency.fist_32 * cpu_multi)); - return 0; + FP_ENTER(); + fetch_ea_16(fetchdat); + SEG_CHECK_WRITE(cpu_state.ea_seg); + seteal(x87_fround32(ST(0))); + if (cpu_state.abrt) + return 1; + x87_pop(); + CLOCK_CYCLES_FPU((fpu_type >= FPU_487SX) ? (x87_timings.fist_32) : (x87_timings.fist_32 * cpu_multi)); + CONCURRENCY_CYCLES((fpu_type >= FPU_487SX) ? (x87_concurrency.fist_32) : (x87_concurrency.fist_32 * cpu_multi)); + return 0; } #ifndef FPU_8087 -static int opFISTPil_a32(uint32_t fetchdat) +static int +opFISTPil_a32(uint32_t fetchdat) { - FP_ENTER(); - fetch_ea_32(fetchdat); - SEG_CHECK_WRITE(cpu_state.ea_seg); - seteal(x87_fround32(ST(0))); if (cpu_state.abrt) return 1; - x87_pop(); - CLOCK_CYCLES_FPU((fpu_type >= FPU_487SX) ? (x87_timings.fist_32) : (x87_timings.fist_32 * cpu_multi)); - CONCURRENCY_CYCLES((fpu_type >= FPU_487SX) ? (x87_concurrency.fist_32) : (x87_concurrency.fist_32 * cpu_multi)); - return 0; + FP_ENTER(); + fetch_ea_32(fetchdat); + SEG_CHECK_WRITE(cpu_state.ea_seg); + seteal(x87_fround32(ST(0))); + if (cpu_state.abrt) + return 1; + x87_pop(); + CLOCK_CYCLES_FPU((fpu_type >= FPU_487SX) ? (x87_timings.fist_32) : (x87_timings.fist_32 * cpu_multi)); + CONCURRENCY_CYCLES((fpu_type >= FPU_487SX) ? (x87_concurrency.fist_32) : (x87_concurrency.fist_32 * cpu_multi)); + return 0; } #endif -static int opFLDe_a16(uint32_t fetchdat) +static int +opFLDe_a16(uint32_t fetchdat) { - double t; - FP_ENTER(); - fetch_ea_16(fetchdat); - SEG_CHECK_READ(cpu_state.ea_seg); - t=x87_ld80(); if (cpu_state.abrt) return 1; - x87_push(t); - CLOCK_CYCLES_FPU((fpu_type >= FPU_487SX) ? (x87_timings.fld_80) : (x87_timings.fld_80 * cpu_multi)); - CONCURRENCY_CYCLES((fpu_type >= FPU_487SX) ? (x87_concurrency.fld_80) : (x87_concurrency.fld_80 * cpu_multi)); - return 0; + double t; + FP_ENTER(); + fetch_ea_16(fetchdat); + SEG_CHECK_READ(cpu_state.ea_seg); + t = x87_ld80(); + if (cpu_state.abrt) + return 1; + x87_push(t); + CLOCK_CYCLES_FPU((fpu_type >= FPU_487SX) ? (x87_timings.fld_80) : (x87_timings.fld_80 * cpu_multi)); + CONCURRENCY_CYCLES((fpu_type >= FPU_487SX) ? (x87_concurrency.fld_80) : (x87_concurrency.fld_80 * cpu_multi)); + return 0; } #ifndef FPU_8087 -static int opFLDe_a32(uint32_t fetchdat) +static int +opFLDe_a32(uint32_t fetchdat) { - double t; - FP_ENTER(); - fetch_ea_32(fetchdat); - SEG_CHECK_READ(cpu_state.ea_seg); - t=x87_ld80(); if (cpu_state.abrt) return 1; - x87_push(t); - CLOCK_CYCLES_FPU((fpu_type >= FPU_487SX) ? (x87_timings.fld_80) : (x87_timings.fld_80 * cpu_multi)); - CONCURRENCY_CYCLES((fpu_type >= FPU_487SX) ? (x87_concurrency.fld_80) : (x87_concurrency.fld_80 * cpu_multi)); - return 0; + double t; + FP_ENTER(); + fetch_ea_32(fetchdat); + SEG_CHECK_READ(cpu_state.ea_seg); + t = x87_ld80(); + if (cpu_state.abrt) + return 1; + x87_push(t); + CLOCK_CYCLES_FPU((fpu_type >= FPU_487SX) ? (x87_timings.fld_80) : (x87_timings.fld_80 * cpu_multi)); + CONCURRENCY_CYCLES((fpu_type >= FPU_487SX) ? (x87_concurrency.fld_80) : (x87_concurrency.fld_80 * cpu_multi)); + return 0; } #endif -static int opFSTPe_a16(uint32_t fetchdat) +static int +opFSTPe_a16(uint32_t fetchdat) { - FP_ENTER(); - fetch_ea_16(fetchdat); - SEG_CHECK_WRITE(cpu_state.ea_seg); - x87_st80(ST(0)); if (cpu_state.abrt) return 1; - x87_pop(); - CLOCK_CYCLES_FPU((fpu_type >= FPU_487SX) ? (x87_timings.fld_80) : (x87_timings.fld_80 * cpu_multi)); - CONCURRENCY_CYCLES((fpu_type >= FPU_487SX) ? (x87_concurrency.fld_80) : (x87_concurrency.fld_80 * cpu_multi)); - return 0; + FP_ENTER(); + fetch_ea_16(fetchdat); + SEG_CHECK_WRITE(cpu_state.ea_seg); + x87_st80(ST(0)); + if (cpu_state.abrt) + return 1; + x87_pop(); + CLOCK_CYCLES_FPU((fpu_type >= FPU_487SX) ? (x87_timings.fld_80) : (x87_timings.fld_80 * cpu_multi)); + CONCURRENCY_CYCLES((fpu_type >= FPU_487SX) ? (x87_concurrency.fld_80) : (x87_concurrency.fld_80 * cpu_multi)); + return 0; } #ifndef FPU_8087 -static int opFSTPe_a32(uint32_t fetchdat) +static int +opFSTPe_a32(uint32_t fetchdat) { - FP_ENTER(); - fetch_ea_32(fetchdat); - SEG_CHECK_WRITE(cpu_state.ea_seg); - x87_st80(ST(0)); if (cpu_state.abrt) return 1; - x87_pop(); - CLOCK_CYCLES_FPU((fpu_type >= FPU_487SX) ? (x87_timings.fld_80) : (x87_timings.fld_80 * cpu_multi)); - CONCURRENCY_CYCLES((fpu_type >= FPU_487SX) ? (x87_concurrency.fld_80) : (x87_concurrency.fld_80 * cpu_multi)); - return 0; + FP_ENTER(); + fetch_ea_32(fetchdat); + SEG_CHECK_WRITE(cpu_state.ea_seg); + x87_st80(ST(0)); + if (cpu_state.abrt) + return 1; + x87_pop(); + CLOCK_CYCLES_FPU((fpu_type >= FPU_487SX) ? (x87_timings.fld_80) : (x87_timings.fld_80 * cpu_multi)); + CONCURRENCY_CYCLES((fpu_type >= FPU_487SX) ? (x87_concurrency.fld_80) : (x87_concurrency.fld_80 * cpu_multi)); + return 0; } #endif -static int opFLDd_a16(uint32_t fetchdat) +static int +opFLDd_a16(uint32_t fetchdat) { - x87_td t; - FP_ENTER(); - fetch_ea_16(fetchdat); - SEG_CHECK_READ(cpu_state.ea_seg); - t.i = geteaq(); if (cpu_state.abrt) return 1; - x87_push(t.d); - CLOCK_CYCLES_FPU((fpu_type >= FPU_487SX) ? (x87_timings.fld_64) : (x87_timings.fld_64 * cpu_multi)); - CONCURRENCY_CYCLES((fpu_type >= FPU_487SX) ? (x87_concurrency.fld_64) : (x87_concurrency.fld_64 * cpu_multi)); - return 0; + x87_td t; + FP_ENTER(); + fetch_ea_16(fetchdat); + SEG_CHECK_READ(cpu_state.ea_seg); + t.i = geteaq(); + if (cpu_state.abrt) + return 1; + x87_push(t.d); + CLOCK_CYCLES_FPU((fpu_type >= FPU_487SX) ? (x87_timings.fld_64) : (x87_timings.fld_64 * cpu_multi)); + CONCURRENCY_CYCLES((fpu_type >= FPU_487SX) ? (x87_concurrency.fld_64) : (x87_concurrency.fld_64 * cpu_multi)); + return 0; } #ifndef FPU_8087 -static int opFLDd_a32(uint32_t fetchdat) +static int +opFLDd_a32(uint32_t fetchdat) { - x87_td t; - FP_ENTER(); - fetch_ea_32(fetchdat); - SEG_CHECK_READ(cpu_state.ea_seg); - t.i = geteaq(); if (cpu_state.abrt) return 1; - x87_push(t.d); - CLOCK_CYCLES_FPU((fpu_type >= FPU_487SX) ? (x87_timings.fld_64) : (x87_timings.fld_64 * cpu_multi)); - CONCURRENCY_CYCLES((fpu_type >= FPU_487SX) ? (x87_concurrency.fld_64) : (x87_concurrency.fld_64 * cpu_multi)); - return 0; + x87_td t; + FP_ENTER(); + fetch_ea_32(fetchdat); + SEG_CHECK_READ(cpu_state.ea_seg); + t.i = geteaq(); + if (cpu_state.abrt) + return 1; + x87_push(t.d); + CLOCK_CYCLES_FPU((fpu_type >= FPU_487SX) ? (x87_timings.fld_64) : (x87_timings.fld_64 * cpu_multi)); + CONCURRENCY_CYCLES((fpu_type >= FPU_487SX) ? (x87_concurrency.fld_64) : (x87_concurrency.fld_64 * cpu_multi)); + return 0; } #endif -static int opFSTd_a16(uint32_t fetchdat) +static int +opFSTd_a16(uint32_t fetchdat) { - x87_td t; - FP_ENTER(); - fetch_ea_16(fetchdat); - SEG_CHECK_WRITE(cpu_state.ea_seg); - t.d = ST(0); - seteaq(t.i); - CLOCK_CYCLES_FPU((fpu_type >= FPU_487SX) ? (x87_timings.fst_64) : (x87_timings.fst_64 * cpu_multi)); - CONCURRENCY_CYCLES((fpu_type >= FPU_487SX) ? (x87_concurrency.fst_64) : (x87_concurrency.fst_64 * cpu_multi)); - return cpu_state.abrt; + x87_td t; + FP_ENTER(); + fetch_ea_16(fetchdat); + SEG_CHECK_WRITE(cpu_state.ea_seg); + t.d = ST(0); + seteaq(t.i); + CLOCK_CYCLES_FPU((fpu_type >= FPU_487SX) ? (x87_timings.fst_64) : (x87_timings.fst_64 * cpu_multi)); + CONCURRENCY_CYCLES((fpu_type >= FPU_487SX) ? (x87_concurrency.fst_64) : (x87_concurrency.fst_64 * cpu_multi)); + return cpu_state.abrt; } #ifndef FPU_8087 -static int opFSTd_a32(uint32_t fetchdat) +static int +opFSTd_a32(uint32_t fetchdat) { - x87_td t; - FP_ENTER(); - fetch_ea_32(fetchdat); - SEG_CHECK_WRITE(cpu_state.ea_seg); - t.d = ST(0); - seteaq(t.i); - CLOCK_CYCLES_FPU((fpu_type >= FPU_487SX) ? (x87_timings.fst_64) : (x87_timings.fst_64 * cpu_multi)); - CONCURRENCY_CYCLES((fpu_type >= FPU_487SX) ? (x87_concurrency.fst_64) : (x87_concurrency.fst_64 * cpu_multi)); - return cpu_state.abrt; + x87_td t; + FP_ENTER(); + fetch_ea_32(fetchdat); + SEG_CHECK_WRITE(cpu_state.ea_seg); + t.d = ST(0); + seteaq(t.i); + CLOCK_CYCLES_FPU((fpu_type >= FPU_487SX) ? (x87_timings.fst_64) : (x87_timings.fst_64 * cpu_multi)); + CONCURRENCY_CYCLES((fpu_type >= FPU_487SX) ? (x87_concurrency.fst_64) : (x87_concurrency.fst_64 * cpu_multi)); + return cpu_state.abrt; } #endif -static int opFSTPd_a16(uint32_t fetchdat) +static int +opFSTPd_a16(uint32_t fetchdat) { - x87_td t; - FP_ENTER(); - fetch_ea_16(fetchdat); - SEG_CHECK_WRITE(cpu_state.ea_seg); - t.d = ST(0); - seteaq(t.i); if (cpu_state.abrt) return 1; - x87_pop(); - CLOCK_CYCLES_FPU((fpu_type >= FPU_487SX) ? (x87_timings.fst_64) : (x87_timings.fst_64 * cpu_multi)); - CONCURRENCY_CYCLES((fpu_type >= FPU_487SX) ? (x87_concurrency.fst_64) : (x87_concurrency.fst_64 * cpu_multi)); - return 0; + x87_td t; + FP_ENTER(); + fetch_ea_16(fetchdat); + SEG_CHECK_WRITE(cpu_state.ea_seg); + t.d = ST(0); + seteaq(t.i); + if (cpu_state.abrt) + return 1; + x87_pop(); + CLOCK_CYCLES_FPU((fpu_type >= FPU_487SX) ? (x87_timings.fst_64) : (x87_timings.fst_64 * cpu_multi)); + CONCURRENCY_CYCLES((fpu_type >= FPU_487SX) ? (x87_concurrency.fst_64) : (x87_concurrency.fst_64 * cpu_multi)); + return 0; } #ifndef FPU_8087 -static int opFSTPd_a32(uint32_t fetchdat) +static int +opFSTPd_a32(uint32_t fetchdat) { - x87_td t; - FP_ENTER(); - fetch_ea_32(fetchdat); - SEG_CHECK_WRITE(cpu_state.ea_seg); - t.d = ST(0); - seteaq(t.i); if (cpu_state.abrt) return 1; - x87_pop(); - CLOCK_CYCLES_FPU((fpu_type >= FPU_487SX) ? (x87_timings.fst_64) : (x87_timings.fst_64 * cpu_multi)); - CONCURRENCY_CYCLES((fpu_type >= FPU_487SX) ? (x87_concurrency.fst_64) : (x87_concurrency.fst_64 * cpu_multi)); - return 0; + x87_td t; + FP_ENTER(); + fetch_ea_32(fetchdat); + SEG_CHECK_WRITE(cpu_state.ea_seg); + t.d = ST(0); + seteaq(t.i); + if (cpu_state.abrt) + return 1; + x87_pop(); + CLOCK_CYCLES_FPU((fpu_type >= FPU_487SX) ? (x87_timings.fst_64) : (x87_timings.fst_64 * cpu_multi)); + CONCURRENCY_CYCLES((fpu_type >= FPU_487SX) ? (x87_concurrency.fst_64) : (x87_concurrency.fst_64 * cpu_multi)); + return 0; } #endif -static int opFLDs_a16(uint32_t fetchdat) +static int +opFLDs_a16(uint32_t fetchdat) { - x87_ts ts; - FP_ENTER(); - fetch_ea_16(fetchdat); - SEG_CHECK_READ(cpu_state.ea_seg); - ts.i = geteal(); if (cpu_state.abrt) return 1; - x87_push((double)ts.s); - CLOCK_CYCLES_FPU((fpu_type >= FPU_487SX) ? (x87_timings.fst_32) : (x87_timings.fst_32 * cpu_multi)); - CONCURRENCY_CYCLES((fpu_type >= FPU_487SX) ? (x87_concurrency.fst_32) : (x87_concurrency.fst_32 * cpu_multi)); - return 0; + x87_ts ts; + FP_ENTER(); + fetch_ea_16(fetchdat); + SEG_CHECK_READ(cpu_state.ea_seg); + ts.i = geteal(); + if (cpu_state.abrt) + return 1; + x87_push((double) ts.s); + CLOCK_CYCLES_FPU((fpu_type >= FPU_487SX) ? (x87_timings.fst_32) : (x87_timings.fst_32 * cpu_multi)); + CONCURRENCY_CYCLES((fpu_type >= FPU_487SX) ? (x87_concurrency.fst_32) : (x87_concurrency.fst_32 * cpu_multi)); + return 0; } #ifndef FPU_8087 -static int opFLDs_a32(uint32_t fetchdat) +static int +opFLDs_a32(uint32_t fetchdat) { - x87_ts ts; - FP_ENTER(); - fetch_ea_32(fetchdat); - SEG_CHECK_READ(cpu_state.ea_seg); - ts.i = geteal(); if (cpu_state.abrt) return 1; - x87_push((double)ts.s); - CLOCK_CYCLES_FPU((fpu_type >= FPU_487SX) ? (x87_timings.fst_32) : (x87_timings.fst_32 * cpu_multi)); - CONCURRENCY_CYCLES((fpu_type >= FPU_487SX) ? (x87_concurrency.fst_32) : (x87_concurrency.fst_32 * cpu_multi)); - return 0; + x87_ts ts; + FP_ENTER(); + fetch_ea_32(fetchdat); + SEG_CHECK_READ(cpu_state.ea_seg); + ts.i = geteal(); + if (cpu_state.abrt) + return 1; + x87_push((double) ts.s); + CLOCK_CYCLES_FPU((fpu_type >= FPU_487SX) ? (x87_timings.fst_32) : (x87_timings.fst_32 * cpu_multi)); + CONCURRENCY_CYCLES((fpu_type >= FPU_487SX) ? (x87_concurrency.fst_32) : (x87_concurrency.fst_32 * cpu_multi)); + return 0; } #endif -static int opFSTs_a16(uint32_t fetchdat) +static int +opFSTs_a16(uint32_t fetchdat) { - x87_ts ts; - FP_ENTER(); - fetch_ea_16(fetchdat); - SEG_CHECK_WRITE(cpu_state.ea_seg); - ts.s = (float)ST(0); - seteal(ts.i); - CLOCK_CYCLES_FPU((fpu_type >= FPU_487SX) ? (x87_timings.fst_32) : (x87_timings.fst_32 * cpu_multi)); - CONCURRENCY_CYCLES((fpu_type >= FPU_487SX) ? (x87_concurrency.fst_32) : (x87_concurrency.fst_32 * cpu_multi)); - return cpu_state.abrt; + x87_ts ts; + FP_ENTER(); + fetch_ea_16(fetchdat); + SEG_CHECK_WRITE(cpu_state.ea_seg); + ts.s = (float) ST(0); + seteal(ts.i); + CLOCK_CYCLES_FPU((fpu_type >= FPU_487SX) ? (x87_timings.fst_32) : (x87_timings.fst_32 * cpu_multi)); + CONCURRENCY_CYCLES((fpu_type >= FPU_487SX) ? (x87_concurrency.fst_32) : (x87_concurrency.fst_32 * cpu_multi)); + return cpu_state.abrt; } #ifndef FPU_8087 -static int opFSTs_a32(uint32_t fetchdat) +static int +opFSTs_a32(uint32_t fetchdat) { - x87_ts ts; - FP_ENTER(); - fetch_ea_32(fetchdat); - SEG_CHECK_WRITE(cpu_state.ea_seg); - ts.s = (float)ST(0); - seteal(ts.i); - CLOCK_CYCLES_FPU((fpu_type >= FPU_487SX) ? (x87_timings.fst_32) : (x87_timings.fst_32 * cpu_multi)); - CONCURRENCY_CYCLES((fpu_type >= FPU_487SX) ? (x87_concurrency.fst_32) : (x87_concurrency.fst_32 * cpu_multi)); - return cpu_state.abrt; + x87_ts ts; + FP_ENTER(); + fetch_ea_32(fetchdat); + SEG_CHECK_WRITE(cpu_state.ea_seg); + ts.s = (float) ST(0); + seteal(ts.i); + CLOCK_CYCLES_FPU((fpu_type >= FPU_487SX) ? (x87_timings.fst_32) : (x87_timings.fst_32 * cpu_multi)); + CONCURRENCY_CYCLES((fpu_type >= FPU_487SX) ? (x87_concurrency.fst_32) : (x87_concurrency.fst_32 * cpu_multi)); + return cpu_state.abrt; } #endif -static int opFSTPs_a16(uint32_t fetchdat) +static int +opFSTPs_a16(uint32_t fetchdat) { - x87_ts ts; - FP_ENTER(); - fetch_ea_16(fetchdat); - SEG_CHECK_WRITE(cpu_state.ea_seg); - ts.s = (float)ST(0); - seteal(ts.i); if (cpu_state.abrt) return 1; - x87_pop(); - CLOCK_CYCLES_FPU((fpu_type >= FPU_487SX) ? (x87_timings.fst_32) : (x87_timings.fst_32 * cpu_multi)); - CONCURRENCY_CYCLES((fpu_type >= FPU_487SX) ? (x87_concurrency.fst_32) : (x87_concurrency.fst_32 * cpu_multi)); - return 0; + x87_ts ts; + FP_ENTER(); + fetch_ea_16(fetchdat); + SEG_CHECK_WRITE(cpu_state.ea_seg); + ts.s = (float) ST(0); + seteal(ts.i); + if (cpu_state.abrt) + return 1; + x87_pop(); + CLOCK_CYCLES_FPU((fpu_type >= FPU_487SX) ? (x87_timings.fst_32) : (x87_timings.fst_32 * cpu_multi)); + CONCURRENCY_CYCLES((fpu_type >= FPU_487SX) ? (x87_concurrency.fst_32) : (x87_concurrency.fst_32 * cpu_multi)); + return 0; } #ifndef FPU_8087 -static int opFSTPs_a32(uint32_t fetchdat) +static int +opFSTPs_a32(uint32_t fetchdat) { - x87_ts ts; - FP_ENTER(); - fetch_ea_32(fetchdat); - SEG_CHECK_WRITE(cpu_state.ea_seg); - ts.s = (float)ST(0); - seteal(ts.i); if (cpu_state.abrt) return 1; - x87_pop(); - CLOCK_CYCLES_FPU((fpu_type >= FPU_487SX) ? (x87_timings.fst_32) : (x87_timings.fst_32 * cpu_multi)); - CONCURRENCY_CYCLES((fpu_type >= FPU_487SX) ? (x87_concurrency.fst_32) : (x87_concurrency.fst_32 * cpu_multi)); - return 0; + x87_ts ts; + FP_ENTER(); + fetch_ea_32(fetchdat); + SEG_CHECK_WRITE(cpu_state.ea_seg); + ts.s = (float) ST(0); + seteal(ts.i); + if (cpu_state.abrt) + return 1; + x87_pop(); + CLOCK_CYCLES_FPU((fpu_type >= FPU_487SX) ? (x87_timings.fst_32) : (x87_timings.fst_32 * cpu_multi)); + CONCURRENCY_CYCLES((fpu_type >= FPU_487SX) ? (x87_concurrency.fst_32) : (x87_concurrency.fst_32 * cpu_multi)); + return 0; } #endif diff --git a/src/cpu/x87_ops_misc.h b/src/cpu/x87_ops_misc.h index 7a6dee001..d854f83db 100644 --- a/src/cpu/x87_ops_misc.h +++ b/src/cpu/x87_ops_misc.h @@ -1,940 +1,1073 @@ #ifdef FPU_8087 -static int opFI(uint32_t fetchdat) +static int +opFI(uint32_t fetchdat) { - FP_ENTER(); - cpu_state.pc++; - cpu_state.npxc &= ~0x80; - if (rmdat == 0xe1) - cpu_state.npxc |= 0x80; - wait(3, 0); - return 0; + FP_ENTER(); + cpu_state.pc++; + cpu_state.npxc &= ~0x80; + if (rmdat == 0xe1) + cpu_state.npxc |= 0x80; + wait(3, 0); + return 0; } #else -static int opFSTSW_AX(uint32_t fetchdat) +static int +opFSTSW_AX(uint32_t fetchdat) { - FP_ENTER(); - cpu_state.pc++; - AX = cpu_state.npxs; - CLOCK_CYCLES_FPU((fpu_type >= FPU_487SX) ? (x87_timings.fstcw_sw) : (x87_timings.fstcw_sw * cpu_multi)); - CONCURRENCY_CYCLES((fpu_type >= FPU_487SX) ? (x87_concurrency.fstcw_sw) : (x87_concurrency.fstcw_sw * cpu_multi)); - return 0; + FP_ENTER(); + cpu_state.pc++; + AX = cpu_state.npxs; + CLOCK_CYCLES_FPU((fpu_type >= FPU_487SX) ? (x87_timings.fstcw_sw) : (x87_timings.fstcw_sw * cpu_multi)); + CONCURRENCY_CYCLES((fpu_type >= FPU_487SX) ? (x87_concurrency.fstcw_sw) : (x87_concurrency.fstcw_sw * cpu_multi)); + return 0; } #endif - -static int opFNOP(uint32_t fetchdat) +static int +opFNOP(uint32_t fetchdat) { - FP_ENTER(); - cpu_state.pc++; - CLOCK_CYCLES_FPU((fpu_type >= FPU_487SX) ? (x87_timings.fnop) : (x87_timings.fnop * cpu_multi)); - CONCURRENCY_CYCLES((fpu_type >= FPU_487SX) ? (x87_concurrency.fnop) : (x87_concurrency.fnop * cpu_multi)); - return 0; + FP_ENTER(); + cpu_state.pc++; + CLOCK_CYCLES_FPU((fpu_type >= FPU_487SX) ? (x87_timings.fnop) : (x87_timings.fnop * cpu_multi)); + CONCURRENCY_CYCLES((fpu_type >= FPU_487SX) ? (x87_concurrency.fnop) : (x87_concurrency.fnop * cpu_multi)); + return 0; } -static int opFCLEX(uint32_t fetchdat) +static int +opFXTRACT(uint32_t fetchdat) { - FP_ENTER(); - cpu_state.pc++; - cpu_state.npxs &= 0xff00; - CLOCK_CYCLES_FPU((fpu_type >= FPU_487SX) ? (x87_timings.fnop) : (x87_timings.fnop * cpu_multi)); - CONCURRENCY_CYCLES((fpu_type >= FPU_487SX) ? (x87_concurrency.fnop) : (x87_concurrency.fnop * cpu_multi)); - return 0; + x87_conv_t test; + int64_t exp80; + int64_t exp80final; + double mant; + + FP_ENTER(); + cpu_state.pc++; + test.eind.d = ST(0); + exp80 = test.eind.ll & 0x7ff0000000000000LL; + exp80final = (exp80 >> 52) - BIAS64; + mant = test.eind.d / (pow(2.0, (double) exp80final)); + ST(0) = (double) exp80final; + FP_TAG_VALID; + x87_push(mant); + CLOCK_CYCLES_FPU((fpu_type >= FPU_487SX) ? (x87_timings.fxtract) : (x87_timings.fxtract * cpu_multi)); + CONCURRENCY_CYCLES((fpu_type >= FPU_487SX) ? (x87_concurrency.fxtract) : (x87_concurrency.fxtract * cpu_multi)); + return 0; } -static int opFINIT(uint32_t fetchdat) +static int +opFCLEX(uint32_t fetchdat) { - uint64_t *p; - FP_ENTER(); - cpu_state.pc++; + FP_ENTER(); + cpu_state.pc++; + cpu_state.npxs &= 0xff00; + CLOCK_CYCLES_FPU((fpu_type >= FPU_487SX) ? (x87_timings.fnop) : (x87_timings.fnop * cpu_multi)); + CONCURRENCY_CYCLES((fpu_type >= FPU_487SX) ? (x87_concurrency.fnop) : (x87_concurrency.fnop * cpu_multi)); + return 0; +} + +static int +opFINIT(uint32_t fetchdat) +{ + uint64_t *p; + FP_ENTER(); + cpu_state.pc++; #ifdef FPU_8087 - cpu_state.npxc = 0x3FF; + cpu_state.npxc = 0x3FF; #else - cpu_state.npxc = 0x37F; + cpu_state.npxc = 0x37F; #endif - codegen_set_rounding_mode(X87_ROUNDING_NEAREST); - cpu_state.npxs = 0; - p = (uint64_t *)cpu_state.tag; + codegen_set_rounding_mode(X87_ROUNDING_NEAREST); + cpu_state.npxs = 0; + p = (uint64_t *) cpu_state.tag; #ifdef USE_NEW_DYNAREC - *p = 0; + *p = 0; #else - *p = 0x0303030303030303ll; + *p = 0x0303030303030303LL; #endif - cpu_state.TOP = 0; - cpu_state.ismmx = 0; - CLOCK_CYCLES_FPU((fpu_type >= FPU_487SX) ? (x87_timings.finit) : (x87_timings.finit * cpu_multi)); - CONCURRENCY_CYCLES((fpu_type >= FPU_487SX) ? (x87_concurrency.finit) : (x87_concurrency.finit * cpu_multi)); - CPU_BLOCK_END(); - return 0; + cpu_state.TOP = 0; + cpu_state.ismmx = 0; + CLOCK_CYCLES_FPU((fpu_type >= FPU_487SX) ? (x87_timings.finit) : (x87_timings.finit * cpu_multi)); + CONCURRENCY_CYCLES((fpu_type >= FPU_487SX) ? (x87_concurrency.finit) : (x87_concurrency.finit * cpu_multi)); + CPU_BLOCK_END(); + return 0; } - -static int opFFREE(uint32_t fetchdat) +static int +opFFREE(uint32_t fetchdat) { - FP_ENTER(); - cpu_state.pc++; + FP_ENTER(); + cpu_state.pc++; #ifdef USE_NEW_DYNAREC - cpu_state.tag[(cpu_state.TOP + fetchdat) & 7] = TAG_EMPTY; + cpu_state.tag[(cpu_state.TOP + fetchdat) & 7] = TAG_EMPTY; #else - cpu_state.tag[(cpu_state.TOP + fetchdat) & 7] = 3; + cpu_state.tag[(cpu_state.TOP + fetchdat) & 7] = 3; #endif - CLOCK_CYCLES_FPU((fpu_type >= FPU_487SX) ? (x87_timings.ffree) : (x87_timings.ffree * cpu_multi)); - CONCURRENCY_CYCLES((fpu_type >= FPU_487SX) ? (x87_concurrency.ffree) : (x87_concurrency.ffree * cpu_multi)); - return 0; + CLOCK_CYCLES_FPU((fpu_type >= FPU_487SX) ? (x87_timings.ffree) : (x87_timings.ffree * cpu_multi)); + CONCURRENCY_CYCLES((fpu_type >= FPU_487SX) ? (x87_concurrency.ffree) : (x87_concurrency.ffree * cpu_multi)); + return 0; } -static int opFFREEP(uint32_t fetchdat) +static int +opFFREEP(uint32_t fetchdat) { - FP_ENTER(); - cpu_state.pc++; - cpu_state.tag[(cpu_state.TOP + fetchdat) & 7] = 3; if (cpu_state.abrt) return 1; - x87_pop(); - CLOCK_CYCLES_FPU((fpu_type >= FPU_487SX) ? (x87_timings.ffree) : (x87_timings.ffree * cpu_multi)); - CONCURRENCY_CYCLES((fpu_type >= FPU_487SX) ? (x87_concurrency.ffree) : (x87_concurrency.ffree * cpu_multi)); - return 0; + FP_ENTER(); + cpu_state.pc++; + cpu_state.tag[(cpu_state.TOP + fetchdat) & 7] = 3; + if (cpu_state.abrt) + return 1; + x87_pop(); + CLOCK_CYCLES_FPU((fpu_type >= FPU_487SX) ? (x87_timings.ffree) : (x87_timings.ffree * cpu_multi)); + CONCURRENCY_CYCLES((fpu_type >= FPU_487SX) ? (x87_concurrency.ffree) : (x87_concurrency.ffree * cpu_multi)); + return 0; } -static int opFST(uint32_t fetchdat) +static int +opFST(uint32_t fetchdat) { - FP_ENTER(); - cpu_state.pc++; - ST(fetchdat & 7) = ST(0); - cpu_state.tag[(cpu_state.TOP + fetchdat) & 7] = cpu_state.tag[cpu_state.TOP & 7]; - CLOCK_CYCLES_FPU((fpu_type >= FPU_487SX) ? (x87_timings.fst) : (x87_timings.fst * cpu_multi)); - CONCURRENCY_CYCLES((fpu_type >= FPU_487SX) ? (x87_concurrency.fst) : (x87_concurrency.fst * cpu_multi)); - return 0; + FP_ENTER(); + cpu_state.pc++; + ST(fetchdat & 7) = ST(0); + cpu_state.tag[(cpu_state.TOP + fetchdat) & 7] = cpu_state.tag[cpu_state.TOP & 7]; + CLOCK_CYCLES_FPU((fpu_type >= FPU_487SX) ? (x87_timings.fst) : (x87_timings.fst * cpu_multi)); + CONCURRENCY_CYCLES((fpu_type >= FPU_487SX) ? (x87_concurrency.fst) : (x87_concurrency.fst * cpu_multi)); + return 0; } -static int opFSTP(uint32_t fetchdat) +static int +opFSTP(uint32_t fetchdat) { - FP_ENTER(); - cpu_state.pc++; - ST(fetchdat & 7) = ST(0); - cpu_state.tag[(cpu_state.TOP + fetchdat) & 7] = cpu_state.tag[cpu_state.TOP & 7]; - x87_pop(); - CLOCK_CYCLES_FPU((fpu_type >= FPU_487SX) ? (x87_timings.fst) : (x87_timings.fst * cpu_multi)); - CONCURRENCY_CYCLES((fpu_type >= FPU_487SX) ? (x87_concurrency.fst) : (x87_concurrency.fst * cpu_multi)); - return 0; + FP_ENTER(); + cpu_state.pc++; + ST(fetchdat & 7) = ST(0); + cpu_state.tag[(cpu_state.TOP + fetchdat) & 7] = cpu_state.tag[cpu_state.TOP & 7]; + x87_pop(); + CLOCK_CYCLES_FPU((fpu_type >= FPU_487SX) ? (x87_timings.fst) : (x87_timings.fst * cpu_multi)); + CONCURRENCY_CYCLES((fpu_type >= FPU_487SX) ? (x87_concurrency.fst) : (x87_concurrency.fst * cpu_multi)); + return 0; } - - - -static int FSTOR() +static int +FSTOR(void) { - uint64_t *p; - FP_ENTER(); - switch ((cr0 & 1) | (cpu_state.op32 & 0x100)) - { - case 0x000: /*16-bit real mode*/ - case 0x001: /*16-bit protected mode*/ - cpu_state.npxc = readmemw(easeg, cpu_state.eaaddr); - codegen_set_rounding_mode((cpu_state.npxc >> 10) & 3); - cpu_state.npxs = readmemw(easeg, cpu_state.eaaddr+2); - x87_settag(readmemw(easeg, cpu_state.eaaddr+4)); - cpu_state.TOP = (cpu_state.npxs >> 11) & 7; - cpu_state.eaaddr += 14; - break; - case 0x100: /*32-bit real mode*/ - case 0x101: /*32-bit protected mode*/ - cpu_state.npxc = readmemw(easeg, cpu_state.eaaddr); - codegen_set_rounding_mode((cpu_state.npxc >> 10) & 3); - cpu_state.npxs = readmemw(easeg, cpu_state.eaaddr+4); - x87_settag(readmemw(easeg, cpu_state.eaaddr+8)); - cpu_state.TOP = (cpu_state.npxs >> 11) & 7; - cpu_state.eaaddr += 28; - break; - } - x87_ld_frstor(0); cpu_state.eaaddr += 10; - x87_ld_frstor(1); cpu_state.eaaddr += 10; - x87_ld_frstor(2); cpu_state.eaaddr += 10; - x87_ld_frstor(3); cpu_state.eaaddr += 10; - x87_ld_frstor(4); cpu_state.eaaddr += 10; - x87_ld_frstor(5); cpu_state.eaaddr += 10; - x87_ld_frstor(6); cpu_state.eaaddr += 10; - x87_ld_frstor(7); - - cpu_state.ismmx = 0; - /*Horrible hack, but as PCem doesn't keep the FPU stack in 80-bit precision at all times - something like this is needed*/ - p = (uint64_t *) cpu_state.tag; + uint64_t *p; + FP_ENTER(); + switch ((cr0 & 1) | (cpu_state.op32 & 0x100)) { + case 0x000: /*16-bit real mode*/ + case 0x001: /*16-bit protected mode*/ + cpu_state.npxc = readmemw(easeg, cpu_state.eaaddr); + codegen_set_rounding_mode((cpu_state.npxc >> 10) & 3); + cpu_state.npxs = readmemw(easeg, cpu_state.eaaddr + 2); + x87_settag(readmemw(easeg, cpu_state.eaaddr + 4)); + cpu_state.TOP = (cpu_state.npxs >> 11) & 7; + cpu_state.eaaddr += 14; + break; + case 0x100: /*32-bit real mode*/ + case 0x101: /*32-bit protected mode*/ + cpu_state.npxc = readmemw(easeg, cpu_state.eaaddr); + codegen_set_rounding_mode((cpu_state.npxc >> 10) & 3); + cpu_state.npxs = readmemw(easeg, cpu_state.eaaddr + 4); + x87_settag(readmemw(easeg, cpu_state.eaaddr + 8)); + cpu_state.TOP = (cpu_state.npxs >> 11) & 7; + cpu_state.eaaddr += 28; + break; + } + x87_ld_frstor(0); + cpu_state.eaaddr += 10; + x87_ld_frstor(1); + cpu_state.eaaddr += 10; + x87_ld_frstor(2); + cpu_state.eaaddr += 10; + x87_ld_frstor(3); + cpu_state.eaaddr += 10; + x87_ld_frstor(4); + cpu_state.eaaddr += 10; + x87_ld_frstor(5); + cpu_state.eaaddr += 10; + x87_ld_frstor(6); + cpu_state.eaaddr += 10; + x87_ld_frstor(7); + + cpu_state.ismmx = 0; + /*Horrible hack, but as PCem doesn't keep the FPU stack in 80-bit precision at all times + something like this is needed*/ + p = (uint64_t *) cpu_state.tag; #ifdef USE_NEW_DYNAREC - if (cpu_state.MM_w4[0] == 0xffff && cpu_state.MM_w4[1] == 0xffff && cpu_state.MM_w4[2] == 0xffff && cpu_state.MM_w4[3] == 0xffff && - cpu_state.MM_w4[4] == 0xffff && cpu_state.MM_w4[5] == 0xffff && cpu_state.MM_w4[6] == 0xffff && cpu_state.MM_w4[7] == 0xffff && - !cpu_state.TOP && (*p == 0x0101010101010101ull)) + if (cpu_state.MM_w4[0] == 0xffff && cpu_state.MM_w4[1] == 0xffff && cpu_state.MM_w4[2] == 0xffff && cpu_state.MM_w4[3] == 0xffff && cpu_state.MM_w4[4] == 0xffff && cpu_state.MM_w4[5] == 0xffff && cpu_state.MM_w4[6] == 0xffff && cpu_state.MM_w4[7] == 0xffff && !cpu_state.TOP && (*p == 0x0101010101010101ULL)) #else - if (cpu_state.MM_w4[0] == 0xffff && cpu_state.MM_w4[1] == 0xffff && cpu_state.MM_w4[2] == 0xffff && cpu_state.MM_w4[3] == 0xffff && - cpu_state.MM_w4[4] == 0xffff && cpu_state.MM_w4[5] == 0xffff && cpu_state.MM_w4[6] == 0xffff && cpu_state.MM_w4[7] == 0xffff && - !cpu_state.TOP && !(*p)) - #endif - cpu_state.ismmx = 1; + if (cpu_state.MM_w4[0] == 0xffff && cpu_state.MM_w4[1] == 0xffff && cpu_state.MM_w4[2] == 0xffff && cpu_state.MM_w4[3] == 0xffff && cpu_state.MM_w4[4] == 0xffff && cpu_state.MM_w4[5] == 0xffff && cpu_state.MM_w4[6] == 0xffff && cpu_state.MM_w4[7] == 0xffff && !cpu_state.TOP && !(*p)) +#endif + cpu_state.ismmx = 1; - CLOCK_CYCLES_FPU((fpu_type >= FPU_487SX) ? (x87_timings.frstor) : (x87_timings.frstor * cpu_multi)); - CONCURRENCY_CYCLES((fpu_type >= FPU_487SX) ? (x87_concurrency.frstor) : (x87_concurrency.frstor * cpu_multi)); - return cpu_state.abrt; + CLOCK_CYCLES_FPU((fpu_type >= FPU_487SX) ? (x87_timings.frstor) : (x87_timings.frstor * cpu_multi)); + CONCURRENCY_CYCLES((fpu_type >= FPU_487SX) ? (x87_concurrency.frstor) : (x87_concurrency.frstor * cpu_multi)); + return cpu_state.abrt; } -static int opFSTOR_a16(uint32_t fetchdat) +static int +opFSTOR_a16(uint32_t fetchdat) { - FP_ENTER(); - fetch_ea_16(fetchdat); - SEG_CHECK_READ(cpu_state.ea_seg); - FSTOR(); - return cpu_state.abrt; + FP_ENTER(); + fetch_ea_16(fetchdat); + SEG_CHECK_READ(cpu_state.ea_seg); + FSTOR(); + return cpu_state.abrt; } #ifndef FPU_8087 -static int opFSTOR_a32(uint32_t fetchdat) +static int +opFSTOR_a32(uint32_t fetchdat) { - FP_ENTER(); - fetch_ea_32(fetchdat); - SEG_CHECK_READ(cpu_state.ea_seg); - FSTOR(); - return cpu_state.abrt; + FP_ENTER(); + fetch_ea_32(fetchdat); + SEG_CHECK_READ(cpu_state.ea_seg); + FSTOR(); + return cpu_state.abrt; } #endif -static int FSAVE() +static int +FSAVE(void) { - uint64_t *p; + uint64_t *p; - FP_ENTER(); - cpu_state.npxs = (cpu_state.npxs & ~(7 << 11)) | ((cpu_state.TOP & 7) << 11); + FP_ENTER(); + cpu_state.npxs = (cpu_state.npxs & ~(7 << 11)) | ((cpu_state.TOP & 7) << 11); - switch ((cr0 & 1) | (cpu_state.op32 & 0x100)) - { - case 0x000: /*16-bit real mode*/ - writememw(easeg,cpu_state.eaaddr,cpu_state.npxc); - writememw(easeg,cpu_state.eaaddr+2,cpu_state.npxs); - writememw(easeg,cpu_state.eaaddr+4,x87_gettag()); - writememw(easeg,cpu_state.eaaddr+6,x87_pc_off); - writememw(easeg,cpu_state.eaaddr+10,x87_op_off); - cpu_state.eaaddr+=14; - if (cpu_state.ismmx) - { - x87_stmmx(cpu_state.MM[0]); cpu_state.eaaddr+=10; - x87_stmmx(cpu_state.MM[1]); cpu_state.eaaddr+=10; - x87_stmmx(cpu_state.MM[2]); cpu_state.eaaddr+=10; - x87_stmmx(cpu_state.MM[3]); cpu_state.eaaddr+=10; - x87_stmmx(cpu_state.MM[4]); cpu_state.eaaddr+=10; - x87_stmmx(cpu_state.MM[5]); cpu_state.eaaddr+=10; - x87_stmmx(cpu_state.MM[6]); cpu_state.eaaddr+=10; - x87_stmmx(cpu_state.MM[7]); - } - else - { - x87_st_fsave(0); cpu_state.eaaddr+=10; - x87_st_fsave(1); cpu_state.eaaddr+=10; - x87_st_fsave(2); cpu_state.eaaddr+=10; - x87_st_fsave(3); cpu_state.eaaddr+=10; - x87_st_fsave(4); cpu_state.eaaddr+=10; - x87_st_fsave(5); cpu_state.eaaddr+=10; - x87_st_fsave(6); cpu_state.eaaddr+=10; - x87_st_fsave(7); - } - break; - case 0x001: /*16-bit protected mode*/ - writememw(easeg,cpu_state.eaaddr,cpu_state.npxc); - writememw(easeg,cpu_state.eaaddr+2,cpu_state.npxs); - writememw(easeg,cpu_state.eaaddr+4,x87_gettag()); - writememw(easeg,cpu_state.eaaddr+6,x87_pc_off); - writememw(easeg,cpu_state.eaaddr+8,x87_pc_seg); - writememw(easeg,cpu_state.eaaddr+10,x87_op_off); - writememw(easeg,cpu_state.eaaddr+12,x87_op_seg); - cpu_state.eaaddr+=14; - if (cpu_state.ismmx) - { - x87_stmmx(cpu_state.MM[0]); cpu_state.eaaddr+=10; - x87_stmmx(cpu_state.MM[1]); cpu_state.eaaddr+=10; - x87_stmmx(cpu_state.MM[2]); cpu_state.eaaddr+=10; - x87_stmmx(cpu_state.MM[3]); cpu_state.eaaddr+=10; - x87_stmmx(cpu_state.MM[4]); cpu_state.eaaddr+=10; - x87_stmmx(cpu_state.MM[5]); cpu_state.eaaddr+=10; - x87_stmmx(cpu_state.MM[6]); cpu_state.eaaddr+=10; - x87_stmmx(cpu_state.MM[7]); - } - else - { - x87_st_fsave(0); cpu_state.eaaddr+=10; - x87_st_fsave(1); cpu_state.eaaddr+=10; - x87_st_fsave(2); cpu_state.eaaddr+=10; - x87_st_fsave(3); cpu_state.eaaddr+=10; - x87_st_fsave(4); cpu_state.eaaddr+=10; - x87_st_fsave(5); cpu_state.eaaddr+=10; - x87_st_fsave(6); cpu_state.eaaddr+=10; - x87_st_fsave(7); - } - break; - case 0x100: /*32-bit real mode*/ - writememw(easeg,cpu_state.eaaddr,cpu_state.npxc); - writememw(easeg,cpu_state.eaaddr+4,cpu_state.npxs); - writememw(easeg,cpu_state.eaaddr+8,x87_gettag()); - writememw(easeg,cpu_state.eaaddr+12,x87_pc_off); - writememw(easeg,cpu_state.eaaddr+20,x87_op_off); - writememl(easeg,cpu_state.eaaddr+24,(x87_op_off>>16)<<12); - cpu_state.eaaddr+=28; - if (cpu_state.ismmx) - { - x87_stmmx(cpu_state.MM[0]); cpu_state.eaaddr+=10; - x87_stmmx(cpu_state.MM[1]); cpu_state.eaaddr+=10; - x87_stmmx(cpu_state.MM[2]); cpu_state.eaaddr+=10; - x87_stmmx(cpu_state.MM[3]); cpu_state.eaaddr+=10; - x87_stmmx(cpu_state.MM[4]); cpu_state.eaaddr+=10; - x87_stmmx(cpu_state.MM[5]); cpu_state.eaaddr+=10; - x87_stmmx(cpu_state.MM[6]); cpu_state.eaaddr+=10; - x87_stmmx(cpu_state.MM[7]); - } - else - { - x87_st_fsave(0); cpu_state.eaaddr+=10; - x87_st_fsave(1); cpu_state.eaaddr+=10; - x87_st_fsave(2); cpu_state.eaaddr+=10; - x87_st_fsave(3); cpu_state.eaaddr+=10; - x87_st_fsave(4); cpu_state.eaaddr+=10; - x87_st_fsave(5); cpu_state.eaaddr+=10; - x87_st_fsave(6); cpu_state.eaaddr+=10; - x87_st_fsave(7); - } - break; - case 0x101: /*32-bit protected mode*/ - writememw(easeg,cpu_state.eaaddr,cpu_state.npxc); - writememw(easeg,cpu_state.eaaddr+4,cpu_state.npxs); - writememw(easeg,cpu_state.eaaddr+8,x87_gettag()); - writememl(easeg,cpu_state.eaaddr+12,x87_pc_off); - writememl(easeg,cpu_state.eaaddr+16,x87_pc_seg); - writememl(easeg,cpu_state.eaaddr+20,x87_op_off); - writememl(easeg,cpu_state.eaaddr+24,x87_op_seg); - cpu_state.eaaddr+=28; - if (cpu_state.ismmx) - { - x87_stmmx(cpu_state.MM[0]); cpu_state.eaaddr+=10; - x87_stmmx(cpu_state.MM[1]); cpu_state.eaaddr+=10; - x87_stmmx(cpu_state.MM[2]); cpu_state.eaaddr+=10; - x87_stmmx(cpu_state.MM[3]); cpu_state.eaaddr+=10; - x87_stmmx(cpu_state.MM[4]); cpu_state.eaaddr+=10; - x87_stmmx(cpu_state.MM[5]); cpu_state.eaaddr+=10; - x87_stmmx(cpu_state.MM[6]); cpu_state.eaaddr+=10; - x87_stmmx(cpu_state.MM[7]); - } - else - { - x87_st_fsave(0); cpu_state.eaaddr+=10; - x87_st_fsave(1); cpu_state.eaaddr+=10; - x87_st_fsave(2); cpu_state.eaaddr+=10; - x87_st_fsave(3); cpu_state.eaaddr+=10; - x87_st_fsave(4); cpu_state.eaaddr+=10; - x87_st_fsave(5); cpu_state.eaaddr+=10; - x87_st_fsave(6); cpu_state.eaaddr+=10; - x87_st_fsave(7); - } - break; - } + switch ((cr0 & 1) | (cpu_state.op32 & 0x100)) { + case 0x000: /*16-bit real mode*/ + writememw(easeg, cpu_state.eaaddr, cpu_state.npxc); + writememw(easeg, cpu_state.eaaddr + 2, cpu_state.npxs); + writememw(easeg, cpu_state.eaaddr + 4, x87_gettag()); + writememw(easeg, cpu_state.eaaddr + 6, x87_pc_off); + writememw(easeg, cpu_state.eaaddr + 10, x87_op_off); + cpu_state.eaaddr += 14; + if (cpu_state.ismmx) { + x87_stmmx(cpu_state.MM[0]); + cpu_state.eaaddr += 10; + x87_stmmx(cpu_state.MM[1]); + cpu_state.eaaddr += 10; + x87_stmmx(cpu_state.MM[2]); + cpu_state.eaaddr += 10; + x87_stmmx(cpu_state.MM[3]); + cpu_state.eaaddr += 10; + x87_stmmx(cpu_state.MM[4]); + cpu_state.eaaddr += 10; + x87_stmmx(cpu_state.MM[5]); + cpu_state.eaaddr += 10; + x87_stmmx(cpu_state.MM[6]); + cpu_state.eaaddr += 10; + x87_stmmx(cpu_state.MM[7]); + } else { + x87_st_fsave(0); + cpu_state.eaaddr += 10; + x87_st_fsave(1); + cpu_state.eaaddr += 10; + x87_st_fsave(2); + cpu_state.eaaddr += 10; + x87_st_fsave(3); + cpu_state.eaaddr += 10; + x87_st_fsave(4); + cpu_state.eaaddr += 10; + x87_st_fsave(5); + cpu_state.eaaddr += 10; + x87_st_fsave(6); + cpu_state.eaaddr += 10; + x87_st_fsave(7); + } + break; + case 0x001: /*16-bit protected mode*/ + writememw(easeg, cpu_state.eaaddr, cpu_state.npxc); + writememw(easeg, cpu_state.eaaddr + 2, cpu_state.npxs); + writememw(easeg, cpu_state.eaaddr + 4, x87_gettag()); + writememw(easeg, cpu_state.eaaddr + 6, x87_pc_off); + writememw(easeg, cpu_state.eaaddr + 8, x87_pc_seg); + writememw(easeg, cpu_state.eaaddr + 10, x87_op_off); + writememw(easeg, cpu_state.eaaddr + 12, x87_op_seg); + cpu_state.eaaddr += 14; + if (cpu_state.ismmx) { + x87_stmmx(cpu_state.MM[0]); + cpu_state.eaaddr += 10; + x87_stmmx(cpu_state.MM[1]); + cpu_state.eaaddr += 10; + x87_stmmx(cpu_state.MM[2]); + cpu_state.eaaddr += 10; + x87_stmmx(cpu_state.MM[3]); + cpu_state.eaaddr += 10; + x87_stmmx(cpu_state.MM[4]); + cpu_state.eaaddr += 10; + x87_stmmx(cpu_state.MM[5]); + cpu_state.eaaddr += 10; + x87_stmmx(cpu_state.MM[6]); + cpu_state.eaaddr += 10; + x87_stmmx(cpu_state.MM[7]); + } else { + x87_st_fsave(0); + cpu_state.eaaddr += 10; + x87_st_fsave(1); + cpu_state.eaaddr += 10; + x87_st_fsave(2); + cpu_state.eaaddr += 10; + x87_st_fsave(3); + cpu_state.eaaddr += 10; + x87_st_fsave(4); + cpu_state.eaaddr += 10; + x87_st_fsave(5); + cpu_state.eaaddr += 10; + x87_st_fsave(6); + cpu_state.eaaddr += 10; + x87_st_fsave(7); + } + break; + case 0x100: /*32-bit real mode*/ + writememw(easeg, cpu_state.eaaddr, cpu_state.npxc); + writememw(easeg, cpu_state.eaaddr + 4, cpu_state.npxs); + writememw(easeg, cpu_state.eaaddr + 8, x87_gettag()); + writememw(easeg, cpu_state.eaaddr + 12, x87_pc_off); + writememw(easeg, cpu_state.eaaddr + 20, x87_op_off); + writememl(easeg, cpu_state.eaaddr + 24, (x87_op_off >> 16) << 12); + cpu_state.eaaddr += 28; + if (cpu_state.ismmx) { + x87_stmmx(cpu_state.MM[0]); + cpu_state.eaaddr += 10; + x87_stmmx(cpu_state.MM[1]); + cpu_state.eaaddr += 10; + x87_stmmx(cpu_state.MM[2]); + cpu_state.eaaddr += 10; + x87_stmmx(cpu_state.MM[3]); + cpu_state.eaaddr += 10; + x87_stmmx(cpu_state.MM[4]); + cpu_state.eaaddr += 10; + x87_stmmx(cpu_state.MM[5]); + cpu_state.eaaddr += 10; + x87_stmmx(cpu_state.MM[6]); + cpu_state.eaaddr += 10; + x87_stmmx(cpu_state.MM[7]); + } else { + x87_st_fsave(0); + cpu_state.eaaddr += 10; + x87_st_fsave(1); + cpu_state.eaaddr += 10; + x87_st_fsave(2); + cpu_state.eaaddr += 10; + x87_st_fsave(3); + cpu_state.eaaddr += 10; + x87_st_fsave(4); + cpu_state.eaaddr += 10; + x87_st_fsave(5); + cpu_state.eaaddr += 10; + x87_st_fsave(6); + cpu_state.eaaddr += 10; + x87_st_fsave(7); + } + break; + case 0x101: /*32-bit protected mode*/ + writememw(easeg, cpu_state.eaaddr, cpu_state.npxc); + writememw(easeg, cpu_state.eaaddr + 4, cpu_state.npxs); + writememw(easeg, cpu_state.eaaddr + 8, x87_gettag()); + writememl(easeg, cpu_state.eaaddr + 12, x87_pc_off); + writememl(easeg, cpu_state.eaaddr + 16, x87_pc_seg); + writememl(easeg, cpu_state.eaaddr + 20, x87_op_off); + writememl(easeg, cpu_state.eaaddr + 24, x87_op_seg); + cpu_state.eaaddr += 28; + if (cpu_state.ismmx) { + x87_stmmx(cpu_state.MM[0]); + cpu_state.eaaddr += 10; + x87_stmmx(cpu_state.MM[1]); + cpu_state.eaaddr += 10; + x87_stmmx(cpu_state.MM[2]); + cpu_state.eaaddr += 10; + x87_stmmx(cpu_state.MM[3]); + cpu_state.eaaddr += 10; + x87_stmmx(cpu_state.MM[4]); + cpu_state.eaaddr += 10; + x87_stmmx(cpu_state.MM[5]); + cpu_state.eaaddr += 10; + x87_stmmx(cpu_state.MM[6]); + cpu_state.eaaddr += 10; + x87_stmmx(cpu_state.MM[7]); + } else { + x87_st_fsave(0); + cpu_state.eaaddr += 10; + x87_st_fsave(1); + cpu_state.eaaddr += 10; + x87_st_fsave(2); + cpu_state.eaaddr += 10; + x87_st_fsave(3); + cpu_state.eaaddr += 10; + x87_st_fsave(4); + cpu_state.eaaddr += 10; + x87_st_fsave(5); + cpu_state.eaaddr += 10; + x87_st_fsave(6); + cpu_state.eaaddr += 10; + x87_st_fsave(7); + } + break; + } - cpu_state.npxc = 0x37F; - codegen_set_rounding_mode(X87_ROUNDING_NEAREST); - cpu_state.npxs = 0; - p = (uint64_t *)cpu_state.tag; + cpu_state.npxc = 0x37F; + codegen_set_rounding_mode(X87_ROUNDING_NEAREST); + cpu_state.npxs = 0; + p = (uint64_t *) cpu_state.tag; #ifdef USE_NEW_DYNAREC - *p = 0; + *p = 0; #else - *p = 0x0303030303030303ll; + *p = 0x0303030303030303LL; #endif - cpu_state.TOP = 0; - cpu_state.ismmx = 0; + cpu_state.TOP = 0; + cpu_state.ismmx = 0; - CLOCK_CYCLES_FPU((fpu_type >= FPU_487SX) ? (x87_timings.fsave) : (x87_timings.fsave * cpu_multi)); - CONCURRENCY_CYCLES((fpu_type >= FPU_487SX) ? (x87_concurrency.fsave) : (x87_concurrency.fsave * cpu_multi)); - return cpu_state.abrt; + CLOCK_CYCLES_FPU((fpu_type >= FPU_487SX) ? (x87_timings.fsave) : (x87_timings.fsave * cpu_multi)); + CONCURRENCY_CYCLES((fpu_type >= FPU_487SX) ? (x87_concurrency.fsave) : (x87_concurrency.fsave * cpu_multi)); + return cpu_state.abrt; } -static int opFSAVE_a16(uint32_t fetchdat) +static int +opFSAVE_a16(uint32_t fetchdat) { - FP_ENTER(); - fetch_ea_16(fetchdat); - SEG_CHECK_WRITE(cpu_state.ea_seg); - FSAVE(); - return cpu_state.abrt; + FP_ENTER(); + fetch_ea_16(fetchdat); + SEG_CHECK_WRITE(cpu_state.ea_seg); + FSAVE(); + return cpu_state.abrt; } #ifndef FPU_8087 -static int opFSAVE_a32(uint32_t fetchdat) +static int +opFSAVE_a32(uint32_t fetchdat) { - FP_ENTER(); - fetch_ea_32(fetchdat); - SEG_CHECK_WRITE(cpu_state.ea_seg); - FSAVE(); - return cpu_state.abrt; + FP_ENTER(); + fetch_ea_32(fetchdat); + SEG_CHECK_WRITE(cpu_state.ea_seg); + FSAVE(); + return cpu_state.abrt; } #endif -static int opFSTSW_a16(uint32_t fetchdat) +static int +opFSTSW_a16(uint32_t fetchdat) { - FP_ENTER(); - fetch_ea_16(fetchdat); - SEG_CHECK_WRITE(cpu_state.ea_seg); - seteaw((cpu_state.npxs & 0xC7FF) | ((cpu_state.TOP & 7) << 11)); - CLOCK_CYCLES_FPU((fpu_type >= FPU_487SX) ? (x87_timings.fstcw_sw) : (x87_timings.fstcw_sw * cpu_multi)); - CONCURRENCY_CYCLES((fpu_type >= FPU_487SX) ? (x87_concurrency.fstcw_sw) : (x87_concurrency.fstcw_sw * cpu_multi)); - return cpu_state.abrt; + FP_ENTER(); + fetch_ea_16(fetchdat); + SEG_CHECK_WRITE(cpu_state.ea_seg); + seteaw((cpu_state.npxs & 0xC7FF) | ((cpu_state.TOP & 7) << 11)); + CLOCK_CYCLES_FPU((fpu_type >= FPU_487SX) ? (x87_timings.fstcw_sw) : (x87_timings.fstcw_sw * cpu_multi)); + CONCURRENCY_CYCLES((fpu_type >= FPU_487SX) ? (x87_concurrency.fstcw_sw) : (x87_concurrency.fstcw_sw * cpu_multi)); + return cpu_state.abrt; } #ifndef FPU_8087 -static int opFSTSW_a32(uint32_t fetchdat) +static int +opFSTSW_a32(uint32_t fetchdat) { - FP_ENTER(); - fetch_ea_32(fetchdat); - SEG_CHECK_WRITE(cpu_state.ea_seg); - seteaw((cpu_state.npxs & 0xC7FF) | ((cpu_state.TOP & 7) << 11)); - CLOCK_CYCLES_FPU((fpu_type >= FPU_487SX) ? (x87_timings.fstcw_sw) : (x87_timings.fstcw_sw * cpu_multi)); - CONCURRENCY_CYCLES((fpu_type >= FPU_487SX) ? (x87_concurrency.fstcw_sw) : (x87_concurrency.fstcw_sw * cpu_multi)); - return cpu_state.abrt; + FP_ENTER(); + fetch_ea_32(fetchdat); + SEG_CHECK_WRITE(cpu_state.ea_seg); + seteaw((cpu_state.npxs & 0xC7FF) | ((cpu_state.TOP & 7) << 11)); + CLOCK_CYCLES_FPU((fpu_type >= FPU_487SX) ? (x87_timings.fstcw_sw) : (x87_timings.fstcw_sw * cpu_multi)); + CONCURRENCY_CYCLES((fpu_type >= FPU_487SX) ? (x87_concurrency.fstcw_sw) : (x87_concurrency.fstcw_sw * cpu_multi)); + return cpu_state.abrt; } #endif - -static int opFLD(uint32_t fetchdat) +static int +opFLD(uint32_t fetchdat) { - int old_tag; - uint64_t old_i64; - - FP_ENTER(); - cpu_state.pc++; - old_tag = cpu_state.tag[(cpu_state.TOP + fetchdat) & 7]; - old_i64 = cpu_state.MM[(cpu_state.TOP + fetchdat) & 7].q; - x87_push(ST(fetchdat&7)); - cpu_state.tag[cpu_state.TOP&7] = old_tag; - cpu_state.MM[cpu_state.TOP&7].q = old_i64; - CLOCK_CYCLES_FPU((fpu_type >= FPU_487SX) ? (x87_timings.fld) : (x87_timings.fld * cpu_multi)); - CONCURRENCY_CYCLES((fpu_type >= FPU_487SX) ? (x87_concurrency.fld) : (x87_concurrency.fld * cpu_multi)); - return 0; + int old_tag; + uint64_t old_i64; + + FP_ENTER(); + cpu_state.pc++; + old_tag = cpu_state.tag[(cpu_state.TOP + fetchdat) & 7]; + old_i64 = cpu_state.MM[(cpu_state.TOP + fetchdat) & 7].q; + x87_push(ST(fetchdat & 7)); + cpu_state.tag[cpu_state.TOP & 7] = old_tag; + cpu_state.MM[cpu_state.TOP & 7].q = old_i64; + CLOCK_CYCLES_FPU((fpu_type >= FPU_487SX) ? (x87_timings.fld) : (x87_timings.fld * cpu_multi)); + CONCURRENCY_CYCLES((fpu_type >= FPU_487SX) ? (x87_concurrency.fld) : (x87_concurrency.fld * cpu_multi)); + return 0; } -static int opFXCH(uint32_t fetchdat) +static int +opFXCH(uint32_t fetchdat) { - double td; - uint8_t old_tag; - uint64_t old_i64; - FP_ENTER(); - cpu_state.pc++; - td = ST(0); - ST(0) = ST(fetchdat&7); - ST(fetchdat&7) = td; - old_tag = cpu_state.tag[cpu_state.TOP&7]; - cpu_state.tag[cpu_state.TOP&7] = cpu_state.tag[(cpu_state.TOP + fetchdat) & 7]; - cpu_state.tag[(cpu_state.TOP + fetchdat) & 7] = old_tag; - old_i64 = cpu_state.MM[cpu_state.TOP&7].q; - cpu_state.MM[cpu_state.TOP&7].q = cpu_state.MM[(cpu_state.TOP + fetchdat) & 7].q; - cpu_state.MM[(cpu_state.TOP + fetchdat) & 7].q = old_i64; - - CLOCK_CYCLES_FPU((fpu_type >= FPU_487SX) ? (x87_timings.fxch) : (x87_timings.fxch * cpu_multi)); - CONCURRENCY_CYCLES((fpu_type >= FPU_487SX) ? (x87_concurrency.fxch) : (x87_concurrency.fxch * cpu_multi)); - return 0; + double td; + uint8_t old_tag; + uint64_t old_i64; + FP_ENTER(); + cpu_state.pc++; + td = ST(0); + ST(0) = ST(fetchdat & 7); + ST(fetchdat & 7) = td; + old_tag = cpu_state.tag[cpu_state.TOP & 7]; + cpu_state.tag[cpu_state.TOP & 7] = cpu_state.tag[(cpu_state.TOP + fetchdat) & 7]; + cpu_state.tag[(cpu_state.TOP + fetchdat) & 7] = old_tag; + old_i64 = cpu_state.MM[cpu_state.TOP & 7].q; + cpu_state.MM[cpu_state.TOP & 7].q = cpu_state.MM[(cpu_state.TOP + fetchdat) & 7].q; + cpu_state.MM[(cpu_state.TOP + fetchdat) & 7].q = old_i64; + + CLOCK_CYCLES_FPU((fpu_type >= FPU_487SX) ? (x87_timings.fxch) : (x87_timings.fxch * cpu_multi)); + CONCURRENCY_CYCLES((fpu_type >= FPU_487SX) ? (x87_concurrency.fxch) : (x87_concurrency.fxch * cpu_multi)); + return 0; } -static int opFCHS(uint32_t fetchdat) +static int +opFCHS(uint32_t fetchdat) { - FP_ENTER(); - cpu_state.pc++; - ST(0) = -ST(0); - FP_TAG_VALID; - CLOCK_CYCLES_FPU((fpu_type >= FPU_487SX) ? (x87_timings.fchs) : (x87_timings.fchs * cpu_multi)); - CONCURRENCY_CYCLES((fpu_type >= FPU_487SX) ? (x87_concurrency.fchs) : (x87_concurrency.fchs * cpu_multi)); - return 0; + FP_ENTER(); + cpu_state.pc++; + ST(0) = -ST(0); + FP_TAG_VALID; + CLOCK_CYCLES_FPU((fpu_type >= FPU_487SX) ? (x87_timings.fchs) : (x87_timings.fchs * cpu_multi)); + CONCURRENCY_CYCLES((fpu_type >= FPU_487SX) ? (x87_concurrency.fchs) : (x87_concurrency.fchs * cpu_multi)); + return 0; } -static int opFABS(uint32_t fetchdat) +static int +opFABS(uint32_t fetchdat) { - FP_ENTER(); - cpu_state.pc++; - ST(0) = fabs(ST(0)); - FP_TAG_VALID; - CLOCK_CYCLES_FPU((fpu_type >= FPU_487SX) ? (x87_timings.fabs) : (x87_timings.fabs * cpu_multi)); - CONCURRENCY_CYCLES((fpu_type >= FPU_487SX) ? (x87_concurrency.fabs) : (x87_concurrency.fabs * cpu_multi)); - return 0; + FP_ENTER(); + cpu_state.pc++; + ST(0) = fabs(ST(0)); + FP_TAG_VALID; + CLOCK_CYCLES_FPU((fpu_type >= FPU_487SX) ? (x87_timings.fabs) : (x87_timings.fabs * cpu_multi)); + CONCURRENCY_CYCLES((fpu_type >= FPU_487SX) ? (x87_concurrency.fabs) : (x87_concurrency.fabs * cpu_multi)); + return 0; } -static int opFTST(uint32_t fetchdat) +static int +opFTST(uint32_t fetchdat) { - FP_ENTER(); - cpu_state.pc++; - cpu_state.npxs &= ~(C0|C2|C3); - if (ST(0) == 0.0) cpu_state.npxs |= C3; - else if (ST(0) < 0.0) cpu_state.npxs |= C0; - CLOCK_CYCLES_FPU((fpu_type >= FPU_487SX) ? (x87_timings.ftst) : (x87_timings.ftst * cpu_multi)); - CONCURRENCY_CYCLES((fpu_type >= FPU_487SX) ? (x87_concurrency.ftst) : (x87_concurrency.ftst * cpu_multi)); - return 0; + FP_ENTER(); + cpu_state.pc++; + cpu_state.npxs &= ~(C0 | C2 | C3); + if (ST(0) == 0.0) + cpu_state.npxs |= C3; + else if (ST(0) < 0.0) + cpu_state.npxs |= C0; + CLOCK_CYCLES_FPU((fpu_type >= FPU_487SX) ? (x87_timings.ftst) : (x87_timings.ftst * cpu_multi)); + CONCURRENCY_CYCLES((fpu_type >= FPU_487SX) ? (x87_concurrency.ftst) : (x87_concurrency.ftst * cpu_multi)); + return 0; } -static int opFXAM(uint32_t fetchdat) +static int +opFXAM(uint32_t fetchdat) { - FP_ENTER(); - cpu_state.pc++; - cpu_state.npxs &= ~(C0|C1|C2|C3); + FP_ENTER(); + cpu_state.pc++; + cpu_state.npxs &= ~(C0 | C1 | C2 | C3); #ifdef USE_NEW_DYNAREC - if (cpu_state.tag[cpu_state.TOP&7] == TAG_EMPTY) cpu_state.npxs |= (C0|C3); + if (cpu_state.tag[cpu_state.TOP & 7] == TAG_EMPTY) + cpu_state.npxs |= (C0 | C3); #else - if (cpu_state.tag[cpu_state.TOP&7] == 3) cpu_state.npxs |= (C0|C3); + if (cpu_state.tag[cpu_state.TOP & 7] == 3) + cpu_state.npxs |= (C0 | C3); #endif - else if (ST(0) == 0.0) cpu_state.npxs |= C3; - else cpu_state.npxs |= C2; - if (ST(0) < 0.0) cpu_state.npxs |= C1; - CLOCK_CYCLES_FPU((fpu_type >= FPU_487SX) ? (x87_timings.fxam) : (x87_timings.fxam * cpu_multi)); - CONCURRENCY_CYCLES((fpu_type >= FPU_487SX) ? (x87_concurrency.fxam) : (x87_concurrency.fxam * cpu_multi)); - return 0; + else if (ST(0) == 0.0) + cpu_state.npxs |= C3; + else + cpu_state.npxs |= C2; + if (ST(0) < 0.0) + cpu_state.npxs |= C1; + CLOCK_CYCLES_FPU((fpu_type >= FPU_487SX) ? (x87_timings.fxam) : (x87_timings.fxam * cpu_multi)); + CONCURRENCY_CYCLES((fpu_type >= FPU_487SX) ? (x87_concurrency.fxam) : (x87_concurrency.fxam * cpu_multi)); + return 0; } -static int opFLD1(uint32_t fetchdat) +static int +opFLD1(uint32_t fetchdat) { - FP_ENTER(); - cpu_state.pc++; - x87_push(1.0); - CLOCK_CYCLES_FPU((fpu_type >= FPU_487SX) ? (x87_timings.fld_z1) : (x87_timings.fld_z1 * cpu_multi)); - CONCURRENCY_CYCLES((fpu_type >= FPU_487SX) ? (x87_concurrency.fld_z1) : (x87_concurrency.fld_z1 * cpu_multi)); - return 0; + FP_ENTER(); + cpu_state.pc++; + x87_push(1.0); + CLOCK_CYCLES_FPU((fpu_type >= FPU_487SX) ? (x87_timings.fld_z1) : (x87_timings.fld_z1 * cpu_multi)); + CONCURRENCY_CYCLES((fpu_type >= FPU_487SX) ? (x87_concurrency.fld_z1) : (x87_concurrency.fld_z1 * cpu_multi)); + return 0; } -static int opFLDL2T(uint32_t fetchdat) +static int +opFLDL2T(uint32_t fetchdat) { - FP_ENTER(); - cpu_state.pc++; - x87_push(3.3219280948873623); - CLOCK_CYCLES_FPU((fpu_type >= FPU_487SX) ? (x87_timings.fld_const) : (x87_timings.fld_const * cpu_multi)); - CONCURRENCY_CYCLES((fpu_type >= FPU_487SX) ? (x87_concurrency.fld_const) : (x87_concurrency.fld_const * cpu_multi)); - return 0; + FP_ENTER(); + cpu_state.pc++; + x87_push(3.3219280948873623); + CLOCK_CYCLES_FPU((fpu_type >= FPU_487SX) ? (x87_timings.fld_const) : (x87_timings.fld_const * cpu_multi)); + CONCURRENCY_CYCLES((fpu_type >= FPU_487SX) ? (x87_concurrency.fld_const) : (x87_concurrency.fld_const * cpu_multi)); + return 0; } -static int opFLDL2E(uint32_t fetchdat) +static int +opFLDL2E(uint32_t fetchdat) { - FP_ENTER(); - cpu_state.pc++; - x87_push(1.4426950408889634); - CLOCK_CYCLES_FPU((fpu_type >= FPU_487SX) ? (x87_timings.fld_const) : (x87_timings.fld_const * cpu_multi)); - CONCURRENCY_CYCLES((fpu_type >= FPU_487SX) ? (x87_concurrency.fld_const) : (x87_concurrency.fld_const * cpu_multi)); - return 0; + FP_ENTER(); + cpu_state.pc++; + x87_push(1.4426950408889634); + CLOCK_CYCLES_FPU((fpu_type >= FPU_487SX) ? (x87_timings.fld_const) : (x87_timings.fld_const * cpu_multi)); + CONCURRENCY_CYCLES((fpu_type >= FPU_487SX) ? (x87_concurrency.fld_const) : (x87_concurrency.fld_const * cpu_multi)); + return 0; } -static int opFLDPI(uint32_t fetchdat) +static int +opFLDPI(uint32_t fetchdat) { - FP_ENTER(); - cpu_state.pc++; - x87_push(3.141592653589793); - CLOCK_CYCLES_FPU((fpu_type >= FPU_487SX) ? (x87_timings.fld_const) : (x87_timings.fld_const * cpu_multi)); - CONCURRENCY_CYCLES((fpu_type >= FPU_487SX) ? (x87_concurrency.fld_const) : (x87_concurrency.fld_const * cpu_multi)); - return 0; + FP_ENTER(); + cpu_state.pc++; + x87_push(3.141592653589793); + CLOCK_CYCLES_FPU((fpu_type >= FPU_487SX) ? (x87_timings.fld_const) : (x87_timings.fld_const * cpu_multi)); + CONCURRENCY_CYCLES((fpu_type >= FPU_487SX) ? (x87_concurrency.fld_const) : (x87_concurrency.fld_const * cpu_multi)); + return 0; } -static int opFLDEG2(uint32_t fetchdat) +static int +opFLDEG2(uint32_t fetchdat) { - FP_ENTER(); - cpu_state.pc++; - x87_push(0.3010299956639812); - CLOCK_CYCLES_FPU((fpu_type >= FPU_487SX) ? (x87_timings.fld_const) : (x87_timings.fld_const * cpu_multi)); - CONCURRENCY_CYCLES((fpu_type >= FPU_487SX) ? (x87_concurrency.fld_const) : (x87_concurrency.fld_const * cpu_multi)); - return 0; + FP_ENTER(); + cpu_state.pc++; + x87_push(0.3010299956639812); + CLOCK_CYCLES_FPU((fpu_type >= FPU_487SX) ? (x87_timings.fld_const) : (x87_timings.fld_const * cpu_multi)); + CONCURRENCY_CYCLES((fpu_type >= FPU_487SX) ? (x87_concurrency.fld_const) : (x87_concurrency.fld_const * cpu_multi)); + return 0; } -static int opFLDLN2(uint32_t fetchdat) +static int +opFLDLN2(uint32_t fetchdat) { - FP_ENTER(); - cpu_state.pc++; - x87_push_u64(0x3fe62e42fefa39f0ull); - CLOCK_CYCLES_FPU((fpu_type >= FPU_487SX) ? (x87_timings.fld_const) : (x87_timings.fld_const * cpu_multi)); - CONCURRENCY_CYCLES((fpu_type >= FPU_487SX) ? (x87_concurrency.fld_const) : (x87_concurrency.fld_const * cpu_multi)); - return 0; -} - -static int opFLDZ(uint32_t fetchdat) -{ - FP_ENTER(); - cpu_state.pc++; - x87_push(0.0); - FP_TAG_VALID; - CLOCK_CYCLES_FPU((fpu_type >= FPU_487SX) ? (x87_timings.fld_z1) : (x87_timings.fld_z1 * cpu_multi)); - CONCURRENCY_CYCLES((fpu_type >= FPU_487SX) ? (x87_concurrency.fld_z1) : (x87_concurrency.fld_z1 * cpu_multi)); - return 0; + FP_ENTER(); + cpu_state.pc++; + x87_push_u64(0x3fe62e42fefa39f0ULL); + CLOCK_CYCLES_FPU((fpu_type >= FPU_487SX) ? (x87_timings.fld_const) : (x87_timings.fld_const * cpu_multi)); + CONCURRENCY_CYCLES((fpu_type >= FPU_487SX) ? (x87_concurrency.fld_const) : (x87_concurrency.fld_const * cpu_multi)); + return 0; } -static int opF2XM1(uint32_t fetchdat) +static int +opFLDZ(uint32_t fetchdat) { - FP_ENTER(); - cpu_state.pc++; - ST(0) = pow(2.0, ST(0)) - 1.0; - FP_TAG_VALID; - CLOCK_CYCLES_FPU((fpu_type >= FPU_487SX) ? (x87_timings.f2xm1) : (x87_timings.f2xm1 * cpu_multi)); - CONCURRENCY_CYCLES((fpu_type >= FPU_487SX) ? (x87_concurrency.f2xm1) : (x87_concurrency.f2xm1 * cpu_multi)); - return 0; + FP_ENTER(); + cpu_state.pc++; + x87_push(0.0); + FP_TAG_VALID; + CLOCK_CYCLES_FPU((fpu_type >= FPU_487SX) ? (x87_timings.fld_z1) : (x87_timings.fld_z1 * cpu_multi)); + CONCURRENCY_CYCLES((fpu_type >= FPU_487SX) ? (x87_concurrency.fld_z1) : (x87_concurrency.fld_z1 * cpu_multi)); + return 0; } -static int opFYL2X(uint32_t fetchdat) +static int +opF2XM1(uint32_t fetchdat) { - FP_ENTER(); - cpu_state.pc++; - ST(1) = ST(1) * (log(ST(0)) / log(2.0)); - FP_TAG_VALID_N; - x87_pop(); - CLOCK_CYCLES_FPU((fpu_type >= FPU_487SX) ? (x87_timings.fyl2x) : (x87_timings.fyl2x * cpu_multi)); - CONCURRENCY_CYCLES((fpu_type >= FPU_487SX) ? (x87_concurrency.fyl2x) : (x87_concurrency.fyl2x * cpu_multi)); - return 0; + FP_ENTER(); + cpu_state.pc++; + ST(0) = pow(2.0, ST(0)) - 1.0; + FP_TAG_VALID; + CLOCK_CYCLES_FPU((fpu_type >= FPU_487SX) ? (x87_timings.f2xm1) : (x87_timings.f2xm1 * cpu_multi)); + CONCURRENCY_CYCLES((fpu_type >= FPU_487SX) ? (x87_concurrency.f2xm1) : (x87_concurrency.f2xm1 * cpu_multi)); + return 0; } -static int opFYL2XP1(uint32_t fetchdat) +static int +opFYL2X(uint32_t fetchdat) { - FP_ENTER(); - cpu_state.pc++; - ST(1) = ST(1) * (log1p(ST(0)) / log(2.0)); - FP_TAG_VALID_N; - x87_pop(); - CLOCK_CYCLES_FPU((fpu_type >= FPU_487SX) ? (x87_timings.fyl2xp1) : (x87_timings.fyl2xp1 * cpu_multi)); - CONCURRENCY_CYCLES((fpu_type >= FPU_487SX) ? (x87_concurrency.fyl2xp1) : (x87_concurrency.fyl2xp1 * cpu_multi)); - return 0; + FP_ENTER(); + cpu_state.pc++; + ST(1) = ST(1) * (log(ST(0)) / log(2.0)); + FP_TAG_VALID_N; + x87_pop(); + CLOCK_CYCLES_FPU((fpu_type >= FPU_487SX) ? (x87_timings.fyl2x) : (x87_timings.fyl2x * cpu_multi)); + CONCURRENCY_CYCLES((fpu_type >= FPU_487SX) ? (x87_concurrency.fyl2x) : (x87_concurrency.fyl2x * cpu_multi)); + return 0; } -static int opFPTAN(uint32_t fetchdat) +static int +opFYL2XP1(uint32_t fetchdat) { - FP_ENTER(); - cpu_state.pc++; - ST(0) = tan(ST(0)); - FP_TAG_VALID; - x87_push(1.0); - cpu_state.npxs &= ~C2; - CLOCK_CYCLES_FPU((fpu_type >= FPU_487SX) ? (x87_timings.fptan) : (x87_timings.fptan * cpu_multi)); - CONCURRENCY_CYCLES((fpu_type >= FPU_487SX) ? (x87_concurrency.fptan) : (x87_concurrency.fptan * cpu_multi)); - return 0; + FP_ENTER(); + cpu_state.pc++; + ST(1) = ST(1) * (log1p(ST(0)) / log(2.0)); + FP_TAG_VALID_N; + x87_pop(); + CLOCK_CYCLES_FPU((fpu_type >= FPU_487SX) ? (x87_timings.fyl2xp1) : (x87_timings.fyl2xp1 * cpu_multi)); + CONCURRENCY_CYCLES((fpu_type >= FPU_487SX) ? (x87_concurrency.fyl2xp1) : (x87_concurrency.fyl2xp1 * cpu_multi)); + return 0; } -static int opFPATAN(uint32_t fetchdat) +static int +opFPTAN(uint32_t fetchdat) { - FP_ENTER(); - cpu_state.pc++; - ST(1) = atan2(ST(1), ST(0)); - FP_TAG_VALID_N; - x87_pop(); - CLOCK_CYCLES_FPU((fpu_type >= FPU_487SX) ? (x87_timings.fpatan) : (x87_timings.fpatan * cpu_multi)); - CONCURRENCY_CYCLES((fpu_type >= FPU_487SX) ? (x87_concurrency.fpatan) : (x87_concurrency.fpatan * cpu_multi)); - return 0; + FP_ENTER(); + cpu_state.pc++; + ST(0) = tan(ST(0)); + FP_TAG_VALID; + x87_push(1.0); + cpu_state.npxs &= ~C2; + CLOCK_CYCLES_FPU((fpu_type >= FPU_487SX) ? (x87_timings.fptan) : (x87_timings.fptan * cpu_multi)); + CONCURRENCY_CYCLES((fpu_type >= FPU_487SX) ? (x87_concurrency.fptan) : (x87_concurrency.fptan * cpu_multi)); + return 0; } -static int opFDECSTP(uint32_t fetchdat) +static int +opFPATAN(uint32_t fetchdat) { - FP_ENTER(); - cpu_state.pc++; + FP_ENTER(); + cpu_state.pc++; + ST(1) = atan2(ST(1), ST(0)); + FP_TAG_VALID_N; + x87_pop(); + CLOCK_CYCLES_FPU((fpu_type >= FPU_487SX) ? (x87_timings.fpatan) : (x87_timings.fpatan * cpu_multi)); + CONCURRENCY_CYCLES((fpu_type >= FPU_487SX) ? (x87_concurrency.fpatan) : (x87_concurrency.fpatan * cpu_multi)); + return 0; +} + +static int +opFDECSTP(uint32_t fetchdat) +{ + FP_ENTER(); + cpu_state.pc++; #ifdef USE_NEW_DYNAREC - cpu_state.TOP--; + cpu_state.TOP--; #else - cpu_state.TOP = (cpu_state.TOP - 1) & 7; + cpu_state.TOP = (cpu_state.TOP - 1) & 7; #endif - CLOCK_CYCLES_FPU((fpu_type >= FPU_487SX) ? (x87_timings.fincdecstp) : (x87_timings.fincdecstp * cpu_multi)); - CONCURRENCY_CYCLES((fpu_type >= FPU_487SX) ? (x87_concurrency.fincdecstp) : (x87_concurrency.fincdecstp * cpu_multi)); - return 0; + CLOCK_CYCLES_FPU((fpu_type >= FPU_487SX) ? (x87_timings.fincdecstp) : (x87_timings.fincdecstp * cpu_multi)); + CONCURRENCY_CYCLES((fpu_type >= FPU_487SX) ? (x87_concurrency.fincdecstp) : (x87_concurrency.fincdecstp * cpu_multi)); + return 0; } -static int opFINCSTP(uint32_t fetchdat) +static int +opFINCSTP(uint32_t fetchdat) { - FP_ENTER(); - cpu_state.pc++; + FP_ENTER(); + cpu_state.pc++; #ifdef USE_NEW_DYNAREC - cpu_state.TOP++; + cpu_state.TOP++; #else - cpu_state.TOP = (cpu_state.TOP + 1) & 7; + cpu_state.TOP = (cpu_state.TOP + 1) & 7; #endif - CLOCK_CYCLES_FPU((fpu_type >= FPU_487SX) ? (x87_timings.fincdecstp) : (x87_timings.fincdecstp * cpu_multi)); - CONCURRENCY_CYCLES((fpu_type >= FPU_487SX) ? (x87_concurrency.fincdecstp) : (x87_concurrency.fincdecstp * cpu_multi)); - return 0; + CLOCK_CYCLES_FPU((fpu_type >= FPU_487SX) ? (x87_timings.fincdecstp) : (x87_timings.fincdecstp * cpu_multi)); + CONCURRENCY_CYCLES((fpu_type >= FPU_487SX) ? (x87_concurrency.fincdecstp) : (x87_concurrency.fincdecstp * cpu_multi)); + return 0; } -static int opFPREM(uint32_t fetchdat) +static int +opFPREM(uint32_t fetchdat) { - int64_t temp64; - FP_ENTER(); - cpu_state.pc++; - temp64 = (int64_t)(ST(0) / ST(1)); - ST(0) = ST(0) - (ST(1) * (double)temp64); - FP_TAG_VALID; - cpu_state.npxs &= ~(C0|C1|C2|C3); - if (temp64 & 4) cpu_state.npxs|=C0; - if (temp64 & 2) cpu_state.npxs|=C3; - if (temp64 & 1) cpu_state.npxs|=C1; - CLOCK_CYCLES_FPU((fpu_type >= FPU_487SX) ? (x87_timings.fprem) : (x87_timings.fprem * cpu_multi)); - CONCURRENCY_CYCLES((fpu_type >= FPU_487SX) ? (x87_concurrency.fprem) : (x87_concurrency.fprem * cpu_multi)); - return 0; + int64_t temp64; + FP_ENTER(); + cpu_state.pc++; + temp64 = (int64_t) (ST(0) / ST(1)); + ST(0) = ST(0) - (ST(1) * (double) temp64); + FP_TAG_VALID; + cpu_state.npxs &= ~(C0 | C1 | C2 | C3); + if (temp64 & 4) + cpu_state.npxs |= C0; + if (temp64 & 2) + cpu_state.npxs |= C3; + if (temp64 & 1) + cpu_state.npxs |= C1; + CLOCK_CYCLES_FPU((fpu_type >= FPU_487SX) ? (x87_timings.fprem) : (x87_timings.fprem * cpu_multi)); + CONCURRENCY_CYCLES((fpu_type >= FPU_487SX) ? (x87_concurrency.fprem) : (x87_concurrency.fprem * cpu_multi)); + return 0; } -#ifndef FPU_8087 -static int opFPREM1(uint32_t fetchdat) -{ - int64_t temp64; - FP_ENTER(); - cpu_state.pc++; - temp64 = (int64_t)(ST(0) / ST(1)); - ST(0) = ST(0) - (ST(1) * (double)temp64); - FP_TAG_VALID; - cpu_state.npxs &= ~(C0|C1|C2|C3); - if (temp64 & 4) cpu_state.npxs|=C0; - if (temp64 & 2) cpu_state.npxs|=C3; - if (temp64 & 1) cpu_state.npxs|=C1; - CLOCK_CYCLES_FPU((fpu_type >= FPU_487SX) ? (x87_timings.fprem1) : (x87_timings.fprem1 * cpu_multi)); - CONCURRENCY_CYCLES((fpu_type >= FPU_487SX) ? (x87_concurrency.fprem1) : (x87_concurrency.fprem1 * cpu_multi)); - return 0; -} -#endif -static int opFSQRT(uint32_t fetchdat) +static int +opFPREM1(uint32_t fetchdat) { - FP_ENTER(); - cpu_state.pc++; - ST(0) = sqrt(ST(0)); - FP_TAG_VALID; - CLOCK_CYCLES_FPU((fpu_type >= FPU_487SX) ? (x87_timings.fsqrt) : (x87_timings.fsqrt * cpu_multi)); - CONCURRENCY_CYCLES((fpu_type >= FPU_487SX) ? (x87_concurrency.fsqrt) : (x87_concurrency.fsqrt * cpu_multi)); - return 0; + int64_t temp64; + FP_ENTER(); + cpu_state.pc++; + temp64 = (int64_t) (ST(0) / ST(1)); + ST(0) = ST(0) - (ST(1) * (double) temp64); + FP_TAG_VALID; + cpu_state.npxs &= ~(C0 | C1 | C2 | C3); + if (temp64 & 4) + cpu_state.npxs |= C0; + if (temp64 & 2) + cpu_state.npxs |= C3; + if (temp64 & 1) + cpu_state.npxs |= C1; + CLOCK_CYCLES_FPU((fpu_type >= FPU_487SX) ? (x87_timings.fprem1) : (x87_timings.fprem1 * cpu_multi)); + CONCURRENCY_CYCLES((fpu_type >= FPU_487SX) ? (x87_concurrency.fprem1) : (x87_concurrency.fprem1 * cpu_multi)); + return 0; +} + +static int +opFSQRT(uint32_t fetchdat) +{ + FP_ENTER(); + cpu_state.pc++; + ST(0) = sqrt(ST(0)); + FP_TAG_VALID; + CLOCK_CYCLES_FPU((fpu_type >= FPU_487SX) ? (x87_timings.fsqrt) : (x87_timings.fsqrt * cpu_multi)); + CONCURRENCY_CYCLES((fpu_type >= FPU_487SX) ? (x87_concurrency.fsqrt) : (x87_concurrency.fsqrt * cpu_multi)); + return 0; } #ifndef FPU_8087 -static int opFSINCOS(uint32_t fetchdat) +static int +opFSINCOS(uint32_t fetchdat) { - double td; - FP_ENTER(); - cpu_state.pc++; - td = ST(0); - ST(0) = sin(td); - FP_TAG_VALID; - x87_push(cos(td)); - cpu_state.npxs &= ~C2; - CLOCK_CYCLES_FPU((fpu_type >= FPU_487SX) ? (x87_timings.fsincos) : (x87_timings.fsincos * cpu_multi)); - CONCURRENCY_CYCLES((fpu_type >= FPU_487SX) ? (x87_concurrency.fsincos) : (x87_concurrency.fsincos * cpu_multi)); - return 0; + double td; + FP_ENTER(); + cpu_state.pc++; + td = ST(0); + ST(0) = sin(td); + FP_TAG_VALID; + x87_push(cos(td)); + cpu_state.npxs &= ~C2; + CLOCK_CYCLES_FPU((fpu_type >= FPU_487SX) ? (x87_timings.fsincos) : (x87_timings.fsincos * cpu_multi)); + CONCURRENCY_CYCLES((fpu_type >= FPU_487SX) ? (x87_concurrency.fsincos) : (x87_concurrency.fsincos * cpu_multi)); + return 0; } #endif -static int opFRNDINT(uint32_t fetchdat) +static int +opFRNDINT(uint32_t fetchdat) { - FP_ENTER(); - cpu_state.pc++; - ST(0) = (double)x87_fround(ST(0)); - FP_TAG_VALID; - CLOCK_CYCLES_FPU((fpu_type >= FPU_487SX) ? (x87_timings.frndint) : (x87_timings.frndint * cpu_multi)); - CONCURRENCY_CYCLES((fpu_type >= FPU_487SX) ? (x87_concurrency.frndint) : (x87_concurrency.frndint * cpu_multi)); - return 0; + double dst0; + + FP_ENTER(); + cpu_state.pc++; + dst0 = x87_fround(ST(0)); + ST(0) = (double) dst0; + FP_TAG_VALID; + CLOCK_CYCLES_FPU((fpu_type >= FPU_487SX) ? (x87_timings.frndint) : (x87_timings.frndint * cpu_multi)); + CONCURRENCY_CYCLES((fpu_type >= FPU_487SX) ? (x87_concurrency.frndint) : (x87_concurrency.frndint * cpu_multi)); + return 0; } -static int opFSCALE(uint32_t fetchdat) +static int +opFSCALE(uint32_t fetchdat) { - int64_t temp64; - FP_ENTER(); - cpu_state.pc++; - temp64 = (int64_t)ST(1); - if(ST(0) != 0.0) - ST(0) = ST(0) * pow(2.0, (double)temp64); - FP_TAG_VALID; - CLOCK_CYCLES_FPU((fpu_type >= FPU_487SX) ? (x87_timings.fscale) : (x87_timings.fscale * cpu_multi)); - CONCURRENCY_CYCLES((fpu_type >= FPU_487SX) ? (x87_concurrency.fscale) : (x87_concurrency.fscale * cpu_multi)); - return 0; + int64_t temp64; + FP_ENTER(); + cpu_state.pc++; + temp64 = (int64_t) ST(1); + if (ST(0) != 0.0) + ST(0) = ST(0) * pow(2.0, (double) temp64); + FP_TAG_VALID; + CLOCK_CYCLES_FPU((fpu_type >= FPU_487SX) ? (x87_timings.fscale) : (x87_timings.fscale * cpu_multi)); + CONCURRENCY_CYCLES((fpu_type >= FPU_487SX) ? (x87_concurrency.fscale) : (x87_concurrency.fscale * cpu_multi)); + return 0; } #ifndef FPU_8087 -static int opFSIN(uint32_t fetchdat) +static int +opFSIN(uint32_t fetchdat) { - FP_ENTER(); - cpu_state.pc++; - ST(0) = sin(ST(0)); - FP_TAG_VALID; - cpu_state.npxs &= ~C2; - CLOCK_CYCLES_FPU((fpu_type >= FPU_487SX) ? (x87_timings.fsin_cos) : (x87_timings.fsin_cos * cpu_multi)); - CONCURRENCY_CYCLES((fpu_type >= FPU_487SX) ? (x87_concurrency.fsin_cos) : (x87_concurrency.fsin_cos * cpu_multi)); - return 0; + FP_ENTER(); + cpu_state.pc++; + ST(0) = sin(ST(0)); + FP_TAG_VALID; + cpu_state.npxs &= ~C2; + CLOCK_CYCLES_FPU((fpu_type >= FPU_487SX) ? (x87_timings.fsin_cos) : (x87_timings.fsin_cos * cpu_multi)); + CONCURRENCY_CYCLES((fpu_type >= FPU_487SX) ? (x87_concurrency.fsin_cos) : (x87_concurrency.fsin_cos * cpu_multi)); + return 0; } -static int opFCOS(uint32_t fetchdat) +static int +opFCOS(uint32_t fetchdat) { - FP_ENTER(); - cpu_state.pc++; - ST(0) = cos(ST(0)); - FP_TAG_VALID; - cpu_state.npxs &= ~C2; - CLOCK_CYCLES_FPU((fpu_type >= FPU_487SX) ? (x87_timings.fsin_cos) : (x87_timings.fsin_cos * cpu_multi)); - CONCURRENCY_CYCLES((fpu_type >= FPU_487SX) ? (x87_concurrency.fsin_cos) : (x87_concurrency.fsin_cos * cpu_multi)); - return 0; + FP_ENTER(); + cpu_state.pc++; + ST(0) = cos(ST(0)); + FP_TAG_VALID; + cpu_state.npxs &= ~C2; + CLOCK_CYCLES_FPU((fpu_type >= FPU_487SX) ? (x87_timings.fsin_cos) : (x87_timings.fsin_cos * cpu_multi)); + CONCURRENCY_CYCLES((fpu_type >= FPU_487SX) ? (x87_concurrency.fsin_cos) : (x87_concurrency.fsin_cos * cpu_multi)); + return 0; } #endif - -static int FLDENV() +static int +FLDENV(void) { - FP_ENTER(); - switch ((cr0 & 1) | (cpu_state.op32 & 0x100)) - { - case 0x000: /*16-bit real mode*/ - case 0x001: /*16-bit protected mode*/ - cpu_state.npxc = readmemw(easeg, cpu_state.eaaddr); - codegen_set_rounding_mode((cpu_state.npxc >> 10) & 3); - cpu_state.npxs = readmemw(easeg, cpu_state.eaaddr+2); - x87_settag(readmemw(easeg, cpu_state.eaaddr+4)); - cpu_state.TOP = (cpu_state.npxs >> 11) & 7; - break; - case 0x100: /*32-bit real mode*/ - case 0x101: /*32-bit protected mode*/ - cpu_state.npxc = readmemw(easeg, cpu_state.eaaddr); - codegen_set_rounding_mode((cpu_state.npxc >> 10) & 3); - cpu_state.npxs = readmemw(easeg, cpu_state.eaaddr+4); - x87_settag(readmemw(easeg, cpu_state.eaaddr+8)); - cpu_state.TOP = (cpu_state.npxs >> 11) & 7; - break; - } - CLOCK_CYCLES_FPU((fpu_type >= FPU_487SX) ? (x87_timings.fldenv) : (x87_timings.fldenv * cpu_multi)); - CONCURRENCY_CYCLES((fpu_type >= FPU_487SX) ? (x87_concurrency.fldenv) : (x87_concurrency.fldenv * cpu_multi)); - return cpu_state.abrt; + FP_ENTER(); + switch ((cr0 & 1) | (cpu_state.op32 & 0x100)) { + case 0x000: /*16-bit real mode*/ + case 0x001: /*16-bit protected mode*/ + cpu_state.npxc = readmemw(easeg, cpu_state.eaaddr); + codegen_set_rounding_mode((cpu_state.npxc >> 10) & 3); + cpu_state.npxs = readmemw(easeg, cpu_state.eaaddr + 2); + x87_settag(readmemw(easeg, cpu_state.eaaddr + 4)); + cpu_state.TOP = (cpu_state.npxs >> 11) & 7; + break; + case 0x100: /*32-bit real mode*/ + case 0x101: /*32-bit protected mode*/ + cpu_state.npxc = readmemw(easeg, cpu_state.eaaddr); + codegen_set_rounding_mode((cpu_state.npxc >> 10) & 3); + cpu_state.npxs = readmemw(easeg, cpu_state.eaaddr + 4); + x87_settag(readmemw(easeg, cpu_state.eaaddr + 8)); + cpu_state.TOP = (cpu_state.npxs >> 11) & 7; + break; + } + CLOCK_CYCLES_FPU((fpu_type >= FPU_487SX) ? (x87_timings.fldenv) : (x87_timings.fldenv * cpu_multi)); + CONCURRENCY_CYCLES((fpu_type >= FPU_487SX) ? (x87_concurrency.fldenv) : (x87_concurrency.fldenv * cpu_multi)); + return cpu_state.abrt; } -static int opFLDENV_a16(uint32_t fetchdat) +static int +opFLDENV_a16(uint32_t fetchdat) { - FP_ENTER(); - fetch_ea_16(fetchdat); - SEG_CHECK_READ(cpu_state.ea_seg); - FLDENV(); - return cpu_state.abrt; + FP_ENTER(); + fetch_ea_16(fetchdat); + SEG_CHECK_READ(cpu_state.ea_seg); + FLDENV(); + return cpu_state.abrt; } #ifndef FPU_8087 -static int opFLDENV_a32(uint32_t fetchdat) +static int +opFLDENV_a32(uint32_t fetchdat) { - FP_ENTER(); - fetch_ea_32(fetchdat); - SEG_CHECK_READ(cpu_state.ea_seg); - FLDENV(); - return cpu_state.abrt; + FP_ENTER(); + fetch_ea_32(fetchdat); + SEG_CHECK_READ(cpu_state.ea_seg); + FLDENV(); + return cpu_state.abrt; } #endif -static int opFLDCW_a16(uint32_t fetchdat) +static int +opFLDCW_a16(uint32_t fetchdat) { - uint16_t tempw; - FP_ENTER(); - fetch_ea_16(fetchdat); - SEG_CHECK_READ(cpu_state.ea_seg); - tempw = geteaw(); - if (cpu_state.abrt) return 1; - cpu_state.npxc = tempw; - codegen_set_rounding_mode((cpu_state.npxc >> 10) & 3); - CLOCK_CYCLES_FPU((fpu_type >= FPU_487SX) ? (x87_timings.fldcw) : (x87_timings.fldcw * cpu_multi)); - CONCURRENCY_CYCLES((fpu_type >= FPU_487SX) ? (x87_concurrency.fldcw) : (x87_concurrency.fldcw * cpu_multi)); - return 0; + uint16_t tempw; + FP_ENTER(); + fetch_ea_16(fetchdat); + SEG_CHECK_READ(cpu_state.ea_seg); + tempw = geteaw(); + if (cpu_state.abrt) + return 1; + cpu_state.npxc = tempw; + codegen_set_rounding_mode((cpu_state.npxc >> 10) & 3); + CLOCK_CYCLES_FPU((fpu_type >= FPU_487SX) ? (x87_timings.fldcw) : (x87_timings.fldcw * cpu_multi)); + CONCURRENCY_CYCLES((fpu_type >= FPU_487SX) ? (x87_concurrency.fldcw) : (x87_concurrency.fldcw * cpu_multi)); + return 0; } #ifndef FPU_8087 -static int opFLDCW_a32(uint32_t fetchdat) +static int +opFLDCW_a32(uint32_t fetchdat) { - uint16_t tempw; - FP_ENTER(); - fetch_ea_32(fetchdat); - SEG_CHECK_READ(cpu_state.ea_seg); - tempw = geteaw(); - if (cpu_state.abrt) return 1; - cpu_state.npxc = tempw; - codegen_set_rounding_mode((cpu_state.npxc >> 10) & 3); - CLOCK_CYCLES_FPU((fpu_type >= FPU_487SX) ? (x87_timings.fldcw) : (x87_timings.fldcw * cpu_multi)); - CONCURRENCY_CYCLES((fpu_type >= FPU_487SX) ? (x87_concurrency.fldcw) : (x87_concurrency.fldcw * cpu_multi)); - return 0; + uint16_t tempw; + FP_ENTER(); + fetch_ea_32(fetchdat); + SEG_CHECK_READ(cpu_state.ea_seg); + tempw = geteaw(); + if (cpu_state.abrt) + return 1; + cpu_state.npxc = tempw; + codegen_set_rounding_mode((cpu_state.npxc >> 10) & 3); + CLOCK_CYCLES_FPU((fpu_type >= FPU_487SX) ? (x87_timings.fldcw) : (x87_timings.fldcw * cpu_multi)); + CONCURRENCY_CYCLES((fpu_type >= FPU_487SX) ? (x87_concurrency.fldcw) : (x87_concurrency.fldcw * cpu_multi)); + return 0; } #endif -static int FSTENV() +static int +FSTENV(void) { - FP_ENTER(); - cpu_state.npxs = (cpu_state.npxs & ~(7 << 11)) | ((cpu_state.TOP & 7) << 11); - - switch ((cr0 & 1) | (cpu_state.op32 & 0x100)) - { - case 0x000: /*16-bit real mode*/ - writememw(easeg,cpu_state.eaaddr,cpu_state.npxc); - writememw(easeg,cpu_state.eaaddr+2,cpu_state.npxs); - writememw(easeg,cpu_state.eaaddr+4,x87_gettag()); - writememw(easeg,cpu_state.eaaddr+6,x87_pc_off); - writememw(easeg,cpu_state.eaaddr+10,x87_op_off); - break; - case 0x001: /*16-bit protected mode*/ - writememw(easeg,cpu_state.eaaddr,cpu_state.npxc); - writememw(easeg,cpu_state.eaaddr+2,cpu_state.npxs); - writememw(easeg,cpu_state.eaaddr+4,x87_gettag()); - writememw(easeg,cpu_state.eaaddr+6,x87_pc_off); - writememw(easeg,cpu_state.eaaddr+8,x87_pc_seg); - writememw(easeg,cpu_state.eaaddr+10,x87_op_off); - writememw(easeg,cpu_state.eaaddr+12,x87_op_seg); - break; - case 0x100: /*32-bit real mode*/ - writememw(easeg,cpu_state.eaaddr,cpu_state.npxc); - writememw(easeg,cpu_state.eaaddr+4,cpu_state.npxs); - writememw(easeg,cpu_state.eaaddr+8,x87_gettag()); - writememw(easeg,cpu_state.eaaddr+12,x87_pc_off); - writememw(easeg,cpu_state.eaaddr+20,x87_op_off); - writememl(easeg,cpu_state.eaaddr+24,(x87_op_off>>16)<<12); - break; - case 0x101: /*32-bit protected mode*/ - writememw(easeg,cpu_state.eaaddr,cpu_state.npxc); - writememw(easeg,cpu_state.eaaddr+4,cpu_state.npxs); - writememw(easeg,cpu_state.eaaddr+8,x87_gettag()); - writememl(easeg,cpu_state.eaaddr+12,x87_pc_off); - writememl(easeg,cpu_state.eaaddr+16,x87_pc_seg); - writememl(easeg,cpu_state.eaaddr+20,x87_op_off); - writememl(easeg,cpu_state.eaaddr+24,x87_op_seg); - break; - } - CLOCK_CYCLES_FPU((fpu_type >= FPU_487SX) ? (x87_timings.fstenv) : (x87_timings.fstenv * cpu_multi)); - CONCURRENCY_CYCLES((fpu_type >= FPU_487SX) ? (x87_concurrency.fstenv) : (x87_concurrency.fstenv * cpu_multi)); - return cpu_state.abrt; + FP_ENTER(); + cpu_state.npxs = (cpu_state.npxs & ~(7 << 11)) | ((cpu_state.TOP & 7) << 11); + + switch ((cr0 & 1) | (cpu_state.op32 & 0x100)) { + case 0x000: /*16-bit real mode*/ + writememw(easeg, cpu_state.eaaddr, cpu_state.npxc); + writememw(easeg, cpu_state.eaaddr + 2, cpu_state.npxs); + writememw(easeg, cpu_state.eaaddr + 4, x87_gettag()); + writememw(easeg, cpu_state.eaaddr + 6, x87_pc_off); + writememw(easeg, cpu_state.eaaddr + 10, x87_op_off); + break; + case 0x001: /*16-bit protected mode*/ + writememw(easeg, cpu_state.eaaddr, cpu_state.npxc); + writememw(easeg, cpu_state.eaaddr + 2, cpu_state.npxs); + writememw(easeg, cpu_state.eaaddr + 4, x87_gettag()); + writememw(easeg, cpu_state.eaaddr + 6, x87_pc_off); + writememw(easeg, cpu_state.eaaddr + 8, x87_pc_seg); + writememw(easeg, cpu_state.eaaddr + 10, x87_op_off); + writememw(easeg, cpu_state.eaaddr + 12, x87_op_seg); + break; + case 0x100: /*32-bit real mode*/ + writememw(easeg, cpu_state.eaaddr, cpu_state.npxc); + writememw(easeg, cpu_state.eaaddr + 4, cpu_state.npxs); + writememw(easeg, cpu_state.eaaddr + 8, x87_gettag()); + writememw(easeg, cpu_state.eaaddr + 12, x87_pc_off); + writememw(easeg, cpu_state.eaaddr + 20, x87_op_off); + writememl(easeg, cpu_state.eaaddr + 24, (x87_op_off >> 16) << 12); + break; + case 0x101: /*32-bit protected mode*/ + writememw(easeg, cpu_state.eaaddr, cpu_state.npxc); + writememw(easeg, cpu_state.eaaddr + 4, cpu_state.npxs); + writememw(easeg, cpu_state.eaaddr + 8, x87_gettag()); + writememl(easeg, cpu_state.eaaddr + 12, x87_pc_off); + writememl(easeg, cpu_state.eaaddr + 16, x87_pc_seg); + writememl(easeg, cpu_state.eaaddr + 20, x87_op_off); + writememl(easeg, cpu_state.eaaddr + 24, x87_op_seg); + break; + } + CLOCK_CYCLES_FPU((fpu_type >= FPU_487SX) ? (x87_timings.fstenv) : (x87_timings.fstenv * cpu_multi)); + CONCURRENCY_CYCLES((fpu_type >= FPU_487SX) ? (x87_concurrency.fstenv) : (x87_concurrency.fstenv * cpu_multi)); + return cpu_state.abrt; } -static int opFSTENV_a16(uint32_t fetchdat) +static int +opFSTENV_a16(uint32_t fetchdat) { - FP_ENTER(); - fetch_ea_16(fetchdat); - SEG_CHECK_WRITE(cpu_state.ea_seg); - FSTENV(); - return cpu_state.abrt; + FP_ENTER(); + fetch_ea_16(fetchdat); + SEG_CHECK_WRITE(cpu_state.ea_seg); + FSTENV(); + return cpu_state.abrt; } #ifndef FPU_8087 -static int opFSTENV_a32(uint32_t fetchdat) +static int +opFSTENV_a32(uint32_t fetchdat) { - FP_ENTER(); - fetch_ea_32(fetchdat); - SEG_CHECK_WRITE(cpu_state.ea_seg); - FSTENV(); - return cpu_state.abrt; + FP_ENTER(); + fetch_ea_32(fetchdat); + SEG_CHECK_WRITE(cpu_state.ea_seg); + FSTENV(); + return cpu_state.abrt; } #endif -static int opFSTCW_a16(uint32_t fetchdat) +static int +opFSTCW_a16(uint32_t fetchdat) { - FP_ENTER(); - fetch_ea_16(fetchdat); - SEG_CHECK_WRITE(cpu_state.ea_seg); - seteaw(cpu_state.npxc); - CLOCK_CYCLES_FPU((fpu_type >= FPU_487SX) ? (x87_timings.fstcw_sw) : (x87_timings.fstcw_sw * cpu_multi)); - CONCURRENCY_CYCLES((fpu_type >= FPU_487SX) ? (x87_concurrency.fstenv) : (x87_concurrency.fstenv * cpu_multi)); - return cpu_state.abrt; + FP_ENTER(); + fetch_ea_16(fetchdat); + SEG_CHECK_WRITE(cpu_state.ea_seg); + seteaw(cpu_state.npxc); + CLOCK_CYCLES_FPU((fpu_type >= FPU_487SX) ? (x87_timings.fstcw_sw) : (x87_timings.fstcw_sw * cpu_multi)); + CONCURRENCY_CYCLES((fpu_type >= FPU_487SX) ? (x87_concurrency.fstenv) : (x87_concurrency.fstenv * cpu_multi)); + return cpu_state.abrt; } #ifndef FPU_8087 -static int opFSTCW_a32(uint32_t fetchdat) +static int +opFSTCW_a32(uint32_t fetchdat) { - FP_ENTER(); - fetch_ea_32(fetchdat); - SEG_CHECK_WRITE(cpu_state.ea_seg); - seteaw(cpu_state.npxc); - CLOCK_CYCLES_FPU((fpu_type >= FPU_487SX) ? (x87_timings.fstcw_sw) : (x87_timings.fstcw_sw * cpu_multi)); - CONCURRENCY_CYCLES((fpu_type >= FPU_487SX) ? (x87_concurrency.fstcw_sw) : (x87_concurrency.fstcw_sw * cpu_multi)); - return cpu_state.abrt; + FP_ENTER(); + fetch_ea_32(fetchdat); + SEG_CHECK_WRITE(cpu_state.ea_seg); + seteaw(cpu_state.npxc); + CLOCK_CYCLES_FPU((fpu_type >= FPU_487SX) ? (x87_timings.fstcw_sw) : (x87_timings.fstcw_sw * cpu_multi)); + CONCURRENCY_CYCLES((fpu_type >= FPU_487SX) ? (x87_concurrency.fstcw_sw) : (x87_concurrency.fstcw_sw * cpu_multi)); + return cpu_state.abrt; } #endif #ifndef FPU_8087 -#define opFCMOV(condition) \ - static int opFCMOV ## condition(uint32_t fetchdat) \ - { \ - FP_ENTER(); \ - cpu_state.pc++; \ - if (cond_ ## condition) \ - { \ - cpu_state.tag[cpu_state.TOP&7] = cpu_state.tag[(cpu_state.TOP + fetchdat) & 7]; \ - cpu_state.MM[cpu_state.TOP&7].q = cpu_state.MM[(cpu_state.TOP + fetchdat) & 7].q; \ - ST(0) = ST(fetchdat & 7); \ - } \ - CLOCK_CYCLES_FPU(4); \ - return 0; \ - } +# ifndef OPS_286_386 +# define opFCMOV(condition) \ + static int opFCMOV##condition(uint32_t fetchdat) \ + { \ + FP_ENTER(); \ + cpu_state.pc++; \ + if (cond_##condition) { \ + cpu_state.tag[cpu_state.TOP & 7] = cpu_state.tag[(cpu_state.TOP + fetchdat) & 7]; \ + cpu_state.MM[cpu_state.TOP & 7].q = cpu_state.MM[(cpu_state.TOP + fetchdat) & 7].q; \ + ST(0) = ST(fetchdat & 7); \ + } \ + CLOCK_CYCLES_FPU(4); \ + return 0; \ + } -#define cond_U ( PF_SET()) -#define cond_NU (!PF_SET()) +# define cond_U (PF_SET()) +# define cond_NU (!PF_SET()) +// clang-format off opFCMOV(B) opFCMOV(E) opFCMOV(BE) @@ -943,4 +1076,6 @@ opFCMOV(NB) opFCMOV(NE) opFCMOV(NBE) opFCMOV(NU) +// clang-format on +# endif #endif diff --git a/src/cpu/x87_ops_sf.h b/src/cpu/x87_ops_sf.h new file mode 100644 index 000000000..137919fa9 --- /dev/null +++ b/src/cpu/x87_ops_sf.h @@ -0,0 +1,607 @@ +static uint32_t +fpu_save_environment(void) +{ + int tag; + unsigned offset = 0; + + /* read all registers in stack order and update x87 tag word */ + for (int n = 0; n < 8; n++) { + // update tag only if it is not empty + if (!IS_TAG_EMPTY(n)) { + tag = FPU_tagof(FPU_read_regi(n)); + FPU_settagi(tag, n); + } + } + + fpu_state.swd = (fpu_state.swd & ~(7 << 11)) | ((fpu_state.tos & 7) << 11); + + switch ((cr0 & 1) | (cpu_state.op32 & 0x100)) { + case 0x000: + { /*16-bit real mode*/ + uint16_t tmp; + uint32_t fp_ip; + uint32_t fp_dp; + + fp_ip = ((uint32_t) (fpu_state.fcs << 4)) | fpu_state.fip; + fp_dp = ((uint32_t) (fpu_state.fds << 4)) | fpu_state.fdp; + + tmp = i387_get_control_word(); + writememw(easeg, cpu_state.eaaddr + 0x00, tmp); + tmp = i387_get_status_word(); + writememw(easeg, cpu_state.eaaddr + 0x02, tmp); + tmp = fpu_state.tag; + writememw(easeg, cpu_state.eaaddr + 0x04, tmp); + tmp = fp_ip & 0xffff; + writememw(easeg, cpu_state.eaaddr + 0x06, tmp); + tmp = (uint16_t) ((fp_ip & 0xf0000) >> 4) | fpu_state.foo; + writememw(easeg, cpu_state.eaaddr + 0x08, tmp); + tmp = fp_dp & 0xffff; + writememw(easeg, cpu_state.eaaddr + 0x0a, tmp); + tmp = (uint16_t) ((fp_dp & 0xf0000) >> 4); + writememw(easeg, cpu_state.eaaddr + 0x0c, tmp); + offset = 0x0e; + } + break; + case 0x001: + { /*16-bit protected mode*/ + uint16_t tmp; + tmp = i387_get_control_word(); + writememw(easeg, cpu_state.eaaddr + 0x00, tmp); + tmp = i387_get_status_word(); + writememw(easeg, cpu_state.eaaddr + 0x02, tmp); + tmp = fpu_state.tag; + writememw(easeg, cpu_state.eaaddr + 0x04, tmp); + tmp = (uint16_t) (fpu_state.fip) & 0xffff; + writememw(easeg, cpu_state.eaaddr + 0x06, tmp); + tmp = fpu_state.fcs; + writememw(easeg, cpu_state.eaaddr + 0x08, tmp); + tmp = (uint16_t) (fpu_state.fdp) & 0xffff; + writememw(easeg, cpu_state.eaaddr + 0x0a, tmp); + tmp = fpu_state.fds; + writememw(easeg, cpu_state.eaaddr + 0x0c, tmp); + offset = 0x0e; + } + break; + case 0x100: + { /*32-bit real mode*/ + uint32_t tmp; + uint32_t fp_ip; + uint32_t fp_dp; + + fp_ip = ((uint32_t) (fpu_state.fcs << 4)) | fpu_state.fip; + fp_dp = ((uint32_t) (fpu_state.fds << 4)) | fpu_state.fdp; + + tmp = 0xffff0000 | i387_get_control_word(); + writememl(easeg, cpu_state.eaaddr + 0x00, tmp); + tmp = 0xffff0000 | i387_get_status_word(); + writememl(easeg, cpu_state.eaaddr + 0x04, tmp); + tmp = 0xffff0000 | fpu_state.tag; + writememl(easeg, cpu_state.eaaddr + 0x08, tmp); + tmp = 0xffff0000 | (fp_ip & 0xffff); + writememl(easeg, cpu_state.eaaddr + 0x0c, tmp); + tmp = ((fp_ip & 0xffff0000) >> 4) | fpu_state.foo; + writememl(easeg, cpu_state.eaaddr + 0x10, tmp); + tmp = 0xffff0000 | (fp_dp & 0xffff); + writememl(easeg, cpu_state.eaaddr + 0x14, tmp); + tmp = (fp_dp & 0xffff0000) >> 4; + writememl(easeg, cpu_state.eaaddr + 0x18, tmp); + offset = 0x1c; + } + break; + case 0x101: + { /*32-bit protected mode*/ + uint32_t tmp; + tmp = 0xffff0000 | i387_get_control_word(); + writememl(easeg, cpu_state.eaaddr + 0x00, tmp); + tmp = 0xffff0000 | i387_get_status_word(); + writememl(easeg, cpu_state.eaaddr + 0x04, tmp); + tmp = 0xffff0000 | fpu_state.tag; + writememl(easeg, cpu_state.eaaddr + 0x08, tmp); + tmp = (uint32_t) (fpu_state.fip); + writememl(easeg, cpu_state.eaaddr + 0x0c, tmp); + tmp = fpu_state.fcs | (((uint32_t) (fpu_state.foo)) << 16); + writememl(easeg, cpu_state.eaaddr + 0x10, tmp); + tmp = (uint32_t) (fpu_state.fdp); + writememl(easeg, cpu_state.eaaddr + 0x14, tmp); + tmp = 0xffff0000 | fpu_state.fds; + writememl(easeg, cpu_state.eaaddr + 0x18, tmp); + offset = 0x1c; + } + break; + } + + return (cpu_state.eaaddr + offset); +} + +static uint32_t +fpu_load_environment(void) +{ + unsigned offset = 0; + + switch ((cr0 & 1) | (cpu_state.op32 & 0x100)) { + case 0x000: + { /*16-bit real mode*/ + uint16_t tmp; + uint32_t fp_ip; + uint32_t fp_dp; + + tmp = readmemw(easeg, cpu_state.eaaddr + 0x0c); + fp_dp = (tmp & 0xf000) << 4; + tmp = readmemw(easeg, cpu_state.eaaddr + 0x0a); + fpu_state.fdp = fp_dp | tmp; + fpu_state.fds = 0; + tmp = readmemw(easeg, cpu_state.eaaddr + 0x08); + fp_ip = (tmp & 0xf000) << 4; + tmp = readmemw(easeg, cpu_state.eaaddr + 0x06); + fpu_state.fip = fp_ip | tmp; + fpu_state.fcs = 0; + tmp = readmemw(easeg, cpu_state.eaaddr + 0x04); + fpu_state.tag = tmp; + tmp = readmemw(easeg, cpu_state.eaaddr + 0x02); + fpu_state.swd = tmp; + fpu_state.tos = (tmp >> 11) & 7; + tmp = readmemw(easeg, cpu_state.eaaddr + 0x00); + fpu_state.cwd = tmp; + offset = 0x0e; + } + break; + case 0x001: + { /*16-bit protected mode*/ + uint16_t tmp; + tmp = readmemw(easeg, cpu_state.eaaddr + 0x0c); + fpu_state.fds = tmp; + tmp = readmemw(easeg, cpu_state.eaaddr + 0x0a); + fpu_state.fdp = tmp; + tmp = readmemw(easeg, cpu_state.eaaddr + 0x08); + fpu_state.fcs = tmp; + tmp = readmemw(easeg, cpu_state.eaaddr + 0x06); + fpu_state.fip = tmp; + tmp = readmemw(easeg, cpu_state.eaaddr + 0x04); + fpu_state.tag = tmp; + tmp = readmemw(easeg, cpu_state.eaaddr + 0x02); + fpu_state.swd = tmp; + fpu_state.tos = (tmp >> 11) & 7; + tmp = readmemw(easeg, cpu_state.eaaddr + 0x00); + fpu_state.cwd = tmp; + offset = 0x0e; + } + break; + case 0x100: + { /*32-bit real mode*/ + uint32_t tmp; + uint32_t fp_ip; + uint32_t fp_dp; + + tmp = readmeml(easeg, cpu_state.eaaddr + 0x18); + fp_dp = (tmp & 0x0ffff000) << 4; + tmp = readmeml(easeg, cpu_state.eaaddr + 0x14); + fp_dp |= (tmp & 0xffff); + fpu_state.fdp = fp_dp; + fpu_state.fds = 0; + tmp = readmeml(easeg, cpu_state.eaaddr + 0x10); + fpu_state.foo = tmp & 0x07ff; + fp_ip = (tmp & 0x0ffff000) << 4; + tmp = readmeml(easeg, cpu_state.eaaddr + 0x0c); + fp_ip |= (tmp & 0xffff); + fpu_state.fip = fp_ip; + fpu_state.fcs = 0; + tmp = readmeml(easeg, cpu_state.eaaddr + 0x08); + fpu_state.tag = tmp & 0xffff; + tmp = readmeml(easeg, cpu_state.eaaddr + 0x04); + fpu_state.swd = tmp & 0xffff; + fpu_state.tos = (tmp >> 11) & 7; + tmp = readmeml(easeg, cpu_state.eaaddr + 0x00); + fpu_state.cwd = tmp & 0xffff; + offset = 0x1c; + } + break; + case 0x101: + { /*32-bit protected mode*/ + uint32_t tmp; + tmp = readmeml(easeg, cpu_state.eaaddr + 0x18); + fpu_state.fds = tmp & 0xffff; + tmp = readmeml(easeg, cpu_state.eaaddr + 0x14); + fpu_state.fdp = tmp; + tmp = readmeml(easeg, cpu_state.eaaddr + 0x10); + fpu_state.fcs = tmp & 0xffff; + fpu_state.foo = (tmp >> 16) & 0x07ff; + tmp = readmeml(easeg, cpu_state.eaaddr + 0x0c); + fpu_state.fip = tmp; + tmp = readmeml(easeg, cpu_state.eaaddr + 0x08); + fpu_state.tag = tmp & 0xffff; + tmp = readmeml(easeg, cpu_state.eaaddr + 0x04); + fpu_state.swd = tmp & 0xffff; + fpu_state.tos = (tmp >> 11) & 7; + tmp = readmeml(easeg, cpu_state.eaaddr + 0x00); + fpu_state.cwd = tmp & 0xffff; + offset = 0x1c; + } + break; + } + + /* always set bit 6 as '1 */ + fpu_state.cwd = (fpu_state.cwd & ~FPU_CW_Reserved_Bits) | 0x0040; + + /* 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); + } + + return (cpu_state.eaaddr + offset); +} + +static int +sf_FLDCW_a16(uint32_t fetchdat) +{ + uint16_t tempw; + + FP_ENTER(); + fetch_ea_16(fetchdat); + SEG_CHECK_READ(cpu_state.ea_seg); + tempw = geteaw(); + if (cpu_state.abrt) + return 1; + fpu_state.cwd = (tempw & ~FPU_CW_Reserved_Bits) | 0x0040; // bit 6 is reserved as '1 + /* 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_FPU((fpu_type >= FPU_487SX) ? (x87_timings.fldcw) : (x87_timings.fldcw * cpu_multi)); + CONCURRENCY_CYCLES((fpu_type >= FPU_487SX) ? (x87_concurrency.fldcw) : (x87_concurrency.fldcw * cpu_multi)); + return 0; +} +#ifndef FPU_8087 +static int +sf_FLDCW_a32(uint32_t fetchdat) +{ + uint16_t tempw; + + FP_ENTER(); + fetch_ea_32(fetchdat); + SEG_CHECK_READ(cpu_state.ea_seg); + tempw = geteaw(); + if (cpu_state.abrt) + return 1; + fpu_state.cwd = (tempw & ~FPU_CW_Reserved_Bits) | 0x0040; // bit 6 is reserved as '1 + /* 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_FPU((fpu_type >= FPU_487SX) ? (x87_timings.fldcw) : (x87_timings.fldcw * cpu_multi)); + CONCURRENCY_CYCLES((fpu_type >= FPU_487SX) ? (x87_concurrency.fldcw) : (x87_concurrency.fldcw * cpu_multi)); + return 0; +} +#endif + +static int +sf_FNSTCW_a16(uint32_t fetchdat) +{ + uint16_t cwd = i387_get_control_word(); + + FP_ENTER(); + fetch_ea_16(fetchdat); + SEG_CHECK_WRITE(cpu_state.ea_seg); + seteaw(cwd); + CLOCK_CYCLES_FPU((fpu_type >= FPU_487SX) ? (x87_timings.fstcw_sw) : (x87_timings.fstcw_sw * cpu_multi)); + CONCURRENCY_CYCLES((fpu_type >= FPU_487SX) ? (x87_concurrency.fstenv) : (x87_concurrency.fstenv * cpu_multi)); + return cpu_state.abrt; +} +#ifndef FPU_8087 +static int +sf_FNSTCW_a32(uint32_t fetchdat) +{ + uint16_t cwd = i387_get_control_word(); + + FP_ENTER(); + fetch_ea_32(fetchdat); + SEG_CHECK_WRITE(cpu_state.ea_seg); + seteaw(cwd); + CLOCK_CYCLES_FPU((fpu_type >= FPU_487SX) ? (x87_timings.fstcw_sw) : (x87_timings.fstcw_sw * cpu_multi)); + CONCURRENCY_CYCLES((fpu_type >= FPU_487SX) ? (x87_concurrency.fstcw_sw) : (x87_concurrency.fstcw_sw * cpu_multi)); + return cpu_state.abrt; +} +#endif + +static int +sf_FNSTSW_a16(uint32_t fetchdat) +{ + uint16_t swd = i387_get_status_word(); + + FP_ENTER(); + fetch_ea_16(fetchdat); + SEG_CHECK_WRITE(cpu_state.ea_seg); + seteaw(swd); + CLOCK_CYCLES_FPU((fpu_type >= FPU_487SX) ? (x87_timings.fstcw_sw) : (x87_timings.fstcw_sw * cpu_multi)); + CONCURRENCY_CYCLES((fpu_type >= FPU_487SX) ? (x87_concurrency.fstcw_sw) : (x87_concurrency.fstcw_sw * cpu_multi)); + return cpu_state.abrt; +} +#ifndef FPU_8087 +static int +sf_FNSTSW_a32(uint32_t fetchdat) +{ + uint16_t swd = i387_get_status_word(); + + FP_ENTER(); + fetch_ea_32(fetchdat); + SEG_CHECK_WRITE(cpu_state.ea_seg); + seteaw(swd); + CLOCK_CYCLES_FPU((fpu_type >= FPU_487SX) ? (x87_timings.fstcw_sw) : (x87_timings.fstcw_sw * cpu_multi)); + CONCURRENCY_CYCLES((fpu_type >= FPU_487SX) ? (x87_concurrency.fstcw_sw) : (x87_concurrency.fstcw_sw * cpu_multi)); + return cpu_state.abrt; +} +#endif + +#ifdef FPU_8087 +static int +sf_FI(uint32_t fetchdat) +{ + FP_ENTER(); + cpu_state.pc++; + fpu_state.cwd &= ~FPU_SW_Summary; + if (rmdat == 0xe1) + fpu_state.cwd |= FPU_SW_Summary; + wait(3, 0); + return 0; +} +#else +static int +sf_FNSTSW_AX(uint32_t fetchdat) +{ + FP_ENTER(); + cpu_state.pc++; + AX = i387_get_status_word(); + CLOCK_CYCLES_FPU((fpu_type >= FPU_487SX) ? (x87_timings.fstcw_sw) : (x87_timings.fstcw_sw * cpu_multi)); + CONCURRENCY_CYCLES((fpu_type >= FPU_487SX) ? (x87_concurrency.fstcw_sw) : (x87_concurrency.fstcw_sw * cpu_multi)); + return 0; +} +#endif + +static int +sf_FRSTOR_a16(uint32_t fetchdat) +{ + floatx80 tmp; + int offset; + + FP_ENTER(); + fetch_ea_16(fetchdat); + SEG_CHECK_READ(cpu_state.ea_seg); + offset = fpu_load_environment(); + for (int n = 0; n < 8; n++) { + tmp.fraction = readmemq(easeg, offset + (n * 10)); + tmp.exp = readmemw(easeg, offset + (n * 10) + 8); + FPU_save_regi_tag(tmp, IS_TAG_EMPTY(n) ? X87_TAG_EMPTY : FPU_tagof(tmp), n); + } + CLOCK_CYCLES_FPU((fpu_type >= FPU_487SX) ? (x87_timings.frstor) : (x87_timings.frstor * cpu_multi)); + CONCURRENCY_CYCLES((fpu_type >= FPU_487SX) ? (x87_concurrency.frstor) : (x87_concurrency.frstor * cpu_multi)); + return cpu_state.abrt; +} +#ifndef FPU_8087 +static int +sf_FRSTOR_a32(uint32_t fetchdat) +{ + floatx80 tmp; + int offset; + + FP_ENTER(); + fetch_ea_32(fetchdat); + SEG_CHECK_READ(cpu_state.ea_seg); + offset = fpu_load_environment(); + for (int n = 0; n < 8; n++) { + tmp.fraction = readmemq(easeg, offset + (n * 10)); + tmp.exp = readmemw(easeg, offset + (n * 10) + 8); + FPU_save_regi_tag(tmp, IS_TAG_EMPTY(n) ? X87_TAG_EMPTY : FPU_tagof(tmp), n); + } + CLOCK_CYCLES_FPU((fpu_type >= FPU_487SX) ? (x87_timings.frstor) : (x87_timings.frstor * cpu_multi)); + CONCURRENCY_CYCLES((fpu_type >= FPU_487SX) ? (x87_concurrency.frstor) : (x87_concurrency.frstor * cpu_multi)); + return cpu_state.abrt; +} +#endif + +static int +sf_FNSAVE_a16(uint32_t fetchdat) +{ + floatx80 stn; + int offset; + + FP_ENTER(); + fetch_ea_16(fetchdat); + SEG_CHECK_WRITE(cpu_state.ea_seg); + offset = fpu_save_environment(); + /* save all registers in stack order. */ + for (int m = 0; m < 8; m++) { + stn = FPU_read_regi(m); + writememq(easeg, offset + (m * 10), stn.fraction); + writememw(easeg, offset + (m * 10) + 8, stn.exp); + } + +#ifdef FPU_8087 + fpu_state.swd = 0x3FF; +#else + fpu_state.cwd = 0x37F; +#endif + fpu_state.swd = 0; + fpu_state.tos = 0; + fpu_state.tag = 0xffff; + cpu_state.ismmx = 0; + fpu_state.foo = 0; + fpu_state.fds = 0; + fpu_state.fdp = 0; + fpu_state.fcs = 0; + fpu_state.fip = 0; + CLOCK_CYCLES_FPU((fpu_type >= FPU_487SX) ? (x87_timings.fsave) : (x87_timings.fsave * cpu_multi)); + CONCURRENCY_CYCLES((fpu_type >= FPU_487SX) ? (x87_concurrency.fsave) : (x87_concurrency.fsave * cpu_multi)); + return cpu_state.abrt; +} +#ifndef FPU_8087 +static int +sf_FNSAVE_a32(uint32_t fetchdat) +{ + floatx80 stn; + int offset; + + FP_ENTER(); + fetch_ea_32(fetchdat); + SEG_CHECK_WRITE(cpu_state.ea_seg); + offset = fpu_save_environment(); + /* save all registers in stack order. */ + for (int m = 0; m < 8; m++) { + stn = FPU_read_regi(m); + writememq(easeg, offset + (m * 10), stn.fraction); + writememw(easeg, offset + (m * 10) + 8, stn.exp); + } + +# ifdef FPU_8087 + fpu_state.swd = 0x3FF; +# else + fpu_state.cwd = 0x37F; +# endif + fpu_state.swd = 0; + fpu_state.tos = 0; + fpu_state.tag = 0xffff; + cpu_state.ismmx = 0; + fpu_state.foo = 0; + fpu_state.fds = 0; + fpu_state.fdp = 0; + fpu_state.fcs = 0; + fpu_state.fip = 0; + CLOCK_CYCLES_FPU((fpu_type >= FPU_487SX) ? (x87_timings.fsave) : (x87_timings.fsave * cpu_multi)); + CONCURRENCY_CYCLES((fpu_type >= FPU_487SX) ? (x87_concurrency.fsave) : (x87_concurrency.fsave * cpu_multi)); + return cpu_state.abrt; +} +#endif + +static int +sf_FNCLEX(uint32_t fetchdat) +{ + FP_ENTER(); + cpu_state.pc++; + fpu_state.swd &= ~(FPU_SW_Backward | FPU_SW_Summary | FPU_SW_Stack_Fault | FPU_SW_Precision | FPU_SW_Underflow | FPU_SW_Overflow | FPU_SW_Zero_Div | FPU_SW_Denormal_Op | FPU_SW_Invalid); + CLOCK_CYCLES_FPU((fpu_type >= FPU_487SX) ? (x87_timings.fnop) : (x87_timings.fnop * cpu_multi)); + CONCURRENCY_CYCLES((fpu_type >= FPU_487SX) ? (x87_concurrency.fnop) : (x87_concurrency.fnop * cpu_multi)); + return 0; +} + +static int +sf_FNINIT(uint32_t fetchdat) +{ + FP_ENTER(); + cpu_state.pc++; +#ifdef FPU_8087 + fpu_state.cwd = 0x3FF; +#else + fpu_state.cwd = 0x37F; +#endif + fpu_state.swd = 0; + fpu_state.tos = 0; + fpu_state.tag = 0xffff; + fpu_state.foo = 0; + fpu_state.fds = 0; + fpu_state.fdp = 0; + fpu_state.fcs = 0; + fpu_state.fip = 0; + cpu_state.ismmx = 0; + CLOCK_CYCLES_FPU((fpu_type >= FPU_487SX) ? (x87_timings.finit) : (x87_timings.finit * cpu_multi)); + CONCURRENCY_CYCLES((fpu_type >= FPU_487SX) ? (x87_concurrency.finit) : (x87_concurrency.finit * cpu_multi)); + CPU_BLOCK_END(); + return 0; +} + +static int +sf_FLDENV_a16(uint32_t fetchdat) +{ + int tag; + + FP_ENTER(); + fetch_ea_16(fetchdat); + SEG_CHECK_READ(cpu_state.ea_seg); + fpu_load_environment(); + /* read all registers in stack order and update x87 tag word */ + for (int n = 0; n < 8; n++) { + // update tag only if it is not empty + if (!IS_TAG_EMPTY(n)) { + tag = FPU_tagof(FPU_read_regi(n)); + FPU_settagi(tag, n); + } + } + CLOCK_CYCLES_FPU((fpu_type >= FPU_487SX) ? (x87_timings.fldenv) : (x87_timings.fldenv * cpu_multi)); + CONCURRENCY_CYCLES((fpu_type >= FPU_487SX) ? (x87_concurrency.fldenv) : (x87_concurrency.fldenv * cpu_multi)); + return cpu_state.abrt; +} +#ifndef FPU_8087 +static int +sf_FLDENV_a32(uint32_t fetchdat) +{ + int tag; + + FP_ENTER(); + fetch_ea_32(fetchdat); + SEG_CHECK_READ(cpu_state.ea_seg); + fpu_load_environment(); + /* read all registers in stack order and update x87 tag word */ + for (int n = 0; n < 8; n++) { + // update tag only if it is not empty + if (!IS_TAG_EMPTY(n)) { + tag = FPU_tagof(FPU_read_regi(n)); + FPU_settagi(tag, n); + } + } + CLOCK_CYCLES_FPU((fpu_type >= FPU_487SX) ? (x87_timings.fldenv) : (x87_timings.fldenv * cpu_multi)); + CONCURRENCY_CYCLES((fpu_type >= FPU_487SX) ? (x87_concurrency.fldenv) : (x87_concurrency.fldenv * cpu_multi)); + return cpu_state.abrt; +} +#endif + +static int +sf_FNSTENV_a16(uint32_t fetchdat) +{ + FP_ENTER(); + fetch_ea_16(fetchdat); + SEG_CHECK_WRITE(cpu_state.ea_seg); + fpu_save_environment(); + /* mask all floating point exceptions */ + fpu_state.cwd |= FPU_CW_Exceptions_Mask; + /* clear the B and ES bits in the status word */ + fpu_state.swd &= ~(FPU_SW_Backward | FPU_SW_Summary); + CLOCK_CYCLES_FPU((fpu_type >= FPU_487SX) ? (x87_timings.fstenv) : (x87_timings.fstenv * cpu_multi)); + CONCURRENCY_CYCLES((fpu_type >= FPU_487SX) ? (x87_concurrency.fstenv) : (x87_concurrency.fstenv * cpu_multi)); + return cpu_state.abrt; +} +#ifndef FPU_8087 +static int +sf_FNSTENV_a32(uint32_t fetchdat) +{ + FP_ENTER(); + fetch_ea_32(fetchdat); + SEG_CHECK_WRITE(cpu_state.ea_seg); + fpu_save_environment(); + /* mask all floating point exceptions */ + fpu_state.cwd |= FPU_CW_Exceptions_Mask; + /* clear the B and ES bits in the status word */ + fpu_state.swd &= ~(FPU_SW_Backward | FPU_SW_Summary); + CLOCK_CYCLES_FPU((fpu_type >= FPU_487SX) ? (x87_timings.fstenv) : (x87_timings.fstenv * cpu_multi)); + CONCURRENCY_CYCLES((fpu_type >= FPU_487SX) ? (x87_concurrency.fstenv) : (x87_concurrency.fstenv * cpu_multi)); + return cpu_state.abrt; +} +#endif + +static int +sf_FNOP(uint32_t fetchdat) +{ + FP_ENTER(); + cpu_state.pc++; + CLOCK_CYCLES_FPU((fpu_type >= FPU_487SX) ? (x87_timings.fnop) : (x87_timings.fnop * cpu_multi)); + CONCURRENCY_CYCLES((fpu_type >= FPU_487SX) ? (x87_concurrency.fnop) : (x87_concurrency.fnop * cpu_multi)); + return 0; +} diff --git a/src/cpu/x87_ops_sf_arith.h b/src/cpu/x87_ops_sf_arith.h new file mode 100644 index 000000000..5144062bb --- /dev/null +++ b/src/cpu/x87_ops_sf_arith.h @@ -0,0 +1,785 @@ +#define sf_FPU(name, optype, a_size, load_var, rw, use_var, is_nan, cycle_postfix) \ + static int sf_FADD##name##_a##a_size(uint32_t fetchdat) \ + { \ + floatx80 a, result; \ + struct float_status_t status; \ + optype temp; \ + FP_ENTER(); \ + FPU_check_pending_exceptions(); \ + fetch_ea_##a_size(fetchdat); \ + SEG_CHECK_READ(cpu_state.ea_seg); \ + load_var = rw; \ + if (cpu_state.abrt) \ + return 1; \ + clear_C1(); \ + if (IS_TAG_EMPTY(0)) { \ + FPU_stack_underflow(fetchdat, 0, 0); \ + goto next_ins; \ + } \ + status = i387cw_to_softfloat_status_word(i387_get_control_word()); \ + a = FPU_read_regi(0); \ + if (!is_nan) \ + result = floatx80_add(a, use_var, &status); \ + \ + if (!FPU_exception(fetchdat, status.float_exception_flags, 0)) \ + FPU_save_regi(result, 0); \ + \ +next_ins: \ + CLOCK_CYCLES_FPU((fpu_type >= FPU_487SX) ? (x87_timings.fadd##cycle_postfix) : ((x87_timings.fadd##cycle_postfix) * cpu_multi)); \ + CONCURRENCY_CYCLES((fpu_type >= FPU_487SX) ? (x87_concurrency.fadd##cycle_postfix) : ((x87_concurrency.fadd##cycle_postfix) * cpu_multi)); \ + return 0; \ + } \ + static int sf_FDIV##name##_a##a_size(uint32_t fetchdat) \ + { \ + floatx80 a, result; \ + struct float_status_t status; \ + optype temp; \ + FP_ENTER(); \ + FPU_check_pending_exceptions(); \ + fetch_ea_##a_size(fetchdat); \ + SEG_CHECK_READ(cpu_state.ea_seg); \ + load_var = rw; \ + if (cpu_state.abrt) \ + return 1; \ + clear_C1(); \ + if (IS_TAG_EMPTY(0)) { \ + FPU_stack_underflow(fetchdat, 0, 0); \ + goto next_ins; \ + } \ + status = i387cw_to_softfloat_status_word(i387_get_control_word()); \ + a = FPU_read_regi(0); \ + if (!is_nan) { \ + result = floatx80_div(a, use_var, &status); \ + } \ + if (!FPU_exception(fetchdat, status.float_exception_flags, 0)) \ + FPU_save_regi(result, 0); \ + \ +next_ins: \ + CLOCK_CYCLES_FPU((fpu_type >= FPU_487SX) ? (x87_timings.fdiv##cycle_postfix) : ((x87_timings.fdiv##cycle_postfix) * cpu_multi)); \ + CONCURRENCY_CYCLES((fpu_type >= FPU_487SX) ? (x87_concurrency.fadd##cycle_postfix) : ((x87_concurrency.fadd##cycle_postfix) * cpu_multi)); \ + return 0; \ + } \ + static int sf_FDIVR##name##_a##a_size(uint32_t fetchdat) \ + { \ + floatx80 a, result; \ + struct float_status_t status; \ + optype temp; \ + FP_ENTER(); \ + FPU_check_pending_exceptions(); \ + fetch_ea_##a_size(fetchdat); \ + SEG_CHECK_READ(cpu_state.ea_seg); \ + load_var = rw; \ + if (cpu_state.abrt) \ + return 1; \ + clear_C1(); \ + if (IS_TAG_EMPTY(0)) { \ + FPU_stack_underflow(fetchdat, 0, 0); \ + goto next_ins; \ + } \ + status = i387cw_to_softfloat_status_word(i387_get_control_word()); \ + a = FPU_read_regi(0); \ + if (!is_nan) { \ + result = floatx80_div(use_var, a, &status); \ + } \ + if (!FPU_exception(fetchdat, status.float_exception_flags, 0)) \ + FPU_save_regi(result, 0); \ + \ +next_ins: \ + CLOCK_CYCLES_FPU((fpu_type >= FPU_487SX) ? (x87_timings.fdiv##cycle_postfix) : ((x87_timings.fdiv##cycle_postfix) * cpu_multi)); \ + CONCURRENCY_CYCLES((fpu_type >= FPU_487SX) ? (x87_concurrency.fdiv##cycle_postfix) : ((x87_concurrency.fdiv##cycle_postfix) * cpu_multi)); \ + return 0; \ + } \ + static int sf_FMUL##name##_a##a_size(uint32_t fetchdat) \ + { \ + floatx80 a, result; \ + struct float_status_t status; \ + optype temp; \ + FP_ENTER(); \ + FPU_check_pending_exceptions(); \ + fetch_ea_##a_size(fetchdat); \ + SEG_CHECK_READ(cpu_state.ea_seg); \ + load_var = rw; \ + if (cpu_state.abrt) \ + return 1; \ + clear_C1(); \ + if (IS_TAG_EMPTY(0)) { \ + FPU_stack_underflow(fetchdat, 0, 0); \ + goto next_ins; \ + } \ + status = i387cw_to_softfloat_status_word(i387_get_control_word()); \ + a = FPU_read_regi(0); \ + if (!is_nan) { \ + result = floatx80_mul(a, use_var, &status); \ + } \ + if (!FPU_exception(fetchdat, status.float_exception_flags, 0)) \ + FPU_save_regi(result, 0); \ + \ +next_ins: \ + CLOCK_CYCLES_FPU((fpu_type >= FPU_487SX) ? (x87_timings.fmul##cycle_postfix) : ((x87_timings.fmul##cycle_postfix) * cpu_multi)); \ + CONCURRENCY_CYCLES((fpu_type >= FPU_487SX) ? (x87_concurrency.fmul##cycle_postfix) : ((x87_concurrency.fmul##cycle_postfix) * cpu_multi)); \ + return 0; \ + } \ + static int sf_FSUB##name##_a##a_size(uint32_t fetchdat) \ + { \ + floatx80 a, result; \ + struct float_status_t status; \ + optype temp; \ + FP_ENTER(); \ + FPU_check_pending_exceptions(); \ + fetch_ea_##a_size(fetchdat); \ + SEG_CHECK_READ(cpu_state.ea_seg); \ + load_var = rw; \ + if (cpu_state.abrt) \ + return 1; \ + clear_C1(); \ + if (IS_TAG_EMPTY(0)) { \ + FPU_stack_underflow(fetchdat, 0, 0); \ + goto next_ins; \ + } \ + status = i387cw_to_softfloat_status_word(i387_get_control_word()); \ + a = FPU_read_regi(0); \ + if (!is_nan) \ + result = floatx80_sub(a, use_var, &status); \ + \ + if (!FPU_exception(fetchdat, status.float_exception_flags, 0)) \ + FPU_save_regi(result, 0); \ + \ +next_ins: \ + CLOCK_CYCLES_FPU((fpu_type >= FPU_487SX) ? (x87_timings.fadd##cycle_postfix) : ((x87_timings.fadd##cycle_postfix) * cpu_multi)); \ + CONCURRENCY_CYCLES((fpu_type >= FPU_487SX) ? (x87_concurrency.fadd##cycle_postfix) : ((x87_concurrency.fadd##cycle_postfix) * cpu_multi)); \ + return 0; \ + } \ + static int sf_FSUBR##name##_a##a_size(uint32_t fetchdat) \ + { \ + floatx80 a, result; \ + struct float_status_t status; \ + optype temp; \ + FP_ENTER(); \ + FPU_check_pending_exceptions(); \ + fetch_ea_##a_size(fetchdat); \ + SEG_CHECK_READ(cpu_state.ea_seg); \ + load_var = rw; \ + if (cpu_state.abrt) \ + return 1; \ + clear_C1(); \ + if (IS_TAG_EMPTY(0)) { \ + FPU_stack_underflow(fetchdat, 0, 0); \ + goto next_ins; \ + } \ + status = i387cw_to_softfloat_status_word(i387_get_control_word()); \ + a = FPU_read_regi(0); \ + if (!is_nan) \ + result = floatx80_sub(use_var, a, &status); \ + \ + if (!FPU_exception(fetchdat, status.float_exception_flags, 0)) \ + FPU_save_regi(result, 0); \ + \ +next_ins: \ + CLOCK_CYCLES_FPU((fpu_type >= FPU_487SX) ? (x87_timings.fadd##cycle_postfix) : ((x87_timings.fadd##cycle_postfix) * cpu_multi)); \ + CONCURRENCY_CYCLES((fpu_type >= FPU_487SX) ? (x87_concurrency.fadd##cycle_postfix) : ((x87_concurrency.fadd##cycle_postfix) * cpu_multi)); \ + return 0; \ + } + +// clang-format off +sf_FPU(s, float32, 16, temp, geteal(), float32_to_floatx80(temp, &status), FPU_handle_NaN32(a, temp, &result, &status), _32) +#ifndef FPU_8087 +sf_FPU(s, float32, 32, temp, geteal(), float32_to_floatx80(temp, &status), FPU_handle_NaN32(a, temp, &result, &status), _32) +#endif +sf_FPU(d, float64, 16, temp, geteaq(), float64_to_floatx80(temp, &status), FPU_handle_NaN64(a, temp, &result, &status), _64) +#ifndef FPU_8087 +sf_FPU(d, float64, 32, temp, geteaq(), float64_to_floatx80(temp, &status), FPU_handle_NaN64(a, temp, &result, &status), _64) +#endif + +sf_FPU(iw, uint16_t, 16, temp, geteaw(), int32_to_floatx80((int16_t)temp), 0, _i16) +#ifndef FPU_8087 +sf_FPU(iw, uint16_t, 32, temp, geteaw(), int32_to_floatx80((int16_t)temp), 0, _i16) +#endif +sf_FPU(il, uint32_t, 16, temp, geteal(), int32_to_floatx80((int32_t)temp), 0, _i32) +#ifndef FPU_8087 +sf_FPU(il, uint32_t, 32, temp, geteal(), int32_to_floatx80((int32_t)temp), 0, _i32) +#endif + // clang-format on + + static int sf_FADD_st0_stj(uint32_t fetchdat) +{ + floatx80 a; + floatx80 b; + floatx80 result; + struct float_status_t status; + + FP_ENTER(); + FPU_check_pending_exceptions(); + cpu_state.pc++; + clear_C1(); + if (IS_TAG_EMPTY(0) || IS_TAG_EMPTY(fetchdat & 7)) { + FPU_stack_underflow(fetchdat, 0, 0); + goto next_ins; + } + status = i387cw_to_softfloat_status_word(i387_get_control_word()); + a = FPU_read_regi(0); + b = FPU_read_regi(fetchdat & 7); + result = floatx80_add(a, b, &status); + + if (!FPU_exception(fetchdat, status.float_exception_flags, 0)) + FPU_save_regi(result, 0); + +next_ins: + CLOCK_CYCLES_FPU((fpu_type >= FPU_487SX) ? (x87_timings.fadd) : (x87_timings.fadd * cpu_multi)); + CONCURRENCY_CYCLES((fpu_type >= FPU_487SX) ? (x87_concurrency.fadd) : (x87_concurrency.fadd * cpu_multi)); + return 0; +} +static int +sf_FADD_sti_st0(uint32_t fetchdat) +{ + floatx80 a; + floatx80 b; + floatx80 result; + struct float_status_t status; + + FP_ENTER(); + FPU_check_pending_exceptions(); + cpu_state.pc++; + clear_C1(); + if (IS_TAG_EMPTY(0) || IS_TAG_EMPTY(fetchdat & 7)) { + FPU_stack_underflow(fetchdat, fetchdat & 7, 0); + goto next_ins; + } + status = i387cw_to_softfloat_status_word(i387_get_control_word()); + a = FPU_read_regi(fetchdat & 7); + b = FPU_read_regi(0); + result = floatx80_add(a, b, &status); + + if (!FPU_exception(fetchdat, status.float_exception_flags, 0)) + FPU_save_regi(result, fetchdat & 7); + +next_ins: + CLOCK_CYCLES_FPU((fpu_type >= FPU_487SX) ? (x87_timings.fadd) : (x87_timings.fadd * cpu_multi)); + CONCURRENCY_CYCLES((fpu_type >= FPU_487SX) ? (x87_concurrency.fadd) : (x87_concurrency.fadd * cpu_multi)); + return 0; +} + +static int +sf_FADDP_sti_st0(uint32_t fetchdat) +{ + floatx80 a; + floatx80 b; + floatx80 result; + struct float_status_t status; + + FP_ENTER(); + FPU_check_pending_exceptions(); + cpu_state.pc++; + clear_C1(); + if (IS_TAG_EMPTY(0) || IS_TAG_EMPTY(fetchdat & 7)) { + FPU_stack_underflow(fetchdat, fetchdat & 7, 1); + goto next_ins; + } + status = i387cw_to_softfloat_status_word(i387_get_control_word()); + a = FPU_read_regi(fetchdat & 7); + b = FPU_read_regi(0); + result = floatx80_add(a, b, &status); + + if (!FPU_exception(fetchdat, status.float_exception_flags, 0)) { + FPU_save_regi(result, fetchdat & 7); + FPU_pop(); + } + +next_ins: + CLOCK_CYCLES_FPU((fpu_type >= FPU_487SX) ? (x87_timings.fadd) : (x87_timings.fadd * cpu_multi)); + CONCURRENCY_CYCLES((fpu_type >= FPU_487SX) ? (x87_concurrency.fadd) : (x87_concurrency.fadd * cpu_multi)); + return 0; +} + +static int +sf_FDIV_st0_stj(uint32_t fetchdat) +{ + floatx80 a; + floatx80 b; + floatx80 result; + struct float_status_t status; + + FP_ENTER(); + cpu_state.pc++; + clear_C1(); + if (IS_TAG_EMPTY(0) || IS_TAG_EMPTY(fetchdat & 7)) { + FPU_stack_underflow(fetchdat, 0, 0); + goto next_ins; + } + status = i387cw_to_softfloat_status_word(i387_get_control_word()); + a = FPU_read_regi(0); + b = FPU_read_regi(fetchdat & 7); + result = floatx80_div(a, b, &status); + + if (!FPU_exception(fetchdat, status.float_exception_flags, 0)) + FPU_save_regi(result, 0); + +next_ins: + CLOCK_CYCLES_FPU((fpu_type >= FPU_487SX) ? (x87_timings.fdiv) : (x87_timings.fdiv * cpu_multi)); + CONCURRENCY_CYCLES((fpu_type >= FPU_487SX) ? (x87_concurrency.fdiv) : (x87_concurrency.fdiv * cpu_multi)); + return 0; +} + +static int +sf_FDIV_sti_st0(uint32_t fetchdat) +{ + floatx80 a; + floatx80 b; + floatx80 result; + struct float_status_t status; + + FP_ENTER(); + cpu_state.pc++; + clear_C1(); + if (IS_TAG_EMPTY(0) || IS_TAG_EMPTY(fetchdat & 7)) { + FPU_stack_underflow(fetchdat, fetchdat & 7, 0); + goto next_ins; + } + status = i387cw_to_softfloat_status_word(i387_get_control_word()); + a = FPU_read_regi(fetchdat & 7); + b = FPU_read_regi(0); + result = floatx80_div(a, b, &status); + + if (!FPU_exception(fetchdat, status.float_exception_flags, 0)) + FPU_save_regi(result, fetchdat & 7); + +next_ins: + CLOCK_CYCLES_FPU((fpu_type >= FPU_487SX) ? (x87_timings.fdiv) : (x87_timings.fdiv * cpu_multi)); + CONCURRENCY_CYCLES((fpu_type >= FPU_487SX) ? (x87_concurrency.fdiv) : (x87_concurrency.fdiv * cpu_multi)); + return 0; +} +static int +sf_FDIVP_sti_st0(uint32_t fetchdat) +{ + floatx80 a; + floatx80 b; + floatx80 result; + struct float_status_t status; + + FP_ENTER(); + cpu_state.pc++; + clear_C1(); + if (IS_TAG_EMPTY(0) || IS_TAG_EMPTY(fetchdat & 7)) { + FPU_stack_underflow(fetchdat, fetchdat & 7, 1); + goto next_ins; + } + status = i387cw_to_softfloat_status_word(i387_get_control_word()); + a = FPU_read_regi(fetchdat & 7); + b = FPU_read_regi(0); + result = floatx80_div(a, b, &status); + + if (!FPU_exception(fetchdat, status.float_exception_flags, 0)) { + FPU_save_regi(result, fetchdat & 7); + FPU_pop(); + } + +next_ins: + CLOCK_CYCLES_FPU((fpu_type >= FPU_487SX) ? (x87_timings.fdiv) : (x87_timings.fdiv * cpu_multi)); + CONCURRENCY_CYCLES((fpu_type >= FPU_487SX) ? (x87_concurrency.fdiv) : (x87_concurrency.fdiv * cpu_multi)); + return 0; +} + +static int +sf_FDIVR_st0_stj(uint32_t fetchdat) +{ + floatx80 a; + floatx80 b; + floatx80 result; + struct float_status_t status; + + FP_ENTER(); + cpu_state.pc++; + clear_C1(); + if (IS_TAG_EMPTY(0) || IS_TAG_EMPTY(fetchdat & 7)) { + FPU_stack_underflow(fetchdat, 0, 0); + goto next_ins; + } + status = i387cw_to_softfloat_status_word(i387_get_control_word()); + a = FPU_read_regi(fetchdat & 7); + b = FPU_read_regi(0); + result = floatx80_div(a, b, &status); + + if (!FPU_exception(fetchdat, status.float_exception_flags, 0)) + FPU_save_regi(result, 0); + +next_ins: + CLOCK_CYCLES_FPU((fpu_type >= FPU_487SX) ? (x87_timings.fdiv) : (x87_timings.fdiv * cpu_multi)); + CONCURRENCY_CYCLES((fpu_type >= FPU_487SX) ? (x87_concurrency.fdiv) : (x87_concurrency.fdiv * cpu_multi)); + return 0; +} +static int +sf_FDIVR_sti_st0(uint32_t fetchdat) +{ + floatx80 a; + floatx80 b; + floatx80 result; + struct float_status_t status; + + FP_ENTER(); + cpu_state.pc++; + clear_C1(); + if (IS_TAG_EMPTY(0) || IS_TAG_EMPTY(fetchdat & 7)) { + FPU_stack_underflow(fetchdat, fetchdat & 7, 0); + goto next_ins; + } + status = i387cw_to_softfloat_status_word(i387_get_control_word()); + a = FPU_read_regi(0); + b = FPU_read_regi(fetchdat & 7); + result = floatx80_div(a, b, &status); + + if (!FPU_exception(fetchdat, status.float_exception_flags, 0)) + FPU_save_regi(result, fetchdat & 7); + +next_ins: + CLOCK_CYCLES_FPU((fpu_type >= FPU_487SX) ? (x87_timings.fdiv) : (x87_timings.fdiv * cpu_multi)); + CONCURRENCY_CYCLES((fpu_type >= FPU_487SX) ? (x87_concurrency.fdiv) : (x87_concurrency.fdiv * cpu_multi)); + return 0; +} +static int +sf_FDIVRP_sti_st0(uint32_t fetchdat) +{ + floatx80 a; + floatx80 b; + floatx80 result; + struct float_status_t status; + + FP_ENTER(); + cpu_state.pc++; + clear_C1(); + if (IS_TAG_EMPTY(0) || IS_TAG_EMPTY(fetchdat & 7)) { + FPU_stack_underflow(fetchdat, fetchdat & 7, 1); + goto next_ins; + } + status = i387cw_to_softfloat_status_word(i387_get_control_word()); + a = FPU_read_regi(0); + b = FPU_read_regi(fetchdat & 7); + result = floatx80_div(a, b, &status); + + if (!FPU_exception(fetchdat, status.float_exception_flags, 0)) { + FPU_save_regi(result, fetchdat & 7); + FPU_pop(); + } + +next_ins: + CLOCK_CYCLES_FPU((fpu_type >= FPU_487SX) ? (x87_timings.fdiv) : (x87_timings.fdiv * cpu_multi)); + CONCURRENCY_CYCLES((fpu_type >= FPU_487SX) ? (x87_concurrency.fdiv) : (x87_concurrency.fdiv * cpu_multi)); + return 0; +} + +static int +sf_FMUL_st0_stj(uint32_t fetchdat) +{ + floatx80 a; + floatx80 b; + floatx80 result; + struct float_status_t status; + + FP_ENTER(); + cpu_state.pc++; + clear_C1(); + if (IS_TAG_EMPTY(0) || IS_TAG_EMPTY(fetchdat & 7)) { + FPU_stack_underflow(fetchdat, 0, 0); + goto next_ins; + } + status = i387cw_to_softfloat_status_word(i387_get_control_word()); + a = FPU_read_regi(0); + b = FPU_read_regi(fetchdat & 7); + result = floatx80_mul(a, b, &status); + + if (!FPU_exception(fetchdat, status.float_exception_flags, 0)) { + FPU_save_regi(result, 0); + } + +next_ins: + CLOCK_CYCLES_FPU((fpu_type >= FPU_487SX) ? (x87_timings.fmul) : (x87_timings.fmul * cpu_multi)); + CONCURRENCY_CYCLES((fpu_type >= FPU_487SX) ? (x87_concurrency.fmul) : (x87_concurrency.fmul * cpu_multi)); + return 0; +} +static int +sf_FMUL_sti_st0(uint32_t fetchdat) +{ + floatx80 a; + floatx80 b; + floatx80 result; + struct float_status_t status; + + FP_ENTER(); + cpu_state.pc++; + clear_C1(); + if (IS_TAG_EMPTY(0) || IS_TAG_EMPTY(fetchdat & 7)) { + FPU_stack_underflow(fetchdat, fetchdat & 7, 0); + goto next_ins; + } + status = i387cw_to_softfloat_status_word(i387_get_control_word()); + a = FPU_read_regi(0); + b = FPU_read_regi(fetchdat & 7); + result = floatx80_mul(a, b, &status); + + if (!FPU_exception(fetchdat, status.float_exception_flags, 0)) { + FPU_save_regi(result, fetchdat & 7); + } + +next_ins: + CLOCK_CYCLES_FPU((fpu_type >= FPU_487SX) ? (x87_timings.fmul) : (x87_timings.fmul * cpu_multi)); + CONCURRENCY_CYCLES((fpu_type >= FPU_487SX) ? (x87_concurrency.fmul) : (x87_concurrency.fmul * cpu_multi)); + return 0; +} +static int +sf_FMULP_sti_st0(uint32_t fetchdat) +{ + floatx80 a; + floatx80 b; + floatx80 result; + struct float_status_t status; + + FP_ENTER(); + cpu_state.pc++; + clear_C1(); + if (IS_TAG_EMPTY(0) || IS_TAG_EMPTY(fetchdat & 7)) { + FPU_stack_underflow(fetchdat, fetchdat & 7, 1); + goto next_ins; + } + status = i387cw_to_softfloat_status_word(i387_get_control_word()); + a = FPU_read_regi(fetchdat & 7); + b = FPU_read_regi(0); + result = floatx80_mul(a, b, &status); + + if (!FPU_exception(fetchdat, status.float_exception_flags, 0)) { + FPU_save_regi(result, fetchdat & 7); + FPU_pop(); + } + +next_ins: + CLOCK_CYCLES_FPU((fpu_type >= FPU_487SX) ? (x87_timings.fmul) : (x87_timings.fmul * cpu_multi)); + CONCURRENCY_CYCLES((fpu_type >= FPU_487SX) ? (x87_concurrency.fmul) : (x87_concurrency.fmul * cpu_multi)); + return 0; +} + +static int +sf_FSUB_st0_stj(uint32_t fetchdat) +{ + floatx80 a; + floatx80 b; + floatx80 result; + struct float_status_t status; + + FP_ENTER(); + cpu_state.pc++; + clear_C1(); + if (IS_TAG_EMPTY(0) || IS_TAG_EMPTY(fetchdat & 7)) { + FPU_stack_underflow(fetchdat, 0, 0); + goto next_ins; + } + status = i387cw_to_softfloat_status_word(i387_get_control_word()); + a = FPU_read_regi(0); + b = FPU_read_regi(fetchdat & 7); + result = floatx80_sub(a, b, &status); + + if (!FPU_exception(fetchdat, status.float_exception_flags, 0)) { + FPU_save_regi(result, 0); + } + +next_ins: + CLOCK_CYCLES_FPU((fpu_type >= FPU_487SX) ? (x87_timings.fadd) : (x87_timings.fadd * cpu_multi)); + CONCURRENCY_CYCLES((fpu_type >= FPU_487SX) ? (x87_concurrency.fadd) : (x87_concurrency.fadd * cpu_multi)); + return 0; +} +static int +sf_FSUB_sti_st0(uint32_t fetchdat) +{ + floatx80 a; + floatx80 b; + floatx80 result; + struct float_status_t status; + + FP_ENTER(); + cpu_state.pc++; + clear_C1(); + if (IS_TAG_EMPTY(0) || IS_TAG_EMPTY(fetchdat & 7)) { + FPU_stack_underflow(fetchdat, fetchdat & 7, 0); + goto next_ins; + } + status = i387cw_to_softfloat_status_word(i387_get_control_word()); + a = FPU_read_regi(fetchdat & 7); + b = FPU_read_regi(0); + result = floatx80_sub(a, b, &status); + + if (!FPU_exception(fetchdat, status.float_exception_flags, 0)) { + FPU_save_regi(result, fetchdat & 7); + } + +next_ins: + CLOCK_CYCLES_FPU((fpu_type >= FPU_487SX) ? (x87_timings.fadd) : (x87_timings.fadd * cpu_multi)); + CONCURRENCY_CYCLES((fpu_type >= FPU_487SX) ? (x87_concurrency.fadd) : (x87_concurrency.fadd * cpu_multi)); + return 0; +} +static int +sf_FSUBP_sti_st0(uint32_t fetchdat) +{ + floatx80 a; + floatx80 b; + floatx80 result; + struct float_status_t status; + + FP_ENTER(); + cpu_state.pc++; + clear_C1(); + if (IS_TAG_EMPTY(0) || IS_TAG_EMPTY(fetchdat & 7)) { + FPU_stack_underflow(fetchdat, fetchdat & 7, 1); + goto next_ins; + } + status = i387cw_to_softfloat_status_word(i387_get_control_word()); + a = FPU_read_regi(fetchdat & 7); + b = FPU_read_regi(0); + result = floatx80_sub(a, b, &status); + + if (!FPU_exception(fetchdat, status.float_exception_flags, 0)) { + FPU_save_regi(result, fetchdat & 7); + FPU_pop(); + } + +next_ins: + CLOCK_CYCLES_FPU((fpu_type >= FPU_487SX) ? (x87_timings.fadd) : (x87_timings.fadd * cpu_multi)); + CONCURRENCY_CYCLES((fpu_type >= FPU_487SX) ? (x87_concurrency.fadd) : (x87_concurrency.fadd * cpu_multi)); + return 0; +} + +static int +sf_FSUBR_st0_stj(uint32_t fetchdat) +{ + floatx80 a; + floatx80 b; + floatx80 result; + struct float_status_t status; + + FP_ENTER(); + cpu_state.pc++; + clear_C1(); + if (IS_TAG_EMPTY(0) || IS_TAG_EMPTY(fetchdat & 7)) { + FPU_stack_underflow(fetchdat, 0, 0); + goto next_ins; + } + status = i387cw_to_softfloat_status_word(i387_get_control_word()); + a = FPU_read_regi(fetchdat & 7); + b = FPU_read_regi(0); + result = floatx80_sub(a, b, &status); + + if (!FPU_exception(fetchdat, status.float_exception_flags, 0)) { + FPU_save_regi(result, 0); + } + +next_ins: + CLOCK_CYCLES_FPU((fpu_type >= FPU_487SX) ? (x87_timings.fadd) : (x87_timings.fadd * cpu_multi)); + CONCURRENCY_CYCLES((fpu_type >= FPU_487SX) ? (x87_concurrency.fadd) : (x87_concurrency.fadd * cpu_multi)); + return 0; +} +static int +sf_FSUBR_sti_st0(uint32_t fetchdat) +{ + floatx80 a; + floatx80 b; + floatx80 result; + struct float_status_t status; + + FP_ENTER(); + cpu_state.pc++; + clear_C1(); + if (IS_TAG_EMPTY(0) || IS_TAG_EMPTY(fetchdat & 7)) { + FPU_stack_underflow(fetchdat, fetchdat & 7, 0); + goto next_ins; + } + status = i387cw_to_softfloat_status_word(i387_get_control_word()); + a = FPU_read_regi(0); + b = FPU_read_regi(fetchdat & 7); + result = floatx80_sub(a, b, &status); + + if (!FPU_exception(fetchdat, status.float_exception_flags, 0)) { + FPU_save_regi(result, fetchdat & 7); + } + +next_ins: + CLOCK_CYCLES_FPU((fpu_type >= FPU_487SX) ? (x87_timings.fadd) : (x87_timings.fadd * cpu_multi)); + CONCURRENCY_CYCLES((fpu_type >= FPU_487SX) ? (x87_concurrency.fadd) : (x87_concurrency.fadd * cpu_multi)); + return 0; +} +static int +sf_FSUBRP_sti_st0(uint32_t fetchdat) +{ + floatx80 a; + floatx80 b; + floatx80 result; + struct float_status_t status; + + FP_ENTER(); + cpu_state.pc++; + clear_C1(); + if (IS_TAG_EMPTY(0) || IS_TAG_EMPTY(fetchdat & 7)) { + FPU_stack_underflow(fetchdat, fetchdat & 7, 1); + goto next_ins; + } + status = i387cw_to_softfloat_status_word(i387_get_control_word()); + a = FPU_read_regi(0); + b = FPU_read_regi(fetchdat & 7); + result = floatx80_sub(a, b, &status); + + if (!FPU_exception(fetchdat, status.float_exception_flags, 0)) { + FPU_save_regi(result, fetchdat & 7); + FPU_pop(); + } + +next_ins: + CLOCK_CYCLES_FPU((fpu_type >= FPU_487SX) ? (x87_timings.fadd) : (x87_timings.fadd * cpu_multi)); + CONCURRENCY_CYCLES((fpu_type >= FPU_487SX) ? (x87_concurrency.fadd) : (x87_concurrency.fadd * cpu_multi)); + return 0; +} + +static int +sf_FSQRT(uint32_t fetchdat) +{ + floatx80 result; + struct float_status_t status; + + FP_ENTER(); + cpu_state.pc++; + clear_C1(); + if (IS_TAG_EMPTY(0)) { + FPU_stack_underflow(fetchdat, 0, 0); + goto next_ins; + } + status = i387cw_to_softfloat_status_word(i387_get_control_word()); + result = floatx80_sqrt(FPU_read_regi(0), &status); + + if (!FPU_exception(fetchdat, status.float_exception_flags, 0)) { + FPU_save_regi(result, 0); + } + +next_ins: + CLOCK_CYCLES_FPU((fpu_type >= FPU_487SX) ? (x87_timings.fsqrt) : (x87_timings.fsqrt * cpu_multi)); + CONCURRENCY_CYCLES((fpu_type >= FPU_487SX) ? (x87_concurrency.fsqrt) : (x87_concurrency.fsqrt * cpu_multi)); + return 0; +} + +static int +sf_FRNDINT(uint32_t fetchdat) +{ + floatx80 result; + struct float_status_t status; + + FP_ENTER(); + cpu_state.pc++; + clear_C1(); + if (IS_TAG_EMPTY(0)) { + FPU_stack_underflow(fetchdat, 0, 0); + goto next_ins; + } + status = i387cw_to_softfloat_status_word(i387_get_control_word()); + result = floatx80_round_to_int(FPU_read_regi(0), &status); + + if (!FPU_exception(fetchdat, status.float_exception_flags, 0)) { + FPU_save_regi(result, 0); + } + +next_ins: + CLOCK_CYCLES_FPU((fpu_type >= FPU_487SX) ? (x87_timings.frndint) : (x87_timings.frndint * cpu_multi)); + CONCURRENCY_CYCLES((fpu_type >= FPU_487SX) ? (x87_concurrency.frndint) : (x87_concurrency.frndint * cpu_multi)); + return 0; +} diff --git a/src/cpu/x87_ops_sf_compare.h b/src/cpu/x87_ops_sf_compare.h new file mode 100644 index 000000000..6b4c1cb62 --- /dev/null +++ b/src/cpu/x87_ops_sf_compare.h @@ -0,0 +1,502 @@ +#define cmp_FPU(name, optype, a_size, load_var, rw, use_var, is_nan, cycle_postfix) \ + static int sf_FCOM##name##_a##a_size(uint32_t fetchdat) \ + { \ + floatx80 a; \ + int rc; \ + struct float_status_t status; \ + optype temp; \ + FP_ENTER(); \ + fetch_ea_##a_size(fetchdat); \ + SEG_CHECK_READ(cpu_state.ea_seg); \ + load_var = rw; \ + if (cpu_state.abrt) \ + return 1; \ + clear_C1(); \ + if (IS_TAG_EMPTY(0)) { \ + FPU_exception(fetchdat, FPU_EX_Stack_Underflow, 0); \ + setcc(C0 | C2 | C3); \ + goto next_ins; \ + } \ + status = i387cw_to_softfloat_status_word(i387_get_control_word()); \ + a = FPU_read_regi(0); \ + if (is_nan) { \ + rc = float_relation_unordered; \ + float_raise(&status, float_flag_invalid); \ + } else { \ + rc = floatx80_compare_two(a, use_var, &status); \ + } \ + setcc(FPU_status_word_flags_fpu_compare(rc)); \ + FPU_exception(fetchdat, status.float_exception_flags, 0); \ + \ +next_ins: \ + CLOCK_CYCLES_FPU((fpu_type >= FPU_487SX) ? (x87_timings.fcom##cycle_postfix) : ((x87_timings.fcom##cycle_postfix) * cpu_multi)); \ + CONCURRENCY_CYCLES((fpu_type >= FPU_487SX) ? (x87_concurrency.fcom##cycle_postfix) : ((x87_concurrency.fcom##cycle_postfix) * cpu_multi)); \ + return 0; \ + } \ + static int sf_FCOMP##name##_a##a_size(uint32_t fetchdat) \ + { \ + floatx80 a; \ + int rc; \ + struct float_status_t status; \ + optype temp; \ + FP_ENTER(); \ + fetch_ea_##a_size(fetchdat); \ + SEG_CHECK_READ(cpu_state.ea_seg); \ + load_var = rw; \ + if (cpu_state.abrt) \ + return 1; \ + clear_C1(); \ + if (IS_TAG_EMPTY(0)) { \ + FPU_exception(fetchdat, FPU_EX_Stack_Underflow, 0); \ + setcc(C0 | C2 | C3); \ + if (is_IA_masked()) \ + FPU_pop(); \ + \ + goto next_ins; \ + } \ + status = i387cw_to_softfloat_status_word(i387_get_control_word()); \ + a = FPU_read_regi(0); \ + if (is_nan) { \ + rc = float_relation_unordered; \ + float_raise(&status, float_flag_invalid); \ + } else { \ + rc = floatx80_compare_two(a, use_var, &status); \ + } \ + setcc(FPU_status_word_flags_fpu_compare(rc)); \ + if (!FPU_exception(fetchdat, status.float_exception_flags, 0)) \ + FPU_pop(); \ + \ +next_ins: \ + CLOCK_CYCLES_FPU((fpu_type >= FPU_487SX) ? (x87_timings.fcom##cycle_postfix) : ((x87_timings.fcom##cycle_postfix) * cpu_multi)); \ + CONCURRENCY_CYCLES((fpu_type >= FPU_487SX) ? (x87_concurrency.fcom##cycle_postfix) : ((x87_concurrency.fcom##cycle_postfix) * cpu_multi)); \ + return 0; \ + } + +// clang-format off +cmp_FPU(s, float32, 16, temp, geteal(), float32_to_floatx80(temp, &status), floatx80_is_nan(a) || floatx80_is_unsupported(a) || float32_is_nan(temp), _32) +#ifndef FPU_8087 +cmp_FPU(s, float32, 32, temp, geteal(), float32_to_floatx80(temp, &status), floatx80_is_nan(a) || floatx80_is_unsupported(a) || float32_is_nan(temp), _32) +#endif +cmp_FPU(d, float64, 16, temp, geteaq(), float64_to_floatx80(temp, &status), floatx80_is_nan(a) || floatx80_is_unsupported(a) || float64_is_nan(temp), _64) +#ifndef FPU_8087 +cmp_FPU(d, float64, 32, temp, geteaq(), float64_to_floatx80(temp, &status), floatx80_is_nan(a) || floatx80_is_unsupported(a) || float64_is_nan(temp), _64) +#endif + +cmp_FPU(iw, int16_t, 16, temp, (int16_t)geteaw(), int32_to_floatx80((int32_t)temp), 0, _i16) +#ifndef FPU_8087 +cmp_FPU(iw, int16_t, 32, temp, (int16_t)geteaw(), int32_to_floatx80((int32_t)temp), 0, _i16) +#endif +cmp_FPU(il, int32_t, 16, temp, (int32_t)geteal(), int32_to_floatx80(temp), 0, _i32) +#ifndef FPU_8087 +cmp_FPU(il, int32_t, 32, temp, (int32_t)geteal(), int32_to_floatx80(temp), 0, _i32) +#endif + // clang-format on + + static int sf_FCOM_sti(uint32_t fetchdat) +{ + floatx80 a; + floatx80 b; + struct float_status_t status; + int rc; + + FP_ENTER(); + cpu_state.pc++; + clear_C1(); + if (IS_TAG_EMPTY(0) || IS_TAG_EMPTY(fetchdat & 7)) { + FPU_exception(fetchdat, FPU_EX_Stack_Underflow, 0); + setcc(C0 | C2 | C3); + goto next_ins; + } + status = i387cw_to_softfloat_status_word(i387_get_control_word()); + a = FPU_read_regi(0); + b = FPU_read_regi(fetchdat & 7); + rc = floatx80_compare_two(a, b, &status); + setcc(FPU_status_word_flags_fpu_compare(rc)); + FPU_exception(fetchdat, status.float_exception_flags, 0); + +next_ins: + CLOCK_CYCLES_FPU((fpu_type >= FPU_487SX) ? (x87_timings.fcom) : (x87_timings.fcom * cpu_multi)); + CONCURRENCY_CYCLES((fpu_type >= FPU_487SX) ? (x87_concurrency.fcom) : (x87_concurrency.fcom * cpu_multi)); + return 0; +} + +static int +sf_FCOMP_sti(uint32_t fetchdat) +{ + floatx80 a; + floatx80 b; + struct float_status_t status; + int rc; + + FP_ENTER(); + cpu_state.pc++; + clear_C1(); + if (IS_TAG_EMPTY(0) || IS_TAG_EMPTY(fetchdat & 7)) { + FPU_exception(fetchdat, FPU_EX_Stack_Underflow, 0); + setcc(C0 | C2 | C3); + if (is_IA_masked()) { + FPU_pop(); + } + goto next_ins; + } + status = i387cw_to_softfloat_status_word(i387_get_control_word()); + a = FPU_read_regi(0); + b = FPU_read_regi(fetchdat & 7); + rc = floatx80_compare_two(a, b, &status); + setcc(FPU_status_word_flags_fpu_compare(rc)); + if (!FPU_exception(fetchdat, status.float_exception_flags, 0)) { + FPU_pop(); + } + +next_ins: + CLOCK_CYCLES_FPU((fpu_type >= FPU_487SX) ? (x87_timings.fcom) : (x87_timings.fcom * cpu_multi)); + CONCURRENCY_CYCLES((fpu_type >= FPU_487SX) ? (x87_concurrency.fcom) : (x87_concurrency.fcom * cpu_multi)); + return 0; +} + +static int +sf_FCOMPP(uint32_t fetchdat) +{ + floatx80 a; + floatx80 b; + struct float_status_t status; + int rc; + + FP_ENTER(); + cpu_state.pc++; + clear_C1(); + if (IS_TAG_EMPTY(0) || IS_TAG_EMPTY(1)) { + FPU_exception(fetchdat, FPU_EX_Stack_Underflow, 0); + setcc(C0 | C2 | C3); + if (is_IA_masked()) { + FPU_pop(); + FPU_pop(); + } + goto next_ins; + } + status = i387cw_to_softfloat_status_word(i387_get_control_word()); + a = FPU_read_regi(0); + b = FPU_read_regi(1); + rc = floatx80_compare_two(a, b, &status); + setcc(FPU_status_word_flags_fpu_compare(rc)); + if (!FPU_exception(fetchdat, status.float_exception_flags, 0)) { + FPU_pop(); + FPU_pop(); + } + +next_ins: + CLOCK_CYCLES_FPU((fpu_type >= FPU_487SX) ? (x87_timings.fcom) : (x87_timings.fcom * cpu_multi)); + CONCURRENCY_CYCLES((fpu_type >= FPU_487SX) ? (x87_concurrency.fcom) : (x87_concurrency.fcom * cpu_multi)); + return 0; +} + +#ifndef FPU_8087 +static int +sf_FUCOMPP(uint32_t fetchdat) +{ + floatx80 a; + floatx80 b; + struct float_status_t status; + int rc; + + FP_ENTER(); + cpu_state.pc++; + clear_C1(); + if (IS_TAG_EMPTY(0) || IS_TAG_EMPTY(1)) { + FPU_exception(fetchdat, FPU_EX_Stack_Underflow, 0); + setcc(C0 | C2 | C3); + if (is_IA_masked()) { + FPU_pop(); + FPU_pop(); + } + goto next_ins; + } + status = i387cw_to_softfloat_status_word(i387_get_control_word()); + a = FPU_read_regi(0); + b = FPU_read_regi(1); + rc = floatx80_compare_quiet(a, b, &status); + setcc(FPU_status_word_flags_fpu_compare(rc)); + if (!FPU_exception(fetchdat, status.float_exception_flags, 0)) { + FPU_pop(); + FPU_pop(); + } + +next_ins: + CLOCK_CYCLES_FPU((fpu_type >= FPU_487SX) ? (x87_timings.fucom) : (x87_timings.fucom * cpu_multi)); + CONCURRENCY_CYCLES((fpu_type >= FPU_487SX) ? (x87_concurrency.fucom) : (x87_concurrency.fucom * cpu_multi)); + return 0; +} + +# ifndef OPS_286_386 +static int +sf_FCOMI_st0_stj(uint32_t fetchdat) +{ + floatx80 a; + floatx80 b; + struct float_status_t status; + int rc; + + FP_ENTER(); + cpu_state.pc++; + flags_rebuild(); + clear_C1(); + if (IS_TAG_EMPTY(0) || IS_TAG_EMPTY(fetchdat & 7)) { + FPU_exception(fetchdat, FPU_EX_Stack_Underflow, 0); + cpu_state.flags |= (Z_FLAG | P_FLAG | C_FLAG); + goto next_ins; + } + status = i387cw_to_softfloat_status_word(i387_get_control_word()); + a = FPU_read_regi(0); + b = FPU_read_regi(fetchdat & 7); + rc = floatx80_compare_two(a, b, &status); + FPU_write_eflags_fpu_compare(rc); + FPU_exception(fetchdat, status.float_exception_flags, 0); + +next_ins: + CLOCK_CYCLES_FPU((fpu_type >= FPU_487SX) ? (x87_timings.fcom) : (x87_timings.fcom * cpu_multi)); + CONCURRENCY_CYCLES((fpu_type >= FPU_487SX) ? (x87_concurrency.fcom) : (x87_concurrency.fcom * cpu_multi)); + return 0; +} +static int +sf_FCOMIP_st0_stj(uint32_t fetchdat) +{ + floatx80 a; + floatx80 b; + struct float_status_t status; + int rc; + + FP_ENTER(); + cpu_state.pc++; + flags_rebuild(); + clear_C1(); + if (IS_TAG_EMPTY(0) || IS_TAG_EMPTY(fetchdat & 7)) { + FPU_exception(fetchdat, FPU_EX_Stack_Underflow, 0); + cpu_state.flags |= (Z_FLAG | P_FLAG | C_FLAG); + if (is_IA_masked()) { + FPU_pop(); + } + goto next_ins; + } + status = i387cw_to_softfloat_status_word(i387_get_control_word()); + a = FPU_read_regi(0); + b = FPU_read_regi(fetchdat & 7); + rc = floatx80_compare_two(a, b, &status); + FPU_write_eflags_fpu_compare(rc); + if (!FPU_exception(fetchdat, status.float_exception_flags, 0)) { + FPU_pop(); + } + +next_ins: + CLOCK_CYCLES_FPU((fpu_type >= FPU_487SX) ? (x87_timings.fcom) : (x87_timings.fcom * cpu_multi)); + CONCURRENCY_CYCLES((fpu_type >= FPU_487SX) ? (x87_concurrency.fcom) : (x87_concurrency.fcom * cpu_multi)); + return 0; +} +# endif + +static int +sf_FUCOM_sti(uint32_t fetchdat) +{ + floatx80 a; + floatx80 b; + struct float_status_t status; + int rc; + + FP_ENTER(); + cpu_state.pc++; + clear_C1(); + if (IS_TAG_EMPTY(0) || IS_TAG_EMPTY(fetchdat & 7)) { + FPU_exception(fetchdat, FPU_EX_Stack_Underflow, 0); + setcc(C0 | C2 | C3); + goto next_ins; + } + status = i387cw_to_softfloat_status_word(i387_get_control_word()); + a = FPU_read_regi(0); + b = FPU_read_regi(fetchdat & 7); + rc = floatx80_compare_quiet(a, b, &status); + setcc(FPU_status_word_flags_fpu_compare(rc)); + FPU_exception(fetchdat, status.float_exception_flags, 0); + +next_ins: + CLOCK_CYCLES_FPU((fpu_type >= FPU_487SX) ? (x87_timings.fucom) : (x87_timings.fucom * cpu_multi)); + CONCURRENCY_CYCLES((fpu_type >= FPU_487SX) ? (x87_concurrency.fucom) : (x87_concurrency.fucom * cpu_multi)); + return 0; +} + +static int +sf_FUCOMP_sti(uint32_t fetchdat) +{ + floatx80 a; + floatx80 b; + struct float_status_t status; + int rc; + + FP_ENTER(); + cpu_state.pc++; + clear_C1(); + if (IS_TAG_EMPTY(0) || IS_TAG_EMPTY(fetchdat & 7)) { + FPU_exception(fetchdat, FPU_EX_Stack_Underflow, 0); + setcc(C0 | C2 | C3); + if (is_IA_masked()) + FPU_pop(); + + goto next_ins; + } + status = i387cw_to_softfloat_status_word(i387_get_control_word()); + a = FPU_read_regi(0); + b = FPU_read_regi(fetchdat & 7); + rc = floatx80_compare_quiet(a, b, &status); + setcc(FPU_status_word_flags_fpu_compare(rc)); + if (!FPU_exception(fetchdat, status.float_exception_flags, 0)) + FPU_pop(); + +next_ins: + CLOCK_CYCLES_FPU((fpu_type >= FPU_487SX) ? (x87_timings.fucom) : (x87_timings.fucom * cpu_multi)); + CONCURRENCY_CYCLES((fpu_type >= FPU_487SX) ? (x87_concurrency.fucom) : (x87_concurrency.fucom * cpu_multi)); + return 0; +} + +# ifndef OPS_286_386 +static int +sf_FUCOMI_st0_stj(uint32_t fetchdat) +{ + floatx80 a; + floatx80 b; + struct float_status_t status; + int rc; + + FP_ENTER(); + cpu_state.pc++; + flags_rebuild(); + clear_C1(); + if (IS_TAG_EMPTY(0) || IS_TAG_EMPTY(fetchdat & 7)) { + FPU_exception(fetchdat, FPU_EX_Stack_Underflow, 0); + cpu_state.flags |= (Z_FLAG | P_FLAG | C_FLAG); + goto next_ins; + } + status = i387cw_to_softfloat_status_word(i387_get_control_word()); + a = FPU_read_regi(0); + b = FPU_read_regi(fetchdat & 7); + rc = floatx80_compare_quiet(a, b, &status); + FPU_write_eflags_fpu_compare(rc); + FPU_exception(fetchdat, status.float_exception_flags, 0); + +next_ins: + CLOCK_CYCLES_FPU((fpu_type >= FPU_487SX) ? (x87_timings.fucom) : (x87_timings.fucom * cpu_multi)); + CONCURRENCY_CYCLES((fpu_type >= FPU_487SX) ? (x87_concurrency.fucom) : (x87_concurrency.fucom * cpu_multi)); + return 0; +} +static int +sf_FUCOMIP_st0_stj(uint32_t fetchdat) +{ + floatx80 a; + floatx80 b; + struct float_status_t status; + int rc; + + FP_ENTER(); + cpu_state.pc++; + flags_rebuild(); + clear_C1(); + if (IS_TAG_EMPTY(0) || IS_TAG_EMPTY(fetchdat & 7)) { + FPU_exception(fetchdat, FPU_EX_Stack_Underflow, 0); + cpu_state.flags |= (Z_FLAG | P_FLAG | C_FLAG); + if (is_IA_masked()) + FPU_pop(); + + goto next_ins; + } + status = i387cw_to_softfloat_status_word(i387_get_control_word()); + a = FPU_read_regi(0); + b = FPU_read_regi(fetchdat & 7); + rc = floatx80_compare_quiet(a, b, &status); + FPU_write_eflags_fpu_compare(rc); + if (!FPU_exception(fetchdat, status.float_exception_flags, 0)) + FPU_pop(); + +next_ins: + CLOCK_CYCLES_FPU((fpu_type >= FPU_487SX) ? (x87_timings.fucom) : (x87_timings.fucom * cpu_multi)); + CONCURRENCY_CYCLES((fpu_type >= FPU_487SX) ? (x87_concurrency.fucom) : (x87_concurrency.fucom * cpu_multi)); + return 0; +} +# endif +#endif + +static int +sf_FTST(uint32_t fetchdat) +{ + int rc; + struct float_status_t status; + + FP_ENTER(); + cpu_state.pc++; + clear_C1(); + if (IS_TAG_EMPTY(0)) { + FPU_exception(fetchdat, FPU_EX_Stack_Underflow, 0); + setcc(C0 | C2 | C3); + } else { + status = i387cw_to_softfloat_status_word(i387_get_control_word()); + rc = floatx80_compare_two(FPU_read_regi(0), Const_Z, &status); + setcc(FPU_status_word_flags_fpu_compare(rc)); + FPU_exception(fetchdat, status.float_exception_flags, 0); + } + CLOCK_CYCLES_FPU((fpu_type >= FPU_487SX) ? (x87_timings.ftst) : (x87_timings.ftst * cpu_multi)); + CONCURRENCY_CYCLES((fpu_type >= FPU_487SX) ? (x87_concurrency.ftst) : (x87_concurrency.ftst * cpu_multi)); + return 0; +} + +static int +sf_FXAM(uint32_t fetchdat) +{ + floatx80 reg; + int sign; + float_class_t aClass; + + FP_ENTER(); + cpu_state.pc++; + reg = FPU_read_regi(0); + sign = floatx80_sign(reg); + /* + * Examine the contents of the ST(0) register and sets the condition + * code flags C0, C2 and C3 in the FPU status word to indicate the + * class of value or number in the register. + */ + if (IS_TAG_EMPTY(0)) { + setcc(C3 | C1 | C0); + } else { + aClass = floatx80_class(reg); + switch (aClass) { + case float_zero: + setcc(C3 | C1); + break; + case float_SNaN: + case float_QNaN: + // unsupported handled as NaNs + if (floatx80_is_unsupported(reg)) { + setcc(C1); + } else { + setcc(C1 | C0); + } + break; + case float_negative_inf: + case float_positive_inf: + setcc(C2 | C1 | C0); + break; + case float_denormal: + setcc(C3 | C2 | C1); + break; + case float_normalized: + setcc(C2 | C1); + break; + } + } + /* + * The C1 flag is set to the sign of the value in ST(0), regardless + * of whether the register is empty or full. + */ + if (!sign) + clear_C1(); + + CLOCK_CYCLES_FPU((fpu_type >= FPU_487SX) ? (x87_timings.fxam) : (x87_timings.fxam * cpu_multi)); + CONCURRENCY_CYCLES((fpu_type >= FPU_487SX) ? (x87_concurrency.fxam) : (x87_concurrency.fxam * cpu_multi)); + return 0; +} diff --git a/src/cpu/x87_ops_sf_const.h b/src/cpu/x87_ops_sf_const.h new file mode 100644 index 000000000..0808cbae8 --- /dev/null +++ b/src/cpu/x87_ops_sf_const.h @@ -0,0 +1,131 @@ +/* A fast way to find out whether x is one of RC_DOWN or RC_CHOP + (and not one of RC_RND or RC_UP). + */ +#define DOWN_OR_CHOP() (fpu_state.cwd & FPU_CW_RC & FPU_RC_DOWN) + +static __inline floatx80 +FPU_round_const(const floatx80 a, int adj) +{ + floatx80 result = a; + result.fraction += adj; + return result; +} + +static int +sf_FLDL2T(uint32_t fetchdat) +{ + FP_ENTER(); + cpu_state.pc++; + clear_C1(); + if (!IS_TAG_EMPTY(-1)) + FPU_stack_overflow(fetchdat); + else { + FPU_push(); + FPU_save_regi(FPU_round_const(Const_L2T, (fpu_state.cwd & FPU_CW_RC) == FPU_RC_UP), 0); + } + CLOCK_CYCLES_FPU((fpu_type >= FPU_487SX) ? (x87_timings.fld_const) : (x87_timings.fld_const * cpu_multi)); + CONCURRENCY_CYCLES((fpu_type >= FPU_487SX) ? (x87_concurrency.fld_const) : (x87_concurrency.fld_const * cpu_multi)); + return 0; +} + +static int +sf_FLDL2E(uint32_t fetchdat) +{ + FP_ENTER(); + cpu_state.pc++; + clear_C1(); + if (!IS_TAG_EMPTY(-1)) + FPU_stack_overflow(fetchdat); + else { + FPU_push(); + FPU_save_regi(FPU_round_const(Const_L2E, DOWN_OR_CHOP() ? -1 : 0), 0); + } + CLOCK_CYCLES_FPU((fpu_type >= FPU_487SX) ? (x87_timings.fld_const) : (x87_timings.fld_const * cpu_multi)); + CONCURRENCY_CYCLES((fpu_type >= FPU_487SX) ? (x87_concurrency.fld_const) : (x87_concurrency.fld_const * cpu_multi)); + return 0; +} + +static int +sf_FLDPI(uint32_t fetchdat) +{ + FP_ENTER(); + cpu_state.pc++; + clear_C1(); + if (!IS_TAG_EMPTY(-1)) + FPU_stack_overflow(fetchdat); + else { + FPU_push(); + FPU_save_regi(FPU_round_const(Const_PI, DOWN_OR_CHOP() ? -1 : 0), 0); + } + CLOCK_CYCLES_FPU((fpu_type >= FPU_487SX) ? (x87_timings.fld_const) : (x87_timings.fld_const * cpu_multi)); + CONCURRENCY_CYCLES((fpu_type >= FPU_487SX) ? (x87_concurrency.fld_const) : (x87_concurrency.fld_const * cpu_multi)); + return 0; +} + +static int +sf_FLDEG2(uint32_t fetchdat) +{ + FP_ENTER(); + cpu_state.pc++; + clear_C1(); + if (!IS_TAG_EMPTY(-1)) + FPU_stack_overflow(fetchdat); + else { + FPU_push(); + FPU_save_regi(FPU_round_const(Const_LG2, DOWN_OR_CHOP() ? -1 : 0), 0); + } + CLOCK_CYCLES_FPU((fpu_type >= FPU_487SX) ? (x87_timings.fld_const) : (x87_timings.fld_const * cpu_multi)); + CONCURRENCY_CYCLES((fpu_type >= FPU_487SX) ? (x87_concurrency.fld_const) : (x87_concurrency.fld_const * cpu_multi)); + return 0; +} + +static int +sf_FLDLN2(uint32_t fetchdat) +{ + FP_ENTER(); + cpu_state.pc++; + clear_C1(); + if (!IS_TAG_EMPTY(-1)) + FPU_stack_overflow(fetchdat); + else { + FPU_push(); + FPU_save_regi(FPU_round_const(Const_LN2, DOWN_OR_CHOP() ? -1 : 0), 0); + } + CLOCK_CYCLES_FPU((fpu_type >= FPU_487SX) ? (x87_timings.fld_const) : (x87_timings.fld_const * cpu_multi)); + CONCURRENCY_CYCLES((fpu_type >= FPU_487SX) ? (x87_concurrency.fld_const) : (x87_concurrency.fld_const * cpu_multi)); + return 0; +} + +static int +sf_FLD1(uint32_t fetchdat) +{ + FP_ENTER(); + cpu_state.pc++; + clear_C1(); + if (!IS_TAG_EMPTY(-1)) + FPU_stack_overflow(fetchdat); + else { + FPU_push(); + FPU_save_regi(Const_1, 0); + } + CLOCK_CYCLES_FPU((fpu_type >= FPU_487SX) ? (x87_timings.fld_z1) : (x87_timings.fld_z1 * cpu_multi)); + CONCURRENCY_CYCLES((fpu_type >= FPU_487SX) ? (x87_concurrency.fld_z1) : (x87_concurrency.fld_z1 * cpu_multi)); + return 0; +} + +static int +sf_FLDZ(uint32_t fetchdat) +{ + FP_ENTER(); + cpu_state.pc++; + clear_C1(); + if (!IS_TAG_EMPTY(-1)) + FPU_stack_overflow(fetchdat); + else { + FPU_push(); + FPU_save_regi(Const_Z, 0); + } + CLOCK_CYCLES_FPU((fpu_type >= FPU_487SX) ? (x87_timings.fld_z1) : (x87_timings.fld_z1 * cpu_multi)); + CONCURRENCY_CYCLES((fpu_type >= FPU_487SX) ? (x87_concurrency.fld_z1) : (x87_concurrency.fld_z1 * cpu_multi)); + return 0; +} diff --git a/src/cpu/x87_ops_sf_load_store.h b/src/cpu/x87_ops_sf_load_store.h new file mode 100644 index 000000000..383a7ee52 --- /dev/null +++ b/src/cpu/x87_ops_sf_load_store.h @@ -0,0 +1,1319 @@ +/* + * 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. + * + * x87 FPU instructions core. + * + * + * + * Authors: Sarah Walker, + * Miran Grca, + * + * Copyright 2008-2019 Sarah Walker. + * Copyright 2016-2019 Miran Grca. + */ + +#define swap_values16u(a, b) \ + { \ + uint16_t tmp = a; \ + a = b; \ + b = tmp; \ + } + +static int +sf_FILDiw_a16(uint32_t fetchdat) +{ + floatx80 result; + int16_t temp; + + FP_ENTER(); + FPU_check_pending_exceptions(); + fetch_ea_16(fetchdat); + SEG_CHECK_READ(cpu_state.ea_seg); + temp = geteaw(); + if (cpu_state.abrt) + return 1; + clear_C1(); + if (!IS_TAG_EMPTY(-1)) { + FPU_stack_overflow(fetchdat); + } else { + result = int32_to_floatx80(temp); + FPU_push(); + FPU_save_regi(result, 0); + } + CLOCK_CYCLES_FPU((fpu_type >= FPU_487SX) ? (x87_timings.fild_16) : (x87_timings.fild_16 * cpu_multi)); + CONCURRENCY_CYCLES((fpu_type >= FPU_487SX) ? (x87_concurrency.fild_16) : (x87_concurrency.fild_16 * cpu_multi)); + return 0; +} +#ifndef FPU_8087 +static int +sf_FILDiw_a32(uint32_t fetchdat) +{ + floatx80 result; + int16_t temp; + + FP_ENTER(); + FPU_check_pending_exceptions(); + fetch_ea_32(fetchdat); + SEG_CHECK_READ(cpu_state.ea_seg); + temp = geteaw(); + if (cpu_state.abrt) + return 1; + clear_C1(); + if (!IS_TAG_EMPTY(-1)) { + FPU_stack_overflow(fetchdat); + } else { + result = int32_to_floatx80(temp); + FPU_push(); + FPU_save_regi(result, 0); + } + CLOCK_CYCLES_FPU((fpu_type >= FPU_487SX) ? (x87_timings.fild_16) : (x87_timings.fild_16 * cpu_multi)); + CONCURRENCY_CYCLES((fpu_type >= FPU_487SX) ? (x87_concurrency.fild_16) : (x87_concurrency.fild_16 * cpu_multi)); + return 0; +} +#endif + +static int +sf_FILDil_a16(uint32_t fetchdat) +{ + floatx80 result; + int32_t templ; + + FP_ENTER(); + FPU_check_pending_exceptions(); + fetch_ea_16(fetchdat); + SEG_CHECK_READ(cpu_state.ea_seg); + templ = geteal(); + if (cpu_state.abrt) + return 1; + clear_C1(); + if (!IS_TAG_EMPTY(-1)) { + FPU_stack_overflow(fetchdat); + } else { + result = int32_to_floatx80(templ); + FPU_push(); + FPU_save_regi(result, 0); + } + CLOCK_CYCLES_FPU((fpu_type >= FPU_487SX) ? (x87_timings.fild_32) : (x87_timings.fild_32 * cpu_multi)); + CONCURRENCY_CYCLES((fpu_type >= FPU_487SX) ? (x87_concurrency.fild_32) : (x87_concurrency.fild_32 * cpu_multi)); + return 0; +} +#ifndef FPU_8087 +static int +sf_FILDil_a32(uint32_t fetchdat) +{ + floatx80 result; + int32_t templ; + + FP_ENTER(); + FPU_check_pending_exceptions(); + fetch_ea_32(fetchdat); + SEG_CHECK_READ(cpu_state.ea_seg); + templ = geteal(); + if (cpu_state.abrt) + return 1; + clear_C1(); + if (!IS_TAG_EMPTY(-1)) { + FPU_stack_overflow(fetchdat); + } else { + result = int32_to_floatx80(templ); + FPU_push(); + FPU_save_regi(result, 0); + } + CLOCK_CYCLES_FPU((fpu_type >= FPU_487SX) ? (x87_timings.fild_32) : (x87_timings.fild_32 * cpu_multi)); + CONCURRENCY_CYCLES((fpu_type >= FPU_487SX) ? (x87_concurrency.fild_32) : (x87_concurrency.fild_32 * cpu_multi)); + return 0; +} +#endif + +static int +sf_FILDiq_a16(uint32_t fetchdat) +{ + floatx80 result; + int64_t temp64; + + FP_ENTER(); + FPU_check_pending_exceptions(); + fetch_ea_16(fetchdat); + SEG_CHECK_READ(cpu_state.ea_seg); + temp64 = geteaq(); + if (cpu_state.abrt) + return 1; + clear_C1(); + if (!IS_TAG_EMPTY(-1)) { + FPU_stack_overflow(fetchdat); + } else { + result = int64_to_floatx80(temp64); + FPU_push(); + FPU_save_regi(result, 0); + } + CLOCK_CYCLES_FPU((fpu_type >= FPU_487SX) ? (x87_timings.fild_64) : (x87_timings.fild_64 * cpu_multi)); + CONCURRENCY_CYCLES((fpu_type >= FPU_487SX) ? (x87_concurrency.fild_64) : (x87_concurrency.fild_64 * cpu_multi)); + return 0; +} +#ifndef FPU_8087 +static int +sf_FILDiq_a32(uint32_t fetchdat) +{ + floatx80 result; + int64_t temp64; + + FP_ENTER(); + FPU_check_pending_exceptions(); + fetch_ea_32(fetchdat); + SEG_CHECK_READ(cpu_state.ea_seg); + temp64 = geteaq(); + if (cpu_state.abrt) + return 1; + clear_C1(); + if (!IS_TAG_EMPTY(-1)) { + FPU_stack_overflow(fetchdat); + } else { + result = int64_to_floatx80(temp64); + FPU_push(); + FPU_save_regi(result, 0); + } + CLOCK_CYCLES_FPU((fpu_type >= FPU_487SX) ? (x87_timings.fild_64) : (x87_timings.fild_64 * cpu_multi)); + CONCURRENCY_CYCLES((fpu_type >= FPU_487SX) ? (x87_concurrency.fild_64) : (x87_concurrency.fild_64 * cpu_multi)); + return 0; +} +#endif + +static int +sf_FLDs_a16(uint32_t fetchdat) +{ + struct float_status_t status; + floatx80 result; + float32 load_reg; + unsigned unmasked; + + FP_ENTER(); + FPU_check_pending_exceptions(); + fetch_ea_16(fetchdat); + SEG_CHECK_READ(cpu_state.ea_seg); + load_reg = geteal(); + if (cpu_state.abrt) + return 1; + clear_C1(); + if (!IS_TAG_EMPTY(-1)) { + FPU_stack_overflow(fetchdat); + goto next_ins; + } + status = i387cw_to_softfloat_status_word(i387_get_control_word()); + result = float32_to_floatx80(load_reg, &status); + unmasked = FPU_exception(fetchdat, status.float_exception_flags, 0); + if (!(unmasked & FPU_CW_Invalid)) { + FPU_push(); + FPU_save_regi(result, 0); + } + +next_ins: + CLOCK_CYCLES_FPU((fpu_type >= FPU_487SX) ? (x87_timings.fst_32) : (x87_timings.fst_32 * cpu_multi)); + CONCURRENCY_CYCLES((fpu_type >= FPU_487SX) ? (x87_concurrency.fst_32) : (x87_concurrency.fst_32 * cpu_multi)); + return 0; +} +#ifndef FPU_8087 +static int +sf_FLDs_a32(uint32_t fetchdat) +{ + struct float_status_t status; + floatx80 result; + float32 load_reg; + unsigned unmasked; + + FP_ENTER(); + FPU_check_pending_exceptions(); + fetch_ea_32(fetchdat); + SEG_CHECK_READ(cpu_state.ea_seg); + load_reg = geteal(); + if (cpu_state.abrt) + return 1; + clear_C1(); + if (!IS_TAG_EMPTY(-1)) { + FPU_stack_overflow(fetchdat); + goto next_ins; + } + status = i387cw_to_softfloat_status_word(i387_get_control_word()); + result = float32_to_floatx80(load_reg, &status); + unmasked = FPU_exception(fetchdat, status.float_exception_flags, 0); + if (!(unmasked & FPU_CW_Invalid)) { + FPU_push(); + FPU_save_regi(result, 0); + } + +next_ins: + CLOCK_CYCLES_FPU((fpu_type >= FPU_487SX) ? (x87_timings.fst_32) : (x87_timings.fst_32 * cpu_multi)); + CONCURRENCY_CYCLES((fpu_type >= FPU_487SX) ? (x87_concurrency.fst_32) : (x87_concurrency.fst_32 * cpu_multi)); + return 0; +} +#endif + +static int +sf_FLDd_a16(uint32_t fetchdat) +{ + struct float_status_t status; + floatx80 result; + float64 load_reg; + unsigned unmasked; + + FP_ENTER(); + FPU_check_pending_exceptions(); + fetch_ea_16(fetchdat); + SEG_CHECK_READ(cpu_state.ea_seg); + load_reg = geteaq(); + if (cpu_state.abrt) + return 1; + clear_C1(); + if (!IS_TAG_EMPTY(-1)) { + FPU_stack_overflow(fetchdat); + goto next_ins; + } + status = i387cw_to_softfloat_status_word(i387_get_control_word()); + result = float64_to_floatx80(load_reg, &status); + unmasked = FPU_exception(fetchdat, status.float_exception_flags, 0); + if (!(unmasked & FPU_CW_Invalid)) { + FPU_push(); + FPU_save_regi(result, 0); + } + +next_ins: + CLOCK_CYCLES_FPU((fpu_type >= FPU_487SX) ? (x87_timings.fld_64) : (x87_timings.fld_64 * cpu_multi)); + CONCURRENCY_CYCLES((fpu_type >= FPU_487SX) ? (x87_concurrency.fld_64) : (x87_concurrency.fld_64 * cpu_multi)); + return 0; +} +#ifndef FPU_8087 +static int +sf_FLDd_a32(uint32_t fetchdat) +{ + struct float_status_t status; + floatx80 result; + float64 load_reg; + unsigned unmasked; + + FP_ENTER(); + FPU_check_pending_exceptions(); + fetch_ea_32(fetchdat); + SEG_CHECK_READ(cpu_state.ea_seg); + load_reg = geteaq(); + if (cpu_state.abrt) + return 1; + clear_C1(); + if (!IS_TAG_EMPTY(-1)) { + FPU_stack_overflow(fetchdat); + goto next_ins; + } + status = i387cw_to_softfloat_status_word(i387_get_control_word()); + result = float64_to_floatx80(load_reg, &status); + unmasked = FPU_exception(fetchdat, status.float_exception_flags, 0); + if (!(unmasked & FPU_CW_Invalid)) { + FPU_push(); + FPU_save_regi(result, 0); + } + +next_ins: + CLOCK_CYCLES_FPU((fpu_type >= FPU_487SX) ? (x87_timings.fld_64) : (x87_timings.fld_64 * cpu_multi)); + CONCURRENCY_CYCLES((fpu_type >= FPU_487SX) ? (x87_concurrency.fld_64) : (x87_concurrency.fld_64 * cpu_multi)); + return 0; +} +#endif + +static int +sf_FLDe_a16(uint32_t fetchdat) +{ + floatx80 result; + + FP_ENTER(); + FPU_check_pending_exceptions(); + fetch_ea_16(fetchdat); + SEG_CHECK_READ(cpu_state.ea_seg); + result.fraction = readmemq(easeg, cpu_state.eaaddr); + result.exp = readmemw(easeg, cpu_state.eaaddr + 8); + if (cpu_state.abrt) + return 1; + clear_C1(); + if (!IS_TAG_EMPTY(-1)) { + FPU_stack_overflow(fetchdat); + } else { + FPU_push(); + FPU_save_regi(result, 0); + } + CLOCK_CYCLES_FPU((fpu_type >= FPU_487SX) ? (x87_timings.fld_80) : (x87_timings.fld_80 * cpu_multi)); + CONCURRENCY_CYCLES((fpu_type >= FPU_487SX) ? (x87_concurrency.fld_80) : (x87_concurrency.fld_80 * cpu_multi)); + return 0; +} +#ifndef FPU_8087 +static int +sf_FLDe_a32(uint32_t fetchdat) +{ + floatx80 result; + + FP_ENTER(); + FPU_check_pending_exceptions(); + fetch_ea_32(fetchdat); + SEG_CHECK_READ(cpu_state.ea_seg); + result.fraction = readmemq(easeg, cpu_state.eaaddr); + result.exp = readmemw(easeg, cpu_state.eaaddr + 8); + if (cpu_state.abrt) + return 1; + clear_C1(); + if (!IS_TAG_EMPTY(-1)) { + FPU_stack_overflow(fetchdat); + } else { + FPU_push(); + FPU_save_regi(result, 0); + } + CLOCK_CYCLES_FPU((fpu_type >= FPU_487SX) ? (x87_timings.fld_80) : (x87_timings.fld_80 * cpu_multi)); + CONCURRENCY_CYCLES((fpu_type >= FPU_487SX) ? (x87_concurrency.fld_80) : (x87_concurrency.fld_80 * cpu_multi)); + return 0; +} +#endif + +static int +sf_FLD_sti(uint32_t fetchdat) +{ + const floatx80 floatx80_default_nan = packFloatx80(0, floatx80_default_nan_exp, floatx80_default_nan_fraction); + floatx80 sti_reg; + + FP_ENTER(); + FPU_check_pending_exceptions(); + cpu_state.pc++; + clear_C1(); + if (!IS_TAG_EMPTY(-1)) { + FPU_stack_overflow(fetchdat); + goto next_ins; + } + sti_reg = floatx80_default_nan; + if (IS_TAG_EMPTY(fetchdat & 7)) { + FPU_exception(fetchdat, FPU_EX_Stack_Underflow, 0); + if (!is_IA_masked()) + goto next_ins; + } else { + sti_reg = FPU_read_regi(fetchdat & 7); + } + + FPU_push(); + FPU_save_regi(sti_reg, 0); + +next_ins: + CLOCK_CYCLES_FPU((fpu_type >= FPU_487SX) ? (x87_timings.fld) : (x87_timings.fld * cpu_multi)); + CONCURRENCY_CYCLES((fpu_type >= FPU_487SX) ? (x87_concurrency.fld) : (x87_concurrency.fld * cpu_multi)); + return 0; +} + +static int +sf_FISTiw_a16(uint32_t fetchdat) +{ + struct float_status_t status; + uint16_t sw = fpu_state.swd; + int16_t save_reg = int16_indefinite; + + FP_ENTER(); + FPU_check_pending_exceptions(); + fetch_ea_16(fetchdat); + SEG_CHECK_WRITE(cpu_state.ea_seg); + clear_C1(); + if (IS_TAG_EMPTY(0)) { + FPU_exception(fetchdat, FPU_EX_Stack_Underflow, 0); + if (!is_IA_masked()) { + goto next_ins; + } + } else { + status = i387cw_to_softfloat_status_word(i387_get_control_word()); + save_reg = floatx80_to_int16(FPU_read_regi(0), &status); + if (FPU_exception(fetchdat, status.float_exception_flags, 1)) { + goto next_ins; + } + } + // store to the memory might generate an exception, in this case original FPU_SW must be kept + swap_values16u(sw, fpu_state.swd); + seteaw(save_reg); + fpu_state.swd = sw; + +next_ins: + CLOCK_CYCLES_FPU((fpu_type >= FPU_487SX) ? (x87_timings.fist_16) : (x87_timings.fist_16 * cpu_multi)); + CONCURRENCY_CYCLES((fpu_type >= FPU_487SX) ? (x87_concurrency.fist_16) : (x87_concurrency.fist_16 * cpu_multi)); + return cpu_state.abrt; +} +#ifndef FPU_8087 +static int +sf_FISTiw_a32(uint32_t fetchdat) +{ + struct float_status_t status; + uint16_t sw = fpu_state.swd; + int16_t save_reg = int16_indefinite; + + FP_ENTER(); + FPU_check_pending_exceptions(); + fetch_ea_32(fetchdat); + SEG_CHECK_WRITE(cpu_state.ea_seg); + clear_C1(); + if (IS_TAG_EMPTY(0)) { + FPU_exception(fetchdat, FPU_EX_Stack_Underflow, 0); + if (!is_IA_masked()) + goto next_ins; + } else { + status = i387cw_to_softfloat_status_word(i387_get_control_word()); + save_reg = floatx80_to_int16(FPU_read_regi(0), &status); + if (FPU_exception(fetchdat, status.float_exception_flags, 1)) + goto next_ins; + } + // store to the memory might generate an exception, in this case original FPU_SW must be kept + swap_values16u(sw, fpu_state.swd); + seteaw(save_reg); + fpu_state.swd = sw; + +next_ins: + CLOCK_CYCLES_FPU((fpu_type >= FPU_487SX) ? (x87_timings.fist_16) : (x87_timings.fist_16 * cpu_multi)); + CONCURRENCY_CYCLES((fpu_type >= FPU_487SX) ? (x87_concurrency.fist_16) : (x87_concurrency.fist_16 * cpu_multi)); + return cpu_state.abrt; +} +#endif + +static int +sf_FISTPiw_a16(uint32_t fetchdat) +{ + struct float_status_t status; + uint16_t sw = fpu_state.swd; + int16_t save_reg = int16_indefinite; + + FP_ENTER(); + FPU_check_pending_exceptions(); + fetch_ea_16(fetchdat); + SEG_CHECK_WRITE(cpu_state.ea_seg); + clear_C1(); + if (IS_TAG_EMPTY(0)) { + FPU_exception(fetchdat, FPU_EX_Stack_Underflow, 0); + if (!is_IA_masked()) + goto next_ins; + } else { + status = i387cw_to_softfloat_status_word(i387_get_control_word()); + save_reg = floatx80_to_int16(FPU_read_regi(0), &status); + if (FPU_exception(fetchdat, status.float_exception_flags, 1)) { + goto next_ins; + } + } + // store to the memory might generate an exception, in this case original FPU_SW must be kept + swap_values16u(sw, fpu_state.swd); + seteaw(save_reg); + if (cpu_state.abrt) + return 1; + fpu_state.swd = sw; + FPU_pop(); + +next_ins: + CLOCK_CYCLES_FPU((fpu_type >= FPU_487SX) ? (x87_timings.fist_16) : (x87_timings.fist_16 * cpu_multi)); + CONCURRENCY_CYCLES((fpu_type >= FPU_487SX) ? (x87_concurrency.fist_16) : (x87_concurrency.fist_16 * cpu_multi)); + return 0; +} +#ifndef FPU_8087 +static int +sf_FISTPiw_a32(uint32_t fetchdat) +{ + struct float_status_t status; + uint16_t sw = fpu_state.swd; + int16_t save_reg = int16_indefinite; + + FP_ENTER(); + FPU_check_pending_exceptions(); + fetch_ea_32(fetchdat); + SEG_CHECK_WRITE(cpu_state.ea_seg); + clear_C1(); + if (IS_TAG_EMPTY(0)) { + FPU_exception(fetchdat, FPU_EX_Stack_Underflow, 0); + if (!is_IA_masked()) + goto next_ins; + } else { + status = i387cw_to_softfloat_status_word(i387_get_control_word()); + save_reg = floatx80_to_int16(FPU_read_regi(0), &status); + if (FPU_exception(fetchdat, status.float_exception_flags, 1)) + goto next_ins; + } + // store to the memory might generate an exception, in this case original FPU_SW must be kept + swap_values16u(sw, fpu_state.swd); + seteaw(save_reg); + if (cpu_state.abrt) + return 1; + fpu_state.swd = sw; + FPU_pop(); + +next_ins: + CLOCK_CYCLES_FPU((fpu_type >= FPU_487SX) ? (x87_timings.fist_16) : (x87_timings.fist_16 * cpu_multi)); + CONCURRENCY_CYCLES((fpu_type >= FPU_487SX) ? (x87_concurrency.fist_16) : (x87_concurrency.fist_16 * cpu_multi)); + return 0; +} +#endif + +static int +sf_FISTil_a16(uint32_t fetchdat) +{ + struct float_status_t status; + uint16_t sw = fpu_state.swd; + int32_t save_reg = int32_indefinite; + + FP_ENTER(); + FPU_check_pending_exceptions(); + fetch_ea_16(fetchdat); + SEG_CHECK_WRITE(cpu_state.ea_seg); + clear_C1(); + if (IS_TAG_EMPTY(0)) { + FPU_exception(fetchdat, FPU_EX_Stack_Underflow, 0); + if (!is_IA_masked()) + goto next_ins; + } else { + status = i387cw_to_softfloat_status_word(i387_get_control_word()); + save_reg = floatx80_to_int32(FPU_read_regi(0), &status); + if (FPU_exception(fetchdat, status.float_exception_flags, 1)) { + goto next_ins; + } + } + // store to the memory might generate an exception, in this case original FPU_SW must be kept + swap_values16u(sw, fpu_state.swd); + seteal(save_reg); + fpu_state.swd = sw; + +next_ins: + CLOCK_CYCLES_FPU((fpu_type >= FPU_487SX) ? (x87_timings.fist_32) : (x87_timings.fist_32 * cpu_multi)); + CONCURRENCY_CYCLES((fpu_type >= FPU_487SX) ? (x87_concurrency.fist_32) : (x87_concurrency.fist_32 * cpu_multi)); + return cpu_state.abrt; +} +#ifndef FPU_8087 +static int +sf_FISTil_a32(uint32_t fetchdat) +{ + struct float_status_t status; + uint16_t sw = fpu_state.swd; + int32_t save_reg = int32_indefinite; + + FP_ENTER(); + FPU_check_pending_exceptions(); + fetch_ea_32(fetchdat); + SEG_CHECK_WRITE(cpu_state.ea_seg); + clear_C1(); + if (IS_TAG_EMPTY(0)) { + FPU_exception(fetchdat, FPU_EX_Stack_Underflow, 0); + if (!is_IA_masked()) + goto next_ins; + } else { + status = i387cw_to_softfloat_status_word(i387_get_control_word()); + save_reg = floatx80_to_int32(FPU_read_regi(0), &status); + if (FPU_exception(fetchdat, status.float_exception_flags, 1)) + goto next_ins; + } + // store to the memory might generate an exception, in this case original FPU_SW must be kept + swap_values16u(sw, fpu_state.swd); + seteal(save_reg); + fpu_state.swd = sw; + +next_ins: + CLOCK_CYCLES_FPU((fpu_type >= FPU_487SX) ? (x87_timings.fist_32) : (x87_timings.fist_32 * cpu_multi)); + CONCURRENCY_CYCLES((fpu_type >= FPU_487SX) ? (x87_concurrency.fist_32) : (x87_concurrency.fist_32 * cpu_multi)); + return cpu_state.abrt; +} +#endif + +static int +sf_FISTPil_a16(uint32_t fetchdat) +{ + struct float_status_t status; + uint16_t sw = fpu_state.swd; + int32_t save_reg = int32_indefinite; + + FP_ENTER(); + FPU_check_pending_exceptions(); + fetch_ea_16(fetchdat); + SEG_CHECK_WRITE(cpu_state.ea_seg); + clear_C1(); + if (IS_TAG_EMPTY(0)) { + FPU_exception(fetchdat, FPU_EX_Stack_Underflow, 0); + if (!is_IA_masked()) + goto next_ins; + } else { + status = i387cw_to_softfloat_status_word(i387_get_control_word()); + save_reg = floatx80_to_int32(FPU_read_regi(0), &status); + if (FPU_exception(fetchdat, status.float_exception_flags, 1)) { + goto next_ins; + } + } + // store to the memory might generate an exception, in this case original FPU_SW must be kept + swap_values16u(sw, fpu_state.swd); + seteal(save_reg); + if (cpu_state.abrt) + return 1; + fpu_state.swd = sw; + FPU_pop(); + +next_ins: + CLOCK_CYCLES_FPU((fpu_type >= FPU_487SX) ? (x87_timings.fist_32) : (x87_timings.fist_32 * cpu_multi)); + CONCURRENCY_CYCLES((fpu_type >= FPU_487SX) ? (x87_concurrency.fist_32) : (x87_concurrency.fist_32 * cpu_multi)); + return 0; +} +#ifndef FPU_8087 +static int +sf_FISTPil_a32(uint32_t fetchdat) +{ + struct float_status_t status; + uint16_t sw = fpu_state.swd; + int32_t save_reg = int32_indefinite; + + FP_ENTER(); + FPU_check_pending_exceptions(); + fetch_ea_32(fetchdat); + SEG_CHECK_WRITE(cpu_state.ea_seg); + clear_C1(); + if (IS_TAG_EMPTY(0)) { + FPU_exception(fetchdat, FPU_EX_Stack_Underflow, 0); + if (!is_IA_masked()) + goto next_ins; + } else { + status = i387cw_to_softfloat_status_word(i387_get_control_word()); + save_reg = floatx80_to_int32(FPU_read_regi(0), &status); + if (FPU_exception(fetchdat, status.float_exception_flags, 1)) + goto next_ins; + } + // store to the memory might generate an exception, in this case original FPU_SW must be kept + swap_values16u(sw, fpu_state.swd); + seteal(save_reg); + if (cpu_state.abrt) + return 1; + fpu_state.swd = sw; + FPU_pop(); + +next_ins: + CLOCK_CYCLES_FPU((fpu_type >= FPU_487SX) ? (x87_timings.fist_32) : (x87_timings.fist_32 * cpu_multi)); + CONCURRENCY_CYCLES((fpu_type >= FPU_487SX) ? (x87_concurrency.fist_32) : (x87_concurrency.fist_32 * cpu_multi)); + return 0; +} +#endif + +static int +sf_FISTPiq_a16(uint32_t fetchdat) +{ + struct float_status_t status; + uint16_t sw = fpu_state.swd; + int64_t save_reg = int64_indefinite; + + FP_ENTER(); + FPU_check_pending_exceptions(); + fetch_ea_16(fetchdat); + SEG_CHECK_WRITE(cpu_state.ea_seg); + clear_C1(); + if (IS_TAG_EMPTY(0)) { + FPU_exception(fetchdat, FPU_EX_Stack_Underflow, 0); + if (!is_IA_masked()) + goto next_ins; + } else { + status = i387cw_to_softfloat_status_word(i387_get_control_word()); + save_reg = floatx80_to_int64(FPU_read_regi(0), &status); + if (FPU_exception(fetchdat, status.float_exception_flags, 1)) { + goto next_ins; + } + } + // store to the memory might generate an exception, in this case origial FPU_SW must be kept + swap_values16u(sw, fpu_state.swd); + seteaq(save_reg); + if (cpu_state.abrt) + return 1; + fpu_state.swd = sw; + FPU_pop(); + +next_ins: + CLOCK_CYCLES_FPU((fpu_type >= FPU_487SX) ? (x87_timings.fist_64) : (x87_timings.fist_64 * cpu_multi)); + CONCURRENCY_CYCLES((fpu_type >= FPU_487SX) ? (x87_concurrency.fist_64) : (x87_concurrency.fist_64 * cpu_multi)); + return 0; +} +#ifndef FPU_8087 +static int +sf_FISTPiq_a32(uint32_t fetchdat) +{ + struct float_status_t status; + uint16_t sw = fpu_state.swd; + int64_t save_reg = int64_indefinite; + + FP_ENTER(); + FPU_check_pending_exceptions(); + fetch_ea_32(fetchdat); + SEG_CHECK_WRITE(cpu_state.ea_seg); + clear_C1(); + if (IS_TAG_EMPTY(0)) { + FPU_exception(fetchdat, FPU_EX_Stack_Underflow, 0); + if (!is_IA_masked()) + goto next_ins; + } else { + status = i387cw_to_softfloat_status_word(i387_get_control_word()); + save_reg = floatx80_to_int64(FPU_read_regi(0), &status); + if (FPU_exception(fetchdat, status.float_exception_flags, 1)) + goto next_ins; + } + // store to the memory might generate an exception, in this case origial FPU_SW must be kept + swap_values16u(sw, fpu_state.swd); + seteaq(save_reg); + if (cpu_state.abrt) + return 1; + fpu_state.swd = sw; + FPU_pop(); + +next_ins: + CLOCK_CYCLES_FPU((fpu_type >= FPU_487SX) ? (x87_timings.fist_64) : (x87_timings.fist_64 * cpu_multi)); + CONCURRENCY_CYCLES((fpu_type >= FPU_487SX) ? (x87_concurrency.fist_64) : (x87_concurrency.fist_64 * cpu_multi)); + return 0; +} +#endif + +static int +sf_FBSTP_PACKED_BCD_a16(uint32_t fetchdat) +{ + struct float_status_t status; + uint16_t sw = fpu_state.swd; + uint16_t save_reg_hi = 0xffff; + uint64_t save_reg_lo = BX_CONST64(0xC000000000000000); + floatx80 reg; + int64_t save_val; + int sign; + + FP_ENTER(); + FPU_check_pending_exceptions(); + fetch_ea_16(fetchdat); + SEG_CHECK_WRITE(cpu_state.ea_seg); + clear_C1(); + if (IS_TAG_EMPTY(0)) { + FPU_exception(fetchdat, FPU_EX_Stack_Underflow, 0); + if (!is_IA_masked()) + goto next_ins; + } else { + status = i387cw_to_softfloat_status_word(i387_get_control_word()); + reg = FPU_read_regi(0); + save_val = floatx80_to_int64(reg, &status); + sign = (reg.exp & 0x8000) != 0; + if (sign) + save_val = -save_val; + + if (save_val > BX_CONST64(999999999999999999)) + status.float_exception_flags = float_flag_invalid; // throw away other flags + + if (!(status.float_exception_flags & float_flag_invalid)) { + save_reg_hi = sign ? 0x8000 : 0; + save_reg_lo = 0; + for (int i = 0; i < 16; i++) { + save_reg_lo += ((uint64_t) (save_val % 10)) << (4 * i); + save_val /= 10; + } + save_reg_hi += (uint16_t) (save_val % 10); + save_val /= 10; + save_reg_hi += (uint16_t) (save_val % 10) << 4; + } + /* check for fpu arithmetic exceptions */ + if (FPU_exception(fetchdat, status.float_exception_flags, 1)) { + goto next_ins; + } + } + // store to the memory might generate an exception, in this case original FPU_SW must be kept + swap_values16u(sw, fpu_state.swd); + + // write packed bcd to memory + writememq(easeg, cpu_state.eaaddr, save_reg_lo); + writememw(easeg, cpu_state.eaaddr + 8, save_reg_hi); + if (cpu_state.abrt) + return 1; + fpu_state.swd = sw; + FPU_pop(); + +next_ins: + CLOCK_CYCLES_FPU((fpu_type >= FPU_487SX) ? (x87_timings.fbstp) : (x87_timings.fbstp * cpu_multi)); + CONCURRENCY_CYCLES((fpu_type >= FPU_487SX) ? (x87_concurrency.fbstp) : (x87_concurrency.fbstp * cpu_multi)); + return 0; +} +#ifndef FPU_8087 +static int +sf_FBSTP_PACKED_BCD_a32(uint32_t fetchdat) +{ + struct float_status_t status; + uint16_t sw = fpu_state.swd; + uint16_t save_reg_hi = 0xffff; + uint64_t save_reg_lo = BX_CONST64(0xC000000000000000); + floatx80 reg; + int64_t save_val; + int sign; + + FP_ENTER(); + FPU_check_pending_exceptions(); + fetch_ea_32(fetchdat); + SEG_CHECK_WRITE(cpu_state.ea_seg); + clear_C1(); + if (IS_TAG_EMPTY(0)) { + FPU_exception(fetchdat, FPU_EX_Stack_Underflow, 0); + if (!is_IA_masked()) + goto next_ins; + } else { + status = i387cw_to_softfloat_status_word(i387_get_control_word()); + reg = FPU_read_regi(0); + save_val = floatx80_to_int64(reg, &status); + sign = (reg.exp & 0x8000) != 0; + if (sign) + save_val = -save_val; + + if (save_val > BX_CONST64(999999999999999999)) + status.float_exception_flags = float_flag_invalid; // throw away other flags + + if (!(status.float_exception_flags & float_flag_invalid)) { + save_reg_hi = sign ? 0x8000 : 0; + save_reg_lo = 0; + for (int i = 0; i < 16; i++) { + save_reg_lo += ((uint64_t) (save_val % 10)) << (4 * i); + save_val /= 10; + } + save_reg_hi += (uint16_t) (save_val % 10); + save_val /= 10; + save_reg_hi += (uint16_t) (save_val % 10) << 4; + } + /* check for fpu arithmetic exceptions */ + if (FPU_exception(fetchdat, status.float_exception_flags, 1)) { + goto next_ins; + } + } + // store to the memory might generate an exception, in this case original FPU_SW must be kept + swap_values16u(sw, fpu_state.swd); + + // write packed bcd to memory + writememq(easeg, cpu_state.eaaddr, save_reg_lo); + writememw(easeg, cpu_state.eaaddr + 8, save_reg_hi); + if (cpu_state.abrt) + return 1; + fpu_state.swd = sw; + FPU_pop(); + +next_ins: + CLOCK_CYCLES_FPU((fpu_type >= FPU_487SX) ? (x87_timings.fbstp) : (x87_timings.fbstp * cpu_multi)); + CONCURRENCY_CYCLES((fpu_type >= FPU_487SX) ? (x87_concurrency.fbstp) : (x87_concurrency.fbstp * cpu_multi)); + return 0; +} +#endif + +static int +sf_FSTs_a16(uint32_t fetchdat) +{ + struct float_status_t status; + uint16_t sw = fpu_state.swd; + float32 save_reg = float32_default_nan; + + FP_ENTER(); + FPU_check_pending_exceptions(); + fetch_ea_16(fetchdat); + SEG_CHECK_WRITE(cpu_state.ea_seg); + clear_C1(); + if (IS_TAG_EMPTY(0)) { + FPU_exception(fetchdat, FPU_EX_Stack_Underflow, 0); + if (!is_IA_masked()) + goto next_ins; + } else { + status = i387cw_to_softfloat_status_word(i387_get_control_word()); + save_reg = floatx80_to_float32(FPU_read_regi(0), &status); + if (FPU_exception(fetchdat, status.float_exception_flags, 1)) { + goto next_ins; + } + } + // store to the memory might generate an exception, in this case original FPU_SW must be kept + swap_values16u(sw, fpu_state.swd); + seteal(save_reg); + fpu_state.swd = sw; + +next_ins: + CLOCK_CYCLES_FPU((fpu_type >= FPU_487SX) ? (x87_timings.fst_32) : (x87_timings.fst_32 * cpu_multi)); + CONCURRENCY_CYCLES((fpu_type >= FPU_487SX) ? (x87_concurrency.fst_32) : (x87_concurrency.fst_32 * cpu_multi)); + return cpu_state.abrt; +} +#ifndef FPU_8087 +static int +sf_FSTs_a32(uint32_t fetchdat) +{ + struct float_status_t status; + uint16_t sw = fpu_state.swd; + float32 save_reg = float32_default_nan; + + FP_ENTER(); + FPU_check_pending_exceptions(); + fetch_ea_32(fetchdat); + SEG_CHECK_WRITE(cpu_state.ea_seg); + clear_C1(); + if (IS_TAG_EMPTY(0)) { + FPU_exception(fetchdat, FPU_EX_Stack_Underflow, 0); + if (!is_IA_masked()) + goto next_ins; + } else { + status = i387cw_to_softfloat_status_word(i387_get_control_word()); + save_reg = floatx80_to_float32(FPU_read_regi(0), &status); + if (FPU_exception(fetchdat, status.float_exception_flags, 1)) + goto next_ins; + } + // store to the memory might generate an exception, in this case original FPU_SW must be kept + swap_values16u(sw, fpu_state.swd); + seteal(save_reg); + fpu_state.swd = sw; + +next_ins: + CLOCK_CYCLES_FPU((fpu_type >= FPU_487SX) ? (x87_timings.fst_32) : (x87_timings.fst_32 * cpu_multi)); + CONCURRENCY_CYCLES((fpu_type >= FPU_487SX) ? (x87_concurrency.fst_32) : (x87_concurrency.fst_32 * cpu_multi)); + return cpu_state.abrt; +} +#endif + +static int +sf_FSTPs_a16(uint32_t fetchdat) +{ + struct float_status_t status; + uint16_t sw = fpu_state.swd; + float32 save_reg = float32_default_nan; + + FP_ENTER(); + FPU_check_pending_exceptions(); + fetch_ea_16(fetchdat); + SEG_CHECK_WRITE(cpu_state.ea_seg); + clear_C1(); + if (IS_TAG_EMPTY(0)) { + FPU_exception(fetchdat, FPU_EX_Stack_Underflow, 0); + if (!is_IA_masked()) + goto next_ins; + } else { + status = i387cw_to_softfloat_status_word(i387_get_control_word()); + save_reg = floatx80_to_float32(FPU_read_regi(0), &status); + if (FPU_exception(fetchdat, status.float_exception_flags, 1)) { + goto next_ins; + } + } + // store to the memory might generate an exception, in this case original FPU_SW must be kept + swap_values16u(sw, fpu_state.swd); + seteal(save_reg); + if (cpu_state.abrt) { + return 1; + } + fpu_state.swd = sw; + FPU_pop(); + +next_ins: + CLOCK_CYCLES_FPU((fpu_type >= FPU_487SX) ? (x87_timings.fst_32) : (x87_timings.fst_32 * cpu_multi)); + CONCURRENCY_CYCLES((fpu_type >= FPU_487SX) ? (x87_concurrency.fst_32) : (x87_concurrency.fst_32 * cpu_multi)); + return 0; +} +#ifndef FPU_8087 +static int +sf_FSTPs_a32(uint32_t fetchdat) +{ + struct float_status_t status; + uint16_t sw = fpu_state.swd; + float32 save_reg = float32_default_nan; + + FP_ENTER(); + FPU_check_pending_exceptions(); + fetch_ea_32(fetchdat); + SEG_CHECK_WRITE(cpu_state.ea_seg); + clear_C1(); + if (IS_TAG_EMPTY(0)) { + FPU_exception(fetchdat, FPU_EX_Stack_Underflow, 0); + if (!is_IA_masked()) + goto next_ins; + } else { + status = i387cw_to_softfloat_status_word(i387_get_control_word()); + save_reg = floatx80_to_float32(FPU_read_regi(0), &status); + if (FPU_exception(fetchdat, status.float_exception_flags, 1)) + goto next_ins; + } + // store to the memory might generate an exception, in this case original FPU_SW must be kept + swap_values16u(sw, fpu_state.swd); + seteal(save_reg); + if (cpu_state.abrt) + return 1; + fpu_state.swd = sw; + FPU_pop(); + +next_ins: + CLOCK_CYCLES_FPU((fpu_type >= FPU_487SX) ? (x87_timings.fst_32) : (x87_timings.fst_32 * cpu_multi)); + CONCURRENCY_CYCLES((fpu_type >= FPU_487SX) ? (x87_concurrency.fst_32) : (x87_concurrency.fst_32 * cpu_multi)); + return 0; +} +#endif + +static int +sf_FSTd_a16(uint32_t fetchdat) +{ + struct float_status_t status; + uint16_t sw = fpu_state.swd; + float64 save_reg = float64_default_nan; + + FP_ENTER(); + FPU_check_pending_exceptions(); + fetch_ea_16(fetchdat); + SEG_CHECK_WRITE(cpu_state.ea_seg); + clear_C1(); + if (IS_TAG_EMPTY(0)) { + FPU_exception(fetchdat, FPU_EX_Stack_Underflow, 0); + if (!is_IA_masked()) + goto next_ins; + } else { + status = i387cw_to_softfloat_status_word(i387_get_control_word()); + save_reg = floatx80_to_float64(FPU_read_regi(0), &status); + if (FPU_exception(fetchdat, status.float_exception_flags, 1)) { + goto next_ins; + } + } + // store to the memory might generate an exception, in this case original FPU_SW must be kept + swap_values16u(sw, fpu_state.swd); + seteaq(save_reg); + fpu_state.swd = sw; + +next_ins: + CLOCK_CYCLES_FPU((fpu_type >= FPU_487SX) ? (x87_timings.fst_64) : (x87_timings.fst_64 * cpu_multi)); + CONCURRENCY_CYCLES((fpu_type >= FPU_487SX) ? (x87_concurrency.fst_64) : (x87_concurrency.fst_64 * cpu_multi)); + return cpu_state.abrt; +} +#ifndef FPU_8087 +static int +sf_FSTd_a32(uint32_t fetchdat) +{ + struct float_status_t status; + uint16_t sw = fpu_state.swd; + float64 save_reg = float64_default_nan; + + FP_ENTER(); + FPU_check_pending_exceptions(); + fetch_ea_32(fetchdat); + SEG_CHECK_WRITE(cpu_state.ea_seg); + clear_C1(); + if (IS_TAG_EMPTY(0)) { + FPU_exception(fetchdat, FPU_EX_Stack_Underflow, 0); + if (!is_IA_masked()) + goto next_ins; + } else { + status = i387cw_to_softfloat_status_word(i387_get_control_word()); + save_reg = floatx80_to_float64(FPU_read_regi(0), &status); + if (FPU_exception(fetchdat, status.float_exception_flags, 1)) + goto next_ins; + } + // store to the memory might generate an exception, in this case original FPU_SW must be kept + swap_values16u(sw, fpu_state.swd); + seteaq(save_reg); + fpu_state.swd = sw; + +next_ins: + CLOCK_CYCLES_FPU((fpu_type >= FPU_487SX) ? (x87_timings.fst_64) : (x87_timings.fst_64 * cpu_multi)); + CONCURRENCY_CYCLES((fpu_type >= FPU_487SX) ? (x87_concurrency.fst_64) : (x87_concurrency.fst_64 * cpu_multi)); + return cpu_state.abrt; +} +#endif + +static int +sf_FSTPd_a16(uint32_t fetchdat) +{ + struct float_status_t status; + uint16_t sw = fpu_state.swd; + float64 save_reg = float64_default_nan; + + FP_ENTER(); + FPU_check_pending_exceptions(); + fetch_ea_16(fetchdat); + SEG_CHECK_WRITE(cpu_state.ea_seg); + clear_C1(); + if (IS_TAG_EMPTY(0)) { + FPU_exception(fetchdat, FPU_EX_Stack_Underflow, 0); + if (!is_IA_masked()) { + goto next_ins; + } + } else { + status = i387cw_to_softfloat_status_word(i387_get_control_word()); + save_reg = floatx80_to_float64(FPU_read_regi(0), &status); + if (FPU_exception(fetchdat, status.float_exception_flags, 1)) { + goto next_ins; + } + } + // store to the memory might generate an exception, in this case original FPU_SW must be kept + swap_values16u(sw, fpu_state.swd); + seteaq(save_reg); + if (cpu_state.abrt) + return 1; + fpu_state.swd = sw; + FPU_pop(); + +next_ins: + CLOCK_CYCLES_FPU((fpu_type >= FPU_487SX) ? (x87_timings.fst_64) : (x87_timings.fst_64 * cpu_multi)); + CONCURRENCY_CYCLES((fpu_type >= FPU_487SX) ? (x87_concurrency.fst_64) : (x87_concurrency.fst_64 * cpu_multi)); + return 0; +} +#ifndef FPU_8087 +static int +sf_FSTPd_a32(uint32_t fetchdat) +{ + struct float_status_t status; + uint16_t sw = fpu_state.swd; + float64 save_reg = float64_default_nan; + + FP_ENTER(); + FPU_check_pending_exceptions(); + fetch_ea_32(fetchdat); + SEG_CHECK_WRITE(cpu_state.ea_seg); + clear_C1(); + if (IS_TAG_EMPTY(0)) { + FPU_exception(fetchdat, FPU_EX_Stack_Underflow, 0); + if (!is_IA_masked()) + goto next_ins; + } else { + status = i387cw_to_softfloat_status_word(i387_get_control_word()); + save_reg = floatx80_to_float64(FPU_read_regi(0), &status); + if (FPU_exception(fetchdat, status.float_exception_flags, 1)) + goto next_ins; + } + // store to the memory might generate an exception, in this case original FPU_SW must be kept + swap_values16u(sw, fpu_state.swd); + seteaq(save_reg); + if (cpu_state.abrt) + return 1; + fpu_state.swd = sw; + FPU_pop(); + +next_ins: + CLOCK_CYCLES_FPU((fpu_type >= FPU_487SX) ? (x87_timings.fst_64) : (x87_timings.fst_64 * cpu_multi)); + CONCURRENCY_CYCLES((fpu_type >= FPU_487SX) ? (x87_concurrency.fst_64) : (x87_concurrency.fst_64 * cpu_multi)); + return 0; +} +#endif + +static int +sf_FSTPe_a16(uint32_t fetchdat) +{ + const floatx80 floatx80_default_nan = packFloatx80(0, floatx80_default_nan_exp, floatx80_default_nan_fraction); + floatx80 save_reg; + + FP_ENTER(); + FPU_check_pending_exceptions(); + fetch_ea_16(fetchdat); + SEG_CHECK_WRITE(cpu_state.ea_seg); + if (cpu_state.abrt) + return 1; + save_reg = floatx80_default_nan; + clear_C1(); + if (IS_TAG_EMPTY(0)) { + FPU_exception(fetchdat, FPU_EX_Stack_Underflow, 0); + if (!is_IA_masked()) { + goto next_ins; + } + } else { + save_reg = FPU_read_regi(0); + } + writememq(easeg, cpu_state.eaaddr, save_reg.fraction); + writememw(easeg, cpu_state.eaaddr + 8, save_reg.exp); + FPU_pop(); + +next_ins: + CLOCK_CYCLES_FPU((fpu_type >= FPU_487SX) ? (x87_timings.fst_80) : (x87_timings.fst_80 * cpu_multi)); + CONCURRENCY_CYCLES((fpu_type >= FPU_487SX) ? (x87_concurrency.fst_80) : (x87_concurrency.fst_80 * cpu_multi)); + return 0; +} +#ifndef FPU_8087 +static int +sf_FSTPe_a32(uint32_t fetchdat) +{ + const floatx80 floatx80_default_nan = packFloatx80(0, floatx80_default_nan_exp, floatx80_default_nan_fraction); + floatx80 save_reg; + + FP_ENTER(); + FPU_check_pending_exceptions(); + fetch_ea_32(fetchdat); + SEG_CHECK_WRITE(cpu_state.ea_seg); + if (cpu_state.abrt) + return 1; + save_reg = floatx80_default_nan; + clear_C1(); + if (IS_TAG_EMPTY(0)) { + FPU_exception(fetchdat, FPU_EX_Stack_Underflow, 0); + if (!is_IA_masked()) + goto next_ins; + } else { + save_reg = FPU_read_regi(0); + } + writememq(easeg, cpu_state.eaaddr, save_reg.fraction); + writememw(easeg, cpu_state.eaaddr + 8, save_reg.exp); + FPU_pop(); + +next_ins: + CLOCK_CYCLES_FPU((fpu_type >= FPU_487SX) ? (x87_timings.fst_80) : (x87_timings.fst_80 * cpu_multi)); + CONCURRENCY_CYCLES((fpu_type >= FPU_487SX) ? (x87_concurrency.fst_80) : (x87_concurrency.fst_80 * cpu_multi)); + return 0; +} +#endif + +static int +sf_FST_sti(uint32_t fetchdat) +{ + floatx80 st0_reg; + + FP_ENTER(); + FPU_check_pending_exceptions(); + cpu_state.pc++; + clear_C1(); + if (IS_TAG_EMPTY(0)) { + FPU_stack_underflow(fetchdat, fetchdat & 7, 0); + } else { + st0_reg = FPU_read_regi(0); + FPU_save_regi(st0_reg, fetchdat & 7); + } + CLOCK_CYCLES_FPU((fpu_type >= FPU_487SX) ? (x87_timings.fst) : (x87_timings.fst * cpu_multi)); + CONCURRENCY_CYCLES((fpu_type >= FPU_487SX) ? (x87_concurrency.fst) : (x87_concurrency.fst * cpu_multi)); + return 0; +} + +static int +sf_FSTP_sti(uint32_t fetchdat) +{ + floatx80 st0_reg; + + FP_ENTER(); + FPU_check_pending_exceptions(); + cpu_state.pc++; + clear_C1(); + if (IS_TAG_EMPTY(0)) { + FPU_stack_underflow(fetchdat, fetchdat & 7, 1); + } else { + st0_reg = FPU_read_regi(0); + FPU_save_regi(st0_reg, fetchdat & 7); + FPU_pop(); + } + CLOCK_CYCLES_FPU((fpu_type >= FPU_487SX) ? (x87_timings.fst) : (x87_timings.fst * cpu_multi)); + CONCURRENCY_CYCLES((fpu_type >= FPU_487SX) ? (x87_concurrency.fst) : (x87_concurrency.fst * cpu_multi)); + return 0; +} + +#ifndef FPU_8087 +# ifndef OPS_286_386 +# define sf_FCMOV(condition) \ + static int sf_FCMOV##condition(uint32_t fetchdat) \ + { \ + FP_ENTER(); \ + FPU_check_pending_exceptions(); \ + cpu_state.pc++; \ + if (IS_TAG_EMPTY(0) || IS_TAG_EMPTY(fetchdat & 7)) \ + FPU_stack_underflow(fetchdat, 0, 0); \ + else { \ + if (cond_##condition) { \ + FPU_save_regi(FPU_read_regi(fetchdat & 7), 0); \ + } \ + } \ + CLOCK_CYCLES_FPU(4); \ + return 0; \ + } + +# define cond_U (PF_SET()) +# define cond_NU (!PF_SET()) + +// clang-format off +sf_FCMOV(B) +sf_FCMOV(E) +sf_FCMOV(BE) +sf_FCMOV(U) +sf_FCMOV(NB) +sf_FCMOV(NE) +sf_FCMOV(NBE) +sf_FCMOV(NU) +// clang-format on +# endif +#endif diff --git a/src/cpu/x87_ops_sf_misc.h b/src/cpu/x87_ops_sf_misc.h new file mode 100644 index 000000000..85f42e6d5 --- /dev/null +++ b/src/cpu/x87_ops_sf_misc.h @@ -0,0 +1,136 @@ +static int +sf_FXCH_sti(uint32_t fetchdat) +{ + const floatx80 floatx80_default_nan = packFloatx80(0, floatx80_default_nan_exp, floatx80_default_nan_fraction); + floatx80 st0_reg; + floatx80 sti_reg; + int st0_tag; + int sti_tag; + + FP_ENTER(); + FPU_check_pending_exceptions(); + cpu_state.pc++; + st0_tag = FPU_gettagi(0); + sti_tag = FPU_gettagi(fetchdat & 7); + st0_reg = FPU_read_regi(0); + sti_reg = FPU_read_regi(fetchdat & 7); + + clear_C1(); + if ((st0_tag == X87_TAG_EMPTY) || (sti_tag == X87_TAG_EMPTY)) { + FPU_exception(fetchdat, FPU_EX_Stack_Underflow, 0); + if (is_IA_masked()) { + /* Masked response */ + if (st0_tag == X87_TAG_EMPTY) + st0_reg = floatx80_default_nan; + if (sti_tag == X87_TAG_EMPTY) + sti_reg = floatx80_default_nan; + } else + goto next_ins; + } + FPU_save_regi(st0_reg, fetchdat & 7); + FPU_save_regi(sti_reg, 0); + +next_ins: + CLOCK_CYCLES_FPU((fpu_type >= FPU_487SX) ? (x87_timings.fxch) : (x87_timings.fxch * cpu_multi)); + CONCURRENCY_CYCLES((fpu_type >= FPU_487SX) ? (x87_concurrency.fxch) : (x87_concurrency.fxch * cpu_multi)); + return 0; +} + +static int +sf_FCHS(uint32_t fetchdat) +{ + floatx80 st0_reg; + floatx80 result; + + FP_ENTER(); + FPU_check_pending_exceptions(); + cpu_state.pc++; + if (IS_TAG_EMPTY(0)) + FPU_stack_underflow(fetchdat, 0, 0); + else { + clear_C1(); + st0_reg = FPU_read_regi(0); + result = floatx80_chs(st0_reg); + FPU_save_regi(result, 0); + } + CLOCK_CYCLES_FPU((fpu_type >= FPU_487SX) ? (x87_timings.fchs) : (x87_timings.fchs * cpu_multi)); + CONCURRENCY_CYCLES((fpu_type >= FPU_487SX) ? (x87_concurrency.fchs) : (x87_concurrency.fchs * cpu_multi)); + return 0; +} + +static int +sf_FABS(uint32_t fetchdat) +{ + floatx80 st0_reg; + floatx80 result; + + FP_ENTER(); + FPU_check_pending_exceptions(); + cpu_state.pc++; + if (IS_TAG_EMPTY(0)) + FPU_stack_underflow(fetchdat, 0, 0); + else { + clear_C1(); + st0_reg = FPU_read_regi(0); + result = floatx80_abs(st0_reg); + FPU_save_regi(result, 0); + } + CLOCK_CYCLES_FPU((fpu_type >= FPU_487SX) ? (x87_timings.fabs) : (x87_timings.fabs * cpu_multi)); + CONCURRENCY_CYCLES((fpu_type >= FPU_487SX) ? (x87_concurrency.fabs) : (x87_concurrency.fabs * cpu_multi)); + return 0; +} + +static int +sf_FDECSTP(uint32_t fetchdat) +{ + FP_ENTER(); + FPU_check_pending_exceptions(); + cpu_state.pc++; + clear_C1(); + fpu_state.tos = (fpu_state.tos - 1) & 7; + CLOCK_CYCLES_FPU((fpu_type >= FPU_487SX) ? (x87_timings.fincdecstp) : (x87_timings.fincdecstp * cpu_multi)); + CONCURRENCY_CYCLES((fpu_type >= FPU_487SX) ? (x87_concurrency.fincdecstp) : (x87_concurrency.fincdecstp * cpu_multi)); + return 0; +} + +static int +sf_FINCSTP(uint32_t fetchdat) +{ + FP_ENTER(); + FPU_check_pending_exceptions(); + cpu_state.pc++; + clear_C1(); + fpu_state.tos = (fpu_state.tos + 1) & 7; + CLOCK_CYCLES_FPU((fpu_type >= FPU_487SX) ? (x87_timings.fincdecstp) : (x87_timings.fincdecstp * cpu_multi)); + CONCURRENCY_CYCLES((fpu_type >= FPU_487SX) ? (x87_concurrency.fincdecstp) : (x87_concurrency.fincdecstp * cpu_multi)); + return 0; +} + +static int +sf_FFREE_sti(uint32_t fetchdat) +{ + FP_ENTER(); + FPU_check_pending_exceptions(); + cpu_state.pc++; + clear_C1(); + FPU_settagi(X87_TAG_EMPTY, fetchdat & 7); + CLOCK_CYCLES_FPU((fpu_type >= FPU_487SX) ? (x87_timings.ffree) : (x87_timings.ffree * cpu_multi)); + CONCURRENCY_CYCLES((fpu_type >= FPU_487SX) ? (x87_concurrency.ffree) : (x87_concurrency.ffree * cpu_multi)); + return 0; +} + +static int +sf_FFREEP_sti(uint32_t fetchdat) +{ + FP_ENTER(); + FPU_check_pending_exceptions(); + cpu_state.pc++; + clear_C1(); + FPU_settagi(X87_TAG_EMPTY, fetchdat & 7); + if (cpu_state.abrt) + return 1; + FPU_pop(); + CLOCK_CYCLES_FPU((fpu_type >= FPU_487SX) ? (x87_timings.ffree) : (x87_timings.ffree * cpu_multi)); + CONCURRENCY_CYCLES((fpu_type >= FPU_487SX) ? (x87_concurrency.ffree) : (x87_concurrency.ffree * cpu_multi)); + return 0; +} diff --git a/src/cpu/x87_ops_sf_trans.h b/src/cpu/x87_ops_sf_trans.h new file mode 100644 index 000000000..5a99abb4c --- /dev/null +++ b/src/cpu/x87_ops_sf_trans.h @@ -0,0 +1,428 @@ +static int +sf_F2XM1(uint32_t fetchdat) +{ + floatx80 result; + struct float_status_t status; + + FP_ENTER(); + cpu_state.pc++; + clear_C1(); + if (IS_TAG_EMPTY(0)) { + FPU_stack_underflow(fetchdat, 0, 0); + goto next_ins; + } + status = i387cw_to_softfloat_status_word(i387_get_control_word() | FPU_PR_80_BITS); + result = f2xm1(FPU_read_regi(0), &status); + if (!FPU_exception(fetchdat, status.float_exception_flags, 0)) + FPU_save_regi(result, 0); + +next_ins: + CLOCK_CYCLES_FPU((fpu_type >= FPU_487SX) ? (x87_timings.f2xm1) : (x87_timings.f2xm1 * cpu_multi)); + CONCURRENCY_CYCLES((fpu_type >= FPU_487SX) ? (x87_concurrency.f2xm1) : (x87_concurrency.f2xm1 * cpu_multi)); + return 0; +} + +static int +sf_FYL2X(uint32_t fetchdat) +{ + floatx80 result; + struct float_status_t status; + + FP_ENTER(); + cpu_state.pc++; + clear_C1(); + if (IS_TAG_EMPTY(0) || IS_TAG_EMPTY(1)) { + FPU_stack_underflow(fetchdat, 1, 1); + goto next_ins; + } + status = i387cw_to_softfloat_status_word(i387_get_control_word() | FPU_PR_80_BITS); + result = fyl2x(FPU_read_regi(0), FPU_read_regi(1), &status); + if (!FPU_exception(fetchdat, status.float_exception_flags, 0)) { + FPU_pop(); + FPU_save_regi(result, 0); + } + +next_ins: + CLOCK_CYCLES_FPU((fpu_type >= FPU_487SX) ? (x87_timings.fyl2x) : (x87_timings.fyl2x * cpu_multi)); + CONCURRENCY_CYCLES((fpu_type >= FPU_487SX) ? (x87_concurrency.fyl2x) : (x87_concurrency.fyl2x * cpu_multi)); + return 0; +} + +static int +sf_FPTAN(uint32_t fetchdat) +{ + const floatx80 floatx80_default_nan = packFloatx80(0, floatx80_default_nan_exp, floatx80_default_nan_fraction); + floatx80 y; + struct float_status_t status; + + FP_ENTER(); + cpu_state.pc++; + clear_C1(); + clear_C2(); + if (IS_TAG_EMPTY(0) || !IS_TAG_EMPTY(-1)) { + if (IS_TAG_EMPTY(0)) + FPU_exception(fetchdat, FPU_EX_Stack_Underflow, 0); + else + FPU_exception(fetchdat, FPU_EX_Stack_Overflow, 0); + + /* The masked response */ + if (is_IA_masked()) { + FPU_save_regi(floatx80_default_nan, 0); + FPU_push(); + FPU_save_regi(floatx80_default_nan, 0); + } + goto next_ins; + } + status = i387cw_to_softfloat_status_word(i387_get_control_word() | FPU_PR_80_BITS); + y = FPU_read_regi(0); + if (ftan(&y, &status) == -1) { + fpu_state.swd |= C2; + goto next_ins; + } + + if (floatx80_is_nan(y)) { + if (!FPU_exception(fetchdat, status.float_exception_flags, 0)) { + FPU_save_regi(y, 0); + FPU_push(); + FPU_save_regi(y, 0); + } + goto next_ins; + } + + if (!FPU_exception(fetchdat, status.float_exception_flags, 0)) { + FPU_save_regi(y, 0); + FPU_push(); + FPU_save_regi(Const_1, 0); + } + +next_ins: + CLOCK_CYCLES_FPU((fpu_type >= FPU_487SX) ? (x87_timings.fptan) : (x87_timings.fptan * cpu_multi)); + CONCURRENCY_CYCLES((fpu_type >= FPU_487SX) ? (x87_concurrency.fptan) : (x87_concurrency.fptan * cpu_multi)); + return 0; +} + +static int +sf_FPATAN(uint32_t fetchdat) +{ + floatx80 a; + floatx80 b; + floatx80 result; + struct float_status_t status; + + FP_ENTER(); + cpu_state.pc++; + if (IS_TAG_EMPTY(0) || IS_TAG_EMPTY(1)) { + FPU_stack_underflow(fetchdat, 1, 1); + goto next_ins; + } + a = FPU_read_regi(0); + b = FPU_read_regi(1); + status = i387cw_to_softfloat_status_word(i387_get_control_word() | FPU_PR_80_BITS); + result = fpatan(a, b, &status); + if (!FPU_exception(fetchdat, status.float_exception_flags, 0)) { + FPU_pop(); + FPU_save_regi(result, 0); + } + +next_ins: + CLOCK_CYCLES_FPU((fpu_type >= FPU_487SX) ? (x87_timings.fpatan) : (x87_timings.fpatan * cpu_multi)); + CONCURRENCY_CYCLES((fpu_type >= FPU_487SX) ? (x87_concurrency.fpatan) : (x87_concurrency.fpatan * cpu_multi)); + return 0; +} + +static int +sf_FXTRACT(uint32_t fetchdat) +{ + struct float_status_t status; + floatx80 a; + floatx80 b; + + FP_ENTER(); + cpu_state.pc++; + clear_C1(); + +#if 0 // TODO + if ((IS_TAG_EMPTY(0) || IS_TAG_EMPTY(-1))) { + if (IS_TAG_EMPTY(0)) + FPU_exception(fetchdat, FPU_EX_Stack_Underflow, 0); + else + FPU_exception(fetchdat, FPU_EX_Stack_Overflow, 0); + + /* The masked response */ + if (is_IA_masked()) { + FPU_save_regi(floatx80_default_nan, 0); + FPU_push(); + FPU_save_regi(floatx80_default_nan, 0); + } + goto next_ins; + } +#endif + + status = i387cw_to_softfloat_status_word(i387_get_control_word()); + a = FPU_read_regi(0); + b = floatx80_extract(&a, &status); + if (!FPU_exception(fetchdat, status.float_exception_flags, 0)) { + FPU_save_regi(b, 0); // exponent + FPU_push(); + FPU_save_regi(a, 0); // fraction + } + +#if 0 // TODO. +next_ins: +#endif + CLOCK_CYCLES_FPU((fpu_type >= FPU_487SX) ? (x87_timings.fxtract) : (x87_timings.fxtract * cpu_multi)); + CONCURRENCY_CYCLES((fpu_type >= FPU_487SX) ? (x87_concurrency.fxtract) : (x87_concurrency.fxtract * cpu_multi)); + return 0; +} + +static int +sf_FPREM1(uint32_t fetchdat) +{ + floatx80 a; + floatx80 b; + floatx80 result; + struct float_status_t status; + uint64_t quotient = 0; + int flags; + int cc; + + FP_ENTER(); + cpu_state.pc++; + clear_C1(); + clear_C2(); + if (IS_TAG_EMPTY(0) || IS_TAG_EMPTY(1)) { + FPU_stack_underflow(fetchdat, 0, 0); + goto next_ins; + } + status = i387cw_to_softfloat_status_word(i387_get_control_word()); + a = FPU_read_regi(0); + b = FPU_read_regi(1); + flags = floatx80_ieee754_remainder(a, b, &result, "ient, &status); + if (!FPU_exception(fetchdat, status.float_exception_flags, 0)) { + if (flags >= 0) { + cc = 0; + if (flags) + cc = C2; + else { + if (quotient & 1) + cc |= C1; + if (quotient & 2) + cc |= C3; + if (quotient & 4) + cc |= C0; + } + setcc(cc); + } + FPU_save_regi(result, 0); + } + +next_ins: + CLOCK_CYCLES_FPU((fpu_type >= FPU_487SX) ? (x87_timings.fprem1) : (x87_timings.fprem1 * cpu_multi)); + CONCURRENCY_CYCLES((fpu_type >= FPU_487SX) ? (x87_concurrency.fprem1) : (x87_concurrency.fprem1 * cpu_multi)); + return 0; +} + +static int +sf_FPREM(uint32_t fetchdat) +{ + floatx80 a; + floatx80 b; + floatx80 result; + struct float_status_t status; + uint64_t quotient = 0; + int flags; + int cc; + + FP_ENTER(); + cpu_state.pc++; + clear_C1(); + clear_C2(); + if (IS_TAG_EMPTY(0) || IS_TAG_EMPTY(1)) { + FPU_stack_underflow(fetchdat, 0, 0); + goto next_ins; + } + status = i387cw_to_softfloat_status_word(i387_get_control_word()); + a = FPU_read_regi(0); + b = FPU_read_regi(1); + // handle unsupported extended double-precision floating encodings + flags = floatx80_remainder(a, b, &result, "ient, &status); + if (!FPU_exception(fetchdat, status.float_exception_flags, 0)) { + if (flags >= 0) { + cc = 0; + if (flags) + cc = C2; + else { + if (quotient & 1) + cc |= C1; + if (quotient & 2) + cc |= C3; + if (quotient & 4) + cc |= C0; + } + setcc(cc); + } + FPU_save_regi(result, 0); + } + +next_ins: + CLOCK_CYCLES_FPU((fpu_type >= FPU_487SX) ? (x87_timings.fprem) : (x87_timings.fprem * cpu_multi)); + CONCURRENCY_CYCLES((fpu_type >= FPU_487SX) ? (x87_concurrency.fprem) : (x87_concurrency.fprem * cpu_multi)); + return 0; +} + +static int +sf_FYL2XP1(uint32_t fetchdat) +{ + floatx80 result; + struct float_status_t status; + + FP_ENTER(); + cpu_state.pc++; + clear_C1(); + if (IS_TAG_EMPTY(0) || IS_TAG_EMPTY(1)) { + FPU_stack_underflow(fetchdat, 1, 1); + goto next_ins; + } + status = i387cw_to_softfloat_status_word(i387_get_control_word() | FPU_PR_80_BITS); + result = fyl2xp1(FPU_read_regi(0), FPU_read_regi(1), &status); + if (!FPU_exception(fetchdat, status.float_exception_flags, 0)) { + FPU_save_regi(result, 1); + FPU_pop(); + } + +next_ins: + CLOCK_CYCLES_FPU((fpu_type >= FPU_487SX) ? (x87_timings.fyl2xp1) : (x87_timings.fyl2xp1 * cpu_multi)); + CONCURRENCY_CYCLES((fpu_type >= FPU_487SX) ? (x87_concurrency.fyl2xp1) : (x87_concurrency.fyl2xp1 * cpu_multi)); + return 0; +} + +#ifndef FPU_8087 +static int +sf_FSINCOS(uint32_t fetchdat) +{ + const floatx80 floatx80_default_nan = packFloatx80(0, floatx80_default_nan_exp, floatx80_default_nan_fraction); + struct float_status_t status; + floatx80 y; + floatx80 sin_y; + floatx80 cos_y; + + FP_ENTER(); + cpu_state.pc++; + clear_C1(); + clear_C2(); + if (IS_TAG_EMPTY(0) || !IS_TAG_EMPTY(-1)) { + if (IS_TAG_EMPTY(0)) + FPU_exception(fetchdat, FPU_EX_Stack_Underflow, 0); + else + FPU_exception(fetchdat, FPU_EX_Stack_Overflow, 0); + + /* The masked response */ + if (is_IA_masked()) { + FPU_save_regi(floatx80_default_nan, 0); + FPU_push(); + FPU_save_regi(floatx80_default_nan, 0); + } + goto next_ins; + } + status = i387cw_to_softfloat_status_word(i387_get_control_word() | FPU_PR_80_BITS); + y = FPU_read_regi(0); + if (fsincos(y, &sin_y, &cos_y, &status) == -1) { + fpu_state.swd |= C2; + goto next_ins; + } + if (!FPU_exception(fetchdat, status.float_exception_flags, 0)) { + FPU_save_regi(sin_y, 0); + FPU_push(); + FPU_save_regi(cos_y, 0); + } + +next_ins: + CLOCK_CYCLES_FPU((fpu_type >= FPU_487SX) ? (x87_timings.fsincos) : (x87_timings.fsincos * cpu_multi)); + CONCURRENCY_CYCLES((fpu_type >= FPU_487SX) ? (x87_concurrency.fsincos) : (x87_concurrency.fsincos * cpu_multi)); + return 0; +} +#endif + +static int +sf_FSCALE(uint32_t fetchdat) +{ + floatx80 result; + struct float_status_t status; + + FP_ENTER(); + cpu_state.pc++; + clear_C1(); + if (IS_TAG_EMPTY(0) || IS_TAG_EMPTY(1)) { + FPU_stack_underflow(fetchdat, 0, 0); + goto next_ins; + } + status = i387cw_to_softfloat_status_word(i387_get_control_word()); + result = floatx80_scale(FPU_read_regi(0), FPU_read_regi(1), &status); + if (!FPU_exception(fetchdat, status.float_exception_flags, 0)) + FPU_save_regi(result, 0); + +next_ins: + CLOCK_CYCLES_FPU((fpu_type >= FPU_487SX) ? (x87_timings.fscale) : (x87_timings.fscale * cpu_multi)); + CONCURRENCY_CYCLES((fpu_type >= FPU_487SX) ? (x87_concurrency.fscale) : (x87_concurrency.fscale * cpu_multi)); + return 0; +} + +#ifndef FPU_8087 +static int +sf_FSIN(uint32_t fetchdat) +{ + floatx80 y; + struct float_status_t status; + + FP_ENTER(); + cpu_state.pc++; + clear_C1(); + clear_C2(); + if (IS_TAG_EMPTY(0)) { + FPU_stack_underflow(fetchdat, 0, 0); + goto next_ins; + } + status = i387cw_to_softfloat_status_word(i387_get_control_word() | FPU_PR_80_BITS); + y = FPU_read_regi(0); + if (fsin(&y, &status) == -1) { + fpu_state.swd |= C2; + goto next_ins; + } + if (!FPU_exception(fetchdat, status.float_exception_flags, 0)) + FPU_save_regi(y, 0); + +next_ins: + CLOCK_CYCLES_FPU((fpu_type >= FPU_487SX) ? (x87_timings.fsin_cos) : (x87_timings.fsin_cos * cpu_multi)); + CONCURRENCY_CYCLES((fpu_type >= FPU_487SX) ? (x87_concurrency.fsin_cos) : (x87_concurrency.fsin_cos * cpu_multi)); + return 0; +} + +static int +sf_FCOS(uint32_t fetchdat) +{ + floatx80 y; + struct float_status_t status; + + FP_ENTER(); + cpu_state.pc++; + clear_C1(); + clear_C2(); + if (IS_TAG_EMPTY(0)) { + FPU_stack_underflow(fetchdat, 0, 0); + goto next_ins; + } + status = i387cw_to_softfloat_status_word(i387_get_control_word() | FPU_PR_80_BITS); + y = FPU_read_regi(0); + if (fcos(&y, &status) == -1) { + fpu_state.swd |= C2; + goto next_ins; + } + if (!FPU_exception(fetchdat, status.float_exception_flags, 0)) + FPU_save_regi(y, 0); + +next_ins: + CLOCK_CYCLES_FPU((fpu_type >= FPU_487SX) ? (x87_timings.fsin_cos) : (x87_timings.fsin_cos * cpu_multi)); + CONCURRENCY_CYCLES((fpu_type >= FPU_487SX) ? (x87_concurrency.fsin_cos) : (x87_concurrency.fsin_cos * cpu_multi)); + return 0; +} +#endif diff --git a/src/cpu/x87_timings.c b/src/cpu/x87_timings.c index 905ff1c6a..a23e195d2 100644 --- a/src/cpu/x87_timings.c +++ b/src/cpu/x87_timings.c @@ -10,461 +10,530 @@ x87_timings_t x87_timings; x87_timings_t x87_concurrency; -const x87_timings_t x87_timings_8087 = -{ - .f2xm1 = (310 + 630) / 2, - .fabs = (10 + 17) / 2, - .fadd = (70 + 100) / 2, - .fadd_32 = (90 + 120) / 2, - .fadd_64 = (95 + 125) / 2, - .fbld = (290 + 310) / 2, - .fbstp = (520 + 540) / 2, - .fchs = (10 + 17) / 2, - .fclex = (2 + 8) / 2, - .fcom = (40 + 50) / 2, - .fcom_32 = (60 + 70) / 2, - .fcom_64 = (65 + 75) / 2, - .fcos = 0, /*387+*/ - .fincdecstp = (6 + 12) / 2, - .fdisi_eni = (6 + 12) / 2, - .fdiv = (193 + 203) / 2, - .fdiv_32 = (215 + 225) / 2, - .fdiv_64 = (220 + 230) / 2, - .ffree = (9 + 16) / 2, - .fadd_i16 = (102 + 137) / 2, - .fadd_i32 = (108 + 143) / 2, - .fcom_i16 = (72 + 86) / 2, - .fcom_i32 = (78 + 91) / 2, - .fdiv_i16 = (224 + 238) / 2, - .fdiv_i32 = (230 + 243) / 2, - .fild_16 = (46 + 54) / 2, - .fild_32 = (50 + 60) / 2, - .fild_64 = (60 + 68) / 2, - .fmul_i16 = (124 + 138) / 2, - .fmul_i32 = (130 + 144) / 2, - .finit = (2 + 8) / 2, - .fist_16 = (80 + 90) / 2, - .fist_32 = (82 + 92) / 2, - .fist_64 = (94 + 105) / 2, - .fld = (17 + 22) / 2, - .fld_32 = (38 + 56) / 2, - .fld_64 = (40 + 60) / 2, - .fld_80 = (53 + 65) / 2, - .fld_z1 = (11 + 21) / 2, - .fld_const = (15 + 24) / 2, - .fldcw = (7 + 14) / 2, - .fldenv = (35 + 45) / 2, - .fmul = (90 + 145) / 2, - .fmul_32 = (110 + 125) / 2, - .fmul_64 = (154 + 168) / 2, - .fnop = (10 + 16) / 2, - .fpatan = (250 + 800) / 2, - .fprem = (15 + 190) / 2, - .fprem1 = 0, /*387+*/ - .fptan = (30 + 540) / 2, - .frndint = (16 + 50) / 2, - .frstor = (197 + 207) / 2, - .fsave = (197 + 207) / 2, - .fscale = (32 + 38) / 2, - .fsetpm = 0, /*287+*/ - .fsin_cos = 0, /*387+*/ - .fsincos = 0, /*387+*/ - .fsqrt = (180 + 186) / 2, - .fst = (15 + 22) / 2, - .fst_32 = (84 + 90) / 2, - .fst_64 = (96 + 104) / 2, - .fst_80 = (52 + 58) / 2, - .fstcw_sw = (12 + 18) / 2, - .fstenv = (40 + 50) / 2, - .ftst = (38 + 48) / 2, - .fucom = 0, /*387+*/ - .fwait = 4, - .fxam = (12 + 23) / 2, - .fxch = (10 + 15) / 2, - .fxtract = (27 + 55) / 2, - .fyl2x = (900 + 1100) / 2, - .fyl2xp1 = (700 + 1000) / 2 +const x87_timings_t x87_timings_8087 = { + .f2xm1 = (310 + 630) / 2, + .fabs = (10 + 17) / 2, + .fadd = (70 + 100) / 2, + .fadd_32 = (90 + 120) / 2, + .fadd_64 = (95 + 125) / 2, + .fbld = (290 + 310) / 2, + .fbstp = (520 + 540) / 2, + .fchs = (10 + 17) / 2, + .fclex = (2 + 8) / 2, + .fcom = (40 + 50) / 2, + .fcom_32 = (60 + 70) / 2, + .fcom_64 = (65 + 75) / 2, + .fcos = 0, /*387+*/ + .fincdecstp = (6 + 12) / 2, + .fdisi_eni = (6 + 12) / 2, + .fdiv = (193 + 203) / 2, + .fdiv_32 = (215 + 225) / 2, + .fdiv_64 = (220 + 230) / 2, + .ffree = (9 + 16) / 2, + .fadd_i16 = (102 + 137) / 2, + .fadd_i32 = (108 + 143) / 2, + .fcom_i16 = (72 + 86) / 2, + .fcom_i32 = (78 + 91) / 2, + .fdiv_i16 = (224 + 238) / 2, + .fdiv_i32 = (230 + 243) / 2, + .fild_16 = (46 + 54) / 2, + .fild_32 = (50 + 60) / 2, + .fild_64 = (60 + 68) / 2, + .fmul_i16 = (124 + 138) / 2, + .fmul_i32 = (130 + 144) / 2, + .finit = (2 + 8) / 2, + .fist_16 = (80 + 90) / 2, + .fist_32 = (82 + 92) / 2, + .fist_64 = (94 + 105) / 2, + .fld = (17 + 22) / 2, + .fld_32 = (38 + 56) / 2, + .fld_64 = (40 + 60) / 2, + .fld_80 = (53 + 65) / 2, + .fld_z1 = (11 + 21) / 2, + .fld_const = (15 + 24) / 2, + .fldcw = (7 + 14) / 2, + .fldenv = (35 + 45) / 2, + .fmul = (90 + 145) / 2, + .fmul_32 = (110 + 125) / 2, + .fmul_64 = (154 + 168) / 2, + .fnop = (10 + 16) / 2, + .fpatan = (250 + 800) / 2, + .fprem = (15 + 190) / 2, + .fprem1 = 0, /*387+*/ + .fptan = (30 + 540) / 2, + .frndint = (16 + 50) / 2, + .frstor = (197 + 207) / 2, + .fsave = (197 + 207) / 2, + .fscale = (32 + 38) / 2, + .fsetpm = 0, /*287+*/ + .fsin_cos = 0, /*387+*/ + .fsincos = 0, /*387+*/ + .fsqrt = (180 + 186) / 2, + .fst = (15 + 22) / 2, + .fst_32 = (84 + 90) / 2, + .fst_64 = (96 + 104) / 2, + .fst_80 = (52 + 58) / 2, + .fstcw_sw = (12 + 18) / 2, + .fstenv = (40 + 50) / 2, + .ftst = (38 + 48) / 2, + .fucom = 0, /*387+*/ + .fwait = 4, + .fxam = (12 + 23) / 2, + .fxch = (10 + 15) / 2, + .fxtract = (27 + 55) / 2, + .fyl2x = (900 + 1100) / 2, + .fyl2xp1 = (700 + 1000) / 2 +}; + +const x87_timings_t x87_timings_80187 = { + .f2xm1 = (310 + 630) / 2, + .fabs = (10 + 17) / 2, + .fadd = (70 + 100) / 2, + .fadd_32 = (90 + 120) / 2, + .fadd_64 = (95 + 125) / 2, + .fbld = (290 + 310) / 2, + .fbstp = (520 + 540) / 2, + .fchs = (10 + 17) / 2, + .fclex = (2 + 8) / 2, + .fcom = (40 + 50) / 2, + .fcom_32 = (60 + 70) / 2, + .fcom_64 = (65 + 75) / 2, + .fcos = 0, /*387+*/ + .fincdecstp = (6 + 12) / 2, + .fdisi_eni = (6 + 12) / 2, + .fdiv = (193 + 203) / 2, + .fdiv_32 = (215 + 225) / 2, + .fdiv_64 = (220 + 230) / 2, + .ffree = (9 + 16) / 2, + .fadd_i16 = (102 + 137) / 2, + .fadd_i32 = (108 + 143) / 2, + .fcom_i16 = (72 + 86) / 2, + .fcom_i32 = (78 + 91) / 2, + .fdiv_i16 = (224 + 238) / 2, + .fdiv_i32 = (230 + 243) / 2, + .fild_16 = (46 + 54) / 2, + .fild_32 = (50 + 60) / 2, + .fild_64 = (60 + 68) / 2, + .fmul_i16 = (124 + 138) / 2, + .fmul_i32 = (130 + 144) / 2, + .finit = (2 + 8) / 2, + .fist_16 = (80 + 90) / 2, + .fist_32 = (82 + 92) / 2, + .fist_64 = (94 + 105) / 2, + .fld = (17 + 22) / 2, + .fld_32 = (38 + 56) / 2, + .fld_64 = (40 + 60) / 2, + .fld_80 = (53 + 65) / 2, + .fld_z1 = (11 + 21) / 2, + .fld_const = (15 + 24) / 2, + .fldcw = (7 + 14) / 2, + .fldenv = (35 + 45) / 2, + .fmul = (90 + 145) / 2, + .fmul_32 = (110 + 125) / 2, + .fmul_64 = (154 + 168) / 2, + .fnop = (10 + 16) / 2, + .fpatan = (250 + 800) / 2, + .fprem = (15 + 190) / 2, + .fprem1 = 0, /*387+*/ + .fptan = (30 + 540) / 2, + .frndint = (16 + 50) / 2, + .frstor = (197 + 207) / 2, + .fsave = (197 + 207) / 2, + .fscale = (32 + 38) / 2, + .fsetpm = 0, /*287+*/ + .fsin_cos = 0, /*387+*/ + .fsincos = 0, /*387+*/ + .fsqrt = (180 + 186) / 2, + .fst = (15 + 22) / 2, + .fst_32 = (84 + 90) / 2, + .fst_64 = (96 + 104) / 2, + .fst_80 = (52 + 58) / 2, + .fstcw_sw = (12 + 18) / 2, + .fstenv = (40 + 50) / 2, + .ftst = (38 + 48) / 2, + .fucom = 0, /*387+*/ + .fwait = 4, + .fxam = (12 + 23) / 2, + .fxch = (10 + 15) / 2, + .fxtract = (27 + 55) / 2, + .fyl2x = (900 + 1100) / 2, + .fyl2xp1 = (700 + 1000) / 2 }; /*Mostly the same as 8087*/ -const x87_timings_t x87_timings_287 = -{ - .f2xm1 = (310 + 630) / 2, - .fabs = (10 + 17) / 2, - .fadd = (70 + 100) / 2, - .fadd_32 = (90 + 120) / 2, - .fadd_64 = (95 + 125) / 2, - .fbld = (290 + 310) / 2, - .fbstp = (520 + 540) / 2, - .fchs = (10 + 17) / 2, - .fclex = (2 + 8) / 2, - .fcom = (40 + 50) / 2, - .fcom_32 = (60 + 70) / 2, - .fcom_64 = (65 + 75) / 2, - .fcos = 0, /*387+*/ - .fincdecstp = (6 + 12) / 2, - .fdisi_eni = 2, - .fdiv = (193 + 203) / 2, - .fdiv_32 = (215 + 225) / 2, - .fdiv_64 = (220 + 230) / 2, - .ffree = (9 + 16) / 2, - .fadd_i16 = (102 + 137) / 2, - .fadd_i32 = (108 + 143) / 2, - .fcom_i16 = (72 + 86) / 2, - .fcom_i32 = (78 + 91) / 2, - .fdiv_i16 = (224 + 238) / 2, - .fdiv_i32 = (230 + 243) / 2, - .fild_16 = (46 + 54) / 2, - .fild_32 = (50 + 60) / 2, - .fild_64 = (60 + 68) / 2, - .fmul_i16 = (124 + 138) / 2, - .fmul_i32 = (130 + 144) / 2, - .finit = (2 + 8) / 2, - .fist_16 = (80 + 90) / 2, - .fist_32 = (82 + 92) / 2, - .fist_64 = (94 + 105) / 2, - .fld = (17 + 22) / 2, - .fld_32 = (38 + 56) / 2, - .fld_64 = (40 + 60) / 2, - .fld_80 = (53 + 65) / 2, - .fld_z1 = (11 + 21) / 2, - .fld_const = (15 + 24) / 2, - .fldcw = (7 + 14) / 2, - .fldenv = (35 + 45) / 2, - .fmul = (90 + 145) / 2, - .fmul_32 = (110 + 125) / 2, - .fmul_64 = (154 + 168) / 2, - .fnop = (10 + 16) / 2, - .fpatan = (250 + 800) / 2, - .fprem = (15 + 190) / 2, - .fprem1 = 0, /*387+*/ - .fptan = (30 + 540) / 2, - .frndint = (16 + 50) / 2, - .frstor = (197 + 207) / 2, - .fsave = (197 + 207) / 2, - .fscale = (32 + 38) / 2, - .fsetpm = (2 + 8) / 2, /*287+*/ - .fsin_cos = 0, /*387+*/ - .fsincos = 0, /*387+*/ - .fsqrt = (180 + 186) / 2, - .fst = (15 + 22) / 2, - .fst_32 = (84 + 90) / 2, - .fst_64 = (96 + 104) / 2, - .fst_80 = (52 + 58) / 2, - .fstcw_sw = (12 + 18) / 2, - .fstenv = (40 + 50) / 2, - .ftst = (38 + 48) / 2, - .fucom = 0, /*387+*/ - .fwait = 3, - .fxam = (12 + 23) / 2, - .fxch = (10 + 15) / 2, - .fxtract = (27 + 55) / 2, - .fyl2x = (900 + 1100) / 2, - .fyl2xp1 = (700 + 1000) / 2 +const x87_timings_t x87_timings_287 = { + .f2xm1 = (310 + 630) / 2, + .fabs = (10 + 17) / 2, + .fadd = (70 + 100) / 2, + .fadd_32 = (90 + 120) / 2, + .fadd_64 = (95 + 125) / 2, + .fbld = (290 + 310) / 2, + .fbstp = (520 + 540) / 2, + .fchs = (10 + 17) / 2, + .fclex = (2 + 8) / 2, + .fcom = (40 + 50) / 2, + .fcom_32 = (60 + 70) / 2, + .fcom_64 = (65 + 75) / 2, + .fcos = 0, /*387+*/ + .fincdecstp = (6 + 12) / 2, + .fdisi_eni = 2, + .fdiv = (193 + 203) / 2, + .fdiv_32 = (215 + 225) / 2, + .fdiv_64 = (220 + 230) / 2, + .ffree = (9 + 16) / 2, + .fadd_i16 = (102 + 137) / 2, + .fadd_i32 = (108 + 143) / 2, + .fcom_i16 = (72 + 86) / 2, + .fcom_i32 = (78 + 91) / 2, + .fdiv_i16 = (224 + 238) / 2, + .fdiv_i32 = (230 + 243) / 2, + .fild_16 = (46 + 54) / 2, + .fild_32 = (50 + 60) / 2, + .fild_64 = (60 + 68) / 2, + .fmul_i16 = (124 + 138) / 2, + .fmul_i32 = (130 + 144) / 2, + .finit = (2 + 8) / 2, + .fist_16 = (80 + 90) / 2, + .fist_32 = (82 + 92) / 2, + .fist_64 = (94 + 105) / 2, + .fld = (17 + 22) / 2, + .fld_32 = (38 + 56) / 2, + .fld_64 = (40 + 60) / 2, + .fld_80 = (53 + 65) / 2, + .fld_z1 = (11 + 21) / 2, + .fld_const = (15 + 24) / 2, + .fldcw = (7 + 14) / 2, + .fldenv = (35 + 45) / 2, + .fmul = (90 + 145) / 2, + .fmul_32 = (110 + 125) / 2, + .fmul_64 = (154 + 168) / 2, + .fnop = (10 + 16) / 2, + .fpatan = (250 + 800) / 2, + .fprem = (15 + 190) / 2, + .fprem1 = 0, /*387+*/ + .fptan = (30 + 540) / 2, + .frndint = (16 + 50) / 2, + .frstor = (197 + 207) / 2, + .fsave = (197 + 207) / 2, + .fscale = (32 + 38) / 2, + .fsetpm = (2 + 8) / 2, /*287+*/ + .fsin_cos = 0, /*387+*/ + .fsincos = 0, /*387+*/ + .fsqrt = (180 + 186) / 2, + .fst = (15 + 22) / 2, + .fst_32 = (84 + 90) / 2, + .fst_64 = (96 + 104) / 2, + .fst_80 = (52 + 58) / 2, + .fstcw_sw = (12 + 18) / 2, + .fstenv = (40 + 50) / 2, + .ftst = (38 + 48) / 2, + .fucom = 0, /*387+*/ + .fwait = 3, + .fxam = (12 + 23) / 2, + .fxch = (10 + 15) / 2, + .fxtract = (27 + 55) / 2, + .fyl2x = (900 + 1100) / 2, + .fyl2xp1 = (700 + 1000) / 2 }; -const x87_timings_t x87_timings_387 = -{ - .f2xm1 = (211 + 476) / 2, - .fabs = 22, - .fadd = (23 + 34) / 2, - .fadd_32 = (24 + 32) / 2, - .fadd_64 = (29 + 37) / 2, - .fbld = (266 + 275) / 2, - .fbstp = (512 + 534) / 2, - .fchs = (24 + 25) / 2, - .fclex = 11, - .fcom = 24, - .fcom_32 = 26, - .fcom_64 = 31, - .fcos = (122 + 772) / 2, - .fincdecstp = 22, - .fdisi_eni = 2, - .fdiv = (88 + 91) / 2, - .fdiv_32 = 89, - .fdiv_64 = 94, - .ffree = 18, - .fadd_i16 = (71 + 85) / 2, - .fadd_i32 = (57 + 72) / 2, - .fcom_i16 = (71 + 75) / 2, - .fcom_i32 = (56 + 63) / 2, - .fdiv_i16 = (136 + 140) / 2, - .fdiv_i32 = (120 + 127) / 2, - .fild_16 = (61 + 65) / 2, - .fild_32 = (45 + 52) / 2, - .fild_64 = (56 + 67) / 2, - .fmul_i16 = (76 + 87) / 2, - .fmul_i32 = (61 + 82) / 2, - .finit = 33, - .fist_16 = (82 + 95) / 2, - .fist_32 = (79 + 93) / 2, - .fist_64 = (80 + 97) / 2, - .fld = 14, - .fld_32 = 20, - .fld_64 = 25, - .fld_80 = 44, - .fld_z1 = (20 + 24) / 2, - .fld_const = 40, - .fldcw = 19, - .fldenv = 71, - .fmul = (29 + 57) / 2, - .fmul_32 = (27 + 35) / 2, - .fmul_64 = (32 + 57) / 2, - .fnop = 12, - .fpatan = (314 + 487) / 2, - .fprem = (74 + 155) / 2, - .fprem1 = (95 + 185) / 2, - .fptan = (191 + 497) / 2, - .frndint = (66 + 80) / 2, - .frstor = 308, - .fsave = 375, - .fscale = (67 + 86) / 2, - .fsetpm = 12, - .fsin_cos = (122 + 771) / 2, - .fsincos = (194 + 809) / 2, - .fsqrt = (122 + 129) / 2, - .fst = 11, - .fst_32 = 44, - .fst_64 = 45, - .fst_80 = 53, - .fstcw_sw = 15, - .fstenv = 103, - .ftst = 28, - .fucom = 24, - .fwait = 6, - .fxam = (30 + 38) / 2, - .fxch = 18, - .fxtract = (70 + 76) / 2, - .fyl2x = (120 + 538) / 2, - .fyl2xp1 = (257 + 547) / 2 +const x87_timings_t x87_timings_387 = { + .f2xm1 = (211 + 476) / 2, + .fabs = 22, + .fadd = (23 + 34) / 2, + .fadd_32 = (24 + 32) / 2, + .fadd_64 = (29 + 37) / 2, + .fbld = (266 + 275) / 2, + .fbstp = (512 + 534) / 2, + .fchs = (24 + 25) / 2, + .fclex = 11, + .fcom = 24, + .fcom_32 = 26, + .fcom_64 = 31, + .fcos = (122 + 772) / 2, + .fincdecstp = 22, + .fdisi_eni = 2, + .fdiv = (88 + 91) / 2, + .fdiv_32 = 89, + .fdiv_64 = 94, + .ffree = 18, + .fadd_i16 = (71 + 85) / 2, + .fadd_i32 = (57 + 72) / 2, + .fcom_i16 = (71 + 75) / 2, + .fcom_i32 = (56 + 63) / 2, + .fdiv_i16 = (136 + 140) / 2, + .fdiv_i32 = (120 + 127) / 2, + .fild_16 = (61 + 65) / 2, + .fild_32 = (45 + 52) / 2, + .fild_64 = (56 + 67) / 2, + .fmul_i16 = (76 + 87) / 2, + .fmul_i32 = (61 + 82) / 2, + .finit = 33, + .fist_16 = (82 + 95) / 2, + .fist_32 = (79 + 93) / 2, + .fist_64 = (80 + 97) / 2, + .fld = 14, + .fld_32 = 20, + .fld_64 = 25, + .fld_80 = 44, + .fld_z1 = (20 + 24) / 2, + .fld_const = 40, + .fldcw = 19, + .fldenv = 71, + .fmul = (29 + 57) / 2, + .fmul_32 = (27 + 35) / 2, + .fmul_64 = (32 + 57) / 2, + .fnop = 12, + .fpatan = (314 + 487) / 2, + .fprem = (74 + 155) / 2, + .fprem1 = (95 + 185) / 2, + .fptan = (191 + 497) / 2, + .frndint = (66 + 80) / 2, + .frstor = 308, + .fsave = 375, + .fscale = (67 + 86) / 2, + .fsetpm = 12, + .fsin_cos = (122 + 771) / 2, + .fsincos = (194 + 809) / 2, + .fsqrt = (122 + 129) / 2, + .fst = 11, + .fst_32 = 44, + .fst_64 = 45, + .fst_80 = 53, + .fstcw_sw = 15, + .fstenv = 103, + .ftst = 28, + .fucom = 24, + .fwait = 6, + .fxam = (30 + 38) / 2, + .fxch = 18, + .fxtract = (70 + 76) / 2, + .fyl2x = (120 + 538) / 2, + .fyl2xp1 = (257 + 547) / 2 }; -const x87_timings_t x87_timings_486 = -{ - .f2xm1 = (140 + 270) / 2, - .fabs = 3, - .fadd = (8 + 20) / 2, - .fadd_32 = (8 + 20) / 2, - .fadd_64 = (8 + 20) / 2, - .fbld = (70 + 103) / 2, - .fbstp = (172 + 176) / 2, - .fchs = 6, - .fclex = 7, - .fcom = 4, - .fcom_32 = 4, - .fcom_64 = 4, - .fcos = (257 + 354) / 2, - .fincdecstp = 3, - .fdisi_eni = 3, - .fdiv = 73, - .fdiv_32 = 73, - .fdiv_64 = 73, - .ffree = 3, - .fadd_i16 = (20 + 35) / 2, - .fadd_i32 = (19 + 32) / 2, - .fcom_i16 = (16 + 20) / 2, - .fcom_i32 = (15 + 17) / 2, - .fdiv_i16 = (85 + 89) / 2, - .fdiv_i32 = (84 + 86) / 2, - .fild_16 = (13 + 16) / 2, - .fild_32 = (9 + 12) / 2, - .fild_64 = (10 + 18) / 2, - .fmul_i16 = (23 + 27) / 2, - .fmul_i32 = (22 + 24) / 2, - .finit = 17, - .fist_16 = (29 + 34) / 2, - .fist_32 = (28 + 34) / 2, - .fist_64 = (29 + 34) / 2, - .fld = 4, - .fld_32 = 3, - .fld_64 = 3, - .fld_80 = 6, - .fld_z1 = 4, - .fld_const = 8, - .fldcw = 4, - .fldenv = 34, - .fmul = 16, - .fmul_32 = 11, - .fmul_64 = 14, - .fnop = 3, - .fpatan = (218 + 303) / 2, - .fprem = (70 + 138) / 2, - .fprem1 = (72 + 167) / 2, - .fptan = (200 + 273) / 2, - .frndint = (21 + 30) / 2, - .frstor = 120, - .fsave = 143, - .fscale = (30 + 32) / 2, - .fsetpm = 3, - .fsin_cos = (257 + 354) / 2, - .fsincos = (292 + 365) / 2, - .fsqrt = (83 + 87) / 2, - .fst = 3, - .fst_32 = 7, - .fst_64 = 8, - .fst_80 = 6, - .fstcw_sw = 3, - .fstenv = 56, - .ftst = 4, - .fucom = 4, - .fwait = (1 + 3) / 2, - .fxam = 8, - .fxch = 4, - .fxtract = (16 + 20) / 2, - .fyl2x = (196 + 329) / 2, - .fyl2xp1 = (171 + 326) / 2 +const x87_timings_t x87_timings_486 = { + .f2xm1 = (140 + 270) / 2, + .fabs = 3, + .fadd = (8 + 20) / 2, + .fadd_32 = (8 + 20) / 2, + .fadd_64 = (8 + 20) / 2, + .fbld = (70 + 103) / 2, + .fbstp = (172 + 176) / 2, + .fchs = 6, + .fclex = 7, + .fcom = 4, + .fcom_32 = 4, + .fcom_64 = 4, + .fcos = (257 + 354) / 2, + .fincdecstp = 3, + .fdisi_eni = 3, + .fdiv = 73, + .fdiv_32 = 73, + .fdiv_64 = 73, + .ffree = 3, + .fadd_i16 = (20 + 35) / 2, + .fadd_i32 = (19 + 32) / 2, + .fcom_i16 = (16 + 20) / 2, + .fcom_i32 = (15 + 17) / 2, + .fdiv_i16 = (85 + 89) / 2, + .fdiv_i32 = (84 + 86) / 2, + .fild_16 = (13 + 16) / 2, + .fild_32 = (9 + 12) / 2, + .fild_64 = (10 + 18) / 2, + .fmul_i16 = (23 + 27) / 2, + .fmul_i32 = (22 + 24) / 2, + .finit = 17, + .fist_16 = (29 + 34) / 2, + .fist_32 = (28 + 34) / 2, + .fist_64 = (29 + 34) / 2, + .fld = 4, + .fld_32 = 3, + .fld_64 = 3, + .fld_80 = 6, + .fld_z1 = 4, + .fld_const = 8, + .fldcw = 4, + .fldenv = 34, + .fmul = 16, + .fmul_32 = 11, + .fmul_64 = 14, + .fnop = 3, + .fpatan = (218 + 303) / 2, + .fprem = (70 + 138) / 2, + .fprem1 = (72 + 167) / 2, + .fptan = (200 + 273) / 2, + .frndint = (21 + 30) / 2, + .frstor = 120, + .fsave = 143, + .fscale = (30 + 32) / 2, + .fsetpm = 3, + .fsin_cos = (257 + 354) / 2, + .fsincos = (292 + 365) / 2, + .fsqrt = (83 + 87) / 2, + .fst = 3, + .fst_32 = 7, + .fst_64 = 8, + .fst_80 = 6, + .fstcw_sw = 3, + .fstenv = 56, + .ftst = 4, + .fucom = 4, + .fwait = (1 + 3) / 2, + .fxam = 8, + .fxch = 4, + .fxtract = (16 + 20) / 2, + .fyl2x = (196 + 329) / 2, + .fyl2xp1 = (171 + 326) / 2 }; /* this should be used for FPUs with no concurrency. some pre-486DX Cyrix FPUs reportedly are like this. */ -const x87_timings_t x87_concurrency_none = -{ - .f2xm1 = 0, - .fabs = 0, - .fadd = 0, - .fadd_32 = 0, - .fadd_64 = 0, - .fbld = 0, - .fbstp = 0, - .fchs = 0, - .fclex = 0, - .fcom = 0, - .fcom_32 = 0, - .fcom_64 = 0, - .fcos = 0, - .fincdecstp = 0, - .fdisi_eni = 0, - .fdiv = 0, - .fdiv_32 = 0, - .fdiv_64 = 0, - .ffree = 0, - .fadd_i16 = 0, - .fadd_i32 = 0, - .fcom_i16 = 0, - .fcom_i32 = 0, - .fdiv_i16 = 0, - .fdiv_i32 = 0, - .fild_16 = 0, - .fild_32 = 0, - .fild_64 = 0, - .fmul_i16 = 0, - .fmul_i32 = 0, - .finit = 0, - .fist_16 = 0, - .fist_32 = 0, - .fist_64 = 0, - .fld = 0, - .fld_32 = 0, - .fld_64 = 0, - .fld_80 = 0, - .fld_z1 = 0, - .fld_const = 0, - .fldcw = 0, - .fldenv = 0, - .fmul = 0, - .fmul_32 = 0, - .fmul_64 = 0, - .fnop = 0, - .fpatan = 0, - .fprem = 0, - .fprem1 = 0, - .fptan = 0, - .frndint = 0, - .frstor = 0, - .fsave = 0, - .fscale = 0, - .fsetpm = 0, - .fsin_cos = 0, - .fsincos = 0, - .fsqrt = 0, - .fst = 0, - .fst_32 = 0, - .fst_64 = 0, - .fst_80 = 0, - .fstcw_sw = 0, - .fstenv = 0, - .ftst = 0, - .fucom = 0, - .fwait = 0, - .fxam = 0, - .fxch = 0, - .fxtract = 0, - .fyl2x = 0, - .fyl2xp1 = 0, +const x87_timings_t x87_concurrency_none = { + .f2xm1 = 0, + .fabs = 0, + .fadd = 0, + .fadd_32 = 0, + .fadd_64 = 0, + .fbld = 0, + .fbstp = 0, + .fchs = 0, + .fclex = 0, + .fcom = 0, + .fcom_32 = 0, + .fcom_64 = 0, + .fcos = 0, + .fincdecstp = 0, + .fdisi_eni = 0, + .fdiv = 0, + .fdiv_32 = 0, + .fdiv_64 = 0, + .ffree = 0, + .fadd_i16 = 0, + .fadd_i32 = 0, + .fcom_i16 = 0, + .fcom_i32 = 0, + .fdiv_i16 = 0, + .fdiv_i32 = 0, + .fild_16 = 0, + .fild_32 = 0, + .fild_64 = 0, + .fmul_i16 = 0, + .fmul_i32 = 0, + .finit = 0, + .fist_16 = 0, + .fist_32 = 0, + .fist_64 = 0, + .fld = 0, + .fld_32 = 0, + .fld_64 = 0, + .fld_80 = 0, + .fld_z1 = 0, + .fld_const = 0, + .fldcw = 0, + .fldenv = 0, + .fmul = 0, + .fmul_32 = 0, + .fmul_64 = 0, + .fnop = 0, + .fpatan = 0, + .fprem = 0, + .fprem1 = 0, + .fptan = 0, + .frndint = 0, + .frstor = 0, + .fsave = 0, + .fscale = 0, + .fsetpm = 0, + .fsin_cos = 0, + .fsincos = 0, + .fsqrt = 0, + .fst = 0, + .fst_32 = 0, + .fst_64 = 0, + .fst_80 = 0, + .fstcw_sw = 0, + .fstenv = 0, + .ftst = 0, + .fucom = 0, + .fwait = 0, + .fxam = 0, + .fxch = 0, + .fxtract = 0, + .fyl2x = 0, + .fyl2xp1 = 0, }; -const x87_timings_t x87_concurrency_486 = -{ - .f2xm1 = 2, - .fabs = 0, - .fadd = 7, - .fadd_32 = 7, - .fadd_64 = 7, - .fbld = 8, - .fbstp = 0, - .fchs = 0, - .fclex = 0, - .fcom = 1, - .fcom_32 = 1, - .fcom_64 = 1, - .fcos = 2, - .fincdecstp = 0, - .fdisi_eni = 0, - .fdiv = 70, - .fdiv_32 = 70, - .fdiv_64 = 70, - .ffree = 0, - .fadd_i16 = 7, - .fadd_i32 = 7, - .fcom_i16 = 1, - .fcom_i32 = 1, - .fdiv_i16 = 70, - .fdiv_i32 = 70, - .fild_16 = 4, - .fild_32 = 4, - .fild_64 = 8, - .fmul_i16 = 8, - .fmul_i32 = 8, - .finit = 0, - .fist_16 = 0, - .fist_32 = 0, - .fist_64 = 0, - .fld = 0, - .fld_32 = 0, - .fld_64 = 0, - .fld_80 = 0, - .fld_z1 = 0, - .fld_const = 2, - .fldcw = 0, - .fldenv = 0, - .fmul = 13, - .fmul_32 = 8, - .fmul_64 = 11, - .fnop = 0, - .fpatan = 5, - .fprem = 2, - .fprem1 = 6, - .fptan = 70, - .frndint = 0, - .frstor = 0, - .fsave = 0, - .fscale = 2, - .fsetpm = 0, - .fsin_cos = 2, - .fsincos = 2, - .fsqrt = 70, - .fst = 0, - .fst_32 = 0, - .fst_64 = 0, - .fst_80 = 0, - .fstcw_sw = 0, - .fstenv = 0, - .ftst = 1, - .fucom = 1, - .fwait = 0, - .fxam = 0, - .fxch = 0, - .fxtract = 4, - .fyl2x = 13, - .fyl2xp1 = 13, -}; \ No newline at end of file +const x87_timings_t x87_concurrency_486 = { + .f2xm1 = 2, + .fabs = 0, + .fadd = 7, + .fadd_32 = 7, + .fadd_64 = 7, + .fbld = 8, + .fbstp = 0, + .fchs = 0, + .fclex = 0, + .fcom = 1, + .fcom_32 = 1, + .fcom_64 = 1, + .fcos = 2, + .fincdecstp = 0, + .fdisi_eni = 0, + .fdiv = 70, + .fdiv_32 = 70, + .fdiv_64 = 70, + .ffree = 0, + .fadd_i16 = 7, + .fadd_i32 = 7, + .fcom_i16 = 1, + .fcom_i32 = 1, + .fdiv_i16 = 70, + .fdiv_i32 = 70, + .fild_16 = 4, + .fild_32 = 4, + .fild_64 = 8, + .fmul_i16 = 8, + .fmul_i32 = 8, + .finit = 0, + .fist_16 = 0, + .fist_32 = 0, + .fist_64 = 0, + .fld = 0, + .fld_32 = 0, + .fld_64 = 0, + .fld_80 = 0, + .fld_z1 = 0, + .fld_const = 2, + .fldcw = 0, + .fldenv = 0, + .fmul = 13, + .fmul_32 = 8, + .fmul_64 = 11, + .fnop = 0, + .fpatan = 5, + .fprem = 2, + .fprem1 = 6, + .fptan = 70, + .frndint = 0, + .frstor = 0, + .fsave = 0, + .fscale = 2, + .fsetpm = 0, + .fsin_cos = 2, + .fsincos = 2, + .fsqrt = 70, + .fst = 0, + .fst_32 = 0, + .fst_64 = 0, + .fst_80 = 0, + .fstcw_sw = 0, + .fstenv = 0, + .ftst = 1, + .fucom = 1, + .fwait = 0, + .fxam = 0, + .fxch = 0, + .fxtract = 4, + .fyl2x = 13, + .fyl2xp1 = 13, +}; diff --git a/src/cpu/x87_timings.h b/src/cpu/x87_timings.h index c7dac8270..7389ddeb6 100644 --- a/src/cpu/x87_timings.h +++ b/src/cpu/x87_timings.h @@ -1,54 +1,55 @@ typedef struct { - int f2xm1; - int fabs; - int fadd, fadd_32, fadd_64; - int fbld; - int fbstp; - int fchs; - int fclex; - int fcom, fcom_32, fcom_64; - int fcos; - int fincdecstp; - int fdisi_eni; - int fdiv, fdiv_32, fdiv_64; - int ffree; - int fadd_i16, fadd_i32; - int fcom_i16, fcom_i32; - int fdiv_i16, fdiv_i32; - int fild_16, fild_32, fild_64; - int fmul_i16, fmul_i32; - int finit; - int fist_16, fist_32, fist_64; - int fld, fld_32, fld_64, fld_80; - int fld_z1, fld_const; - int fldcw; - int fldenv; - int fmul, fmul_32, fmul_64; - int fnop; - int fpatan; - int fprem, fprem1; - int fptan; - int frndint; - int frstor; - int fsave; - int fscale; - int fsetpm; - int fsin_cos, fsincos; - int fsqrt; - int fst, fst_32, fst_64, fst_80; - int fstcw_sw; - int fstenv; - int ftst; - int fucom; - int fwait; - int fxam; - int fxch; - int fxtract; - int fyl2x, fyl2xp1; + int f2xm1; + int fabs; + int fadd, fadd_32, fadd_64; + int fbld; + int fbstp; + int fchs; + int fclex; + int fcom, fcom_32, fcom_64; + int fcos; + int fincdecstp; + int fdisi_eni; + int fdiv, fdiv_32, fdiv_64; + int ffree; + int fadd_i16, fadd_i32; + int fcom_i16, fcom_i32; + int fdiv_i16, fdiv_i32; + int fild_16, fild_32, fild_64; + int fmul_i16, fmul_i32; + int finit; + int fist_16, fist_32, fist_64; + int fld, fld_32, fld_64, fld_80; + int fld_z1, fld_const; + int fldcw; + int fldenv; + int fmul, fmul_32, fmul_64; + int fnop; + int fpatan; + int fprem, fprem1; + int fptan; + int frndint; + int frstor; + int fsave; + int fscale; + int fsetpm; + int fsin_cos, fsincos; + int fsqrt; + int fst, fst_32, fst_64, fst_80; + int fstcw_sw; + int fstenv; + int ftst; + int fucom; + int fwait; + int fxam; + int fxch; + int fxtract; + int fyl2x, fyl2xp1; } x87_timings_t; extern const x87_timings_t x87_timings_8087; +extern const x87_timings_t x87_timings_80187; extern const x87_timings_t x87_timings_287; extern const x87_timings_t x87_timings_387; extern const x87_timings_t x87_timings_486; @@ -56,4 +57,4 @@ extern const x87_timings_t x87_timings_486; extern const x87_timings_t x87_concurrency_486; extern x87_timings_t x87_timings; -extern x87_timings_t x87_concurrency; \ No newline at end of file +extern x87_timings_t x87_concurrency; diff --git a/src/cpu/x886seg_2386.c b/src/cpu/x886seg_2386.c new file mode 100644 index 000000000..335c757e4 --- /dev/null +++ b/src/cpu/x886seg_2386.c @@ -0,0 +1,22 @@ +/* + * 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. + * + * x86 CPU segment emulation for the 286/386 interpreter. + * + * + * + * Authors: Sarah Walker, + * Miran Grca, + * + * Copyright 2008-2018 Sarah Walker. + * Copyright 2016-2018 Miran Grca. + */ +#ifndef OPS_286_386 +# define OPS_286_386 +#endif +#include "x86seg.c" diff --git a/src/crcspeed/crc64speed.c b/src/crcspeed/crc64speed.c index b1a7bbb94..b32990b12 100644 --- a/src/crcspeed/crc64speed.c +++ b/src/crcspeed/crc64speed.c @@ -36,7 +36,8 @@ * each 8x256 lookup table is 16k. */ #ifndef CRC64SPEED_DUAL static uint64_t crc64_table[8][256] = {{0}}; -static void *crc64_table_little = NULL, *crc64_table_big = NULL; +static void *crc64_table_little = NULL; +static void *crc64_table_big = NULL; static const bool dual = false; #else static uint64_t crc64_table_little[8][256] = {{0}}; @@ -124,7 +125,7 @@ static inline uint_fast64_t crc_reflect(uint_fast64_t data, size_t data_len) { * \return The updated crc value. ******************************************************************************/ uint64_t crc64(uint_fast64_t crc, const void *in_data, const uint64_t len) { - const uint8_t *data = in_data; + const uint8_t *data = (uint8_t *) in_data; bool bit; for (uint64_t offset = 0; offset < len; offset++) { @@ -152,7 +153,7 @@ uint64_t crc64(uint_fast64_t crc, const void *in_data, const uint64_t len) { /* Only for testing; doesn't support DUAL */ uint64_t crc64_lookup(uint64_t crc, const void *in_data, const uint64_t len) { - const uint8_t *data = in_data; + const uint8_t *data = (uint8_t *) in_data; for (size_t i = 0; i < len; i++) { crc = crc64_table[0][(uint8_t)crc ^ data[i]] ^ (crc >> 8); } @@ -167,7 +168,7 @@ bool crc64speed_init(void) { #else should_init(crc64_table_little, LITTLE1); #endif - crcspeed64little_init(crc64, dual ? crc64_table_little : crc64_table); + crcspeed64little_init(crc64, dual ? (uint64_t (*)[256]) crc64_table_little : crc64_table); return true; } @@ -178,7 +179,7 @@ bool crc64speed_init_big(void) { #else should_init(crc64_table_big, BIG1); #endif - crcspeed64big_init(crc64, dual ? crc64_table_big : crc64_table); + crcspeed64big_init(crc64, dual ? (uint64_t (*)[256]) crc64_table_big : crc64_table); return true; } @@ -189,7 +190,7 @@ uint64_t crc64speed(uint64_t crc, const void *s, const uint64_t l) { #else check_init(crc64_table_little, LITTLE1); #endif - return crcspeed64little(dual ? crc64_table_little : crc64_table, crc, + return crcspeed64little(dual ? (uint64_t (*)[256]) crc64_table_little : crc64_table, crc, (void *)s, l); } @@ -200,7 +201,7 @@ uint64_t crc64speed_big(uint64_t crc, const void *s, const uint64_t l) { #else check_init(crc64_table_big, BIG1); #endif - return crcspeed64big(dual ? crc64_table_big : crc64_table, crc, (void *)s, + return crcspeed64big(dual ? (uint64_t (*)[256]) crc64_table_big : crc64_table, crc, (void *)s, l); } diff --git a/src/ddma.c b/src/ddma.c index 1ce7f1997..7cbe2831e 100644 --- a/src/ddma.c +++ b/src/ddma.c @@ -1,18 +1,18 @@ /* - * 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. + * 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. + * This file is part of the 86Box distribution. * - * Distributed DMA emulation. + * Distributed DMA emulation. * * * - * Authors: Miran Grca, + * Authors: Miran Grca, * - * Copyright 2020 Miran Grca. + * Copyright 2020 Miran Grca. */ #include #include @@ -34,131 +34,133 @@ #include <86box/pit.h> #include <86box/dma.h> #include <86box/ddma.h> - +#include <86box/plat_unused.h> #ifdef ENABLE_DDMA_LOG int ddma_do_log = ENABLE_DDMA_LOG; - static void ddma_log(const char *fmt, ...) { va_list ap; if (ddma_do_log) { - va_start(ap, fmt); - pclog_ex(fmt, ap); - va_end(ap); + va_start(ap, fmt); + pclog_ex(fmt, ap); + va_end(ap); } } #else -#define ddma_log(fmt, ...) +# define ddma_log(fmt, ...) #endif static uint8_t -ddma_reg_read(uint16_t addr, void *p) +ddma_reg_read(uint16_t addr, void *priv) { - ddma_channel_t *dev = (ddma_channel_t *) p; - uint8_t ret = 0xff; - int ch = dev->channel; - int dmab = (ch >= 4) ? 0xc0 : 0x00; + const ddma_channel_t *dev = (ddma_channel_t *) priv; + uint8_t ret = 0xff; + int ch = dev->channel; + uint8_t dmab = (ch >= 4) ? 0xc0 : 0x00; switch (addr & 0x0f) { - case 0x00: - ret = dma[ch].ac & 0xff; - break; - case 0x01: - ret = (dma[ch].ac >> 8) & 0xff; - break; - case 0x02: - ret = dma[ch].page; - break; - case 0x04: - ret = dma[ch].cc & 0xff; - break; - case 0x05: - ret = (dma[ch].cc >> 8) & 0xff; - break; - case 0x09: - ret = inb(dmab + 0x08); - break; + case 0x00: + ret = dma[ch].ac & 0xff; + break; + case 0x01: + ret = (dma[ch].ac >> 8) & 0xff; + break; + case 0x02: + ret = dma[ch].page; + break; + case 0x04: + ret = dma[ch].cc & 0xff; + break; + case 0x05: + ret = (dma[ch].cc >> 8) & 0xff; + break; + case 0x09: + ret = inb(dmab + 0x08); + break; + + default: + break; } return ret; } - static void -ddma_reg_write(uint16_t addr, uint8_t val, void *p) +ddma_reg_write(uint16_t addr, uint8_t val, void *priv) { - ddma_channel_t *dev = (ddma_channel_t *) p; - int ch = dev->channel; - int page_regs[4] = { 7, 3, 1, 2 }; - int i, dmab = (ch >= 4) ? 0xc0 : 0x00; + const ddma_channel_t *dev = (ddma_channel_t *) priv; + int ch = dev->channel; + uint8_t page_regs[4] = { 7, 3, 1, 2 }; + uint8_t dmab = (ch >= 4) ? 0xc0 : 0x00; switch (addr & 0x0f) { - case 0x00: - dma[ch].ab = (dma[ch].ab & 0xffff00) | val; - dma[ch].ac = dma[ch].ab; - break; - case 0x01: - dma[ch].ab = (dma[ch].ab & 0xff00ff) | (val << 8); - dma[ch].ac = dma[ch].ab; - break; - case 0x02: - if (ch >= 4) - outb(0x88 + page_regs[ch & 3], val); - else - outb(0x80 + page_regs[ch & 3], val); - break; - case 0x04: - dma[ch].cb = (dma[ch].cb & 0xffff00) | val; - dma[ch].cc = dma[ch].cb; - break; - case 0x05: - dma[ch].cb = (dma[ch].cb & 0xff00ff) | (val << 8); - dma[ch].cc = dma[ch].cb; - break; - case 0x08: - outb(dmab + 0x08, val); - break; - case 0x09: - outb(dmab + 0x09, val); - break; - case 0x0a: - outb(dmab + 0x0a, val); - break; - case 0x0b: - outb(dmab + 0x0b, val); - break; - case 0x0d: - outb(dmab + 0x0d, val); - break; - case 0x0e: - for (i = 0; i < 4; i++) - outb(dmab + 0x0a, i); - break; - case 0x0f: - outb(dmab + 0x0a, (val << 2) | (ch & 3)); - break; + case 0x00: + dma[ch].ab = (dma[ch].ab & 0xffff00) | val; + dma[ch].ac = dma[ch].ab; + break; + case 0x01: + dma[ch].ab = (dma[ch].ab & 0xff00ff) | (val << 8); + dma[ch].ac = dma[ch].ab; + break; + case 0x02: + if (ch >= 4) + outb(0x88 + page_regs[ch & 3], val); + else + outb(0x80 + page_regs[ch & 3], val); + break; + case 0x04: + dma[ch].cb = (dma[ch].cb & 0xffff00) | val; + dma[ch].cc = dma[ch].cb; + break; + case 0x05: + dma[ch].cb = (dma[ch].cb & 0xff00ff) | (val << 8); + dma[ch].cc = dma[ch].cb; + break; + case 0x08: + outb(dmab + 0x08, val); + break; + case 0x09: + outb(dmab + 0x09, val); + break; + case 0x0a: + outb(dmab + 0x0a, val); + break; + case 0x0b: + outb(dmab + 0x0b, val); + break; + case 0x0d: + outb(dmab + 0x0d, val); + break; + case 0x0e: + for (uint8_t i = 0; i < 4; i++) + outb(dmab + 0x0a, i); + break; + case 0x0f: + outb(dmab + 0x0a, (val << 2) | (ch & 3)); + break; + + default: + break; } } - void ddma_update_io_mapping(ddma_t *dev, int ch, uint8_t base_l, uint8_t base_h, int enable) { if (dev->channels[ch].enable && (dev->channels[ch].io_base != 0x0000)) - io_removehandler(dev->channels[ch].io_base, 0x10, ddma_reg_read, NULL, NULL, ddma_reg_write, NULL, NULL, &dev->channels[ch]); + io_removehandler(dev->channels[ch].io_base, 0x10, ddma_reg_read, NULL, NULL, ddma_reg_write, NULL, NULL, &dev->channels[ch]); dev->channels[ch].io_base = base_l | (base_h << 8); - dev->channels[ch].enable = enable; + dev->channels[ch].enable = enable; if (dev->channels[ch].enable && (dev->channels[ch].io_base != 0x0000)) - io_sethandler(dev->channels[ch].io_base, 0x10, ddma_reg_read, NULL, NULL, ddma_reg_write, NULL, NULL, &dev->channels[ch]); + io_sethandler(dev->channels[ch].io_base, 0x10, ddma_reg_read, NULL, NULL, ddma_reg_write, NULL, NULL, &dev->channels[ch]); } - static void ddma_close(void *priv) { @@ -167,35 +169,32 @@ ddma_close(void *priv) free(dev); } - static void * -ddma_init(const device_t *info) +ddma_init(UNUSED(const device_t *info)) { ddma_t *dev; - int i; - dev = (ddma_t *)malloc(sizeof(ddma_t)); - if (dev == NULL) return(NULL); + dev = (ddma_t *) malloc(sizeof(ddma_t)); + if (dev == NULL) + return (NULL); memset(dev, 0x00, sizeof(ddma_t)); - for (i = 0; i < 8; i++) - dev->channels[i].channel = i; + for (uint8_t i = 0; i < 8; i++) + dev->channels[i].channel = i; return dev; } - -const device_t ddma_device = -{ - "Distributed DMA", - "ddma", - DEVICE_PCI, - 0, - ddma_init, - ddma_close, - NULL, - { NULL }, - NULL, - NULL, - NULL +const device_t ddma_device = { + .name = "Distributed DMA", + .internal_name = "ddma", + .flags = DEVICE_PCI, + .local = 0, + .init = ddma_init, + .close = ddma_close, + .reset = NULL, + { .available = NULL }, + .speed_changed = NULL, + .force_redraw = NULL, + .config = NULL }; diff --git a/src/device.c b/src/device.c index 136c11446..c517f98e9 100644 --- a/src/device.c +++ b/src/device.c @@ -1,23 +1,25 @@ /* - * VARCem Virtual ARchaeological Computer EMulator. - * An emulator of (mostly) x86-based PC systems and devices, - * using the ISA,EISA,VLB,MCA and PCI system buses, roughly - * spanning the era between 1981 and 1995. + * 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 VARCem Project. + * This file is part of the 86Box distribution. * - * Implementation of the generic device interface to handle - * all devices attached to the emulator. + * Implementation of the generic device interface to handle + * all devices attached to the emulator. * * * - * Authors: Fred N. van Kempen, - * Miran Grca, - * Sarah Walker, + * Authors: Fred N. van Kempen, + * Miran Grca, + * Sarah Walker, * - * Copyright 2017-2019 Fred N. van Kempen. - * Copyright 2016-2019 Miran Grca. - * Copyright 2008-2019 Sarah Walker. + * Copyright 2017-2019 Fred N. van Kempen. + * Copyright 2016-2019 Miran Grca. + * Copyright 2008-2019 Sarah Walker. + * Copyright 2021 Andreas J. Reichel. + * Copyright 2021-2022 Jasmine Iwanek. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -37,6 +39,7 @@ * Boston, MA 02111-1307 * USA. */ +#include #include #include #include @@ -45,40 +48,39 @@ #include #define HAVE_STDARG_H #include <86box/86box.h> +#include <86box/ini.h> #include <86box/config.h> #include <86box/device.h> #include <86box/machine.h> +#include <86box/mem.h> +#include <86box/rom.h> #include <86box/sound.h> +#define DEVICE_MAX 256 /* max # of devices */ -#define DEVICE_MAX 256 /* max # of devices */ - - -static device_t *devices[DEVICE_MAX]; -static void *device_priv[DEVICE_MAX]; -static device_context_t device_current, device_prev; - +static device_t *devices[DEVICE_MAX]; +static void *device_priv[DEVICE_MAX]; +static device_context_t device_current; +static device_context_t device_prev; #ifdef ENABLE_DEVICE_LOG int device_do_log = ENABLE_DEVICE_LOG; - static void device_log(const char *fmt, ...) { va_list ap; if (device_do_log) { - va_start(ap, fmt); - pclog_ex(fmt, ap); - va_end(ap); + va_start(ap, fmt); + pclog_ex(fmt, ap); + va_end(ap); } } #else -#define device_log(fmt, ...) +# define device_log(fmt, ...) #endif - /* Initialize the module for use. */ void device_init(void) @@ -86,416 +88,514 @@ device_init(void) memset(devices, 0x00, sizeof(devices)); } - void -device_set_context(device_context_t *c, const device_t *d, int inst) +device_set_context(device_context_t *c, const device_t *dev, int inst) { - void *sec, *single_sec; + const void *sec; + void *single_sec; memset(c, 0, sizeof(device_context_t)); - c->dev = d; + c->dev = dev; + c->instance = inst; if (inst) { - sprintf(c->name, "%s #%i", d->name, inst); + sprintf(c->name, "%s #%i", dev->name, inst); - /* If this is the first instance and a numbered section is not present, but a non-numbered - section of the same name is, rename the non-numbered section to numbered. */ - if (inst == 1) { - sec = config_find_section(c->name); - single_sec = config_find_section((char *) d->name); - if ((sec == NULL) && (single_sec != NULL)) - config_rename_section(single_sec, c->name); - } + /* If this is the first instance and a numbered section is not present, but a non-numbered + section of the same name is, rename the non-numbered section to numbered. */ + if (inst == 1) { + sec = config_find_section(c->name); + single_sec = config_find_section((char *) dev->name); + if ((sec == NULL) && (single_sec != NULL)) + config_rename_section(single_sec, c->name); + } } else - sprintf(c->name, "%s", d->name); + sprintf(c->name, "%s", dev->name); } - static void -device_context_common(const device_t *d, int inst) +device_context_common(const device_t *dev, int inst) { memcpy(&device_prev, &device_current, sizeof(device_context_t)); - device_set_context(&device_current, d, inst); + device_set_context(&device_current, dev, inst); } - void -device_context(const device_t *d) +device_context(const device_t *dev) { - device_context_common(d, 0); + device_context_common(dev, 0); } - void -device_context_inst(const device_t *d, int inst) +device_context_inst(const device_t *dev, int inst) { - device_context_common(d, inst); + device_context_common(dev, inst); } - void device_context_restore(void) { memcpy(&device_current, &device_prev, sizeof(device_context_t)); } - static void * -device_add_common(const device_t *d, const device_t *cd, void *p, int inst) +device_add_common(const device_t *dev, const device_t *cd, void *p, void *params, int inst) { void *priv = NULL; - int c; + int c; for (c = 0; c < 256; c++) { - if (!inst && (devices[c] == (device_t *) d)) { - device_log("DEVICE: device already exists!\n"); - return (NULL); - } - if (devices[c] == NULL) break; + if (!inst && (devices[c] == dev)) { + device_log("DEVICE: device already exists!\n"); + return (NULL); + } + if (devices[c] == NULL) + break; + } + if ((c >= DEVICE_MAX) || (c >= 256)) { + fatal("DEVICE: too many devices\n"); + return NULL; } - if (c >= DEVICE_MAX) - fatal("DEVICE: too many devices\n"); /* Do this so that a chained device_add will not identify the same ID its master device is already trying to assign. */ - devices[c] = (device_t *)d; + devices[c] = (device_t *) dev; + if (!strcmp(dev->name, "None") || !strcmp(dev->name, "Internal")) + fatal("Attempting to add dummy device of type: %s\n", dev->name); if (p == NULL) { - memcpy(&device_prev, &device_current, sizeof(device_context_t)); - device_set_context(&device_current, cd, inst); + memcpy(&device_prev, &device_current, sizeof(device_context_t)); + device_set_context(&device_current, cd, inst); - if (d->init != NULL) { - priv = d->init(d); - if (priv == NULL) { - if (d->name) - device_log("DEVICE: device '%s' init failed\n", d->name); - else - device_log("DEVICE: device init failed\n"); + if (dev->init != NULL) { + priv = (dev->flags & DEVICE_EXTPARAMS) ? dev->init_ext(dev, params) : dev->init(dev); + if (priv == NULL) { + if (dev->name) + device_log("DEVICE: device '%s' init failed\n", dev->name); + else + device_log("DEVICE: device init failed\n"); - devices[c] = NULL; - device_priv[c] = NULL; + devices[c] = NULL; + device_priv[c] = NULL; - return(NULL); - } - } + return (NULL); + } + } - if (d->name) - device_log("DEVICE: device '%s' init successful\n", d->name); - else - device_log("DEVICE: device init successful\n"); + if (dev->name) + device_log("DEVICE: device '%s' init successful\n", dev->name); + else + device_log("DEVICE: device init successful\n"); - memcpy(&device_current, &device_prev, sizeof(device_context_t)); - device_priv[c] = priv; + memcpy(&device_current, &device_prev, sizeof(device_context_t)); + device_priv[c] = priv; } else - device_priv[c] = p; + device_priv[c] = p; - return(priv); + return priv; } - -char * -device_get_internal_name(const device_t *d) +const char * +device_get_internal_name(const device_t *dev) { - if (d == NULL) - return ""; + if (dev == NULL) + return ""; - return (char *) d->internal_name; + return dev->internal_name; } - void * -device_add(const device_t *d) +device_add(const device_t *dev) { - return device_add_common(d, d, NULL, 0); + return device_add_common(dev, dev, NULL, NULL, 0); } +void * +device_add_parameters(const device_t *dev, void *params) +{ + return device_add_common(dev, dev, NULL, params, 0); +} /* For devices that do not have an init function (internal video etc.) */ void -device_add_ex(const device_t *d, void *priv) +device_add_ex(const device_t *dev, void *priv) { - device_add_common(d, d, priv, 0); + device_add_common(dev, dev, priv, NULL, 0); } +void +device_add_ex_parameters(const device_t *dev, void *priv, void *params) +{ + device_add_common(dev, dev, priv, params, 0); +} void * -device_add_inst(const device_t *d, int inst) +device_add_inst(const device_t *dev, int inst) { - return device_add_common(d, d, NULL, inst); + return device_add_common(dev, dev, NULL, NULL, inst); } +void * +device_add_inst_parameters(const device_t *dev, int inst, void *params) +{ + return device_add_common(dev, dev, NULL, params, inst); +} /* For devices that do not have an init function (internal video etc.) */ void -device_add_inst_ex(const device_t *d, void *priv, int inst) +device_add_inst_ex(const device_t *dev, void *priv, int inst) { - device_add_common(d, d, priv, inst); + device_add_common(dev, dev, priv, NULL, inst); } +void +device_add_inst_ex_parameters(const device_t *dev, void *priv, int inst, void *params) +{ + device_add_common(dev, dev, priv, params, inst); +} -/* These four are to add a device with another device's context - will be +/* These eight are to add a device with another device's context - will be used to add machines' internal devices. */ void * -device_cadd(const device_t *d, const device_t *cd) +device_cadd(const device_t *dev, const device_t *cd) { - return device_add_common(d, cd, NULL, 0); + return device_add_common(dev, cd, NULL, NULL, 0); } - -/* For devices that do not have an init function (internal video etc.) */ -void -device_cadd_ex(const device_t *d, const device_t *cd, void *priv) -{ - device_add_common(d, cd, priv, 0); -} - - void * -device_cadd_inst(const device_t *d, const device_t *cd, int inst) +device_cadd_parameters(const device_t *dev, const device_t *cd, void *params) { - return device_add_common(d, cd, NULL, inst); + return device_add_common(dev, cd, NULL, params, 0); } - /* For devices that do not have an init function (internal video etc.) */ void -device_cadd_inst_ex(const device_t *d, const device_t *cd, void *priv, int inst) +device_cadd_ex(const device_t *dev, const device_t *cd, void *priv) { - device_add_common(d, cd, priv, inst); + device_add_common(dev, cd, priv, NULL, 0); } +void +device_cadd_ex_parameters(const device_t *dev, const device_t *cd, void *priv, void *params) +{ + device_add_common(dev, cd, priv, params, 0); +} + +void * +device_cadd_inst(const device_t *dev, const device_t *cd, int inst) +{ + return device_add_common(dev, cd, NULL, NULL, inst); +} + +void * +device_cadd_inst_parameters(const device_t *dev, const device_t *cd, int inst, void *params) +{ + return device_add_common(dev, cd, NULL, params, inst); +} + +/* For devices that do not have an init function (internal video etc.) */ +void +device_cadd_inst_ex(const device_t *dev, const device_t *cd, void *priv, int inst) +{ + device_add_common(dev, cd, priv, NULL, inst); +} + +void +device_cadd_inst_ex_parameters(const device_t *dev, const device_t *cd, void *priv, int inst, void *params) +{ + device_add_common(dev, cd, priv, params, inst); +} void device_close_all(void) { - int c; - - for (c = (DEVICE_MAX - 1); c >= 0; c--) { - if (devices[c] != NULL) { - if (devices[c]->name) - device_log("Closing device: \"%s\"...\n", devices[c]->name); - if (devices[c]->close != NULL) - devices[c]->close(device_priv[c]); - devices[c] = device_priv[c] = NULL; - } + for (int16_t c = (DEVICE_MAX - 1); c >= 0; c--) { + if (devices[c] != NULL) { + if (devices[c]->name) + device_log("Closing device: \"%s\"...\n", devices[c]->name); + if (devices[c]->close != NULL) + devices[c]->close(device_priv[c]); + devices[c] = device_priv[c] = NULL; + } } } - void -device_reset_all(void) +device_reset_all(uint32_t match_flags) { - int c; - - for (c = 0; c < DEVICE_MAX; c++) { - if (devices[c] != NULL) { - if (devices[c]->reset != NULL) - devices[c]->reset(device_priv[c]); - } + for (uint16_t c = 0; c < DEVICE_MAX; c++) { + if (devices[c] != NULL) { + if ((devices[c]->reset != NULL) && (devices[c]->flags & match_flags)) + devices[c]->reset(device_priv[c]); + } } } - -/* Reset all attached PCI devices - needed for PCI turbo reset control. */ -void -device_reset_all_pci(void) -{ - int c; - - for (c=0; creset != NULL) && (devices[c]->flags & DEVICE_PCI)) - devices[c]->reset(device_priv[c]); - } - } -} - - void * -device_get_priv(const device_t *d) +device_find_first_priv(uint32_t match_flags) { - int c; + void *ret = NULL; - for (c = 0; c < DEVICE_MAX; c++) { - if (devices[c] != NULL) { - if (devices[c] == d) - return(device_priv[c]); - } + for (uint16_t c = 0; c < DEVICE_MAX; c++) { + if (devices[c] != NULL) { + if ((device_priv[c] != NULL) && (devices[c]->flags & match_flags)) { + ret = device_priv[c]; + break; + } + } } - return(NULL); + return ret; } +void * +device_get_priv(const device_t *dev) +{ + for (uint16_t c = 0; c < DEVICE_MAX; c++) { + if (devices[c] != NULL) { + if (devices[c] == dev) + return (device_priv[c]); + } + } + + return (NULL); +} int -device_available(const device_t *d) +device_available(const device_t *dev) { -#ifdef RELEASE_BUILD - if (d->flags & DEVICE_NOT_WORKING) return(0); -#endif - if (d->available != NULL) - return(d->available()); + const device_config_t *config = NULL; + const device_config_bios_t *bios = NULL; + int roms_present = 0; + int i = 0; - return(1); + if (dev != NULL) { + config = dev->config; + if (config != NULL) { + while (config->type != -1) { + if (config->type == CONFIG_BIOS) { + bios = (const device_config_bios_t *) config->bios; + + /* Go through the ROM's in the device configuration. */ + while (bios->files_no != 0) { + i = 0; + for (int bf = 0; bf < bios->files_no; bf++) + i += !!rom_present(bios->files[bf]); + if (i == bios->files_no) + roms_present++; + bios++; + } + + return (roms_present ? -1 : 0); + } + config++; + } + } + + /* No CONFIG_BIOS field present, use the classic available(). */ + if (dev->available != NULL) + return (dev->available()); + else + return 1; + } + + /* A NULL device is never available. */ + return 0; } +const char * +device_get_bios_file(const device_t *dev, const char *internal_name, int file_no) +{ + const device_config_t *config = NULL; + const device_config_bios_t *bios = NULL; + + if (dev != NULL) { + config = dev->config; + if (config != NULL) { + while (config->type != -1) { + if (config->type == CONFIG_BIOS) { + bios = config->bios; + + /* Go through the ROM's in the device configuration. */ + while (bios->files_no != 0) { + if (!strcmp(internal_name, bios->internal_name)) { + if (file_no < bios->files_no) + return bios->files[file_no]; + else + return NULL; + } + bios++; + } + } + config++; + } + } + } + + /* A NULL device is never available. */ + return (NULL); +} int -device_poll(const device_t *d, int x, int y, int z, int b) +device_has_config(const device_t *dev) { - int c; + int c = 0; + const device_config_t *config; - for (c = 0; c < DEVICE_MAX; c++) { - if (devices[c] != NULL) { - if (devices[c] == d) { - if (devices[c]->poll) - return(devices[c]->poll(x, y, z, b, device_priv[c])); - } - } + if (dev == NULL) + return 0; + + if (dev->config == NULL) + return 0; + + config = dev->config; + + while (config->type != -1) { + if (config->type != CONFIG_MAC) + c++; + config++; } - return(0); + return (c > 0) ? 1 : 0; } - -void -device_register_pci_slot(const device_t *d, int device, int type, int inta, int intb, int intc, int intd) +int +device_poll(const device_t *dev) { - int c; - - for (c = 0; c < DEVICE_MAX; c++) { - if (devices[c] != NULL) { - if (devices[c] == d) { - if (devices[c]->register_pci_slot) - devices[c]->register_pci_slot(device, type, inta, intb, intc, intd, device_priv[c]); - return; - } - } + for (uint16_t c = 0; c < DEVICE_MAX; c++) { + if (devices[c] != NULL) { + if (devices[c] == dev) { + if (devices[c]->poll) + return (devices[c]->poll(device_priv[c])); + } + } } - return; + return 0; } - void -device_get_name(const device_t *d, int bus, char *name) +device_get_name(const device_t *dev, int bus, char *name) { - char *sbus = NULL, *fbus; - char *tname, pbus[8] = { 0 }; + const char *sbus = NULL; + const char *fbus; + char *tname; + char pbus[8] = { 0 }; - if (d == NULL) - return; + if (dev == NULL) + return; name[0] = 0x00; if (bus) { - if (d->flags & DEVICE_ISA) - sbus = (d->flags & DEVICE_AT) ? "ISA16" : "ISA"; - else if (d->flags & DEVICE_CBUS) - sbus = "C-BUS"; - else if (d->flags & DEVICE_MCA) - sbus = "MCA"; - else if (d->flags & DEVICE_EISA) - sbus = "EISA"; - else if (d->flags & DEVICE_VLB) - sbus = "VLB"; - else if (d->flags & DEVICE_PCI) - sbus = "PCI"; - else if (d->flags & DEVICE_AGP) - sbus = "AGP"; - else if (d->flags & DEVICE_AC97) - sbus = "AMR"; - else if (d->flags & DEVICE_COM) - sbus = "COM"; - else if (d->flags & DEVICE_LPT) - sbus = "LPT"; + if (dev->flags & DEVICE_ISA) + sbus = (dev->flags & DEVICE_AT) ? "ISA16" : "ISA"; + else if (dev->flags & DEVICE_CBUS) + sbus = "C-BUS"; + else if (dev->flags & DEVICE_MCA) + sbus = "MCA"; + else if (dev->flags & DEVICE_EISA) + sbus = "EISA"; + else if (dev->flags & DEVICE_VLB) + sbus = "VLB"; + else if (dev->flags & DEVICE_PCI) + sbus = "PCI"; + else if (dev->flags & DEVICE_AGP) + sbus = "AGP"; + else if (dev->flags & DEVICE_AC97) + sbus = "AMR"; + else if (dev->flags & DEVICE_COM) + sbus = "COM"; + else if (dev->flags & DEVICE_LPT) + sbus = "LPT"; - if (sbus != NULL) { - /* First concatenate [] before the device's name. */ - strcat(name, "["); - strcat(name, sbus); - strcat(name, "] "); + if (sbus != NULL) { + /* First concatenate [] before the device's name. */ + strcat(name, "["); + strcat(name, sbus); + strcat(name, "] "); - /* Then change string from ISA16 to ISA if applicable. */ - if (!strcmp(sbus, "ISA16")) - sbus = "ISA"; - else if (!strcmp(sbus, "COM")|| !strcmp(sbus, "LPT")) { - sbus = NULL; - strcat(name, d->name); - return; - } + /* Then change string from ISA16 to ISA if applicable. */ + if (!strcmp(sbus, "ISA16")) + sbus = "ISA"; + else if (!strcmp(sbus, "COM") || !strcmp(sbus, "LPT")) { + sbus = NULL; + strcat(name, dev->name); + return; + } - /* Generate the bus string with parentheses. */ - strcat(pbus, "("); - strcat(pbus, sbus); - strcat(pbus, ")"); + /* Generate the bus string with parentheses. */ + strcat(pbus, "("); + strcat(pbus, sbus); + strcat(pbus, ")"); - /* Allocate the temporary device name string and set it to all zeroes. */ - tname = (char *) malloc(strlen(d->name) + 1); - memset(tname, 0x00, strlen(d->name) + 1); + /* Allocate the temporary device name string and set it to all zeroes. */ + tname = (char *) malloc(strlen(dev->name) + 1); + memset(tname, 0x00, strlen(dev->name) + 1); - /* First strip the bus string with parentheses. */ - fbus = strstr(d->name, pbus); - if (fbus == d->name) - strcat(tname, d->name + strlen(pbus) + 1); - else if (fbus == NULL) - strcat(tname, d->name); - else { - strncat(tname, d->name, fbus - d->name - 1); - strcat(tname, fbus + strlen(pbus)); - } + /* First strip the bus string with parentheses. */ + fbus = strstr(dev->name, pbus); + if (fbus == dev->name) + strcat(tname, dev->name + strlen(pbus) + 1); + else if (fbus == NULL) + strcat(tname, dev->name); + else { + strncat(tname, dev->name, fbus - dev->name - 1); + strcat(tname, fbus + strlen(pbus)); + } - /* Then also strip the bus string with parentheses. */ - fbus = strstr(tname, sbus); - if (fbus == tname) - strcat(name, tname + strlen(sbus) + 1); - /* Special case to not strip the "oPCI" from "Ensoniq AudioPCI" or - the "-ISA" from "AMD PCnet-ISA". */ - else if ((fbus == NULL) || (*(fbus - 1) == 'o') || (*(fbus - 1) == '-')) - strcat(name, tname); - else { - strncat(name, tname, fbus - tname - 1); - strcat(name, fbus + strlen(sbus)); - } + /* Then also strip the bus string with parentheses. */ + fbus = strstr(tname, sbus); + if (fbus == tname) + strcat(name, tname + strlen(sbus) + 1); + /* Special case to not strip the "oPCI" from "Ensoniq AudioPCI" or + the "-ISA" from "AMD PCnet-ISA". */ + else if ((fbus == NULL) || (*(fbus - 1) == 'o') || (*(fbus - 1) == '-')) + strcat(name, tname); + else { + strncat(name, tname, fbus - tname - 1); + strcat(name, fbus + strlen(sbus)); + } - /* Free the temporary device name string. */ - free(tname); - tname = NULL; - } else - strcat(name, d->name); + /* Free the temporary device name string. */ + free(tname); + tname = NULL; + } else + strcat(name, dev->name); } else - strcat(name, d->name); + strcat(name, dev->name); } - void device_speed_changed(void) { - int c; + for (uint16_t c = 0; c < DEVICE_MAX; c++) { + if (devices[c] != NULL) { + device_log("DEVICE: device '%s' speed changed\n", devices[c]->name); - for (c = 0; c < DEVICE_MAX; c++) { - if (devices[c] != NULL) { - if (devices[c]->speed_changed != NULL) - devices[c]->speed_changed(device_priv[c]); - } + if (devices[c]->speed_changed != NULL) + devices[c]->speed_changed(device_priv[c]); + } } sound_speed_changed(); } - void device_force_redraw(void) { - int c; - - for (c = 0; c < DEVICE_MAX; c++) { - if (devices[c] != NULL) { - if (devices[c]->force_redraw != NULL) - devices[c]->force_redraw(device_priv[c]); - } + for (uint16_t c = 0; c < DEVICE_MAX; c++) { + if (devices[c] != NULL) { + if (devices[c]->force_redraw != NULL) + devices[c]->force_redraw(device_priv[c]); + } } } +const int +device_get_instance(void) +{ + return device_current.instance; +} const char * device_get_config_string(const char *s) @@ -503,224 +603,249 @@ device_get_config_string(const char *s) const device_config_t *c = device_current.dev->config; while (c && c->type != -1) { - if (! strcmp(s, c->name)) - return(config_get_string((char *) device_current.name, (char *) s, (char *) c->default_string)); + if (!strcmp(s, c->name)) + return (config_get_string((char *) device_current.name, (char *) s, (char *) c->default_string)); - c++; + c++; } - return(NULL); + return (NULL); } - int device_get_config_int(const char *s) { const device_config_t *c = device_current.dev->config; while (c && c->type != -1) { - if (! strcmp(s, c->name)) - return(config_get_int((char *) device_current.name, (char *) s, c->default_int)); + if (!strcmp(s, c->name)) + return (config_get_int((char *) device_current.name, (char *) s, c->default_int)); - c++; + c++; } - return(0); + return 0; } - int device_get_config_int_ex(const char *s, int def) { const device_config_t *c = device_current.dev->config; while (c && c->type != -1) { - if (! strcmp(s, c->name)) - return(config_get_int((char *) device_current.name, (char *) s, def)); + if (!strcmp(s, c->name)) + return (config_get_int((char *) device_current.name, (char *) s, def)); - c++; + c++; } - return(def); + return def; } - int device_get_config_hex16(const char *s) { const device_config_t *c = device_current.dev->config; while (c && c->type != -1) { - if (! strcmp(s, c->name)) - return(config_get_hex16((char *) device_current.name, (char *) s, c->default_int)); + if (!strcmp(s, c->name)) + return (config_get_hex16((char *) device_current.name, (char *) s, c->default_int)); - c++; + c++; } - return(0); + return 0; } - int device_get_config_hex20(const char *s) { const device_config_t *c = device_current.dev->config; while (c && c->type != -1) { - if (! strcmp(s, c->name)) - return(config_get_hex20((char *) device_current.name, (char *) s, c->default_int)); + if (!strcmp(s, c->name)) + return (config_get_hex20((char *) device_current.name, (char *) s, c->default_int)); - c++; + c++; } - return(0); + return 0; } - int device_get_config_mac(const char *s, int def) { const device_config_t *c = device_current.dev->config; while (c && c->type != -1) { - if (! strcmp(s, c->name)) - return(config_get_mac((char *) device_current.name, (char *) s, def)); + if (!strcmp(s, c->name)) + return (config_get_mac((char *) device_current.name, (char *) s, def)); - c++; + c++; } - return(def); + return def; } - void device_set_config_int(const char *s, int val) { const device_config_t *c = device_current.dev->config; while (c && c->type != -1) { - if (! strcmp(s, c->name)) { - config_set_int((char *) device_current.name, (char *) s, val); - break; - } + if (!strcmp(s, c->name)) { + config_set_int((char *) device_current.name, (char *) s, val); + break; + } - c++; + c++; } } - void device_set_config_hex16(const char *s, int val) { const device_config_t *c = device_current.dev->config; while (c && c->type != -1) { - if (! strcmp(s, c->name)) { - config_set_hex16((char *) device_current.name, (char *) s, val); - break; - } + if (!strcmp(s, c->name)) { + config_set_hex16((char *) device_current.name, (char *) s, val); + break; + } - c++; + c++; } } - void device_set_config_hex20(const char *s, int val) { const device_config_t *c = device_current.dev->config; while (c && c->type != -1) { - if (! strcmp(s, c->name)) { - config_set_hex20((char *) device_current.name, (char *) s, val); - break; - } + if (!strcmp(s, c->name)) { + config_set_hex20((char *) device_current.name, (char *) s, val); + break; + } - c++; + c++; } } - void device_set_config_mac(const char *s, int val) { const device_config_t *c = device_current.dev->config; while (c && c->type != -1) { - if (! strcmp(s, c->name)) { - config_set_mac((char *) device_current.name, (char *) s, val); - break; - } + if (!strcmp(s, c->name)) { + config_set_mac((char *) device_current.name, (char *) s, val); + break; + } - c++; + c++; } } - int device_is_valid(const device_t *device, int m) { - if (device == NULL) return(1); + if (device == NULL) + return 1; - if ((device->flags & DEVICE_AT) && !machine_has_bus(m, MACHINE_BUS_ISA16)) return(0); + if ((device->flags & DEVICE_PCJR) && !machine_has_bus(m, MACHINE_BUS_PCJR)) + return 0; - if ((device->flags & DEVICE_CBUS) && !machine_has_bus(m, MACHINE_BUS_CBUS)) return(0); + if ((device->flags & DEVICE_XTKBC) && machine_has_bus(m, MACHINE_BUS_ISA16) && !machine_has_bus(m, MACHINE_BUS_DM_KBC)) + return 0; - if ((device->flags & DEVICE_ISA) && !machine_has_bus(m, MACHINE_BUS_ISA)) return(0); + if ((device->flags & DEVICE_AT) && !machine_has_bus(m, MACHINE_BUS_ISA16)) + return 0; - if ((device->flags & DEVICE_MCA) && !machine_has_bus(m, MACHINE_BUS_MCA)) return(0); + if ((device->flags & DEVICE_ATKBC) && !machine_has_bus(m, MACHINE_BUS_ISA16) && !machine_has_bus(m, MACHINE_BUS_DM_KBC)) + return 0; - if ((device->flags & DEVICE_EISA) && !machine_has_bus(m, MACHINE_BUS_EISA)) return(0); + if ((device->flags & DEVICE_ISA) && !machine_has_bus(m, MACHINE_BUS_ISA)) + return 0; - if ((device->flags & DEVICE_VLB) && !machine_has_bus(m, MACHINE_BUS_VLB)) return(0); + if ((device->flags & DEVICE_CBUS) && !machine_has_bus(m, MACHINE_BUS_CBUS)) + return 0; - if ((device->flags & DEVICE_PCI) && !machine_has_bus(m, MACHINE_BUS_PCI)) return(0); + if ((device->flags & DEVICE_PCMCIA) && !machine_has_bus(m, MACHINE_BUS_PCMCIA)) + return 0; - if ((device->flags & DEVICE_AGP) && !machine_has_bus(m, MACHINE_BUS_AGP)) return(0); + if ((device->flags & DEVICE_MCA) && !machine_has_bus(m, MACHINE_BUS_MCA)) + return 0; - if ((device->flags & DEVICE_PS2) && !machine_has_bus(m, MACHINE_BUS_PS2)) return(0); + if ((device->flags & DEVICE_HIL) && !machine_has_bus(m, MACHINE_BUS_HIL)) + return 0; - if ((device->flags & DEVICE_AC97) && !machine_has_bus(m, MACHINE_BUS_AC97)) return(0); + if ((device->flags & DEVICE_EISA) && !machine_has_bus(m, MACHINE_BUS_EISA)) + return 0; - return(1); + if ((device->flags & DEVICE_OLB) && !machine_has_bus(m, MACHINE_BUS_OLB)) + return 0; + + if ((device->flags & DEVICE_VLB) && !machine_has_bus(m, MACHINE_BUS_VLB)) + return 0; + + if ((device->flags & DEVICE_PCI) && !machine_has_bus(m, MACHINE_BUS_PCI)) + return 0; + + if ((device->flags & DEVICE_CARDBUS) && !machine_has_bus(m, MACHINE_BUS_CARDBUS)) + return 0; + + if ((device->flags & DEVICE_USB) && !machine_has_bus(m, MACHINE_BUS_USB)) + return 0; + + if ((device->flags & DEVICE_AGP) && !machine_has_bus(m, MACHINE_BUS_AGP)) + return 0; + + if ((device->flags & DEVICE_PS2) && !machine_has_bus(m, MACHINE_BUS_PS2_PORTS)) + return 0; + + if ((device->flags & DEVICE_AC97) && !machine_has_bus(m, MACHINE_BUS_AC97)) + return 0; + + return 1; } - int machine_get_config_int(char *s) { - const device_t *d = machine_getdevice(machine); + const device_t *d = machine_get_device(machine); const device_config_t *c; - if (d == NULL) return(0); + if (d == NULL) + return 0; c = d->config; while (c && c->type != -1) { - if (! strcmp(s, c->name)) - return(config_get_int((char *)d->name, s, c->default_int)); + if (!strcmp(s, c->name)) + return (config_get_int((char *) d->name, s, c->default_int)); - c++; + c++; } - return(0); + return 0; } - char * machine_get_config_string(char *s) { - const device_t *d = machine_getdevice(machine); + const device_t *d = machine_get_device(machine); const device_config_t *c; - if (d == NULL) return(0); + if (d == NULL) + return 0; c = d->config; while (c && c->type != -1) { - if (! strcmp(s, c->name)) - return(config_get_string((char *)d->name, s, (char *)c->default_string)); + if (!strcmp(s, c->name)) + return (config_get_string((char *) d->name, s, (char *) c->default_string)); - c++; + c++; } - return(NULL); + return NULL; } diff --git a/src/device/CMakeLists.txt b/src/device/CMakeLists.txt index 658da7280..2988152c1 100644 --- a/src/device/CMakeLists.txt +++ b/src/device/CMakeLists.txt @@ -1,23 +1,32 @@ # -# 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. +# 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. +# This file is part of the 86Box distribution. # -# CMake build script. +# CMake build script. # -# Authors: David HrdliÄka, +# Authors: David HrdliÄka, # -# Copyright 2020,2021 David HrdliÄka. +# Copyright 2020-2021 David HrdliÄka. +# Copyright 2021 Andreas J. Reichel. +# Copyright 2021-2022 Jasmine Iwanek. # add_library(dev OBJECT bugger.c cassette.c cartridge.c hasp.c hwm.c hwm_lm75.c hwm_lm78.c hwm_gl518sm.c hwm_vt82c686.c ibm_5161.c isamem.c isartc.c ../lpt.c pci_bridge.c postcard.c serial.c clock_ics9xxx.c isapnp.c i2c.c i2c_gpio.c - smbus_piix4.c smbus_ali7101.c keyboard.c keyboard_xt.c keyboard_at.c - mouse.c mouse_bus.c mouse_serial.c mouse_ps2.c phoenix_486_jumper.c) + smbus_piix4.c smbus_ali7101.c keyboard.c keyboard_xt.c + kbc_at.c kbc_at_dev.c + keyboard_at.c + mouse.c mouse_bus.c mouse_serial.c mouse_ps2.c phoenix_486_jumper.c + serial_passthrough.c) + +if(NOT CMAKE_CXX_COMPILER_ID MATCHES "Clang") + target_link_libraries(86Box atomic) +endif() if(ISAMEM_RAMPAGE) target_compile_definitions(dev PRIVATE USE_ISAMEM_RAMPAGE) diff --git a/src/device/bugger.c b/src/device/bugger.c index 56ad119a1..c2678d66a 100644 --- a/src/device/bugger.c +++ b/src/device/bugger.c @@ -1,53 +1,53 @@ /* - * 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. + * 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. + * This file is part of the 86Box distribution. * - * Implementation of the ISA Bus (de)Bugger expansion card - * sold as a DIY kit in the late 1980's in The Netherlands. - * This card was a assemble-yourself 8bit ISA addon card for - * PC and AT systems that had several tools to aid in low- - * level debugging (mostly for faulty BIOSes, bootloaders - * and system kernels...) + * Implementation of the ISA Bus (de)Bugger expansion card + * sold as a DIY kit in the late 1980's in The Netherlands. + * This card was a assemble-yourself 8bit ISA addon card for + * PC and AT systems that had several tools to aid in low- + * level debugging (mostly for faulty BIOSes, bootloaders + * and system kernels...) * - * The standard version had a total of 16 LEDs (8 RED, plus - * 8 GREEN), two 7-segment displays and one 8-position DIP - * switch block on board for use as debugging tools. + * The standard version had a total of 16 LEDs (8 RED, plus + * 8 GREEN), two 7-segment displays and one 8-position DIP + * switch block on board for use as debugging tools. * - * The "Plus" version, added an extra 2 7-segment displays, - * as well as a very simple RS-232 serial interface that - * could be used as a mini-console terminal. + * The "Plus" version, added an extra 2 7-segment displays, + * as well as a very simple RS-232 serial interface that + * could be used as a mini-console terminal. * - * Two I/O ports were used; one for control, at offset 0 in - * I/O space, and one for data, at offset 1 in I/O space. - * Both registers could be read from and written to. Although - * the author has a vague memory of a DIP switch to set the - * board's I/O address, comments in old software seems to - * indicate that it was actually fixed to 0x7A (and 0x7B.) + * Two I/O ports were used; one for control, at offset 0 in + * I/O space, and one for data, at offset 1 in I/O space. + * Both registers could be read from and written to. Although + * the author has a vague memory of a DIP switch to set the + * board's I/O address, comments in old software seems to + * indicate that it was actually fixed to 0x7A (and 0x7B.) * - * A READ on the data register always returned the actual - * state of the DIP switch. Writing data to the LEDs was done - * in two steps.. first, the block number (RED or GREEN) was - * written to the CTRL register, and then the actual LED data - * was written to the DATA register. Likewise, data for the - * 7-segment displays was written. + * A READ on the data register always returned the actual + * state of the DIP switch. Writing data to the LEDs was done + * in two steps.. first, the block number (RED or GREEN) was + * written to the CTRL register, and then the actual LED data + * was written to the DATA register. Likewise, data for the + * 7-segment displays was written. * - * The serial port was a bit different, and its operation is - * not verified, but two extra bits in the control register - * were used to set up parameters, and also the actual data - * input and output. + * The serial port was a bit different, and its operation is + * not verified, but two extra bits in the control register + * were used to set up parameters, and also the actual data + * input and output. * - * TODO: Still have to implement the RS232 Serial Port Parameters - * configuration register (CTRL_SPCFG bit set) but have to - * remember that stuff first... + * TODO: Still have to implement the RS232 Serial Port Parameters + * configuration register (CTRL_SPCFG bit set) but have to + * remember that stuff first... * * * - * Author: Fred N. van Kempen, - * Copyright 1989-2018 Fred N. van Kempen. + * Authors: Fred N. van Kempen, + * Copyright 1989-2018 Fred N. van Kempen. */ #include #include @@ -62,76 +62,71 @@ #include <86box/ui.h> #include <86box/bugger.h> - /* BugBugger registers. */ -#define BUG_CTRL 0 -# define CTRL_RLED 0x00 /* write to the RED LED block */ -# define CTRL_GLED 0x01 /* write to the GREEN LED block */ -# define CTRL_SEG1 0x02 /* write to the RIGHT 7SEG displays */ -# define CTRL_SEG2 0x04 /* write to the LEFT 7SEG displays */ -# define CTRL_SPORT 0x20 /* enable the serial port */ -# define CTRL_SPCFG 0x40 /* set up the serial port */ -# define CTRL_INIT 0x80 /* enable and reset the card */ -# define CTRL_RESET 0xff /* this resets the board */ -#define BUG_DATA 1 +#define BUG_CTRL 0 +#define CTRL_RLED 0x00 /* write to the RED LED block */ +#define CTRL_GLED 0x01 /* write to the GREEN LED block */ +#define CTRL_SEG1 0x02 /* write to the RIGHT 7SEG displays */ +#define CTRL_SEG2 0x04 /* write to the LEFT 7SEG displays */ +#define CTRL_SPORT 0x20 /* enable the serial port */ +#define CTRL_SPCFG 0x40 /* set up the serial port */ +#define CTRL_INIT 0x80 /* enable and reset the card */ +#define CTRL_RESET 0xff /* this resets the board */ +#define BUG_DATA 1 +static uint8_t bug_ctrl; /* control register */ +static uint8_t bug_data; /* data register */ +static uint8_t bug_ledr; /* RED LEDs */ +static uint8_t bug_ledg; /* GREEN LEDs */ +static uint8_t bug_seg1; +static uint8_t bug_seg2; /* LEFT and RIGHT 7SEG displays */ +static uint8_t bug_spcfg; /* serial port configuration */ +#define FIFO_LEN 256 +static uint8_t bug_buff[FIFO_LEN]; /* serial port data buffer */ +static uint8_t *bug_bptr; +#define UISTR_LEN 24 +static char bug_str[UISTR_LEN]; /* UI output string */ -static uint8_t bug_ctrl, /* control register */ - bug_data, /* data register */ - bug_ledr, bug_ledg, /* RED and GREEN LEDs */ - bug_seg1, bug_seg2, /* LEFT and RIGHT 7SEG displays */ - bug_spcfg; /* serial port configuration */ -# define FIFO_LEN 256 -static uint8_t bug_buff[FIFO_LEN], /* serial port data buffer */ - *bug_bptr; -# define UISTR_LEN 24 -static char bug_str[UISTR_LEN]; /* UI output string */ - - -extern void ui_sb_bugui(char *__str); - +extern void ui_sb_bugui(char *__str); #ifdef ENABLE_BUGGER_LOG int bugger_do_log = ENABLE_BUGGER_LOG; - static void bugger_log(const char *fmt, ...) { va_list ap; if (bugger_do_log) { - va_start(ap, fmt); - pclog_ex(fmt, ap); - va_end(ap); + va_start(ap, fmt); + pclog_ex(fmt, ap); + va_end(ap); } } #else -#define bugger_log(fmt, ...) +# define bugger_log(fmt, ...) #endif - /* Update the system's UI with the actual Bugger status. */ static void bug_setui(void) { /* Format all current info in a string. */ sprintf(bug_str, "%02X:%02X %c%c%c%c%c%c%c%c-%c%c%c%c%c%c%c%c", - bug_seg2, bug_seg1, - (bug_ledg&0x80)?'G':'g', (bug_ledg&0x40)?'G':'g', - (bug_ledg&0x20)?'G':'g', (bug_ledg&0x10)?'G':'g', - (bug_ledg&0x08)?'G':'g', (bug_ledg&0x04)?'G':'g', - (bug_ledg&0x02)?'G':'g', (bug_ledg&0x01)?'G':'g', - (bug_ledr&0x80)?'R':'r', (bug_ledr&0x40)?'R':'r', - (bug_ledr&0x20)?'R':'r', (bug_ledr&0x10)?'R':'r', - (bug_ledr&0x08)?'R':'r', (bug_ledr&0x04)?'R':'r', - (bug_ledr&0x02)?'R':'r', (bug_ledr&0x01)?'R':'r'); + bug_seg2, bug_seg1, + (bug_ledg & 0x80) ? 'G' : 'g', (bug_ledg & 0x40) ? 'G' : 'g', + (bug_ledg & 0x20) ? 'G' : 'g', (bug_ledg & 0x10) ? 'G' : 'g', + (bug_ledg & 0x08) ? 'G' : 'g', (bug_ledg & 0x04) ? 'G' : 'g', + (bug_ledg & 0x02) ? 'G' : 'g', (bug_ledg & 0x01) ? 'G' : 'g', + (bug_ledr & 0x80) ? 'R' : 'r', (bug_ledr & 0x40) ? 'R' : 'r', + (bug_ledr & 0x20) ? 'R' : 'r', (bug_ledr & 0x10) ? 'R' : 'r', + (bug_ledr & 0x08) ? 'R' : 'r', (bug_ledr & 0x04) ? 'R' : 'r', + (bug_ledr & 0x02) ? 'R' : 'r', (bug_ledr & 0x01) ? 'R' : 'r'); /* Send formatted string to the UI. */ ui_sb_bugui(bug_str); } - /* Flush the serial port. */ static void bug_spflsh(void) @@ -141,7 +136,6 @@ bug_spflsh(void) bug_bptr = bug_buff; } - /* Handle a write to the Serial Port Data register. */ static void bug_wsport(uint8_t val) @@ -152,9 +146,9 @@ bug_wsport(uint8_t val) bug_ctrl &= ~CTRL_SPORT; /* Delay while processing byte.. */ - if (bug_bptr == &bug_buff[FIFO_LEN-1]) { - /* Buffer full, gotta flush. */ - bug_spflsh(); + if (bug_bptr == &bug_buff[FIFO_LEN - 1]) { + /* Buffer full, gotta flush. */ + bug_spflsh(); } /* Write (store) the byte. */ @@ -166,7 +160,6 @@ bug_wsport(uint8_t val) bugger_log("BUGGER- sport %02x\n", val); } - /* Handle a write to the Serial Port Configuration register. */ static void bug_wspcfg(uint8_t val) @@ -176,50 +169,48 @@ bug_wspcfg(uint8_t val) bugger_log("BUGGER- spcfg %02x\n", bug_spcfg); } - /* Handle a write to the control register. */ static void bug_wctrl(uint8_t val) { if (val == CTRL_RESET) { - /* User wants us to reset. */ - bug_ctrl = CTRL_INIT; - bug_spcfg = 0x00; - bug_bptr = NULL; + /* User wants us to reset. */ + bug_ctrl = CTRL_INIT; + bug_spcfg = 0x00; + bug_bptr = NULL; } else { - /* If turning off the serial port, flush it. */ - if ((bug_ctrl & CTRL_SPORT) && !(val & CTRL_SPORT)) - bug_spflsh(); + /* If turning off the serial port, flush it. */ + if ((bug_ctrl & CTRL_SPORT) && !(val & CTRL_SPORT)) + bug_spflsh(); - /* FIXME: did they do this using an XOR of operation bits? --FvK */ + /* FIXME: did they do this using an XOR of operation bits? --FvK */ - if (val & CTRL_SPCFG) { - /* User wants to configure the serial port. */ - bug_ctrl &= ~(CTRL_SPORT|CTRL_SEG2|CTRL_SEG1|CTRL_GLED); - bug_ctrl |= CTRL_SPCFG; - } else if (val & CTRL_SPORT) { - /* User wants to talk to the serial port. */ - bug_ctrl &= ~(CTRL_SPCFG|CTRL_SEG2|CTRL_SEG1|CTRL_GLED); - bug_ctrl |= CTRL_SPORT; - if (bug_bptr == NULL) - bug_bptr = bug_buff; - } else if (val & CTRL_SEG2) { - /* User selected SEG2 (LEFT, Plus only) for output. */ - bug_ctrl &= ~(CTRL_SPCFG|CTRL_SPORT|CTRL_SEG1|CTRL_GLED); - bug_ctrl |= CTRL_SEG2; - } else if (val & CTRL_SEG1) { - /* User selected SEG1 (RIGHT) for output. */ - bug_ctrl &= ~(CTRL_SPCFG|CTRL_SPORT|CTRL_SEG2|CTRL_GLED); - bug_ctrl |= CTRL_SEG1; - } else if (val & CTRL_GLED) { - /* User selected the GREEN LEDs for output. */ - bug_ctrl &= ~(CTRL_SPCFG|CTRL_SPORT|CTRL_SEG2|CTRL_SEG1); - bug_ctrl |= CTRL_GLED; - } else { - /* User selected the RED LEDs for output. */ - bug_ctrl &= - ~(CTRL_SPCFG|CTRL_SPORT|CTRL_SEG2|CTRL_SEG1|CTRL_GLED); - } + if (val & CTRL_SPCFG) { + /* User wants to configure the serial port. */ + bug_ctrl &= ~(CTRL_SPORT | CTRL_SEG2 | CTRL_SEG1 | CTRL_GLED); + bug_ctrl |= CTRL_SPCFG; + } else if (val & CTRL_SPORT) { + /* User wants to talk to the serial port. */ + bug_ctrl &= ~(CTRL_SPCFG | CTRL_SEG2 | CTRL_SEG1 | CTRL_GLED); + bug_ctrl |= CTRL_SPORT; + if (bug_bptr == NULL) + bug_bptr = bug_buff; + } else if (val & CTRL_SEG2) { + /* User selected SEG2 (LEFT, Plus only) for output. */ + bug_ctrl &= ~(CTRL_SPCFG | CTRL_SPORT | CTRL_SEG1 | CTRL_GLED); + bug_ctrl |= CTRL_SEG2; + } else if (val & CTRL_SEG1) { + /* User selected SEG1 (RIGHT) for output. */ + bug_ctrl &= ~(CTRL_SPCFG | CTRL_SPORT | CTRL_SEG2 | CTRL_GLED); + bug_ctrl |= CTRL_SEG1; + } else if (val & CTRL_GLED) { + /* User selected the GREEN LEDs for output. */ + bug_ctrl &= ~(CTRL_SPCFG | CTRL_SPORT | CTRL_SEG2 | CTRL_SEG1); + bug_ctrl |= CTRL_GLED; + } else { + /* User selected the RED LEDs for output. */ + bug_ctrl &= ~(CTRL_SPCFG | CTRL_SPORT | CTRL_SEG2 | CTRL_SEG1 | CTRL_GLED); + } } /* Update the UI with active settings. */ @@ -227,7 +218,6 @@ bug_wctrl(uint8_t val) bug_setui(); } - /* Handle a write to the data register. */ static void bug_wdata(uint8_t val) @@ -235,27 +225,26 @@ bug_wdata(uint8_t val) bug_data = val; if (bug_ctrl & CTRL_SPCFG) - bug_wspcfg(val); - else if (bug_ctrl & CTRL_SPORT) - bug_wsport(val); - else { - if (bug_ctrl & CTRL_SEG2) - bug_seg2 = val; - else if (bug_ctrl & CTRL_SEG1) - bug_seg1 = val; - else if (bug_ctrl & CTRL_GLED) - bug_ledg = val; - else - bug_ledr = val; + bug_wspcfg(val); + else if (bug_ctrl & CTRL_SPORT) + bug_wsport(val); + else { + if (bug_ctrl & CTRL_SEG2) + bug_seg2 = val; + else if (bug_ctrl & CTRL_SEG1) + bug_seg1 = val; + else if (bug_ctrl & CTRL_GLED) + bug_ledg = val; + else + bug_ledr = val; - bugger_log("BUGGER- data %02x\n", bug_data); + bugger_log("BUGGER- data %02x\n", bug_data); } /* Update the UI with active settings. */ bug_setui(); } - /* Reset the ISA BusBugger controller. */ static void bug_reset(void) @@ -264,74 +253,75 @@ bug_reset(void) bug_data = 0x00; /* Clear the RED and GREEN LEDs. */ - bug_ledr = 0x00; bug_ledg = 0x00; + bug_ledr = 0x00; + bug_ledg = 0x00; /* Clear both 7SEG displays. */ - bug_seg1 = 0x00; bug_seg2 = 0x00; - + bug_seg1 = 0x00; + bug_seg2 = 0x00; + /* Reset the control register (updates UI.) */ bug_wctrl(CTRL_RESET); } - /* Handle a WRITE operation to one of our registers. */ static void -bug_write(uint16_t port, uint8_t val, void *priv) +bug_write(uint16_t port, uint8_t val, UNUSED(void *priv)) { - switch (port-BUGGER_ADDR) { - case BUG_CTRL: /* control register */ - if (val == CTRL_RESET) { - /* Perform a full reset. */ - bug_reset(); - } else if (bug_ctrl & CTRL_INIT) { - /* Only allow writes if initialized. */ - bug_wctrl(val); - } - break; - - case BUG_DATA: /* data register */ - if (bug_ctrl & CTRL_INIT) { - bug_wdata(val); - } - break; + switch (port - BUGGER_ADDR) { + case BUG_CTRL: /* control register */ + if (val == CTRL_RESET) { + /* Perform a full reset. */ + bug_reset(); + } else if (bug_ctrl & CTRL_INIT) { + /* Only allow writes if initialized. */ + bug_wctrl(val); + } + break; + case BUG_DATA: /* data register */ + if (bug_ctrl & CTRL_INIT) { + bug_wdata(val); + } + break; + default: + break; } } - /* Handle a READ operation from one of our registers. */ static uint8_t -bug_read(uint16_t port, void *priv) +bug_read(uint16_t port, UNUSED(void *priv)) { uint8_t ret = 0xff; - if (bug_ctrl & CTRL_INIT) switch (port-BUGGER_ADDR) { - case BUG_CTRL: /* control register */ - ret = bug_ctrl; - break; + if (bug_ctrl & CTRL_INIT) + switch (port - BUGGER_ADDR) { + case BUG_CTRL: /* control register */ + ret = bug_ctrl; + break; - case BUG_DATA: /* data register */ - if (bug_ctrl & CTRL_SPCFG) { - ret = bug_spcfg; - } else if (bug_ctrl & CTRL_SPORT) { - ret = 0x00; /* input not supported */ - } else { - /* Just read the DIP switch. */ - ret = bug_data; - } - break; + case BUG_DATA: /* data register */ + if (bug_ctrl & CTRL_SPCFG) { + ret = bug_spcfg; + } else if (bug_ctrl & CTRL_SPORT) { + ret = 0x00; /* input not supported */ + } else { + /* Just read the DIP switch. */ + ret = bug_data; + } + break; - default: - break; - } + default: + break; + } - return(ret); + return ret; } - /* Initialize the ISA BusBugger emulator. */ static void * -bug_init(const device_t *info) +bug_init(UNUSED(const device_t *info)) { bugger_log("%s, I/O=%04x\n", info->name, BUGGER_ADDR); @@ -339,28 +329,30 @@ bug_init(const device_t *info) bug_reset(); io_sethandler(BUGGER_ADDR, BUGGER_ADDRLEN, - bug_read, NULL, NULL, bug_write, NULL, NULL, NULL); + bug_read, NULL, NULL, bug_write, NULL, NULL, NULL); /* Just so its not NULL. */ - return(&bug_ctrl); + return (&bug_ctrl); } - /* Remove the ISA BusBugger emulator from the system. */ static void bug_close(UNUSED(void *priv)) { io_removehandler(BUGGER_ADDR, BUGGER_ADDRLEN, - bug_read, NULL, NULL, bug_write, NULL, NULL, NULL); + bug_read, NULL, NULL, bug_write, NULL, NULL, NULL); } - const device_t bugger_device = { - "ISA/PCI Bus Bugger", - "bugger", - DEVICE_ISA | DEVICE_AT, - 0, - bug_init, bug_close, NULL, - { NULL }, NULL, NULL, - NULL + .name = "ISA/PCI Bus Bugger", + .internal_name = "bugger", + .flags = DEVICE_ISA | DEVICE_AT, + .local = 0, + .init = bug_init, + .close = bug_close, + .reset = NULL, + { .available = NULL }, + .speed_changed = NULL, + .force_redraw = NULL, + .config = NULL }; diff --git a/src/device/cartridge.c b/src/device/cartridge.c index 9743c2e87..edabd3ed0 100644 --- a/src/device/cartridge.c +++ b/src/device/cartridge.c @@ -1,18 +1,18 @@ /* - * 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. + * 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. + * This file is part of the 86Box distribution. * - * Implementation of the PCjr cartridge emulation. + * Implementation of the PCjr cartridge emulation. * * * - * Authors: Miran Grca, + * Authors: Miran Grca, * - * Copyright 2021 Miran Grca. + * Copyright 2021 Miran Grca. */ #include #include @@ -29,67 +29,57 @@ #include <86box/machine.h> #include <86box/cartridge.h> - -typedef struct -{ - uint8_t * buf; - uint32_t base; +typedef struct cart_t { + uint8_t *buf; + uint32_t base; } cart_t; +char cart_fns[2][512]; -char cart_fns[2][512]; - - -static cart_t carts[2]; - -static mem_mapping_t cart_mappings[2]; +static cart_t carts[2]; +static mem_mapping_t cart_mappings[2]; #ifdef ENABLE_CARTRIDGE_LOG int cartridge_do_log = ENABLE_CARTRIDGE_LOG; - static void cartridge_log(const char *fmt, ...) { - va_list ap; + va_list ap; - if (cartridge_do_log) - { - va_start(ap, fmt); - pclog_ex(fmt, ap); - va_end(ap); - } + if (cartridge_do_log) { + va_start(ap, fmt); + pclog_ex(fmt, ap); + va_end(ap); + } } #else -#define cartridge_log(fmt, ...) +# define cartridge_log(fmt, ...) #endif - static uint8_t cart_read(uint32_t addr, void *priv) { - cart_t *dev = (cart_t *) priv; + const cart_t *dev = (cart_t *) priv; return dev->buf[addr - dev->base]; } - static void -cart_load_error(int drive, char *fn) +cart_load_error(int drive, UNUSED(char *fn)) { - cartridge_log("Cartridge: could not load '%s'\n",fn); + cartridge_log("Cartridge: could not load '%s'\n", fn); memset(cart_fns[drive], 0, sizeof(cart_fns[drive])); ui_sb_update_icon_state(SB_CARTRIDGE | drive, 1); } - static void cart_image_close(int drive) { if (carts[drive].buf != NULL) { - free(carts[drive].buf); - carts[drive].buf = NULL; + free(carts[drive].buf); + carts[drive].buf = NULL; } carts[drive].base = 0x00000000; @@ -97,44 +87,43 @@ cart_image_close(int drive) mem_mapping_disable(&cart_mappings[drive]); } - static void cart_image_load(int drive, char *fn) { - FILE *f; + FILE *fp; uint32_t size; uint32_t base = 0x00000000; cart_image_close(drive); - f = fopen(fn, "rb"); - if (fseek(f, 0, SEEK_END) == -1) - fatal("cart_image_load(): Error seeking to the end of the file\n"); - size = ftell(f); + fp = fopen(fn, "rb"); + if (fseek(fp, 0, SEEK_END) == -1) + fatal("cart_image_load(): Error seeking to the end of the file\n"); + size = ftell(fp); if (size < 0x1200) { - cartridge_log("cart_image_load(): File size %i is too small\n", size); - cart_load_error(drive, fn); - return; + cartridge_log("cart_image_load(): File size %i is too small\n", size); + cart_load_error(drive, fn); + return; } if (size & 0x00000fff) { - size -= 0x00000200; - fseek(f, 0x000001ce, SEEK_SET); - fread(&base, 1, 2, f); - base <<= 4; - fseek(f, 0x00000200, SEEK_SET); - carts[drive].buf = (uint8_t *) malloc(size); - memset(carts[drive].buf, 0x00, size); - fread(carts[drive].buf, 1, size, f); - fclose(f); + size -= 0x00000200; + fseek(fp, 0x000001ce, SEEK_SET); + (void) !fread(&base, 1, 2, fp); + base <<= 4; + fseek(fp, 0x00000200, SEEK_SET); + carts[drive].buf = (uint8_t *) malloc(size); + memset(carts[drive].buf, 0x00, size); + (void) !fread(carts[drive].buf, 1, size, fp); + fclose(fp); } else { - base = drive ? 0xe0000 : 0xd0000; - if (size == 32768) - base += 0x8000; - fseek(f, 0x00000000, SEEK_SET); - carts[drive].buf = (uint8_t *) malloc(size); - memset(carts[drive].buf, 0x00, size); - fread(carts[drive].buf, 1, size, f); - fclose(f); + base = drive ? 0xe0000 : 0xd0000; + if (size == 32768) + base += 0x8000; + fseek(fp, 0x00000000, SEEK_SET); + carts[drive].buf = (uint8_t *) malloc(size); + memset(carts[drive].buf, 0x00, size); + (void) !fread(carts[drive].buf, 1, size, fp); + fclose(fp); } cartridge_log("cart_image_load(): %s at %08X-%08X\n", fn, base, base + size - 1); @@ -144,37 +133,34 @@ cart_image_load(int drive, char *fn) mem_mapping_set_p(&cart_mappings[drive], &(carts[drive])); } - static void cart_load_common(int drive, char *fn, uint8_t hard_reset) { - FILE *f; + FILE *fp; cartridge_log("Cartridge: loading drive %d with '%s'\n", drive, fn); if (!fn) - return; - f = plat_fopen(fn, "rb"); - if (f) { - fclose(f); - strcpy(cart_fns[drive], fn); - cart_image_load(drive, cart_fns[drive]); - /* On the real PCjr, inserting a cartridge causes a reset - in order to boot from the cartridge. */ - if (!hard_reset) - resetx86(); + return; + fp = plat_fopen(fn, "rb"); + if (fp) { + fclose(fp); + strcpy(cart_fns[drive], fn); + cart_image_load(drive, cart_fns[drive]); + /* On the real PCjr, inserting a cartridge causes a reset + in order to boot from the cartridge. */ + if (!hard_reset) + resetx86(); } else - cart_load_error(drive, fn); + cart_load_error(drive, fn); } - void cart_load(int drive, char *fn) { cart_load_common(drive, fn, 0); } - void cart_close(int drive) { @@ -185,24 +171,21 @@ cart_close(int drive) ui_sb_update_icon_state(SB_CARTRIDGE | drive, 1); } - void cart_reset(void) { - int i; - cart_image_close(1); cart_image_close(0); if (!machine_has_cartridge(machine)) - return; + return; - for (i = 0; i < 2; i++) { - mem_mapping_add(&cart_mappings[i], 0x000d0000, 0x00002000, - cart_read,NULL,NULL, - NULL,NULL,NULL, - NULL, MEM_MAPPING_EXTERNAL, NULL); - mem_mapping_disable(&cart_mappings[i]); + for (uint8_t i = 0; i < 2; i++) { + mem_mapping_add(&cart_mappings[i], 0x000d0000, 0x00002000, + cart_read, NULL, NULL, + NULL, NULL, NULL, + NULL, MEM_MAPPING_EXTERNAL, NULL); + mem_mapping_disable(&cart_mappings[i]); } cart_load_common(0, cart_fns[0], 1); diff --git a/src/device/cassette.c b/src/device/cassette.c index 9c13c7dbb..1d0b88531 100644 --- a/src/device/cassette.c +++ b/src/device/cassette.c @@ -19,7 +19,6 @@ * Public License for more details. * *****************************************************************************/ - #include #include #include @@ -40,685 +39,690 @@ // #include - #define CAS_CLK 1193182 +pc_cassette_t *cassette; -pc_cassette_t * cassette; +char cassette_fname[512]; +char cassette_mode[512]; +unsigned long cassette_pos; +unsigned long cassette_srate; +int cassette_enable; +int cassette_append; +int cassette_pcm; +int cassette_ui_writeprot; -char cassette_fname[512]; -char cassette_mode[512]; -unsigned long cassette_pos, cassette_srate; -int cassette_enable; -int cassette_append, cassette_pcm; -int cassette_ui_writeprot; - - -static int cassette_cycles = -1; - - -static void pc_cas_reset (pc_cassette_t *cas); +static int cassette_cycles = -1; +static void pc_cas_reset(pc_cassette_t *cas); #ifdef ENABLE_CASSETTE_LOG int cassette_do_log = ENABLE_CASSETTE_LOG; - static void cassette_log(const char *fmt, ...) { - va_list ap; + va_list ap; - if (cassette_do_log) - { - va_start(ap, fmt); - pclog_ex(fmt, ap); - va_end(ap); - } + if (cassette_do_log) { + va_start(ap, fmt); + pclog_ex(fmt, ap); + va_end(ap); + } } #else -#define cassette_log(fmt, ...) +# define cassette_log(fmt, ...) #endif - -void pc_cas_init (pc_cassette_t *cas) +void +pc_cas_init(pc_cassette_t *cas) { - cas->save = 0; - cas->pcm = 0; + cas->save = 0; + cas->pcm = 0; - cas->motor = 0; - ui_sb_update_icon(SB_CASSETTE, 0); + cas->motor = 0; + ui_sb_update_icon(SB_CASSETTE, 0); - cas->position = 0; + cas->position = 0; - cas->position_save = 0; - cas->position_load = 0; + cas->position_save = 0; + cas->position_load = 0; - cas->data_out = 0; - cas->data_inp = 0; + cas->data_out = 0; + cas->data_inp = 0; - cas->pcm_out_vol = 64; - cas->pcm_out_val = 0; + cas->pcm_out_vol = 64; + cas->pcm_out_val = 0; - cas->cas_out_cnt = 0; - cas->cas_out_buf = 0; + cas->cas_out_cnt = 0; + cas->cas_out_buf = 0; - cas->cas_inp_cnt = 0; - cas->cas_inp_buf = 0; - cas->cas_inp_bit = 0; + cas->cas_inp_cnt = 0; + cas->cas_inp_buf = 0; + cas->cas_inp_bit = 0; - cas->clk = 0; + cas->clk = 0; - cas->clk_pcm = 0; + cas->clk_pcm = 0; - cas->clk_out = 0; - cas->clk_inp = 0; + cas->clk_out = 0; + cas->clk_inp = 0; - cas->srate = 44100; + cas->srate = 44100; - cas->close = 0; - cas->fname = NULL; - cas->fp = NULL; + cas->close = 0; + cas->fname = NULL; + cas->fp = NULL; - pc_cas_reset (cas); + pc_cas_reset(cas); } -void pc_cas_free (pc_cassette_t *cas) +void +pc_cas_free(pc_cassette_t *cas) { - free (cas->fname); + free(cas->fname); - if (cas->close) { - fclose (cas->fp); - } + if (cas->close) { + fclose(cas->fp); + } } -pc_cassette_t *pc_cas_new (void) +pc_cassette_t * +pc_cas_new(void) { - pc_cassette_t *cas; + pc_cassette_t *cas; - cas = malloc (sizeof (pc_cassette_t)); + cas = malloc(sizeof(pc_cassette_t)); - if (cas == NULL) { - return (NULL); - } + if (cas == NULL) { + return (NULL); + } - pc_cas_init (cas); + pc_cas_init(cas); - return (cas); + return cas; } -void pc_cas_del (pc_cassette_t *cas) +void +pc_cas_del(pc_cassette_t *cas) { - if (cas != NULL) { - pc_cas_free (cas); - free (cas); - } + if (cas != NULL) { + pc_cas_free(cas); + free(cas); + } } -int pc_cas_set_fname (pc_cassette_t *cas, const char *fname) +int +pc_cas_set_fname(pc_cassette_t *cas, const char *fname) { - unsigned n; - const char * ext; + unsigned n; + const char *ext; - if (cas->close) - fclose (cas->fp); + if (cas->close) + fclose(cas->fp); - cas->close = 0; - cas->fp = NULL; + cas->close = 0; + cas->fp = NULL; - free (cas->fname); - cas->fname = NULL; + free(cas->fname); + cas->fname = NULL; - cas->position = 0; + cas->position = 0; - cas->position_save = 0; - cas->position_load = 0; + cas->position_save = 0; + cas->position_load = 0; - if (fname == NULL) { - ui_sb_update_icon_state(SB_CASSETTE, 1); - return (0); - } + if (fname == NULL) { + ui_sb_update_icon_state(SB_CASSETTE, 1); + return 0; + } - cas->fp = plat_fopen (fname, "r+b"); + cas->fp = plat_fopen(fname, "r+b"); - if (cas->fp == NULL) - cas->fp = plat_fopen (fname, "w+b"); + if (cas->fp == NULL) + cas->fp = plat_fopen(fname, "w+b"); - if (cas->fp == NULL) { - ui_sb_update_icon_state(SB_CASSETTE, 1); - return (1); - } + if (cas->fp == NULL) { + ui_sb_update_icon_state(SB_CASSETTE, 1); + return 1; + } - cas->close = 1; + cas->close = 1; - pc_cas_append (cas); + pc_cas_append(cas); - cas->position_save = cas->position; + cas->position_save = cas->position; - if (cas->save == 0) - pc_cas_set_position (cas, 0); + if (cas->save == 0) + pc_cas_set_position(cas, 0); - n = strlen (fname); + n = strlen(fname); - cas->fname = malloc ((n + 1) * sizeof(char)); + cas->fname = malloc((n + 1) * sizeof(char)); - if (cas->fname != NULL) - memcpy (cas->fname, fname, (n + 1) * sizeof(char)); + if (cas->fname != NULL) + memcpy(cas->fname, fname, (n + 1) * sizeof(char)); - if (n > 4) { - ext = fname + (n - 4); + if (n > 4) { + ext = fname + (n - 4); - /* Has to be 44.1 kHz, mono, 8-bit. */ - if (stricmp (ext, ".pcm") == 0) - pc_cas_set_pcm (cas, 1); - else if (stricmp (ext, ".raw") == 0) - pc_cas_set_pcm (cas, 1); - else if (stricmp (ext, ".wav") == 0) - pc_cas_set_pcm (cas, 1); - else if (stricmp (ext, ".cas") == 0) - pc_cas_set_pcm (cas, 0); - } + /* Has to be 44.1 kHz, mono, 8-bit. */ + if (stricmp(ext, ".pcm") == 0) + pc_cas_set_pcm(cas, 1); + else if (stricmp(ext, ".raw") == 0) + pc_cas_set_pcm(cas, 1); + else if (stricmp(ext, ".wav") == 0) + pc_cas_set_pcm(cas, 1); + else if (stricmp(ext, ".cas") == 0) + pc_cas_set_pcm(cas, 0); + } - return (0); + return 0; } -static -void pc_cas_reset (pc_cassette_t *cas) +static void +pc_cas_reset(pc_cassette_t *cas) { - unsigned i; + cas->clk_pcm = 0; - cas->clk_pcm = 0; + cas->clk_out = cas->clk; + cas->clk_inp = 0; - cas->clk_out = cas->clk; - cas->clk_inp = 0; + cas->pcm_out_val = 0; - cas->pcm_out_val = 0; + cas->cas_out_cnt = 0; + cas->cas_out_buf = 0; - cas->cas_out_cnt = 0; - cas->cas_out_buf = 0; + cas->cas_inp_cnt = 0; + cas->cas_inp_buf = 0; + cas->cas_inp_bit = 0; - cas->cas_inp_cnt = 0; - cas->cas_inp_buf = 0; - cas->cas_inp_bit = 0; - - for (i = 0; i < 3; i++) { - cas->pcm_inp_fir[i] = 0; - } + for (uint8_t i = 0; i < 3; i++) { + cas->pcm_inp_fir[i] = 0; + } } -int pc_cas_get_mode (const pc_cassette_t *cas) +int +pc_cas_get_mode(const pc_cassette_t *cas) { - return (cas->save); + return (cas->save); } -void pc_cas_set_mode (pc_cassette_t *cas, int save) +void +pc_cas_set_mode(pc_cassette_t *cas, int save) { - save = (save != 0); + save = (save != 0); - if (cas->save == save) { - return; - } + if (cas->save == save) { + return; + } - if (cas->save) { - cas->position_save = cas->position; - cas->position = cas->position_load; - } - else { - cas->position_load = cas->position; - cas->position = cas->position_save; - } + if (cas->save) { + cas->position_save = cas->position; + cas->position = cas->position_load; + } else { + cas->position_load = cas->position; + cas->position = cas->position_save; + } - cas->save = save; + cas->save = save; - memset(cassette_mode, 0x00, sizeof(cassette_mode)); - if (save) - memcpy(cassette_mode, "save", strlen("save") + 1); - else - memcpy(cassette_mode, "load", strlen("load") + 1); + memset(cassette_mode, 0x00, sizeof(cassette_mode)); + if (save) + memcpy(cassette_mode, "save", strlen("save") + 1); + else + memcpy(cassette_mode, "load", strlen("load") + 1); - if (cas->fp != NULL) { - fflush (cas->fp); + if (cas->fp != NULL) { + fflush(cas->fp); - pc_cas_set_position (cas, cas->position); - } + pc_cas_set_position(cas, cas->position); + } - pc_cas_reset (cas); + pc_cas_reset(cas); } -int pc_cas_get_pcm (const pc_cassette_t *cas) +int +pc_cas_get_pcm(const pc_cassette_t *cas) { - return (cas->pcm); + return (cas->pcm); } -void pc_cas_set_pcm (pc_cassette_t *cas, int pcm) +void +pc_cas_set_pcm(pc_cassette_t *cas, int pcm) { - cas->pcm = (pcm != 0); + cas->pcm = (pcm != 0); - cassette_pcm = (pcm != 0); + cassette_pcm = (pcm != 0); - pc_cas_reset (cas); + pc_cas_reset(cas); } -unsigned long pc_cas_get_srate (const pc_cassette_t *cas) +unsigned long +pc_cas_get_srate(const pc_cassette_t *cas) { - return (cas->srate); + return (cas->srate); } -void pc_cas_set_srate (pc_cassette_t *cas, unsigned long srate) +void +pc_cas_set_srate(pc_cassette_t *cas, unsigned long srate) { - cas->srate = srate; + cas->srate = srate; - pc_cas_reset (cas); + pc_cas_reset(cas); } -void pc_cas_rewind (pc_cassette_t *cas) +void +pc_cas_rewind(pc_cassette_t *cas) { - if (cas->fp != NULL) { - rewind (cas->fp); - cas->position = 0; - } + if (cas->fp != NULL) { + rewind(cas->fp); + cas->position = 0; + } - pc_cas_reset (cas); + pc_cas_reset(cas); } -void pc_cas_append (pc_cassette_t *cas) +void +pc_cas_append(pc_cassette_t *cas) { - if (cas->fp != NULL) { - fseek (cas->fp, 0, SEEK_END); - cas->position = ftell (cas->fp); - } + if (cas->fp != NULL) { + fseek(cas->fp, 0, SEEK_END); + cas->position = ftell(cas->fp); + } - pc_cas_reset (cas); + pc_cas_reset(cas); } -unsigned long pc_cas_get_position (const pc_cassette_t *cas) +unsigned long +pc_cas_get_position(const pc_cassette_t *cas) { - return (cas->position); + return (cas->position); } -int pc_cas_set_position (pc_cassette_t *cas, unsigned long pos) +int +pc_cas_set_position(pc_cassette_t *cas, unsigned long pos) { - if (cas->fp == NULL) { - return (1); - } + if (cas->fp == NULL) { + return 1; + } - if (fseek (cas->fp, pos, SEEK_SET) != 0) { - return (1); - } + if (fseek(cas->fp, pos, SEEK_SET) != 0) { + return 1; + } - cas->position = pos; + cas->position = pos; - pc_cas_reset (cas); + pc_cas_reset(cas); - return (0); + return 0; } -static -void pc_cas_read_bit (pc_cassette_t *cas) +static void +pc_cas_read_bit(pc_cassette_t *cas) { - int val; + int val; - if (cas->cas_inp_cnt == 0) { - if (cas->fp == NULL) { - return; - } + if (cas->cas_inp_cnt == 0) { + if (cas->fp == NULL) { + return; + } - if (feof (cas->fp)) { - return; - } + if (feof(cas->fp)) { + return; + } - val = fgetc (cas->fp); + val = fgetc(cas->fp); - if (val == EOF) { - cassette_log ("cassette EOF at %lu\n", cas->position); - return; - } + if (val == EOF) { + cassette_log("cassette EOF at %lu\n", cas->position); + return; + } - cas->position += 1; + cas->position += 1; - cas->cas_inp_cnt = 8; - cas->cas_inp_buf = val; - } + cas->cas_inp_cnt = 8; + cas->cas_inp_buf = val; + } - cas->cas_inp_bit = ((cas->cas_inp_buf & 0x80) != 0); + cas->cas_inp_bit = ((cas->cas_inp_buf & 0x80) != 0); - cas->cas_inp_buf = (cas->cas_inp_buf << 1) & 0xff; - cas->cas_inp_cnt -= 1; + cas->cas_inp_buf = (cas->cas_inp_buf << 1) & 0xff; + cas->cas_inp_cnt -= 1; } -static -int pc_cas_read_smp (pc_cassette_t *cas) +static int +pc_cas_read_smp(pc_cassette_t *cas) { - int smp, *fir; + int smp; + int *fir; - if (feof (cas->fp)) { - return (0); - } + if (feof(cas->fp)) { + return 0; + } - smp = fgetc (cas->fp); + smp = fgetc(cas->fp); - if (smp == EOF) { - cassette_log ("cassette EOF at %lu\n", cas->position); - return (0); - } + if (smp == EOF) { + cassette_log("cassette EOF at %lu\n", cas->position); + return 0; + } - cas->position += 1; + cas->position += 1; - fir = cas->pcm_inp_fir; + fir = cas->pcm_inp_fir; - fir[0] = fir[1]; - fir[1] = fir[2]; - fir[2] = (smp & 0x80) ? (smp - 256) : smp; + fir[0] = fir[1]; + fir[1] = fir[2]; + fir[2] = (smp & 0x80) ? (smp - 256) : smp; - smp = (fir[0] + 2 * fir[1] + fir[2]) / 4; + smp = (fir[0] + 2 * fir[1] + fir[2]) / 4; - return (smp); + return smp; } -static -void pc_cas_write_bit (pc_cassette_t *cas, unsigned char val) +static void +pc_cas_write_bit(pc_cassette_t *cas, unsigned char val) { - if (val && !cassette_ui_writeprot) { - cas->cas_out_buf |= (0x80 >> cas->cas_out_cnt); - } + if (val && !cassette_ui_writeprot) { + cas->cas_out_buf |= (0x80 >> cas->cas_out_cnt); + } - cas->cas_out_cnt += 1; + cas->cas_out_cnt += 1; - if (cas->cas_out_cnt >= 8) { - if (cas->fp != NULL) { - if (!cassette_ui_writeprot) - fputc (cas->cas_out_buf, cas->fp); - cas->position += 1; - } + if (cas->cas_out_cnt >= 8) { + if (cas->fp != NULL) { + if (!cassette_ui_writeprot) + fputc(cas->cas_out_buf, cas->fp); + cas->position += 1; + } - cas->cas_out_buf = 0; - cas->cas_out_cnt = 0; - } + cas->cas_out_buf = 0; + cas->cas_out_cnt = 0; + } } -static -void pc_cas_write_smp (pc_cassette_t *cas, int val) +static void +pc_cas_write_smp(pc_cassette_t *cas, int val) { - unsigned char smp; + unsigned char smp; - if (val < 0) { - smp = (val < -127) ? 0x80 : (val + 256); - } - else { - smp = (val > 127) ? 0x7f : val; - } + if (val < 0) { + smp = (val < -127) ? 0x80 : (val + 256); + } else { + smp = (val > 127) ? 0x7f : val; + } - if (!cassette_ui_writeprot) - fputc (smp, cas->fp); + if (!cassette_ui_writeprot) + fputc(smp, cas->fp); - cas->position += 1; + cas->position += 1; } -void pc_cas_set_motor (pc_cassette_t *cas, unsigned char val) +void +pc_cas_set_motor(pc_cassette_t *cas, unsigned char val) { - unsigned i; + val = (val != 0); - val = (val != 0); + if (val == cas->motor) { + return; + } - if (val == cas->motor) { - return; - } + if ((val == 0) && cas->save && cas->pcm) { + for (unsigned long i = 0; i < (cas->srate / 16); i++) { + pc_cas_write_smp(cas, 0); + } + } - if ((val == 0) && cas->save && cas->pcm) { - for (i = 0; i < (cas->srate / 16); i++) { - pc_cas_write_smp (cas, 0); - } - } + cassette_log("cassette %S at %lu motor %s\n", (cas->fname != NULL) ? cas->fname : "", cas->position, val ? "on" : "off"); - cassette_log ("cassette %S at %lu motor %s\n", (cas->fname != NULL) ? cas->fname : "", cas->position, val ? "on" : "off"); + cas->motor = val; - cas->motor = val; + if (cas->fp != NULL) { + fflush(cas->fp); - if (cas->fp != NULL) { - fflush (cas->fp); + pc_cas_set_position(cas, cas->position); + } - pc_cas_set_position (cas, cas->position); - } + pc_cas_reset(cas); - pc_cas_reset (cas); + if (cas->motor) + timer_set_delay_u64(&cas->timer, 8ULL * PITCONST); + else + timer_disable(&cas->timer); - if (cas->motor) - timer_set_delay_u64(&cas->timer, 8ULL * PITCONST); - else - timer_disable(&cas->timer); - - ui_sb_update_icon(SB_CASSETTE, !!val); + ui_sb_update_icon(SB_CASSETTE, !!val); } -unsigned char pc_cas_get_inp (const pc_cassette_t *cas) +unsigned char +pc_cas_get_inp(const pc_cassette_t *cas) { - return (cas->data_inp); + return (cas->data_inp); } -void pc_cas_set_out (pc_cassette_t *cas, unsigned char val) +void +pc_cas_set_out(pc_cassette_t *cas, unsigned char val) { - unsigned long clk; + unsigned long clk; - val = (val != 0); + val = (val != 0); - if (cas->motor == 0) { - cas->data_inp = val; - return; - } + if (cas->motor == 0) { + cas->data_inp = val; + return; + } - if (cas->data_out == val) { - return; - } + if (cas->data_out == val) { + return; + } - cas->data_out = val; + cas->data_out = val; - if (cas->pcm) { - cas->pcm_out_val = val ? -cas->pcm_out_vol : cas->pcm_out_vol; - return; - } + if (cas->pcm) { + cas->pcm_out_val = val ? -cas->pcm_out_vol : cas->pcm_out_vol; + return; + } - if (cas->save == 0) { - return; - } + if (cas->save == 0) { + return; + } - if (val == 0) { - return; - } + if (val == 0) { + return; + } - clk = cas->clk - cas->clk_out; - cas->clk_out = cas->clk; + clk = cas->clk - cas->clk_out; + cas->clk_out = cas->clk; - if (clk < (CAS_CLK / 4000)) { - ; - } - else if (clk < ((3 * CAS_CLK) / 4000)) { - pc_cas_write_bit (cas, 0); - } - else if (clk < ((5 * CAS_CLK) / 4000)) { - pc_cas_write_bit (cas, 1); - } + if (clk < (CAS_CLK / 4000)) { + ; + } else if (clk < ((3 * CAS_CLK) / 4000)) { + pc_cas_write_bit(cas, 0); + } else if (clk < ((5 * CAS_CLK) / 4000)) { + pc_cas_write_bit(cas, 1); + } } -void pc_cas_print_state (const pc_cassette_t *cas) +void +pc_cas_print_state(UNUSED(const pc_cassette_t *cas)) { - cassette_log ("%s %s %lu %s %lu\n", (cas->fname != NULL) ? cas->fname : "", cas->pcm ? "pcm" : "cas", cas->srate, cas->save ? "save" : "load", cas->position); + cassette_log("%s %s %lu %s %lu\n", (cas->fname != NULL) ? cas->fname : "", cas->pcm ? "pcm" : "cas", cas->srate, cas->save ? "save" : "load", cas->position); } -static -void pc_cas_clock_pcm (pc_cassette_t *cas, unsigned long cnt) +static void +pc_cas_clock_pcm(pc_cassette_t *cas, unsigned long cnt) { - unsigned long i, n; - int v = 0; + uint64_t n; + int v = 0; - n = cas->srate * cnt + cas->clk_pcm; + n = cas->srate * cnt + cas->clk_pcm; - cas->clk_pcm = n % CAS_CLK; + cas->clk_pcm = n % CAS_CLK; - n = n / CAS_CLK; + n = n / CAS_CLK; - if (n == 0) { - return; - } + if (n == 0) { + return; + } - if (cas->save) { - for (i = 0; i < n; i++) { - pc_cas_write_smp (cas, cas->pcm_out_val); - } - } - else { - for (i = 0; i < n; i++) { - v = pc_cas_read_smp (cas); - } + if (cas->save) { + for (uint64_t i = 0; i < n; i++) { + pc_cas_write_smp(cas, cas->pcm_out_val); + } + } else { + for (uint64_t i = 0; i < n; i++) { + v = pc_cas_read_smp(cas); + } - cas->data_inp = (v < 0) ? 0 : 1; - } + cas->data_inp = (v < 0) ? 0 : 1; + } } -void pc_cas_clock (pc_cassette_t *cas, unsigned long cnt) +void +pc_cas_clock(pc_cassette_t *cas, unsigned long cnt) { - cas->clk += cnt; + cas->clk += cnt; - if (cas->motor == 0) { - return; - } + if (cas->motor == 0) { + return; + } - if (cas->pcm) { - pc_cas_clock_pcm (cas, cnt); - return; - } + if (cas->pcm) { + pc_cas_clock_pcm(cas, cnt); + return; + } - if (cas->save) { - return; - } + if (cas->save) { + return; + } - if (cas->clk_inp > cnt) { - cas->clk_inp -= cnt; - return; - } + if (cas->clk_inp > cnt) { + cas->clk_inp -= cnt; + return; + } - cnt -= cas->clk_inp; + cnt -= cas->clk_inp; - cas->data_inp = !cas->data_inp; + cas->data_inp = !cas->data_inp; - if (cas->data_inp) { - pc_cas_read_bit (cas); - } + if (cas->data_inp) { + pc_cas_read_bit(cas); + } - if (cas->cas_inp_bit) { - cas->clk_inp = CAS_CLK / 2000; - } - else { - cas->clk_inp = CAS_CLK / 4000; - } + if (cas->cas_inp_bit) { + cas->clk_inp = CAS_CLK / 2000; + } else { + cas->clk_inp = CAS_CLK / 4000; + } - if (cas->clk_inp > cnt) { - cas->clk_inp -= cnt; - } + if (cas->clk_inp > cnt) { + cas->clk_inp -= cnt; + } } - -void pc_cas_advance (pc_cassette_t *cas) +void +pc_cas_advance(pc_cassette_t *cas) { int ticks; cpu_s = (CPU *) &cpu_f->cpus[cpu_effective]; if (cas->motor == 0) - return; + return; - if (cassette_cycles == -1) - cassette_cycles = cycles; + if (cassette_cycles == -1) + cassette_cycles = cycles; if (cycles <= cassette_cycles) - ticks = (cassette_cycles - cycles); + ticks = (cassette_cycles - cycles); else - ticks = (cassette_cycles + (cpu_s->rspeed / 100) - cycles); + ticks = (cassette_cycles + (cpu_s->rspeed / 100) - cycles); cassette_cycles = cycles; pc_cas_clock(cas, ticks); } - static void -cassette_close(void *p) +cassette_close(UNUSED(void *priv)) { if (cassette != NULL) { - free(cassette); - cassette = NULL; + free(cassette); + cassette = NULL; } } - static void -cassette_callback(void *p) +cassette_callback(void *priv) { - pc_cassette_t *cas = (pc_cassette_t *) p; + pc_cassette_t *cas = (pc_cassette_t *) priv; - pc_cas_clock (cas, 8); + pc_cas_clock(cas, 8); if (cas->motor) - ui_sb_update_icon(SB_CASSETTE, 1); + ui_sb_update_icon(SB_CASSETTE, 1); timer_advance_u64(&cas->timer, 8ULL * PITCONST); } - static void * -cassette_init(const device_t *info) +cassette_init(UNUSED(const device_t *info)) { - cassette = NULL; + cassette = NULL; - if (cassette_pcm == 1) - cassette_pcm = -1; + if (cassette_pcm == 1) + cassette_pcm = -1; - cassette_log("CASSETTE: file=%s mode=%s pcm=%d srate=%lu pos=%lu append=%d\n", - (cassette_fname != NULL) ? cassette_fname : "", cassette_mode, cassette_pcm, cassette_srate, cassette_pos, cassette_append); + cassette_log("CASSETTE: file=%s mode=%s pcm=%d srate=%lu pos=%lu append=%d\n", + (cassette_fname != NULL) ? cassette_fname : "", cassette_mode, cassette_pcm, cassette_srate, cassette_pos, cassette_append); - cassette = pc_cas_new(); + cassette = pc_cas_new(); - if (cassette == NULL) { - cassette_log("ERROR: *** alloc failed\n"); - return NULL; - } + if (cassette == NULL) { + cassette_log("ERROR: *** alloc failed\n"); + return NULL; + } - if (strlen(cassette_fname) == 0) { - if (pc_cas_set_fname (cassette, NULL)) { - cassette_log("ERROR: *** opening file failed (%s)\n", cassette_fname); - } - } else { - if (pc_cas_set_fname (cassette, cassette_fname)) { - cassette_log("ERROR: *** opening file failed (%s)\n", cassette_fname); - } - } + if (strlen(cassette_fname) == 0) { + if (pc_cas_set_fname(cassette, NULL)) { + cassette_log("ERROR: *** opening file failed (%s)\n", cassette_fname); + } + } else { + if (pc_cas_set_fname(cassette, cassette_fname)) { + cassette_log("ERROR: *** opening file failed (%s)\n", cassette_fname); + } + } - if (strcmp (cassette_mode, "load") == 0) - pc_cas_set_mode (cassette, 0); - else if (strcmp (cassette_mode, "save") == 0) - pc_cas_set_mode (cassette, 1); - else { - cassette_log ("ERROR: *** unknown cassette mode (%s)\n", cassette_mode); - } + if (strcmp(cassette_mode, "load") == 0) + pc_cas_set_mode(cassette, 0); + else if (strcmp(cassette_mode, "save") == 0) + pc_cas_set_mode(cassette, 1); + else { + cassette_log("ERROR: *** unknown cassette mode (%s)\n", cassette_mode); + } - if (cassette_append) - pc_cas_append (cassette); - else - pc_cas_set_position (cassette, cassette_pos); + if (cassette_append) + pc_cas_append(cassette); + else + pc_cas_set_position(cassette, cassette_pos); - if (cassette_pcm >= 0) - pc_cas_set_pcm (cassette, cassette_pcm); + if (cassette_pcm >= 0) + pc_cas_set_pcm(cassette, cassette_pcm); - pc_cas_set_srate (cassette, cassette_srate); + pc_cas_set_srate(cassette, cassette_srate); - timer_add(&cassette->timer, cassette_callback, cassette, 0); + timer_add(&cassette->timer, cassette_callback, cassette, 0); - return cassette; + return cassette; } - const device_t cassette_device = { - "IBM PC/PCjr Cassette Device", - "cassette", - 0, - 0, - cassette_init, cassette_close, NULL, - { NULL }, NULL, NULL, - NULL + .name = "IBM PC/PCjr Cassette Device", + .internal_name = "cassette", + .flags = 0, + .local = 0, + .init = cassette_init, + .close = cassette_close, + .reset = NULL, + { .available = NULL }, + .speed_changed = NULL, + .force_redraw = NULL, + .config = NULL }; diff --git a/src/device/clock_ics9xxx.c b/src/device/clock_ics9xxx.c index 9f7e790af..263170741 100644 --- a/src/device/clock_ics9xxx.c +++ b/src/device/clock_ics9xxx.c @@ -1,18 +1,18 @@ /* - * 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. + * 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. + * This file is part of the 86Box distribution. * - * Emulation of the ICS9xxx series of clock generators. + * Emulation of the ICS9xxx series of clock generators. * * * - * Authors: RichardG, + * Authors: RichardG, * - * Copyright 2020 RichardG. + * Copyright 2020 RichardG. */ #include #include @@ -26,897 +26,893 @@ #include <86box/i2c.h> #include "cpu.h" #include <86box/clock.h> - +#include <86box/plat_unused.h> #ifdef ENABLE_ICS9xxx_LOG int ics9xxx_do_log = ENABLE_ICS9xxx_LOG; - static void ics9xxx_log(const char *fmt, ...) { va_list ap; if (ics9xxx_do_log) { - va_start(ap, fmt); - pclog_ex(fmt, ap); - va_end(ap); + va_start(ap, fmt); + pclog_ex(fmt, ap); + va_end(ap); } } -#define ICS9xxx_MODEL(model) [model] = {.name = #model, +# define ICS9xxx_MODEL(model) [model] = { .name = # model, #else -#define ics9xxx_log(fmt, ...) -#define ICS9xxx_MODEL(model) [model] = { +# define ics9xxx_log(fmt, ...) +# define ICS9xxx_MODEL(model) [model] = { #endif -#define ICS9xxx_MODEL_END() }, -#define agp_div ram_mult /* temporarily saves space while neither field matters */ +#define ICS9xxx_MODEL_END() \ + } \ + , +#define agp_div ram_mult /* temporarily saves space while neither field matters */ - - -typedef struct { - uint16_t bus: 15; - uint8_t ram_mult: 2; /* change to full float when this becomes useful */ - uint8_t pci_div: 3; +typedef struct ics9xxx_frequency_t { + uint16_t bus : 15; + uint8_t ram_mult : 2; /* change to full float when this becomes useful */ + uint8_t pci_div : 3; } ics9xxx_frequency_t; -typedef struct { +typedef struct ics9xxx_model_t { #if defined(ENABLE_ICS9xxx_LOG) || defined(ENABLE_ICS9xxx_DETECT) - const char *name; /* populated by macro */ + const char *name; /* populated by macro */ #endif - uint8_t max_reg: 3; /* largest register index */ - uint8_t regs[7]; /* default registers */ - struct { /* for each hardware frequency select bit [FS0:FS4]: */ - uint8_t normal_reg: 3; /* which register (or -1) for non-inverted input (FSn) */ - uint8_t normal_bit: 3; /* which bit (0-7) for non-inverted input (FSn) */ - uint8_t inv_reg: 3; /* which register (or -1) for inverted input (FSn#) */ - uint8_t inv_bit: 3; /* which bit (0-7) for inverted input (FSn#) */ + uint8_t max_reg : 3; /* largest register index */ + uint8_t regs[7]; /* default registers */ + struct fs_regs { /* for each hardware frequency select bit [FS0:FS4]: */ + uint8_t normal_reg : 3; /* which register (or -1) for non-inverted input (FSn) */ + uint8_t normal_bit : 3; /* which bit (0-7) for non-inverted input (FSn) */ + uint8_t inv_reg : 3; /* which register (or -1) for inverted input (FSn#) */ + uint8_t inv_bit : 3; /* which bit (0-7) for inverted input (FSn#) */ } fs_regs[5]; - uint8_t normal_bits_fixed: 1; /* set to 1 if the non-inverted bits are straps (hardware select only) */ - struct { /* hardware select bit, which should be cleared for hardware select (latched inputs), or set for programming */ - uint8_t normal_reg: 3; /* which register (or -1) */ - uint8_t normal_bit: 3; /* which bit (0-7) */ + uint8_t normal_bits_fixed : 1; /* set to 1 if the non-inverted bits are straps (hardware select only) */ + struct hw_select { /* hardware select bit, which should be cleared for hardware select (latched inputs), or set for programming */ + uint8_t normal_reg : 3; /* which register (or -1) */ + uint8_t normal_bit : 3; /* which bit (0-7) */ } hw_select; - uint8_t frequencies_ref; /* which other model to use the frequency table from (or 0) */ - const ics9xxx_frequency_t *frequencies; /* frequency table, if not using another model's table */ + uint8_t frequencies_ref; /* which other model to use the frequency table from (or 0) */ + const ics9xxx_frequency_t *frequencies; /* frequency table, if not using another model's table */ } ics9xxx_model_t; -typedef struct { - uint8_t model_idx; +typedef struct ics9xxx_t { + uint8_t model_idx; ics9xxx_model_t *model; - device_t *dyn_device; + device_t *dyn_device; ics9xxx_frequency_t *frequencies_ptr; - uint8_t regs[7]; - int8_t addr_register: 4; - uint8_t relevant_regs: 7; - uint8_t bus_match: 5; + uint8_t regs[7]; + int8_t addr_register : 4; + uint8_t relevant_regs : 7; + uint8_t bus_match : 5; } ics9xxx_t; - static const ics9xxx_model_t ics9xxx_models[] = { #ifdef ENABLE_ICS9xxx_DETECT ICS9xxx_MODEL(ICS9xxx_xx) - .max_reg = 6 - ICS9xxx_MODEL_END() + .max_reg + = 6 ICS9xxx_MODEL_END() #endif ICS9xxx_MODEL(ICS9150_08) - .max_reg = 5, - .regs = {0x00, 0xff, 0xff, 0xff, 0x6f, 0xbf}, - .fs_regs = {{0, 4, 4, 7}, {0, 5, 4, 4}, {0, 6, 5, 6}, {0, 7, 4, 1}, {-1, -1, -1, -1}}, - .hw_select = {0, 3}, - .frequencies = (const ics9xxx_frequency_t[]) { - {.bus = 5000, .pci_div = 2}, - {.bus = 7500, .pci_div = 2}, - {.bus = 8333, .pci_div = 2}, - {.bus = 6680, .pci_div = 2}, - {.bus = 10300, .pci_div = 3}, - {.bus = 11200, .pci_div = 3}, - {.bus = 13333, .pci_div = 4}, - {.bus = 10020, .pci_div = 3}, - {0} - } + .max_reg = 5, + .regs = {0x00, 0xff, 0xff, 0xff, 0x6f, 0xbf}, + .fs_regs = {{0, 4, 4, 7}, {0, 5, 4, 4}, {0, 6, 5, 6}, {0, 7, 4, 1}, {-1, -1, -1, -1}}, + .hw_select = {0, 3}, + .frequencies = (const ics9xxx_frequency_t[]) { + {.bus = 5000, .pci_div = 2}, + {.bus = 7500, .pci_div = 2}, + {.bus = 8333, .pci_div = 2}, + {.bus = 6680, .pci_div = 2}, + {.bus = 10300, .pci_div = 3}, + {.bus = 11200, .pci_div = 3}, + {.bus = 13333, .pci_div = 4}, + {.bus = 10020, .pci_div = 3}, + {0} + } ICS9xxx_MODEL_END() ICS9xxx_MODEL(ICS9248_39) - .max_reg = 5, - .regs = {0x00, 0x7f, 0xff, 0xbf, 0xf5, 0xff}, - .fs_regs = {{0, 4, 3, 6}, {0, 5, 4, 3}, {0, 6, 1, 7}, {0, 7, 4, 1}, {-1, -1, -1, -1}}, - .hw_select = {0, 3}, - .frequencies_ref = ICS9250_08 + .max_reg = 5, + .regs = {0x00, 0x7f, 0xff, 0xbf, 0xf5, 0xff}, + .fs_regs = {{0, 4, 3, 6}, {0, 5, 4, 3}, {0, 6, 1, 7}, {0, 7, 4, 1}, {-1, -1, -1, -1}}, + .hw_select = {0, 3}, + .frequencies_ref = ICS9250_08 ICS9xxx_MODEL_END() #ifdef ENABLE_ICS9xxx_DETECT ICS9xxx_MODEL(ICS9248_81) - .max_reg = 5, - .regs = {0x82, 0xfe, 0x7f, 0xff, 0xff, 0xb7}, - .fs_regs = {{0, 4, 1, 0}, {0, 5, 2, 7}, {0, 6, 5, 6}, {0, 2, 5, 3}, {-1, -1, -1, -1}}, - .hw_select = {0, 3}, - .frequencies = (const ics9xxx_frequency_t[]) { - {.bus = 9000, .ram_mult = 1, .pci_div = 3}, - {.bus = 6670, .ram_mult = 1.5, .pci_div = 2}, - {.bus = 9500, .ram_mult = 2.0/3.0, .pci_div = 3}, - {.bus = 10000, .ram_mult = 2.0/3.0, .pci_div = 3}, - {.bus = 10000, .ram_mult = 0.75, .pci_div = 3}, - {.bus = 11200, .ram_mult = 2.0/3.0, .pci_div = 3}, - {.bus = 12400, .ram_mult = 2.0/3.0, .pci_div = 4}, - {.bus = 13330, .ram_mult = 2.0/3.0, .pci_div = 4}, - {.bus = 6670, .ram_mult = 1, .pci_div = 2}, - {.bus = 7500, .ram_mult = 1, .pci_div = 3}, - {.bus = 8330, .ram_mult = 1, .pci_div = 3}, - {.bus = 9500, .ram_mult = 1, .pci_div = 3}, - {.bus = 10000, .ram_mult = 1, .pci_div = 3}, - {.bus = 11200, .ram_mult = 1, .pci_div = 3}, - {.bus = 12400, .ram_mult = 1, .pci_div = 4}, - {.bus = 13330, .ram_mult = 1, .pci_div = 4}, - {0} - } + .max_reg = 5, + .regs = {0x82, 0xfe, 0x7f, 0xff, 0xff, 0xb7}, + .fs_regs = {{0, 4, 1, 0}, {0, 5, 2, 7}, {0, 6, 5, 6}, {0, 2, 5, 3}, {-1, -1, -1, -1}}, + .hw_select = {0, 3}, + .frequencies = (const ics9xxx_frequency_t[]) { + {.bus = 9000, .ram_mult = 1, .pci_div = 3}, + {.bus = 6670, .ram_mult = 1.5, .pci_div = 2}, + {.bus = 9500, .ram_mult = 2.0/3.0, .pci_div = 3}, + {.bus = 10000, .ram_mult = 2.0/3.0, .pci_div = 3}, + {.bus = 10000, .ram_mult = 0.75, .pci_div = 3}, + {.bus = 11200, .ram_mult = 2.0/3.0, .pci_div = 3}, + {.bus = 12400, .ram_mult = 2.0/3.0, .pci_div = 4}, + {.bus = 13330, .ram_mult = 2.0/3.0, .pci_div = 4}, + {.bus = 6670, .ram_mult = 1, .pci_div = 2}, + {.bus = 7500, .ram_mult = 1, .pci_div = 3}, + {.bus = 8330, .ram_mult = 1, .pci_div = 3}, + {.bus = 9500, .ram_mult = 1, .pci_div = 3}, + {.bus = 10000, .ram_mult = 1, .pci_div = 3}, + {.bus = 11200, .ram_mult = 1, .pci_div = 3}, + {.bus = 12400, .ram_mult = 1, .pci_div = 4}, + {.bus = 13330, .ram_mult = 1, .pci_div = 4}, + {0} + } ICS9xxx_MODEL_END() ICS9xxx_MODEL(ICS9248_95) - .max_reg = 5, - .regs = {0x82, 0xff, 0xff, 0xff, 0xd5, 0xff}, - .fs_regs = {{0, 4, -1, -1}, {0, 5, 4, 3}, {0, 6, -1, -1}, {0, 2, 4, 1}, {-1, -1, -1, -1}}, - .hw_select = {0, 3}, - .frequencies = (const ics9xxx_frequency_t[]) { - {.bus = 6667, .pci_div = 2}, - {.bus = 10000, .pci_div = 3}, - {.bus = 10030, .pci_div = 3}, - {.bus = 13333, .pci_div = 4}, - {.bus = 10500, .pci_div = 3}, - {.bus = 13337, .pci_div = 4}, - {.bus = 13700, .pci_div = 4}, - {.bus = 7500, .pci_div = 2}, - {.bus = 10000, .pci_div = 3}, - {.bus = 9500, .pci_div = 2}, - {.bus = 9700, .pci_div = 3}, - {.bus = 13333, .pci_div = 4}, - {.bus = 9000, .pci_div = 3}, - {.bus = 9622, .pci_div = 3}, - {.bus = 6681, .pci_div = 2}, - {.bus = 9150, .pci_div = 3}, - {0} - } + .max_reg = 5, + .regs = {0x82, 0xff, 0xff, 0xff, 0xd5, 0xff}, + .fs_regs = {{0, 4, -1, -1}, {0, 5, 4, 3}, {0, 6, -1, -1}, {0, 2, 4, 1}, {-1, -1, -1, -1}}, + .hw_select = {0, 3}, + .frequencies = (const ics9xxx_frequency_t[]) { + {.bus = 6667, .pci_div = 2}, + {.bus = 10000, .pci_div = 3}, + {.bus = 10030, .pci_div = 3}, + {.bus = 13333, .pci_div = 4}, + {.bus = 10500, .pci_div = 3}, + {.bus = 13337, .pci_div = 4}, + {.bus = 13700, .pci_div = 4}, + {.bus = 7500, .pci_div = 2}, + {.bus = 10000, .pci_div = 3}, + {.bus = 9500, .pci_div = 2}, + {.bus = 9700, .pci_div = 3}, + {.bus = 13333, .pci_div = 4}, + {.bus = 9000, .pci_div = 3}, + {.bus = 9622, .pci_div = 3}, + {.bus = 6681, .pci_div = 2}, + {.bus = 9150, .pci_div = 3}, + {0} + } ICS9xxx_MODEL_END() ICS9xxx_MODEL(ICS9248_98) - .max_reg = 6, - .regs = {0x00, 0x7f, 0xff, 0xbf, 0xf5, 0xff, 0x06}, - .fs_regs = {{0, 4, 3, 6}, {0, 5, 4, 3}, {0, 6, 1, 7}, {0, 7, 4, 1}, {0, 2, -1, -1}}, - .hw_select = {0, 3}, - .frequencies = (const ics9xxx_frequency_t[]) { - {.bus = 8000, .pci_div = 2}, - {.bus = 7500, .pci_div = 2}, - {.bus = 8331, .pci_div = 2}, - {.bus = 6682, .pci_div = 2}, - {.bus = 10300, .pci_div = 3}, - {.bus = 11201, .pci_div = 3}, - {.bus = 6801, .pci_div = 2}, - {.bus = 10023, .pci_div = 3}, - {.bus = 12000, .pci_div = 3}, - {.bus = 11499, .pci_div = 3}, - {.bus = 10999, .pci_div = 3}, - {.bus = 10500, .pci_div = 3}, - {.bus = 14000, .pci_div = 4}, - {.bus = 15000, .pci_div = 4}, - {.bus = 12400, .pci_div = 4}, - {.bus = 13299, .pci_div = 4}, - {.bus = 13500, .pci_div = 4}, - {.bus = 12999, .pci_div = 4}, - {.bus = 12600, .pci_div = 4}, - {.bus = 11800, .pci_div = 3}, - {.bus = 11598, .pci_div = 3}, - {.bus = 9500, .pci_div = 3}, - {.bus = 9000, .pci_div = 3}, - {.bus = 8501, .pci_div = 3}, - {.bus = 16600, .pci_div = 4}, - {.bus = 16001, .pci_div = 4}, - {.bus = 15499, .pci_div = 4}, - {.bus = 14795, .pci_div = 4}, - {.bus = 14598, .pci_div = 4}, - {.bus = 14398, .pci_div = 4}, - {.bus = 14199, .pci_div = 4}, - {.bus = 13801, .pci_div = 4}, - {0} - } + .max_reg = 6, + .regs = {0x00, 0x7f, 0xff, 0xbf, 0xf5, 0xff, 0x06}, + .fs_regs = {{0, 4, 3, 6}, {0, 5, 4, 3}, {0, 6, 1, 7}, {0, 7, 4, 1}, {0, 2, -1, -1}}, + .hw_select = {0, 3}, + .frequencies = (const ics9xxx_frequency_t[]) { + {.bus = 8000, .pci_div = 2}, + {.bus = 7500, .pci_div = 2}, + {.bus = 8331, .pci_div = 2}, + {.bus = 6682, .pci_div = 2}, + {.bus = 10300, .pci_div = 3}, + {.bus = 11201, .pci_div = 3}, + {.bus = 6801, .pci_div = 2}, + {.bus = 10023, .pci_div = 3}, + {.bus = 12000, .pci_div = 3}, + {.bus = 11499, .pci_div = 3}, + {.bus = 10999, .pci_div = 3}, + {.bus = 10500, .pci_div = 3}, + {.bus = 14000, .pci_div = 4}, + {.bus = 15000, .pci_div = 4}, + {.bus = 12400, .pci_div = 4}, + {.bus = 13299, .pci_div = 4}, + {.bus = 13500, .pci_div = 4}, + {.bus = 12999, .pci_div = 4}, + {.bus = 12600, .pci_div = 4}, + {.bus = 11800, .pci_div = 3}, + {.bus = 11598, .pci_div = 3}, + {.bus = 9500, .pci_div = 3}, + {.bus = 9000, .pci_div = 3}, + {.bus = 8501, .pci_div = 3}, + {.bus = 16600, .pci_div = 4}, + {.bus = 16001, .pci_div = 4}, + {.bus = 15499, .pci_div = 4}, + {.bus = 14795, .pci_div = 4}, + {.bus = 14598, .pci_div = 4}, + {.bus = 14398, .pci_div = 4}, + {.bus = 14199, .pci_div = 4}, + {.bus = 13801, .pci_div = 4}, + {0} + } ICS9xxx_MODEL_END() ICS9xxx_MODEL(ICS9248_101) - .max_reg = 5, - .regs = {0x82, 0xff, 0xff, 0xff, 0xf5, 0xff}, - .fs_regs = {{0, 4, -1, -1}, {0, 5, 4, 3}, {0, 6, -1, -1}, {0, 2, 4, 1}, {-1, -1, -1, -1}}, - .hw_select = {0, 3}, - .frequencies = (const ics9xxx_frequency_t[]) { - {.bus = 12400, .pci_div = 3}, - {.bus = 12000, .pci_div = 3}, - {.bus = 11499, .pci_div = 3}, - {.bus = 10999, .pci_div = 3}, - {.bus = 10500, .pci_div = 3}, - {.bus = 8331, .pci_div = 2}, - {.bus = 13700, .pci_div = 4}, - {.bus = 7500, .pci_div = 2}, - {.bus = 10000, .pci_div = 3}, - {.bus = 9500, .pci_div = 3}, - {.bus = 8331, .pci_div = 3}, - {.bus = 13333, .pci_div = 4}, - {.bus = 9000, .pci_div = 3}, - {.bus = 9622, .pci_div = 3}, - {.bus = 6682, .pci_div = 2}, - {.bus = 9150, .pci_div = 3}, - {0} - } + .max_reg = 5, + .regs = {0x82, 0xff, 0xff, 0xff, 0xf5, 0xff}, + .fs_regs = {{0, 4, -1, -1}, {0, 5, 4, 3}, {0, 6, -1, -1}, {0, 2, 4, 1}, {-1, -1, -1, -1}}, + .hw_select = {0, 3}, + .frequencies = (const ics9xxx_frequency_t[]) { + {.bus = 12400, .pci_div = 3}, + {.bus = 12000, .pci_div = 3}, + {.bus = 11499, .pci_div = 3}, + {.bus = 10999, .pci_div = 3}, + {.bus = 10500, .pci_div = 3}, + {.bus = 8331, .pci_div = 2}, + {.bus = 13700, .pci_div = 4}, + {.bus = 7500, .pci_div = 2}, + {.bus = 10000, .pci_div = 3}, + {.bus = 9500, .pci_div = 3}, + {.bus = 8331, .pci_div = 3}, + {.bus = 13333, .pci_div = 4}, + {.bus = 9000, .pci_div = 3}, + {.bus = 9622, .pci_div = 3}, + {.bus = 6682, .pci_div = 2}, + {.bus = 9150, .pci_div = 3}, + {0} + } ICS9xxx_MODEL_END() ICS9xxx_MODEL(ICS9248_103) - .max_reg = 5, - .regs = {0x82, 0xff, 0xff, 0xff, 0xf5, 0xff}, - .fs_regs = {{0, 4, -1, -1}, {0, 5, 4, 3}, {0, 6, -1, -1}, {0, 2, 4, 1}, {-1, -1, -1, -1}}, - .hw_select = {0, 3}, - .frequencies_ref = ICS9248_101 + .max_reg = 5, + .regs = {0x82, 0xff, 0xff, 0xff, 0xf5, 0xff}, + .fs_regs = {{0, 4, -1, -1}, {0, 5, 4, 3}, {0, 6, -1, -1}, {0, 2, 4, 1}, {-1, -1, -1, -1}}, + .hw_select = {0, 3}, + .frequencies_ref = ICS9248_101 ICS9xxx_MODEL_END() ICS9xxx_MODEL(ICS9248_107) - .max_reg = 6, - .regs = {0x02, 0xff, 0xff, 0xec, 0xde, 0xff, 0x06}, - .fs_regs = {{0, 4, 4, 5}, {0, 5, 3, 4}, {0, 6, 3, 0}, {0, 7, 3, 1}, {0, 2, 4, 0}}, - .hw_select = {0, 3}, - .frequencies = (const ics9xxx_frequency_t[]) { - {.bus = 10300, .pci_div = 3}, - {.bus = 10000, .pci_div = 3}, - {.bus = 10045, .pci_div = 3}, - {.bus = 10090, .pci_div = 3}, - {.bus = 10710, .pci_div = 2}, - {.bus = 10900, .pci_div = 3}, - {.bus = 11200, .pci_div = 3}, - {.bus = 11400, .pci_div = 4}, - {.bus = 11600, .pci_div = 4}, - {.bus = 11800, .pci_div = 4}, - {.bus = 13330, .pci_div = 3}, - {.bus = 12000, .pci_div = 4}, - {.bus = 12200, .pci_div = 4}, - {.bus = 12500, .pci_div = 4}, - {.bus = 5000, .pci_div = 2}, - {.bus = 6670, .pci_div = 4}, - {.bus = 13330, .pci_div = 3}, - {.bus = 13390, .pci_div = 3}, - {.bus = 13800, .pci_div = 4}, - {.bus = 14200, .pci_div = 4}, - {.bus = 14600, .pci_div = 4}, - {.bus = 15000, .pci_div = 4}, - {.bus = 15300, .pci_div = 4}, - {.bus = 15600, .pci_div = 4}, - {.bus = 15910, .pci_div = 3}, - {.bus = 16200, .pci_div = 4}, - {.bus = 16670, .pci_div = 4}, - {.bus = 16800, .pci_div = 4}, - {.bus = 17100, .pci_div = 4}, - {.bus = 17400, .pci_div = 4}, - {.bus = 17700, .pci_div = 4}, - {.bus = 18000, .pci_div = 4}, - {0} - } + .max_reg = 6, + .regs = {0x02, 0xff, 0xff, 0xec, 0xde, 0xff, 0x06}, + .fs_regs = {{0, 4, 4, 5}, {0, 5, 3, 4}, {0, 6, 3, 0}, {0, 7, 3, 1}, {0, 2, 4, 0}}, + .hw_select = {0, 3}, + .frequencies = (const ics9xxx_frequency_t[]) { + {.bus = 10300, .pci_div = 3}, + {.bus = 10000, .pci_div = 3}, + {.bus = 10045, .pci_div = 3}, + {.bus = 10090, .pci_div = 3}, + {.bus = 10710, .pci_div = 2}, + {.bus = 10900, .pci_div = 3}, + {.bus = 11200, .pci_div = 3}, + {.bus = 11400, .pci_div = 4}, + {.bus = 11600, .pci_div = 4}, + {.bus = 11800, .pci_div = 4}, + {.bus = 13330, .pci_div = 3}, + {.bus = 12000, .pci_div = 4}, + {.bus = 12200, .pci_div = 4}, + {.bus = 12500, .pci_div = 4}, + {.bus = 5000, .pci_div = 2}, + {.bus = 6670, .pci_div = 4}, + {.bus = 13330, .pci_div = 3}, + {.bus = 13390, .pci_div = 3}, + {.bus = 13800, .pci_div = 4}, + {.bus = 14200, .pci_div = 4}, + {.bus = 14600, .pci_div = 4}, + {.bus = 15000, .pci_div = 4}, + {.bus = 15300, .pci_div = 4}, + {.bus = 15600, .pci_div = 4}, + {.bus = 15910, .pci_div = 3}, + {.bus = 16200, .pci_div = 4}, + {.bus = 16670, .pci_div = 4}, + {.bus = 16800, .pci_div = 4}, + {.bus = 17100, .pci_div = 4}, + {.bus = 17400, .pci_div = 4}, + {.bus = 17700, .pci_div = 4}, + {.bus = 18000, .pci_div = 4}, + {0} + } ICS9xxx_MODEL_END() ICS9xxx_MODEL(ICS9248_112) - .max_reg = 6, - .regs = {0x02, 0x1f, 0xff, 0xff, 0xfb, 0xff, 0x06}, - .fs_regs = {{0, 4, 1, 6}, {0, 5, 4, 2}, {0, 6, 1, 5}, {0, 7, 1, 7}, {0, 2, -1, -1}}, - .hw_select = {0, 3}, - .frequencies = (const ics9xxx_frequency_t[]) { - {.bus = 6680, .ram_mult = 1.5, .pci_div = 2}, - {.bus = 6800, .ram_mult = 1.5, .pci_div = 2}, - {.bus = 10030, .ram_mult = 1, .pci_div = 3}, - {.bus = 10300, .ram_mult = 1, .pci_div = 3}, - {.bus = 13372, .ram_mult = 0.75, .pci_div = 4}, - {.bus = 14500, .ram_mult = 0.75, .pci_div = 4}, - {.bus = 13372, .ram_mult = 0.75, .pci_div = 4}, - {.bus = 13733, .ram_mult = 0.75, .pci_div = 4}, - {.bus = 14000, .ram_mult = 0.75, .pci_div = 4}, - {.bus = 14000, .ram_mult = 1, .pci_div = 2}, - {.bus = 11800, .ram_mult = 1, .pci_div = 3}, - {.bus = 12400, .ram_mult = 1, .pci_div = 3}, - {.bus = 13369, .ram_mult = 1, .pci_div = 2}, - {.bus = 13700, .ram_mult = 1, .pci_div = 2}, - {.bus = 15000, .ram_mult = 0.75, .pci_div = 4}, - {.bus = 7250, .ram_mult = 1.5, .pci_div = 2}, - {.bus = 7500, .ram_mult = 1.5, .pci_div = 2}, - {.bus = 8300, .ram_mult = 1, .pci_div = 6}, - {.bus = 11000, .ram_mult = 1, .pci_div = 2}, - {.bus = 12000, .ram_mult = 1, .pci_div = 3}, - {.bus = 12500, .ram_mult = 1, .pci_div = 2}, - {.bus = 6925, .ram_mult = 1.5, .pci_div = 1}, - {.bus = 7000, .ram_mult = 1.5, .pci_div = 2}, - {.bus = 7667, .ram_mult = 1.5, .pci_div = 2}, - {.bus = 14500, .ram_mult = 1, .pci_div = 3}, - {.bus = 6650, .ram_mult = 1.5, .pci_div = 2}, - {.bus = 15000, .ram_mult = 1, .pci_div = 3}, - {.bus = 9975, .ram_mult = 1, .pci_div = 3}, - {.bus = 15500, .ram_mult = 1, .pci_div = 2}, - {.bus = 16650, .ram_mult = 1, .pci_div = 3}, - {.bus = 15333, .ram_mult = 0.75, .pci_div = 4}, - {.bus = 13300, .ram_mult = 0.75, .pci_div = 4}, - {0} - } + .max_reg = 6, + .regs = {0x02, 0x1f, 0xff, 0xff, 0xfb, 0xff, 0x06}, + .fs_regs = {{0, 4, 1, 6}, {0, 5, 4, 2}, {0, 6, 1, 5}, {0, 7, 1, 7}, {0, 2, -1, -1}}, + .hw_select = {0, 3}, + .frequencies = (const ics9xxx_frequency_t[]) { + {.bus = 6680, .ram_mult = 1.5, .pci_div = 2}, + {.bus = 6800, .ram_mult = 1.5, .pci_div = 2}, + {.bus = 10030, .ram_mult = 1, .pci_div = 3}, + {.bus = 10300, .ram_mult = 1, .pci_div = 3}, + {.bus = 13372, .ram_mult = 0.75, .pci_div = 4}, + {.bus = 14500, .ram_mult = 0.75, .pci_div = 4}, + {.bus = 13372, .ram_mult = 0.75, .pci_div = 4}, + {.bus = 13733, .ram_mult = 0.75, .pci_div = 4}, + {.bus = 14000, .ram_mult = 0.75, .pci_div = 4}, + {.bus = 14000, .ram_mult = 1, .pci_div = 2}, + {.bus = 11800, .ram_mult = 1, .pci_div = 3}, + {.bus = 12400, .ram_mult = 1, .pci_div = 3}, + {.bus = 13369, .ram_mult = 1, .pci_div = 2}, + {.bus = 13700, .ram_mult = 1, .pci_div = 2}, + {.bus = 15000, .ram_mult = 0.75, .pci_div = 4}, + {.bus = 7250, .ram_mult = 1.5, .pci_div = 2}, + {.bus = 7500, .ram_mult = 1.5, .pci_div = 2}, + {.bus = 8300, .ram_mult = 1, .pci_div = 6}, + {.bus = 11000, .ram_mult = 1, .pci_div = 2}, + {.bus = 12000, .ram_mult = 1, .pci_div = 3}, + {.bus = 12500, .ram_mult = 1, .pci_div = 2}, + {.bus = 6925, .ram_mult = 1.5, .pci_div = 1}, + {.bus = 7000, .ram_mult = 1.5, .pci_div = 2}, + {.bus = 7667, .ram_mult = 1.5, .pci_div = 2}, + {.bus = 14500, .ram_mult = 1, .pci_div = 3}, + {.bus = 6650, .ram_mult = 1.5, .pci_div = 2}, + {.bus = 15000, .ram_mult = 1, .pci_div = 3}, + {.bus = 9975, .ram_mult = 1, .pci_div = 3}, + {.bus = 15500, .ram_mult = 1, .pci_div = 2}, + {.bus = 16650, .ram_mult = 1, .pci_div = 3}, + {.bus = 15333, .ram_mult = 0.75, .pci_div = 4}, + {.bus = 13300, .ram_mult = 0.75, .pci_div = 4}, + {0} + } ICS9xxx_MODEL_END() ICS9xxx_MODEL(ICS9248_138) - .max_reg = 6, - .regs = {0x02, 0x3f, 0x7f, 0x6f, 0xff, 0xff, 0x06}, - .fs_regs = {{0, 4, 2, 7}, {0, 5, 1, 6}, {0, 6, 1, 7}, {0, 7, 3, 4}, {0, 2, 3, 7}}, - .hw_select = {0, 3}, - .frequencies = (const ics9xxx_frequency_t[]) { - {.bus = 6667, .ram_mult = 1.5, .pci_div = 2}, - {.bus = 6687, .ram_mult = 1.5, .pci_div = 2}, - {.bus = 6867, .ram_mult = 1.5, .pci_div = 2}, - {.bus = 7134, .ram_mult = 1.5, .pci_div = 2}, - {.bus = 10000, .ram_mult = 1, .pci_div = 3}, - {.bus = 10030, .ram_mult = 1, .pci_div = 3}, - {.bus = 10300, .ram_mult = 1, .pci_div = 3}, - {.bus = 10700, .ram_mult = 1, .pci_div = 2}, - {.bus = 13333, .ram_mult = 1, .pci_div = 4}, - {.bus = 13372, .ram_mult = 1, .pci_div = 4}, - {.bus = 13733, .ram_mult = 1, .pci_div = 4}, - {.bus = 12000, .ram_mult = 1, .pci_div = 4}, - {.bus = 13333, .ram_mult = 0.75, .pci_div = 4}, - {.bus = 13372, .ram_mult = 0.75, .pci_div = 4}, - {.bus = 13733, .ram_mult = 0.75, .pci_div = 4}, - {.bus = 12000, .ram_mult = 0.75, .pci_div = 4}, - {.bus = 13600, .ram_mult = 1, .pci_div = 4}, - {.bus = 14000, .ram_mult = 1, .pci_div = 4}, - {.bus = 14266, .ram_mult = 1, .pci_div = 3}, - {.bus = 14533, .ram_mult = 1, .pci_div = 4}, - {.bus = 13600, .ram_mult = 0.75, .pci_div = 4}, - {.bus = 14000, .ram_mult = 0.75, .pci_div = 4}, - {.bus = 14266, .ram_mult = 0.75, .pci_div = 3}, - {.bus = 14533, .ram_mult = 0.75, .pci_div = 4}, - {.bus = 14666, .ram_mult = 1, .pci_div = 3}, - {.bus = 15333, .ram_mult = 1, .pci_div = 4}, - {.bus = 16000, .ram_mult = 1, .pci_div = 4}, - {.bus = 16667, .ram_mult = 1, .pci_div = 3}, - {.bus = 14666, .ram_mult = 0.75, .pci_div = 3}, - {.bus = 16000, .ram_mult = 0.75, .pci_div = 4}, - {.bus = 16667, .ram_mult = 0.75, .pci_div = 3}, - {.bus = 20000, .ram_mult = 1, .pci_div = 6}, - {0} - } + .max_reg = 6, + .regs = {0x02, 0x3f, 0x7f, 0x6f, 0xff, 0xff, 0x06}, + .fs_regs = {{0, 4, 2, 7}, {0, 5, 1, 6}, {0, 6, 1, 7}, {0, 7, 3, 4}, {0, 2, 3, 7}}, + .hw_select = {0, 3}, + .frequencies = (const ics9xxx_frequency_t[]) { + {.bus = 6667, .ram_mult = 1.5, .pci_div = 2}, + {.bus = 6687, .ram_mult = 1.5, .pci_div = 2}, + {.bus = 6867, .ram_mult = 1.5, .pci_div = 2}, + {.bus = 7134, .ram_mult = 1.5, .pci_div = 2}, + {.bus = 10000, .ram_mult = 1, .pci_div = 3}, + {.bus = 10030, .ram_mult = 1, .pci_div = 3}, + {.bus = 10300, .ram_mult = 1, .pci_div = 3}, + {.bus = 10700, .ram_mult = 1, .pci_div = 2}, + {.bus = 13333, .ram_mult = 1, .pci_div = 4}, + {.bus = 13372, .ram_mult = 1, .pci_div = 4}, + {.bus = 13733, .ram_mult = 1, .pci_div = 4}, + {.bus = 12000, .ram_mult = 1, .pci_div = 4}, + {.bus = 13333, .ram_mult = 0.75, .pci_div = 4}, + {.bus = 13372, .ram_mult = 0.75, .pci_div = 4}, + {.bus = 13733, .ram_mult = 0.75, .pci_div = 4}, + {.bus = 12000, .ram_mult = 0.75, .pci_div = 4}, + {.bus = 13600, .ram_mult = 1, .pci_div = 4}, + {.bus = 14000, .ram_mult = 1, .pci_div = 4}, + {.bus = 14266, .ram_mult = 1, .pci_div = 3}, + {.bus = 14533, .ram_mult = 1, .pci_div = 4}, + {.bus = 13600, .ram_mult = 0.75, .pci_div = 4}, + {.bus = 14000, .ram_mult = 0.75, .pci_div = 4}, + {.bus = 14266, .ram_mult = 0.75, .pci_div = 3}, + {.bus = 14533, .ram_mult = 0.75, .pci_div = 4}, + {.bus = 14666, .ram_mult = 1, .pci_div = 3}, + {.bus = 15333, .ram_mult = 1, .pci_div = 4}, + {.bus = 16000, .ram_mult = 1, .pci_div = 4}, + {.bus = 16667, .ram_mult = 1, .pci_div = 3}, + {.bus = 14666, .ram_mult = 0.75, .pci_div = 3}, + {.bus = 16000, .ram_mult = 0.75, .pci_div = 4}, + {.bus = 16667, .ram_mult = 0.75, .pci_div = 3}, + {.bus = 20000, .ram_mult = 1, .pci_div = 6}, + {0} + } ICS9xxx_MODEL_END() ICS9xxx_MODEL(ICS9248_141) - .max_reg = 6, - .regs = {0x02, 0x6b, 0x7f, 0xff, 0xff, 0xe7, 0x06}, - .fs_regs = {{0, 4, 2, 7}, {0, 5, 5, 3}, {0, 6, 1, 7}, {0, 7, 1, 4}, {0, 2, -1, -1}}, - .hw_select = {0, 3}, - .frequencies = (const ics9xxx_frequency_t[]) { - {.bus = 9000, .pci_div = 3}, - {.bus = 9500, .pci_div = 2}, - {.bus = 10100, .pci_div = 2}, - {.bus = 10200, .pci_div = 3}, - {.bus = 10090, .pci_div = 3}, - {.bus = 10300, .pci_div = 3}, - {.bus = 10500, .pci_div = 3}, - {.bus = 10000, .pci_div = 3}, - {.bus = 10700, .pci_div = 2}, - {.bus = 10900, .pci_div = 3}, - {.bus = 11000, .pci_div = 2}, - {.bus = 11100, .pci_div = 3}, - {.bus = 11300, .pci_div = 2}, - {.bus = 11500, .pci_div = 3}, - {.bus = 11700, .pci_div = 3}, - {.bus = 13330, .pci_div = 3}, - {.bus = 12000, .pci_div = 3}, - {.bus = 12500, .pci_div = 4}, - {.bus = 13000, .pci_div = 4}, - {.bus = 13372, .pci_div = 4}, - {.bus = 13500, .pci_div = 4}, - {.bus = 13700, .pci_div = 4}, - {.bus = 13900, .pci_div = 4}, - {.bus = 10000, .pci_div = 3}, - {.bus = 14000, .pci_div = 4}, - {.bus = 14300, .pci_div = 4}, - {.bus = 14500, .pci_div = 4}, - {.bus = 14800, .pci_div = 4}, - {.bus = 15000, .pci_div = 4}, - {.bus = 15500, .pci_div = 4}, - {.bus = 16666, .pci_div = 3}, - {.bus = 13333, .pci_div = 4}, - {0} - } + .max_reg = 6, + .regs = {0x02, 0x6b, 0x7f, 0xff, 0xff, 0xe7, 0x06}, + .fs_regs = {{0, 4, 2, 7}, {0, 5, 5, 3}, {0, 6, 1, 7}, {0, 7, 1, 4}, {0, 2, -1, -1}}, + .hw_select = {0, 3}, + .frequencies = (const ics9xxx_frequency_t[]) { + {.bus = 9000, .pci_div = 3}, + {.bus = 9500, .pci_div = 2}, + {.bus = 10100, .pci_div = 2}, + {.bus = 10200, .pci_div = 3}, + {.bus = 10090, .pci_div = 3}, + {.bus = 10300, .pci_div = 3}, + {.bus = 10500, .pci_div = 3}, + {.bus = 10000, .pci_div = 3}, + {.bus = 10700, .pci_div = 2}, + {.bus = 10900, .pci_div = 3}, + {.bus = 11000, .pci_div = 2}, + {.bus = 11100, .pci_div = 3}, + {.bus = 11300, .pci_div = 2}, + {.bus = 11500, .pci_div = 3}, + {.bus = 11700, .pci_div = 3}, + {.bus = 13330, .pci_div = 3}, + {.bus = 12000, .pci_div = 3}, + {.bus = 12500, .pci_div = 4}, + {.bus = 13000, .pci_div = 4}, + {.bus = 13372, .pci_div = 4}, + {.bus = 13500, .pci_div = 4}, + {.bus = 13700, .pci_div = 4}, + {.bus = 13900, .pci_div = 4}, + {.bus = 10000, .pci_div = 3}, + {.bus = 14000, .pci_div = 4}, + {.bus = 14300, .pci_div = 4}, + {.bus = 14500, .pci_div = 4}, + {.bus = 14800, .pci_div = 4}, + {.bus = 15000, .pci_div = 4}, + {.bus = 15500, .pci_div = 4}, + {.bus = 16666, .pci_div = 3}, + {.bus = 13333, .pci_div = 4}, + {0} + } ICS9xxx_MODEL_END() ICS9xxx_MODEL(ICS9248_143) - .max_reg = 5, - .regs = {0x82, 0xff, 0xff, 0xff, 0xd5, 0xff}, - .fs_regs = {{0, 4, -1, -1}, {0, 5, 4, 3}, {0, 6, -1, -1}, {0, 2, 4, 1}, {-1, -1, -1, -1}}, - .frequencies = (const ics9xxx_frequency_t[]) { - {.bus = 6667, .pci_div = 2}, - {.bus = 10000, .pci_div = 3}, - {.bus = 10030, .pci_div = 3}, - {.bus = 13333, .pci_div = 4}, - {.bus = 10500, .pci_div = 3}, - {.bus = 13337, .pci_div = 4}, - {.bus = 13700, .pci_div = 4}, - {.bus = 7500, .pci_div = 2}, - {.bus = 10000, .pci_div = 3}, - {.bus = 9500, .pci_div = 2}, - {.bus = 9700, .pci_div = 3}, - {.bus = 13333, .pci_div = 4}, - {.bus = 9000, .pci_div = 3}, - {.bus = 9622, .pci_div = 3}, - {.bus = 6681, .pci_div = 2}, - {.bus = 9150, .pci_div = 3}, - {0} - } + .max_reg = 5, + .regs = {0x82, 0xff, 0xff, 0xff, 0xd5, 0xff}, + .fs_regs = {{0, 4, -1, -1}, {0, 5, 4, 3}, {0, 6, -1, -1}, {0, 2, 4, 1}, {-1, -1, -1, -1}}, + .frequencies = (const ics9xxx_frequency_t[]) { + {.bus = 6667, .pci_div = 2}, + {.bus = 10000, .pci_div = 3}, + {.bus = 10030, .pci_div = 3}, + {.bus = 13333, .pci_div = 4}, + {.bus = 10500, .pci_div = 3}, + {.bus = 13337, .pci_div = 4}, + {.bus = 13700, .pci_div = 4}, + {.bus = 7500, .pci_div = 2}, + {.bus = 10000, .pci_div = 3}, + {.bus = 9500, .pci_div = 2}, + {.bus = 9700, .pci_div = 3}, + {.bus = 13333, .pci_div = 4}, + {.bus = 9000, .pci_div = 3}, + {.bus = 9622, .pci_div = 3}, + {.bus = 6681, .pci_div = 2}, + {.bus = 9150, .pci_div = 3}, + {0} + } ICS9xxx_MODEL_END() ICS9xxx_MODEL(ICS9248_151) - .max_reg = 6, - .regs = {0x80, 0x4f, 0xff, 0x3f, 0xff, 0xff, 0x06}, - .fs_regs = {{0, 4, -1, -1}, {0, 5, -1, -1}, {0, 6, 3, 7}, {0, 1, 1, 4}, {0, 2, 1, 5}}, - .hw_select = {0, 3}, - .frequencies = (const ics9xxx_frequency_t[]) { - {.bus = 20000, .pci_div = 5, .agp_div = 2.5}, - {.bus = 19000, .pci_div = 5, .agp_div = 2.5}, - {.bus = 18000, .pci_div = 5, .agp_div = 2.5}, - {.bus = 17000, .pci_div = 5, .agp_div = 2.5}, - {.bus = 16600, .pci_div = 5, .agp_div = 2.5}, - {.bus = 16000, .pci_div = 5, .agp_div = 2.5}, - {.bus = 15000, .pci_div = 4, .agp_div = 2}, - {.bus = 14500, .pci_div = 4, .agp_div = 2}, - {.bus = 14000, .pci_div = 4, .agp_div = 2}, - {.bus = 13600, .pci_div = 4, .agp_div = 2}, - {.bus = 13000, .pci_div = 4, .agp_div = 2}, - {.bus = 12400, .pci_div = 4, .agp_div = 2}, - {.bus = 6667, .pci_div = 1, .agp_div = 1}, - {.bus = 10000, .pci_div = 3, .agp_div = 1.5}, - {.bus = 11800, .pci_div = 3, .agp_div = 1.5}, - {.bus = 13333, .pci_div = 3, .agp_div = 2}, - {.bus = 6680, .pci_div = 2, .agp_div = 1}, - {.bus = 10020, .pci_div = 3, .agp_div = 1.5}, - {.bus = 11500, .pci_div = 3, .agp_div = 1.5}, - {.bus = 13340, .pci_div = 4, .agp_div = 2}, - {.bus = 6680, .pci_div = 2, .agp_div = 1}, - {.bus = 10020, .pci_div = 3, .agp_div = 1.5}, - {.bus = 11000, .pci_div = 2, .agp_div = 1.5}, - {.bus = 13340, .pci_div = 4, .agp_div = 2}, - {.bus = 10500, .pci_div = 3, .agp_div = 1.5}, - {.bus = 9000, .pci_div = 3, .agp_div = 1.5}, - {.bus = 8500, .pci_div = 3, .agp_div = 1.5}, - {.bus = 7800, .pci_div = 2, .agp_div = 1}, - {.bus = 6667, .pci_div = 1, .agp_div = 1}, - {.bus = 10000, .pci_div = 3, .agp_div = 1.5}, - {.bus = 7500, .pci_div = 2, .agp_div = 1}, - {.bus = 13333, .pci_div = 3, .agp_div = 2}, - {0} - } + .max_reg = 6, + .regs = {0x80, 0x4f, 0xff, 0x3f, 0xff, 0xff, 0x06}, + .fs_regs = {{0, 4, -1, -1}, {0, 5, -1, -1}, {0, 6, 3, 7}, {0, 1, 1, 4}, {0, 2, 1, 5}}, + .hw_select = {0, 3}, + .frequencies = (const ics9xxx_frequency_t[]) { + {.bus = 20000, .pci_div = 5, .agp_div = 2.5}, + {.bus = 19000, .pci_div = 5, .agp_div = 2.5}, + {.bus = 18000, .pci_div = 5, .agp_div = 2.5}, + {.bus = 17000, .pci_div = 5, .agp_div = 2.5}, + {.bus = 16600, .pci_div = 5, .agp_div = 2.5}, + {.bus = 16000, .pci_div = 5, .agp_div = 2.5}, + {.bus = 15000, .pci_div = 4, .agp_div = 2}, + {.bus = 14500, .pci_div = 4, .agp_div = 2}, + {.bus = 14000, .pci_div = 4, .agp_div = 2}, + {.bus = 13600, .pci_div = 4, .agp_div = 2}, + {.bus = 13000, .pci_div = 4, .agp_div = 2}, + {.bus = 12400, .pci_div = 4, .agp_div = 2}, + {.bus = 6667, .pci_div = 1, .agp_div = 1}, + {.bus = 10000, .pci_div = 3, .agp_div = 1.5}, + {.bus = 11800, .pci_div = 3, .agp_div = 1.5}, + {.bus = 13333, .pci_div = 3, .agp_div = 2}, + {.bus = 6680, .pci_div = 2, .agp_div = 1}, + {.bus = 10020, .pci_div = 3, .agp_div = 1.5}, + {.bus = 11500, .pci_div = 3, .agp_div = 1.5}, + {.bus = 13340, .pci_div = 4, .agp_div = 2}, + {.bus = 6680, .pci_div = 2, .agp_div = 1}, + {.bus = 10020, .pci_div = 3, .agp_div = 1.5}, + {.bus = 11000, .pci_div = 2, .agp_div = 1.5}, + {.bus = 13340, .pci_div = 4, .agp_div = 2}, + {.bus = 10500, .pci_div = 3, .agp_div = 1.5}, + {.bus = 9000, .pci_div = 3, .agp_div = 1.5}, + {.bus = 8500, .pci_div = 3, .agp_div = 1.5}, + {.bus = 7800, .pci_div = 2, .agp_div = 1}, + {.bus = 6667, .pci_div = 1, .agp_div = 1}, + {.bus = 10000, .pci_div = 3, .agp_div = 1.5}, + {.bus = 7500, .pci_div = 2, .agp_div = 1}, + {.bus = 13333, .pci_div = 3, .agp_div = 2}, + {0} + } ICS9xxx_MODEL_END() ICS9xxx_MODEL(ICS9248_192) - .max_reg = 6, - .regs = {0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff}, - .fs_regs = {{0, 4, -1, -1}, {0, 5, 4, 3}, {0, 6, -1, -1}, {0, 7, -1, -1}, {0, 2, -1, -1}}, - .hw_select = {0, 3}, - .frequencies = (const ics9xxx_frequency_t[]) { - {.bus = 6000, .pci_div = 2}, - {.bus = 6000, .pci_div = 2}, - {.bus = 6000, .pci_div = 2}, - {.bus = 6000, .pci_div = 2}, - {.bus = 6659, .pci_div = 2}, - {.bus = 6659, .pci_div = 2}, - {.bus = 6659, .pci_div = 2}, - {.bus = 6659, .pci_div = 2}, - {.bus = 6731, .pci_div = 2}, - {.bus = 6864, .pci_div = 2}, - {.bus = 6995, .pci_div = 2}, - {.bus = 7259, .pci_div = 2}, - {.bus = 6150, .pci_div = 2}, - {.bus = 6300, .pci_div = 2}, - {.bus = 6400, .pci_div = 2}, - {.bus = 6500, .pci_div = 2}, - {.bus = 6000, .pci_div = 2}, - {.bus = 6659, .pci_div = 2}, - {.bus = 5000, .pci_div = 2}, - {.bus = 4800, .pci_div = 2}, - {.bus = 5880, .pci_div = 2}, - {.bus = 5760, .pci_div = 2}, - {.bus = 5640, .pci_div = 2}, - {.bus = 5400, .pci_div = 2}, - {.bus = 6000, .pci_div = 2}, - {.bus = 6000, .pci_div = 2}, - {.bus = 6000, .pci_div = 2}, - {.bus = 6000, .pci_div = 2}, - {.bus = 6659, .pci_div = 2}, - {.bus = 6659, .pci_div = 2}, - {.bus = 6659, .pci_div = 2}, - {.bus = 6659, .pci_div = 2}, - {0} - } + .max_reg = 6, + .regs = {0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff}, + .fs_regs = {{0, 4, -1, -1}, {0, 5, 4, 3}, {0, 6, -1, -1}, {0, 7, -1, -1}, {0, 2, -1, -1}}, + .hw_select = {0, 3}, + .frequencies = (const ics9xxx_frequency_t[]) { + {.bus = 6000, .pci_div = 2}, + {.bus = 6000, .pci_div = 2}, + {.bus = 6000, .pci_div = 2}, + {.bus = 6000, .pci_div = 2}, + {.bus = 6659, .pci_div = 2}, + {.bus = 6659, .pci_div = 2}, + {.bus = 6659, .pci_div = 2}, + {.bus = 6659, .pci_div = 2}, + {.bus = 6731, .pci_div = 2}, + {.bus = 6864, .pci_div = 2}, + {.bus = 6995, .pci_div = 2}, + {.bus = 7259, .pci_div = 2}, + {.bus = 6150, .pci_div = 2}, + {.bus = 6300, .pci_div = 2}, + {.bus = 6400, .pci_div = 2}, + {.bus = 6500, .pci_div = 2}, + {.bus = 6000, .pci_div = 2}, + {.bus = 6659, .pci_div = 2}, + {.bus = 5000, .pci_div = 2}, + {.bus = 4800, .pci_div = 2}, + {.bus = 5880, .pci_div = 2}, + {.bus = 5760, .pci_div = 2}, + {.bus = 5640, .pci_div = 2}, + {.bus = 5400, .pci_div = 2}, + {.bus = 6000, .pci_div = 2}, + {.bus = 6000, .pci_div = 2}, + {.bus = 6000, .pci_div = 2}, + {.bus = 6000, .pci_div = 2}, + {.bus = 6659, .pci_div = 2}, + {.bus = 6659, .pci_div = 2}, + {.bus = 6659, .pci_div = 2}, + {.bus = 6659, .pci_div = 2}, + {0} + } ICS9xxx_MODEL_END() #endif ICS9xxx_MODEL(ICS9250_08) - .max_reg = 5, - .regs = {0x00, 0xff, 0xff, 0xff, 0x6d, 0xbf}, - .fs_regs = {{0, 4, 4, 7}, {0, 5, 4, 4}, {0, 6, 5, 6}, {0, 2, 4, 1}, {-1, -1, -1, -1}}, - .hw_select = {0, 3}, - .frequencies = (const ics9xxx_frequency_t[]) { - {.bus = 12400, .pci_div = 3}, - {.bus = 7500, .pci_div = 2}, - {.bus = 8333, .pci_div = 2}, - {.bus = 6680, .pci_div = 2}, - {.bus = 10300, .pci_div = 3}, - {.bus = 11200, .pci_div = 3}, - {.bus = 13300, .pci_div = 3}, - {.bus = 10030, .pci_div = 3}, - {.bus = 12000, .pci_div = 3}, - {.bus = 11500, .pci_div = 3}, - {.bus = 11000, .pci_div = 3}, - {.bus = 10500, .pci_div = 3}, - {.bus = 14000, .pci_div = 4}, - {.bus = 15000, .pci_div = 4}, - {.bus = 12400, .pci_div = 4}, - {.bus = 13300, .pci_div = 4}, - {0} - } + .max_reg = 5, + .regs = {0x00, 0xff, 0xff, 0xff, 0x6d, 0xbf}, + .fs_regs = {{0, 4, 4, 7}, {0, 5, 4, 4}, {0, 6, 5, 6}, {0, 2, 4, 1}, {-1, -1, -1, -1}}, + .hw_select = {0, 3}, + .frequencies = (const ics9xxx_frequency_t[]) { + {.bus = 12400, .pci_div = 3}, + {.bus = 7500, .pci_div = 2}, + {.bus = 8333, .pci_div = 2}, + {.bus = 6680, .pci_div = 2}, + {.bus = 10300, .pci_div = 3}, + {.bus = 11200, .pci_div = 3}, + {.bus = 13300, .pci_div = 3}, + {.bus = 10030, .pci_div = 3}, + {.bus = 12000, .pci_div = 3}, + {.bus = 11500, .pci_div = 3}, + {.bus = 11000, .pci_div = 3}, + {.bus = 10500, .pci_div = 3}, + {.bus = 14000, .pci_div = 4}, + {.bus = 15000, .pci_div = 4}, + {.bus = 12400, .pci_div = 4}, + {.bus = 13300, .pci_div = 4}, + {0} + } ICS9xxx_MODEL_END() #ifdef ENABLE_ICS9xxx_DETECT ICS9xxx_MODEL(ICS9250_10) - .max_reg = 5, - .regs = {0x1f, 0xff, 0xfe, 0x00, 0x00, 0x06}, - .fs_regs = {{5, 0, -1, -1}, {5, 3, -1, -1}, {5, 4, -1, -1}, {-1, -1, -1, -1}, {-1, -1, -1, -1}}, - .hw_select = {-1, -1}, - .frequencies = (const ics9xxx_frequency_t[]) { - {.bus = 6667, .ram_mult = 1.5, .pci_div = 2}, - {.bus = 7067, .ram_mult = 1.5, .pci_div = 2}, - {.bus = 7466, .ram_mult = 1.5, .pci_div = 2}, - {.bus = 8266, .ram_mult = 1.5, .pci_div = 2}, - {.bus = 6350, .ram_mult = 1.5, .pci_div = 2}, - {.bus = 6867, .ram_mult = 1.5, .pci_div = 2}, - {.bus = 7267, .ram_mult = 1.5, .pci_div = 2}, - {.bus = 8866, .ram_mult = 1.5, .pci_div = 2}, - {.bus = 10000, .ram_mult = 1, .pci_div = 3}, - {.bus = 10600, .ram_mult = 1, .pci_div = 3}, - {.bus = 11200, .ram_mult = 1, .pci_div = 3}, - {.bus = 12400, .ram_mult = 1, .pci_div = 3}, - {.bus = 9525, .ram_mult = 1, .pci_div = 3}, - {.bus = 10300, .ram_mult = 1, .pci_div = 3}, - {.bus = 10900, .ram_mult = 1, .pci_div = 3}, - {.bus = 13300, .ram_mult = 1, .pci_div = 3}, - {0} - } + .max_reg = 5, + .regs = {0x1f, 0xff, 0xfe, 0x00, 0x00, 0x06}, + .fs_regs = {{5, 0, -1, -1}, {5, 3, -1, -1}, {5, 4, -1, -1}, {-1, -1, -1, -1}, {-1, -1, -1, -1}}, + .hw_select = {-1, -1}, + .frequencies = (const ics9xxx_frequency_t[]) { + {.bus = 6667, .ram_mult = 1.5, .pci_div = 2}, + {.bus = 7067, .ram_mult = 1.5, .pci_div = 2}, + {.bus = 7466, .ram_mult = 1.5, .pci_div = 2}, + {.bus = 8266, .ram_mult = 1.5, .pci_div = 2}, + {.bus = 6350, .ram_mult = 1.5, .pci_div = 2}, + {.bus = 6867, .ram_mult = 1.5, .pci_div = 2}, + {.bus = 7267, .ram_mult = 1.5, .pci_div = 2}, + {.bus = 8866, .ram_mult = 1.5, .pci_div = 2}, + {.bus = 10000, .ram_mult = 1, .pci_div = 3}, + {.bus = 10600, .ram_mult = 1, .pci_div = 3}, + {.bus = 11200, .ram_mult = 1, .pci_div = 3}, + {.bus = 12400, .ram_mult = 1, .pci_div = 3}, + {.bus = 9525, .ram_mult = 1, .pci_div = 3}, + {.bus = 10300, .ram_mult = 1, .pci_div = 3}, + {.bus = 10900, .ram_mult = 1, .pci_div = 3}, + {.bus = 13300, .ram_mult = 1, .pci_div = 3}, + {0} + } ICS9xxx_MODEL_END() ICS9xxx_MODEL(ICS9250_13) - .max_reg = 5, - .regs = {0x82, 0xcf, 0x7f, 0xff, 0xff, 0xf7}, - .fs_regs = {{0, 4, 1, 4}, {0, 5, 5, 7}, {0, 6, 1, 5}, {0, 2, 2, 7}, {-1, -1, -1, -1}}, - .hw_select = {0, 3}, - .frequencies = (const ics9xxx_frequency_t[]) { - {.bus = 9000, .ram_mult = 1, .pci_div = 2}, - {.bus = 8901, .ram_mult = 1, .pci_div = 2}, - {.bus = 8800, .ram_mult = 1, .pci_div = 2}, - {.bus = 8699, .ram_mult = 1, .pci_div = 2}, - {.bus = 8591, .ram_mult = 1, .pci_div = 2}, - {.bus = 8501, .ram_mult = 1, .pci_div = 2}, - {.bus = 8400, .ram_mult = 1, .pci_div = 2}, - {.bus = 8200, .ram_mult = 1, .pci_div = 2}, - {.bus = 8101, .ram_mult = 1, .pci_div = 2}, - {.bus = 8000, .ram_mult = 1, .pci_div = 2}, - {.bus = 8331, .ram_mult = 1, .pci_div = 2}, - {.bus = 6849, .ram_mult = 1, .pci_div = 2}, - {.bus = 7800, .ram_mult = 1, .pci_div = 2}, - {.bus = 7500, .ram_mult = 1, .pci_div = 2}, - {.bus = 7199, .ram_mult = 1, .pci_div = 2}, - {.bus = 6682, .ram_mult = 1, .pci_div = 2}, - {0} - } + .max_reg = 5, + .regs = {0x82, 0xcf, 0x7f, 0xff, 0xff, 0xf7}, + .fs_regs = {{0, 4, 1, 4}, {0, 5, 5, 7}, {0, 6, 1, 5}, {0, 2, 2, 7}, {-1, -1, -1, -1}}, + .hw_select = {0, 3}, + .frequencies = (const ics9xxx_frequency_t[]) { + {.bus = 9000, .ram_mult = 1, .pci_div = 2}, + {.bus = 8901, .ram_mult = 1, .pci_div = 2}, + {.bus = 8800, .ram_mult = 1, .pci_div = 2}, + {.bus = 8699, .ram_mult = 1, .pci_div = 2}, + {.bus = 8591, .ram_mult = 1, .pci_div = 2}, + {.bus = 8501, .ram_mult = 1, .pci_div = 2}, + {.bus = 8400, .ram_mult = 1, .pci_div = 2}, + {.bus = 8200, .ram_mult = 1, .pci_div = 2}, + {.bus = 8101, .ram_mult = 1, .pci_div = 2}, + {.bus = 8000, .ram_mult = 1, .pci_div = 2}, + {.bus = 8331, .ram_mult = 1, .pci_div = 2}, + {.bus = 6849, .ram_mult = 1, .pci_div = 2}, + {.bus = 7800, .ram_mult = 1, .pci_div = 2}, + {.bus = 7500, .ram_mult = 1, .pci_div = 2}, + {.bus = 7199, .ram_mult = 1, .pci_div = 2}, + {.bus = 6682, .ram_mult = 1, .pci_div = 2}, + {0} + } ICS9xxx_MODEL_END() ICS9xxx_MODEL(ICS9250_14) - .max_reg = 5, - .regs = {0x02, 0x1f, 0xff, 0xff, 0xeb, 0xff}, - .fs_regs = {{0, 4, 1, 6}, {0, 5, 4, 2}, {0, 6, 1, 5}, {0, 7, 1, 7}, {0, 2, 4, 4}}, - .hw_select = {0, 3}, - .frequencies = (const ics9xxx_frequency_t[]) { - {.bus = 6781, .ram_mult = 1.5, .pci_div = 2}, - {.bus = 7000, .ram_mult = 1.5, .pci_div = 2}, - {.bus = 7201, .ram_mult = 1.5, .pci_div = 2}, - {.bus = 6667, .ram_mult = 1.5, .pci_div = 2}, - {.bus = 7301, .ram_mult = 1.5, .pci_div = 2}, - {.bus = 7500, .ram_mult = 1.5, .pci_div = 2}, - {.bus = 7700, .ram_mult = 1.5, .pci_div = 2}, - {.bus = 7801, .ram_mult = 1.5, .pci_div = 2}, - {.bus = 8000, .ram_mult = 1.5, .pci_div = 2}, - {.bus = 8300, .ram_mult = 1.5, .pci_div = 2}, - {.bus = 8449, .ram_mult = 1.5, .pci_div = 2}, - {.bus = 10000, .ram_mult = 1.5, .pci_div = 2}, - {.bus = 8608, .ram_mult = 1.5, .pci_div = 2}, - {.bus = 8800, .ram_mult = 1.5, .pci_div = 2}, - {.bus = 9000, .ram_mult = 1.5, .pci_div = 2}, - {.bus = 9500, .ram_mult = 1.5, .pci_div = 2}, - {.bus = 4990, .ram_mult = 1, .pci_div = 3}, - {.bus = 10000, .ram_mult = 1, .pci_div = 3}, - {.bus = 7485, .ram_mult = 1, .pci_div = 3}, - {.bus = 6658, .ram_mult = 1, .pci_div = 3}, - {.bus = 8284, .ram_mult = 1, .pci_div = 3}, - {.bus = 8981, .ram_mult = 1, .pci_div = 3}, - {.bus = 9480, .ram_mult = 1, .pci_div = 3}, - {.bus = 10050, .ram_mult = 1, .pci_div = 3}, - {.bus = 10478, .ram_mult = 1, .pci_div = 3}, - {.bus = 11177, .ram_mult = 1, .pci_div = 3}, - {.bus = 11477, .ram_mult = 1, .pci_div = 3}, - {.bus = 10000, .ram_mult = 1, .pci_div = 3}, - {.bus = 12375, .ram_mult = 1, .pci_div = 3}, - {.bus = 13274, .ram_mult = 1, .pci_div = 3}, - {.bus = 13975, .ram_mult = 1, .pci_div = 3}, - {.bus = 14969, .ram_mult = 1, .pci_div = 3}, - {0} - } + .max_reg = 5, + .regs = {0x02, 0x1f, 0xff, 0xff, 0xeb, 0xff}, + .fs_regs = {{0, 4, 1, 6}, {0, 5, 4, 2}, {0, 6, 1, 5}, {0, 7, 1, 7}, {0, 2, 4, 4}}, + .hw_select = {0, 3}, + .frequencies = (const ics9xxx_frequency_t[]) { + {.bus = 6781, .ram_mult = 1.5, .pci_div = 2}, + {.bus = 7000, .ram_mult = 1.5, .pci_div = 2}, + {.bus = 7201, .ram_mult = 1.5, .pci_div = 2}, + {.bus = 6667, .ram_mult = 1.5, .pci_div = 2}, + {.bus = 7301, .ram_mult = 1.5, .pci_div = 2}, + {.bus = 7500, .ram_mult = 1.5, .pci_div = 2}, + {.bus = 7700, .ram_mult = 1.5, .pci_div = 2}, + {.bus = 7801, .ram_mult = 1.5, .pci_div = 2}, + {.bus = 8000, .ram_mult = 1.5, .pci_div = 2}, + {.bus = 8300, .ram_mult = 1.5, .pci_div = 2}, + {.bus = 8449, .ram_mult = 1.5, .pci_div = 2}, + {.bus = 10000, .ram_mult = 1.5, .pci_div = 2}, + {.bus = 8608, .ram_mult = 1.5, .pci_div = 2}, + {.bus = 8800, .ram_mult = 1.5, .pci_div = 2}, + {.bus = 9000, .ram_mult = 1.5, .pci_div = 2}, + {.bus = 9500, .ram_mult = 1.5, .pci_div = 2}, + {.bus = 4990, .ram_mult = 1, .pci_div = 3}, + {.bus = 10000, .ram_mult = 1, .pci_div = 3}, + {.bus = 7485, .ram_mult = 1, .pci_div = 3}, + {.bus = 6658, .ram_mult = 1, .pci_div = 3}, + {.bus = 8284, .ram_mult = 1, .pci_div = 3}, + {.bus = 8981, .ram_mult = 1, .pci_div = 3}, + {.bus = 9480, .ram_mult = 1, .pci_div = 3}, + {.bus = 10050, .ram_mult = 1, .pci_div = 3}, + {.bus = 10478, .ram_mult = 1, .pci_div = 3}, + {.bus = 11177, .ram_mult = 1, .pci_div = 3}, + {.bus = 11477, .ram_mult = 1, .pci_div = 3}, + {.bus = 10000, .ram_mult = 1, .pci_div = 3}, + {.bus = 12375, .ram_mult = 1, .pci_div = 3}, + {.bus = 13274, .ram_mult = 1, .pci_div = 3}, + {.bus = 13975, .ram_mult = 1, .pci_div = 3}, + {.bus = 14969, .ram_mult = 1, .pci_div = 3}, + {0} + } ICS9xxx_MODEL_END() ICS9xxx_MODEL(ICS9250_16) - .max_reg = 5, - .regs = {0x1f, 0xff, 0xff, 0x00, 0x00, 0x06}, - .fs_regs = {{5, 0, -1, -1}, {5, 3, -1, -1}, {-1, -1, -1, -1}, {-1, -1, -1, -1}, {-1, -1, -1, -1}}, - .hw_select = {-1, -1}, - .frequencies = (const ics9xxx_frequency_t[]) { - {.bus = 6667, .ram_mult = 1.5, .pci_div = 2}, - {.bus = 7000, .ram_mult = 1.5, .pci_div = 2}, - {.bus = 7267, .ram_mult = 1.5, .pci_div = 2}, - {.bus = 7467, .ram_mult = 1.5, .pci_div = 2}, - {.bus = 10000, .ram_mult = 1, .pci_div = 3}, - {.bus = 10500, .ram_mult = 1, .pci_div = 3}, - {.bus = 10900, .ram_mult = 1, .pci_div = 3}, - {.bus = 11201, .ram_mult = 1, .pci_div = 3}, - {.bus = 13334, .ram_mult = 1, .pci_div = 3}, - {.bus = 14000, .ram_mult = 0.75, .pci_div = 4}, - {.bus = 12000, .ram_mult = 0.75, .pci_div = 4}, - {.bus = 12400, .ram_mult = 1, .pci_div = 3}, - {.bus = 13334, .ram_mult = 0.75, .pci_div = 4}, - {.bus = 15000, .ram_mult = 1, .pci_div = 4}, - {.bus = 14000, .ram_mult = 1, .pci_div = 4}, - {.bus = 13299, .ram_mult = 1, .pci_div = 4}, - {0} - } + .max_reg = 5, + .regs = {0x1f, 0xff, 0xff, 0x00, 0x00, 0x06}, + .fs_regs = {{5, 0, -1, -1}, {5, 3, -1, -1}, {-1, -1, -1, -1}, {-1, -1, -1, -1}, {-1, -1, -1, -1}}, + .hw_select = {-1, -1}, + .frequencies = (const ics9xxx_frequency_t[]) { + {.bus = 6667, .ram_mult = 1.5, .pci_div = 2}, + {.bus = 7000, .ram_mult = 1.5, .pci_div = 2}, + {.bus = 7267, .ram_mult = 1.5, .pci_div = 2}, + {.bus = 7467, .ram_mult = 1.5, .pci_div = 2}, + {.bus = 10000, .ram_mult = 1, .pci_div = 3}, + {.bus = 10500, .ram_mult = 1, .pci_div = 3}, + {.bus = 10900, .ram_mult = 1, .pci_div = 3}, + {.bus = 11201, .ram_mult = 1, .pci_div = 3}, + {.bus = 13334, .ram_mult = 1, .pci_div = 3}, + {.bus = 14000, .ram_mult = 0.75, .pci_div = 4}, + {.bus = 12000, .ram_mult = 0.75, .pci_div = 4}, + {.bus = 12400, .ram_mult = 1, .pci_div = 3}, + {.bus = 13334, .ram_mult = 0.75, .pci_div = 4}, + {.bus = 15000, .ram_mult = 1, .pci_div = 4}, + {.bus = 14000, .ram_mult = 1, .pci_div = 4}, + {.bus = 13299, .ram_mult = 1, .pci_div = 4}, + {0} + } ICS9xxx_MODEL_END() #endif ICS9xxx_MODEL(ICS9250_18) - .max_reg = 5, - .regs = {0x02, 0xff, 0xff, 0xff, 0x6d, 0xbf}, - .fs_regs = {{0, 4, 4, 7}, {0, 5, 4, 4}, {0, 6, 5, 6}, {0, 7, 4, 1}, {-1, -1, -1, -1}}, - .hw_select = {0, 3}, - .frequencies = (const ics9xxx_frequency_t[]) { - {.bus = 8000, .pci_div = 2}, - {.bus = 7500, .pci_div = 2}, - {.bus = 8331, .pci_div = 2}, - {.bus = 6690, .pci_div = 2}, - {.bus = 10300, .pci_div = 3}, - {.bus = 11201, .pci_div = 3}, - {.bus = 6801, .pci_div = 2}, - {.bus = 10070, .pci_div = 3}, - {.bus = 12000, .pci_div = 3}, - {.bus = 11499, .pci_div = 3}, - {.bus = 10999, .pci_div = 3}, - {.bus = 10500, .pci_div = 3}, - {.bus = 14000, .pci_div = 4}, - {.bus = 15000, .pci_div = 4}, - {.bus = 12400, .pci_div = 4}, - {.bus = 13390, .pci_div = 4}, - {.bus = 13500, .pci_div = 4}, - {.bus = 12999, .pci_div = 4}, - {.bus = 12600, .pci_div = 4}, - {.bus = 11800, .pci_div = 4}, - {.bus = 11598, .pci_div = 4}, - {.bus = 9500, .pci_div = 3}, - {.bus = 9000, .pci_div = 3}, - {.bus = 8501, .pci_div = 3}, - {.bus = 16600, .pci_div = 4}, - {.bus = 16001, .pci_div = 4}, - {.bus = 15499, .pci_div = 4}, - {.bus = 14795, .pci_div = 4}, - {.bus = 14598, .pci_div = 4}, - {.bus = 14398, .pci_div = 4}, - {.bus = 14199, .pci_div = 4}, - {.bus = 13801, .pci_div = 4}, - {0} - } + .max_reg = 5, + .regs = {0x02, 0xff, 0xff, 0xff, 0x6d, 0xbf}, + .fs_regs = {{0, 4, 4, 7}, {0, 5, 4, 4}, {0, 6, 5, 6}, {0, 7, 4, 1}, {-1, -1, -1, -1}}, + .hw_select = {0, 3}, + .frequencies = (const ics9xxx_frequency_t[]) { + {.bus = 8000, .pci_div = 2}, + {.bus = 7500, .pci_div = 2}, + {.bus = 8331, .pci_div = 2}, + {.bus = 6690, .pci_div = 2}, + {.bus = 10300, .pci_div = 3}, + {.bus = 11201, .pci_div = 3}, + {.bus = 6801, .pci_div = 2}, + {.bus = 10070, .pci_div = 3}, + {.bus = 12000, .pci_div = 3}, + {.bus = 11499, .pci_div = 3}, + {.bus = 10999, .pci_div = 3}, + {.bus = 10500, .pci_div = 3}, + {.bus = 14000, .pci_div = 4}, + {.bus = 15000, .pci_div = 4}, + {.bus = 12400, .pci_div = 4}, + {.bus = 13390, .pci_div = 4}, + {.bus = 13500, .pci_div = 4}, + {.bus = 12999, .pci_div = 4}, + {.bus = 12600, .pci_div = 4}, + {.bus = 11800, .pci_div = 4}, + {.bus = 11598, .pci_div = 4}, + {.bus = 9500, .pci_div = 3}, + {.bus = 9000, .pci_div = 3}, + {.bus = 8501, .pci_div = 3}, + {.bus = 16600, .pci_div = 4}, + {.bus = 16001, .pci_div = 4}, + {.bus = 15499, .pci_div = 4}, + {.bus = 14795, .pci_div = 4}, + {.bus = 14598, .pci_div = 4}, + {.bus = 14398, .pci_div = 4}, + {.bus = 14199, .pci_div = 4}, + {.bus = 13801, .pci_div = 4}, + {0} + } ICS9xxx_MODEL_END() #ifdef ENABLE_ICS9xxx_DETECT ICS9xxx_MODEL(ICS9250_19) - .max_reg = 5, - .regs = {0x02, 0xff, 0xff, 0xff, 0x6d, 0xbf}, - .fs_regs = {{0, 4, 4, 7}, {0, 5, 4, 4}, {0, 6, 5, 6}, {0, 7, 4, 1}, {-1, -1, -1, -1}}, - .hw_select = {0, 3}, - .frequencies_ref = ICS9250_08 + .max_reg = 5, + .regs = {0x02, 0xff, 0xff, 0xff, 0x6d, 0xbf}, + .fs_regs = {{0, 4, 4, 7}, {0, 5, 4, 4}, {0, 6, 5, 6}, {0, 7, 4, 1}, {-1, -1, -1, -1}}, + .hw_select = {0, 3}, + .frequencies_ref = ICS9250_08 ICS9xxx_MODEL_END() ICS9xxx_MODEL(ICS9250_23) - .max_reg = 5, - .regs = {0x02, 0x1f, 0xff, 0xff, 0xeb, 0xff}, - .fs_regs = {{0, 4, 1, 6}, {0, 5, 4, 2}, {0, 6, 1, 5}, {0, 7, 1, 7}, {0, 2, 4, 4}}, - .hw_select = {0, 3}, - .frequencies = (const ics9xxx_frequency_t[]) { - {.bus = 6900, .ram_mult = 1.5, .pci_div = 2}, - {.bus = 7000, .ram_mult = 1.5, .pci_div = 2}, - {.bus = 7100, .ram_mult = 1.5, .pci_div = 2}, - {.bus = 6690, .ram_mult = 1.5, .pci_div = 2}, - {.bus = 7200, .ram_mult = 1.5, .pci_div = 2}, - {.bus = 7500, .ram_mult = 1.5, .pci_div = 2}, - {.bus = 7660, .ram_mult = 1.5, .pci_div = 2}, - {.bus = 8500, .ram_mult = 1.5, .pci_div = 2}, - {.bus = 6800, .ram_mult = 1.5, .pci_div = 2}, - {.bus = 7400, .ram_mult = 1.5, .pci_div = 2}, - {.bus = 14000, .ram_mult = 1, .pci_div = 4}, - {.bus = 13333, .ram_mult = 1, .pci_div = 4}, - {.bus = 15000, .ram_mult = 1, .pci_div = 4}, - {.bus = 15500, .ram_mult = 1, .pci_div = 4}, - {.bus = 16600, .ram_mult = 1, .pci_div = 4}, - {.bus = 16600, .ram_mult = 1, .pci_div = 3}, - {.bus = 11177, .ram_mult = 1, .pci_div = 3}, - {.bus = 10478, .ram_mult = 1, .pci_div = 3}, - {.bus = 10951, .ram_mult = 1, .pci_div = 3}, - {.bus = 10090, .ram_mult = 1, .pci_div = 3}, - {.bus = 11700, .ram_mult = 1, .pci_div = 3}, - {.bus = 12375, .ram_mult = 1, .pci_div = 3}, - {.bus = 13333, .ram_mult = 1, .pci_div = 3}, - {.bus = 14250, .ram_mult = 1, .pci_div = 3}, - {.bus = 13600, .ram_mult = 0.75, .pci_div = 4}, - {.bus = 14000, .ram_mult = 0.75, .pci_div = 4}, - {.bus = 14300, .ram_mult = 0.75, .pci_div = 4}, - {.bus = 13390, .ram_mult = 0.75, .pci_div = 4}, - {.bus = 14667, .ram_mult = 0.75, .pci_div = 4}, - {.bus = 14933, .ram_mult = 0.75, .pci_div = 4}, - {.bus = 15330, .ram_mult = 0.75, .pci_div = 4}, - {.bus = 16667, .ram_mult = 0.75, .pci_div = 4}, - {0} - } + .max_reg = 5, + .regs = {0x02, 0x1f, 0xff, 0xff, 0xeb, 0xff}, + .fs_regs = {{0, 4, 1, 6}, {0, 5, 4, 2}, {0, 6, 1, 5}, {0, 7, 1, 7}, {0, 2, 4, 4}}, + .hw_select = {0, 3}, + .frequencies = (const ics9xxx_frequency_t[]) { + {.bus = 6900, .ram_mult = 1.5, .pci_div = 2}, + {.bus = 7000, .ram_mult = 1.5, .pci_div = 2}, + {.bus = 7100, .ram_mult = 1.5, .pci_div = 2}, + {.bus = 6690, .ram_mult = 1.5, .pci_div = 2}, + {.bus = 7200, .ram_mult = 1.5, .pci_div = 2}, + {.bus = 7500, .ram_mult = 1.5, .pci_div = 2}, + {.bus = 7660, .ram_mult = 1.5, .pci_div = 2}, + {.bus = 8500, .ram_mult = 1.5, .pci_div = 2}, + {.bus = 6800, .ram_mult = 1.5, .pci_div = 2}, + {.bus = 7400, .ram_mult = 1.5, .pci_div = 2}, + {.bus = 14000, .ram_mult = 1, .pci_div = 4}, + {.bus = 13333, .ram_mult = 1, .pci_div = 4}, + {.bus = 15000, .ram_mult = 1, .pci_div = 4}, + {.bus = 15500, .ram_mult = 1, .pci_div = 4}, + {.bus = 16600, .ram_mult = 1, .pci_div = 4}, + {.bus = 16600, .ram_mult = 1, .pci_div = 3}, + {.bus = 11177, .ram_mult = 1, .pci_div = 3}, + {.bus = 10478, .ram_mult = 1, .pci_div = 3}, + {.bus = 10951, .ram_mult = 1, .pci_div = 3}, + {.bus = 10090, .ram_mult = 1, .pci_div = 3}, + {.bus = 11700, .ram_mult = 1, .pci_div = 3}, + {.bus = 12375, .ram_mult = 1, .pci_div = 3}, + {.bus = 13333, .ram_mult = 1, .pci_div = 3}, + {.bus = 14250, .ram_mult = 1, .pci_div = 3}, + {.bus = 13600, .ram_mult = 0.75, .pci_div = 4}, + {.bus = 14000, .ram_mult = 0.75, .pci_div = 4}, + {.bus = 14300, .ram_mult = 0.75, .pci_div = 4}, + {.bus = 13390, .ram_mult = 0.75, .pci_div = 4}, + {.bus = 14667, .ram_mult = 0.75, .pci_div = 4}, + {.bus = 14933, .ram_mult = 0.75, .pci_div = 4}, + {.bus = 15330, .ram_mult = 0.75, .pci_div = 4}, + {.bus = 16667, .ram_mult = 0.75, .pci_div = 4}, + {0} + } ICS9xxx_MODEL_END() ICS9xxx_MODEL(ICS9250_25) - .max_reg = 6, - .regs = {0x02, 0x1f, 0xff, 0xff, 0xeb, 0xff, 0x06}, - .fs_regs = {{0, 4, 1, 6}, {0, 5, 4, 2}, {0, 6, 1, 5}, {0, 7, 1, 7}, {0, 2, 4, 4}}, - .hw_select = {0, 3}, - .frequencies = (const ics9xxx_frequency_t[]) { - {.bus = 5500, .ram_mult = 1.5, .pci_div = 2}, - {.bus = 6000, .ram_mult = 1.5, .pci_div = 2}, - {.bus = 6680, .ram_mult = 1.5, .pci_div = 2}, - {.bus = 6833, .ram_mult = 1.5, .pci_div = 2}, - {.bus = 7000, .ram_mult = 1.5, .pci_div = 2}, - {.bus = 7200, .ram_mult = 1.5, .pci_div = 2}, - {.bus = 7500, .ram_mult = 1.5, .pci_div = 2}, - {.bus = 7700, .ram_mult = 1.5, .pci_div = 2}, - {.bus = 8330, .ram_mult = 1, .pci_div = 3}, - {.bus = 9000, .ram_mult = 1, .pci_div = 3}, - {.bus = 10030, .ram_mult = 1, .pci_div = 3}, - {.bus = 10300, .ram_mult = 1, .pci_div = 3}, - {.bus = 11250, .ram_mult = 1, .pci_div = 3}, - {.bus = 11500, .ram_mult = 1, .pci_div = 3}, - {.bus = 12000, .ram_mult = 1, .pci_div = 3}, - {.bus = 12500, .ram_mult = 1, .pci_div = 3}, - {.bus = 12800, .ram_mult = 1, .pci_div = 4}, - {.bus = 13000, .ram_mult = 1, .pci_div = 4}, - {.bus = 13370, .ram_mult = 1, .pci_div = 4}, - {.bus = 13700, .ram_mult = 1, .pci_div = 4}, - {.bus = 14000, .ram_mult = 1, .pci_div = 4}, - {.bus = 14500, .ram_mult = 1, .pci_div = 4}, - {.bus = 15000, .ram_mult = 1, .pci_div = 4}, - {.bus = 15333, .ram_mult = 1, .pci_div = 4}, - {.bus = 12500, .ram_mult = 0.75, .pci_div = 4}, - {.bus = 13000, .ram_mult = 0.75, .pci_div = 4}, - {.bus = 13370, .ram_mult = 0.75, .pci_div = 4}, - {.bus = 13700, .ram_mult = 0.75, .pci_div = 4}, - {.bus = 14000, .ram_mult = 0.75, .pci_div = 4}, - {.bus = 14500, .ram_mult = 0.75, .pci_div = 4}, - {.bus = 15000, .ram_mult = 0.75, .pci_div = 4}, - {.bus = 15333, .ram_mult = 0.75, .pci_div = 4}, - {0} - } + .max_reg = 6, + .regs = {0x02, 0x1f, 0xff, 0xff, 0xeb, 0xff, 0x06}, + .fs_regs = {{0, 4, 1, 6}, {0, 5, 4, 2}, {0, 6, 1, 5}, {0, 7, 1, 7}, {0, 2, 4, 4}}, + .hw_select = {0, 3}, + .frequencies = (const ics9xxx_frequency_t[]) { + {.bus = 5500, .ram_mult = 1.5, .pci_div = 2}, + {.bus = 6000, .ram_mult = 1.5, .pci_div = 2}, + {.bus = 6680, .ram_mult = 1.5, .pci_div = 2}, + {.bus = 6833, .ram_mult = 1.5, .pci_div = 2}, + {.bus = 7000, .ram_mult = 1.5, .pci_div = 2}, + {.bus = 7200, .ram_mult = 1.5, .pci_div = 2}, + {.bus = 7500, .ram_mult = 1.5, .pci_div = 2}, + {.bus = 7700, .ram_mult = 1.5, .pci_div = 2}, + {.bus = 8330, .ram_mult = 1, .pci_div = 3}, + {.bus = 9000, .ram_mult = 1, .pci_div = 3}, + {.bus = 10030, .ram_mult = 1, .pci_div = 3}, + {.bus = 10300, .ram_mult = 1, .pci_div = 3}, + {.bus = 11250, .ram_mult = 1, .pci_div = 3}, + {.bus = 11500, .ram_mult = 1, .pci_div = 3}, + {.bus = 12000, .ram_mult = 1, .pci_div = 3}, + {.bus = 12500, .ram_mult = 1, .pci_div = 3}, + {.bus = 12800, .ram_mult = 1, .pci_div = 4}, + {.bus = 13000, .ram_mult = 1, .pci_div = 4}, + {.bus = 13370, .ram_mult = 1, .pci_div = 4}, + {.bus = 13700, .ram_mult = 1, .pci_div = 4}, + {.bus = 14000, .ram_mult = 1, .pci_div = 4}, + {.bus = 14500, .ram_mult = 1, .pci_div = 4}, + {.bus = 15000, .ram_mult = 1, .pci_div = 4}, + {.bus = 15333, .ram_mult = 1, .pci_div = 4}, + {.bus = 12500, .ram_mult = 0.75, .pci_div = 4}, + {.bus = 13000, .ram_mult = 0.75, .pci_div = 4}, + {.bus = 13370, .ram_mult = 0.75, .pci_div = 4}, + {.bus = 13700, .ram_mult = 0.75, .pci_div = 4}, + {.bus = 14000, .ram_mult = 0.75, .pci_div = 4}, + {.bus = 14500, .ram_mult = 0.75, .pci_div = 4}, + {.bus = 15000, .ram_mult = 0.75, .pci_div = 4}, + {.bus = 15333, .ram_mult = 0.75, .pci_div = 4}, + {0} + } ICS9xxx_MODEL_END() ICS9xxx_MODEL(ICS9250_26) - .max_reg = 5, - .regs = {0x1e, 0xff, 0xff, 0x00, 0x00, 0x06}, - .fs_regs = {{5, 0, -1, -1}, {5, 3, -1, -1}, {-1, -1, -1, -1}, {-1, -1, -1, -1}, {-1, -1, -1, -1}}, - .hw_select = {-1, -1}, - .frequencies_ref = ICS9250_16 + .max_reg = 5, + .regs = {0x1e, 0xff, 0xff, 0x00, 0x00, 0x06}, + .fs_regs = {{5, 0, -1, -1}, {5, 3, -1, -1}, {-1, -1, -1, -1}, {-1, -1, -1, -1}, {-1, -1, -1, -1}}, + .hw_select = {-1, -1}, + .frequencies_ref = ICS9250_16 ICS9xxx_MODEL_END() ICS9xxx_MODEL(ICS9250_27) - .max_reg = 5, - .regs = {0x0f, 0xff, 0xfe, 0x00, 0x00, 0x00}, - .fs_regs = {{-1, -1, -1, -1}, {-1, -1, -1, -1}, {3, 0, -1, -1}, {-1, -1, -1, -1}, {-1, -1, -1, -1}}, - .hw_select = {-1, -1}, - .frequencies = (const ics9xxx_frequency_t[]) { - {.bus = 6666, .ram_mult = 1.5, .pci_div = 2}, - {.bus = 13332, .ram_mult = 1, .pci_div = 4}, - {.bus = 10000, .ram_mult = 1, .pci_div = 3}, - {.bus = 13332, .ram_mult = 0.75, .pci_div = 4}, - {.bus = 6666, .ram_mult = 1.5, .pci_div = 2}, - {.bus = 13332, .ram_mult = 1, .pci_div = 4}, - {.bus = 10000, .ram_mult = 1, .pci_div = 3}, - {.bus = 13332, .ram_mult = 1, .pci_div = 4}, - {0} - } + .max_reg = 5, + .regs = {0x0f, 0xff, 0xfe, 0x00, 0x00, 0x00}, + .fs_regs = {{-1, -1, -1, -1}, {-1, -1, -1, -1}, {3, 0, -1, -1}, {-1, -1, -1, -1}, {-1, -1, -1, -1}}, + .hw_select = {-1, -1}, + .frequencies = (const ics9xxx_frequency_t[]) { + {.bus = 6666, .ram_mult = 1.5, .pci_div = 2}, + {.bus = 13332, .ram_mult = 1, .pci_div = 4}, + {.bus = 10000, .ram_mult = 1, .pci_div = 3}, + {.bus = 13332, .ram_mult = 0.75, .pci_div = 4}, + {.bus = 6666, .ram_mult = 1.5, .pci_div = 2}, + {.bus = 13332, .ram_mult = 1, .pci_div = 4}, + {.bus = 10000, .ram_mult = 1, .pci_div = 3}, + {.bus = 13332, .ram_mult = 1, .pci_div = 4}, + {0} + } ICS9xxx_MODEL_END() ICS9xxx_MODEL(ICS9250_28) - .max_reg = 4, - .regs = {0x1e, 0xff, 0xfe, 0x00, 0x00}, - .fs_regs = {{-1, -1, -1, -1}, {-1, -1, -1, -1}, {3, 0, -1, -1}, {-1, -1, -1, -1}, {-1, -1, -1, -1}}, - .hw_select = {-1, -1}, - .frequencies_ref = ICS9250_27 + .max_reg = 4, + .regs = {0x1e, 0xff, 0xfe, 0x00, 0x00}, + .fs_regs = {{-1, -1, -1, -1}, {-1, -1, -1, -1}, {3, 0, -1, -1}, {-1, -1, -1, -1}, {-1, -1, -1, -1}}, + .hw_select = {-1, -1}, + .frequencies_ref = ICS9250_27 ICS9xxx_MODEL_END() ICS9xxx_MODEL(ICS9250_29) - .max_reg = 5, - .regs = {0x16, 0xff, 0xfe, 0x00, 0x00, 0x00}, - .fs_regs = {{-1, -1, -1, -1}, {-1, -1, -1, -1}, {3, 0, -1, -1}, {-1, -1, -1, -1}, {-1, -1, -1, -1}}, - .hw_select = {-1, -1}, - .frequencies_ref = ICS9250_27 + .max_reg = 5, + .regs = {0x16, 0xff, 0xfe, 0x00, 0x00, 0x00}, + .fs_regs = {{-1, -1, -1, -1}, {-1, -1, -1, -1}, {3, 0, -1, -1}, {-1, -1, -1, -1}, {-1, -1, -1, -1}}, + .hw_select = {-1, -1}, + .frequencies_ref = ICS9250_27 ICS9xxx_MODEL_END() ICS9xxx_MODEL(ICS9250_30) - .max_reg = 6, - .regs = {0x02, 0x0f, 0xff, 0xff, 0xeb, 0xff, 0x06}, - .fs_regs = {{0, 4, 1, 6}, {0, 5, 4, 2}, {0, 6, 1, 5}, {0, 7, 1, 7}, {0, 2, 4, 4}}, - .hw_select = {0, 3}, - .frequencies = (const ics9xxx_frequency_t[]) { - {.bus = 6667, .ram_mult = 1.5, .pci_div = 2}, - {.bus = 6000, .ram_mult = 1.5, .pci_div = 2}, - {.bus = 6680, .ram_mult = 1.5, .pci_div = 2}, - {.bus = 6833, .ram_mult = 1.5, .pci_div = 2}, - {.bus = 7000, .ram_mult = 1.5, .pci_div = 2}, - {.bus = 7500, .ram_mult = 1.5, .pci_div = 2}, - {.bus = 8000, .ram_mult = 1.5, .pci_div = 2}, - {.bus = 8300, .ram_mult = 1.5, .pci_div = 2}, - {.bus = 10000, .ram_mult = 1, .pci_div = 3}, - {.bus = 9000, .ram_mult = 1, .pci_div = 3}, - {.bus = 10030, .ram_mult = 1, .pci_div = 3}, - {.bus = 10300, .ram_mult = 1, .pci_div = 3}, - {.bus = 10500, .ram_mult = 1, .pci_div = 3}, - {.bus = 11000, .ram_mult = 1, .pci_div = 3}, - {.bus = 11500, .ram_mult = 1, .pci_div = 3}, - {.bus = 20000, .ram_mult = 1, .pci_div = 6}, - {.bus = 13333, .ram_mult = 1, .pci_div = 4}, - {.bus = 16667, .ram_mult = 1, .pci_div = 4}, - {.bus = 13370, .ram_mult = 1, .pci_div = 4}, - {.bus = 13700, .ram_mult = 1, .pci_div = 4}, - {.bus = 14000, .ram_mult = 1, .pci_div = 4}, - {.bus = 14500, .ram_mult = 1, .pci_div = 4}, - {.bus = 15000, .ram_mult = 1, .pci_div = 4}, - {.bus = 16000, .ram_mult = 1, .pci_div = 4}, - {.bus = 13333, .ram_mult = 0.75, .pci_div = 4}, - {.bus = 16667, .ram_mult = 0.75, .pci_div = 4}, - {.bus = 13370, .ram_mult = 0.75, .pci_div = 4}, - {.bus = 13700, .ram_mult = 0.75, .pci_div = 4}, - {.bus = 14000, .ram_mult = 0.75, .pci_div = 4}, - {.bus = 14500, .ram_mult = 0.75, .pci_div = 4}, - {.bus = 15000, .ram_mult = 0.75, .pci_div = 4}, - {.bus = 16000, .ram_mult = 0.75, .pci_div = 4}, - {0} - } + .max_reg = 6, + .regs = {0x02, 0x0f, 0xff, 0xff, 0xeb, 0xff, 0x06}, + .fs_regs = {{0, 4, 1, 6}, {0, 5, 4, 2}, {0, 6, 1, 5}, {0, 7, 1, 7}, {0, 2, 4, 4}}, + .hw_select = {0, 3}, + .frequencies = (const ics9xxx_frequency_t[]) { + {.bus = 6667, .ram_mult = 1.5, .pci_div = 2}, + {.bus = 6000, .ram_mult = 1.5, .pci_div = 2}, + {.bus = 6680, .ram_mult = 1.5, .pci_div = 2}, + {.bus = 6833, .ram_mult = 1.5, .pci_div = 2}, + {.bus = 7000, .ram_mult = 1.5, .pci_div = 2}, + {.bus = 7500, .ram_mult = 1.5, .pci_div = 2}, + {.bus = 8000, .ram_mult = 1.5, .pci_div = 2}, + {.bus = 8300, .ram_mult = 1.5, .pci_div = 2}, + {.bus = 10000, .ram_mult = 1, .pci_div = 3}, + {.bus = 9000, .ram_mult = 1, .pci_div = 3}, + {.bus = 10030, .ram_mult = 1, .pci_div = 3}, + {.bus = 10300, .ram_mult = 1, .pci_div = 3}, + {.bus = 10500, .ram_mult = 1, .pci_div = 3}, + {.bus = 11000, .ram_mult = 1, .pci_div = 3}, + {.bus = 11500, .ram_mult = 1, .pci_div = 3}, + {.bus = 20000, .ram_mult = 1, .pci_div = 6}, + {.bus = 13333, .ram_mult = 1, .pci_div = 4}, + {.bus = 16667, .ram_mult = 1, .pci_div = 4}, + {.bus = 13370, .ram_mult = 1, .pci_div = 4}, + {.bus = 13700, .ram_mult = 1, .pci_div = 4}, + {.bus = 14000, .ram_mult = 1, .pci_div = 4}, + {.bus = 14500, .ram_mult = 1, .pci_div = 4}, + {.bus = 15000, .ram_mult = 1, .pci_div = 4}, + {.bus = 16000, .ram_mult = 1, .pci_div = 4}, + {.bus = 13333, .ram_mult = 0.75, .pci_div = 4}, + {.bus = 16667, .ram_mult = 0.75, .pci_div = 4}, + {.bus = 13370, .ram_mult = 0.75, .pci_div = 4}, + {.bus = 13700, .ram_mult = 0.75, .pci_div = 4}, + {.bus = 14000, .ram_mult = 0.75, .pci_div = 4}, + {.bus = 14500, .ram_mult = 0.75, .pci_div = 4}, + {.bus = 15000, .ram_mult = 0.75, .pci_div = 4}, + {.bus = 16000, .ram_mult = 0.75, .pci_div = 4}, + {0} + } ICS9xxx_MODEL_END() ICS9xxx_MODEL(ICS9250_32) - .max_reg = 4, - .regs = {0x07, 0xff, 0xff, 0x00, 0x00}, - .fs_regs = {{-1, -1, -1, -1}, {-1, -1, -1, -1}, {-1, -1, -1, -1}, {-1, -1, -1, -1}, {-1, -1, -1, -1}} + .max_reg = 4, + .regs = {0x07, 0xff, 0xff, 0x00, 0x00}, + .fs_regs = {{-1, -1, -1, -1}, {-1, -1, -1, -1}, {-1, -1, -1, -1}, {-1, -1, -1, -1}, {-1, -1, -1, -1}} ICS9xxx_MODEL_END() ICS9xxx_MODEL(ICS9250_38) - .max_reg = 6, - .regs = {0x18, 0x07, 0xfe, 0xc7, 0xfc, 0x00, 0x80}, - .fs_regs = {{0, 0, -1, -1}, {0, 1, -1, -1}, {0, 2, -1, -1}, {-1, -1, -1, -1}, {-1, -1, -1, -1}}, - .normal_bits_fixed = 1, - .frequencies = (const ics9xxx_frequency_t[]) { - {.bus = 6666, .ram_mult = 1, .pci_div = 1}, - {.bus = 10000, .ram_mult = 2.0/3.0, .pci_div = 3}, - {.bus = 20000, .ram_mult = 1.0/3.0, .pci_div = 6}, - {.bus = 13333, .ram_mult = 0.5, .pci_div = 2}, - {.bus = 6666, .ram_mult = 1, .pci_div = 1}, - {.bus = 10000, .ram_mult = 2.0/3.0, .pci_div = 3}, - {.bus = 20000, .ram_mult = 1.0/3.0, .pci_div = 6}, - {.bus = 13333, .ram_mult = 0.5, .pci_div = 2}, - {0} - } + .max_reg = 6, + .regs = {0x18, 0x07, 0xfe, 0xc7, 0xfc, 0x00, 0x80}, + .fs_regs = {{0, 0, -1, -1}, {0, 1, -1, -1}, {0, 2, -1, -1}, {-1, -1, -1, -1}, {-1, -1, -1, -1}}, + .normal_bits_fixed = 1, + .frequencies = (const ics9xxx_frequency_t[]) { + {.bus = 6666, .ram_mult = 1, .pci_div = 1}, + {.bus = 10000, .ram_mult = 2.0/3.0, .pci_div = 3}, + {.bus = 20000, .ram_mult = 1.0/3.0, .pci_div = 6}, + {.bus = 13333, .ram_mult = 0.5, .pci_div = 2}, + {.bus = 6666, .ram_mult = 1, .pci_div = 1}, + {.bus = 10000, .ram_mult = 2.0/3.0, .pci_div = 3}, + {.bus = 20000, .ram_mult = 1.0/3.0, .pci_div = 6}, + {.bus = 13333, .ram_mult = 0.5, .pci_div = 2}, + {0} + } ICS9xxx_MODEL_END() ICS9xxx_MODEL(ICS9250_50) - .max_reg = 6, - .regs = {0x02, 0x6f, 0xff, 0xff, 0xef, 0xff, 0x06}, - .fs_regs = {{-1, -1, 1, 6}, {-1, -1, 4, 2}, {-1, -1, 1, 5}, {0, 7, 1, 7}, {0, 2, 4, 4}}, - .hw_select = {0, 3}, - .frequencies = (const ics9xxx_frequency_t[]) { - [0 ... 7] = {.bus = 6667, .ram_mult = 1.5, .pci_div = 2}, - [8 ... 15] = {.bus = 10000, .ram_mult = 1, .pci_div = 3}, - [16 ... 23] = {.bus = 13333, .ram_mult = 1, .pci_div = 4}, - [24 ... 31] = {.bus = 13333, .ram_mult = 0.75, .pci_div = 4}, - {0} - } + .max_reg = 6, + .regs = {0x02, 0x6f, 0xff, 0xff, 0xef, 0xff, 0x06}, + .fs_regs = {{-1, -1, 1, 6}, {-1, -1, 4, 2}, {-1, -1, 1, 5}, {0, 7, 1, 7}, {0, 2, 4, 4}}, + .hw_select = {0, 3}, + .frequencies = (const ics9xxx_frequency_t[]) { + [0 ... 7] = {.bus = 6667, .ram_mult = 1.5, .pci_div = 2}, + [8 ... 15] = {.bus = 10000, .ram_mult = 1, .pci_div = 3}, + [16 ... 23] = {.bus = 13333, .ram_mult = 1, .pci_div = 4}, + [24 ... 31] = {.bus = 13333, .ram_mult = 0.75, .pci_div = 4}, + {0} + } ICS9xxx_MODEL_END() #endif }; - /* Don't enable the detection device here. Enable it further up near logging. */ #ifdef ENABLE_ICS9xxx_DETECT -static uint16_t detect_bus = 0; -static uint8_t detect_reg = 0; -static uint8_t discarded[ICS9xxx_MAX] = {0}; - +static uint16_t detect_bus = 0; +static uint8_t detect_reg = 0; +static uint8_t discarded[ICS9xxx_MAX] = { 0 }; static void ics9xxx_detect_reset(void *priv) @@ -924,73 +920,74 @@ ics9xxx_detect_reset(void *priv) pclog("Please enter the frequency set in the BIOS (7500 for 75.00 MHz)\nAnswer 0 if unsure or set to auto, I'll ask again next reset.\n"); scanf("%hu", &detect_bus); if ((detect_bus > 0) && (detect_bus < 1000)) - detect_bus *= 100; + detect_bus *= 100; pclog("Frequency interpreted as %d\n", detect_bus); } - static void ics9xxx_detect(ics9xxx_t *dev) { if (!detect_bus) { - pclog("Frequency not entered on this reset, ignoring change.\n"); - return; + pclog("Frequency not entered on this reset, ignoring change.\n"); + return; } if ((detect_reg == 0) && (dev->regs[detect_reg] >= 0xfe)) { - pclog("Register %d set to %02X, probably not it, trying %d instead\n", detect_reg, dev->regs[detect_reg], 3); - detect_reg = 3; - dev->relevant_regs = 1 << detect_reg; - return; + pclog("Register %d set to %02X, probably not it, trying %d instead\n", detect_reg, dev->regs[detect_reg], 3); + detect_reg = 3; + dev->relevant_regs = 1 << detect_reg; + return; } if (!(dev->regs[detect_reg] & 0x40)) - pclog("Bit 3 of register %d is clear, probably in hardware select mode!\n", detect_reg); + pclog("Bit 3 of register %d is clear, probably in hardware select mode!\n", detect_reg); - uint8_t i = 0, matches = 0, val, bitmask; + uint8_t i = 0; + uint8_t matches = 0; + uint8_t val; + uint8_t bitmask; ics9xxx_frequency_t *frequencies_ptr; - uint32_t delta; + uint32_t delta; for (uint8_t j = 0; j < ICS9xxx_MAX; j++) { - if (discarded[j]) - continue; - discarded[j] = 1; + if (discarded[j]) + continue; + discarded[j] = 1; - frequencies_ptr = (ics9xxx_frequency_t *) ics9xxx_models[ics9xxx_models[j].frequencies_ref ? ics9xxx_models[j].frequencies_ref : j].frequencies; - if (!frequencies_ptr) - continue; + frequencies_ptr = (ics9xxx_frequency_t *) ics9xxx_models[ics9xxx_models[j].frequencies_ref ? ics9xxx_models[j].frequencies_ref : j].frequencies; + if (!frequencies_ptr) + continue; - while (frequencies_ptr[i].bus) { - delta = ABS((int32_t) (detect_bus - frequencies_ptr[i].bus)); - if (delta <= 100) { - val = bitmask = 0; - for (uint8_t k = 0; k < sizeof(ics9xxx_models[j].fs_regs) / sizeof(ics9xxx_models[j].fs_regs[0]); k++) { - if (ics9xxx_models[j].fs_regs[k].normal_reg == detect_reg) { - bitmask |= 1 << k; - val |= (1 << k) * !!(dev->regs[detect_reg] & (1 << ics9xxx_models[j].fs_regs[k].normal_bit)); - } - } - if (bitmask && (val == (i & bitmask))) { - matches++; - discarded[j] = 0; - pclog("> Potential match for %s (frequency %d index %d)\n", ics9xxx_models[j].name, frequencies_ptr[i].bus, val); - } - } + while (frequencies_ptr[i].bus) { + delta = ABS((int32_t) (detect_bus - frequencies_ptr[i].bus)); + if (delta <= 100) { + val = bitmask = 0; + for (uint8_t k = 0; k < sizeof(ics9xxx_models[j].fs_regs) / sizeof(ics9xxx_models[j].fs_regs[0]); k++) { + if (ics9xxx_models[j].fs_regs[k].normal_reg == detect_reg) { + bitmask |= 1 << k; + val |= (1 << k) * !!(dev->regs[detect_reg] & (1 << ics9xxx_models[j].fs_regs[k].normal_bit)); + } + } + if (bitmask && (val == (i & bitmask))) { + matches++; + discarded[j] = 0; + pclog("> Potential match for %s (frequency %d index %d)\n", ics9xxx_models[j].name, frequencies_ptr[i].bus, val); + } + } - i++; - } + i++; + } } pclog("Found a total of %d matches for register %d value %02X and bus frequency %d\n", matches, detect_reg, dev->regs[detect_reg], detect_bus); if (matches == 0) { - pclog("Resetting list of discarded models since there were no matches.\n"); - memset(discarded, 0, sizeof(discarded)); + pclog("Resetting list of discarded models since there were no matches.\n"); + memset(discarded, 0, sizeof(discarded)); } } #endif - static uint8_t -ics9xxx_start(void *bus, uint8_t addr, uint8_t read, void *priv) +ics9xxx_start(UNUSED(void *bus), UNUSED(uint8_t addr), UNUSED(uint8_t read), void *priv) { ics9xxx_t *dev = (ics9xxx_t *) priv; @@ -1001,53 +998,51 @@ ics9xxx_start(void *bus, uint8_t addr, uint8_t read, void *priv) return 1; } - static uint8_t -ics9xxx_read(void *bus, uint8_t addr, void *priv) +ics9xxx_read(UNUSED(void *bus), UNUSED(uint8_t addr), void *priv) { ics9xxx_t *dev = (ics9xxx_t *) priv; - uint8_t ret = 0xff; + uint8_t ret = 0xff; if (dev->addr_register < 0) { - dev->addr_register = -1; - ret = dev->model->max_reg + 1; + dev->addr_register = -1; + ret = dev->model->max_reg + 1; } #if 0 else if ((dev->model_idx == ICS9250_50) && (dev->addr_register == 0)) - ret = dev->regs[dev->addr_register] & 0x0b; /* -50 reads back revision ID instead */ + ret = dev->regs[dev->addr_register] & 0x0b; /* -50 reads back revision ID instead */ #endif else - ret = dev->regs[dev->addr_register]; + ret = dev->regs[dev->addr_register]; #ifdef ENABLE_ICS9xxx_LOG if (dev->addr_register < 0) - ics9xxx_log("ICS9xxx: read(%s) = %02X\n", (dev->addr_register == -1) ? "blocklen" : "command", ret); + ics9xxx_log("ICS9xxx: read(%s) = %02X\n", (dev->addr_register == -1) ? "blocklen" : "command", ret); else - ics9xxx_log("ICS9xxx: read(%x) = %02X\n", dev->addr_register, ret); + ics9xxx_log("ICS9xxx: read(%x) = %02X\n", dev->addr_register, ret); #endif if (dev->addr_register >= dev->model->max_reg) - dev->addr_register = 0; /* roll-over */ + dev->addr_register = 0; /* roll-over */ else - dev->addr_register++; + dev->addr_register++; return ret; } - static void ics9xxx_set(ics9xxx_t *dev, uint8_t val) { /* Get the active mode, which determines what to add to the static frequency bits we were passed. */ uint8_t hw_select = (dev->model->hw_select.normal_reg < 7) && !(dev->regs[dev->model->hw_select.normal_reg] & (1 << dev->model->hw_select.normal_bit)); if (hw_select) { - /* Hardware select mode: add strapped frequency bits. */ - val |= dev->bus_match; + /* Hardware select mode: add strapped frequency bits. */ + val |= dev->bus_match; } else { - /* Programmable mode: add register-defined frequency bits. */ - for (uint8_t i = 0; i < sizeof(dev->model->fs_regs) / sizeof(dev->model->fs_regs[0]); i++) { - if ((dev->model->fs_regs[i].normal_reg < 7) && (dev->regs[dev->model->fs_regs[i].normal_reg] & (1 << dev->model->fs_regs[i].normal_bit))) - val |= 1 << i; - } + /* Programmable mode: add register-defined frequency bits. */ + for (uint8_t i = 0; i < sizeof(dev->model->fs_regs) / sizeof(dev->model->fs_regs[0]); i++) { + if ((dev->model->fs_regs[i].normal_reg < 7) && (dev->regs[dev->model->fs_regs[i].normal_reg] & (1 << dev->model->fs_regs[i].normal_bit))) + val |= 1 << i; + } } uint16_t bus = dev->frequencies_ptr[val].bus; @@ -1057,125 +1052,125 @@ ics9xxx_set(ics9xxx_t *dev, uint8_t val) ics9xxx_log("ICS9xxx: set(%d) = hw=%d bus=%d ram=%d pci=%d\n", val, hw_select, bus, bus * dev->frequencies_ptr[val].ram_mult, pci); } - static uint8_t -ics9xxx_write(void *bus, uint8_t addr, uint8_t data, void *priv) +ics9xxx_write(UNUSED(void *bus), UNUSED(uint8_t addr), uint8_t data, void *priv) { ics9xxx_t *dev = (ics9xxx_t *) priv; #ifdef ENABLE_ICS9xxx_LOG if (dev->addr_register < 0) - ics9xxx_log("ICS9xxx: write(%s, %02X)\n", (dev->addr_register == -1) ? "blocklen" : "command", data); + ics9xxx_log("ICS9xxx: write(%s, %02X)\n", (dev->addr_register == -1) ? "blocklen" : "command", data); else - ics9xxx_log("ICS9xxx: write(%x, %02X)\n", dev->addr_register, data); + ics9xxx_log("ICS9xxx: write(%x, %02X)\n", dev->addr_register, data); #endif if (dev->addr_register >= 0) { - /* Preserve fixed bits. */ + /* Preserve fixed bits. */ #ifdef ENABLE_ICS9xxx_DETECT - if (dev->model != ICS9xxx_xx) + if (dev->model != ICS9xxx_xx) #endif - { - for (uint8_t i = 0; i < sizeof(dev->model->fs_regs) / sizeof(dev->model->fs_regs[0]); i++) { - if (dev->model->normal_bits_fixed && (dev->model->fs_regs[i].normal_reg == dev->addr_register)) - data = (dev->regs[dev->addr_register] & (1 << dev->model->fs_regs[i].normal_bit)) | (data & ~(1 << dev->model->fs_regs[i].normal_bit)); - if (dev->model->fs_regs[i].inv_reg == dev->addr_register) - data = (dev->regs[dev->addr_register] & (1 << dev->model->fs_regs[i].inv_bit)) | (data & ~(1 << dev->model->fs_regs[i].inv_bit)); - } - } + { + for (uint8_t i = 0; i < sizeof(dev->model->fs_regs) / sizeof(dev->model->fs_regs[0]); i++) { + if (dev->model->normal_bits_fixed && (dev->model->fs_regs[i].normal_reg == dev->addr_register)) + data = (dev->regs[dev->addr_register] & (1 << dev->model->fs_regs[i].normal_bit)) | (data & ~(1 << dev->model->fs_regs[i].normal_bit)); + if (dev->model->fs_regs[i].inv_reg == dev->addr_register) + data = (dev->regs[dev->addr_register] & (1 << dev->model->fs_regs[i].inv_bit)) | (data & ~(1 << dev->model->fs_regs[i].inv_bit)); + } + } #if 0 - switch (dev->addr_register) { - case 0: - if (dev->model_idx == ICS9250_38) - data = (dev->regs[dev->addr_register] & ~0xe8) | (data & 0xe8); - break; + switch (dev->addr_register) { + case 0: + if (dev->model_idx == ICS9250_38) + data = (dev->regs[dev->addr_register] & ~0xe8) | (data & 0xe8); + break; - case 1: - if (dev->model_idx == ICS9250_38) - data = (dev->regs[dev->addr_register] & ~0xfe) | (data & 0xfe); - break; + case 1: + if (dev->model_idx == ICS9250_38) + data = (dev->regs[dev->addr_register] & ~0xfe) | (data & 0xfe); + break; - case 3: - if (dev->model_idx == ICS9250_32) - data ^= 0x70; - break; + case 3: + if (dev->model_idx == ICS9250_32) + data ^= 0x70; + break; - case 4: - if (dev->model_idx == ICS9250_38) - data = (dev->regs[dev->addr_register] & ~0xfc) | (data & 0xfc); - break; + case 4: + if (dev->model_idx == ICS9250_38) + data = (dev->regs[dev->addr_register] & ~0xfc) | (data & 0xfc); + break; - case 6: - if (dev->model_idx == ICS9250_38) /* read-only */ - data = dev->regs[dev->addr_register]; - break; - } + case 6: + if (dev->model_idx == ICS9250_38) /* read-only */ + data = dev->regs[dev->addr_register]; + break; + } #endif - dev->regs[dev->addr_register] = data; + dev->regs[dev->addr_register] = data; - /* Update frequency if a relevant register was written to. */ - if (dev->relevant_regs & (1 << dev->addr_register)) { - switch (dev->model_idx) { + /* Update frequency if a relevant register was written to. */ + if (dev->relevant_regs & (1 << dev->addr_register)) { + switch (dev->model_idx) { #ifdef ENABLE_ICS9xxx_DETECT - case ICS9xxx_xx: - ics9xxx_detect(dev); - break; + case ICS9xxx_xx: + ics9xxx_detect(dev); + break; #endif #if 0 - case ICS9250_10: - ics9xxx_set(dev, (cpu_busspeed >= 100000000) * 0x08); - break; + case ICS9250_10: + ics9xxx_set(dev, (cpu_busspeed >= 100000000) * 0x08); + break; - case ICS9250_16: - case ICS9250_26: - ics9xxx_set(dev, ((cpu_busspeed >= 120000000) * 0x08) | ((((cpu_busspeed >= 100000000) && (cpu_busspeed < 120000000)) || (cpu_busspeed == 150000000) || (cpu_busspeed == 132999999)) * 0x04)); - break; + case ICS9250_16: + case ICS9250_26: + ics9xxx_set(dev, ((cpu_busspeed >= 120000000) * 0x08) | ((((cpu_busspeed >= 100000000) && (cpu_busspeed < 120000000)) || (cpu_busspeed == 150000000) || (cpu_busspeed == 132999999)) * 0x04)); + break; - case ICS9250_27: - case ICS9250_28: - case ICS9250_29: - ics9xxx_set(dev, ((cpu_busspeed == 100000000) * 0x02) | ((cpu_busspeed > 100000000) * 0x01)); - break; + case ICS9250_27: + case ICS9250_28: + case ICS9250_29: + ics9xxx_set(dev, ((cpu_busspeed == 100000000) * 0x02) | ((cpu_busspeed > 100000000) * 0x01)); + break; #endif - default: - ics9xxx_set(dev, 0x00); - break; - } - } + default: + ics9xxx_set(dev, 0x00); + break; + } + } } if (dev->addr_register >= dev->model->max_reg) - dev->addr_register = 0; /* roll-over */ + dev->addr_register = 0; /* roll-over */ else - dev->addr_register++; + dev->addr_register++; return 1; } - static uint8_t -ics9xxx_find_bus_match(ics9xxx_t *dev, uint32_t bus, uint8_t preset_mask, uint8_t preset) { - uint8_t best_match = 0; - uint32_t delta, best_delta = -1; +ics9xxx_find_bus_match(ics9xxx_t *dev, uint32_t bus, uint8_t preset_mask, uint8_t preset) +{ + uint8_t best_match = 0; + uint32_t delta; + uint32_t best_delta = -1; #ifdef ENABLE_ICS9xxx_DETECT if (dev->model_idx == ICS9xxx_xx) - return 0; + return 0; #endif bus /= 10000; uint8_t i = 0; while (dev->frequencies_ptr[i].bus) { - if ((i & preset_mask) == preset) { - delta = ABS((int32_t) (bus - dev->frequencies_ptr[i].bus)); - if (delta < best_delta) { - best_match = i; - best_delta = delta; - } - } + if ((i & preset_mask) == preset) { + delta = ABS((int32_t) (bus - dev->frequencies_ptr[i].bus)); + if (delta < best_delta) { + best_match = i; + best_delta = delta; + } + } - i++; + i++; } ics9xxx_log("ICS9xxx: find_match(%s, %d) = match=%d bus=%d\n", dev->model->name, bus, best_match, dev->frequencies_ptr[best_match].bus); @@ -1183,15 +1178,14 @@ ics9xxx_find_bus_match(ics9xxx_t *dev, uint32_t bus, uint8_t preset_mask, uint8_ return best_match; } - static void * ics9xxx_init(const device_t *info) { ics9xxx_t *dev = (ics9xxx_t *) malloc(sizeof(ics9xxx_t)); memset(dev, 0, sizeof(ics9xxx_t)); - dev->model_idx = info->local; - dev->model = (ics9xxx_model_t *) &ics9xxx_models[dev->model_idx]; + dev->model_idx = info->local; + dev->model = (ics9xxx_model_t *) &ics9xxx_models[dev->model_idx]; dev->dyn_device = (device_t *) info; memcpy(&dev->regs, &dev->model->regs, dev->model->max_reg + 1); @@ -1200,56 +1194,56 @@ ics9xxx_init(const device_t *info) uint8_t i; #ifdef ENABLE_ICS9xxx_DETECT for (i = ICS9xxx_xx + 1; i < ICS9xxx_MAX; i++) { - if (ics9xxx_models[i].frequencies_ref || !ics9xxx_models[i].name) - continue; - for (uint8_t j = 0; j < i; j++) { - if (ics9xxx_models[j].frequencies_ref || !ics9xxx_models[j].name) - continue; - if (!memcmp(&ics9xxx_models[i].frequencies, &ics9xxx_models[j].frequencies, sizeof(ics9xxx_models[i].frequencies))) - pclog("Optimization warning: %s and %s have duplicate tables\n", ics9xxx_models[j].name, ics9xxx_models[i].name); - } + if (ics9xxx_models[i].frequencies_ref || !ics9xxx_models[i].name) + continue; + for (uint8_t j = 0; j < i; j++) { + if (ics9xxx_models[j].frequencies_ref || !ics9xxx_models[j].name) + continue; + if (!memcmp(&ics9xxx_models[i].frequencies, &ics9xxx_models[j].frequencies, sizeof(ics9xxx_models[i].frequencies))) + pclog("Optimization warning: %s and %s have duplicate tables\n", ics9xxx_models[j].name, ics9xxx_models[i].name); + } } if (dev->model_idx == ICS9xxx_xx) { /* detection device */ - dev->relevant_regs = 1 << 0; /* register 0 matters the most on the detection device */ + dev->relevant_regs = 1 << 0; /* register 0 matters the most on the detection device */ - ics9xxx_detect_reset(dev); + ics9xxx_detect_reset(dev); } else #endif { /* regular device */ - dev->frequencies_ptr = (ics9xxx_frequency_t *) (dev->model->frequencies_ref ? ics9xxx_models[dev->model->frequencies_ref].frequencies : dev->model->frequencies); - if (!dev->frequencies_ptr) - fatal("ICS9xxx: NULL frequency table\n"); - - /* Determine which frequency bits cannot be strapped (register only). */ - uint8_t register_only_bits = 0x00; - for (i = 0; i < sizeof(dev->model->fs_regs) / sizeof(dev->model->fs_regs[0]); i++) { - if (!dev->model->normal_bits_fixed && (dev->model->fs_regs[i].normal_reg < 7)) /* mark a normal, programmable bit as relevant */ - dev->relevant_regs |= 1 << dev->model->fs_regs[i].normal_reg; - if ((dev->model->fs_regs[i].normal_reg == 7) && (dev->model->fs_regs[i].inv_reg == 7)) /* mark as register only */ - register_only_bits |= 1 << i; - } - - /* Mark the hardware select bit's register as relevant, if there's one. */ - if (dev->model->hw_select.normal_reg < 7) - dev->relevant_regs |= 1 << dev->model->hw_select.normal_reg; - - /* Find bus speed match and set default register bits accordingly. */ - dev->bus_match = ics9xxx_find_bus_match(dev, cpu_busspeed, register_only_bits, 0x00); - for (i = 0; i < sizeof(dev->model->fs_regs) / sizeof(dev->model->fs_regs[0]); i++) { - if (dev->model->fs_regs[i].normal_reg < 7) { - if (dev->bus_match & (1 << i)) - dev->regs[dev->model->fs_regs[i].normal_reg] |= 1 << dev->model->fs_regs[i].normal_bit; - else - dev->regs[dev->model->fs_regs[i].normal_reg] &= ~(1 << dev->model->fs_regs[i].normal_bit); - } - if (dev->model->fs_regs[i].inv_reg < 7) { - if (dev->bus_match & (1 << i)) - dev->regs[dev->model->fs_regs[i].inv_reg] &= ~(1 << dev->model->fs_regs[i].inv_bit); - else - dev->regs[dev->model->fs_regs[i].inv_reg] |= 1 << dev->model->fs_regs[i].inv_bit; - } - } + dev->frequencies_ptr = (ics9xxx_frequency_t *) (dev->model->frequencies_ref ? ics9xxx_models[dev->model->frequencies_ref].frequencies : dev->model->frequencies); + if (!dev->frequencies_ptr) + fatal("ICS9xxx: NULL frequency table\n"); + + /* Determine which frequency bits cannot be strapped (register only). */ + uint8_t register_only_bits = 0x00; + for (i = 0; i < sizeof(dev->model->fs_regs) / sizeof(dev->model->fs_regs[0]); i++) { + if (!dev->model->normal_bits_fixed && (dev->model->fs_regs[i].normal_reg < 7)) /* mark a normal, programmable bit as relevant */ + dev->relevant_regs |= 1 << dev->model->fs_regs[i].normal_reg; + if ((dev->model->fs_regs[i].normal_reg == 7) && (dev->model->fs_regs[i].inv_reg == 7)) /* mark as register only */ + register_only_bits |= 1 << i; + } + + /* Mark the hardware select bit's register as relevant, if there's one. */ + if (dev->model->hw_select.normal_reg < 7) + dev->relevant_regs |= 1 << dev->model->hw_select.normal_reg; + + /* Find bus speed match and set default register bits accordingly. */ + dev->bus_match = ics9xxx_find_bus_match(dev, cpu_busspeed, register_only_bits, 0x00); + for (i = 0; i < sizeof(dev->model->fs_regs) / sizeof(dev->model->fs_regs[0]); i++) { + if (dev->model->fs_regs[i].normal_reg < 7) { + if (dev->bus_match & (1 << i)) + dev->regs[dev->model->fs_regs[i].normal_reg] |= 1 << dev->model->fs_regs[i].normal_bit; + else + dev->regs[dev->model->fs_regs[i].normal_reg] &= ~(1 << dev->model->fs_regs[i].normal_bit); + } + if (dev->model->fs_regs[i].inv_reg < 7) { + if (dev->bus_match & (1 << i)) + dev->regs[dev->model->fs_regs[i].inv_reg] &= ~(1 << dev->model->fs_regs[i].inv_bit); + else + dev->regs[dev->model->fs_regs[i].inv_reg] |= 1 << dev->model->fs_regs[i].inv_bit; + } + } } i2c_sethandler(i2c_smbus, 0x69, 1, ics9xxx_start, ics9xxx_read, ics9xxx_write, NULL, dev); @@ -1257,7 +1251,6 @@ ics9xxx_init(const device_t *info) return dev; } - static void ics9xxx_close(void *priv) { @@ -1271,21 +1264,20 @@ ics9xxx_close(void *priv) free(dev); } - device_t * ics9xxx_get(uint8_t model) { device_t *dev = (device_t *) malloc(sizeof(device_t)); memset(dev, 0, sizeof(device_t)); - dev->name = "ICS9xxx-xx Clock Generator"; + dev->name = "ICS9xxx-xx Clock Generator"; dev->local = model; dev->flags = DEVICE_ISA; #ifdef ENABLE_ICS9xxx_DETECT if (model == ICS9xxx_xx) - dev->reset = ics9xxx_detect_reset; + dev->reset = ics9xxx_detect_reset; #endif - dev->init = ics9xxx_init; + dev->init = ics9xxx_init; dev->close = ics9xxx_close; return dev; diff --git a/src/device/hasp.c b/src/device/hasp.c index 60dae74c6..9873c3460 100644 --- a/src/device/hasp.c +++ b/src/device/hasp.c @@ -1,24 +1,24 @@ /* - * 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. + * 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. + * This file is part of the 86Box distribution. * - * HASP parallel port copy protection dongle emulation. + * HASP parallel port copy protection dongle emulation. * - * Based on the MAME driver for Savage Quest. This incomplete - * emulation is enough to satisfy that game, but not Aladdin's - * DiagnostiX utility. + * Based on the MAME driver for Savage Quest. This incomplete + * emulation is enough to satisfy that game, but not Aladdin's + * DiagnostiX utility. * * * - * Author: RichardG, - * Peter Ferrie + * Authors: RichardG, + * Peter Ferrie * - * Copyright 2021 RichardG. - * Copyright Peter Ferrie. + * Copyright 2021 RichardG. + * Copyright Peter Ferrie. */ #include #include @@ -30,14 +30,16 @@ #include <86box/lpt.h> #include <86box/device.h> -#define HASP_BYTEARRAY(...) {__VA_ARGS__} -#define HASP_TYPE(type, password_arr, prodinfo_arr) [type] = { \ - .password = (const uint8_t[]) password_arr, \ - .prodinfo = (const uint8_t[]) prodinfo_arr, \ - .password_size = sizeof((uint8_t[]) password_arr), \ - .prodinfo_size = sizeof((uint8_t[]) prodinfo_arr) \ - }, - +#define HASP_BYTEARRAY(...) \ + { \ + __VA_ARGS__ \ + } +#define HASP_TYPE(type, password_arr, prodinfo_arr) [type] = { \ + .password = (const uint8_t[]) password_arr, \ + .prodinfo = (const uint8_t[]) prodinfo_arr, \ + .password_size = sizeof((uint8_t[]) password_arr), \ + .prodinfo_size = sizeof((uint8_t[]) prodinfo_arr) \ +}, enum { HASP_STATE_NONE = 0, @@ -50,30 +52,35 @@ enum { HASP_TYPE_SAVQUEST = 0 }; - -typedef struct { - const uint8_t *password, *prodinfo; - const uint8_t password_size, prodinfo_size; +typedef struct hasp_type_t { + const uint8_t *password; + const uint8_t *prodinfo; + const uint8_t password_size; + const uint8_t prodinfo_size; } hasp_type_t; typedef struct { - void *lpt; + void *lpt; const hasp_type_t *type; - int index, state, passindex, passmode, prodindex; - uint8_t tmppass[0x29], status; + int index; + int state; + int passindex; + int passmode; + int prodindex; + uint8_t tmppass[0x29]; + uint8_t status; } hasp_t; static const hasp_type_t hasp_types[] = { HASP_TYPE(HASP_TYPE_SAVQUEST, - HASP_BYTEARRAY(0xc3, 0xd9, 0xd3, 0xfb, 0x9d, 0x89, 0xb9, 0xa1, 0xb3, 0xc1, 0xf1, 0xcd, 0xdf, 0x9d), - HASP_BYTEARRAY(0x51, 0x4c, 0x52, 0x4d, 0x53, 0x4e, 0x53, 0x4e, 0x53, 0x49, 0x53, 0x48, 0x53, 0x4b, 0x53, 0x4a, - 0x53, 0x43, 0x53, 0x45, 0x52, 0x46, 0x53, 0x43, 0x53, 0x41, 0xac, 0x40, 0x53, 0xbc, 0x53, 0x42, - 0x53, 0x57, 0x53, 0x5d, 0x52, 0x5e, 0x53, 0x5b, 0x53, 0x59, 0xac, 0x58, 0x53, 0xa4)) + HASP_BYTEARRAY(0xc3, 0xd9, 0xd3, 0xfb, 0x9d, 0x89, 0xb9, 0xa1, 0xb3, 0xc1, 0xf1, 0xcd, 0xdf, 0x9d), + HASP_BYTEARRAY(0x51, 0x4c, 0x52, 0x4d, 0x53, 0x4e, 0x53, 0x4e, 0x53, 0x49, 0x53, 0x48, 0x53, 0x4b, 0x53, 0x4a, + 0x53, 0x43, 0x53, 0x45, 0x52, 0x46, 0x53, 0x43, 0x53, 0x41, 0xac, 0x40, 0x53, 0xbc, 0x53, 0x42, + 0x53, 0x57, 0x53, 0x5d, 0x52, 0x5e, 0x53, 0x5b, 0x53, 0x59, 0xac, 0x58, 0x53, 0xa4)) }; - #ifdef ENABLE_HASP_LOG int hasp_do_log = ENABLE_HASP_LOG; @@ -83,16 +90,15 @@ hasp_log(const char *fmt, ...) va_list ap; if (hasp_do_log) { - va_start(ap, fmt); - pclog_ex(fmt, ap); - va_end(ap); + va_start(ap, fmt); + pclog_ex(fmt, ap); + va_end(ap); } } #else -#define hasp_log(fmt, ...) +# define hasp_log(fmt, ...) #endif - static void hasp_write_data(uint8_t val, void *priv) { @@ -101,161 +107,194 @@ hasp_write_data(uint8_t val, void *priv) hasp_log("HASP: write_data(%02X)\n", val); switch (dev->index) { - case 0: - if (val == 0xc6) - dev->index++; - else - dev->index = 0; - break; + case 0: + if (val == 0xc6) + dev->index++; + else + dev->index = 0; + break; - case 1: - if (val == 0xc7) - dev->index++; - else - dev->index = 0; - break; + case 1: + if (val == 0xc7) + dev->index++; + else + dev->index = 0; + break; - case 2: - if (val == 0xc6) { - dev->index++; - } else { - dev->index = 0; - dev->state = HASP_STATE_NONE; - } - break; + case 2: + if (val == 0xc6) { + dev->index++; + } else { + dev->index = 0; + dev->state = HASP_STATE_NONE; + } + break; - case 3: - dev->index = 0; - if (val == 0x80) { - dev->state = HASP_STATE_PASSWORD_BEGIN; - dev->passindex = 0; - return; - } - break; + case 3: + dev->index = 0; + if (val == 0x80) { + dev->state = HASP_STATE_PASSWORD_BEGIN; + dev->passindex = 0; + return; + } + break; + default: + break; } dev->status = 0; if (dev->state == HASP_STATE_READ) { - /* different passwords cause different values to be returned - but there are really only two passwords of interest - passmode 2 is used to verify that the dongle is responding correctly */ - if (dev->passmode == 2) { - switch (val) { - case 0x94: case 0x9e: case 0xa4: - case 0xb2: case 0xbe: case 0xd0: - return; + /* different passwords cause different values to be returned + but there are really only two passwords of interest + passmode 2 is used to verify that the dongle is responding correctly */ + if (dev->passmode == 2) { + switch (val) { + case 0x94: + case 0x9e: + case 0xa4: + case 0xb2: + case 0xbe: + case 0xd0: + return; - case 0x8a: case 0x8e: case 0xca: case 0xd2: - case 0xe2: case 0xf0: case 0xfc: - /* someone with access to the actual dongle could dump the true values - I've never seen it so I just determined the relevant bits instead - from the disassembly of the software - some of the keys are verified explicitly, the others implicitly - I guessed the implicit ones with a bit of trial and error */ - dev->status = 0x20; - return; - } - } + case 0x8a: + case 0x8e: + case 0xca: + case 0xd2: + case 0xe2: + case 0xf0: + case 0xfc: + /* someone with access to the actual dongle could dump the true values + I've never seen it so I just determined the relevant bits instead + from the disassembly of the software + some of the keys are verified explicitly, the others implicitly + I guessed the implicit ones with a bit of trial and error */ + dev->status = 0x20; + return; + default: + break; + } + } - switch (val) { - /* in passmode 0, some values remain unknown: 8a, 8e (inconclusive), 94, 96, 9a, a4, b2, be, c4, d2, d4 (inconclusive), e2, ec, f8, fc - this is less of a concern since the contents seem to decrypt correctly */ - case 0x88: - case 0x94: case 0x98: case 0x9c: case 0x9e: - case 0xa0: case 0xa4: case 0xaa: case 0xae: - case 0xb0: case 0xb2: case 0xbc: case 0xbe: - case 0xc2: case 0xc6: case 0xc8: case 0xce: - case 0xd0: case 0xd6: case 0xd8: case 0xdc: - case 0xe0: case 0xe6: case 0xea: case 0xee: - case 0xf2: case 0xf6: - /* again, just the relevant bits instead of the true values */ - dev->status = 0x20; - break; - } + switch (val) { + /* in passmode 0, some values remain unknown: 8a, 8e (inconclusive), 94, 96, 9a, a4, b2, be, c4, d2, d4 (inconclusive), e2, ec, f8, fc + this is less of a concern since the contents seem to decrypt correctly */ + case 0x88: + case 0x94: + case 0x98: + case 0x9c: + case 0x9e: + case 0xa0: + case 0xa4: + case 0xaa: + case 0xae: + case 0xb0: + case 0xb2: + case 0xbc: + case 0xbe: + case 0xc2: + case 0xc6: + case 0xc8: + case 0xce: + case 0xd0: + case 0xd6: + case 0xd8: + case 0xdc: + case 0xe0: + case 0xe6: + case 0xea: + case 0xee: + case 0xf2: + case 0xf6: + /* again, just the relevant bits instead of the true values */ + dev->status = 0x20; + break; + default: + break; + } } else if (dev->state == HASP_STATE_PASSWORD_END) { - if (val & 1) { - if ((dev->passmode == 1) && (val == 0x9d)) - dev->passmode = 2; - dev->state = HASP_STATE_READ; - } else if (dev->passmode == 1) { - dev->tmppass[dev->passindex++] = val; + if (val & 1) { + if ((dev->passmode == 1) && (val == 0x9d)) + dev->passmode = 2; + dev->state = HASP_STATE_READ; + } else if (dev->passmode == 1) { + dev->tmppass[dev->passindex++] = val; - if (dev->passindex == sizeof(dev->tmppass)) { - if ((dev->tmppass[0] == 0x9c) && (dev->tmppass[1] == 0x9e)) { - int i = 2; - dev->prodindex = 0; + if (dev->passindex == sizeof(dev->tmppass)) { + if ((dev->tmppass[0] == 0x9c) && (dev->tmppass[1] == 0x9e)) { + int i = 2; + dev->prodindex = 0; - do { - dev->prodindex = (dev->prodindex << 1) + ((dev->tmppass[i] >> 6) & 1); - } while ((i += 3) < sizeof(dev->tmppass)); + do { + dev->prodindex = (dev->prodindex << 1) + ((dev->tmppass[i] >> 6) & 1); + } while ((i += 3) < sizeof(dev->tmppass)); - dev->prodindex = (dev->prodindex - 0xc08) << 4; + dev->prodindex = (dev->prodindex - 0xc08) << 4; - hasp_log("HASP: Password prodindex = %d\n", dev->prodindex); + hasp_log("HASP: Password prodindex = %d\n", dev->prodindex); - if (dev->prodindex < (0x38 << 4)) - dev->passmode = 3; - } + if (dev->prodindex < (0x38 << 4)) + dev->passmode = 3; + } - dev->state = HASP_STATE_READ; - } - } + dev->state = HASP_STATE_READ; + } + } } else if ((dev->state == HASP_STATE_PASSWORD_BEGIN) && (val & 1)) { - dev->tmppass[dev->passindex++] = val; + dev->tmppass[dev->passindex++] = val; - if (dev->passindex == dev->type->password_size) { - dev->state = HASP_STATE_PASSWORD_END; - dev->passindex = 0; - dev->passmode = (int) !memcmp(dev->tmppass, dev->type->password, dev->type->password_size); - hasp_log("HASP: Password comparison result = %d\n", dev->passmode); - } + if (dev->passindex == dev->type->password_size) { + dev->state = HASP_STATE_PASSWORD_END; + dev->passindex = 0; + dev->passmode = (int) !memcmp(dev->tmppass, dev->type->password, dev->type->password_size); + hasp_log("HASP: Password comparison result = %d\n", dev->passmode); + } } } - static uint8_t hasp_read_status(void *priv) { hasp_t *dev = (hasp_t *) priv; if ((dev->state == HASP_STATE_READ) && (dev->passmode == 3)) { - /* passmode 3 is used to retrieve the product(s) information - it comes in two parts: header and product - the header has this format: - offset range purpose - 00 01 header type - 01 01-05 count of used product slots, must be 2 - 02 01-05 count of unused product slots - this is assumed to be 6-(count of used slots) - but it is not enforced here - however a total of 6 structures will be checked - 03 01-02 unknown - 04 01-46 country code - 05-0f 00 reserved - the used product slots have this format: - (the unused product slots must be entirely zeroes) - 00-01 0001-000a product ID, one must be 6, the other 0a - 02 0001-0003 unknown but must be 0001 - 04 01-05 HASP plug country ID - 05 01-02 unknown but must be 01 - 06 05 unknown - 07-0a any unknown, not used - 0b ff unknown - 0c ff unknown - 0d-0f 00 reserved - the read is performed by accessing an array of 16-bit big-endian values - and returning one bit at a time into bit 5 of the result - the 16-bit value is then XORed with 0x534d and the register index */ + /* passmode 3 is used to retrieve the product(s) information + it comes in two parts: header and product + the header has this format: + offset range purpose + 00 01 header type + 01 01-05 count of used product slots, must be 2 + 02 01-05 count of unused product slots + this is assumed to be 6-(count of used slots) + but it is not enforced here + however a total of 6 structures will be checked + 03 01-02 unknown + 04 01-46 country code + 05-0f 00 reserved + the used product slots have this format: + (the unused product slots must be entirely zeroes) + 00-01 0001-000a product ID, one must be 6, the other 0a + 02 0001-0003 unknown but must be 0001 + 04 01-05 HASP plug country ID + 05 01-02 unknown but must be 01 + 06 05 unknown + 07-0a any unknown, not used + 0b ff unknown + 0c ff unknown + 0d-0f 00 reserved + the read is performed by accessing an array of 16-bit big-endian values + and returning one bit at a time into bit 5 of the result + the 16-bit value is then XORed with 0x534d and the register index */ - if (dev->prodindex <= (dev->type->prodinfo_size * 8)) - dev->status = ((dev->type->prodinfo[(dev->prodindex - 1) >> 3] >> ((8 - dev->prodindex) & 7)) & 1) << 5; /* return defined info */ - else - dev->status = (((0x534d ^ ((dev->prodindex - 1) >> 4)) >> ((16 - dev->prodindex) & 15)) & 1) << 5; /* then just alternate between the two key values */ + if (dev->prodindex <= (dev->type->prodinfo_size * 8)) + dev->status = ((dev->type->prodinfo[(dev->prodindex - 1) >> 3] >> ((8 - dev->prodindex) & 7)) & 1) << 5; /* return defined info */ + else + dev->status = (((0x534d ^ ((dev->prodindex - 1) >> 4)) >> ((16 - dev->prodindex) & 15)) & 1) << 5; /* then just alternate between the two key values */ - hasp_log("HASP: Reading %02X from prodindex %d\n", dev->status, dev->prodindex); + hasp_log("HASP: Reading %02X from prodindex %d\n", dev->status, dev->prodindex); - dev->prodindex++; + dev->prodindex++; } hasp_log("HASP: read_status() = %02X\n", dev->status); @@ -263,7 +302,6 @@ hasp_read_status(void *priv) return dev->status; } - static void * hasp_init(void *lpt, int type) { @@ -272,7 +310,7 @@ hasp_init(void *lpt, int type) hasp_log("HASP: init(%d)\n", type); - dev->lpt = lpt; + dev->lpt = lpt; dev->type = &hasp_types[type]; dev->status = 0x80; @@ -280,14 +318,12 @@ hasp_init(void *lpt, int type) return dev; } - static void * hasp_init_savquest(void *lpt) { return hasp_init(lpt, HASP_TYPE_SAVQUEST); } - static void hasp_close(void *priv) { @@ -298,14 +334,14 @@ hasp_close(void *priv) free(dev); } - const lpt_device_t lpt_hasp_savquest_device = { - .name = "Protection Dongle for Savage Quest", - .init = hasp_init_savquest, - .close = hasp_close, - .write_data = hasp_write_data, - .write_ctrl = NULL, - .read_data = NULL, - .read_status = hasp_read_status, - .read_ctrl = NULL + .name = "Protection Dongle for Savage Quest", + .internal_name = "dongle_savquest", + .init = hasp_init_savquest, + .close = hasp_close, + .write_data = hasp_write_data, + .write_ctrl = NULL, + .read_data = NULL, + .read_status = hasp_read_status, + .read_ctrl = NULL }; diff --git a/src/device/hwm.c b/src/device/hwm.c index 83ac74699..85c689740 100644 --- a/src/device/hwm.c +++ b/src/device/hwm.c @@ -1,18 +1,18 @@ /* - * 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. + * 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. + * This file is part of the 86Box distribution. * - * Common functions for hardware monitoring chips. + * Common functions for hardware monitoring chips. * * * - * Author: RichardG, + * Authors: RichardG, * - * Copyright 2020 RichardG. + * Copyright 2020 RichardG. */ #include @@ -27,13 +27,11 @@ #include <86box/machine.h> #include <86box/hwm.h> - /* Refer to specific hardware monitor implementations for the meaning of hwm_values. */ -hwm_values_t hwm_values; - +hwm_values_t hwm_values; uint16_t -hwm_get_vcore() +hwm_get_vcore(void) { /* Determine Vcore for the active CPU. */ return cpu_s->voltage; diff --git a/src/device/hwm_gl518sm.c b/src/device/hwm_gl518sm.c index 67742679a..01f917b32 100644 --- a/src/device/hwm_gl518sm.c +++ b/src/device/hwm_gl518sm.c @@ -1,18 +1,18 @@ /* - * 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. + * 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. + * This file is part of the 86Box distribution. * - * Emulation of the Genesys Logic GL518SM hardware monitoring chip. + * Emulation of the Genesys Logic GL518SM hardware monitoring chip. * * * - * Author: RichardG, + * Authors: RichardG, * - * Copyright 2020 RichardG. + * Copyright 2020 RichardG. */ #include #include @@ -27,73 +27,69 @@ #include <86box/io.h> #include <86box/i2c.h> #include <86box/hwm.h> +#include <86box/plat_unused.h> - -#define CLAMP(a, min, max) (((a) < (min)) ? (min) : (((a) > (max)) ? (max) : (a))) + +#define CLAMP(a, min, max) (((a) < (min)) ? (min) : (((a) > (max)) ? (max) : (a))) /* Formulas and factors derived from Linux's gl518sm.c driver. */ -#define GL518SM_RPMDIV(r, d) (CLAMP((r), 1, 960000) * (d)) -#define GL518SM_RPM_TO_REG(r, d) ((r) ? CLAMP((480000 + GL518SM_RPMDIV(r, d) / 2) / GL518SM_RPMDIV(r, d), 1, 255) : 0) -#define GL518SM_VOLTAGE_TO_REG(v) ((uint8_t) round((v) / 19.0)) -#define GL518SM_VDD_TO_REG(v) ((uint8_t) (((v) * 4) / 95.0)) +#define GL518SM_RPM_TO_REG(r, d) ((r) ? CLAMP((480000 + (r) * (d) / 2) / (r) * (d), 1, 255) : 0) +#define GL518SM_VOLTAGE_TO_REG(v) ((uint8_t) round((v) / 19.0)) +#define GL518SM_VDD_TO_REG(v) ((uint8_t) (((v) *4) / 95.0)) - -typedef struct { - uint32_t local; - hwm_values_t *values; +typedef struct gl518sm_t { + uint32_t local; + hwm_values_t *values; uint16_t regs[32]; - uint8_t addr_register: 5; + uint8_t addr_register : 5; - uint8_t i2c_addr: 7, i2c_state: 2, i2c_enabled: 1; + uint8_t i2c_addr : 7; + uint8_t i2c_state : 2; + uint8_t i2c_enabled : 1; } gl518sm_t; - -static uint8_t gl518sm_i2c_start(void *bus, uint8_t addr, uint8_t read, void *priv); -static uint8_t gl518sm_i2c_read(void *bus, uint8_t addr, void *priv); -static uint16_t gl518sm_read(gl518sm_t *dev, uint8_t reg); -static uint8_t gl518sm_i2c_write(void *bus, uint8_t addr, uint8_t data, void *priv); -static uint8_t gl518sm_write(gl518sm_t *dev, uint8_t reg, uint16_t val); -static void gl518sm_reset(gl518sm_t *dev); - +static uint8_t gl518sm_i2c_start(void *bus, uint8_t addr, uint8_t read, void *priv); +static uint8_t gl518sm_i2c_read(void *bus, uint8_t addr, void *priv); +static uint16_t gl518sm_read(gl518sm_t *dev, uint8_t reg); +static uint8_t gl518sm_i2c_write(void *bus, uint8_t addr, uint8_t data, void *priv); +static uint8_t gl518sm_write(gl518sm_t *dev, uint8_t reg, uint16_t val); +static void gl518sm_reset(gl518sm_t *dev); #ifdef ENABLE_GL518SM_LOG int gl518sm_do_log = ENABLE_GL518SM_LOG; - static void gl518sm_log(const char *fmt, ...) { va_list ap; if (gl518sm_do_log) { - va_start(ap, fmt); - pclog_ex(fmt, ap); - va_end(ap); + va_start(ap, fmt); + pclog_ex(fmt, ap); + va_end(ap); } } #else -#define gl518sm_log(fmt, ...) +# define gl518sm_log(fmt, ...) #endif - static void gl518sm_remap(gl518sm_t *dev, uint8_t addr) { gl518sm_log("GL518SM: remapping to SMBus %02Xh\n", addr); if (dev->i2c_enabled) - i2c_removehandler(i2c_smbus, dev->i2c_addr, 1, gl518sm_i2c_start, gl518sm_i2c_read, gl518sm_i2c_write, NULL, dev); + i2c_removehandler(i2c_smbus, dev->i2c_addr, 1, gl518sm_i2c_start, gl518sm_i2c_read, gl518sm_i2c_write, NULL, dev); if (addr < 0x80) - i2c_sethandler(i2c_smbus, addr, 1, gl518sm_i2c_start, gl518sm_i2c_read, gl518sm_i2c_write, NULL, dev); + i2c_sethandler(i2c_smbus, addr, 1, gl518sm_i2c_start, gl518sm_i2c_read, gl518sm_i2c_write, NULL, dev); - dev->i2c_addr = addr & 0x7f; + dev->i2c_addr = addr & 0x7f; dev->i2c_enabled = !(addr & 0x80); } - static uint8_t -gl518sm_i2c_start(void *bus, uint8_t addr, uint8_t read, void *priv) +gl518sm_i2c_start(UNUSED(void *bus), UNUSED(uint8_t addr), UNUSED(uint8_t read), void *priv) { gl518sm_t *dev = (gl518sm_t *) priv; @@ -102,29 +98,27 @@ gl518sm_i2c_start(void *bus, uint8_t addr, uint8_t read, void *priv) return 1; } - static uint8_t -gl518sm_i2c_read(void *bus, uint8_t addr, void *priv) +gl518sm_i2c_read(UNUSED(void *bus), UNUSED(uint8_t addr), void *priv) { - gl518sm_t *dev = (gl518sm_t *) priv; - uint16_t read = gl518sm_read(dev, dev->addr_register); - uint8_t ret = 0; + gl518sm_t *dev = (gl518sm_t *) priv; + uint16_t read = gl518sm_read(dev, dev->addr_register); + uint8_t ret = 0; if (dev->i2c_state == 0) - dev->i2c_state = 1; + dev->i2c_state = 1; if ((dev->i2c_state == 1) && (dev->addr_register >= 0x07) && (dev->addr_register <= 0x0c)) { /* two-byte registers: read MSB first */ - dev->i2c_state = 2; - ret = read >> 8; + dev->i2c_state = 2; + ret = read >> 8; } else { - ret = read; - dev->addr_register++; + ret = read; + dev->addr_register++; } return ret; } - static uint16_t gl518sm_read(gl518sm_t *dev, uint8_t reg) { @@ -133,34 +127,34 @@ gl518sm_read(gl518sm_t *dev, uint8_t reg) reg &= 0x1f; switch (reg) { - case 0x04: /* temperature */ - ret = (dev->values->temperatures[0] + 119) & 0xff; - break; + case 0x04: /* temperature */ + ret = (dev->values->temperatures[0] + 119) & 0xff; + break; - case 0x07: /* fan speeds */ - ret = GL518SM_RPM_TO_REG(dev->values->fans[0], 1 << ((dev->regs[0x0f] >> 6) & 0x3)) << 8; - ret |= GL518SM_RPM_TO_REG(dev->values->fans[1], 1 << ((dev->regs[0x0f] >> 4) & 0x3)); - break; + case 0x07: /* fan speeds */ + ret = GL518SM_RPM_TO_REG(dev->values->fans[0], 1 << ((dev->regs[0x0f] >> 6) & 0x3)) << 8; + ret |= GL518SM_RPM_TO_REG(dev->values->fans[1], 1 << ((dev->regs[0x0f] >> 4) & 0x3)); + break; - case 0x0d: /* VIN3 */ - ret = GL518SM_VOLTAGE_TO_REG(dev->values->voltages[2]); - break; + case 0x0d: /* VIN3 */ + ret = GL518SM_VOLTAGE_TO_REG(dev->values->voltages[2]); + break; - case 0x13: /* VIN2 */ - ret = GL518SM_VOLTAGE_TO_REG(dev->values->voltages[1]); - break; + case 0x13: /* VIN2 */ + ret = GL518SM_VOLTAGE_TO_REG(dev->values->voltages[1]); + break; - case 0x14: /* VIN1 */ - ret = GL518SM_VOLTAGE_TO_REG(dev->values->voltages[0]); - break; + case 0x14: /* VIN1 */ + ret = GL518SM_VOLTAGE_TO_REG(dev->values->voltages[0]); + break; - case 0x15: /* VDD */ - ret = GL518SM_VDD_TO_REG(dev->values->voltages[3]); - break; + case 0x15: /* VDD */ + ret = GL518SM_VDD_TO_REG(dev->values->voltages[3]); + break; - default: /* other registers */ - ret = dev->regs[reg]; - break; + default: /* other registers */ + ret = dev->regs[reg]; + break; } gl518sm_log("GL518SM: read(%02X) = %04X\n", reg, ret); @@ -168,72 +162,77 @@ gl518sm_read(gl518sm_t *dev, uint8_t reg) return ret; } - static uint8_t -gl518sm_i2c_write(void *bus, uint8_t addr, uint8_t data, void *priv) +gl518sm_i2c_write(UNUSED(void *bus), UNUSED(uint8_t addr), uint8_t data, void *priv) { gl518sm_t *dev = (gl518sm_t *) priv; switch (dev->i2c_state++) { - case 0: - dev->addr_register = data; - break; + case 0: + dev->addr_register = data; + break; - case 1: - gl518sm_write(dev, dev->addr_register, (gl518sm_read(dev, dev->addr_register) & 0xff00) | data); - break; + case 1: + gl518sm_write(dev, dev->addr_register, (gl518sm_read(dev, dev->addr_register) & 0xff00) | data); + break; - case 2: - gl518sm_write(dev, dev->addr_register, (gl518sm_read(dev, dev->addr_register) << 8) | data); - break; + case 2: + gl518sm_write(dev, dev->addr_register, (gl518sm_read(dev, dev->addr_register) << 8) | data); + break; - default: - dev->i2c_state = 3; - return 0; + default: + dev->i2c_state = 3; + return 0; } return 1; } - static uint8_t gl518sm_write(gl518sm_t *dev, uint8_t reg, uint16_t val) { gl518sm_log("GL518SM: write(%02X, %04X)\n", reg, val); switch (reg) { - case 0x00: case 0x01: case 0x04: case 0x07: case 0x0d: case 0x12: case 0x13: case 0x14: case 0x15: - /* read-only registers */ - return 0; + case 0x00: + case 0x01: + case 0x04: + case 0x07: + case 0x0d: + case 0x12: + case 0x13: + case 0x14: + case 0x15: + /* read-only registers */ + return 0; - case 0x0a: - dev->regs[0x13] = val & 0xff; - break; + case 0x0a: + dev->regs[0x13] = val & 0xff; + break; - case 0x03: - dev->regs[reg] = val & 0xfc; + case 0x03: + dev->regs[reg] = val & 0xfc; - if (val & 0x80) /* Init */ - gl518sm_reset(dev); - break; + if (val & 0x80) /* Init */ + gl518sm_reset(dev); + break; - case 0x0f: - dev->regs[reg] = val & 0xf8; - break; + case 0x0f: + dev->regs[reg] = val & 0xf8; + break; - case 0x11: - dev->regs[reg] = val & 0x7f; - break; + case 0x11: + dev->regs[reg] = val & 0x7f; + break; - default: - dev->regs[reg] = val; - break; + default: + dev->regs[reg] = val; + break; } return 1; } - static void gl518sm_reset(gl518sm_t *dev) { @@ -253,7 +252,6 @@ gl518sm_reset(gl518sm_t *dev) gl518sm_remap(dev, dev->i2c_addr | (dev->i2c_enabled ? 0x00 : 0x80)); } - static void gl518sm_close(void *priv) { @@ -264,7 +262,6 @@ gl518sm_close(void *priv) free(dev); } - static void * gl518sm_init(const device_t *info) { @@ -272,22 +269,27 @@ gl518sm_init(const device_t *info) memset(dev, 0, sizeof(gl518sm_t)); dev->local = info->local; - + /* Set default values. */ hwm_values_t defaults = { - { /* fan speeds */ - 3000, /* usually Chassis */ - 3000 /* usually CPU */ - }, { /* temperatures */ - 30 /* usually CPU */ - }, { /* voltages */ - hwm_get_vcore(), /* Vcore */ - RESISTOR_DIVIDER(12000, 150, 47), /* +12V (15K/4.7K divider suggested in the datasheet) */ - 3300, /* +3.3V */ - 5000 /* +5V */ - } + { + /* fan speeds */ + 3000, /* usually Chassis */ + 3000 /* usually CPU */ + }, + { + /* temperatures */ + 30 /* usually CPU */ + }, + { + /* voltages */ + hwm_get_vcore(), /* Vcore */ + RESISTOR_DIVIDER(12000, 150, 47), /* +12V (15K/4.7K divider suggested in the datasheet) */ + 3300, /* +3.3V */ + 5000 /* +5V */ + } }; - hwm_values = defaults; + hwm_values = defaults; dev->values = &hwm_values; gl518sm_reset(dev); @@ -296,25 +298,32 @@ gl518sm_init(const device_t *info) return dev; } - /* GL518SM on SMBus address 2Ch */ const device_t gl518sm_2c_device = { - "Genesys Logic GL518SM Hardware Monitor", - "gl518sm_2c", - DEVICE_ISA, - 0x2c, - gl518sm_init, gl518sm_close, NULL, - { NULL }, NULL, NULL, - NULL + .name = "Genesys Logic GL518SM Hardware Monitor", + .internal_name = "gl518sm_2c", + .flags = DEVICE_ISA, + .local = 0x2c, + .init = gl518sm_init, + .close = gl518sm_close, + .reset = NULL, + { .available = NULL }, + .speed_changed = NULL, + .force_redraw = NULL, + .config = NULL }; /* GL518SM on SMBus address 2Dh */ const device_t gl518sm_2d_device = { - "Genesys Logic GL518SM Hardware Monitor", - "gl518sm_2d", - DEVICE_ISA, - 0x2d, - gl518sm_init, gl518sm_close, NULL, - { NULL }, NULL, NULL, - NULL + .name = "Genesys Logic GL518SM Hardware Monitor", + .internal_name = "gl518sm_2d", + .flags = DEVICE_ISA, + .local = 0x2d, + .init = gl518sm_init, + .close = gl518sm_close, + .reset = NULL, + { .available = NULL }, + .speed_changed = NULL, + .force_redraw = NULL, + .config = NULL }; diff --git a/src/device/hwm_lm75.c b/src/device/hwm_lm75.c index f9bfa397b..14b638365 100644 --- a/src/device/hwm_lm75.c +++ b/src/device/hwm_lm75.c @@ -1,18 +1,18 @@ /* - * 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. + * 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. + * This file is part of the 86Box distribution. * - * Emulation of the National Semiconductor LM75 temperature sensor chip. + * Emulation of the National Semiconductor LM75 temperature sensor chip. * * * - * Author: RichardG, + * Authors: RichardG, * - * Copyright 2020 RichardG. + * Copyright 2020 RichardG. */ #include #include @@ -25,33 +25,30 @@ #include <86box/device.h> #include <86box/i2c.h> #include <86box/hwm.h> +#include <86box/plat_unused.h> - -#define LM75_TEMP_TO_REG(t) ((t) << 8) - +#define LM75_TEMP_TO_REG(t) ((t) << 8) #ifdef ENABLE_LM75_LOG int lm75_do_log = ENABLE_LM75_LOG; - static void lm75_log(const char *fmt, ...) { va_list ap; if (lm75_do_log) { - va_start(ap, fmt); - pclog_ex(fmt, ap); - va_end(ap); + va_start(ap, fmt); + pclog_ex(fmt, ap); + va_end(ap); } } #else -#define lm75_log(fmt, ...) +# define lm75_log(fmt, ...) #endif - static uint8_t -lm75_i2c_start(void *bus, uint8_t addr, uint8_t read, void *priv) +lm75_i2c_start(UNUSED(void *bus), UNUSED(uint8_t addr), UNUSED(uint8_t read), void *priv) { lm75_t *dev = (lm75_t *) priv; @@ -60,65 +57,64 @@ lm75_i2c_start(void *bus, uint8_t addr, uint8_t read, void *priv) return 1; } - uint8_t lm75_read(lm75_t *dev, uint8_t reg) { uint8_t ret; if ((reg & 0x7) == 0x0) /* temperature high byte */ - ret = LM75_TEMP_TO_REG(dev->values->temperatures[dev->local >> 8]) >> 8; + ret = LM75_TEMP_TO_REG(dev->values->temperatures[dev->local >> 8]) >> 8; else if ((reg & 0x7) == 0x1) /* temperature low byte */ - ret = LM75_TEMP_TO_REG(dev->values->temperatures[dev->local >> 8]); + ret = LM75_TEMP_TO_REG(dev->values->temperatures[dev->local >> 8]); else - ret = dev->regs[reg & 0x7]; + ret = dev->regs[reg & 0x7]; lm75_log("LM75: read(%02X) = %02X\n", reg, ret); return ret; } - static uint8_t -lm75_i2c_read(void *bus, uint8_t addr, void *priv) +lm75_i2c_read(UNUSED(void *bus), UNUSED(uint8_t addr), void *priv) { lm75_t *dev = (lm75_t *) priv; uint8_t ret = 0; if (dev->i2c_state == 0) - dev->i2c_state = 1; + dev->i2c_state = 1; /* The AS99127F hardware monitor uses its primary LM75 device's address to access some of its proprietary registers. Pass this operation on to the main monitor code, if necessary. */ if ((dev->addr_register & 0x80) && dev->as99127f) { - ret = lm78_as99127f_read(dev->as99127f, dev->addr_register); + ret = lm78_as99127f_read(dev->as99127f, dev->addr_register); } else { - switch (dev->addr_register & 0x3) { - case 0x0: /* temperature */ - ret = lm75_read(dev, (dev->i2c_state == 1) ? 0x0 : 0x1); - break; + switch (dev->addr_register & 0x3) { + case 0x0: /* temperature */ + ret = lm75_read(dev, (dev->i2c_state == 1) ? 0x0 : 0x1); + break; - case 0x1: /* configuration */ - ret = lm75_read(dev, 0x2); - break; + case 0x1: /* configuration */ + ret = lm75_read(dev, 0x2); + break; - case 0x2: /* Thyst */ - ret = lm75_read(dev, (dev->i2c_state == 1) ? 0x3 : 0x4); - break; - case 0x3: /* Tos */ - ret = lm75_read(dev, (dev->i2c_state == 1) ? 0x5 : 0x6); - break; - } + case 0x2: /* Thyst */ + ret = lm75_read(dev, (dev->i2c_state == 1) ? 0x3 : 0x4); + break; + case 0x3: /* Tos */ + ret = lm75_read(dev, (dev->i2c_state == 1) ? 0x5 : 0x6); + break; + default: + break; + } } if (dev->i2c_state < 2) - dev->i2c_state++; + dev->i2c_state++; return ret; } - uint8_t lm75_write(lm75_t *dev, uint8_t reg, uint8_t val) { @@ -127,77 +123,77 @@ lm75_write(lm75_t *dev, uint8_t reg, uint8_t val) uint8_t reg_idx = (reg & 0x7); if ((reg_idx <= 0x1) || (reg_idx == 0x7)) - return 0; /* read-only registers */ + return 0; /* read-only registers */ dev->regs[reg_idx] = val; return 1; } - static uint8_t -lm75_i2c_write(void *bus, uint8_t addr, uint8_t data, void *priv) +lm75_i2c_write(UNUSED(void *bus), UNUSED(uint8_t addr), uint8_t data, void *priv) { lm75_t *dev = (lm75_t *) priv; if ((dev->i2c_state > 2) || ((dev->i2c_state == 2) && ((dev->addr_register & 0x3) == 0x1))) { - return 0; + return 0; } else if (dev->i2c_state == 0) { - dev->i2c_state = 1; - /* Linux lm75.c driver relies on the address register not changing if bit 2 is set. */ - if (((dev->addr_register & 0x80) && dev->as99127f) || !(data & 0x04)) - dev->addr_register = data; - return 1; + dev->i2c_state = 1; + /* Linux lm75.c driver relies on the address register not changing if bit 2 is set. */ + if (((dev->addr_register & 0x80) && dev->as99127f) || !(data & 0x04)) + dev->addr_register = data; + return 1; } /* The AS99127F hardware monitor uses its primary LM75 device's address to access some of its proprietary registers. Pass this operation on to the main monitor code, if necessary. */ if ((dev->addr_register & 0x80) && dev->as99127f) { - return lm78_as99127f_write(dev->as99127f, dev->addr_register, data); + return lm78_as99127f_write(dev->as99127f, dev->addr_register, data); } else { - switch (dev->addr_register & 0x3) { - case 0x0: /* temperature */ - lm75_write(dev, (dev->i2c_state == 1) ? 0x0 : 0x1, data); - break; + switch (dev->addr_register & 0x3) { + case 0x0: /* temperature */ + lm75_write(dev, (dev->i2c_state == 1) ? 0x0 : 0x1, data); + break; - case 0x1: /* configuration */ - lm75_write(dev, 0x2, data); - break; + case 0x1: /* configuration */ + lm75_write(dev, 0x2, data); + break; - case 0x2: /* Thyst */ - lm75_write(dev, (dev->i2c_state == 1) ? 0x3 : 0x4, data); - break; + case 0x2: /* Thyst */ + lm75_write(dev, (dev->i2c_state == 1) ? 0x3 : 0x4, data); + break; - case 0x3: /* Tos */ - lm75_write(dev, (dev->i2c_state == 1) ? 0x5 : 0x6, data); - break; - } + case 0x3: /* Tos */ + lm75_write(dev, (dev->i2c_state == 1) ? 0x5 : 0x6, data); + break; + + default: + break; + } } if (dev->i2c_state == 1) - dev->i2c_state = 2; + dev->i2c_state = 2; return 1; } - void lm75_remap(lm75_t *dev, uint8_t addr) { lm75_log("LM75: remapping to SMBus %02Xh\n", addr); if (dev->i2c_enabled) - i2c_removehandler(i2c_smbus, dev->i2c_addr, 1, lm75_i2c_start, lm75_i2c_read, lm75_i2c_write, NULL, dev); + i2c_removehandler(i2c_smbus, dev->i2c_addr, 1, lm75_i2c_start, lm75_i2c_read, lm75_i2c_write, NULL, dev); if (addr < 0x80) - i2c_sethandler(i2c_smbus, addr, 1, lm75_i2c_start, lm75_i2c_read, lm75_i2c_write, NULL, dev); + i2c_sethandler(i2c_smbus, addr, 1, lm75_i2c_start, lm75_i2c_read, lm75_i2c_write, NULL, dev); - dev->i2c_addr = addr & 0x7f; + dev->i2c_addr = addr & 0x7f; dev->i2c_enabled = !(addr & 0x80); } - static void lm75_reset(lm75_t *dev) { @@ -207,7 +203,6 @@ lm75_reset(lm75_t *dev) lm75_remap(dev, dev->i2c_addr | (dev->i2c_enabled ? 0x00 : 0x80)); } - static void lm75_close(void *priv) { @@ -218,7 +213,6 @@ lm75_close(void *priv) free(dev); } - static void * lm75_init(const device_t *info) { @@ -229,10 +223,10 @@ lm75_init(const device_t *info) /* Set default value. */ if (dev->local) - hwm_values.temperatures[dev->local >> 8] = 30; + hwm_values.temperatures[dev->local >> 8] = 30; dev->values = &hwm_values; - dev->i2c_addr = dev->local & 0x7f; + dev->i2c_addr = dev->local & 0x7f; dev->i2c_enabled = 1; lm75_reset(dev); @@ -240,27 +234,33 @@ lm75_init(const device_t *info) return dev; } - /* LM75 on SMBus address 4Ah, reporting temperatures[1]. */ const device_t lm75_1_4a_device = { - "National Semiconductor LM75 Temperature Sensor", - "lm75_1_4a", - DEVICE_ISA, - 0x14a, - lm75_init, lm75_close, NULL, - { NULL }, NULL, NULL, - NULL + .name = "National Semiconductor LM75 Temperature Sensor", + .internal_name = "lm75_1_4a", + .flags = DEVICE_ISA, + .local = 0x14a, + .init = lm75_init, + .close = lm75_close, + .reset = NULL, + { .available = NULL }, + .speed_changed = NULL, + .force_redraw = NULL, + .config = NULL }; - /* LM75 secondary/tertiary temperature sensors built into the Winbond W83781D family. Not to be used stand-alone. */ const device_t lm75_w83781d_device = { - "Winbond W83781D Secondary Temperature Sensor", - "lm75_w83781d", - DEVICE_ISA, - 0, - lm75_init, lm75_close, NULL, - { NULL }, NULL, NULL, - NULL + .name = "Winbond W83781D Secondary Temperature Sensor", + .internal_name = "lm75_w83781d", + .flags = DEVICE_ISA, + .local = 0, + .init = lm75_init, + .close = lm75_close, + .reset = NULL, + { .available = NULL }, + .speed_changed = NULL, + .force_redraw = NULL, + .config = NULL }; diff --git a/src/device/hwm_lm78.c b/src/device/hwm_lm78.c index b49807bff..f3003db26 100644 --- a/src/device/hwm_lm78.c +++ b/src/device/hwm_lm78.c @@ -1,18 +1,18 @@ /* - * 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. + * 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. + * This file is part of the 86Box distribution. * - * Emulation of the National Semiconductor LM78 hardware monitoring chip. + * Emulation of the National Semiconductor LM78 hardware monitoring chip. * * * - * Author: RichardG, + * Authors: RichardG, * - * Copyright 2020 RichardG. + * Copyright 2020 RichardG. */ #include #include @@ -27,101 +27,99 @@ #include <86box/timer.h> #include <86box/machine.h> #include <86box/nvr.h> +#include <86box/plat_fallthrough.h> +#include <86box/plat_unused.h> #include "cpu.h" #include <86box/i2c.h> #include <86box/hwm.h> +#define LM78_I2C 0x010000 +#define LM78_W83781D 0x020000 +#define LM78_AS99127F_REV1 0x040000 +#define LM78_AS99127F_REV2 0x080000 +#define LM78_W83782D 0x100000 +#define LM78_P5A 0x200000 +#define LM78_AS99127F (LM78_AS99127F_REV1 | LM78_AS99127F_REV2) /* mask covering both _REV1 and _REV2 */ +#define LM78_WINBOND (LM78_W83781D | LM78_AS99127F | LM78_W83782D) /* mask covering all Winbond variants */ +#define LM78_WINBOND_VENDOR_ID ((dev->local & LM78_AS99127F_REV1) ? 0x12c3 : 0x5ca3) +#define LM78_WINBOND_BANK (dev->regs[0x4e] & 0x07) -#define LM78_I2C 0x010000 -#define LM78_W83781D 0x020000 -#define LM78_AS99127F_REV1 0x040000 -#define LM78_AS99127F_REV2 0x080000 -#define LM78_W83782D 0x100000 -#define LM78_P5A 0x200000 -#define LM78_AS99127F (LM78_AS99127F_REV1 | LM78_AS99127F_REV2) /* mask covering both _REV1 and _REV2 */ -#define LM78_WINBOND (LM78_W83781D | LM78_AS99127F | LM78_W83782D) /* mask covering all Winbond variants */ -#define LM78_WINBOND_VENDOR_ID ((dev->local & LM78_AS99127F_REV1) ? 0x12c3 : 0x5ca3) -#define LM78_WINBOND_BANK (dev->regs[0x4e] & 0x07) +#define CLAMP(a, min, max) (((a) < (min)) ? (min) : (((a) > (max)) ? (max) : (a))) +#define LM78_RPM_TO_REG(r, d) ((r) ? CLAMP(1350000 / (r * d), 1, 255) : 0) +#define LM78_VOLTAGE_TO_REG(v) ((v) >> 4) +#define LM78_NEG_VOLTAGE(v, r) (v * (604.0 / ((double) r))) /* negative voltage formula from the W83781D datasheet */ +#define LM78_NEG_VOLTAGE2(v, r) (((3600 + v) * (((double) r) / (((double) r) + 56.0))) - v) /* negative voltage formula from the W83782D datasheet */ -#define CLAMP(a, min, max) (((a) < (min)) ? (min) : (((a) > (max)) ? (max) : (a))) -#define LM78_RPM_TO_REG(r, d) ((r) ? CLAMP(1350000 / (r * d), 1, 255) : 0) -#define LM78_VOLTAGE_TO_REG(v) ((v) >> 4) -#define LM78_NEG_VOLTAGE(v, r) (v * (604.0 / ((double) r))) /* negative voltage formula from the W83781D datasheet */ -#define LM78_NEG_VOLTAGE2(v, r) (((3600 + v) * (((double) r) / (((double) r) + 56.0))) - v) /* negative voltage formula from the W83782D datasheet */ - - -typedef struct { - uint32_t local; +typedef struct lm78_t { + uint32_t local; hwm_values_t *values; - device_t *lm75[2]; - pc_timer_t reset_timer; + device_t *lm75[2]; + pc_timer_t reset_timer; - uint8_t regs[256]; + uint8_t regs[256]; union { - struct { - uint8_t regs[2][16]; - } w83782d; - struct { - uint8_t regs[3][128]; + struct w83782d { + uint8_t regs[2][16]; + } w83782d; + struct as99127f { + uint8_t regs[3][128]; - uint8_t nvram[1024], nvram_i2c_state: 2, nvram_updated: 1; - uint16_t nvram_addr_register: 10; - int8_t nvram_block_len: 6; + uint8_t nvram[1024], nvram_i2c_state : 2, nvram_updated : 1; + uint16_t nvram_addr_register : 10; + int8_t nvram_block_len : 6; - uint8_t security_i2c_state: 1, security_addr_register: 7; - } as99127f; + uint8_t security_i2c_state : 1, security_addr_register : 7; + } as99127f; }; - uint8_t addr_register, data_register; + uint8_t addr_register; + uint8_t data_register; - uint8_t i2c_addr: 7, i2c_state: 1, i2c_enabled: 1; + uint8_t i2c_addr : 7; + uint8_t i2c_state : 1; + uint8_t i2c_enabled : 1; } lm78_t; - -static void lm78_remap(lm78_t *dev, uint8_t addr); - +static void lm78_remap(lm78_t *dev, uint8_t addr); #ifdef ENABLE_LM78_LOG int lm78_do_log = ENABLE_LM78_LOG; - static void lm78_log(const char *fmt, ...) { va_list ap; if (lm78_do_log) { - va_start(ap, fmt); - pclog_ex(fmt, ap); - va_end(ap); + va_start(ap, fmt); + pclog_ex(fmt, ap); + va_end(ap); } } #else -#define lm78_log(fmt, ...) +# define lm78_log(fmt, ...) #endif - void lm78_nvram(lm78_t *dev, uint8_t save) { - size_t l = strlen(machine_get_internal_name_ex(machine)) + 14; - char *nvr_path = (char *) malloc(l); + size_t l = strlen(machine_get_internal_name_ex(machine)) + 14; + char *nvr_path = (char *) malloc(l); sprintf(nvr_path, "%s_as99127f.nvr", machine_get_internal_name_ex(machine)); - FILE *f = nvr_fopen(nvr_path, save ? "wb" : "rb"); - if (f) { - if (save) - fwrite(&dev->as99127f.nvram, sizeof(dev->as99127f.nvram), 1, f); - else - fread(&dev->as99127f.nvram, sizeof(dev->as99127f.nvram), 1, f); - fclose(f); + FILE *fp = nvr_fopen(nvr_path, save ? "wb" : "rb"); + if (fp) { + if (save) + fwrite(&dev->as99127f.nvram, sizeof(dev->as99127f.nvram), 1, fp); + else + (void) !fread(&dev->as99127f.nvram, sizeof(dev->as99127f.nvram), 1, fp); + fclose(fp); } - + free(nvr_path); } - static uint8_t -lm78_nvram_start(void *bus, uint8_t addr, uint8_t read, void *priv) +lm78_nvram_start(UNUSED(void *bus), UNUSED(uint8_t addr), UNUSED(uint8_t read), void *priv) { lm78_t *dev = (lm78_t *) priv; @@ -130,82 +128,79 @@ lm78_nvram_start(void *bus, uint8_t addr, uint8_t read, void *priv) return 1; } - static uint8_t -lm78_nvram_read(void *bus, uint8_t addr, void *priv) +lm78_nvram_read(UNUSED(void *bus), UNUSED(uint8_t addr), void *priv) { lm78_t *dev = (lm78_t *) priv; uint8_t ret = 0xff; switch (dev->as99127f.nvram_i2c_state) { - case 0: - dev->as99127f.nvram_i2c_state = 1; - /* fall-through */ + case 0: + dev->as99127f.nvram_i2c_state = 1; + fallthrough; - case 1: - ret = dev->as99127f.regs[0][0x0b] & 0x3f; - lm78_log("LM78: nvram_read(blocklen) = %02X\n", ret); - break; + case 1: + ret = dev->as99127f.regs[0][0x0b] & 0x3f; + lm78_log("LM78: nvram_read(blocklen) = %02X\n", ret); + break; - case 2: - ret = dev->as99127f.nvram[dev->as99127f.nvram_addr_register]; - lm78_log("LM78: nvram_read(%03X) = %02X\n", dev->as99127f.nvram_addr_register, ret); + case 2: + ret = dev->as99127f.nvram[dev->as99127f.nvram_addr_register]; + lm78_log("LM78: nvram_read(%03X) = %02X\n", dev->as99127f.nvram_addr_register, ret); - dev->as99127f.nvram_addr_register++; - break; + dev->as99127f.nvram_addr_register++; + break; - default: - lm78_log("LM78: nvram_read(unknown) = %02X\n", ret); - break; + default: + lm78_log("LM78: nvram_read(unknown) = %02X\n", ret); + break; } if (dev->as99127f.nvram_i2c_state < 2) - dev->as99127f.nvram_i2c_state++; + dev->as99127f.nvram_i2c_state++; return ret; } - static uint8_t -lm78_nvram_write(void *bus, uint8_t addr, uint8_t val, void *priv) +lm78_nvram_write(UNUSED(void *bus), uint8_t addr, uint8_t val, void *priv) { lm78_t *dev = (lm78_t *) priv; switch (dev->as99127f.nvram_i2c_state) { - case 0: - lm78_log("LM78: nvram_write(address, %02X)\n", val); - dev->as99127f.nvram_addr_register = (addr << 8) | val; - break; + case 0: + lm78_log("LM78: nvram_write(address, %02X)\n", val); + dev->as99127f.nvram_addr_register = (addr << 8) | val; + break; - case 1: - lm78_log("LM78: nvram_write(blocklen, %02X)\n", val); - dev->as99127f.nvram_block_len = val & 0x3f; - if (dev->as99127f.nvram_block_len <= 0) - dev->as99127f.nvram_i2c_state = 3; - break; + case 1: + lm78_log("LM78: nvram_write(blocklen, %02X)\n", val); + dev->as99127f.nvram_block_len = val & 0x3f; + if (dev->as99127f.nvram_block_len <= 0) + dev->as99127f.nvram_i2c_state = 3; + break; - case 2: - lm78_log("LM78: nvram_write(%03X, %02X)\n", dev->as99127f.nvram_addr_register, val); - dev->as99127f.nvram[dev->as99127f.nvram_addr_register++] = val; - dev->as99127f.nvram_updated = 1; - if (--dev->as99127f.nvram_block_len <= 0) - dev->as99127f.nvram_i2c_state = 3; - break; + case 2: + lm78_log("LM78: nvram_write(%03X, %02X)\n", dev->as99127f.nvram_addr_register, val); + dev->as99127f.nvram[dev->as99127f.nvram_addr_register++] = val; + dev->as99127f.nvram_updated = 1; + if (--dev->as99127f.nvram_block_len <= 0) + dev->as99127f.nvram_i2c_state = 3; + break; - default: - lm78_log("LM78: nvram_write(unknown, %02X)\n", val); - break; + default: + lm78_log("LM78: nvram_write(unknown, %02X)\n", val); + break; } if (dev->as99127f.nvram_i2c_state < 2) - dev->as99127f.nvram_i2c_state++; + dev->as99127f.nvram_i2c_state++; return dev->as99127f.nvram_i2c_state < 3; } - static uint8_t -lm78_security_start(void *bus, uint8_t addr, uint8_t read, void *priv) +lm78_security_start(UNUSED(void *bus), UNUSED(uint8_t addr), UNUSED(uint8_t read), void *priv) { lm78_t *dev = (lm78_t *) priv; @@ -214,42 +209,45 @@ lm78_security_start(void *bus, uint8_t addr, uint8_t read, void *priv) return 1; } - static uint8_t -lm78_security_read(void *bus, uint8_t addr, void *priv) +lm78_security_read(UNUSED(void *bus), UNUSED(uint8_t addr), void *priv) { lm78_t *dev = (lm78_t *) priv; return dev->as99127f.regs[2][dev->as99127f.security_addr_register++]; } - static uint8_t -lm78_security_write(void *bus, uint8_t addr, uint8_t val, void *priv) +lm78_security_write(UNUSED(void *bus), UNUSED(uint8_t addr), uint8_t val, void *priv) { lm78_t *dev = (lm78_t *) priv; if (dev->as99127f.security_i2c_state == 0) { - dev->as99127f.security_i2c_state = 1; - dev->as99127f.security_addr_register = val; + dev->as99127f.security_i2c_state = 1; + dev->as99127f.security_addr_register = val; } else { - switch (dev->as99127f.security_addr_register) { - case 0xe0: case 0xe4: case 0xe5: case 0xe6: case 0xe7: - /* read-only registers */ - return 1; - } + switch (dev->as99127f.security_addr_register) { + case 0xe0: + case 0xe4: + case 0xe5: + case 0xe6: + case 0xe7: + /* read-only registers */ + return 1; + default: + break; + } - dev->as99127f.regs[2][dev->as99127f.security_addr_register++] = val; + dev->as99127f.regs[2][dev->as99127f.security_addr_register++] = val; } return 1; } - static void lm78_reset(void *priv) { - lm78_t *dev = (lm78_t *) priv; + lm78_t *dev = (lm78_t *) priv; uint8_t initialization = dev->regs[0x40] & 0x80; memset(dev->regs, 0, 256); @@ -259,74 +257,73 @@ lm78_reset(void *priv) dev->regs[0x46] = 0x40; dev->regs[0x47] = 0x50; if (dev->local & LM78_I2C) { - if (!initialization) { /* don't reset main I2C address if the reset was triggered by the INITIALIZATION bit */ - if (dev->local & LM78_P5A) - dev->i2c_addr = 0x77; - else - dev->i2c_addr = 0x2d; - dev->i2c_enabled = 1; - } - dev->regs[0x48] = dev->i2c_addr; - if (dev->local & LM78_WINBOND) - dev->regs[0x4a] = 0x01; + if (!initialization) { /* don't reset main I2C address if the reset was triggered by the INITIALIZATION bit */ + if (dev->local & LM78_P5A) + dev->i2c_addr = 0x77; + else + dev->i2c_addr = 0x2d; + dev->i2c_enabled = 1; + } + dev->regs[0x48] = dev->i2c_addr; + if (dev->local & LM78_WINBOND) + dev->regs[0x4a] = 0x01; } else { - dev->regs[0x48] = 0x00; - if (dev->local & LM78_WINBOND) - dev->regs[0x4a] = 0x88; + dev->regs[0x48] = 0x00; + if (dev->local & LM78_WINBOND) + dev->regs[0x4a] = 0x88; } if (dev->local & LM78_WINBOND) { - dev->regs[0x49] = 0x02; - dev->regs[0x4b] = 0x44; - dev->regs[0x4c] = 0x01; - dev->regs[0x4d] = 0x15; - dev->regs[0x4e] = 0x80; - dev->regs[0x4f] = LM78_WINBOND_VENDOR_ID >> 8; - dev->regs[0x57] = 0x80; + dev->regs[0x49] = 0x02; + dev->regs[0x4b] = 0x44; + dev->regs[0x4c] = 0x01; + dev->regs[0x4d] = 0x15; + dev->regs[0x4e] = 0x80; + dev->regs[0x4f] = LM78_WINBOND_VENDOR_ID >> 8; + dev->regs[0x57] = 0x80; - if (dev->local & LM78_AS99127F) { - dev->regs[0x49] = 0x20; - dev->regs[0x4c] = 0x00; - dev->regs[0x56] = 0xff; - dev->regs[0x57] = 0xff; - dev->regs[0x58] = 0x31; - dev->regs[0x59] = 0x8f; - dev->regs[0x5a] = 0x8f; - dev->regs[0x5b] = 0x2a; - dev->regs[0x5c] = 0xe0; - dev->regs[0x5d] = 0x48; - dev->regs[0x5e] = 0xe2; - dev->regs[0x5f] = 0x1f; + if (dev->local & LM78_AS99127F) { + dev->regs[0x49] = 0x20; + dev->regs[0x4c] = 0x00; + dev->regs[0x56] = 0xff; + dev->regs[0x57] = 0xff; + dev->regs[0x58] = 0x31; + dev->regs[0x59] = 0x8f; + dev->regs[0x5a] = 0x8f; + dev->regs[0x5b] = 0x2a; + dev->regs[0x5c] = 0xe0; + dev->regs[0x5d] = 0x48; + dev->regs[0x5e] = 0xe2; + dev->regs[0x5f] = 0x1f; - dev->as99127f.regs[0][0x02] = 0xff; - dev->as99127f.regs[0][0x03] = 0xff; - dev->as99127f.regs[0][0x08] = 0xff; - dev->as99127f.regs[0][0x09] = 0xff; - dev->as99127f.regs[0][0x0b] = 0x01; + dev->as99127f.regs[0][0x02] = 0xff; + dev->as99127f.regs[0][0x03] = 0xff; + dev->as99127f.regs[0][0x08] = 0xff; + dev->as99127f.regs[0][0x09] = 0xff; + dev->as99127f.regs[0][0x0b] = 0x01; - /* regs[1] and regs[2] start at 0x80 */ - dev->as99127f.regs[1][0x00] = 0x88; - dev->as99127f.regs[1][0x01] = 0x10; - dev->as99127f.regs[1][0x03] = 0x02; /* GPO, but things break if GPO16 isn't set */ - dev->as99127f.regs[1][0x04] = 0x01; - dev->as99127f.regs[1][0x05] = 0x1f; - lm78_as99127f_write(dev, 0x06, 0x2f); + /* regs[1] and regs[2] start at 0x80 */ + dev->as99127f.regs[1][0x00] = 0x88; + dev->as99127f.regs[1][0x01] = 0x10; + dev->as99127f.regs[1][0x03] = 0x02; /* GPO, but things break if GPO16 isn't set */ + dev->as99127f.regs[1][0x04] = 0x01; + dev->as99127f.regs[1][0x05] = 0x1f; + lm78_as99127f_write(dev, 0x06, 0x2f); - dev->as99127f.regs[2][0x60] = 0xf0; - } else if (dev->local & LM78_W83781D) { - dev->regs[0x58] = 0x10; - } else if (dev->local & LM78_W83782D) { - dev->regs[0x58] = 0x30; - } + dev->as99127f.regs[2][0x60] = 0xf0; + } else if (dev->local & LM78_W83781D) { + dev->regs[0x58] = 0x10; + } else if (dev->local & LM78_W83782D) { + dev->regs[0x58] = 0x30; + } } else { - dev->regs[0x49] = 0x40; + dev->regs[0x49] = 0x40; } lm78_remap(dev, dev->i2c_addr | (dev->i2c_enabled ? 0x00 : 0x80)); } - static uint8_t -lm78_i2c_start(void *bus, uint8_t addr, uint8_t read, void *priv) +lm78_i2c_start(UNUSED(void *bus), UNUSED(uint8_t addr), UNUSED(uint8_t read), void *priv) { lm78_t *dev = (lm78_t *) priv; @@ -335,49 +332,50 @@ lm78_i2c_start(void *bus, uint8_t addr, uint8_t read, void *priv) return 1; } - static uint8_t lm78_read(lm78_t *dev, uint8_t reg, uint8_t bank) { - uint8_t ret = 0, masked_reg = reg, bankswitched = ((reg & 0xf8) == 0x50); + uint8_t ret = 0; + uint8_t masked_reg = reg; + uint8_t bankswitched = ((reg & 0xf8) == 0x50); lm75_t *lm75; if ((dev->local & LM78_AS99127F) && (bank == 3) && (reg != 0x4e)) { - /* AS99127F additional registers */ - if (!((dev->local & LM78_AS99127F_REV2) && ((reg == 0x80) || (reg == 0x81)))) - ret = dev->as99127f.regs[0][reg & 0x7f]; + /* AS99127F additional registers */ + if (!((dev->local & LM78_AS99127F_REV2) && ((reg == 0x80) || (reg == 0x81)))) + ret = dev->as99127f.regs[0][reg & 0x7f]; } else if (bankswitched && ((bank == 1) || (bank == 2))) { - /* LM75 registers */ - lm75 = device_get_priv(dev->lm75[bank - 1]); - if (lm75) - ret = lm75_read(lm75, reg); + /* LM75 registers */ + lm75 = device_get_priv(dev->lm75[bank - 1]); + if (lm75) + ret = lm75_read(lm75, reg); } else if (bankswitched && ((bank == 4) || (bank == 5) || (bank == 6))) { - /* W83782D additional registers */ - if (dev->local & LM78_W83782D) { - if ((bank == 5) && ((reg == 0x50) || (reg == 0x51))) /* voltages */ - ret = LM78_VOLTAGE_TO_REG(dev->values->voltages[7 + (reg & 1)]); - else if (bank < 6) - ret = dev->w83782d.regs[bank - 4][reg & 0x0f]; - } + /* W83782D additional registers */ + if (dev->local & LM78_W83782D) { + if ((bank == 5) && ((reg == 0x50) || (reg == 0x51))) /* voltages */ + ret = LM78_VOLTAGE_TO_REG(dev->values->voltages[7 + (reg & 1)]); + else if (bank < 6) + ret = dev->w83782d.regs[bank - 4][reg & 0x0f]; + } } else { - /* regular registers */ - if ((reg >= 0x60) && (reg <= 0x94)) /* read auto-increment value RAM registers from their non-auto-increment locations */ - masked_reg = reg & 0x3f; - if ((masked_reg >= 0x20) && (masked_reg <= 0x26)) /* voltages */ - ret = LM78_VOLTAGE_TO_REG(dev->values->voltages[reg & 7]); - else if ((dev->local & LM78_AS99127F) && (masked_reg <= 0x05)) /* AS99127F additional voltages */ - ret = LM78_VOLTAGE_TO_REG(dev->values->voltages[7 + masked_reg]); - else if (masked_reg == 0x27) /* temperature */ - ret = dev->values->temperatures[0]; - else if ((masked_reg >= 0x28) && (masked_reg <= 0x2a)) { /* fan speeds */ - ret = (dev->regs[((reg & 3) == 2) ? 0x4b : 0x47] >> ((reg & 3) ? 6 : 4)) & 0x03; /* bits [1:0] */ - if (dev->local & LM78_W83782D) - ret |= (dev->regs[0x5d] >> (3 + (reg & 3))) & 0x04; /* bit 2 */ - ret = LM78_RPM_TO_REG(dev->values->fans[reg & 3], 1 << ret); - } else if ((reg == 0x4f) && (dev->local & LM78_WINBOND)) /* two-byte vendor ID register */ - ret = (dev->regs[0x4e] & 0x80) ? (uint8_t) (LM78_WINBOND_VENDOR_ID >> 8) : (uint8_t) LM78_WINBOND_VENDOR_ID; - else - ret = dev->regs[masked_reg]; + /* regular registers */ + if ((reg >= 0x60) && (reg <= 0x94)) /* read auto-increment value RAM registers from their non-auto-increment locations */ + masked_reg = reg & 0x3f; + if ((masked_reg >= 0x20) && (masked_reg <= 0x26)) /* voltages */ + ret = LM78_VOLTAGE_TO_REG(dev->values->voltages[reg & 7]); + else if ((dev->local & LM78_AS99127F) && (masked_reg <= 0x05)) /* AS99127F additional voltages */ + ret = LM78_VOLTAGE_TO_REG(dev->values->voltages[7 + masked_reg]); + else if (masked_reg == 0x27) /* temperature */ + ret = dev->values->temperatures[0]; + else if ((masked_reg >= 0x28) && (masked_reg <= 0x2a)) { /* fan speeds */ + ret = (dev->regs[((reg & 3) == 2) ? 0x4b : 0x47] >> ((reg & 3) ? 6 : 4)) & 0x03; /* bits [1:0] */ + if (dev->local & LM78_W83782D) + ret |= (dev->regs[0x5d] >> (3 + (reg & 3))) & 0x04; /* bit 2 */ + ret = LM78_RPM_TO_REG(dev->values->fans[reg & 3], 1 << ret); + } else if ((reg == 0x4f) && (dev->local & LM78_WINBOND)) /* two-byte vendor ID register */ + ret = (dev->regs[0x4e] & 0x80) ? (uint8_t) (LM78_WINBOND_VENDOR_ID >> 8) : (uint8_t) LM78_WINBOND_VENDOR_ID; + else + ret = dev->regs[masked_reg]; } lm78_log("LM78: read(%02X, %d) = %02X\n", reg, bank, ret); @@ -385,7 +383,6 @@ lm78_read(lm78_t *dev, uint8_t reg, uint8_t bank) return ret; } - static uint8_t lm78_isa_read(uint16_t port, void *priv) { @@ -393,52 +390,46 @@ lm78_isa_read(uint16_t port, void *priv) uint8_t ret = 0xff; switch (port & 0x7) { - case 0x5: - ret = dev->addr_register & 0x7f; - break; + case 0x5: + ret = dev->addr_register & 0x7f; + break; - case 0x6: - ret = lm78_read(dev, dev->addr_register, LM78_WINBOND_BANK); + case 0x6: + ret = lm78_read(dev, dev->addr_register, LM78_WINBOND_BANK); - if (((LM78_WINBOND_BANK == 0) && - ((dev->addr_register == 0x41) || (dev->addr_register == 0x43) || (dev->addr_register == 0x45) || (dev->addr_register == 0x56) || - ((dev->addr_register >= 0x60) && (dev->addr_register < 0x94)))) || - ((dev->local & LM78_W83782D) && (LM78_WINBOND_BANK == 5) && (dev->addr_register >= 0x50) && (dev->addr_register < 0x58))) { - /* auto-increment registers */ - dev->addr_register++; - } - break; + if (((LM78_WINBOND_BANK == 0) && ((dev->addr_register == 0x41) || (dev->addr_register == 0x43) || (dev->addr_register == 0x45) || (dev->addr_register == 0x56) || ((dev->addr_register >= 0x60) && (dev->addr_register < 0x94)))) || ((dev->local & LM78_W83782D) && (LM78_WINBOND_BANK == 5) && (dev->addr_register >= 0x50) && (dev->addr_register < 0x58))) { + /* auto-increment registers */ + dev->addr_register++; + } + break; - default: - lm78_log("LM78: Read from unknown ISA port %d\n", port & 0x7); - break; + default: + lm78_log("LM78: Read from unknown ISA port %d\n", port & 0x7); + break; } return ret; } - static uint8_t -lm78_i2c_read(void *bus, uint8_t addr, void *priv) +lm78_i2c_read(UNUSED(void *bus), UNUSED(uint8_t addr), void *priv) { lm78_t *dev = (lm78_t *) priv; return lm78_read(dev, dev->addr_register++, LM78_WINBOND_BANK); } - uint8_t lm78_as99127f_read(void *priv, uint8_t reg) { - lm78_t *dev = (lm78_t *) priv; - uint8_t ret = dev->as99127f.regs[1][reg & 0x7f]; + const lm78_t *dev = (lm78_t *) priv; + uint8_t ret = dev->as99127f.regs[1][reg & 0x7f]; lm78_log("LM78: read(%02X, AS99127F) = %02X\n", reg, ret); return ret; } - static uint8_t lm78_write(lm78_t *dev, uint8_t reg, uint8_t val, uint8_t bank) { @@ -447,174 +438,243 @@ lm78_write(lm78_t *dev, uint8_t reg, uint8_t val, uint8_t bank) lm78_log("LM78: write(%02X, %d, %02X)\n", reg, bank, val); if ((dev->local & LM78_AS99127F) && (bank == 3) && (reg != 0x4e)) { - /* AS99127F additional registers */ - reg &= 0x7f; - switch (reg) { - case 0x00: case 0x01: case 0x04: case 0x05: case 0x06: case 0x07: - /* read-only registers */ - return 0; + /* AS99127F additional registers */ + reg &= 0x7f; + switch (reg) { + case 0x00: + case 0x01: + case 0x04: + case 0x05: + case 0x06: + case 0x07: + /* read-only registers */ + return 0; - case 0x20: - val &= 0x7f; - break; - } + case 0x20: + val &= 0x7f; + break; + default: + break; + } - dev->as99127f.regs[0][reg] = val; - return 1; + dev->as99127f.regs[0][reg] = val; + return 1; } else if ((reg & 0xf8) == 0x50) { - if ((bank == 1) || (bank == 2)) { - /* LM75 registers */ - lm75 = device_get_priv(dev->lm75[bank - 1]); - if (lm75) - return lm75_write(lm75, reg, val); - return 1; - } else if (dev->local & LM78_W83782D) { - /* W83782D additional registers */ - if (bank == 4) { - switch (reg) { - case 0x50: case 0x52: case 0x53: case 0x54: case 0x55: case 0x56: case 0x57: - case 0x58: case 0x59: case 0x5a: case 0x5b: case 0x5d: case 0x5e: case 0x5f: - /* read-only registers */ - return 0; - } + if ((bank == 1) || (bank == 2)) { + /* LM75 registers */ + lm75 = device_get_priv(dev->lm75[bank - 1]); + if (lm75) + return lm75_write(lm75, reg, val); + return 1; + } else if (dev->local & LM78_W83782D) { + /* W83782D additional registers */ + if (bank == 4) { + switch (reg) { + case 0x50: + case 0x52: + case 0x53: + case 0x54: + case 0x55: + case 0x56: + case 0x57: + case 0x58: + case 0x59: + case 0x5a: + case 0x5b: + case 0x5d: + case 0x5e: + case 0x5f: + /* read-only registers */ + return 0; + default: + break; + } - dev->w83782d.regs[0][reg & 0x0f] = val; - return 1; - } else if (bank == 5) { - switch (reg) { - case 0x50: case 0x51: case 0x52: case 0x53: case 0x58: case 0x59: case 0x5a: - case 0x5b: case 0x5c: case 0x5d: case 0x5e: case 0x5f: - /* read-only registers */ - return 0; - } + dev->w83782d.regs[0][reg & 0x0f] = val; + return 1; + } else if (bank == 5) { + switch (reg) { + case 0x50: + case 0x51: + case 0x52: + case 0x53: + case 0x58: + case 0x59: + case 0x5a: + case 0x5b: + case 0x5c: + case 0x5d: + case 0x5e: + case 0x5f: + /* read-only registers */ + return 0; + default: + break; + } - dev->w83782d.regs[1][reg & 0x0f] = val; - return 1; - } else if (bank == 6) { - return 0; - } - } - } + dev->w83782d.regs[1][reg & 0x0f] = val; + return 1; + } else if (bank == 6) { + return 0; + } + } + } /* regular registers */ switch (reg) { - case 0x41: case 0x42: case 0x4f: case 0x58: - case 0x20: case 0x21: case 0x22: case 0x23: case 0x24: case 0x25: case 0x26: case 0x27: case 0x28: case 0x29: case 0x2a: - case 0x60: case 0x61: case 0x62: case 0x63: case 0x64: case 0x65: case 0x66: case 0x67: case 0x68: case 0x69: case 0x6a: - case 0x00: case 0x01: case 0x02: case 0x03: case 0x04: case 0x05: - case 0x80: case 0x81: case 0x82: case 0x83: case 0x84: case 0x85: - /* read-only registers */ - return 0; + case 0x41: + case 0x42: + case 0x4f: + case 0x58: + case 0x20: + case 0x21: + case 0x22: + case 0x23: + case 0x24: + case 0x25: + case 0x26: + case 0x27: + case 0x28: + case 0x29: + case 0x2a: + case 0x60: + case 0x61: + case 0x62: + case 0x63: + case 0x64: + case 0x65: + case 0x66: + case 0x67: + case 0x68: + case 0x69: + case 0x6a: + case 0x00: + case 0x01: + case 0x02: + case 0x03: + case 0x04: + case 0x05: + case 0x80: + case 0x81: + case 0x82: + case 0x83: + case 0x84: + case 0x85: + /* read-only registers */ + return 0; - case 0x4a: case 0x4b: case 0x4c: case 0x4d: case 0x4e: - /* Winbond-only registers */ - if (!(dev->local & LM78_WINBOND)) - return 0; - break; + case 0x4a: + case 0x4b: + case 0x4c: + case 0x4d: + case 0x4e: + /* Winbond-only registers */ + if (!(dev->local & LM78_WINBOND)) + return 0; + break; + default: + break; } if ((reg >= 0x60) && (reg <= 0x94)) /* write auto-increment value RAM registers to their non-auto-increment locations */ - reg &= 0x3f; - uint8_t prev = dev->regs[reg]; + reg &= 0x3f; + uint8_t prev = dev->regs[reg]; dev->regs[reg] = val; switch (reg) { - case 0x40: - if (val & 0x80) /* INITIALIZATION bit resets all registers except main I2C address */ - lm78_reset(dev); - break; + case 0x40: + if (val & 0x80) /* INITIALIZATION bit resets all registers except main I2C address */ + lm78_reset(dev); + break; - case 0x48: - /* set main I2C address */ - if (dev->local & LM78_I2C) - lm78_remap(dev, dev->regs[0x48] & 0x7f); - break; + case 0x48: + /* set main I2C address */ + if (dev->local & LM78_I2C) + lm78_remap(dev, dev->regs[0x48] & 0x7f); + break; - case 0x49: - if (!(dev->local & LM78_WINBOND)) { - if (val & 0x20) /* Chip Reset bit (LM78 only) resets all registers */ - lm78_reset(dev); - else - dev->regs[0x49] = 0x40; - } else { - dev->regs[0x49] &= 0x01; - } - break; + case 0x49: + if (!(dev->local & LM78_WINBOND)) { + if (val & 0x20) /* Chip Reset bit (LM78 only) resets all registers */ + lm78_reset(dev); + else + dev->regs[0x49] = 0x40; + } else { + dev->regs[0x49] &= 0x01; + } + break; - case 0x4a: - /* set LM75 I2C addresses (Winbond only) */ - if (dev->local & LM78_I2C) { - for (uint8_t i = 0; i <= 1; i++) { - lm75 = device_get_priv(dev->lm75[i]); - if (!lm75) - continue; - if (val & (0x08 * (0x10 * i))) /* DIS_T2 and DIS_T3 bit disable those interfaces */ - lm75_remap(lm75, 0x80); - else - lm75_remap(lm75, 0x48 + ((val >> (i * 4)) & 0x7)); - } - } - break; + case 0x4a: + /* set LM75 I2C addresses (Winbond only) */ + if (dev->local & LM78_I2C) { + for (uint8_t i = 0; i <= 1; i++) { + lm75 = device_get_priv(dev->lm75[i]); + if (!lm75) + continue; + if (val & (0x08 * (0x10 * i))) /* DIS_T2 and DIS_T3 bit disable those interfaces */ + lm75_remap(lm75, 0x80); + else + lm75_remap(lm75, 0x48 + ((val >> (i * 4)) & 0x7)); + } + } + break; - case 0x5c: - /* enable/disable AS99127F NVRAM */ - if (dev->local & LM78_AS99127F) { - if (prev & 0x01) - i2c_removehandler(i2c_smbus, (prev & 0xf8) >> 1, 4, lm78_nvram_start, lm78_nvram_read, lm78_nvram_write, NULL, dev); - if (val & 0x01) - i2c_sethandler(i2c_smbus, (val & 0xf8) >> 1, 4, lm78_nvram_start, lm78_nvram_read, lm78_nvram_write, NULL, dev); - } - break; + case 0x5c: + /* enable/disable AS99127F NVRAM */ + if (dev->local & LM78_AS99127F) { + if (prev & 0x01) + i2c_removehandler(i2c_smbus, (prev & 0xf8) >> 1, 4, lm78_nvram_start, lm78_nvram_read, lm78_nvram_write, NULL, dev); + if (val & 0x01) + i2c_sethandler(i2c_smbus, (val & 0xf8) >> 1, 4, lm78_nvram_start, lm78_nvram_read, lm78_nvram_write, NULL, dev); + } + break; + + default: + break; } return 1; } - static void lm78_isa_write(uint16_t port, uint8_t val, void *priv) { lm78_t *dev = (lm78_t *) priv; switch (port & 0x7) { - case 0x5: - dev->addr_register = val & 0x7f; - break; + case 0x5: + dev->addr_register = val & 0x7f; + break; - case 0x6: - lm78_write(dev, dev->addr_register, val, LM78_WINBOND_BANK); + case 0x6: + lm78_write(dev, dev->addr_register, val, LM78_WINBOND_BANK); - if (((LM78_WINBOND_BANK == 0) && - ((dev->addr_register == 0x41) || (dev->addr_register == 0x43) || (dev->addr_register == 0x45) || (dev->addr_register == 0x56) || - ((dev->addr_register >= 0x60) && (dev->addr_register < 0x94)))) || - ((dev->local & LM78_W83782D) && (LM78_WINBOND_BANK == 5) && (dev->addr_register >= 0x50) && (dev->addr_register < 0x58))) { - /* auto-increment registers */ - dev->addr_register++; - } - break; + if (((LM78_WINBOND_BANK == 0) && ((dev->addr_register == 0x41) || (dev->addr_register == 0x43) || (dev->addr_register == 0x45) || (dev->addr_register == 0x56) || ((dev->addr_register >= 0x60) && (dev->addr_register < 0x94)))) || ((dev->local & LM78_W83782D) && (LM78_WINBOND_BANK == 5) && (dev->addr_register >= 0x50) && (dev->addr_register < 0x58))) { + /* auto-increment registers */ + dev->addr_register++; + } + break; - default: - lm78_log("LM78: Write %02X to unknown ISA port %d\n", val, port & 0x7); - break; + default: + lm78_log("LM78: Write %02X to unknown ISA port %d\n", val, port & 0x7); + break; } } - static uint8_t -lm78_i2c_write(void *bus, uint8_t addr, uint8_t val, void *priv) +lm78_i2c_write(UNUSED(void *bus), UNUSED(uint8_t addr), uint8_t val, void *priv) { lm78_t *dev = (lm78_t *) priv; if (dev->i2c_state == 0) { - dev->i2c_state = 1; - dev->addr_register = val; + dev->i2c_state = 1; + dev->addr_register = val; } else - lm78_write(dev, dev->addr_register++, val, LM78_WINBOND_BANK); + lm78_write(dev, dev->addr_register++, val, LM78_WINBOND_BANK); return 1; } - uint8_t lm78_as99127f_write(void *priv, uint8_t reg, uint8_t val) { @@ -623,75 +683,76 @@ lm78_as99127f_write(void *priv, uint8_t reg, uint8_t val) lm78_log("LM78: write(%02X, AS99127F, %02X)\n", reg, val); reg &= 0x7f; - uint8_t prev = dev->as99127f.regs[1][reg]; + uint8_t prev = dev->as99127f.regs[1][reg]; dev->as99127f.regs[1][reg] = val; switch (reg) { - case 0x01: - if (val & 0x40) { - dev->as99127f.regs[1][0x00] = 0x88; - dev->as99127f.regs[1][0x01] &= 0xe0; - dev->as99127f.regs[1][0x03] &= 0xf7; - dev->as99127f.regs[1][0x07] &= 0xfe; - } - if (!(val & 0x10)) { /* CUV4X-LS */ - lm78_log("LM78: Reset requested through AS99127F CLKRST\n"); - timer_set_delay_u64(&dev->reset_timer, 300000 * TIMER_USEC); - } - break; + case 0x01: + if (val & 0x40) { + dev->as99127f.regs[1][0x00] = 0x88; + dev->as99127f.regs[1][0x01] &= 0xe0; + dev->as99127f.regs[1][0x03] &= 0xf7; + dev->as99127f.regs[1][0x07] &= 0xfe; + } + if (!(val & 0x10)) { /* CUV4X-LS */ + lm78_log("LM78: Reset requested through AS99127F CLKRST\n"); + timer_set_delay_u64(&dev->reset_timer, 300000 * TIMER_USEC); + } + break; - case 0x06: - /* security device I2C address */ - i2c_removehandler(i2c_smbus, prev & 0x7f, 1, lm78_security_start, lm78_security_read, lm78_security_write, NULL, dev); - i2c_sethandler(i2c_smbus, val & 0x7f, 1, lm78_security_start, lm78_security_read, lm78_security_write, NULL, dev); - break; + case 0x06: + /* security device I2C address */ + i2c_removehandler(i2c_smbus, prev & 0x7f, 1, lm78_security_start, lm78_security_read, lm78_security_write, NULL, dev); + i2c_sethandler(i2c_smbus, val & 0x7f, 1, lm78_security_start, lm78_security_read, lm78_security_write, NULL, dev); + break; - case 0x07: - if (val & 0x01) { /* other AS99127F boards */ - lm78_log("LM78: Reset requested through AS99127F GPO15\n"); - resetx86(); - } - break; + case 0x07: + if (val & 0x01) { /* other AS99127F boards */ + lm78_log("LM78: Reset requested through AS99127F GPO15\n"); + resetx86(); + } + break; + + default: + break; } return 1; } - static void -lm78_reset_timer(void *priv) +lm78_reset_timer(UNUSED(void *priv)) { pc_reset_hard(); } - static void lm78_remap(lm78_t *dev, uint8_t addr) { lm75_t *lm75; - if (!(dev->local & LM78_I2C)) return; + if (!(dev->local & LM78_I2C)) + return; lm78_log("LM78: remapping to SMBus %02Xh\n", addr); if (dev->i2c_enabled) - i2c_removehandler(i2c_smbus, dev->i2c_addr, 1, lm78_i2c_start, lm78_i2c_read, lm78_i2c_write, NULL, dev); + i2c_removehandler(i2c_smbus, dev->i2c_addr, 1, lm78_i2c_start, lm78_i2c_read, lm78_i2c_write, NULL, dev); if (addr < 0x80) - i2c_sethandler(i2c_smbus, addr, 1, lm78_i2c_start, lm78_i2c_read, lm78_i2c_write, NULL, dev); + i2c_sethandler(i2c_smbus, addr, 1, lm78_i2c_start, lm78_i2c_read, lm78_i2c_write, NULL, dev); - dev->i2c_addr = addr & 0x7f; + dev->i2c_addr = addr & 0x7f; dev->i2c_enabled = !(addr & 0x80); if (dev->local & LM78_AS99127F) { - /* Store our handle on the primary LM75 device to ensure reads/writes - to the AS99127F's proprietary registers are passed through to this side. */ - if ((lm75 = device_get_priv(dev->lm75[0]))) - lm75->as99127f = dev; + /* Store our handle on the primary LM75 device to ensure reads/writes + to the AS99127F's proprietary registers are passed through to this side. */ + if ((lm75 = device_get_priv(dev->lm75[0]))) + lm75->as99127f = dev; } } - static void lm78_close(void *priv) { @@ -699,15 +760,14 @@ lm78_close(void *priv) uint16_t isa_io = dev->local & 0xffff; if (isa_io) - io_removehandler(isa_io, 8, lm78_isa_read, NULL, NULL, lm78_isa_write, NULL, NULL, dev); + io_removehandler(isa_io, 8, lm78_isa_read, NULL, NULL, lm78_isa_write, NULL, NULL, dev); if (dev->as99127f.nvram_updated) - lm78_nvram(dev, 1); + lm78_nvram(dev, 1); free(dev); } - static void * lm78_init(const device_t *info) { @@ -718,140 +778,163 @@ lm78_init(const device_t *info) /* Set global default values. */ hwm_values_t defaults = { - { /* fan speeds */ - 3000, /* usually Chassis, sometimes CPU */ - 3000, /* usually CPU, sometimes Chassis */ - 3000 /* usually PSU, sometimes Chassis */ - }, { /* temperatures */ - 30, /* usually Board, sometimes Chassis */ - 30, /* Winbond only: usually CPU, sometimes Probe */ - 30 /* Winbond only: usually CPU when not the one above */ - }, { /* voltages */ - hwm_get_vcore(), /* Vcore */ - 0, /* sometimes Vtt, Vio or second CPU */ - 3300, /* +3.3V */ - RESISTOR_DIVIDER(5000, 11, 16), /* +5V (divider values bruteforced) */ - RESISTOR_DIVIDER(12000, 28, 10), /* +12V (28K/10K divider suggested in the W83781D datasheet) */ - LM78_NEG_VOLTAGE(12000, 2100), /* -12V */ - LM78_NEG_VOLTAGE(5000, 909), /* -5V */ - RESISTOR_DIVIDER(5000, 51, 75), /* W83782D/AS99127F only: +5VSB (5.1K/7.5K divider suggested in the datasheet) */ - 3000, /* W83782D/AS99127F only: Vbat */ - 2500, /* AS99127F only: +2.5V */ - 1500, /* AS99127F only: +1.5V */ - 3000, /* AS99127F only: NVRAM */ - 3300 /* AS99127F only: +3.3VSB */ - } + { + /* fan speeds */ + 3000, /* usually Chassis, sometimes CPU */ + 3000, /* usually CPU, sometimes Chassis */ + 3000 /* usually PSU, sometimes Chassis */ + }, + { + /* temperatures */ + 30, /* usually Board, sometimes Chassis */ + 30, /* Winbond only: usually CPU, sometimes Probe */ + 30 /* Winbond only: usually CPU when not the one above */ + }, + { + /* voltages */ + hwm_get_vcore(), /* Vcore */ + 0, /* sometimes Vtt, Vio or second CPU */ + 3300, /* +3.3V */ + RESISTOR_DIVIDER(5000, 11, 16), /* +5V (divider values bruteforced) */ + RESISTOR_DIVIDER(12000, 28, 10), /* +12V (28K/10K divider suggested in the W83781D datasheet) */ + LM78_NEG_VOLTAGE(12000, 2100), /* -12V */ + LM78_NEG_VOLTAGE(5000, 909), /* -5V */ + RESISTOR_DIVIDER(5000, 51, 75), /* W83782D/AS99127F only: +5VSB (5.1K/7.5K divider suggested in the datasheet) */ + 3000, /* W83782D/AS99127F only: Vbat */ + 2500, /* AS99127F only: +2.5V */ + 1500, /* AS99127F only: +1.5V */ + 3000, /* AS99127F only: NVRAM */ + 3300 /* AS99127F only: +3.3VSB */ + } }; /* Set chip-specific default values. */ if (dev->local & LM78_AS99127F) { - /* AS99127F: different -12V Rin value (bruteforced) */ - defaults.voltages[5] = LM78_NEG_VOLTAGE(12000, 2400); + /* AS99127F: different -12V Rin value (bruteforced) */ + defaults.voltages[5] = LM78_NEG_VOLTAGE(12000, 2400); - timer_add(&dev->reset_timer, lm78_reset_timer, dev, 0); + timer_add(&dev->reset_timer, lm78_reset_timer, dev, 0); - lm78_nvram(dev, 0); + lm78_nvram(dev, 0); } else if (dev->local & LM78_W83782D) { - /* W83782D: different negative voltage formula */ - defaults.voltages[5] = LM78_NEG_VOLTAGE2(12000, 232); - defaults.voltages[6] = LM78_NEG_VOLTAGE2(5000, 120); + /* W83782D: different negative voltage formula */ + defaults.voltages[5] = LM78_NEG_VOLTAGE2(12000, 232); + defaults.voltages[6] = LM78_NEG_VOLTAGE2(5000, 120); } - hwm_values = defaults; + hwm_values = defaults; dev->values = &hwm_values; /* Initialize secondary/tertiary LM75 sensors on Winbond. */ for (uint8_t i = 0; i <= 1; i++) { - if (dev->local & LM78_WINBOND) { - dev->lm75[i] = (device_t *) malloc(sizeof(device_t)); - memcpy(dev->lm75[i], &lm75_w83781d_device, sizeof(device_t)); - dev->lm75[i]->local = (i + 1) << 8; - if (dev->local & LM78_I2C) - dev->lm75[i]->local |= 0x48 + i; - device_add(dev->lm75[i]); - } else { - dev->lm75[i] = NULL; - } + if (dev->local & LM78_WINBOND) { + dev->lm75[i] = (device_t *) malloc(sizeof(device_t)); + memcpy(dev->lm75[i], &lm75_w83781d_device, sizeof(device_t)); + dev->lm75[i]->local = (i + 1) << 8; + if (dev->local & LM78_I2C) + dev->lm75[i]->local |= 0x48 + i; + device_add(dev->lm75[i]); + } else { + dev->lm75[i] = NULL; + } } lm78_reset(dev); uint16_t isa_io = dev->local & 0xffff; if (isa_io) - io_sethandler(isa_io, 8, lm78_isa_read, NULL, NULL, lm78_isa_write, NULL, NULL, dev); + io_sethandler(isa_io, 8, lm78_isa_read, NULL, NULL, lm78_isa_write, NULL, NULL, dev); return dev; } - /* National Semiconductor LM78 on ISA and SMBus. */ const device_t lm78_device = { - "National Semiconductor LM78 Hardware Monitor", - "lm78", - DEVICE_ISA, - 0x290 | LM78_I2C, - lm78_init, lm78_close, lm78_reset, - { NULL }, NULL, NULL, - NULL + .name = "National Semiconductor LM78 Hardware Monitor", + .internal_name = "lm78", + .flags = DEVICE_ISA, + .local = 0x290 | LM78_I2C, + .init = lm78_init, + .close = lm78_close, + .reset = lm78_reset, + { .available = NULL }, + .speed_changed = NULL, + .force_redraw = NULL, + .config = NULL }; - /* Winbond W83781D on ISA and SMBus. */ const device_t w83781d_device = { - "Winbond W83781D Hardware Monitor", - "w83781d", - DEVICE_ISA, - 0x290 | LM78_I2C | LM78_W83781D, - lm78_init, lm78_close, lm78_reset, - { NULL }, NULL, NULL, - NULL + .name = "Winbond W83781D Hardware Monitor", + .internal_name = "w83781d", + .flags = DEVICE_ISA, + .local = 0x290 | LM78_I2C | LM78_W83781D, + .init = lm78_init, + .close = lm78_close, + .reset = lm78_reset, + { .available = NULL }, + .speed_changed = NULL, + .force_redraw = NULL, + .config = NULL }; - /* Winbond W83781D on ISA and SMBus. */ const device_t w83781d_p5a_device = { - "Winbond W83781D Hardware Monitor (ASUS P5A)", - "w83781d_p5a", - DEVICE_ISA, - 0x290 | LM78_I2C | LM78_W83781D | LM78_P5A, - lm78_init, lm78_close, lm78_reset, - { NULL }, NULL, NULL, - NULL + .name = "Winbond W83781D Hardware Monitor (ASUS P5A)", + .internal_name = "w83781d_p5a", + .flags = DEVICE_ISA, + .local = 0x290 | LM78_I2C | LM78_W83781D | LM78_P5A, + .init = lm78_init, + .close = lm78_close, + .reset = lm78_reset, + { .available = NULL }, + .speed_changed = NULL, + .force_redraw = NULL, + .config = NULL }; - /* The AS99127F is an ASIC manufactured by Holtek for ASUS, containing an I2C-only W83781D clone with additional voltages, GPIOs and fan control. */ const device_t as99127f_device = { - "ASUS AS99127F Rev. 1 Hardware Monitor", - "as99137f", - DEVICE_ISA, - LM78_I2C | LM78_AS99127F_REV1, - lm78_init, lm78_close, lm78_reset, - { NULL }, NULL, NULL, - NULL + .name = "ASUS AS99127F Rev. 1 Hardware Monitor", + .internal_name = "as99137f", + .flags = DEVICE_ISA, + .local = LM78_I2C | LM78_AS99127F_REV1, + .init = lm78_init, + .close = lm78_close, + .reset = lm78_reset, + { .available = NULL }, + .speed_changed = NULL, + .force_redraw = NULL, + .config = NULL }; - /* Rev. 2 is manufactured by Winbond and differs only in GPI registers. */ const device_t as99127f_rev2_device = { - "ASUS AS99127F Rev. 2 Hardware Monitor", - "as99127f_rev2", - DEVICE_ISA, - LM78_I2C | LM78_AS99127F_REV2, - lm78_init, lm78_close, lm78_reset, - { NULL }, NULL, NULL, - NULL + .name = "ASUS AS99127F Rev. 2 Hardware Monitor", + .internal_name = "as99127f_rev2", + .flags = DEVICE_ISA, + .local = LM78_I2C | LM78_AS99127F_REV2, + .init = lm78_init, + .close = lm78_close, + .reset = lm78_reset, + { .available = NULL }, + .speed_changed = NULL, + .force_redraw = NULL, + .config = NULL }; - /* Winbond W83782D on ISA and SMBus. */ const device_t w83782d_device = { - "Winbond W83782D Hardware Monitor", - "w83783d", - DEVICE_ISA, - 0x290 | LM78_I2C | LM78_W83782D, - lm78_init, lm78_close, lm78_reset, - { NULL }, NULL, NULL, - NULL + .name = "Winbond W83782D Hardware Monitor", + .internal_name = "w83783d", + .flags = DEVICE_ISA, + .local = 0x290 | LM78_I2C | LM78_W83782D, + .init = lm78_init, + .close = lm78_close, + .reset = lm78_reset, + { .available = NULL }, + .speed_changed = NULL, + .force_redraw = NULL, + .config = NULL }; diff --git a/src/device/hwm_vt82c686.c b/src/device/hwm_vt82c686.c index d2a1d00dc..b6a0dddda 100644 --- a/src/device/hwm_vt82c686.c +++ b/src/device/hwm_vt82c686.c @@ -1,18 +1,18 @@ /* - * 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. + * 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. + * This file is part of the 86Box distribution. * - * Emulation of the VIA VT82C686A/B integrated hardware monitor. + * Emulation of the VIA VT82C686A/B integrated hardware monitor. * * * - * Author: RichardG, + * Authors: RichardG, * - * Copyright 2020 RichardG. + * Copyright 2020 RichardG. */ #include #include @@ -25,95 +25,103 @@ #include <86box/device.h> #include <86box/io.h> #include <86box/hwm.h> +#include <86box/plat_unused.h> - -#define CLAMP(a, min, max) (((a) < (min)) ? (min) : (((a) > (max)) ? (max) : (a))) +#define CLAMP(a, min, max) (((a) < (min)) ? (min) : (((a) > (max)) ? (max) : (a))) /* Formulas and factors derived from Linux's via686a.c driver. */ -#define VT82C686_RPM_TO_REG(r, d) ((r) ? CLAMP(1350000 / (r * d), 1, 255) : 0) -#define VT82C686_TEMP_TO_REG(t) (-1.160370e-10*(t*t*t*t*t*t) + 3.193693e-08*(t*t*t*t*t) - 1.464447e-06*(t*t*t*t) - 2.525453e-04*(t*t*t) + 1.424593e-02*(t*t) + 2.148941e+00*t + 7.275808e+01) -#define VT82C686_VOLTAGE_TO_REG(v, f) CLAMP((((v) * (2.628 / (f))) - 120.5) / 25, 0, 255) +#define VT82C686_RPM_TO_REG(r, d) ((r) ? CLAMP(1350000 / (r * d), 1, 255) : 0) +#define VT82C686_TEMP_TO_REG(t) (-1.160370e-10 * (t * t * t * t * t * t) + 3.193693e-08 * (t * t * t * t * t) - 1.464447e-06 * (t * t * t * t) - 2.525453e-04 * (t * t * t) + 1.424593e-02 * (t * t) + 2.148941e+00 * t + 7.275808e+01) +#define VT82C686_VOLTAGE_TO_REG(v, f) CLAMP((((v) * (2.628 / (f))) - 120.5) / 25, 0, 255) - -typedef struct { +typedef struct vt82c686_t { hwm_values_t *values; - uint8_t enable; - uint16_t io_base; - uint8_t regs[128]; + uint8_t enable; + uint16_t io_base; + uint8_t regs[128]; } vt82c686_t; +static double voltage_factors[5] = { 1.25, 1.25, 1.67, 2.6, 6.3 }; -static double voltage_factors[5] = {1.25, 1.25, 1.67, 2.6, 6.3}; - - -static void vt82c686_reset(vt82c686_t *dev, uint8_t initialization); - +static void vt82c686_reset(vt82c686_t *dev, uint8_t initialization); static uint8_t vt82c686_read(uint16_t addr, void *priv) { - vt82c686_t *dev = (vt82c686_t *) priv; - uint8_t ret; + const vt82c686_t *dev = (vt82c686_t *) priv; + uint8_t ret; addr -= dev->io_base; switch (addr) { - case 0x00 ... 0x0f: case 0x50 ... 0x7f: /* undefined registers */ - /* Real 686B returns the contents of 0x40. */ - ret = dev->regs[0x40]; - break; + case 0x00 ... 0x0f: + case 0x50 ... 0x7f: /* undefined registers */ + /* Real 686B returns the contents of 0x40. */ + ret = dev->regs[0x40]; + break; - case 0x1f: case 0x20: case 0x21: /* temperatures */ - ret = VT82C686_TEMP_TO_REG(dev->values->temperatures[(addr == 0x1f) ? 2 : (addr & 1)]); - break; + case 0x1f: + case 0x20: + case 0x21: /* temperatures */ + ret = VT82C686_TEMP_TO_REG(dev->values->temperatures[(addr == 0x1f) ? 2 : (addr & 1)]); + break; - case 0x22: case 0x23: case 0x24: case 0x25: case 0x26: /* voltages */ - ret = VT82C686_VOLTAGE_TO_REG(dev->values->voltages[addr - 0x22], voltage_factors[addr - 0x22]); - break; + case 0x22: + case 0x23: + case 0x24: + case 0x25: + case 0x26: /* voltages */ + ret = VT82C686_VOLTAGE_TO_REG(dev->values->voltages[addr - 0x22], voltage_factors[addr - 0x22]); + break; - case 0x29: case 0x2a: /* fan speeds */ - ret = VT82C686_RPM_TO_REG(dev->values->fans[addr - 0x29], 1 << ((dev->regs[0x47] >> ((addr == 0x29) ? 4 : 6)) & 0x3)); - break; + case 0x29: + case 0x2a: /* fan speeds */ + ret = VT82C686_RPM_TO_REG(dev->values->fans[addr - 0x29], 1 << ((dev->regs[0x47] >> ((addr == 0x29) ? 4 : 6)) & 0x3)); + break; - default: /* other registers */ - ret = dev->regs[addr]; - break; + default: /* other registers */ + ret = dev->regs[addr]; + break; } return ret; } - static void vt82c686_write(uint16_t port, uint8_t val, void *priv) { vt82c686_t *dev = (vt82c686_t *) priv; - uint8_t reg = port & 0x7f; + uint8_t reg = port & 0x7f; switch (reg) { - case 0x00 ... 0x0f: - case 0x3f: case 0x41: case 0x42: case 0x4a: - case 0x4c ... 0x7f: - /* Read-only registers. */ - return; + case 0x00 ... 0x0f: + case 0x3f: + case 0x41: + case 0x42: + case 0x4a: + case 0x4c ... 0x7f: + /* Read-only registers. */ + return; - case 0x40: - /* Reset if requested. */ - if (val & 0x80) { - vt82c686_reset(dev, 1); - return; - } - break; + case 0x40: + /* Reset if requested. */ + if (val & 0x80) { + vt82c686_reset(dev, 1); + return; + } + break; - case 0x48: - val &= 0x7f; - break; + case 0x48: + val &= 0x7f; + break; + + default: + break; } dev->regs[reg] = val; } - /* Writes to hardware monitor-related configuration space registers of the VT82C686 power management function are sent here by via_pipc.c */ void @@ -122,31 +130,33 @@ vt82c686_hwm_write(uint8_t addr, uint8_t val, void *priv) vt82c686_t *dev = (vt82c686_t *) priv; if (dev->io_base) - io_removehandler(dev->io_base, 128, - vt82c686_read, NULL, NULL, vt82c686_write, NULL, NULL, dev); + io_removehandler(dev->io_base, 128, + vt82c686_read, NULL, NULL, vt82c686_write, NULL, NULL, dev); switch (addr) { - case 0x70: - dev->io_base &= 0xff00; - dev->io_base |= val & 0x80; - break; + case 0x70: + dev->io_base &= 0xff00; + dev->io_base |= val & 0x80; + break; - case 0x71: - dev->io_base &= 0x00ff; - dev->io_base |= val << 8; - break; + case 0x71: + dev->io_base &= 0x00ff; + dev->io_base |= val << 8; + break; - case 0x74: - dev->enable = val & 0x01; - break; + case 0x74: + dev->enable = val & 0x01; + break; + + default: + break; } if (dev->enable && dev->io_base) - io_sethandler(dev->io_base, 128, - vt82c686_read, NULL, NULL, vt82c686_write, NULL, NULL, dev); + io_sethandler(dev->io_base, 128, + vt82c686_read, NULL, NULL, vt82c686_write, NULL, NULL, dev); } - static void vt82c686_reset(vt82c686_t *dev, uint8_t initialization) { @@ -159,10 +169,9 @@ vt82c686_reset(vt82c686_t *dev, uint8_t initialization) dev->regs[0x4b] = 0x15; if (!initialization) - vt82c686_hwm_write(0x74, 0x00, dev); + vt82c686_hwm_write(0x74, 0x00, dev); } - static void vt82c686_close(void *priv) { @@ -171,9 +180,8 @@ vt82c686_close(void *priv) free(dev); } - static void * -vt82c686_init(const device_t *info) +vt82c686_init(UNUSED(const device_t *info)) { vt82c686_t *dev = (vt82c686_t *) malloc(sizeof(vt82c686_t)); memset(dev, 0, sizeof(vt82c686_t)); @@ -181,22 +189,24 @@ vt82c686_init(const device_t *info) /* Set default values. Since this hardware monitor has a complex voltage factor system, the values struct contains voltage values *before* applying their respective factors. */ hwm_values_t defaults = { - { /* fan speeds */ - 3000, /* usually CPU */ - 3000 /* usually Chassis */ - }, { /* temperatures */ - 30, /* usually CPU */ - 30, /* usually System */ - 30 - }, { /* voltages */ - hwm_get_vcore(), /* Vcore */ - 2500, /* +2.5V */ - 3300, /* +3.3V */ - 5000, /* +5V */ - 12000 /* +12V */ - } + // clang-format off + { /* fan speeds */ + 3000, /* usually CPU */ + 3000 /* usually Chassis */ + }, { /* temperatures */ + 30, /* usually CPU */ + 30, /* usually System */ + 30 + }, { /* voltages */ + hwm_get_vcore(), /* Vcore */ + 2500, /* +2.5V */ + 3300, /* +3.3V */ + 5000, /* +5V */ + 12000 /* +12V */ + } + // clang-format on }; - hwm_values = defaults; + hwm_values = defaults; dev->values = &hwm_values; vt82c686_reset(dev, 0); @@ -204,13 +214,16 @@ vt82c686_init(const device_t *info) return dev; } - const device_t via_vt82c686_hwm_device = { - "VIA VT82C686 Integrated Hardware Monitor", - "via_vt82c686_hwm", - DEVICE_ISA, - 0, - vt82c686_init, vt82c686_close, NULL, - { NULL }, NULL, NULL, - NULL + .name = "VIA VT82C686 Integrated Hardware Monitor", + .internal_name = "via_vt82c686_hwm", + .flags = DEVICE_ISA, + .local = 0, + .init = vt82c686_init, + .close = vt82c686_close, + .reset = NULL, + { .available = NULL }, + .speed_changed = NULL, + .force_redraw = NULL, + .config = NULL }; diff --git a/src/device/i2c.c b/src/device/i2c.c index ac0e5ee83..56e6f8f4c 100644 --- a/src/device/i2c.c +++ b/src/device/i2c.c @@ -1,18 +1,18 @@ /* - * 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. + * 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. + * This file is part of the 86Box distribution. * - * Implementation of the I2C bus and its operations. + * Implementation of the I2C bus and its operations. * * * - * Authors: RichardG, + * Authors: RichardG, * - * Copyright 2020 RichardG. + * Copyright 2020 RichardG. */ #include #include @@ -24,51 +24,46 @@ #include <86box/86box.h> #include <86box/i2c.h> - -#define NADDRS 128 /* I2C supports 128 addresses */ +#define NADDRS 128 /* I2C supports 128 addresses */ #define MAX(a, b) ((a) > (b) ? (a) : (b)) - typedef struct _i2c_ { - uint8_t (*start)(void *bus, uint8_t addr, uint8_t read, void *priv); - uint8_t (*read)(void *bus, uint8_t addr, void *priv); - uint8_t (*write)(void *bus, uint8_t addr, uint8_t data, void *priv); - void (*stop)(void *bus, uint8_t addr, void *priv); + uint8_t (*start)(void *bus, uint8_t addr, uint8_t read, void *priv); + uint8_t (*read)(void *bus, uint8_t addr, void *priv); + uint8_t (*write)(void *bus, uint8_t addr, uint8_t data, void *priv); + void (*stop)(void *bus, uint8_t addr, void *priv); - void *priv; + void *priv; struct _i2c_ *prev, *next; } i2c_t; -typedef struct { - char *name; - i2c_t *devices[NADDRS], *last[NADDRS]; +typedef struct i2c_bus_t { + char *name; + i2c_t *devices[NADDRS]; + i2c_t *last[NADDRS]; } i2c_bus_t; - void *i2c_smbus; - #ifdef ENABLE_I2C_LOG int i2c_do_log = ENABLE_I2C_LOG; - static void i2c_log(const char *fmt, ...) { va_list ap; if (i2c_do_log) { - va_start(ap, fmt); - pclog_ex(fmt, ap); - va_end(ap); + va_start(ap, fmt); + pclog_ex(fmt, ap); + va_end(ap); } } #else -#define i2c_log(fmt, ...) +# define i2c_log(fmt, ...) #endif - void * i2c_addbus(char *name) { @@ -80,235 +75,226 @@ i2c_addbus(char *name) return bus; } - void i2c_removebus(void *bus_handle) { - int c; - i2c_t *p, *q; + i2c_t *p; + i2c_t *q; i2c_bus_t *bus = (i2c_bus_t *) bus_handle; if (!bus_handle) - return; + return; - for (c = 0; c < NADDRS; c++) { - p = bus->devices[c]; - if (!p) - continue; - while(p) { - q = p->next; - free(p); - p = q; - } + for (uint8_t c = 0; c < NADDRS; c++) { + p = bus->devices[c]; + if (!p) + continue; + while (p) { + q = p->next; + free(p); + p = q; + } } free(bus); } - char * i2c_getbusname(void *bus_handle) { i2c_bus_t *bus = (i2c_bus_t *) bus_handle; if (!bus_handle) - return(NULL); + return (NULL); - return(bus->name); + return (bus->name); } - void i2c_sethandler(void *bus_handle, uint8_t base, int size, - uint8_t (*start)(void *bus, uint8_t addr, uint8_t read, void *priv), - uint8_t (*read)(void *bus, uint8_t addr, void *priv), - uint8_t (*write)(void *bus, uint8_t addr, uint8_t data, void *priv), - void (*stop)(void *bus, uint8_t addr, void *priv), - void *priv) + uint8_t (*start)(void *bus, uint8_t addr, uint8_t read, void *priv), + uint8_t (*read)(void *bus, uint8_t addr, void *priv), + uint8_t (*write)(void *bus, uint8_t addr, uint8_t data, void *priv), + void (*stop)(void *bus, uint8_t addr, void *priv), + void *priv) { - int c; - i2c_t *p, *q = NULL; + i2c_t *p; + i2c_t *q = NULL; i2c_bus_t *bus = (i2c_bus_t *) bus_handle; if (!bus_handle || ((base + size) > NADDRS)) - return; + return; - for (c = 0; c < size; c++) { - p = bus->last[base + c]; - q = (i2c_t *) malloc(sizeof(i2c_t)); - memset(q, 0, sizeof(i2c_t)); - if (p) { - p->next = q; - q->prev = p; - } else { - bus->devices[base + c] = q; - q->prev = NULL; - } + for (int c = 0; c < size; c++) { + p = bus->last[base + c]; + q = (i2c_t *) malloc(sizeof(i2c_t)); + memset(q, 0, sizeof(i2c_t)); + if (p) { + p->next = q; + q->prev = p; + } else { + bus->devices[base + c] = q; + q->prev = NULL; + } - q->start = start; - q->read = read; - q->write = write; - q->stop = stop; + q->start = start; + q->read = read; + q->write = write; + q->stop = stop; - q->priv = priv; - q->next = NULL; + q->priv = priv; + q->next = NULL; - bus->last[base + c] = q; + bus->last[base + c] = q; } } - void i2c_removehandler(void *bus_handle, uint8_t base, int size, - uint8_t (*start)(void *bus, uint8_t addr, uint8_t read, void *priv), - uint8_t (*read)(void *bus, uint8_t addr, void *priv), - uint8_t (*write)(void *bus, uint8_t addr, uint8_t data, void *priv), - void (*stop)(void *bus, uint8_t addr, void *priv), - void *priv) + uint8_t (*start)(void *bus, uint8_t addr, uint8_t read, void *priv), + uint8_t (*read)(void *bus, uint8_t addr, void *priv), + uint8_t (*write)(void *bus, uint8_t addr, uint8_t data, void *priv), + void (*stop)(void *bus, uint8_t addr, void *priv), + void *priv) { - int c; - i2c_t *p, *q; + i2c_t *p; + i2c_t *q; i2c_bus_t *bus = (i2c_bus_t *) bus_handle; if (!bus_handle || ((base + size) > NADDRS)) - return; + return; - for (c = 0; c < size; c++) { - p = bus->devices[base + c]; - if (!p) - continue; - while(p) { - q = p->next; - if ((p->start == start) && (p->read == read) && (p->write == write) && (p->stop == stop) && (p->priv == priv)) { - if (p->prev) - p->prev->next = p->next; - else - bus->devices[base + c] = p->next; - if (p->next) - p->next->prev = p->prev; - else - bus->last[base + c] = p->prev; - free(p); - p = NULL; - break; - } - p = q; - } + for (int c = 0; c < size; c++) { + p = bus->devices[base + c]; + if (!p) + continue; + while (p) { + q = p->next; + if ((p->start == start) && (p->read == read) && (p->write == write) && (p->stop == stop) && (p->priv == priv)) { + if (p->prev) + p->prev->next = p->next; + else + bus->devices[base + c] = p->next; + if (p->next) + p->next->prev = p->prev; + else + bus->last[base + c] = p->prev; + free(p); + p = NULL; + break; + } + p = q; + } } } - void i2c_handler(int set, void *bus_handle, uint8_t base, int size, - uint8_t (*start)(void *bus, uint8_t addr, uint8_t read, void *priv), - uint8_t (*read)(void *bus, uint8_t addr, void *priv), - uint8_t (*write)(void *bus, uint8_t addr, uint8_t data, void *priv), - void (*stop)(void *bus, uint8_t addr, void *priv), - void *priv) + uint8_t (*start)(void *bus, uint8_t addr, uint8_t read, void *priv), + uint8_t (*read)(void *bus, uint8_t addr, void *priv), + uint8_t (*write)(void *bus, uint8_t addr, uint8_t data, void *priv), + void (*stop)(void *bus, uint8_t addr, void *priv), + void *priv) { if (set) - i2c_sethandler(bus_handle, base, size, start, read, write, stop, priv); + i2c_sethandler(bus_handle, base, size, start, read, write, stop, priv); else - i2c_removehandler(bus_handle, base, size, start, read, write, stop, priv); + i2c_removehandler(bus_handle, base, size, start, read, write, stop, priv); } - uint8_t i2c_start(void *bus_handle, uint8_t addr, uint8_t read) { - uint8_t ret = 0; - i2c_bus_t *bus = (i2c_bus_t *) bus_handle; - i2c_t *p; + uint8_t ret = 0; + const i2c_bus_t *bus = (i2c_bus_t *) bus_handle; + i2c_t *p; if (!bus) - return(ret); + return ret; p = bus->devices[addr]; if (p) { - while(p) { - if (p->start) { - ret |= p->start(bus_handle, addr, read, p->priv); - } - p = p->next; - } + while (p) { + if (p->start) { + ret |= p->start(bus_handle, addr, read, p->priv); + } + p = p->next; + } } i2c_log("I2C %s: start(%02X) = %d\n", bus->name, addr, ret); - return(ret); + return ret; } - uint8_t i2c_read(void *bus_handle, uint8_t addr) { - uint8_t ret = 0; - i2c_bus_t *bus = (i2c_bus_t *) bus_handle; - i2c_t *p; + uint8_t ret = 0; + const i2c_bus_t *bus = (i2c_bus_t *) bus_handle; + i2c_t *p; if (!bus) - return(ret); + return ret; p = bus->devices[addr]; if (p) { - while(p) { - if (p->read) { - ret = p->read(bus_handle, addr, p->priv); - break; - } - p = p->next; - } + while (p) { + if (p->read) { + ret = p->read(bus_handle, addr, p->priv); + break; + } + p = p->next; + } } i2c_log("I2C %s: read(%02X) = %02X\n", bus->name, addr, ret); - return(ret); + return ret; } - uint8_t i2c_write(void *bus_handle, uint8_t addr, uint8_t data) { - uint8_t ret = 0; - i2c_t *p; - i2c_bus_t *bus = (i2c_bus_t *) bus_handle; + uint8_t ret = 0; + i2c_t *p; + const i2c_bus_t *bus = (i2c_bus_t *) bus_handle; if (!bus) - return(ret); + return ret; p = bus->devices[addr]; if (p) { - while(p) { - if (p->write) { - ret |= p->write(bus_handle, addr, data, p->priv); - } - p = p->next; - } + while (p) { + if (p->write) { + ret |= p->write(bus_handle, addr, data, p->priv); + } + p = p->next; + } } i2c_log("I2C %s: write(%02X, %02X) = %d\n", bus->name, addr, data, ret); - return(ret); + return ret; } - void i2c_stop(void *bus_handle, uint8_t addr) { - i2c_bus_t *bus = (i2c_bus_t *) bus_handle; - i2c_t *p; + const i2c_bus_t *bus = (i2c_bus_t *) bus_handle; + i2c_t *p; if (!bus) - return; + return; p = bus->devices[addr]; if (p) { - while(p) { - if (p->stop) { - p->stop(bus_handle, addr, p->priv); - } - p = p->next; - } + while (p) { + if (p->stop) { + p->stop(bus_handle, addr, p->priv); + } + p = p->next; + } } i2c_log("I2C %s: stop(%02X)\n", bus->name, addr); diff --git a/src/device/i2c_gpio.c b/src/device/i2c_gpio.c index e3902baaa..22bdaffd3 100644 --- a/src/device/i2c_gpio.c +++ b/src/device/i2c_gpio.c @@ -1,18 +1,18 @@ /* - * 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. + * 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. + * This file is part of the 86Box distribution. * - * Emulation of a GPIO-based I2C host controller. + * Emulation of a GPIO-based I2C host controller. * * * - * Authors: RichardG, + * Authors: RichardG, * - * Copyright 2020 RichardG. + * Copyright 2020 RichardG. */ #include #include @@ -24,35 +24,38 @@ #include <86box/86box.h> #include <86box/i2c.h> - -typedef struct { - char *bus_name; - void *i2c; - uint8_t prev_scl, prev_sda, slave_sda, started, - slave_addr_received, slave_addr, slave_read, pos, byte; +typedef struct i2c_gpio_t { + char *bus_name; + void *i2c; + uint8_t prev_scl; + uint8_t prev_sda; + uint8_t slave_sda; + uint8_t started; + uint8_t slave_addr_received; + uint8_t slave_addr; + uint8_t slave_read; + uint8_t pos; + uint8_t byte; } i2c_gpio_t; - #ifdef ENABLE_I2C_GPIO_LOG int i2c_gpio_do_log = ENABLE_I2C_GPIO_LOG; - static void i2c_gpio_log(int level, const char *fmt, ...) { va_list ap; if (i2c_gpio_do_log >= level) { - va_start(ap, fmt); - pclog_ex(fmt, ap); - va_end(ap); + va_start(ap, fmt); + pclog_ex(fmt, ap); + va_end(ap); } } #else -#define i2c_gpio_log(fmt, ...) +# define i2c_gpio_log(fmt, ...) #endif - void * i2c_gpio_init(char *bus_name) { @@ -62,14 +65,13 @@ i2c_gpio_init(char *bus_name) i2c_gpio_log(1, "I2C GPIO %s: init()\n", bus_name); dev->bus_name = bus_name; - dev->i2c = i2c_addbus(dev->bus_name); + dev->i2c = i2c_addbus(dev->bus_name); dev->prev_scl = dev->prev_sda = dev->slave_sda = 1; - dev->slave_addr = 0xff; + dev->slave_addr = 0xff; return dev; } - void i2c_gpio_close(void *dev_handle) { @@ -82,7 +84,6 @@ i2c_gpio_close(void *dev_handle) free(dev); } - void i2c_gpio_set(void *dev_handle, uint8_t scl, uint8_t sda) { @@ -91,97 +92,99 @@ i2c_gpio_set(void *dev_handle, uint8_t scl, uint8_t sda) i2c_gpio_log(3, "I2C GPIO %s: write scl=%d->%d sda=%d->%d read=%d\n", dev->bus_name, dev->prev_scl, scl, dev->prev_sda, sda, dev->slave_read); if (dev->prev_scl && scl) { - if (dev->prev_sda && !sda) { - i2c_gpio_log(2, "I2C GPIO %s: Start condition\n", dev->bus_name); - dev->started = 1; - dev->pos = 0; - dev->slave_addr = 0xff; - dev->slave_read = 2; /* start with address transfer */ - dev->slave_sda = 1; - } else if (!dev->prev_sda && sda) { - i2c_gpio_log(2, "I2C GPIO %s: Stop condition\n", dev->bus_name); - dev->started = 0; - if (dev->slave_addr != 0xff) - i2c_stop(dev->i2c, dev->slave_addr); - dev->slave_addr = 0xff; - dev->slave_sda = 1; - } + if (dev->prev_sda && !sda) { + i2c_gpio_log(2, "I2C GPIO %s: Start condition\n", dev->bus_name); + dev->started = 1; + dev->pos = 0; + dev->slave_addr = 0xff; + dev->slave_read = 2; /* start with address transfer */ + dev->slave_sda = 1; + } else if (!dev->prev_sda && sda) { + i2c_gpio_log(2, "I2C GPIO %s: Stop condition\n", dev->bus_name); + dev->started = 0; + if (dev->slave_addr != 0xff) + i2c_stop(dev->i2c, dev->slave_addr); + dev->slave_addr = 0xff; + dev->slave_sda = 1; + } } else if (!dev->prev_scl && scl && dev->started) { - if (dev->pos++ < 8) { - if (dev->slave_read == 1) { - dev->slave_sda = !!(dev->byte & 0x80); - dev->byte <<= 1; - } else { - dev->byte <<= 1; - dev->byte |= sda; - } + if (dev->pos++ < 8) { + if (dev->slave_read == 1) { + dev->slave_sda = !!(dev->byte & 0x80); + dev->byte <<= 1; + } else { + dev->byte <<= 1; + dev->byte |= sda; + } - i2c_gpio_log(2, "I2C GPIO %s: Bit %d = %d\n", dev->bus_name, 8 - dev->pos, (dev->slave_read == 1) ? dev->slave_sda : sda); - } + i2c_gpio_log(2, "I2C GPIO %s: Bit %d = %d\n", dev->bus_name, 8 - dev->pos, (dev->slave_read == 1) ? dev->slave_sda : sda); + } - if (dev->pos == 8) { - i2c_gpio_log(2, "I2C GPIO %s: Byte = %02X\n", dev->bus_name, dev->byte); + if (dev->pos == 8) { + i2c_gpio_log(2, "I2C GPIO %s: Byte = %02X\n", dev->bus_name, dev->byte); - /* (N)ACKing here instead of at the 9th bit may sound odd, but is required by the Matrox Mystique Windows drivers. */ - switch (dev->slave_read) { - case 2: /* address transfer */ - dev->slave_addr = dev->byte >> 1; - dev->slave_read = dev->byte & 1; + /* (N)ACKing here instead of at the 9th bit may sound odd, but is required by the Matrox Mystique Windows drivers. */ + switch (dev->slave_read) { + case 2: /* address transfer */ + dev->slave_addr = dev->byte >> 1; + dev->slave_read = dev->byte & 1; - /* slave ACKs? */ - dev->slave_sda = !i2c_start(dev->i2c, dev->slave_addr, dev->slave_read); - i2c_gpio_log(2, "I2C GPIO %s: Slave %02X %s %sACK\n", dev->bus_name, dev->slave_addr, dev->slave_read ? "read" : "write", dev->slave_sda ? "N" : ""); + /* slave ACKs? */ + dev->slave_sda = !i2c_start(dev->i2c, dev->slave_addr, dev->slave_read); + i2c_gpio_log(2, "I2C GPIO %s: Slave %02X %s %sACK\n", dev->bus_name, dev->slave_addr, dev->slave_read ? "read" : "write", dev->slave_sda ? "N" : ""); - if (!dev->slave_sda && dev->slave_read) /* read first byte on an ACKed read transfer */ - dev->byte = i2c_read(dev->i2c, dev->slave_addr); + if (!dev->slave_sda && dev->slave_read) /* read first byte on an ACKed read transfer */ + dev->byte = i2c_read(dev->i2c, dev->slave_addr); - dev->slave_read |= 0x80; /* slave_read was overwritten; stop the master ACK read logic from running at the 9th bit if we're reading */ - break; + dev->slave_read |= 0x80; /* slave_read was overwritten; stop the master ACK read logic from running at the 9th bit if we're reading */ + break; - case 0: /* write transfer */ - dev->slave_sda = !i2c_write(dev->i2c, dev->slave_addr, dev->byte); - i2c_gpio_log(2, "I2C GPIO %s: Write %02X %sACK\n", dev->bus_name, dev->byte, dev->slave_sda ? "N" : ""); - break; - } - } else if (dev->pos == 9) { - switch (dev->slave_read) { - case 1: /* read transfer (unless we're in an address transfer) */ - if (!sda) /* master ACKs? */ - dev->byte = i2c_read(dev->i2c, dev->slave_addr); - i2c_gpio_log(2, "I2C GPIO %s: Read %02X %sACK\n", dev->bus_name, dev->byte, sda ? "N" : ""); - break; + case 0: /* write transfer */ + dev->slave_sda = !i2c_write(dev->i2c, dev->slave_addr, dev->byte); + i2c_gpio_log(2, "I2C GPIO %s: Write %02X %sACK\n", dev->bus_name, dev->byte, dev->slave_sda ? "N" : ""); + break; + + default: + break; + } + } else if (dev->pos == 9) { + switch (dev->slave_read) { + case 1: /* read transfer (unless we're in an address transfer) */ + if (!sda) /* master ACKs? */ + dev->byte = i2c_read(dev->i2c, dev->slave_addr); + i2c_gpio_log(2, "I2C GPIO %s: Read %02X %sACK\n", dev->bus_name, dev->byte, sda ? "N" : ""); + break; - default: - dev->slave_read &= 1; /* if we're in an address transfer, clear it */ - } - dev->pos = 0; /* start over */ - } + default: + dev->slave_read &= 1; /* if we're in an address transfer, clear it */ + } + dev->pos = 0; /* start over */ + } } else if (dev->prev_scl && !scl && (dev->pos != 8)) { /* keep (N)ACK computed at the 8th bit when transitioning to the 9th bit */ - dev->slave_sda = 1; + dev->slave_sda = 1; } dev->prev_scl = scl; dev->prev_sda = sda; } - uint8_t i2c_gpio_get_scl(void *dev_handle) { - i2c_gpio_t *dev = (i2c_gpio_t *) dev_handle; + const i2c_gpio_t *dev = (i2c_gpio_t *) dev_handle; + return dev->prev_scl; } - uint8_t i2c_gpio_get_sda(void *dev_handle) { - i2c_gpio_t *dev = (i2c_gpio_t *) dev_handle; + const i2c_gpio_t *dev = (i2c_gpio_t *) dev_handle; + i2c_gpio_log(3, "I2C GPIO %s: read myscl=%d mysda=%d slavesda=%d\n", dev->bus_name, dev->prev_scl, dev->prev_sda, dev->slave_sda); return dev->prev_sda && dev->slave_sda; } - void * i2c_gpio_get_bus(void *dev_handle) { diff --git a/src/device/ibm_5161.c b/src/device/ibm_5161.c index d18b93cc2..07083873e 100644 --- a/src/device/ibm_5161.c +++ b/src/device/ibm_5161.c @@ -1,16 +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. + * 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. * - * Emulation of the IBM Expansion Unit (5161). + * Emulation of the IBM Expansion Unit (5161). * * * - * Authors: Miran Grca, + * Authors: Miran Grca, * - * Copyright 2016-2018 Miran Grca. + * Copyright 2016-2018 Miran Grca. */ #include #include @@ -26,16 +26,14 @@ #include <86box/pci.h> #include <86box/timer.h> #include <86box/pit.h> +#include <86box/plat_unused.h> #include <86box/port_92.h> #include <86box/machine.h> - -typedef struct -{ - uint8_t regs[8]; +typedef struct ibm_5161_t { + uint8_t regs[8]; } ibm_5161_t; - static void ibm_5161_out(uint16_t port, uint8_t val, void *priv) { @@ -44,85 +42,83 @@ ibm_5161_out(uint16_t port, uint8_t val, void *priv) dev->regs[port & 0x0007] = val; } - static uint8_t ibm_5161_in(uint16_t port, void *priv) { - ibm_5161_t *dev = (ibm_5161_t *) priv; - uint8_t ret = 0xff; + const ibm_5161_t *dev = (ibm_5161_t *) priv; + uint8_t ret = 0xff; ret = dev->regs[port & 0x0007]; switch (port) { - case 0x210: /* Write to latch expansion bus data (ED0-ED7) */ - /* Read to verify expansion bus data (ED0-ED7) */ - break; - case 0x214: /* Write to latch data bus bits (DO - 07) */ - /* Read data bus bits (DO - D7) */ - break; - case 0x211: /* Read high-order address bits (A8 - A 15) */ - case 0x215: /* Read high-order address bits (A8 - A 15) */ - ret = (get_last_addr() >> 8) & 0xff; - break; - case 0x212: /* Read low-order address bits (A0 - A7) */ - case 0x216: /* Read low-order address bits (A0 - A7) */ - ret = get_last_addr() & 0xff; - break; - case 0x213: /* Write 00 to disable expansion unit */ - /* Write 01 to enable expansion unit */ - /* Read status of expansion unit - 00 = enable/disable - 01 = wait-state request flag - 02-03 = not used - 04-07 = switch position - 1 = Off - 0 =On */ - ret = dev->regs[3] & 0x01; - break; + case 0x210: /* Write to latch expansion bus data (ED0-ED7) */ + /* Read to verify expansion bus data (ED0-ED7) */ + break; + case 0x214: /* Write to latch data bus bits (DO - 07) */ + /* Read data bus bits (DO - D7) */ + break; + case 0x211: /* Read high-order address bits (A8 - A 15) */ + case 0x215: /* Read high-order address bits (A8 - A 15) */ + ret = (get_last_addr() >> 8) & 0xff; + break; + case 0x212: /* Read low-order address bits (A0 - A7) */ + case 0x216: /* Read low-order address bits (A0 - A7) */ + ret = get_last_addr() & 0xff; + break; + case 0x213: /* Write 00 to disable expansion unit */ + /* Write 01 to enable expansion unit */ + /* Read status of expansion unit + 00 = enable/disable + 01 = wait-state request flag + 02-03 = not used + 04-07 = switch position + 1 = Off + 0 =On */ + ret = dev->regs[3] & 0x01; + break; + + default: + break; } return ret; } - static void -ibm_5161_close(void *p) +ibm_5161_close(void *priv) { - ibm_5161_t *dev = (ibm_5161_t *) p; + ibm_5161_t *dev = (ibm_5161_t *) priv; free(dev); } - static void * -ibm_5161_init(const device_t *info) +ibm_5161_init(UNUSED(const device_t *info)) { ibm_5161_t *dev = (ibm_5161_t *) malloc(sizeof(ibm_5161_t)); memset(dev, 0, sizeof(ibm_5161_t)); /* Extender Card Registers */ io_sethandler(0x0210, 0x0004, - ibm_5161_in, NULL, NULL, ibm_5161_out, NULL, NULL, dev); + ibm_5161_in, NULL, NULL, ibm_5161_out, NULL, NULL, dev); /* Receiver Card Registers */ io_sethandler(0x0214, 0x0003, - ibm_5161_in, NULL, NULL, ibm_5161_out, NULL, NULL, dev); + ibm_5161_in, NULL, NULL, ibm_5161_out, NULL, NULL, dev); return dev; } - -const device_t ibm_5161_device = -{ - "IBM Expansion Unit (5161)", - "ibm_5161", - DEVICE_ISA, - 0, - ibm_5161_init, - ibm_5161_close, - NULL, - { NULL }, - NULL, - NULL, - NULL +const device_t ibm_5161_device = { + .name = "IBM Expansion Unit (5161)", + .internal_name = "ibm_5161", + .flags = DEVICE_ISA, + .local = 0, + .init = ibm_5161_init, + .close = ibm_5161_close, + .reset = NULL, + { .available = NULL }, + .speed_changed = NULL, + .force_redraw = NULL, + .config = NULL }; diff --git a/src/device/isamem.c b/src/device/isamem.c index a987cba77..5b880d6eb 100644 --- a/src/device/isamem.c +++ b/src/device/isamem.c @@ -1,60 +1,58 @@ /* - * VARCem Virtual ARchaeological Computer EMulator. - * An emulator of (mostly) x86-based PC systems and devices, - * using the ISA,EISA,VLB,MCA and PCI system buses, roughly - * spanning the era between 1981 and 1995. + * VARCem Virtual ARchaeological Computer EMulator. + * An emulator of (mostly) x86-based PC systems and devices, + * using the ISA,EISA,VLB,MCA and PCI system buses, roughly + * spanning the era between 1981 and 1995. * - * This file is part of the VARCem Project. + * Implementation of a memory expansion board for the ISA Bus. * - * Implementation of a memory expansion board for the ISA Bus. + * Although modern systems use direct-connect local buses to + * connect the CPU with its memory, originally the main system + * bus(es) were used for that. Memory expension cards could add + * memory to the system through the ISA bus, using a variety of + * techniques. * - * Although modern systems use direct-connect local buses to - * connect the CPU with its memory, originally the main system - * bus(es) were used for that. Memory expension cards could add - * memory to the system through the ISA bus, using a variety of - * techniques. + * The majority of these boards could provide some (additional) + * conventional (low) memory, extended (high) memory on 80286 + * and higher systems, as well as EMS bank-switched memory. * - * The majority of these boards could provide some (additional) - * conventional (low) memory, extended (high) memory on 80286 - * and higher systems, as well as EMS bank-switched memory. + * This implementation uses the LIM 3.2 specifications for EMS. * - * This implementation uses the LIM 3.2 specifications for EMS. + * With the EMS method, the system's standard memory is expanded + * by means of bank-switching. One or more 'frames' in the upper + * memory area (640K-1024K) are used as viewports into an array + * of RAM pages numbered 0 to N. Each page is defined to be 16KB + * in size, so, for a 1024KB board, 64 such pages are available. + * I/O control registers are used to set up the mappings. More + * modern boards even have multiple 'copies' of those registers, + * which can be switched very fast, to allow for multitasking. * - * With the EMS method, the system's standard memory is expanded - * by means of bank-switching. One or more 'frames' in the upper - * memory area (640K-1024K) are used as viewports into an array - * of RAM pages numbered 0 to N. Each page is defined to be 16KB - * in size, so, for a 1024KB board, 64 such pages are available. - * I/O control registers are used to set up the mappings. More - * modern boards even have multiple 'copies' of those registers, - * which can be switched very fast, to allow for multitasking. - * - * TODO: The EV159 is supposed to support 16b EMS transfers, but the - * EMM.sys driver for it doesn't seem to want to do that.. + * TODO: The EV159 is supposed to support 16b EMS transfers, but the + * EMM.sys driver for it doesn't seem to want to do that.. * * * - * Author: Fred N. van Kempen, + * Authors: Fred N. van Kempen, * - * Copyright 2018 Fred N. van Kempen. + * Copyright 2018 Fred N. van Kempen. * - * Redistribution and use in source and binary forms, with - * or without modification, are permitted provided that the - * following conditions are met: + * Redistribution and use in source and binary forms, with + * or without modification, are permitted provided that the + * following conditions are met: * - * 1. Redistributions of source code must retain the entire - * above notice, this list of conditions and the following - * disclaimer. + * 1. Redistributions of source code must retain the entire + * above notice, this list of conditions and the following + * disclaimer. * - * 2. Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the - * following disclaimer in the documentation and/or other - * materials provided with the distribution. + * 2. Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the + * following disclaimer in the documentation and/or other + * materials provided with the distribution. * - * 3. Neither the name of the copyright holder nor the names - * of its contributors may be used to endorse or promote - * products derived from this software without specific - * prior written permission. + * 3. Neither the name of the copyright holder nor the names + * of its contributors may be used to endorse or promote + * products derived from this software without specific + * prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT @@ -86,247 +84,245 @@ #include "cpu.h" -#define ISAMEM_IBMXT_CARD 0 -#define ISAMEM_GENXT_CARD 1 -#define ISAMEM_IBMAT_CARD 2 -#define ISAMEM_GENAT_CARD 3 -#define ISAMEM_P5PAK_CARD 4 -#define ISAMEM_A6PAK_CARD 5 -#define ISAMEM_EMS5150_CARD 6 -#define ISAMEM_EV159_CARD 10 -#define ISAMEM_RAMPAGEXT_CARD 11 +#define ISAMEM_IBMXT_CARD 0 +#define ISAMEM_GENXT_CARD 1 +#define ISAMEM_RAMCARD_CARD 2 +#define ISAMEM_SYSTEMCARD_CARD 3 +#define ISAMEM_IBMAT_CARD 4 +#define ISAMEM_GENAT_CARD 5 +#define ISAMEM_P5PAK_CARD 6 +#define ISAMEM_A6PAK_CARD 7 +#define ISAMEM_EMS5150_CARD 8 +#define ISAMEM_EV159_CARD 10 +#define ISAMEM_RAMPAGEXT_CARD 11 #define ISAMEM_ABOVEBOARD_CARD 12 -#define ISAMEM_BRAT_CARD 13 +#define ISAMEM_BRAT_CARD 13 -#define ISAMEM_DEBUG 0 +#define ISAMEM_DEBUG 0 -#define RAM_TOPMEM (640 << 10) /* end of low memory */ -#define RAM_UMAMEM (384 << 10) /* upper memory block */ -#define RAM_EXTMEM (1024 << 10) /* start of high memory */ +#define RAM_TOPMEM (640 << 10) /* end of low memory */ +#define RAM_UMAMEM (384 << 10) /* upper memory block */ +#define RAM_EXTMEM (1024 << 10) /* start of high memory */ -#define EMS_MAXSIZE (2048 << 10) /* max EMS memory size */ -#define EMS_PGSIZE (16 << 10) /* one page is this big */ -#define EMS_MAXPAGE 4 /* number of viewport pages */ +#define EMS_MAXSIZE (2048 << 10) /* max EMS memory size */ +#define EMS_PGSIZE (16 << 10) /* one page is this big */ +#define EMS_MAXPAGE 4 /* number of viewport pages */ -#define EXTRAM_CONVENTIONAL 0 -#define EXTRAM_HIGH 1 -#define EXTRAM_XMS 2 +#define EXTRAM_CONVENTIONAL 0 +#define EXTRAM_HIGH 1 +#define EXTRAM_XMS 2 -typedef struct { - int8_t enabled; /* 1=ENABLED */ - uint8_t page; /* page# in EMS RAM */ - uint8_t frame; /* (varies with board) */ - char pad; - uint8_t *addr; /* start addr in EMS RAM */ - mem_mapping_t mapping; /* mapping entry for page */ +typedef struct emsreg_t { + int8_t enabled; /* 1=ENABLED */ + uint8_t page; /* page# in EMS RAM */ + uint8_t frame; /* (varies with board) */ + char pad; + uint8_t *addr; /* start addr in EMS RAM */ + mem_mapping_t mapping; /* mapping entry for page */ } emsreg_t; -typedef struct { - uint32_t base; - uint8_t *ptr; +typedef struct ext_ram_t { + uint32_t base; + uint8_t *ptr; } ext_ram_t; -typedef struct { - const char *name; - uint8_t board : 6, /* board type */ - reserved : 2; +typedef struct memdev_t { + const char *name; + uint8_t board : 6; /* board type */ + uint8_t reserved : 2; - uint8_t flags; -#define FLAG_CONFIG 0x01 /* card is configured */ -#define FLAG_WIDE 0x10 /* card uses 16b mode */ -#define FLAG_FAST 0x20 /* fast (<= 120ns) chips */ -#define FLAG_EMS 0x40 /* card has EMS mode enabled */ + uint8_t flags; +#define FLAG_CONFIG 0x01 /* card is configured */ +#define FLAG_WIDE 0x10 /* card uses 16b mode */ +#define FLAG_FAST 0x20 /* fast (<= 120ns) chips */ +#define FLAG_EMS 0x40 /* card has EMS mode enabled */ - uint16_t total_size; /* configured size in KB */ - uint32_t base_addr, /* configured I/O address */ - start_addr, /* configured memory start */ - frame_addr; /* configured frame address */ + uint16_t total_size; /* configured size in KB */ + uint32_t base_addr; /* configured I/O address */ + uint32_t start_addr; /* configured memory start */ + uint32_t frame_addr; /* configured frame address */ - uint16_t ems_size, /* EMS size in KB */ - ems_pages; /* EMS size in pages */ - uint32_t ems_start; /* start of EMS in RAM */ + uint16_t ems_size; /* EMS size in KB */ + uint16_t ems_pages; /* EMS size in pages */ + uint32_t ems_start; /* start of EMS in RAM */ - uint8_t *ram; /* allocated RAM buffer */ + uint8_t *ram; /* allocated RAM buffer */ - ext_ram_t ext_ram[3]; /* structures for the mappings */ + ext_ram_t ext_ram[3]; /* structures for the mappings */ - mem_mapping_t low_mapping; /* mapping for low mem */ - mem_mapping_t high_mapping; /* mapping for high mem */ + mem_mapping_t low_mapping; /* mapping for low mem */ + mem_mapping_t high_mapping; /* mapping for high mem */ - emsreg_t ems[EMS_MAXPAGE]; /* EMS controller registers */ + emsreg_t ems[EMS_MAXPAGE]; /* EMS controller registers */ } memdev_t; #ifdef ENABLE_ISAMEM_LOG int isamem_do_log = ENABLE_ISAMEM_LOG; - static void isamem_log(const char *fmt, ...) { va_list ap; if (isamem_do_log) { - va_start(ap, fmt); - pclog_ex(fmt, ap); - va_end(ap); + va_start(ap, fmt); + pclog_ex(fmt, ap); + va_end(ap); } } #else -#define isamem_log(fmt, ...) +# define isamem_log(fmt, ...) #endif - /* Why this convoluted setup with the mem_dev stuff when it's much simpler to just pass the exec pointer as p as well, and then just use that. */ /* Read one byte from onboard RAM. */ static uint8_t ram_readb(uint32_t addr, void *priv) { - ext_ram_t *dev = (ext_ram_t *)priv; - uint8_t ret = 0xff; + ext_ram_t *dev = (ext_ram_t *) priv; + uint8_t ret = 0xff; /* Grab the data. */ - ret = *(uint8_t *)(dev->ptr + (addr - dev->base)); + ret = *(uint8_t *) (dev->ptr + (addr - dev->base)); - return(ret); + return ret; } - /* Read one word from onboard RAM. */ static uint16_t ram_readw(uint32_t addr, void *priv) { - ext_ram_t *dev = (ext_ram_t *)priv; - uint16_t ret = 0xffff; + ext_ram_t *dev = (ext_ram_t *) priv; + uint16_t ret = 0xffff; /* Grab the data. */ - ret = *(uint16_t *)(dev->ptr + (addr - dev->base)); + ret = *(uint16_t *) (dev->ptr + (addr - dev->base)); - return(ret); + return ret; } - /* Write one byte to onboard RAM. */ static void ram_writeb(uint32_t addr, uint8_t val, void *priv) { - ext_ram_t *dev = (ext_ram_t *)priv; + ext_ram_t *dev = (ext_ram_t *) priv; /* Write the data. */ - *(uint8_t *)(dev->ptr + (addr - dev->base)) = val; + *(uint8_t *) (dev->ptr + (addr - dev->base)) = val; } - /* Write one word to onboard RAM. */ static void ram_writew(uint32_t addr, uint16_t val, void *priv) { - ext_ram_t *dev = (ext_ram_t *)priv; + ext_ram_t *dev = (ext_ram_t *) priv; /* Write the data. */ - *(uint16_t *)(dev->ptr + (addr - dev->base)) = val; + *(uint16_t *) (dev->ptr + (addr - dev->base)) = val; } - /* Read one byte from onboard paged RAM. */ static uint8_t ems_readb(uint32_t addr, void *priv) { - memdev_t *dev = (memdev_t *)priv; - uint8_t ret = 0xff; + memdev_t *dev = (memdev_t *) priv; + uint8_t ret = 0xff; /* Grab the data. */ - ret = *(uint8_t *)(dev->ems[((addr & 0xffff) >> 14)].addr + (addr & 0x3fff)); + ret = *(uint8_t *) (dev->ems[(addr & 0xffff) >> 14].addr + (addr & 0x3fff)); #if ISAMEM_DEBUG - if ((addr % 4096)==0) isamem_log("EMS readb(%06x) = %02x\n",addr-dev&0x3fff,ret); + if ((addr % 4096) == 0) + isamem_log("EMS readb(%06x) = %02x\n", addr - dev & 0x3fff, ret); #endif - return(ret); + return ret; } - /* Read one word from onboard paged RAM. */ static uint16_t ems_readw(uint32_t addr, void *priv) { - memdev_t *dev = (memdev_t *)priv; - uint16_t ret = 0xffff; + memdev_t *dev = (memdev_t *) priv; + uint16_t ret = 0xffff; /* Grab the data. */ - ret = *(uint16_t *)(dev->ems[((addr & 0xffff) >> 14)].addr + (addr & 0x3fff)); + ret = *(uint16_t *) (dev->ems[(addr & 0xffff) >> 14].addr + (addr & 0x3fff)); #if ISAMEM_DEBUG - if ((addr % 4096)==0) isamem_log("EMS readw(%06x) = %04x\n",addr-dev&0x3fff,ret); + if ((addr % 4096) == 0) + isamem_log("EMS readw(%06x) = %04x\n", addr - dev & 0x3fff, ret); #endif - return(ret); + return ret; } - /* Write one byte to onboard paged RAM. */ static void ems_writeb(uint32_t addr, uint8_t val, void *priv) { - memdev_t *dev = (memdev_t *)priv; + memdev_t *dev = (memdev_t *) priv; /* Write the data. */ #if ISAMEM_DEBUG - if ((addr % 4096)==0) isamem_log("EMS writeb(%06x, %02x)\n",addr-dev&0x3fff,val); + if ((addr % 4096) == 0) + isamem_log("EMS writeb(%06x, %02x)\n", addr - dev & 0x3fff, val); #endif - *(uint8_t *)(dev->ems[((addr & 0xffff) >> 14)].addr + (addr & 0x3fff)) = val; + *(uint8_t *) (dev->ems[(addr & 0xffff) >> 14].addr + (addr & 0x3fff)) = val; } - /* Write one word to onboard paged RAM. */ static void ems_writew(uint32_t addr, uint16_t val, void *priv) { - memdev_t *dev = (memdev_t *)priv; + memdev_t *dev = (memdev_t *) priv; /* Write the data. */ #if ISAMEM_DEBUG - if ((addr % 4096)==0) isamem_log("EMS writew(%06x, %04x)\n",addr&0x3fff,val); + if ((addr % 4096) == 0) + isamem_log("EMS writew(%06x, %04x)\n", addr & 0x3fff, val); #endif - *(uint16_t *)(dev->ems[((addr & 0xffff) >> 14)].addr + (addr & 0x3fff)) = val; + *(uint16_t *) (dev->ems[(addr & 0xffff) >> 14].addr + (addr & 0x3fff)) = val; } - /* Handle a READ operation from one of our registers. */ static uint8_t ems_read(uint16_t port, void *priv) { - memdev_t *dev = (memdev_t *)priv; - uint8_t ret = 0xff; - int vpage; + const memdev_t *dev = (memdev_t *) priv; + uint8_t ret = 0xff; + int vpage; /* Get the viewport page number. */ vpage = (port / EMS_PGSIZE); port &= (EMS_PGSIZE - 1); - switch(port - dev->base_addr) { - case 0x0000: /* page number register */ - ret = dev->ems[vpage].page; - if (dev->ems[vpage].enabled) - ret |= 0x80; - break; + switch (port - dev->base_addr) { + case 0x0000: /* page number register */ + ret = dev->ems[vpage].page; + if (dev->ems[vpage].enabled) + ret |= 0x80; + break; - case 0x0001: /* W/O */ - break; + case 0x0001: /* W/O */ + break; + + default: + break; } #if ISAMEM_DEBUG isamem_log("ISAMEM: read(%04x) = %02x)\n", port, ret); #endif - return(ret); + return ret; } - /* Handle a WRITE operation to one of our registers. */ static void ems_write(uint16_t port, uint8_t val, void *priv) { - memdev_t *dev = (memdev_t *)priv; - int vpage; + memdev_t *dev = (memdev_t *) priv; + int vpage; /* Get the viewport page number. */ vpage = (port / EMS_PGSIZE); @@ -336,134 +332,141 @@ ems_write(uint16_t port, uint8_t val, void *priv) isamem_log("ISAMEM: write(%04x, %02x) page=%d\n", port, val, vpage); #endif - switch(port - dev->base_addr) { - case 0x0000: /* page mapping registers */ - /* Set the page number. */ - dev->ems[vpage].enabled = (val & 0x80); - dev->ems[vpage].page = (val & 0x7f); + switch (port - dev->base_addr) { + case 0x0000: /* page mapping registers */ + /* Set the page number. */ + dev->ems[vpage].enabled = (val & 0x80); + dev->ems[vpage].page = (val & 0x7f); - /* Make sure we can do that.. */ - if (dev->flags & FLAG_CONFIG) { - if (dev->ems[vpage].page < dev->ems_pages) { - /* Pre-calculate the page address in EMS RAM. */ - dev->ems[vpage].addr = dev->ram + dev->ems_start + ((val & 0x7f) * EMS_PGSIZE); - } else { - /* That page does not exist. */ - dev->ems[vpage].enabled = 0; - } + /* Make sure we can do that.. */ + if (dev->flags & FLAG_CONFIG) { + if (dev->ems[vpage].page < dev->ems_pages) { + /* Pre-calculate the page address in EMS RAM. */ + dev->ems[vpage].addr = dev->ram + dev->ems_start + ((val & 0x7f) * EMS_PGSIZE); + } else { + /* That page does not exist. */ + dev->ems[vpage].enabled = 0; + } - if (dev->ems[vpage].enabled) { - /* Update the EMS RAM address for this page. */ - mem_mapping_set_exec(&dev->ems[vpage].mapping, - dev->ems[vpage].addr); + if (dev->ems[vpage].enabled) { + /* Update the EMS RAM address for this page. */ + mem_mapping_set_exec(&dev->ems[vpage].mapping, + dev->ems[vpage].addr); - /* Enable this page. */ - mem_mapping_enable(&dev->ems[vpage].mapping); - } else { - /* Disable this page. */ - mem_mapping_disable(&dev->ems[vpage].mapping); - } - } - break; + /* Enable this page. */ + mem_mapping_enable(&dev->ems[vpage].mapping); + } else { + /* Disable this page. */ + mem_mapping_disable(&dev->ems[vpage].mapping); + } + } + break; - case 0x0001: /* page frame registers */ - /* - * The EV-159 EMM driver configures the frame address - * by setting bits in these registers. The information - * in their manual is unclear, but here is what was - * found out by repeatedly changing EMM's config: - * - * 00 04 08 Address - * ----------------- - * 80 c0 e0 C0000 - * 80 c0 e0 C4000 - * 80 c0 e0 C8000 - * 80 c0 e0 CC000 - * 80 c0 e0 D0000 - * 80 c0 e0 D4000 - * 80 c0 e0 D8000 - * 80 c0 e0 DC000 - * 80 c0 e0 E0000 - */ -isamem_log("EMS: write(%02x) to register 1 !\n"); - dev->ems[vpage].frame = val; - if (val) - dev->flags |= FLAG_CONFIG; - break; + case 0x0001: /* page frame registers */ + /* + * The EV-159 EMM driver configures the frame address + * by setting bits in these registers. The information + * in their manual is unclear, but here is what was + * found out by repeatedly changing EMM's config: + * + * 00 04 08 Address + * ----------------- + * 80 c0 e0 C0000 + * 80 c0 e0 C4000 + * 80 c0 e0 C8000 + * 80 c0 e0 CC000 + * 80 c0 e0 D0000 + * 80 c0 e0 D4000 + * 80 c0 e0 D8000 + * 80 c0 e0 DC000 + * 80 c0 e0 E0000 + */ + isamem_log("EMS: write(%02x) to register 1 !\n"); + dev->ems[vpage].frame = val; + if (val) + dev->flags |= FLAG_CONFIG; + break; + + default: + break; } } - /* Initialize the device for use. */ static void * isamem_init(const device_t *info) { memdev_t *dev; - uint32_t k, t; - uint32_t addr; - uint32_t tot; - uint8_t *ptr; - int i; + uint32_t k; + uint32_t t; + uint32_t addr; + uint32_t tot; + uint8_t *ptr; /* Find our device and create an instance. */ - dev = (memdev_t *)malloc(sizeof(memdev_t)); + dev = (memdev_t *) malloc(sizeof(memdev_t)); memset(dev, 0x00, sizeof(memdev_t)); - dev->name = info->name; + dev->name = info->name; dev->board = info->local; /* Do per-board initialization. */ tot = 0; - switch(dev->board) { - case ISAMEM_IBMXT_CARD: /* IBM PC/XT Memory Expansion Card */ - case ISAMEM_GENXT_CARD: /* Generic PC/XT Memory Expansion Card */ - case ISAMEM_P5PAK_CARD: /* Paradise Systems 5-PAK */ - case ISAMEM_A6PAK_CARD: /* AST SixPakPlus */ - dev->total_size = device_get_config_int("size"); - dev->start_addr = device_get_config_int("start"); - tot = dev->total_size; - break; + switch (dev->board) { + case ISAMEM_IBMXT_CARD: /* IBM PC/XT Memory Expansion Card */ + case ISAMEM_GENXT_CARD: /* Generic PC/XT Memory Expansion Card */ + case ISAMEM_RAMCARD_CARD: /* Microsoft RAMCard for IBM PC */ + case ISAMEM_SYSTEMCARD_CARD: /* Microsoft SystemCard */ + case ISAMEM_P5PAK_CARD: /* Paradise Systems 5-PAK */ + case ISAMEM_A6PAK_CARD: /* AST SixPakPlus */ + dev->total_size = device_get_config_int("size"); + dev->start_addr = device_get_config_int("start"); + tot = dev->total_size; + break; - case ISAMEM_IBMAT_CARD: /* IBM PC/AT Memory Expansion Card */ - case ISAMEM_GENAT_CARD: /* Generic PC/AT Memory Expansion Card */ - dev->total_size = device_get_config_int("size"); - dev->start_addr = device_get_config_int("start"); - tot = dev->total_size; - dev->flags |= FLAG_WIDE; - break; + case ISAMEM_IBMAT_CARD: /* IBM PC/AT Memory Expansion Card */ + case ISAMEM_GENAT_CARD: /* Generic PC/AT Memory Expansion Card */ + dev->total_size = device_get_config_int("size"); + dev->start_addr = device_get_config_int("start"); + tot = dev->total_size; + dev->flags |= FLAG_WIDE; + break; - case ISAMEM_EMS5150_CARD: /* Micro Mainframe EMS-5150(T) */ - dev->base_addr = device_get_config_hex16("base"); - dev->total_size = device_get_config_int("size"); - dev->frame_addr = 0xD0000; - dev->flags |= (FLAG_EMS | FLAG_CONFIG); - break; + case ISAMEM_EMS5150_CARD: /* Micro Mainframe EMS-5150(T) */ + dev->base_addr = device_get_config_hex16("base"); + dev->total_size = device_get_config_int("size"); + dev->frame_addr = 0xD0000; + dev->flags |= (FLAG_EMS | FLAG_CONFIG); + break; - case ISAMEM_EV159_CARD: /* Everex EV-159 RAM 3000 */ - dev->base_addr = device_get_config_hex16("base"); - dev->total_size = device_get_config_int("size"); - dev->start_addr = device_get_config_int("start"); - tot = device_get_config_int("length"); - if (!!device_get_config_int("width")) - dev->flags |= FLAG_WIDE; - if (!!device_get_config_int("speed")) - dev->flags |= FLAG_FAST; - if (!!device_get_config_int("ems")) - dev->flags |= FLAG_EMS; -dev->frame_addr = 0xE0000; - break; + case ISAMEM_EV159_CARD: /* Everex EV-159 RAM 3000 */ + dev->base_addr = device_get_config_hex16("base"); + dev->total_size = device_get_config_int("size"); + dev->start_addr = device_get_config_int("start"); + tot = device_get_config_int("length"); + if (!!device_get_config_int("width")) + dev->flags |= FLAG_WIDE; + if (!!device_get_config_int("speed")) + dev->flags |= FLAG_FAST; + if (!!device_get_config_int("ems")) + dev->flags |= FLAG_EMS; + dev->frame_addr = 0xE0000; + break; - case ISAMEM_RAMPAGEXT_CARD: /* AST RAMpage/XT */ - case ISAMEM_ABOVEBOARD_CARD: /* Intel AboveBoard */ - case ISAMEM_BRAT_CARD: /* BocaRAM/AT */ - dev->base_addr = device_get_config_hex16("base"); - dev->total_size = device_get_config_int("size"); - dev->start_addr = device_get_config_int("start"); - dev->frame_addr = device_get_config_hex20("frame"); - if (!!device_get_config_int("width")) - dev->flags |= FLAG_WIDE; - if (!!device_get_config_int("speed")) - dev->flags |= FLAG_FAST; - break; + case ISAMEM_RAMPAGEXT_CARD: /* AST RAMpage/XT */ + case ISAMEM_ABOVEBOARD_CARD: /* Intel AboveBoard */ + case ISAMEM_BRAT_CARD: /* BocaRAM/AT */ + dev->base_addr = device_get_config_hex16("base"); + dev->total_size = device_get_config_int("size"); + dev->start_addr = device_get_config_int("start"); + dev->frame_addr = device_get_config_hex20("frame"); + if (!!device_get_config_int("width")) + dev->flags |= FLAG_WIDE; + if (!!device_get_config_int("speed")) + dev->flags |= FLAG_FAST; + break; + + default: + break; } /* Fix up the memory start address. */ @@ -472,20 +475,23 @@ dev->frame_addr = 0xE0000; /* Say hello! */ isamem_log("ISAMEM: %s (%iKB", info->name, dev->total_size); if (tot && (dev->total_size != tot)) - isamem_log(", %iKB for RAM", tot); - if (dev->flags & FLAG_FAST) isamem_log(", FAST"); - if (dev->flags & FLAG_WIDE) isamem_log(", 16BIT"); + isamem_log(", %iKB for RAM", tot); + if (dev->flags & FLAG_FAST) + isamem_log(", FAST"); + if (dev->flags & FLAG_WIDE) + isamem_log(", 16BIT"); + isamem_log(")\n"); /* Force (back to) 8-bit bus if needed. */ if ((!is286) && (dev->flags & FLAG_WIDE)) { - isamem_log("ISAMEM: not AT+ system, forcing 8-bit mode!\n"); - dev->flags &= ~FLAG_WIDE; + isamem_log("ISAMEM: not AT+ system, forcing 8-bit mode!\n"); + dev->flags &= ~FLAG_WIDE; } /* Allocate and initialize our RAM. */ - k = dev->total_size << 10; - dev->ram = (uint8_t *)malloc(k); + k = dev->total_size << 10; + dev->ram = (uint8_t *) malloc(k); memset(dev->ram, 0x00, k); ptr = dev->ram; @@ -497,82 +503,82 @@ dev->frame_addr = 0xE0000; tot <<= 10; addr = dev->start_addr; if (addr > 0 && tot > 0) { - /* Adjust K for the RAM we will use. */ - k -= tot; + /* Adjust K for the RAM we will use. */ + k -= tot; - /* - * First, see if we have to expand the conventional - * (low) memory area. This can extend up to 640KB, - * so check this first. - */ - t = (addr < RAM_TOPMEM) ? RAM_TOPMEM - addr : 0; - if (t > 0) { - /* - * We need T bytes to extend that area. - * - * If the board doesn't have that much, grab - * as much as we can. - */ - if (t > tot) - t = tot; - isamem_log("ISAMEM: RAM at %05iKB (%iKB)\n", addr>>10, t>>10); + /* + * First, see if we have to expand the conventional + * (low) memory area. This can extend up to 640KB, + * so check this first. + */ + t = (addr < RAM_TOPMEM) ? RAM_TOPMEM - addr : 0; + if (t > 0) { + /* + * We need T bytes to extend that area. + * + * If the board doesn't have that much, grab + * as much as we can. + */ + if (t > tot) + t = tot; + isamem_log("ISAMEM: RAM at %05iKB (%iKB)\n", addr >> 10, t >> 10); - dev->ext_ram[EXTRAM_CONVENTIONAL].ptr = ptr; - dev->ext_ram[EXTRAM_CONVENTIONAL].base = addr; + dev->ext_ram[EXTRAM_CONVENTIONAL].ptr = ptr; + dev->ext_ram[EXTRAM_CONVENTIONAL].base = addr; - /* Create, initialize and enable the low-memory mapping. */ - mem_mapping_add(&dev->low_mapping, addr, t, - ram_readb, - (dev->flags&FLAG_WIDE) ? ram_readw : NULL, - NULL, - ram_writeb, - (dev->flags&FLAG_WIDE) ? ram_writew : NULL, - NULL, - ptr, MEM_MAPPING_EXTERNAL, &dev->ext_ram[EXTRAM_CONVENTIONAL]); + /* Create, initialize and enable the low-memory mapping. */ + mem_mapping_add(&dev->low_mapping, addr, t, + ram_readb, + (dev->flags & FLAG_WIDE) ? ram_readw : NULL, + NULL, + ram_writeb, + (dev->flags & FLAG_WIDE) ? ram_writew : NULL, + NULL, + ptr, MEM_MAPPING_EXTERNAL, &dev->ext_ram[EXTRAM_CONVENTIONAL]); - /* Tell the memory system this is external RAM. */ - mem_set_mem_state(addr, t, - MEM_READ_EXTERNAL | MEM_WRITE_EXTERNAL); + /* Tell the memory system this is external RAM. */ + mem_set_mem_state(addr, t, + MEM_READ_EXTERNAL | MEM_WRITE_EXTERNAL); - /* Update pointers. */ - ptr += t; - tot -= t; - addr += t; - } + /* Update pointers. */ + ptr += t; + tot -= t; + addr += t; + } - /* Skip to high memory if needed. */ - if ((addr == RAM_TOPMEM) && (tot >= RAM_UMAMEM)) { - /* - * We have more RAM available, but we are at the - * top of conventional RAM. So, the next 384K are - * skipped, and placed into different mappings so - * they can be re-mapped later. - */ - t = RAM_UMAMEM; /* 384KB */ + /* Skip to high memory if needed. */ + if ((addr == RAM_TOPMEM) && (tot >= RAM_UMAMEM)) { + /* + * We have more RAM available, but we are at the + * top of conventional RAM. So, the next 384K are + * skipped, and placed into different mappings so + * they can be re-mapped later. + */ + t = RAM_UMAMEM; /* 384KB */ - isamem_log("ISAMEM: RAM at %05iKB (%iKB)\n", addr>>10, t>>10); + isamem_log("ISAMEM: RAM at %05iKB (%iKB)\n", addr >> 10, t >> 10); - dev->ext_ram[EXTRAM_HIGH].ptr = ptr; - dev->ext_ram[EXTRAM_HIGH].base = addr + tot; + dev->ext_ram[EXTRAM_HIGH].ptr = ptr; + dev->ext_ram[EXTRAM_HIGH].base = addr + tot; - /* Update and enable the remap. */ - mem_mapping_set(&ram_remapped_mapping, - addr + tot, t, - ram_readb, ram_readw, NULL, - ram_writeb, ram_writew, NULL, - ptr, MEM_MAPPING_EXTERNAL, - &dev->ext_ram[EXTRAM_HIGH]); - mem_mapping_disable(&ram_remapped_mapping); + /* Update and enable the remap. */ + mem_mapping_set(&ram_remapped_mapping, + addr + tot, t, + ram_readb, ram_readw, NULL, + ram_writeb, ram_writew, NULL, + ptr, MEM_MAPPING_EXTERNAL, + &dev->ext_ram[EXTRAM_HIGH]); + mem_mapping_disable(&ram_remapped_mapping); - /* Tell the memory system this is external RAM. */ - mem_set_mem_state(addr + tot, t, - MEM_READ_EXTERNAL | MEM_WRITE_EXTERNAL); + /* Tell the memory system this is external RAM. */ + mem_set_mem_state(addr + tot, t, + MEM_READ_EXTERNAL | MEM_WRITE_EXTERNAL); - /* Update pointers. */ - ptr += t; - tot -= t; - addr += t; - } + /* Update pointers. */ + ptr += t; + tot -= t; + addr += t; + } } /* @@ -583,802 +589,1038 @@ dev->frame_addr = 0xE0000; * protected mode. */ if (is286 && addr > 0 && tot > 0) { - t = tot; - isamem_log("ISAMEM: RAM at %05iKB (%iKB)\n", addr>>10, t>>10); + t = tot; + isamem_log("ISAMEM: RAM at %05iKB (%iKB)\n", addr >> 10, t >> 10); - dev->ext_ram[EXTRAM_XMS].ptr = ptr; - dev->ext_ram[EXTRAM_XMS].base = addr; + dev->ext_ram[EXTRAM_XMS].ptr = ptr; + dev->ext_ram[EXTRAM_XMS].base = addr; - /* Create, initialize and enable the high-memory mapping. */ - mem_mapping_add(&dev->high_mapping, addr, t, - ram_readb, ram_readw, NULL, - ram_writeb, ram_writew, NULL, - ptr, MEM_MAPPING_EXTERNAL, &dev->ext_ram[EXTRAM_XMS]); + /* Create, initialize and enable the high-memory mapping. */ + mem_mapping_add(&dev->high_mapping, addr, t, + ram_readb, ram_readw, NULL, + ram_writeb, ram_writew, NULL, + ptr, MEM_MAPPING_EXTERNAL, &dev->ext_ram[EXTRAM_XMS]); - /* Tell the memory system this is external RAM. */ - mem_set_mem_state(addr, t, MEM_READ_EXTERNAL | MEM_WRITE_EXTERNAL); + /* Tell the memory system this is external RAM. */ + mem_set_mem_state(addr, t, MEM_READ_EXTERNAL | MEM_WRITE_EXTERNAL); - /* Update pointers. */ - ptr += t; - tot -= t; - addr += t; + /* Update pointers. */ + ptr += t; + tot -= t; + addr += t; } isa_mem_size += dev->total_size - (k >> 10); /* If EMS is enabled, use the remainder for EMS. */ if (dev->flags & FLAG_EMS) { - /* EMS 3.2 cannot have more than 2048KB per board. */ - t = k; - if (t > EMS_MAXSIZE) - t = EMS_MAXSIZE; + /* EMS 3.2 cannot have more than 2048KB per board. */ + t = k; + if (t > EMS_MAXSIZE) + t = EMS_MAXSIZE; - /* Set up where EMS begins in local RAM, and how much we have. */ - dev->ems_start = ptr - dev->ram; - dev->ems_size = t >> 10; - dev->ems_pages = t / EMS_PGSIZE; - isamem_log("ISAMEM: EMS enabled, I/O=%04XH, %iKB (%i pages)", - dev->base_addr, dev->ems_size, dev->ems_pages); - if (dev->frame_addr > 0) - isamem_log(", Frame=%05XH", dev->frame_addr); - isamem_log("\n"); + /* Set up where EMS begins in local RAM, and how much we have. */ + dev->ems_start = ptr - dev->ram; + dev->ems_size = t >> 10; + dev->ems_pages = t / EMS_PGSIZE; + isamem_log("ISAMEM: EMS enabled, I/O=%04XH, %iKB (%i pages)", + dev->base_addr, dev->ems_size, dev->ems_pages); + if (dev->frame_addr > 0) + isamem_log(", Frame=%05XH", dev->frame_addr); - /* - * For each supported page (we can have a maximum of 4), - * create, initialize and disable the mappings, and set - * up the I/O control handler. - */ - for (i = 0; i < EMS_MAXPAGE; i++) { - /* Create and initialize a page mapping. */ - mem_mapping_add(&dev->ems[i].mapping, - dev->frame_addr + (EMS_PGSIZE*i), EMS_PGSIZE, - ems_readb, - (dev->flags&FLAG_WIDE) ? ems_readw : NULL, - NULL, - ems_writeb, - (dev->flags&FLAG_WIDE) ? ems_writew : NULL, - NULL, - ptr, MEM_MAPPING_EXTERNAL, - dev); + isamem_log("\n"); - /* For now, disable it. */ - mem_mapping_disable(&dev->ems[i].mapping); + /* + * For each supported page (we can have a maximum of 4), + * create, initialize and disable the mappings, and set + * up the I/O control handler. + */ + for (uint8_t i = 0; i < EMS_MAXPAGE; i++) { + /* Create and initialize a page mapping. */ + mem_mapping_add(&dev->ems[i].mapping, + dev->frame_addr + (EMS_PGSIZE * i), EMS_PGSIZE, + ems_readb, + (dev->flags & FLAG_WIDE) ? ems_readw : NULL, + NULL, + ems_writeb, + (dev->flags & FLAG_WIDE) ? ems_writew : NULL, + NULL, + ptr, MEM_MAPPING_EXTERNAL, + dev); - /* Set up an I/O port handler. */ - io_sethandler(dev->base_addr + (EMS_PGSIZE*i), 2, - ems_read,NULL,NULL, ems_write,NULL,NULL, dev); - } + /* For now, disable it. */ + mem_mapping_disable(&dev->ems[i].mapping); + + /* Set up an I/O port handler. */ + io_sethandler(dev->base_addr + (EMS_PGSIZE * i), 2, + ems_read, NULL, NULL, ems_write, NULL, NULL, dev); + } } /* Let them know our device instance. */ - return((void *) dev); + return ((void *) dev); } - /* Remove the device from the system. */ static void isamem_close(void *priv) { - memdev_t *dev = (memdev_t *)priv; - int i; + memdev_t *dev = (memdev_t *) priv; if (dev->flags & FLAG_EMS) { - for (i = 0; i < EMS_MAXPAGE; i++) { - io_removehandler(dev->base_addr + (EMS_PGSIZE*i), 2, - ems_read,NULL,NULL, ems_write,NULL,NULL, dev); - - } + for (uint8_t i = 0; i < EMS_MAXPAGE; i++) { + io_removehandler(dev->base_addr + (EMS_PGSIZE * i), 2, + ems_read, NULL, NULL, ems_write, NULL, NULL, dev); + } } if (dev->ram != NULL) - free(dev->ram); + free(dev->ram); free(dev); } - -static const device_config_t ibmxt_config[] = -{ - { - "size", "Memory Size", CONFIG_SPINNER, "", 128, "", - { 0, 512, 16 }, - { { 0 } } - }, - { - "start", "Start Address", CONFIG_SPINNER, "", 256, "", - { 0, 576, 64 }, - { { 0 } } - }, - { - "", "", -1 - } +static const device_config_t ibmxt_config[] = { + // clang-format off + { + .name = "size", + .description = "Memory Size", + .type = CONFIG_SPINNER, + .default_string = "", + .default_int = 128, + .file_filter = "", + .spinner = { + .min = 0, + .max = 512, + .step = 16 + }, + .selection = { { 0 } } + }, + { + .name = "start", + .description = "Start Address", + .type = CONFIG_SPINNER, + .default_string = "", + .default_int = 256, + .file_filter = "", + .spinner = { + .min = 0, + .max = 576, + .step = 64 + }, + .selection = { { 0 } } + }, + { .name = "", .description = "", .type = CONFIG_END } + // clang-format on }; static const device_t ibmxt_device = { - "IBM PC/XT Memory Expansion", - "ibmxt", - DEVICE_ISA, - ISAMEM_IBMXT_CARD, - isamem_init, isamem_close, NULL, - { NULL }, NULL, NULL, - ibmxt_config + .name = "IBM PC/XT Memory Expansion", + .internal_name = "ibmxt", + .flags = DEVICE_ISA, + .local = ISAMEM_IBMXT_CARD, + .init = isamem_init, + .close = isamem_close, + .reset = NULL, + { .available = NULL }, + .speed_changed = NULL, + .force_redraw = NULL, + .config = ibmxt_config }; - -static const device_config_t genericxt_config[] = -{ - { - "size", "Memory Size", CONFIG_SPINNER, "", 16, "", - { 0, 640, 16 }, - { { 0 } } - }, - { - "start", "Start Address", CONFIG_SPINNER, "", 0, "", - { 0, 624, 16 }, - { { 0 } } - }, - { - "", "", -1 - } +static const device_config_t genericxt_config[] = { + // clang-format off + { + .name = "size", + .description = "Memory Size", + .type = CONFIG_SPINNER, + .default_string = "", + .default_int = 16, + .file_filter = "", + .spinner = { + .min = 0, + .max = 640, + .step = 16 + }, + .selection = { { 0 } } + }, + { + .name = "start", + .description = "Start Address", + .type = CONFIG_SPINNER, + .default_string = "", + .default_int = 0, + .file_filter = "", + .spinner = { + .min = 0, + .max = 624, + .step = 16 + }, + .selection = { { 0 } } + }, + { .name = "", .description = "", .type = CONFIG_END } + // clang-format on }; static const device_t genericxt_device = { - "Generic PC/XT Memory Expansion", - "genericxt", - DEVICE_ISA, - ISAMEM_GENXT_CARD, - isamem_init, isamem_close, NULL, - { NULL }, NULL, NULL, - genericxt_config + .name = "Generic PC/XT Memory Expansion", + .internal_name = "genericxt", + .flags = DEVICE_ISA, + .local = ISAMEM_GENXT_CARD, + .init = isamem_init, + .close = isamem_close, + .reset = NULL, + { .available = NULL }, + .speed_changed = NULL, + .force_redraw = NULL, + .config = genericxt_config }; +static const device_config_t msramcard_config[] = { + // clang-format off + { + .name = "size", + .description = "Memory Size", + .type = CONFIG_SPINNER, + .default_string = "", + .default_int = 64, + .file_filter = "", + .spinner = { + .min = 0, + .max = 256, + .step = 64 + }, + .selection = { { 0 } } + }, + { + .name = "start", + .description = "Start Address", + .type = CONFIG_SPINNER, + .default_string = "", + .default_int = 0, + .file_filter = "", + .spinner = { + .min = 0, + .max = 624, + .step = 64 + }, + .selection = { { 0 } } + }, + { .name = "", .description = "", .type = CONFIG_END } + // clang-format on +}; -static const device_config_t ibmat_config[] = -{ - { - "size", "Memory Size", CONFIG_SPINNER, "", 512, "", - { 0, 12288, 512 }, - { { 0 } } - }, - { - "start", "Start Address", CONFIG_SPINNER, "", 512, "", - { 0, 15872, 512 }, - { { 0 } } - }, - { - "", "", -1 - } +static const device_t msramcard_device = { + .name = "Microsoft RAMCard for IBM PC", + .internal_name = "msramcard", + .flags = DEVICE_ISA, + .local = ISAMEM_RAMCARD_CARD, + .init = isamem_init, + .close = isamem_close, + .reset = NULL, + { .available = NULL }, + .speed_changed = NULL, + .force_redraw = NULL, + .config = msramcard_config +}; + +static const device_config_t mssystemcard_config[] = { + // clang-format off + { + .name = "size", + .description = "Memory Size", + .type = CONFIG_SPINNER, + .default_string = "", + .default_int = 64, + .file_filter = "", + .spinner = { + .min = 0, + .max = 256, + .step = 64 + }, + .selection = { { 0 } } + }, + { + .name = "start", + .description = "Start Address", + .type = CONFIG_SPINNER, + .default_string = "", + .default_int = 0, + .file_filter = "", + .spinner = { + .min = 0, + .max = 624, + .step = 64 + }, + .selection = { { 0 } } + }, + { .name = "", .description = "", .type = CONFIG_END } + // clang-format on +}; + +static const device_t mssystemcard_device = { + .name = "Microsoft SystemCard", + .internal_name = "mssystemcard", + .flags = DEVICE_ISA, + .local = ISAMEM_SYSTEMCARD_CARD, + .init = isamem_init, + .close = isamem_close, + .reset = NULL, + { .available = NULL }, + .speed_changed = NULL, + .force_redraw = NULL, + .config = mssystemcard_config +}; + +static const device_config_t ibmat_config[] = { + // clang-format off + { + .name = "size", + .description = "Memory Size", + .type = CONFIG_SPINNER, + .default_string = "", + .default_int = 512, + .file_filter = "", + .spinner = { + .min = 0, + .max = 12288, + .step = 512 + }, + .selection = { { 0 } } + }, + { + .name = "start", + .description = "Start Address", + .type = CONFIG_SPINNER, + .default_string = "", + .default_int = 512, + .file_filter = "", + .spinner = { + .min = 0, + .max = 15872, + .step = 512 + }, + .selection = { { 0 } } + }, + { .name = "", .description = "", .type = CONFIG_END } + // clang-format on }; static const device_t ibmat_device = { - "IBM PC/AT Memory Expansion", - "ibmat", - DEVICE_ISA, - ISAMEM_IBMAT_CARD, - isamem_init, isamem_close, NULL, - { NULL }, NULL, NULL, - ibmat_config + .name = "IBM PC/AT Memory Expansion", + .internal_name = "ibmat", + .flags = DEVICE_ISA, + .local = ISAMEM_IBMAT_CARD, + .init = isamem_init, + .close = isamem_close, + .reset = NULL, + { .available = NULL }, + .speed_changed = NULL, + .force_redraw = NULL, + .config = ibmat_config }; - -static const device_config_t genericat_config[] = -{ - { - "size", "Memory Size", CONFIG_SPINNER, "", 512, "", - { 0, 16384, 512 }, - { { 0 } } - }, - { - "start", "Start Address", CONFIG_SPINNER, "", 512, "", - { 0, 15872, 128 }, - { { 0 } } - }, - { - "", "", -1 - } +static const device_config_t genericat_config[] = { + // clang-format off + { + .name = "size", + .description = "Memory Size", + .type = CONFIG_SPINNER, + .default_string = "", + .default_int = 512, + .file_filter = "", + .spinner = { + .min = 0, + .max = 16384, + .step = 512 + }, + .selection = { { 0 } } + }, + { + .name = "start", + .description = "Start Address", + .type = CONFIG_SPINNER, + .default_string = "", + .default_int = 512, + .file_filter = "", + .spinner = { + .min = 0, + .max = 15872, + .step = 128 + }, + .selection = { { 0 } } + }, + { .name = "", .description = "", .type = CONFIG_END } + // clang-format on }; static const device_t genericat_device = { - "Generic PC/AT Memory Expansion", - "genericat", - DEVICE_ISA, - ISAMEM_GENAT_CARD, - isamem_init, isamem_close, NULL, - { NULL }, NULL, NULL, - genericat_config + .name = "Generic PC/AT Memory Expansion", + .internal_name = "genericat", + .flags = DEVICE_ISA, + .local = ISAMEM_GENAT_CARD, + .init = isamem_init, + .close = isamem_close, + .reset = NULL, + { .available = NULL }, + .speed_changed = NULL, + .force_redraw = NULL, + .config = genericat_config }; - -static const device_config_t p5pak_config[] = -{ - { - "size", "Memory Size", CONFIG_SPINNER, "", 128, "", - { 0, 384, 64 }, - { { 0 } } - }, - { - "start", "Start Address", CONFIG_SPINNER, "", 512, "", - { 64, 576, 64 }, - { { 0 } } - }, - { - "", "", -1 - } +static const device_config_t p5pak_config[] = { + // clang-format off + { + .name = "size", + .description = "Memory Size", + .type = CONFIG_SPINNER, + .default_string = "", + .default_int = 128, + .file_filter = "", + .spinner = { + .min = 0, + .max = 384, + .step = 64 + }, + .selection = { { 0 } } + }, + { + .name = "start", + .description = "Start Address", + .type = CONFIG_SPINNER, + .default_string = "", + .default_int = 512, + .file_filter = "", + .spinner = { + .min = 64, + .max = 576, + .step = 64 + }, + .selection = { { 0 } } + }, + { .name = "", .description = "", .type = CONFIG_END } + // clang-format on }; static const device_t p5pak_device = { - "Paradise Systems 5-PAK", - "p5pak", - DEVICE_ISA, - ISAMEM_P5PAK_CARD, - isamem_init, isamem_close, NULL, - { NULL }, NULL, NULL, - p5pak_config + .name = "Paradise Systems 5-PAK", + .internal_name = "p5pak", + .flags = DEVICE_ISA, + .local = ISAMEM_P5PAK_CARD, + .init = isamem_init, + .close = isamem_close, + .reset = NULL, + { .available = NULL }, + .speed_changed = NULL, + .force_redraw = NULL, + .config = p5pak_config }; - -static const device_config_t a6pak_config[] = -{ - { - "size", "Memory Size", CONFIG_SPINNER, "", 64, "", - { 0, 576, 64 }, - { { 0 } } - }, - { - "start", "Start Address", CONFIG_SPINNER, "", 256, "", - { 64, 512, 64 }, - { { 0 } } - }, - { - "", "", -1 - } +static const device_config_t a6pak_config[] = { + // clang-format off + { + .name = "size", + .description = "Memory Size", + .type = CONFIG_SPINNER, + .default_string = "", + .default_int = 64, + .file_filter = "", + .spinner = { + .min = 0, + .max = 576, + .step = 64 + }, + .selection = { { 0 } } + }, + { + .name = "start", + .description = "Start Address", + .type = CONFIG_SPINNER, + .default_string = "", + .default_int = 256, + .file_filter = "", + .spinner = { + .min = 64, + .max = 512, + .step = 64 + }, + .selection = { { 0 } } + }, + { .name = "", .description = "", .type = CONFIG_END } + // clang-format on }; static const device_t a6pak_device = { - "AST SixPakPlus", - "a6pak", - DEVICE_ISA, - ISAMEM_A6PAK_CARD, - isamem_init, isamem_close, NULL, - { NULL }, NULL, NULL, - a6pak_config + .name = "AST SixPakPlus", + .internal_name = "a6pak", + .flags = DEVICE_ISA, + .local = ISAMEM_A6PAK_CARD, + .init = isamem_init, + .close = isamem_close, + .reset = NULL, + { .available = NULL }, + .speed_changed = NULL, + .force_redraw = NULL, + .config = a6pak_config }; - -static const device_config_t ems5150_config[] = -{ - { - "size", "Memory Size", CONFIG_SPINNER, "", 256, - "", - { 0, 2048, 64 }, - { { 0 } } - }, - { - "base", "Address", CONFIG_HEX16, "", 0, "", { 0 }, - { - { - "Disabled", 0 - }, - { - "Board 1", 0x0208 - }, - { - "Board 2", 0x020a - }, - { - "Board 3", 0x020c - }, - { - "Board 4", 0x020e - }, - { - "" - } - }, - }, - { - "", "", -1 - } +static const device_config_t ems5150_config[] = { + // clang-format off + { + .name = "size", + .description = "Memory Size", + .type = CONFIG_SPINNER, + .default_string = "", + .default_int = 256, + .file_filter = "", + .spinner = { + .min = 0, + .max = 2048, + .step = 64 + }, + .selection = { { 0 } } + }, + { + .name = "base", + .description = "Address", + .type = CONFIG_HEX16, + .default_string = "", + .default_int = 0, + .file_filter = "", + .spinner = { 0 }, + .selection = { + { .description = "Disabled", .value = 0x0000 }, + { .description = "Board 1", .value = 0x0208 }, + { .description = "Board 2", .value = 0x020a }, + { .description = "Board 3", .value = 0x020c }, + { .description = "Board 4", .value = 0x020e }, + { .description = "" } + }, + }, + { .name = "", .description = "", .type = CONFIG_END } + // clang-format on }; static const device_t ems5150_device = { - "Micro Mainframe EMS-5150(T)", - "ems5150", - DEVICE_ISA, - ISAMEM_EMS5150_CARD, - isamem_init, isamem_close, NULL, - { NULL }, NULL, NULL, - ems5150_config + .name = "Micro Mainframe EMS-5150(T)", + .internal_name = "ems5150", + .flags = DEVICE_ISA, + .local = ISAMEM_EMS5150_CARD, + .init = isamem_init, + .close = isamem_close, + .reset = NULL, + { .available = NULL }, + .speed_changed = NULL, + .force_redraw = NULL, + .config = ems5150_config }; - -static const device_config_t ev159_config[] = -{ - { - "size", "Memory Size", CONFIG_SPINNER, "", 512, "", - { 0, 3072, 512 }, - { { 0 } } - }, - { - "start", "Start Address", CONFIG_SPINNER, "", 0, "", - { 0, 16128, 128 }, - { { 0 } } - }, - { - "length", "Contiguous Size", CONFIG_SPINNER, "", 0, "", - { 0, 16384, 128 }, - { { 0 } } - }, - { - "width", "I/O Width", CONFIG_SELECTION, "", 0, "", { 0 }, - { - { - "8-bit", 0 - }, - { - "16-bit", 1 - }, - { - "" - } - }, - }, - { - "speed", "Transfer Speed", CONFIG_SELECTION, "", 0, "", { 0 }, - { - { - "Standard (150ns)", 0 - }, - { - "High-Speed (120ns)", 1 - }, - { - "" - } - } - }, - { - "ems", "EMS mode", CONFIG_SELECTION, "", 0, "", { 0 }, - { - { - "Disabled", 0 - }, - { - "Enabled", 1 - }, - { - "" - } - }, - }, - { - "base", "Address", CONFIG_HEX16, "", 0x0258, "", { 0 }, - { - { - "208H", 0x0208 - }, - { - "218H", 0x0218 - }, - { - "258H", 0x0258 - }, - { - "268H", 0x0268 - }, - { - "2A8H", 0x02A8 - }, - { - "2B8H", 0x02B8 - }, - { - "2E8H", 0x02E8 - }, - { - "" - } - }, - }, - { - "", "", -1 - } +static const device_config_t ev159_config[] = { + // clang-format off + { + .name = "size", + .description = "Memory Size", + .type = CONFIG_SPINNER, + .default_string = "", + .default_int = 512, + .file_filter = "", + .spinner = { + .min = 0, + .max = 3072, + .step = 512 + }, + .selection = { { 0 } } + }, + { + .name = "start", + .description = "Start Address", + .type = CONFIG_SPINNER, + .default_string = "", + .default_int = 0, + .file_filter = "", + .spinner = { + .min = 0, + .max = 16128, + .step = 128 + }, + .selection = { { 0 } } + }, + { + .name = "length", + .description = "Contiguous Size", + .type = CONFIG_SPINNER, + .default_string = "", + .default_int = 0, + .file_filter = "", + .spinner = { + .min = 0, + .max = 16384, + .step = 128 + }, + .selection = { { 0 } } + }, + { + .name = "width", + .description = "I/O Width", + .type = CONFIG_SELECTION, + .default_string = "", + .default_int = 0, + .file_filter = "", + .spinner = { 0 }, + .selection = { + { .description = "8-bit", .value = 0 }, + { .description = "16-bit", .value = 1 }, + { .description = "" } + }, + }, + { + .name = "speed", + .description = "Transfer Speed", + .type = CONFIG_SELECTION, + .default_string = "", + .default_int = 0, + .file_filter = "", + .spinner = { 0 }, + .selection = { + { .description = "Standard (150ns)", .value = 0 }, + { .description = "High-Speed (120ns)", .value = 1 }, + { .description = "" } + } + }, + { + .name = "ems", + .description = "EMS mode", + .type = CONFIG_SELECTION, + .default_string = "", + .default_int = 0, + .file_filter = "", + .spinner = { 0 }, + .selection = { + { .description = "Disabled", .value = 0 }, + { .description = "Enabled", .value = 1 }, + { .description = "" } + }, + }, + { + .name = "base", + .description = "Address", + .type = CONFIG_HEX16, + .default_string = "", + .default_int = 0x0258, + .file_filter = "", + .spinner = { 0 }, + .selection = { + { .description = "208H", .value = 0x0208 }, + { .description = "218H", .value = 0x0218 }, + { .description = "258H", .value = 0x0258 }, + { .description = "268H", .value = 0x0268 }, + { .description = "2A8H", .value = 0x02A8 }, + { .description = "2B8H", .value = 0x02B8 }, + { .description = "2E8H", .value = 0x02E8 }, + { .description = "" } + }, + }, + { .name = "", .description = "", .type = CONFIG_END } + // clang-format on }; static const device_t ev159_device = { - "Everex EV-159 RAM 3000 Deluxe", - "ev159", - DEVICE_ISA, - ISAMEM_EV159_CARD, - isamem_init, isamem_close, NULL, - { NULL }, NULL, NULL, - ev159_config + .name = "Everex EV-159 RAM 3000 Deluxe", + .internal_name = "ev159", + .flags = DEVICE_ISA, + .local = ISAMEM_EV159_CARD, + .init = isamem_init, + .close = isamem_close, + .reset = NULL, + { .available = NULL }, + .speed_changed = NULL, + .force_redraw = NULL, + .config = ev159_config }; - #if defined(DEV_BRANCH) && defined(USE_ISAMEM_BRAT) -static const device_config_t brat_config[] = -{ - { - "base", "Address", CONFIG_HEX16, "", 0x0258, "", { 0 }, - { - { - "208H", 0x0208 - }, - { - "218H", 0x0218 - }, - { - "258H", 0x0258 - }, - { - "268H", 0x0268 - }, - { - "" - } - }, - }, - { - "frame", "Frame Address", CONFIG_HEX20, "", 0, "", { 0 }, - { - { - "Disabled", 0x00000 - }, - { - "D000H", 0xD0000 - }, - { - "E000H", 0xE0000 - }, - { - "" - } - }, - }, - { - "width", "I/O Width", CONFIG_SELECTION, "", 8, "", { 0 }, - { - { - "8-bit", 8 - }, - { - "16-bit", 16 - }, - { - "" - } - }, - }, - { - "speed", "Transfer Speed", CONFIG_SELECTION, "", 0, "", { 0 }, - { - { - "Standard", 0 - }, - { - "High-Speed", 1 - }, - { - "" - } - } - }, - { - "size", "Memory Size", CONFIG_SPINNER, "", 128, - "", - { 0, 8192, 512 }, - { { 0 } } - }, - { - "", "", -1 - } +static const device_config_t brat_config[] = { + // clang-format off + { + .name = "base", + .description = "Address", + .type = CONFIG_HEX16, + .default_string = "", + .default_int = 0x0258, + .file_filter = "", + .spinner = { 0 }, + .selection = { + { .description = "208H", .value = 0x0208 }, + { .description = "218H", .value = 0x0218 }, + { .description = "258H", .value = 0x0258 }, + { .description = "268H", .value = 0x0268 }, + { .description = "" } + }, + }, + { + .name = "frame", + .description = "Frame Address", + .type = CONFIG_HEX20, + .default_string = "", + .default_int = 0, + .file_filter = "", + .spinner = { 0 }, + .selection = { + { .description = "Disabled", .value = 0x00000 }, + { .description = "D000H", .value = 0xD0000 }, + { .description = "E000H", .value = 0xE0000 }, + { .description = "" } + }, + }, + { + .name = "width", + .description = "I/O Width", + .type = CONFIG_SELECTION, + .default_string = "", + .default_int = 8, + .file_filter = "", + .spinner = { 0 }, + .selection = { + { .description = "8-bit", .value = 8 }, + { .description = "16-bit", .value = 16 }, + { .description = "" } + }, + }, + { + .name = "speed", + .description = "Transfer Speed", + .type = CONFIG_SELECTION, + .default_string = "", + .default_int = 0, + .file_filter = "", + .spinner = { 0 }, + .selection = { + { .description = "Standard", .value = 0 }, + { .description = "High-Speed", .value = 1 }, + { .description = "" } + } + }, + { + .name = "size", + .description = "Memory Size", + .type = CONFIG_SPINNER, + .default_string = "", + .default_int = 128, + .file_filter = "", + .spinner = { + .min = 0, + .max = 8192, + .step = 512 + }, + .selection = { { 0 } } + }, + { .name = "", .description = "", .type = CONFIG_END } + // clang-format on }; static const device_t brat_device = { - "BocaRAM/AT", - "brat", - DEVICE_ISA, - ISAMEM_BRAT_CARD, - isamem_init, isamem_close, NULL, - { NULL }, NULL, NULL, - brat_config + .name = "BocaRAM/AT", + .internal_name = "brat", + .flags = DEVICE_ISA, + .local = ISAMEM_BRAT_CARD, + .init = isamem_init, + .close = isamem_close, + .reset = NULL, + { .available = NULL }, + .speed_changed = NULL, + .force_redraw = NULL, + .config = brat_config }; #endif - #if defined(DEV_BRANCH) && defined(USE_ISAMEM_RAMPAGE) -static const device_config_t rampage_config[] = -{ - { - "base", "Address", CONFIG_HEX16, "", 0x0258, "", { 0 }, - { - { - "208H", 0x0208 - }, - { - "218H", 0x0218 - }, - { - "258H", 0x0258 - }, - { - "268H", 0x0268 - }, - { - "2A8H", 0x02A8 - }, - { - "2B8H", 0x02B8 - }, - { - "2E8H", 0x02E8 - }, - { - "" - } - }, - }, - { - "frame", "Frame Address", CONFIG_HEX20, "", 0, "", { 0 }, - { - { - "Disabled", 0x00000 - }, - { - "C000H", 0xC0000 - }, - { - "D000H", 0xD0000 - }, - { - "E000H", 0xE0000 - }, - { - "" - } - }, - }, - { - "width", "I/O Width", CONFIG_SELECTION, "", 8, "", { 0 }, - { - { - "8-bit", 8 - }, - { - "16-bit", 16 - }, - { - "" - } - }, - }, - { - "speed", "Transfer Speed", CONFIG_SELECTION, "", 0, "", { 0 }, - { - { - "Standard", 0 - }, - { - "High-Speed", 1 - }, - { - "" - } - } - }, - { - "size", "Memory Size", CONFIG_SPINNER, "", 128, - "", - { 0, 8192, 128 }, - { { 0 } } - }, - { - "", "", -1 - } +static const device_config_t rampage_config[] = { + // clang-format off + { + .name = "base", + .description = "Address", + .type = CONFIG_HEX16, + .default_string = "", + .default_int = 0x0258, + .file_filter = "", + .spinner = { 0 }, + .selection = { + { .description = "208H", .value = 0x0208 }, + { .description = "218H", .value = 0x0218 }, + { .description = "258H", .value = 0x0258 }, + { .description = "268H", .value = 0x0268 }, + { .description = "2A8H", .value = 0x02A8 }, + { .description = "2B8H", .value = 0x02B8 }, + { .description = "2E8H", .value = 0x02E8 }, + { .description = "" } + }, + }, + { + .name = "frame", + .description = "Frame Address", + .type = CONFIG_HEX20, + .default_string = "", + .default_int = 0, + .file_filter = "", + .spinner = { 0 }, + .selection = { + { .description = "Disabled", .value = 0x00000 }, + { .description = "C000H", .value = 0xC0000 }, + { .description = "D000H", .value = 0xD0000 }, + { .description = "E000H", .value = 0xE0000 }, + { .description = "" } + }, + }, + { + .name = "width", + .description = "I/O Width", + .type = CONFIG_SELECTION, + .default_string = "", + .default_int = 8, + .file_filter = "", + .spinner = { 0 }, + .selection = { + { .description = "8-bit", .value = 8 }, + { .description = "16-bit", .value = 16 }, + { .description = "" } + }, + }, + { + .name = "speed", + .description = "Transfer Speed", + .type = CONFIG_SELECTION, + .default_string = "", + .default_int = 0, + .file_filter = "", + .spinner = { 0 }, + .selection = { + { .description = "Standard", .value = 0 }, + { .description = "High-Speed", .value = 1 }, + { .description = "" } + } + }, + { + .name = "size", + .description = "Memory Size", + .type = CONFIG_SPINNER, + .default_string = "", + .default_int = 128, + .file_filter = "", + .spinner = { + .min = 0, + .max = 8192, + .step = 128 + }, + .selection = { { 0 } } + }, + { .name = "", .description = "", .type = CONFIG_END } + // clang-format on }; static const device_t rampage_device = { - "AST RAMpage/XT", - "rampage", - DEVICE_ISA, - ISAMEM_RAMPAGEXT_CARD, - isamem_init, isamem_close, NULL, - { NULL }, NULL, NULL, - rampage_config + .name = "AST RAMpage/XT", + .internal_name = "rampage", + .flags = DEVICE_ISA, + .local = ISAMEM_RAMPAGEXT_CARD, + .init = isamem_init, + .close = isamem_close, + .reset = NULL, + { .available = NULL }, + .speed_changed = NULL, + .force_redraw = NULL, + .config = rampage_config }; #endif - #if defined(DEV_BRANCH) && defined(USE_ISAMEM_IAB) -static const device_config_t iab_config[] = -{ - { - "base", "Address", CONFIG_HEX16, "", 0x0258, "", { 0 }, - { - { - "208H", 0x0208 - }, - { - "218H", 0x0218 - }, - { - "258H", 0x0258 - }, - { - "268H", 0x0268 - }, - { - "2A8H", 0x02A8 - }, - { - "2B8H", 0x02B8 - }, - { - "2E8H", 0x02E8 - }, - { - "" - } - }, - }, - { - "frame", "Frame Address", CONFIG_HEX20, "", 0, "", { 0 }, - { - { - "Disabled", 0x00000 - }, - { - "C000H", 0xC0000 - }, - { - "D000H", 0xD0000 - }, - { - "E000H", 0xE0000 - }, - { - "" - } - }, - }, - { - "width", "I/O Width", CONFIG_SELECTION, "", 8, "", { 0 }, - { - { - "8-bit", 8 - }, - { - "16-bit", 16 - }, - { - "" - } - }, - }, - { - "speed", "Transfer Speed", CONFIG_SELECTION, "", 0, "", { 0 }, - { - { - "Standard", 0 - }, - { - "High-Speed", 1 - }, - { - "" - } - } - }, - { - "size", "Memory Size", CONFIG_SPINNER, "", 128, - "", - { 0, 8192, 128 }, - { { 0 } } - }, - { - "", "", -1 - } +static const device_config_t iab_config[] = { + // clang-format off + { + .name = "base", + .description = "Address", + .type = CONFIG_HEX16, + .default_string = "", + .default_int = 0x0258, + .file_filter = "", + .spinner = { 0 }, + .selection = { + { .description = "208H", .value = 0x0208 }, + { .description = "218H", .value = 0x0218 }, + { .description = "258H", .value = 0x0258 }, + { .description = "268H", .value = 0x0268 }, + { .description = "2A8H", .value = 0x02A8 }, + { .description = "2B8H", .value = 0x02B8 }, + { .description = "2E8H", .value = 0x02E8 }, + { .description = "" } + }, + }, + { + .name = "frame", + .description = "Frame Address", + .type = CONFIG_HEX20, + .default_string = "", + .default_int = 0, + .file_filter = "", + .spinner = { 0 }, + .selection = { + { .description = "Disabled", .value = 0x00000 }, + { .description = "C000H", .value = 0xC0000 }, + { .description = "D000H", .value = 0xD0000 }, + { .description = "E000H", .value = 0xE0000 }, + { .description = "" } + }, + }, + { + .name = "width", + .description = "I/O Width", + .type = CONFIG_SELECTION, + .default_string = "", + .default_int = 8, + .file_filter = "", + .spinner = { 0 }, + .selection = { + { .description = "8-bit", .value = 8 }, + { .description = "16-bit", .value = 16 }, + { .description = "" } + }, + }, + { + .name = "speed", + .description = "Transfer Speed", + .type = CONFIG_SELECTION, + .default_string = "", + .default_int = 0, + .file_filter = "", + .spinner = { 0 }, + .selection = { + { .description = "Standard", .value = 0 }, + { .description = "High-Speed", .value = 1 }, + { .description = "" } + } + }, + { + .name = "size", + .description = "Memory Size", + .type = CONFIG_SPINNER, + .default_string = "", + .default_int = 128, + .file_filter = "", + .spinner = { + .min = 0, + .max = 8192, + .step = 128 + }, + .selection = { { 0 } } + }, + { .name = "", .description = "", .type = CONFIG_END } + // clang-format on }; static const device_t iab_device = { - "Intel AboveBoard", - "iab", - DEVICE_ISA, - ISAMEM_ABOVEBOARD_CARD, - isamem_init, isamem_close, NULL, - { NULL }, NULL, NULL, - iab_config + .name = "Intel AboveBoard", + .internal_name = "iab", + .flags = DEVICE_ISA, + .local = ISAMEM_ABOVEBOARD_CARD, + .init = isamem_init, + .close = isamem_close, + .reset = NULL, + { .available = NULL }, + .speed_changed = NULL, + .force_redraw = NULL, + .config = iab_config }; #endif - static const device_t isa_none_device = { - "None", - "none", - 0, 0, - NULL, NULL, NULL, - { NULL }, NULL, NULL, - NULL + .name = "None", + .internal_name = "none", + .flags = 0, + .local = 0, + .init = NULL, + .close = NULL, + .reset = NULL, + { .available = NULL }, + .speed_changed = NULL, + .force_redraw = NULL, + .config = NULL }; - static const struct { - const device_t *dev; + const device_t *dev; } boards[] = { - { &isa_none_device }, - { &ibmxt_device }, - { &genericxt_device }, - { &ibmat_device }, - { &genericat_device }, - { &p5pak_device }, - { &a6pak_device }, - { &ems5150_device }, - { &ev159_device }, + // clang-format off + { &isa_none_device }, + { &ibmxt_device }, + { &genericxt_device }, + { &msramcard_device }, + { &mssystemcard_device }, + { &ibmat_device }, + { &genericat_device }, + { &p5pak_device }, + { &a6pak_device }, + { &ems5150_device }, + { &ev159_device }, #if defined(DEV_BRANCH) && defined(USE_ISAMEM_BRAT) - { &brat_device }, + { &brat_device }, #endif #if defined(DEV_BRANCH) && defined(USE_ISAMEM_RAMPAGE) - { &rampage_device }, + { &rampage_device }, #endif #if defined(DEV_BRANCH) && defined(USE_ISAMEM_IAB) - { &iab_device }, + { &iab_device }, #endif - { NULL } + { NULL } + // clang-format on }; - void isamem_reset(void) { - int k, i; + int k; /* We explicitly set to zero here or bad things happen */ isa_mem_size = 0; - for (i = 0; i < ISAMEM_MAX; i++) { - k = isamem_type[i]; - if (k == 0) continue; + for (uint8_t i = 0; i < ISAMEM_MAX; i++) { + k = isamem_type[i]; + if (k == 0) + continue; - /* Add the instance to the system. */ - device_add_inst(boards[k].dev, i + 1); + /* Add the instance to the system. */ + device_add_inst(boards[k].dev, i + 1); } } - const char * isamem_get_name(int board) { - if (boards[board].dev == NULL) return(NULL); + if (boards[board].dev == NULL) + return (NULL); - return(boards[board].dev->name); + return (boards[board].dev->name); } - const char * isamem_get_internal_name(int board) { return device_get_internal_name(boards[board].dev); } - - int isamem_get_from_internal_name(const char *s) { int c = 0; while (boards[c].dev != NULL) { - if (! strcmp(boards[c].dev->internal_name, s)) - return(c); - c++; + if (!strcmp(boards[c].dev->internal_name, s)) + return c; + c++; } /* Not found. */ - return(0); + return 0; } - const device_t * isamem_get_device(int board) { diff --git a/src/device/isapnp.c b/src/device/isapnp.c index 2b75969ce..26301b622 100644 --- a/src/device/isapnp.c +++ b/src/device/isapnp.c @@ -1,20 +1,20 @@ /* - * 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. + * 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. + * This file is part of the 86Box distribution. * - * Implementation of ISA Plug and Play. + * Implementation of ISA Plug and Play. * * * - * Author: Miran Grca, - * RichardG, + * Authors: Miran Grca, + * RichardG, * - * Copyright 2016-2018 Miran Grca. - * Copyright 2021 RichardG. + * Copyright 2016-2018 Miran Grca. + * Copyright 2021 RichardG. */ #include #include @@ -26,54 +26,52 @@ #include <86box/device.h> #include <86box/io.h> #include <86box/isapnp.h> +#include <86box/plat_unused.h> +#define CHECK_CURRENT_LD() \ + if (!dev->current_ld) { \ + isapnp_log("ISAPnP: No logical device selected\n"); \ + break; \ + } -#define CHECK_CURRENT_LD() if (!dev->current_ld) { \ - isapnp_log("ISAPnP: No logical device selected\n"); \ - break; \ - } +#define CHECK_CURRENT_CARD() \ + if (1) { \ + card = dev->first_card; \ + while (card) { \ + if (card->enable && (card->state == PNP_STATE_CONFIG)) \ + break; \ + card = card->next; \ + } \ + if (!card) { \ + isapnp_log("ISAPnP: No card in CONFIG state\n"); \ + break; \ + } \ + } -#define CHECK_CURRENT_CARD() if (1) { \ - card = dev->first_card; \ - while (card) { \ - if (card->enable && (card->state == PNP_STATE_CONFIG)) \ - break; \ - card = card->next; \ - } \ - if (!card) { \ - isapnp_log("ISAPnP: No card in CONFIG state\n"); \ - break; \ - } \ - } - - -static const uint8_t pnp_init_key[32] = { 0x6A, 0xB5, 0xDA, 0xED, 0xF6, 0xFB, 0x7D, 0xBE, - 0xDF, 0x6F, 0x37, 0x1B, 0x0D, 0x86, 0xC3, 0x61, - 0xB0, 0x58, 0x2C, 0x16, 0x8B, 0x45, 0xA2, 0xD1, - 0xE8, 0x74, 0x3A, 0x9D, 0xCE, 0xE7, 0x73, 0x39 }; +static const uint8_t pnp_init_key[32] = { 0x6A, 0xB5, 0xDA, 0xED, 0xF6, 0xFB, 0x7D, 0xBE, + 0xDF, 0x6F, 0x37, 0x1B, 0x0D, 0x86, 0xC3, 0x61, + 0xB0, 0x58, 0x2C, 0x16, 0x8B, 0x45, 0xA2, 0xD1, + 0xE8, 0x74, 0x3A, 0x9D, 0xCE, 0xE7, 0x73, 0x39 }; static const device_t isapnp_device; - #ifdef ENABLE_ISAPNP_LOG int isapnp_do_log = ENABLE_ISAPNP_LOG; - static void isapnp_log(const char *fmt, ...) { va_list ap; if (isapnp_do_log) { - va_start(ap, fmt); - pclog_ex(fmt, ap); - va_end(ap); + va_start(ap, fmt); + pclog_ex(fmt, ap); + va_end(ap); } } #else -#define isapnp_log(fmt, ...) +# define isapnp_log(fmt, ...) #endif - enum { PNP_STATE_WAIT_FOR_KEY = 0, PNP_STATE_CONFIG, @@ -82,140 +80,151 @@ enum { }; typedef struct _isapnp_device_ { - uint8_t number; - uint8_t regs[256]; - uint8_t mem_upperlimit, irq_types, io_16bit, io_len[8]; + uint8_t number; + uint8_t regs[256]; + uint8_t mem_upperlimit; + uint8_t irq_types; + uint8_t io_16bit; + uint8_t io_len[8]; const isapnp_device_config_t *defaults; struct _isapnp_device_ *next; } isapnp_device_t; typedef struct _isapnp_card_ { - uint8_t enable, state, csn, id_checksum, serial_read, serial_read_pair, serial_read_pos, *rom; - uint16_t rom_pos, rom_size; - void *priv; + uint8_t enable; + uint8_t state; + uint8_t csn; + uint8_t id_checksum; + uint8_t serial_read; + uint8_t serial_read_pair; + uint8_t serial_read_pos; + uint8_t *rom; + uint16_t rom_pos; + uint16_t rom_size; + void *priv; /* ISAPnP memory and I/O addresses are awkwardly big endian, so we populate this structure whenever something on some device changes, and pass it on instead. */ isapnp_device_config_t config; - void (*config_changed)(uint8_t ld, isapnp_device_config_t *config, void *priv); - void (*csn_changed)(uint8_t csn, void *priv); - uint8_t (*read_vendor_reg)(uint8_t ld, uint8_t reg, void *priv); - void (*write_vendor_reg)(uint8_t ld, uint8_t reg, uint8_t val, void *priv); + void (*config_changed)(uint8_t ld, isapnp_device_config_t *config, void *priv); + void (*csn_changed)(uint8_t csn, void *priv); + uint8_t (*read_vendor_reg)(uint8_t ld, uint8_t reg, void *priv); + void (*write_vendor_reg)(uint8_t ld, uint8_t reg, uint8_t val, void *priv); - isapnp_device_t *first_ld; + isapnp_device_t *first_ld; struct _isapnp_card_ *next; } isapnp_card_t; typedef struct { - uint8_t reg, key_pos: 5; - uint16_t read_data_addr; + uint8_t reg; + uint8_t key_pos : 5; + uint16_t read_data_addr; - isapnp_card_t *first_card, *isolated_card, *current_ld_card; + isapnp_card_t *first_card; + isapnp_card_t *isolated_card; + isapnp_card_t *current_ld_card; isapnp_device_t *current_ld; } isapnp_t; - static void isapnp_device_config_changed(isapnp_card_t *card, isapnp_device_t *ld) { /* Ignore card if it hasn't signed up for configuration changes. */ if (!card->config_changed) - return; + return; /* Populate config structure, performing endianness conversion as needed. */ card->config.activate = ld->regs[0x30] & 0x01; - uint8_t i, reg_base; - for (i = 0; i < 4; i++) { - reg_base = 0x40 + (8 * i); - card->config.mem[i].base = (ld->regs[reg_base] << 16) | (ld->regs[reg_base + 1] << 8); - card->config.mem[i].size = (ld->regs[reg_base + 3] << 16) | (ld->regs[reg_base + 4] << 8); - if (ld->regs[reg_base + 2] & 0x01) /* upper limit */ - card->config.mem[i].size -= card->config.mem[i].base; + uint8_t reg_base; + for (uint8_t i = 0; i < 4; i++) { + reg_base = 0x40 + (8 * i); + card->config.mem[i].base = (ld->regs[reg_base] << 16) | (ld->regs[reg_base + 1] << 8); + card->config.mem[i].size = (ld->regs[reg_base + 3] << 16) | (ld->regs[reg_base + 4] << 8); + if (ld->regs[reg_base + 2] & 0x01) /* upper limit */ + card->config.mem[i].size -= card->config.mem[i].base; } - for (i = 0; i < 4; i++) { - reg_base = (i == 0) ? 0x76 : (0x80 + (16 * i)); - card->config.mem32[i].base = (ld->regs[reg_base] << 24) | (ld->regs[reg_base + 1] << 16) | (ld->regs[reg_base + 2] << 8) | ld->regs[reg_base + 3]; - card->config.mem32[i].size = (ld->regs[reg_base + 5] << 24) | (ld->regs[reg_base + 6] << 16) | (ld->regs[reg_base + 7] << 8) | ld->regs[reg_base + 8]; - if (ld->regs[reg_base + 4] & 0x01) /* upper limit */ - card->config.mem32[i].size -= card->config.mem32[i].base; + for (uint8_t i = 0; i < 4; i++) { + reg_base = (i == 0) ? 0x76 : (0x80 + (16 * i)); + card->config.mem32[i].base = (ld->regs[reg_base] << 24) | (ld->regs[reg_base + 1] << 16) | (ld->regs[reg_base + 2] << 8) | ld->regs[reg_base + 3]; + card->config.mem32[i].size = (ld->regs[reg_base + 5] << 24) | (ld->regs[reg_base + 6] << 16) | (ld->regs[reg_base + 7] << 8) | ld->regs[reg_base + 8]; + if (ld->regs[reg_base + 4] & 0x01) /* upper limit */ + card->config.mem32[i].size -= card->config.mem32[i].base; } - for (i = 0; i < 8; i++) { - reg_base = 0x60 + (2 * i); - if (ld->regs[0x31] & 0x02) - card->config.io[i].base = 0; /* let us handle I/O range check reads */ - else - card->config.io[i].base = (ld->regs[reg_base] << 8) | ld->regs[reg_base + 1]; + for (uint8_t i = 0; i < 8; i++) { + reg_base = 0x60 + (2 * i); + if (ld->regs[0x31] & 0x02) + card->config.io[i].base = 0; /* let us handle I/O range check reads */ + else + card->config.io[i].base = (ld->regs[reg_base] << 8) | ld->regs[reg_base + 1]; } - for (i = 0; i < 2; i++) { - reg_base = 0x70 + (2 * i); - card->config.irq[i].irq = ld->regs[reg_base]; - card->config.irq[i].level = ld->regs[reg_base + 1] & 0x02; - card->config.irq[i].type = ld->regs[reg_base + 1] & 0x01; + for (uint8_t i = 0; i < 2; i++) { + reg_base = 0x70 + (2 * i); + card->config.irq[i].irq = ld->regs[reg_base]; + card->config.irq[i].level = ld->regs[reg_base + 1] & 0x02; + card->config.irq[i].type = ld->regs[reg_base + 1] & 0x01; } - for (i = 0; i < 2; i++) { - reg_base = 0x74 + i; - card->config.dma[i].dma = ld->regs[reg_base]; + for (uint8_t i = 0; i < 2; i++) { + reg_base = 0x74 + i; + card->config.dma[i].dma = ld->regs[reg_base]; } /* Signal the configuration change. */ card->config_changed(ld->number, &card->config, card->priv); } - static void isapnp_reset_ld_config(isapnp_device_t *ld) { /* Do nothing if there's no default configuration for this device. */ const isapnp_device_config_t *config = ld->defaults; if (!config) - return; + return; /* Populate configuration registers. */ ld->regs[0x30] = !!config->activate; - uint8_t i, reg_base; + uint8_t reg_base; uint32_t size; - for (i = 0; i < 4; i++) { - reg_base = 0x40 + (8 * i); - ld->regs[reg_base] = config->mem[i].base >> 16; - ld->regs[reg_base + 1] = config->mem[i].base >> 8; - size = config->mem[i].size; - if (ld->regs[reg_base + 2] & 0x01) /* upper limit */ - size += config->mem[i].base; - ld->regs[reg_base + 3] = size >> 16; - ld->regs[reg_base + 4] = size >> 8; + for (uint8_t i = 0; i < 4; i++) { + reg_base = 0x40 + (8 * i); + ld->regs[reg_base] = config->mem[i].base >> 16; + ld->regs[reg_base + 1] = config->mem[i].base >> 8; + size = config->mem[i].size; + if (ld->regs[reg_base + 2] & 0x01) /* upper limit */ + size += config->mem[i].base; + ld->regs[reg_base + 3] = size >> 16; + ld->regs[reg_base + 4] = size >> 8; } - for (i = 0; i < 4; i++) { - reg_base = (i == 0) ? 0x76 : (0x80 + (16 * i)); - ld->regs[reg_base] = config->mem32[i].base >> 24; - ld->regs[reg_base + 1] = config->mem32[i].base >> 16; - ld->regs[reg_base + 2] = config->mem32[i].base >> 8; - ld->regs[reg_base + 3] = config->mem32[i].base; - size = config->mem32[i].size; - if (ld->regs[reg_base + 4] & 0x01) /* upper limit */ - size += config->mem32[i].base; - ld->regs[reg_base + 5] = size >> 24; - ld->regs[reg_base + 6] = size >> 16; - ld->regs[reg_base + 7] = size >> 8; - ld->regs[reg_base + 8] = size; + for (uint8_t i = 0; i < 4; i++) { + reg_base = (i == 0) ? 0x76 : (0x80 + (16 * i)); + ld->regs[reg_base] = config->mem32[i].base >> 24; + ld->regs[reg_base + 1] = config->mem32[i].base >> 16; + ld->regs[reg_base + 2] = config->mem32[i].base >> 8; + ld->regs[reg_base + 3] = config->mem32[i].base; + size = config->mem32[i].size; + if (ld->regs[reg_base + 4] & 0x01) /* upper limit */ + size += config->mem32[i].base; + ld->regs[reg_base + 5] = size >> 24; + ld->regs[reg_base + 6] = size >> 16; + ld->regs[reg_base + 7] = size >> 8; + ld->regs[reg_base + 8] = size; } - for (i = 0; i < 8; i++) { - reg_base = 0x60 + (2 * i); - ld->regs[reg_base] = config->io[i].base >> 8; - ld->regs[reg_base + 1] = config->io[i].base; + for (uint8_t i = 0; i < 8; i++) { + reg_base = 0x60 + (2 * i); + ld->regs[reg_base] = config->io[i].base >> 8; + ld->regs[reg_base + 1] = config->io[i].base; } - for (i = 0; i < 2; i++) { - reg_base = 0x70 + (2 * i); - ld->regs[reg_base] = config->irq[i].irq; - ld->regs[reg_base + 1] = (!!config->irq[i].level << 1) | !!config->irq[i].type; + for (uint8_t i = 0; i < 2; i++) { + reg_base = 0x70 + (2 * i); + ld->regs[reg_base] = config->irq[i].irq; + ld->regs[reg_base + 1] = (!!config->irq[i].level << 1) | !!config->irq[i].type; } - for (i = 0; i < 2; i++) { - reg_base = 0x74 + i; - ld->regs[reg_base] = config->dma[i].dma; + for (uint8_t i = 0; i < 2; i++) { + reg_base = 0x74 + i; + ld->regs[reg_base] = config->dma[i].dma; } } - static void isapnp_reset_ld_regs(isapnp_device_t *ld) { @@ -225,150 +234,179 @@ isapnp_reset_ld_regs(isapnp_device_t *ld) ld->regs[0x74] = ld->regs[0x75] = ISAPNP_DMA_DISABLED; /* Set the upper limit bit on memory ranges which require it. */ - uint8_t i; - for (i = 0; i < 4; i++) - ld->regs[0x42 + (8 * i)] |= !!(ld->mem_upperlimit & (1 << i)); + for (uint8_t i = 0; i < 4; i++) + ld->regs[0x42 + (8 * i)] |= !!(ld->mem_upperlimit & (1 << i)); ld->regs[0x7a] |= !!(ld->mem_upperlimit & (1 << 4)); - for (i = 1; i < 4; i++) - ld->regs[0x84 + (16 * i)] |= !!(ld->mem_upperlimit & (1 << (4 + i))); + for (uint8_t i = 1; i < 4; i++) + ld->regs[0x84 + (16 * i)] |= !!(ld->mem_upperlimit & (1 << (4 + i))); /* Set the default IRQ type bits. */ - for (i = 0; i < 2; i++) { - if (ld->irq_types & (0x1 << (4 * i))) - ld->regs[0x70 + (2 * i)] = 0x02; - else if (ld->irq_types & (0x2 << (4 * i))) - ld->regs[0x70 + (2 * i)] = 0x00; - else if (ld->irq_types & (0x4 << (4 * i))) - ld->regs[0x70 + (2 * i)] = 0x03; - else if (ld->irq_types & (0x8 << (4 * i))) - ld->regs[0x70 + (2 * i)] = 0x01; + for (uint8_t i = 0; i < 2; i++) { + if (ld->irq_types & (0x1 << (4 * i))) + ld->regs[0x70 + (2 * i)] = 0x02; + else if (ld->irq_types & (0x2 << (4 * i))) + ld->regs[0x70 + (2 * i)] = 0x00; + else if (ld->irq_types & (0x4 << (4 * i))) + ld->regs[0x70 + (2 * i)] = 0x03; + else if (ld->irq_types & (0x8 << (4 * i))) + ld->regs[0x70 + (2 * i)] = 0x01; } /* Reset configuration registers to match the default configuration. */ isapnp_reset_ld_config(ld); } - static uint8_t -isapnp_read_rangecheck(uint16_t addr, void *priv) +isapnp_read_rangecheck(UNUSED(uint16_t addr), void *priv) { - isapnp_device_t *dev = (isapnp_device_t *) priv; + const isapnp_device_t *dev = (isapnp_device_t *) priv; + return (dev->regs[0x31] & 0x01) ? 0x55 : 0xaa; } - static uint8_t -isapnp_read_data(uint16_t addr, void *priv) +isapnp_read_data(UNUSED(uint16_t addr), void *priv) { - isapnp_t *dev = (isapnp_t *) priv; - uint8_t ret = 0xff, bit, next_shift; + isapnp_t *dev = (isapnp_t *) priv; + uint8_t ret = 0xff; + uint8_t bit; + uint8_t next_shift; isapnp_card_t *card; switch (dev->reg) { - case 0x01: /* Serial Isolation */ - card = dev->first_card; - while (card) { - if (card->enable && (card->state == PNP_STATE_ISOLATION)) - break; - card = card->next; - } - dev->isolated_card = card; + case 0x01: /* Serial Isolation */ + card = dev->first_card; + while (card) { + if (card->enable && card->rom && (card->state == PNP_STATE_ISOLATION)) + break; + card = card->next; + } + dev->isolated_card = card; - if (card) { - if (card->serial_read_pair) { /* second byte (aa/00) */ - card->serial_read <<= 1; - if (!card->serial_read_pos) - card->rom_pos = 0x09; - } else { /* first byte (55/00) */ - if (card->serial_read_pos < 64) { /* reading 64-bit vendor/serial */ - bit = (card->rom[card->serial_read_pos >> 3] >> (card->serial_read_pos & 0x7)) & 0x01; - next_shift = (!!(card->id_checksum & 0x02) ^ !!(card->id_checksum & 0x01) ^ bit) & 0x01; - card->id_checksum >>= 1; - card->id_checksum |= (next_shift << 7); - } else { /* reading 8-bit checksum */ - if (card->serial_read_pos == 64) /* populate ID checksum in ROM */ - card->rom[0x08] = card->id_checksum; - bit = (card->id_checksum >> (card->serial_read_pos & 0x7)) & 0x01; - } - isapnp_log("ISAPnP: Read bit %d of byte %02X (%02X) = %d\n", card->serial_read_pos & 0x7, card->serial_read_pos >> 3, card->rom[card->serial_read_pos >> 3], bit); - card->serial_read = bit ? 0x55 : 0x00; - card->serial_read_pos = (card->serial_read_pos + 1) % 72; - } - card->serial_read_pair ^= 1; - ret = card->serial_read; - } + if (card) { + if (card->serial_read_pair) { /* second byte (aa/00) */ + card->serial_read <<= 1; + if (!card->serial_read_pos) + card->rom_pos = 0x09; + } else { /* first byte (55/00) */ + if (card->serial_read_pos < 64) { /* reading 64-bit vendor/serial */ + bit = (card->rom[card->serial_read_pos >> 3] >> (card->serial_read_pos & 0x7)) & 0x01; + next_shift = (!!(card->id_checksum & 0x02) ^ !!(card->id_checksum & 0x01) ^ bit) & 0x01; + card->id_checksum >>= 1; + card->id_checksum |= (next_shift << 7); + } else { /* reading 8-bit checksum */ + if (card->serial_read_pos == 64) /* populate ID checksum in ROM */ + card->rom[0x08] = card->id_checksum; + bit = (card->id_checksum >> (card->serial_read_pos & 0x7)) & 0x01; + } + isapnp_log("ISAPnP: Read bit %d of byte %02X (%02X) = %d\n", card->serial_read_pos & 0x7, card->serial_read_pos >> 3, card->rom[card->serial_read_pos >> 3], bit); + card->serial_read = bit ? 0x55 : 0x00; + card->serial_read_pos = (card->serial_read_pos + 1) % 72; + } + card->serial_read_pair ^= 1; + ret = card->serial_read; + } - break; + break; - case 0x04: /* Resource Data */ - CHECK_CURRENT_CARD(); + case 0x04: /* Resource Data */ + CHECK_CURRENT_CARD(); - isapnp_log("ISAPnP: Read resource data index %02X (%02X) from CSN %02X\n", card->rom_pos, card->rom[card->rom_pos], card->csn); - if (card->rom_pos >= card->rom_size) - ret = 0xff; - else - ret = card->rom[card->rom_pos++]; + isapnp_log("ISAPnP: Read resource data index %02X (%02X) from CSN %02X\n", card->rom_pos, card->rom[card->rom_pos], card->csn); + if (card->rom_pos >= card->rom_size) + ret = 0xff; + else + ret = card->rom[card->rom_pos++]; - break; + break; - case 0x05: /* Status */ - ret = 0x00; - CHECK_CURRENT_CARD(); + case 0x05: /* Status */ + ret = 0x00; + CHECK_CURRENT_CARD(); - isapnp_log("ISAPnP: Query status for CSN %02X\n", card->csn); - ret = 0x01; + isapnp_log("ISAPnP: Query status for CSN %02X\n", card->csn); + ret = 0x01; - break; + break; - case 0x06: /* Card Select Number */ - ret = 0x00; - CHECK_CURRENT_CARD(); + case 0x06: /* Card Select Number */ + ret = 0x00; + CHECK_CURRENT_CARD(); - isapnp_log("ISAPnP: Query CSN %02X\n", card->csn); - ret = card->csn; + isapnp_log("ISAPnP: Query CSN %02X\n", card->csn); + ret = card->csn; - break; + break; - case 0x07: /* Logical Device Number */ - ret = 0x00; - CHECK_CURRENT_LD(); + case 0x07: /* Logical Device Number */ + ret = 0x00; + CHECK_CURRENT_LD(); - isapnp_log("ISAPnP: Query LDN for CSN %02X device %02X\n", dev->current_ld_card->csn, dev->current_ld->number); - ret = dev->current_ld->number; + isapnp_log("ISAPnP: Query LDN for CSN %02X device %02X\n", dev->current_ld_card->csn, dev->current_ld->number); + ret = dev->current_ld->number; - break; + break; - case 0x20: case 0x21: case 0x22: case 0x23: - case 0x24: case 0x25: case 0x26: case 0x27: - case 0x28: case 0x29: case 0x2a: case 0x2b: - case 0x2c: case 0x2d: case 0x2e: case 0x2f: - CHECK_CURRENT_CARD(); + case 0x20: + case 0x21: + case 0x22: + case 0x23: + case 0x24: + case 0x25: + case 0x26: + case 0x27: + case 0x28: + case 0x29: + case 0x2a: + case 0x2b: + case 0x2c: + case 0x2d: + case 0x2e: + case 0x2f: + CHECK_CURRENT_CARD(); - isapnp_log("ISAPnP: Read vendor-defined register %02X from CSN %02X\n", dev->reg, card->csn); + isapnp_log("ISAPnP: Read vendor-defined register %02X from CSN %02X\n", dev->reg, card->csn); - if (card->read_vendor_reg) - ret = card->read_vendor_reg(0, dev->reg, card->priv); - break; + if (card->read_vendor_reg) + ret = card->read_vendor_reg(0, dev->reg, card->priv); + break; - case 0x38: case 0x39: case 0x3a: case 0x3b: - case 0x3c: case 0x3d: case 0x3e: case 0x3f: - case 0xf0: case 0xf1: case 0xf2: case 0xf3: - case 0xf4: case 0xf5: case 0xf6: case 0xf7: - case 0xf8: case 0xf9: case 0xfa: case 0xfb: - case 0xfc: case 0xfd: case 0xfe: - CHECK_CURRENT_LD(); - isapnp_log("ISAPnP: Read vendor-defined register %02X from CSN %02X device %02X\n", dev->reg, dev->current_ld_card->csn, dev->current_ld->number); - if (dev->current_ld_card->read_vendor_reg) - ret = dev->current_ld_card->read_vendor_reg(dev->current_ld->number, dev->reg, dev->current_ld_card->priv); - break; + case 0x38: + case 0x39: + case 0x3a: + case 0x3b: + case 0x3c: + case 0x3d: + case 0x3e: + case 0x3f: + case 0xf0: + case 0xf1: + case 0xf2: + case 0xf3: + case 0xf4: + case 0xf5: + case 0xf6: + case 0xf7: + case 0xf8: + case 0xf9: + case 0xfa: + case 0xfb: + case 0xfc: + case 0xfd: + case 0xfe: + CHECK_CURRENT_LD(); + isapnp_log("ISAPnP: Read vendor-defined register %02X from CSN %02X device %02X\n", dev->reg, dev->current_ld_card->csn, dev->current_ld->number); + if (dev->current_ld_card->read_vendor_reg) + ret = dev->current_ld_card->read_vendor_reg(dev->current_ld->number, dev->reg, dev->current_ld_card->priv); + break; - default: - if (dev->reg >= 0x30) { - CHECK_CURRENT_LD(); - isapnp_log("ISAPnP: Read register %02X from CSN %02X device %02X\n", dev->reg, dev->current_ld_card->csn, dev->current_ld->number); - ret = dev->current_ld->regs[dev->reg]; - } - break; + default: + if (dev->reg >= 0x30) { + CHECK_CURRENT_LD(); + isapnp_log("ISAPnP: Read register %02X from CSN %02X device %02X\n", dev->reg, dev->current_ld_card->csn, dev->current_ld->number); + ret = dev->current_ld->regs[dev->reg]; + } + break; } isapnp_log("ISAPnP: read_data(%02X) = %02X\n", dev->reg, ret); @@ -376,257 +414,300 @@ isapnp_read_data(uint16_t addr, void *priv) return ret; } - static void isapnp_set_read_data(uint16_t addr, isapnp_t *dev) { /* Remove existing READ_DATA port if set. */ if (dev->read_data_addr) { - io_removehandler(dev->read_data_addr, 1, isapnp_read_data, NULL, NULL, NULL, NULL, NULL, dev); - dev->read_data_addr = 0; + io_removehandler(dev->read_data_addr, 1, isapnp_read_data, NULL, NULL, NULL, NULL, NULL, dev); + dev->read_data_addr = 0; } /* Set new READ_DATA port if within range. */ if ((addr >= 0x203) && (addr <= 0x3ff)) { - dev->read_data_addr = addr; - io_sethandler(dev->read_data_addr, 1, isapnp_read_data, NULL, NULL, NULL, NULL, NULL, dev); + dev->read_data_addr = addr; + io_sethandler(dev->read_data_addr, 1, isapnp_read_data, NULL, NULL, NULL, NULL, NULL, dev); } } - static void -isapnp_write_addr(uint16_t addr, uint8_t val, void *priv) +isapnp_write_addr(UNUSED(uint16_t addr), uint8_t val, void *priv) { - isapnp_t *dev = (isapnp_t *) priv; + isapnp_t *dev = (isapnp_t *) priv; isapnp_card_t *card = dev->first_card; isapnp_log("ISAPnP: write_addr(%02X)\n", val); if (!card) /* don't do anything if we have no PnP cards */ - return; + return; dev->reg = val; if (card->state == PNP_STATE_WAIT_FOR_KEY) { /* checking only the first card should be fine */ - /* Check written value against LFSR key. */ - if (val == pnp_init_key[dev->key_pos]) { - dev->key_pos++; - if (!dev->key_pos) { - isapnp_log("ISAPnP: Key unlocked, putting cards to SLEEP\n"); - while (card) { - if (card->enable && (card->state == PNP_STATE_WAIT_FOR_KEY)) - card->state = PNP_STATE_SLEEP; - card = card->next; - } - } - } else { - dev->key_pos = 0; - } + /* Check written value against LFSR key. */ + if (val == pnp_init_key[dev->key_pos]) { + dev->key_pos++; + if (!dev->key_pos) { + isapnp_log("ISAPnP: Key unlocked, putting cards to SLEEP\n"); + while (card) { + if (card->enable && (card->enable != ISAPNP_CARD_NO_KEY) && (card->state == PNP_STATE_WAIT_FOR_KEY)) + card->state = PNP_STATE_SLEEP; + card = card->next; + } + } + } else { + dev->key_pos = 0; + } } } - static void -isapnp_write_data(uint16_t addr, uint8_t val, void *priv) +isapnp_write_data(UNUSED(uint16_t addr), uint8_t val, void *priv) { - isapnp_t *dev = (isapnp_t *) priv; - isapnp_card_t *card; + isapnp_t *dev = (isapnp_t *) priv; + isapnp_card_t *card; isapnp_device_t *ld; - uint16_t io_addr, reset_cards = 0; + uint16_t io_addr; + uint16_t reset_cards = 0; isapnp_log("ISAPnP: write_data(%02X)\n", val); switch (dev->reg) { - case 0x00: /* Set RD_DATA Port */ - isapnp_set_read_data((val << 2) | 3, dev); - isapnp_log("ISAPnP: Read data port set to %04X\n", dev->read_data_addr); - break; + case 0x00: /* Set RD_DATA Port */ + isapnp_set_read_data((val << 2) | 3, dev); + isapnp_log("ISAPnP: Read data port set to %04X\n", dev->read_data_addr); + break; - case 0x02: /* Config Control */ - if (val & 0x01) { - isapnp_log("ISAPnP: Reset\n"); + case 0x02: /* Config Control */ + if (val & 0x01) { + isapnp_log("ISAPnP: Reset\n"); - card = dev->first_card; - while (card) { - ld = card->first_ld; - while (ld) { - if (card->state != PNP_STATE_WAIT_FOR_KEY) { - isapnp_reset_ld_regs(ld); - isapnp_device_config_changed(card, ld); - reset_cards++; - } - ld = ld->next; - } - card = card->next; - } + card = dev->first_card; + while (card) { + ld = card->first_ld; + while (ld) { + if (card->state != PNP_STATE_WAIT_FOR_KEY) { + isapnp_reset_ld_regs(ld); + isapnp_device_config_changed(card, ld); + reset_cards++; + } + ld = ld->next; + } + card = card->next; + } - if (reset_cards != 0) { - dev->current_ld = NULL; - dev->current_ld_card = NULL; - dev->isolated_card = NULL; - } - } - if (val & 0x02) { - isapnp_log("ISAPnP: Return to WAIT_FOR_KEY\n"); - card = dev->first_card; - while (card) { - card->state = PNP_STATE_WAIT_FOR_KEY; - card = card->next; - } - } - if (val & 0x04) { - isapnp_log("ISAPnP: Reset CSN\n"); - card = dev->first_card; - while (card) { - isapnp_set_csn(card, 0); - card = card->next; - } - } - break; + if (reset_cards != 0) { + dev->current_ld = NULL; + dev->current_ld_card = NULL; + dev->isolated_card = NULL; + } + } + if (val & 0x02) { + isapnp_log("ISAPnP: Return to WAIT_FOR_KEY\n"); + card = dev->first_card; + while (card) { + card->state = PNP_STATE_WAIT_FOR_KEY; + card = card->next; + } + } + if (val & 0x04) { + isapnp_log("ISAPnP: Reset CSN\n"); + card = dev->first_card; + while (card) { + isapnp_set_csn(card, 0); + card = card->next; + } + } + break; - case 0x03: /* Wake[CSN] */ - isapnp_log("ISAPnP: Wake[%02X]\n", val); - card = dev->first_card; - while (card) { - if (card->csn == val) { - card->rom_pos = 0; - card->id_checksum = pnp_init_key[0]; - if (card->state == PNP_STATE_SLEEP) - card->state = (val == 0) ? PNP_STATE_ISOLATION : PNP_STATE_CONFIG; - } else { - card->state = PNP_STATE_SLEEP; - } + case 0x03: /* Wake[CSN] */ + isapnp_log("ISAPnP: Wake[%02X]\n", val); + card = dev->first_card; + while (card) { + if (card->csn == val) { + card->rom_pos = 0; + card->id_checksum = pnp_init_key[0]; + if (card->state == PNP_STATE_SLEEP) + card->state = (val == 0) ? PNP_STATE_ISOLATION : PNP_STATE_CONFIG; + } else { + card->state = PNP_STATE_SLEEP; + } - card = card->next; - } - break; + card = card->next; + } + break; - case 0x06: /* Card Select Number */ - if (dev->isolated_card) { - isapnp_log("ISAPnP: Set CSN %02X\n", val); - isapnp_set_csn(dev->isolated_card, val); - dev->isolated_card->state = PNP_STATE_CONFIG; - dev->isolated_card = NULL; - } else { - isapnp_log("ISAPnP: Set CSN %02X but no card is isolated\n", val); - } - break; + case 0x06: /* Card Select Number */ + if (dev->isolated_card) { + isapnp_log("ISAPnP: Set CSN %02X\n", val); + isapnp_set_csn(dev->isolated_card, val); + dev->isolated_card->state = PNP_STATE_CONFIG; + dev->isolated_card = NULL; + } else { + isapnp_log("ISAPnP: Set CSN %02X but no card is isolated\n", val); + } + break; - case 0x07: /* Logical Device Number */ - CHECK_CURRENT_CARD(); + case 0x07: /* Logical Device Number */ + CHECK_CURRENT_CARD(); - ld = card->first_ld; - while (ld) { - if (ld->number == val) { - isapnp_log("ISAPnP: Select CSN %02X device %02X\n", card->csn, val); - dev->current_ld_card = card; - dev->current_ld = ld; - break; - } - ld = ld->next; - } + ld = card->first_ld; + while (ld) { + if (ld->number == val) { + isapnp_log("ISAPnP: Select CSN %02X device %02X\n", card->csn, val); + dev->current_ld_card = card; + dev->current_ld = ld; + break; + } + ld = ld->next; + } - if (!ld) - isapnp_log("ISAPnP: CSN %02X has no device %02X\n", card->csn, val); + if (!ld) + isapnp_log("ISAPnP: CSN %02X has no device %02X\n", card->csn, val); - break; + break; - case 0x30: /* Activate */ - CHECK_CURRENT_LD(); + case 0x30: /* Activate */ + CHECK_CURRENT_LD(); - isapnp_log("ISAPnP: %sctivate CSN %02X device %02X\n", (val & 0x01) ? "A" : "Dea", dev->current_ld_card->csn, dev->current_ld->number); + isapnp_log("ISAPnP: %sctivate CSN %02X device %02X\n", (val & 0x01) ? "A" : "Dea", dev->current_ld_card->csn, dev->current_ld->number); - dev->current_ld->regs[dev->reg] = val & 0x01; - isapnp_device_config_changed(dev->current_ld_card, dev->current_ld); + dev->current_ld->regs[dev->reg] = val & 0x01; + isapnp_device_config_changed(dev->current_ld_card, dev->current_ld); - break; + break; - case 0x31: /* I/O Range Check */ - CHECK_CURRENT_LD(); + case 0x31: /* I/O Range Check */ + CHECK_CURRENT_LD(); - for (uint8_t i = 0; i < 8; i++) { - if (!dev->current_ld->io_len[i]) - continue; + for (uint8_t i = 0; i < 8; i++) { + if (!dev->current_ld->io_len[i]) + continue; - io_addr = (dev->current_ld->regs[0x60 + (2 * i)] << 8) | dev->current_ld->regs[0x61 + (2 * i)]; - if (dev->current_ld->regs[dev->reg] & 0x02) - io_removehandler(io_addr, dev->current_ld->io_len[i], isapnp_read_rangecheck, NULL, NULL, NULL, NULL, NULL, dev->current_ld); - if (val & 0x02) - io_sethandler(io_addr, dev->current_ld->io_len[i], isapnp_read_rangecheck, NULL, NULL, NULL, NULL, NULL, dev->current_ld); - } + io_addr = (dev->current_ld->regs[0x60 + (2 * i)] << 8) | dev->current_ld->regs[0x61 + (2 * i)]; + if (dev->current_ld->regs[dev->reg] & 0x02) + io_removehandler(io_addr, dev->current_ld->io_len[i], isapnp_read_rangecheck, NULL, NULL, NULL, NULL, NULL, dev->current_ld); + if (val & 0x02) + io_sethandler(io_addr, dev->current_ld->io_len[i], isapnp_read_rangecheck, NULL, NULL, NULL, NULL, NULL, dev->current_ld); + } - dev->current_ld->regs[dev->reg] = val & 0x03; - isapnp_device_config_changed(dev->current_ld_card, dev->current_ld); + dev->current_ld->regs[dev->reg] = val & 0x03; + isapnp_device_config_changed(dev->current_ld_card, dev->current_ld); - break; + break; - case 0x20: case 0x21: case 0x22: case 0x23: - case 0x24: case 0x25: case 0x26: case 0x27: - case 0x28: case 0x29: case 0x2a: case 0x2b: - case 0x2c: case 0x2d: case 0x2e: case 0x2f: - CHECK_CURRENT_CARD(); + case 0x20: + case 0x21: + case 0x22: + case 0x23: + case 0x24: + case 0x25: + case 0x26: + case 0x27: + case 0x28: + case 0x29: + case 0x2a: + case 0x2b: + case 0x2c: + case 0x2d: + case 0x2e: + case 0x2f: + CHECK_CURRENT_CARD(); - isapnp_log("ISAPnP: Write %02X to vendor-defined register %02X on CSN %02X\n", val, dev->reg, card->csn); + isapnp_log("ISAPnP: Write %02X to vendor-defined register %02X on CSN %02X\n", val, dev->reg, card->csn); - if (card->write_vendor_reg) - card->write_vendor_reg(0, dev->reg, val, card->priv); - break; + if (card->write_vendor_reg) + card->write_vendor_reg(0, dev->reg, val, card->priv); + break; - case 0x38: case 0x39: case 0x3a: case 0x3b: - case 0x3c: case 0x3d: case 0x3e: case 0x3f: - case 0xf0: case 0xf1: case 0xf2: case 0xf3: - case 0xf4: case 0xf5: case 0xf6: case 0xf7: - case 0xf8: case 0xf9: case 0xfa: case 0xfb: - case 0xfc: case 0xfd: case 0xfe: - CHECK_CURRENT_LD(); - isapnp_log("ISAPnP: Write %02X to vendor-defined register %02X on CSN %02X device %02X\n", val, dev->reg, dev->current_ld_card->csn, dev->current_ld->number); - if (dev->current_ld_card->write_vendor_reg) - dev->current_ld_card->write_vendor_reg(dev->current_ld->number, dev->reg, val, dev->current_ld_card->priv); - break; + case 0x38: + case 0x39: + case 0x3a: + case 0x3b: + case 0x3c: + case 0x3d: + case 0x3e: + case 0x3f: + case 0xf0: + case 0xf1: + case 0xf2: + case 0xf3: + case 0xf4: + case 0xf5: + case 0xf6: + case 0xf7: + case 0xf8: + case 0xf9: + case 0xfa: + case 0xfb: + case 0xfc: + case 0xfd: + case 0xfe: + CHECK_CURRENT_LD(); + isapnp_log("ISAPnP: Write %02X to vendor-defined register %02X on CSN %02X device %02X\n", val, dev->reg, dev->current_ld_card->csn, dev->current_ld->number); + if (dev->current_ld_card->write_vendor_reg) + dev->current_ld_card->write_vendor_reg(dev->current_ld->number, dev->reg, val, dev->current_ld_card->priv); + break; - default: - if (dev->reg >= 0x40) { - CHECK_CURRENT_LD(); - isapnp_log("ISAPnP: Write %02X to register %02X on CSN %02X device %02X\n", val, dev->reg, dev->current_ld_card->csn, dev->current_ld->number); + default: + if (dev->reg >= 0x40) { + CHECK_CURRENT_LD(); + isapnp_log("ISAPnP: Write %02X to register %02X on CSN %02X device %02X\n", val, dev->reg, dev->current_ld_card->csn, dev->current_ld->number); - switch (dev->reg) { - case 0x42: case 0x4a: case 0x52: case 0x5a: - case 0x7a: case 0x84: case 0x94: case 0xa4: - /* Read-only memory range length / upper limit bit. */ - val = (val & 0xfe) | (dev->current_ld->regs[dev->reg] & 0x01); - break; + switch (dev->reg) { + case 0x42: + case 0x4a: + case 0x52: + case 0x5a: + case 0x7a: + case 0x84: + case 0x94: + case 0xa4: + /* Read-only memory range length / upper limit bit. */ + val = (val & 0xfe) | (dev->current_ld->regs[dev->reg] & 0x01); + break; - case 0x60: case 0x62: case 0x64: case 0x66: case 0x68: case 0x6a: case 0x6c: case 0x6e: - /* Discard upper address bits if this I/O range can only decode 10-bit. */ - if (!(dev->current_ld->io_16bit & (1 << ((dev->reg >> 1) & 0x07)))) - val &= 0x03; - break; + case 0x60: + case 0x62: + case 0x64: + case 0x66: + case 0x68: + case 0x6a: + case 0x6c: + case 0x6e: + /* Discard upper address bits if this I/O range can only decode 10-bit. */ + if (!(dev->current_ld->io_16bit & (1 << ((dev->reg >> 1) & 0x07)))) + val &= 0x03; + break; - case 0x71: case 0x73: - /* Limit IRQ types to supported ones. */ - if ((val & 0x01) && !(dev->current_ld->irq_types & ((dev->reg == 0x71) ? 0x0c : 0xc0))) /* level, not supported = force edge */ - val &= ~0x01; - else if (!(val & 0x01) && !(dev->current_ld->irq_types & ((dev->reg == 0x71) ? 0x03 : 0x30))) /* edge, not supported = force level */ - val |= 0x01; + case 0x71: + case 0x73: + /* Limit IRQ types to supported ones. */ + if ((val & 0x01) && !(dev->current_ld->irq_types & ((dev->reg == 0x71) ? 0x0c : 0xc0))) /* level, not supported = force edge */ + val &= ~0x01; + else if (!(val & 0x01) && !(dev->current_ld->irq_types & ((dev->reg == 0x71) ? 0x03 : 0x30))) /* edge, not supported = force level */ + val |= 0x01; - if ((val & 0x02) && !(dev->current_ld->irq_types & ((dev->reg == 0x71) ? 0x05 : 0x50))) /* high, not supported = force low */ - val &= ~0x02; - else if (!(val & 0x02) && !(dev->current_ld->irq_types & ((dev->reg == 0x71) ? 0x0a : 0xa0))) /* low, not supported = force high */ - val |= 0x02; + if ((val & 0x02) && !(dev->current_ld->irq_types & ((dev->reg == 0x71) ? 0x05 : 0x50))) /* high, not supported = force low */ + val &= ~0x02; + else if (!(val & 0x02) && !(dev->current_ld->irq_types & ((dev->reg == 0x71) ? 0x0a : 0xa0))) /* low, not supported = force high */ + val |= 0x02; - break; - } + break; - dev->current_ld->regs[dev->reg] = val; - isapnp_device_config_changed(dev->current_ld_card, dev->current_ld); - } - break; + default: + break; + } + + dev->current_ld->regs[dev->reg] = val; + isapnp_device_config_changed(dev->current_ld_card, dev->current_ld); + } + break; } } - static void * -isapnp_init(const device_t *info) +isapnp_init(UNUSED(const device_t *info)) { isapnp_t *dev = (isapnp_t *) malloc(sizeof(isapnp_t)); memset(dev, 0, sizeof(isapnp_t)); @@ -637,25 +718,26 @@ isapnp_init(const device_t *info) return dev; } - static void isapnp_close(void *priv) { - isapnp_t *dev = (isapnp_t *) priv; - isapnp_card_t *card = dev->first_card, *next_card; - isapnp_device_t *ld, *next_ld; + isapnp_t *dev = (isapnp_t *) priv; + isapnp_card_t *card = dev->first_card; + isapnp_card_t *next_card; + isapnp_device_t *ld; + isapnp_device_t *next_ld; while (card) { - ld = card->first_ld; - while (ld) { - next_ld = ld->next; - free(ld); - ld = next_ld; - } + ld = card->first_ld; + while (ld) { + next_ld = ld->next; + free(ld); + ld = next_ld; + } - next_card = card->next; - free(card); - card = next_card; + next_card = card->next; + free(card); + card = next_card; } io_removehandler(0x279, 1, NULL, NULL, NULL, isapnp_write_addr, NULL, NULL, dev); @@ -664,63 +746,78 @@ isapnp_close(void *priv) free(dev); } - void * isapnp_add_card(uint8_t *rom, uint16_t rom_size, - void (*config_changed)(uint8_t ld, isapnp_device_config_t *config, void *priv), - void (*csn_changed)(uint8_t csn, void *priv), - uint8_t (*read_vendor_reg)(uint8_t ld, uint8_t reg, void *priv), - void (*write_vendor_reg)(uint8_t ld, uint8_t reg, uint8_t val, void *priv), - void *priv) + void (*config_changed)(uint8_t ld, isapnp_device_config_t *config, void *priv), + void (*csn_changed)(uint8_t csn, void *priv), + uint8_t (*read_vendor_reg)(uint8_t ld, uint8_t reg, void *priv), + void (*write_vendor_reg)(uint8_t ld, uint8_t reg, uint8_t val, void *priv), + void *priv) { isapnp_t *dev = (isapnp_t *) device_get_priv(&isapnp_device); if (!dev) - dev = (isapnp_t *) device_add(&isapnp_device); + dev = (isapnp_t *) device_add(&isapnp_device); isapnp_card_t *card = (isapnp_card_t *) malloc(sizeof(isapnp_card_t)); memset(card, 0, sizeof(isapnp_card_t)); - card->enable = 1; - card->priv = priv; - card->config_changed = config_changed; - card->csn_changed = csn_changed; - card->read_vendor_reg = read_vendor_reg; + card->enable = 1; + card->priv = priv; + card->config_changed = config_changed; + card->csn_changed = csn_changed; + card->read_vendor_reg = read_vendor_reg; card->write_vendor_reg = write_vendor_reg; if (!dev->first_card) { - dev->first_card = card; + dev->first_card = card; } else { - isapnp_card_t *prev_card = dev->first_card; - while (prev_card->next) - prev_card = prev_card->next; - prev_card->next = card; + isapnp_card_t *prev_card = dev->first_card; + while (prev_card->next) + prev_card = prev_card->next; + prev_card->next = card; } if (rom && rom_size) - isapnp_update_card_rom(card, rom, rom_size); + isapnp_update_card_rom(card, rom, rom_size); return card; } - void isapnp_update_card_rom(void *priv, uint8_t *rom, uint16_t rom_size) { isapnp_card_t *card = (isapnp_card_t *) priv; - card->rom = rom; - card->rom_size = rom_size; + card->rom = rom; + card->rom_size = rom_size; /* Parse resources in ROM to allocate logical devices, and determine the state of read-only register bits. */ #ifdef ENABLE_ISAPNP_LOG uint16_t vendor = (card->rom[0] << 8) | card->rom[1]; isapnp_log("ISAPnP: Parsing ROM resources for card %c%c%c%02X%02X (serial %08X)\n", '@' + ((vendor >> 10) & 0x1f), '@' + ((vendor >> 5) & 0x1f), '@' + (vendor & 0x1f), card->rom[2], card->rom[3], (card->rom[7] << 24) | (card->rom[6] << 16) | (card->rom[5] << 8) | card->rom[4]); + const char *df_priority[] = { "good", "acceptable", "sub-optimal", "unknown priority" }; + const char *mem_control[] = { "8-bit", "16-bit", "8/16-bit", "32-bit" }; + const char *dma_transfer[] = { "8-bit", "8/16-bit", "16-bit", "unknown" }; + const char *dma_speed[] = { "compatibility", "Type A", "Type B", "Type F" }; #endif - uint16_t i = 9, j; - uint8_t existing = 0, ldn = 0, res, in_df = 0; - uint8_t irq = 0, io = 0, mem_range = 0, mem_range_32 = 0, irq_df = 0, io_df = 0, mem_range_df = 0, mem_range_32_df = 0; - uint32_t len; - isapnp_device_t *ld = NULL, *prev_ld = NULL; + uint16_t i = 9; + uint8_t existing = 0; + uint8_t ldn = 0; + uint8_t res; + uint8_t in_df = 0; + uint8_t irq = 0; + uint8_t dma = 0; + uint8_t io = 0; + uint8_t mem_range = 0; + uint8_t mem_range_32 = 0; + uint8_t irq_df = 0; + uint8_t dma_df = 0; + uint8_t io_df = 0; + uint8_t mem_range_df = 0; + uint8_t mem_range_32_df = 0; + uint32_t len; + isapnp_device_t *ld = NULL; + isapnp_device_t *prev_ld = NULL; /* Check if this is an existing card which already has logical devices. Any new logical devices will be added to the list after existing ones. @@ -729,278 +826,305 @@ isapnp_update_card_rom(void *priv, uint8_t *rom, uint16_t rom_size) /* Iterate through ROM resources. */ while (i < card->rom_size) { - if (card->rom[i] & 0x80) { /* large resource */ - res = card->rom[i] & 0x7f; - len = (card->rom[i + 2] << 8) | card->rom[i + 1]; + if (card->rom[i] & 0x80) { /* large resource */ + res = card->rom[i] & 0x7f; + len = (card->rom[i + 2] << 8) | card->rom[i + 1]; - switch (res) { - case 0x01: /* memory range */ - case 0x05: /* 32-bit memory range */ - if (res == 0x01) { - if (!ld) { - isapnp_log("ISAPnP: >>%s Memory descriptor with no logical device\n", in_df ? ">" : ""); - break; - } + switch (res) { + case 0x01: /* memory range */ + case 0x05: /* 32-bit memory range */ + if (res == 0x01) { + if (!ld) { + isapnp_log("ISAPnP: >>%s Memory descriptor with no logical device\n", in_df ? ">" : ""); + break; + } - if (mem_range > 3) { - isapnp_log("ISAPnP: >>%s Memory descriptor overflow (%d)\n", in_df ? ">" : "", mem_range++); - break; - } + if (mem_range > 3) { + isapnp_log("ISAPnP: >>%s Memory descriptor overflow (%d)\n", in_df ? ">" : "", mem_range++); + break; + } - isapnp_log("ISAPnP: >>%s Memory range %d uses upper limit = ", in_df ? ">" : "", mem_range); - res = 1 << mem_range; - mem_range++; - } else { - if (!ld) { - isapnp_log("ISAPnP: >>%s 32-bit memory descriptor with no logical device\n", in_df ? ">" : ""); - break; - } + isapnp_log("ISAPnP: >>%s Memory range %d with %d bytes at %06X-%06X, align %d", + in_df ? ">" : "", mem_range, + *((uint16_t *) &card->rom[i + 10]) << 8, *((uint16_t *) &card->rom[i + 4]) << 8, ((card->rom[i + 3] & 0x4) ? 0 : (*((uint16_t *) &card->rom[i + 4]) << 8)) + (*((uint16_t *) &card->rom[i + 6]) << 8), + (*((uint16_t *) &card->rom[i + 8]) + 1) << 16); + res = 1 << mem_range; + mem_range++; + } else { + if (!ld) { + isapnp_log("ISAPnP: >>%s 32-bit memory descriptor with no logical device\n", in_df ? ">" : ""); + break; + } - if (mem_range_32 > 3) { - isapnp_log("ISAPnP: >>%s 32-bit memory descriptor overflow (%d)\n", in_df ? ">" : "", mem_range_32++); - break; - } + if (mem_range_32 > 3) { + isapnp_log("ISAPnP: >>%s 32-bit memory descriptor overflow (%d)\n", in_df ? ">" : "", mem_range_32++); + break; + } - isapnp_log("ISAPnP: >>%s 32-bit memory range %d uses upper limit = ", in_df ? ">" : "", mem_range_32); - res = 1 << (4 + mem_range_32); - mem_range_32++; - } - - if (card->rom[i + 3] & 0x4) { - isapnp_log("yes\n"); - ld->mem_upperlimit |= res; - } else { - isapnp_log("no\n"); - ld->mem_upperlimit &= ~res; - } - - break; + isapnp_log("ISAPnP: >>%s 32-bit memory range %d with %d bytes at %08X-%08X, align %d", in_df ? ">" : "", mem_range_32, + *((uint32_t *) &card->rom[i + 16]) << 8, *((uint32_t *) &card->rom[i + 4]) << 8, ((card->rom[i + 3] & 0x4) ? 0 : (*((uint32_t *) &card->rom[i + 4]) << 8)) + (*((uint32_t *) &card->rom[i + 8]) << 8), + *((uint32_t *) &card->rom[i + 12])); + res = 1 << (4 + mem_range_32); + mem_range_32++; + } #ifdef ENABLE_ISAPNP_LOG - case 0x02: /* ANSI identifier */ - res = card->rom[i + 3 + len]; - card->rom[i + 3 + len] = '\0'; - isapnp_log("ISAPnP: >%s ANSI identifier: \"%s\"\n", ldn ? ">" : "", &card->rom[i + 3]); - card->rom[i + 3 + len] = res; - break; - - default: - isapnp_log("ISAPnP: >%s%s Large resource %02X (length %d)\n", ldn ? ">" : "", in_df ? ">" : "", res, (card->rom[i + 2] << 8) | card->rom[i + 1]); - break; -#endif - } - - i += 3; /* header */ - } else { /* small resource */ - res = (card->rom[i] >> 3) & 0x0f; - len = card->rom[i] & 0x07; - - switch (res) { - case 0x02: -#ifdef ENABLE_ISAPNP_LOG - vendor = (card->rom[i + 1] << 8) | card->rom[i + 2]; - isapnp_log("ISAPnP: > Logical device %02X: %c%c%c%02X%02X\n", ldn, '@' + ((vendor >> 10) & 0x1f), '@' + ((vendor >> 5) & 0x1f), '@' + (vendor & 0x1f), card->rom[i + 3], card->rom[i + 4]); + isapnp_log(" bytes, %swritable, %sread cacheable, %s, %sshadowable, %sexpansion ROM\n", + (card->rom[i + 3] & 0x01) ? "not " : "", + (card->rom[i + 3] & 0x02) ? "not " : "", + (card->rom[i + 3] & 0x04) ? "upper limit" : "range length", + mem_control[(card->rom[i + 3] >> 3) & 0x03], + (card->rom[i + 3] & 0x20) ? "not " : "", + (card->rom[i + 3] & 0x40) ? "not " : ""); #endif - /* We're done with the previous logical device. */ - if (ld && !existing) - isapnp_reset_ld_regs(ld); + if (card->rom[i + 3] & 0x4) + ld->mem_upperlimit |= res; + else + ld->mem_upperlimit &= ~res; - /* Look for an existing logical device with this number, - and create one if none exist. */ - if (existing) { - ld = card->first_ld; - while (ld && (ld->number != ldn)) - ld = ld->next; - } - if (ld && (ld->number == ldn)) { - /* Reset some logical device state. */ - ld->mem_upperlimit = ld->io_16bit = ld->irq_types = 0; - memset(ld->io_len, 0, sizeof(ld->io_len)); - } else { - /* Create logical device. */ - ld = (isapnp_device_t *) malloc(sizeof(isapnp_device_t)); - memset(ld, 0, sizeof(isapnp_device_t)); - - /* Add to end of list. */ - prev_ld = card->first_ld; - if (prev_ld) { - while (prev_ld->next) - prev_ld = prev_ld->next; - prev_ld->next = ld; - } else { - card->first_ld = ld; - } - } - - /* Set and increment logical device number. */ - ld->number = ldn++; - - /* Start the position counts over. */ - irq = io = mem_range = mem_range_32 = irq_df = io_df = mem_range_df = mem_range_32_df = 0; - - break; + break; #ifdef ENABLE_ISAPNP_LOG - case 0x03: /* compatible device ID */ - if (!ld) { - isapnp_log("ISAPnP: >> Compatible device ID with no logical device\n"); - break; - } - - vendor = (card->rom[i + 1] << 8) | card->rom[i + 2]; - isapnp_log("ISAPnP: >> Compatible device ID: %c%c%c%02X%02X\n", '@' + ((vendor >> 10) & 0x1f), '@' + ((vendor >> 5) & 0x1f), '@' + (vendor & 0x1f), card->rom[i + 3], card->rom[i + 4]); - break; + case 0x02: /* ANSI identifier */ + res = card->rom[i + 3 + len]; + card->rom[i + 3 + len] = '\0'; + isapnp_log("ISAPnP: >%s ANSI identifier: \"%s\"\n", ldn ? ">" : "", &card->rom[i + 3]); + card->rom[i + 3 + len] = res; + break; #endif - case 0x04: /* IRQ */ - if (!ld) { - isapnp_log("ISAPnP: >>%s IRQ descriptor with no logical device\n", in_df ? ">" : ""); - break; - } + default: + isapnp_log("ISAPnP: >%s%s Large resource %02X (length %d)\n", ldn ? ">" : "", in_df ? ">" : "", res, (card->rom[i + 2] << 8) | card->rom[i + 1]); + break; + } - if (irq > 1) { - isapnp_log("ISAPnP: >>%s IRQ descriptor overflow (%d)\n", in_df ? ">" : "", irq++); - break; - } + i += 3; /* header */ + } else { /* small resource */ + res = (card->rom[i] >> 3) & 0x0f; + len = card->rom[i] & 0x07; - if (len == 2) /* default */ - res = 0x01; /* high true edge sensitive */ - else /* specific */ - res = card->rom[i + 3] & 0x0f; + switch (res) { +#ifdef ENABLE_ISAPNP_LOG + case 0x01: /* PnP version */ + isapnp_log("ISAPnP: > PnP version %d.%d, vendor-specific version %02X\n", card->rom[i + 1] >> 4, card->rom[i + 1] & 0x0f, card->rom[i + 2]); + break; +#endif - isapnp_log("ISAPnP: >>%s IRQ index %d interrupt types = %01X\n", in_df ? ">" : "", irq, res); + case 0x02: /* logical device */ +#ifdef ENABLE_ISAPNP_LOG + vendor = (card->rom[i + 1] << 8) | card->rom[i + 2]; + isapnp_log("ISAPnP: > Logical device %02X: %c%c%c%02X%02X\n", ldn, '@' + ((vendor >> 10) & 0x1f), '@' + ((vendor >> 5) & 0x1f), '@' + (vendor & 0x1f), card->rom[i + 3], card->rom[i + 4]); +#endif - ld->irq_types &= ~(0x0f << (4 * irq)); - ld->irq_types |= res << (4 * irq); + /* We're done with the previous logical device. */ + if (ld && !existing) + isapnp_reset_ld_regs(ld); - irq++; + /* Look for an existing logical device with this number, + and create one if none exist. */ + if (existing) { + ld = card->first_ld; + while (ld && (ld->number != ldn)) + ld = ld->next; + } + if (ld && (ld->number == ldn)) { + /* Reset some logical device state. */ + ld->mem_upperlimit = ld->io_16bit = ld->irq_types = 0; + memset(ld->io_len, 0, sizeof(ld->io_len)); + } else { + /* Create logical device. */ + ld = (isapnp_device_t *) malloc(sizeof(isapnp_device_t)); + memset(ld, 0, sizeof(isapnp_device_t)); - break; + /* Add to end of list. */ + prev_ld = card->first_ld; + if (prev_ld) { + while (prev_ld->next) + prev_ld = prev_ld->next; + prev_ld->next = ld; + } else { + card->first_ld = ld; + } + } - case 0x06: /* start dependent function */ - if (!ld) { - isapnp_log("ISAPnP: >> Start dependent function with no logical device\n"); - break; - } + /* Set and increment logical device number. */ + ld->number = ldn++; - isapnp_log("ISAPnP: >> Start dependent function: %s\n", (((len == 0) || (card->rom[i + 1] == 1)) ? "acceptable" : ((card->rom[i + 1] == 0) ? "good" : ((card->rom[i + 1] == 2) ? "sub-optimal" : "unknown priority")))); + /* Start the position counts over. */ + irq = dma = io = mem_range = mem_range_32 = irq_df = dma_df = io_df = mem_range_df = mem_range_32_df = 0; - if (in_df) { - /* We're in a dependent function and this is the next one starting. - Walk positions back to the saved values. */ - irq = irq_df; - io = io_df; - mem_range = mem_range_df; - mem_range_32 = mem_range_32_df; - } else { - /* Save current positions to restore at the next DF. */ - irq_df = irq; - io_df = io; - mem_range_df = mem_range; - mem_range_32_df = mem_range_32; - in_df = 1; - } - - break; - - case 0x07: /* end dependent function */ - isapnp_log("ISAPnP: >> End dependent function\n"); - in_df = 0; - break; - - case 0x08: /* I/O port */ - if (!ld) { - isapnp_log("ISAPnP: >>%s I/O descriptor with no logical device\n", in_df ? ">" : ""); - break; - } - - if (io > 7) { - isapnp_log("ISAPnP: >>%s I/O descriptor overflow (%d)\n", in_df ? ">" : "", io++); - break; - } - - isapnp_log("ISAPnP: >>%s I/O range %d %d-bit decode, %d ports\n", in_df ? ">" : "", io, (card->rom[i + 1] & 0x01) ? 16 : 10, card->rom[i + 7]); - - if (card->rom[i + 1] & 0x01) - ld->io_16bit |= 1 << io; - else - ld->io_16bit &= ~(1 << io); - - if (card->rom[i + 7] > ld->io_len[io]) - ld->io_len[io] = card->rom[i + 7]; - - io++; - - break; - - case 0x0f: /* end tag */ - /* Calculate checksum. */ - res = 0x00; - for (j = 9; j <= i; j++) - res += card->rom[j]; - card->rom[i + 1] = -res; - - isapnp_log("ISAPnP: End card resources (checksum %02X)\n", card->rom[i + 1]); - - /* Stop parsing here. */ - card->rom_size = i + 2; - break; + break; #ifdef ENABLE_ISAPNP_LOG - default: - isapnp_log("ISAPnP: >%s%s Small resource %02X (length %d)\n", ldn ? ">" : "", in_df ? ">" : "", res, card->rom[i] & 0x07); - break; -#endif - } + case 0x03: /* compatible device ID */ + if (!ld) { + isapnp_log("ISAPnP: >> Compatible device ID with no logical device\n"); + break; + } - i++; /* header */ - } - i += len; /* specified length */ + vendor = (card->rom[i + 1] << 8) | card->rom[i + 2]; + isapnp_log("ISAPnP: >> Compatible device ID: %c%c%c%02X%02X\n", '@' + ((vendor >> 10) & 0x1f), '@' + ((vendor >> 5) & 0x1f), '@' + (vendor & 0x1f), card->rom[i + 3], card->rom[i + 4]); + break; +#endif + + case 0x04: /* IRQ */ + if (!ld) { + isapnp_log("ISAPnP: >>%s IRQ descriptor with no logical device\n", in_df ? ">" : ""); + break; + } + + if (irq > 1) { + isapnp_log("ISAPnP: >>%s IRQ descriptor overflow (%d)\n", in_df ? ">" : "", irq++); + break; + } + + if (len == 2) /* default */ + res = 0x01; /* high true edge sensitive */ + else /* specific */ + res = card->rom[i + 3] & 0x0f; + + isapnp_log("ISAPnP: >>%s IRQ index %d with mask %04X, types %01X\n", in_df ? ">" : "", irq, *((uint16_t *) &card->rom[i + 1]), res); + + ld->irq_types &= ~(0x0f << (4 * irq)); + ld->irq_types |= res << (4 * irq); + + irq++; + + break; + +#ifdef ENABLE_ISAPNP_LOG + case 0x05: /* DMA */ + isapnp_log("ISAPnP: >>%s DMA index %d with mask %02X, %s, %sbus master, %scount by byte, %scount by word, %s speed\n", in_df ? ">" : "", dma++, card->rom[i + 1], + dma_transfer[card->rom[i + 2] & 3], + (card->rom[i + 2] & 0x04) ? "not " : "", + (card->rom[i + 2] & 0x08) ? "not " : "", + (card->rom[i + 2] & 0x10) ? "not " : "", + dma_speed[(card->rom[i + 2] >> 5) & 3]); + break; +#endif + + case 0x06: /* start dependent function */ + if (!ld) { + isapnp_log("ISAPnP: >> Start dependent function with no logical device\n"); + break; + } + +#ifdef ENABLE_ISAPNP_LOG + isapnp_log("ISAPnP: >> Start dependent function: %s\n", df_priority[(len < 1) ? 1 : (card->rom[i + 1] & 3)]); +#endif + + if (in_df) { + /* We're in a dependent function and this is the next one starting. + Walk positions back to the saved values. */ + irq = irq_df; + dma = dma_df; + io = io_df; + mem_range = mem_range_df; + mem_range_32 = mem_range_32_df; + } else { + /* Save current positions to restore at the next DF. */ + irq_df = irq; + dma_df = dma; + io_df = io; + mem_range_df = mem_range; + mem_range_32_df = mem_range_32; + in_df = 1; + } + + break; + + case 0x07: /* end dependent function */ + isapnp_log("ISAPnP: >> End dependent function\n"); + in_df = 0; + break; + + case 0x08: /* I/O port */ + if (!ld) { + isapnp_log("ISAPnP: >>%s I/O descriptor with no logical device\n", in_df ? ">" : ""); + break; + } + + if (io > 7) { + isapnp_log("ISAPnP: >>%s I/O descriptor overflow (%d)\n", in_df ? ">" : "", io++); + break; + } + + isapnp_log("ISAPnP: >>%s I/O range %d with %d ports at %04X-%04X, align %d, %d-bit decode\n", in_df ? ">" : "", io, card->rom[i + 7], *((uint16_t *) &card->rom[i + 2]), *((uint16_t *) &card->rom[i + 4]), card->rom[i + 6], (card->rom[i + 1] & 0x01) ? 16 : 10); + + if (card->rom[i + 1] & 0x01) + ld->io_16bit |= 1 << io; + else + ld->io_16bit &= ~(1 << io); + + if (card->rom[i + 7] > ld->io_len[io]) + ld->io_len[io] = card->rom[i + 7]; + + io++; + + break; + + case 0x0f: /* end tag */ + /* Calculate checksum. */ + res = 0x00; + for (uint16_t j = 9; j <= i; j++) + res += card->rom[j]; + card->rom[i + 1] = -res; + + isapnp_log("ISAPnP: End card resources (checksum %02X)\n", card->rom[i + 1]); + + /* Stop parsing here. */ + card->rom_size = i + 2; + break; + + default: + isapnp_log("ISAPnP: >%s%s Small resource %02X (length %d)\n", ldn ? ">" : "", in_df ? ">" : "", res, card->rom[i] & 0x07); + break; + } + + i++; /* header */ + } + i += len; /* specified length */ } /* We're done with the last logical device. */ if (ld && !existing) - isapnp_reset_ld_regs(ld); + isapnp_reset_ld_regs(ld); } - void isapnp_enable_card(void *priv, uint8_t enable) { isapnp_t *dev = (isapnp_t *) device_get_priv(&isapnp_device); if (!dev) - return; + return; /* Look for a matching card. */ isapnp_card_t *card = dev->first_card; - uint8_t will_enable; while (card) { - if (card == priv) { - /* Enable or disable the card. */ - will_enable = (enable >= ISAPNP_CARD_ENABLE); - if (will_enable ^ card->enable) - card->state = (enable == ISAPNP_CARD_FORCE_CONFIG) ? PNP_STATE_CONFIG : PNP_STATE_WAIT_FOR_KEY; - card->enable = will_enable; + if (card == priv) { + /* Enable or disable the card. */ + if (!!enable ^ !!card->enable) + card->state = (enable == ISAPNP_CARD_FORCE_CONFIG) ? PNP_STATE_CONFIG : PNP_STATE_WAIT_FOR_KEY; + card->enable = enable; - /* Invalidate other references if we're disabling this card. */ - if (!card->enable) { - if (dev->isolated_card == card) - dev->isolated_card = NULL; - if (dev->current_ld_card == card) { - dev->current_ld = NULL; - dev->current_ld_card = NULL; - } - } + /* Invalidate other references if we're disabling this card. */ + if (!card->enable) { + if (dev->isolated_card == card) + dev->isolated_card = NULL; + if (dev->current_ld_card == card) { + dev->current_ld = NULL; + dev->current_ld_card = NULL; + } + } - break; - } + break; + } - card = card->next; + card = card->next; } } - void isapnp_set_csn(void *priv, uint8_t csn) { @@ -1008,69 +1132,69 @@ isapnp_set_csn(void *priv, uint8_t csn) card->csn = csn; if (card->csn_changed) - card->csn_changed(card->csn, card->priv); + card->csn_changed(card->csn, card->priv); } - void isapnp_set_device_defaults(void *priv, uint8_t ldn, const isapnp_device_config_t *config) { - isapnp_card_t *card = (isapnp_card_t *) priv; - isapnp_device_t *ld = card->first_ld; + isapnp_card_t *card = (isapnp_card_t *) priv; + isapnp_device_t *ld = card->first_ld; /* Look for a logical device with this number. */ while (ld && (ld->number != ldn)) - ld = ld->next; + ld = ld->next; if (!ld) /* none found */ - return; + return; ld->defaults = config; } - void isapnp_reset_card(void *priv) { - isapnp_card_t *card = (isapnp_card_t *) priv; - isapnp_device_t *ld = card->first_ld; + isapnp_card_t *card = (isapnp_card_t *) priv; + isapnp_device_t *ld = card->first_ld; /* Reset all logical devices. */ while (ld) { - /* Reset the logical device's configuration. */ - isapnp_reset_ld_config(ld); - isapnp_device_config_changed(card, ld); + /* Reset the logical device's configuration. */ + isapnp_reset_ld_config(ld); + isapnp_device_config_changed(card, ld); - ld = ld->next; + ld = ld->next; } } - void isapnp_reset_device(void *priv, uint8_t ldn) { - isapnp_card_t *card = (isapnp_card_t *) priv; - isapnp_device_t *ld = card->first_ld; + isapnp_card_t *card = (isapnp_card_t *) priv; + isapnp_device_t *ld = card->first_ld; /* Look for a logical device with this number. */ while (ld && (ld->number != ldn)) - ld = ld->next; + ld = ld->next; if (!ld) /* none found */ - return; + return; /* Reset the logical device's configuration. */ isapnp_reset_ld_config(ld); isapnp_device_config_changed(card, ld); } - static const device_t isapnp_device = { - "ISA Plug and Play", - "isapnp", - 0, - 0, - isapnp_init, isapnp_close, NULL, - { NULL }, NULL, NULL, - NULL + .name = "ISA Plug and Play", + .internal_name = "isapnp", + .flags = 0, + .local = 0, + .init = isapnp_init, + .close = isapnp_close, + .reset = NULL, + { .available = NULL }, + .speed_changed = NULL, + .force_redraw = NULL, + .config = NULL }; diff --git a/src/device/isartc.c b/src/device/isartc.c index 57ccd957f..46f31c137 100644 --- a/src/device/isartc.c +++ b/src/device/isartc.c @@ -1,56 +1,54 @@ /* - * VARCem Virtual ARchaeological Computer EMulator. - * An emulator of (mostly) x86-based PC systems and devices, - * using the ISA,EISA,VLB,MCA and PCI system buses, roughly - * spanning the era between 1981 and 1995. + * VARCem Virtual ARchaeological Computer EMulator. + * An emulator of (mostly) x86-based PC systems and devices, + * using the ISA,EISA,VLB,MCA and PCI system buses, roughly + * spanning the era between 1981 and 1995. * - * This file is part of the VARCem Project. + * Implementation of a Clock/RTC Card for the ISA PC/XT. * - * Implementation of a Clock/RTC Card for the ISA PC/XT. + * Systems starting with the PC/XT had, by default, a realtime + * clock and NVR chip on the mainboard. The BIOS stored config + * data in the NVR, and the system could maintain time and date + * using the RTC. * - * Systems starting with the PC/XT had, by default, a realtime - * clock and NVR chip on the mainboard. The BIOS stored config - * data in the NVR, and the system could maintain time and date - * using the RTC. + * Originally, PC systems did not have this, and they first did + * show up in non-IBM clone systems. Shortly after, expansion + * cards with this function became available for the PC's (ISA) + * bus, and they came in many forms and designs. * - * Originally, PC systems did not have this, and they first did - * show up in non-IBM clone systems. Shortly after, expansion - * cards with this function became available for the PC's (ISA) - * bus, and they came in many forms and designs. + * This implementation offers some of those boards: * - * This implementation offers some of those boards: + * Everex EV-170 (using NatSemi MM58167 chip) + * DTK PII-147 Hexa I/O Plus (using UMC 82C8167 chip) * - * Everex EV-170 (using NatSemi MM58167 chip) - * DTK PII-147 Hexa I/O Plus (using UMC 82C8167 chip) + * and more will follow as time permits. * - * and more will follow as time permits. - * - * NOTE: The IRQ functionalities have been implemented, but not yet - * tested, as I need to write test software for them first :) + * NOTE: The IRQ functionalities have been implemented, but not yet + * tested, as I need to write test software for them first :) * * * - * Author: Fred N. van Kempen, + * Authors: Fred N. van Kempen, * - * Copyright 2018 Fred N. van Kempen. + * Copyright 2018 Fred N. van Kempen. * - * Redistribution and use in source and binary forms, with - * or without modification, are permitted provided that the - * following conditions are met: + * Redistribution and use in source and binary forms, with + * or without modification, are permitted provided that the + * following conditions are met: * - * 1. Redistributions of source code must retain the entire - * above notice, this list of conditions and the following - * disclaimer. + * 1. Redistributions of source code must retain the entire + * above notice, this list of conditions and the following + * disclaimer. * - * 2. Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the - * following disclaimer in the documentation and/or other - * materials provided with the distribution. + * 2. Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the + * following disclaimer in the documentation and/or other + * materials provided with the distribution. * - * 3. Neither the name of the copyright holder nor the names - * of its contributors may be used to endorse or promote - * products derived from this software without specific - * prior written permission. + * 3. Neither the name of the copyright holder nor the names + * of its contributors may be used to endorse or promote + * products derived from this software without specific + * prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT @@ -63,13 +61,15 @@ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -*/ + */ +#include #include #include #include #include #include #include +#define HAVE_STDARG_H #include <86box/86box.h> #include "cpu.h" #include <86box/timer.h> @@ -82,108 +82,102 @@ #include <86box/pic.h> #include <86box/isartc.h> +#define ISARTC_EV170 0 +#define ISARTC_DTK 1 +#define ISARTC_P5PAK 2 +#define ISARTC_A6PAK 3 +#define ISARTC_VENDEX 4 -#define ISARTC_EV170 0 -#define ISARTC_DTK 1 -#define ISARTC_P5PAK 2 -#define ISARTC_A6PAK 3 +#define ISARTC_DEBUG 0 -#define ISARTC_DEBUG 0 +typedef struct rtcdev_t { + const char *name; /* board name */ + uint8_t board; /* board type */ + uint8_t flags; /* various flags */ +#define FLAG_YEAR80 0x01 /* YEAR byte is base-80 */ +#define FLAG_YEARBCD 0x02 /* YEAR byte is in BCD */ -typedef struct { - const char *name; /* board name */ - uint8_t board; /* board type */ - - uint8_t flags; /* various flags */ -#define FLAG_YEAR80 0x01 /* YEAR byte is base-80 */ -#define FLAG_YEARBCD 0x02 /* YEAR byte is in BCD */ - - int8_t irq; /* configured IRQ channel */ - int8_t base_addrsz; - uint32_t base_addr; /* configured I/O address */ + int8_t irq; /* configured IRQ channel */ + int8_t base_addrsz; + uint32_t base_addr; /* configured I/O address */ /* Fields for the specific driver. */ - void (*f_wr)(uint16_t, uint8_t, void *); - uint8_t (*f_rd)(uint16_t, void *); - int8_t year; /* register for YEAR value */ - char pad[3]; + void (*f_wr)(uint16_t, uint8_t, void *); + uint8_t (*f_rd)(uint16_t, void *); + int8_t year; /* register for YEAR value */ + char pad[3]; - nvr_t nvr; /* RTC/NVR */ + nvr_t nvr; /* RTC/NVR */ } rtcdev_t; - /************************************************************************ - * * - * Driver for the NatSemi MM58167 chip. * - * * + * * + * Driver for the NatSemi MM58167 chip. * + * * ************************************************************************/ -#define MM67_REGS 32 +#define MM67_REGS 32 /* Define the RTC chip registers - see datasheet, pg4. */ -#define MM67_MSEC 0 /* milliseconds */ -#define MM67_HUNTEN 1 /* hundredths/tenths of seconds */ -#define MM67_SEC 2 /* seconds */ -#define MM67_MIN 3 /* minutes */ -#define MM67_HOUR 4 /* hours */ -#define MM67_DOW 5 /* day of the week */ -#define MM67_DOM 6 /* day of the month */ -#define MM67_MON 7 /* month */ -#define MM67_AL_MSEC 8 /* milliseconds */ -#define MM67_AL_HUNTEN 9 /* hundredths/tenths of seconds */ -#define MM67_AL_SEC 10 /* seconds */ -#define MM67_AL_MIN 11 /* minutes */ -#define MM67_AL_HOUR 12 /* hours */ -#define MM67_AL_DOW 13 /* day of the week */ -#define MM67_AL_DOM 14 /* day of the month */ -#define MM67_AL_MON 15 /* month */ -# define MM67_AL_DONTCARE 0xc0 /* always match in compare */ -#define MM67_ISTAT 16 /* IRQ status */ -#define MM67_ICTRL 17 /* IRQ control */ -# define MM67INT_COMPARE 0x01 /* Compare */ -# define MM67INT_TENTH 0x02 /* Tenth */ -# define MM67INT_SEC 0x04 /* Second */ -# define MM67INT_MIN 0x08 /* Minute */ -# define MM67INT_HOUR 0x10 /* Hour */ -# define MM67INT_DAY 0x20 /* Day */ -# define MM67INT_WEEK 0x40 /* Week */ -# define MM67INT_MON 0x80 /* Month */ -#define MM67_RSTCTR 18 /* reset counters */ -#define MM67_RSTRAM 19 /* reset RAM */ -#define MM67_STATUS 20 /* status bit */ -#define MM67_GOCMD 21 /* GO Command */ -#define MM67_STBYIRQ 22 /* standby IRQ */ -#define MM67_TEST 31 /* test mode */ +#define MM67_MSEC 0 /* milliseconds */ +#define MM67_HUNTEN 1 /* hundredths/tenths of seconds */ +#define MM67_SEC 2 /* seconds */ +#define MM67_MIN 3 /* minutes */ +#define MM67_HOUR 4 /* hours */ +#define MM67_DOW 5 /* day of the week */ +#define MM67_DOM 6 /* day of the month */ +#define MM67_MON 7 /* month */ +#define MM67_AL_MSEC 8 /* milliseconds */ +#define MM67_AL_HUNTEN 9 /* hundredths/tenths of seconds */ +#define MM67_AL_SEC 10 /* seconds */ +#define MM67_AL_MIN 11 /* minutes */ +#define MM67_AL_HOUR 12 /* hours */ +#define MM67_AL_DOW 13 /* day of the week */ +#define MM67_AL_DOM 14 /* day of the month */ +#define MM67_AL_MON 15 /* month */ +#define MM67_AL_DONTCARE 0xc0 /* always match in compare */ +#define MM67_ISTAT 16 /* IRQ status */ +#define MM67_ICTRL 17 /* IRQ control */ +#define MM67INT_COMPARE 0x01 /* Compare */ +#define MM67INT_TENTH 0x02 /* Tenth */ +#define MM67INT_SEC 0x04 /* Second */ +#define MM67INT_MIN 0x08 /* Minute */ +#define MM67INT_HOUR 0x10 /* Hour */ +#define MM67INT_DAY 0x20 /* Day */ +#define MM67INT_WEEK 0x40 /* Week */ +#define MM67INT_MON 0x80 /* Month */ +#define MM67_RSTCTR 18 /* reset counters */ +#define MM67_RSTRAM 19 /* reset RAM */ +#define MM67_STATUS 20 /* status bit */ +#define MM67_GOCMD 21 /* GO Command */ +#define MM67_STBYIRQ 22 /* standby IRQ */ +#define MM67_TEST 31 /* test mode */ #ifdef ENABLE_ISARTC_LOG int isartc_do_log = ENABLE_ISARTC_LOG; - static void isartc_log(const char *fmt, ...) { va_list ap; if (isartc_do_log) { - va_start(ap, fmt); - pclog_ex(fmt, ap); - va_end(ap); + va_start(ap, fmt); + pclog_ex(fmt, ap); + va_end(ap); } } #else -#define isartc_log(fmt, ...) +# define isartc_log(fmt, ...) #endif - /* Check if the current time matches a set alarm time. */ static int8_t mm67_chkalrm(nvr_t *nvr, int8_t addr) { - return((nvr->regs[addr-MM67_AL_SEC+MM67_SEC] == nvr->regs[addr]) || - ((nvr->regs[addr] & MM67_AL_DONTCARE) == MM67_AL_DONTCARE)); + return ((nvr->regs[addr - MM67_AL_SEC + MM67_SEC] == nvr->regs[addr]) || ((nvr->regs[addr] & MM67_AL_DONTCARE) == MM67_AL_DONTCARE)); } - /* * This is called every second through the NVR/RTC hook. * @@ -197,160 +191,168 @@ mm67_chkalrm(nvr_t *nvr, int8_t addr) static void mm67_tick(nvr_t *nvr) { - rtcdev_t *dev = (rtcdev_t *)nvr->data; - uint8_t *regs = nvr->regs; - int mon, year, f = 0; + const rtcdev_t *dev = (rtcdev_t *) nvr->data; + uint8_t *regs = nvr->regs; + int mon; + int year; + int f = 0; /* Update and set interrupt if needed. */ regs[MM67_SEC] = RTC_BCDINC(nvr->regs[MM67_SEC], 1); - if (regs[MM67_ICTRL] & MM67INT_SEC) f = MM67INT_SEC; + if (regs[MM67_ICTRL] & MM67INT_SEC) + f = MM67INT_SEC; /* Roll over? */ if (regs[MM67_SEC] >= RTC_BCD(60)) { - /* Update and set interrupt if needed. */ - regs[MM67_SEC] = RTC_BCD(0); - regs[MM67_MIN] = RTC_BCDINC(regs[MM67_MIN], 1); - if (regs[MM67_ICTRL] & MM67INT_MIN) f = MM67INT_MIN; + /* Update and set interrupt if needed. */ + regs[MM67_SEC] = RTC_BCD(0); + regs[MM67_MIN] = RTC_BCDINC(regs[MM67_MIN], 1); + if (regs[MM67_ICTRL] & MM67INT_MIN) + f = MM67INT_MIN; - /* Roll over? */ - if (regs[MM67_MIN] >= RTC_BCD(60)) { - /* Update and set interrupt if needed. */ - regs[MM67_MIN] = RTC_BCD(0); - regs[MM67_HOUR] = RTC_BCDINC(regs[MM67_HOUR], 1); - if (regs[MM67_ICTRL] & MM67INT_HOUR) f = MM67INT_HOUR; + /* Roll over? */ + if (regs[MM67_MIN] >= RTC_BCD(60)) { + /* Update and set interrupt if needed. */ + regs[MM67_MIN] = RTC_BCD(0); + regs[MM67_HOUR] = RTC_BCDINC(regs[MM67_HOUR], 1); + if (regs[MM67_ICTRL] & MM67INT_HOUR) + f = MM67INT_HOUR; - /* Roll over? */ - if (regs[MM67_HOUR] >= RTC_BCD(24)) { - /* Update and set interrupt if needed. */ - regs[MM67_HOUR] = RTC_BCD(0); - regs[MM67_DOW] = RTC_BCDINC(regs[MM67_DOW], 1); - if (regs[MM67_ICTRL] & MM67INT_DAY) f = MM67INT_DAY; + /* Roll over? */ + if (regs[MM67_HOUR] >= RTC_BCD(24)) { + /* Update and set interrupt if needed. */ + regs[MM67_HOUR] = RTC_BCD(0); + regs[MM67_DOW] = RTC_BCDINC(regs[MM67_DOW], 1); + if (regs[MM67_ICTRL] & MM67INT_DAY) + f = MM67INT_DAY; - /* Roll over? */ - if (regs[MM67_DOW] > RTC_BCD(7)) { - /* Update and set interrupt if needed. */ - regs[MM67_DOW] = RTC_BCD(1); - if (regs[MM67_ICTRL] & MM67INT_WEEK) f = MM67INT_WEEK; - } + /* Roll over? */ + if (regs[MM67_DOW] > RTC_BCD(7)) { + /* Update and set interrupt if needed. */ + regs[MM67_DOW] = RTC_BCD(1); + if (regs[MM67_ICTRL] & MM67INT_WEEK) + f = MM67INT_WEEK; + } - /* Roll over? */ - regs[MM67_DOM] = RTC_BCDINC(regs[MM67_DOM], 1); - mon = RTC_DCB(regs[MM67_MON]); - if (dev->year != -1) { - year = RTC_DCB(regs[dev->year]); - if (dev->flags & FLAG_YEAR80) - year += 80; - } else - year = 80; - year += 1900; - if (RTC_DCB(regs[MM67_DOM]) > nvr_get_days(mon, year)) { - /* Update and set interrupt if needed. */ - regs[MM67_DOM] = RTC_BCD(1); - regs[MM67_MON] = RTC_BCDINC(regs[MM67_MON], 1); - if (regs[MM67_ICTRL] & MM67INT_MON) f = MM67INT_MON; + /* Roll over? */ + regs[MM67_DOM] = RTC_BCDINC(regs[MM67_DOM], 1); + mon = RTC_DCB(regs[MM67_MON]); + if (dev->year != -1) { + if (dev->flags & FLAG_YEARBCD) + year = RTC_DCB(regs[dev->year]); + else + year = regs[dev->year]; + if (dev->flags & FLAG_YEAR80) + year += 80; + } else + year = 80; + year += 1900; + if (RTC_DCB(regs[MM67_DOM]) > nvr_get_days(mon, year)) { + /* Update and set interrupt if needed. */ + regs[MM67_DOM] = RTC_BCD(1); + regs[MM67_MON] = RTC_BCDINC(regs[MM67_MON], 1); + if (regs[MM67_ICTRL] & MM67INT_MON) + f = MM67INT_MON; - /* Roll over? */ - if (regs[MM67_MON] > RTC_BCD(12)) { - /* Update. */ - regs[MM67_MON] = RTC_BCD(1); - if (dev->year != -1) { - year++; - if (dev->flags & FLAG_YEAR80) - year -= 80; + /* Roll over? */ + if (regs[MM67_MON] > RTC_BCD(12)) { + /* Update. */ + regs[MM67_MON] = RTC_BCD(1); + if (dev->year != -1) { + year++; + if (dev->flags & FLAG_YEAR80) + year -= 80; - if (dev->flags & FLAG_YEARBCD) - regs[dev->year] = RTC_BCD(year % 100); - else - regs[dev->year] = year % 100; - } - } - } - } - } + if (dev->flags & FLAG_YEARBCD) + regs[dev->year] = RTC_BCD(year % 100); + else + regs[dev->year] = year % 100; + } + } + } + } + } } /* Check for programmed alarm interrupt. */ if (regs[MM67_ICTRL] & MM67INT_COMPARE) { - year = 1; - for (mon = MM67_AL_SEC; mon <= MM67_AL_MON; mon++) - if (mon != dev->year) - year &= mm67_chkalrm(nvr, mon); - f = year ? MM67INT_COMPARE : 0x00; + year = 1; + for (mon = MM67_AL_SEC; mon <= MM67_AL_MON; mon++) + if (mon != dev->year) + year &= mm67_chkalrm(nvr, mon); + f = year ? MM67INT_COMPARE : 0x00; } /* Raise the IRQ if needed (and if we have one..) */ if (f != 0) { - regs[MM67_ISTAT] = f; - if (nvr->irq != -1) - picint(1 << nvr->irq); + regs[MM67_ISTAT] = f; + if (nvr->irq != -1) + picint(1 << nvr->irq); } } - /* Get the current NVR time. */ static void mm67_time_get(nvr_t *nvr, struct tm *tm) { - rtcdev_t *dev = (rtcdev_t *)nvr->data; - uint8_t *regs = nvr->regs; + const rtcdev_t *dev = (rtcdev_t *) nvr->data; + const uint8_t *regs = nvr->regs; /* NVR is in BCD data mode. */ - tm->tm_sec = RTC_DCB(regs[MM67_SEC]); - tm->tm_min = RTC_DCB(regs[MM67_MIN]); + tm->tm_sec = RTC_DCB(regs[MM67_SEC]); + tm->tm_min = RTC_DCB(regs[MM67_MIN]); tm->tm_hour = RTC_DCB(regs[MM67_HOUR]); tm->tm_wday = (RTC_DCB(regs[MM67_DOW]) - 1); tm->tm_mday = RTC_DCB(regs[MM67_DOM]); - tm->tm_mon = (RTC_DCB(regs[MM67_MON]) - 1); + tm->tm_mon = (RTC_DCB(regs[MM67_MON]) - 1); if (dev->year != -1) { - if (dev->flags & FLAG_YEARBCD) - tm->tm_year = RTC_DCB(regs[dev->year]); - else - tm->tm_year = regs[dev->year]; - if (dev->flags & FLAG_YEAR80) - tm->tm_year += 80; + if (dev->flags & FLAG_YEARBCD) + tm->tm_year = RTC_DCB(regs[dev->year]); + else + tm->tm_year = regs[dev->year]; + if (dev->flags & FLAG_YEAR80) + tm->tm_year += 80; #ifdef MM67_CENTURY - tm->tm_year += (regs[MM67_CENTURY] * 100) - 1900; + tm->tm_year += (regs[MM67_CENTURY] * 100) - 1900; #endif #if ISARTC_DEBUG > 1 - isartc_log("ISARTC: get_time: year=%i [%02x]\n", tm->tm_year, regs[dev->year]); + isartc_log("ISARTC: get_time: year=%i [%02x]\n", tm->tm_year, regs[dev->year]); #endif } } - /* Set the current NVR time. */ static void mm67_time_set(nvr_t *nvr, struct tm *tm) { - rtcdev_t *dev = (rtcdev_t *)nvr->data; - uint8_t *regs = nvr->regs; - int year; + const rtcdev_t *dev = (rtcdev_t *) nvr->data; + uint8_t *regs = nvr->regs; + int year; /* NVR is in BCD data mode. */ - regs[MM67_SEC] = RTC_BCD(tm->tm_sec); - regs[MM67_MIN] = RTC_BCD(tm->tm_min); + regs[MM67_SEC] = RTC_BCD(tm->tm_sec); + regs[MM67_MIN] = RTC_BCD(tm->tm_min); regs[MM67_HOUR] = RTC_BCD(tm->tm_hour); - regs[MM67_DOW] = RTC_BCD(tm->tm_wday + 1); - regs[MM67_DOM] = RTC_BCD(tm->tm_mday); - regs[MM67_MON] = RTC_BCD(tm->tm_mon + 1); + regs[MM67_DOW] = RTC_BCD(tm->tm_wday + 1); + regs[MM67_DOM] = RTC_BCD(tm->tm_mday); + regs[MM67_MON] = RTC_BCD(tm->tm_mon + 1); if (dev->year != -1) { - year = tm->tm_year; - if (dev->flags & FLAG_YEAR80) - year -= 80; - if (dev->flags & FLAG_YEARBCD) - regs[dev->year] = RTC_BCD(year % 100); - else - regs[dev->year] = year % 100; + year = tm->tm_year; + if (dev->flags & FLAG_YEAR80) + year -= 80; + if (dev->flags & FLAG_YEARBCD) + regs[dev->year] = RTC_BCD(year % 100); + else + regs[dev->year] = year % 100; #ifdef MM67_CENTURY - regs[MM67_CENTURY] = (year + 1900) / 100; + regs[MM67_CENTURY] = (year + 1900) / 100; #endif #if ISARTC_DEBUG > 1 - isartc_log("ISARTC: set_time: [%02x] year=%i (%i)\n", regs[dev->year], year, tm->tm_year); + isartc_log("ISARTC: set_time: [%02x] year=%i (%i)\n", regs[dev->year], year, tm->tm_year); #endif } } - static void mm67_start(nvr_t *nvr) { @@ -358,139 +360,148 @@ mm67_start(nvr_t *nvr) /* Initialize the internal and chip times. */ if (time_sync) { - /* Use the internal clock's time. */ - nvr_time_get(&tm); - mm67_time_set(nvr, &tm); + /* Use the internal clock's time. */ + nvr_time_get(&tm); + mm67_time_set(nvr, &tm); } else { - /* Set the internal clock from the chip time. */ - mm67_time_get(nvr, &tm); - nvr_time_set(&tm); + /* Set the internal clock from the chip time. */ + mm67_time_get(nvr, &tm); + nvr_time_set(&tm); } } - /* Reset the RTC counters to a sane state. */ static void mm67_reset(nvr_t *nvr) { - int i; - /* Initialize the RTC to a known state. */ - for (i = MM67_MSEC; i <= MM67_MON; i++) - nvr->regs[i] = RTC_BCD(0); + for (uint8_t i = MM67_MSEC; i <= MM67_MON; i++) + nvr->regs[i] = RTC_BCD(0); nvr->regs[MM67_DOW] = RTC_BCD(1); nvr->regs[MM67_DOM] = RTC_BCD(1); nvr->regs[MM67_MON] = RTC_BCD(1); } - /* Handle a READ operation from one of our registers. */ static uint8_t mm67_read(uint16_t port, void *priv) { - rtcdev_t *dev = (rtcdev_t *)priv; - int reg = port - dev->base_addr; - uint8_t ret = 0xff; + rtcdev_t *dev = (rtcdev_t *) priv; + int reg = port - dev->base_addr; + uint8_t ret = 0xff; /* This chip is directly mapped on I/O. */ cycles -= ISA_CYCLES(4); - switch(reg) { - case MM67_ISTAT: /* IRQ status (RO) */ - ret = dev->nvr.regs[reg]; - dev->nvr.regs[reg] = 0x00; - if (dev->irq != -1) - picintc(1 << dev->irq); - break; + switch (reg) { + case MM67_ISTAT: /* IRQ status (RO) */ + ret = dev->nvr.regs[reg]; + dev->nvr.regs[reg] = 0x00; + if (dev->irq != -1) + picintc(1 << dev->irq); + break; - default: - ret = dev->nvr.regs[reg]; - break; + case MM67_AL_MSEC: + ret = dev->nvr.regs[reg] & 0xf0; + break; + + case MM67_AL_DOW: + ret = dev->nvr.regs[reg] & 0x0f; + break; + + default: + ret = dev->nvr.regs[reg]; + break; } -#if ISARTC_DEBUG - isartc_log("ISARTC: read(%04x) = %02x\n", port-dev->base_addr, ret); +#if ISARTC_DEBUG + isartc_log("ISARTC: read(%04x) = %02x\n", port - dev->base_addr, ret); #endif - return(ret); + return ret; } - /* Handle a WRITE operation to one of our registers. */ static void mm67_write(uint16_t port, uint8_t val, void *priv) { - rtcdev_t *dev = (rtcdev_t *)priv; - int reg = port - dev->base_addr; - int i; + rtcdev_t *dev = (rtcdev_t *) priv; + int reg = port - dev->base_addr; -#if ISARTC_DEBUG - isartc_log("ISARTC: write(%04x, %02x)\n", port-dev->base_addr, val); +#if ISARTC_DEBUG + isartc_log("ISARTC: write(%04x, %02x)\n", port - dev->base_addr, val); #endif /* This chip is directly mapped on I/O. */ cycles -= ISA_CYCLES(4); - switch(reg) { - case MM67_ISTAT: /* intr status (RO) */ - break; + switch (reg) { + case MM67_ISTAT: /* intr status (RO) */ + break; - case MM67_ICTRL: /* intr control */ - dev->nvr.regs[MM67_ISTAT] = 0x00; - dev->nvr.regs[reg] = val; - break; + case MM67_ICTRL: /* intr control */ + dev->nvr.regs[MM67_ISTAT] = 0x00; + dev->nvr.regs[reg] = val; + break; - case MM67_RSTCTR: - if (val == 0xff) - mm67_reset(&dev->nvr); - break; + case MM67_RSTCTR: + if (val == 0xff) + mm67_reset(&dev->nvr); + break; - case MM67_RSTRAM: - if (val == 0xff) { - for (i = MM67_AL_MSEC; i <= MM67_AL_MON; i++) - dev->nvr.regs[i] = RTC_BCD(0); - dev->nvr.regs[MM67_DOW] = RTC_BCD(1); - dev->nvr.regs[MM67_DOM] = RTC_BCD(1); - dev->nvr.regs[MM67_MON] = RTC_BCD(1); - if (dev->year != -1) { - val = (dev->flags & FLAG_YEAR80) ? 0 : 80; - if (dev->flags & FLAG_YEARBCD) - dev->nvr.regs[dev->year] = RTC_BCD(val); - else - dev->nvr.regs[dev->year] = val; + case MM67_RSTRAM: + if (val == 0xff) { + for (uint8_t i = MM67_AL_MSEC; i <= MM67_AL_MON; i++) + dev->nvr.regs[i] = RTC_BCD(0); + dev->nvr.regs[MM67_DOW] = RTC_BCD(1); + dev->nvr.regs[MM67_DOM] = RTC_BCD(1); + dev->nvr.regs[MM67_MON] = RTC_BCD(1); + if (dev->year != -1) { + val = (dev->flags & FLAG_YEAR80) ? 0 : 80; + if (dev->flags & FLAG_YEARBCD) + dev->nvr.regs[dev->year] = RTC_BCD(val); + else + dev->nvr.regs[dev->year] = val; #ifdef MM67_CENTURY - dev->nvr.regs[MM67_CENTURY] = 19; + dev->nvr.regs[MM67_CENTURY] = 19; #endif - } - } - break; + } + } + break; - case MM67_STATUS: /* STATUS (RO) */ - break; + case MM67_STATUS: /* STATUS (RO) */ + break; - case MM67_GOCMD: -isartc_log("RTC: write gocmd=%02x\n", val); - break; + case MM67_GOCMD: + isartc_log("RTC: write gocmd=%02x\n", val); + break; - case MM67_STBYIRQ: -isartc_log("RTC: write stby=%02x\n", val); - break; + case MM67_STBYIRQ: + isartc_log("RTC: write stby=%02x\n", val); + break; - case MM67_TEST: -isartc_log("RTC: write test=%02x\n", val); - break; + case MM67_TEST: + isartc_log("RTC: write test=%02x\n", val); + break; - default: - dev->nvr.regs[reg] = val; - break; + case MM67_AL_MSEC: + dev->nvr.regs[reg] = val & 0xf0; + break; + + case MM67_AL_DOW: + dev->nvr.regs[reg] = val & 0x0f; + break; + + default: + dev->nvr.regs[reg] = val; + break; } } - /************************************************************************ - * * - * Generic code for all supported chips. * - * * + * * + * Generic code for all supported chips. * + * * ************************************************************************/ /* Initialize the device for use. */ @@ -498,314 +509,309 @@ static void * isartc_init(const device_t *info) { rtcdev_t *dev; - int is_at = IS_AT(machine); - is_at = is_at || !strcmp(machine_get_internal_name(), "xi8088"); + int is_at = IS_AT(machine); + is_at = is_at || !strcmp(machine_get_internal_name(), "xi8088"); /* Create a device instance. */ - dev = (rtcdev_t *)malloc(sizeof(rtcdev_t)); + dev = (rtcdev_t *) malloc(sizeof(rtcdev_t)); memset(dev, 0x00, sizeof(rtcdev_t)); - dev->name = info->name; - dev->board = info->local; - dev->irq = -1; - dev->year = -1; + dev->name = info->name; + dev->board = info->local; + dev->irq = -1; + dev->year = -1; dev->nvr.data = dev; dev->nvr.size = 16; /* Do per-board initialization. */ - switch(dev->board) { - case ISARTC_EV170: /* Everex EV-170 Magic I/O */ - dev->flags |= FLAG_YEAR80; - dev->base_addr = device_get_config_hex16("base"); - dev->base_addrsz = 32; - dev->irq = device_get_config_int("irq"); - dev->f_rd = mm67_read; - dev->f_wr = mm67_write; - dev->nvr.reset = mm67_reset; - dev->nvr.start = mm67_start; - dev->nvr.tick = mm67_tick; - dev->year = MM67_AL_DOM; /* year, NON STANDARD */ - break; + switch (dev->board) { + case ISARTC_EV170: /* Everex EV-170 Magic I/O */ + dev->flags |= FLAG_YEAR80; + dev->base_addr = device_get_config_hex16("base"); + dev->base_addrsz = 32; + dev->irq = device_get_config_int("irq"); + dev->f_rd = mm67_read; + dev->f_wr = mm67_write; + dev->nvr.reset = mm67_reset; + dev->nvr.start = mm67_start; + dev->nvr.tick = mm67_tick; + dev->year = MM67_AL_DOM; /* year, NON STANDARD */ + break; - case ISARTC_DTK: /* DTK PII-147 Hexa I/O Plus */ - dev->flags |= FLAG_YEARBCD; - dev->base_addr = device_get_config_hex16("base"); - dev->base_addrsz = 32; - dev->f_rd = mm67_read; - dev->f_wr = mm67_write; - dev->nvr.reset = mm67_reset; - dev->nvr.start = mm67_start; - dev->nvr.tick = mm67_tick; - dev->year = MM67_AL_HUNTEN; /* year, NON STANDARD */ - break; + case ISARTC_DTK: /* DTK PII-147 Hexa I/O Plus */ + dev->flags |= FLAG_YEARBCD; + dev->base_addr = device_get_config_hex16("base"); + dev->base_addrsz = 32; + dev->f_rd = mm67_read; + dev->f_wr = mm67_write; + dev->nvr.reset = mm67_reset; + dev->nvr.start = mm67_start; + dev->nvr.tick = mm67_tick; + dev->year = MM67_AL_HUNTEN; /* year, NON STANDARD */ + break; - case ISARTC_P5PAK: /* Paradise Systems 5PAK */ - case ISARTC_A6PAK: /* AST SixPakPlus */ - dev->flags |= FLAG_YEAR80; - dev->base_addr = 0x02c0; - dev->base_addrsz = 32; - dev->irq = device_get_config_int("irq"); - dev->f_rd = mm67_read; - dev->f_wr = mm67_write; - dev->nvr.reset = mm67_reset; - dev->nvr.start = mm67_start; - dev->nvr.tick = mm67_tick; - dev->year = MM67_AL_DOM; /* year, NON STANDARD */ - break; + case ISARTC_P5PAK: /* Paradise Systems 5PAK */ + case ISARTC_A6PAK: /* AST SixPakPlus */ + dev->flags |= FLAG_YEAR80; + dev->base_addr = 0x02c0; + dev->base_addrsz = 32; + dev->irq = device_get_config_int("irq"); + dev->f_rd = mm67_read; + dev->f_wr = mm67_write; + dev->nvr.reset = mm67_reset; + dev->nvr.start = mm67_start; + dev->nvr.tick = mm67_tick; + dev->year = MM67_AL_DOM; /* year, NON STANDARD */ + break; - default: - break; + case ISARTC_VENDEX: /* Vendex HeadStart Turbo 888-XT RTC */ + dev->flags |= FLAG_YEAR80 | FLAG_YEARBCD; + dev->base_addr = 0x0300; + dev->base_addrsz = 32; + dev->f_rd = mm67_read; + dev->f_wr = mm67_write; + dev->nvr.reset = mm67_reset; + dev->nvr.start = mm67_start; + dev->nvr.tick = mm67_tick; + dev->year = MM67_AL_DOM; /* year, NON STANDARD */ + break; + + default: + break; } /* Say hello! */ isartc_log("ISARTC: %s (I/O=%04XH", info->name, dev->base_addr); if (dev->irq != -1) - isartc_log(", IRQ%i", dev->irq); + isartc_log(", IRQ%i", dev->irq); isartc_log(")\n"); /* Set up an I/O port handler. */ io_sethandler(dev->base_addr, dev->base_addrsz, - dev->f_rd,NULL,NULL, dev->f_wr,NULL,NULL, dev); + dev->f_rd, NULL, NULL, dev->f_wr, NULL, NULL, dev); /* Hook into the NVR backend. */ - dev->nvr.fn = isartc_get_internal_name(isartc_type); + dev->nvr.fn = (char *) info->internal_name; dev->nvr.irq = dev->irq; if (!is_at) - nvr_init(&dev->nvr); + nvr_init(&dev->nvr); /* Let them know our device instance. */ - return((void *)dev); + return ((void *) dev); } - /* Remove the device from the system. */ static void isartc_close(void *priv) { - rtcdev_t *dev = (rtcdev_t *)priv; + rtcdev_t *dev = (rtcdev_t *) priv; io_removehandler(dev->base_addr, dev->base_addrsz, - dev->f_rd,NULL,NULL, dev->f_wr,NULL,NULL, dev); - - if (dev->nvr.fn != NULL) - free(dev->nvr.fn); + dev->f_rd, NULL, NULL, dev->f_wr, NULL, NULL, dev); free(dev); } - static const device_config_t ev170_config[] = { - { - "base", "Address", CONFIG_HEX16, "", 0x02C0, "", { 0 }, - { - { - "240H", 0x0240 - }, - { - "2C0H", 0x02c0 - }, - { - "" - } - }, - }, - { - "irq", "IRQ", CONFIG_SELECTION, "", -1, "", { 0 }, - { - { - "Disabled", -1 - }, - { - "IRQ2", 2 - }, - { - "IRQ5", 5 - }, - { - "IRQ7", 7 - }, - { - "" - } - }, - }, - { - "", "", -1 - } + // clang-format off + { + "base", "Address", CONFIG_HEX16, "", 0x02C0, "", { 0 }, + { + { "240H", 0x0240 }, + { "2C0H", 0x02c0 }, + { "" } + }, + }, + { + "irq", "IRQ", CONFIG_SELECTION, "", -1, "", { 0 }, + { + { "Disabled", -1 }, + { "IRQ2", 2 }, + { "IRQ5", 5 }, + { "IRQ7", 7 }, + { "" } + }, + }, + { "", "", -1 } + // clang-format on }; static const device_t ev170_device = { - "Everex EV-170 Magic I/O", - "ev170", - DEVICE_ISA, - ISARTC_EV170, - isartc_init, isartc_close, NULL, - { NULL }, NULL, NULL, - ev170_config + .name = "Everex EV-170 Magic I/O", + .internal_name = "ev170", + .flags = DEVICE_ISA, + .local = ISARTC_EV170, + .init = isartc_init, + .close = isartc_close, + .reset = NULL, + { .available = NULL }, + .speed_changed = NULL, + .force_redraw = NULL, + .config = ev170_config }; - static const device_config_t pii147_config[] = { - { - "base", "Address", CONFIG_HEX16, "", 0x0240, "", { 0 }, - { - { - "Clock 1", 0x0240 - }, - { - "Clock 2", 0x0340 - }, - { - "" - } - }, - }, - { - "", "", -1 - } + // clang-format off + { + "base", "Address", CONFIG_HEX16, "", 0x0240, "", { 0 }, + { + { "Clock 1", 0x0240 }, + { "Clock 2", 0x0340 }, + { "" } + }, + }, + { "", "", -1 } + // clang-format on }; static const device_t pii147_device = { - "DTK PII-147 Hexa I/O Plus", - "pii147", - DEVICE_ISA, - ISARTC_DTK, - isartc_init, isartc_close, NULL, - { NULL }, NULL, NULL, - pii147_config + .name = "DTK PII-147 Hexa I/O Plus", + .internal_name = "pii147", + .flags = DEVICE_ISA, + .local = ISARTC_DTK, + .init = isartc_init, + .close = isartc_close, + .reset = NULL, + { .available = NULL }, + .speed_changed = NULL, + .force_redraw = NULL, + .config = pii147_config }; - static const device_config_t p5pak_config[] = { - { - "irq", "IRQ", CONFIG_SELECTION, "", -1, "", { 0 }, - { - { - "Disabled", -1 - }, - { - "IRQ2", 2 - }, - { - "IRQ3", 3 - }, - { - "IRQ5", 5 - }, - { - "" - } - }, - }, - { - "", "", -1 - } + // clang-format off + { + "irq", "IRQ", CONFIG_SELECTION, "", -1, "", { 0 }, + { + { "Disabled", -1 }, + { "IRQ2", 2 }, + { "IRQ3", 3 }, + { "IRQ5", 5 }, + { "" } + }, + }, + { "", "", -1 } + // clang-format on }; static const device_t p5pak_device = { - "Paradise Systems 5-PAK", - "p5pak", - DEVICE_ISA, - ISARTC_P5PAK, - isartc_init, isartc_close, NULL, - { NULL }, NULL, NULL, - p5pak_config + .name = "Paradise Systems 5-PAK", + .internal_name = "p5pak", + .flags = DEVICE_ISA, + .local = ISARTC_P5PAK, + .init = isartc_init, + .close = isartc_close, + .reset = NULL, + { .available = NULL }, + .speed_changed = NULL, + .force_redraw = NULL, + .config = p5pak_config }; - static const device_config_t a6pak_config[] = { - { - "irq", "IRQ", CONFIG_SELECTION, "", -1, "", { 0 }, - { - { - "Disabled", -1 - }, - { - "IRQ2", 2 - }, - { - "IRQ3", 3 - }, - { - "IRQ5", 5 - }, - { - "" - } - }, - }, - { - "", "", -1 - } + // clang-format off + { + "irq", "IRQ", CONFIG_SELECTION, "", -1, "", { 0 }, + { + { "Disabled", -1 }, + { "IRQ2", 2 }, + { "IRQ3", 3 }, + { "IRQ5", 5 }, + { "" } + }, + }, + { "", "", -1 } + // clang-format on }; static const device_t a6pak_device = { - "AST SixPakPlus", - "a6pak", - DEVICE_ISA, - ISARTC_A6PAK, - isartc_init, isartc_close, NULL, - { NULL }, NULL, NULL, - a6pak_config + .name = "AST SixPakPlus", + .internal_name = "a6pak", + .flags = DEVICE_ISA, + .local = ISARTC_A6PAK, + .init = isartc_init, + .close = isartc_close, + .reset = NULL, + { .available = NULL }, + .speed_changed = NULL, + .force_redraw = NULL, + .config = a6pak_config }; +/* Onboard RTC devices */ +const device_t vendex_xt_rtc_onboard_device = { + .name = "National Semiconductor MM58167 (Vendex)", + .internal_name = "vendex_xt_rtc", + .flags = DEVICE_ISA, + .local = ISARTC_VENDEX, + .init = isartc_init, + .close = isartc_close, + .reset = NULL, + { .available = NULL }, + .speed_changed = NULL, + .force_redraw = NULL, + .config = NULL +}; static const device_t isartc_none_device = { - "None", - "none", - 0, 0, - NULL, NULL, NULL, - { NULL }, NULL, NULL, - NULL + .name = "None", + .internal_name = "none", + .flags = 0, + .local = 0, + .init = NULL, + .close = NULL, + .reset = NULL, + { .available = NULL }, + .speed_changed = NULL, + .force_redraw = NULL, + .config = NULL }; - static const struct { - const device_t *dev; + const device_t *dev; } boards[] = { - { &isartc_none_device }, - { &ev170_device }, - { &pii147_device }, - { &p5pak_device }, - { &a6pak_device }, - { NULL }, + // clang-format off + { &isartc_none_device }, + { &ev170_device }, + { &pii147_device }, + { &p5pak_device }, + { &a6pak_device }, + { NULL }, + // clang-format on }; - void isartc_reset(void) { - if (isartc_type == 0) return; + if (isartc_type == 0) + return; /* Add the device to the system. */ device_add(boards[isartc_type].dev); } - -char * +const char * isartc_get_internal_name(int board) { return device_get_internal_name(boards[board].dev); } - int isartc_get_from_internal_name(char *s) { int c = 0; while (boards[c].dev != NULL) { - if (! strcmp(boards[c].dev->internal_name, s)) - return(c); - c++; + if (!strcmp(boards[c].dev->internal_name, s)) + return c; + c++; } /* Not found. */ - return(0); + return 0; } - const device_t * isartc_get_device(int board) { - return(boards[board].dev); + return (boards[board].dev); } diff --git a/src/device/kbc_at.c b/src/device/kbc_at.c new file mode 100644 index 000000000..8045ea1df --- /dev/null +++ b/src/device/kbc_at.c @@ -0,0 +1,2372 @@ +/* + * 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. + * + * Intel 8042 (AT keyboard controller) emulation. + * + * + * + * Authors: Miran Grca, + * EngiNerd, + * + * Copyright 2023 Miran Grca. + * Copyright 2023 EngiNerd. + */ +#include +#include +#include +#include +#include +#define HAVE_STDARG_H +#include +#include <86box/86box.h> +#include "cpu.h" +#include "x86seg.h" +#include <86box/timer.h> +#include <86box/io.h> +#include <86box/pic.h> +#include <86box/pit.h> +#include <86box/plat_fallthrough.h> +#include <86box/plat_unused.h> +#include <86box/ppi.h> +#include <86box/mem.h> +#include <86box/device.h> +#include <86box/machine.h> +#include <86box/m_at_t3100e.h> +#include <86box/fdd.h> +#include <86box/fdc.h> +#include <86box/sound.h> +#include <86box/snd_speaker.h> +#include <86box/video.h> +#include <86box/keyboard.h> + +#define STAT_PARITY 0x80 +#define STAT_RTIMEOUT 0x40 +#define STAT_TTIMEOUT 0x20 +#define STAT_MFULL 0x20 +#define STAT_UNLOCKED 0x10 +#define STAT_CD 0x08 +#define STAT_SYSFLAG 0x04 +#define STAT_IFULL 0x02 +#define STAT_OFULL 0x01 + +#define CCB_UNUSED 0x80 +#define CCB_TRANSLATE 0x40 +#define CCB_PCMODE 0x20 +#define CCB_ENABLEKBD 0x10 +#define CCB_IGNORELOCK 0x08 +#define CCB_SYSTEM 0x04 +#define CCB_ENABLEMINT 0x02 +#define CCB_ENABLEKINT 0x01 + +#define CCB_MASK 0x68 +#define MODE_MASK 0x6c + +#define KBC_TYPE_ISA 0x00 /* AT ISA-based chips */ +#define KBC_TYPE_PS2_1 0x01 /* PS2 on PS/2, type 1 */ +#define KBC_TYPE_PS2_2 0x02 /* PS2 on PS/2, type 2 */ +#define KBC_TYPE_GREEN 0x03 /* PS2 green controller */ +#define KBC_TYPE_MASK 0x03 + +#define KBC_VEN_GENERIC 0x00 +#define KBC_VEN_IBM_PS1 0x04 +#define KBC_VEN_TOSHIBA 0x08 +#define KBC_VEN_OLIVETTI 0x0c +#define KBC_VEN_AMI 0x10 +#define KBC_VEN_TRIGEM_AMI 0x14 +#define KBC_VEN_QUADTEL 0x18 +#define KBC_VEN_PHOENIX 0x1c +#define KBC_VEN_ACER 0x20 +#define KBC_VEN_NCR 0x24 +#define KBC_VEN_ALI 0x28 +#define KBC_VEN_SIEMENS 0x2c +#define KBC_VEN_COMPAQ 0x30 +#define KBC_VEN_MASK 0x7c + +#define FLAG_CLOCK 0x01 +#define FLAG_CACHE 0x02 +#define FLAG_PS2 0x04 +#define FLAG_PCI 0x08 + +enum { + STATE_RESET = 0, /* KBC reset state, only accepts command AA. */ + STATE_KBC_DELAY_OUT, /* KBC is sending one single byte. */ + STATE_KBC_AMI_OUT, /* KBC waiting for OBF - needed for AMIKey commands that require clearing of the output byte. */ + STATE_MAIN_IBF, /* KBC checking if the input buffer is full. */ + STATE_MAIN_KBD, /* KBC checking if the keyboard has anything to send. */ + STATE_MAIN_AUX, /* KBC checking if the auxiliary has anything to send. */ + STATE_MAIN_BOTH, /* KBC checking if either device has anything to send. */ + STATE_KBC_OUT, /* KBC is sending multiple bytes. */ + STATE_KBC_PARAM, /* KBC wants a parameter. */ + STATE_SEND_KBD, /* KBC is sending command to the keyboard. */ + STATE_SCAN_KBD, /* KBC is waiting for the keyboard command response. */ + STATE_SEND_AUX, /* KBC is sending command to the auxiliary device. */ + STATE_SCAN_AUX /* KBC is waiting for the auxiliary command response. */ +}; + +typedef struct atkbc_t { + uint8_t state; + uint8_t command; + uint8_t command_phase; + uint8_t status; + uint8_t wantdata; + uint8_t ib; + uint8_t ob; + uint8_t sc_or; + uint8_t mem_addr; + uint8_t p1; + uint8_t p2; + uint8_t old_p2; + uint8_t misc_flags; + uint8_t ami_flags; + uint8_t key_ctrl_queue_start; + uint8_t key_ctrl_queue_end; + uint8_t val; + uint8_t channel; + uint8_t stat_hi; + uint8_t pending; + uint8_t irq_state; + uint8_t pad; + uint8_t pad0; + uint8_t pad1; + + uint8_t mem[0x100]; + + /* Internal FIFO for the purpose of commands with multi-byte output. */ + uint8_t key_ctrl_queue[64]; + + uint32_t flags; + + /* Main timer. */ + pc_timer_t send_delay_timer; + + /* P2 pulse callback timer. */ + pc_timer_t pulse_cb; + + /* Local copies of the pointers to both ports for easier swapping (AMI '5' MegaKey). */ + kbc_at_port_t *ports[2]; + + uint8_t (*write60_ven)(void *priv, uint8_t val); + uint8_t (*write64_ven)(void *priv, uint8_t val); +} atkbc_t; + +/* Keyboard controller ports. */ +kbc_at_port_t *kbc_at_ports[2] = { NULL, NULL }; + +static uint8_t kbc_ami_revision = '8'; +static uint8_t kbc_award_revision = 0x42; + +static void (*kbc_at_do_poll)(atkbc_t *dev); + +/* Non-translated to translated scan codes. */ +static const uint8_t nont_to_t[256] = { + 0xff, 0x43, 0x41, 0x3f, 0x3d, 0x3b, 0x3c, 0x58, + 0x64, 0x44, 0x42, 0x40, 0x3e, 0x0f, 0x29, 0x59, + 0x65, 0x38, 0x2a, 0x70, 0x1d, 0x10, 0x02, 0x5a, + 0x66, 0x71, 0x2c, 0x1f, 0x1e, 0x11, 0x03, 0x5b, + 0x67, 0x2e, 0x2d, 0x20, 0x12, 0x05, 0x04, 0x5c, + 0x68, 0x39, 0x2f, 0x21, 0x14, 0x13, 0x06, 0x5d, + 0x69, 0x31, 0x30, 0x23, 0x22, 0x15, 0x07, 0x5e, + 0x6a, 0x72, 0x32, 0x24, 0x16, 0x08, 0x09, 0x5f, + 0x6b, 0x33, 0x25, 0x17, 0x18, 0x0b, 0x0a, 0x60, + 0x6c, 0x34, 0x35, 0x26, 0x27, 0x19, 0x0c, 0x61, + 0x6d, 0x73, 0x28, 0x74, 0x1a, 0x0d, 0x62, 0x6e, + 0x3a, 0x36, 0x1c, 0x1b, 0x75, 0x2b, 0x63, 0x76, + 0x55, 0x56, 0x77, 0x78, 0x79, 0x7a, 0x0e, 0x7b, + 0x7c, 0x4f, 0x7d, 0x4b, 0x47, 0x7e, 0x7f, 0x6f, + 0x52, 0x53, 0x50, 0x4c, 0x4d, 0x48, 0x01, 0x45, + 0x57, 0x4e, 0x51, 0x4a, 0x37, 0x49, 0x46, 0x54, + 0x80, 0x81, 0x82, 0x41, 0x54, 0x85, 0x86, 0x87, + 0x88, 0x89, 0x8a, 0x8b, 0x8c, 0x8d, 0x8e, 0x8f, + 0x90, 0x91, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97, + 0x98, 0x99, 0x9a, 0x9b, 0x9c, 0x9d, 0x9e, 0x9f, + 0xa0, 0xa1, 0xa2, 0xa3, 0xa4, 0xa5, 0xa6, 0xa7, + 0xa8, 0xa9, 0xaa, 0xab, 0xac, 0xad, 0xae, 0xaf, + 0xb0, 0xb1, 0xb2, 0xb3, 0xb4, 0xb5, 0xb6, 0xb7, + 0xb8, 0xb9, 0xba, 0xbb, 0xbc, 0xbd, 0xbe, 0xbf, + 0xc0, 0xc1, 0xc2, 0xc3, 0xc4, 0xc5, 0xc6, 0xc7, + 0xc8, 0xc9, 0xca, 0xcb, 0xcc, 0xcd, 0xce, 0xcf, + 0xd0, 0xd1, 0xd2, 0xd3, 0xd4, 0xd5, 0xd6, 0xd7, + 0xd8, 0xd9, 0xda, 0xdb, 0xdc, 0xdd, 0xde, 0xdf, + 0xe0, 0xe1, 0xe2, 0xe3, 0xe4, 0xe5, 0xe6, 0xe7, + 0xe8, 0xe9, 0xea, 0xeb, 0xec, 0xed, 0xee, 0xef, + 0xf0, 0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7, + 0xf8, 0xf9, 0xfa, 0xfb, 0xfc, 0xfd, 0xfe, 0xff +}; + +#ifdef ENABLE_KBC_AT_LOG +int kbc_at_do_log = ENABLE_KBC_AT_LOG; + +static void +kbc_at_log(const char *fmt, ...) +{ + va_list ap; + + if (kbc_at_do_log) { + va_start(ap, fmt); + pclog_ex(fmt, ap); + va_end(ap); + } +} +#else +# define kbc_at_log(fmt, ...) +#endif + +static void +kbc_at_queue_reset(atkbc_t *dev) +{ + dev->key_ctrl_queue_start = dev->key_ctrl_queue_end = 0; + memset(dev->key_ctrl_queue, 0x00, sizeof(dev->key_ctrl_queue)); +} + +static void +kbc_at_queue_add(atkbc_t *dev, uint8_t val) +{ + kbc_at_log("ATkbc: dev->key_ctrl_queue[%02X] = %02X;\n", dev->key_ctrl_queue_end, val); + dev->key_ctrl_queue[dev->key_ctrl_queue_end] = val; + dev->key_ctrl_queue_end = (dev->key_ctrl_queue_end + 1) & 0x3f; + dev->state = STATE_KBC_OUT; +} + +static int +kbc_translate(atkbc_t *dev, uint8_t val) +{ + int xt_mode = (dev->mem[0x20] & 0x20) && !(dev->misc_flags & FLAG_PS2); + /* The IBM AT keyboard controller firmware does not apply translation in XT mode. */ + int translate = !xt_mode && ((dev->mem[0x20] & 0x40) || ((dev->flags & KBC_TYPE_MASK) == KBC_TYPE_PS2_2)); + uint8_t kbc_ven = dev->flags & KBC_VEN_MASK; + int ret = - 1; + + /* Allow for scan code translation. */ + if (translate && (val == 0xf0)) { + kbc_at_log("ATkbc: translate is on, F0 prefix detected\n"); + dev->sc_or = 0x80; + return ret; + } + + /* Skip break code if translated make code has bit 7 set. */ + if (translate && (dev->sc_or == 0x80) && (nont_to_t[val] & 0x80)) { + kbc_at_log("ATkbc: translate is on, skipping scan code: %02X (original: F0 %02X)\n", nont_to_t[val], val); + dev->sc_or = 0; + return ret; + } + + /* Test for T3100E 'Fn' key (Right Alt / Right Ctrl) */ + if ((dev != NULL) && (kbc_ven == KBC_VEN_TOSHIBA) && + (keyboard_recv(0x138) || keyboard_recv(0x11d))) switch (val) { + case 0x4f: + t3100e_notify_set(0x01); + break; /* End */ + case 0x50: + t3100e_notify_set(0x02); + break; /* Down */ + case 0x51: + t3100e_notify_set(0x03); + break; /* PgDn */ + case 0x52: + t3100e_notify_set(0x04); + break; /* Ins */ + case 0x53: + t3100e_notify_set(0x05); + break; /* Del */ + case 0x54: + t3100e_notify_set(0x06); + break; /* SysRQ */ + case 0x45: + t3100e_notify_set(0x07); + break; /* NumLock */ + case 0x46: + t3100e_notify_set(0x08); + break; /* ScrLock */ + case 0x47: + t3100e_notify_set(0x09); + break; /* Home */ + case 0x48: + t3100e_notify_set(0x0a); + break; /* Up */ + case 0x49: + t3100e_notify_set(0x0b); + break; /* PgUp */ + case 0x4a: + t3100e_notify_set(0x0c); + break; /* Keypad - */ + case 0x4b: + t3100e_notify_set(0x0d); + break; /* Left */ + case 0x4c: + t3100e_notify_set(0x0e); + break; /* KP 5 */ + case 0x4d: + t3100e_notify_set(0x0f); + break; /* Right */ + default: + break; + } + + kbc_at_log("ATkbc: translate is %s, ", translate ? "on" : "off"); +#ifdef ENABLE_KEYBOARD_AT_LOG + kbc_at_log("scan code: "); + if (translate) { + kbc_at_log("%02X (original: ", (nont_to_t[val] | dev->sc_or)); + if (dev->sc_or == 0x80) + kbc_at_log("F0 "); + kbc_at_log("%02X)\n", val); + } else + kbc_at_log("%02X\n", val); +#endif + + ret = translate ? (nont_to_t[val] | dev->sc_or) : val; + + if (dev->sc_or == 0x80) + dev->sc_or = 0; + + return ret; +} + +static void +kbc_send_to_ob(atkbc_t *dev, uint8_t val, uint8_t channel, uint8_t stat_hi) +{ + uint8_t kbc_ven = dev->flags & KBC_VEN_MASK; + int temp = (channel == 1) ? kbc_translate(dev, val) : ((int) val); + + if (temp == -1) + return; + + if ((kbc_ven == KBC_VEN_AMI) || (kbc_ven == KBC_VEN_TRIGEM_AMI) || + (dev->misc_flags & FLAG_PS2)) + stat_hi |= ((dev->p1 & 0x80) ? 0x10 : 0x00); + else + stat_hi |= 0x10; + + kbc_at_log("ATkbc: Sending %02X to the output buffer on channel %i...\n", temp, channel); + dev->status = (dev->status & ~0xf0) | STAT_OFULL | stat_hi; + + /* WARNING: On PS/2, all IRQ's are level-triggered, but the IBM PS/2 KBC firmware is explicitly + written to pulse its P2 IRQ bits, so they should be kept as as edge-triggered here. */ + if (dev->misc_flags & FLAG_PS2) { + if (channel >= 2) { + dev->status |= STAT_MFULL; + + if (dev->mem[0x20] & 0x02) + picint_common(1 << 12, 0, 1, NULL); + picint_common(1 << 1, 0, 0, NULL); + } else { + if (dev->mem[0x20] & 0x01) + picint_common(1 << 1, 0, 1, NULL); + picint_common(1 << 12, 0, 0, NULL); + } + } else if (dev->mem[0x20] & 0x01) + picintlevel(1 << 1, &dev->irq_state); /* AT KBC: IRQ 1 is level-triggered because it is tied to OBF. */ + + dev->ob = temp; +} + +static void +kbc_delay_to_ob(atkbc_t *dev, uint8_t val, uint8_t channel, uint8_t stat_hi) +{ + dev->val = val; + dev->channel = channel; + dev->stat_hi = stat_hi; + dev->pending = 1; + dev->state = STATE_KBC_DELAY_OUT; +} + +static void kbc_at_process_cmd(void *priv); + +static void +set_enable_kbd(atkbc_t *dev, uint8_t enable) +{ + dev->mem[0x20] &= 0xef; + dev->mem[0x20] |= (enable ? 0x00 : 0x10); +} + +static void +set_enable_aux(atkbc_t *dev, uint8_t enable) +{ + dev->mem[0x20] &= 0xdf; + dev->mem[0x20] |= (enable ? 0x00 : 0x20); +} + +static void +kbc_ibf_process(atkbc_t *dev) +{ + /* IBF set, process both commands and data. */ + dev->status &= ~STAT_IFULL; + dev->state = STATE_MAIN_IBF; + if (dev->status & STAT_CD) + kbc_at_process_cmd(dev); + else { + set_enable_kbd(dev, 1); + if ((dev->ports[0] != NULL) && (dev->ports[0]->priv != NULL)) { + dev->ports[0]->wantcmd = 1; + dev->ports[0]->dat = dev->ib; + dev->state = STATE_SEND_KBD; + } else + kbc_delay_to_ob(dev, 0xfe, 1, 0x40); + } +} + +static void +kbc_scan_kbd_at(atkbc_t *dev) +{ + if (!(dev->mem[0x20] & 0x10)) { + /* Both OBF and IBF clear and keyboard is enabled. */ + /* XT mode. */ + if (dev->mem[0x20] & 0x20) { + if ((dev->ports[0] != NULL) && (dev->ports[0]->out_new != -1)) { + kbc_send_to_ob(dev, dev->ports[0]->out_new, 1, 0x00); + dev->ports[0]->out_new = -1; + dev->state = STATE_MAIN_IBF; + } else if (dev->status & STAT_IFULL) + kbc_ibf_process(dev); + /* AT mode. */ + } else { +#if 0 + dev->t = dev->mem[0x28]; +#endif + if (dev->mem[0x2e] != 0x00) { +#if 0 + if (!(dev->t & 0x02)) + return; +#endif + dev->mem[0x2e] = 0x00; + } + dev->p2 &= 0xbf; + if ((dev->ports[0] != NULL) && (dev->ports[0]->out_new != -1)) { + /* In our case, we never have noise on the line, so we can simplify this. */ + /* Read data from the keyboard. */ + if (dev->mem[0x20] & 0x40) { + if ((dev->mem[0x20] & 0x08) || (dev->p1 & 0x80)) + kbc_send_to_ob(dev, dev->ports[0]->out_new, 1, 0x00); + dev->mem[0x2d] = (dev->ports[0]->out_new == 0xf0) ? 0x80 : 0x00; + } else + kbc_send_to_ob(dev, dev->ports[0]->out_new, 1, 0x00); + dev->ports[0]->out_new = -1; + dev->state = STATE_MAIN_IBF; + } + } + } +} + +static void +write_p2(atkbc_t *dev, uint8_t val); + +static void +kbc_at_poll_at(atkbc_t *dev) +{ + switch (dev->state) { + case STATE_RESET: + if (dev->status & STAT_IFULL) { + dev->status = ((dev->status & 0x0f) | 0x10) & ~STAT_IFULL; + if ((dev->status & STAT_CD) && (dev->ib == 0xaa)) + kbc_at_process_cmd(dev); + } + break; + case STATE_KBC_AMI_OUT: + if (dev->status & STAT_OFULL) + break; + fallthrough; + case STATE_MAIN_IBF: + default: +at_main_ibf: + if (dev->status & STAT_OFULL) { + /* OBF set, wait until it is cleared but still process commands. */ + if ((dev->status & STAT_IFULL) && (dev->status & STAT_CD)) { + dev->status &= ~STAT_IFULL; + kbc_at_process_cmd(dev); + } + } else if (dev->status & STAT_IFULL) + kbc_ibf_process(dev); + else if (!(dev->mem[0x20] & 0x10)) + dev->state = STATE_MAIN_KBD; + break; + case STATE_MAIN_KBD: + case STATE_MAIN_BOTH: + if (dev->status & STAT_IFULL) + kbc_ibf_process(dev); + else { + (void) kbc_scan_kbd_at(dev); + dev->state = STATE_MAIN_IBF; + } + break; + case STATE_KBC_DELAY_OUT: + /* Keyboard controller command want to output a single byte. */ + kbc_at_log("ATkbc: %02X coming from channel %i with high status %02X\n", dev->val, dev->channel, dev->stat_hi); + kbc_send_to_ob(dev, dev->val, dev->channel, dev->stat_hi); +#if 0 + dev->state = (dev->pending == 2) ? STATE_KBC_AMI_OUT : STATE_MAIN_IBF; +#endif + dev->state = STATE_MAIN_IBF; + dev->pending = 0; + goto at_main_ibf; + case STATE_KBC_OUT: + /* Keyboard controller command want to output multiple bytes. */ + if (dev->status & STAT_IFULL) { + /* Data from host aborts dumping. */ + dev->state = STATE_MAIN_IBF; + kbc_ibf_process(dev); + } + /* Do not continue dumping until OBF is clear. */ + if (!(dev->status & STAT_OFULL)) { + kbc_at_log("ATkbc: %02X coming from channel 0\n", dev->key_ctrl_queue[dev->key_ctrl_queue_start]); + kbc_send_to_ob(dev, dev->key_ctrl_queue[dev->key_ctrl_queue_start], 0, 0x00); + dev->key_ctrl_queue_start = (dev->key_ctrl_queue_start + 1) & 0x3f; + if (dev->key_ctrl_queue_start == dev->key_ctrl_queue_end) + dev->state = STATE_MAIN_IBF; + } + break; + case STATE_KBC_PARAM: + /* Keyboard controller command wants data, wait for said data. */ + if (dev->status & STAT_IFULL) { + /* Command written, abort current command. */ + if (dev->status & STAT_CD) + dev->state = STATE_MAIN_IBF; + + dev->status &= ~STAT_IFULL; + kbc_at_process_cmd(dev); + } + break; + case STATE_SEND_KBD: + if (!dev->ports[0]->wantcmd) + dev->state = STATE_SCAN_KBD; + break; + case STATE_SCAN_KBD: + kbc_scan_kbd_at(dev); + break; + } +} + +/* + Correct Procedure: + 1. Controller asks the device (keyboard or auxiliary device) for a byte. + 2. The device, unless it's in the reset or command states, sees if there's anything to give it, + and if yes, begins the transfer. + 3. The controller checks if there is a transfer, if yes, transfers the byte and sends it to the host, + otherwise, checks the next device, or if there is no device left to check, checks if IBF is full + and if yes, processes it. + */ +static int +kbc_scan_kbd_ps2(atkbc_t *dev) +{ + if ((dev->ports[0] != NULL) && (dev->ports[0]->out_new != -1)) { + kbc_at_log("ATkbc: %02X coming from channel 1\n", dev->ports[0]->out_new & 0xff); + kbc_send_to_ob(dev, dev->ports[0]->out_new, 1, 0x00); + dev->ports[0]->out_new = -1; + dev->state = STATE_MAIN_IBF; + return 1; + } + + return 0; +} + +static int +kbc_scan_aux_ps2(atkbc_t *dev) +{ + if ((dev->ports[1] != NULL) && (dev->ports[1]->out_new != -1)) { + kbc_at_log("ATkbc: %02X coming from channel 2\n", dev->ports[1]->out_new & 0xff); + kbc_send_to_ob(dev, dev->ports[1]->out_new, 2, 0x00); + dev->ports[1]->out_new = -1; + dev->state = STATE_MAIN_IBF; + return 1; + } + + return 0; +} + +static void +kbc_at_poll_ps2(atkbc_t *dev) +{ + switch (dev->state) { + case STATE_RESET: + if (dev->status & STAT_IFULL) { + dev->status = ((dev->status & 0x0f) | 0x10) & ~STAT_IFULL; + if ((dev->status & STAT_CD) && (dev->ib == 0xaa)) + kbc_at_process_cmd(dev); + } + break; + case STATE_KBC_AMI_OUT: + if (dev->status & STAT_OFULL) + break; + fallthrough; + case STATE_MAIN_IBF: + default: +ps2_main_ibf: + if (dev->status & STAT_IFULL) + kbc_ibf_process(dev); + else if (!(dev->status & STAT_OFULL)) { + if (dev->mem[0x20] & 0x20) { + if (!(dev->mem[0x20] & 0x10)) { + dev->p2 &= 0xbf; + dev->state = STATE_MAIN_KBD; + } + } else { + dev->p2 &= 0xf7; + if (dev->mem[0x20] & 0x10) + dev->state = STATE_MAIN_AUX; + else { + dev->p2 &= 0xbf; + dev->state = STATE_MAIN_BOTH; + } + } + } + break; + case STATE_MAIN_KBD: + if (dev->status & STAT_IFULL) + kbc_ibf_process(dev); + else { + (void) kbc_scan_kbd_ps2(dev); + dev->state = STATE_MAIN_IBF; + } + break; + case STATE_MAIN_AUX: + if (dev->status & STAT_IFULL) + kbc_ibf_process(dev); + else { + (void) kbc_scan_aux_ps2(dev); + dev->state = STATE_MAIN_IBF; + } + break; + case STATE_MAIN_BOTH: + if (kbc_scan_kbd_ps2(dev)) + dev->state = STATE_MAIN_IBF; + else + dev->state = STATE_MAIN_AUX; + break; + case STATE_KBC_DELAY_OUT: + /* Keyboard controller command want to output a single byte. */ + kbc_at_log("ATkbc: %02X coming from channel %i with high status %02X\n", dev->val, dev->channel, dev->stat_hi); + kbc_send_to_ob(dev, dev->val, dev->channel, dev->stat_hi); +#if 0 + dev->state = (dev->pending == 2) ? STATE_KBC_AMI_OUT : STATE_MAIN_IBF; +#endif + dev->state = STATE_MAIN_IBF; + dev->pending = 0; + goto ps2_main_ibf; + case STATE_KBC_OUT: + /* Keyboard controller command want to output multiple bytes. */ + if (dev->status & STAT_IFULL) { + /* Data from host aborts dumping. */ + dev->state = STATE_MAIN_IBF; + kbc_ibf_process(dev); + } + /* Do not continue dumping until OBF is clear. */ + if (!(dev->status & STAT_OFULL)) { + kbc_at_log("ATkbc: %02X coming from channel 0\n", dev->key_ctrl_queue[dev->key_ctrl_queue_start] & 0xff); + kbc_send_to_ob(dev, dev->key_ctrl_queue[dev->key_ctrl_queue_start], 0, 0x00); + dev->key_ctrl_queue_start = (dev->key_ctrl_queue_start + 1) & 0x3f; + if (dev->key_ctrl_queue_start == dev->key_ctrl_queue_end) + dev->state = STATE_MAIN_IBF; + } + break; + case STATE_KBC_PARAM: + /* Keyboard controller command wants data, wait for said data. */ + if (dev->status & STAT_IFULL) { + /* Command written, abort current command. */ + if (dev->status & STAT_CD) + dev->state = STATE_MAIN_IBF; + + dev->status &= ~STAT_IFULL; + kbc_at_process_cmd(dev); + } + break; + case STATE_SEND_KBD: + if (!dev->ports[0]->wantcmd) + dev->state = STATE_SCAN_KBD; + break; + case STATE_SCAN_KBD: + (void) kbc_scan_kbd_ps2(dev); + break; + case STATE_SEND_AUX: + if (!dev->ports[1]->wantcmd) + dev->state = STATE_SCAN_AUX; + break; + case STATE_SCAN_AUX: + (void) kbc_scan_aux_ps2(dev); + break; + } +} + +static void +kbc_at_poll(void *priv) +{ + atkbc_t *dev = (atkbc_t *) priv; + + timer_advance_u64(&dev->send_delay_timer, (100ULL * TIMER_USEC)); + + /* TODO: Implement the password security state. */ + kbc_at_do_poll(dev); + + if ((kbc_at_ports[0] != NULL) && (kbc_at_ports[0]->priv != NULL)) + kbc_at_ports[0]->poll(kbc_at_ports[0]->priv); + + if ((kbc_at_ports[1] != NULL) && (kbc_at_ports[1]->priv != NULL)) + kbc_at_ports[1]->poll(kbc_at_ports[1]->priv); +} + +static void +write_p2(atkbc_t *dev, uint8_t val) +{ + uint8_t old = dev->p2; + kbc_at_log("ATkbc: write P2: %02X (old: %02X)\n", val, dev->p2); + + uint8_t kbc_ven = dev->flags & KBC_VEN_MASK; + +#if 0 + /* PS/2: Handle IRQ's. */ + if (dev->misc_flags & FLAG_PS2) { + /* IRQ 12 */ + picint_common(1 << 12, 0, val & 0x20, NULL); + + /* IRQ 1 */ + picint_common(1 << 1, 0, val & 0x10, NULL); + } +#endif + + /* AT, PS/2: Handle A20. */ + if ((mem_a20_key ^ val) & 0x02) { /* A20 enable change */ + mem_a20_key = val & 0x02; + mem_a20_recalc(); + flushmmucache(); + } + + /* AT, PS/2: Handle reset. */ + /* 0 holds the CPU in the RESET state, 1 releases it. To simplify this, + we just do everything on release. */ + if ((old ^ val) & 0x01) { /*Reset*/ + if (!(val & 0x01)) { /* Pin 0 selected. */ + /* Pin 0 selected. */ + kbc_at_log("write_p2(): Pulse reset!\n"); + if (machines[machine].flags & MACHINE_COREBOOT) { + /* The SeaBIOS hard reset code attempts a KBC reset if ACPI RESET_REG + is not available. However, the KBC reset is normally a soft reset, so + SeaBIOS gets caught in a soft reset loop as it tries to hard reset the + machine. Hack around this by making the KBC reset a hard reset only on + coreboot machines. */ + pc_reset_hard(); + } else { + softresetx86(); /* Pulse reset! */ + cpu_set_edx(); + flushmmucache(); + if (kbc_ven == KBC_VEN_ALI) + smbase = 0x00030000; + /* Yes, this is a hack, but until someone gets ahold of the real PCD-2L + and can find out what they actually did to make it boot from FFFFF0 + correctly despite A20 being gated when the CPU is reset, this will + have to do. */ + else if (kbc_ven == KBC_VEN_SIEMENS) + is486 ? loadcs(0xf000) : loadcs_2386(0xf000); + } + } + } + + /* Do this here to avoid an infinite reset loop. */ + dev->p2 = val; +} + +static void +write_p2_fast_a20(atkbc_t *dev, uint8_t val) +{ + uint8_t old = dev->p2; + kbc_at_log("ATkbc: write P2 in fast A20 mode: %02X (old: %02X)\n", val, dev->p2); + + /* AT, PS/2: Handle A20. */ + if ((old ^ val) & 0x02) { /* A20 enable change */ + mem_a20_key = val & 0x02; + mem_a20_recalc(); + flushmmucache(); + } + + /* Do this here to avoid an infinite reset loop. */ + dev->p2 = val; +} + +static void +write_cmd(atkbc_t *dev, uint8_t val) +{ + kbc_at_log("ATkbc: write command byte: %02X (old: %02X)\n", val, dev->mem[0x20]); + + /* PS/2 type 2 keyboard controllers always force the XLAT bit to 0. */ + if ((dev->flags & KBC_TYPE_MASK) == KBC_TYPE_PS2_2) { + val &= ~CCB_TRANSLATE; + dev->mem[0x20] &= ~CCB_TRANSLATE; + } else if (!(dev->misc_flags & FLAG_PS2)) { + if (val & 0x10) + dev->mem[0x2e] = 0x01; + } + + kbc_at_log("ATkbc: keyboard interrupt is now %s\n", (val & 0x01) ? "enabled" : "disabled"); + + if (!(dev->misc_flags & FLAG_PS2)) { + /* Update P2 to mirror the IBF and OBF bits, if active. */ + write_p2(dev, (dev->p2 & 0x0f) | ((val & 0x03) << 4) | ((val & 0x20) ? 0xc0 : 0x00)); + } + + kbc_at_log("ATkbc: Command byte now: %02X (%02X)\n", dev->mem[0x20], val); + + dev->status = (dev->status & ~STAT_SYSFLAG) | (val & STAT_SYSFLAG); +} + +static void +pulse_output(atkbc_t *dev, uint8_t mask) +{ + if (mask != 0x0f) { + dev->old_p2 = dev->p2 & ~(0xf0 | mask); + kbc_at_log("ATkbc: pulse_output(): P2 now: %02X\n", dev->p2 & (0xf0 | mask)); + write_p2(dev, dev->p2 & (0xf0 | mask)); + timer_set_delay_u64(&dev->pulse_cb, 6ULL * TIMER_USEC); + } +} + +static void +pulse_poll(void *priv) +{ + atkbc_t *dev = (atkbc_t *) priv; + + kbc_at_log("ATkbc: pulse_poll(): P2 now: %02X\n", dev->p2 | dev->old_p2); + write_p2(dev, dev->p2 | dev->old_p2); +} + +static uint8_t +write64_generic(void *priv, uint8_t val) +{ + atkbc_t *dev = (atkbc_t *) priv; + uint8_t current_drive; + uint8_t fixed_bits; + uint8_t kbc_ven = 0x0; + kbc_ven = dev->flags & KBC_VEN_MASK; + + switch (val) { + case 0xa4: /* check if password installed */ + if (dev->misc_flags & FLAG_PS2) { + kbc_at_log("ATkbc: check if password installed\n"); + kbc_delay_to_ob(dev, 0xf1, 0, 0x00); + return 0; + } + break; + + case 0xa5: /* load security */ + kbc_at_log("ATkbc: load security\n"); + dev->wantdata = 1; + dev->state = STATE_KBC_PARAM; + return 0; + + case 0xa7: /* disable auxiliary port */ + if (dev->misc_flags & FLAG_PS2) { + kbc_at_log("ATkbc: disable auxiliary port\n"); + set_enable_aux(dev, 0); + return 0; + } + break; + + case 0xa8: /* Enable auxiliary port */ + if (dev->misc_flags & FLAG_PS2) { + kbc_at_log("ATkbc: enable auxiliary port\n"); + set_enable_aux(dev, 1); + return 0; + } + break; + + case 0xa9: /* Test auxiliary port */ + kbc_at_log("ATkbc: test auxiliary port\n"); + if (dev->misc_flags & FLAG_PS2) { + kbc_delay_to_ob(dev, 0x00, 0, 0x00); /* no error, this is testing the channel 2 interface */ + return 0; + } + break; + + /* TODO: Make this command do nothing on the Regional HT6542, + or else, Efflixi's Award OPTi 495 BIOS gets a stuck key + in Norton Commander 3.0. */ + case 0xaf: /* read keyboard version */ + kbc_at_log("ATkbc: read keyboard version\n"); + kbc_delay_to_ob(dev, kbc_award_revision, 0, 0x00); + return 0; + + /* + P1 bits: 76543210 + ----------------- + IBM PS/1: xxxxxxxx + IBM PS/2 MCA: xxxxx1xx + Intel AMI Pentium BIOS'es with AMI MegaKey KB-5 keyboard controller: x1x1xxxx + Acer: xxxxx0xx + Packard Bell PB450: xxxxx1xx + P6RP4: xx1xx1xx + Epson Action Tower 2600: xxxx01xx + TriGem Hawk: xxxx11xx + + Machine input based on current code: 11111111 + Everything non-Green: Pull down bit 7 if not PS/2 and keyboard is inhibited. + Pull down bit 6 if primary display is CGA. + Xi8088: Pull down bit 6 if primary display is MDA. + Acer: Pull down bit 6 if primary display is MDA. + Pull down bit 2 always (must be so to enable CMOS Setup). + IBM PS/1: Pull down bit 6 if current floppy drive is 3.5". + Epson Action Tower 2600: Pull down bit 3 always (for Epson logo). + NCR: Pull down bit 5 always (power-on default speed = high). + Pull down bit 3 if there is no FPU. + Pull down bits 1 and 0 always? + Compaq: Pull down bit 6 if Compaq dual-scan display is in use. + Pull down bit 5 if system board DIP switch is ON. + Pull down bit 4 if CPU speed selected is auto. + Pull down bit 3 if CPU speed selected is slow (4 MHz). + Pull down bit 2 if FPU is present. + Pull down bits 1 and 0 always? + + Bit 7: AT KBC only - keyboard inhibited (often physical lock): 0 = yes, 1 = no (also Compaq); + Bit 6: Mostly, display: 0 = CGA, 1 = MDA, inverted on Xi8088 and Acer KBC's; + Intel AMI MegaKey KB-5: Used for green features, SMM handler expects it to be set; + IBM PS/1 Model 2011: 0 = current FDD is 3.5", 1 = current FDD is 5.25"; + Compaq: 0 = Compaq dual-scan display, 1 = non-Compaq display. + Bit 5: Mostly, manufacturing jumper: 0 = installed (infinite loop at POST), 1 = not installed; + NCR: power-on default speed: 0 = high, 1 = low; + Compaq: System board DIP switch 5: 0 = ON, 1 = OFF. + Bit 4: (Which board?): RAM on motherboard: 0 = 512 kB, 1 = 256 kB; + NCR: RAM on motherboard: 0 = unsupported, 1 = 512 kB; + Intel AMI MegaKey KB-5: Must be 1; + IBM PS/1: Ignored; + Compaq: 0 = Auto speed selected, 1 = High speed selected. + Bit 3: TriGem AMIKey: most significant bit of 2-bit OEM ID; + NCR: Coprocessor detect (1 = yes, 0 = no); + Compaq: 0 = Slow (4 MHz), 1 = Fast (8 MHz); + Sometimes configured for clock switching; + Bit 2: TriGem AMIKey: least significant bit of 2-bit OEM ID; + Bit 3, 2: + 1, 1: TriGem logo; + 1, 0: Garbled logo; + 0, 1: Epson logo; + 0, 0: Generic AMI logo. + NCR: Unused; + IBM PS/2: Keyboard power: 0 = no power (fuse error), 1 = OK + (for some reason, www.win.tue.nl has this in reverse); + Compaq: FPU: 0 = 80287, 1 = none; + Sometimes configured for clock switching; + Bit 1: PS/2: Auxiliary device data in; + Compaq: Reserved; + NCR: High/auto speed. + Bit 0: PS/2: Keyboard device data in; + Compaq: Reserved; + NCR: DMA mode. + */ + case 0xc0: /* read P1 */ + kbc_at_log("ATkbc: read P1\n"); + fixed_bits = 4; + /* The SMM handlers of Intel AMI Pentium BIOS'es expect bit 6 to be set. */ + if ((kbc_ven == KBC_VEN_AMI) && ((dev->flags & KBC_TYPE_MASK) == KBC_TYPE_GREEN)) + fixed_bits |= 0x40; + if (kbc_ven == KBC_VEN_IBM_PS1) { + current_drive = fdc_get_current_drive(); + /* (B0 or F0) | (fdd_is_525(current_drive) on bit 6) */ + kbc_delay_to_ob(dev, dev->p1 | fixed_bits | (fdd_is_525(current_drive) ? 0x40 : 0x00), + 0, 0x00); + } else if (kbc_ven == KBC_VEN_NCR) { + /* switch settings + * bit 7: keyboard disable + * bit 6: display type (0 color, 1 mono) + * bit 5: power-on default speed (0 high, 1 low) + * bit 4: sense RAM size (0 unsupported, 1 512k on system board) + * bit 3: coprocessor detect + * bit 2: unused + * bit 1: high/auto speed + * bit 0: dma mode + */ + /* (B0 or F0) | 0x04 | (display on bit 6) | (fpu on bit 3) */ + kbc_delay_to_ob(dev, (dev->p1 | fixed_bits | (video_is_mda() ? 0x40 : 0x00) | (hasfpu ? 0x08 : 0x00)) & 0xdf, + 0, 0x00); + } else if (kbc_ven == KBC_VEN_TRIGEM_AMI) { + /* Bit 3, 2: + 1, 1: TriGem logo; + 1, 0: Garbled logo; + 0, 1: Epson logo; + 0, 0: Generic AMI logo. */ + if (dev->misc_flags & FLAG_PCI) + fixed_bits |= 8; + /* (B0 or F0) | (0x04 or 0x0c) */ + kbc_delay_to_ob(dev, dev->p1 | fixed_bits, 0, 0x00); + } 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); + dev->p1 = ((dev->p1 + 1) & 3) | (dev->p1 & 0xfc); + return 0; + + case 0xc1: /*Copy bits 0 to 3 of P1 to status bits 4 to 7*/ + if (dev->misc_flags & FLAG_PS2) { + kbc_at_log("ATkbc: copy bits 0 to 3 of P1 to status bits 4 to 7\n"); + dev->status &= 0x0f; + dev->status |= (dev->p1 << 4); + return 0; + } + break; + + case 0xc2: /*Copy bits 4 to 7 of P1 to status bits 4 to 7*/ + if (dev->misc_flags & FLAG_PS2) { + kbc_at_log("ATkbc: copy bits 4 to 7 of P1 to status bits 4 to 7\n"); + dev->status &= 0x0f; + dev->status |= (dev->p1 & 0xf0); + return 0; + } + break; + + case 0xd3: /* write auxiliary output buffer */ + if (dev->misc_flags & FLAG_PS2) { + kbc_at_log("ATkbc: write auxiliary output buffer\n"); + dev->wantdata = 1; + dev->state = STATE_KBC_PARAM; + return 0; + } + break; + + case 0xd4: /* write to auxiliary port */ + kbc_at_log("ATkbc: write to auxiliary port\n"); + dev->wantdata = 1; + dev->state = STATE_KBC_PARAM; + return 0; + + case 0xf0 ... 0xff: + kbc_at_log("ATkbc: pulse %01X\n", val & 0x0f); + pulse_output(dev, val & 0x0f); + return 0; + + default: + break; + } + + kbc_at_log("ATkbc: bad command %02X\n", val); + return 1; +} + +static uint8_t +write60_ami(void *priv, uint8_t val) +{ + atkbc_t *dev = (atkbc_t *) priv; + + switch (dev->command) { + /* 0x40 - 0x5F are aliases for 0x60-0x7F */ + case 0x40 ... 0x5f: + kbc_at_log("ATkbc: AMI - alias write to %02X\n", dev->command & 0x1f); + dev->mem[(dev->command & 0x1f) + 0x20] = val; + if (dev->command == 0x60) + write_cmd(dev, val); + return 0; + + case 0xaf: /* set extended controller RAM */ + kbc_at_log("ATkbc: AMI - set extended controller RAM\n"); + if (dev->command_phase == 1) { + dev->mem_addr = val; + dev->wantdata = 1; + dev->state = STATE_KBC_PARAM; + dev->command_phase = 2; + } else if (dev->command_phase == 2) { + dev->mem[dev->mem_addr] = val; + dev->command_phase = 0; + } + return 0; + + case 0xc1: + kbc_at_log("ATkbc: AMI MegaKey - write %02X to P1\n", val); + dev->p1 = val; + return 0; + + case 0xcb: /* set keyboard mode */ + kbc_at_log("ATkbc: AMI - set keyboard mode\n"); + dev->ami_flags = val; + dev->misc_flags &= ~FLAG_PS2; + if (val & 0x01) { + kbc_at_log("ATkbc: AMI: Emulate PS/2 keyboard\n"); + dev->misc_flags |= FLAG_PS2; + kbc_at_do_poll = kbc_at_poll_ps2; + } else { + kbc_at_log("ATkbc: AMI: Emulate AT keyboard\n"); + kbc_at_do_poll = kbc_at_poll_at; + } + return 0; + + default: + break; + } + + return 1; +} + +static uint8_t +write64_ami(void *priv, uint8_t val) +{ + atkbc_t *dev = (atkbc_t *) priv; + uint8_t kbc_ven = dev->flags & KBC_VEN_MASK; + + switch (val) { + case 0x00 ... 0x1f: + kbc_at_log("ATkbc: AMI - alias read from %08X\n", val); + kbc_delay_to_ob(dev, dev->mem[val + 0x20], 0, 0x00); + return 0; + + case 0x40 ... 0x5f: + kbc_at_log("ATkbc: AMI - alias write to %08X\n", dev->command); + dev->wantdata = 1; + dev->state = STATE_KBC_PARAM; + return 0; + + case 0xa0: /* copyright message */ + kbc_at_queue_add(dev, 0x28); + kbc_at_queue_add(dev, 0x00); + return 0; + + case 0xa1: /* get controller version */ + kbc_at_log("ATkbc: AMI - get controller version\n"); + kbc_delay_to_ob(dev, kbc_ami_revision, 0, 0x00); + return 0; + + case 0xa2: /* clear keyboard controller lines P22/P23 */ + if (!(dev->misc_flags & FLAG_PS2)) { + kbc_at_log("ATkbc: AMI - clear KBC lines P22 and P23\n"); + write_p2(dev, dev->p2 & 0xf3); + kbc_delay_to_ob(dev, 0x00, 0, 0x00); + return 0; + } + break; + + case 0xa3: /* set keyboard controller lines P22/P23 */ + if (!(dev->misc_flags & FLAG_PS2)) { + kbc_at_log("ATkbc: AMI - set KBC lines P22 and P23\n"); + write_p2(dev, dev->p2 | 0x0c); + kbc_delay_to_ob(dev, 0x00, 0, 0x00); + return 0; + } + break; + + case 0xa4: /* write clock = low */ + if (!(dev->misc_flags & FLAG_PS2)) { + kbc_at_log("ATkbc: AMI - write clock = low\n"); + dev->misc_flags &= ~FLAG_CLOCK; + return 0; + } + break; + + case 0xa5: /* write clock = high */ + if (!(dev->misc_flags & FLAG_PS2)) { + kbc_at_log("ATkbc: AMI - write clock = high\n"); + dev->misc_flags |= FLAG_CLOCK; + return 0; + } + + case 0xa6: /* read clock */ + if (!(dev->misc_flags & FLAG_PS2)) { + kbc_at_log("ATkbc: AMI - read clock\n"); + kbc_delay_to_ob(dev, (dev->misc_flags & FLAG_CLOCK) ? 0xff : 0x00, 0, 0x00); + return 0; + } + break; + + case 0xa7: /* write cache bad */ + if (!(dev->misc_flags & FLAG_PS2)) { + kbc_at_log("ATkbc: AMI - write cache bad\n"); + dev->misc_flags &= FLAG_CACHE; + return 0; + } + break; + + case 0xa8: /* write cache good */ + if (!(dev->misc_flags & FLAG_PS2)) { + kbc_at_log("ATkbc: AMI - write cache good\n"); + dev->misc_flags |= FLAG_CACHE; + return 0; + } + break; + + case 0xa9: /* read cache */ + if (!(dev->misc_flags & FLAG_PS2)) { + kbc_at_log("ATkbc: AMI - read cache\n"); + kbc_delay_to_ob(dev, (dev->misc_flags & FLAG_CACHE) ? 0xff : 0x00, 0, 0x00); + return 0; + } + break; + + case 0xaf: /* set extended controller RAM */ + if ((kbc_ven != KBC_VEN_SIEMENS) && (kbc_ven != KBC_VEN_ALI)) { + kbc_at_log("ATkbc: set extended controller RAM\n"); + dev->wantdata = 1; + dev->state = STATE_KBC_PARAM; + dev->command_phase = 1; + return 0; + } + break; + + case 0xb0 ... 0xb3: + /* set KBC lines P10-P13 (P1 bits 0-3) low */ + kbc_at_log("ATkbc: set KBC lines P10-P13 (P1 bits 0-3) low\n"); + if (!(dev->flags & DEVICE_PCI) || (val > 0xb1)) + dev->p1 &= ~(1 << (val & 0x03)); + kbc_delay_to_ob(dev, dev->ob, 0, 0x00); + dev->pending++; + return 0; + + /* TODO: The ICS SB486PV sends command B4 but expects to read *TWO* bytes. */ + case 0xb4: case 0xb5: + /* set KBC lines P22-P23 (P2 bits 2-3) low */ + kbc_at_log("ATkbc: set KBC lines P22-P23 (P2 bits 2-3) low\n"); + if (!(dev->flags & DEVICE_PCI)) + write_p2(dev, dev->p2 & ~(4 << (val & 0x01))); + kbc_delay_to_ob(dev, dev->ob, 0, 0x00); + dev->pending++; + return 0; + + case 0xb8 ... 0xbb: + /* set KBC lines P10-P13 (P1 bits 0-3) high */ + kbc_at_log("ATkbc: set KBC lines P10-P13 (P1 bits 0-3) high\n"); + if (!(dev->flags & DEVICE_PCI) || (val > 0xb9)) { + dev->p1 |= (1 << (val & 0x03)); + kbc_delay_to_ob(dev, dev->ob, 0, 0x00); + dev->pending++; + } + return 0; + + case 0xbc: case 0xbd: + /* set KBC lines P22-P23 (P2 bits 2-3) high */ + kbc_at_log("ATkbc: set KBC lines P22-P23 (P2 bits 2-3) high\n"); + if (!(dev->flags & DEVICE_PCI)) + write_p2(dev, dev->p2 | (4 << (val & 0x01))); + kbc_delay_to_ob(dev, dev->ob, 0, 0x00); + dev->pending++; + return 0; + + case 0xc1: /* write P1 */ + kbc_at_log("ATkbc: AMI MegaKey - write P1\n"); + dev->wantdata = 1; + dev->state = STATE_KBC_PARAM; + return 0; + + case 0xc4: + /* set KBC line P14 low */ + kbc_at_log("ATkbc: set KBC line P14 (P1 bit 4) low\n"); + dev->p1 &= 0xef; + kbc_delay_to_ob(dev, dev->ob, 0, 0x00); + dev->pending++; + return 0; + case 0xc5: + /* set KBC line P15 low */ + kbc_at_log("ATkbc: set KBC line P15 (P1 bit 5) low\n"); + dev->p1 &= 0xdf; + kbc_delay_to_ob(dev, dev->ob, 0, 0x00); + dev->pending++; + return 0; + + case 0xc8: + /* + * unblock KBC lines P22/P23 + * (allow command D1 to change bits 2/3 of P2) + */ + kbc_at_log("ATkbc: AMI - unblock KBC lines P22 and P23\n"); + dev->ami_flags &= 0xfb; + return 0; + + case 0xc9: + /* + * block KBC lines P22/P23 + * (disallow command D1 from changing bits 2/3 of the port) + */ + kbc_at_log("ATkbc: AMI - block KBC lines P22 and P23\n"); + dev->ami_flags |= 0x04; + return 0; + + case 0xcc: + /* set KBC line P14 high */ + kbc_at_log("ATkbc: set KBC line P14 (P1 bit 4) high\n"); + dev->p1 |= 0x10; + kbc_delay_to_ob(dev, dev->ob, 0, 0x00); + dev->pending++; + return 0; + case 0xcd: + /* set KBC line P15 high */ + kbc_at_log("ATkbc: set KBC line P15 (P1 bit 5) high\n"); + dev->p1 |= 0x20; + kbc_delay_to_ob(dev, dev->ob, 0, 0x00); + dev->pending++; + return 0; + + case 0xef: /* ??? - sent by AMI486 */ + kbc_at_log("ATkbc: ??? - sent by AMI486\n"); + return 0; + + default: + break; + } + + return write64_generic(dev, val); +} + +static uint8_t +write64_siemens(void *priv, uint8_t val) +{ + atkbc_t *dev = (atkbc_t *) priv; + + switch (val) { + case 0x92: /*Siemens Award - 92 sent by PCD-2L BIOS*/ + kbc_at_log("Siemens Award - 92 sent by PCD-2L BIOS\n"); + return 0; + + case 0x94: /*Siemens Award - 94 sent by PCD-2L BIOS*/ + kbc_at_log("Siemens Award - 94 sent by PCD-2L BIOS\n"); + return 0; + + case 0x9a: /*Siemens Award - 9A sent by PCD-2L BIOS*/ + kbc_at_log("Siemens Award - 9A sent by PCD-2L BIOS\n"); + return 0; + + case 0x9c: /*Siemens Award - 9C sent by PCD-2L BIOS*/ + kbc_at_log("Siemens Award - 9C sent by PCD-2L BIOS\n"); + return 0; + + case 0xa9: /*Siemens Award - A9 sent by PCD-2L BIOS*/ + kbc_at_log("Siemens Award - A9 sent by PCD-2L BIOS\n"); + return 0; + + default: + break; + } + + return write64_ami(dev, val); +} + +static uint8_t +write60_quadtel(void *priv, UNUSED(uint8_t val)) +{ + const atkbc_t *dev = (atkbc_t *) priv; + + switch (dev->command) { + case 0xcf: /*??? - sent by MegaPC BIOS*/ + kbc_at_log("ATkbc: ??? - sent by MegaPC BIOS\n"); + return 0; + + default: + break; + } + + return 1; +} + +static uint8_t +write64_olivetti(void *priv, uint8_t val) +{ + atkbc_t *dev = (atkbc_t *) priv; + + switch (val) { + case 0x80: /* Olivetti-specific command */ + /* + * bit 7: bus expansion board present (M300) / keyboard unlocked (M290) + * bits 4-6: ??? + * bit 3: fast ram check (if inactive keyboard works erratically) + * bit 2: keyboard fuse present + * bits 0-1: ??? + */ + kbc_delay_to_ob(dev, (0x0c | (is386 ? 0x00 : 0x80)) & 0xdf, 0, 0x00); + dev->p1 = ((dev->p1 + 1) & 3) | (dev->p1 & 0xfc); + return 0; + + default: + break; + } + + return write64_generic(dev, val); +} + +static uint8_t +write64_quadtel(void *priv, uint8_t val) +{ + atkbc_t *dev = (atkbc_t *) priv; + + switch (val) { + case 0xaf: + kbc_at_log("ATkbc: bad KBC command AF\n"); + return 1; + + case 0xcf: /*??? - sent by MegaPC BIOS*/ + kbc_at_log("ATkbc: ??? - sent by MegaPC BIOS\n"); + dev->wantdata = 1; + dev->state = STATE_KBC_PARAM; + return 0; + + default: + break; + } + + return write64_generic(dev, val); +} + +static uint8_t +write60_toshiba(void *priv, uint8_t val) +{ + const atkbc_t *dev = (atkbc_t *) priv; + + switch (dev->command) { + case 0xb6: /* T3100e - set color/mono switch */ + kbc_at_log("ATkbc: T3100e - set color/mono switch\n"); + t3100e_mono_set(val); + return 0; + + default: + break; + } + + return 1; +} + +static uint8_t +write64_toshiba(void *priv, uint8_t val) +{ + atkbc_t *dev = (atkbc_t *) priv; + + switch (val) { + case 0xaf: + kbc_at_log("ATkbc: bad KBC command AF\n"); + return 1; + + case 0xb0: /* T3100e: Turbo on */ + kbc_at_log("ATkbc: T3100e: Turbo on\n"); + t3100e_turbo_set(1); + return 0; + + case 0xb1: /* T3100e: Turbo off */ + kbc_at_log("ATkbc: T3100e: Turbo off\n"); + t3100e_turbo_set(0); + return 0; + + case 0xb2: /* T3100e: Select external display */ + kbc_at_log("ATkbc: T3100e: Select external display\n"); + t3100e_display_set(0x00); + return 0; + + case 0xb3: /* T3100e: Select internal display */ + kbc_at_log("ATkbc: T3100e: Select internal display\n"); + t3100e_display_set(0x01); + return 0; + + case 0xb4: /* T3100e: Get configuration / status */ + kbc_at_log("ATkbc: T3100e: Get configuration / status\n"); + kbc_delay_to_ob(dev, t3100e_config_get(), 0, 0x00); + return 0; + + case 0xb5: /* T3100e: Get colour / mono byte */ + kbc_at_log("ATkbc: T3100e: Get colour / mono byte\n"); + kbc_delay_to_ob(dev, t3100e_mono_get(), 0, 0x00); + return 0; + + case 0xb6: /* T3100e: Set colour / mono byte */ + kbc_at_log("ATkbc: T3100e: Set colour / mono byte\n"); + dev->wantdata = 1; + dev->state = STATE_KBC_PARAM; + return 0; + + /* TODO: Toshiba KBC mode switching. */ + case 0xb7: /* T3100e: Emulate PS/2 keyboard */ + case 0xb8: /* T3100e: Emulate AT keyboard */ + dev->misc_flags &= ~FLAG_PS2; + if (val == 0xb7) { + kbc_at_log("ATkbc: T3100e: Emulate PS/2 keyboard\n"); + dev->misc_flags |= FLAG_PS2; + kbc_at_do_poll = kbc_at_poll_ps2; + } else { + kbc_at_log("ATkbc: T3100e: Emulate AT keyboard\n"); + kbc_at_do_poll = kbc_at_poll_at; + } + return 0; + + case 0xbb: /* T3100e: Read 'Fn' key. + Return it for right Ctrl and right Alt; on the real + T3100e, these keystrokes could only be generated + using 'Fn'. */ + kbc_at_log("ATkbc: T3100e: Read 'Fn' key\n"); + if (keyboard_recv(0xb8) || /* Right Alt */ + keyboard_recv(0x9d)) /* Right Ctrl */ + kbc_delay_to_ob(dev, 0x04, 0, 0x00); + else + kbc_delay_to_ob(dev, 0x00, 0, 0x00); + return 0; + + case 0xbc: /* T3100e: Reset Fn+Key notification */ + kbc_at_log("ATkbc: T3100e: Reset Fn+Key notification\n"); + t3100e_notify_set(0x00); + return 0; + + case 0xc0: /* Read P1 */ + kbc_at_log("ATkbc: read P1\n"); + + /* The T3100e returns all bits set except bit 6 which + * is set by t3100e_mono_set() */ + dev->p1 = (t3100e_mono_get() & 1) ? 0xff : 0xbf; + kbc_delay_to_ob(dev, dev->p1, 0, 0x00); + return 0; + + default: + break; + } + + return write64_generic(dev, val); +} + +static void +kbc_at_process_cmd(void *priv) +{ + atkbc_t *dev = (atkbc_t *) priv; + int bad = 1; + uint8_t mask; + uint8_t kbc_ven = dev->flags & KBC_VEN_MASK; + uint8_t cmd_ac_conv[16] = { 0x0b, 2, 3, 4, 5, 6, 7, 8, 9, 0x0a, 0x1e, 0x30, 0x2e, 0x20, 0x12, 0x21 }; + + if (dev->status & STAT_CD) { + /* Controller command. */ + dev->wantdata = 0; + dev->state = STATE_MAIN_IBF; + + /* Clear the keyboard controller queue. */ + kbc_at_queue_reset(dev); + + switch (dev->ib) { + /* Read data from KBC memory. */ + case 0x20 ... 0x3f: + kbc_delay_to_ob(dev, dev->mem[dev->ib], 0, 0x00); + if (dev->ib == 0x20) + dev->pending++; + break; + + /* Write data to KBC memory. */ + case 0x60 ... 0x7f: + dev->wantdata = 1; + dev->state = STATE_KBC_PARAM; + break; + + case 0xaa: /* self-test */ + kbc_at_log("ATkbc: self-test\n"); + + if ((dev->flags & KBC_TYPE_MASK) >= KBC_TYPE_PS2_1) { + if (dev->state != STATE_RESET) { + kbc_at_log("ATkbc: self-test reinitialization\n"); + /* Yes, the firmware has an OR, but we need to make sure to keep any forcibly lowered bytes lowered. */ + /* TODO: Proper P1 implementation, with OR and AND flags in the machine table. */ + dev->p1 = dev->p1 & 0xff; + write_p2(dev, 0x4b); + picintc(0x1000); + picintc(0x0002); + } + + dev->status = (dev->status & 0x0f) | 0x60; + + dev->mem[0x20] = 0x30; + dev->mem[0x22] = 0x0b; + dev->mem[0x25] = 0x02; + dev->mem[0x27] = 0xf8; + dev->mem[0x28] = 0xce; + dev->mem[0x29] = 0x0b; + dev->mem[0x30] = 0x0b; + } else { + if (dev->state != STATE_RESET) { + kbc_at_log("ATkbc: self-test reinitialization\n"); + /* Yes, the firmware has an OR, but we need to make sure to keep any forcibly lowered bytes lowered. */ + /* TODO: Proper P1 implementation, with OR and AND flags in the machine table. */ + dev->p1 = dev->p1 & 0xff; + write_p2(dev, 0xcf); + picintclevel(0x0002, &dev->irq_state); + dev->irq_state = 0; + } + + dev->status = (dev->status & 0x0f) | 0x60; + + dev->mem[0x20] = 0x10; + dev->mem[0x22] = 0x06; + dev->mem[0x25] = 0x01; + dev->mem[0x27] = 0xfb; + dev->mem[0x28] = 0xe0; + dev->mem[0x29] = 0x06; + } + + dev->mem[0x21] = 0x01; + dev->mem[0x2a] = 0x10; + dev->mem[0x2b] = 0x20; + dev->mem[0x2c] = 0x15; + + if (dev->ports[0] != NULL) + dev->ports[0]->out_new = -1; + if (dev->ports[1] != NULL) + dev->ports[1]->out_new = -1; + kbc_at_queue_reset(dev); + + kbc_at_queue_add(dev, 0x55); + break; + + case 0xab: /* interface test */ + kbc_at_log("ATkbc: interface test\n"); + kbc_delay_to_ob(dev, 0x00, 0, 0x00); /*no error*/ + break; + + case 0xac: /* diagnostic dump */ + if (dev->misc_flags & FLAG_PS2) { + kbc_at_log("ATkbc: diagnostic dump\n"); + dev->mem[0x30] = (dev->p1 & 0xf0) | 0x80; + dev->mem[0x31] = dev->p2; + dev->mem[0x32] = 0x00; /* T0 and T1. */ + dev->mem[0x33] = 0x00; /* PSW - Program Status Word - always return 0x00 because we do not emulate this byte. */ + /* 20 bytes in high nibble in set 1, low nibble in set 1, set 1 space format = 60 bytes. */ + for (uint8_t i = 0; i < 20; i++) { + kbc_at_queue_add(dev, cmd_ac_conv[dev->mem[i + 0x20] >> 4]); + kbc_at_queue_add(dev, cmd_ac_conv[dev->mem[i + 0x20] & 0x0f]); + kbc_at_queue_add(dev, 0x39); + } + } + break; + + case 0xad: /* disable keyboard */ + kbc_at_log("ATkbc: disable keyboard\n"); + set_enable_kbd(dev, 0); + break; + + case 0xae: /* enable keyboard */ + kbc_at_log("ATkbc: enable keyboard\n"); + set_enable_kbd(dev, 1); + break; + + case 0xc7: /* set port1 bits */ + kbc_at_log("ATkbc: Phoenix - set port1 bits\n"); + dev->wantdata = 1; + dev->state = STATE_KBC_PARAM; + break; + + case 0xca: /* read keyboard mode */ + kbc_at_log("ATkbc: AMI - read keyboard mode\n"); + kbc_delay_to_ob(dev, dev->ami_flags, 0, 0x00); + break; + + case 0xcb: /* set keyboard mode */ + kbc_at_log("ATkbc: AMI - set keyboard mode\n"); + dev->wantdata = 1; + dev->state = STATE_KBC_PARAM; + break; + + case 0xd0: /* read P2 */ + kbc_at_log("ATkbc: read P2\n"); + mask = 0xff; + if ((kbc_ven != KBC_VEN_OLIVETTI) && !(dev->misc_flags & FLAG_PS2) && (dev->mem[0x20] & 0x10)) + mask &= 0xbf; + kbc_delay_to_ob(dev, ((dev->p2 & 0xfd) | mem_a20_key) & mask, 0, 0x00); + break; + + case 0xd1: /* write P2 */ + kbc_at_log("ATkbc: write P2\n"); + dev->wantdata = 1; + dev->state = STATE_KBC_PARAM; + break; + + case 0xd2: /* write keyboard output buffer */ + kbc_at_log("ATkbc: write keyboard output buffer\n"); + dev->wantdata = 1; + dev->state = STATE_KBC_PARAM; + break; + + case 0xdd: /* disable A20 address line */ + case 0xdf: /* enable A20 address line */ + kbc_at_log("ATkbc: %sable A20\n", (dev->ib == 0xdd) ? "dis" : "en"); + write_p2_fast_a20(dev, (dev->p2 & 0xfd) | (dev->ib & 0x02)); + break; + + case 0xe0: /* read test inputs */ + kbc_at_log("ATkbc: read test inputs\n"); + kbc_delay_to_ob(dev, 0x00, 0, 0x00); + break; + + default: + /* + * Unrecognized controller command. + * + * If we have a vendor-specific handler, run + * that. Otherwise, or if that handler fails, + * log a bad command. + */ + if (dev->write64_ven) + bad = dev->write64_ven(dev, dev->ib); + + kbc_at_log(bad ? "ATkbc: bad controller command %02X\n" : "", dev->ib); + } + + /* If the command needs data, remember the command. */ + if (dev->wantdata) + dev->command = dev->ib; + } else if (dev->wantdata) { + /* Write data to controller. */ + dev->wantdata = 0; + dev->state = STATE_MAIN_IBF; + + switch (dev->command) { + case 0x60 ... 0x7f: + dev->mem[(dev->command & 0x1f) + 0x20] = dev->ib; + if (dev->command == 0x60) + write_cmd(dev, dev->ib); + break; + + case 0xa5: /* load security */ + if (dev->misc_flags & FLAG_PS2) { + kbc_at_log("ATkbc: load security (%02X)\n", dev->ib); + + if (dev->ib != 0x00) { + dev->wantdata = 1; + dev->state = STATE_KBC_PARAM; + } + } + break; + + case 0xc7: /* set port1 bits */ + kbc_at_log("ATkbc: Phoenix - set port1 bits\n"); + dev->p1 |= dev->ib; + break; + + case 0xd1: /* write P2 */ + kbc_at_log("ATkbc: write P2\n"); + /* Bit 2 of AMI flags is P22-P23 blocked (1 = yes, 0 = no), + discovered by reverse-engineering the AOpen Vi15G BIOS. */ + if (dev->ami_flags & 0x04) { + /* If keyboard controller lines P22-P23 are blocked, + we force them to remain unchanged. */ + dev->ib &= ~0x0c; + dev->ib |= (dev->p2 & 0x0c); + } + write_p2(dev, dev->ib | 0x01); + break; + + case 0xd2: /* write to keyboard output buffer */ + kbc_at_log("ATkbc: write to keyboard output buffer\n"); + kbc_delay_to_ob(dev, dev->ib, 0, 0x00); + break; + + case 0xd3: /* write to auxiliary output buffer */ + kbc_at_log("ATkbc: write to auxiliary output buffer\n"); + kbc_delay_to_ob(dev, dev->ib, 2, 0x00); + break; + + case 0xd4: /* write to auxiliary port */ + kbc_at_log("ATkbc: write to auxiliary port (%02X)\n", dev->ib); + + if (dev->ib == 0xbb) + break; + + if (dev->misc_flags & FLAG_PS2) { + set_enable_aux(dev, 1); + if ((dev->ports[1] != NULL) && (dev->ports[1]->priv != NULL)) { + dev->ports[1]->wantcmd = 1; + dev->ports[1]->dat = dev->ib; + dev->state = STATE_SEND_AUX; + } else + kbc_delay_to_ob(dev, 0xfe, 2, 0x40); + } + break; + + default: + /* + * Run the vendor-specific handler + * if we have one. Otherwise, or if + * it returns an error, log a bad + * controller command. + */ + if (dev->write60_ven) + bad = dev->write60_ven(dev, dev->ib); + + if (bad) { + kbc_at_log("ATkbc: bad controller command %02x data %02x\n", dev->command, dev->ib); + } + } + } +} + +static void +kbc_at_write(uint16_t port, uint8_t val, void *priv) +{ + atkbc_t *dev = (atkbc_t *) priv; + uint8_t kbc_ven = dev->flags & KBC_VEN_MASK; + uint8_t fast_a20 = (kbc_ven != KBC_VEN_SIEMENS); + + kbc_at_log("ATkbc: [%04X:%08X] write(%04X) = %02X\n", CS, cpu_state.pc, port, val); + + switch (port) { + case 0x60: + dev->status &= ~STAT_CD; + if (fast_a20 && dev->wantdata && (dev->command == 0xd1)) { + kbc_at_log("ATkbc: write P2\n"); + +#if 0 + /* Fast A20 - ignore all other bits. */ + val = (val & 0x02) | (dev->p2 & 0xfd); + + /* Bit 2 of AMI flags is P22-P23 blocked (1 = yes, 0 = no), + discovered by reverse-engineering the AOpeN Vi15G BIOS. */ + if (dev->ami_flags & 0x04) { + /* If keyboard controller lines P22-P23 are blocked, + we force them to remain unchanged. */ + val &= ~0x0c; + val |= (dev->p2 & 0x0c); + } + + write_p2_fast_a20(dev, val | 0x01); +#else + /* Fast A20 - ignore all other bits. */ + write_p2_fast_a20(dev, (dev->p2 & 0xfd) | (val & 0x02)); +#endif + + dev->wantdata = 0; + dev->state = STATE_MAIN_IBF; + return; + } + break; + + case 0x64: + dev->status |= STAT_CD; + if (fast_a20 && (val == 0xd1)) { + kbc_at_log("ATkbc: write P2\n"); + dev->wantdata = 1; + dev->state = STATE_KBC_PARAM; + dev->command = 0xd1; + return; + } + break; + + default: + break; + } + + dev->ib = val; + dev->status |= STAT_IFULL; +} + +static uint8_t +kbc_at_read(uint16_t port, void *priv) +{ + atkbc_t *dev = (atkbc_t *) priv; + uint8_t ret = 0xff; + + if ((dev->flags & KBC_TYPE_MASK) >= KBC_TYPE_PS2_1) + cycles -= ISA_CYCLES(8); + + switch (port) { + case 0x60: + ret = dev->ob; + dev->status &= ~STAT_OFULL; + /* TODO: IRQ is only tied to OBF on the AT KBC, on the PS/2 KBC, it is controlled by a P2 bit. + This also means that in AT mode, the IRQ is level-triggered. */ + if (!(dev->misc_flags & FLAG_PS2)) + picintclevel(1 << 1, &dev->irq_state); + break; + + case 0x64: + ret = dev->status; + break; + + default: + kbc_at_log("ATkbc: read(%04x) invalid!\n",port); + break; + } + + kbc_at_log("ATkbc: [%04X:%08X] read (%04X) = %02X\n", CS, cpu_state.pc, port, ret); + + return ret; +} + +static void +kbc_at_reset(void *priv) +{ + atkbc_t *dev = (atkbc_t *) priv; + uint8_t kbc_ven = dev->flags & KBC_VEN_MASK; + + dev->status = STAT_UNLOCKED; + dev->mem[0x20] = 0x01; + dev->mem[0x20] |= CCB_TRANSLATE; + dev->command_phase = 0; + + /* Set up the correct Video Type bits. */ + if (!is286 || (kbc_ven == KBC_VEN_ACER)) + dev->p1 = video_is_mda() ? 0xb0 : 0xf0; + else + dev->p1 = video_is_mda() ? 0xf0 : 0xb0; + kbc_at_log("ATkbc: P1 = %02x\n", dev->p1); + + /* Disabled both the keyboard and auxiliary ports. */ + set_enable_kbd(dev, 0); + set_enable_aux(dev, 0); + + kbc_at_queue_reset(dev); + + dev->sc_or = 0; + + dev->ami_flags = ((dev->flags & KBC_TYPE_MASK) >= KBC_TYPE_PS2_1) ? 0x01 : 0x00; + dev->misc_flags &= FLAG_PCI; + + if ((dev->flags & KBC_TYPE_MASK) >= KBC_TYPE_PS2_1) { + dev->misc_flags |= FLAG_PS2; + kbc_at_do_poll = kbc_at_poll_ps2; + picintc(0x1000); + picintc(0x0002); + } else { + kbc_at_do_poll = kbc_at_poll_at; + picintclevel(0x0002, &dev->irq_state); + dev->irq_state = 0; + } + + dev->misc_flags |= FLAG_CACHE; + + dev->p2 = 0xcd; + if ((dev->flags & KBC_TYPE_MASK) >= KBC_TYPE_PS2_1) { + write_p2(dev, 0x4b); + } else { + /* The real thing writes CF and then AND's it with BF. */ + write_p2(dev, 0x8f); + } + + /* Stage 1. */ + dev->status = (dev->status & 0x0f) | (dev->p1 & 0xf0); +} + +static void +kbc_at_close(void *priv) +{ + atkbc_t *dev = (atkbc_t *) priv; + int max_ports = ((dev->flags & KBC_TYPE_MASK) >= KBC_TYPE_PS2_1) ? 2 : 1; + + /* Stop timers. */ + timer_disable(&dev->send_delay_timer); + + for (int i = 0; i < max_ports; i++) { + if (kbc_at_ports[i] != NULL) { + free(kbc_at_ports[i]); + kbc_at_ports[i] = NULL; + } + } + + free(dev); +} + +static void * +kbc_at_init(const device_t *info) +{ + atkbc_t *dev; + int max_ports; + + dev = (atkbc_t *) malloc(sizeof(atkbc_t)); + memset(dev, 0x00, sizeof(atkbc_t)); + + dev->flags = info->local; + + video_reset(gfxcard[0]); + kbc_at_reset(dev); + + if (info->flags & DEVICE_PCI) + dev->misc_flags |= FLAG_PCI; + + io_sethandler(0x0060, 1, kbc_at_read, NULL, NULL, kbc_at_write, NULL, NULL, dev); + io_sethandler(0x0064, 1, kbc_at_read, NULL, NULL, kbc_at_write, NULL, NULL, dev); + + timer_add(&dev->send_delay_timer, kbc_at_poll, dev, 1); + timer_add(&dev->pulse_cb, pulse_poll, dev, 0); + + dev->write60_ven = NULL; + dev->write64_ven = NULL; + + kbc_ami_revision = '8'; + kbc_award_revision = 0x42; + + switch (dev->flags & KBC_VEN_MASK) { + case KBC_VEN_SIEMENS: + kbc_ami_revision = '8'; + kbc_award_revision = 0x42; + dev->write60_ven = write60_ami; + dev->write64_ven = write64_siemens; + break; + + case KBC_VEN_ACER: + case KBC_VEN_GENERIC: + case KBC_VEN_NCR: + case KBC_VEN_IBM_PS1: + case KBC_VEN_COMPAQ: + dev->write64_ven = write64_generic; + break; + + case KBC_VEN_OLIVETTI: + dev->write64_ven = write64_olivetti; + break; + + case KBC_VEN_ALI: + kbc_ami_revision = 'F'; + kbc_award_revision = 0x43; + dev->write60_ven = write60_ami; + dev->write64_ven = write64_ami; + break; + + case KBC_VEN_TRIGEM_AMI: + kbc_ami_revision = 'Z'; + dev->write60_ven = write60_ami; + dev->write64_ven = write64_ami; + break; + + case KBC_VEN_AMI: + if ((dev->flags & KBC_TYPE_MASK) == KBC_TYPE_GREEN) + kbc_ami_revision = '5'; + else if ((dev->flags & KBC_TYPE_MASK) >= KBC_TYPE_PS2_1) { + if (cpu_64bitbus) + kbc_ami_revision = 'R'; + else if (is486) + kbc_ami_revision = 'P'; + else + kbc_ami_revision = 'H'; + } else if (is386 && !is486) { + if (cpu_16bitbus) + kbc_ami_revision = 'D'; + else + kbc_ami_revision = 'B'; + } else if (!is386) + kbc_ami_revision = '8'; + else + kbc_ami_revision = 'F'; + + dev->write60_ven = write60_ami; + dev->write64_ven = write64_ami; + break; + + case KBC_VEN_QUADTEL: + dev->write60_ven = write60_quadtel; + dev->write64_ven = write64_quadtel; + break; + + case KBC_VEN_TOSHIBA: + dev->write60_ven = write60_toshiba; + dev->write64_ven = write64_toshiba; + break; + + default: + break; + } + + max_ports = ((dev->flags & KBC_TYPE_MASK) >= KBC_TYPE_PS2_1) ? 2 : 1; + + for (int i = 0; i < max_ports; i++) { + kbc_at_ports[i] = (kbc_at_port_t *) malloc(sizeof(kbc_at_port_t)); + memset(kbc_at_ports[i], 0x00, sizeof(kbc_at_port_t)); + kbc_at_ports[i]->out_new = -1; + } + + dev->ports[0] = kbc_at_ports[0]; + dev->ports[1] = kbc_at_ports[1]; + + /* The actual keyboard. */ + device_add(&keyboard_at_generic_device); + + return dev; +} + +const device_t keyboard_at_device = { + .name = "PC/AT Keyboard", + .internal_name = "keyboard_at", + .flags = DEVICE_KBC, + .local = KBC_TYPE_ISA | KBC_VEN_GENERIC, + .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_at_siemens_device = { + .name = "PC/AT Keyboard", + .internal_name = "keyboard_at", + .flags = DEVICE_KBC, + .local = KBC_TYPE_ISA | KBC_VEN_SIEMENS, + .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_at_ami_device = { + .name = "PC/AT Keyboard (AMI)", + .internal_name = "keyboard_at_ami", + .flags = DEVICE_KBC, + .local = KBC_TYPE_ISA | KBC_VEN_AMI, + .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_at_tg_ami_device = { + .name = "PC/AT Keyboard (TriGem AMI)", + .internal_name = "keyboard_at_tg_ami", + .flags = DEVICE_KBC, + .local = KBC_TYPE_ISA | KBC_VEN_TRIGEM_AMI, + .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_at_toshiba_device = { + .name = "PC/AT Keyboard (Toshiba)", + .internal_name = "keyboard_at_toshiba", + .flags = DEVICE_KBC, + .local = KBC_TYPE_ISA | KBC_VEN_TOSHIBA, + .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_at_olivetti_device = { + .name = "PC/AT Keyboard (Olivetti)", + .internal_name = "keyboard_at_olivetti", + .flags = DEVICE_KBC, + .local = KBC_TYPE_ISA | KBC_VEN_OLIVETTI, + .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_at_ncr_device = { + .name = "PC/AT Keyboard (NCR)", + .internal_name = "keyboard_at_ncr", + .flags = DEVICE_KBC, + .local = KBC_TYPE_ISA | KBC_VEN_NCR, + .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_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", + .flags = DEVICE_KBC, + .local = KBC_TYPE_PS2_1 | KBC_VEN_GENERIC, + .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_ps1_device = { + .name = "PS/2 Keyboard (IBM PS/1)", + .internal_name = "keyboard_ps2_ps1", + .flags = DEVICE_KBC, + .local = KBC_TYPE_PS2_1 | KBC_VEN_IBM_PS1, + .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_ps1_pci_device = { + .name = "PS/2 Keyboard (IBM PS/1)", + .internal_name = "keyboard_ps2_ps1_pci", + .flags = DEVICE_KBC | DEVICE_PCI, + .local = KBC_TYPE_PS2_1 | KBC_VEN_IBM_PS1, + .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_xi8088_device = { + .name = "PS/2 Keyboard (Xi8088)", + .internal_name = "keyboard_ps2_xi8088", + .flags = DEVICE_KBC, + .local = KBC_TYPE_PS2_1 | KBC_VEN_GENERIC, + .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_ami_device = { + .name = "PS/2 Keyboard (AMI)", + .internal_name = "keyboard_ps2_ami", + .flags = DEVICE_KBC, + .local = KBC_TYPE_PS2_1 | KBC_VEN_AMI, + .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_tg_ami_device = { + .name = "PS/2 Keyboard (TriGem AMI)", + .internal_name = "keyboard_ps2_tg_ami", + .flags = DEVICE_KBC, + .local = KBC_TYPE_PS2_1 | KBC_VEN_TRIGEM_AMI, + .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_mca_2_device = { + .name = "PS/2 Keyboard", + .internal_name = "keyboard_ps2_mca_2", + .flags = DEVICE_KBC, + .local = KBC_TYPE_PS2_2 | KBC_VEN_GENERIC, + .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_quadtel_device = { + .name = "PS/2 Keyboard (Quadtel/MegaPC)", + .internal_name = "keyboard_ps2_quadtel", + .flags = DEVICE_KBC, + .local = KBC_TYPE_PS2_1 | KBC_VEN_QUADTEL, + .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_pci_device = { + .name = "PS/2 Keyboard", + .internal_name = "keyboard_ps2_pci", + .flags = DEVICE_KBC | DEVICE_PCI, + .local = KBC_TYPE_PS2_1 | KBC_VEN_GENERIC, + .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_ami_pci_device = { + .name = "PS/2 Keyboard (AMI)", + .internal_name = "keyboard_ps2_ami_pci", + .flags = DEVICE_KBC | DEVICE_PCI, + .local = KBC_TYPE_PS2_1 | KBC_VEN_AMI, + .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_ali_pci_device = { + .name = "PS/2 Keyboard (ALi M5123/M1543C)", + .internal_name = "keyboard_ps2_ali_pci", + .flags = DEVICE_KBC | DEVICE_PCI, + .local = KBC_TYPE_PS2_1 | KBC_VEN_ALI, + .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_intel_ami_pci_device = { + .name = "PS/2 Keyboard (AMI)", + .internal_name = "keyboard_ps2_intel_ami_pci", + .flags = DEVICE_KBC | DEVICE_PCI, + .local = KBC_TYPE_GREEN | KBC_VEN_AMI, + .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_tg_ami_pci_device = { + .name = "PS/2 Keyboard (TriGem AMI)", + .internal_name = "keyboard_ps2_tg_ami_pci", + .flags = DEVICE_KBC | DEVICE_PCI, + .local = KBC_TYPE_PS2_1 | KBC_VEN_TRIGEM_AMI, + .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_acer_pci_device = { + .name = "PS/2 Keyboard (Acer 90M002A)", + .internal_name = "keyboard_ps2_acer_pci", + .flags = DEVICE_KBC | DEVICE_PCI, + .local = KBC_TYPE_PS2_1 | KBC_VEN_ACER, + .init = kbc_at_init, + .close = kbc_at_close, + .reset = kbc_at_reset, + { .available = NULL }, + .speed_changed = NULL, + .force_redraw = NULL, + .config = NULL +}; diff --git a/src/device/kbc_at_dev.c b/src/device/kbc_at_dev.c new file mode 100644 index 000000000..1c1a0e91a --- /dev/null +++ b/src/device/kbc_at_dev.c @@ -0,0 +1,214 @@ +/* + * 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. + * + * AT / PS/2 attached device emulation. + * + * + * + * Authors: Miran Grca, + * + * Copyright 2023 Miran Grca. + */ +#include +#include +#include +#include +#include +#define HAVE_STDARG_H +#include +#include <86box/86box.h> +#include "cpu.h" +#include <86box/timer.h> +#include <86box/io.h> +#include <86box/pic.h> +#include <86box/pit.h> +#include <86box/ppi.h> +#include <86box/mem.h> +#include <86box/device.h> +#include <86box/machine.h> +#include <86box/m_at_t3100e.h> +#include <86box/fdd.h> +#include <86box/fdc.h> +#include <86box/sound.h> +#include <86box/snd_speaker.h> +#include <86box/video.h> +#include <86box/keyboard.h> +#include <86box/plat_fallthrough.h> + +#ifdef ENABLE_KBC_AT_DEV_LOG +int kbc_at_dev_do_log = ENABLE_KBC_AT_DEV_LOG; + +static void +kbc_at_dev_log(const char *fmt, ...) +{ + va_list ap; + + if (kbc_at_dev_do_log) { + va_start(ap, fmt); + pclog_ex(fmt, ap); + va_end(ap); + } +} +#else +# define kbc_at_dev_log(fmt, ...) +#endif + +static void +kbc_at_dev_queue_reset(atkbc_dev_t *dev, uint8_t reset_main) +{ + if (reset_main) { + dev->queue_start = dev->queue_end = 0; + memset(dev->queue, 0x00, sizeof(dev->queue)); + } + + dev->cmd_queue_start = dev->cmd_queue_end = 0; + memset(dev->cmd_queue, 0x00, sizeof(dev->cmd_queue)); +} + +uint8_t +kbc_at_dev_queue_pos(atkbc_dev_t *dev, uint8_t main) +{ + uint8_t ret; + + if (main) + ret = ((dev->queue_end - dev->queue_start) & dev->fifo_mask); + else + ret = ((dev->cmd_queue_end - dev->cmd_queue_start) & 0xf); + + return ret; +} + +void +kbc_at_dev_queue_add(atkbc_dev_t *dev, uint8_t val, uint8_t main) +{ + if (main) { + kbc_at_dev_log("%s: dev->queue[%02X] = %02X;\n", dev->name, dev->queue_end, val); + dev->queue[dev->queue_end] = val; + dev->queue_end = (dev->queue_end + 1) & dev->fifo_mask; + } else { + kbc_at_dev_log("%s: dev->cmd_queue[%02X] = %02X;\n", dev->name, dev->cmd_queue_end, val); + dev->cmd_queue[dev->cmd_queue_end] = val; + dev->cmd_queue_end = (dev->cmd_queue_end + 1) & 0xf; + } + + /* TODO: This should be done on actual send to host. */ + if (val != 0xfe) + dev->last_scan_code = val; +} + +static void +kbc_at_dev_poll(void *priv) +{ + atkbc_dev_t *dev = (atkbc_dev_t *) priv; + + switch (dev->state) { + case DEV_STATE_MAIN_1: + /* Process the command if needed and then return to main loop #2. */ + if (dev->port->wantcmd) { + kbc_at_dev_log("%s: Processing keyboard command %02X...\n", dev->name, dev->port->dat); + kbc_at_dev_queue_reset(dev, 0); + dev->process_cmd(dev); + dev->port->wantcmd = 0; + } else + dev->state = DEV_STATE_MAIN_2; + break; + case DEV_STATE_MAIN_2: + /* Output from scan queue if needed and then return to main loop #1. */ + if (*dev->scan && (dev->port->out_new == -1) && (dev->queue_start != dev->queue_end)) { + kbc_at_dev_log("%s: %02X (DATA) on channel 1\n", dev->name, dev->queue[dev->queue_start]); + dev->port->out_new = dev->queue[dev->queue_start]; + dev->queue_start = (dev->queue_start + 1) & dev->fifo_mask; + } + if (!(*dev->scan) || dev->port->wantcmd) + dev->state = DEV_STATE_MAIN_1; + break; + case DEV_STATE_MAIN_OUT: + /* If host wants to send command while we're sending a byte to host, process the command. */ + if (dev->port->wantcmd) { + kbc_at_dev_log("%s: Processing keyboard command %02X...\n", dev->name, dev->port->dat); + kbc_at_dev_queue_reset(dev, 0); + dev->process_cmd(dev); + dev->port->wantcmd = 0; + break; + } + fallthrough; + case DEV_STATE_MAIN_WANT_IN: + /* Output command response and then return to main loop #2. */ + if ((dev->port->out_new == -1) && (dev->cmd_queue_start != dev->cmd_queue_end)) { + kbc_at_dev_log("%s: %02X (CMD ) on channel 1\n", dev->name, dev->cmd_queue[dev->cmd_queue_start]); + dev->port->out_new = dev->cmd_queue[dev->cmd_queue_start]; + dev->cmd_queue_start = (dev->cmd_queue_start + 1) & 0xf; + } + if (dev->cmd_queue_start == dev->cmd_queue_end) + dev->state++; + break; + case DEV_STATE_MAIN_IN: + /* Wait for host data. */ + if (dev->port->wantcmd) { + kbc_at_dev_log("%s: Processing keyboard command %02X parameter %02X...\n", dev->name, dev->command, dev->port->dat); + kbc_at_dev_queue_reset(dev, 0); + dev->process_cmd(dev); + dev->port->wantcmd = 0; + } + break; + case DEV_STATE_EXECUTE_BAT: + dev->state = DEV_STATE_MAIN_OUT; + dev->execute_bat(dev); + break; + case DEV_STATE_MAIN_WANT_EXECUTE_BAT: + /* Output command response and then return to main loop #2. */ + if ((dev->port->out_new == -1) && (dev->cmd_queue_start != dev->cmd_queue_end)) { + kbc_at_dev_log("%s: %02X (CMD ) on channel 1\n", dev->name, dev->cmd_queue[dev->cmd_queue_start]); + dev->port->out_new = dev->cmd_queue[dev->cmd_queue_start]; + dev->cmd_queue_start = (dev->cmd_queue_start + 1) & 0xf; + } + if (dev->cmd_queue_start == dev->cmd_queue_end) + dev->state = DEV_STATE_EXECUTE_BAT; + break; + default: + break; + } +} + +void +kbc_at_dev_reset(atkbc_dev_t *dev, int do_fa) +{ + dev->port->out_new = -1; + dev->port->wantcmd = 0; + + kbc_at_dev_queue_reset(dev, 1); + + dev->last_scan_code = 0x00; + + *dev->scan = 1; + + if (do_fa) { + kbc_at_dev_queue_add(dev, 0xfa, 0); + dev->state = DEV_STATE_MAIN_WANT_EXECUTE_BAT; + } else + dev->state = DEV_STATE_EXECUTE_BAT; +} + +atkbc_dev_t * +kbc_at_dev_init(uint8_t inst) +{ + atkbc_dev_t *dev; + + dev = (atkbc_dev_t *) malloc(sizeof(atkbc_dev_t)); + memset(dev, 0x00, sizeof(atkbc_dev_t)); + + dev->port = kbc_at_ports[inst]; + + if (dev->port != NULL) { + dev->port->priv = dev; + dev->port->poll = kbc_at_dev_poll; + } + + /* Return our private data to the I/O layer. */ + return dev; +} diff --git a/src/device/keyboard.c b/src/device/keyboard.c index 7c1581d52..5f9986d7b 100644 --- a/src/device/keyboard.c +++ b/src/device/keyboard.c @@ -1,22 +1,22 @@ /* - * 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. + * 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. + * This file is part of the 86Box distribution. * - * General keyboard driver interface. + * General keyboard driver interface. * * * - * Authors: Sarah Walker, - * Miran Grca, - * Fred N. van Kempen, + * Authors: Sarah Walker, + * Miran Grca, + * Fred N. van Kempen, * - * Copyright 2008-2019 Sarah Walker. - * Copyright 2015-2019 Miran Grca. - * Copyright 2017-2019 Fred N. van Kempen. + * Copyright 2008-2019 Sarah Walker. + * Copyright 2015-2019 Miran Grca. + * Copyright 2017-2019 Fred N. van Kempen. */ #include #include @@ -28,23 +28,39 @@ #include "cpu.h" +int keyboard_scan; -int keyboard_scan; -void (*keyboard_send)(uint16_t val); - - -static int recv_key[512]; /* keyboard input buffer */ -static int oldkey[512]; -#if 0 -static int keydelay[512]; +#ifdef _WIN32 +/* Windows: F8+F12 */ +uint16_t key_prefix_1_1 = 0x042; /* F8 */ +uint16_t key_prefix_1_2 = 0x000; /* Invalid */ +uint16_t key_prefix_2_1 = 0x000; /* Invalid */ +uint16_t key_prefix_2_2 = 0x000; /* Invalid */ +uint16_t key_uncapture_1 = 0x058; /* F12 */ +uint16_t key_uncapture_2 = 0x000; /* Invalid */ +#else +/* WxWidgets cannot do two regular keys.. CTRL+END */ +uint16_t key_prefix_1_1 = 0x01d; /* Left Ctrl */ +uint16_t key_prefix_1_2 = 0x11d; /* Right Ctrl */ +uint16_t key_prefix_2_1 = 0x000; /* Invalid */ +uint16_t key_prefix_2_2 = 0x000; /* Invalid */ +uint16_t key_uncapture_1 = 0x04f; /* Numpad End */ +uint16_t key_uncapture_2 = 0x14f; /* End */ #endif -static scancode *scan_table; /* scancode table for keyboard */ -static uint8_t caps_lock = 0; -static uint8_t num_lock = 0; -static uint8_t scroll_lock = 0; -static uint8_t shift = 0; +void (*keyboard_send)(uint16_t val); +static int recv_key[512]; /* keyboard input buffer */ +static int oldkey[512]; +#if 0 +static int keydelay[512]; +#endif +static scancode *scan_table; /* scancode table for keyboard */ + +static uint8_t caps_lock = 0; +static uint8_t num_lock = 0; +static uint8_t scroll_lock = 0; +static uint8_t shift = 0; void keyboard_init(void) @@ -52,156 +68,181 @@ keyboard_init(void) memset(recv_key, 0x00, sizeof(recv_key)); keyboard_scan = 1; - scan_table = NULL; + scan_table = NULL; memset(keyboard_set3_flags, 0x00, sizeof(keyboard_set3_flags)); keyboard_set3_all_repeat = 0; - keyboard_set3_all_break = 0; + keyboard_set3_all_break = 0; } - void keyboard_set_table(const scancode *ptr) { scan_table = (scancode *) ptr; } - static uint8_t fake_shift_needed(uint16_t scan) { - switch(scan) { - case 0x147: - case 0x148: - case 0x149: - case 0x14a: - case 0x14b: - case 0x14d: - case 0x14f: - case 0x150: - case 0x151: - case 0x152: - case 0x153: - return 1; - default: - return 0; + switch (scan) { + case 0x137: /* Yes, Print Screen requires the fake shifts. */ + case 0x147: + case 0x148: + case 0x149: + case 0x14a: + case 0x14b: + case 0x14d: + case 0x14f: + case 0x150: + case 0x151: + case 0x152: + case 0x153: + return 1; + default: + return 0; } } - void key_process(uint16_t scan, int down) { - scancode *codes = scan_table; - int c; + const scancode *codes = scan_table; + int c; + + if (!codes) + return; if (!keyboard_scan || (keyboard_send == NULL)) - return; + return; oldkey[scan] = down; - if (down && codes[scan].mk[0] == 0) - return; - if (!down && codes[scan].brk[0] == 0) - return; + if (down && (codes[scan].mk[0] == 0)) + return; + + if (!down && (codes[scan].brk[0] == 0)) + return; /* TODO: The keyboard controller needs to report the AT flag to us here. */ if (is286 && ((keyboard_mode & 3) == 3)) { - if (!keyboard_set3_all_break && !down && !(keyboard_set3_flags[codes[scan].mk[0]] & 2)) - return; + if (!keyboard_set3_all_break && !down && !(keyboard_set3_flags[codes[scan].mk[0]] & 2)) + return; } c = 0; if (down) { - /* Send the special code indicating an opening fake shift might be needed. */ - if (fake_shift_needed(scan)) - keyboard_send(0x100); - while (codes[scan].mk[c] != 0) - keyboard_send(codes[scan].mk[c++]); + /* Send the special code indicating an opening fake shift might be needed. */ + if (fake_shift_needed(scan)) + keyboard_send(0x100); + while (codes[scan].mk[c] != 0) + keyboard_send(codes[scan].mk[c++]); } else { - while (codes[scan].brk[c] != 0) - keyboard_send(codes[scan].brk[c++]); - /* Send the special code indicating a closing fake shift might be needed. */ - if (fake_shift_needed(scan)) - keyboard_send(0x101); + while (codes[scan].brk[c] != 0) + keyboard_send(codes[scan].brk[c++]); + /* Send the special code indicating a closing fake shift might be needed. */ + if (fake_shift_needed(scan)) + keyboard_send(0x101); } } - /* Handle a keystroke event from the UI layer. */ void keyboard_input(int down, uint16_t scan) { + /* Special case for E1 1D, translate it to 0100 - special case. */ + if ((scan >> 8) == 0xe1) { + if ((scan & 0xff) == 0x1d) + scan = 0x0100; /* Translate E0 xx scan codes to 01xx because we use 512-byte arrays for states and scan code sets. */ - if ((scan >> 8) == 0xe0) { - scan &= 0x00ff; - scan |= 0x0100; /* extended key code */ + } else if ((scan >> 8) == 0xe0) { + scan &= 0x00ff; + scan |= 0x0100; /* extended key code */ } else if ((scan >> 8) != 0x01) - scan &= 0x00ff; /* we can receive a scan code whose upper byte is 0x01, - this means we're the Win32 version running on windows - that already sends us preprocessed scan codes, which - means we then use the scan code as is, and need to - make sure we do not accidentally strip that upper byte */ + scan &= 0x00ff; /* we can receive a scan code whose upper byte is 0x01, + this means we're the Win32 version running on windows + that already sends us preprocessed scan codes, which + means we then use the scan code as is, and need to + make sure we do not accidentally strip that upper byte */ if (recv_key[scan & 0x1ff] ^ down) { - if (down) { - switch(scan & 0x1ff) { - case 0x01c: /* Left Ctrl */ - shift |= 0x01; - break; - case 0x11c: /* Right Ctrl */ - shift |= 0x10; - break; - case 0x02a: /* Left Shift */ - shift |= 0x02; - break; - case 0x036: /* Right Shift */ - shift |= 0x20; - break; - case 0x038: /* Left Alt */ - shift |= 0x04; - break; - case 0x138: /* Right Alt */ - shift |= 0x40; - break; - } - } else { - switch(scan & 0x1ff) { - case 0x01c: /* Left Ctrl */ - shift &= ~0x01; - break; - case 0x11c: /* Right Ctrl */ - shift &= ~0x10; - break; - case 0x02a: /* Left Shift */ - shift &= ~0x02; - break; - case 0x036: /* Right Shift */ - shift &= ~0x20; - break; - case 0x038: /* Left Alt */ - shift &= ~0x04; - break; - case 0x138: /* Right Alt */ - shift &= ~0x40; - break; - case 0x03a: /* Caps Lock */ - caps_lock ^= 1; - break; - case 0x045: - num_lock ^= 1; - break; - case 0x046: - scroll_lock ^= 1; - break; - } - } + if (down) { + switch (scan & 0x1ff) { + case 0x01d: /* Left Ctrl */ + shift |= 0x01; + break; + case 0x11d: /* Right Ctrl */ + shift |= 0x10; + break; + case 0x02a: /* Left Shift */ + shift |= 0x02; + break; + case 0x036: /* Right Shift */ + shift |= 0x20; + break; + case 0x038: /* Left Alt */ + shift |= 0x04; + break; + case 0x138: /* Right Alt */ + shift |= 0x40; + break; + case 0x15b: /* Left Windows */ + shift |= 0x08; + break; + case 0x15c: /* Right Windows */ + shift |= 0x80; + break; + + default: + break; + } + } else { + switch (scan & 0x1ff) { + case 0x01d: /* Left Ctrl */ + shift &= ~0x01; + break; + case 0x11d: /* Right Ctrl */ + shift &= ~0x10; + break; + case 0x02a: /* Left Shift */ + shift &= ~0x02; + break; + case 0x036: /* Right Shift */ + shift &= ~0x20; + break; + case 0x038: /* Left Alt */ + shift &= ~0x04; + break; + case 0x138: /* Right Alt */ + shift &= ~0x40; + break; + case 0x15b: /* Left Windows */ + shift &= ~0x08; + break; + case 0x15c: /* Right Windows */ + shift &= ~0x80; + break; + case 0x03a: /* Caps Lock */ + caps_lock ^= 1; + break; + case 0x045: + num_lock ^= 1; + break; + case 0x046: + scroll_lock ^= 1; + break; + + default: + break; + } + } } /* NOTE: Shouldn't this be some sort of bit shift? An array of 8 unsigned 64-bit integers - should be enough. */ - /* recv_key[scan >> 6] |= ((uint64_t) down << ((uint64_t) scan & 0x3fLL)); */ + should be enough. */ +#if 0 + recv_key[scan >> 6] |= ((uint64_t) down << ((uint64_t) scan & 0x3fLL)); +#endif /* pclog("Received scan code: %03X (%s)\n", scan & 0x1ff, down ? "down" : "up"); */ recv_key[scan & 0x1ff] = down; @@ -209,127 +250,134 @@ keyboard_input(int down, uint16_t scan) key_process(scan & 0x1ff, down); } - static uint8_t keyboard_do_break(uint16_t scan) { - scancode *codes = scan_table; + const scancode *codes = scan_table; /* TODO: The keyboard controller needs to report the AT flag to us here. */ if (is286 && ((keyboard_mode & 3) == 3)) { - if (!keyboard_set3_all_break && - !recv_key[scan] && - !(keyboard_set3_flags[codes[scan].mk[0]] & 2)) - return 0; - else - return 1; + if (!keyboard_set3_all_break && !recv_key[scan] && !(keyboard_set3_flags[codes[scan].mk[0]] & 2)) + return 0; + else + return 1; } else - return 1; + return 1; } - /* Also called by the emulated keyboard controller to update the states of Caps Lock, Num Lock, and Scroll Lock when receving the "Set keyboard LEDs" command. */ void keyboard_update_states(uint8_t cl, uint8_t nl, uint8_t sl) { - caps_lock = cl; - num_lock = nl; - scroll_lock = sl; + caps_lock = cl; + num_lock = nl; + scroll_lock = sl; } - uint8_t keyboard_get_shift(void) { - return shift; + return shift; } - void keyboard_get_states(uint8_t *cl, uint8_t *nl, uint8_t *sl) { - if (cl) - *cl = caps_lock; - if (nl) - *nl = num_lock; - if (sl) - *sl = scroll_lock; + if (cl) + *cl = caps_lock; + if (nl) + *nl = num_lock; + if (sl) + *sl = scroll_lock; } - /* Called by the UI to update the states of Caps Lock, Num Lock, and Scroll Lock. */ void keyboard_set_states(uint8_t cl, uint8_t nl, uint8_t sl) { - scancode *codes = scan_table; + const scancode *codes = scan_table; int i; if (caps_lock != cl) { - i = 0; - while (codes[0x03a].mk[i] != 0) - keyboard_send(codes[0x03a].mk[i++]); - if (keyboard_do_break(0x03a)) { - i = 0; - while (codes[0x03a].brk[i] != 0) - keyboard_send(codes[0x03a].brk[i++]); - } + i = 0; + while (codes[0x03a].mk[i] != 0) + keyboard_send(codes[0x03a].mk[i++]); + if (keyboard_do_break(0x03a)) { + i = 0; + while (codes[0x03a].brk[i] != 0) + keyboard_send(codes[0x03a].brk[i++]); + } } if (num_lock != nl) { - i = 0; - while (codes[0x045].mk[i] != 0) - keyboard_send(codes[0x045].mk[i++]); - if (keyboard_do_break(0x045)) { - i = 0; - while (codes[0x045].brk[i] != 0) - keyboard_send(codes[0x045].brk[i++]); - } + i = 0; + while (codes[0x045].mk[i] != 0) + keyboard_send(codes[0x045].mk[i++]); + if (keyboard_do_break(0x045)) { + i = 0; + while (codes[0x045].brk[i] != 0) + keyboard_send(codes[0x045].brk[i++]); + } } if (scroll_lock != sl) { - i = 0; - while (codes[0x046].mk[i] != 0) - keyboard_send(codes[0x046].mk[i++]); - if (keyboard_do_break(0x046)) { - i = 0; - while (codes[0x046].brk[i] != 0) - keyboard_send(codes[0x046].brk[i++]); - } + i = 0; + while (codes[0x046].mk[i] != 0) + keyboard_send(codes[0x046].mk[i++]); + if (keyboard_do_break(0x046)) { + i = 0; + while (codes[0x046].brk[i] != 0) + keyboard_send(codes[0x046].brk[i++]); + } } keyboard_update_states(cl, nl, sl); } - int keyboard_recv(uint16_t key) { - return recv_key[key]; + return recv_key[key]; } +/* Do we have Control-Alt-PgDn in the keyboard buffer? */ +int +keyboard_isfsenter(void) +{ + return ((recv_key[0x01d] || recv_key[0x11d]) && (recv_key[0x038] || recv_key[0x138]) && (recv_key[0x049] || recv_key[0x149])); +} + +int +keyboard_isfsenter_up(void) +{ + return (!recv_key[0x01d] && !recv_key[0x11d] && !recv_key[0x038] && !recv_key[0x138] && !recv_key[0x049] && !recv_key[0x149]); +} /* Do we have Control-Alt-PgDn in the keyboard buffer? */ int keyboard_isfsexit(void) { - return( (recv_key[0x01D] || recv_key[0x11D]) && - (recv_key[0x038] || recv_key[0x138]) && - (recv_key[0x051] || recv_key[0x151]) ); + return ((recv_key[0x01d] || recv_key[0x11d]) && (recv_key[0x038] || recv_key[0x138]) && (recv_key[0x051] || recv_key[0x151])); } +int +keyboard_isfsexit_up(void) +{ + return (!recv_key[0x01d] && !recv_key[0x11d] && !recv_key[0x038] && !recv_key[0x138] && !recv_key[0x051] && !recv_key[0x151]); +} -/* Do we have F8-F12 in the keyboard buffer? */ +/* Do we have the mouse uncapture combination in the keyboard buffer? */ int keyboard_ismsexit(void) { -#ifdef _WIN32 - /* Windows: F8+F12 */ - return( recv_key[0x042] && recv_key[0x058] ); -#else - /* WxWidgets cannot do two regular keys.. CTRL+END */ - return( (recv_key[0x01D] || recv_key[0x11D]) && (recv_key[0x04F] || recv_key[0x14F]) ); -#endif + if ((key_prefix_2_1 != 0x000) || (key_prefix_2_2 != 0x000)) + return ((recv_key[key_prefix_1_1] || recv_key[key_prefix_1_2]) && + (recv_key[key_prefix_2_1] || recv_key[key_prefix_2_2]) && + (recv_key[key_uncapture_1] || recv_key[key_uncapture_2])); + else + return ((recv_key[key_prefix_1_1] || recv_key[key_prefix_1_2]) && + (recv_key[key_uncapture_1] || recv_key[key_uncapture_2])); } diff --git a/src/device/keyboard_at.c b/src/device/keyboard_at.c index 06357e605..21c4884b7 100644 --- a/src/device/keyboard_at.c +++ b/src/device/keyboard_at.c @@ -1,180 +1,82 @@ /* - * 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. + * 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. + * This file is part of the 86Box distribution. * - * Intel 8042 (AT keyboard controller) emulation. + * Implementation of PS/2 series Mouse devices. * + * Authors: Miran Grca, + * Fred N. van Kempen, * - * - * Authors: Sarah Walker, - * Miran Grca, - * Fred N. van Kempen, - * EngiNerd - * - * Copyright 2008-2020 Sarah Walker. - * Copyright 2016-2020 Miran Grca. - * Copyright 2017-2020 Fred N. van Kempen. - * Copyright 2020 EngiNerd. + * Copyright 2016-2023 Miran Grca. + * Copyright 2017-2023 Fred N. van Kempen. */ +#include #include #include -#include #include -#include -#define HAVE_STDARG_H +#include #include +#define HAVE_STDARG_H #include <86box/86box.h> -#include "cpu.h" -#include <86box/timer.h> -#include <86box/io.h> -#include <86box/pic.h> -#include <86box/pit.h> -#include <86box/ppi.h> -#include <86box/mem.h> #include <86box/device.h> -#include <86box/machine.h> -#include <86box/m_xt_xi8088.h> -#include <86box/m_at_t3100e.h> -#include <86box/fdd.h> -#include <86box/fdc.h> -#include <86box/sound.h> -#include <86box/snd_speaker.h> -#include <86box/video.h> #include <86box/keyboard.h> +#include <86box/mouse.h> +#define FLAG_PS2 0x08 /* dev is AT or PS/2 */ +#define FLAG_AT 0x00 /* dev is AT or PS/2 */ +#define FLAG_TYPE_MASK 0x07 /* mask for type */ -#define STAT_PARITY 0x80 -#define STAT_RTIMEOUT 0x40 -#define STAT_TTIMEOUT 0x20 -#define STAT_MFULL 0x20 -#define STAT_UNLOCKED 0x10 -#define STAT_CD 0x08 -#define STAT_SYSFLAG 0x04 -#define STAT_IFULL 0x02 -#define STAT_OFULL 0x01 +#define FIFO_SIZE 16 -#define RESET_DELAY_TIME (100 * 10) /* 600ms */ - -#define CCB_UNUSED 0x80 -#define CCB_TRANSLATE 0x40 -#define CCB_PCMODE 0x20 -#define CCB_ENABLEKBD 0x10 -#define CCB_IGNORELOCK 0x08 -#define CCB_SYSTEM 0x04 -#define CCB_ENABLEMINT 0x02 -#define CCB_ENABLEKINT 0x01 - -#define CCB_MASK 0x68 -#define MODE_MASK 0x6c - -#define KBC_TYPE_ISA 0x00 /* AT ISA-based chips */ -#define KBC_TYPE_PS2_NOREF 0x01 /* PS2 type, no refresh */ -#define KBC_TYPE_PS2_1 0x02 /* PS2 on PS/2, type 1 */ -#define KBC_TYPE_PS2_2 0x03 /* PS2 on PS/2, type 2 */ -#define KBC_TYPE_MASK 0x03 - -#define KBC_VEN_GENERIC 0x00 -#define KBC_VEN_AMI 0x04 -#define KBC_VEN_IBM_MCA 0x08 -#define KBC_VEN_QUADTEL 0x0c -#define KBC_VEN_TOSHIBA 0x10 -#define KBC_VEN_XI8088 0x14 -#define KBC_VEN_IBM_PS1 0x18 -#define KBC_VEN_ACER 0x1c -#define KBC_VEN_INTEL_AMI 0x20 -#define KBC_VEN_OLIVETTI 0x24 -#define KBC_VEN_NCR 0x28 -#define KBC_VEN_SAMSUNG 0x2c -#define KBC_VEN_MASK 0x3c - - -typedef struct { - uint8_t command, status, old_status, out, old_out, secr_phase, - mem_addr, input_port, output_port, old_output_port, - key_command, output_locked, ami_stat, want60, - wantirq, key_wantdata, ami_flags, first_write; - - uint8_t mem[0x100]; - - int last_irq, old_last_irq, - reset_delay, - out_new, out_delayed; - - uint32_t flags; - - pc_timer_t pulse_cb; - - uint8_t (*write60_ven)(void *p, uint8_t val); - uint8_t (*write64_ven)(void *p, uint8_t val); - - pc_timer_t send_delay_timer; -} atkbd_t; - - -/* bit 0 = repeat, bit 1 = makes break code? */ -uint8_t keyboard_set3_flags[512]; -uint8_t keyboard_set3_all_repeat; -uint8_t keyboard_set3_all_break; - -/* Bits 0 - 1 = scan code set, bit 6 = translate or not. */ -uint8_t keyboard_mode = 0x42; - - -static uint8_t key_ctrl_queue[16]; -static int key_ctrl_queue_start = 0, key_ctrl_queue_end = 0; -static uint8_t key_queue[16]; -static int key_queue_start = 0, key_queue_end = 0; -uint8_t mouse_queue[16]; -int mouse_queue_start = 0, mouse_queue_end = 0; -static uint8_t kbd_last_scan_code; -static void (*mouse_write)(uint8_t val, void *priv) = NULL; -static void *mouse_p = NULL; -static uint8_t sc_or = 0; -static atkbd_t *SavedKbd = NULL; // FIXME: remove!!! --FvK - - -/* Non-translated to translated scan codes. */ -static const uint8_t nont_to_t[256] = { - 0xff, 0x43, 0x41, 0x3f, 0x3d, 0x3b, 0x3c, 0x58, - 0x64, 0x44, 0x42, 0x40, 0x3e, 0x0f, 0x29, 0x59, - 0x65, 0x38, 0x2a, 0x70, 0x1d, 0x10, 0x02, 0x5a, - 0x66, 0x71, 0x2c, 0x1f, 0x1e, 0x11, 0x03, 0x5b, - 0x67, 0x2e, 0x2d, 0x20, 0x12, 0x05, 0x04, 0x5c, - 0x68, 0x39, 0x2f, 0x21, 0x14, 0x13, 0x06, 0x5d, - 0x69, 0x31, 0x30, 0x23, 0x22, 0x15, 0x07, 0x5e, - 0x6a, 0x72, 0x32, 0x24, 0x16, 0x08, 0x09, 0x5f, - 0x6b, 0x33, 0x25, 0x17, 0x18, 0x0b, 0x0a, 0x60, - 0x6c, 0x34, 0x35, 0x26, 0x27, 0x19, 0x0c, 0x61, - 0x6d, 0x73, 0x28, 0x74, 0x1a, 0x0d, 0x62, 0x6e, - 0x3a, 0x36, 0x1c, 0x1b, 0x75, 0x2b, 0x63, 0x76, - 0x55, 0x56, 0x77, 0x78, 0x79, 0x7a, 0x0e, 0x7b, - 0x7c, 0x4f, 0x7d, 0x4b, 0x47, 0x7e, 0x7f, 0x6f, - 0x52, 0x53, 0x50, 0x4c, 0x4d, 0x48, 0x01, 0x45, - 0x57, 0x4e, 0x51, 0x4a, 0x37, 0x49, 0x46, 0x54, - 0x80, 0x81, 0x82, 0x41, 0x54, 0x85, 0x86, 0x87, - 0x88, 0x89, 0x8a, 0x8b, 0x8c, 0x8d, 0x8e, 0x8f, - 0x90, 0x91, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97, - 0x98, 0x99, 0x9a, 0x9b, 0x9c, 0x9d, 0x9e, 0x9f, - 0xa0, 0xa1, 0xa2, 0xa3, 0xa4, 0xa5, 0xa6, 0xa7, - 0xa8, 0xa9, 0xaa, 0xab, 0xac, 0xad, 0xae, 0xaf, - 0xb0, 0xb1, 0xb2, 0xb3, 0xb4, 0xb5, 0xb6, 0xb7, - 0xb8, 0xb9, 0xba, 0xbb, 0xbc, 0xbd, 0xbe, 0xbf, - 0xc0, 0xc1, 0xc2, 0xc3, 0xc4, 0xc5, 0xc6, 0xc7, - 0xc8, 0xc9, 0xca, 0xcb, 0xcc, 0xcd, 0xce, 0xcf, - 0xd0, 0xd1, 0xd2, 0xd3, 0xd4, 0xd5, 0xd6, 0xd7, - 0xd8, 0xd9, 0xda, 0xdb, 0xdc, 0xdd, 0xde, 0xdf, - 0xe0, 0xe1, 0xe2, 0xe3, 0xe4, 0xe5, 0xe6, 0xe7, - 0xe8, 0xe9, 0xea, 0xeb, 0xec, 0xed, 0xee, 0xef, - 0xf0, 0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7, - 0xf8, 0xf9, 0xfa, 0xfb, 0xfc, 0xfd, 0xfe, 0xff +enum { + KBD_84_KEY = 0, + KBD_101_KEY, + KBD_102_KEY, + KBD_JIS, + KBD_KOREAN }; -#ifdef USE_SET1 +#define FLAG_ENABLED 0x10 /* dev is enabled for use */ +#define FLAG_CTRLDAT 0x08 /* ctrl or data mode */ + +const uint8_t id_bytes[16][4] = { { 0x00, 0x00, 0x00, 0x00 }, /* AT 84-key */ + { 0x00, 0x00, 0x00, 0x00 }, /* AT 101/102/106-key */ + { 0x00, 0x00, 0x00, 0x00 }, + { 0x00, 0x00, 0x00, 0x00 }, + { 0x00, 0x00, 0x00, 0x00 }, /* AT Korean */ + { 0x00, 0x00, 0x00, 0x00 }, + { 0x00, 0x00, 0x00, 0x00 }, + { 0x00, 0x00, 0x00, 0x00 }, + { 0x00, 0x00, 0x00, 0x00 }, + { 0xab, 0x83, 0x00, 0x00 }, /* PS/2 101-key */ + { 0xab, 0x83, 0x00, 0x00 }, /* PS/2 102-key */ + { 0xab, 0x90, 0x00, 0x00 }, /* PS/2 106-key JIS */ + /* Japanese keyboard ID - TODO: Find the actual Korean one. */ + { 0xab, 0x90, 0x00, 0x00 }, /* PS/2 Korean */ + { 0x00, 0x00, 0x00, 0x00 }, + { 0x00, 0x00, 0x00, 0x00 }, + { 0x00, 0x00, 0x00, 0x00 } }; + +/* Global keyboard flags for scan code set 3: + bit 0 = repeat, bit 1 = makes break code? */ +uint8_t keyboard_set3_flags[512]; +uint8_t keyboard_set3_all_repeat; +uint8_t keyboard_set3_all_break; + +/* Global keyboard mode: + Bits 0 - 1 = scan code set. */ +uint8_t keyboard_mode = 0x02; + +static atkbc_dev_t *SavedKbd = NULL; + +static uint8_t inv_cmd_response = 0xfa; + static const scancode scancode_set1[512] = { + // clang-format off { { 0},{ 0} }, { { 0x01,0},{ 0x81,0} }, { { 0x02,0},{ 0x82,0} }, { { 0x03,0},{ 0x83,0} }, /*000*/ { { 0x04,0},{ 0x84,0} }, { { 0x05,0},{ 0x85,0} }, { { 0x06,0},{ 0x86,0} }, { { 0x07,0},{ 0x87,0} }, /*004*/ { { 0x08,0},{ 0x88,0} }, { { 0x09,0},{ 0x89,0} }, { { 0x0a,0},{ 0x8a,0} }, { { 0x0b,0},{ 0x8b,0} }, /*008*/ @@ -302,10 +204,11 @@ static const scancode scancode_set1[512] = { { { 0},{ 0} }, { { 0},{ 0} }, { { 0},{ 0} }, { { 0},{ 0} }, /*1f4*/ { { 0},{ 0} }, { { 0},{ 0} }, { { 0},{ 0} }, { { 0},{ 0} }, /*1f8*/ { { 0},{ 0} }, { { 0},{ 0} }, { {0xe0,0xfe,0},{ 0} }, { {0xe0,0xff,0},{ 0} } /*1fc*/ + // clang-format on }; -#endif static const scancode scancode_set2[512] = { + // clang-format off { { 0},{ 0} }, { { 0x76,0},{ 0xF0,0x76,0} }, { { 0x16,0},{ 0xF0,0x16,0} }, { { 0x1E,0},{ 0xF0,0x1E,0} }, /*000*/ { { 0x26,0},{ 0xF0,0x26,0} }, { { 0x25,0},{ 0xF0,0x25,0} }, { { 0x2E,0},{ 0xF0,0x2E,0} }, { { 0x36,0},{ 0xF0,0x36,0} }, /*004*/ { { 0x3D,0},{ 0xF0,0x3D,0} }, { { 0x3E,0},{ 0xF0,0x3E,0} }, { { 0x46,0},{ 0xF0,0x46,0} }, { { 0x45,0},{ 0xF0,0x45,0} }, /*008*/ @@ -433,9 +336,11 @@ static const scancode scancode_set2[512] = { { { 0},{ 0} }, { { 0},{ 0} }, { { 0},{ 0} }, { { 0},{ 0} }, /*1f4*/ { { 0},{ 0} }, { { 0},{ 0} }, { { 0},{ 0} }, { { 0},{ 0} }, /*1f8*/ { { 0},{ 0} }, { { 0},{ 0} }, { {0xe0,0xfe,0},{0xe0,0xF0,0xFE,0} }, { {0xe0,0xff,0},{0xe0,0xF0,0xFF,0} } /*1fc*/ + // clang-format on }; static const scancode scancode_set3[512] = { + // clang-format off { { 0},{ 0} }, { { 0x08,0},{ 0xf0,0x08,0} }, { { 0x16,0},{ 0xf0,0x16,0} }, { { 0x1E,0},{ 0xf0,0x1E,0} }, /*000*/ { { 0x26,0},{ 0xf0,0x26,0} }, { { 0x25,0},{ 0xf0,0x25,0} }, { { 0x2E,0},{ 0xf0,0x2E,0} }, { { 0x36,0},{ 0xf0,0x36,0} }, /*004*/ { { 0x3D,0},{ 0xf0,0x3D,0} }, { { 0x3E,0},{ 0xf0,0x3E,0} }, { { 0x46,0},{ 0xf0,0x46,0} }, { { 0x45,0},{ 0xf0,0x45,0} }, /*008*/ @@ -563,1707 +468,519 @@ static const scancode scancode_set3[512] = { { { 0},{ 0} }, { { 0},{ 0} }, { { 0},{ 0} }, { { 0},{ 0} }, /*1f4*/ { { 0},{ 0} }, { { 0},{ 0} }, { { 0},{ 0} }, { { 0},{ 0} }, /*1f8*/ { { 0},{ 0} }, { { 0},{ 0} }, { {0xe0,0xfe,0},{0xe0,0xF0,0xFE,0} }, { {0xe0,0xff,0},{0xe0,0xF0,0xFF,0} } /*1fc*/ + // clang-format on }; - -static void add_data_kbd(uint16_t val); - - #ifdef ENABLE_KEYBOARD_AT_LOG int keyboard_at_do_log = ENABLE_KEYBOARD_AT_LOG; - static void -kbd_log(const char *fmt, ...) +keyboard_at_log(const char *fmt, ...) { va_list ap; if (keyboard_at_do_log) { - va_start(ap, fmt); - pclog_ex(fmt, ap); - va_end(ap); + va_start(ap, fmt); + pclog_ex(fmt, ap); + va_end(ap); } } #else -#define kbd_log(fmt, ...) +# define keyboard_at_log(fmt, ...) #endif - static void -set_scancode_map(atkbd_t *dev) +keyboard_at_set_scancode_set(void) { - switch (keyboard_mode & 3) { -#ifdef USE_SET1 - case 1: - default: - keyboard_set_table(scancode_set1); - break; -#else - default: -#endif - case 2: - keyboard_set_table(scancode_set2); - break; + switch (keyboard_mode) { + default: + case 0x01: + keyboard_set_table(scancode_set1); + break; - case 3: - keyboard_set_table(scancode_set3); - break; - } + case 0x02: + keyboard_set_table(scancode_set2); + break; - if (keyboard_mode & 0x20) -#ifdef USE_SET1 - keyboard_set_table(scancode_set1); -#else - keyboard_set_table(scancode_set2); -#endif -} - - - -static void -kbc_queue_reset(uint8_t channel) -{ - if (channel == 2) { - mouse_queue_start = mouse_queue_end = 0; - memset(mouse_queue, 0x00, sizeof(mouse_queue)); - } else if (channel == 1) { - key_queue_start = key_queue_end = 0; - memset(key_queue, 0x00, sizeof(key_queue)); - } else { - key_ctrl_queue_start = key_ctrl_queue_end = 0; - memset(key_ctrl_queue, 0x00, sizeof(key_ctrl_queue)); + case 0x03: + keyboard_set_table(scancode_set3); + break; } } - static void -kbc_queue_add(atkbd_t *dev, uint8_t val, uint8_t channel, uint8_t stat_hi) +add_data_vals(atkbc_dev_t *dev, uint8_t *val, uint8_t len) { - uint8_t kbc_ven = dev->flags & KBC_VEN_MASK; - - if ((kbc_ven == KBC_VEN_AMI) || ((dev->flags & KBC_TYPE_MASK) >= KBC_TYPE_PS2_NOREF)) - stat_hi |= ((dev->input_port & 0x80) ? 0x10 : 0x00); - else - stat_hi |= 0x10; - - dev->status = (dev->status & 0x0f) | stat_hi; - - if (channel == 2) { - kbd_log("ATkbc: mouse_queue[%02X] = %02X;\n", mouse_queue_end, val); - mouse_queue[mouse_queue_end] = val; - mouse_queue_end = (mouse_queue_end + 1) & 0xf; - } else if (channel == 1) { - kbd_log("ATkbc: key_queue[%02X] = %02X;\n", key_queue_end, val); - key_queue[key_queue_end] = val; - key_queue_end = (key_queue_end + 1) & 0xf; - } else { - kbd_log("ATkbc: key_ctrl_queue[%02X] = %02X;\n", key_ctrl_queue_end, val); - key_ctrl_queue[key_ctrl_queue_end] = val; - key_ctrl_queue_end = (key_ctrl_queue_end + 1) & 0xf; - } + for (uint8_t i = 0; i < len; i++) + kbc_at_dev_queue_add(dev, val[i], 1); } - -static void -add_to_kbc_queue_front(atkbd_t *dev, uint8_t val, uint8_t channel, uint8_t stat_hi) -{ - uint8_t kbc_ven = dev->flags & KBC_VEN_MASK; - - if ((kbc_ven == KBC_VEN_AMI) || ((dev->flags & KBC_TYPE_MASK) >= KBC_TYPE_PS2_NOREF)) - stat_hi |= ((dev->input_port & 0x80) ? 0x10 : 0x00); - else - stat_hi |= 0x10; - - kbd_log("ATkbc: Adding %02X to front...\n", val); - dev->wantirq = 0; - if (channel == 2) { - if (dev->mem[0] & 0x02) - picint(0x1000); - if (kbc_ven != KBC_VEN_OLIVETTI) - dev->last_irq = 0x1000; - } else { - if (dev->mem[0] & 0x01) - picint(2); - if (kbc_ven != KBC_VEN_OLIVETTI) - dev->last_irq = 2; - } - dev->out = val; - if (channel == 2) - dev->status = (dev->status & ~STAT_IFULL) | (STAT_OFULL | STAT_MFULL) | stat_hi; - else - dev->status = (dev->status & ~(STAT_IFULL | STAT_MFULL)) | STAT_OFULL | stat_hi; - if (kbc_ven == KBC_VEN_OLIVETTI) - dev->last_irq = 0x0000; -} - - -static void -add_data_kbd_queue(atkbd_t *dev, int direct, uint8_t val) -{ - if ((!keyboard_scan && !direct) || (dev->reset_delay > 0) || (key_queue_end >= 16)) { - kbd_log("ATkbc: Unable to add to queue, conditions: %i, %i, %i\n", !keyboard_scan, (dev->reset_delay > 0), (key_queue_end >= 16)); - return; - } - kbd_log("ATkbc: key_queue[%02X] = %02X;\n", key_queue_end, val); - kbc_queue_add(dev, val, 1, 0x00); - kbd_last_scan_code = val; -} - - - -static void -add_data_kbd_direct(atkbd_t *dev, uint8_t val) -{ - int xt_mode = (keyboard_mode & 0x20) && ((dev->flags & KBC_TYPE_MASK) < KBC_TYPE_PS2_NOREF); - int translate = (keyboard_mode & 0x40); - uint8_t send; - - if (dev->reset_delay) - return; - - translate = translate || (keyboard_mode & 0x40) || xt_mode; - translate = translate || ((dev->flags & KBC_TYPE_MASK) == KBC_TYPE_PS2_2); - - if (translate) - send = nont_to_t[val]; - else - send = val; - - add_data_kbd_queue(dev, 1, send); -} - - -static void -add_data_kbd_raw(atkbd_t *dev, uint8_t val) -{ - add_data_kbd_queue(dev, 1, val); -} - - -static void -kbd_poll(void *priv) -{ - atkbd_t *dev = (atkbd_t *)priv; -#ifdef ENABLE_KEYBOARD_AT_LOG - const uint8_t channels[4] = { 1, 2, 0, 0 }; -#endif - - timer_advance_u64(&dev->send_delay_timer, (100ULL * TIMER_USEC)); - - if (dev->out_new != -1 && !dev->last_irq) { - dev->wantirq = 0; - if (dev->out_new & 0x100) { - if (dev->mem[0] & 0x02) - picint(0x1000); - kbd_log("ATkbc: %02X coming from channel 2\n"); - dev->out = dev->out_new & 0xff; - dev->out_new = -1; - dev->status = (dev->status & ~STAT_IFULL) | (STAT_OFULL | STAT_MFULL); - dev->last_irq = 0x1000; - } else { - if (dev->mem[0] & 0x01) - picint(2); - kbd_log("ATkbc: %02X coming from channel %i\n", dev->out_new & 0xff, channels[(dev->out_new >> 8) & 0x03]); - dev->out = dev->out_new & 0xff; - dev->out_new = -1; - dev->status = (dev->status & ~(STAT_IFULL | STAT_MFULL)) | STAT_OFULL; - dev->last_irq = 2; - } - } - - if (dev->out_new == -1 && !(dev->status & STAT_OFULL) && key_ctrl_queue_start != key_ctrl_queue_end) { - kbd_log("ATkbc: %02X on channel 0\n", key_ctrl_queue[key_ctrl_queue_start]); - dev->out_new = key_ctrl_queue[key_ctrl_queue_start] | 0x200; - key_ctrl_queue_start = (key_ctrl_queue_start + 1) & 0xf; - } else if (!(dev->status & STAT_OFULL) && dev->out_new == -1 && dev->out_delayed != -1) { - kbd_log("ATkbc: %02X delayed on channel %i\n", dev->out_delayed & 0xff, channels[(dev->out_delayed >> 8) & 0x03]); - dev->out_new = dev->out_delayed; - dev->out_delayed = -1; - } else if (!(dev->status & STAT_OFULL) && dev->out_new == -1 && mouse_queue_start != mouse_queue_end) { - kbd_log("ATkbc: %02X on channel 2\n", mouse_queue[mouse_queue_start]); - dev->out_new = mouse_queue[mouse_queue_start] | 0x100; - mouse_queue_start = (mouse_queue_start + 1) & 0xf; - } else if (!(dev->status & STAT_OFULL) && dev->out_new == -1 && !(dev->mem[0] & 0x10) && key_queue_start != key_queue_end) { - kbd_log("ATkbc: %02X on channel 1\n", key_queue[key_queue_start]); - dev->out_new = key_queue[key_queue_start]; - key_queue_start = (key_queue_start + 1) & 0xf; - } - - if (dev->reset_delay) { - dev->reset_delay--; - if (!dev->reset_delay) { - kbd_log("ATkbc: Sending AA on keyboard reset...\n"); - add_data_kbd_direct(dev, 0xaa); - } - } -} - - -static void -add_data(atkbd_t *dev, uint8_t val) -{ - kbd_log("ATkbc: add to queue\n"); - - kbd_log("ATkbc: key_ctrl_queue[%02X] = %02X;\n", key_ctrl_queue_end, val); - kbc_queue_add(dev, val, 0, 0x00); - - if (!(dev->out_new & 0x300)) { - dev->out_delayed = dev->out_new; - dev->out_new = -1; - } -} - - -static void -add_data_vals(atkbd_t *dev, uint8_t *val, uint8_t len) -{ - int xt_mode = (keyboard_mode & 0x20) && ((dev->flags & KBC_TYPE_MASK) < KBC_TYPE_PS2_NOREF); - int translate = (keyboard_mode & 0x40); - int i; - uint8_t or = 0; - uint8_t send; - - if (dev->reset_delay) - return; - - translate = translate || (keyboard_mode & 0x40) || xt_mode; - translate = translate || ((dev->flags & KBC_TYPE_MASK) == KBC_TYPE_PS2_2); - - for (i = 0; i < len; i++) { - if (translate) { - if (val[i] == 0xf0) { - or = 0x80; - continue; - } - send = nont_to_t[val[i]] | or; - if (or == 0x80) - or = 0; - } else - send = val[i]; - - add_data_kbd_queue(dev, 0, send); - } -} - - static void add_data_kbd(uint16_t val) { - atkbd_t *dev = SavedKbd; - int xt_mode = (keyboard_mode & 0x20) && ((dev->flags & KBC_TYPE_MASK) < KBC_TYPE_PS2_NOREF); - int translate = (keyboard_mode & 0x40); - uint8_t fake_shift[4]; - uint8_t num_lock = 0, shift_states = 0; - uint8_t kbc_ven = dev->flags & KBC_VEN_MASK; - - if (dev->reset_delay) - return; - - translate = translate || (keyboard_mode & 0x40) || xt_mode; - translate = translate || ((dev->flags & KBC_TYPE_MASK) == KBC_TYPE_PS2_2); + atkbc_dev_t *dev = SavedKbd; + uint8_t fake_shift[4]; + uint8_t num_lock = 0; + uint8_t shift_states = 0; keyboard_get_states(NULL, &num_lock, NULL); shift_states = keyboard_get_shift() & STATE_SHIFT_MASK; - /* Allow for scan code translation. */ - if (translate && (val == 0xf0)) { - kbd_log("ATkbd: translate is on, F0 prefix detected\n"); - sc_or = 0x80; - return; - } - - /* Skip break code if translated make code has bit 7 set. */ - if (translate && (sc_or == 0x80) && (val & 0x80)) { - kbd_log("ATkbd: translate is on, skipping scan code: %02X (original: F0 %02X)\n", nont_to_t[val], val); - sc_or = 0; - return; - } - - /* Test for T3100E 'Fn' key (Right Alt / Right Ctrl) */ - if ((dev != NULL) && (kbc_ven == KBC_VEN_TOSHIBA) && - (keyboard_recv(0xb8) || keyboard_recv(0x9d))) switch (val) { - case 0x4f: t3100e_notify_set(0x01); break; /* End */ - case 0x50: t3100e_notify_set(0x02); break; /* Down */ - case 0x51: t3100e_notify_set(0x03); break; /* PgDn */ - case 0x52: t3100e_notify_set(0x04); break; /* Ins */ - case 0x53: t3100e_notify_set(0x05); break; /* Del */ - case 0x54: t3100e_notify_set(0x06); break; /* SysRQ */ - case 0x45: t3100e_notify_set(0x07); break; /* NumLock */ - case 0x46: t3100e_notify_set(0x08); break; /* ScrLock */ - case 0x47: t3100e_notify_set(0x09); break; /* Home */ - case 0x48: t3100e_notify_set(0x0a); break; /* Up */ - case 0x49: t3100e_notify_set(0x0b); break; /* PgUp */ - case 0x4A: t3100e_notify_set(0x0c); break; /* Keypad -*/ - case 0x4B: t3100e_notify_set(0x0d); break; /* Left */ - case 0x4C: t3100e_notify_set(0x0e); break; /* KP 5 */ - case 0x4D: t3100e_notify_set(0x0f); break; /* Right */ - } - - kbd_log("ATkbd: translate is %s, ", translate ? "on" : "off"); - switch(val) { - case FAKE_LSHIFT_ON: - kbd_log("fake left shift on, scan code: "); - if (num_lock) { - if (shift_states) { - kbd_log("N/A (one or both shifts on)\n"); - break; - } else { - /* Num lock on and no shifts are pressed, send non-inverted fake shift. */ - switch(keyboard_mode & 0x02) { - case 1: - fake_shift[0] = 0xe0; fake_shift[1] = 0x2a; - add_data_vals(dev, fake_shift, 2); - break; - - case 2: - fake_shift[0] = 0xe0; fake_shift[1] = 0x12; - add_data_vals(dev, fake_shift, 2); - break; - - default: - kbd_log("N/A (scan code set %i)\n", keyboard_mode & 0x02); - break; - } - } - } else { - if (shift_states & STATE_LSHIFT) { - /* Num lock off and left shift pressed. */ - switch(keyboard_mode & 0x02) { - case 1: - fake_shift[0] = 0xe0; fake_shift[1] = 0xaa; - add_data_vals(dev, fake_shift, 2); - break; - - case 2: - fake_shift[0] = 0xe0; fake_shift[1] = 0xf0; fake_shift[2] = 0x12; - add_data_vals(dev, fake_shift, 3); - break; - - default: - kbd_log("N/A (scan code set %i)\n", keyboard_mode & 0x02); - break; - } - } - if (shift_states & STATE_RSHIFT) { - /* Num lock off and right shift pressed. */ - switch(keyboard_mode & 0x02) { - case 1: - fake_shift[0] = 0xe0; fake_shift[1] = 0xb6; - add_data_vals(dev, fake_shift, 2); - break; - - case 2: - fake_shift[0] = 0xe0; fake_shift[1] = 0xf0; fake_shift[2] = 0x59; - add_data_vals(dev, fake_shift, 3); - break; - - default: - kbd_log("N/A (scan code set %i)\n", keyboard_mode & 0x02); - break; - } - } - kbd_log(shift_states ? "" : "N/A (both shifts off)\n"); - } - break; - - case FAKE_LSHIFT_OFF: - kbd_log("fake left shift on, scan code: "); - if (num_lock) { - if (shift_states) { - kbd_log("N/A (one or both shifts on)\n"); - break; - } else { - /* Num lock on and no shifts are pressed, send non-inverted fake shift. */ - switch(keyboard_mode & 0x02) { - case 1: - fake_shift[0] = 0xe0; fake_shift[1] = 0xaa; - add_data_vals(dev, fake_shift, 2); - break; - - case 2: - fake_shift[0] = 0xe0; fake_shift[1] = 0xf0; fake_shift[2] = 0x12; - add_data_vals(dev, fake_shift, 3); - break; - - default: - kbd_log("N/A (scan code set %i)\n", keyboard_mode & 0x02); - break; - } - } - } else { - if (shift_states & STATE_LSHIFT) { - /* Num lock off and left shift pressed. */ - switch(keyboard_mode & 0x02) { - case 1: - fake_shift[0] = 0xe0; fake_shift[1] = 0x2a; - add_data_vals(dev, fake_shift, 2); - break; - - case 2: - fake_shift[0] = 0xe0; fake_shift[1] = 0x12; - add_data_vals(dev, fake_shift, 2); - break; - - default: - kbd_log("N/A (scan code set %i)\n", keyboard_mode & 0x02); - break; - } - } - if (shift_states & STATE_RSHIFT) { - /* Num lock off and right shift pressed. */ - switch(keyboard_mode & 0x02) { - case 1: - fake_shift[0] = 0xe0; fake_shift[1] = 0x36; - add_data_vals(dev, fake_shift, 2); - break; - - case 2: - fake_shift[0] = 0xe0; fake_shift[1] = 0x59; - add_data_vals(dev, fake_shift, 2); - break; - - default: - kbd_log("N/A (scan code set %i)\n", keyboard_mode & 0x02); - break; - } - } - kbd_log(shift_states ? "" : "N/A (both shifts off)\n"); - } - break; - - default: -#ifdef ENABLE_KEYBOARD_AT_LOG - kbd_log("scan code: "); - if (translate) { - kbd_log("%02X (original: ", (nont_to_t[val] | sc_or)); - if (sc_or == 0x80) - kbd_log("F0 "); - kbd_log("%02X)\n", val); - } else - kbd_log("%02X\n", val); -#endif - - add_data_kbd_queue(dev, 0, translate ? (nont_to_t[val] | sc_or) : val); - break; - } - - if (sc_or == 0x80) - sc_or = 0; -} - - -static void -write_output(atkbd_t *dev, uint8_t val) -{ - uint8_t old = dev->output_port; - kbd_log("ATkbc: write output port: %02X (old: %02X)\n", val, dev->output_port); - - uint8_t kbc_ven = dev->flags & KBC_VEN_MASK; - if ((kbc_ven != KBC_VEN_OLIVETTI) && ((kbc_ven == KBC_VEN_AMI) || ((dev->flags & KBC_TYPE_MASK) < KBC_TYPE_PS2_NOREF))) - val |= ((dev->mem[0] << 4) & 0x10); - - /*IRQ 12*/ - if ((old ^ val) & 0x20) { - if (val & 0x20) - picint(1 << 12); - else - picintc(1 << 12); - } - - /*IRQ 1*/ - if ((old ^ val) & 0x10) { - if (val & 0x10) - picint(1 << 1); - else - picintc(1 << 1); - } - - if ((old ^ val) & 0x02) { /*A20 enable change*/ - mem_a20_key = val & 0x02; - mem_a20_recalc(); - flushmmucache(); - } - - /* 0 holds the CPU in the RESET state, 1 releases it. To simplify this, - we just do everything on release. */ - if ((old ^ val) & 0x01) { /*Reset*/ - if (! (val & 0x01)) { /* Pin 0 selected. */ - /* Pin 0 selected. */ - kbd_log("write_output(): Pulse reset!\n"); - softresetx86(); /*Pulse reset!*/ - cpu_set_edx(); - flushmmucache(); - } - } - - /* Do this here to avoid an infinite reset loop. */ - dev->output_port = val; -} - - -static void -write_cmd(atkbd_t *dev, uint8_t val) -{ - uint8_t kbc_ven = dev->flags & KBC_VEN_MASK; - kbd_log("ATkbc: write command byte: %02X (old: %02X)\n", val, dev->mem[0]); - - if ((val & 1) && (dev->status & STAT_OFULL)) - dev->wantirq = 1; - if (!(val & 1) && dev->wantirq) - dev->wantirq = 0; - - /* PS/2 type 2 keyboard controllers always force the XLAT bit to 0. */ - if ((dev->flags & KBC_TYPE_MASK) == KBC_TYPE_PS2_2) { - val &= ~CCB_TRANSLATE; - dev->mem[0] &= ~CCB_TRANSLATE; - } - - /* Scan code translate ON/OFF. */ - keyboard_mode &= 0x93; - keyboard_mode |= (val & MODE_MASK); - - kbd_log("ATkbc: keyboard interrupt is now %s\n", (val & 0x01) ? "enabled" : "disabled"); - - /* ISA AT keyboard controllers use bit 5 for keyboard mode (1 = PC/XT, 2 = AT); - PS/2 (and EISA/PCI) keyboard controllers use it as the PS/2 mouse enable switch. - The AMIKEY firmware apparently uses this bit for something else. */ - if ((kbc_ven == KBC_VEN_AMI) || - ((dev->flags & KBC_TYPE_MASK) >= KBC_TYPE_PS2_NOREF)) { - keyboard_mode &= ~CCB_PCMODE; - - kbd_log("ATkbc: mouse interrupt is now %s\n", (val & 0x02) ? "enabled" : "disabled"); - } - - if ((kbc_ven == KBC_VEN_AMI) || ((dev->flags & KBC_TYPE_MASK) < KBC_TYPE_PS2_NOREF)) { - /* Update the output port to mirror the KBD DIS and AUX DIS bits, if active. */ - write_output(dev, dev->output_port); - } - - kbd_log("Command byte now: %02X (%02X)\n", dev->mem[0], val); - - dev->status = (dev->status & ~STAT_SYSFLAG) | (val & STAT_SYSFLAG); -} - - -static void -pulse_output(atkbd_t *dev, uint8_t mask) -{ - if (mask != 0x0f) { - dev->old_output_port = dev->output_port & ~(0xf0 | mask); - kbd_log("pulse_output(): Output port now: %02X\n", dev->output_port & (0xf0 | mask)); - write_output(dev, dev->output_port & (0xf0 | mask)); - timer_set_delay_u64(&dev->pulse_cb, 6ULL * TIMER_USEC); - } -} - - -static void -pulse_poll(void *priv) -{ - atkbd_t *dev = (atkbd_t *)priv; - - kbd_log("pulse_poll(): Output port now: %02X\n", dev->output_port | dev->old_output_port); - write_output(dev, dev->output_port | dev->old_output_port); -} - - -static void -set_enable_kbd(atkbd_t *dev, uint8_t enable) -{ - dev->mem[0] &= 0xef; - dev->mem[0] |= (enable ? 0x00 : 0x10); -} - - -static void -set_enable_mouse(atkbd_t *dev, uint8_t enable) -{ - dev->mem[0] &= 0xdf; - dev->mem[0] |= (enable ? 0x00 : 0x20); -} - - -static uint8_t -write64_generic(void *priv, uint8_t val) -{ - atkbd_t *dev = (atkbd_t *)priv; - uint8_t current_drive, fixed_bits; - uint8_t kbc_ven = 0x0; - kbc_ven = dev->flags & KBC_VEN_MASK; - - switch (val) { - case 0xa4: /* check if password installed */ - if ((dev->flags & KBC_TYPE_MASK) >= KBC_TYPE_PS2_NOREF) { - kbd_log("ATkbc: check if password installed\n"); - add_data(dev, 0xf1); - return 0; - } - break; + case FAKE_LSHIFT_ON: + keyboard_at_log("%s: Fake left shift on, scan code: ", dev->name); + if (num_lock) { + if (shift_states) { + keyboard_at_log("N/A (one or both shifts on)\n"); + break; + } else { + /* Num lock on and no shifts are pressed, send non-inverted fake shift. */ + switch (keyboard_mode & 0x02) { + case 1: + fake_shift[0] = 0xe0; + fake_shift[1] = 0x2a; + add_data_vals(dev, fake_shift, 2); + break; - case 0xa7: /* disable mouse port */ - if ((dev->flags & KBC_TYPE_MASK) >= KBC_TYPE_PS2_NOREF) { - kbd_log("ATkbc: disable mouse port\n"); - set_enable_mouse(dev, 0); - return 0; - } - break; + case 2: + fake_shift[0] = 0xe0; + fake_shift[1] = 0x12; + add_data_vals(dev, fake_shift, 2); + break; - case 0xa8: /*Enable mouse port*/ - if ((dev->flags & KBC_TYPE_MASK) >= KBC_TYPE_PS2_NOREF) { - kbd_log("ATkbc: enable mouse port\n"); - set_enable_mouse(dev, 1); - return 0; - } - break; + default: + keyboard_at_log("N/A (scan code set %i)\n", keyboard_mode & 0x02); + break; + } + } + } else { + if (shift_states & STATE_LSHIFT) { + /* Num lock off and left shift pressed. */ + switch (keyboard_mode & 0x02) { + case 1: + fake_shift[0] = 0xe0; + fake_shift[1] = 0xaa; + add_data_vals(dev, fake_shift, 2); + break; - case 0xa9: /*Test mouse port*/ - kbd_log("ATkbc: test mouse port\n"); - if ((dev->flags & KBC_TYPE_MASK) >= KBC_TYPE_PS2_NOREF) { - add_data(dev, 0x00); /* no error, this is testing the channel 2 interface */ - return 0; - } - break; + case 2: + fake_shift[0] = 0xe0; + fake_shift[1] = 0xf0; + fake_shift[2] = 0x12; + add_data_vals(dev, fake_shift, 3); + break; - case 0xaf: /* read keyboard version */ - kbd_log("ATkbc: read keyboard version\n"); - add_data(dev, 0x00); - return 0; + default: + keyboard_at_log("N/A (scan code set %i)\n", keyboard_mode & 0x02); + break; + } + } + if (shift_states & STATE_RSHIFT) { + /* Num lock off and right shift pressed. */ + switch (keyboard_mode & 0x02) { + case 1: + fake_shift[0] = 0xe0; + fake_shift[1] = 0xb6; + add_data_vals(dev, fake_shift, 2); + break; - case 0xc0: /* read input port */ - kbd_log("ATkbc: read input port\n"); - fixed_bits = 4; - /* The SMM handlers of Intel AMI Pentium BIOS'es expect bit 6 to be set. */ - if (kbc_ven == KBC_VEN_INTEL_AMI) - fixed_bits |= 0x40; - if (kbc_ven == KBC_VEN_IBM_PS1) { - current_drive = fdc_get_current_drive(); - add_to_kbc_queue_front(dev, dev->input_port | fixed_bits | (fdd_is_525(current_drive) ? 0x40 : 0x00), - 0, 0x00); - dev->input_port = ((dev->input_port + 1) & 3) | - (dev->input_port & 0xfc) | - (fdd_is_525(current_drive) ? 0x40 : 0x00); - } else if (kbc_ven == KBC_VEN_NCR) { - /* switch settings - * bit 7: keyboard disable - * bit 6: display type (0 color, 1 mono) - * bit 5: power-on default speed (0 high, 1 low) - * bit 4: sense RAM size (0 unsupported, 1 512k on system board) - * bit 3: coprocessor detect - * bit 2: unused - * bit 1: high/auto speed - * bit 0: dma mode - */ - add_to_kbc_queue_front(dev, (dev->input_port | fixed_bits | (video_is_mda() ? 0x40 : 0x00) | (hasfpu ? 0x08 : 0x00)) & 0xdf, - 0, 0x00); - dev->input_port = ((dev->input_port + 1) & 3) | - (dev->input_port & 0xfc); - } else { - if (((dev->flags & KBC_TYPE_MASK) >= KBC_TYPE_PS2_NOREF) && - ((dev->flags & KBC_VEN_MASK) != KBC_VEN_INTEL_AMI)) -#if 0 - add_to_kbc_queue_front(dev, (dev->input_port | fixed_bits) & - (((dev->flags & KBC_VEN_MASK) == KBC_VEN_ACER) ? 0xeb : 0xef), 0, 0x00); -#else - add_to_kbc_queue_front(dev, ((dev->input_port | fixed_bits) & 0xf0) | (((dev->flags & KBC_VEN_MASK) == KBC_VEN_ACER) ? 0x08 : 0x0c), 0, 0x00); -#endif - else - add_to_kbc_queue_front(dev, dev->input_port | fixed_bits, 0, 0x00); - dev->input_port = ((dev->input_port + 1) & 3) | - (dev->input_port & 0xfc); - } - return 0; + case 2: + fake_shift[0] = 0xe0; + fake_shift[1] = 0xf0; + fake_shift[2] = 0x59; + add_data_vals(dev, fake_shift, 3); + break; - case 0xd3: /* write mouse output buffer */ - if ((dev->flags & KBC_TYPE_MASK) >= KBC_TYPE_PS2_NOREF) { - kbd_log("ATkbc: write mouse output buffer\n"); - dev->want60 = 1; - return 0; - } - break; + default: + keyboard_at_log("N/A (scan code set %i)\n", keyboard_mode & 0x02); + break; + } + } + keyboard_at_log(shift_states ? "" : "N/A (both shifts off)\n"); + } + break; - case 0xd4: /* write to mouse */ - kbd_log("ATkbc: write to mouse\n"); - dev->want60 = 1; - return 0; + case FAKE_LSHIFT_OFF: + keyboard_at_log("%s: Fake left shift on, scan code: ", dev->name); + if (num_lock) { + if (shift_states) { + keyboard_at_log("N/A (one or both shifts on)\n"); + break; + } else { + /* Num lock on and no shifts are pressed, send non-inverted fake shift. */ + switch (keyboard_mode & 0x02) { + case 1: + fake_shift[0] = 0xe0; + fake_shift[1] = 0xaa; + add_data_vals(dev, fake_shift, 2); + break; - case 0xf0: case 0xf1: case 0xf2: case 0xf3: - case 0xf4: case 0xf5: case 0xf6: case 0xf7: - case 0xf8: case 0xf9: case 0xfa: case 0xfb: - case 0xfc: case 0xfd: case 0xfe: case 0xff: - kbd_log("ATkbc: pulse %01X\n", val & 0x0f); - pulse_output(dev, val & 0x0f); - return 0; + case 2: + fake_shift[0] = 0xe0; + fake_shift[1] = 0xf0; + fake_shift[2] = 0x12; + add_data_vals(dev, fake_shift, 3); + break; + + default: + keyboard_at_log("N/A (scan code set %i)\n", keyboard_mode & 0x02); + break; + } + } + } else { + if (shift_states & STATE_LSHIFT) { + /* Num lock off and left shift pressed. */ + switch (keyboard_mode & 0x02) { + case 1: + fake_shift[0] = 0xe0; + fake_shift[1] = 0x2a; + add_data_vals(dev, fake_shift, 2); + break; + + case 2: + fake_shift[0] = 0xe0; + fake_shift[1] = 0x12; + add_data_vals(dev, fake_shift, 2); + break; + + default: + keyboard_at_log("N/A (scan code set %i)\n", keyboard_mode & 0x02); + break; + } + } + if (shift_states & STATE_RSHIFT) { + /* Num lock off and right shift pressed. */ + switch (keyboard_mode & 0x02) { + case 1: + fake_shift[0] = 0xe0; + fake_shift[1] = 0x36; + add_data_vals(dev, fake_shift, 2); + break; + + case 2: + fake_shift[0] = 0xe0; + fake_shift[1] = 0x59; + add_data_vals(dev, fake_shift, 2); + break; + + default: + keyboard_at_log("N/A (scan code set %i)\n", keyboard_mode & 0x02); + break; + } + } + keyboard_at_log(shift_states ? "" : "N/A (both shifts off)\n"); + } + break; + + default: + kbc_at_dev_queue_add(dev, val, 1); + break; } - - kbd_log("ATkbc: bad command %02X\n", val); - return 1; } - -static uint8_t -write60_ami(void *priv, uint8_t val) +void +keyboard_at_clear_data(void *priv) { - atkbd_t *dev = (atkbd_t *)priv; + atkbc_dev_t *dev = (atkbc_dev_t *) priv; - switch(dev->command) { - /* 0x40 - 0x5F are aliases for 0x60-0x7F */ - case 0x40: case 0x41: case 0x42: case 0x43: - case 0x44: case 0x45: case 0x46: case 0x47: - case 0x48: case 0x49: case 0x4a: case 0x4b: - case 0x4c: case 0x4d: case 0x4e: case 0x4f: - case 0x50: case 0x51: case 0x52: case 0x53: - case 0x54: case 0x55: case 0x56: case 0x57: - case 0x58: case 0x59: case 0x5a: case 0x5b: - case 0x5c: case 0x5d: case 0x5e: case 0x5f: - kbd_log("ATkbc: AMI - alias write to %08X\n", dev->command); - dev->mem[dev->command & 0x1f] = val; - if (dev->command == 0x60) - write_cmd(dev, val); - return 0; - - case 0xaf: /* set extended controller RAM */ - kbd_log("ATkbc: AMI - set extended controller RAM\n"); - if (dev->secr_phase == 1) { - dev->mem_addr = val; - dev->want60 = 1; - dev->secr_phase = 2; - } else if (dev->secr_phase == 2) { - dev->mem[dev->mem_addr] = val; - dev->secr_phase = 0; - } - return 0; - - case 0xc1: - kbd_log("ATkbc: AMI MegaKey - write %02X to input port\n", val); - dev->input_port = val; - return 0; - - case 0xcb: /* set keyboard mode */ - kbd_log("ATkbc: AMI - set keyboard mode\n"); - dev->ami_flags = val; - return 0; - } - - return 1; + dev->flags &= ~FLAG_CTRLDAT; } - -static uint8_t -write64_ami(void *priv, uint8_t val) -{ - atkbd_t *dev = (atkbd_t *)priv; - - switch (val) { - case 0x00: case 0x01: case 0x02: case 0x03: - case 0x04: case 0x05: case 0x06: case 0x07: - case 0x08: case 0x09: case 0x0a: case 0x0b: - case 0x0c: case 0x0d: case 0x0e: case 0x0f: - case 0x10: case 0x11: case 0x12: case 0x13: - case 0x14: case 0x15: case 0x16: case 0x17: - case 0x18: case 0x19: case 0x1a: case 0x1b: - case 0x1c: case 0x1d: case 0x1e: case 0x1f: - kbd_log("ATkbc: AMI - alias read from %08X\n", val); - add_data(dev, dev->mem[val]); - return 0; - - case 0x40: case 0x41: case 0x42: case 0x43: - case 0x44: case 0x45: case 0x46: case 0x47: - case 0x48: case 0x49: case 0x4a: case 0x4b: - case 0x4c: case 0x4d: case 0x4e: case 0x4f: - case 0x50: case 0x51: case 0x52: case 0x53: - case 0x54: case 0x55: case 0x56: case 0x57: - case 0x58: case 0x59: case 0x5a: case 0x5b: - case 0x5c: case 0x5d: case 0x5e: case 0x5f: - kbd_log("ATkbc: AMI - alias write to %08X\n", dev->command); - dev->want60 = 1; - return 0; - - case 0xa0: /* copyright message */ - add_data(dev, 0x28); - add_data(dev, 0x00); - break; - - case 0xa1: /* get controller version */ - kbd_log("ATkbc: AMI - get controller version\n"); - add_data(dev, 'H'); - return 0; - - case 0xa2: /* clear keyboard controller lines P22/P23 */ - if ((dev->flags & KBC_TYPE_MASK) < KBC_TYPE_PS2_NOREF) { - kbd_log("ATkbc: AMI - clear KBC lines P22 and P23\n"); - write_output(dev, dev->output_port & 0xf3); - add_data(dev, 0x00); - return 0; - } - break; - - case 0xa3: /* set keyboard controller lines P22/P23 */ - if ((dev->flags & KBC_TYPE_MASK) < KBC_TYPE_PS2_NOREF) { - kbd_log("ATkbc: AMI - set KBC lines P22 and P23\n"); - write_output(dev, dev->output_port | 0x0c); - add_data(dev, 0x00); - return 0; - } - break; - - case 0xa4: /* write clock = low */ - if ((dev->flags & KBC_TYPE_MASK) < KBC_TYPE_PS2_NOREF) { - kbd_log("ATkbc: AMI - write clock = low\n"); - dev->ami_stat &= 0xfe; - return 0; - } - break; - - case 0xa5: /* write clock = high */ - if ((dev->flags & KBC_TYPE_MASK) < KBC_TYPE_PS2_NOREF) { - kbd_log("ATkbc: AMI - write clock = high\n"); - dev->ami_stat |= 0x01; - return 0; - } - break; - - case 0xa6: /* read clock */ - if ((dev->flags & KBC_TYPE_MASK) < KBC_TYPE_PS2_NOREF) { - kbd_log("ATkbc: AMI - read clock\n"); - add_data(dev, !!(dev->ami_stat & 1)); - return 0; - } - break; - - case 0xa7: /* write cache bad */ - if ((dev->flags & KBC_TYPE_MASK) < KBC_TYPE_PS2_NOREF) { - kbd_log("ATkbc: AMI - write cache bad\n"); - dev->ami_stat &= 0xfd; - return 0; - } - break; - - case 0xa8: /* write cache good */ - if ((dev->flags & KBC_TYPE_MASK) < KBC_TYPE_PS2_NOREF) { - kbd_log("ATkbc: AMI - write cache good\n"); - dev->ami_stat |= 0x02; - return 0; - } - break; - - case 0xa9: /* read cache */ - if ((dev->flags & KBC_TYPE_MASK) < KBC_TYPE_PS2_NOREF) { - kbd_log("ATkbc: AMI - read cache\n"); - add_data(dev, !!(dev->ami_stat & 2)); - return 0; - } - break; - - case 0xaf: /* set extended controller RAM */ - kbd_log("ATkbc: set extended controller RAM\n"); - dev->want60 = 1; - dev->secr_phase = 1; - return 0; - - case 0xb0: case 0xb1: case 0xb2: case 0xb3: - /* set KBC lines P10-P13 (input port bits 0-3) low */ - kbd_log("ATkbc: set KBC lines P10-P13 (input port bits 0-3) low\n"); - if (!(dev->flags & DEVICE_PCI) || (val > 0xb1)) - dev->input_port &= ~(1 << (val & 0x03)); - add_data(dev, 0x00); - return 0; - - case 0xb4: case 0xb5: - /* set KBC lines P22-P23 (output port bits 2-3) low */ - kbd_log("ATkbc: set KBC lines P22-P23 (output port bits 2-3) low\n"); - if (! (dev->flags & DEVICE_PCI)) - write_output(dev, dev->output_port & ~(4 << (val & 0x01))); - add_data(dev, 0x00); - return 0; - - case 0xb8: case 0xb9: case 0xba: case 0xbb: - /* set KBC lines P10-P13 (input port bits 0-3) high */ - kbd_log("ATkbc: set KBC lines P10-P13 (input port bits 0-3) high\n"); - if (!(dev->flags & DEVICE_PCI) || (val > 0xb9)) { - dev->input_port |= (1 << (val & 0x03)); - add_data(dev, 0x00); - } - return 0; - - case 0xbc: case 0xbd: - /* set KBC lines P22-P23 (output port bits 2-3) high */ - kbd_log("ATkbc: set KBC lines P22-P23 (output port bits 2-3) high\n"); - if (! (dev->flags & DEVICE_PCI)) - write_output(dev, dev->output_port | (4 << (val & 0x01))); - add_data(dev, 0x00); - return 0; - - case 0xc1: /* write input port */ - kbd_log("ATkbc: AMI MegaKey - write input port\n"); - dev->want60 = 1; - return 0; - - case 0xc4: - /* set KBC line P14 low */ - kbd_log("ATkbc: set KBC line P14 (input port bit 4) low\n"); - dev->input_port &= 0xef; - add_data(dev, 0x00); - return 0; - case 0xc5: - /* set KBC line P15 low */ - kbd_log("ATkbc: set KBC line P15 (input port bit 5) low\n"); - dev->input_port &= 0xdf; - add_data(dev, 0x00); - return 0; - - case 0xc8: - /* - * unblock KBC lines P22/P23 - * (allow command D1 to change bits 2/3 of the output port) - */ - kbd_log("ATkbc: AMI - unblock KBC lines P22 and P23\n"); - dev->output_locked = 1; - return 0; - - case 0xc9: - /* - * block KBC lines P22/P23 - * (disallow command D1 from changing bits 2/3 of the port) - */ - kbd_log("ATkbc: AMI - block KBC lines P22 and P23\n"); - dev->output_locked = 1; - return 0; - - case 0xcc: - /* set KBC line P14 high */ - kbd_log("ATkbc: set KBC line P14 (input port bit 4) high\n"); - dev->input_port |= 0x10; - add_data(dev, 0x00); - return 0; - case 0xcd: - /* set KBC line P15 high */ - kbd_log("ATkbc: set KBC line P15 (input port bit 5) high\n"); - dev->input_port |= 0x20; - add_data(dev, 0x00); - return 0; - - case 0xef: /* ??? - sent by AMI486 */ - kbd_log("ATkbc: ??? - sent by AMI486\n"); - return 0; - } - - return write64_generic(dev, val); -} - - -static uint8_t -write64_ibm_mca(void *priv, uint8_t val) -{ - atkbd_t *dev = (atkbd_t *)priv; - - switch (val) { - case 0xc1: /*Copy bits 0 to 3 of input port to status bits 4 to 7*/ - kbd_log("ATkbc: copy bits 0 to 3 of input port to status bits 4 to 7\n"); - dev->status &= 0x0f; - dev->status |= ((((dev->input_port & 0xfc) | 0x84) & 0x0f) << 4); - return 0; - - case 0xc2: /*Copy bits 4 to 7 of input port to status bits 4 to 7*/ - kbd_log("ATkbc: copy bits 4 to 7 of input port to status bits 4 to 7\n"); - dev->status &= 0x0f; - dev->status |= (((dev->input_port & 0xfc) | 0x84) & 0xf0); - return 0; - - case 0xaf: - kbd_log("ATkbc: bad KBC command AF\n"); - return 1; - - case 0xf0: case 0xf1: case 0xf2: case 0xf3: - case 0xf4: case 0xf5: case 0xf6: case 0xf7: - case 0xf8: case 0xf9: case 0xfa: case 0xfb: - case 0xfc: case 0xfd: case 0xfe: case 0xff: - kbd_log("ATkbc: pulse: %01X\n", (val & 0x03) | 0x0c); - pulse_output(dev, (val & 0x03) | 0x0c); - return 0; - } - - return write64_generic(dev, val); -} - - -static uint8_t -write60_quadtel(void *priv, uint8_t val) -{ - atkbd_t *dev = (atkbd_t *)priv; - - switch(dev->command) { - case 0xcf: /*??? - sent by MegaPC BIOS*/ - kbd_log("ATkbc: ??? - sent by MegaPC BIOS\n"); - return 0; - } - - return 1; -} - -static uint8_t -write64_olivetti(void *priv, uint8_t val) -{ - atkbd_t *dev = (atkbd_t *)priv; - - switch (val) { - case 0x80: /* Olivetti-specific command */ - /* - * bit 7: bus expansion board present (M300) / keyboard unlocked (M290) - * bits 4-6: ??? - * bit 3: fast ram check (if inactive keyboard works erratically) - * bit 2: keyboard fuse present - * bits 0-1: ??? - */ - add_to_kbc_queue_front(dev, (0x0c | ((is386) ? 0x00 : 0x80)) & 0xdf, 0, 0x00); - dev->input_port = ((dev->input_port + 1) & 3) | - (dev->input_port & 0xfc); - return 0; - } - - return write64_generic(dev, val); -} - - -static uint8_t -write64_quadtel(void *priv, uint8_t val) -{ - atkbd_t *dev = (atkbd_t *)priv; - - switch (val) { - case 0xaf: - kbd_log("ATkbc: bad KBC command AF\n"); - return 1; - - case 0xcf: /*??? - sent by MegaPC BIOS*/ - kbd_log("ATkbc: ??? - sent by MegaPC BIOS\n"); - dev->want60 = 1; - return 0; - } - - return write64_generic(dev, val); -} - - -static uint8_t -write60_toshiba(void *priv, uint8_t val) -{ - atkbd_t *dev = (atkbd_t *)priv; - - switch(dev->command) { - case 0xb6: /* T3100e - set color/mono switch */ - kbd_log("ATkbc: T3100e - set color/mono switch\n"); - t3100e_mono_set(val); - return 0; - } - - return 1; -} - - -static uint8_t -write64_toshiba(void *priv, uint8_t val) -{ - atkbd_t *dev = (atkbd_t *)priv; - - switch (val) { - case 0xaf: - kbd_log("ATkbc: bad KBC command AF\n"); - return 1; - - case 0xb0: /* T3100e: Turbo on */ - kbd_log("ATkbc: T3100e: Turbo on\n"); - t3100e_turbo_set(1); - return 0; - - case 0xb1: /* T3100e: Turbo off */ - kbd_log("ATkbc: T3100e: Turbo off\n"); - t3100e_turbo_set(0); - return 0; - - case 0xb2: /* T3100e: Select external display */ - kbd_log("ATkbc: T3100e: Select external display\n"); - t3100e_display_set(0x00); - return 0; - - case 0xb3: /* T3100e: Select internal display */ - kbd_log("ATkbc: T3100e: Select internal display\n"); - t3100e_display_set(0x01); - return 0; - - case 0xb4: /* T3100e: Get configuration / status */ - kbd_log("ATkbc: T3100e: Get configuration / status\n"); - add_data(dev, t3100e_config_get()); - return 0; - - case 0xb5: /* T3100e: Get colour / mono byte */ - kbd_log("ATkbc: T3100e: Get colour / mono byte\n"); - add_data(dev, t3100e_mono_get()); - return 0; - - case 0xb6: /* T3100e: Set colour / mono byte */ - kbd_log("ATkbc: T3100e: Set colour / mono byte\n"); - dev->want60 = 1; - return 0; - - case 0xb7: /* T3100e: Emulate PS/2 keyboard */ - case 0xb8: /* T3100e: Emulate AT keyboard */ - dev->flags &= ~KBC_TYPE_MASK; - if (val == 0xb7) { - kbd_log("ATkbc: T3100e: Emulate PS/2 keyboard\n"); - dev->flags |= KBC_TYPE_PS2_NOREF; - } else { - kbd_log("ATkbc: T3100e: Emulate AT keyboard\n"); - dev->flags |= KBC_TYPE_ISA; - } - return 0; - - case 0xbb: /* T3100e: Read 'Fn' key. - Return it for right Ctrl and right Alt; on the real - T3100e, these keystrokes could only be generated - using 'Fn'. */ - kbd_log("ATkbc: T3100e: Read 'Fn' key\n"); - if (keyboard_recv(0xb8) || /* Right Alt */ - keyboard_recv(0x9d)) /* Right Ctrl */ - add_data(dev, 0x04); - else add_data(dev, 0x00); - return 0; - - case 0xbc: /* T3100e: Reset Fn+Key notification */ - kbd_log("ATkbc: T3100e: Reset Fn+Key notification\n"); - t3100e_notify_set(0x00); - return 0; - - case 0xc0: /*Read input port*/ - kbd_log("ATkbc: read input port\n"); - - /* The T3100e returns all bits set except bit 6 which - * is set by t3100e_mono_set() */ - dev->input_port = (t3100e_mono_get() & 1) ? 0xff : 0xbf; - add_data(dev, dev->input_port); - return 0; - - } - - return write64_generic(dev, val); -} - - static void -kbd_write(uint16_t port, uint8_t val, void *priv) +keyboard_at_set_defaults(atkbc_dev_t *dev) { - atkbd_t *dev = (atkbd_t *)priv; - int i = 0, bad = 1; - uint8_t mask, kbc_ven = 0x0; - kbc_ven = dev->flags & KBC_VEN_MASK; - - switch (port) { - case 0x60: - dev->status &= ~STAT_CD; - if (dev->want60) { - /* Write data to controller. */ - dev->want60 = 0; - - switch (dev->command) { - case 0x60: case 0x61: case 0x62: case 0x63: - case 0x64: case 0x65: case 0x66: case 0x67: - case 0x68: case 0x69: case 0x6a: case 0x6b: - case 0x6c: case 0x6d: case 0x6e: case 0x6f: - case 0x70: case 0x71: case 0x72: case 0x73: - case 0x74: case 0x75: case 0x76: case 0x77: - case 0x78: case 0x79: case 0x7a: case 0x7b: - case 0x7c: case 0x7d: case 0x7e: case 0x7f: - dev->mem[dev->command & 0x1f] = val; - if (dev->command == 0x60) - write_cmd(dev, val); - break; - - case 0xd1: /* write output port */ - kbd_log("ATkbc: write output port\n"); - if (dev->output_locked) { - /*If keyboard controller lines P22-P23 are blocked, - we force them to remain unchanged.*/ - val &= ~0x0c; - val |= (dev->output_port & 0x0c); - } - write_output(dev, val); - break; - - case 0xd2: /* write to keyboard output buffer */ - kbd_log("ATkbc: write to keyboard output buffer\n"); - add_to_kbc_queue_front(dev, val, 0, 0x00); - break; - - case 0xd3: /* write to mouse output buffer */ - kbd_log("ATkbc: write to mouse output buffer\n"); - if (mouse_write && ((dev->flags & KBC_TYPE_MASK) >= KBC_TYPE_PS2_NOREF)) - keyboard_at_adddata_mouse(val); - break; - - case 0xd4: /* write to mouse */ - kbd_log("ATkbc: write to mouse (%02X)\n", val); - - if (val == 0xbb) - break; - - if ((dev->flags & KBC_TYPE_MASK) >= KBC_TYPE_PS2_NOREF) { - set_enable_mouse(dev, 1); - if (mouse_write) - mouse_write(val, mouse_p); - else - add_to_kbc_queue_front(dev, 0xfe, 2, 0x40); - } - break; - - default: - /* - * Run the vendor-specific handler - * if we have one. Otherwise, or if - * it returns an error, log a bad - * controller command. - */ - if (dev->write60_ven) - bad = dev->write60_ven(dev, val); - - if (bad) { - kbd_log("ATkbc: bad controller command %02x data %02x\n", dev->command, val); - add_data_kbd(0xfe); - } - } - } else { - /* Write data to keyboard. */ - dev->mem[0] &= ~0x10; - - if (dev->key_wantdata) { - dev->key_wantdata = 0; - - /* - * Several system BIOSes and OS device drivers - * mess up with this, and repeat the command - * code many times. Fun! - */ - if (val == dev->key_command) { - /* Respond NAK and ignore it. */ - add_data_kbd(0xfe); - dev->key_command = 0x00; - break; - } - - switch (dev->key_command) { - case 0xed: /* set/reset LEDs */ - add_data_kbd_direct(dev, 0xfa); - kbd_log("ATkbd: set LEDs [%02x]\n", val); - break; - - case 0xf0: /* get/set scancode set */ - add_data_kbd_direct(dev, 0xfa); - if (val == 0) { - kbd_log("Get scan code set: %02X\n", keyboard_mode & 3); - add_data_kbd_direct(dev, keyboard_mode & 3); - } else { - if ((val <= 3) && (val != 1)) { - keyboard_mode &= 0xfc; - keyboard_mode |= (val & 3); - kbd_log("Scan code set now: %02X\n", val); - } - set_scancode_map(dev); - } - break; - - case 0xf3: /* set typematic rate/delay */ - add_data_kbd_direct(dev, 0xfa); - break; - - default: - kbd_log("ATkbd: bad keyboard 0060 write %02X command %02X\n", val, dev->key_command); - add_data_kbd_direct(dev, 0xfe); - break; - } - - /* Keyboard command is now done. */ - dev->key_command = 0x00; - } else { - /* No keyboard command in progress. */ - dev->key_command = 0x00; - - set_enable_kbd(dev, 1); - - switch (val) { - case 0x00: - kbd_log("ATkbd: command 00\n"); - add_data_kbd_direct(dev, 0xfa); - break; - - case 0x05: /*??? - sent by NT 4.0*/ - kbd_log("ATkbd: command 05 (NT 4.0)\n"); - add_data_kbd_direct(dev, 0xfe); - break; - - /* Sent by Pentium-era AMI BIOS'es.*/ - case 0x71: case 0x82: - kbd_log("ATkbd: Pentium-era AMI BIOS command %02X\n", val); - break; - - case 0xed: /* set/reset LEDs */ - kbd_log("ATkbd: set/reset leds\n"); - add_data_kbd_direct(dev, 0xfa); - - dev->key_wantdata = 1; - break; - - case 0xee: /* diagnostic echo */ - kbd_log("ATkbd: ECHO\n"); - add_data_kbd_direct(dev, 0xee); - break; - - case 0xef: /* NOP (reserved for future use) */ - kbd_log("ATkbd: NOP\n"); - break; - - case 0xf0: /* get/set scan code set */ - kbd_log("ATkbd: scan code set\n"); - add_data_kbd_direct(dev, 0xfa); - dev->key_wantdata = 1; - break; - - case 0xf2: /* read ID */ - /* Fixed as translation will be done in add_data_kbd(). */ - kbd_log("ATkbd: read keyboard id\n"); - /* TODO: After keyboard type selection is implemented, make this - return the correct keyboard ID for the selected type. */ - add_data_kbd_direct(dev, 0xfa); - add_data_kbd_direct(dev, 0xab); - add_data_kbd_direct(dev, 0x83); - break; - - case 0xf3: /* set typematic rate/delay */ - kbd_log("ATkbd: set typematic rate/delay\n"); - add_data_kbd_direct(dev, 0xfa); - dev->key_wantdata = 1; - break; - - case 0xf4: /* enable keyboard */ - kbd_log("ATkbd: enable keyboard\n"); - add_data_kbd_direct(dev, 0xfa); - keyboard_scan = 1; - break; - - case 0xf5: /* set defaults and disable keyboard */ - case 0xf6: /* set defaults */ - kbd_log("ATkbd: set defaults%s\n", (val == 0xf6) ? "" : " and disable keyboard"); - keyboard_scan = (val == 0xf6); - kbd_log("val = %02X, keyboard_scan = %i, dev->mem[0] = %02X\n", - val, keyboard_scan, dev->mem[0]); - add_data_kbd_direct(dev, 0xfa); - - keyboard_set3_all_break = 0; - keyboard_set3_all_repeat = 0; - memset(keyboard_set3_flags, 0, 512); - keyboard_mode = (keyboard_mode & 0xfc) | 0x02; - set_scancode_map(dev); - break; - - case 0xf7: /* set all keys to repeat */ - kbd_log("ATkbd: set all keys to repeat\n"); - add_data_kbd_direct(dev, 0xfa); - keyboard_set3_all_break = 1; - break; - - case 0xf8: /* set all keys to give make/break codes */ - kbd_log("ATkbd: set all keys to give make/break codes\n"); - add_data_kbd_direct(dev, 0xfa); - keyboard_set3_all_break = 1; - break; - - case 0xf9: /* set all keys to give make codes only */ - kbd_log("ATkbd: set all keys to give make codes only\n"); - add_data_kbd_direct(dev, 0xfa); - keyboard_set3_all_break = 0; - break; - - case 0xfa: /* set all keys to repeat and give make/break codes */ - kbd_log("ATkbd: set all keys to repeat and give make/break codes\n"); - add_data_kbd_direct(dev, 0xfa); - keyboard_set3_all_repeat = 1; - keyboard_set3_all_break = 1; - break; - - case 0xfe: /* resend last scan code */ - kbd_log("ATkbd: reset last scan code\n"); - add_data_kbd_raw(dev, kbd_last_scan_code); - break; - - case 0xff: /* reset */ - kbd_log("ATkbd: kbd reset\n"); - kbc_queue_reset(1); - kbd_last_scan_code = 0x00; - add_data_kbd_direct(dev, 0xfa); - - /* Set scan code set to 2. */ - keyboard_mode = (keyboard_mode & 0xfc) | 0x02; - set_scancode_map(dev); - - dev->reset_delay = RESET_DELAY_TIME; - break; - - default: - kbd_log("ATkbd: bad keyboard command %02X\n", val); - add_data_kbd_direct(dev, 0xfe); - } - - /* If command needs data, remember command. */ - if (dev->key_wantdata == 1) - dev->key_command = val; - } - } - break; - - case 0x64: - /* Controller command. */ - dev->want60 = 0; - dev->status |= STAT_CD; - - switch (val) { - /* Read data from KBC memory. */ - case 0x20: case 0x21: case 0x22: case 0x23: - case 0x24: case 0x25: case 0x26: case 0x27: - case 0x28: case 0x29: case 0x2a: case 0x2b: - case 0x2c: case 0x2d: case 0x2e: case 0x2f: - case 0x30: case 0x31: case 0x32: case 0x33: - case 0x34: case 0x35: case 0x36: case 0x37: - case 0x38: case 0x39: case 0x3a: case 0x3b: - case 0x3c: case 0x3d: case 0x3e: case 0x3f: - add_data(dev, dev->mem[val & 0x1f]); - break; - - /* Write data to KBC memory. */ - case 0x60: case 0x61: case 0x62: case 0x63: - case 0x64: case 0x65: case 0x66: case 0x67: - case 0x68: case 0x69: case 0x6a: case 0x6b: - case 0x6c: case 0x6d: case 0x6e: case 0x6f: - case 0x70: case 0x71: case 0x72: case 0x73: - case 0x74: case 0x75: case 0x76: case 0x77: - case 0x78: case 0x79: case 0x7a: case 0x7b: - case 0x7c: case 0x7d: case 0x7e: case 0x7f: - dev->want60 = 1; - break; - - case 0xaa: /* self-test */ - kbd_log("ATkbc: self-test\n"); - if ((kbc_ven == KBC_VEN_TOSHIBA) || (kbc_ven == KBC_VEN_SAMSUNG)) - dev->status |= STAT_IFULL; - write_output(dev, ((dev->flags & KBC_TYPE_MASK) >= KBC_TYPE_PS2_NOREF) ? 0x4b : 0xcf); - - /* Always reinitialize all queues - the real hardware pulls keyboard and mouse - clocks high, which stops keyboard scanning. */ - kbd_log("ATkbc: self-test reinitialization\n"); - dev->out_new = dev->out_delayed = -1; - for (i = 0; i < 3; i++) - kbc_queue_reset(i); - kbd_last_scan_code = 0x00; - dev->status &= ~STAT_OFULL; - dev->last_irq = dev->old_last_irq = 0; - - if ((dev->flags & KBC_TYPE_MASK) >= KBC_TYPE_PS2_NOREF) - write_cmd(dev, 0x30 | STAT_SYSFLAG); - else - write_cmd(dev, 0x10 | STAT_SYSFLAG); - add_data(dev, 0x55); - break; - - case 0xab: /* interface test */ - kbd_log("ATkbc: interface test\n"); - add_data(dev, 0x00); /*no error*/ - break; - - case 0xac: /* diagnostic dump */ - kbd_log("ATkbc: diagnostic dump\n"); - for (i = 0; i < 16; i++) - add_data(dev, dev->mem[i]); - add_data(dev, (dev->input_port & 0xf0) | 0x80); - add_data(dev, dev->output_port); - add_data(dev, dev->status); - break; - - case 0xad: /* disable keyboard */ - kbd_log("ATkbc: disable keyboard\n"); - set_enable_kbd(dev, 0); - break; - - case 0xae: /* enable keyboard */ - kbd_log("ATkbc: enable keyboard\n"); - set_enable_kbd(dev, 1); - break; - - case 0xca: /* read keyboard mode */ - kbd_log("ATkbc: AMI - read keyboard mode\n"); - add_data(dev, dev->ami_flags); - break; - - case 0xcb: /* set keyboard mode */ - kbd_log("ATkbc: AMI - set keyboard mode\n"); - dev->want60 = 1; - break; - - case 0xd0: /* read output port */ - kbd_log("ATkbc: read output port\n"); - mask = 0xff; - if ((kbc_ven != KBC_VEN_OLIVETTI) && ((dev->flags & KBC_TYPE_MASK) < KBC_TYPE_PS2_NOREF) && (dev->mem[0] & 0x10)) - mask &= 0xbf; - add_to_kbc_queue_front(dev, dev->output_port & mask, 0, 0x00); - break; - - case 0xd1: /* write output port */ - kbd_log("ATkbc: write output port\n"); - dev->want60 = 1; - break; - - case 0xd2: /* write keyboard output buffer */ - kbd_log("ATkbc: write keyboard output buffer\n"); - dev->want60 = 1; - break; - - case 0xdd: /* disable A20 address line */ - case 0xdf: /* enable A20 address line */ - kbd_log("ATkbc: %sable A20\n", (val == 0xdd) ? "dis": "en"); - write_output(dev, (dev->output_port & 0xfd) | (val & 0x02)); - break; - - case 0xe0: /* read test inputs */ - kbd_log("ATkbc: read test inputs\n"); - add_data(dev, 0x00); - break; - - default: - /* - * Unrecognized controller command. - * - * If we have a vendor-specific handler, run - * that. Otherwise, or if that handler fails, - * log a bad command. - */ - if (dev->write64_ven) - bad = dev->write64_ven(dev, val); - - kbd_log(bad ? "ATkbc: bad controller command %02X\n" : "", val); - } - - /* If the command needs data, remember the command. */ - if (dev->want60) - dev->command = val; - break; - } -} - - -static uint8_t -kbd_read(uint16_t port, void *priv) -{ - atkbd_t *dev = (atkbd_t *)priv; - uint8_t ret = 0xff; - uint8_t kbc_ven = 0x0; - kbc_ven = dev->flags & KBC_VEN_MASK; - - if ((dev->flags & KBC_TYPE_MASK) >= KBC_TYPE_PS2_NOREF) - cycles -= ISA_CYCLES(8); - - switch (port) { - case 0x60: - ret = dev->out; - dev->status &= ~STAT_OFULL; - picintc(dev->last_irq); - dev->last_irq = 0; - break; - - case 0x64: - ret = (dev->status & 0xfb); - if (dev->mem[0] & STAT_SYSFLAG) - ret |= STAT_SYSFLAG; - /* Only clear the transmit timeout flag on non-PS/2 controllers, as on - PS/2 controller, it is the keyboard/mouse output source bit. */ - // dev->status &= ~STAT_RTIMEOUT; - if (((dev->flags & KBC_TYPE_MASK) > KBC_TYPE_PS2_NOREF) && - (kbc_ven != KBC_VEN_IBM_MCA)) - dev->status &= ~STAT_TTIMEOUT; - break; - - default: - kbd_log("ATkbc: read(%04x) invalid!\n", port); - break; - } - - kbd_log((port == 0x61) ? "" : "ATkbc: read(%04X) = %02X\n", port, ret); - - return(ret); -} - - -static void -kbd_reset(void *priv) -{ - atkbd_t *dev = (atkbd_t *)priv; - int i; - uint8_t kbc_ven = dev->flags & KBC_VEN_MASK; - - dev->first_write = 1; - // dev->status = STAT_UNLOCKED | STAT_CD; - dev->status = STAT_UNLOCKED; - dev->mem[0] = 0x01; - dev->mem[0] |= CCB_TRANSLATE; - dev->wantirq = 0; - write_output(dev, 0xcf); - dev->last_irq = dev->old_last_irq = 0; - dev->secr_phase = 0; - dev->key_wantdata = 0; - - /* Set up the correct Video Type bits. */ - if ((kbc_ven == KBC_VEN_XI8088) || (kbc_ven == KBC_VEN_ACER)) - dev->input_port = video_is_mda() ? 0xb0 : 0xf0; - else - dev->input_port = video_is_mda() ? 0xf0 : 0xb0; - kbd_log("ATkbc: input port = %02x\n", dev->input_port); - - keyboard_mode = 0x02 | (dev->mem[0] & CCB_TRANSLATE); - - /* Enable keyboard, disable mouse. */ - set_enable_kbd(dev, 1); - keyboard_scan = 1; - set_enable_mouse(dev, 0); - mouse_scan = 0; - - dev->out_new = dev->out_delayed = -1; - for (i = 0; i < 3; i++) - kbc_queue_reset(i); - kbd_last_scan_code = 0; - - sc_or = 0; + dev->rate = 1; + keyboard_set3_all_break = 0; + keyboard_set3_all_repeat = 0; memset(keyboard_set3_flags, 0, 512); - set_scancode_map(dev); - - dev->ami_flags = ((dev->flags & KBC_TYPE_MASK) >= KBC_TYPE_PS2_NOREF) ? 0x01 : 0x00; + keyboard_mode = 0x02; + keyboard_at_set_scancode_set(); } - -/* Reset the AT keyboard - this is needed for the PCI TRC and is done - until a better solution is found. */ -void -keyboard_at_reset(void) +static void +keyboard_at_bat(void *priv) { - kbd_reset(SavedKbd); + atkbc_dev_t *dev = (atkbc_dev_t *) priv; + + keyboard_at_set_defaults(dev); + + keyboard_scan = 1; + + kbc_at_dev_queue_add(dev, 0xaa, 0); +} + +static void +keyboard_at_invalid_cmd(atkbc_dev_t *dev) +{ + keyboard_at_log("%s: Invalid command [%02X]\n", dev->name, dev->port->dat); + kbc_at_dev_queue_add(dev, inv_cmd_response, 0); } static void -kbd_close(void *priv) +keyboard_at_write(void *priv) { - atkbd_t *dev = (atkbd_t *)priv; + atkbc_dev_t *dev = (atkbc_dev_t *) priv; + uint8_t val; - kbd_reset(dev); + if (dev->port == NULL) + return; - /* Stop timers. */ - timer_disable(&dev->send_delay_timer); + val = dev->port->dat; + + dev->state = DEV_STATE_MAIN_OUT; + + if ((val < 0xed) && (dev->flags & FLAG_CTRLDAT)) { + dev->flags &= ~FLAG_CTRLDAT; + + switch (dev->command) { + case 0xed: /* Set/reset LEDs */ + kbc_at_dev_queue_add(dev, 0xfa, 0); + keyboard_at_log("%s: Set/reset LEDs [%02X]\n", dev->name, val); + break; + + case 0xf0: /* Get/set scancode set */ + kbc_at_dev_queue_add(dev, (val > 3) ? 0xfe : 0xfa, 0); + switch (val) { + case 0x00: + keyboard_at_log("%s: Get scan code set [%02X]\n", dev->name, keyboard_mode); + kbc_at_dev_queue_add(dev, keyboard_mode, 0); + break; + case 0x01 ... 0x03: + keyboard_mode = val; + keyboard_at_log("%s: Set scan code set [%02X]\n", dev->name, keyboard_mode); + keyboard_at_set_scancode_set(); + break; + default: + /* Fatal so any instance of anything attempting to set scan code > 3 can be reported to us. */ + fatal("%s: Scan code set [%02X] invalid, resend\n", dev->name, val); + dev->flags |= FLAG_CTRLDAT; + dev->state = DEV_STATE_MAIN_WANT_IN; + break; + } + break; + + case 0xf3: /* set typematic rate/delay */ + if (val & 0x80) { + keyboard_at_log("%s: Set typematic rate/delay [%02X] has bit 7 set - invalid\n", dev->name, val); + dev->flags |= FLAG_CTRLDAT; /* Resend = keep waiting for parameter. */ + kbc_at_dev_queue_add(dev, 0xfe, 0); /* Command response */ + dev->state = DEV_STATE_MAIN_WANT_IN; + } else { + dev->rate = val; + kbc_at_dev_queue_add(dev, 0xfa, 0); /* Command response */ + keyboard_at_log("%s: Set typematic rate/delay [%02X]\n", dev->name, val); + } + break; + + default: + fatal("%s: Parameter [%02X] for invalid command [%02X] - possibly memory corruption!\n", dev->name, val, dev->command); + kbc_at_dev_queue_add(dev, 0xfe, 0); + } + } else { + if (dev->flags & FLAG_CTRLDAT) { + /* Special case - another command during another command that wants input - proceed + as normal but do not cancel the command (so keep waiting for input), unless the + command in progress is ED (Set/reset LEDs). */ + if (val == 0xed) { + keyboard_scan = 1; + dev->flags &= ~FLAG_CTRLDAT; + } else + dev->state = DEV_STATE_MAIN_WANT_IN; + } + + switch (val) { + case 0xed: /* set/reset LEDs */ + dev->command = val; + keyboard_at_log("%s: set/reset LEDs\n", dev->name); + dev->flags |= FLAG_CTRLDAT; + kbc_at_dev_queue_add(dev, 0xfa, 0); /* ACK for command byte */ + dev->state = DEV_STATE_MAIN_WANT_IN; + break; + + case 0xee: /* diagnostic echo */ + keyboard_at_log("%s: ECHO\n", dev->name); + kbc_at_dev_queue_add(dev, 0xee, 0); + break; + + case 0xef: /* Invalid command */ + case 0xf1: /* Invalid command */ + keyboard_at_log("%s: Invalid command [%02X]\n", dev->name, dev->port->dat); + kbc_at_dev_queue_add(dev, inv_cmd_response, 0); + break; + + case 0xf0: /* get/set scan code set */ + if (dev->type & FLAG_PS2) { + dev->command = val; + keyboard_at_log("%s: scan code set\n", dev->name); + dev->flags |= FLAG_CTRLDAT; + kbc_at_dev_queue_add(dev, 0xfa, 0); /* ACK for command byte */ + dev->state = DEV_STATE_MAIN_WANT_IN; + } else + keyboard_at_invalid_cmd(dev); + break; + + case 0xf2: /* read ID */ + keyboard_at_log("%s: read keyboard id\n", dev->name); + /* TODO: After keyboard type selection is implemented, make this + return the correct keyboard ID for the selected type. */ + kbc_at_dev_queue_add(dev, 0xfa, 0); + for (uint8_t i = 0; i < 4; i++) { + if (id_bytes[dev->type][i] == 0) + break; + + kbc_at_dev_queue_add(dev, id_bytes[dev->type][i], 0); + } + break; + + case 0xf3: /* set command mode */ + dev->command = val; + keyboard_at_log("%s: set typematic rate/delay\n", dev->name); + dev->flags |= FLAG_CTRLDAT; + kbc_at_dev_queue_add(dev, 0xfa, 0); /* ACK for command byte */ + dev->state = DEV_STATE_MAIN_WANT_IN; + break; + + case 0xf4: /* enable */ + keyboard_at_log("%s: enable keyboard\n", dev->name); + keyboard_scan = 1; + kbc_at_dev_queue_add(dev, 0xfa, 0); + break; + + case 0xf5: /* set defaults and disable keyboard */ + case 0xf6: /* set defaults */ + keyboard_at_log("%s: set defaults%s\n", (val == 0xf6) ? "" : " and disable keyboard"); + keyboard_scan = !(val & 0x01); + keyboard_at_log("%s: val = %02X, keyboard_scan = %i\n", + dev->name, val, keyboard_scan); + kbc_at_dev_queue_add(dev, 0xfa, 0); + + keyboard_set3_all_break = 0; + keyboard_set3_all_repeat = 0; + memset(keyboard_set3_flags, 0, 512); + + keyboard_mode = 0x02; + keyboard_at_set_scancode_set(); + break; + + case 0xf7: /* set all keys to repeat */ + if (dev->type & FLAG_PS2) { + keyboard_at_log("%s: set all keys to repeat\n", dev->name); + kbc_at_dev_queue_add(dev, 0xfa, 0); + keyboard_set3_all_break = 1; + } else + keyboard_at_invalid_cmd(dev); + break; + + case 0xf8: /* set all keys to give make/break codes */ + if (dev->type & FLAG_PS2) { + keyboard_at_log("%s: set all keys to give make/break codes\n", dev->name); + kbc_at_dev_queue_add(dev, 0xfa, 0); + keyboard_set3_all_break = 1; + } else + keyboard_at_invalid_cmd(dev); + break; + + case 0xf9: /* set all keys to give make codes only */ + if (dev->type & FLAG_PS2) { + keyboard_at_log("%s: set all keys to give make codes only\n", dev->name); + kbc_at_dev_queue_add(dev, 0xfa, 0); + keyboard_set3_all_break = 0; + } else + keyboard_at_invalid_cmd(dev); + break; + + case 0xfa: /* set all keys to repeat and give make/break codes */ + if (dev->type & FLAG_PS2) { + keyboard_at_log("%s: set all keys to repeat and give make/break codes\n", dev->name); + kbc_at_dev_queue_add(dev, 0xfa, 0); + keyboard_set3_all_repeat = 1; + keyboard_set3_all_break = 1; + } else + keyboard_at_invalid_cmd(dev); + break; + + /* TODO: Actually implement these commands. */ + case 0xfb: /* set some keys to repeat */ + keyboard_at_log("%s: set some keys to repeat\n", dev->name); + kbc_at_dev_queue_add(dev, inv_cmd_response, 0); + break; + + case 0xfc: /* set some keys to give make/break codes */ + keyboard_at_log("%s: set some keys to give make/break codes\n", dev->name); + kbc_at_dev_queue_add(dev, inv_cmd_response, 0); + break; + + case 0xfd: /* set some keys to give make codes only */ + keyboard_at_log("%s: set some keys to give make codes only\n", dev->name); + kbc_at_dev_queue_add(dev, inv_cmd_response, 0); + break; + + /* TODO: This is supposed to resend multiple bytes after some commands. */ + case 0xfe: /* resend last scan code */ + keyboard_at_log("%s: resend last scan code\n", dev->name); + kbc_at_dev_queue_add(dev, dev->last_scan_code, 0); + break; + + case 0xff: /* reset */ + kbc_at_dev_reset(dev, 1); + break; + + default: + kbc_at_dev_queue_add(dev, 0xfe, 0); + } + } +} + +/* + * Initialize the device for use by the user. + * + * We also get called from the various machines. + */ +void * +keyboard_at_init(const device_t *info) +{ + atkbc_dev_t *dev = kbc_at_dev_init(DEV_KBD); + + dev->name = info->name; + /* Key 14 = Japanese key next to backspace, scan code: 13 (Yen 7D); + Key 29 = US backslash, scan code: 5C (Backslash 2B); + Key 42 = European backslash, scan code: 53 (Backslash 2B); + Key 45 = European key next to left shift, scan code: 13 (Key 56); + Key 56 = Japanese key next to right shift, scan code: 5C (Backslash 73); + Key 59 = Japanese key between left Ctrl and left Alt, scan code: 85 (Muhenkan 7B); + Key 63 = Japanese key between right Ctrl and right Alt, scan code: 86 (Henkan/Zenkouho 79); + Key 65? = Japanese key between right Ctrl and right Alt, scan code: 87 (Hiragana/Katakana 70). + */ + dev->type = FLAG_PS2 | KBD_102_KEY /* device_get_config_int("type") */; + + keyboard_at_log("%s: type=%d\n", dev->name, dev->type); + + dev->process_cmd = keyboard_at_write; + dev->execute_bat = keyboard_at_bat; + + dev->scan = &keyboard_scan; + + dev->fifo_mask = FIFO_SIZE - 1; + + if (dev->port != NULL) + kbc_at_dev_reset(dev, 0); + + keyboard_send = add_data_kbd; + SavedKbd = dev; + + inv_cmd_response = (dev->type & FLAG_PS2) ? 0xfe : 0xfa; + + /* Return our private data to the I/O layer. */ + return dev; +} + +static void +keyboard_at_close(void *priv) +{ + atkbc_dev_t *dev = (atkbc_dev_t *) priv; keyboard_scan = 0; keyboard_send = NULL; @@ -2272,364 +989,48 @@ kbd_close(void *priv) keyboard_set_table(NULL); SavedKbd = NULL; + free(dev); } - -static void * -kbd_init(const device_t *info) -{ - atkbd_t *dev; - - dev = (atkbd_t *)malloc(sizeof(atkbd_t)); - memset(dev, 0x00, sizeof(atkbd_t)); - - dev->flags = info->local; - - video_reset(gfxcard); - kbd_reset(dev); - - io_sethandler(0x0060, 1, kbd_read, NULL, NULL, kbd_write, NULL, NULL, dev); - io_sethandler(0x0064, 1, kbd_read, NULL, NULL, kbd_write, NULL, NULL, dev); - keyboard_send = add_data_kbd; - - timer_add(&dev->send_delay_timer, kbd_poll, dev, 1); - timer_add(&dev->pulse_cb, pulse_poll, dev, 0); - - dev->write60_ven = NULL; - dev->write64_ven = NULL; - - switch(dev->flags & KBC_VEN_MASK) { - case KBC_VEN_ACER: - case KBC_VEN_GENERIC: - case KBC_VEN_NCR: - case KBC_VEN_IBM_PS1: - case KBC_VEN_XI8088: - dev->write64_ven = write64_generic; - break; - - case KBC_VEN_OLIVETTI: - dev->write64_ven = write64_olivetti; - break; - - case KBC_VEN_AMI: - case KBC_VEN_INTEL_AMI: - case KBC_VEN_SAMSUNG: - dev->write60_ven = write60_ami; - dev->write64_ven = write64_ami; - break; - - case KBC_VEN_IBM_MCA: - dev->write64_ven = write64_ibm_mca; - break; - - case KBC_VEN_QUADTEL: - dev->write60_ven = write60_quadtel; - dev->write64_ven = write64_quadtel; - break; - - case KBC_VEN_TOSHIBA: - dev->write60_ven = write60_toshiba; - dev->write64_ven = write64_toshiba; - break; +static const device_config_t keyboard_at_config[] = { + // clang-format off + { + .name = "type", + .description = "Type", + .type = CONFIG_SELECTION, + .default_string = "", + .default_int = 2, + .file_filter = "", + .spinner = { 0 }, + .selection = { + { .description = "AT 84-key", .value = FLAG_AT | KBD_84_KEY }, + { .description = "AT 101/102/106-key", .value = FLAG_AT | KBD_101_KEY }, + { .description = "AT Korean", .value = FLAG_AT | KBD_KOREAN }, + { .description = "PS/2 101-key", .value = FLAG_PS2 | KBD_101_KEY }, + { .description = "PS/2 102-key", .value = FLAG_PS2 | KBD_102_KEY }, + { .description = "PS/2 106-key JIS", .value = FLAG_PS2 | KBD_JIS }, + { .description = "PS/2 Korean", .value = FLAG_PS2 | KBD_KOREAN }, + { .description = "" } + } + }, + { + .name = "", .description = "", .type = CONFIG_END } - - /* We need this, sadly. */ - SavedKbd = dev; - - return(dev); -} - - -const device_t keyboard_at_device = { - "PC/AT Keyboard", - "keyboard_at", - 0, - KBC_TYPE_ISA | KBC_VEN_GENERIC, - kbd_init, - kbd_close, - kbd_reset, - { NULL }, NULL, NULL, NULL + // clang-format on }; -const device_t keyboard_at_ami_device = { - "PC/AT Keyboard (AMI)", - "keyboard_at_ami", - 0, - KBC_TYPE_ISA | KBC_VEN_AMI, - kbd_init, - kbd_close, - kbd_reset, - { NULL }, NULL, NULL, NULL +/* TODO: Add more keyboard types. */ +const device_t keyboard_at_generic_device = { + .name = "Standard AT or PS/2 Keyboard", + .internal_name = "ps2", + .flags = DEVICE_PS2, + .local = 0, + .init = keyboard_at_init, + .close = keyboard_at_close, + .reset = NULL, + { .poll = NULL }, + .speed_changed = NULL, + .force_redraw = NULL, + .config = keyboard_at_config }; - -const device_t keyboard_at_samsung_device = { - "PC/AT Keyboard (Samsung)", - "keyboard_at_samsung", - 0, - KBC_TYPE_ISA | KBC_VEN_SAMSUNG, - kbd_init, - kbd_close, - kbd_reset, - { NULL }, NULL, NULL, NULL -}; - -const device_t keyboard_at_toshiba_device = { - "PC/AT Keyboard (Toshiba)", - "keyboard_at_toshiba", - 0, - KBC_TYPE_ISA | KBC_VEN_TOSHIBA, - kbd_init, - kbd_close, - kbd_reset, - { NULL }, NULL, NULL, NULL -}; - -const device_t keyboard_at_olivetti_device = { - "PC/AT Keyboard (Olivetti)", - "keyboard_at_olivetti", - 0, - KBC_TYPE_ISA | KBC_VEN_OLIVETTI, - kbd_init, - kbd_close, - kbd_reset, - { NULL }, NULL, NULL, NULL -}; - -const device_t keyboard_at_ncr_device = { - "PC/AT Keyboard (NCR)", - "keyboard_at_ncr", - 0, - KBC_TYPE_ISA | KBC_VEN_NCR, - kbd_init, - kbd_close, - kbd_reset, - { NULL }, NULL, NULL, NULL -}; - -const device_t keyboard_ps2_device = { - "PS/2 Keyboard", - "keyboard_ps2", - 0, - KBC_TYPE_PS2_NOREF | KBC_VEN_GENERIC, - kbd_init, - kbd_close, - kbd_reset, - { NULL }, NULL, NULL, NULL -}; - -const device_t keyboard_ps2_ps2_device = { - "PS/2 Keyboard", - "keyboard_ps2_ps2", - 0, - KBC_TYPE_PS2_1 | KBC_VEN_GENERIC, - kbd_init, - kbd_close, - kbd_reset, - { NULL }, NULL, NULL, NULL -}; - -const device_t keyboard_ps2_ps1_device = { - "PS/2 Keyboard (IBM PS/1)", - "keyboard_ps2_ps1", - 0, - KBC_TYPE_PS2_NOREF | KBC_VEN_IBM_PS1, - kbd_init, - kbd_close, - kbd_reset, - { NULL }, NULL, NULL, NULL -}; - -const device_t keyboard_ps2_ps1_pci_device = { - "PS/2 Keyboard (IBM PS/1)", - "keyboard_ps2_ps1_pci", - DEVICE_PCI, - KBC_TYPE_PS2_NOREF | KBC_VEN_IBM_PS1, - kbd_init, - kbd_close, - kbd_reset, - { NULL }, NULL, NULL, NULL -}; - -const device_t keyboard_ps2_xi8088_device = { - "PS/2 Keyboard (Xi8088)", - "keyboard_ps2_xi8088", - 0, - KBC_TYPE_PS2_1 | KBC_VEN_XI8088, - kbd_init, - kbd_close, - kbd_reset, - { NULL }, NULL, NULL, NULL -}; - -const device_t keyboard_ps2_ami_device = { - "PS/2 Keyboard (AMI)", - "keyboard_ps2_ami", - 0, - KBC_TYPE_PS2_NOREF | KBC_VEN_AMI, - kbd_init, - kbd_close, - kbd_reset, - { NULL }, NULL, NULL, NULL -}; - -const device_t keyboard_ps2_olivetti_device = { - "PS/2 Keyboard (Olivetti)", - "keyboard_ps2_olivetti", - 0, - KBC_TYPE_PS2_NOREF | KBC_VEN_OLIVETTI, - kbd_init, - kbd_close, - kbd_reset, - { NULL }, NULL, NULL, NULL -}; - -const device_t keyboard_ps2_mca_device = { - "PS/2 Keyboard", - "keyboard_ps2_mca", - 0, - KBC_TYPE_PS2_1 | KBC_VEN_IBM_MCA, - kbd_init, - kbd_close, - kbd_reset, - { NULL }, NULL, NULL, NULL -}; - -const device_t keyboard_ps2_mca_2_device = { - "PS/2 Keyboard", - "keyboard_ps2_mca_2", - 0, - KBC_TYPE_PS2_2 | KBC_VEN_IBM_MCA, - kbd_init, - kbd_close, - kbd_reset, - { NULL }, NULL, NULL, NULL -}; - -const device_t keyboard_ps2_quadtel_device = { - "PS/2 Keyboard (Quadtel/MegaPC)", - "keyboard_ps2_quadtel", - 0, - KBC_TYPE_PS2_NOREF | KBC_VEN_QUADTEL, - kbd_init, - kbd_close, - kbd_reset, - { NULL }, NULL, NULL, NULL -}; - -const device_t keyboard_ps2_pci_device = { - "PS/2 Keyboard", - "keyboard_ps2_pci", - DEVICE_PCI, - KBC_TYPE_PS2_NOREF | KBC_VEN_GENERIC, - kbd_init, - kbd_close, - kbd_reset, - { NULL }, NULL, NULL, NULL -}; - -const device_t keyboard_ps2_ami_pci_device = { - "PS/2 Keyboard (AMI)", - "keyboard_ps2_ami_pci", - DEVICE_PCI, - KBC_TYPE_PS2_NOREF | KBC_VEN_AMI, - kbd_init, - kbd_close, - kbd_reset, - { NULL }, NULL, NULL, NULL -}; - -const device_t keyboard_ps2_intel_ami_pci_device = { - "PS/2 Keyboard (AMI)", - "keyboard_ps2_intel_ami_pci", - DEVICE_PCI, - KBC_TYPE_PS2_NOREF | KBC_VEN_INTEL_AMI, - kbd_init, - kbd_close, - kbd_reset, - { NULL }, NULL, NULL, NULL -}; - -const device_t keyboard_ps2_acer_pci_device = { - "PS/2 Keyboard (Acer 90M002A)", - "keyboard_ps2_acer_pci", - DEVICE_PCI, - KBC_TYPE_PS2_NOREF | KBC_VEN_ACER, - kbd_init, - kbd_close, - kbd_reset, - { NULL }, NULL, NULL, NULL -}; - - -void -keyboard_at_set_mouse(void (*func)(uint8_t val, void *priv), void *priv) -{ - mouse_write = func; - mouse_p = priv; -} - - -void -keyboard_at_adddata_keyboard_raw(uint8_t val) -{ - atkbd_t *dev = SavedKbd; - - add_data_kbd_queue(dev, 0, val); -} - - -void -keyboard_at_adddata_mouse(uint8_t val) -{ - atkbd_t *dev = SavedKbd; - - kbc_queue_add(dev, val, 2, 0x00); -} - - -void -keyboard_at_mouse_reset(void) -{ - kbc_queue_reset(2); -} - - -uint8_t -keyboard_at_mouse_pos(void) -{ - return ((mouse_queue_end - mouse_queue_start) & 0xf); -} - - -void -keyboard_at_set_mouse_scan(uint8_t val) -{ - atkbd_t *dev = SavedKbd; - uint8_t temp_mouse_scan = val ? 1 : 0; - - if (temp_mouse_scan == !(dev->mem[0] & 0x20)) - return; - - set_enable_mouse(dev, val ? 1 : 0); - - kbd_log("ATkbc: mouse scan %sabled via PCI\n", mouse_scan ? "en" : "dis"); -} - - -uint8_t -keyboard_at_get_mouse_scan(void) -{ - atkbd_t *dev = SavedKbd; - - return((dev->mem[0] & 0x20) ? 0x00 : 0x10); -} - - -void -keyboard_at_set_a20_key(int state) -{ - atkbd_t *dev = SavedKbd; - - write_output(dev, (dev->output_port & 0xfd) | ((!!state) << 1)); -} diff --git a/src/device/keyboard_xt.c b/src/device/keyboard_xt.c index 9e0cf8ff7..f65a6dffc 100644 --- a/src/device/keyboard_xt.c +++ b/src/device/keyboard_xt.c @@ -1,24 +1,24 @@ /* - * 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. + * 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. + * This file is part of the 86Box distribution. * - * Implementation of the XT-style keyboard. + * Implementation of the XT-style keyboard. * * * - * Authors: Sarah Walker, - * Miran Grca, - * Fred N. van Kempen, - * EngiNerd, + * Authors: Sarah Walker, + * Miran Grca, + * Fred N. van Kempen, + * EngiNerd, * - * Copyright 2008-2019 Sarah Walker. - * Copyright 2016-2019 Miran Grca. - * Copyright 2017-2019 Fred N. van kempen. - * Copyright 2020 EngiNerd. + * Copyright 2008-2019 Sarah Walker. + * Copyright 2016-2019 Miran Grca. + * Copyright 2017-2019 Fred N. van kempen. + * Copyright 2020 EngiNerd. */ #include #include @@ -45,43 +45,51 @@ #include <86box/video.h> #include <86box/keyboard.h> +#define STAT_PARITY 0x80 +#define STAT_RTIMEOUT 0x40 +#define STAT_TTIMEOUT 0x20 +#define STAT_LOCK 0x10 +#define STAT_CD 0x08 +#define STAT_SYSFLAG 0x04 +#define STAT_IFULL 0x02 +#define STAT_OFULL 0x01 -#define STAT_PARITY 0x80 -#define STAT_RTIMEOUT 0x40 -#define STAT_TTIMEOUT 0x20 -#define STAT_LOCK 0x10 -#define STAT_CD 0x08 -#define STAT_SYSFLAG 0x04 -#define STAT_IFULL 0x02 -#define STAT_OFULL 0x01 +/* Keyboard Types */ +enum { + KBD_TYPE_PC81 = 0, + KBD_TYPE_PC82, + KBD_TYPE_XT82, + KBD_TYPE_XT86, + KBD_TYPE_COMPAQ, + KBD_TYPE_TANDY, + KBD_TYPE_TOSHIBA, + KBD_TYPE_VTECH, + KBD_TYPE_OLIVETTI, + KBD_TYPE_ZENITH, + KBD_TYPE_PRAVETZ, + KBD_TYPE_HYUNDAI, + KBD_TYPE_XTCLONE +}; -// Keyboard Types -#define KBD_TYPE_PC81 0 -#define KBD_TYPE_PC82 1 -#define KBD_TYPE_XT82 2 -#define KBD_TYPE_XT86 3 -#define KBD_TYPE_COMPAQ 4 -#define KBD_TYPE_TANDY 5 -#define KBD_TYPE_TOSHIBA 6 -#define KBD_TYPE_VTECH 7 -#define KBD_TYPE_OLIVETTI 8 -#define KBD_TYPE_ZENITH 9 - -typedef struct { - int want_irq; +typedef struct xtkbd_t { + int want_irq; int blocked; int tandy; - uint8_t pa, pb, pd; + uint8_t pa; + uint8_t pb; + uint8_t pd; + uint8_t clock; uint8_t key_waiting; uint8_t type; + uint8_t pravetz_flags; pc_timer_t send_delay_timer; } xtkbd_t; - /*XT keyboard has no escape scancodes, and no scancodes beyond 53*/ const scancode scancode_xt[512] = { + // clang-format off { {0}, {0} }, { {0x01, 0}, {0x81, 0} }, { {0x02, 0}, {0x82, 0} }, { {0x03, 0}, {0x83, 0} }, { {0x04, 0}, {0x84, 0} }, { {0x05, 0}, {0x85, 0} }, @@ -125,256 +133,256 @@ const scancode scancode_xt[512] = { { {0x50, 0}, {0xd0, 0} }, { {0x51, 0}, {0xd1, 0} }, { {0x52, 0}, {0xd2, 0} }, { {0x53, 0}, {0xd3, 0} }, { {0}, {0} }, { {0}, {0} }, - { {0}, {0} }, { {0}, {0} }, /*054*/ + { {0}, {0} }, { {0}, {0} }, /*054*/ { {0}, {0} }, { {0}, {0} }, - { {0}, {0} }, { {0}, {0} }, /*058*/ + { {0}, {0} }, { {0}, {0} }, /*058*/ { {0}, {0} }, { {0}, {0} }, - { {0}, {0} }, { {0}, {0} }, /*05c*/ + { {0}, {0} }, { {0}, {0} }, /*05c*/ { {0}, {0} }, { {0}, {0} }, - { {0}, {0} }, { {0}, {0} }, /*060*/ + { {0}, {0} }, { {0}, {0} }, /*060*/ { {0}, {0} }, { {0}, {0} }, - { {0}, {0} }, { {0}, {0} }, /*064*/ + { {0}, {0} }, { {0}, {0} }, /*064*/ { {0}, {0} }, { {0}, {0} }, - { {0}, {0} }, { {0}, {0} }, /*068*/ + { {0}, {0} }, { {0}, {0} }, /*068*/ { {0}, {0} }, { {0}, {0} }, - { {0}, {0} }, { {0}, {0} }, /*06c*/ + { {0}, {0} }, { {0}, {0} }, /*06c*/ { {0}, {0} }, { {0}, {0} }, - { {0}, {0} }, { {0}, {0} }, /*070*/ + { {0}, {0} }, { {0}, {0} }, /*070*/ { {0}, {0} }, { {0}, {0} }, - { {0}, {0} }, { {0}, {0} }, /*074*/ + { {0}, {0} }, { {0}, {0} }, /*074*/ { {0}, {0} }, { {0}, {0} }, - { {0}, {0} }, { {0}, {0} }, /*078*/ + { {0}, {0} }, { {0}, {0} }, /*078*/ { {0}, {0} }, { {0}, {0} }, - { {0}, {0} }, { {0}, {0} }, /*07c*/ + { {0}, {0} }, { {0}, {0} }, /*07c*/ { {0}, {0} }, { {0}, {0} }, - { {0}, {0} }, { {0}, {0} }, /*080*/ + { {0}, {0} }, { {0}, {0} }, /*080*/ { {0}, {0} }, { {0}, {0} }, - { {0}, {0} }, { {0}, {0} }, /*084*/ + { {0}, {0} }, { {0}, {0} }, /*084*/ { {0}, {0} }, { {0}, {0} }, - { {0}, {0} }, { {0}, {0} }, /*088*/ + { {0}, {0} }, { {0}, {0} }, /*088*/ { {0}, {0} }, { {0}, {0} }, - { {0}, {0} }, { {0}, {0} }, /*08c*/ + { {0}, {0} }, { {0}, {0} }, /*08c*/ { {0}, {0} }, { {0}, {0} }, - { {0}, {0} }, { {0}, {0} }, /*090*/ + { {0}, {0} }, { {0}, {0} }, /*090*/ { {0}, {0} }, { {0}, {0} }, - { {0}, {0} }, { {0}, {0} }, /*094*/ + { {0}, {0} }, { {0}, {0} }, /*094*/ { {0}, {0} }, { {0}, {0} }, - { {0}, {0} }, { {0}, {0} }, /*098*/ + { {0}, {0} }, { {0}, {0} }, /*098*/ { {0}, {0} }, { {0}, {0} }, - { {0}, {0} }, { {0}, {0} }, /*09c*/ + { {0}, {0} }, { {0}, {0} }, /*09c*/ { {0}, {0} }, { {0}, {0} }, - { {0}, {0} }, { {0}, {0} }, /*0a0*/ + { {0}, {0} }, { {0}, {0} }, /*0a0*/ { {0}, {0} }, { {0}, {0} }, - { {0}, {0} }, { {0}, {0} }, /*0a4*/ + { {0}, {0} }, { {0}, {0} }, /*0a4*/ { {0}, {0} }, { {0}, {0} }, - { {0}, {0} }, { {0}, {0} }, /*0a8*/ + { {0}, {0} }, { {0}, {0} }, /*0a8*/ { {0}, {0} }, { {0}, {0} }, - { {0}, {0} }, { {0}, {0} }, /*0ac*/ + { {0}, {0} }, { {0}, {0} }, /*0ac*/ { {0}, {0} }, { {0}, {0} }, - { {0}, {0} }, { {0}, {0} }, /*0b0*/ + { {0}, {0} }, { {0}, {0} }, /*0b0*/ { {0}, {0} }, { {0}, {0} }, - { {0}, {0} }, { {0}, {0} }, /*0b4*/ + { {0}, {0} }, { {0}, {0} }, /*0b4*/ { {0}, {0} }, { {0}, {0} }, - { {0}, {0} }, { {0}, {0} }, /*0b8*/ + { {0}, {0} }, { {0}, {0} }, /*0b8*/ { {0}, {0} }, { {0}, {0} }, - { {0}, {0} }, { {0}, {0} }, /*0bc*/ + { {0}, {0} }, { {0}, {0} }, /*0bc*/ { {0}, {0} }, { {0}, {0} }, - { {0}, {0} }, { {0}, {0} }, /*0c0*/ + { {0}, {0} }, { {0}, {0} }, /*0c0*/ { {0}, {0} }, { {0}, {0} }, - { {0}, {0} }, { {0}, {0} }, /*0c4*/ + { {0}, {0} }, { {0}, {0} }, /*0c4*/ { {0}, {0} }, { {0}, {0} }, - { {0}, {0} }, { {0}, {0} }, /*0c8*/ + { {0}, {0} }, { {0}, {0} }, /*0c8*/ { {0}, {0} }, { {0}, {0} }, - { {0}, {0} }, { {0}, {0} }, /*0cc*/ + { {0}, {0} }, { {0}, {0} }, /*0cc*/ { {0}, {0} }, { {0}, {0} }, - { {0}, {0} }, { {0}, {0} }, /*0d0*/ + { {0}, {0} }, { {0}, {0} }, /*0d0*/ { {0}, {0} }, { {0}, {0} }, - { {0}, {0} }, { {0}, {0} }, /*0d4*/ + { {0}, {0} }, { {0}, {0} }, /*0d4*/ { {0}, {0} }, { {0}, {0} }, - { {0}, {0} }, { {0}, {0} }, /*0d8*/ + { {0}, {0} }, { {0}, {0} }, /*0d8*/ { {0}, {0} }, { {0}, {0} }, - { {0}, {0} }, { {0}, {0} }, /*0dc*/ + { {0}, {0} }, { {0}, {0} }, /*0dc*/ { {0}, {0} }, { {0}, {0} }, - { {0}, {0} }, { {0}, {0} }, /*0e0*/ + { {0}, {0} }, { {0}, {0} }, /*0e0*/ { {0}, {0} }, { {0}, {0} }, - { {0}, {0} }, { {0}, {0} }, /*0e4*/ + { {0}, {0} }, { {0}, {0} }, /*0e4*/ { {0}, {0} }, { {0}, {0} }, - { {0}, {0} }, { {0}, {0} }, /*0e8*/ + { {0}, {0} }, { {0}, {0} }, /*0e8*/ { {0}, {0} }, { {0}, {0} }, - { {0}, {0} }, { {0}, {0} }, /*0ec*/ + { {0}, {0} }, { {0}, {0} }, /*0ec*/ { {0}, {0} }, { {0}, {0} }, - { {0}, {0} }, { {0}, {0} }, /*0f0*/ + { {0}, {0} }, { {0}, {0} }, /*0f0*/ { {0}, {0} }, { {0}, {0} }, - { {0}, {0} }, { {0}, {0} }, /*0f4*/ + { {0}, {0} }, { {0}, {0} }, /*0f4*/ { {0}, {0} }, { {0}, {0} }, - { {0}, {0} }, { {0}, {0} }, /*0f8*/ + { {0}, {0} }, { {0}, {0} }, /*0f8*/ { {0}, {0} }, { {0}, {0} }, - { {0}, {0} }, { {0}, {0} }, /*0fc*/ + { {0}, {0} }, { {0}, {0} }, /*0fc*/ { {0}, {0} }, { {0}, {0} }, - { {0}, {0} }, { {0}, {0} }, /*100*/ + { {0}, {0} }, { {0}, {0} }, /*100*/ { {0}, {0} }, { {0}, {0} }, - { {0}, {0} }, { {0}, {0} }, /*104*/ + { {0}, {0} }, { {0}, {0} }, /*104*/ { {0}, {0} }, { {0}, {0} }, - { {0}, {0} }, { {0}, {0} }, /*108*/ + { {0}, {0} }, { {0}, {0} }, /*108*/ { {0}, {0} }, { {0}, {0} }, - { {0}, {0} }, { {0}, {0} }, /*10c*/ + { {0}, {0} }, { {0}, {0} }, /*10c*/ { {0}, {0} }, { {0}, {0} }, - { {0}, {0} }, { {0}, {0} }, /*110*/ + { {0}, {0} }, { {0}, {0} }, /*110*/ { {0}, {0} }, { {0}, {0} }, - { {0}, {0} }, { {0}, {0} }, /*114*/ + { {0}, {0} }, { {0}, {0} }, /*114*/ { {0}, {0} }, { {0}, {0} }, - { {0}, {0} }, { {0}, {0} }, /*118*/ + { {0}, {0} }, { {0}, {0} }, /*118*/ { {0x1c, 0}, {0x9c, 0} }, { {0x1d, 0}, {0x9d, 0} }, - { {0}, {0} }, { {0}, {0} }, /*11c*/ + { {0}, {0} }, { {0}, {0} }, /*11c*/ { {0}, {0} }, { {0}, {0} }, - { {0}, {0} }, { {0}, {0} }, /*120*/ + { {0}, {0} }, { {0}, {0} }, /*120*/ { {0}, {0} }, { {0}, {0} }, - { {0}, {0} }, { {0}, {0} }, /*124*/ + { {0}, {0} }, { {0}, {0} }, /*124*/ { {0}, {0} }, { {0}, {0} }, - { {0}, {0} }, { {0}, {0} }, /*128*/ + { {0}, {0} }, { {0}, {0} }, /*128*/ { {0}, {0} }, { {0}, {0} }, - { {0}, {0} }, { {0}, {0} }, /*12c*/ + { {0}, {0} }, { {0}, {0} }, /*12c*/ { {0}, {0} }, { {0}, {0} }, - { {0}, {0} }, { {0}, {0} }, /*130*/ + { {0}, {0} }, { {0}, {0} }, /*130*/ { {0}, {0} }, { {0x35, 0}, {0xb5, 0} }, - { {0}, {0} }, { {0x37, 0}, {0xb7, 0} }, /*134*/ + { {0}, {0} }, { {0x37, 0}, {0xb7, 0} }, /*134*/ { {0x38, 0}, {0xb8, 0} }, { {0}, {0} }, - { {0}, {0} }, { {0}, {0} }, /*138*/ + { {0}, {0} }, { {0}, {0} }, /*138*/ { {0}, {0} }, { {0}, {0} }, - { {0}, {0} }, { {0}, {0} }, /*13c*/ + { {0}, {0} }, { {0}, {0} }, /*13c*/ { {0}, {0} }, { {0}, {0} }, - { {0}, {0} }, { {0}, {0} }, /*140*/ + { {0}, {0} }, { {0}, {0} }, /*140*/ { {0}, {0} }, { {0}, {0} }, - { {0x46, 0}, {0xc6, 0} }, { {0x47, 0}, {0xc7, 0} }, /*144*/ + { {0x46, 0}, {0xc6, 0} }, { {0x47, 0}, {0xc7, 0} }, /*144*/ { {0x48, 0}, {0xc8, 0} }, { {0x49, 0}, {0xc9, 0} }, - { {0}, {0} }, { {0x4b, 0}, {0xcb, 0} }, /*148*/ + { {0}, {0} }, { {0x4b, 0}, {0xcb, 0} }, /*148*/ { {0}, {0} }, { {0x4d, 0}, {0xcd, 0} }, - { {0}, {0} }, { {0x4f, 0}, {0xcf, 0} }, /*14c*/ + { {0}, {0} }, { {0x4f, 0}, {0xcf, 0} }, /*14c*/ { {0x50, 0}, {0xd0, 0} }, { {0x51, 0}, {0xd1, 0} }, - { {0x52, 0}, {0xd2, 0} }, { {0x53, 0}, {0xd3, 0} }, /*150*/ + { {0x52, 0}, {0xd2, 0} }, { {0x53, 0}, {0xd3, 0} }, /*150*/ { {0}, {0} }, { {0}, {0} }, - { {0}, {0} }, { {0}, {0} }, /*154*/ + { {0}, {0} }, { {0}, {0} }, /*154*/ { {0}, {0} }, { {0}, {0} }, - { {0}, {0} }, { {0}, {0} }, /*158*/ + { {0}, {0} }, { {0}, {0} }, /*158*/ { {0}, {0} }, { {0}, {0} }, - { {0}, {0} }, { {0}, {0} }, /*15c*/ + { {0}, {0} }, { {0}, {0} }, /*15c*/ { {0}, {0} }, { {0}, {0} }, - { {0}, {0} }, { {0}, {0} }, /*160*/ + { {0}, {0} }, { {0}, {0} }, /*160*/ { {0}, {0} }, { {0}, {0} }, - { {0}, {0} }, { {0}, {0} }, /*164*/ + { {0}, {0} }, { {0}, {0} }, /*164*/ { {0}, {0} }, { {0}, {0} }, - { {0}, {0} }, { {0}, {0} }, /*168*/ + { {0}, {0} }, { {0}, {0} }, /*168*/ { {0}, {0} }, { {0}, {0} }, - { {0}, {0} }, { {0}, {0} }, /*16c*/ + { {0}, {0} }, { {0}, {0} }, /*16c*/ { {0}, {0} }, { {0}, {0} }, - { {0}, {0} }, { {0}, {0} }, /*170*/ + { {0}, {0} }, { {0}, {0} }, /*170*/ { {0}, {0} }, { {0}, {0} }, - { {0}, {0} }, { {0}, {0} }, /*174*/ + { {0}, {0} }, { {0}, {0} }, /*174*/ { {0}, {0} }, { {0}, {0} }, - { {0}, {0} }, { {0}, {0} }, /*148*/ + { {0}, {0} }, { {0}, {0} }, /*148*/ { {0}, {0} }, { {0}, {0} }, - { {0}, {0} }, { {0}, {0} }, /*17c*/ + { {0}, {0} }, { {0}, {0} }, /*17c*/ { {0}, {0} }, { {0}, {0} }, - { {0}, {0} }, { {0}, {0} }, /*180*/ + { {0}, {0} }, { {0}, {0} }, /*180*/ { {0}, {0} }, { {0}, {0} }, - { {0}, {0} }, { {0}, {0} }, /*184*/ + { {0}, {0} }, { {0}, {0} }, /*184*/ { {0}, {0} }, { {0}, {0} }, - { {0}, {0} }, { {0}, {0} }, /*88*/ + { {0}, {0} }, { {0}, {0} }, /*88*/ { {0}, {0} }, { {0}, {0} }, - { {0}, {0} }, { {0}, {0} }, /*18c*/ + { {0}, {0} }, { {0}, {0} }, /*18c*/ { {0}, {0} }, { {0}, {0} }, - { {0}, {0} }, { {0}, {0} }, /*190*/ + { {0}, {0} }, { {0}, {0} }, /*190*/ { {0}, {0} }, { {0}, {0} }, - { {0}, {0} }, { {0}, {0} }, /*194*/ + { {0}, {0} }, { {0}, {0} }, /*194*/ { {0}, {0} }, { {0}, {0} }, - { {0}, {0} }, { {0}, {0} }, /*198*/ + { {0}, {0} }, { {0}, {0} }, /*198*/ { {0}, {0} }, { {0}, {0} }, - { {0}, {0} }, { {0}, {0} }, /*19c*/ + { {0}, {0} }, { {0}, {0} }, /*19c*/ { {0}, {0} }, { {0}, {0} }, - { {0}, {0} }, { {0}, {0} }, /*1a0*/ + { {0}, {0} }, { {0}, {0} }, /*1a0*/ { {0}, {0} }, { {0}, {0} }, - { {0}, {0} }, { {0}, {0} }, /*1a4*/ + { {0}, {0} }, { {0}, {0} }, /*1a4*/ { {0}, {0} }, { {0}, {0} }, - { {0}, {0} }, { {0}, {0} }, /*1a8*/ + { {0}, {0} }, { {0}, {0} }, /*1a8*/ { {0}, {0} }, { {0}, {0} }, - { {0}, {0} }, { {0}, {0} }, /*1ac*/ + { {0}, {0} }, { {0}, {0} }, /*1ac*/ { {0}, {0} }, { {0}, {0} }, - { {0}, {0} }, { {0}, {0} }, /*1b0*/ + { {0}, {0} }, { {0}, {0} }, /*1b0*/ { {0}, {0} }, { {0}, {0} }, - { {0}, {0} }, { {0}, {0} }, /*1b4*/ + { {0}, {0} }, { {0}, {0} }, /*1b4*/ { {0}, {0} }, { {0}, {0} }, - { {0}, {0} }, { {0}, {0} }, /*1b8*/ + { {0}, {0} }, { {0}, {0} }, /*1b8*/ { {0}, {0} }, { {0}, {0} }, - { {0}, {0} }, { {0}, {0} }, /*1bc*/ + { {0}, {0} }, { {0}, {0} }, /*1bc*/ { {0}, {0} }, { {0}, {0} }, - { {0}, {0} }, { {0}, {0} }, /*1c0*/ + { {0}, {0} }, { {0}, {0} }, /*1c0*/ { {0}, {0} }, { {0}, {0} }, - { {0}, {0} }, { {0}, {0} }, /*1c4*/ + { {0}, {0} }, { {0}, {0} }, /*1c4*/ { {0}, {0} }, { {0}, {0} }, - { {0}, {0} }, { {0}, {0} }, /*1c8*/ + { {0}, {0} }, { {0}, {0} }, /*1c8*/ { {0}, {0} }, { {0}, {0} }, - { {0}, {0} }, { {0}, {0} }, /*1cc*/ + { {0}, {0} }, { {0}, {0} }, /*1cc*/ { {0}, {0} }, { {0}, {0} }, - { {0}, {0} }, { {0}, {0} }, /*1d0*/ + { {0}, {0} }, { {0}, {0} }, /*1d0*/ { {0}, {0} }, { {0}, {0} }, - { {0}, {0} }, { {0}, {0} }, /*1d4*/ + { {0}, {0} }, { {0}, {0} }, /*1d4*/ { {0}, {0} }, { {0}, {0} }, - { {0}, {0} }, { {0}, {0} }, /*1d8*/ + { {0}, {0} }, { {0}, {0} }, /*1d8*/ { {0}, {0} }, { {0}, {0} }, - { {0}, {0} }, { {0}, {0} }, /*1dc*/ + { {0}, {0} }, { {0}, {0} }, /*1dc*/ { {0}, {0} }, { {0}, {0} }, - { {0}, {0} }, { {0}, {0} }, /*1e0*/ + { {0}, {0} }, { {0}, {0} }, /*1e0*/ { {0}, {0} }, { {0}, {0} }, - { {0}, {0} }, { {0}, {0} }, /*1e4*/ + { {0}, {0} }, { {0}, {0} }, /*1e4*/ { {0}, {0} }, { {0}, {0} }, - { {0}, {0} }, { {0}, {0} }, /*1e8*/ + { {0}, {0} }, { {0}, {0} }, /*1e8*/ { {0}, {0} }, { {0}, {0} }, - { {0}, {0} }, { {0}, {0} }, /*1ec*/ + { {0}, {0} }, { {0}, {0} }, /*1ec*/ { {0}, {0} }, { {0}, {0} }, - { {0}, {0} }, { {0}, {0} }, /*1f0*/ + { {0}, {0} }, { {0}, {0} }, /*1f0*/ { {0}, {0} }, { {0}, {0} }, - { {0}, {0} }, { {0}, {0} }, /*1f4*/ + { {0}, {0} }, { {0}, {0} }, /*1f4*/ { {0}, {0} }, { {0}, {0} }, - { {0}, {0} }, { {0}, {0} }, /*1f8*/ + { {0}, {0} }, { {0}, {0} }, /*1f8*/ { {0}, {0} }, { {0}, {0} }, - { {0}, {0} }, { {0}, {0} } /*1fc*/ + { {0}, {0} }, { {0}, {0} } /*1fc*/ + // clang-format on }; - -static uint8_t key_queue[16]; -static int key_queue_start = 0, - key_queue_end = 0; -static int is_tandy = 0, is_t1x00 = 0, - is_amstrad = 0; - +static uint8_t key_queue[16]; +static int key_queue_start = 0; +static int key_queue_end = 0; +static int is_tandy = 0; +static int is_t1x00 = 0; +static int is_amstrad = 0; #ifdef ENABLE_KEYBOARD_XT_LOG int keyboard_xt_do_log = ENABLE_KEYBOARD_XT_LOG; - static void kbd_log(const char *fmt, ...) { va_list ap; if (keyboard_xt_do_log) { - va_start(ap, fmt); - pclog_ex(fmt, ap); - va_end(ap); + va_start(ap, fmt); + pclog_ex(fmt, ap); + va_end(ap); } } #else -#define kbd_log(fmt, ...) +# define kbd_log(fmt, ...) #endif static uint8_t -get_fdd_switch_settings() { +get_fdd_switch_settings(void) +{ - int i, fdd_count = 0; - - for (i = 0; i < FDD_NUM; i++) { - if (fdd_get_flags(i)) - fdd_count++; + uint8_t fdd_count = 0; + + for (uint8_t i = 0; i < FDD_NUM; i++) { + if (fdd_get_flags(i)) + fdd_count++; } if (!fdd_count) @@ -384,12 +392,13 @@ get_fdd_switch_settings() { } static uint8_t -get_videomode_switch_settings() { +get_videomode_switch_settings(void) +{ if (video_is_mda()) return 0x30; else if (video_is_cga()) - return 0x20; /* 0x10 would be 40x25 */ + return 0x20; /* 0x10 would be 40x25 */ else return 0x00; } @@ -397,341 +406,386 @@ get_videomode_switch_settings() { static void kbd_poll(void *priv) { - xtkbd_t *kbd = (xtkbd_t *)priv; + xtkbd_t *kbd = (xtkbd_t *) priv; timer_advance_u64(&kbd->send_delay_timer, 1000 * TIMER_USEC); if (!(kbd->pb & 0x40) && (kbd->type != KBD_TYPE_TANDY)) - return; + return; if (kbd->want_irq) { - kbd->want_irq = 0; - kbd->pa = kbd->key_waiting; - kbd->blocked = 1; - picint(2); + kbd->want_irq = 0; + kbd->pa = kbd->key_waiting; + kbd->blocked = 1; + picint(2); #ifdef ENABLE_KEYBOARD_XT_LOG - kbd_log("kbd_poll(): keyboard_xt : take IRQ\n"); + kbd_log("XTkbd: kbd_poll(): keyboard_xt : take IRQ\n"); #endif } if ((key_queue_start != key_queue_end) && !kbd->blocked) { - kbd->key_waiting = key_queue[key_queue_start]; - kbd_log("XTkbd: reading %02X from the key queue at %i\n", - kbd->key_waiting, key_queue_start); - key_queue_start = (key_queue_start + 1) & 0x0f; - kbd->want_irq = 1; + kbd->key_waiting = key_queue[key_queue_start]; + kbd_log("XTkbd: reading %02X from the key queue at %i\n", + kbd->key_waiting, key_queue_start); + key_queue_start = (key_queue_start + 1) & 0x0f; + kbd->want_irq = 1; } } - static void kbd_adddata(uint16_t val) { /* Test for T1000 'Fn' key (Right Alt / Right Ctrl) */ if (is_t1x00) { - if (keyboard_recv(0xb8) || keyboard_recv(0x9d)) { /* 'Fn' pressed */ - t1000_syskey(0x00, 0x04, 0x00); /* Set 'Fn' indicator */ - switch (val) { - case 0x45: /* Num Lock => toggle numpad */ - t1000_syskey(0x00, 0x00, 0x10); break; - case 0x47: /* Home => internal display */ - t1000_syskey(0x40, 0x00, 0x00); break; - case 0x49: /* PgDn => turbo on */ - t1000_syskey(0x80, 0x00, 0x00); break; - case 0x4D: /* Right => toggle LCD font */ - t1000_syskey(0x00, 0x00, 0x20); break; - case 0x4F: /* End => external display */ - t1000_syskey(0x00, 0x40, 0x00); break; - case 0x51: /* PgDn => turbo off */ - t1000_syskey(0x00, 0x80, 0x00); break; - case 0x54: /* SysRQ => toggle window */ - t1000_syskey(0x00, 0x00, 0x08); break; - } - } else - t1000_syskey(0x04, 0x00, 0x00); /* Reset 'Fn' indicator */ + if (keyboard_recv(0x138) || keyboard_recv(0x11d)) { /* 'Fn' pressed */ + t1000_syskey(0x00, 0x04, 0x00); /* Set 'Fn' indicator */ + switch (val) { + case 0x45: /* Num Lock => toggle numpad */ + t1000_syskey(0x00, 0x00, 0x10); + break; + case 0x47: /* Home => internal display */ + t1000_syskey(0x40, 0x00, 0x00); + break; + case 0x49: /* PgDn => turbo on */ + t1000_syskey(0x80, 0x00, 0x00); + break; + case 0x4D: /* Right => toggle LCD font */ + t1000_syskey(0x00, 0x00, 0x20); + break; + case 0x4F: /* End => external display */ + t1000_syskey(0x00, 0x40, 0x00); + break; + case 0x51: /* PgDn => turbo off */ + t1000_syskey(0x00, 0x80, 0x00); + break; + case 0x54: /* SysRQ => toggle window */ + t1000_syskey(0x00, 0x00, 0x08); + break; + + default: + break; + } + } else + t1000_syskey(0x04, 0x00, 0x00); /* Reset 'Fn' indicator */ } key_queue[key_queue_end] = val; kbd_log("XTkbd: %02X added to key queue at %i\n", - val, key_queue_end); + val, key_queue_end); key_queue_end = (key_queue_end + 1) & 0x0f; } - void kbd_adddata_process(uint16_t val, void (*adddata)(uint16_t val)) { - uint8_t num_lock = 0, shift_states = 0; + uint8_t num_lock = 0; + uint8_t shift_states = 0; if (!adddata) - return; + return; keyboard_get_states(NULL, &num_lock, NULL); shift_states = keyboard_get_shift() & STATE_LSHIFT; if (is_amstrad) - num_lock = !num_lock; + num_lock = !num_lock; /* If NumLock is on, invert the left shift state so we can always check for the the same way flag being set (and with NumLock on that then means it is actually *NOT* set). */ if (num_lock) - shift_states ^= STATE_LSHIFT; + shift_states ^= STATE_LSHIFT; - switch(val) { - case FAKE_LSHIFT_ON: - /* If NumLock is on, fake shifts are sent when shift is *NOT* presed, - if NumLock is off, fake shifts are sent when shift is pressed. */ - if (shift_states) { - /* Send fake shift. */ - adddata(num_lock ? 0x2a : 0xaa); - } - break; - case FAKE_LSHIFT_OFF: - if (shift_states) { - /* Send fake shift. */ - adddata(num_lock ? 0xaa : 0x2a); - } - break; - default: - adddata(val); - break; + switch (val) { + case FAKE_LSHIFT_ON: + /* If NumLock is on, fake shifts are sent when shift is *NOT* presed, + if NumLock is off, fake shifts are sent when shift is pressed. */ + if (shift_states) { + /* Send fake shift. */ + adddata(num_lock ? 0x2a : 0xaa); + } + break; + case FAKE_LSHIFT_OFF: + if (shift_states) { + /* Send fake shift. */ + adddata(num_lock ? 0xaa : 0x2a); + } + break; + default: + adddata(val); + break; } } - static void kbd_adddata_ex(uint16_t val) { kbd_adddata_process(val, kbd_adddata); } - static void kbd_write(uint16_t port, uint8_t val, void *priv) { - xtkbd_t *kbd = (xtkbd_t *)priv; + xtkbd_t *kbd = (xtkbd_t *) priv; + uint8_t bit; + uint8_t set; + uint8_t new_clock; switch (port) { - case 0x61: /* Keyboard Control Register (aka Port B) */ - if (!(kbd->pb & 0x40) && (val & 0x40)) { - key_queue_start = key_queue_end = 0; - kbd->want_irq = 0; - kbd->blocked = 0; - kbd_adddata(0xaa); - } - kbd->pb = val; - ppi.pb = val; + case 0x61: /* Keyboard Control Register (aka Port B) */ + if (!(val & 0x80) || (kbd->type == KBD_TYPE_HYUNDAI)) { + new_clock = !!(val & 0x40); + if (!kbd->clock && new_clock) { + key_queue_start = key_queue_end = 0; + kbd->want_irq = 0; + kbd->blocked = 0; + kbd_adddata(0xaa); + } + } + kbd->pb = val; + if (!(kbd->pb & 0x80) || (kbd->type == KBD_TYPE_HYUNDAI)) + kbd->clock = !!(kbd->pb & 0x40); + ppi.pb = val; - timer_process(); + timer_process(); - if (((kbd->type == KBD_TYPE_PC81) || (kbd->type == KBD_TYPE_PC82)) && (cassette != NULL)) - pc_cas_set_motor(cassette, (kbd->pb & 0x08) == 0); + if (((kbd->type == KBD_TYPE_PC81) || (kbd->type == KBD_TYPE_PC82) || + (kbd->type == KBD_TYPE_PRAVETZ)) && (cassette != NULL)) + pc_cas_set_motor(cassette, (kbd->pb & 0x08) == 0); - speaker_update(); + speaker_update(); - speaker_gated = val & 1; - speaker_enable = val & 2; + speaker_gated = val & 1; + speaker_enable = val & 2; - if (speaker_enable) - was_speaker_enable = 1; - pit_ctr_set_gate(&pit->counters[2], val & 1); + if (speaker_enable) + was_speaker_enable = 1; + pit_devs[0].set_gate(pit_devs[0].data, 2, val & 1); - if (val & 0x80) { - kbd->pa = 0; - kbd->blocked = 0; - picintc(2); - } + if (val & 0x80) { + kbd->pa = 0; + kbd->blocked = 0; + picintc(2); + } #ifdef ENABLE_KEYBOARD_XT_LOG - if ((kbd->type == KBD_TYPE_PC81) || (kbd->type == KBD_TYPE_PC82)) - kbd_log("Cassette motor is %s\n", !(val & 0x08) ? "ON" : "OFF"); + if ((kbd->type == KBD_TYPE_PC81) || (kbd->type == KBD_TYPE_PC82) || (kbd->type == KBD_TYPE_PRAVETZ)) + kbd_log("XTkbd: Cassette motor is %s\n", !(val & 0x08) ? "ON" : "OFF"); #endif - break; + break; #ifdef ENABLE_KEYBOARD_XT_LOG - case 0x62: /* Switch Register (aka Port C) */ - if ((kbd->type == KBD_TYPE_PC81) || (kbd->type == KBD_TYPE_PC82)) - kbd_log("Cassette IN is %i\n", !!(val & 0x10)); - break; + case 0x62: /* Switch Register (aka Port C) */ + if ((kbd->type == KBD_TYPE_PC81) || (kbd->type == KBD_TYPE_PC82) || (kbd->type == KBD_TYPE_PRAVETZ)) + kbd_log("XTkbd: Cassette IN is %i\n", !!(val & 0x10)); + break; #endif + + case 0xc0 ... 0xcf: /* Pravetz Flags */ + kbd_log("XTkbd: Port %02X out: %02X\n", port, val); + if (kbd->type == KBD_TYPE_PRAVETZ) { + bit = (port >> 1) & 0x07; + set = (port & 0x01) << bit; + kbd->pravetz_flags = (kbd->pravetz_flags & ~(1 << bit)) | set; + } + break; + + default: + break; } } - static uint8_t kbd_read(uint16_t port, void *priv) { - xtkbd_t *kbd = (xtkbd_t *)priv; - uint8_t ret = 0xff; + const xtkbd_t *kbd = (xtkbd_t *) priv; + uint8_t ret = 0xff; switch (port) { - case 0x60: /* Keyboard Data Register (aka Port A) */ - if ((kbd->pb & 0x80) && ((kbd->type == KBD_TYPE_PC81) || (kbd->type == KBD_TYPE_PC82) - || (kbd->type == KBD_TYPE_XT82) || (kbd->type == KBD_TYPE_XT86) - || (kbd->type == KBD_TYPE_ZENITH))) { - if ((kbd->type == KBD_TYPE_PC81) || (kbd->type == KBD_TYPE_PC82)) - ret = (kbd->pd & ~0x02) | (hasfpu ? 0x02 : 0x00); - else if ((kbd->type == KBD_TYPE_XT82) || (kbd->type == KBD_TYPE_XT86)) - ret = 0xff; /* According to Ruud on the PCem forum, this is supposed to return 0xFF on the XT. */ - else if (kbd->type == KBD_TYPE_ZENITH) { - /* Zenith Data Systems Z-151 - * SW1 switch settings: - * bits 6-7: floppy drive number - * bits 4-5: video mode - * bit 2-3: base memory size - * bit 1: fpu enable - * bit 0: fdc enable - */ - ret = get_fdd_switch_settings(); + case 0x60: /* Keyboard Data Register (aka Port A) */ + if ((kbd->pb & 0x80) && ((kbd->type == KBD_TYPE_PC81) || + (kbd->type == KBD_TYPE_PC82) || (kbd->type == KBD_TYPE_PRAVETZ) || + (kbd->type == KBD_TYPE_XT82) || (kbd->type == KBD_TYPE_XT86) || + (kbd->type == KBD_TYPE_XTCLONE) || (kbd->type == KBD_TYPE_COMPAQ) || + (kbd->type == KBD_TYPE_ZENITH) || (kbd->type == KBD_TYPE_HYUNDAI))) { + if ((kbd->type == KBD_TYPE_PC81) || (kbd->type == KBD_TYPE_PC82) || + (kbd->type == KBD_TYPE_XTCLONE) || (kbd->type == KBD_TYPE_COMPAQ) || + (kbd->type == KBD_TYPE_PRAVETZ) || (kbd->type == KBD_TYPE_HYUNDAI)) + ret = (kbd->pd & ~0x02) | (hasfpu ? 0x02 : 0x00); + else if ((kbd->type == KBD_TYPE_XT82) || (kbd->type == KBD_TYPE_XT86)) + /* According to Ruud on the PCem forum, this is supposed to + return 0xFF on the XT. */ + ret = 0xff; + else if (kbd->type == KBD_TYPE_ZENITH) { + /* Zenith Data Systems Z-151 + * SW1 switch settings: + * bits 6-7: floppy drive number + * bits 4-5: video mode + * bit 2-3: base memory size + * bit 1: fpu enable + * bit 0: fdc enable + */ + ret = get_fdd_switch_settings(); - ret |= get_videomode_switch_settings(); + ret |= get_videomode_switch_settings(); - /* Base memory size should always be 64k */ - ret |= 0x0c; + /* Base memory size should always be 64k */ + ret |= 0x0c; - if (hasfpu) - ret |= 0x02; - } - } else - ret = kbd->pa; - break; - - case 0x61: /* Keyboard Control Register (aka Port B) */ - ret = kbd->pb; - break; - - case 0x62: /* Switch Register (aka Port C) */ - if ((kbd->type == KBD_TYPE_PC81) || (kbd->type == KBD_TYPE_PC82)) { - if (kbd->pb & 0x04) /* PB2 */ - switch (mem_size + isa_mem_size) { - case 64: - case 48: - case 32: - case 16: - ret = 0x00; - break; - default: - ret = (((mem_size + isa_mem_size) - 64) / 32) & 0x0f; - break; + if (hasfpu) + ret |= 0x02; } - else - ret = (((mem_size + isa_mem_size) - 64) / 32) >> 4; - } else if (kbd->type == KBD_TYPE_OLIVETTI - || kbd->type == KBD_TYPE_ZENITH) { - /* Olivetti M19 or Zenith Data Systems Z-151 */ - if (kbd->pb & 0x04) /* PB2 */ - ret = kbd->pd & 0xbf; - else - ret = kbd->pd >> 4; - } else { - if (kbd->pb & 0x08) /* PB3 */ - ret = kbd->pd >> 4; - else { - /* LaserXT = Always 512k RAM; - LaserXT/3 = Bit 0: set = 512k, clear = 256k. */ + } else + ret = kbd->pa; + break; + + case 0x61: /* Keyboard Control Register (aka Port B) */ + ret = kbd->pb; + break; + + case 0x62: /* Switch Register (aka Port C) */ + if ((kbd->type == KBD_TYPE_PC81) || (kbd->type == KBD_TYPE_PC82) || + (kbd->type == KBD_TYPE_PRAVETZ)) { + if (kbd->pb & 0x04) /* PB2 */ + switch (mem_size + isa_mem_size) { + case 64: + case 48: + case 32: + case 16: + ret = 0x00; + break; + default: + ret = (((mem_size + isa_mem_size) - 64) / 32) & 0x0f; + break; + } + else + ret = (((mem_size + isa_mem_size) - 64) / 32) >> 4; + } else if ((kbd->type == KBD_TYPE_OLIVETTI) || + (kbd->type == KBD_TYPE_ZENITH)) { + /* Olivetti M19 or Zenith Data Systems Z-151 */ + if (kbd->pb & 0x04) /* PB2 */ + ret = kbd->pd & 0xbf; + else + ret = kbd->pd >> 4; + } else { + if (kbd->pb & 0x08) /* PB3 */ + ret = kbd->pd >> 4; + else { + /* LaserXT = Always 512k RAM; + LaserXT/3 = Bit 0: set = 512k, clear = 256k. */ #if defined(DEV_BRANCH) && defined(USE_LASERXT) - if (kbd->type == KBD_TYPE_TOSHIBA) - ret = ((mem_size == 512) ? 0x0d : 0x0c) | (hasfpu ? 0x02 : 0x00); - else + if (kbd->type == KBD_TYPE_VTECH) + ret = ((mem_size == 512) ? 0x0d : 0x0c) | (hasfpu ? 0x02 : 0x00); + else #endif - ret = (kbd->pd & 0x0d) | (hasfpu ? 0x02 : 0x00); - } - } - ret |= (ppispeakon ? 0x20 : 0); + ret = (kbd->pd & 0x0d) | (hasfpu ? 0x02 : 0x00); + } + } + ret |= (ppispeakon ? 0x20 : 0); - /* This is needed to avoid error 131 (cassette error). - This is serial read: bit 5 = clock, bit 4 = data, cassette header is 256 x 0xff. */ - if ((kbd->type == KBD_TYPE_PC81) || (kbd->type == KBD_TYPE_PC82)) { - if (cassette == NULL) - ret |= (ppispeakon ? 0x10 : 0); - else - ret |= (pc_cas_get_inp(cassette) ? 0x10 : 0); - } + /* This is needed to avoid error 131 (cassette error). + This is serial read: bit 5 = clock, bit 4 = data, cassette header is 256 x 0xff. */ + if ((kbd->type == KBD_TYPE_PC81) || (kbd->type == KBD_TYPE_PC82) || + (kbd->type == KBD_TYPE_PRAVETZ)) { + if (cassette == NULL) + ret |= (ppispeakon ? 0x10 : 0); + else + ret |= (pc_cas_get_inp(cassette) ? 0x10 : 0); + } - if (kbd->type == KBD_TYPE_TANDY) - ret |= (tandy1k_eeprom_read() ? 0x10 : 0); - break; + if (kbd->type == KBD_TYPE_TANDY) + ret |= (tandy1k_eeprom_read() ? 0x10 : 0); + break; - case 0x63: /* Keyboard Configuration Register (aka Port D) */ - if ((kbd->type == KBD_TYPE_XT82) || (kbd->type == KBD_TYPE_XT86) - || (kbd->type == KBD_TYPE_COMPAQ) - || (kbd->type == KBD_TYPE_TOSHIBA)) - ret = kbd->pd; - break; + case 0x63: /* Keyboard Configuration Register (aka Port D) */ + if ((kbd->type == KBD_TYPE_XT82) || (kbd->type == KBD_TYPE_XT86) || + (kbd->type == KBD_TYPE_XTCLONE) || (kbd->type == KBD_TYPE_COMPAQ) || + (kbd->type == KBD_TYPE_TOSHIBA) || (kbd->type == KBD_TYPE_HYUNDAI)) + ret = kbd->pd; + break; + + case 0xc0: /* Pravetz Flags */ + if (kbd->type == KBD_TYPE_PRAVETZ) + ret = kbd->pravetz_flags; + kbd_log("XTkbd: Port %02X in : %02X\n", port, ret); + break; + + default: + break; } - return(ret); + return ret; } - static void kbd_reset(void *priv) { - xtkbd_t *kbd = (xtkbd_t *)priv; + xtkbd_t *kbd = (xtkbd_t *) priv; - kbd->want_irq = 0; - kbd->blocked = 0; - kbd->pa = 0x00; - kbd->pb = 0x00; + kbd->want_irq = 0; + kbd->blocked = 0; + kbd->pa = 0x00; + kbd->pb = 0x00; + kbd->pravetz_flags = 0x00; keyboard_scan = 1; - key_queue_start = 0, - key_queue_end = 0; + key_queue_start = 0; + key_queue_end = 0; } - void keyboard_set_is_amstrad(int ams) { is_amstrad = ams; } - static void * kbd_init(const device_t *info) { xtkbd_t *kbd; - kbd = (xtkbd_t *)malloc(sizeof(xtkbd_t)); + kbd = (xtkbd_t *) malloc(sizeof(xtkbd_t)); memset(kbd, 0x00, sizeof(xtkbd_t)); io_sethandler(0x0060, 4, - kbd_read, NULL, NULL, kbd_write, NULL, NULL, kbd); + kbd_read, NULL, NULL, kbd_write, NULL, NULL, kbd); keyboard_send = kbd_adddata_ex; kbd_reset(kbd); kbd->type = info->local; + if (kbd->type == KBD_TYPE_PRAVETZ) { + io_sethandler(0x00c0, 16, + kbd_read, NULL, NULL, kbd_write, NULL, NULL, kbd); + } key_queue_start = key_queue_end = 0; - video_reset(gfxcard); - - if ((kbd->type == KBD_TYPE_PC81) || (kbd->type == KBD_TYPE_PC82) - || (kbd->type == KBD_TYPE_XT82) || (kbd->type <= KBD_TYPE_XT86) - || (kbd->type == KBD_TYPE_COMPAQ) - || (kbd->type == KBD_TYPE_TOSHIBA) - || (kbd->type == KBD_TYPE_OLIVETTI)) { + video_reset(gfxcard[0]); + if ((kbd->type == KBD_TYPE_PC81) || (kbd->type == KBD_TYPE_PC82) || + (kbd->type == KBD_TYPE_PRAVETZ) || (kbd->type == KBD_TYPE_XT82) || + (kbd->type <= KBD_TYPE_XT86) || (kbd->type == KBD_TYPE_XTCLONE) || + (kbd->type == KBD_TYPE_COMPAQ) || (kbd->type == KBD_TYPE_TOSHIBA) || + (kbd->type == KBD_TYPE_OLIVETTI) || (kbd->type == KBD_TYPE_HYUNDAI)) { /* DIP switch readout: bit set = OFF, clear = ON. */ if (kbd->type == KBD_TYPE_OLIVETTI) - /* Olivetti M19 - * Jumpers J1, J2 - monitor type. - * 01 - mono (high-res) - * 10 - color (low-res, disables 640x400x2 mode) - * 00 - autoswitching - */ - kbd->pd |= 0x00; - else - /* Switches 7, 8 - floppy drives. */ - kbd->pd = get_fdd_switch_settings(); + /* Olivetti M19 + * Jumpers J1, J2 - monitor type. + * 01 - mono (high-res) + * 10 - color (low-res, disables 640x400x2 mode) + * 00 - autoswitching + */ + kbd->pd |= 0x00; + else + /* Switches 7, 8 - floppy drives. */ + kbd->pd = get_fdd_switch_settings(); /* Siitches 5, 6 - video card type */ - kbd->pd |= get_videomode_switch_settings(); + kbd->pd |= get_videomode_switch_settings(); /* Switches 3, 4 - memory size. */ - if ((kbd->type == KBD_TYPE_XT86) - || (kbd->type == KBD_TYPE_COMPAQ) - || (kbd->type == KBD_TYPE_TOSHIBA)) { + if ((kbd->type == KBD_TYPE_XT86) || (kbd->type == KBD_TYPE_XTCLONE) || + (kbd->type == KBD_TYPE_HYUNDAI) || (kbd->type == KBD_TYPE_COMPAQ) || + (kbd->type == KBD_TYPE_TOSHIBA)) { switch (mem_size) { case 256: kbd->pd |= 0x00; @@ -747,9 +801,9 @@ kbd_init(const device_t *info) kbd->pd |= 0x0c; break; } - } else if (kbd->type == KBD_TYPE_XT82) { + } else if (kbd->type == KBD_TYPE_XT82) { switch (mem_size) { - case 64: /* 1x64k */ + case 64: /* 1x64k */ kbd->pd |= 0x00; break; case 128: /* 2x64k */ @@ -763,7 +817,7 @@ kbd_init(const device_t *info) kbd->pd |= 0x0c; break; } - } else if (kbd->type == KBD_TYPE_PC82) { + } else if (kbd->type == KBD_TYPE_PC82) { switch (mem_size) { case 192: /* 3x64k, not supported by stock BIOS due to bugs */ kbd->pd |= 0x08; @@ -793,19 +847,19 @@ kbd_init(const device_t *info) default: kbd->pd |= 0x0c; break; - } - } + } + } /* Switch 2 - 8087 FPU. */ if (hasfpu) kbd->pd |= 0x02; - } else if (kbd-> type == KBD_TYPE_ZENITH) { + } else if (kbd->type == KBD_TYPE_ZENITH) { /* Zenith Data Systems Z-151 - * SW2 switch settings: - * bit 7: monitor frequency - * bits 5-6: autoboot (00-11 resident monitor, 10 hdd, 01 fdd) - * bits 0-4: installed memory - */ + * SW2 switch settings: + * bit 7: monitor frequency + * bits 5-6: autoboot (00-11 resident monitor, 10 hdd, 01 fdd) + * bits 0-4: installed memory + */ kbd->pd = 0x20; switch (mem_size) { case 128: @@ -848,14 +902,13 @@ kbd_init(const device_t *info) is_amstrad = 0; - return(kbd); + return kbd; } - static void kbd_close(void *priv) { - xtkbd_t *kbd = (xtkbd_t *)priv; + xtkbd_t *kbd = (xtkbd_t *) priv; /* Stop the timer. */ timer_disable(&kbd->send_delay_timer); @@ -866,120 +919,191 @@ kbd_close(void *priv) keyboard_send = NULL; io_removehandler(0x0060, 4, - kbd_read, NULL, NULL, kbd_write, NULL, NULL, kbd); + kbd_read, NULL, NULL, kbd_write, NULL, NULL, kbd); free(kbd); } - const device_t keyboard_pc_device = { - "IBM PC Keyboard (1981)", - "keyboard_pc", - 0, - KBD_TYPE_PC81, - kbd_init, - kbd_close, - kbd_reset, - { NULL }, NULL, NULL + .name = "IBM PC Keyboard (1981)", + .internal_name = "keyboard_pc", + .flags = 0, + .local = KBD_TYPE_PC81, + .init = kbd_init, + .close = kbd_close, + .reset = kbd_reset, + { .available = NULL }, + .speed_changed = NULL, + .force_redraw = NULL, + .config = NULL }; const device_t keyboard_pc82_device = { - "IBM PC Keyboard (1982)", - "keyboard_pc82", - 0, - KBD_TYPE_PC82, - kbd_init, - kbd_close, - kbd_reset, - { NULL }, NULL, NULL + .name = "IBM PC Keyboard (1982)", + .internal_name = "keyboard_pc82", + .flags = 0, + .local = KBD_TYPE_PC82, + .init = kbd_init, + .close = kbd_close, + .reset = kbd_reset, + { .available = NULL }, + .speed_changed = NULL, + .force_redraw = NULL, + .config = NULL +}; + +const device_t keyboard_pravetz_device = { + .name = "Pravetz Keyboard", + .internal_name = "keyboard_pravetz", + .flags = 0, + .local = KBD_TYPE_PRAVETZ, + .init = kbd_init, + .close = kbd_close, + .reset = kbd_reset, + { .available = NULL }, + .speed_changed = NULL, + .force_redraw = NULL, + .config = NULL }; const device_t keyboard_xt_device = { - "XT (1982) Keyboard", - "keyboard_xt", - 0, - KBD_TYPE_XT82, - kbd_init, - kbd_close, - kbd_reset, - { NULL }, NULL, NULL + .name = "XT (1982) Keyboard", + .internal_name = "keyboard_xt", + .flags = 0, + .local = KBD_TYPE_XT82, + .init = kbd_init, + .close = kbd_close, + .reset = kbd_reset, + { .available = NULL }, + .speed_changed = NULL, + .force_redraw = NULL, + .config = NULL }; const device_t keyboard_xt86_device = { - "XT (1986) Keyboard", - "keyboard_xt86", - 0, - KBD_TYPE_XT86, - kbd_init, - kbd_close, - kbd_reset, - { NULL }, NULL, NULL + .name = "XT (1986) Keyboard", + .internal_name = "keyboard_xt86", + .flags = 0, + .local = KBD_TYPE_XT86, + .init = kbd_init, + .close = kbd_close, + .reset = kbd_reset, + { .available = NULL }, + .speed_changed = NULL, + .force_redraw = NULL, + .config = NULL }; const device_t keyboard_xt_compaq_device = { - "Compaq Portable Keyboard", - "keyboard_xt_compaq", - 0, - KBD_TYPE_COMPAQ, - kbd_init, - kbd_close, - kbd_reset, - { NULL }, NULL, NULL + .name = "Compaq Portable Keyboard", + .internal_name = "keyboard_xt_compaq", + .flags = 0, + .local = KBD_TYPE_COMPAQ, + .init = kbd_init, + .close = kbd_close, + .reset = kbd_reset, + { .available = NULL }, + .speed_changed = NULL, + .force_redraw = NULL, + .config = NULL }; const device_t keyboard_tandy_device = { - "Tandy 1000 Keyboard", - "keyboard_tandy", - 0, - KBD_TYPE_TANDY, - kbd_init, - kbd_close, - kbd_reset, - { NULL }, NULL, NULL + .name = "Tandy 1000 Keyboard", + .internal_name = "keyboard_tandy", + .flags = 0, + .local = KBD_TYPE_TANDY, + .init = kbd_init, + .close = kbd_close, + .reset = kbd_reset, + { .available = NULL }, + .speed_changed = NULL, + .force_redraw = NULL, + .config = NULL }; const device_t keyboard_xt_t1x00_device = { - "Toshiba T1x00 Keyboard", - "keyboard_xt_t1x00", - 0, - KBD_TYPE_TOSHIBA, - kbd_init, - kbd_close, - kbd_reset, - { NULL }, NULL, NULL + .name = "Toshiba T1x00 Keyboard", + .internal_name = "keyboard_xt_t1x00", + .flags = 0, + .local = KBD_TYPE_TOSHIBA, + .init = kbd_init, + .close = kbd_close, + .reset = kbd_reset, + { .available = NULL }, + .speed_changed = NULL, + .force_redraw = NULL, + .config = NULL }; #if defined(DEV_BRANCH) && defined(USE_LASERXT) const device_t keyboard_xt_lxt3_device = { - "VTech Laser XT3 Keyboard", - "keyboard_xt_lxt3", - 0, - KBD_TYPE_VTECH, - kbd_init, - kbd_close, - kbd_reset, - { NULL }, NULL, NULL + .name = "VTech Laser XT3 Keyboard", + .internal_name = "keyboard_xt_lxt3", + .flags = 0, + .local = KBD_TYPE_VTECH, + .init = kbd_init, + .close = kbd_close, + .reset = kbd_reset, + { .available = NULL }, + .speed_changed = NULL, + .force_redraw = NULL, + .config = NULL }; #endif const device_t keyboard_xt_olivetti_device = { - "Olivetti XT Keyboard", - "keyboard_xt_olivetti", - 0, - KBD_TYPE_OLIVETTI, - kbd_init, - kbd_close, - kbd_reset, - { NULL }, NULL, NULL + .name = "Olivetti XT Keyboard", + .internal_name = "keyboard_xt_olivetti", + .flags = 0, + .local = KBD_TYPE_OLIVETTI, + .init = kbd_init, + .close = kbd_close, + .reset = kbd_reset, + { .available = NULL }, + .speed_changed = NULL, + .force_redraw = NULL, + .config = NULL }; const device_t keyboard_xt_zenith_device = { - "Zenith XT Keyboard", - "keyboard_xt_zenith", - 0, - KBD_TYPE_ZENITH, - kbd_init, - kbd_close, - kbd_reset, - { NULL }, NULL, NULL + .name = "Zenith XT Keyboard", + .internal_name = "keyboard_xt_zenith", + .flags = 0, + .local = KBD_TYPE_ZENITH, + .init = kbd_init, + .close = kbd_close, + .reset = kbd_reset, + { .available = NULL }, + .speed_changed = NULL, + .force_redraw = NULL, + .config = NULL +}; + +const device_t keyboard_xt_hyundai_device = { + .name = "Hyundai XT Keyboard", + .internal_name = "keyboard_x_hyundai", + .flags = 0, + .local = KBD_TYPE_HYUNDAI, + .init = kbd_init, + .close = kbd_close, + .reset = kbd_reset, + { .available = NULL }, + .speed_changed = NULL, + .force_redraw = NULL, + .config = NULL +}; + +const device_t keyboard_xtclone_device = { + .name = "XT (Clone) Keyboard", + .internal_name = "keyboard_xtclone", + .flags = 0, + .local = KBD_TYPE_XTCLONE, + .init = kbd_init, + .close = kbd_close, + .reset = kbd_reset, + { .available = NULL }, + .speed_changed = NULL, + .force_redraw = NULL, + .config = NULL }; diff --git a/src/device/mouse.c b/src/device/mouse.c index 662d5e76e..193149bc8 100644 --- a/src/device/mouse.c +++ b/src/device/mouse.c @@ -1,25 +1,27 @@ /* - * 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. + * 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. + * This file is part of the 86Box distribution. * - * Common driver module for MOUSE devices. + * Common driver module for MOUSE devices. * - * TODO: Add the Genius bus- and serial mouse. - * Remove the '3-button' flag from mouse types. + * TODO: Add the Genius bus- and serial mouse. + * Remove the '3-button' flag from mouse types. * * * - * Authors: Miran Grca, - * Fred N. van Kempen, + * Authors: Miran Grca, + * Fred N. van Kempen, * - * Copyright 2016-2018 Miran Grca. - * Copyright 2017,2018 Fred N. van Kempen. + * Copyright 2016-2018 Miran Grca. + * Copyright 2017-2018 Fred N. van Kempen. */ +#include #include +#include #include #include #include @@ -27,131 +29,486 @@ #define HAVE_STDARG_H #include <86box/86box.h> #include <86box/device.h> +#include <86box/timer.h> +#include <86box/gdbstub.h> #include <86box/mouse.h> +#include <86box/video.h> +#include <86box/plat.h> +#include <86box/plat_unused.h> - -typedef struct { - const device_t *device; +typedef struct mouse_t { + const device_t *device; } mouse_t; +int mouse_type = 0; +int mouse_input_mode; +int mouse_timed = 1; +int mouse_tablet_in_proximity = 0; +int tablet_tool_type = 1; /* 0 = Puck/Cursor, 1 = Pen */ -int mouse_type = 0; -int mouse_x, - mouse_y, - mouse_z, - mouse_buttons; +double mouse_x_abs; +double mouse_y_abs; +double mouse_sensitivity = 1.0; + +pc_timer_t mouse_timer; /* mouse event timer */ static const device_t mouse_none_device = { - "None", - "none", - 0, MOUSE_TYPE_NONE, - NULL, NULL, NULL, - { NULL }, NULL, NULL, - NULL -}; -static const device_t mouse_internal_device = { - "Internal", - "internal", - 0, MOUSE_TYPE_INTERNAL, - NULL, NULL, NULL, - { NULL }, NULL, NULL, - NULL + .name = "None", + .internal_name = "none", + .flags = 0, + .local = MOUSE_TYPE_NONE, + .init = NULL, + .close = NULL, + .reset = NULL, + { .poll = NULL }, + .speed_changed = NULL, + .force_redraw = NULL, + .config = NULL }; +static const device_t mouse_internal_device = { + .name = "Internal", + .internal_name = "internal", + .flags = 0, + .local = MOUSE_TYPE_INTERNAL, + .init = NULL, + .close = NULL, + .reset = NULL, + { .poll = NULL }, + .speed_changed = NULL, + .force_redraw = NULL, + .config = NULL +}; static mouse_t mouse_devices[] = { - { &mouse_none_device }, - { &mouse_internal_device }, - { &mouse_logibus_device }, - { &mouse_msinport_device }, -#if 0 - { &mouse_genibus_device }, + // clang-format off + { &mouse_none_device }, + { &mouse_internal_device }, + { &mouse_logibus_device }, + { &mouse_msinport_device }, +#ifdef USE_GENIBUS + { &mouse_genibus_device }, #endif - { &mouse_mssystems_device }, - { &mouse_msserial_device }, - { &mouse_ltserial_device }, - { &mouse_ps2_device }, - { NULL } + { &mouse_mssystems_device }, + { &mouse_msserial_device }, + { &mouse_ltserial_device }, + { &mouse_ps2_device }, +#ifdef USE_WACOM + { &mouse_wacom_device }, + { &mouse_wacom_artpad_device }, +#endif + { NULL } + // clang-format on }; +static _Atomic double mouse_x; +static _Atomic double mouse_y; +static atomic_int mouse_z; +static atomic_int mouse_buttons; -static const device_t *mouse_curr; -static void *mouse_priv; -static int mouse_nbut; -static int (*mouse_dev_poll)(); +static int mouse_delta_b; +static int mouse_old_b; +static const device_t *mouse_curr; +static void *mouse_priv; +static int mouse_nbut; +static int mouse_raw; +static int (*mouse_dev_poll)(void *priv); +static void (*mouse_poll_ex)(void) = NULL; + +static double sample_rate = 200.0; #ifdef ENABLE_MOUSE_LOG int mouse_do_log = ENABLE_MOUSE_LOG; - static void mouse_log(const char *fmt, ...) { va_list ap; if (mouse_do_log) { - va_start(ap, fmt); - pclog_ex(fmt, ap); - va_end(ap); + va_start(ap, fmt); + pclog_ex(fmt, ap); + va_end(ap); } } #else -#define mouse_log(fmt, ...) +# define mouse_log(fmt, ...) #endif - -/* Initialize the mouse module. */ void -mouse_init(void) +mouse_clear_x(void) { - /* Initialize local data. */ - mouse_x = mouse_y = mouse_z = 0; - mouse_buttons = 0x00; - - mouse_type = MOUSE_TYPE_NONE; - mouse_curr = NULL; - mouse_priv = NULL; - mouse_nbut = 0; - mouse_dev_poll = NULL; + mouse_x = 0.0; } - void -mouse_close(void) +mouse_clear_y(void) { - if (mouse_curr == NULL) return; - - mouse_curr = NULL; - mouse_priv = NULL; - mouse_nbut = 0; - mouse_dev_poll = NULL; + mouse_y = 0.0; } - void -mouse_reset(void) +mouse_clear_coords(void) { - if (mouse_curr != NULL) - return; /* Mouse already initialized. */ + mouse_clear_x(); + mouse_clear_y(); - mouse_log("MOUSE: reset(type=%d, '%s')\n", - mouse_type, mouse_devices[mouse_type].device->name); - - /* Clear local data. */ - mouse_x = mouse_y = mouse_z = 0; - mouse_buttons = 0x00; - - /* If no mouse configured, we're done. */ - if (mouse_type == 0) return; - - mouse_curr = mouse_devices[mouse_type].device; - - if (mouse_curr != NULL) - mouse_priv = device_add(mouse_curr); + mouse_z = 0; } +void +mouse_clear_buttons(void) +{ + mouse_buttons = 0x00; + mouse_old_b = 0x00; + + mouse_delta_b = 0x00; +} + +static double +mouse_scale_coord_x(double x, int mul) +{ + double ratio = 1.0; + + if (!mouse_raw) + ratio = ((double) monitors[0].mon_unscaled_size_x) / monitors[0].mon_res_x; + + if (mul) + x *= ratio; + else + x /= ratio; + + return x; +} + +static double +mouse_scale_coord_y(double y, int mul) +{ + double ratio = 1.0; + + if (!mouse_raw) + ratio = ((double) monitors[0].mon_efscrnsz_y) / monitors[0].mon_res_y; + + if (mul) + y *= ratio; + else + y /= ratio; + + return y; +} + +void +mouse_subtract_x(int *delta_x, int *o_x, int min, int max, int abs) +{ + double real_x = atomic_load(&mouse_x); + double smax_x; + double rsmin_x; + double smin_x; + int ds_x; + int scaled_x; + + rsmin_x = mouse_scale_coord_x(min, 0); + if (abs) { + smax_x = mouse_scale_coord_x(max, 0) + ABS(rsmin_x); + max += ABSD(min); + real_x += rsmin_x; + smin_x = 0; + } else { + smax_x = mouse_scale_coord_x(max, 0); + smin_x = rsmin_x; + } + + smax_x = floor(smax_x); + smin_x = ceil(smin_x); + + /* Default the X overflow to 1. */ + if (o_x != NULL) + *o_x = 1; + + ds_x = mouse_scale_coord_x(real_x, 1); + + if (ds_x >= 0.0) + scaled_x = (int) floor(mouse_scale_coord_x(real_x, 1)); + else + scaled_x = (int) ceil(mouse_scale_coord_x(real_x, 1)); + + if (real_x > smax_x) { + if (abs) { + *delta_x = scaled_x; + real_x -= mouse_scale_coord_x((double) scaled_x, 0); + } else { + *delta_x = max; + real_x -= smax_x; + } + } else if (real_x < smin_x) { + if (abs) { + *delta_x = scaled_x; + real_x -= mouse_scale_coord_x((double) scaled_x, 0); + } else { + *delta_x = min; + real_x += ABSD(smin_x); + } + } else { + *delta_x = scaled_x; + real_x -= mouse_scale_coord_x((double) scaled_x, 0); + if (o_x != NULL) + *o_x = 0; + } + + if (abs) + real_x -= rsmin_x; + + atomic_store(&mouse_x, real_x); +} + +/* It appears all host platforms give us y in the Microsoft format + (positive to the south), so for all non-Microsoft report formsts, + we have to invert that. */ +void +mouse_subtract_y(int *delta_y, int *o_y, int min, int max, int invert, int abs) +{ + double real_y = atomic_load(&mouse_y); + double smax_y; + double rsmin_y; + double smin_y; + int ds_y; + int scaled_y; + + if (invert) + real_y = -real_y; + + rsmin_y = mouse_scale_coord_y(min, 0); + if (abs) { + smax_y = mouse_scale_coord_y(max, 0) + ABS(rsmin_y); + max += ABSD(min); + real_y += rsmin_y; + smin_y = 0; + } else { + smax_y = mouse_scale_coord_y(max, 0); + smin_y = rsmin_y; + } + + smax_y = floor(smax_y); + smin_y = ceil(smin_y); + + /* Default Y overflow to 1. */ + if (o_y != NULL) + *o_y = 1; + + ds_y = mouse_scale_coord_x(real_y, 1); + + if (ds_y >= 0.0) + scaled_y = (int) floor(mouse_scale_coord_x(real_y, 1)); + else + scaled_y = (int) ceil(mouse_scale_coord_x(real_y, 1)); + + if (real_y > smax_y) { + if (abs) { + *delta_y = scaled_y; + real_y -= mouse_scale_coord_y((double) scaled_y, 0); + } else { + *delta_y = max; + real_y -= smax_y; + } + } else if (real_y < smin_y) { + if (abs) { + *delta_y = scaled_y; + real_y -= mouse_scale_coord_y((double) scaled_y, 0); + } else { + *delta_y = min; + real_y += ABSD(smin_y); + } + } else { + *delta_y = scaled_y; + real_y -= mouse_scale_coord_y((double) scaled_y, 0); + if (o_y != NULL) + *o_y = 0; + } + + if (abs) + real_y -= rsmin_y; + + if (invert) + real_y = -real_y; + + atomic_store(&mouse_y, real_y); +} + +/* It appears all host platforms give us y in the Microsoft format + (positive to the south), so for all non-Microsoft report formsts, + we have to invenrt that. */ +void +mouse_subtract_coords(int *delta_x, int *delta_y, int *o_x, int *o_y, + int min, int max, int invert, int abs) +{ + mouse_subtract_x(delta_x, o_x, min, max, abs); + mouse_subtract_y(delta_y, o_y, min, max, invert, abs); +} + +int +mouse_wheel_moved(void) +{ + int ret = !!(atomic_load(&mouse_z)); + + return ret; +} + +int +mouse_moved(void) +{ + int moved_x = !!((int) floor(ABSD(mouse_scale_coord_x(atomic_load(&mouse_x), 1)))); + int moved_y = !!((int) floor(ABSD(mouse_scale_coord_y(atomic_load(&mouse_y), 1)))); + + /* Convert them to integer so we treat < 1.0 and > -1.0 as 0. */ + int ret = (moved_x || moved_y); + + return ret; +} + +int +mouse_state_changed(void) +{ + int b; + int b_mask = (1 << mouse_nbut) - 1; + int wheel = (mouse_nbut >= 4); + int ret; + + b = atomic_load(&mouse_buttons); + mouse_delta_b = (b ^ mouse_old_b); + mouse_old_b = b; + + ret = mouse_moved() || ((atomic_load(&mouse_z) != 0) && wheel) || (mouse_delta_b & b_mask); + + return ret; +} + +int +mouse_mbut_changed(void) +{ + return !!(mouse_delta_b & 0x04); +} + +static void +mouse_timer_poll(UNUSED(void *priv)) +{ + /* Poll at the specified sample rate. */ + timer_on_auto(&mouse_timer, 1000000.0 / sample_rate); + +#ifdef USE_GDBSTUB /* avoid a KBC FIFO overflow when CPU emulation is stalled */ + if (gdbstub_step == GDBSTUB_EXEC) { +#endif + if (mouse_timed) + mouse_process(); +#ifdef USE_GDBSTUB /* avoid a KBC FIFO overflow when CPU emulation is stalled */ + } +#endif +} + +static void +atomic_double_add(_Atomic double *var, double val) +{ + double temp = atomic_load(var); + + temp += val; + + atomic_store(var, temp); +} + +void +mouse_scale_fx(double x) +{ + atomic_double_add(&mouse_x, ((double) x) * mouse_sensitivity); +} + +void +mouse_scale_fy(double y) +{ + atomic_double_add(&mouse_y, ((double) y) * mouse_sensitivity); +} + +void +mouse_scale_x(int x) +{ + atomic_double_add(&mouse_x, ((double) x) * mouse_sensitivity); +} + +void +mouse_scale_y(int y) +{ + atomic_double_add(&mouse_y, ((double) y) * mouse_sensitivity); +} + +void +mouse_scalef(double x, double y) +{ + mouse_scale_fx(x); + mouse_scale_fy(y); +} + +void +mouse_scale(int x, int y) +{ + mouse_scale_x(x); + mouse_scale_y(y); +} + +void +mouse_set_z(int z) +{ + atomic_fetch_add(&mouse_z, z); +} + +void +mouse_clear_z(void) +{ + atomic_store(&mouse_z, 0); +} + +void +mouse_subtract_z(int *delta_z, int min, int max, int invert) +{ + int z = atomic_load(&mouse_z); + int real_z = invert ? -z : z; + + if (mouse_z > max) { + *delta_z = max; + real_z -= max; + } else if (mouse_z < min) { + *delta_z = min; + real_z += ABS(min); + } else { + *delta_z = real_z; + real_z = 0; + } + + atomic_store(&mouse_z, invert ? -real_z : real_z); +} + +void +mouse_set_buttons_ex(int b) +{ + atomic_store(&mouse_buttons, b); +} + +int +mouse_get_buttons_ex(void) +{ + return atomic_load(&mouse_buttons); +} + +void +mouse_set_sample_rate(double new_rate) +{ + mouse_timed = (new_rate > 0.0); + + timer_stop(&mouse_timer); + + sample_rate = new_rate; + if (mouse_timed) + timer_on_auto(&mouse_timer, 1000000.0 / sample_rate); +} /* Callback from the hardware driver. */ void @@ -160,98 +517,161 @@ mouse_set_buttons(int buttons) mouse_nbut = buttons; } +void +mouse_get_abs_coords(double *x_abs, double *y_abs) +{ + *x_abs = mouse_x_abs; + *y_abs = mouse_y_abs; +} void mouse_process(void) { - static int poll_delay = 2; - if (mouse_curr == NULL) - return; + return; - if (--poll_delay) return; - - mouse_poll(); - - if ((mouse_dev_poll != NULL) || (mouse_curr->poll != NULL)) { - if (mouse_curr->poll != NULL) - mouse_curr->poll(mouse_x,mouse_y,mouse_z,mouse_buttons, mouse_priv); - else - mouse_dev_poll(mouse_x,mouse_y,mouse_z,mouse_buttons, mouse_priv); - - /* Reset mouse deltas. */ - mouse_x = mouse_y = mouse_z = 0; + if ((mouse_input_mode >= 1) && mouse_poll_ex) + mouse_poll_ex(); + else if ((mouse_input_mode == 0) && ((mouse_dev_poll != NULL) || (mouse_curr->poll != NULL))) { + if (mouse_curr->poll != NULL) + mouse_curr->poll(mouse_priv); + else + mouse_dev_poll(mouse_priv); } - - poll_delay = 2; } - void -mouse_set_poll(int (*func)(int,int,int,int,void *), void *arg) +mouse_set_poll_ex(void (*poll_ex)(void)) { - if (mouse_type != MOUSE_TYPE_INTERNAL) return; + mouse_poll_ex = poll_ex; +} + +void +mouse_set_poll(int (*func)(void *), void *arg) +{ + if (mouse_type != MOUSE_TYPE_INTERNAL) + return; mouse_dev_poll = func; - mouse_priv = arg; + mouse_priv = arg; } - -char * +const char * mouse_get_name(int mouse) { - return((char *)mouse_devices[mouse].device->name); + return (mouse_devices[mouse].device->name); } - -char * +const char * mouse_get_internal_name(int mouse) { return device_get_internal_name(mouse_devices[mouse].device); } - int mouse_get_from_internal_name(char *s) { int c = 0; while (mouse_devices[c].device != NULL) { - if (! strcmp((char *)mouse_devices[c].device->internal_name, s)) - return(c); - c++; + if (!strcmp((char *) mouse_devices[c].device->internal_name, s)) + return c; + c++; } - return(0); + return 0; } - int mouse_has_config(int mouse) { - if (mouse_devices[mouse].device == NULL) return(0); + if (mouse_devices[mouse].device == NULL) + return 0; - return(mouse_devices[mouse].device->config ? 1 : 0); + return (mouse_devices[mouse].device->config ? 1 : 0); } - const device_t * mouse_get_device(int mouse) { - return(mouse_devices[mouse].device); + return (mouse_devices[mouse].device); } - int mouse_get_buttons(void) { - return(mouse_nbut); + return mouse_nbut; } - /* Return number of MOUSE types we know about. */ int mouse_get_ndev(void) { - return((sizeof(mouse_devices)/sizeof(mouse_t)) - 1); + return ((sizeof(mouse_devices) / sizeof(mouse_t)) - 1); +} + +void +mouse_set_raw(int raw) +{ + mouse_raw = raw; +} + +void +mouse_reset(void) +{ + if (mouse_curr != NULL) + return; /* Mouse already initialized. */ + + mouse_log("MOUSE: reset(type=%d, '%s')\n", + mouse_type, mouse_devices[mouse_type].device->name); + + /* Clear local data. */ + mouse_clear_coords(); + mouse_clear_buttons(); + mouse_input_mode = 0; + mouse_timed = 1; + + /* If no mouse configured, we're done. */ + if (mouse_type == 0) + return; + + timer_add(&mouse_timer, mouse_timer_poll, NULL, 0); + + /* Poll at 100 Hz, the default of a PS/2 mouse. */ + sample_rate = 100.0; + timer_on_auto(&mouse_timer, 1000000.0 / sample_rate); + + mouse_curr = mouse_devices[mouse_type].device; + + if ((mouse_type > 1) && (mouse_curr != NULL)) + mouse_priv = device_add(mouse_curr); +} + +void +mouse_close(void) +{ + if (mouse_curr == NULL) + return; + + mouse_curr = NULL; + mouse_priv = NULL; + mouse_nbut = 0; + mouse_dev_poll = NULL; + + timer_stop(&mouse_timer); +} + +/* Initialize the mouse module. */ +void +mouse_init(void) +{ + /* Initialize local data. */ + mouse_clear_coords(); + mouse_clear_buttons(); + + mouse_type = MOUSE_TYPE_NONE; + mouse_curr = NULL; + mouse_priv = NULL; + mouse_nbut = 0; + mouse_dev_poll = NULL; } diff --git a/src/device/mouse_bus.c b/src/device/mouse_bus.c index d627db75f..554704c9d 100644 --- a/src/device/mouse_bus.c +++ b/src/device/mouse_bus.c @@ -1,73 +1,74 @@ /* - * 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. + * 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. + * This file is part of the 86Box distribution. * - * Implementation of Bus Mouse devices. + * Implementation of Bus Mouse devices. * - * These devices were made by both Microsoft and Logitech. At - * first, Microsoft used the same protocol as Logitech, but did - * switch to their new protocol for their InPort interface. So, - * although alike enough to be handled in the same driver, they - * are not the same. + * These devices were made by both Microsoft and Logitech. At + * first, Microsoft used the same protocol as Logitech, but did + * switch to their new protocol for their InPort interface. So, + * although alike enough to be handled in the same driver, they + * are not the same. * - * NOTES: Ported from Bochs with extensive modifications per testing - * of the real hardware, testing of drivers, and the old code. + * NOTES: Ported from Bochs with extensive modifications per testing + * of the real hardware, testing of drivers, and the old code. * - * Logitech Bus Mouse verified with: - * Linux Slackware 3.0 - * Logitech LMouse.com 3.12 - * Logitech LMouse.com 3.30 - * Logitech LMouse.com 3.41 - * Logitech LMouse.com 3.42 - * Logitech LMouse.com 4.00 - * Logitech LMouse.com 5.00 - * Logitech LMouse.com 6.00 - * Logitech LMouse.com 6.02 Beta - * Logitech LMouse.com 6.02 - * Logitech LMouse.com 6.12 - * Logitech LMouse.com 6.20 - * Logitech LMouse.com 6.23 - * Logitech LMouse.com 6.30 - * Logitech LMouse.com 6.31E - * Logitech LMouse.com 6.34 - * Logitech Mouse.exe 6.40 - * Logitech Mouse.exe 6.41 - * Logitech Mouse.exe 6.44 - * Logitech Mouse.exe 6.46 - * Logitech Mouse.exe 6.50 - * Microsoft Mouse.com 2.00 - * Microsoft Mouse.sys 3.00 - * Microsoft Mouse.com 7.04 - * Microsoft Mouse.com 8.21J - * Microsoft Windows 1.00 DR5 - * Microsoft Windows 3.10.026 - * Microsoft Windows 3.10.068 both MOUSE.DRV and LMOUSE.DRV - * Microsoft Windows NT 3.1 - * Microsoft Windows 95 + * Logitech Bus Mouse verified with: + * Linux Slackware 3.0 + * Logitech LMouse.com 3.12 + * Logitech LMouse.com 3.30 + * Logitech LMouse.com 3.41 + * Logitech LMouse.com 3.42 + * Logitech LMouse.com 4.00 + * Logitech LMouse.com 5.00 + * Logitech LMouse.com 6.00 + * Logitech LMouse.com 6.02 Beta + * Logitech LMouse.com 6.02 + * Logitech LMouse.com 6.12 + * Logitech LMouse.com 6.20 + * Logitech LMouse.com 6.23 + * Logitech LMouse.com 6.30 + * Logitech LMouse.com 6.31E + * Logitech LMouse.com 6.34 + * Logitech Mouse.exe 6.40 + * Logitech Mouse.exe 6.41 + * Logitech Mouse.exe 6.44 + * Logitech Mouse.exe 6.46 + * Logitech Mouse.exe 6.50 + * Microsoft Mouse.com 2.00 + * Microsoft Mouse.sys 3.00 + * Microsoft Mouse.com 7.04 + * Microsoft Mouse.com 8.21J + * Microsoft Windows 1.00 DR5 + * Microsoft Windows 3.10.026 + * Microsoft Windows 3.10.068 both MOUSE.DRV and LMOUSE.DRV + * Microsoft Windows NT 3.1 + * Microsoft Windows 95 * - * InPort verified with: - * Linux Slackware 3.0 - * Logitech LMouse.com 6.12 - * Logitech LMouse.com 6.41 - * Microsoft Windows 3.10.068 both MOUSE.DRV and LMOUSE.DRV - * Microsoft Windows NT 3.1 - * Microsoft Windows 98 SE + * InPort verified with: + * Linux Slackware 3.0 + * Logitech LMouse.com 6.12 + * Logitech LMouse.com 6.41 + * Microsoft Windows 3.10.068 both MOUSE.DRV and LMOUSE.DRV + * Microsoft Windows NT 3.1 + * Microsoft Windows 98 SE * * * - * Authors: Miran Grca, - * Fred N. van Kempen, + * Authors: Miran Grca, + * Fred N. van Kempen, * - * Copyright 200?-2019 Bochs. - * Copyright 2017-2019 Miran Grca. - * Copyright 1989-2019 Fred N. van Kempen. + * Copyright 200?-2019 Bochs. + * Copyright 2017-2019 Miran Grca. + * Copyright 1989-2019 Fred N. van Kempen. */ #include #include +#include #include #include #include @@ -80,15 +81,17 @@ #include <86box/timer.h> #include <86box/device.h> #include <86box/mouse.h> +#include <86box/plat.h> +#include <86box/plat_unused.h> #include <86box/random.h> #define IRQ_MASK ((1 << 5) >> dev->irq) /* MS Inport Bus Mouse Adapter */ -#define INP_PORT_CONTROL 0x0000 -#define INP_PORT_DATA 0x0001 -#define INP_PORT_SIGNATURE 0x0002 -#define INP_PORT_CONFIG 0x0003 +#define INP_PORT_CONTROL 0x0000 +#define INP_PORT_DATA 0x0001 +#define INP_PORT_SIGNATURE 0x0002 +#define INP_PORT_CONFIG 0x0003 #define INP_CTRL_READ_BUTTONS 0x00 #define INP_CTRL_READ_X 0x01 @@ -103,123 +106,129 @@ #define INP_PERIOD_MASK 0x07 /* MS/Logictech Standard Bus Mouse Adapter */ -#define BUSM_PORT_DATA 0x0000 -#define BUSM_PORT_SIGNATURE 0x0001 -#define BUSM_PORT_CONTROL 0x0002 -#define BUSM_PORT_CONFIG 0x0003 +#define BUSM_PORT_DATA 0x0000 +#define BUSM_PORT_SIGNATURE 0x0001 +#define BUSM_PORT_CONTROL 0x0002 +#define BUSM_PORT_CONFIG 0x0003 -#define HOLD_COUNTER (1 << 7) -#define READ_X (0 << 6) -#define READ_Y (1 << 6) -#define READ_LOW (0 << 5) -#define READ_HIGH (1 << 5) -#define DISABLE_IRQ (1 << 4) +#define HOLD_COUNTER (1 << 7) +#define READ_X (0 << 6) +#define READ_Y (1 << 6) +#define READ_LOW (0 << 5) +#define READ_HIGH (1 << 5) +#define DISABLE_IRQ (1 << 4) -#define DEVICE_ACTIVE (1 << 7) +#define DEVICE_ACTIVE (1 << 7) -#define READ_X_LOW (READ_X | READ_LOW) -#define READ_X_HIGH (READ_X | READ_HIGH) -#define READ_Y_LOW (READ_Y | READ_LOW) -#define READ_Y_HIGH (READ_Y | READ_HIGH) +#define READ_X_LOW (READ_X | READ_LOW) +#define READ_X_HIGH (READ_X | READ_HIGH) +#define READ_Y_LOW (READ_Y | READ_LOW) +#define READ_Y_HIGH (READ_Y | READ_HIGH) -#define FLAG_INPORT (1 << 0) -#define FLAG_ENABLED (1 << 1) -#define FLAG_HOLD (1 << 2) -#define FLAG_TIMER_INT (1 << 3) -#define FLAG_DATA_INT (1 << 4) +#define FLAG_INPORT (1 << 0) +#define FLAG_ENABLED (1 << 1) +#define FLAG_HOLD (1 << 2) +#define FLAG_TIMER_INT (1 << 3) +#define FLAG_DATA_INT (1 << 4) static const uint8_t periods[4] = { 30, 50, 100, 200 }; - /* Our mouse device. */ typedef struct mouse { - uint8_t current_b, control_val, - config_val, sig_val, - command_val, pad; + uint8_t current_b; + uint8_t control_val; + uint8_t config_val; + uint8_t sig_val; + uint8_t command_val; + uint8_t pad; - int8_t current_x, current_y; + int8_t current_x; + int8_t current_y; - int base, irq, bn, flags, - mouse_delayed_dx, mouse_delayed_dy, - mouse_buttons, mouse_buttons_last, - toggle_counter, timer_enabled; + int base; + int irq; + int bn; + int flags; + int mouse_buttons; + int mouse_buttons_last; + int toggle_counter; + int timer_enabled; - double period; - pc_timer_t timer; /* mouse event timer */ + double period; + pc_timer_t timer; /* mouse event timer */ } mouse_t; - #ifdef ENABLE_MOUSE_BUS_LOG int bm_do_log = ENABLE_MOUSE_BUS_LOG; - static void bm_log(const char *fmt, ...) { va_list ap; if (bm_do_log) { - va_start(ap, fmt); - pclog_ex(fmt, ap); - va_end(ap); + va_start(ap, fmt); + pclog_ex(fmt, ap); + va_end(ap); } } #else -#define bm_log(fmt, ...) +# define bm_log(fmt, ...) #endif - /* Handle a READ operation from one of our registers. */ static uint8_t lt_read(uint16_t port, void *priv) { - mouse_t *dev = (mouse_t *)priv; - uint8_t value = 0xff; + mouse_t *dev = (mouse_t *) priv; + uint8_t value = 0xff; switch (port & 0x03) { - case BUSM_PORT_DATA: - /* Testing and another source confirm that the buttons are - *ALWAYS* present, so I'm going to change this a bit. */ - switch (dev->control_val & 0x60) { - case READ_X_LOW: - value = dev->current_x & 0x0F; - dev->current_x &= ~0x0F; - break; - case READ_X_HIGH: - value = (dev->current_x >> 4) & 0x0F; - dev->current_x &= ~0xF0; - break; - case READ_Y_LOW: - value = dev->current_y & 0x0F; - dev->current_y &= ~0x0F; - break; - case READ_Y_HIGH: - value = (dev->current_y >> 4) & 0x0F; - dev->current_y &= ~0xF0; - break; - default: - bm_log("ERROR: Reading data port in unsupported mode 0x%02x\n", dev->control_val); - } - value |= ((dev->current_b ^ 7) << 5); - break; - case BUSM_PORT_SIGNATURE: - value = dev->sig_val; - break; - case BUSM_PORT_CONTROL: - value = dev->control_val; - dev->control_val |= 0x0F; - /* If the conditions are right, simulate the flakiness of the correct IRQ bit. */ - if (dev->flags & FLAG_TIMER_INT) - dev->control_val = (dev->control_val & ~IRQ_MASK) | (random_generate() & IRQ_MASK); - break; - case BUSM_PORT_CONFIG: - /* Read from config port returns control_val in the upper 4 bits when enabled, - possibly solid interrupt readout in the lower 4 bits, 0xff when not (at power-up). */ - if (dev->flags & FLAG_ENABLED) - return (dev->control_val | 0x0F) & ~IRQ_MASK; - else - return 0xff; - break; + case BUSM_PORT_DATA: + /* Testing and another source confirm that the buttons are + *ALWAYS* present, so I'm going to change this a bit. */ + switch (dev->control_val & 0x60) { + case READ_X_LOW: + value = dev->current_x & 0x0F; + dev->current_x &= ~0x0F; + break; + case READ_X_HIGH: + value = (dev->current_x >> 4) & 0x0F; + dev->current_x &= ~0xF0; + break; + case READ_Y_LOW: + value = dev->current_y & 0x0F; + dev->current_y &= ~0x0F; + break; + case READ_Y_HIGH: + value = (dev->current_y >> 4) & 0x0F; + dev->current_y &= ~0xF0; + break; + default: + bm_log("ERROR: Reading data port in unsupported mode 0x%02x\n", dev->control_val); + } + value |= ((dev->current_b ^ 7) << 5); + break; + case BUSM_PORT_SIGNATURE: + value = dev->sig_val; + break; + case BUSM_PORT_CONTROL: + value = dev->control_val; + dev->control_val |= 0x0F; + /* If the conditions are right, simulate the flakiness of the correct IRQ bit. */ + if (dev->flags & FLAG_TIMER_INT) + dev->control_val = (dev->control_val & ~IRQ_MASK) | (random_generate() & IRQ_MASK); + break; + case BUSM_PORT_CONFIG: + /* Read from config port returns control_val in the upper 4 bits when enabled, + possibly solid interrupt readout in the lower 4 bits, 0xff when not (at power-up). */ + if (dev->flags & FLAG_ENABLED) + return (dev->control_val | 0x0F) & ~IRQ_MASK; + else + return 0xff; + + default: + break; } bm_log("DEBUG: read from address 0x%04x, value = 0x%02x\n", port, value); @@ -227,47 +236,50 @@ lt_read(uint16_t port, void *priv) return value; } - static uint8_t ms_read(uint16_t port, void *priv) { - mouse_t *dev = (mouse_t *)priv; - uint8_t value = 0xff; + mouse_t *dev = (mouse_t *) priv; + uint8_t value = 0xff; switch (port & 0x03) { - case INP_PORT_CONTROL: - value = dev->control_val; - break; - case INP_PORT_DATA: - switch (dev->command_val) { - case INP_CTRL_READ_BUTTONS: - value = dev->current_b; - break; - case INP_CTRL_READ_X: - value = dev->current_x; - dev->current_x = 0; - break; - case INP_CTRL_READ_Y: - value = dev->current_y; - dev->current_y = 0; - break; - case INP_CTRL_COMMAND: - value = dev->control_val; - break; - default: - bm_log("ERROR: Reading data port in unsupported mode 0x%02x\n", dev->control_val); - } - break; - case INP_PORT_SIGNATURE: - if (dev->toggle_counter) - value = 0x12; - else - value = 0xDE; - dev->toggle_counter ^= 1; - break; - case INP_PORT_CONFIG: - bm_log("ERROR: Unsupported read from port 0x%04x\n", port); - break; + case INP_PORT_CONTROL: + value = dev->control_val; + break; + case INP_PORT_DATA: + switch (dev->command_val) { + case INP_CTRL_READ_BUTTONS: + value = dev->current_b; + break; + case INP_CTRL_READ_X: + value = dev->current_x; + dev->current_x = 0; + break; + case INP_CTRL_READ_Y: + value = dev->current_y; + dev->current_y = 0; + break; + case INP_CTRL_COMMAND: + value = dev->control_val; + break; + + default: + bm_log("ERROR: Reading data port in unsupported mode 0x%02x\n", dev->control_val); + } + break; + case INP_PORT_SIGNATURE: + if (dev->toggle_counter) + value = 0x12; + else + value = 0xDE; + dev->toggle_counter ^= 1; + break; + case INP_PORT_CONFIG: + bm_log("ERROR: Unsupported read from port 0x%04x\n", port); + break; + + default: + break; } bm_log("DEBUG: read from address 0x%04x, value = 0x%02x\n", port, value); @@ -275,587 +287,561 @@ ms_read(uint16_t port, void *priv) return value; } - /* Handle a WRITE operation to one of our registers. */ static void lt_write(uint16_t port, uint8_t val, void *priv) { - mouse_t *dev = (mouse_t *)priv; - uint8_t bit; + mouse_t *dev = (mouse_t *) priv; + uint8_t bit; bm_log("DEBUG: write to address 0x%04x, value = 0x%02x\n", port, val); switch (port & 0x03) { - case BUSM_PORT_DATA: - bm_log("ERROR: Unsupported write to port 0x%04x (value = 0x%02x)\n", port, val); - break; - case BUSM_PORT_SIGNATURE: - dev->sig_val = val; - break; - case BUSM_PORT_CONTROL: - dev->control_val = val | 0x0F; + case BUSM_PORT_DATA: + bm_log("ERROR: Unsupported write to port 0x%04x (value = 0x%02x)\n", port, val); + break; + case BUSM_PORT_SIGNATURE: + dev->sig_val = val; + break; + case BUSM_PORT_CONTROL: + dev->control_val = val | 0x0F; - if (!(val & DISABLE_IRQ)) - dev->flags |= FLAG_TIMER_INT; - else - dev->flags &= ~FLAG_TIMER_INT; + if (!(val & DISABLE_IRQ)) + dev->flags |= FLAG_TIMER_INT; + else + dev->flags &= ~FLAG_TIMER_INT; - if (val & HOLD_COUNTER) - dev->flags |= FLAG_HOLD; - else - dev->flags &= ~FLAG_HOLD; + if (val & HOLD_COUNTER) + dev->flags |= FLAG_HOLD; + else + dev->flags &= ~FLAG_HOLD; - if (dev->irq != -1) - picintc(1 << dev->irq); + if (dev->irq != -1) + picintc(1 << dev->irq); - break; - case BUSM_PORT_CONFIG: - /* - * The original Logitech design was based on using a - * 8255 parallel I/O chip. This chip has to be set up - * for proper operation, and this configuration data - * is what is programmed into this register. - * - * A snippet of code found in the FreeBSD kernel source - * explains the value: - * - * D7 = Mode set flag (1 = active) - * This indicates the mode of operation of D7: - * 1 = Mode set, 0 = Bit set/reset - * D6,D5 = Mode selection (port A) - * 00 = Mode 0 = Basic I/O - * 01 = Mode 1 = Strobed I/O - * 10 = Mode 2 = Bi-dir bus - * D4 = Port A direction (1 = input) - * D3 = Port C (upper 4 bits) direction. (1 = input) - * D2 = Mode selection (port B & C) - * 0 = Mode 0 = Basic I/O - * 1 = Mode 1 = Strobed I/O - * D1 = Port B direction (1 = input) - * D0 = Port C (lower 4 bits) direction. (1 = input) - * - * So 91 means Basic I/O on all 3 ports, Port A is an input - * port, B is an output port, C is split with upper 4 bits - * being an output port and lower 4 bits an input port, and - * enable the sucker. Courtesy Intel 8255 databook. Lars - * - * 1001 1011 9B 1111 Default state - * 1001 0001 91 1001 Driver-initialized state - * The only difference is - port C upper and port B go from - * input to output. - */ - if (val & DEVICE_ACTIVE) { - /* Mode set/reset - enable this */ - dev->config_val = val; - if (dev->timer_enabled) - dev->flags |= (FLAG_ENABLED | FLAG_TIMER_INT); - else - dev->flags |= FLAG_ENABLED; - dev->control_val = 0x0F & ~IRQ_MASK; - } else { - /* Single bit set/reset */ - bit = 1 << ((val >> 1) & 0x07); /* Bits 3-1 specify the target bit */ - if (val & 1) - dev->control_val |= bit; /* Set */ - else - dev->control_val &= ~bit; /* Reset */ - } - break; + break; + case BUSM_PORT_CONFIG: + /* + * The original Logitech design was based on using a + * 8255 parallel I/O chip. This chip has to be set up + * for proper operation, and this configuration data + * is what is programmed into this register. + * + * A snippet of code found in the FreeBSD kernel source + * explains the value: + * + * D7 = Mode set flag (1 = active) + * This indicates the mode of operation of D7: + * 1 = Mode set, 0 = Bit set/reset + * D6,D5 = Mode selection (port A) + * 00 = Mode 0 = Basic I/O + * 01 = Mode 1 = Strobed I/O + * 10 = Mode 2 = Bi-dir bus + * D4 = Port A direction (1 = input) + * D3 = Port C (upper 4 bits) direction. (1 = input) + * D2 = Mode selection (port B & C) + * 0 = Mode 0 = Basic I/O + * 1 = Mode 1 = Strobed I/O + * D1 = Port B direction (1 = input) + * D0 = Port C (lower 4 bits) direction. (1 = input) + * + * So 91 means Basic I/O on all 3 ports, Port A is an input + * port, B is an output port, C is split with upper 4 bits + * being an output port and lower 4 bits an input port, and + * enable the sucker. Courtesy Intel 8255 databook. Lars + * + * 1001 1011 9B 1111 Default state + * 1001 0001 91 1001 Driver-initialized state + * The only difference is - port C upper and port B go from + * input to output. + */ + if (val & DEVICE_ACTIVE) { + /* Mode set/reset - enable this */ + dev->config_val = val; + if (dev->timer_enabled) + dev->flags |= (FLAG_ENABLED | FLAG_TIMER_INT); + else + dev->flags |= FLAG_ENABLED; + dev->control_val = 0x0F & ~IRQ_MASK; + } else { + /* Single bit set/reset */ + bit = 1 << ((val >> 1) & 0x07); /* Bits 3-1 specify the target bit */ + if (val & 1) + dev->control_val |= bit; /* Set */ + else + dev->control_val &= ~bit; /* Reset */ + } + break; + + default: + break; } } - /* Handle a WRITE operation to one of our registers. */ static void ms_write(uint16_t port, uint8_t val, void *priv) { - mouse_t *dev = (mouse_t *)priv; + mouse_t *dev = (mouse_t *) priv; bm_log("DEBUG: write to address 0x%04x, value = 0x%02x\n", port, val); switch (port & 0x03) { - case INP_PORT_CONTROL: - /* Bit 7 is reset. */ - if (val & INP_CTRL_RESET) - dev->control_val = 0; + case INP_PORT_CONTROL: + /* Bit 7 is reset. */ + if (val & INP_CTRL_RESET) + dev->control_val = 0; - /* Bits 0-2 are the internal register index. */ - switch(val & 0x07) { - case INP_CTRL_COMMAND: - case INP_CTRL_READ_BUTTONS: - case INP_CTRL_READ_X: - case INP_CTRL_READ_Y: - dev->command_val = val & 0x07; - break; - default: - bm_log("ERROR: Unsupported command written to port 0x%04x (value = 0x%02x)\n", port, val); - } - break; - case INP_PORT_DATA: - if (dev->irq != -1) - picintc(1 << dev->irq); - switch(dev->command_val) { - case INP_CTRL_COMMAND: - if (val & INP_HOLD_COUNTER) - dev->flags |= FLAG_HOLD; - else - dev->flags &= ~FLAG_HOLD; + /* Bits 0-2 are the internal register index. */ + switch (val & 0x07) { + case INP_CTRL_COMMAND: + case INP_CTRL_READ_BUTTONS: + case INP_CTRL_READ_X: + case INP_CTRL_READ_Y: + dev->command_val = val & 0x07; + break; - if (val & INP_ENABLE_TIMER_IRQ) - dev->flags |= FLAG_TIMER_INT; - else - dev->flags &= ~FLAG_TIMER_INT; + default: + bm_log("ERROR: Unsupported command written to port 0x%04x (value = 0x%02x)\n", port, val); + } + break; + case INP_PORT_DATA: + if (dev->irq != -1) + picintc(1 << dev->irq); + switch (dev->command_val) { + case INP_CTRL_COMMAND: + if (val & INP_HOLD_COUNTER) + dev->flags |= FLAG_HOLD; + else + dev->flags &= ~FLAG_HOLD; - if (val & INP_ENABLE_DATA_IRQ) - dev->flags |= FLAG_DATA_INT; - else - dev->flags &= ~FLAG_DATA_INT; + if (val & INP_ENABLE_TIMER_IRQ) + dev->flags |= FLAG_TIMER_INT; + else + dev->flags &= ~FLAG_TIMER_INT; - switch(val & INP_PERIOD_MASK) { - case 0: - dev->period = 0.0; - timer_disable(&dev->timer); - dev->timer_enabled = 0; - break; + if (val & INP_ENABLE_DATA_IRQ) + dev->flags |= FLAG_DATA_INT; + else + dev->flags &= ~FLAG_DATA_INT; - case 1: - case 2: - case 3: - case 4: - dev->period = (1000000.0 / (double)periods[(val & INP_PERIOD_MASK) - 1]); - dev->timer_enabled = (val & INP_ENABLE_TIMER_IRQ) ? 1 : 0; - timer_disable(&dev->timer); - if (dev->timer_enabled) - timer_set_delay_u64(&dev->timer, (uint64_t) (dev->period * (double)TIMER_USEC)); - bm_log("DEBUG: Timer is now %sabled at period %i\n", (val & INP_ENABLE_TIMER_IRQ) ? "en" : "dis", (int32_t) dev->period); - break; + switch (val & INP_PERIOD_MASK) { + case 0: + dev->period = 0.0; + timer_disable(&dev->timer); + dev->timer_enabled = 0; + break; - case 6: - if ((val & INP_ENABLE_TIMER_IRQ) && (dev->irq != -1)) - picint(1 << dev->irq); - dev->control_val &= INP_PERIOD_MASK; - dev->control_val |= (val & ~INP_PERIOD_MASK); - return; - default: - bm_log("ERROR: Unsupported period written to port 0x%04x (value = 0x%02x)\n", port, val); - } + case 1: + case 2: + case 3: + case 4: + dev->period = (1000000.0 / (double) periods[(val & INP_PERIOD_MASK) - 1]); + dev->timer_enabled = (val & INP_ENABLE_TIMER_IRQ) ? 1 : 0; + timer_disable(&dev->timer); + if (dev->timer_enabled) + timer_set_delay_u64(&dev->timer, (uint64_t) (dev->period * (double) TIMER_USEC)); + bm_log("DEBUG: Timer is now %sabled at period %i\n", (val & INP_ENABLE_TIMER_IRQ) ? "en" : "dis", (int32_t) dev->period); + break; - dev->control_val = val; + case 6: + if ((val & INP_ENABLE_TIMER_IRQ) && (dev->irq != -1)) + picint(1 << dev->irq); + dev->control_val &= INP_PERIOD_MASK; + dev->control_val |= (val & ~INP_PERIOD_MASK); + return; - break; - default: - bm_log("ERROR: Unsupported write to port 0x%04x (value = 0x%02x)\n", port, val); - } - break; - case INP_PORT_SIGNATURE: - case INP_PORT_CONFIG: - bm_log("ERROR: Unsupported write to port 0x%04x (value = 0x%02x)\n", port, val); - break; + default: + bm_log("ERROR: Unsupported period written to port 0x%04x (value = 0x%02x)\n", port, val); + } + + dev->control_val = val; + + break; + + default: + bm_log("ERROR: Unsupported write to port 0x%04x (value = 0x%02x)\n", port, val); + } + break; + case INP_PORT_SIGNATURE: + case INP_PORT_CONFIG: + bm_log("ERROR: Unsupported write to port 0x%04x (value = 0x%02x)\n", port, val); + break; + + default: + break; } } - /* The emulator calls us with an update on the host mouse device. */ static int -bm_poll(int x, int y, int z, int b, void *priv) +bm_poll(void *priv) { - mouse_t *dev = (mouse_t *)priv; + mouse_t *dev = (mouse_t *) priv; + int delta_x; + int delta_y; int xor; + int b = mouse_get_buttons_ex(); + + if (!mouse_capture && !video_fullscreen) + return 1; if (!(dev->flags & FLAG_ENABLED)) - return(1); /* Mouse is disabled, do nothing. */ + return 1; /* Mouse is disabled, do nothing. */ - if (!x && !y && !((b ^ dev->mouse_buttons_last) & 0x07)) { - dev->mouse_buttons_last = b; - return(1); /* State has not changed, do nothing. */ + if (!mouse_state_changed()) { + dev->mouse_buttons_last = 0x00; + return 1; /* State has not changed, do nothing. */ } /* Converts button states from MRL to LMR. */ dev->mouse_buttons = (uint8_t) (((b & 1) << 2) | ((b & 2) >> 1)); if (dev->bn == 3) - dev->mouse_buttons |= ((b & 4) >> 1); + dev->mouse_buttons |= ((b & 4) >> 1); if ((dev->flags & FLAG_INPORT) && !dev->timer_enabled) { - /* This is an InPort mouse in data interrupt mode, - so update bits 6-3 here. */ + /* This is an InPort mouse in data interrupt mode, + so update bits 6-3 here. */ - /* If the mouse has moved, set bit 6. */ - if (x || y) - dev->mouse_buttons |= 0x40; + /* If the mouse has moved, set bit 6. */ + if (mouse_moved()) + dev->mouse_buttons |= 0x40; - /* Set bits 3-5 according to button state changes. */ - xor = ((dev->current_b ^ dev->mouse_buttons) & 0x07) << 3; - dev->mouse_buttons |= xor; + /* Set bits 3-5 according to button state changes. */ + xor = ((dev->current_b ^ mouse_get_buttons_ex()) & 0x07) << 3; + dev->mouse_buttons |= xor; } dev->mouse_buttons_last = b; - /* Clamp x and y to between -128 and 127 (int8_t range). */ - if (x > 127) x = 127; - if (x < -128) x = -128; + if (!dev->timer_enabled) { + /* If the counters are not frozen, update them. */ + if (!(dev->flags & FLAG_HOLD)) { + mouse_subtract_coords(&delta_x, &delta_y, NULL, NULL, -128, 127, 0, 0); - if (y > 127) y = 127; - if (y < -128) y = -128; + dev->current_x = (int8_t) delta_x; + dev->current_y = (int8_t) delta_y; - if (dev->timer_enabled) { - /* Update delayed coordinates. */ - dev->mouse_delayed_dx += x; - dev->mouse_delayed_dy += y; - } else { - /* If the counters are not frozen, update them. */ - if (!(dev->flags & FLAG_HOLD)) { - dev->current_x = (int8_t) x; - dev->current_y = (int8_t) y; + dev->current_b = dev->mouse_buttons; + } - dev->current_b = dev->mouse_buttons; - } - - /* Send interrupt. */ - if ((dev->flags & FLAG_DATA_INT) && (dev->irq != -1)) { - picint(1 << dev->irq); - bm_log("DEBUG: Data Interrupt Fired...\n"); - } + /* Send interrupt. */ + if ((dev->flags & FLAG_DATA_INT) && (dev->irq != -1)) { + picint(1 << dev->irq); + bm_log("DEBUG: Data Interrupt Fired...\n"); + } } - return(0); -} + return 0; +} /* The timer calls us on every tick if the mouse is in timer mode (InPort mouse is so configured, MS/Logitech Bus mouse always). */ static void bm_update_data(mouse_t *dev) { - int delta_x, delta_y; + int delta_x; + int delta_y; int xor; /* If the counters are not frozen, update them. */ - if (!(dev->flags & FLAG_HOLD)) { - /* Update the deltas and the delays. */ - if (dev->mouse_delayed_dx > 127) { - delta_x = 127; - dev->mouse_delayed_dx -= 127; - } else if (dev->mouse_delayed_dx < -128) { - delta_x = -128; - dev->mouse_delayed_dx += 128; - } else { - delta_x = dev->mouse_delayed_dx; - dev->mouse_delayed_dx = 0; - } + if ((mouse_capture || video_fullscreen) && !(dev->flags & FLAG_HOLD)) { + /* Update the deltas and the delays. */ + mouse_subtract_coords(&delta_x, &delta_y, NULL, NULL, -128, 127, 0, 0); - if (dev->mouse_delayed_dy > 127) { - delta_y = 127; - dev->mouse_delayed_dy -= 127; - } else if (dev->mouse_delayed_dy < -128) { - delta_y = -128; - dev->mouse_delayed_dy += 128; - } else { - delta_y = dev->mouse_delayed_dy; - dev->mouse_delayed_dy = 0; - } - - dev->current_x = (int8_t) delta_x; - dev->current_y = (int8_t) delta_y; + dev->current_x = (int8_t) delta_x; + dev->current_y = (int8_t) delta_y; } else - delta_x = delta_y = 0; + delta_x = delta_y = 0; if (dev->flags & FLAG_INPORT) { - /* This is an InPort mouse in timer mode, so update current_b always, - and update bits 6-3 (mouse moved and button state changed) here. */ - xor = ((dev->current_b ^ dev->mouse_buttons) & 0x07) << 3; - dev->current_b = (dev->mouse_buttons & 0x87) | xor; - if (delta_x || delta_y) - dev->current_b |= 0x40; + /* This is an InPort mouse in timer mode, so update current_b always, + and update bits 6-3 (mouse moved and button state changed) here. */ + xor = ((dev->current_b ^ dev->mouse_buttons) & 0x07) << 3; + dev->current_b = (dev->mouse_buttons & 0x87) | xor; + if (delta_x || delta_y) + dev->current_b |= 0x40; } else if (!(dev->flags & FLAG_HOLD)) { - /* This is a MS/Logitech Bus Mouse, so only update current_b if the - counters are frozen. */ - dev->current_b = dev->mouse_buttons; + /* This is a MS/Logitech Bus Mouse, so only update current_b if the + counters are frozen. */ + dev->current_b = dev->mouse_buttons; } } - /* Called at the configured period (InPort mouse) or 45 times per second (MS/Logitech Bus mouse). */ static void bm_timer(void *priv) { - mouse_t *dev = (mouse_t *)priv; + mouse_t *dev = (mouse_t *) priv; bm_log("DEBUG: Timer Tick (flags=%08X)...\n", dev->flags); /* The period is configured either via emulator settings (for MS/Logitech Bus mouse) or via software (for InPort mouse). */ - timer_advance_u64(&dev->timer, (uint64_t) (dev->period * (double)TIMER_USEC)); + timer_advance_u64(&dev->timer, (uint64_t) (dev->period * (double) TIMER_USEC)); if ((dev->flags & FLAG_TIMER_INT) && (dev->irq != -1)) { - picint(1 << dev->irq); - bm_log("DEBUG: Timer Interrupt Fired...\n"); + picint(1 << dev->irq); + bm_log("DEBUG: Timer Interrupt Fired...\n"); } bm_update_data(dev); } - /* Release all resources held by the device. */ static void bm_close(void *priv) { - mouse_t *dev = (mouse_t *)priv; + mouse_t *dev = (mouse_t *) priv; if (dev) - free(dev); + free(dev); } - /* Set the mouse's IRQ. */ void mouse_bus_set_irq(void *priv, int irq) { - mouse_t *dev = (mouse_t *)priv; + mouse_t *dev = (mouse_t *) priv; dev->irq = irq; } - /* Initialize the device for use by the user. */ static void * bm_init(const device_t *info) { mouse_t *dev; - int hz; + int hz; - dev = (mouse_t *)malloc(sizeof(mouse_t)); + dev = (mouse_t *) malloc(sizeof(mouse_t)); memset(dev, 0x00, sizeof(mouse_t)); if ((info->local & ~MOUSE_TYPE_ONBOARD) == MOUSE_TYPE_INPORT) - dev->flags = FLAG_INPORT; + dev->flags = FLAG_INPORT; else - dev->flags = 0; + dev->flags = 0; if (info->local & MOUSE_TYPE_ONBOARD) { - dev->base = 0x023c; - dev->irq = -1; - dev->bn = 2; + dev->base = 0x023c; + dev->irq = -1; + dev->bn = 2; } else { - dev->base = device_get_config_hex16("base"); - dev->irq = device_get_config_int("irq"); - dev->bn = device_get_config_int("buttons"); + dev->base = device_get_config_hex16("base"); + dev->irq = device_get_config_int("irq"); + dev->bn = device_get_config_int("buttons"); } mouse_set_buttons(dev->bn); - dev->mouse_delayed_dx = 0; - dev->mouse_delayed_dy = 0; - dev->mouse_buttons = 0; - dev->mouse_buttons_last = 0; - dev->sig_val = 0; /* the signature port value */ - dev->current_x = - dev->current_y = 0; - dev->current_b = 0; - dev->command_val = 0; /* command byte */ - dev->toggle_counter = 0; /* signature byte / IRQ bit toggle */ - dev->period = 0.0; + dev->mouse_buttons = 0; + dev->mouse_buttons_last = 0; + dev->sig_val = 0; /* the signature port value */ + dev->current_x = dev->current_y = 0; + dev->current_b = 0; + dev->command_val = 0; /* command byte */ + dev->toggle_counter = 0; /* signature byte / IRQ bit toggle */ + dev->period = 0.0; timer_add(&dev->timer, bm_timer, dev, 0); if (dev->flags & FLAG_INPORT) { - dev->control_val = 0; /* the control port value */ - dev->flags |= FLAG_ENABLED; + dev->control_val = 0; /* the control port value */ + dev->flags |= FLAG_ENABLED; - io_sethandler(dev->base, 4, - ms_read, NULL, NULL, ms_write, NULL, NULL, dev); + io_sethandler(dev->base, 4, + ms_read, NULL, NULL, ms_write, NULL, NULL, dev); - dev->timer_enabled = 0; + dev->timer_enabled = 0; } else { - dev->control_val = 0x0f; /* the control port value */ - dev->config_val = 0x9b; /* the config port value - 0x9b is the - default state of the 8255: all ports - are set to input */ + dev->control_val = 0x0f; /* the control port value */ + dev->config_val = 0x9b; /* the config port value - 0x9b is the + default state of the 8255: all ports + are set to input */ - hz = device_get_config_int("hz"); - if (hz > 0) - dev->period = (1000000.0 / (double)hz); + hz = device_get_config_int("hz"); + if (hz > 0) + dev->period = (1000000.0 / (double) hz); - io_sethandler(dev->base, 4, - lt_read, NULL, NULL, lt_write, NULL, NULL, dev); + io_sethandler(dev->base, 4, + lt_read, NULL, NULL, lt_write, NULL, NULL, dev); - if (hz > 0) { - timer_set_delay_u64(&dev->timer, (uint64_t) (dev->period * (double)TIMER_USEC)); - dev->timer_enabled = 1; - } else { - dev->flags |= FLAG_DATA_INT; - dev->timer_enabled = 0; - } + if (hz > 0) { + timer_set_delay_u64(&dev->timer, (uint64_t) (dev->period * (double) TIMER_USEC)); + dev->timer_enabled = 1; + } else { + dev->flags |= FLAG_DATA_INT; + dev->timer_enabled = 0; + } } if (dev->flags & FLAG_INPORT) - bm_log("MS Inport BusMouse initialized\n"); + bm_log("MS Inport BusMouse initialized\n"); else - bm_log("Standard MS/Logitech BusMouse initialized\n"); + bm_log("Standard MS/Logitech BusMouse initialized\n"); + + mouse_set_sample_rate(0.0); return dev; } - static const device_config_t lt_config[] = { + // clang-format off { - "base", "Address", CONFIG_HEX16, "", 0x23c, "", { 0 }, - { - { - "0x230", 0x230 - }, - { - "0x234", 0x234 - }, - { - "0x238", 0x238 - }, - { - "0x23C", 0x23c - }, - { - "" - } - } + .name = "base", + .description = "Address", + .type = CONFIG_HEX16, + .default_string = "", + .default_int = 0x23c, + .file_filter = "", + .spinner = { 0 }, + .selection = { + { .description = "0x230", .value = 0x230 }, + { .description = "0x234", .value = 0x234 }, + { .description = "0x238", .value = 0x238 }, + { .description = "0x23C", .value = 0x23c }, + { .description = "" } + } }, { - "irq", "IRQ", CONFIG_SELECTION, "", 5, "", { 0 }, { - { - "IRQ 2", 2 - }, - { - "IRQ 3", 3 - }, - { - "IRQ 4", 4 - }, - { - "IRQ 5", 5 - }, - { - "" - } - } + .name = "irq", + .description = "IRQ", + .type = CONFIG_SELECTION, + .default_string = "", + .default_int = 5, + .file_filter = "", + .spinner = { 0 }, + .selection = { + { .description = "IRQ 2", .value = 2 }, + { .description = "IRQ 3", .value = 3 }, + { .description = "IRQ 4", .value = 4 }, + { .description = "IRQ 5", .value = 5 }, + { .description = "" } + } }, { - "hz", "Hz", CONFIG_SELECTION, "", 45, "", { 0 }, { - { - "Non-timed (original)", 0 - }, - { - "30 Hz (JMP2 = 1)", 30 - }, - { - "45 Hz (JMP2 not populated)", 45 - }, - { - "60 Hz (JMP 2 = 2)", 60 - }, - { - "" - } - } + .name = "hz", + .description = "Hz", + .type = CONFIG_SELECTION, + .default_string = "", + .default_int = 45, + .file_filter = "", + .spinner = { 0 }, + .selection = { + { .description = "Non-timed (original)", .value = 0 }, + { .description = "30 Hz (JMP2 = 1)", .value = 30 }, + { .description = "45 Hz (JMP2 not populated)", .value = 45 }, + { .description = "60 Hz (JMP 2 = 2)", .value = 60 }, + { .description = "" } + } }, { - "buttons", "Buttons", CONFIG_SELECTION, "", 2, "", { 0 }, { - { - "Two", 2 - }, - { - "Three", 3 - }, - { - "" - } - } + .name = "buttons", + .description = "Buttons", + .type = CONFIG_SELECTION, + .default_string = "", + .default_int = 2, + .file_filter = "", + .spinner = { 0 }, + .selection = { + { .description = "Two", .value = 2 }, + { .description = "Three", .value = 3 }, + { .description = "" } + } }, - { - "", "", -1 - } + { .name = "", .description = "", .type = CONFIG_END } + // clang-format on }; - static const device_config_t ms_config[] = { + // clang-format off { - "base", "Address", CONFIG_HEX16, "", 0x23c, "", { 0 }, - { - { - "0x230", 0x230 - }, - { - "0x234", 0x234 - }, - { - "0x238", 0x238 - }, - { - "0x23C", 0x23c - }, - { - "" - } - } + .name = "base", + .description = "Address", + .type = CONFIG_HEX16, + .default_string = "", + .default_int = 0x23c, + .file_filter = "", + .spinner = { 0 }, + .selection = { + { .description = "0x230", .value = 0x230 }, + { .description = "0x234", .value = 0x234 }, + { .description = "0x238", .value = 0x238 }, + { .description = "0x23C", .value = 0x23c }, + { .description = "" } + } }, { - "irq", "IRQ", CONFIG_SELECTION, "", 5, "", { 0 }, { - { - "IRQ 2", 2 - }, - { - "IRQ 3", 3 - }, - { - "IRQ 4", 4 - }, - { - "IRQ 5", 5 - }, - { - "" - } - } + .name = "irq", + .description = "IRQ", + .type = CONFIG_SELECTION, + .default_string = "", + .default_int = 5, + .file_filter = "", + .spinner = { 0 }, + .selection = { + { .description = "IRQ 2", .value = 2 }, + { .description = "IRQ 3", .value = 3 }, + { .description = "IRQ 4", .value = 4 }, + { .description = "IRQ 5", .value = 5 }, + { .description = "" } + } }, { - "buttons", "Buttons", CONFIG_SELECTION, "", 2, "", { 0 }, { - { - "Two", 2 - }, - { - "Three", 3 - }, - { - "" - } - } + .name = "buttons", + .description = "Buttons", + .type = CONFIG_SELECTION, + .default_string = "", + .default_int = 2, + .file_filter = "", + .spinner = { 0 }, + .selection = { + { .description = "Two", .value = 2 }, + { .description = "Three", .value = 3 }, + { .description = "" } + } }, - { - "", "", -1 - } + { .name = "", .description = "", .type = CONFIG_END } + // clang-format on }; - const device_t mouse_logibus_device = { - "Logitech/Microsoft Bus Mouse", - "logibus", - DEVICE_ISA, - MOUSE_TYPE_LOGIBUS, - bm_init, bm_close, NULL, - { .poll = bm_poll }, NULL, NULL, - lt_config + .name = "Logitech/Microsoft Bus Mouse", + .internal_name = "logibus", + .flags = DEVICE_ISA, + .local = MOUSE_TYPE_LOGIBUS, + .init = bm_init, + .close = bm_close, + .reset = NULL, + { .poll = bm_poll }, + .speed_changed = NULL, + .force_redraw = NULL, + .config = lt_config }; const device_t mouse_logibus_onboard_device = { - "Logitech Bus Mouse (On-Board)", - "logibus_onboard", - DEVICE_ISA, - MOUSE_TYPE_LOGIBUS | MOUSE_TYPE_ONBOARD, - bm_init, bm_close, NULL, - { .poll = bm_poll }, NULL, NULL + .name = "Logitech Bus Mouse (On-Board)", + .internal_name = "logibus_onboard", + .flags = DEVICE_ISA, + .local = MOUSE_TYPE_LOGIBUS | MOUSE_TYPE_ONBOARD, + .init = bm_init, + .close = bm_close, + .reset = NULL, + { .poll = bm_poll }, + .speed_changed = NULL, + .force_redraw = NULL, + .config = NULL }; const device_t mouse_msinport_device = { - "Microsoft Bus Mouse (InPort)", - "msbus", - DEVICE_ISA, - MOUSE_TYPE_INPORT, - bm_init, bm_close, NULL, - { .poll = bm_poll }, NULL, NULL, - ms_config + .name = "Microsoft Bus Mouse (InPort)", + .internal_name = "msbus", + .flags = DEVICE_ISA, + .local = MOUSE_TYPE_INPORT, + .init = bm_init, + .close = bm_close, + .reset = NULL, + { .poll = bm_poll }, + .speed_changed = NULL, + .force_redraw = NULL, + .config = ms_config }; diff --git a/src/device/mouse_ps2.c b/src/device/mouse_ps2.c index b1b1ba3ca..35f0cd9e8 100644 --- a/src/device/mouse_ps2.c +++ b/src/device/mouse_ps2.c @@ -1,18 +1,19 @@ /* - * 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. + * 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. + * This file is part of the 86Box distribution. * - * Implementation of PS/2 series Mouse devices. + * Implementation of PS/2 series Mouse devices. * + * Authors: Miran Grca, * - * - * Authors: Fred N. van Kempen, + * Copyright 2023 Miran Grca. */ #include +#include #include #include #include @@ -23,7 +24,8 @@ #include <86box/device.h> #include <86box/keyboard.h> #include <86box/mouse.h> - +#include <86box/plat.h> +#include <86box/plat_unused.h> enum { MODE_STREAM, @@ -31,259 +33,287 @@ enum { MODE_ECHO }; +#define FLAG_EXPLORER 0x200 /* Has 5 buttons */ +#define FLAG_5BTN 0x100 /* using Intellimouse Optical mode */ +#define FLAG_INTELLI 0x80 /* device is IntelliMouse */ +#define FLAG_INTMODE 0x40 /* using Intellimouse mode */ +#define FLAG_SCALED 0x20 /* enable delta scaling */ +#define FLAG_ENABLED 0x10 /* dev is enabled for use */ +#define FLAG_CTRLDAT 0x08 /* ctrl or data mode */ -typedef struct { - const char *name; /* name of this device */ - int8_t type; /* type of this device */ - - int mode; - - uint8_t flags; - uint8_t resolution; - uint8_t sample_rate; - - uint8_t command; - - int x, y, z, b; - - uint8_t last_data[6]; -} mouse_t; -#define FLAG_INTELLI 0x80 /* device is IntelliMouse */ -#define FLAG_INTMODE 0x40 /* using Intellimouse mode */ -#define FLAG_SCALED 0x20 /* enable delta scaling */ -#define FLAG_ENABLED 0x10 /* dev is enabled for use */ -#define FLAG_CTRLDAT 0x08 /* ctrl or data mode */ - +#define FIFO_SIZE 16 int mouse_scan = 0; - #ifdef ENABLE_MOUSE_PS2_LOG int mouse_ps2_do_log = ENABLE_MOUSE_PS2_LOG; - static void mouse_ps2_log(const char *fmt, ...) { va_list ap; if (mouse_ps2_do_log) { - va_start(ap, fmt); - pclog_ex(fmt, ap); - va_end(ap); + va_start(ap, fmt); + pclog_ex(fmt, ap); + va_end(ap); } } #else -#define mouse_ps2_log(fmt, ...) +# define mouse_ps2_log(fmt, ...) #endif - void mouse_clear_data(void *priv) { - mouse_t *dev = (mouse_t *)priv; + atkbc_dev_t *dev = (atkbc_dev_t *) priv; dev->flags &= ~FLAG_CTRLDAT; } +static void +ps2_report_coordinates(atkbc_dev_t *dev, int main) +{ + uint8_t buff[3] = { 0x08, 0x00, 0x00 }; + int delta_x; + int delta_y; + int overflow_x; + int overflow_y; + int b = mouse_get_buttons_ex(); + int delta_z; + + mouse_subtract_coords(&delta_x, &delta_y, &overflow_x, &overflow_y, + -256, 255, 1, 0); + mouse_subtract_z(&delta_z, -8, 7, 1); + + buff[0] |= (overflow_y << 7) | (overflow_x << 6) | + ((delta_y & 0x0100) >> 3) | ((delta_x & 0x0100) >> 4) | + (b & ((dev->flags & FLAG_INTELLI) ? 0x07 : 0x03)); + buff[1] = (delta_x & 0x00ff); + buff[2] = (delta_y & 0x00ff); + + kbc_at_dev_queue_add(dev, buff[0], main); + kbc_at_dev_queue_add(dev, buff[1], main); + kbc_at_dev_queue_add(dev, buff[2], main); + if (dev->flags & FLAG_INTMODE) { + delta_z &= 0x0f; + + if (dev->flags & FLAG_5BTN) { + if (b & 8) + delta_z |= 0x10; + if (b & 16) + delta_z |= 0x20; + } else { + /* The wheel coordinate is sign-extended. */ + if (delta_z & 0x08) + delta_z |= 0xf0; + } + kbc_at_dev_queue_add(dev, delta_z, main); + } +} static void -ps2_write(uint8_t val, void *priv) +ps2_set_defaults(atkbc_dev_t *dev) { - mouse_t *dev = (mouse_t *)priv; - uint8_t temp; + dev->mode = MODE_STREAM; + dev->rate = 100; + mouse_set_sample_rate(100.0); + dev->resolution = 2; + dev->flags &= 0x188; + mouse_scan = 0; +} + +static void +ps2_bat(void *priv) +{ + atkbc_dev_t *dev = (atkbc_dev_t *) priv; + + ps2_set_defaults(dev); + + kbc_at_dev_queue_add(dev, 0xaa, 0); + kbc_at_dev_queue_add(dev, 0x00, 0); +} + +static void +ps2_write(void *priv) +{ + atkbc_dev_t *dev = (atkbc_dev_t *) priv; + int b; + uint8_t temp; + uint8_t val; + static uint8_t last_data[6] = { 0x00 }; + + if (dev->port == NULL) + return; + + val = dev->port->dat; + + dev->state = DEV_STATE_MAIN_OUT; if (dev->flags & FLAG_CTRLDAT) { - dev->flags &= ~FLAG_CTRLDAT; + dev->flags &= ~FLAG_CTRLDAT; - if (val == 0xff) - goto mouse_reset; + if (val == 0xff) + kbc_at_dev_reset(dev, 1); + else switch (dev->command) { + case 0xe8: /* set mouse resolution */ + dev->resolution = val; + kbc_at_dev_queue_add(dev, 0xfa, 0); + mouse_ps2_log("%s: Set mouse resolution [%02X]\n", dev->name, val); + break; - switch (dev->command) { - case 0xe8: /* set mouse resolution */ - dev->resolution = val; - keyboard_at_adddata_mouse(0xfa); - break; + case 0xf3: /* set sample rate */ + dev->rate = val; + mouse_set_sample_rate((double) val); + kbc_at_dev_queue_add(dev, 0xfa, 0); /* Command response */ + mouse_ps2_log("%s: Set sample rate [%02X]\n", dev->name, val); + break; - case 0xf3: /* set sample rate */ - dev->sample_rate = val; - keyboard_at_adddata_mouse(0xfa); /* Command response */ - break; - - default: - keyboard_at_adddata_mouse(0xfc); - } + default: + kbc_at_dev_queue_add(dev, 0xfc, 0); + } } else { - dev->command = val; + dev->command = val; - switch (dev->command) { - case 0xe6: /* set scaling to 1:1 */ - dev->flags &= ~FLAG_SCALED; - keyboard_at_adddata_mouse(0xfa); - break; + switch (dev->command) { + case 0xe6: /* set scaling to 1:1 */ + mouse_ps2_log("%s: Set scaling to 1:1\n", dev->name); + dev->flags &= ~FLAG_SCALED; + kbc_at_dev_queue_add(dev, 0xfa, 0); + break; - case 0xe7: /* set scaling to 2:1 */ - dev->flags |= FLAG_SCALED; - keyboard_at_adddata_mouse(0xfa); - break; + case 0xe7: /* set scaling to 2:1 */ + mouse_ps2_log("%s: Set scaling to 2:1\n", dev->name); + dev->flags |= FLAG_SCALED; + kbc_at_dev_queue_add(dev, 0xfa, 0); + break; - case 0xe8: /* set mouse resolution */ - dev->flags |= FLAG_CTRLDAT; - keyboard_at_adddata_mouse(0xfa); - break; + case 0xe8: /* set mouse resolution */ + mouse_ps2_log("%s: Set mouse resolution\n", dev->name); + dev->flags |= FLAG_CTRLDAT; + kbc_at_dev_queue_add(dev, 0xfa, 0); + dev->state = DEV_STATE_MAIN_WANT_IN; + break; - case 0xe9: /* status request */ - keyboard_at_adddata_mouse(0xfa); - temp = (dev->flags & 0x30); - if (mouse_buttons & 0x01) - temp |= 0x01; - if (mouse_buttons & 0x02) - temp |= 0x02; - if (mouse_buttons & 0x04) - temp |= 0x03; - keyboard_at_adddata_mouse(temp); - keyboard_at_adddata_mouse(dev->resolution); - keyboard_at_adddata_mouse(dev->sample_rate); - break; + case 0xe9: /* status request */ + mouse_ps2_log("%s: Status request\n", dev->name); + b = mouse_get_buttons_ex(); + kbc_at_dev_queue_add(dev, 0xfa, 0); + temp = (dev->flags & 0x20); + if (mouse_scan) + temp |= FLAG_ENABLED; + if (b & 1) + temp |= 4; + if (b & 2) + temp |= 1; + if ((b & 4) && (dev->flags & FLAG_INTELLI)) + temp |= 2; + kbc_at_dev_queue_add(dev, temp, 0); + kbc_at_dev_queue_add(dev, dev->resolution, 0); + kbc_at_dev_queue_add(dev, dev->rate, 0); + break; - case 0xeb: /* Get mouse data */ - keyboard_at_adddata_mouse(0xfa); + case 0xea: /* set stream */ + mouse_ps2_log("%s: Set stream\n", dev->name); + dev->flags &= ~FLAG_CTRLDAT; + dev->mode = MODE_STREAM; + mouse_scan = 1; + kbc_at_dev_queue_add(dev, 0xfa, 0); /* ACK for command byte */ + break; - temp = 0; - if (dev->x < 0) - temp |= 0x10; - if (dev->y < 0) - temp |= 0x20; - if (mouse_buttons & 1) - temp |= 1; - if (mouse_buttons & 2) - temp |= 2; - if ((mouse_buttons & 4) && (dev->flags & FLAG_INTELLI)) - temp |= 4; - keyboard_at_adddata_mouse(temp); - keyboard_at_adddata_mouse(dev->x & 0xff); - keyboard_at_adddata_mouse(dev->y & 0xff); - if (dev->flags & FLAG_INTMODE) - keyboard_at_adddata_mouse(dev->z); - break; + case 0xeb: /* Get mouse data */ + mouse_ps2_log("%s: Get mouse data\n", dev->name); + kbc_at_dev_queue_add(dev, 0xfa, 0); - case 0xf2: /* read ID */ - keyboard_at_adddata_mouse(0xfa); - if (dev->flags & FLAG_INTMODE) - keyboard_at_adddata_mouse(0x03); - else - keyboard_at_adddata_mouse(0x00); - break; + ps2_report_coordinates(dev, 0); + break; - case 0xf3: /* set command mode */ - dev->flags |= FLAG_CTRLDAT; - keyboard_at_adddata_mouse(0xfa); /* ACK for command byte */ - break; + case 0xf0: /* set remote */ + mouse_ps2_log("%s: Set remote\n", dev->name); + dev->flags &= ~FLAG_CTRLDAT; + dev->mode = MODE_REMOTE; + mouse_scan = 1; + kbc_at_dev_queue_add(dev, 0xfa, 0); /* ACK for command byte */ + break; - case 0xf4: /* enable */ - dev->flags |= FLAG_ENABLED; - mouse_scan = 1; - keyboard_at_adddata_mouse(0xfa); - break; + case 0xf2: /* read ID */ + mouse_ps2_log("%s: Read ID\n", dev->name); + kbc_at_dev_queue_add(dev, 0xfa, 0); + if (dev->flags & FLAG_INTMODE) + kbc_at_dev_queue_add(dev, (dev->flags & FLAG_5BTN) ? 0x04 : 0x03, 0); + else + kbc_at_dev_queue_add(dev, 0x00, 0); + break; - case 0xf5: /* disable */ - dev->flags &= ~FLAG_ENABLED; - mouse_scan = 0; - keyboard_at_adddata_mouse(0xfa); - break; + case 0xf3: /* set sample rate */ + mouse_ps2_log("%s: Set sample rate\n", dev->name); + dev->flags |= FLAG_CTRLDAT; + kbc_at_dev_queue_add(dev, 0xfa, 0); /* ACK for command byte */ + dev->state = DEV_STATE_MAIN_WANT_IN; + break; - case 0xf6: /* set defaults */ - case 0xff: /* reset */ -mouse_reset: - dev->mode = MODE_STREAM; - dev->flags &= 0x88; - mouse_scan = 1; - keyboard_at_mouse_reset(); - keyboard_at_adddata_mouse(0xfa); - if (dev->command == 0xff) { - keyboard_at_adddata_mouse(0xaa); - keyboard_at_adddata_mouse(0x00); - } - break; + case 0xf4: /* enable */ + mouse_ps2_log("%s: Enable\n", dev->name); + mouse_scan = 1; + kbc_at_dev_queue_add(dev, 0xfa, 0); + break; - default: - keyboard_at_adddata_mouse(0xfe); - } + case 0xf5: /* disable */ + mouse_ps2_log("%s: Disable\n", dev->name); + mouse_scan = 0; + kbc_at_dev_queue_add(dev, 0xfa, 0); + break; + + case 0xf6: /* set defaults */ + mouse_ps2_log("%s: Set defaults\n", dev->name); + ps2_set_defaults(dev); + kbc_at_dev_queue_add(dev, 0xfa, 0); + break; + + case 0xff: /* reset */ + mouse_ps2_log("%s: Reset\n", dev->name); + kbc_at_dev_reset(dev, 1); + break; + + default: + kbc_at_dev_queue_add(dev, 0xfe, 0); + } } if (dev->flags & FLAG_INTELLI) { - for (temp = 0; temp < 5; temp++) - dev->last_data[temp] = dev->last_data[temp + 1]; + for (temp = 0; temp < 5; temp++) + last_data[temp] = last_data[temp + 1]; - dev->last_data[5] = val; + last_data[5] = val; - if (dev->last_data[0] == 0xf3 && dev->last_data[1] == 0xc8 && - dev->last_data[2] == 0xf3 && dev->last_data[3] == 0x64 && - dev->last_data[4] == 0xf3 && dev->last_data[5] == 0x50) - dev->flags |= FLAG_INTMODE; + if ((last_data[0] == 0xf3) && (last_data[1] == 0xc8) && + (last_data[2] == 0xf3) && (last_data[3] == 0x64) && + (last_data[4] == 0xf3) && (last_data[5] == 0x50)) + dev->flags |= FLAG_INTMODE; + + if ((dev->flags & FLAG_EXPLORER) && (dev->flags & FLAG_INTMODE) && + (last_data[0] == 0xf3) && (last_data[1] == 0xc8) && + (last_data[2] == 0xf3) && (last_data[3] == 0xc8) && + (last_data[4] == 0xf3) && (last_data[5] == 0x50)) + dev->flags |= FLAG_5BTN; } } - static int -ps2_poll(int x, int y, int z, int b, void *priv) +ps2_poll(void *priv) { - mouse_t *dev = (mouse_t *)priv; - uint8_t buff[3] = { 0x08, 0x00, 0x00 }; + atkbc_dev_t *dev = (atkbc_dev_t *) priv; + int packet_size = (dev->flags & FLAG_INTMODE) ? 4 : 3; - if (!x && !y && !z && (b == dev->b)) - return(0xff); + int cond = (!mouse_capture && !video_fullscreen) || (!mouse_scan || !mouse_state_changed()) || + ((dev->mode == MODE_STREAM) && (kbc_at_dev_queue_pos(dev, 1) >= (FIFO_SIZE - packet_size))); -#if 0 - if (!(dev->flags & FLAG_ENABLED)) - return(0xff); -#endif + if (!cond && (dev->mode == MODE_STREAM)) + ps2_report_coordinates(dev, 1); - if (!mouse_scan) - return(0xff); - - dev->x += x; - dev->y -= y; - dev->z -= z; - if ((dev->mode == MODE_STREAM) && (dev->flags & FLAG_ENABLED) && - (keyboard_at_mouse_pos() < 13)) { - dev->b = b; - - if (dev->x > 255) dev->x = 255; - if (dev->x < -256) dev->x = -256; - if (dev->y > 255) dev->y = 255; - if (dev->y < -256) dev->y = -256; - if (dev->z < -8) dev->z = -8; - if (dev->z > 7) dev->z = 7; - - if (dev->x < 0) - buff[0] |= 0x10; - if (dev->y < 0) - buff[0] |= 0x20; - if (mouse_buttons & 0x01) - buff[0] |= 0x01; - if (mouse_buttons & 0x02) - buff[0] |= 0x02; - if (dev->flags & FLAG_INTELLI) { - if (mouse_buttons & 0x04) - buff[0] |= 0x04; - } - buff[1] = (dev->x & 0xff); - buff[2] = (dev->y & 0xff); - - keyboard_at_adddata_mouse(buff[0]); - keyboard_at_adddata_mouse(buff[1]); - keyboard_at_adddata_mouse(buff[2]); - if (dev->flags & FLAG_INTMODE) - keyboard_at_adddata_mouse(dev->z); - - dev->x = dev->y = dev->z = 0; - } - - return(0); + return cond; } - /* * Initialize the device for use by the user. * @@ -292,73 +322,80 @@ ps2_poll(int x, int y, int z, int b, void *priv) void * mouse_ps2_init(const device_t *info) { - mouse_t *dev; - int i; + atkbc_dev_t *dev = kbc_at_dev_init(DEV_AUX); + int i; - dev = (mouse_t *)malloc(sizeof(mouse_t)); - memset(dev, 0x00, sizeof(mouse_t)); dev->name = info->name; dev->type = info->local; dev->mode = MODE_STREAM; - i = device_get_config_int("buttons"); + i = device_get_config_int("buttons"); if (i > 2) dev->flags |= FLAG_INTELLI; + if (i > 4) + dev->flags |= FLAG_EXPLORER; - /* Hook into the general AT Keyboard driver. */ - keyboard_at_set_mouse(ps2_write, dev); - - mouse_ps2_log("%s: buttons=%d\n", dev->name, (dev->flags & FLAG_INTELLI) ? 3 : 2); + mouse_ps2_log("%s: buttons=%d\n", dev->name, i); /* Tell them how many buttons we have. */ - mouse_set_buttons((dev->flags & FLAG_INTELLI) ? 3 : 2); + mouse_set_buttons(i); + + dev->process_cmd = ps2_write; + dev->execute_bat = ps2_bat; + + dev->scan = &mouse_scan; + + dev->fifo_mask = FIFO_SIZE - 1; + + if (dev->port != NULL) + kbc_at_dev_reset(dev, 0); /* Return our private data to the I/O layer. */ - return(dev); + return dev; } - static void ps2_close(void *priv) { - mouse_t *dev = (mouse_t *)priv; - - /* Unhook from the general AT Keyboard driver. */ - keyboard_at_set_mouse(NULL, NULL); + atkbc_dev_t *dev = (atkbc_dev_t *) priv; free(dev); } - static const device_config_t ps2_config[] = { + // clang-format off { - "buttons", "Buttons", CONFIG_SELECTION, "", 2, "", { 0 }, { - { - "Two", 2 - }, - { - "Three", 3 - }, - { - "Wheel", 4 - }, - { - "" - } - } + .name = "buttons", + .description = "Buttons", + .type = CONFIG_SELECTION, + .default_string = "", + .default_int = 2, + .file_filter = "", + .spinner = { 0 }, + .selection = { + { .description = "Two", .value = 2 }, + { .description = "Three", .value = 3 }, + { .description = "Wheel", .value = 4 }, + { .description = "Five + Wheel", .value = 5 }, + { .description = "" } + } }, { - "", "", -1 + .name = "", .description = "", .type = CONFIG_END } + // clang-format on }; - const device_t mouse_ps2_device = { - "Standard PS/2 Mouse", - "ps2", - DEVICE_PS2, - MOUSE_TYPE_PS2, - mouse_ps2_init, ps2_close, NULL, - { .poll = ps2_poll }, NULL, NULL, - ps2_config + .name = "Standard PS/2 Mouse", + .internal_name = "ps2", + .flags = DEVICE_PS2, + .local = MOUSE_TYPE_PS2, + .init = mouse_ps2_init, + .close = ps2_close, + .reset = NULL, + { .poll = ps2_poll }, + .speed_changed = NULL, + .force_redraw = NULL, + .config = ps2_config }; diff --git a/src/device/mouse_serial.c b/src/device/mouse_serial.c index 3cb49439a..9e4556a88 100644 --- a/src/device/mouse_serial.c +++ b/src/device/mouse_serial.c @@ -1,19 +1,20 @@ /* - * 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. + * 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. + * This file is part of the 86Box distribution. * - * Implementation of Serial Mouse devices. + * Implementation of Serial Mouse devices. * - * TODO: Add the Genius Serial Mouse. + * TODO: Add the Genius Serial Mouse. * + * Authors: Miran Grca, * - * - * Author: Fred N. van Kempen, + * Copyright 2023 Miran Grca. */ +#include #include #include #include @@ -26,904 +27,1069 @@ #include <86box/timer.h> #include <86box/serial.h> #include <86box/mouse.h> +#include <86box/plat.h> - -#define SERMOUSE_PORT 0 /* attach to Serial0 */ +#define SERMOUSE_PORT 0 /* attach to Serial0 */ enum { - PHASE_IDLE, - PHASE_ID, - PHASE_DATA, - PHASE_STATUS, - PHASE_DIAGNOSTIC, - PHASE_FORMAT_AND_REVISION, - PHASE_COPYRIGHT_STRING, - PHASE_BUTTONS + STATE_RESET, + STATE_BAUD_RATE, + STATE_DORMANT, + STATE_IDLE, + STATE_COMMAND, + STATE_DATA, + STATE_TRANSMIT, + STATE_TRANSMIT_REPORT, + STATE_SKIP_REPORT }; enum { - REPORT_PHASE_PREPARE, - REPORT_PHASE_TRANSMIT + FORMAT_BP1_ABS = 0x01, + FORMAT_BP1_REL, + FORMAT_MM_SERIES = 0x13, + FORMAT_PB_3BYTE, + FORMAT_PB_5BYTE, + FORMAT_MSYSTEMS = 0x15, /* Alias for FORMAT_PB_5BYTE. */ + FORMAT_MS, + FORMAT_HEX, + FORMAT_MS_4BYTE, + FORMAT_MS_WHEEL, + FORMATS_NUM }; +typedef struct mouse_t { + const char *name; /* name of this device */ -typedef struct { - const char *name; /* name of this device */ - int8_t type, /* type of this device */ - port; - uint8_t flags, but, /* device flags */ - want_data, - status, format, - prompt, on_change, - id_len, id[255], - data_len, data[5]; - int abs_x, abs_y, - rel_x, rel_y, - rel_z, - oldb, lastb; + uint8_t id[252]; + uint8_t buf[256]; - int command_pos, command_phase, - report_pos, report_phase, - command_enabled, report_enabled; - double transmit_period, report_period; - pc_timer_t command_timer, report_timer; + uint8_t flags; /* device flags */ + uint8_t but; + uint8_t rts_toggle; + uint8_t status; + uint8_t format; + uint8_t prompt; - serial_t *serial; + uint8_t continuous; + uint8_t ib; + uint8_t command; + uint8_t buf_len; + uint8_t report_mode; + uint8_t id_len; + uint8_t buf_pos; + uint8_t rev; + + int8_t type; /* type of this device */ + int8_t port; + + int state; + + int bps; + int rps; + + double transmit_period; + double report_period; + double cur_period; + double min_bit_period; + double acc_time; + double host_transmit_period; + + pc_timer_t timer; + + serial_t * serial; } mouse_t; -#define FLAG_INPORT 0x80 /* device is MS InPort */ -#define FLAG_3BTN 0x20 /* enable 3-button mode */ -#define FLAG_SCALED 0x10 /* enable delta scaling */ -#define FLAG_INTR 0x04 /* dev can send interrupts */ -#define FLAG_FROZEN 0x02 /* do not update counters */ -#define FLAG_ENABLED 0x01 /* dev is enabled for use */ +#define FLAG_INPORT 0x80 /* device is MS InPort */ +#define FLAG_3BTN 0x20 /* enable 3-button mode */ +#define FLAG_SCALED 0x10 /* enable delta scaling */ +#define FLAG_INTR 0x04 /* dev can send interrupts */ +#define FLAG_FROZEN 0x02 /* do not update counters */ +#define FLAG_ENABLED 0x01 /* dev is enabled for use */ #ifdef ENABLE_MOUSE_SERIAL_LOG int mouse_serial_do_log = ENABLE_MOUSE_SERIAL_LOG; - static void mouse_serial_log(const char *fmt, ...) { va_list ap; if (mouse_serial_do_log) { - va_start(ap, fmt); - pclog_ex(fmt, ap); - va_end(ap); + va_start(ap, fmt); + pclog_ex(fmt, ap); + va_end(ap); } } #else -#define mouse_serial_log(fmt, ...) +# define mouse_serial_log(fmt, ...) #endif +static void +sermouse_set_period(mouse_t *dev, double period) +{ + dev->cur_period = period; /* Needed for the recalculation of the timings. */ + + timer_stop(&dev->timer); + + if (period > 0.0) + timer_on_auto(&dev->timer, 10000.0); +} static void -sermouse_timer_on(mouse_t *dev, double period, int report) +sermouse_transmit_byte(mouse_t *dev, int do_next) { - pc_timer_t *timer; - int *enabled; + if (dev->buf_pos == 0) + dev->acc_time = 0.0; - if (report) { - timer = &dev->report_timer; - enabled = &dev->report_enabled; - } else { - timer = &dev->command_timer; - enabled = &dev->command_enabled; + serial_write_fifo(dev->serial, dev->buf[dev->buf_pos]); + + if (do_next) { + dev->buf_pos = (dev->buf_pos + 1) % dev->buf_len; + + if (dev->buf_pos != 0) + sermouse_set_period(dev, dev->transmit_period); } - - timer_on_auto(timer, period); - - *enabled = 1; } - -static double -sermouse_transmit_period(mouse_t *dev, int bps, int rps) -{ - double dbps = (double) bps; - double temp = 0.0; - int word_len; - - switch (dev->format) { - case 0: - case 1: /* Mouse Systems and Three Byte Packed formats: 8 data, no parity, 2 stop, 1 start */ - word_len = 11; - break; - case 2: /* Hexadecimal format - 8 data, no parity, 1 stop, 1 start - number of stop bits is a guess because - it is not documented anywhere. */ - word_len = 10; - break; - case 3: - case 6: /* Bit Pad One formats: 7 data, even parity, 2 stop, 1 start */ - word_len = 11; - break; - case 5: /* MM Series format: 8 data, odd parity, 1 stop, 1 start */ - word_len = 11; - break; - default: - case 7: /* Microsoft-compatible format: 7 data, no parity, 1 stop, 1 start */ - word_len = 9; - break; - } - - if (rps == -1) - temp = (double) word_len; - else { - temp = (double) rps; - temp = (9600.0 - (temp * 33.0)); - temp /= rps; - } - temp = (1000000.0 / dbps) * temp; - - return temp; -} - - -/* Callback from serial driver: RTS was toggled. */ static void -sermouse_callback(struct serial_s *serial, void *priv) +sermouse_transmit(mouse_t *dev, int len, int from_report, int to_report) { - mouse_t *dev = (mouse_t *)priv; + dev->state = to_report ? STATE_TRANSMIT_REPORT : STATE_TRANSMIT; + dev->buf_pos = 0; + dev->buf_len = len; - /* Start a timer to wake us up in a little while. */ - dev->command_pos = 0; - dev->command_phase = PHASE_ID; - if (dev->id[0] != 'H') - dev->format = 7; - dev->transmit_period = sermouse_transmit_period(dev, 1200, -1); - timer_stop(&dev->command_timer); -#ifdef USE_NEW_DYNAREC - sermouse_timer_on(dev, cpu_use_dynarec ? 5000.0 : dev->transmit_period, 0); -#else - sermouse_timer_on(dev, dev->transmit_period, 0); -#endif + if (from_report) { + if (dev->acc_time > dev->report_period) + dev->acc_time -= dev->report_period; + + /* We have too little time left, pretend it's zero and handle + schedule the next report at byte period. */ + if (dev->acc_time < dev->min_bit_period) + sermouse_set_period(dev, dev->transmit_period); + /* We have enough time, schedule the next report at report period, + subtract the accumulated time from the total period, and add + one byte period (the first byte delay). */ + else + sermouse_set_period(dev, dev->report_period - dev->acc_time + dev->transmit_period); + } else + sermouse_set_period(dev, dev->transmit_period); } - static uint8_t -sermouse_data_msystems(mouse_t *dev, int x, int y, int b) +sermouse_report_msystems(mouse_t *dev) { - dev->data[0] = 0x80; - dev->data[0] |= (b & 0x01) ? 0x00 : 0x04; /* left button */ - dev->data[0] |= (b & 0x02) ? 0x00 : 0x01; /* middle button */ - dev->data[0] |= (b & 0x04) ? 0x00 : 0x02; /* right button */ - dev->data[1] = x; - dev->data[2] = -y; - dev->data[3] = x; /* same as byte 1 */ - dev->data[4] = -y; /* same as byte 2 */ + int delta_x = 0; + int delta_y = 0; + int b = mouse_get_buttons_ex(); + + mouse_subtract_coords(&delta_x, &delta_y, NULL, NULL, -128, 127, 1, 0); + + dev->buf[0] = 0x80; + dev->buf[0] |= (b & 0x01) ? 0x00 : 0x04; /* left button */ + if (dev->but >= 3) + dev->buf[0] |= (b & 0x04) ? 0x00 : 0x02; /* middle button */ + else + dev->buf[0] |= 0x02; /* middle button */ + dev->buf[0] |= (b & 0x02) ? 0x00 : 0x01; /* right button */ + dev->buf[1] = delta_x; + dev->buf[2] = delta_y; + dev->buf[3] = delta_x; /* same as byte 1 */ + dev->buf[4] = delta_y; /* same as byte 2 */ return 5; } - static uint8_t -sermouse_data_3bp(mouse_t *dev, int x, int y, int b) +sermouse_report_3bp(mouse_t *dev) { - dev->data[0] |= (b & 0x01) ? 0x00 : 0x04; /* left button */ - dev->data[0] |= (b & 0x04) ? 0x00 : 0x02; /* middle button */ - dev->data[0] |= (b & 0x02) ? 0x00 : 0x01; /* right button */ - dev->data[1] = x; - dev->data[2] = -y; + int delta_x = 0; + int delta_y = 0; + int b = mouse_get_buttons_ex(); + + mouse_subtract_coords(&delta_x, &delta_y, NULL, NULL, -128, 127, 1, 0); + + dev->buf[0] = 0x80; + dev->buf[0] |= (b & 0x01) ? 0x04 : 0x00; /* left button */ + if (dev->but >= 3) + dev->buf[0] |= (b & 0x04) ? 0x02 : 0x00; /* middle button */ + dev->buf[0] |= (b & 0x02) ? 0x01 : 0x00; /* right button */ + dev->buf[1] = delta_x; + dev->buf[2] = delta_y; return 3; } - static uint8_t -sermouse_data_mmseries(mouse_t *dev, int x, int y, int b) +sermouse_report_mmseries(mouse_t *dev) { - if (x < -127) - x = -127; - if (y < -127) - y = -127; + int delta_x = 0; + int delta_y = 0; + int b = mouse_get_buttons_ex(); - dev->data[0] = 0x80; - if (x >= 0) - dev->data[0] |= 0x10; - if (y < 0) - dev->data[0] |= 0x08; - dev->data[0] |= (b & 0x01) ? 0x04 : 0x00; /* left button */ - dev->data[0] |= (b & 0x04) ? 0x02 : 0x00; /* middle button */ - dev->data[0] |= (b & 0x02) ? 0x01 : 0x00; /* right button */ - dev->data[1] = abs(x); - dev->data[2] = abs(y); + mouse_subtract_coords(&delta_x, &delta_y, NULL, NULL, -127, 127, 1, 0); + + dev->buf[0] = 0x80; + if (delta_x >= 0) + dev->buf[0] |= 0x10; + if (delta_y >= 0) + dev->buf[0] |= 0x08; + + dev->buf[0] |= (b & 0x01) ? 0x04 : 0x00; /* left button */ + if (dev->but >= 3) + dev->buf[0] |= (b & 0x04) ? 0x02 : 0x00; /* middle button */ + dev->buf[0] |= (b & 0x02) ? 0x01 : 0x00; /* right button */ + dev->buf[1] = ABS(delta_x) & 0x7f; + dev->buf[2] = ABS(delta_y) & 0x7f; + mouse_serial_log("MM series mouse report: %02X %02X %02X\n", dev->buf[0], dev->buf[1], dev->buf[2]); return 3; } - static uint8_t -sermouse_data_bp1(mouse_t *dev, int x, int y, int b) +sermouse_report_bp1(mouse_t *dev, int abs) { - dev->data[0] = 0x80; - dev->data[0] |= (b & 0x01) ? 0x10 : 0x00; /* left button */ - dev->data[0] |= (b & 0x04) ? 0x08 : 0x00; /* middle button */ - dev->data[0] |= (b & 0x02) ? 0x04 : 0x00; /* right button */ - dev->data[1] = (x & 0x3f); - dev->data[2] = (x >> 6); - dev->data[3] = (y & 0x3f); - dev->data[4] = (y >> 6); + int delta_x = 0; + int delta_y = 0; + int b = mouse_get_buttons_ex(); + + mouse_subtract_coords(&delta_x, &delta_y, NULL, NULL, -2048, 2047, 1, abs); + + dev->buf[0] = 0x80; + dev->buf[0] |= (b & 0x01) ? 0x10 : 0x00; /* left button */ + if (dev->but >= 3) + dev->buf[0] |= (b & 0x04) ? 0x08 : 0x00; /* middle button */ + dev->buf[0] |= (b & 0x02) ? 0x04 : 0x00; /* right button */ + dev->buf[1] = (delta_x & 0x3f); + dev->buf[2] = ((delta_x >> 6) & 0x3f); + dev->buf[3] = (delta_y & 0x3f); + dev->buf[4] = ((delta_y >> 6) & 0x3f); return 5; } - static uint8_t -sermouse_data_ms(mouse_t *dev, int x, int y, int z, int b) +sermouse_report_ms(mouse_t *dev) { uint8_t len; + int delta_x = 0; + int delta_y = 0; + int delta_z = 0; + int b = mouse_get_buttons_ex(); - dev->data[0] = 0x40; - dev->data[0] |= (((y >> 6) & 0x03) << 2); - dev->data[0] |= ((x >> 6) & 0x03); + mouse_subtract_coords(&delta_x, &delta_y, NULL, NULL, -128, 127, 0, 0); + mouse_subtract_z(&delta_z, -8, 7, 1); + + dev->buf[0] = 0x40; + dev->buf[0] |= (((delta_y >> 6) & 0x03) << 2); + dev->buf[0] |= ((delta_x >> 6) & 0x03); if (b & 0x01) - dev->data[0] |= 0x20; + dev->buf[0] |= 0x20; if (b & 0x02) - dev->data[0] |= 0x10; - dev->data[1] = x & 0x3F; - dev->data[2] = y & 0x3F; + dev->buf[0] |= 0x10; + dev->buf[1] = delta_x & 0x3f; + dev->buf[2] = delta_y & 0x3f; + mouse_serial_log("Microsoft serial mouse report: %02X %02X %02X\n", dev->buf[0], dev->buf[1], dev->buf[2]); if (dev->but == 3) { - len = 3; - if (dev->type == MOUSE_TYPE_LT3BUTTON) { - if (b & 0x04) { - dev->data[3] = 0x20; - len++; - } - } else { - if ((b ^ dev->oldb) & 0x04) { - /* Microsoft 3-button mice send a fourth byte of 0x00 when the middle button - has changed. */ - dev->data[3] = 0x00; - len++; - } - } + len = 3; + if (dev->format == FORMAT_MS) { + if (b & 0x04) { + dev->buf[3] = 0x20; + len++; + } + } else { + if (mouse_mbut_changed()) { + /* Microsoft 3-button mice send a fourth byte of 0x00 when the middle button + has changed. */ + dev->buf[3] = 0x00; + len++; + } + } } else if (dev->but == 4) { - len = 4; - dev->data[3] = z & 0x0F; - if (b & 0x04) - dev->data[3] |= 0x10; + len = 4; + + dev->buf[3] = delta_z & 0x0f; + if (b & 0x04) + dev->buf[3] |= 0x10; } else - len = 3; + len = 3; return len; } - static uint8_t -sermouse_data_hex(mouse_t *dev, int x, int y, int b) +sermouse_report_hex(mouse_t *dev) { - char ret[6] = { 0, 0, 0, 0, 0, 0 }; - uint8_t i, but = 0x00; + char ret[6] = { 0, 0, 0, 0, 0, 0 }; + uint8_t but = 0x00; + int delta_x = 0; + int delta_y = 0; + int b = mouse_get_buttons_ex(); - but |= (b & 0x01) ? 0x04 : 0x00; /* left button */ - but |= (b & 0x04) ? 0x02 : 0x00; /* middle button */ - but |= (b & 0x02) ? 0x01 : 0x00; /* right button */ + mouse_subtract_coords(&delta_x, &delta_y, NULL, NULL, -128, 127, 1, 0); - sprintf(ret, "%02X%02X%01X", (int8_t) y, (int8_t) x, but & 0x0f); + but |= (b & 0x01) ? 0x04 : 0x00; /* left button */ + if (dev->but >= 3) + but |= (b & 0x04) ? 0x02 : 0x00; /* middle button */ + but |= (b & 0x02) ? 0x01 : 0x00; /* right button */ - for (i = 0; i < 5; i++) - dev->data[i] = ret[4 - i]; + sprintf(ret, "%01X%02X%02X", but & 0x0f, (int8_t) delta_x, (int8_t) delta_y); + + memcpy(dev->buf, ret, 5); return 5; } - -static void -sermouse_report(int x, int y, int z, int b, mouse_t *dev) +static int +sermouse_report(mouse_t *dev) { int len = 0; - memset(dev->data, 0, 5); - - /* If the mouse is 2-button, ignore the middle button. */ - if (dev->but == 2) - b &= ~0x04; + memset(dev->buf, 0, 5); switch (dev->format) { - case 0: - len = sermouse_data_msystems(dev, x, y, b); - break; - case 1: - len = sermouse_data_3bp(dev, x, y, b); - break; - case 2: - len = sermouse_data_hex(dev, x, y, b); - break; - case 3: /* Relative */ - len = sermouse_data_bp1(dev, x, y, b); - break; - case 5: - len = sermouse_data_mmseries(dev, x, y, b); - break; - case 6: /* Absolute */ - len = sermouse_data_bp1(dev, dev->abs_x, dev->abs_y, b); - break; - case 7: - len = sermouse_data_ms(dev, x, y, z, b); - break; + case FORMAT_PB_5BYTE: + len = sermouse_report_msystems(dev); + break; + case FORMAT_PB_3BYTE: + len = sermouse_report_3bp(dev); + break; + case FORMAT_HEX: + len = sermouse_report_hex(dev); + break; + case FORMAT_BP1_REL: + len = sermouse_report_bp1(dev, 0); + break; + case FORMAT_MM_SERIES: + len = sermouse_report_mmseries(dev); + break; + case FORMAT_BP1_ABS: + len = sermouse_report_bp1(dev, 1); + break; + case FORMAT_MS: + case FORMAT_MS_4BYTE: + case FORMAT_MS_WHEEL: + len = sermouse_report_ms(dev); + break; + + default: + break; } - dev->data_len = len; + return len; } - static void -sermouse_command_phase_idle(mouse_t *dev) +sermouse_transmit_report(mouse_t *dev, int from_report) { - dev->command_pos = 0; - dev->command_phase = PHASE_IDLE; - dev->command_enabled = 0; -} - - -static void -sermouse_command_pos_check(mouse_t *dev, int len) -{ - if (++dev->command_pos == len) - sermouse_command_phase_idle(dev); - else - timer_on_auto(&dev->command_timer, dev->transmit_period); -} - - -static uint8_t -sermouse_last_button_status(mouse_t *dev) -{ - uint8_t ret = 0x00; - - if (dev->oldb & 0x01) - ret |= 0x04; - if (dev->oldb & 0x02) - ret |= 0x02; - if (dev->oldb & 0x04) - ret |= 0x01; - - return ret; -} - - -static void -sermouse_update_delta(mouse_t *dev, int *local, int *global) -{ - int min, max; - - if (dev->format == 3) { - min = -2048; - max = 2047; - } else { - min = -128; - max = 127; - } - - if (*global > max) { - *local = max; - *global -= max; - } else if (*global < min) { - *local = min; - *global += -min; - } else { - *local = *global; - *global = 0; - } -} - - -static uint8_t -sermouse_update_data(mouse_t *dev) -{ - uint8_t ret = 0; - int delta_x, delta_y, delta_z; - - /* Update the deltas and the delays. */ - sermouse_update_delta(dev, &delta_x, &dev->rel_x); - sermouse_update_delta(dev, &delta_y, &dev->rel_y); - sermouse_update_delta(dev, &delta_z, &dev->rel_z); - - sermouse_report(delta_x, delta_y, delta_z, dev->oldb, dev); - - mouse_serial_log("delta_x = %i, delta_y = %i, delta_z = %i, dev->oldb = %02X\n", - delta_x, delta_y, delta_z, dev->oldb); - - if (delta_x || delta_y || delta_z || (dev->oldb != dev->lastb) || !dev->on_change) - ret = 1; - - dev->lastb = dev->oldb; - - mouse_serial_log("sermouse_update_data(): ret = %i\n", ret); - - return ret; -} - - -static double -sermouse_report_period(mouse_t *dev) -{ - if (dev->report_period == 0) - return dev->transmit_period; - else - return dev->report_period; -} - - -static void -sermouse_report_prepare(mouse_t *dev) -{ - if (sermouse_update_data(dev)) { - /* Start sending data. */ - dev->report_phase = REPORT_PHASE_TRANSMIT; - dev->report_pos = 0; - sermouse_timer_on(dev, dev->transmit_period, 1); - } else { - dev->report_phase = REPORT_PHASE_PREPARE; - sermouse_timer_on(dev, sermouse_report_period(dev), 1); - } -} - - -static void -sermouse_report_timer(void *priv) -{ - mouse_t *dev = (mouse_t *)priv; - - if (dev->report_phase == REPORT_PHASE_PREPARE) - sermouse_report_prepare(dev); + if (mouse_capture && mouse_state_changed()) + sermouse_transmit(dev, sermouse_report(dev), from_report, 1); else { - /* If using the Mouse Systems format, update data because - the last two bytes are the X and Y delta since bytes 1 - and 2 were transmitted. */ - if (!dev->format && (dev->report_pos == 3)) - sermouse_update_data(dev); - serial_write_fifo(dev->serial, dev->data[dev->report_pos]); - if (++dev->report_pos == dev->data_len) { - if (!dev->report_enabled) - sermouse_report_prepare(dev); - else { - sermouse_timer_on(dev, sermouse_report_period(dev), 1); - dev->report_phase = REPORT_PHASE_PREPARE; - } - } else - sermouse_timer_on(dev, dev->transmit_period, 1); + if (dev->prompt || dev->continuous) + sermouse_set_period(dev, 0.0); + else { + dev->state = STATE_SKIP_REPORT; + /* Not in prompt or continuous mode and there have been no changes, + skip the next report entirely. */ + if (from_report) { + if (dev->acc_time > dev->report_period) + dev->acc_time -= dev->report_period; + + if (dev->acc_time < dev->min_bit_period) + sermouse_set_period(dev, dev->report_period); + else + sermouse_set_period(dev, (dev->report_period * 2.0) - dev->acc_time); + } else + sermouse_set_period(dev, dev->report_period); + } } } - -/* Callback timer expired, now send our "mouse ID" to the serial port. */ -static void -sermouse_command_timer(void *priv) -{ - mouse_t *dev = (mouse_t *)priv; - - switch (dev->command_phase) { - case PHASE_ID: - serial_write_fifo(dev->serial, dev->id[dev->command_pos]); - sermouse_command_pos_check(dev, dev->id_len); - if ((dev->command_phase == PHASE_IDLE) && (dev->type != MOUSE_TYPE_MSYSTEMS)) { - /* This resets back to Microsoft-compatible mode. */ - dev->report_phase = REPORT_PHASE_PREPARE; - sermouse_report_timer((void *) dev); - } - break; - case PHASE_DATA: - serial_write_fifo(dev->serial, dev->data[dev->command_pos]); - sermouse_command_pos_check(dev, dev->data_len); - break; - case PHASE_STATUS: - serial_write_fifo(dev->serial, dev->status); - sermouse_command_phase_idle(dev); - break; - case PHASE_DIAGNOSTIC: - if (dev->command_pos) - serial_write_fifo(dev->serial, 0x00); - else - serial_write_fifo(dev->serial, sermouse_last_button_status(dev)); - sermouse_command_pos_check(dev, 3); - break; - case PHASE_FORMAT_AND_REVISION: - serial_write_fifo(dev->serial, 0x10 | (dev->format << 1)); - sermouse_command_phase_idle(dev); - break; - case PHASE_BUTTONS: - serial_write_fifo(dev->serial, dev->but); - sermouse_command_phase_idle(dev); - break; - default: - sermouse_command_phase_idle(dev); - break; - } -} - - static int -sermouse_poll(int x, int y, int z, int b, void *priv) +sermouse_poll(void *priv) { - mouse_t *dev = (mouse_t *)priv; + mouse_t *dev = (mouse_t *) priv; - if (!x && !y && !z && (b == dev->oldb)) { - dev->oldb = b; - return(1); - } + if (!mouse_capture || dev->prompt || !dev->continuous || (dev->state != STATE_IDLE)) + return 1; - dev->oldb = b; - dev->abs_x += x; - dev->abs_y += y; - if (dev->abs_x < 0) - dev->abs_x = 0; - if (dev->abs_x > 4095) - dev->abs_x = 4095; - if (dev->abs_y < 0) - dev->abs_y = 0; - if (dev->abs_y > 4095) - dev->abs_y = 4095; - - if (dev->format == 3) { - if (x > 2047) x = 2047; - if (y > 2047) y = 2047; - if (x <- 2048) x = -2048; - if (y <- 2048) y = -2048; - } else { - if (x > 127) x = 127; - if (y > 127) y = 127; - if (x <- 128) x = -128; - if (y <- 128) y = -128; - } - - dev->rel_x += x; - dev->rel_y += y; - dev->rel_z += z; - - return(0); + sermouse_transmit_report(dev, 0); + return (dev->cur_period == 0.0) ? 1 : 0; } - static void -ltsermouse_prompt_mode(mouse_t *dev, int prompt) +ltsermouse_set_prompt_mode(mouse_t *dev, int prompt) { dev->prompt = prompt; - dev->status &= 0xBF; - if (prompt) - dev->status |= 0x40; + + if (prompt || dev->continuous) + sermouse_set_period(dev, 0.0); + else + sermouse_set_period(dev, dev->transmit_period); } - -static void -ltsermouse_command_phase(mouse_t *dev, int phase) -{ - dev->command_pos = 0; - dev->command_phase = phase; - timer_stop(&dev->command_timer); - sermouse_timer_on(dev, dev->transmit_period, 0); -} - - static void ltsermouse_set_report_period(mouse_t *dev, int rps) { - dev->report_period = sermouse_transmit_period(dev, 9600, rps); - timer_stop(&dev->report_timer); - sermouse_timer_on(dev, dev->report_period, 1); - ltsermouse_prompt_mode(dev, 0); - dev->report_phase = REPORT_PHASE_PREPARE; -} + /* Limit the reports rate according to the baud rate. */ + if (rps == 0) { + sermouse_set_period(dev, 0.0); + dev->report_period = 0.0; + dev->continuous = 1; + } else { +#if 0 + if (rps > dev->max_rps) + rps = dev->max_rps; +#endif -static void -ltsermouse_write(struct serial_s *serial, void *priv, uint8_t data) -{ - mouse_t *dev = (mouse_t *)priv; - - /* Stop reporting when we're processing a command. */ - dev->report_phase = REPORT_PHASE_PREPARE; - - if (dev->want_data) switch (dev->want_data) { - case 0x2A: - dev->data_len--; - dev->want_data = 0; - switch (data) { - default: - mouse_serial_log("Serial mouse: Invalid period %02X, using 1200 bps\n", data); - /*FALLTHROUGH*/ - case 0x6E: - dev->transmit_period = sermouse_transmit_period(dev, 1200, -1); - break; - case 0x6F: - dev->transmit_period = sermouse_transmit_period(dev, 2400, -1); - break; - case 0x70: - dev->transmit_period = sermouse_transmit_period(dev, 4800, -1); - break; - case 0x71: - dev->transmit_period = sermouse_transmit_period(dev, 9600, -1); - break; - } - break; - } else switch (data) { - case 0x2A: - dev->want_data = data; - dev->data_len = 1; - break; - case 0x44: /* Set prompt mode */ - ltsermouse_prompt_mode(dev, 1); - break; - case 0x50: - if (!dev->prompt) - ltsermouse_prompt_mode(dev, 1); - sermouse_update_data(dev); - ltsermouse_command_phase(dev, PHASE_DATA); - break; - case 0x73: /* Status */ - ltsermouse_command_phase(dev, PHASE_STATUS); - break; - case 0x4A: /* Report Rate Selection commands */ - ltsermouse_set_report_period(dev, 10); - break; - case 0x4B: - ltsermouse_set_report_period(dev, 20); - break; - case 0x4C: - ltsermouse_set_report_period(dev, 35); - break; - case 0x52: - ltsermouse_set_report_period(dev, 50); - break; - case 0x4D: - ltsermouse_set_report_period(dev, 70); - break; - case 0x51: - ltsermouse_set_report_period(dev, 100); - break; - case 0x4E: - ltsermouse_set_report_period(dev, 150); - break; - case 0x4F: - ltsermouse_prompt_mode(dev, 0); - dev->report_period = 0; - timer_stop(&dev->report_timer); - dev->report_phase = REPORT_PHASE_PREPARE; - sermouse_report_timer((void *) dev); - break; - case 0x41: - dev->format = 6; /* Aboslute Bit Pad One Format */ - dev->abs_x = dev->abs_y = 0; - break; - case 0x42: - dev->format = 3; /* Relative Bit Pad One Format */ - break; - case 0x53: - dev->format = 5; /* MM Series Format */ - break; - case 0x54: - dev->format = 1; /* Three Byte Packed Binary Format */ - break; - case 0x55: /* This is the Mouse Systems-compatible format */ - dev->format = 0; /* Five Byte Packed Binary Format */ - break; - case 0x56: - dev->format = 7; /* Microsoft Compatible Format */ - break; - case 0x57: - dev->format = 2; /* Hexadecimal Format */ - break; - case 0x05: - ltsermouse_command_phase(dev, PHASE_DIAGNOSTIC); - break; - case 0x66: - ltsermouse_command_phase(dev, PHASE_FORMAT_AND_REVISION); - break; - case 0x6B: - ltsermouse_command_phase(dev, PHASE_BUTTONS); - break; + dev->continuous = 0; + dev->report_period = 1000000.0 / ((double) rps); + /* Actual spacing between reports. */ } } +static void +ltsermouse_update_report_period(mouse_t *dev) +{ + ltsermouse_set_report_period(dev, dev->rps); + + ltsermouse_set_prompt_mode(dev, 0); + mouse_serial_log("ltsermouse_update_report_period(): %i, %i\n", dev->continuous, dev->prompt); + if (dev->continuous) + dev->state = STATE_IDLE; + else { + sermouse_transmit_report(dev, 0); + dev->state = STATE_TRANSMIT_REPORT; + } +} + +static void +ltsermouse_switch_baud_rate(mouse_t *dev, int next_state) +{ + double word_lens[FORMATS_NUM] = { + [FORMAT_BP1_ABS] = 7.0 + 1.0, /* 7 data bits + even parity */ + [FORMAT_BP1_REL] = 7.0 + 1.0, /* 7 data bits + even parity */ + [FORMAT_MM_SERIES] = 8.0 + 1.0, /* 8 data bits + odd parity */ + [FORMAT_PB_3BYTE] = 8.0, /* 8 data bits + no parity */ + [FORMAT_PB_5BYTE] = 8.0, /* 8 data bits + no parity */ + [FORMAT_MS] = 7.0, /* 7 datas bits + no parity */ + [FORMAT_HEX] = 8.0, /* 8 data bits + no parity */ + [FORMAT_MS_4BYTE] = 7.0, /* 7 datas bits + no parity */ + [FORMAT_MS_WHEEL] = 7.0 }; /* 7 datas bits + no parity */ + double word_len = word_lens[dev->format]; + + word_len += 1.0 + 2.0; /* 1 start bit + 2 stop bits */ + +#if 0 + dev->max_rps = (int) floor(((double) dev->bps) / (word_len * num_words)); +#endif + + if (next_state == STATE_BAUD_RATE) + dev->transmit_period = dev->host_transmit_period; + else + dev->transmit_period = 1000000.0 / ((double) dev->bps); + + dev->min_bit_period = dev->transmit_period; + + dev->transmit_period *= word_len; + /* The transmit period for the entire report, we're going to need this in ltsermouse_set_report_period(). */ +#if 0 + dev->report_transmit_period = dev->transmit_period * num_words; +#endif + + ltsermouse_set_report_period(dev, dev->rps); + + if (!dev->continuous && (next_state != STATE_BAUD_RATE)) { + if (dev->prompt) + ltsermouse_set_prompt_mode(dev, 0); + + sermouse_transmit_report(dev, 0); + } + + dev->state = next_state; +} + +static int +sermouse_next_state(mouse_t *dev) +{ + int ret = STATE_IDLE; + + if (dev->prompt || (dev->rps == 0)) + ret = STATE_IDLE; + else + ret = STATE_TRANSMIT; + + return ret; +} + +static void +ltsermouse_process_command(mouse_t *dev) +{ + int cmd_to_rps[9] = { 10, 20, 35, 70, 150, 0, -1, 100, 50 }; + int b; + uint8_t format_codes[FORMATS_NUM] = { + [FORMAT_BP1_ABS] = 0x0c, + [FORMAT_BP1_REL] = 0x06, + [FORMAT_MM_SERIES] = 0x0a, + [FORMAT_PB_3BYTE] = 0x00, + [FORMAT_PB_5BYTE] = 0x02, + [FORMAT_MS] = 0x0e, + [FORMAT_HEX] = 0x04, + [FORMAT_MS_4BYTE] = 0x08, /* Guess */ + [FORMAT_MS_WHEEL] = 0x08 }; /* Guess */ + const char *copr = "\r\n(C) 2023 86Box, Revision 3.0"; + + mouse_serial_log("ltsermouse_process_command(): %02X\n", dev->ib); + dev->command = dev->ib; + + switch (dev->command) { + case 0x20: + /* Auto Baud Selection */ + dev->bps = (int) floor(1000000.0 / dev->host_transmit_period); + dev->transmit_period = dev->host_transmit_period; + + dev->buf[0] = 0x06; + sermouse_transmit(dev, 1, 0, 0); + + ltsermouse_switch_baud_rate(dev, STATE_BAUD_RATE); + break; + + case 0x4a: /* Report Rate Selection commands */ + case 0x4b: + case 0x4c: + case 0x52: + case 0x4d: + case 0x51: + case 0x4e: + case 0x4f: + dev->report_mode = dev->command; + dev->rps = cmd_to_rps[dev->command - 0x4a]; + ltsermouse_update_report_period(dev); + break; + + case 0x44: + /* Select Prompt Mode */ + dev->report_mode = dev->command; + ltsermouse_set_prompt_mode(dev, 1); + dev->state = STATE_IDLE; + break; + case 0x50: + /* Promopt to send a report (also enters Prompt Mode). */ + if (!dev->prompt) { + dev->report_mode = 0x44; + ltsermouse_set_prompt_mode(dev, 1); + } + sermouse_transmit_report(dev, 0); + dev->state = STATE_TRANSMIT_REPORT; + break; + + case 0x41: + /* Absolute Bit Pad One Packed Binary Format */ + mouse_clear_coords(); + fallthrough; + case 0x42: /* Relative Bit Pad One Packed Binary Format */ + case 0x53: /* MM Series Data Format */ + case 0x54: /* Three Byte Packed Binary Format */ + case 0x55: /* Five Byte Packed Binary Format (Mouse Systems-compatible) */ + case 0x56: /* Microsoft Compatible Format */ + case 0x57: /* Hexadecimal Format */ + case 0x58: /* Microsoft Compatible Format (3+1 byte 3-button, from the FreeBSD source code) */ + if ((dev->rev >= 0x02) && ((dev->command != 0x58) || (dev->rev > 0x04))) { + dev->format = dev->command & 0x1f; + ltsermouse_switch_baud_rate(dev, sermouse_next_state(dev)); + } + break; + + case 0x2a: + if (dev->rev >= 0x03) { + /* Programmable Baud Rate Selection */ + dev->state = STATE_DATA; + } + break; + + case 0x73: + /* Status */ + dev->buf[0] = dev->prompt ? 0x4f : 0x0f; + sermouse_transmit(dev, 1, 0, 0); + break; + case 0x05: + /* Diagnostic */ + b = mouse_get_buttons_ex(); + dev->buf[0] = ((b & 0x01) << 2) | ((b & 0x06) >> 1); + dev->buf[1] = dev->buf[2] = 0x00; + sermouse_transmit(dev, 3, 0, 0); + break; + + case 0x66: + if (dev->rev >= 0x20) { + /* Format and Revision Number */ + dev->buf[0] = format_codes[dev->format]; + dev->buf[0] |= 0x10; /* Revision 3.0, 0x00 would be Revision 2.0 */ + sermouse_transmit(dev, 1, 0, 0); + } + break; + + case 0x74: + /* Format and Mode in ASCII */ + if (dev->rev >= 0x03) { + dev->buf[0] = dev->format | 0x40; + dev->buf[1] = dev->report_mode; + sermouse_transmit(dev, 2, 0, 0); + } + break; + + case 0x63: + /* Copyright and Revision in ASCII */ + if (dev->rev >= 0x03) { + memcpy(&(dev->buf[0]), copr, strlen(copr) + 1); + sermouse_transmit(dev, strlen(copr) + 1, 0, 0); + } else { + memcpy(&(dev->buf[0]), copr, strlen(copr)); + sermouse_transmit(dev, strlen(copr), 0, 0); + } + dev->buf[29] = dev->rev | 0x30; + break; + + case 0x64: + /* Dormant State */ + dev->state = STATE_DORMANT; + break; + + case 0x6b: + /* Buttons - 86Box-specific command. */ + dev->state = dev->but; + break; + + default: + break; + } +} + +static void +ltsermouse_process_data(mouse_t *dev) +{ + mouse_serial_log("ltsermouse_process_data(): %02X (command = %02X)\n", dev->ib, dev->command); + + switch(dev->command) { + case 0x2a: + switch (dev->ib) { + default: + mouse_serial_log("Serial mouse: Invalid period %02X, using 1200 bps\n", data); + fallthrough; + case 0x6e: + dev->bps = 1200; + break; + case 0x6f: + dev->bps = 2400; + break; + case 0x70: + dev->bps = 4800; + break; + case 0x71: + dev->bps = 9600; + break; + } + ltsermouse_switch_baud_rate(dev, (dev->prompt || dev->continuous) ? STATE_IDLE : STATE_TRANSMIT_REPORT); + break; + default: + dev->state = STATE_IDLE; + break; + } +} + +static void +sermouse_reset(mouse_t *dev, int callback) +{ + sermouse_set_period(dev, 0.0); + + dev->bps = 1200; + dev->rps = 0; + dev->prompt = 0; + if (dev->id[0] == 'H') + dev->format = FORMAT_MSYSTEMS; + else switch (dev->but) { + default: + case 2: + dev->format = FORMAT_MS; + break; + case 3: + dev->format = (dev->type == MOUSE_TYPE_LT3BUTTON) ? FORMAT_MS : FORMAT_MS_4BYTE; + break; + case 4: + dev->format = FORMAT_MS_WHEEL; + break; + } + + ltsermouse_switch_baud_rate(dev, callback ? STATE_TRANSMIT : STATE_IDLE); +} + +static void +sermouse_timer(void *priv) +{ + mouse_t *dev = (mouse_t *) priv; +#ifdef ENABLE_MOUSE_SERIAL_LOG + int old_state = dev->state; +#endif + + switch (dev->state) { + case STATE_RESET: + /* All three mice default to continuous reporting. */ + sermouse_reset(dev, 0); + break; + case STATE_DATA: + ltsermouse_process_data(dev); + break; + case STATE_COMMAND: + ltsermouse_process_command(dev); + break; + case STATE_SKIP_REPORT: + if (!dev->prompt && !dev->continuous) + sermouse_transmit_report(dev, (dev->state == STATE_TRANSMIT_REPORT)); + else + dev->state = STATE_IDLE; + break; + case STATE_TRANSMIT_REPORT: + case STATE_TRANSMIT: + case STATE_BAUD_RATE: + sermouse_transmit_byte(dev, 1); + + if (dev->buf_pos == 0) { + if (!dev->prompt && !dev->continuous) + sermouse_transmit_report(dev, (dev->state == STATE_TRANSMIT_REPORT)); + else + dev->state = STATE_IDLE; + } + break; + default: + break; + } + + mouse_serial_log("sermouse_timer(): %02i -> %02i\n", old_state, dev->state); +} + +static void +ltsermouse_write(UNUSED(struct serial_s *serial), void *priv, uint8_t data) +{ + mouse_t *dev = (mouse_t *) priv; + + mouse_serial_log("ltsermouse_write(): %02X\n", data); + + dev->ib = data; + + switch (dev->state) { + case STATE_RESET: + case STATE_BAUD_RATE: + break; + case STATE_TRANSMIT_REPORT: + case STATE_TRANSMIT: + case STATE_SKIP_REPORT: + sermouse_set_period(dev, 0.0); + fallthrough; + default: + dev->state = STATE_COMMAND; + fallthrough; + case STATE_DATA: + sermouse_timer(dev); + break; + } +} + +/* Callback from serial driver: RTS was toggled. */ +static void +sermouse_callback(UNUSED(struct serial_s *serial), void *priv) +{ + mouse_t *dev = (mouse_t *) priv; + + sermouse_reset(dev, 1); + + memcpy(dev->buf, dev->id, dev->id_len); + sermouse_transmit(dev, dev->id_len, 0, 0); +} + +static void +ltsermouse_transmit_period(UNUSED(serial_t *serial), void *priv, double transmit_period) +{ + mouse_t *dev = (mouse_t *) priv; + + dev->host_transmit_period = transmit_period; +} static void sermouse_speed_changed(void *priv) { - mouse_t *dev = (mouse_t *)priv; + mouse_t *dev = (mouse_t *) priv; - if (dev->report_enabled) { - timer_stop(&dev->report_timer); - if (dev->report_phase == REPORT_PHASE_TRANSMIT) - sermouse_timer_on(dev, dev->transmit_period, 1); - else - sermouse_timer_on(dev, sermouse_report_period(dev), 1); - } - - if (dev->command_enabled) { - timer_stop(&dev->command_timer); - sermouse_timer_on(dev, dev->transmit_period, 0); - } + if (dev->cur_period != 0.0) + sermouse_set_period(dev, dev->cur_period); } - static void sermouse_close(void *priv) { - mouse_t *dev = (mouse_t *)priv; + mouse_t *dev = (mouse_t *) priv; /* Detach serial port from the mouse. */ if (dev && dev->serial && dev->serial->sd) - memset(dev->serial->sd, 0, sizeof(serial_device_t)); + memset(dev->serial->sd, 0, sizeof(serial_device_t)); free(dev); } - /* Initialize the device for use by the user. */ static void * sermouse_init(const device_t *info) { mouse_t *dev; + void (*rcr_callback)(struct serial_s *serial, void *priv); + void (*dev_write)(struct serial_s *serial, void *priv, uint8_t data); + void (*transmit_period_callback)(struct serial_s *serial, void *priv, double transmit_period); - dev = (mouse_t *)malloc(sizeof(mouse_t)); + dev = (mouse_t *) malloc(sizeof(mouse_t)); memset(dev, 0x00, sizeof(mouse_t)); dev->name = info->name; - dev->but = device_get_config_int("buttons"); + dev->but = device_get_config_int("buttons"); + dev->rev = device_get_config_int("revision"); + + if (info->local == 0) + dev->rts_toggle = 1; + else + dev->rts_toggle = device_get_config_int("rts_toggle"); + if (dev->but > 2) - dev->flags |= FLAG_3BTN; + dev->flags |= FLAG_3BTN; if (info->local == MOUSE_TYPE_MSYSTEMS) { - dev->on_change = 1; - dev->format = 0; - dev->type = info->local; - dev->id_len = 1; - dev->id[0] = 'H'; + dev->format = 0; + dev->type = info->local; + dev->id_len = 1; + dev->id[0] = 'H'; } else { - dev->on_change = !info->local; - dev->format = 7; - dev->status = 0x0f; - dev->id_len = 1; - dev->id[0] = 'M'; - switch(dev->but) { - case 2: - default: - dev->type = info->local ? MOUSE_TYPE_LOGITECH : MOUSE_TYPE_MICROSOFT; - break; - case 3: - dev->type = info->local ? MOUSE_TYPE_LT3BUTTON : MOUSE_TYPE_MS3BUTTON; - dev->id_len = 2; - dev->id[1] = '3'; - break; - case 4: - dev->type = MOUSE_TYPE_MSWHEEL; - dev->id_len = 6; - dev->id[1] = 'Z'; - dev->id[2] = '@'; - break; - } + dev->format = 7; + dev->status = 0x0f; + dev->id_len = 1; + dev->id[0] = 'M'; + if (info->local) + dev->rev = device_get_config_int("revision"); + switch (dev->but) { + default: + case 2: + dev->type = info->local ? MOUSE_TYPE_LOGITECH : MOUSE_TYPE_MICROSOFT; + break; + case 3: + dev->type = info->local ? MOUSE_TYPE_LT3BUTTON : MOUSE_TYPE_MS3BUTTON; + dev->id_len = 2; + dev->id[1] = '3'; + break; + case 4: + dev->type = MOUSE_TYPE_MSWHEEL; + dev->id_len = 6; + dev->id[1] = 'Z'; + dev->id[2] = '@'; + break; + } } - dev->transmit_period = sermouse_transmit_period(dev, 1200, -1); - - /* Default: Continuous reporting = no delay between reports. */ - dev->report_phase = REPORT_PHASE_PREPARE; - dev->report_period = 0; - - /* Default: Doing nothing - command transmit timer deactivated. */ - dev->command_phase = PHASE_IDLE; - dev->port = device_get_config_int("port"); /* Attach a serial port to the mouse. */ - if (info->local) - dev->serial = serial_attach(dev->port, sermouse_callback, ltsermouse_write, dev); - else - dev->serial = serial_attach(dev->port, sermouse_callback, NULL, dev); + rcr_callback = dev->rts_toggle ? sermouse_callback : NULL; + dev_write = (info->local == 1) ? ltsermouse_write : NULL; + transmit_period_callback = (info->local == 1) ? ltsermouse_transmit_period : NULL; + + dev->serial = serial_attach_ex(dev->port, rcr_callback, dev_write, + transmit_period_callback, NULL, dev); mouse_serial_log("%s: port=COM%d\n", dev->name, dev->port + 1); - timer_add(&dev->report_timer, sermouse_report_timer, dev, 0); - timer_add(&dev->command_timer, sermouse_command_timer, dev, 0); + timer_add(&dev->timer, sermouse_timer, dev, 0); - if (info->local == MOUSE_TYPE_MSYSTEMS) { - sermouse_timer_on(dev, dev->transmit_period, 1); - dev->report_enabled = 1; - } + /* The five second delay allows the mouse to execute internal initializations. */ + sermouse_set_period(dev, 5000000.0); /* Tell them how many buttons we have. */ - mouse_set_buttons((dev->flags & FLAG_3BTN) ? 3 : 2); + mouse_set_buttons(dev->but); /* Return our private data to the I/O layer. */ - return(dev); + return dev; } +static const device_config_t msssermouse_config[] = { + // clang-format off + { + .name = "port", + .description = "Serial Port", + .type = CONFIG_SELECTION, + .default_string = "", + .default_int = 0, + .file_filter = "", + .spinner = { 0 }, + .selection = { + { .description = "COM1", .value = 0 }, + { .description = "COM2", .value = 1 }, + { .description = "COM3", .value = 2 }, + { .description = "COM4", .value = 3 }, + { .description = "" } + } + }, + { + .name = "buttons", + .description = "Buttons", + .type = CONFIG_SELECTION, + .default_string = "", + .default_int = 2, + .file_filter = "", + .spinner = { 0 }, + .selection = { + { .description = "Two", .value = 2 }, + { .description = "Three", .value = 3 }, + { .description = "" } + } + }, + { + .name = "rts_toggle", + .description = "RTS toggle", + .type = CONFIG_BINARY, + .default_string = "", + .default_int = 0 + }, + { .name = "", .description = "", .type = CONFIG_END } + // clang-format on +}; static const device_config_t mssermouse_config[] = { + // clang-format off { - "port", "Serial Port", CONFIG_SELECTION, "", 0, "", { 0 }, { - { - "COM1", 0 - }, - { - "COM2", 1 - }, - { - "" - } - } + .name = "port", + .description = "Serial Port", + .type = CONFIG_SELECTION, + .default_string = "", + .default_int = 0, + .file_filter = "", + .spinner = { 0 }, + .selection = { + { .description = "COM1", .value = 0 }, + { .description = "COM2", .value = 1 }, + { .description = "COM3", .value = 2 }, + { .description = "COM4", .value = 3 }, + { .description = "" } + } }, { - "buttons", "Buttons", CONFIG_SELECTION, "", 2, "", { 0 }, { - { - "Two", 2 - }, - { - "Three", 3 - }, - { - "Wheel", 4 - }, - { - "" - } - } + .name = "buttons", + .description = "Buttons", + .type = CONFIG_SELECTION, + .default_string = "", + .default_int = 2, + .file_filter = "", + .spinner = { 0 }, + .selection = { + { .description = "Two", .value = 2 }, + { .description = "Three", .value = 3 }, + { .description = "Wheel", .value = 4 }, + { .description = "" } + } }, - { - "", "", -1 - } + { .name = "", .description = "", .type = CONFIG_END } + // clang-format on }; - static const device_config_t ltsermouse_config[] = { + // clang-format off { - "port", "Serial Port", CONFIG_SELECTION, "", 0, "", { 0 }, { - { - "COM1", 0 - }, - { - "COM2", 1 - }, - { - "" - } - } + .name = "port", + .description = "Serial Port", + .type = CONFIG_SELECTION, + .default_string = "", + .default_int = 0, + .file_filter = "", + .spinner = { 0 }, + .selection = { + { .description = "COM1", .value = 0 }, + { .description = "COM2", .value = 1 }, + { .description = "COM3", .value = 2 }, + { .description = "COM4", .value = 3 }, + { .description = "" } + } }, { - "buttons", "Buttons", CONFIG_SELECTION, "", 2, "", { 0 }, { - { - "Two", 2 - }, - { - "Three", 3 - }, - { - "" - } - } + .name = "buttons", + .description = "Buttons", + .type = CONFIG_SELECTION, + .default_string = "", + .default_int = 2, + .file_filter = "", + .spinner = { 0 }, + .selection = { + { .description = "Two", .value = 2 }, + { .description = "Three", .value = 3 }, + { .description = "" } + } }, { - "", "", -1 - } + .name = "revision", + .description = "Revision", + .type = CONFIG_SELECTION, + .default_string = "", + .default_int = 3, + .file_filter = "", + .spinner = { 0 }, + .selection = { + { .description = "LOGIMOUSE R7 1.0", .value = 1 }, + { .description = "LOGIMOUSE R7 2.0", .value = 2 }, + { .description = "LOGIMOUSE C7 3.0", .value = 3 }, + { .description = "Logitech MouseMan", .value = 4 }, + { .description = "" } + } + }, + { + .name = "rts_toggle", + .description = "Microsoft-compatible RTS toggle", + .type = CONFIG_BINARY, + .default_string = "", + .default_int = 0 + }, + { .name = "", .description = "", .type = CONFIG_END } + // clang-format on }; - const device_t mouse_mssystems_device = { - "Mouse Systems Serial Mouse", - "mssystems", - 0, - MOUSE_TYPE_MSYSTEMS, - sermouse_init, sermouse_close, NULL, - { .poll = sermouse_poll }, sermouse_speed_changed, NULL, - mssermouse_config + .name = "Mouse Systems Serial Mouse", + .internal_name = "mssystems", + .flags = DEVICE_COM, + .local = MOUSE_TYPE_MSYSTEMS, + .init = sermouse_init, + .close = sermouse_close, + .reset = NULL, + { .poll = sermouse_poll }, + .speed_changed = sermouse_speed_changed, + .force_redraw = NULL, + .config = msssermouse_config }; const device_t mouse_msserial_device = { - "Microsoft Serial Mouse", - "msserial", - 0, - 0, - sermouse_init, sermouse_close, NULL, - { .poll = sermouse_poll }, sermouse_speed_changed, NULL, - mssermouse_config + .name = "Microsoft Serial Mouse", + .internal_name = "msserial", + .flags = DEVICE_COM, + .local = 0, + .init = sermouse_init, + .close = sermouse_close, + .reset = NULL, + { .poll = sermouse_poll }, + .speed_changed = sermouse_speed_changed, + .force_redraw = NULL, + .config = mssermouse_config }; const device_t mouse_ltserial_device = { - "Logitech Serial Mouse", - "ltserial", - 0, - 1, - sermouse_init, sermouse_close, NULL, - { .poll = sermouse_poll }, sermouse_speed_changed, NULL, - ltsermouse_config + .name = "Logitech Serial Mouse", + .internal_name = "ltserial", + .flags = DEVICE_COM, + .local = 1, + .init = sermouse_init, + .close = sermouse_close, + .reset = NULL, + { .poll = sermouse_poll }, + .speed_changed = sermouse_speed_changed, + .force_redraw = NULL, + .config = ltsermouse_config }; diff --git a/src/device/mouse_wacom_tablet.c b/src/device/mouse_wacom_tablet.c new file mode 100644 index 000000000..d299d8bab --- /dev/null +++ b/src/device/mouse_wacom_tablet.c @@ -0,0 +1,741 @@ +#include +#include +#include +#include +#include +#include <86box/86box.h> +#include <86box/device.h> +#include <86box/timer.h> +#include <86box/mouse.h> +#include <86box/serial.h> +#include <86box/plat.h> +#include <86box/fifo8.h> + +#define FLAG_3BTN 0x20 /* enable 3-button mode */ + +enum wacom_modes { + WACOM_MODE_SUPPRESSED = 0, + WACOM_MODE_POINT = 1, + WACOM_MODE_STREAM = 2, + WACOM_MODE_SWITCH = 3, +}; + +enum wacom_handshake_modes { + WACOM_HANDSHAKE_NONE = 0, + WACOM_HANDSHAKE_CTS = 1, + WACOM_HANDSHAKE_DTS = 2, + WACOM_HANDSHAKE_BOTH = 3, +}; + +enum wacom_cmd_set { + WACOM_CMDSET_BITPAD = 0, + WACOM_CMDSET_MM1201 = 1, + WACOM_CMDSET_IIS = 2, + WACOM_CMDSET_IV = 3 +}; + +enum wacom_tablet_type { + WACOM_TYPE_IISONLY = 0, + WACOM_TYPE_IV, +}; + +enum { + REPORT_PHASE_PREPARE, + REPORT_PHASE_TRANSMIT +}; + +typedef struct wacom_tablet_id { + char id[64]; + int type; +} wacom_tablet_id; + +static const wacom_tablet_id sd510_id = { + .id = "~#SD51C V3.2.1.01\r", + .type = WACOM_TYPE_IISONLY +}; + +static const wacom_tablet_id artpad_id = { + .id = "~#KT-0405-R00 V1.1-0\r", + .type = WACOM_TYPE_IV +}; + +static const uint32_t wacom_resolution_values[4] = { + 500, + 508, + 1000, + 1270 +}; + +typedef struct mouse_wacom_t { + const char *name; /* name of this device */ + int8_t type; /* type of this device */ + int8_t port; + uint8_t flags; /* device flags */ + uint8_t but; + uint8_t status; + uint8_t bits; + uint8_t data_rec[0x200]; + int abs_x; + int abs_y; + int rel_x; + int rel_y; + int oldb; + int b; + + Fifo8 data; + + int data_rec_pos; + int mode; + int interval; + int increment; + int suppressed_increment; + int transmission_stopped; + int reset; + int transmit_id; + int transmit_id_pending; + int pressure_mode; + int suppressed; + int measurement; + int remote_req; + + uint32_t x_res; + uint32_t y_res; + const wacom_tablet_id *tablet_type; + + int last_abs_x; /* Suppressed/Increment Mode. */ + int last_abs_y; /* Suppressed/Increment Mode. */ + union { + uint32_t settings; /* Settings DWORD */ + /* We don't target any architectures except x86/x64/ARM32/ARM64. + (The ABIs for those are explicit in little-endian bit ordering) */ + struct settings_bits { + uint8_t remote_mode : 1; + uint8_t bitpad_two_cursor_data : 1; + uint8_t mm961_orientation : 1; + uint8_t mm_command_set : 1; + uint8_t tilt : 1; + uint8_t multi_device : 1; + uint8_t reading_height : 1; + uint8_t pressure_sensitivity : 1; + + uint8_t pnp : 1; /* Unused. */ + uint8_t dummy : 1; + uint8_t terminator : 2; + uint8_t out_of_range_data : 1; + uint8_t origin_location : 1; + uint8_t resolution : 2; + + uint8_t transfer_rate : 2; + uint8_t coord_sys : 1; + uint8_t output_format : 1; + uint8_t transfer_mode : 2; + uint8_t handshake : 2; + + uint8_t stop_bits_conf : 1; + uint8_t data_bits_conf : 1; + uint8_t parity : 2; + uint8_t baud_rate : 2; + uint8_t cmd_set : 2; + } settings_bits; + }; + + double transmit_period; + double old_tsc; + double reset_tsc; + pc_timer_t report_timer; + + serial_t *serial; +} mouse_wacom_t; + +/* TODO: What is this needed for? */ +#if 0 +static unsigned int +reverse(register unsigned int x) +{ + x = (((x & 0xaaaaaaaa) >> 1) | ((x & 0x55555555) << 1)); + x = (((x & 0xcccccccc) >> 2) | ((x & 0x33333333) << 2)); + x = (((x & 0xf0f0f0f0) >> 4) | ((x & 0x0f0f0f0f) << 4)); + x = (((x & 0xff00ff00) >> 8) | ((x & 0x00ff00ff) << 8)); + return ((x >> 16) | (x << 16)); +} +#endif + +static double +wacom_transmit_period(mouse_wacom_t *dev, int bps, int rps) +{ + double dbps = (double) bps; + double temp = 0.0; + int word_len = dev->bits; + + if (rps == -1) + temp = (double) word_len; + else { + temp = (double) rps; + temp = (9600.0 - (temp * 33.0)); + temp /= rps; + } + temp = (1000000.0 / dbps) * temp; + + return temp; +} + +static void +wacom_process_settings_dword(mouse_wacom_t *wacom, uint32_t dword) +{ + wacom->settings = dword; + + wacom->mode = wacom->settings_bits.transfer_mode; + + wacom->bits = 1 + 7 + wacom->settings_bits.data_bits_conf; + wacom->bits += 1 + wacom->settings_bits.stop_bits_conf; + if (wacom->settings_bits.parity == 2 && !(wacom->bits % 2)) { + wacom->bits++; + } else if (wacom->settings_bits.parity == 3 && (wacom->bits % 2)) { + wacom->bits++; + } + + switch(wacom->settings_bits.baud_rate) { + case 0: + wacom->transmit_period = wacom_transmit_period(wacom, 2400, -1); + break; + + case 1: + wacom->transmit_period = wacom_transmit_period(wacom, 4800, -1); + break; + + case 2: + wacom->transmit_period = wacom_transmit_period(wacom, 9600, -1); + break; + + case 3: + wacom->transmit_period = wacom_transmit_period(wacom, 19200, -1); + break; + + default: + break; + } + + mouse_input_mode = !wacom->settings_bits.coord_sys; + wacom->x_res = wacom->y_res = wacom_resolution_values[wacom->settings_bits.resolution]; +} + +static void +wacom_reset(mouse_wacom_t *wacom) +{ + wacom->transmit_period = wacom_transmit_period(wacom, 9600, -1); + wacom->mode = WACOM_MODE_POINT; + wacom->transmission_stopped = 0; + wacom->interval = 0; + wacom->transmit_id = 0; + wacom->settings_bits.output_format = 1; /* ASCII */ + wacom->settings_bits.cmd_set = 1; + wacom->measurement = 1; + wacom->increment = wacom->suppressed_increment = 0; + wacom->reset_tsc = tsc; + wacom->settings_bits.remote_mode = wacom->remote_req = 0; + wacom->settings_bits.out_of_range_data = 0; + + mouse_input_mode = 1; + wacom_process_settings_dword(wacom, 0xA21BC800); +} + +static void +wacom_reset_artpad(mouse_wacom_t *wacom) +{ + wacom->transmit_period = wacom_transmit_period(wacom, 9600, -1); + wacom->mode = WACOM_MODE_SUPPRESSED; + wacom->transmission_stopped = 0; + wacom->interval = 0; + wacom->transmit_id = 0; + wacom->settings_bits.output_format = 0; /* Binary */ + wacom->measurement = 1; + wacom->increment = 0; + wacom->suppressed_increment = 1; + wacom->reset_tsc = tsc; + wacom->settings_bits.remote_mode = 0; + wacom->remote_req = 0; + wacom->settings_bits.out_of_range_data = 0; + + wacom_process_settings_dword(wacom, 0xE203C000); + mouse_input_mode = 1; +} + +static void +wacom_callback(UNUSED(struct serial_s *serial), void *priv) +{ + mouse_wacom_t *wacom = (mouse_wacom_t *) priv; + + switch(wacom->settings_bits.baud_rate) { + case 0: + wacom->transmit_period = wacom_transmit_period(wacom, 2400, -1); + break; + + case 1: + wacom->transmit_period = wacom_transmit_period(wacom, 4800, -1); + break; + + case 2: + wacom->transmit_period = wacom_transmit_period(wacom, 9600, -1); + break; + + case 3: + wacom->transmit_period = wacom_transmit_period(wacom, 19200, -1); + break; + + default: + break; + } + timer_stop(&wacom->report_timer); + timer_on_auto(&wacom->report_timer, wacom->transmit_period); +} + +static void +wacom_write(UNUSED(struct serial_s *serial), void *priv, uint8_t data) +{ + mouse_wacom_t *wacom = (mouse_wacom_t *) priv; + static int special_command = 0; + + if (data == '~') { + special_command = 1; + return; + } + if (special_command) { + switch (data) { + case '#': + { + wacom->transmit_id = 1; + break; + } + case 'C': + case '*': + case 'R': + { + wacom->data_rec[wacom->data_rec_pos++] = '~'; + wacom->data_rec[wacom->data_rec_pos++] = data; + break; + } + default: + break; + } + special_command = 0; + return; + } + + if (data == '@') { + wacom->remote_req = 1; + wacom->settings_bits.remote_mode = 1; + return; + } + if (data == '#' && wacom->tablet_type->type == WACOM_TYPE_IV) { + wacom_reset_artpad(wacom); + return; + } + if (data == '$') { + wacom_reset(wacom); + return; + } + if (data == 0x13) { + wacom->transmission_stopped = 1; + return; + } + if (data == 0x11) { + wacom->transmission_stopped = 0; + wacom->settings_bits.remote_mode = wacom->remote_req = 0; + return; + } + wacom->data_rec[wacom->data_rec_pos++] = data; + if (data == '\r' || data == '\n') { + wacom->data_rec[wacom->data_rec_pos] = 0; + wacom->data_rec_pos = 0; + + if (data == '\n') + pclog("Wacom: written %s", wacom->data_rec); + else + pclog("Wacom: written %s\n", wacom->data_rec); + if (!memcmp(wacom->data_rec, "AS", 2) && wacom->settings_bits.cmd_set == WACOM_CMDSET_IIS) { + wacom->settings_bits.output_format = !(wacom->data_rec[2] == '1'); + } else if (!memcmp(wacom->data_rec, "SR", 2)) { + wacom->mode = WACOM_MODE_STREAM; + } else if (!memcmp(wacom->data_rec, "IN", 2)) { + sscanf((const char *) wacom->data_rec, "IN%d", &wacom->increment); + } else if (!memcmp(wacom->data_rec, "RE", 2)) { + if (wacom->tablet_type->type == WACOM_TYPE_IV) wacom_reset_artpad(wacom); + else wacom_reset(wacom); + } else if (!memcmp(wacom->data_rec, "IT", 2)) { + sscanf((const char *) wacom->data_rec, "IT%d", &wacom->interval); + } else if (!memcmp(wacom->data_rec, "DE", 2) && wacom->settings_bits.cmd_set == WACOM_CMDSET_IIS) { + sscanf((const char *) wacom->data_rec, "DE%d", &mouse_input_mode); + mouse_input_mode = !mouse_input_mode; + plat_mouse_capture(0); + } else if (!memcmp(wacom->data_rec, "SU", 2)) { + sscanf((const char *) wacom->data_rec, "SU%d", &wacom->suppressed_increment); + wacom->settings_bits.transfer_mode = wacom->mode = WACOM_MODE_SUPPRESSED; + } else if (!memcmp(wacom->data_rec, "PH", 2) && wacom->settings_bits.cmd_set == WACOM_CMDSET_IIS) { + sscanf((const char *) wacom->data_rec, "PH%d", &wacom->pressure_mode); + } else if (!memcmp(wacom->data_rec, "IC", 2)) { + sscanf((const char *) wacom->data_rec, "IC%d", &wacom->measurement); + } else if (!memcmp(wacom->data_rec, "SW", 2)) { + wacom->mode = WACOM_MODE_SWITCH; + } else if (!memcmp(wacom->data_rec, "AL", 2)) { + uint8_t out_of_range_data = wacom->settings_bits.out_of_range_data; + wacom->settings_bits.out_of_range_data = !!out_of_range_data; + } else if (!memcmp(wacom->data_rec, "RQ", 2)) { + int remote_mode = 0; + sscanf((const char *) wacom->data_rec, "RQ%d", &remote_mode); + wacom->settings_bits.remote_mode = !!remote_mode; + if (wacom->settings_bits.remote_mode) + wacom->remote_req = 1; + } else if (!memcmp(wacom->data_rec, "SP", 2)) { + wacom->transmission_stopped = 1; + } else if (!memcmp(wacom->data_rec, "ST", 2)) { + wacom->transmission_stopped = 0; + wacom->settings_bits.remote_mode = wacom->remote_req = 0; + } else if (!memcmp(wacom->data_rec, "NR", 2)) { + sscanf((const char *) wacom->data_rec, "NR%d", &wacom->x_res); + wacom->y_res = wacom->x_res; + } else if (wacom->tablet_type->type == WACOM_TYPE_IV && wacom->data_rec[0] == '~') { + if (!memcmp(wacom->data_rec, "~*", 2)) { + uint32_t settings_dword = wacom->settings; + if (strstr((const char *) wacom->data_rec, ",")) { + uint32_t x_res = wacom->x_res; + uint32_t y_res = wacom->y_res; + uint32_t increment = wacom->increment; + uint32_t interval = wacom->interval; + + sscanf((const char *) wacom->data_rec, "~*%08X,%d,%d,%d,%d", &settings_dword, &increment, &interval, &x_res, &y_res); + + wacom->interval = interval; + wacom->increment = increment; + wacom->x_res = x_res; + wacom->y_res = y_res; + } else { + sscanf((const char *) wacom->data_rec, "~*%X", &settings_dword); + } + wacom_process_settings_dword(wacom, settings_dword); + } else if (!memcmp(wacom->data_rec, "~C", 2)) { + fifo8_push_all(&wacom->data, (const uint8_t *) "~C5039,3779\r", sizeof("~C5039,3779\r") - 1); + } else if (!memcmp(wacom->data_rec, "~R", 2)) { + uint8_t data[256] = { 0 }; + snprintf((char *)data, sizeof(data), (const char *) "~*%08X,%d,%d,%d,%d\r", wacom->settings, wacom->increment, wacom->interval, wacom->x_res, wacom->y_res); + fifo8_push_all(&wacom->data, data, strlen((const char *) data)); + } + } + } +} + +static int +wacom_poll(void *priv) +{ + mouse_wacom_t *wacom = (mouse_wacom_t *) priv; + int delta_x; + int delta_y; + int b = mouse_get_buttons_ex(); + double abs_x; + double abs_y; + + mouse_subtract_coords(&delta_x, &delta_y, NULL, NULL, -32768, 32767, 0, 0); + mouse_get_abs_coords(&abs_x, &abs_y); + + if (wacom->settings_bits.cmd_set == WACOM_CMDSET_IV) { + wacom->abs_x = abs_x * 5039. * (wacom->x_res / 1000.); + wacom->abs_y = abs_y * 3779. * (wacom->y_res / 1000.); + } else { + wacom->abs_x = abs_x * (wacom->measurement ? 4566. : 5800.); + wacom->abs_y = abs_y * (wacom->measurement ? 2972. : 3774.); + if (wacom->abs_x > (wacom->measurement ? 4566 : 5800)) + wacom->abs_x = (wacom->measurement ? 4566 : 5800); + if (wacom->abs_y > (wacom->measurement ? 2972 : 3774)) + wacom->abs_x = (wacom->measurement ? 2972 : 3774); + if (wacom->abs_x < 0) + wacom->abs_x = 0; + if (wacom->abs_y < 0) + wacom->abs_y = 0; + wacom->rel_x = delta_x; + wacom->rel_y = delta_y; + } + if (wacom->b != b) + wacom->oldb = wacom->b; + wacom->b = b; + return 0; +} + +static int +wacom_switch_off_to_on(int b, int oldb) +{ + if (!(oldb & 0x1) && (b & 1)) + return 1; + if (!(oldb & 0x2) && (b & 2)) + return 1; + if (!(oldb & 0x4) && (b & 4)) + return 1; + + return 0; +} + +static uint8_t +wacom_get_switch(int b) +{ + if (b & 0x4) + return 0x23; + if (b & 0x2) + return 0x22; + if (b & 0x1) + return 0x21; + + return 0x00; +} + +static void +wacom_transmit_prepare(mouse_wacom_t *wacom, int x, int y) +{ + if (wacom->transmit_id) { + uint8_t data[128] = { 0 }; + snprintf((char *) data, sizeof(data), "%s", wacom->tablet_type->id); + fifo8_push_all(&wacom->data, data, strlen((char *)data)); + wacom->transmit_id = 0; + return; + } + wacom->last_abs_x = wacom->abs_x; + wacom->last_abs_y = wacom->abs_y; + wacom->remote_req = 0; + + wacom->oldb = wacom->b; + if (wacom->settings_bits.output_format == 0) { + uint8_t data[7]; + data[0] = 0xC0; + if (wacom->settings_bits.cmd_set == WACOM_CMDSET_IV) { + if (tablet_tool_type == 0) + data[6] = ((wacom->b & 0x1) ? (uint8_t) 31 : (uint8_t) -1); + else + data[6] = ((wacom->b & 0x1) ? (uint8_t) 63 : (uint8_t) -63); + } + else + data[6] = (wacom->pressure_mode || wacom->settings_bits.cmd_set == WACOM_CMDSET_IV) ? ((wacom->b & 0x1) ? (uint8_t) 31 : (uint8_t) -31) : wacom_get_switch(wacom->b); + + data[5] = (y & 0x7F); + data[4] = ((y & 0x3F80) >> 7) & 0x7F; + data[3] = (((y & 0xC000) >> 14) & 3); + + data[2] = (x & 0x7F); + data[1] = ((x & 0x3F80) >> 7) & 0x7F; + data[0] |= (((x & 0xC000) >> 14) & 3); + + if (mouse_input_mode == 0 && wacom->settings_bits.cmd_set == WACOM_CMDSET_IIS) { + data[0] |= (!!(x < 0)) << 2; + data[3] |= (!!(y < 0)) << 2; + } + + if (wacom->settings_bits.cmd_set == WACOM_CMDSET_IV) { + data[6] &= 0x7F; + data[3] &= 0x3; + if (wacom_get_switch(wacom->b) != 0x21) { + data[3] |= (wacom_get_switch(wacom->b) & 0xF) << 3; + data[0] |= 0x8; + } + } + + if (wacom->pressure_mode && wacom->settings_bits.cmd_set == WACOM_CMDSET_IIS) { + data[0] |= 0x10; + data[6] &= 0x7F; + } + + if (tablet_tool_type == 1) { + data[0] |= 0x20; + } + + if (!mouse_tablet_in_proximity) { + data[0] &= ~0x40; + } + fifo8_push_all(&wacom->data, data, 7); + } else { + uint8_t data[128]; + data[0] = 0; + snprintf((char *) data, sizeof(data), "*,%05d,%05d,%d\r\n", + wacom->abs_x, wacom->abs_y, + wacom->pressure_mode ? ((wacom->b & 0x1) ? (uint8_t) -31 : (uint8_t) 15) : ((wacom->b & 0x1) ? 21 : 00)); + fifo8_push_all(&wacom->data, data, strlen((char *)data)); + } +} + +extern double cpuclock; +static void +wacom_report_timer(void *priv) +{ + mouse_wacom_t *wacom = (mouse_wacom_t *) priv; + double milisecond_diff = ((double) (tsc - wacom->old_tsc)) / cpuclock * 1000.0; + int relative_mode = (mouse_input_mode == 0); + int x = (relative_mode ? wacom->rel_x : wacom->abs_x); + int y = (relative_mode ? wacom->rel_y : wacom->abs_y); + int x_diff = abs(relative_mode ? wacom->rel_x : (wacom->abs_x - wacom->last_abs_x)); + int y_diff = abs(relative_mode ? wacom->rel_y : (wacom->abs_y - wacom->last_abs_y)); + int increment = wacom->suppressed_increment ? wacom->suppressed_increment : wacom->increment; + + timer_on_auto(&wacom->report_timer, wacom->transmit_period); + if ((((double) (tsc - wacom->reset_tsc)) / cpuclock * 1000.0) <= 10) + return; + if (wacom->transmit_id) + goto transmit_prepare; + if (fifo8_num_used(&wacom->data)) + goto transmit; + else if (wacom->settings_bits.remote_mode && !wacom->remote_req) + return; + else { + if (wacom->settings_bits.remote_mode && wacom->remote_req) { + goto transmit_prepare; + } + if (wacom->transmission_stopped || (!mouse_tablet_in_proximity && !wacom->settings_bits.out_of_range_data)) + return; + + if (milisecond_diff >= (wacom->interval * 5)) { + wacom->old_tsc = tsc; + } else + return; + + switch (wacom->mode) { + default: + case WACOM_MODE_STREAM: + break; + + case WACOM_MODE_POINT: + { + if (wacom->suppressed_increment) + break; + if (!(wacom_switch_off_to_on(wacom->b, wacom->oldb))) + return; + break; + } + + case WACOM_MODE_SWITCH: + { + if (!wacom->b) + return; + + break; + } + } + + if (increment && !mouse_tablet_in_proximity) + return; + + if (increment && !(x_diff > increment || y_diff > increment)) { + if (wacom->suppressed_increment && (wacom->b == wacom->oldb)) + return; + + if (wacom->increment && !wacom_switch_off_to_on(wacom->b, wacom->oldb)) + return; + } + } + +transmit_prepare: + wacom_transmit_prepare(wacom, x, y); + +transmit: + serial_write_fifo(wacom->serial, fifo8_pop(&wacom->data)); + if (fifo8_num_used(&wacom->data) == 0) { + wacom->old_tsc = tsc; + } + return; +} + +static void * +wacom_init(const device_t *info) +{ + mouse_wacom_t *dev; + + dev = (mouse_wacom_t *) calloc(1, sizeof(mouse_wacom_t)); + dev->name = info->name; + dev->but = 3; + dev->bits = 10; + if (info->local == 0) { + dev->tablet_type = &sd510_id; + } else + dev->tablet_type = (wacom_tablet_id*)info->local; + + fifo8_create(&dev->data, 512); + + dev->port = device_get_config_int("port"); + + dev->serial = serial_attach(dev->port, wacom_callback, wacom_write, dev); + timer_add(&dev->report_timer, wacom_report_timer, dev, 0); + mouse_set_buttons(dev->but); + + if (dev->tablet_type->type == WACOM_TYPE_IV) { + wacom_reset_artpad(dev); + wacom_process_settings_dword(dev, 0xE2018000); + } + else wacom_reset(dev); + + return dev; +} + +static void +wacom_speed_changed(void *priv) +{ + mouse_wacom_t *dev = (mouse_wacom_t *) priv; + + wacom_callback(dev->serial, dev); +} + +static void +wacom_close(void *priv) +{ + mouse_wacom_t *dev = (mouse_wacom_t *) priv; + + fifo8_destroy(&dev->data); + + /* Detach serial port from the mouse. */ + if (dev && dev->serial && dev->serial->sd) + memset(dev->serial->sd, 0, sizeof(serial_device_t)); + + free(dev); +} + +static const device_config_t wacom_config[] = { + // clang-format off + { + .name = "port", + .description = "Serial Port", + .type = CONFIG_SELECTION, + .default_string = "", + .default_int = 0, + .file_filter = "", + .spinner = { 0 }, + .selection = { + { .description = "COM1", .value = 0 }, + { .description = "COM2", .value = 1 }, + { .description = "COM3", .value = 2 }, + { .description = "COM4", .value = 3 }, + { .description = "" } + } + }, + { .name = "", .description = "", .type = CONFIG_END } + // clang-format on +}; + +const device_t mouse_wacom_device = { + .name = "Wacom SD-510C", + .internal_name = "wacom_serial", + .flags = DEVICE_COM, + .local = 0, + .init = wacom_init, + .close = wacom_close, + .reset = NULL, + { .poll = wacom_poll }, + .speed_changed = wacom_speed_changed, + .force_redraw = NULL, + .config = wacom_config +}; + +const device_t mouse_wacom_artpad_device = { + .name = "Wacom ArtPad", + .internal_name = "wacom_serial_artpad", + .flags = DEVICE_COM, + .local = (uintptr_t)&artpad_id, + .init = wacom_init, + .close = wacom_close, + .reset = NULL, + { .poll = wacom_poll }, + .speed_changed = wacom_speed_changed, + .force_redraw = NULL, + .config = wacom_config +}; diff --git a/src/device/pci_bridge.c b/src/device/pci_bridge.c index 5cb13a1f5..8183f8afa 100644 --- a/src/device/pci_bridge.c +++ b/src/device/pci_bridge.c @@ -1,18 +1,18 @@ /* - * 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. + * 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. + * This file is part of the 86Box distribution. * - * Implementation of PCI-PCI and host-AGP bridges. + * Implementation of PCI-PCI and host-AGP bridges. * * * - * Authors: RichardG, + * Authors: RichardG, * - * Copyright 2020 RichardG. + * Copyright 2020 RichardG. */ #include @@ -31,55 +31,50 @@ #include <86box/device.h> #include <86box/pci.h> +#define PCI_BRIDGE_DEC_21150 0x10110022 +#define AGP_BRIDGE_ALI_M5243 0x10b95243 +#define AGP_BRIDGE_ALI_M5247 0x10b95247 +#define AGP_BRIDGE_INTEL_440LX 0x80867181 +#define AGP_BRIDGE_INTEL_440BX 0x80867191 +#define AGP_BRIDGE_INTEL_440GX 0x808671a1 +#define AGP_BRIDGE_VIA_597 0x11068597 +#define AGP_BRIDGE_VIA_598 0x11068598 +#define AGP_BRIDGE_VIA_691 0x11068691 +#define AGP_BRIDGE_VIA_8601 0x11068601 -#define PCI_BRIDGE_DEC_21150 0x10110022 -#define AGP_BRIDGE_ALI_M5243 0x10b95243 -#define AGP_BRIDGE_ALI_M5247 0x10b95247 -#define AGP_BRIDGE_INTEL_440LX 0x80867181 -#define AGP_BRIDGE_INTEL_440BX 0x80867191 -#define AGP_BRIDGE_INTEL_440GX 0x808671a1 -#define AGP_BRIDGE_VIA_597 0x11068597 -#define AGP_BRIDGE_VIA_598 0x11068598 -#define AGP_BRIDGE_VIA_691 0x11068691 -#define AGP_BRIDGE_VIA_8601 0x11068601 +#define AGP_BRIDGE_ALI(x) (((x) >> 16) == 0x10b9) +#define AGP_BRIDGE_INTEL(x) (((x) >> 16) == 0x8086) +#define AGP_BRIDGE_VIA(x) (((x) >> 16) == 0x1106) +#define AGP_BRIDGE(x) ((x) >= AGP_BRIDGE_ALI_M5243) -#define AGP_BRIDGE_ALI(x) (((x) >> 16) == 0x10b9) -#define AGP_BRIDGE_INTEL(x) (((x) >> 16) == 0x8086) -#define AGP_BRIDGE_VIA(x) (((x) >> 16) == 0x1106) -#define AGP_BRIDGE(x) ((x) >= AGP_BRIDGE_ALI_M5243) +typedef struct pci_bridge_t { + uint32_t local; + uint8_t type; + uint8_t ctl; - -typedef struct -{ - uint32_t local; - uint8_t type, ctl; - - uint8_t regs[256]; - uint8_t bus_index; - int slot; + uint8_t regs[256]; + uint8_t bus_index; + uint8_t slot; } pci_bridge_t; - #ifdef ENABLE_PCI_BRIDGE_LOG int pci_bridge_do_log = ENABLE_PCI_BRIDGE_LOG; - static void pci_bridge_log(const char *fmt, ...) { va_list ap; if (pci_bridge_do_log) { - va_start(ap, fmt); - pclog_ex(fmt, ap); - va_end(ap); + va_start(ap, fmt); + pclog_ex(fmt, ap); + va_end(ap); } } #else -#define pci_bridge_log(fmt, ...) +# define pci_bridge_log(fmt, ...) #endif - void pci_bridge_set_ctl(void *priv, uint8_t ctl) { @@ -88,7 +83,6 @@ pci_bridge_set_ctl(void *priv, uint8_t ctl) dev->ctl = ctl; } - static void pci_bridge_write(int func, int addr, uint8_t val, void *priv) { @@ -97,266 +91,290 @@ pci_bridge_write(int func, int addr, uint8_t val, void *priv) pci_bridge_log("PCI Bridge %d: write(%d, %02X, %02X)\n", dev->bus_index, func, addr, val); if (func > 0) - return; + return; if ((dev->local == AGP_BRIDGE_ALI_M5247) && (addr >= 0x40)) - return; + return; switch (addr) { - case 0x00: case 0x01: case 0x02: case 0x03: - case 0x06: case 0x08: case 0x09: case 0x0a: - case 0x0b: case 0x0e: case 0x0f: case 0x10: - case 0x11: case 0x12: case 0x13: case 0x14: - case 0x15: case 0x16: case 0x17: case 0x1e: - case 0x34: case 0x3d: case 0x67: case 0xdc: - case 0xdd: case 0xde: case 0xdf: - return; + case 0x00: + case 0x01: + case 0x02: + case 0x03: + case 0x06: + case 0x08: + case 0x09: + case 0x0a: + case 0x0b: + case 0x0e: + case 0x0f: + case 0x10: + case 0x11: + case 0x12: + case 0x13: + case 0x14: + case 0x15: + case 0x16: + case 0x17: + case 0x1e: + case 0x34: + case 0x3d: + case 0x67: + case 0xdc: + case 0xdd: + case 0xde: + case 0xdf: + return; - case 0x04: - if (AGP_BRIDGE_INTEL(dev->local)) { - if (dev->local == AGP_BRIDGE_INTEL_440BX) - val &= 0x1f; - } else if (dev->local == AGP_BRIDGE_ALI_M5243) - val |= 0x02; - else if (dev->local == AGP_BRIDGE_ALI_M5247) - val &= 0xc3; - else - val &= 0x67; - break; + case 0x04: + if (AGP_BRIDGE_INTEL(dev->local)) { + if (dev->local == AGP_BRIDGE_INTEL_440BX) + val &= 0x1f; + } else if (dev->local == AGP_BRIDGE_ALI_M5243) + val |= 0x02; + else if (dev->local == AGP_BRIDGE_ALI_M5247) + val &= 0xc3; + else + val &= 0x67; + break; - case 0x05: - if (AGP_BRIDGE_INTEL(dev->local)) - val &= 0x01; - else if (AGP_BRIDGE_ALI(dev->local)) - val &= 0x01; - else - val &= 0x03; - break; + case 0x05: + if (AGP_BRIDGE_INTEL(dev->local)) + val &= 0x01; + else if (AGP_BRIDGE_ALI(dev->local)) + val &= 0x01; + else + val &= 0x03; + break; - case 0x07: - if (dev->local == AGP_BRIDGE_INTEL_440LX) - dev->regs[addr] &= ~(val & 0x40); - else if (dev->local == AGP_BRIDGE_ALI_M5243) - dev->regs[addr] &= ~(val & 0xf8); - else if (dev->local == AGP_BRIDGE_ALI_M5247) - dev->regs[addr] &= ~(val & 0xc0); - return; + case 0x07: + if (dev->local == AGP_BRIDGE_INTEL_440LX) + dev->regs[addr] &= ~(val & 0x40); + else if (dev->local == AGP_BRIDGE_ALI_M5243) + dev->regs[addr] &= ~(val & 0xf8); + else if (dev->local == AGP_BRIDGE_ALI_M5247) + dev->regs[addr] &= ~(val & 0xc0); + return; - case 0x0c: case 0x18: - /* Parent bus number (0x18) is always 0 on AGP bridges. */ - if (AGP_BRIDGE(dev->local)) - return; - break; + case 0x0c: + case 0x18: + /* Parent bus number (0x18) is always 0 on AGP bridges. */ + if (AGP_BRIDGE(dev->local)) + return; + break; - case 0x0d: - if (AGP_BRIDGE_VIA(dev->local)) - return; - else if (AGP_BRIDGE_INTEL(dev->local)) - val &= 0xf8; - else if (AGP_BRIDGE_ALI(dev->local)) - val &= 0xf8; - break; + case 0x0d: + if (AGP_BRIDGE_VIA(dev->local)) + return; + else if (AGP_BRIDGE_INTEL(dev->local)) + val &= 0xf8; + else if (AGP_BRIDGE_ALI(dev->local)) + val &= 0xf8; + break; - case 0x19: - /* Set our bus number. */ - pci_bridge_log("PCI Bridge %d: remapping from bus %02X to %02X\n", dev->bus_index, dev->regs[addr], val); - pci_remap_bus(dev->bus_index, val); - break; + case 0x19: + /* Set our bus number. */ + pci_bridge_log("PCI Bridge %d: remapping from bus %02X to %02X\n", dev->bus_index, dev->regs[addr], val); + pci_remap_bus(dev->bus_index, val); + break; - case 0x1f: - if (AGP_BRIDGE_INTEL(dev->local)) { - if (dev->local == AGP_BRIDGE_INTEL_440LX) - dev->regs[addr] &= ~(val & 0xf1); - else if ((dev->local == AGP_BRIDGE_INTEL_440BX) || - (dev->local == AGP_BRIDGE_INTEL_440GX)) - dev->regs[addr] &= ~(val & 0xf0); - } else if (AGP_BRIDGE_ALI(dev->local)) - dev->regs[addr] &= ~(val & 0xf0); - return; + case 0x1f: + if (AGP_BRIDGE_INTEL(dev->local)) { + if (dev->local == AGP_BRIDGE_INTEL_440LX) + dev->regs[addr] &= ~(val & 0xf1); + else if ((dev->local == AGP_BRIDGE_INTEL_440BX) || (dev->local == AGP_BRIDGE_INTEL_440GX)) + dev->regs[addr] &= ~(val & 0xf0); + } else if (AGP_BRIDGE_ALI(dev->local)) + dev->regs[addr] &= ~(val & 0xf0); + return; - case 0x1c: case 0x1d: case 0x20: case 0x22: - case 0x24: case 0x26: - val &= 0xf0; - break; + case 0x1c: + case 0x1d: + case 0x20: + case 0x22: + case 0x24: + case 0x26: + val &= 0xf0; + break; - case 0x3c: - if (!(dev->ctl & 0x80)) - return; - break; + case 0x3c: + if (!(dev->ctl & 0x80)) + return; + break; - case 0x3e: - if (AGP_BRIDGE_VIA(dev->local)) - val &= 0x0c; - else if (dev->local == AGP_BRIDGE_ALI_M5247) - val &= 0x0f; - else if (dev->local == AGP_BRIDGE_ALI_M5243) - return; - else if (AGP_BRIDGE(dev->local)) { - if ((dev->local == AGP_BRIDGE_INTEL_440BX) || - (dev->local == AGP_BRIDGE_INTEL_440GX)) - val &= 0xed; - else - val &= 0x0f; - } - else if (dev->local == PCI_BRIDGE_DEC_21150) - val &= 0xef; - break; + case 0x3e: + if (AGP_BRIDGE_VIA(dev->local)) + val &= 0x0c; + else if (dev->local == AGP_BRIDGE_ALI_M5247) + val &= 0x0f; + else if (dev->local == AGP_BRIDGE_ALI_M5243) + return; + else if (AGP_BRIDGE(dev->local)) { + if ((dev->local == AGP_BRIDGE_INTEL_440BX) || (dev->local == AGP_BRIDGE_INTEL_440GX)) + val &= 0xed; + else + val &= 0x0f; + } else if (dev->local == PCI_BRIDGE_DEC_21150) + val &= 0xef; + break; - case 0x3f: - if (dev->local == AGP_BRIDGE_INTEL_440LX) { - dev->regs[addr] = ((dev->regs[addr] & 0x04) | (val & 0x02)) & ~(val & 0x04); - return; - } else if (dev->local == AGP_BRIDGE_ALI_M5247) - return; - else if (dev->local == AGP_BRIDGE_ALI_M5243) - val &= 0x06; - else if (AGP_BRIDGE(dev->local)) - return; - else if (dev->local == PCI_BRIDGE_DEC_21150) - val &= 0x0f; - break; + case 0x3f: + if (dev->local == AGP_BRIDGE_INTEL_440LX) { + dev->regs[addr] = ((dev->regs[addr] & 0x04) | (val & 0x02)) & ~(val & 0x04); + return; + } else if (dev->local == AGP_BRIDGE_ALI_M5247) + return; + else if (dev->local == AGP_BRIDGE_ALI_M5243) + val &= 0x06; + else if (AGP_BRIDGE(dev->local)) + return; + else if (dev->local == PCI_BRIDGE_DEC_21150) + val &= 0x0f; + break; - case 0x40: - if (dev->local == PCI_BRIDGE_DEC_21150) - val &= 0x32; - break; + case 0x40: + if (dev->local == PCI_BRIDGE_DEC_21150) + val &= 0x32; + break; - case 0x41: - if (AGP_BRIDGE_VIA(dev->local)) - val &= 0x7e; - else if (dev->local == PCI_BRIDGE_DEC_21150) - val &= 0x07; - break; + case 0x41: + if (AGP_BRIDGE_VIA(dev->local)) + val &= 0x7e; + else if (dev->local == PCI_BRIDGE_DEC_21150) + val &= 0x07; + break; - case 0x42: - if (AGP_BRIDGE_VIA(dev->local)) - val &= 0xfe; - break; + case 0x42: + if (AGP_BRIDGE_VIA(dev->local)) + val &= 0xfe; + break; - case 0x43: - if (dev->local == PCI_BRIDGE_DEC_21150) - val &= 0x03; - break; + case 0x43: + if (dev->local == PCI_BRIDGE_DEC_21150) + val &= 0x03; + break; - case 0x64: - if (dev->local == PCI_BRIDGE_DEC_21150) - val &= 0x7e; - break; + case 0x64: + if (dev->local == PCI_BRIDGE_DEC_21150) + val &= 0x7e; + break; - case 0x69: - if (dev->local == PCI_BRIDGE_DEC_21150) - val &= 0x3f; - break; + case 0x69: + if (dev->local == PCI_BRIDGE_DEC_21150) + val &= 0x3f; + break; - case 0x86: - if (AGP_BRIDGE_ALI(dev->local)) - val &= 0x3f; - break; + case 0x86: + if (AGP_BRIDGE_ALI(dev->local)) + val &= 0x3f; + break; - case 0x87: - if (AGP_BRIDGE_ALI(dev->local)) - val &= 0x60; - break; + case 0x87: + if (AGP_BRIDGE_ALI(dev->local)) + val &= 0x60; + break; - case 0x88: - if (AGP_BRIDGE_ALI(dev->local)) - val &= 0x8c; - break; + case 0x88: + if (AGP_BRIDGE_ALI(dev->local)) + val &= 0x8c; + break; - case 0x8b: - if (AGP_BRIDGE_ALI(dev->local)) - val &= 0x0f; - break; + case 0x8b: + if (AGP_BRIDGE_ALI(dev->local)) + val &= 0x0f; + break; - case 0x8c: - if (AGP_BRIDGE_ALI(dev->local)) - val &= 0x83; - break; + case 0x8c: + if (AGP_BRIDGE_ALI(dev->local)) + val &= 0x83; + break; - case 0x8d: - if (AGP_BRIDGE_ALI(dev->local)) - return; - break; + case 0x8d: + if (AGP_BRIDGE_ALI(dev->local)) + return; + break; - case 0xe0: case 0xe1: - if (AGP_BRIDGE_ALI(dev->local)) { - if (!(dev->ctl & 0x20)) - return; - } else - return; - break; + case 0xe0: + case 0xe1: + if (AGP_BRIDGE_ALI(dev->local)) { + if (!(dev->ctl & 0x20)) + return; + } else + return; + break; - case 0xe2: - if (AGP_BRIDGE_ALI(dev->local)) { - if (dev->ctl & 0x20) - val &= 0x3f; - else - return; - } else - return; - break; - case 0xe3: - if (AGP_BRIDGE_ALI(dev->local)) { - if (dev->ctl & 0x20) - val &= 0xfe; - else - return; - } else - return; - break; + case 0xe2: + if (AGP_BRIDGE_ALI(dev->local)) { + if (dev->ctl & 0x20) + val &= 0x3f; + else + return; + } else + return; + break; + case 0xe3: + if (AGP_BRIDGE_ALI(dev->local)) { + if (dev->ctl & 0x20) + val &= 0xfe; + else + return; + } else + return; + break; - case 0xe4: - if (AGP_BRIDGE_ALI(dev->local)) { - if (dev->ctl & 0x20) - val &= 0x03; - else - return; - } - break; - case 0xe5: - if (AGP_BRIDGE_ALI(dev->local)) { - if (!(dev->ctl & 0x20)) - return; - } - break; + case 0xe4: + if (AGP_BRIDGE_ALI(dev->local)) { + if (dev->ctl & 0x20) + val &= 0x03; + else + return; + } + break; + case 0xe5: + if (AGP_BRIDGE_ALI(dev->local)) { + if (!(dev->ctl & 0x20)) + return; + } + break; - case 0xe6: - if (AGP_BRIDGE_ALI(dev->local)) { - if (dev->ctl & 0x20) - val &= 0xc0; - else - return; - } - break; + case 0xe6: + if (AGP_BRIDGE_ALI(dev->local)) { + if (dev->ctl & 0x20) + val &= 0xc0; + else + return; + } + break; - case 0xe7: - if (AGP_BRIDGE_ALI(dev->local)) { - if (!(dev->ctl & 0x20)) - return; - } - break; + case 0xe7: + if (AGP_BRIDGE_ALI(dev->local)) { + if (!(dev->ctl & 0x20)) + return; + } + break; + + default: + break; } dev->regs[addr] = val; } - static uint8_t pci_bridge_read(int func, int addr, void *priv) { - pci_bridge_t *dev = (pci_bridge_t *) priv; - uint8_t ret; + const pci_bridge_t *dev = (pci_bridge_t *) priv; + uint8_t ret; if (func > 0) - ret = 0xff; + ret = 0xff; else - ret = dev->regs[addr]; + ret = dev->regs[addr]; pci_bridge_log("PCI Bridge %d: read(%d, %02X) = %02X\n", dev->bus_index, func, addr, ret); return ret; } - static void pci_bridge_reset(void *priv) { @@ -374,51 +392,54 @@ pci_bridge_reset(void *priv) /* command and status */ switch (dev->local) { - case PCI_BRIDGE_DEC_21150: - dev->regs[0x06] = 0x80; - dev->regs[0x07] = 0x02; - break; + case PCI_BRIDGE_DEC_21150: + dev->regs[0x06] = 0x80; + dev->regs[0x07] = 0x02; + break; - case AGP_BRIDGE_ALI_M5243: - dev->regs[0x04] = 0x06; - dev->regs[0x07] = 0x04; - dev->regs[0x0d] = 0x20; - dev->regs[0x19] = 0x01; - dev->regs[0x1b] = 0x20; - dev->regs[0x34] = 0xe0; - dev->regs[0x89] = 0x20; - dev->regs[0x8a] = 0xa0; - dev->regs[0x8e] = 0x20; - dev->regs[0x8f] = 0x20; - dev->regs[0xe0] = 0x01; - pci_remap_bus(dev->bus_index, 0x01); - break; + case AGP_BRIDGE_ALI_M5243: + dev->regs[0x04] = 0x06; + dev->regs[0x07] = 0x04; + dev->regs[0x0d] = 0x20; + dev->regs[0x19] = 0x01; + dev->regs[0x1b] = 0x20; + dev->regs[0x34] = 0xe0; + dev->regs[0x89] = 0x20; + dev->regs[0x8a] = 0xa0; + dev->regs[0x8e] = 0x20; + dev->regs[0x8f] = 0x20; + dev->regs[0xe0] = 0x01; + pci_remap_bus(dev->bus_index, 0x01); + break; - case AGP_BRIDGE_ALI_M5247: - dev->regs[0x04] = 0x03; - dev->regs[0x08] = 0x01; - break; + case AGP_BRIDGE_ALI_M5247: + dev->regs[0x04] = 0x03; + dev->regs[0x08] = 0x01; + break; - case AGP_BRIDGE_INTEL_440LX: - dev->regs[0x06] = 0xa0; - dev->regs[0x07] = 0x02; - dev->regs[0x08] = 0x03; - break; + case AGP_BRIDGE_INTEL_440LX: + dev->regs[0x06] = 0xa0; + dev->regs[0x07] = 0x02; + dev->regs[0x08] = 0x03; + break; - case AGP_BRIDGE_INTEL_440BX: - case AGP_BRIDGE_INTEL_440GX: - dev->regs[0x06] = 0x20; - dev->regs[0x07] = dev->regs[0x08] = 0x02; - break; + case AGP_BRIDGE_INTEL_440BX: + case AGP_BRIDGE_INTEL_440GX: + dev->regs[0x06] = 0x20; + dev->regs[0x07] = dev->regs[0x08] = 0x02; + break; - case AGP_BRIDGE_VIA_597: - case AGP_BRIDGE_VIA_598: - case AGP_BRIDGE_VIA_691: - case AGP_BRIDGE_VIA_8601: - dev->regs[0x04] = 0x07; - dev->regs[0x06] = 0x20; - dev->regs[0x07] = 0x02; - break; + case AGP_BRIDGE_VIA_597: + case AGP_BRIDGE_VIA_598: + case AGP_BRIDGE_VIA_691: + case AGP_BRIDGE_VIA_8601: + dev->regs[0x04] = 0x07; + dev->regs[0x06] = 0x20; + dev->regs[0x07] = 0x02; + break; + + default: + break; } /* class */ @@ -428,225 +449,222 @@ pci_bridge_reset(void *priv) /* IO BARs */ if (AGP_BRIDGE(dev->local)) - dev->regs[0x1c] = 0xf0; + dev->regs[0x1c] = 0xf0; else - dev->regs[0x1c] = dev->regs[0x1d] = 0x01; + dev->regs[0x1c] = dev->regs[0x1d] = 0x01; if (dev->local == AGP_BRIDGE_ALI_M5247) - dev->regs[0x1e] = 0x20; + dev->regs[0x1e] = 0x20; else if (!AGP_BRIDGE_VIA(dev->local)) { - dev->regs[0x1e] = AGP_BRIDGE(dev->local) ? 0xa0 : 0x80; - dev->regs[0x1f] = 0x02; + dev->regs[0x1e] = AGP_BRIDGE(dev->local) ? 0xa0 : 0x80; + dev->regs[0x1f] = 0x02; } /* prefetchable memory limits */ if (AGP_BRIDGE(dev->local)) { - dev->regs[0x20] = dev->regs[0x24] = 0xf0; - dev->regs[0x21] = dev->regs[0x25] = 0xff; + dev->regs[0x20] = dev->regs[0x24] = 0xf0; + dev->regs[0x21] = dev->regs[0x25] = 0xff; } else { - dev->regs[0x24] = dev->regs[0x26] = 0x01; + dev->regs[0x24] = dev->regs[0x26] = 0x01; } /* power management */ if (dev->local == PCI_BRIDGE_DEC_21150) { - dev->regs[0x34] = 0xdc; - dev->regs[0x43] = 0x02; - dev->regs[0xdc] = dev->regs[0xde] = 0x01; + dev->regs[0x34] = 0xdc; + dev->regs[0x43] = 0x02; + dev->regs[0xdc] = dev->regs[0xde] = 0x01; } } - static void * pci_bridge_init(const device_t *info) { - uint8_t interrupts[4], interrupt_count, interrupt_mask, slot_count, i; + uint8_t interrupts[4]; + uint8_t interrupt_count; + uint8_t interrupt_mask; + uint8_t slot_count; pci_bridge_t *dev = (pci_bridge_t *) malloc(sizeof(pci_bridge_t)); memset(dev, 0, sizeof(pci_bridge_t)); - dev->local = info->local; + dev->local = info->local; dev->bus_index = pci_register_bus(); pci_bridge_log("PCI Bridge %d: init()\n", dev->bus_index); pci_bridge_reset(dev); - dev->slot = pci_add_card(AGP_BRIDGE(dev->local) ? PCI_ADD_AGPBRIDGE : PCI_ADD_BRIDGE, pci_bridge_read, pci_bridge_write, dev); + pci_add_bridge(AGP_BRIDGE(dev->local), pci_bridge_read, pci_bridge_write, dev, &dev->slot); + interrupt_count = sizeof(interrupts); - interrupt_mask = interrupt_count - 1; + interrupt_mask = interrupt_count - 1; if (dev->slot < 32) { - for (i = 0; i < interrupt_count; i++) - interrupts[i] = pci_get_int(dev->slot, PCI_INTA + i); + for (uint8_t i = 0; i < interrupt_count; i++) + interrupts[i] = pci_get_int(dev->slot, PCI_INTA + i); } - pci_bridge_log("PCI Bridge %d: upstream bus %02X slot %02X interrupts %02X %02X %02X %02X\n", dev->bus_index, (dev->slot >> 5) & 0xff, dev->slot & 31, interrupts[0], interrupts[1], interrupts[2], interrupts[3]); + pci_bridge_log("PCI Bridge %d: upstream bus %02X slot %02X interrupts %02X %02X %02X %02X\n", + dev->bus_index, (dev->slot >> 5) & 0xff, dev->slot & 31, interrupts[0], + interrupts[1], interrupts[2], interrupts[3]); if (info->local == PCI_BRIDGE_DEC_21150) - slot_count = 9; /* 9 bus masters */ + slot_count = 9; /* 9 bus masters */ else - slot_count = 1; /* AGP bridges always have 1 slot */ + slot_count = 1; /* AGP bridges always have 1 slot */ - for (i = 0; i < slot_count; i++) { - /* Interrupts for bridge slots are assigned in round-robin: ABCD, BCDA, CDAB and so on. */ - pci_bridge_log("PCI Bridge %d: downstream slot %02X interrupts %02X %02X %02X %02X\n", dev->bus_index, i, interrupts[i & interrupt_mask], interrupts[(i + 1) & interrupt_mask], interrupts[(i + 2) & interrupt_mask], interrupts[(i + 3) & interrupt_mask]); - pci_register_bus_slot(dev->bus_index, i, AGP_BRIDGE(dev->local) ? PCI_CARD_AGP : PCI_CARD_NORMAL, - interrupts[i & interrupt_mask], - interrupts[(i + 1) & interrupt_mask], - interrupts[(i + 2) & interrupt_mask], - interrupts[(i + 3) & interrupt_mask]); + for (uint8_t i = 0; i < slot_count; i++) { + /* Interrupts for bridge slots are assigned in round-robin: ABCD, BCDA, CDAB and so on. */ + pci_bridge_log("PCI Bridge %d: downstream slot %02X interrupts %02X %02X %02X %02X\n", + dev->bus_index, i, interrupts[i & interrupt_mask], + interrupts[(i + 1) & interrupt_mask], interrupts[(i + 2) & interrupt_mask], + interrupts[(i + 3) & interrupt_mask]); + pci_register_bus_slot(dev->bus_index, i, AGP_BRIDGE(dev->local) ? PCI_CARD_AGP : PCI_CARD_NORMAL, + interrupts[i & interrupt_mask], + interrupts[(i + 1) & interrupt_mask], + interrupts[(i + 2) & interrupt_mask], + interrupts[(i + 3) & interrupt_mask]); } return dev; } - /* PCI bridges */ -const device_t dec21150_device = -{ - "DEC 21150 PCI Bridge", - "dec21150", - DEVICE_PCI, - PCI_BRIDGE_DEC_21150, - pci_bridge_init, - NULL, - pci_bridge_reset, - { NULL }, - NULL, - NULL, - NULL +const device_t dec21150_device = { + .name = "DEC 21150 PCI Bridge", + .internal_name = "dec21150", + .flags = DEVICE_PCI, + .local = PCI_BRIDGE_DEC_21150, + .init = pci_bridge_init, + .close = NULL, + .reset = pci_bridge_reset, + { .available = NULL }, + .speed_changed = NULL, + .force_redraw = NULL, + .config = NULL }; /* AGP bridges */ -const device_t ali5243_agp_device = -{ - "ALi M5243 AGP Bridge", - "ali5243_agp", - DEVICE_PCI, - AGP_BRIDGE_ALI_M5243, - pci_bridge_init, - NULL, - pci_bridge_reset, - { NULL }, - NULL, - NULL, - NULL +const device_t ali5243_agp_device = { + .name = "ALi M5243 AGP Bridge", + .internal_name = "ali5243_agp", + .flags = DEVICE_PCI, + .local = AGP_BRIDGE_ALI_M5243, + .init = pci_bridge_init, + .close = NULL, + .reset = pci_bridge_reset, + { .available = NULL }, + .speed_changed = NULL, + .force_redraw = NULL, + .config = NULL }; /* AGP bridges */ -const device_t ali5247_agp_device = -{ - "ALi M5247 AGP Bridge", - "ali5247_agp", - DEVICE_PCI, - AGP_BRIDGE_ALI_M5247, - pci_bridge_init, - NULL, - pci_bridge_reset, - { NULL }, - NULL, - NULL, - NULL +const device_t ali5247_agp_device = { + .name = "ALi M5247 AGP Bridge", + .internal_name = "ali5247_agp", + .flags = DEVICE_PCI, + .local = AGP_BRIDGE_ALI_M5247, + .init = pci_bridge_init, + .close = NULL, + .reset = pci_bridge_reset, + { .available = NULL }, + .speed_changed = NULL, + .force_redraw = NULL, + .config = NULL }; -const device_t i440lx_agp_device = -{ - "Intel 82443LX/EX AGP Bridge", - "i440lx_agp", - DEVICE_PCI, - AGP_BRIDGE_INTEL_440LX, - pci_bridge_init, - NULL, - pci_bridge_reset, - { NULL }, - NULL, - NULL, - NULL +const device_t i440lx_agp_device = { + .name = "Intel 82443LX/EX AGP Bridge", + .internal_name = "i440lx_agp", + .flags = DEVICE_PCI, + .local = AGP_BRIDGE_INTEL_440LX, + .init = pci_bridge_init, + .close = NULL, + .reset = pci_bridge_reset, + { .available = NULL }, + .speed_changed = NULL, + .force_redraw = NULL, + .config = NULL }; -const device_t i440bx_agp_device = -{ - "Intel 82443BX/ZX AGP Bridge", - "i440bx_agp", - DEVICE_PCI, - AGP_BRIDGE_INTEL_440BX, - pci_bridge_init, - NULL, - pci_bridge_reset, - { NULL }, - NULL, - NULL, - NULL +const device_t i440bx_agp_device = { + .name = "Intel 82443BX/ZX AGP Bridge", + .internal_name = "i440bx_agp", + .flags = DEVICE_PCI, + .local = AGP_BRIDGE_INTEL_440BX, + .init = pci_bridge_init, + .close = NULL, + .reset = pci_bridge_reset, + { .available = NULL }, + .speed_changed = NULL, + .force_redraw = NULL, + .config = NULL }; -const device_t i440gx_agp_device = -{ - "Intel 82443GX AGP Bridge", - "i440gx_agp", - DEVICE_PCI, - AGP_BRIDGE_INTEL_440GX, - pci_bridge_init, - NULL, - pci_bridge_reset, - { NULL }, - NULL, - NULL, - NULL +const device_t i440gx_agp_device = { + .name = "Intel 82443GX AGP Bridge", + .internal_name = "i440gx_agp", + .flags = DEVICE_PCI, + .local = AGP_BRIDGE_INTEL_440GX, + .init = pci_bridge_init, + .close = NULL, + .reset = pci_bridge_reset, + { .available = NULL }, + .speed_changed = NULL, + .force_redraw = NULL, + .config = NULL }; -const device_t via_vp3_agp_device = -{ - "VIA Apollo VP3 AGP Bridge", - "via_vp3_agp", - DEVICE_PCI, - AGP_BRIDGE_VIA_597, - pci_bridge_init, - NULL, - pci_bridge_reset, - { NULL }, - NULL, - NULL, - NULL +const device_t via_vp3_agp_device = { + .name = "VIA Apollo VP3 AGP Bridge", + .internal_name = "via_vp3_agp", + .flags = DEVICE_PCI, + .local = AGP_BRIDGE_VIA_597, + .init = pci_bridge_init, + .close = NULL, + .reset = pci_bridge_reset, + { .available = NULL }, + .speed_changed = NULL, + .force_redraw = NULL, + .config = NULL }; -const device_t via_mvp3_agp_device = -{ - "VIA Apollo MVP3 AGP Bridge", - "via_mvp3_agp", - DEVICE_PCI, - AGP_BRIDGE_VIA_598, - pci_bridge_init, - NULL, - pci_bridge_reset, - { NULL }, - NULL, - NULL, - NULL +const device_t via_mvp3_agp_device = { + .name = "VIA Apollo MVP3 AGP Bridge", + .internal_name = "via_mvp3_agp", + .flags = DEVICE_PCI, + .local = AGP_BRIDGE_VIA_598, + .init = pci_bridge_init, + .close = NULL, + .reset = pci_bridge_reset, + { .available = NULL }, + .speed_changed = NULL, + .force_redraw = NULL, + .config = NULL }; -const device_t via_apro_agp_device = -{ - "VIA Apollo Pro AGP Bridge", - "via_apro_agp", - DEVICE_PCI, - AGP_BRIDGE_VIA_691, - pci_bridge_init, - NULL, - pci_bridge_reset, - { NULL }, - NULL, - NULL, - NULL +const device_t via_apro_agp_device = { + .name = "VIA Apollo Pro AGP Bridge", + .internal_name = "via_apro_agp", + .flags = DEVICE_PCI, + .local = AGP_BRIDGE_VIA_691, + .init = pci_bridge_init, + .close = NULL, + .reset = pci_bridge_reset, + { .available = NULL }, + .speed_changed = NULL, + .force_redraw = NULL, + .config = NULL }; -const device_t via_vt8601_agp_device = -{ - "VIA Apollo ProMedia AGP Bridge", - "via_vt8601_agp", - DEVICE_PCI, - AGP_BRIDGE_VIA_8601, - pci_bridge_init, - NULL, - pci_bridge_reset, - { NULL }, - NULL, - NULL, - NULL +const device_t via_vt8601_agp_device = { + .name = "VIA Apollo ProMedia AGP Bridge", + .internal_name = "via_vt8601_agp", + .flags = DEVICE_PCI, + .local = AGP_BRIDGE_VIA_8601, + .init = pci_bridge_init, + .close = NULL, + .reset = pci_bridge_reset, + { .available = NULL }, + .speed_changed = NULL, + .force_redraw = NULL, + .config = NULL }; diff --git a/src/device/phoenix_486_jumper.c b/src/device/phoenix_486_jumper.c index 8bbbdaee1..a3c891c90 100644 --- a/src/device/phoenix_486_jumper.c +++ b/src/device/phoenix_486_jumper.c @@ -1,146 +1,151 @@ -/* - * 86Box A hypervisor and IBM PC system emulator that specializes in - * running old operating systems and software designed for IBM - * PC systems and compatibles from 1981 through fairly recent - * system designs based on the PCI bus. - * - * This file is part of the 86Box distribution. - * - * Implementation of the Phoenix 486 Jumper Readout - * - * Copyright 2020 Tiseno100 - */ - - -#include -#include -#include -#include -#include -#include -#define HAVE_STDARG_H -#include <86box/86box.h> -#include "cpu.h" -#include <86box/timer.h> -#include <86box/io.h> -#include <86box/device.h> -#include <86box/chipset.h> - -/* - Bit 7 = Super I/O chip: 1 = enabled, 0 = disabled; - Bit 6 = Graphics card: 1 = standalone, 0 = on-board; - Bit 5 = ???? (if 1, siren and hangs); - Bit 4 = ????; - Bit 3 = ????; - Bit 2 = ????; - Bit 1 = ????; - Bit 0 = ????. -*/ - -typedef struct -{ - uint8_t type, jumper; -} phoenix_486_jumper_t; - - -#ifdef ENABLE_PHOENIX_486_JUMPER_LOG -int phoenix_486_jumper_do_log = ENABLE_PHOENIX_486_JUMPER_LOG; - - -static void -phoenix_486_jumper_log(const char *fmt, ...) -{ - va_list ap; - - if (phoenix_486_jumper_do_log) { - va_start(ap, fmt); - pclog_ex(fmt, ap); - va_end(ap); - } -} -#else -#define phoenix_486_jumper_log(fmt, ...) -#endif - - -static void -phoenix_486_jumper_write(uint16_t addr, uint8_t val, void *priv) -{ - phoenix_486_jumper_t *dev = (phoenix_486_jumper_t *) priv; - phoenix_486_jumper_log("Phoenix 486 Jumper: Write %02x\n", val); - if (dev->type == 1) - dev->jumper = val & 0xbf; - else - dev->jumper = val; -} - - -static uint8_t -phoenix_486_jumper_read(uint16_t addr, void *priv) -{ - phoenix_486_jumper_t *dev = (phoenix_486_jumper_t *) priv; - phoenix_486_jumper_log("Phoenix 486 Jumper: Read %02x\n", dev->jumper); - return dev->jumper; -} - - -static void -phoenix_486_jumper_reset(void *priv) -{ - phoenix_486_jumper_t *dev = (phoenix_486_jumper_t *) priv; - - if (dev->type == 1) - dev->jumper = 0x00; - else { - dev->jumper = 0x9f; - if (gfxcard != 0x01) - dev->jumper |= 0x40; - } -} - - -static void -phoenix_486_jumper_close(void *priv) -{ - phoenix_486_jumper_t *dev = (phoenix_486_jumper_t *) priv; - - free(dev); -} - - -static void * -phoenix_486_jumper_init(const device_t *info) -{ - phoenix_486_jumper_t *dev = (phoenix_486_jumper_t *) malloc(sizeof(phoenix_486_jumper_t)); - memset(dev, 0, sizeof(phoenix_486_jumper_t)); - - dev->type = info->local; - - phoenix_486_jumper_reset(dev); - - io_sethandler(0x0078, 0x0001, phoenix_486_jumper_read, NULL, NULL, phoenix_486_jumper_write, NULL, NULL, dev); - - return dev; -} - - -const device_t phoenix_486_jumper_device = { - "Phoenix 486 Jumper Readout", - "phoenix_486_jumper", - 0, - 0, - phoenix_486_jumper_init, phoenix_486_jumper_close, phoenix_486_jumper_reset, - { NULL }, NULL, NULL, - NULL -}; - - -const device_t phoenix_486_jumper_pci_device = { - "Phoenix 486 Jumper Readout (PCI machines)", - "phoenix_486_jumper_pci", - 0, - 1, - phoenix_486_jumper_init, phoenix_486_jumper_close, phoenix_486_jumper_reset, - { NULL }, NULL, NULL, - NULL -}; +/* + * 86Box A hypervisor and IBM PC system emulator that specializes in + * running old operating systems and software designed for IBM + * PC systems and compatibles from 1981 through fairly recent + * system designs based on the PCI bus. + * + * This file is part of the 86Box distribution. + * + * Implementation of the Phoenix 486 Jumper Readout. + * + * + * + * Authors: Miran Grca, + * Tiseno100, + * + * Copyright 2020-2023 Miran Grca. + * Copyright 2020-2023 Tiseno100. + */ +#include +#include +#include +#include +#include +#include +#define HAVE_STDARG_H +#include <86box/86box.h> +#include "cpu.h" +#include <86box/timer.h> +#include <86box/io.h> +#include <86box/device.h> +#include <86box/chipset.h> +#include <86box/plat_unused.h> + +/* + Bit 7 = Super I/O chip: 1 = enabled, 0 = disabled; + Bit 6 = Graphics card: 1 = standalone, 0 = on-board; + Bit 5 = ???? (if 1, siren and hangs); + Bit 4 = ????; + Bit 3 = ????; + Bit 2 = ????; + Bit 1 = ????; + Bit 0 = ????. +*/ + +typedef struct phoenix_486_jumper_t { + uint8_t type; + uint8_t jumper; +} phoenix_486_jumper_t; + +#ifdef ENABLE_PHOENIX_486_JUMPER_LOG +int phoenix_486_jumper_do_log = ENABLE_PHOENIX_486_JUMPER_LOG; + +static void +phoenix_486_jumper_log(const char *fmt, ...) +{ + va_list ap; + + if (phoenix_486_jumper_do_log) { + va_start(ap, fmt); + pclog_ex(fmt, ap); + va_end(ap); + } +} +#else +# define phoenix_486_jumper_log(fmt, ...) +#endif + +static void +phoenix_486_jumper_write(UNUSED(uint16_t addr), uint8_t val, void *priv) +{ + phoenix_486_jumper_t *dev = (phoenix_486_jumper_t *) priv; + phoenix_486_jumper_log("Phoenix 486 Jumper: Write %02x\n", val); + if (dev->type == 1) + dev->jumper = val & 0xbf; + else + dev->jumper = val; +} + +static uint8_t +phoenix_486_jumper_read(UNUSED(uint16_t addr), void *priv) +{ + const phoenix_486_jumper_t *dev = (phoenix_486_jumper_t *) priv; + + phoenix_486_jumper_log("Phoenix 486 Jumper: Read %02x\n", dev->jumper); + return dev->jumper; +} + +static void +phoenix_486_jumper_reset(void *priv) +{ + phoenix_486_jumper_t *dev = (phoenix_486_jumper_t *) priv; + + if (dev->type == 1) + dev->jumper = 0x00; + else { + dev->jumper = 0x9f; + if (gfxcard[0] != 0x01) + dev->jumper |= 0x40; + } +} + +static void +phoenix_486_jumper_close(void *priv) +{ + phoenix_486_jumper_t *dev = (phoenix_486_jumper_t *) priv; + + free(dev); +} + +static void * +phoenix_486_jumper_init(const device_t *info) +{ + phoenix_486_jumper_t *dev = (phoenix_486_jumper_t *) malloc(sizeof(phoenix_486_jumper_t)); + memset(dev, 0, sizeof(phoenix_486_jumper_t)); + + dev->type = info->local; + + phoenix_486_jumper_reset(dev); + + io_sethandler(0x0078, 0x0001, phoenix_486_jumper_read, NULL, NULL, phoenix_486_jumper_write, NULL, NULL, dev); + + return dev; +} + +const device_t phoenix_486_jumper_device = { + .name = "Phoenix 486 Jumper Readout", + .internal_name = "phoenix_486_jumper", + .flags = 0, + .local = 0, + .init = phoenix_486_jumper_init, + .close = phoenix_486_jumper_close, + .reset = phoenix_486_jumper_reset, + { .available = NULL }, + .speed_changed = NULL, + .force_redraw = NULL, + .config = NULL +}; + +const device_t phoenix_486_jumper_pci_device = { + .name = "Phoenix 486 Jumper Readout (PCI machines)", + .internal_name = "phoenix_486_jumper_pci", + .flags = 0, + .local = 1, + .init = phoenix_486_jumper_init, + .close = phoenix_486_jumper_close, + .reset = phoenix_486_jumper_reset, + { .available = NULL }, + .speed_changed = NULL, + .force_redraw = NULL, + .config = NULL +}; diff --git a/src/device/postcard.c b/src/device/postcard.c index 62d37c156..dbae3232a 100644 --- a/src/device/postcard.c +++ b/src/device/postcard.c @@ -1,18 +1,18 @@ /* - * 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. + * 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. + * This file is part of the 86Box distribution. * - * Implementation of a port 80h POST diagnostic card. + * Implementation of a port 80h POST diagnostic card. * * * - * Author: RichardG, + * Authors: RichardG, * - * Copyright 2020 RichardG. + * Copyright 2020 RichardG. */ #include #include @@ -29,123 +29,166 @@ #include <86box/postcard.h> #include "cpu.h" +uint8_t postcard_codes[POSTCARDS_NUM]; -static uint16_t postcard_port; -static uint8_t postcard_written; -static uint8_t postcard_code, postcard_prev_code; -#define UISTR_LEN 13 -static char postcard_str[UISTR_LEN]; /* UI output string */ - - -extern void ui_sb_bugui(char *__str); +static uint16_t postcard_port; +static uint8_t postcard_written[POSTCARDS_NUM]; +static uint8_t postcard_ports_num = 1; +static uint8_t postcard_prev_codes[POSTCARDS_NUM]; +#define UISTR_LEN 32 +static char postcard_str[UISTR_LEN]; /* UI output string */ +extern void ui_sb_bugui(char *__str); #ifdef ENABLE_POSTCARD_LOG int postcard_do_log = ENABLE_POSTCARD_LOG; - static void postcard_log(const char *fmt, ...) { va_list ap; if (postcard_do_log) { - va_start(ap, fmt); - pclog_ex(fmt, ap); - va_end(ap); + va_start(ap, fmt); + pclog_ex(fmt, ap); + va_end(ap); } } #else int postcard_do_log = 0; -#define postcard_log(fmt, ...) +# define postcard_log(fmt, ...) #endif - static void postcard_setui(void) { - if (!postcard_written) - sprintf(postcard_str, "POST: -- --"); - else if (postcard_written == 1) - sprintf(postcard_str, "POST: %02X --", postcard_code); - else - sprintf(postcard_str, "POST: %02X %02X", postcard_code, postcard_prev_code); + if (postcard_ports_num > 1) { + char ps[2][POSTCARDS_NUM][3] = { { { 0 }, + { 0 }, + } }; + + for (uint8_t i = 0; i < POSTCARDS_NUM; i++) { + if (!postcard_written[i]) { + snprintf(ps[0][i], sizeof(ps[0][i]), "--"); + snprintf(ps[1][i], sizeof(ps[1][i]), "--"); + } else if (postcard_written[i] == 1) { + snprintf(ps[0][i], sizeof(ps[0][i]), "%02X", postcard_codes[i]); + snprintf(ps[1][i], sizeof(ps[1][i]), "--"); + } else { + snprintf(ps[0][i], sizeof(ps[0][i]), "%02X", postcard_codes[i]); + snprintf(ps[1][i], sizeof(ps[1][i]), "%02X", postcard_prev_codes[i]); + } + } + + switch (postcard_ports_num) { + default: + case 2: + snprintf(postcard_str, sizeof(postcard_str), "POST: %s%s %s%s", + ps[0][0], ps[0][1], ps[1][0], ps[1][1]); + break; + case 3: + snprintf(postcard_str, sizeof(postcard_str), "POST: %s/%s%s %s/%s%s", + ps[0][0], ps[0][1], ps[0][2], ps[1][0], ps[1][1], ps[1][2]); + break; + case 4: + snprintf(postcard_str, sizeof(postcard_str), "POST: %s%s/%s%s %s%s/%s%s", + ps[0][0], ps[0][1], ps[0][2], ps[0][3], + ps[1][0], ps[1][1], ps[1][2], ps[1][3]); + break; + } + } else { + if (!postcard_written[0]) + snprintf(postcard_str, sizeof(postcard_str), "POST: -- --"); + else if (postcard_written[0] == 1) + snprintf(postcard_str, sizeof(postcard_str), "POST: %02X --", postcard_codes[0]); + else + snprintf(postcard_str, sizeof(postcard_str), "POST: %02X %02X", postcard_codes[0], postcard_prev_codes[0]); + } ui_sb_bugui(postcard_str); if (postcard_do_log) { - /* log same string sent to the UI */ - postcard_log("[%04X:%08X] %s\n", CS, cpu_state.pc, postcard_str); + /* log same string sent to the UI */ + postcard_log("[%04X:%08X] %s\n", CS, cpu_state.pc, postcard_str); } } - static void postcard_reset(void) { - postcard_written = 0; - postcard_code = postcard_prev_code = 0x00; + memset(postcard_written, 0x00, POSTCARDS_NUM * sizeof(uint8_t)); + + memset(postcard_codes, 0x00, POSTCARDS_NUM * sizeof(uint8_t)); + memset(postcard_prev_codes, 0x00, POSTCARDS_NUM * sizeof(uint8_t)); postcard_setui(); } - static void -postcard_write(uint16_t port, uint8_t val, void *priv) +postcard_write(uint16_t port, uint8_t val, UNUSED(void *priv)) { - if (postcard_written && (val == postcard_code)) - return; + if (postcard_written[port & POSTCARD_MASK] && + (val == postcard_codes[port & POSTCARD_MASK])) + return; - postcard_prev_code = postcard_code; - postcard_code = val; - if (postcard_written < 2) - postcard_written++; + postcard_prev_codes[port & POSTCARD_MASK] = postcard_codes[port & POSTCARD_MASK]; + postcard_codes[port & POSTCARD_MASK] = val; + if (postcard_written[port & POSTCARD_MASK] < 2) + postcard_written[port & POSTCARD_MASK]++; postcard_setui(); } - static void * -postcard_init(const device_t *info) +postcard_init(UNUSED(const device_t *info)) { - postcard_reset(); + postcard_ports_num = 1; if (machine_has_bus(machine, MACHINE_BUS_MCA)) - postcard_port = 0x680; /* MCA machines */ + postcard_port = 0x680; /* MCA machines */ else if (strstr(machines[machine].name, " PS/2 ") || strstr(machine_getname_ex(machine), " PS/1 ")) - postcard_port = 0x190; /* ISA PS/2 machines */ + postcard_port = 0x190; /* ISA PS/2 machines */ else if (strstr(machines[machine].name, " IBM XT ")) - postcard_port = 0x60; /* IBM XT */ - else if (strstr(machines[machine].name, " IBM PCjr")) - postcard_port = 0x10; /* IBM PCjr */ - else if (strstr(machines[machine].name, " Compaq ") && !machine_has_bus(machine, MACHINE_BUS_PCI)) - postcard_port = 0x84; /* ISA Compaq machines */ + postcard_port = 0x60; /* IBM XT */ + else if (strstr(machines[machine].name, " IBM PCjr")) { + postcard_port = 0x10; /* IBM PCjr */ + postcard_ports_num = 3; /* IBM PCjr error ports 11h and 12h */ + } else if (strstr(machines[machine].name, " Compaq ") && !machine_has_bus(machine, MACHINE_BUS_PCI)) + postcard_port = 0x84; /* ISA Compaq machines */ + else if (strstr(machines[machine].name, "Olivetti")) + postcard_port = 0x378; /* Olivetti machines */ else - postcard_port = 0x80; /* AT and clone machines */ + postcard_port = 0x80; /* AT and clone machines */ postcard_log("POST card initializing on port %04Xh\n", postcard_port); - if (postcard_port) io_sethandler(postcard_port, 1, - NULL, NULL, NULL, postcard_write, NULL, NULL, NULL); + postcard_reset(); + + if (postcard_port) + io_sethandler(postcard_port, postcard_ports_num, + NULL, NULL, NULL, postcard_write, NULL, NULL, NULL); return postcard_write; } - static void postcard_close(UNUSED(void *priv)) { - if (postcard_port) io_removehandler(postcard_port, 1, - NULL, NULL, NULL, postcard_write, NULL, NULL, NULL); + if (postcard_port) + io_removehandler(postcard_port, postcard_ports_num, + NULL, NULL, NULL, postcard_write, NULL, NULL, NULL); } - const device_t postcard_device = { - "POST Card", - "postcard", - DEVICE_ISA, - 0, - postcard_init, postcard_close, NULL, - { NULL }, NULL, NULL, - NULL + .name = "POST Card", + .internal_name = "postcard", + .flags = DEVICE_ISA, + .local = 0, + .init = postcard_init, + .close = postcard_close, + .reset = NULL, + { .available = NULL }, + .speed_changed = NULL, + .force_redraw = NULL, + .config = NULL }; diff --git a/src/device/serial.c b/src/device/serial.c index 65c919d1b..37aadf8fe 100644 --- a/src/device/serial.c +++ b/src/device/serial.c @@ -1,24 +1,22 @@ /* - * 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. + * 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. + * This file is part of the 86Box distribution. * - * NS8250/16450/16550 UART emulation. + * NS8250/16450/16550 UART emulation. * - * Now passes all the AMIDIAG tests. + * Now passes all the AMIDIAG tests. * * * - * Author: Sarah Walker, - * Miran Grca, - * Fred N. van Kempen, + * Authors: Miran Grca, + * Fred N. van Kempen, * - * Copyright 2008-2020 Sarah Walker. - * Copyright 2016-2020 Miran Grca. - * Copyright 2017-2020 Fred N. van Kempen. + * Copyright 2016-2020 Miran Grca. + * Copyright 2017-2020 Fred N. van Kempen. */ #include #include @@ -35,109 +33,118 @@ #include <86box/pic.h> #include <86box/mem.h> #include <86box/rom.h> +#include <86box/fifo.h> #include <86box/serial.h> #include <86box/mouse.h> +serial_port_t com_ports[SERIAL_MAX]; -enum -{ - SERIAL_INT_LSR = 1, - SERIAL_INT_RECEIVE = 2, - SERIAL_INT_TRANSMIT = 4, - SERIAL_INT_MSR = 8, - SERIAL_INT_TIMEOUT = 16 +enum { + SERIAL_INT_LSR = 1, + SERIAL_INT_TIMEOUT = 2, + SERIAL_INT_RECEIVE = 4, + SERIAL_INT_TRANSMIT = 8, + SERIAL_INT_MSR = 16, + SERIAL_INT_RX_DMA_TC = 32, + SERIAL_INT_TX_DMA_TC = 64 }; +void serial_update_ints(serial_t *dev); -static int next_inst = 0; -static serial_device_t serial_devices[SERIAL_MAX]; +static int next_inst = 0; +static serial_device_t serial_devices[SERIAL_MAX]; +static void serial_xmit_d_empty_evt(void *priv); #ifdef ENABLE_SERIAL_LOG int serial_do_log = ENABLE_SERIAL_LOG; - static void serial_log(const char *fmt, ...) { va_list ap; if (serial_do_log) { - va_start(ap, fmt); - pclog_ex(fmt, ap); - va_end(ap); + va_start(ap, fmt); + pclog_ex(fmt, ap); + va_end(ap); } } #else -#define serial_log(fmt, ...) +# define serial_log(fmt, ...) #endif - void serial_reset_port(serial_t *dev) { - dev->lsr = 0x60; /* Mark that both THR/FIFO and TXSR are empty. */ - dev->iir = dev->ier = dev->lcr = dev->fcr = 0; - dev->fifo_enabled = 0; - dev->xmit_fifo_pos = dev->rcvr_fifo_pos = 0; - dev->rcvr_fifo_full = 0; - dev->baud_cycles = 0; - memset(dev->xmit_fifo, 0, 16); - memset(dev->rcvr_fifo, 0, 14); -} + if (dev->type >= SERIAL_16550) { + if (dev->fifo_enabled) + fifo_reset_evt(dev->xmit_fifo); + else + fifo_reset(dev->xmit_fifo); + } + dev->lsr = 0x60; /* Mark that both THR/FIFO and TXSR are empty. */ + dev->iir = dev->ier = dev->lcr = dev->fcr = 0; + + dev->fifo_enabled = 0; + dev->baud_cycles = 0; + dev->out_new = 0xffff; + + dev->txsr_empty = 1; + dev->thr_empty = 1; + + serial_update_ints(dev); + dev->irq_state = 0; +} void serial_transmit_period(serial_t *dev) { double ddlab; - ddlab = (double) dev->dlab; + if (dev->dlab != 0x0000) + ddlab = (double) dev->dlab; + else + ddlab = 65536.0; /* Bit period based on DLAB. */ dev->transmit_period = (16000000.0 * ddlab) / dev->clock_src; + if (dev->sd && dev->sd->transmit_period_callback) + dev->sd->transmit_period_callback(dev, dev->sd->priv, dev->transmit_period); } +void +serial_do_irq(serial_t *dev, int set) +{ + if (dev->irq != 0xff) { + if (set || (dev->irq_state != !!set)) + picint_common(1 << dev->irq, !!(dev->type >= SERIAL_16450), set, &dev->irq_state); + if (dev->type < SERIAL_16450) + dev->irq_state = !!set; + } +} void serial_update_ints(serial_t *dev) { - int stat = 0; + /* TODO: The IRQ priorities are 6 - we need to find a way to treat timeout and receive + as equal and still somehow distinguish them. */ + uint8_t ier_map[7] = { 0x04, 0x01, 0x01, 0x02, 0x08, 0x40, 0x80 }; + uint8_t iir_map[7] = { 0x06, 0x0c, 0x04, 0x02, 0x00, 0x0e, 0x0a }; - dev->iir = 1; + dev->iir = (dev->iir & 0xf0) | 0x01; - if ((dev->ier & 4) && (dev->int_status & SERIAL_INT_LSR)) { - /* Line status interrupt */ - stat = 1; - dev->iir = 6; - } else if ((dev->ier & 1) && (dev->int_status & SERIAL_INT_TIMEOUT)) { - /* Received data available */ - stat = 1; - dev->iir = 0x0c; - } else if ((dev->ier & 1) && (dev->int_status & SERIAL_INT_RECEIVE)) { - /* Received data available */ - stat = 1; - dev->iir = 4; - } else if ((dev->ier & 2) && (dev->int_status & SERIAL_INT_TRANSMIT)) { - /* Transmit data empty */ - stat = 1; - dev->iir = 2; - } else if ((dev->ier & 8) && (dev->int_status & SERIAL_INT_MSR)) { - /* Modem status interrupt */ - stat = 1; - dev->iir = 0; + for (uint8_t i = 0; i < 7; i++) { + if ((dev->ier & ier_map[i]) && (dev->int_status & (1 << i))) { + dev->iir = (dev->iir & 0xf0) | iir_map[i]; + break; + } } - if (stat && (dev->irq != 0xff) && ((dev->mctrl & 8) || (dev->type == SERIAL_8250_PCJR))) { - if (dev->type >= SERIAL_16450) - picintlevel(1 << dev->irq); - else - picint(1 << dev->irq); - } else - picintc(1 << dev->irq); + serial_do_irq(dev, !(dev->iir & 0x01) && ((dev->mctrl & 8) || (dev->type == SERIAL_8250_PCJR))); } - static void serial_clear_timeout(serial_t *dev) { @@ -147,195 +154,283 @@ serial_clear_timeout(serial_t *dev) serial_update_ints(dev); } +static void +serial_receive_timer(void *priv) +{ + serial_t *dev = (serial_t *) priv; + + serial_log("serial_receive_timer()\n"); + + timer_on_auto(&dev->receive_timer, /* dev->bits * */ dev->transmit_period); + + if (dev->fifo_enabled) { + /* FIFO mode. */ + if (dev->out_new != 0xffff) { + /* We have received a byte into the RSR. */ + + /* Clear FIFO timeout. */ + serial_clear_timeout(dev); + + fifo_write_evt((uint8_t) (dev->out_new & 0xff), dev->rcvr_fifo); + dev->out_new = 0xffff; + +#if 0 + pclog("serial_receive_timer(): lsr = %02X, ier = %02X, iir = %02X, int_status = %02X\n", + dev->lsr, dev->ier, dev->iir, dev->int_status); +#endif + + timer_on_auto(&dev->timeout_timer, 4.0 * dev->bits * dev->transmit_period); + } + } else { + /* Non-FIFO mode. */ + if (dev->out_new != 0xffff) { + /* We have received a byte into the RSR. */ + serial_log("Byte received: %04X\n", dev->out_new); + + /* Indicate overrun. */ + if (dev->lsr & 0x01) + dev->lsr |= 0x02; + + dev->dat = (uint8_t) (dev->out_new & 0xff); + dev->out_new = 0xffff; + + /* Raise Data Ready interrupt. */ + dev->lsr |= 0x01; + dev->int_status |= SERIAL_INT_RECEIVE; + + serial_update_ints(dev); + } + } +} static void write_fifo(serial_t *dev, uint8_t dat) { - serial_log("write_fifo(%08X, %02X, %i, %i)\n", dev, dat, (dev->type >= SERIAL_16550) && dev->fifo_enabled, dev->rcvr_fifo_pos & 0x0f); + serial_log("write_fifo(%08X, %02X, %i, %i)\n", dev, dat, + (dev->type >= SERIAL_16550) && dev->fifo_enabled, + ((dev->type >= SERIAL_16550) && dev->fifo_enabled) ? + fifo_get_count(dev->rcvr_fifo) : 0); - if ((dev->type >= SERIAL_16550) && dev->fifo_enabled) { - /* FIFO mode. */ - timer_disable(&dev->timeout_timer); - /* Indicate overrun. */ - if (dev->rcvr_fifo_full) - dev->lsr |= 0x02; - else - dev->rcvr_fifo[dev->rcvr_fifo_pos] = dat; - dev->lsr &= 0xfe; - dev->int_status &= ~SERIAL_INT_RECEIVE; - if (dev->rcvr_fifo_pos == (dev->rcvr_fifo_len - 1)) { - dev->lsr |= 0x01; - dev->int_status |= SERIAL_INT_RECEIVE; - } - if (dev->rcvr_fifo_pos < 15) - dev->rcvr_fifo_pos++; - else - dev->rcvr_fifo_full = 1; - serial_update_ints(dev); - timer_on_auto(&dev->timeout_timer, 4.0 * dev->bits * dev->transmit_period); - } else { - /* Non-FIFO mode. */ - /* Indicate overrun. */ - if (dev->lsr & 0x01) - dev->lsr |= 0x02; - dev->dat = dat; - dev->lsr |= 0x01; - dev->int_status |= SERIAL_INT_RECEIVE; - serial_update_ints(dev); - } + /* Do this here, because in non-FIFO mode, this is read directly. */ + dev->out_new = (uint16_t) dat; } - void serial_write_fifo(serial_t *dev, uint8_t dat) { - serial_log("serial_write_fifo(%08X, %02X, %i, %i)\n", dev, dat, (dev->type >= SERIAL_16550) && dev->fifo_enabled, dev->rcvr_fifo_pos & 0x0f); + serial_log("serial_write_fifo(%08X, %02X, %i, %i)\n", dev, dat, + (dev->type >= SERIAL_16550) && dev->fifo_enabled, + ((dev->type >= SERIAL_16550) && dev->fifo_enabled) ? + fifo_get_count(dev->rcvr_fifo) : 0); if (!(dev->mctrl & 0x10)) - write_fifo(dev, dat); + write_fifo(dev, dat); } - void serial_transmit(serial_t *dev, uint8_t val) { if (dev->mctrl & 0x10) - write_fifo(dev, val); + write_fifo(dev, val); else if (dev->sd->dev_write) - dev->sd->dev_write(dev, dev->sd->priv, val); -} + dev->sd->dev_write(dev, dev->sd->priv, val); +#ifdef ENABLE_SERIAL_CONSOLE + if ((val >= ' ' && val <= '~') || val == '\r' || val == '\n') { + fputc(val, stdout); + if (val == '\n') + fflush(stdout); + } else + fprintf(stdout, "[%02X]", val); +#endif +} static void serial_move_to_txsr(serial_t *dev) { - int i = 0; - - if (dev->fifo_enabled) { - dev->txsr = dev->xmit_fifo[0]; - if (dev->xmit_fifo_pos > 0) { - /* Move the entire fifo forward by one byte. */ - for (i = 1; i < 16; i++) - dev->xmit_fifo[i - 1] = dev->xmit_fifo[i]; - /* Decrease FIFO position. */ - dev->xmit_fifo_pos--; - } - } else { - dev->txsr = dev->thr; - dev->thr = 0; + dev->txsr_empty = 0; + if (dev->fifo_enabled) + dev->txsr = fifo_read_evt(dev->xmit_fifo); + else { + dev->txsr = dev->thr; + dev->thr = 0; + dev->thr_empty = 1; + serial_xmit_d_empty_evt(dev); } dev->lsr &= ~0x40; - serial_log("serial_move_to_txsr(): FIFO %sabled, FIFO pos = %i\n", dev->fifo_enabled ? "en" : "dis", dev->xmit_fifo_pos & 0x0f); + serial_log("serial_move_to_txsr(): FIFO %sabled, FIFO pos = %i\n", dev->fifo_enabled ? "en" : "dis", + fifo_get_count(dev->xmit_fifo) & 0x0f); - if (!dev->fifo_enabled || (dev->xmit_fifo_pos == 0x0)) { - /* Update interrupts to signal THRE and that TXSR is no longer empty. */ - dev->lsr |= 0x20; - dev->int_status |= SERIAL_INT_TRANSMIT; - serial_update_ints(dev); + if (!dev->fifo_enabled || (fifo_get_count(dev->xmit_fifo) == 0x0)) { + /* Update interrupts to signal THRE and that TXSR is no longer empty. */ + serial_update_ints(dev); } if (dev->transmit_enabled & 2) - dev->baud_cycles++; + dev->baud_cycles++; else - dev->baud_cycles = 0; /* If not moving while transmitting, reset BAUDOUT cycle count. */ - if (!dev->fifo_enabled || (dev->xmit_fifo_pos == 0x0)) - dev->transmit_enabled &= ~1; /* Stop moving. */ - dev->transmit_enabled |= 2; /* Start transmitting. */ + dev->baud_cycles = 0; /* If not moving while transmitting, reset BAUDOUT cycle count. */ + if (!dev->fifo_enabled || (fifo_get_count(dev->xmit_fifo) == 0x0)) + dev->transmit_enabled &= ~1; /* Stop moving. */ + dev->transmit_enabled |= 2; /* Start transmitting. */ } - static void serial_process_txsr(serial_t *dev) { serial_log("serial_process_txsr(): FIFO %sabled\n", dev->fifo_enabled ? "en" : "dis"); serial_transmit(dev, dev->txsr); dev->txsr = 0; + dev->txsr_empty = 1; + serial_xmit_d_empty_evt(dev); /* Reset BAUDOUT cycle count. */ dev->baud_cycles = 0; /* If FIFO is enabled and there are bytes left to transmit, continue with the FIFO, otherwise stop. */ - if (dev->fifo_enabled && (dev->xmit_fifo_pos != 0x0)) - dev->transmit_enabled |= 1; - else { - /* Both FIFO/THR and TXSR are empty. */ - /* If bit 5 is set, also set bit 6 to mark both THR and shift register as empty. */ - if (dev->lsr & 0x20) - dev->lsr |= 0x40; - dev->transmit_enabled &= ~2; - } - dev->int_status &= ~SERIAL_INT_TRANSMIT; + if (dev->fifo_enabled && (fifo_get_count(dev->xmit_fifo) != 0x0)) + dev->transmit_enabled |= 1; + /* Both FIFO/THR and TXSR are empty. */ + else + dev->transmit_enabled &= ~2; + serial_update_ints(dev); } - /* Transmit_enable flags: - Bit 0 = Do move if set; - Bit 1 = Do transmit if set. */ + Bit 0 = Do move if set; + Bit 1 = Do transmit if set. */ static void serial_transmit_timer(void *priv) { - serial_t *dev = (serial_t *) priv; - int delay = 8; /* STOP to THRE delay is 8 BAUDOUT cycles. */ + serial_t *dev = (serial_t *) priv; + int delay = 8; /* STOP to THRE delay is 8 BAUDOUT cycles. */ if (dev->transmit_enabled & 3) { - if ((dev->transmit_enabled & 1) && (dev->transmit_enabled & 2)) - delay = dev->data_bits; /* Delay by less if already transmitting. */ + if ((dev->transmit_enabled & 1) && (dev->transmit_enabled & 2)) + delay = dev->data_bits; /* Delay by less if already transmitting. */ - dev->baud_cycles++; + dev->baud_cycles++; - /* We have processed (total bits) BAUDOUT cycles, transmit the byte. */ - if ((dev->baud_cycles == dev->bits) && (dev->transmit_enabled & 2)) - serial_process_txsr(dev); + /* We have processed (total bits) BAUDOUT cycles, transmit the byte. */ + if ((dev->baud_cycles == dev->bits) && (dev->transmit_enabled & 2)) + serial_process_txsr(dev); - /* We have processed (data bits) BAUDOUT cycles. */ - if ((dev->baud_cycles == delay) && (dev->transmit_enabled & 1)) - serial_move_to_txsr(dev); + /* We have processed (data bits) BAUDOUT cycles. */ + if ((dev->baud_cycles == delay) && (dev->transmit_enabled & 1)) + serial_move_to_txsr(dev); - if (dev->transmit_enabled & 3) - timer_on_auto(&dev->transmit_timer, dev->transmit_period); + if (dev->transmit_enabled & 3) + timer_on_auto(&dev->transmit_timer, dev->transmit_period); } else { - dev->baud_cycles = 0; - return; + dev->baud_cycles = 0; + return; } } - static void serial_timeout_timer(void *priv) { serial_t *dev = (serial_t *) priv; -#ifdef ENABLE_SERIAL_LOG serial_log("serial_timeout_timer()\n"); -#endif dev->lsr |= 0x01; dev->int_status |= SERIAL_INT_TIMEOUT; serial_update_ints(dev); } +void +serial_device_timeout(void *priv) +{ + serial_t *dev = (serial_t *) priv; + + serial_log("serial_device_timeout()\n"); + + if (!dev->fifo_enabled) { + dev->lsr |= 0x10; + dev->int_status |= SERIAL_INT_LSR; + serial_update_ints(dev); + } +} static void serial_update_speed(serial_t *dev) { + serial_log("serial_update_speed(%lf)\n", dev->transmit_period); + timer_on_auto(&dev->receive_timer, /* dev->bits * */ dev->transmit_period); + if (dev->transmit_enabled & 3) - timer_on_auto(&dev->transmit_timer, dev->transmit_period); + timer_on_auto(&dev->transmit_timer, dev->transmit_period); - if (timer_is_enabled(&dev->timeout_timer)) - timer_on_auto(&dev->timeout_timer, 4.0 * dev->bits * dev->transmit_period); + if (timer_is_on(&dev->timeout_timer)) + timer_on_auto(&dev->timeout_timer, 4.0 * dev->bits * dev->transmit_period); } - static void serial_reset_fifo(serial_t *dev) { - dev->lsr = (dev->lsr & 0xfe) | 0x60; - dev->int_status = (dev->int_status & ~SERIAL_INT_RECEIVE) | SERIAL_INT_TRANSMIT; + fifo_reset_evt(dev->xmit_fifo); + fifo_reset_evt(dev->rcvr_fifo); + serial_update_ints(dev); - dev->xmit_fifo_pos = dev->rcvr_fifo_pos = 0; - dev->rcvr_fifo_full = 0; } +void +serial_set_dsr(serial_t *dev, uint8_t enabled) +{ + if (dev->mctrl & 0x10) + return; + + dev->msr &= ~0x2; + dev->msr |= ((dev->msr & 0x20) ^ ((!!enabled) << 5)) >> 4; + dev->msr &= ~0x20; + dev->msr |= (!!enabled) << 5; + dev->msr_set &= ~0x20; + dev->msr_set |= (!!enabled) << 5; + + if (dev->msr & 0x2) { + dev->int_status |= SERIAL_INT_MSR; + serial_update_ints(dev); + } +} + +void +serial_set_cts(serial_t *dev, uint8_t enabled) +{ + if (dev->mctrl & 0x10) + return; + + dev->msr &= ~0x1; + dev->msr |= ((dev->msr & 0x10) ^ ((!!enabled) << 4)) >> 4; + dev->msr &= ~0x10; + dev->msr |= (!!enabled) << 4; + dev->msr_set &= ~0x10; + dev->msr_set |= (!!enabled) << 4; + + if (dev->msr & 0x1) { + dev->int_status |= SERIAL_INT_MSR; + serial_update_ints(dev); + } +} + +void +serial_set_dcd(serial_t *dev, uint8_t enabled) +{ + if (dev->mctrl & 0x10) + return; + + dev->msr &= ~0x8; + dev->msr |= ((dev->msr & 0x80) ^ ((!!enabled) << 7)) >> 4; + dev->msr &= ~0x80; + dev->msr |= (!!enabled) << 7; + dev->msr_set &= ~0x80; + dev->msr_set |= (!!enabled) << 7; + + if (dev->msr & 0x8) { + dev->int_status |= SERIAL_INT_MSR; + serial_update_ints(dev); + } +} void serial_set_clock_src(serial_t *dev, double clock_src) @@ -346,309 +441,359 @@ serial_set_clock_src(serial_t *dev, double clock_src) serial_update_speed(dev); } - void -serial_write(uint16_t addr, uint8_t val, void *p) +serial_write(uint16_t addr, uint8_t val, void *priv) { - serial_t *dev = (serial_t *)p; - uint8_t new_msr, old; + serial_t *dev = (serial_t *) priv; + uint8_t new_msr; + uint8_t old; - serial_log("UART: Write %02X to port %02X\n", val, addr); + serial_log("UART: [%04X:%08X] Write %02X to port %02X\n", CS, cpu_state.pc, val, addr); cycles -= ISA_CYCLES(8); switch (addr & 7) { - case 0: - if (dev->lcr & 0x80) { - dev->dlab = (dev->dlab & 0xff00) | val; - serial_transmit_period(dev); - serial_update_speed(dev); - return; + case 0: + if (dev->lcr & 0x80) { + dev->dlab = (dev->dlab & 0xff00) | val; + serial_transmit_period(dev); + serial_update_speed(dev); + return; + } + + if (dev->fifo_enabled && (fifo_get_count(dev->xmit_fifo) < 16)) { + /* FIFO mode, begin transmitting. */ + timer_on_auto(&dev->transmit_timer, dev->transmit_period); + dev->transmit_enabled |= 1; /* Start moving. */ + fifo_write_evt(val, dev->xmit_fifo); + } else if (!dev->fifo_enabled) { + /* Indicate THR is no longer empty. */ + dev->lsr &= 0x9f; + dev->int_status &= ~SERIAL_INT_TRANSMIT; + serial_update_ints(dev); + + /* Non-FIFO mode, begin transmitting. */ + timer_on_auto(&dev->transmit_timer, dev->transmit_period); + dev->transmit_enabled |= 1; /* Start moving. */ + dev->thr = val; + dev->thr_empty = 0; + } + break; + case 1: + if (dev->lcr & 0x80) { + dev->dlab = (dev->dlab & 0x00ff) | (val << 8); + serial_transmit_period(dev); + serial_update_speed(dev); + return; + } + if ((val & 2) && (dev->lsr & 0x20)) + dev->int_status |= SERIAL_INT_TRANSMIT; + dev->ier = val & 0xf; + serial_update_ints(dev); + break; + case 2: + if (dev->type >= SERIAL_16550) { + if ((val ^ dev->fcr) & 0x01) + serial_reset_fifo(dev); + dev->fcr = val & 0xf9; + dev->fifo_enabled = val & 0x01; + /* TODO: When switching modes, shouldn't we reset the LSR + based on the new conditions? */ + if (!dev->fifo_enabled) { + fifo_reset(dev->xmit_fifo); + fifo_reset(dev->rcvr_fifo); + break; } + if (val & 0x02) { + if (dev->fifo_enabled) + fifo_reset_evt(dev->rcvr_fifo); + else + fifo_reset(dev->rcvr_fifo); + } + if (val & 0x04) { + if (dev->fifo_enabled) + fifo_reset_evt(dev->xmit_fifo); + else + fifo_reset(dev->xmit_fifo); + } + switch ((val >> 6) & 0x03) { + case 0: + fifo_set_trigger_len(dev->rcvr_fifo, 1); + break; + case 1: + fifo_set_trigger_len(dev->rcvr_fifo, 4); + break; + case 2: + fifo_set_trigger_len(dev->rcvr_fifo, 8); + break; + case 3: + fifo_set_trigger_len(dev->rcvr_fifo, 14); + break; - /* Indicate FIFO/THR is no longer empty. */ - dev->lsr &= 0x9f; - dev->int_status &= ~SERIAL_INT_TRANSMIT; - serial_update_ints(dev); + default: + break; + } + fifo_set_trigger_len(dev->xmit_fifo, 16); + dev->out_new = 0xffff; + serial_log("FIFO now %sabled\n", dev->fifo_enabled ? "en" : "dis"); + } + break; + case 3: + old = dev->lcr; + dev->lcr = val; + if ((old ^ val) & 0x3f) { + /* Data bits + start bit. */ + dev->bits = ((dev->lcr & 0x03) + 5) + 1; + /* Stop bits. */ + dev->bits++; /* First stop bit. */ + if (dev->lcr & 0x04) + dev->bits++; /* Second stop bit. */ + /* Parity bit. */ + if (dev->lcr & 0x08) + dev->bits++; - if ((dev->type >= SERIAL_16550) && dev->fifo_enabled && (dev->xmit_fifo_pos < 16)) { - /* FIFO mode, begin transmitting. */ - timer_on_auto(&dev->transmit_timer, dev->transmit_period); - dev->transmit_enabled |= 1; /* Start moving. */ - dev->xmit_fifo[dev->xmit_fifo_pos++] = val; - } else { - /* Non-FIFO mode, begin transmitting. */ - timer_on_auto(&dev->transmit_timer, dev->transmit_period); - dev->transmit_enabled |= 1; /* Start moving. */ - dev->thr = val; - } - break; - case 1: - if (dev->lcr & 0x80) { - dev->dlab = (dev->dlab & 0x00ff) | (val << 8); - serial_transmit_period(dev); - serial_update_speed(dev); - return; - } - if ((val & 2) && (dev->lsr & 0x20)) - dev->int_status |= SERIAL_INT_TRANSMIT; - dev->ier = val & 0xf; - serial_update_ints(dev); - break; - case 2: - if (dev->type >= SERIAL_16550) { - if ((val ^ dev->fcr) & 0x01) - serial_reset_fifo(dev); - dev->fcr = val & 0xf9; - dev->fifo_enabled = val & 0x01; - if (!dev->fifo_enabled) { - memset(dev->rcvr_fifo, 0, 14); - memset(dev->xmit_fifo, 0, 16); - dev->xmit_fifo_pos = dev->rcvr_fifo_pos = 0; - dev->rcvr_fifo_full = 0; - dev->rcvr_fifo_len = 1; - break; - } - if (val & 0x02) { - memset(dev->rcvr_fifo, 0, 14); - dev->rcvr_fifo_pos = 0; - dev->rcvr_fifo_full = 0; - } - if (val & 0x04) { - memset(dev->xmit_fifo, 0, 16); - dev->xmit_fifo_pos = 0; - } - switch ((val >> 6) & 0x03) { - case 0: - dev->rcvr_fifo_len = 1; - break; - case 1: - dev->rcvr_fifo_len = 4; - break; - case 2: - dev->rcvr_fifo_len = 8; - break; - case 3: - dev->rcvr_fifo_len = 14; - break; - } - serial_log("FIFO now %sabled, receive FIFO length = %i\n", dev->fifo_enabled ? "en" : "dis", dev->rcvr_fifo_len); - } - break; - case 3: - old = dev->lcr; - dev->lcr = val; - if ((old ^ val) & 0x0f) { - /* Data bits + start bit. */ - dev->bits = ((dev->lcr & 0x03) + 5) + 1; - /* Stop bits. */ - dev->bits++; /* First stop bit. */ - if (dev->lcr & 0x04) - dev->bits++; /* Second stop bit. */ - /* Parity bit. */ - if (dev->lcr & 0x08) - dev->bits++; + serial_transmit_period(dev); + serial_update_speed(dev); - serial_transmit_period(dev); - serial_update_speed(dev); - } - break; - case 4: - if ((val & 2) && !(dev->mctrl & 2)) { - if (dev->sd->rcr_callback) - dev->sd->rcr_callback(dev, dev->sd->priv); - } - if (!(val & 8) && (dev->mctrl & 8)) - picintc(1 << dev->irq); - if ((val ^ dev->mctrl) & 0x10) - serial_reset_fifo(dev); - dev->mctrl = val; - if (val & 0x10) { - new_msr = (val & 0x0c) << 4; - new_msr |= (val & 0x02) ? 0x10: 0; - new_msr |= (val & 0x01) ? 0x20: 0; + if (dev->sd && dev->sd->lcr_callback) + dev->sd->lcr_callback(dev, dev->sd->priv, dev->lcr); + } + break; + case 4: + if ((val & 2) && !(dev->mctrl & 2)) { + if (dev->sd && dev->sd->rcr_callback) { + serial_log("RTS toggle callback\n"); + dev->sd->rcr_callback(dev, dev->sd->priv); + } + } + if (!(val & 8) && (dev->mctrl & 8)) + serial_do_irq(dev, 0); + if ((val ^ dev->mctrl) & 0x10) + serial_reset_fifo(dev); + dev->mctrl = val; + if (val & 0x10) { + new_msr = (val & 0x0c) << 4; + new_msr |= (val & 0x02) ? 0x10 : 0; + new_msr |= (val & 0x01) ? 0x20 : 0; - if ((dev->msr ^ new_msr) & 0x10) - new_msr |= 0x01; - if ((dev->msr ^ new_msr) & 0x20) - new_msr |= 0x02; - if ((dev->msr ^ new_msr) & 0x80) - new_msr |= 0x08; - if ((dev->msr & 0x40) && !(new_msr & 0x40)) - new_msr |= 0x04; + if ((dev->msr ^ new_msr) & 0x10) + new_msr |= 0x01; + if ((dev->msr ^ new_msr) & 0x20) + new_msr |= 0x02; + if ((dev->msr ^ new_msr) & 0x80) + new_msr |= 0x08; + if ((dev->msr & 0x40) && !(new_msr & 0x40)) + new_msr |= 0x04; - dev->msr = new_msr; + dev->msr = new_msr; - dev->xmit_fifo_pos = dev->rcvr_fifo_pos = 0; - dev->rcvr_fifo_full = 0; - } - break; - case 5: - dev->lsr = (dev->lsr & 0xe0) | (val & 0x1f); - if (dev->lsr & 0x01) - dev->int_status |= SERIAL_INT_RECEIVE; - if (dev->lsr & 0x1e) - dev->int_status |= SERIAL_INT_LSR; - if (dev->lsr & 0x20) - dev->int_status |= SERIAL_INT_TRANSMIT; - serial_update_ints(dev); - break; - case 6: - dev->msr = val; - if (dev->msr & 0x0f) - dev->int_status |= SERIAL_INT_MSR; - serial_update_ints(dev); - break; - case 7: - if (dev->type >= SERIAL_16450) - dev->scratch = val; - break; + /* TODO: Why reset the FIFO's here?! */ + fifo_reset(dev->xmit_fifo); + fifo_reset(dev->rcvr_fifo); + } + break; + case 5: + dev->lsr = (dev->lsr & 0xe0) | (val & 0x1f); + if (dev->lsr & 0x01) + dev->int_status |= SERIAL_INT_RECEIVE; + if (dev->lsr & 0x1e) + dev->int_status |= SERIAL_INT_LSR; + if (dev->lsr & 0x20) + dev->int_status |= SERIAL_INT_TRANSMIT; + serial_update_ints(dev); + break; + case 6: +#if 0 + dev->msr = (val & 0xf0) | (dev->msr & 0x0f); + dev->msr = val; +#endif + /* The actual condition bits of the MSR are read-only, but the delta bits are + undocumentedly writable, and the PCjr BIOS uses them to raise MSR interrupts. */ + dev->msr = (dev->msr & 0xf0) | (val & 0x0f); + if (dev->msr & 0x0f) + dev->int_status |= SERIAL_INT_MSR; + serial_update_ints(dev); + break; + case 7: + if (dev->type >= SERIAL_16450) + dev->scratch = val; + break; + default: + break; } } - uint8_t -serial_read(uint16_t addr, void *p) +serial_read(uint16_t addr, void *priv) { - serial_t *dev = (serial_t *)p; - uint8_t i, ret = 0; + serial_t *dev = (serial_t *) priv; + uint8_t ret = 0; cycles -= ISA_CYCLES(8); switch (addr & 7) { - case 0: - if (dev->lcr & 0x80) { - ret = dev->dlab & 0xff; - break; - } + case 0: + if (dev->lcr & 0x80) { + ret = dev->dlab & 0xff; + break; + } - if ((dev->type >= SERIAL_16550) && dev->fifo_enabled) { - /* FIFO mode. */ + if (dev->fifo_enabled) { + /* FIFO mode. */ + serial_clear_timeout(dev); + ret = fifo_read_evt(dev->rcvr_fifo); - serial_clear_timeout(dev); + if (dev->lsr & 0x01) + timer_on_auto(&dev->timeout_timer, 4.0 * dev->bits * dev->transmit_period); + } else { + /* Non-FIFO mode. */ + ret = dev->dat; - ret = dev->rcvr_fifo[0]; - dev->rcvr_fifo_full = 0; - if (dev->rcvr_fifo_pos > 0) { - for (i = 1; i < 16; i++) - dev->rcvr_fifo[i - 1] = dev->rcvr_fifo[i]; - serial_log("FIFO position %i: read %02X, next %02X\n", dev->rcvr_fifo_pos, ret, dev->rcvr_fifo[0]); - dev->rcvr_fifo_pos--; - /* At least one byte remains to be read, start the timeout - timer so that a timeout is indicated in case of no read. */ - timer_on_auto(&dev->timeout_timer, 4.0 * dev->bits * dev->transmit_period); - } else { - dev->lsr &= 0xfe; - dev->int_status &= ~SERIAL_INT_RECEIVE; - serial_update_ints(dev); - } - } else { - ret = dev->dat; - dev->lsr &= 0xfe; - dev->int_status &= ~SERIAL_INT_RECEIVE; - serial_update_ints(dev); - } - serial_log("Read data: %02X\n", ret); - break; - case 1: - if (dev->lcr & 0x80) - ret = (dev->dlab >> 8) & 0xff; - else - ret = dev->ier; - break; - case 2: - ret = dev->iir; - if ((ret & 0xe) == 2) { - dev->int_status &= ~SERIAL_INT_TRANSMIT; - serial_update_ints(dev); - } - if (dev->fcr & 1) - ret |= 0xc0; - break; - case 3: - ret = dev->lcr; - break; - case 4: - ret = dev->mctrl; - break; - case 5: - ret = dev->lsr; - if (dev->lsr & 0x1f) - dev->lsr &= ~0x1e; - dev->int_status &= ~SERIAL_INT_LSR; - serial_update_ints(dev); - break; - case 6: - ret = dev->msr; - dev->msr &= ~0x0f; - dev->int_status &= ~SERIAL_INT_MSR; - serial_update_ints(dev); - break; - case 7: - ret = dev->scratch; - break; + /* Always clear Data Ready interrupt. */ + dev->lsr &= 0xfe; + dev->int_status &= ~SERIAL_INT_RECEIVE; + serial_update_ints(dev); + } + + serial_log("Read data: %02X\n", ret); + break; + case 1: + if (dev->lcr & 0x80) + ret = (dev->dlab >> 8) & 0xff; + else + ret = dev->ier; + break; + case 2: + ret = dev->iir; + if ((ret & 0xe) == 2) { + dev->int_status &= ~SERIAL_INT_TRANSMIT; + serial_update_ints(dev); + } + if (dev->fcr & 1) + ret |= 0xc0; + break; + case 3: + ret = dev->lcr; + break; + case 4: + ret = dev->mctrl; + break; + case 5: + ret = dev->lsr; + if (dev->lsr & 0x1f) + dev->lsr &= ~0x1e; + dev->int_status &= ~SERIAL_INT_LSR; + serial_update_ints(dev); + break; + case 6: + ret = dev->msr | dev->msr_set; + dev->msr &= ~0x0f; + dev->int_status &= ~SERIAL_INT_MSR; + serial_update_ints(dev); + break; + case 7: + ret = dev->scratch; + break; + default: + break; } - serial_log("UART: Read %02X from port %02X\n", ret, addr); + serial_log("UART: [%04X:%08X] Read %02X from port %02X\n", CS, cpu_state.pc, ret, addr); return ret; } - void serial_remove(serial_t *dev) { if (dev == NULL) - return; + return; - if (!serial_enabled[dev->inst]) - return; + if (!com_ports[dev->inst].enabled) + return; if (!dev->base_address) - return; + return; serial_log("Removing serial port %i at %04X...\n", dev->inst, dev->base_address); io_removehandler(dev->base_address, 0x0008, - serial_read, NULL, NULL, serial_write, NULL, NULL, dev); + serial_read, NULL, NULL, serial_write, NULL, NULL, dev); dev->base_address = 0x0000; } - void serial_setup(serial_t *dev, uint16_t addr, uint8_t irq) { serial_log("Adding serial port %i at %04X...\n", dev->inst, addr); if (dev == NULL) - return; + return; - if (!serial_enabled[dev->inst]) - return; + if (!com_ports[dev->inst].enabled) + return; if (dev->base_address != 0x0000) - serial_remove(dev); + serial_remove(dev); dev->base_address = addr; if (addr != 0x0000) - io_sethandler(addr, 0x0008, serial_read, NULL, NULL, serial_write, NULL, NULL, dev); + io_sethandler(addr, 0x0008, serial_read, NULL, NULL, serial_write, NULL, NULL, dev); dev->irq = irq; } +static void +serial_rcvr_d_empty_evt(void *priv) +{ + serial_t *dev = (serial_t *) priv; + + dev->lsr = (dev->lsr & 0xfe) | (fifo_get_empty(dev->rcvr_fifo) ? 0 : 1); +} + +static void +serial_rcvr_d_overrun_evt(void *priv) +{ + serial_t *dev = (serial_t *) priv; + + dev->lsr = (dev->lsr & 0xfd) | (fifo_get_overrun(dev->rcvr_fifo) << 1); +} + +static void +serial_rcvr_d_ready_evt(void *priv) +{ + serial_t *dev = (serial_t *) priv; + + dev->int_status = (dev->int_status & ~SERIAL_INT_RECEIVE) | + (fifo_get_ready(dev->rcvr_fifo) ? SERIAL_INT_RECEIVE : 0); + serial_update_ints(dev); +} + +static void +serial_xmit_d_empty_evt(void *priv) +{ + serial_t *dev = (serial_t *) priv; + uint8_t is_empty = dev->fifo_enabled ? fifo_get_empty(dev->xmit_fifo) : dev->thr_empty; + + dev->lsr = (dev->lsr & 0x9f) | (is_empty << 5) | ((dev->txsr_empty && is_empty) << 6); + dev->int_status = (dev->int_status & ~SERIAL_INT_TRANSMIT) | (is_empty ? SERIAL_INT_TRANSMIT : 0); +} serial_t * -serial_attach(int port, - void (*rcr_callback)(struct serial_s *serial, void *p), - void (*dev_write)(struct serial_s *serial, void *p, uint8_t data), - void *priv) +serial_attach_ex(int port, + void (*rcr_callback)(struct serial_s *serial, void *priv), + void (*dev_write)(struct serial_s *serial, void *priv, uint8_t data), + void (*transmit_period_callback)(struct serial_s *serial, void *priv, double transmit_period), + void (*lcr_callback)(struct serial_s *serial, void *priv, uint8_t data_bits), + void *priv) { serial_device_t *sd = &serial_devices[port]; - sd->rcr_callback = rcr_callback; - sd->dev_write = dev_write; - sd->priv = priv; + sd->rcr_callback = rcr_callback; + sd->dev_write = dev_write; + sd->transmit_period_callback = transmit_period_callback; + sd->lcr_callback = lcr_callback; + sd->priv = priv; return sd->serial; } - static void serial_speed_changed(void *priv) { @@ -657,7 +802,6 @@ serial_speed_changed(void *priv) serial_update_speed(dev); } - static void serial_close(void *priv) { @@ -665,9 +809,45 @@ serial_close(void *priv) next_inst--; + if (com_ports[dev->inst].enabled) + fifo_close(dev->rcvr_fifo); + free(dev); } +static void +serial_reset(void *priv) +{ + serial_t *dev = (serial_t *) priv; + + if (com_ports[dev->inst].enabled) { + timer_disable(&dev->transmit_timer); + timer_disable(&dev->timeout_timer); + timer_disable(&dev->receive_timer); + + dev->lsr = dev->thr = dev->mctrl = dev->rcr = 0x00; + dev->iir = dev->ier = dev->lcr = dev->msr = 0x00; + dev->dat = dev->int_status = dev->scratch = dev->fcr = 0x00; + dev->fifo_enabled = dev->bits = 0x000; + dev->data_bits = dev->baud_cycles = 0x00; + dev->txsr = 0x00; + dev->txsr_empty = 0x01; + dev->thr_empty = 0x0001; + + dev->dlab = dev->out_new = 0x0000; + + if (dev->rcvr_fifo != NULL) + fifo_reset(dev->rcvr_fifo); + + serial_reset_port(dev); + + dev->dlab = 96; + dev->fcr = 0x06; + + serial_transmit_period(dev); + serial_update_speed(dev); + } +} static void * serial_init(const device_t *info) @@ -677,29 +857,49 @@ serial_init(const device_t *info) dev->inst = next_inst; - if (serial_enabled[next_inst]) { - serial_log("Adding serial port %i...\n", next_inst); - dev->type = info->local; - memset(&(serial_devices[next_inst]), 0, sizeof(serial_device_t)); - dev->sd = &(serial_devices[next_inst]); - dev->sd->serial = dev; - serial_reset_port(dev); - if (next_inst == 3) - serial_setup(dev, SERIAL4_ADDR, SERIAL4_IRQ); - else if (next_inst == 2) - serial_setup(dev, SERIAL3_ADDR, SERIAL3_IRQ); - else if ((next_inst == 1) || (info->flags & DEVICE_PCJR)) - serial_setup(dev, SERIAL2_ADDR, SERIAL2_IRQ); - else if (next_inst == 0) - serial_setup(dev, SERIAL1_ADDR, SERIAL1_IRQ); + if (com_ports[next_inst].enabled) { + serial_log("Adding serial port %i...\n", next_inst); + dev->type = info->local; + memset(&(serial_devices[next_inst]), 0, sizeof(serial_device_t)); + dev->sd = &(serial_devices[next_inst]); + dev->sd->serial = dev; + if (next_inst == 3) + serial_setup(dev, COM4_ADDR, COM4_IRQ); + else if (next_inst == 2) + serial_setup(dev, COM3_ADDR, COM3_IRQ); + else if ((next_inst == 1) || (info->flags & DEVICE_PCJR)) + serial_setup(dev, COM2_ADDR, COM2_IRQ); + else if (next_inst == 0) + serial_setup(dev, COM1_ADDR, COM1_IRQ); - /* Default to 1200,N,7. */ - dev->dlab = 96; - dev->fcr = 0x06; - dev->clock_src = 1843200.0; - serial_transmit_period(dev); - timer_add(&dev->transmit_timer, serial_transmit_timer, dev, 0); - timer_add(&dev->timeout_timer, serial_timeout_timer, dev, 0); + /* Default to 1200,N,7. */ + dev->dlab = 96; + dev->fcr = 0x06; + if (info->local == SERIAL_8250_PCJR) + dev->clock_src = 1789500.0; + else + dev->clock_src = 1843200.0; + timer_add(&dev->transmit_timer, serial_transmit_timer, dev, 0); + timer_add(&dev->timeout_timer, serial_timeout_timer, dev, 0); + timer_add(&dev->receive_timer, serial_receive_timer, dev, 0); + serial_transmit_period(dev); + serial_update_speed(dev); + + dev->rcvr_fifo = fifo64_init(); + fifo_set_priv(dev->rcvr_fifo, dev); + fifo_set_d_empty_evt(dev->rcvr_fifo, serial_rcvr_d_empty_evt); + fifo_set_d_overrun_evt(dev->rcvr_fifo, serial_rcvr_d_overrun_evt); + fifo_set_d_ready_evt(dev->rcvr_fifo, serial_rcvr_d_ready_evt); + fifo_reset_evt(dev->rcvr_fifo); + fifo_set_len(dev->rcvr_fifo, 16); + + dev->xmit_fifo = fifo64_init(); + fifo_set_priv(dev->xmit_fifo, dev); + fifo_set_d_empty_evt(dev->xmit_fifo, serial_xmit_d_empty_evt); + fifo_reset_evt(dev->xmit_fifo); + fifo_set_len(dev->xmit_fifo, 16); + + serial_reset_port(dev); } next_inst++; @@ -707,97 +907,127 @@ serial_init(const device_t *info) return dev; } - void serial_set_next_inst(int ni) { next_inst = ni; } - void -serial_standalone_init(void) { - for ( ; next_inst < 4; ) - device_add_inst(&ns8250_device, next_inst + 1); +serial_standalone_init(void) +{ + while (next_inst < SERIAL_MAX) + device_add_inst(&ns8250_device, next_inst + 1); }; - const device_t ns8250_device = { - "National Semiconductor 8250(-compatible) UART", - "ns8250", - 0, - SERIAL_8250, - serial_init, serial_close, NULL, - { NULL }, serial_speed_changed, NULL, - NULL + .name = "National Semiconductor 8250(-compatible) UART", + .internal_name = "ns8250", + .flags = 0, + .local = SERIAL_8250, + .init = serial_init, + .close = serial_close, + .reset = serial_reset, + { .available = NULL }, + .speed_changed = serial_speed_changed, + .force_redraw = NULL, + .config = NULL }; const device_t ns8250_pcjr_device = { - "National Semiconductor 8250(-compatible) UART for PCjr", - "ns8250_pcjr", - DEVICE_PCJR, - SERIAL_8250_PCJR, - serial_init, serial_close, NULL, - { NULL }, serial_speed_changed, NULL, - NULL + .name = "National Semiconductor 8250(-compatible) UART for PCjr", + .internal_name = "ns8250_pcjr", + .flags = DEVICE_PCJR, + .local = SERIAL_8250_PCJR, + .init = serial_init, + .close = serial_close, + .reset = serial_reset, + { .available = NULL }, + .speed_changed = serial_speed_changed, + .force_redraw = NULL, + .config = NULL }; const device_t ns16450_device = { - "National Semiconductor NS16450(-compatible) UART", - "ns16450", - 0, - SERIAL_16450, - serial_init, serial_close, NULL, - { NULL }, serial_speed_changed, NULL, - NULL + .name = "National Semiconductor NS16450(-compatible) UART", + .internal_name = "ns16450", + .flags = 0, + .local = SERIAL_16450, + .init = serial_init, + .close = serial_close, + .reset = serial_reset, + { .available = NULL }, + .speed_changed = serial_speed_changed, + .force_redraw = NULL, + .config = NULL }; const device_t ns16550_device = { - "National Semiconductor NS16550(-compatible) UART", - "ns16550", - 0, - SERIAL_16550, - serial_init, serial_close, NULL, - { NULL }, serial_speed_changed, NULL, - NULL + .name = "National Semiconductor NS16550(-compatible) UART", + .internal_name = "ns16550", + .flags = 0, + .local = SERIAL_16550, + .init = serial_init, + .close = serial_close, + .reset = serial_reset, + { .available = NULL }, + .speed_changed = serial_speed_changed, + .force_redraw = NULL, + .config = NULL }; const device_t ns16650_device = { - "Startech Semiconductor 16650(-compatible) UART", - "ns16650", - 0, - SERIAL_16650, - serial_init, serial_close, NULL, - { NULL }, serial_speed_changed, NULL, - NULL + .name = "Startech Semiconductor 16650(-compatible) UART", + .internal_name = "ns16650", + .flags = 0, + .local = SERIAL_16650, + .init = serial_init, + .close = serial_close, + .reset = serial_reset, + { .available = NULL }, + .speed_changed = serial_speed_changed, + .force_redraw = NULL, + .config = NULL }; const device_t ns16750_device = { - "Texas Instruments 16750(-compatible) UART", - "ns16750", - 0, - SERIAL_16750, - serial_init, serial_close, NULL, - { NULL }, serial_speed_changed, NULL, - NULL + .name = "Texas Instruments 16750(-compatible) UART", + .internal_name = "ns16750", + .flags = 0, + .local = SERIAL_16750, + .init = serial_init, + .close = serial_close, + .reset = serial_reset, + { .available = NULL }, + .speed_changed = serial_speed_changed, + .force_redraw = NULL, + .config = NULL }; const device_t ns16850_device = { - "Exar Corporation NS16850(-compatible) UART", - "ns16850", - 0, - SERIAL_16850, - serial_init, serial_close, NULL, - { NULL }, serial_speed_changed, NULL, - NULL + .name = "Exar Corporation NS16850(-compatible) UART", + .internal_name = "ns16850", + .flags = 0, + .local = SERIAL_16850, + .init = serial_init, + .close = serial_close, + .reset = serial_reset, + { .available = NULL }, + .speed_changed = serial_speed_changed, + .force_redraw = NULL, + .config = NULL }; const device_t ns16950_device = { - "Oxford Semiconductor NS16950(-compatible) UART", - "ns16950", - 0, - SERIAL_16950, - serial_init, serial_close, NULL, - { NULL }, serial_speed_changed, NULL, - NULL + .name = "Oxford Semiconductor NS16950(-compatible) UART", + .internal_name = "ns16950", + .flags = 0, + .local = SERIAL_16950, + .init = serial_init, + .close = serial_close, + .reset = serial_reset, + { .available = NULL }, + .speed_changed = serial_speed_changed, + .force_redraw = NULL, + .config = NULL }; diff --git a/src/device/serial_passthrough.c b/src/device/serial_passthrough.c new file mode 100644 index 000000000..1b1c5e3bf --- /dev/null +++ b/src/device/serial_passthrough.c @@ -0,0 +1,383 @@ +/* + * 86Box A hypervisor and IBM PC system emulator that specializes in + * running old operating systems and software designed for IBM + * PC systems and compatibles from 1981 through fairly recent + * system designs based on the PCI bus. + * + * This file is part of the 86Box distribution. + * + * Implementation of Serial passthrough device. + * + * + * Authors: Andreas J. Reichel , + * Jasmine Iwanek + * + * Copyright 2021 Andreas J. Reichel. + * Copyright 2021-2022 Jasmine Iwanek. + */ + +#include +#include +#include +#include +#include +#include +#define HAVE_STDARG_H +#include <86box/86box.h> +#include <86box/device.h> +#include <86box/fifo.h> +#include <86box/timer.h> +#include <86box/serial.h> +#include <86box/serial_passthrough.h> +#include <86box/plat_serial_passthrough.h> +#include <86box/plat_unused.h> + +#define ENABLE_SERIAL_PASSTHROUGH_LOG 1 +#ifdef ENABLE_SERIAL_PASSTHROUGH_LOG +int serial_passthrough_do_log = ENABLE_SERIAL_PASSTHROUGH_LOG; + +static void +serial_passthrough_log(const char *fmt, ...) +{ + va_list ap; + + if (serial_passthrough_do_log) { + va_start(ap, fmt); + pclog_ex(fmt, ap); + va_end(ap); + } +} +#else +# define serial_passthrough_log(fmt, ...) +#endif + +void +serial_passthrough_init(void) +{ + for (uint8_t c = 0; c < SERIAL_MAX; c++) { + if (serial_passthrough_enabled[c]) { + /* Instance n for COM n */ + device_add_inst(&serial_passthrough_device, c + 1); + } + } +} + +static void +serial_passthrough_write(UNUSED(serial_t *s), void *priv, uint8_t val) +{ + plat_serpt_write(priv, val); +} + +static void +host_to_serial_cb(void *priv) +{ + serial_passthrough_t *dev = (serial_passthrough_t *) priv; + + uint8_t byte; + + /* write_fifo has no failure indication, but if we write to fast, the host + * can never fetch the bytes in time, so check if the fifo is full if in + * fifo mode or if lsr has bit 0 set if not in fifo mode */ + if ((dev->serial->type >= SERIAL_16550) && dev->serial->fifo_enabled) { + if (fifo_get_full(dev->serial->rcvr_fifo)) { + goto no_write_to_machine; + } + } else { + if (dev->serial->lsr & 1) { + goto no_write_to_machine; + } + } + if (plat_serpt_read(dev, &byte)) { +#if 0 + printf("got byte %02X\n", byte); +#endif + serial_write_fifo(dev->serial, byte); +#if 0 + serial_set_dsr(dev->serial, 1); +#endif + } +no_write_to_machine: +#if 0 + serial_device_timeout(dev->serial); +#endif + timer_on_auto(&dev->host_to_serial_timer, (1000000.0 / dev->baudrate) * (double) dev->bits); +} + +static void +serial_passthrough_rcr_cb(UNUSED(struct serial_s *serial), void *priv) +{ + serial_passthrough_t *dev = (serial_passthrough_t *) priv; + + timer_stop(&dev->host_to_serial_timer); + /* FIXME: do something to dev->baudrate */ + timer_on_auto(&dev->host_to_serial_timer, (1000000.0 / dev->baudrate) * (double) dev->bits); +#if 0 + serial_clear_fifo(dev->serial); +#endif +} + +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 */ + timer_on_auto(&dev->host_to_serial_timer, (1000000.0 / dev->baudrate) * (double) dev->bits); +#if 0 + serial_clear_fifo(dev->serial); +#endif +} + +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->serial && dev->serial->sd) + memset(dev->serial->sd, 0, sizeof(serial_device_t)); + + plat_serpt_close(dev); + free(dev); +} + +void +serial_passthrough_transmit_period(UNUSED(serial_t *serial), void *priv, double transmit_period) +{ + serial_passthrough_t *dev = (serial_passthrough_t *) priv; + + if (dev->mode != SERPT_MODE_HOSTSER) + return; + dev->baudrate = 1000000.0 / transmit_period; + + serial_passthrough_speed_changed(priv); + plat_serpt_set_params(dev); +} + +void +serial_passthrough_lcr_callback(serial_t *serial, void *priv, uint8_t lcr) +{ + serial_passthrough_t *dev = (serial_passthrough_t *) priv; + + if (dev->mode != SERPT_MODE_HOSTSER) + return; + dev->bits = serial->bits; + dev->data_bits = ((lcr & 0x03) + 5); + serial_passthrough_speed_changed(priv); + plat_serpt_set_params(dev); +} + +/* Initialize the device for use by the user. */ +static void * +serial_passthrough_dev_init(const device_t *info) +{ + serial_passthrough_t *dev; + + dev = (serial_passthrough_t *) malloc(sizeof(serial_passthrough_t)); + memset(dev, 0, sizeof(serial_passthrough_t)); + dev->mode = device_get_config_int("mode"); + + dev->port = device_get_instance() - 1; + dev->baudrate = device_get_config_int("baudrate"); + dev->data_bits = device_get_config_int("data_bits"); + + /* 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 + strncpy(dev->named_pipe, device_get_config_string("named_pipe"), 1023); +#endif + + serial_passthrough_log("%s: port=COM%d\n", info->name, dev->port + 1); + serial_passthrough_log("%s: baud=%f\n", info->name, dev->baudrate); + serial_passthrough_log("%s: mode=%s\n", info->name, serpt_mode_names[dev->mode]); + + if (plat_serpt_open_device(dev)) { + serial_passthrough_log("%s: not running\n", info->name); + return NULL; + } + serial_passthrough_log("%s: running\n", info->name); + + memset(&dev->host_to_serial_timer, 0, sizeof(pc_timer_t)); + timer_add(&dev->host_to_serial_timer, host_to_serial_cb, dev, 1); + serial_set_cts(dev->serial, 1); + serial_set_dsr(dev->serial, 1); + serial_set_dcd(dev->serial, 1); + + /* 1 start bit + data bits + stop bits (no parity assumed) */ + dev->bits = 1 + device_get_config_int("data_bits") + device_get_config_int("stop_bits"); + + /* Return our private data to the I/O layer. */ + return dev; +} + +const char *serpt_mode_names[SERPT_MODES_MAX] = { + [SERPT_MODE_VCON] = "vcon", + [SERPT_MODE_TCPSRV] = "tcpsrv", + [SERPT_MODE_TCPCLNT] = "tcpclnt", + [SERPT_MODE_HOSTSER] = "hostser", +}; + +// clang-format off +static const device_config_t serial_passthrough_config[] = { + { + .name = "mode", + .description = "Passthrough Mode", + .type = CONFIG_SELECTION, + .default_string = "", + .default_int = 0, + .file_filter = "", + .spinner = { 0 }, + .selection = { +#ifdef _WIN32 + { + .description = "Named Pipe (Server)", + .value = SERPT_MODE_VCON + }, +#if 0 /* TODO */ + { + .description = "Named Pipe (Client)", + .value = SERPT_MODE_VCON + }, +#endif +#else + { + .description = "Pseudo Terminal/Virtual Console", + .value = SERPT_MODE_VCON + }, +#endif +#if 0 /* TODO */ + { + .description = "TCP Server", + .value = SERPT_MODE_TCPSRV + }, + { + .description = "TCP Client", + .value = SERPT_MODE_TCPCLNT + }, +#endif + { + .description = "Host Serial Passthrough", + .value = SERPT_MODE_HOSTSER + }, + { + .description = "" + } + } + }, + { + .name = "host_serial_path", + .description = "Host Serial Device", + .type = CONFIG_SERPORT, + .default_string = "", + .file_filter = NULL, + .spinner = {}, + .selection = {} + }, +#ifdef _WIN32 + { + .name = "named_pipe", + .description = "Name of pipe", + .type = CONFIG_STRING, + .default_string = "\\\\.\\pipe\\86Box\\test", + .file_filter = NULL, + .spinner = {}, + .selection = {} + }, +#endif + { + .name = "data_bits", + .description = "Data bits", + .type = CONFIG_SELECTION, + .default_string = "8", + .default_int = 8, + .file_filter = NULL, + .spinner = { 0 }, + .selection = { +#if 0 /* Mentioned by WFW 3.1x, not supported, atleast on Linux */ + { .description = "4", .value = 4 }, +#endif + { .description = "5", .value = 5 }, + { .description = "6", .value = 6 }, + { .description = "7", .value = 7 }, + { .description = "8", .value = 8 } + } + }, + { + .name = "stop_bits", + .description = "Stop bits", + .type = CONFIG_SELECTION, + .default_string = "1", + .default_int = 1, + .file_filter = NULL, + .spinner = { 0 }, + .selection = { + { .description = "1", .value = 1 }, +#if 0 + { .description = "1.5", .value = 1.5 }, +#endif + { .description = "2", .value = 2 } + } + }, + { + .name = "baudrate", + .description = "Baud Rate of Passthrough", + .type = CONFIG_SELECTION, + .default_string = "", + .default_int = 115200, + .file_filter = NULL, + .spinner = { 0 }, + .selection = { +#if 0 + { .description = "256000", .value = 256000 }, + { .description = "128000", .value = 128000 }, +#endif + { .description = "115200", .value = 115200 }, + { .description = "57600", .value = 57600 }, + { .description = "56000", .value = 56000 }, + { .description = "38400", .value = 38400 }, + { .description = "19200", .value = 19200 }, + { .description = "14400", .value = 14400 }, + { .description = "9600", .value = 9600 }, + { .description = "7200", .value = 7200 }, + { .description = "4800", .value = 4800 }, + { .description = "2400", .value = 2400 }, + { .description = "1800", .value = 1800 }, + { .description = "1200", .value = 1200 }, + { .description = "600", .value = 600 }, + { .description = "300", .value = 300 }, + { .description = "150", .value = 150 }, +#if 0 + { .description = "134.5", .value = 134.5 }, +#endif + { .description = "110", .value = 110 }, + { .description = "75", .value = 75 } + } + }, + { .name = "", .description = "", .type = CONFIG_END } +}; +// clang-format on + +const device_t serial_passthrough_device = { + .name = "Serial Passthrough Device", + .flags = 0, + .local = 0, + .init = serial_passthrough_dev_init, + .close = serial_passthrough_dev_close, + .reset = NULL, + { .poll = NULL }, + .speed_changed = serial_passthrough_speed_changed, + .force_redraw = NULL, + .config = serial_passthrough_config +}; diff --git a/src/device/smbus_ali7101.c b/src/device/smbus_ali7101.c index 5733c46eb..349de470d 100644 --- a/src/device/smbus_ali7101.c +++ b/src/device/smbus_ali7101.c @@ -1,19 +1,19 @@ /* - * 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. + * 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. + * This file is part of the 86Box distribution. * - * Implementation of a generic ALi M7101-compatible SMBus host - * controller. + * Implementation of a generic ALi M7101-compatible SMBus host + * controller. * - * Authors: RichardG, - * Miran Grca, + * Authors: RichardG, + * Miran Grca, * - * Copyright 2020,2021 RichardG. - * Copyright 2021 Miran Grca. + * Copyright 2020-2021 RichardG. + * Copyright 2021 Miran Grca. */ #include #include @@ -28,60 +28,61 @@ #include <86box/timer.h> #include <86box/i2c.h> #include <86box/smbus.h> - +#include <86box/plat_fallthrough.h> #ifdef ENABLE_SMBUS_ALI7101_LOG int smbus_ali7101_do_log = ENABLE_SMBUS_ALI7101_LOG; - static void smbus_ali7101_log(const char *fmt, ...) { va_list ap; if (smbus_ali7101_do_log) { - va_start(ap, fmt); - pclog_ex(fmt, ap); - va_end(ap); + va_start(ap, fmt); + pclog_ex(fmt, ap); + va_end(ap); } } #else -#define smbus_ali7101_log(fmt, ...) +# define smbus_ali7101_log(fmt, ...) #endif - static uint8_t smbus_ali7101_read(uint16_t addr, void *priv) { smbus_ali7101_t *dev = (smbus_ali7101_t *) priv; - uint8_t ret = 0x00; + uint8_t ret = 0x00; switch (addr - dev->io_base) { - case 0x00: - ret = dev->stat; - break; + case 0x00: + ret = dev->stat; + break; - case 0x03: - ret = dev->addr; - break; + case 0x03: + ret = dev->addr; + break; - case 0x04: - ret = dev->data0; - break; + case 0x04: + ret = dev->data0; + break; - case 0x05: - ret = dev->data1; - break; + case 0x05: + ret = dev->data1; + break; - case 0x06: - ret = dev->data[dev->index++]; - if (dev->index >= SMBUS_ALI7101_BLOCK_DATA_SIZE) - dev->index = 0; - break; + case 0x06: + ret = dev->data[dev->index++]; + if (dev->index >= SMBUS_ALI7101_BLOCK_DATA_SIZE) + dev->index = 0; + break; - case 0x07: - ret = dev->cmd; - break; + case 0x07: + ret = dev->cmd; + break; + + default: + break; } smbus_ali7101_log("SMBus ALI7101: read(%02X) = %02x\n", addr, ret); @@ -89,152 +90,155 @@ smbus_ali7101_read(uint16_t addr, void *priv) return ret; } - static void smbus_ali7101_write(uint16_t addr, uint8_t val, void *priv) { smbus_ali7101_t *dev = (smbus_ali7101_t *) priv; - uint8_t smbus_addr, cmd, read, prev_stat; - uint16_t timer_bytes = 0; + uint8_t smbus_addr; + uint8_t cmd; + uint8_t read; + uint8_t prev_stat; + uint16_t timer_bytes = 0; smbus_ali7101_log("SMBus ALI7101: write(%02X, %02X)\n", addr, val); - prev_stat = dev->next_stat; + prev_stat = dev->next_stat; dev->next_stat = 0x04; switch (addr - dev->io_base) { - case 0x00: - dev->stat &= ~(val & 0xf2); - /* Make sure IDLE is set if we're not busy or errored. */ - if (dev->stat == 0x00) - dev->stat = 0x04; - break; + case 0x00: + dev->stat &= ~(val & 0xf2); + /* Make sure IDLE is set if we're not busy or errored. */ + if (dev->stat == 0x00) + dev->stat = 0x04; + break; - case 0x01: - dev->ctl = val & 0xfc; - if (val & 0x04) { /* cancel an in-progress command if KILL is set */ - if (prev_stat) { /* cancel only if a command is in progress */ - timer_disable(&dev->response_timer); - dev->stat = 0x80; /* raise FAILED */ - } - } else if (val & 0x08) { /* T_OUT_CMD */ - if (prev_stat) { /* cancel only if a command is in progress */ - timer_disable(&dev->response_timer); - dev->stat = 0x20; /* raise DEVICE_ERR */ - } - } + case 0x01: + dev->ctl = val & 0xfc; + if (val & 0x04) { /* cancel an in-progress command if KILL is set */ + if (prev_stat) { /* cancel only if a command is in progress */ + timer_disable(&dev->response_timer); + dev->stat = 0x80; /* raise FAILED */ + } + } else if (val & 0x08) { /* T_OUT_CMD */ + if (prev_stat) { /* cancel only if a command is in progress */ + timer_disable(&dev->response_timer); + dev->stat = 0x20; /* raise DEVICE_ERR */ + } + } - if (val & 0x80) - dev->index = 0; - break; + if (val & 0x80) + dev->index = 0; + break; - case 0x02: - /* dispatch command if START is set */ - timer_bytes++; /* address */ + case 0x02: + /* dispatch command if START is set */ + timer_bytes++; /* address */ - smbus_addr = (dev->addr >> 1); - read = dev->addr & 0x01; + smbus_addr = (dev->addr >> 1); + read = dev->addr & 0x01; - cmd = (dev->ctl >> 4) & 0x7; - smbus_ali7101_log("SMBus ALI7101: addr=%02X read=%d protocol=%X cmd=%02X data0=%02X data1=%02X\n", smbus_addr, read, cmd, dev->cmd, dev->data0, dev->data1); + cmd = (dev->ctl >> 4) & 0x7; + smbus_ali7101_log("SMBus ALI7101: addr=%02X read=%d protocol=%X cmd=%02X data0=%02X data1=%02X\n", smbus_addr, read, cmd, dev->cmd, dev->data0, dev->data1); - /* Raise DEV_ERR if no device is at this address, or if the device returned NAK when starting the transfer. */ - if (!i2c_start(i2c_smbus, smbus_addr, read)) { - dev->next_stat = 0x40; - break; - } + /* Raise DEV_ERR if no device is at this address, or if the device returned NAK when starting the transfer. */ + if (!i2c_start(i2c_smbus, smbus_addr, read)) { + dev->next_stat = 0x40; + break; + } - dev->next_stat = 0x10; /* raise INTER (command completed) by default */ + dev->next_stat = 0x10; /* raise INTER (command completed) by default */ - /* Decode the command protocol. */ - switch (cmd) { - case 0x0: /* quick R/W */ - break; + /* Decode the command protocol. */ + switch (cmd) { + case 0x0: /* quick R/W */ + break; - case 0x1: /* byte R/W */ - if (read) /* byte read */ - dev->data0 = i2c_read(i2c_smbus, smbus_addr); - else /* byte write */ - i2c_write(i2c_smbus, smbus_addr, dev->data0); - timer_bytes++; + case 0x1: /* byte R/W */ + if (read) /* byte read */ + dev->data0 = i2c_read(i2c_smbus, smbus_addr); + else /* byte write */ + i2c_write(i2c_smbus, smbus_addr, dev->data0); + timer_bytes++; - break; + break; - case 0x2: /* byte data R/W */ - /* command write */ - i2c_write(i2c_smbus, smbus_addr, dev->cmd); - timer_bytes++; + case 0x2: /* byte data R/W */ + /* command write */ + i2c_write(i2c_smbus, smbus_addr, dev->cmd); + timer_bytes++; - if (read) /* byte read */ - dev->data0 = i2c_read(i2c_smbus, smbus_addr); - else /* byte write */ - i2c_write(i2c_smbus, smbus_addr, dev->data0); - timer_bytes++; + if (read) /* byte read */ + dev->data0 = i2c_read(i2c_smbus, smbus_addr); + else /* byte write */ + i2c_write(i2c_smbus, smbus_addr, dev->data0); + timer_bytes++; - break; + break; - case 0x3: /* word data R/W */ - /* command write */ - i2c_write(i2c_smbus, smbus_addr, dev->cmd); - timer_bytes++; + case 0x3: /* word data R/W */ + /* command write */ + i2c_write(i2c_smbus, smbus_addr, dev->cmd); + timer_bytes++; - if (read) { /* word read */ - dev->data0 = i2c_read(i2c_smbus, smbus_addr); - dev->data1 = i2c_read(i2c_smbus, smbus_addr); - } else { /* word write */ - i2c_write(i2c_smbus, smbus_addr, dev->data0); - i2c_write(i2c_smbus, smbus_addr, dev->data1); - } - timer_bytes += 2; + if (read) { /* word read */ + dev->data0 = i2c_read(i2c_smbus, smbus_addr); + dev->data1 = i2c_read(i2c_smbus, smbus_addr); + } else { /* word write */ + i2c_write(i2c_smbus, smbus_addr, dev->data0); + i2c_write(i2c_smbus, smbus_addr, dev->data1); + } + timer_bytes += 2; - break; + break; - case 0x4: /* block R/W */ - timer_bytes++; /* count the SMBus length byte now */ + case 0x4: /* block R/W */ + timer_bytes++; /* count the SMBus length byte now */ + fallthrough; - /* fall-through */ + default: /* unknown */ + dev->next_stat = 0x20; /* raise DEV_ERR */ + timer_bytes = 0; + break; + } - default: /* unknown */ - dev->next_stat = 0x20; /* raise DEV_ERR */ - timer_bytes = 0; - break; - } + /* Finish transfer. */ + i2c_stop(i2c_smbus, smbus_addr); + break; - /* Finish transfer. */ - i2c_stop(i2c_smbus, smbus_addr); - break; + case 0x03: + dev->addr = val; + break; - case 0x03: - dev->addr = val; - break; + case 0x04: + dev->data0 = val; + break; - case 0x04: - dev->data0 = val; - break; + case 0x05: + dev->data1 = val; + break; - case 0x05: - dev->data1 = val; - break; + case 0x06: + dev->data[dev->index++] = val; + if (dev->index >= SMBUS_ALI7101_BLOCK_DATA_SIZE) + dev->index = 0; + break; - case 0x06: - dev->data[dev->index++] = val; - if (dev->index >= SMBUS_ALI7101_BLOCK_DATA_SIZE) - dev->index = 0; - break; + case 0x07: + dev->cmd = val; + break; - case 0x07: - dev->cmd = val; - break; + default: + break; } if (dev->next_stat != 0x04) { /* schedule dispatch of any pending status register update */ - dev->stat = 0x08; /* raise HOST_BUSY while waiting */ - timer_disable(&dev->response_timer); - /* delay = ((half clock for start + half clock for stop) + (bytes * (8 bits + ack))) * 60us period measured on real VIA 686B */ - timer_set_delay_u64(&dev->response_timer, (1 + (timer_bytes * 9)) * 60 * TIMER_USEC); + dev->stat = 0x08; /* raise HOST_BUSY while waiting */ + timer_disable(&dev->response_timer); + /* delay = ((half clock for start + half clock for stop) + (bytes * (8 bits + ack))) * 60us period measured on real VIA 686B */ + timer_set_delay_u64(&dev->response_timer, (1 + (timer_bytes * 9)) * 60 * TIMER_USEC); } } - static void smbus_ali7101_response(void *priv) { @@ -244,21 +248,19 @@ smbus_ali7101_response(void *priv) dev->stat = dev->next_stat; } - void smbus_ali7101_remap(smbus_ali7101_t *dev, uint16_t new_io_base, uint8_t enable) { if (dev->io_base) - io_removehandler(dev->io_base, 0x10, smbus_ali7101_read, NULL, NULL, smbus_ali7101_write, NULL, NULL, dev); + io_removehandler(dev->io_base, 0x10, smbus_ali7101_read, NULL, NULL, smbus_ali7101_write, NULL, NULL, dev); dev->io_base = new_io_base; smbus_ali7101_log("SMBus ALI7101: remap to %04Xh (%sabled)\n", dev->io_base, enable ? "en" : "dis"); if (enable && dev->io_base) - io_sethandler(dev->io_base, 0x10, smbus_ali7101_read, NULL, NULL, smbus_ali7101_write, NULL, NULL, dev); + io_sethandler(dev->io_base, 0x10, smbus_ali7101_read, NULL, NULL, smbus_ali7101_write, NULL, NULL, dev); } - static void smbus_ali7101_reset(void *priv) { @@ -268,7 +270,6 @@ smbus_ali7101_reset(void *priv) dev->stat = 0x04; } - static void * smbus_ali7101_init(const device_t *info) { @@ -276,7 +277,7 @@ smbus_ali7101_init(const device_t *info) memset(dev, 0, sizeof(smbus_ali7101_t)); dev->local = info->local; - dev->stat = 0x04; + dev->stat = 0x04; /* We save the I2C bus handle on dev but use i2c_smbus for all operations because dev and therefore dev->i2c will be invalidated if a device triggers a hard reset. */ i2c_smbus = dev->i2c = i2c_addbus("smbus_ali7101"); @@ -286,26 +287,28 @@ smbus_ali7101_init(const device_t *info) return dev; } - static void smbus_ali7101_close(void *priv) { smbus_ali7101_t *dev = (smbus_ali7101_t *) priv; if (i2c_smbus == dev->i2c) - i2c_smbus = NULL; + i2c_smbus = NULL; i2c_removebus(dev->i2c); free(dev); } - const device_t ali7101_smbus_device = { - "ALi M7101-compatible SMBus Host Controller", - "ali7101_smbus", - DEVICE_AT, - 0, - smbus_ali7101_init, smbus_ali7101_close, smbus_ali7101_reset, - { NULL }, NULL, NULL, - NULL + .name = "ALi M7101-compatible SMBus Host Controller", + .internal_name = "ali7101_smbus", + .flags = DEVICE_AT, + .local = 0, + .init = smbus_ali7101_init, + .close = smbus_ali7101_close, + .reset = smbus_ali7101_reset, + { .available = NULL }, + .speed_changed = NULL, + .force_redraw = NULL, + .config = NULL }; diff --git a/src/device/smbus_piix4.c b/src/device/smbus_piix4.c index 0b2416ad7..6f2b1632e 100644 --- a/src/device/smbus_piix4.c +++ b/src/device/smbus_piix4.c @@ -1,18 +1,18 @@ /* - * 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. + * 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. + * This file is part of the 86Box distribution. * - * Implementation of a generic PIIX4-compatible SMBus host controller. + * Implementation of a generic PIIX4-compatible SMBus host controller. * * * - * Authors: RichardG, + * Authors: RichardG, * - * Copyright 2020 RichardG. + * Copyright 2020 RichardG. */ #include #include @@ -27,65 +27,66 @@ #include <86box/timer.h> #include <86box/i2c.h> #include <86box/smbus.h> - +#include <86box/plat_fallthrough.h> #ifdef ENABLE_SMBUS_PIIX4_LOG int smbus_piix4_do_log = ENABLE_SMBUS_PIIX4_LOG; - static void smbus_piix4_log(const char *fmt, ...) { va_list ap; if (smbus_piix4_do_log) { - va_start(ap, fmt); - pclog_ex(fmt, ap); - va_end(ap); + va_start(ap, fmt); + pclog_ex(fmt, ap); + va_end(ap); } } #else -#define smbus_piix4_log(fmt, ...) +# define smbus_piix4_log(fmt, ...) #endif - static uint8_t smbus_piix4_read(uint16_t addr, void *priv) { smbus_piix4_t *dev = (smbus_piix4_t *) priv; - uint8_t ret = 0x00; + uint8_t ret = 0x00; switch (addr - dev->io_base) { - case 0x00: - ret = dev->stat; - break; + case 0x00: + ret = dev->stat; + break; - case 0x02: - dev->index = 0; /* reading from this resets the block data index */ - ret = dev->ctl; - break; + case 0x02: + dev->index = 0; /* reading from this resets the block data index */ + ret = dev->ctl; + break; - case 0x03: - ret = dev->cmd; - break; + case 0x03: + ret = dev->cmd; + break; - case 0x04: - ret = dev->addr; - break; + case 0x04: + ret = dev->addr; + break; - case 0x05: - ret = dev->data0; - break; + case 0x05: + ret = dev->data0; + break; - case 0x06: - ret = dev->data1; - break; + case 0x06: + ret = dev->data1; + break; - case 0x07: - ret = dev->data[dev->index++]; - if (dev->index >= SMBUS_PIIX4_BLOCK_DATA_SIZE) - dev->index = 0; - break; + case 0x07: + ret = dev->data[dev->index++]; + if (dev->index >= SMBUS_PIIX4_BLOCK_DATA_SIZE) + dev->index = 0; + break; + + default: + break; } smbus_piix4_log("SMBus PIIX4: read(%02X) = %02x\n", addr, ret); @@ -93,232 +94,235 @@ smbus_piix4_read(uint16_t addr, void *priv) return ret; } - static void smbus_piix4_write(uint16_t addr, uint8_t val, void *priv) { smbus_piix4_t *dev = (smbus_piix4_t *) priv; - uint8_t smbus_addr, cmd, read, block_len, prev_stat; - uint16_t timer_bytes = 0, i; + uint8_t smbus_addr; + uint8_t cmd; + uint8_t read; + uint8_t block_len; + uint8_t prev_stat; + uint16_t timer_bytes = 0; + uint16_t i = 0; smbus_piix4_log("SMBus PIIX4: write(%02X, %02X)\n", addr, val); - prev_stat = dev->next_stat; + prev_stat = dev->next_stat; dev->next_stat = 0x00; switch (addr - dev->io_base) { - case 0x00: - for (smbus_addr = 0x02; smbus_addr <= 0x10; smbus_addr <<= 1) { /* handle clearable bits */ - if (val & smbus_addr) - dev->stat &= ~smbus_addr; - } - break; + case 0x00: + for (smbus_addr = 0x02; smbus_addr <= 0x10; smbus_addr <<= 1) { /* handle clearable bits */ + if (val & smbus_addr) + dev->stat &= ~smbus_addr; + } + break; - case 0x02: - dev->ctl = val & ((dev->local == SMBUS_VIA) ? 0x3f : 0x1f); - if (val & 0x02) { /* cancel an in-progress command if KILL is set */ - if (prev_stat) { /* cancel only if a command is in progress */ - timer_disable(&dev->response_timer); - dev->stat = 0x10; /* raise FAILED */ - } - } - if (val & 0x40) { /* dispatch command if START is set */ - timer_bytes++; /* address */ + case 0x02: + dev->ctl = val & ((dev->local == SMBUS_VIA) ? 0x3f : 0x1f); + if (val & 0x02) { /* cancel an in-progress command if KILL is set */ + if (prev_stat) { /* cancel only if a command is in progress */ + timer_disable(&dev->response_timer); + dev->stat = 0x10; /* raise FAILED */ + } + } + if (val & 0x40) { /* dispatch command if START is set */ + timer_bytes++; /* address */ - smbus_addr = dev->addr >> 1; - read = dev->addr & 0x01; + smbus_addr = dev->addr >> 1; + read = dev->addr & 0x01; - cmd = (dev->ctl >> 2) & 0xf; - smbus_piix4_log("SMBus PIIX4: addr=%02X read=%d protocol=%X cmd=%02X data0=%02X data1=%02X\n", smbus_addr, read, cmd, dev->cmd, dev->data0, dev->data1); + cmd = (dev->ctl >> 2) & 0xf; + smbus_piix4_log("SMBus PIIX4: addr=%02X read=%d protocol=%X cmd=%02X data0=%02X data1=%02X\n", smbus_addr, read, cmd, dev->cmd, dev->data0, dev->data1); - /* Raise DEV_ERR if no device is at this address, or if the device returned NAK. */ - if (!i2c_start(i2c_smbus, smbus_addr, read)) { - dev->next_stat = 0x04; - break; - } + /* Raise DEV_ERR if no device is at this address, or if the device returned NAK. */ + if (!i2c_start(i2c_smbus, smbus_addr, read)) { + dev->next_stat = 0x04; + break; + } - dev->next_stat = 0x02; /* raise INTER (command completed) by default */ + dev->next_stat = 0x02; /* raise INTER (command completed) by default */ - /* Decode the command protocol. - VIA-specific modes (0x4 and [0x6:0xf]) are undocumented and required real hardware research. */ - switch (cmd) { - case 0x0: /* quick R/W */ - break; + /* Decode the command protocol. + VIA-specific modes (0x4 and [0x6:0xf]) are undocumented and required real hardware research. */ + switch (cmd) { + case 0x0: /* quick R/W */ + break; - case 0x1: /* byte R/W */ - if (read) /* byte read */ - dev->data0 = i2c_read(i2c_smbus, smbus_addr); - else /* byte write */ - i2c_write(i2c_smbus, smbus_addr, dev->data0); - timer_bytes++; + case 0x1: /* byte R/W */ + if (read) /* byte read */ + dev->data0 = i2c_read(i2c_smbus, smbus_addr); + else /* byte write */ + i2c_write(i2c_smbus, smbus_addr, dev->data0); + timer_bytes++; - break; + break; - case 0x2: /* byte data R/W */ - /* command write */ - i2c_write(i2c_smbus, smbus_addr, dev->cmd); - timer_bytes++; + case 0x2: /* byte data R/W */ + /* command write */ + i2c_write(i2c_smbus, smbus_addr, dev->cmd); + timer_bytes++; - if (read) /* byte read */ - dev->data0 = i2c_read(i2c_smbus, smbus_addr); - else /* byte write */ - i2c_write(i2c_smbus, smbus_addr, dev->data0); - timer_bytes++; + if (read) /* byte read */ + dev->data0 = i2c_read(i2c_smbus, smbus_addr); + else /* byte write */ + i2c_write(i2c_smbus, smbus_addr, dev->data0); + timer_bytes++; - break; + break; - case 0x3: /* word data R/W */ - /* command write */ - i2c_write(i2c_smbus, smbus_addr, dev->cmd); - timer_bytes++; + case 0x3: /* word data R/W */ + /* command write */ + i2c_write(i2c_smbus, smbus_addr, dev->cmd); + timer_bytes++; - if (read) { /* word read */ - dev->data0 = i2c_read(i2c_smbus, smbus_addr); - dev->data1 = i2c_read(i2c_smbus, smbus_addr); - } else { /* word write */ - i2c_write(i2c_smbus, smbus_addr, dev->data0); - i2c_write(i2c_smbus, smbus_addr, dev->data1); - } - timer_bytes += 2; + if (read) { /* word read */ + dev->data0 = i2c_read(i2c_smbus, smbus_addr); + dev->data1 = i2c_read(i2c_smbus, smbus_addr); + } else { /* word write */ + i2c_write(i2c_smbus, smbus_addr, dev->data0); + i2c_write(i2c_smbus, smbus_addr, dev->data1); + } + timer_bytes += 2; - break; + break; - case 0x4: /* process call */ - if (dev->local != SMBUS_VIA) /* VIA only */ - goto unknown_protocol; + case 0x4: /* process call */ + if (dev->local != SMBUS_VIA) /* VIA only */ + goto unknown_protocol; - if (!read) { /* command write (only when writing) */ - i2c_write(i2c_smbus, smbus_addr, dev->cmd); - timer_bytes++; - } + if (!read) { /* command write (only when writing) */ + i2c_write(i2c_smbus, smbus_addr, dev->cmd); + timer_bytes++; + } + fallthrough; - /* fall-through */ + case 0xc: /* I2C process call */ + if (!read) { /* word write (only when writing) */ + i2c_write(i2c_smbus, smbus_addr, dev->data0); + i2c_write(i2c_smbus, smbus_addr, dev->data1); + timer_bytes += 2; + } - case 0xc: /* I2C process call */ - if (!read) { /* word write (only when writing) */ - i2c_write(i2c_smbus, smbus_addr, dev->data0); - i2c_write(i2c_smbus, smbus_addr, dev->data1); - timer_bytes += 2; - } + /* word read */ + dev->data0 = i2c_read(i2c_smbus, smbus_addr); + dev->data1 = i2c_read(i2c_smbus, smbus_addr); + timer_bytes += 2; - /* word read */ - dev->data0 = i2c_read(i2c_smbus, smbus_addr); - dev->data1 = i2c_read(i2c_smbus, smbus_addr); - timer_bytes += 2; + break; - break; + case 0x5: /* block R/W */ + timer_bytes++; /* count the SMBus length byte now */ + fallthrough; - case 0x5: /* block R/W */ - timer_bytes++; /* count the SMBus length byte now */ + case 0xd: /* I2C block R/W */ + i2c_write(i2c_smbus, smbus_addr, dev->cmd); + timer_bytes++; - /* fall-through */ + if (read) { + /* block read [data0] (I2C) or [first byte] (SMBus) bytes */ + if (cmd == 0x5) + dev->data0 = i2c_read(i2c_smbus, smbus_addr); + for (i = 0; i < dev->data0; i++) + dev->data[i & SMBUS_PIIX4_BLOCK_DATA_MASK] = i2c_read(i2c_smbus, smbus_addr); + } else { + if (cmd == 0x5) /* send length [data0] as first byte on SMBus */ + i2c_write(i2c_smbus, smbus_addr, dev->data0); + /* block write [data0] bytes */ + for (i = 0; i < dev->data0; i++) { + if (!i2c_write(i2c_smbus, smbus_addr, dev->data[i & SMBUS_PIIX4_BLOCK_DATA_MASK])) + break; + } + } + timer_bytes += i; - case 0xd: /* I2C block R/W */ - i2c_write(i2c_smbus, smbus_addr, dev->cmd); - timer_bytes++; + break; - if (read) { - /* block read [data0] (I2C) or [first byte] (SMBus) bytes */ - if (cmd == 0x5) - dev->data0 = i2c_read(i2c_smbus, smbus_addr); - for (i = 0; i < dev->data0; i++) - dev->data[i & SMBUS_PIIX4_BLOCK_DATA_MASK] = i2c_read(i2c_smbus, smbus_addr); - } else { - if (cmd == 0x5) /* send length [data0] as first byte on SMBus */ - i2c_write(i2c_smbus, smbus_addr, dev->data0); - /* block write [data0] bytes */ - for (i = 0; i < dev->data0; i++) { - if (!i2c_write(i2c_smbus, smbus_addr, dev->data[i & SMBUS_PIIX4_BLOCK_DATA_MASK])) - break; - } - } - timer_bytes += i; + case 0x6: /* I2C with 10-bit address */ + if (dev->local != SMBUS_VIA) /* VIA only */ + goto unknown_protocol; - break; + /* command write */ + i2c_write(i2c_smbus, smbus_addr, dev->cmd); + timer_bytes++; + fallthrough; - case 0x6: /* I2C with 10-bit address */ - if (dev->local != SMBUS_VIA) /* VIA only */ - goto unknown_protocol; + case 0xe: /* I2C with 7-bit address */ + if (!read) { /* word write (only when writing) */ + i2c_write(i2c_smbus, smbus_addr, dev->data0); + i2c_write(i2c_smbus, smbus_addr, dev->data1); + timer_bytes += 2; + } - /* command write */ - i2c_write(i2c_smbus, smbus_addr, dev->cmd); - timer_bytes++; + /* block read [first byte] bytes */ + block_len = dev->data[0]; + for (i = 0; i < block_len; i++) + dev->data[i & SMBUS_PIIX4_BLOCK_DATA_MASK] = i2c_read(i2c_smbus, smbus_addr); + timer_bytes += i; - /* fall-through */ + break; - case 0xe: /* I2C with 7-bit address */ - if (!read) { /* word write (only when writing) */ - i2c_write(i2c_smbus, smbus_addr, dev->data0); - i2c_write(i2c_smbus, smbus_addr, dev->data1); - timer_bytes += 2; - } + case 0xf: /* universal */ + /* block write [data0] bytes */ + for (i = 0; i < dev->data0; i++) { + if (!i2c_write(i2c_smbus, smbus_addr, dev->data[i & SMBUS_PIIX4_BLOCK_DATA_MASK])) + break; /* write NAK behavior is unknown */ + } + timer_bytes += i; - /* block read [first byte] bytes */ - block_len = dev->data[0]; - for (i = 0; i < block_len; i++) - dev->data[i & SMBUS_PIIX4_BLOCK_DATA_MASK] = i2c_read(i2c_smbus, smbus_addr); - timer_bytes += i; + /* block read [data1] bytes */ + for (i = 0; i < dev->data1; i++) + dev->data[i & SMBUS_PIIX4_BLOCK_DATA_MASK] = i2c_read(i2c_smbus, smbus_addr); + timer_bytes += i; - break; + break; - case 0xf: /* universal */ - /* block write [data0] bytes */ - for (i = 0; i < dev->data0; i++) { - if (!i2c_write(i2c_smbus, smbus_addr, dev->data[i & SMBUS_PIIX4_BLOCK_DATA_MASK])) - break; /* write NAK behavior is unknown */ - } - timer_bytes += i; - - /* block read [data1] bytes */ - for (i = 0; i < dev->data1; i++) - dev->data[i & SMBUS_PIIX4_BLOCK_DATA_MASK] = i2c_read(i2c_smbus, smbus_addr); - timer_bytes += i; - - break; - - default: /* unknown */ + default: /* unknown */ unknown_protocol: - dev->next_stat = 0x04; /* raise DEV_ERR */ - timer_bytes = 0; - break; - } + dev->next_stat = 0x04; /* raise DEV_ERR */ + timer_bytes = 0; + break; + } - /* Finish transfer. */ - i2c_stop(i2c_smbus, smbus_addr); - } - break; + /* Finish transfer. */ + i2c_stop(i2c_smbus, smbus_addr); + } + break; - case 0x03: - dev->cmd = val; - break; + case 0x03: + dev->cmd = val; + break; - case 0x04: - dev->addr = val; - break; + case 0x04: + dev->addr = val; + break; - case 0x05: - dev->data0 = val; - break; + case 0x05: + dev->data0 = val; + break; - case 0x06: - dev->data1 = val; - break; + case 0x06: + dev->data1 = val; + break; - case 0x07: - dev->data[dev->index++] = val; - if (dev->index >= SMBUS_PIIX4_BLOCK_DATA_SIZE) - dev->index = 0; - break; + case 0x07: + dev->data[dev->index++] = val; + if (dev->index >= SMBUS_PIIX4_BLOCK_DATA_SIZE) + dev->index = 0; + break; + + default: + break; } if (dev->next_stat) { /* schedule dispatch of any pending status register update */ - dev->stat = 0x01; /* raise HOST_BUSY while waiting */ - timer_disable(&dev->response_timer); - /* delay = ((half clock for start + half clock for stop) + (bytes * (8 bits + ack))) * bit period in usecs */ - timer_set_delay_u64(&dev->response_timer, (1 + (timer_bytes * 9)) * dev->bit_period * TIMER_USEC); + dev->stat = 0x01; /* raise HOST_BUSY while waiting */ + timer_disable(&dev->response_timer); + /* delay = ((half clock for start + half clock for stop) + (bytes * (8 bits + ack))) * bit period in usecs */ + timer_set_delay_u64(&dev->response_timer, (1 + (timer_bytes * 9)) * dev->bit_period * TIMER_USEC); } } - static void smbus_piix4_response(void *priv) { @@ -328,21 +332,19 @@ smbus_piix4_response(void *priv) dev->stat = dev->next_stat; } - void smbus_piix4_remap(smbus_piix4_t *dev, uint16_t new_io_base, uint8_t enable) { if (dev->io_base) - io_removehandler(dev->io_base, 0x10, smbus_piix4_read, NULL, NULL, smbus_piix4_write, NULL, NULL, dev); + io_removehandler(dev->io_base, 0x10, smbus_piix4_read, NULL, NULL, smbus_piix4_write, NULL, NULL, dev); dev->io_base = new_io_base; smbus_piix4_log("SMBus PIIX4: remap to %04Xh (%sabled)\n", dev->io_base, enable ? "en" : "dis"); if (enable && dev->io_base) - io_sethandler(dev->io_base, 0x10, smbus_piix4_read, NULL, NULL, smbus_piix4_write, NULL, NULL, dev); + io_sethandler(dev->io_base, 0x10, smbus_piix4_read, NULL, NULL, smbus_piix4_write, NULL, NULL, dev); } - void smbus_piix4_setclock(smbus_piix4_t *dev, int clock) { @@ -352,7 +354,6 @@ smbus_piix4_setclock(smbus_piix4_t *dev, int clock) dev->bit_period = 1000000.0 / dev->clock; } - static void * smbus_piix4_init(const device_t *info) { @@ -371,36 +372,42 @@ smbus_piix4_init(const device_t *info) return dev; } - static void smbus_piix4_close(void *priv) { smbus_piix4_t *dev = (smbus_piix4_t *) priv; if (i2c_smbus == dev->i2c) - i2c_smbus = NULL; + i2c_smbus = NULL; i2c_removebus(dev->i2c); free(dev); } - const device_t piix4_smbus_device = { - "PIIX4-compatible SMBus Host Controller", - "piix4_smbus", - DEVICE_AT, - SMBUS_PIIX4, - smbus_piix4_init, smbus_piix4_close, NULL, - { NULL }, NULL, NULL, - NULL + .name = "PIIX4-compatible SMBus Host Controller", + .internal_name = "piix4_smbus", + .flags = DEVICE_AT, + .local = SMBUS_PIIX4, + .init = smbus_piix4_init, + .close = smbus_piix4_close, + .reset = NULL, + { .available = NULL }, + .speed_changed = NULL, + .force_redraw = NULL, + .config = NULL }; const device_t via_smbus_device = { - "VIA VT82C686B SMBus Host Controller", - "via_smbus", - DEVICE_AT, - SMBUS_VIA, - smbus_piix4_init, smbus_piix4_close, NULL, - { NULL }, NULL, NULL, - NULL + .name = "VIA VT82C686B SMBus Host Controller", + .internal_name = "via_smbus", + .flags = DEVICE_AT, + .local = SMBUS_VIA, + .init = smbus_piix4_init, + .close = smbus_piix4_close, + .reset = NULL, + { .available = NULL }, + .speed_changed = NULL, + .force_redraw = NULL, + .config = NULL }; diff --git a/src/discord.c b/src/discord.c index 7a9dc1fec..18faee696 100644 --- a/src/discord.c +++ b/src/discord.c @@ -1,83 +1,82 @@ /* - * 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. + * 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. + * This file is part of the 86Box distribution. * - * Discord integration module. + * Discord integration module. * * * - * Authors: David HrdliÄka, + * Authors: David HrdliÄka, * - * Copyright 2019 David HrdliÄka. + * Copyright 2019 David HrdliÄka. */ #include -#include #include +#include #include #include #include #define HAVE_STDARG_H -#include <86box/86box.h> #include "cpu/cpu.h" +#include <86box/86box.h> +#include <86box/discord.h> #include <86box/machine.h> #include <86box/plat.h> #include <86box/plat_dynld.h> -#include <86box/discord.h> #include #ifdef _WIN32 -#define PATH_DISCORD_DLL "discord_game_sdk.dll" +# define PATH_DISCORD_DLL "discord_game_sdk.dll" #elif defined __APPLE__ -#define PATH_DISCORD_DLL "discord_game_sdk.dylib" +# define PATH_DISCORD_DLL "discord_game_sdk.dylib" #else -#define PATH_DISCORD_DLL "discord_game_sdk.so" +# define PATH_DISCORD_DLL "discord_game_sdk.so" #endif -int discord_loaded = 0; +int discord_loaded = 0; -static void *discord_handle = NULL; -static struct IDiscordCore *discord_core = NULL; -static struct IDiscordActivityManager *discord_activities = NULL; +static void *discord_handle = NULL; +static struct IDiscordCore *discord_core = NULL; +static struct IDiscordActivityManager *discord_activities = NULL; -static enum EDiscordResult (*discord_create)(DiscordVersion version, struct DiscordCreateParams* params, struct IDiscordCore** result); +static enum EDiscordResult(DISCORD_API *discord_create)(DiscordVersion version, struct DiscordCreateParams *params, struct IDiscordCore **result); static dllimp_t discord_imports[] = { - { "DiscordCreate", &discord_create }, - { NULL, NULL } + {"DiscordCreate", &discord_create}, + { NULL, NULL } }; #ifdef ENABLE_DISCORD_LOG int discord_do_log = 1; - static void discord_log(const char *fmt, ...) { va_list ap; if (discord_do_log) { - va_start(ap, fmt); - pclog_ex(fmt, ap); - va_end(ap); + va_start(ap, fmt); + pclog_ex(fmt, ap); + va_end(ap); } } #else -#define discord_log(fmt, ...) +# define discord_log(fmt, ...) #endif void discord_update_activity(int paused) { struct DiscordActivity activity; - char cpufamily[1024]; - char *paren; + char cpufamily[1024]; + char *paren; - if(discord_activities == NULL) - return; + if (discord_activities == NULL) + return; discord_log("discord: discord_update_activity(paused=%d)\n", paused); @@ -86,93 +85,90 @@ discord_update_activity(int paused) strncpy(cpufamily, cpu_f->name, sizeof(cpufamily) - 1); paren = strchr(cpufamily, '('); if (paren) - *(paren - 1) = '\0'; + *(paren - 1) = '\0'; - if (strlen(vm_name) < 100) - { - snprintf(activity.details, sizeof(activity.details), "Running \"%s\"", vm_name); - snprintf(activity.state, sizeof(activity.state), "%s (%s/%s)", strchr(machine_getname(), ']') + 2, cpufamily, cpu_s->name); - } - else - { - strncpy(activity.details, strchr(machine_getname(), ']') + 2, sizeof(activity.details) - 1); - snprintf(activity.state, sizeof(activity.state), "%s/%s", cpufamily, cpu_s->name); +#pragma GCC diagnostic push +#if defined(__GNUC__) && !defined(__clang__) +# pragma GCC diagnostic ignored "-Wformat-truncation" +#endif + if (strlen(vm_name) < 100) { + snprintf(activity.details, sizeof(activity.details), "Running \"%s\"", vm_name); + snprintf(activity.state, sizeof(activity.state), "%s (%s/%s)", strchr(machine_getname(), ']') + 2, cpufamily, cpu_s->name); + } else { + strncpy(activity.details, strchr(machine_getname(), ']') + 2, sizeof(activity.details) - 1); + snprintf(activity.state, sizeof(activity.state), "%s/%s", cpufamily, cpu_s->name); } +#pragma GCC diagnostic pop activity.timestamps.start = time(NULL); -/* Icon choosing for Discord based on 86Box.rc */ + /* Icon choosing for Discord based on 86Box.rc */ #ifdef RELEASE_BUILD -/* Icon by OBattler and laciba96 (green for release builds)*/ + /* Icon by OBattler and laciba96 (green for release builds)*/ strcpy(activity.assets.large_image, "86box-green"); #elif BETA_BUILD -/* Icon by OBattler and laciba96 (yellow for beta builds done by Jenkins)*/ + /* Icon by OBattler and laciba96 (yellow for beta builds done by Jenkins)*/ strcpy(activity.assets.large_image, "86box-yellow"); #elif ALPHA_BUILD -/* Icon by OBattler and laciba96 (red for alpha builds done by Jenkins)*/ + /* Icon by OBattler and laciba96 (red for alpha builds done by Jenkins)*/ strcpy(activity.assets.large_image, "86box-red"); #else -/* Icon by OBattler and laciba96 (gray for builds of branches and from the git master)*/ + /* Icon by OBattler and laciba96 (gray for builds of branches and from the git master)*/ strcpy(activity.assets.large_image, "86box"); #endif -/* End of icon choosing */ + /* End of icon choosing */ - if (paused) - { - strcpy(activity.assets.small_image, "status-paused"); - strcpy(activity.assets.small_text, "Paused"); - } - else - { - strcpy(activity.assets.small_image, "status-running"); - strcpy(activity.assets.small_text, "Running"); + if (paused) { + strcpy(activity.assets.small_image, "status-paused"); + strcpy(activity.assets.small_text, "Paused"); + } else { + strcpy(activity.assets.small_image, "status-running"); + strcpy(activity.assets.small_text, "Running"); } discord_activities->update_activity(discord_activities, &activity, NULL, NULL); } int -discord_load() +discord_load(void) { if (discord_handle != NULL) - return(1); + return 1; // Try to load the DLL discord_handle = dynld_module(PATH_DISCORD_DLL, discord_imports); - if (discord_handle == NULL) - { - discord_log("discord: couldn't load " PATH_DISCORD_DLL "\n"); - discord_close(); + if (discord_handle == NULL) { + discord_log("discord: couldn't load " PATH_DISCORD_DLL "\n"); + discord_close(); - return(0); + return 0; } discord_loaded = 1; - return(1); + return 1; } void -discord_init() +discord_init(void) { - enum EDiscordResult result; + enum EDiscordResult result; struct DiscordCreateParams params; - if(discord_handle == NULL) - return; + if (discord_handle == NULL) + return; DiscordCreateParamsSetDefault(¶ms); params.client_id = 906956844956782613; - params.flags = DiscordCreateFlags_NoRequireDiscord; + params.flags = DiscordCreateFlags_NoRequireDiscord; result = discord_create(DISCORD_VERSION, ¶ms, &discord_core); - if (result != DiscordResult_Ok) - { - discord_log("discord: DiscordCreate returned %d\n", result); - discord_close(); - return; + if (result != DiscordResult_Ok) { + discord_log("discord: DiscordCreate returned %d\n", result); + discord_close(); + return; } discord_activities = discord_core->get_activity_manager(discord_core); @@ -181,20 +177,20 @@ discord_init() } void -discord_close() +discord_close(void) { if (discord_core != NULL) - discord_core->destroy(discord_core); + discord_core->destroy(discord_core); - discord_core = NULL; + discord_core = NULL; discord_activities = NULL; } void -discord_run_callbacks() +discord_run_callbacks(void) { - if(discord_core == NULL) - return; + if (discord_core == NULL) + return; discord_core->run_callbacks(discord_core); } diff --git a/src/disk/CMakeLists.txt b/src/disk/CMakeLists.txt index f1a101516..7771a0b72 100644 --- a/src/disk/CMakeLists.txt +++ b/src/disk/CMakeLists.txt @@ -1,16 +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. +# 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. +# This file is part of the 86Box distribution. # -# CMake build script. +# CMake build script. # -# Authors: David HrdliÄka, +# Authors: David HrdliÄka, # -# Copyright 2020,2021 David HrdliÄka. +# Copyright 2020-2021 David HrdliÄka. # add_library(hdd OBJECT hdd.c hdd_image.c hdd_table.c hdc.c hdc_st506_xt.c @@ -22,4 +22,4 @@ add_library(zip OBJECT zip.c) add_library(mo OBJECT mo.c) add_subdirectory(minivhd) -target_link_libraries(86Box minivhd) \ No newline at end of file +target_link_libraries(86Box minivhd) diff --git a/src/disk/hdc.c b/src/disk/hdc.c index a6e09b732..07df9d0e6 100644 --- a/src/disk/hdc.c +++ b/src/disk/hdc.c @@ -1,20 +1,20 @@ /* - * 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. + * 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. + * This file is part of the 86Box distribution. * - * Common code to handle all sorts of disk controllers. + * Common code to handle all sorts of disk controllers. * * * - * Authors: Miran Grca, - * Fred N. van Kempen, + * Authors: Miran Grca, + * Fred N. van Kempen, * - * Copyright 2016-2018 Miran Grca. - * Copyright 2017,2018 Fred N. van Kempen. + * Copyright 2016-2018 Miran Grca. + * Copyright 2017-2018 Fred N. van Kempen. */ #include #include @@ -24,103 +24,97 @@ #define HAVE_STDARG_H #include <86box/86box.h> #include <86box/machine.h> +#include <86box/timer.h> #include <86box/device.h> #include <86box/hdc.h> #include <86box/hdc_ide.h> #include <86box/hdd.h> - -int hdc_current; - +int hdc_current; #ifdef ENABLE_HDC_LOG int hdc_do_log = ENABLE_HDC_LOG; - static void hdc_log(const char *fmt, ...) { va_list ap; if (hdc_do_log) { - va_start(ap, fmt); - pclog_ex(fmt, ap); - va_end(ap); + va_start(ap, fmt); + pclog_ex(fmt, ap); + va_end(ap); } } #else -#define hdc_log(fmt, ...) +# define hdc_log(fmt, ...) #endif - -static void * -null_init(const device_t *info) -{ - return(NULL); -} - - -static void -null_close(void *priv) -{ -} - - -static void * -inthdc_init(const device_t *info) -{ - return(NULL); -} - - -static void -inthdc_close(void *priv) -{ -} - - static const device_t hdc_none_device = { - "None", "none", 0, 0, - null_init, null_close, NULL, - { NULL }, NULL, NULL, NULL -}; -static const device_t hdc_internal_device = { - "Internal", "internal", 0, 0, - inthdc_init, inthdc_close, NULL, - { NULL }, NULL, NULL, NULL + .name = "None", + .internal_name = "none", + .flags = 0, + .local = 0, + .init = NULL, + .close = NULL, + .reset = NULL, + { .available = NULL }, + .speed_changed = NULL, + .force_redraw = NULL, + .config = NULL }; +static const device_t hdc_internal_device = { + .name = "Internal", + .internal_name = "internal", + .flags = 0, + .local = 0, + .init = NULL, + .close = NULL, + .reset = NULL, + { .available = NULL }, + .speed_changed = NULL, + .force_redraw = NULL, + .config = NULL +}; static const struct { - const device_t *device; + const device_t *device; } controllers[] = { - { &hdc_none_device }, - { &hdc_internal_device }, - { &st506_xt_xebec_device }, - { &st506_xt_dtc5150x_device }, - { &st506_xt_st11_m_device }, - { &st506_xt_wd1002a_wx1_device }, - { &st506_at_wd1003_device }, - { &st506_xt_st11_r_device }, - { &st506_xt_wd1002a_27x_device }, - { &esdi_at_wd1007vse1_device }, - { &ide_isa_device }, - { &ide_isa_2ch_device }, - { &xtide_at_device }, - { &xtide_at_386_device }, - { &xtide_at_ps2_device }, - { &xta_wdxt150_device }, - { &xtide_acculogic_device }, - { &xtide_device }, - { &esdi_ps2_device }, - { &ide_pci_device }, - { &ide_pci_2ch_device }, - { &ide_vlb_device }, - { &ide_vlb_2ch_device }, - { NULL } + // clang-format off + { &hdc_none_device }, + { &hdc_internal_device }, + { &st506_xt_xebec_device }, + { &st506_xt_wdxt_gen_device }, + { &st506_xt_dtc5150x_device }, + { &st506_xt_st11_m_device }, + { &st506_xt_wd1002a_wx1_device }, + { &st506_xt_wd1004a_wx1_device }, + { &st506_at_wd1003_device }, + { &st506_xt_st11_r_device }, + { &st506_xt_wd1002a_27x_device }, + { &st506_xt_wd1004_27x_device }, + { &st506_xt_wd1004a_27x_device }, + { &st506_xt_victor_v86p_device }, + { &esdi_at_wd1007vse1_device }, + { &ide_isa_device }, + { &ide_isa_2ch_device }, + { &xtide_at_device }, + { &xtide_at_386_device }, + { &xtide_at_ps2_device }, + { &xta_wdxt150_device }, + { &xtide_acculogic_device }, + { &xtide_device }, + { &xtide_plus_device }, + { &esdi_ps2_device }, + { &ide_pci_device }, + { &ide_pci_2ch_device }, + { &ide_vlb_device }, + { &ide_vlb_2ch_device }, + { NULL } + // clang-format on }; - /* Initialize the 'hdc_current' value based on configured HDC name. */ void hdc_init(void) @@ -131,77 +125,72 @@ hdc_init(void) hdd_image_init(); } - /* Reset the HDC, whichever one that is. */ void hdc_reset(void) { hdc_log("HDC: reset(current=%d, internal=%d)\n", - hdc_current, (machines[machine].flags & MACHINE_HDC) ? 1 : 0); + hdc_current, (machines[machine].flags & MACHINE_HDC) ? 1 : 0); /* If we have a valid controller, add its device. */ if (hdc_current > 1) - device_add(controllers[hdc_current].device); + device_add(controllers[hdc_current].device); /* Now, add the tertiary and/or quaternary IDE controllers. */ if (ide_ter_enabled) - device_add(&ide_ter_device); + device_add(&ide_ter_device); if (ide_qua_enabled) - device_add(&ide_qua_device); + device_add(&ide_qua_device); } - -char * +const char * hdc_get_internal_name(int hdc) { return device_get_internal_name(controllers[hdc].device); } - int hdc_get_from_internal_name(char *s) { int c = 0; while (controllers[c].device != NULL) { - if (!strcmp((char *) controllers[c].device->internal_name, s)) - return c; - c++; + if (!strcmp(controllers[c].device->internal_name, s)) + return c; + c++; } return 0; } - const device_t * hdc_get_device(int hdc) { - return(controllers[hdc].device); + return (controllers[hdc].device); } - int hdc_has_config(int hdc) { const device_t *dev = hdc_get_device(hdc); - if (dev == NULL) return(0); + if (dev == NULL) + return 0; - if (dev->config == NULL) return(0); + if (!device_has_config(dev)) + return 0; - return(1); + return 1; } - int hdc_get_flags(int hdc) { - return(controllers[hdc].device->flags); + return (controllers[hdc].device->flags); } - int hdc_available(int hdc) { - return(device_available(controllers[hdc].device)); + return (device_available(controllers[hdc].device)); } diff --git a/src/disk/hdc_esdi_at.c b/src/disk/hdc_esdi_at.c index e6d2729fa..65184094a 100644 --- a/src/disk/hdc_esdi_at.c +++ b/src/disk/hdc_esdi_at.c @@ -1,25 +1,23 @@ /* - * 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. + * 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. + * This file is part of the 86Box distribution. * - * Driver for the ESDI controller (WD1007-vse1) for PC/AT. + * Driver for the ESDI controller (WD1007-vse1) for PC/AT. * * * - * Authors: Sarah Walker, - * Miran Grca, - * Fred N. van Kempen, + * Authors: Sarah Walker, + * Miran Grca, + * Fred N. van Kempen, * - * Copyright 2008-2019 Sarah Walker. - * Copyright 2016-2019 Miran Grca. - * Copyright 2017-2019 Fred N. van Kempen. + * Copyright 2008-2019 Sarah Walker. + * Copyright 2016-2019 Miran Grca. + * Copyright 2017-2019 Fred N. van Kempen. */ -#define _LARGEFILE_SOURCE -#define _LARGEFILE64_SOURCE #define _GNU_SOURCE #include #include @@ -42,160 +40,178 @@ #include <86box/hdc.h> #include <86box/hdd.h> +#define HDC_TIME 10.0 +#define BIOS_FILE "roms/hdd/esdi_at/62-000279-061.bin" -#define HDC_TIME (TIMER_USEC*10LL) -#define BIOS_FILE "roms/hdd/esdi_at/62-000279-061.bin" +#define STAT_ERR 0x01 +#define STAT_INDEX 0x02 +#define STAT_CORRECTED_DATA 0x04 +#define STAT_DRQ 0x08 /* Data request */ +#define STAT_DSC 0x10 +#define STAT_SEEK_COMPLETE 0x20 +#define STAT_READY 0x40 +#define STAT_BUSY 0x80 -#define STAT_ERR 0x01 -#define STAT_INDEX 0x02 -#define STAT_CORRECTED_DATA 0x04 -#define STAT_DRQ 0x08 /* Data request */ -#define STAT_DSC 0x10 -#define STAT_SEEK_COMPLETE 0x20 -#define STAT_READY 0x40 -#define STAT_BUSY 0x80 +#define ERR_DAM_NOT_FOUND 0x01 /* Data Address Mark not found */ +#define ERR_TR000 0x02 /* track 0 not found */ +#define ERR_ABRT 0x04 /* command aborted */ +#define ERR_ID_NOT_FOUND 0x10 /* ID not found */ +#define ERR_DATA_CRC 0x40 /* data CRC error */ +#define ERR_BAD_BLOCK 0x80 /* bad block detected */ -#define ERR_DAM_NOT_FOUND 0x01 /* Data Address Mark not found */ -#define ERR_TR000 0x02 /* track 0 not found */ -#define ERR_ABRT 0x04 /* command aborted */ -#define ERR_ID_NOT_FOUND 0x10 /* ID not found */ -#define ERR_DATA_CRC 0x40 /* data CRC error */ -#define ERR_BAD_BLOCK 0x80 /* bad block detected */ +#define CMD_NOP 0x00 +#define CMD_RESTORE 0x10 +#define CMD_READ 0x20 +#define CMD_WRITE 0x30 +#define CMD_VERIFY 0x40 +#define CMD_FORMAT 0x50 +#define CMD_SEEK 0x70 +#define CMD_DIAGNOSE 0x90 +#define CMD_SET_PARAMETERS 0x91 +#define CMD_READ_PARAMETERS 0xec -#define CMD_NOP 0x00 -#define CMD_RESTORE 0x10 -#define CMD_READ 0x20 -#define CMD_WRITE 0x30 -#define CMD_VERIFY 0x40 -#define CMD_FORMAT 0x50 -#define CMD_SEEK 0x70 -#define CMD_DIAGNOSE 0x90 -#define CMD_SET_PARAMETERS 0x91 -#define CMD_READ_PARAMETERS 0xec - - -typedef struct { - int cfg_spt; - int cfg_hpc; - int current_cylinder; - int real_spt; - int real_hpc; - int real_tracks; - int present; - int hdd_num; +typedef struct drive_t { + int cfg_spt; + int cfg_hpc; + int current_cylinder; + int real_spt; + int real_hpc; + int real_tracks; + int present; + int hdd_num; } drive_t; -typedef struct { - uint8_t status; - uint8_t error; - int secount,sector,cylinder,head,cylprecomp; - uint8_t command; - uint8_t fdisk; - int pos; +typedef struct esdi_t { + uint8_t status; + uint8_t error; + int secount; + int sector; + int cylinder; + int head; + int cylprecomp; + uint8_t command; + uint8_t fdisk; + int pos; - int drive_sel; - int reset; - uint16_t buffer[256]; - int irqstat; + int drive_sel; + int reset; + uint16_t buffer[256]; + int irqstat; - pc_timer_t callback_timer; + pc_timer_t callback_timer; - drive_t drives[2]; + drive_t drives[2]; - rom_t bios_rom; + rom_t bios_rom; } esdi_t; - -static uint8_t esdi_read(uint16_t port, void *priv); -static void esdi_write(uint16_t port, uint8_t val, void *priv); - +static uint8_t esdi_read(uint16_t port, void *priv); +static void esdi_write(uint16_t port, uint8_t val, void *priv); #ifdef ENABLE_ESDI_AT_LOG int esdi_at_do_log = ENABLE_ESDI_AT_LOG; - static void esdi_at_log(const char *fmt, ...) { va_list ap; if (esdi_at_do_log) { - va_start(ap, fmt); - pclog_ex(fmt, ap); - va_end(ap); + va_start(ap, fmt); + pclog_ex(fmt, ap); + va_end(ap); } } #else -#define esdi_at_log(fmt, ...) +# define esdi_at_log(fmt, ...) #endif - static __inline void irq_raise(esdi_t *esdi) { if (!(esdi->fdisk & 2)) - picint(1 << 14); + picint(1 << 14); esdi->irqstat = 1; } - static __inline void -irq_lower(esdi_t *esdi) +irq_lower(UNUSED(esdi_t *esdi)) { picintc(1 << 14); } - static __inline void -irq_update(esdi_t *esdi) +irq_update(UNUSED(esdi_t *esdi)) { if (esdi->irqstat && !((pic2.irr | pic2.isr) & 0x40) && !(esdi->fdisk & 2)) - picint(1 << 14); + picint(1 << 14); } +static void +esdi_set_callback(esdi_t *esdi, double callback) +{ + if (!esdi) { + esdi_at_log("esdi_set_callback(NULL): Set callback failed\n"); + return; + } + + if (callback == 0.0) + timer_stop(&esdi->callback_timer); + else + timer_on_auto(&esdi->callback_timer, callback); +} + +double +esdi_get_xfer_time(UNUSED(esdi_t *esdi), int size) +{ + /* 390.625 us per sector at 10 Mbit/s = 1280 kB/s. */ + return (3125.0 / 8.0) * (double) size; +} /* Return the sector offset for the current register values. */ static int get_sector(esdi_t *esdi, off64_t *addr) { - drive_t *drive = &esdi->drives[esdi->drive_sel]; - int heads = drive->cfg_hpc; - int sectors = drive->cfg_spt; - int c, h, s; + const drive_t *drive = &esdi->drives[esdi->drive_sel]; + int heads = drive->cfg_hpc; + int sectors = drive->cfg_spt; + int c; + int h; + int s; + int sector; if (esdi->head > heads) { - esdi_at_log("esdi_get_sector: past end of configured heads\n"); - return(1); + esdi_at_log("esdi_get_sector: past end of configured heads\n"); + return 1; } - if (esdi->sector >= sectors+1) { - esdi_at_log("esdi_get_sector: past end of configured sectors\n"); - return(1); + if (esdi->sector >= sectors + 1) { + esdi_at_log("esdi_get_sector: past end of configured sectors\n"); + return 1; } - if (drive->cfg_spt==drive->real_spt && drive->cfg_hpc==drive->real_hpc) { - *addr = ((((off64_t) esdi->cylinder * heads) + esdi->head) * - sectors) + (esdi->sector - 1); + sector = esdi->sector ? esdi->sector : 1; + + if (drive->cfg_spt == drive->real_spt && drive->cfg_hpc == drive->real_hpc) { + *addr = ((((off64_t) esdi->cylinder * heads) + esdi->head) * sectors) + (sector - 1); } else { - /* - * When performing translation, the firmware seems to leave 1 - * sector per track inaccessible (spare sector) - */ + /* + * When performing translation, the firmware seems to leave 1 + * sector per track inaccessible (spare sector) + */ - *addr = ((((off64_t) esdi->cylinder * heads) + esdi->head) * - sectors) + (esdi->sector - 1); + *addr = ((((off64_t) esdi->cylinder * heads) + esdi->head) * sectors) + (sector - 1); - s = *addr % (drive->real_spt - 1); - h = (*addr / (drive->real_spt - 1)) % drive->real_hpc; - c = (*addr / (drive->real_spt - 1)) / drive->real_hpc; + s = *addr % (drive->real_spt - 1); + h = (*addr / (drive->real_spt - 1)) % drive->real_hpc; + c = (*addr / (drive->real_spt - 1)) / drive->real_hpc; - *addr = ((((off64_t)c * drive->real_hpc) + h) * drive->real_spt) + s; + *addr = ((((off64_t) c * drive->real_hpc) + h) * drive->real_spt) + s; } - - return(0); -} + return 0; +} /* Move to the next sector using CHS addressing. */ static void @@ -205,630 +221,670 @@ next_sector(esdi_t *esdi) esdi->sector++; if (esdi->sector == (drive->cfg_spt + 1)) { - esdi->sector = 1; - if (++esdi->head == drive->cfg_hpc) { - esdi->head = 0; - esdi->cylinder++; - if (drive->current_cylinder < drive->real_tracks) - drive->current_cylinder++; - } + esdi->sector = 1; + if (++esdi->head == drive->cfg_hpc) { + esdi->head = 0; + esdi->cylinder++; + if (drive->current_cylinder < drive->real_tracks) + drive->current_cylinder++; + } } } - static void esdi_writew(uint16_t port, uint16_t val, void *priv) { - esdi_t *esdi = (esdi_t *)priv; + esdi_t *esdi = (esdi_t *) priv; + off64_t addr; if (port > 0x01f0) { - esdi_write(port, val & 0xff, priv); - if (port != 0x01f7) - esdi_write(port + 1, (val >> 8) & 0xff, priv); + esdi_write(port, val & 0xff, priv); + if (port != 0x01f7) + esdi_write(port + 1, (val >> 8) & 0xff, priv); } else { - esdi->buffer[esdi->pos >> 1] = val; - esdi->pos += 2; + esdi->buffer[esdi->pos >> 1] = val; + esdi->pos += 2; - if (esdi->pos >= 512) { - esdi->pos = 0; - esdi->status = STAT_BUSY; - /* 390.625 us per sector at 10 Mbit/s = 1280 kB/s. */ - timer_set_delay_u64(&esdi->callback_timer, (3125 * TIMER_USEC) / 8); - } + if (esdi->pos >= 512) { + esdi->pos = 0; + esdi->status = STAT_BUSY; + get_sector(esdi, &addr); + double seek_time = hdd_timing_write(&hdd[esdi->drives[esdi->drive_sel].hdd_num], addr, 1); + double xfer_time = esdi_get_xfer_time(esdi, 1); + esdi_set_callback(esdi, seek_time + xfer_time); + } } } - static void esdi_write(uint16_t port, uint8_t val, void *priv) { - esdi_t *esdi = (esdi_t *)priv; + esdi_t *esdi = (esdi_t *) priv; + double seek_time; + double xfer_time; + off64_t addr; esdi_at_log("WD1007 write(%04x, %02x)\n", port, val); switch (port) { - case 0x1f0: /* data */ - esdi_writew(port, val | (val << 8), priv); - return; + case 0x1f0: /* data */ + esdi_writew(port, val | (val << 8), priv); + return; - case 0x1f1: /* write precompensation */ - esdi->cylprecomp = val; - return; + case 0x1f1: /* write precompensation */ + esdi->cylprecomp = val; + return; - case 0x1f2: /* sector count */ - esdi->secount = val; - return; + case 0x1f2: /* sector count */ + esdi->secount = val; + return; - case 0x1f3: /* sector */ - esdi->sector = val; - return; + case 0x1f3: /* sector */ + esdi->sector = val; + return; - case 0x1f4: /* cylinder low */ - esdi->cylinder = (esdi->cylinder & 0xFF00) | val; - return; + case 0x1f4: /* cylinder low */ + esdi->cylinder = (esdi->cylinder & 0xFF00) | val; + return; - case 0x1f5: /* cylinder high */ - esdi->cylinder = (esdi->cylinder & 0xFF) | (val << 8); - return; + case 0x1f5: /* cylinder high */ + esdi->cylinder = (esdi->cylinder & 0xFF) | (val << 8); + return; - case 0x1f6: /* drive/Head */ - esdi->head = val & 0xF; - esdi->drive_sel = (val & 0x10) ? 1 : 0; - if (esdi->drives[esdi->drive_sel].present) - esdi->status = STAT_READY | STAT_DSC; - else - esdi->status = 0; - return; + case 0x1f6: /* drive/Head */ + esdi->head = val & 0xF; + esdi->drive_sel = (val & 0x10) ? 1 : 0; + if (esdi->drives[esdi->drive_sel].present) + esdi->status = STAT_READY | STAT_DSC; + else + esdi->status = 0; + return; - case 0x1f7: /* command register */ - irq_lower(esdi); - esdi->command = val; - esdi->error = 0; + case 0x1f7: /* command register */ + irq_lower(esdi); + esdi->command = val; + esdi->error = 0; - esdi_at_log("WD1007: command %02x\n", val & 0xf0); + esdi_at_log("WD1007: command %02x\n", val & 0xf0); - switch (val & 0xf0) { - case CMD_RESTORE: - esdi->command &= ~0x0f; /*mask off step rate*/ - esdi->status = STAT_BUSY; - timer_set_delay_u64(&esdi->callback_timer, 200 * HDC_TIME); - break; + switch (val & 0xf0) { + case CMD_RESTORE: + esdi->command &= ~0x0f; /*mask off step rate*/ + esdi->status = STAT_BUSY; + esdi_set_callback(esdi, 200 * HDC_TIME); + ui_sb_update_icon(SB_HDD | HDD_BUS_ESDI, 1); + break; - case CMD_SEEK: - esdi->command &= ~0x0f; /*mask off step rate*/ - esdi->status = STAT_BUSY; - timer_set_delay_u64(&esdi->callback_timer, 200 * HDC_TIME); - break; + case CMD_SEEK: + esdi->command &= ~0x0f; /*mask off step rate*/ + esdi->status = STAT_BUSY; + get_sector(esdi, &addr); + seek_time = hdd_seek_get_time(&hdd[esdi->drives[esdi->drive_sel].hdd_num], addr, HDD_OP_SEEK, 0, 0.0); + esdi_set_callback(esdi, seek_time); + ui_sb_update_icon(SB_HDD | HDD_BUS_ESDI, 1); + break; - default: - switch (val) { - case CMD_NOP: - esdi->status = STAT_BUSY; - timer_set_delay_u64(&esdi->callback_timer, 200 * HDC_TIME); - break; + default: + switch (val) { + case CMD_NOP: + esdi->status = STAT_BUSY; + esdi_set_callback(esdi, 200 * HDC_TIME); + break; - case CMD_READ: - case CMD_READ+1: - case CMD_READ+2: - case CMD_READ+3: - esdi->command &= ~0x03; - if (val & 0x02) - fatal("Read with ECC\n"); - /*FALLTHROUGH*/ + case CMD_READ: + case CMD_READ + 1: + case CMD_READ + 2: + case CMD_READ + 3: + esdi->command &= ~0x03; + if (val & 0x02) + fatal("Read with ECC\n"); + fallthrough; - case 0xa0: - esdi->status = STAT_BUSY; - timer_set_delay_u64(&esdi->callback_timer, 200 * HDC_TIME); - break; + case 0xa0: + esdi->status = STAT_BUSY; + get_sector(esdi, &addr); + seek_time = hdd_timing_read(&hdd[esdi->drives[esdi->drive_sel].hdd_num], addr, 1); + xfer_time = esdi_get_xfer_time(esdi, 1); + esdi_set_callback(esdi, seek_time + xfer_time); + ui_sb_update_icon(SB_HDD | HDD_BUS_ESDI, 1); + break; - case CMD_WRITE: - case CMD_WRITE+1: - case CMD_WRITE+2: - case CMD_WRITE+3: - esdi->command &= ~0x03; - if (val & 0x02) - fatal("Write with ECC\n"); - esdi->status = STAT_READY | STAT_DRQ | STAT_DSC; - esdi->pos = 0; - break; + case CMD_WRITE: + case CMD_WRITE + 1: + case CMD_WRITE + 2: + case CMD_WRITE + 3: + esdi->command &= ~0x03; + if (val & 0x02) + fatal("Write with ECC\n"); + esdi->status = STAT_READY | STAT_DRQ | STAT_DSC; + esdi->pos = 0; + ui_sb_update_icon(SB_HDD | HDD_BUS_ESDI, 1); + break; - case CMD_VERIFY: - case CMD_VERIFY+1: - esdi->command &= ~0x01; - esdi->status = STAT_BUSY; - timer_set_delay_u64(&esdi->callback_timer, 200 * HDC_TIME); - break; + case CMD_VERIFY: + case CMD_VERIFY + 1: + esdi->command &= ~0x01; + esdi->status = STAT_BUSY; + get_sector(esdi, &addr); + seek_time = hdd_timing_read(&hdd[esdi->drives[esdi->drive_sel].hdd_num], addr, 1); + xfer_time = esdi_get_xfer_time(esdi, 1); + esdi_set_callback(esdi, seek_time + xfer_time); + ui_sb_update_icon(SB_HDD | HDD_BUS_ESDI, 1); + break; - case CMD_FORMAT: - esdi->status = STAT_DRQ; - esdi->pos = 0; - break; + case CMD_FORMAT: + esdi->status = STAT_DRQ; + esdi->pos = 0; + ui_sb_update_icon(SB_HDD | HDD_BUS_ESDI, 1); + break; - case CMD_SET_PARAMETERS: /* Initialize Drive Parameters */ - esdi->status = STAT_BUSY; - timer_set_delay_u64(&esdi->callback_timer, 30 * HDC_TIME); - break; + case CMD_SET_PARAMETERS: /* Initialize Drive Parameters */ + esdi->status = STAT_BUSY; + esdi_set_callback(esdi, 30 * HDC_TIME); + break; - case CMD_DIAGNOSE: /* Execute Drive Diagnostics */ - esdi->status = STAT_BUSY; - timer_set_delay_u64(&esdi->callback_timer, 200 * HDC_TIME); - break; + case CMD_DIAGNOSE: /* Execute Drive Diagnostics */ + esdi->status = STAT_BUSY; + esdi_set_callback(esdi, 200 * HDC_TIME); + ui_sb_update_icon(SB_HDD | HDD_BUS_ESDI, 1); + break; - case 0xe0: /*???*/ - case CMD_READ_PARAMETERS: - esdi->status = STAT_BUSY; - timer_set_delay_u64(&esdi->callback_timer, 200 * HDC_TIME); - break; + case 0xe0: /*???*/ + case CMD_READ_PARAMETERS: + esdi->status = STAT_BUSY; + esdi_set_callback(esdi, 200 * HDC_TIME); + break; - default: - esdi_at_log("WD1007: bad command %02X\n", val); - /*FALLTHROUGH*/ - case 0xe8: /*???*/ - esdi->status = STAT_BUSY; - timer_set_delay_u64(&esdi->callback_timer, 200 * HDC_TIME); - break; - } - } - break; + default: + esdi_at_log("WD1007: bad command %02X\n", val); + fallthrough; + case 0xe8: /*???*/ + esdi->status = STAT_BUSY; + esdi_set_callback(esdi, 200 * HDC_TIME); + break; + } + } + break; - case 0x3f6: /* Device control */ - if ((esdi->fdisk & 0x04) && !(val & 0x04)) { - timer_set_delay_u64(&esdi->callback_timer, 500 * HDC_TIME); - esdi->reset = 1; - esdi->status = STAT_BUSY; - } + case 0x3f6: /* Device control */ + if ((esdi->fdisk & 0x04) && !(val & 0x04)) { + esdi_set_callback(esdi, 500 * HDC_TIME); + esdi->reset = 1; + esdi->status = STAT_BUSY; + } - if (val & 0x04) { - /* Drive held in reset. */ - timer_disable(&esdi->callback_timer); - esdi->status = STAT_BUSY; - } - esdi->fdisk = val; - irq_update(esdi); - break; - } + if (val & 0x04) { + /* Drive held in reset. */ + esdi_set_callback(esdi, 0); + esdi->status = STAT_BUSY; + } + esdi->fdisk = val; + irq_update(esdi); + break; + + default: + break; + } } - static uint16_t esdi_readw(uint16_t port, void *priv) { - esdi_t *esdi = (esdi_t *)priv; + esdi_t *esdi = (esdi_t *) priv; uint16_t temp; + off64_t addr; if (port > 0x01f0) { - temp = esdi_read(port, priv); - if (port == 0x01f7) - temp |= 0xff00; - else - temp |= (esdi_read(port + 1, priv) << 8); + temp = esdi_read(port, priv); + if (port == 0x01f7) + temp |= 0xff00; + else + temp |= (esdi_read(port + 1, priv) << 8); } else { - temp = esdi->buffer[esdi->pos >> 1]; - esdi->pos += 2; + temp = esdi->buffer[esdi->pos >> 1]; + esdi->pos += 2; - if (esdi->pos >= 512) { - esdi->pos=0; - esdi->status = STAT_READY | STAT_DSC; - if (esdi->command == CMD_READ || esdi->command == 0xa0) { - esdi->secount = (esdi->secount - 1) & 0xff; - if (esdi->secount) { - next_sector(esdi); - esdi->status = STAT_BUSY; - /* 390.625 us per sector at 10 Mbit/s = 1280 kB/s. */ - timer_set_delay_u64(&esdi->callback_timer, (3125 * TIMER_USEC) / 8); - } else - ui_sb_update_icon(SB_HDD|HDD_BUS_ESDI, 0); - } - } + if (esdi->pos >= 512) { + esdi->pos = 0; + esdi->status = STAT_READY | STAT_DSC; + if (esdi->command == CMD_READ || esdi->command == 0xa0) { + esdi->secount = (esdi->secount - 1) & 0xff; + if (esdi->secount) { + next_sector(esdi); + esdi->status = STAT_BUSY; + get_sector(esdi, &addr); + double seek_time = hdd_timing_read(&hdd[esdi->drives[esdi->drive_sel].hdd_num], addr, 1); + double xfer_time = esdi_get_xfer_time(esdi, 1); + /* 390.625 us per sector at 10 Mbit/s = 1280 kB/s. */ + esdi_set_callback(esdi, seek_time + xfer_time); + } else + ui_sb_update_icon(SB_HDD | HDD_BUS_ESDI, 0); + } + } } - return(temp); + return temp; } - static uint8_t esdi_read(uint16_t port, void *priv) { - esdi_t *esdi = (esdi_t *)priv; + esdi_t *esdi = (esdi_t *) priv; uint8_t temp = 0xff; switch (port) { - case 0x1f0: /* data */ - temp = esdi_readw(port, esdi) & 0xff; - break; + case 0x1f0: /* data */ + temp = esdi_readw(port, esdi) & 0xff; + break; - case 0x1f1: /* error */ - temp = esdi->error; - break; + case 0x1f1: /* error */ + temp = esdi->error; + break; - case 0x1f2: /* sector count */ - temp = esdi->secount; - break; + case 0x1f2: /* sector count */ + temp = esdi->secount; + break; - case 0x1f3: /* sector */ - temp = esdi->sector; - break; + case 0x1f3: /* sector */ + temp = esdi->sector; + break; - case 0x1f4: /* cylinder low */ - temp = (uint8_t) (esdi->cylinder&0xff); - break; + case 0x1f4: /* cylinder low */ + temp = (uint8_t) (esdi->cylinder & 0xff); + break; - case 0x1f5: /* cylinder high */ - temp = (uint8_t) (esdi->cylinder>>8); - break; + case 0x1f5: /* cylinder high */ + temp = (uint8_t) (esdi->cylinder >> 8); + break; - case 0x1f6: /* drive/Head */ - temp = (uint8_t) (esdi->head | (esdi->drive_sel ? 0x10 : 0) | 0xa0); - break; + case 0x1f6: /* drive/Head */ + temp = (uint8_t) (esdi->head | (esdi->drive_sel ? 0x10 : 0) | 0xa0); + break; - case 0x1f7: /* status */ - irq_lower(esdi); - temp = esdi->status; - break; + case 0x1f7: /* status */ + irq_lower(esdi); + temp = esdi->status; + break; + + default: + break; } esdi_at_log("WD1007 read(%04x) = %02x\n", port, temp); - return(temp); + return temp; } - static void esdi_callback(void *priv) { - esdi_t *esdi = (esdi_t *)priv; + esdi_t *esdi = (esdi_t *) priv; drive_t *drive = &esdi->drives[esdi->drive_sel]; - off64_t addr; + off64_t addr; + double seek_time; if (esdi->reset) { - esdi->status = STAT_READY|STAT_DSC; - esdi->error = 1; - esdi->secount = 1; - esdi->sector = 1; - esdi->head = 0; - esdi->cylinder = 0; - esdi->reset = 0; + esdi->status = STAT_READY | STAT_DSC; + esdi->error = 1; + esdi->secount = 1; + esdi->sector = 1; + esdi->head = 0; + esdi->cylinder = 0; + esdi->reset = 0; - ui_sb_update_icon(SB_HDD|HDD_BUS_ESDI, 0); - return; + ui_sb_update_icon(SB_HDD | HDD_BUS_ESDI, 0); + return; } esdi_at_log("WD1007: command %02x on drive %i\n", esdi->command, esdi->drive_sel); switch (esdi->command) { - case CMD_RESTORE: - if (! drive->present) { - esdi->status = STAT_READY|STAT_ERR|STAT_DSC; - esdi->error = ERR_ABRT; - } else { - drive->current_cylinder = 0; - esdi->status = STAT_READY|STAT_DSC; - } - irq_raise(esdi); - break; + case CMD_RESTORE: + if (!drive->present) { + esdi->status = STAT_READY | STAT_ERR | STAT_DSC; + esdi->error = ERR_ABRT; + } else { + drive->current_cylinder = 0; + esdi->status = STAT_READY | STAT_DSC; + } + irq_raise(esdi); + ui_sb_update_icon(SB_HDD | HDD_BUS_ESDI, 0); + break; - case CMD_SEEK: - if (! drive->present) { - esdi->status = STAT_READY|STAT_ERR|STAT_DSC; - esdi->error = ERR_ABRT; - } else - esdi->status = STAT_READY|STAT_DSC; - irq_raise(esdi); - break; + case CMD_SEEK: + if (!drive->present) { + esdi->status = STAT_READY | STAT_ERR | STAT_DSC; + esdi->error = ERR_ABRT; + } else + esdi->status = STAT_READY | STAT_DSC; + irq_raise(esdi); + ui_sb_update_icon(SB_HDD | HDD_BUS_ESDI, 0); + break; - case CMD_READ: - if (! drive->present) { - esdi->status = STAT_READY|STAT_ERR|STAT_DSC; - esdi->error = ERR_ABRT; - irq_raise(esdi); - } else { - if (get_sector(esdi, &addr)) { - esdi->error = ERR_ID_NOT_FOUND; - esdi->status = STAT_READY|STAT_DSC|STAT_ERR; - irq_raise(esdi); - break; - } - - hdd_image_read(drive->hdd_num, addr, 1, (uint8_t *)esdi->buffer); - esdi->pos = 0; - esdi->status = STAT_DRQ|STAT_READY|STAT_DSC; - irq_raise(esdi); - ui_sb_update_icon(SB_HDD|HDD_BUS_ESDI, 1); - } - break; + case CMD_READ: + if (!drive->present) { + esdi->status = STAT_READY | STAT_ERR | STAT_DSC; + esdi->error = ERR_ABRT; + irq_raise(esdi); + } else { + if (get_sector(esdi, &addr)) { + esdi->error = ERR_ID_NOT_FOUND; + esdi->status = STAT_READY | STAT_DSC | STAT_ERR; + irq_raise(esdi); + break; + } - case CMD_WRITE: - if (! drive->present) { - esdi->status = STAT_READY|STAT_ERR|STAT_DSC; - esdi->error = ERR_ABRT; - irq_raise(esdi); - break; - } else { - if (get_sector(esdi, &addr)) { - esdi->error = ERR_ID_NOT_FOUND; - esdi->status = STAT_READY|STAT_DSC|STAT_ERR; - irq_raise(esdi); - break; - } - - hdd_image_write(drive->hdd_num, addr, 1, (uint8_t *)esdi->buffer); - irq_raise(esdi); - esdi->secount = (esdi->secount - 1) & 0xff; - if (esdi->secount) { - esdi->status = STAT_DRQ|STAT_READY|STAT_DSC; - esdi->pos = 0; - next_sector(esdi); - } else - esdi->status = STAT_READY|STAT_DSC; - ui_sb_update_icon(SB_HDD|HDD_BUS_ESDI, 1); - } - break; + hdd_image_read(drive->hdd_num, addr, 1, (uint8_t *) esdi->buffer); + esdi->pos = 0; + esdi->status = STAT_DRQ | STAT_READY | STAT_DSC; + irq_raise(esdi); + } + break; - case CMD_VERIFY: - if (! drive->present) { - esdi->status = STAT_READY|STAT_ERR|STAT_DSC; - esdi->error = ERR_ABRT; - irq_raise(esdi); - break; - } else { - if (get_sector(esdi, &addr)) { - esdi->error = ERR_ID_NOT_FOUND; - esdi->status = STAT_READY|STAT_DSC|STAT_ERR; - irq_raise(esdi); - break; - } + case CMD_WRITE: + if (!drive->present) { + esdi->status = STAT_READY | STAT_ERR | STAT_DSC; + esdi->error = ERR_ABRT; + irq_raise(esdi); + ui_sb_update_icon(SB_HDD | HDD_BUS_ESDI, 0); + break; + } else { + if (get_sector(esdi, &addr)) { + esdi->error = ERR_ID_NOT_FOUND; + esdi->status = STAT_READY | STAT_DSC | STAT_ERR; + irq_raise(esdi); + ui_sb_update_icon(SB_HDD | HDD_BUS_ESDI, 0); + break; + } - hdd_image_read(drive->hdd_num, addr, 1, (uint8_t *)esdi->buffer); - ui_sb_update_icon(SB_HDD|HDD_BUS_ESDI, 1); - next_sector(esdi); - esdi->secount = (esdi->secount - 1) & 0xff; - if (esdi->secount) - timer_set_delay_u64(&esdi->callback_timer, 6 * HDC_TIME); - else { - esdi->pos = 0; - esdi->status = STAT_READY|STAT_DSC; - irq_raise(esdi); - } - } - break; + hdd_image_write(drive->hdd_num, addr, 1, (uint8_t *) esdi->buffer); + irq_raise(esdi); + esdi->secount = (esdi->secount - 1) & 0xff; + if (esdi->secount) { + esdi->status = STAT_DRQ | STAT_READY | STAT_DSC; + esdi->pos = 0; + next_sector(esdi); + ui_sb_update_icon(SB_HDD | HDD_BUS_ESDI, 1); + } else { + esdi->status = STAT_READY | STAT_DSC; + ui_sb_update_icon(SB_HDD | HDD_BUS_ESDI, 0); + } + } + break; - case CMD_FORMAT: - if (! drive->present) { - esdi->status = STAT_READY|STAT_ERR|STAT_DSC; - esdi->error = ERR_ABRT; - irq_raise(esdi); - break; - } else { - if (get_sector(esdi, &addr)) { - esdi->error = ERR_ID_NOT_FOUND; - esdi->status = STAT_READY|STAT_DSC|STAT_ERR; - irq_raise(esdi); - break; - } - - hdd_image_zero(drive->hdd_num, addr, esdi->secount); - esdi->status = STAT_READY|STAT_DSC; - irq_raise(esdi); - ui_sb_update_icon(SB_HDD|HDD_BUS_ESDI, 1); - } - break; + case CMD_VERIFY: + if (!drive->present) { + esdi->status = STAT_READY | STAT_ERR | STAT_DSC; + esdi->error = ERR_ABRT; + irq_raise(esdi); + ui_sb_update_icon(SB_HDD | HDD_BUS_ESDI, 0); + break; + } else { + if (get_sector(esdi, &addr)) { + esdi->error = ERR_ID_NOT_FOUND; + esdi->status = STAT_READY | STAT_DSC | STAT_ERR; + irq_raise(esdi); + ui_sb_update_icon(SB_HDD | HDD_BUS_ESDI, 0); + break; + } - case CMD_DIAGNOSE: - /* This is basically controller diagnostics - it resets drive select to 0, - and resets error and status to ready, DSC, and no error detected. */ - esdi->drive_sel = 0; - drive = &esdi->drives[esdi->drive_sel]; + hdd_image_read(drive->hdd_num, addr, 1, (uint8_t *) esdi->buffer); + ui_sb_update_icon(SB_HDD | HDD_BUS_ESDI, 1); + next_sector(esdi); + esdi->secount = (esdi->secount - 1) & 0xff; + if (esdi->secount) { + get_sector(esdi, &addr); + seek_time = hdd_timing_read(&hdd[esdi->drives[esdi->drive_sel].hdd_num], addr, 1); + esdi_set_callback(esdi, seek_time + HDC_TIME); + } else { + esdi->pos = 0; + esdi->status = STAT_READY | STAT_DSC; + irq_raise(esdi); + ui_sb_update_icon(SB_HDD | HDD_BUS_ESDI, 0); + } + } + break; - esdi->error = 1; /*no error detected*/ - esdi->status = STAT_READY|STAT_DSC; - irq_raise(esdi); - break; + case CMD_FORMAT: + ui_sb_update_icon(SB_HDD | HDD_BUS_ESDI, 0); + if (!drive->present) { + esdi->status = STAT_READY | STAT_ERR | STAT_DSC; + esdi->error = ERR_ABRT; + irq_raise(esdi); + break; + } else { + if (get_sector(esdi, &addr)) { + esdi->error = ERR_ID_NOT_FOUND; + esdi->status = STAT_READY | STAT_DSC | STAT_ERR; + irq_raise(esdi); + break; + } - case CMD_SET_PARAMETERS: /* Initialize Drive Parameters */ - if (! drive->present) { - esdi->status = STAT_READY|STAT_ERR|STAT_DSC; - esdi->error = ERR_ABRT; - irq_raise(esdi); - } else { - drive->cfg_spt = esdi->secount; - drive->cfg_hpc = esdi->head+1; + hdd_image_zero(drive->hdd_num, addr, esdi->secount); + esdi->status = STAT_READY | STAT_DSC; + irq_raise(esdi); + } + break; - esdi_at_log("WD1007: parameters: spt=%i hpc=%i\n", drive->cfg_spt,drive->cfg_hpc); + case CMD_DIAGNOSE: + /* This is basically controller diagnostics - it resets drive select to 0, + and resets error and status to ready, DSC, and no error detected. */ + esdi->drive_sel = 0; + drive = &esdi->drives[esdi->drive_sel]; - if (! esdi->secount) - fatal("WD1007: secount=0\n"); - esdi->status = STAT_READY|STAT_DSC; - irq_raise(esdi); - } - break; + esdi->error = 1; /*no error detected*/ + esdi->status = STAT_READY | STAT_DSC; + irq_raise(esdi); + ui_sb_update_icon(SB_HDD | HDD_BUS_ESDI, 0); + break; - case CMD_NOP: - esdi->status = STAT_READY|STAT_ERR|STAT_DSC; - esdi->error = ERR_ABRT; - irq_raise(esdi); - break; + case CMD_SET_PARAMETERS: /* Initialize Drive Parameters */ + ui_sb_update_icon(SB_HDD | HDD_BUS_ESDI, 0); + if (!drive->present) { + esdi->status = STAT_READY | STAT_ERR | STAT_DSC; + esdi->error = ERR_ABRT; + irq_raise(esdi); + } else { + drive->cfg_spt = esdi->secount; + drive->cfg_hpc = esdi->head + 1; - case 0xe0: - if (! drive->present) { - esdi->status = STAT_READY|STAT_ERR|STAT_DSC; - esdi->error = ERR_ABRT; - irq_raise(esdi); - break; - } else { - switch (esdi->cylinder >> 8) { - case 0x31: - esdi->cylinder = drive->real_tracks; - break; + esdi_at_log("WD1007: parameters: spt=%i hpc=%i\n", drive->cfg_spt, drive->cfg_hpc); - case 0x33: - esdi->cylinder = drive->real_hpc; - break; + if (!esdi->secount) + fatal("WD1007: secount=0\n"); + esdi->status = STAT_READY | STAT_DSC; + irq_raise(esdi); + } + break; - case 0x35: - esdi->cylinder = 0x200; - break; + case CMD_NOP: + esdi->status = STAT_READY | STAT_ERR | STAT_DSC; + esdi->error = ERR_ABRT; + irq_raise(esdi); + ui_sb_update_icon(SB_HDD | HDD_BUS_ESDI, 0); + break; - case 0x36: - esdi->cylinder = drive->real_spt; - break; + case 0xe0: + ui_sb_update_icon(SB_HDD | HDD_BUS_ESDI, 0); + if (!drive->present) { + esdi->status = STAT_READY | STAT_ERR | STAT_DSC; + esdi->error = ERR_ABRT; + irq_raise(esdi); + break; + } else { + switch (esdi->cylinder >> 8) { + case 0x31: + esdi->cylinder = drive->real_tracks; + break; - default: - esdi_at_log("WD1007: bad read config %02x\n", esdi->cylinder >> 8); - } - esdi->status = STAT_READY|STAT_DSC; - irq_raise(esdi); - } - break; + case 0x33: + esdi->cylinder = drive->real_hpc; + break; - case 0xa0: - if (! drive->present) { - esdi->status = STAT_READY|STAT_ERR|STAT_DSC; - esdi->error = ERR_ABRT; - } else { - memset(esdi->buffer, 0x00, 512); - memset(&esdi->buffer[3], 0xff, 512-6); - esdi->pos = 0; - esdi->status = STAT_DRQ|STAT_READY|STAT_DSC; - } - irq_raise(esdi); - break; + case 0x35: + esdi->cylinder = 0x200; + break; - case CMD_READ_PARAMETERS: - if (! drive->present) { - esdi->status = STAT_READY|STAT_ERR|STAT_DSC; - esdi->error = ERR_ABRT; - irq_raise(esdi); - } else { - memset(esdi->buffer, 0x00, 512); - esdi->buffer[0] = 0x44; /* general configuration */ - esdi->buffer[1] = drive->real_tracks; /* number of non-removable cylinders */ - esdi->buffer[2] = 0; /* number of removable cylinders */ - esdi->buffer[3] = drive->real_hpc; /* number of heads */ - esdi->buffer[4] = 600; /* number of unformatted bytes/sector */ - esdi->buffer[5] = esdi->buffer[4] * drive->real_spt; /* number of unformatted bytes/track */ - esdi->buffer[6] = drive->real_spt; /* number of sectors */ - esdi->buffer[7] = 0; /*minimum bytes in inter-sector gap*/ - esdi->buffer[8] = 0; /* minimum bytes in postamble */ - esdi->buffer[9] = 0; /* number of words of vendor status */ - /* controller info */ - esdi->buffer[20] = 2; /* controller type */ - esdi->buffer[21] = 1; /* sector buffer size, in sectors */ - esdi->buffer[22] = 0; /* ecc bytes appended */ - esdi->buffer[27] = 'W' | ('D' << 8); - esdi->buffer[28] = '1' | ('0' << 8); - esdi->buffer[29] = '0' | ('7' << 8); - esdi->buffer[30] = 'V' | ('-' << 8); - esdi->buffer[31] = 'S' | ('E' << 8); - esdi->buffer[32] = '1'; - esdi->buffer[47] = 0; /* sectors per interrupt */ - esdi->buffer[48] = 0; /* can use double word read/write? */ - esdi->pos = 0; - esdi->status = STAT_DRQ|STAT_READY|STAT_DSC; - irq_raise(esdi); - } - break; + case 0x36: + esdi->cylinder = drive->real_spt; + break; - default: - esdi_at_log("WD1007: callback on unknown command %02x\n", esdi->command); - /*FALLTHROUGH*/ + default: + esdi_at_log("WD1007: bad read config %02x\n", esdi->cylinder >> 8); + } + esdi->status = STAT_READY | STAT_DSC; + irq_raise(esdi); + } + break; - case 0xe8: - esdi->status = STAT_READY|STAT_ERR|STAT_DSC; - esdi->error = ERR_ABRT; - irq_raise(esdi); - break; + case 0xa0: + if (!drive->present) { + esdi->status = STAT_READY | STAT_ERR | STAT_DSC; + esdi->error = ERR_ABRT; + } else { + memset(esdi->buffer, 0x00, 512); + memset(&esdi->buffer[3], 0xff, 512 - 6); + esdi->pos = 0; + esdi->status = STAT_DRQ | STAT_READY | STAT_DSC; + } + irq_raise(esdi); + ui_sb_update_icon(SB_HDD | HDD_BUS_ESDI, 0); + break; + + case CMD_READ_PARAMETERS: + if (!drive->present) { + esdi->status = STAT_READY | STAT_ERR | STAT_DSC; + esdi->error = ERR_ABRT; + irq_raise(esdi); + } else { + memset(esdi->buffer, 0x00, 512); + esdi->buffer[0] = 0x44; /* general configuration */ + esdi->buffer[1] = drive->real_tracks; /* number of non-removable cylinders */ + esdi->buffer[2] = 0; /* number of removable cylinders */ + esdi->buffer[3] = drive->real_hpc; /* number of heads */ + esdi->buffer[4] = 600; /* number of unformatted bytes/sector */ + esdi->buffer[5] = esdi->buffer[4] * drive->real_spt; /* number of unformatted bytes/track */ + esdi->buffer[6] = drive->real_spt; /* number of sectors */ + esdi->buffer[7] = 0; /*minimum bytes in inter-sector gap*/ + esdi->buffer[8] = 0; /* minimum bytes in postamble */ + esdi->buffer[9] = 0; /* number of words of vendor status */ + /* controller info */ + esdi->buffer[20] = 2; /* controller type */ + esdi->buffer[21] = 1; /* sector buffer size, in sectors */ + esdi->buffer[22] = 0; /* ecc bytes appended */ + esdi->buffer[27] = 'W' | ('D' << 8); + esdi->buffer[28] = '1' | ('0' << 8); + esdi->buffer[29] = '0' | ('7' << 8); + esdi->buffer[30] = 'V' | ('-' << 8); + esdi->buffer[31] = 'S' | ('E' << 8); + esdi->buffer[32] = '1'; + esdi->buffer[47] = 0; /* sectors per interrupt */ + esdi->buffer[48] = 0; /* can use double word read/write? */ + esdi->pos = 0; + esdi->status = STAT_DRQ | STAT_READY | STAT_DSC; + irq_raise(esdi); + } + ui_sb_update_icon(SB_HDD | HDD_BUS_ESDI, 0); + break; + + default: + esdi_at_log("WD1007: callback on unknown command %02x\n", esdi->command); + fallthrough; + + case 0xe8: + esdi->status = STAT_READY | STAT_ERR | STAT_DSC; + esdi->error = ERR_ABRT; + irq_raise(esdi); + ui_sb_update_icon(SB_HDD | HDD_BUS_ESDI, 0); + break; } - - ui_sb_update_icon(SB_HDD|HDD_BUS_ESDI, 0); } - static void -loadhd(esdi_t *esdi, int hdd_num, int d, const char *fn) +loadhd(esdi_t *esdi, int hdd_num, int d, UNUSED(const char *fn)) { drive_t *drive = &esdi->drives[hdd_num]; - if (! hdd_image_load(d)) { - esdi_at_log("WD1007: drive %d not present!\n", d); - drive->present = 0; - return; + if (!hdd_image_load(d)) { + esdi_at_log("WD1007: drive %d not present!\n", d); + drive->present = 0; + return; } + hdd_preset_apply(d); + drive->cfg_spt = drive->real_spt = hdd[d].spt; drive->cfg_hpc = drive->real_hpc = hdd[d].hpc; - drive->real_tracks = hdd[d].tracks; - drive->hdd_num = d; - drive->present = 1; + drive->real_tracks = hdd[d].tracks; + drive->hdd_num = d; + drive->present = 1; } - static void -esdi_rom_write(uint32_t addr, uint8_t val, void *p) +esdi_rom_write(uint32_t addr, uint8_t val, void *priv) { - rom_t *rom = (rom_t *)p; + rom_t *rom = (rom_t *) priv; addr &= rom->mask; if (addr >= 0x1f00 && addr < 0x2000) - rom->rom[addr] = val; + rom->rom[addr] = val; } - static void * -wd1007vse1_init(const device_t *info) +wd1007vse1_init(UNUSED(const device_t *info)) { - int c, d; + int c; esdi_t *esdi = malloc(sizeof(esdi_t)); memset(esdi, 0x00, sizeof(esdi_t)); c = 0; - for (d=0; d= ESDI_NUM) break; - } + if (++c >= ESDI_NUM) + break; + } } - esdi->status = STAT_READY|STAT_DSC; - esdi->error = 1; + esdi->status = STAT_READY | STAT_DSC; + esdi->error = 1; rom_init(&esdi->bios_rom, - BIOS_FILE, 0xc8000, 0x4000, 0x3fff, 0, MEM_MAPPING_EXTERNAL); + BIOS_FILE, 0xc8000, 0x4000, 0x3fff, 0, MEM_MAPPING_EXTERNAL); mem_mapping_set_handler(&esdi->bios_rom.mapping, - rom_read, rom_readw, rom_readl, - esdi_rom_write, NULL, NULL); + rom_read, rom_readw, rom_readl, + esdi_rom_write, NULL, NULL); io_sethandler(0x01f0, 1, - esdi_read, esdi_readw, NULL, - esdi_write, esdi_writew, NULL, esdi); + esdi_read, esdi_readw, NULL, + esdi_write, esdi_writew, NULL, esdi); io_sethandler(0x01f1, 7, - esdi_read, esdi_readw, NULL, - esdi_write, esdi_writew, NULL, esdi); + esdi_read, esdi_readw, NULL, + esdi_write, esdi_writew, NULL, esdi); io_sethandler(0x03f6, 1, NULL, NULL, NULL, - esdi_write, NULL, NULL, esdi); + esdi_write, NULL, NULL, esdi); timer_add(&esdi->callback_timer, esdi_callback, esdi, 0); ui_sb_update_icon(SB_HDD | HDD_BUS_ESDI, 0); - return(esdi); + return esdi; } - static void wd1007vse1_close(void *priv) { - esdi_t *esdi = (esdi_t *)priv; - drive_t *drive; - int d; + esdi_t *esdi = (esdi_t *) priv; + const drive_t *drive; - for (d=0; d<2; d++) { - drive = &esdi->drives[d]; + for (uint8_t d = 0; d < 2; d++) { + drive = &esdi->drives[d]; - hdd_image_close(drive->hdd_num); + hdd_image_close(drive->hdd_num); } free(esdi); @@ -836,21 +892,22 @@ wd1007vse1_close(void *priv) ui_sb_update_icon(SB_HDD | HDD_BUS_ESDI, 0); } - static int wd1007vse1_available(void) { - return(rom_present(BIOS_FILE)); + return (rom_present(BIOS_FILE)); } - const device_t esdi_at_wd1007vse1_device = { - "Western Digital WD1007V-SE1 (ESDI)", - "esdi_at", - DEVICE_ISA | DEVICE_AT, - 0, - wd1007vse1_init, wd1007vse1_close, NULL, - { wd1007vse1_available }, - NULL, NULL, - NULL + .name = "Western Digital WD1007V-SE1 (ESDI)", + .internal_name = "esdi_at", + .flags = DEVICE_ISA | DEVICE_AT, + .local = 0, + .init = wd1007vse1_init, + .close = wd1007vse1_close, + .reset = NULL, + { .available = wd1007vse1_available }, + .speed_changed = NULL, + .force_redraw = NULL, + .config = NULL }; diff --git a/src/disk/hdc_esdi_mca.c b/src/disk/hdc_esdi_mca.c index f50a128f6..02f054ca2 100644 --- a/src/disk/hdc_esdi_mca.c +++ b/src/disk/hdc_esdi_mca.c @@ -1,71 +1,74 @@ /* - * 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. + * 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. + * This file is part of the 86Box distribution. * - * Driver for IBM PS/2 ESDI disk controller (MCA) + * Driver for IBM PS/2 ESDI disk controller (MCA) * - * AdapterID: 0xDDFF - * AdapterName: "ESDI Fixed Disk Controller" - * NumBytes 2 - * I/O base: 0x3510-0x3517 - * IRQ: 14 + * AdapterID: 0xDDFF + * AdapterName: "ESDI Fixed Disk Controller" + * NumBytes 2 + * I/O base: 0x3510-0x3517 + * IRQ: 14 * - * Primary Board pos[0]=XXxx xx0X 0x3510 - * Secondary Board pos[0]=XXxx xx1X 0x3518 + * Primary Board pos[0]=XXxx xx0X 0x3510 + * Secondary Board pos[0]=XXxx xx1X 0x3518 * - * DMA 5 pos[0]=XX01 01XX - * DMA 6 pos[0]=XX01 10XX - * DMA 7 pos[0]=XX01 11XX - * DMA 0 pos[0]=XX00 00XX - * DMA 1 pos[0]=XX00 01XX - * DMA 3 pos[0]=XX00 11XX - * DMA 4 pos[0]=XX01 00XX + * DMA 5 pos[0]=XX01 01XX + * DMA 6 pos[0]=XX01 10XX + * DMA 7 pos[0]=XX01 11XX + * DMA 0 pos[0]=XX00 00XX + * DMA 1 pos[0]=XX00 01XX + * DMA 3 pos[0]=XX00 11XX + * DMA 4 pos[0]=XX01 00XX * - * MCA Fairness ON pos[0]=X1XX XXXX - * MCA Fairness OFF pos[0]=X0XX XXXX + * MCA Fairness ON pos[0]=X1XX XXXX + * MCA Fairness OFF pos[0]=X0XX XXXX * - * ROM C000 pos[1]=XXXX 0000 - * ROM C400 pos[1]=XXXX 0001 - * ROM C800 pos[1]=XXXX 0010 - * ROM CC00 pos[1]=XXXX 0011 - * ROM D000 pos[1]=XXXX 0100 - * ROM D400 pos[1]=XXXX 0101 - * ROM D800 pos[1]=XXXX 0110 - * ROM DC00 pos[1]=XXXX 0111 - * ROM Disabled pos[1]=XXXX 1XXX + * ROM C000 pos[1]=XXXX 0000 + * ROM C400 pos[1]=XXXX 0001 + * ROM C800 pos[1]=XXXX 0010 + * ROM CC00 pos[1]=XXXX 0011 + * ROM D000 pos[1]=XXXX 0100 + * ROM D400 pos[1]=XXXX 0101 + * ROM D800 pos[1]=XXXX 0110 + * ROM DC00 pos[1]=XXXX 0111 + * ROM Disabled pos[1]=XXXX 1XXX * - * DMA Burst 8 pos[1]=XX01 XXXX - * DMA Burst 16 pos[1]=XX10 XXXX - * DMA Burst 24 pos[1]=XX11 XXXX - * DMA Disabled pos[1]=XX00 XXXX + * DMA Burst 8 pos[1]=XX01 XXXX + * DMA Burst 16 pos[1]=XX10 XXXX + * DMA Burst 24 pos[1]=XX11 XXXX + * DMA Disabled pos[1]=XX00 XXXX * - * Although this is an MCA device, meaning that the system - * software will take care of device configuration, the ESDI - * controller is a somewhat weird one.. it's I/O base address - * and IRQ channel are locked to 0x3510 and IRQ14, possibly - * to enforce compatibility with the IBM MFM disk controller - * that was also in use on these systems. All other settings, - * however, are auto-configured by the system software as - * shown above. + * Although this is an MCA device, meaning that the system + * software will take care of device configuration, the ESDI + * controller is a somewhat weird one.. it's I/O base address + * and IRQ channel are locked to 0x3510 and IRQ14, possibly + * to enforce compatibility with the IBM MFM disk controller + * that was also in use on these systems. All other settings, + * however, are auto-configured by the system software as + * shown above. * * * - * Authors: Sarah Walker, - * Fred N. van Kempen, + * Authors: Sarah Walker, + * Fred N. van Kempen, * - * Copyright 2008-2018 Sarah Walker. - * Copyright 2017,2018 Fred N. van Kempen. + * Copyright 2008-2018 Sarah Walker. + * Copyright 2017-2018 Fred N. van Kempen. */ + #include +#include #include #include #include #include #include +#include #define HAVE_STDARG_H #include <86box/86box.h> #include <86box/device.h> @@ -79,179 +82,177 @@ #include <86box/ui.h> #include <86box/hdc.h> #include <86box/hdd.h> - +#include <86box/plat_unused.h> /* These are hardwired. */ -#define ESDI_IOADDR_PRI 0x3510 -#define ESDI_IOADDR_SEC 0x3518 -#define ESDI_IRQCHAN 14 +#define ESDI_IOADDR_PRI 0x3510 +#define ESDI_IOADDR_SEC 0x3518 +#define ESDI_IRQCHAN 14 -#define BIOS_FILE_L "roms/hdd/esdi/90x8969.bin" -#define BIOS_FILE_H "roms/hdd/esdi/90x8970.bin" +#define BIOS_FILE_L "roms/hdd/esdi/90x8969.bin" +#define BIOS_FILE_H "roms/hdd/esdi/90x8970.bin" +#define ESDI_TIME 512.0 +#define CMD_ADAPTER 0 -#define ESDI_TIME (200*TIMER_USEC) -#define CMD_ADAPTER 0 - - -typedef struct esdi_drive { - int spt, hpc; +typedef struct esdi_drive_t { + int spt; + int hpc; int tracks; int sectors; int present; int hdd_num; } drive_t; -typedef struct esdi { - int8_t dma; +typedef struct esdi_t { + int8_t dma; - uint32_t bios; - rom_t bios_rom; - - uint8_t basic_ctrl; - uint8_t status; - uint8_t irq_status; - int irq_in_progress; - int cmd_req_in_progress; - int cmd_pos; - uint16_t cmd_data[4]; - int cmd_dev; + uint32_t bios; + rom_t bios_rom; - int status_pos, - status_len; + uint8_t basic_ctrl; + uint8_t status; + uint8_t irq_status; + int irq_in_progress; + int cmd_req_in_progress; + int cmd_pos; + uint16_t cmd_data[4]; + int cmd_dev; - uint16_t status_data[256]; + int status_pos; + int status_len; - int data_pos; - uint16_t data[256]; + uint16_t status_data[256]; - uint16_t sector_buffer[256][256]; + int data_pos; + uint16_t data[256]; - int sector_pos; - int sector_count; - - int command; - int cmd_state; - - int in_reset; - uint64_t callback; - pc_timer_t timer; - - uint32_t rba; - - struct { + uint16_t sector_buffer[256][256]; + + int sector_pos; + int sector_count; + + int command; + int cmd_state; + + int in_reset; + pc_timer_t timer; + + uint32_t rba; + + struct cmds { int req_in_progress; - } cmds[3]; - - drive_t drives[2]; + } cmds[3]; - uint8_t pos_regs[8]; + drive_t drives[2]; + + uint8_t pos_regs[8]; } esdi_t; -#define STATUS_DMA_ENA (1 << 7) -#define STATUS_IRQ_PENDING (1 << 6) -#define STATUS_CMD_IN_PROGRESS (1 << 5) -#define STATUS_BUSY (1 << 4) -#define STATUS_STATUS_OUT_FULL (1 << 3) -#define STATUS_CMD_IR_FULL (1 << 2) -#define STATUS_TRANSFER_REQ (1 << 1) -#define STATUS_IRQ (1 << 0) +#define STATUS_DMA_ENA (1 << 7) +#define STATUS_IRQ_PENDING (1 << 6) +#define STATUS_CMD_IN_PROGRESS (1 << 5) +#define STATUS_BUSY (1 << 4) +#define STATUS_STATUS_OUT_FULL (1 << 3) +#define STATUS_CMD_IR_FULL (1 << 2) +#define STATUS_TRANSFER_REQ (1 << 1) +#define STATUS_IRQ (1 << 0) -#define CTRL_RESET (1 << 7) -#define CTRL_DMA_ENA (1 << 1) -#define CTRL_IRQ_ENA (1 << 0) +#define CTRL_RESET (1 << 7) +#define CTRL_DMA_ENA (1 << 1) +#define CTRL_IRQ_ENA (1 << 0) -#define IRQ_HOST_ADAPTER (7 << 5) -#define IRQ_DEVICE_0 (0 << 5) -#define IRQ_CMD_COMPLETE_SUCCESS 0x1 -#define IRQ_RESET_COMPLETE 0xa -#define IRQ_DATA_TRANSFER_READY 0xb -#define IRQ_CMD_COMPLETE_FAILURE 0xc +#define IRQ_HOST_ADAPTER (7 << 5) +#define IRQ_DEVICE_0 (0 << 5) +#define IRQ_CMD_COMPLETE_SUCCESS 0x1 +#define IRQ_RESET_COMPLETE 0xa +#define IRQ_DATA_TRANSFER_READY 0xb +#define IRQ_CMD_COMPLETE_FAILURE 0xc -#define ATTN_DEVICE_SEL (7 << 5) -#define ATTN_HOST_ADAPTER (7 << 5) -#define ATTN_DEVICE_0 (0 << 5) -#define ATTN_DEVICE_1 (1 << 5) -#define ATTN_REQ_MASK 0x0f -#define ATTN_CMD_REQ 1 -#define ATTN_EOI 2 -#define ATTN_RESET 4 +#define ATTN_DEVICE_SEL (7 << 5) +#define ATTN_HOST_ADAPTER (7 << 5) +#define ATTN_DEVICE_0 (0 << 5) +#define ATTN_DEVICE_1 (1 << 5) +#define ATTN_REQ_MASK 0x0f +#define ATTN_CMD_REQ 1 +#define ATTN_EOI 2 +#define ATTN_RESET 4 -#define CMD_SIZE_4 (1 << 14) +#define CMD_SIZE_4 (1 << 14) -#define CMD_DEVICE_SEL (7 << 5) -#define CMD_MASK 0x1f -#define CMD_READ 0x01 -#define CMD_WRITE 0x02 -#define CMD_READ_VERIFY 0x03 -#define CMD_WRITE_VERIFY 0x04 -#define CMD_SEEK 0x05 -#define CMD_GET_DEV_STATUS 0x08 -#define CMD_GET_DEV_CONFIG 0x09 -#define CMD_GET_POS_INFO 0x0a -#define CMD_FORMAT_UNIT 0x16 -#define CMD_FORMAT_PREPARE 0x17 +#define CMD_DEVICE_SEL (7 << 5) +#define CMD_MASK 0x1f +#define CMD_READ 0x01 +#define CMD_WRITE 0x02 +#define CMD_READ_VERIFY 0x03 +#define CMD_WRITE_VERIFY 0x04 +#define CMD_SEEK 0x05 +#define CMD_GET_DEV_STATUS 0x08 +#define CMD_GET_DEV_CONFIG 0x09 +#define CMD_GET_POS_INFO 0x0a +#define CMD_FORMAT_UNIT 0x16 +#define CMD_FORMAT_PREPARE 0x17 -#define STATUS_LEN(x) ((x) << 8) -#define STATUS_DEVICE(x) ((x) << 5) +#define STATUS_LEN(x) ((x) << 8) +#define STATUS_DEVICE(x) ((x) << 5) #define STATUS_DEVICE_HOST_ADAPTER (7 << 5) - #ifdef ENABLE_ESDI_MCA_LOG int esdi_mca_do_log = ENABLE_ESDI_MCA_LOG; - static void esdi_mca_log(const char *fmt, ...) { va_list ap; if (esdi_mca_do_log) { - va_start(ap, fmt); - pclog_ex(fmt, ap); - va_end(ap); + va_start(ap, fmt); + pclog_ex(fmt, ap); + va_end(ap); } } #else -#define esdi_mca_log(fmt, ...) +# define esdi_mca_log(fmt, ...) #endif - static __inline void set_irq(esdi_t *dev) { if (dev->basic_ctrl & CTRL_IRQ_ENA) - picint(1 << 14); + picint(1 << 14); } - static __inline void -clear_irq(esdi_t *dev) +clear_irq(UNUSED(esdi_t *dev)) { picintc(1 << 14); } static void -esdi_mca_set_callback(esdi_t *dev, uint64_t callback) +esdi_mca_set_callback(esdi_t *dev, double callback) { if (!dev) { - return; + return; } if (callback) { - dev->callback = callback; - timer_set_delay_u64(&dev->timer, dev->callback); - } else { - dev->callback = 0; - timer_disable(&dev->timer); - } + timer_on_auto(&dev->timer, callback); + } else { + timer_stop(&dev->timer); + } } +static double +esdi_mca_get_xfer_time(UNUSED(esdi_t *esdi), int size) +{ + /* 390.625 us per sector at 10 Mbit/s = 1280 kB/s. */ + return (3125.0 / 8.0) * (double) size; +} static void cmd_unsupported(esdi_t *dev) { - dev->status_len = 9; + dev->status_len = 9; dev->status_data[0] = dev->command | STATUS_LEN(9) | dev->cmd_dev; dev->status_data[1] = 0x0f03; /*Attention error, command not supported*/ dev->status_data[2] = 0x0002; /*Interface fault*/ @@ -262,876 +263,930 @@ cmd_unsupported(esdi_t *dev) dev->status_data[7] = 0; dev->status_data[8] = 0; - dev->status = STATUS_IRQ | STATUS_STATUS_OUT_FULL; - dev->irq_status = dev->cmd_dev | IRQ_CMD_COMPLETE_FAILURE; + dev->status = STATUS_IRQ | STATUS_STATUS_OUT_FULL; + dev->irq_status = dev->cmd_dev | IRQ_CMD_COMPLETE_FAILURE; dev->irq_in_progress = 1; set_irq(dev); + ui_sb_update_icon(SB_HDD | HDD_BUS_ESDI, 0); } - static void device_not_present(esdi_t *dev) { - dev->status_len = 9; + dev->status_len = 9; dev->status_data[0] = dev->command | STATUS_LEN(9) | dev->cmd_dev; dev->status_data[1] = 0x0c11; /*Command failed, internal hardware error*/ dev->status_data[2] = 0x000b; /*Selection error*/ dev->status_data[3] = 0; dev->status_data[4] = 0; dev->status_data[5] = 0; - dev->status_data[6] = 0; - dev->status_data[7] = 0; + dev->status_data[6] = 0; + dev->status_data[7] = 0; dev->status_data[8] = 0; - dev->status = STATUS_IRQ | STATUS_STATUS_OUT_FULL; - dev->irq_status = dev->cmd_dev | IRQ_CMD_COMPLETE_FAILURE; + dev->status = STATUS_IRQ | STATUS_STATUS_OUT_FULL; + dev->irq_status = dev->cmd_dev | IRQ_CMD_COMPLETE_FAILURE; dev->irq_in_progress = 1; set_irq(dev); + ui_sb_update_icon(SB_HDD | HDD_BUS_ESDI, 0); } - static void rba_out_of_range(esdi_t *dev) { - dev->status_len = 9; + dev->status_len = 9; dev->status_data[0] = dev->command | STATUS_LEN(9) | dev->cmd_dev; dev->status_data[1] = 0x0e01; /*Command block error, invalid parameter*/ dev->status_data[2] = 0x0007; /*RBA out of range*/ dev->status_data[3] = 0; dev->status_data[4] = 0; dev->status_data[5] = 0; - dev->status_data[6] = 0; - dev->status_data[7] = 0; + dev->status_data[6] = 0; + dev->status_data[7] = 0; dev->status_data[8] = 0; - dev->status = STATUS_IRQ | STATUS_STATUS_OUT_FULL; - dev->irq_status = dev->cmd_dev | IRQ_CMD_COMPLETE_FAILURE; + dev->status = STATUS_IRQ | STATUS_STATUS_OUT_FULL; + dev->irq_status = dev->cmd_dev | IRQ_CMD_COMPLETE_FAILURE; dev->irq_in_progress = 1; set_irq(dev); + ui_sb_update_icon(SB_HDD | HDD_BUS_ESDI, 0); } - static void complete_command_status(esdi_t *dev) { dev->status_len = 7; if (dev->cmd_dev == ATTN_DEVICE_0) - dev->status_data[0] = CMD_READ | STATUS_LEN(7) | STATUS_DEVICE(0); + dev->status_data[0] = CMD_READ | STATUS_LEN(7) | STATUS_DEVICE(0); else - dev->status_data[0] = CMD_READ | STATUS_LEN(7) | STATUS_DEVICE(1); - dev->status_data[1] = 0x0000; /*Error bits*/ - dev->status_data[2] = 0x1900; /*Device status*/ - dev->status_data[3] = 0; /*Number of blocks left to do*/ - dev->status_data[4] = (dev->rba-1) & 0xffff; /*Last RBA processed*/ - dev->status_data[5] = (dev->rba-1) >> 8; + dev->status_data[0] = CMD_READ | STATUS_LEN(7) | STATUS_DEVICE(1); + dev->status_data[1] = 0x0000; /*Error bits*/ + dev->status_data[2] = 0x1900; /*Device status*/ + dev->status_data[3] = 0; /*Number of blocks left to do*/ + dev->status_data[4] = (dev->rba - 1) & 0xffff; /*Last RBA processed*/ + dev->status_data[5] = (dev->rba - 1) >> 8; dev->status_data[6] = 0; /*Number of blocks requiring error recovery*/ + ui_sb_update_icon(SB_HDD | HDD_BUS_ESDI, 0); } -#define ESDI_ADAPTER_ONLY() do \ - { \ - if (dev->cmd_dev != ATTN_HOST_ADAPTER) \ - { \ - cmd_unsupported(dev); \ - return; \ - } \ - } while (0) +#define ESDI_ADAPTER_ONLY() \ + do { \ + if (dev->cmd_dev != ATTN_HOST_ADAPTER) { \ + cmd_unsupported(dev); \ + return; \ + } \ + } while (0) -#define ESDI_DRIVE_ONLY() do \ - { \ - if (dev->cmd_dev != ATTN_DEVICE_0 && dev->cmd_dev != ATTN_DEVICE_1) \ - { \ - cmd_unsupported(dev); \ - return; \ - } \ - if (dev->cmd_dev == ATTN_DEVICE_0) \ - drive = &dev->drives[0]; \ - else \ - drive = &dev->drives[1]; \ - } while (0) - +#define ESDI_DRIVE_ONLY() \ + do { \ + if (dev->cmd_dev != ATTN_DEVICE_0 && dev->cmd_dev != ATTN_DEVICE_1) { \ + cmd_unsupported(dev); \ + return; \ + } \ + if (dev->cmd_dev == ATTN_DEVICE_0) \ + drive = &dev->drives[0]; \ + else \ + drive = &dev->drives[1]; \ + } while (0) static void esdi_callback(void *priv) { - esdi_t *dev = (esdi_t *)priv; - drive_t *drive; - int val; + esdi_t *dev = (esdi_t *) priv; + const drive_t *drive; + int val; + double cmd_time = 0.0; esdi_mca_set_callback(dev, 0); /* If we are returning from a RESET, handle this first. */ if (dev->in_reset) { - dev->in_reset = 0; - dev->status = STATUS_IRQ; - dev->irq_status = IRQ_HOST_ADAPTER | IRQ_RESET_COMPLETE; + dev->in_reset = 0; + dev->status = STATUS_IRQ; + dev->irq_status = IRQ_HOST_ADAPTER | IRQ_RESET_COMPLETE; - return; + return; } switch (dev->command) { - case CMD_READ: - ESDI_DRIVE_ONLY(); + case CMD_READ: + ESDI_DRIVE_ONLY(); - if (! drive->present) { - device_not_present(dev); + if (!drive->present) { + device_not_present(dev); + return; + } + + switch (dev->cmd_state) { + case 0: + dev->rba = (dev->cmd_data[2] | (dev->cmd_data[3] << 16)) & 0x0fffffff; + + dev->sector_pos = 0; + dev->sector_count = dev->cmd_data[1]; + + if ((dev->rba + dev->sector_count) > hdd_image_get_last_sector(drive->hdd_num)) { + rba_out_of_range(dev); return; - } + } - switch (dev->cmd_state) { - case 0: - dev->rba = (dev->cmd_data[2] | (dev->cmd_data[3] << 16)) & 0x0fffffff; + dev->status = STATUS_IRQ | STATUS_CMD_IN_PROGRESS | STATUS_TRANSFER_REQ; + dev->irq_status = dev->cmd_dev | IRQ_DATA_TRANSFER_READY; + dev->irq_in_progress = 1; + set_irq(dev); - dev->sector_pos = 0; - dev->sector_count = dev->cmd_data[1]; + dev->cmd_state = 1; + esdi_mca_set_callback(dev, ESDI_TIME); + dev->data_pos = 0; + break; - if ((dev->rba + dev->sector_count) > hdd_image_get_last_sector(drive->hdd_num)) { - rba_out_of_range(dev); - return; - } - - dev->status = STATUS_IRQ | STATUS_CMD_IN_PROGRESS | STATUS_TRANSFER_REQ; - dev->irq_status = dev->cmd_dev | IRQ_DATA_TRANSFER_READY; - dev->irq_in_progress = 1; - set_irq(dev); - - dev->cmd_state = 1; - esdi_mca_set_callback(dev, ESDI_TIME); - dev->data_pos = 0; - break; - - case 1: - if (!(dev->basic_ctrl & CTRL_DMA_ENA)) { - esdi_mca_set_callback(dev, ESDI_TIME); - return; - } - - while (dev->sector_pos < dev->sector_count) { - if (! dev->data_pos) { - if (dev->rba >= drive->sectors) - fatal("Read past end of drive\n"); - hdd_image_read(drive->hdd_num, dev->rba, 1, (uint8_t *)dev->data); - ui_sb_update_icon(SB_HDD | HDD_BUS_ESDI, 1); - } - - while (dev->data_pos < 256) { - val = dma_channel_write(dev->dma, dev->data[dev->data_pos]); - - if (val == DMA_NODATA) { - esdi_mca_set_callback(dev, ESDI_TIME); - return; - } - - dev->data_pos++; - } - - dev->data_pos = 0; - dev->sector_pos++; - dev->rba++; - } - - dev->status = STATUS_CMD_IN_PROGRESS; - dev->cmd_state = 2; - esdi_mca_set_callback(dev, ESDI_TIME); - break; - - case 2: - complete_command_status(dev); - dev->status = STATUS_IRQ | STATUS_STATUS_OUT_FULL; - dev->irq_status = dev->cmd_dev | IRQ_CMD_COMPLETE_SUCCESS; - dev->irq_in_progress = 1; - set_irq(dev); - break; - } - break; - - case CMD_WRITE: - case CMD_WRITE_VERIFY: - ESDI_DRIVE_ONLY(); - if (! drive->present) { - device_not_present(dev); + case 1: + if (!(dev->basic_ctrl & CTRL_DMA_ENA)) { + esdi_mca_set_callback(dev, ESDI_TIME); return; - } - - switch (dev->cmd_state) { - case 0: - dev->rba = (dev->cmd_data[2] | (dev->cmd_data[3] << 16)) & 0x0fffffff; + } - dev->sector_pos = 0; - dev->sector_count = dev->cmd_data[1]; + while (dev->sector_pos < dev->sector_count) { + if (!dev->data_pos) { + if (dev->rba >= drive->sectors) + fatal("Read past end of drive\n"); + hdd_image_read(drive->hdd_num, dev->rba, 1, (uint8_t *) dev->data); + cmd_time += hdd_timing_read(&hdd[drive->hdd_num], dev->rba, 1); + cmd_time += esdi_mca_get_xfer_time(dev, 1); + } - if ((dev->rba + dev->sector_count) > hdd_image_get_last_sector(drive->hdd_num)) { - rba_out_of_range(dev); - return; - } + while (dev->data_pos < 256) { + val = dma_channel_write(dev->dma, dev->data[dev->data_pos]); - dev->status = STATUS_IRQ | STATUS_CMD_IN_PROGRESS | STATUS_TRANSFER_REQ; - dev->irq_status = dev->cmd_dev | IRQ_DATA_TRANSFER_READY; - dev->irq_in_progress = 1; - set_irq(dev); - - dev->cmd_state = 1; - esdi_mca_set_callback(dev, ESDI_TIME); - dev->data_pos = 0; - break; - - case 1: - if (! (dev->basic_ctrl & CTRL_DMA_ENA)) { - esdi_mca_set_callback(dev, ESDI_TIME); - return; - } - - while (dev->sector_pos < dev->sector_count) { - while (dev->data_pos < 256) { - val = dma_channel_read(dev->dma); - - if (val == DMA_NODATA) { - esdi_mca_set_callback(dev, ESDI_TIME); - return; - } - - dev->data[dev->data_pos++] = val & 0xffff; - } - - if (dev->rba >= drive->sectors) - fatal("Write past end of drive\n"); - hdd_image_write(drive->hdd_num, dev->rba, 1, (uint8_t *)dev->data); - dev->rba++; - dev->sector_pos++; - ui_sb_update_icon(SB_HDD | HDD_BUS_ESDI, - dev->cmd_dev == ATTN_DEVICE_0 ? 0 : 1); - - dev->data_pos = 0; - } - - dev->status = STATUS_CMD_IN_PROGRESS; - dev->cmd_state = 2; - esdi_mca_set_callback(dev, ESDI_TIME); - break; - - case 2: - complete_command_status(dev); - dev->status = STATUS_IRQ | STATUS_STATUS_OUT_FULL; - dev->irq_status = dev->cmd_dev | IRQ_CMD_COMPLETE_SUCCESS; - dev->irq_in_progress = 1; - set_irq(dev); - break; - } - break; - - case CMD_READ_VERIFY: - ESDI_DRIVE_ONLY(); - - if (! drive->present) { - device_not_present(dev); - return; - } - - if ((dev->rba + dev->sector_count) > hdd_image_get_last_sector(drive->hdd_num)) { - rba_out_of_range(dev); - return; - } - - dev->rba += dev->sector_count; - complete_command_status(dev); - dev->status = STATUS_IRQ | STATUS_STATUS_OUT_FULL; - dev->irq_status = dev->cmd_dev | IRQ_CMD_COMPLETE_SUCCESS; - dev->irq_in_progress = 1; - set_irq(dev); - break; - - case CMD_SEEK: - ESDI_DRIVE_ONLY(); - - if (! drive->present) { - device_not_present(dev); - return; - } - - complete_command_status(dev); - dev->status = STATUS_IRQ | STATUS_STATUS_OUT_FULL; - dev->irq_status = dev->cmd_dev | IRQ_CMD_COMPLETE_SUCCESS; - dev->irq_in_progress = 1; - set_irq(dev); - break; - - case CMD_GET_DEV_STATUS: - ESDI_DRIVE_ONLY(); - - if (! drive->present) { - device_not_present(dev); - return; - } - - if ((dev->status & STATUS_IRQ) || dev->irq_in_progress) - fatal("IRQ in progress %02x %i\n", dev->status, dev->irq_in_progress); - - dev->status_len = 9; - dev->status_data[0] = CMD_GET_DEV_STATUS | STATUS_LEN(9) | STATUS_DEVICE_HOST_ADAPTER; - dev->status_data[1] = 0x0000; /*Error bits*/ - dev->status_data[2] = 0x1900; /*Device status*/ - dev->status_data[3] = 0; /*ESDI Standard Status*/ - dev->status_data[4] = 0; /*ESDI Vendor Unique Status*/ - dev->status_data[5] = 0; - dev->status_data[6] = 0; - dev->status_data[7] = 0; - dev->status_data[8] = 0; - - dev->status = STATUS_IRQ | STATUS_STATUS_OUT_FULL; - dev->irq_status = dev->cmd_dev | IRQ_CMD_COMPLETE_SUCCESS; - dev->irq_in_progress = 1; - set_irq(dev); - break; - - case CMD_GET_DEV_CONFIG: - ESDI_DRIVE_ONLY(); - - if (! drive->present) { - device_not_present(dev); - return; - } - - if ((dev->status & STATUS_IRQ) || dev->irq_in_progress) - fatal("IRQ in progress %02x %i\n", dev->status, dev->irq_in_progress); - - dev->status_len = 6; - dev->status_data[0] = CMD_GET_DEV_CONFIG | STATUS_LEN(6) | STATUS_DEVICE_HOST_ADAPTER; - dev->status_data[1] = 0x10; /*Zero defect*/ - dev->status_data[2] = drive->sectors & 0xffff; - dev->status_data[3] = drive->sectors >> 16; - dev->status_data[4] = drive->tracks; - dev->status_data[5] = drive->hpc | (drive->spt << 16); - - esdi_mca_log("CMD_GET_DEV_CONFIG %i %04x %04x %04x %04x %04x %04x\n", - drive->sectors, - dev->status_data[0], dev->status_data[1], - dev->status_data[2], dev->status_data[3], - dev->status_data[4], dev->status_data[5]); - - dev->status = STATUS_IRQ | STATUS_STATUS_OUT_FULL; - dev->irq_status = dev->cmd_dev | IRQ_CMD_COMPLETE_SUCCESS; - dev->irq_in_progress = 1; - set_irq(dev); - break; - - case CMD_GET_POS_INFO: - ESDI_ADAPTER_ONLY(); - - if ((dev->status & STATUS_IRQ) || dev->irq_in_progress) - fatal("IRQ in progress %02x %i\n", dev->status, dev->irq_in_progress); - - dev->status_len = 5; - dev->status_data[0] = CMD_GET_POS_INFO | STATUS_LEN(5) | STATUS_DEVICE_HOST_ADAPTER; - dev->status_data[1] = 0xffdd; /*MCA ID*/ - dev->status_data[2] = dev->pos_regs[3] | - (dev->pos_regs[2] << 8); - dev->status_data[3] = 0xff; - dev->status_data[4] = 0xff; - - dev->status = STATUS_IRQ | STATUS_STATUS_OUT_FULL; - dev->irq_status = IRQ_HOST_ADAPTER | IRQ_CMD_COMPLETE_SUCCESS; - dev->irq_in_progress = 1; - set_irq(dev); - break; - - case 0x10: - ESDI_ADAPTER_ONLY(); - switch (dev->cmd_state) { - case 0: - dev->sector_pos = 0; - dev->sector_count = dev->cmd_data[1]; - if (dev->sector_count > 256) - fatal("Write sector buffer count %04x\n", dev->cmd_data[1]); - - dev->status = STATUS_IRQ | STATUS_CMD_IN_PROGRESS | STATUS_TRANSFER_REQ; - dev->irq_status = IRQ_HOST_ADAPTER | IRQ_DATA_TRANSFER_READY; - dev->irq_in_progress = 1; - set_irq(dev); - - dev->cmd_state = 1; - esdi_mca_set_callback(dev, ESDI_TIME); - dev->data_pos = 0; - break; - - case 1: - if (! (dev->basic_ctrl & CTRL_DMA_ENA)) { - esdi_mca_set_callback(dev, ESDI_TIME); - return; - } - while (dev->sector_pos < dev->sector_count) { - while (dev->data_pos < 256) { - val = dma_channel_read(dev->dma); - - if (val == DMA_NODATA) { - esdi_mca_set_callback(dev, ESDI_TIME); - return; - } - - dev->data[dev->data_pos++] = val & 0xffff;; - } - - memcpy(dev->sector_buffer[dev->sector_pos++], dev->data, 512); - dev->data_pos = 0; - } - - dev->status = STATUS_CMD_IN_PROGRESS; - dev->cmd_state = 2; - esdi_mca_set_callback(dev, ESDI_TIME); - break; - - case 2: - dev->status = STATUS_IRQ; - dev->irq_status = IRQ_HOST_ADAPTER | IRQ_CMD_COMPLETE_SUCCESS; - dev->irq_in_progress = 1; - set_irq(dev); - break; - } - break; - - case 0x11: - ESDI_ADAPTER_ONLY(); - switch (dev->cmd_state) { - case 0: - dev->sector_pos = 0; - dev->sector_count = dev->cmd_data[1]; - if (dev->sector_count > 256) - fatal("Read sector buffer count %04x\n", dev->cmd_data[1]); - - dev->status = STATUS_IRQ | STATUS_CMD_IN_PROGRESS | STATUS_TRANSFER_REQ; - dev->irq_status = IRQ_HOST_ADAPTER | IRQ_DATA_TRANSFER_READY; - dev->irq_in_progress = 1; - set_irq(dev); - - dev->cmd_state = 1; - esdi_mca_set_callback(dev, ESDI_TIME); - dev->data_pos = 0; - break; - - case 1: - if (! (dev->basic_ctrl & CTRL_DMA_ENA)) { - esdi_mca_set_callback(dev, ESDI_TIME); - return; - } - - while (dev->sector_pos < dev->sector_count) { - if (! dev->data_pos) - memcpy(dev->data, dev->sector_buffer[dev->sector_pos++], 512); - while (dev->data_pos < 256) { - val = dma_channel_write(dev->dma, dev->data[dev->data_pos]); - - if (val == DMA_NODATA) { - esdi_mca_set_callback(dev, ESDI_TIME); - return; - } - - dev->data_pos++; - } - - dev->data_pos = 0; - } - - dev->status = STATUS_CMD_IN_PROGRESS; - dev->cmd_state = 2; - esdi_mca_set_callback(dev, ESDI_TIME); - break; - - case 2: - dev->status = STATUS_IRQ; - dev->irq_status = IRQ_HOST_ADAPTER | IRQ_CMD_COMPLETE_SUCCESS; - dev->irq_in_progress = 1; - set_irq(dev); - break; - } - break; - - case 0x12: - ESDI_ADAPTER_ONLY(); - if ((dev->status & STATUS_IRQ) || dev->irq_in_progress) - fatal("IRQ in progress %02x %i\n", dev->status, dev->irq_in_progress); - - dev->status_len = 2; - dev->status_data[0] = 0x12 | STATUS_LEN(5) | STATUS_DEVICE_HOST_ADAPTER; - dev->status_data[1] = 0; - - dev->status = STATUS_IRQ | STATUS_STATUS_OUT_FULL; - dev->irq_status = IRQ_HOST_ADAPTER | IRQ_CMD_COMPLETE_SUCCESS; - dev->irq_in_progress = 1; - set_irq(dev); - break; - - case CMD_FORMAT_UNIT: - case CMD_FORMAT_PREPARE: - ESDI_DRIVE_ONLY(); - - if (! drive->present) { - device_not_present(dev); - return; - } - - switch (dev->cmd_state) { - case 0: - dev->rba = (dev->cmd_data[2] | (dev->cmd_data[3] << 16)) & 0x0fffffff; - - dev->sector_count = dev->cmd_data[1]; - - if ((dev->rba + dev->sector_count) > hdd_image_get_last_sector(drive->hdd_num)) { - rba_out_of_range(dev); - return; + if (val == DMA_NODATA) { + esdi_mca_set_callback(dev, ESDI_TIME + cmd_time); + return; } - - dev->status = STATUS_IRQ | STATUS_CMD_IN_PROGRESS | STATUS_TRANSFER_REQ; - dev->irq_status = dev->cmd_dev | IRQ_DATA_TRANSFER_READY; - dev->irq_in_progress = 1; - set_irq(dev); - - dev->cmd_state = 1; - esdi_mca_set_callback(dev, ESDI_TIME); - break; - - case 1: - if (!(dev->basic_ctrl & CTRL_DMA_ENA)) { - esdi_mca_set_callback(dev, ESDI_TIME); - return; - } - - hdd_image_zero(drive->hdd_num, dev->rba, dev->sector_count); - ui_sb_update_icon(SB_HDD | HDD_BUS_ESDI, 1); - - dev->status = STATUS_CMD_IN_PROGRESS; - dev->cmd_state = 2; - esdi_mca_set_callback(dev, ESDI_TIME); - break; - - case 2: - complete_command_status(dev); - dev->status = STATUS_IRQ | STATUS_STATUS_OUT_FULL; - dev->irq_status = dev->cmd_dev | IRQ_CMD_COMPLETE_SUCCESS; - dev->irq_in_progress = 1; - set_irq(dev); - break; - } - break; - default: - fatal("BAD COMMAND %02x %i\n", dev->command, dev->cmd_dev); + dev->data_pos++; + } + + dev->data_pos = 0; + dev->sector_pos++; + dev->rba++; + } + + dev->status = STATUS_CMD_IN_PROGRESS; + dev->cmd_state = 2; + esdi_mca_set_callback(dev, cmd_time); + break; + + case 2: + complete_command_status(dev); + dev->status = STATUS_IRQ | STATUS_STATUS_OUT_FULL; + dev->irq_status = dev->cmd_dev | IRQ_CMD_COMPLETE_SUCCESS; + dev->irq_in_progress = 1; + set_irq(dev); + break; + + default: + break; + } + break; + + case CMD_WRITE: + case CMD_WRITE_VERIFY: + ESDI_DRIVE_ONLY(); + if (!drive->present) { + device_not_present(dev); + return; + } + + switch (dev->cmd_state) { + case 0: + dev->rba = (dev->cmd_data[2] | (dev->cmd_data[3] << 16)) & 0x0fffffff; + + dev->sector_pos = 0; + dev->sector_count = dev->cmd_data[1]; + + if ((dev->rba + dev->sector_count) > hdd_image_get_last_sector(drive->hdd_num)) { + rba_out_of_range(dev); + return; + } + + dev->status = STATUS_IRQ | STATUS_CMD_IN_PROGRESS | STATUS_TRANSFER_REQ; + dev->irq_status = dev->cmd_dev | IRQ_DATA_TRANSFER_READY; + dev->irq_in_progress = 1; + set_irq(dev); + + dev->cmd_state = 1; + esdi_mca_set_callback(dev, ESDI_TIME); + dev->data_pos = 0; + break; + + case 1: + if (!(dev->basic_ctrl & CTRL_DMA_ENA)) { + esdi_mca_set_callback(dev, ESDI_TIME); + return; + } + + while (dev->sector_pos < dev->sector_count) { + while (dev->data_pos < 256) { + val = dma_channel_read(dev->dma); + + if (val == DMA_NODATA) { + esdi_mca_set_callback(dev, ESDI_TIME + cmd_time); + return; + } + + dev->data[dev->data_pos++] = val & 0xffff; + } + + if (dev->rba >= drive->sectors) + fatal("Write past end of drive\n"); + hdd_image_write(drive->hdd_num, dev->rba, 1, (uint8_t *) dev->data); + cmd_time += hdd_timing_write(&hdd[drive->hdd_num], dev->rba, 1); + cmd_time += esdi_mca_get_xfer_time(dev, 1); + dev->rba++; + dev->sector_pos++; + dev->data_pos = 0; + } + + dev->status = STATUS_CMD_IN_PROGRESS; + dev->cmd_state = 2; + esdi_mca_set_callback(dev, cmd_time); + break; + + case 2: + complete_command_status(dev); + dev->status = STATUS_IRQ | STATUS_STATUS_OUT_FULL; + dev->irq_status = dev->cmd_dev | IRQ_CMD_COMPLETE_SUCCESS; + dev->irq_in_progress = 1; + set_irq(dev); + break; + + default: + break; + } + break; + + case CMD_READ_VERIFY: + ESDI_DRIVE_ONLY(); + + if (!drive->present) { + device_not_present(dev); + return; + } + + switch (dev->cmd_state) { + case 0: + dev->rba = (dev->cmd_data[2] | (dev->cmd_data[3] << 16)) & 0x0fffffff; + dev->sector_count = dev->cmd_data[1]; + + if ((dev->rba + dev->sector_count) > hdd_image_get_last_sector(drive->hdd_num)) { + rba_out_of_range(dev); + return; + } + + cmd_time = hdd_timing_read(&hdd[drive->hdd_num], dev->rba, dev->sector_count); + esdi_mca_set_callback(dev, ESDI_TIME + cmd_time); + dev->cmd_state = 1; + break; + + case 1: + complete_command_status(dev); + dev->status = STATUS_IRQ | STATUS_STATUS_OUT_FULL; + dev->irq_status = dev->cmd_dev | IRQ_CMD_COMPLETE_SUCCESS; + dev->irq_in_progress = 1; + set_irq(dev); + break; + + default: + break; + } + break; + + case CMD_SEEK: + ESDI_DRIVE_ONLY(); + + if (!drive->present) { + device_not_present(dev); + return; + } + + if ((dev->rba + dev->sector_count) > hdd_image_get_last_sector(drive->hdd_num)) { + rba_out_of_range(dev); + return; + } + + switch (dev->cmd_state) { + case 0: + dev->rba = (dev->cmd_data[2] | (dev->cmd_data[3] << 16)) & 0x0fffffff; + cmd_time = hdd_seek_get_time(&hdd[drive->hdd_num], dev->rba, HDD_OP_SEEK, 0, 0.0); + esdi_mca_set_callback(dev, ESDI_TIME + cmd_time); + dev->cmd_state = 1; + break; + + case 1: + complete_command_status(dev); + dev->status = STATUS_IRQ | STATUS_STATUS_OUT_FULL; + dev->irq_status = dev->cmd_dev | IRQ_CMD_COMPLETE_SUCCESS; + dev->irq_in_progress = 1; + set_irq(dev); + break; + + default: + break; + } + break; + + case CMD_GET_DEV_STATUS: + ESDI_DRIVE_ONLY(); + + if (!drive->present) { + device_not_present(dev); + return; + } + + if ((dev->status & STATUS_IRQ) || dev->irq_in_progress) + fatal("IRQ in progress %02x %i\n", dev->status, dev->irq_in_progress); + + dev->status_len = 9; + dev->status_data[0] = CMD_GET_DEV_STATUS | STATUS_LEN(9) | STATUS_DEVICE_HOST_ADAPTER; + dev->status_data[1] = 0x0000; /*Error bits*/ + dev->status_data[2] = 0x1900; /*Device status*/ + dev->status_data[3] = 0; /*ESDI Standard Status*/ + dev->status_data[4] = 0; /*ESDI Vendor Unique Status*/ + dev->status_data[5] = 0; + dev->status_data[6] = 0; + dev->status_data[7] = 0; + dev->status_data[8] = 0; + + dev->status = STATUS_IRQ | STATUS_STATUS_OUT_FULL; + dev->irq_status = dev->cmd_dev | IRQ_CMD_COMPLETE_SUCCESS; + dev->irq_in_progress = 1; + set_irq(dev); + ui_sb_update_icon(SB_HDD | HDD_BUS_ESDI, 0); + break; + + case CMD_GET_DEV_CONFIG: + ESDI_DRIVE_ONLY(); + + if (!drive->present) { + device_not_present(dev); + return; + } + + if ((dev->status & STATUS_IRQ) || dev->irq_in_progress) + fatal("IRQ in progress %02x %i\n", dev->status, dev->irq_in_progress); + + dev->status_len = 6; + dev->status_data[0] = CMD_GET_DEV_CONFIG | STATUS_LEN(6) | STATUS_DEVICE_HOST_ADAPTER; + dev->status_data[1] = 0x10; /*Zero defect*/ + dev->status_data[2] = drive->sectors & 0xffff; + dev->status_data[3] = drive->sectors >> 16; + dev->status_data[4] = drive->tracks; + dev->status_data[5] = drive->hpc | (drive->spt << 16); + + esdi_mca_log("CMD_GET_DEV_CONFIG %i %04x %04x %04x %04x %04x %04x\n", + drive->sectors, + dev->status_data[0], dev->status_data[1], + dev->status_data[2], dev->status_data[3], + dev->status_data[4], dev->status_data[5]); + + dev->status = STATUS_IRQ | STATUS_STATUS_OUT_FULL; + dev->irq_status = dev->cmd_dev | IRQ_CMD_COMPLETE_SUCCESS; + dev->irq_in_progress = 1; + set_irq(dev); + ui_sb_update_icon(SB_HDD | HDD_BUS_ESDI, 0); + break; + + case CMD_GET_POS_INFO: + ESDI_ADAPTER_ONLY(); + + if ((dev->status & STATUS_IRQ) || dev->irq_in_progress) + fatal("IRQ in progress %02x %i\n", dev->status, dev->irq_in_progress); + + dev->status_len = 5; + dev->status_data[0] = CMD_GET_POS_INFO | STATUS_LEN(5) | STATUS_DEVICE_HOST_ADAPTER; + dev->status_data[1] = 0xffdd; /*MCA ID*/ + dev->status_data[2] = dev->pos_regs[3] | (dev->pos_regs[2] << 8); + dev->status_data[3] = 0xff; + dev->status_data[4] = 0xff; + + dev->status = STATUS_IRQ | STATUS_STATUS_OUT_FULL; + dev->irq_status = IRQ_HOST_ADAPTER | IRQ_CMD_COMPLETE_SUCCESS; + dev->irq_in_progress = 1; + set_irq(dev); + ui_sb_update_icon(SB_HDD | HDD_BUS_ESDI, 0); + break; + + case 0x10: + ESDI_ADAPTER_ONLY(); + switch (dev->cmd_state) { + case 0: + dev->sector_pos = 0; + dev->sector_count = dev->cmd_data[1]; + if (dev->sector_count > 256) + fatal("Write sector buffer count %04x\n", dev->cmd_data[1]); + + dev->status = STATUS_IRQ | STATUS_CMD_IN_PROGRESS | STATUS_TRANSFER_REQ; + dev->irq_status = IRQ_HOST_ADAPTER | IRQ_DATA_TRANSFER_READY; + dev->irq_in_progress = 1; + set_irq(dev); + + dev->cmd_state = 1; + esdi_mca_set_callback(dev, ESDI_TIME); + dev->data_pos = 0; + break; + + case 1: + if (!(dev->basic_ctrl & CTRL_DMA_ENA)) { + esdi_mca_set_callback(dev, ESDI_TIME); + return; + } + while (dev->sector_pos < dev->sector_count) { + while (dev->data_pos < 256) { + val = dma_channel_read(dev->dma); + + if (val == DMA_NODATA) { + esdi_mca_set_callback(dev, ESDI_TIME); + return; + } + + dev->data[dev->data_pos++] = val & 0xffff; + } + + memcpy(dev->sector_buffer[dev->sector_pos++], dev->data, 512); + dev->data_pos = 0; + } + + dev->status = STATUS_CMD_IN_PROGRESS; + dev->cmd_state = 2; + esdi_mca_set_callback(dev, ESDI_TIME); + break; + + case 2: + dev->status = STATUS_IRQ; + dev->irq_status = IRQ_HOST_ADAPTER | IRQ_CMD_COMPLETE_SUCCESS; + dev->irq_in_progress = 1; + set_irq(dev); + ui_sb_update_icon(SB_HDD | HDD_BUS_ESDI, 0); + break; + + default: + break; + } + break; + + case 0x11: + ESDI_ADAPTER_ONLY(); + switch (dev->cmd_state) { + case 0: + dev->sector_pos = 0; + dev->sector_count = dev->cmd_data[1]; + if (dev->sector_count > 256) + fatal("Read sector buffer count %04x\n", dev->cmd_data[1]); + + dev->status = STATUS_IRQ | STATUS_CMD_IN_PROGRESS | STATUS_TRANSFER_REQ; + dev->irq_status = IRQ_HOST_ADAPTER | IRQ_DATA_TRANSFER_READY; + dev->irq_in_progress = 1; + set_irq(dev); + + dev->cmd_state = 1; + esdi_mca_set_callback(dev, ESDI_TIME); + dev->data_pos = 0; + break; + + case 1: + if (!(dev->basic_ctrl & CTRL_DMA_ENA)) { + esdi_mca_set_callback(dev, ESDI_TIME); + return; + } + + while (dev->sector_pos < dev->sector_count) { + if (!dev->data_pos) + memcpy(dev->data, dev->sector_buffer[dev->sector_pos++], 512); + while (dev->data_pos < 256) { + val = dma_channel_write(dev->dma, dev->data[dev->data_pos]); + + if (val == DMA_NODATA) { + esdi_mca_set_callback(dev, ESDI_TIME); + return; + } + + dev->data_pos++; + } + + dev->data_pos = 0; + } + + dev->status = STATUS_CMD_IN_PROGRESS; + dev->cmd_state = 2; + esdi_mca_set_callback(dev, ESDI_TIME); + break; + + case 2: + dev->status = STATUS_IRQ; + dev->irq_status = IRQ_HOST_ADAPTER | IRQ_CMD_COMPLETE_SUCCESS; + dev->irq_in_progress = 1; + set_irq(dev); + ui_sb_update_icon(SB_HDD | HDD_BUS_ESDI, 0); + break; + + default: + break; + } + break; + + case 0x12: + ESDI_ADAPTER_ONLY(); + if ((dev->status & STATUS_IRQ) || dev->irq_in_progress) + fatal("IRQ in progress %02x %i\n", dev->status, dev->irq_in_progress); + + dev->status_len = 2; + dev->status_data[0] = 0x12 | STATUS_LEN(5) | STATUS_DEVICE_HOST_ADAPTER; + dev->status_data[1] = 0; + + dev->status = STATUS_IRQ | STATUS_STATUS_OUT_FULL; + dev->irq_status = IRQ_HOST_ADAPTER | IRQ_CMD_COMPLETE_SUCCESS; + dev->irq_in_progress = 1; + set_irq(dev); + ui_sb_update_icon(SB_HDD | HDD_BUS_ESDI, 0); + break; + + case CMD_FORMAT_UNIT: + case CMD_FORMAT_PREPARE: + ESDI_DRIVE_ONLY(); + + if (!drive->present) { + device_not_present(dev); + return; + } + + switch (dev->cmd_state) { + case 0: + dev->rba = (dev->cmd_data[2] | (dev->cmd_data[3] << 16)) & 0x0fffffff; + + dev->sector_count = dev->cmd_data[1]; + + if ((dev->rba + dev->sector_count) > hdd_image_get_last_sector(drive->hdd_num)) { + rba_out_of_range(dev); + return; + } + + dev->status = STATUS_IRQ | STATUS_CMD_IN_PROGRESS | STATUS_TRANSFER_REQ; + dev->irq_status = dev->cmd_dev | IRQ_DATA_TRANSFER_READY; + dev->irq_in_progress = 1; + set_irq(dev); + + dev->cmd_state = 1; + esdi_mca_set_callback(dev, ESDI_TIME); + break; + + case 1: + if (!(dev->basic_ctrl & CTRL_DMA_ENA)) { + esdi_mca_set_callback(dev, ESDI_TIME); + return; + } + + hdd_image_zero(drive->hdd_num, dev->rba, dev->sector_count); + + dev->status = STATUS_CMD_IN_PROGRESS; + dev->cmd_state = 2; + esdi_mca_set_callback(dev, ESDI_TIME); + break; + + case 2: + complete_command_status(dev); + dev->status = STATUS_IRQ | STATUS_STATUS_OUT_FULL; + dev->irq_status = dev->cmd_dev | IRQ_CMD_COMPLETE_SUCCESS; + dev->irq_in_progress = 1; + set_irq(dev); + break; + + default: + break; + } + break; + + default: + fatal("BAD COMMAND %02x %i\n", dev->command, dev->cmd_dev); } } - static uint8_t esdi_read(uint16_t port, void *priv) { - esdi_t *dev = (esdi_t *)priv; + esdi_t *dev = (esdi_t *) priv; uint8_t ret = 0xff; switch (port & 7) { - case 2: /*Basic status register*/ - ret = dev->status; - break; + case 2: /*Basic status register*/ + ret = dev->status; + break; - case 3: /*IRQ status*/ - dev->status &= ~STATUS_IRQ; - ret = dev->irq_status; - break; + case 3: /*IRQ status*/ + dev->status &= ~STATUS_IRQ; + ret = dev->irq_status; + break; - default: - fatal("esdi_read port=%04x\n", port); + default: + esdi_mca_log("esdi_read port=%04x\n", port); + break; } - return(ret); + return ret; } - static void esdi_write(uint16_t port, uint8_t val, void *priv) { - esdi_t *dev = (esdi_t *)priv; + esdi_t *dev = (esdi_t *) priv; esdi_mca_log("ESDI: wr(%04x, %02x)\n", port & 7, val); switch (port & 7) { - case 2: /*Basic control register*/ - if ((dev->basic_ctrl & CTRL_RESET) && !(val & CTRL_RESET)) { - dev->in_reset = 1; - esdi_mca_set_callback(dev, ESDI_TIME * 50); - dev->status = STATUS_BUSY; - } - dev->basic_ctrl = val; + case 2: /*Basic control register*/ + if ((dev->basic_ctrl & CTRL_RESET) && !(val & CTRL_RESET)) { + dev->in_reset = 1; + esdi_mca_set_callback(dev, ESDI_TIME * 50); + dev->status = STATUS_BUSY; + } + dev->basic_ctrl = val; - if (! (dev->basic_ctrl & CTRL_IRQ_ENA)) - picintc(1 << 14); - break; + if (!(dev->basic_ctrl & CTRL_IRQ_ENA)) + picintc(1 << 14); + break; - case 3: /*Attention register*/ - switch (val & ATTN_DEVICE_SEL) { - case ATTN_HOST_ADAPTER: - switch (val & ATTN_REQ_MASK) { - case ATTN_CMD_REQ: - if (dev->cmd_req_in_progress) - fatal("Try to start command on in_progress adapter\n"); - dev->cmd_req_in_progress = 1; - dev->cmd_dev = ATTN_HOST_ADAPTER; - dev->status |= STATUS_BUSY; - dev->cmd_pos = 0; - dev->status_pos = 0; - break; + case 3: /*Attention register*/ + switch (val & ATTN_DEVICE_SEL) { + case ATTN_HOST_ADAPTER: + switch (val & ATTN_REQ_MASK) { + case ATTN_CMD_REQ: + if (dev->cmd_req_in_progress) + fatal("Try to start command on in_progress adapter\n"); + dev->cmd_req_in_progress = 1; + dev->cmd_dev = ATTN_HOST_ADAPTER; + dev->status |= STATUS_BUSY; + dev->cmd_pos = 0; + dev->status_pos = 0; + break; - case ATTN_EOI: - dev->irq_in_progress = 0; - dev->status &= ~STATUS_IRQ; - clear_irq(dev); - break; + case ATTN_EOI: + dev->irq_in_progress = 0; + dev->status &= ~STATUS_IRQ; + clear_irq(dev); + break; - case ATTN_RESET: - dev->in_reset = 1; - esdi_mca_set_callback(dev, ESDI_TIME * 50); - dev->status = STATUS_BUSY; - break; - - default: - fatal("Bad attention request %02x\n", val); - } - break; + case ATTN_RESET: + dev->in_reset = 1; + esdi_mca_set_callback(dev, ESDI_TIME * 50); + dev->status = STATUS_BUSY; + break; - case ATTN_DEVICE_0: - switch (val & ATTN_REQ_MASK) { - case ATTN_CMD_REQ: - if (dev->cmd_req_in_progress) - fatal("Try to start command on in_progress device0\n"); - dev->cmd_req_in_progress = 1; - dev->cmd_dev = ATTN_DEVICE_0; - dev->status |= STATUS_BUSY; - dev->cmd_pos = 0; - dev->status_pos = 0; - break; - - case ATTN_EOI: - dev->irq_in_progress = 0; - dev->status &= ~STATUS_IRQ; - clear_irq(dev); - break; - - default: - fatal("Bad attention request %02x\n", val); - } - break; + default: + fatal("Bad attention request %02x\n", val); + } + break; - case ATTN_DEVICE_1: - switch (val & ATTN_REQ_MASK) { - case ATTN_CMD_REQ: - if (dev->cmd_req_in_progress) - fatal("Try to start command on in_progress device0\n"); - dev->cmd_req_in_progress = 1; - dev->cmd_dev = ATTN_DEVICE_1; - dev->status |= STATUS_BUSY; - dev->cmd_pos = 0; - dev->status_pos = 0; - break; + case ATTN_DEVICE_0: + switch (val & ATTN_REQ_MASK) { + case ATTN_CMD_REQ: + if (dev->cmd_req_in_progress) + fatal("Try to start command on in_progress device0\n"); + dev->cmd_req_in_progress = 1; + dev->cmd_dev = ATTN_DEVICE_0; + dev->status |= STATUS_BUSY; + dev->cmd_pos = 0; + dev->status_pos = 0; + break; - case ATTN_EOI: - dev->irq_in_progress = 0; - dev->status &= ~STATUS_IRQ; - clear_irq(dev); - break; - - default: - fatal("Bad attention request %02x\n", val); - } - break; + case ATTN_EOI: + dev->irq_in_progress = 0; + dev->status &= ~STATUS_IRQ; + clear_irq(dev); + break; - default: - fatal("Attention to unknown device %02x\n", val); - } - break; + default: + fatal("Bad attention request %02x\n", val); + } + break; - default: - fatal("esdi_write port=%04x val=%02x\n", port, val); + case ATTN_DEVICE_1: + switch (val & ATTN_REQ_MASK) { + case ATTN_CMD_REQ: + if (dev->cmd_req_in_progress) + fatal("Try to start command on in_progress device0\n"); + dev->cmd_req_in_progress = 1; + dev->cmd_dev = ATTN_DEVICE_1; + dev->status |= STATUS_BUSY; + dev->cmd_pos = 0; + dev->status_pos = 0; + break; + + case ATTN_EOI: + dev->irq_in_progress = 0; + dev->status &= ~STATUS_IRQ; + clear_irq(dev); + break; + + default: + fatal("Bad attention request %02x\n", val); + } + break; + + default: + fatal("Attention to unknown device %02x\n", val); + } + break; + + default: + fatal("esdi_write port=%04x val=%02x\n", port, val); } } - static uint16_t esdi_readw(uint16_t port, void *priv) { - esdi_t *dev = (esdi_t *)priv; + esdi_t *dev = (esdi_t *) priv; uint16_t ret = 0xffff; switch (port & 7) { - case 0: /*Status Interface Register*/ - if (dev->status_pos >= dev->status_len) - return(0); - ret = dev->status_data[dev->status_pos++]; if (dev->status_pos >= dev->status_len) { - dev->status &= ~STATUS_STATUS_OUT_FULL; - dev->status_pos = dev->status_len = 0; - } - break; + case 0: /*Status Interface Register*/ + if (dev->status_pos >= dev->status_len) + return 0; + ret = dev->status_data[dev->status_pos++]; + if (dev->status_pos >= dev->status_len) { + dev->status &= ~STATUS_STATUS_OUT_FULL; + dev->status_pos = dev->status_len = 0; + } + break; - default: - fatal("esdi_readw port=%04x\n", port); + default: + fatal("esdi_readw port=%04x\n", port); } - - return(ret); -} + return ret; +} static void esdi_writew(uint16_t port, uint16_t val, void *priv) { - esdi_t *dev = (esdi_t *)priv; + esdi_t *dev = (esdi_t *) priv; esdi_mca_log("ESDI: wrw(%04x, %04x)\n", port & 7, val); switch (port & 7) { - case 0: /*Command Interface Register*/ - if (dev->cmd_pos >= 4) - fatal("CIR pos 4\n"); - dev->cmd_data[dev->cmd_pos++] = val; - if (((dev->cmd_data[0] & CMD_SIZE_4) && dev->cmd_pos == 4) || - (!(dev->cmd_data[0] & CMD_SIZE_4) && dev->cmd_pos == 2)) { - dev->cmd_pos = 0; - dev->cmd_req_in_progress = 0; - dev->cmd_state = 0; + case 0: /*Command Interface Register*/ + if (dev->cmd_pos >= 4) + fatal("CIR pos 4\n"); + dev->cmd_data[dev->cmd_pos++] = val; + if (((dev->cmd_data[0] & CMD_SIZE_4) && dev->cmd_pos == 4) || (!(dev->cmd_data[0] & CMD_SIZE_4) && dev->cmd_pos == 2)) { + dev->cmd_pos = 0; + dev->cmd_req_in_progress = 0; + dev->cmd_state = 0; - if ((dev->cmd_data[0] & CMD_DEVICE_SEL) != dev->cmd_dev) - fatal("Command device mismatch with attn\n"); - dev->command = dev->cmd_data[0] & CMD_MASK; - esdi_mca_set_callback(dev, ESDI_TIME); - dev->status = STATUS_BUSY; - dev->data_pos = 0; - } - break; + if ((dev->cmd_data[0] & CMD_DEVICE_SEL) != dev->cmd_dev) + fatal("Command device mismatch with attn\n"); + dev->command = dev->cmd_data[0] & CMD_MASK; + esdi_mca_set_callback(dev, ESDI_TIME); + dev->status = STATUS_BUSY; + dev->data_pos = 0; + ui_sb_update_icon(SB_HDD | HDD_BUS_ESDI, 1); + } + break; - default: - fatal("esdi_writew port=%04x val=%04x\n", port, val); + default: + fatal("esdi_writew port=%04x val=%04x\n", port, val); } } - static uint8_t esdi_mca_read(int port, void *priv) { - esdi_t *dev = (esdi_t *)priv; + const esdi_t *dev = (esdi_t *) priv; esdi_mca_log("ESDI: mcard(%04x)\n", port); - return(dev->pos_regs[port & 7]); + return (dev->pos_regs[port & 7]); } - static void esdi_mca_write(int port, uint8_t val, void *priv) { - esdi_t *dev = (esdi_t *)priv; + esdi_t *dev = (esdi_t *) priv; esdi_mca_log("ESDI: mcawr(%04x, %02x) pos[2]=%02x pos[3]=%02x\n", - port, val, dev->pos_regs[2], dev->pos_regs[3]); + port, val, dev->pos_regs[2], dev->pos_regs[3]); if (port < 0x102) - return; + return; /* Save the new value. */ dev->pos_regs[port & 7] = val; io_removehandler(ESDI_IOADDR_PRI, 8, - esdi_read, esdi_readw, NULL, - esdi_write, esdi_writew, NULL, dev); + esdi_read, esdi_readw, NULL, + esdi_write, esdi_writew, NULL, dev); mem_mapping_disable(&dev->bios_rom.mapping); - switch(dev->pos_regs[2] & 0x3c) { - case 0x14: - dev->dma = 5; - break; - case 0x18: - dev->dma = 6; - break; - case 0x1c: - dev->dma = 7; - break; - case 0x00: - dev->dma = 0; - break; - case 0x04: - dev->dma = 1; - break; - case 0x0c: - dev->dma = 3; - break; - case 0x10: - dev->dma = 4; - break; + switch (dev->pos_regs[2] & 0x3c) { + case 0x14: + dev->dma = 5; + break; + case 0x18: + dev->dma = 6; + break; + case 0x1c: + dev->dma = 7; + break; + case 0x00: + dev->dma = 0; + break; + case 0x04: + dev->dma = 1; + break; + case 0x0c: + dev->dma = 3; + break; + case 0x10: + dev->dma = 4; + break; + + default: + break; } if (dev->pos_regs[2] & 1) { - io_sethandler(ESDI_IOADDR_PRI, 8, - esdi_read, esdi_readw, NULL, - esdi_write, esdi_writew, NULL, dev); + io_sethandler(ESDI_IOADDR_PRI, 8, + esdi_read, esdi_readw, NULL, + esdi_write, esdi_writew, NULL, dev); - if (!(dev->pos_regs[3] & 8)) { - mem_mapping_enable(&dev->bios_rom.mapping); - mem_mapping_set_addr(&dev->bios_rom.mapping, - ((dev->pos_regs[3] & 7) * 0x4000) + 0xc0000, 0x4000); - } + if (!(dev->pos_regs[3] & 8)) { + mem_mapping_enable(&dev->bios_rom.mapping); + mem_mapping_set_addr(&dev->bios_rom.mapping, + ((dev->pos_regs[3] & 7) * 0x4000) + 0xc0000, 0x4000); + } - /* Say hello. */ - esdi_mca_log("ESDI: I/O=3510, IRQ=14, DMA=%d, BIOS @%05X\n", - dev->dma, dev->bios); + /* Say hello. */ + esdi_mca_log("ESDI: I/O=3510, IRQ=14, DMA=%d, BIOS @%05X\n", + dev->dma, dev->bios); } } - static uint8_t esdi_mca_feedb(void *priv) { - esdi_t *dev = (esdi_t *)priv; + const esdi_t *dev = (esdi_t *) priv; return (dev->pos_regs[2] & 1); } - static void * -esdi_init(const device_t *info) +esdi_init(UNUSED(const device_t *info)) { drive_t *drive; - esdi_t *dev; - int c, i; + esdi_t *dev; + uint8_t c; + uint8_t i; dev = malloc(sizeof(esdi_t)); - if (dev == NULL) return(NULL); + if (dev == NULL) + return (NULL); memset(dev, 0x00, sizeof(esdi_t)); /* Mark as unconfigured. */ dev->irq_status = 0xff; rom_init_interleaved(&dev->bios_rom, - BIOS_FILE_H, BIOS_FILE_L, - 0xc8000, 0x4000, 0x3fff, 0, MEM_MAPPING_EXTERNAL); + BIOS_FILE_H, BIOS_FILE_L, + 0xc8000, 0x4000, 0x3fff, 0, MEM_MAPPING_EXTERNAL); mem_mapping_disable(&dev->bios_rom.mapping); dev->drives[0].present = dev->drives[1].present = 0; - for (c=0,i=0; idrives[hdd[i].esdi_channel]; + for (c = 0, i = 0; i < HDD_NUM; i++) { + if ((hdd[i].bus == HDD_BUS_ESDI) && (hdd[i].esdi_channel < ESDI_NUM)) { + /* This is an ESDI drive. */ + drive = &dev->drives[hdd[i].esdi_channel]; - /* Try to load an image for the drive. */ - if (! hdd_image_load(i)) { - /* Nope. */ - drive->present = 0; - continue; - } + /* Try to load an image for the drive. */ + if (!hdd_image_load(i)) { + /* Nope. */ + drive->present = 0; + continue; + } - /* OK, so fill in geometry info. */ - drive->spt = hdd[i].spt; - drive->hpc = hdd[i].hpc; - drive->tracks = hdd[i].tracks; - drive->sectors = hdd_image_get_last_sector(i) + 1; - drive->hdd_num = i; + hdd_preset_apply(i); - /* Mark drive as present. */ - drive->present = 1; - } + /* OK, so fill in geometry info. */ + drive->spt = hdd[i].spt; + drive->hpc = hdd[i].hpc; + drive->tracks = hdd[i].tracks; + drive->sectors = hdd_image_get_last_sector(i) + 1; + drive->hdd_num = i; - if (++c >= ESDI_NUM) break; + /* Mark drive as present. */ + drive->present = 1; + } + + if (++c >= ESDI_NUM) + break; } /* Set the MCA ID for this controller, 0xFFDD. */ @@ -1147,42 +1202,44 @@ esdi_init(const device_t *info) dev->status = STATUS_BUSY; /* Set the reply timer. */ - timer_add(&dev->timer, esdi_callback, dev, 0); + timer_add(&dev->timer, esdi_callback, dev, 0); - return(dev); + return dev; } - static void esdi_close(void *priv) { - esdi_t *dev = (esdi_t *)priv; - drive_t *drive; - int d; + esdi_t *dev = (esdi_t *) priv; + const drive_t *drive; dev->drives[0].present = dev->drives[1].present = 0; - for (d=0; d<2; d++) { - drive = &dev->drives[d]; + for (uint8_t d = 0; d < 2; d++) { + drive = &dev->drives[d]; - hdd_image_close(drive->hdd_num); + hdd_image_close(drive->hdd_num); } free(dev); } - static int esdi_available(void) { - return(rom_present(BIOS_FILE_L) && rom_present(BIOS_FILE_H)); + return (rom_present(BIOS_FILE_L) && rom_present(BIOS_FILE_H)); } - const device_t esdi_ps2_device = { - "IBM PS/2 ESDI Fixed Disk Adapter (MCA)", - "esdi_mca", - DEVICE_MCA, 0, - esdi_init, esdi_close, NULL, - { esdi_available }, NULL, NULL, NULL + .name = "IBM PS/2 ESDI Fixed Disk Adapter (MCA)", + .internal_name = "esdi_mca", + .flags = DEVICE_MCA, + .local = 0, + .init = esdi_init, + .close = esdi_close, + .reset = NULL, + { .available = esdi_available }, + .speed_changed = NULL, + .force_redraw = NULL, + .config = NULL }; diff --git a/src/disk/hdc_ide.c b/src/disk/hdc_ide.c index 6db383cf0..2bb83b4ab 100644 --- a/src/disk/hdc_ide.c +++ b/src/disk/hdc_ide.c @@ -1,26 +1,24 @@ /* - * 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. + * 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. + * This file is part of the 86Box distribution. * - * Implementation of the IDE emulation for hard disks and ATAPI - * CD-ROM devices. + * Implementation of the IDE emulation for hard disks and ATAPI + * CD-ROM devices. * * * - * Authors: Sarah Walker, - * Miran Grca, + * Authors: Sarah Walker, + * Miran Grca, * - * Copyright 2008-2020 Sarah Walker. - * Copyright 2016-2020 Miran Grca. + * Copyright 2008-2020 Sarah Walker. + * Copyright 2016-2020 Miran Grca. */ -#define __USE_LARGEFILE64 -#define _LARGEFILE_SOURCE -#define _LARGEFILE64_SOURCE #include +#include #include #include #include @@ -49,346 +47,375 @@ #include <86box/zip.h> #include <86box/version.h> - /* Bits of 'atastat' */ -#define ERR_STAT 0x01 /* Error */ -#define IDX_STAT 0x02 /* Index */ -#define CORR_STAT 0x04 /* Corrected data */ -#define DRQ_STAT 0x08 /* Data request */ -#define DSC_STAT 0x10 /* Drive seek complete */ -#define SERVICE_STAT 0x10 /* ATAPI service */ -#define DWF_STAT 0x20 /* Drive write fault */ -#define DRDY_STAT 0x40 /* Ready */ -#define BSY_STAT 0x80 /* Busy */ +#define ERR_STAT 0x01 /* Error */ +#define IDX_STAT 0x02 /* Index */ +#define CORR_STAT 0x04 /* Corrected data */ +#define DRQ_STAT 0x08 /* Data request */ +#define DSC_STAT 0x10 /* Drive seek complete */ +#define SERVICE_STAT 0x10 /* ATAPI service */ +#define DWF_STAT 0x20 /* Drive write fault */ +#define DRDY_STAT 0x40 /* Ready */ +#define BSY_STAT 0x80 /* Busy */ /* Bits of 'error' */ -#define AMNF_ERR 0x01 /* Address mark not found */ -#define TK0NF_ERR 0x02 /* Track 0 not found */ -#define ABRT_ERR 0x04 /* Command aborted */ -#define MCR_ERR 0x08 /* Media change request */ -#define IDNF_ERR 0x10 /* Sector ID not found */ -#define MC_ERR 0x20 /* Media change */ -#define UNC_ERR 0x40 /* Uncorrectable data error */ -#define BBK_ERR 0x80 /* Bad block mark detected */ +#define AMNF_ERR 0x01 /* Address mark not found */ +#define TK0NF_ERR 0x02 /* Track 0 not found */ +#define ABRT_ERR 0x04 /* Command aborted */ +#define MCR_ERR 0x08 /* Media change request */ +#define IDNF_ERR 0x10 /* Sector ID not found */ +#define MC_ERR 0x20 /* Media change */ +#define UNC_ERR 0x40 /* Uncorrectable data error */ +#define BBK_ERR 0x80 /* Bad block mark detected */ /* ATA Commands */ -#define WIN_NOP 0x00 -#define WIN_SRST 0x08 /* ATAPI Device Reset */ -#define WIN_RECAL 0x10 -#define WIN_READ 0x20 /* 28-Bit Read */ -#define WIN_READ_NORETRY 0x21 /* 28-Bit Read - no retry */ -#define WIN_WRITE 0x30 /* 28-Bit Write */ -#define WIN_WRITE_NORETRY 0x31 /* 28-Bit Write - no retry */ -#define WIN_VERIFY 0x40 /* 28-Bit Verify */ -#define WIN_VERIFY_ONCE 0x41 /* Added by OBattler - deprected older ATA command, according to the specification I found, it is identical to 0x40 */ -#define WIN_FORMAT 0x50 -#define WIN_SEEK 0x70 -#define WIN_DRIVE_DIAGNOSTICS 0x90 /* Execute Drive Diagnostics */ -#define WIN_SPECIFY 0x91 /* Initialize Drive Parameters */ -#define WIN_PACKETCMD 0xA0 /* Send a packet command. */ -#define WIN_PIDENTIFY 0xA1 /* Identify ATAPI device */ -#define WIN_READ_MULTIPLE 0xC4 -#define WIN_WRITE_MULTIPLE 0xC5 -#define WIN_SET_MULTIPLE_MODE 0xC6 -#define WIN_READ_DMA 0xC8 -#define WIN_READ_DMA_ALT 0xC9 -#define WIN_WRITE_DMA 0xCA -#define WIN_WRITE_DMA_ALT 0xCB -#define WIN_STANDBYNOW1 0xE0 -#define WIN_IDLENOW1 0xE1 -#define WIN_SETIDLE1 0xE3 -#define WIN_CHECKPOWERMODE1 0xE5 -#define WIN_SLEEP1 0xE6 -#define WIN_IDENTIFY 0xEC /* Ask drive to identify itself */ -#define WIN_SET_FEATURES 0xEF -#define WIN_READ_NATIVE_MAX 0xF8 +#define WIN_NOP 0x00 +#define WIN_SRST 0x08 /* ATAPI Device Reset */ +#define WIN_RECAL 0x10 +#define WIN_READ 0x20 /* 28-Bit Read */ +#define WIN_READ_NORETRY 0x21 /* 28-Bit Read - no retry */ +#define WIN_WRITE 0x30 /* 28-Bit Write */ +#define WIN_WRITE_NORETRY 0x31 /* 28-Bit Write - no retry */ +#define WIN_VERIFY 0x40 /* 28-Bit Verify */ +#define WIN_VERIFY_ONCE 0x41 /* Added by OBattler - deprected older ATA command, according to the specification I found, it is identical to 0x40 */ +#define WIN_FORMAT 0x50 +#define WIN_SEEK 0x70 +#define WIN_DRIVE_DIAGNOSTICS 0x90 /* Execute Drive Diagnostics */ +#define WIN_SPECIFY 0x91 /* Initialize Drive Parameters */ +#define WIN_PACKETCMD 0xa0 /* Send a packet command. */ +#define WIN_PIDENTIFY 0xa1 /* Identify ATAPI device */ +#define WIN_READ_MULTIPLE 0xc4 +#define WIN_WRITE_MULTIPLE 0xc5 +#define WIN_SET_MULTIPLE_MODE 0xc6 +#define WIN_READ_DMA 0xc8 +#define WIN_READ_DMA_ALT 0xc9 +#define WIN_WRITE_DMA 0xcA +#define WIN_WRITE_DMA_ALT 0xcB +#define WIN_STANDBYNOW1 0xe0 +#define WIN_IDLENOW1 0xe1 +#define WIN_SETIDLE1 0xe3 +#define WIN_CHECKPOWERMODE1 0xe5 +#define WIN_SLEEP1 0xe6 +#define WIN_IDENTIFY 0xeC /* Ask drive to identify itself */ +#define WIN_SET_FEATURES 0xeF +#define WIN_READ_NATIVE_MAX 0xf8 -#define FEATURE_SET_TRANSFER_MODE 0x03 -#define FEATURE_ENABLE_IRQ_OVERLAPPED 0x5d -#define FEATURE_ENABLE_IRQ_SERVICE 0x5e -#define FEATURE_DISABLE_REVERT 0x66 -#define FEATURE_ENABLE_REVERT 0xcc -#define FEATURE_DISABLE_IRQ_OVERLAPPED 0xdd -#define FEATURE_DISABLE_IRQ_SERVICE 0xde +#define FEATURE_SET_TRANSFER_MODE 0x03 +#define FEATURE_ENABLE_IRQ_OVERLAPPED 0x5d +#define FEATURE_ENABLE_IRQ_SERVICE 0x5e +#define FEATURE_DISABLE_REVERT 0x66 +#define FEATURE_ENABLE_REVERT 0xcc +#define FEATURE_DISABLE_IRQ_OVERLAPPED 0xdd +#define FEATURE_DISABLE_IRQ_SERVICE 0xde -#define IDE_TIME 10.0 +#define IDE_TIME 10.0 +#define IDE_ATAPI_IS_EARLY ide->sc->pad0 -typedef struct { - int bit32, cur_dev, - irq, inited, - diag, force_ata3; - uint16_t base_main, side_main; - pc_timer_t timer; - ide_t *ide[2]; -} ide_board_t; - -typedef struct { - int (*dma)(int channel, uint8_t *data, int transfer_length, int out, void *priv); - void (*set_irq)(int channel, void *priv); - void *priv; +typedef struct ide_bm_t { + int (*dma)(uint8_t *data, int transfer_length, int out, void *priv); + void (*set_irq)(uint8_t status, void *priv); + void *priv; } ide_bm_t; -static ide_board_t *ide_boards[4] = { NULL, NULL, NULL, NULL }; -static ide_bm_t *ide_bm[4] = { NULL, NULL, NULL, NULL }; +typedef struct ide_board_t { + uint8_t devctl; + uint8_t pad; + uint16_t base[2]; + int bit32; + int cur_dev; + int irq; + int inited; + int diag; + int force_ata3; + + pc_timer_t timer; + + ide_t *ide[2]; + ide_bm_t *bm; +} ide_board_t; + +ide_board_t *ide_boards[IDE_BUS_MAX]; static uint8_t ide_ter_pnp_rom[] = { - 0x09, 0xf8, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, /* BOX0001, serial 0, dummy checksum (filled in by isapnp_add_card) */ - 0x0a, 0x10, 0x10, /* PnP version 1.0, vendor version 1.0 */ - 0x82, 0x0e, 0x00, 'I', 'D', 'E', ' ', 'C', 'o', 'n', 't', 'r', 'o', 'l', 'l', 'e', 'r', /* ANSI identifier */ + /* BOX0001, serial 0, dummy checksum (filled in by isapnp_add_card) */ + 0x09, 0xf8, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, + /* PnP version 1.0, vendor version 1.0 */ + 0x0a, 0x10, 0x10, + /* ANSI identifier */ + 0x82, 0x0e, 0x00, 'I', 'D', 'E', ' ', 'C', 'o', 'n', 't', 'r', 'o', + 'l', 'l', 'e', 'r', - 0x15, 0x09, 0xf8, 0x00, 0x01, 0x00, /* logical device BOX0001 */ - 0x1c, 0x41, 0xd0, 0x06, 0x00, /* compatible device PNP0600 */ - 0x31, 0x00, /* start dependent functions, preferred */ - 0x22, 0x00, 0x04, /* IRQ 10 */ - 0x47, 0x01, 0x68, 0x01, 0x68, 0x01, 0x01, 0x08, /* I/O 0x168, decodes 16-bit, 1-byte alignment, 8 addresses */ - 0x47, 0x01, 0x6e, 0x03, 0x6e, 0x03, 0x01, 0x01, /* I/O 0x36E, decodes 16-bit, 1-byte alignment, 1 address */ - 0x30, /* start dependent functions, acceptable */ - 0x22, 0xb8, 0x1e, /* IRQ 3/4/5/7/9/10/11/12 */ - 0x47, 0x01, 0x68, 0x01, 0x68, 0x01, 0x01, 0x08, /* I/O 0x168, decodes 16-bit, 1-byte alignment, 8 addresses */ - 0x47, 0x01, 0x6e, 0x03, 0x6e, 0x03, 0x01, 0x01, /* I/O 0x36E, decodes 16-bit, 1-byte alignment, 1 address */ - 0x30, /* start dependent functions, acceptable */ - 0x22, 0xb8, 0x1e, /* IRQ 3/4/5/7/9/10/11/12 */ - 0x47, 0x01, 0x00, 0x01, 0xf8, 0xff, 0x08, 0x08, /* I/O 0x100-0xFFF8, decodes 16-bit, 8-byte alignment, 8 addresses */ - 0x47, 0x01, 0x00, 0x01, 0xff, 0xff, 0x01, 0x01, /* I/O 0x100-0xFFFF, decodes 16-bit, 1-byte alignment, 1 address */ - 0x38, /* end dependent functions */ + /* Logical device BOX0001 */ + 0x15, 0x09, 0xf8, 0x00, 0x01, 0x00, + /* Compatible device PNP0600 */ + 0x1c, 0x41, 0xd0, 0x06, 0x00, + /* Start dependent functions, preferred */ + 0x31, 0x00, + /* IRQ 11 */ + 0x22, 0x00, 0x08, + /* I/O 0x1E8, decodes 16-bit, 1-byte alignment, 8 addresses */ + 0x47, 0x01, 0xe8, 0x01, 0xe8, 0x01, 0x01, 0x08, + /* I/O 0x3EE, decodes 16-bit, 1-byte alignment, 1 address */ + 0x47, 0x01, 0xee, 0x03, 0xee, 0x03, 0x01, 0x01, + /* Start dependent functions, acceptable */ + 0x30, + /* IRQ 3/4/5/7/9/10/11/12 */ + 0x22, 0xb8, 0x1e, + /* I/O 0x1E8, decodes 16-bit, 1-byte alignment, 8 addresses */ + 0x47, 0x01, 0xe8, 0x01, 0xe8, 0x01, 0x01, 0x08, + /* I/O 0x3EE, decodes 16-bit, 1-byte alignment, 1 address */ + 0x47, 0x01, 0xee, 0x03, 0xee, 0x03, 0x01, 0x01, + /* Start dependent functions, acceptable */ + 0x30, + /* IRQ 3/4/5/7/9/10/11/12 */ + 0x22, 0xb8, 0x1e, + /* I/O 0x100-0xFFF8, decodes 16-bit, 8-byte alignment, 8 addresses */ + 0x47, 0x01, 0x00, 0x01, 0xf8, 0xff, 0x08, 0x08, + /* I/O 0x100-0xFFFF, decodes 16-bit, 1-byte alignment, 1 address */ + 0x47, 0x01, 0x00, 0x01, 0xff, 0xff, 0x01, 0x01, + /* End dependent functions */ + 0x38, - 0x79, 0x00 /* end tag, dummy checksum (filled in by isapnp_add_card) */ + /* End tag, dummy checksum (filled in by isapnp_add_card) */ + 0x79, 0x00 }; static uint8_t ide_qua_pnp_rom[] = { - 0x09, 0xf8, 0x00, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, /* BOX0001, serial 1, dummy checksum (filled in by isapnp_add_card) */ - 0x0a, 0x10, 0x10, /* PnP version 1.0, vendor version 1.0 */ - 0x82, 0x0e, 0x00, 'I', 'D', 'E', ' ', 'C', 'o', 'n', 't', 'r', 'o', 'l', 'l', 'e', 'r', /* ANSI identifier */ + /* BOX0001, serial 1, dummy checksum (filled in by isapnp_add_card) */ + 0x09, 0xf8, 0x00, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, + /* PnP version 1.0, vendor version 1.0 */ + 0x0a, 0x10, 0x10, + /* ANSI identifier */ + 0x82, 0x0e, 0x00, 'I', 'D', 'E', ' ', 'C', 'o', 'n', 't', 'r', 'o', + 'l', 'l', 'e', 'r', - 0x15, 0x09, 0xf8, 0x00, 0x01, 0x00, /* logical device BOX0001 */ - 0x1c, 0x41, 0xd0, 0x06, 0x00, /* compatible device PNP0600 */ - 0x31, 0x00, /* start dependent functions, preferred */ - 0x22, 0x00, 0x08, /* IRQ 11 */ - 0x47, 0x01, 0xe8, 0x01, 0xe8, 0x01, 0x01, 0x08, /* I/O 0x1E8, decodes 16-bit, 1-byte alignment, 8 addresses */ - 0x47, 0x01, 0xee, 0x03, 0xee, 0x03, 0x01, 0x01, /* I/O 0x3EE, decodes 16-bit, 1-byte alignment, 1 address */ - 0x30, /* start dependent functions, acceptable */ - 0x22, 0xb8, 0x1e, /* IRQ 3/4/5/7/9/10/11/12 */ - 0x47, 0x01, 0xe8, 0x01, 0xe8, 0x01, 0x01, 0x08, /* I/O 0x1E8, decodes 16-bit, 1-byte alignment, 8 addresses */ - 0x47, 0x01, 0xee, 0x03, 0xee, 0x03, 0x01, 0x01, /* I/O 0x3EE, decodes 16-bit, 1-byte alignment, 1 address */ - 0x30, /* start dependent functions, acceptable */ - 0x22, 0xb8, 0x1e, /* IRQ 3/4/5/7/9/10/11/12 */ - 0x47, 0x01, 0x00, 0x01, 0xf8, 0xff, 0x08, 0x08, /* I/O 0x100-0xFFF8, decodes 16-bit, 8-byte alignment, 8 addresses */ - 0x47, 0x01, 0x00, 0x01, 0xff, 0xff, 0x01, 0x01, /* I/O 0x100-0xFFFF, decodes 16-bit, 1-byte alignment, 1 address */ - 0x38, /* end dependent functions */ + /* Logical device BOX0001 */ + 0x15, 0x09, 0xf8, 0x00, 0x01, 0x00, + /* Compatible device PNP0600 */ + 0x1c, 0x41, 0xd0, 0x06, 0x00, + /* Start dependent functions, preferred */ + 0x31, 0x00, + /* IRQ 10 */ + 0x22, 0x00, 0x04, + /* I/O 0x168, decodes 16-bit, 1-byte alignment, 8 addresses */ + 0x47, 0x01, 0x68, 0x01, 0x68, 0x01, 0x01, 0x08, + /* I/O 0x36E, decodes 16-bit, 1-byte alignment, 1 address */ + 0x47, 0x01, 0x6e, 0x03, 0x6e, 0x03, 0x01, 0x01, + /* Start dependent functions, acceptable */ + 0x30, + /* IRQ 3/4/5/7/9/10/11/12 */ + 0x22, 0xb8, 0x1e, + /* I/O 0x168, decodes 16-bit, 1-byte alignment, 8 addresses */ + 0x47, 0x01, 0x68, 0x01, 0x68, 0x01, 0x01, 0x08, + /* I/O 0x36E, decodes 16-bit, 1-byte alignment, 1 address */ + 0x47, 0x01, 0x6e, 0x03, 0x6e, 0x03, 0x01, 0x01, + /* Start dependent functions, acceptable */ + 0x30, + /* IRQ 3/4/5/7/9/10/11/12 */ + 0x22, 0xb8, 0x1e, + /* I/O 0x100-0xFFF8, decodes 16-bit, 8-byte alignment, 8 addresses */ + 0x47, 0x01, 0x00, 0x01, 0xf8, 0xff, 0x08, 0x08, + /* I/O 0x100-0xFFFF, decodes 16-bit, 1-byte alignment, 1 address */ + 0x47, 0x01, 0x00, 0x01, 0xff, 0xff, 0x01, 0x01, + /* End dependent functions */ + 0x38, - 0x79, 0x00 /* end tag, dummy checksum (filled in by isapnp_add_card) */ + /* End tag, dummy checksum (filled in by isapnp_add_card) */ + 0x79, 0x00 }; -ide_t *ide_drives[IDE_NUM]; -int ide_ter_enabled = 0, ide_qua_enabled = 0; - -static void ide_atapi_callback(ide_t *ide); -static void ide_callback(void *priv); +ide_t *ide_drives[IDE_NUM]; +int ide_ter_enabled = 0; +int ide_qua_enabled = 0; +static void ide_atapi_callback(ide_t *ide); +static void ide_callback(void *priv); #ifdef ENABLE_IDE_LOG int ide_do_log = ENABLE_IDE_LOG; - static void ide_log(const char *fmt, ...) { va_list ap; if (ide_do_log) { - va_start(ap, fmt); - pclog_ex(fmt, ap); - va_end(ap); + va_start(ap, fmt); + pclog_ex(fmt, ap); + va_end(ap); } } #else -#define ide_log(fmt, ...) +# define ide_log(fmt, ...) #endif - uint8_t -getstat(ide_t *ide) { - return ide->atastat; +getstat(ide_t *ide) +{ + return ide->tf->atastat; } - ide_t * ide_get_drive(int ch) { if (ch >= 8) - return NULL; + return NULL; return ide_drives[ch]; } - double -ide_get_period(ide_t *ide, int size) +ide_get_xfer_time(ide_t *ide, int size) { double period = (10.0 / 3.0); /* We assume that 1 MB = 1000000 B in this case, so we have as many B/us as there are MB/s because 1 s = 1000000 us. */ - switch(ide->mdma_mode & 0x300) { - case 0x000: /* PIO */ - switch(ide->mdma_mode & 0xff) { - case 0x01: - period = (10.0 / 3.0); - break; - case 0x02: - period = (20.0 / 3.83); - break; - case 0x04: - period = (25.0 / 3.0); - break; - case 0x08: - period = (100.0 / 9.0); - break; - case 0x10: - period = (50.0 / 3.0); - break; - } - break; - case 0x100: /* Single Word DMA */ - switch(ide->mdma_mode & 0xff) { - case 0x01: - period = (25.0 / 12.0); - break; - case 0x02: - period = (25.0 / 6.0); - break; - case 0x04: - period = (25.0 / 3.0); - break; - } - break; - case 0x200: /* Multiword DMA */ - switch(ide->mdma_mode & 0xff) { - case 0x01: - period = (25.0 / 6.0); - break; - case 0x02: - period = (40.0 / 3.0); - break; - case 0x04: - period = (50.0 / 3.0); - break; - } - break; - case 0x300: /* Ultra DMA */ - switch(ide->mdma_mode & 0xff) { - case 0x01: - period = (50.0 / 3.0); - break; - case 0x02: - period = 25.0; - break; - case 0x04: - period = (100.0 / 3.0); - break; - case 0x08: - period = (400.0 / 9.0); - break; - case 0x10: - period = (200.0 / 3.0); - break; - case 0x20: - period = 100.0; - break; - } - break; + switch (ide->mdma_mode & 0x300) { + case 0x000: /* PIO */ + switch (ide->mdma_mode & 0xff) { + case 0x01: + period = (10.0 / 3.0); + break; + case 0x02: + period = (20.0 / 3.83); + break; + case 0x04: + period = (25.0 / 3.0); + break; + case 0x08: + period = (100.0 / 9.0); + break; + case 0x10: + period = (50.0 / 3.0); + break; + + default: + break; + } + break; + case 0x100: /* Single Word DMA */ + switch (ide->mdma_mode & 0xff) { + case 0x01: + period = (25.0 / 12.0); + break; + case 0x02: + period = (25.0 / 6.0); + break; + case 0x04: + period = (25.0 / 3.0); + break; + + default: + break; + } + break; + case 0x200: /* Multiword DMA */ + switch (ide->mdma_mode & 0xff) { + case 0x01: + period = (25.0 / 6.0); + break; + case 0x02: + period = (40.0 / 3.0); + break; + case 0x04: + period = (50.0 / 3.0); + break; + + default: + break; + } + break; + case 0x300: /* Ultra DMA */ + switch (ide->mdma_mode & 0xff) { + case 0x01: + period = (50.0 / 3.0); + break; + case 0x02: + period = 25.0; + break; + case 0x04: + period = (100.0 / 3.0); + break; + case 0x08: + period = (400.0 / 9.0); + break; + case 0x10: + period = (200.0 / 3.0); + break; + case 0x20: + period = 100.0; + break; + + default: + break; + } + break; + + default: + break; } - period = (1.0 / period); /* get us for 1 byte */ - return period * ((double) size); /* multiply by bytes to get period for the entire transfer */ + period = (1.0 / period); /* get us for 1 byte */ + return period * ((double) size); /* multiply by bytes to get period for the entire transfer */ } - double ide_atapi_get_period(uint8_t channel) { ide_t *ide = ide_drives[channel]; - + ide_log("ide_atapi_get_period(%i)\n", channel); if (!ide) { - ide_log("Get period failed\n"); - return -1.0; + ide_log("Get period failed\n"); + return -1.0; } - return ide_get_period(ide, 1); + return ide_get_xfer_time(ide, 1); } - -void -ide_irq_raise(ide_t *ide) -{ - if (!ide_boards[ide->board]) - return; - - /* ide_log("Raising IRQ %i (board %i)\n", ide_boards[ide->board]->irq, ide->board); */ - - ide_log("IDE %i: IRQ raise\n", ide->board); - - if (!(ide->fdisk & 2) && ide->selected) { - if (!ide_boards[ide->board]->force_ata3 && ide_bm[ide->board] && ide_bm[ide->board]->set_irq) - ide_bm[ide->board]->set_irq(ide->board | 0x40, ide_bm[ide->board]->priv); - else if (ide_boards[ide->board]->irq != -1) - picint(1 << ide_boards[ide->board]->irq); - } - - ide->irqstat = 1; - ide->service = 1; -} - - -void -ide_irq_lower(ide_t *ide) -{ - if (!ide_boards[ide->board]) - return; - - /* ide_log("Lowering IRQ %i (board %i)\n", ide_boards[ide->board]->irq, ide->board); */ - - // ide_log("IDE %i: IRQ lower\n", ide->board); - - if (ide->irqstat && ide->selected) { - if (!ide_boards[ide->board]->force_ata3 && ide_bm[ide->board] && ide_bm[ide->board]->set_irq) - ide_bm[ide->board]->set_irq(ide->board, ide_bm[ide->board]->priv); - else if (ide_boards[ide->board]->irq != -1) - picintc(1 << ide_boards[ide->board]->irq); - } - - ide->irqstat = 0; -} - - static void -ide_irq_update(ide_t *ide) +ide_irq_update(ide_board_t *dev, int log) { - if (!ide_boards[ide->board]) - return; + ide_t *ide; + uint8_t set; - /* ide_log("Raising IRQ %i (board %i)\n", ide_boards[ide->board]->irq, ide->board); */ + if (dev == NULL) + return; - if (!(ide->fdisk & 2) && ide->irqstat) { - ide_log("IDE %i: IRQ update raise\n", ide->board); - if (!ide_boards[ide->board]->force_ata3 && ide_bm[ide->board] && ide_bm[ide->board]->set_irq) { - ide_bm[ide->board]->set_irq(ide->board, ide_bm[ide->board]->priv); - ide_bm[ide->board]->set_irq(ide->board | 0x40, ide_bm[ide->board]->priv); - } else if (ide_boards[ide->board]->irq != -1) { - picintc(1 << ide_boards[ide->board]->irq); - picint(1 << ide_boards[ide->board]->irq); - } - } else if ((ide->fdisk & 2) || !ide->irqstat) { - ide_log("IDE %i: IRQ update lower\n", ide->board); - if (!ide_boards[ide->board]->force_ata3 && ide_bm[ide->board] && ide_bm[ide->board]->set_irq) - ide_bm[ide->board]->set_irq(ide->board, ide_bm[ide->board]->priv); - else if (ide_boards[ide->board]->irq != -1) - picintc(1 << ide_boards[ide->board]->irq); - } +#ifdef ENABLE_IDE_LOG + if (log) + ide_log("IDE %i: IRQ update (%i)\n", dev->cur_dev >> 1, dev->irq); +#endif + + ide = ide_drives[dev->cur_dev]; + set = !(ide_boards[ide->board]->devctl & 2) && ide->irqstat; + + if (!dev->force_ata3 && dev->bm && dev->bm->set_irq) + dev->bm->set_irq(set << 2, dev->bm->priv); + else if (ide_boards[ide->board]->irq != -1) + picint_common(1 << dev->irq, PIC_IRQ_EDGE, set, NULL); } +void +ide_irq(ide_t *ide, int set, int log) +{ + if (!ide_boards[ide->board]) + return; + +#if defined(ENABLE_IDE_LOG) && (ENABLE_IDE_LOG == 2) + ide_log("IDE %i: IRQ %s\n", ide->channel, set ? "raise" : "lower"); +#endif + + ide->irqstat = set; + + if (set) + ide->service = 1; + + if (ide->selected) + ide_irq_update(ide_boards[ide->board], log); +} /** * Copy a string into a buffer, padding with spaces, and placing characters as @@ -402,18 +429,17 @@ ide_irq_update(ide_t *ide) void ide_padstr(char *str, const char *src, int len) { - int i, v; + int v; - for (i = 0; i < len; i++) { - if (*src != '\0') - v = *src++; - else - v = ' '; - str[i ^ 1] = v; + for (int i = 0; i < len; i++) { + if (*src != '\0') + v = *src++; + else + v = ' '; + str[i ^ 1] = v; } } - /** * Copy a string into a buffer, padding with spaces. Does not add string * terminator. @@ -423,88 +449,67 @@ ide_padstr(char *str, const char *src, int len) * this length will be padded with spaces. * @param src Source string */ -void ide_padstr8(uint8_t *buf, int buf_size, const char *src) +void +ide_padstr8(uint8_t *buf, int buf_size, const char *src) { - int i; - - for (i = 0; i < buf_size; i++) { - if (*src != '\0') - buf[i] = *src++; - else - buf[i] = ' '; + for (int i = 0; i < buf_size; i++) { + if (*src != '\0') + buf[i] = *src++; + else + buf[i] = ' '; } } - static int ide_get_max(ide_t *ide, int type) { + int ret = -1; + ide_bm_t *bm = ide_boards[ide->board]->bm; + int ata_4 = (!ide_boards[ide->board]->force_ata3 && (bm != NULL)); + int max[2][4] = { { 0, -1, -1, -1 }, { 4, 2, 2, 5 } }; + if (ide->type == IDE_ATAPI) - return ide->get_max(!ide_boards[ide->board]->force_ata3 && (ide_bm[ide->board] != NULL), type); + ret = ide->get_max(!IDE_ATAPI_IS_EARLY && ata_4, type); + else if (type <= TYPE_UDMA) + ret = max[ata_4][type]; + else + fatal("Unknown transfer type: %i\n", type); - switch(type) { - case TYPE_PIO: /* PIO */ - if (!ide_boards[ide->board]->force_ata3 && (ide_bm[ide->board] != NULL)) - return 4; - - return 0; /* Maximum PIO 0 for legacy PIO-only drive. */ - case TYPE_SDMA: /* SDMA */ - if (!ide_boards[ide->board]->force_ata3 && (ide_bm[ide->board] != NULL)) - return 2; - - return -1; - case TYPE_MDMA: /* MDMA */ - if (!ide_boards[ide->board]->force_ata3 && (ide_bm[ide->board] != NULL)) - return 2; - - return -1; - case TYPE_UDMA: /* UDMA */ - if (!ide_boards[ide->board]->force_ata3 && (ide_bm[ide->board] != NULL)) - return 5; - - return -1; - default: - fatal("Unknown transfer type: %i\n", type); - return -1; - } + return ret; } - static int ide_get_timings(ide_t *ide, int type) { + int ret = 0; + ide_bm_t *bm = ide_boards[ide->board]->bm; + int ata_4 = (!ide_boards[ide->board]->force_ata3 && (bm != NULL)); + int timings[2][3] = { { 0, 0, 0 }, { 120, 120, 0 } }; + if (ide->type == IDE_ATAPI) - return ide->get_timings(!ide_boards[ide->board]->force_ata3 && (ide_bm[ide->board] != NULL), type); + ret = ide->get_timings(!IDE_ATAPI_IS_EARLY && ata_4, type); + else if (type <= TIMINGS_PIO_FC) + ret = timings[ata_4][type]; + else + fatal("Unknown transfer type: %i\n", type); - switch(type) { - case TIMINGS_DMA: - if (!ide_boards[ide->board]->force_ata3 && (ide_bm[ide->board] != NULL)) - return 120; - - return 0; - case TIMINGS_PIO: - if (!ide_boards[ide->board]->force_ata3 && (ide_bm[ide->board] != NULL)) - return 120; - - return 0; - case TIMINGS_PIO_FC: - return 0; - default: - fatal("Unknown transfer type: %i\n", type); - return 0; - } + return ret; } - /** * Fill in ide->buffer with the output of the "IDENTIFY DEVICE" command */ -static void ide_hd_identify(ide_t *ide) +static void +ide_hd_identify(ide_t *ide) { char device_identify[9] = { '8', '6', 'B', '_', 'H', 'D', '0', '0', 0 }; + ide_bm_t *bm = ide_boards[ide->board]->bm; - uint32_t d_hpc, d_spt, d_tracks; - uint64_t full_size = (((uint64_t) hdd[ide->hdd_num].tracks) * hdd[ide->hdd_num].hpc * hdd[ide->hdd_num].spt); + uint32_t d_hpc; + uint32_t d_spt; + uint32_t d_tracks; + uint64_t full_size = (((uint64_t) hdd[ide->hdd_num].tracks) * + hdd[ide->hdd_num].hpc * hdd[ide->hdd_num].spt); device_identify[6] = (ide->hdd_num / 10) + 0x30; device_identify[7] = (ide->hdd_num % 10) + 0x30; @@ -512,426 +517,443 @@ static void ide_hd_identify(ide_t *ide) d_spt = ide->spt; if (ide->hpc <= 16) { - /* HPC <= 16, report as needed. */ - d_tracks = ide->tracks; - d_hpc = ide->hpc; + /* HPC <= 16, report as needed. */ + d_tracks = ide->tracks; + d_hpc = ide->hpc; } else { - /* HPC > 16, convert to 16 HPC. */ - d_hpc = 16; - d_tracks = (ide->tracks * ide->hpc) / 16; + /* HPC > 16, convert to 16 HPC. */ + d_hpc = 16; + d_tracks = (ide->tracks * ide->hpc) / 16; } /* Specify default CHS translation */ if (full_size <= 16514064) { - ide->buffer[1] = d_tracks; /* Tracks in default CHS translation. */ - ide->buffer[3] = d_hpc; /* Heads in default CHS translation. */ - ide->buffer[6] = d_spt; /* Heads in default CHS translation. */ + ide->buffer[1] = d_tracks; /* Tracks in default CHS translation. */ + ide->buffer[3] = d_hpc; /* Heads in default CHS translation. */ + ide->buffer[6] = d_spt; /* Heads in default CHS translation. */ } else { - ide->buffer[1] = 16383; /* Tracks in default CHS translation. */ - ide->buffer[3] = 16; /* Heads in default CHS translation. */ - ide->buffer[6] = 63; /* Heads in default CHS translation. */ + ide->buffer[1] = 16383; /* Tracks in default CHS translation. */ + ide->buffer[3] = 16; /* Heads in default CHS translation. */ + ide->buffer[6] = 63; /* Heads in default CHS translation. */ } ide_log("Default CHS translation: %i, %i, %i\n", ide->buffer[1], ide->buffer[3], ide->buffer[6]); - ide_padstr((char *) (ide->buffer + 10), "", 20); /* Serial Number */ - ide_padstr((char *) (ide->buffer + 23), EMU_VERSION_EX, 8); /* Firmware */ - ide_padstr((char *) (ide->buffer + 27), device_identify, 40); /* Model */ - ide->buffer[0] = (1 << 6); /*Fixed drive*/ - ide->buffer[20] = 3; /*Buffer type*/ - ide->buffer[21] = 512; /*Buffer size*/ - ide->buffer[50] = 0x4000; /* Capabilities */ + /* Serial Number */ + ide_padstr((char *) (ide->buffer + 10), "", 20); + /* Firmware */ + ide_padstr((char *) (ide->buffer + 23), EMU_VERSION_EX, 8); + /* Model */ + ide_padstr((char *) (ide->buffer + 27), device_identify, 40); + /* Fixed drive */ + ide->buffer[0] = (1 << 6); + /* Buffer type */ + ide->buffer[20] = 3; + /* Buffer size */ + ide->buffer[21] = hdd[ide->hdd_num].cache.num_segments * hdd[ide->hdd_num].cache.segment_size; + /* Capabilities */ + ide->buffer[50] = 0x4000; ide->buffer[59] = ide->blocksize ? (ide->blocksize | 0x100) : 0; if ((ide->tracks >= 1024) || (ide->hpc > 16) || (ide->spt > 63)) { - ide->buffer[49] = (1 << 9); - ide_log("LBA supported\n"); + ide->buffer[49] = (1 << 9); + ide_log("LBA supported\n"); - ide->buffer[60] = full_size & 0xFFFF; /* Total addressable sectors (LBA) */ - ide->buffer[61] = (full_size >> 16) & 0x0FFF; - ide_log("Full size: %" PRIu64 "\n", full_size); + ide->buffer[60] = full_size & 0xFFFF; /* Total addressable sectors (LBA) */ + ide->buffer[61] = (full_size >> 16) & 0x0FFF; + ide_log("Full size: %" PRIu64 "\n", full_size); /* - Bit 0 = The fields reported in words 54-58 are valid; - Bit 1 = The fields reported in words 64-70 are valid; - Bit 2 = The fields reported in word 88 are valid. */ - ide->buffer[53] = 1; + Bit 0 = The fields reported in words 54-58 are valid; + Bit 1 = The fields reported in words 64-70 are valid; + Bit 2 = The fields reported in word 88 are valid. + */ + ide->buffer[53] = 1; - if (ide->cfg_spt != 0) { - ide->buffer[54] = (full_size / ide->cfg_hpc) / ide->cfg_spt; - ide->buffer[55] = ide->cfg_hpc; - ide->buffer[56] = ide->cfg_spt; - } else { - if (full_size <= 16514064) { - ide->buffer[54] = d_tracks; - ide->buffer[55] = d_hpc; - ide->buffer[56] = d_spt; - } else { - ide->buffer[54] = 16383; - ide->buffer[55] = 16; - ide->buffer[56] = 63; - } - } + if (ide->cfg_spt != 0) { + ide->buffer[54] = (full_size / ide->cfg_hpc) / ide->cfg_spt; + ide->buffer[55] = ide->cfg_hpc; + ide->buffer[56] = ide->cfg_spt; + } else { + if (full_size <= 16514064) { + ide->buffer[54] = d_tracks; + ide->buffer[55] = d_hpc; + ide->buffer[56] = d_spt; + } else { + ide->buffer[54] = 16383; + ide->buffer[55] = 16; + ide->buffer[56] = 63; + } + } - full_size = ((uint64_t) ide->buffer[54]) * ((uint64_t) ide->buffer[55]) * ((uint64_t) ide->buffer[56]); + full_size = ((uint64_t) ide->buffer[54]) * ((uint64_t) ide->buffer[55]) * + ((uint64_t) ide->buffer[56]); - ide->buffer[57] = full_size & 0xFFFF; /* Total addressable sectors (LBA) */ - ide->buffer[58] = (full_size >> 16) & 0x0FFF; + /* Total addressable sectors (LBA) */ + ide->buffer[57] = full_size & 0xFFFF; + ide->buffer[58] = (full_size >> 16) & 0x0FFF; - ide_log("Current CHS translation: %i, %i, %i\n", ide->buffer[54], ide->buffer[55], ide->buffer[56]); + ide_log("Current CHS translation: %i, %i, %i\n", ide->buffer[54], ide->buffer[55], ide->buffer[56]); } - if (!ide_boards[ide->board]->force_ata3 && ide_bm[ide->board]) { - ide->buffer[47] = 32 | 0x8000; /*Max sectors on multiple transfer command*/ - ide->buffer[80] = 0x7e; /*ATA-1 to ATA-6 supported*/ - ide->buffer[81] = 0x19; /*ATA-6 revision 3a supported*/ + /* Max sectors on multiple transfer command */ + ide->buffer[47] = hdd[ide->hdd_num].max_multiple_block | 0x8000; + if (!ide_boards[ide->board]->force_ata3 && (bm != NULL)) { + ide->buffer[80] = 0x7e; /*ATA-1 to ATA-6 supported*/ + ide->buffer[81] = 0x19; /*ATA-6 revision 3a supported*/ } else { - ide->buffer[47] = 16 | 0x8000; /*Max sectors on multiple transfer command*/ - ide->buffer[80] = 0x0e; /*ATA-1 to ATA-3 supported*/ + ide->buffer[80] = 0x0e; /*ATA-1 to ATA-3 supported*/ } } - static void ide_identify(ide_t *ide) { - int d, i, max_pio, max_sdma, max_mdma, max_udma; - ide_t *ide_other = ide_drives[ide->channel ^ 1]; + int d; + int i; + int max_pio; + int max_sdma; + int max_mdma; + int max_udma; + const ide_t *ide_other = ide_drives[ide->channel ^ 1]; + ide_bm_t *bm = ide_boards[ide->board]->bm; ide_log("IDE IDENTIFY or IDENTIFY PACKET DEVICE on board %i (channel %i)\n", ide->board, ide->channel); memset(ide->buffer, 0, 512); if (ide->type == IDE_ATAPI) - ide->identify(ide, !ide_boards[ide->board]->force_ata3 && (ide_bm[ide->board] != NULL)); - else if (ide->type != IDE_NONE) - ide_hd_identify(ide); + ide->identify(ide, !IDE_ATAPI_IS_EARLY && !ide_boards[ide->board]->force_ata3 && (bm != NULL)); + else if (ide->type == IDE_HDD) + ide_hd_identify(ide); else { - fatal("IDE IDENTIFY or IDENTIFY PACKET DEVICE on non-attached IDE device\n"); - return; + fatal("IDE IDENTIFY or IDENTIFY PACKET DEVICE on non-attached IDE device\n"); + return; } - max_pio = ide_get_max(ide, TYPE_PIO); + max_pio = ide_get_max(ide, TYPE_PIO); max_sdma = ide_get_max(ide, TYPE_SDMA); max_mdma = ide_get_max(ide, TYPE_MDMA); max_udma = ide_get_max(ide, TYPE_UDMA); ide_log("IDE %i: max_pio = %i, max_sdma = %i, max_mdma = %i, max_udma = %i\n", - ide->channel, max_pio, max_sdma, max_mdma, max_udma); + ide->channel, max_pio, max_sdma, max_mdma, max_udma); if (ide_boards[ide->board]->bit32) - ide->buffer[48] |= 1; /*Dword transfers supported*/ + ide->buffer[48] |= 1; /*Dword transfers supported*/ ide->buffer[51] = ide_get_timings(ide, TIMINGS_PIO); ide->buffer[53] &= 0xfff9; ide->buffer[52] = ide->buffer[62] = ide->buffer[63] = ide->buffer[64] = 0x0000; ide->buffer[65] = ide->buffer[66] = ide_get_timings(ide, TIMINGS_DMA); ide->buffer[67] = ide->buffer[68] = 0x0000; - ide->buffer[88] = 0x0000; + ide->buffer[88] = 0x0000; if (max_pio >= 3) { - ide->buffer[53] |= 0x0002; - ide->buffer[67] = ide_get_timings(ide, TIMINGS_PIO); - ide->buffer[68] = ide_get_timings(ide, TIMINGS_PIO_FC); - for (i = 3; i <= max_pio; i++) - ide->buffer[64] |= (1 << (i - 3)); + ide->buffer[53] |= 0x0002; + ide->buffer[67] = ide_get_timings(ide, TIMINGS_PIO); + ide->buffer[68] = ide_get_timings(ide, TIMINGS_PIO_FC); + for (i = 3; i <= max_pio; i++) + ide->buffer[64] |= (1 << (i - 3)); } if (max_sdma != -1) { - for (i = 0; i <= max_sdma; i++) - ide->buffer[62] |= (1 << i); + for (i = 0; i <= max_sdma; i++) + ide->buffer[62] |= (1 << i); } if (max_mdma != -1) { - for (i = 0; i <= max_mdma; i++) - ide->buffer[63] |= (1 << i); + for (i = 0; i <= max_mdma; i++) + ide->buffer[63] |= (1 << i); } if (max_udma != -1) { - ide->buffer[53] |= 0x0004; - for (i = 0; i <= max_udma; i++) - ide->buffer[88] |= (1 << i); - if (max_udma >= 4) - ide->buffer[93] = 0x6000; /* Drive reports 80-conductor cable */ + ide->buffer[53] |= 0x0004; + for (i = 0; i <= max_udma; i++) + ide->buffer[88] |= (1 << i); + if (max_udma >= 4) + ide->buffer[93] = 0x6000; /* Drive reports 80-conductor cable */ - if (ide->channel & 1) - ide->buffer[93] |= 0x0b00; - else { - ide->buffer[93] |= 0x000b; - /* PDIAG- is assered by device 1, so the bit should be 1 if there's a device 1, - so it should be |= 0x001b if device 1 is present. */ - if (ide_other != NULL) - ide->buffer[93] |= 0x0010; - } + if (ide->channel & 1) + ide->buffer[93] |= 0x0b00; + else { + ide->buffer[93] |= 0x000b; + /* PDIAG- is assered by device 1, so the bit should be 1 if there's a device 1, + so it should be |= 0x001b if device 1 is present. */ + if (ide_other != NULL) + ide->buffer[93] |= 0x0010; + } } if ((max_sdma != -1) || (max_mdma != -1) || (max_udma != -1)) { - ide->buffer[49] |= 0x100; /* DMA supported */ - ide->buffer[52] = ide_get_timings(ide, TIMINGS_DMA); + /* DMA supported */ + ide->buffer[49] |= 0x100; + ide->buffer[52] = ide_get_timings(ide, TIMINGS_DMA); } if ((max_mdma != -1) || (max_udma != -1)) { - ide->buffer[65] = ide_get_timings(ide, TIMINGS_DMA); - ide->buffer[66] = ide_get_timings(ide, TIMINGS_DMA); + ide->buffer[65] = ide_get_timings(ide, TIMINGS_DMA); + ide->buffer[66] = ide_get_timings(ide, TIMINGS_DMA); } if (ide->mdma_mode != -1) { - d = (ide->mdma_mode & 0xff); - d <<= 8; - if ((ide->mdma_mode & 0x300) == 0x000) { - if ((ide->mdma_mode & 0xff) >= 3) - ide->buffer[64] |= d; - } else if ((ide->mdma_mode & 0x300) == 0x100) - ide->buffer[62] |= d; - else if ((ide->mdma_mode & 0x300) == 0x200) - ide->buffer[63] |= d; - else if ((ide->mdma_mode & 0x300) == 0x300) - ide->buffer[88] |= d; - ide_log("PIDENTIFY DMA Mode: %04X, %04X\n", ide->buffer[62], ide->buffer[63]); + d = (ide->mdma_mode & 0xff); + d <<= 8; + if ((ide->mdma_mode & 0x300) == 0x000) { + if ((ide->mdma_mode & 0xff) >= 3) + ide->buffer[64] |= d; + } else if ((ide->mdma_mode & 0x300) == 0x100) + ide->buffer[62] |= d; + else if ((ide->mdma_mode & 0x300) == 0x200) + ide->buffer[63] |= d; + else if ((ide->mdma_mode & 0x300) == 0x300) + ide->buffer[88] |= d; + ide_log("PIDENTIFY DMA Mode: %04X, %04X\n", ide->buffer[62], ide->buffer[63]); } } - /* * Return the sector offset for the current register values */ static off64_t ide_get_sector(ide_t *ide) { - uint32_t heads, sectors; + uint32_t heads; + uint32_t sectors; - if (ide->lba) - return (off64_t)ide->lba_addr + ide->skip512; + if (ide->tf->lba) + return (off64_t) ide->lba_addr; else { - heads = ide->cfg_hpc; - sectors = ide->cfg_spt; + heads = ide->cfg_hpc; + sectors = ide->cfg_spt; - return ((((off64_t) ide->cylinder * heads) + ide->head) * - sectors) + (ide->sector - 1) + ide->skip512; + uint8_t sector = ide->tf->sector ? (ide->tf->sector - 1) : 0; + + return ((((off64_t) ide->tf->cylinder * heads) + (off64_t) ide->tf->head) * sectors) + + (off64_t) sector; } } - /** * Move to the next sector using CHS addressing */ static void ide_next_sector(ide_t *ide) { - if (ide->lba) - ide->lba_addr++; + if (ide->tf->lba) + ide->lba_addr++; else { - ide->sector++; - if (ide->sector == (ide->cfg_spt + 1)) { - ide->sector = 1; - ide->head++; - if (ide->head == ide->cfg_hpc) { - ide->head = 0; - ide->cylinder++; - } - } + ide->tf->sector++; + if ((ide->tf->sector == 0) || (ide->tf->sector == (ide->cfg_spt + 1))) { + ide->tf->sector = 1; + ide->tf->head++; + if ((ide->tf->head == 0) || (ide->head == ide->cfg_hpc)) { + ide->tf->head = 0; + ide->tf->cylinder++; + } + } } } - static void -loadhd(ide_t *ide, int d, const char *fn) +loadhd(ide_t *ide, int d, UNUSED(const char *fn)) { - if (! hdd_image_load(d)) { - ide->type = IDE_NONE; - return; + if (!hdd_image_load(d)) { + ide->type = IDE_NONE; + return; } + hdd_preset_apply(d); + ide->spt = ide->cfg_spt = hdd[d].spt; ide->hpc = ide->cfg_hpc = hdd[d].hpc; - ide->tracks = hdd[d].tracks; - ide->type = IDE_HDD; - ide->hdd_num = d; + ide->tracks = hdd[d].tracks; + ide->type = IDE_HDD; + ide->hdd_num = d; } - void ide_set_signature(ide_t *ide) { - ide->sector=1; - ide->head=0; + uint16_t ide_signatures[4] = { 0x7f7f, 0x0000, 0xeb14, 0x7f7f }; - if (ide->type == IDE_ATAPI) { - ide->sc->phase = 1; - ide->sc->request_length = 0xEB14; - ide->secount = ide->sc->phase; - ide->cylinder = ide->sc->request_length; - } else { - ide->secount = 1; - ide->cylinder = ((ide->type == IDE_HDD) ? 0 : 0xFFFF); - if (ide->type == IDE_HDD) - ide->drive = 0; - } + ide->tf->sector = 1; + ide->tf->head = 0; + ide->tf->secount = 1; + ide->tf->cylinder = ide_signatures[ide->type & ~IDE_SHADOW]; + + if (ide->type == IDE_HDD) + ide->drive = 0; } - static int ide_set_features(ide_t *ide) { - uint8_t features, features_data; - int mode, submode, max; + uint8_t features; + uint8_t features_data; + int mode; + int submode; + int max; - features = ide->cylprecomp; - features_data = ide->secount; - - ide_log("Features code %02X\n", features); + features = ide->tf->cylprecomp; + features_data = ide->tf->secount; ide_log("IDE %02X: Set features: %02X, %02X\n", ide->channel, features, features_data); - switch(features) { - case FEATURE_SET_TRANSFER_MODE: /* Set transfer mode. */ - ide_log("Transfer mode %02X\n", features_data >> 3); + switch (features) { + case FEATURE_SET_TRANSFER_MODE: /* Set transfer mode. */ + ide_log("Transfer mode %02X\n", features_data >> 3); - mode = (features_data >> 3); - submode = features_data & 7; + mode = (features_data >> 3); + submode = features_data & 7; - switch (mode) { - case 0x00: /* PIO default */ - if (submode != 0) - return 0; - max = ide_get_max(ide, TYPE_PIO); - ide->mdma_mode = (1 << max); - ide_log("IDE %02X: Setting DPIO mode: %02X, %08X\n", ide->channel, submode, ide->mdma_mode); - break; + switch (mode) { + case 0x00: /* PIO default */ + if (submode != 0) + return 0; + max = ide_get_max(ide, TYPE_PIO); + ide->mdma_mode = (1 << max); + ide_log("IDE %02X: Setting DPIO mode: %02X, %08X\n", ide->channel, + submode, ide->mdma_mode); + break; - case 0x01: /* PIO mode */ - max = ide_get_max(ide, TYPE_PIO); - if (submode > max) - return 0; - ide->mdma_mode = (1 << submode); - ide_log("IDE %02X: Setting PIO mode: %02X, %08X\n", ide->channel, submode, ide->mdma_mode); - break; + case 0x01: /* PIO mode */ + max = ide_get_max(ide, TYPE_PIO); + if (submode > max) + return 0; + ide->mdma_mode = (1 << submode); + ide_log("IDE %02X: Setting PIO mode: %02X, %08X\n", ide->channel, + submode, ide->mdma_mode); + break; - case 0x02: /* Singleword DMA mode */ - max = ide_get_max(ide, TYPE_SDMA); - if (submode > max) - return 0; - ide->mdma_mode = (1 << submode) | 0x100; - ide_log("IDE %02X: Setting SDMA mode: %02X, %08X\n", ide->channel, submode, ide->mdma_mode); - break; + case 0x02: /* Singleword DMA mode */ + max = ide_get_max(ide, TYPE_SDMA); + if (submode > max) + return 0; + ide->mdma_mode = (1 << submode) | 0x100; + ide_log("IDE %02X: Setting SDMA mode: %02X, %08X\n", ide->channel, + submode, ide->mdma_mode); + break; - case 0x04: /* Multiword DMA mode */ - max = ide_get_max(ide, TYPE_MDMA); - if (submode > max) - return 0; - ide->mdma_mode = (1 << submode) | 0x200; - ide_log("IDE %02X: Setting MDMA mode: %02X, %08X\n", ide->channel, submode, ide->mdma_mode); - break; + case 0x04: /* Multiword DMA mode */ + max = ide_get_max(ide, TYPE_MDMA); + if (submode > max) + return 0; + ide->mdma_mode = (1 << submode) | 0x200; + ide_log("IDE %02X: Setting MDMA mode: %02X, %08X\n", ide->channel, + submode, ide->mdma_mode); + break; - case 0x08: /* Ultra DMA mode */ - max = ide_get_max(ide, TYPE_UDMA); - if (submode > max) - return 0; - ide->mdma_mode = (1 << submode) | 0x300; - ide_log("IDE %02X: Setting UDMA mode: %02X, %08X\n", ide->channel, submode, ide->mdma_mode); - break; + case 0x08: /* Ultra DMA mode */ + max = ide_get_max(ide, TYPE_UDMA); + if (submode > max) + return 0; + ide->mdma_mode = (1 << submode) | 0x300; + ide_log("IDE %02X: Setting UDMA mode: %02X, %08X\n", ide->channel, + submode, ide->mdma_mode); + break; - default: - return 0; - } - break; + default: + return 0; + } + break; - case FEATURE_ENABLE_IRQ_OVERLAPPED: - case FEATURE_ENABLE_IRQ_SERVICE: - case FEATURE_DISABLE_IRQ_OVERLAPPED: - case FEATURE_DISABLE_IRQ_SERVICE: - max = ide_get_max(ide, TYPE_MDMA); - if (max == -1) - return 0; - else - return 1; + case FEATURE_ENABLE_IRQ_OVERLAPPED: + case FEATURE_ENABLE_IRQ_SERVICE: + case FEATURE_DISABLE_IRQ_OVERLAPPED: + case FEATURE_DISABLE_IRQ_SERVICE: + max = ide_get_max(ide, TYPE_MDMA); + if (max == -1) + return 0; + else + return 1; - case FEATURE_DISABLE_REVERT: /* Disable reverting to power on defaults. */ - case FEATURE_ENABLE_REVERT: /* Enable reverting to power on defaults. */ - return 1; + case FEATURE_DISABLE_REVERT: /* Disable reverting to power on defaults. */ + case FEATURE_ENABLE_REVERT: /* Enable reverting to power on defaults. */ + return 1; - default: - return 0; + default: + return 0; } return 1; } - void ide_set_sector(ide_t *ide, int64_t sector_num) { - unsigned int cyl, r; - if (ide->lba) { - ide->head = (sector_num >> 24); - ide->cylinder = (sector_num >> 8); - ide->sector = (sector_num); + unsigned int cyl; + unsigned int r; + if (ide->tf->lba) { + ide->tf->head = (sector_num >> 24) & 0xff; + ide->tf->cylinder = (sector_num >> 8) & 0xffff; + ide->tf->sector = sector_num & 0xff; } else { - cyl = sector_num / (hdd[ide->hdd_num].hpc * hdd[ide->hdd_num].spt); - r = sector_num % (hdd[ide->hdd_num].hpc * hdd[ide->hdd_num].spt); - ide->cylinder = cyl; - ide->head = ((r / hdd[ide->hdd_num].spt) & 0x0f); - ide->sector = (r % hdd[ide->hdd_num].spt) + 1; + cyl = sector_num / (hdd[ide->hdd_num].hpc * hdd[ide->hdd_num].spt); + r = sector_num % (hdd[ide->hdd_num].hpc * hdd[ide->hdd_num].spt); + ide->tf->cylinder = cyl & 0xffff; + ide->tf->head = ((r / hdd[ide->hdd_num].spt) & 0x0f) & 0xff; + ide->tf->sector = ((r % hdd[ide->hdd_num].spt) + 1) & 0xff; } } - static void ide_zero(int d) { ide_t *dev; + if (ide_drives[d] == NULL) - ide_drives[d] = (ide_t *) malloc(sizeof(ide_t)); - memset(ide_drives[d], 0, sizeof(ide_t)); - dev = ide_drives[d]; - dev->channel = d; - dev->type = IDE_NONE; - dev->hdd_num = -1; - dev->atastat = DRDY_STAT | DSC_STAT; - dev->service = 0; - dev->board = d >> 1; - dev->selected = !(d & 1); + ide_drives[d] = (ide_t *) calloc(1, sizeof(ide_t)); + + dev = ide_drives[d]; + dev->tf = (ide_tf_t *) calloc(1, sizeof(ide_tf_t)); + dev->channel = d; + dev->type = IDE_NONE; + dev->hdd_num = -1; + dev->tf->atastat = DRDY_STAT | DSC_STAT; + dev->service = 0; + dev->board = d >> 1; + dev->selected = !(d & 1); ide_boards[dev->board]->ide[d & 1] = dev; timer_add(&dev->timer, ide_callback, dev, 0); } - void ide_allocate_buffer(ide_t *dev) { if (dev->buffer == NULL) - dev->buffer = (uint16_t *) malloc(65536 * sizeof(uint16_t)); - memset(dev->buffer, 0, 65536 * sizeof(uint16_t)); + dev->buffer = (uint16_t *) calloc(1, 65536 * sizeof(uint16_t)); } - void ide_atapi_attach(ide_t *ide) { + ide_bm_t *bm = ide_boards[ide->board]->bm; + if (ide->type != IDE_NONE) - return; + return; ide->type = IDE_ATAPI; ide_allocate_buffer(ide); ide_set_signature(ide); - ide->mdma_mode = (1 << ide->get_max(ide_boards[ide->board]->force_ata3 || !ide_bm[ide->board], TYPE_PIO)); - ide->error = 1; + ide->mdma_mode = (1 << ide->get_max(!IDE_ATAPI_IS_EARLY && + !ide_boards[ide->board]->force_ata3 && (bm != NULL), TYPE_PIO)); + ide->tf->error = 1; ide->cfg_spt = ide->cfg_hpc = 0; + if (!IDE_ATAPI_IS_EARLY) + ide->tf->atastat = 0; } - void ide_set_callback(ide_t *ide, double callback) { - if (!ide) { - ide_log("ide_set_callback(NULL): Set callback failed\n"); - return; + ide_log("ide_set_callback(NULL): Set callback failed\n"); + return; } ide_log("ide_set_callback(%i)\n", ide->channel); if (callback == 0.0) - timer_stop(&ide->timer); + timer_stop(&ide->timer); else - timer_on_auto(&ide->timer, callback); + timer_on_auto(&ide->timer, callback); } - void ide_set_board_callback(uint8_t board, double callback) { @@ -940,1756 +962,1674 @@ ide_set_board_callback(uint8_t board, double callback) ide_log("ide_set_board_callback(%i)\n", board); if (!dev) { - ide_log("Set board callback failed\n"); - return; + ide_log("Set board callback failed\n"); + return; } if (callback == 0.0) - timer_stop(&dev->timer); + timer_stop(&dev->timer); else - timer_on_auto(&dev->timer, callback); + timer_on_auto(&dev->timer, callback); } - static void ide_atapi_command_bus(ide_t *ide) { - ide->sc->status = BUSY_STAT; - ide->sc->phase = 1; - ide->sc->pos = 0; + ide->tf->atastat = BUSY_STAT; + ide->tf->phase = 1; + ide->tf->pos = 0; ide->sc->callback = 1.0 * IDE_TIME; ide_set_callback(ide, ide->sc->callback); } - static void ide_atapi_callback(ide_t *ide) { - int out, ret = 0; + int out; + int ret = 0; + ide_bm_t *bm = ide_boards[ide->board]->bm; +#ifdef ENABLE_IDE_LOG + char *phases[7] = { "Idle", "Command", "Data in", "Data out", "Data in DMA", "Data out DMA", + "Complete" }; + char *phase; - switch(ide->sc->packet_status) { - case PHASE_IDLE: -#ifdef ENABLE_IDE_LOG - ide_log("PHASE_IDLE\n"); -#endif - ide->sc->pos = 0; - ide->sc->phase = 1; - ide->sc->status = READY_STAT | DRQ_STAT | (ide->sc->status & ERR_STAT); - return; - case PHASE_COMMAND: -#ifdef ENABLE_IDE_LOG - ide_log("PHASE_COMMAND\n"); -#endif - ide->sc->status = BUSY_STAT | (ide->sc->status & ERR_STAT); - if (ide->packet_command) { - ide->packet_command(ide->sc, ide->sc->atapi_cdb); - if ((ide->sc->packet_status == PHASE_COMPLETE) && (ide->sc->callback == 0.0)) - ide_atapi_callback(ide); - } - return; - case PHASE_COMPLETE: -#ifdef ENABLE_IDE_LOG - ide_log("PHASE_COMPLETE\n"); -#endif - ide->sc->status = READY_STAT; - ide->sc->phase = 3; - ide->sc->packet_status = PHASE_NONE; - ide_irq_raise(ide); - return; - case PHASE_DATA_IN: - case PHASE_DATA_OUT: -#ifdef ENABLE_IDE_LOG - ide_log("PHASE_DATA_IN or PHASE_DATA_OUT\n"); -#endif - ide->sc->status = READY_STAT | DRQ_STAT | (ide->sc->status & ERR_STAT); - ide->sc->phase = !(ide->sc->packet_status & 0x01) << 1; - ide_irq_raise(ide); - return; - case PHASE_DATA_IN_DMA: - case PHASE_DATA_OUT_DMA: -#ifdef ENABLE_IDE_LOG - ide_log("PHASE_DATA_IN_DMA or PHASE_DATA_OUT_DMA\n"); -#endif - out = (ide->sc->packet_status & 0x01); + switch (ide->sc->packet_status) { + default: + phase = "Unknown"; + break; + case PHASE_IDLE ... PHASE_COMPLETE: + phase = phases[ide->sc->packet_status]; + break; + case PHASE_ERROR: + phase = "Error"; + break; + case PHASE_NONE: + phase = "None"; + break; + } - if (!ide_boards[ide->board]->force_ata3 && ide_bm[ide->board] && ide_bm[ide->board]->dma) { - ret = ide_bm[ide->board]->dma(ide->board, - ide->sc->temp_buffer, ide->sc->packet_len, - out, ide_bm[ide->board]->priv); - } else { - /* DMA command without a bus master. */ - if (ide->bus_master_error) - ide->bus_master_error(ide->sc); - return; - } - - if (ret == 0) { - if (ide->bus_master_error) - ide->bus_master_error(ide->sc); - } else if (ret == 1) { - if (out && ide->phase_data_out) - ret = ide->phase_data_out(ide->sc); - else if (!out && ide->command_stop) - ide->command_stop(ide->sc); - - if ((ide->sc->packet_status == PHASE_COMPLETE) && (ide->sc->callback == 0.0)) - ide_atapi_callback(ide); - } else if (ret == 2) - ide_atapi_command_bus(ide); - - return; - case PHASE_ERROR: -#ifdef ENABLE_IDE_LOG - ide_log("PHASE_ERROR\n"); + ide_log("Phase: %02X (%s)\n", ide->sc->packet_status, phase); #endif - ide->sc->status = READY_STAT | ERR_STAT; - ide->sc->phase = 3; - ide->sc->packet_status = PHASE_NONE; - ide_irq_raise(ide); - return; - default: - ide_log("PHASE_UNKNOWN %02X\n", ide->sc->packet_status); - return; + + switch (ide->sc->packet_status) { + default: + break; + + case PHASE_IDLE: + ide->tf->pos = 0; + ide->tf->phase = 1; + ide->tf->atastat = READY_STAT | DRQ_STAT | (ide->tf->atastat & ERR_STAT); + break; + case PHASE_COMMAND: + ide->tf->atastat = BUSY_STAT | (ide->tf->atastat & ERR_STAT); + if (ide->packet_command) { + ide->packet_command(ide->sc, ide->sc->atapi_cdb); + if ((ide->sc->packet_status == PHASE_COMPLETE) && (ide->sc->callback == 0.0)) + ide_atapi_callback(ide); + } + break; + case PHASE_COMPLETE: + case PHASE_ERROR: + ide->tf->atastat = READY_STAT; + if (ide->sc->packet_status == PHASE_ERROR) + ide->tf->atastat |= ERR_STAT; + ide->tf->phase = 3; + ide->sc->packet_status = PHASE_NONE; + ide_irq_raise(ide); + break; + case PHASE_DATA_IN: + case PHASE_DATA_OUT: + ide->tf->atastat = READY_STAT | DRQ_STAT | (ide->tf->atastat & ERR_STAT); + ide->tf->phase = !(ide->sc->packet_status & 0x01) << 1; + ide_irq_raise(ide); + break; + case PHASE_DATA_IN_DMA: + case PHASE_DATA_OUT_DMA: + out = (ide->sc->packet_status & 0x01); + + if (!IDE_ATAPI_IS_EARLY && !ide_boards[ide->board]->force_ata3 && + (bm != NULL) && bm->dma) { + ret = bm->dma(ide->sc->temp_buffer, ide->sc->packet_len, out, bm->priv); + } + /* Else, DMA command without a bus master, ret = 0 (default). */ + + switch (ret) { + case 0: + if (ide->bus_master_error) + ide->bus_master_error(ide->sc); + break; + case 1: + if (out && ide->phase_data_out) + ret = ide->phase_data_out(ide->sc); + else if (!out && ide->command_stop) + ide->command_stop(ide->sc); + + if ((ide->sc->packet_status == PHASE_COMPLETE) && (ide->sc->callback == 0.0)) + ide_atapi_callback(ide); + break; + case 2: + ide_atapi_command_bus(ide); + break; + } + break; } } - /* This is the general ATAPI PIO request function. */ static void ide_atapi_pio_request(ide_t *ide, uint8_t out) { scsi_common_t *dev = ide->sc; - ide_irq_lower(ide_drives[ide->board]); + ide_irq_lower(ide); - dev->status = BSY_STAT; + ide->tf->atastat = BSY_STAT; - if (dev->pos >= dev->packet_len) { - ide_log("%i bytes %s, command done\n", dev->pos, out ? "written" : "read"); + if (ide->tf->pos >= dev->packet_len) { + ide_log("%i bytes %s, command done\n", ide->tf->pos, out ? "written" : "read"); - dev->pos = dev->request_pos = 0; - if (out && ide->phase_data_out) - ide->phase_data_out(dev); - else if (!out && ide->command_stop) - ide->command_stop(dev); + ide->tf->pos = dev->request_pos = 0; + if (out && ide->phase_data_out) + ide->phase_data_out(dev); + else if (!out && ide->command_stop) + ide->command_stop(dev); - if ((ide->sc->packet_status == PHASE_COMPLETE) && (ide->sc->callback == 0.0)) - ide_atapi_callback(ide); + if ((ide->sc->packet_status == PHASE_COMPLETE) && (ide->sc->callback == 0.0)) + ide_atapi_callback(ide); } else { - ide_log("%i bytes %s, %i bytes are still left\n", dev->pos, - out ? "written" : "read", dev->packet_len - dev->pos); + ide_log("%i bytes %s, %i bytes are still left\n", ide->tf->pos, + out ? "written" : "read", dev->packet_len - ide->tf->pos); - /* If less than (packet length) bytes are remaining, update packet length - accordingly. */ - if ((dev->packet_len - dev->pos) < (dev->max_transfer_len)) { - dev->max_transfer_len = dev->packet_len - dev->pos; - /* Also update the request length so the host knows how many bytes to transfer. */ - dev->request_length = dev->max_transfer_len; + /* If less than (packet length) bytes are remaining, update packet length + accordingly. */ + if ((dev->packet_len - ide->tf->pos) < (dev->max_transfer_len)) { + dev->max_transfer_len = dev->packet_len - ide->tf->pos; + /* Also update the request length so the host knows how many bytes to transfer. */ + ide->tf->request_length = dev->max_transfer_len; } - ide_log("CD-ROM %i: Packet length %i, request length %i\n", dev->id, dev->packet_len, - dev->max_transfer_len); + ide_log("CD-ROM %i: Packet length %i, request length %i\n", dev->id, dev->packet_len, + dev->max_transfer_len); - dev->packet_status = PHASE_DATA_IN | out; + dev->packet_status = PHASE_DATA_IN | out; - dev->status = BSY_STAT; - dev->phase = 1; - ide_atapi_callback(ide); - ide_set_callback(ide, 0.0); + ide->tf->atastat = BSY_STAT; + ide->tf->phase = 1; + ide_atapi_callback(ide); + ide_set_callback(ide, 0.0); - dev->request_pos = 0; + dev->request_pos = 0; } } - -static uint32_t +static uint16_t ide_atapi_packet_read(ide_t *ide, int length) { scsi_common_t *dev = ide->sc; + const uint16_t *bufferw; + uint16_t ret = 0; - uint16_t *bufferw; - uint32_t *bufferl; + if (dev && dev->temp_buffer && (dev->packet_status == PHASE_DATA_IN)) { + ide_log("PHASE_DATA_IN read: %i, %i, %i, %i\n", + dev->request_pos, dev->max_transfer_len, ide->tf->pos, dev->packet_len); - uint32_t temp = 0; + bufferw = (uint16_t *) dev->temp_buffer; - if (!dev || !dev->temp_buffer || (dev->packet_status != PHASE_DATA_IN)) - return 0; + /* Make sure we return a 0 and don't attempt to read from the buffer if + we're transferring bytes beyond it, which can happen when issuing media + access commands with an allocated length below minimum request length + (which is 1 sector = 2048 bytes). */ + if (length == 2) { + ret = (ide->tf->pos < dev->packet_len) ? bufferw[ide->tf->pos >> 1] : 0; + ide->tf->pos += 2; + dev->request_pos += 2; + } else { + ret = (ide->tf->pos < dev->packet_len) ? dev->temp_buffer[ide->tf->pos] : 0; + ide->tf->pos++; + dev->request_pos++; + } - if (dev->packet_status == PHASE_DATA_IN) - ide_log("PHASE_DATA_IN read: %i, %i, %i, %i\n", dev->request_pos, dev->max_transfer_len, dev->pos, dev->packet_len); - - bufferw = (uint16_t *) dev->temp_buffer; - bufferl = (uint32_t *) dev->temp_buffer; - - /* Make sure we return a 0 and don't attempt to read from the buffer if we're transferring bytes beyond it, - which can happen when issuing media access commands with an allocated length below minimum request length - (which is 1 sector = 2048 bytes). */ - switch(length) { - case 1: - temp = (dev->pos < dev->packet_len) ? dev->temp_buffer[dev->pos] : 0; - dev->pos++; - dev->request_pos++; - break; - case 2: - temp = (dev->pos < dev->packet_len) ? bufferw[dev->pos >> 1] : 0; - dev->pos += 2; - dev->request_pos += 2; - break; - case 4: - temp = (dev->pos < dev->packet_len) ? bufferl[dev->pos >> 2] : 0; - dev->pos += 4; - dev->request_pos += 4; - break; - default: - return 0; + if ((dev->request_pos >= dev->max_transfer_len) || (ide->tf->pos >= dev->packet_len)) { + /* Time for a DRQ. */ + ide_atapi_pio_request(ide, 0); + } } - if (dev->packet_status == PHASE_DATA_IN) { - if ((dev->request_pos >= dev->max_transfer_len) || (dev->pos >= dev->packet_len)) { - /* Time for a DRQ. */ - ide_atapi_pio_request(ide, 0); - } - return temp; - } else - return 0; + return ret; } - static void -ide_atapi_packet_write(ide_t *ide, uint32_t val, int length) +ide_atapi_packet_write(ide_t *ide, uint16_t val, int length) { scsi_common_t *dev = ide->sc; - uint8_t *bufferb; - uint16_t *bufferw; - uint32_t *bufferl; + uint8_t *bufferb = NULL; + uint16_t *bufferw = NULL; - if (!dev) - return; + if (dev) { + if (dev->packet_status == PHASE_IDLE) + bufferb = dev->atapi_cdb; + else if (dev->temp_buffer) + bufferb = dev->temp_buffer; - if (dev->packet_status == PHASE_IDLE) - bufferb = dev->atapi_cdb; - else { - if (dev->temp_buffer) - bufferb = dev->temp_buffer; - else - return; + bufferw = (uint16_t *) bufferb; } - bufferw = (uint16_t *) bufferb; - bufferl = (uint32_t *) bufferb; + if ((bufferb != NULL) && (dev->packet_status != PHASE_DATA_IN)) { + if (length == 2) { + bufferw[ide->tf->pos >> 1] = val & 0xffff; + ide->tf->pos += 2; + dev->request_pos += 2; + } else { + bufferb[ide->tf->pos] = val & 0xff; + ide->tf->pos++; + dev->request_pos++; + } - switch(length) { - case 1: - bufferb[dev->pos] = val & 0xff; - dev->pos++; - dev->request_pos++; - break; - case 2: - bufferw[dev->pos >> 1] = val & 0xffff; - dev->pos += 2; - dev->request_pos += 2; - break; - case 4: - bufferl[dev->pos >> 2] = val; - dev->pos += 4; - dev->request_pos += 4; - break; - default: - return; - } - - if (dev->packet_status == PHASE_DATA_OUT) { - if ((dev->request_pos >= dev->max_transfer_len) || (dev->pos >= dev->packet_len)) { - /* Time for a DRQ. */ - ide_atapi_pio_request(ide, 1); - } - return; - } else if (dev->packet_status == PHASE_IDLE) { - if (dev->pos >= 12) { - dev->pos = 0; - dev->status = BSY_STAT; - dev->packet_status = PHASE_COMMAND; - ide_atapi_callback(ide); - } - return; + if (dev->packet_status == PHASE_DATA_OUT) { + if ((dev->request_pos >= dev->max_transfer_len) || (ide->tf->pos >= dev->packet_len)) { + /* Time for a DRQ. */ + ide_atapi_pio_request(ide, 1); + } + } else if (dev->packet_status == PHASE_IDLE) { + if (ide->tf->pos >= 12) { + ide->tf->pos = 0; + ide->tf->atastat = BSY_STAT; + dev->packet_status = PHASE_COMMAND; + ide_atapi_callback(ide); + } + } } } - -void -ide_write_data(ide_t *ide, uint32_t val, int length) +static void +ide_write_data(ide_t *ide, uint16_t val, int length) { - uint8_t *idebufferb = (uint8_t *) ide->buffer; + uint8_t *idebufferb = (uint8_t *) ide->buffer; uint16_t *idebufferw = ide->buffer; - uint32_t *idebufferl = (uint32_t *) ide->buffer; - if (ide->command == WIN_PACKETCMD) { - ide->pos = 0; + if ((ide->type != IDE_NONE) && !(ide->type & IDE_SHADOW) && ide->buffer) { + if (ide->command == WIN_PACKETCMD) { + if (ide->type == IDE_ATAPI) + ide_atapi_packet_write(ide, val, length); + else + ide->tf->pos = 0; + } else { + if (length == 2) { + idebufferw[ide->tf->pos >> 1] = val & 0xffff; + ide->tf->pos += 2; + } else { + idebufferb[ide->tf->pos] = val & 0xff; + ide->tf->pos++; + } - if (ide->type == IDE_ATAPI) - ide_atapi_packet_write(ide, val, length); - } else { - switch(length) { - case 1: - idebufferb[ide->pos] = val & 0xff; - ide->pos++; - break; - case 2: - idebufferw[ide->pos >> 1] = val & 0xffff; - ide->pos += 2; - break; - case 4: - idebufferl[ide->pos >> 2] = val; - ide->pos += 4; - break; - default: - return; - } - - if (ide->pos >= 512) { - ide->pos=0; - ide->atastat = BSY_STAT; - if (ide->command == WIN_WRITE_MULTIPLE) - ide_callback(ide); - else - ide_set_callback(ide, ide_get_period(ide, 512)); - } + if (ide->tf->pos >= 512) { + ide->tf->pos = 0; + ide->tf->atastat = BSY_STAT; + double seek_time = hdd_timing_write(&hdd[ide->hdd_num], ide_get_sector(ide), 1); + double xfer_time = ide_get_xfer_time(ide, 512); + double wait_time = seek_time + xfer_time; + if (ide->command == WIN_WRITE_MULTIPLE) { + if ((ide->blockcount + 1) >= ide->blocksize || ide->tf->secount == 1) { + ide_set_callback(ide, seek_time + xfer_time + ide->pending_delay); + ide->pending_delay = 0; + } else { + ide->pending_delay += wait_time; + ide_callback(ide); + } + } else + ide_set_callback(ide, wait_time); + } + } } } - void ide_writew(uint16_t addr, uint16_t val, void *priv) { - ide_board_t *dev = (ide_board_t *) priv; + const ide_board_t *dev = (ide_board_t *) priv; ide_t *ide; - int ch; + int ch; - ch = dev->cur_dev; + ch = dev->cur_dev; ide = ide_drives[ch]; - ide_log("ide_writew %04X %04X from %04X(%08X):%08X\n", addr, val, CS, cs, cpu_state.pc); +#if defined(ENABLE_IDE_LOG) && (ENABLE_IDE_LOG == 2) + ide_log("ide_writew(%04X, %04X, %08X)\n", addr, val, priv); +#endif addr &= 0x7; if ((ide->type == IDE_NONE) && ((addr == 0x0) || (addr == 0x7))) - return; + return; switch (addr) { - case 0x0: /* Data */ - ide_write_data(ide, val, 2); - break; - case 0x7: - ide_writeb(addr, val & 0xff, priv); - break; - default: - ide_writeb(addr, val & 0xff, priv); - ide_writeb(addr + 1, (val >> 8) & 0xff, priv); - break; + case 0x0: /* Data */ + ide_write_data(ide, val, 2); + break; + case 0x7: + ide_writeb(addr, val & 0xff, priv); + break; + default: + ide_writeb(addr, val & 0xff, priv); + ide_writeb(addr + 1, (val >> 8) & 0xff, priv); + break; } } - static void ide_writel(uint16_t addr, uint32_t val, void *priv) { - ide_board_t *dev = (ide_board_t *) priv; + const ide_board_t *dev = (ide_board_t *) priv; ide_t *ide; - int ch; + int ch; - ch = dev->cur_dev; + ch = dev->cur_dev; ide = ide_drives[ch]; - ide_log("ide_writel %04X %08X from %04X(%08X):%08X\n", addr, val, CS, cs, cpu_state.pc); +#if defined(ENABLE_IDE_LOG) && (ENABLE_IDE_LOG == 2) + ide_log("ide_writel(%04X, %08X, %08X)\n", addr, val, priv); +#endif addr &= 0x7; if ((ide->type == IDE_NONE) && ((addr == 0x0) || (addr == 0x7))) - return; + return; switch (addr) { - case 0x0: /* Data */ - ide_write_data(ide, val & 0xffff, 2); - if (dev->bit32) - ide_write_data(ide, val >> 16, 2); - else - ide_writew(addr + 2, (val >> 16) & 0xffff, priv); - break; - case 0x6: case 0x7: - ide_writew(addr, val & 0xffff, priv); - break; - default: - ide_writew(addr, val & 0xffff, priv); - ide_writew(addr + 2, (val >> 16) & 0xffff, priv); - break; + case 0x0: /* Data */ + ide_write_data(ide, val & 0xffff, 2); + if (dev->bit32) + ide_write_data(ide, val >> 16, 2); + else + ide_writew(addr + 2, (val >> 16) & 0xffff, priv); + break; + case 0x6: + case 0x7: + ide_writew(addr, val & 0xffff, priv); + break; + default: + ide_writew(addr, val & 0xffff, priv); + ide_writew(addr + 2, (val >> 16) & 0xffff, priv); + break; } } - static void dev_reset(ide_t *ide) { ide_set_signature(ide); if ((ide->type == IDE_ATAPI) && ide->stop) - ide->stop(ide->sc); + ide->stop(ide->sc); } - void -ide_write_devctl(uint16_t addr, uint8_t val, void *priv) +ide_write_devctl(UNUSED(uint16_t addr), uint8_t val, void *priv) { ide_board_t *dev = (ide_board_t *) priv; - ide_t *ide, *ide_other; - int ch; + ide_t *ide; + ide_t *ide_other; + int ch; uint8_t old; - ch = dev->cur_dev; - ide = ide_drives[ch]; + ch = dev->cur_dev; + ide = ide_drives[ch]; ide_other = ide_drives[ch ^ 1]; - ide_log("ide_write_devctl %04X %02X from %04X(%08X):%08X\n", addr, val, CS, cs, cpu_state.pc); + ide_log("ide_write_devctl(%04X, %02X, %08X)\n", addr, val, priv); if ((ide->type == IDE_NONE) && (ide_other->type == IDE_NONE)) - return; + return; dev->diag = 0; - - if ((val & 4) && !(ide->fdisk & 4)) { - /* Reset toggled from 0 to 1, initiate reset procedure. */ - if (ide->type == IDE_ATAPI) - ide->sc->callback = 0.0; - ide_set_callback(ide, 0.0); - ide_set_callback(ide_other, 0.0); - /* We must set set the status to busy in reset mode or - some 286 and 386 machines error out. */ - if (!(ch & 1)) { - if (ide->type != IDE_NONE) { - ide->atastat = BSY_STAT; - ide->error = 1; - if (ide->type == IDE_ATAPI) { - ide->sc->status = BSY_STAT; - ide->sc->error = 1; - } - } + if ((val & 4) && !(dev->devctl & 4)) { + /* Reset toggled from 0 to 1, initiate reset procedure. */ + if (ide->type == IDE_ATAPI) + ide->sc->callback = 0.0; + ide_set_callback(ide, 0.0); + ide_set_callback(ide_other, 0.0); - if (ide_other->type != IDE_NONE) { - ide_other->atastat = BSY_STAT; - ide_other->error = 1; - if (ide_other->type == IDE_ATAPI) { - ide_other->sc->status = BSY_STAT; - ide_other->sc->error = 1; - } - } - } - } else if (!(val & 4) && (ide->fdisk & 4)) { - /* Reset toggled from 1 to 0. */ - if (!(ch & 1)) { - /* Currently active device is 0, use the device 0 reset protocol. */ - /* Device 0. */ - dev_reset(ide); - ide->atastat = BSY_STAT; - ide->error = 1; - if (ide->type == IDE_ATAPI) { - ide->sc->status = BSY_STAT; - ide->sc->error = 1; - } + /* We must set set the status to busy in reset mode or + some 286 and 386 machines error out. */ + if (!(ch & 1)) { + if (ide->type != IDE_NONE) { + ide->tf->atastat = BSY_STAT; + ide->tf->error = 1; + } - /* Device 1. */ - dev_reset(ide_other); - ide_other->atastat = BSY_STAT; - ide_other->error = 1; - if (ide_other->type == IDE_ATAPI) { - ide_other->sc->status = BSY_STAT; - ide_other->sc->error = 1; - } + if (ide_other->type != IDE_NONE) { + ide_other->tf->atastat = BSY_STAT; + ide_other->tf->error = 1; + } + } + } else if (!(val & 4) && (dev->devctl & 4)) { + /* Reset toggled from 1 to 0. */ + if (!(ch & 1)) { + /* Currently active device is 0, use the device 0 reset protocol. */ + /* Device 0. */ + dev_reset(ide); + ide->tf->atastat = BSY_STAT; + ide->tf->error = 1; - /* Fire the timer. */ - dev->diag = 0; - ide->reset = 1; - ide_set_callback(ide, 0.0); - ide_set_callback(ide_other, 0.0); - ide_set_board_callback(ide->board, 1000.4); /* 1 ms + 400 ns, per the specification */ - } else { - /* Currently active device is 1, simply reset the status and the active device. */ - dev_reset(ide); - ide->atastat = DRDY_STAT | DSC_STAT; - ide->error = 1; - if (ide->type == IDE_ATAPI) { - ide->sc->status = DRDY_STAT | DSC_STAT; - ide->sc->error = 1; - } - dev->cur_dev &= ~1; - ch = dev->cur_dev; + /* Device 1. */ + dev_reset(ide_other); + ide_other->tf->atastat = BSY_STAT; + ide_other->tf->error = 1; - ide = ide_drives[ch]; - ide->selected = 1; + /* Fire the timer. */ + dev->diag = 0; + ide->reset = 1; + ide_set_callback(ide, 0.0); + ide_set_callback(ide_other, 0.0); + ide_set_board_callback(ide->board, 1000.4); /* 1 ms + 400 ns, per the specification */ + } else { + /* Currently active device is 1, simply reset the status and the active device. */ + dev_reset(ide); + ide->tf->atastat = DRDY_STAT | DSC_STAT; + ide->tf->error = 1; + dev->cur_dev &= ~1; + ch = dev->cur_dev; - ide_other = ide_drives[ch ^ 1]; - ide_other->selected = 0; - } + ide = ide_drives[ch]; + ide->selected = 1; + + ide_other = ide_drives[ch ^ 1]; + ide_other->selected = 0; + } } - old = ide->fdisk; - ide->fdisk = ide_other->fdisk = val; - if (!(val & 0x02) && (old & 0x02) && ide->irqstat) - ide_irq_update(ide); + old = dev->devctl; + dev->devctl = val; + if (!(val & 0x02) && (old & 0x02)) + ide_irq_update(ide_boards[ide->board], 1); } +static void +ide_reset_registers(ide_t *ide) +{ + uint16_t ide_signatures[4] = { 0x7f7f, 0x0000, 0xeb14, 0x7f7f }; + + ide->tf->atastat = DRDY_STAT | DSC_STAT; + ide->tf->error = 1; + ide->tf->secount = 1; + ide->tf->cylinder = ide_signatures[ide->type & ~IDE_SHADOW]; + ide->tf->sector = 1; + ide->tf->head = 0; + + ide->reset = 0; + + if (ide->type == IDE_ATAPI) + ide->sc->callback = 0.0; + + ide_set_callback(ide, 0.0); +} void ide_writeb(uint16_t addr, uint8_t val, void *priv) { ide_board_t *dev = (ide_board_t *) priv; + ide_t *ide; + ide_t *ide_other; + int ch; + int bad = 0; + int reset = 0; - ide_t *ide, *ide_other; - int ch; - - ch = dev->cur_dev; - ide = ide_drives[ch]; + ch = dev->cur_dev; + ide = ide_drives[ch]; ide_other = ide_drives[ch ^ 1]; - ide_log("ide_write %04X %02X from %04X(%08X):%08X\n", addr, val, CS, cs, cpu_state.pc); + ide_log("ide_writeb(%04X, %02X, %08X)\n", addr, val, priv); addr &= 0x7; - if ((ide->type == IDE_NONE) && ((addr == 0x0) || (addr == 0x7))) - return; + if ((ide->type != IDE_NONE) || ((addr != 0x0) && (addr != 0x7))) switch (addr) { + case 0x0: /* Data */ + ide_write_data(ide, val | (val << 8), 2); + break; - switch (addr) { - case 0x0: /* Data */ - ide_write_data(ide, val | (val << 8), 2); - return; + /* Note to self: for ATAPI, bit 0 of this is DMA if set, PIO if clear. */ + case 0x1: /* Features */ + if (!(ide->tf->atastat & (BSY_STAT | DRQ_STAT))) { + ide->tf->cylprecomp = val; + if (ide->type == IDE_ATAPI) + ide_log("ATAPI transfer mode: %s\n", (val & 1) ? "DMA" : "PIO"); + } - /* Note to self: for ATAPI, bit 0 of this is DMA if set, PIO if clear. */ - case 0x1: /* Features */ - if (ide->type == IDE_ATAPI) { - ide_log("ATAPI transfer mode: %s\n", (val & 1) ? "DMA" : "PIO"); - ide->sc->features = val; - } - ide->cylprecomp = val; + if (!(ide_other->tf->atastat & (BSY_STAT | DRQ_STAT))) + ide_other->tf->cylprecomp = val; + break; - if (ide_other->type == IDE_ATAPI) - ide_other->sc->features = val; - ide_other->cylprecomp = val; - return; + case 0x2: /* Sector count */ + if (!(ide->tf->atastat & (BSY_STAT | DRQ_STAT))) + ide->tf->secount = val; + if (!(ide_other->tf->atastat & (BSY_STAT | DRQ_STAT))) + ide_other->tf->secount = val; + break; - case 0x2: /* Sector count */ - if (ide->type == IDE_ATAPI) { - ide_log("Sector count write: %i\n", val); - ide->sc->phase = val; - } - ide->secount = val; + case 0x3: /* Sector */ + if (!(ide->tf->atastat & (BSY_STAT | DRQ_STAT))) { + ide->tf->sector = val; + ide->lba_addr = (ide->lba_addr & 0xfffff00) | val; + } - if (ide_other->type == IDE_ATAPI) { - ide_log("Other sector count write: %i\n", val); - ide_other->sc->phase = val; - } - ide_other->secount = val; - return; + if (!(ide_other->tf->atastat & (BSY_STAT | DRQ_STAT))) { + ide_other->tf->sector = val; + ide_other->lba_addr = (ide_other->lba_addr & 0xfffff00) | val; + } + break; - case 0x3: /* Sector */ - ide->sector = val; - ide->lba_addr = (ide->lba_addr & 0xFFFFF00) | val; - ide_other->sector = val; - ide_other->lba_addr = (ide_other->lba_addr & 0xFFFFF00) | val; - return; + case 0x4: /* Cylinder low */ + if (ide->type & IDE_SHADOW) + break; - case 0x4: /* Cylinder low */ - if (ide->type == IDE_ATAPI) { - ide->sc->request_length &= 0xFF00; - ide->sc->request_length |= val; - } - ide->cylinder = (ide->cylinder & 0xFF00) | val; - ide->lba_addr = (ide->lba_addr & 0xFFF00FF) | (val << 8); + if (!(ide->tf->atastat & (BSY_STAT | DRQ_STAT))) { + ide->tf->cylinder = (ide->tf->cylinder & 0xff00) | val; + ide->lba_addr = (ide->lba_addr & 0xfff00ff) | (val << 8); + } - if (ide_other->type == IDE_ATAPI) { - ide_other->sc->request_length &= 0xFF00; - ide_other->sc->request_length |= val; - } - ide_other->cylinder = (ide_other->cylinder & 0xFF00) | val; - ide_other->lba_addr = (ide_other->lba_addr & 0xFFF00FF) | (val << 8); - return; + if (!(ide_other->tf->atastat & (BSY_STAT | DRQ_STAT))) { + ide_other->tf->cylinder = (ide_other->tf->cylinder & 0xff00) | val; + ide_other->lba_addr = (ide_other->lba_addr & 0xfff00ff) | (val << 8); + } + break; - case 0x5: /* Cylinder high */ - if (ide->type == IDE_ATAPI) { - ide->sc->request_length &= 0xFF; - ide->sc->request_length |= (val << 8); - } - ide->cylinder = (ide->cylinder & 0xFF) | (val << 8); - ide->lba_addr = (ide->lba_addr & 0xF00FFFF) | (val << 16); + case 0x5: /* Cylinder high */ + if (ide->type & IDE_SHADOW) + break; - if (ide_other->type == IDE_ATAPI) { - ide_other->sc->request_length &= 0xFF; - ide_other->sc->request_length |= (val << 8); - } - ide_other->cylinder = (ide_other->cylinder & 0xFF) | (val << 8); - ide_other->lba_addr = (ide_other->lba_addr & 0xF00FFFF) | (val << 16); - return; + if (!(ide->tf->atastat & (BSY_STAT | DRQ_STAT))) { + ide->tf->cylinder = (ide->tf->cylinder & 0xff) | (val << 8); + ide->lba_addr = (ide->lba_addr & 0xf00ffff) | (val << 16); + } - case 0x6: /* Drive/Head */ - if (ch != ((val >> 4) & 1) + (ide->board << 1)) { - ide_boards[ide->board]->cur_dev = ((val >> 4) & 1) + (ide->board << 1); - ch = ide_boards[ide->board]->cur_dev; + if (!(ide_other->tf->atastat & (BSY_STAT | DRQ_STAT))) { + ide_other->tf->cylinder = (ide_other->tf->cylinder & 0xff) | (val << 8); + ide_other->lba_addr = (ide_other->lba_addr & 0xf00ffff) | (val << 16); + } + break; - ide = ide_drives[ch]; - ide->selected = 1; + case 0x6: /* Drive/Head */ + if (ch != ((val >> 4) & 1) + (ide->board << 1)) { + if (!ide->reset && !ide_other->reset && ide->irqstat) { + ide_irq_lower(ide); + ide->irqstat = 1; + } - ide_other = ide_drives[ch ^ 1]; - ide_other->selected = 0; + ide_boards[ide->board]->cur_dev = ((val >> 4) & 1) + (ide->board << 1); + ch = ide_boards[ide->board]->cur_dev; - if (ide->reset || ide_other->reset) { - ide->atastat = ide_other->atastat = DRDY_STAT | DSC_STAT; - ide->error = ide_other->error = 1; - ide->secount = ide_other->secount = 1; - ide->sector = ide_other->sector = 1; - ide->head = ide_other->head = 0; - ide->cylinder = ide_other->cylinder = 0; - ide->reset = ide_other->reset = 0; + ide = ide_drives[ch]; + ide->selected = 1; - if (ide->type == IDE_ATAPI) { - ide->sc->status = DRDY_STAT | DSC_STAT; - ide->sc->error = 1; - ide->sc->phase = 1; - ide->sc->request_length = 0xEB14; - ide->sc->callback = 0.0; - ide->cylinder = 0xEB14; - } + ide_other = ide_drives[ch ^ 1]; + ide_other->selected = 0; - if (ide_other->type == IDE_ATAPI) { - ide_other->sc->status = DRDY_STAT | DSC_STAT; - ide_other->sc->error = 1; - ide_other->sc->phase = 1; - ide_other->sc->request_length = 0xEB14; - ide_other->sc->callback = 0.0; - ide_other->cylinder = 0xEB14; - } + if (ide->reset || ide_other->reset) { + ide_reset_registers(ide); + ide_reset_registers(ide_other); - ide_set_callback(ide, 0.0); - ide_set_callback(ide_other, 0.0); - ide_set_board_callback(ide->board, 0.0); - return; - } - } - - ide->head = val & 0xF; - ide->lba = val & 0x40; - ide_other->head = val & 0xF; - ide_other->lba = val & 0x40; + ide_set_board_callback(ide->board, 0.0); + reset = 1; + } else + ide_irq_update(ide_boards[ide->board], 1); + } - ide->lba_addr = (ide->lba_addr & 0x0FFFFFF) | ((val & 0xF) << 24); - ide_other->lba_addr = (ide_other->lba_addr & 0x0FFFFFF)|((val & 0xF) << 24); + if (!reset) { + if (!(ide->tf->atastat & (BSY_STAT | DRQ_STAT))) { + ide->tf->drvsel = val & 0xef; + ide->lba_addr = (ide->lba_addr & 0x0ffffff) | + (ide->tf->head << 24); + } - ide_irq_update(ide); - return; + if (!(ide_other->tf->atastat & (BSY_STAT | DRQ_STAT))) { + ide_other->tf->drvsel = val & 0xef; + ide_other->lba_addr = (ide_other->lba_addr & 0x0ffffff) | + (ide->tf->head << 24); + } + } + break; - case 0x7: /* Command register */ - if (ide->type == IDE_NONE) - return; + case 0x7: /* Command register */ + if (ide->tf->atastat & (BSY_STAT | DRQ_STAT)) + break; - ide_irq_lower(ide); - ide->command = val; + if ((ide->type == IDE_NONE) || ((ide->type & IDE_SHADOW) && (val != WIN_DRIVE_DIAGNOSTICS))) + break; - ide->error = 0; - if (ide->type == IDE_ATAPI) - ide->sc->error = 0; + ide_irq_lower(ide); + ide->command = val; - if (((val >= WIN_RECAL) && (val <= 0x1F)) || ((val >= WIN_SEEK) && (val <= 0x7F))) { - if (ide->type == IDE_ATAPI) - ide->sc->status = DRDY_STAT; - else - ide->atastat = READY_STAT | BSY_STAT; + ide->tf->error = 0; - if (ide->type == IDE_ATAPI) - ide->sc->callback = 100.0 * IDE_TIME; - ide_set_callback(ide, 100.0 * IDE_TIME); - return; - } + switch (val) { + case WIN_RECAL ... 0x1F: + case WIN_SEEK ... 0x7F: + if (ide->type == IDE_ATAPI) + ide->tf->atastat = DRDY_STAT; + else + ide->tf->atastat = READY_STAT | BSY_STAT; - switch (val) { - case WIN_SRST: /* ATAPI Device Reset */ - if (ide->type == IDE_ATAPI) { - ide->sc->status = BSY_STAT; - ide->sc->callback = 100.0 * IDE_TIME; - } else - ide->atastat = DRDY_STAT; - - ide_set_callback(ide, 100.0 * IDE_TIME); - return; + if (ide->type == IDE_ATAPI) { + ide->sc->callback = 100.0 * IDE_TIME; + ide_set_callback(ide, 100.0 * IDE_TIME); + } else { + double seek_time = hdd_seek_get_time(&hdd[ide->hdd_num], (val & 0x60) ? + ide_get_sector(ide) : 0, HDD_OP_SEEK, 0, 0.0); + ide_set_callback(ide, seek_time); + } + break; - case WIN_READ_MULTIPLE: - /* Fatal removed in accordance with the official ATAPI reference: - If the Read Multiple command is attempted before the Set Multiple Mode - command has been executed or when Read Multiple commands are - disabled, the Read Multiple operation is rejected with an Aborted Com- - mand error. */ - ide->blockcount = 0; - /* Turn on the activity indicator *here* so that it gets turned on - less times. */ - ui_sb_update_icon(SB_HDD | hdd[ide->hdd_num].bus, 1); - /*FALLTHROUGH*/ + case WIN_SRST: /* ATAPI Device Reset */ + if (ide->type == IDE_ATAPI) { + ide->tf->atastat = BSY_STAT; + ide->sc->callback = 100.0 * IDE_TIME; + } else + ide->tf->atastat = DRDY_STAT; - case WIN_READ: - case WIN_READ_NORETRY: - case WIN_READ_DMA: - case WIN_READ_DMA_ALT: - if (ide->type == IDE_ATAPI) { - ide->sc->status = BSY_STAT; - ide->sc->callback = 200.0 * IDE_TIME; - } else - ide->atastat = BSY_STAT; + ide_set_callback(ide, 100.0 * IDE_TIME); + break; - if (ide->type == IDE_HDD) { - if ((val == WIN_READ_DMA) || (val == WIN_READ_DMA_ALT)) { - if (ide->secount) - ide_set_callback(ide, ide_get_period(ide, (int) ide->secount << 9)); - else - ide_set_callback(ide, ide_get_period(ide, 131072)); - } else if (val == WIN_READ_MULTIPLE) - ide_set_callback(ide, 200.0 * IDE_TIME); - else - ide_set_callback(ide, ide_get_period(ide, 512)); - } else - ide_set_callback(ide, 200.0 * IDE_TIME); - ide->do_initial_read = 1; - return; + case WIN_READ_MULTIPLE: + /* Fatal removed in accordance with the official ATAPI reference: + If the Read Multiple command is attempted before the Set Multiple Mode + command has been executed or when Read Multiple commands are + disabled, the Read Multiple operation is rejected with an Aborted Com- + mand error. */ + ide->blockcount = 0; + fallthrough; - case WIN_WRITE_MULTIPLE: - if (!ide->blocksize && (ide->type != IDE_ATAPI)) - fatal("Write_MULTIPLE - blocksize = 0\n"); - ide->blockcount = 0; - /* Turn on the activity indicator *here* so that it gets turned on - less times. */ - ui_sb_update_icon(SB_HDD | hdd[ide->hdd_num].bus, 1); - /*FALLTHROUGH*/ + case WIN_READ: + case WIN_READ_NORETRY: + case WIN_READ_DMA: + case WIN_READ_DMA_ALT: + ide->tf->atastat = BSY_STAT; - case WIN_WRITE: - case WIN_WRITE_NORETRY: - if (ide->type == IDE_ATAPI) { - ide->sc->status = DRQ_STAT | DSC_STAT | DRDY_STAT; - ide->sc->pos = 0; - } else { - ide->atastat = DRQ_STAT | DSC_STAT | DRDY_STAT; - ide->pos=0; - } - return; + if (ide->type == IDE_ATAPI) + ide->sc->callback = 200.0 * IDE_TIME; - case WIN_WRITE_DMA: - case WIN_WRITE_DMA_ALT: - case WIN_VERIFY: - case WIN_VERIFY_ONCE: - case WIN_IDENTIFY: /* Identify Device */ - case WIN_SET_FEATURES: /* Set Features */ - case WIN_READ_NATIVE_MAX: - if (ide->type == IDE_ATAPI) { - ide->sc->status = BSY_STAT; - ide->sc->callback = 200.0 * IDE_TIME; - } else - ide->atastat = BSY_STAT; + if (ide->type == IDE_HDD) { + ui_sb_update_icon(SB_HDD | hdd[ide->hdd_num].bus, 1); + uint32_t sec_count; + double wait_time; + if ((val == WIN_READ_DMA) || (val == WIN_READ_DMA_ALT)) { + /* TODO make DMA timing more accurate */ + sec_count = ide->tf->secount ? ide->tf->secount : 256; + double seek_time = hdd_timing_read(&hdd[ide->hdd_num], + ide_get_sector(ide), sec_count); + double xfer_time = ide_get_xfer_time(ide, 512 * sec_count); + wait_time = seek_time > xfer_time ? seek_time : xfer_time; + } else if ((val == WIN_READ_MULTIPLE) && (ide->blocksize > 0)) { + sec_count = ide->tf->secount ? ide->tf->secount : 256; + if (sec_count > ide->blocksize) + sec_count = ide->blocksize; + double seek_time = hdd_timing_read(&hdd[ide->hdd_num], + ide_get_sector(ide), sec_count); + double xfer_time = ide_get_xfer_time(ide, 512 * sec_count); + wait_time = seek_time + xfer_time; + } else if ((val == WIN_READ_MULTIPLE) && (ide->blocksize == 0)) + wait_time = 200.0; + else { + sec_count = 1; + double seek_time = hdd_timing_read(&hdd[ide->hdd_num], + ide_get_sector(ide), sec_count); + double xfer_time = ide_get_xfer_time(ide, 512 * sec_count); + wait_time = seek_time + xfer_time; + } + ide_set_callback(ide, wait_time); + } else + ide_set_callback(ide, 200.0 * IDE_TIME); + ide->do_initial_read = 1; + break; - if ((ide->type == IDE_HDD) && - ((val == WIN_WRITE_DMA) || (val == WIN_WRITE_DMA_ALT))) { - if (ide->secount) - ide_set_callback(ide, ide_get_period(ide, (int) ide->secount << 9)); - else - ide_set_callback(ide, ide_get_period(ide, 131072)); - } else if ((ide->type == IDE_HDD) && - ((val == WIN_VERIFY) || (val == WIN_VERIFY_ONCE))) - ide_set_callback(ide, ide_get_period(ide, 512)); - else if (val == WIN_IDENTIFY) - ide_callback(ide); - else - ide_set_callback(ide, 200.0 * IDE_TIME); - return; + case WIN_WRITE_MULTIPLE: + /* Fatal removed for the same reason as for WIN_READ_MULTIPLE. */ + ide->blockcount = 0; + /* Turn on the activity indicator *here* so that it gets turned on + less times. */ + ui_sb_update_icon(SB_HDD | hdd[ide->hdd_num].bus, 1); + fallthrough; - case WIN_FORMAT: - if (ide->type == IDE_ATAPI) - goto ide_bad_command; - else { - ide->atastat = DRQ_STAT; - ide->pos=0; - } - return; + case WIN_WRITE: + case WIN_WRITE_NORETRY: + ide->tf->atastat = DRQ_STAT | DSC_STAT | DRDY_STAT; + ide->tf->pos = 0; + break; - case WIN_SPECIFY: /* Initialize Drive Parameters */ - if (ide->type == IDE_ATAPI) { - ide->sc->status = BSY_STAT; - ide->sc->callback = 30.0 * IDE_TIME; - } else - ide->atastat = BSY_STAT; + case WIN_WRITE_DMA: + case WIN_WRITE_DMA_ALT: + case WIN_VERIFY: + case WIN_VERIFY_ONCE: + case WIN_IDENTIFY: /* Identify Device */ + case WIN_SET_FEATURES: /* Set Features */ + case WIN_READ_NATIVE_MAX: + ide->tf->atastat = BSY_STAT; - ide_set_callback(ide, 30.0 * IDE_TIME); - return; + if (ide->type == IDE_ATAPI) + ide->sc->callback = 200.0 * IDE_TIME; - case WIN_DRIVE_DIAGNOSTICS: /* Execute Drive Diagnostics */ - dev->cur_dev &= ~1; - ide = ide_drives[ch & ~1]; - ide->selected = 1; - ide_other = ide_drives[ch | 1]; - ide_other->selected = 0; + if ((ide->type == IDE_HDD) && ((val == WIN_WRITE_DMA) || (val == WIN_WRITE_DMA_ALT))) { + uint32_t sec_count = ide->tf->secount ? ide->tf->secount : 256; + double seek_time = hdd_timing_read(&hdd[ide->hdd_num], + ide_get_sector(ide), sec_count); + double xfer_time = ide_get_xfer_time(ide, 512 * sec_count); + double wait_time = seek_time > xfer_time ? seek_time : xfer_time; + ide_set_callback(ide, wait_time); + } else if ((ide->type == IDE_HDD) && ((val == WIN_VERIFY) || + (val == WIN_VERIFY_ONCE))) { + uint32_t sec_count = ide->tf->secount ? ide->tf->secount : 256; + double seek_time = hdd_timing_read(&hdd[ide->hdd_num], + ide_get_sector(ide), sec_count); + ide_set_callback(ide, seek_time + ide_get_xfer_time(ide, 2)); + } else if ((val == WIN_IDENTIFY) || (val == WIN_SET_FEATURES)) + ide_callback(ide); + else + ide_set_callback(ide, 200.0 * IDE_TIME); + break; - /* Device 0. */ - dev_reset(ide); - ide->atastat = BSY_STAT; - ide->error = 1; - if (ide->type == IDE_ATAPI) { - ide->sc->status = BSY_STAT; - ide->sc->error = 1; - } + case WIN_FORMAT: + if (ide->type == IDE_ATAPI) + bad = 1; + else { + ide->tf->atastat = DRQ_STAT; + ide->tf->pos = 0; + } + break; - /* Device 1. */ - dev_reset(ide_other); - ide_other->atastat = BSY_STAT; - ide_other->error = 1; - if (ide_other->type == IDE_ATAPI) { - ide_other->sc->status = BSY_STAT; - ide_other->sc->error = 1; - } + case WIN_SPECIFY: /* Initialize Drive Parameters */ + ide->tf->atastat = BSY_STAT; - /* Fire the timer. */ - dev->diag = 1; - ide->reset = 1; - ide_set_callback(ide, 0.0); - ide_set_callback(ide_other, 0.0); - ide_set_board_callback(ide->board, 200.0 * IDE_TIME); - return; + if (ide->type == IDE_ATAPI) + ide->sc->callback = 30.0 * IDE_TIME; - case WIN_PIDENTIFY: /* Identify Packet Device */ - case WIN_SET_MULTIPLE_MODE: /* Set Multiple Mode */ - case WIN_NOP: - case WIN_STANDBYNOW1: - case WIN_IDLENOW1: - case WIN_SETIDLE1: /* Idle */ - case WIN_CHECKPOWERMODE1: - case WIN_SLEEP1: - if (ide->type == IDE_ATAPI) - ide->sc->status = BSY_STAT; - else - ide->atastat = BSY_STAT; - ide_callback(ide); - return; + ide_set_callback(ide, 30.0 * IDE_TIME); + break; - case WIN_PACKETCMD: /* ATAPI Packet */ - /* Skip the command callback wait, and process immediately. */ - if (ide->type == IDE_ATAPI) { - ide->sc->packet_status = PHASE_IDLE; - ide->sc->pos = 0; - ide->sc->phase = 1; - ide->sc->status = DRDY_STAT | DRQ_STAT; - if (ide->interrupt_drq) - ide_irq_raise(ide); /* Interrupt DRQ, requires IRQ on any DRQ. */ - } else { - ide->atastat = BSY_STAT; - ide_set_callback(ide, 200.0 * IDE_TIME); - ide->pos=0; - } - return; + case WIN_DRIVE_DIAGNOSTICS: /* Execute Drive Diagnostics */ + dev->cur_dev &= ~1; + ide = ide_drives[ch & ~1]; + ide->selected = 1; + ide_other = ide_drives[ch | 1]; + ide_other->selected = 0; - case 0xF0: - default: -ide_bad_command: - if (ide->type == IDE_ATAPI) { - ide->sc->status = DRDY_STAT | ERR_STAT | DSC_STAT; - ide->sc->error = ABRT_ERR; - } else { - ide->atastat = DRDY_STAT | ERR_STAT | DSC_STAT; - ide->error = ABRT_ERR; - } - ide_irq_raise(ide); - return; - } - return; + /* Device 0. */ + dev_reset(ide); + ide->tf->atastat = BSY_STAT; + ide->tf->error = 1; + + /* Device 1. */ + dev_reset(ide_other); + ide_other->tf->atastat = BSY_STAT; + ide_other->tf->error = 1; + + /* Fire the timer. */ + dev->diag = 1; + ide->reset = 1; + ide_set_callback(ide, 0.0); + ide_set_callback(ide_other, 0.0); + ide_set_board_callback(ide->board, 200.0 * IDE_TIME); + break; + + case WIN_PIDENTIFY: /* Identify Packet Device */ + case WIN_SET_MULTIPLE_MODE: /* Set Multiple Mode */ + case WIN_NOP: + case WIN_STANDBYNOW1: + case WIN_IDLENOW1: + case WIN_SETIDLE1: /* Idle */ + case WIN_CHECKPOWERMODE1: + case WIN_SLEEP1: + ide->tf->atastat = BSY_STAT; + ide_callback(ide); + break; + + case WIN_PACKETCMD: /* ATAPI Packet */ + /* Skip the command callback wait, and process immediately. */ + ide->tf->pos = 0; + if (ide->type == IDE_ATAPI) { + ide->sc->packet_status = PHASE_IDLE; + ide->tf->secount = 1; + ide->tf->atastat = DRDY_STAT | DRQ_STAT; + if (ide->interrupt_drq) + ide_irq_raise(ide); /* Interrupt DRQ, requires IRQ on any DRQ. */ + } else { + ide->tf->atastat = BSY_STAT; + ide_set_callback(ide, 200.0 * IDE_TIME); + } + break; + + case 0xf0: + default: + bad = 1; + break; + } + + if (bad) { + ide->tf->atastat = DRDY_STAT | ERR_STAT | DSC_STAT; + ide->tf->error = ABRT_ERR; + ide_irq_raise(ide); + } + return; + + default: + break; } } - -static uint32_t +static uint16_t ide_read_data(ide_t *ide, int length) { - uint32_t temp = 0; + const uint8_t *idebufferb = (uint8_t *) ide->buffer; + const uint16_t *idebufferw = ide->buffer; + uint16_t ret = 0; + double seek_us; + double xfer_us; - if (!ide->buffer) { - switch (length) { - case 1: - return 0xff; - case 2: - return 0xffff; - case 4: - return 0xffffffff; - default: - return 0; - } - } +#if defined(ENABLE_IDE_LOG) && (ENABLE_IDE_LOG == 2) + ide_log("ide_read_data(): ch = %i, board = %i, type = %i\n", ch, + ide->board, ide->type); +#endif - uint8_t *idebufferb = (uint8_t *) ide->buffer; - uint16_t *idebufferw = ide->buffer; - uint32_t *idebufferl = (uint32_t *) ide->buffer; - - if (ide->command == WIN_PACKETCMD) { - ide->pos = 0; - if (ide->type == IDE_ATAPI) - temp = ide_atapi_packet_read(ide, length); - else { - ide_log("Drive not ATAPI (position: %i)\n", ide->pos); - return 0; - } + if ((ide->type == IDE_NONE) || (ide->type & IDE_SHADOW) || !ide->buffer) { + if (length == 2) + ret = 0xff7f; + else + ret = 0x7f; + } else if (ide->command == WIN_PACKETCMD) { + if (ide->type == IDE_ATAPI) + ret = ide_atapi_packet_read(ide, length); + else { + ide_log("Drive not ATAPI (position: %i)\n", ide->tf->pos); + ide->tf->pos = 0; + } } else { - switch (length) { - case 1: - temp = idebufferb[ide->pos]; - ide->pos++; - break; - case 2: - temp = idebufferw[ide->pos >> 1]; - ide->pos += 2; - break; - case 4: - temp = idebufferl[ide->pos >> 2]; - ide->pos += 4; - break; - default: - return 0; - } - } - if ((ide->pos >= 512) && (ide->command != WIN_PACKETCMD)) { - ide->pos = 0; - ide->atastat = DRDY_STAT | DSC_STAT; - if (ide->type == IDE_ATAPI) { - ide->sc->status = DRDY_STAT | DSC_STAT; - ide->sc->packet_status = PHASE_IDLE; - } - if ((ide->command == WIN_READ) || (ide->command == WIN_READ_NORETRY) || (ide->command == WIN_READ_MULTIPLE)) { - ide->secount = (ide->secount - 1) & 0xff; - if (ide->secount) { - ide_next_sector(ide); - ide->atastat = BSY_STAT | READY_STAT | DSC_STAT; - if (ide->command == WIN_READ_MULTIPLE) - ide_callback(ide); - else - ide_set_callback(ide, ide_get_period(ide, 512)); - } else if (ide->command != WIN_READ_MULTIPLE) - ui_sb_update_icon(SB_HDD | hdd[ide->hdd_num].bus, 0); - } + if (length == 2) { + ret = idebufferw[ide->tf->pos >> 1]; + ide->tf->pos += 2; + } else { + ret = idebufferb[ide->tf->pos]; + ide->tf->pos++; + } + + if (ide->tf->pos >= 512) { + ide->tf->pos = 0; + ide->tf->atastat = DRDY_STAT | DSC_STAT; + if (ide->type == IDE_ATAPI) + ide->sc->packet_status = PHASE_IDLE; + + if ((ide->command == WIN_READ) || + (ide->command == WIN_READ_NORETRY) || + (ide->command == WIN_READ_MULTIPLE)) { + ide->tf->secount--; + + if (ide->tf->secount) { + ide_next_sector(ide); + ide->tf->atastat = BSY_STAT | READY_STAT | DSC_STAT; + if (ide->command == WIN_READ_MULTIPLE) { + if (!ide->blockcount) { + uint32_t cnt = ide->tf->secount ? + ide->tf->secount : 256; + if (cnt > ide->blocksize) + cnt = ide->blocksize; + seek_us = hdd_timing_read(&hdd[ide->hdd_num], + ide_get_sector(ide), cnt); + xfer_us = ide_get_xfer_time(ide, 512 * cnt); + ide_set_callback(ide, seek_us + xfer_us); + } else + ide_callback(ide); + } else { + seek_us = hdd_timing_read(&hdd[ide->hdd_num], + ide_get_sector(ide), 1); + xfer_us = ide_get_xfer_time(ide, 512); + ide_set_callback(ide, seek_us + xfer_us); + } + } else + ui_sb_update_icon(SB_HDD | hdd[ide->hdd_num].bus, 0); + } + } } - return temp; + return ret; } - static uint8_t ide_status(ide_t *ide, ide_t *ide_other, int ch) { - if ((ide->type == IDE_NONE) && ((ide_other->type == IDE_NONE) || !(ch & 1))) -#ifdef STATUS_BIT_7_PULLDOWN - return 0x7F; /* Bit 7 pulled down, all other bits pulled up, per the spec. */ -#else - return 0xFF; -#endif - else if ((ide->type == IDE_NONE) && (ch & 1)) - return 0x00; /* On real hardware, a slave with a present master always returns a status of 0x00. */ - else if (ide->type == IDE_ATAPI) - return (ide->sc->status & ~DSC_STAT) | (ide->service ? SERVICE_STAT : 0); - else - return ide->atastat; -} + uint8_t ret; + /* Absent and is master or both are absent. */ + if (ide->type == IDE_NONE) { + /* Bit 7 pulled down, all other bits pulled up, per the spec. */ + ret = 0x7f; + /* Absent and is slave and master is present. */ + } else if (ide->type & IDE_SHADOW) { + /* On real hardware, a slave with a present master always + returns a status of 0x00. + Confirmed by the ATA-3 and ATA-4 specifications. */ + ret = 0x00; + } else { + ret = ide->tf->atastat; + if (ide->type == IDE_ATAPI) + ret = (ret & ~DSC_STAT) | (ide->service << 4); + } + + return ret; +} uint8_t ide_readb(uint16_t addr, void *priv) { - ide_board_t *dev = (ide_board_t *) priv; - - int ch; + const ide_board_t *dev = (ide_board_t *) priv; + int ch; ide_t *ide; + uint8_t ret = 0xff; - ch = dev->cur_dev; + ch = dev->cur_dev; ide = ide_drives[ch]; - uint8_t temp = 0xff; - uint16_t tempw; - - addr |= 0x90; - addr &= 0xFFF7; - switch (addr & 0x7) { - case 0x0: /* Data */ - tempw = ide_read_data(ide, 2); - temp = tempw & 0xff; - break; + case 0x0: /* Data */ + ret = ide_read_data(ide, 2) & 0xff; + break; - /* For ATAPI: Bits 7-4 = sense key, bit 3 = MCR (media change requested), - Bit 2 = ABRT (aborted command), Bit 1 = EOM (end of media), - and Bit 0 = ILI (illegal length indication). */ - case 0x1: /* Error */ - if (ide->type == IDE_NONE) - temp = 0; - else if (ide->type == IDE_ATAPI) - temp = ide->sc->error; - else - temp = ide->error; - break; + /* For ATAPI: Bits 7-4 = sense key, bit 3 = MCR (media change requested), + Bit 2 = ABRT (aborted command), Bit 1 = EOM (end of media), + and Bit 0 = ILI (illegal length indication). */ + case 0x1: /* Error */ + if (ide->type == IDE_NONE) + ret = 0x7f; + else + ret = ide->tf->error; + break; - /* For ATAPI: - Bit 0: Command or Data: - Data if clear, Command if set; - Bit 1: I/OB - Direction: - To device if set; - From device if clear. - IO DRQ CoD - 0 1 1 Ready to accept command packet - 1 1 1 Message - ready to send message to host - 1 1 0 Data to host - 0 1 0 Data from host - 1 0 1 Status. */ - case 0x2: /* Sector count */ - if (ide->type == IDE_ATAPI) - temp = ide->sc->phase; - else if (ide->type != IDE_NONE) - temp = ide->secount; - break; + /* For ATAPI: + Bit 0: Command or Data: + Data if clear, Command if set; + Bit 1: I/OB + Direction: + To device if set; + From device if clear. + IO DRQ CoD + 0 1 1 Ready to accept command packet + 1 1 1 Message - ready to send message to host + 1 1 0 Data to host + 0 1 0 Data from host + 1 0 1 Status. */ + case 0x2: /* Sector count */ + if (ide->type == IDE_NONE) + ret = 0x7f; + else + ret = ide->tf->secount; + break; - case 0x3: /* Sector */ - if (ide->type != IDE_NONE) - temp = (uint8_t) ide->sector; - break; + case 0x3: /* Sector */ + if (ide->type == IDE_NONE) + ret = 0x7f; + else + ret = (uint8_t) ide->tf->sector; + break; - case 0x4: /* Cylinder low */ - if (ide->type == IDE_NONE) - temp = 0xFF; - else if (ide->type == IDE_ATAPI) - temp = ide->sc->request_length & 0xff; - else - temp = ide->cylinder & 0xff; - break; + case 0x4: /* Cylinder low */ + if (ide->type == IDE_NONE) + ret = 0x7f; + else + ret = ide->tf->cylinder & 0xff; +#if defined(ENABLE_IDE_LOG) && (ENABLE_IDE_LOG == 2) + ide_log("Cylinder low @ board %i, channel %i: ide->type = %i, " + "ret = %02X\n", ide->board, ide->channel, ide->type, ret); +#endif + break; - case 0x5: /* Cylinder high */ - if (ide->type == IDE_NONE) - temp = 0xFF; - else if (ide->type == IDE_ATAPI) - temp = ide->sc->request_length >> 8; - else - temp = ide->cylinder >> 8; - break; + case 0x5: /* Cylinder high */ + if (ide->type == IDE_NONE) + ret = 0x7f; + else + ret = ide->tf->cylinder >> 8; +#if defined(ENABLE_IDE_LOG) && (ENABLE_IDE_LOG == 2) + pclog("Cylinder high @ board %i, channel %i: ide->type = %i, " + "ret = %02X\n", ide->board, ide->channel, ide->type, ret); +#endif + break; - case 0x6: /* Drive/Head */ - temp = (uint8_t)(ide->head | ((ch & 1) ? 0x10 : 0) | (ide->lba ? 0x40 : 0) | 0xa0); - break; + case 0x6: /* Drive/Head */ + if (ide->type == IDE_NONE) + ret = 0x7f; + else + ret = ide->tf->drvsel | ((ch & 1) ? 0xb0 : 0xa0); + break; - /* For ATAPI: Bit 5 is DMA ready, but without overlapped or interlaved DMA, it is - DF (drive fault). */ - case 0x7: /* Status */ - ide_irq_lower(ide); - temp = ide_status(ide, ide_drives[ch ^ 1], ch); - break; + /* For ATAPI: Bit 5 is DMA ready, but without overlapped or interlaved DMA, it is + DF (drive fault). */ + case 0x7: /* Status */ + ide_irq(ide, 0, 0); + ret = ide_status(ide, ide_drives[ch ^ 1], ch); + break; + + default: + break; } - ide_log("ide_readb(%04X, %08X) = %02X\n", addr, priv, temp); - return temp; + ide_log("ide_readb(%04X, %08X) = %02X\n", addr, priv, ret); + return ret; } - uint8_t -ide_read_alt_status(uint16_t addr, void *priv) +ide_read_alt_status(UNUSED(uint16_t addr), void *priv) { - uint8_t temp = 0xff; + uint8_t ret = 0xff; - ide_board_t *dev = (ide_board_t *) priv; + const ide_board_t *dev = (ide_board_t *) priv; ide_t *ide; - int ch; + int ch; - ch = dev->cur_dev; + ch = dev->cur_dev; ide = ide_drives[ch]; /* Per the Seagate ATA-3 specification: Reading the alternate status does *NOT* clear the IRQ. */ - temp = ide_status(ide, ide_drives[ch ^ 1], ch); + ret = ide_status(ide, ide_drives[ch ^ 1], ch); - ide_log("ide_read_alt_status(%04X, %08X) = %02X\n", addr, priv, temp); - return temp; + ide_log("ide_read_alt_status(%04X, %08X) = %02X\n", addr, priv, ret); + return ret; } - uint16_t ide_readw(uint16_t addr, void *priv) { - uint16_t temp = 0xffff; + uint16_t ret = 0xffff; - ide_board_t *dev = (ide_board_t *) priv; + const ide_board_t *dev = (ide_board_t *) priv; ide_t *ide; - int ch; + int ch; - ch = dev->cur_dev; + ch = dev->cur_dev; ide = ide_drives[ch]; switch (addr & 0x7) { - case 0x0: /* Data */ - temp = ide_read_data(ide, 2); - break; - case 0x7: - temp = ide_readb(addr, priv) | 0xff00; - break; - default: - temp = ide_readb(addr, priv) | (ide_readb(addr + 1, priv) << 8); - break; + case 0x0: /* Data */ + ret = ide_read_data(ide, 2); + break; + case 0x7: + ret = ide_readb(addr, priv) | 0xff00; + break; + default: + ret = ide_readb(addr, priv) | (ide_readb(addr + 1, priv) << 8); + break; } - ide_log("ide_readw(%04X, %08X) = %04X\n", addr, priv, temp); - return temp; +#if defined(ENABLE_IDE_LOG) && (ENABLE_IDE_LOG == 2) + ide_log("ide_readw(%04X, %08X) = %04X\n", addr, priv, ret); +#endif + return ret; } - static uint32_t ide_readl(uint16_t addr, void *priv) { - uint16_t temp2; - uint32_t temp = 0xffffffff; - - ide_board_t *dev = (ide_board_t *) priv; - ide_t *ide; - int ch; + int ch; + uint32_t ret = 0xffffffff; - ch = dev->cur_dev; + const ide_board_t *dev = (ide_board_t *) priv; + + ch = dev->cur_dev; ide = ide_drives[ch]; switch (addr & 0x7) { - case 0x0: /* Data */ - temp2 = ide_read_data(ide, 2); - if (dev->bit32) - temp = temp2 | (ide_read_data(ide, 2) << 16); - else - temp = temp2 | (ide_readw(addr + 2, priv) << 16); - break; - case 0x6: case 0x7: - temp = ide_readw(addr, priv) | 0xffff0000; - break; - default: - temp = ide_readw(addr, priv) | (ide_readw(addr + 2, priv) << 16); - break; + case 0x0: /* Data */ + ret = ide_read_data(ide, 2); + if (dev->bit32) + ret |= (ide_read_data(ide, 2) << 16); + else + ret |= (ide_readw(addr + 2, priv) << 16); + break; + case 0x6: + case 0x7: + ret = ide_readw(addr, priv) | 0xffff0000; + break; + default: + ret = ide_readw(addr, priv) | (ide_readw(addr + 2, priv) << 16); + break; } - ide_log("ide_readl(%04X, %08X) = %04X\n", addr, priv, temp); - return temp; +#if defined(ENABLE_IDE_LOG) && (ENABLE_IDE_LOG == 2) + ide_log("ide_readl(%04X, %08X) = %04X\n", addr, priv, ret); +#endif + return ret; } - static void ide_board_callback(void *priv) { - ide_board_t *dev = (ide_board_t *) priv; + ide_board_t *dev = (ide_board_t *) priv; + ide_t *ide; -#ifdef ENABLE_IDE_LOG - ide_log("CALLBACK RESET\n"); -#endif + ide_log("ide_board_callback(%i)\n", dev->cur_dev >> 1); - dev->ide[0]->atastat = DRDY_STAT | DSC_STAT; - if (dev->ide[0]->type == IDE_ATAPI) - dev->ide[0]->sc->status = DRDY_STAT | DSC_STAT; - - dev->ide[1]->atastat = DRDY_STAT | DSC_STAT; - if (dev->ide[1]->type == IDE_ATAPI) - dev->ide[1]->sc->status = DRDY_STAT | DSC_STAT; + for (uint8_t i = 0; i < 2; i++) { + ide = dev->ide[i]; + if (ide->type == IDE_ATAPI) { + ide->tf->atastat = 0; + if (IDE_ATAPI_IS_EARLY) + ide->tf->atastat |= DRDY_STAT | DSC_STAT; + } else + ide->tf->atastat = DRDY_STAT | DSC_STAT; + } dev->cur_dev &= ~1; + ide = dev->ide[0]; if (dev->diag) { - dev->diag = 0; - ide_irq_raise(dev->ide[0]); + dev->diag = 0; + if ((ide->type != IDE_ATAPI) || IDE_ATAPI_IS_EARLY) + ide_irq_raise(ide); } } +static void +atapi_error_no_ready(ide_t *ide) +{ + ide->command = 0; + ide->tf->atastat = ERR_STAT | DSC_STAT; + ide->tf->error = ABRT_ERR; + ide->tf->pos = 0; + + ide_irq_raise(ide); +} static void ide_callback(void *priv) { - int snum, ret = 0; - + int snum; + int ret = 0; + uint8_t err = 0x00; + int chk_chs = 0; ide_t *ide = (ide_t *) priv; + ide_bm_t *bm = ide_boards[ide->board]->bm; - ide_log("CALLBACK %02X %i %i\n", ide->command, ide->reset, ide->channel); - - if (((ide->command >= WIN_RECAL) && (ide->command <= 0x1F)) || - ((ide->command >= WIN_SEEK) && (ide->command <= 0x7F))) { - if (ide->type != IDE_HDD) - goto abort_cmd; - if ((ide->command >= WIN_SEEK) && (ide->command <= 0x7F) && !ide->lba) { - if ((ide->cylinder >= ide->tracks) || (ide->head >= ide->hpc) || - !ide->sector || (ide->sector > ide->spt)) - goto id_not_found; - } - ide->atastat = DRDY_STAT | DSC_STAT; - ide_irq_raise(ide); - return; - } + ide_log("ide_callback(%i): %02X\n", ide->channel, ide->command); switch (ide->command) { - /* Initialize the Task File Registers as follows: Status = 00h, Error = 01h, Sector Count = 01h, Sector Number = 01h, - Cylinder Low = 14h, Cylinder High =EBh and Drive/Head = 00h. */ + case WIN_SEEK ... 0x7f: + chk_chs = !ide->tf->lba; + if (ide->type == IDE_ATAPI) + atapi_error_no_ready(ide); + else { + if (chk_chs && ((ide->tf->cylinder >= ide->tracks) || (ide->tf->head >= ide->hpc) || + !ide->tf->sector || (ide->tf->sector > ide->spt))) + err = IDNF_ERR; + else { + ide->tf->atastat = DRDY_STAT | DSC_STAT; + ide_irq_raise(ide); + } + } + break; + + case WIN_RECAL ... 0x1f: + if (ide->type == IDE_ATAPI) + atapi_error_no_ready(ide); + else { + ide->tf->atastat = DRDY_STAT | DSC_STAT; + ide_irq_raise(ide); + } + break; + + /* Initialize the Task File Registers as follows: + Status = 00h, Error = 01h, Sector Count = 01h, Sector Number = 01h, + Cylinder Low = 14h, Cylinder High = EBh and Drive/Head = 00h. */ case WIN_SRST: /*ATAPI Device Reset */ + ide->tf->error = 1; /*Device passed*/ - ide->atastat = DRDY_STAT | DSC_STAT; - ide->error = 1; /*Device passed*/ - ide->secount = 1; - ide->sector = 1; + ide->tf->secount = 1; + ide->tf->sector = 1; - ide_set_signature(ide); + ide_set_signature(ide); - if (ide->type == IDE_ATAPI) { - ide->sc->status = DRDY_STAT | DSC_STAT; - ide->sc->error = 1; - if (ide->device_reset) - ide->device_reset(ide->sc); - } - ide_irq_raise(ide); - if (ide->type == IDE_ATAPI) - ide->service = 0; - return; + ide->tf->atastat = DRDY_STAT | DSC_STAT; + if (ide->type == IDE_ATAPI) { + if (ide->device_reset) + ide->device_reset(ide->sc); + if (!IDE_ATAPI_IS_EARLY) + ide->tf->atastat = 0; + } - case WIN_NOP: - case WIN_STANDBYNOW1: - case WIN_IDLENOW1: - case WIN_SETIDLE1: - if (ide->type == IDE_ATAPI) - ide->sc->status = DRDY_STAT | DSC_STAT; - else - ide->atastat = DRDY_STAT | DSC_STAT; - ide_irq_raise(ide); - return; + ide_irq_raise(ide); - case WIN_CHECKPOWERMODE1: - case WIN_SLEEP1: - if (ide->type == IDE_ATAPI) { - ide->sc->phase = 0xFF; - ide->sc->status = DRDY_STAT | DSC_STAT; - } - ide->secount = 0xFF; - ide->atastat = DRDY_STAT | DSC_STAT; - ide_irq_raise(ide); - return; + if ((ide->type == IDE_ATAPI) && !IDE_ATAPI_IS_EARLY) + ide->service = 0; + break; - case WIN_READ: - case WIN_READ_NORETRY: - if (ide->type == IDE_ATAPI) { - ide_set_signature(ide); - goto abort_cmd; - } - if (!ide->lba && (ide->cfg_spt == 0)) - goto id_not_found; + case WIN_NOP: + case WIN_STANDBYNOW1: + case WIN_IDLENOW1: + case WIN_SETIDLE1: + ide->tf->atastat = DRDY_STAT | DSC_STAT; + ide_irq_raise(ide); + break; - if (ide->do_initial_read) { - ide->do_initial_read = 0; - ide->sector_pos = 0; - if (ide->secount) - hdd_image_read(ide->hdd_num, ide_get_sector(ide), ide->secount, ide->sector_buffer); - else - hdd_image_read(ide->hdd_num, ide_get_sector(ide), 256, ide->sector_buffer); - } + case WIN_CHECKPOWERMODE1: + case WIN_SLEEP1: + ide->tf->secount = 0xff; + ide->tf->atastat = DRDY_STAT | DSC_STAT; + ide_irq_raise(ide); + break; - memcpy(ide->buffer, &ide->sector_buffer[ide->sector_pos*512], 512); + case WIN_READ: + case WIN_READ_NORETRY: + if (ide->type == IDE_ATAPI) { + ide_set_signature(ide); + err = ABRT_ERR; + } else if (!ide->tf->lba && (ide->cfg_spt == 0)) + err = IDNF_ERR; + else { + if (ide->do_initial_read) { + ide->do_initial_read = 0; + ide->sector_pos = 0; + hdd_image_read(ide->hdd_num, ide_get_sector(ide), + ide->tf->secount ? ide->tf->secount : 256, ide->sector_buffer); + } - ide->sector_pos++; - ide->pos = 0; + memcpy(ide->buffer, &ide->sector_buffer[ide->sector_pos * 512], 512); - ide->atastat = DRQ_STAT | DRDY_STAT | DSC_STAT; + ide->sector_pos++; - ide_irq_raise(ide); + ide->tf->pos = 0; + ide->tf->atastat = DRQ_STAT | DRDY_STAT | DSC_STAT; - ui_sb_update_icon(SB_HDD | hdd[ide->hdd_num].bus, 1); - return; + ide_irq_raise(ide); - case WIN_READ_DMA: - case WIN_READ_DMA_ALT: - if ((ide->type == IDE_ATAPI) || ide_boards[ide->board]->force_ata3 || !ide_bm[ide->board]) { - ide_log("IDE %i: DMA read aborted (bad device or board)\n", ide->channel); - goto abort_cmd; - } - if (!ide->lba && (ide->cfg_spt == 0)) { - ide_log("IDE %i: DMA read aborted (SPECIFY failed)\n", ide->channel); - goto id_not_found; - } + ui_sb_update_icon(SB_HDD | hdd[ide->hdd_num].bus, 1); + } + break; - ide->sector_pos = 0; - if (ide->secount) - ide->sector_pos = ide->secount; - else - ide->sector_pos = 256; - hdd_image_read(ide->hdd_num, ide_get_sector(ide), ide->sector_pos, ide->sector_buffer); + case WIN_READ_DMA: + case WIN_READ_DMA_ALT: + if ((ide->type == IDE_ATAPI) || ide_boards[ide->board]->force_ata3 || (bm == NULL)) { + ide_log("IDE %i: DMA read aborted (bad device or board)\n", ide->channel); + err = ABRT_ERR; + } else if (!ide->tf->lba && (ide->cfg_spt == 0)) { + ide_log("IDE %i: DMA read aborted (SPECIFY failed)\n", ide->channel); + err = IDNF_ERR; + } else { + ide->sector_pos = 0; + if (ide->tf->secount) + ide->sector_pos = ide->tf->secount; + else + ide->sector_pos = 256; + hdd_image_read(ide->hdd_num, ide_get_sector(ide), ide->sector_pos, ide->sector_buffer); - ide->pos=0; + ide->tf->pos = 0; - if (!ide_boards[ide->board]->force_ata3 && ide_bm[ide->board] && ide_bm[ide->board]->dma) { - /* We should not abort - we should simply wait for the host to start DMA. */ - ret = ide_bm[ide->board]->dma(ide->board, - ide->sector_buffer, ide->sector_pos * 512, - 0, ide_bm[ide->board]->priv); - if (ret == 2) { - /* Bus master DMA disabled, simply wait for the host to enable DMA. */ - ide->atastat = DRQ_STAT | DRDY_STAT | DSC_STAT; - ide_set_callback(ide, 6.0 * IDE_TIME); - return; - } else if (ret == 1) { - /*DMA successful*/ - ide_log("IDE %i: DMA read successful\n", ide->channel); + if (!ide_boards[ide->board]->force_ata3 && (bm != NULL) && bm->dma) { + /* We should not abort - we should simply wait for the host to start DMA. */ + ret = bm->dma(ide->sector_buffer, ide->sector_pos * 512, 0, bm->priv); + if (ret == 2) { + /* Bus master DMA disabled, simply wait for the host to enable DMA. */ + ide->tf->atastat = DRQ_STAT | DRDY_STAT | DSC_STAT; + ide_set_callback(ide, 6.0 * IDE_TIME); + return; + } else if (ret == 1) { + /* DMA successful */ + ide_log("IDE %i: DMA read successful\n", ide->channel); - ide->atastat = DRDY_STAT | DSC_STAT; + ide->tf->atastat = DRDY_STAT | DSC_STAT; - ide_irq_raise(ide); - ui_sb_update_icon(SB_HDD | hdd[ide->hdd_num].bus, 0); - } else { - /* Bus master DMAS error, abort the command. */ - ide_log("IDE %i: DMA read aborted (failed)\n", ide->channel); - goto abort_cmd; - } - } else { - ide_log("IDE %i: DMA read aborted (no bus master)\n", ide->channel); - goto abort_cmd; - } - return; + ide_irq_raise(ide); + ui_sb_update_icon(SB_HDD | hdd[ide->hdd_num].bus, 0); + } else { + /* Bus master DMAS error, abort the command. */ + ide_log("IDE %i: DMA read aborted (failed)\n", ide->channel); + err = ABRT_ERR; + } + } else { + ide_log("IDE %i: DMA read aborted (no bus master)\n", ide->channel); + err = ABRT_ERR; + } + } + break; - case WIN_READ_MULTIPLE: - /* According to the official ATA reference: + case WIN_READ_MULTIPLE: + /* According to the official ATA reference: - If the Read Multiple command is attempted before the Set Multiple Mode - command has been executed or when Read Multiple commands are - disabled, the Read Multiple operation is rejected with an Aborted Com- - mand error. */ - if ((ide->type == IDE_ATAPI) || !ide->blocksize) - goto abort_cmd; - if (!ide->lba && (ide->cfg_spt == 0)) - goto id_not_found; + If the Read Multiple command is attempted before the Set Multiple Mode + command has been executed or when Read Multiple commands are + disabled, the Read Multiple operation is rejected with an Aborted Com- + mand error. */ + if ((ide->type == IDE_ATAPI) || !ide->blocksize) + err = ABRT_ERR; + else if (!ide->tf->lba && (ide->cfg_spt == 0)) + err = IDNF_ERR; + else { + if (ide->do_initial_read) { + ide->do_initial_read = 0; + ide->sector_pos = 0; + hdd_image_read(ide->hdd_num, ide_get_sector(ide), + ide->tf->secount ? ide->tf->secount : 256, ide->sector_buffer); + } - if (ide->do_initial_read) { - ide->do_initial_read = 0; - ide->sector_pos = 0; - if (ide->secount) - hdd_image_read(ide->hdd_num, ide_get_sector(ide), ide->secount, ide->sector_buffer); - else - hdd_image_read(ide->hdd_num, ide_get_sector(ide), 256, ide->sector_buffer); - } + memcpy(ide->buffer, &ide->sector_buffer[ide->sector_pos * 512], 512); - memcpy(ide->buffer, &ide->sector_buffer[ide->sector_pos*512], 512); + ide->sector_pos++; + ide->tf->pos = 0; - ide->sector_pos++; - ide->pos=0; + ide->tf->atastat = DRQ_STAT | DRDY_STAT | DSC_STAT; + if (!ide->blockcount) + ide_irq_raise(ide); + ide->blockcount++; + if (ide->blockcount >= ide->blocksize) + ide->blockcount = 0; + } + break; - ide->atastat = DRQ_STAT | DRDY_STAT | DSC_STAT; - if (!ide->blockcount) - ide_irq_raise(ide); - ide->blockcount++; - if (ide->blockcount >= ide->blocksize) - ide->blockcount = 0; - return; + case WIN_WRITE: + case WIN_WRITE_NORETRY: + if (ide->type == IDE_ATAPI) + err = ABRT_ERR; + else if (!ide->tf->lba && (ide->cfg_spt == 0)) + err = IDNF_ERR; + else { + hdd_image_write(ide->hdd_num, ide_get_sector(ide), 1, (uint8_t *) ide->buffer); + ide_irq_raise(ide); + ide->tf->secount--; + if (ide->tf->secount) { + ide->tf->atastat = DRQ_STAT | DRDY_STAT | DSC_STAT; + ide->tf->pos = 0; + ide_next_sector(ide); + ui_sb_update_icon(SB_HDD | hdd[ide->hdd_num].bus, 1); + } else { + ide->tf->atastat = DRDY_STAT | DSC_STAT; + ui_sb_update_icon(SB_HDD | hdd[ide->hdd_num].bus, 0); + } + } + break; - case WIN_WRITE: - case WIN_WRITE_NORETRY: - if (ide->type == IDE_ATAPI) - goto abort_cmd; - if (!ide->lba && (ide->cfg_spt == 0)) - goto id_not_found; - hdd_image_write(ide->hdd_num, ide_get_sector(ide), 1, (uint8_t *) ide->buffer); - ide_irq_raise(ide); - ide->secount = (ide->secount - 1) & 0xff; - if (ide->secount) { - ide->atastat = DRQ_STAT | DRDY_STAT | DSC_STAT; - ide->pos=0; - ide_next_sector(ide); - ui_sb_update_icon(SB_HDD | hdd[ide->hdd_num].bus, 1); - } else { - ide->atastat = DRDY_STAT | DSC_STAT; - ui_sb_update_icon(SB_HDD | hdd[ide->hdd_num].bus, 0); - } - return; + case WIN_WRITE_DMA: + case WIN_WRITE_DMA_ALT: + if ((ide->type == IDE_ATAPI) || ide_boards[ide->board]->force_ata3 || (bm == NULL)) { + ide_log("IDE %i: DMA write aborted (bad device type or board)\n", ide->channel); + err = ABRT_ERR; + } else if (!ide->tf->lba && (ide->cfg_spt == 0)) { + ide_log("IDE %i: DMA write aborted (SPECIFY failed)\n", ide->channel); + err = IDNF_ERR; + } else { + if (!ide_boards[ide->board]->force_ata3 && (bm != NULL) && bm->dma) { + if (ide->tf->secount) + ide->sector_pos = ide->tf->secount; + else + ide->sector_pos = 256; - case WIN_WRITE_DMA: - case WIN_WRITE_DMA_ALT: - if ((ide->type == IDE_ATAPI) || ide_boards[ide->board]->force_ata3 || !ide_bm[ide->board]) { - ide_log("IDE %i: DMA write aborted (bad device type or board)\n", ide->channel); - goto abort_cmd; - } - if (!ide->lba && (ide->cfg_spt == 0)) { - ide_log("IDE %i: DMA write aborted (SPECIFY failed)\n", ide->channel); - goto id_not_found; - } + ret = bm->dma(ide->sector_buffer, ide->sector_pos * 512, 1, bm->priv); - if (!ide_boards[ide->board]->force_ata3 && ide_bm[ide->board] && ide_bm[ide->board]->dma) { - if (ide->secount) - ide->sector_pos = ide->secount; - else - ide->sector_pos = 256; + if (ret == 2) { + /* Bus master DMA disabled, simply wait for the host to enable DMA. */ + ide->tf->atastat = DRQ_STAT | DRDY_STAT | DSC_STAT; + ide_set_callback(ide, 6.0 * IDE_TIME); + return; + } else if (ret == 1) { + /* DMA successful */ + ide_log("IDE %i: DMA write successful\n", ide->channel); - ret = ide_bm[ide->board]->dma(ide->board, - ide->sector_buffer, ide->sector_pos * 512, - 1, ide_bm[ide->board]->priv); + hdd_image_write(ide->hdd_num, ide_get_sector(ide), + ide->sector_pos, ide->sector_buffer); - if (ret == 2) { - /* Bus master DMA disabled, simply wait for the host to enable DMA. */ - ide->atastat = DRQ_STAT | DRDY_STAT | DSC_STAT; - ide_set_callback(ide, 6.0 * IDE_TIME); - return; - } else if (ret == 1) { - /*DMA successful*/ - ide_log("IDE %i: DMA write successful\n", ide->channel); + ide->tf->atastat = DRDY_STAT | DSC_STAT; - hdd_image_write(ide->hdd_num, ide_get_sector(ide), ide->sector_pos, ide->sector_buffer); + ide_irq_raise(ide); + ui_sb_update_icon(SB_HDD | hdd[ide->hdd_num].bus, 0); + } else { + /* Bus master DMA error, abort the command. */ + ide_log("IDE %i: DMA read aborted (failed)\n", ide->channel); + err = ABRT_ERR; + } + } else { + ide_log("IDE %i: DMA write aborted (no bus master)\n", ide->channel); + err = ABRT_ERR; + } + } + break; - ide->atastat = DRDY_STAT | DSC_STAT; + case WIN_WRITE_MULTIPLE: + /* According to the official ATA reference: - ide_irq_raise(ide); - ui_sb_update_icon(SB_HDD | hdd[ide->hdd_num].bus, 0); - } else { - /* Bus master DMA error, abort the command. */ - ide_log("IDE %i: DMA read aborted (failed)\n", ide->channel); - goto abort_cmd; - } - } else { - ide_log("IDE %i: DMA write aborted (no bus master)\n", ide->channel); - goto abort_cmd; - } + If the Read Multiple command is attempted before the Set Multiple Mode + command has been executed or when Read Multiple commands are + disabled, the Read Multiple operation is rejected with an Aborted Com- + mand error. */ + if ((ide->type == IDE_ATAPI) || !ide->blocksize) + err = ABRT_ERR; + else if (!ide->tf->lba && (ide->cfg_spt == 0)) + err = IDNF_ERR; + else { + hdd_image_write(ide->hdd_num, ide_get_sector(ide), 1, (uint8_t *) ide->buffer); + ide->blockcount++; + if (ide->blockcount >= ide->blocksize || ide->tf->secount == 1) { + ide->blockcount = 0; + ide_irq_raise(ide); + } + ide->tf->secount--; + if (ide->tf->secount) { + ide->tf->atastat = DRQ_STAT | DRDY_STAT | DSC_STAT; + ide->tf->pos = 0; + ide_next_sector(ide); + } else { + ide->tf->atastat = DRDY_STAT | DSC_STAT; + ui_sb_update_icon(SB_HDD | hdd[ide->hdd_num].bus, 0); + } + } + break; - return; + case WIN_VERIFY: + case WIN_VERIFY_ONCE: + if (ide->type == IDE_ATAPI) + err = ABRT_ERR; + else if (!ide->tf->lba && (ide->cfg_spt == 0)) + err = IDNF_ERR; + else { + ide->tf->pos = 0; + ide->tf->atastat = DRDY_STAT | DSC_STAT; + ide_irq_raise(ide); + ui_sb_update_icon(SB_HDD | hdd[ide->hdd_num].bus, 1); + } + break; - case WIN_WRITE_MULTIPLE: - if (ide->type == IDE_ATAPI) - goto abort_cmd; - if (!ide->lba && (ide->cfg_spt == 0)) - goto id_not_found; - hdd_image_write(ide->hdd_num, ide_get_sector(ide), 1, (uint8_t *) ide->buffer); - ide->blockcount++; - if (ide->blockcount >= ide->blocksize || ide->secount == 1) { - ide->blockcount = 0; - ide_irq_raise(ide); - } - ide->secount = (ide->secount - 1) & 0xff; - if (ide->secount) { - ide->atastat = DRQ_STAT | DRDY_STAT | DSC_STAT; - ide->pos=0; - ide_next_sector(ide); - } else { - ide->atastat = DRDY_STAT | DSC_STAT; - ui_sb_update_icon(SB_HDD | hdd[ide->hdd_num].bus, 0); - } - return; + case WIN_FORMAT: + if (ide->type == IDE_ATAPI) + err = ABRT_ERR; + else if (!ide->tf->lba && (ide->cfg_spt == 0)) + err = IDNF_ERR; + else { + hdd_image_zero(ide->hdd_num, ide_get_sector(ide), ide->tf->secount); - case WIN_VERIFY: - case WIN_VERIFY_ONCE: - if (ide->type == IDE_ATAPI) - goto abort_cmd; - if (!ide->lba && (ide->cfg_spt == 0)) - goto id_not_found; - ide->pos=0; - ide->atastat = DRDY_STAT | DSC_STAT; - ide_irq_raise(ide); - ui_sb_update_icon(SB_HDD | hdd[ide->hdd_num].bus, 1); - return; + ide->tf->atastat = DRDY_STAT | DSC_STAT; + ide_irq_raise(ide); - case WIN_FORMAT: - if (ide->type == IDE_ATAPI) - goto abort_cmd; - if (!ide->lba && (ide->cfg_spt == 0)) - goto id_not_found; - hdd_image_zero(ide->hdd_num, ide_get_sector(ide), ide->secount); + ui_sb_update_icon(SB_HDD | hdd[ide->hdd_num].bus, 1); + } + break; - ide->atastat = DRDY_STAT | DSC_STAT; - ide_irq_raise(ide); + case WIN_SPECIFY: /* Initialize Drive Parameters */ + if (ide->type == IDE_ATAPI) + err = ABRT_ERR; + else { + if (ide->cfg_spt == 0) { + /* Only accept after RESET or DIAG. */ + ide->cfg_spt = ide->tf->secount; + ide->cfg_hpc = ide->tf->head + 1; + } + ide->command = 0x00; + ide->tf->atastat = DRDY_STAT | DSC_STAT; + ide->tf->error = 1; + ide_irq_raise(ide); + } + break; - ui_sb_update_icon(SB_HDD | hdd[ide->hdd_num].bus, 1); - return; + case WIN_PIDENTIFY: /* Identify Packet Device */ + if (ide->type == IDE_ATAPI) { + ide_identify(ide); + ide->tf->pos = 0; + ide->tf->phase = 2; + ide->tf->error = 0; + ide->tf->atastat = DRQ_STAT | DRDY_STAT | DSC_STAT; + ide_irq_raise(ide); + } else + err = ABRT_ERR; + break; - case WIN_SPECIFY: /* Initialize Drive Parameters */ - if (ide->type == IDE_ATAPI) - goto abort_cmd; - if (ide->cfg_spt == 0) { - /* Only accept after RESET or DIAG. */ - ide->cfg_spt = ide->secount; - ide->cfg_hpc = ide->head + 1; - } - ide->command = 0x00; - ide->atastat = DRDY_STAT | DSC_STAT; - ide->error = 1; - ide_irq_raise(ide); - return; + case WIN_SET_MULTIPLE_MODE: + if ((ide->type == IDE_ATAPI) || (ide->tf->secount < 2) || + (ide->tf->secount > hdd[ide->hdd_num].max_multiple_block)) + err = ABRT_ERR; + else { + ide->blocksize = ide->tf->secount; + ide->tf->atastat = DRDY_STAT | DSC_STAT; + ide_irq_raise(ide); + } + break; - case WIN_PIDENTIFY: /* Identify Packet Device */ - if (ide->type == IDE_ATAPI) { - ide_identify(ide); - ide->pos = 0; - ide->sc->phase = 2; - ide->sc->pos = 0; - ide->sc->error = 0; - ide->sc->status = DRQ_STAT | DRDY_STAT | DSC_STAT; - ide_irq_raise(ide); - return; - } - goto abort_cmd; + case WIN_SET_FEATURES: + if ((ide->type == IDE_NONE) || !ide_set_features(ide)) + err = ABRT_ERR; + else { + ide->tf->atastat = DRDY_STAT | DSC_STAT; - case WIN_SET_MULTIPLE_MODE: - if (ide->type == IDE_ATAPI) - goto abort_cmd; - ide->blocksize = ide->secount; - ide->atastat = DRDY_STAT | DSC_STAT; - ide_irq_raise(ide); - return; + if (ide->type == IDE_ATAPI) + ide->tf->pos = 0; - case WIN_SET_FEATURES: - if ((ide->type == IDE_NONE) || !ide_set_features(ide)) - goto abort_cmd; + ide_irq_raise(ide); + } + break; - if (ide->type == IDE_ATAPI) { - ide->sc->status = DRDY_STAT | DSC_STAT; - ide->sc->pos = 0; - } + case WIN_READ_NATIVE_MAX: + if (ide->type == IDE_HDD) { + snum = hdd[ide->hdd_num].spt; + snum *= hdd[ide->hdd_num].hpc; + snum *= hdd[ide->hdd_num].tracks; + ide_set_sector(ide, snum - 1); + ide->tf->atastat = DRDY_STAT | DSC_STAT; + ide_irq_raise(ide); + } else + err = ABRT_ERR; + break; - ide->atastat = DRDY_STAT | DSC_STAT; - ide_irq_raise(ide); - return; + case WIN_IDENTIFY: /* Identify Device */ + if (ide->type == IDE_HDD) { + ide_identify(ide); + ide->tf->pos = 0; + ide->tf->atastat = DRQ_STAT | DRDY_STAT | DSC_STAT; + ide_irq_raise(ide); + } else { + ide_set_signature(ide); + err = ABRT_ERR; + } + break; - case WIN_READ_NATIVE_MAX: - if (ide->type != IDE_HDD) - goto abort_cmd; - snum = hdd[ide->hdd_num].spt; - snum *= hdd[ide->hdd_num].hpc; - snum *= hdd[ide->hdd_num].tracks; - ide_set_sector(ide, snum - 1); - ide->atastat = DRDY_STAT | DSC_STAT; - ide_irq_raise(ide); - return; + case WIN_PACKETCMD: /* ATAPI Packet */ + if (ide->type == IDE_ATAPI) + ide_atapi_callback(ide); + else + err = ABRT_ERR; + break; - case WIN_IDENTIFY: /* Identify Device */ - if (ide->type != IDE_HDD) { - ide_set_signature(ide); - goto abort_cmd; - } else { - ide_identify(ide); - ide->pos = 0; - ide->atastat = DRQ_STAT | DRDY_STAT | DSC_STAT; - ide_irq_raise(ide); - } - return; - - case WIN_PACKETCMD: /* ATAPI Packet */ - if (ide->type != IDE_ATAPI) - goto abort_cmd; - - ide_atapi_callback(ide); - return; - - case 0xFF: - goto abort_cmd; + default: + case 0xff: + err = ABRT_ERR; + break; } -abort_cmd: - ide->command = 0; - if (ide->type == IDE_ATAPI) { - ide->sc->status = DRDY_STAT | ERR_STAT | DSC_STAT; - ide->sc->error = ABRT_ERR; - ide->sc->pos = 0; - } else { - ide->atastat = DRDY_STAT | ERR_STAT | DSC_STAT; - ide->error = ABRT_ERR; - ide->pos = 0; - } - ide_irq_raise(ide); - return; + if (err != 0x00) { + ide->tf->atastat = DRDY_STAT | ERR_STAT | DSC_STAT; + ide->tf->error = err; -id_not_found: - ide->atastat = DRDY_STAT | ERR_STAT | DSC_STAT; - ide->error = IDNF_ERR; - ide->pos = 0; - ide_irq_raise(ide); + ide->tf->pos = 0; + + ide_irq_raise(ide); + } } - uint8_t ide_read_ali_75(void) { - ide_t *ide0, *ide1; - int ch0, ch1; - uint8_t ret = 0x00; + const ide_t *ide0; + const ide_t *ide1; + int ch0; + int ch1; + uint8_t ret = 0x00; - ch0 = ide_boards[0]->cur_dev; - ch1 = ide_boards[1]->cur_dev; + ch0 = ide_boards[0]->cur_dev; + ch1 = ide_boards[1]->cur_dev; ide0 = ide_drives[ch0]; ide1 = ide_drives[ch1]; if (ch1) - ret |= 0x08; + ret |= 0x08; if (ch0) - ret |= 0x04; + ret |= 0x04; if (ide1->irqstat) - ret |= 0x02; + ret |= 0x02; if (ide0->irqstat) - ret |= 0x01; + ret |= 0x01; return ret; } - uint8_t ide_read_ali_76(void) { - ide_t *ide0, *ide1; - int ch0, ch1; - uint8_t ret = 0x00; + const ide_t *ide0; + const ide_t *ide1; + int ch0; + int ch1; + uint8_t ret = 0x00; - ch0 = ide_boards[0]->cur_dev; - ch1 = ide_boards[1]->cur_dev; + ch0 = ide_boards[0]->cur_dev; + ch1 = ide_boards[1]->cur_dev; ide0 = ide_drives[ch0]; ide1 = ide_drives[ch1]; - if (ide1->atastat & BSY_STAT) - ret |= 0x40; - if (ide1->atastat & DRQ_STAT) - ret |= 0x20; - if (ide1->atastat & ERR_STAT) - ret |= 0x10; - if (ide0->atastat & BSY_STAT) - ret |= 0x04; - if (ide0->atastat & DRQ_STAT) - ret |= 0x02; - if (ide0->atastat & ERR_STAT) - ret |= 0x01; + if (ide1->tf->atastat & BSY_STAT) + ret |= 0x40; + if (ide1->tf->atastat & DRQ_STAT) + ret |= 0x20; + if (ide1->tf->atastat & ERR_STAT) + ret |= 0x10; + if (ide0->tf->atastat & BSY_STAT) + ret |= 0x04; + if (ide0->tf->atastat & DRQ_STAT) + ret |= 0x02; + if (ide0->tf->atastat & ERR_STAT) + ret |= 0x01; return ret; } - -static void -ide_set_handlers(uint8_t board) +void +ide_handlers(uint8_t board, int set) { - if (ide_boards[board] == NULL) - return; + if (ide_boards[board] != NULL) { + if (ide_boards[board]->base[0]) { + io_handler(set, ide_boards[board]->base[0], 8, + ide_readb, ide_readw, ide_readl, + ide_writeb, ide_writew, ide_writel, + ide_boards[board]); + } - if (ide_boards[board]->base_main) { - io_sethandler(ide_boards[board]->base_main, 8, - ide_readb, ide_readw, ide_readl, - ide_writeb, ide_writew, ide_writel, - ide_boards[board]); - } - - if (ide_boards[board]->side_main) { - io_sethandler(ide_boards[board]->side_main, 1, - ide_read_alt_status, NULL, NULL, - ide_write_devctl, NULL, NULL, - ide_boards[board]); + if (ide_boards[board]->base[1]) { + io_handler(set, ide_boards[board]->base[1], 1, + ide_read_alt_status, NULL, NULL, + ide_write_devctl, NULL, NULL, + ide_boards[board]); + } } } - -static void -ide_remove_handlers(uint8_t board) -{ - if (ide_boards[board] == NULL) - return; - - if (ide_boards[board]->base_main) { - io_removehandler(ide_boards[board]->base_main, 8, - ide_readb, ide_readw, ide_readl, - ide_writeb, ide_writew, ide_writel, - ide_boards[board]); - } - - if (ide_boards[board]->side_main) { - io_removehandler(ide_boards[board]->side_main, 1, - ide_read_alt_status, NULL, NULL, - ide_write_devctl, NULL, NULL, - ide_boards[board]); - } -} - - void -ide_pri_enable(void) +ide_set_base_addr(int board, int base, uint16_t port) { - ide_set_handlers(0); + ide_log("ide_set_base_addr(%i, %i, %04X)\n", board, base, port); + + if (ide_boards[board] != NULL) + ide_boards[board]->base[base] = port; } - -void -ide_pri_disable(void) -{ - ide_remove_handlers(0); -} - - -void -ide_sec_enable(void) -{ - ide_set_handlers(1); -} - - -void -ide_sec_disable(void) -{ - ide_remove_handlers(1); -} - - -void -ide_set_base(int board, uint16_t port) -{ - ide_log("ide_set_base(%i, %04X)\n", board, port); - - if (ide_boards[board] == NULL) - return; - - ide_boards[board]->base_main = port; -} - - -void -ide_set_side(int board, uint16_t port) -{ - ide_log("ide_set_side(%i, %04X)\n", board, port); - - if (ide_boards[board] == NULL) - return; - - ide_boards[board]->side_main = port; -} - - static void ide_clear_bus_master(int board) { - if (ide_bm[board]) { - free(ide_bm[board]); - ide_bm[board] = NULL; + ide_bm_t *bm = ide_boards[board]->bm; + + if (bm != NULL) { + free(bm); + ide_boards[board]->bm = NULL; } } - -/* This so drives can be forced to ATA-3 (no DMA) for machines that hide the on-board PCI IDE controller - (eg. Packard Bell PB640 and ASUS P/I-P54TP4XE), breaking DMA drivers unless this is done. */ +/* + This so drives can be forced to ATA-3 (no DMA) for machines that hide the + on-board PCI IDE controller (eg. Packard Bell PB640 and ASUS P/I-P54TP4XE), + breaking DMA drivers unless this is done. + */ extern void ide_board_set_force_ata3(int board, int force_ata3) { ide_log("ide_board_set_force_ata3(%i, %i)\n", board, force_ata3); - if ((ide_boards[board] == NULL)|| !ide_boards[board]->inited) - return; - - ide_boards[board]->force_ata3 = force_ata3; + if ((ide_boards[board] != NULL) && ide_boards[board]->inited) + ide_boards[board]->force_ata3 = force_ata3; } - static void ide_board_close(int board) { ide_t *dev; - int c, d; + int c; ide_log("ide_board_close(%i)\n", board); - if ((ide_boards[board] == NULL)|| !ide_boards[board]->inited) - return; + if ((ide_boards[board] == NULL) || !ide_boards[board]->inited) + return; ide_log("IDE: Closing board %i...\n", board); @@ -2698,119 +2638,127 @@ ide_board_close(int board) ide_clear_bus_master(board); /* Close hard disk image files (if previously open) */ - for (d = 0; d < 2; d++) { - c = (board << 1) + d; + for (uint8_t d = 0; d < 2; d++) { + c = (board << 1) + d; - ide_boards[board]->ide[d] = NULL; + ide_boards[board]->ide[d] = NULL; - dev = ide_drives[c]; + dev = ide_drives[c]; - if (dev == NULL) - continue; + if (dev != NULL) { + if ((dev->type == IDE_HDD) && (dev->hdd_num != -1)) + hdd_image_close(dev->hdd_num); - if ((dev->type == IDE_HDD) && (dev->hdd_num != -1)) - hdd_image_close(dev->hdd_num); + if (dev->type == IDE_ATAPI) + dev->tf->atastat = DRDY_STAT | DSC_STAT; + else if (!(dev->type & IDE_SHADOW) && (dev->tf != NULL)) { + free(dev->tf); + dev->tf = NULL; + } - if (dev->type == IDE_ATAPI) - dev->sc->status = DRDY_STAT | DSC_STAT; + if (dev->buffer) { + free(dev->buffer); + dev->buffer = NULL; + } - if (dev->buffer) { - free(dev->buffer); - dev->buffer = NULL; - } + if (dev->sector_buffer) { + free(dev->sector_buffer); + dev->buffer = NULL; + } - if (dev->sector_buffer) { - free(dev->sector_buffer); - dev->buffer = NULL; - } - - if (dev) { - free(dev); - ide_drives[c] = NULL; - } + if (dev) { + free(dev); + ide_drives[c] = NULL; + } + } } free(ide_boards[board]); ide_boards[board] = NULL; } - static void ide_board_setup(int board) { ide_t *dev; - int c, d; - int ch, is_ide, valid_ch; - int min_ch, max_ch; + int c; + int d; + int ch; + int is_ide; + int valid_ch; + int min_ch; + int max_ch; min_ch = (board << 1); max_ch = min_ch + 1; ide_log("IDE: board %i: loading disks...\n", board); for (d = 0; d < 2; d++) { - c = (board << 1) + d; - ide_zero(c); + c = (board << 1) + d; + ide_zero(c); } c = 0; for (d = 0; d < HDD_NUM; d++) { - is_ide = (hdd[d].bus == HDD_BUS_IDE); - ch = hdd[d].ide_channel; + is_ide = (hdd[d].bus == HDD_BUS_IDE); + ch = hdd[d].ide_channel; - if (board == 4) { - valid_ch = ((ch >= 0) && (ch <= 1)); - ch |= 8; - } else - valid_ch = ((ch >= min_ch) && (ch <= max_ch)); + if (board == 4) { + valid_ch = ((ch >= 0) && (ch <= 1)); + ch |= 8; + } else + valid_ch = ((ch >= min_ch) && (ch <= max_ch)); - if (is_ide && valid_ch) { - ide_log("Found IDE hard disk on channel %i\n", ch); - loadhd(ide_drives[ch], d, hdd[d].fn); - if (ide_drives[ch]->sector_buffer == NULL) - ide_drives[ch]->sector_buffer = (uint8_t *) malloc(256*512); - memset(ide_drives[ch]->sector_buffer, 0, 256*512); - if (++c >= 2) break; - } + if (is_ide && valid_ch) { + ide_log("Found IDE hard disk on channel %i\n", ch); + loadhd(ide_drives[ch], d, hdd[d].fn); + if (ide_drives[ch]->sector_buffer == NULL) + ide_drives[ch]->sector_buffer = (uint8_t *) calloc(1, 256 * 512); + if (++c >= 2) + break; + } } ide_log("IDE: board %i: done, loaded %d disks.\n", board, c); for (d = 0; d < 2; d++) { - c = (board << 1) + d; - dev = ide_drives[c]; + c = (board << 1) + d; + dev = ide_drives[c]; - if (dev->type == IDE_NONE) - continue; + if (dev->type == IDE_NONE) + continue; - ide_allocate_buffer(dev); + ide_allocate_buffer(dev); - ide_set_signature(dev); + ide_set_signature(dev); - dev->mdma_mode = (1 << ide_get_max(dev, TYPE_PIO)); - dev->error = 1; - if (dev->type != IDE_HDD) - dev->cfg_spt = dev->cfg_hpc = 0; + dev->mdma_mode = (1 << ide_get_max(dev, TYPE_PIO)); + dev->tf->error = 1; + if (dev->type != IDE_HDD) + dev->cfg_spt = dev->cfg_hpc = 0; + if (dev->type == IDE_HDD) + dev->blocksize = hdd[dev->hdd_num].max_multiple_block; } } - static void ide_board_init(int board, int irq, int base_main, int side_main, int type) { ide_log("ide_board_init(%i, %i, %04X, %04X, %i)\n", board, irq, base_main, side_main, type); if ((ide_boards[board] != NULL) && ide_boards[board]->inited) - return; + return; ide_log("IDE: Initializing board %i...\n", board); - ide_boards[board] = (ide_board_t *) malloc(sizeof(ide_board_t)); - memset(ide_boards[board], 0, sizeof(ide_board_t)); - ide_boards[board]->irq = irq; + if (ide_boards[board] == NULL) + ide_boards[board] = (ide_board_t *) calloc(1, sizeof(ide_board_t)); + + ide_boards[board]->irq = irq; ide_boards[board]->cur_dev = board << 1; if (type & 6) - ide_boards[board]->bit32 = 1; - ide_boards[board]->base_main = base_main; - ide_boards[board]->side_main = side_main; + ide_boards[board]->bit32 = 1; + ide_boards[board]->base[0] = base_main; + ide_boards[board]->base[1] = side_main; ide_set_handlers(board); timer_add(&ide_boards[board]->timer, ide_board_callback, ide_boards[board], 0); @@ -2820,101 +2768,98 @@ ide_board_init(int board, int irq, int base_main, int side_main, int type) ide_boards[board]->inited = 1; } - void ide_pnp_config_changed(uint8_t ld, isapnp_device_config_t *config, void *priv) { - if (ld) - return; - intptr_t board = (intptr_t) priv; - if (ide_boards[board]->base_main || ide_boards[board]->side_main) { - ide_remove_handlers(board); - ide_boards[board]->base_main = ide_boards[board]->side_main = 0; + if (ld) + return; + + if (ide_boards[board]->base[0] || ide_boards[board]->base[1]) { + ide_remove_handlers(board); + ide_boards[board]->base[0] = ide_boards[board]->base[1] = 0; } ide_boards[board]->irq = -1; if (config->activate) { - ide_boards[board]->base_main = config->io[0].base; - ide_boards[board]->side_main = config->io[1].base; + ide_boards[board]->base[0] = (config->io[0].base != ISAPNP_IO_DISABLED) ? + config->io[0].base : 0x0000; + ide_boards[board]->base[1] = (config->io[1].base != ISAPNP_IO_DISABLED) ? + config->io[1].base : 0x0000; - if ((ide_boards[board]->base_main != ISAPNP_IO_DISABLED) && (ide_boards[board]->side_main != ISAPNP_IO_DISABLED)) - ide_set_handlers(board); + if (ide_boards[board]->base[0] && ide_boards[board]->base[1]) + ide_set_handlers(board); - if (config->irq[0].irq != ISAPNP_IRQ_DISABLED) - ide_boards[board]->irq = config->irq[0].irq; + if (config->irq[0].irq != ISAPNP_IRQ_DISABLED) + ide_boards[board]->irq = config->irq[0].irq; } } - static void * ide_ter_init(const device_t *info) { /* Don't claim this channel again if it was already claimed. */ if (ide_boards[2]) - return(NULL); + return (NULL); int irq; if (info->local) - irq = -2; + irq = -2; else - irq = device_get_config_int("irq"); + irq = device_get_config_int("irq"); if (irq < 0) { - ide_board_init(2, -1, 0, 0, 0); - if (irq == -1) - isapnp_add_card(ide_ter_pnp_rom, sizeof(ide_ter_pnp_rom), ide_pnp_config_changed, NULL, NULL, NULL, (void *) 2); + ide_board_init(2, -1, 0, 0, 0); + if (irq == -1) + isapnp_add_card(ide_ter_pnp_rom, sizeof(ide_ter_pnp_rom), + ide_pnp_config_changed, NULL, NULL, NULL, (void *) 2); } else { - ide_board_init(2, irq, 0x168, 0x36e, 0); + ide_board_init(2, irq, HDC_TERTIARY_BASE, HDC_TERTIARY_SIDE, 0); } - return(ide_boards[2]); + return (ide_boards[2]); } - /* Close a standalone IDE unit. */ static void -ide_ter_close(void *priv) +ide_ter_close(UNUSED(void *priv)) { ide_board_close(2); } - static void * ide_qua_init(const device_t *info) { /* Don't claim this channel again if it was already claimed. */ if (ide_boards[3]) - return(NULL); + return (NULL); int irq; if (info->local) - irq = -2; + irq = -2; else - irq = device_get_config_int("irq"); + irq = device_get_config_int("irq"); if (irq < 0) { - ide_board_init(3, -1, 0, 0, 0); - if (irq == -1) - isapnp_add_card(ide_qua_pnp_rom, sizeof(ide_qua_pnp_rom), ide_pnp_config_changed, NULL, NULL, NULL, (void *) 3); - } else { - ide_board_init(3, irq, 0x1e8, 0x3ee, 0); - } + ide_board_init(3, -1, 0, 0, 0); + if (irq == -1) + isapnp_add_card(ide_qua_pnp_rom, sizeof(ide_qua_pnp_rom), + ide_pnp_config_changed, NULL, NULL, NULL, (void *) 3); + } else + ide_board_init(3, irq, HDC_QUATERNARY_BASE, HDC_QUATERNARY_SIDE, 0); - return(ide_boards[3]); + return (ide_boards[3]); } - /* Close a standalone IDE unit. */ static void -ide_qua_close(void *priv) +ide_qua_close(UNUSED(void *priv)) { ide_board_close(3); } - void * ide_xtide_init(void) { @@ -2923,82 +2868,87 @@ ide_xtide_init(void) return ide_boards[0]; } - void ide_xtide_close(void) { ide_board_close(0); } - void ide_set_bus_master(int board, - int (*dma)(int channel, uint8_t *data, int transfer_length, int out, void *priv), - void (*set_irq)(int channel, void *priv), void *priv) + int (*dma)(uint8_t *data, int transfer_length, int out, void *priv), + void (*set_irq)(uint8_t status, void *priv), void *priv) { - if (ide_bm[board] == NULL) - ide_bm[board] = (ide_bm_t *) malloc(sizeof(ide_bm_t)); + ide_bm_t *bm; - ide_bm[board]->dma = dma; - ide_bm[board]->set_irq = set_irq; - ide_bm[board]->priv = priv; + if (ide_boards[board]->bm == NULL) { + bm = (ide_bm_t *) calloc(1, sizeof(ide_bm_t)); + ide_boards[board]->bm = bm; + } else + bm = ide_boards[board]->bm; + + bm->dma = dma; + bm->set_irq = set_irq; + bm->priv = priv; } - static void * ide_init(const device_t *info) { ide_log("Initializing IDE...\n"); - switch(info->local) { - case 0: /* ISA, single-channel */ - case 1: /* ISA, dual-channel */ - case 2: /* VLB, single-channel */ - case 3: /* VLB, dual-channel */ - case 4: /* PCI, single-channel */ - case 5: /* PCI, dual-channel */ - ide_board_init(0, 14, 0x1f0, 0x3f6, info->local); + switch (info->local) { + case 0 ... 5: + ide_board_init(0, 14, 0x1f0, 0x3f6, info->local); - if (info->local & 1) - ide_board_init(1, 15, 0x170, 0x376, info->local); - break; + if (info->local & 1) + ide_board_init(1, 15, 0x170, 0x376, info->local); + break; + + default: + break; } - return(ide_drives); + return (void *) (intptr_t) -1; } - static void ide_drive_reset(int d) { ide_log("Resetting IDE drive %i...\n", d); - ide_drives[d]->channel = d; - ide_drives[d]->atastat = DRDY_STAT | DSC_STAT; - ide_drives[d]->service = 0; - ide_drives[d]->board = d >> 1; - ide_drives[d]->selected = !(d & 1); + if ((d & 1) && (ide_drives[d]->type == IDE_NONE) && (ide_drives[d ^ 1]->type != IDE_NONE)) { + ide_drives[d]->type = ide_drives[d ^ 1]->type | IDE_SHADOW; + free(ide_drives[d]->tf); + ide_drives[d]->tf = ide_drives[d ^ 1]->tf; + } else + ide_drives[d]->tf->atastat = DRDY_STAT | DSC_STAT; + + ide_drives[d]->channel = d; + ide_drives[d]->service = 0; + ide_drives[d]->board = d >> 1; + ide_drives[d]->selected = !(d & 1); timer_stop(&ide_drives[d]->timer); if (ide_boards[d >> 1]) { - ide_boards[d >> 1]->cur_dev = d & ~1; - timer_stop(&ide_boards[d >> 1]->timer); + ide_boards[d >> 1]->cur_dev = d & ~1; + timer_stop(&ide_boards[d >> 1]->timer); } ide_set_signature(ide_drives[d]); if (ide_drives[d]->sector_buffer) - memset(ide_drives[d]->sector_buffer, 0, 256*512); + memset(ide_drives[d]->sector_buffer, 0, 256 * 512); if (ide_drives[d]->buffer) - memset(ide_drives[d]->buffer, 0, 65536 * sizeof(uint16_t)); + memset(ide_drives[d]->buffer, 0, 65536 * sizeof(uint16_t)); } - static void ide_board_reset(int board) { - int d, min, max; + int min; + int max; ide_log("Resetting IDE board %i...\n", board); @@ -3007,223 +2957,226 @@ ide_board_reset(int board) min = (board << 1); max = min + 2; - for (d = min; d < max; d++) - ide_drive_reset(d); + for (int d = min; d < max; d++) + ide_drive_reset(d); } - /* Reset a standalone IDE unit. */ static void -ide_reset(void *p) +ide_reset(UNUSED(void *priv)) { ide_log("Resetting IDE...\n"); - if (ide_boards[0] != NULL) - ide_board_reset(0); - - if (ide_boards[1] != NULL) - ide_board_reset(1); + for (uint8_t i = 0; i < 2; i++) { + if (ide_boards[i] != NULL) + ide_board_reset(i); + } } - /* Close a standalone IDE unit. */ static void -ide_close(void *priv) +ide_close(UNUSED(void *priv)) { ide_log("Closing IDE...\n"); - if (ide_boards[0] != NULL) { - ide_board_close(0); - ide_boards[0] = NULL; - } - - if (ide_boards[1] != NULL) { - ide_board_close(1); - ide_boards[1] = NULL; + for (uint8_t i = 0; i < 2; i++) { + if (ide_boards[i] != NULL) { + ide_board_close(i); + ide_boards[i] = NULL; + } } } - const device_t ide_isa_device = { - "ISA PC/AT IDE Controller", - "ide_isa", - DEVICE_ISA | DEVICE_AT, - 0, - ide_init, ide_close, ide_reset, - { NULL }, NULL, NULL, NULL + .name = "ISA PC/AT IDE Controller", + .internal_name = "ide_isa", + .flags = DEVICE_ISA | DEVICE_AT, + .local = 0, + .init = ide_init, + .close = ide_close, + .reset = ide_reset, + { .available = NULL }, + .speed_changed = NULL, + .force_redraw = NULL, + .config = NULL }; const device_t ide_isa_2ch_device = { - "ISA PC/AT IDE Controller (Dual-Channel)", - "ide_isa_2ch", - DEVICE_ISA | DEVICE_AT, - 1, - ide_init, ide_close, ide_reset, - { NULL }, NULL, NULL, NULL + .name = "ISA PC/AT IDE Controller (Dual-Channel)", + .internal_name = "ide_isa_2ch", + .flags = DEVICE_ISA | DEVICE_AT, + .local = 1, + .init = ide_init, + .close = ide_close, + .reset = ide_reset, + { .available = NULL }, + .speed_changed = NULL, + .force_redraw = NULL, + .config = NULL }; const device_t ide_vlb_device = { - "VLB IDE Controller", - "ide_vlb", - DEVICE_VLB | DEVICE_AT, - 2, - ide_init, ide_close, ide_reset, - { NULL }, NULL, NULL, NULL + .name = "VLB IDE Controller", + .internal_name = "ide_vlb", + .flags = DEVICE_VLB | DEVICE_AT, + .local = 2, + .init = ide_init, + .close = ide_close, + .reset = ide_reset, + { .available = NULL }, + .speed_changed = NULL, + .force_redraw = NULL, + .config = NULL }; const device_t ide_vlb_2ch_device = { - "VLB IDE Controller (Dual-Channel)", - "ide_vlb_2ch", - DEVICE_VLB | DEVICE_AT, - 3, - ide_init, ide_close, ide_reset, - { NULL }, NULL, NULL, NULL + .name = "VLB IDE Controller (Dual-Channel)", + .internal_name = "ide_vlb_2ch", + .flags = DEVICE_VLB | DEVICE_AT, + .local = 3, + .init = ide_init, + .close = ide_close, + .reset = ide_reset, + { .available = NULL }, + .speed_changed = NULL, + .force_redraw = NULL, + .config = NULL }; const device_t ide_pci_device = { - "PCI IDE Controller", - "ide_pci", - DEVICE_PCI | DEVICE_AT, - 4, - ide_init, ide_close, ide_reset, - { NULL }, NULL, NULL, NULL + .name = "PCI IDE Controller", + .internal_name = "ide_pci", + .flags = DEVICE_PCI | DEVICE_AT, + .local = 4, + .init = ide_init, + .close = ide_close, + .reset = ide_reset, + { .available = NULL }, + .speed_changed = NULL, + .force_redraw = NULL, + .config = NULL }; const device_t ide_pci_2ch_device = { - "PCI IDE Controller (Dual-Channel)", - "ide_pci_2ch", - DEVICE_PCI | DEVICE_AT, - 5, - ide_init, ide_close, ide_reset, - { NULL }, NULL, NULL, NULL + .name = "PCI IDE Controller (Dual-Channel)", + .internal_name = "ide_pci_2ch", + .flags = DEVICE_PCI | DEVICE_AT, + .local = 5, + .init = ide_init, + .close = ide_close, + .reset = ide_reset, + { .available = NULL }, + .speed_changed = NULL, + .force_redraw = NULL, + .config = NULL }; -static const device_config_t ide_ter_config[] = -{ - { - "irq", "IRQ", CONFIG_SELECTION, "", 10, "", { 0 }, - { - { - "Plug and Play", -1 - }, - { - "IRQ 2", 2 - }, - { - "IRQ 3", 3 - }, - { - "IRQ 4", 4 - }, - { - "IRQ 5", 5 - }, - { - "IRQ 7", 7 - }, - { - "IRQ 9", 9 - }, - { - "IRQ 10", 10 - }, - { - "IRQ 11", 11 - }, - { - "IRQ 12", 12 - }, - { - "" - } - } - }, - { - "", "", -1 +// clang-format off +static const device_config_t ide_ter_config[] = { + { + .name = "irq", + .description = "IRQ", + .type = CONFIG_SELECTION, + .default_string = "", + .default_int = HDC_TERTIARY_IRQ, + .file_filter = "", + .spinner = { 0 }, + .selection = { + { .description = "Plug and Play", .value = -1 }, + { .description = "IRQ 2", .value = 2 }, + { .description = "IRQ 3", .value = 3 }, + { .description = "IRQ 4", .value = 4 }, + { .description = "IRQ 5", .value = 5 }, + { .description = "IRQ 7", .value = 7 }, + { .description = "IRQ 9", .value = 9 }, + { .description = "IRQ 10", .value = 10 }, + { .description = "IRQ 11", .value = 11 }, + { .description = "IRQ 12", .value = 12 }, + { .description = "" } } + }, + { .name = "", .description = "", .type = CONFIG_END } }; -static const device_config_t ide_qua_config[] = -{ - { - "irq", "IRQ", CONFIG_SELECTION, "", 11, "", { 0 }, - { - { - "Plug and Play", -1 - }, - { - "IRQ 2", 2 - }, - { - "IRQ 3", 3 - }, - { - "IRQ 4", 4 - }, - { - "IRQ 5", 5 - }, - { - "IRQ 7", 7 - }, - { - "IRQ 9", 9 - }, - { - "IRQ 10", 10 - }, - { - "IRQ 11", 11 - }, - { - "IRQ 12", 12 - }, - { - "" - } - } - }, - { - "", "", -1 +static const device_config_t ide_qua_config[] = { + { + .name = "irq", + .description = "IRQ", + .type = CONFIG_SELECTION, + .default_string = "", + .default_int = HDC_QUATERNARY_IRQ, + .file_filter = "", + .spinner = { 0 }, + .selection = { + { .description = "Plug and Play", .value = -1 }, + { .description = "IRQ 2", .value = 2 }, + { .description = "IRQ 3", .value = 3 }, + { .description = "IRQ 4", .value = 4 }, + { .description = "IRQ 5", .value = 5 }, + { .description = "IRQ 7", .value = 7 }, + { .description = "IRQ 9", .value = 9 }, + { .description = "IRQ 10", .value = 10 }, + { .description = "IRQ 11", .value = 11 }, + { .description = "IRQ 12", .value = 12 }, + { .description = "" } } + }, + { .name = "", .description = "", .type = CONFIG_END } }; +// clang-format on const device_t ide_ter_device = { - "Tertiary IDE Controller", - "ide_ter", - DEVICE_AT, - 0, - ide_ter_init, ide_ter_close, NULL, - { NULL }, NULL, NULL, - ide_ter_config + .name = "Tertiary IDE Controller", + .internal_name = "ide_ter", + .flags = DEVICE_AT, + .local = 0, + .init = ide_ter_init, + .close = ide_ter_close, + .reset = NULL, + { .available = NULL }, + .speed_changed = NULL, + .force_redraw = NULL, + .config = ide_ter_config }; const device_t ide_ter_pnp_device = { - "Tertiary IDE Controller (Plug and Play only)", - "ide_ter_pnp", - DEVICE_AT, - 1, - ide_ter_init, ide_ter_close, NULL, - { NULL }, NULL, NULL, - NULL + .name = "Tertiary IDE Controller (Plug and Play only)", + .internal_name = "ide_ter_pnp", + .flags = DEVICE_AT, + .local = 1, + .init = ide_ter_init, + .close = ide_ter_close, + .reset = NULL, + { .available = NULL }, + .speed_changed = NULL, + .force_redraw = NULL, + .config = NULL }; const device_t ide_qua_device = { - "Quaternary IDE Controller", - "ide_qua", - DEVICE_AT, - 0, - ide_qua_init, ide_qua_close, NULL, - { NULL }, NULL, NULL, - ide_qua_config + .name = "Quaternary IDE Controller", + .internal_name = "ide_qua", + .flags = DEVICE_AT, + .local = 0, + .init = ide_qua_init, + .close = ide_qua_close, + .reset = NULL, + { .available = NULL }, + .speed_changed = NULL, + .force_redraw = NULL, + .config = ide_qua_config }; const device_t ide_qua_pnp_device = { - "Quaternary IDE Controller (Plug and Play only)", - "ide_qua_pnp", - DEVICE_AT, - 1, - ide_qua_init, ide_qua_close, NULL, - { NULL }, NULL, NULL, - ide_qua_config + .name = "Quaternary IDE Controller (Plug and Play only)", + .internal_name = "ide_qua_pnp", + .flags = DEVICE_AT, + .local = 1, + .init = ide_qua_init, + .close = ide_qua_close, + .reset = NULL, + { .available = NULL }, + .speed_changed = NULL, + .force_redraw = NULL, + .config = ide_qua_config }; diff --git a/src/disk/hdc_ide_cmd640.c b/src/disk/hdc_ide_cmd640.c index a4e1c8ca6..3e77730a2 100644 --- a/src/disk/hdc_ide_cmd640.c +++ b/src/disk/hdc_ide_cmd640.c @@ -1,16 +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. + * 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. + * This file is part of the 86Box distribution. * - * Implementation of the CMD PCI-0640B controller. + * Implementation of the CMD PCI-0640B controller. * - * Authors: Miran Grca, + * Authors: Miran Grca, * - * Copyright 2020 Miran Grca. + * Copyright 2020 Miran Grca. */ #include #include @@ -37,163 +37,191 @@ #include <86box/zip.h> #include <86box/mo.h> - -typedef struct -{ - uint8_t vlb_idx, id, - in_cfg, single_channel, - pci, regs[256]; - uint32_t local; - int slot, irq_mode[2], - irq_pin, irq_line; +typedef struct cmd640_t { + uint8_t vlb_idx; + uint8_t id; + uint8_t in_cfg; + uint8_t channels; + uint8_t pci; + uint8_t irq_state; + uint8_t pci_slot; + uint8_t pad0; + uint8_t regs[256]; + uint32_t local; + int irq_mode[2]; + int irq_pin; + int irq_line; } cmd640_t; - -static int next_id = 0; - +static int next_id = 0; #ifdef ENABLE_CMD640_LOG int cmd640_do_log = ENABLE_CMD640_LOG; + static void cmd640_log(const char *fmt, ...) { va_list ap; - if (cmd640_do_log) - { - va_start(ap, fmt); - pclog_ex(fmt, ap); - va_end(ap); + if (cmd640_do_log) { + va_start(ap, fmt); + pclog_ex(fmt, ap); + va_end(ap); } } #else -#define cmd640_log(fmt, ...) +# define cmd640_log(fmt, ...) #endif - void -cmd640_set_irq(int channel, void *priv) +cmd640_set_irq_0(uint8_t status, void *priv) { cmd640_t *dev = (cmd640_t *) priv; - int irq = !!(channel & 0x40); + int irq = !!(status & 0x04); - if (channel & 0x01) { - if (!(dev->regs[0x57] & 0x10) || (channel & 0x40)) { - dev->regs[0x57] &= ~0x10; - dev->regs[0x57] |= (channel >> 2); - } - } else { - if (!(dev->regs[0x50] & 0x04) || (channel & 0x40)) { - dev->regs[0x50] &= ~0x04; - dev->regs[0x50] |= (channel >> 4); - } - } + if (!(dev->regs[0x50] & 0x04) || (status & 0x04)) + dev->regs[0x50] = (dev->regs[0x50] & ~0x04) | status; + + if (!(dev->channels & 1)) + return; - channel &= 0x01; if (irq) { - if (dev->irq_mode[channel] == 1) - pci_set_irq(dev->slot, dev->irq_pin); - else - picint(1 << (14 + channel)); + if (dev->irq_mode[0] == 1) + pci_set_irq(dev->pci_slot, dev->irq_pin, &dev->irq_state); + else + picint(1 << 14); } else { - if (dev->irq_mode[channel] == 1) - pci_clear_irq(dev->slot, dev->irq_pin); - else - picintc(1 << (14 + channel)); + if (dev->irq_mode[0] == 1) + pci_clear_irq(dev->pci_slot, dev->irq_pin, &dev->irq_state); + else + picintc(1 << 14); } } +void +cmd640_set_irq_1(uint8_t status, void *priv) +{ + cmd640_t *dev = (cmd640_t *) priv; + int irq = !!(status & 0x04); + + if (!(dev->regs[0x57] & 0x10) || (status & 0x04)) + dev->regs[0x57] = (dev->regs[0x57] & ~0x10) | (status << 2); + + if (!(dev->channels & 2)) + return; + + if (irq) { + if (dev->irq_mode[1] == 1) + pci_set_irq(dev->pci_slot, dev->irq_pin, &dev->irq_state); + else + picint(1 << 15); + } else { + if (dev->irq_mode[1] == 1) + pci_clear_irq(dev->pci_slot, dev->irq_pin, &dev->irq_state); + else + picintc(1 << 15); + } +} static void cmd640_ide_handlers(cmd640_t *dev) { - uint16_t main, side; + uint16_t main; + uint16_t side; - ide_pri_disable(); + if (dev->channels & 0x01) { + ide_pri_disable(); - if ((dev->regs[0x09] & 0x01) && (dev->regs[0x50] & 0x40)) { - main = (dev->regs[0x11] << 8) | (dev->regs[0x10] & 0xf8); - side = ((dev->regs[0x15] << 8) | (dev->regs[0x14] & 0xfc)) + 2; - } else { - main = 0x1f0; - side = 0x3f6; + if ((dev->regs[0x09] & 0x01) && (dev->regs[0x50] & 0x40)) { + main = (dev->regs[0x11] << 8) | (dev->regs[0x10] & 0xf8); + side = ((dev->regs[0x15] << 8) | (dev->regs[0x14] & 0xfc)) + 2; + } else { + main = 0x1f0; + side = 0x3f6; + } + + ide_set_base(0, main); + ide_set_side(0, side); + + if (dev->regs[0x04] & 0x01) + ide_pri_enable(); } - ide_set_base(0, main); - ide_set_side(0, side); + if (dev->channels & 0x02) { + ide_sec_disable(); - if (dev->regs[0x04] & 0x01) - ide_pri_enable(); + if ((dev->regs[0x09] & 0x04) && (dev->regs[0x50] & 0x40)) { + main = (dev->regs[0x19] << 8) | (dev->regs[0x18] & 0xf8); + side = ((dev->regs[0x1d] << 8) | (dev->regs[0x1c] & 0xfc)) + 2; + } else { + main = 0x170; + side = 0x376; + } - if (dev->single_channel) - return; + ide_set_base(1, main); + ide_set_side(1, side); - ide_sec_disable(); - - if ((dev->regs[0x09] & 0x04) && (dev->regs[0x50] & 0x40)) { - main = (dev->regs[0x19] << 8) | (dev->regs[0x18] & 0xf8); - side = ((dev->regs[0x1d] << 8) | (dev->regs[0x1c] & 0xfc)) + 2; - } else { - main = 0x170; - side = 0x376; + if ((dev->regs[0x04] & 0x01) && (dev->regs[0x51] & 0x08)) + ide_sec_enable(); } - - ide_set_base(1, main); - ide_set_side(1, side); - - if ((dev->regs[0x04] & 0x01) && (dev->regs[0x51] & 0x08)) - ide_sec_enable(); } - static void cmd640_common_write(int addr, uint8_t val, cmd640_t *dev) { switch (addr) { - case 0x51: - dev->regs[addr] = val; - cmd640_ide_handlers(dev); - break; - case 0x52: case 0x54: case 0x56: case 0x58: - case 0x59: - dev->regs[addr] = val; - break; - case 0x53: case 0x55: - dev->regs[addr] = val & 0xc0; - break; - case 0x57: - dev->regs[addr] = val & 0xdc; - break; - case 0x5b: /* Undocumented register that Linux attempts to use! */ - dev->regs[addr] = val; - break; + case 0x51: + dev->regs[addr] = val; + cmd640_ide_handlers(dev); + break; + case 0x52: + case 0x54: + case 0x56: + case 0x58: + case 0x59: + dev->regs[addr] = val; + break; + case 0x53: + case 0x55: + dev->regs[addr] = val & 0xc0; + break; + case 0x57: + dev->regs[addr] = val & 0xdc; + break; + case 0x5b: /* Undocumented register that Linux attempts to use! */ + dev->regs[addr] = val; + break; + + default: + break; } } - static void cmd640_vlb_write(uint16_t addr, uint8_t val, void *priv) { cmd640_t *dev = (cmd640_t *) priv; addr &= 0x00ff; - + switch (addr) { - case 0x0078: - if (dev->in_cfg) - dev->vlb_idx = val; - else if ((dev->regs[0x50] & 0x80) && (val == dev->id)) - dev->in_cfg = 1; - break; - case 0x007c: - cmd640_common_write(dev->vlb_idx, val, dev); - if (dev->regs[0x50] & 0x80) - dev->in_cfg = 0; - break; + case 0x0078: + if (dev->in_cfg) + dev->vlb_idx = val; + else if ((dev->regs[0x50] & 0x80) && (val == dev->id)) + dev->in_cfg = 1; + break; + case 0x007c: + cmd640_common_write(dev->vlb_idx, val, dev); + if (dev->regs[0x50] & 0x80) + dev->in_cfg = 0; + break; + + default: + break; } } - static void cmd640_vlb_writew(uint16_t addr, uint16_t val, void *priv) { @@ -201,7 +229,6 @@ cmd640_vlb_writew(uint16_t addr, uint16_t val, void *priv) cmd640_vlb_write(addr + 1, val >> 8, priv); } - static void cmd640_vlb_writel(uint16_t addr, uint32_t val, void *priv) { @@ -209,35 +236,36 @@ cmd640_vlb_writel(uint16_t addr, uint32_t val, void *priv) cmd640_vlb_writew(addr + 2, val >> 16, priv); } - static uint8_t cmd640_vlb_read(uint16_t addr, void *priv) { - uint8_t ret = 0xff; + uint8_t ret = 0xff; cmd640_t *dev = (cmd640_t *) priv; addr &= 0x00ff; switch (addr) { - case 0x0078: - if (dev->in_cfg) - ret = dev->vlb_idx; - break; - case 0x007c: - ret = dev->regs[dev->vlb_idx]; - if (dev->vlb_idx == 0x50) - dev->regs[0x50] &= ~0x04; - else if (dev->vlb_idx == 0x57) - dev->regs[0x57] &= ~0x10; - if (dev->regs[0x50] & 0x80) - dev->in_cfg = 0; - break; + case 0x0078: + if (dev->in_cfg) + ret = dev->vlb_idx; + break; + case 0x007c: + ret = dev->regs[dev->vlb_idx]; + if (dev->vlb_idx == 0x50) + dev->regs[0x50] &= ~0x04; + else if (dev->vlb_idx == 0x57) + dev->regs[0x57] &= ~0x10; + if (dev->regs[0x50] & 0x80) + dev->in_cfg = 0; + break; + + default: + break; } return ret; } - static uint16_t cmd640_vlb_readw(uint16_t addr, void *priv) { @@ -249,7 +277,6 @@ cmd640_vlb_readw(uint16_t addr, void *priv) return ret; } - static uint32_t cmd640_vlb_readl(uint16_t addr, void *priv) { @@ -261,7 +288,6 @@ cmd640_vlb_readl(uint16_t addr, void *priv) return ret; } - static void cmd640_pci_write(int func, int addr, uint8_t val, void *priv) { @@ -269,89 +295,89 @@ cmd640_pci_write(int func, int addr, uint8_t val, void *priv) cmd640_log("cmd640_pci_write(%i, %02X, %02X)\n", func, addr, val); - if (func == 0x00) switch (addr) { - case 0x04: - dev->regs[addr] = (val & 0x41); - cmd640_ide_handlers(dev); - break; - case 0x07: - dev->regs[addr] &= ~(val & 0x80); - break; - case 0x09: - if ((dev->regs[addr] & 0x0a) == 0x0a) { - dev->regs[addr] = (dev->regs[addr] & 0x0a) | (val & 0x05); - dev->irq_mode[0] = !!(val & 0x01); - dev->irq_mode[1] = !!(val & 0x04); - cmd640_ide_handlers(dev); - } - break; - case 0x10: - if (dev->regs[0x50] & 0x40) { - dev->regs[0x10] = (val & 0xf8) | 1; - cmd640_ide_handlers(dev); - } - break; - case 0x11: - if (dev->regs[0x50] & 0x40) { - dev->regs[0x11] = val; - cmd640_ide_handlers(dev); - } - break; - case 0x14: - if (dev->regs[0x50] & 0x40) { - dev->regs[0x14] = (val & 0xfc) | 1; - cmd640_ide_handlers(dev); - } - break; - case 0x15: - if (dev->regs[0x50] & 0x40) { - dev->regs[0x15] = val; - cmd640_ide_handlers(dev); - } - break; - case 0x18: - if (dev->regs[0x50] & 0x40) { - dev->regs[0x18] = (val & 0xf8) | 1; - cmd640_ide_handlers(dev); - } - break; - case 0x19: - if (dev->regs[0x50] & 0x40) { - dev->regs[0x19] = val; - cmd640_ide_handlers(dev); - } - break; - case 0x1c: - if (dev->regs[0x50] & 0x40) { - dev->regs[0x1c] = (val & 0xfc) | 1; - cmd640_ide_handlers(dev); - } - break; - case 0x1d: - if (dev->regs[0x50] & 0x40) { - dev->regs[0x1d] = val; - cmd640_ide_handlers(dev); - } - break; - default: - cmd640_common_write(addr, val, dev); - break; - } + if (func == 0x00) + switch (addr) { + case 0x04: + dev->regs[addr] = (val & 0x41); + cmd640_ide_handlers(dev); + break; + case 0x07: + dev->regs[addr] &= ~(val & 0x80); + break; + case 0x09: + if ((dev->regs[addr] & 0x0a) == 0x0a) { + dev->regs[addr] = (dev->regs[addr] & 0x0a) | (val & 0x05); + dev->irq_mode[0] = !!(val & 0x01); + dev->irq_mode[1] = !!(val & 0x04); + cmd640_ide_handlers(dev); + } + break; + case 0x10: + if (dev->regs[0x50] & 0x40) { + dev->regs[0x10] = (val & 0xf8) | 1; + cmd640_ide_handlers(dev); + } + break; + case 0x11: + if (dev->regs[0x50] & 0x40) { + dev->regs[0x11] = val; + cmd640_ide_handlers(dev); + } + break; + case 0x14: + if (dev->regs[0x50] & 0x40) { + dev->regs[0x14] = (val & 0xfc) | 1; + cmd640_ide_handlers(dev); + } + break; + case 0x15: + if (dev->regs[0x50] & 0x40) { + dev->regs[0x15] = val; + cmd640_ide_handlers(dev); + } + break; + case 0x18: + if (dev->regs[0x50] & 0x40) { + dev->regs[0x18] = (val & 0xf8) | 1; + cmd640_ide_handlers(dev); + } + break; + case 0x19: + if (dev->regs[0x50] & 0x40) { + dev->regs[0x19] = val; + cmd640_ide_handlers(dev); + } + break; + case 0x1c: + if (dev->regs[0x50] & 0x40) { + dev->regs[0x1c] = (val & 0xfc) | 1; + cmd640_ide_handlers(dev); + } + break; + case 0x1d: + if (dev->regs[0x50] & 0x40) { + dev->regs[0x1d] = val; + cmd640_ide_handlers(dev); + } + break; + default: + cmd640_common_write(addr, val, dev); + break; + } } - static uint8_t cmd640_pci_read(int func, int addr, void *priv) { cmd640_t *dev = (cmd640_t *) priv; - uint8_t ret = 0xff; + uint8_t ret = 0xff; if (func == 0x00) { - ret = dev->regs[addr]; - if (addr == 0x50) - dev->regs[0x50] &= ~0x04; - else if (addr == 0x57) - dev->regs[0x57] &= ~0x10; + ret = dev->regs[addr]; + if (addr == 0x50) + dev->regs[0x50] &= ~0x04; + else if (addr == 0x57) + dev->regs[0x57] &= ~0x10; } cmd640_log("cmd640_pci_read(%i, %02X, %02X)\n", func, addr, ret); @@ -359,84 +385,112 @@ cmd640_pci_read(int func, int addr, void *priv) return ret; } - static void cmd640_reset(void *priv) { cmd640_t *dev = (cmd640_t *) priv; - int i = 0; + int i = 0; + int min_channel; + int max_channel; + + switch (dev->channels) { + default: + case 0x00: + min_channel = max_channel = 0; + break; + case 0x01: + min_channel = 0; + max_channel = 1; + break; + case 0x02: + min_channel = 2; + max_channel = 3; + break; + case 0x03: + min_channel = 0; + max_channel = 3; + break; + } for (i = 0; i < CDROM_NUM; i++) { - if ((cdrom[i].bus_type == CDROM_BUS_ATAPI) && - (cdrom[i].ide_channel < 4) && cdrom[i].priv) - scsi_cdrom_reset((scsi_common_t *) cdrom[i].priv); + if ((cdrom[i].bus_type == CDROM_BUS_ATAPI) && (cdrom[i].ide_channel >= min_channel) && + (cdrom[i].ide_channel <= max_channel) && cdrom[i].priv) + scsi_cdrom_reset((scsi_common_t *) cdrom[i].priv); } for (i = 0; i < ZIP_NUM; i++) { - if ((zip_drives[i].bus_type == ZIP_BUS_ATAPI) && - (zip_drives[i].ide_channel < 4) && zip_drives[i].priv) - zip_reset((scsi_common_t *) zip_drives[i].priv); + if ((zip_drives[i].bus_type == ZIP_BUS_ATAPI) && (zip_drives[i].ide_channel >= min_channel) && + (zip_drives[i].ide_channel <= max_channel) && zip_drives[i].priv) + zip_reset((scsi_common_t *) zip_drives[i].priv); + } + for (i = 0; i < MO_NUM; i++) { + if ((mo_drives[i].bus_type == MO_BUS_ATAPI) && (mo_drives[i].ide_channel >= min_channel) && + (mo_drives[i].ide_channel <= max_channel) && mo_drives[i].priv) + mo_reset((scsi_common_t *) mo_drives[i].priv); } - for (i = 0; i < MO_NUM; i++) { - if ((mo_drives[i].bus_type == MO_BUS_ATAPI) && - (mo_drives[i].ide_channel < 4) && mo_drives[i].priv) - mo_reset((scsi_common_t *) mo_drives[i].priv); - } - cmd640_set_irq(0x00, priv); - cmd640_set_irq(0x01, priv); + if (dev->channels & 0x01) + cmd640_set_irq_0(0x00, priv); + + if (dev->channels & 0x02) + cmd640_set_irq_1(0x00, priv); memset(dev->regs, 0x00, sizeof(dev->regs)); - dev->regs[0x50] = 0x02; /* Revision 02 */ - dev->regs[0x50] |= (dev->id << 3); /* Device ID: 00 = 60h, 01 = 61h, 10 = 62h, 11 = 63h */ + dev->regs[0x50] = 0x02; /* Revision 02 */ + dev->regs[0x50] |= (dev->id << 3); /* Device ID: 00 = 60h, 01 = 61h, 10 = 62h, 11 = 63h */ dev->regs[0x59] = 0x40; if (dev->pci) { - cmd640_log("dev->local = %08X\n", dev->local); - if ((dev->local & 0xffff) == 0x0a) { - dev->regs[0x50] |= 0x40; /* Enable Base address register R/W; - If 0, they return 0 and are read-only 8 */ - } + cmd640_log("dev->local = %08X\n", dev->local); + if ((dev->local & 0xffff) == 0x0a) { + dev->regs[0x50] |= 0x40; /* Enable Base address register R/W; + If 0, they return 0 and are read-only 8 */ + } - dev->regs[0x00] = 0x95; /* CMD */ - dev->regs[0x01] = 0x10; - dev->regs[0x02] = 0x40; /* PCI-0640B */ - dev->regs[0x03] = 0x06; - dev->regs[0x04] = 0x01; /* Apparently required by the ASUS PCI/I-P5SP4 AND PCI/I-P54SP4 */ - dev->regs[0x07] = 0x02; /* DEVSEL timing: 01 medium */ - dev->regs[0x08] = 0x02; /* Revision 02 */ - dev->regs[0x09] = dev->local; /* Programming interface */ - dev->regs[0x0a] = 0x01; /* IDE controller */ - dev->regs[0x0b] = 0x01; /* Mass storage controller */ + dev->regs[0x00] = 0x95; /* CMD */ + dev->regs[0x01] = 0x10; + dev->regs[0x02] = 0x40; /* PCI-0640B */ + dev->regs[0x03] = 0x06; + dev->regs[0x04] = 0x01; /* Apparently required by the ASUS PCI/I-P5SP4 AND PCI/I-P54SP4 */ + dev->regs[0x07] = 0x02; /* DEVSEL timing: 01 medium */ + dev->regs[0x08] = 0x02; /* Revision 02 */ + dev->regs[0x09] = dev->local; /* Programming interface */ + dev->regs[0x0a] = 0x01; /* IDE controller */ + dev->regs[0x0b] = 0x01; /* Mass storage controller */ - /* Base addresses (1F0, 3F4, 170, 374) */ - if (dev->regs[0x50] & 0x40) { - dev->regs[0x10] = 0xf1; dev->regs[0x11] = 0x01; - dev->regs[0x14] = 0xf5; dev->regs[0x15] = 0x03; - dev->regs[0x18] = 0x71; dev->regs[0x19] = 0x01; - dev->regs[0x1c] = 0x75; dev->regs[0x1d] = 0x03; - } + /* Base addresses (1F0, 3F4, 170, 374) */ + if (dev->regs[0x50] & 0x40) { + dev->regs[0x10] = 0xf1; + dev->regs[0x11] = 0x01; + dev->regs[0x14] = 0xf5; + dev->regs[0x15] = 0x03; + dev->regs[0x18] = 0x71; + dev->regs[0x19] = 0x01; + dev->regs[0x1c] = 0x75; + dev->regs[0x1d] = 0x03; + } - dev->regs[0x3c] = 0x14; /* IRQ 14 */ - dev->regs[0x3d] = 0x01; /* INTA */ + dev->regs[0x3c] = 0x14; /* IRQ 14 */ + dev->regs[0x3d] = 0x01; /* INTA */ - dev->irq_mode[0] = dev->irq_mode[1] = 0; - dev->irq_pin = PCI_INTA; - dev->irq_line = 14; + dev->irq_mode[0] = dev->irq_mode[1] = 0; + dev->irq_pin = PCI_INTA; + dev->irq_line = 14; } else { - if ((dev->local & 0xffff) == 0x0078) - dev->regs[0x50] |= 0x20; /* 0 = 178h, 17Ch; 1 = 078h, 07Ch */ + dev->regs[0x04] = 0x01; /* To make sure the two channels get enabled. */ - /* If bit 7 is 1, then device ID has to be written on port x78h before - accessing the configuration registers */ - dev->in_cfg = 1; /* Configuration registers are accessible */ + if ((dev->local & 0xffff) == 0x0078) + dev->regs[0x50] |= 0x20; /* 0 = 178h, 17Ch; 1 = 078h, 07Ch */ + + /* If bit 7 is 1, then device ID has to be written on port x78h before + accessing the configuration registers */ + dev->in_cfg = 1; /* Configuration registers are accessible */ } cmd640_ide_handlers(dev); } - static void cmd640_close(void *priv) { @@ -447,7 +501,6 @@ cmd640_close(void *priv) next_id = 0; } - static void * cmd640_init(const device_t *info) { @@ -456,34 +509,45 @@ cmd640_init(const device_t *info) dev->id = next_id | 0x60; - dev->pci = !!(info->flags & DEVICE_PCI); + dev->pci = !!(info->flags & DEVICE_PCI); dev->local = info->local; + dev->channels = ((info->local & 0x60000) >> 17) & 0x03; + if (info->flags & DEVICE_PCI) { - device_add(&ide_pci_2ch_device); + device_add(&ide_pci_2ch_device); - dev->slot = pci_add_card(PCI_ADD_IDE, cmd640_pci_read, cmd640_pci_write, dev); + if (info->local & 0x80000) + pci_add_card(PCI_ADD_NORMAL, cmd640_pci_read, cmd640_pci_write, dev, &dev->pci_slot); + else + pci_add_card(PCI_ADD_IDE, cmd640_pci_read, cmd640_pci_write, dev, &dev->pci_slot); - ide_set_bus_master(0, NULL, cmd640_set_irq, dev); - ide_set_bus_master(1, NULL, cmd640_set_irq, dev); + if (dev->channels & 0x01) + ide_set_bus_master(0, NULL, cmd640_set_irq_0, dev); - /* The CMD PCI-0640B IDE controller has no DMA capability, - so set our devices IDE devices to force ATA-3 (no DMA). */ - ide_board_set_force_ata3(0, 1); - ide_board_set_force_ata3(1, 1); + if (dev->channels & 0x02) + ide_set_bus_master(1, NULL, cmd640_set_irq_1, dev); - // ide_pri_disable(); + /* The CMD PCI-0640B IDE controller has no DMA capability, + so set our devices IDE devices to force ATA-3 (no DMA). */ + if (dev->channels & 0x01) + ide_board_set_force_ata3(0, 1); + + if (dev->channels & 0x02) + ide_board_set_force_ata3(1, 1); + +#if 0 + ide_pri_disable(); +#endif } else if (info->flags & DEVICE_VLB) { - device_add(&ide_vlb_2ch_device); + device_add(&ide_vlb_2ch_device); - io_sethandler(info->local & 0xffff, 0x0008, - cmd640_vlb_read, cmd640_vlb_readw, cmd640_vlb_readl, - cmd640_vlb_write, cmd640_vlb_writew, cmd640_vlb_writel, - dev); + io_sethandler(info->local & 0xffff, 0x0008, + cmd640_vlb_read, cmd640_vlb_readw, cmd640_vlb_readl, + cmd640_vlb_write, cmd640_vlb_writew, cmd640_vlb_writel, + dev); } - dev->single_channel = !!(info->local & 0x20000); - next_id++; cmd640_reset(dev); @@ -491,53 +555,142 @@ cmd640_init(const device_t *info) return dev; } - const device_t ide_cmd640_vlb_device = { - "CMD PCI-0640B VLB", - "ide_cmd640_vlb", - DEVICE_VLB, - 0x0078, - cmd640_init, cmd640_close, cmd640_reset, - { NULL }, NULL, NULL, - NULL + .name = "CMD PCI-0640B VLB", + .internal_name = "ide_cmd640_vlb", + .flags = DEVICE_VLB, + .local = 0x60078, + .init = cmd640_init, + .close = cmd640_close, + .reset = cmd640_reset, + { .available = NULL }, + .speed_changed = NULL, + .force_redraw = NULL, + .config = NULL }; const device_t ide_cmd640_vlb_178_device = { - "CMD PCI-0640B VLB (Port 178h)", - "ide_cmd640_vlb_178", - DEVICE_VLB, - 0x0178, - cmd640_init, cmd640_close, cmd640_reset, - { NULL }, NULL, NULL, - NULL + .name = "CMD PCI-0640B VLB (Port 178h)", + .internal_name = "ide_cmd640_vlb_178", + .flags = DEVICE_VLB, + .local = 0x60178, + .init = cmd640_init, + .close = cmd640_close, + .reset = cmd640_reset, + { .available = NULL }, + .speed_changed = NULL, + .force_redraw = NULL, + .config = NULL +}; + +const device_t ide_cmd640_vlb_pri_device = { + .name = "CMD PCI-0640B VLB", + .internal_name = "ide_cmd640_vlb", + .flags = DEVICE_VLB, + .local = 0x20078, + .init = cmd640_init, + .close = cmd640_close, + .reset = cmd640_reset, + { .available = NULL }, + .speed_changed = NULL, + .force_redraw = NULL, + .config = NULL +}; + +const device_t ide_cmd640_vlb_pri_178_device = { + .name = "CMD PCI-0640B VLB (Port 178h)", + .internal_name = "ide_cmd640_vlb_178", + .flags = DEVICE_VLB, + .local = 0x20178, + .init = cmd640_init, + .close = cmd640_close, + .reset = cmd640_reset, + { .available = NULL }, + .speed_changed = NULL, + .force_redraw = NULL, + .config = NULL +}; + +const device_t ide_cmd640_vlb_sec_device = { + .name = "CMD PCI-0640B VLB", + .internal_name = "ide_cmd640_vlb", + .flags = DEVICE_VLB, + .local = 0x40078, + .init = cmd640_init, + .close = cmd640_close, + .reset = cmd640_reset, + { .available = NULL }, + .speed_changed = NULL, + .force_redraw = NULL, + .config = NULL +}; + +const device_t ide_cmd640_vlb_sec_178_device = { + .name = "CMD PCI-0640B VLB (Port 178h)", + .internal_name = "ide_cmd640_vlb_178", + .flags = DEVICE_VLB, + .local = 0x40178, + .init = cmd640_init, + .close = cmd640_close, + .reset = cmd640_reset, + { .available = NULL }, + .speed_changed = NULL, + .force_redraw = NULL, + .config = NULL }; const device_t ide_cmd640_pci_device = { - "CMD PCI-0640B PCI", - "ide_cmd640_pci", - DEVICE_PCI, - 0x0a, - cmd640_init, cmd640_close, cmd640_reset, - { NULL }, NULL, NULL, - NULL + .name = "CMD PCI-0640B PCI", + .internal_name = "ide_cmd640_pci", + .flags = DEVICE_PCI, + .local = 0x6000a, + .init = cmd640_init, + .close = cmd640_close, + .reset = cmd640_reset, + { .available = NULL }, + .speed_changed = NULL, + .force_redraw = NULL, + .config = NULL }; const device_t ide_cmd640_pci_legacy_only_device = { - "CMD PCI-0640B PCI (Legacy Mode Only)", - "ide_cmd640_pci_legacy_only", - DEVICE_PCI, - 0x00, - cmd640_init, cmd640_close, cmd640_reset, - { NULL }, NULL, NULL, - NULL + .name = "CMD PCI-0640B PCI (Legacy Mode Only)", + .internal_name = "ide_cmd640_pci_legacy_only", + .flags = DEVICE_PCI, + .local = 0x60000, + .init = cmd640_init, + .close = cmd640_close, + .reset = cmd640_reset, + { .available = NULL }, + .speed_changed = NULL, + .force_redraw = NULL, + .config = NULL }; const device_t ide_cmd640_pci_single_channel_device = { - "CMD PCI-0640B PCI", - "ide_cmd640_pci_single_channel", - DEVICE_PCI, - 0x2000a, - cmd640_init, cmd640_close, cmd640_reset, - { NULL }, NULL, NULL, - NULL + .name = "CMD PCI-0640B PCI", + .internal_name = "ide_cmd640_pci_single_channel", + .flags = DEVICE_PCI, + .local = 0x2000a, + .init = cmd640_init, + .close = cmd640_close, + .reset = cmd640_reset, + { .available = NULL }, + .speed_changed = NULL, + .force_redraw = NULL, + .config = NULL +}; + +const device_t ide_cmd640_pci_single_channel_sec_device = { + .name = "CMD PCI-0640B PCI", + .internal_name = "ide_cmd640_pci_single_channel_sec", + .flags = DEVICE_PCI, + .local = 0x4000a, + .init = cmd640_init, + .close = cmd640_close, + .reset = cmd640_reset, + { .available = NULL }, + .speed_changed = NULL, + .force_redraw = NULL, + .config = NULL }; diff --git a/src/disk/hdc_ide_cmd646.c b/src/disk/hdc_ide_cmd646.c index d2b2fe978..8367b9a41 100644 --- a/src/disk/hdc_ide_cmd646.c +++ b/src/disk/hdc_ide_cmd646.c @@ -1,16 +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. + * 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. + * This file is part of the 86Box distribution. * - * Implementation of the CMD PCI-0646 controller. + * Implementation of the CMD PCI-0646 controller. * - * Authors: Miran Grca, + * Authors: Miran Grca, * - * Copyright 2020 Miran Grca. + * Copyright 2020 Miran Grca. */ #include #include @@ -37,123 +37,135 @@ #include <86box/zip.h> #include <86box/mo.h> +typedef struct cmd646_t { + uint8_t vlb_idx; + uint8_t single_channel; + uint8_t in_cfg; + uint8_t pci_slot; -typedef struct -{ - uint8_t vlb_idx, single_channel, - in_cfg, regs[256]; - uint32_t local; - int slot, irq_mode[2], - irq_pin; - sff8038i_t *bm[2]; + uint8_t regs[256]; + + uint32_t local; + + int irq_pin; + + int irq_mode[2]; + + sff8038i_t *bm[2]; } cmd646_t; - #ifdef ENABLE_CMD646_LOG int cmd646_do_log = ENABLE_CMD646_LOG; + static void cmd646_log(const char *fmt, ...) { va_list ap; - if (cmd646_do_log) - { - va_start(ap, fmt); - pclog_ex(fmt, ap); - va_end(ap); + if (cmd646_do_log) { + va_start(ap, fmt); + pclog_ex(fmt, ap); + va_end(ap); } } #else -#define cmd646_log(fmt, ...) +# define cmd646_log(fmt, ...) #endif +static void +cmd646_set_irq_0(uint8_t status, void *priv) +{ + cmd646_t *dev = (cmd646_t *) priv; + + if (!(dev->regs[0x50] & 0x04) || (status & 0x04)) + dev->regs[0x50] = (dev->regs[0x50] & ~0x04) | status; + + sff_bus_master_set_irq(status, dev->bm[0]); +} static void -cmd646_set_irq(int channel, void *priv) +cmd646_set_irq_1(uint8_t status, void *priv) { cmd646_t *dev = (cmd646_t *) priv; - if (channel & 0x01) { - if (!(dev->regs[0x57] & 0x10) || (channel & 0x40)) { - dev->regs[0x57] &= ~0x10; - dev->regs[0x57] |= (channel >> 2); - } - } else { - if (!(dev->regs[0x50] & 0x04) || (channel & 0x40)) { - dev->regs[0x50] &= ~0x04; - dev->regs[0x50] |= (channel >> 4); - } - } + if (!(dev->regs[0x57] & 0x10) || (status & 0x04)) + dev->regs[0x57] = (dev->regs[0x57] & ~0x10) | (status << 2); - sff_bus_master_set_irq(channel, dev->bm[channel & 0x01]); + sff_bus_master_set_irq(status, dev->bm[1]); } - static int -cmd646_bus_master_dma(int channel, uint8_t *data, int transfer_length, int out, void *priv) +cmd646_bus_master_dma_0(uint8_t *data, int transfer_length, int out, void *priv) { - cmd646_t *dev = (cmd646_t *) priv; + const cmd646_t *dev = (cmd646_t *) priv; - return sff_bus_master_dma(channel, data, transfer_length, out, dev->bm[channel & 0x01]); + return sff_bus_master_dma(data, transfer_length, out, dev->bm[0]); } +static int +cmd646_bus_master_dma_1(uint8_t *data, int transfer_length, int out, void *priv) +{ + const cmd646_t *dev = (cmd646_t *) priv; + + return sff_bus_master_dma(data, transfer_length, out, dev->bm[1]); +} static void cmd646_ide_handlers(cmd646_t *dev) { - uint16_t main, side; - int irq_mode[2] = { 0, 0 }; + uint16_t main; + uint16_t side; + int irq_mode[2] = { IRQ_MODE_LEGACY, IRQ_MODE_LEGACY }; + + sff_set_slot(dev->bm[0], dev->pci_slot); + sff_set_slot(dev->bm[1], dev->pci_slot); ide_pri_disable(); if ((dev->regs[0x09] & 0x01) && (dev->regs[0x50] & 0x40)) { - main = (dev->regs[0x11] << 8) | (dev->regs[0x10] & 0xf8); - side = ((dev->regs[0x15] << 8) | (dev->regs[0x14] & 0xfc)) + 2; + main = (dev->regs[0x11] << 8) | (dev->regs[0x10] & 0xf8); + side = ((dev->regs[0x15] << 8) | (dev->regs[0x14] & 0xfc)) + 2; } else { - main = 0x1f0; - side = 0x3f6; + main = 0x1f0; + side = 0x3f6; } ide_set_base(0, main); ide_set_side(0, side); if (dev->regs[0x09] & 0x01) - irq_mode[0] = 1; + irq_mode[0] = IRQ_MODE_PCI_IRQ_PIN; - sff_set_irq_mode(dev->bm[0], 0, irq_mode[0]); - sff_set_irq_mode(dev->bm[0], 1, irq_mode[1]); + sff_set_irq_mode(dev->bm[0], irq_mode[0]); if (dev->regs[0x04] & 0x01) - ide_pri_enable(); + ide_pri_enable(); if (dev->single_channel) - return; + return; ide_sec_disable(); if ((dev->regs[0x09] & 0x04) && (dev->regs[0x50] & 0x40)) { - main = (dev->regs[0x19] << 8) | (dev->regs[0x18] & 0xf8); - side = ((dev->regs[0x1d] << 8) | (dev->regs[0x1c] & 0xfc)) + 2; + main = (dev->regs[0x19] << 8) | (dev->regs[0x18] & 0xf8); + side = ((dev->regs[0x1d] << 8) | (dev->regs[0x1c] & 0xfc)) + 2; } else { - main = 0x170; - side = 0x376; + main = 0x170; + side = 0x376; } ide_set_base(1, main); ide_set_side(1, side); if (dev->regs[0x09] & 0x04) - irq_mode[1] = 1; + irq_mode[1] = 1; - sff_set_irq_mode(dev->bm[1], 0, irq_mode[0]); - sff_set_irq_mode(dev->bm[1], 1, irq_mode[1]); + sff_set_irq_mode(dev->bm[1], irq_mode[1]); if ((dev->regs[0x04] & 0x01) && (dev->regs[0x51] & 0x08)) - ide_sec_enable(); - + ide_sec_enable(); } - static void cmd646_ide_bm_handlers(cmd646_t *dev) { @@ -163,7 +175,6 @@ cmd646_ide_bm_handlers(cmd646_t *dev) sff_bus_master_handler(dev->bm[1], (dev->regs[0x04] & 1), base + 8); } - static void cmd646_pci_write(int func, int addr, uint8_t val, void *priv) { @@ -171,119 +182,127 @@ cmd646_pci_write(int func, int addr, uint8_t val, void *priv) cmd646_log("[%04X:%08X] (%08X) cmd646_pci_write(%i, %02X, %02X)\n", CS, cpu_state.pc, ESI, func, addr, val); - if (func == 0x00) switch (addr) { - case 0x04: - dev->regs[addr] = (val & 0x45); - cmd646_ide_handlers(dev); - break; - case 0x07: - dev->regs[addr] &= ~(val & 0xb1); - break; - case 0x09: - if ((dev->regs[addr] & 0x0a) == 0x0a) { - dev->regs[addr] = (dev->regs[addr] & 0x0a) | (val & 0x05); - dev->irq_mode[0] = !!(val & 0x01); - dev->irq_mode[1] = !!(val & 0x04); - cmd646_ide_handlers(dev); - } - break; - case 0x10: - if (dev->regs[0x50] & 0x40) { - dev->regs[0x10] = (val & 0xf8) | 1; - cmd646_ide_handlers(dev); - } - break; - case 0x11: - if (dev->regs[0x50] & 0x40) { - dev->regs[0x11] = val; - cmd646_ide_handlers(dev); - } - break; - case 0x14: - if (dev->regs[0x50] & 0x40) { - dev->regs[0x14] = (val & 0xfc) | 1; - cmd646_ide_handlers(dev); - } - break; - case 0x15: - if (dev->regs[0x50] & 0x40) { - dev->regs[0x15] = val; - cmd646_ide_handlers(dev); - } - break; - case 0x18: - if (dev->regs[0x50] & 0x40) { - dev->regs[0x18] = (val & 0xf8) | 1; - cmd646_ide_handlers(dev); - } - break; - case 0x19: - if (dev->regs[0x50] & 0x40) { - dev->regs[0x19] = val; - cmd646_ide_handlers(dev); - } - break; - case 0x1c: - if (dev->regs[0x50] & 0x40) { - dev->regs[0x1c] = (val & 0xfc) | 1; - cmd646_ide_handlers(dev); - } - break; - case 0x1d: - if (dev->regs[0x50] & 0x40) { - dev->regs[0x1d] = val; - cmd646_ide_handlers(dev); - } - break; - case 0x20: - dev->regs[0x20] = (val & 0xf0) | 1; - cmd646_ide_bm_handlers(dev); - break; - case 0x21: - dev->regs[0x21] = val; - cmd646_ide_bm_handlers(dev); - break; - case 0x51: - dev->regs[addr] = val & 0xc8; - cmd646_ide_handlers(dev); - break; - case 0x52: case 0x54: case 0x56: case 0x58: - case 0x59: case 0x5b: - dev->regs[addr] = val; - break; - case 0x53: case 0x55: - dev->regs[addr] = val & 0xc0; - break; - case 0x57: - dev->regs[addr] = (dev->regs[addr] & 0x10) | (val & 0xcc); - break; - case 0x70 ... 0x77: - sff_bus_master_write(addr & 0x0f, val, dev->bm[0]); - break; - case 0x78 ... 0x7f: - sff_bus_master_write(addr & 0x0f, val, dev->bm[1]); - break; - } -} + if (func == 0x00) + switch (addr) { + case 0x04: + dev->regs[addr] = (val & 0x45); + cmd646_ide_handlers(dev); + break; + case 0x07: + dev->regs[addr] &= ~(val & 0xb1); + break; + case 0x09: + if ((dev->regs[addr] & 0x0a) == 0x0a) { + dev->regs[addr] = (dev->regs[addr] & 0x0a) | (val & 0x05); + dev->irq_mode[0] = !!(val & 0x01); + dev->irq_mode[1] = !!(val & 0x04); + cmd646_ide_handlers(dev); + } + break; + case 0x10: + if (dev->regs[0x50] & 0x40) { + dev->regs[0x10] = (val & 0xf8) | 1; + cmd646_ide_handlers(dev); + } + break; + case 0x11: + if (dev->regs[0x50] & 0x40) { + dev->regs[0x11] = val; + cmd646_ide_handlers(dev); + } + break; + case 0x14: + if (dev->regs[0x50] & 0x40) { + dev->regs[0x14] = (val & 0xfc) | 1; + cmd646_ide_handlers(dev); + } + break; + case 0x15: + if (dev->regs[0x50] & 0x40) { + dev->regs[0x15] = val; + cmd646_ide_handlers(dev); + } + break; + case 0x18: + if (dev->regs[0x50] & 0x40) { + dev->regs[0x18] = (val & 0xf8) | 1; + cmd646_ide_handlers(dev); + } + break; + case 0x19: + if (dev->regs[0x50] & 0x40) { + dev->regs[0x19] = val; + cmd646_ide_handlers(dev); + } + break; + case 0x1c: + if (dev->regs[0x50] & 0x40) { + dev->regs[0x1c] = (val & 0xfc) | 1; + cmd646_ide_handlers(dev); + } + break; + case 0x1d: + if (dev->regs[0x50] & 0x40) { + dev->regs[0x1d] = val; + cmd646_ide_handlers(dev); + } + break; + case 0x20: + dev->regs[0x20] = (val & 0xf0) | 1; + cmd646_ide_bm_handlers(dev); + break; + case 0x21: + dev->regs[0x21] = val; + cmd646_ide_bm_handlers(dev); + break; + case 0x51: + dev->regs[addr] = val & 0xc8; + cmd646_ide_handlers(dev); + break; + case 0x52: + case 0x54: + case 0x56: + case 0x58: + case 0x59: + case 0x5b: + dev->regs[addr] = val; + break; + case 0x53: + case 0x55: + dev->regs[addr] = val & 0xc0; + break; + case 0x57: + dev->regs[addr] = (dev->regs[addr] & 0x10) | (val & 0xcc); + break; + case 0x70 ... 0x77: + sff_bus_master_write(addr & 0x0f, val, dev->bm[0]); + break; + case 0x78 ... 0x7f: + sff_bus_master_write(addr & 0x0f, val, dev->bm[1]); + break; + default: + break; + } +} static uint8_t cmd646_pci_read(int func, int addr, void *priv) { cmd646_t *dev = (cmd646_t *) priv; - uint8_t ret = 0xff; + uint8_t ret = 0xff; if (func == 0x00) { - ret = dev->regs[addr]; + ret = dev->regs[addr]; - if (addr == 0x50) - dev->regs[0x50] &= ~0x04; - else if (addr == 0x57) - dev->regs[0x57] &= ~0x10; - else if ((addr >= 0x70) && (addr <= 0x77)) - ret = sff_bus_master_read(addr & 0x0f, dev->bm[0]); - else if ((addr >= 0x78) && (addr <= 0x7f)) - ret = sff_bus_master_read(addr & 0x0f, dev->bm[0]); + if (addr == 0x50) + dev->regs[0x50] &= ~0x04; + else if (addr == 0x57) + dev->regs[0x57] &= ~0x10; + else if ((addr >= 0x70) && (addr <= 0x77)) + ret = sff_bus_master_read(addr & 0x0f, dev->bm[0]); + else if ((addr >= 0x78) && (addr <= 0x7f)) + ret = sff_bus_master_read(addr & 0x0f, dev->bm[0]); } cmd646_log("[%04X:%08X] (%08X) cmd646_pci_read(%i, %02X, %02X)\n", CS, cpu_state.pc, ESI, func, addr, ret); @@ -291,77 +310,76 @@ cmd646_pci_read(int func, int addr, void *priv) return ret; } - static void cmd646_reset(void *priv) { cmd646_t *dev = (cmd646_t *) priv; - int i = 0; + int i = 0; for (i = 0; i < CDROM_NUM; i++) { - if ((cdrom[i].bus_type == CDROM_BUS_ATAPI) && - (cdrom[i].ide_channel < 4) && cdrom[i].priv) - scsi_cdrom_reset((scsi_common_t *) cdrom[i].priv); + if ((cdrom[i].bus_type == CDROM_BUS_ATAPI) && (cdrom[i].ide_channel < 4) && cdrom[i].priv) + scsi_cdrom_reset((scsi_common_t *) cdrom[i].priv); } for (i = 0; i < ZIP_NUM; i++) { - if ((zip_drives[i].bus_type == ZIP_BUS_ATAPI) && - (zip_drives[i].ide_channel < 4) && zip_drives[i].priv) - zip_reset((scsi_common_t *) zip_drives[i].priv); + if ((zip_drives[i].bus_type == ZIP_BUS_ATAPI) && (zip_drives[i].ide_channel < 4) && zip_drives[i].priv) + zip_reset((scsi_common_t *) zip_drives[i].priv); + } + for (i = 0; i < MO_NUM; i++) { + if ((mo_drives[i].bus_type == MO_BUS_ATAPI) && (mo_drives[i].ide_channel < 4) && mo_drives[i].priv) + mo_reset((scsi_common_t *) mo_drives[i].priv); } - for (i = 0; i < MO_NUM; i++) { - if ((mo_drives[i].bus_type == MO_BUS_ATAPI) && - (mo_drives[i].ide_channel < 4) && mo_drives[i].priv) - mo_reset((scsi_common_t *) mo_drives[i].priv); - } - cmd646_set_irq(0x00, priv); - cmd646_set_irq(0x01, priv); + cmd646_set_irq_0(0x00, priv); + cmd646_set_irq_1(0x00, priv); memset(dev->regs, 0x00, sizeof(dev->regs)); - dev->regs[0x00] = 0x95; /* CMD */ + dev->regs[0x00] = 0x95; /* CMD */ dev->regs[0x01] = 0x10; - dev->regs[0x02] = 0x46; /* PCI-0646 */ + dev->regs[0x02] = 0x46; /* PCI-0646 */ dev->regs[0x03] = 0x06; dev->regs[0x04] = 0x00; dev->regs[0x06] = 0x80; - dev->regs[0x07] = 0x02; /* DEVSEL timing: 01 medium */ - dev->regs[0x09] = dev->local; /* Programming interface */ - dev->regs[0x0a] = 0x01; /* IDE controller */ - dev->regs[0x0b] = 0x01; /* Mass storage controller */ + dev->regs[0x07] = 0x02; /* DEVSEL timing: 01 medium */ + dev->regs[0x09] = dev->local; /* Programming interface */ + dev->regs[0x0a] = 0x01; /* IDE controller */ + dev->regs[0x0b] = 0x01; /* Mass storage controller */ if ((dev->local & 0xffff) == 0x8a) { - dev->regs[0x50] = 0x40; /* Enable Base address register R/W; - If 0, they return 0 and are read-only 8 */ + dev->regs[0x50] = 0x40; /* Enable Base address register R/W; + If 0, they return 0 and are read-only 8 */ - /* Base addresses (1F0, 3F4, 170, 374) */ - dev->regs[0x10] = 0xf1; dev->regs[0x11] = 0x01; - dev->regs[0x14] = 0xf5; dev->regs[0x15] = 0x03; - dev->regs[0x18] = 0x71; dev->regs[0x19] = 0x01; - dev->regs[0x1c] = 0x75; dev->regs[0x1d] = 0x03; + /* Base addresses (1F0, 3F4, 170, 374) */ + dev->regs[0x10] = 0xf1; + dev->regs[0x11] = 0x01; + dev->regs[0x14] = 0xf5; + dev->regs[0x15] = 0x03; + dev->regs[0x18] = 0x71; + dev->regs[0x19] = 0x01; + dev->regs[0x1c] = 0x75; + dev->regs[0x1d] = 0x03; } dev->regs[0x20] = 0x01; - dev->regs[0x3c] = 0x0e; /* IRQ 14 */ - dev->regs[0x3d] = 0x01; /* INTA */ - dev->regs[0x3e] = 0x02; /* Min_Gnt */ - dev->regs[0x3f] = 0x04; /* Max_Iat */ + dev->regs[0x3c] = 0x0e; /* IRQ 14 */ + dev->regs[0x3d] = 0x01; /* INTA */ + dev->regs[0x3e] = 0x02; /* Min_Gnt */ + dev->regs[0x3f] = 0x04; /* Max_Iat */ if (!dev->single_channel) - dev->regs[0x51] = 0x08; + dev->regs[0x51] = 0x08; dev->regs[0x57] = 0x0c; dev->regs[0x59] = 0x40; dev->irq_mode[0] = dev->irq_mode[1] = 0; - dev->irq_pin = PCI_INTA; + dev->irq_pin = PCI_INTA; cmd646_ide_handlers(dev); cmd646_ide_bm_handlers(dev); } - static void cmd646_close(void *priv) { @@ -370,7 +388,6 @@ cmd646_close(void *priv) free(dev); } - static void * cmd646_init(const device_t *info) { @@ -381,58 +398,69 @@ cmd646_init(const device_t *info) device_add(&ide_pci_2ch_device); - dev->slot = pci_add_card(PCI_ADD_IDE, cmd646_pci_read, cmd646_pci_write, dev); + if (info->local & 0x80000) + pci_add_card(PCI_ADD_NORMAL, cmd646_pci_read, cmd646_pci_write, dev, &dev->pci_slot); + else + pci_add_card(PCI_ADD_IDE, cmd646_pci_read, cmd646_pci_write, dev, &dev->pci_slot); dev->single_channel = !!(info->local & 0x20000); dev->bm[0] = device_add_inst(&sff8038i_device, 1); if (!dev->single_channel) - dev->bm[1] = device_add_inst(&sff8038i_device, 2); + dev->bm[1] = device_add_inst(&sff8038i_device, 2); - ide_set_bus_master(0, cmd646_bus_master_dma, cmd646_set_irq, dev); + ide_set_bus_master(0, cmd646_bus_master_dma_0, cmd646_set_irq_0, dev); if (!dev->single_channel) - ide_set_bus_master(1, cmd646_bus_master_dma, cmd646_set_irq, dev); + ide_set_bus_master(1, cmd646_bus_master_dma_1, cmd646_set_irq_1, dev); - sff_set_irq_mode(dev->bm[0], 0, 0); - sff_set_irq_mode(dev->bm[0], 1, 0); + sff_set_irq_mode(dev->bm[0], IRQ_MODE_LEGACY); - if (!dev->single_channel) { - sff_set_irq_mode(dev->bm[1], 0, 0); - sff_set_irq_mode(dev->bm[1], 1, 0); - } + if (!dev->single_channel) + sff_set_irq_mode(dev->bm[1], IRQ_MODE_LEGACY); cmd646_reset(dev); return dev; } - const device_t ide_cmd646_device = { - "CMD PCI-0646", - "ide_cmd646", - DEVICE_PCI, - 0x8a, - cmd646_init, cmd646_close, cmd646_reset, - { NULL }, NULL, NULL, - NULL + .name = "CMD PCI-0646", + .internal_name = "ide_cmd646", + .flags = DEVICE_PCI, + .local = 0x8a, + .init = cmd646_init, + .close = cmd646_close, + .reset = cmd646_reset, + { .available = NULL }, + .speed_changed = NULL, + .force_redraw = NULL, + .config = NULL }; const device_t ide_cmd646_legacy_only_device = { - "CMD PCI-0646 (Legacy Mode Only)", - "ide_cmd646_legacy_only", - DEVICE_PCI, - 0x80, - cmd646_init, cmd646_close, cmd646_reset, - { NULL }, NULL, NULL, - NULL + .name = "CMD PCI-0646 (Legacy Mode Only)", + .internal_name = "ide_cmd646_legacy_only", + .flags = DEVICE_PCI, + .local = 0x80, + .init = cmd646_init, + .close = cmd646_close, + .reset = cmd646_reset, + { .available = NULL }, + .speed_changed = NULL, + .force_redraw = NULL, + .config = NULL }; const device_t ide_cmd646_single_channel_device = { - "CMD PCI-0646", - "ide_cmd646_single_channel", - DEVICE_PCI, - 0x2008a, - cmd646_init, cmd646_close, cmd646_reset, - { NULL }, NULL, NULL, - NULL + .name = "CMD PCI-0646", + .internal_name = "ide_cmd646_single_channel", + .flags = DEVICE_PCI, + .local = 0x2008a, + .init = cmd646_init, + .close = cmd646_close, + .reset = cmd646_reset, + { .available = NULL }, + .speed_changed = NULL, + .force_redraw = NULL, + .config = NULL }; diff --git a/src/disk/hdc_ide_opti611.c b/src/disk/hdc_ide_opti611.c index 30b57249f..480331201 100644 --- a/src/disk/hdc_ide_opti611.c +++ b/src/disk/hdc_ide_opti611.c @@ -1,16 +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. + * 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. + * This file is part of the 86Box distribution. * - * Implementation of the OPTi 82C611/611A VLB IDE controller. - - * Authors: Miran Grca, + * Implementation of the OPTi 82C611/611A VLB IDE controller. + + * Authors: Miran Grca, * - * Copyright 2020 Miran Grca. + * Copyright 2020 Miran Grca. */ #include #include @@ -28,18 +28,17 @@ #include <86box/mem.h> #include <86box/hdc.h> #include <86box/hdc_ide.h> +#include <86box/plat_unused.h> - -typedef struct -{ - uint8_t tries, - in_cfg, cfg_locked, - regs[19]; +typedef struct opti611_t { + uint8_t is_sec; + uint8_t tries; + uint8_t in_cfg; + uint8_t cfg_locked; + uint8_t regs[19]; } opti611_t; - -static void opti611_ide_handler(opti611_t *dev); - +static void opti611_ide_handler(opti611_t *dev); static void opti611_cfg_write(uint16_t addr, uint8_t val, void *priv) @@ -47,34 +46,36 @@ opti611_cfg_write(uint16_t addr, uint8_t val, void *priv) opti611_t *dev = (opti611_t *) priv; addr &= 0x0007; - + switch (addr) { - case 0x0000: - case 0x0001: - dev->regs[((dev->regs[0x06] & 0x01) << 4) + addr] = val; - break; - case 0x0002: - dev->regs[0x12] = (val & 0xc1) | 0x02; - if (val & 0xc0) { - if (val & 0x40) - dev->cfg_locked = 1; - dev->in_cfg = 0; - opti611_ide_handler(dev); - } - break; - case 0x0003: - dev->regs[0x03] = (val & 0xdf); - break; - case 0x0005: - dev->regs[0x05] = (dev->regs[0x05] & 0x78) | (val & 0x87); - break; - case 0x0006: - dev->regs[0x06] = val; - break; + case 0x0000: + case 0x0001: + dev->regs[((dev->regs[0x06] & 0x01) << 4) + addr] = val; + break; + case 0x0002: + dev->regs[0x12] = (val & 0xc1) | 0x02; + if (val & 0xc0) { + if (val & 0x40) + dev->cfg_locked = 1; + dev->in_cfg = 0; + opti611_ide_handler(dev); + } + break; + case 0x0003: + dev->regs[0x03] = (val & 0xdf); + break; + case 0x0005: + dev->regs[0x05] = (dev->regs[0x05] & 0x78) | (val & 0x87); + break; + case 0x0006: + dev->regs[0x06] = val; + break; + + default: + break; } } - static void opti611_cfg_writew(uint16_t addr, uint16_t val, void *priv) { @@ -82,7 +83,6 @@ opti611_cfg_writew(uint16_t addr, uint16_t val, void *priv) opti611_cfg_write(addr + 1, val >> 8, priv); } - static void opti611_cfg_writel(uint16_t addr, uint32_t val, void *priv) { @@ -90,34 +90,38 @@ opti611_cfg_writel(uint16_t addr, uint32_t val, void *priv) opti611_cfg_writew(addr + 2, val >> 16, priv); } - static uint8_t opti611_cfg_read(uint16_t addr, void *priv) { - uint8_t ret = 0xff; - opti611_t *dev = (opti611_t *) priv; + uint8_t ret = 0xff; + const opti611_t *dev = (opti611_t *) priv; addr &= 0x0007; switch (addr) { - case 0x0000: - case 0x0001: - ret = dev->regs[((dev->regs[0x06] & 0x01) << 4) + addr]; - break; - case 0x0002: - ret = ((!!in_smm) << 7); - if (ret & 0x80) - ret |= (dev->regs[addr] & 0x7f); - break; - case 0x0003: case 0x0004: case 0x0005: case 0x0006: - ret = dev->regs[addr]; - break; + case 0x0000: + case 0x0001: + ret = dev->regs[((dev->regs[0x06] & 0x01) << 4) + addr]; + break; + case 0x0002: + ret = ((!!in_smm) << 7); + if (ret & 0x80) + ret |= (dev->regs[addr] & 0x7f); + break; + case 0x0003: + case 0x0004: + case 0x0005: + case 0x0006: + ret = dev->regs[addr]; + break; + + default: + break; } return ret; } - static uint16_t opti611_cfg_readw(uint16_t addr, void *priv) { @@ -129,7 +133,6 @@ opti611_cfg_readw(uint16_t addr, void *priv) return ret; } - static uint32_t opti611_cfg_readl(uint16_t addr, void *priv) { @@ -141,7 +144,6 @@ opti611_cfg_readl(uint16_t addr, void *priv) return ret; } - static void opti611_ide_write(uint16_t addr, uint8_t val, void *priv) { @@ -152,15 +154,14 @@ opti611_ide_write(uint16_t addr, uint8_t val, void *priv) uint8_t smibe = (addr & 0x0003); if (dev->regs[0x03] & 0x02) { - smi_line = 1; - dev->regs[0x02] = smia9 | smia2 | smibe; - dev->regs[0x04] = val; + smi_raise(); + dev->regs[0x02] = smia9 | smia2 | smibe; + dev->regs[0x04] = val; } } - static void -opti611_ide_writew(uint16_t addr, uint16_t val, void *priv) +opti611_ide_writew(uint16_t addr, UNUSED(uint16_t val), void *priv) { opti611_t *dev = (opti611_t *) priv; @@ -169,15 +170,14 @@ opti611_ide_writew(uint16_t addr, uint16_t val, void *priv) uint8_t smibe = (addr & 0x0002) | 0x0001; if (dev->regs[0x03] & 0x02) { - smi_line = 1; - dev->regs[0x02] = smia9 | smia2 | smibe; - dev->regs[0x04] = 0x00; + smi_raise(); + dev->regs[0x02] = smia9 | smia2 | smibe; + dev->regs[0x04] = 0x00; } } - static void -opti611_ide_writel(uint16_t addr, uint32_t val, void *priv) +opti611_ide_writel(uint16_t addr, UNUSED(uint32_t val), void *priv) { opti611_t *dev = (opti611_t *) priv; @@ -185,13 +185,12 @@ opti611_ide_writel(uint16_t addr, uint32_t val, void *priv) uint8_t smia2 = (!!(addr & 0x0004)) << 4; if (dev->regs[0x03] & 0x02) { - smi_line = 1; - dev->regs[0x02] = smia9 | smia2 | 0x0003; - dev->regs[0x04] = 0x00; + smi_raise(); + dev->regs[0x02] = smia9 | smia2 | 0x0003; + dev->regs[0x04] = 0x00; } } - static uint8_t opti611_ide_read(uint16_t addr, void *priv) { @@ -202,15 +201,14 @@ opti611_ide_read(uint16_t addr, void *priv) uint8_t smibe = (addr & 0x0003); if (dev->regs[0x03] & 0x02) { - smi_line = 1; - dev->regs[0x02] = smia9 | smia2 | smibe; - dev->regs[0x04] = 0x00; + smi_raise(); + dev->regs[0x02] = smia9 | smia2 | smibe; + dev->regs[0x04] = 0x00; } return 0xff; } - static uint16_t opti611_ide_readw(uint16_t addr, void *priv) { @@ -221,23 +219,22 @@ opti611_ide_readw(uint16_t addr, void *priv) uint8_t smibe = (addr & 0x0002) | 0x0001; if ((addr & 0x0007) == 0x0001) { - dev->tries = (dev->tries + 1) & 0x01; - if ((dev->tries == 0x00) && !dev->cfg_locked) { - dev->in_cfg = 1; - opti611_ide_handler(dev); - } + dev->tries = (dev->tries + 1) & 0x01; + if ((dev->tries == 0x00) && !dev->cfg_locked) { + dev->in_cfg = 1; + opti611_ide_handler(dev); + } } if (dev->regs[0x03] & 0x02) { - smi_line = 1; - dev->regs[0x02] = smia9 | smia2 | smibe; - dev->regs[0x04] = 0x00; + smi_raise(); + dev->regs[0x02] = smia9 | smia2 | smibe; + dev->regs[0x04] = 0x00; } return 0xffff; } - static uint32_t opti611_ide_readl(uint16_t addr, void *priv) { @@ -247,44 +244,68 @@ opti611_ide_readl(uint16_t addr, void *priv) uint8_t smia2 = (!!(addr & 0x0004)) << 4; if (dev->regs[0x03] & 0x02) { - smi_line = 1; - dev->regs[0x02] = smia9 | smia2 | 0x0003; - dev->regs[0x04] = 0x00; + smi_raise(); + dev->regs[0x02] = smia9 | smia2 | 0x0003; + dev->regs[0x04] = 0x00; } return 0xffffffff; } - static void opti611_ide_handler(opti611_t *dev) { - ide_pri_disable(); - io_removehandler(0x01f0, 0x0007, - opti611_ide_read, opti611_ide_readw, opti611_ide_readl, - opti611_ide_write, opti611_ide_writew, opti611_ide_writel, - dev); - io_removehandler(0x01f0, 0x0007, - opti611_cfg_read, opti611_cfg_readw, opti611_cfg_readl, - opti611_cfg_write, opti611_cfg_writew, opti611_cfg_writel, - dev); + if (dev->is_sec) { + ide_sec_disable(); + io_removehandler(0x0170, 0x0007, + opti611_ide_read, opti611_ide_readw, opti611_ide_readl, + opti611_ide_write, opti611_ide_writew, opti611_ide_writel, + dev); + io_removehandler(0x0170, 0x0007, + opti611_cfg_read, opti611_cfg_readw, opti611_cfg_readl, + opti611_cfg_write, opti611_cfg_writew, opti611_cfg_writel, + dev); - if (dev->in_cfg && !dev->cfg_locked) { - io_sethandler(0x01f0, 0x0007, - opti611_cfg_read, opti611_cfg_readw, opti611_cfg_readl, - opti611_cfg_write, opti611_cfg_writew, opti611_cfg_writel, - dev); + if (dev->in_cfg && !dev->cfg_locked) { + io_sethandler(0x0170, 0x0007, + opti611_cfg_read, opti611_cfg_readw, opti611_cfg_readl, + opti611_cfg_write, opti611_cfg_writew, opti611_cfg_writel, + dev); + } else { + if (dev->regs[0x03] & 0x01) + ide_sec_enable(); + io_sethandler(0x0170, 0x0007, + opti611_ide_read, opti611_ide_readw, opti611_ide_readl, + opti611_ide_write, opti611_ide_writew, opti611_ide_writel, + dev); + } } else { - if (dev->regs[0x03] & 0x01) - ide_pri_enable(); - io_sethandler(0x01f0, 0x0007, - opti611_ide_read, opti611_ide_readw, opti611_ide_readl, - opti611_ide_write, opti611_ide_writew, opti611_ide_writel, - dev); + ide_pri_disable(); + io_removehandler(0x01f0, 0x0007, + opti611_ide_read, opti611_ide_readw, opti611_ide_readl, + opti611_ide_write, opti611_ide_writew, opti611_ide_writel, + dev); + io_removehandler(0x01f0, 0x0007, + opti611_cfg_read, opti611_cfg_readw, opti611_cfg_readl, + opti611_cfg_write, opti611_cfg_writew, opti611_cfg_writel, + dev); + + if (dev->in_cfg && !dev->cfg_locked) { + io_sethandler(0x01f0, 0x0007, + opti611_cfg_read, opti611_cfg_readw, opti611_cfg_readl, + opti611_cfg_write, opti611_cfg_writew, opti611_cfg_writel, + dev); + } else { + if (dev->regs[0x03] & 0x01) + ide_pri_enable(); + io_sethandler(0x01f0, 0x0007, + opti611_ide_read, opti611_ide_readw, opti611_ide_readl, + opti611_ide_write, opti611_ide_writew, opti611_ide_writel, + dev); + } } } - static void opti611_close(void *priv) { @@ -293,13 +314,14 @@ opti611_close(void *priv) free(dev); } - static void * -opti611_init(const device_t *info) +opti611_init(UNUSED(const device_t *info)) { opti611_t *dev = (opti611_t *) malloc(sizeof(opti611_t)); memset(dev, 0, sizeof(opti611_t)); + dev->is_sec = info->local; + dev->regs[0x12] = 0x80; dev->regs[0x03] = 0x01; dev->regs[0x05] = 0x20; @@ -311,13 +333,30 @@ opti611_init(const device_t *info) return dev; } - const device_t ide_opti611_vlb_device = { - "OPTi 82C611/82C611A VLB", - "ide_opti611_vlb", - 0, - 0, - opti611_init, opti611_close, NULL, - { NULL }, NULL, NULL, - NULL + .name = "OPTi 82C611/82C611A VLB", + .internal_name = "ide_opti611_vlb", + .flags = DEVICE_VLB, + .local = 0, + .init = opti611_init, + .close = opti611_close, + .reset = NULL, + { .available = NULL }, + .speed_changed = NULL, + .force_redraw = NULL, + .config = NULL +}; + +const device_t ide_opti611_vlb_sec_device = { + .name = "OPTi 82C611/82C611A VLB (Secondary)", + .internal_name = "ide_opti611_vlb", + .flags = DEVICE_VLB, + .local = 1, + .init = opti611_init, + .close = opti611_close, + .reset = NULL, + { .available = NULL }, + .speed_changed = NULL, + .force_redraw = NULL, + .config = NULL }; diff --git a/src/disk/hdc_ide_sff8038i.c b/src/disk/hdc_ide_sff8038i.c index 516b8dcc7..3f43f80e6 100644 --- a/src/disk/hdc_ide_sff8038i.c +++ b/src/disk/hdc_ide_sff8038i.c @@ -1,22 +1,22 @@ /* - * 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. + * 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. * - * Emulation of the SFF-8038i IDE Bus Master. + * Emulation of the SFF-8038i IDE Bus Master. * - * PRD format : - * word 0 - base address - * word 1 - bits 1-15 = byte count, bit 31 = end of transfer + * PRD format : + * word 0 - base address + * word 1 - bits 1-15 = byte count, bit 31 = end of transfer * * * - * Authors: Sarah Walker, - * Miran Grca, + * Authors: Sarah Walker, + * Miran Grca, * - * Copyright 2008-2020 Sarah Walker. - * Copyright 2016-2020 Miran Grca. + * Copyright 2008-2020 Sarah Walker. + * Copyright 2016-2020 Miran Grca. */ #include #include @@ -27,7 +27,9 @@ #define HAVE_STDARG_H #include <86box/86box.h> #include <86box/cdrom.h> +#include <86box/hdd.h> #include <86box/scsi_device.h> +#include <86box/scsi_disk.h> #include <86box/scsi_cdrom.h> #include <86box/dma.h> #include <86box/io.h> @@ -42,76 +44,70 @@ #include <86box/hdc_ide_sff8038i.h> #include <86box/zip.h> #include <86box/mo.h> +#include <86box/plat_unused.h> +static int next_id = 0; -static int next_id = 0; - - -uint8_t sff_bus_master_read(uint16_t port, void *priv); -static uint16_t sff_bus_master_readw(uint16_t port, void *priv); -static uint32_t sff_bus_master_readl(uint16_t port, void *priv); -void sff_bus_master_write(uint16_t port, uint8_t val, void *priv); -static void sff_bus_master_writew(uint16_t port, uint16_t val, void *priv); -static void sff_bus_master_writel(uint16_t port, uint32_t val, void *priv); - +uint8_t sff_bus_master_read(uint16_t port, void *priv); +static uint16_t sff_bus_master_readw(uint16_t port, void *priv); +static uint32_t sff_bus_master_readl(uint16_t port, void *priv); +void sff_bus_master_write(uint16_t port, uint8_t val, void *priv); +static void sff_bus_master_writew(uint16_t port, uint16_t val, void *priv); +static void sff_bus_master_writel(uint16_t port, uint32_t val, void *priv); #ifdef ENABLE_SFF_LOG int sff_do_log = ENABLE_SFF_LOG; - static void sff_log(const char *fmt, ...) { va_list ap; if (sff_do_log) { - va_start(ap, fmt); - pclog_ex(fmt, ap); - va_end(ap); + va_start(ap, fmt); + pclog_ex(fmt, ap); + va_end(ap); } } #else -#define sff_log(fmt, ...) +# define sff_log(fmt, ...) #endif - void sff_bus_master_handler(sff8038i_t *dev, int enabled, uint16_t base) { - if (dev->base != 0x0000) { - io_removehandler(dev->base, 0x08, - sff_bus_master_read, sff_bus_master_readw, sff_bus_master_readl, - sff_bus_master_write, sff_bus_master_writew, sff_bus_master_writel, - dev); + if (dev->enabled && (dev->base != 0x0000)) { + io_removehandler(dev->base, 0x08, + sff_bus_master_read, sff_bus_master_readw, sff_bus_master_readl, + sff_bus_master_write, sff_bus_master_writew, sff_bus_master_writel, + dev); } if (enabled && (base != 0x0000)) { - io_sethandler(base, 0x08, - sff_bus_master_read, sff_bus_master_readw, sff_bus_master_readl, - sff_bus_master_write, sff_bus_master_writew, sff_bus_master_writel, - dev); + io_sethandler(base, 0x08, + sff_bus_master_read, sff_bus_master_readw, sff_bus_master_readl, + sff_bus_master_write, sff_bus_master_writew, sff_bus_master_writel, + dev); } dev->enabled = enabled; - dev->base = base; + dev->base = base; } - static void sff_bus_master_next_addr(sff8038i_t *dev) { - dma_bm_read(dev->ptr_cur, (uint8_t *)&(dev->addr), 4, 4); - dma_bm_read(dev->ptr_cur + 4, (uint8_t *)&(dev->count), 4, 4); + dma_bm_read(dev->ptr_cur, (uint8_t *) &(dev->addr), 4, 4); + dma_bm_read(dev->ptr_cur + 4, (uint8_t *) &(dev->count), 4, 4); sff_log("SFF-8038i Bus master DWORDs: %08X %08X\n", dev->addr, dev->count); dev->eot = dev->count >> 31; dev->count &= 0xfffe; if (!dev->count) - dev->count = 65536; + dev->count = 65536; dev->addr &= 0xfffffffe; dev->ptr_cur += 8; } - void sff_bus_master_write(uint16_t port, uint8_t val, void *priv) { @@ -123,54 +119,56 @@ sff_bus_master_write(uint16_t port, uint8_t val, void *priv) sff_log("SFF-8038i Bus master BYTE write: %04X %02X\n", port, val); switch (port & 7) { - case 0: - sff_log("sff Cmd : val = %02X, old = %02X\n", val, dev->command); - if ((val & 1) && !(dev->command & 1)) { /*Start*/ - sff_log("sff Bus Master start on channel %i\n", channel); - dev->ptr_cur = dev->ptr; - sff_bus_master_next_addr(dev); - dev->status |= 1; - } - if (!(val & 1) && (dev->command & 1)) { /*Stop*/ - sff_log("sff Bus Master stop on channel %i\n", channel); - dev->status &= ~1; - } + case 0: + sff_log("sff Cmd : val = %02X, old = %02X\n", val, dev->command); + if ((val & 1) && !(dev->command & 1)) { /*Start*/ + sff_log("sff Bus Master start on channel %i\n", channel); + dev->ptr_cur = dev->ptr; + sff_bus_master_next_addr(dev); + dev->status |= 1; + } + if (!(val & 1) && (dev->command & 1)) { /*Stop*/ + sff_log("sff Bus Master stop on channel %i\n", channel); + dev->status &= ~1; + } - dev->command = val; - break; - case 1: - dev->dma_mode = val & 0x03; - break; - case 2: - sff_log("sff Status: val = %02X, old = %02X\n", val, dev->status); - dev->status &= 0x07; - dev->status |= (val & 0x60); - if (val & 0x04) - dev->status &= ~0x04; - if (val & 0x02) - dev->status &= ~0x02; - break; - case 4: - dev->ptr = (dev->ptr & 0xffffff00) | (val & 0xfc); - dev->ptr %= (mem_size * 1024); - dev->ptr0 = val; - break; - case 5: - dev->ptr = (dev->ptr & 0xffff00fc) | (val << 8); - dev->ptr %= (mem_size * 1024); - break; - case 6: - dev->ptr = (dev->ptr & 0xff00fffc) | (val << 16); - dev->ptr %= (mem_size * 1024); - break; - case 7: - dev->ptr = (dev->ptr & 0x00fffffc) | (val << 24); - dev->ptr %= (mem_size * 1024); - break; + dev->command = val; + break; + case 1: + dev->dma_mode = val & 0x03; + break; + case 2: + sff_log("sff Status: val = %02X, old = %02X\n", val, dev->status); + dev->status &= 0x07; + dev->status |= (val & 0x60); + if (val & 0x04) + dev->status &= ~0x04; + if (val & 0x02) + dev->status &= ~0x02; + break; + case 4: + dev->ptr = (dev->ptr & 0xffffff00) | (val & 0xfc); + dev->ptr %= (mem_size * 1024); + dev->ptr0 = val; + break; + case 5: + dev->ptr = (dev->ptr & 0xffff00fc) | (val << 8); + dev->ptr %= (mem_size * 1024); + break; + case 6: + dev->ptr = (dev->ptr & 0xff00fffc) | (val << 16); + dev->ptr %= (mem_size * 1024); + break; + case 7: + dev->ptr = (dev->ptr & 0x00fffffc) | (val << 24); + dev->ptr %= (mem_size * 1024); + break; + + default: + break; } } - static void sff_bus_master_writew(uint16_t port, uint16_t val, void *priv) { @@ -179,24 +177,26 @@ sff_bus_master_writew(uint16_t port, uint16_t val, void *priv) sff_log("SFF-8038i Bus master WORD write: %04X %04X\n", port, val); switch (port & 7) { - case 0: - case 1: - case 2: - sff_bus_master_write(port, val & 0xff, priv); - break; - case 4: - dev->ptr = (dev->ptr & 0xffff0000) | (val & 0xfffc); - dev->ptr %= (mem_size * 1024); - dev->ptr0 = val & 0xff; - break; - case 6: - dev->ptr = (dev->ptr & 0x0000fffc) | (val << 16); - dev->ptr %= (mem_size * 1024); - break; + case 0: + case 1: + case 2: + sff_bus_master_write(port, val & 0xff, priv); + break; + case 4: + dev->ptr = (dev->ptr & 0xffff0000) | (val & 0xfffc); + dev->ptr %= (mem_size * 1024); + dev->ptr0 = val & 0xff; + break; + case 6: + dev->ptr = (dev->ptr & 0x0000fffc) | (val << 16); + dev->ptr %= (mem_size * 1024); + break; + + default: + break; } } - static void sff_bus_master_writel(uint16_t port, uint32_t val, void *priv) { @@ -205,49 +205,54 @@ sff_bus_master_writel(uint16_t port, uint32_t val, void *priv) sff_log("SFF-8038i Bus master DWORD write: %04X %08X\n", port, val); switch (port & 7) { - case 0: - case 1: - case 2: - sff_bus_master_write(port, val & 0xff, priv); - break; - case 4: - dev->ptr = (val & 0xfffffffc); - dev->ptr %= (mem_size * 1024); - dev->ptr0 = val & 0xff; - break; + case 0: + case 1: + case 2: + sff_bus_master_write(port, val & 0xff, priv); + break; + case 4: + dev->ptr = (val & 0xfffffffc); + dev->ptr %= (mem_size * 1024); + dev->ptr0 = val & 0xff; + break; + + default: + break; } } - uint8_t sff_bus_master_read(uint16_t port, void *priv) { - sff8038i_t *dev = (sff8038i_t *) priv; + const sff8038i_t *dev = (sff8038i_t *) priv; uint8_t ret = 0xff; switch (port & 7) { - case 0: - ret = dev->command; - break; - case 1: - ret = dev->dma_mode & 0x03; - break; - case 2: - ret = dev->status & 0x67; - break; - case 4: - ret = dev->ptr0; - break; - case 5: - ret = dev->ptr >> 8; - break; - case 6: - ret = dev->ptr >> 16; - break; - case 7: - ret = dev->ptr >> 24; - break; + case 0: + ret = dev->command; + break; + case 1: + ret = dev->dma_mode & 0x03; + break; + case 2: + ret = dev->status & 0x67; + break; + case 4: + ret = dev->ptr0; + break; + case 5: + ret = dev->ptr >> 8; + break; + case 6: + ret = dev->ptr >> 16; + break; + case 7: + ret = dev->ptr >> 24; + break; + + default: + break; } sff_log("SFF-8038i Bus master BYTE read : %04X %02X\n", port, ret); @@ -255,26 +260,28 @@ sff_bus_master_read(uint16_t port, void *priv) return ret; } - static uint16_t sff_bus_master_readw(uint16_t port, void *priv) { - sff8038i_t *dev = (sff8038i_t *) priv; + const sff8038i_t *dev = (sff8038i_t *) priv; uint16_t ret = 0xffff; switch (port & 7) { - case 0: - case 1: - case 2: - ret = (uint16_t) sff_bus_master_read(port, priv); - break; - case 4: - ret = dev->ptr0 | (dev->ptr & 0xff00); - break; - case 6: - ret = dev->ptr >> 16; - break; + case 0: + case 1: + case 2: + ret = (uint16_t) sff_bus_master_read(port, priv); + break; + case 4: + ret = dev->ptr0 | (dev->ptr & 0xff00); + break; + case 6: + ret = dev->ptr >> 16; + break; + + default: + break; } sff_log("SFF-8038i Bus master WORD read : %04X %04X\n", port, ret); @@ -282,23 +289,25 @@ sff_bus_master_readw(uint16_t port, void *priv) return ret; } - static uint32_t sff_bus_master_readl(uint16_t port, void *priv) { - sff8038i_t *dev = (sff8038i_t *) priv; + const sff8038i_t *dev = (sff8038i_t *) priv; uint32_t ret = 0xffffffff; switch (port & 7) { - case 0: - case 1: - case 2: - ret = (uint32_t) sff_bus_master_read(port, priv); - break; - case 4: - ret = dev->ptr0 | (dev->ptr & 0xffffff00); - break; + case 0: + case 1: + case 2: + ret = (uint32_t) sff_bus_master_read(port, priv); + break; + case 4: + ret = dev->ptr0 | (dev->ptr & 0xffffff00); + break; + + default: + break; } sff_log("sff Bus master DWORD read : %04X %08X\n", port, ret); @@ -306,296 +315,294 @@ sff_bus_master_readl(uint16_t port, void *priv) return ret; } - int -sff_bus_master_dma(int channel, uint8_t *data, int transfer_length, int out, void *priv) +sff_bus_master_dma(uint8_t *data, int transfer_length, int out, void *priv) { sff8038i_t *dev = (sff8038i_t *) priv; #ifdef ENABLE_SFF_LOG char *sop; #endif - int force_end = 0, buffer_pos = 0; + int force_end = 0; + int buffer_pos = 0; #ifdef ENABLE_SFF_LOG sop = out ? "Read" : "Writ"; #endif if (!(dev->status & 1)) { - sff_log("DMA disabled\n"); - return 2; /*DMA disabled*/ + sff_log("DMA disabled\n"); + return 2; /*DMA disabled*/ } sff_log("SFF-8038i Bus master %s: %i bytes\n", out ? "write" : "read", transfer_length); while (1) { - if (dev->count <= transfer_length) { - sff_log("%sing %i bytes to %08X\n", sop, dev->count, dev->addr); - if (out) - dma_bm_read(dev->addr, (uint8_t *)(data + buffer_pos), dev->count, 4); - else - dma_bm_write(dev->addr, (uint8_t *)(data + buffer_pos), dev->count, 4); - transfer_length -= dev->count; - buffer_pos += dev->count; - } else { - sff_log("%sing %i bytes to %08X\n", sop, transfer_length, dev->addr); - if (out) - dma_bm_read(dev->addr, (uint8_t *)(data + buffer_pos), transfer_length, 4); - else - dma_bm_write(dev->addr, (uint8_t *)(data + buffer_pos), transfer_length, 4); - /* Increase addr and decrease count so that resumed transfers do not mess up. */ - dev->addr += transfer_length; - dev->count -= transfer_length; - transfer_length = 0; - force_end = 1; - } + if (dev->count <= transfer_length) { + sff_log("%sing %i bytes to %08X\n", sop, dev->count, dev->addr); + if (out) + dma_bm_read(dev->addr, (uint8_t *) (data + buffer_pos), dev->count, 4); + else + dma_bm_write(dev->addr, (uint8_t *) (data + buffer_pos), dev->count, 4); + transfer_length -= dev->count; + buffer_pos += dev->count; + } else { + sff_log("%sing %i bytes to %08X\n", sop, transfer_length, dev->addr); + if (out) + dma_bm_read(dev->addr, (uint8_t *) (data + buffer_pos), transfer_length, 4); + else + dma_bm_write(dev->addr, (uint8_t *) (data + buffer_pos), transfer_length, 4); + /* Increase addr and decrease count so that resumed transfers do not mess up. */ + dev->addr += transfer_length; + dev->count -= transfer_length; + transfer_length = 0; + force_end = 1; + } - if (force_end) { - sff_log("Total transfer length smaller than sum of all blocks, partial block\n"); - dev->status &= ~2; - return 1; /* This block has exhausted the data to transfer and it was smaller than the count, break. */ - } else { - if (!transfer_length && !dev->eot) { - sff_log("Total transfer length smaller than sum of all blocks, full block\n"); - dev->status &= ~2; - return 1; /* We have exhausted the data to transfer but there's more blocks left, break. */ - } else if (transfer_length && dev->eot) { - sff_log("Total transfer length greater than sum of all blocks\n"); - dev->status |= 2; - return 0; /* There is data left to transfer but we have reached EOT - return with error. */ - } else if (dev->eot) { - sff_log("Regular EOT\n"); - dev->status &= ~3; - return 1; /* We have regularly reached EOT - clear status and break. */ - } else { - /* We have more to transfer and there are blocks left, get next block. */ - sff_bus_master_next_addr(dev); - } - } + if (force_end) { + sff_log("Total transfer length smaller than sum of all blocks, partial block\n"); + dev->status &= ~2; + return 1; /* This block has exhausted the data to transfer and it was smaller than the count, break. */ + } else { + if (!transfer_length && !dev->eot) { + sff_log("Total transfer length smaller than sum of all blocks, full block\n"); + dev->status &= ~2; + return 1; /* We have exhausted the data to transfer but there's more blocks left, break. */ + } else if (transfer_length && dev->eot) { + sff_log("Total transfer length greater than sum of all blocks\n"); + dev->status |= 2; + return 0; /* There is data left to transfer but we have reached EOT - return with error. */ + } else if (dev->eot) { + sff_log("Regular EOT\n"); + dev->status &= ~3; + return 1; /* We have regularly reached EOT - clear status and break. */ + } else { + /* We have more to transfer and there are blocks left, get next block. */ + sff_bus_master_next_addr(dev); + } + } } return 1; } - void -sff_bus_master_set_irq(int channel, void *priv) +sff_bus_master_set_irq(uint8_t status, void *priv) { sff8038i_t *dev = (sff8038i_t *) priv; - uint8_t irq = !!(channel & 0x40); + uint8_t irq = !!(status & 0x04); - if (!(dev->status & 0x04) || (channel & 0x40)) { - dev->status &= ~0x04; - dev->status |= (channel >> 4); - } + if (!(dev->status & 0x04) || (status & 0x04)) + dev->status = (dev->status & ~0x04) | status; - channel &= 0x01; - - switch (dev->irq_mode[channel]) { - case 0: - default: - /* Legacy IRQ mode. */ - if (irq) - picint(1 << (14 + channel)); - else - picintc(1 << (14 + channel)); - break; - case 1: - /* Native PCI IRQ mode with interrupt pin. */ - if (irq) - pci_set_irq(dev->slot, dev->irq_pin); - else - pci_clear_irq(dev->slot, dev->irq_pin); - break; - case 2: - case 5: - /* MIRQ 0 or 1. */ - if (irq) - pci_set_mirq(dev->irq_mode[channel] & 1, 0); - else - pci_clear_mirq(dev->irq_mode[channel] & 1, 0); - break; - case 3: - /* Native PCI IRQ mode with specified interrupt line. */ - if (irq) - picintlevel(1 << dev->irq_line); - else - picintc(1 << dev->irq_line); - break; - case 4: - /* ALi Aladdin Native PCI INTAJ mode. */ - if (irq) - pci_set_mirq(channel + 2, dev->irq_level[channel]); - else - pci_clear_mirq(channel + 2, dev->irq_level[channel]); - break; + switch (dev->irq_mode) { + default: + case IRQ_MODE_LEGACY: + /* Legacy IRQ mode. */ + if (irq) + picint(1 << dev->irq_line); + else + picintc(1 << dev->irq_line); + break; + case IRQ_MODE_PCI_IRQ_PIN: + /* Native PCI IRQ mode with interrupt pin. */ + if (irq) + pci_set_irq(dev->slot, dev->irq_pin, &dev->irq_state); + else + pci_clear_irq(dev->slot, dev->irq_pin, &dev->irq_state); + break; + case IRQ_MODE_MIRQ_0 ... IRQ_MODE_MIRQ_3: + /* MIRQ 0, 1, 2, or 3. */ + if (irq) + pci_set_mirq(dev->irq_mode & 3, 0, &dev->irq_state); + else + pci_clear_mirq(dev->irq_mode & 3, 0, &dev->irq_state); + break; + /* TODO: Redo this as a MIRQ. */ + case IRQ_MODE_PCI_IRQ_LINE: + /* Native PCI IRQ mode with specified interrupt line. */ + if (irq) + pci_set_dirq(dev->pci_irq_line, &dev->irq_state); + else + pci_clear_dirq(dev->pci_irq_line, &dev->irq_state); + break; + case IRQ_MODE_ALI_ALADDIN: + /* ALi Aladdin Native PCI INTAJ mode. */ + if (irq) + pci_set_mirq((dev->channel + 2), pci_get_mirq_level(dev->channel + 2), &dev->irq_state); + else + pci_clear_mirq((dev->channel + 2), pci_get_mirq_level(dev->channel + 2), &dev->irq_state); + break; + case IRQ_MODE_SIS_551X: + /* SiS 551x mode. */ + if (irq) + pci_set_mirq(2, 1, &dev->irq_state); + else + pci_clear_mirq(2, 1, &dev->irq_state); + break; } } - void -sff_bus_master_reset(sff8038i_t *dev, uint16_t old_base) +sff_bus_master_reset(sff8038i_t *dev) { - if (dev->enabled) { - io_removehandler(old_base, 0x08, - sff_bus_master_read, sff_bus_master_readw, sff_bus_master_readl, - sff_bus_master_write, sff_bus_master_writew, sff_bus_master_writel, - dev); + if (dev->enabled && (dev->base != 0x0000)) { + io_removehandler(dev->base, 0x08, + sff_bus_master_read, sff_bus_master_readw, sff_bus_master_readl, + sff_bus_master_write, sff_bus_master_writew, sff_bus_master_writel, + dev); - dev->enabled = 0; + dev->enabled = 0; } dev->command = 0x00; - dev->status = 0x00; + dev->status = 0x00; dev->ptr = dev->ptr_cur = 0x00000000; - dev->addr = 0x00000000; - dev->ptr0 = 0x00; + dev->addr = 0x00000000; + dev->ptr0 = 0x00; dev->count = dev->eot = 0x00000000; + dev->irq_state = 0; ide_pri_disable(); ide_sec_disable(); } - static void -sff_reset(void *p) +sff_reset(void *priv) { - int i = 0; - #ifdef ENABLE_SFF_LOG sff_log("SFF8038i: Reset\n"); #endif - for (i = 0; i < CDROM_NUM; i++) { - if ((cdrom[i].bus_type == CDROM_BUS_ATAPI) && - (cdrom[i].ide_channel < 4) && cdrom[i].priv) - scsi_cdrom_reset((scsi_common_t *) cdrom[i].priv); + for (uint8_t i = 0; i < HDD_NUM; i++) { + if ((hdd[i].bus == HDD_BUS_ATAPI) && (hdd[i].ide_channel < 4) && hdd[i].priv) + scsi_disk_reset((scsi_common_t *) hdd[i].priv); } - for (i = 0; i < ZIP_NUM; i++) { - if ((zip_drives[i].bus_type == ZIP_BUS_ATAPI) && - (zip_drives[i].ide_channel < 4) && zip_drives[i].priv) - zip_reset((scsi_common_t *) zip_drives[i].priv); + for (uint8_t i = 0; i < CDROM_NUM; i++) { + if ((cdrom[i].bus_type == CDROM_BUS_ATAPI) && (cdrom[i].ide_channel < 4) && cdrom[i].priv) + scsi_cdrom_reset((scsi_common_t *) cdrom[i].priv); + } + for (uint8_t i = 0; i < ZIP_NUM; i++) { + if ((zip_drives[i].bus_type == ZIP_BUS_ATAPI) && (zip_drives[i].ide_channel < 4) && zip_drives[i].priv) + zip_reset((scsi_common_t *) zip_drives[i].priv); + } + for (uint8_t i = 0; i < MO_NUM; i++) { + if ((mo_drives[i].bus_type == MO_BUS_ATAPI) && (mo_drives[i].ide_channel < 4) && mo_drives[i].priv) + mo_reset((scsi_common_t *) mo_drives[i].priv); } - for (i = 0; i < MO_NUM; i++) { - if ((mo_drives[i].bus_type == MO_BUS_ATAPI) && - (mo_drives[i].ide_channel < 4) && mo_drives[i].priv) - mo_reset((scsi_common_t *) mo_drives[i].priv); - } - sff_bus_master_set_irq(0x00, p); - sff_bus_master_set_irq(0x01, p); + sff_bus_master_set_irq(0x00, priv); + sff_bus_master_set_irq(0x01, priv); } - void sff_set_slot(sff8038i_t *dev, int slot) { dev->slot = slot; } - void -sff_set_irq_line(sff8038i_t *dev, int irq_line) +sff_set_irq_line(sff8038i_t *dev, int pci_irq_line) { - dev->irq_line = irq_line; + dev->pci_irq_line = pci_irq_line; } - +/* TODO: Why does this always set the level to 0, regardless of the parameter?! */ void -sff_set_irq_level(sff8038i_t *dev, int channel, int irq_level) +sff_set_irq_level(sff8038i_t *dev, UNUSED(int irq_level)) { - dev->irq_level[channel] = 0; + dev->irq_level = 0; } - void -sff_set_irq_mode(sff8038i_t *dev, int channel, int irq_mode) +sff_set_irq_mode(sff8038i_t *dev, int irq_mode) { - dev->irq_mode[channel] = irq_mode; + dev->irq_mode = irq_mode; - switch (dev->irq_mode[channel]) { - case 0: - default: - /* Legacy IRQ mode. */ - sff_log("[%08X] Setting channel %i to legacy IRQ %i\n", dev, channel, 14 + channel); - break; - case 1: - /* Native PCI IRQ mode with interrupt pin. */ - sff_log("[%08X] Setting channel %i to native PCI INT%c\n", dev, channel, '@' + dev->irq_pin); - break; - case 2: - case 5: - /* MIRQ 0 or 1. */ - sff_log("[%08X] Setting channel %i to PCI MIRQ%i\n", dev, channel, irq_mode & 1); - break; - case 3: - /* Native PCI IRQ mode with specified interrupt line. */ - sff_log("[%08X] Setting channel %i to native PCI IRQ %i\n", dev, channel, dev->irq_line); - break; - case 4: - /* ALi Aladdin Native PCI INTAJ mode. */ - sff_log("[%08X] Setting channel %i to INT%cJ\n", dev, channel, 'A' + channel); - break; + switch (dev->irq_mode) { + default: + case IRQ_MODE_LEGACY: + /* Legacy IRQ mode. */ + sff_log("[%08X] Setting IRQ mode to legacy IRQ %i\n", dev, dev->irq_line); + break; + case IRQ_MODE_PCI_IRQ_PIN: + /* Native PCI IRQ mode with interrupt pin. */ + sff_log("[%08X] Setting IRQ mode to native PCI INT%c\n", dev, 0x40 + dev->irq_pin); + break; + case IRQ_MODE_MIRQ_0 ... IRQ_MODE_MIRQ_3: + /* MIRQ 0, 1, 2, or 3. */ + sff_log("[%08X] Setting IRQ mode to PCI MIRQ%i\n", dev, dev->irq_mode & 3); + break; + case IRQ_MODE_PCI_IRQ_LINE: + /* Native PCI IRQ mode with specified interrupt line. */ + sff_log("[%08X] Setting IRQ mode to native PCI IRQ %i\n", dev, dev->pci_irq_line); + break; + case IRQ_MODE_ALI_ALADDIN: + /* ALi Aladdin Native PCI INTAJ mode. */ + sff_log("[%08X] Setting IRQ mode to INT%cJ\n", dev, 'A' + dev->channel); + break; + case IRQ_MODE_SIS_551X: + /* SiS 551x mode. */ + sff_log("[%08X] Setting IRQ mode to PCI MIRQ2\n", dev); + break; } } - void sff_set_irq_pin(sff8038i_t *dev, int irq_pin) { dev->irq_pin = irq_pin; } - static void -sff_close(void *p) +sff_close(void *priv) { - sff8038i_t *dev = (sff8038i_t *)p; + sff8038i_t *dev = (sff8038i_t *) priv; free(dev); next_id--; if (next_id < 0) - next_id = 0; + next_id = 0; } - -static void -*sff_init(const device_t *info) +static void * +sff_init(UNUSED(const device_t *info)) { sff8038i_t *dev = (sff8038i_t *) malloc(sizeof(sff8038i_t)); memset(dev, 0, sizeof(sff8038i_t)); /* Make sure to only add IDE once. */ if (next_id == 0) - device_add(&ide_pci_2ch_device); + device_add(&ide_pci_2ch_device); ide_set_bus_master(next_id, sff_bus_master_dma, sff_bus_master_set_irq, dev); - dev->slot = 7; - dev->irq_mode[0] = 0; /* Channel 0 goes to IRQ 14. */ - dev->irq_mode[1] = 2; /* Channel 1 goes to MIRQ0. */ - dev->irq_pin = PCI_INTA; - dev->irq_line = 14; - dev->irq_level[0] = dev->irq_level[1] = 0; + dev->slot = 7; + /* Channel 0 goes to IRQ 14, channel 1 goes to MIRQ0. */ + dev->irq_mode = next_id ? IRQ_MODE_MIRQ_0 : IRQ_MODE_LEGACY; + dev->irq_pin = PCI_INTA; + dev->irq_line = 14 + next_id; + dev->pci_irq_line = 14; + dev->irq_level = 0; + dev->irq_state = 0; + dev->channel = next_id; next_id++; return dev; } - -const device_t sff8038i_device = -{ - "SFF-8038i IDE Bus Master", - "sff8038i", - DEVICE_PCI, - 0, - sff_init, - sff_close, - sff_reset, - { NULL }, - NULL, - NULL, - NULL +const device_t sff8038i_device = { + .name = "SFF-8038i IDE Bus Master", + .internal_name = "sff8038i", + .flags = DEVICE_PCI, + .local = 0, + .init = sff_init, + .close = sff_close, + .reset = sff_reset, + { .available = NULL }, + .speed_changed = NULL, + .force_redraw = NULL, + .config = NULL }; diff --git a/src/disk/hdc_st506_at.c b/src/disk/hdc_st506_at.c index e78871103..41499591d 100644 --- a/src/disk/hdc_st506_at.c +++ b/src/disk/hdc_st506_at.c @@ -1,28 +1,25 @@ /* - * 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. + * 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. + * This file is part of the 86Box distribution. * - * Driver for the IBM PC-AT MFM/RLL Fixed Disk controller. + * Driver for the IBM PC-AT MFM/RLL Fixed Disk controller. * - * This controller was a 16bit ISA card, and it used a WD1003 - * based design. Most cards were WD1003-WA2 or -WAH, where the - * -WA2 cards had a floppy controller as well (to save space.) + * This controller was a 16bit ISA card, and it used a WD1003 + * based design. Most cards were WD1003-WA2 or -WAH, where the + * -WA2 cards had a floppy controller as well (to save space.) * * * - * Authors: Sarah Walker, - * Fred N. van Kempen, + * Authors: Sarah Walker, + * Fred N. van Kempen, * - * Copyright 2008-2019 Sarah Walker. - * Copyright 2017-2019 Fred N. van Kempen. + * Copyright 2008-2019 Sarah Walker. + * Copyright 2017-2019 Fred N. van Kempen. */ -#define __USE_LARGEFILE64 -#define _LARGEFILE_SOURCE -#define _LARGEFILE64_SOURCE #include #include #include @@ -42,8 +39,7 @@ #include <86box/hdc.h> #include <86box/hdd.h> - -#define MFM_TIME (TIMER_USEC*10) +#define MFM_TIME (TIMER_USEC * 10) /*Rough estimate - MFM drives spin at 3600 RPM, with 17 sectors per track, meaning (3600/60)*17 = 1020 sectors per second, or 980us per sector. @@ -51,125 +47,115 @@ This is required for OS/2 on slow 286 systems, as the hard drive formatter will crash with 'internal processing error' if write sector interrupts are too close in time*/ -#define SECTOR_TIME (TIMER_USEC * 980) +#define SECTOR_TIME (TIMER_USEC * 980) -#define STAT_ERR 0x01 -#define STAT_INDEX 0x02 -#define STAT_ECC 0x04 -#define STAT_DRQ 0x08 /* data request */ -#define STAT_DSC 0x10 -#define STAT_WRFLT 0x20 -#define STAT_READY 0x40 -#define STAT_BUSY 0x80 +#define STAT_ERR 0x01 +#define STAT_INDEX 0x02 +#define STAT_ECC 0x04 +#define STAT_DRQ 0x08 /* data request */ +#define STAT_DSC 0x10 +#define STAT_WRFLT 0x20 +#define STAT_READY 0x40 +#define STAT_BUSY 0x80 -#define ERR_DAM_NOT_FOUND 0x01 /* Data Address Mark not found */ -#define ERR_TR000 0x02 /* track 0 not found */ -#define ERR_ABRT 0x04 /* command aborted */ -#define ERR_ID_NOT_FOUND 0x10 /* ID not found */ -#define ERR_DATA_CRC 0x40 /* data CRC error */ -#define ERR_BAD_BLOCK 0x80 /* bad block detected */ +#define ERR_DAM_NOT_FOUND 0x01 /* Data Address Mark not found */ +#define ERR_TR000 0x02 /* track 0 not found */ +#define ERR_ABRT 0x04 /* command aborted */ +#define ERR_ID_NOT_FOUND 0x10 /* ID not found */ +#define ERR_DATA_CRC 0x40 /* data CRC error */ +#define ERR_BAD_BLOCK 0x80 /* bad block detected */ -#define CMD_RESTORE 0x10 -#define CMD_READ 0x20 -#define CMD_WRITE 0x30 -#define CMD_VERIFY 0x40 -#define CMD_FORMAT 0x50 -#define CMD_SEEK 0x70 -#define CMD_DIAGNOSE 0x90 -#define CMD_SET_PARAMETERS 0x91 +#define CMD_RESTORE 0x10 +#define CMD_READ 0x20 +#define CMD_WRITE 0x30 +#define CMD_VERIFY 0x40 +#define CMD_FORMAT 0x50 +#define CMD_SEEK 0x70 +#define CMD_DIAGNOSE 0x90 +#define CMD_SET_PARAMETERS 0x91 +typedef struct drive_t { + int8_t present; /* drive is present */ + int8_t hdd_num; /* drive number in system */ + int8_t steprate; /* current servo step rate */ + int8_t spt; /* physical #sectors per track */ + int8_t hpc; /* physical #heads per cylinder */ + int8_t pad; + int16_t tracks; /* physical #tracks per cylinder */ -typedef struct { - int8_t present, /* drive is present */ - hdd_num, /* drive number in system */ - steprate, /* current servo step rate */ - spt, /* physical #sectors per track */ - hpc, /* physical #heads per cylinder */ - pad; - int16_t tracks; /* physical #tracks per cylinder */ + int8_t cfg_spt; /* configured #sectors per track */ + int8_t cfg_hpc; /* configured #heads per track */ - int8_t cfg_spt, /* configured #sectors per track */ - cfg_hpc; /* configured #heads per track */ - - int16_t curcyl; /* current track number */ + int16_t curcyl; /* current track number */ } drive_t; +typedef struct mfm_t { + uint8_t precomp; /* 1: precomp/error register */ + uint8_t error; + uint8_t secount; /* 2: sector count register */ + uint8_t sector; /* 3: sector number */ + uint8_t head; /* 6: head number + drive select */ + uint8_t command; /* 7: command/status */ + uint8_t status; + uint8_t fdisk; /* 8: control register */ + uint16_t cylinder; /* 4/5: cylinder LOW and HIGH */ -typedef struct { - uint8_t precomp, /* 1: precomp/error register */ - error, - secount, /* 2: sector count register */ - sector, /* 3: sector number */ - head, /* 6: head number + drive select */ - command, /* 7: command/status */ - status, - fdisk; /* 8: control register */ - uint16_t cylinder; /* 4/5: cylinder LOW and HIGH */ + int8_t reset; /* controller in reset */ + int8_t irqstat; /* current IRQ status */ + int8_t drvsel; /* current selected drive */ + int8_t pad; - int8_t reset, /* controller in reset */ - irqstat, /* current IRQ status */ - drvsel, /* current selected drive */ - pad; + int pos; /* offset within data buffer */ + pc_timer_t callback_timer; /* callback delay timer */ - int pos; /* offset within data buffer */ - pc_timer_t callback_timer; /* callback delay timer */ + uint16_t buffer[256]; /* data buffer (16b wide) */ - uint16_t buffer[256]; /* data buffer (16b wide) */ - - drive_t drives[MFM_NUM]; /* attached drives */ + drive_t drives[MFM_NUM]; /* attached drives */ } mfm_t; - -static uint8_t mfm_read(uint16_t port, void *priv); -static void mfm_write(uint16_t port, uint8_t val, void *priv); - +static uint8_t mfm_read(uint16_t port, void *priv); +static void mfm_write(uint16_t port, uint8_t val, void *priv); #ifdef ENABLE_ST506_AT_LOG int st506_at_do_log = ENABLE_ST506_AT_LOG; - static void st506_at_log(const char *fmt, ...) { va_list ap; if (st506_at_do_log) { - va_start(ap, fmt); - pclog_ex(fmt, ap); - va_end(ap); + va_start(ap, fmt); + pclog_ex(fmt, ap); + va_end(ap); } } #else -#define st506_at_log(fmt, ...) +# define st506_at_log(fmt, ...) #endif - static inline void irq_raise(mfm_t *mfm) { if (!(mfm->fdisk & 2)) - picint(1 << 14); + picint(1 << 14); mfm->irqstat = 1; } - static inline void -irq_lower(mfm_t *mfm) +irq_lower(UNUSED(mfm_t *mfm)) { picintc(1 << 14); } - - static void irq_update(mfm_t *mfm) { if (mfm->irqstat && !((pic2.irr | pic2.isr) & 0x40) && !(mfm->fdisk & 2)) - picint(1 << 14); + picint(1 << 14); } - /* * Return the sector offset for the current register values. * @@ -185,594 +171,589 @@ irq_update(mfm_t *mfm) static int get_sector(mfm_t *mfm, off64_t *addr) { - drive_t *drive = &mfm->drives[mfm->drvsel]; + const drive_t *drive = &mfm->drives[mfm->drvsel]; -/* FIXME: See if this is even needed - if the code is present, IBM AT - diagnostics v2.07 will error with: ERROR 152 - SYSTEM BOARD. */ + /* FIXME: See if this is even needed - if the code is present, IBM AT + diagnostics v2.07 will error with: ERROR 152 - SYSTEM BOARD. */ if (drive->curcyl != mfm->cylinder) { - st506_at_log("WD1003(%d) sector: wrong cylinder\n"); - return(1); + st506_at_log("WD1003(%d) sector: wrong cylinder\n"); + return 1; } if (mfm->head > drive->cfg_hpc) { - st506_at_log("WD1003(%d) get_sector: past end of configured heads\n", - mfm->drvsel); - return(1); + st506_at_log("WD1003(%d) get_sector: past end of configured heads\n", + mfm->drvsel); + return 1; } - if (mfm->sector >= drive->cfg_spt+1) { - st506_at_log("WD1003(%d) get_sector: past end of configured sectors\n", - mfm->drvsel); - return(1); + if (mfm->sector >= drive->cfg_spt + 1) { + st506_at_log("WD1003(%d) get_sector: past end of configured sectors\n", + mfm->drvsel); + return 1; } /* We should check this in the SET_DRIVE_PARAMETERS command! --FvK */ if (mfm->head > drive->hpc) { - st506_at_log("WD1003(%d) get_sector: past end of heads\n", mfm->drvsel); - return(1); + st506_at_log("WD1003(%d) get_sector: past end of heads\n", mfm->drvsel); + return 1; } - if (mfm->sector >= drive->spt+1) { - st506_at_log("WD1003(%d) get_sector: past end of sectors\n", mfm->drvsel); - return(1); + if (mfm->sector >= drive->spt + 1) { + st506_at_log("WD1003(%d) get_sector: past end of sectors\n", mfm->drvsel); + return 1; } - *addr = ((((off64_t) mfm->cylinder * drive->cfg_hpc) + mfm->head) * - drive->cfg_spt) + (mfm->sector - 1); + *addr = ((((off64_t) mfm->cylinder * drive->cfg_hpc) + mfm->head) * drive->cfg_spt) + (mfm->sector - 1); - return(0); + return 0; } - /* Move to the next sector using CHS addressing. */ static void next_sector(mfm_t *mfm) { drive_t *drive = &mfm->drives[mfm->drvsel]; - if (++mfm->sector == (drive->cfg_spt+1)) { - mfm->sector = 1; - if (++mfm->head == drive->cfg_hpc) { - mfm->head = 0; - mfm->cylinder++; - if (drive->curcyl < drive->tracks) - drive->curcyl++; - } + if (++mfm->sector == (drive->cfg_spt + 1)) { + mfm->sector = 1; + if (++mfm->head == drive->cfg_hpc) { + mfm->head = 0; + mfm->cylinder++; + if (drive->curcyl < drive->tracks) + drive->curcyl++; + } } } - static void mfm_cmd(mfm_t *mfm, uint8_t val) { drive_t *drive = &mfm->drives[mfm->drvsel]; - if (! drive->present) { - /* This happens if sofware polls all drives. */ - st506_at_log("WD1003(%d) command %02x on non-present drive\n", - mfm->drvsel, val); - mfm->command = 0xff; - mfm->status = STAT_BUSY; - timer_set_delay_u64(&mfm->callback_timer, 200 * MFM_TIME); - return; + if (!drive->present) { + /* This happens if sofware polls all drives. */ + st506_at_log("WD1003(%d) command %02x on non-present drive\n", + mfm->drvsel, val); + mfm->command = 0xff; + mfm->status = STAT_BUSY; + timer_set_delay_u64(&mfm->callback_timer, 200 * MFM_TIME); + return; } irq_lower(mfm); mfm->command = val; - mfm->error = 0; + mfm->error = 0; switch (val & 0xf0) { - case CMD_RESTORE: - drive->steprate = (val & 0x0f); - st506_at_log("WD1003(%d) restore, step=%d\n", - mfm->drvsel, drive->steprate); - drive->curcyl = 0; - mfm->cylinder = 0; - mfm->status = STAT_READY|STAT_DSC; - mfm->command &= 0xf0; - irq_raise(mfm); - break; + case CMD_RESTORE: + drive->steprate = (val & 0x0f); + st506_at_log("WD1003(%d) restore, step=%d\n", + mfm->drvsel, drive->steprate); + drive->curcyl = 0; + mfm->cylinder = 0; + mfm->status = STAT_READY | STAT_DSC; + mfm->command &= 0xf0; + irq_raise(mfm); + break; - case CMD_SEEK: - drive->steprate = (val & 0x0f); - mfm->command &= 0xf0; - mfm->status = STAT_BUSY; - timer_set_delay_u64(&mfm->callback_timer, 200 * MFM_TIME); - break; + case CMD_SEEK: + drive->steprate = (val & 0x0f); + mfm->command &= 0xf0; + mfm->status = STAT_BUSY; + timer_set_delay_u64(&mfm->callback_timer, 200 * MFM_TIME); + break; - default: - mfm->command = val; - switch (val) { - case CMD_READ: - case CMD_READ+1: - case CMD_READ+2: - case CMD_READ+3: - st506_at_log("WD1003(%d) read, opt=%d\n", - mfm->drvsel, val&0x03); - mfm->command &= 0xfc; - if (val & 2) - fatal("WD1003: READ with ECC\n"); - mfm->status = STAT_BUSY; - timer_set_delay_u64(&mfm->callback_timer, 200 * MFM_TIME); - break; + default: + mfm->command = val; + switch (val) { + case CMD_READ: + case CMD_READ + 1: + case CMD_READ + 2: + case CMD_READ + 3: + st506_at_log("WD1003(%d) read, opt=%d\n", + mfm->drvsel, val & 0x03); + mfm->command &= 0xfc; + if (val & 2) + fatal("WD1003: READ with ECC\n"); + mfm->status = STAT_BUSY; + timer_set_delay_u64(&mfm->callback_timer, 200 * MFM_TIME); + break; - case CMD_WRITE: - case CMD_WRITE+1: - case CMD_WRITE+2: - case CMD_WRITE+3: - st506_at_log("WD1003(%d) write, opt=%d\n", - mfm->drvsel, val & 0x03); - mfm->command &= 0xfc; - if (val & 2) - fatal("WD1003: WRITE with ECC\n"); - mfm->status = STAT_READY|STAT_DRQ|STAT_DSC; - mfm->pos = 0; - break; + case CMD_WRITE: + case CMD_WRITE + 1: + case CMD_WRITE + 2: + case CMD_WRITE + 3: + st506_at_log("WD1003(%d) write, opt=%d\n", + mfm->drvsel, val & 0x03); + mfm->command &= 0xfc; + if (val & 2) + fatal("WD1003: WRITE with ECC\n"); + mfm->status = STAT_READY | STAT_DRQ | STAT_DSC; + mfm->pos = 0; + break; - case CMD_VERIFY: - case CMD_VERIFY+1: - mfm->command &= 0xfe; - mfm->status = STAT_BUSY; - timer_set_delay_u64(&mfm->callback_timer, 200 * MFM_TIME); - break; + case CMD_VERIFY: + case CMD_VERIFY + 1: + mfm->command &= 0xfe; + mfm->status = STAT_BUSY; + timer_set_delay_u64(&mfm->callback_timer, 200 * MFM_TIME); + break; - case CMD_FORMAT: - mfm->status = STAT_DRQ|STAT_BUSY; - mfm->pos = 0; - break; + case CMD_FORMAT: + mfm->status = STAT_DRQ | STAT_BUSY; + mfm->pos = 0; + break; - case CMD_DIAGNOSE: - mfm->status = STAT_BUSY; - timer_set_delay_u64(&mfm->callback_timer, 200 * MFM_TIME); - break; + case CMD_DIAGNOSE: + mfm->status = STAT_BUSY; + timer_set_delay_u64(&mfm->callback_timer, 200 * MFM_TIME); + break; - case CMD_SET_PARAMETERS: - /* - * NOTE: - * - * We currently just set these parameters, and - * never bother to check if they "fit within" - * the actual parameters, as determined by the - * image loader. - * - * The difference in parameters is OK, and - * occurs when the BIOS or operating system - * decides to use a different translation - * scheme, but either way, it SHOULD always - * fit within the actual parameters! - * - * We SHOULD check that here!! --FvK - */ - if (drive->cfg_spt == 0) { - /* Only accept after RESET or DIAG. */ - drive->cfg_spt = mfm->secount; - drive->cfg_hpc = mfm->head+1; - st506_at_log("WD1003(%d) parameters: tracks=%d, spt=%i, hpc=%i\n", - mfm->drvsel, drive->tracks, - drive->cfg_spt, drive->cfg_hpc); - } else { - st506_at_log("WD1003(%d) parameters: tracks=%d,spt=%i,hpc=%i (IGNORED)\n", - mfm->drvsel, drive->tracks, - drive->cfg_spt, drive->cfg_hpc); - } - mfm->command = 0x00; - mfm->status = STAT_READY|STAT_DSC; - mfm->error = 1; - irq_raise(mfm); - break; + case CMD_SET_PARAMETERS: + /* + * NOTE: + * + * We currently just set these parameters, and + * never bother to check if they "fit within" + * the actual parameters, as determined by the + * image loader. + * + * The difference in parameters is OK, and + * occurs when the BIOS or operating system + * decides to use a different translation + * scheme, but either way, it SHOULD always + * fit within the actual parameters! + * + * We SHOULD check that here!! --FvK + */ + if (drive->cfg_spt == 0) { + /* Only accept after RESET or DIAG. */ + drive->cfg_spt = mfm->secount; + drive->cfg_hpc = mfm->head + 1; + st506_at_log("WD1003(%d) parameters: tracks=%d, spt=%i, hpc=%i\n", + mfm->drvsel, drive->tracks, + drive->cfg_spt, drive->cfg_hpc); + } else { + st506_at_log("WD1003(%d) parameters: tracks=%d,spt=%i,hpc=%i (IGNORED)\n", + mfm->drvsel, drive->tracks, + drive->cfg_spt, drive->cfg_hpc); + } + mfm->command = 0x00; + mfm->status = STAT_READY | STAT_DSC; + mfm->error = 1; + irq_raise(mfm); + break; - default: - st506_at_log("WD1003: bad command %02X\n", val); - mfm->status = STAT_BUSY; - timer_set_delay_u64(&mfm->callback_timer, 200 * MFM_TIME); - break; - } + default: + st506_at_log("WD1003: bad command %02X\n", val); + mfm->status = STAT_BUSY; + timer_set_delay_u64(&mfm->callback_timer, 200 * MFM_TIME); + break; + } } } - static void mfm_writew(uint16_t port, uint16_t val, void *priv) { - mfm_t *mfm = (mfm_t *)priv; + mfm_t *mfm = (mfm_t *) priv; if (port > 0x01f0) { - mfm_write(port, val & 0xff, priv); - if (port != 0x01f7) - mfm_write(port + 1, (val >> 8) & 0xff, priv); + mfm_write(port, val & 0xff, priv); + if (port != 0x01f7) + mfm_write(port + 1, (val >> 8) & 0xff, priv); } else { - mfm->buffer[mfm->pos >> 1] = val; - mfm->pos += 2; + mfm->buffer[mfm->pos >> 1] = val; + mfm->pos += 2; - if (mfm->pos >= 512) { - mfm->pos = 0; - mfm->status = STAT_BUSY; - timer_set_delay_u64(&mfm->callback_timer, SECTOR_TIME); - } + if (mfm->pos >= 512) { + mfm->pos = 0; + mfm->status = STAT_BUSY; + timer_set_delay_u64(&mfm->callback_timer, SECTOR_TIME); + } } } - static void mfm_write(uint16_t port, uint8_t val, void *priv) { - mfm_t *mfm = (mfm_t *)priv; + mfm_t *mfm = (mfm_t *) priv; st506_at_log("WD1003 write(%04x, %02x)\n", port, val); switch (port) { - case 0x01f0: /* data */ - mfm_writew(port, val | (val << 8), priv); - return; + case 0x01f0: /* data */ + mfm_writew(port, val | (val << 8), priv); + return; - case 0x01f1: /* write precompenstation */ - mfm->precomp = val; - return; + case 0x01f1: /* write precompenstation */ + mfm->precomp = val; + return; - case 0x01f2: /* sector count */ - mfm->secount = val; - return; + case 0x01f2: /* sector count */ + mfm->secount = val; + return; - case 0x01f3: /* sector */ - mfm->sector = val; - return; + case 0x01f3: /* sector */ + mfm->sector = val; + return; - case 0x01f4: /* cylinder low */ - mfm->cylinder = (mfm->cylinder & 0xff00) | val; - return; + case 0x01f4: /* cylinder low */ + mfm->cylinder = (mfm->cylinder & 0xff00) | val; + return; - case 0x01f5: /* cylinder high */ - mfm->cylinder = (mfm->cylinder & 0xff) | (val << 8); - return; + case 0x01f5: /* cylinder high */ + mfm->cylinder = (mfm->cylinder & 0xff) | (val << 8); + return; - case 0x01f6: /* drive/head */ - mfm->head = val & 0xF; - mfm->drvsel = (val & 0x10) ? 1 : 0; - if (mfm->drives[mfm->drvsel].present) - mfm->status = STAT_READY|STAT_DSC; - else - mfm->status = 0; - return; + case 0x01f6: /* drive/head */ + mfm->head = val & 0xF; + mfm->drvsel = (val & 0x10) ? 1 : 0; + if (mfm->drives[mfm->drvsel].present) + mfm->status = STAT_READY | STAT_DSC; + else + mfm->status = 0; + return; - case 0x01f7: /* command register */ - mfm_cmd(mfm, val); - break; + case 0x01f7: /* command register */ + mfm_cmd(mfm, val); + break; - case 0x03f6: /* device control */ - val &= 0x0f; - if ((mfm->fdisk & 0x04) && !(val & 0x04)) { - timer_set_delay_u64(&mfm->callback_timer, 500 * MFM_TIME); - mfm->reset = 1; - mfm->status = STAT_BUSY; - } + case 0x03f6: /* device control */ + val &= 0x0f; + if ((mfm->fdisk & 0x04) && !(val & 0x04)) { + timer_set_delay_u64(&mfm->callback_timer, 500 * MFM_TIME); + mfm->reset = 1; + mfm->status = STAT_BUSY; + } - if (val & 0x04) { - /* Drive held in reset. */ - timer_disable(&mfm->callback_timer); - mfm->status = STAT_BUSY; - } - mfm->fdisk = val; - irq_update(mfm); - break; + if (val & 0x04) { + /* Drive held in reset. */ + timer_disable(&mfm->callback_timer); + mfm->status = STAT_BUSY; + } + mfm->fdisk = val; + irq_update(mfm); + break; + + default: + break; } } - static uint16_t mfm_readw(uint16_t port, void *priv) { - mfm_t *mfm = (mfm_t *)priv; + mfm_t *mfm = (mfm_t *) priv; uint16_t ret; if (port > 0x01f0) { - ret = mfm_read(port, priv); - if (port == 0x01f7) - ret |= 0xff00; - else - ret |= (mfm_read(port + 1, priv) << 8); + ret = mfm_read(port, priv); + if (port == 0x01f7) + ret |= 0xff00; + else + ret |= (mfm_read(port + 1, priv) << 8); } else { - ret = mfm->buffer[mfm->pos >> 1]; - mfm->pos += 2; - if (mfm->pos >= 512) { - mfm->pos = 0; - mfm->status = STAT_READY|STAT_DSC; - if (mfm->command == CMD_READ) { - mfm->secount = (mfm->secount - 1) & 0xff; - if (mfm->secount) { - next_sector(mfm); - mfm->status = STAT_BUSY | STAT_READY | STAT_DSC; - timer_set_delay_u64(&mfm->callback_timer, SECTOR_TIME); - } else - ui_sb_update_icon(SB_HDD|HDD_BUS_MFM, 0); - } - } + ret = mfm->buffer[mfm->pos >> 1]; + mfm->pos += 2; + if (mfm->pos >= 512) { + mfm->pos = 0; + mfm->status = STAT_READY | STAT_DSC; + if (mfm->command == CMD_READ) { + mfm->secount = (mfm->secount - 1) & 0xff; + if (mfm->secount) { + next_sector(mfm); + mfm->status = STAT_BUSY | STAT_READY | STAT_DSC; + timer_set_delay_u64(&mfm->callback_timer, SECTOR_TIME); + } else + ui_sb_update_icon(SB_HDD | HDD_BUS_MFM, 0); + } + } } - return(ret); + return ret; } - static uint8_t mfm_read(uint16_t port, void *priv) { - mfm_t *mfm = (mfm_t *)priv; + mfm_t *mfm = (mfm_t *) priv; uint8_t ret = 0xff; switch (port) { - case 0x01f0: /* data */ - ret = mfm_readw(port, mfm) & 0xff; - break; + case 0x01f0: /* data */ + ret = mfm_readw(port, mfm) & 0xff; + break; - case 0x01f1: /* error */ - ret = mfm->error; - break; + case 0x01f1: /* error */ + ret = mfm->error; + break; - case 0x01f2: /* sector count */ - ret = mfm->secount; - break; + case 0x01f2: /* sector count */ + ret = mfm->secount; + break; - case 0x01f3: /* sector */ - ret = mfm->sector; - break; + case 0x01f3: /* sector */ + ret = mfm->sector; + break; - case 0x01f4: /* CYlinder low */ - ret = (uint8_t)(mfm->cylinder&0xff); - break; + case 0x01f4: /* CYlinder low */ + ret = (uint8_t) (mfm->cylinder & 0xff); + break; - case 0x01f5: /* Cylinder high */ - ret = (uint8_t)(mfm->cylinder>>8); - break; + case 0x01f5: /* Cylinder high */ + ret = (uint8_t) (mfm->cylinder >> 8); + break; - case 0x01f6: /* drive/head */ - ret = (uint8_t)(0xa0 | mfm->head | (mfm->drvsel?0x10:0)); - break; + case 0x01f6: /* drive/head */ + ret = (uint8_t) (0xa0 | mfm->head | (mfm->drvsel ? 0x10 : 0)); + break; - case 0x01f7: /* Status */ - irq_lower(mfm); - ret = mfm->status; - break; + case 0x01f7: /* Status */ + irq_lower(mfm); + ret = mfm->status; + break; - default: - break; + default: + break; } st506_at_log("WD1003 read(%04x) = %02x\n", port, ret); - return(ret); + return ret; } - static void do_seek(mfm_t *mfm) { drive_t *drive = &mfm->drives[mfm->drvsel]; st506_at_log("WD1003(%d) seek(%d) max=%d\n", - mfm->drvsel,mfm->cylinder,drive->tracks); + mfm->drvsel, mfm->cylinder, drive->tracks); if (mfm->cylinder < drive->tracks) - drive->curcyl = mfm->cylinder; - else - drive->curcyl = drive->tracks-1; + drive->curcyl = mfm->cylinder; + else + drive->curcyl = drive->tracks - 1; } - static void do_callback(void *priv) { - mfm_t *mfm = (mfm_t *)priv; + mfm_t *mfm = (mfm_t *) priv; drive_t *drive = &mfm->drives[mfm->drvsel]; - off64_t addr; + off64_t addr; if (mfm->reset) { - st506_at_log("WD1003(%d) reset\n", mfm->drvsel); + st506_at_log("WD1003(%d) reset\n", mfm->drvsel); - mfm->status = STAT_READY|STAT_DSC; - mfm->error = 1; - mfm->secount = 1; - mfm->sector = 1; - mfm->head = 0; - mfm->cylinder = 0; + mfm->status = STAT_READY | STAT_DSC; + mfm->error = 1; + mfm->secount = 1; + mfm->sector = 1; + mfm->head = 0; + mfm->cylinder = 0; - drive->steprate = 0x0f; /* default steprate */ - drive->cfg_spt = 0; /* need new parameters */ + drive->steprate = 0x0f; /* default steprate */ + drive->cfg_spt = 0; /* need new parameters */ - mfm->reset = 0; + mfm->reset = 0; - ui_sb_update_icon(SB_HDD|HDD_BUS_MFM, 0); + ui_sb_update_icon(SB_HDD | HDD_BUS_MFM, 0); - return; + return; } switch (mfm->command) { - case CMD_SEEK: - st506_at_log("WD1003(%d) seek, step=%d\n", - mfm->drvsel, drive->steprate); - do_seek(mfm); - mfm->status = STAT_READY|STAT_DSC; - irq_raise(mfm); - break; + case CMD_SEEK: + st506_at_log("WD1003(%d) seek, step=%d\n", + mfm->drvsel, drive->steprate); + do_seek(mfm); + mfm->status = STAT_READY | STAT_DSC; + irq_raise(mfm); + break; - case CMD_READ: - st506_at_log("WD1003(%d) read(%d,%d,%d)\n", - mfm->drvsel, mfm->cylinder, mfm->head, mfm->sector); - do_seek(mfm); - if (get_sector(mfm, &addr)) { - mfm->error = ERR_ID_NOT_FOUND; - mfm->status = STAT_READY|STAT_DSC|STAT_ERR; - irq_raise(mfm); - break; - } + case CMD_READ: + st506_at_log("WD1003(%d) read(%d,%d,%d)\n", + mfm->drvsel, mfm->cylinder, mfm->head, mfm->sector); + do_seek(mfm); + if (get_sector(mfm, &addr)) { + mfm->error = ERR_ID_NOT_FOUND; + mfm->status = STAT_READY | STAT_DSC | STAT_ERR; + irq_raise(mfm); + break; + } - hdd_image_read(drive->hdd_num, addr, 1, (uint8_t *)mfm->buffer); + hdd_image_read(drive->hdd_num, addr, 1, (uint8_t *) mfm->buffer); - mfm->pos = 0; - mfm->status = STAT_DRQ|STAT_READY|STAT_DSC; - irq_raise(mfm); - ui_sb_update_icon(SB_HDD|HDD_BUS_MFM, 1); - break; + mfm->pos = 0; + mfm->status = STAT_DRQ | STAT_READY | STAT_DSC; + irq_raise(mfm); + ui_sb_update_icon(SB_HDD | HDD_BUS_MFM, 1); + break; - case CMD_WRITE: - st506_at_log("WD1003(%d) write(%d,%d,%d)\n", - mfm->drvsel, mfm->cylinder, mfm->head, mfm->sector); - do_seek(mfm); - if (get_sector(mfm, &addr)) { - mfm->error = ERR_ID_NOT_FOUND; - mfm->status = STAT_READY|STAT_DSC|STAT_ERR; - irq_raise(mfm); - break; - } + case CMD_WRITE: + st506_at_log("WD1003(%d) write(%d,%d,%d)\n", + mfm->drvsel, mfm->cylinder, mfm->head, mfm->sector); + do_seek(mfm); + if (get_sector(mfm, &addr)) { + mfm->error = ERR_ID_NOT_FOUND; + mfm->status = STAT_READY | STAT_DSC | STAT_ERR; + irq_raise(mfm); + break; + } - hdd_image_write(drive->hdd_num, addr, 1,(uint8_t *)mfm->buffer); - irq_raise(mfm); - mfm->secount = (mfm->secount - 1) & 0xff; + hdd_image_write(drive->hdd_num, addr, 1, (uint8_t *) mfm->buffer); + irq_raise(mfm); + mfm->secount = (mfm->secount - 1) & 0xff; - mfm->status = STAT_READY|STAT_DSC; - if (mfm->secount) { - /* More sectors to do.. */ - mfm->status |= STAT_DRQ; - mfm->pos = 0; - next_sector(mfm); - ui_sb_update_icon(SB_HDD|HDD_BUS_MFM, 1); - } else - ui_sb_update_icon(SB_HDD|HDD_BUS_MFM, 0); - break; + mfm->status = STAT_READY | STAT_DSC; + if (mfm->secount) { + /* More sectors to do.. */ + mfm->status |= STAT_DRQ; + mfm->pos = 0; + next_sector(mfm); + ui_sb_update_icon(SB_HDD | HDD_BUS_MFM, 1); + } else + ui_sb_update_icon(SB_HDD | HDD_BUS_MFM, 0); + break; - case CMD_VERIFY: - st506_at_log("WD1003(%d) verify(%d,%d,%d)\n", - mfm->drvsel, mfm->cylinder, mfm->head, mfm->sector); - do_seek(mfm); - mfm->pos = 0; - mfm->status = STAT_READY|STAT_DSC; - irq_raise(mfm); - ui_sb_update_icon(SB_HDD|HDD_BUS_MFM, 1); - break; + case CMD_VERIFY: + st506_at_log("WD1003(%d) verify(%d,%d,%d)\n", + mfm->drvsel, mfm->cylinder, mfm->head, mfm->sector); + do_seek(mfm); + mfm->pos = 0; + mfm->status = STAT_READY | STAT_DSC; + irq_raise(mfm); + ui_sb_update_icon(SB_HDD | HDD_BUS_MFM, 1); + break; - case CMD_FORMAT: - st506_at_log("WD1003(%d) format(%d,%d)\n", - mfm->drvsel, mfm->cylinder, mfm->head); - do_seek(mfm); - if (get_sector(mfm, &addr)) { - mfm->error = ERR_ID_NOT_FOUND; - mfm->status = STAT_READY|STAT_DSC|STAT_ERR; - irq_raise(mfm); - break; - } + case CMD_FORMAT: + st506_at_log("WD1003(%d) format(%d,%d)\n", + mfm->drvsel, mfm->cylinder, mfm->head); + do_seek(mfm); + if (get_sector(mfm, &addr)) { + mfm->error = ERR_ID_NOT_FOUND; + mfm->status = STAT_READY | STAT_DSC | STAT_ERR; + irq_raise(mfm); + break; + } - hdd_image_zero(drive->hdd_num, addr, mfm->secount); + hdd_image_zero(drive->hdd_num, addr, mfm->secount); - mfm->status = STAT_READY|STAT_DSC; - irq_raise(mfm); - ui_sb_update_icon(SB_HDD|HDD_BUS_MFM, 1); - break; + mfm->status = STAT_READY | STAT_DSC; + irq_raise(mfm); + ui_sb_update_icon(SB_HDD | HDD_BUS_MFM, 1); + break; - case CMD_DIAGNOSE: - st506_at_log("WD1003(%d) diag\n", mfm->drvsel); + case CMD_DIAGNOSE: + st506_at_log("WD1003(%d) diag\n", mfm->drvsel); - /* This is basically controller diagnostics - it resets drive select to 0, - and resets error and status to ready, DSC, and no error detected. */ - mfm->drvsel = 0; - drive = &mfm->drives[mfm->drvsel]; + /* This is basically controller diagnostics - it resets drive select to 0, + and resets error and status to ready, DSC, and no error detected. */ + mfm->drvsel = 0; + drive = &mfm->drives[mfm->drvsel]; - drive->steprate = 0x0f; - mfm->error = 1; - mfm->status = STAT_READY|STAT_DSC; - irq_raise(mfm); - break; + drive->steprate = 0x0f; + mfm->error = 1; + mfm->status = STAT_READY | STAT_DSC; + irq_raise(mfm); + break; - default: - st506_at_log("WD1003(%d) callback on unknown command %02x\n", - mfm->drvsel, mfm->command); - mfm->status = STAT_READY|STAT_ERR|STAT_DSC; - mfm->error = ERR_ABRT; - irq_raise(mfm); - break; + default: + st506_at_log("WD1003(%d) callback on unknown command %02x\n", + mfm->drvsel, mfm->command); + mfm->status = STAT_READY | STAT_ERR | STAT_DSC; + mfm->error = ERR_ABRT; + irq_raise(mfm); + break; } } - static void -loadhd(mfm_t *mfm, int c, int d, const char *fn) +loadhd(mfm_t *mfm, int c, int d, UNUSED(const char *fn)) { drive_t *drive = &mfm->drives[c]; - if (! hdd_image_load(d)) { - drive->present = 0; + if (!hdd_image_load(d)) { + drive->present = 0; - return; + return; } - drive->spt = hdd[d].spt; - drive->hpc = hdd[d].hpc; - drive->tracks = hdd[d].tracks; + drive->spt = hdd[d].spt; + drive->hpc = hdd[d].hpc; + drive->tracks = hdd[d].tracks; drive->hdd_num = d; drive->present = 1; } - static void * -mfm_init(const device_t *info) +mfm_init(UNUSED(const device_t *info)) { mfm_t *mfm; - int c, d; + int c; st506_at_log("WD1003: ISA MFM/RLL Fixed Disk Adapter initializing ...\n"); mfm = malloc(sizeof(mfm_t)); memset(mfm, 0x00, sizeof(mfm_t)); c = 0; - for (d=0; d= MFM_NUM) break; - } + if (++c >= MFM_NUM) + break; + } } - mfm->status = STAT_READY|STAT_DSC; /* drive is ready */ - mfm->error = 1; /* no errors */ + mfm->status = STAT_READY | STAT_DSC; /* drive is ready */ + mfm->error = 1; /* no errors */ io_sethandler(0x01f0, 1, - mfm_read, mfm_readw, NULL, mfm_write, mfm_writew, NULL, mfm); + mfm_read, mfm_readw, NULL, mfm_write, mfm_writew, NULL, mfm); io_sethandler(0x01f1, 7, - mfm_read, mfm_readw, NULL, mfm_write, mfm_writew, NULL, mfm); + mfm_read, mfm_readw, NULL, mfm_write, mfm_writew, NULL, mfm); io_sethandler(0x03f6, 1, - NULL, NULL, NULL, mfm_write, NULL, NULL, mfm); + NULL, NULL, NULL, mfm_write, NULL, NULL, mfm); - timer_add(&mfm->callback_timer, do_callback, mfm, 0); + timer_add(&mfm->callback_timer, do_callback, mfm, 0); - ui_sb_update_icon(SB_HDD|HDD_BUS_MFM, 0); + ui_sb_update_icon(SB_HDD | HDD_BUS_MFM, 0); - return(mfm); + return mfm; } - static void mfm_close(void *priv) { - mfm_t *mfm = (mfm_t *)priv; - int d; + mfm_t *mfm = (mfm_t *) priv; - for (d=0; d<2; d++) { - drive_t *drive = &mfm->drives[d]; + for (uint8_t d = 0; d < 2; d++) { + const drive_t *drive = &mfm->drives[d]; - hdd_image_close(drive->hdd_num); + hdd_image_close(drive->hdd_num); } free(mfm); - ui_sb_update_icon(SB_HDD|HDD_BUS_MFM, 0); + ui_sb_update_icon(SB_HDD | HDD_BUS_MFM, 0); } - const device_t st506_at_wd1003_device = { - "WD1003 AT MFM/RLL Controller", - "st506_at", - DEVICE_ISA | DEVICE_AT, - 0, - mfm_init, mfm_close, NULL, - { NULL }, NULL, NULL, NULL + .name = "WD1003 AT MFM/RLL Controller", + .internal_name = "st506_at", + .flags = DEVICE_ISA | DEVICE_AT, + .local = 0, + .init = mfm_init, + .close = mfm_close, + .reset = NULL, + { .available = NULL }, + .speed_changed = NULL, + .force_redraw = NULL, + .config = NULL }; diff --git a/src/disk/hdc_st506_xt.c b/src/disk/hdc_st506_xt.c index 7d1f4ee20..40709d307 100644 --- a/src/disk/hdc_st506_xt.c +++ b/src/disk/hdc_st506_xt.c @@ -1,53 +1,53 @@ /* - * 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. + * 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. + * This file is part of the 86Box distribution. * - * Driver for the IBM PC-XT Fixed Disk controller. + * Driver for the IBM PC-XT Fixed Disk controller. * - * The original controller shipped by IBM was made by Xebec, and - * several variations had been made: + * The original controller shipped by IBM was made by Xebec, and + * several variations had been made: * - * #1 Original, single drive (ST412), 10MB, 2 heads. - * #2 Update, single drive (ST412) but with option for a - * switch block that can be used to 'set' the actual - * drive type. Four switches are defined, where switches - * 1 and 2 define drive0, and switches 3 and 4 drive1. + * #1 Original, single drive (ST412), 10MB, 2 heads. + * #2 Update, single drive (ST412) but with option for a + * switch block that can be used to 'set' the actual + * drive type. Four switches are defined, where switches + * 1 and 2 define drive0, and switches 3 and 4 drive1. * - * 0 ON ON 306 2 0 - * 1 ON OFF 375 8 0 - * 2 OFF ON 306 6 256 - * 3 OFF OFF 306 4 0 + * 0 ON ON 306 2 0 + * 1 ON OFF 375 8 0 + * 2 OFF ON 306 6 256 + * 3 OFF OFF 306 4 0 * - * The latter option is the default, in use on boards - * without the switch block option. + * The latter option is the default, in use on boards + * without the switch block option. * - * #3 Another updated board, mostly to accomodate the new - * 20MB disk now being shipped. The controller can have - * up to 2 drives, the type of which is set using the - * switch block: + * #3 Another updated board, mostly to accomodate the new + * 20MB disk now being shipped. The controller can have + * up to 2 drives, the type of which is set using the + * switch block: * - * SW1 SW2 CYLS HD SPT WPC - * 0 ON ON 306 4 17 0 - * 1 ON OFF 612 4 17 0 (type 16) - * 2 OFF ON 615 4 17 300 (Seagate ST-225, 2) - * 3 OFF OFF 306 8 17 128 (IBM WD25, 13) + * SW1 SW2 CYLS HD SPT WPC + * 0 ON ON 306 4 17 0 + * 1 ON OFF 612 4 17 0 (type 16) + * 2 OFF ON 615 4 17 300 (Seagate ST-225, 2) + * 3 OFF OFF 306 8 17 128 (IBM WD25, 13) * - * Examples of #3 are IBM/Xebec, WD10004A-WX1 and ST11R. + * Examples of #3 are IBM/Xebec, WD10004A-WX1 and ST11R. * - * Since all controllers (including the ones made by DTC) use - * (mostly) the same API, we keep them all in this module. + * Since all controllers (including the ones made by DTC) use + * (mostly) the same API, we keep them all in this module. * * * - * Authors: Fred N. van Kempen, - * Sarah Walker, + * Authors: Fred N. van Kempen, + * Sarah Walker, * - * Copyright 2017-2019 Fred N. van Kempen. - * Copyright 2008-2019 Sarah Walker. + * Copyright 2017-2019 Fred N. van Kempen. + * Copyright 2008-2019 Sarah Walker. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -67,9 +67,6 @@ * Boston, MA 02111-1307 * USA. */ -#define __USE_LARGEFILE64 -#define _LARGEFILE_SOURCE -#define _LARGEFILE64_SOURCE #include #include #include @@ -90,118 +87,135 @@ #include <86box/hdc.h> #include <86box/hdd.h> +#define ST506_XT_TYPE_XEBEC 0 +#define ST506_XT_TYPE_WDXT_GEN 1 +#define ST506_XT_TYPE_DTC_5150X 2 +#define ST506_XT_TYPE_ST11M 11 +#define ST506_XT_TYPE_ST11R 12 +#define ST506_XT_TYPE_WD1002A_WX1 21 +#define ST506_XT_TYPE_WD1002A_WX1_NOBIOS 22 +#define ST506_XT_TYPE_WD1002A_27X 23 +#define ST506_XT_TYPE_WD1004A_WX1 24 +#define ST506_XT_TYPE_WD1004_27X 25 +#define ST506_XT_TYPE_WD1004A_27X 26 +#define ST506_XT_TYPE_VICTOR_V86P 27 +#define ST506_XT_TYPE_TOSHIBA_T1200 28 -#define XEBEC_BIOS_FILE "roms/hdd/st506/ibm_xebec_62x0822_1985.bin" -#define DTC_BIOS_FILE "roms/hdd/st506/dtc_cxd21a.bin" -#define ST11_BIOS_FILE_OLD "roms/hdd/st506/st11_bios_vers_1.7.bin" -#define ST11_BIOS_FILE_NEW "roms/hdd/st506/st11_bios_vers_2.0.bin" -#define WD1002A_WX1_BIOS_FILE "roms/hdd/st506/wd1002a_wx1-62-000094-032.bin" +#define XEBEC_BIOS_FILE "roms/hdd/st506/ibm_xebec_62x0822_1985.bin" +#define WDXT_GEN_BIOS_FILE "roms/hdd/st506/wdxt-gen/62-000128-000.bin" +#define DTC_BIOS_FILE "roms/hdd/st506/dtc_cxd21a.bin" +#define ST11_BIOS_FILE_OLD "roms/hdd/st506/st11_bios_vers_1.7.bin" +#define ST11_BIOS_FILE_NEW "roms/hdd/st506/st11_bios_vers_2.0.bin" +#define WD1002A_WX1_BIOS_FILE "roms/hdd/st506/wd1002a_wx1-62-000094-032.bin" +#define WD1004A_WX1_BIOS_FILE "roms/hdd/st506/wd1002a_wx1-62-000094-032.bin" /* SuperBIOS was for both the WX1 and 27X, users jumpers readout to determine if to use 26 sectors per track, 26 -> 17 sectors per track translation, or 17 sectors per track. */ -#define WD1002A_27X_BIOS_FILE "roms/hdd/st506/wd1002a_27x-62-000094-032.bin" +#define WD1002A_27X_BIOS_FILE "roms/hdd/st506/wd1002a_27x-62-000094-032.bin" +#define WD1004_27X_BIOS_FILE "roms/hdd/st506/western_digital_WD1004A-27X.bin" +#define WD1004A_27X_BIOS_FILE "roms/hdd/st506/western_digital_WD1004A-27X.bin" +#define VICTOR_V86P_BIOS_FILE "roms/machines/v86p/2793VG.10010688.rom" - -#define ST506_TIME (250 * TIMER_USEC) -#define ST506_TIME_MS (1000 * TIMER_USEC) +#define ST506_TIME (250 * TIMER_USEC) +#define ST506_TIME_MS (1000 * TIMER_USEC) /* MFM and RLL use different sectors/track. */ -#define SECTOR_SIZE 512 -#define MFM_SECTORS 17 -#define RLL_SECTORS 26 - +#define SECTOR_SIZE 512 +#define MFM_SECTORS 17 +#define RLL_SECTORS 26 /* Status register. */ -#define STAT_REQ 0x01 /* controller ready */ -#define STAT_IO 0x02 /* input, data to host */ -#define STAT_CD 0x04 /* command mode (else data) */ -#define STAT_BSY 0x08 /* controller is busy */ -#define STAT_DRQ 0x10 /* controller needs DMA */ -#define STAT_IRQ 0x20 /* interrupt, we have info */ +#define STAT_REQ 0x01 /* controller ready */ +#define STAT_IO 0x02 /* input, data to host */ +#define STAT_CD 0x04 /* command mode (else data) */ +#define STAT_BSY 0x08 /* controller is busy */ +#define STAT_DRQ 0x10 /* controller needs DMA */ +#define STAT_IRQ 0x20 /* interrupt, we have info */ /* DMA/IRQ enable register. */ -#define DMA_ENA 0x01 /* DMA operation enabled */ -#define IRQ_ENA 0x02 /* IRQ operation enabled */ +#define DMA_ENA 0x01 /* DMA operation enabled */ +#define IRQ_ENA 0x02 /* IRQ operation enabled */ /* Error codes in sense report. */ -#define ERR_BV 0x80 -#define ERR_TYPE_MASK 0x30 -#define ERR_TYPE_SHIFT 4 -# define ERR_TYPE_DRIVE 0x00 -# define ERR_TYPE_CONTROLLER 0x01 -# define ERR_TYPE_COMMAND 0x02 -# define ERR_TYPE_MISC 0x03 +#define ERR_BV 0x80 +#define ERR_TYPE_MASK 0x30 +#define ERR_TYPE_SHIFT 4 +#define ERR_TYPE_DRIVE 0x00 +#define ERR_TYPE_CONTROLLER 0x01 +#define ERR_TYPE_COMMAND 0x02 +#define ERR_TYPE_MISC 0x03 /* No, um, errors.. */ -#define ERR_NONE 0x00 +#define ERR_NONE 0x00 /* Group 0: drive errors. */ -#define ERR_NO_SEEK 0x02 /* no seek_complete */ -#define ERR_WR_FAULT 0x03 /* write fault */ -#define ERR_NOT_READY 0x04 /* drive not ready */ -#define ERR_NO_TRACK0 0x06 /* track 0 not found */ -#define ERR_STILL_SEEKING 0x08 /* drive is still seeking */ -#define ERR_NOT_AVAILABLE 0x09 /* drive not available */ +#define ERR_NO_SEEK 0x02 /* no seek_complete */ +#define ERR_WR_FAULT 0x03 /* write fault */ +#define ERR_NOT_READY 0x04 /* drive not ready */ +#define ERR_NO_TRACK0 0x06 /* track 0 not found */ +#define ERR_STILL_SEEKING 0x08 /* drive is still seeking */ +#define ERR_NOT_AVAILABLE 0x09 /* drive not available */ /* Group 1: controller errors. */ -#define ERR_ID_FAULT 0x10 /* could not read ID field */ -#define ERR_UNC_ERR 0x11 /* uncorrectable data */ -#define ERR_SECTOR_ADDR 0x12 /* sector address */ -#define ERR_DATA_ADDR 0x13 /* data mark not found */ -#define ERR_TARGET_SECTOR 0x14 /* target sector not found */ -#define ERR_SEEK_ERROR 0x15 /* seek error- cyl not found */ -#define ERR_CORR_ERR 0x18 /* correctable data */ -#define ERR_BAD_TRACK 0x19 /* track is flagged as bad */ -#define ERR_ALT_TRACK_FLAGGED 0x1c /* alt trk not flagged as alt */ -#define ERR_ALT_TRACK_ACCESS 0x1e /* illegal access to alt trk */ -#define ERR_NO_RECOVERY 0x1f /* recovery mode not avail */ +#define ERR_ID_FAULT 0x10 /* could not read ID field */ +#define ERR_UNC_ERR 0x11 /* uncorrectable data */ +#define ERR_SECTOR_ADDR 0x12 /* sector address */ +#define ERR_DATA_ADDR 0x13 /* data mark not found */ +#define ERR_TARGET_SECTOR 0x14 /* target sector not found */ +#define ERR_SEEK_ERROR 0x15 /* seek error- cyl not found */ +#define ERR_CORR_ERR 0x18 /* correctable data */ +#define ERR_BAD_TRACK 0x19 /* track is flagged as bad */ +#define ERR_ALT_TRACK_FLAGGED 0x1c /* alt trk not flagged as alt */ +#define ERR_ALT_TRACK_ACCESS 0x1e /* illegal access to alt trk */ +#define ERR_NO_RECOVERY 0x1f /* recovery mode not avail */ /* Group 2: command errors. */ -#define ERR_BAD_COMMAND 0x20 /* invalid command */ -#define ERR_ILLEGAL_ADDR 0x21 /* address beyond disk size */ -#define ERR_BAD_PARAMETER 0x22 /* invalid command parameter */ +#define ERR_BAD_COMMAND 0x20 /* invalid command */ +#define ERR_ILLEGAL_ADDR 0x21 /* address beyond disk size */ +#define ERR_BAD_PARAMETER 0x22 /* invalid command parameter */ /* Group 3: misc errors. */ -#define ERR_BAD_RAM 0x30 /* controller has bad RAM */ -#define ERR_BAD_ROM 0x31 /* ROM failed checksum test */ -#define ERR_CRC_FAIL 0x32 /* CRC circuit failed test */ +#define ERR_BAD_RAM 0x30 /* controller has bad RAM */ +#define ERR_BAD_ROM 0x31 /* ROM failed checksum test */ +#define ERR_CRC_FAIL 0x32 /* CRC circuit failed test */ /* Controller commands. */ -#define CMD_TEST_DRIVE_READY 0x00 -#define CMD_RECALIBRATE 0x01 -/* reserved 0x02 */ -#define CMD_STATUS 0x03 -#define CMD_FORMAT_DRIVE 0x04 -#define CMD_VERIFY 0x05 -#define CMD_FORMAT_TRACK 0x06 -#define CMD_FORMAT_BAD_TRACK 0x07 -#define CMD_READ 0x08 -#define CMD_REASSIGN 0x09 -#define CMD_WRITE 0x0a -#define CMD_SEEK 0x0b -#define CMD_SPECIFY 0x0c -#define CMD_READ_ECC_BURST_LEN 0x0d -#define CMD_READ_BUFFER 0x0e -#define CMD_WRITE_BUFFER 0x0f -#define CMD_ALT_TRACK 0x11 -#define CMD_INQUIRY_ST11 0x12 /* ST-11 BIOS */ -#define CMD_RAM_DIAGNOSTIC 0xe0 -/* reserved 0xe1 */ -/* reserved 0xe2 */ -#define CMD_DRIVE_DIAGNOSTIC 0xe3 -#define CMD_CTRLR_DIAGNOSTIC 0xe4 -#define CMD_READ_LONG 0xe5 -#define CMD_WRITE_LONG 0xe6 +#define CMD_TEST_DRIVE_READY 0x00 +#define CMD_RECALIBRATE 0x01 +/* reserved 0x02 */ +#define CMD_STATUS 0x03 +#define CMD_FORMAT_DRIVE 0x04 +#define CMD_VERIFY 0x05 +#define CMD_FORMAT_TRACK 0x06 +#define CMD_FORMAT_BAD_TRACK 0x07 +#define CMD_READ 0x08 +#define CMD_REASSIGN 0x09 +#define CMD_WRITE 0x0a +#define CMD_SEEK 0x0b +#define CMD_SPECIFY 0x0c +#define CMD_READ_ECC_BURST_LEN 0x0d +#define CMD_READ_BUFFER 0x0e +#define CMD_WRITE_BUFFER 0x0f +#define CMD_ALT_TRACK 0x11 +#define CMD_INQUIRY_ST11 0x12 /* ST-11 BIOS */ +#define CMD_V86P_POWEROFF 0x1a /* Victor V86P */ +#define CMD_RAM_DIAGNOSTIC 0xe0 +/* reserved 0xe1 */ +/* reserved 0xe2 */ +#define CMD_DRIVE_DIAGNOSTIC 0xe3 +#define CMD_CTRLR_DIAGNOSTIC 0xe4 +#define CMD_READ_LONG 0xe5 +#define CMD_WRITE_LONG 0xe6 -#define CMD_FORMAT_ST11 0xf6 /* ST-11 BIOS */ -#define CMD_GET_GEOMETRY_ST11 0xf8 /* ST-11 BIOS */ -#define CMD_SET_GEOMETRY_ST11 0xfa /* ST-11 BIOS */ -#define CMD_WRITE_GEOMETRY_ST11 0xfc /* ST-11 BIOS 2.0 */ +#define CMD_FORMAT_ST11 0xf6 /* ST-11 BIOS */ +#define CMD_GET_GEOMETRY_ST11 0xf8 /* ST-11 BIOS */ +#define CMD_SET_GEOMETRY_ST11 0xfa /* ST-11 BIOS */ +#define CMD_WRITE_GEOMETRY_ST11 0xfc /* ST-11 BIOS 2.0 */ -#define CMD_GET_DRIVE_PARAMS_DTC 0xfb /* DTC */ -#define CMD_SET_STEP_RATE_DTC 0xfc /* DTC */ -#define CMD_SET_GEOMETRY_DTC 0xfe /* DTC */ -#define CMD_GET_GEOMETRY_DTC 0xff /* DTC */ +#define CMD_GET_DRIVE_PARAMS_DTC 0xfb /* DTC */ +#define CMD_SET_STEP_RATE_DTC 0xfc /* DTC */ +#define CMD_SET_GEOMETRY_DTC 0xfe /* DTC */ +#define CMD_GET_GEOMETRY_DTC 0xff /* DTC */ enum { STATE_IDLE, @@ -215,117 +229,136 @@ enum { STATE_DONE }; +typedef struct drive_t { + int8_t present; + uint8_t hdd_num; -typedef struct { - int8_t present; - uint8_t hdd_num; + uint8_t interleave; /* default interleave */ + char pad; - uint8_t interleave; /* default interleave */ - char pad; + uint16_t cylinder; /* current cylinder */ - uint16_t cylinder; /* current cylinder */ + uint8_t spt; /* physical parameters */ + uint8_t hpc; + uint16_t tracks; - uint8_t spt, /* physical parameters */ - hpc; - uint16_t tracks; - - uint8_t cfg_spt, /* configured parameters */ - cfg_hpc; - uint16_t cfg_cyl; + uint8_t cfg_spt; /* configured parameters */ + uint8_t cfg_hpc; + uint16_t cfg_cyl; } drive_t; +typedef struct hdc_t { + uint8_t type; /* controller type */ -typedef struct { - uint8_t type; /* controller type */ + uint8_t spt; /* sectors-per-track for controller */ - uint8_t spt; /* sectors-per-track for controller */ + uint16_t base; /* controller configuration */ + int8_t irq; + int8_t dma; + uint8_t switches; + uint8_t misc; + uint8_t nr_err; + uint8_t err_bv; + uint8_t cur_sec; + uint8_t pad; + uint32_t bios_addr; + uint32_t bios_size; + uint32_t bios_ram; + rom_t bios_rom; - uint16_t base; /* controller configuration */ - int8_t irq, - dma; - uint8_t switches; - uint8_t misc; - uint8_t nr_err, err_bv, cur_sec, pad; - uint32_t bios_addr, - bios_size, - bios_ram; - rom_t bios_rom; + int state; /* operational data */ + uint8_t irq_dma; + uint8_t error; + uint8_t status; + int8_t cyl_off; /* for ST-11, cylinder0 offset */ + pc_timer_t timer; - int state; /* operational data */ - uint8_t irq_dma; - uint8_t error; - uint8_t status; - int8_t cyl_off; /* for ST-11, cylinder0 offset */ - pc_timer_t timer; + uint8_t command[6]; /* current command request */ + int drive_sel; + int sector; + int head; + int cylinder; + int count; + uint8_t compl ; /* current request completion code */ - uint8_t command[6]; /* current command request */ - int drive_sel; - int sector, - head, - cylinder, - count; - uint8_t compl; /* current request completion code */ + int buff_pos; /* pointers to the RAM buffer */ + int buff_cnt; - int buff_pos, /* pointers to the RAM buffer */ - buff_cnt; - - drive_t drives[MFM_NUM]; /* the attached drives */ - uint8_t scratch[64]; /* ST-11 scratchpad RAM */ - uint8_t buff[SECTOR_SIZE + 4]; /* sector buffer RAM (+ ECC bytes) */ + drive_t drives[MFM_NUM]; /* the attached drives */ + uint8_t scratch[64]; /* ST-11 scratchpad RAM */ + uint8_t buff[SECTOR_SIZE + 4]; /* sector buffer RAM (+ ECC bytes) */ } hdc_t; - /* Supported drives table for the Xebec controller. */ -typedef struct { - uint16_t tracks; - uint8_t hpc; - uint8_t spt; +typedef struct hd_type_t { + uint16_t tracks; + uint8_t hpc; + uint8_t spt; } hd_type_t; hd_type_t hd_types[4] = { - { 306, 4, MFM_SECTORS }, /* type 0 */ - { 612, 4, MFM_SECTORS }, /* type 16 */ - { 615, 4, MFM_SECTORS }, /* type 2 */ - { 306, 8, MFM_SECTORS } /* type 13 */ + // clang-format off + { 306, 4, MFM_SECTORS}, /* type 0 */ + { 612, 4, MFM_SECTORS}, /* type 16 */ + { 615, 4, MFM_SECTORS}, /* type 2 */ + { 306, 8, MFM_SECTORS} /* type 13 */ + // clang-format on }; +hd_type_t hd_types_olivetti[16] = { + // clang-format off + { 697, 5, MFM_SECTORS}, + { 612, 4, MFM_SECTORS}, /* type 16 */ + { 612, 4, MFM_SECTORS}, /* type 16 */ + { 306, 4, MFM_SECTORS}, /* type 0 */ + { 612, 8, MFM_SECTORS}, + { 820, 6, MFM_SECTORS}, + { 820, 6, MFM_SECTORS}, + { 823, 10, MFM_SECTORS}, + { 981, 5, MFM_SECTORS}, + { 981, 5, MFM_SECTORS}, + {1024, 8, MFM_SECTORS}, + {1024, 9, MFM_SECTORS}, + { 872, 5, MFM_SECTORS}, + { 612, 4, MFM_SECTORS}, /* type 16 */ + { 612, 4, MFM_SECTORS}, /* type 16 */ + { 306, 4, MFM_SECTORS} /* "not present" with the second hard disk */ + // clang-format on +}; #ifdef ENABLE_ST506_XT_LOG int st506_xt_do_log = ENABLE_ST506_XT_LOG; - static void st506_xt_log(const char *fmt, ...) { va_list ap; if (st506_xt_do_log) { - va_start(ap, fmt); - pclog_ex(fmt, ap); - va_end(ap); + va_start(ap, fmt); + pclog_ex(fmt, ap); + va_end(ap); } } #else -#define st506_xt_log(fmt, ...) +# define st506_xt_log(fmt, ...) #endif - static void st506_complete(hdc_t *dev) { dev->status = STAT_REQ | STAT_CD | STAT_IO | STAT_BSY; - dev->state = STATE_COMPLETION_BYTE; + dev->state = STATE_COMPLETION_BYTE; if (dev->irq_dma & DMA_ENA) - dma_set_drq(dev->dma, 0); + dma_set_drq(dev->dma, 0); if (dev->irq_dma & IRQ_ENA) { - dev->status |= STAT_IRQ; - picint(1 << dev->irq); + dev->status |= STAT_IRQ; + picint(1 << dev->irq); } } - static void st506_error(hdc_t *dev, uint8_t err) { @@ -333,68 +366,65 @@ st506_error(hdc_t *dev, uint8_t err) dev->error = err; } - static int get_sector(hdc_t *dev, drive_t *drive, off64_t *addr) { - if (! drive->present) { - /* No need to log this. */ - dev->error = dev->nr_err; - return(0); + if (!drive->present) { + /* No need to log this. */ + dev->error = dev->nr_err; + return 0; } #if 0 if (drive->cylinder != dev->cylinder) { -#ifdef ENABLE_ST506_XT_LOG - st506_xt_log("ST506: get_sector: wrong cylinder\n"); -#endif - dev->error = ERR_ILLEGAL_ADDR; - return(0); +# ifdef ENABLE_ST506_XT_LOG + st506_xt_log("ST506: get_sector: wrong cylinder\n"); +# endif + dev->error = ERR_ILLEGAL_ADDR; + return(0); } #endif if (dev->head >= drive->cfg_hpc) { #ifdef ENABLE_ST506_XT_LOG - st506_xt_log("ST506: get_sector: past end of configured heads\n"); + st506_xt_log("ST506: get_sector: past end of configured heads\n"); #endif - dev->error = ERR_ILLEGAL_ADDR; - return(0); + dev->error = ERR_ILLEGAL_ADDR; + return 0; } if (dev->sector >= drive->cfg_spt) { #ifdef ENABLE_ST506_XT_LOG - st506_xt_log("ST506: get_sector: past end of configured sectors\n"); + st506_xt_log("ST506: get_sector: past end of configured sectors\n"); #endif - dev->error = ERR_ILLEGAL_ADDR; - return(0); + dev->error = ERR_ILLEGAL_ADDR; + return 0; } - *addr = ((((off64_t)dev->cylinder * drive->cfg_hpc) + dev->head) * drive->cfg_spt) + dev->sector; - - return(1); -} + *addr = ((((off64_t) dev->cylinder * drive->cfg_hpc) + dev->head) * drive->cfg_spt) + dev->sector; + return 1; +} static void next_sector(hdc_t *dev, drive_t *drive) { if (++dev->sector >= drive->cfg_spt) { - dev->sector = 0; - if (++dev->head >= drive->cfg_hpc) { - dev->head = 0; - if (++drive->cylinder >= drive->cfg_cyl) { - /* - * This really is an error, we cannot move - * past the end of the drive, which should - * result in an ERR_ILLEGAL_ADDR. --FvK - */ - drive->cylinder = drive->cfg_cyl - 1; - } else - dev->cylinder++; - } + dev->sector = 0; + if (++dev->head >= drive->cfg_hpc) { + dev->head = 0; + if (++drive->cylinder >= drive->cfg_cyl) { + /* + * This really is an error, we cannot move + * past the end of the drive, which should + * result in an ERR_ILLEGAL_ADDR. --FvK + */ + drive->cylinder = drive->cfg_cyl - 1; + } else + dev->cylinder++; + } } } - /* Extract the CHS info from a command block. */ static int get_chs(hdc_t *dev, drive_t *drive) @@ -404,899 +434,1014 @@ get_chs(hdc_t *dev, drive_t *drive) dev->head = dev->command[1] & 0x1f; /* 6 bits are used for the sector number even on the IBM PC controller. */ dev->sector = dev->command[2] & 0x3f; - dev->count = dev->command[4]; - if (((dev->type == 11) || (dev->type == 12)) && (dev->command[0] >= 0xf0)) - dev->cylinder = 0; + dev->count = dev->command[4]; + if (((dev->type == ST506_XT_TYPE_ST11M) || (dev->type == ST506_XT_TYPE_ST11R)) && (dev->command[0] >= 0xf0)) + dev->cylinder = 0; else { - dev->cylinder = dev->command[3] | ((dev->command[2] & 0xc0) << 2); - dev->cylinder += dev->cyl_off; /* for ST-11 */ + dev->cylinder = dev->command[3] | ((dev->command[2] & 0xc0) << 2); + dev->cylinder += dev->cyl_off; /* for ST-11 */ } if (dev->cylinder >= drive->cfg_cyl) { - /* - * This really is an error, we cannot move - * past the end of the drive, which should - * result in an ERR_ILLEGAL_ADDR. --FvK - */ - drive->cylinder = drive->cfg_cyl - 1; - return(0); + /* + * This really is an error, we cannot move + * past the end of the drive, which should + * result in an ERR_ILLEGAL_ADDR. --FvK + */ + drive->cylinder = drive->cfg_cyl - 1; + return 0; } drive->cylinder = dev->cylinder; - return(1); + return 1; } - static void st506_callback(void *priv) { - hdc_t *dev = (hdc_t *)priv; + hdc_t *dev = (hdc_t *) priv; drive_t *drive; - off64_t addr; + off64_t addr; uint32_t capac; - int val; + int val; /* Get the drive info. Note that the API supports up to 8 drives! */ dev->drive_sel = (dev->command[1] >> 5) & 0x07; - drive = &dev->drives[dev->drive_sel]; + drive = &dev->drives[dev->drive_sel]; /* Preset the completion byte to "No error" and the selected drive. */ dev->compl = (dev->drive_sel << 5) | ERR_NONE; if (dev->command[0] != 3) - dev->err_bv = 0x00; + dev->err_bv = 0x00; switch (dev->command[0]) { - case CMD_TEST_DRIVE_READY: - st506_xt_log("ST506: TEST_READY(%i) = %i\n", - dev->drive_sel, drive->present); - if (! drive->present) - st506_error(dev, dev->nr_err); - st506_complete(dev); - break; + case CMD_TEST_DRIVE_READY: + st506_xt_log("ST506: TEST_READY(%i) = %i\n", + dev->drive_sel, drive->present); + if (!drive->present) + st506_error(dev, dev->nr_err); + st506_complete(dev); + break; - case CMD_RECALIBRATE: - switch (dev->state) { - case STATE_START_COMMAND: - st506_xt_log("ST506: RECALIBRATE(%i) [%i]\n", - dev->drive_sel, drive->present); - if (! drive->present) { - st506_error(dev, dev->nr_err); - st506_complete(dev); - break; - } + case CMD_RECALIBRATE: + switch (dev->state) { + case STATE_START_COMMAND: + st506_xt_log("ST506: RECALIBRATE(%i) [%i]\n", + dev->drive_sel, drive->present); + if (!drive->present) { + st506_error(dev, dev->nr_err); + st506_complete(dev); + break; + } - /* Wait 20msec. */ - timer_advance_u64(&dev->timer, ST506_TIME_MS * 20); + /* Wait 20msec. */ + timer_advance_u64(&dev->timer, ST506_TIME_MS * 20); - dev->cylinder = dev->cyl_off; - drive->cylinder = dev->cylinder; - dev->state = STATE_DONE; + dev->cylinder = dev->cyl_off; + drive->cylinder = dev->cylinder; + dev->state = STATE_DONE; - break; + break; - case STATE_DONE: - st506_complete(dev); - break; - } - break; + case STATE_DONE: + st506_complete(dev); + break; - case CMD_STATUS: - switch (dev->state) { - case STATE_START_COMMAND: + default: + break; + } + break; + + case CMD_STATUS: + switch (dev->state) { + case STATE_START_COMMAND: #ifdef ENABLE_ST506_XT_LOG - st506_xt_log("ST506: STATUS\n"); + st506_xt_log("ST506: STATUS\n"); #endif - dev->buff_pos = 0; - dev->buff_cnt = 4; - dev->buff[0] = dev->err_bv | dev->error; - dev->error = 0; + dev->buff_pos = 0; + dev->buff_cnt = 4; + dev->buff[0] = dev->err_bv | dev->error; + dev->error = 0; - /* Give address of last operation. */ - dev->buff[1] = (dev->drive_sel ? 0x20 : 0) | - dev->head; - dev->buff[2] = ((dev->cylinder & 0x0300) >> 2) | - dev->sector; - dev->buff[3] = (dev->cylinder & 0xff); + /* Give address of last operation. */ + dev->buff[1] = (dev->drive_sel ? 0x20 : 0) | dev->head; + dev->buff[2] = ((dev->cylinder & 0x0300) >> 2) | dev->sector; + dev->buff[3] = (dev->cylinder & 0xff); - dev->status = STAT_BSY | STAT_IO | STAT_REQ; - dev->state = STATE_SEND_DATA; - break; + dev->status = STAT_BSY | STAT_IO | STAT_REQ; + dev->state = STATE_SEND_DATA; + break; - case STATE_SENT_DATA: - st506_complete(dev); - break; - } - break; + case STATE_SENT_DATA: + st506_complete(dev); + break; - case CMD_FORMAT_DRIVE: - switch (dev->state) { - case STATE_START_COMMAND: - (void)get_chs(dev, drive); - st506_xt_log("ST506: FORMAT_DRIVE(%i) interleave=%i\n", - dev->drive_sel, dev->command[4]); - ui_sb_update_icon(SB_HDD | HDD_BUS_MFM, 1); - timer_advance_u64(&dev->timer, ST506_TIME); - dev->state = STATE_SEND_DATA; - break; + default: + break; + } + break; - case STATE_SEND_DATA: /* wrong, but works */ - if (! get_sector(dev, drive, &addr)) { - ui_sb_update_icon(SB_HDD | HDD_BUS_MFM, 0); - st506_error(dev, dev->error); - st506_complete(dev); - return; - } + case CMD_FORMAT_DRIVE: + switch (dev->state) { + case STATE_START_COMMAND: + (void) get_chs(dev, drive); + st506_xt_log("ST506: FORMAT_DRIVE(%i) interleave=%i\n", + dev->drive_sel, dev->command[4]); + ui_sb_update_icon(SB_HDD | HDD_BUS_MFM, 1); + timer_advance_u64(&dev->timer, ST506_TIME); + dev->state = STATE_SEND_DATA; + break; - /* FIXME: should be drive->capac, not ->spt */ - capac = (drive->tracks - 1) * drive->hpc * drive->spt; - hdd_image_zero(drive->hdd_num, addr, capac); + case STATE_SEND_DATA: /* wrong, but works */ + if (!get_sector(dev, drive, &addr)) { + ui_sb_update_icon(SB_HDD | HDD_BUS_MFM, 0); + st506_error(dev, dev->error); + st506_complete(dev); + return; + } - /* Wait 20msec per cylinder. */ - timer_advance_u64(&dev->timer, ST506_TIME_MS * 20); + /* FIXME: should be drive->capac, not ->spt */ + capac = (drive->tracks - 1) * drive->hpc * drive->spt; + hdd_image_zero(drive->hdd_num, addr, capac); - dev->state = STATE_SENT_DATA; - break; + /* Wait 20msec per cylinder. */ + timer_advance_u64(&dev->timer, ST506_TIME_MS * 20); - case STATE_SENT_DATA: - ui_sb_update_icon(SB_HDD | HDD_BUS_MFM, 0); - st506_complete(dev); - break; - } - break; + dev->state = STATE_SENT_DATA; + break; - case CMD_VERIFY: - switch (dev->state) { - case STATE_START_COMMAND: - (void)get_chs(dev, drive); - st506_xt_log("ST506: VERIFY(%i, %i/%i/%i, %i)\n", - dev->drive_sel, dev->cylinder, - dev->head, dev->sector, dev->count); - ui_sb_update_icon(SB_HDD | HDD_BUS_MFM, 1); - timer_advance_u64(&dev->timer, ST506_TIME); - dev->state = STATE_SEND_DATA; - break; + case STATE_SENT_DATA: + ui_sb_update_icon(SB_HDD | HDD_BUS_MFM, 0); + st506_complete(dev); + break; - case STATE_SEND_DATA: - if (dev->count-- == 0) { - ui_sb_update_icon(SB_HDD | HDD_BUS_MFM, 0); - st506_complete(dev); - } + default: + break; + } + break; - if (! get_sector(dev, drive, &addr)) { - ui_sb_update_icon(SB_HDD | HDD_BUS_MFM, 0); - st506_error(dev, dev->error); - st506_complete(dev); - return; - } + case CMD_VERIFY: + switch (dev->state) { + case STATE_START_COMMAND: + (void) get_chs(dev, drive); + st506_xt_log("ST506: VERIFY(%i, %i/%i/%i, %i)\n", + dev->drive_sel, dev->cylinder, + dev->head, dev->sector, dev->count); + ui_sb_update_icon(SB_HDD | HDD_BUS_MFM, 1); + timer_advance_u64(&dev->timer, ST506_TIME); + dev->state = STATE_SEND_DATA; + break; - next_sector(dev, drive); + case STATE_SEND_DATA: + if (dev->count-- == 0) { + ui_sb_update_icon(SB_HDD | HDD_BUS_MFM, 0); + st506_complete(dev); + } - timer_advance_u64(&dev->timer, ST506_TIME); - break; - } - break; + if (!get_sector(dev, drive, &addr)) { + ui_sb_update_icon(SB_HDD | HDD_BUS_MFM, 0); + st506_error(dev, dev->error); + st506_complete(dev); + return; + } - case CMD_FORMAT_ST11: /* This is really "Format cylinder 0" */ - if ((dev->type < 11) || (dev->type > 12)) { - st506_error(dev, ERR_BAD_COMMAND); - st506_complete(dev); - break; - } - case CMD_FORMAT_TRACK: - case CMD_FORMAT_BAD_TRACK: - switch (dev->state) { - case STATE_START_COMMAND: - (void)get_chs(dev, drive); - st506_xt_log("ST506: FORMAT_%sTRACK(%i, %i/%i)\n", - (dev->command[0] == CMD_FORMAT_BAD_TRACK) ? "BAD_" : "", - dev->drive_sel, dev->cylinder, dev->head); - ui_sb_update_icon(SB_HDD | HDD_BUS_MFM, 1); - timer_advance_u64(&dev->timer, ST506_TIME); - dev->state = STATE_SEND_DATA; - break; + next_sector(dev, drive); - case STATE_SEND_DATA: /* wrong, but works */ - if (! get_sector(dev, drive, &addr)) { - ui_sb_update_icon(SB_HDD | HDD_BUS_MFM, 0); - st506_error(dev, dev->error); - st506_complete(dev); - return; - } + timer_advance_u64(&dev->timer, ST506_TIME); + break; - hdd_image_zero(drive->hdd_num, - addr, drive->cfg_spt); + default: + break; + } + break; - /* Wait 20 msec per cylinder. */ - timer_advance_u64(&dev->timer, ST506_TIME_MS * 20); + case CMD_FORMAT_ST11: /* This is really "Format cylinder 0" */ + if ((dev->type < ST506_XT_TYPE_ST11M) || (dev->type > ST506_XT_TYPE_ST11R)) { + st506_error(dev, ERR_BAD_COMMAND); + st506_complete(dev); + break; + } + fallthrough; + case CMD_FORMAT_TRACK: + case CMD_FORMAT_BAD_TRACK: + switch (dev->state) { + case STATE_START_COMMAND: + (void) get_chs(dev, drive); + st506_xt_log("ST506: FORMAT_%sTRACK(%i, %i/%i)\n", + (dev->command[0] == CMD_FORMAT_BAD_TRACK) ? "BAD_" : "", + dev->drive_sel, dev->cylinder, dev->head); + ui_sb_update_icon(SB_HDD | HDD_BUS_MFM, 1); + timer_advance_u64(&dev->timer, ST506_TIME); + dev->state = STATE_SEND_DATA; + break; - dev->state = STATE_SENT_DATA; - break; + case STATE_SEND_DATA: /* wrong, but works */ + if (!get_sector(dev, drive, &addr)) { + ui_sb_update_icon(SB_HDD | HDD_BUS_MFM, 0); + st506_error(dev, dev->error); + st506_complete(dev); + return; + } - case STATE_SENT_DATA: - ui_sb_update_icon(SB_HDD | HDD_BUS_MFM, 0); - st506_complete(dev); - break; - } - break; + hdd_image_zero(drive->hdd_num, + addr, drive->cfg_spt); - case CMD_GET_GEOMETRY_ST11: /* "Get geometry" is really "Read cylinder 0" */ - if ((dev->type < 11) || (dev->type > 12)) { - st506_error(dev, ERR_BAD_COMMAND); - st506_complete(dev); - break; - } - case CMD_READ: + /* Wait 20 msec per cylinder. */ + timer_advance_u64(&dev->timer, ST506_TIME_MS * 20); + + dev->state = STATE_SENT_DATA; + break; + + case STATE_SENT_DATA: + ui_sb_update_icon(SB_HDD | HDD_BUS_MFM, 0); + st506_complete(dev); + break; + + default: + break; + } + break; + + case CMD_GET_GEOMETRY_ST11: /* "Get geometry" is really "Read cylinder 0" */ + if ((dev->type < ST506_XT_TYPE_ST11M) || (dev->type > ST506_XT_TYPE_ST11R)) { + st506_error(dev, ERR_BAD_COMMAND); + st506_complete(dev); + break; + } + fallthrough; + case CMD_READ: #if 0 - case CMD_READ_LONG: + case CMD_READ_LONG: #endif - switch (dev->state) { - case STATE_START_COMMAND: - (void)get_chs(dev, drive); - st506_xt_log("ST506: READ%s(%i, %i/%i/%i, %i)\n", - (dev->command[0] == CMD_READ_LONG) ? "_LONG" : "", - dev->drive_sel, dev->cylinder, - dev->head, dev->sector, dev->count); + switch (dev->state) { + case STATE_START_COMMAND: + (void) get_chs(dev, drive); + st506_xt_log("ST506: READ%s(%i, %i/%i/%i, %i)\n", + (dev->command[0] == CMD_READ_LONG) ? "_LONG" : "", + dev->drive_sel, dev->cylinder, + dev->head, dev->sector, dev->count); - if (! get_sector(dev, drive, &addr)) { - st506_error(dev, dev->error); - st506_complete(dev); - return; - } - ui_sb_update_icon(SB_HDD | HDD_BUS_MFM, 1); + if (!get_sector(dev, drive, &addr)) { + st506_error(dev, dev->error); + st506_complete(dev); + return; + } + ui_sb_update_icon(SB_HDD | HDD_BUS_MFM, 1); - /* Read data from the image. */ - hdd_image_read(drive->hdd_num, addr, 1, - (uint8_t *)dev->buff); + /* Read data from the image. */ + hdd_image_read(drive->hdd_num, addr, 1, + (uint8_t *) dev->buff); - /* Set up the data transfer. */ - dev->buff_pos = 0; - dev->buff_cnt = SECTOR_SIZE; - if (dev->command[0] == CMD_READ_LONG) - dev->buff_cnt += 4; - dev->status = STAT_BSY | STAT_IO | STAT_REQ; - if (dev->irq_dma & DMA_ENA) { - timer_advance_u64(&dev->timer, ST506_TIME); - dma_set_drq(dev->dma, 1); - } - dev->state = STATE_SEND_DATA; - break; + /* Set up the data transfer. */ + dev->buff_pos = 0; + dev->buff_cnt = SECTOR_SIZE; + if (dev->command[0] == CMD_READ_LONG) + dev->buff_cnt += 4; + dev->status = STAT_BSY | STAT_IO | STAT_REQ; + if (dev->irq_dma & DMA_ENA) { + timer_advance_u64(&dev->timer, ST506_TIME); + dma_set_drq(dev->dma, 1); + } + dev->state = STATE_SEND_DATA; + break; - case STATE_SEND_DATA: - for (; dev->buff_pos < dev->buff_cnt; dev->buff_pos++) { - val = dma_channel_write(dev->dma, dev->buff[dev->buff_pos]); - if (val == DMA_NODATA) { + case STATE_SEND_DATA: + for (; dev->buff_pos < dev->buff_cnt; dev->buff_pos++) { + val = dma_channel_write(dev->dma, dev->buff[dev->buff_pos]); + if (val == DMA_NODATA) { #ifdef ENABLE_ST506_XT_LOG - st506_xt_log("ST506: CMD_READ out of data!\n"); + st506_xt_log("ST506: CMD_READ out of data!\n"); #endif - st506_error(dev, ERR_NO_RECOVERY); - st506_complete(dev); - return; - } - } - dma_set_drq(dev->dma, 0); - timer_advance_u64(&dev->timer, ST506_TIME); - dev->state = STATE_SENT_DATA; - break; + st506_error(dev, ERR_NO_RECOVERY); + st506_complete(dev); + return; + } + } + dma_set_drq(dev->dma, 0); + timer_advance_u64(&dev->timer, ST506_TIME); + dev->state = STATE_SENT_DATA; + break; - case STATE_SENT_DATA: - if (--dev->count == 0) { - ui_sb_update_icon(SB_HDD | HDD_BUS_MFM, 0); - st506_complete(dev); - break; - } + case STATE_SENT_DATA: + if (--dev->count == 0) { + ui_sb_update_icon(SB_HDD | HDD_BUS_MFM, 0); + st506_complete(dev); + break; + } - next_sector(dev, drive); + next_sector(dev, drive); - if (! get_sector(dev, drive, &addr)) { - ui_sb_update_icon(SB_HDD | HDD_BUS_MFM, 0); - st506_error(dev, dev->error); - st506_complete(dev); - return; - } + if (!get_sector(dev, drive, &addr)) { + ui_sb_update_icon(SB_HDD | HDD_BUS_MFM, 0); + st506_error(dev, dev->error); + st506_complete(dev); + return; + } - /* Read data from the image. */ - hdd_image_read(drive->hdd_num, addr, 1, - (uint8_t *)dev->buff); + /* Read data from the image. */ + hdd_image_read(drive->hdd_num, addr, 1, + (uint8_t *) dev->buff); - /* Set up the data transfer. */ - dev->buff_pos = 0; - dev->buff_cnt = SECTOR_SIZE; - dev->status = STAT_BSY | STAT_IO | STAT_REQ; - if (dev->irq_dma & DMA_ENA) { - timer_advance_u64(&dev->timer, ST506_TIME); - dma_set_drq(dev->dma, 1); - } - dev->state = STATE_SEND_DATA; - break; - } - break; + /* Set up the data transfer. */ + dev->buff_pos = 0; + dev->buff_cnt = SECTOR_SIZE; + dev->status = STAT_BSY | STAT_IO | STAT_REQ; + if (dev->irq_dma & DMA_ENA) { + timer_advance_u64(&dev->timer, ST506_TIME); + dma_set_drq(dev->dma, 1); + } + dev->state = STATE_SEND_DATA; + break; - case CMD_SET_GEOMETRY_ST11: /* "Set geometry" is really "Write cylinder 0" */ - if (dev->type == 1) { - /* DTC sends this... */ - st506_complete(dev); - break; - } else if ((dev->type < 11) || (dev->type > 12)) { - st506_error(dev, ERR_BAD_COMMAND); - st506_complete(dev); - break; - } - case CMD_WRITE: + default: + break; + } + break; + + case CMD_SET_GEOMETRY_ST11: /* "Set geometry" is really "Write cylinder 0" */ + if (dev->type == ST506_XT_TYPE_DTC_5150X) { + /* DTC sends this... */ + st506_complete(dev); + break; + } else if ((dev->type < ST506_XT_TYPE_ST11M) || (dev->type > ST506_XT_TYPE_ST11R)) { + st506_error(dev, ERR_BAD_COMMAND); + st506_complete(dev); + break; + } + fallthrough; + case CMD_WRITE: #if 0 - case CMD_WRITE_LONG: + case CMD_WRITE_LONG: #endif - switch (dev->state) { - case STATE_START_COMMAND: - (void)get_chs(dev, drive); - st506_xt_log("ST506: WRITE%s(%i, %i/%i/%i, %i)\n", - (dev->command[0] == CMD_WRITE_LONG) ? "_LONG" : "", - dev->drive_sel, dev->cylinder, - dev->head, dev->sector, dev->count); + switch (dev->state) { + case STATE_START_COMMAND: + (void) get_chs(dev, drive); + st506_xt_log("ST506: WRITE%s(%i, %i/%i/%i, %i)\n", + (dev->command[0] == CMD_WRITE_LONG) ? "_LONG" : "", + dev->drive_sel, dev->cylinder, + dev->head, dev->sector, dev->count); - if (! get_sector(dev, drive, &addr)) { - st506_error(dev, ERR_BAD_PARAMETER); - st506_complete(dev); - return; - } + if (!get_sector(dev, drive, &addr)) { + st506_error(dev, ERR_BAD_PARAMETER); + st506_complete(dev); + return; + } - ui_sb_update_icon(SB_HDD | HDD_BUS_MFM, 1); + ui_sb_update_icon(SB_HDD | HDD_BUS_MFM, 1); - /* Set up the data transfer. */ - dev->buff_pos = 0; - dev->buff_cnt = SECTOR_SIZE; - if (dev->command[0] == CMD_WRITE_LONG) - dev->buff_cnt += 4; - dev->status = STAT_BSY | STAT_REQ; - if (dev->irq_dma & DMA_ENA) { - timer_advance_u64(&dev->timer, ST506_TIME); - dma_set_drq(dev->dma, 1); - } - dev->state = STATE_RECEIVE_DATA; - break; + /* Set up the data transfer. */ + dev->buff_pos = 0; + dev->buff_cnt = SECTOR_SIZE; + if (dev->command[0] == CMD_WRITE_LONG) + dev->buff_cnt += 4; + dev->status = STAT_BSY | STAT_REQ; + if (dev->irq_dma & DMA_ENA) { + timer_advance_u64(&dev->timer, ST506_TIME); + dma_set_drq(dev->dma, 1); + } + dev->state = STATE_RECEIVE_DATA; + break; - case STATE_RECEIVE_DATA: - for (; dev->buff_pos < dev->buff_cnt; dev->buff_pos++) { - val = dma_channel_read(dev->dma); - if (val == DMA_NODATA) { + case STATE_RECEIVE_DATA: + for (; dev->buff_pos < dev->buff_cnt; dev->buff_pos++) { + val = dma_channel_read(dev->dma); + if (val == DMA_NODATA) { #ifdef ENABLE_ST506_XT_LOG - st506_xt_log("ST506: CMD_WRITE out of data!\n"); + st506_xt_log("ST506: CMD_WRITE out of data!\n"); #endif - st506_error(dev, ERR_NO_RECOVERY); - st506_complete(dev); - return; - } - dev->buff[dev->buff_pos] = val & 0xff; - } + st506_error(dev, ERR_NO_RECOVERY); + st506_complete(dev); + return; + } + dev->buff[dev->buff_pos] = val & 0xff; + } - dma_set_drq(dev->dma, 0); - timer_advance_u64(&dev->timer, ST506_TIME); - dev->state = STATE_RECEIVED_DATA; - break; + dma_set_drq(dev->dma, 0); + timer_advance_u64(&dev->timer, ST506_TIME); + dev->state = STATE_RECEIVED_DATA; + break; - case STATE_RECEIVED_DATA: - if (! get_sector(dev, drive, &addr)) { - ui_sb_update_icon(SB_HDD | HDD_BUS_MFM, 0); - st506_error(dev, dev->error); - st506_complete(dev); - return; - } + case STATE_RECEIVED_DATA: + if (!get_sector(dev, drive, &addr)) { + ui_sb_update_icon(SB_HDD | HDD_BUS_MFM, 0); + st506_error(dev, dev->error); + st506_complete(dev); + return; + } - /* Write data to image. */ - hdd_image_write(drive->hdd_num, addr, 1, - (uint8_t *)dev->buff); + /* Write data to image. */ + hdd_image_write(drive->hdd_num, addr, 1, + (uint8_t *) dev->buff); - if (--dev->count == 0) { - ui_sb_update_icon(SB_HDD | HDD_BUS_MFM, 0); - st506_complete(dev); - break; - } + if (--dev->count == 0) { + ui_sb_update_icon(SB_HDD | HDD_BUS_MFM, 0); + st506_complete(dev); + break; + } - next_sector(dev, drive); + next_sector(dev, drive); - /* Set up the data transfer. */ - dev->buff_pos = 0; - dev->buff_cnt = SECTOR_SIZE; - dev->status = STAT_BSY | STAT_REQ; - if (dev->irq_dma & DMA_ENA) { - timer_advance_u64(&dev->timer, ST506_TIME); - dma_set_drq(dev->dma, 1); - } - dev->state = STATE_RECEIVE_DATA; - break; - } - break; + /* Set up the data transfer. */ + dev->buff_pos = 0; + dev->buff_cnt = SECTOR_SIZE; + dev->status = STAT_BSY | STAT_REQ; + if (dev->irq_dma & DMA_ENA) { + timer_advance_u64(&dev->timer, ST506_TIME); + dma_set_drq(dev->dma, 1); + } + dev->state = STATE_RECEIVE_DATA; + break; - case CMD_SEEK: - if (drive->present) { - val = get_chs(dev, drive); - st506_xt_log("ST506: SEEK(%i, %i) [%i]\n", - dev->drive_sel, drive->cylinder, val); - if (! val) - st506_error(dev, ERR_SEEK_ERROR); - } else - st506_error(dev, dev->nr_err); - st506_complete(dev); - break; + default: + break; + } + break; - case CMD_SPECIFY: - switch (dev->state) { - case STATE_START_COMMAND: - dev->buff_pos = 0; - dev->buff_cnt = 8; - dev->status = STAT_BSY | STAT_REQ; - dev->state = STATE_RECEIVE_DATA; - break; + case CMD_SEEK: + if (drive->present) { + val = get_chs(dev, drive); + st506_xt_log("ST506: SEEK(%i, %i) [%i]\n", + dev->drive_sel, drive->cylinder, val); + if (!val) + st506_error(dev, ERR_SEEK_ERROR); + } else + st506_error(dev, dev->nr_err); + st506_complete(dev); + break; - case STATE_RECEIVED_DATA: - drive->cfg_cyl = dev->buff[1] | (dev->buff[0] << 8); - drive->cfg_hpc = dev->buff[2]; - /* For a 615/4/26 we get 666/2/31 geometry. */ - st506_xt_log("ST506: drive%i: cyls=%i, heads=%i\n", - dev->drive_sel, drive->cfg_cyl, drive->cfg_hpc); - st506_complete(dev); - break; - } - break; + case CMD_SPECIFY: + switch (dev->state) { + case STATE_START_COMMAND: + dev->buff_pos = 0; + dev->buff_cnt = 8; + dev->status = STAT_BSY | STAT_REQ; + dev->state = STATE_RECEIVE_DATA; + break; - case CMD_READ_ECC_BURST_LEN: - switch (dev->state) { - case STATE_START_COMMAND: + case STATE_RECEIVED_DATA: + drive->cfg_cyl = dev->buff[1] | (dev->buff[0] << 8); + drive->cfg_hpc = dev->buff[2]; + /* For a 615/4/26 we get 666/2/31 geometry. */ + st506_xt_log("ST506: drive%i: cyls=%i, heads=%i\n", + dev->drive_sel, drive->cfg_cyl, drive->cfg_hpc); + if ((dev->type >= ST506_XT_TYPE_VICTOR_V86P) && (drive->cfg_hpc == 2)) { + /* + * On Victor V86P, there's a disagreement between + * the physical geometry, what the controller + * pretends it to be, and what the BIOS uses. + * + * The disk physically has 2/34 heads/sectors per + * track, but it is treated as 4/17 in order to + * look like a regular type 3 drive (see [1], + * line 1859). The controller accepts the 4/17 + * geometry, so this should not really matter. + * + * However, the BIOS issues SPECIFY (see [1], + * line 2089) with head count of two. Let's + * hardwire the correct number instead, just like + * the real hardware seems to. + * + * [1] https://archive.org/download/v86p-hd/V86P-HD.TXT + */ + drive->cfg_hpc = 4; + st506_xt_log("ST506: drive%i: corrected to heads=%i\n", + dev->drive_sel, drive->cfg_hpc); + } + st506_complete(dev); + break; + + default: + break; + } + break; + + case CMD_READ_ECC_BURST_LEN: + switch (dev->state) { + case STATE_START_COMMAND: #ifdef ENABLE_ST506_XT_LOG - st506_xt_log("ST506: READ_ECC_BURST_LEN\n"); + st506_xt_log("ST506: READ_ECC_BURST_LEN\n"); #endif - dev->buff_pos = 0; - dev->buff_cnt = 1; - dev->buff[0] = 0; /* 0 bits */ - dev->status = STAT_BSY | STAT_IO | STAT_REQ; - dev->state = STATE_SEND_DATA; - break; + dev->buff_pos = 0; + dev->buff_cnt = 1; + dev->buff[0] = 0; /* 0 bits */ + dev->status = STAT_BSY | STAT_IO | STAT_REQ; + dev->state = STATE_SEND_DATA; + break; - case STATE_SENT_DATA: - st506_complete(dev); - break; - } - break; + case STATE_SENT_DATA: + st506_complete(dev); + break; - case CMD_READ_BUFFER: - switch (dev->state) { - case STATE_START_COMMAND: - dev->buff_pos = 0; - dev->buff_cnt = SECTOR_SIZE; - st506_xt_log("ST506: READ_BUFFER (%i)\n", - dev->buff_cnt); + default: + break; + } + break; - dev->status = STAT_BSY | STAT_IO | STAT_REQ; - if (dev->irq_dma & DMA_ENA) { - timer_advance_u64(&dev->timer, ST506_TIME); - dma_set_drq(dev->dma, 1); - } - dev->state = STATE_SEND_DATA; - break; + case CMD_READ_BUFFER: + switch (dev->state) { + case STATE_START_COMMAND: + dev->buff_pos = 0; + dev->buff_cnt = SECTOR_SIZE; + st506_xt_log("ST506: READ_BUFFER (%i)\n", + dev->buff_cnt); - case STATE_SEND_DATA: - for (; dev->buff_pos < dev->buff_cnt; dev->buff_pos++) { - val = dma_channel_write(dev->dma, dev->buff[dev->buff_pos]); - if (val == DMA_NODATA) { + dev->status = STAT_BSY | STAT_IO | STAT_REQ; + if (dev->irq_dma & DMA_ENA) { + timer_advance_u64(&dev->timer, ST506_TIME); + dma_set_drq(dev->dma, 1); + } + dev->state = STATE_SEND_DATA; + break; + + case STATE_SEND_DATA: + for (; dev->buff_pos < dev->buff_cnt; dev->buff_pos++) { + val = dma_channel_write(dev->dma, dev->buff[dev->buff_pos]); + if (val == DMA_NODATA) { #ifdef ENABLE_ST506_XT_LOG - st506_xt_log("ST506: CMD_READ_BUFFER out of data!\n"); + st506_xt_log("ST506: CMD_READ_BUFFER out of data!\n"); #endif - st506_error(dev, ERR_NO_RECOVERY); - st506_complete(dev); - return; - } - } + st506_error(dev, ERR_NO_RECOVERY); + st506_complete(dev); + return; + } + } - dma_set_drq(dev->dma, 0); - timer_advance_u64(&dev->timer, ST506_TIME); - dev->state = STATE_SENT_DATA; - break; + dma_set_drq(dev->dma, 0); + timer_advance_u64(&dev->timer, ST506_TIME); + dev->state = STATE_SENT_DATA; + break; - case STATE_SENT_DATA: - st506_complete(dev); - break; - } - break; + case STATE_SENT_DATA: + st506_complete(dev); + break; - case CMD_WRITE_BUFFER: - switch (dev->state) { - case STATE_START_COMMAND: - dev->buff_pos = 0; - dev->buff_cnt = SECTOR_SIZE; - st506_xt_log("ST506: WRITE_BUFFER (%i)\n", - dev->buff_cnt); + default: + break; + } + break; - dev->status = STAT_BSY | STAT_REQ; - if (dev->irq_dma & DMA_ENA) { - timer_advance_u64(&dev->timer, ST506_TIME); - dma_set_drq(dev->dma, 1); - } - dev->state = STATE_RECEIVE_DATA; - break; + case CMD_WRITE_BUFFER: + switch (dev->state) { + case STATE_START_COMMAND: + dev->buff_pos = 0; + dev->buff_cnt = SECTOR_SIZE; + st506_xt_log("ST506: WRITE_BUFFER (%i)\n", + dev->buff_cnt); - case STATE_RECEIVE_DATA: - for (; dev->buff_pos < dev->buff_cnt; dev->buff_pos++) { - val = dma_channel_read(dev->dma); - if (val == DMA_NODATA) { + dev->status = STAT_BSY | STAT_REQ; + if (dev->irq_dma & DMA_ENA) { + timer_advance_u64(&dev->timer, ST506_TIME); + dma_set_drq(dev->dma, 1); + } + dev->state = STATE_RECEIVE_DATA; + break; + + case STATE_RECEIVE_DATA: + for (; dev->buff_pos < dev->buff_cnt; dev->buff_pos++) { + val = dma_channel_read(dev->dma); + if (val == DMA_NODATA) { #ifdef ENABLE_ST506_XT_LOG - st506_xt_log("ST506: CMD_WRITE_BUFFER out of data!\n"); + st506_xt_log("ST506: CMD_WRITE_BUFFER out of data!\n"); #endif - st506_error(dev, ERR_NO_RECOVERY); - st506_complete(dev); - return; - } - dev->buff[dev->buff_pos] = val & 0xff; - } + st506_error(dev, ERR_NO_RECOVERY); + st506_complete(dev); + return; + } + dev->buff[dev->buff_pos] = val & 0xff; + } - dma_set_drq(dev->dma, 0); - timer_advance_u64(&dev->timer, ST506_TIME); - dev->state = STATE_RECEIVED_DATA; - break; + dma_set_drq(dev->dma, 0); + timer_advance_u64(&dev->timer, ST506_TIME); + dev->state = STATE_RECEIVED_DATA; + break; - case STATE_RECEIVED_DATA: - st506_complete(dev); - break; - } - break; + case STATE_RECEIVED_DATA: + st506_complete(dev); + break; - case CMD_INQUIRY_ST11: - if (dev->type == 11 || dev->type == 12) switch (dev->state) { - case STATE_START_COMMAND: - st506_xt_log("ST506: INQUIRY (type=%i)\n", dev->type); - dev->buff_pos = 0; - dev->buff_cnt = 2; - dev->buff[0] = 0x80; /* "ST-11" */ - if (dev->spt == 17) - dev->buff[0] |= 0x40; /* MFM */ - dev->buff[1] = dev->misc; /* revision */ - dev->status = STAT_BSY | STAT_IO | STAT_REQ; - dev->state = STATE_SEND_DATA; - break; + default: + break; + } + break; - case STATE_SENT_DATA: - st506_complete(dev); - break; - } else { - st506_error(dev, ERR_BAD_COMMAND); - st506_complete(dev); - } - break; + case CMD_INQUIRY_ST11: + if (dev->type == ST506_XT_TYPE_ST11M || dev->type == ST506_XT_TYPE_ST11R) + switch (dev->state) { + case STATE_START_COMMAND: + st506_xt_log("ST506: INQUIRY (type=%i)\n", dev->type); + dev->buff_pos = 0; + dev->buff_cnt = 2; + dev->buff[0] = 0x80; /* "ST-11" */ + if (dev->spt == 17) + dev->buff[0] |= 0x40; /* MFM */ + dev->buff[1] = dev->misc; /* revision */ + dev->status = STAT_BSY | STAT_IO | STAT_REQ; + dev->state = STATE_SEND_DATA; + break; - case CMD_RAM_DIAGNOSTIC: + case STATE_SENT_DATA: + st506_complete(dev); + break; + + default: + break; + } + else { + st506_error(dev, ERR_BAD_COMMAND); + st506_complete(dev); + } + break; + + case CMD_V86P_POWEROFF: + if (dev->type >= ST506_XT_TYPE_VICTOR_V86P) { + /* + * Main BIOS (not the option ROM on disk) issues this. + * Not much we can do, since we don't have a physical disk + * to spin down, but handle this anyways so that we log + * something more reasonable than "unknown command". + * + * Entirely undocumented, but this is what's been observed: + * BIOS setting | Command sent + * 1 minutes | 1a 00 00 0c 02 00 + * 2 minutes | 1a 00 00 18 02 00 + * 3 minutes | 1a 00 00 24 02 00 + * 4 minutes | 1a 00 00 30 02 00 + * 5 minutes | 1a 00 00 3c 02 00 + * off | 1a 00 00 00 02 00 + */ + if (dev->command[3]) + st506_xt_log("ST506: Auto power-off in %d seconds (type=%i)\n", + dev->command[3] * 5, dev->type); + else + st506_xt_log("ST506: Auto power-off disabled (type=%i)\n", dev->type); + } else { + st506_error(dev, ERR_BAD_COMMAND); + } + st506_complete(dev); + break; + + case CMD_RAM_DIAGNOSTIC: #ifdef ENABLE_ST506_XT_LOG - st506_xt_log("ST506: RAM_DIAG\n"); + st506_xt_log("ST506: RAM_DIAG\n"); #endif - st506_complete(dev); - break; + st506_complete(dev); + break; - case CMD_CTRLR_DIAGNOSTIC: + case CMD_CTRLR_DIAGNOSTIC: #ifdef ENABLE_ST506_XT_LOG - st506_xt_log("ST506: CTRLR_DIAG\n"); + st506_xt_log("ST506: CTRLR_DIAG\n"); #endif - st506_complete(dev); - break; + st506_complete(dev); + break; - case CMD_SET_STEP_RATE_DTC: - if (dev->type == 1) { - /* For DTC, we are done. */ - st506_complete(dev); - } else if (dev->type == 11 || dev->type == 12) { - /* - * For Seagate ST-11, this is WriteGeometry. - * - * This writes the contents of the buffer to track 0. - * - * By the time this command is sent, it will have - * formatted the first track, so it should be good, - * and our sector buffer contains the magic data - * (see above) we need to write to it. - */ - (void)get_chs(dev, drive); - st506_xt_log("ST506: WRITE BUFFER (%i, %i/%i/%i, %i)\n", - dev->drive_sel, dev->cylinder, - dev->head, dev->sector, dev->count); + case CMD_SET_STEP_RATE_DTC: + if (dev->type == ST506_XT_TYPE_DTC_5150X) { + /* For DTC, we are done. */ + st506_complete(dev); + } else if (dev->type == ST506_XT_TYPE_ST11M || dev->type == ST506_XT_TYPE_ST11R) { + /* + * For Seagate ST-11, this is WriteGeometry. + * + * This writes the contents of the buffer to track 0. + * + * By the time this command is sent, it will have + * formatted the first track, so it should be good, + * and our sector buffer contains the magic data + * (see above) we need to write to it. + */ + (void) get_chs(dev, drive); + st506_xt_log("ST506: WRITE BUFFER (%i, %i/%i/%i, %i)\n", + dev->drive_sel, dev->cylinder, + dev->head, dev->sector, dev->count); - if (! get_sector(dev, drive, &addr)) { - st506_error(dev, ERR_BAD_PARAMETER); - st506_complete(dev); - return; - } + if (!get_sector(dev, drive, &addr)) { + st506_error(dev, ERR_BAD_PARAMETER); + st506_complete(dev); + return; + } - ui_sb_update_icon(SB_HDD | HDD_BUS_MFM, 1); + ui_sb_update_icon(SB_HDD | HDD_BUS_MFM, 1); - /* Write data to image. */ - hdd_image_write(drive->hdd_num, addr, 1, - (uint8_t *)dev->buff); + /* Write data to image. */ + hdd_image_write(drive->hdd_num, addr, 1, + (uint8_t *) dev->buff); - if (--dev->count == 0) { - ui_sb_update_icon(SB_HDD | HDD_BUS_MFM, 0); - st506_complete(dev); - break; - } + if (--dev->count == 0) { + ui_sb_update_icon(SB_HDD | HDD_BUS_MFM, 0); + st506_complete(dev); + break; + } - next_sector(dev, drive); - timer_advance_u64(&dev->timer, ST506_TIME); - break; - } else { - st506_error(dev, ERR_BAD_COMMAND); - st506_complete(dev); - } - break; + next_sector(dev, drive); + timer_advance_u64(&dev->timer, ST506_TIME); + break; + } else { + st506_error(dev, ERR_BAD_COMMAND); + st506_complete(dev); + } + break; - case CMD_GET_DRIVE_PARAMS_DTC: - switch (dev->state) { - case STATE_START_COMMAND: - dev->buff_pos = 0; - dev->buff_cnt = 4; - memset(dev->buff, 0x00, dev->buff_cnt); - dev->buff[0] = drive->tracks & 0xff; - dev->buff[1] = ((drive->tracks >> 2) & 0xc0) | dev->spt; - dev->buff[2] = drive->hpc - 1; - dev->status = STAT_BSY | STAT_IO | STAT_REQ; - dev->state = STATE_SEND_DATA; - break; + case CMD_GET_DRIVE_PARAMS_DTC: + switch (dev->state) { + case STATE_START_COMMAND: + dev->buff_pos = 0; + dev->buff_cnt = 4; + memset(dev->buff, 0x00, dev->buff_cnt); + dev->buff[0] = drive->tracks & 0xff; + dev->buff[1] = ((drive->tracks >> 2) & 0xc0) | dev->spt; + dev->buff[2] = drive->hpc - 1; + dev->status = STAT_BSY | STAT_IO | STAT_REQ; + dev->state = STATE_SEND_DATA; + break; - case STATE_SENT_DATA: - st506_complete(dev); - break; - } - break; + case STATE_SENT_DATA: + st506_complete(dev); + break; - case CMD_SET_GEOMETRY_DTC: - switch (dev->state) { - case STATE_START_COMMAND: - val = dev->command[1] & 0x01; - st506_xt_log("ST506: DTC_GET_GEOMETRY(%i) %i\n", - dev->drive_sel, val); - dev->buff_pos = 0; - dev->buff_cnt = 16; - dev->status = STAT_BSY | STAT_REQ; - dev->state = STATE_RECEIVE_DATA; - break; + default: + break; + } + break; - case STATE_RECEIVED_DATA: - /* FIXME: ignore the results. */ - st506_complete(dev); - break; - } - break; + case CMD_SET_GEOMETRY_DTC: + switch (dev->state) { + case STATE_START_COMMAND: + val = dev->command[1] & 0x01; + st506_xt_log("ST506: DTC_GET_GEOMETRY(%i) %i\n", + dev->drive_sel, val); + dev->buff_pos = 0; + dev->buff_cnt = 16; + dev->status = STAT_BSY | STAT_REQ; + dev->state = STATE_RECEIVE_DATA; + break; - case CMD_GET_GEOMETRY_DTC: - switch (dev->state) { - case STATE_START_COMMAND: - val = dev->command[1] & 0x01; - st506_xt_log("ST506: DTC_GET_GEOMETRY(%i) %i\n", - dev->drive_sel, val); - dev->buff_pos = 0; - dev->buff_cnt = 16; - memset(dev->buff, 0x00, dev->buff_cnt); - dev->buff[4] = drive->tracks & 0xff; - dev->buff[5] = (drive->tracks >> 8) & 0xff; - dev->buff[10] = drive->hpc; - dev->status = STAT_BSY | STAT_IO | STAT_REQ; - dev->state = STATE_SEND_DATA; - break; + case STATE_RECEIVED_DATA: + /* FIXME: ignore the results. */ + st506_complete(dev); + break; - case STATE_SENT_DATA: - st506_complete(dev); - break; - } - break; + default: + break; + } + break; - default: - if (dev->command[0] == CMD_WRITE_GEOMETRY_ST11) - fatal("CMD_WRITE_GEOMETRY_ST11\n"); + case CMD_GET_GEOMETRY_DTC: + switch (dev->state) { + case STATE_START_COMMAND: + val = dev->command[1] & 0x01; + st506_xt_log("ST506: DTC_GET_GEOMETRY(%i) %i\n", + dev->drive_sel, val); + dev->buff_pos = 0; + dev->buff_cnt = 16; + memset(dev->buff, 0x00, dev->buff_cnt); + dev->buff[4] = drive->tracks & 0xff; + dev->buff[5] = (drive->tracks >> 8) & 0xff; + dev->buff[10] = drive->hpc; + dev->status = STAT_BSY | STAT_IO | STAT_REQ; + dev->state = STATE_SEND_DATA; + break; + + case STATE_SENT_DATA: + st506_complete(dev); + break; + + default: + break; + } + break; + + default: + if (dev->command[0] == CMD_WRITE_GEOMETRY_ST11) + fatal("CMD_WRITE_GEOMETRY_ST11\n"); #ifdef ENABLE_ST506_XT_LOG - st506_xt_log("ST506: unknown command:\n"); + st506_xt_log("ST506: unknown command:\n"); #endif - st506_xt_log("ST506: %02x %02x %02x %02x %02x %02x\n", - dev->command[0], dev->command[1], dev->command[2], - dev->command[3], dev->command[4], dev->command[5]); - st506_error(dev, ERR_BAD_COMMAND); - st506_complete(dev); + st506_xt_log("ST506: %02x %02x %02x %02x %02x %02x\n", + dev->command[0], dev->command[1], dev->command[2], + dev->command[3], dev->command[4], dev->command[5]); + st506_error(dev, ERR_BAD_COMMAND); + st506_complete(dev); } } - /* Read from one of the registers. */ static uint8_t st506_read(uint16_t port, void *priv) { - hdc_t *dev = (hdc_t *)priv; + hdc_t *dev = (hdc_t *) priv; uint8_t ret = 0xff; switch (port & 3) { - case 0: /* read data */ - dev->status &= ~STAT_IRQ; - switch (dev->state) { - case STATE_COMPLETION_BYTE: - ret = dev->compl; - dev->status = 0x00; - dev->state = STATE_IDLE; - break; - - case STATE_SEND_DATA: - ret = dev->buff[dev->buff_pos++]; - if (dev->buff_pos == dev->buff_cnt) { - dev->buff_pos = 0; - dev->buff_cnt = 0; - dev->status = STAT_BSY; - dev->state = STATE_SENT_DATA; - timer_set_delay_u64(&dev->timer, ST506_TIME); - } - break; - } - break; + case 0: /* read data */ + dev->status &= ~STAT_IRQ; + switch (dev->state) { + case STATE_COMPLETION_BYTE: + ret = dev->compl ; + dev->status = 0x00; + dev->state = STATE_IDLE; + break; - case 1: /* read status */ - ret = dev->status; - if ((dev->irq_dma & DMA_ENA) && dma_get_drq(dev->dma)) - ret |= STAT_DRQ; - break; + case STATE_SEND_DATA: + ret = dev->buff[dev->buff_pos++]; + if (dev->buff_pos == dev->buff_cnt) { + dev->buff_pos = 0; + dev->buff_cnt = 0; + dev->status = STAT_BSY; + dev->state = STATE_SENT_DATA; + timer_set_delay_u64(&dev->timer, ST506_TIME); + } + break; - case 2: /* read option jumpers */ - ret = dev->switches; - break; + default: + break; + } + break; + + case 1: /* read status */ + ret = dev->status; + if ((dev->irq_dma & DMA_ENA) && dma_get_drq(dev->dma)) + ret |= STAT_DRQ; + break; + + case 2: /* read option jumpers */ + ret = dev->switches; + break; + + default: + break; } st506_xt_log("ST506: read(%04x) = %02x\n", port, ret); - return(ret); + return ret; } - /* Write to one of the registers. */ static void st506_write(uint16_t port, uint8_t val, void *priv) { - hdc_t *dev = (hdc_t *)priv; + hdc_t *dev = (hdc_t *) priv; st506_xt_log("ST506: write(%04x, %02x)\n", port, val); switch (port & 3) { - case 0: /* write data */ - switch (dev->state) { - case STATE_RECEIVE_COMMAND: /* command data */ - /* Write directly to the command buffer to avoid overwriting - the data buffer. */ - dev->command[dev->buff_pos++] = val; - if (dev->buff_pos == dev->buff_cnt) { - /* We have a new command. */ - dev->buff_pos = 0; - dev->buff_cnt = 0; - dev->status = STAT_BSY; - dev->state = STATE_START_COMMAND; - timer_set_delay_u64(&dev->timer, ST506_TIME); - } - break; + case 0: /* write data */ + switch (dev->state) { + case STATE_RECEIVE_COMMAND: /* command data */ + /* Write directly to the command buffer to avoid overwriting + the data buffer. */ + dev->command[dev->buff_pos++] = val; + if (dev->buff_pos == dev->buff_cnt) { + /* We have a new command. */ + dev->buff_pos = 0; + dev->buff_cnt = 0; + dev->status = STAT_BSY; + dev->state = STATE_START_COMMAND; + timer_set_delay_u64(&dev->timer, ST506_TIME); + } + break; - case STATE_RECEIVE_DATA: /* data */ - dev->buff[dev->buff_pos++] = val; - if (dev->buff_pos == dev->buff_cnt) { - dev->buff_pos = 0; - dev->buff_cnt = 0; - dev->status = STAT_BSY; - dev->state = STATE_RECEIVED_DATA; - timer_set_delay_u64(&dev->timer, ST506_TIME); - } - break; - } - break; + case STATE_RECEIVE_DATA: /* data */ + dev->buff[dev->buff_pos++] = val; + if (dev->buff_pos == dev->buff_cnt) { + dev->buff_pos = 0; + dev->buff_cnt = 0; + dev->status = STAT_BSY; + dev->state = STATE_RECEIVED_DATA; + timer_set_delay_u64(&dev->timer, ST506_TIME); + } + break; - case 1: /* controller reset */ - dev->status = 0x00; - break; + default: + break; + } + break; - case 2: /* generate controller-select-pulse */ - dev->status = STAT_BSY | STAT_CD | STAT_REQ; - dev->buff_pos = 0; - dev->buff_cnt = sizeof(dev->command); - dev->state = STATE_RECEIVE_COMMAND; - break; + case 1: /* controller reset */ + dev->status = 0x00; + break; - case 3: /* DMA/IRQ enable register */ - dev->irq_dma = val; + case 2: /* generate controller-select-pulse */ + dev->status = STAT_BSY | STAT_CD | STAT_REQ; + dev->buff_pos = 0; + dev->buff_cnt = sizeof(dev->command); + dev->state = STATE_RECEIVE_COMMAND; + break; - if (!(dev->irq_dma & DMA_ENA)) - dma_set_drq(dev->dma, 0); + case 3: /* DMA/IRQ enable register */ + dev->irq_dma = val; - if (!(dev->irq_dma & IRQ_ENA)) { - dev->status &= ~STAT_IRQ; - picintc(1 << dev->irq); - } - break; + if (!(dev->irq_dma & DMA_ENA)) + dma_set_drq(dev->dma, 0); + + if (!(dev->irq_dma & IRQ_ENA)) { + dev->status &= ~STAT_IRQ; + picintc(1 << dev->irq); + } + break; + + default: + break; } } - /* Write to ROM (or scratchpad RAM.) */ static void mem_write(uint32_t addr, uint8_t val, void *priv) { - hdc_t *dev = (hdc_t *)priv; - uint32_t ptr, mask = 0; + hdc_t *dev = (hdc_t *) priv; + uint32_t ptr; + uint32_t mask = 0; /* Ignore accesses to anything below the configured address, needed because of the emulator's 4k mapping granularity. */ if (addr < dev->bios_addr) - return; + return; addr -= dev->bios_addr; - switch(dev->type) { - case 11: /* ST-11M */ - case 12: /* ST-11R */ - mask = 0x1fff; /* ST-11 decodes RAM on each 8K block */ - break; + switch (dev->type) { + case ST506_XT_TYPE_ST11M: /* ST-11M */ + case ST506_XT_TYPE_ST11R: /* ST-11R */ + mask = 0x1fff; /* ST-11 decodes RAM on each 8K block */ + break; - default: - break; + default: + break; } addr &= dev->bios_rom.mask; ptr = (dev->bios_rom.mask & mask) - dev->bios_ram; - if (mask && ((addr & mask) > ptr) && - ((addr & mask) <= (ptr + dev->bios_ram))) - dev->scratch[addr & (dev->bios_ram - 1)] = val; + if (mask && ((addr & mask) > ptr) && ((addr & mask) <= (ptr + dev->bios_ram))) + dev->scratch[addr & (dev->bios_ram - 1)] = val; } - static uint8_t mem_read(uint32_t addr, void *priv) { - hdc_t *dev = (hdc_t *)priv; - uint32_t ptr, mask = 0; - uint8_t ret = 0xff; + const hdc_t *dev = (hdc_t *) priv; + uint32_t ptr; + uint32_t mask = 0; + uint8_t ret = 0xff; /* Ignore accesses to anything below the configured address, needed because of the emulator's 4k mapping granularity. */ if (addr < dev->bios_addr) - return 0xff; + return 0xff; addr -= dev->bios_addr; - switch(dev->type) { - case 0: /* Xebec */ - if (addr >= 0x001000) { + switch (dev->type) { + case ST506_XT_TYPE_XEBEC: /* Xebec */ + if (addr >= 0x001000) { #ifdef ENABLE_ST506_XT_LOG - st506_xt_log("ST506: Xebec ROM access(0x%06lx)\n", addr); + st506_xt_log("ST506: Xebec ROM access(0x%06lx)\n", addr); #endif - return 0xff; - } - break; + return 0xff; + } + break; - case 1: /* DTC */ - default: - if (addr >= 0x002000) { + case ST506_XT_TYPE_WDXT_GEN: /* WDXT-GEN */ + if (addr >= 0x002000) { #ifdef ENABLE_ST506_XT_LOG - st506_xt_log("ST506: DTC-5150X ROM access(0x%06lx)\n", addr); + st506_xt_log("ST506: WDXT-GEN ROM access(0x%06lx)\n", addr); #endif - return 0xff; - } - break; + return 0xff; + } + break; - case 11: /* ST-11M */ - case 12: /* ST-11R */ - mask = 0x1fff; /* ST-11 decodes RAM on each 8K block */ - break; + case ST506_XT_TYPE_DTC_5150X: /* DTC */ + default: + if (addr >= 0x002000) { +#ifdef ENABLE_ST506_XT_LOG + st506_xt_log("ST506: DTC-5150X ROM access(0x%06lx)\n", addr); +#endif + return 0xff; + } + break; - /* default: - break; */ + case ST506_XT_TYPE_ST11M: /* ST-11M */ + case ST506_XT_TYPE_ST11R: /* ST-11R */ + mask = 0x1fff; /* ST-11 decodes RAM on each 8K block */ + break; +#if 0 + default: + break; +#endif } addr = addr & dev->bios_rom.mask; ptr = (dev->bios_rom.mask & mask) - dev->bios_ram; - if (mask && ((addr & mask) > ptr) && - ((addr & mask) <= (ptr + dev->bios_ram))) - ret = dev->scratch[addr & (dev->bios_ram - 1)]; + if (mask && ((addr & mask) > ptr) && ((addr & mask) <= (ptr + dev->bios_ram))) + ret = dev->scratch[addr & (dev->bios_ram - 1)]; else - ret = dev->bios_rom.rom[addr]; + ret = dev->bios_rom.rom[addr]; - return(ret); + return ret; } - /* * Set up and load the ROM BIOS for this controller. * @@ -1308,208 +1453,284 @@ static void loadrom(hdc_t *dev, const char *fn) { uint32_t size; - FILE *fp; + FILE *fp; if (fn == NULL) { #ifdef ENABLE_ST506_XT_LOG - st506_xt_log("ST506: NULL BIOS ROM file pointer!\n"); + st506_xt_log("ST506: NULL BIOS ROM file pointer!\n"); #endif - return; + return; } if ((fp = rom_fopen((char *) fn, "rb")) == NULL) { - st506_xt_log("ST506: BIOS ROM '%s' not found!\n", fn); - return; + st506_xt_log("ST506: BIOS ROM '%s' not found!\n", fn); + return; } /* Initialize the ROM entry. */ memset(&dev->bios_rom, 0x00, sizeof(rom_t)); /* Manually load and process the ROM image. */ - (void)fseek(fp, 0L, SEEK_END); + (void) fseek(fp, 0L, SEEK_END); size = ftell(fp); - (void)fseek(fp, 0L, SEEK_SET); + (void) fseek(fp, 0L, SEEK_SET); /* Load the ROM data. */ - dev->bios_rom.rom = (uint8_t *)malloc(size); + dev->bios_rom.rom = (uint8_t *) malloc(size); memset(dev->bios_rom.rom, 0xff, size); if (fread(dev->bios_rom.rom, 1, size, fp) != size) - fatal("ST-506 XT loadrom(): Error reading data\n"); - (void)fclose(fp); + fatal("ST-506 XT loadrom(): Error reading data\n"); + (void) fclose(fp); /* Set up an address mask for this memory. */ - dev->bios_size = size; + dev->bios_size = size; dev->bios_rom.mask = (size - 1); /* Map this system into the memory map. */ mem_mapping_add(&dev->bios_rom.mapping, dev->bios_addr, size, - mem_read,NULL,NULL, mem_write,NULL,NULL, - dev->bios_rom.rom, MEM_MAPPING_EXTERNAL, dev); + mem_read, NULL, NULL, mem_write, NULL, NULL, + dev->bios_rom.rom, MEM_MAPPING_EXTERNAL, dev); } - static void -loadhd(hdc_t *dev, int c, int d, const char *fn) +loadhd(hdc_t *dev, int c, int d, UNUSED(const char *fn)) { drive_t *drive = &dev->drives[c]; - if (! hdd_image_load(d)) { - drive->present = 0; - return; + if (!hdd_image_load(d)) { + drive->present = 0; + return; } - + /* Make sure we can do this. */ /* Allow 31 sectors per track on RLL controllers, for the ST225R, which is 667/2/31. */ if ((hdd[d].spt != dev->spt) && (hdd[d].spt != 31) && (dev->spt != 26)) { - /* - * Uh-oh, MFM/RLL mismatch. - * - * Although this would be no issue in the code itself, - * most of the BIOSes were hardwired to whatever their - * native SPT setting was, so, do not allow this here. - */ - st506_xt_log("ST506: drive%i: MFM/RLL mismatch (%i/%i)\n", - c, hdd[d].spt, dev->spt); - hdd_image_close(d); - drive->present = 0; - return; + /* + * Uh-oh, MFM/RLL mismatch. + * + * Although this would be no issue in the code itself, + * most of the BIOSes were hardwired to whatever their + * native SPT setting was, so, do not allow this here. + */ + st506_xt_log("ST506: drive%i: MFM/RLL mismatch (%i/%i)\n", + c, hdd[d].spt, dev->spt); + hdd_image_close(d); + drive->present = 0; + return; } - drive->spt = (uint8_t)hdd[d].spt; - drive->hpc = (uint8_t)hdd[d].hpc; - drive->tracks = (uint16_t)hdd[d].tracks; + drive->spt = (uint8_t) hdd[d].spt; + drive->hpc = (uint8_t) hdd[d].hpc; + drive->tracks = (uint16_t) hdd[d].tracks; drive->hdd_num = d; drive->present = 1; } - /* Set the "drive type" switches for the IBM Xebec controller. */ static void -set_switches(hdc_t *dev) +set_switches(hdc_t *dev, hd_type_t *hdt, int num) { - drive_t *drive; - int c, d; + const drive_t *drive; + int e; dev->switches = 0x00; - for (d = 0; d < MFM_NUM; d++) { - drive = &dev->drives[d]; + for (uint8_t d = 0; d < MFM_NUM; d++) { + drive = &dev->drives[d]; - if (! drive->present) continue; + if (!drive->present) { + if (dev->type == ST506_XT_TYPE_WD1002A_WX1_NOBIOS) + dev->switches |= (0x33 << (d ? 0 : 2)); + continue; + } - for (c = 0; c < 4; c++) { - if ((drive->spt == hd_types[c].spt) && - (drive->hpc == hd_types[c].hpc) && - (drive->tracks == hd_types[c].tracks)) { - dev->switches |= (c << (d ? 0 : 2)); - break; - } - } + for (int c = 0; c < num; c++) { + /* Does the Xebec also support more than 4 types? */ + if ((drive->spt == hdt[c].spt) && (drive->hpc == hdt[c].hpc) && (drive->tracks == hdt[c].tracks)) { + /* Olivetti M24/M240: Move the upper 2 bites up by 2 bits, as the + layout is as follows: D0_3 D0_2 D1_3 D1_2 D0_1 D0_0 D1_1 D1_0. */ + if (dev->type == ST506_XT_TYPE_WD1002A_WX1_NOBIOS) + e = (c & 0x03) | ((c >> 2) << 4); + else + e = c; + dev->switches |= (e << (d ? 0 : 2)); + break; + } + } #ifdef ENABLE_ST506_XT_LOG - st506_xt_log("ST506: "); - if (c == 4) - st506_xt_log("*WARNING* drive%i unsupported", d); - else - st506_xt_log("drive%i is type %i", d, c); - st506_xt_log(" (%i/%i/%i)\n", drive->tracks, drive->hpc, drive->spt); + st506_xt_log("ST506: "); + if (c == num) + st506_xt_log("*WARNING* drive%i unsupported", d); + else + st506_xt_log("drive%i is type %i", d, c); + st506_xt_log(" (%i/%i/%i)\n", drive->tracks, drive->hpc, drive->spt); #endif } } - static void * st506_init(const device_t *info) { - char *fn = NULL; - hdc_t *dev; - int i, c; + const char *fn = NULL; + hdc_t *dev; + int i; + int c; - dev = (hdc_t *)malloc(sizeof(hdc_t)); + dev = (hdc_t *) malloc(sizeof(hdc_t)); memset(dev, 0x00, sizeof(hdc_t)); dev->type = info->local & 255; /* Set defaults for the controller. */ - dev->spt = MFM_SECTORS; - dev->base = 0x0320; - dev->irq = 5; - dev->dma = 3; + dev->spt = MFM_SECTORS; + dev->base = 0x0320; + dev->irq = 5; + dev->dma = 3; dev->bios_addr = 0xc8000; - dev->nr_err = ERR_NOT_READY; + dev->nr_err = ERR_NOT_READY; - switch(dev->type) { - case 0: /* Xebec (MFM) */ - fn = XEBEC_BIOS_FILE; - break; + switch (dev->type) { + case ST506_XT_TYPE_XEBEC: /* Xebec (MFM) */ + fn = XEBEC_BIOS_FILE; + break; - case 1: /* DTC5150 (MFM) */ - fn = DTC_BIOS_FILE; - dev->switches = 0xff; - break; + case ST506_XT_TYPE_WDXT_GEN: /* WDXT-GEN (MFM) */ + fn = WDXT_GEN_BIOS_FILE; + break; - case 12: /* Seagate ST-11R (RLL) */ - dev->spt = RLL_SECTORS; - /*FALLTHROUGH*/ + case ST506_XT_TYPE_DTC_5150X: /* DTC5150 (MFM) */ + fn = DTC_BIOS_FILE; + dev->switches = 0xff; + break; - case 11: /* Seagate ST-11M (MFM) */ - dev->nr_err = ERR_NOT_AVAILABLE; - dev->switches = 0x01; /* fixed */ - dev->misc = device_get_config_int("revision"); - switch (dev->misc) { - case 5: /* v1.7 */ - fn = ST11_BIOS_FILE_OLD; - break; + case ST506_XT_TYPE_ST11R: /* Seagate ST-11R (RLL) */ + dev->spt = RLL_SECTORS; + fallthrough; - case 19: /* v2.0 */ - fn = ST11_BIOS_FILE_NEW; - break; - } - dev->base = device_get_config_hex16("base"); - dev->irq = device_get_config_int("irq"); - dev->bios_addr = device_get_config_hex20("bios_addr"); - dev->bios_ram = 64; /* scratch RAM size */ + case ST506_XT_TYPE_ST11M: /* Seagate ST-11M (MFM) */ + dev->nr_err = ERR_NOT_AVAILABLE; + dev->switches = 0x01; /* fixed */ + dev->misc = device_get_config_int("revision"); + switch (dev->misc) { + case 5: /* v1.7 */ + fn = ST11_BIOS_FILE_OLD; + break; - /* - * Industrial Madness Alert. - * - * With the ST-11 controller, Seagate decided to act - * like they owned the industry, and reserved the - * first cylinder of a drive for the controller. So, - * when the host accessed cylinder 0, that would be - * the actual cylinder 1 on the drive, and so on. - */ - dev->cyl_off = 1; - break; + case 19: /* v2.0 */ + fn = ST11_BIOS_FILE_NEW; + break; - case 21: /* Western Digital WD1002A-WX1 (MFM) */ - dev->nr_err = ERR_NOT_AVAILABLE; - fn = WD1002A_WX1_BIOS_FILE; - /* The switches are read in reverse: 0 = closed, 1 = open. - Both open means MFM, 17 sectors per track. */ - dev->switches = 0x30; /* autobios */ - dev->base = device_get_config_hex16("base"); - dev->irq = device_get_config_int("irq"); - if (dev->irq == 2) - dev->switches |= 0x40; - dev->bios_addr = device_get_config_hex20("bios_addr"); - break; + default: + break; + } + dev->base = device_get_config_hex16("base"); + dev->irq = device_get_config_int("irq"); + dev->bios_addr = device_get_config_hex20("bios_addr"); + dev->bios_ram = 64; /* scratch RAM size */ - case 22: /* Western Digital WD1002A-27X (RLL) */ - dev->nr_err = ERR_NOT_AVAILABLE; - fn = WD1002A_27X_BIOS_FILE; - /* The switches are read in reverse: 0 = closed, 1 = open. - Both closed means translate 26 sectors per track to 17, - SW6 closed, SW5 open means 26 sectors per track. */ - dev->switches = device_get_config_int("translate") ? 0x00 : 0x10; /* autobios */ - dev->spt = RLL_SECTORS; - dev->base = device_get_config_hex16("base"); - dev->irq = device_get_config_int("irq"); - if (dev->irq == 2) - dev->switches |= 0x40; - dev->bios_addr = device_get_config_hex20("bios_addr"); - break; + /* + * Industrial Madness Alert. + * + * With the ST-11 controller, Seagate decided to act + * like they owned the industry, and reserved the + * first cylinder of a drive for the controller. So, + * when the host accessed cylinder 0, that would be + * the actual cylinder 1 on the drive, and so on. + */ + dev->cyl_off = 1; + break; + + case ST506_XT_TYPE_WD1002A_WX1: /* Western Digital WD1002A-WX1 (MFM) */ + dev->nr_err = ERR_NOT_AVAILABLE; + fn = WD1002A_WX1_BIOS_FILE; + /* The switches are read in reverse: 0 = closed, 1 = open. + Both open means MFM, 17 sectors per track. */ + dev->switches = 0x30; /* autobios */ + dev->base = device_get_config_hex16("base"); + dev->irq = device_get_config_int("irq"); + if (dev->irq == 2) + dev->switches |= 0x40; + dev->bios_addr = device_get_config_hex20("bios_addr"); + break; + + case ST506_XT_TYPE_WD1002A_WX1_NOBIOS: /* Western Digital WD1002A-WX1 (MFM, No BIOS) */ + /* Supported base addresses: 320h, 324h, 328h, 32Ch. */ + dev->nr_err = ERR_NOT_AVAILABLE; + fn = NULL; + break; + + case ST506_XT_TYPE_WD1004A_WX1: /* Western Digital WD1004A-WX1 (MFM) */ + dev->nr_err = ERR_NOT_AVAILABLE; + fn = WD1004A_WX1_BIOS_FILE; + /* The switches are read in reverse: 0 = closed, 1 = open. + Both open means MFM, 17 sectors per track. */ + dev->switches = 0x10; /* autobios */ + dev->base = device_get_config_hex16("base"); + dev->irq = device_get_config_int("irq"); + if (dev->irq == 2) + dev->switches |= 0x40; + dev->bios_addr = device_get_config_hex20("bios_addr"); + break; + + case ST506_XT_TYPE_WD1002A_27X: /* Western Digital WD1002A-27X (RLL) */ + dev->nr_err = ERR_NOT_AVAILABLE; + fn = WD1002A_27X_BIOS_FILE; + /* The switches are read in reverse: 0 = closed, 1 = open. + Both closed means translate 26 sectors per track to 17, + SW6 closed, SW5 open means 26 sectors per track. */ + dev->switches = device_get_config_int("translate") ? 0x00 : 0x10; /* autobios */ + dev->spt = RLL_SECTORS; + dev->base = device_get_config_hex16("base"); + dev->irq = device_get_config_int("irq"); + if (dev->irq == 2) + dev->switches |= 0x40; + dev->bios_addr = device_get_config_hex20("bios_addr"); + break; + + case ST506_XT_TYPE_WD1004_27X: /* Western Digital WD1004-27X (RLL) */ + dev->nr_err = ERR_NOT_AVAILABLE; + fn = WD1004_27X_BIOS_FILE; + /* The switches are read in reverse: 0 = closed, 1 = open. + Both closed means translate 26 sectors per track to 17, + SW6 closed, SW5 open means 26 sectors per track. */ + dev->switches = device_get_config_int("translate") ? 0x00 : 0x10; /* autobios */ + dev->spt = RLL_SECTORS; + dev->base = device_get_config_hex16("base"); + dev->irq = device_get_config_int("irq"); + if (dev->irq == 2) + dev->switches |= 0x40; + dev->bios_addr = device_get_config_hex20("bios_addr"); + break; + + case ST506_XT_TYPE_WD1004A_27X: /* Western Digital WD1004A-27X (RLL) */ + dev->nr_err = ERR_NOT_AVAILABLE; + fn = WD1004A_27X_BIOS_FILE; + /* The switches are read in reverse: 0 = closed, 1 = open. + Both closed means translate 26 sectors per track to 17, + SW6 closed, SW5 open means 26 sectors per track. */ + dev->switches = device_get_config_int("translate") ? 0x00 : 0x10; /* autobios */ + dev->spt = RLL_SECTORS; + dev->base = device_get_config_hex16("base"); + dev->irq = device_get_config_int("irq"); + if (dev->irq == 2) + dev->switches |= 0x40; + dev->bios_addr = device_get_config_hex20("bios_addr"); + break; + + case ST506_XT_TYPE_VICTOR_V86P: /* Victor V86P (RLL) */ + fn = VICTOR_V86P_BIOS_FILE; + break; + + case ST506_XT_TYPE_TOSHIBA_T1200: /* Toshiba T1200 */ + fn = NULL; + dev->base = 0x01f0; + dev->switches = 0x0c; + break; + + default: + break; } /* Load the ROM BIOS. */ @@ -1517,383 +1738,648 @@ st506_init(const device_t *info) /* Set up the I/O region. */ io_sethandler(dev->base, 4, - st506_read,NULL,NULL, st506_write,NULL,NULL, dev); + st506_read, NULL, NULL, st506_write, NULL, NULL, dev); /* Add the timer. */ timer_add(&dev->timer, st506_callback, dev, 0); st506_xt_log("ST506: %s (I/O=%03X, IRQ=%i, DMA=%i, BIOS @0x%06lX, size %lu)\n", - info->name,dev->base,dev->irq,dev->dma, dev->bios_addr,dev->bios_size); + info->name, dev->base, dev->irq, dev->dma, dev->bios_addr, dev->bios_size); /* Load any drives configured for us. */ #ifdef ENABLE_ST506_XT_LOG st506_xt_log("ST506: looking for disks...\n"); #endif for (c = 0, i = 0; i < HDD_NUM; i++) { - if ((hdd[i].bus == HDD_BUS_MFM) && (hdd[i].mfm_channel < MFM_NUM)) { - st506_xt_log("ST506: disk '%s' on channel %i\n", - hdd[i].fn, hdd[i].mfm_channel); - loadhd(dev, hdd[i].mfm_channel, i, hdd[i].fn); + if ((hdd[i].bus == HDD_BUS_MFM) && (hdd[i].mfm_channel < MFM_NUM)) { + st506_xt_log("ST506: disk '%s' on channel %i\n", + hdd[i].fn, hdd[i].mfm_channel); + loadhd(dev, hdd[i].mfm_channel, i, hdd[i].fn); - if (++c > MFM_NUM) break; - } + if (++c > MFM_NUM) + break; + } } st506_xt_log("ST506: %i disks loaded.\n", c); /* For the Xebec, set the switches now. */ - if (dev->type == 0) - set_switches(dev); + if (dev->type == ST506_XT_TYPE_XEBEC) + set_switches(dev, (hd_type_t *) hd_types, 4); + else if (dev->type == ST506_XT_TYPE_WD1002A_WX1_NOBIOS) + set_switches(dev, (hd_type_t *) hd_types_olivetti, 16); /* Initial "active" drive parameters. */ for (c = 0; c < MFM_NUM; c++) { - dev->drives[c].cfg_cyl = dev->drives[c].tracks; - dev->drives[c].cfg_hpc = dev->drives[c].hpc; - dev->drives[c].cfg_spt = dev->drives[c].spt; + dev->drives[c].cfg_cyl = dev->drives[c].tracks; + dev->drives[c].cfg_hpc = dev->drives[c].hpc; + dev->drives[c].cfg_spt = dev->drives[c].spt; } - return(dev); + return dev; } - static void st506_close(void *priv) { - hdc_t *dev = (hdc_t *)priv; - drive_t *drive; - int d; + hdc_t *dev = (hdc_t *) priv; + const drive_t *drive; - for (d = 0; d < MFM_NUM; d++) { - drive = &dev->drives[d]; + for (uint8_t d = 0; d < MFM_NUM; d++) { + drive = &dev->drives[d]; - hdd_image_close(drive->hdd_num); + hdd_image_close(drive->hdd_num); } if (dev->bios_rom.rom != NULL) { - free(dev->bios_rom.rom); - dev->bios_rom.rom = NULL; + free(dev->bios_rom.rom); + dev->bios_rom.rom = NULL; } free(dev); } - static int xebec_available(void) { - return(rom_present(XEBEC_BIOS_FILE)); + return (rom_present(XEBEC_BIOS_FILE)); } +static int +wdxt_available(void) +{ + return (rom_present(WDXT_GEN_BIOS_FILE)); +} static int dtc5150x_available(void) { - return(rom_present(DTC_BIOS_FILE)); + return (rom_present(DTC_BIOS_FILE)); } static int st11_m_available(void) { - return(rom_present(ST11_BIOS_FILE_OLD) && rom_present(ST11_BIOS_FILE_NEW)); + return (rom_present(ST11_BIOS_FILE_OLD) && rom_present(ST11_BIOS_FILE_NEW)); } static int st11_r_available(void) { - return(rom_present(ST11_BIOS_FILE_OLD) && rom_present(ST11_BIOS_FILE_NEW)); + return (rom_present(ST11_BIOS_FILE_OLD) && rom_present(ST11_BIOS_FILE_NEW)); } static int wd1002a_wx1_available(void) { - return(rom_present(WD1002A_WX1_BIOS_FILE)); + return (rom_present(WD1002A_WX1_BIOS_FILE)); } static int wd1002a_27x_available(void) { - return(rom_present(WD1002A_27X_BIOS_FILE)); + return (rom_present(WD1002A_27X_BIOS_FILE)); } +static int +wd1004a_wx1_available(void) +{ + return (rom_present(WD1004A_WX1_BIOS_FILE)); +} +static int +wd1004_27x_available(void) +{ + return (rom_present(WD1004_27X_BIOS_FILE)); +} + +static int +wd1004a_27x_available(void) +{ + return (rom_present(WD1004A_27X_BIOS_FILE)); +} + +static int +victor_v86p_available(void) +{ + return (rom_present(VICTOR_V86P_BIOS_FILE)); +} + +// clang-format off static const device_config_t dtc_config[] = { { - "bios_addr", "BIOS address", CONFIG_HEX20, "", 0xc8000, "", { 0 }, - { - { - "Disabled", 0x00000 - }, - { - "C800H", 0xc8000 - }, - { - "CA00H", 0xca000 - }, - { - "D800H", 0xd8000 - }, - { - "F400H", 0xf4000 - }, - { - "" - } - } + .name = "bios_addr", + .description = "BIOS address", + .type = CONFIG_HEX20, + .default_string = "", + .default_int = 0xc8000, + .file_filter = "", + .spinner = { 0 }, + .selection = { + { .description = "Disabled", .value = 0x00000 }, + { .description = "C800H", .value = 0xc8000 }, + { .description = "CA00H", .value = 0xca000 }, + { .description = "D800H", .value = 0xd8000 }, + { .description = "F400H", .value = 0xf4000 }, + { .description = "" } + } }, - { - "", "", -1 - } + { .name = "", .description = "", .type = CONFIG_END } }; static const device_config_t st11_config[] = { { - "base", "Address", CONFIG_HEX16, "", 0x0320, "", { 0 }, - { - { - "320H", 0x0320 - }, - { - "324H", 0x0324 - }, - { - "328H", 0x0328 - }, - { - "32CH", 0x032c - }, - { - "" - } - } + .name = "base", + .description = "Address", + .type = CONFIG_HEX16, + .default_string = "", + .default_int = 0x0320, + .file_filter = "", + .spinner = { 0 }, + .selection = { + { .description = "320H", .value = 0x0320 }, + { .description = "324H", .value = 0x0324 }, + { .description = "328H", .value = 0x0328 }, + { .description = "32CH", .value = 0x032c }, + { .description = "" } + } }, { - "irq", "IRQ", CONFIG_SELECTION, "", 5, "", { 0 }, - { - { - "IRQ 2", 2 - }, - { - "IRQ 5", 5 - }, - { - "" - } - } + .name = "irq", + .description = "IRQ", + .type = CONFIG_SELECTION, + .default_string = "", + .default_int = 5, + .file_filter = "", + .spinner = { 0 }, + .selection = { + { .description = "IRQ 2", .value = 2 }, + { .description = "IRQ 5", .value = 5 }, + { .description = "" } + } }, { - "bios_addr", "BIOS address", CONFIG_HEX20, "", 0xc8000, "", { 0 }, - { - { - "Disabled", 0x00000 - }, - { - "C800H", 0xc8000 - }, - { - "D000H", 0xd0000 - }, - { - "D800H", 0xd8000 - }, - { - "E000H", 0xe0000 - }, - { - "" - } - } + .name = "bios_addr", + .description = "BIOS address", + .type = CONFIG_HEX20, + .default_string = "", + .default_int = 0xc8000, + .file_filter = "", + .spinner = { 0 }, + .selection = { + { .description = "Disabled", .value = 0x00000 }, + { .description = "C800H", .value = 0xc8000 }, + { .description = "D000H", .value = 0xd0000 }, + { .description = "D800H", .value = 0xd8000 }, + { .description = "E000H", .value = 0xe0000 }, + { .description = "" } + } }, { - "revision", "Board Revision", CONFIG_SELECTION, "", 19, "", { 0 }, - { - { - "Rev. 05 (v1.7)", 5 - }, - { - "Rev. 19 (v2.0)", 19 - }, - { - "" - } - } + .name = "revision", + .description = "Board Revision", + .type = CONFIG_SELECTION, + .default_string = "", + .default_int = 19, + .file_filter = "", + .spinner = { 0 }, + .selection = { + { .description = "Rev. 05 (v1.7)", .value = 5 }, + { .description = "Rev. 19 (v2.0)", .value = 19 }, + { .description = "" } + } }, - { - "", "", -1 - } + { .name = "", .description = "", .type = CONFIG_END } }; static const device_config_t wd_config[] = { { - "bios_addr", "BIOS address", CONFIG_HEX20, "", 0xc8000, "", { 0 }, - { - { - "Disabled", 0x00000 - }, - { - "C800H", 0xc8000 - }, - { - "" - } - } + .name = "bios_addr", + .description = "BIOS address", + .type = CONFIG_HEX20, + .default_string = "", + .default_int = 0xc8000, + .file_filter = "", + .spinner = { 0 }, + .selection = { + { .description = "Disabled", .value = 0x00000 }, + { .description = "C800H", .value = 0xc8000 }, + { .description = "" } + } }, { - "base", "Address", CONFIG_HEX16, "", 0x0320, "", { 0 }, - { - { - "320H", 0x0320 - }, - { - "324H", 0x0324 - }, - { - "" - } - } + .name = "base", + .description = "Address", + .type = CONFIG_HEX16, + .default_string = "", + .default_int = 0x0320, + .file_filter = "", + .spinner = { 0 }, + .selection = { + { .description = "320H", .value = 0x0320 }, + { .description = "324H", .value = 0x0324 }, + { .description = "" } + } }, { - "irq", "IRQ", CONFIG_SELECTION, "", 5, "", { 0 }, - { - { - "IRQ 2", 2 - }, - { - "IRQ 5", 5 - }, - { - "" - } - } + .name = "irq", + .description = "IRQ", + .type = CONFIG_SELECTION, + .default_string = "", + .default_int = 5, + .file_filter = "", + .spinner = { 0 }, + .selection = { + { .description = "IRQ 2", .value = 2 }, + { .description = "IRQ 5", .value = 5 }, + { .description = "" } + } + }, + { .name = "", .description = "", .type = CONFIG_END } +}; + +static const device_config_t wd_nobios_config[] = { + { + .name = "base", + .description = "Address", + .type = CONFIG_HEX16, + .default_string = "", + .default_int = 0x0320, + .file_filter = "", + .spinner = { 0 }, + .selection = { + { .description = "320H", .value = 0x0320 }, + { .description = "324H", .value = 0x0324 }, + { .description = "" } + } }, { - "", "", -1 - } + .name = "irq", + .description = "IRQ", + .type = CONFIG_SELECTION, + .default_string = "", + .default_int = 5, + .file_filter = "", + .spinner = { 0 }, + .selection = { + { .description = "IRQ 2", .value = 2 }, + { .description = "IRQ 5", .value = 5 }, + { .description = "" } + } + }, + { .name = "", .description = "", .type = CONFIG_END } }; static const device_config_t wd_rll_config[] = { { - "bios_addr", "BIOS address", CONFIG_HEX20, "", 0xc8000, "", { 0 }, - { - { - "Disabled", 0x00000 - }, - { - "C800H", 0xc8000 - }, - { - "" - } - } + .name = "bios_addr", + .description = "BIOS address", + .type = CONFIG_HEX20, + .default_string = "", + .default_int = 0xc8000, + .file_filter = "", + .spinner = { 0 }, + .selection = { + { .description = "Disabled", .value = 0x00000 }, + { .description = "C800H", .value = 0xc8000 }, + { .description = "" } + } }, { - "base", "Address", CONFIG_HEX16, "", 0x0320, "", { 0 }, - { - { - "320H", 0x0320 - }, - { - "324H", 0x0324 - }, - { - "" - } - } + .name = "base", + .description = "Address", + .type = CONFIG_HEX16, + .default_string = "", + .default_int = 0x0320, + .file_filter = "", + .spinner = { 0 }, + .selection = { + { .description = "320H", .value = 0x0320 }, + { .description = "324H", .value = 0x0324 }, + { .description = "" } + } }, { - "irq", "IRQ", CONFIG_SELECTION, "", 5, "", { 0 }, - { - { - "IRQ 2", 2 - }, - { - "IRQ 5", 5 - }, - { - "" - } - } + .name = "irq", + .description = "IRQ", + .type = CONFIG_SELECTION, + .default_string = "", + .default_int = 5, + .file_filter = "", + .spinner = { 0 }, + .selection = { + { .description = "IRQ 2", .value = 2 }, + { .description = "IRQ 5", .value = 5 }, + { .description = "" } + } }, { - "translate", "Translate 26 -> 17", CONFIG_SELECTION, "", 0, "", { 0 }, - { - { - "Off", 0 - }, - { - "On", 1 - }, - { - "" - } - } + .name = "translate", + .description = "Translate 26 -> 17", + .type = CONFIG_SELECTION, + .default_string = "", + .default_int = 0, + .file_filter = "", + .spinner = { 0 }, + .selection = { + { .description = "Off", .value = 0 }, + { .description = "On", .value = 1 }, + { .description = "" } + } }, - { - "", "", -1 - } + { .name = "", .description = "", .type = CONFIG_END } }; +static const device_config_t wd1004a_config[] = { + { + .name = "bios_addr", + .description = "BIOS address", + .type = CONFIG_HEX20, + .default_string = "", + .default_int = 0xc8000, + .file_filter = "", + .spinner = { 0 }, + .selection = { + { .description = "Disabled", .value = 0x00000 }, + { .description = "C800H", .value = 0xc8000 }, + { .description = "" } + } + }, + { + .name = "base", + .description = "Address", + .type = CONFIG_HEX16, + .default_string = "", + .default_int = 0x0320, + .file_filter = "", + .spinner = { 0 }, + .selection = { + { .description = "320H", .value = 0x0320 }, + { .description = "324H", .value = 0x0324 }, + { .description = "" } + } + }, + { + .name = "irq", + .description = "IRQ", + .type = CONFIG_SELECTION, + .default_string = "", + .default_int = 5, + .file_filter = "", + .spinner = { 0 }, + .selection = { + { .description = "IRQ 2", .value = 2 }, + { .description = "IRQ 5", .value = 5 }, + { .description = "" } + } + }, + { .name = "", .description = "", .type = CONFIG_END } +}; + +static const device_config_t wd1004_rll_config[] = { + { + .name = "bios_addr", + .description = "BIOS address", + .type = CONFIG_HEX20, + .default_string = "", + .default_int = 0xc8000, + .file_filter = "", + .spinner = { 0 }, + .selection = { + { .description = "Disabled", .value = 0x00000 }, + { .description = "C800H", .value = 0xc8000 }, + { .description = "CA00H", .value = 0xca000 }, + { .description = "CC00H", .value = 0xcc000 }, + { .description = "CE00H", .value = 0xce000 }, + { .description = "" } + } + }, + { + .name = "base", + .description = "Address", + .type = CONFIG_HEX16, + .default_string = "", + .default_int = 0x0320, + .file_filter = "", + .spinner = { 0 }, + .selection = { + { .description = "320H", .value = 0x0320 }, + { .description = "324H", .value = 0x0324 }, + { .description = "328H", .value = 0x0328 }, + { .description = "32CH", .value = 0x032c }, + { .description = "" } + } + }, + { + .name = "irq", + .description = "IRQ", + .type = CONFIG_SELECTION, + .default_string = "", + .default_int = 5, + .file_filter = "", + .spinner = { 0 }, + .selection = { + { .description = "IRQ 2", .value = 2 }, + { .description = "IRQ 5", .value = 5 }, + { .description = "" } + } + }, + { + .name = "translate", + .description = "Translate 26 -> 17", + .type = CONFIG_SELECTION, + .default_string = "", + .default_int = 0, + .file_filter = "", + .spinner = { 0 }, + .selection = { + { .description = "Off", .value = 0 }, + { .description = "On", .value = 1 }, + { .description = "" } + } + }, + { .name = "", .description = "", .type = CONFIG_END } +}; + +// clang-format on const device_t st506_xt_xebec_device = { - "IBM PC Fixed Disk Adapter (MFM)", - "st506_xt", - DEVICE_ISA, - (HDD_BUS_MFM << 8) | 0, - st506_init, st506_close, NULL, - { xebec_available }, - NULL, NULL, - NULL + .name = "IBM PC Fixed Disk Adapter (MFM)", + .internal_name = "st506_xt", + .flags = DEVICE_ISA, + .local = (HDD_BUS_MFM << 8) | ST506_XT_TYPE_XEBEC, + .init = st506_init, + .close = st506_close, + .reset = NULL, + { .available = xebec_available }, + .speed_changed = NULL, + .force_redraw = NULL, + .config = NULL +}; + +const device_t st506_xt_wdxt_gen_device = { + .name = "Western Digital WDXT-GEN (MFM)", + .internal_name = "st506_xt_gen", + .flags = DEVICE_ISA, + .local = (HDD_BUS_MFM << 8) | ST506_XT_TYPE_WDXT_GEN, + .init = st506_init, + .close = st506_close, + .reset = NULL, + { .available = wdxt_available }, + .speed_changed = NULL, + .force_redraw = NULL, + .config = NULL }; const device_t st506_xt_dtc5150x_device = { - "DTC 5150X MFM Fixed Disk Adapter", - "st506_xt_dtc5150x", - DEVICE_ISA, - (HDD_BUS_MFM << 8) | 1, - st506_init, st506_close, NULL, - { dtc5150x_available }, - NULL, NULL, - dtc_config + .name = "DTC 5150X MFM Fixed Disk Adapter", + .internal_name = "st506_xt_dtc5150x", + .flags = DEVICE_ISA, + .local = (HDD_BUS_MFM << 8) | ST506_XT_TYPE_DTC_5150X, + .init = st506_init, + .close = st506_close, + .reset = NULL, + { .available = dtc5150x_available }, + .speed_changed = NULL, + .force_redraw = NULL, + .config = dtc_config }; const device_t st506_xt_st11_m_device = { - "ST-11M MFM Fixed Disk Adapter", - "st506_xt_st11_m", - DEVICE_ISA, - (HDD_BUS_MFM << 8) | 11, - st506_init, st506_close, NULL, - { st11_m_available }, - NULL, NULL, - st11_config + .name = "ST-11M MFM Fixed Disk Adapter", + .internal_name = "st506_xt_st11_m", + .flags = DEVICE_ISA, + .local = (HDD_BUS_MFM << 8) | ST506_XT_TYPE_ST11M, + .init = st506_init, + .close = st506_close, + .reset = NULL, + { .available = st11_m_available }, + .speed_changed = NULL, + .force_redraw = NULL, + .config = st11_config }; const device_t st506_xt_st11_r_device = { - "ST-11R RLL Fixed Disk Adapter", - "st506_xt_st11_r", - DEVICE_ISA, - (HDD_BUS_MFM << 8) | 12, - st506_init, st506_close, NULL, - { st11_r_available }, - NULL, NULL, - st11_config + .name = "ST-11R RLL Fixed Disk Adapter", + .internal_name = "st506_xt_st11_r", + .flags = DEVICE_ISA, + .local = (HDD_BUS_MFM << 8) | ST506_XT_TYPE_ST11R, + .init = st506_init, + .close = st506_close, + .reset = NULL, + { .available = st11_r_available }, + .speed_changed = NULL, + .force_redraw = NULL, + .config = st11_config }; const device_t st506_xt_wd1002a_wx1_device = { - "WD1002A-WX1 MFM Fixed Disk Adapter", - "st506_xt_wd1002a_wx1", - DEVICE_ISA, - (HDD_BUS_MFM << 8) | 21, - st506_init, st506_close, NULL, - { wd1002a_wx1_available }, - NULL, NULL, - wd_config + .name = "WD1002A-WX1 MFM Fixed Disk Adapter", + .internal_name = "st506_xt_wd1002a_wx1", + .flags = DEVICE_ISA, + .local = (HDD_BUS_MFM << 8) | ST506_XT_TYPE_WD1002A_WX1, + .init = st506_init, + .close = st506_close, + .reset = NULL, + { .available = wd1002a_wx1_available }, + .speed_changed = NULL, + .force_redraw = NULL, + .config = wd_config +}; + +const device_t st506_xt_wd1002a_wx1_nobios_device = { + .name = "WD1002A-WX1 MFM Fixed Disk Adapter (No BIOS)", + .internal_name = "st506_xt_wd1002a_wx1", + .flags = DEVICE_ISA, + .local = (HDD_BUS_MFM << 8) | ST506_XT_TYPE_WD1002A_WX1_NOBIOS, + .init = st506_init, + .close = st506_close, + .reset = NULL, + { .available = wd1002a_wx1_available }, + .speed_changed = NULL, + .force_redraw = NULL, + .config = wd_nobios_config }; const device_t st506_xt_wd1002a_27x_device = { - "WD1002A-27X RLL Fixed Disk Adapter", - "st506_xt_wd1002a_27x", - DEVICE_ISA, - (HDD_BUS_MFM << 8) | 22, - st506_init, st506_close, NULL, - { wd1002a_27x_available }, - NULL, NULL, - wd_rll_config + .name = "WD1002A-27X RLL Fixed Disk Adapter", + .internal_name = "st506_xt_wd1002a_27x", + .flags = DEVICE_ISA, + .local = (HDD_BUS_MFM << 8) | ST506_XT_TYPE_WD1002A_27X, + .init = st506_init, + .close = st506_close, + .reset = NULL, + { .available = wd1002a_27x_available }, + .speed_changed = NULL, + .force_redraw = NULL, + .config = wd_rll_config +}; + +const device_t st506_xt_wd1004a_wx1_device = { + .name = "WD1004A-WX1 MFM Fixed Disk Adapter", + .internal_name = "st506_xt_wd1004a_wx1", + .flags = DEVICE_ISA, + .local = (HDD_BUS_MFM << 8) | ST506_XT_TYPE_WD1004A_WX1, + .init = st506_init, + .close = st506_close, + .reset = NULL, + { .available = wd1004a_wx1_available }, + .speed_changed = NULL, + .force_redraw = NULL, + .config = wd1004a_config +}; + +const device_t st506_xt_wd1004_27x_device = { + .name = "WD1004-27X RLL Fixed Disk Adapter", + .internal_name = "st506_xt_wd1004_27x", + .flags = DEVICE_ISA, + .local = (HDD_BUS_MFM << 8) | ST506_XT_TYPE_WD1004_27X, + .init = st506_init, + .close = st506_close, + .reset = NULL, + { .available = wd1004_27x_available }, + .speed_changed = NULL, + .force_redraw = NULL, + .config = wd1004_rll_config +}; + +const device_t st506_xt_wd1004a_27x_device = { + .name = "WD1004a-27X RLL Fixed Disk Adapter", + .internal_name = "st506_xt_wd1004a_27x", + .flags = DEVICE_ISA, + .local = (HDD_BUS_MFM << 8) | ST506_XT_TYPE_WD1004A_27X, + .init = st506_init, + .close = st506_close, + .reset = NULL, + { .available = wd1004a_27x_available }, + .speed_changed = NULL, + .force_redraw = NULL, + .config = wd_rll_config +}; + +const device_t st506_xt_victor_v86p_device = { + .name = "Victor V86P RLL Fixed Disk Adapter", + .internal_name = "st506_xt_victor_v86p", + .flags = DEVICE_ISA, + .local = (HDD_BUS_MFM << 8) | ST506_XT_TYPE_VICTOR_V86P, + .init = st506_init, + .close = st506_close, + .reset = NULL, + { .available = victor_v86p_available }, + .speed_changed = NULL, + .force_redraw = NULL, + .config = NULL +}; + +const device_t st506_xt_toshiba_t1200_device = { + .name = "Toshiba T1200 RLL Fixed Disk Adapter", + .internal_name = "st506_xt_toshiba_t1200", + .flags = DEVICE_ISA, + .local = (HDD_BUS_MFM << 8) | ST506_XT_TYPE_TOSHIBA_T1200, + .init = st506_init, + .close = st506_close, + .reset = NULL, + { .available = NULL }, + .speed_changed = NULL, + .force_redraw = NULL, + .config = NULL }; diff --git a/src/disk/hdc_xta.c b/src/disk/hdc_xta.c index ee43461c1..ede21caf2 100644 --- a/src/disk/hdc_xta.c +++ b/src/disk/hdc_xta.c @@ -1,76 +1,74 @@ /* - * VARCem Virtual ARchaeological Computer EMulator. - * An emulator of (mostly) x86-based PC systems and devices, - * using the ISA,EISA,VLB,MCA and PCI system buses, roughly - * spanning the era between 1981 and 1995. + * VARCem Virtual ARchaeological Computer EMulator. + * An emulator of (mostly) x86-based PC systems and devices, + * using the ISA,EISA,VLB,MCA and PCI system buses, roughly + * spanning the era between 1981 and 1995. * - * This file is part of the VARCem Project. + * Implementation of a generic IDE-XTA disk controller. * - * Implementation of a generic IDE-XTA disk controller. + * XTA is the acronym for 'XT-Attached', which was basically + * the XT-counterpart to what we know now as IDE (which is + * also named ATA - AT Attachment.) The basic ideas was to + * put the actual drive controller electronics onto the drive + * itself, and have the host machine just talk to that using + * a simpe, standardized I/O path- hence the name IDE, for + * Integrated Drive Electronics. * - * XTA is the acronym for 'XT-Attached', which was basically - * the XT-counterpart to what we know now as IDE (which is - * also named ATA - AT Attachment.) The basic ideas was to - * put the actual drive controller electronics onto the drive - * itself, and have the host machine just talk to that using - * a simpe, standardized I/O path- hence the name IDE, for - * Integrated Drive Electronics. + * In the ATA version of IDE, the programming interface of + * the IBM PC/AT (which used the Western Digitial 1002/1003 + * controllers) was kept, and, so, ATA-IDE assumes a 16bit + * data path: it reads and writes 16bit words of data. The + * disk drives for this bus commonly have an 'A' suffix to + * identify them as 'ATBUS'. * - * In the ATA version of IDE, the programming interface of - * the IBM PC/AT (which used the Western Digitial 1002/1003 - * controllers) was kept, and, so, ATA-IDE assumes a 16bit - * data path: it reads and writes 16bit words of data. The - * disk drives for this bus commonly have an 'A' suffix to - * identify them as 'ATBUS'. + * In XTA-IDE, which is slightly older, the programming + * interface of the IBM PC/XT (which used the MFM controller + * from Xebec) was kept, and, so, it uses an 8bit data path. + * Disk drives for this bus commonly have the 'X' suffix to + * mark them as being for this XTBUS variant. * - * In XTA-IDE, which is slightly older, the programming - * interface of the IBM PC/XT (which used the MFM controller - * from Xebec) was kept, and, so, it uses an 8bit data path. - * Disk drives for this bus commonly have the 'X' suffix to - * mark them as being for this XTBUS variant. + * So, XTA and ATA try to do the same thing, but they use + * different ways to achive their goal. * - * So, XTA and ATA try to do the same thing, but they use - * different ways to achive their goal. + * Also, XTA is **not** the same as XTIDE. XTIDE is a modern + * variant of ATA-IDE, but retro-fitted for use on 8bit XT + * systems: an extra register is used to deal with the extra + * data byte per transfer. XTIDE uses regular IDE drives, + * and uses the regular ATA/IDE programming interface, just + * with the extra register. * - * Also, XTA is **not** the same as XTIDE. XTIDE is a modern - * variant of ATA-IDE, but retro-fitted for use on 8bit XT - * systems: an extra register is used to deal with the extra - * data byte per transfer. XTIDE uses regular IDE drives, - * and uses the regular ATA/IDE programming interface, just - * with the extra register. - * - * NOTE: This driver implements both the 'standard' XTA interface, - * sold by Western Digital as the WDXT-140 (no BIOS) and the - * WDXT-150 (with BIOS), as well as some variants customized - * for specific machines. + * NOTE: This driver implements both the 'standard' XTA interface, + * sold by Western Digital as the WDXT-140 (no BIOS) and the + * WDXT-150 (with BIOS), as well as some variants customized + * for specific machines. * - * NOTE: The XTA interface is 0-based for sector numbers !! + * NOTE: The XTA interface is 0-based for sector numbers !! * * * - * Author: Fred N. van Kempen, + * Authors: Fred N. van Kempen, * - * Based on my earlier HD20 driver for the EuroPC. + * Based on my earlier HD20 driver for the EuroPC. * - * Copyright 2017,2018 Fred N. van Kempen. + * Copyright 2017-2018 Fred N. van Kempen. * - * Redistribution and use in source and binary forms, with - * or without modification, are permitted provided that the - * following conditions are met: + * Redistribution and use in source and binary forms, with + * or without modification, are permitted provided that the + * following conditions are met: * - * 1. Redistributions of source code must retain the entire - * above notice, this list of conditions and the following - * disclaimer. + * 1. Redistributions of source code must retain the entire + * above notice, this list of conditions and the following + * disclaimer. * - * 2. Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the - * following disclaimer in the documentation and/or other - * materials provided with the distribution. + * 2. Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the + * following disclaimer in the documentation and/or other + * materials provided with the distribution. * - * 3. Neither the name of the copyright holder nor the names - * of its contributors may be used to endorse or promote - * products derived from this software without specific - * prior written permission. + * 3. Neither the name of the copyright holder nor the names + * of its contributors may be used to endorse or promote + * products derived from this software without specific + * prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT @@ -84,9 +82,6 @@ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -#define __USE_LARGEFILE64 -#define _LARGEFILE_SOURCE -#define _LARGEFILE64_SOURCE #include #include #include @@ -107,11 +102,10 @@ #include <86box/hdc.h> #include <86box/hdd.h> +#define HDC_TIME (250 * TIMER_USEC) -#define HDC_TIME (50*TIMER_USEC) - -#define WD_BIOS_FILE "roms/hdd/xta/idexywd2.bin" - +#define WD_REV_1_BIOS_FILE "roms/hdd/xta/idexywd2.bin" +#define WD_REV_2_BIOS_FILE "roms/hdd/xta/infowdbios.rom" enum { STATE_IDLE = 0, @@ -124,257 +118,230 @@ enum { STATE_COMPL }; - /* Command values. */ -#define CMD_TEST_READY 0x00 -#define CMD_RECALIBRATE 0x01 - /* unused 0x02 */ -#define CMD_READ_SENSE 0x03 -#define CMD_FORMAT_DRIVE 0x04 -#define CMD_READ_VERIFY 0x05 -#define CMD_FORMAT_TRACK 0x06 -#define CMD_FORMAT_BAD_TRACK 0x07 -#define CMD_READ_SECTORS 0x08 - /* unused 0x09 */ -#define CMD_WRITE_SECTORS 0x0a -#define CMD_SEEK 0x0b -#define CMD_SET_DRIVE_PARAMS 0x0c -#define CMD_READ_ECC_BURST 0x0d -#define CMD_READ_SECTOR_BUFFER 0x0e -#define CMD_WRITE_SECTOR_BUFFER 0x0f -#define CMD_RAM_DIAGS 0xe0 - /* unused 0xe1 */ - /* unused 0xe2 */ -#define CMD_DRIVE_DIAGS 0xe3 -#define CMD_CTRL_DIAGS 0xe4 -#define CMD_READ_LONG 0xe5 -#define CMD_WRITE_LONG 0xe6 +#define CMD_TEST_READY 0x00 +#define CMD_RECALIBRATE 0x01 +/* unused 0x02 */ +#define CMD_READ_SENSE 0x03 +#define CMD_FORMAT_DRIVE 0x04 +#define CMD_READ_VERIFY 0x05 +#define CMD_FORMAT_TRACK 0x06 +#define CMD_FORMAT_BAD_TRACK 0x07 +#define CMD_READ_SECTORS 0x08 +/* unused 0x09 */ +#define CMD_WRITE_SECTORS 0x0a +#define CMD_SEEK 0x0b +#define CMD_SET_DRIVE_PARAMS 0x0c +#define CMD_READ_ECC_BURST 0x0d +#define CMD_READ_SECTOR_BUFFER 0x0e +#define CMD_WRITE_SECTOR_BUFFER 0x0f +#define CMD_RAM_DIAGS 0xe0 +/* unused 0xe1 */ +/* unused 0xe2 */ +#define CMD_DRIVE_DIAGS 0xe3 +#define CMD_CTRL_DIAGS 0xe4 +#define CMD_READ_LONG 0xe5 +#define CMD_WRITE_LONG 0xe6 /* Status register (reg 1) values. */ -#define STAT_REQ 0x01 /* controller needs data transfer */ -#define STAT_IO 0x02 /* direction of transfer (TO bus) */ -#define STAT_CD 0x04 /* transfer of Command or Data */ -#define STAT_BSY 0x08 /* controller is busy */ -#define STAT_DRQ 0x10 /* DMA requested */ -#define STAT_IRQ 0x20 /* interrupt requested */ -#define STAT_DCB 0x80 /* not seen by driver */ +#define STAT_REQ 0x01 /* controller needs data transfer */ +#define STAT_IO 0x02 /* direction of transfer (TO bus) */ +#define STAT_CD 0x04 /* transfer of Command or Data */ +#define STAT_BSY 0x08 /* controller is busy */ +#define STAT_DRQ 0x10 /* DMA requested */ +#define STAT_IRQ 0x20 /* interrupt requested */ +#define STAT_DCB 0x80 /* not seen by driver */ /* Sense Error codes. */ -#define ERR_NOERROR 0x00 /* no error detected */ -#define ERR_NOINDEX 0x01 /* drive did not detect IDX pulse */ -#define ERR_NOSEEK 0x02 /* drive did not complete SEEK */ -#define ERR_WRFAULT 0x03 /* write fault during last cmd */ -#define ERR_NOTRDY 0x04 /* drive did not go READY after cmd */ -#define ERR_NOTRK000 0x06 /* drive did not see TRK0 signal */ -#define ERR_LONGSEEK 0x08 /* long seek in progress */ -#define ERR_IDREAD 0x10 /* ECC error during ID field */ -#define ERR_DATA 0x11 /* uncorrectable ECC err in data */ -#define ERR_NOMARK 0x12 /* no address mark detected */ -#define ERR_NOSECT 0x14 /* sector not found */ -#define ERR_SEEK 0x15 /* seek error */ -#define ERR_ECCDATA 0x18 /* ECC corrected data */ -#define ERR_BADTRK 0x19 /* bad track detected */ -#define ERR_ILLCMD 0x20 /* invalid command received */ -#define ERR_ILLADDR 0x21 /* invalid disk address received */ -#define ERR_BADRAM 0x30 /* bad RAM in sector data buffer */ -#define ERR_BADROM 0x31 /* bad checksum in ROM test */ -#define ERR_BADECC 0x32 /* ECC polynomial generator bad */ +#define ERR_NOERROR 0x00 /* no error detected */ +#define ERR_NOINDEX 0x01 /* drive did not detect IDX pulse */ +#define ERR_NOSEEK 0x02 /* drive did not complete SEEK */ +#define ERR_WRFAULT 0x03 /* write fault during last cmd */ +#define ERR_NOTRDY 0x04 /* drive did not go READY after cmd */ +#define ERR_NOTRK000 0x06 /* drive did not see TRK0 signal */ +#define ERR_LONGSEEK 0x08 /* long seek in progress */ +#define ERR_IDREAD 0x10 /* ECC error during ID field */ +#define ERR_DATA 0x11 /* uncorrectable ECC err in data */ +#define ERR_NOMARK 0x12 /* no address mark detected */ +#define ERR_NOSECT 0x14 /* sector not found */ +#define ERR_SEEK 0x15 /* seek error */ +#define ERR_ECCDATA 0x18 /* ECC corrected data */ +#define ERR_BADTRK 0x19 /* bad track detected */ +#define ERR_ILLCMD 0x20 /* invalid command received */ +#define ERR_ILLADDR 0x21 /* invalid disk address received */ +#define ERR_BADRAM 0x30 /* bad RAM in sector data buffer */ +#define ERR_BADROM 0x31 /* bad checksum in ROM test */ +#define ERR_BADECC 0x32 /* ECC polynomial generator bad */ /* Completion Byte fields. */ -#define COMP_DRIVE 0x20 -#define COMP_ERR 0x02 - -#define IRQ_ENA 0x02 -#define DMA_ENA 0x01 +#define COMP_DRIVE 0x20 +#define COMP_ERR 0x02 +#define IRQ_ENA 0x02 +#define DMA_ENA 0x01 /* The device control block (6 bytes) */ -#pragma pack(push,1) -typedef struct { - uint8_t cmd; /* [7:5] class, [4:0] opcode */ +#pragma pack(push, 1) +typedef struct dcb_t { + uint8_t cmd; /* [7:5] class, [4:0] opcode */ - uint8_t head :5, /* [4:0] head number */ - drvsel :1, /* [5] drive select */ - mbz :2; /* [7:6] 00 */ + uint8_t head : 5; /* [4:0] head number */ + uint8_t drvsel : 1; /* [5] drive select */ + uint8_t mbz : 2; /* [7:6] 00 */ - uint8_t sector :6, /* [5:0] sector number 0-63 */ - cyl_high :2; /* [7:6] cylinder [9:8] bits */ + uint8_t sector : 6; /* [5:0] sector number 0-63 */ + uint8_t cyl_high : 2; /* [7:6] cylinder [9:8] bits */ - uint8_t cyl_low; /* [7:0] cylinder [7:0] bits */ + uint8_t cyl_low; /* [7:0] cylinder [7:0] bits */ - uint8_t count; /* [7:0] blk count / interleave */ + uint8_t count; /* [7:0] blk count / interleave */ - uint8_t ctrl; /* [7:0] control field */ + uint8_t ctrl; /* [7:0] control field */ } dcb_t; #pragma pack(pop) /* The (configured) Drive Parameters. */ -#pragma pack(push,1) -typedef struct { - uint8_t cyl_high; /* (MSB) number of cylinders */ - uint8_t cyl_low; /* (LSB) number of cylinders */ - uint8_t heads; /* number of heads per cylinder */ - uint8_t rwc_high; /* (MSB) reduced write current cylinder */ - uint8_t rwc_low; /* (LSB) reduced write current cylinder */ - uint8_t wp_high; /* (MSB) write precompensation cylinder */ - uint8_t wp_low; /* (LSB) write precompensation cylinder */ - uint8_t maxecc; /* max ECC data burst length */ +#pragma pack(push, 1) +typedef struct dprm_t { + uint8_t cyl_high; /* (MSB) number of cylinders */ + uint8_t cyl_low; /* (LSB) number of cylinders */ + uint8_t heads; /* number of heads per cylinder */ + uint8_t rwc_high; /* (MSB) reduced write current cylinder */ + uint8_t rwc_low; /* (LSB) reduced write current cylinder */ + uint8_t wp_high; /* (MSB) write precompensation cylinder */ + uint8_t wp_low; /* (LSB) write precompensation cylinder */ + uint8_t maxecc; /* max ECC data burst length */ } dprm_t; #pragma pack(pop) /* Define an attached drive. */ -typedef struct { - int8_t id, /* drive ID on bus */ - present, /* drive is present */ - hdd_num, /* index to global disk table */ - type; /* drive type ID */ +typedef struct drive_t { + int8_t id; /* drive ID on bus */ + int8_t present; /* drive is present */ + int8_t hdd_num; /* index to global disk table */ + int8_t type; /* drive type ID */ - uint16_t cur_cyl; /* last known position of heads */ + uint16_t cur_cyl; /* last known position of heads */ - uint8_t spt, /* active drive parameters */ - hpc; - uint16_t tracks; + uint8_t spt; /* active drive parameters */ + uint8_t hpc; + uint16_t tracks; - uint8_t cfg_spt, /* configured drive parameters */ - cfg_hpc; - uint16_t cfg_tracks; + uint8_t cfg_spt; /* configured drive parameters */ + uint8_t cfg_hpc; + uint16_t cfg_tracks; } drive_t; +typedef struct hdc_t { + const char *name; /* controller name */ -typedef struct { - const char *name; /* controller name */ + uint16_t base; /* controller base I/O address */ + int8_t irq; /* controller IRQ channel */ + int8_t dma; /* controller DMA channel */ + int8_t type; /* controller type ID */ - uint16_t base; /* controller base I/O address */ - int8_t irq; /* controller IRQ channel */ - int8_t dma; /* controller DMA channel */ - int8_t type; /* controller type ID */ - - uint32_t rom_addr; /* address where ROM is */ - rom_t bios_rom; /* descriptor for the BIOS */ + uint32_t rom_addr; /* address where ROM is */ + rom_t bios_rom; /* descriptor for the BIOS */ /* Controller state. */ - int8_t state; /* controller state */ - uint8_t sense; /* current SENSE ERROR value */ - uint8_t status; /* current operational status */ - uint8_t intr; - uint64_t callback; - pc_timer_t timer; + int8_t state; /* controller state */ + uint8_t sense; /* current SENSE ERROR value */ + uint8_t status; /* current operational status */ + uint8_t intr; + pc_timer_t timer; /* Data transfer. */ - int16_t buf_idx, /* buffer index and pointer */ - buf_len; - uint8_t *buf_ptr; + int16_t buf_idx; /* buffer index and pointer */ + int16_t buf_len; + uint8_t *buf_ptr; /* Current operation parameters. */ - dcb_t dcb; /* device control block */ - uint16_t track; /* requested track# */ - uint8_t head, /* requested head# */ - sector, /* requested sector# */ - comp; /* operation completion byte */ - int count; /* requested sector count */ + dcb_t dcb; /* device control block */ + uint16_t track; /* requested track# */ + uint8_t head; /* requested head# */ + uint8_t sector; /* requested sector# */ + uint8_t comp; /* operation completion byte */ + int count; /* requested sector count */ - drive_t drives[XTA_NUM]; /* the attached drive(s) */ + drive_t drives[XTA_NUM]; /* the attached drive(s) */ - uint8_t data[512]; /* data buffer */ - uint8_t sector_buf[512]; /* sector buffer */ + uint8_t data[512]; /* data buffer */ + uint8_t sector_buf[512]; /* sector buffer */ } hdc_t; - #ifdef ENABLE_XTA_LOG int xta_do_log = ENABLE_XTA_LOG; - static void xta_log(const char *fmt, ...) { va_list ap; if (xta_do_log) { - va_start(ap, fmt); - pclog_ex(fmt, ap); - va_end(ap); + va_start(ap, fmt); + pclog_ex(fmt, ap); + va_end(ap); } } #else -#define xta_log(fmt, ...) +# define xta_log(fmt, ...) #endif - static void set_intr(hdc_t *dev) { - dev->status = STAT_REQ|STAT_CD|STAT_IO|STAT_BSY; - dev->state = STATE_COMPL; + dev->status = STAT_REQ | STAT_CD | STAT_IO | STAT_BSY; + dev->state = STATE_COMPL; if (dev->intr & IRQ_ENA) { - dev->status |= STAT_IRQ; - picint(1 << dev->irq); + dev->status |= STAT_IRQ; + picint(1 << dev->irq); } } - /* Get the logical (block) address of a CHS triplet. */ static int get_sector(hdc_t *dev, drive_t *drive, off64_t *addr) { if (drive->cur_cyl != dev->track) { - xta_log("%s: get_sector: wrong cylinder %d/%d\n", - dev->name, drive->cur_cyl, dev->track); - dev->sense = ERR_ILLADDR; - return(1); + xta_log("%s: get_sector: wrong cylinder %d/%d\n", + dev->name, drive->cur_cyl, dev->track); + dev->sense = ERR_ILLADDR; + return 1; } if (dev->head >= drive->hpc) { - xta_log("%s: get_sector: past end of heads\n", dev->name); - dev->sense = ERR_ILLADDR; - return(1); + xta_log("%s: get_sector: past end of heads\n", dev->name); + dev->sense = ERR_ILLADDR; + return 1; } if (dev->sector >= drive->spt) { - xta_log("%s: get_sector: past end of sectors\n", dev->name); - dev->sense = ERR_ILLADDR; - return(1); + xta_log("%s: get_sector: past end of sectors\n", dev->name); + dev->sense = ERR_ILLADDR; + return 1; } /* Calculate logical address (block number) of desired sector. */ - *addr = ((((off64_t) dev->track*drive->hpc) + \ - dev->head)*drive->spt) + dev->sector; + *addr = ((((off64_t) dev->track * drive->hpc) + dev->head) * drive->spt) + dev->sector; - return(0); + return 0; } - static void next_sector(hdc_t *dev, drive_t *drive) { if (++dev->sector >= drive->spt) { - dev->sector = 0; - if (++dev->head >= drive->hpc) { - dev->head = 0; - dev->track++; - if (++drive->cur_cyl >= drive->tracks) - drive->cur_cyl = (drive->tracks - 1); - } + dev->sector = 0; + if (++dev->head >= drive->hpc) { + dev->head = 0; + dev->track++; + if (++drive->cur_cyl >= drive->tracks) + drive->cur_cyl = (drive->tracks - 1); + } } } -static void -xta_set_callback(hdc_t *dev, uint64_t callback) -{ - if (!dev) { - return; - } - - if (callback) { - dev->callback = callback; - timer_set_delay_u64(&dev->timer, dev->callback); - } else { - dev->callback = 0; - timer_disable(&dev->timer); - } -} - - /* Perform the seek operation. */ static void do_seek(hdc_t *dev, drive_t *drive, int cyl) @@ -382,623 +349,646 @@ do_seek(hdc_t *dev, drive_t *drive, int cyl) dev->track = cyl; if (dev->track >= drive->tracks) - drive->cur_cyl = (drive->tracks - 1); - else - drive->cur_cyl = dev->track; + drive->cur_cyl = (drive->tracks - 1); + else + drive->cur_cyl = dev->track; } - /* Format a track or an entire drive. */ static void do_format(hdc_t *dev, drive_t *drive, dcb_t *dcb) { - int start_cyl, end_cyl; - int start_hd, end_hd; + int start_cyl; + int end_cyl; + int start_hd; + int end_hd; off64_t addr; - int h, s; /* Get the parameters from the DCB. */ if (dcb->cmd == CMD_FORMAT_DRIVE) { - start_cyl = 0; - start_hd = 0; - end_cyl = drive->tracks; - end_hd = drive->hpc; + start_cyl = 0; + start_hd = 0; + end_cyl = drive->tracks; + end_hd = drive->hpc; } else { - start_cyl = (dcb->cyl_low | (dcb->cyl_high << 8)); - start_hd = dcb->head; - end_cyl = start_cyl + 1; - end_hd = start_hd + 1; + start_cyl = (dcb->cyl_low | (dcb->cyl_high << 8)); + start_hd = dcb->head; + end_cyl = start_cyl + 1; + end_hd = start_hd + 1; } switch (dev->state) { - case STATE_IDLE: - /* Seek to cylinder. */ - do_seek(dev, drive, start_cyl); - dev->head = dcb->head; - dev->sector = 0; + case STATE_IDLE: + /* Seek to cylinder. */ + do_seek(dev, drive, start_cyl); + dev->head = dcb->head; + dev->sector = 0; - /* Activate the status icon. */ - ui_sb_update_icon(SB_HDD|HDD_BUS_XTA, 1); + /* Activate the status icon. */ + ui_sb_update_icon(SB_HDD | HDD_BUS_XTA, 1); do_fmt: - /* - * For now, we don't use the interleave factor (in - * dcb->count), although we should one day use an - * image format that can handle it.. - * - * That said, we have been given a sector_buf of - * data to fill the sectors with, so we will use - * that at least. - */ - for (h = start_hd; h < end_hd; h++) { - for (s = 0; s < drive->spt; s++) { - /* Set the sector we need to write. */ - dev->head = h; - dev->sector = s; + /* + * For now, we don't use the interleave factor (in + * dcb->count), although we should one day use an + * image format that can handle it.. + * + * That said, we have been given a sector_buf of + * data to fill the sectors with, so we will use + * that at least. + */ + for (int h = start_hd; h < end_hd; h++) { + for (uint8_t s = 0; s < drive->spt; s++) { + /* Set the sector we need to write. */ + dev->head = h; + dev->sector = s; - /* Get address of sector to write. */ - if (get_sector(dev, drive, &addr)) break; + /* Get address of sector to write. */ + if (get_sector(dev, drive, &addr)) + break; - /* Write the block to the image. */ - hdd_image_write(drive->hdd_num, addr, 1, - (uint8_t *)dev->sector_buf); - } - } + /* Write the block to the image. */ + hdd_image_write(drive->hdd_num, addr, 1, + (uint8_t *) dev->sector_buf); + } + } - /* One more track done. */ - if (++start_cyl == end_cyl) break; + /* One more track done. */ + if (++start_cyl == end_cyl) + break; - /* This saves us a LOT of code. */ - goto do_fmt; + /* This saves us a LOT of code. */ + goto do_fmt; + + default: + break; } /* De-activate the status icon. */ - ui_sb_update_icon(SB_HDD|HDD_BUS_XTA, 0); + ui_sb_update_icon(SB_HDD | HDD_BUS_XTA, 0); } - /* Execute the DCB we just received. */ static void hdc_callback(void *priv) { - hdc_t *dev = (hdc_t *)priv; - dcb_t *dcb = &dev->dcb; - drive_t *drive; - dprm_t *params; - off64_t addr; - int no_data = 0; - int val; + hdc_t *dev = (hdc_t *) priv; + dcb_t *dcb = &dev->dcb; + drive_t *drive; + const dprm_t *params; + off64_t addr; + int no_data = 0; + int val; - /* Cancel timer. */ - xta_set_callback(dev, 0); - - drive = &dev->drives[dcb->drvsel]; + drive = &dev->drives[dcb->drvsel]; dev->comp = (dcb->drvsel) ? COMP_DRIVE : 0x00; dev->status |= STAT_DCB; switch (dcb->cmd) { - case CMD_TEST_READY: - if (! drive->present) { - dev->comp |= COMP_ERR; - dev->sense = ERR_NOTRDY; - } - set_intr(dev); - break; + case CMD_TEST_READY: + if (!drive->present) { + dev->comp |= COMP_ERR; + dev->sense = ERR_NOTRDY; + } + set_intr(dev); + break; - case CMD_RECALIBRATE: - if (! drive->present) { - dev->comp |= COMP_ERR; - dev->sense = ERR_NOTRDY; - } else { - dev->track = drive->cur_cyl = 0; - } - set_intr(dev); - break; - - case CMD_READ_SENSE: - switch(dev->state) { - case STATE_IDLE: - dev->buf_idx = 0; - dev->buf_len = 4; - dev->buf_ptr = dev->data; - dev->buf_ptr[0] = dev->sense; - dev->buf_ptr[1] = dcb->drvsel ? 0x20 : 0x00; - dev->buf_ptr[2] = (drive->cur_cyl >> 2) | \ - (dev->sector & 0x3f); - dev->buf_ptr[3] = (drive->cur_cyl & 0xff); - dev->sense = ERR_NOERROR; - dev->status |= (STAT_IO | STAT_REQ); - dev->state = STATE_SDATA; - break; + case CMD_RECALIBRATE: + if (!drive->present) { + dev->comp |= COMP_ERR; + dev->sense = ERR_NOTRDY; + } else { + dev->track = drive->cur_cyl = 0; + } + set_intr(dev); + break; - case STATE_SDONE: - set_intr(dev); - } - break; + case CMD_READ_SENSE: + switch (dev->state) { + case STATE_IDLE: + dev->buf_idx = 0; + dev->buf_len = 4; + dev->buf_ptr = dev->data; + dev->buf_ptr[0] = dev->sense; + dev->buf_ptr[1] = dcb->drvsel ? 0x20 : 0x00; + dev->buf_ptr[2] = (drive->cur_cyl >> 2) | (dev->sector & 0x3f); + dev->buf_ptr[3] = (drive->cur_cyl & 0xff); + dev->sense = ERR_NOERROR; + dev->status |= (STAT_IO | STAT_REQ); + dev->state = STATE_SDATA; + break; - case CMD_READ_VERIFY: - no_data = 1; - /*FALLTHROUGH*/ + case STATE_SDONE: + set_intr(dev); + break; - case CMD_READ_SECTORS: - if (! drive->present) { - dev->comp |= COMP_ERR; - dev->sense = ERR_NOTRDY; - set_intr(dev); - break; - } + default: + break; + } + break; - switch (dev->state) { - case STATE_IDLE: - /* Seek to cylinder. */ - do_seek(dev, drive, - (dcb->cyl_low|(dcb->cyl_high<<8))); - dev->head = dcb->head; - dev->sector = dcb->sector; + case CMD_READ_VERIFY: + no_data = 1; + fallthrough; - /* Get sector count; count=0 means 256. */ - dev->count = (int)dcb->count; - if (dev->count == 0) - dev->count = 256; - dev->buf_len = 512; + case CMD_READ_SECTORS: + if (!drive->present) { + dev->comp |= COMP_ERR; + dev->sense = ERR_NOTRDY; + set_intr(dev); + break; + } - dev->state = STATE_SEND; - /*FALLTHROUGH*/ + switch (dev->state) { + case STATE_IDLE: + /* Seek to cylinder. */ + do_seek(dev, drive, + (dcb->cyl_low | (dcb->cyl_high << 8))); + dev->head = dcb->head; + dev->sector = dcb->sector; - case STATE_SEND: - /* Activate the status icon. */ - ui_sb_update_icon(SB_HDD|HDD_BUS_XTA, 1); + /* Get sector count; count=0 means 256. */ + dev->count = (int) dcb->count; + if (dev->count == 0) + dev->count = 256; + dev->buf_len = 512; + + dev->state = STATE_SEND; + fallthrough; + + case STATE_SEND: + /* Activate the status icon. */ + ui_sb_update_icon(SB_HDD | HDD_BUS_XTA, 1); do_send: - /* Get address of sector to load. */ - if (get_sector(dev, drive, &addr)) { - /* De-activate the status icon. */ - ui_sb_update_icon(SB_HDD|HDD_BUS_XTA, 0); - dev->comp |= COMP_ERR; - set_intr(dev); - return; - } + /* Get address of sector to load. */ + if (get_sector(dev, drive, &addr)) { + /* De-activate the status icon. */ + ui_sb_update_icon(SB_HDD | HDD_BUS_XTA, 0); + dev->comp |= COMP_ERR; + set_intr(dev); + return; + } - /* Read the block from the image. */ - hdd_image_read(drive->hdd_num, addr, 1, - (uint8_t *)dev->sector_buf); + /* Read the block from the image. */ + hdd_image_read(drive->hdd_num, addr, 1, + (uint8_t *) dev->sector_buf); - /* Ready to transfer the data out. */ - dev->state = STATE_SDATA; - dev->buf_idx = 0; - if (no_data) { - /* Delay a bit, no actual transfer. */ - xta_set_callback(dev, HDC_TIME); - } else { - if (dev->intr & DMA_ENA) { - /* DMA enabled. */ - dev->buf_ptr = dev->sector_buf; - xta_set_callback(dev, HDC_TIME); - } else { - /* Copy from sector to data. */ - memcpy(dev->data, - dev->sector_buf, - dev->buf_len); - dev->buf_ptr = dev->data; + /* Ready to transfer the data out. */ + dev->state = STATE_SDATA; + dev->buf_idx = 0; + if (no_data) { + /* Delay a bit, no actual transfer. */ + timer_advance_u64(&dev->timer, HDC_TIME); + } else { + if (dev->intr & DMA_ENA) { + /* DMA enabled. */ + dev->buf_ptr = dev->sector_buf; + timer_advance_u64(&dev->timer, HDC_TIME); + } else { + /* Copy from sector to data. */ + memcpy(dev->data, + dev->sector_buf, + dev->buf_len); + dev->buf_ptr = dev->data; - dev->status |= (STAT_IO | STAT_REQ); - } - } - break; - - case STATE_SDATA: - if (! no_data) { - /* Perform DMA. */ - while (dev->buf_idx < dev->buf_len) { - val = dma_channel_write(dev->dma, - *dev->buf_ptr); - if (val == DMA_NODATA) { - xta_log("%s: CMD_READ_SECTORS out of data (idx=%d, len=%d)!\n", dev->name, dev->buf_idx, dev->buf_len); + dev->status |= (STAT_IO | STAT_REQ); + } + } + break; - dev->status |= (STAT_CD | STAT_IO| STAT_REQ); - xta_set_callback(dev, HDC_TIME); - return; - } - dev->buf_ptr++; - dev->buf_idx++; - } - } - xta_set_callback(dev, HDC_TIME); - dev->state = STATE_SDONE; - break; + case STATE_SDATA: + if (!no_data) { + /* Perform DMA. */ + while (dev->buf_idx < dev->buf_len) { + val = dma_channel_write(dev->dma, + *dev->buf_ptr); + if (val == DMA_NODATA) { + xta_log("%s: CMD_READ_SECTORS out of data (idx=%d, len=%d)!\n", dev->name, dev->buf_idx, dev->buf_len); - case STATE_SDONE: - dev->buf_idx = 0; - if (--dev->count == 0) { - /* De-activate the status icon. */ - ui_sb_update_icon(SB_HDD|HDD_BUS_XTA, 0); + dev->status |= (STAT_CD | STAT_IO | STAT_REQ); + timer_advance_u64(&dev->timer, HDC_TIME); + return; + } + dev->buf_ptr++; + dev->buf_idx++; + } + } + timer_advance_u64(&dev->timer, HDC_TIME); + dev->state = STATE_SDONE; + break; - set_intr(dev); - return; - } + case STATE_SDONE: + dev->buf_idx = 0; + if (--dev->count == 0) { + /* De-activate the status icon. */ + ui_sb_update_icon(SB_HDD | HDD_BUS_XTA, 0); - /* Addvance to next sector. */ - next_sector(dev, drive); + set_intr(dev); + return; + } - /* This saves us a LOT of code. */ - dev->state = STATE_SEND; - goto do_send; - } - break; + /* Addvance to next sector. */ + next_sector(dev, drive); - case CMD_WRITE_SECTORS: - if (! drive->present) { - dev->comp |= COMP_ERR; - dev->sense = ERR_NOTRDY; - set_intr(dev); - break; - } + /* This saves us a LOT of code. */ + dev->state = STATE_SEND; + goto do_send; - switch (dev->state) { - case STATE_IDLE: - /* Seek to cylinder. */ - do_seek(dev, drive, - (dcb->cyl_low|(dcb->cyl_high<<8))); - dev->head = dcb->head; - dev->sector = dcb->sector; + default: + break; + } + break; - /* Get sector count; count=0 means 256. */ - dev->count = (int)dev->dcb.count; - if (dev->count == 0) - dev->count = 256; - dev->buf_len = 512; + case CMD_WRITE_SECTORS: + if (!drive->present) { + dev->comp |= COMP_ERR; + dev->sense = ERR_NOTRDY; + set_intr(dev); + break; + } - dev->state = STATE_RECV; - /*FALLTHROUGH*/ + switch (dev->state) { + case STATE_IDLE: + /* Seek to cylinder. */ + do_seek(dev, drive, + (dcb->cyl_low | (dcb->cyl_high << 8))); + dev->head = dcb->head; + dev->sector = dcb->sector; - case STATE_RECV: - /* Activate the status icon. */ - ui_sb_update_icon(SB_HDD|HDD_BUS_XTA, 1); + /* Get sector count; count=0 means 256. */ + dev->count = (int) dev->dcb.count; + if (dev->count == 0) + dev->count = 256; + dev->buf_len = 512; + + dev->state = STATE_RECV; + fallthrough; + + case STATE_RECV: + /* Activate the status icon. */ + ui_sb_update_icon(SB_HDD | HDD_BUS_XTA, 1); do_recv: - /* Ready to transfer the data in. */ - dev->state = STATE_RDATA; - dev->buf_idx = 0; - if (dev->intr & DMA_ENA) { - /* DMA enabled. */ - dev->buf_ptr = dev->sector_buf; - xta_set_callback(dev, HDC_TIME); - } else { - /* No DMA, do PIO. */ - dev->buf_ptr = dev->data; - dev->status |= STAT_REQ; - } - break; + /* Ready to transfer the data in. */ + dev->state = STATE_RDATA; + dev->buf_idx = 0; + if (dev->intr & DMA_ENA) { + /* DMA enabled. */ + dev->buf_ptr = dev->sector_buf; + timer_advance_u64(&dev->timer, HDC_TIME); + } else { + /* No DMA, do PIO. */ + dev->buf_ptr = dev->data; + dev->status |= STAT_REQ; + } + break; - case STATE_RDATA: - if (! no_data) { - /* Perform DMA. */ - dev->status = STAT_BSY; - while (dev->buf_idx < dev->buf_len) { - val = dma_channel_read(dev->dma); - if (val == DMA_NODATA) { - xta_log("%s: CMD_WRITE_SECTORS out of data (idx=%d, len=%d)!\n", dev->name, dev->buf_idx, dev->buf_len); + case STATE_RDATA: + if (!no_data) { + /* Perform DMA. */ + dev->status = STAT_BSY; + while (dev->buf_idx < dev->buf_len) { + val = dma_channel_read(dev->dma); + if (val == DMA_NODATA) { + xta_log("%s: CMD_WRITE_SECTORS out of data (idx=%d, len=%d)!\n", dev->name, dev->buf_idx, dev->buf_len); - xta_log("%s: CMD_WRITE_SECTORS out of data!\n", dev->name); - dev->status |= (STAT_CD | STAT_IO | STAT_REQ); - xta_set_callback(dev, HDC_TIME); - return; - } + xta_log("%s: CMD_WRITE_SECTORS out of data!\n", dev->name); + dev->status |= (STAT_CD | STAT_IO | STAT_REQ); + timer_advance_u64(&dev->timer, HDC_TIME); + return; + } - dev->buf_ptr[dev->buf_idx] = (val & 0xff); - dev->buf_idx++; - } - dev->state = STATE_RDONE; - xta_set_callback(dev, HDC_TIME); - } - break; + dev->buf_ptr[dev->buf_idx] = (val & 0xff); + dev->buf_idx++; + } + dev->state = STATE_RDONE; + timer_advance_u64(&dev->timer, HDC_TIME); + } + break; - case STATE_RDONE: - /* Copy from data to sector if PIO. */ - if (! (dev->intr & DMA_ENA)) - memcpy(dev->sector_buf, dev->data, - dev->buf_len); + case STATE_RDONE: + /* Copy from data to sector if PIO. */ + if (!(dev->intr & DMA_ENA)) + memcpy(dev->sector_buf, dev->data, + dev->buf_len); - /* Get address of sector to write. */ - if (get_sector(dev, drive, &addr)) { - /* De-activate the status icon. */ - ui_sb_update_icon(SB_HDD|HDD_BUS_XTA, 0); + /* Get address of sector to write. */ + if (get_sector(dev, drive, &addr)) { + /* De-activate the status icon. */ + ui_sb_update_icon(SB_HDD | HDD_BUS_XTA, 0); - dev->comp |= COMP_ERR; - set_intr(dev); - return; - } + dev->comp |= COMP_ERR; + set_intr(dev); + return; + } - /* Write the block to the image. */ - hdd_image_write(drive->hdd_num, addr, 1, - (uint8_t *)dev->sector_buf); + /* Write the block to the image. */ + hdd_image_write(drive->hdd_num, addr, 1, + (uint8_t *) dev->sector_buf); - dev->buf_idx = 0; - if (--dev->count == 0) { - /* De-activate the status icon. */ - ui_sb_update_icon(SB_HDD|HDD_BUS_XTA, 0); + dev->buf_idx = 0; + if (--dev->count == 0) { + /* De-activate the status icon. */ + ui_sb_update_icon(SB_HDD | HDD_BUS_XTA, 0); - set_intr(dev); - return; - } + set_intr(dev); + return; + } - /* Advance to next sector. */ - next_sector(dev, drive); + /* Advance to next sector. */ + next_sector(dev, drive); - /* This saves us a LOT of code. */ - dev->state = STATE_RECV; - goto do_recv; - } - break; + /* This saves us a LOT of code. */ + dev->state = STATE_RECV; + goto do_recv; - case CMD_FORMAT_DRIVE: - case CMD_FORMAT_TRACK: - if (drive->present) { - do_format(dev, drive, dcb); - } else { - dev->comp |= COMP_ERR; - dev->sense = ERR_NOTRDY; - } - set_intr(dev); - break; + default: + break; + } + break; - case CMD_SEEK: - /* Seek to cylinder. */ - val = (dcb->cyl_low | (dcb->cyl_high << 8)); - if (drive->present) { - do_seek(dev, drive, val); - if (val != drive->cur_cyl) { - dev->comp |= COMP_ERR; - dev->sense = ERR_SEEK; - } - } else { - dev->comp |= COMP_ERR; - dev->sense = ERR_NOTRDY; - } - set_intr(dev); - break; + case CMD_FORMAT_DRIVE: + case CMD_FORMAT_TRACK: + if (drive->present) { + do_format(dev, drive, dcb); + } else { + dev->comp |= COMP_ERR; + dev->sense = ERR_NOTRDY; + } + set_intr(dev); + break; - case CMD_SET_DRIVE_PARAMS: - switch(dev->state) { - case STATE_IDLE: - dev->state = STATE_RDATA; - dev->buf_idx = 0; - dev->buf_len = sizeof(dprm_t); - dev->buf_ptr = (uint8_t *)dev->data; - dev->status |= STAT_REQ; - break; + case CMD_SEEK: + /* Seek to cylinder. */ + val = (dcb->cyl_low | (dcb->cyl_high << 8)); + if (drive->present) { + do_seek(dev, drive, val); + if (val != drive->cur_cyl) { + dev->comp |= COMP_ERR; + dev->sense = ERR_SEEK; + } + } else { + dev->comp |= COMP_ERR; + dev->sense = ERR_NOTRDY; + } + set_intr(dev); + break; - case STATE_RDONE: - params = (dprm_t *)dev->data; - drive->tracks = - (params->cyl_high << 8) | params->cyl_low; - drive->hpc = params->heads; - drive->spt = 17 /*hardcoded*/; - dev->status &= ~STAT_REQ; - set_intr(dev); - break; - } - break; + case CMD_SET_DRIVE_PARAMS: + switch (dev->state) { + case STATE_IDLE: + dev->state = STATE_RDATA; + dev->buf_idx = 0; + dev->buf_len = sizeof(dprm_t); + dev->buf_ptr = (uint8_t *) dev->data; + dev->status |= STAT_REQ; + break; - case CMD_WRITE_SECTOR_BUFFER: - switch (dev->state) { - case STATE_IDLE: - dev->buf_idx = 0; - dev->buf_len = 512; - dev->state = STATE_RDATA; - if (dev->intr & DMA_ENA) { - dev->buf_ptr = dev->sector_buf; - xta_set_callback(dev, HDC_TIME); - } else { - dev->buf_ptr = dev->data; - dev->status |= STAT_REQ; - } - break; + case STATE_RDONE: + params = (dprm_t *) dev->data; + drive->tracks = (params->cyl_high << 8) | params->cyl_low; + drive->hpc = params->heads; + drive->spt = 17 /*hardcoded*/; + dev->status &= ~STAT_REQ; + set_intr(dev); + break; - case STATE_RDATA: - if (dev->intr & DMA_ENA) { - /* Perform DMA. */ - while (dev->buf_idx < dev->buf_len) { - val = dma_channel_read(dev->dma); - if (val == DMA_NODATA) { - xta_log("%s: CMD_WRITE_BUFFER out of data!\n", dev->name); - dev->status |= (STAT_CD | STAT_IO | STAT_REQ); - xta_set_callback(dev, HDC_TIME); - return; - } + default: + break; + } + break; - dev->buf_ptr[dev->buf_idx] = (val & 0xff); - dev->buf_idx++; - } - dev->state = STATE_RDONE; - xta_set_callback(dev, HDC_TIME); - } - break; + case CMD_WRITE_SECTOR_BUFFER: + switch (dev->state) { + case STATE_IDLE: + dev->buf_idx = 0; + dev->buf_len = 512; + dev->state = STATE_RDATA; + if (dev->intr & DMA_ENA) { + dev->buf_ptr = dev->sector_buf; + timer_advance_u64(&dev->timer, HDC_TIME); + } else { + dev->buf_ptr = dev->data; + dev->status |= STAT_REQ; + } + break; - case STATE_RDONE: - if (! (dev->intr & DMA_ENA)) - memcpy(dev->sector_buf, - dev->data, dev->buf_len); - set_intr(dev); - break; - } - break; + case STATE_RDATA: + if (dev->intr & DMA_ENA) { + /* Perform DMA. */ + while (dev->buf_idx < dev->buf_len) { + val = dma_channel_read(dev->dma); + if (val == DMA_NODATA) { + xta_log("%s: CMD_WRITE_BUFFER out of data!\n", dev->name); + dev->status |= (STAT_CD | STAT_IO | STAT_REQ); + timer_advance_u64(&dev->timer, HDC_TIME); + return; + } - case CMD_RAM_DIAGS: - switch(dev->state) { - case STATE_IDLE: - dev->state = STATE_RDONE; - xta_set_callback(dev, 5 * HDC_TIME); - break; + dev->buf_ptr[dev->buf_idx] = (val & 0xff); + dev->buf_idx++; + } + dev->state = STATE_RDONE; + timer_advance_u64(&dev->timer, HDC_TIME); + } + break; - case STATE_RDONE: - set_intr(dev); - break; - } - break; + case STATE_RDONE: + if (!(dev->intr & DMA_ENA)) + memcpy(dev->sector_buf, + dev->data, dev->buf_len); + set_intr(dev); + break; - case CMD_DRIVE_DIAGS: - switch(dev->state) { - case STATE_IDLE: - if (drive->present) { - dev->state = STATE_RDONE; - xta_set_callback(dev, 5 * HDC_TIME); - } else { - dev->comp |= COMP_ERR; - dev->sense = ERR_NOTRDY; - set_intr(dev); - } - break; + default: + break; + } + break; - case STATE_RDONE: - set_intr(dev); - break; - } - break; + case CMD_RAM_DIAGS: + switch (dev->state) { + case STATE_IDLE: + dev->state = STATE_RDONE; + timer_advance_u64(&dev->timer, 5 * HDC_TIME); + break; - case CMD_CTRL_DIAGS: - switch(dev->state) { - case STATE_IDLE: - dev->state = STATE_RDONE; - xta_set_callback(dev, 10 * HDC_TIME); - break; + case STATE_RDONE: + set_intr(dev); + break; - case STATE_RDONE: - set_intr(dev); - break; - } - break; + default: + break; + } + break; - default: - xta_log("%s: unknown command - %02x\n", dev->name, dcb->cmd); - dev->comp |= COMP_ERR; - dev->sense = ERR_ILLCMD; - set_intr(dev); + case CMD_DRIVE_DIAGS: + switch (dev->state) { + case STATE_IDLE: + if (drive->present) { + dev->state = STATE_RDONE; + timer_advance_u64(&dev->timer, 5 * HDC_TIME); + } else { + dev->comp |= COMP_ERR; + dev->sense = ERR_NOTRDY; + set_intr(dev); + } + break; + + case STATE_RDONE: + set_intr(dev); + break; + + default: + break; + } + break; + + case CMD_CTRL_DIAGS: + switch (dev->state) { + case STATE_IDLE: + dev->state = STATE_RDONE; + timer_advance_u64(&dev->timer, 10 * HDC_TIME); + break; + + case STATE_RDONE: + set_intr(dev); + break; + + default: + break; + } + break; + + default: + xta_log("%s: unknown command - %02x\n", dev->name, dcb->cmd); + dev->comp |= COMP_ERR; + dev->sense = ERR_ILLCMD; + set_intr(dev); } } - /* Read one of the controller registers. */ static uint8_t hdc_read(uint16_t port, void *priv) { - hdc_t *dev = (hdc_t *)priv; + hdc_t *dev = (hdc_t *) priv; uint8_t ret = 0xff; - + switch (port & 7) { - case 0: /* DATA register */ - dev->status &= ~STAT_IRQ; + case 0: /* DATA register */ + dev->status &= ~STAT_IRQ; - if (dev->state == STATE_SDATA) { - if (dev->buf_idx > dev->buf_len) { - xta_log("%s: read with empty buffer!\n", - dev->name); - dev->comp |= COMP_ERR; - dev->sense = ERR_ILLCMD; - break; - } + if (dev->state == STATE_SDATA) { + if (dev->buf_idx > dev->buf_len) { + xta_log("%s: read with empty buffer!\n", + dev->name); + dev->comp |= COMP_ERR; + dev->sense = ERR_ILLCMD; + break; + } - ret = dev->buf_ptr[dev->buf_idx]; - if (++dev->buf_idx == dev->buf_len) { - /* All data sent. */ - dev->status &= ~STAT_REQ; - dev->state = STATE_SDONE; - xta_set_callback(dev, HDC_TIME); - } - } else if (dev->state == STATE_COMPL) { -xta_log("DCB=%02X status=%02X comp=%02X\n", dev->dcb.cmd, dev->status, dev->comp); - ret = dev->comp; - dev->status = 0x00; - dev->state = STATE_IDLE; - } - break; + ret = dev->buf_ptr[dev->buf_idx]; + if (++dev->buf_idx == dev->buf_len) { + /* All data sent. */ + dev->status &= ~STAT_REQ; + dev->state = STATE_SDONE; + timer_set_delay_u64(&dev->timer, HDC_TIME); + } + } else if (dev->state == STATE_COMPL) { + xta_log("DCB=%02X status=%02X comp=%02X\n", dev->dcb.cmd, dev->status, dev->comp); + ret = dev->comp; + dev->status = 0x00; + dev->state = STATE_IDLE; + } + break; - case 1: /* STATUS register */ - ret = (dev->status & ~STAT_DCB); - break; + case 1: /* STATUS register */ + ret = (dev->status & ~STAT_DCB); + break; - case 2: /* "read option jumpers" */ - ret = 0xff; /* all switches off */ - break; + case 2: /* "read option jumpers" */ + ret = 0xff; /* all switches off */ + break; + + default: + break; } - return(ret); + return ret; } - /* Write to one of the controller registers. */ static void hdc_write(uint16_t port, uint8_t val, void *priv) { - hdc_t *dev = (hdc_t *)priv; + hdc_t *dev = (hdc_t *) priv; switch (port & 7) { - case 0: /* DATA register */ - if (dev->state == STATE_RDATA) { - if (! (dev->status & STAT_REQ)) { - xta_log("%s: not ready for command/data!\n", dev->name); - dev->comp |= COMP_ERR; - dev->sense = ERR_ILLCMD; - break; - } + case 0: /* DATA register */ + if (dev->state == STATE_RDATA) { + if (!(dev->status & STAT_REQ)) { + xta_log("%s: not ready for command/data!\n", dev->name); + dev->comp |= COMP_ERR; + dev->sense = ERR_ILLCMD; + break; + } - if (dev->buf_idx >= dev->buf_len) { - xta_log("%s: write with full buffer!\n", dev->name); - dev->comp |= COMP_ERR; - dev->sense = ERR_ILLCMD; - break; - } + if (dev->buf_idx >= dev->buf_len) { + xta_log("%s: write with full buffer!\n", dev->name); + dev->comp |= COMP_ERR; + dev->sense = ERR_ILLCMD; + break; + } - /* Store the data into the buffer. */ - dev->buf_ptr[dev->buf_idx] = val; - if (++dev->buf_idx == dev->buf_len) { - /* We got all the data we need. */ - dev->status &= ~STAT_REQ; - if (dev->status & STAT_DCB) - dev->state = STATE_RDONE; - else - dev->state = STATE_IDLE; - dev->status &= ~STAT_CD; - xta_set_callback(dev, HDC_TIME); - } - } - break; + /* Store the data into the buffer. */ + dev->buf_ptr[dev->buf_idx] = val; + if (++dev->buf_idx == dev->buf_len) { + /* We got all the data we need. */ + dev->status &= ~STAT_REQ; + if (dev->status & STAT_DCB) + dev->state = STATE_RDONE; + else + dev->state = STATE_IDLE; + dev->status &= ~STAT_CD; + timer_set_delay_u64(&dev->timer, HDC_TIME); + } + } + break; - case 1: /* RESET register */ - dev->sense = 0x00; - dev->state = STATE_IDLE; - break; + case 1: /* RESET register */ + dev->sense = 0x00; + dev->state = STATE_IDLE; + break; - case 2: /* "controller-select" */ - /* Reset the DCB buffer. */ - dev->buf_idx = 0; - dev->buf_len = sizeof(dcb_t); - dev->buf_ptr = (uint8_t *)&dev->dcb; - dev->state = STATE_RDATA; - dev->status = (STAT_BSY | STAT_CD | STAT_REQ); - break; + case 2: /* "controller-select" */ + /* Reset the DCB buffer. */ + dev->buf_idx = 0; + dev->buf_len = sizeof(dcb_t); + dev->buf_ptr = (uint8_t *) &dev->dcb; + dev->state = STATE_RDATA; + dev->status = (STAT_BSY | STAT_CD | STAT_REQ); + break; - case 3: /* DMA/IRQ intr register */ -//xta_log("%s: WriteMASK(%02X)\n", dev->name, val); - dev->intr = val; - break; + case 3: /* DMA/IRQ intr register */ +#if 0 + xta_log("%s: WriteMASK(%02X)\n", dev->name, val); +#endif + dev->intr = val; + break; + + default: + break; } } - -static int -xta_available(void) -{ - return(rom_present(WD_BIOS_FILE)); -} - - static void * xta_init(const device_t *info) { - drive_t *drive; - char *fn = NULL; - hdc_t *dev; - int c, i; - int max = XTA_NUM; + drive_t *drive; + const char *bios_rev = NULL; + const char *fn = NULL; + hdc_t *dev; + int c; + int max = XTA_NUM; /* Allocate and initialize device block. */ dev = malloc(sizeof(hdc_t)); @@ -1006,169 +996,194 @@ xta_init(const device_t *info) dev->type = info->local; /* Do per-controller-type setup. */ - switch(dev->type) { - case 0: /* WDXT-150, with BIOS */ - dev->name = "WDXT-150"; - dev->base = device_get_config_hex16("base"); - dev->irq = device_get_config_int("irq"); - dev->rom_addr = device_get_config_hex20("bios_addr"); - dev->dma = 3; - fn = WD_BIOS_FILE; - max = 1; - break; + switch (dev->type) { + case 0: /* WDXT-150, with BIOS */ + dev->name = "WDXT-150"; + dev->base = device_get_config_hex16("base"); + dev->irq = device_get_config_int("irq"); + dev->rom_addr = device_get_config_hex20("bios_addr"); + dev->dma = 3; + bios_rev = (char *) device_get_config_bios("bios_rev"); + fn = (char *) device_get_bios_file(info, bios_rev, 0); + max = 1; + break; - case 1: /* EuroPC */ - dev->name = "HD20"; - dev->base = 0x0320; - dev->irq = 5; - dev->dma = 3; - break; + case 1: /* EuroPC */ + dev->name = "HD20"; + dev->base = 0x0320; + dev->irq = 5; + dev->dma = 3; + break; + + default: + break; } xta_log("%s: initializing (I/O=%04X, IRQ=%d, DMA=%d", - dev->name, dev->base, dev->irq, dev->dma); + dev->name, dev->base, dev->irq, dev->dma); if (dev->rom_addr != 0x000000) - xta_log(", BIOS=%06X", dev->rom_addr); + xta_log(", BIOS=%06X", dev->rom_addr); + xta_log(")\n"); /* Load any disks for this device class. */ c = 0; - for (i = 0; i < HDD_NUM; i++) { - if ((hdd[i].bus == HDD_BUS_XTA) && (hdd[i].xta_channel < max)) { - drive = &dev->drives[hdd[i].xta_channel]; + for (uint8_t i = 0; i < HDD_NUM; i++) { + if ((hdd[i].bus == HDD_BUS_XTA) && (hdd[i].xta_channel < max)) { + drive = &dev->drives[hdd[i].xta_channel]; - if (! hdd_image_load(i)) { - drive->present = 0; - continue; - } - drive->id = c; - drive->hdd_num = i; - drive->present = 1; + if (!hdd_image_load(i)) { + drive->present = 0; + continue; + } + drive->id = c; + drive->hdd_num = i; + drive->present = 1; - /* These are the "hardware" parameters (from the image.) */ - drive->cfg_spt = (uint8_t)(hdd[i].spt & 0xff); - drive->cfg_hpc = (uint8_t)(hdd[i].hpc & 0xff); - drive->cfg_tracks = (uint16_t)hdd[i].tracks; + /* These are the "hardware" parameters (from the image.) */ + drive->cfg_spt = (uint8_t) (hdd[i].spt & 0xff); + drive->cfg_hpc = (uint8_t) (hdd[i].hpc & 0xff); + drive->cfg_tracks = (uint16_t) hdd[i].tracks; - /* Use them as "configured" parameters until overwritten. */ - drive->spt = drive->cfg_spt; - drive->hpc = drive->cfg_hpc; - drive->tracks = drive->cfg_tracks; + /* Use them as "configured" parameters until overwritten. */ + drive->spt = drive->cfg_spt; + drive->hpc = drive->cfg_hpc; + drive->tracks = drive->cfg_tracks; - xta_log("%s: drive%d (cyl=%d,hd=%d,spt=%d), disk %d\n", - dev->name, hdd[i].xta_channel, drive->tracks, - drive->hpc, drive->spt, i); + xta_log("%s: drive%d (cyl=%d,hd=%d,spt=%d), disk %d\n", + dev->name, hdd[i].xta_channel, drive->tracks, + drive->hpc, drive->spt, i); - if (++c > max) break; - } + if (++c > max) + break; + } } /* Enable the I/O block. */ io_sethandler(dev->base, 4, - hdc_read,NULL,NULL, hdc_write,NULL,NULL, dev); + hdc_read, NULL, NULL, hdc_write, NULL, NULL, dev); /* Load BIOS if it has one. */ if (dev->rom_addr != 0x000000) { - rom_init(&dev->bios_rom, fn, - dev->rom_addr, 0x2000, 0x1fff, 0, MEM_MAPPING_EXTERNAL); - } - + rom_init(&dev->bios_rom, fn, + dev->rom_addr, 0x2000, 0x1fff, 0, MEM_MAPPING_EXTERNAL); + } + /* Create a timer for command delays. */ timer_add(&dev->timer, hdc_callback, dev, 0); - return(dev); + return dev; } - static void xta_close(void *priv) { - hdc_t *dev = (hdc_t *)priv; - drive_t *drive; - int d; + hdc_t *dev = (hdc_t *) priv; + const drive_t *drive; /* Remove the I/O handler. */ io_removehandler(dev->base, 4, - hdc_read,NULL,NULL, hdc_write,NULL,NULL, dev); + hdc_read, NULL, NULL, hdc_write, NULL, NULL, dev); /* Close all disks and their images. */ - for (d = 0; d < XTA_NUM; d++) { - drive = &dev->drives[d]; + for (uint8_t d = 0; d < XTA_NUM; d++) { + drive = &dev->drives[d]; - hdd_image_close(drive->hdd_num); + hdd_image_close(drive->hdd_num); } /* Release the device. */ free(dev); } - static const device_config_t wdxt150_config[] = { - { - "base", "Address", CONFIG_HEX16, "", 0x0320, "", { 0 }, /*W2*/ - { - { - "320H", 0x0320 - }, - { - "324H", 0x0324 - }, - { - "" - } - }, + // clang-format off + { + .name = "base", + .description = "Address", + .type = CONFIG_HEX16, + .default_string = "", + .default_int = 0x0320, + .file_filter = "", + .spinner = { 0 }, /*W2*/ + .selection = { + { .description = "320H", .value = 0x0320 }, + { .description = "324H", .value = 0x0324 }, + { .description = "" } }, - { - "irq", "IRQ", CONFIG_SELECTION, "", 5, "", { 0 }, /*W3*/ - { - { - "IRQ 5", 5 - }, - { - "IRQ 4", 4 - }, - { - "" - } - }, + }, + { + .name = "irq", + .description = "IRQ", + .type = CONFIG_SELECTION, + .default_string = "", + .default_int = 5, + .file_filter = "", + .spinner = { 0 }, /*W3*/ + .selection = { + { .description = "IRQ 5", .value = 5 }, + { .description = "IRQ 4", .value = 4 }, + { .description = "" } }, - { - "bios_addr", "BIOS Address", CONFIG_HEX20, "", 0xc8000, "", { 0 }, /*W1*/ - { - { - "C800H", 0xc8000 - }, - { - "CA00H", 0xca000 - }, - { - "" - } - }, + }, + { + .name = "bios_addr", + .description = "BIOS Address", + .type = CONFIG_HEX20, + .default_string = "", + .default_int = 0xc8000, + .file_filter = "", + .spinner = { 0 }, /*W1*/ + .selection = { + { .description = "C800H", .value = 0xc8000 }, + { .description = "CA00H", .value = 0xca000 }, + { .description = "" } }, - { - "", "", -1 - } + }, + { + .name = "bios_rev", + .description = "BIOS Revision", + .type = CONFIG_BIOS, + .default_string = "rev_1", + .default_int = 0, + .file_filter = "", + .spinner = { 0 }, /*W1*/ + .bios = { + { .name = "Revision 1.0", .internal_name = "rev_1", .bios_type = BIOS_NORMAL, + .files_no = 1, .local = 0, .size = 8192, .files = { WD_REV_1_BIOS_FILE, "" } }, + { .name = "Revision 2.0", .internal_name = "rev_2", .bios_type = BIOS_NORMAL, + .files_no = 1, .local = 0, .size = 8192, .files = { WD_REV_2_BIOS_FILE, "" } }, + { .files_no = 0 } + }, + }, + { .name = "", .description = "", .type = CONFIG_END } +// clang-format off }; - const device_t xta_wdxt150_device = { - "WDXT-150 XTA Fixed Disk Controller", - "xta_wdxt150", - DEVICE_ISA, - 0, - xta_init, xta_close, NULL, - { xta_available }, NULL, NULL, - wdxt150_config + .name = "WDXT-150 XTA Fixed Disk Controller", + .internal_name = "xta_wdxt150", + .flags = DEVICE_ISA, + .local = 0, + .init = xta_init, + .close = xta_close, + .reset = NULL, + { .available = NULL /*xta_available*/ }, + .speed_changed = NULL, + .force_redraw = NULL, + .config = wdxt150_config }; - const device_t xta_hd20_device = { - "EuroPC HD20 Fixed Disk Controller", - "xta_hd20", - DEVICE_ISA, - 1, - xta_init, xta_close, NULL, - { NULL }, NULL, NULL, - NULL + .name = "EuroPC HD20 Fixed Disk Controller", + .internal_name = "xta_hd20", + .flags = DEVICE_ISA, + .local = 1, + .init = xta_init, + .close = xta_close, + .reset = NULL, + { .available = NULL }, + .speed_changed = NULL, + .force_redraw = NULL, + .config = NULL }; diff --git a/src/disk/hdc_xtide.c b/src/disk/hdc_xtide.c index 84b31bc8d..dfe5931f1 100644 --- a/src/disk/hdc_xtide.c +++ b/src/disk/hdc_xtide.c @@ -1,35 +1,35 @@ /* - * 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. + * 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. + * This file is part of the 86Box distribution. * - * XT-IDE controller emulation. + * XT-IDE controller emulation. * - * The XT-IDE project is intended to allow 8-bit ("XT") systems - * to use regular IDE drives. IDE is a standard based on the - * 16b PC/AT design, and so a special board (with its own BIOS) - * had to be created for this. + * The XT-IDE project is intended to allow 8-bit ("XT") systems + * to use regular IDE drives. IDE is a standard based on the + * 16b PC/AT design, and so a special board (with its own BIOS) + * had to be created for this. * - * XT-IDE is *NOT* the same as XTA, or X-IDE, which is an older - * standard where the actual MFM/RLL controller for the PC/XT - * was placed on the hard drive (hard drives where its drive - * type would end in "X" or "XT", such as the 8425XT.) This was - * more or less the original IDE, but since those systems were - * already on their way out, the newer IDE standard based on the - * PC/AT controller and 16b design became the IDE we now know. + * XT-IDE is *NOT* the same as XTA, or X-IDE, which is an older + * standard where the actual MFM/RLL controller for the PC/XT + * was placed on the hard drive (hard drives where its drive + * type would end in "X" or "XT", such as the 8425XT.) This was + * more or less the original IDE, but since those systems were + * already on their way out, the newer IDE standard based on the + * PC/AT controller and 16b design became the IDE we now know. * * * - * Authors: Sarah Walker, - * Miran Grca, - * Fred N. van Kempen, + * Authors: Sarah Walker, + * Miran Grca, + * Fred N. van Kempen, * - * Copyright 2008-2018 Sarah Walker. - * Copyright 2016-2018 Miran Grca. - * Copyright 2017,2018 Fred N. van Kempen. + * Copyright 2008-2018 Sarah Walker. + * Copyright 2016-2018 Miran Grca. + * Copyright 2017-2018 Fred N. van Kempen. */ #include #include @@ -40,94 +40,95 @@ #include <86box/io.h> #include <86box/mem.h> #include <86box/rom.h> +#include <86box/timer.h> #include <86box/device.h> #include <86box/hdc.h> #include <86box/hdc_ide.h> +#include <86box/plat_unused.h> +#define ROM_PATH_XT "roms/hdd/xtide/ide_xt.bin" +#define ROM_PATH_XTP "roms/hdd/xtide/ide_xtp.bin" +#define ROM_PATH_AT "roms/hdd/xtide/ide_at.bin" +#define ROM_PATH_PS2 "roms/hdd/xtide/SIDE1V12.BIN" +#define ROM_PATH_PS2AT "roms/hdd/xtide/ide_at_1_1_5.bin" +#define ROM_PATH_AT_386 "roms/hdd/xtide/ide_386.bin" -#define ROM_PATH_XT "roms/hdd/xtide/ide_xt.bin" -#define ROM_PATH_AT "roms/hdd/xtide/ide_at.bin" -#define ROM_PATH_PS2 "roms/hdd/xtide/SIDE1V12.BIN" -#define ROM_PATH_PS2AT "roms/hdd/xtide/ide_at_1_1_5.bin" -#define ROM_PATH_AT_386 "roms/hdd/xtide/ide_386.bin" - - -typedef struct { - void *ide_board; - uint8_t data_high; - rom_t bios_rom; +typedef struct xtide_t { + void *ide_board; + uint8_t data_high; + rom_t bios_rom; } xtide_t; - static void xtide_write(uint16_t port, uint8_t val, void *priv) { - xtide_t *xtide = (xtide_t *)priv; + xtide_t *xtide = (xtide_t *) priv; switch (port & 0xf) { - case 0x0: - ide_writew(0x0, val | (xtide->data_high << 8), xtide->ide_board); - return; + case 0x0: + ide_writew(0x0, val | (xtide->data_high << 8), xtide->ide_board); + return; - case 0x1: - case 0x2: - case 0x3: - case 0x4: - case 0x5: - case 0x6: - case 0x7: - ide_writeb((port & 0xf), val, xtide->ide_board); - return; + case 0x1: + case 0x2: + case 0x3: + case 0x4: + case 0x5: + case 0x6: + case 0x7: + ide_writeb((port & 0xf), val, xtide->ide_board); + return; - case 0x8: - xtide->data_high = val; - return; + case 0x8: + xtide->data_high = val; + return; - case 0xe: - ide_write_devctl(0x0, val, xtide->ide_board); - return; + case 0xe: + ide_write_devctl(0x0, val, xtide->ide_board); + return; + + default: + break; } } - static uint8_t xtide_read(uint16_t port, void *priv) { - xtide_t *xtide = (xtide_t *)priv; + xtide_t *xtide = (xtide_t *) priv; uint16_t tempw = 0xffff; switch (port & 0xf) { - case 0x0: - tempw = ide_readw(0x0, xtide->ide_board); - xtide->data_high = tempw >> 8; - break; + case 0x0: + tempw = ide_readw(0x0, xtide->ide_board); + xtide->data_high = tempw >> 8; + break; - case 0x1: - case 0x2: - case 0x3: - case 0x4: - case 0x5: - case 0x6: - case 0x7: - tempw = ide_readb((port & 0xf), xtide->ide_board); - break; + case 0x1: + case 0x2: + case 0x3: + case 0x4: + case 0x5: + case 0x6: + case 0x7: + tempw = ide_readb((port & 0xf), xtide->ide_board); + break; - case 0x8: - tempw = xtide->data_high; - break; + case 0x8: + tempw = xtide->data_high; + break; - case 0xe: - tempw = ide_read_alt_status(0x0, xtide->ide_board); - break; + case 0xe: + tempw = ide_read_alt_status(0x0, xtide->ide_board); + break; - default: - break; + default: + break; } - return(tempw & 0xff); + return (tempw & 0xff); } - static void * xtide_init(const device_t *info) { @@ -135,25 +136,34 @@ xtide_init(const device_t *info) memset(xtide, 0x00, sizeof(xtide_t)); - rom_init(&xtide->bios_rom, ROM_PATH_XT, - 0xc8000, 0x2000, 0x1fff, 0, MEM_MAPPING_EXTERNAL); + if (info->local == 1) { + rom_init(&xtide->bios_rom, ROM_PATH_XTP, + 0xc8000, 0x2000, 0x1fff, 0, MEM_MAPPING_EXTERNAL); + } else { + rom_init(&xtide->bios_rom, ROM_PATH_XT, + 0xc8000, 0x2000, 0x1fff, 0, MEM_MAPPING_EXTERNAL); + } xtide->ide_board = ide_xtide_init(); io_sethandler(0x0300, 16, - xtide_read, NULL, NULL, - xtide_write, NULL, NULL, xtide); + xtide_read, NULL, NULL, + xtide_write, NULL, NULL, xtide); - return(xtide); + return xtide; } - static int xtide_available(void) { - return(rom_present(ROM_PATH_XT)); + return (rom_present(ROM_PATH_XT)); } +static int +xtide_plus_available(void) +{ + return (rom_present(ROM_PATH_XTP)); +} static void * xtide_at_init(const device_t *info) @@ -163,149 +173,174 @@ xtide_at_init(const device_t *info) memset(xtide, 0x00, sizeof(xtide_t)); if (info->local == 1) { - rom_init(&xtide->bios_rom, ROM_PATH_AT_386, - 0xc8000, 0x2000, 0x1fff, 0, MEM_MAPPING_EXTERNAL); + rom_init(&xtide->bios_rom, ROM_PATH_AT_386, + 0xc8000, 0x2000, 0x1fff, 0, MEM_MAPPING_EXTERNAL); } else { - rom_init(&xtide->bios_rom, ROM_PATH_AT, - 0xc8000, 0x2000, 0x1fff, 0, MEM_MAPPING_EXTERNAL); + rom_init(&xtide->bios_rom, ROM_PATH_AT, + 0xc8000, 0x2000, 0x1fff, 0, MEM_MAPPING_EXTERNAL); } device_add(&ide_isa_2ch_device); - return(xtide); + return xtide; } - static int xtide_at_available(void) { - return(rom_present(ROM_PATH_AT)); + return (rom_present(ROM_PATH_AT)); } - static int xtide_at_386_available(void) { - return(rom_present(ROM_PATH_AT_386)); + return (rom_present(ROM_PATH_AT_386)); } - static void * -xtide_acculogic_init(const device_t *info) +xtide_acculogic_init(UNUSED(const device_t *info)) { xtide_t *xtide = malloc(sizeof(xtide_t)); memset(xtide, 0x00, sizeof(xtide_t)); rom_init(&xtide->bios_rom, ROM_PATH_PS2, - 0xc8000, 0x2000, 0x1fff, 0, MEM_MAPPING_EXTERNAL); + 0xc8000, 0x2000, 0x1fff, 0, MEM_MAPPING_EXTERNAL); xtide->ide_board = ide_xtide_init(); io_sethandler(0x0360, 16, - xtide_read, NULL, NULL, - xtide_write, NULL, NULL, xtide); + xtide_read, NULL, NULL, + xtide_write, NULL, NULL, xtide); - return(xtide); + return xtide; } - static int xtide_acculogic_available(void) { - return(rom_present(ROM_PATH_PS2)); + return (rom_present(ROM_PATH_PS2)); } - static void xtide_close(void *priv) { - xtide_t *xtide = (xtide_t *)priv; + xtide_t *xtide = (xtide_t *) priv; free(xtide); ide_xtide_close(); } - static void * -xtide_at_ps2_init(const device_t *info) +xtide_at_ps2_init(UNUSED(const device_t *info)) { xtide_t *xtide = malloc(sizeof(xtide_t)); memset(xtide, 0x00, sizeof(xtide_t)); rom_init(&xtide->bios_rom, ROM_PATH_PS2AT, - 0xc8000, 0x2000, 0x1fff, 0, MEM_MAPPING_EXTERNAL); + 0xc8000, 0x2000, 0x1fff, 0, MEM_MAPPING_EXTERNAL); device_add(&ide_isa_2ch_device); - return(xtide); + return xtide; } - static int xtide_at_ps2_available(void) { - return(rom_present(ROM_PATH_PS2AT)); + return (rom_present(ROM_PATH_PS2AT)); } - static void xtide_at_close(void *priv) { - xtide_t *xtide = (xtide_t *)priv; + xtide_t *xtide = (xtide_t *) priv; free(xtide); } - const device_t xtide_device = { - "PC/XT XTIDE", - "xtide", - DEVICE_ISA, - 0, - xtide_init, xtide_close, NULL, - { xtide_available }, NULL, NULL, - NULL + .name = "PC/XT XTIDE", + .internal_name = "xtide", + .flags = DEVICE_ISA, + .local = 0, + .init = xtide_init, + .close = xtide_close, + .reset = NULL, + { .available = xtide_available }, + .speed_changed = NULL, + .force_redraw = NULL, + .config = NULL +}; + +const device_t xtide_plus_device = { + .name = "PC/XT XTIDE (V20/V30/8018x)", + .internal_name = "xtide_plus", + .flags = DEVICE_ISA, + .local = 1, + .init = xtide_init, + .close = xtide_close, + .reset = NULL, + { .available = xtide_plus_available }, + .speed_changed = NULL, + .force_redraw = NULL, + .config = NULL }; const device_t xtide_at_device = { - "PC/AT XTIDE", - "xtide_at", - DEVICE_ISA | DEVICE_AT, - 0, - xtide_at_init, xtide_at_close, NULL, - { xtide_at_available }, NULL, NULL, - NULL + .name = "PC/AT XTIDE", + .internal_name = "xtide_at", + .flags = DEVICE_ISA | DEVICE_AT, + .local = 0, + .init = xtide_at_init, + .close = xtide_at_close, + .reset = NULL, + { .available = xtide_at_available }, + .speed_changed = NULL, + .force_redraw = NULL, + .config = NULL }; const device_t xtide_at_386_device = { - "PC/AT XTIDE (386)", - "xtide_at_386", - DEVICE_ISA | DEVICE_AT, - 1, - xtide_at_init, xtide_at_close, NULL, - { xtide_at_386_available }, NULL, NULL, - NULL + .name = "PC/AT XTIDE (386)", + .internal_name = "xtide_at_386", + .flags = DEVICE_ISA | DEVICE_AT, + .local = 1, + .init = xtide_at_init, + .close = xtide_at_close, + .reset = NULL, + { .available = xtide_at_386_available }, + .speed_changed = NULL, + .force_redraw = NULL, + .config = NULL }; const device_t xtide_acculogic_device = { - "Acculogic XT IDE", - "xtide_acculogic", - DEVICE_ISA, - 0, - xtide_acculogic_init, xtide_close, NULL, - { xtide_acculogic_available }, NULL, NULL, - NULL + .name = "Acculogic XT IDE", + .internal_name = "xtide_acculogic", + .flags = DEVICE_ISA, + .local = 0, + .init = xtide_acculogic_init, + .close = xtide_close, + .reset = NULL, + { .available = xtide_acculogic_available }, + .speed_changed = NULL, + .force_redraw = NULL, + .config = NULL }; const device_t xtide_at_ps2_device = { - "PS/2 AT XTIDE (1.1.5)", - "xtide_at_ps2", - DEVICE_ISA | DEVICE_AT, - 0, - xtide_at_ps2_init, xtide_at_close, NULL, - { xtide_at_ps2_available }, NULL, NULL, - NULL + .name = "PS/2 AT XTIDE (1.1.5)", + .internal_name = "xtide_at_ps2", + .flags = DEVICE_ISA | DEVICE_AT, + .local = 0, + .init = xtide_at_ps2_init, + .close = xtide_at_close, + .reset = NULL, + { .available = xtide_at_ps2_available }, + .speed_changed = NULL, + .force_redraw = NULL, + .config = NULL }; diff --git a/src/disk/hdd.c b/src/disk/hdd.c index c2d619062..3bb15c241 100644 --- a/src/disk/hdd.c +++ b/src/disk/hdd.c @@ -1,34 +1,39 @@ /* - * 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. + * 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. + * This file is part of the 86Box distribution. * - * Common code to handle all sorts of hard disk images. + * Common code to handle all sorts of hard disk images. * * * - * Authors: Miran Grca, - * Fred N. van Kempen, + * Authors: Miran Grca, + * Fred N. van Kempen, * - * Copyright 2016-2019 Miran Grca. - * Copyright 2017-2019 Fred N. van Kempen. + * Copyright 2016-2019 Miran Grca. + * Copyright 2017-2019 Fred N. van Kempen. */ #include -#include +#include #include +#include +#include +#include #include #include <86box/86box.h> #include <86box/plat.h> #include <86box/ui.h> #include <86box/hdd.h> #include <86box/cdrom.h> +#include <86box/video.h> +#include "cpu.h" +#define HDD_OVERHEAD_TIME 50.0 -hard_disk_t hdd[HDD_NUM]; - +hard_disk_t hdd[HDD_NUM]; int hdd_init(void) @@ -36,117 +41,496 @@ hdd_init(void) /* Clear all global data. */ memset(hdd, 0x00, sizeof(hdd)); - return(0); + return 0; } - int hdd_string_to_bus(char *str, int cdrom) { - if (! strcmp(str, "none")) - return(HDD_BUS_DISABLED); + if (!strcmp(str, "none")) + return HDD_BUS_DISABLED; - if (! strcmp(str, "mfm") || ! strcmp(str, "rll")) { - if (cdrom) { + if (!strcmp(str, "mfm") || !strcmp(str, "rll")) { + if (cdrom) { no_cdrom: - ui_msgbox_header(MBX_ERROR, (wchar_t *) IDS_2130, (wchar_t *) IDS_4099); - return(0); - } + ui_msgbox_header(MBX_ERROR, (wchar_t *) IDS_2131, (wchar_t *) IDS_4099); + return 0; + } - return(HDD_BUS_MFM); + return HDD_BUS_MFM; } /* FIXME: delete 'rll' in a year or so.. --FvK */ if (!strcmp(str, "esdi") || !strcmp(str, "rll")) { - if (cdrom) goto no_cdrom; + if (cdrom) + goto no_cdrom; - return(HDD_BUS_ESDI); + return HDD_BUS_ESDI; } - if (! strcmp(str, "ide_pio_only")) - return(HDD_BUS_IDE); + if (!strcmp(str, "ide_pio_only")) + return HDD_BUS_IDE; - if (! strcmp(str, "ide")) - return(HDD_BUS_IDE); + if (!strcmp(str, "ide")) + return HDD_BUS_IDE; - if (! strcmp(str, "atapi_pio_only")) - return(HDD_BUS_ATAPI); + if (!strcmp(str, "atapi_pio_only")) + return HDD_BUS_ATAPI; - if (! strcmp(str, "atapi")) - return(HDD_BUS_ATAPI); + if (!strcmp(str, "atapi")) + return HDD_BUS_ATAPI; - if (! strcmp(str, "eide")) - return(HDD_BUS_IDE); + if (!strcmp(str, "eide")) + return HDD_BUS_IDE; - if (! strcmp(str, "xta")) - return(HDD_BUS_XTA); + if (!strcmp(str, "xta")) + return HDD_BUS_XTA; - if (! strcmp(str, "atide")) - return(HDD_BUS_IDE); + if (!strcmp(str, "atide")) + return HDD_BUS_IDE; - if (! strcmp(str, "ide_pio_and_dma")) - return(HDD_BUS_IDE); + if (!strcmp(str, "ide_pio_and_dma")) + return HDD_BUS_IDE; - if (! strcmp(str, "atapi_pio_and_dma")) - return(HDD_BUS_ATAPI); + if (!strcmp(str, "atapi_pio_and_dma")) + return HDD_BUS_ATAPI; - if (! strcmp(str, "scsi")) - return(HDD_BUS_SCSI); + if (!strcmp(str, "scsi")) + return HDD_BUS_SCSI; - return(0); + return 0; } - char * -hdd_bus_to_string(int bus, int cdrom) +hdd_bus_to_string(int bus, UNUSED(int cdrom)) { char *s = "none"; switch (bus) { - case HDD_BUS_DISABLED: - default: - break; + default: + case HDD_BUS_DISABLED: + break; - case HDD_BUS_MFM: - s = "mfm"; - break; + case HDD_BUS_MFM: + s = "mfm"; + break; - case HDD_BUS_XTA: - s = "xta"; - break; + case HDD_BUS_XTA: + s = "xta"; + break; - case HDD_BUS_ESDI: - s = "esdi"; - break; + case HDD_BUS_ESDI: + s = "esdi"; + break; - case HDD_BUS_IDE: - s = "ide"; - break; + case HDD_BUS_IDE: + s = "ide"; + break; - case HDD_BUS_ATAPI: - s = "atapi"; - break; + case HDD_BUS_ATAPI: + s = "atapi"; + break; - case HDD_BUS_SCSI: - s = "scsi"; - break; + case HDD_BUS_SCSI: + s = "scsi"; + break; } - return(s); + return s; } - int hdd_is_valid(int c) { if (hdd[c].bus == HDD_BUS_DISABLED) - return(0); + return 0; if (strlen(hdd[c].fn) == 0) - return(0); + return 0; - if ((hdd[c].tracks==0) || (hdd[c].hpc==0) || (hdd[c].spt==0)) - return(0); + if ((hdd[c].tracks == 0) || (hdd[c].hpc == 0) || (hdd[c].spt == 0)) + return 0; - return(1); + return 1; +} + +double +hdd_seek_get_time(hard_disk_t *hdd, uint32_t dst_addr, uint8_t operation, uint8_t continuous, double max_seek_time) +{ + if (!hdd->speed_preset) + return HDD_OVERHEAD_TIME; + + const hdd_zone_t *zone = NULL; + if (hdd->num_zones <= 0) { + fatal("hdd_seek_get_time(): hdd->num_zones < 0)\n"); + return 0.0; + } + for (uint32_t i = 0; i < hdd->num_zones; i++) { + zone = &hdd->zones[i]; + if (zone->end_sector >= dst_addr) + break; + } + + double continuous_times[2][2] = { + {hdd->head_switch_usec, hdd->cyl_switch_usec }, + { zone->sector_time_usec, zone->sector_time_usec} + }; + double times[2] = { HDD_OVERHEAD_TIME, hdd->avg_rotation_lat_usec }; + + uint32_t new_track = zone->start_track + ((dst_addr - zone->start_sector) / zone->sectors_per_track); + uint32_t new_cylinder = new_track / hdd->phy_heads; + uint32_t cylinder_diff = abs((int) hdd->cur_cylinder - (int) new_cylinder); + + bool sequential = dst_addr == hdd->cur_addr + 1; + continuous = continuous && sequential; + + double seek_time = 0.0; + if (continuous) + seek_time = continuous_times[new_track == hdd->cur_track][!!cylinder_diff]; + else { + if (!cylinder_diff) + seek_time = times[operation != HDD_OP_SEEK]; + else { + seek_time = hdd->cyl_switch_usec + (hdd->full_stroke_usec * (double) cylinder_diff / (double) hdd->phy_cyl) + ((operation != HDD_OP_SEEK) * hdd->avg_rotation_lat_usec); + } + } + + if (!max_seek_time || seek_time <= max_seek_time) { + hdd->cur_addr = dst_addr; + hdd->cur_track = new_track; + hdd->cur_cylinder = new_cylinder; + } + + return seek_time; +} + +static void +hdd_readahead_update(hard_disk_t *hdd) +{ + uint64_t elapsed_cycles; + double elapsed_us; + double seek_time; + int32_t max_read_ahead; + uint32_t space_needed; + + hdd_cache_t *cache = &hdd->cache; + if (cache->ra_ongoing) { + hdd_cache_seg_t *segment = &cache->segments[cache->ra_segment]; + + elapsed_cycles = tsc - cache->ra_start_time; + elapsed_us = (double) elapsed_cycles / cpuclock * 1000000.0; + /* Do not overwrite data not yet read by host */ + max_read_ahead = (segment->host_addr + cache->segment_size) - segment->ra_addr; + + seek_time = 0.0; + + for (int32_t i = 0; i < max_read_ahead; i++) { + seek_time += hdd_seek_get_time(hdd, segment->ra_addr, HDD_OP_READ, 1, elapsed_us - seek_time); + if (seek_time > elapsed_us) + break; + + segment->ra_addr++; + } + + if (segment->ra_addr > segment->lba_addr + cache->segment_size) { + space_needed = segment->ra_addr - (segment->lba_addr + cache->segment_size); + segment->lba_addr += space_needed; + } + } +} + +static double +hdd_writecache_flush(hard_disk_t *hdd) +{ + double seek_time = 0.0; + + while (hdd->cache.write_pending) { + seek_time += hdd_seek_get_time(hdd, hdd->cache.write_addr, HDD_OP_WRITE, 1, 0); + hdd->cache.write_addr++; + hdd->cache.write_pending--; + } + + return seek_time; +} + +static void +hdd_writecache_update(hard_disk_t *hdd) +{ + uint64_t elapsed_cycles; + double elapsed_us; + double seek_time; + + if (hdd->cache.write_pending) { + elapsed_cycles = tsc - hdd->cache.write_start_time; + elapsed_us = (double) elapsed_cycles / cpuclock * 1000000.0; + seek_time = 0.0; + + while (hdd->cache.write_pending) { + seek_time += hdd_seek_get_time(hdd, hdd->cache.write_addr, HDD_OP_WRITE, 1, elapsed_us - seek_time); + if (seek_time > elapsed_us) + break; + + hdd->cache.write_addr++; + hdd->cache.write_pending--; + } + } +} + +double +hdd_timing_write(hard_disk_t *hdd, uint32_t addr, uint32_t len) +{ + double seek_time = 0.0; + uint32_t flush_needed; + + if (!hdd->speed_preset) + return HDD_OVERHEAD_TIME; + + hdd_readahead_update(hdd); + hdd_writecache_update(hdd); + + hdd->cache.ra_ongoing = 0; + + if (hdd->cache.write_pending && (addr != (hdd->cache.write_addr + hdd->cache.write_pending))) { + /* New request is not sequential to existing cache, need to flush it */ + seek_time += hdd_writecache_flush(hdd); + } + + if (!hdd->cache.write_pending) { + /* Cache is empty */ + hdd->cache.write_addr = addr; + } + + hdd->cache.write_pending += len; + if (hdd->cache.write_pending > hdd->cache.write_size) { + /* If request is bigger than free cache, flush some data first */ + flush_needed = hdd->cache.write_pending - hdd->cache.write_size; + for (uint32_t i = 0; i < flush_needed; i++) { + seek_time += hdd_seek_get_time(hdd, hdd->cache.write_addr, HDD_OP_WRITE, 1, 0); + hdd->cache.write_addr++; + } + } + + hdd->cache.write_start_time = tsc + (uint32_t) (seek_time * cpuclock / 1000000.0); + + return seek_time; +} + +double +hdd_timing_read(hard_disk_t *hdd, uint32_t addr, uint32_t len) +{ + double seek_time = 0.0; + + if (!hdd->speed_preset) + return HDD_OVERHEAD_TIME; + + hdd_readahead_update(hdd); + hdd_writecache_update(hdd); + + seek_time += hdd_writecache_flush(hdd); + + hdd_cache_t *cache = &hdd->cache; + hdd_cache_seg_t *active_seg = &cache->segments[0]; + + for (uint32_t i = 0; i < cache->num_segments; i++) { + hdd_cache_seg_t *segment = &cache->segments[i]; + if (!segment->valid) { + active_seg = segment; + continue; + } + + if (segment->lba_addr <= addr && (segment->lba_addr + cache->segment_size) >= addr) { + /* Cache HIT */ + segment->host_addr = addr; + active_seg = segment; + if (addr + len > segment->ra_addr) { + uint32_t need_read = (addr + len) - segment->ra_addr; + for (uint32_t j = 0; j < need_read; j++) { + seek_time += hdd_seek_get_time(hdd, segment->ra_addr, HDD_OP_READ, 1, 0.0); + segment->ra_addr++; + } + } + if (addr + len > segment->lba_addr + cache->segment_size) { + /* Need to erase some previously cached data */ + uint32_t space_needed = (addr + len) - (segment->lba_addr + cache->segment_size); + segment->lba_addr += space_needed; + } + goto update_lru; + } else { + if (segment->lru > active_seg->lru) + active_seg = segment; + } + } + + /* Cache MISS */ + active_seg->lba_addr = addr; + active_seg->valid = 1; + active_seg->host_addr = addr; + active_seg->ra_addr = addr; + + for (uint32_t i = 0; i < len; i++) { + seek_time += hdd_seek_get_time(hdd, active_seg->ra_addr, HDD_OP_READ, i != 0, 0.0); + active_seg->ra_addr++; + } + +update_lru: + for (uint32_t i = 0; i < cache->num_segments; i++) + cache->segments[i].lru++; + + active_seg->lru = 0; + + cache->ra_ongoing = 1; + cache->ra_segment = active_seg->id; + cache->ra_start_time = tsc + (uint32_t) (seek_time * cpuclock / 1000000.0); + + return seek_time; +} + +static void +hdd_cache_init(hard_disk_t *hdd) +{ + hdd_cache_t *cache = &hdd->cache; + + cache->ra_segment = 0; + cache->ra_ongoing = 0; + cache->ra_start_time = 0; + + for (uint32_t i = 0; i < cache->num_segments; i++) { + cache->segments[i].valid = 0; + cache->segments[i].lru = 0; + cache->segments[i].id = i; + cache->segments[i].ra_addr = 0; + cache->segments[i].host_addr = 0; + } +} + +static void +hdd_zones_init(hard_disk_t *hdd) +{ + uint32_t lba = 0; + uint32_t track = 0; + uint32_t tracks; + double revolution_usec = 60.0 / (double) hdd->rpm * 1000000.0; + hdd_zone_t *zone; + + for (uint32_t i = 0; i < hdd->num_zones; i++) { + zone = &hdd->zones[i]; + zone->start_sector = lba; + zone->start_track = track; + zone->sector_time_usec = revolution_usec / (double) zone->sectors_per_track; + tracks = zone->cylinders * hdd->phy_heads; + lba += tracks * zone->sectors_per_track; + zone->end_sector = lba - 1; + track += tracks - 1; + } +} + +static hdd_preset_t hdd_speed_presets[] = { + // clang-format off + { .name = "RAM Disk (max. speed)", .internal_name = "ramdisk", .rcache_num_seg = 16, .rcache_seg_size = 128, .max_multiple = 32 }, + { .name = "[1989] 3500 RPM", .internal_name = "1989_3500rpm", .zones = 1, .avg_spt = 35, .heads = 2, .rpm = 3500, .full_stroke_ms = 40, .track_seek_ms = 8, .rcache_num_seg = 1, .rcache_seg_size = 16, .max_multiple = 8 }, + { .name = "[1992] 3600 RPM", .internal_name = "1992_3600rpm", .zones = 1, .avg_spt = 45, .heads = 2, .rpm = 3600, .full_stroke_ms = 30, .track_seek_ms = 6, .rcache_num_seg = 4, .rcache_seg_size = 16, .max_multiple = 8 }, + { .name = "[1994] 4500 RPM", .internal_name = "1994_4500rpm", .zones = 8, .avg_spt = 80, .heads = 4, .rpm = 4500, .full_stroke_ms = 26, .track_seek_ms = 5, .rcache_num_seg = 4, .rcache_seg_size = 32, .max_multiple = 16 }, + { .name = "[1996] 5400 RPM", .internal_name = "1996_5400rpm", .zones = 16, .avg_spt = 135, .heads = 4, .rpm = 5400, .full_stroke_ms = 24, .track_seek_ms = 3, .rcache_num_seg = 4, .rcache_seg_size = 64, .max_multiple = 16 }, + { .name = "[1997] 5400 RPM", .internal_name = "1997_5400rpm", .zones = 16, .avg_spt = 185, .heads = 6, .rpm = 5400, .full_stroke_ms = 20, .track_seek_ms = 2.5, .rcache_num_seg = 8, .rcache_seg_size = 64, .max_multiple = 32 }, + { .name = "[1998] 5400 RPM", .internal_name = "1998_5400rpm", .zones = 16, .avg_spt = 300, .heads = 8, .rpm = 5400, .full_stroke_ms = 20, .track_seek_ms = 2, .rcache_num_seg = 8, .rcache_seg_size = 128, .max_multiple = 32 }, + { .name = "[2000] 7200 RPM", .internal_name = "2000_7200rpm", .zones = 16, .avg_spt = 350, .heads = 6, .rpm = 7200, .full_stroke_ms = 15, .track_seek_ms = 2, .rcache_num_seg = 16, .rcache_seg_size = 128, .max_multiple = 32 }, + // clang-format on +}; + +int +hdd_preset_get_num(void) +{ + return sizeof(hdd_speed_presets) / sizeof(hdd_preset_t); +} + +const char * +hdd_preset_getname(int preset) +{ + return hdd_speed_presets[preset].name; +} + +const char * +hdd_preset_get_internal_name(int preset) +{ + return hdd_speed_presets[preset].internal_name; +} + +int +hdd_preset_get_from_internal_name(char *s) +{ + int c = 0; + + for (int i = 0; i < (sizeof(hdd_speed_presets) / sizeof(hdd_preset_t)); i++) { + if (!strcmp(hdd_speed_presets[c].internal_name, s)) + return c; + c++; + } + + return 0; +} + +void +hdd_preset_apply(int hdd_id) +{ + hard_disk_t *hd = &hdd[hdd_id]; + double revolution_usec; + double zone_percent; + uint32_t disk_sectors; + uint32_t sectors_per_surface; + uint32_t cylinders; + uint32_t cylinders_per_zone; + uint32_t total_sectors = 0; + uint32_t spt; + uint32_t zone_sectors; + + if (hd->speed_preset >= hdd_preset_get_num()) + hd->speed_preset = 0; + + const hdd_preset_t *preset = &hdd_speed_presets[hd->speed_preset]; + + hd->cache.num_segments = preset->rcache_num_seg; + hd->cache.segment_size = preset->rcache_seg_size; + hd->max_multiple_block = preset->max_multiple; + + if (!hd->speed_preset) + return; + + hd->phy_heads = preset->heads; + hd->rpm = preset->rpm; + + revolution_usec = 60.0 / (double) hd->rpm * 1000000.0; + hd->avg_rotation_lat_usec = revolution_usec / 2; + hd->full_stroke_usec = preset->full_stroke_ms * 1000; + hd->head_switch_usec = preset->track_seek_ms * 1000; + hd->cyl_switch_usec = preset->track_seek_ms * 1000; + + hd->cache.write_size = 64; + + hd->num_zones = preset->zones; + + disk_sectors = hd->tracks * hd->hpc * hd->spt; + sectors_per_surface = (uint32_t) ceil((double) disk_sectors / (double) hd->phy_heads); + cylinders = (uint32_t) ceil((double) sectors_per_surface / (double) preset->avg_spt); + hd->phy_cyl = cylinders; + cylinders_per_zone = cylinders / preset->zones; + + for (uint32_t i = 0; i < preset->zones; i++) { + zone_percent = i * 100 / (double) preset->zones; + + if (i < preset->zones - 1) { + /* Function for realistic zone sector density */ + double spt_percent = -0.00341684 * pow(zone_percent, 2) - 0.175811 * zone_percent + 118.48; + spt = (uint32_t) ceil((double) preset->avg_spt * spt_percent / 100); + } else + spt = (uint32_t) ceil((double) (disk_sectors - total_sectors) / (double) (cylinders_per_zone * preset->heads)); + + zone_sectors = spt * cylinders_per_zone * preset->heads; + total_sectors += zone_sectors; + + hd->zones[i].cylinders = cylinders_per_zone; + hd->zones[i].sectors_per_track = spt; + } + + hdd_zones_init(hd); + hdd_cache_init(hd); } diff --git a/src/disk/hdd_image.c b/src/disk/hdd_image.c index 029ee03b1..df473d7d9 100644 --- a/src/disk/hdd_image.c +++ b/src/disk/hdd_image.c @@ -1,25 +1,24 @@ /* - * 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. + * 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. + * This file is part of the 86Box distribution. * - * Handling of hard disk image files. + * Handling of hard disk image files. * * * - * Authors: Miran Grca, - * Fred N. van Kempen, + * Authors: Miran Grca, + * Fred N. van Kempen, * - * Copyright 2016-2018 Miran Grca. - * Copyright 2017,2018 Fred N. van Kempen. + * Copyright 2016-2018 Miran Grca. + * Copyright 2017-2018 Fred N. van Kempen. */ -#define _LARGEFILE_SOURCE -#define _LARGEFILE64_SOURCE #define _GNU_SOURCE #include +#include #include #include #include @@ -29,664 +28,652 @@ #include #define HAVE_STDARG_H #include <86box/86box.h> +#include <86box/path.h> #include <86box/plat.h> #include <86box/random.h> #include <86box/hdd.h> #include "minivhd/minivhd.h" -#include "minivhd/minivhd_internal.h" +#include "minivhd/internal.h" #define HDD_IMAGE_RAW 0 #define HDD_IMAGE_HDI 1 #define HDD_IMAGE_HDX 2 #define HDD_IMAGE_VHD 3 -typedef struct -{ - FILE *file; /* Used for HDD_IMAGE_RAW, HDD_IMAGE_HDI, and HDD_IMAGE_HDX. */ - MVHDMeta* vhd; /* Used for HDD_IMAGE_VHD. */ - uint32_t base; - uint32_t pos, last_sector; - uint8_t type; /* HDD_IMAGE_RAW, HDD_IMAGE_HDI, HDD_IMAGE_HDX, or HDD_IMAGE_VHD */ - uint8_t loaded; +typedef struct hdd_image_t { + FILE *file; /* Used for HDD_IMAGE_RAW, HDD_IMAGE_HDI, and HDD_IMAGE_HDX. */ + MVHDMeta *vhd; /* Used for HDD_IMAGE_VHD. */ + uint32_t base; + uint32_t pos; + uint32_t last_sector; + uint8_t type; /* HDD_IMAGE_RAW, HDD_IMAGE_HDI, HDD_IMAGE_HDX, or HDD_IMAGE_VHD */ + uint8_t loaded; } hdd_image_t; - hdd_image_t hdd_images[HDD_NUM]; -static char empty_sector[512]; +static char empty_sector[512]; static char *empty_sector_1mb; #ifdef ENABLE_HDD_IMAGE_LOG int hdd_image_do_log = ENABLE_HDD_IMAGE_LOG; - static void hdd_image_log(const char *fmt, ...) { - va_list ap; + va_list ap; - if (hdd_image_do_log) { - va_start(ap, fmt); - pclog_ex(fmt, ap); - va_end(ap); - } + if (hdd_image_do_log) { + va_start(ap, fmt); + pclog_ex(fmt, ap); + va_end(ap); + } } #else -#define hdd_image_log(fmt, ...) +# define hdd_image_log(fmt, ...) #endif int image_is_hdi(const char *s) { - if (! strcasecmp(plat_get_extension((char *) s), "HDI")) - return 1; - else - return 0; + if (!strcasecmp(path_get_extension((char *) s), "HDI")) + return 1; + else + return 0; } - int image_is_hdx(const char *s, int check_signature) { - FILE *f; - uint64_t filelen; - uint64_t signature; + FILE *fp; + uint64_t filelen; + uint64_t signature; - if (! strcasecmp(plat_get_extension((char *) s), "HDX")) { - if (check_signature) { - f = plat_fopen(s, "rb"); - if (!f) - return 0; - if (fseeko64(f, 0, SEEK_END)) - fatal("image_is_hdx(): Error while seeking"); - filelen = ftello64(f); - if (fseeko64(f, 0, SEEK_SET)) - fatal("image_is_hdx(): Error while seeking"); - if (filelen < 44) { - if (f != NULL) - fclose(f); - return 0; - } - if (fread(&signature, 1, 8, f) != 8) - fatal("image_is_hdx(): Error reading signature\n"); - fclose(f); - if (signature == 0xD778A82044445459ll) - return 1; - else - return 0; - } else - return 1; - } else - return 0; + if (!strcasecmp(path_get_extension((char *) s), "HDX")) { + if (check_signature) { + fp = plat_fopen(s, "rb"); + if (!fp) + return 0; + if (fseeko64(fp, 0, SEEK_END)) + fatal("image_is_hdx(): Error while seeking"); + filelen = ftello64(fp); + if (fseeko64(fp, 0, SEEK_SET)) + fatal("image_is_hdx(): Error while seeking"); + if (filelen < 44) { + if (fp != NULL) + fclose(fp); + return 0; + } + if (fread(&signature, 1, 8, fp) != 8) + fatal("image_is_hdx(): Error reading signature\n"); + fclose(fp); + if (signature == 0xD778A82044445459LL) + return 1; + else + return 0; + } else + return 1; + } else + return 0; } - int image_is_vhd(const char *s, int check_signature) { - FILE* f; + FILE *fp; - if (! strcasecmp(plat_get_extension((char *) s), "VHD")) { - if (check_signature) { - f = plat_fopen(s, "rb"); - if (!f) - return 0; + if (!strcasecmp(path_get_extension((char *) s), "VHD")) { + if (check_signature) { + fp = plat_fopen(s, "rb"); + if (!fp) + return 0; - bool is_vhd = mvhd_file_is_vhd(f); - fclose(f); - return is_vhd ? 1 : 0; - } else - return 1; - } else - return 0; + bool is_vhd = mvhd_file_is_vhd(fp); + fclose(fp); + return is_vhd ? 1 : 0; + } else + return 1; + } else + return 0; } void hdd_image_calc_chs(uint32_t *c, uint32_t *h, uint32_t *s, uint32_t size) { - /* Calculate the geometry from size (in MB), using the algorithm provided in - "Virtual Hard Disk Image Format Specification, Appendix: CHS Calculation" */ - uint64_t ts = ((uint64_t) size) << 11LL; - uint32_t spt, heads, cyl, cth; - if (ts > 65535 * 16 * 255) - ts = 65535 * 16 * 255; + /* Calculate the geometry from size (in MB), using the algorithm provided in + "Virtual Hard Disk Image Format Specification, Appendix: CHS Calculation" */ + uint64_t ts = ((uint64_t) size) << 11LL; + uint32_t spt; + uint32_t heads; + uint32_t cyl; + uint32_t cth; - if (ts >= 65535 * 16 * 63) { - spt = 255; - heads = 16; - cth = (uint32_t) (ts / spt); - } else { - spt = 17; - cth = (uint32_t) (ts / spt); - heads = (cth +1023) / 1024; - if (heads < 4) - heads = 4; - if ((cth >= (heads * 1024)) || (heads > 16)) { - spt = 31; - heads = 16; - cth = (uint32_t) (ts / spt); - } - if (cth >= (heads * 1024)) { - spt = 63; - heads = 16; - cth = (uint32_t) (ts / spt); - } - } - cyl = cth / heads; - *c = cyl; - *h = heads; - *s = spt; + if (ts > 65535 * 16 * 255) + ts = 65535 * 16 * 255; + + if (ts >= 65535 * 16 * 63) { + spt = 255; + heads = 16; + cth = (uint32_t) (ts / spt); + } else { + spt = 17; + cth = (uint32_t) (ts / spt); + heads = (cth + 1023) / 1024; + if (heads < 4) + heads = 4; + if ((cth >= (heads * 1024)) || (heads > 16)) { + spt = 31; + heads = 16; + cth = (uint32_t) (ts / spt); + } + if (cth >= (heads * 1024)) { + spt = 63; + heads = 16; + cth = (uint32_t) (ts / spt); + } + } + cyl = cth / heads; + *c = cyl; + *h = heads; + *s = spt; } - static int prepare_new_hard_disk(uint8_t id, uint64_t full_size) { - uint64_t target_size = (full_size + hdd_images[id].base) - ftello64(hdd_images[id].file); + uint64_t target_size = (full_size + hdd_images[id].base) - ftello64(hdd_images[id].file); - uint32_t size; - uint32_t t, i; + uint32_t size; + uint32_t t; - t = (uint32_t) (target_size >> 20); /* Amount of 1 MB blocks. */ - size = (uint32_t) (target_size & 0xfffff); /* 1 MB mask. */ + t = (uint32_t) (target_size >> 20); /* Amount of 1 MB blocks. */ + size = (uint32_t) (target_size & 0xfffff); /* 1 MB mask. */ - empty_sector_1mb = (char *) malloc(1048576); - memset(empty_sector_1mb, 0, 1048576); + empty_sector_1mb = (char *) malloc(1048576); + memset(empty_sector_1mb, 0, 1048576); - /* Temporarily switch off suppression of seen messages so that the - progress gets displayed. */ - pclog_toggle_suppr(); - pclog("Writing image sectors: ["); + /* Temporarily switch off suppression of seen messages so that the + progress gets displayed. */ + pclog_toggle_suppr(); + pclog("Writing image sectors: ["); - /* First, write all the 1 MB blocks. */ - if (t > 0) { - for (i = 0; i < t; i++) { - fseek(hdd_images[id].file, 0, SEEK_END); - fwrite(empty_sector_1mb, 1, 1048576, hdd_images[id].file); - pclog("#"); - } - } + /* First, write all the 1 MB blocks. */ + if (t > 0) { + for (uint32_t i = 0; i < t; i++) { + fseek(hdd_images[id].file, 0, SEEK_END); + fwrite(empty_sector_1mb, 1, 1048576, hdd_images[id].file); + pclog("#"); + } + } - /* Then, write the remainder. */ - if (size > 0) { - fseek(hdd_images[id].file, 0, SEEK_END); - fwrite(empty_sector_1mb, 1, size, hdd_images[id].file); - pclog("#"); - } - pclog("]\n"); - /* Switch the suppression of seen messages back on. */ - pclog_toggle_suppr(); + /* Then, write the remainder. */ + if (size > 0) { + fseek(hdd_images[id].file, 0, SEEK_END); + fwrite(empty_sector_1mb, 1, size, hdd_images[id].file); + pclog("#"); + } + pclog("]\n"); + /* Switch the suppression of seen messages back on. */ + pclog_toggle_suppr(); - free(empty_sector_1mb); + free(empty_sector_1mb); - hdd_images[id].last_sector = (uint32_t) (full_size >> 9) - 1; + hdd_images[id].last_sector = (uint32_t) (full_size >> 9) - 1; - hdd_images[id].loaded = 1; + hdd_images[id].loaded = 1; - return 1; + return 1; } - void hdd_image_init(void) { - int i; - - for (i = 0; i < HDD_NUM; i++) - memset(&hdd_images[i], 0, sizeof(hdd_image_t)); + for (uint8_t i = 0; i < HDD_NUM; i++) + memset(&hdd_images[i], 0, sizeof(hdd_image_t)); } int hdd_image_load(int id) { - uint32_t sector_size = 512; - uint32_t zero = 0; - uint64_t signature = 0xD778A82044445459ll; - uint64_t full_size = 0; - uint64_t spt = 0, hpc = 0, tracks = 0; - int c, ret; - uint64_t s = 0; - char *fn = hdd[id].fn; - int is_hdx[2] = { 0, 0 }; - int is_vhd[2] = { 0, 0 }; - int vhd_error = 0; + uint32_t sector_size = 512; + uint32_t zero = 0; + uint64_t signature = 0xD778A82044445459LL; + uint64_t full_size = 0; + uint64_t spt = 0; + uint64_t hpc = 0; + uint64_t tracks = 0; + int ret; + uint64_t s = 0; + char *fn = hdd[id].fn; + int is_hdx[2] = { 0, 0 }; + int is_vhd[2] = { 0, 0 }; + int vhd_error = 0; - memset(empty_sector, 0, sizeof(empty_sector)); + memset(empty_sector, 0, sizeof(empty_sector)); + if (fn) { + path_normalize(fn); + } - hdd_images[id].base = 0; + hdd_images[id].base = 0; - if (hdd_images[id].loaded) { - if (hdd_images[id].file) { - fclose(hdd_images[id].file); - hdd_images[id].file = NULL; - } - else if (hdd_images[id].vhd) { - mvhd_close(hdd_images[id].vhd); - hdd_images[id].vhd = NULL; - } - hdd_images[id].loaded = 0; - } + if (hdd_images[id].loaded) { + if (hdd_images[id].file) { + fclose(hdd_images[id].file); + hdd_images[id].file = NULL; + } else if (hdd_images[id].vhd) { + mvhd_close(hdd_images[id].vhd); + hdd_images[id].vhd = NULL; + } + hdd_images[id].loaded = 0; + } - is_hdx[0] = image_is_hdx(fn, 0); - is_hdx[1] = image_is_hdx(fn, 1); + is_hdx[0] = image_is_hdx(fn, 0); + is_hdx[1] = image_is_hdx(fn, 1); - is_vhd[0] = image_is_vhd(fn, 0); - is_vhd[1] = image_is_vhd(fn, 1); + is_vhd[0] = image_is_vhd(fn, 0); + is_vhd[1] = image_is_vhd(fn, 1); - hdd_images[id].pos = 0; + hdd_images[id].pos = 0; - /* Try to open existing hard disk image */ - if (fn[0] == '.') { - hdd_image_log("File name starts with .\n"); - memset(hdd[id].fn, 0, sizeof(hdd[id].fn)); - return 0; - } - hdd_images[id].file = plat_fopen(fn, "rb+"); - if (hdd_images[id].file == NULL) { - /* Failed to open existing hard disk image */ - if (errno == ENOENT) { - /* Failed because it does not exist, - so try to create new file */ - if (hdd[id].wp) { - hdd_image_log("A write-protected image must exist\n"); - memset(hdd[id].fn, 0, sizeof(hdd[id].fn)); - return 0; - } + /* Try to open existing hard disk image */ + if (fn[0] == '.') { + hdd_image_log("File name starts with .\n"); + memset(hdd[id].fn, 0, sizeof(hdd[id].fn)); + return 0; + } + hdd_images[id].file = plat_fopen(fn, "rb+"); + if (hdd_images[id].file == NULL) { + /* Failed to open existing hard disk image */ + if (errno == ENOENT) { + /* Failed because it does not exist, + so try to create new file */ + if (hdd[id].wp) { + hdd_image_log("A write-protected image must exist\n"); + memset(hdd[id].fn, 0, sizeof(hdd[id].fn)); + return 0; + } - hdd_images[id].file = plat_fopen(fn, "wb+"); - if (hdd_images[id].file == NULL) { - hdd_image_log("Unable to open image\n"); - memset(hdd[id].fn, 0, sizeof(hdd[id].fn)); - return 0; - } else { - if (image_is_hdi(fn)) { - full_size = ((uint64_t) hdd[id].spt) * - ((uint64_t) hdd[id].hpc) * - ((uint64_t) hdd[id].tracks) << 9LL; - hdd_images[id].base = 0x1000; - fwrite(&zero, 1, 4, hdd_images[id].file); - fwrite(&zero, 1, 4, hdd_images[id].file); - fwrite(&(hdd_images[id].base), 1, 4, hdd_images[id].file); - fwrite(&full_size, 1, 4, hdd_images[id].file); - fwrite(§or_size, 1, 4, hdd_images[id].file); - fwrite(&(hdd[id].spt), 1, 4, hdd_images[id].file); - fwrite(&(hdd[id].hpc), 1, 4, hdd_images[id].file); - fwrite(&(hdd[id].tracks), 1, 4, hdd_images[id].file); - for (c = 0; c < 0x3f8; c++) - fwrite(&zero, 1, 4, hdd_images[id].file); - hdd_images[id].type = HDD_IMAGE_HDI; - } else if (is_hdx[0]) { - full_size = ((uint64_t) hdd[id].spt) * - ((uint64_t) hdd[id].hpc) * - ((uint64_t) hdd[id].tracks) << 9LL; - hdd_images[id].base = 0x28; - fwrite(&signature, 1, 8, hdd_images[id].file); - fwrite(&full_size, 1, 8, hdd_images[id].file); - fwrite(§or_size, 1, 4, hdd_images[id].file); - fwrite(&(hdd[id].spt), 1, 4, hdd_images[id].file); - fwrite(&(hdd[id].hpc), 1, 4, hdd_images[id].file); - fwrite(&(hdd[id].tracks), 1, 4, hdd_images[id].file); - fwrite(&zero, 1, 4, hdd_images[id].file); - fwrite(&zero, 1, 4, hdd_images[id].file); - hdd_images[id].type = HDD_IMAGE_HDX; - } else if (is_vhd[0]) { - fclose(hdd_images[id].file); - MVHDGeom geometry; - geometry.cyl = hdd[id].tracks; - geometry.heads = hdd[id].hpc; - geometry.spt = hdd[id].spt; - full_size = ((uint64_t) hdd[id].spt) * - ((uint64_t) hdd[id].hpc) * - ((uint64_t) hdd[id].tracks) << 9LL; - hdd_images[id].last_sector = (full_size >> 9LL) - 1; + hdd_images[id].file = plat_fopen(fn, "wb+"); + if (hdd_images[id].file == NULL) { + hdd_image_log("Unable to open image\n"); + memset(hdd[id].fn, 0, sizeof(hdd[id].fn)); + return 0; + } else { + if (image_is_hdi(fn)) { + full_size = ((uint64_t) hdd[id].spt) * ((uint64_t) hdd[id].hpc) * ((uint64_t) hdd[id].tracks) << 9LL; + hdd_images[id].base = 0x1000; + fwrite(&zero, 1, 4, hdd_images[id].file); + fwrite(&zero, 1, 4, hdd_images[id].file); + fwrite(&(hdd_images[id].base), 1, 4, hdd_images[id].file); + fwrite(&full_size, 1, 4, hdd_images[id].file); + fwrite(§or_size, 1, 4, hdd_images[id].file); + fwrite(&(hdd[id].spt), 1, 4, hdd_images[id].file); + fwrite(&(hdd[id].hpc), 1, 4, hdd_images[id].file); + fwrite(&(hdd[id].tracks), 1, 4, hdd_images[id].file); + for (uint16_t c = 0; c < 0x3f8; c++) + fwrite(&zero, 1, 4, hdd_images[id].file); + hdd_images[id].type = HDD_IMAGE_HDI; + } else if (is_hdx[0]) { + full_size = ((uint64_t) hdd[id].spt) * ((uint64_t) hdd[id].hpc) * ((uint64_t) hdd[id].tracks) << 9LL; + hdd_images[id].base = 0x28; + fwrite(&signature, 1, 8, hdd_images[id].file); + fwrite(&full_size, 1, 8, hdd_images[id].file); + fwrite(§or_size, 1, 4, hdd_images[id].file); + fwrite(&(hdd[id].spt), 1, 4, hdd_images[id].file); + fwrite(&(hdd[id].hpc), 1, 4, hdd_images[id].file); + fwrite(&(hdd[id].tracks), 1, 4, hdd_images[id].file); + fwrite(&zero, 1, 4, hdd_images[id].file); + fwrite(&zero, 1, 4, hdd_images[id].file); + hdd_images[id].type = HDD_IMAGE_HDX; + } else if (is_vhd[0]) { + fclose(hdd_images[id].file); + MVHDGeom geometry; + geometry.cyl = hdd[id].tracks; + geometry.heads = hdd[id].hpc; + geometry.spt = hdd[id].spt; + full_size = ((uint64_t) hdd[id].spt) * ((uint64_t) hdd[id].hpc) * ((uint64_t) hdd[id].tracks) << 9LL; + hdd_images[id].last_sector = (full_size >> 9LL) - 1; - hdd_images[id].vhd = mvhd_create_fixed(fn, geometry, &vhd_error, NULL); - if (hdd_images[id].vhd == NULL) - fatal("hdd_image_load(): VHD: Could not create VHD : %s\n", mvhd_strerr(vhd_error)); + if (hdd[id].vhd_blocksize || hdd[id].vhd_parent[0]) { + MVHDCreationOptions options; +retry_vhd: + options.block_size_in_sectors = hdd[id].vhd_blocksize; + options.path = fn; + options.size_in_bytes = 0; + options.geometry = geometry; + if (hdd[id].vhd_parent[0]) { + options.type = MVHD_TYPE_DIFF; + options.parent_path = hdd[id].vhd_parent; + } else { + options.type = MVHD_TYPE_DYNAMIC; + options.parent_path = NULL; + } - hdd_images[id].type = HDD_IMAGE_VHD; - return 1; - } else { - hdd_images[id].type = HDD_IMAGE_RAW; - } - hdd_images[id].last_sector = 0; - } + hdd_images[id].vhd = mvhd_create_ex(options, &vhd_error); + } else { + hdd_images[id].vhd = mvhd_create_fixed(fn, geometry, &vhd_error, NULL); + } + if (hdd_images[id].vhd == NULL) { + /* Don't lock out if the parent of a differential VHD doesn't exist. */ + if (hdd[id].vhd_parent[0]) { + hdd[id].vhd_parent[0] = '\0'; + goto retry_vhd; + } + fatal("hdd_image_load(): VHD: Could not create VHD : %s\n", mvhd_strerr(vhd_error)); + } + hdd_images[id].type = HDD_IMAGE_VHD; - s = full_size = ((uint64_t) hdd[id].spt) * - ((uint64_t) hdd[id].hpc) * - ((uint64_t) hdd[id].tracks) << 9LL; + return 1; + } else { + hdd_images[id].type = HDD_IMAGE_RAW; + } + hdd_images[id].last_sector = 0; + } - ret = prepare_new_hard_disk(id, full_size); - return ret; - } else { - /* Failed for another reason */ - hdd_image_log("Failed for another reason\n"); - memset(hdd[id].fn, 0, sizeof(hdd[id].fn)); - return 0; - } - } else { - if (image_is_hdi(fn)) { - if (fseeko64(hdd_images[id].file, 0x8, SEEK_SET) == -1) - fatal("hdd_image_load(): HDI: Error seeking to offset 0x8\n"); - if (fread(&(hdd_images[id].base), 1, 4, hdd_images[id].file) != 4) - fatal("hdd_image_load(): HDI: Error reading base offset\n"); - if (fseeko64(hdd_images[id].file, 0xC, SEEK_SET) == -1) - fatal("hdd_image_load(): HDI: Error seeking to offest 0xC\n"); - full_size = 0LL; - if (fread(&full_size, 1, 4, hdd_images[id].file) != 4) - fatal("hdd_image_load(): HDI: Error reading full size\n"); - if (fseeko64(hdd_images[id].file, 0x10, SEEK_SET) == -1) - fatal("hdd_image_load(): HDI: Error seeking to offset 0x10\n"); - if (fread(§or_size, 1, 4, hdd_images[id].file) != 4) - fatal("hdd_image_load(): HDI: Error reading sector size\n"); - if (sector_size != 512) { - /* Sector size is not 512 */ - hdd_image_log("HDI: Sector size is not 512\n"); - fclose(hdd_images[id].file); - hdd_images[id].file = NULL; - memset(hdd[id].fn, 0, sizeof(hdd[id].fn)); - return 0; - } - if (fread(&spt, 1, 4, hdd_images[id].file) != 4) - fatal("hdd_image_load(): HDI: Error reading sectors per track\n"); - if (fread(&hpc, 1, 4, hdd_images[id].file) != 4) - fatal("hdd_image_load(): HDI: Error reading heads per cylinder\n"); - if (fread(&tracks, 1, 4, hdd_images[id].file) != 4) - fatal("hdd_image_load(): HDI: Error reading number of tracks\n"); - hdd[id].spt = spt; - hdd[id].hpc = hpc; - hdd[id].tracks = tracks; - hdd_images[id].type = HDD_IMAGE_HDI; - } else if (is_hdx[1]) { - hdd_images[id].base = 0x28; - if (fseeko64(hdd_images[id].file, 8, SEEK_SET) == -1) - fatal("hdd_image_load(): HDX: Error seeking to offset 0x8\n"); - if (fread(&full_size, 1, 8, hdd_images[id].file) != 8) - fatal("hdd_image_load(): HDX: Error reading full size\n"); - if (fseeko64(hdd_images[id].file, 0x10, SEEK_SET) == -1) - fatal("hdd_image_load(): HDX: Error seeking to offset 0x10\n"); - if (fread(§or_size, 1, 4, hdd_images[id].file) != 4) - fatal("hdd_image_load(): HDX: Error reading sector size\n"); - if (sector_size != 512) { - /* Sector size is not 512 */ - hdd_image_log("HDX: Sector size is not 512\n"); - fclose(hdd_images[id].file); - hdd_images[id].file = NULL; - memset(hdd[id].fn, 0, sizeof(hdd[id].fn)); - return 0; - } - if (fread(&spt, 1, 4, hdd_images[id].file) != 4) - fatal("hdd_image_load(): HDI: Error reading sectors per track\n"); - if (fread(&hpc, 1, 4, hdd_images[id].file) != 4) - fatal("hdd_image_load(): HDI: Error reading heads per cylinder\n"); - if (fread(&tracks, 1, 4, hdd_images[id].file) != 4) - fatal("hdd_image_load(): HDX: Error reading number of tracks\n"); - hdd[id].spt = spt; - hdd[id].hpc = hpc; - hdd[id].tracks = tracks; - hdd_images[id].type = HDD_IMAGE_HDX; - } else if (is_vhd[1]) { - fclose(hdd_images[id].file); - hdd_images[id].file = NULL; - hdd_images[id].vhd = mvhd_open(fn, (bool)0, &vhd_error); - if (hdd_images[id].vhd == NULL) { - if (vhd_error == MVHD_ERR_FILE) - fatal("hdd_image_load(): VHD: Error opening VHD file '%s': %s\n", fn, strerror(mvhd_errno)); - else - fatal("hdd_image_load(): VHD: Error opening VHD file '%s': %s\n", fn, mvhd_strerr(vhd_error)); - } - else if (vhd_error == MVHD_ERR_TIMESTAMP) { - fatal("hdd_image_load(): VHD: Parent/child timestamp mismatch for VHD file '%s'\n", fn); - } + s = full_size = ((uint64_t) hdd[id].spt) * ((uint64_t) hdd[id].hpc) * ((uint64_t) hdd[id].tracks) << 9LL; - hdd[id].tracks = hdd_images[id].vhd->footer.geom.cyl; - hdd[id].hpc = hdd_images[id].vhd->footer.geom.heads; - hdd[id].spt = hdd_images[id].vhd->footer.geom.spt; - full_size = ((uint64_t) hdd[id].spt) * - ((uint64_t) hdd[id].hpc) * - ((uint64_t) hdd[id].tracks) << 9LL; - hdd_images[id].type = HDD_IMAGE_VHD; - /* If we're here, this means there is a valid VHD footer in the - image, which means that by definition, all valid sectors - are there. */ - hdd_images[id].last_sector = (uint32_t) (full_size >> 9) - 1; - hdd_images[id].loaded = 1; - return 1; - } else { - full_size = ((uint64_t) hdd[id].spt) * - ((uint64_t) hdd[id].hpc) * - ((uint64_t) hdd[id].tracks) << 9LL; - hdd_images[id].type = HDD_IMAGE_RAW; - } - } + ret = prepare_new_hard_disk(id, full_size); + return ret; + } else { + /* Failed for another reason */ + hdd_image_log("Failed for another reason\n"); + return 0; + } + } else { + if (image_is_hdi(fn)) { + if (fseeko64(hdd_images[id].file, 0x8, SEEK_SET) == -1) + fatal("hdd_image_load(): HDI: Error seeking to offset 0x8\n"); + if (fread(&(hdd_images[id].base), 1, 4, hdd_images[id].file) != 4) + fatal("hdd_image_load(): HDI: Error reading base offset\n"); + if (fseeko64(hdd_images[id].file, 0xC, SEEK_SET) == -1) + fatal("hdd_image_load(): HDI: Error seeking to offest 0xC\n"); + full_size = 0LL; + if (fread(&full_size, 1, 4, hdd_images[id].file) != 4) + fatal("hdd_image_load(): HDI: Error reading full size\n"); + if (fseeko64(hdd_images[id].file, 0x10, SEEK_SET) == -1) + fatal("hdd_image_load(): HDI: Error seeking to offset 0x10\n"); + if (fread(§or_size, 1, 4, hdd_images[id].file) != 4) + fatal("hdd_image_load(): HDI: Error reading sector size\n"); + if (sector_size != 512) { + /* Sector size is not 512 */ + hdd_image_log("HDI: Sector size is not 512\n"); + fclose(hdd_images[id].file); + hdd_images[id].file = NULL; + memset(hdd[id].fn, 0, sizeof(hdd[id].fn)); + return 0; + } + if (fread(&spt, 1, 4, hdd_images[id].file) != 4) + fatal("hdd_image_load(): HDI: Error reading sectors per track\n"); + if (fread(&hpc, 1, 4, hdd_images[id].file) != 4) + fatal("hdd_image_load(): HDI: Error reading heads per cylinder\n"); + if (fread(&tracks, 1, 4, hdd_images[id].file) != 4) + fatal("hdd_image_load(): HDI: Error reading number of tracks\n"); + hdd[id].spt = spt; + hdd[id].hpc = hpc; + hdd[id].tracks = tracks; + hdd_images[id].type = HDD_IMAGE_HDI; + } else if (is_hdx[1]) { + hdd_images[id].base = 0x28; + if (fseeko64(hdd_images[id].file, 8, SEEK_SET) == -1) + fatal("hdd_image_load(): HDX: Error seeking to offset 0x8\n"); + if (fread(&full_size, 1, 8, hdd_images[id].file) != 8) + fatal("hdd_image_load(): HDX: Error reading full size\n"); + if (fseeko64(hdd_images[id].file, 0x10, SEEK_SET) == -1) + fatal("hdd_image_load(): HDX: Error seeking to offset 0x10\n"); + if (fread(§or_size, 1, 4, hdd_images[id].file) != 4) + fatal("hdd_image_load(): HDX: Error reading sector size\n"); + if (sector_size != 512) { + /* Sector size is not 512 */ + hdd_image_log("HDX: Sector size is not 512\n"); + fclose(hdd_images[id].file); + hdd_images[id].file = NULL; + memset(hdd[id].fn, 0, sizeof(hdd[id].fn)); + return 0; + } + if (fread(&spt, 1, 4, hdd_images[id].file) != 4) + fatal("hdd_image_load(): HDI: Error reading sectors per track\n"); + if (fread(&hpc, 1, 4, hdd_images[id].file) != 4) + fatal("hdd_image_load(): HDI: Error reading heads per cylinder\n"); + if (fread(&tracks, 1, 4, hdd_images[id].file) != 4) + fatal("hdd_image_load(): HDX: Error reading number of tracks\n"); + hdd[id].spt = spt; + hdd[id].hpc = hpc; + hdd[id].tracks = tracks; + hdd_images[id].type = HDD_IMAGE_HDX; + } else if (is_vhd[1]) { + fclose(hdd_images[id].file); + hdd_images[id].file = NULL; + hdd_images[id].vhd = mvhd_open(fn, (bool) 0, &vhd_error); + if (hdd_images[id].vhd == NULL) { + if (vhd_error == MVHD_ERR_FILE) + fatal("hdd_image_load(): VHD: Error opening VHD file '%s': %s\n", fn, strerror(mvhd_errno)); + else + fatal("hdd_image_load(): VHD: Error opening VHD file '%s': %s\n", fn, mvhd_strerr(vhd_error)); + } else if (vhd_error == MVHD_ERR_TIMESTAMP) { + pclog("hdd_image_load(): VHD: Parent/child timestamp mismatch for VHD file '%s'\n", fn); + } - if (fseeko64(hdd_images[id].file, 0, SEEK_END) == -1) - fatal("hdd_image_load(): Error seeking to the end of file\n"); - s = ftello64(hdd_images[id].file); - if (s < (full_size + hdd_images[id].base)) - ret = prepare_new_hard_disk(id, full_size); - else { - hdd_images[id].last_sector = (uint32_t) (full_size >> 9) - 1; - hdd_images[id].loaded = 1; - ret = 1; - } + hdd[id].tracks = hdd_images[id].vhd->footer.geom.cyl; + hdd[id].hpc = hdd_images[id].vhd->footer.geom.heads; + hdd[id].spt = hdd_images[id].vhd->footer.geom.spt; + hdd[id].vhd_blocksize = (hdd_images[id].vhd->footer.disk_type == MVHD_TYPE_FIXED) ? 0 : (hdd_images[id].vhd->sparse.block_sz / MVHD_SECTOR_SIZE); + if (hdd_images[id].vhd->parent && hdd_images[id].vhd->parent->filename[0]) + strncpy(hdd[id].vhd_parent, hdd_images[id].vhd->parent->filename, sizeof(hdd[id].vhd_parent) - 1); + full_size = ((uint64_t) hdd[id].spt) * ((uint64_t) hdd[id].hpc) * ((uint64_t) hdd[id].tracks) << 9LL; + hdd_images[id].type = HDD_IMAGE_VHD; + /* If we're here, this means there is a valid VHD footer in the + image, which means that by definition, all valid sectors + are there. */ + hdd_images[id].last_sector = (uint32_t) (full_size >> 9) - 1; + hdd_images[id].loaded = 1; + return 1; + } else { + full_size = ((uint64_t) hdd[id].spt) * ((uint64_t) hdd[id].hpc) * ((uint64_t) hdd[id].tracks) << 9LL; + hdd_images[id].type = HDD_IMAGE_RAW; + } + } - return ret; + if (fseeko64(hdd_images[id].file, 0, SEEK_END) == -1) + fatal("hdd_image_load(): Error seeking to the end of file\n"); + s = ftello64(hdd_images[id].file); + if (s < (full_size + hdd_images[id].base)) + ret = prepare_new_hard_disk(id, full_size); + else { + hdd_images[id].last_sector = (uint32_t) (full_size >> 9) - 1; + hdd_images[id].loaded = 1; + ret = 1; + } + + return ret; } - void hdd_image_seek(uint8_t id, uint32_t sector) { - off64_t addr = sector; - addr = (uint64_t)sector << 9LL; + off64_t addr = sector; + addr = (uint64_t) sector << 9LL; - hdd_images[id].pos = sector; - if (hdd_images[id].type != HDD_IMAGE_VHD) { - if (fseeko64(hdd_images[id].file, addr + hdd_images[id].base, SEEK_SET) == -1) - fatal("hdd_image_seek(): Error seeking\n"); - } + hdd_images[id].pos = sector; + if (hdd_images[id].type != HDD_IMAGE_VHD) { + if (fseeko64(hdd_images[id].file, addr + hdd_images[id].base, SEEK_SET) == -1) + fatal("hdd_image_seek(): Error seeking\n"); + } } - void hdd_image_read(uint8_t id, uint32_t sector, uint32_t count, uint8_t *buffer) { - if (hdd_images[id].type == HDD_IMAGE_VHD) { - int non_transferred_sectors = mvhd_read_sectors(hdd_images[id].vhd, sector, count, buffer); - hdd_images[id].pos = sector + count - non_transferred_sectors - 1; - } else { - int i; + int non_transferred_sectors; + size_t num_read; - if (fseeko64(hdd_images[id].file, ((uint64_t)(sector) << 9LL) + hdd_images[id].base, SEEK_SET) == -1) { - fatal("Hard disk image %i: Read error during seek\n", id); - return; - } + if (hdd_images[id].type == HDD_IMAGE_VHD) { + non_transferred_sectors = mvhd_read_sectors(hdd_images[id].vhd, sector, count, buffer); + hdd_images[id].pos = sector + count - non_transferred_sectors - 1; + } else { + if (fseeko64(hdd_images[id].file, ((uint64_t) (sector) << 9LL) + hdd_images[id].base, SEEK_SET) == -1) { + fatal("Hard disk image %i: Read error during seek\n", id); + return; + } - for (i = 0; i < count; i++) { - if (feof(hdd_images[id].file)) - break; - - hdd_images[id].pos = sector + i; - fread(buffer + (i << 9), 1, 512, hdd_images[id].file); - } - } + num_read = fread(buffer, 512, count, hdd_images[id].file); + hdd_images[id].pos = sector + num_read; + } } - uint32_t hdd_image_get_last_sector(uint8_t id) { - return hdd_images[id].last_sector; + return hdd_images[id].last_sector; } - uint32_t hdd_sectors(uint8_t id) { - return hdd_image_get_last_sector(id) - 1; + return hdd_image_get_last_sector(id) - 1; } - int hdd_image_read_ex(uint8_t id, uint32_t sector, uint32_t count, uint8_t *buffer) { - uint32_t transfer_sectors = count; - uint32_t sectors = hdd_sectors(id); + uint32_t transfer_sectors = count; + uint32_t sectors = hdd_sectors(id); - if ((sectors - sector) < transfer_sectors) - transfer_sectors = sectors - sector; + if ((sectors - sector) < transfer_sectors) + transfer_sectors = sectors - sector; - hdd_image_read(id, sector, transfer_sectors, buffer); + hdd_image_read(id, sector, transfer_sectors, buffer); - if (count != transfer_sectors) - return 1; - return 0; + if (count != transfer_sectors) + return 1; + return 0; } - void hdd_image_write(uint8_t id, uint32_t sector, uint32_t count, uint8_t *buffer) { - if (hdd_images[id].type == HDD_IMAGE_VHD) { - int non_transferred_sectors = mvhd_write_sectors(hdd_images[id].vhd, sector, count, buffer); - hdd_images[id].pos = sector + count - non_transferred_sectors - 1; - } else { - int i; + int non_transferred_sectors; + size_t num_write; - if (fseeko64(hdd_images[id].file, ((uint64_t)(sector) << 9LL) + hdd_images[id].base, SEEK_SET) == -1) { - fatal("Hard disk image %i: Write error during seek\n", id); - return; - } + if (hdd_images[id].type == HDD_IMAGE_VHD) { + non_transferred_sectors = mvhd_write_sectors(hdd_images[id].vhd, sector, count, buffer); + hdd_images[id].pos = sector + count - non_transferred_sectors - 1; + } else { + if (fseeko64(hdd_images[id].file, ((uint64_t) (sector) << 9LL) + hdd_images[id].base, SEEK_SET) == -1) { + fatal("Hard disk image %i: Write error during seek\n", id); + return; + } - for (i = 0; i < count; i++) { - if (feof(hdd_images[id].file)) - break; - - hdd_images[id].pos = sector + i; - fwrite(buffer + (i << 9), 512, 1, hdd_images[id].file); - } - } + num_write = fwrite(buffer, 512, count, hdd_images[id].file); + hdd_images[id].pos = sector + num_write; + } } - int hdd_image_write_ex(uint8_t id, uint32_t sector, uint32_t count, uint8_t *buffer) { - uint32_t transfer_sectors = count; - uint32_t sectors = hdd_sectors(id); + uint32_t transfer_sectors = count; + uint32_t sectors = hdd_sectors(id); - if ((sectors - sector) < transfer_sectors) - transfer_sectors = sectors - sector; + if ((sectors - sector) < transfer_sectors) + transfer_sectors = sectors - sector; - hdd_image_write(id, sector, transfer_sectors, buffer); + hdd_image_write(id, sector, transfer_sectors, buffer); - if (count != transfer_sectors) - return 1; - return 0; + if (count != transfer_sectors) + return 1; + return 0; } - void hdd_image_zero(uint8_t id, uint32_t sector, uint32_t count) { - if (hdd_images[id].type == HDD_IMAGE_VHD) { - int non_transferred_sectors = mvhd_format_sectors(hdd_images[id].vhd, sector, count); - hdd_images[id].pos = sector + count - non_transferred_sectors - 1; - } else { - uint32_t i = 0; + if (hdd_images[id].type == HDD_IMAGE_VHD) { + int non_transferred_sectors = mvhd_format_sectors(hdd_images[id].vhd, sector, count); + hdd_images[id].pos = sector + count - non_transferred_sectors - 1; + } else { + memset(empty_sector, 0, 512); - memset(empty_sector, 0, 512); + if (fseeko64(hdd_images[id].file, ((uint64_t) (sector) << 9LL) + hdd_images[id].base, SEEK_SET) == -1) { + fatal("Hard disk image %i: Zero error during seek\n", id); + return; + } - if (fseeko64(hdd_images[id].file, ((uint64_t)(sector) << 9LL) + hdd_images[id].base, SEEK_SET) == -1) { - fatal("Hard disk image %i: Zero error during seek\n", id); - return; - } + for (uint32_t i = 0; i < count; i++) { + if (feof(hdd_images[id].file)) + break; - for (i = 0; i < count; i++) { - if (feof(hdd_images[id].file)) - break; - - hdd_images[id].pos = sector + i; - fwrite(empty_sector, 512, 1, hdd_images[id].file); - } - } + hdd_images[id].pos = sector + i; + fwrite(empty_sector, 512, 1, hdd_images[id].file); + } + } } - int hdd_image_zero_ex(uint8_t id, uint32_t sector, uint32_t count) { - uint32_t transfer_sectors = count; - uint32_t sectors = hdd_sectors(id); + uint32_t transfer_sectors = count; + uint32_t sectors = hdd_sectors(id); - if ((sectors - sector) < transfer_sectors) - transfer_sectors = sectors - sector; + if ((sectors - sector) < transfer_sectors) + transfer_sectors = sectors - sector; - hdd_image_zero(id, sector, transfer_sectors); + hdd_image_zero(id, sector, transfer_sectors); - if (count != transfer_sectors) - return 1; - return 0; + if (count != transfer_sectors) + return 1; + return 0; } - uint32_t hdd_image_get_pos(uint8_t id) { - return hdd_images[id].pos; + return hdd_images[id].pos; } - uint8_t hdd_image_get_type(uint8_t id) { - return hdd_images[id].type; + return hdd_images[id].type; } - void -hdd_image_unload(uint8_t id, int fn_preserve) +hdd_image_unload(uint8_t id, UNUSED(int fn_preserve)) { - if (strlen(hdd[id].fn) == 0) - return; + if (strlen(hdd[id].fn) == 0) + return; - if (hdd_images[id].loaded) { - if (hdd_images[id].file != NULL) { - fclose(hdd_images[id].file); - hdd_images[id].file = NULL; - } else if (hdd_images[id].vhd != NULL) { - mvhd_close(hdd_images[id].vhd); - hdd_images[id].vhd = NULL; - } - hdd_images[id].loaded = 0; - } + if (hdd_images[id].loaded) { + if (hdd_images[id].file != NULL) { + fclose(hdd_images[id].file); + hdd_images[id].file = NULL; + } else if (hdd_images[id].vhd != NULL) { + mvhd_close(hdd_images[id].vhd); + hdd_images[id].vhd = NULL; + } + hdd_images[id].loaded = 0; + } - hdd_images[id].last_sector = -1; + hdd_images[id].last_sector = -1; - memset(hdd[id].prev_fn, 0, sizeof(hdd[id].prev_fn)); - if (fn_preserve) - strcpy(hdd[id].prev_fn, hdd[id].fn); - memset(hdd[id].fn, 0, sizeof(hdd[id].fn)); + memset(hdd[id].fn, 0, sizeof(hdd[id].fn)); } - void hdd_image_close(uint8_t id) { - hdd_image_log("hdd_image_close(%i)\n", id); + hdd_image_log("hdd_image_close(%i)\n", id); - if (!hdd_images[id].loaded) - return; + if (!hdd_images[id].loaded) + return; - if (hdd_images[id].file != NULL) { - fclose(hdd_images[id].file); - hdd_images[id].file = NULL; - } else if (hdd_images[id].vhd != NULL) { - mvhd_close(hdd_images[id].vhd); - hdd_images[id].vhd = NULL; - } + if (hdd_images[id].file != NULL) { + fclose(hdd_images[id].file); + hdd_images[id].file = NULL; + } else if (hdd_images[id].vhd != NULL) { + mvhd_close(hdd_images[id].vhd); + hdd_images[id].vhd = NULL; + } - memset(&hdd_images[id], 0, sizeof(hdd_image_t)); - hdd_images[id].loaded = 0; + memset(&hdd_images[id], 0, sizeof(hdd_image_t)); + hdd_images[id].loaded = 0; } diff --git a/src/disk/hdd_table.c b/src/disk/hdd_table.c index 05eae6990..12a0040ef 100644 --- a/src/disk/hdd_table.c +++ b/src/disk/hdd_table.c @@ -1,21 +1,21 @@ /* - * 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. + * 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. + * This file is part of the 86Box distribution. * - * Implementation of the IDE emulation for hard disks and ATAPI - * CD-ROM devices. + * Implementation of the IDE emulation for hard disks and ATAPI + * CD-ROM devices. * * * - * Authors: Miran Grca, - * Fred N. van Kempen, + * Authors: Miran Grca, + * Fred N. van Kempen, * - * Copyright 2016-2018 Miran Grca. - * Copyright 2017,2018 Fred N. van Kempen. + * Copyright 2016-2018 Miran Grca. + * Copyright 2017-2018 Fred N. van Kempen. */ #include #include @@ -25,9 +25,9 @@ #include <86box/86box.h> #include <86box/hdd.h> - unsigned int hdd_table[128][3] = { - { 306, 4, 17 }, /* 0 - 7 */ + // clang-format off + { 306, 4, 17 }, /* 0 - 7 */ { 615, 2, 17 }, { 306, 4, 26 }, { 1024, 2, 17 }, @@ -36,7 +36,7 @@ unsigned int hdd_table[128][3] = { { 614, 4, 17 }, { 615, 4, 17 }, - { 670, 4, 17 }, /* 8 - 15 */ + { 670, 4, 17 }, /* 8 - 15 */ { 697, 4, 17 }, { 987, 3, 17 }, { 820, 4, 17 }, @@ -45,7 +45,7 @@ unsigned int hdd_table[128][3] = { { 733, 5, 17 }, { 615, 6, 17 }, - { 462, 8, 17 }, /* 016-023 */ + { 462, 8, 17 }, /* 016-023 */ { 306, 8, 26 }, { 615, 4, 26 }, { 1024, 4, 17 }, @@ -54,7 +54,7 @@ unsigned int hdd_table[128][3] = { { 932, 5, 17 }, { 1024, 2, 40 }, - { 809, 6, 17 }, /* 024-031 */ + { 809, 6, 17 }, /* 024-031 */ { 976, 5, 17 }, { 977, 5, 17 }, { 698, 7, 17 }, @@ -63,7 +63,7 @@ unsigned int hdd_table[128][3] = { { 615, 8, 17 }, { 989, 5, 17 }, - { 820, 4, 26 }, /* 032-039 */ + { 820, 4, 26 }, /* 032-039 */ { 1024, 5, 17 }, { 733, 7, 17 }, { 754, 7, 17 }, @@ -72,7 +72,7 @@ unsigned int hdd_table[128][3] = { { 615, 6, 26 }, { 462, 8, 26 }, - { 830, 7, 17 }, /* 040-047 */ + { 830, 7, 17 }, /* 040-047 */ { 855, 7, 17 }, { 751, 8, 17 }, { 1024, 4, 26 }, @@ -81,7 +81,7 @@ unsigned int hdd_table[128][3] = { { 855, 5, 26 }, { 977, 7, 17 }, - { 987, 7, 17 }, /* 048-055 */ + { 987, 7, 17 }, /* 048-055 */ { 1024, 7, 17 }, { 823, 4, 38 }, { 925, 8, 17 }, @@ -90,7 +90,7 @@ unsigned int hdd_table[128][3] = { { 977, 5, 26 }, { 698, 7, 26 }, - { 699, 7, 26 }, /* 056-063 */ + { 699, 7, 26 }, /* 056-063 */ { 940, 8, 17 }, { 615, 8, 26 }, { 1024, 5, 26 }, @@ -99,7 +99,7 @@ unsigned int hdd_table[128][3] = { { 823, 10, 17 }, { 754, 11, 17 }, - { 830, 10, 17 }, /* 064-071 */ + { 830, 10, 17 }, /* 064-071 */ { 925, 9, 17 }, { 1224, 7, 17 }, { 940, 6, 26 }, @@ -107,8 +107,8 @@ unsigned int hdd_table[128][3] = { { 751, 8, 26 }, { 1024, 9, 17 }, { 965, 10, 17 }, - - { 969, 5, 34 }, /* 072-079 */ + + { 969, 5, 34 }, /* 072-079 */ { 980, 10, 17 }, { 960, 5, 35 }, { 918, 11, 17 }, @@ -117,7 +117,7 @@ unsigned int hdd_table[128][3] = { { 1024, 7, 26 }, { 1024, 11, 17 }, - { 940, 8, 26 }, /* 080-087 */ + { 940, 8, 26 }, /* 080-087 */ { 776, 8, 33 }, { 755, 16, 17 }, { 1024, 12, 17 }, @@ -126,7 +126,7 @@ unsigned int hdd_table[128][3] = { { 830, 10, 26 }, { 925, 9, 26 }, - { 960, 9, 26 }, /* 088-095 */ + { 960, 9, 26 }, /* 088-095 */ { 1024, 13, 17 }, { 1224, 11, 17 }, { 900, 15, 17 }, @@ -135,7 +135,7 @@ unsigned int hdd_table[128][3] = { { 918, 15, 17 }, { 1524, 4, 39 }, - { 1024, 9, 26 }, /* 096-103 */ + { 1024, 9, 26 }, /* 096-103 */ { 1024, 14, 17 }, { 965, 10, 26 }, { 980, 10, 26 }, @@ -144,7 +144,7 @@ unsigned int hdd_table[128][3] = { { 1024, 15, 17 }, { 1024, 16, 17 }, - { 1224, 15, 17 }, /* 104-111 */ + { 1224, 15, 17 }, /* 104-111 */ { 755, 16, 26 }, { 903, 8, 46 }, { 984, 10, 34 }, @@ -153,7 +153,7 @@ unsigned int hdd_table[128][3] = { { 1023, 15, 26 }, { 684, 16, 38 }, - { 1930, 4, 62 }, /* 112-119 */ + { 1930, 4, 62 }, /* 112-119 */ { 967, 16, 31 }, { 1013, 10, 63 }, { 1218, 15, 36 }, @@ -162,7 +162,7 @@ unsigned int hdd_table[128][3] = { { 702, 16, 63 }, { 1002, 13, 63 }, - { 854, 16, 63 }, /* 119-127 */ + { 854, 16, 63 }, /* 119-127 */ { 987, 16, 63 }, { 995, 16, 63 }, { 1024, 16, 63 }, @@ -170,4 +170,5 @@ unsigned int hdd_table[128][3] = { { 1120, 16, 59 }, { 1054, 16, 63 }, { 0, 0, 0 } + // clang-format on }; diff --git a/src/disk/minivhd/CMakeLists.txt b/src/disk/minivhd/CMakeLists.txt index a96b871b8..324acf81b 100644 --- a/src/disk/minivhd/CMakeLists.txt +++ b/src/disk/minivhd/CMakeLists.txt @@ -1,18 +1,17 @@ # -# 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. +# 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. +# This file is part of the 86Box distribution. # -# CMake build script. +# CMake build script. # -# Authors: David HrdliÄka, +# Authors: David HrdliÄka, # -# Copyright 2020,2021 David HrdliÄka. +# Copyright 2020,2021 David HrdliÄka. # -add_library(minivhd STATIC cwalk.c libxml2_encoding.c minivhd_convert.c - minivhd_create.c minivhd_io.c minivhd_manage.c minivhd_struct_rw.c - minivhd_util.c) \ No newline at end of file +add_library(minivhd STATIC cwalk.c xml2_encoding.c convert.c + create.c minivhd_io.c manage.c struct_rw.c minivhd_util.c) diff --git a/src/disk/minivhd/CREDITS.md b/src/disk/minivhd/CREDITS.md index c494d4e43..266e9f0e4 100644 --- a/src/disk/minivhd/CREDITS.md +++ b/src/disk/minivhd/CREDITS.md @@ -1,7 +1,7 @@ # Credits -MiniVHD Copyright (c) 2019 Sherman Perry +MiniVHD Copyright 2019-2021 Sherman Perry. -MiniVHD was made possible with the help of the following projects +MiniVHD was made possible with the help of the following projects: ### libxml2 **Project Home:** http://www.xmlsoft.org/ @@ -10,3 +10,8 @@ MiniVHD was made possible with the help of the following projects ### cwalk **Project Home:** https://likle.github.io/cwalk/ **Licence:** MIT (https://github.com/likle/cwalk/blob/master/LICENSE.md) + +### VARCem +The MiniVHD was rewritten into a standalone library (both shared as well +as static) by Fred N. van Kempen for use with the VARCem PC Systems +emulator - see https://www.varcem.com/ for more info. diff --git a/src/disk/minivhd/minivhd_convert.c b/src/disk/minivhd/convert.c similarity index 55% rename from src/disk/minivhd/minivhd_convert.c rename to src/disk/minivhd/convert.c index 1de6f4613..1b7d10c87 100644 --- a/src/disk/minivhd/minivhd_convert.c +++ b/src/disk/minivhd/convert.c @@ -1,28 +1,66 @@ +/* + * MiniVHD Minimalist VHD implementation in C. + * + * This file is part of the MiniVHD Project. + * + * Version: @(#)convert.c 1.0.2 2021/04/16 + * + * Authors: Sherman Perry, + * Fred N. van Kempen, + * + * Copyright 2019-2021 Sherman Perry. + * Copyright 2021 Fred N. van Kempen. + * + * MIT License + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documenta- + * tion files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, + * copy, modify, merge, publish, distribute, sublicense, and/or + * sell copies of the Software, and to permit persons to whom + * the Software is furnished to do so, subject to the following + * conditions: + * + * The above copyright notice and this permission notice shall + * be included in all copies or substantial portions of the + * Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF O R IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ #ifndef _FILE_OFFSET_BITS -#define _FILE_OFFSET_BITS 64 +# define _FILE_OFFSET_BITS 64 #endif #include #include #include #include #include -#include "minivhd_create.h" -#include "minivhd_internal.h" -#include "minivhd_util.h" +#include #include "minivhd.h" +#include "internal.h" -static FILE* mvhd_open_existing_raw_img(const char* utf8_raw_path, MVHDGeom* geom, int* err); -static FILE* mvhd_open_existing_raw_img(const char* utf8_raw_path, MVHDGeom* geom, int* err) { +static FILE* +open_existing_raw_img(const char* utf8_raw_path, MVHDGeom* geom, int* err) +{ + if (geom == NULL) { + *err = MVHD_ERR_INVALID_GEOM; + return NULL; + } + FILE *raw_img = mvhd_fopen(utf8_raw_path, "rb", err); if (raw_img == NULL) { *err = MVHD_ERR_FILE; return NULL; } - if (geom == NULL) { - *err = MVHD_ERR_INVALID_GEOM; - return NULL; - } + mvhd_fseeko64(raw_img, 0, SEEK_END); uint64_t size_bytes = (uint64_t)mvhd_ftello64(raw_img); MVHDGeom new_geom = mvhd_calculate_geometry(size_bytes); @@ -34,44 +72,60 @@ static FILE* mvhd_open_existing_raw_img(const char* utf8_raw_path, MVHDGeom* geo geom->heads = new_geom.heads; geom->spt = new_geom.spt; mvhd_fseeko64(raw_img, 0, SEEK_SET); + return raw_img; } -MVHDMeta* mvhd_convert_to_vhd_fixed(const char* utf8_raw_path, const char* utf8_vhd_path, int* err) { + +MVHDAPI MVHDMeta* +mvhd_convert_to_vhd_fixed(const char* utf8_raw_path, const char* utf8_vhd_path, int* err) +{ MVHDGeom geom; - FILE *raw_img = mvhd_open_existing_raw_img(utf8_raw_path, &geom, err); + + FILE *raw_img = open_existing_raw_img(utf8_raw_path, &geom, err); if (raw_img == NULL) { return NULL; - } + } + uint64_t size_in_bytes = mvhd_calc_size_bytes(&geom); MVHDMeta *vhdm = mvhd_create_fixed_raw(utf8_vhd_path, raw_img, size_in_bytes, &geom, err, NULL); if (vhdm == NULL) { return NULL; } + return vhdm; } -MVHDMeta* mvhd_convert_to_vhd_sparse(const char* utf8_raw_path, const char* utf8_vhd_path, int* err) { + + +MVHDAPI MVHDMeta* +mvhd_convert_to_vhd_sparse(const char* utf8_raw_path, const char* utf8_vhd_path, int* err) +{ MVHDGeom geom; MVHDMeta *vhdm = NULL; - FILE *raw_img = mvhd_open_existing_raw_img(utf8_raw_path, &geom, err); + + FILE *raw_img = open_existing_raw_img(utf8_raw_path, &geom, err); if (raw_img == NULL) { return NULL; } + vhdm = mvhd_create_sparse(utf8_vhd_path, geom, err); if (vhdm == NULL) { goto end; } + uint8_t buff[4096] = {0}; // 8 sectors uint8_t empty_buff[4096] = {0}; int total_sectors = mvhd_calc_size_sectors(&geom); int copy_sect = 0; + for (int i = 0; i < total_sectors; i += 8) { copy_sect = 8; if ((i + 8) >= total_sectors) { copy_sect = total_sectors - i; memset(buff, 0, sizeof buff); } - fread(buff, MVHD_SECTOR_SIZE, copy_sect, raw_img); + (void) !fread(buff, MVHD_SECTOR_SIZE, copy_sect, raw_img); + /* Only write data if there's data to write, to take advantage of the sparse VHD format */ if (memcmp(buff, empty_buff, sizeof buff) != 0) { mvhd_write_sectors(vhdm, i, copy_sect, buff); @@ -79,18 +133,25 @@ MVHDMeta* mvhd_convert_to_vhd_sparse(const char* utf8_raw_path, const char* utf8 } end: fclose(raw_img); + return vhdm; } -FILE* mvhd_convert_to_raw(const char* utf8_vhd_path, const char* utf8_raw_path, int *err) { + + +MVHDAPI FILE* +mvhd_convert_to_raw(const char* utf8_vhd_path, const char* utf8_raw_path, int *err) +{ FILE *raw_img = mvhd_fopen(utf8_raw_path, "wb", err); if (raw_img == NULL) { return NULL; } + MVHDMeta *vhdm = mvhd_open(utf8_vhd_path, true, err); if (vhdm == NULL) { fclose(raw_img); return NULL; } + uint8_t buff[4096] = {0}; // 8 sectors int total_sectors = mvhd_calc_size_sectors((MVHDGeom*)&vhdm->footer.geom); int copy_sect = 0; @@ -104,5 +165,6 @@ FILE* mvhd_convert_to_raw(const char* utf8_vhd_path, const char* utf8_raw_path, } mvhd_close(vhdm); mvhd_fseeko64(raw_img, 0, SEEK_SET); + return raw_img; -} \ No newline at end of file +} diff --git a/src/disk/minivhd/minivhd_create.c b/src/disk/minivhd/create.c similarity index 62% rename from src/disk/minivhd/minivhd_create.c rename to src/disk/minivhd/create.c index c47c7d82d..d06382ef9 100644 --- a/src/disk/minivhd/minivhd_create.c +++ b/src/disk/minivhd/create.c @@ -1,68 +1,105 @@ +/* + * MiniVHD Minimalist VHD implementation in C. + * + * This file is part of the MiniVHD Project. + * + * Version: @(#)create.c 1.0.3 2021/04/16 + * + * Authors: Sherman Perry, + * Fred N. van Kempen, + * + * Copyright 2019-2021 Sherman Perry. + * Copyright 2021 Fred N. van Kempen. + * + * MIT License + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documenta- + * tion files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, + * copy, modify, merge, publish, distribute, sublicense, and/or + * sell copies of the Software, and to permit persons to whom + * the Software is furnished to do so, subject to the following + * conditions: + * + * The above copyright notice and this permission notice shall + * be included in all copies or substantial portions of the + * Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF O R IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ #ifndef _FILE_OFFSET_BITS -#define _FILE_OFFSET_BITS 64 +# define _FILE_OFFSET_BITS 64 #endif #include +#include #include #include #include #include -#include "cwalk.h" -#include "libxml2_encoding.h" -#include "minivhd_internal.h" -#include "minivhd_util.h" -#include "minivhd_struct_rw.h" -#include "minivhd_io.h" -#include "minivhd_create.h" +#include #include "minivhd.h" +#include "internal.h" +#include "cwalk.h" +#include "xml2_encoding.h" + + +static const char MVHD_CONECTIX_COOKIE[] = "conectix"; +static const char MVHD_CREATOR[] = "mVHD"; +static const char MVHD_CREATOR_HOST_OS[] = "Wi2k"; +static const char MVHD_CXSPARSE_COOKIE[] = "cxsparse"; -static void mvhd_gen_footer(MVHDFooter* footer, uint64_t size_in_bytes, MVHDGeom* geom, MVHDType type, uint64_t sparse_header_off); -static void mvhd_gen_sparse_header(MVHDSparseHeader* header, uint32_t num_blks, uint64_t bat_offset, uint32_t block_size_in_sectors); -static int mvhd_gen_par_loc(MVHDSparseHeader* header, - const char* child_path, - const char* par_path, - uint64_t start_offset, - mvhd_utf16* w2ku_path_buff, - mvhd_utf16* w2ru_path_buff, - MVHDError* err); -static MVHDMeta* mvhd_create_sparse_diff(const char* path, const char* par_path, uint64_t size_in_bytes, MVHDGeom* geom, uint32_t block_size_in_sectors, int* err); /** * \brief Populate a VHD footer - * + * * \param [in] footer to populate * \param [in] size_in_bytes is the total size of the virtual hard disk in bytes * \param [in] geom to use * \param [in] type of HVD that is being created * \param [in] sparse_header_off, an absolute file offset to the sparse header. Not used for fixed VHD images */ -static void mvhd_gen_footer(MVHDFooter* footer, uint64_t size_in_bytes, MVHDGeom* geom, MVHDType type, uint64_t sparse_header_off) { - memcpy(footer->cookie, "conectix", sizeof footer->cookie); +static void +gen_footer(MVHDFooter* footer, uint64_t size_in_bytes, MVHDGeom* geom, MVHDType type, uint64_t sparse_header_off) +{ + memcpy(footer->cookie, MVHD_CONECTIX_COOKIE, sizeof footer->cookie); footer->features = 0x00000002; footer->fi_fmt_vers = 0x00010000; footer->data_offset = (type == MVHD_TYPE_DIFF || type == MVHD_TYPE_DYNAMIC) ? sparse_header_off : 0xffffffffffffffff; footer->timestamp = vhd_calc_timestamp(); - memcpy(footer->cr_app, "mvhd", sizeof footer->cr_app); + memcpy(footer->cr_app, MVHD_CREATOR, sizeof footer->cr_app); footer->cr_vers = 0x000e0000; - memcpy(footer->cr_host_os, "Wi2k", sizeof footer->cr_host_os); + memcpy(footer->cr_host_os, MVHD_CREATOR_HOST_OS, sizeof footer->cr_host_os); footer->orig_sz = footer->curr_sz = size_in_bytes; footer->geom.cyl = geom->cyl; footer->geom.heads = geom->heads; footer->geom.spt = geom->spt; footer->disk_type = type; + mvhd_generate_uuid(footer->uuid); + footer->checksum = mvhd_gen_footer_checksum(footer); } + /** * \brief Populate a VHD sparse header - * + * * \param [in] header for sparse and differencing images * \param [in] num_blks is the number of data blocks that the image contains * \param [in] bat_offset is the absolute file offset for start of the Block Allocation Table * \param [in] block_size_in_sectors is the block size in sectors. */ -static void mvhd_gen_sparse_header(MVHDSparseHeader* header, uint32_t num_blks, uint64_t bat_offset, uint32_t block_size_in_sectors) { - memcpy(header->cookie, "cxsparse", sizeof header->cookie); +static void +gen_sparse_header(MVHDSparseHeader* header, uint32_t num_blks, uint64_t bat_offset, uint32_t block_size_in_sectors) +{ + memcpy(header->cookie, MVHD_CXSPARSE_COOKIE, sizeof header->cookie); header->data_offset = 0xffffffffffffffff; header->bat_offset = bat_offset; header->head_vers = 0x00010000; @@ -71,9 +108,10 @@ static void mvhd_gen_sparse_header(MVHDSparseHeader* header, uint32_t num_blks, header->checksum = mvhd_gen_sparse_checksum(header); } + /** * \brief Generate parent locators for differencing VHD images - * + * * \param [in] header the sparse header to populate with parent locator entries * \param [in] child_path is the full path to the VHD being created * \param [in] par_path is the full path to the parent image @@ -81,25 +119,25 @@ static void mvhd_gen_sparse_header(MVHDSparseHeader* header, uint32_t num_blks, * \param [out] w2ku_path_buff is a buffer containing the full path to the parent, encoded as UTF16-LE * \param [out] w2ru_path_buff is a buffer containing the relative path to the parent, encoded as UTF16-LE * \param [out] err indicates what error occurred, if any - * + * * \retval 0 if success * \retval < 0 if an error occurrs. Check value of *err for actual error */ -static int mvhd_gen_par_loc(MVHDSparseHeader* header, - const char* child_path, - const char* par_path, - uint64_t start_offset, - mvhd_utf16* w2ku_path_buff, - mvhd_utf16* w2ru_path_buff, - MVHDError* err) { +static int +gen_par_loc(MVHDSparseHeader* header, const char* child_path, + const char* par_path, uint64_t start_offset, + mvhd_utf16* w2ku_path_buff, mvhd_utf16* w2ru_path_buff, + MVHDError* err) +{ /* Get our paths to store in the differencing VHD. We want both the absolute path to the parent, as well as the relative path from the child VHD */ int rv = 0; char* par_filename; size_t par_fn_len; - char rel_path[MVHD_MAX_PATH_BYTES] = {0}; + char rel_path[MVHD_MAX_PATH_BYTES] = {0}; char child_dir[MVHD_MAX_PATH_BYTES] = {0}; size_t child_dir_len; + if (strlen(child_path) < sizeof child_dir) { strcpy(child_dir, child_path); } else { @@ -107,6 +145,7 @@ static int mvhd_gen_par_loc(MVHDSparseHeader* header, rv = -1; goto end; } + cwk_path_get_basename(par_path, (const char**)&par_filename, &par_fn_len); cwk_path_get_dirname(child_dir, &child_dir_len); child_dir[child_dir_len] = '\0'; @@ -115,18 +154,19 @@ static int mvhd_gen_par_loc(MVHDSparseHeader* header, *err = MVHD_ERR_PATH_LEN; rv = -1; goto end; - } + } + /* We have our paths, now store the parent filename directly in the sparse header. */ - int outlen = sizeof header->par_utf16_name; + int outlen = sizeof header->par_utf16_name; int utf_ret; - utf_ret = UTF8ToUTF16BE((unsigned char*)header->par_utf16_name, &outlen, (const unsigned char*)par_filename, (int*)&par_fn_len); + utf_ret = UTF8ToUTF16BE((unsigned char*)header->par_utf16_name, &outlen, (const unsigned char*)par_filename, (int*)&par_fn_len); if (utf_ret < 0) { mvhd_set_encoding_err(utf_ret, (int*)err); rv = -1; goto end; } - - /* And encode the paths to UTF16-LE */ + + /* And encode the paths to UTF16-LE */ size_t par_path_len = strlen(par_path); outlen = sizeof *w2ku_path_buff * MVHD_MAX_PATH_CHARS; utf_ret = UTF8ToUTF16LE((unsigned char*)w2ku_path_buff, &outlen, (const unsigned char*)par_path, (int*)&par_path_len); @@ -136,7 +176,7 @@ static int mvhd_gen_par_loc(MVHDSparseHeader* header, goto end; } int w2ku_len = utf_ret; - outlen = sizeof *w2ru_path_buff * MVHD_MAX_PATH_CHARS; + outlen = sizeof *w2ru_path_buff * MVHD_MAX_PATH_CHARS; utf_ret = UTF8ToUTF16LE((unsigned char*)w2ru_path_buff, &outlen, (const unsigned char*)rel_path, (int*)&rel_len); if (utf_ret < 0) { mvhd_set_encoding_err(utf_ret, (int*)err); @@ -144,16 +184,17 @@ static int mvhd_gen_par_loc(MVHDSparseHeader* header, goto end; } int w2ru_len = utf_ret; - /** + + /** * Finally populate the parent locaters in the sparse header. * This is the information needed to find the paths saved elsewhere - * in the VHD image + * in the VHD image */ /* Note about the plat_data_space field: The VHD spec says this field stores the number of sectors needed to store the locator path. - * However, Hyper-V and VPC store the number of bytes, not the number of sectors, and will refuse to open VHDs which have the + * However, Hyper-V and VPC store the number of bytes, not the number of sectors, and will refuse to open VHDs which have the * number of sectors in this field. - * See https://stackoverflow.com/questions/40760181/mistake-in-virtual-hard-disk-image-format-specification + * See https://stackoverflow.com/questions/40760181/mistake-in-virtual-hard-disk-image-format-specification */ header->par_loc_entry[0].plat_code = MVHD_DIF_LOC_W2KU; header->par_loc_entry[0].plat_data_len = (uint32_t)w2ku_len; @@ -169,40 +210,53 @@ end: return rv; } -MVHDMeta* mvhd_create_fixed(const char* path, MVHDGeom geom, int* err, mvhd_progress_callback progress_callback) { + +MVHDAPI MVHDMeta* +mvhd_create_fixed(const char* path, MVHDGeom geom, int* err, mvhd_progress_callback progress_callback) +{ uint64_t size_in_bytes = mvhd_calc_size_bytes(&geom); + return mvhd_create_fixed_raw(path, NULL, size_in_bytes, &geom, err, progress_callback); } + /** * \brief internal function that implements public mvhd_create_fixed() functionality - * + * * Contains one more parameter than the public function, to allow using an existing * raw disk image as the data source for the new fixed VHD. - * + * * \param [in] raw_image file handle to a raw disk image to populate VHD */ -MVHDMeta* mvhd_create_fixed_raw(const char* path, FILE* raw_img, uint64_t size_in_bytes, MVHDGeom* geom, int* err, mvhd_progress_callback progress_callback) { +MVHDMeta* +mvhd_create_fixed_raw(const char* path, FILE* raw_img, uint64_t size_in_bytes, MVHDGeom* geom, int* err, mvhd_progress_callback progress_callback) +{ uint8_t img_data[MVHD_SECTOR_SIZE] = {0}; uint8_t footer_buff[MVHD_FOOTER_SIZE] = {0}; + + if (geom == NULL || (geom->cyl == 0 || geom->heads == 0 || geom->spt == 0)) { + *err = MVHD_ERR_INVALID_GEOM; + return NULL; + } + MVHDMeta* vhdm = calloc(1, sizeof *vhdm); if (vhdm == NULL) { *err = MVHD_ERR_MEM; goto end; } - if (geom == NULL || (geom->cyl == 0 || geom->heads == 0 || geom->spt == 0)) { - *err = MVHD_ERR_INVALID_GEOM; + + FILE* fp = mvhd_fopen(path, "wb+", err); + if (fp == NULL) { goto cleanup_vhdm; } - FILE* f = mvhd_fopen(path, "wb+", err); - if (f == NULL) { - goto cleanup_vhdm; - } - mvhd_fseeko64(f, 0, SEEK_SET); + mvhd_fseeko64(fp, 0, SEEK_SET); + uint32_t size_sectors = (uint32_t)(size_in_bytes / MVHD_SECTOR_SIZE); uint32_t s; + if (progress_callback) progress_callback(0, size_sectors); + if (raw_img != NULL) { mvhd_fseeko64(raw_img, 0, SEEK_END); uint64_t raw_size = (uint64_t)mvhd_ftello64(raw_img); @@ -211,26 +265,26 @@ MVHDMeta* mvhd_create_fixed_raw(const char* path, FILE* raw_img, uint64_t size_i *err = MVHD_ERR_CONV_SIZE; goto cleanup_vhdm; } - mvhd_gen_footer(&vhdm->footer, raw_size, geom, MVHD_TYPE_FIXED, 0); + gen_footer(&vhdm->footer, raw_size, geom, MVHD_TYPE_FIXED, 0); mvhd_fseeko64(raw_img, 0, SEEK_SET); - for (s = 0; s < size_sectors; s++) { - fread(img_data, sizeof img_data, 1, raw_img); - fwrite(img_data, sizeof img_data, 1, f); + for (s = 0; s < size_sectors; s++) { + (void) !fread(img_data, sizeof img_data, 1, raw_img); + fwrite(img_data, sizeof img_data, 1, fp); if (progress_callback) progress_callback(s + 1, size_sectors); } } else { - mvhd_gen_footer(&vhdm->footer, size_in_bytes, geom, MVHD_TYPE_FIXED, 0); - for (s = 0; s < size_sectors; s++) { - fwrite(img_data, sizeof img_data, 1, f); + gen_footer(&vhdm->footer, size_in_bytes, geom, MVHD_TYPE_FIXED, 0); + for (s = 0; s < size_sectors; s++) { + fwrite(img_data, sizeof img_data, 1, fp); if (progress_callback) progress_callback(s + 1, size_sectors); } } mvhd_footer_to_buffer(&vhdm->footer, footer_buff); - fwrite(footer_buff, sizeof footer_buff, 1, f); - fclose(f); - f = NULL; + fwrite(footer_buff, sizeof footer_buff, 1, fp); + fclose(fp); + fp = NULL; free(vhdm); vhdm = mvhd_open(path, false, err); goto end; @@ -238,23 +292,27 @@ MVHDMeta* mvhd_create_fixed_raw(const char* path, FILE* raw_img, uint64_t size_i cleanup_vhdm: free(vhdm); vhdm = NULL; + end: return vhdm; } + /** * \brief Create sparse or differencing VHD image. - * + * * \param [in] path is the absolute path to the VHD file to create * \param [in] par_path is the absolute path to a parent image. If NULL, a sparse image is created, otherwise create a differencing image * \param [in] size_in_bytes is the total size in bytes of the virtual hard disk image * \param [in] geom is the HDD geometry of the image to create. Determines final image size * \param [in] block_size_in_sectors is the block size in sectors * \param [out] err indicates what error occurred, if any - * + * * \return NULL if an error occurrs. Check value of *err for actual error. Otherwise returns pointer to a MVHDMeta struct */ -static MVHDMeta* mvhd_create_sparse_diff(const char* path, const char* par_path, uint64_t size_in_bytes, MVHDGeom* geom, uint32_t block_size_in_sectors, int* err) { +static MVHDMeta* +create_sparse_diff(const char* path, const char* par_path, uint64_t size_in_bytes, MVHDGeom* geom, uint32_t block_size_in_sectors, int* err) +{ uint8_t footer_buff[MVHD_FOOTER_SIZE] = {0}; uint8_t sparse_buff[MVHD_SPARSE_SIZE] = {0}; uint8_t bat_sect[MVHD_SECTOR_SIZE]; @@ -265,6 +323,7 @@ static MVHDMeta* mvhd_create_sparse_diff(const char* path, const char* par_path, mvhd_utf16* w2ku_path_buff = NULL; mvhd_utf16* w2ru_path_buff = NULL; uint32_t par_mod_timestamp = 0; + if (par_path != NULL) { par_mod_timestamp = mvhd_file_mod_timestamp(par_path, err); if (*err != 0) { @@ -275,6 +334,7 @@ static MVHDMeta* mvhd_create_sparse_diff(const char* path, const char* par_path, goto end; } } + vhdm = calloc(1, sizeof *vhdm); if (vhdm == NULL) { *err = MVHD_ERR_MEM; @@ -290,27 +350,30 @@ static MVHDMeta* mvhd_create_sparse_diff(const char* path, const char* par_path, } else if (geom == NULL || (geom->cyl == 0 || geom->heads == 0 || geom->spt == 0)) { *err = MVHD_ERR_INVALID_GEOM; goto cleanup_vhdm; - } - - FILE* f = mvhd_fopen(path, "wb+", err); - if (f == NULL) { + } + + FILE* fp = mvhd_fopen(path, "wb+", err); + if (fp == NULL) { goto cleanup_vhdm; } - mvhd_fseeko64(f, 0, SEEK_SET); + mvhd_fseeko64(fp, 0, SEEK_SET); + /* Note, the sparse header follows the footer copy at the beginning of the file */ if (par_path == NULL) { - mvhd_gen_footer(&vhdm->footer, size_in_bytes, geom, MVHD_TYPE_DYNAMIC, MVHD_FOOTER_SIZE); + gen_footer(&vhdm->footer, size_in_bytes, geom, MVHD_TYPE_DYNAMIC, MVHD_FOOTER_SIZE); } else { - mvhd_gen_footer(&vhdm->footer, size_in_bytes, geom, MVHD_TYPE_DIFF, MVHD_FOOTER_SIZE); + gen_footer(&vhdm->footer, size_in_bytes, geom, MVHD_TYPE_DIFF, MVHD_FOOTER_SIZE); } mvhd_footer_to_buffer(&vhdm->footer, footer_buff); + /* As mentioned, start with a copy of the footer */ - fwrite(footer_buff, sizeof footer_buff, 1, f); + fwrite(footer_buff, sizeof footer_buff, 1, fp); + /** * Calculate the number of (2MB or 512KB) data blocks required to store the entire - * contents of the disk image, followed by the number of sectors the + * contents of the disk image, followed by the number of sectors the * BAT occupies in the image. Note, the BAT is sector aligned, and is padded - * to the next sector boundary + * to the next sector boundary * */ uint32_t size_in_sectors = (uint32_t)(size_in_bytes / MVHD_SECTOR_SIZE); uint32_t num_blks = size_in_sectors / block_size_in_sectors; @@ -323,10 +386,10 @@ static MVHDMeta* mvhd_create_sparse_diff(const char* path, const char* par_path, } /* Storing the BAT directly following the footer and header */ uint64_t bat_offset = MVHD_FOOTER_SIZE + MVHD_SPARSE_SIZE; - uint64_t par_loc_offset = 0; + uint64_t par_loc_offset = 0; /** - * If creating a differencing VHD, populate the sparse header with additional + * If creating a differencing VHD, populate the sparse header with additional * data about the parent image, and where to find it, and it's last modified timestamp * */ if (par_vhdm != NULL) { @@ -337,57 +400,65 @@ static MVHDMeta* mvhd_create_sparse_diff(const char* path, const char* par_path, */ w2ku_path_buff = calloc(MVHD_MAX_PATH_CHARS, sizeof * w2ku_path_buff); if (w2ku_path_buff == NULL) { - *err = MVHD_ERR_MEM; + *err = MVHD_ERR_MEM; goto end; } w2ru_path_buff = calloc(MVHD_MAX_PATH_CHARS, sizeof * w2ru_path_buff); if (w2ru_path_buff == NULL) { - *err = MVHD_ERR_MEM; + *err = MVHD_ERR_MEM; goto end; } memcpy(vhdm->sparse.par_uuid, par_vhdm->footer.uuid, sizeof vhdm->sparse.par_uuid); par_loc_offset = bat_offset + ((uint64_t)num_bat_sect * MVHD_SECTOR_SIZE) + (5 * MVHD_SECTOR_SIZE); - if (mvhd_gen_par_loc(&vhdm->sparse, path, par_path, par_loc_offset, w2ku_path_buff, w2ru_path_buff, (MVHDError*)err) < 0) { + if (gen_par_loc(&vhdm->sparse, path, par_path, par_loc_offset, w2ku_path_buff, w2ru_path_buff, (MVHDError*)err) < 0) { goto cleanup_vhdm; } vhdm->sparse.par_timestamp = par_mod_timestamp; } - mvhd_gen_sparse_header(&vhdm->sparse, num_blks, bat_offset, block_size_in_sectors); + gen_sparse_header(&vhdm->sparse, num_blks, bat_offset, block_size_in_sectors); mvhd_header_to_buffer(&vhdm->sparse, sparse_buff); - fwrite(sparse_buff, sizeof sparse_buff, 1, f); + fwrite(sparse_buff, sizeof sparse_buff, 1, fp); + /* The BAT sectors need to be filled with 0xffffffff */ - for (uint32_t i = 0; i < num_bat_sect; i++) { - fwrite(bat_sect, sizeof bat_sect, 1, f); + for (uint32_t k = 0; k < num_bat_sect; k++) { + fwrite(bat_sect, sizeof bat_sect, 1, fp); } - mvhd_write_empty_sectors(f, 5); + mvhd_write_empty_sectors(fp, 5); + /** * If creating a differencing VHD, the paths to the parent image need to be written - * tp the file. Both absolute and relative paths are written + * tp the file. Both absolute and relative paths are written * */ if (par_vhdm != NULL) { - uint64_t curr_pos = (uint64_t)mvhd_ftello64(f); + uint64_t curr_pos = (uint64_t)mvhd_ftello64(fp); + /* Double check my sums... */ assert(curr_pos == par_loc_offset); + /* Fill the space required for location data with zero */ uint8_t empty_sect[MVHD_SECTOR_SIZE] = {0}; + for (int i = 0; i < 2; i++) { for (uint32_t j = 0; j < (vhdm->sparse.par_loc_entry[i].plat_data_space / MVHD_SECTOR_SIZE); j++) { - fwrite(empty_sect, sizeof empty_sect, 1, f); + fwrite(empty_sect, sizeof empty_sect, 1, fp); } } + /* Now write the location entries */ - mvhd_fseeko64(f, vhdm->sparse.par_loc_entry[0].plat_data_offset, SEEK_SET); - fwrite(w2ku_path_buff, vhdm->sparse.par_loc_entry[0].plat_data_len, 1, f); - mvhd_fseeko64(f, vhdm->sparse.par_loc_entry[1].plat_data_offset, SEEK_SET); - fwrite(w2ru_path_buff, vhdm->sparse.par_loc_entry[1].plat_data_len, 1, f); + mvhd_fseeko64(fp, vhdm->sparse.par_loc_entry[0].plat_data_offset, SEEK_SET); + fwrite(w2ku_path_buff, vhdm->sparse.par_loc_entry[0].plat_data_len, 1, fp); + mvhd_fseeko64(fp, vhdm->sparse.par_loc_entry[1].plat_data_offset, SEEK_SET); + fwrite(w2ru_path_buff, vhdm->sparse.par_loc_entry[1].plat_data_len, 1, fp); + /* and reset the file position to continue */ - mvhd_fseeko64(f, vhdm->sparse.par_loc_entry[1].plat_data_offset + vhdm->sparse.par_loc_entry[1].plat_data_space, SEEK_SET); - mvhd_write_empty_sectors(f, 5); + mvhd_fseeko64(fp, vhdm->sparse.par_loc_entry[1].plat_data_offset + vhdm->sparse.par_loc_entry[1].plat_data_space, SEEK_SET); + mvhd_write_empty_sectors(fp, 5); } + /* And finish with the footer */ - fwrite(footer_buff, sizeof footer_buff, 1, f); - fclose(f); - f = NULL; + fwrite(footer_buff, sizeof footer_buff, 1, fp); + fclose(fp); + fp = NULL; free(vhdm); vhdm = mvhd_open(path, false, err); goto end; @@ -395,91 +466,112 @@ static MVHDMeta* mvhd_create_sparse_diff(const char* path, const char* par_path, cleanup_vhdm: free(vhdm); vhdm = NULL; + cleanup_par_vhdm: if (par_vhdm != NULL) { mvhd_close(par_vhdm); } -end: - free(w2ku_path_buff); - free(w2ru_path_buff); + +end: + free(w2ku_path_buff); + free(w2ru_path_buff); + return vhdm; } -MVHDMeta* mvhd_create_sparse(const char* path, MVHDGeom geom, int* err) { + +MVHDAPI MVHDMeta* +mvhd_create_sparse(const char* path, MVHDGeom geom, int* err) +{ uint64_t size_in_bytes = mvhd_calc_size_bytes(&geom); - return mvhd_create_sparse_diff(path, NULL, size_in_bytes, &geom, MVHD_BLOCK_LARGE, err); + + return create_sparse_diff(path, NULL, size_in_bytes, &geom, MVHD_BLOCK_LARGE, err); } -MVHDMeta* mvhd_create_diff(const char* path, const char* par_path, int* err) { - return mvhd_create_sparse_diff(path, par_path, 0, NULL, MVHD_BLOCK_LARGE, err); + +MVHDAPI MVHDMeta* +mvhd_create_diff(const char* path, const char* par_path, int* err) +{ + return create_sparse_diff(path, par_path, 0, NULL, MVHD_BLOCK_LARGE, err); } -MVHDMeta* mvhd_create_ex(MVHDCreationOptions options, int* err) { - uint32_t geom_sector_size; - switch (options.type) - { - case MVHD_TYPE_FIXED: - case MVHD_TYPE_DYNAMIC: - geom_sector_size = mvhd_calc_size_sectors(&(options.geometry)); - if ((options.size_in_bytes > 0 && (options.size_in_bytes % MVHD_SECTOR_SIZE) > 0) - || (options.size_in_bytes > MVHD_MAX_SIZE_IN_BYTES) - || (options.size_in_bytes == 0 && geom_sector_size == 0)) - { - *err = MVHD_ERR_INVALID_SIZE; - return NULL; - } - if (options.size_in_bytes > 0 && ((uint64_t)geom_sector_size * MVHD_SECTOR_SIZE) > options.size_in_bytes) - { - *err = MVHD_ERR_INVALID_GEOM; - return NULL; - } +MVHDAPI MVHDMeta* +mvhd_create_ex(MVHDCreationOptions options, int* err) +{ + uint32_t geom_sector_size; - if (options.size_in_bytes == 0) - options.size_in_bytes = (uint64_t)geom_sector_size * MVHD_SECTOR_SIZE; + switch (options.type) { + case MVHD_TYPE_FIXED: + case MVHD_TYPE_DYNAMIC: + geom_sector_size = mvhd_calc_size_sectors(&(options.geometry)); + if ((options.size_in_bytes > 0 && (options.size_in_bytes % MVHD_SECTOR_SIZE) > 0) + || (options.size_in_bytes > MVHD_MAX_SIZE_IN_BYTES) + || (options.size_in_bytes == 0 && geom_sector_size == 0)) { + *err = MVHD_ERR_INVALID_SIZE; + return NULL; + } - if (geom_sector_size == 0) - options.geometry = mvhd_calculate_geometry(options.size_in_bytes); - break; - case MVHD_TYPE_DIFF: - if (options.parent_path == NULL) - { - *err = MVHD_ERR_FILE; + if (options.size_in_bytes > 0 && ((uint64_t)geom_sector_size * MVHD_SECTOR_SIZE) > options.size_in_bytes) { + *err = MVHD_ERR_INVALID_GEOM; + return NULL; + } + + if (options.size_in_bytes == 0) + options.size_in_bytes = (uint64_t)geom_sector_size * MVHD_SECTOR_SIZE; + + if (geom_sector_size == 0) + options.geometry = mvhd_calculate_geometry(options.size_in_bytes); + break; + + case MVHD_TYPE_DIFF: + if (options.parent_path == NULL) { + *err = MVHD_ERR_FILE; + return NULL; + } + break; + + default: + *err = MVHD_ERR_TYPE; return NULL; - } - break; - default: - *err = MVHD_ERR_TYPE; - return NULL; } - if (options.path == NULL) - { + if (options.path == NULL) { *err = MVHD_ERR_FILE; return NULL; } - if (options.type != MVHD_TYPE_FIXED) - { + if (options.type != MVHD_TYPE_FIXED) { if (options.block_size_in_sectors == MVHD_BLOCK_DEFAULT) options.block_size_in_sectors = MVHD_BLOCK_LARGE; - if (options.block_size_in_sectors != MVHD_BLOCK_LARGE && options.block_size_in_sectors != MVHD_BLOCK_SMALL) - { + if (options.block_size_in_sectors != MVHD_BLOCK_LARGE && options.block_size_in_sectors != MVHD_BLOCK_SMALL) { *err = MVHD_ERR_INVALID_BLOCK_SIZE; return NULL; } } - switch (options.type) - { - case MVHD_TYPE_FIXED: - return mvhd_create_fixed_raw(options.path, NULL, options.size_in_bytes, &(options.geometry), err, options.progress_callback); - case MVHD_TYPE_DYNAMIC: - return mvhd_create_sparse_diff(options.path, NULL, options.size_in_bytes, &(options.geometry), options.block_size_in_sectors, err); - case MVHD_TYPE_DIFF: - return mvhd_create_sparse_diff(options.path, options.parent_path, 0, NULL, options.block_size_in_sectors, err); + switch (options.type) { + case MVHD_TYPE_FIXED: + return mvhd_create_fixed_raw(options.path, NULL, options.size_in_bytes, &(options.geometry), err, options.progress_callback); + + case MVHD_TYPE_DYNAMIC: + return create_sparse_diff(options.path, NULL, options.size_in_bytes, &(options.geometry), options.block_size_in_sectors, err); + + case MVHD_TYPE_DIFF: + return create_sparse_diff(options.path, options.parent_path, 0, NULL, options.block_size_in_sectors, err); } return NULL; /* Make the compiler happy */ -} \ No newline at end of file +} + + +bool +mvhd_is_conectix_str(const void* buffer) +{ + if (strncmp(buffer, MVHD_CONECTIX_COOKIE, strlen(MVHD_CONECTIX_COOKIE)) == 0) { + return true; + } + + return false; +} diff --git a/src/disk/minivhd/cwalk.c b/src/disk/minivhd/cwalk.c index f0c48427c..02964af25 100644 --- a/src/disk/minivhd/cwalk.c +++ b/src/disk/minivhd/cwalk.c @@ -1,12 +1,49 @@ +/* + * libCWALK Path library for C/C++ + * + * Version: @(#)cwalk.c 1.0.2 2021/03/16 + * + * Authors: Sherman Perry, + * Leonard Iklé, + * + * Copyright 2019-2021 Sherman Perry. + * Copyright 2020 Leonard Iklé. + * + * MIT License + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documenta- + * tion files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, + * copy, modify, merge, publish, distribute, sublicense, and/or + * sell copies of the Software, and to permit persons to whom + * the Software is furnished to do so, subject to the following + * conditions: + * + * The above copyright notice and this permission notice shall + * be included in all copies or substantial portions of the + * Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF O R IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ #ifndef _FILE_OFFSET_BITS -#define _FILE_OFFSET_BITS 64 +# define _FILE_OFFSET_BITS 64 #endif #include #include +#include #include #include #include #include "cwalk.h" + + /** * We try to default to a different path style depending on the operating * system. So this should detect whether we should use windows or unix paths. diff --git a/src/disk/minivhd/cwalk.h b/src/disk/minivhd/cwalk.h index baa5d432d..380f6fa2c 100644 --- a/src/disk/minivhd/cwalk.h +++ b/src/disk/minivhd/cwalk.h @@ -1,10 +1,40 @@ -#pragma once - +/* + * libCWALK path library for C/C++ + * + * Version: @(#)cwalk.h 1.0.3 2021/03/22 + * + * Authors: Sherman Perry, + * Leonard Iklé, + * + * Copyright 2019-2021 Sherman Perry. + * Copyright 2020 Leonard Iklé. + * + * MIT License + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documenta- + * tion files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, + * copy, modify, merge, publish, distribute, sublicense, and/or + * sell copies of the Software, and to permit persons to whom + * the Software is furnished to do so, subject to the following + * conditions: + * + * The above copyright notice and this permission notice shall + * be included in all copies or substantial portions of the + * Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF O R IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ #ifndef CWK_LIBRARY_H -#define CWK_LIBRARY_H +# define CWK_LIBRARY_H -#include -#include /** * A segment represents a single component of a path. For instance, on linux a @@ -45,6 +75,11 @@ enum cwk_path_style CWK_STYLE_UNIX }; + +#ifdef __cplusplus +extern "C" { +#endif + /** * @brief Generates an absolute path based on a base. * @@ -454,4 +489,9 @@ void cwk_path_set_style(enum cwk_path_style style); */ enum cwk_path_style cwk_path_get_style(void); +#ifdef __cplusplus +} #endif + + +#endif /*CWK_LIBRARY_H*/ diff --git a/src/disk/minivhd/internal.h b/src/disk/minivhd/internal.h new file mode 100644 index 000000000..d3f930110 --- /dev/null +++ b/src/disk/minivhd/internal.h @@ -0,0 +1,429 @@ +/* + * MiniVHD Minimalist VHD implementation in C. + * + * This file is part of the MiniVHD Project. + * + * Internal definitions. + * + * Version: @(#)internal.h 1.0.1 2021/03/15 + * + * Author: Sherman Perry, + * + * Copyright 2019-2021 Sherman Perry. + * + * MIT License + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documenta- + * tion files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, + * copy, modify, merge, publish, distribute, sublicense, and/or + * sell copies of the Software, and to permit persons to whom + * the Software is furnished to do so, subject to the following + * conditions: + * + * The above copyright notice and this permission notice shall + * be included in all copies or substantial portions of the + * Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF O R IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ +#ifndef MINIVHD_INTERNAL_H +# define MINIVHD_INTERNAL_H + + +#define MVHD_FOOTER_SIZE 512 +#define MVHD_SPARSE_SIZE 1024 + +#define MVHD_SECTOR_SIZE 512 +#define MVHD_BAT_ENT_PER_SECT 128 + +#define MVHD_MAX_SIZE_IN_BYTES 0x1fe00000000 + +#define MVHD_SPARSE_BLK 0xffffffff + +/* For simplicity, we don't handle paths longer than this + * Note, this is the max path in characters, as that is what + * Windows uses + */ +#define MVHD_MAX_PATH_CHARS 260 +#define MVHD_MAX_PATH_BYTES 1040 + +#define MVHD_DIF_LOC_W2RU 0x57327275 +#define MVHD_DIF_LOC_W2KU 0x57326B75 + +#define MVHD_START_TS 946684800 + + +typedef struct MVHDSectorBitmap { + uint8_t* curr_bitmap; + int sector_count; + int curr_block; +} MVHDSectorBitmap; + +typedef struct MVHDFooter { + uint8_t cookie[8]; + uint32_t features; + uint32_t fi_fmt_vers; + uint64_t data_offset; + uint32_t timestamp; + uint8_t cr_app[4]; + uint32_t cr_vers; + uint8_t cr_host_os[4]; + uint64_t orig_sz; + uint64_t curr_sz; + struct { + uint16_t cyl; + uint8_t heads; + uint8_t spt; + } geom; + uint32_t disk_type; + uint32_t checksum; + uint8_t uuid[16]; + uint8_t saved_st; + uint8_t reserved[427]; +} MVHDFooter; + +typedef struct MVHDSparseHeader { + uint8_t cookie[8]; + uint64_t data_offset; + uint64_t bat_offset; + uint32_t head_vers; + uint32_t max_bat_ent; + uint32_t block_sz; + uint32_t checksum; + uint8_t par_uuid[16]; + uint32_t par_timestamp; + uint32_t reserved_1; + uint8_t par_utf16_name[512]; + struct { + uint32_t plat_code; + uint32_t plat_data_space; + uint32_t plat_data_len; + uint32_t reserved; + uint64_t plat_data_offset; + } par_loc_entry[8]; + uint8_t reserved_2[256]; +} MVHDSparseHeader; + +struct MVHDMeta { + FILE* f; + bool readonly; + char filename[MVHD_MAX_PATH_BYTES]; + struct MVHDMeta* parent; + MVHDFooter footer; + MVHDSparseHeader sparse; + uint32_t* block_offset; + int sect_per_block; + MVHDSectorBitmap bitmap; + int (*read_sectors)(struct MVHDMeta*, uint32_t, int, void*); + int (*write_sectors)(struct MVHDMeta*, uint32_t, int, void*); + struct { + uint8_t* zero_data; + int sector_count; + } format_buffer; +}; + + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * Functions to deal with endian issues + */ +uint16_t mvhd_from_be16(uint16_t val); +uint32_t mvhd_from_be32(uint32_t val); +uint64_t mvhd_from_be64(uint64_t val); +uint16_t mvhd_to_be16(uint16_t val); +uint32_t mvhd_to_be32(uint32_t val); +uint64_t mvhd_to_be64(uint64_t val); + +/** + * \brief Check if provided buffer begins with the string "conectix" + * + * \param [in] buffer The buffer to compare. Must be at least 8 bytes in length + * + * \return true if the buffer begins with "conectix" + * \return false if the buffer does not begin with "conectix" + */ +bool mvhd_is_conectix_str(const void* buffer); + +/** + * \brief Generate a raw 16 byte UUID + * + * \param [out] uuid A 16 byte buffer in which the generated UUID will be stored to + */ +void mvhd_generate_uuid(uint8_t *uuid); + +/** + * \brief Calculate a VHD formatted timestamp from the current time + */ +uint32_t vhd_calc_timestamp(void); + +/** + * \brief Convert an epoch timestamp to a VHD timestamp + * + * \param [in] ts epoch timestamp to convert. + * + * \return The adjusted timestamp, or 0 if the input timestamp is + * earlier that 1 Janurary 2000 + */ +uint32_t mvhd_epoch_to_vhd_ts(time_t ts); + +/** + * \brief Return the created time from a VHD image + * + * \param [in] vhdm Pointer to the MiniVHD metadata structure + * + * \return The created time, as a Unix timestamp + */ +time_t vhd_get_created_time(struct MVHDMeta *vhdm); + +/** + * \brief Cross platform, unicode filepath opening + * + * This function accounts for the fact that fopen() handles file paths differently compared to other + * operating systems. Windows version of fopen() will not handle multi byte encoded text like UTF-8. + * + * Unicode filepath support on Windows requires using the _wfopen() function, which expects UTF-16LE + * encoded path and modestring. + * + * \param [in] path The filepath to open as a UTF-8 string + * \param [in] mode The mode string to use (eg: "rb+"") + * \param [out] err The error value, if an error occurrs + * + * \return a FILE pointer if successful, NULL otherwise. If NULL, check the value of err + */ +FILE* mvhd_fopen(const char* path, const char* mode, int* err); + +void mvhd_set_encoding_err(int encoding_retval, int* err); + +/** + * \brief Generate VHD footer checksum + * + * \param [in] vhdm MiniVHD data structure + */ +uint32_t mvhd_gen_footer_checksum(MVHDFooter* footer); + +/** + * \brief Generate VHD sparse header checksum + * + * \param [in] vhdm MiniVHD data structure + */ +uint32_t mvhd_gen_sparse_checksum(MVHDSparseHeader* header); + +uint32_t mvhd_crc32_for_byte(uint32_t r); + +/** + * \brief Get current position in file stream + * + * This is a portable version of the POSIX ftello64(). * + */ +int64_t mvhd_ftello64(FILE* stream); + +/** + * \brief Reposition the file stream's position + * + * This is a portable version of the POSIX fseeko64(). * + */ +int mvhd_fseeko64(FILE* stream, int64_t offset, int origin); + +/** + * \brief Calculate the CRC32 of a data buffer. + * + * This function can be used for verifying data integrity. + * + * \param [in] data The data buffer + * \param [in] n_bytes The size of the data buffer in bytes + * + * \return The CRC32 of the data buffer + */ +uint32_t mvhd_crc32(const void* data, size_t n_bytes); + +/** + * \brief Calculate the file modification timestamp. + * + * This function is primarily to help protect differencing VHD's + * + * \param [in] path the UTF-8 file path + * \param [out] err The error value, if an error occurrs + * + * \return The file modified timestamp, in VHD compatible timestamp. + * 'err' will be set to non-zero on error + */ +uint32_t mvhd_file_mod_timestamp(const char* path, int *err); + +struct MVHDMeta* mvhd_create_fixed_raw(const char* path, FILE* raw_img, uint64_t size_in_bytes, MVHDGeom* geom, int* err, mvhd_progress_callback progress_callback); + +/** + * \brief Write zero filled sectors to file. + * + * Note, the caller should set the file position before calling this + * function for correct operation. + * + * \param [in] f File to write sectors to + * \param [in] sector_count The number of sectors to write + */ +void mvhd_write_empty_sectors(FILE* f, int sector_count); + +/** + * \brief Read a fixed VHD image + * + * Fixed VHD images are essentially raw image files with a footer tacked on + * the end. They are therefore straightforward to write + * + * \param [in] vhdm MiniVHD data structure + * \param [in] offset Sector offset to read from + * \param [in] num_sectors The desired number of sectors to read + * \param [out] out_buff An output buffer to store read sectors. Must be + * large enough to hold num_sectors worth of sectors. + * + * \retval 0 num_sectors were read from file + * \retval >0 < num_sectors were read from file + */ +int mvhd_fixed_read(struct MVHDMeta* vhdm, uint32_t offset, int num_sectors, void* out_buff); + +/** + * \brief Read a sparse VHD image + * + * Sparse, or dynamic images are VHD images that grow as data is written to them. + * + * This function implements the logic to read sectors from the file, taking into + * account the fact that blocks may be stored on disk in any order, and that the + * read could cross block boundaries. + * + * \param [in] vhdm MiniVHD data structure + * \param [in] offset Sector offset to read from + * \param [in] num_sectors The desired number of sectors to read + * \param [out] out_buff An output buffer to store read sectors. Must be + * large enough to hold num_sectors worth of sectors. + * + * \retval 0 num_sectors were read from file + * \retval >0 < num_sectors were read from file + */ +int mvhd_sparse_read(struct MVHDMeta* vhdm, uint32_t offset, int num_sectors, void* out_buff); + +/** + * \brief Read a differencing VHD image + * + * Differencing images are a variant of a sparse image. They contain the grow-on-demand + * properties of sparse images, but also reference a parent image. Data is read from the + * child image only if it is newer than the data stored in the parent image. + * + * This function implements the logic to read sectors from the child, or a parent image. + * Differencing images may have a differencing image as a parent, creating a chain of images. + * There is no theoretical chain length limit, although I do not consider long chains to be + * advisable. Verifying the parent-child relationship is not very robust. + * + * \param [in] vhdm MiniVHD data structure + * \param [in] offset Sector offset to read from + * \param [in] num_sectors The desired number of sectors to read + * \param [out] out_buff An output buffer to store read sectors. Must be + * large enough to hold num_sectors worth of sectors. + * + * \retval 0 num_sectors were read from file + * \retval >0 < num_sectors were read from file + */ +int mvhd_diff_read(struct MVHDMeta* vhdm, uint32_t offset, int num_sectors, void* out_buff); + +/** + * \brief Write to a fixed VHD image + * + * Fixed VHD images are essentially raw image files with a footer tacked on + * the end. They are therefore straightforward to write + * + * \param [in] vhdm MiniVHD data structure + * \param [in] offset Sector offset to write to + * \param [in] num_sectors The desired number of sectors to write + * \param [in] in_buff A source buffer to write sectors from. Must be + * large enough to hold num_sectors worth of sectors. + * + * \retval 0 num_sectors were written to file + * \retval >0 < num_sectors were written to file + */ +int mvhd_fixed_write(struct MVHDMeta* vhdm, uint32_t offset, int num_sectors, void* in_buff); + +/** + * \brief Write to a sparse or differencing VHD image + * + * Sparse, or dynamic images are VHD images that grow as data is written to them. + * + * Differencing images are a variant of a sparse image. They contain the grow-on-demand + * properties of sparse images, but also reference a parent image. Data is always written + * to the child image. This makes writing to differencing images essentially identical to + * writing to sparse images, hence they use the same function. + * + * This function implements the logic to write sectors to the file, taking into + * account the fact that blocks may be stored on disk in any order, and that the + * write operation could cross block boundaries. + * + * \param [in] vhdm MiniVHD data structure + * \param [in] offset Sector offset to write to + * \param [in] num_sectors The desired number of sectors to write + * \param [in] in_buff A source buffer to write sectors from. Must be + * large enough to hold num_sectors worth of sectors. + * + * \retval 0 num_sectors were written to file + * \retval >0 < num_sectors were written to file + */ +int mvhd_sparse_diff_write(struct MVHDMeta* vhdm, uint32_t offset, int num_sectors, void* in_buff); + +/** + * \brief A no-op function to "write" to read-only VHD images + * + * \param [in] vhdm MiniVHD data structure + * \param [in] offset Sector offset to write to + * \param [in] num_sectors The desired number of sectors to write + * \param [in] in_buff A source buffer to write sectors from. Must be + * large enough to hold num_sectors worth of sectors. + * + * \retval 0 num_sectors were written to file + * \retval >0 < num_sectors were written to file + */ +int mvhd_noop_write(struct MVHDMeta* vhdm, uint32_t offset, int num_sectors, void* in_buff); + +/** + * \brief Save the contents of a VHD footer from a buffer to a struct + * + * \param [out] footer save contents of buffer into footer + * \param [in] buffer VHD footer in raw bytes + */ +void mvhd_buffer_to_footer(MVHDFooter* footer, uint8_t* buffer); + +/** + * \brief Save the contents of a VHD sparse header from a buffer to a struct + * + * \param [out] header save contents of buffer into header + * \param [in] buffer VHD header in raw bytes + */ +void mvhd_buffer_to_header(MVHDSparseHeader* header, uint8_t* buffer); + +/** + * \brief Save the contents of a VHD footer struct to a buffer + * + * \param [in] footer save contents of struct into buffer + * \param [out] buffer VHD footer in raw bytes + */ +void mvhd_footer_to_buffer(MVHDFooter* footer, uint8_t* buffer); + +/** + * \brief Save the contents of a VHD sparse header struct to a buffer + * + * \param [in] header save contents of struct into buffer + * \param [out] buffer VHD sparse header in raw bytes + */ +void mvhd_header_to_buffer(MVHDSparseHeader* header, uint8_t* buffer); + +#ifdef __cplusplus +} +#endif + + +#endif /*MINIVHD_INTERNAL_H*/ diff --git a/src/disk/minivhd/libxml2_encoding.h b/src/disk/minivhd/libxml2_encoding.h deleted file mode 100644 index 831aea4af..000000000 --- a/src/disk/minivhd/libxml2_encoding.h +++ /dev/null @@ -1,12 +0,0 @@ -#ifndef LIBXML2_ENCODING_H -#define LIBXML2_ENCODING_H - -#include -typedef uint16_t mvhd_utf16; - -void xmlEncodingInit(void); -int UTF16LEToUTF8(unsigned char* out, int *outlen, const unsigned char* inb, int *inlenb); -int UTF8ToUTF16LE(unsigned char* outb, int *outlen, const unsigned char* in, int *inlen); -int UTF16BEToUTF8(unsigned char* out, int *outlen, const unsigned char* inb, int *inlenb); -int UTF8ToUTF16BE(unsigned char* outb, int *outlen, const unsigned char* in, int *inlen); -#endif \ No newline at end of file diff --git a/src/disk/minivhd/minivhd_manage.c b/src/disk/minivhd/manage.c similarity index 68% rename from src/disk/minivhd/minivhd_manage.c rename to src/disk/minivhd/manage.c index e9473c0e3..7ac3989e6 100644 --- a/src/disk/minivhd/minivhd_manage.c +++ b/src/disk/minivhd/manage.c @@ -1,175 +1,240 @@ -/** - * \file - * \brief VHD management functions (open, close, read write etc) +/* + * MiniVHD Minimalist VHD implementation in C. + * + * This file is part of the MiniVHD Project. + * + * VHD management functions (open, close, read write etc) + * + * Version: @(#)manage.c 1.0.4 2021/04/16 + * + * Authors: Sherman Perry, + * Fred N. van Kempen, + * + * Copyright 2019-2021 Sherman Perry. + * Copyright 2021 Fred N. van Kempen. + * + * MIT License + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documenta- + * tion files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, + * copy, modify, merge, publish, distribute, sublicense, and/or + * sell copies of the Software, and to permit persons to whom + * the Software is furnished to do so, subject to the following + * conditions: + * + * The above copyright notice and this permission notice shall + * be included in all copies or substantial portions of the + * Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF O R IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. */ #ifndef _FILE_OFFSET_BITS -#define _FILE_OFFSET_BITS 64 +# define _FILE_OFFSET_BITS 64 #endif #include #include #include #include #include -#include "cwalk.h" -#include "libxml2_encoding.h" -#include "minivhd_internal.h" -#include "minivhd_io.h" -#include "minivhd_util.h" -#include "minivhd_struct_rw.h" +#include #include "minivhd.h" +#include "internal.h" +#include "version.h" +#include "cwalk.h" +#include "xml2_encoding.h" + -int mvhd_errno = 0; -static char tmp_open_path[MVHD_MAX_PATH_BYTES] = {0}; struct MVHDPaths { - char dir_path[MVHD_MAX_PATH_BYTES]; - char file_name[MVHD_MAX_PATH_BYTES]; - char w2ku_path[MVHD_MAX_PATH_BYTES]; - char w2ru_path[MVHD_MAX_PATH_BYTES]; - char joined_path[MVHD_MAX_PATH_BYTES]; + char dir_path[MVHD_MAX_PATH_BYTES]; + char file_name[MVHD_MAX_PATH_BYTES]; + char w2ku_path[MVHD_MAX_PATH_BYTES]; + char w2ru_path[MVHD_MAX_PATH_BYTES]; + char joined_path[MVHD_MAX_PATH_BYTES]; uint16_t tmp_src_path[MVHD_MAX_PATH_CHARS]; }; -static void mvhd_read_footer(MVHDMeta* vhdm); -static void mvhd_read_sparse_header(MVHDMeta* vhdm); -static bool mvhd_footer_checksum_valid(MVHDMeta* vhdm); -static bool mvhd_sparse_checksum_valid(MVHDMeta* vhdm); -static int mvhd_read_bat(MVHDMeta *vhdm, MVHDError* err); -static void mvhd_calc_sparse_values(MVHDMeta* vhdm); -static int mvhd_init_sector_bitmap(MVHDMeta* vhdm, MVHDError* err); + +int mvhd_errno = 0; + + +static char tmp_open_path[MVHD_MAX_PATH_BYTES] = {0}; + /** * \brief Populate data stuctures with content from a VHD footer - * + * * \param [in] vhdm MiniVHD data structure */ -static void mvhd_read_footer(MVHDMeta* vhdm) { +static void +read_footer(MVHDMeta* vhdm) +{ uint8_t buffer[MVHD_FOOTER_SIZE]; + mvhd_fseeko64(vhdm->f, -MVHD_FOOTER_SIZE, SEEK_END); - fread(buffer, sizeof buffer, 1, vhdm->f); + (void) !fread(buffer, sizeof buffer, 1, vhdm->f); mvhd_buffer_to_footer(&vhdm->footer, buffer); } + /** * \brief Populate data stuctures with content from a VHD sparse header - * + * * \param [in] vhdm MiniVHD data structure */ -static void mvhd_read_sparse_header(MVHDMeta* vhdm) { +static void +read_sparse_header(MVHDMeta* vhdm) +{ uint8_t buffer[MVHD_SPARSE_SIZE]; + mvhd_fseeko64(vhdm->f, vhdm->footer.data_offset, SEEK_SET); - fread(buffer, sizeof buffer, 1, vhdm->f); + (void) !fread(buffer, sizeof buffer, 1, vhdm->f); mvhd_buffer_to_header(&vhdm->sparse, buffer); } + /** * \brief Validate VHD footer checksum - * + * * This works by generating a checksum from the footer, and comparing it against the stored checksum. - * + * * \param [in] vhdm MiniVHD data structure */ -static bool mvhd_footer_checksum_valid(MVHDMeta* vhdm) { +static bool +footer_checksum_valid(MVHDMeta* vhdm) +{ return vhdm->footer.checksum == mvhd_gen_footer_checksum(&vhdm->footer); } + /** * \brief Validate VHD sparse header checksum - * + * * This works by generating a checksum from the sparse header, and comparing it against the stored checksum. - * + * * \param [in] vhdm MiniVHD data structure */ -static bool mvhd_sparse_checksum_valid(MVHDMeta* vhdm) { +static bool +sparse_checksum_valid(MVHDMeta* vhdm) +{ return vhdm->sparse.checksum == mvhd_gen_sparse_checksum(&vhdm->sparse); } + /** * \brief Read BAT into MiniVHD data structure - * - * The Block Allocation Table (BAT) is the structure in a sparse and differencing VHD which stores + * + * The Block Allocation Table (BAT) is the structure in a sparse and differencing VHD which stores * the 4-byte sector offsets for each data block. This function allocates enough memory to contain * the entire BAT, and then reads the contents of the BAT into the buffer. - * + * * \param [in] vhdm MiniVHD data structure * \param [out] err this is populated with MVHD_ERR_MEM if the calloc fails - * + * * \retval -1 if an error occurrs. Check value of err in this case * \retval 0 if the function call succeeds */ -static int mvhd_read_bat(MVHDMeta *vhdm, MVHDError* err) { +static int +read_bat(MVHDMeta *vhdm, MVHDError* err) +{ vhdm->block_offset = calloc(vhdm->sparse.max_bat_ent, sizeof *vhdm->block_offset); if (vhdm->block_offset == NULL) { *err = MVHD_ERR_MEM; return -1; } + mvhd_fseeko64(vhdm->f, vhdm->sparse.bat_offset, SEEK_SET); + for (uint32_t i = 0; i < vhdm->sparse.max_bat_ent; i++) { - fread(&vhdm->block_offset[i], sizeof *vhdm->block_offset, 1, vhdm->f); + (void) !fread(&vhdm->block_offset[i], sizeof *vhdm->block_offset, 1, vhdm->f); vhdm->block_offset[i] = mvhd_from_be32(vhdm->block_offset[i]); } return 0; } + /** * \brief Perform a one-time calculation of some sparse VHD values - * + * * \param [in] vhdm MiniVHD data structure */ -static void mvhd_calc_sparse_values(MVHDMeta* vhdm) { +static void +calc_sparse_values(MVHDMeta* vhdm) +{ vhdm->sect_per_block = vhdm->sparse.block_sz / MVHD_SECTOR_SIZE; int bm_bytes = vhdm->sect_per_block / 8; vhdm->bitmap.sector_count = bm_bytes / MVHD_SECTOR_SIZE; + if (bm_bytes % MVHD_SECTOR_SIZE > 0) { vhdm->bitmap.sector_count++; } } + /** * \brief Allocate memory for a sector bitmap. - * + * * Each data block is preceded by a sector bitmap. Each bit indicates whether the corresponding sector - * is considered 'clean' or 'dirty' (for sparse VHD images), or whether to read from the parent or current + * is considered 'clean' or 'dirty' (for sparse VHD images), or whether to read from the parent or current * image (for differencing images). - * + * * \param [in] vhdm MiniVHD data structure * \param [out] err this is populated with MVHD_ERR_MEM if the calloc fails - * + * * \retval -1 if an error occurrs. Check value of err in this case * \retval 0 if the function call succeeds */ -static int mvhd_init_sector_bitmap(MVHDMeta* vhdm, MVHDError* err) { +static int +init_sector_bitmap(MVHDMeta* vhdm, MVHDError* err) +{ vhdm->bitmap.curr_bitmap = calloc(vhdm->bitmap.sector_count, MVHD_SECTOR_SIZE); if (vhdm->bitmap.curr_bitmap == NULL) { *err = MVHD_ERR_MEM; return -1; } + vhdm->bitmap.curr_block = -1; + return 0; } + /** * \brief Check if the path for a given platform code exists - * - * From the available paths, both relative and absolute, construct a full path + * + * From the available paths, both relative and absolute, construct a full path * and attempt to open a file at that path. - * - * Note, this function makes no attempt to verify that the path is the correct + * + * Note, this function makes no attempt to verify that the path is the correct * VHD image, or even a VHD image at all. - * + * * \param [in] paths a struct containing all available paths to work with - * \param [in] the platform code to try and obtain a path for. Setting this to zero + * \param [in] the platform code to try and obtain a path for. Setting this to zero * will try using the directory of the child image - * + * * \retval true if a file is found * \retval false if a file is not found */ -static bool mvhd_parent_path_exists(struct MVHDPaths* paths, uint32_t plat_code) { - memset(paths->joined_path, 0, sizeof paths->joined_path); +static bool +mvhd_parent_path_exists(struct MVHDPaths* paths, uint32_t plat_code) +{ FILE* f; - int cwk_ret, ferr; - enum cwk_path_style style = cwk_path_guess_style((const char*)paths->dir_path); + int ferr; + size_t cwk_ret; + enum cwk_path_style style; + + memset(paths->joined_path, 0, sizeof paths->joined_path); + style = cwk_path_guess_style((const char*)paths->dir_path); cwk_path_set_style(style); cwk_ret = 1; + if (plat_code == MVHD_DIF_LOC_W2RU && *paths->w2ru_path) { cwk_ret = cwk_path_join((const char*)paths->dir_path, (const char*)paths->w2ru_path, paths->joined_path, sizeof paths->joined_path); } else if (plat_code == MVHD_DIF_LOC_W2KU && *paths->w2ku_path) { @@ -181,6 +246,7 @@ static bool mvhd_parent_path_exists(struct MVHDPaths* paths, uint32_t plat_code) if (cwk_ret > MVHD_MAX_PATH_BYTES) { return false; } + f = mvhd_fopen((const char*)paths->joined_path, "rb", &ferr); if (f != NULL) { /* We found a file at the requested path! */ @@ -188,47 +254,54 @@ static bool mvhd_parent_path_exists(struct MVHDPaths* paths, uint32_t plat_code) tmp_open_path[sizeof tmp_open_path - 1] = '\0'; fclose(f); return true; - } else { - return false; } + + return false; } + /** * \brief attempt to obtain a file path to a file that may be a valid VHD image - * - * Differential VHD images store both a UTF-16BE file name (or path), and up to - * eight "parent locator" entries. Using this information, this function tries to + * + * Differential VHD images store both a UTF-16BE file name (or path), and up to + * eight "parent locator" entries. Using this information, this function tries to * find a parent image. - * + * * This function does not verify if the path returned is a valid parent image. - * + * * \param [in] vhdm current MiniVHD data structure * \param [out] err any errors that may occurr. Check this if NULL is returned - * - * \return a pointer to the global string `tmp_open_path`, or NULL if a path could + * + * \return a pointer to the global string `tmp_open_path`, or NULL if a path could * not be found, or some error occurred */ -static char* mvhd_get_diff_parent_path(MVHDMeta* vhdm, int* err) { +static char* +get_diff_parent_path(MVHDMeta* vhdm, int* err) +{ int utf_outlen, utf_inlen, utf_ret; - char* par_fp = NULL; - /* We can't resolve relative paths if we don't have an absolute + char *par_fp = NULL; + struct MVHDPaths *paths; + size_t dirlen; + + /* We can't resolve relative paths if we don't have an absolute path to work with */ if (!cwk_path_is_absolute((const char*)vhdm->filename)) { *err = MVHD_ERR_PATH_REL; goto end; } - struct MVHDPaths* paths = calloc(1, sizeof *paths); + + paths = calloc(1, sizeof *paths); if (paths == NULL) { *err = MVHD_ERR_MEM; goto end; } - size_t dirlen; cwk_path_get_dirname((const char*)vhdm->filename, &dirlen); if (dirlen >= sizeof paths->dir_path) { *err = MVHD_ERR_PATH_LEN; goto paths_cleanup; } memcpy(paths->dir_path, vhdm->filename, dirlen); + /* Get the filename field from the sparse header. */ utf_outlen = (int)sizeof paths->file_name; utf_inlen = (int)sizeof vhdm->sparse.par_utf16_name; @@ -237,8 +310,10 @@ static char* mvhd_get_diff_parent_path(MVHDMeta* vhdm, int* err) { mvhd_set_encoding_err(utf_ret, err); goto paths_cleanup; } + /* Now read the parent locator entries, both relative and absolute, if they exist */ unsigned char* loc_path; + for (int i = 0; i < 8; i++) { utf_outlen = MVHD_MAX_PATH_BYTES - 1; if (vhdm->sparse.par_loc_entry[i].plat_code == MVHD_DIF_LOC_W2RU) { @@ -248,14 +323,16 @@ static char* mvhd_get_diff_parent_path(MVHDMeta* vhdm, int* err) { } else { continue; } + utf_inlen = vhdm->sparse.par_loc_entry[i].plat_data_len; if (utf_inlen > MVHD_MAX_PATH_BYTES) { *err = MVHD_ERR_PATH_LEN; goto paths_cleanup; } mvhd_fseeko64(vhdm->f, vhdm->sparse.par_loc_entry[i].plat_data_offset, SEEK_SET); - fread(paths->tmp_src_path, sizeof (uint8_t), utf_inlen, vhdm->f); - /* Note, the W2*u parent locators are UTF-16LE, unlike the filename field previously obtained, + (void) !fread(paths->tmp_src_path, sizeof (uint8_t), utf_inlen, vhdm->f); + + /* Note, the W2*u parent locators are UTF-16LE, unlike the filename field previously obtained, which is UTF-16BE */ utf_ret = UTF16LEToUTF8(loc_path, &utf_outlen, (const unsigned char*)paths->tmp_src_path, &utf_inlen); if (utf_ret < 0) { @@ -263,80 +340,132 @@ static char* mvhd_get_diff_parent_path(MVHDMeta* vhdm, int* err) { goto paths_cleanup; } } + /* We have paths in UTF-8. We should have enough info to try and find the parent VHD */ /* Does the relative path exist? */ if (mvhd_parent_path_exists(paths, MVHD_DIF_LOC_W2RU)) { par_fp = tmp_open_path; goto paths_cleanup; } + /* What about trying the child directory? */ if (mvhd_parent_path_exists(paths, 0)) { par_fp = tmp_open_path; goto paths_cleanup; } + /* Well, all else fails, try the stored absolute path, if it exists */ if (mvhd_parent_path_exists(paths, MVHD_DIF_LOC_W2KU)) { par_fp = tmp_open_path; goto paths_cleanup; } + /* If we reach this point, we could not find a path with a valid file */ par_fp = NULL; *err = MVHD_ERR_PAR_NOT_FOUND; - + paths_cleanup: free(paths); paths = NULL; + end: return par_fp; } + /** * \brief Attach the read/write function pointers to read/write functions - * - * Depending on the VHD type, different sector reading and writing functions are used. + * + * Depending on the VHD type, different sector reading and writing functions are used. * The functions are called via function pointers stored in the vhdm struct. - * + * * \param [in] vhdm MiniVHD data structure */ -static void mvhd_assign_io_funcs(MVHDMeta* vhdm) { +static void +assign_io_funcs(MVHDMeta* vhdm) +{ switch (vhdm->footer.disk_type) { - case MVHD_TYPE_FIXED: - vhdm->read_sectors = mvhd_fixed_read; - vhdm->write_sectors = mvhd_fixed_write; - break; - case MVHD_TYPE_DYNAMIC: - vhdm->read_sectors = mvhd_sparse_read; - vhdm->write_sectors = mvhd_sparse_diff_write; - break; - case MVHD_TYPE_DIFF: - vhdm->read_sectors = mvhd_diff_read; - vhdm->write_sectors = mvhd_sparse_diff_write; - break; + case MVHD_TYPE_FIXED: + vhdm->read_sectors = mvhd_fixed_read; + vhdm->write_sectors = mvhd_fixed_write; + break; + + case MVHD_TYPE_DYNAMIC: + vhdm->read_sectors = mvhd_sparse_read; + vhdm->write_sectors = mvhd_sparse_diff_write; + break; + + case MVHD_TYPE_DIFF: + vhdm->read_sectors = mvhd_diff_read; + vhdm->write_sectors = mvhd_sparse_diff_write; + break; } - if (vhdm->readonly) { + + if (vhdm->readonly) vhdm->write_sectors = mvhd_noop_write; - } } -bool mvhd_file_is_vhd(FILE* f) { - if (f) { - uint8_t con_str[8]; - mvhd_fseeko64(f, -MVHD_FOOTER_SIZE, SEEK_END); - fread(con_str, sizeof con_str, 1, f); - return mvhd_is_conectix_str(con_str); - } else { - return false; - } + +/** + * \brief Return the library version as a string + */ +MVHDAPI const char * +mvhd_version(void) +{ + return LIB_VERSION_4; } -MVHDGeom mvhd_calculate_geometry(uint64_t size) { + +/** + * \brief Return the library version as a number + */ +MVHDAPI uint32_t +mvhd_version_id(void) +{ + return (LIB_VER_MAJOR << 24) | (LIB_VER_MINOR << 16) | + (LIB_VER_REV << 16) | LIB_VER_PATCH; +} + + +/** + * \brief A simple test to see if a given file is a VHD + * + * \param [in] f file to test + * + * \retval 1 if f is a VHD + * \retval 0 if f is not a VHD + */ +MVHDAPI int +mvhd_file_is_vhd(FILE* f) +{ + uint8_t con_str[8]; + + if (f == NULL) { + return 0; + } + + mvhd_fseeko64(f, -MVHD_FOOTER_SIZE, SEEK_END); + (void) !fread(con_str, sizeof con_str, 1, f); + if (mvhd_is_conectix_str(con_str)) { + return 1; + } + + return 0; +} + + +MVHDAPI MVHDGeom +mvhd_calculate_geometry(uint64_t size) +{ MVHDGeom chs; uint32_t ts = (uint32_t)(size / MVHD_SECTOR_SIZE); uint32_t spt, heads, cyl, cth; + if (ts > 65535 * 16 * 255) { ts = 65535 * 16 * 255; } - if (ts >= 65535 * 16 * 63) { + + if (ts >= 65535 * 16 * 63) { spt = 255; heads = 16; cth = ts / spt; @@ -358,77 +487,95 @@ MVHDGeom mvhd_calculate_geometry(uint64_t size) { cth = ts / spt; } } + cyl = cth / heads; chs.heads = heads; chs.spt = spt; chs.cyl = cyl; + return chs; } -MVHDMeta* mvhd_open(const char* path, bool readonly, int* err) { + +MVHDAPI MVHDMeta* +mvhd_open(const char* path, int readonly, int* err) +{ MVHDError open_err; + MVHDMeta *vhdm = calloc(sizeof *vhdm, 1); if (vhdm == NULL) { *err = MVHD_ERR_MEM; goto end; } + if (strlen(path) >= sizeof vhdm->filename) { *err = MVHD_ERR_PATH_LEN; goto cleanup_vhdm; } + //This is safe, as we've just checked for potential overflow above strcpy(vhdm->filename, path); - vhdm->f = readonly ? mvhd_fopen((const char*)vhdm->filename, "rb", err) : mvhd_fopen((const char*)vhdm->filename, "rb+", err); + + if (readonly) { + vhdm->f = mvhd_fopen((const char*)vhdm->filename, "rb", err); + } else { + vhdm->f = mvhd_fopen((const char*)vhdm->filename, "rb+", err); + } if (vhdm->f == NULL) { /* note, mvhd_fopen sets err for us */ goto cleanup_vhdm; } vhdm->readonly = readonly; + if (!mvhd_file_is_vhd(vhdm->f)) { *err = MVHD_ERR_NOT_VHD; goto cleanup_file; } - mvhd_read_footer(vhdm); - if (!mvhd_footer_checksum_valid(vhdm)) { + + read_footer(vhdm); + if (!footer_checksum_valid(vhdm)) { *err = MVHD_ERR_FOOTER_CHECKSUM; goto cleanup_file; } if (vhdm->footer.disk_type == MVHD_TYPE_DIFF || vhdm->footer.disk_type == MVHD_TYPE_DYNAMIC) { - mvhd_read_sparse_header(vhdm); - if (!mvhd_sparse_checksum_valid(vhdm)) { + read_sparse_header(vhdm); + if (!sparse_checksum_valid(vhdm)) { *err = MVHD_ERR_SPARSE_CHECKSUM; goto cleanup_file; } - if (mvhd_read_bat(vhdm, &open_err) == -1) { + if (read_bat(vhdm, &open_err) == -1) { *err = open_err; goto cleanup_file; } - mvhd_calc_sparse_values(vhdm); - if (mvhd_init_sector_bitmap(vhdm, &open_err) == -1) { + calc_sparse_values(vhdm); + if (init_sector_bitmap(vhdm, &open_err) == -1) { *err = open_err; goto cleanup_bat; } - } else if (vhdm->footer.disk_type != MVHD_TYPE_FIXED) { *err = MVHD_ERR_TYPE; goto cleanup_bitmap; } - mvhd_assign_io_funcs(vhdm); + assign_io_funcs(vhdm); + vhdm->format_buffer.zero_data = calloc(64, MVHD_SECTOR_SIZE); if (vhdm->format_buffer.zero_data == NULL) { *err = MVHD_ERR_MEM; goto cleanup_bitmap; } + vhdm->format_buffer.sector_count = 64; if (vhdm->footer.disk_type == MVHD_TYPE_DIFF) { - char* par_path = mvhd_get_diff_parent_path(vhdm, err); + char* par_path = get_diff_parent_path(vhdm, err); if (par_path == NULL) { goto cleanup_format_buff; } + uint32_t par_mod_ts = mvhd_file_mod_timestamp(par_path, err); if (*err != 0) { goto cleanup_format_buff; } + if (vhdm->sparse.par_timestamp != par_mod_ts) { /* The last-modified timestamp is to fragile to make this a fatal error. Instead, we inform the caller of the potential problem. */ @@ -438,57 +585,78 @@ MVHDMeta* mvhd_open(const char* path, bool readonly, int* err) { if (vhdm->parent == NULL) { goto cleanup_format_buff; } + if (memcmp(vhdm->sparse.par_uuid, vhdm->parent->footer.uuid, sizeof vhdm->sparse.par_uuid) != 0) { *err = MVHD_ERR_INVALID_PAR_UUID; goto cleanup_format_buff; } } - /* If we've reached this point, we are good to go, so skip the cleanup steps */ + + /* + * If we've reached this point, we are good to go, + * so skip the cleanup steps. + */ goto end; + cleanup_format_buff: free(vhdm->format_buffer.zero_data); vhdm->format_buffer.zero_data = NULL; + cleanup_bitmap: free(vhdm->bitmap.curr_bitmap); vhdm->bitmap.curr_bitmap = NULL; + cleanup_bat: free(vhdm->block_offset); vhdm->block_offset = NULL; + cleanup_file: fclose(vhdm->f); vhdm->f = NULL; + cleanup_vhdm: free(vhdm); vhdm = NULL; + end: return vhdm; } -void mvhd_close(MVHDMeta* vhdm) { - if (vhdm != NULL) { - if (vhdm->parent != NULL) { - mvhd_close(vhdm->parent); - } - fclose(vhdm->f); - if (vhdm->block_offset != NULL) { - free(vhdm->block_offset); - vhdm->block_offset = NULL; - } - if (vhdm->bitmap.curr_bitmap != NULL) { - free(vhdm->bitmap.curr_bitmap); - vhdm->bitmap.curr_bitmap = NULL; - } - if (vhdm->format_buffer.zero_data != NULL) { - free(vhdm->format_buffer.zero_data); - vhdm->format_buffer.zero_data = NULL; - } - free(vhdm); - vhdm = NULL; + +MVHDAPI void +mvhd_close(MVHDMeta* vhdm) +{ + if (vhdm == NULL) + return; + + if (vhdm->parent != NULL) { + mvhd_close(vhdm->parent); } + + fclose(vhdm->f); + + if (vhdm->block_offset != NULL) { + free(vhdm->block_offset); + vhdm->block_offset = NULL; + } + if (vhdm->bitmap.curr_bitmap != NULL) { + free(vhdm->bitmap.curr_bitmap); + vhdm->bitmap.curr_bitmap = NULL; + } + if (vhdm->format_buffer.zero_data != NULL) { + free(vhdm->format_buffer.zero_data); + vhdm->format_buffer.zero_data = NULL; + } + + free(vhdm); } -int mvhd_diff_update_par_timestamp(MVHDMeta* vhdm, int* err) { + +MVHDAPI int +mvhd_diff_update_par_timestamp(MVHDMeta* vhdm, int* err) +{ uint8_t sparse_buff[1024]; + if (vhdm == NULL || err == NULL) { *err = MVHD_ERR_INVALID_PARAMS; return -1; @@ -497,7 +665,7 @@ int mvhd_diff_update_par_timestamp(MVHDMeta* vhdm, int* err) { *err = MVHD_ERR_TYPE; return -1; } - char* par_path = mvhd_get_diff_parent_path(vhdm, err); + char* par_path = get_diff_parent_path(vhdm, err); if (par_path == NULL) { return -1; } @@ -505,31 +673,53 @@ int mvhd_diff_update_par_timestamp(MVHDMeta* vhdm, int* err) { if (*err != 0) { return -1; } + /* Update the timestamp and sparse header checksum */ vhdm->sparse.par_timestamp = par_mod_ts; vhdm->sparse.checksum = mvhd_gen_sparse_checksum(&vhdm->sparse); + /* Generate and write the updated sparse header */ mvhd_header_to_buffer(&vhdm->sparse, sparse_buff); mvhd_fseeko64(vhdm->f, (int64_t)vhdm->footer.data_offset, SEEK_SET); fwrite(sparse_buff, sizeof sparse_buff, 1, vhdm->f); + return 0; } -int mvhd_read_sectors(MVHDMeta* vhdm, uint32_t offset, int num_sectors, void* out_buff) { + +MVHDAPI int +mvhd_read_sectors(MVHDMeta* vhdm, uint32_t offset, int num_sectors, void* out_buff) +{ return vhdm->read_sectors(vhdm, offset, num_sectors, out_buff); } -int mvhd_write_sectors(MVHDMeta* vhdm, uint32_t offset, int num_sectors, void* in_buff) { + +MVHDAPI int +mvhd_write_sectors(MVHDMeta* vhdm, uint32_t offset, int num_sectors, void* in_buff) +{ return vhdm->write_sectors(vhdm, offset, num_sectors, in_buff); } -int mvhd_format_sectors(MVHDMeta* vhdm, uint32_t offset, int num_sectors) { + +MVHDAPI int +mvhd_format_sectors(MVHDMeta* vhdm, uint32_t offset, int num_sectors) +{ int num_full = num_sectors / vhdm->format_buffer.sector_count; int remain = num_sectors % vhdm->format_buffer.sector_count; + for (int i = 0; i < num_full; i++) { vhdm->write_sectors(vhdm, offset, vhdm->format_buffer.sector_count, vhdm->format_buffer.zero_data); offset += vhdm->format_buffer.sector_count; } + vhdm->write_sectors(vhdm, offset, remain, vhdm->format_buffer.zero_data); + return 0; -} \ No newline at end of file +} + + +MVHDAPI MVHDType +mvhd_get_type(MVHDMeta* vhdm) +{ + return vhdm->footer.disk_type; +} diff --git a/src/disk/minivhd/minivhd.h b/src/disk/minivhd/minivhd.h index 0d925f71a..929ea5b27 100644 --- a/src/disk/minivhd/minivhd.h +++ b/src/disk/minivhd/minivhd.h @@ -1,11 +1,49 @@ +/* + * MiniVHD Minimalist VHD implementation in C. + * MiniVHD is a minimalist implementation of read/write/creation + * of VHD files. It is designed to read and write to VHD files + * at a sector level. It does not enable file access, or provide + * mounting options. Those features are left to more advanced + * libraries and/or the operating system. + * + * This file is part of the MiniVHD Project. + * + * Definitions for the MiniVHD library. + * + * Version: @(#)minivhd.h 1.0.3 2021/04/16 + * + * Authors: Sherman Perry, + * Fred N. van Kempen, + * + * Copyright 2019-2021 Sherman Perry. + * Copyright 2021 Fred N. van Kempen. + * + * MIT License + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documenta- + * tion files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, + * copy, modify, merge, publish, distribute, sublicense, and/or + * sell copies of the Software, and to permit persons to whom + * the Software is furnished to do so, subject to the following + * conditions: + * + * The above copyright notice and this permission notice shall + * be included in all copies or substantial portions of the + * Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF O R IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ #ifndef MINIVHD_H -#define MINIVHD_H +# define MINIVHD_H -#include -#include -#include - -extern int mvhd_errno; typedef enum MVHDError { MVHD_ERR_MEM = -128, @@ -23,7 +61,7 @@ typedef enum MVHDError { MVHD_ERR_INVALID_GEOM, MVHD_ERR_INVALID_SIZE, MVHD_ERR_INVALID_BLOCK_SIZE, - MVHD_ERR_INVALID_PARAMS, + MVHD_ERR_INVALID_PARAMS, MVHD_ERR_CONV_SIZE, MVHD_ERR_TIMESTAMP } MVHDError; @@ -46,6 +84,11 @@ typedef struct MVHDGeom { uint8_t spt; } MVHDGeom; + +#ifdef __cplusplus +extern "C" { +#endif + typedef void (*mvhd_progress_callback)(uint32_t current_sector, uint32_t total_sectors); typedef struct MVHDCreationOptions { @@ -60,97 +103,142 @@ typedef struct MVHDCreationOptions { typedef struct MVHDMeta MVHDMeta; + +extern int mvhd_errno; + + +/* Shared-library madness. */ +//#if defined(_WIN32) +//# ifdef STATIC +# define MVHDAPI /*nothing*/ +//# else +//# ifdef BUILDING_LIBRARY +//# define MVHDAPI __declspec(dllexport) +//# else +//# define MVHDAPI __declspec(dllimport) +//# endif +//# endif +//#elif defined(__GNUC__) +//# ifdef BUILDING_LIBRARY +//# define MVHDAPI __attribute__((visibility("default"))) +//# else +//# define MVHDAPI /*nothing*/ +//# endif +//#else +//# define MVHDAPI /*nothing*/ +//#endif + + +/** + * \brief Return the library version as a string + */ +MVHDAPI const char *mvhd_version(void); + +/** + * \brief Return the library version as a number + */ +MVHDAPI uint32_t mvhd_version_id(void); + /** * \brief Output a string from a MiniVHD error number - * + * * \param [in] err is the error number to return string from - * + * * \return Error string */ -const char* mvhd_strerr(MVHDError err); +MVHDAPI const char* mvhd_strerr(MVHDError err); /** * \brief A simple test to see if a given file is a VHD - * + * * \param [in] f file to test - * - * \retval true if f is a VHD - * \retval false if f is not a VHD + * + * \retval 1 if f is a VHD + * \retval 0 if f is not a VHD */ -bool mvhd_file_is_vhd(FILE* f); +MVHDAPI int mvhd_file_is_vhd(FILE* f); + +/** + * \brief Return the file type of the given file + * + * \param [in] vhdm VHD to check. + * + * \retval one of the defined MVHDType values + */ +MVHDAPI MVHDType mvhd_get_type(MVHDMeta* vhdm); /** * \brief Open a VHD image for reading and/or writing - * - * The returned pointer contains all required values and structures (and files) to + * + * The returned pointer contains all required values and structures (and files) to * read and write to a VHD file. - * + * * Remember to call mvhd_close() when you are finished. - * + * * \param [in] Absolute path to VHD file. Relative path will cause issues when opening * a differencing VHD file - * \param [in] readonly set this to true to open the VHD in a read only manner - * \param [out] err will be set if the VHD fails to open. Value could be one of - * MVHD_ERR_MEM, MVHD_ERR_FILE, MVHD_ERR_NOT_VHD, MVHD_ERR_FOOTER_CHECKSUM, MVHD_ERR_SPARSE_CHECKSUM, + * \param [in] readonly set this to 1 to open the VHD in a read only manner + * \param [out] err will be set if the VHD fails to open. Value could be one of + * MVHD_ERR_MEM, MVHD_ERR_FILE, MVHD_ERR_NOT_VHD, MVHD_ERR_FOOTER_CHECKSUM, MVHD_ERR_SPARSE_CHECKSUM, * MVHD_ERR_TYPE, MVHD_ERR_TIMESTAMP * If MVHD_ERR_FILE is set, mvhd_errno will be set to the appropriate system errno value - * + * * \return MVHDMeta pointer. If NULL, check err. err may also be set to MVHD_ERR_TIMESTAMP if * opening a differencing VHD. */ -MVHDMeta* mvhd_open(const char* path, bool readonly, int* err); +MVHDAPI MVHDMeta* mvhd_open(const char* path, int readonly, int* err); /** * \brief Update the parent modified timestamp in the VHD file - * + * * Differencing VHD's use a parent last modified timestamp to try and detect if the * parent has been modified after the child has been created. However, this is rather * fragile and can be broken by moving/copying the parent. Also, MS DiskPart does not * set this timestamp in the child :( - * + * * Be careful when using this function that you don't update the timestamp after the * parent actually has been modified. - * + * * \param [in] vhdm Differencing VHD to update. * \param [out] err will be set if the timestamp could not be updated - * + * * \return non-zero on error, 0 on success */ -int mvhd_diff_update_par_timestamp(MVHDMeta* vhdm, int* err); +MVHDAPI int mvhd_diff_update_par_timestamp(MVHDMeta* vhdm, int* err); /** * \brief Create a fixed VHD image - * + * * \param [in] path is the absolute path to the image to create * \param [in] geom is the HDD geometry of the image to create. Determines final image size * \param [out] err indicates what error occurred, if any - * \param [out] progress_callback optional; if not NULL, gets called to indicate progress on the creation operation - * + * \param [out] progress_callback optional; if not NULL, gets called to indicate progress on the creation operation + * * \retval NULL if an error occurrs. Check value of *err for actual error. Otherwise returns pointer to a MVHDMeta struct */ -MVHDMeta* mvhd_create_fixed(const char* path, MVHDGeom geom, int* err, mvhd_progress_callback progress_callback); +MVHDAPI MVHDMeta* mvhd_create_fixed(const char* path, MVHDGeom geom, int* err, mvhd_progress_callback progress_callback); /** * \brief Create sparse (dynamic) VHD image. - * + * * \param [in] path is the absolute path to the VHD file to create * \param [in] geom is the HDD geometry of the image to create. Determines final image size - * \param [out] err indicates what error occurred, if any - * + * \param [out] err indicates what error occurred, if any + * * \return NULL if an error occurrs. Check value of *err for actual error. Otherwise returns pointer to a MVHDMeta struct */ -MVHDMeta* mvhd_create_sparse(const char* path, MVHDGeom geom, int* err); +MVHDAPI MVHDMeta* mvhd_create_sparse(const char* path, MVHDGeom geom, int* err); /** * \brief Create differencing VHD imagee. - * + * * \param [in] path is the absolute path to the VHD file to create * \param [in] par_path is the absolute path to a parent image. If NULL, a sparse image is created, otherwise create a differencing image * \param [out] err indicates what error occurred, if any - * + * * \return NULL if an error occurrs. Check value of *err for actual error. Otherwise returns pointer to a MVHDMeta struct */ -MVHDMeta* mvhd_create_diff(const char* path, const char* par_path, int* err); +MVHDAPI MVHDMeta* mvhd_create_diff(const char* path, const char* par_path, int* err); /** * \brief Create a VHD using the provided options @@ -162,108 +250,154 @@ MVHDMeta* mvhd_create_diff(const char* path, const char* par_path, int* err); * * \retval NULL if an error occurrs. Check value of *err for actual error. Otherwise returns pointer to a MVHDMeta struct */ -MVHDMeta* mvhd_create_ex(MVHDCreationOptions options, int* err); +MVHDAPI MVHDMeta* mvhd_create_ex(MVHDCreationOptions options, int* err); /** * \brief Safely close a VHD image - * + * * \param [in] vhdm MiniVHD data structure to close */ -void mvhd_close(MVHDMeta* vhdm); +MVHDAPI void mvhd_close(MVHDMeta* vhdm); /** * \brief Calculate hard disk geometry from a provided size - * + * * The VHD format uses Cylinder, Heads, Sectors per Track (CHS) when accessing the disk. * The size of the disk can be determined from C * H * S * sector_size. - * + * * Note, maximum geometry size (in bytes) is 65535 * 16 * 255 * 512, which is 127GB. * However, the maximum VHD size is 2040GB. For VHDs larger than 127GB, the geometry size will be * smaller than the actual VHD size. - * + * * This function determines the appropriate CHS geometry from a provided size in bytes. - * The calculations used are those provided in "Appendix: CHS Calculation" from the document + * The calculations used are those provided in "Appendix: CHS Calculation" from the document * "Virtual Hard Disk Image Format Specification" provided by Microsoft. - * + * * \param [in] size the desired VHD image size, in bytes - * + * * \return MVHDGeom the calculated geometry. This can be used in the appropriate create functions. */ -MVHDGeom mvhd_calculate_geometry(uint64_t size); +MVHDAPI MVHDGeom mvhd_calculate_geometry(uint64_t size); + +/** + * \brief Get the CHS geometry from the image + * + * \param [in] vhdm MiniVHD data structure + * + * \return The CHS geometry as stored in the image + */ +MVHDAPI MVHDGeom mvhd_get_geometry(MVHDMeta* vhdm); + +/** + * \brief Get the 'current_size' value from the image + * + * Note that the size returned may not match the size calculated from the + * CHS geometry. It is up to the caller to decide how best to handle this. + * + * \param [in] vhdm MiniVHD data structure + * + * \return The 'current_size' value in bytes, as stored in the image. + * Note, this may not match the CHS geometry. + */ +MVHDAPI uint64_t mvhd_get_current_size(MVHDMeta* vhdm); + +/** + * \brief Calculate CHS geometry size in bytes + * + * \param [in] geom the CHS geometry to calculate + * + * \return the size in bytes + */ +MVHDAPI uint64_t mvhd_calc_size_bytes(MVHDGeom *geom); + +/** + * \brief Calculate CHS geometry size in sectors + * + * \param [in] geom the CHS geometry to calculate + * + * \return the size in sectors + */ +MVHDAPI uint32_t mvhd_calc_size_sectors(MVHDGeom *geom); /** * \brief Convert a raw disk image to a fixed VHD image - * + * * \param [in] utf8_raw_path is the path of the raw image to convert * \param [in] utf8_vhd_path is the path of the VHD to create * \param [out] err indicates what error occurred, if any - * + * * \return NULL if an error occurrs. Check value of *err for actual error. Otherwise returns pointer to a MVHDMeta struct */ -MVHDMeta* mvhd_convert_to_vhd_fixed(const char* utf8_raw_path, const char* utf8_vhd_path, int* err); +MVHDAPI MVHDMeta* mvhd_convert_to_vhd_fixed(const char* utf8_raw_path, const char* utf8_vhd_path, int* err); /** * \brief Convert a raw disk image to a sparse VHD image - * + * * \param [in] utf8_raw_path is the path of the raw image to convert * \param [in] utf8_vhd_path is the path of the VHD to create * \param [out] err indicates what error occurred, if any - * + * * \return NULL if an error occurrs. Check value of *err for actual error. Otherwise returns pointer to a MVHDMeta struct */ -MVHDMeta* mvhd_convert_to_vhd_sparse(const char* utf8_raw_path, const char* utf8_vhd_path, int* err); +MVHDAPI MVHDMeta* mvhd_convert_to_vhd_sparse(const char* utf8_raw_path, const char* utf8_vhd_path, int* err); /** * \brief Convert a VHD image to a raw disk image - * + * * \param [in] utf8_vhd_path is the path of the VHD to convert * \param [in] utf8_raw_path is the path of the raw image to create * \param [out] err indicates what error occurred, if any - * + * * \return NULL if an error occurrs. Check value of *err for actual error. Otherwise returns the raw disk image FILE pointer */ -FILE* mvhd_convert_to_raw(const char* utf8_vhd_path, const char* utf8_raw_path, int *err); +MVHDAPI FILE* mvhd_convert_to_raw(const char* utf8_vhd_path, const char* utf8_raw_path, int *err); /** * \brief Read sectors from VHD file - * + * * Read num_sectors, beginning at offset from the VHD file into a buffer - * + * * \param [in] vhdm MiniVHD data structure * \param [in] offset the sector offset from which to start reading from * \param [in] num_sectors the number of sectors to read * \param [out] out_buff the buffer to write sector data to - * + * * \return the number of sectors that were not read, or zero */ -int mvhd_read_sectors(MVHDMeta* vhdm, uint32_t offset, int num_sectors, void* out_buff); +MVHDAPI int mvhd_read_sectors(MVHDMeta* vhdm, uint32_t offset, int num_sectors, void* out_buff); /** * \brief Write sectors to VHD file - * + * * Write num_sectors, beginning at offset from a buffer VHD file into the VHD file - * + * * \param [in] vhdm MiniVHD data structure * \param [in] offset the sector offset from which to start writing to * \param [in] num_sectors the number of sectors to write * \param [in] in_buffer the buffer to write sector data to - * + * * \return the number of sectors that were not written, or zero */ -int mvhd_write_sectors(MVHDMeta* vhdm, uint32_t offset, int num_sectors, void* in_buff); +MVHDAPI int mvhd_write_sectors(MVHDMeta* vhdm, uint32_t offset, int num_sectors, void* in_buff); /** * \brief Write zeroed sectors to VHD file - * - * Write num_sectors, beginning at offset, of zero data into the VHD file. - * We reuse the existing write functions, with a preallocated zero buffer as + * + * Write num_sectors, beginning at offset, of zero data into the VHD file. + * We reuse the existing write functions, with a preallocated zero buffer as * our source buffer. - * + * * \param [in] vhdm MiniVHD data structure * \param [in] offset the sector offset from which to start writing to * \param [in] num_sectors the number of sectors to write - * + * * \return the number of sectors that were not written, or zero */ -int mvhd_format_sectors(MVHDMeta* vhdm, uint32_t offset, int num_sectors); -#endif \ No newline at end of file +MVHDAPI int mvhd_format_sectors(MVHDMeta* vhdm, uint32_t offset, int num_sectors); + +#ifdef __cplusplus +} +#endif + + +#endif /*MINIVHD_H*/ diff --git a/src/disk/minivhd/minivhd_create.h b/src/disk/minivhd/minivhd_create.h deleted file mode 100644 index 9840d19ff..000000000 --- a/src/disk/minivhd/minivhd_create.h +++ /dev/null @@ -1,8 +0,0 @@ -#ifndef MINIVHD_CREATE_H -#define MINIVHD_CREATE_H -#include -#include "minivhd.h" - -MVHDMeta* mvhd_create_fixed_raw(const char* path, FILE* raw_img, uint64_t size_in_bytes, MVHDGeom* geom, int* err, mvhd_progress_callback progress_callback); - -#endif \ No newline at end of file diff --git a/src/disk/minivhd/minivhd_internal.h b/src/disk/minivhd/minivhd_internal.h deleted file mode 100644 index ea75284f8..000000000 --- a/src/disk/minivhd/minivhd_internal.h +++ /dev/null @@ -1,96 +0,0 @@ -#ifndef MINIVHD_INTERNAL_H -#define MINIVHD_INTERNAL_H -#include -#include -#include - -#define MVHD_FOOTER_SIZE 512 -#define MVHD_SPARSE_SIZE 1024 - -#define MVHD_SECTOR_SIZE 512 -#define MVHD_BAT_ENT_PER_SECT 128 - -#define MVHD_MAX_SIZE_IN_BYTES 0x1fe00000000 - -#define MVHD_SPARSE_BLK 0xffffffff -/* For simplicity, we don't handle paths longer than this - * Note, this is the max path in characters, as that is what - * Windows uses - */ -#define MVHD_MAX_PATH_CHARS 260 -#define MVHD_MAX_PATH_BYTES 1040 - -#define MVHD_DIF_LOC_W2RU 0x57327275 -#define MVHD_DIF_LOC_W2KU 0x57326B75 - -typedef struct MVHDSectorBitmap { - uint8_t* curr_bitmap; - int sector_count; - int curr_block; -} MVHDSectorBitmap; - -typedef struct MVHDFooter { - uint8_t cookie[8]; - uint32_t features; - uint32_t fi_fmt_vers; - uint64_t data_offset; - uint32_t timestamp; - uint8_t cr_app[4]; - uint32_t cr_vers; - uint8_t cr_host_os[4]; - uint64_t orig_sz; - uint64_t curr_sz; - struct { - uint16_t cyl; - uint8_t heads; - uint8_t spt; - } geom; - uint32_t disk_type; - uint32_t checksum; - uint8_t uuid[16]; - uint8_t saved_st; - uint8_t reserved[427]; -} MVHDFooter; - -typedef struct MVHDSparseHeader { - uint8_t cookie[8]; - uint64_t data_offset; - uint64_t bat_offset; - uint32_t head_vers; - uint32_t max_bat_ent; - uint32_t block_sz; - uint32_t checksum; - uint8_t par_uuid[16]; - uint32_t par_timestamp; - uint32_t reserved_1; - uint8_t par_utf16_name[512]; - struct { - uint32_t plat_code; - uint32_t plat_data_space; - uint32_t plat_data_len; - uint32_t reserved; - uint64_t plat_data_offset; - } par_loc_entry[8]; - uint8_t reserved_2[256]; -} MVHDSparseHeader; - -typedef struct MVHDMeta MVHDMeta; -struct MVHDMeta { - FILE* f; - bool readonly; - char filename[MVHD_MAX_PATH_BYTES]; - struct MVHDMeta* parent; - MVHDFooter footer; - MVHDSparseHeader sparse; - uint32_t* block_offset; - int sect_per_block; - MVHDSectorBitmap bitmap; - int (*read_sectors)(MVHDMeta*, uint32_t, int, void*); - int (*write_sectors)(MVHDMeta*, uint32_t, int, void*); - struct { - uint8_t* zero_data; - int sector_count; - } format_buffer; -}; - -#endif \ No newline at end of file diff --git a/src/disk/minivhd/minivhd_io.c b/src/disk/minivhd/minivhd_io.c index 4169d66f1..ff86a8337 100644 --- a/src/disk/minivhd/minivhd_io.c +++ b/src/disk/minivhd/minivhd_io.c @@ -1,80 +1,127 @@ -/** - * \file - * \brief Sector reading and writing implementations +/* + * MiniVHD Minimalist VHD implementation in C. + * + * This file is part of the MiniVHD Project. + * + * Sector reading and writing implementations. + * + * Version: @(#)io.c 1.0.3 2021/04/16 + * + * Author: Sherman Perry, + * + * Copyright 2019-2021 Sherman Perry. + * + * MIT License + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documenta- + * tion files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, + * copy, modify, merge, publish, distribute, sublicense, and/or + * sell copies of the Software, and to permit persons to whom + * the Software is furnished to do so, subject to the following + * conditions: + * + * The above copyright notice and this permission notice shall + * be included in all copies or substantial portions of the + * Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF O R IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. */ - #ifndef _FILE_OFFSET_BITS -#define _FILE_OFFSET_BITS 64 +# define _FILE_OFFSET_BITS 64 #endif +#include +#include #include +#include #include -#include "minivhd_internal.h" -#include "minivhd_util.h" +#include +#include "minivhd.h" +#include "internal.h" -/* The following bit array macros adapted from - http://www.mathcs.emory.edu/~cheung/Courses/255/Syllabus/1-C-intro/bit-array.html */ -#define VHD_SETBIT(A,k) ( A[(k/8)] |= (0x80 >> (k%8)) ) -#define VHD_CLEARBIT(A,k) ( A[(k/8)] &= ~(0x80 >> (k%8)) ) -#define VHD_TESTBIT(A,k) ( A[(k/8)] & (0x80 >> (k%8)) ) +/* + * The following bit array macros adapted from: + * + * http://www.mathcs.emory.edu/~cheung/Courses/255/Syllabus/1-C-intro/bit-array.html + */ +#define VHD_SETBIT(A,k) ( A[(k>>3)] |= (0x80 >> (k&7)) ) +#define VHD_CLEARBIT(A,k) ( A[(k>>3)] &= ~(0x80 >> (k&7)) ) +#define VHD_TESTBIT(A,k) ( A[(k>>3)] & (0x80 >> (k&7)) ) -static inline void mvhd_check_sectors(uint32_t offset, int num_sectors, uint32_t total_sectors, int* transfer_sect, int* trunc_sect); -static void mvhd_read_sect_bitmap(MVHDMeta* vhdm, int blk); -static void mvhd_write_bat_entry(MVHDMeta* vhdm, int blk); -static void mvhd_create_block(MVHDMeta* vhdm, int blk); -static void mvhd_write_curr_sect_bitmap(MVHDMeta* vhdm); /** * \brief Check that we will not be overflowing buffers - * + * * \param [in] offset The offset from which we are beginning from * \param [in] num_sectors The number of sectors which we desire to read/write * \param [in] total_sectors The total number of sectors available - * \param [out] transfer_sect The number of sectors to actually write. + * \param [out] transfer_sect The number of sectors to actually write. * This may be lower than num_sectors if offset + num_sectors >= total_sectors * \param [out] trunc_sectors The number of sectors truncated if transfer_sectors < num_sectors */ -static inline void mvhd_check_sectors(uint32_t offset, int num_sectors, uint32_t total_sectors, int* transfer_sect, int* trunc_sect) { +static inline void +check_sectors(uint32_t offset, int num_sectors, uint32_t total_sectors, int* transfer_sect, int* trunc_sect) +{ *transfer_sect = num_sectors; *trunc_sect = 0; + if ((total_sectors - offset) < (uint32_t)*transfer_sect) { *transfer_sect = total_sectors - offset; *trunc_sect = num_sectors - *transfer_sect; } } -void mvhd_write_empty_sectors(FILE* f, int sector_count) { + +void +mvhd_write_empty_sectors(FILE* f, int sector_count) +{ uint8_t zero_bytes[MVHD_SECTOR_SIZE] = {0}; + for (int i = 0; i < sector_count; i++) { fwrite(zero_bytes, sizeof zero_bytes, 1, f); } } + /** * \brief Read the sector bitmap for a block. - * - * If the block is sparse, the sector bitmap in memory will be + * + * If the block is sparse, the sector bitmap in memory will be * zeroed. Otherwise, the sector bitmap is read from the VHD file. - * + * * \param [in] vhdm MiniVHD data structure * \param [in] blk The block for which to read the sector bitmap from */ -static void mvhd_read_sect_bitmap(MVHDMeta* vhdm, int blk) { +static void +read_sect_bitmap(MVHDMeta* vhdm, int blk) +{ if (vhdm->block_offset[blk] != MVHD_SPARSE_BLK) { mvhd_fseeko64(vhdm->f, (uint64_t)vhdm->block_offset[blk] * MVHD_SECTOR_SIZE, SEEK_SET); - fread(vhdm->bitmap.curr_bitmap, vhdm->bitmap.sector_count * MVHD_SECTOR_SIZE, 1, vhdm->f); + (void) !fread(vhdm->bitmap.curr_bitmap, vhdm->bitmap.sector_count * MVHD_SECTOR_SIZE, 1, vhdm->f); } else { memset(vhdm->bitmap.curr_bitmap, 0, vhdm->bitmap.sector_count * MVHD_SECTOR_SIZE); } + vhdm->bitmap.curr_block = blk; } + /** * \brief Write the current sector bitmap in memory to file - * + * * \param [in] vhdm MiniVHD data structure */ -static void mvhd_write_curr_sect_bitmap(MVHDMeta* vhdm) { +static void +write_curr_sect_bitmap(MVHDMeta* vhdm) +{ if (vhdm->bitmap.curr_block >= 0) { int64_t abs_offset = (int64_t)vhdm->block_offset[vhdm->bitmap.curr_block] * MVHD_SECTOR_SIZE; mvhd_fseeko64(vhdm->f, abs_offset, SEEK_SET); @@ -82,45 +129,55 @@ static void mvhd_write_curr_sect_bitmap(MVHDMeta* vhdm) { } } + /** * \brief Write block offset from memory into file - * + * * \param [in] vhdm MiniVHD data structure * \param [in] blk The block for which to write the offset for */ -static void mvhd_write_bat_entry(MVHDMeta* vhdm, int blk) { +static void +write_bat_entry(MVHDMeta* vhdm, int blk) +{ uint64_t table_offset = vhdm->sparse.bat_offset + ((uint64_t)blk * sizeof *vhdm->block_offset); uint32_t offset = mvhd_to_be32(vhdm->block_offset[blk]); + mvhd_fseeko64(vhdm->f, table_offset, SEEK_SET); fwrite(&offset, sizeof offset, 1, vhdm->f); } + /** * \brief Create an empty block in a sparse or differencing VHD image - * - * VHD images store data in blocks, which are typically 4096 sectors in size - * (~2MB). These blocks may be stored on disk in any order. Blocks are created + * + * VHD images store data in blocks, which are typically 4096 sectors in size + * (~2MB). These blocks may be stored on disk in any order. Blocks are created * on demand when required. - * - * This function creates new, empty blocks, by replacing the footer at the end of the file + * + * This function creates new, empty blocks, by replacing the footer at the end of the file * and then re-inserting the footer at the new file end. The BAT table entry for the * new block is updated with the new offset. - * + * * \param [in] vhdm MiniVHD data structure * \param [in] blk The block number to create */ -static void mvhd_create_block(MVHDMeta* vhdm, int blk) { +static void +create_block(MVHDMeta* vhdm, int blk) +{ uint8_t footer[MVHD_FOOTER_SIZE]; + /* Seek to where the footer SHOULD be */ mvhd_fseeko64(vhdm->f, -MVHD_FOOTER_SIZE, SEEK_END); - fread(footer, sizeof footer, 1, vhdm->f); + (void) !fread(footer, sizeof footer, 1, vhdm->f); mvhd_fseeko64(vhdm->f, -MVHD_FOOTER_SIZE, SEEK_END); + if (!mvhd_is_conectix_str(footer)) { /* Oh dear. We use the header instead, since something has gone wrong at the footer */ mvhd_fseeko64(vhdm->f, 0, SEEK_SET); - fread(footer, sizeof footer, 1, vhdm->f); + (void) !fread(footer, sizeof footer, 1, vhdm->f); mvhd_fseeko64(vhdm->f, 0, SEEK_END); } + int64_t abs_offset = mvhd_ftello64(vhdm->f); if (abs_offset % MVHD_SECTOR_SIZE != 0) { /* Yikes! We're supposed to be on a sector boundary. Add some padding */ @@ -131,83 +188,107 @@ static void mvhd_create_block(MVHDMeta* vhdm, int blk) { } abs_offset += padding_amount; } + uint32_t sect_offset = (uint32_t)(abs_offset / MVHD_SECTOR_SIZE); int blk_size_sectors = vhdm->sparse.block_sz / MVHD_SECTOR_SIZE; mvhd_write_empty_sectors(vhdm->f, vhdm->bitmap.sector_count + blk_size_sectors); + /* Add a bit of padding. That's what Windows appears to do, although it's not strictly necessary... */ mvhd_write_empty_sectors(vhdm->f, 5); + /* And we finish with the footer */ fwrite(footer, sizeof footer, 1, vhdm->f); + /* We no longer have a sparse block. Update that BAT! */ vhdm->block_offset[blk] = sect_offset; - mvhd_write_bat_entry(vhdm, blk); + write_bat_entry(vhdm, blk); } -int mvhd_fixed_read(MVHDMeta* vhdm, uint32_t offset, int num_sectors, void* out_buff) { + +int +mvhd_fixed_read(MVHDMeta* vhdm, uint32_t offset, int num_sectors, void* out_buff) { int64_t addr; int transfer_sectors, truncated_sectors; uint32_t total_sectors = (uint32_t)(vhdm->footer.curr_sz / MVHD_SECTOR_SIZE); - mvhd_check_sectors(offset, num_sectors, total_sectors, &transfer_sectors, &truncated_sectors); + + check_sectors(offset, num_sectors, total_sectors, &transfer_sectors, &truncated_sectors); + addr = (int64_t)offset * MVHD_SECTOR_SIZE; mvhd_fseeko64(vhdm->f, addr, SEEK_SET); - fread(out_buff, transfer_sectors*MVHD_SECTOR_SIZE, 1, vhdm->f); + (void) !fread(out_buff, transfer_sectors*MVHD_SECTOR_SIZE, 1, vhdm->f); + return truncated_sectors; } -int mvhd_sparse_read(MVHDMeta* vhdm, uint32_t offset, int num_sectors, void* out_buff) { + +int +mvhd_sparse_read(MVHDMeta* vhdm, uint32_t offset, int num_sectors, void* out_buff) +{ int transfer_sectors, truncated_sectors; uint32_t total_sectors = (uint32_t)(vhdm->footer.curr_sz / MVHD_SECTOR_SIZE); - mvhd_check_sectors(offset, num_sectors, total_sectors, &transfer_sectors, &truncated_sectors); + + check_sectors(offset, num_sectors, total_sectors, &transfer_sectors, &truncated_sectors); + uint8_t* buff = (uint8_t*)out_buff; int64_t addr; uint32_t s, ls; int blk, prev_blk, sib; ls = offset + transfer_sectors; prev_blk = -1; + for (s = offset; s < ls; s++) { blk = s / vhdm->sect_per_block; sib = s % vhdm->sect_per_block; if (blk != prev_blk) { prev_blk = blk; if (vhdm->bitmap.curr_block != blk) { - mvhd_read_sect_bitmap(vhdm, blk); + read_sect_bitmap(vhdm, blk); mvhd_fseeko64(vhdm->f, (uint64_t)sib * MVHD_SECTOR_SIZE, SEEK_CUR); } else { addr = ((int64_t)vhdm->block_offset[blk] + vhdm->bitmap.sector_count + sib) * MVHD_SECTOR_SIZE; mvhd_fseeko64(vhdm->f, addr, SEEK_SET); } - } + } + if (VHD_TESTBIT(vhdm->bitmap.curr_bitmap, sib)) { - fread(buff, MVHD_SECTOR_SIZE, 1, vhdm->f); + (void) !fread(buff, MVHD_SECTOR_SIZE, 1, vhdm->f); } else { memset(buff, 0, MVHD_SECTOR_SIZE); mvhd_fseeko64(vhdm->f, MVHD_SECTOR_SIZE, SEEK_CUR); } buff += MVHD_SECTOR_SIZE; } + return truncated_sectors; } -int mvhd_diff_read(MVHDMeta* vhdm, uint32_t offset, int num_sectors, void* out_buff) { + +int +mvhd_diff_read(MVHDMeta* vhdm, uint32_t offset, int num_sectors, void* out_buff) +{ int transfer_sectors, truncated_sectors; uint32_t total_sectors = (uint32_t)(vhdm->footer.curr_sz / MVHD_SECTOR_SIZE); - mvhd_check_sectors(offset, num_sectors, total_sectors, &transfer_sectors, &truncated_sectors); + + check_sectors(offset, num_sectors, total_sectors, &transfer_sectors, &truncated_sectors); + uint8_t* buff = (uint8_t*)out_buff; MVHDMeta* curr_vhdm = vhdm; uint32_t s, ls; int blk, sib; ls = offset + transfer_sectors; + for (s = offset; s < ls; s++) { while (curr_vhdm->footer.disk_type == MVHD_TYPE_DIFF) { blk = s / curr_vhdm->sect_per_block; sib = s % curr_vhdm->sect_per_block; if (curr_vhdm->bitmap.curr_block != blk) { - mvhd_read_sect_bitmap(curr_vhdm, blk); + read_sect_bitmap(curr_vhdm, blk); } if (!VHD_TESTBIT(curr_vhdm->bitmap.curr_bitmap, sib)) { curr_vhdm = curr_vhdm->parent; } else { break; } } + /* We handle actual sector reading using the fixed or sparse functions, as a differencing VHD is also a sparse VHD */ if (curr_vhdm->footer.disk_type == MVHD_TYPE_DIFF || curr_vhdm->footer.disk_type == MVHD_TYPE_DYNAMIC) { @@ -215,49 +296,65 @@ int mvhd_diff_read(MVHDMeta* vhdm, uint32_t offset, int num_sectors, void* out_b } else { mvhd_fixed_read(curr_vhdm, s, 1, buff); } + curr_vhdm = vhdm; buff += MVHD_SECTOR_SIZE; } + return truncated_sectors; } -int mvhd_fixed_write(MVHDMeta* vhdm, uint32_t offset, int num_sectors, void* in_buff) { + +int +mvhd_fixed_write(MVHDMeta* vhdm, uint32_t offset, int num_sectors, void* in_buff) +{ int64_t addr; int transfer_sectors, truncated_sectors; uint32_t total_sectors = (uint32_t)(vhdm->footer.curr_sz / MVHD_SECTOR_SIZE); - mvhd_check_sectors(offset, num_sectors, total_sectors, &transfer_sectors, &truncated_sectors); + + check_sectors(offset, num_sectors, total_sectors, &transfer_sectors, &truncated_sectors); + addr = (int64_t)offset * MVHD_SECTOR_SIZE; mvhd_fseeko64(vhdm->f, addr, SEEK_SET); fwrite(in_buff, transfer_sectors*MVHD_SECTOR_SIZE, 1, vhdm->f); + return truncated_sectors; } -int mvhd_sparse_diff_write(MVHDMeta* vhdm, uint32_t offset, int num_sectors, void* in_buff) { + +int +mvhd_sparse_diff_write(MVHDMeta* vhdm, uint32_t offset, int num_sectors, void* in_buff) +{ int transfer_sectors, truncated_sectors; uint32_t total_sectors = (uint32_t)(vhdm->footer.curr_sz / MVHD_SECTOR_SIZE); - mvhd_check_sectors(offset, num_sectors, total_sectors, &transfer_sectors, &truncated_sectors); + + check_sectors(offset, num_sectors, total_sectors, &transfer_sectors, &truncated_sectors); + uint8_t* buff = (uint8_t*)in_buff; int64_t addr; uint32_t s, ls; int blk, prev_blk, sib; ls = offset + transfer_sectors; prev_blk = -1; + for (s = offset; s < ls; s++) { blk = s / vhdm->sect_per_block; sib = s % vhdm->sect_per_block; - if (vhdm->bitmap.curr_block != blk && prev_blk >= 0) { + if (vhdm->bitmap.curr_block != blk && prev_blk >= 0) { /* Write the sector bitmap for the previous block, before we replace it. */ - mvhd_write_curr_sect_bitmap(vhdm); + write_curr_sect_bitmap(vhdm); } + if (vhdm->block_offset[blk] == MVHD_SPARSE_BLK) { /* "read" the sector bitmap first, before creating a new block, as the bitmap will be zero either way */ - mvhd_read_sect_bitmap(vhdm, blk); - mvhd_create_block(vhdm, blk); - } + read_sect_bitmap(vhdm, blk); + create_block(vhdm, blk); + } + if (blk != prev_blk) { - if (vhdm->bitmap.curr_block != blk) { - mvhd_read_sect_bitmap(vhdm, blk); + if (vhdm->bitmap.curr_block != blk) { + read_sect_bitmap(vhdm, blk); mvhd_fseeko64(vhdm->f, (uint64_t)sib * MVHD_SECTOR_SIZE, SEEK_CUR); } else { addr = ((int64_t)vhdm->block_offset[blk] + vhdm->bitmap.sector_count + sib) * MVHD_SECTOR_SIZE; @@ -265,15 +362,26 @@ int mvhd_sparse_diff_write(MVHDMeta* vhdm, uint32_t offset, int num_sectors, voi } prev_blk = blk; } + fwrite(buff, MVHD_SECTOR_SIZE, 1, vhdm->f); VHD_SETBIT(vhdm->bitmap.curr_bitmap, sib); buff += MVHD_SECTOR_SIZE; } + /* And write the sector bitmap for the last block we visited to disk */ - mvhd_write_curr_sect_bitmap(vhdm); + write_curr_sect_bitmap(vhdm); + return truncated_sectors; } -int mvhd_noop_write(MVHDMeta* vhdm, uint32_t offset, int num_sectors, void* in_buff) { + +int +mvhd_noop_write(MVHDMeta* vhdm, uint32_t offset, int num_sectors, void* in_buff) +{ + (void)vhdm; + (void)offset; + (void)num_sectors; + (void)in_buff; + return 0; } diff --git a/src/disk/minivhd/minivhd_io.h b/src/disk/minivhd/minivhd_io.h deleted file mode 100644 index cdbfa6d77..000000000 --- a/src/disk/minivhd/minivhd_io.h +++ /dev/null @@ -1,132 +0,0 @@ -#ifndef MINIVHD_IO_H -#define MINIVHD_IO_H -#include "minivhd.h" - -/** - * \brief Write zero filled sectors to file. - * - * Note, the caller should set the file position before calling this - * function for correct operation. - * - * \param [in] f File to write sectors to - * \param [in] sector_count The number of sectors to write - */ -void mvhd_write_empty_sectors(FILE* f, int sector_count); - -/** - * \brief Read a fixed VHD image - * - * Fixed VHD images are essentially raw image files with a footer tacked on - * the end. They are therefore straightforward to write - * - * \param [in] vhdm MiniVHD data structure - * \param [in] offset Sector offset to read from - * \param [in] num_sectors The desired number of sectors to read - * \param [out] out_buff An output buffer to store read sectors. Must be - * large enough to hold num_sectors worth of sectors. - * - * \retval 0 num_sectors were read from file - * \retval >0 < num_sectors were read from file - */ -int mvhd_fixed_read(MVHDMeta* vhdm, uint32_t offset, int num_sectors, void* out_buff); - -/** - * \brief Read a sparse VHD image - * - * Sparse, or dynamic images are VHD images that grow as data is written to them. - * - * This function implements the logic to read sectors from the file, taking into - * account the fact that blocks may be stored on disk in any order, and that the - * read could cross block boundaries. - * - * \param [in] vhdm MiniVHD data structure - * \param [in] offset Sector offset to read from - * \param [in] num_sectors The desired number of sectors to read - * \param [out] out_buff An output buffer to store read sectors. Must be - * large enough to hold num_sectors worth of sectors. - * - * \retval 0 num_sectors were read from file - * \retval >0 < num_sectors were read from file - */ -int mvhd_sparse_read(MVHDMeta* vhdm, uint32_t offset, int num_sectors, void* out_buff); - -/** - * \brief Read a differencing VHD image - * - * Differencing images are a variant of a sparse image. They contain the grow-on-demand - * properties of sparse images, but also reference a parent image. Data is read from the - * child image only if it is newer than the data stored in the parent image. - * - * This function implements the logic to read sectors from the child, or a parent image. - * Differencing images may have a differencing image as a parent, creating a chain of images. - * There is no theoretical chain length limit, although I do not consider long chains to be - * advisable. Verifying the parent-child relationship is not very robust. - * - * \param [in] vhdm MiniVHD data structure - * \param [in] offset Sector offset to read from - * \param [in] num_sectors The desired number of sectors to read - * \param [out] out_buff An output buffer to store read sectors. Must be - * large enough to hold num_sectors worth of sectors. - * - * \retval 0 num_sectors were read from file - * \retval >0 < num_sectors were read from file - */ -int mvhd_diff_read(MVHDMeta* vhdm, uint32_t offset, int num_sectors, void* out_buff); - -/** - * \brief Write to a fixed VHD image - * - * Fixed VHD images are essentially raw image files with a footer tacked on - * the end. They are therefore straightforward to write - * - * \param [in] vhdm MiniVHD data structure - * \param [in] offset Sector offset to write to - * \param [in] num_sectors The desired number of sectors to write - * \param [in] in_buff A source buffer to write sectors from. Must be - * large enough to hold num_sectors worth of sectors. - * - * \retval 0 num_sectors were written to file - * \retval >0 < num_sectors were written to file - */ -int mvhd_fixed_write(MVHDMeta* vhdm, uint32_t offset, int num_sectors, void* in_buff); - -/** - * \brief Write to a sparse or differencing VHD image - * - * Sparse, or dynamic images are VHD images that grow as data is written to them. - * - * Differencing images are a variant of a sparse image. They contain the grow-on-demand - * properties of sparse images, but also reference a parent image. Data is always written - * to the child image. This makes writing to differencing images essentially identical to - * writing to sparse images, hence they use the same function. - * - * This function implements the logic to write sectors to the file, taking into - * account the fact that blocks may be stored on disk in any order, and that the - * write operation could cross block boundaries. - * - * \param [in] vhdm MiniVHD data structure - * \param [in] offset Sector offset to write to - * \param [in] num_sectors The desired number of sectors to write - * \param [in] in_buff A source buffer to write sectors from. Must be - * large enough to hold num_sectors worth of sectors. - * - * \retval 0 num_sectors were written to file - * \retval >0 < num_sectors were written to file - */ -int mvhd_sparse_diff_write(MVHDMeta* vhdm, uint32_t offset, int num_sectors, void* in_buff); - -/** - * \brief A no-op function to "write" to read-only VHD images - * - * \param [in] vhdm MiniVHD data structure - * \param [in] offset Sector offset to write to - * \param [in] num_sectors The desired number of sectors to write - * \param [in] in_buff A source buffer to write sectors from. Must be - * large enough to hold num_sectors worth of sectors. - * - * \retval 0 num_sectors were written to file - * \retval >0 < num_sectors were written to file - */ -int mvhd_noop_write(MVHDMeta* vhdm, uint32_t offset, int num_sectors, void* in_buff); - -#endif \ No newline at end of file diff --git a/src/disk/minivhd/minivhd_struct_rw.c b/src/disk/minivhd/minivhd_struct_rw.c deleted file mode 100644 index c77fa600a..000000000 --- a/src/disk/minivhd/minivhd_struct_rw.c +++ /dev/null @@ -1,167 +0,0 @@ -/** - * \file - * \brief Header and footer serialize/deserialize functions - */ -#ifndef _FILE_OFFSET_BITS -#define _FILE_OFFSET_BITS 64 -#endif -#include -#include -#include -#include -#include -#include "minivhd_util.h" -#include "minivhd_internal.h" - -/* Read data from footer into the struct members, swapping endian where necessary - Note: order matters here! We must read each field in the order the struct is in. - Doing this may be less elegant than performing a memcpy to a packed struct, but - it avoids potential data alignment issues, and the endian swapping allows us to - use the fields directly. */ - -static void mvhd_next_buffer_to_struct(void* struct_memb, size_t memb_size, bool req_endian, uint8_t** buffer); -static void mvhd_next_struct_to_buffer(void* struct_memb, size_t memb_size, bool req_endian, uint8_t** buffer); - -/** - * \brief Get the next field from a buffer and store it in a struct member, converting endian if necessary - * - * \param [out] struct_memb struct member to save the field to - * \param [in] memb_size the size of struct_memb, in bytes - * \param [in] req_endian is the field a value that requires endian conversion (eg: uint16, uint32) - * \param [in] buffer the buffer from which fields are read from. Will be advanced at the end of the function call - */ -static void mvhd_next_buffer_to_struct(void* struct_memb, size_t memb_size, bool req_endian, uint8_t** buffer) { - memcpy(struct_memb, *buffer, memb_size); - if (req_endian) { - switch (memb_size) { - case 2: - *(uint16_t*)(struct_memb) = mvhd_from_be16(*(uint16_t*)(struct_memb)); - break; - case 4: - *(uint32_t*)(struct_memb) = mvhd_from_be32(*(uint32_t*)(struct_memb)); - break; - case 8: - *(uint64_t*)(struct_memb) = mvhd_from_be64(*(uint64_t*)(struct_memb)); - break; - } - } - *buffer += memb_size; -} - -/** - * \brief Save a struct member into a buffer, converting endian if necessary - * - * \param [in] struct_memb struct member read from - * \param [in] memb_size the size of struct_memb, in bytes - * \param [in] req_endian is the field a value that requires endian conversion (eg: uint16, uint32) - * \param [out] buffer the buffer from which struct member is saved to. Will be advanced at the end of the function call - */ -static void mvhd_next_struct_to_buffer(void* struct_memb, size_t memb_size, bool req_endian, uint8_t** buffer) { - uint8_t *buf_ptr = *buffer; - memcpy(buf_ptr, struct_memb, memb_size); - if (req_endian) { - switch (memb_size) { - case 2: - *((uint16_t*)buf_ptr) = mvhd_to_be16(*(uint16_t*)(struct_memb)); - break; - case 4: - *((uint32_t*)buf_ptr) = mvhd_to_be32(*(uint32_t*)(struct_memb)); - break; - case 8: - *((uint64_t*)buf_ptr) = mvhd_to_be64(*(uint64_t*)(struct_memb)); - break; - } - } - buf_ptr += memb_size; - *buffer = buf_ptr; -} - -void mvhd_buffer_to_footer(MVHDFooter* footer, uint8_t* buffer) { - uint8_t* buff_ptr = buffer; - mvhd_next_buffer_to_struct(&footer->cookie, sizeof footer->cookie, false, &buff_ptr); - mvhd_next_buffer_to_struct(&footer->features, sizeof footer->features, true, &buff_ptr); - mvhd_next_buffer_to_struct(&footer->fi_fmt_vers, sizeof footer->fi_fmt_vers, true, &buff_ptr); - mvhd_next_buffer_to_struct(&footer->data_offset, sizeof footer->data_offset, true, &buff_ptr); - mvhd_next_buffer_to_struct(&footer->timestamp, sizeof footer->timestamp, true, &buff_ptr); - mvhd_next_buffer_to_struct(&footer->cr_app, sizeof footer->cr_app, false, &buff_ptr); - mvhd_next_buffer_to_struct(&footer->cr_vers, sizeof footer->cr_vers, true, &buff_ptr); - mvhd_next_buffer_to_struct(&footer->cr_host_os, sizeof footer->cr_host_os, false, &buff_ptr); - mvhd_next_buffer_to_struct(&footer->orig_sz, sizeof footer->orig_sz, true, &buff_ptr); - mvhd_next_buffer_to_struct(&footer->curr_sz, sizeof footer->curr_sz, true, &buff_ptr); - mvhd_next_buffer_to_struct(&footer->geom.cyl, sizeof footer->geom.cyl, true, &buff_ptr); - mvhd_next_buffer_to_struct(&footer->geom.heads, sizeof footer->geom.heads, false, &buff_ptr); - mvhd_next_buffer_to_struct(&footer->geom.spt, sizeof footer->geom.spt, false, &buff_ptr); - mvhd_next_buffer_to_struct(&footer->disk_type, sizeof footer->disk_type, true, &buff_ptr); - mvhd_next_buffer_to_struct(&footer->checksum, sizeof footer->checksum, true, &buff_ptr); - mvhd_next_buffer_to_struct(&footer->uuid, sizeof footer->uuid, false, &buff_ptr); - mvhd_next_buffer_to_struct(&footer->saved_st, sizeof footer->saved_st, false, &buff_ptr); - mvhd_next_buffer_to_struct(&footer->reserved, sizeof footer->reserved, false, &buff_ptr); -} - -void mvhd_footer_to_buffer(MVHDFooter* footer, uint8_t* buffer) { - uint8_t* buff_ptr = buffer; - mvhd_next_struct_to_buffer(&footer->cookie, sizeof footer->cookie, false, &buff_ptr); - mvhd_next_struct_to_buffer(&footer->features, sizeof footer->features, true, &buff_ptr); - mvhd_next_struct_to_buffer(&footer->fi_fmt_vers, sizeof footer->fi_fmt_vers, true, &buff_ptr); - mvhd_next_struct_to_buffer(&footer->data_offset, sizeof footer->data_offset, true, &buff_ptr); - mvhd_next_struct_to_buffer(&footer->timestamp, sizeof footer->timestamp, true, &buff_ptr); - mvhd_next_struct_to_buffer(&footer->cr_app, sizeof footer->cr_app, false, &buff_ptr); - mvhd_next_struct_to_buffer(&footer->cr_vers, sizeof footer->cr_vers, true, &buff_ptr); - mvhd_next_struct_to_buffer(&footer->cr_host_os, sizeof footer->cr_host_os, false, &buff_ptr); - mvhd_next_struct_to_buffer(&footer->orig_sz, sizeof footer->orig_sz, true, &buff_ptr); - mvhd_next_struct_to_buffer(&footer->curr_sz, sizeof footer->curr_sz, true, &buff_ptr); - mvhd_next_struct_to_buffer(&footer->geom.cyl, sizeof footer->geom.cyl, true, &buff_ptr); - mvhd_next_struct_to_buffer(&footer->geom.heads, sizeof footer->geom.heads, false, &buff_ptr); - mvhd_next_struct_to_buffer(&footer->geom.spt, sizeof footer->geom.spt, false, &buff_ptr); - mvhd_next_struct_to_buffer(&footer->disk_type, sizeof footer->disk_type, true, &buff_ptr); - mvhd_next_struct_to_buffer(&footer->checksum, sizeof footer->checksum, true, &buff_ptr); - mvhd_next_struct_to_buffer(&footer->uuid, sizeof footer->uuid, false, &buff_ptr); - mvhd_next_struct_to_buffer(&footer->saved_st, sizeof footer->saved_st, false, &buff_ptr); - mvhd_next_struct_to_buffer(&footer->reserved, sizeof footer->reserved, false, &buff_ptr); -} - -void mvhd_buffer_to_header(MVHDSparseHeader* header, uint8_t* buffer) { - uint8_t* buff_ptr = buffer; - mvhd_next_buffer_to_struct(&header->cookie, sizeof header->cookie, false, &buff_ptr); - mvhd_next_buffer_to_struct(&header->data_offset, sizeof header->data_offset, true, &buff_ptr); - mvhd_next_buffer_to_struct(&header->bat_offset, sizeof header->bat_offset, true, &buff_ptr); - mvhd_next_buffer_to_struct(&header->head_vers, sizeof header->head_vers, true, &buff_ptr); - mvhd_next_buffer_to_struct(&header->max_bat_ent, sizeof header->max_bat_ent, true, &buff_ptr); - mvhd_next_buffer_to_struct(&header->block_sz, sizeof header->block_sz, true, &buff_ptr); - mvhd_next_buffer_to_struct(&header->checksum, sizeof header->checksum, true, &buff_ptr); - mvhd_next_buffer_to_struct(&header->par_uuid, sizeof header->par_uuid, false, &buff_ptr); - mvhd_next_buffer_to_struct(&header->par_timestamp, sizeof header->par_timestamp, true, &buff_ptr); - mvhd_next_buffer_to_struct(&header->reserved_1, sizeof header->reserved_1, true, &buff_ptr); - mvhd_next_buffer_to_struct(&header->par_utf16_name, sizeof header->par_utf16_name, false, &buff_ptr); - for (int i = 0; i < 8; i++) { - mvhd_next_buffer_to_struct(&header->par_loc_entry[i].plat_code, sizeof header->par_loc_entry[i].plat_code, true, &buff_ptr); - mvhd_next_buffer_to_struct(&header->par_loc_entry[i].plat_data_space, sizeof header->par_loc_entry[i].plat_data_space, true, &buff_ptr); - mvhd_next_buffer_to_struct(&header->par_loc_entry[i].plat_data_len, sizeof header->par_loc_entry[i].plat_data_len, true, &buff_ptr); - mvhd_next_buffer_to_struct(&header->par_loc_entry[i].reserved, sizeof header->par_loc_entry[i].reserved, true, &buff_ptr); - mvhd_next_buffer_to_struct(&header->par_loc_entry[i].plat_data_offset, sizeof header->par_loc_entry[i].plat_data_offset, true, &buff_ptr); - } - mvhd_next_buffer_to_struct(&header->reserved_2, sizeof header->reserved_2, false, &buff_ptr); -} - -void mvhd_header_to_buffer(MVHDSparseHeader* header, uint8_t* buffer) { - uint8_t* buff_ptr = buffer; - mvhd_next_struct_to_buffer(&header->cookie, sizeof header->cookie, false, &buff_ptr); - mvhd_next_struct_to_buffer(&header->data_offset, sizeof header->data_offset, true, &buff_ptr); - mvhd_next_struct_to_buffer(&header->bat_offset, sizeof header->bat_offset, true, &buff_ptr); - mvhd_next_struct_to_buffer(&header->head_vers, sizeof header->head_vers, true, &buff_ptr); - mvhd_next_struct_to_buffer(&header->max_bat_ent, sizeof header->max_bat_ent, true, &buff_ptr); - mvhd_next_struct_to_buffer(&header->block_sz, sizeof header->block_sz, true, &buff_ptr); - mvhd_next_struct_to_buffer(&header->checksum, sizeof header->checksum, true, &buff_ptr); - mvhd_next_struct_to_buffer(&header->par_uuid, sizeof header->par_uuid, false, &buff_ptr); - mvhd_next_struct_to_buffer(&header->par_timestamp, sizeof header->par_timestamp, true, &buff_ptr); - mvhd_next_struct_to_buffer(&header->reserved_1, sizeof header->reserved_1, true, &buff_ptr); - mvhd_next_struct_to_buffer(&header->par_utf16_name, sizeof header->par_utf16_name, false, &buff_ptr); - for (int i = 0; i < 8; i++) { - mvhd_next_struct_to_buffer(&header->par_loc_entry[i].plat_code, sizeof header->par_loc_entry[i].plat_code, true, &buff_ptr); - mvhd_next_struct_to_buffer(&header->par_loc_entry[i].plat_data_space, sizeof header->par_loc_entry[i].plat_data_space, true, &buff_ptr); - mvhd_next_struct_to_buffer(&header->par_loc_entry[i].plat_data_len, sizeof header->par_loc_entry[i].plat_data_len, true, &buff_ptr); - mvhd_next_struct_to_buffer(&header->par_loc_entry[i].reserved, sizeof header->par_loc_entry[i].reserved, true, &buff_ptr); - mvhd_next_struct_to_buffer(&header->par_loc_entry[i].plat_data_offset, sizeof header->par_loc_entry[i].plat_data_offset, true, &buff_ptr); - } - mvhd_next_struct_to_buffer(&header->reserved_2, sizeof header->reserved_2, false, &buff_ptr); -} \ No newline at end of file diff --git a/src/disk/minivhd/minivhd_struct_rw.h b/src/disk/minivhd/minivhd_struct_rw.h deleted file mode 100644 index ee49bb696..000000000 --- a/src/disk/minivhd/minivhd_struct_rw.h +++ /dev/null @@ -1,38 +0,0 @@ -#ifndef MINIVHD_STRUCT_RW_H -#define MINIVHD_STRUCT_RW_H - -#include "minivhd_internal.h" - -/** - * \brief Save the contents of a VHD footer from a buffer to a struct - * - * \param [out] footer save contents of buffer into footer - * \param [in] buffer VHD footer in raw bytes - */ -void mvhd_buffer_to_footer(MVHDFooter* footer, uint8_t* buffer); - -/** - * \brief Save the contents of a VHD sparse header from a buffer to a struct - * - * \param [out] header save contents of buffer into header - * \param [in] buffer VHD header in raw bytes - */ -void mvhd_buffer_to_header(MVHDSparseHeader* header, uint8_t* buffer); - -/** - * \brief Save the contents of a VHD footer struct to a buffer - * - * \param [in] footer save contents of struct into buffer - * \param [out] buffer VHD footer in raw bytes - */ -void mvhd_footer_to_buffer(MVHDFooter* footer, uint8_t* buffer); - -/** - * \brief Save the contents of a VHD sparse header struct to a buffer - * - * \param [in] header save contents of struct into buffer - * \param [out] buffer VHD sparse header in raw bytes - */ -void mvhd_header_to_buffer(MVHDSparseHeader* header, uint8_t* buffer); - -#endif \ No newline at end of file diff --git a/src/disk/minivhd/minivhd_util.c b/src/disk/minivhd/minivhd_util.c index 5bfc59915..dd3244322 100644 --- a/src/disk/minivhd/minivhd_util.c +++ b/src/disk/minivhd/minivhd_util.c @@ -1,46 +1,90 @@ -/** - * \file - * \brief Utility functions +/* + * MiniVHD Minimalist VHD implementation in C. + * + * This file is part of the MiniVHD Project. + * + * Utility functions. + * + * Version: @(#)util.c 1.0.4 2021/04/16 + * + * Author: Sherman Perry, + * + * Copyright 2019-2021 Sherman Perry. + * + * MIT License + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documenta- + * tion files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, + * copy, modify, merge, publish, distribute, sublicense, and/or + * sell copies of the Software, and to permit persons to whom + * the Software is furnished to do so, subject to the following + * conditions: + * + * The above copyright notice and this permission notice shall + * be included in all copies or substantial portions of the + * Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF O R IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. */ #ifndef _FILE_OFFSET_BITS -#define _FILE_OFFSET_BITS 64 +# define _FILE_OFFSET_BITS 64 #endif #include #include #include #include +#include #include #include #include #include -#include "libxml2_encoding.h" -#include "minivhd_internal.h" -#include "minivhd_util.h" +#include "minivhd.h" +#include "internal.h" +#include "xml2_encoding.h" -const char MVHD_CONECTIX_COOKIE[] = "conectix"; -const char MVHD_CREATOR[] = "pcem"; -const char MVHD_CREATOR_HOST_OS[] = "Wi2k"; -const char MVHD_CXSPARSE_COOKIE[] = "cxsparse"; -uint16_t mvhd_from_be16(uint16_t val) { +uint16_t +mvhd_from_be16(uint16_t val) +{ uint8_t *tmp = (uint8_t*)&val; uint16_t ret = 0; + ret |= (uint16_t)tmp[0] << 8; ret |= (uint16_t)tmp[1] << 0; + return ret; } -uint32_t mvhd_from_be32(uint32_t val) { + + +uint32_t +mvhd_from_be32(uint32_t val) +{ uint8_t *tmp = (uint8_t*)&val; uint32_t ret = 0; + ret = (uint32_t)tmp[0] << 24; ret |= (uint32_t)tmp[1] << 16; ret |= (uint32_t)tmp[2] << 8; ret |= (uint32_t)tmp[3] << 0; + return ret; } -uint64_t mvhd_from_be64(uint64_t val) { + + +uint64_t +mvhd_from_be64(uint64_t val) +{ uint8_t *tmp = (uint8_t*)&val; uint64_t ret = 0; + ret = (uint64_t)tmp[0] << 56; ret |= (uint64_t)tmp[1] << 48; ret |= (uint64_t)tmp[2] << 40; @@ -49,27 +93,45 @@ uint64_t mvhd_from_be64(uint64_t val) { ret |= (uint64_t)tmp[5] << 16; ret |= (uint64_t)tmp[6] << 8; ret |= (uint64_t)tmp[7] << 0; + return ret; } -uint16_t mvhd_to_be16(uint16_t val) { + + +uint16_t +mvhd_to_be16(uint16_t val) +{ uint16_t ret = 0; uint8_t *tmp = (uint8_t*)&ret; + tmp[0] = (val & 0xff00) >> 8; tmp[1] = (val & 0x00ff) >> 0; + return ret; } -uint32_t mvhd_to_be32(uint32_t val) { + + +uint32_t +mvhd_to_be32(uint32_t val) +{ uint32_t ret = 0; uint8_t *tmp = (uint8_t*)&ret; + tmp[0] = (val & 0xff000000) >> 24; tmp[1] = (val & 0x00ff0000) >> 16; tmp[2] = (val & 0x0000ff00) >> 8; tmp[3] = (val & 0x000000ff) >> 0; + return ret; } -uint64_t mvhd_to_be64(uint64_t val) { + + +uint64_t +mvhd_to_be64(uint64_t val) +{ uint64_t ret = 0; uint8_t *tmp = (uint8_t*)&ret; + tmp[0] = (uint8_t)((val & 0xff00000000000000) >> 56); tmp[1] = (uint8_t)((val & 0x00ff000000000000) >> 48); tmp[2] = (uint8_t)((val & 0x0000ff0000000000) >> 40); @@ -78,21 +140,17 @@ uint64_t mvhd_to_be64(uint64_t val) { tmp[5] = (uint8_t)((val & 0x0000000000ff0000) >> 16); tmp[6] = (uint8_t)((val & 0x000000000000ff00) >> 8); tmp[7] = (uint8_t)((val & 0x00000000000000ff) >> 0); + return ret; } -bool mvhd_is_conectix_str(const void* buffer) { - if (strncmp(buffer, MVHD_CONECTIX_COOKIE, strlen(MVHD_CONECTIX_COOKIE)) == 0) { - return true; - } else { - return false; - } -} -void mvhd_generate_uuid(uint8_t* uuid) +void +mvhd_generate_uuid(uint8_t* uuid) { /* We aren't doing crypto here, so using system time as seed should be good enough */ srand((unsigned int)time(0)); + for (int n = 0; n < 16; n++) { uuid[n] = rand(); } @@ -102,34 +160,50 @@ void mvhd_generate_uuid(uint8_t* uuid) uuid[8] |= 0x80; /* Variant 1 */ } -uint32_t vhd_calc_timestamp(void) -{ - time_t start_time; - time_t curr_time; - double vhd_time; - start_time = MVHD_START_TS; /* 1 Jan 2000 00:00 */ - curr_time = time(NULL); - vhd_time = difftime(curr_time, start_time); - return (uint32_t)vhd_time; -} -uint32_t mvhd_epoch_to_vhd_ts(time_t ts) { - time_t start_time = MVHD_START_TS; - if (ts < start_time) { - return start_time; - } - double vhd_time = difftime(ts, start_time); +uint32_t +vhd_calc_timestamp(void) +{ + time_t start_time; + time_t curr_time; + double vhd_time; + + start_time = MVHD_START_TS; /* 1 Jan 2000 00:00 */ + curr_time = time(NULL); + vhd_time = difftime(curr_time, start_time); + return (uint32_t)vhd_time; } -time_t vhd_get_created_time(MVHDMeta *vhdm) + +uint32_t +mvhd_epoch_to_vhd_ts(time_t ts) { - time_t vhd_time = (time_t)vhdm->footer.timestamp; - time_t vhd_time_unix = MVHD_START_TS + vhd_time; - return vhd_time_unix; + time_t start_time = MVHD_START_TS; + double vhd_time; + + if (ts < start_time) + return (uint32_t)start_time; + + vhd_time = difftime(ts, start_time); + + return (uint32_t)vhd_time; } -FILE* mvhd_fopen(const char* path, const char* mode, int* err) { + +time_t +vhd_get_created_time(MVHDMeta *vhdm) +{ + time_t vhd_time = (time_t)vhdm->footer.timestamp; + time_t vhd_time_unix = MVHD_START_TS + vhd_time; + + return vhd_time_unix; +} + + +FILE* +mvhd_fopen(const char* path, const char* mode, int* err) +{ FILE* f = NULL; #ifdef _WIN32 size_t path_len = strlen(path); @@ -140,6 +214,7 @@ FILE* mvhd_fopen(const char* path, const char* mode, int* err) { int new_mode_len = (sizeof mode_str) - 2; int path_res = UTF8ToUTF16LE((unsigned char*)new_path, &new_path_len, (const unsigned char*)path, (int*)&path_len); int mode_res = UTF8ToUTF16LE((unsigned char*)mode_str, &new_mode_len, (const unsigned char*)mode, (int*)&mode_len); + if (path_res > 0 && mode_res > 0) { f = _wfopen(new_path, mode_str); if (f == NULL) { @@ -160,10 +235,14 @@ FILE* mvhd_fopen(const char* path, const char* mode, int* err) { *err = MVHD_ERR_FILE; } #endif + return f; } -void mvhd_set_encoding_err(int encoding_retval, int* err) { + +void +mvhd_set_encoding_err(int encoding_retval, int* err) +{ if (encoding_retval == -1) { *err = MVHD_ERR_UTF_SIZE; } else if (encoding_retval == -2) { @@ -171,87 +250,162 @@ void mvhd_set_encoding_err(int encoding_retval, int* err) { } } -uint64_t mvhd_calc_size_bytes(MVHDGeom *geom) { + +uint64_t +mvhd_calc_size_bytes(MVHDGeom *geom) +{ uint64_t img_size = (uint64_t)geom->cyl * (uint64_t)geom->heads * (uint64_t)geom->spt * (uint64_t)MVHD_SECTOR_SIZE; + return img_size; } -uint32_t mvhd_calc_size_sectors(MVHDGeom *geom) { + +uint32_t +mvhd_calc_size_sectors(MVHDGeom *geom) +{ uint32_t sector_size = (uint32_t)geom->cyl * (uint32_t)geom->heads * (uint32_t)geom->spt; + return sector_size; } -MVHDGeom mvhd_get_geometry(MVHDMeta* vhdm) { - MVHDGeom geometry = { .cyl = vhdm->footer.geom.cyl, .heads = vhdm->footer.geom.heads, .spt = vhdm->footer.geom.spt }; + +MVHDAPI MVHDGeom +mvhd_get_geometry(MVHDMeta* vhdm) +{ + MVHDGeom geometry = { + .cyl = vhdm->footer.geom.cyl, + .heads = vhdm->footer.geom.heads, + .spt = vhdm->footer.geom.spt + }; + return geometry; } -uint32_t mvhd_gen_footer_checksum(MVHDFooter* footer) { + +MVHDAPI uint64_t +mvhd_get_current_size(MVHDMeta* vhdm) +{ + return vhdm->footer.curr_sz; +} + + +uint32_t +mvhd_gen_footer_checksum(MVHDFooter* footer) +{ uint32_t new_chk = 0; uint32_t orig_chk = footer->checksum; footer->checksum = 0; uint8_t* footer_bytes = (uint8_t*)footer; - for (size_t i = 0; i < sizeof *footer; i++) { + + for (size_t i = 0; i < sizeof *footer; i++) new_chk += footer_bytes[i]; - } footer->checksum = orig_chk; + return ~new_chk; } -uint32_t mvhd_gen_sparse_checksum(MVHDSparseHeader* header) { + +uint32_t +mvhd_gen_sparse_checksum(MVHDSparseHeader* header) +{ uint32_t new_chk = 0; uint32_t orig_chk = header->checksum; header->checksum = 0; uint8_t* sparse_bytes = (uint8_t*)header; + for (size_t i = 0; i < sizeof *header; i++) { new_chk += sparse_bytes[i]; } header->checksum = orig_chk; + return ~new_chk; } -const char* mvhd_strerr(MVHDError err) { + +MVHDAPI const char* +mvhd_strerr(MVHDError err) +{ + const char *s = "unknown error"; + switch (err) { - case MVHD_ERR_MEM: - return "memory allocation error"; - case MVHD_ERR_FILE: - return "file error"; - case MVHD_ERR_NOT_VHD: - return "file is not a VHD image"; - case MVHD_ERR_TYPE: - return "unsupported VHD image type"; - case MVHD_ERR_FOOTER_CHECKSUM: - return "invalid VHD footer checksum"; - case MVHD_ERR_SPARSE_CHECKSUM: - return "invalid VHD sparse header checksum"; - case MVHD_ERR_UTF_TRANSCODING_FAILED: - return "error converting path encoding"; - case MVHD_ERR_UTF_SIZE: - return "buffer size mismatch when converting path encoding"; - case MVHD_ERR_PATH_REL: - return "relative path detected where absolute path expected"; - case MVHD_ERR_PATH_LEN: - return "path length exceeds MVHD_MAX_PATH"; - case MVHD_ERR_PAR_NOT_FOUND: - return "parent VHD image not found"; - case MVHD_ERR_INVALID_PAR_UUID: - return "UUID mismatch between child and parent VHD"; - case MVHD_ERR_INVALID_GEOM: - return "invalid geometry detected"; - case MVHD_ERR_INVALID_SIZE: - return "invalid size"; - case MVHD_ERR_INVALID_BLOCK_SIZE: - return "invalid block size"; - case MVHD_ERR_INVALID_PARAMS: - return "invalid parameters passed to function"; - case MVHD_ERR_CONV_SIZE: - return "error converting image. Size mismatch detechted"; - default: - return "unknown error"; + case MVHD_ERR_MEM: + s = "memory allocation error"; + break; + + case MVHD_ERR_FILE: + s = "file error"; + break; + + case MVHD_ERR_NOT_VHD: + s = "file is not a VHD image"; + break; + + case MVHD_ERR_TYPE: + s = "unsupported VHD image type"; + break; + + case MVHD_ERR_FOOTER_CHECKSUM: + s = "invalid VHD footer checksum"; + break; + + case MVHD_ERR_SPARSE_CHECKSUM: + s = "invalid VHD sparse header checksum"; + break; + + case MVHD_ERR_UTF_TRANSCODING_FAILED: + s = "error converting path encoding"; + break; + + case MVHD_ERR_UTF_SIZE: + s = "buffer size mismatch when converting path encoding"; + break; + + case MVHD_ERR_PATH_REL: + s = "relative path detected where absolute path expected"; + break; + + case MVHD_ERR_PATH_LEN: + s = "path length exceeds MVHD_MAX_PATH"; + break; + + case MVHD_ERR_PAR_NOT_FOUND: + s = "parent VHD image not found"; + break; + + case MVHD_ERR_INVALID_PAR_UUID: + s = "UUID mismatch between child and parent VHD"; + break; + + case MVHD_ERR_INVALID_GEOM: + s = "invalid geometry detected"; + break; + + case MVHD_ERR_INVALID_SIZE: + s = "invalid size"; + break; + + case MVHD_ERR_INVALID_BLOCK_SIZE: + s = "invalid block size"; + break; + + case MVHD_ERR_INVALID_PARAMS: + s = "invalid parameters passed to function"; + break; + + case MVHD_ERR_CONV_SIZE: + s = "error converting image. Size mismatch detected"; + break; + + default: + break; } + + return s; } -int64_t mvhd_ftello64(FILE* stream) + +int64_t +mvhd_ftello64(FILE* stream) { #ifdef _MSC_VER return _ftelli64(stream); @@ -262,7 +416,9 @@ int64_t mvhd_ftello64(FILE* stream) #endif } -int mvhd_fseeko64(FILE* stream, int64_t offset, int origin) + +int +mvhd_fseeko64(FILE* stream, int64_t offset, int origin) { #ifdef _MSC_VER return _fseeki64(stream, offset, origin); @@ -273,17 +429,25 @@ int mvhd_fseeko64(FILE* stream, int64_t offset, int origin) #endif } -uint32_t mvhd_crc32_for_byte(uint32_t r) { + +uint32_t +mvhd_crc32_for_byte(uint32_t r) +{ for (int j = 0; j < 8; ++j) r = (r & 1 ? 0 : (uint32_t)0xEDB88320L) ^ r >> 1; + return r ^ (uint32_t)0xFF000000L; } -uint32_t mvhd_crc32(const void* data, size_t n_bytes) { + +uint32_t +mvhd_crc32(const void* data, size_t n_bytes) +{ static uint32_t table[0x100]; + if (!*table) for (size_t i = 0; i < 0x100; ++i) - table[i] = mvhd_crc32_for_byte(i); + table[i] = mvhd_crc32_for_byte((uint32_t)i); uint32_t crc = 0; for (size_t i = 0; i < n_bytes; ++i) @@ -292,7 +456,10 @@ uint32_t mvhd_crc32(const void* data, size_t n_bytes) { return crc; } -uint32_t mvhd_file_mod_timestamp(const char* path, int *err) { + +uint32_t +mvhd_file_mod_timestamp(const char* path, int *err) +{ *err = 0; #ifdef _WIN32 struct _stat file_stat; @@ -300,6 +467,7 @@ uint32_t mvhd_file_mod_timestamp(const char* path, int *err) { mvhd_utf16 new_path[260] = {0}; int new_path_len = (sizeof new_path) - 2; int path_res = UTF8ToUTF16LE((unsigned char*)new_path, &new_path_len, (const unsigned char*)path, (int*)&path_len); + if (path_res > 0) { int stat_res = _wstat(new_path, &file_stat); if (stat_res != 0) { @@ -319,6 +487,7 @@ uint32_t mvhd_file_mod_timestamp(const char* path, int *err) { #else struct stat file_stat; int stat_res = stat(path, &file_stat); + if (stat_res != 0) { mvhd_errno = errno; *err = MVHD_ERR_FILE; diff --git a/src/disk/minivhd/minivhd_util.h b/src/disk/minivhd/minivhd_util.h deleted file mode 100644 index df6841009..000000000 --- a/src/disk/minivhd/minivhd_util.h +++ /dev/null @@ -1,136 +0,0 @@ -#ifndef MINIVHD_UTIL_H -#define MINIVHD_UTIL_H - -#include -#include -#include -#include "minivhd_internal.h" -#include "minivhd.h" -#define MVHD_START_TS 946684800 - -/** - * Functions to deal with endian issues - */ -uint16_t mvhd_from_be16(uint16_t val); -uint32_t mvhd_from_be32(uint32_t val); -uint64_t mvhd_from_be64(uint64_t val); -uint16_t mvhd_to_be16(uint16_t val); -uint32_t mvhd_to_be32(uint32_t val); -uint64_t mvhd_to_be64(uint64_t val); - -/** - * \brief Check if provided buffer begins with the string "conectix" - * - * \param [in] buffer The buffer to compare. Must be at least 8 bytes in length - * - * \return true if the buffer begins with "conectix" - * \return false if the buffer does not begin with "conectix" - */ -bool mvhd_is_conectix_str(const void* buffer); - -/** - * \brief Generate a raw 16 byte UUID - * - * \param [out] uuid A 16 byte buffer in which the generated UUID will be stored to - */ -void mvhd_generate_uuid(uint8_t *uuid); - -/** - * \brief Calculate a VHD formatted timestamp from the current time - */ -uint32_t vhd_calc_timestamp(void); - -/** - * \brief Convert an epoch timestamp to a VHD timestamp - * - * \param [in] ts epoch timestamp to convert. - * - * \return The adjusted timestamp, or 0 if the input timestamp is - * earlier that 1 Janurary 2000 - */ -uint32_t mvhd_epoch_to_vhd_ts(time_t ts); - -/** - * \brief Return the created time from a VHD image - * - * \param [in] vhdm Pointer to the MiniVHD metadata structure - * - * \return The created time, as a Unix timestamp - */ -time_t vhd_get_created_time(MVHDMeta *vhdm); - -/** - * \brief Cross platform, unicode filepath opening - * - * This function accounts for the fact that fopen() handles file paths differently compared to other - * operating systems. Windows version of fopen() will not handle multi byte encoded text like UTF-8. - * - * Unicode filepath support on Windows requires using the _wfopen() function, which expects UTF-16LE - * encoded path and modestring. - * - * \param [in] path The filepath to open as a UTF-8 string - * \param [in] mode The mode string to use (eg: "rb+"") - * \param [out] err The error value, if an error occurrs - * - * \return a FILE pointer if successful, NULL otherwise. If NULL, check the value of err - */ -FILE* mvhd_fopen(const char* path, const char* mode, int* err); - -void mvhd_set_encoding_err(int encoding_retval, int* err); -uint64_t mvhd_calc_size_bytes(MVHDGeom *geom); -uint32_t mvhd_calc_size_sectors(MVHDGeom *geom); -MVHDGeom mvhd_get_geometry(MVHDMeta* vhdm); - -/** - * \brief Generate VHD footer checksum - * - * \param [in] vhdm MiniVHD data structure - */ -uint32_t mvhd_gen_footer_checksum(MVHDFooter* footer); - -/** - * \brief Generate VHD sparse header checksum - * - * \param [in] vhdm MiniVHD data structure - */ -uint32_t mvhd_gen_sparse_checksum(MVHDSparseHeader* header); - -/** - * \brief Get current position in file stream - * - * This is a portable version of the POSIX ftello64(). * - */ -int64_t mvhd_ftello64(FILE* stream); - -/** - * \brief Reposition the file stream's position - * - * This is a portable version of the POSIX fseeko64(). * - */ -int mvhd_fseeko64(FILE* stream, int64_t offset, int origin); - -/** - * \brief Calculate the CRC32 of a data buffer. - * - * This function can be used for verifying data integrity. - * - * \param [in] data The data buffer - * \param [in] n_bytes The size of the data buffer in bytes - * - * \return The CRC32 of the data buffer - */ -uint32_t mvhd_crc32(const void* data, size_t n_bytes); - -/** - * \brief Calculate the file modification timestamp. - * - * This function is primarily to help protect differencing VHD's - * - * \param [in] path the UTF-8 file path - * \param [out] err The error value, if an error occurrs - * - * \return The file modified timestamp, in VHD compatible timestamp. - * 'err' will be set to non-zero on error - */ -uint32_t mvhd_file_mod_timestamp(const char* path, int *err); -#endif diff --git a/src/disk/minivhd/struct_rw.c b/src/disk/minivhd/struct_rw.c new file mode 100644 index 000000000..ceb98253a --- /dev/null +++ b/src/disk/minivhd/struct_rw.c @@ -0,0 +1,232 @@ +/* + * MiniVHD Minimalist VHD implementation in C. + * + * This file is part of the MiniVHD Project. + * + * Header and footer serialize/deserialize functions. + * + * Read data from footer into the struct members, swapping + * endian where necessary. + * + * NOTE: Order matters here! + * We must read each field in the order the struct is in. + * Doing this may be less elegant than performing a memcpy + * to a packed struct, but it avoids potential data alignment + * issues, and the endian swapping allows us to use the fields + * directly. + * + * Version: @(#)struct_rw.c 1.0.2 2021/04/16 + * + * Author: Sherman Perry, + * + * Copyright 2019-2021 Sherman Perry. + * + * MIT License + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documenta- + * tion files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, + * copy, modify, merge, publish, distribute, sublicense, and/or + * sell copies of the Software, and to permit persons to whom + * the Software is furnished to do so, subject to the following + * conditions: + * + * The above copyright notice and this permission notice shall + * be included in all copies or substantial portions of the + * Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF O R IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ +#ifndef _FILE_OFFSET_BITS +# define _FILE_OFFSET_BITS 64 +#endif +#include +#include +#include +#include +#include +#include +#include "minivhd.h" +#include "internal.h" + + +/** + * \brief Get the next field from a buffer and store it in a struct member, converting endian if necessary + * + * \param [out] struct_memb struct member to save the field to + * \param [in] memb_size the size of struct_memb, in bytes + * \param [in] req_endian is the field a value that requires endian conversion (eg: uint16, uint32) + * \param [in] buffer the buffer from which fields are read from. Will be advanced at the end of the function call + */ +static void +next_buffer_to_struct(void* struct_memb, size_t memb_size, bool req_endian, uint8_t** buffer) +{ + memcpy(struct_memb, *buffer, memb_size); + + if (req_endian) switch (memb_size) { + case 2: + *(uint16_t*)(struct_memb) = mvhd_from_be16(*(uint16_t*)(struct_memb)); + break; + + case 4: + *(uint32_t*)(struct_memb) = mvhd_from_be32(*(uint32_t*)(struct_memb)); + break; + + case 8: + *(uint64_t*)(struct_memb) = mvhd_from_be64(*(uint64_t*)(struct_memb)); + break; + } + + *buffer += memb_size; +} + + +/** + * \brief Save a struct member into a buffer, converting endian if necessary + * + * \param [in] struct_memb struct member read from + * \param [in] memb_size the size of struct_memb, in bytes + * \param [in] req_endian is the field a value that requires endian conversion (eg: uint16, uint32) + * \param [out] buffer the buffer from which struct member is saved to. Will be advanced at the end of the function call + */ +static void +next_struct_to_buffer(void* struct_memb, size_t memb_size, bool req_endian, uint8_t** buffer) +{ + uint8_t *buf_ptr = *buffer; + + memcpy(buf_ptr, struct_memb, memb_size); + + if (req_endian) switch (memb_size) { + case 2: + *((uint16_t*)buf_ptr) = mvhd_to_be16(*(uint16_t*)(struct_memb)); + break; + + case 4: + *((uint32_t*)buf_ptr) = mvhd_to_be32(*(uint32_t*)(struct_memb)); + break; + + case 8: + *((uint64_t*)buf_ptr) = mvhd_to_be64(*(uint64_t*)(struct_memb)); + break; + } + + buf_ptr += memb_size; + *buffer = buf_ptr; +} + + +void +mvhd_buffer_to_footer(MVHDFooter* footer, uint8_t* buffer) +{ + uint8_t* buff_ptr = buffer; + + next_buffer_to_struct(&footer->cookie, sizeof footer->cookie, false, &buff_ptr); + next_buffer_to_struct(&footer->features, sizeof footer->features, true, &buff_ptr); + next_buffer_to_struct(&footer->fi_fmt_vers, sizeof footer->fi_fmt_vers, true, &buff_ptr); + next_buffer_to_struct(&footer->data_offset, sizeof footer->data_offset, true, &buff_ptr); + next_buffer_to_struct(&footer->timestamp, sizeof footer->timestamp, true, &buff_ptr); + next_buffer_to_struct(&footer->cr_app, sizeof footer->cr_app, false, &buff_ptr); + next_buffer_to_struct(&footer->cr_vers, sizeof footer->cr_vers, true, &buff_ptr); + next_buffer_to_struct(&footer->cr_host_os, sizeof footer->cr_host_os, false, &buff_ptr); + next_buffer_to_struct(&footer->orig_sz, sizeof footer->orig_sz, true, &buff_ptr); + next_buffer_to_struct(&footer->curr_sz, sizeof footer->curr_sz, true, &buff_ptr); + next_buffer_to_struct(&footer->geom.cyl, sizeof footer->geom.cyl, true, &buff_ptr); + next_buffer_to_struct(&footer->geom.heads, sizeof footer->geom.heads, false, &buff_ptr); + next_buffer_to_struct(&footer->geom.spt, sizeof footer->geom.spt, false, &buff_ptr); + next_buffer_to_struct(&footer->disk_type, sizeof footer->disk_type, true, &buff_ptr); + next_buffer_to_struct(&footer->checksum, sizeof footer->checksum, true, &buff_ptr); + next_buffer_to_struct(&footer->uuid, sizeof footer->uuid, false, &buff_ptr); + next_buffer_to_struct(&footer->saved_st, sizeof footer->saved_st, false, &buff_ptr); + next_buffer_to_struct(&footer->reserved, sizeof footer->reserved, false, &buff_ptr); +} + + +void +mvhd_footer_to_buffer(MVHDFooter* footer, uint8_t* buffer) +{ + uint8_t* buff_ptr = buffer; + + next_struct_to_buffer(&footer->cookie, sizeof footer->cookie, false, &buff_ptr); + next_struct_to_buffer(&footer->features, sizeof footer->features, true, &buff_ptr); + next_struct_to_buffer(&footer->fi_fmt_vers, sizeof footer->fi_fmt_vers, true, &buff_ptr); + next_struct_to_buffer(&footer->data_offset, sizeof footer->data_offset, true, &buff_ptr); + next_struct_to_buffer(&footer->timestamp, sizeof footer->timestamp, true, &buff_ptr); + next_struct_to_buffer(&footer->cr_app, sizeof footer->cr_app, false, &buff_ptr); + next_struct_to_buffer(&footer->cr_vers, sizeof footer->cr_vers, true, &buff_ptr); + next_struct_to_buffer(&footer->cr_host_os, sizeof footer->cr_host_os, false, &buff_ptr); + next_struct_to_buffer(&footer->orig_sz, sizeof footer->orig_sz, true, &buff_ptr); + next_struct_to_buffer(&footer->curr_sz, sizeof footer->curr_sz, true, &buff_ptr); + next_struct_to_buffer(&footer->geom.cyl, sizeof footer->geom.cyl, true, &buff_ptr); + next_struct_to_buffer(&footer->geom.heads, sizeof footer->geom.heads, false, &buff_ptr); + next_struct_to_buffer(&footer->geom.spt, sizeof footer->geom.spt, false, &buff_ptr); + next_struct_to_buffer(&footer->disk_type, sizeof footer->disk_type, true, &buff_ptr); + next_struct_to_buffer(&footer->checksum, sizeof footer->checksum, true, &buff_ptr); + next_struct_to_buffer(&footer->uuid, sizeof footer->uuid, false, &buff_ptr); + next_struct_to_buffer(&footer->saved_st, sizeof footer->saved_st, false, &buff_ptr); + next_struct_to_buffer(&footer->reserved, sizeof footer->reserved, false, &buff_ptr); +} + + +void +mvhd_buffer_to_header(MVHDSparseHeader* header, uint8_t* buffer) +{ + uint8_t* buff_ptr = buffer; + + next_buffer_to_struct(&header->cookie, sizeof header->cookie, false, &buff_ptr); + next_buffer_to_struct(&header->data_offset, sizeof header->data_offset, true, &buff_ptr); + next_buffer_to_struct(&header->bat_offset, sizeof header->bat_offset, true, &buff_ptr); + next_buffer_to_struct(&header->head_vers, sizeof header->head_vers, true, &buff_ptr); + next_buffer_to_struct(&header->max_bat_ent, sizeof header->max_bat_ent, true, &buff_ptr); + next_buffer_to_struct(&header->block_sz, sizeof header->block_sz, true, &buff_ptr); + next_buffer_to_struct(&header->checksum, sizeof header->checksum, true, &buff_ptr); + next_buffer_to_struct(&header->par_uuid, sizeof header->par_uuid, false, &buff_ptr); + next_buffer_to_struct(&header->par_timestamp, sizeof header->par_timestamp, true, &buff_ptr); + next_buffer_to_struct(&header->reserved_1, sizeof header->reserved_1, true, &buff_ptr); + next_buffer_to_struct(&header->par_utf16_name, sizeof header->par_utf16_name, false, &buff_ptr); + + for (int i = 0; i < 8; i++) { + next_buffer_to_struct(&header->par_loc_entry[i].plat_code, sizeof header->par_loc_entry[i].plat_code, true, &buff_ptr); + next_buffer_to_struct(&header->par_loc_entry[i].plat_data_space, sizeof header->par_loc_entry[i].plat_data_space, true, &buff_ptr); + next_buffer_to_struct(&header->par_loc_entry[i].plat_data_len, sizeof header->par_loc_entry[i].plat_data_len, true, &buff_ptr); + next_buffer_to_struct(&header->par_loc_entry[i].reserved, sizeof header->par_loc_entry[i].reserved, true, &buff_ptr); + next_buffer_to_struct(&header->par_loc_entry[i].plat_data_offset, sizeof header->par_loc_entry[i].plat_data_offset, true, &buff_ptr); + } + + next_buffer_to_struct(&header->reserved_2, sizeof header->reserved_2, false, &buff_ptr); +} + + +void +mvhd_header_to_buffer(MVHDSparseHeader* header, uint8_t* buffer) +{ + uint8_t* buff_ptr = buffer; + + next_struct_to_buffer(&header->cookie, sizeof header->cookie, false, &buff_ptr); + next_struct_to_buffer(&header->data_offset, sizeof header->data_offset, true, &buff_ptr); + next_struct_to_buffer(&header->bat_offset, sizeof header->bat_offset, true, &buff_ptr); + next_struct_to_buffer(&header->head_vers, sizeof header->head_vers, true, &buff_ptr); + next_struct_to_buffer(&header->max_bat_ent, sizeof header->max_bat_ent, true, &buff_ptr); + next_struct_to_buffer(&header->block_sz, sizeof header->block_sz, true, &buff_ptr); + next_struct_to_buffer(&header->checksum, sizeof header->checksum, true, &buff_ptr); + next_struct_to_buffer(&header->par_uuid, sizeof header->par_uuid, false, &buff_ptr); + next_struct_to_buffer(&header->par_timestamp, sizeof header->par_timestamp, true, &buff_ptr); + next_struct_to_buffer(&header->reserved_1, sizeof header->reserved_1, true, &buff_ptr); + next_struct_to_buffer(&header->par_utf16_name, sizeof header->par_utf16_name, false, &buff_ptr); + + for (int i = 0; i < 8; i++) { + next_struct_to_buffer(&header->par_loc_entry[i].plat_code, sizeof header->par_loc_entry[i].plat_code, true, &buff_ptr); + next_struct_to_buffer(&header->par_loc_entry[i].plat_data_space, sizeof header->par_loc_entry[i].plat_data_space, true, &buff_ptr); + next_struct_to_buffer(&header->par_loc_entry[i].plat_data_len, sizeof header->par_loc_entry[i].plat_data_len, true, &buff_ptr); + next_struct_to_buffer(&header->par_loc_entry[i].reserved, sizeof header->par_loc_entry[i].reserved, true, &buff_ptr); + next_struct_to_buffer(&header->par_loc_entry[i].plat_data_offset, sizeof header->par_loc_entry[i].plat_data_offset, true, &buff_ptr); + } + + next_struct_to_buffer(&header->reserved_2, sizeof header->reserved_2, false, &buff_ptr); +} diff --git a/src/disk/minivhd/version.h b/src/disk/minivhd/version.h new file mode 100644 index 000000000..fcedc1be2 --- /dev/null +++ b/src/disk/minivhd/version.h @@ -0,0 +1,68 @@ +/* + * MiniVHD Minimalist VHD implementation in C. + * + * This file is part of the MiniVHD Project. + * + * Define library version and build info. + * + * Version: @(#)version.h 1.034 2021/04/16 + * + * Author: Fred N. van Kempen, + * + * Copyright 2021 Fred N. van Kempen. + * + * MIT License + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documenta- + * tion files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, + * copy, modify, merge, publish, distribute, sublicense, and/or + * sell copies of the Software, and to permit persons to whom + * the Software is furnished to do so, subject to the following + * conditions: + * + * The above copyright notice and this permission notice shall + * be included in all copies or substantial portions of the + * Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF O R IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ +#ifndef MINIVHD_VERSION_H +# define MINIVHD_VERSION_H + + +/* Library name. */ +#define LIB_NAME "MiniVHD" + +/* Version info. */ +#define LIB_VER_MAJOR 1 +#define LIB_VER_MINOR 0 +#define LIB_VER_REV 3 +#define LIB_VER_PATCH 0 + + +/* Standard C preprocessor macros. */ +#define STR_STRING(x) #x +#define STR(x) STR_STRING(x) +#define STR_RC(a,e) a ## , ## e + + +/* These are used in the application. */ +#define LIB_VER_NUM LIB_VER_MAJOR.LIB_VER_MINOR.LIB_VER_REV +#if defined(LIB_VER_PATCH) && LIB_VER_PATCH > 0 +# define LIB_VER_NUM_4 LIB_VER_MAJOR.LIB_VER_MINOR.LIB_VER_REV.LIB_VER_PATCH +#else +# define LIB_VER_NUM_4 LIB_VER_MAJOR.LIB_VER_MINOR.LIB_VER_REV.0 +#endif +#define LIB_VERSION STR(LIB_VER_NUM) +#define LIB_VERSION_4 STR(LIB_VER_NUM_4) + + +#endif /*MINIVHD_VERSION_H*/ diff --git a/src/disk/minivhd/libxml2_encoding.c b/src/disk/minivhd/xml2_encoding.c similarity index 91% rename from src/disk/minivhd/libxml2_encoding.c rename to src/disk/minivhd/xml2_encoding.c index cb881a89b..6c39cb7f6 100644 --- a/src/disk/minivhd/libxml2_encoding.c +++ b/src/disk/minivhd/xml2_encoding.c @@ -18,15 +18,25 @@ * daniel@veillard.com * * Original code for IsoLatin1 and UTF-16 by "Martin J. Duerst" - * + * * Adapted and abridged for MiniVHD by Sherman Perry */ #include +#include +#include +#include +#include +#define BUILDING_LIBRARY +#include "minivhd.h" +#include "internal.h" +#include "xml2_encoding.h" + static int xmlLittleEndian = 1; + /* Note: extracted from original 'void xmlInitCharEncodingHandlers(void)' function */ -void xmlEncodingInit(void) +void xmlEncodingInit(void) { unsigned short int tst = 0x1234; unsigned char *ptr = (unsigned char *) &tst; @@ -96,8 +106,8 @@ int UTF16LEToUTF8(unsigned char* out, int *outlen, c += 0x10000; } else { - *outlen = out - outstart; - *inlenb = processed - inb; + *outlen = (int)(out - outstart); + *inlenb = (int)(processed - inb); return(-2); } } @@ -117,8 +127,8 @@ int UTF16LEToUTF8(unsigned char* out, int *outlen, } processed = (const unsigned char*) in; } - *outlen = out - outstart; - *inlenb = processed - inb; + *outlen = (int)(out - outstart); + *inlenb = (int)(processed - inb); return(*outlen); } @@ -163,16 +173,16 @@ int UTF8ToUTF16LE(unsigned char* outb, int *outlen, if (d < 0x80) { c= d; trailing= 0; } else if (d < 0xC0) { /* trailing byte in leading position */ - *outlen = (out - outstart) * 2; - *inlen = processed - instart; + *outlen = (int)((out - outstart) * 2); + *inlen = (int)(processed - instart); return(-2); } else if (d < 0xE0) { c= d & 0x1F; trailing= 1; } else if (d < 0xF0) { c= d & 0x0F; trailing= 2; } else if (d < 0xF8) { c= d & 0x07; trailing= 3; } else { /* no chance for this in UTF-16 */ - *outlen = (out - outstart) * 2; - *inlen = processed - instart; + *outlen = (int)((out - outstart) * 2); + *inlen = (int)(processed - instart); return(-2); } @@ -225,8 +235,8 @@ int UTF8ToUTF16LE(unsigned char* outb, int *outlen, break; processed = in; } - *outlen = (out - outstart) * 2; - *inlen = processed - instart; + *outlen = (int)((out - outstart) * 2); + *inlen = (int)(processed - instart); return(*outlen); } @@ -275,8 +285,8 @@ int UTF16BEToUTF8(unsigned char* out, int *outlen, } if ((c & 0xFC00) == 0xD800) { /* surrogates */ if (in >= inend) { /* (in > inend) shouldn't happens */ - *outlen = out - outstart; - *inlenb = processed - inb; + *outlen = (int)(out - outstart); + *inlenb = (int)(processed - inb); return(-2); } if (xmlLittleEndian) { @@ -295,8 +305,8 @@ int UTF16BEToUTF8(unsigned char* out, int *outlen, c += 0x10000; } else { - *outlen = out - outstart; - *inlenb = processed - inb; + *outlen = (int)(out - outstart); + *inlenb = (int)(processed - inb); return(-2); } } @@ -316,8 +326,8 @@ int UTF16BEToUTF8(unsigned char* out, int *outlen, } processed = (const unsigned char*) in; } - *outlen = out - outstart; - *inlenb = processed - inb; + *outlen = (int)(out - outstart); + *inlenb = (int)(processed - inb); return(*outlen); } @@ -362,16 +372,16 @@ int UTF8ToUTF16BE(unsigned char* outb, int *outlen, if (d < 0x80) { c= d; trailing= 0; } else if (d < 0xC0) { /* trailing byte in leading position */ - *outlen = out - outstart; - *inlen = processed - instart; + *outlen = (int)(out - outstart); + *inlen = (int)(processed - instart); return(-2); } else if (d < 0xE0) { c= d & 0x1F; trailing= 1; } else if (d < 0xF0) { c= d & 0x0F; trailing= 2; } else if (d < 0xF8) { c= d & 0x07; trailing= 3; } else { /* no chance for this in UTF-16 */ - *outlen = out - outstart; - *inlen = processed - instart; + *outlen = (int)(out - outstart); + *inlen = (int)(processed - instart); return(-2); } @@ -421,12 +431,12 @@ int UTF8ToUTF16BE(unsigned char* outb, int *outlen, break; processed = in; } - *outlen = (out - outstart) * 2; - *inlen = processed - instart; + *outlen = (int)((out - outstart) * 2); + *inlen = (int)(processed - instart); return(*outlen); } -/* This file is licenced under the MIT licence as follows: +/* This file is licenced under the MIT licence as follows: Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal @@ -444,4 +454,4 @@ NESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -THE SOFTWARE. */ \ No newline at end of file +THE SOFTWARE. */ diff --git a/src/disk/minivhd/xml2_encoding.h b/src/disk/minivhd/xml2_encoding.h new file mode 100644 index 000000000..68c85390d --- /dev/null +++ b/src/disk/minivhd/xml2_encoding.h @@ -0,0 +1,62 @@ +/* + * MiniVHD Minimalist VHD implementation in C. + * + * This file is part of the MiniVHD Project. + * + * Version: @(#)xml2_encoding.h 1.0.1 2021/03/15 + * + * Author: Sherman Perry, + * + * Copyright 2019-2021 Sherman Perry. + * + * MIT License + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documenta- + * tion files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, + * copy, modify, merge, publish, distribute, sublicense, and/or + * sell copies of the Software, and to permit persons to whom + * the Software is furnished to do so, subject to the following + * conditions: + * + * The above copyright notice and this permission notice shall + * be included in all copies or substantial portions of the + * Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF O R IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ +#ifndef XML2_ENCODING_H +# define XML2_ENCODING_H + + +typedef uint16_t mvhd_utf16; + + +#ifdef __cplusplus +extern "C" { +#endif + +void xmlEncodingInit(void); + +int UTF16LEToUTF8(uint8_t *out, int *outlen, const uint8_t *inb, + int *inlenb); +int UTF8ToUTF16LE(uint8_t *outb, int *outlen, const uint8_t *in, + int *inlen); +int UTF16BEToUTF8(uint8_t *out, int *outlen, const uint8_t *inb, + int *inlenb); +int UTF8ToUTF16BE(uint8_t *outb, int *outlen, const uint8_t *in, + int *inlen); + +#ifdef __cplusplus +} +#endif + + +#endif /*XML2_ENCODING_H*/ diff --git a/src/disk/mo.c b/src/disk/mo.c index d6924a438..ad781a8ac 100644 --- a/src/disk/mo.c +++ b/src/disk/mo.c @@ -1,23 +1,23 @@ /* - * 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. + * 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. + * This file is part of the 86Box distribution. * - * Implementation of a generic Magneto-Optical Disk drive - * commands, for both ATAPI and SCSI usage. + * Implementation of a generic Magneto-Optical Disk drive + * commands, for both ATAPI and SCSI usage. * * * - * Authors: Natalia Portillo - * Miran Grca, - * Fred N. van Kempen, + * Authors: Natalia Portillo + * Miran Grca, + * Fred N. van Kempen, * - * Copyright 2020,2021 Natalia Portillo. - * Copyright 2020,2021 Miran Grca. - * Copyright 2020,2021 Fred N. van Kempen + * Copyright 2020-2021 Natalia Portillo. + * Copyright 2020-2021 Miran Grca. + * Copyright 2020-2021 Fred N. van Kempen */ #include #include @@ -31,8 +31,10 @@ #include <86box/config.h> #include <86box/timer.h> #include <86box/device.h> +#include <86box/scsi.h> #include <86box/scsi_device.h> #include <86box/nvr.h> +#include <86box/path.h> #include <86box/plat.h> #include <86box/ui.h> #include <86box/hdc.h> @@ -41,74 +43,74 @@ #include <86box/version.h> #ifdef _WIN32 -#include -#include +# include +# include #else -#include +# include #endif -mo_drive_t mo_drives[MO_NUM]; +#define IDE_ATAPI_IS_EARLY id->sc->pad0 +mo_drive_t mo_drives[MO_NUM]; /* Table of all SCSI commands and their flags, needed for the new disc change / not ready handler. */ -const uint8_t mo_command_flags[0x100] = -{ - IMPLEMENTED | CHECK_READY | NONDATA, /* 0x00 */ - IMPLEMENTED | ALLOW_UA | NONDATA | SCSI_ONLY, /* 0x01 */ +const uint8_t mo_command_flags[0x100] = { + IMPLEMENTED | CHECK_READY | NONDATA, /* 0x00 */ + IMPLEMENTED | ALLOW_UA | NONDATA | SCSI_ONLY, /* 0x01 */ 0, - IMPLEMENTED | ALLOW_UA, /* 0x03 */ - IMPLEMENTED | CHECK_READY | ALLOW_UA | NONDATA | SCSI_ONLY, /* 0x04 */ + IMPLEMENTED | ALLOW_UA, /* 0x03 */ + IMPLEMENTED | CHECK_READY | ALLOW_UA | NONDATA | SCSI_ONLY, /* 0x04 */ 0, 0, 0, - IMPLEMENTED | CHECK_READY, /* 0x08 */ + IMPLEMENTED | CHECK_READY, /* 0x08 */ 0, - IMPLEMENTED | CHECK_READY, /* 0x0A */ - IMPLEMENTED | CHECK_READY | NONDATA, /* 0x0B */ + IMPLEMENTED | CHECK_READY, /* 0x0A */ + IMPLEMENTED | CHECK_READY | NONDATA, /* 0x0B */ 0, 0, 0, 0, 0, 0, - IMPLEMENTED | ALLOW_UA, /* 0x12 */ - IMPLEMENTED | CHECK_READY | NONDATA | SCSI_ONLY, /* 0x13 */ + IMPLEMENTED | ALLOW_UA, /* 0x12 */ + IMPLEMENTED | CHECK_READY | NONDATA | SCSI_ONLY, /* 0x13 */ 0, - IMPLEMENTED, /* 0x15 */ - IMPLEMENTED | SCSI_ONLY, /* 0x16 */ - IMPLEMENTED | SCSI_ONLY, /* 0x17 */ + IMPLEMENTED, /* 0x15 */ + IMPLEMENTED | SCSI_ONLY, /* 0x16 */ + IMPLEMENTED | SCSI_ONLY, /* 0x17 */ 0, 0, - IMPLEMENTED, /* 0x1A */ - IMPLEMENTED | CHECK_READY, /* 0x1B */ + IMPLEMENTED, /* 0x1A */ + IMPLEMENTED | CHECK_READY, /* 0x1B */ 0, - IMPLEMENTED, /* 0x1D */ - IMPLEMENTED | CHECK_READY, /* 0x1E */ + IMPLEMENTED, /* 0x1D */ + IMPLEMENTED | CHECK_READY, /* 0x1E */ 0, 0, 0, 0, 0, 0, - IMPLEMENTED | CHECK_READY, /* 0x25 */ + IMPLEMENTED | CHECK_READY, /* 0x25 */ 0, 0, - IMPLEMENTED | CHECK_READY, /* 0x28 */ + IMPLEMENTED | CHECK_READY, /* 0x28 */ 0, - IMPLEMENTED | CHECK_READY, /* 0x2A */ - IMPLEMENTED | CHECK_READY | NONDATA, /* 0x2B */ - IMPLEMENTED | CHECK_READY | NONDATA, /* 0x2C */ + IMPLEMENTED | CHECK_READY, /* 0x2A */ + IMPLEMENTED | CHECK_READY | NONDATA, /* 0x2B */ + IMPLEMENTED | CHECK_READY | NONDATA, /* 0x2C */ 0, - IMPLEMENTED | CHECK_READY, /* 0x2E */ - IMPLEMENTED | CHECK_READY | NONDATA | SCSI_ONLY, /* 0x2F */ + IMPLEMENTED | CHECK_READY, /* 0x2E */ + IMPLEMENTED | CHECK_READY | NONDATA | SCSI_ONLY, /* 0x2F */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - IMPLEMENTED, /* 0x55 */ + IMPLEMENTED, /* 0x55 */ 0, 0, 0, 0, - IMPLEMENTED, /* 0x5A */ + IMPLEMENTED, /* 0x5A */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - IMPLEMENTED | CHECK_READY, /* 0xA8 */ + IMPLEMENTED | CHECK_READY, /* 0xA8 */ 0, - IMPLEMENTED | CHECK_READY, /* 0xAA */ - 0, - IMPLEMENTED | CHECK_READY | NONDATA, /* 0xAC */ + IMPLEMENTED | CHECK_READY, /* 0xAA */ 0, - IMPLEMENTED | CHECK_READY, /* 0xAE */ - IMPLEMENTED | CHECK_READY | NONDATA | SCSI_ONLY, /* 0xAF */ + IMPLEMENTED | CHECK_READY | NONDATA, /* 0xAC */ + 0, + IMPLEMENTED | CHECK_READY, /* 0xAE */ + IMPLEMENTED | CHECK_READY | NONDATA | SCSI_ONLY, /* 0xAF */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, @@ -118,10 +120,10 @@ const uint8_t mo_command_flags[0x100] = 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }; -static uint64_t mo_mode_sense_page_flags = (GPMODEP_ALL_PAGES); - +static uint64_t mo_mode_sense_page_flags = GPMODEP_ALL_PAGES; static const mode_sense_pages_t mo_mode_sense_pages_default = + // clang-format off { { { 0, 0 }, { 0, 0 }, @@ -172,8 +174,10 @@ static const mode_sense_pages_t mo_mode_sense_pages_default = { 0, 0 }, { 0, 0 } } }; +// clang-format on static const mode_sense_pages_t mo_mode_sense_pages_default_scsi = + // clang-format off { { { 0, 0 }, { 0, 0 }, @@ -224,9 +228,10 @@ static const mode_sense_pages_t mo_mode_sense_pages_default_scsi = { 0, 0 }, { 0, 0 } } }; - +// clang-format on static const mode_sense_pages_t mo_mode_sense_pages_changeable = + // clang-format off { { { 0, 0 }, { 0, 0 }, @@ -277,466 +282,417 @@ static const mode_sense_pages_t mo_mode_sense_pages_changeable = { 0, 0 }, { 0, 0 } } }; +// clang-format on - -static void mo_command_complete(mo_t *dev); -static void mo_init(mo_t *dev); - +static void mo_command_complete(mo_t *dev); +static void mo_init(mo_t *dev); #ifdef ENABLE_MO_LOG int mo_do_log = ENABLE_MO_LOG; - static void mo_log(const char *fmt, ...) { va_list ap; if (mo_do_log) { - va_start(ap, fmt); - pclog_ex(fmt, ap); - va_end(ap); + va_start(ap, fmt); + pclog_ex(fmt, ap); + va_end(ap); } } #else -#define mo_log(fmt, ...) +# define mo_log(fmt, ...) #endif - int find_mo_for_channel(uint8_t channel) { - uint8_t i = 0; - - for (i = 0; i < MO_NUM; i++) { - if ((mo_drives[i].bus_type == MO_BUS_ATAPI) && (mo_drives[i].ide_channel == channel)) - return i; + for (uint8_t i = 0; i < MO_NUM; i++) { + if ((mo_drives[i].bus_type == MO_BUS_ATAPI) && (mo_drives[i].ide_channel == channel)) + return i; } return 0xff; } - static int mo_load_abort(mo_t *dev) { - if (dev->drv->f) - fclose(dev->drv->f); - dev->drv->f = NULL; + if (dev->drv->fp) + fclose(dev->drv->fp); + dev->drv->fp = NULL; dev->drv->medium_size = 0; dev->drv->sector_size = 0; - mo_eject(dev->id); /* Make sure the host OS knows we've rejected (and ejected) the image. */ + mo_eject(dev->id); /* Make sure the host OS knows we've rejected (and ejected) the image. */ return 0; } - int image_is_mdi(const char *s) { - if (! strcasecmp(plat_get_extension((char *) s), "MDI")) - return 1; + if (!strcasecmp(path_get_extension((char *) s), "MDI")) + return 1; else - return 0; + return 0; } - int mo_load(mo_t *dev, char *fn) { - int is_mdi; - uint32_t size = 0; - unsigned int i, found = 0; + int is_mdi; + uint32_t size = 0; + unsigned int found = 0; is_mdi = image_is_mdi(fn); - dev->drv->f = plat_fopen(fn, dev->drv->read_only ? "rb" : "rb+"); - if (!dev->drv->f) { - if (!dev->drv->read_only) { - dev->drv->f = plat_fopen(fn, "rb"); - if (dev->drv->f) - dev->drv->read_only = 1; - else - return mo_load_abort(dev); - } else - return mo_load_abort(dev); + dev->drv->fp = plat_fopen(fn, dev->drv->read_only ? "rb" : "rb+"); + if (!dev->drv->fp) { + if (!dev->drv->read_only) { + dev->drv->fp = plat_fopen(fn, "rb"); + if (dev->drv->fp) + dev->drv->read_only = 1; + else + return mo_load_abort(dev); + } else + return mo_load_abort(dev); } - fseek(dev->drv->f, 0, SEEK_END); - size = (uint32_t) ftell(dev->drv->f); + fseek(dev->drv->fp, 0, SEEK_END); + size = (uint32_t) ftell(dev->drv->fp); if (is_mdi) { - /* This is a MDI image. */ - size -= 0x1000LL; - dev->drv->base = 0x1000; + /* This is a MDI image. */ + size -= 0x1000LL; + dev->drv->base = 0x1000; } - for (i = 0; i < KNOWN_MO_TYPES; i++) { - if (size == (mo_types[i].sectors * mo_types[i].bytes_per_sector)) { - found = 1; - dev->drv->medium_size = mo_types[i].sectors; - dev->drv->sector_size = mo_types[i].bytes_per_sector; - break; - } + for (uint8_t i = 0; i < KNOWN_MO_TYPES; i++) { + if (size == (mo_types[i].sectors * mo_types[i].bytes_per_sector)) { + found = 1; + dev->drv->medium_size = mo_types[i].sectors; + dev->drv->sector_size = mo_types[i].bytes_per_sector; + break; + } } - + if (!found) - return mo_load_abort(dev); + return mo_load_abort(dev); - if (fseek(dev->drv->f, dev->drv->base, SEEK_SET) == -1) - fatal("mo_load(): Error seeking to the beginning of the file\n"); + if (fseek(dev->drv->fp, dev->drv->base, SEEK_SET) == -1) + fatal("mo_load(): Error seeking to the beginning of the file\n"); strncpy(dev->drv->image_path, fn, sizeof(dev->drv->image_path) - 1); return 1; } - void mo_disk_reload(mo_t *dev) { int ret = 0; if (strlen(dev->drv->prev_image_path) == 0) - return; + return; else - ret = mo_load(dev, dev->drv->prev_image_path); + ret = mo_load(dev, dev->drv->prev_image_path); if (ret) - dev->unit_attention = 1; + dev->unit_attention = 1; } - void mo_disk_unload(mo_t *dev) { - if (dev->drv->f) { - fclose(dev->drv->f); - dev->drv->f = NULL; + if (dev->drv->fp) { + fclose(dev->drv->fp); + dev->drv->fp = NULL; } } - void mo_disk_close(mo_t *dev) { - if (dev->drv->f) { - mo_disk_unload(dev); + if (dev->drv->fp) { + mo_disk_unload(dev); - memcpy(dev->drv->prev_image_path, dev->drv->image_path, sizeof(dev->drv->prev_image_path)); - memset(dev->drv->image_path, 0, sizeof(dev->drv->image_path)); + memcpy(dev->drv->prev_image_path, dev->drv->image_path, sizeof(dev->drv->prev_image_path)); + memset(dev->drv->image_path, 0, sizeof(dev->drv->image_path)); - dev->drv->medium_size = 0; + dev->drv->medium_size = 0; } } - static void mo_set_callback(mo_t *dev) { if (dev->drv->bus_type != MO_BUS_SCSI) - ide_set_callback(ide_drives[dev->drv->ide_channel], dev->callback); + ide_set_callback(ide_drives[dev->drv->ide_channel], dev->callback); } - static void mo_init(mo_t *dev) { if (dev->id >= MO_NUM) - return; + return; dev->requested_blocks = 1; - dev->sense[0] = 0xf0; - dev->sense[7] = 10; - dev->drv->bus_mode = 0; + dev->sense[0] = 0xf0; + dev->sense[7] = 10; + dev->drv->bus_mode = 0; if (dev->drv->bus_type >= MO_BUS_ATAPI) - dev->drv->bus_mode |= 2; + dev->drv->bus_mode |= 2; if (dev->drv->bus_type < MO_BUS_SCSI) - dev->drv->bus_mode |= 1; + dev->drv->bus_mode |= 1; mo_log("MO %i: Bus type %i, bus mode %i\n", dev->id, dev->drv->bus_type, dev->drv->bus_mode); if (dev->drv->bus_type < MO_BUS_SCSI) { - dev->phase = 1; - dev->request_length = 0xEB14; + dev->tf->phase = 1; + dev->tf->request_length = 0xEB14; } - dev->status = READY_STAT | DSC_STAT; - dev->pos = 0; + dev->tf->status = READY_STAT | DSC_STAT; + dev->tf->pos = 0; dev->packet_status = PHASE_NONE; mo_sense_key = mo_asc = mo_ascq = dev->unit_attention = 0; } - static int mo_supports_pio(mo_t *dev) { return (dev->drv->bus_mode & 1); } - static int mo_supports_dma(mo_t *dev) { return (dev->drv->bus_mode & 2); } - /* Returns: 0 for none, 1 for PIO, 2 for DMA. */ static int mo_current_mode(mo_t *dev) { if (!mo_supports_pio(dev) && !mo_supports_dma(dev)) - return 0; + return 0; if (mo_supports_pio(dev) && !mo_supports_dma(dev)) { - mo_log("MO %i: Drive does not support DMA, setting to PIO\n", dev->id); - return 1; + mo_log("MO %i: Drive does not support DMA, setting to PIO\n", dev->id); + return 1; } if (!mo_supports_pio(dev) && mo_supports_dma(dev)) - return 2; + return 2; if (mo_supports_pio(dev) && mo_supports_dma(dev)) { - mo_log("MO %i: Drive supports both, setting to %s\n", dev->id, (dev->features & 1) ? "DMA" : "PIO"); - return (dev->features & 1) ? 2 : 1; + mo_log("MO %i: Drive supports both, setting to %s\n", dev->id, + (dev->tf->features & 1) ? "DMA" : "PIO"); + return (dev->tf->features & 1) ? 2 : 1; } return 0; } - -/* Translates ATAPI phase (DRQ, I/O, C/D) to SCSI phase (MSG, C/D, I/O). */ -int -mo_atapi_phase_to_scsi(mo_t *dev) -{ - if (dev->status & 8) { - switch (dev->phase & 3) { - case 0: - return 0; - case 1: - return 2; - case 2: - return 1; - case 3: - return 7; - } - } else { - if ((dev->phase & 3) == 3) - return 3; - else - return 4; - } - - return 0; -} - - static void mo_mode_sense_load(mo_t *dev) { - FILE *f; - char file_name[512]; + FILE *fp; + char fn[512]; memset(&dev->ms_pages_saved, 0, sizeof(mode_sense_pages_t)); if (mo_drives[dev->id].bus_type == MO_BUS_SCSI) - memcpy(&dev->ms_pages_saved, &mo_mode_sense_pages_default_scsi, sizeof(mode_sense_pages_t)); + memcpy(&dev->ms_pages_saved, &mo_mode_sense_pages_default_scsi, sizeof(mode_sense_pages_t)); else - memcpy(&dev->ms_pages_saved, &mo_mode_sense_pages_default, sizeof(mode_sense_pages_t)); + memcpy(&dev->ms_pages_saved, &mo_mode_sense_pages_default, sizeof(mode_sense_pages_t)); - memset(file_name, 0, 512); + memset(fn, 0, 512); if (dev->drv->bus_type == MO_BUS_SCSI) - sprintf(file_name, "scsi_mo_%02i_mode_sense_bin", dev->id); + sprintf(fn, "scsi_mo_%02i_mode_sense_bin", dev->id); else - sprintf(file_name, "mo_%02i_mode_sense_bin", dev->id); - f = plat_fopen(nvr_path(file_name), "rb"); - if (f) { - /* Nothing to read, not used by MO. */ - fclose(f); + sprintf(fn, "mo_%02i_mode_sense_bin", dev->id); + fp = plat_fopen(nvr_path(fn), "rb"); + if (fp) { + /* Nothing to read, not used by MO. */ + fclose(fp); } } - static void mo_mode_sense_save(mo_t *dev) { - FILE *f; - char file_name[512]; + FILE *fp; + char fn[512]; - memset(file_name, 0, 512); + memset(fn, 0, 512); if (dev->drv->bus_type == MO_BUS_SCSI) - sprintf(file_name, "scsi_mo_%02i_mode_sense_bin", dev->id); + sprintf(fn, "scsi_mo_%02i_mode_sense_bin", dev->id); else - sprintf(file_name, "mo_%02i_mode_sense_bin", dev->id); - f = plat_fopen(nvr_path(file_name), "wb"); - if (f) { - /* Nothing to write, not used by MO. */ - fclose(f); + sprintf(fn, "mo_%02i_mode_sense_bin", dev->id); + fp = plat_fopen(nvr_path(fn), "wb"); + if (fp) { + /* Nothing to write, not used by MO. */ + fclose(fp); } } - /*SCSI Mode Sense 6/10*/ static uint8_t mo_mode_sense_read(mo_t *dev, uint8_t page_control, uint8_t page, uint8_t pos) { switch (page_control) { - case 0: - case 3: - return dev->ms_pages_saved.pages[page][pos]; - break; - case 1: - return mo_mode_sense_pages_changeable.pages[page][pos]; - break; - case 2: - if (dev->drv->bus_type == MO_BUS_SCSI) - return mo_mode_sense_pages_default_scsi.pages[page][pos]; - else - return mo_mode_sense_pages_default.pages[page][pos]; - break; + case 0: + case 3: + return dev->ms_pages_saved.pages[page][pos]; + case 1: + return mo_mode_sense_pages_changeable.pages[page][pos]; + case 2: + if (dev->drv->bus_type == MO_BUS_SCSI) + return mo_mode_sense_pages_default_scsi.pages[page][pos]; + else + return mo_mode_sense_pages_default.pages[page][pos]; + + default: + break; } return 0; } - static uint32_t mo_mode_sense(mo_t *dev, uint8_t *buf, uint32_t pos, uint8_t page, uint8_t block_descriptor_len) { uint64_t pf; - uint8_t page_control = (page >> 6) & 3; + uint8_t page_control = (page >> 6) & 3; pf = mo_mode_sense_page_flags; - int i = 0; - int j = 0; - uint8_t msplen; page &= 0x3f; if (block_descriptor_len) { - buf[pos++] = ((dev->drv->medium_size >> 24) & 0xff); - buf[pos++] = ((dev->drv->medium_size >> 16) & 0xff); - buf[pos++] = ((dev->drv->medium_size >> 8) & 0xff); - buf[pos++] = ( dev->drv->medium_size & 0xff); - buf[pos++] = 0; /* Reserved. */ - buf[pos++] = 0; - buf[pos++] = ((dev->drv->sector_size >> 8) & 0xff); - buf[pos++] = ( dev->drv->sector_size & 0xff); + buf[pos++] = ((dev->drv->medium_size >> 24) & 0xff); + buf[pos++] = ((dev->drv->medium_size >> 16) & 0xff); + buf[pos++] = ((dev->drv->medium_size >> 8) & 0xff); + buf[pos++] = (dev->drv->medium_size & 0xff); + buf[pos++] = 0; /* Reserved. */ + buf[pos++] = 0; + buf[pos++] = ((dev->drv->sector_size >> 8) & 0xff); + buf[pos++] = (dev->drv->sector_size & 0xff); } - for (i = 0; i < 0x40; i++) { + for (uint8_t i = 0; i < 0x40; i++) { if ((page == GPMODE_ALL_PAGES) || (page == i)) { - if (pf & (1LL << ((uint64_t) page))) { - buf[pos++] = mo_mode_sense_read(dev, page_control, i, 0); - msplen = mo_mode_sense_read(dev, page_control, i, 1); - buf[pos++] = msplen; - mo_log("MO %i: MODE SENSE: Page [%02X] length %i\n", dev->id, i, msplen); - for (j = 0; j < msplen; j++) - buf[pos++] = mo_mode_sense_read(dev, page_control, i, 2 + j); - } - } + if (pf & (1LL << ((uint64_t) page))) { + buf[pos++] = mo_mode_sense_read(dev, page_control, i, 0); + msplen = mo_mode_sense_read(dev, page_control, i, 1); + buf[pos++] = msplen; + mo_log("MO %i: MODE SENSE: Page [%02X] length %i\n", dev->id, i, msplen); + for (uint8_t j = 0; j < msplen; j++) + buf[pos++] = mo_mode_sense_read(dev, page_control, i, 2 + j); + } + } } return pos; } - static void mo_update_request_length(mo_t *dev, int len, int block_len) { - int bt, min_len = 0; + int bt; + int min_len = 0; - dev->max_transfer_len = dev->request_length; + dev->max_transfer_len = dev->tf->request_length; /* For media access commands, make sure the requested DRQ length matches the block length. */ switch (dev->current_cdb[0]) { - case 0x08: - case 0x0a: - case 0x28: - case 0x2a: - case 0xa8: - case 0xaa: - /* Round it to the nearest 2048 bytes. */ - dev->max_transfer_len = (dev->max_transfer_len >> 9) << 9; + case 0x08: + case 0x0a: + case 0x28: + case 0x2a: + case 0xa8: + case 0xaa: + /* Round it to the nearest 2048 bytes. */ + dev->max_transfer_len = (dev->max_transfer_len >> 9) << 9; - /* Make sure total length is not bigger than sum of the lengths of - all the requested blocks. */ - bt = (dev->requested_blocks * block_len); - if (len > bt) - len = bt; + /* Make sure total length is not bigger than sum of the lengths of + all the requested blocks. */ + bt = (dev->requested_blocks * block_len); + if (len > bt) + len = bt; - min_len = block_len; + min_len = block_len; - if (len <= block_len) { - /* Total length is less or equal to block length. */ - if (dev->max_transfer_len < block_len) { - /* Transfer a minimum of (block size) bytes. */ - dev->max_transfer_len = block_len; - dev->packet_len = block_len; - break; - } - } - /*FALLTHROUGH*/ - default: - dev->packet_len = len; - break; + if (len <= block_len) { + /* Total length is less or equal to block length. */ + if (dev->max_transfer_len < block_len) { + /* Transfer a minimum of (block size) bytes. */ + dev->max_transfer_len = block_len; + dev->packet_len = block_len; + break; + } + } + fallthrough; + + default: + dev->packet_len = len; + break; } /* If the DRQ length is odd, and the total remaining length is bigger, make sure it's even. */ if ((dev->max_transfer_len & 1) && (dev->max_transfer_len < len)) - dev->max_transfer_len &= 0xfffe; + dev->max_transfer_len &= 0xfffe; /* If the DRQ length is smaller or equal in size to the total remaining length, set it to that. */ if (!dev->max_transfer_len) - dev->max_transfer_len = 65534; + dev->max_transfer_len = 65534; if ((len <= dev->max_transfer_len) && (len >= min_len)) - dev->request_length = dev->max_transfer_len = len; + dev->tf->request_length = dev->max_transfer_len = len; else if (len > dev->max_transfer_len) - dev->request_length = dev->max_transfer_len; + dev->tf->request_length = dev->max_transfer_len; return; } - static double mo_bus_speed(mo_t *dev) { double ret = -1.0; if (dev && dev->drv && (dev->drv->bus_type == MO_BUS_SCSI)) { - dev->callback = -1.0; /* Speed depends on SCSI controller */ - return 0.0; + dev->callback = -1.0; /* Speed depends on SCSI controller */ + return 0.0; } else { - if (dev && dev->drv) - ret = ide_atapi_get_period(dev->drv->ide_channel); - if (ret == -1.0) { - if (dev) - dev->callback = -1.0; - return 0.0; - } else - return ret * 1000000.0; + if (dev && dev->drv) + ret = ide_atapi_get_period(dev->drv->ide_channel); + if (ret == -1.0) { + if (dev) + dev->callback = -1.0; + return 0.0; + } else + return ret * 1000000.0; } } - static void mo_command_common(mo_t *dev) { - double bytes_per_second, period; + double bytes_per_second; + double period; - dev->status = BUSY_STAT; - dev->phase = 1; - dev->pos = 0; + dev->tf->status = BUSY_STAT; + dev->tf->phase = 1; + dev->tf->pos = 0; if (dev->packet_status == PHASE_COMPLETE) - dev->callback = 0.0; + dev->callback = 0.0; else { - if (dev->drv->bus_type == MO_BUS_SCSI) { - dev->callback = -1.0; /* Speed depends on SCSI controller */ - return; - } else - bytes_per_second = mo_bus_speed(dev); + if (dev->drv->bus_type == MO_BUS_SCSI) { + dev->callback = -1.0; /* Speed depends on SCSI controller */ + return; + } else + bytes_per_second = mo_bus_speed(dev); - period = 1000000.0 / bytes_per_second; - dev->callback = period * (double) (dev->packet_len); + period = 1000000.0 / bytes_per_second; + dev->callback = period * (double) (dev->packet_len); } mo_set_callback(dev); } - static void mo_command_complete(mo_t *dev) { @@ -745,7 +701,6 @@ mo_command_complete(mo_t *dev) mo_command_common(dev); } - static void mo_command_read(mo_t *dev) { @@ -753,7 +708,6 @@ mo_command_read(mo_t *dev) mo_command_common(dev); } - static void mo_command_read_dma(mo_t *dev) { @@ -761,7 +715,6 @@ mo_command_read_dma(mo_t *dev) mo_command_common(dev); } - static void mo_command_write(mo_t *dev) { @@ -769,7 +722,6 @@ mo_command_write(mo_t *dev) mo_command_common(dev); } - static void mo_command_write_dma(mo_t *dev) { @@ -777,7 +729,6 @@ mo_command_write_dma(mo_t *dev) mo_command_common(dev); } - /* id = Current MO device ID; len = Total transfer length; block_len = Length of a single block (why does it matter?!); @@ -787,116 +738,110 @@ static void mo_data_command_finish(mo_t *dev, int len, int block_len, int alloc_len, int direction) { mo_log("MO %i: Finishing command (%02X): %i, %i, %i, %i, %i\n", - dev->id, dev->current_cdb[0], len, block_len, alloc_len, direction, dev->request_length); - dev->pos = 0; + dev->id, dev->current_cdb[0], len, block_len, alloc_len, direction, dev->tf->request_length); + dev->tf->pos = 0; if (alloc_len >= 0) { - if (alloc_len < len) - len = alloc_len; + if (alloc_len < len) + len = alloc_len; } if ((len == 0) || (mo_current_mode(dev) == 0)) { - if (dev->drv->bus_type != MO_BUS_SCSI) - dev->packet_len = 0; + if (dev->drv->bus_type != MO_BUS_SCSI) + dev->packet_len = 0; - mo_command_complete(dev); + mo_command_complete(dev); } else { - if (mo_current_mode(dev) == 2) { - if (dev->drv->bus_type != MO_BUS_SCSI) - dev->packet_len = alloc_len; + if (mo_current_mode(dev) == 2) { + if (dev->drv->bus_type != MO_BUS_SCSI) + dev->packet_len = alloc_len; - if (direction == 0) - mo_command_read_dma(dev); - else - mo_command_write_dma(dev); - } else { - mo_update_request_length(dev, len, block_len); - if (direction == 0) - mo_command_read(dev); - else - mo_command_write(dev); - } + if (direction == 0) + mo_command_read_dma(dev); + else + mo_command_write_dma(dev); + } else { + mo_update_request_length(dev, len, block_len); + if (direction == 0) + mo_command_read(dev); + else + mo_command_write(dev); + } } mo_log("MO %i: Status: %i, cylinder %i, packet length: %i, position: %i, phase: %i\n", - dev->id, dev->packet_status, dev->request_length, dev->packet_len, dev->pos, dev->phase); + dev->id, dev->packet_status, dev->tf->request_length, dev->packet_len, dev->tf->pos, + dev->tf->phase); } - static void -mo_sense_clear(mo_t *dev, int command) +mo_sense_clear(mo_t *dev, UNUSED(int command)) { mo_sense_key = mo_asc = mo_ascq = 0; } - static void mo_set_phase(mo_t *dev, uint8_t phase) { uint8_t scsi_bus = (dev->drv->scsi_device_id >> 4) & 0x0f; - uint8_t scsi_id = dev->drv->scsi_device_id & 0x0f; + uint8_t scsi_id = dev->drv->scsi_device_id & 0x0f; if (dev->drv->bus_type != MO_BUS_SCSI) - return; + return; scsi_devices[scsi_bus][scsi_id].phase = phase; } - static void mo_cmd_error(mo_t *dev) { mo_set_phase(dev, SCSI_PHASE_STATUS); - dev->error = ((mo_sense_key & 0xf) << 4) | ABRT_ERR; + dev->tf->error = ((mo_sense_key & 0xf) << 4) | ABRT_ERR; if (dev->unit_attention) - dev->error |= MCR_ERR; - dev->status = READY_STAT | ERR_STAT; - dev->phase = 3; - dev->pos = 0; - dev->packet_status = PHASE_ERROR; - dev->callback = 50.0 * MO_TIME; + dev->tf->error |= MCR_ERR; + dev->tf->status = READY_STAT | ERR_STAT; + dev->tf->phase = 3; + dev->tf->pos = 0; + dev->packet_status = PHASE_ERROR; + dev->callback = 50.0 * MO_TIME; mo_set_callback(dev); ui_sb_update_icon(SB_MO | dev->id, 0); mo_log("MO %i: [%02X] ERROR: %02X/%02X/%02X\n", dev->id, dev->current_cdb[0], mo_sense_key, mo_asc, mo_ascq); } - static void mo_unit_attention(mo_t *dev) { mo_set_phase(dev, SCSI_PHASE_STATUS); - dev->error = (SENSE_UNIT_ATTENTION << 4) | ABRT_ERR; + dev->tf->error = (SENSE_UNIT_ATTENTION << 4) | ABRT_ERR; if (dev->unit_attention) - dev->error |= MCR_ERR; - dev->status = READY_STAT | ERR_STAT; - dev->phase = 3; - dev->pos = 0; - dev->packet_status = PHASE_ERROR; - dev->callback = 50.0 * MO_TIME; + dev->tf->error |= MCR_ERR; + dev->tf->status = READY_STAT | ERR_STAT; + dev->tf->phase = 3; + dev->tf->pos = 0; + dev->packet_status = PHASE_ERROR; + dev->callback = 50.0 * MO_TIME; mo_set_callback(dev); ui_sb_update_icon(SB_MO | dev->id, 0); mo_log("MO %i: UNIT ATTENTION\n", dev->id); } - static void mo_buf_alloc(mo_t *dev, uint32_t len) { mo_log("MO %i: Allocated buffer length: %i\n", dev->id, len); if (!dev->buffer) - dev->buffer = (uint8_t *) malloc(len); + dev->buffer = (uint8_t *) malloc(len); } - static void mo_buf_free(mo_t *dev) { if (dev->buffer) { - mo_log("MO %i: Freeing buffer...\n", dev->id); - free(dev->buffer); - dev->buffer = NULL; + mo_log("MO %i: Freeing buffer...\n", dev->id); + free(dev->buffer); + dev->buffer = NULL; } } - static void mo_bus_master_error(scsi_common_t *sc) { @@ -907,114 +852,105 @@ mo_bus_master_error(scsi_common_t *sc) mo_cmd_error(dev); } - static void mo_not_ready(mo_t *dev) { mo_sense_key = SENSE_NOT_READY; - mo_asc = ASC_MEDIUM_NOT_PRESENT; - mo_ascq = 0; + mo_asc = ASC_MEDIUM_NOT_PRESENT; + mo_ascq = 0; mo_cmd_error(dev); } - static void mo_write_protected(mo_t *dev) { mo_sense_key = SENSE_UNIT_ATTENTION; - mo_asc = ASC_WRITE_PROTECTED; - mo_ascq = 0; + mo_asc = ASC_WRITE_PROTECTED; + mo_ascq = 0; mo_cmd_error(dev); } - static void mo_invalid_lun(mo_t *dev) { mo_sense_key = SENSE_ILLEGAL_REQUEST; - mo_asc = ASC_INV_LUN; - mo_ascq = 0; + mo_asc = ASC_INV_LUN; + mo_ascq = 0; mo_cmd_error(dev); } - static void mo_illegal_opcode(mo_t *dev) { mo_sense_key = SENSE_ILLEGAL_REQUEST; - mo_asc = ASC_ILLEGAL_OPCODE; - mo_ascq = 0; + mo_asc = ASC_ILLEGAL_OPCODE; + mo_ascq = 0; mo_cmd_error(dev); } - static void mo_lba_out_of_range(mo_t *dev) { mo_sense_key = SENSE_ILLEGAL_REQUEST; - mo_asc = ASC_LBA_OUT_OF_RANGE; - mo_ascq = 0; + mo_asc = ASC_LBA_OUT_OF_RANGE; + mo_ascq = 0; mo_cmd_error(dev); } - static void mo_invalid_field(mo_t *dev) { mo_sense_key = SENSE_ILLEGAL_REQUEST; - mo_asc = ASC_INV_FIELD_IN_CMD_PACKET; - mo_ascq = 0; + mo_asc = ASC_INV_FIELD_IN_CMD_PACKET; + mo_ascq = 0; mo_cmd_error(dev); - dev->status = 0x53; + dev->tf->status = 0x53; } - static void mo_invalid_field_pl(mo_t *dev) { mo_sense_key = SENSE_ILLEGAL_REQUEST; - mo_asc = ASC_INV_FIELD_IN_PARAMETER_LIST; - mo_ascq = 0; + mo_asc = ASC_INV_FIELD_IN_PARAMETER_LIST; + mo_ascq = 0; mo_cmd_error(dev); - dev->status = 0x53; + dev->tf->status = 0x53; } - static int -mo_blocks(mo_t *dev, int32_t *len, int first_batch, int out) +mo_blocks(mo_t *dev, int32_t *len, UNUSED(int first_batch), int out) { *len = 0; - int i; if (!dev->sector_len) { - mo_command_complete(dev); - return -1; + mo_command_complete(dev); + return -1; } mo_log("%sing %i blocks starting from %i...\n", out ? "Writ" : "Read", dev->requested_blocks, dev->sector_pos); if (dev->sector_pos >= dev->drv->medium_size) { - mo_log("MO %i: Trying to %s beyond the end of disk\n", dev->id, out ? "write" : "read"); - mo_lba_out_of_range(dev); - return 0; + mo_log("MO %i: Trying to %s beyond the end of disk\n", dev->id, out ? "write" : "read"); + mo_lba_out_of_range(dev); + return 0; } *len = dev->requested_blocks * dev->drv->sector_size; - for (i = 0; i < dev->requested_blocks; i++) { - if (fseek(dev->drv->f, dev->drv->base + (dev->sector_pos * dev->drv->sector_size) + (i * dev->drv->sector_size), SEEK_SET) == 1) - break; + for (int i = 0; i < dev->requested_blocks; i++) { + if (fseek(dev->drv->fp, dev->drv->base + (dev->sector_pos * dev->drv->sector_size) + (i * dev->drv->sector_size), SEEK_SET) == 1) + break; - if (feof(dev->drv->f)) - break; + if (feof(dev->drv->fp)) + break; - if (out) { - if (fwrite(dev->buffer + (i * dev->drv->sector_size), 1, dev->drv->sector_size, dev->drv->f) != dev->drv->sector_size) - fatal("mo_blocks(): Error writing data\n"); - } else { - if (fread(dev->buffer + (i * dev->drv->sector_size), 1, dev->drv->sector_size, dev->drv->f) != dev->drv->sector_size) - fatal("mo_blocks(): Error reading data\n"); - } + if (out) { + if (fwrite(dev->buffer + (i * dev->drv->sector_size), 1, dev->drv->sector_size, dev->drv->fp) != dev->drv->sector_size) + fatal("mo_blocks(): Error writing data\n"); + } else { + if (fread(dev->buffer + (i * dev->drv->sector_size), 1, dev->drv->sector_size, dev->drv->fp) != dev->drv->sector_size) + fatal("mo_blocks(): Error reading data\n"); + } } mo_log("%s %i bytes of blocks...\n", out ? "Written" : "Read", *len); @@ -1025,7 +961,6 @@ mo_blocks(mo_t *dev, int32_t *len, int first_batch, int out) return 1; } - void mo_insert(mo_t *dev) { @@ -1036,66 +971,66 @@ void mo_format(mo_t *dev) { long size; - int ret; - int fd; + int ret; + int fd; mo_log("MO %i: Formatting media...\n", dev->id); - fseek(dev->drv->f, 0, SEEK_END); - size = ftell(dev->drv->f); + fseek(dev->drv->fp, 0, SEEK_END); + size = ftell(dev->drv->fp); #ifdef _WIN32 - HANDLE fh; + HANDLE fh; LARGE_INTEGER liSize; - fd = _fileno(dev->drv->f); - fh = (HANDLE)_get_osfhandle(fd); + fd = _fileno(dev->drv->fp); + fh = (HANDLE) _get_osfhandle(fd); liSize.QuadPart = 0; - ret = (int)SetFilePointerEx(fh, liSize, NULL, FILE_BEGIN); + ret = (int) SetFilePointerEx(fh, liSize, NULL, FILE_BEGIN); - if(!ret) { - mo_log("MO %i: Failed seek to start of image file\n", dev->id); - return; + if (!ret) { + mo_log("MO %i: Failed seek to start of image file\n", dev->id); + return; } - ret = (int)SetEndOfFile(fh); + ret = (int) SetEndOfFile(fh); - if(!ret) { - mo_log("MO %i: Failed to truncate image file to 0\n", dev->id); - return; + if (!ret) { + mo_log("MO %i: Failed to truncate image file to 0\n", dev->id); + return; } liSize.QuadPart = size; - ret = (int)SetFilePointerEx(fh, liSize, NULL, FILE_BEGIN); + ret = (int) SetFilePointerEx(fh, liSize, NULL, FILE_BEGIN); - if(!ret) { - mo_log("MO %i: Failed seek to end of image file\n", dev->id); - return; + if (!ret) { + mo_log("MO %i: Failed seek to end of image file\n", dev->id); + return; } - ret = (int)SetEndOfFile(fh); + ret = (int) SetEndOfFile(fh); - if(!ret) { - mo_log("MO %i: Failed to truncate image file to %llu\n", dev->id, size); - return; + if (!ret) { + mo_log("MO %i: Failed to truncate image file to %llu\n", dev->id, size); + return; } #else - fd = fileno(dev->drv->f); + fd = fileno(dev->drv->fp); ret = ftruncate(fd, 0); - if(ret) { - mo_log("MO %i: Failed to truncate image file to 0\n", dev->id); - return; + if (ret) { + mo_log("MO %i: Failed to truncate image file to 0\n", dev->id); + return; } ret = ftruncate(fd, size); - if(ret) { - mo_log("MO %i: Failed to truncate image file to %llu", dev->id, size); - return; + if (ret) { + mo_log("MO %i: Failed to truncate image file to %llu", dev->id, size); + return; } #endif } @@ -1105,29 +1040,29 @@ mo_erase(mo_t *dev) { int i; - if (! dev->sector_len) { - mo_command_complete(dev); - return -1; + if (!dev->sector_len) { + mo_command_complete(dev); + return -1; } mo_log("MO %i: Erasing %i blocks starting from %i...\n", dev->id, dev->sector_len, dev->sector_pos); if (dev->sector_pos >= dev->drv->medium_size) { - mo_log("MO %i: Trying to erase beyond the end of disk\n", dev->id); - mo_lba_out_of_range(dev); - return 0; + mo_log("MO %i: Trying to erase beyond the end of disk\n", dev->id); + mo_lba_out_of_range(dev); + return 0; } mo_buf_alloc(dev, dev->drv->sector_size); memset(dev->buffer, 0, dev->drv->sector_size); - fseek(dev->drv->f, dev->drv->base + (dev->sector_pos * dev->drv->sector_size), SEEK_SET); + fseek(dev->drv->fp, dev->drv->base + (dev->sector_pos * dev->drv->sector_size), SEEK_SET); for (i = 0; i < dev->requested_blocks; i++) { - if (feof(dev->drv->f)) - break; + if (feof(dev->drv->fp)) + break; - fwrite(dev->buffer, 1, dev->drv->sector_size, dev->drv->f); + fwrite(dev->buffer, 1, dev->drv->sector_size, dev->drv->fp); } mo_log("MO %i: Erased %i bytes of blocks...\n", dev->id, i * dev->drv->sector_size); @@ -1141,82 +1076,80 @@ mo_erase(mo_t *dev) /*SCSI Sense Initialization*/ void mo_sense_code_ok(mo_t *dev) -{ +{ mo_sense_key = SENSE_NONE; - mo_asc = 0; - mo_ascq = 0; + mo_asc = 0; + mo_ascq = 0; } - static int mo_pre_execution_check(mo_t *dev, uint8_t *cdb) { int ready = 0; - if (dev->drv->bus_type == MO_BUS_SCSI) { - if ((cdb[0] != GPCMD_REQUEST_SENSE) && (dev->cur_lun == SCSI_LUN_USE_CDB) && (cdb[1] & 0xe0)) { - mo_log("MO %i: Attempting to execute a unknown command targeted at SCSI LUN %i\n", dev->id, ((dev->request_length >> 5) & 7)); - mo_invalid_lun(dev); - return 0; - } + if ((cdb[0] != GPCMD_REQUEST_SENSE) && (dev->cur_lun == SCSI_LUN_USE_CDB) && (cdb[1] & 0xe0)) { + mo_log("MO %i: Attempting to execute a unknown command targeted at SCSI LUN %i\n", dev->id, + ((dev->tf->request_length >> 5) & 7)); + mo_invalid_lun(dev); + return 0; } if (!(mo_command_flags[cdb[0]] & IMPLEMENTED)) { - mo_log("MO %i: Attempting to execute unknown command %02X over %s\n", dev->id, cdb[0], - (dev->drv->bus_type == MO_BUS_SCSI) ? "SCSI" : "ATAPI"); + mo_log("MO %i: Attempting to execute unknown command %02X over %s\n", dev->id, cdb[0], + (dev->drv->bus_type == MO_BUS_SCSI) ? "SCSI" : "ATAPI"); - mo_illegal_opcode(dev); - return 0; + mo_illegal_opcode(dev); + return 0; } if ((dev->drv->bus_type < MO_BUS_SCSI) && (mo_command_flags[cdb[0]] & SCSI_ONLY)) { - mo_log("MO %i: Attempting to execute SCSI-only command %02X over ATAPI\n", dev->id, cdb[0]); - mo_illegal_opcode(dev); - return 0; + mo_log("MO %i: Attempting to execute SCSI-only command %02X over ATAPI\n", dev->id, cdb[0]); + mo_illegal_opcode(dev); + return 0; } if ((dev->drv->bus_type == MO_BUS_SCSI) && (mo_command_flags[cdb[0]] & ATAPI_ONLY)) { - mo_log("MO %i: Attempting to execute ATAPI-only command %02X over SCSI\n", dev->id, cdb[0]); - mo_illegal_opcode(dev); - return 0; + mo_log("MO %i: Attempting to execute ATAPI-only command %02X over SCSI\n", dev->id, cdb[0]); + mo_illegal_opcode(dev); + return 0; } - ready = (dev->drv->f != NULL); + ready = (dev->drv->fp != NULL); /* If the drive is not ready, there is no reason to keep the UNIT ATTENTION condition present, as we only use it to mark disc changes. */ if (!ready && dev->unit_attention) - dev->unit_attention = 0; + dev->unit_attention = 0; /* If the UNIT ATTENTION condition is set and the command does not allow execution under it, error out and report the condition. */ if (dev->unit_attention == 1) { - /* Only increment the unit attention phase if the command can not pass through it. */ - if (!(mo_command_flags[cdb[0]] & ALLOW_UA)) { - /* mo_log("MO %i: Unit attention now 2\n", dev->id); */ - dev->unit_attention = 2; - mo_log("MO %i: UNIT ATTENTION: Command %02X not allowed to pass through\n", dev->id, cdb[0]); - mo_unit_attention(dev); - return 0; - } + /* Only increment the unit attention phase if the command can not pass through it. */ + if (!(mo_command_flags[cdb[0]] & ALLOW_UA)) { + /* mo_log("MO %i: Unit attention now 2\n", dev->id); */ + dev->unit_attention = 2; + mo_log("MO %i: UNIT ATTENTION: Command %02X not allowed to pass through\n", dev->id, cdb[0]); + mo_unit_attention(dev); + return 0; + } } else if (dev->unit_attention == 2) { - if (cdb[0] != GPCMD_REQUEST_SENSE) { - /* mo_log("MO %i: Unit attention now 0\n", dev->id); */ - dev->unit_attention = 0; - } + if (cdb[0] != GPCMD_REQUEST_SENSE) { + /* mo_log("MO %i: Unit attention now 0\n", dev->id); */ + dev->unit_attention = 0; + } } /* Unless the command is REQUEST SENSE, clear the sense. This will *NOT* the UNIT ATTENTION condition if it's set. */ if (cdb[0] != GPCMD_REQUEST_SENSE) - mo_sense_clear(dev, cdb[0]); + mo_sense_clear(dev, cdb[0]); /* Next it's time for NOT READY. */ if ((mo_command_flags[cdb[0]] & CHECK_READY) && !ready) { - mo_log("MO %i: Not ready (%02X)\n", dev->id, cdb[0]); - mo_not_ready(dev); - return 0; + mo_log("MO %i: Not ready (%02X)\n", dev->id, cdb[0]); + mo_not_ready(dev); + return 0; } mo_log("MO %i: Continuing with command %02X\n", dev->id, cdb[0]); @@ -1224,15 +1157,15 @@ mo_pre_execution_check(mo_t *dev, uint8_t *cdb) return 1; } - static void mo_seek(mo_t *dev, uint32_t pos) { - /* mo_log("MO %i: Seek %08X\n", dev->id, pos); */ - dev->sector_pos = pos; +#if 0 + mo_log("MO %i: Seek %08X\n", dev->id, pos); +#endif + dev->sector_pos = pos; } - static void mo_rezero(mo_t *dev) { @@ -1240,73 +1173,70 @@ mo_rezero(mo_t *dev) mo_seek(dev, 0); } - void mo_reset(scsi_common_t *sc) { mo_t *dev = (mo_t *) sc; mo_rezero(dev); - dev->status = 0; - dev->callback = 0.0; + dev->tf->status = 0; + dev->callback = 0.0; mo_set_callback(dev); - dev->phase = 1; - dev->request_length = 0xEB14; - dev->packet_status = PHASE_NONE; - dev->unit_attention = 0; - dev->cur_lun = SCSI_LUN_USE_CDB; + dev->tf->phase = 1; + dev->tf->request_length = 0xEB14; + dev->packet_status = PHASE_NONE; + dev->unit_attention = 0; + dev->cur_lun = SCSI_LUN_USE_CDB; } - static void mo_request_sense(mo_t *dev, uint8_t *buffer, uint8_t alloc_length, int desc) -{ +{ /*Will return 18 bytes of 0*/ if (alloc_length != 0) { - memset(buffer, 0, alloc_length); - if (!desc) - memcpy(buffer, dev->sense, alloc_length); - else { - buffer[1] = mo_sense_key; - buffer[2] = mo_asc; - buffer[3] = mo_ascq; - } + memset(buffer, 0, alloc_length); + if (!desc) + memcpy(buffer, dev->sense, alloc_length); + else { + buffer[1] = mo_sense_key; + buffer[2] = mo_asc; + buffer[3] = mo_ascq; + } } buffer[0] = desc ? 0x72 : 0x70; if (dev->unit_attention && (mo_sense_key == 0)) { - buffer[desc ? 1 : 2] = SENSE_UNIT_ATTENTION; - buffer[desc ? 2 : 12] = ASC_MEDIUM_MAY_HAVE_CHANGED; - buffer[desc ? 3 : 13] = 0; + buffer[desc ? 1 : 2] = SENSE_UNIT_ATTENTION; + buffer[desc ? 2 : 12] = ASC_MEDIUM_MAY_HAVE_CHANGED; + buffer[desc ? 3 : 13] = 0; } mo_log("MO %i: Reporting sense: %02X %02X %02X\n", dev->id, buffer[2], buffer[12], buffer[13]); if (buffer[desc ? 1 : 2] == SENSE_UNIT_ATTENTION) { - /* If the last remaining sense is unit attention, clear - that condition. */ - dev->unit_attention = 0; + /* If the last remaining sense is unit attention, clear + that condition. */ + dev->unit_attention = 0; } /* Clear the sense stuff as per the spec. */ mo_sense_clear(dev, GPCMD_REQUEST_SENSE); } - static void mo_request_sense_for_scsi(scsi_common_t *sc, uint8_t *buffer, uint8_t alloc_length) { - mo_t *dev = (mo_t *) sc; - int ready = 0; + mo_t *dev = (mo_t *) sc; + int ready = 0; - ready = (dev->drv->f != NULL); + ready = (dev->drv->fp != NULL); if (!ready && dev->unit_attention) { - /* If the drive is not ready, there is no reason to keep the - UNIT ATTENTION condition present, as we only use it to mark - disc changes. */ - dev->unit_attention = 0; + /* If the drive is not ready, there is no reason to keep the + UNIT ATTENTION condition present, as we only use it to mark + disc changes. */ + dev->unit_attention = 0; } /* Do *NOT* advance the unit attention phase. */ @@ -1314,48 +1244,49 @@ mo_request_sense_for_scsi(scsi_common_t *sc, uint8_t *buffer, uint8_t alloc_leng mo_request_sense(dev, buffer, alloc_length, 0); } - static void mo_set_buf_len(mo_t *dev, int32_t *BufLen, int32_t *src_len) { if (dev->drv->bus_type == MO_BUS_SCSI) { - if (*BufLen == -1) - *BufLen = *src_len; - else { - *BufLen = MIN(*src_len, *BufLen); - *src_len = *BufLen; - } - mo_log("MO %i: Actual transfer length: %i\n", dev->id, *BufLen); + if (*BufLen == -1) + *BufLen = *src_len; + else { + *BufLen = MIN(*src_len, *BufLen); + *src_len = *BufLen; + } + mo_log("MO %i: Actual transfer length: %i\n", dev->id, *BufLen); } } - static void mo_command(scsi_common_t *sc, uint8_t *cdb) { - mo_t *dev = (mo_t *) sc; - int pos = 0, block_desc = 0; - int ret; - int32_t len, max_len; - int32_t alloc_length; - int size_idx, idx = 0; + mo_t *dev = (mo_t *) sc; + int pos = 0; + int block_desc = 0; + int ret; + int32_t len; + int32_t max_len; + int32_t alloc_length; + int size_idx; + int idx = 0; unsigned preamble_len; - char device_identify[9] = { '8', '6', 'B', '_', 'M', 'O', '0', '0', 0 }; - int32_t blen = 0; + char device_identify[9] = { '8', '6', 'B', '_', 'M', 'O', '0', '0', 0 }; + int32_t blen = 0; int32_t *BufLen; uint32_t previous_pos = 0; - uint8_t scsi_bus = (dev->drv->scsi_device_id >> 4) & 0x0f; - uint8_t scsi_id = dev->drv->scsi_device_id & 0x0f; + uint8_t scsi_bus = (dev->drv->scsi_device_id >> 4) & 0x0f; + uint8_t scsi_id = dev->drv->scsi_device_id & 0x0f; if (dev->drv->bus_type == MO_BUS_SCSI) { - BufLen = &scsi_devices[scsi_bus][scsi_id].buffer_length; - dev->status &= ~ERR_STAT; + BufLen = &scsi_devices[scsi_bus][scsi_id].buffer_length; + dev->tf->status &= ~ERR_STAT; } else { - BufLen = &blen; - dev->error = 0; + BufLen = &blen; + dev->tf->error = 0; } - dev->packet_len = 0; + dev->packet_len = 0; dev->request_pos = 0; device_identify[7] = dev->id + 0x30; @@ -1363,13 +1294,13 @@ mo_command(scsi_common_t *sc, uint8_t *cdb) memcpy(dev->current_cdb, cdb, 12); if (cdb[0] != 0) { - mo_log("MO %i: Command 0x%02X, Sense Key %02X, Asc %02X, Ascq %02X, Unit attention: %i\n", - dev->id, cdb[0], mo_sense_key, mo_asc, mo_ascq, dev->unit_attention); - mo_log("MO %i: Request length: %04X\n", dev->id, dev->request_length); + mo_log("MO %i: Command 0x%02X, Sense Key %02X, Asc %02X, Ascq %02X, Unit attention: %i\n", + dev->id, cdb[0], mo_sense_key, mo_asc, mo_ascq, dev->unit_attention); + mo_log("MO %i: Request length: %04X\n", dev->id, dev->tf->request_length); - mo_log("MO %i: CDB: %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X\n", dev->id, - cdb[0], cdb[1], cdb[2], cdb[3], cdb[4], cdb[5], cdb[6], cdb[7], - cdb[8], cdb[9], cdb[10], cdb[11]); + mo_log("MO %i: CDB: %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X\n", dev->id, + cdb[0], cdb[1], cdb[2], cdb[3], cdb[4], cdb[5], cdb[6], cdb[7], + cdb[8], cdb[9], cdb[10], cdb[11]); } dev->sector_len = 0; @@ -1378,516 +1309,538 @@ mo_command(scsi_common_t *sc, uint8_t *cdb) /* This handles the Not Ready/Unit Attention check if it has to be handled at this point. */ if (mo_pre_execution_check(dev, cdb) == 0) - return; + return; switch (cdb[0]) { - case GPCMD_SEND_DIAGNOSTIC: - if (!(cdb[1] & (1 << 2))) { - mo_invalid_field(dev); - return; - } - /*FALLTHROUGH*/ - case GPCMD_SCSI_RESERVE: - case GPCMD_SCSI_RELEASE: - case GPCMD_TEST_UNIT_READY: - mo_set_phase(dev, SCSI_PHASE_STATUS); - mo_command_complete(dev); - break; - - case GPCMD_FORMAT_UNIT: - if (dev->drv->read_only) { - mo_write_protected(dev); - return; - } - - mo_format(dev); - mo_set_phase(dev, SCSI_PHASE_STATUS); - mo_command_complete(dev); - break; - - case GPCMD_REZERO_UNIT: - dev->sector_pos = dev->sector_len = 0; - mo_seek(dev, 0); - mo_set_phase(dev, SCSI_PHASE_STATUS); - break; - - case GPCMD_REQUEST_SENSE: - /* If there's a unit attention condition and there's a buffered not ready, a standalone REQUEST SENSE - should forget about the not ready, and report unit attention straight away. */ - mo_set_phase(dev, SCSI_PHASE_DATA_IN); - max_len = cdb[4]; - - if (!max_len) { - mo_set_phase(dev, SCSI_PHASE_STATUS); - dev->packet_status = PHASE_COMPLETE; - dev->callback = 20.0 * MO_TIME; - mo_set_callback(dev); - break; - } - - mo_buf_alloc(dev, 256); - mo_set_buf_len(dev, BufLen, &max_len); - len = (cdb[1] & 1) ? 8 : 18; - mo_request_sense(dev, dev->buffer, max_len, cdb[1] & 1); - mo_data_command_finish(dev, len, len, cdb[4], 0); - break; - - case GPCMD_MECHANISM_STATUS: - mo_set_phase(dev, SCSI_PHASE_DATA_IN); - len = (cdb[8] << 8) | cdb[9]; - - mo_buf_alloc(dev, 8); - mo_set_buf_len(dev, BufLen, &len); - - memset(dev->buffer, 0, 8); - dev->buffer[5] = 1; - - mo_data_command_finish(dev, 8, 8, len, 0); - break; - - case GPCMD_READ_6: - case GPCMD_READ_10: - case GPCMD_READ_12: - mo_set_phase(dev, SCSI_PHASE_DATA_IN); - alloc_length = dev->drv->sector_size; - - switch(cdb[0]) { - case GPCMD_READ_6: - dev->sector_len = cdb[4]; - dev->sector_pos = ((((uint32_t) cdb[1]) & 0x1f) << 16) | (((uint32_t) cdb[2]) << 8) | ((uint32_t) cdb[3]); - if (dev->sector_len == 0) - dev->sector_len = 256; - mo_log("MO %i: Length: %i, LBA: %i\n", dev->id, dev->sector_len, dev->sector_pos); - break; - case GPCMD_READ_10: - dev->sector_len = (cdb[7] << 8) | cdb[8]; - dev->sector_pos = (cdb[2] << 24) | (cdb[3] << 16) | (cdb[4] << 8) | cdb[5]; - mo_log("MO %i: Length: %i, LBA: %i\n", dev->id, dev->sector_len, dev->sector_pos); - break; - case GPCMD_READ_12: - dev->sector_len = (((uint32_t) cdb[6]) << 24) | (((uint32_t) cdb[7]) << 16) | (((uint32_t) cdb[8]) << 8) | ((uint32_t) cdb[9]); - dev->sector_pos = (((uint32_t) cdb[2]) << 24) | (((uint32_t) cdb[3]) << 16) | (((uint32_t) cdb[4]) << 8) | ((uint32_t) cdb[5]); - mo_log("MO %i: Length: %i, LBA: %i\n", dev->id, dev->sector_len, dev->sector_pos); - break; - } - - if (!dev->sector_len) { - mo_set_phase(dev, SCSI_PHASE_STATUS); - /* mo_log("MO %i: All done - callback set\n", dev->id); */ - dev->packet_status = PHASE_COMPLETE; - dev->callback = 20.0 * MO_TIME; - mo_set_callback(dev); - break; - } - - max_len = dev->sector_len; - dev->requested_blocks = max_len; /* If we're reading all blocks in one go for DMA, why not also for PIO, it should NOT - matter anyway, this step should be identical and only the way the read dat is - transferred to the host should be different. */ - - dev->packet_len = max_len * alloc_length; - mo_buf_alloc(dev, dev->packet_len); - - ret = mo_blocks(dev, &alloc_length, 1, 0); - if (ret <= 0) { - mo_set_phase(dev, SCSI_PHASE_STATUS); - dev->packet_status = PHASE_COMPLETE; - dev->callback = 20.0 * MO_TIME; - mo_set_callback(dev); - mo_buf_free(dev); - return; - } - - dev->requested_blocks = max_len; - dev->packet_len = alloc_length; - - mo_set_buf_len(dev, BufLen, (int32_t *) &dev->packet_len); - - mo_data_command_finish(dev, alloc_length, dev->drv->sector_size, alloc_length, 0); - - if (dev->packet_status != PHASE_COMPLETE) - ui_sb_update_icon(SB_MO | dev->id, 1); - else - ui_sb_update_icon(SB_MO | dev->id, 0); - return; - - case GPCMD_VERIFY_6: - case GPCMD_VERIFY_10: - case GPCMD_VERIFY_12: - /* Data and blank verification cannot be set at the same time */ - if ((cdb[1] & 2) && (cdb[1] & 4)) { - mo_invalid_field(dev); - return; - } - if (!(cdb[1] & 2) || (cdb[1] & 4)) { - mo_set_phase(dev, SCSI_PHASE_STATUS); - mo_command_complete(dev); - break; - } - /*TODO: Implement*/ - mo_invalid_field(dev); - return; - - case GPCMD_WRITE_6: - case GPCMD_WRITE_10: - case GPCMD_WRITE_AND_VERIFY_10: - case GPCMD_WRITE_12: - case GPCMD_WRITE_AND_VERIFY_12: - mo_set_phase(dev, SCSI_PHASE_DATA_OUT); - alloc_length = dev->drv->sector_size; - - if (dev->drv->read_only) { - mo_write_protected(dev); - return; - } - - switch (cdb[0]) { - case GPCMD_VERIFY_6: - case GPCMD_WRITE_6: - dev->sector_len = cdb[4]; - if (dev->sector_len == 0) - dev->sector_len = 256; /* For READ (6) and WRITE (6), a length of 0 indicates a transfer of 256 sector. */ - dev->sector_pos = ((((uint32_t) cdb[1]) & 0x1f) << 16) | (((uint32_t) cdb[2]) << 8) | ((uint32_t) cdb[3]); - break; - case GPCMD_VERIFY_10: - case GPCMD_WRITE_10: - case GPCMD_WRITE_AND_VERIFY_10: - dev->sector_len = (cdb[7] << 8) | cdb[8]; - dev->sector_pos = (cdb[2] << 24) | (cdb[3] << 16) | (cdb[4] << 8) | cdb[5]; - mo_log("MO %i: Length: %i, LBA: %i\n", dev->id, dev->sector_len, dev->sector_pos); - break; - case GPCMD_VERIFY_12: - case GPCMD_WRITE_12: - case GPCMD_WRITE_AND_VERIFY_12: - dev->sector_len = (((uint32_t) cdb[6]) << 24) | (((uint32_t) cdb[7]) << 16) | (((uint32_t) cdb[8]) << 8) | ((uint32_t) cdb[9]); - dev->sector_pos = (((uint32_t) cdb[2]) << 24) | (((uint32_t) cdb[3]) << 16) | (((uint32_t) cdb[4]) << 8) | ((uint32_t) cdb[5]); - break; - } - - if ((dev->sector_pos >= dev->drv->medium_size)/* || - ((dev->sector_pos + dev->sector_len - 1) >= dev->drv->medium_size)*/) { - mo_lba_out_of_range(dev); - return; - } - - if (!dev->sector_len) { - mo_set_phase(dev, SCSI_PHASE_STATUS); - /* mo_log("MO %i: All done - callback set\n", dev->id); */ - dev->packet_status = PHASE_COMPLETE; - dev->callback = 20.0 * MO_TIME; - mo_set_callback(dev); - break; - } - - max_len = dev->sector_len; - dev->requested_blocks = max_len; /* If we're writing all blocks in one go for DMA, why not also for PIO, it should NOT - matter anyway, this step should be identical and only the way the read dat is - transferred to the host should be different. */ - - dev->packet_len = max_len * alloc_length; - mo_buf_alloc(dev, dev->packet_len); - - dev->requested_blocks = max_len; - dev->packet_len = max_len << 9; - - mo_set_buf_len(dev, BufLen, (int32_t *) &dev->packet_len); - - mo_data_command_finish(dev, dev->packet_len, dev->drv->sector_size, dev->packet_len, 1); - - if (dev->packet_status != PHASE_COMPLETE) - ui_sb_update_icon(SB_MO | dev->id, 1); - else - ui_sb_update_icon(SB_MO | dev->id, 0); - return; - - case GPCMD_MODE_SENSE_6: - case GPCMD_MODE_SENSE_10: - mo_set_phase(dev, SCSI_PHASE_DATA_IN); - - if (dev->drv->bus_type == MO_BUS_SCSI) - block_desc = ((cdb[1] >> 3) & 1) ? 0 : 1; - else - block_desc = 0; - - if (cdb[0] == GPCMD_MODE_SENSE_6) { - len = cdb[4]; - mo_buf_alloc(dev, 256); - } else { - len = (cdb[8] | (cdb[7] << 8)); - mo_buf_alloc(dev, 65536); - } - - if (!(mo_mode_sense_page_flags & (1LL << (uint64_t) (cdb[2] & 0x3f)))) { - mo_invalid_field(dev); - mo_buf_free(dev); - return; - } - - memset(dev->buffer, 0, len); - alloc_length = len; - - if (cdb[0] == GPCMD_MODE_SENSE_6) { - len = mo_mode_sense(dev, dev->buffer, 4, cdb[2], block_desc); - len = MIN(len, alloc_length); - dev->buffer[0] = len - 1; - dev->buffer[1] = 0; - if (block_desc) - dev->buffer[3] = 8; - } else { - len = mo_mode_sense(dev, dev->buffer, 8, cdb[2], block_desc); - len = MIN(len, alloc_length); - dev->buffer[0]=(len - 2) >> 8; - dev->buffer[1]=(len - 2) & 255; - dev->buffer[2] = 0; - if (block_desc) { - dev->buffer[6] = 0; - dev->buffer[7] = 8; - } - } - - mo_set_buf_len(dev, BufLen, &len); - - mo_log("MO %i: Reading mode page: %02X...\n", dev->id, cdb[2]); - - mo_data_command_finish(dev, len, len, alloc_length, 0); - return; - - case GPCMD_MODE_SELECT_6: - case GPCMD_MODE_SELECT_10: - mo_set_phase(dev, SCSI_PHASE_DATA_OUT); - - if (cdb[0] == GPCMD_MODE_SELECT_6) { - len = cdb[4]; - mo_buf_alloc(dev, 256); - } else { - len = (cdb[7] << 8) | cdb[8]; - mo_buf_alloc(dev, 65536); - } - - mo_set_buf_len(dev, BufLen, &len); - - dev->total_length = len; - dev->do_page_save = cdb[1] & 1; - - mo_data_command_finish(dev, len, len, len, 1); - return; - - case GPCMD_START_STOP_UNIT: - mo_set_phase(dev, SCSI_PHASE_STATUS); - - switch(cdb[4] & 3) { - case 0: /* Stop the disk. */ - break; - case 1: /* Start the disk and read the TOC. */ - break; - case 2: /* Eject the disk if possible. */ - mo_eject(dev->id); - break; - case 3: /* Load the disk (close tray). */ - mo_reload(dev->id); - break; - } - - mo_command_complete(dev); - break; - - case GPCMD_INQUIRY: - mo_set_phase(dev, SCSI_PHASE_DATA_IN); - - max_len = cdb[3]; - max_len <<= 8; - max_len |= cdb[4]; - - mo_buf_alloc(dev, 65536); - - if (cdb[1] & 1) { - preamble_len = 4; - size_idx = 3; - - dev->buffer[idx++] = 7; /*Optical disk*/ - dev->buffer[idx++] = cdb[2]; - dev->buffer[idx++] = 0; - - idx++; - - switch (cdb[2]) { - case 0x00: - dev->buffer[idx++] = 0x00; - dev->buffer[idx++] = 0x80; - break; - case 0x80: /*Unit serial number page*/ - dev->buffer[idx++] = strlen("VCM!10") + 1; - ide_padstr8(dev->buffer + idx, 20, "VCM!10"); /* Serial */ - idx += strlen("VCM!10"); - break; - default: - mo_log("INQUIRY: Invalid page: %02X\n", cdb[2]); - mo_invalid_field(dev); - mo_buf_free(dev); - return; - } - } else { - preamble_len = 5; - size_idx = 4; - - memset(dev->buffer, 0, 8); - if (cdb[1] & 0xe0) - dev->buffer[0] = 0x60; /*No physical device on this LUN*/ - else - dev->buffer[0] = 0x07; /*Optical disk*/ - dev->buffer[1] = 0x80; /*Removable*/ - dev->buffer[2] = (dev->drv->bus_type == MO_BUS_SCSI) ? 0x02 : 0x00; /*SCSI-2 compliant*/ - dev->buffer[3] = (dev->drv->bus_type == MO_BUS_SCSI) ? 0x02 : 0x21; - // dev->buffer[4] = 31; - dev->buffer[4] = 0; - if (dev->drv->bus_type == MO_BUS_SCSI) { - dev->buffer[6] = 1; /* 16-bit transfers supported */ - dev->buffer[7] = 0x20; /* Wide bus supported */ - } - dev->buffer[7] |= 0x02; - - if (dev->drv->type > 0) { - ide_padstr8(dev->buffer + 8, 8, mo_drive_types[dev->drv->type].vendor); /* Vendor */ - ide_padstr8(dev->buffer + 16, 16, mo_drive_types[dev->drv->type].model); /* Product */ - ide_padstr8(dev->buffer + 32, 4, mo_drive_types[dev->drv->type].revision); /* Revision */ - } else { - ide_padstr8(dev->buffer + 8, 8, EMU_NAME); /* Vendor */ - ide_padstr8(dev->buffer + 16, 16, device_identify); /* Product */ - ide_padstr8(dev->buffer + 32, 4, EMU_VERSION_EX); /* Revision */ - } - idx = 36; - - if (max_len == 96) { - dev->buffer[4] = 91; - idx = 96; - } else if (max_len == 128) { - dev->buffer[4] = 0x75; - idx = 128; - } - } - - dev->buffer[size_idx] = idx - preamble_len; - len=idx; - - len = MIN(len, max_len); - mo_set_buf_len(dev, BufLen, &len); - - mo_data_command_finish(dev, len, len, max_len, 0); - break; - - case GPCMD_PREVENT_REMOVAL: - mo_set_phase(dev, SCSI_PHASE_STATUS); - mo_command_complete(dev); - break; - - case GPCMD_SEEK_6: - case GPCMD_SEEK_10: - mo_set_phase(dev, SCSI_PHASE_STATUS); - - switch(cdb[0]) { - case GPCMD_SEEK_6: - pos = (cdb[2] << 8) | cdb[3]; - break; - case GPCMD_SEEK_10: - pos = (cdb[2] << 24) | (cdb[3] << 16) | (cdb[4] << 8) | cdb[5]; - break; - } - mo_seek(dev, pos); - mo_command_complete(dev); - break; - - case GPCMD_READ_CDROM_CAPACITY: - mo_set_phase(dev, SCSI_PHASE_DATA_IN); - - mo_buf_alloc(dev, 8); - - max_len = dev->drv->medium_size - 1; /* IMPORTANT: What's returned is the last LBA block. */ - memset(dev->buffer, 0, 8); - dev->buffer[0] = (max_len >> 24) & 0xff; - dev->buffer[1] = (max_len >> 16) & 0xff; - dev->buffer[2] = (max_len >> 8) & 0xff; - dev->buffer[3] = max_len & 0xff; - dev->buffer[6] = (dev->drv->sector_size >> 8) & 0xff; - dev->buffer[7] = dev->drv->sector_size & 0xff; - len = 8; - - mo_set_buf_len(dev, BufLen, &len); - - mo_data_command_finish(dev, len, len, len, 0); - break; - - case GPCMD_ERASE_10: - case GPCMD_ERASE_12: - /*Relative address*/ - if ((cdb[1] & 1)) - previous_pos = dev->sector_pos; - - switch (cdb[0]) { - case GPCMD_ERASE_10: - dev->sector_len = (cdb[7] << 8) | cdb[8]; - break; - case GPCMD_ERASE_12: - dev->sector_len = (((uint32_t) cdb[6]) << 24) | (((uint32_t) cdb[7]) << 16) | (((uint32_t) cdb[8]) << 8) | ((uint32_t) cdb[9]); - break; - } - - /*Erase all remaining sectors*/ - if ((cdb[1] & 4)) { - /* Cannot have a sector number when erase all*/ - if (dev->sector_len) { - mo_invalid_field(dev); - return; - } - mo_format(dev); - mo_set_phase(dev, SCSI_PHASE_STATUS); - mo_command_complete(dev); - break; - } - - switch (cdb[0]) { - case GPCMD_ERASE_10: - dev->sector_pos = (cdb[2] << 24) | (cdb[3] << 16) | (cdb[4] << 8) | cdb[5]; - break; - case GPCMD_ERASE_12: - dev->sector_pos = (((uint32_t) cdb[2]) << 24) | (((uint32_t) cdb[3]) << 16) | (((uint32_t) cdb[4]) << 8) | ((uint32_t) cdb[5]); - break; - } - - dev->sector_pos += previous_pos; - - mo_erase(dev); - mo_set_phase(dev, SCSI_PHASE_STATUS); - mo_command_complete(dev); - break; - - /*Never seen media that supports generations but it's interesting to know if any implementation calls this commmand*/ - case GPCMD_READ_GENERATION: - mo_set_phase(dev, SCSI_PHASE_DATA_IN); - - mo_buf_alloc(dev, 4); - len = 4; - - dev->buffer[0] = 0; - dev->buffer[1] = 0; - dev->buffer[2] = 0; - dev->buffer[3] = 0; - - mo_set_buf_len(dev, BufLen, &len); - mo_data_command_finish(dev, len, len, len, 0); - break; - - default: - mo_illegal_opcode(dev); - break; + case GPCMD_SEND_DIAGNOSTIC: + if (!(cdb[1] & (1 << 2))) { + mo_invalid_field(dev); + return; + } + fallthrough; + case GPCMD_SCSI_RESERVE: + case GPCMD_SCSI_RELEASE: + case GPCMD_TEST_UNIT_READY: + mo_set_phase(dev, SCSI_PHASE_STATUS); + mo_command_complete(dev); + break; + + case GPCMD_FORMAT_UNIT: + if (dev->drv->read_only) { + mo_write_protected(dev); + return; + } + + mo_format(dev); + mo_set_phase(dev, SCSI_PHASE_STATUS); + mo_command_complete(dev); + break; + + case GPCMD_REZERO_UNIT: + dev->sector_pos = dev->sector_len = 0; + mo_seek(dev, 0); + mo_set_phase(dev, SCSI_PHASE_STATUS); + break; + + case GPCMD_REQUEST_SENSE: + /* If there's a unit attention condition and there's a buffered not ready, a standalone REQUEST SENSE + should forget about the not ready, and report unit attention straight away. */ + mo_set_phase(dev, SCSI_PHASE_DATA_IN); + max_len = cdb[4]; + + if (!max_len) { + mo_set_phase(dev, SCSI_PHASE_STATUS); + dev->packet_status = PHASE_COMPLETE; + dev->callback = 20.0 * MO_TIME; + mo_set_callback(dev); + break; + } + + mo_buf_alloc(dev, 256); + mo_set_buf_len(dev, BufLen, &max_len); + len = (cdb[1] & 1) ? 8 : 18; + mo_request_sense(dev, dev->buffer, max_len, cdb[1] & 1); + mo_data_command_finish(dev, len, len, cdb[4], 0); + break; + + case GPCMD_MECHANISM_STATUS: + mo_set_phase(dev, SCSI_PHASE_DATA_IN); + len = (cdb[8] << 8) | cdb[9]; + + mo_buf_alloc(dev, 8); + mo_set_buf_len(dev, BufLen, &len); + + memset(dev->buffer, 0, 8); + dev->buffer[5] = 1; + + mo_data_command_finish(dev, 8, 8, len, 0); + break; + + case GPCMD_READ_6: + case GPCMD_READ_10: + case GPCMD_READ_12: + mo_set_phase(dev, SCSI_PHASE_DATA_IN); + alloc_length = dev->drv->sector_size; + + switch (cdb[0]) { + case GPCMD_READ_6: + dev->sector_len = cdb[4]; + dev->sector_pos = ((((uint32_t) cdb[1]) & 0x1f) << 16) | (((uint32_t) cdb[2]) << 8) | ((uint32_t) cdb[3]); + if (dev->sector_len == 0) + dev->sector_len = 256; + mo_log("MO %i: Length: %i, LBA: %i\n", dev->id, dev->sector_len, dev->sector_pos); + break; + case GPCMD_READ_10: + dev->sector_len = (cdb[7] << 8) | cdb[8]; + dev->sector_pos = (cdb[2] << 24) | (cdb[3] << 16) | (cdb[4] << 8) | cdb[5]; + mo_log("MO %i: Length: %i, LBA: %i\n", dev->id, dev->sector_len, dev->sector_pos); + break; + case GPCMD_READ_12: + dev->sector_len = (((uint32_t) cdb[6]) << 24) | (((uint32_t) cdb[7]) << 16) | (((uint32_t) cdb[8]) << 8) | ((uint32_t) cdb[9]); + dev->sector_pos = (((uint32_t) cdb[2]) << 24) | (((uint32_t) cdb[3]) << 16) | (((uint32_t) cdb[4]) << 8) | ((uint32_t) cdb[5]); + mo_log("MO %i: Length: %i, LBA: %i\n", dev->id, dev->sector_len, dev->sector_pos); + break; + + default: + break; + } + + if (!dev->sector_len) { + mo_set_phase(dev, SCSI_PHASE_STATUS); + /* mo_log("MO %i: All done - callback set\n", dev->id); */ + dev->packet_status = PHASE_COMPLETE; + dev->callback = 20.0 * MO_TIME; + mo_set_callback(dev); + break; + } + + max_len = dev->sector_len; + dev->requested_blocks = max_len; /* If we're reading all blocks in one go for DMA, why not also for PIO, it should NOT + matter anyway, this step should be identical and only the way the read dat is + transferred to the host should be different. */ + + dev->packet_len = max_len * alloc_length; + mo_buf_alloc(dev, dev->packet_len); + + ret = mo_blocks(dev, &alloc_length, 1, 0); + if (ret <= 0) { + mo_set_phase(dev, SCSI_PHASE_STATUS); + dev->packet_status = PHASE_COMPLETE; + dev->callback = 20.0 * MO_TIME; + mo_set_callback(dev); + mo_buf_free(dev); + return; + } + + dev->requested_blocks = max_len; + dev->packet_len = alloc_length; + + mo_set_buf_len(dev, BufLen, (int32_t *) &dev->packet_len); + + mo_data_command_finish(dev, alloc_length, dev->drv->sector_size, alloc_length, 0); + + if (dev->packet_status != PHASE_COMPLETE) + ui_sb_update_icon(SB_MO | dev->id, 1); + else + ui_sb_update_icon(SB_MO | dev->id, 0); + return; + + case GPCMD_VERIFY_6: + case GPCMD_VERIFY_10: + case GPCMD_VERIFY_12: + /* Data and blank verification cannot be set at the same time */ + if ((cdb[1] & 2) && (cdb[1] & 4)) { + mo_invalid_field(dev); + return; + } + if (!(cdb[1] & 2) || (cdb[1] & 4)) { + mo_set_phase(dev, SCSI_PHASE_STATUS); + mo_command_complete(dev); + break; + } + /*TODO: Implement*/ + mo_invalid_field(dev); + return; + + case GPCMD_WRITE_6: + case GPCMD_WRITE_10: + case GPCMD_WRITE_AND_VERIFY_10: + case GPCMD_WRITE_12: + case GPCMD_WRITE_AND_VERIFY_12: + mo_set_phase(dev, SCSI_PHASE_DATA_OUT); + alloc_length = dev->drv->sector_size; + + if (dev->drv->read_only) { + mo_write_protected(dev); + return; + } + + switch (cdb[0]) { + case GPCMD_VERIFY_6: + case GPCMD_WRITE_6: + dev->sector_len = cdb[4]; + if (dev->sector_len == 0) + dev->sector_len = 256; /* For READ (6) and WRITE (6), a length of 0 indicates a transfer of 256 sector. */ + dev->sector_pos = ((((uint32_t) cdb[1]) & 0x1f) << 16) | (((uint32_t) cdb[2]) << 8) | ((uint32_t) cdb[3]); + break; + case GPCMD_VERIFY_10: + case GPCMD_WRITE_10: + case GPCMD_WRITE_AND_VERIFY_10: + dev->sector_len = (cdb[7] << 8) | cdb[8]; + dev->sector_pos = (cdb[2] << 24) | (cdb[3] << 16) | (cdb[4] << 8) | cdb[5]; + mo_log("MO %i: Length: %i, LBA: %i\n", dev->id, dev->sector_len, dev->sector_pos); + break; + case GPCMD_VERIFY_12: + case GPCMD_WRITE_12: + case GPCMD_WRITE_AND_VERIFY_12: + dev->sector_len = (((uint32_t) cdb[6]) << 24) | (((uint32_t) cdb[7]) << 16) | (((uint32_t) cdb[8]) << 8) | ((uint32_t) cdb[9]); + dev->sector_pos = (((uint32_t) cdb[2]) << 24) | (((uint32_t) cdb[3]) << 16) | (((uint32_t) cdb[4]) << 8) | ((uint32_t) cdb[5]); + break; + + default: + break; + } + + if ((dev->sector_pos >= dev->drv->medium_size) /* || + ((dev->sector_pos + dev->sector_len - 1) >= dev->drv->medium_size)*/ + ) { + mo_lba_out_of_range(dev); + return; + } + + if (!dev->sector_len) { + mo_set_phase(dev, SCSI_PHASE_STATUS); + /* mo_log("MO %i: All done - callback set\n", dev->id); */ + dev->packet_status = PHASE_COMPLETE; + dev->callback = 20.0 * MO_TIME; + mo_set_callback(dev); + break; + } + + max_len = dev->sector_len; + dev->requested_blocks = max_len; /* If we're writing all blocks in one go for DMA, why not also for PIO, it should NOT + matter anyway, this step should be identical and only the way the read dat is + transferred to the host should be different. */ + + dev->packet_len = max_len * alloc_length; + mo_buf_alloc(dev, dev->packet_len); + + dev->requested_blocks = max_len; + dev->packet_len = max_len << 9; + + mo_set_buf_len(dev, BufLen, (int32_t *) &dev->packet_len); + + mo_data_command_finish(dev, dev->packet_len, dev->drv->sector_size, dev->packet_len, 1); + + if (dev->packet_status != PHASE_COMPLETE) + ui_sb_update_icon(SB_MO | dev->id, 1); + else + ui_sb_update_icon(SB_MO | dev->id, 0); + return; + + case GPCMD_MODE_SENSE_6: + case GPCMD_MODE_SENSE_10: + mo_set_phase(dev, SCSI_PHASE_DATA_IN); + + if (dev->drv->bus_type == MO_BUS_SCSI) + block_desc = ((cdb[1] >> 3) & 1) ? 0 : 1; + else + block_desc = 0; + + if (cdb[0] == GPCMD_MODE_SENSE_6) { + len = cdb[4]; + mo_buf_alloc(dev, 256); + } else { + len = (cdb[8] | (cdb[7] << 8)); + mo_buf_alloc(dev, 65536); + } + + if (!(mo_mode_sense_page_flags & (1LL << (uint64_t) (cdb[2] & 0x3f)))) { + mo_invalid_field(dev); + mo_buf_free(dev); + return; + } + + memset(dev->buffer, 0, len); + alloc_length = len; + + if (cdb[0] == GPCMD_MODE_SENSE_6) { + len = mo_mode_sense(dev, dev->buffer, 4, cdb[2], block_desc); + len = MIN(len, alloc_length); + dev->buffer[0] = len - 1; + dev->buffer[1] = 0; + if (block_desc) + dev->buffer[3] = 8; + } else { + len = mo_mode_sense(dev, dev->buffer, 8, cdb[2], block_desc); + len = MIN(len, alloc_length); + dev->buffer[0] = (len - 2) >> 8; + dev->buffer[1] = (len - 2) & 255; + dev->buffer[2] = 0; + if (block_desc) { + dev->buffer[6] = 0; + dev->buffer[7] = 8; + } + } + + mo_set_buf_len(dev, BufLen, &len); + + mo_log("MO %i: Reading mode page: %02X...\n", dev->id, cdb[2]); + + mo_data_command_finish(dev, len, len, alloc_length, 0); + return; + + case GPCMD_MODE_SELECT_6: + case GPCMD_MODE_SELECT_10: + mo_set_phase(dev, SCSI_PHASE_DATA_OUT); + + if (cdb[0] == GPCMD_MODE_SELECT_6) { + len = cdb[4]; + mo_buf_alloc(dev, 256); + } else { + len = (cdb[7] << 8) | cdb[8]; + mo_buf_alloc(dev, 65536); + } + + mo_set_buf_len(dev, BufLen, &len); + + dev->total_length = len; + dev->do_page_save = cdb[1] & 1; + + mo_data_command_finish(dev, len, len, len, 1); + return; + + case GPCMD_START_STOP_UNIT: + mo_set_phase(dev, SCSI_PHASE_STATUS); + + switch (cdb[4] & 3) { + case 0: /* Stop the disk. */ + break; + case 1: /* Start the disk and read the TOC. */ + break; + case 2: /* Eject the disk if possible. */ + mo_eject(dev->id); + break; + case 3: /* Load the disk (close tray). */ + mo_reload(dev->id); + break; + + default: + break; + } + + mo_command_complete(dev); + break; + + case GPCMD_INQUIRY: + mo_set_phase(dev, SCSI_PHASE_DATA_IN); + + max_len = cdb[3]; + max_len <<= 8; + max_len |= cdb[4]; + + mo_buf_alloc(dev, 65536); + + if (cdb[1] & 1) { + preamble_len = 4; + size_idx = 3; + + dev->buffer[idx++] = 7; /*Optical disk*/ + dev->buffer[idx++] = cdb[2]; + dev->buffer[idx++] = 0; + + idx++; + + switch (cdb[2]) { + case 0x00: + dev->buffer[idx++] = 0x00; + dev->buffer[idx++] = 0x80; + break; + case 0x80: /*Unit serial number page*/ + dev->buffer[idx++] = strlen("VCM!10") + 1; + ide_padstr8(dev->buffer + idx, 20, "VCM!10"); /* Serial */ + idx += strlen("VCM!10"); + break; + default: + mo_log("INQUIRY: Invalid page: %02X\n", cdb[2]); + mo_invalid_field(dev); + mo_buf_free(dev); + return; + } + } else { + preamble_len = 5; + size_idx = 4; + + memset(dev->buffer, 0, 8); + if (cdb[1] & 0xe0) + dev->buffer[0] = 0x60; /*No physical device on this LUN*/ + else + dev->buffer[0] = 0x07; /*Optical disk*/ + dev->buffer[1] = 0x80; /*Removable*/ + dev->buffer[2] = (dev->drv->bus_type == MO_BUS_SCSI) ? 0x02 : 0x00; /*SCSI-2 compliant*/ + dev->buffer[3] = (dev->drv->bus_type == MO_BUS_SCSI) ? 0x02 : 0x21; +#if 0 + dev->buffer[4] = 31; +#endif + dev->buffer[4] = 0; + if (dev->drv->bus_type == MO_BUS_SCSI) { + dev->buffer[6] = 1; /* 16-bit transfers supported */ + dev->buffer[7] = 0x20; /* Wide bus supported */ + } + dev->buffer[7] |= 0x02; + + if (dev->drv->type > 0) { + ide_padstr8(dev->buffer + 8, 8, mo_drive_types[dev->drv->type].vendor); /* Vendor */ + ide_padstr8(dev->buffer + 16, 16, mo_drive_types[dev->drv->type].model); /* Product */ + ide_padstr8(dev->buffer + 32, 4, mo_drive_types[dev->drv->type].revision); /* Revision */ + } else { + ide_padstr8(dev->buffer + 8, 8, EMU_NAME); /* Vendor */ + ide_padstr8(dev->buffer + 16, 16, device_identify); /* Product */ + ide_padstr8(dev->buffer + 32, 4, EMU_VERSION_EX); /* Revision */ + } + idx = 36; + + if (max_len == 96) { + dev->buffer[4] = 91; + idx = 96; + } else if (max_len == 128) { + dev->buffer[4] = 0x75; + idx = 128; + } + } + + dev->buffer[size_idx] = idx - preamble_len; + len = idx; + + len = MIN(len, max_len); + mo_set_buf_len(dev, BufLen, &len); + + mo_data_command_finish(dev, len, len, max_len, 0); + break; + + case GPCMD_PREVENT_REMOVAL: + mo_set_phase(dev, SCSI_PHASE_STATUS); + mo_command_complete(dev); + break; + + case GPCMD_SEEK_6: + case GPCMD_SEEK_10: + mo_set_phase(dev, SCSI_PHASE_STATUS); + + switch (cdb[0]) { + case GPCMD_SEEK_6: + pos = (cdb[2] << 8) | cdb[3]; + break; + case GPCMD_SEEK_10: + pos = (cdb[2] << 24) | (cdb[3] << 16) | (cdb[4] << 8) | cdb[5]; + break; + + default: + break; + } + mo_seek(dev, pos); + mo_command_complete(dev); + break; + + case GPCMD_READ_CDROM_CAPACITY: + mo_set_phase(dev, SCSI_PHASE_DATA_IN); + + mo_buf_alloc(dev, 8); + + max_len = dev->drv->medium_size - 1; /* IMPORTANT: What's returned is the last LBA block. */ + memset(dev->buffer, 0, 8); + dev->buffer[0] = (max_len >> 24) & 0xff; + dev->buffer[1] = (max_len >> 16) & 0xff; + dev->buffer[2] = (max_len >> 8) & 0xff; + dev->buffer[3] = max_len & 0xff; + dev->buffer[6] = (dev->drv->sector_size >> 8) & 0xff; + dev->buffer[7] = dev->drv->sector_size & 0xff; + len = 8; + + mo_set_buf_len(dev, BufLen, &len); + + mo_data_command_finish(dev, len, len, len, 0); + break; + + case GPCMD_ERASE_10: + case GPCMD_ERASE_12: + /*Relative address*/ + if (cdb[1] & 1) + previous_pos = dev->sector_pos; + + switch (cdb[0]) { + case GPCMD_ERASE_10: + dev->sector_len = (cdb[7] << 8) | cdb[8]; + break; + case GPCMD_ERASE_12: + dev->sector_len = (((uint32_t) cdb[6]) << 24) | (((uint32_t) cdb[7]) << 16) | (((uint32_t) cdb[8]) << 8) | ((uint32_t) cdb[9]); + break; + + default: + break; + } + + /*Erase all remaining sectors*/ + if (cdb[1] & 4) { + /* Cannot have a sector number when erase all*/ + if (dev->sector_len) { + mo_invalid_field(dev); + return; + } + mo_format(dev); + mo_set_phase(dev, SCSI_PHASE_STATUS); + mo_command_complete(dev); + break; + } + + switch (cdb[0]) { + case GPCMD_ERASE_10: + dev->sector_pos = (cdb[2] << 24) | (cdb[3] << 16) | (cdb[4] << 8) | cdb[5]; + break; + case GPCMD_ERASE_12: + dev->sector_pos = (((uint32_t) cdb[2]) << 24) | (((uint32_t) cdb[3]) << 16) | (((uint32_t) cdb[4]) << 8) | ((uint32_t) cdb[5]); + break; + + default: + break; + } + + dev->sector_pos += previous_pos; + + mo_erase(dev); + mo_set_phase(dev, SCSI_PHASE_STATUS); + mo_command_complete(dev); + break; + + /*Never seen media that supports generations but it's interesting to know if any implementation calls this commmand*/ + case GPCMD_READ_GENERATION: + mo_set_phase(dev, SCSI_PHASE_DATA_IN); + + mo_buf_alloc(dev, 4); + len = 4; + + dev->buffer[0] = 0; + dev->buffer[1] = 0; + dev->buffer[2] = 0; + dev->buffer[3] = 0; + + mo_set_buf_len(dev, BufLen, &len); + mo_data_command_finish(dev, len, len, len, 0); + break; + + default: + mo_illegal_opcode(dev); + break; } - /* mo_log("MO %i: Phase: %02X, request length: %i\n", dev->id, dev->phase, dev->request_length); */ +#if 0 + mo_log("MO %i: Phase: %02X, request length: %i\n", dev->id, dev->tf->phase, dev->tf->request_length); +#endif - if (mo_atapi_phase_to_scsi(dev) == SCSI_PHASE_STATUS) - mo_buf_free(dev); + if ((dev->packet_status == PHASE_COMPLETE) || (dev->packet_status == PHASE_ERROR)) + mo_buf_free(dev); } - static void mo_command_stop(scsi_common_t *sc) { @@ -1897,118 +1850,122 @@ mo_command_stop(scsi_common_t *sc) mo_buf_free(dev); } - /* The command second phase function, needed for Mode Select. */ static uint8_t mo_phase_data_out(scsi_common_t *sc) { mo_t *dev = (mo_t *) sc; - uint16_t block_desc_len, pos; + uint16_t block_desc_len; + uint16_t pos; uint16_t param_list_len; uint8_t error = 0; - uint8_t page, page_len; + uint8_t page; + uint8_t page_len; - uint32_t i = 0; - - uint8_t hdr_len, val, old_val, ch; + uint8_t hdr_len; + uint8_t val; + uint8_t old_val; + uint8_t ch; int len = 0; - switch(dev->current_cdb[0]) { - case GPCMD_VERIFY_6: - case GPCMD_VERIFY_10: - case GPCMD_VERIFY_12: - break; - case GPCMD_WRITE_6: - case GPCMD_WRITE_10: - case GPCMD_WRITE_AND_VERIFY_10: - case GPCMD_WRITE_12: - case GPCMD_WRITE_AND_VERIFY_12: - if (dev->requested_blocks > 0) - mo_blocks(dev, &len, 1, 1); - break; - case GPCMD_MODE_SELECT_6: - case GPCMD_MODE_SELECT_10: - if (dev->current_cdb[0] == GPCMD_MODE_SELECT_10) { - hdr_len = 8; - param_list_len = dev->current_cdb[7]; - param_list_len <<= 8; - param_list_len |= dev->current_cdb[8]; - } else { - hdr_len = 4; - param_list_len = dev->current_cdb[4]; - } + switch (dev->current_cdb[0]) { + case GPCMD_VERIFY_6: + case GPCMD_VERIFY_10: + case GPCMD_VERIFY_12: + break; + case GPCMD_WRITE_6: + case GPCMD_WRITE_10: + case GPCMD_WRITE_AND_VERIFY_10: + case GPCMD_WRITE_12: + case GPCMD_WRITE_AND_VERIFY_12: + if (dev->requested_blocks > 0) + mo_blocks(dev, &len, 1, 1); + break; + case GPCMD_MODE_SELECT_6: + case GPCMD_MODE_SELECT_10: + if (dev->current_cdb[0] == GPCMD_MODE_SELECT_10) { + hdr_len = 8; + param_list_len = dev->current_cdb[7]; + param_list_len <<= 8; + param_list_len |= dev->current_cdb[8]; + } else { + hdr_len = 4; + param_list_len = dev->current_cdb[4]; + } - if (dev->drv->bus_type == MO_BUS_SCSI) { - if (dev->current_cdb[0] == GPCMD_MODE_SELECT_6) { - block_desc_len = dev->buffer[2]; - block_desc_len <<= 8; - block_desc_len |= dev->buffer[3]; - } else { - block_desc_len = dev->buffer[6]; - block_desc_len <<= 8; - block_desc_len |= dev->buffer[7]; - } - } else - block_desc_len = 0; + if (dev->drv->bus_type == MO_BUS_SCSI) { + if (dev->current_cdb[0] == GPCMD_MODE_SELECT_6) { + block_desc_len = dev->buffer[2]; + block_desc_len <<= 8; + block_desc_len |= dev->buffer[3]; + } else { + block_desc_len = dev->buffer[6]; + block_desc_len <<= 8; + block_desc_len |= dev->buffer[7]; + } + } else + block_desc_len = 0; - pos = hdr_len + block_desc_len; + pos = hdr_len + block_desc_len; - while(1) { - if (pos >= param_list_len) { - mo_log("MO %i: Buffer has only block descriptor\n", dev->id); - break; - } + while (1) { + if (pos >= param_list_len) { + mo_log("MO %i: Buffer has only block descriptor\n", dev->id); + break; + } - page = dev->buffer[pos] & 0x3F; - page_len = dev->buffer[pos + 1]; + page = dev->buffer[pos] & 0x3F; + page_len = dev->buffer[pos + 1]; - pos += 2; + pos += 2; - if (!(mo_mode_sense_page_flags & (1LL << ((uint64_t) page)))) - error |= 1; - else { - for (i = 0; i < page_len; i++) { - ch = mo_mode_sense_pages_changeable.pages[page][i + 2]; - val = dev->buffer[pos + i]; - old_val = dev->ms_pages_saved.pages[page][i + 2]; - if (val != old_val) { - if (ch) - dev->ms_pages_saved.pages[page][i + 2] = val; - else - error |= 1; - } - } - } + if (!(mo_mode_sense_page_flags & (1LL << ((uint64_t) page)))) + error |= 1; + else { + for (uint8_t i = 0; i < page_len; i++) { + ch = mo_mode_sense_pages_changeable.pages[page][i + 2]; + val = dev->buffer[pos + i]; + old_val = dev->ms_pages_saved.pages[page][i + 2]; + if (val != old_val) { + if (ch) + dev->ms_pages_saved.pages[page][i + 2] = val; + else + error |= 1; + } + } + } - pos += page_len; + pos += page_len; - if (dev->drv->bus_type == MO_BUS_SCSI) - val = mo_mode_sense_pages_default_scsi.pages[page][0] & 0x80; - else - val = mo_mode_sense_pages_default.pages[page][0] & 0x80; - if (dev->do_page_save && val) - mo_mode_sense_save(dev); + if (dev->drv->bus_type == MO_BUS_SCSI) + val = mo_mode_sense_pages_default_scsi.pages[page][0] & 0x80; + else + val = mo_mode_sense_pages_default.pages[page][0] & 0x80; + if (dev->do_page_save && val) + mo_mode_sense_save(dev); - if (pos >= dev->total_length) - break; - } + if (pos >= dev->total_length) + break; + } - if (error) { - mo_buf_free(dev); - mo_invalid_field_pl(dev); - return 0; - } - break; + if (error) { + mo_buf_free(dev); + mo_invalid_field_pl(dev); + return 0; + } + break; + + default: + break; } mo_command_stop((scsi_common_t *) dev); return 1; } - /* Peform a master init on the entire module. */ void mo_global_init(void) @@ -2017,50 +1974,48 @@ mo_global_init(void) memset(mo_drives, 0x00, sizeof(mo_drives)); } - static int mo_get_max(int ide_has_dma, int type) { int ret; - switch(type) { - case TYPE_PIO: - ret = ide_has_dma ? 3 : 0; - break; - case TYPE_SDMA: - default: - ret = -1; - break; - case TYPE_MDMA: - ret = ide_has_dma ? 1 : -1; - break; - case TYPE_UDMA: - ret = ide_has_dma ? 5 : -1; - break; + switch (type) { + case TYPE_PIO: + ret = ide_has_dma ? 3 : 0; + break; + case TYPE_SDMA: + default: + ret = -1; + break; + case TYPE_MDMA: + ret = ide_has_dma ? 1 : -1; + break; + case TYPE_UDMA: + ret = ide_has_dma ? 5 : -1; + break; } return ret; } - static int mo_get_timings(int ide_has_dma, int type) { int ret; - switch(type) { - case TIMINGS_DMA: - ret = ide_has_dma ? 0x96 : 0; - break; - case TIMINGS_PIO: - ret = ide_has_dma ? 0xb4 : 0; - break; - case TIMINGS_PIO_FC: - ret = ide_has_dma ? 0xb4 : 0; - break; - default: - ret = 0; - break; + switch (type) { + case TIMINGS_DMA: + ret = ide_has_dma ? 0x96 : 0; + break; + case TIMINGS_PIO: + ret = ide_has_dma ? 0xb4 : 0; + break; + case TIMINGS_PIO_FC: + ret = ide_has_dma ? 0xb4 : 0; + break; + default: + ret = 0; + break; } return ret; @@ -2071,166 +2026,170 @@ mo_do_identify(ide_t *ide, int ide_has_dma) { char model[40]; - mo_t* mo = (mo_t*) ide->sc; + const mo_t *mo = (mo_t *) ide->sc; memset(model, 0, 40); if (mo_drives[mo->id].type > 0) { - snprintf(model, 40, "%s %s", mo_drive_types[mo_drives[mo->id].type].vendor, mo_drive_types[mo_drives[mo->id].type].model); - ide_padstr((char *) (ide->buffer + 23), mo_drive_types[mo_drives[mo->id].type].revision, 8); /* Firmware */ - ide_padstr((char *) (ide->buffer + 27), model, 40); /* Model */ + snprintf(model, 40, "%s %s", mo_drive_types[mo_drives[mo->id].type].vendor, mo_drive_types[mo_drives[mo->id].type].model); + ide_padstr((char *) (ide->buffer + 23), mo_drive_types[mo_drives[mo->id].type].revision, 8); /* Firmware */ + ide_padstr((char *) (ide->buffer + 27), model, 40); /* Model */ } else { - snprintf(model, 40, "%s %s%02i", EMU_NAME, "86B_MO", mo->id); - ide_padstr((char *) (ide->buffer + 23), EMU_VERSION_EX, 8); /* Firmware */ - ide_padstr((char *) (ide->buffer + 27), model, 40); /* Model */ + snprintf(model, 40, "%s %s%02i", EMU_NAME, "86B_MO", mo->id); + ide_padstr((char *) (ide->buffer + 23), EMU_VERSION_EX, 8); /* Firmware */ + ide_padstr((char *) (ide->buffer + 27), model, 40); /* Model */ } if (ide_has_dma) { - ide->buffer[80] = 0x70; /*Supported ATA versions : ATA/ATAPI-4 ATA/ATAPI-6*/ - ide->buffer[81] = 0x19; /*Maximum ATA revision supported : ATA/ATAPI-6 T13 1410D revision 3a*/ + ide->buffer[80] = 0x70; /*Supported ATA versions : ATA/ATAPI-4 ATA/ATAPI-6*/ + ide->buffer[81] = 0x19; /*Maximum ATA revision supported : ATA/ATAPI-6 T13 1410D revision 3a*/ } } - static void mo_identify(ide_t *ide, int ide_has_dma) { - ide->buffer[0] = 0x8000 | (0 << 8) | 0x80 | (1 << 5); /* ATAPI device, direct-access device, removable media, interrupt DRQ */ - ide_padstr((char *) (ide->buffer + 10), "", 20); /* Serial Number */ - ide->buffer[49] = 0x200; /* LBA supported */ - ide->buffer[126] = 0xfffe; /* Interpret zero byte count limit as maximum length */ + ide->buffer[0] = 0x8000 | (0 << 8) | 0x80 | (1 << 5); /* ATAPI device, direct-access device, removable media, interrupt DRQ */ + ide_padstr((char *) (ide->buffer + 10), "", 20); /* Serial Number */ + ide->buffer[49] = 0x200; /* LBA supported */ + ide->buffer[126] = 0xfffe; /* Interpret zero byte count limit as maximum length */ mo_do_identify(ide, ide_has_dma); } - static void mo_drive_reset(int c) { - mo_t *dev; + mo_t *dev; scsi_device_t *sd; - ide_t *id; - uint8_t scsi_bus = (mo_drives[c].scsi_device_id >> 4) & 0x0f; - uint8_t scsi_id = mo_drives[c].scsi_device_id & 0x0f; + ide_t *id; + uint8_t scsi_bus = (mo_drives[c].scsi_device_id >> 4) & 0x0f; + uint8_t scsi_id = mo_drives[c].scsi_device_id & 0x0f; if (!mo_drives[c].priv) { - mo_drives[c].priv = (mo_t *) malloc(sizeof(mo_t)); - memset(mo_drives[c].priv, 0, sizeof(mo_t)); + mo_drives[c].priv = (mo_t *) malloc(sizeof(mo_t)); + memset(mo_drives[c].priv, 0, sizeof(mo_t)); } dev = (mo_t *) mo_drives[c].priv; - dev->id = c; + dev->id = c; dev->cur_lun = SCSI_LUN_USE_CDB; if (mo_drives[c].bus_type == MO_BUS_SCSI) { - /* SCSI MO, attach to the SCSI bus. */ - sd = &scsi_devices[scsi_bus][scsi_id]; + if (!dev->tf) + dev->tf = (ide_tf_t *) calloc(1, sizeof(ide_tf_t)); - sd->sc = (scsi_common_t *) dev; - sd->command = mo_command; - sd->request_sense = mo_request_sense_for_scsi; - sd->reset = mo_reset; - sd->phase_data_out = mo_phase_data_out; - sd->command_stop = mo_command_stop; - sd->type = SCSI_REMOVABLE_DISK; + /* SCSI MO, attach to the SCSI bus. */ + sd = &scsi_devices[scsi_bus][scsi_id]; + + sd->sc = (scsi_common_t *) dev; + sd->command = mo_command; + sd->request_sense = mo_request_sense_for_scsi; + sd->reset = mo_reset; + sd->phase_data_out = mo_phase_data_out; + sd->command_stop = mo_command_stop; + sd->type = SCSI_REMOVABLE_DISK; } else if (mo_drives[c].bus_type == MO_BUS_ATAPI) { - /* ATAPI MO, attach to the IDE bus. */ - id = ide_get_drive(mo_drives[c].ide_channel); - /* If the IDE channel is initialized, we attach to it, - otherwise, we do nothing - it's going to be a drive - that's not attached to anything. */ - if (id) { - id->sc = (scsi_common_t *) dev; - id->get_max = mo_get_max; - id->get_timings = mo_get_timings; - id->identify = mo_identify; - id->stop = NULL; - id->packet_command = mo_command; - id->device_reset = mo_reset; - id->phase_data_out = mo_phase_data_out; - id->command_stop = mo_command_stop; - id->bus_master_error = mo_bus_master_error; - id->interrupt_drq = 1; + /* ATAPI MO, attach to the IDE bus. */ + id = ide_get_drive(mo_drives[c].ide_channel); + /* If the IDE channel is initialized, we attach to it, + otherwise, we do nothing - it's going to be a drive + that's not attached to anything. */ + if (id) { + id->sc = (scsi_common_t *) dev; + dev->tf = id->tf; + IDE_ATAPI_IS_EARLY = 0; + id->get_max = mo_get_max; + id->get_timings = mo_get_timings; + id->identify = mo_identify; + id->stop = NULL; + id->packet_command = mo_command; + id->device_reset = mo_reset; + id->phase_data_out = mo_phase_data_out; + id->command_stop = mo_command_stop; + id->bus_master_error = mo_bus_master_error; + id->interrupt_drq = 1; - ide_atapi_attach(id); - } + ide_atapi_attach(id); + } } } - void mo_hard_reset(void) { - mo_t *dev; - int c; - uint8_t scsi_id, scsi_bus; + mo_t *dev; + uint8_t scsi_id; + uint8_t scsi_bus; - for (c = 0; c < MO_NUM; c++) { - if ((mo_drives[c].bus_type == MO_BUS_ATAPI) || (mo_drives[c].bus_type == MO_BUS_SCSI)) { - mo_log("MO hard_reset drive=%d\n", c); + for (uint8_t c = 0; c < MO_NUM; c++) { + if ((mo_drives[c].bus_type == MO_BUS_ATAPI) || (mo_drives[c].bus_type == MO_BUS_SCSI)) { + mo_log("MO hard_reset drive=%d\n", c); - if (mo_drives[c].bus_type == MO_BUS_SCSI) { - scsi_bus = (mo_drives[c].scsi_device_id >> 4) & 0x0f; - scsi_id = mo_drives[c].scsi_device_id & 0x0f; + if (mo_drives[c].bus_type == MO_BUS_SCSI) { + scsi_bus = (mo_drives[c].scsi_device_id >> 4) & 0x0f; + scsi_id = mo_drives[c].scsi_device_id & 0x0f; - /* Make sure to ignore any SCSI MO drive that has an out of range SCSI Bus. */ - if (scsi_bus >= SCSI_BUS_MAX) - continue; + /* Make sure to ignore any SCSI MO drive that has an out of range SCSI Bus. */ + if (scsi_bus >= SCSI_BUS_MAX) + continue; - /* Make sure to ignore any SCSI MO drive that has an out of range ID. */ - if (scsi_id >= SCSI_ID_MAX) - continue; - } + /* Make sure to ignore any SCSI MO drive that has an out of range ID. */ + if (scsi_id >= SCSI_ID_MAX) + continue; + } - /* Make sure to ignore any ATAPI MO drive that has an out of range IDE channel. */ - if ((mo_drives[c].bus_type == MO_BUS_ATAPI) && (mo_drives[c].ide_channel > 7)) - continue; + /* Make sure to ignore any ATAPI MO drive that has an out of range IDE channel. */ + if ((mo_drives[c].bus_type == MO_BUS_ATAPI) && (mo_drives[c].ide_channel > 7)) + continue; - mo_drive_reset(c); + mo_drive_reset(c); - dev = (mo_t *) mo_drives[c].priv; + dev = (mo_t *) mo_drives[c].priv; - dev->id = c; - dev->drv = &mo_drives[c]; + dev->id = c; + dev->drv = &mo_drives[c]; - mo_init(dev); + mo_init(dev); - if (strlen(mo_drives[c].image_path)) - mo_load(dev, mo_drives[c].image_path); + if (strlen(mo_drives[c].image_path)) + mo_load(dev, mo_drives[c].image_path); - mo_mode_sense_load(dev); + mo_mode_sense_load(dev); - if (mo_drives[c].bus_type == MO_BUS_SCSI) - mo_log("SCSI MO drive %i attached to SCSI ID %i\n", c, mo_drives[c].scsi_device_id); - else if (mo_drives[c].bus_type == MO_BUS_ATAPI) - mo_log("ATAPI MO drive %i attached to IDE channel %i\n", c, mo_drives[c].ide_channel); - } + if (mo_drives[c].bus_type == MO_BUS_SCSI) + mo_log("SCSI MO drive %i attached to SCSI ID %i\n", c, mo_drives[c].scsi_device_id); + else if (mo_drives[c].bus_type == MO_BUS_ATAPI) + mo_log("ATAPI MO drive %i attached to IDE channel %i\n", c, mo_drives[c].ide_channel); + } } } - void mo_close(void) { - mo_t *dev; - int c; - uint8_t scsi_id, scsi_bus; + mo_t *dev; + uint8_t scsi_id; + uint8_t scsi_bus; - for (c = 0; c < MO_NUM; c++) { - if (mo_drives[c].bus_type == MO_BUS_SCSI) { - scsi_bus = (mo_drives[c].scsi_device_id >> 4) & 0x0f; - scsi_id = mo_drives[c].scsi_device_id & 0x0f; + for (uint8_t c = 0; c < MO_NUM; c++) { + if (mo_drives[c].bus_type == MO_BUS_SCSI) { + scsi_bus = (mo_drives[c].scsi_device_id >> 4) & 0x0f; + scsi_id = mo_drives[c].scsi_device_id & 0x0f; - memset(&scsi_devices[scsi_bus][scsi_id], 0x00, sizeof(scsi_device_t)); - } + memset(&scsi_devices[scsi_bus][scsi_id], 0x00, sizeof(scsi_device_t)); + } - dev = (mo_t *) mo_drives[c].priv; + dev = (mo_t *) mo_drives[c].priv; - if (dev) { - mo_disk_unload(dev); + if (dev) { + mo_disk_unload(dev); - free(dev); - mo_drives[c].priv = NULL; - } + if (dev->tf) + free(dev->tf); + + free(dev); + mo_drives[c].priv = NULL; + } } } diff --git a/src/disk/zip.c b/src/disk/zip.c index 38cbf2eda..c498383e8 100644 --- a/src/disk/zip.c +++ b/src/disk/zip.c @@ -1,19 +1,19 @@ /* - * 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. + * 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. + * This file is part of the 86Box distribution. * - * Implementation of the Iomega ZIP drive with SCSI(-like) - * commands, for both ATAPI and SCSI usage. + * Implementation of the Iomega ZIP drive with SCSI(-like) + * commands, for both ATAPI and SCSI usage. * * * - * Author: Miran Grca, + * Authors: Miran Grca, * - * Copyright 2018,2019 Miran Grca. + * Copyright 2018-2019 Miran Grca. */ #include #include @@ -27,6 +27,7 @@ #include <86box/config.h> #include <86box/timer.h> #include <86box/device.h> +#include <86box/scsi.h> #include <86box/scsi_device.h> #include <86box/nvr.h> #include <86box/plat.h> @@ -35,74 +36,73 @@ #include <86box/hdc_ide.h> #include <86box/zip.h> +#define IDE_ATAPI_IS_EARLY id->sc->pad0 -zip_drive_t zip_drives[ZIP_NUM]; - +zip_drive_t zip_drives[ZIP_NUM]; /* Table of all SCSI commands and their flags, needed for the new disc change / not ready handler. */ -const uint8_t zip_command_flags[0x100] = -{ - IMPLEMENTED | CHECK_READY | NONDATA, /* 0x00 */ - IMPLEMENTED | ALLOW_UA | NONDATA | SCSI_ONLY, /* 0x01 */ +const uint8_t zip_command_flags[0x100] = { + IMPLEMENTED | CHECK_READY | NONDATA, /* 0x00 */ + IMPLEMENTED | ALLOW_UA | NONDATA | SCSI_ONLY, /* 0x01 */ 0, - IMPLEMENTED | ALLOW_UA, /* 0x03 */ - IMPLEMENTED | CHECK_READY | ALLOW_UA | NONDATA | SCSI_ONLY, /* 0x04 */ + IMPLEMENTED | ALLOW_UA, /* 0x03 */ + IMPLEMENTED | CHECK_READY | ALLOW_UA | NONDATA | SCSI_ONLY, /* 0x04 */ 0, - IMPLEMENTED, /* 0x06 */ + IMPLEMENTED, /* 0x06 */ 0, - IMPLEMENTED | CHECK_READY, /* 0x08 */ + IMPLEMENTED | CHECK_READY, /* 0x08 */ 0, - IMPLEMENTED | CHECK_READY, /* 0x0A */ - IMPLEMENTED | CHECK_READY | NONDATA, /* 0x0B */ - IMPLEMENTED, /* 0x0C */ - IMPLEMENTED | ATAPI_ONLY, /* 0x0D */ + IMPLEMENTED | CHECK_READY, /* 0x0A */ + IMPLEMENTED | CHECK_READY | NONDATA, /* 0x0B */ + IMPLEMENTED, /* 0x0C */ + IMPLEMENTED | ATAPI_ONLY, /* 0x0D */ 0, 0, 0, 0, - IMPLEMENTED | ALLOW_UA, /* 0x12 */ - IMPLEMENTED | CHECK_READY | NONDATA | SCSI_ONLY, /* 0x13 */ + IMPLEMENTED | ALLOW_UA, /* 0x12 */ + IMPLEMENTED | CHECK_READY | NONDATA | SCSI_ONLY, /* 0x13 */ 0, - IMPLEMENTED, /* 0x15 */ - IMPLEMENTED | SCSI_ONLY, /* 0x16 */ - IMPLEMENTED | SCSI_ONLY, /* 0x17 */ + IMPLEMENTED, /* 0x15 */ + IMPLEMENTED | SCSI_ONLY, /* 0x16 */ + IMPLEMENTED | SCSI_ONLY, /* 0x17 */ 0, 0, - IMPLEMENTED, /* 0x1A */ - IMPLEMENTED | CHECK_READY, /* 0x1B */ + IMPLEMENTED, /* 0x1A */ + IMPLEMENTED | CHECK_READY, /* 0x1B */ 0, - IMPLEMENTED, /* 0x1D */ - IMPLEMENTED | CHECK_READY, /* 0x1E */ + IMPLEMENTED, /* 0x1D */ + IMPLEMENTED | CHECK_READY, /* 0x1E */ 0, 0, 0, 0, - IMPLEMENTED | ATAPI_ONLY, /* 0x23 */ + IMPLEMENTED | ATAPI_ONLY, /* 0x23 */ 0, - IMPLEMENTED | CHECK_READY, /* 0x25 */ + IMPLEMENTED | CHECK_READY, /* 0x25 */ 0, 0, - IMPLEMENTED | CHECK_READY, /* 0x28 */ + IMPLEMENTED | CHECK_READY, /* 0x28 */ 0, - IMPLEMENTED | CHECK_READY, /* 0x2A */ - IMPLEMENTED | CHECK_READY | NONDATA, /* 0x2B */ + IMPLEMENTED | CHECK_READY, /* 0x2A */ + IMPLEMENTED | CHECK_READY | NONDATA, /* 0x2B */ 0, 0, - IMPLEMENTED | CHECK_READY, /* 0x2E */ - IMPLEMENTED | CHECK_READY | NONDATA | SCSI_ONLY, /* 0x2F */ + IMPLEMENTED | CHECK_READY, /* 0x2E */ + IMPLEMENTED | CHECK_READY | NONDATA | SCSI_ONLY, /* 0x2F */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - IMPLEMENTED | CHECK_READY, /* 0x41 */ + IMPLEMENTED | CHECK_READY, /* 0x41 */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - IMPLEMENTED, /* 0x55 */ + IMPLEMENTED, /* 0x55 */ 0, 0, 0, 0, - IMPLEMENTED, /* 0x5A */ + IMPLEMENTED, /* 0x5A */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - IMPLEMENTED | CHECK_READY, /* 0xA8 */ + IMPLEMENTED | CHECK_READY, /* 0xA8 */ 0, - IMPLEMENTED | CHECK_READY, /* 0xAA */ + IMPLEMENTED | CHECK_READY, /* 0xAA */ 0, 0, 0, - IMPLEMENTED | CHECK_READY, /* 0xAE */ - IMPLEMENTED | CHECK_READY | NONDATA | SCSI_ONLY, /* 0xAF */ + IMPLEMENTED | CHECK_READY, /* 0xAE */ + IMPLEMENTED | CHECK_READY | NONDATA | SCSI_ONLY, /* 0xAF */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - IMPLEMENTED, /* 0xBD */ + IMPLEMENTED, /* 0xBD */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, @@ -110,18 +110,11 @@ const uint8_t zip_command_flags[0x100] = 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }; -static uint64_t zip_mode_sense_page_flags = (GPMODEP_R_W_ERROR_PAGE | - GPMODEP_DISCONNECT_PAGE | - GPMODEP_IOMEGA_PAGE | - GPMODEP_ALL_PAGES); -static uint64_t zip_250_mode_sense_page_flags = (GPMODEP_R_W_ERROR_PAGE | - GPMODEP_FLEXIBLE_DISK_PAGE | - GPMODEP_CACHING_PAGE | - GPMODEP_IOMEGA_PAGE | - GPMODEP_ALL_PAGES); - +static uint64_t zip_mode_sense_page_flags = (GPMODEP_R_W_ERROR_PAGE | GPMODEP_DISCONNECT_PAGE | GPMODEP_IOMEGA_PAGE | GPMODEP_ALL_PAGES); +static uint64_t zip_250_mode_sense_page_flags = (GPMODEP_R_W_ERROR_PAGE | GPMODEP_FLEXIBLE_DISK_PAGE | GPMODEP_CACHING_PAGE | GPMODEP_IOMEGA_PAGE | GPMODEP_ALL_PAGES); static const mode_sense_pages_t zip_mode_sense_pages_default = + // clang-format off { { { 0, 0 }, { GPMODE_R_W_ERROR_PAGE, 0x0a, 0xc8, 22, 0, 0, 0, 0, 90, 0, 0x50, 0x20 }, @@ -172,8 +165,10 @@ static const mode_sense_pages_t zip_mode_sense_pages_default = { 0, 0 }, { GPMODE_IOMEGA_PAGE, 0x04, 0x5c, 0x0f, 0xff, 0x0f } } }; +// clang-format on static const mode_sense_pages_t zip_250_mode_sense_pages_default = + // clang-format off { { { 0, 0 }, { GPMODE_R_W_ERROR_PAGE, 0x06, 0xc8, 0x64, 0, 0, 0, 0 }, @@ -206,7 +201,8 @@ static const mode_sense_pages_t zip_250_mode_sense_pages_default = { 0, 0 }, { 0, 0 }, { 0, 0 }, - { 0, 0 }, { 0, 0 }, + { 0, 0 }, + { 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 }, @@ -223,8 +219,10 @@ static const mode_sense_pages_t zip_250_mode_sense_pages_default = { 0, 0 }, { GPMODE_IOMEGA_PAGE, 0x04, 0x5c, 0x0f, 0x3c, 0x0f } } }; +// clang-format on static const mode_sense_pages_t zip_mode_sense_pages_default_scsi = + // clang-format off { { { 0, 0 }, { GPMODE_R_W_ERROR_PAGE, 0x0a, 0xc8, 22, 0, 0, 0, 0, 90, 0, 0x50, 0x20 }, @@ -275,8 +273,10 @@ static const mode_sense_pages_t zip_mode_sense_pages_default_scsi = { 0, 0 }, { GPMODE_IOMEGA_PAGE, 0x04, 0x5c, 0x0f, 0xff, 0x0f } } }; +// clang-format on static const mode_sense_pages_t zip_250_mode_sense_pages_default_scsi = + // clang-format off { { { 0, 0 }, { GPMODE_R_W_ERROR_PAGE, 0x06, 0xc8, 0x64, 0, 0, 0, 0 }, @@ -327,8 +327,10 @@ static const mode_sense_pages_t zip_250_mode_sense_pages_default_scsi = { 0, 0 }, { GPMODE_IOMEGA_PAGE, 0x04, 0x5c, 0x0f, 0x3c, 0x0f } } }; +// clang-format on static const mode_sense_pages_t zip_mode_sense_pages_changeable = + // clang-format off { { { 0, 0 }, @@ -380,8 +382,10 @@ static const mode_sense_pages_t zip_mode_sense_pages_changeable = { 0, 0 }, { GPMODE_IOMEGA_PAGE, 0x04, 0xff, 0xff, 0xff, 0xff } } }; +// clang-format on static const mode_sense_pages_t zip_250_mode_sense_pages_changeable = + // clang-format off { { { 0, 0 }, { GPMODE_R_W_ERROR_PAGE, 0x06, 0xFF, 0xFF, 0, 0, 0, 0 }, @@ -432,480 +436,432 @@ static const mode_sense_pages_t zip_250_mode_sense_pages_changeable = { 0, 0 }, { GPMODE_IOMEGA_PAGE, 0x04, 0xff, 0xff, 0xff, 0xff } } }; +// clang-format on - -static void zip_command_complete(zip_t *dev); -static void zip_init(zip_t *dev); - +static void zip_command_complete(zip_t *dev); +static void zip_init(zip_t *dev); #ifdef ENABLE_ZIP_LOG int zip_do_log = ENABLE_ZIP_LOG; - static void zip_log(const char *fmt, ...) { va_list ap; if (zip_do_log) { - va_start(ap, fmt); - pclog_ex(fmt, ap); - va_end(ap); + va_start(ap, fmt); + pclog_ex(fmt, ap); + va_end(ap); } } #else -#define zip_log(fmt, ...) +# define zip_log(fmt, ...) #endif - int find_zip_for_channel(uint8_t channel) { - uint8_t i = 0; - - for (i = 0; i < ZIP_NUM; i++) { - if ((zip_drives[i].bus_type == ZIP_BUS_ATAPI) && (zip_drives[i].ide_channel == channel)) - return i; + for (uint8_t i = 0; i < ZIP_NUM; i++) { + if ((zip_drives[i].bus_type == ZIP_BUS_ATAPI) && (zip_drives[i].ide_channel == channel)) + return i; } return 0xff; } - static int zip_load_abort(zip_t *dev) { - if (dev->drv->f) - fclose(dev->drv->f); - dev->drv->f = NULL; + if (dev->drv->fp) + fclose(dev->drv->fp); + dev->drv->fp = NULL; dev->drv->medium_size = 0; - zip_eject(dev->id); /* Make sure the host OS knows we've rejected (and ejected) the image. */ + zip_eject(dev->id); /* Make sure the host OS knows we've rejected (and ejected) the image. */ return 0; } - int zip_load(zip_t *dev, char *fn) { int size = 0; - dev->drv->f = plat_fopen(fn, dev->drv->read_only ? "rb" : "rb+"); - if (!dev->drv->f) { - if (!dev->drv->read_only) { - dev->drv->f = plat_fopen(fn, "rb"); - if (dev->drv->f) - dev->drv->read_only = 1; - else - return zip_load_abort(dev); - } else - return zip_load_abort(dev); + dev->drv->fp = plat_fopen(fn, dev->drv->read_only ? "rb" : "rb+"); + if (!dev->drv->fp) { + if (!dev->drv->read_only) { + dev->drv->fp = plat_fopen(fn, "rb"); + if (dev->drv->fp) + dev->drv->read_only = 1; + else + return zip_load_abort(dev); + } else + return zip_load_abort(dev); } - fseek(dev->drv->f, 0, SEEK_END); - size = ftell(dev->drv->f); + fseek(dev->drv->fp, 0, SEEK_END); + size = ftell(dev->drv->fp); if ((size == ((ZIP_250_SECTORS << 9) + 0x1000)) || (size == ((ZIP_SECTORS << 9) + 0x1000))) { - /* This is a ZDI image. */ - size -= 0x1000; - dev->drv->base = 0x1000; + /* This is a ZDI image. */ + size -= 0x1000; + dev->drv->base = 0x1000; } else - dev->drv->base = 0; + dev->drv->base = 0; if (dev->drv->is_250) { - if ((size != (ZIP_250_SECTORS << 9)) && (size != (ZIP_SECTORS << 9))) { - zip_log("File is incorrect size for a ZIP image\nMust be exactly %i or %i bytes\n", - ZIP_250_SECTORS << 9, ZIP_SECTORS << 9); - return zip_load_abort(dev); - } + if ((size != (ZIP_250_SECTORS << 9)) && (size != (ZIP_SECTORS << 9))) { + zip_log("File is incorrect size for a ZIP image\nMust be exactly %i or %i bytes\n", + ZIP_250_SECTORS << 9, ZIP_SECTORS << 9); + return zip_load_abort(dev); + } } else { - if (size != (ZIP_SECTORS << 9)) { - zip_log("File is incorrect size for a ZIP image\nMust be exactly %i bytes\n", - ZIP_SECTORS << 9); - return zip_load_abort(dev); - } + if (size != (ZIP_SECTORS << 9)) { + zip_log("File is incorrect size for a ZIP image\nMust be exactly %i bytes\n", + ZIP_SECTORS << 9); + return zip_load_abort(dev); + } } dev->drv->medium_size = size >> 9; - if (fseek(dev->drv->f, dev->drv->base, SEEK_SET) == -1) - fatal("zip_load(): Error seeking to the beginning of the file\n"); + if (fseek(dev->drv->fp, dev->drv->base, SEEK_SET) == -1) + fatal("zip_load(): Error seeking to the beginning of the file\n"); strncpy(dev->drv->image_path, fn, sizeof(dev->drv->image_path) - 1); return 1; } - void zip_disk_reload(zip_t *dev) { int ret = 0; if (strlen(dev->drv->prev_image_path) == 0) - return; + return; else - ret = zip_load(dev, dev->drv->prev_image_path); + ret = zip_load(dev, dev->drv->prev_image_path); if (ret) - dev->unit_attention = 1; + dev->unit_attention = 1; } - void zip_disk_unload(zip_t *dev) { - if (dev->drv->f) { - fclose(dev->drv->f); - dev->drv->f = NULL; + if (dev->drv->fp) { + fclose(dev->drv->fp); + dev->drv->fp = NULL; } } - void zip_disk_close(zip_t *dev) { - if (dev->drv->f) { - zip_disk_unload(dev); + if (dev->drv->fp) { + zip_disk_unload(dev); - memcpy(dev->drv->prev_image_path, dev->drv->image_path, sizeof(dev->drv->prev_image_path)); - memset(dev->drv->image_path, 0, sizeof(dev->drv->image_path)); + memcpy(dev->drv->prev_image_path, dev->drv->image_path, sizeof(dev->drv->prev_image_path)); + memset(dev->drv->image_path, 0, sizeof(dev->drv->image_path)); - dev->drv->medium_size = 0; + dev->drv->medium_size = 0; } } - static void zip_set_callback(zip_t *dev) { if (dev->drv->bus_type != ZIP_BUS_SCSI) - ide_set_callback(ide_drives[dev->drv->ide_channel], dev->callback); + ide_set_callback(ide_drives[dev->drv->ide_channel], dev->callback); } - static void zip_init(zip_t *dev) { if (dev->id >= ZIP_NUM) - return; + return; dev->requested_blocks = 1; - dev->sense[0] = 0xf0; - dev->sense[7] = 10; - dev->drv->bus_mode = 0; + dev->sense[0] = 0xf0; + dev->sense[7] = 10; + dev->drv->bus_mode = 0; if (dev->drv->bus_type >= ZIP_BUS_ATAPI) - dev->drv->bus_mode |= 2; + dev->drv->bus_mode |= 2; if (dev->drv->bus_type < ZIP_BUS_SCSI) - dev->drv->bus_mode |= 1; + dev->drv->bus_mode |= 1; zip_log("ZIP %i: Bus type %i, bus mode %i\n", dev->id, dev->drv->bus_type, dev->drv->bus_mode); if (dev->drv->bus_type < ZIP_BUS_SCSI) { - dev->phase = 1; - dev->request_length = 0xEB14; + dev->tf->phase = 1; + dev->tf->request_length = 0xEB14; } - dev->status = READY_STAT | DSC_STAT; - dev->pos = 0; + dev->tf->status = READY_STAT | DSC_STAT; + dev->tf->pos = 0; dev->packet_status = PHASE_NONE; zip_sense_key = zip_asc = zip_ascq = dev->unit_attention = 0; } - static int zip_supports_pio(zip_t *dev) { return (dev->drv->bus_mode & 1); } - static int zip_supports_dma(zip_t *dev) { return (dev->drv->bus_mode & 2); } - /* Returns: 0 for none, 1 for PIO, 2 for DMA. */ static int zip_current_mode(zip_t *dev) { if (!zip_supports_pio(dev) && !zip_supports_dma(dev)) - return 0; + return 0; if (zip_supports_pio(dev) && !zip_supports_dma(dev)) { - zip_log("ZIP %i: Drive does not support DMA, setting to PIO\n", dev->id); - return 1; + zip_log("ZIP %i: Drive does not support DMA, setting to PIO\n", dev->id); + return 1; } if (!zip_supports_pio(dev) && zip_supports_dma(dev)) - return 2; + return 2; if (zip_supports_pio(dev) && zip_supports_dma(dev)) { - zip_log("ZIP %i: Drive supports both, setting to %s\n", dev->id, (dev->features & 1) ? "DMA" : "PIO"); - return (dev->features & 1) ? 2 : 1; + zip_log("ZIP %i: Drive supports both, setting to %s\n", dev->id, + (dev->tf->features & 1) ? "DMA" : "PIO"); + return (dev->tf->features & 1) ? 2 : 1; } return 0; } - -/* Translates ATAPI phase (DRQ, I/O, C/D) to SCSI phase (MSG, C/D, I/O). */ -int -zip_atapi_phase_to_scsi(zip_t *dev) -{ - if (dev->status & 8) { - switch (dev->phase & 3) { - case 0: - return 0; - case 1: - return 2; - case 2: - return 1; - case 3: - return 7; - } - } else { - if ((dev->phase & 3) == 3) - return 3; - else - return 4; - } - - return 0; -} - - static void zip_mode_sense_load(zip_t *dev) { - FILE *f; - char file_name[512]; + FILE *fp; + char fn[512]; memset(&dev->ms_pages_saved, 0, sizeof(mode_sense_pages_t)); if (dev->drv->is_250) { - if (zip_drives[dev->id].bus_type == ZIP_BUS_SCSI) - memcpy(&dev->ms_pages_saved, &zip_250_mode_sense_pages_default_scsi, sizeof(mode_sense_pages_t)); - else - memcpy(&dev->ms_pages_saved, &zip_250_mode_sense_pages_default, sizeof(mode_sense_pages_t)); + if (zip_drives[dev->id].bus_type == ZIP_BUS_SCSI) + memcpy(&dev->ms_pages_saved, &zip_250_mode_sense_pages_default_scsi, sizeof(mode_sense_pages_t)); + else + memcpy(&dev->ms_pages_saved, &zip_250_mode_sense_pages_default, sizeof(mode_sense_pages_t)); } else { - if (zip_drives[dev->id].bus_type == ZIP_BUS_SCSI) - memcpy(&dev->ms_pages_saved, &zip_mode_sense_pages_default_scsi, sizeof(mode_sense_pages_t)); - else - memcpy(&dev->ms_pages_saved, &zip_mode_sense_pages_default, sizeof(mode_sense_pages_t)); + if (zip_drives[dev->id].bus_type == ZIP_BUS_SCSI) + memcpy(&dev->ms_pages_saved, &zip_mode_sense_pages_default_scsi, sizeof(mode_sense_pages_t)); + else + memcpy(&dev->ms_pages_saved, &zip_mode_sense_pages_default, sizeof(mode_sense_pages_t)); } - memset(file_name, 0, 512); + memset(fn, 0, 512); if (dev->drv->bus_type == ZIP_BUS_SCSI) - sprintf(file_name, "scsi_zip_%02i_mode_sense_bin", dev->id); + sprintf(fn, "scsi_zip_%02i_mode_sense_bin", dev->id); else - sprintf(file_name, "zip_%02i_mode_sense_bin", dev->id); - f = plat_fopen(nvr_path(file_name), "rb"); - if (f) { - /* Nothing to read, not used by ZIP. */ - fclose(f); + sprintf(fn, "zip_%02i_mode_sense_bin", dev->id); + fp = plat_fopen(nvr_path(fn), "rb"); + if (fp) { + /* Nothing to read, not used by ZIP. */ + fclose(fp); } } - static void zip_mode_sense_save(zip_t *dev) { - FILE *f; - char file_name[512]; + FILE *fp; + char fn[512]; - memset(file_name, 0, 512); + memset(fn, 0, 512); if (dev->drv->bus_type == ZIP_BUS_SCSI) - sprintf(file_name, "scsi_zip_%02i_mode_sense_bin", dev->id); + sprintf(fn, "scsi_zip_%02i_mode_sense_bin", dev->id); else - sprintf(file_name, "zip_%02i_mode_sense_bin", dev->id); - f = plat_fopen(nvr_path(file_name), "wb"); - if (f) { - /* Nothing to write, not used by ZIP. */ - fclose(f); + sprintf(fn, "zip_%02i_mode_sense_bin", dev->id); + fp = plat_fopen(nvr_path(fn), "wb"); + if (fp) { + /* Nothing to write, not used by ZIP. */ + fclose(fp); } } - /*SCSI Mode Sense 6/10*/ static uint8_t zip_mode_sense_read(zip_t *dev, uint8_t page_control, uint8_t page, uint8_t pos) { switch (page_control) { - case 0: - case 3: - if (dev->drv->is_250 && (page == 5) && (pos == 9) && (dev->drv->medium_size == ZIP_SECTORS)) - return 0x60; - return dev->ms_pages_saved.pages[page][pos]; - break; - case 1: - if (dev->drv->is_250) - return zip_250_mode_sense_pages_changeable.pages[page][pos]; - else - return zip_mode_sense_pages_changeable.pages[page][pos]; - break; - case 2: - if (dev->drv->is_250) { - if ((page == 5) && (pos == 9) && (dev->drv->medium_size == ZIP_SECTORS)) - return 0x60; - if (dev->drv->bus_type == ZIP_BUS_SCSI) - return zip_250_mode_sense_pages_default_scsi.pages[page][pos]; - else - return zip_250_mode_sense_pages_default.pages[page][pos]; - } else { - if (dev->drv->bus_type == ZIP_BUS_SCSI) - return zip_mode_sense_pages_default_scsi.pages[page][pos]; - else - return zip_mode_sense_pages_default.pages[page][pos]; - } - break; + case 0: + case 3: + if (dev->drv->is_250 && (page == 5) && (pos == 9) && (dev->drv->medium_size == ZIP_SECTORS)) + return 0x60; + return dev->ms_pages_saved.pages[page][pos]; + case 1: + if (dev->drv->is_250) + return zip_250_mode_sense_pages_changeable.pages[page][pos]; + else + return zip_mode_sense_pages_changeable.pages[page][pos]; + case 2: + if (dev->drv->is_250) { + if ((page == 5) && (pos == 9) && (dev->drv->medium_size == ZIP_SECTORS)) + return 0x60; + if (dev->drv->bus_type == ZIP_BUS_SCSI) + return zip_250_mode_sense_pages_default_scsi.pages[page][pos]; + else + return zip_250_mode_sense_pages_default.pages[page][pos]; + } else { + if (dev->drv->bus_type == ZIP_BUS_SCSI) + return zip_mode_sense_pages_default_scsi.pages[page][pos]; + else + return zip_mode_sense_pages_default.pages[page][pos]; + } + + default: + break; } return 0; } - static uint32_t zip_mode_sense(zip_t *dev, uint8_t *buf, uint32_t pos, uint8_t page, uint8_t block_descriptor_len) { uint64_t pf; - uint8_t page_control = (page >> 6) & 3; + uint8_t page_control = (page >> 6) & 3; if (dev->drv->is_250) - pf = zip_250_mode_sense_page_flags; + pf = zip_250_mode_sense_page_flags; else - pf = zip_mode_sense_page_flags; - - int i = 0; - int j = 0; + pf = zip_mode_sense_page_flags; uint8_t msplen; page &= 0x3f; if (block_descriptor_len) { - buf[pos++] = ((dev->drv->medium_size >> 24) & 0xff); - buf[pos++] = ((dev->drv->medium_size >> 16) & 0xff); - buf[pos++] = ((dev->drv->medium_size >> 8) & 0xff); - buf[pos++] = ( dev->drv->medium_size & 0xff); - buf[pos++] = 0; /* Reserved. */ - buf[pos++] = 0; /* Block length (0x200 = 512 bytes). */ - buf[pos++] = 2; - buf[pos++] = 0; + buf[pos++] = ((dev->drv->medium_size >> 24) & 0xff); + buf[pos++] = ((dev->drv->medium_size >> 16) & 0xff); + buf[pos++] = ((dev->drv->medium_size >> 8) & 0xff); + buf[pos++] = (dev->drv->medium_size & 0xff); + buf[pos++] = 0; /* Reserved. */ + buf[pos++] = 0; /* Block length (0x200 = 512 bytes). */ + buf[pos++] = 2; + buf[pos++] = 0; } - for (i = 0; i < 0x40; i++) { + for (uint8_t i = 0; i < 0x40; i++) { if ((page == GPMODE_ALL_PAGES) || (page == i)) { - if (pf & (1LL << ((uint64_t) page))) { - buf[pos++] = zip_mode_sense_read(dev, page_control, i, 0); - msplen = zip_mode_sense_read(dev, page_control, i, 1); - buf[pos++] = msplen; - zip_log("ZIP %i: MODE SENSE: Page [%02X] length %i\n", dev->id, i, msplen); - for (j = 0; j < msplen; j++) - buf[pos++] = zip_mode_sense_read(dev, page_control, i, 2 + j); - } - } + if (pf & (1LL << ((uint64_t) page))) { + buf[pos++] = zip_mode_sense_read(dev, page_control, i, 0); + msplen = zip_mode_sense_read(dev, page_control, i, 1); + buf[pos++] = msplen; + zip_log("ZIP %i: MODE SENSE: Page [%02X] length %i\n", dev->id, i, msplen); + for (uint8_t j = 0; j < msplen; j++) + buf[pos++] = zip_mode_sense_read(dev, page_control, i, 2 + j); + } + } } return pos; } - static void zip_update_request_length(zip_t *dev, int len, int block_len) { - int bt, min_len = 0; + int bt; + int min_len = 0; - dev->max_transfer_len = dev->request_length; + dev->max_transfer_len = dev->tf->request_length; /* For media access commands, make sure the requested DRQ length matches the block length. */ switch (dev->current_cdb[0]) { - case 0x08: - case 0x0a: - case 0x28: - case 0x2a: - case 0xa8: - case 0xaa: - /* Round it to the nearest 2048 bytes. */ - dev->max_transfer_len = (dev->max_transfer_len >> 9) << 9; + case 0x08: + case 0x0a: + case 0x28: + case 0x2a: + case 0xa8: + case 0xaa: + /* Round it to the nearest 2048 bytes. */ + dev->max_transfer_len = (dev->max_transfer_len >> 9) << 9; - /* Make sure total length is not bigger than sum of the lengths of - all the requested blocks. */ - bt = (dev->requested_blocks * block_len); - if (len > bt) - len = bt; + /* Make sure total length is not bigger than sum of the lengths of + all the requested blocks. */ + bt = (dev->requested_blocks * block_len); + if (len > bt) + len = bt; - min_len = block_len; + min_len = block_len; - if (len <= block_len) { - /* Total length is less or equal to block length. */ - if (dev->max_transfer_len < block_len) { - /* Transfer a minimum of (block size) bytes. */ - dev->max_transfer_len = block_len; - dev->packet_len = block_len; - break; - } - } - /*FALLTHROUGH*/ - default: - dev->packet_len = len; - break; + if (len <= block_len) { + /* Total length is less or equal to block length. */ + if (dev->max_transfer_len < block_len) { + /* Transfer a minimum of (block size) bytes. */ + dev->max_transfer_len = block_len; + dev->packet_len = block_len; + break; + } + } + fallthrough; + + default: + dev->packet_len = len; + break; } /* If the DRQ length is odd, and the total remaining length is bigger, make sure it's even. */ if ((dev->max_transfer_len & 1) && (dev->max_transfer_len < len)) - dev->max_transfer_len &= 0xfffe; + dev->max_transfer_len &= 0xfffe; /* If the DRQ length is smaller or equal in size to the total remaining length, set it to that. */ if (!dev->max_transfer_len) - dev->max_transfer_len = 65534; + dev->max_transfer_len = 65534; if ((len <= dev->max_transfer_len) && (len >= min_len)) - dev->request_length = dev->max_transfer_len = len; + dev->tf->request_length = dev->max_transfer_len = len; else if (len > dev->max_transfer_len) - dev->request_length = dev->max_transfer_len; + dev->tf->request_length = dev->max_transfer_len; return; } - static double zip_bus_speed(zip_t *dev) { double ret = -1.0; if (dev && dev->drv && (dev->drv->bus_type == ZIP_BUS_SCSI)) { - dev->callback = -1.0; /* Speed depends on SCSI controller */ - return 0.0; + dev->callback = -1.0; /* Speed depends on SCSI controller */ + return 0.0; } else { - if (dev && dev->drv) - ret = ide_atapi_get_period(dev->drv->ide_channel); - if (ret == -1.0) { - if (dev) - dev->callback = -1.0; - return 0.0; - } else - return ret * 1000000.0; + if (dev && dev->drv) + ret = ide_atapi_get_period(dev->drv->ide_channel); + if (ret == -1.0) { + if (dev) + dev->callback = -1.0; + return 0.0; + } else + return ret * 1000000.0; } } - static void zip_command_common(zip_t *dev) { - double bytes_per_second, period; + double bytes_per_second; + double period; - dev->status = BUSY_STAT; - dev->phase = 1; - dev->pos = 0; + dev->tf->status = BUSY_STAT; + dev->tf->phase = 1; + dev->tf->pos = 0; if (dev->packet_status == PHASE_COMPLETE) - dev->callback = 0.0; + dev->callback = 0.0; else { - if (dev->drv->bus_type == ZIP_BUS_SCSI) { - dev->callback = -1.0; /* Speed depends on SCSI controller */ - return; - } else - bytes_per_second = zip_bus_speed(dev); + if (dev->drv->bus_type == ZIP_BUS_SCSI) { + dev->callback = -1.0; /* Speed depends on SCSI controller */ + return; + } else + bytes_per_second = zip_bus_speed(dev); - period = 1000000.0 / bytes_per_second; - dev->callback = period * (double) (dev->packet_len); + period = 1000000.0 / bytes_per_second; + dev->callback = period * (double) (dev->packet_len); } zip_set_callback(dev); } - static void zip_command_complete(zip_t *dev) { @@ -914,7 +870,6 @@ zip_command_complete(zip_t *dev) zip_command_common(dev); } - static void zip_command_read(zip_t *dev) { @@ -922,7 +877,6 @@ zip_command_read(zip_t *dev) zip_command_common(dev); } - static void zip_command_read_dma(zip_t *dev) { @@ -930,7 +884,6 @@ zip_command_read_dma(zip_t *dev) zip_command_common(dev); } - static void zip_command_write(zip_t *dev) { @@ -938,7 +891,6 @@ zip_command_write(zip_t *dev) zip_command_common(dev); } - static void zip_command_write_dma(zip_t *dev) { @@ -946,7 +898,6 @@ zip_command_write_dma(zip_t *dev) zip_command_common(dev); } - /* id = Current ZIP device ID; len = Total transfer length; block_len = Length of a single block (why does it matter?!); @@ -956,116 +907,110 @@ static void zip_data_command_finish(zip_t *dev, int len, int block_len, int alloc_len, int direction) { zip_log("ZIP %i: Finishing command (%02X): %i, %i, %i, %i, %i\n", - dev->id, dev->current_cdb[0], len, block_len, alloc_len, direction, dev->request_length); - dev->pos = 0; + dev->id, dev->current_cdb[0], len, block_len, alloc_len, direction, dev->tf->request_length); + dev->tf->pos = 0; if (alloc_len >= 0) { - if (alloc_len < len) - len = alloc_len; + if (alloc_len < len) + len = alloc_len; } if ((len == 0) || (zip_current_mode(dev) == 0)) { - if (dev->drv->bus_type != ZIP_BUS_SCSI) - dev->packet_len = 0; + if (dev->drv->bus_type != ZIP_BUS_SCSI) + dev->packet_len = 0; - zip_command_complete(dev); + zip_command_complete(dev); } else { - if (zip_current_mode(dev) == 2) { - if (dev->drv->bus_type != ZIP_BUS_SCSI) - dev->packet_len = alloc_len; + if (zip_current_mode(dev) == 2) { + if (dev->drv->bus_type != ZIP_BUS_SCSI) + dev->packet_len = alloc_len; - if (direction == 0) - zip_command_read_dma(dev); - else - zip_command_write_dma(dev); - } else { - zip_update_request_length(dev, len, block_len); - if (direction == 0) - zip_command_read(dev); - else - zip_command_write(dev); - } + if (direction == 0) + zip_command_read_dma(dev); + else + zip_command_write_dma(dev); + } else { + zip_update_request_length(dev, len, block_len); + if (direction == 0) + zip_command_read(dev); + else + zip_command_write(dev); + } } zip_log("ZIP %i: Status: %i, cylinder %i, packet length: %i, position: %i, phase: %i\n", - dev->id, dev->packet_status, dev->request_length, dev->packet_len, dev->pos, dev->phase); + dev->id, dev->packet_status, dev->tf->request_length, dev->packet_len, dev->tf->pos, + dev->tf->phase); } - static void -zip_sense_clear(zip_t *dev, int command) +zip_sense_clear(zip_t *dev, UNUSED(int command)) { zip_sense_key = zip_asc = zip_ascq = 0; } - static void zip_set_phase(zip_t *dev, uint8_t phase) { uint8_t scsi_bus = (dev->drv->scsi_device_id >> 4) & 0x0f; - uint8_t scsi_id = dev->drv->scsi_device_id & 0x0f; + uint8_t scsi_id = dev->drv->scsi_device_id & 0x0f; if (dev->drv->bus_type != ZIP_BUS_SCSI) - return; + return; scsi_devices[scsi_bus][scsi_id].phase = phase; } - static void zip_cmd_error(zip_t *dev) { zip_set_phase(dev, SCSI_PHASE_STATUS); - dev->error = ((zip_sense_key & 0xf) << 4) | ABRT_ERR; + dev->tf->error = ((zip_sense_key & 0xf) << 4) | ABRT_ERR; if (dev->unit_attention) - dev->error |= MCR_ERR; - dev->status = READY_STAT | ERR_STAT; - dev->phase = 3; - dev->pos = 0; + dev->tf->error |= MCR_ERR; + dev->tf->status = READY_STAT | ERR_STAT; + dev->tf->phase = 3; + dev->tf->pos = 0; dev->packet_status = PHASE_ERROR; - dev->callback = 50.0 * ZIP_TIME; + dev->callback = 50.0 * ZIP_TIME; zip_set_callback(dev); ui_sb_update_icon(SB_ZIP | dev->id, 0); zip_log("ZIP %i: [%02X] ERROR: %02X/%02X/%02X\n", dev->id, dev->current_cdb[0], zip_sense_key, zip_asc, zip_ascq); } - static void zip_unit_attention(zip_t *dev) { zip_set_phase(dev, SCSI_PHASE_STATUS); - dev->error = (SENSE_UNIT_ATTENTION << 4) | ABRT_ERR; + dev->tf->error = (SENSE_UNIT_ATTENTION << 4) | ABRT_ERR; if (dev->unit_attention) - dev->error |= MCR_ERR; - dev->status = READY_STAT | ERR_STAT; - dev->phase = 3; - dev->pos = 0; + dev->tf->error |= MCR_ERR; + dev->tf->status = READY_STAT | ERR_STAT; + dev->tf->phase = 3; + dev->tf->pos = 0; dev->packet_status = PHASE_ERROR; - dev->callback = 50.0 * ZIP_TIME; + dev->callback = 50.0 * ZIP_TIME; zip_set_callback(dev); ui_sb_update_icon(SB_ZIP | dev->id, 0); zip_log("ZIP %i: UNIT ATTENTION\n", dev->id); } - static void zip_buf_alloc(zip_t *dev, uint32_t len) { zip_log("ZIP %i: Allocated buffer length: %i\n", dev->id, len); if (!dev->buffer) - dev->buffer = (uint8_t *) malloc(len); + dev->buffer = (uint8_t *) malloc(len); } - static void zip_buf_free(zip_t *dev) { if (dev->buffer) { - zip_log("ZIP %i: Freeing buffer...\n", dev->id); - free(dev->buffer); - dev->buffer = NULL; + zip_log("ZIP %i: Freeing buffer...\n", dev->id); + free(dev->buffer); + dev->buffer = NULL; } } - static void zip_bus_master_error(scsi_common_t *sc) { @@ -1076,124 +1021,114 @@ zip_bus_master_error(scsi_common_t *sc) zip_cmd_error(dev); } - static void zip_not_ready(zip_t *dev) { zip_sense_key = SENSE_NOT_READY; - zip_asc = ASC_MEDIUM_NOT_PRESENT; - zip_ascq = 0; + zip_asc = ASC_MEDIUM_NOT_PRESENT; + zip_ascq = 0; zip_cmd_error(dev); } - static void zip_write_protected(zip_t *dev) { zip_sense_key = SENSE_UNIT_ATTENTION; - zip_asc = ASC_WRITE_PROTECTED; - zip_ascq = 0; + zip_asc = ASC_WRITE_PROTECTED; + zip_ascq = 0; zip_cmd_error(dev); } - static void zip_invalid_lun(zip_t *dev) { zip_sense_key = SENSE_ILLEGAL_REQUEST; - zip_asc = ASC_INV_LUN; - zip_ascq = 0; + zip_asc = ASC_INV_LUN; + zip_ascq = 0; zip_cmd_error(dev); } - static void zip_illegal_opcode(zip_t *dev) { zip_sense_key = SENSE_ILLEGAL_REQUEST; - zip_asc = ASC_ILLEGAL_OPCODE; - zip_ascq = 0; + zip_asc = ASC_ILLEGAL_OPCODE; + zip_ascq = 0; zip_cmd_error(dev); } - static void zip_lba_out_of_range(zip_t *dev) { zip_sense_key = SENSE_ILLEGAL_REQUEST; - zip_asc = ASC_LBA_OUT_OF_RANGE; - zip_ascq = 0; + zip_asc = ASC_LBA_OUT_OF_RANGE; + zip_ascq = 0; zip_cmd_error(dev); } - static void zip_invalid_field(zip_t *dev) { zip_sense_key = SENSE_ILLEGAL_REQUEST; - zip_asc = ASC_INV_FIELD_IN_CMD_PACKET; - zip_ascq = 0; + zip_asc = ASC_INV_FIELD_IN_CMD_PACKET; + zip_ascq = 0; zip_cmd_error(dev); - dev->status = 0x53; + dev->tf->status = 0x53; } - static void zip_invalid_field_pl(zip_t *dev) { zip_sense_key = SENSE_ILLEGAL_REQUEST; - zip_asc = ASC_INV_FIELD_IN_PARAMETER_LIST; - zip_ascq = 0; + zip_asc = ASC_INV_FIELD_IN_PARAMETER_LIST; + zip_ascq = 0; zip_cmd_error(dev); - dev->status = 0x53; + dev->tf->status = 0x53; } - static void zip_data_phase_error(zip_t *dev) { zip_sense_key = SENSE_ILLEGAL_REQUEST; - zip_asc = ASC_DATA_PHASE_ERROR; - zip_ascq = 0; + zip_asc = ASC_DATA_PHASE_ERROR; + zip_ascq = 0; zip_cmd_error(dev); } - static int -zip_blocks(zip_t *dev, int32_t *len, int first_batch, int out) +zip_blocks(zip_t *dev, int32_t *len, UNUSED(int first_batch), int out) { *len = 0; - int i; if (!dev->sector_len) { - zip_command_complete(dev); - return -1; + zip_command_complete(dev); + return -1; } zip_log("%sing %i blocks starting from %i...\n", out ? "Writ" : "Read", dev->requested_blocks, dev->sector_pos); if (dev->sector_pos >= dev->drv->medium_size) { - zip_log("ZIP %i: Trying to %s beyond the end of disk\n", dev->id, out ? "write" : "read"); - zip_lba_out_of_range(dev); - return 0; + zip_log("ZIP %i: Trying to %s beyond the end of disk\n", dev->id, out ? "write" : "read"); + zip_lba_out_of_range(dev); + return 0; } *len = dev->requested_blocks << 9; - for (i = 0; i < dev->requested_blocks; i++) { - if (fseek(dev->drv->f, dev->drv->base + (dev->sector_pos << 9) + (i << 9), SEEK_SET) == 1) - break; + for (int i = 0; i < dev->requested_blocks; i++) { + if (fseek(dev->drv->fp, dev->drv->base + (dev->sector_pos << 9) + (i << 9), SEEK_SET) == 1) + break; - if (feof(dev->drv->f)) - break; + if (feof(dev->drv->fp)) + break; - if (out) { - if (fwrite(dev->buffer + (i << 9), 1, 512, dev->drv->f) != 512) - fatal("zip_blocks(): Error writing data\n"); - } else { - if (fread(dev->buffer + (i << 9), 1, 512, dev->drv->f) != 512) - fatal("zip_blocks(): Error reading data\n"); - } + if (out) { + if (fwrite(dev->buffer + (i << 9), 1, 512, dev->drv->fp) != 512) + fatal("zip_blocks(): Error writing data\n"); + } else { + if (fread(dev->buffer + (i << 9), 1, 512, dev->drv->fp) != 512) + fatal("zip_blocks(): Error reading data\n"); + } } zip_log("%s %i bytes of blocks...\n", out ? "Written" : "Read", *len); @@ -1204,93 +1139,89 @@ zip_blocks(zip_t *dev, int32_t *len, int first_batch, int out) return 1; } - void zip_insert(zip_t *dev) { dev->unit_attention = 1; } - /*SCSI Sense Initialization*/ void zip_sense_code_ok(zip_t *dev) -{ +{ zip_sense_key = SENSE_NONE; - zip_asc = 0; - zip_ascq = 0; + zip_asc = 0; + zip_ascq = 0; } - static int zip_pre_execution_check(zip_t *dev, uint8_t *cdb) { int ready = 0; - if (dev->drv->bus_type == ZIP_BUS_SCSI) { - if ((cdb[0] != GPCMD_REQUEST_SENSE) && (dev->cur_lun == SCSI_LUN_USE_CDB) && (cdb[1] & 0xe0)) { - zip_log("ZIP %i: Attempting to execute a unknown command targeted at SCSI LUN %i\n", dev->id, ((dev->request_length >> 5) & 7)); - zip_invalid_lun(dev); - return 0; - } + if ((cdb[0] != GPCMD_REQUEST_SENSE) && (dev->cur_lun == SCSI_LUN_USE_CDB) && (cdb[1] & 0xe0)) { + zip_log("ZIP %i: Attempting to execute a unknown command targeted at SCSI LUN %i\n", dev->id, + ((dev->tf->request_length >> 5) & 7)); + zip_invalid_lun(dev); + return 0; } if (!(zip_command_flags[cdb[0]] & IMPLEMENTED)) { - zip_log("ZIP %i: Attempting to execute unknown command %02X over %s\n", dev->id, cdb[0], - (dev->drv->bus_type == ZIP_BUS_SCSI) ? "SCSI" : "ATAPI"); + zip_log("ZIP %i: Attempting to execute unknown command %02X over %s\n", dev->id, cdb[0], + (dev->drv->bus_type == ZIP_BUS_SCSI) ? "SCSI" : "ATAPI"); - zip_illegal_opcode(dev); - return 0; + zip_illegal_opcode(dev); + return 0; } if ((dev->drv->bus_type < ZIP_BUS_SCSI) && (zip_command_flags[cdb[0]] & SCSI_ONLY)) { - zip_log("ZIP %i: Attempting to execute SCSI-only command %02X over ATAPI\n", dev->id, cdb[0]); - zip_illegal_opcode(dev); - return 0; + zip_log("ZIP %i: Attempting to execute SCSI-only command %02X over ATAPI\n", dev->id, cdb[0]); + zip_illegal_opcode(dev); + return 0; } if ((dev->drv->bus_type == ZIP_BUS_SCSI) && (zip_command_flags[cdb[0]] & ATAPI_ONLY)) { - zip_log("ZIP %i: Attempting to execute ATAPI-only command %02X over SCSI\n", dev->id, cdb[0]); - zip_illegal_opcode(dev); - return 0; + zip_log("ZIP %i: Attempting to execute ATAPI-only command %02X over SCSI\n", dev->id, cdb[0]); + zip_illegal_opcode(dev); + return 0; } - ready = (dev->drv->f != NULL); + ready = (dev->drv->fp != NULL); /* If the drive is not ready, there is no reason to keep the UNIT ATTENTION condition present, as we only use it to mark disc changes. */ if (!ready && dev->unit_attention) - dev->unit_attention = 0; + dev->unit_attention = 0; /* If the UNIT ATTENTION condition is set and the command does not allow execution under it, error out and report the condition. */ if (dev->unit_attention == 1) { - /* Only increment the unit attention phase if the command can not pass through it. */ - if (!(zip_command_flags[cdb[0]] & ALLOW_UA)) { - /* zip_log("ZIP %i: Unit attention now 2\n", dev->id); */ - dev->unit_attention = 2; - zip_log("ZIP %i: UNIT ATTENTION: Command %02X not allowed to pass through\n", dev->id, cdb[0]); - zip_unit_attention(dev); - return 0; - } + /* Only increment the unit attention phase if the command can not pass through it. */ + if (!(zip_command_flags[cdb[0]] & ALLOW_UA)) { + /* zip_log("ZIP %i: Unit attention now 2\n", dev->id); */ + dev->unit_attention = 2; + zip_log("ZIP %i: UNIT ATTENTION: Command %02X not allowed to pass through\n", dev->id, cdb[0]); + zip_unit_attention(dev); + return 0; + } } else if (dev->unit_attention == 2) { - if (cdb[0] != GPCMD_REQUEST_SENSE) { - /* zip_log("ZIP %i: Unit attention now 0\n", dev->id); */ - dev->unit_attention = 0; - } + if (cdb[0] != GPCMD_REQUEST_SENSE) { + /* zip_log("ZIP %i: Unit attention now 0\n", dev->id); */ + dev->unit_attention = 0; + } } /* Unless the command is REQUEST SENSE, clear the sense. This will *NOT* the UNIT ATTENTION condition if it's set. */ if (cdb[0] != GPCMD_REQUEST_SENSE) - zip_sense_clear(dev, cdb[0]); + zip_sense_clear(dev, cdb[0]); /* Next it's time for NOT READY. */ if ((zip_command_flags[cdb[0]] & CHECK_READY) && !ready) { - zip_log("ZIP %i: Not ready (%02X)\n", dev->id, cdb[0]); - zip_not_ready(dev); - return 0; + zip_log("ZIP %i: Not ready (%02X)\n", dev->id, cdb[0]); + zip_not_ready(dev); + return 0; } zip_log("ZIP %i: Continuing with command %02X\n", dev->id, cdb[0]); @@ -1298,15 +1229,15 @@ zip_pre_execution_check(zip_t *dev, uint8_t *cdb) return 1; } - static void zip_seek(zip_t *dev, uint32_t pos) { - /* zip_log("ZIP %i: Seek %08X\n", dev->id, pos); */ - dev->sector_pos = pos; +#if 0 + zip_log("ZIP %i: Seek %08X\n", dev->id, pos); +#endif + dev->sector_pos = pos; } - static void zip_rezero(zip_t *dev) { @@ -1314,73 +1245,70 @@ zip_rezero(zip_t *dev) zip_seek(dev, 0); } - void zip_reset(scsi_common_t *sc) { zip_t *dev = (zip_t *) sc; zip_rezero(dev); - dev->status = 0; - dev->callback = 0.0; + dev->tf->status = 0; + dev->callback = 0.0; zip_set_callback(dev); - dev->phase = 1; - dev->request_length = 0xEB14; - dev->packet_status = PHASE_NONE; - dev->unit_attention = 0; - dev->cur_lun = SCSI_LUN_USE_CDB; + dev->tf->phase = 1; + dev->tf->request_length = 0xEB14; + dev->packet_status = PHASE_NONE; + dev->unit_attention = 0; + dev->cur_lun = SCSI_LUN_USE_CDB; } - static void zip_request_sense(zip_t *dev, uint8_t *buffer, uint8_t alloc_length, int desc) -{ +{ /*Will return 18 bytes of 0*/ if (alloc_length != 0) { - memset(buffer, 0, alloc_length); - if (!desc) - memcpy(buffer, dev->sense, alloc_length); - else { - buffer[1] = zip_sense_key; - buffer[2] = zip_asc; - buffer[3] = zip_ascq; - } + memset(buffer, 0, alloc_length); + if (!desc) + memcpy(buffer, dev->sense, alloc_length); + else { + buffer[1] = zip_sense_key; + buffer[2] = zip_asc; + buffer[3] = zip_ascq; + } } buffer[0] = desc ? 0x72 : 0x70; if (dev->unit_attention && (zip_sense_key == 0)) { - buffer[desc ? 1 : 2] = SENSE_UNIT_ATTENTION; - buffer[desc ? 2 : 12] = ASC_MEDIUM_MAY_HAVE_CHANGED; - buffer[desc ? 3 : 13] = 0; + buffer[desc ? 1 : 2] = SENSE_UNIT_ATTENTION; + buffer[desc ? 2 : 12] = ASC_MEDIUM_MAY_HAVE_CHANGED; + buffer[desc ? 3 : 13] = 0; } zip_log("ZIP %i: Reporting sense: %02X %02X %02X\n", dev->id, buffer[2], buffer[12], buffer[13]); if (buffer[desc ? 1 : 2] == SENSE_UNIT_ATTENTION) { - /* If the last remaining sense is unit attention, clear - that condition. */ - dev->unit_attention = 0; + /* If the last remaining sense is unit attention, clear + that condition. */ + dev->unit_attention = 0; } /* Clear the sense stuff as per the spec. */ zip_sense_clear(dev, GPCMD_REQUEST_SENSE); } - static void zip_request_sense_for_scsi(scsi_common_t *sc, uint8_t *buffer, uint8_t alloc_length) { - zip_t *dev = (zip_t *) sc; - int ready = 0; + zip_t *dev = (zip_t *) sc; + int ready = 0; - ready = (dev->drv->f != NULL); + ready = (dev->drv->fp != NULL); if (!ready && dev->unit_attention) { - /* If the drive is not ready, there is no reason to keep the - UNIT ATTENTION condition present, as we only use it to mark - disc changes. */ - dev->unit_attention = 0; + /* If the drive is not ready, there is no reason to keep the + UNIT ATTENTION condition present, as we only use it to mark + disc changes. */ + dev->unit_attention = 0; } /* Do *NOT* advance the unit attention phase. */ @@ -1388,59 +1316,60 @@ zip_request_sense_for_scsi(scsi_common_t *sc, uint8_t *buffer, uint8_t alloc_len zip_request_sense(dev, buffer, alloc_length, 0); } - static void zip_set_buf_len(zip_t *dev, int32_t *BufLen, int32_t *src_len) { if (dev->drv->bus_type == ZIP_BUS_SCSI) { - if (*BufLen == -1) - *BufLen = *src_len; - else { - *BufLen = MIN(*src_len, *BufLen); - *src_len = *BufLen; - } - zip_log("ZIP %i: Actual transfer length: %i\n", dev->id, *BufLen); + if (*BufLen == -1) + *BufLen = *src_len; + else { + *BufLen = MIN(*src_len, *BufLen); + *src_len = *BufLen; + } + zip_log("ZIP %i: Actual transfer length: %i\n", dev->id, *BufLen); } } - static void zip_command(scsi_common_t *sc, uint8_t *cdb) { - zip_t *dev = (zip_t *) sc; - int pos = 0, block_desc = 0; - int ret; - int32_t len, max_len; - int32_t alloc_length; + zip_t *dev = (zip_t *) sc; + int pos = 0; + int block_desc = 0; + int ret; + int32_t len; + int32_t max_len; + int32_t alloc_length; uint32_t i = 0; - int size_idx, idx = 0; + int size_idx; + int idx = 0; unsigned preamble_len; - int32_t blen = 0; + int32_t blen = 0; int32_t *BufLen; - uint8_t scsi_bus = (dev->drv->scsi_device_id >> 4) & 0x0f; - uint8_t scsi_id = dev->drv->scsi_device_id & 0x0f; + uint8_t scsi_bus = (dev->drv->scsi_device_id >> 4) & 0x0f; + uint8_t scsi_id = dev->drv->scsi_device_id & 0x0f; if (dev->drv->bus_type == ZIP_BUS_SCSI) { - BufLen = &scsi_devices[scsi_bus][scsi_id].buffer_length; - dev->status &= ~ERR_STAT; + BufLen = &scsi_devices[scsi_bus][scsi_id].buffer_length; + dev->tf->status &= ~ERR_STAT; } else { - BufLen = &blen; - dev->error = 0; + BufLen = &blen; + dev->tf->error = 0; } - dev->packet_len = 0; + dev->packet_len = 0; dev->request_pos = 0; memcpy(dev->current_cdb, cdb, 12); if (cdb[0] != 0) { - zip_log("ZIP %i: Command 0x%02X, Sense Key %02X, Asc %02X, Ascq %02X, Unit attention: %i\n", - dev->id, cdb[0], zip_sense_key, zip_asc, zip_ascq, dev->unit_attention); - zip_log("ZIP %i: Request length: %04X\n", dev->id, dev->request_length); + zip_log("ZIP %i: Command 0x%02X, Sense Key %02X, Asc %02X, Ascq %02X, Unit attention: %i\n", + dev->id, cdb[0], zip_sense_key, zip_asc, zip_ascq, dev->unit_attention); + zip_log("ZIP %i: Request length: %04X\n", dev->id, dev->tf->request_length); - zip_log("ZIP %i: CDB: %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X\n", dev->id, - cdb[0], cdb[1], cdb[2], cdb[3], cdb[4], cdb[5], cdb[6], cdb[7], - cdb[8], cdb[9], cdb[10], cdb[11]); + zip_log("ZIP %i: CDB: %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X\n", dev->id, + cdb[0], cdb[1], cdb[2], cdb[3], cdb[4], cdb[5], cdb[6], cdb[7], + cdb[8], cdb[9], cdb[10], cdb[11]); } dev->sector_len = 0; @@ -1449,626 +1378,663 @@ zip_command(scsi_common_t *sc, uint8_t *cdb) /* This handles the Not Ready/Unit Attention check if it has to be handled at this point. */ if (zip_pre_execution_check(dev, cdb) == 0) - return; + return; switch (cdb[0]) { - case GPCMD_SEND_DIAGNOSTIC: - if (!(cdb[1] & (1 << 2))) { - zip_invalid_field(dev); - return; - } - /*FALLTHROUGH*/ - case GPCMD_SCSI_RESERVE: - case GPCMD_SCSI_RELEASE: - case GPCMD_TEST_UNIT_READY: - zip_set_phase(dev, SCSI_PHASE_STATUS); - zip_command_complete(dev); - break; - - case GPCMD_FORMAT_UNIT: - if (dev->drv->read_only) { - zip_write_protected(dev); - return; - } - - zip_set_phase(dev, SCSI_PHASE_STATUS); - zip_command_complete(dev); - break; - - case GPCMD_IOMEGA_SENSE: - zip_set_phase(dev, SCSI_PHASE_DATA_IN); - max_len = cdb[4]; - zip_buf_alloc(dev, 256); - zip_set_buf_len(dev, BufLen, &max_len); - memset(dev->buffer, 0, 256); - if (cdb[2] == 1) { - /* This page is related to disk health status - setting - this page to 0 makes disk health read as "marginal". */ - dev->buffer[0] = 0x58; - dev->buffer[1] = 0x00; - for (i = 0x00; i < 0x58; i++) - dev->buffer[i + 0x02] = 0xff; - } else if (cdb[2] == 2) { - dev->buffer[0] = 0x3d; - dev->buffer[1] = 0x00; - for (i = 0x00; i < 0x13; i++) - dev->buffer[i + 0x02] = 0x00; - dev->buffer[0x15] = 0x00; - if (dev->drv->read_only) - dev->buffer[0x15] |= 0x02; - for (i = 0x00; i < 0x27; i++) - dev->buffer[i + 0x16] = 0x00; - } else { - zip_invalid_field(dev); - zip_buf_free(dev); - return; - } - zip_data_command_finish(dev, 18, 18, cdb[4], 0); - break; - - case GPCMD_REZERO_UNIT: - dev->sector_pos = dev->sector_len = 0; - zip_seek(dev, 0); - zip_set_phase(dev, SCSI_PHASE_STATUS); - break; - - case GPCMD_REQUEST_SENSE: - /* If there's a unit attention condition and there's a buffered not ready, a standalone REQUEST SENSE - should forget about the not ready, and report unit attention straight away. */ - zip_set_phase(dev, SCSI_PHASE_DATA_IN); - max_len = cdb[4]; - - if (!max_len) { - zip_set_phase(dev, SCSI_PHASE_STATUS); - dev->packet_status = PHASE_COMPLETE; - dev->callback = 20.0 * ZIP_TIME; - zip_set_callback(dev); - break; - } - - zip_buf_alloc(dev, 256); - zip_set_buf_len(dev, BufLen, &max_len); - len = (cdb[1] & 1) ? 8 : 18; - zip_request_sense(dev, dev->buffer, max_len, cdb[1] & 1); - zip_data_command_finish(dev, len, len, cdb[4], 0); - break; - - case GPCMD_MECHANISM_STATUS: - zip_set_phase(dev, SCSI_PHASE_DATA_IN); - len = (cdb[8] << 8) | cdb[9]; - - zip_buf_alloc(dev, 8); - zip_set_buf_len(dev, BufLen, &len); - - memset(dev->buffer, 0, 8); - dev->buffer[5] = 1; - - zip_data_command_finish(dev, 8, 8, len, 0); - break; - - case GPCMD_READ_6: - case GPCMD_READ_10: - case GPCMD_READ_12: - zip_set_phase(dev, SCSI_PHASE_DATA_IN); - alloc_length = 512; - - switch(cdb[0]) { - case GPCMD_READ_6: - dev->sector_len = cdb[4]; - dev->sector_pos = ((((uint32_t) cdb[1]) & 0x1f) << 16) | (((uint32_t) cdb[2]) << 8) | ((uint32_t) cdb[3]); - zip_log("ZIP %i: Length: %i, LBA: %i\n", dev->id, dev->sector_len, dev->sector_pos); - break; - case GPCMD_READ_10: - dev->sector_len = (cdb[7] << 8) | cdb[8]; - dev->sector_pos = (cdb[2] << 24) | (cdb[3] << 16) | (cdb[4] << 8) | cdb[5]; - zip_log("ZIP %i: Length: %i, LBA: %i\n", dev->id, dev->sector_len, dev->sector_pos); - break; - case GPCMD_READ_12: - dev->sector_len = (((uint32_t) cdb[6]) << 24) | (((uint32_t) cdb[7]) << 16) | (((uint32_t) cdb[8]) << 8) | ((uint32_t) cdb[9]); - dev->sector_pos = (((uint32_t) cdb[2]) << 24) | (((uint32_t) cdb[3]) << 16) | (((uint32_t) cdb[4]) << 8) | ((uint32_t) cdb[5]); - break; - } - - if (!dev->sector_len) { - zip_set_phase(dev, SCSI_PHASE_STATUS); - /* zip_log("ZIP %i: All done - callback set\n", dev->id); */ - dev->packet_status = PHASE_COMPLETE; - dev->callback = 20.0 * ZIP_TIME; - zip_set_callback(dev); - break; - } - - max_len = dev->sector_len; - dev->requested_blocks = max_len; /* If we're reading all blocks in one go for DMA, why not also for PIO, it should NOT - matter anyway, this step should be identical and only the way the read dat is - transferred to the host should be different. */ - - dev->packet_len = max_len * alloc_length; - zip_buf_alloc(dev, dev->packet_len); - - ret = zip_blocks(dev, &alloc_length, 1, 0); - if (ret <= 0) { - zip_set_phase(dev, SCSI_PHASE_STATUS); - dev->packet_status = PHASE_COMPLETE; - dev->callback = 20.0 * ZIP_TIME; - zip_set_callback(dev); - zip_buf_free(dev); - return; - } - - dev->requested_blocks = max_len; - dev->packet_len = alloc_length; - - zip_set_buf_len(dev, BufLen, (int32_t *) &dev->packet_len); - - zip_data_command_finish(dev, alloc_length, 512, alloc_length, 0); - - if (dev->packet_status != PHASE_COMPLETE) - ui_sb_update_icon(SB_ZIP | dev->id, 1); - else - ui_sb_update_icon(SB_ZIP | dev->id, 0); - return; - - case GPCMD_VERIFY_6: - case GPCMD_VERIFY_10: - case GPCMD_VERIFY_12: - if (!(cdb[1] & 2)) { - zip_set_phase(dev, SCSI_PHASE_STATUS); - zip_command_complete(dev); - break; - } - case GPCMD_WRITE_6: - case GPCMD_WRITE_10: - case GPCMD_WRITE_AND_VERIFY_10: - case GPCMD_WRITE_12: - case GPCMD_WRITE_AND_VERIFY_12: - zip_set_phase(dev, SCSI_PHASE_DATA_OUT); - alloc_length = 512; - - if (dev->drv->read_only) { - zip_write_protected(dev); - return; - } - - switch(cdb[0]) { - case GPCMD_VERIFY_6: - case GPCMD_WRITE_6: - dev->sector_len = cdb[4]; - if (dev->sector_len == 0) - dev->sector_len = 256; /* For READ (6) and WRITE (6), a length of 0 indicates a transfer of 256 sector. */ - dev->sector_pos = ((((uint32_t) cdb[1]) & 0x1f) << 16) | (((uint32_t) cdb[2]) << 8) | ((uint32_t) cdb[3]); - break; - case GPCMD_VERIFY_10: - case GPCMD_WRITE_10: - case GPCMD_WRITE_AND_VERIFY_10: - dev->sector_len = (cdb[7] << 8) | cdb[8]; - dev->sector_pos = (cdb[2] << 24) | (cdb[3] << 16) | (cdb[4] << 8) | cdb[5]; - zip_log("ZIP %i: Length: %i, LBA: %i\n", dev->id, dev->sector_len, dev->sector_pos); - break; - case GPCMD_VERIFY_12: - case GPCMD_WRITE_12: - case GPCMD_WRITE_AND_VERIFY_12: - dev->sector_len = (((uint32_t) cdb[6]) << 24) | (((uint32_t) cdb[7]) << 16) | (((uint32_t) cdb[8]) << 8) | ((uint32_t) cdb[9]); - dev->sector_pos = (((uint32_t) cdb[2]) << 24) | (((uint32_t) cdb[3]) << 16) | (((uint32_t) cdb[4]) << 8) | ((uint32_t) cdb[5]); - break; - } - - if ((dev->sector_pos >= dev->drv->medium_size)/* || - ((dev->sector_pos + dev->sector_len - 1) >= dev->drv->medium_size)*/) { - zip_lba_out_of_range(dev); - return; - } - - if (!dev->sector_len) { - zip_set_phase(dev, SCSI_PHASE_STATUS); - /* zip_log("ZIP %i: All done - callback set\n", dev->id); */ - dev->packet_status = PHASE_COMPLETE; - dev->callback = 20.0 * ZIP_TIME; - zip_set_callback(dev); - break; - } - - max_len = dev->sector_len; - dev->requested_blocks = max_len; /* If we're writing all blocks in one go for DMA, why not also for PIO, it should NOT - matter anyway, this step should be identical and only the way the read dat is - transferred to the host should be different. */ - - dev->packet_len = max_len * alloc_length; - zip_buf_alloc(dev, dev->packet_len); - - dev->requested_blocks = max_len; - dev->packet_len = max_len << 9; - - zip_set_buf_len(dev, BufLen, (int32_t *) &dev->packet_len); - - zip_data_command_finish(dev, dev->packet_len, 512, dev->packet_len, 1); - - if (dev->packet_status != PHASE_COMPLETE) - ui_sb_update_icon(SB_ZIP | dev->id, 1); - else - ui_sb_update_icon(SB_ZIP | dev->id, 0); - return; - - case GPCMD_WRITE_SAME_10: - alloc_length = 512; - - if ((cdb[1] & 6) == 6) { - zip_invalid_field(dev); - return; - } - - if (dev->drv->read_only) { - zip_write_protected(dev); - return; - } - - dev->sector_len = (cdb[7] << 8) | cdb[8]; - dev->sector_pos = (cdb[2] << 24) | (cdb[3] << 16) | (cdb[4] << 8) | cdb[5]; - - if ((dev->sector_pos >= dev->drv->medium_size)/* || - ((dev->sector_pos + dev->sector_len - 1) >= dev->drv->medium_size)*/) { - zip_lba_out_of_range(dev); - return; - } - - if (!dev->sector_len) { - zip_set_phase(dev, SCSI_PHASE_STATUS); - /* zip_log("ZIP %i: All done - callback set\n", dev->id); */ - dev->packet_status = PHASE_COMPLETE; - dev->callback = 20.0 * ZIP_TIME; - zip_set_callback(dev); - break; - } - - zip_buf_alloc(dev, alloc_length); - zip_set_buf_len(dev, BufLen, (int32_t *) &dev->packet_len); - - max_len = 1; - dev->requested_blocks = 1; - - dev->packet_len = alloc_length; - - zip_set_phase(dev, SCSI_PHASE_DATA_OUT); - - zip_data_command_finish(dev, 512, 512, alloc_length, 1); - - if (dev->packet_status != PHASE_COMPLETE) - ui_sb_update_icon(SB_ZIP | dev->id, 1); - else - ui_sb_update_icon(SB_ZIP | dev->id, 0); - return; - - case GPCMD_MODE_SENSE_6: - case GPCMD_MODE_SENSE_10: - zip_set_phase(dev, SCSI_PHASE_DATA_IN); - - if (dev->drv->bus_type == ZIP_BUS_SCSI) - block_desc = ((cdb[1] >> 3) & 1) ? 0 : 1; - else - block_desc = 0; - - if (cdb[0] == GPCMD_MODE_SENSE_6) { - len = cdb[4]; - zip_buf_alloc(dev, 256); - } else { - len = (cdb[8] | (cdb[7] << 8)); - zip_buf_alloc(dev, 65536); - } - - if (!(zip_mode_sense_page_flags & (1LL << (uint64_t) (cdb[2] & 0x3f)))) { - zip_invalid_field(dev); - zip_buf_free(dev); - return; - } - - memset(dev->buffer, 0, len); - alloc_length = len; - - if (cdb[0] == GPCMD_MODE_SENSE_6) { - len = zip_mode_sense(dev, dev->buffer, 4, cdb[2], block_desc); - len = MIN(len, alloc_length); - dev->buffer[0] = len - 1; - dev->buffer[1] = 0; - if (block_desc) - dev->buffer[3] = 8; - } else { - len = zip_mode_sense(dev, dev->buffer, 8, cdb[2], block_desc); - len = MIN(len, alloc_length); - dev->buffer[0]=(len - 2) >> 8; - dev->buffer[1]=(len - 2) & 255; - dev->buffer[2] = 0; - if (block_desc) { - dev->buffer[6] = 0; - dev->buffer[7] = 8; - } - } - - zip_set_buf_len(dev, BufLen, &len); - - zip_log("ZIP %i: Reading mode page: %02X...\n", dev->id, cdb[2]); - - zip_data_command_finish(dev, len, len, alloc_length, 0); - return; - - case GPCMD_MODE_SELECT_6: - case GPCMD_MODE_SELECT_10: - zip_set_phase(dev, SCSI_PHASE_DATA_OUT); - - if (cdb[0] == GPCMD_MODE_SELECT_6) { - len = cdb[4]; - zip_buf_alloc(dev, 256); - } else { - len = (cdb[7] << 8) | cdb[8]; - zip_buf_alloc(dev, 65536); - } - - zip_set_buf_len(dev, BufLen, &len); - - dev->total_length = len; - dev->do_page_save = cdb[1] & 1; - - zip_data_command_finish(dev, len, len, len, 1); - return; - - case GPCMD_START_STOP_UNIT: - zip_set_phase(dev, SCSI_PHASE_STATUS); - - switch(cdb[4] & 3) { - case 0: /* Stop the disc. */ - zip_eject(dev->id); /* The Iomega Windows 9x drivers require this. */ - break; - case 1: /* Start the disc and read the TOC. */ - break; - case 2: /* Eject the disc if possible. */ - /* zip_eject(dev->id); */ - break; - case 3: /* Load the disc (close tray). */ - zip_reload(dev->id); - break; - } - - zip_command_complete(dev); - break; - - case GPCMD_INQUIRY: - zip_set_phase(dev, SCSI_PHASE_DATA_IN); - - max_len = cdb[3]; - max_len <<= 8; - max_len |= cdb[4]; - - zip_buf_alloc(dev, 65536); - - if (cdb[1] & 1) { - preamble_len = 4; - size_idx = 3; - - dev->buffer[idx++] = 0; - dev->buffer[idx++] = cdb[2]; - dev->buffer[idx++] = 0; - - idx++; - - switch (cdb[2]) { - case 0x00: - dev->buffer[idx++] = 0x00; - dev->buffer[idx++] = 0x83; - break; - case 0x83: - if (idx + 24 > max_len) { - zip_data_phase_error(dev); - zip_buf_free(dev); - return; - } - - dev->buffer[idx++] = 0x02; - dev->buffer[idx++] = 0x00; - dev->buffer[idx++] = 0x00; - dev->buffer[idx++] = 20; - ide_padstr8(dev->buffer + idx, 20, "53R141"); /* Serial */ - idx += 20; - - if (idx + 72 > cdb[4]) - goto atapi_out; - dev->buffer[idx++] = 0x02; - dev->buffer[idx++] = 0x01; - dev->buffer[idx++] = 0x00; - dev->buffer[idx++] = 68; - ide_padstr8(dev->buffer + idx, 8, "IOMEGA "); /* Vendor */ - idx += 8; - if (dev->drv->is_250) - ide_padstr8(dev->buffer + idx, 40, "ZIP 250 "); /* Product */ - else - ide_padstr8(dev->buffer + idx, 40, "ZIP 100 "); /* Product */ - idx += 40; - ide_padstr8(dev->buffer + idx, 20, "53R141"); /* Product */ - idx += 20; - break; - default: - zip_log("INQUIRY: Invalid page: %02X\n", cdb[2]); - zip_invalid_field(dev); - zip_buf_free(dev); - return; - } - } else { - preamble_len = 5; - size_idx = 4; - - memset(dev->buffer, 0, 8); - if (cdb[1] & 0xe0) - dev->buffer[0] = 0x60; /*No physical device on this LUN*/ - else - dev->buffer[0] = 0x00; /*Hard disk*/ - dev->buffer[1] = 0x80; /*Removable*/ - dev->buffer[2] = (dev->drv->bus_type == ZIP_BUS_SCSI) ? 0x02 : 0x00; /*SCSI-2 compliant*/ - dev->buffer[3] = (dev->drv->bus_type == ZIP_BUS_SCSI) ? 0x02 : 0x21; - // dev->buffer[4] = 31; - dev->buffer[4] = 0; - if (dev->drv->bus_type == ZIP_BUS_SCSI) { - dev->buffer[6] = 1; /* 16-bit transfers supported */ - dev->buffer[7] = 0x20; /* Wide bus supported */ - } - dev->buffer[7] |= 0x02; - - ide_padstr8(dev->buffer + 8, 8, "IOMEGA "); /* Vendor */ - if (dev->drv->is_250) { - ide_padstr8(dev->buffer + 16, 16, "ZIP 250 "); /* Product */ - ide_padstr8(dev->buffer + 32, 4, "42.S"); /* Revision */ - if (max_len >= 44) - ide_padstr8(dev->buffer + 36, 8, "08/08/01"); /* Date? */ - if (max_len >= 122) - ide_padstr8(dev->buffer + 96, 26, "(c) Copyright IOMEGA 2000 "); /* Copyright string */ - } else { - ide_padstr8(dev->buffer + 16, 16, "ZIP 100 "); /* Product */ - ide_padstr8(dev->buffer + 32, 4, "E.08"); /* Revision */ - } - idx = 36; - - if (max_len == 96) { - dev->buffer[4] = 91; - idx = 96; - } else if (max_len == 128) { - dev->buffer[4] = 0x75; - idx = 128; - } - } + case GPCMD_SEND_DIAGNOSTIC: + if (!(cdb[1] & (1 << 2))) { + zip_invalid_field(dev); + return; + } + fallthrough; + case GPCMD_SCSI_RESERVE: + case GPCMD_SCSI_RELEASE: + case GPCMD_TEST_UNIT_READY: + zip_set_phase(dev, SCSI_PHASE_STATUS); + zip_command_complete(dev); + break; + + case GPCMD_FORMAT_UNIT: + if (dev->drv->read_only) { + zip_write_protected(dev); + return; + } + + zip_set_phase(dev, SCSI_PHASE_STATUS); + zip_command_complete(dev); + break; + + case GPCMD_IOMEGA_SENSE: + zip_set_phase(dev, SCSI_PHASE_DATA_IN); + max_len = cdb[4]; + zip_buf_alloc(dev, 256); + zip_set_buf_len(dev, BufLen, &max_len); + memset(dev->buffer, 0, 256); + if (cdb[2] == 1) { + /* This page is related to disk health status - setting + this page to 0 makes disk health read as "marginal". */ + dev->buffer[0] = 0x58; + dev->buffer[1] = 0x00; + for (i = 0x00; i < 0x58; i++) + dev->buffer[i + 0x02] = 0xff; + } else if (cdb[2] == 2) { + dev->buffer[0] = 0x3d; + dev->buffer[1] = 0x00; + for (i = 0x00; i < 0x13; i++) + dev->buffer[i + 0x02] = 0x00; + dev->buffer[0x15] = 0x00; + if (dev->drv->read_only) + dev->buffer[0x15] |= 0x02; + for (i = 0x00; i < 0x27; i++) + dev->buffer[i + 0x16] = 0x00; + } else { + zip_invalid_field(dev); + zip_buf_free(dev); + return; + } + zip_data_command_finish(dev, 18, 18, cdb[4], 0); + break; + + case GPCMD_REZERO_UNIT: + dev->sector_pos = dev->sector_len = 0; + zip_seek(dev, 0); + zip_set_phase(dev, SCSI_PHASE_STATUS); + break; + + case GPCMD_REQUEST_SENSE: + /* If there's a unit attention condition and there's a buffered not + ready, a standalone REQUEST SENSE should forget about the not + ready, and report unit attention straight away. */ + zip_set_phase(dev, SCSI_PHASE_DATA_IN); + max_len = cdb[4]; + + if (!max_len) { + zip_set_phase(dev, SCSI_PHASE_STATUS); + dev->packet_status = PHASE_COMPLETE; + dev->callback = 20.0 * ZIP_TIME; + zip_set_callback(dev); + break; + } + + zip_buf_alloc(dev, 256); + zip_set_buf_len(dev, BufLen, &max_len); + len = (cdb[1] & 1) ? 8 : 18; + zip_request_sense(dev, dev->buffer, max_len, cdb[1] & 1); + zip_data_command_finish(dev, len, len, cdb[4], 0); + break; + + case GPCMD_MECHANISM_STATUS: + zip_set_phase(dev, SCSI_PHASE_DATA_IN); + len = (cdb[8] << 8) | cdb[9]; + + zip_buf_alloc(dev, 8); + zip_set_buf_len(dev, BufLen, &len); + + memset(dev->buffer, 0, 8); + dev->buffer[5] = 1; + + zip_data_command_finish(dev, 8, 8, len, 0); + break; + + case GPCMD_READ_6: + case GPCMD_READ_10: + case GPCMD_READ_12: + zip_set_phase(dev, SCSI_PHASE_DATA_IN); + alloc_length = 512; + + switch (cdb[0]) { + case GPCMD_READ_6: + dev->sector_len = cdb[4]; + /* + For READ (6) and WRITE (6), a length of 0 indicates a + transfer of 256 sectors. + */ + if (dev->sector_len == 0) + dev->sector_len = 256; + dev->sector_pos = ((((uint32_t) cdb[1]) & 0x1f) << 16) | + (((uint32_t) cdb[2]) << 8) | ((uint32_t) cdb[3]); + zip_log("ZIP %i: Length: %i, LBA: %i\n", dev->id, dev->sector_len, dev->sector_pos); + break; + case GPCMD_READ_10: + dev->sector_len = (cdb[7] << 8) | cdb[8]; + dev->sector_pos = (cdb[2] << 24) | (cdb[3] << 16) | (cdb[4] << 8) | cdb[5]; + zip_log("ZIP %i: Length: %i, LBA: %i\n", dev->id, dev->sector_len, dev->sector_pos); + break; + case GPCMD_READ_12: + dev->sector_len = (((uint32_t) cdb[6]) << 24) | (((uint32_t) cdb[7]) << 16) | + (((uint32_t) cdb[8]) << 8) | ((uint32_t) cdb[9]); + dev->sector_pos = (((uint32_t) cdb[2]) << 24) | (((uint32_t) cdb[3]) << 16) | + (((uint32_t) cdb[4]) << 8) | ((uint32_t) cdb[5]); + break; + + default: + break; + } + + if (dev->sector_pos >= dev->drv->medium_size) { + zip_lba_out_of_range(dev); + return; + } + + if (!dev->sector_len) { + zip_set_phase(dev, SCSI_PHASE_STATUS); + /* zip_log("ZIP %i: All done - callback set\n", dev->id); */ + dev->packet_status = PHASE_COMPLETE; + dev->callback = 20.0 * ZIP_TIME; + zip_set_callback(dev); + break; + } + + max_len = dev->sector_len; + /* + If we're reading all blocks in one go for DMA, why not also for + PIO, it should NOT matter anyway, this step should be identical + and only the way the read dat is transferred to the host should + be different. + */ + dev->requested_blocks = max_len; + + dev->packet_len = max_len * alloc_length; + zip_buf_alloc(dev, dev->packet_len); + + ret = zip_blocks(dev, &alloc_length, 1, 0); + if (ret <= 0) { + zip_set_phase(dev, SCSI_PHASE_STATUS); + dev->packet_status = PHASE_COMPLETE; + dev->callback = 20.0 * ZIP_TIME; + zip_set_callback(dev); + zip_buf_free(dev); + return; + } + + dev->requested_blocks = max_len; + dev->packet_len = alloc_length; + + zip_set_buf_len(dev, BufLen, (int32_t *) &dev->packet_len); + + zip_data_command_finish(dev, alloc_length, 512, alloc_length, 0); + + ui_sb_update_icon(SB_ZIP | dev->id, dev->packet_status != PHASE_COMPLETE); + return; + + case GPCMD_VERIFY_6: + case GPCMD_VERIFY_10: + case GPCMD_VERIFY_12: + if (!(cdb[1] & 2)) { + zip_set_phase(dev, SCSI_PHASE_STATUS); + zip_command_complete(dev); + break; + } + fallthrough; + case GPCMD_WRITE_6: + case GPCMD_WRITE_10: + case GPCMD_WRITE_AND_VERIFY_10: + case GPCMD_WRITE_12: + case GPCMD_WRITE_AND_VERIFY_12: + zip_set_phase(dev, SCSI_PHASE_DATA_OUT); + alloc_length = 512; + + if (dev->drv->read_only) { + zip_write_protected(dev); + return; + } + + switch (cdb[0]) { + case GPCMD_VERIFY_6: + case GPCMD_WRITE_6: + dev->sector_len = cdb[4]; + /* + For READ (6) and WRITE (6), a length of 0 indicates a + transfer of 256 sectors. + */ + if (dev->sector_len == 0) + dev->sector_len = 256; + dev->sector_pos = ((((uint32_t) cdb[1]) & 0x1f) << 16) | + (((uint32_t) cdb[2]) << 8) | ((uint32_t) cdb[3]); + break; + case GPCMD_VERIFY_10: + case GPCMD_WRITE_10: + case GPCMD_WRITE_AND_VERIFY_10: + dev->sector_len = (cdb[7] << 8) | cdb[8]; + dev->sector_pos = (cdb[2] << 24) | (cdb[3] << 16) | (cdb[4] << 8) | cdb[5]; + zip_log("ZIP %i: Length: %i, LBA: %i\n", dev->id, dev->sector_len, dev->sector_pos); + break; + case GPCMD_VERIFY_12: + case GPCMD_WRITE_12: + case GPCMD_WRITE_AND_VERIFY_12: + dev->sector_len = (((uint32_t) cdb[6]) << 24) | (((uint32_t) cdb[7]) << 16) | + (((uint32_t) cdb[8]) << 8) | ((uint32_t) cdb[9]); + dev->sector_pos = (((uint32_t) cdb[2]) << 24) | (((uint32_t) cdb[3]) << 16) | + (((uint32_t) cdb[4]) << 8) | ((uint32_t) cdb[5]); + break; + + default: + break; + } + + if (dev->sector_pos >= dev->drv->medium_size) { + zip_lba_out_of_range(dev); + return; + } + + if (!dev->sector_len) { + zip_set_phase(dev, SCSI_PHASE_STATUS); + /* zip_log("ZIP %i: All done - callback set\n", dev->id); */ + dev->packet_status = PHASE_COMPLETE; + dev->callback = 20.0 * ZIP_TIME; + zip_set_callback(dev); + break; + } + + max_len = dev->sector_len; + /* + If we're writing all blocks in one go for DMA, why not also for + PIO, it should NOT matter anyway, this step should be identical + and only the way the read dat is transferred to the host should + be different. + */ + dev->requested_blocks = max_len; + + dev->packet_len = max_len * alloc_length; + zip_buf_alloc(dev, dev->packet_len); + + dev->requested_blocks = max_len; + dev->packet_len = max_len << 9; + + zip_set_buf_len(dev, BufLen, (int32_t *) &dev->packet_len); + + zip_data_command_finish(dev, dev->packet_len, 512, dev->packet_len, 1); + + ui_sb_update_icon(SB_ZIP | dev->id, dev->packet_status != PHASE_COMPLETE); + return; + + case GPCMD_WRITE_SAME_10: + alloc_length = 512; + + if ((cdb[1] & 6) == 6) { + zip_invalid_field(dev); + return; + } + + if (dev->drv->read_only) { + zip_write_protected(dev); + return; + } + + dev->sector_len = (cdb[7] << 8) | cdb[8]; + dev->sector_pos = (cdb[2] << 24) | (cdb[3] << 16) | (cdb[4] << 8) | cdb[5]; + + if (dev->sector_pos >= dev->drv->medium_size) { + zip_lba_out_of_range(dev); + return; + } + + if (!dev->sector_len) { + zip_set_phase(dev, SCSI_PHASE_STATUS); + /* zip_log("ZIP %i: All done - callback set\n", dev->id); */ + dev->packet_status = PHASE_COMPLETE; + dev->callback = 20.0 * ZIP_TIME; + zip_set_callback(dev); + break; + } + + zip_buf_alloc(dev, alloc_length); + zip_set_buf_len(dev, BufLen, (int32_t *) &dev->packet_len); + + max_len = 1; + dev->requested_blocks = 1; + + dev->packet_len = alloc_length; + + zip_set_phase(dev, SCSI_PHASE_DATA_OUT); + + zip_data_command_finish(dev, 512, 512, alloc_length, 1); + + ui_sb_update_icon(SB_ZIP | dev->id, dev->packet_status != PHASE_COMPLETE); + return; + + case GPCMD_MODE_SENSE_6: + case GPCMD_MODE_SENSE_10: + zip_set_phase(dev, SCSI_PHASE_DATA_IN); + + if (dev->drv->bus_type == ZIP_BUS_SCSI) + block_desc = ((cdb[1] >> 3) & 1) ? 0 : 1; + else + block_desc = 0; + + if (cdb[0] == GPCMD_MODE_SENSE_6) { + len = cdb[4]; + zip_buf_alloc(dev, 256); + } else { + len = (cdb[8] | (cdb[7] << 8)); + zip_buf_alloc(dev, 65536); + } + + if (!(zip_mode_sense_page_flags & (1LL << (uint64_t) (cdb[2] & 0x3f)))) { + zip_invalid_field(dev); + zip_buf_free(dev); + return; + } + + memset(dev->buffer, 0, len); + alloc_length = len; + + if (cdb[0] == GPCMD_MODE_SENSE_6) { + len = zip_mode_sense(dev, dev->buffer, 4, cdb[2], block_desc); + len = MIN(len, alloc_length); + dev->buffer[0] = len - 1; + dev->buffer[1] = 0; + if (block_desc) + dev->buffer[3] = 8; + } else { + len = zip_mode_sense(dev, dev->buffer, 8, cdb[2], block_desc); + len = MIN(len, alloc_length); + dev->buffer[0] = (len - 2) >> 8; + dev->buffer[1] = (len - 2) & 255; + dev->buffer[2] = 0; + if (block_desc) { + dev->buffer[6] = 0; + dev->buffer[7] = 8; + } + } + + zip_set_buf_len(dev, BufLen, &len); + + zip_log("ZIP %i: Reading mode page: %02X...\n", dev->id, cdb[2]); + + zip_data_command_finish(dev, len, len, alloc_length, 0); + return; + + case GPCMD_MODE_SELECT_6: + case GPCMD_MODE_SELECT_10: + zip_set_phase(dev, SCSI_PHASE_DATA_OUT); + + if (cdb[0] == GPCMD_MODE_SELECT_6) { + len = cdb[4]; + zip_buf_alloc(dev, 256); + } else { + len = (cdb[7] << 8) | cdb[8]; + zip_buf_alloc(dev, 65536); + } + + zip_set_buf_len(dev, BufLen, &len); + + dev->total_length = len; + dev->do_page_save = cdb[1] & 1; + + zip_data_command_finish(dev, len, len, len, 1); + return; + + case GPCMD_START_STOP_UNIT: + zip_set_phase(dev, SCSI_PHASE_STATUS); + + switch (cdb[4] & 3) { + case 0: /* Stop the disc. */ + zip_eject(dev->id); /* The Iomega Windows 9x drivers require this. */ + break; + case 1: /* Start the disc and read the TOC. */ + break; + case 2: /* Eject the disc if possible. */ +#if 0 + zip_eject(dev->id); +#endif + break; + case 3: /* Load the disc (close tray). */ + zip_reload(dev->id); + break; + + default: + break; + } + + zip_command_complete(dev); + break; + + case GPCMD_INQUIRY: + zip_set_phase(dev, SCSI_PHASE_DATA_IN); + + max_len = cdb[3]; + max_len <<= 8; + max_len |= cdb[4]; + + zip_buf_alloc(dev, 65536); + + if (cdb[1] & 1) { + preamble_len = 4; + size_idx = 3; + + dev->buffer[idx++] = 0; + dev->buffer[idx++] = cdb[2]; + dev->buffer[idx++] = 0; + + idx++; + + switch (cdb[2]) { + case 0x00: + dev->buffer[idx++] = 0x00; + dev->buffer[idx++] = 0x83; + break; + case 0x83: + if (idx + 24 > max_len) { + zip_data_phase_error(dev); + zip_buf_free(dev); + return; + } + + dev->buffer[idx++] = 0x02; + dev->buffer[idx++] = 0x00; + dev->buffer[idx++] = 0x00; + dev->buffer[idx++] = 20; + ide_padstr8(dev->buffer + idx, 20, "53R141"); /* Serial */ + idx += 20; + + if (idx + 72 > cdb[4]) + goto atapi_out; + dev->buffer[idx++] = 0x02; + dev->buffer[idx++] = 0x01; + dev->buffer[idx++] = 0x00; + dev->buffer[idx++] = 68; + ide_padstr8(dev->buffer + idx, 8, "IOMEGA "); /* Vendor */ + idx += 8; + if (dev->drv->is_250) + ide_padstr8(dev->buffer + idx, 40, "ZIP 250 "); /* Product */ + else + ide_padstr8(dev->buffer + idx, 40, "ZIP 100 "); /* Product */ + idx += 40; + ide_padstr8(dev->buffer + idx, 20, "53R141"); /* Product */ + idx += 20; + break; + default: + zip_log("INQUIRY: Invalid page: %02X\n", cdb[2]); + zip_invalid_field(dev); + zip_buf_free(dev); + return; + } + } else { + preamble_len = 5; + size_idx = 4; + + memset(dev->buffer, 0, 8); + if (cdb[1] & 0xe0) + dev->buffer[0] = 0x60; /*No physical device on this LUN*/ + else + dev->buffer[0] = 0x00; /*Hard disk*/ + dev->buffer[1] = 0x80; /*Removable*/ + dev->buffer[2] = (dev->drv->bus_type == ZIP_BUS_SCSI) ? 0x02 : 0x00; /*SCSI-2 compliant*/ + dev->buffer[3] = (dev->drv->bus_type == ZIP_BUS_SCSI) ? 0x02 : 0x21; +#if 0 + dev->buffer[4] = 31; +#endif + dev->buffer[4] = 0; + if (dev->drv->bus_type == ZIP_BUS_SCSI) { + dev->buffer[6] = 1; /* 16-bit transfers supported */ + dev->buffer[7] = 0x20; /* Wide bus supported */ + } + dev->buffer[7] |= 0x02; + + ide_padstr8(dev->buffer + 8, 8, "IOMEGA "); /* Vendor */ + if (dev->drv->is_250) { + ide_padstr8(dev->buffer + 16, 16, "ZIP 250 "); /* Product */ + ide_padstr8(dev->buffer + 32, 4, "42.S"); /* Revision */ + if (max_len >= 44) + ide_padstr8(dev->buffer + 36, 8, "08/08/01"); /* Date? */ + if (max_len >= 122) + ide_padstr8(dev->buffer + 96, 26, "(c) Copyright IOMEGA 2000 "); /* Copyright string */ + } else { + ide_padstr8(dev->buffer + 16, 16, "ZIP 100 "); /* Product */ + ide_padstr8(dev->buffer + 32, 4, "E.08"); /* Revision */ + } + idx = 36; + + if (max_len == 96) { + dev->buffer[4] = 91; + idx = 96; + } else if (max_len == 128) { + dev->buffer[4] = 0x75; + idx = 128; + } + } atapi_out: - dev->buffer[size_idx] = idx - preamble_len; - len=idx; + dev->buffer[size_idx] = idx - preamble_len; + len = idx; - len = MIN(len, max_len); - zip_set_buf_len(dev, BufLen, &len); + len = MIN(len, max_len); + zip_set_buf_len(dev, BufLen, &len); - zip_data_command_finish(dev, len, len, max_len, 0); - break; + zip_data_command_finish(dev, len, len, max_len, 0); + break; - case GPCMD_PREVENT_REMOVAL: - zip_set_phase(dev, SCSI_PHASE_STATUS); - zip_command_complete(dev); - break; + case GPCMD_PREVENT_REMOVAL: + zip_set_phase(dev, SCSI_PHASE_STATUS); + zip_command_complete(dev); + break; - case GPCMD_SEEK_6: - case GPCMD_SEEK_10: - zip_set_phase(dev, SCSI_PHASE_STATUS); + case GPCMD_SEEK_6: + case GPCMD_SEEK_10: + zip_set_phase(dev, SCSI_PHASE_STATUS); - switch(cdb[0]) { - case GPCMD_SEEK_6: - pos = (cdb[2] << 8) | cdb[3]; - break; - case GPCMD_SEEK_10: - pos = (cdb[2] << 24) | (cdb[3] << 16) | (cdb[4] << 8) | cdb[5]; - break; - } - zip_seek(dev, pos); - zip_command_complete(dev); - break; + switch (cdb[0]) { + case GPCMD_SEEK_6: + pos = (cdb[2] << 8) | cdb[3]; + break; + case GPCMD_SEEK_10: + pos = (cdb[2] << 24) | (cdb[3] << 16) | (cdb[4] << 8) | cdb[5]; + break; - case GPCMD_READ_CDROM_CAPACITY: - zip_set_phase(dev, SCSI_PHASE_DATA_IN); + default: + break; + } + zip_seek(dev, pos); + zip_command_complete(dev); + break; - zip_buf_alloc(dev, 8); + case GPCMD_READ_CDROM_CAPACITY: + zip_set_phase(dev, SCSI_PHASE_DATA_IN); - max_len = dev->drv->medium_size - 1; /* IMPORTANT: What's returned is the last LBA block. */ - memset(dev->buffer, 0, 8); - dev->buffer[0] = (max_len >> 24) & 0xff; - dev->buffer[1] = (max_len >> 16) & 0xff; - dev->buffer[2] = (max_len >> 8) & 0xff; - dev->buffer[3] = max_len & 0xff; - dev->buffer[6] = 2; /* 512 = 0x0200 */ - len = 8; + zip_buf_alloc(dev, 8); - zip_set_buf_len(dev, BufLen, &len); + max_len = dev->drv->medium_size - 1; /* IMPORTANT: What's returned is the last LBA block. */ + memset(dev->buffer, 0, 8); + dev->buffer[0] = (max_len >> 24) & 0xff; + dev->buffer[1] = (max_len >> 16) & 0xff; + dev->buffer[2] = (max_len >> 8) & 0xff; + dev->buffer[3] = max_len & 0xff; + dev->buffer[6] = 2; /* 512 = 0x0200 */ + len = 8; - zip_data_command_finish(dev, len, len, len, 0); - break; + zip_set_buf_len(dev, BufLen, &len); - case GPCMD_IOMEGA_EJECT: - zip_set_phase(dev, SCSI_PHASE_STATUS); - zip_eject(dev->id); - zip_command_complete(dev); - break; + zip_data_command_finish(dev, len, len, len, 0); + break; - case GPCMD_READ_FORMAT_CAPACITIES: - len = (cdb[7] << 8) | cdb[8]; + case GPCMD_IOMEGA_EJECT: + zip_set_phase(dev, SCSI_PHASE_STATUS); + zip_eject(dev->id); + zip_command_complete(dev); + break; - zip_buf_alloc(dev, len); - memset(dev->buffer, 0, len); + case GPCMD_READ_FORMAT_CAPACITIES: + len = (cdb[7] << 8) | cdb[8]; - pos = 0; + zip_buf_alloc(dev, len); + memset(dev->buffer, 0, len); - /* List header */ - dev->buffer[pos++] = 0; - dev->buffer[pos++] = 0; - dev->buffer[pos++] = 0; - if (dev->drv->f != NULL) - dev->buffer[pos++] = 16; - else - dev->buffer[pos++] = 8; + pos = 0; - /* Current/Maximum capacity header */ - if (dev->drv->is_250) { - /* ZIP 250 also supports ZIP 100 media, so if the medium is inserted, - we return the inserted medium's size, otherwise, the ZIP 250 size. */ - if (dev->drv->f != NULL) { - dev->buffer[pos++] = (dev->drv->medium_size >> 24) & 0xff; - dev->buffer[pos++] = (dev->drv->medium_size >> 16) & 0xff; - dev->buffer[pos++] = (dev->drv->medium_size >> 8) & 0xff; - dev->buffer[pos++] = dev->drv->medium_size & 0xff; - dev->buffer[pos++] = 2; /* Current medium capacity */ - } else { - dev->buffer[pos++] = (ZIP_250_SECTORS >> 24) & 0xff; - dev->buffer[pos++] = (ZIP_250_SECTORS >> 16) & 0xff; - dev->buffer[pos++] = (ZIP_250_SECTORS >> 8) & 0xff; - dev->buffer[pos++] = ZIP_250_SECTORS & 0xff; - dev->buffer[pos++] = 3; /* Maximum medium capacity */ - } - } else { - /* ZIP 100 only supports ZIP 100 media as well, so we always return - the ZIP 100 size. */ - dev->buffer[pos++] = (ZIP_SECTORS >> 24) & 0xff; - dev->buffer[pos++] = (ZIP_SECTORS >> 16) & 0xff; - dev->buffer[pos++] = (ZIP_SECTORS >> 8) & 0xff; - dev->buffer[pos++] = ZIP_SECTORS & 0xff; - if (dev->drv->f != NULL) - dev->buffer[pos++] = 2; - else - dev->buffer[pos++] = 3; - } + /* List header */ + dev->buffer[pos++] = 0; + dev->buffer[pos++] = 0; + dev->buffer[pos++] = 0; + if (dev->drv->fp != NULL) + dev->buffer[pos++] = 16; + else + dev->buffer[pos++] = 8; - dev->buffer[pos++] = 512 >> 16; - dev->buffer[pos++] = 512 >> 8; - dev->buffer[pos++] = 512 & 0xff; + /* Current/Maximum capacity header */ + if (dev->drv->is_250) { + /* ZIP 250 also supports ZIP 100 media, so if the medium is inserted, + we return the inserted medium's size, otherwise, the ZIP 250 size. */ + if (dev->drv->fp != NULL) { + dev->buffer[pos++] = (dev->drv->medium_size >> 24) & 0xff; + dev->buffer[pos++] = (dev->drv->medium_size >> 16) & 0xff; + dev->buffer[pos++] = (dev->drv->medium_size >> 8) & 0xff; + dev->buffer[pos++] = dev->drv->medium_size & 0xff; + dev->buffer[pos++] = 2; /* Current medium capacity */ + } else { + dev->buffer[pos++] = (ZIP_250_SECTORS >> 24) & 0xff; + dev->buffer[pos++] = (ZIP_250_SECTORS >> 16) & 0xff; + dev->buffer[pos++] = (ZIP_250_SECTORS >> 8) & 0xff; + dev->buffer[pos++] = ZIP_250_SECTORS & 0xff; + dev->buffer[pos++] = 3; /* Maximum medium capacity */ + } + } else { + /* ZIP 100 only supports ZIP 100 media as well, so we always return + the ZIP 100 size. */ + dev->buffer[pos++] = (ZIP_SECTORS >> 24) & 0xff; + dev->buffer[pos++] = (ZIP_SECTORS >> 16) & 0xff; + dev->buffer[pos++] = (ZIP_SECTORS >> 8) & 0xff; + dev->buffer[pos++] = ZIP_SECTORS & 0xff; + if (dev->drv->fp != NULL) + dev->buffer[pos++] = 2; + else + dev->buffer[pos++] = 3; + } - if (dev->drv->f != NULL) { - /* Formattable capacity descriptor */ - dev->buffer[pos++] = (dev->drv->medium_size >> 24) & 0xff; - dev->buffer[pos++] = (dev->drv->medium_size >> 16) & 0xff; - dev->buffer[pos++] = (dev->drv->medium_size >> 8) & 0xff; - dev->buffer[pos++] = dev->drv->medium_size & 0xff; - dev->buffer[pos++] = 0; - dev->buffer[pos++] = 512 >> 16; - dev->buffer[pos++] = 512 >> 8; - dev->buffer[pos++] = 512 & 0xff; - } + dev->buffer[pos++] = 512 >> 16; + dev->buffer[pos++] = 512 >> 8; + dev->buffer[pos++] = 512 & 0xff; - zip_set_buf_len(dev, BufLen, &len); + if (dev->drv->fp != NULL) { + /* Formattable capacity descriptor */ + dev->buffer[pos++] = (dev->drv->medium_size >> 24) & 0xff; + dev->buffer[pos++] = (dev->drv->medium_size >> 16) & 0xff; + dev->buffer[pos++] = (dev->drv->medium_size >> 8) & 0xff; + dev->buffer[pos++] = dev->drv->medium_size & 0xff; + dev->buffer[pos++] = 0; + dev->buffer[pos++] = 512 >> 16; + dev->buffer[pos++] = 512 >> 8; + dev->buffer[pos++] = 512 & 0xff; + } - zip_data_command_finish(dev, len, len, len, 0); - break; + zip_set_buf_len(dev, BufLen, &len); - default: - zip_illegal_opcode(dev); - break; + zip_data_command_finish(dev, len, len, len, 0); + break; + + default: + zip_illegal_opcode(dev); + break; } - /* zip_log("ZIP %i: Phase: %02X, request length: %i\n", dev->id, dev->phase, dev->request_length); */ +#if 0 + zip_log("ZIP %i: Phase: %02X, request length: %i\n", dev->id, dev->tf->phase, dev->tf->request_length); +#endif - if (zip_atapi_phase_to_scsi(dev) == SCSI_PHASE_STATUS) - zip_buf_free(dev); + if ((dev->packet_status == PHASE_COMPLETE) || (dev->packet_status == PHASE_ERROR)) + zip_buf_free(dev); } - static void zip_command_stop(scsi_common_t *sc) { @@ -2078,153 +2044,161 @@ zip_command_stop(scsi_common_t *sc) zip_buf_free(dev); } - /* The command second phase function, needed for Mode Select. */ static uint8_t zip_phase_data_out(scsi_common_t *sc) { zip_t *dev = (zip_t *) sc; - uint16_t block_desc_len, pos; + uint16_t block_desc_len; + uint16_t pos; uint16_t param_list_len; uint8_t error = 0; - uint8_t page, page_len; + uint8_t page; + uint8_t page_len; uint32_t i = 0; - uint8_t hdr_len, val, old_val, ch; + uint8_t hdr_len; + uint8_t val; + uint8_t old_val; + uint8_t ch; uint32_t last_to_write = 0; - uint32_t c, h, s; + uint32_t c; + uint32_t h; + uint32_t s; int len = 0; - switch(dev->current_cdb[0]) { - case GPCMD_VERIFY_6: - case GPCMD_VERIFY_10: - case GPCMD_VERIFY_12: - break; - case GPCMD_WRITE_6: - case GPCMD_WRITE_10: - case GPCMD_WRITE_AND_VERIFY_10: - case GPCMD_WRITE_12: - case GPCMD_WRITE_AND_VERIFY_12: - if (dev->requested_blocks > 0) - zip_blocks(dev, &len, 1, 1); - break; - case GPCMD_WRITE_SAME_10: - if (!dev->current_cdb[7] && !dev->current_cdb[8]) { - last_to_write = (dev->drv->medium_size - 1); - } else - last_to_write = dev->sector_pos + dev->sector_len - 1; + switch (dev->current_cdb[0]) { + case GPCMD_VERIFY_6: + case GPCMD_VERIFY_10: + case GPCMD_VERIFY_12: + break; + case GPCMD_WRITE_6: + case GPCMD_WRITE_10: + case GPCMD_WRITE_AND_VERIFY_10: + case GPCMD_WRITE_12: + case GPCMD_WRITE_AND_VERIFY_12: + if (dev->requested_blocks > 0) + zip_blocks(dev, &len, 1, 1); + break; + case GPCMD_WRITE_SAME_10: + if (!dev->current_cdb[7] && !dev->current_cdb[8]) { + last_to_write = (dev->drv->medium_size - 1); + } else + last_to_write = dev->sector_pos + dev->sector_len - 1; - for (i = dev->sector_pos; i <= last_to_write; i++) { - if (dev->current_cdb[1] & 2) { - dev->buffer[0] = (i >> 24) & 0xff; - dev->buffer[1] = (i >> 16) & 0xff; - dev->buffer[2] = (i >> 8) & 0xff; - dev->buffer[3] = i & 0xff; - } else if (dev->current_cdb[1] & 4) { - /* CHS are 96,1,2048 (ZIP 100) and 239,1,2048 (ZIP 250) */ - s = (i % 2048); - h = ((i - s) / 2048) % 1; - c = ((i - s) / 2048) / 1; - dev->buffer[0] = (c >> 16) & 0xff; - dev->buffer[1] = (c >> 8) & 0xff; - dev->buffer[2] = c & 0xff; - dev->buffer[3] = h & 0xff; - dev->buffer[4] = (s >> 24) & 0xff; - dev->buffer[5] = (s >> 16) & 0xff; - dev->buffer[6] = (s >> 8) & 0xff; - dev->buffer[7] = s & 0xff; - } - if (fseek(dev->drv->f, dev->drv->base + (i << 9), SEEK_SET) == -1) - fatal("zip_phase_data_out(): Error seeking\n"); - if (fwrite(dev->buffer, 1, 512, dev->drv->f) != 512) - fatal("zip_phase_data_out(): Error writing data\n"); - } - break; - case GPCMD_MODE_SELECT_6: - case GPCMD_MODE_SELECT_10: - if (dev->current_cdb[0] == GPCMD_MODE_SELECT_10) { - hdr_len = 8; - param_list_len = dev->current_cdb[7]; - param_list_len <<= 8; - param_list_len |= dev->current_cdb[8]; - } else { - hdr_len = 4; - param_list_len = dev->current_cdb[4]; - } + for (i = dev->sector_pos; i <= last_to_write; i++) { + if (dev->current_cdb[1] & 2) { + dev->buffer[0] = (i >> 24) & 0xff; + dev->buffer[1] = (i >> 16) & 0xff; + dev->buffer[2] = (i >> 8) & 0xff; + dev->buffer[3] = i & 0xff; + } else if (dev->current_cdb[1] & 4) { + /* CHS are 96, 1, 2048 (ZIP 100) and 239, 1, 2048 (ZIP 250) */ + s = (i % 2048); + h = ((i - s) / 2048) % 1; + c = ((i - s) / 2048) / 1; + dev->buffer[0] = (c >> 16) & 0xff; + dev->buffer[1] = (c >> 8) & 0xff; + dev->buffer[2] = c & 0xff; + dev->buffer[3] = h & 0xff; + dev->buffer[4] = (s >> 24) & 0xff; + dev->buffer[5] = (s >> 16) & 0xff; + dev->buffer[6] = (s >> 8) & 0xff; + dev->buffer[7] = s & 0xff; + } + if (fseek(dev->drv->fp, dev->drv->base + (i << 9), SEEK_SET) == -1) + fatal("zip_phase_data_out(): Error seeking\n"); + if (fwrite(dev->buffer, 1, 512, dev->drv->fp) != 512) + fatal("zip_phase_data_out(): Error writing data\n"); + } + break; + case GPCMD_MODE_SELECT_6: + case GPCMD_MODE_SELECT_10: + if (dev->current_cdb[0] == GPCMD_MODE_SELECT_10) { + hdr_len = 8; + param_list_len = dev->current_cdb[7]; + param_list_len <<= 8; + param_list_len |= dev->current_cdb[8]; + } else { + hdr_len = 4; + param_list_len = dev->current_cdb[4]; + } - if (dev->drv->bus_type == ZIP_BUS_SCSI) { - if (dev->current_cdb[0] == GPCMD_MODE_SELECT_6) { - block_desc_len = dev->buffer[2]; - block_desc_len <<= 8; - block_desc_len |= dev->buffer[3]; - } else { - block_desc_len = dev->buffer[6]; - block_desc_len <<= 8; - block_desc_len |= dev->buffer[7]; - } - } else - block_desc_len = 0; + if (dev->drv->bus_type == ZIP_BUS_SCSI) { + if (dev->current_cdb[0] == GPCMD_MODE_SELECT_6) { + block_desc_len = dev->buffer[2]; + block_desc_len <<= 8; + block_desc_len |= dev->buffer[3]; + } else { + block_desc_len = dev->buffer[6]; + block_desc_len <<= 8; + block_desc_len |= dev->buffer[7]; + } + } else + block_desc_len = 0; - pos = hdr_len + block_desc_len; + pos = hdr_len + block_desc_len; - while(1) { - if (pos >= param_list_len) { - zip_log("ZIP %i: Buffer has only block descriptor\n", dev->id); - break; - } + while (1) { + if (pos >= param_list_len) { + zip_log("ZIP %i: Buffer has only block descriptor\n", dev->id); + break; + } - page = dev->buffer[pos] & 0x3F; - page_len = dev->buffer[pos + 1]; + page = dev->buffer[pos] & 0x3F; + page_len = dev->buffer[pos + 1]; - pos += 2; + pos += 2; - if (!(zip_mode_sense_page_flags & (1LL << ((uint64_t) page)))) - error |= 1; - else { - for (i = 0; i < page_len; i++) { - ch = zip_mode_sense_pages_changeable.pages[page][i + 2]; - val = dev->buffer[pos + i]; - old_val = dev->ms_pages_saved.pages[page][i + 2]; - if (val != old_val) { - if (ch) - dev->ms_pages_saved.pages[page][i + 2] = val; - else - error |= 1; - } - } - } + if (!(zip_mode_sense_page_flags & (1LL << ((uint64_t) page)))) + error |= 1; + else { + for (i = 0; i < page_len; i++) { + ch = zip_mode_sense_pages_changeable.pages[page][i + 2]; + val = dev->buffer[pos + i]; + old_val = dev->ms_pages_saved.pages[page][i + 2]; + if (val != old_val) { + if (ch) + dev->ms_pages_saved.pages[page][i + 2] = val; + else + error |= 1; + } + } + } - pos += page_len; + pos += page_len; - if (dev->drv->bus_type == ZIP_BUS_SCSI) - val = zip_mode_sense_pages_default_scsi.pages[page][0] & 0x80; - else - val = zip_mode_sense_pages_default.pages[page][0] & 0x80; - if (dev->do_page_save && val) - zip_mode_sense_save(dev); + if (dev->drv->bus_type == ZIP_BUS_SCSI) + val = zip_mode_sense_pages_default_scsi.pages[page][0] & 0x80; + else + val = zip_mode_sense_pages_default.pages[page][0] & 0x80; + if (dev->do_page_save && val) + zip_mode_sense_save(dev); - if (pos >= dev->total_length) - break; - } + if (pos >= dev->total_length) + break; + } - if (error) { - zip_buf_free(dev); - zip_invalid_field_pl(dev); - return 0; - } - break; + if (error) { + zip_buf_free(dev); + zip_invalid_field_pl(dev); + return 0; + } + break; + + default: + break; } zip_command_stop((scsi_common_t *) dev); return 1; } - /* Peform a master init on the entire module. */ void zip_global_init(void) @@ -2233,81 +2207,76 @@ zip_global_init(void) memset(zip_drives, 0x00, sizeof(zip_drives)); } - static int zip_get_max(int ide_has_dma, int type) { int ret; - switch(type) { - case TYPE_PIO: - ret = ide_has_dma ? 3 : 0; - break; - case TYPE_SDMA: - default: - ret = -1; - break; - case TYPE_MDMA: - ret = ide_has_dma ? 1 : -1; - break; - case TYPE_UDMA: - ret = ide_has_dma ? 5 : -1; - break; + switch (type) { + case TYPE_PIO: + ret = ide_has_dma ? 3 : 0; + break; + case TYPE_SDMA: + default: + ret = -1; + break; + case TYPE_MDMA: + ret = ide_has_dma ? 1 : -1; + break; + case TYPE_UDMA: + ret = ide_has_dma ? 5 : -1; + break; } return ret; } - static int zip_get_timings(int ide_has_dma, int type) { int ret; - switch(type) { - case TIMINGS_DMA: - ret = ide_has_dma ? 0x96 : 0; - break; - case TIMINGS_PIO: - ret = ide_has_dma ? 0xb4 : 0; - break; - case TIMINGS_PIO_FC: - ret = ide_has_dma ? 0xb4 : 0; - break; - default: - ret = 0; - break; + switch (type) { + case TIMINGS_DMA: + ret = ide_has_dma ? 0x96 : 0; + break; + case TIMINGS_PIO: + ret = ide_has_dma ? 0xb4 : 0; + break; + case TIMINGS_PIO_FC: + ret = ide_has_dma ? 0xb4 : 0; + break; + default: + ret = 0; + break; } return ret; } - static void zip_100_identify(ide_t *ide) { - ide_padstr((char *) (ide->buffer + 23), "E.08", 8); /* Firmware */ + ide_padstr((char *) (ide->buffer + 23), "E.08", 8); /* Firmware */ ide_padstr((char *) (ide->buffer + 27), "IOMEGA ZIP 100 ATAPI", 40); /* Model */ } - static void zip_250_identify(ide_t *ide, int ide_has_dma) { - ide_padstr((char *) (ide->buffer + 23), "42.S", 8); /* Firmware */ + ide_padstr((char *) (ide->buffer + 23), "42.S", 8); /* Firmware */ ide_padstr((char *) (ide->buffer + 27), "IOMEGA ZIP 250 ATAPI", 40); /* Model */ if (ide_has_dma) { - ide->buffer[80] = 0x70; /*Supported ATA versions : ATA/ATAPI-4 ATA/ATAPI-6*/ - ide->buffer[81] = 0x19; /*Maximum ATA revision supported : ATA/ATAPI-6 T13 1410D revision 3a*/ + ide->buffer[80] = 0x70; /*Supported ATA versions : ATA/ATAPI-4 ATA/ATAPI-6*/ + ide->buffer[81] = 0x19; /*Maximum ATA revision supported : ATA/ATAPI-6 T13 1410D revision 3a*/ } } - static void zip_identify(ide_t *ide, int ide_has_dma) { - zip_t *zip; + const zip_t *zip; zip = (zip_t *) ide->sc; @@ -2317,144 +2286,149 @@ zip_identify(ide_t *ide, int ide_has_dma) as a LS-120. */ ide->buffer[0] = 0x8000 | (0 << 8) | 0x80 | (1 << 5); ide_padstr((char *) (ide->buffer + 10), "", 20); /* Serial Number */ - ide->buffer[49] = 0x200; /* LBA supported */ - ide->buffer[126] = 0xfffe; /* Interpret zero byte count limit as maximum length */ + ide->buffer[49] = 0x200; /* LBA supported */ + ide->buffer[126] = 0xfffe; /* Interpret zero byte count limit as maximum length */ if (zip_drives[zip->id].is_250) - zip_250_identify(ide, ide_has_dma); + zip_250_identify(ide, ide_has_dma); else - zip_100_identify(ide); + zip_100_identify(ide); } - static void zip_drive_reset(int c) { - zip_t *dev; + zip_t *dev; scsi_device_t *sd; - ide_t *id; - uint8_t scsi_bus = (zip_drives[c].scsi_device_id >> 4) & 0x0f; - uint8_t scsi_id = zip_drives[c].scsi_device_id & 0x0f; + ide_t *id; + uint8_t scsi_bus = (zip_drives[c].scsi_device_id >> 4) & 0x0f; + uint8_t scsi_id = zip_drives[c].scsi_device_id & 0x0f; if (!zip_drives[c].priv) { - zip_drives[c].priv = (zip_t *) malloc(sizeof(zip_t)); - memset(zip_drives[c].priv, 0, sizeof(zip_t)); + zip_drives[c].priv = (zip_t *) malloc(sizeof(zip_t)); + memset(zip_drives[c].priv, 0, sizeof(zip_t)); } dev = (zip_t *) zip_drives[c].priv; - dev->id = c; + dev->id = c; dev->cur_lun = SCSI_LUN_USE_CDB; if (zip_drives[c].bus_type == ZIP_BUS_SCSI) { - /* SCSI ZIP, attach to the SCSI bus. */ - sd = &scsi_devices[scsi_bus][scsi_id]; + if (!dev->tf) + dev->tf = (ide_tf_t *) calloc(1, sizeof(ide_tf_t)); - sd->sc = (scsi_common_t *) dev; - sd->command = zip_command; - sd->request_sense = zip_request_sense_for_scsi; - sd->reset = zip_reset; - sd->phase_data_out = zip_phase_data_out; - sd->command_stop = zip_command_stop; - sd->type = SCSI_REMOVABLE_DISK; + /* SCSI ZIP, attach to the SCSI bus. */ + sd = &scsi_devices[scsi_bus][scsi_id]; + + sd->sc = (scsi_common_t *) dev; + sd->command = zip_command; + sd->request_sense = zip_request_sense_for_scsi; + sd->reset = zip_reset; + sd->phase_data_out = zip_phase_data_out; + sd->command_stop = zip_command_stop; + sd->type = SCSI_REMOVABLE_DISK; } else if (zip_drives[c].bus_type == ZIP_BUS_ATAPI) { - /* ATAPI CD-ROM, attach to the IDE bus. */ - id = ide_get_drive(zip_drives[c].ide_channel); - /* If the IDE channel is initialized, we attach to it, - otherwise, we do nothing - it's going to be a drive - that's not attached to anything. */ - if (id) { - id->sc = (scsi_common_t *) dev; - id->get_max = zip_get_max; - id->get_timings = zip_get_timings; - id->identify = zip_identify; - id->stop = NULL; - id->packet_command = zip_command; - id->device_reset = zip_reset; - id->phase_data_out = zip_phase_data_out; - id->command_stop = zip_command_stop; - id->bus_master_error = zip_bus_master_error; - id->interrupt_drq = 1; + /* ATAPI CD-ROM, attach to the IDE bus. */ + id = ide_get_drive(zip_drives[c].ide_channel); + /* If the IDE channel is initialized, we attach to it, + otherwise, we do nothing - it's going to be a drive + that's not attached to anything. */ + if (id) { + id->sc = (scsi_common_t *) dev; + dev->tf = id->tf; + IDE_ATAPI_IS_EARLY = 0; + id->get_max = zip_get_max; + id->get_timings = zip_get_timings; + id->identify = zip_identify; + id->stop = NULL; + id->packet_command = zip_command; + id->device_reset = zip_reset; + id->phase_data_out = zip_phase_data_out; + id->command_stop = zip_command_stop; + id->bus_master_error = zip_bus_master_error; + id->interrupt_drq = 1; - ide_atapi_attach(id); - } + ide_atapi_attach(id); + } } } - void zip_hard_reset(void) { - zip_t *dev; - int c; - uint8_t scsi_id, scsi_bus; + zip_t *dev; + uint8_t scsi_id; + uint8_t scsi_bus; - for (c = 0; c < ZIP_NUM; c++) { - if ((zip_drives[c].bus_type == ZIP_BUS_ATAPI) || (zip_drives[c].bus_type == ZIP_BUS_SCSI)) { - zip_log("ZIP hard_reset drive=%d\n", c); + for (uint8_t c = 0; c < ZIP_NUM; c++) { + if ((zip_drives[c].bus_type == ZIP_BUS_ATAPI) || (zip_drives[c].bus_type == ZIP_BUS_SCSI)) { + zip_log("ZIP hard_reset drive=%d\n", c); - if (zip_drives[c].bus_type == ZIP_BUS_SCSI) { - scsi_bus = (zip_drives[c].scsi_device_id >> 4) & 0x0f; - scsi_id = zip_drives[c].scsi_device_id & 0x0f; + if (zip_drives[c].bus_type == ZIP_BUS_SCSI) { + scsi_bus = (zip_drives[c].scsi_device_id >> 4) & 0x0f; + scsi_id = zip_drives[c].scsi_device_id & 0x0f; - /* Make sure to ignore any SCSI ZIP drive that has an out of range SCSI bus. */ - if (scsi_bus >= SCSI_BUS_MAX) - continue; + /* Make sure to ignore any SCSI ZIP drive that has an out of range SCSI bus. */ + if (scsi_bus >= SCSI_BUS_MAX) + continue; - /* Make sure to ignore any SCSI ZIP drive that has an out of range ID. */ - if (scsi_id >= SCSI_ID_MAX) - continue; - } + /* Make sure to ignore any SCSI ZIP drive that has an out of range ID. */ + if (scsi_id >= SCSI_ID_MAX) + continue; + } - /* Make sure to ignore any ATAPI ZIP drive that has an out of range IDE channel. */ - if ((zip_drives[c].bus_type == ZIP_BUS_ATAPI) && (zip_drives[c].ide_channel > 7)) - continue; + /* Make sure to ignore any ATAPI ZIP drive that has an out of range IDE channel. */ + if ((zip_drives[c].bus_type == ZIP_BUS_ATAPI) && (zip_drives[c].ide_channel > 7)) + continue; - zip_drive_reset(c); + zip_drive_reset(c); - dev = (zip_t *) zip_drives[c].priv; + dev = (zip_t *) zip_drives[c].priv; - dev->id = c; - dev->drv = &zip_drives[c]; + dev->id = c; + dev->drv = &zip_drives[c]; - zip_init(dev); + zip_init(dev); - if (strlen(zip_drives[c].image_path)) - zip_load(dev, zip_drives[c].image_path); + if (strlen(zip_drives[c].image_path)) + zip_load(dev, zip_drives[c].image_path); - zip_mode_sense_load(dev); + zip_mode_sense_load(dev); - if (zip_drives[c].bus_type == ZIP_BUS_SCSI) - zip_log("SCSI ZIP drive %i attached to SCSI ID %i\n", c, zip_drives[c].scsi_device_id); - else if (zip_drives[c].bus_type == ZIP_BUS_ATAPI) - zip_log("ATAPI ZIP drive %i attached to IDE channel %i\n", c, zip_drives[c].ide_channel); - } + if (zip_drives[c].bus_type == ZIP_BUS_SCSI) + zip_log("SCSI ZIP drive %i attached to SCSI ID %i\n", c, zip_drives[c].scsi_device_id); + else if (zip_drives[c].bus_type == ZIP_BUS_ATAPI) + zip_log("ATAPI ZIP drive %i attached to IDE channel %i\n", c, zip_drives[c].ide_channel); + } } } - void zip_close(void) { - zip_t *dev; - int c; - uint8_t scsi_bus, scsi_id; + zip_t *dev; + uint8_t scsi_bus; + uint8_t scsi_id; - for (c = 0; c < ZIP_NUM; c++) { - if (zip_drives[c].bus_type == ZIP_BUS_SCSI) { - scsi_bus = (zip_drives[c].scsi_device_id >> 4) & 0x0f; - scsi_id = zip_drives[c].scsi_device_id & 0x0f; + for (uint8_t c = 0; c < ZIP_NUM; c++) { + if (zip_drives[c].bus_type == ZIP_BUS_SCSI) { + scsi_bus = (zip_drives[c].scsi_device_id >> 4) & 0x0f; + scsi_id = zip_drives[c].scsi_device_id & 0x0f; - memset(&scsi_devices[scsi_bus][scsi_id], 0x00, sizeof(scsi_device_t)); - } + memset(&scsi_devices[scsi_bus][scsi_id], 0x00, sizeof(scsi_device_t)); + } - dev = (zip_t *) zip_drives[c].priv; + dev = (zip_t *) zip_drives[c].priv; - if (dev) { - zip_disk_unload(dev); + if (dev) { + zip_disk_unload(dev); - free(dev); - zip_drives[c].priv = NULL; - } + if (dev->tf) + free(dev->tf); + + free(dev); + zip_drives[c].priv = NULL; + } } } diff --git a/src/dma.c b/src/dma.c index 26fe1a6bf..55cf31236 100644 --- a/src/dma.c +++ b/src/dma.c @@ -1,22 +1,22 @@ /* - * 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. + * 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. + * This file is part of the 86Box distribution. * - * Implementation of the Intel DMA controllers. + * Implementation of the Intel DMA controllers. * * * - * Authors: Sarah Walker, - * Miran Grca, - * Fred N. van Kempen, + * Authors: Sarah Walker, + * Miran Grca, + * Fred N. van Kempen, * - * Copyright 2008-2020 Sarah Walker. - * Copyright 2016-2020 Miran Grca. - * Copyright 2017-2020 Fred N. van Kempen. + * Copyright 2008-2020 Sarah Walker. + * Copyright 2016-2020 Miran Grca. + * Copyright 2017-2020 Fred N. van Kempen. */ #include #include @@ -31,164 +31,151 @@ #include <86box/io.h> #include <86box/pic.h> #include <86box/dma.h> +#include <86box/plat_unused.h> +dma_t dma[8]; +uint8_t dma_e; +uint8_t dma_m; -dma_t dma[8]; -uint8_t dma_e; - - -static uint8_t dmaregs[3][16]; -static int dma_wp[2]; -static uint8_t dma_m; -static uint8_t dma_stat; -static uint8_t dma_stat_rq; -static uint8_t dma_stat_rq_pc; -static uint8_t dma_command[2]; -static uint8_t dma_req_is_soft; -static uint8_t dma_advanced; -static uint8_t dma_at; -static uint8_t dma_buffer[65536]; -static uint16_t dma_sg_base; -static uint16_t dma16_buffer[65536]; +static uint8_t dmaregs[3][16]; +static int dma_wp[2]; +static uint8_t dma_stat; +static uint8_t dma_stat_rq; +static uint8_t dma_stat_rq_pc; +static uint8_t dma_command[2]; +static uint8_t dma_req_is_soft; +static uint8_t dma_advanced; +static uint8_t dma_at; +static uint8_t dma_buffer[65536]; +static uint16_t dma_sg_base; +static uint16_t dma16_buffer[65536]; static uint32_t dma_mask; -static struct { - int xfr_command, - xfr_channel; - int byte_ptr; +static struct dma_ps2_t { + int xfr_command; + int xfr_channel; + int byte_ptr; - int is_ps2; + int is_ps2; } dma_ps2; - -#define DMA_PS2_IOA (1 << 0) -#define DMA_PS2_XFER_MEM_TO_IO (1 << 2) -#define DMA_PS2_XFER_IO_TO_MEM (3 << 2) -#define DMA_PS2_XFER_MASK (3 << 2) -#define DMA_PS2_DEC2 (1 << 4) -#define DMA_PS2_SIZE16 (1 << 6) - +#define DMA_PS2_IOA (1 << 0) +#define DMA_PS2_AUTOINIT (1 << 1) +#define DMA_PS2_XFER_MEM_TO_IO (1 << 2) +#define DMA_PS2_XFER_IO_TO_MEM (3 << 2) +#define DMA_PS2_XFER_MASK (3 << 2) +#define DMA_PS2_DEC2 (1 << 4) +#define DMA_PS2_SIZE16 (1 << 6) #ifdef ENABLE_DMA_LOG int dma_do_log = ENABLE_DMA_LOG; - static void dma_log(const char *fmt, ...) { va_list ap; if (dma_do_log) { - va_start(ap, fmt); - pclog_ex(fmt, ap); - va_end(ap); + va_start(ap, fmt); + pclog_ex(fmt, ap); + va_end(ap); } } #else -#define dma_log(fmt, ...) +# define dma_log(fmt, ...) #endif - static void dma_ps2_run(int channel); - int dma_get_drq(int channel) { return !!(dma_stat_rq_pc & (1 << channel)); } - void dma_set_drq(int channel, int set) { dma_stat_rq_pc &= ~(1 << channel); if (set) - dma_stat_rq_pc |= (1 << channel); + dma_stat_rq_pc |= (1 << channel); } - static int dma_transfer_size(dma_t *dev) { return dev->transfer_mode & 0xff; } - static void dma_sg_next_addr(dma_t *dev) { int ts = dma_transfer_size(dev); - dma_bm_read(dev->ptr_cur, (uint8_t *)&(dev->addr), 4, ts); - dma_bm_read(dev->ptr_cur + 4, (uint8_t *)&(dev->count), 4, ts); + dma_bm_read(dev->ptr_cur, (uint8_t *) &(dev->addr), 4, ts); + dma_bm_read(dev->ptr_cur + 4, (uint8_t *) &(dev->count), 4, ts); dma_log("DMA S/G DWORDs: %08X %08X\n", dev->addr, dev->count); dev->eot = dev->count >> 31; dev->count &= 0xfffe; dev->cb = (uint16_t) dev->count; - dev->cc = (int) dev->count; + dev->cc = dev->count; if (!dev->count) - dev->count = 65536; + dev->count = 65536; if (ts == 2) - dev->addr &= 0xfffffffe; - dev->ab = dev->addr & dma_mask; - dev->ac = dev->addr & dma_mask; + dev->addr &= 0xfffffffe; + dev->ab = dev->addr & dma_mask; + dev->ac = dev->addr & dma_mask; dev->page = dev->page_l = (dev->ac >> 16) & 0xff; - dev->page_h = (dev->ac >> 24) & 0xff; + dev->page_h = (dev->ac >> 24) & 0xff; dev->ptr_cur += 8; } - static void dma_block_transfer(int channel) { - int i, bit16; - - bit16 = (channel >= 4); + int bit16 = (channel >= 4); if (dma_advanced) - bit16 = !!(dma_transfer_size(&(dma[channel])) == 2); + bit16 = !!(dma_transfer_size(&(dma[channel])) == 2); dma_req_is_soft = 1; - for (i = 0; i <= dma[channel].cb; i++) { - if ((dma[channel].mode & 0x8c) == 0x84) { - if (bit16) - dma_channel_write(channel, dma16_buffer[i]); - else - dma_channel_write(channel, dma_buffer[i]); - } else if ((dma[channel].mode & 0x8c) == 0x88) { - if (bit16) - dma16_buffer[i] = dma_channel_read(channel); - else - dma_buffer[i] = dma_channel_read(channel); - } + for (uint16_t i = 0; i <= dma[channel].cb; i++) { + if ((dma[channel].mode & 0x8c) == 0x84) { + if (bit16) + dma_channel_write(channel, dma16_buffer[i]); + else + dma_channel_write(channel, dma_buffer[i]); + } else if ((dma[channel].mode & 0x8c) == 0x88) { + if (bit16) + dma16_buffer[i] = dma_channel_read(channel); + else + dma_buffer[i] = dma_channel_read(channel); + } } dma_req_is_soft = 0; } - static void dma_mem_to_mem_transfer(void) { int i; if ((dma[0].mode & 0x0c) != 0x08) - fatal("DMA memory to memory transfer: channel 0 mode not read\n"); + fatal("DMA memory to memory transfer: channel 0 mode not read\n"); if ((dma[1].mode & 0x0c) != 0x04) - fatal("DMA memory to memory transfer: channel 1 mode not write\n"); + fatal("DMA memory to memory transfer: channel 1 mode not write\n"); dma_req_is_soft = 1; for (i = 0; i <= dma[0].cb; i++) - dma_buffer[i] = dma_channel_read(0); + dma_buffer[i] = dma_channel_read(0); for (i = 0; i <= dma[1].cb; i++) - dma_channel_write(1, dma_buffer[i]); + dma_channel_write(1, dma_buffer[i]); dma_req_is_soft = 0; } - static void dma_sg_write(uint16_t port, uint8_t val, void *priv) { @@ -199,51 +186,53 @@ dma_sg_write(uint16_t port, uint8_t val, void *priv) port &= 0xff; if (port < 0x20) - port &= 0xf8; + port &= 0xf8; else - port &= 0xe3; + port &= 0xe3; switch (port) { - case 0x00: - dma_log("DMA S/G Cmd : val = %02X, old = %02X\n", val, dev->sg_command); - if ((val & 1) && !(dev->sg_command & 1)) { /*Start*/ + case 0x00: + dma_log("DMA S/G Cmd : val = %02X, old = %02X\n", val, dev->sg_command); + if ((val & 1) && !(dev->sg_command & 1)) { /*Start*/ #ifdef ENABLE_DMA_LOG - dma_log("DMA S/G start\n"); + dma_log("DMA S/G start\n"); #endif - dev->ptr_cur = dev->ptr; - dma_sg_next_addr(dev); - dev->sg_status = (dev->sg_status & 0xf7) | 0x01; - } - if (!(val & 1) && (dev->sg_command & 1)) { /*Stop*/ + dev->ptr_cur = dev->ptr; + dma_sg_next_addr(dev); + dev->sg_status = (dev->sg_status & 0xf7) | 0x01; + } + if (!(val & 1) && (dev->sg_command & 1)) { /*Stop*/ #ifdef ENABLE_DMA_LOG - dma_log("DMA S/G stop\n"); + dma_log("DMA S/G stop\n"); #endif - dev->sg_status &= ~0x81; - } + dev->sg_status &= ~0x81; + } - dev->sg_command = val; - break; - case 0x20: - dev->ptr = (dev->ptr & 0xffffff00) | (val & 0xfc); - dev->ptr %= (mem_size * 1024); - dev->ptr0 = val; - break; - case 0x21: - dev->ptr = (dev->ptr & 0xffff00fc) | (val << 8); - dev->ptr %= (mem_size * 1024); - break; - case 0x22: - dev->ptr = (dev->ptr & 0xff00fffc) | (val << 16); - dev->ptr %= (mem_size * 1024); - break; - case 0x23: - dev->ptr = (dev->ptr & 0x00fffffc) | (val << 24); - dev->ptr %= (mem_size * 1024); - break; + dev->sg_command = val; + break; + case 0x20: + dev->ptr = (dev->ptr & 0xffffff00) | (val & 0xfc); + dev->ptr %= (mem_size * 1024); + dev->ptr0 = val; + break; + case 0x21: + dev->ptr = (dev->ptr & 0xffff00fc) | (val << 8); + dev->ptr %= (mem_size * 1024); + break; + case 0x22: + dev->ptr = (dev->ptr & 0xff00fffc) | (val << 16); + dev->ptr %= (mem_size * 1024); + break; + case 0x23: + dev->ptr = (dev->ptr & 0x00fffffc) | (val << 24); + dev->ptr %= (mem_size * 1024); + break; + + default: + break; } } - static void dma_sg_writew(uint16_t port, uint16_t val, void *priv) { @@ -254,27 +243,29 @@ dma_sg_writew(uint16_t port, uint16_t val, void *priv) port &= 0xff; if (port < 0x20) - port &= 0xf8; + port &= 0xf8; else - port &= 0xe3; + port &= 0xe3; switch (port) { - case 0x00: - dma_sg_write(port, val & 0xff, priv); - break; - case 0x20: - dev->ptr = (dev->ptr & 0xffff0000) | (val & 0xfffc); - dev->ptr %= (mem_size * 1024); - dev->ptr0 = val & 0xff; - break; - case 0x22: - dev->ptr = (dev->ptr & 0x0000fffc) | (val << 16); - dev->ptr %= (mem_size * 1024); - break; + case 0x00: + dma_sg_write(port, val & 0xff, priv); + break; + case 0x20: + dev->ptr = (dev->ptr & 0xffff0000) | (val & 0xfffc); + dev->ptr %= (mem_size * 1024); + dev->ptr0 = val & 0xff; + break; + case 0x22: + dev->ptr = (dev->ptr & 0x0000fffc) | (val << 16); + dev->ptr %= (mem_size * 1024); + break; + + default: + break; } } - static void dma_sg_writel(uint16_t port, uint32_t val, void *priv) { @@ -285,61 +276,66 @@ dma_sg_writel(uint16_t port, uint32_t val, void *priv) port &= 0xff; if (port < 0x20) - port &= 0xf8; + port &= 0xf8; else - port &= 0xe3; + port &= 0xe3; switch (port) { - case 0x00: - dma_sg_write(port, val & 0xff, priv); - break; - case 0x20: - dev->ptr = (val & 0xfffffffc); - dev->ptr %= (mem_size * 1024); - dev->ptr0 = val & 0xff; - break; + case 0x00: + dma_sg_write(port, val & 0xff, priv); + break; + case 0x20: + dev->ptr = (val & 0xfffffffc); + dev->ptr %= (mem_size * 1024); + dev->ptr0 = val & 0xff; + break; + + default: + break; } } - static uint8_t dma_sg_read(uint16_t port, void *priv) { - dma_t *dev = (dma_t *) priv; + const dma_t *dev = (dma_t *) priv; uint8_t ret = 0xff; port &= 0xff; if (port < 0x20) - port &= 0xf8; + port &= 0xf8; else - port &= 0xe3; + port &= 0xe3; switch (port) { - case 0x08: - ret = (dev->sg_status & 0x01); - if (dev->eot) - ret |= 0x80; - if ((dev->sg_command & 0xc0) == 0x40) - ret |= 0x20; - if (dev->ab != 0x00000000) - ret |= 0x08; - if (dev->ac != 0x00000000) - ret |= 0x04; - break; - case 0x20: - ret = dev->ptr0; - break; - case 0x21: - ret = dev->ptr >> 8; - break; - case 0x22: - ret = dev->ptr >> 16; - break; - case 0x23: - ret = dev->ptr >> 24; - break; + case 0x08: + ret = (dev->sg_status & 0x01); + if (dev->eot) + ret |= 0x80; + if ((dev->sg_command & 0xc0) == 0x40) + ret |= 0x20; + if (dev->ab != 0x00000000) + ret |= 0x08; + if (dev->ac != 0x00000000) + ret |= 0x04; + break; + case 0x20: + ret = dev->ptr0; + break; + case 0x21: + ret = dev->ptr >> 8; + break; + case 0x22: + ret = dev->ptr >> 16; + break; + case 0x23: + ret = dev->ptr >> 24; + break; + + default: + break; } dma_log("DMA S/G BYTE read : %04X %02X\n", port, ret); @@ -347,31 +343,33 @@ dma_sg_read(uint16_t port, void *priv) return ret; } - static uint16_t dma_sg_readw(uint16_t port, void *priv) { - dma_t *dev = (dma_t *) priv; + const dma_t *dev = (dma_t *) priv; uint16_t ret = 0xffff; port &= 0xff; if (port < 0x20) - port &= 0xf8; + port &= 0xf8; else - port &= 0xe3; + port &= 0xe3; switch (port) { - case 0x08: - ret = (uint16_t) dma_sg_read(port, priv); - break; - case 0x20: - ret = dev->ptr0 | (dev->ptr & 0xff00); - break; - case 0x22: - ret = dev->ptr >> 16; - break; + case 0x08: + ret = (uint16_t) dma_sg_read(port, priv); + break; + case 0x20: + ret = dev->ptr0 | (dev->ptr & 0xff00); + break; + case 0x22: + ret = dev->ptr >> 16; + break; + + default: + break; } dma_log("DMA S/G WORD read : %04X %04X\n", port, ret); @@ -379,28 +377,30 @@ dma_sg_readw(uint16_t port, void *priv) return ret; } - static uint32_t dma_sg_readl(uint16_t port, void *priv) { - dma_t *dev = (dma_t *) priv; + const dma_t *dev = (dma_t *) priv; uint32_t ret = 0xffffffff; port &= 0xff; if (port < 0x20) - port &= 0xf8; + port &= 0xf8; else - port &= 0xe3; + port &= 0xe3; switch (port) { - case 0x08: - ret = (uint32_t) dma_sg_read(port, priv); - break; - case 0x20: - ret = dev->ptr0 | (dev->ptr & 0xffffff00); - break; + case 0x08: + ret = (uint32_t) dma_sg_read(port, priv); + break; + case 0x20: + ret = dev->ptr0 | (dev->ptr & 0xffffff00); + break; + + default: + break; } dma_log("DMA S/G DWORD read : %04X %08X\n", port, ret); @@ -408,634 +408,648 @@ dma_sg_readl(uint16_t port, void *priv) return ret; } - static void -dma_ext_mode_write(uint16_t addr, uint8_t val, void *priv) +dma_ext_mode_write(uint16_t addr, uint8_t val, UNUSED(void *priv)) { int channel = (val & 0x03); if (addr == 0x4d6) - channel |= 4; + channel |= 4; dma[channel].ext_mode = val & 0x7c; switch ((val > 2) & 0x03) { - case 0x00: - dma[channel].transfer_mode = 0x0101; - break; - case 0x01: - dma[channel].transfer_mode = 0x0202; - break; - case 0x02: /* 0x02 is reserved. */ - /* Logic says this should be an undocumented mode that counts by words, - but is 8-bit I/O, thus only transferring every second byte. */ - dma[channel].transfer_mode = 0x0201; - break; - case 0x03: - dma[channel].transfer_mode = 0x0102; - break; + case 0x00: + dma[channel].transfer_mode = 0x0101; + break; + case 0x01: + dma[channel].transfer_mode = 0x0202; + break; + case 0x02: /* 0x02 is reserved. */ + /* Logic says this should be an undocumented mode that counts by words, + but is 8-bit I/O, thus only transferring every second byte. */ + dma[channel].transfer_mode = 0x0201; + break; + case 0x03: + dma[channel].transfer_mode = 0x0102; + break; + + default: + break; } } - static uint8_t -dma_sg_int_status_read(uint16_t addr, void *priv) +dma_sg_int_status_read(UNUSED(uint16_t addr), UNUSED(void *priv)) { - int i; uint8_t ret = 0x00; - for (i = 0; i < 8; i++) { - if (i != 4) - ret = (!!(dma[i].sg_status & 8)) << i; + for (uint8_t i = 0; i < 8; i++) { + if (i != 4) + ret = (!!(dma[i].sg_status & 8)) << i; } return ret; } - static uint8_t -dma_read(uint16_t addr, void *priv) +dma_read(uint16_t addr, UNUSED(void *priv)) { - int channel = (addr >> 1) & 3; + int channel = (addr >> 1) & 3; uint8_t temp; switch (addr & 0xf) { - case 0: - case 2: - case 4: - case 6: /*Address registers*/ - dma_wp[0] ^= 1; - if (dma_wp[0]) - return(dma[channel].ac & 0xff); - return((dma[channel].ac >> 8) & 0xff); + case 0: + case 2: + case 4: + case 6: /*Address registers*/ + dma_wp[0] ^= 1; + if (dma_wp[0]) + return (dma[channel].ac & 0xff); + return ((dma[channel].ac >> 8) & 0xff); - case 1: - case 3: - case 5: - case 7: /*Count registers*/ - dma_wp[0] ^= 1; - if (dma_wp[0]) - temp = dma[channel].cc & 0xff; - else - temp = dma[channel].cc >> 8; - return(temp); + case 1: + case 3: + case 5: + case 7: /*Count registers*/ + dma_wp[0] ^= 1; + if (dma_wp[0]) + temp = dma[channel].cc & 0xff; + else + temp = dma[channel].cc >> 8; + return temp; - case 8: /*Status register*/ - temp = dma_stat_rq_pc & 0xf; - temp <<= 4; - temp |= dma_stat & 0xf; - dma_stat &= ~0xf; - return(temp); + case 8: /*Status register*/ + temp = dma_stat_rq_pc & 0xf; + temp <<= 4; + temp |= dma_stat & 0xf; + dma_stat &= ~0xf; + return temp; - case 0xd: /*Temporary register*/ - return(0); + case 0xd: /*Temporary register*/ + return 0; + + default: + break; } - return(dmaregs[0][addr & 0xf]); + return (dmaregs[0][addr & 0xf]); } - static void -dma_write(uint16_t addr, uint8_t val, void *priv) +dma_write(uint16_t addr, uint8_t val, UNUSED(void *priv)) { int channel = (addr >> 1) & 3; dmaregs[0][addr & 0xf] = val; switch (addr & 0xf) { - case 0: - case 2: - case 4: - case 6: /*Address registers*/ - dma_wp[0] ^= 1; - if (dma_wp[0]) - dma[channel].ab = (dma[channel].ab & 0xffffff00 & dma_mask) | val; - else - dma[channel].ab = (dma[channel].ab & 0xffff00ff & dma_mask) | (val << 8); - dma[channel].ac = dma[channel].ab; - return; + case 0: + case 2: + case 4: + case 6: /*Address registers*/ + dma_wp[0] ^= 1; + if (dma_wp[0]) + dma[channel].ab = (dma[channel].ab & 0xffffff00 & dma_mask) | val; + else + dma[channel].ab = (dma[channel].ab & 0xffff00ff & dma_mask) | (val << 8); + dma[channel].ac = dma[channel].ab; + return; - case 1: - case 3: - case 5: - case 7: /*Count registers*/ - dma_wp[0] ^= 1; - if (dma_wp[0]) - dma[channel].cb = (dma[channel].cb & 0xff00) | val; - else - dma[channel].cb = (dma[channel].cb & 0x00ff) | (val << 8); - dma[channel].cc = dma[channel].cb; - return; + case 1: + case 3: + case 5: + case 7: /*Count registers*/ + dma_wp[0] ^= 1; + if (dma_wp[0]) + dma[channel].cb = (dma[channel].cb & 0xff00) | val; + else + dma[channel].cb = (dma[channel].cb & 0x00ff) | (val << 8); + dma[channel].cc = dma[channel].cb; + return; - case 8: /*Control register*/ - dma_command[0] = val; - if (val & 0x01) - pclog("[%08X:%04X] Memory-to-memory enable\n", CS, cpu_state.pc); - return; + case 8: /*Control register*/ + dma_command[0] = val; + if (val & 0x01) + pclog("[%08X:%04X] Memory-to-memory enable\n", CS, cpu_state.pc); + return; - case 9: /*Request register */ - channel = (val & 3); - if (val & 4) { - dma_stat_rq_pc |= (1 << channel); - if ((channel == 0) && (dma_command[0] & 0x01)) { - pclog("Memory to memory transfer start\n"); - dma_mem_to_mem_transfer(); - } else - dma_block_transfer(channel); - } else - dma_stat_rq_pc &= ~(1 << channel); - break; + case 9: /*Request register */ + channel = (val & 3); + if (val & 4) { + dma_stat_rq_pc |= (1 << channel); + if ((channel == 0) && (dma_command[0] & 0x01)) { + pclog("Memory to memory transfer start\n"); + dma_mem_to_mem_transfer(); + } else + dma_block_transfer(channel); + } else + dma_stat_rq_pc &= ~(1 << channel); + break; - case 0xa: /*Mask*/ - channel = (val & 3); - if (val & 4) - dma_m |= (1 << channel); - else - dma_m &= ~(1 << channel); - return; + case 0xa: /*Mask*/ + channel = (val & 3); + if (val & 4) + dma_m |= (1 << channel); + else + dma_m &= ~(1 << channel); + return; - case 0xb: /*Mode*/ - channel = (val & 3); - dma[channel].mode = val; - if (dma_ps2.is_ps2) { - dma[channel].ps2_mode &= ~0x1c; - if (val & 0x20) - dma[channel].ps2_mode |= 0x10; - if ((val & 0xc) == 8) - dma[channel].ps2_mode |= 4; - else if ((val & 0xc) == 4) - dma[channel].ps2_mode |= 0xc; - } - return; + case 0xb: /*Mode*/ + channel = (val & 3); + dma[channel].mode = val; + if (dma_ps2.is_ps2) { + dma[channel].ps2_mode &= ~0x1c; + if (val & 0x20) + dma[channel].ps2_mode |= 0x10; + if ((val & 0xc) == 8) + dma[channel].ps2_mode |= 4; + else if ((val & 0xc) == 4) + dma[channel].ps2_mode |= 0xc; + } + return; - case 0xc: /*Clear FF*/ - dma_wp[0] = 0; - return; + case 0xc: /*Clear FF*/ + dma_wp[0] = 0; + return; - case 0xd: /*Master clear*/ - dma_wp[0] = 0; - dma_m |= 0xf; - dma_stat_rq_pc &= ~0x0f; - return; + case 0xd: /*Master clear*/ + dma_wp[0] = 0; + dma_m |= 0xf; + dma_stat_rq_pc &= ~0x0f; + return; - case 0xe: /*Clear mask*/ - dma_m &= 0xf0; - return; + case 0xe: /*Clear mask*/ + dma_m &= 0xf0; + return; - case 0xf: /*Mask write*/ - dma_m = (dma_m & 0xf0) | (val & 0xf); - return; + case 0xf: /*Mask write*/ + dma_m = (dma_m & 0xf0) | (val & 0xf); + return; + + default: + break; } } - static uint8_t -dma_ps2_read(uint16_t addr, void *priv) +dma_ps2_read(uint16_t addr, UNUSED(void *priv)) { - dma_t *dma_c = &dma[dma_ps2.xfr_channel]; - uint8_t temp = 0xff; + const dma_t *dma_c = &dma[dma_ps2.xfr_channel]; + uint8_t temp = 0xff; switch (addr) { - case 0x1a: - switch (dma_ps2.xfr_command) { - case 2: /*Address*/ - case 3: - switch (dma_ps2.byte_ptr) { - case 0: - temp = dma_c->ac & 0xff; - dma_ps2.byte_ptr = 1; - break; - case 1: - temp = (dma_c->ac >> 8) & 0xff; - dma_ps2.byte_ptr = 2; - break; - case 2: - temp = (dma_c->ac >> 16) & 0xff; - dma_ps2.byte_ptr = 0; - break; - } - break; + case 0x1a: + switch (dma_ps2.xfr_command) { + case 2: /*Address*/ + case 3: + switch (dma_ps2.byte_ptr) { + case 0: + temp = dma_c->ac & 0xff; + dma_ps2.byte_ptr = 1; + break; + case 1: + temp = (dma_c->ac >> 8) & 0xff; + dma_ps2.byte_ptr = 2; + break; + case 2: + temp = (dma_c->ac >> 16) & 0xff; + dma_ps2.byte_ptr = 0; + break; - case 4: /*Count*/ - case 5: - if (dma_ps2.byte_ptr) - temp = dma_c->cc >> 8; - else - temp = dma_c->cc & 0xff; - dma_ps2.byte_ptr = (dma_ps2.byte_ptr + 1) & 1; - break; + default: + break; + } + break; - case 6: /*Read DMA status*/ - if (dma_ps2.byte_ptr) { - temp = ((dma_stat_rq & 0xf0) >> 4) | (dma_stat & 0xf0); - dma_stat &= ~0xf0; - dma_stat_rq &= ~0xf0; - } else { - temp = (dma_stat_rq & 0xf) | ((dma_stat & 0xf) << 4); - dma_stat &= ~0xf; - dma_stat_rq &= ~0xf; - } - dma_ps2.byte_ptr = (dma_ps2.byte_ptr + 1) & 1; - break; + case 4: /*Count*/ + case 5: + if (dma_ps2.byte_ptr) + temp = dma_c->cc >> 8; + else + temp = dma_c->cc & 0xff; + dma_ps2.byte_ptr = (dma_ps2.byte_ptr + 1) & 1; + break; - case 7: /*Mode*/ - temp = dma_c->ps2_mode; - break; + case 6: /*Read DMA status*/ + if (dma_ps2.byte_ptr) { + temp = ((dma_stat_rq & 0xf0) >> 4) | (dma_stat & 0xf0); + dma_stat &= ~0xf0; + dma_stat_rq &= ~0xf0; + } else { + temp = (dma_stat_rq & 0xf) | ((dma_stat & 0xf) << 4); + dma_stat &= ~0xf; + dma_stat_rq &= ~0xf; + } + dma_ps2.byte_ptr = (dma_ps2.byte_ptr + 1) & 1; + break; - case 8: /*Arbitration Level*/ - temp = dma_c->arb_level; - break; + case 7: /*Mode*/ + temp = dma_c->ps2_mode; + break; - default: - fatal("Bad XFR Read command %i channel %i\n", dma_ps2.xfr_command, dma_ps2.xfr_channel); - } - break; + case 8: /*Arbitration Level*/ + temp = dma_c->arb_level; + break; + + default: + fatal("Bad XFR Read command %i channel %i\n", dma_ps2.xfr_command, dma_ps2.xfr_channel); + } + break; + + default: + break; } - - return(temp); + return temp; } - static void -dma_ps2_write(uint16_t addr, uint8_t val, void *priv) +dma_ps2_write(uint16_t addr, uint8_t val, UNUSED(void *priv)) { - dma_t *dma_c = &dma[dma_ps2.xfr_channel]; + dma_t *dma_c = &dma[dma_ps2.xfr_channel]; uint8_t mode; switch (addr) { - case 0x18: - dma_ps2.xfr_channel = val & 0x7; - dma_ps2.xfr_command = val >> 4; - dma_ps2.byte_ptr = 0; - switch (dma_ps2.xfr_command) { - case 9: /*Set DMA mask*/ - dma_m |= (1 << dma_ps2.xfr_channel); - break; + case 0x18: + dma_ps2.xfr_channel = val & 0x7; + dma_ps2.xfr_command = val >> 4; + dma_ps2.byte_ptr = 0; + switch (dma_ps2.xfr_command) { + case 9: /*Set DMA mask*/ + dma_m |= (1 << dma_ps2.xfr_channel); + break; - case 0xa: /*Reset DMA mask*/ - dma_m &= ~(1 << dma_ps2.xfr_channel); - break; + case 0xa: /*Reset DMA mask*/ + dma_m &= ~(1 << dma_ps2.xfr_channel); + break; - case 0xb: - if (!(dma_m & (1 << dma_ps2.xfr_channel))) - dma_ps2_run(dma_ps2.xfr_channel); - break; - } - break; + case 0xb: + if (!(dma_m & (1 << dma_ps2.xfr_channel))) + dma_ps2_run(dma_ps2.xfr_channel); + break; - case 0x1a: - switch (dma_ps2.xfr_command) { - case 0: /*I/O address*/ - if (dma_ps2.byte_ptr) - dma_c->io_addr = (dma_c->io_addr & 0x00ff) | (val << 8); - else - dma_c->io_addr = (dma_c->io_addr & 0xff00) | val; - dma_ps2.byte_ptr = (dma_ps2.byte_ptr + 1) & 1; - break; + default: + break; + } + break; - case 2: /*Address*/ - switch (dma_ps2.byte_ptr) { - case 0: - dma_c->ac = (dma_c->ac & 0xffff00) | val; - dma_ps2.byte_ptr = 1; - break; + case 0x1a: + switch (dma_ps2.xfr_command) { + case 0: /*I/O address*/ + if (dma_ps2.byte_ptr) + dma_c->io_addr = (dma_c->io_addr & 0x00ff) | (val << 8); + else + dma_c->io_addr = (dma_c->io_addr & 0xff00) | val; + dma_ps2.byte_ptr = (dma_ps2.byte_ptr + 1) & 1; + break; - case 1: - dma_c->ac = (dma_c->ac & 0xff00ff) | (val << 8); - dma_ps2.byte_ptr = 2; - break; + case 2: /*Address*/ + switch (dma_ps2.byte_ptr) { + case 0: + dma_c->ac = (dma_c->ac & 0xffff00) | val; + dma_ps2.byte_ptr = 1; + break; - case 2: - dma_c->ac = (dma_c->ac & 0x00ffff) | (val << 16); - dma_ps2.byte_ptr = 0; - break; - } - dma_c->ab = dma_c->ac; - break; + case 1: + dma_c->ac = (dma_c->ac & 0xff00ff) | (val << 8); + dma_ps2.byte_ptr = 2; + break; - case 4: /*Count*/ - if (dma_ps2.byte_ptr) - dma_c->cc = (dma_c->cc & 0xff) | (val << 8); - else - dma_c->cc = (dma_c->cc & 0xff00) | val; - dma_ps2.byte_ptr = (dma_ps2.byte_ptr + 1) & 1; - dma_c->cb = dma_c->cc; - break; + case 2: + dma_c->ac = (dma_c->ac & 0x00ffff) | (val << 16); + dma_ps2.byte_ptr = 0; + break; - case 7: /*Mode register*/ - mode = 0; - if (val & DMA_PS2_DEC2) - mode |= 0x20; - if ((val & DMA_PS2_XFER_MASK) == DMA_PS2_XFER_MEM_TO_IO) - mode |= 8; - else if ((val & DMA_PS2_XFER_MASK) == DMA_PS2_XFER_IO_TO_MEM) - mode |= 4; - dma_c->mode = (dma_c->mode & ~0x2c) | mode; - dma_c->ps2_mode = val; - dma_c->size = val & DMA_PS2_SIZE16; - break; + default: + break; + } + dma_c->ab = dma_c->ac; + break; - case 8: /*Arbitration Level*/ - dma_c->arb_level = val; - break; + case 4: /*Count*/ + if (dma_ps2.byte_ptr) + dma_c->cc = (dma_c->cc & 0xff) | (val << 8); + else + dma_c->cc = (dma_c->cc & 0xff00) | val; + dma_ps2.byte_ptr = (dma_ps2.byte_ptr + 1) & 1; + dma_c->cb = dma_c->cc; + break; - default: - fatal("Bad XFR command %i channel %i val %02x\n", dma_ps2.xfr_command, dma_ps2.xfr_channel, val); - } - break; + case 7: /*Mode register*/ + mode = 0; + if (val & DMA_PS2_DEC2) + mode |= 0x20; + if ((val & DMA_PS2_XFER_MASK) == DMA_PS2_XFER_MEM_TO_IO) + mode |= 8; + else if ((val & DMA_PS2_XFER_MASK) == DMA_PS2_XFER_IO_TO_MEM) + mode |= 4; + dma_c->mode = (dma_c->mode & ~0x2c) | mode; + if (val & DMA_PS2_AUTOINIT) + dma_c->mode |= 0x10; + dma_c->ps2_mode = val; + dma_c->size = val & DMA_PS2_SIZE16; + break; + + case 8: /*Arbitration Level*/ + dma_c->arb_level = val; + break; + + default: + fatal("Bad XFR command %i channel %i val %02x\n", dma_ps2.xfr_command, dma_ps2.xfr_channel, val); + } + break; + + default: + break; } } - static uint8_t -dma16_read(uint16_t addr, void *priv) +dma16_read(uint16_t addr, UNUSED(void *priv)) { - int channel = ((addr >> 2) & 3) + 4; + int channel = ((addr >> 2) & 3) + 4; uint8_t temp; addr >>= 1; switch (addr & 0xf) { - case 0: - case 2: - case 4: - case 6: /*Address registers*/ - dma_wp[1] ^= 1; - if (dma_ps2.is_ps2) { - if (dma_wp[1]) - return(dma[channel].ac); - return((dma[channel].ac >> 8) & 0xff); - } - if (dma_wp[1]) - return((dma[channel].ac >> 1) & 0xff); - return((dma[channel].ac >> 9) & 0xff); + case 0: + case 2: + case 4: + case 6: /*Address registers*/ + dma_wp[1] ^= 1; + if (dma_ps2.is_ps2) { + if (dma_wp[1]) + return (dma[channel].ac); + return ((dma[channel].ac >> 8) & 0xff); + } + if (dma_wp[1]) + return ((dma[channel].ac >> 1) & 0xff); + return ((dma[channel].ac >> 9) & 0xff); - case 1: - case 3: - case 5: - case 7: /*Count registers*/ - dma_wp[1] ^= 1; - if (dma_wp[1]) - temp = dma[channel].cc & 0xff; - else - temp = dma[channel].cc >> 8; - return(temp); + case 1: + case 3: + case 5: + case 7: /*Count registers*/ + dma_wp[1] ^= 1; + if (dma_wp[1]) + temp = dma[channel].cc & 0xff; + else + temp = dma[channel].cc >> 8; + return temp; - case 8: /*Status register*/ - temp = (dma_stat_rq_pc & 0xf0); - temp |= dma_stat >> 4; - dma_stat &= ~0xf0; - return(temp); + case 8: /*Status register*/ + temp = (dma_stat_rq_pc & 0xf0); + temp |= dma_stat >> 4; + dma_stat &= ~0xf0; + return temp; + + default: + break; } - return(dmaregs[1][addr & 0xf]); + return (dmaregs[1][addr & 0xf]); } - static void -dma16_write(uint16_t addr, uint8_t val, void *priv) +dma16_write(uint16_t addr, uint8_t val, UNUSED(void *priv)) { int channel = ((addr >> 2) & 3) + 4; addr >>= 1; dmaregs[1][addr & 0xf] = val; switch (addr & 0xf) { - case 0: - case 2: - case 4: - case 6: /*Address registers*/ - dma_wp[1] ^= 1; - if (dma_ps2.is_ps2) { - if (dma_wp[1]) - dma[channel].ab = (dma[channel].ab & 0xffffff00 & dma_mask) | val; - else - dma[channel].ab = (dma[channel].ab & 0xffff00ff & dma_mask) | (val << 8); - } else { - if (dma_wp[1]) - dma[channel].ab = (dma[channel].ab & 0xfffffe00 & dma_mask) | (val << 1); - else - dma[channel].ab = (dma[channel].ab & 0xfffe01ff & dma_mask) | (val << 9); - } - dma[channel].ac = dma[channel].ab; - return; + case 0: + case 2: + case 4: + case 6: /*Address registers*/ + dma_wp[1] ^= 1; + if (dma_ps2.is_ps2) { + if (dma_wp[1]) + dma[channel].ab = (dma[channel].ab & 0xffffff00 & dma_mask) | val; + else + dma[channel].ab = (dma[channel].ab & 0xffff00ff & dma_mask) | (val << 8); + } else { + if (dma_wp[1]) + dma[channel].ab = (dma[channel].ab & 0xfffffe00 & dma_mask) | (val << 1); + else + dma[channel].ab = (dma[channel].ab & 0xfffe01ff & dma_mask) | (val << 9); + } + dma[channel].ac = dma[channel].ab; + return; - case 1: - case 3: - case 5: - case 7: /*Count registers*/ - dma_wp[1] ^= 1; - if (dma_wp[1]) - dma[channel].cb = (dma[channel].cb & 0xff00) | val; - else - dma[channel].cb = (dma[channel].cb & 0x00ff) | (val << 8); - dma[channel].cc = dma[channel].cb; - return; + case 1: + case 3: + case 5: + case 7: /*Count registers*/ + dma_wp[1] ^= 1; + if (dma_wp[1]) + dma[channel].cb = (dma[channel].cb & 0xff00) | val; + else + dma[channel].cb = (dma[channel].cb & 0x00ff) | (val << 8); + dma[channel].cc = dma[channel].cb; + return; - case 8: /*Control register*/ - return; + case 8: /*Control register*/ + return; - case 9: /*Request register */ - channel = (val & 3) + 4; - if (val & 4) { - dma_stat_rq_pc |= (1 << channel); - dma_block_transfer(channel); - } else - dma_stat_rq_pc &= ~(1 << channel); - break; + case 9: /*Request register */ + channel = (val & 3) + 4; + if (val & 4) { + dma_stat_rq_pc |= (1 << channel); + dma_block_transfer(channel); + } else + dma_stat_rq_pc &= ~(1 << channel); + break; - case 0xa: /*Mask*/ - channel = (val & 3); - if (val & 4) - dma_m |= (0x10 << channel); - else - dma_m &= ~(0x10 << channel); - return; + case 0xa: /*Mask*/ + channel = (val & 3); + if (val & 4) + dma_m |= (0x10 << channel); + else + dma_m &= ~(0x10 << channel); + return; - case 0xb: /*Mode*/ - channel = (val & 3) + 4; - dma[channel].mode = val; - if (dma_ps2.is_ps2) { - dma[channel].ps2_mode &= ~0x1c; - if (val & 0x20) - dma[channel].ps2_mode |= 0x10; - if ((val & 0xc) == 8) - dma[channel].ps2_mode |= 4; - else if ((val & 0xc) == 4) - dma[channel].ps2_mode |= 0xc; - } - return; + case 0xb: /*Mode*/ + channel = (val & 3) + 4; + dma[channel].mode = val; + if (dma_ps2.is_ps2) { + dma[channel].ps2_mode &= ~0x1c; + if (val & 0x20) + dma[channel].ps2_mode |= 0x10; + if ((val & 0xc) == 8) + dma[channel].ps2_mode |= 4; + else if ((val & 0xc) == 4) + dma[channel].ps2_mode |= 0xc; + } + return; - case 0xc: /*Clear FF*/ - dma_wp[1] = 0; - return; + case 0xc: /*Clear FF*/ + dma_wp[1] = 0; + return; - case 0xd: /*Master clear*/ - dma_wp[1] = 0; - dma_m |= 0xf0; - dma_stat_rq_pc &= ~0xf0; - return; + case 0xd: /*Master clear*/ + dma_wp[1] = 0; + dma_m |= 0xf0; + dma_stat_rq_pc &= ~0xf0; + return; - case 0xe: /*Clear mask*/ - dma_m &= 0x0f; - return; + case 0xe: /*Clear mask*/ + dma_m &= 0x0f; + return; - case 0xf: /*Mask write*/ - dma_m = (dma_m & 0x0f) | ((val & 0xf) << 4); - return; + case 0xf: /*Mask write*/ + dma_m = (dma_m & 0x0f) | ((val & 0xf) << 4); + return; + + default: + break; } } - -#define CHANNELS { 8, 2, 3, 1, 8, 8, 8, 0 } - +#define CHANNELS \ + { \ + 8, 2, 3, 1, 8, 8, 8, 0 \ + } static void -dma_page_write(uint16_t addr, uint8_t val, void *priv) +dma_page_write(uint16_t addr, uint8_t val, UNUSED(void *priv)) { uint8_t convert[8] = CHANNELS; #ifdef USE_DYNAREC if ((addr == 0x84) && cpu_use_dynarec) - update_tsc(); + update_tsc(); #endif addr &= 0x0f; dmaregs[2][addr] = val; if (addr >= 8) - addr = convert[addr & 0x07] | 4; + addr = convert[addr & 0x07] | 4; else - addr = convert[addr & 0x07]; + addr = convert[addr & 0x07]; if (addr < 8) { - dma[addr].page_l = val; + dma[addr].page_l = val; - if (addr > 4) { - dma[addr].page = val & 0xfe; - dma[addr].ab = (dma[addr].ab & 0xff01ffff & dma_mask) | (dma[addr].page << 16); - dma[addr].ac = (dma[addr].ac & 0xff01ffff & dma_mask) | (dma[addr].page << 16); - } else { - dma[addr].page = (dma_at) ? val : val & 0xf; - dma[addr].ab = (dma[addr].ab & 0xff00ffff & dma_mask) | (dma[addr].page << 16); - dma[addr].ac = (dma[addr].ac & 0xff00ffff & dma_mask) | (dma[addr].page << 16); - } + if (addr > 4) { + dma[addr].page = val & 0xfe; + dma[addr].ab = (dma[addr].ab & 0xff01ffff & dma_mask) | (dma[addr].page << 16); + dma[addr].ac = (dma[addr].ac & 0xff01ffff & dma_mask) | (dma[addr].page << 16); + } else { + dma[addr].page = dma_at ? val : val & 0xf; + dma[addr].ab = (dma[addr].ab & 0xff00ffff & dma_mask) | (dma[addr].page << 16); + dma[addr].ac = (dma[addr].ac & 0xff00ffff & dma_mask) | (dma[addr].page << 16); + } } } - static uint8_t -dma_page_read(uint16_t addr, void *priv) +dma_page_read(uint16_t addr, UNUSED(void *priv)) { uint8_t convert[8] = CHANNELS; - uint8_t ret = 0xff; + uint8_t ret = 0xff; addr &= 0x0f; ret = dmaregs[2][addr]; if (addr >= 8) - addr = convert[addr & 0x07] | 4; + addr = convert[addr & 0x07] | 4; else - addr = convert[addr & 0x07]; + addr = convert[addr & 0x07]; if (addr < 8) - ret = dma[addr].page_l; + ret = dma[addr].page_l; return ret; } - static void -dma_high_page_write(uint16_t addr, uint8_t val, void *priv) +dma_high_page_write(uint16_t addr, uint8_t val, UNUSED(void *priv)) { uint8_t convert[8] = CHANNELS; addr &= 0x0f; if (addr >= 8) - addr = convert[addr & 0x07] | 4; + addr = convert[addr & 0x07] | 4; else - addr = convert[addr & 0x07]; + addr = convert[addr & 0x07]; if (addr < 8) { - dma[addr].page_h = val; + dma[addr].page_h = val; - dma[addr].ab = ((dma[addr].ab & 0xffffff) | (dma[addr].page << 24)) & dma_mask; - dma[addr].ac = ((dma[addr].ac & 0xffffff) | (dma[addr].page << 24)) & dma_mask; + dma[addr].ab = ((dma[addr].ab & 0xffffff) | (dma[addr].page << 24)) & dma_mask; + dma[addr].ac = ((dma[addr].ac & 0xffffff) | (dma[addr].page << 24)) & dma_mask; } } - static uint8_t -dma_high_page_read(uint16_t addr, void *priv) +dma_high_page_read(uint16_t addr, UNUSED(void *priv)) { uint8_t convert[8] = CHANNELS; - uint8_t ret = 0xff; + uint8_t ret = 0xff; addr &= 0x0f; if (addr >= 8) - addr = convert[addr & 0x07] | 4; + addr = convert[addr & 0x07] | 4; else - addr = convert[addr & 0x07]; + addr = convert[addr & 0x07]; if (addr < 8) - ret = dma[addr].page_h; + ret = dma[addr].page_h; return ret; } - void dma_set_params(uint8_t advanced, uint32_t mask) { dma_advanced = advanced; - dma_mask = mask; + dma_mask = mask; } - void dma_set_mask(uint32_t mask) { - int i; - dma_mask = mask; - for (i = 0; i < 8; i++) { - dma[i].ab &= mask; - dma[i].ac &= mask; + for (uint8_t i = 0; i < 8; i++) { + dma[i].ab &= mask; + dma[i].ac &= mask; } } - void dma_set_at(uint8_t at) { dma_at = at; } - void dma_reset(void) { int c; dma_wp[0] = dma_wp[1] = 0; - dma_m = 0; + dma_m = 0; dma_e = 0xff; for (c = 0; c < 16; c++) - dmaregs[0][c] = dmaregs[1][c] = 0; + dmaregs[0][c] = dmaregs[1][c] = 0; for (c = 0; c < 8; c++) { - memset(&(dma[c]), 0x00, sizeof(dma_t)); - dma[c].size = (c & 4) ? 1 : 0; - dma[c].transfer_mode = (c & 4) ? 0x0202 : 0x0101; + memset(&(dma[c]), 0x00, sizeof(dma_t)); + dma[c].size = (c & 4) ? 1 : 0; + dma[c].transfer_mode = (c & 4) ? 0x0202 : 0x0101; } - dma_stat = 0x00; - dma_stat_rq = 0x00; - dma_stat_rq_pc = 0x00; + dma_stat = 0x00; + dma_stat_rq = 0x00; + dma_stat_rq_pc = 0x00; dma_req_is_soft = 0; - dma_advanced = 0; + dma_advanced = 0; memset(dma_buffer, 0x00, sizeof(dma_buffer)); memset(dma16_buffer, 0x00, sizeof(dma16_buffer)); @@ -1048,170 +1062,153 @@ dma_reset(void) dma_at = is286; } - void dma_remove_sg(void) { - int i; - io_removehandler(dma_sg_base + 0x0a, 0x01, - dma_sg_int_status_read, NULL, NULL, - NULL, NULL, NULL, - NULL); + dma_sg_int_status_read, NULL, NULL, + NULL, NULL, NULL, + NULL); - for (i = 0; i < 8; i++) { - io_removehandler(dma_sg_base + 0x10 + i, 0x01, - dma_sg_read, dma_sg_readw, dma_sg_readl, - dma_sg_write, dma_sg_writew, dma_sg_writel, - &dma[i]); - io_removehandler(dma_sg_base + 0x18 + i, 0x01, - dma_sg_read, dma_sg_readw, dma_sg_readl, - dma_sg_write, dma_sg_writew, dma_sg_writel, - &dma[i]); - io_removehandler(dma_sg_base + 0x20 + i, 0x04, - dma_sg_read, dma_sg_readw, dma_sg_readl, - dma_sg_write, dma_sg_writew, dma_sg_writel, - &dma[i]); + for (uint8_t i = 0; i < 8; i++) { + io_removehandler(dma_sg_base + 0x10 + i, 0x01, + dma_sg_read, dma_sg_readw, dma_sg_readl, + dma_sg_write, dma_sg_writew, dma_sg_writel, + &dma[i]); + io_removehandler(dma_sg_base + 0x18 + i, 0x01, + dma_sg_read, dma_sg_readw, dma_sg_readl, + dma_sg_write, dma_sg_writew, dma_sg_writel, + &dma[i]); + io_removehandler(dma_sg_base + 0x20 + i, 0x04, + dma_sg_read, dma_sg_readw, dma_sg_readl, + dma_sg_write, dma_sg_writew, dma_sg_writel, + &dma[i]); } } - void dma_set_sg_base(uint8_t sg_base) { - int i; - dma_sg_base = sg_base << 8; io_sethandler(dma_sg_base + 0x0a, 0x01, - dma_sg_int_status_read, NULL, NULL, - NULL, NULL, NULL, - NULL); + dma_sg_int_status_read, NULL, NULL, + NULL, NULL, NULL, + NULL); - for (i = 0; i < 8; i++) { - io_sethandler(dma_sg_base + 0x10 + i, 0x01, - dma_sg_read, dma_sg_readw, dma_sg_readl, - dma_sg_write, dma_sg_writew, dma_sg_writel, - &dma[i]); - io_sethandler(dma_sg_base + 0x18 + i, 0x01, - dma_sg_read, dma_sg_readw, dma_sg_readl, - dma_sg_write, dma_sg_writew, dma_sg_writel, - &dma[i]); - io_sethandler(dma_sg_base + 0x20 + i, 0x04, - dma_sg_read, dma_sg_readw, dma_sg_readl, - dma_sg_write, dma_sg_writew, dma_sg_writel, - &dma[i]); + for (uint8_t i = 0; i < 8; i++) { + io_sethandler(dma_sg_base + 0x10 + i, 0x01, + dma_sg_read, dma_sg_readw, dma_sg_readl, + dma_sg_write, dma_sg_writew, dma_sg_writel, + &dma[i]); + io_sethandler(dma_sg_base + 0x18 + i, 0x01, + dma_sg_read, dma_sg_readw, dma_sg_readl, + dma_sg_write, dma_sg_writew, dma_sg_writel, + &dma[i]); + io_sethandler(dma_sg_base + 0x20 + i, 0x04, + dma_sg_read, dma_sg_readw, dma_sg_readl, + dma_sg_write, dma_sg_writew, dma_sg_writel, + &dma[i]); } } - void dma_ext_mode_init(void) { io_sethandler(0x040b, 0x01, - NULL,NULL,NULL, dma_ext_mode_write,NULL,NULL, NULL); + NULL, NULL, NULL, dma_ext_mode_write, NULL, NULL, NULL); io_sethandler(0x04d6, 0x01, - NULL,NULL,NULL, dma_ext_mode_write,NULL,NULL, NULL); + NULL, NULL, NULL, dma_ext_mode_write, NULL, NULL, NULL); } - void dma_high_page_init(void) { io_sethandler(0x0480, 8, - dma_high_page_read,NULL,NULL, dma_high_page_write,NULL,NULL, NULL); + dma_high_page_read, NULL, NULL, dma_high_page_write, NULL, NULL, NULL); } - void dma_init(void) { dma_reset(); io_sethandler(0x0000, 16, - dma_read,NULL,NULL, dma_write,NULL,NULL, NULL); + dma_read, NULL, NULL, dma_write, NULL, NULL, NULL); io_sethandler(0x0080, 8, - dma_page_read,NULL,NULL, dma_page_write,NULL,NULL, NULL); + dma_page_read, NULL, NULL, dma_page_write, NULL, NULL, NULL); dma_ps2.is_ps2 = 0; } - void dma16_init(void) { dma_reset(); io_sethandler(0x00C0, 32, - dma16_read,NULL,NULL, dma16_write,NULL,NULL, NULL); + dma16_read, NULL, NULL, dma16_write, NULL, NULL, NULL); io_sethandler(0x0088, 8, - dma_page_read,NULL,NULL, dma_page_write,NULL,NULL, NULL); + dma_page_read, NULL, NULL, dma_page_write, NULL, NULL, NULL); } - void dma_alias_set(void) { io_sethandler(0x0090, 2, - dma_page_read,NULL,NULL, dma_page_write,NULL,NULL, NULL); + dma_page_read, NULL, NULL, dma_page_write, NULL, NULL, NULL); io_sethandler(0x0093, 13, - dma_page_read,NULL,NULL, dma_page_write,NULL,NULL, NULL); + dma_page_read, NULL, NULL, dma_page_write, NULL, NULL, NULL); } - void dma_alias_set_piix(void) { io_sethandler(0x0090, 1, - dma_page_read,NULL,NULL, dma_page_write,NULL,NULL, NULL); + dma_page_read, NULL, NULL, dma_page_write, NULL, NULL, NULL); io_sethandler(0x0094, 3, - dma_page_read,NULL,NULL, dma_page_write,NULL,NULL, NULL); + dma_page_read, NULL, NULL, dma_page_write, NULL, NULL, NULL); io_sethandler(0x0098, 1, - dma_page_read,NULL,NULL, dma_page_write,NULL,NULL, NULL); + dma_page_read, NULL, NULL, dma_page_write, NULL, NULL, NULL); io_sethandler(0x009C, 3, - dma_page_read,NULL,NULL, dma_page_write,NULL,NULL, NULL); + dma_page_read, NULL, NULL, dma_page_write, NULL, NULL, NULL); } - void dma_alias_remove(void) { io_removehandler(0x0090, 2, - dma_page_read,NULL,NULL, dma_page_write,NULL,NULL, NULL); + dma_page_read, NULL, NULL, dma_page_write, NULL, NULL, NULL); io_removehandler(0x0093, 13, - dma_page_read,NULL,NULL, dma_page_write,NULL,NULL, NULL); + dma_page_read, NULL, NULL, dma_page_write, NULL, NULL, NULL); } - void dma_alias_remove_piix(void) { io_removehandler(0x0090, 1, - dma_page_read,NULL,NULL, dma_page_write,NULL,NULL, NULL); + dma_page_read, NULL, NULL, dma_page_write, NULL, NULL, NULL); io_removehandler(0x0094, 3, - dma_page_read,NULL,NULL, dma_page_write,NULL,NULL, NULL); + dma_page_read, NULL, NULL, dma_page_write, NULL, NULL, NULL); io_removehandler(0x0098, 1, - dma_page_read,NULL,NULL, dma_page_write,NULL,NULL, NULL); + dma_page_read, NULL, NULL, dma_page_write, NULL, NULL, NULL); io_removehandler(0x009C, 3, - dma_page_read,NULL,NULL, dma_page_write,NULL,NULL, NULL); + dma_page_read, NULL, NULL, dma_page_write, NULL, NULL, NULL); } - void ps2_dma_init(void) { dma_reset(); io_sethandler(0x0018, 1, - dma_ps2_read,NULL,NULL, dma_ps2_write,NULL,NULL, NULL); + dma_ps2_read, NULL, NULL, dma_ps2_write, NULL, NULL, NULL); io_sethandler(0x001a, 1, - dma_ps2_read,NULL,NULL, dma_ps2_write,NULL,NULL, NULL); + dma_ps2_read, NULL, NULL, dma_ps2_write, NULL, NULL, NULL); dma_ps2.is_ps2 = 1; } - -extern void dma_bm_read(uint32_t PhysAddress, uint8_t *DataRead, uint32_t TotalSize, int TransferSize); -extern void dma_bm_write(uint32_t PhysAddress, const uint8_t *DataWrite, uint32_t TotalSize, int TransferSize); - +extern void dma_bm_read(uint32_t PhysAddress, uint8_t *DataRead, uint32_t TotalSize, int TransferSize); +extern void dma_bm_write(uint32_t PhysAddress, const uint8_t *DataWrite, uint32_t TotalSize, int TransferSize); static int dma_sg(uint8_t *data, int transfer_length, int out, void *priv) @@ -1221,486 +1218,474 @@ dma_sg(uint8_t *data, int transfer_length, int out, void *priv) char *sop; #endif - int force_end = 0, buffer_pos = 0; + int force_end = 0; + int buffer_pos = 0; #ifdef ENABLE_DMA_LOG sop = out ? "Read" : "Writ"; #endif if (!(dev->sg_status & 1)) - return 2; /*S/G disabled*/ + return 2; /*S/G disabled*/ dma_log("DMA S/G %s: %i bytes\n", out ? "write" : "read", transfer_length); while (1) { - if (dev->count <= transfer_length) { - dma_log("%sing %i bytes to %08X\n", sop, dev->count, dev->addr); - if (out) - dma_bm_read(dev->addr, (uint8_t *)(data + buffer_pos), dev->count, 4); - else - dma_bm_write(dev->addr, (uint8_t *)(data + buffer_pos), dev->count, 4); - transfer_length -= dev->count; - buffer_pos += dev->count; - } else { - dma_log("%sing %i bytes to %08X\n", sop, transfer_length, dev->addr); - if (out) - dma_bm_read(dev->addr, (uint8_t *)(data + buffer_pos), transfer_length, 4); - else - dma_bm_write(dev->addr, (uint8_t *)(data + buffer_pos), transfer_length, 4); - /* Increase addr and decrease count so that resumed transfers do not mess up. */ - dev->addr += transfer_length; - dev->count -= transfer_length; - transfer_length = 0; - force_end = 1; - } + if (dev->count <= transfer_length) { + dma_log("%sing %i bytes to %08X\n", sop, dev->count, dev->addr); + if (out) + dma_bm_read(dev->addr, (uint8_t *) (data + buffer_pos), dev->count, 4); + else + dma_bm_write(dev->addr, (uint8_t *) (data + buffer_pos), dev->count, 4); + transfer_length -= dev->count; + buffer_pos += dev->count; + } else { + dma_log("%sing %i bytes to %08X\n", sop, transfer_length, dev->addr); + if (out) + dma_bm_read(dev->addr, (uint8_t *) (data + buffer_pos), transfer_length, 4); + else + dma_bm_write(dev->addr, (uint8_t *) (data + buffer_pos), transfer_length, 4); + /* Increase addr and decrease count so that resumed transfers do not mess up. */ + dev->addr += transfer_length; + dev->count -= transfer_length; + transfer_length = 0; + force_end = 1; + } - if (force_end) { - dma_log("Total transfer length smaller than sum of all blocks, partial block\n"); - return 1; /* This block has exhausted the data to transfer and it was smaller than the count, break. */ - } else { - if (!transfer_length && !dev->eot) { - dma_log("Total transfer length smaller than sum of all blocks, full block\n"); - return 1; /* We have exhausted the data to transfer but there's more blocks left, break. */ - } else if (transfer_length && dev->eot) { - dma_log("Total transfer length greater than sum of all blocks\n"); - return 4; /* There is data left to transfer but we have reached EOT - return with error. */ - } else if (dev->eot) { - dma_log("Regular EOT\n"); - return 5; /* We have regularly reached EOT - clear status and break. */ - } else { - /* We have more to transfer and there are blocks left, get next block. */ - dma_sg_next_addr(dev); - } - } + if (force_end) { + dma_log("Total transfer length smaller than sum of all blocks, partial block\n"); + return 1; /* This block has exhausted the data to transfer and it was smaller than the count, break. */ + } else { + if (!transfer_length && !dev->eot) { + dma_log("Total transfer length smaller than sum of all blocks, full block\n"); + return 1; /* We have exhausted the data to transfer but there's more blocks left, break. */ + } else if (transfer_length && dev->eot) { + dma_log("Total transfer length greater than sum of all blocks\n"); + return 4; /* There is data left to transfer but we have reached EOT - return with error. */ + } else if (dev->eot) { + dma_log("Regular EOT\n"); + return 5; /* We have regularly reached EOT - clear status and break. */ + } else { + /* We have more to transfer and there are blocks left, get next block. */ + dma_sg_next_addr(dev); + } + } } - - return 1; } - uint8_t _dma_read(uint32_t addr, dma_t *dma_c) { - uint8_t temp; + uint8_t temp = 0; if (dma_advanced) { - if (dma_c->sg_status & 1) - dma_c->sg_status = (dma_c->sg_status & 0x0f) | (dma_sg(&temp, 1, 1, dma_c) << 4); - else - dma_bm_read(addr, &temp, 1, dma_transfer_size(dma_c)); + if (dma_c->sg_status & 1) + dma_c->sg_status = (dma_c->sg_status & 0x0f) | (dma_sg(&temp, 1, 1, dma_c) << 4); + else + dma_bm_read(addr, &temp, 1, dma_transfer_size(dma_c)); } else - temp = mem_readb_phys(addr); + temp = mem_readb_phys(addr); - return(temp); + return temp; } - static uint16_t _dma_readw(uint32_t addr, dma_t *dma_c) { - uint16_t temp; + uint16_t temp = 0; if (dma_advanced) { - if (dma_c->sg_status & 1) - dma_c->sg_status = (dma_c->sg_status & 0x0f) | (dma_sg((uint8_t *) &temp, 2, 1, dma_c) << 4); - else - dma_bm_read(addr, (uint8_t *) &temp, 2, dma_transfer_size(dma_c)); + if (dma_c->sg_status & 1) + dma_c->sg_status = (dma_c->sg_status & 0x0f) | (dma_sg((uint8_t *) &temp, 2, 1, dma_c) << 4); + else + dma_bm_read(addr, (uint8_t *) &temp, 2, dma_transfer_size(dma_c)); } else - temp = _dma_read(addr, dma_c) | (_dma_read(addr + 1, dma_c) << 8); + temp = _dma_read(addr, dma_c) | (_dma_read(addr + 1, dma_c) << 8); - return(temp); + return temp; } - static void _dma_write(uint32_t addr, uint8_t val, dma_t *dma_c) { if (dma_advanced) { - if (dma_c->sg_status & 1) - dma_c->sg_status = (dma_c->sg_status & 0x0f) | (dma_sg(&val, 1, 0, dma_c) << 4); - else - dma_bm_write(addr, &val, 1, dma_transfer_size(dma_c)); + if (dma_c->sg_status & 1) + dma_c->sg_status = (dma_c->sg_status & 0x0f) | (dma_sg(&val, 1, 0, dma_c) << 4); + else + dma_bm_write(addr, &val, 1, dma_transfer_size(dma_c)); } else { - mem_writeb_phys(addr, val); - if (dma_at) - mem_invalidate_range(addr, addr); + mem_writeb_phys(addr, val); + if (dma_at) + mem_invalidate_range(addr, addr); } } - static void _dma_writew(uint32_t addr, uint16_t val, dma_t *dma_c) { if (dma_advanced) { - if (dma_c->sg_status & 1) - dma_c->sg_status = (dma_c->sg_status & 0x0f) | (dma_sg((uint8_t *) &val, 2, 0, dma_c) << 4); - else - dma_bm_write(addr, (uint8_t *) &val, 2, dma_transfer_size(dma_c)); + if (dma_c->sg_status & 1) + dma_c->sg_status = (dma_c->sg_status & 0x0f) | (dma_sg((uint8_t *) &val, 2, 0, dma_c) << 4); + else + dma_bm_write(addr, (uint8_t *) &val, 2, dma_transfer_size(dma_c)); } else { - _dma_write(addr, val & 0xff, dma_c); - _dma_write(addr + 1, val >> 8, dma_c); + _dma_write(addr, val & 0xff, dma_c); + _dma_write(addr + 1, val >> 8, dma_c); } } - static void dma_retreat(dma_t *dma_c) { int as = dma_c->transfer_mode >> 8; if (dma->sg_status & 1) { - dma_c->ac = (dma_c->ac - as) & dma_mask; + dma_c->ac = (dma_c->ac - as) & dma_mask; - dma_c->page = dma_c->page_l = (dma_c->ac >> 16) & 0xff; - dma_c->page_h = (dma_c->ac >> 24) & 0xff; + dma_c->page = dma_c->page_l = (dma_c->ac >> 16) & 0xff; + dma_c->page_h = (dma_c->ac >> 24) & 0xff; } else if (as == 2) - dma_c->ac = ((dma_c->ac & 0xfffe0000) & dma_mask) | ((dma_c->ac - as) & 0xffff); + dma_c->ac = ((dma_c->ac & 0xfffe0000) & dma_mask) | ((dma_c->ac - as) & 0xffff); else - dma_c->ac = ((dma_c->ac & 0xffff0000) & dma_mask) | ((dma_c->ac - as) & 0xffff); + dma_c->ac = ((dma_c->ac & 0xffff0000) & dma_mask) | ((dma_c->ac - as) & 0xffff); } - void dma_advance(dma_t *dma_c) { int as = dma_c->transfer_mode >> 8; if (dma->sg_status & 1) { - dma_c->ac = (dma_c->ac + as) & dma_mask; + dma_c->ac = (dma_c->ac + as) & dma_mask; - dma_c->page = dma_c->page_l = (dma_c->ac >> 16) & 0xff; - dma_c->page_h = (dma_c->ac >> 24) & 0xff; + dma_c->page = dma_c->page_l = (dma_c->ac >> 16) & 0xff; + dma_c->page_h = (dma_c->ac >> 24) & 0xff; } else if (as == 2) - dma_c->ac = ((dma_c->ac & 0xfffe0000) & dma_mask) | ((dma_c->ac + as) & 0xffff); + dma_c->ac = ((dma_c->ac & 0xfffe0000) & dma_mask) | ((dma_c->ac + as) & 0xffff); else - dma_c->ac = ((dma_c->ac & 0xffff0000) & dma_mask) | ((dma_c->ac + as) & 0xffff); + dma_c->ac = ((dma_c->ac & 0xffff0000) & dma_mask) | ((dma_c->ac + as) & 0xffff); } - int dma_channel_read(int channel) { - dma_t *dma_c = &dma[channel]; + dma_t *dma_c = &dma[channel]; uint16_t temp; - int tc = 0; + int tc = 0; if (channel < 4) { - if (dma_command[0] & 0x04) - return(DMA_NODATA); + if (dma_command[0] & 0x04) + return (DMA_NODATA); } else { - if (dma_command[1] & 0x04) - return(DMA_NODATA); + if (dma_command[1] & 0x04) + return (DMA_NODATA); } if (!(dma_e & (1 << channel))) - return(DMA_NODATA); + return (DMA_NODATA); if ((dma_m & (1 << channel)) && !dma_req_is_soft) - return(DMA_NODATA); + return (DMA_NODATA); if ((dma_c->mode & 0xC) != 8) - return(DMA_NODATA); + return (DMA_NODATA); if (!dma_at && !channel) - refreshread(); + refreshread(); - if (! dma_c->size) { - temp = _dma_read(dma_c->ac, dma_c); + if (!dma_c->size) { + temp = _dma_read(dma_c->ac, dma_c); - if (dma_c->mode & 0x20) { - if (dma_ps2.is_ps2) - dma_c->ac--; - else if (dma_advanced) - dma_retreat(dma_c); - else - dma_c->ac = (dma_c->ac & 0xffff0000 & dma_mask) | ((dma_c->ac - 1) & 0xffff); - } else { - if (dma_ps2.is_ps2) - dma_c->ac++; - else if (dma_advanced) - dma_advance(dma_c); - else - dma_c->ac = (dma_c->ac & 0xffff0000 & dma_mask) | ((dma_c->ac + 1) & 0xffff); - } + if (dma_c->mode & 0x20) { + if (dma_ps2.is_ps2) + dma_c->ac--; + else if (dma_advanced) + dma_retreat(dma_c); + else + dma_c->ac = (dma_c->ac & 0xffff0000 & dma_mask) | ((dma_c->ac - 1) & 0xffff); + } else { + if (dma_ps2.is_ps2) + dma_c->ac++; + else if (dma_advanced) + dma_advance(dma_c); + else + dma_c->ac = (dma_c->ac & 0xffff0000 & dma_mask) | ((dma_c->ac + 1) & 0xffff); + } } else { - temp = _dma_readw(dma_c->ac, dma_c); + temp = _dma_readw(dma_c->ac, dma_c); - if (dma_c->mode & 0x20) { - if (dma_ps2.is_ps2) - dma_c->ac -= 2; - else if (dma_advanced) - dma_retreat(dma_c); - else - dma_c->ac = (dma_c->ac & 0xfffe0000 & dma_mask) | ((dma_c->ac - 2) & 0x1ffff); - } else { - if (dma_ps2.is_ps2) - dma_c->ac += 2; - else if (dma_advanced) - dma_advance(dma_c); - else - dma_c->ac = (dma_c->ac & 0xfffe0000 & dma_mask) | ((dma_c->ac + 2) & 0x1ffff); - } + if (dma_c->mode & 0x20) { + if (dma_ps2.is_ps2) + dma_c->ac -= 2; + else if (dma_advanced) + dma_retreat(dma_c); + else + dma_c->ac = (dma_c->ac & 0xfffe0000 & dma_mask) | ((dma_c->ac - 2) & 0x1ffff); + } else { + if (dma_ps2.is_ps2) + dma_c->ac += 2; + else if (dma_advanced) + dma_advance(dma_c); + else + dma_c->ac = (dma_c->ac & 0xfffe0000 & dma_mask) | ((dma_c->ac + 2) & 0x1ffff); + } } dma_stat_rq |= (1 << channel); dma_c->cc--; if (dma_c->cc < 0) { - if (dma_advanced && (dma_c->sg_status & 1) && !(dma_c->sg_status & 6)) - dma_sg_next_addr(dma_c); - else { - tc = 1; - if (dma_c->mode & 0x10) { /*Auto-init*/ - dma_c->cc = dma_c->cb; - dma_c->ac = dma_c->ab; - } else - dma_m |= (1 << channel); - dma_stat |= (1 << channel); - } + if (dma_advanced && (dma_c->sg_status & 1) && !(dma_c->sg_status & 6)) + dma_sg_next_addr(dma_c); + else { + tc = 1; + if (dma_c->mode & 0x10) { /*Auto-init*/ + dma_c->cc = dma_c->cb; + dma_c->ac = dma_c->ab; + } else + dma_m |= (1 << channel); + dma_stat |= (1 << channel); + } } if (tc) { - if (dma_advanced && (dma_c->sg_status & 1) && ((dma_c->sg_command & 0xc0) == 0x40)) { - picint(1 << 13); - dma_c->sg_status |= 8; - } + if (dma_advanced && (dma_c->sg_status & 1) && ((dma_c->sg_command & 0xc0) == 0x40)) { + picint(1 << 13); + dma_c->sg_status |= 8; + } - return(temp | DMA_OVER); + return (temp | DMA_OVER); } - return(temp); + return temp; } - int dma_channel_write(int channel, uint16_t val) { dma_t *dma_c = &dma[channel]; if (channel < 4) { - if (dma_command[0] & 0x04) - return(DMA_NODATA); + if (dma_command[0] & 0x04) + return (DMA_NODATA); } else { - if (dma_command[1] & 0x04) - return(DMA_NODATA); + if (dma_command[1] & 0x04) + return (DMA_NODATA); } if (!(dma_e & (1 << channel))) - return(DMA_NODATA); + return (DMA_NODATA); if ((dma_m & (1 << channel)) && !dma_req_is_soft) - return(DMA_NODATA); + return (DMA_NODATA); if ((dma_c->mode & 0xC) != 4) - return(DMA_NODATA); + return (DMA_NODATA); - if (! dma_c->size) { - _dma_write(dma_c->ac, val & 0xff, dma_c); + if (!dma_c->size) { + _dma_write(dma_c->ac, val & 0xff, dma_c); - if (dma_c->mode & 0x20) { - if (dma_ps2.is_ps2) - dma_c->ac--; - else if (dma_advanced) - dma_retreat(dma_c); - else - dma_c->ac = (dma_c->ac & 0xffff0000 & dma_mask) | ((dma_c->ac - 1) & 0xffff); - } else { - if (dma_ps2.is_ps2) - dma_c->ac++; - else if (dma_advanced) - dma_advance(dma_c); - else - dma_c->ac = (dma_c->ac & 0xffff0000 & dma_mask) | ((dma_c->ac + 1) & 0xffff); - } + if (dma_c->mode & 0x20) { + if (dma_ps2.is_ps2) + dma_c->ac--; + else if (dma_advanced) + dma_retreat(dma_c); + else + dma_c->ac = (dma_c->ac & 0xffff0000 & dma_mask) | ((dma_c->ac - 1) & 0xffff); + } else { + if (dma_ps2.is_ps2) + dma_c->ac++; + else if (dma_advanced) + dma_advance(dma_c); + else + dma_c->ac = (dma_c->ac & 0xffff0000 & dma_mask) | ((dma_c->ac + 1) & 0xffff); + } } else { - _dma_writew(dma_c->ac, val, dma_c); + _dma_writew(dma_c->ac, val, dma_c); - if (dma_c->mode & 0x20) { - if (dma_ps2.is_ps2) - dma_c->ac -= 2; - else if (dma_advanced) - dma_retreat(dma_c); - else - dma_c->ac = (dma_c->ac & 0xfffe0000 & dma_mask) | ((dma_c->ac - 2) & 0x1ffff); - dma_c->ac = (dma_c->ac & 0xfffe0000 & dma_mask) | ((dma_c->ac - 2) & 0x1ffff); - } else { - if (dma_ps2.is_ps2) - dma_c->ac += 2; - else if (dma_advanced) - dma_advance(dma_c); - else - dma_c->ac = (dma_c->ac & 0xfffe0000 & dma_mask) | ((dma_c->ac + 2) & 0x1ffff); - } + if (dma_c->mode & 0x20) { + if (dma_ps2.is_ps2) + dma_c->ac -= 2; + else if (dma_advanced) + dma_retreat(dma_c); + else + dma_c->ac = (dma_c->ac & 0xfffe0000 & dma_mask) | ((dma_c->ac - 2) & 0x1ffff); + dma_c->ac = (dma_c->ac & 0xfffe0000 & dma_mask) | ((dma_c->ac - 2) & 0x1ffff); + } else { + if (dma_ps2.is_ps2) + dma_c->ac += 2; + else if (dma_advanced) + dma_advance(dma_c); + else + dma_c->ac = (dma_c->ac & 0xfffe0000 & dma_mask) | ((dma_c->ac + 2) & 0x1ffff); + } } dma_stat_rq |= (1 << channel); dma_c->cc--; if (dma_c->cc < 0) { - if (dma_advanced && (dma_c->sg_status & 1) && !(dma_c->sg_status & 6)) - dma_sg_next_addr(dma_c); - else { - if (dma_c->mode & 0x10) { /*Auto-init*/ - dma_c->cc = dma_c->cb; - dma_c->ac = dma_c->ab; - } else - dma_m |= (1 << channel); - dma_stat |= (1 << channel); - } + if (dma_advanced && (dma_c->sg_status & 1) && !(dma_c->sg_status & 6)) + dma_sg_next_addr(dma_c); + else { + if (dma_c->mode & 0x10) { /*Auto-init*/ + dma_c->cc = dma_c->cb; + dma_c->ac = dma_c->ab; + } else + dma_m |= (1 << channel); + dma_stat |= (1 << channel); + } } if (dma_m & (1 << channel)) { - if (dma_advanced && (dma_c->sg_status & 1) && ((dma_c->sg_command & 0xc0) == 0x40)) { - picint(1 << 13); - dma_c->sg_status |= 8; - } + if (dma_advanced && (dma_c->sg_status & 1) && ((dma_c->sg_command & 0xc0) == 0x40)) { + picint(1 << 13); + dma_c->sg_status |= 8; + } - return(DMA_OVER); + return DMA_OVER; } - return(0); + return 0; } - static void dma_ps2_run(int channel) { dma_t *dma_c = &dma[channel]; switch (dma_c->ps2_mode & DMA_PS2_XFER_MASK) { - case DMA_PS2_XFER_MEM_TO_IO: - do { - if (! dma_c->size) { - uint8_t temp = _dma_read(dma_c->ac, dma_c); + case DMA_PS2_XFER_MEM_TO_IO: + do { + if (!dma_c->size) { + uint8_t temp = _dma_read(dma_c->ac, dma_c); - outb(dma_c->io_addr, temp); + outb(dma_c->io_addr, temp); - if (dma_c->ps2_mode & DMA_PS2_DEC2) - dma_c->ac--; - else - dma_c->ac++; - } else { - uint16_t temp = _dma_readw(dma_c->ac, dma_c); + if (dma_c->ps2_mode & DMA_PS2_DEC2) + dma_c->ac--; + else + dma_c->ac++; + } else { + uint16_t temp = _dma_readw(dma_c->ac, dma_c); - outw(dma_c->io_addr, temp); + outw(dma_c->io_addr, temp); - if (dma_c->ps2_mode & DMA_PS2_DEC2) - dma_c->ac -= 2; - else - dma_c->ac += 2; - } + if (dma_c->ps2_mode & DMA_PS2_DEC2) + dma_c->ac -= 2; + else + dma_c->ac += 2; + } - dma_stat_rq |= (1 << channel); - dma_c->cc--; - } while (dma_c->cc > 0); + dma_stat_rq |= (1 << channel); + dma_c->cc--; + } while (dma_c->cc > 0); - dma_stat |= (1 << channel); - break; + dma_stat |= (1 << channel); + break; - case DMA_PS2_XFER_IO_TO_MEM: - do { - if (! dma_c->size) { - uint8_t temp = inb(dma_c->io_addr); + case DMA_PS2_XFER_IO_TO_MEM: + do { + if (!dma_c->size) { + uint8_t temp = inb(dma_c->io_addr); - _dma_write(dma_c->ac, temp, dma_c); + _dma_write(dma_c->ac, temp, dma_c); - if (dma_c->ps2_mode & DMA_PS2_DEC2) - dma_c->ac--; - else - dma_c->ac++; - } else { - uint16_t temp = inw(dma_c->io_addr); + if (dma_c->ps2_mode & DMA_PS2_DEC2) + dma_c->ac--; + else + dma_c->ac++; + } else { + uint16_t temp = inw(dma_c->io_addr); - _dma_writew(dma_c->ac, temp, dma_c); + _dma_writew(dma_c->ac, temp, dma_c); - if (dma_c->ps2_mode & DMA_PS2_DEC2) - dma_c->ac -= 2; - else - dma_c->ac += 2; - } + if (dma_c->ps2_mode & DMA_PS2_DEC2) + dma_c->ac -= 2; + else + dma_c->ac += 2; + } - dma_stat_rq |= (1 << channel); - dma_c->cc--; - } while (dma_c->cc > 0); + dma_stat_rq |= (1 << channel); + dma_c->cc--; + } while (dma_c->cc > 0); - ps2_cache_clean(); - dma_stat |= (1 << channel); - break; + ps2_cache_clean(); + dma_stat |= (1 << channel); + break; - default: /*Memory verify*/ - do { - if (! dma_c->size) { - if (dma_c->ps2_mode & DMA_PS2_DEC2) - dma_c->ac--; - else - dma_c->ac++; - } else { - if (dma_c->ps2_mode & DMA_PS2_DEC2) - dma_c->ac -= 2; - else - dma_c->ac += 2; - } + default: /*Memory verify*/ + do { + if (!dma_c->size) { + if (dma_c->ps2_mode & DMA_PS2_DEC2) + dma_c->ac--; + else + dma_c->ac++; + } else { + if (dma_c->ps2_mode & DMA_PS2_DEC2) + dma_c->ac -= 2; + else + dma_c->ac += 2; + } - dma_stat_rq |= (1 << channel); - dma->cc--; - } while (dma->cc > 0); - - dma_stat |= (1 << channel); - break; + dma_stat_rq |= (1 << channel); + dma->cc--; + } while (dma->cc > 0); + dma_stat |= (1 << channel); + break; } } - int dma_mode(int channel) { - return(dma[channel].mode); + return (dma[channel].mode); } - /* DMA Bus Master Page Read/Write */ void dma_bm_read(uint32_t PhysAddress, uint8_t *DataRead, uint32_t TotalSize, int TransferSize) { - uint32_t i = 0, n, n2; - uint8_t bytes[4] = { 0, 0, 0, 0 }; + uint32_t n; + uint32_t n2; + uint8_t bytes[4] = { 0, 0, 0, 0 }; - n = TotalSize & ~(TransferSize - 1); + n = TotalSize & ~(TransferSize - 1); n2 = TotalSize - n; /* Do the divisible block, if there is one. */ if (n) { - for (i = 0; i < n; i += TransferSize) - mem_read_phys((void *) &(DataRead[i]), PhysAddress + i, TransferSize); + for (uint32_t i = 0; i < n; i += TransferSize) + mem_read_phys((void *) &(DataRead[i]), PhysAddress + i, TransferSize); } /* Do the non-divisible block, if there is one. */ if (n2) { - mem_read_phys((void *) bytes, PhysAddress + n, TransferSize); - memcpy((void *) &(DataRead[n]), bytes, n2); + mem_read_phys((void *) bytes, PhysAddress + n, TransferSize); + memcpy((void *) &(DataRead[n]), bytes, n2); } } - void dma_bm_write(uint32_t PhysAddress, const uint8_t *DataWrite, uint32_t TotalSize, int TransferSize) { - uint32_t i = 0, n, n2; - uint8_t bytes[4] = { 0, 0, 0, 0 }; + uint32_t n; + uint32_t n2; + uint8_t bytes[4] = { 0, 0, 0, 0 }; - n = TotalSize & ~(TransferSize - 1); + n = TotalSize & ~(TransferSize - 1); n2 = TotalSize - n; /* Do the divisible block, if there is one. */ if (n) { - for (i = 0; i < n; i += TransferSize) - mem_write_phys((void *) &(DataWrite[i]), PhysAddress + i, TransferSize); + for (uint32_t i = 0; i < n; i += TransferSize) + mem_write_phys((void *) &(DataWrite[i]), PhysAddress + i, TransferSize); } /* Do the non-divisible block, if there is one. */ if (n2) { - mem_read_phys((void *) bytes, PhysAddress + n, TransferSize); - memcpy(bytes, (void *) &(DataWrite[n]), n2); - mem_write_phys((void *) bytes, PhysAddress + n, TransferSize); + mem_read_phys((void *) bytes, PhysAddress + n, TransferSize); + memcpy(bytes, (void *) &(DataWrite[n]), n2); + mem_write_phys((void *) bytes, PhysAddress + n, TransferSize); } if (dma_at) - mem_invalidate_range(PhysAddress, PhysAddress + TotalSize - 1); + mem_invalidate_range(PhysAddress, PhysAddress + TotalSize - 1); } diff --git a/src/fifo.c b/src/fifo.c new file mode 100644 index 000000000..72084e11b --- /dev/null +++ b/src/fifo.c @@ -0,0 +1,596 @@ +/* + * 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. + * + * FIFO infrastructure. + * + * Authors: Miran Grca, + * + * Copyright 2023 Miran Grca. + */ +#include +#include +#include +#include +#include +#ifdef FIFO_STANDALONE +#define fatal printf +#define pclog_ex printf +#define pclog printf +#include "include/86box/fifo.h" +#else +#define HAVE_STDARG_H +#include <86box/86box.h> +#include <86box/fifo.h> +#endif + +#ifdef ENABLE_FIFO_LOG +int fifo_do_log = ENABLE_FIFO_LOG; + +static void +fifo_log(const char *fmt, ...) +{ + va_list ap; + + if (fifo_do_log) { + va_start(ap, fmt); + pclog_ex(fmt, ap); + va_end(ap); + } +} +#else +# define fifo_log(fmt, ...) +#endif + +int +fifo_get_count(void *priv) +{ + const fifo_t *fifo = (fifo_t *) priv; + int ret = fifo->len; + + if (fifo->end == fifo->start) + ret = fifo->full ? fifo->len : 0; + else + ret = abs(fifo->end - fifo->start); + + return ret; +} + +void +fifo_write(uint8_t val, void *priv) +{ + fifo_t *fifo = (fifo_t *) priv; + + fifo->d_full = fifo->d_empty = 0; + fifo->d_ready = fifo->d_overrun = 0; + + if (fifo->full) + fifo->overrun = 1; + else { + fifo->buf[fifo->end] = val; + fifo->end = (fifo->end + 1) & 0x0f; + + if (fifo->end == fifo->start) + fifo->full = 1; + + fifo->empty = 0; + + if (fifo_get_count(fifo) >= fifo->trigger_len) + fifo->ready = 1; + } +} + +void +fifo_write_evt(uint8_t val, void *priv) +{ + fifo_t *fifo = (fifo_t *) priv; + + fifo->d_full = fifo->d_empty = 0; + fifo->d_ready = fifo->d_overrun = 0; + + if (fifo->full) { + fifo->d_overrun = (fifo->overrun != 1); + fifo->overrun = 1; + if (fifo->d_overrun && (fifo->d_overrun_evt != NULL)) + fifo->d_overrun_evt(fifo->priv); + } else { + fifo->buf[fifo->end] = val; + fifo->end = (fifo->end + 1) & 0x0f; + + if (fifo->end == fifo->start) { + fifo->d_full = (fifo->full != 1); + fifo->full = 1; + if (fifo->d_full && (fifo->d_full_evt != NULL)) + fifo->d_full_evt(fifo->priv); + } + + fifo->d_empty = (fifo->empty != 0); + fifo->empty = 0; + if (fifo->d_empty && (fifo->d_empty_evt != NULL)) + fifo->d_empty_evt(fifo->priv); + + if (fifo_get_count(fifo) >= fifo->trigger_len) { + fifo->d_ready = (fifo->ready != 1); + fifo->ready = 1; + if (fifo->d_ready && (fifo->d_ready_evt != NULL)) + fifo->d_ready_evt(fifo->priv); + } + } +} + +uint8_t +fifo_read(void *priv) +{ + fifo_t *fifo = (fifo_t *) priv; + uint8_t ret = 0x00; + int count; + + if (!fifo->empty) { + ret = fifo->buf[fifo->start]; + fifo->start = (fifo->start + 1) & 0x0f; + + fifo->full = 0; + + count = fifo_get_count(fifo); + + if (count < fifo->trigger_len) { + fifo->ready = 0; + + if (count == 0) + fifo->empty = 1; + } + } + + return ret; +} + +uint8_t +fifo_read_evt(void *priv) +{ + fifo_t *fifo = (fifo_t *) priv; + uint8_t ret = 0x00; + int count; + + fifo->d_full = fifo->d_empty = 0; + fifo->d_ready = 0; + + if (!fifo->empty) { + ret = fifo->buf[fifo->start]; + fifo->start = (fifo->start + 1) & 0x0f; + + fifo->d_full = (fifo->full != 0); + fifo->full = 0; + if (fifo->d_full && (fifo->d_full_evt != NULL)) + fifo->d_full_evt(fifo->priv); + + count = fifo_get_count(fifo); + + if (count < fifo->trigger_len) { + fifo->d_ready = (fifo->ready != 0); + fifo->ready = 0; + if (fifo->d_ready && (fifo->d_ready_evt != NULL)) + fifo->d_ready_evt(fifo->priv); + + if (count == 0) { + fifo->d_empty = (fifo->empty != 1); + fifo->empty = 1; + if (fifo->d_empty && (fifo->d_empty_evt != NULL)) + fifo->d_empty_evt(fifo->priv); + } + } + } + + return ret; +} + +void +fifo_clear_overrun(void *priv) +{ + fifo_t *fifo = (fifo_t *) priv; + + fifo->d_overrun = (fifo->overrun != 0); + fifo->overrun = 0; +} + +int +fifo_get_full(void *priv) +{ + const fifo_t *fifo = (fifo_t *) priv; + + return fifo->full; +} + +int +fifo_get_d_full(void *priv) +{ + fifo_t *fifo = (fifo_t *) priv; + int ret = fifo->d_full; + + fifo->d_full = 0; + + return ret; +} + +int +fifo_get_empty(void *priv) +{ + const fifo_t *fifo = (fifo_t *) priv; + + return fifo->empty; +} + +int +fifo_get_d_empty(void *priv) +{ + fifo_t *fifo = (fifo_t *) priv; + int ret = fifo->d_empty; + + fifo->d_empty = 0; + + return ret; +} + +int +fifo_get_overrun(void *priv) +{ + const fifo_t *fifo = (fifo_t *) priv; + + return fifo->overrun; +} + +int +fifo_get_d_overrun(void *priv) +{ + fifo_t *fifo = (fifo_t *) priv; + int ret = fifo->d_overrun; + + fifo->d_overrun = 0; + + return ret; +} + +int +fifo_get_ready(void *priv) +{ + const fifo_t *fifo = (fifo_t *) priv; + + return fifo->ready; +} + +int +fifo_get_d_ready(void *priv) +{ + fifo_t *fifo = (fifo_t *) priv; + int ret = fifo->d_ready; + + fifo->d_ready = 0; + + return ret; +} + +int +fifo_get_trigger_len(void *priv) +{ + const fifo_t *fifo = (fifo_t *) priv; + + return fifo->trigger_len; +} + +void +fifo_set_trigger_len(void *priv, int trigger_len) +{ + fifo_t *fifo = (fifo_t *) priv; + + fifo->trigger_len = trigger_len; +} + +void +fifo_set_len(void *priv, int len) +{ + fifo_t *fifo = (fifo_t *) priv; + + fifo->len = len; +} + +void +fifo_set_d_full_evt(void *priv, void (*d_full_evt)(void *)) +{ + fifo_t *fifo = (fifo_t *) priv; + + fifo->d_full_evt = d_full_evt; +} + +void +fifo_set_d_empty_evt(void *priv, void (*d_empty_evt)(void *)) +{ + fifo_t *fifo = (fifo_t *) priv; + + fifo->d_empty_evt = d_empty_evt; +} + +void +fifo_set_d_overrun_evt(void *priv, void (*d_overrun_evt)(void *)) +{ + fifo_t *fifo = (fifo_t *) priv; + + fifo->d_overrun_evt = d_overrun_evt; +} + +void +fifo_set_d_ready_evt(void *priv, void (*d_ready_evt)(void *)) +{ + fifo_t *fifo = (fifo_t *) priv; + + fifo->d_ready_evt = d_ready_evt; +} + +void +fifo_set_priv(void *priv, void *sub_priv) +{ + fifo_t *fifo = (fifo_t *) priv; + + fifo->priv = sub_priv; +} + +void +fifo_reset(void *priv) +{ + fifo_t *fifo = (fifo_t *) priv; + + fifo->start = fifo->end = 0; + fifo->full = fifo->overrun = 0; + fifo->empty = 1; + fifo->ready = 0; +} + +void +fifo_reset_evt(void *priv) +{ + fifo_t *fifo = (fifo_t *) priv; + + fifo->start = fifo->end = 0; + fifo->full = fifo->overrun = 0; + fifo->empty = 1; + fifo->ready = 0; + fifo->d_full = fifo->d_overrun = 0; + fifo->d_empty = fifo->d_ready = 0; + + if (fifo->d_full_evt != NULL) + fifo->d_full_evt(fifo->priv); + + if (fifo->d_overrun_evt != NULL) + fifo->d_overrun_evt(fifo->priv); + + if (fifo->d_empty_evt != NULL) + fifo->d_empty_evt(fifo->priv); + + if (fifo->d_ready_evt != NULL) + fifo->d_ready_evt(fifo->priv); +} + +void +fifo_close(void *priv) +{ + free(priv); +} + +void * +fifo_init(int len) +{ + void *fifo = NULL; + + if (len == 64) + fifo = calloc(1, sizeof(fifo64_t)); + else if (len == 16) + fifo = calloc(1, sizeof(fifo16_t)); + else { + fatal("FIFO : Invalid FIFO length: %i\n", len); + return NULL; + } + + if (fifo == NULL) + fatal("FIFO%i: Failed to allocate memory for the FIFO\n", len); + else + ((fifo_t *) fifo)->len = len; + + return fifo; +} + +#ifdef FIFO_STANDALONE +enum { + SERIAL_INT_LSR = 1, + SERIAL_INT_RECEIVE = 2, + SERIAL_INT_TRANSMIT = 4, + SERIAL_INT_MSR = 8, + SERIAL_INT_TIMEOUT = 16 +}; + +typedef struct serial_t { + uint8_t lsr; + uint8_t int_status; + uint8_t tsr; + uint8_t tsr_empty; + + fifo16_t *rcvr_fifo; + fifo16_t *xmit_fifo; +} serial_t; + +static void +serial_receive_timer(fifo16_t *f16, uint8_t val) +{ + fifo_write_evt(val, f16); + + printf("Write %02X to FIFO [F: %i, E: %i, O: %i, R: %i]\n", val, + fifo_get_full(f16), fifo_get_empty(f16), + fifo_get_overrun(f16), fifo_get_ready(f16)); + +#if 0 + if (fifo_get_d_overrun(f16)) + dev->lsr = (dev->lsr & 0xfd) | (fifo_get_overrun(f16) << 1); +#endif + + if (fifo_get_d_overrun(f16)) printf(" FIFO overrun state changed: %i -> %i\n", + !fifo_get_overrun(f16), fifo_get_overrun(f16)); + +#if 0 + if (fifo_get_d_empty(f16)) { + dev->lsr = (dev->lsr & 0xfe) | !fifo_get_empty(f16); + timer_on_auto(&dev->timeout_timer, 4.0 * dev->bits * dev->transmit_period); + } +#endif + + if (fifo_get_d_empty(f16)) + printf(" FIFO empty state changed: %i -> %i\n", + !fifo_get_empty(f16), fifo_get_empty(f16)); + +#if 0 + if (fifo_get_d_ready(f16)) { + dev->int_status = (dev->int_status & ~SERIAL_INT_RECEIVE) | + (fifo_get_ready(f16) ? SERIAL_INT_RECEIVE : 0); + serial_update_ints(); + } +#endif + if (fifo_get_d_ready(f16)) printf(" FIFO ready state changed: %i -> %i\n", + !fifo_get_ready(f16), fifo_get_ready(f16)); +} + +static uint8_t +serial_read(fifo16_t *f16) +{ + uint8_t ret; + + ret = fifo_read_evt(f16); + + printf("Read %02X from FIFO [F: %i, E: %i, O: %i, R: %i]\n", ret, + fifo_get_full(f16), fifo_get_empty(f16), + fifo_get_overrun(f16), fifo_get_ready(f16)); + +#if 0 + if (fifo_get_d_ready(f16)) { + dev->int_status = (dev->int_status & ~SERIAL_INT_RECEIVE) | + (fifo_get_ready(f16) ? SERIAL_INT_RECEIVE : 0); + serial_update_ints(); + } +#endif + + if (fifo_get_d_ready(f16)) + printf(" FIFO ready state changed: %i -> %i\n", + !fifo_get_ready(f16), fifo_get_ready(f16)); + +#if 0 + if (fifo_get_d_empty(f16)) { + dev->lsr = (dev->lsr & 0xfe) | !fifo_get_empty(f16); + timer_on_auto(&dev->timeout_timer, 4.0 * dev->bits * dev->transmit_period); + } +#endif + if (fifo_get_d_empty(f16)) + printf(" FIFO empty state changed: %i -> %i\n", + !fifo_get_empty(f16), fifo_get_empty(f16)); + + return ret; +} + +static void +serial_xmit_d_empty_evt(void *priv) +{ + serial_t *dev = (serial_t *) priv; + + dev->lsr = (dev->lsr & 0x9f) | (fifo_get_empty(dev->xmit_fifo) << 5) | + ((dev->tsr_empty && fifo_get_empty(dev->xmit_fifo)) << 6); + dev->int_status = (dev->int_status & ~SERIAL_INT_TRANSMIT) | + (fifo_get_empty(dev->xmit_fifo) ? SERIAL_INT_TRANSMIT : 0); + // serial_update_ints(); + + printf("NS16550: serial_xmit_d_empty_evt(%08X): dev->lsr = %02X\n", priv, dev->lsr); + printf("NS16550: serial_xmit_d_empty_evt(%08X): dev->int_status = %02X\n", priv, dev->int_status); +} + +static void +serial_rcvr_d_empty_evt(void *priv) +{ + serial_t *dev = (serial_t *) priv; + + dev->lsr = (dev->lsr & 0xfe) | !fifo_get_empty(dev->rcvr_fifo); + // timer_on_auto(&dev->timeout_timer, 4.0 * dev->bits * dev->transmit_period); + + printf("NS16550: serial_rcvr_d_empty_evt(%08X): dev->lsr = %02X\n", priv, dev->lsr); +} + +static void +serial_rcvr_d_overrun_evt(void *priv) +{ + serial_t *dev = (serial_t *) priv; + + dev->lsr = (dev->lsr & 0xfd) | (fifo_get_overrun(dev->rcvr_fifo) << 1); + + printf("NS16550: serial_rcvr_d_overrun_evt(%08X): dev->lsr = %02X\n", priv, dev->lsr); +} + +static void +serial_rcvr_d_ready_evt(void *priv) +{ + serial_t *dev = (serial_t *) priv; + + dev->int_status = (dev->int_status & ~SERIAL_INT_RECEIVE) | + (fifo_get_ready(dev->rcvr_fifo) ? SERIAL_INT_RECEIVE : 0); + // serial_update_ints(); + + printf("NS16550: serial_rcvr_d_ready_evt(%08X): dev->int_status = %02X\n", priv, dev->int_status); +} + +int +main(int argc, char *argv[]) +{ + uint8_t val; + uint8_t ret; + + printf("Initializing serial...\n"); + serial_t *dev = (serial_t *) calloc(1, sizeof(serial_t)); + dev->tsr_empty = 1; + + printf("Initializing dev->xmit_fifo...\n"); + dev->xmit_fifo = fifo16_init(); + fifo_set_trigger_len(dev->xmit_fifo, 255); + + fifo_set_priv(dev->xmit_fifo, dev); + fifo_set_d_empty_evt(dev->xmit_fifo, serial_xmit_d_empty_evt); + + printf("\nResetting dev->xmit_fifo...\n"); + fifo_reset_evt(dev->xmit_fifo); + + printf("\nInitializing dev->rcvr_fifo...\n"); + dev->rcvr_fifo = fifo16_init(); + fifo_set_trigger_len(dev->rcvr_fifo, 4); + + fifo_set_priv(dev->rcvr_fifo, dev); + fifo_set_d_empty_evt(dev->rcvr_fifo, serial_rcvr_d_empty_evt); + fifo_set_d_overrun_evt(dev->rcvr_fifo, serial_rcvr_d_overrun_evt); + fifo_set_d_ready_evt(dev->rcvr_fifo, serial_rcvr_d_ready_evt); + + printf("\nResetting dev->rcvr_fifo...\n"); + fifo_reset_evt(dev->rcvr_fifo); + + printf("\nSending/receiving data...\n"); + serial_receive_timer(dev->rcvr_fifo, '8'); + serial_receive_timer(dev->rcvr_fifo, '6'); + ret = serial_read(dev->rcvr_fifo); + serial_receive_timer(dev->rcvr_fifo, 'B'); + ret = serial_read(dev->rcvr_fifo); + serial_receive_timer(dev->rcvr_fifo, 'o'); + ret = serial_read(dev->rcvr_fifo); + serial_receive_timer(dev->rcvr_fifo, 'x'); + ret = serial_read(dev->rcvr_fifo); + ret = serial_read(dev->rcvr_fifo); + + fifo_close(dev->rcvr_fifo); + fifo_close(dev->xmit_fifo); + + free(dev); + + return 0; +} +#endif diff --git a/src/fifo8.c b/src/fifo8.c index 34e90d591..feef0deb2 100644 --- a/src/fifo8.c +++ b/src/fifo8.c @@ -21,33 +21,38 @@ #include <86box/86box.h> #include <86box/fifo8.h> -void fifo8_create(Fifo8 *fifo, uint32_t capacity) +void +fifo8_create(Fifo8 *fifo, uint32_t capacity) { - fifo->data = (uint8_t *)malloc(capacity); - memset(fifo->data, 0, capacity); + fifo->data = (uint8_t *) malloc(capacity); + memset(fifo->data, 0, capacity); fifo->capacity = capacity; - fifo->head = 0; - fifo->num = 0; + fifo->head = 0; + fifo->num = 0; } -void fifo8_destroy(Fifo8 *fifo) +void +fifo8_destroy(Fifo8 *fifo) { if (fifo->data) { - free(fifo->data); - fifo->data = NULL; - } + free(fifo->data); + fifo->data = NULL; + } } -void fifo8_push(Fifo8 *fifo, uint8_t data) +void +fifo8_push(Fifo8 *fifo, uint8_t data) { assert(fifo->num < fifo->capacity); fifo->data[(fifo->head + fifo->num) % fifo->capacity] = data; fifo->num++; } -void fifo8_push_all(Fifo8 *fifo, const uint8_t *data, uint32_t num) +void +fifo8_push_all(Fifo8 *fifo, const uint8_t *data, uint32_t num) { - uint32_t start, avail; + uint32_t start; + uint32_t avail; assert(fifo->num + num <= fifo->capacity); @@ -64,7 +69,8 @@ void fifo8_push_all(Fifo8 *fifo, const uint8_t *data, uint32_t num) fifo->num += num; } -uint8_t fifo8_pop(Fifo8 *fifo) +uint8_t +fifo8_pop(Fifo8 *fifo) { uint8_t ret; @@ -75,42 +81,47 @@ uint8_t fifo8_pop(Fifo8 *fifo) return ret; } -const uint8_t *fifo8_pop_buf(Fifo8 *fifo, uint32_t max, uint32_t *num) +const uint8_t * +fifo8_pop_buf(Fifo8 *fifo, uint32_t max, uint32_t *num) { - uint8_t *ret; + const uint8_t *ret; assert(max > 0 && max <= fifo->num); *num = MIN(fifo->capacity - fifo->head, max); - ret = &fifo->data[fifo->head]; + ret = &fifo->data[fifo->head]; fifo->head += *num; fifo->head %= fifo->capacity; fifo->num -= *num; return ret; } -void fifo8_reset(Fifo8 *fifo) +void +fifo8_reset(Fifo8 *fifo) { - fifo->num = 0; + fifo->num = 0; fifo->head = 0; } -int fifo8_is_empty(Fifo8 *fifo) +int +fifo8_is_empty(Fifo8 *fifo) { return (fifo->num == 0); } -int fifo8_is_full(Fifo8 *fifo) +int +fifo8_is_full(Fifo8 *fifo) { return (fifo->num == fifo->capacity); } -uint32_t fifo8_num_free(Fifo8 *fifo) +uint32_t +fifo8_num_free(Fifo8 *fifo) { return fifo->capacity - fifo->num; } -uint32_t fifo8_num_used(Fifo8 *fifo) +uint32_t +fifo8_num_used(Fifo8 *fifo) { return fifo->num; } - diff --git a/src/floppy/CMakeLists.txt b/src/floppy/CMakeLists.txt index 4517bc634..89fbbf76f 100644 --- a/src/floppy/CMakeLists.txt +++ b/src/floppy/CMakeLists.txt @@ -1,17 +1,18 @@ # -# 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. +# 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. +# This file is part of the 86Box distribution. # -# CMake build script. +# CMake build script. # -# Authors: David HrdliÄka, +# Authors: David HrdliÄka, # -# Copyright 2020,2021 David HrdliÄka. +# Copyright 2020-2021 David HrdliÄka. # -add_library(fdd OBJECT fdd.c fdc.c fdc_magitronic.c fdc_pii15xb.c fdi2raw.c fdd_common.c - fdd_86f.c fdd_fdi.c fdd_imd.c fdd_img.c fdd_json.c fdd_mfm.c fdd_td0.c) \ No newline at end of file +add_library(fdd OBJECT fdd.c fdc.c fdc_magitronic.c fdc_monster.c fdc_pii15xb.c + fdi2raw.c fdd_common.c fdd_86f.c fdd_fdi.c fdd_imd.c fdd_img.c fdd_json.c + fdd_mfm.c fdd_td0.c) diff --git a/src/floppy/fdc.c b/src/floppy/fdc.c index 0a8ecafc4..88948aed9 100644 --- a/src/floppy/fdc.c +++ b/src/floppy/fdc.c @@ -1,21 +1,21 @@ /* - * 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. + * 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. + * This file is part of the 86Box distribution. * - * Implementation of the NEC uPD-765 and compatible floppy disk - * controller. + * Implementation of the NEC uPD-765 and compatible floppy disk + * controller. * * * - * Authors: Sarah Walker, - * Miran Grca, + * Authors: Sarah Walker, + * Miran Grca, * - * Copyright 2008-2020 Sarah Walker. - * Copyright 2016-2020 Miran Grca. + * Copyright 2008-2020 Sarah Walker. + * Copyright 2016-2020 Miran Grca. */ #include #include @@ -36,310 +36,306 @@ #include <86box/fdd.h> #include <86box/fdc.h> #include <86box/fdc_ext.h> - +#include <86box/plat_fallthrough.h> +#include <86box/plat_unused.h> extern uint64_t motoron[FDD_NUM]; - const uint8_t command_has_drivesel[32] = { - 0, 0, - 1, /* READ TRACK */ - 0, - 1, /* SENSE DRIVE STATUS */ - 1, /* WRITE DATA */ - 1, /* READ DATA */ - 1, /* RECALIBRATE */ - 0, - 1, /* WRITE DELETED DATA */ - 1, /* READ ID */ - 0, - 1, /* READ DELETED DATA */ - 1, /* FORMAT TRACK */ - 0, - 1, /* SEEK, RELATIVE SEEK */ - 0, - 1, /* SCAN EQUAL */ - 0, 0, 0, 0, - 1, /* VERIFY */ - 0, 0, - 1, /* SCAN LOW OR EQUAL */ - 0, 0, 0, - 1, /* SCAN HIGH OR EQUAL */ - 0, 0 + 0, 0, + 1, /* READ TRACK */ + 0, + 1, /* SENSE DRIVE STATUS */ + 1, /* WRITE DATA */ + 1, /* READ DATA */ + 1, /* RECALIBRATE */ + 0, + 1, /* WRITE DELETED DATA */ + 1, /* READ ID */ + 0, + 1, /* READ DELETED DATA */ + 1, /* FORMAT TRACK */ + 0, + 1, /* SEEK, RELATIVE SEEK */ + 0, + 1, /* SCAN EQUAL */ + 0, 0, 0, 0, + 1, /* VERIFY */ + 0, 0, + 1, /* SCAN LOW OR EQUAL */ + 0, 0, 0, + 1, /* SCAN HIGH OR EQUAL */ + 0, 0 }; - static uint8_t current_drive = 0; static void fdc_callback(void *priv); -int lastbyte=0; +int lastbyte = 0; int floppymodified[4]; int floppyrate[4]; - int fdc_type = 0; #ifdef ENABLE_FDC_LOG int fdc_do_log = ENABLE_FDC_LOG; - static void fdc_log(const char *fmt, ...) { - va_list ap; + va_list ap; - if (fdc_do_log) - { - va_start(ap, fmt); - pclog_ex(fmt, ap); - va_end(ap); - } + if (fdc_do_log) { + va_start(ap, fmt); + pclog_ex(fmt, ap); + va_end(ap); + } } #else -#define fdc_log(fmt, ...) +# define fdc_log(fmt, ...) #endif +#if 0 +const device_t fdc_none_device = { + .name = "None", + .internal_name = "none", + .flags = 0, + .local = 0, + .init = NULL, + .close = NULL, + .reset = NULL, + { .available = NULL }, + .speed_changed = NULL, + .force_redraw = NULL, + .config = NULL +}; +#endif const device_t fdc_internal_device = { - "Internal", - "internal", - 0, 0, - NULL, NULL, NULL, - { NULL }, NULL, NULL, - NULL + .name = "Internal", + .internal_name = "internal", + .flags = 0, + .local = 0, + .init = NULL, + .close = NULL, + .reset = NULL, + { .available = NULL }, + .speed_changed = NULL, + .force_redraw = NULL, + .config = NULL }; - typedef const struct { - const device_t *device; + const device_t *device; } fdc_cards_t; -/* All emulated machines have at least one integrated FDC controller */ static fdc_cards_t fdc_cards[] = { - { &fdc_internal_device }, - { &fdc_b215_device }, - { &fdc_pii151b_device }, - { &fdc_pii158b_device }, - { NULL } + // clang-format off +#if 0 + { &fdc_none_device }, +#endif + { &fdc_internal_device }, + { &fdc_b215_device }, + { &fdc_pii151b_device }, + { &fdc_pii158b_device }, + { &fdc_monster_device }, + { NULL } + // clang-format on }; - int fdc_card_available(int card) { if (fdc_cards[card].device) - return(device_available(fdc_cards[card].device)); + return (device_available(fdc_cards[card].device)); - return(1); + return 1; } - const device_t * fdc_card_getdevice(int card) { - return(fdc_cards[card].device); + return (fdc_cards[card].device); } - int fdc_card_has_config(int card) { - if (! fdc_cards[card].device) return(0); + if (!fdc_cards[card].device) + return 0; - return(fdc_cards[card].device->config ? 1 : 0); + return (device_has_config(fdc_cards[card].device) ? 1 : 0); } - -char * +const char * fdc_card_get_internal_name(int card) { return device_get_internal_name(fdc_cards[card].device); } - int fdc_card_get_from_internal_name(char *s) { int c = 0; while (fdc_cards[c].device != NULL) { - if (!strcmp((char *) fdc_cards[c].device->internal_name, s)) - return(c); - c++; + if (!strcmp(fdc_cards[c].device->internal_name, s)) + return c; + c++; } - - return(0); -} + return 0; +} void fdc_card_init(void) { - if (!fdc_cards[fdc_type].device) - return; - - device_add(fdc_cards[fdc_type].device); + if ((fdc_type > 0) && fdc_cards[fdc_type].device) + device_add(fdc_cards[fdc_type].device); } - uint8_t fdc_get_current_drive(void) { return current_drive; } - void -fdc_ctrl_reset(void *p) +fdc_ctrl_reset(void *priv) { - fdc_t *fdc = (fdc_t *) p; + fdc_t *fdc = (fdc_t *) priv; fdc->stat = 0x80; - fdc->pnum = fdc->ptot=0; - fdc->st0 = 0; - fdc->lock = 0; - fdc->head = 0; - fdc->step = 0; + fdc->pnum = fdc->ptot = 0; + fdc->st0 = 0; + fdc->lock = 0; + fdc->head = 0; + fdc->step = 0; if (!(fdc->flags & FDC_FLAG_AT)) - fdc->rate = 2; + fdc->rate = 2; } - sector_id_t fdc_get_read_track_sector(fdc_t *fdc) { return fdc->read_track_sector; } - int fdc_get_compare_condition(fdc_t *fdc) { switch (fdc->interrupt) { - case 0x11: - default: - return 0; - case 0x19: - return 1; - case 0x1D: - return 2; + default: + case 0x11: + return 0; + case 0x19: + return 1; + case 0x1D: + return 2; } } - int fdc_is_deleted(fdc_t *fdc) { return fdc->deleted & 1; } - int fdc_is_sk(fdc_t *fdc) { return (fdc->deleted & 0x20) ? 1 : 0; } - void fdc_set_wrong_am(fdc_t *fdc) { fdc->wrong_am = 1; } - int fdc_get_drive(fdc_t *fdc) { return fdc->drive; } - -int fdc_get_bitcell_period(fdc_t *fdc); -int fdc_get_bit_rate(fdc_t *fdc); -static void fdc_rate(fdc_t *fdc, int drive); - +int fdc_get_bitcell_period(fdc_t *fdc); +int fdc_get_bit_rate(fdc_t *fdc); +static void fdc_rate(fdc_t *fdc, int drive); int fdc_get_perp(fdc_t *fdc) { if (!(fdc->flags & FDC_FLAG_AT) || (fdc->flags & FDC_FLAG_PCJR)) - return 0; + return 0; return fdc->perp; } - int fdc_get_gap2(fdc_t *fdc, int drive) { int auto_gap2 = 22; if (!(fdc->flags & FDC_FLAG_AT) || (fdc->flags & FDC_FLAG_PCJR)) - return 22; + return 22; if (fdc->perp & 3) - return ((fdc->perp & 3) == 3) ? 41 : 22; + return ((fdc->perp & 3) == 3) ? 41 : 22; else { - auto_gap2 = (fdc_get_bit_rate(fdc) >= 3) ? 41 : 22; - return (fdc->perp & (4 << drive)) ? auto_gap2 : 22; + auto_gap2 = (fdc_get_bit_rate(fdc) >= 3) ? 41 : 22; + return (fdc->perp & (4 << drive)) ? auto_gap2 : 22; } } - int fdc_get_format_n(fdc_t *fdc) { return fdc->format_n; } - int fdc_is_mfm(fdc_t *fdc) { return fdc->mfm ? 1 : 0; } - void fdc_request_next_sector_id(fdc_t *fdc) { if ((fdc->flags & FDC_FLAG_PCJR) || !fdc->dma) - fdc->stat = 0xf0; - else - fdc->stat = 0xd0; + fdc->stat = 0xf0; + else { + dma_set_drq(fdc->dma_ch, 1); + fdc->stat = 0xd0; + } } - void fdc_stop_id_request(fdc_t *fdc) { fdc->stat &= 0x7f; } - int fdc_get_gap(fdc_t *fdc) { return fdc->gap; } - int fdc_get_dtl(fdc_t *fdc) { return fdc->dtl; } - int fdc_get_format_sectors(fdc_t *fdc) { return fdc->format_sectors; } - static void fdc_reset_fifo_buf(fdc_t *fdc) { @@ -347,17 +343,15 @@ fdc_reset_fifo_buf(fdc_t *fdc) fdc->fifobufpos = 0; } - static void fdc_fifo_buf_advance(fdc_t *fdc) { if (fdc->fifobufpos == fdc->tfifo) - fdc->fifobufpos = 0; + fdc->fifobufpos = 0; else - fdc->fifobufpos++; + fdc->fifobufpos++; } - static void fdc_fifo_buf_write(fdc_t *fdc, uint8_t val) { @@ -365,35 +359,32 @@ fdc_fifo_buf_write(fdc_t *fdc, uint8_t val) fdc_fifo_buf_advance(fdc); } - static int fdc_fifo_buf_read(fdc_t *fdc) { int temp = fdc->fifobuf[fdc->fifobufpos]; fdc_fifo_buf_advance(fdc); if (!fdc->fifobufpos) - fdc->data_ready = 0; + fdc->data_ready = 0; return temp; } - -static -void fdc_int(fdc_t *fdc, int set_fintr) +static void +fdc_int(fdc_t *fdc, int set_fintr) { int ienable = 0; if (!(fdc->flags & FDC_FLAG_PCJR)) - ienable = !!(fdc->dor & 8); + ienable = !!(fdc->dor & 8); if (ienable) - picint(1 << fdc->irq); + picint(1 << fdc->irq); if (set_fintr) - fdc->fintr = 1; + fdc->fintr = 1; fdc_log("fdc_int(%i): fdc->fintr = %i\n", set_fintr, fdc->fintr); } - static void fdc_watchdog_poll(void *priv) { @@ -401,14 +392,13 @@ fdc_watchdog_poll(void *priv) fdc->watchdog_count--; if (fdc->watchdog_count) - timer_advance_u64(&fdc->watchdog_timer, 1000 * TIMER_USEC); + timer_advance_u64(&fdc->watchdog_timer, 1000 * TIMER_USEC); else { - if (fdc->dor & 0x20) - picint(1 << fdc->irq); + if (fdc->dor & 0x20) + picint(1 << fdc->irq); } } - /* fdc->rwc per Winbond W83877F datasheet: 0 = normal; 1 = 500 kbps, 360 rpm; @@ -428,14 +418,12 @@ fdc_update_rates(fdc_t *fdc) fdc_rate(fdc, 3); } - void fdc_update_max_track(fdc_t *fdc, int max_track) { fdc->max_track = max_track; } - void fdc_update_enh_mode(fdc_t *fdc, int enh_mode) { @@ -443,14 +431,12 @@ fdc_update_enh_mode(fdc_t *fdc, int enh_mode) fdc_update_rates(fdc); } - int fdc_get_rwc(fdc_t *fdc, int drive) { return fdc->rwc[drive]; } - void fdc_update_rwc(fdc_t *fdc, int drive, int rwc) { @@ -459,21 +445,18 @@ fdc_update_rwc(fdc_t *fdc, int drive, int rwc) fdc_rate(fdc, drive); } - int fdc_get_boot_drive(fdc_t *fdc) { return fdc->boot_drive; } - void fdc_update_boot_drive(fdc_t *fdc, int boot_drive) { fdc->boot_drive = boot_drive; } - void fdc_update_densel_polarity(fdc_t *fdc, int densel_polarity) { @@ -482,14 +465,12 @@ fdc_update_densel_polarity(fdc_t *fdc, int densel_polarity) fdc_update_rates(fdc); } - uint8_t fdc_get_densel_polarity(fdc_t *fdc) { return fdc->densel_polarity; } - void fdc_update_densel_force(fdc_t *fdc, int densel_force) { @@ -498,7 +479,6 @@ fdc_update_densel_force(fdc_t *fdc, int densel_force) fdc_update_rates(fdc); } - void fdc_update_drvrate(fdc_t *fdc, int drive, int drvrate) { @@ -507,141 +487,155 @@ fdc_update_drvrate(fdc_t *fdc, int drive, int drvrate) fdc_rate(fdc, drive); } - void fdc_update_drv2en(fdc_t *fdc, int drv2en) { fdc->drv2en = drv2en; } - void fdc_update_rate(fdc_t *fdc, int drive) { if (((fdc->rwc[drive] == 1) || (fdc->rwc[drive] == 2)) && fdc->enh_mode) - fdc->bit_rate = 500; + fdc->bit_rate = 500; else if ((fdc->rwc[drive] == 3) && fdc->enh_mode) - fdc->bit_rate = 250; - else switch (fdc->rate) { - case 0: /*High density*/ - fdc->bit_rate = 500; - break; - case 1: /*Double density (360 rpm)*/ - switch(fdc->drvrate[drive]) { - case 0: - fdc->bit_rate = 300; - break; - case 1: - fdc->bit_rate = 500; - break; - case 2: - fdc->bit_rate = 2000; - break; - } - break; - case 2: /*Double density*/ - fdc->bit_rate = 250; - break; - case 3: /*Extended density*/ - fdc->bit_rate = 1000; - break; - } + fdc->bit_rate = 250; + else + switch (fdc->rate) { + case 0: /*High density*/ + fdc->bit_rate = 500; + break; + case 1: /*Double density (360 rpm)*/ + switch (fdc->drvrate[drive]) { + case 0: + fdc->bit_rate = 300; + break; + case 1: + fdc->bit_rate = 500; + break; + case 2: + fdc->bit_rate = 2000; + break; + + default: + break; + } + break; + case 2: /*Double density*/ + fdc->bit_rate = 250; + break; + case 3: /*Extended density*/ + fdc->bit_rate = 1000; + break; + + default: + break; + } fdc->bitcell_period = (1000000 / fdc->bit_rate) * 2; /*Bitcell period in ns*/ } - int fdc_get_bit_rate(fdc_t *fdc) { - switch(fdc->bit_rate) { - case 500: - return 0; - case 300: - return 1; - case 2000: - return 1 | 4; - case 250: - return 2; - case 1000: - return 3; - default: - return 2; + switch (fdc->bit_rate) { + case 500: + return 0; + case 300: + return 1; + case 2000: + return 1 | 4; + case 250: + return 2; + case 1000: + return 3; + + default: + break; } return 2; } - int fdc_get_bitcell_period(fdc_t *fdc) { return fdc->bitcell_period; } - static int fdc_get_densel(fdc_t *fdc, int drive) { if (fdc->enh_mode) { - switch (fdc->rwc[drive]) { - case 1: - case 3: - return 0; - case 2: - return 1; - } + switch (fdc->rwc[drive]) { + case 1: + case 3: + return 0; + case 2: + return 1; + + default: + break; + } } if (!(fdc->flags & FDC_FLAG_NSC)) { - switch (fdc->densel_force) { - case 2: - return 1; - case 3: - return 0; - } + switch (fdc->densel_force) { + case 2: + return 1; + case 3: + return 0; + + default: + break; + } } else { - switch (fdc->densel_force) { - case 0: - return 0; - case 1: - return 1; - } + switch (fdc->densel_force) { + case 0: + return 0; + case 1: + return 1; + + default: + break; + } } switch (fdc->rate) { - case 0: - case 3: - return fdc->densel_polarity ? 1 : 0; - case 1: - case 2: - return fdc->densel_polarity ? 0 : 1; + case 0: + case 3: + return fdc->densel_polarity ? 1 : 0; + case 1: + case 2: + return fdc->densel_polarity ? 0 : 1; + + default: + break; } return 0; } - static void fdc_rate(fdc_t *fdc, int drive) { fdc_update_rate(fdc, drive); - // fdc_log("FDD %c: Setting rate: %i, %i, %i (%i, %i)\n", 0x41 + drive, fdc->drvrate[drive], fdc->rate, fdc_get_densel(fdc, drive), fdc->rwc[drive], fdc->densel_force); +#if 0 + fdc_log("FDD %c: Setting rate: %i, %i, %i (%i, %i)\n", 0x41 + drive, fdc->drvrate[drive], fdc->rate, fdc_get_densel(fdc, drive), fdc->rwc[drive], fdc->densel_force); +#endif fdc_log("FDD %c: [%i] Setting rate: %i, %i, %i (%i, %i, %i)\n", 0x41 + drive, fdc->enh_mode, fdc->drvrate[drive], fdc->rate, fdc_get_densel(fdc, drive), fdc->rwc[drive], fdc->densel_force, fdc->densel_polarity); fdd_set_densel(fdc_get_densel(fdc, drive)); fdc_log("FDD %c: [%i] Densel: %i\n", 0x41 + drive, fdc->enh_mode, fdc_get_densel(fdc, drive)); } - int real_drive(fdc_t *fdc, int drive) { if (drive < 2) - return drive ^ fdc->swap; + return drive ^ fdc->swap; else - return drive; + return drive; } - void fdc_seek(fdc_t *fdc, int drive, int params) { @@ -649,16 +643,14 @@ fdc_seek(fdc_t *fdc, int drive, int params) fdc->stat |= (1 << fdc->drive); } - static void fdc_bad_command(fdc_t *fdc) { - fdc->stat = 0x10; + fdc->stat = 0x10; fdc->interrupt = 0xfc; timer_set_delay_u64(&fdc->timer, 100 * TIMER_USEC); } - static void fdc_io_command_phase1(fdc_t *fdc, int out) { @@ -668,7 +660,7 @@ fdc_io_command_phase1(fdc_t *fdc, int out) pclog_toggle_suppr(); pclog("%02X ", fdc->processed_cmd); for (i = 0; i < fdc->pnum; i++) - pclog("%02X ", fdc->params[i]); + pclog("%02X ", fdc->params[i]); pclog("\n"); pclog_toggle_suppr(); #endif @@ -677,56 +669,57 @@ fdc_io_command_phase1(fdc_t *fdc, int out) fdc_rate(fdc, fdc->drive); fdc->head = fdc->params[2]; fdd_set_head(real_drive(fdc, fdc->drive), (fdc->params[0] & 4) ? 1 : 0); - fdc->sector=fdc->params[3]; + fdc->sector = fdc->params[3]; fdc->eot[fdc->drive] = fdc->params[5]; - fdc->gap = fdc->params[6]; - fdc->dtl = fdc->params[7]; - fdc->rw_track = fdc->params[1]; + fdc->gap = fdc->params[6]; + fdc->dtl = fdc->params[7]; + fdc->rw_track = fdc->params[1]; if (fdc->config & 0x40) { - if (fdc->rw_track != fdc->pcn[fdc->params[0] & 3]) { - fdc_seek(fdc, fdc->drive, ((int) fdc->rw_track) - ((int) fdc->pcn[fdc->params[0] & 3])); - fdc->pcn[fdc->params[0] & 3] = fdc->rw_track; - } + if (fdc->rw_track != fdc->pcn[fdc->params[0] & 3]) { + fdc_seek(fdc, fdc->drive, ((int) fdc->rw_track) - ((int) fdc->pcn[fdc->params[0] & 3])); + fdc->pcn[fdc->params[0] & 3] = fdc->rw_track; + } } ui_sb_update_icon(SB_FLOPPY | real_drive(fdc, fdc->drive), 1); fdc->stat = out ? 0x90 : 0x50; if ((fdc->flags & FDC_FLAG_PCJR) || !fdc->dma) - fdc->stat |= 0x20; - if (out) - fdc->pos = 0; + fdc->stat |= 0x20; else - fdc->inread = 1; + dma_set_drq(fdc->dma_ch, 1); + if (out) + fdc->pos = 0; + else + fdc->inread = 1; } - static void fdc_sis(fdc_t *fdc) { int drive_num; - fdc->stat = (fdc->stat & 0xf) | 0xd0; + fdc->stat = (fdc->stat & 0xf) | 0xd0; if (fdc->reset_stat) { - drive_num = real_drive(fdc, 4 - fdc->reset_stat); - if ((drive_num < FDD_NUM) && fdd_get_flags(drive_num)) { - fdd_stop(drive_num); - fdd_set_head(drive_num, 0); - fdc->res[9] = 0xc0 | (4 - fdc->reset_stat) | (fdd_get_head(drive_num) ? 4 : 0); - } else - fdc->res[9] = 0xc0 | (4 - fdc->reset_stat); + drive_num = real_drive(fdc, 4 - fdc->reset_stat); + if ((drive_num < FDD_NUM) && fdd_get_flags(drive_num)) { + fdd_stop(drive_num); + fdd_set_head(drive_num, 0); + fdc->res[9] = 0xc0 | (4 - fdc->reset_stat) | (fdd_get_head(drive_num) ? 4 : 0); + } else + fdc->res[9] = 0xc0 | (4 - fdc->reset_stat); - fdc->reset_stat--; + fdc->reset_stat--; } else { - if (fdc->fintr) { - fdc->res[9] = (fdc->st0 & ~0x04) | (fdd_get_head(real_drive(fdc, fdc->drive)) ? 4 : 0); - fdc->fintr = 0; - } else { - fdc->res[10] = 0x80; - fdc->paramstogo = 1; - return; - } + if (fdc->fintr) { + fdc->res[9] = (fdc->st0 & ~0x04) | (fdd_get_head(real_drive(fdc, fdc->drive)) ? 4 : 0); + fdc->fintr = 0; + } else { + fdc->res[10] = 0x80; + fdc->paramstogo = 1; + return; + } } fdc->res[10] = fdc->pcn[fdc->res[9] & 3]; @@ -735,711 +728,725 @@ fdc_sis(fdc_t *fdc) fdc->paramstogo = 2; } - static void fdc_write(uint16_t addr, uint8_t val, void *priv) { fdc_t *fdc = (fdc_t *) priv; - int drive, i, drive_num; + int drive; + int i; + int drive_num; fdc_log("Write FDC %04X %02X\n", addr, val); cycles -= ISA_CYCLES(8); - switch (addr&7) { - case 0: - return; - case 1: - return; - case 2: /*DOR*/ - if (fdc->flags & FDC_FLAG_PCJR) { - if ((fdc->dor & 0x40) && !(val & 0x40)) { - timer_set_delay_u64(&fdc->watchdog_timer, 1000 * TIMER_USEC); - fdc->watchdog_count = 1000; - picintc(1 << fdc->irq); - } - if ((val & 0x80) && !(fdc->dor & 0x80)) { - timer_set_delay_u64(&fdc->timer, 8 * TIMER_USEC); - fdc->interrupt = -1; - ui_sb_update_icon(SB_FLOPPY | 0, 0); - fdc_ctrl_reset(fdc); - fdd_changed[0] = 1; - } - if (!fdd_get_flags(0)) - val &= 0xfe; - fdd_set_motor_enable(0, val & 0x01); - fdc->st0 &= ~0x07; - fdc->st0 |= (fdd_get_head(0) ? 4 : 0); + switch (addr & 7) { + case 0: + return; + case 1: + return; + case 2: /*DOR*/ + if (fdc->flags & FDC_FLAG_PCJR) { + if ((fdc->dor & 0x40) && !(val & 0x40)) { + timer_set_delay_u64(&fdc->watchdog_timer, 1000 * TIMER_USEC); + fdc->watchdog_count = 1000; + picintc(1 << fdc->irq); + } + if ((val & 0x80) && !(fdc->dor & 0x80)) { + timer_set_delay_u64(&fdc->timer, 8 * TIMER_USEC); + fdc->interrupt = -1; + ui_sb_update_icon(SB_FLOPPY | 0, 0); + fdc_ctrl_reset(fdc); + fdd_changed[0] = 1; + } + if (!fdd_get_flags(0)) + val &= 0xfe; + fdd_set_motor_enable(0, val & 0x01); + fdc->st0 &= ~0x07; + fdc->st0 |= (fdd_get_head(0) ? 4 : 0); + } else { + if (!(val & 8) && (fdc->dor & 8)) { + fdc->tc = 1; + fdc_int(fdc, 1); + } + if (!(val & 4)) { + fdd_stop(real_drive(fdc, val & 3)); + fdc->stat = 0x00; + fdc->pnum = fdc->ptot = 0; + } + if ((val & 4) && !(fdc->dor & 4)) { + timer_set_delay_u64(&fdc->timer, 8 * TIMER_USEC); + fdc->interrupt = -1; + fdc->perp &= 0xfc; + + for (i = 0; i < FDD_NUM; i++) + ui_sb_update_icon(SB_FLOPPY | i, 0); + + fdc_ctrl_reset(fdc); + } + /* We can now simplify this since each motor now spins separately. */ + for (i = 0; i < FDD_NUM; i++) { + drive_num = real_drive(fdc, i); + if ((!fdd_get_flags(drive_num)) || (drive_num >= FDD_NUM)) + val &= ~(0x10 << drive_num); + else + fdd_set_motor_enable(i, (val & (0x10 << drive_num))); + } + drive_num = real_drive(fdc, val & 0x03); + current_drive = drive_num; + fdc->st0 = (fdc->st0 & 0xf8) | (val & 0x03) | (fdd_get_head(drive_num) ? 4 : 0); + } + fdc->dor = val; + return; + case 3: /* TDR */ + if (fdc->enh_mode) { + drive = real_drive(fdc, fdc->dor & 3); + fdc_update_rwc(fdc, drive, (val & 0x30) >> 4); + } + return; + case 4: + if (val & 0x80) { + timer_set_delay_u64(&fdc->timer, 8 * TIMER_USEC); + fdc->interrupt = -1; + fdc->perp &= 0xfc; + fdc_ctrl_reset(fdc); + } + return; + case 5: /*Command register*/ + if ((fdc->stat & 0xf0) == 0xb0) { + if ((fdc->flags & FDC_FLAG_PCJR) || !fdc->fifo) { + fdc->dat = val; + fdc->stat &= ~0x80; } else { - if (!(val & 8) && (fdc->dor & 8)) { - fdc->tc = 1; - fdc_int(fdc, 1); - } - if (!(val&4)) { - fdd_stop(real_drive(fdc, val & 3)); - fdc->stat = 0x00; - fdc->pnum = fdc->ptot = 0; - } - if ((val&4) && !(fdc->dor&4)) { - timer_set_delay_u64(&fdc->timer, 8 * TIMER_USEC); - fdc->interrupt = -1; - fdc->perp &= 0xfc; + fdc_fifo_buf_write(fdc, val); + if (fdc->fifobufpos == 0) + fdc->stat &= ~0x80; + } + break; + } + if (fdc->pnum == fdc->ptot) { + if ((fdc->stat & 0xf0) != 0x80) { + /* If bit 4 of the MSR is set, or the MSR is 0x00, + the fdc_t is NOT in the command phase, therefore + do NOT accept commands. */ + return; + } - for (i = 0; i < FDD_NUM; i++) - ui_sb_update_icon(SB_FLOPPY | i, 0); + fdc->stat &= 0xf; - fdc_ctrl_reset(fdc); - } - /* We can now simplify this since each motor now spins separately. */ - for (i = 0; i < FDD_NUM; i++) { - drive_num = real_drive(fdc, i); - if ((!fdd_get_flags(drive_num)) || (drive_num >= FDD_NUM)) - val &= ~(0x10 << drive_num); - else - fdd_set_motor_enable(i, (val & (0x10 << drive_num))); - } - drive_num = real_drive(fdc, val & 0x03); - current_drive = drive_num; - fdc->st0 = (fdc->st0 & 0xf8) | (val & 0x03) | (fdd_get_head(drive_num) ? 4 : 0); - } - fdc->dor = val; - return; - case 3: /* TDR */ - if (fdc->enh_mode) { - drive = real_drive(fdc, fdc->dor & 3); - fdc_update_rwc(fdc, drive, (val & 0x30) >> 4); - } - return; - case 4: - if (val & 0x80) { - timer_set_delay_u64(&fdc->timer, 8 * TIMER_USEC); - fdc->interrupt = -1; - fdc->perp &= 0xfc; - fdc_ctrl_reset(fdc); - } - return; - case 5: /*Command register*/ - if ((fdc->stat & 0xf0) == 0xb0) { - if ((fdc->flags & FDC_FLAG_PCJR) || !fdc->fifo) { - fdc->dat = val; - fdc->stat &= ~0x80; - } else { - fdc_fifo_buf_write(fdc, val); - if (fdc->fifobufpos == 0) - fdc->stat &= ~0x80; - } - break; - } - if (fdc->pnum == fdc->ptot) { - if ((fdc->stat & 0xf0) != 0x80) { - /* If bit 4 of the MSR is set, or the MSR is 0x00, - the fdc_t is NOT in the command phase, therefore - do NOT accept commands. */ - return; - } + fdc->tc = 0; + fdc->data_ready = 0; - fdc->stat &= 0xf; + fdc->command = val; + fdc->stat |= 0x10; + fdc_log("Starting FDC command %02X\n", fdc->command); + fdc->error = 0; - fdc->tc = 0; - fdc->data_ready = 0; + if (((fdc->command & 0x1f) == 0x02) || ((fdc->command & 0x1f) == 0x05) || ((fdc->command & 0x1f) == 0x06) || ((fdc->command & 0x1f) == 0x0a) || ((fdc->command & 0x1f) == 0x0c) || ((fdc->command & 0x1f) == 0x0d) || ((fdc->command & 0x1f) == 0x11) || ((fdc->command & 0x1f) == 0x16) || ((fdc->command & 0x1f) == 0x19) || ((fdc->command & 0x1f) == 0x1d)) + fdc->processed_cmd = fdc->command & 0x1f; + else + fdc->processed_cmd = fdc->command; - fdc->command = val; - fdc->stat |= 0x10; - fdc_log("Starting FDC command %02X\n",fdc->command); - fdc->error = 0; + switch (fdc->processed_cmd) { + case 0x01: /*Mode*/ + if (fdc->flags & FDC_FLAG_NSC) { + fdc->pnum = 0; + fdc->ptot = 4; + fdc->stat |= 0x90; + fdc->pos = 0; + fdc->format_state = 0; + } else + fdc_bad_command(fdc); + break; + case 0x02: /*Read track*/ + fdc->satisfying_sectors = 0; + fdc->sc = 0; + fdc->wrong_am = 0; + fdc->pnum = 0; + fdc->ptot = 8; + fdc->stat |= 0x90; + fdc->pos = 0; + fdc->mfm = (fdc->command & 0x40) ? 1 : 0; + break; + case 0x03: /*Specify*/ + fdc->pnum = 0; + fdc->ptot = 2; + fdc->stat |= 0x90; + break; + case 0x04: /*Sense drive status*/ + fdc->pnum = 0; + fdc->ptot = 1; + fdc->stat |= 0x90; + break; + case 0x05: /*Write data*/ + case 0x09: /*Write deleted data*/ + fdc->satisfying_sectors = 0; + fdc->sc = 0; + fdc->wrong_am = 0; + fdc->deleted = ((fdc->command & 0x1F) == 9) ? 1 : 0; + fdc->pnum = 0; + fdc->ptot = 8; + fdc->stat |= 0x90; + fdc->pos = 0; + fdc->mfm = (fdc->command & 0x40) ? 1 : 0; + break; + case 0x06: /*Read data*/ + case 0x0c: /*Read deleted data*/ + case 0x11: /*Scan equal*/ + case 0x19: /*Scan low or equal*/ + case 0x16: /*Verify*/ + case 0x1d: /*Scan high or equal*/ + fdc->satisfying_sectors = 0; + fdc->sc = 0; + fdc->wrong_am = 0; + fdc->deleted = ((fdc->command & 0x1F) == 0xC) ? 1 : 0; + if ((fdc->command & 0x1F) == 0x16) + fdc->deleted = 2; + fdc->deleted |= (fdc->command & 0x20); + fdc->pnum = 0; + fdc->ptot = 8; + fdc->stat |= 0x90; + fdc->pos = 0; + fdc->mfm = (fdc->command & 0x40) ? 1 : 0; + break; + case 0x17: /*Powerdown mode*/ + if (!(fdc->flags & FDC_FLAG_ALI)) { + fdc_bad_command(fdc); + break; + } + fallthrough; + case 0x07: /*Recalibrate*/ + fdc->pnum = 0; + fdc->ptot = 1; + fdc->stat |= 0x90; + break; + case 0x08: /*Sense interrupt status*/ + fdc_log("fdc->fintr = %i, fdc->reset_stat = %i\n", fdc->fintr, fdc->reset_stat); + fdc->lastdrive = fdc->drive; + fdc->pos = 0; + fdc_sis(fdc); + break; + case 0x0a: /*Read sector ID*/ + fdc->pnum = 0; + fdc->ptot = 1; + fdc->stat |= 0x90; + fdc->pos = 0; + fdc->mfm = (fdc->command & 0x40) ? 1 : 0; + break; + case 0x0d: /*Format track*/ + fdc->pnum = 0; + fdc->ptot = 5; + fdc->stat |= 0x90; + fdc->pos = 0; + fdc->mfm = (fdc->command & 0x40) ? 1 : 0; + fdc->format_state = 0; + break; + case 0x0e: /*Dump registers*/ + fdc->lastdrive = fdc->drive; + fdc->interrupt = 0x0e; + fdc->pos = 0; + fdc_callback(fdc); + break; + case 0x0f: /*Seek*/ + fdc->pnum = 0; + fdc->ptot = 2; + fdc->stat |= 0x90; + break; + case 0x18: /*NSC*/ + if (!(fdc->flags & FDC_FLAG_NSC)) { + fdc_bad_command(fdc); + break; + } + fallthrough; + case 0x10: /*Get version*/ + case 0x14: /*Unlock*/ + case 0x94: /*Lock*/ + fdc->lastdrive = fdc->drive; + fdc->interrupt = fdc->command; + fdc->pos = 0; + fdc_callback(fdc); + break; + case 0x12: /*Set perpendicular mode*/ + if ((fdc->flags & FDC_FLAG_AT) && !(fdc->flags & FDC_FLAG_PCJR)) { + fdc->pnum = 0; + fdc->ptot = 1; + fdc->stat |= 0x90; + fdc->pos = 0; + } else + fdc_bad_command(fdc); + break; + case 0x13: /*Configure*/ + fdc->pnum = 0; + fdc->ptot = 3; + fdc->stat |= 0x90; + fdc->pos = 0; + break; + default: + fdc_bad_command(fdc); + break; + } + } else { + fdc->stat = 0x10 | (fdc->stat & 0xf); + fdc->params[fdc->pnum++] = val; + if (fdc->pnum == 1) { + if (command_has_drivesel[fdc->command & 0x1F]) { + if (fdc->flags & FDC_FLAG_PCJR) + fdc->drive = 0; + else + fdc->drive = fdc->dor & 3; + fdc->rw_drive = fdc->params[0] & 3; + if (((fdc->command & 0x1F) == 7) || ((fdc->command & 0x1F) == 15)) + fdc->stat |= (1 << real_drive(fdc, fdc->drive)); + } + } + if (fdc->pnum == fdc->ptot) { + fdc_log("Got all params %02X\n", fdc->command); + fdc->interrupt = fdc->processed_cmd; + fdc->reset_stat = 0; + /* Disable timer if enabled. */ + timer_disable(&fdc->timer); + /* Start timer if needed at this point. */ + switch (fdc->interrupt & 0x1f) { + case 0x02: /* Read a track */ + case 0x03: /* Specify */ + case 0x0a: /* Read sector ID */ + case 0x05: /* Write data */ + case 0x06: /* Read data */ + case 0x09: /* Write deleted data */ + case 0x0c: /* Read deleted data */ + case 0x11: /* Scan equal */ + case 0x12: /* Perpendicular mode */ + case 0x16: /* Verify */ + case 0x19: /* Scan low or equal */ + case 0x1d: /* Scan high or equal */ + /* Do nothing. */ + break; + case 0x07: /* Recalibrate */ + case 0x0f: /* Seek */ + if (fdc->flags & FDC_FLAG_PCJR) + timer_set_delay_u64(&fdc->timer, 1000 * TIMER_USEC); + else + timer_set_delay_u64(&fdc->timer, 256 * TIMER_USEC); + break; + default: + timer_set_delay_u64(&fdc->timer, 256 * TIMER_USEC); + break; + } + /* Process the firt phase of the command. */ + switch (fdc->processed_cmd) { + case 0x02: /* Read a track */ + fdc_io_command_phase1(fdc, 0); + fdc->read_track_sector.id.c = fdc->params[1]; + fdc->read_track_sector.id.h = fdc->params[2]; + fdc->read_track_sector.id.r = 1; + fdc->read_track_sector.id.n = fdc->params[4]; + if ((fdc->head & 0x01) && !fdd_is_double_sided(real_drive(fdc, fdc->drive))) { + fdc_noidam(fdc); + return; + } + fdd_readsector(real_drive(fdc, fdc->drive), SECTOR_FIRST, fdc->params[1], fdc->head, fdc->rate, fdc->params[4]); + break; + case 0x03: /* Specify */ + fdc->stat = 0x80; + fdc->specify[0] = fdc->params[0]; + fdc->specify[1] = fdc->params[1]; + fdc->dma = (fdc->specify[1] & 1) ^ 1; + if (!fdc->dma) + dma_set_drq(fdc->dma_ch, 0); + break; + case 0x04: /*Sense drive status*/ + fdd_set_head(real_drive(fdc, fdc->drive), (fdc->params[0] & 4) ? 1 : 0); + break; + case 0x05: /* Write data */ + case 0x09: /* Write deleted data */ + fdc_io_command_phase1(fdc, 1); + if ((fdc->head & 0x01) && !fdd_is_double_sided(real_drive(fdc, fdc->drive))) { + fdc_noidam(fdc); + return; + } + fdd_writesector(real_drive(fdc, fdc->drive), fdc->sector, fdc->params[1], fdc->head, fdc->rate, fdc->params[4]); + break; + case 0x11: /* Scan equal */ + case 0x19: /* Scan low or equal */ + case 0x1d: /* Scan high or equal */ + fdc_io_command_phase1(fdc, 1); + if ((fdc->head & 0x01) && !fdd_is_double_sided(real_drive(fdc, fdc->drive))) { + fdc_noidam(fdc); + return; + } + fdd_comparesector(real_drive(fdc, fdc->drive), fdc->sector, fdc->params[1], fdc->head, fdc->rate, fdc->params[4]); + break; + case 0x16: /* Verify */ + if (fdc->params[0] & 0x80) + fdc->sc = fdc->params[7]; + fallthrough; + case 0x06: /* Read data */ + case 0x0c: /* Read deleted data */ + fdc_io_command_phase1(fdc, 0); + fdc_log("Reading sector (drive %i) (%i) (%i %i %i %i) (%i %i %i)\n", fdc->drive, fdc->params[0], fdc->params[1], fdc->params[2], fdc->params[3], fdc->params[4], fdc->params[5], fdc->params[6], fdc->params[7]); + if ((fdc->head & 0x01) && !fdd_is_double_sided(real_drive(fdc, fdc->drive))) { + fdc_noidam(fdc); + return; + } + if (((dma_mode(2) & 0x0C) == 0x00) && !(fdc->flags & FDC_FLAG_PCJR) && fdc->dma) { + /* DMA is in verify mode, treat this like a VERIFY command. */ + fdc_log("Verify-mode read!\n"); + fdc->tc = 1; + fdc->deleted |= 2; + } + fdd_readsector(real_drive(fdc, fdc->drive), fdc->sector, fdc->params[1], fdc->head, fdc->rate, fdc->params[4]); + break; - if (((fdc->command & 0x1f) == 0x02) || ((fdc->command & 0x1f) == 0x05) || - ((fdc->command & 0x1f) == 0x06) || ((fdc->command & 0x1f) == 0x0a) || - ((fdc->command & 0x1f) == 0x0c) || ((fdc->command & 0x1f) == 0x0d) || - ((fdc->command & 0x1f) == 0x11) || ((fdc->command & 0x1f) == 0x16) || - ((fdc->command & 0x1f) == 0x19) || ((fdc->command & 0x1f) == 0x1d)) - fdc->processed_cmd = fdc->command & 0x1f; - else - fdc->processed_cmd = fdc->command; + case 0x07: /* Recalibrate */ + fdc->rw_drive = fdc->params[0] & 3; + fdc->stat = (1 << real_drive(fdc, fdc->drive)); + if (!(fdc->flags & FDC_FLAG_PCJR)) + fdc->stat |= 0x80; + fdc->st0 = fdc->params[0] & 3; + fdc->st0 |= fdd_get_head(real_drive(fdc, fdc->drive)) ? 0x04 : 0x00; + fdc->st0 |= 0x80; + drive_num = real_drive(fdc, fdc->drive); + /* Three conditions under which the command should fail. */ + if ((drive_num >= FDD_NUM) || !fdd_get_flags(drive_num) || !motoron[drive_num] || fdd_track0(drive_num)) { + fdc_log("Failed recalibrate\n"); + if ((drive_num >= FDD_NUM) || !fdd_get_flags(drive_num) || !motoron[drive_num]) + fdc->st0 = 0x70 | (fdc->params[0] & 3); + else + fdc->st0 = 0x20 | (fdc->params[0] & 3); + fdc->pcn[fdc->params[0] & 3] = 0; + if (fdc->flags & FDC_FLAG_PCJR) { + fdc->fintr = 1; + fdc->interrupt = -4; + } else { + timer_disable(&fdc->timer); + fdc->interrupt = -3; + fdc_callback(fdc); + } + break; + } + if ((real_drive(fdc, fdc->drive) != 1) || fdc->drv2en) + fdc_seek(fdc, fdc->drive, -fdc->max_track); + fdc_log("Recalibrating...\n"); + fdc->seek_dir = fdc->step = 1; + break; + case 0x0a: /* Read sector ID */ + fdc_rate(fdc, fdc->drive); + fdc->head = (fdc->params[0] & 4) ? 1 : 0; + fdd_set_head(real_drive(fdc, fdc->drive), (fdc->params[0] & 4) ? 1 : 0); + if ((real_drive(fdc, fdc->drive) != 1) || fdc->drv2en) { + fdd_readaddress(real_drive(fdc, fdc->drive), fdc->head, fdc->rate); + if ((fdc->flags & FDC_FLAG_PCJR) || !fdc->dma) + fdc->stat = 0x70; + else + fdc->stat = 0x50; + } else + fdc_noidam(fdc); + break; + case 0x0d: /* Format */ + fdc_rate(fdc, fdc->drive); + fdc->head = (fdc->params[0] & 4) ? 1 : 0; + fdd_set_head(real_drive(fdc, fdc->drive), (fdc->params[0] & 4) ? 1 : 0); + fdc->gap = fdc->params[3]; + fdc->format_sectors = fdc->params[2]; + fdc->format_n = fdc->params[1]; + fdc->format_state = 1; + fdc->pos = 0; + fdc->stat = 0x10; + break; + case 0x0f: /* Seek */ + fdc->rw_drive = fdc->params[0] & 3; + fdc->stat = (1 << fdc->drive); + if (!(fdc->flags & FDC_FLAG_PCJR)) + fdc->stat |= 0x80; +#if 0 + fdc->head = (fdc->params[0] & 4) ? 1 : 0; +#endif + fdc->head = 0; /* TODO: See if this is correct. */ + fdc->st0 = fdc->params[0] & 0x03; + fdc->st0 |= (fdc->params[0] & 4); + fdc->st0 |= 0x80; + fdd_set_head(real_drive(fdc, fdc->drive), (fdc->params[0] & 4) ? 1 : 0); + drive_num = real_drive(fdc, fdc->drive); + /* Three conditions under which the command should fail. */ + if (!fdd_get_flags(drive_num) || (drive_num >= FDD_NUM) || !motoron[drive_num]) { + /* Yes, failed SEEK's still report success, unlike failed RECALIBRATE's. */ + fdc->st0 = 0x20 | (fdc->params[0] & 3); + if (fdc->command & 0x80) { + if (fdc->command & 0x40) + fdc->pcn[fdc->params[0] & 3] += fdc->params[1]; + else + fdc->pcn[fdc->params[0] & 3] -= fdc->params[1]; + } else + fdc->pcn[fdc->params[0] & 3] = fdc->params[1]; + if (fdc->flags & FDC_FLAG_PCJR) { + fdc->fintr = 1; + fdc->interrupt = -4; + } else { + timer_disable(&fdc->timer); + fdc->interrupt = -3; + fdc_callback(fdc); + } + break; + } + if (fdc->command & 0x80) { + if (fdc->params[1]) { + if (fdc->command & 0x40) { + /* Relative seek inwards. */ + fdc->seek_dir = 0; + fdc_seek(fdc, fdc->drive, fdc->params[1]); + fdc->pcn[fdc->params[0] & 3] += fdc->params[1]; + } else { + /* Relative seek outwards. */ + fdc->seek_dir = 1; + fdc_seek(fdc, fdc->drive, -fdc->params[1]); + fdc->pcn[fdc->params[0] & 3] -= fdc->params[1]; + } + fdc->step = 1; + } else { + fdc->st0 = 0x20 | (fdc->params[0] & 3); + if (fdc->flags & FDC_FLAG_PCJR) { + fdc->fintr = 1; + fdc->interrupt = -4; + } else { + timer_disable(&fdc->timer); + fdc->interrupt = -3; + fdc_callback(fdc); + } + break; + } + } else { + fdc_log("Seeking to track %i (PCN = %i)...\n", fdc->params[1], fdc->pcn[fdc->params[0] & 3]); + if ((fdc->params[1] - fdc->pcn[fdc->params[0] & 3]) == 0) { + fdc_log("Failed seek\n"); + fdc->st0 = 0x20 | (fdc->params[0] & 3); + if (fdc->flags & FDC_FLAG_PCJR) { + fdc->fintr = 1; + fdc->interrupt = -4; + } else { + timer_disable(&fdc->timer); + fdc->interrupt = -3; + fdc_callback(fdc); + } + break; + } + if (fdc->params[1] > fdc->pcn[fdc->params[0] & 3]) + fdc->seek_dir = 0; + else + fdc->seek_dir = 1; + fdc_seek(fdc, fdc->drive, fdc->params[1] - fdc->pcn[fdc->params[0] & 3]); + fdc->pcn[fdc->params[0] & 3] = fdc->params[1]; + fdc->step = 1; + } + break; + case 0x12: /* Perpendicular mode */ + fdc->stat = 0x80; + if (fdc->params[0] & 0x80) + fdc->perp = fdc->params[0] & 0x3f; + else { + fdc->perp &= 0xfc; + fdc->perp |= (fdc->params[0] & 0x03); + } + return; - switch (fdc->processed_cmd) { - case 0x01: /*Mode*/ - if (fdc->flags & FDC_FLAG_NSC) { - fdc->pnum = 0; - fdc->ptot = 4; - fdc->stat |= 0x90; - fdc->pos = 0; - fdc->format_state = 0; - } else - fdc_bad_command(fdc); - break; - case 0x02: /*Read track*/ - fdc->satisfying_sectors = 0; - fdc->sc = 0; - fdc->wrong_am = 0; - fdc->pnum = 0; - fdc->ptot = 8; - fdc->stat |= 0x90; - fdc->pos = 0; - fdc->mfm = (fdc->command & 0x40) ? 1:0; - break; - case 0x03: /*Specify*/ - fdc->pnum = 0; - fdc->ptot = 2; - fdc->stat |= 0x90; - break; - case 0x04: /*Sense drive status*/ - fdc->pnum = 0; - fdc->ptot = 1; - fdc->stat |= 0x90; - break; - case 0x05: /*Write data*/ - case 0x09: /*Write deleted data*/ - fdc->satisfying_sectors = 0; - fdc->sc = 0; - fdc->wrong_am = 0; - fdc->deleted = ((fdc->command&0x1F) == 9) ? 1 : 0; - fdc->pnum = 0; - fdc->ptot = 8; - fdc->stat |= 0x90; - fdc->pos = 0; - fdc->mfm = (fdc->command & 0x40) ? 1 : 0; - break; - case 0x06: /*Read data*/ - case 0x0c: /*Read deleted data*/ - case 0x11: /*Scan equal*/ - case 0x19: /*Scan low or equal*/ - case 0x16: /*Verify*/ - case 0x1d: /*Scan high or equal*/ - fdc->satisfying_sectors = 0; - fdc->sc = 0; - fdc->wrong_am = 0; - fdc->deleted = ((fdc->command&0x1F) == 0xC) ? 1 : 0; - if ((fdc->command&0x1F) == 0x16) fdc->deleted = 2; - fdc->deleted |= (fdc->command & 0x20); - fdc->pnum = 0; - fdc->ptot = 8; - fdc->stat |= 0x90; - fdc->pos = 0; - fdc->mfm = (fdc->command&0x40)?1:0; - break; - case 0x07: /*Recalibrate*/ - fdc->pnum=0; - fdc->ptot=1; - fdc->stat |= 0x90; - break; - case 0x08: /*Sense interrupt status*/ - fdc_log("fdc->fintr = %i, fdc->reset_stat = %i\n", fdc->fintr, fdc->reset_stat); - fdc->lastdrive = fdc->drive; - fdc->pos = 0; - fdc_sis(fdc); - break; - case 0x0a: /*Read sector ID*/ - fdc->pnum = 0; - fdc->ptot = 1; - fdc->stat |= 0x90; - fdc->pos = 0; - fdc->mfm = (fdc->command & 0x40) ? 1 : 0; - break; - case 0x0d: /*Format track*/ - fdc->pnum = 0; - fdc->ptot = 5; - fdc->stat |= 0x90; - fdc->pos = 0; - fdc->mfm = (fdc->command & 0x40) ? 1:0; - fdc->format_state = 0; - break; - case 0x0e: /*Dump registers*/ - fdc->lastdrive = fdc->drive; - fdc->interrupt = 0x0e; - fdc->pos = 0; - fdc_callback(fdc); - break; - case 0x0f: /*Seek*/ - fdc->pnum = 0; - fdc->ptot = 2; - fdc->stat |= 0x90; - break; - case 0x18: /*NSC*/ - if (!(fdc->flags & FDC_FLAG_NSC)) { - fdc_bad_command(fdc); - break; - } - /*FALLTHROUGH*/ - case 0x10: /*Get version*/ - case 0x14: /*Unlock*/ - case 0x94: /*Lock*/ - fdc->lastdrive = fdc->drive; - fdc->interrupt = fdc->command; - fdc->pos = 0; - fdc_callback(fdc); - break; - case 0x12: /*Set perpendicular mode*/ - if ((fdc->flags & FDC_FLAG_AT) && !(fdc->flags & FDC_FLAG_PCJR)) { - fdc->pnum=0; - fdc->ptot=1; - fdc->stat |= 0x90; - fdc->pos=0; - } else - fdc_bad_command(fdc); - break; - case 0x13: /*Configure*/ - fdc->pnum=0; - fdc->ptot=3; - fdc->stat |= 0x90; - fdc->pos=0; - break; - default: - fdc_bad_command(fdc); - break; - } - } else { - fdc->stat = 0x10 | (fdc->stat & 0xf); - fdc->params[fdc->pnum++]=val; - if (fdc->pnum == 1) { - if (command_has_drivesel[fdc->command & 0x1F]) { - if (fdc->flags & FDC_FLAG_PCJR) - fdc->drive = 0; - else - fdc->drive = fdc->dor & 3; - fdc->rw_drive = fdc->params[0] & 3; - if (((fdc->command & 0x1F) == 7) || ((fdc->command & 0x1F) == 15)) - fdc->stat |= (1 << real_drive(fdc, fdc->drive)); - } - } - if (fdc->pnum == fdc->ptot) { - fdc_log("Got all params %02X\n", fdc->command); - fdc->interrupt = fdc->processed_cmd; - fdc->reset_stat = 0; - /* Disable timer if enabled. */ - timer_disable(&fdc->timer); - /* Start timer if needed at this point. */ - switch (fdc->interrupt & 0x1f) { - case 0x02: /* Read a track */ - case 0x03: /* Specify */ - case 0x0a: /* Read sector ID */ - case 0x05: /* Write data */ - case 0x06: /* Read data */ - case 0x09: /* Write deleted data */ - case 0x0c: /* Read deleted data */ - case 0x11: /* Scan equal */ - case 0x12: /* Perpendicular mode */ - case 0x16: /* Verify */ - case 0x19: /* Scan low or equal */ - case 0x1d: /* Scan high or equal */ - /* Do nothing. */ - break; - case 0x07: /* Recalibrate */ - case 0x0f: /* Seek */ - if (fdc->flags & FDC_FLAG_PCJR) - timer_set_delay_u64(&fdc->timer, 1000 * TIMER_USEC); - else - timer_set_delay_u64(&fdc->timer, 256 * TIMER_USEC); - break; - default: - timer_set_delay_u64(&fdc->timer, 256 * TIMER_USEC); - break; - } - /* Process the firt phase of the command. */ - switch (fdc->processed_cmd) { - case 0x02: /* Read a track */ - fdc_io_command_phase1(fdc, 0); - fdc->read_track_sector.id.c = fdc->params[1]; - fdc->read_track_sector.id.h = fdc->params[2]; - fdc->read_track_sector.id.r = 1; - fdc->read_track_sector.id.n = fdc->params[4]; - if ((fdc->head & 0x01) && !fdd_is_double_sided(real_drive(fdc, fdc->drive))) { - fdc_noidam(fdc); - return; - } - fdd_readsector(real_drive(fdc, fdc->drive), SECTOR_FIRST, fdc->params[1], fdc->head, fdc->rate, fdc->params[4]); - break; - case 0x03: /* Specify */ - fdc->stat = 0x80; - fdc->specify[0] = fdc->params[0]; - fdc->specify[1] = fdc->params[1]; - fdc->dma = (fdc->specify[1] & 1) ^ 1; - break; - case 0x04: /*Sense drive status*/ - fdd_set_head(real_drive(fdc, fdc->drive), (fdc->params[0] & 4) ? 1 : 0); - break; - case 0x05: /* Write data */ - case 0x09: /* Write deleted data */ - fdc_io_command_phase1(fdc, 1); - if ((fdc->head & 0x01) && !fdd_is_double_sided(real_drive(fdc, fdc->drive))) { - fdc_noidam(fdc); - return; - } - fdd_writesector(real_drive(fdc, fdc->drive), fdc->sector, fdc->params[1], fdc->head, fdc->rate, fdc->params[4]); - break; - case 0x11: /* Scan equal */ - case 0x19: /* Scan low or equal */ - case 0x1d: /* Scan high or equal */ - fdc_io_command_phase1(fdc, 1); - if ((fdc->head & 0x01) && !fdd_is_double_sided(real_drive(fdc, fdc->drive))) { - fdc_noidam(fdc); - return; - } - fdd_comparesector(real_drive(fdc, fdc->drive), fdc->sector, fdc->params[1], fdc->head, fdc->rate, fdc->params[4]); - break; - case 0x16: /* Verify */ - if (fdc->params[0] & 0x80) - fdc->sc = fdc->params[7]; - /*FALLTHROUGH*/ - case 0x06: /* Read data */ - case 0x0c: /* Read deleted data */ - fdc_io_command_phase1(fdc, 0); - fdc_log("Reading sector (drive %i) (%i) (%i %i %i %i) (%i %i %i)\n", fdc->drive, fdc->params[0], fdc->params[1], fdc->params[2], fdc->params[3], fdc->params[4], fdc->params[5], fdc->params[6], fdc->params[7]); - if ((fdc->head & 0x01) && !fdd_is_double_sided(real_drive(fdc, fdc->drive))) { - fdc_noidam(fdc); - return; - } - if (((dma_mode(2) & 0x0C) == 0x00) && !(fdc->flags & FDC_FLAG_PCJR) && fdc->dma) { - /* DMA is in verify mode, treat this like a VERIFY command. */ - fdc_log("Verify-mode read!\n"); - fdc->tc = 1; - fdc->deleted |= 2; - } - fdd_readsector(real_drive(fdc, fdc->drive), fdc->sector, fdc->params[1], fdc->head, fdc->rate, fdc->params[4]); - break; - - case 0x07: /* Recalibrate */ - fdc->rw_drive = fdc->params[0] & 3; - fdc->stat = (1 << real_drive(fdc, fdc->drive)); - if (!(fdc->flags & FDC_FLAG_PCJR)) - fdc->stat |= 0x80; - fdc->st0 = fdc->params[0] & 3; - fdc->st0 |= fdd_get_head(real_drive(fdc, fdc->drive)) ? 0x04 : 0x00; - fdc->st0 |= 0x80; - drive_num = real_drive(fdc, fdc->drive); - /* Three conditions under which the command should fail. */ - if ((drive_num >= FDD_NUM) || !fdd_get_flags(drive_num) || !motoron[drive_num] || fdd_track0(drive_num)) { - fdc_log("Failed recalibrate\n"); - if ((drive_num >= FDD_NUM) || !fdd_get_flags(drive_num) || !motoron[drive_num]) - fdc->st0 = 0x70 | (fdc->params[0] & 3); - else - fdc->st0 = 0x20 | (fdc->params[0] & 3); - fdc->pcn[fdc->params[0] & 3] = 0; - if (fdc->flags & FDC_FLAG_PCJR) { - fdc->fintr = 1; - fdc->interrupt = -4; - } else { - timer_disable(&fdc->timer); - fdc->interrupt = -3; - fdc_callback(fdc); - } - break; - } - if ((real_drive(fdc, fdc->drive) != 1) || fdc->drv2en) - fdc_seek(fdc, fdc->drive, -fdc->max_track); - fdc_log("Recalibrating...\n"); - fdc->seek_dir = fdc->step = 1; - break; - case 0x0a: /* Read sector ID */ - fdc_rate(fdc, fdc->drive); - fdc->head = (fdc->params[0] & 4) ? 1 : 0; - fdd_set_head(real_drive(fdc, fdc->drive), (fdc->params[0] & 4) ? 1 : 0); - if ((real_drive(fdc, fdc->drive) != 1) || fdc->drv2en) { - fdd_readaddress(real_drive(fdc, fdc->drive), fdc->head, fdc->rate); - if ((fdc->flags & FDC_FLAG_PCJR) || !fdc->dma) - fdc->stat = 0x70; - else - fdc->stat = 0x50; - } - else - fdc_noidam(fdc); - break; - case 0x0d: /* Format */ - fdc_rate(fdc, fdc->drive); - fdc->head = (fdc->params[0] & 4) ? 1 : 0; - fdd_set_head(real_drive(fdc, fdc->drive), (fdc->params[0] & 4) ? 1 : 0); - fdc->gap = fdc->params[3]; - fdc->format_sectors = fdc->params[2]; - fdc->format_n = fdc->params[1]; - fdc->format_state = 1; - fdc->pos = 0; - fdc->stat = 0x10; - break; - case 0x0f: /* Seek */ - fdc->rw_drive = fdc->params[0] & 3; - fdc->stat = (1 << fdc->drive); - if (!(fdc->flags & FDC_FLAG_PCJR)) - fdc->stat |= 0x80; - /* fdc->head = (fdc->params[0] & 4) ? 1 : 0; */ - fdc->head = 0; /* TODO: See if this is correct. */ - fdc->st0 = fdc->params[0] & 0x03; - fdc->st0 |= (fdc->params[0] & 4); - fdc->st0 |= 0x80; - fdd_set_head(real_drive(fdc, fdc->drive), (fdc->params[0] & 4) ? 1 : 0); - drive_num = real_drive(fdc, fdc->drive); - /* Three conditions under which the command should fail. */ - if (!fdd_get_flags(drive_num) || (drive_num >= FDD_NUM) || !motoron[drive_num]) { - /* Yes, failed SEEK's still report success, unlike failed RECALIBRATE's. */ - fdc->st0 = 0x20 | (fdc->params[0] & 3); - if (fdc->command & 0x80) { - if (fdc->command & 0x40) - fdc->pcn[fdc->params[0] & 3] += fdc->params[1]; - else - fdc->pcn[fdc->params[0] & 3] -= fdc->params[1]; - } else - fdc->pcn[fdc->params[0] & 3] = fdc->params[1]; - if (fdc->flags & FDC_FLAG_PCJR) { - fdc->fintr = 1; - fdc->interrupt = -4; - } else { - timer_disable(&fdc->timer); - fdc->interrupt = -3; - fdc_callback(fdc); - } - break; - } - if (fdc->command & 0x80) { - if (fdc->params[1]) { - if (fdc->command & 0x40) { - /* Relative seek inwards. */ - fdc->seek_dir = 0; - fdc_seek(fdc, fdc->drive, fdc->params[1]); - fdc->pcn[fdc->params[0] & 3] += fdc->params[1]; - } else { - /* Relative seek outwards. */ - fdc->seek_dir = 1; - fdc_seek(fdc, fdc->drive, -fdc->params[1]); - fdc->pcn[fdc->params[0] & 3] -= fdc->params[1]; - } - fdc->step = 1; - } else { - fdc->st0 = 0x20 | (fdc->params[0] & 3); - if (fdc->flags & FDC_FLAG_PCJR) { - fdc->fintr = 1; - fdc->interrupt = -4; - } else { - timer_disable(&fdc->timer); - fdc->interrupt = -3; - fdc_callback(fdc); - } - break; - } - } else { - fdc_log("Seeking to track %i (PCN = %i)...\n", fdc->params[1], fdc->pcn[fdc->params[0] & 3]); - if ((fdc->params[1] - fdc->pcn[fdc->params[0] & 3]) == 0) { - fdc_log("Failed seek\n"); - fdc->st0 = 0x20 | (fdc->params[0] & 3); - if (fdc->flags & FDC_FLAG_PCJR) { - fdc->fintr = 1; - fdc->interrupt = -4; - } else { - timer_disable(&fdc->timer); - fdc->interrupt = -3; - fdc_callback(fdc); - } - break; - } - if (fdc->params[1] > fdc->pcn[fdc->params[0] & 3]) - fdc->seek_dir = 0; - else - fdc->seek_dir = 1; - fdc_seek(fdc, fdc->drive, fdc->params[1] - fdc->pcn[fdc->params[0] & 3]); - fdc->pcn[fdc->params[0] & 3] = fdc->params[1]; - fdc->step = 1; - } - break; - case 0x12: /* Perpendicular mode */ - fdc->stat = 0x80; - if (fdc->params[0] & 0x80) - fdc->perp = fdc->params[0] & 0x3f; - else { - fdc->perp &= 0xfc; - fdc->perp |= (fdc->params[0] & 0x03); - } - return; - } - } else - fdc->stat = 0x90 | (fdc->stat & 0xf); - } - return; - case 7: - if (!(fdc->flags & FDC_FLAG_TOSHIBA) && !(fdc->flags & FDC_FLAG_AT) && !(fdc->flags & FDC_FLAG_UMC)) - return; - fdc->rate = val & 0x03; - if (fdc->flags & FDC_FLAG_PS1) - fdc->noprec = !!(val & 0x04); - return; + default: + break; + } + } else + fdc->stat = 0x90 | (fdc->stat & 0xf); + } + return; + case 7: + if (!(fdc->flags & FDC_FLAG_TOSHIBA) && !(fdc->flags & FDC_FLAG_AT) && !(fdc->flags & FDC_FLAG_UMC)) + return; + fdc->rate = val & 0x03; + if (fdc->flags & FDC_FLAG_PS1) + fdc->noprec = !!(val & 0x04); + return; + + default: + break; } } - uint8_t fdc_read(uint16_t addr, void *priv) { - fdc_t *fdc = (fdc_t *) priv; + fdc_t *fdc = (fdc_t *) priv; uint8_t ret; - int drive; + int drive = 0; cycles -= ISA_CYCLES(8); switch (addr & 7) { - case 0: /* STA */ - if (fdc->flags & FDC_FLAG_PS1) { - drive = real_drive(fdc, fdc->dor & 3); - ret = 0x00; - /* TODO: - Bit 2: INDEX (best return always 0 as it goes by very fast) - Bit 6: DRQ - */ - if (fdc->seek_dir) /* nDIRECTION */ - ret |= 0x01; - if (writeprot[drive]) /* WRITEPROT */ - ret |= 0x02; - if (!fdd_get_head(drive)) /* nHDSEL */ - ret |= 0x08; - if (fdd_track0(drive)) /* TRK0 */ - ret |= 0x10; - if (fdc->step) /* STEP */ - ret |= 0x20; - if (fdc->fintr || fdc->reset_stat) /* INTR */ - ret |= 0x80; - } else - ret = 0xff; - break; - case 1: /* STB */ - if (fdc->flags & FDC_FLAG_PS1) { - drive = real_drive(fdc, fdc->dor & 3); - ret = 0x00; - /* -Drive 2 Installed */ - if (!fdd_get_type(1)) - ret |= 0x80; - /* -Drive Select 1,0 */ - switch (drive) { - case 0: - ret |= 0x43; - break; - case 1: - ret |= 0x23; - break; - case 2: - ret |= 0x62; - break; - case 3: - ret |= 0x61; - break; - } - } else { - if (is486 || !fdc->enable_3f1) - ret = 0xff; - else{ - if(fdc->flags & FDC_FLAG_UMC) - { - drive = real_drive(fdc, fdc->dor & 1); - ret = !fdd_is_dd(drive) ? ((fdc->dor & 1) ? 2 : 1) : 0; - } - else { - ret = 0x70; + case 0: /* STA */ + if (fdc->flags & FDC_FLAG_PS1) { + drive = real_drive(fdc, fdc->dor & 3); + ret = 0x00; + /* TODO: + Bit 2: INDEX (best return always 0 as it goes by very fast) + */ + if (fdc->seek_dir) /* nDIRECTION */ + ret |= 0x01; + if (writeprot[drive]) /* WRITEPROT */ + ret |= 0x02; + if (!fdd_get_head(drive)) /* nHDSEL */ + ret |= 0x08; + if (fdd_track0(drive)) /* TRK0 */ + ret |= 0x10; + if (fdc->step) /* STEP */ + ret |= 0x20; + if (dma_get_drq(fdc->dma_ch)) /* DRQ */ + ret |= 0x40; + if (fdc->fintr || fdc->reset_stat) /* INTR */ + ret |= 0x80; + } else + ret = 0xff; + break; + case 1: /* STB */ + if (fdc->flags & FDC_FLAG_PS1) { + drive = real_drive(fdc, fdc->dor & 3); + ret = 0x00; + /* -Drive 2 Installed */ + if (!fdd_get_type(1)) + ret |= 0x80; + /* -Drive Select 1,0 */ + switch (drive) { + case 0: + ret |= 0x43; + break; + case 1: + ret |= 0x23; + break; + case 2: + ret |= 0x62; + break; + case 3: + ret |= 0x61; + break; - drive = real_drive(fdc, fdc->dor & 3); + default: + break; + } + } else { + if (is486 || !fdc->enable_3f1) + ret = 0xff; + else { + if (fdc->flags & FDC_FLAG_UMC) { + drive = real_drive(fdc, fdc->dor & 1); + ret = !fdd_is_dd(drive) ? ((fdc->dor & 1) ? 2 : 1) : 0; + } else { + ret = 0x70; - if (drive) - ret &= ~0x40; - else - ret &= ~0x20; + drive = real_drive(fdc, fdc->dor & 3); - if (fdc->dor & 0x10) - ret |= 1; - if (fdc->dor & 0x20) - ret |= 2; - } - } - } - break; - case 2: - ret = fdc->dor; - break; - case 3: - drive = real_drive(fdc, fdc->dor & 3); - if (fdc->flags & FDC_FLAG_PS1) { - /* PS/1 Model 2121 seems return drive type in port - * 0x3f3, despite the 82077AA fdc_t not implementing - * this. This is presumably implemented outside the - * fdc_t on one of the motherboard's support chips. - * - * Confirmed: 00=1.44M 3.5 - * 10=2.88M 3.5 - * 20=1.2M 5.25 - * 30=1.2M 5.25 - * - * as reported by Configur.exe. - */ - if (fdd_is_525(drive)) - ret = 0x20; - else if (fdd_is_ed(drive)) - ret = 0x10; - else - ret = 0x00; - } else if (!fdc->enh_mode) - ret = 0x20; - else - ret = fdc->rwc[drive] << 4; - break; - case 4: /*Status*/ - ret = fdc->stat; - break; - case 5: /*Data*/ - if ((fdc->stat & 0xf0) == 0xf0) { - fdc->stat &= ~0x80; - if ((fdc->flags & FDC_FLAG_PCJR) || !fdc->fifo) { - fdc->data_ready = 0; - ret = fdc->dat; - } else - ret = fdc_fifo_buf_read(fdc); - break; - } - fdc->stat &= ~0x80; - if (fdc->paramstogo) { - fdc_log("%i parameters to go\n", fdc->paramstogo); - fdc->paramstogo--; - ret = fdc->res[10 - fdc->paramstogo]; - if (!fdc->paramstogo) - fdc->stat = 0x80; - else - fdc->stat |= 0xC0; - } else { - if (lastbyte) - fdc->stat = 0x80; - lastbyte = 0; - ret = fdc->dat; - fdc->data_ready = 0; - } - fdc->stat &= 0xf0; - break; - case 7: /*Disk change*/ - drive = real_drive(fdc, fdc->dor & 3); + if (drive) + ret &= ~0x40; + else + ret &= ~0x20; - if (fdc->flags & FDC_FLAG_PS1) { - if (fdc->dor & (0x10 << drive)) { - ret = (fdd_changed[drive] || drive_empty[drive]) ? 0x00 : 0x80; - ret |= (fdc->dor & 0x08); - ret |= (fdc->noprec << 2); - ret |= (fdc->rate & 0x03); - } else - ret = 0x00; - } else { - if (fdc->dor & (0x10 << drive)) { - if ((drive == 1) && (fdc->flags & FDC_FLAG_TOSHIBA)) - ret = 0x00; - else - ret = (fdd_changed[drive] || drive_empty[drive]) ? 0x80 : 0x00; - } else - ret = 0x00; - if (fdc->flags & FDC_FLAG_DISKCHG_ACTLOW) /*PC2086/3086 seem to reverse this bit*/ - ret ^= 0x80; + if (fdc->dor & 0x10) + ret |= 1; + if (fdc->dor & 0x20) + ret |= 2; + } + } + } + break; + case 2: + ret = fdc->dor; + break; + case 3: + drive = real_drive(fdc, fdc->dor & 3); + if (fdc->flags & FDC_FLAG_PS1) { + /* PS/1 Model 2121 seems return drive type in port + * 0x3f3, despite the 82077AA fdc_t not implementing + * this. This is presumably implemented outside the + * fdc_t on one of the motherboard's support chips. + * + * Confirmed: 00=1.44M 3.5 + * 10=2.88M 3.5 + * 20=1.2M 5.25 + * 30=1.2M 5.25 + * + * as reported by Configur.exe. + */ + if (fdd_is_525(drive)) + ret = 0x20; + else if (fdd_is_ed(drive)) + ret = 0x10; + else + ret = 0x00; + } else if (!fdc->enh_mode) + ret = 0x20; + else + ret = fdc->rwc[drive] << 4; + break; + case 4: /*Status*/ + ret = fdc->stat; + break; + case 5: /*Data*/ + if ((fdc->stat & 0xf0) == 0xf0) { + fdc->stat &= ~0x80; + if ((fdc->flags & FDC_FLAG_PCJR) || !fdc->fifo) { + fdc->data_ready = 0; + ret = fdc->dat; + } else + ret = fdc_fifo_buf_read(fdc); + break; + } + fdc->stat &= ~0x80; + if (fdc->paramstogo) { + fdc_log("%i parameters to go\n", fdc->paramstogo); + fdc->paramstogo--; + ret = fdc->res[10 - fdc->paramstogo]; + if (!fdc->paramstogo) + fdc->stat = 0x80; + else + fdc->stat |= 0xC0; + } else { + if (lastbyte) + fdc->stat = 0x80; + lastbyte = 0; + ret = fdc->dat; + fdc->data_ready = 0; + } + fdc->stat &= 0xf0; + break; + case 7: /*Disk change*/ + drive = real_drive(fdc, fdc->dor & 3); - /* 0 = ????, 1 = Ext. FDD off, 2 = Ext. FDD = FDD A, 3 = Ext. FDD = FDD B */ - if (fdc->flags & FDC_FLAG_TOSHIBA) { - ret |= (3 << 5); - ret |= 0x01; - } else - ret |= 0x7F; - } + if (fdc->flags & FDC_FLAG_PS1) { + if (fdc->dor & (0x10 << drive)) { + ret = (fdd_changed[drive] || drive_empty[drive]) ? 0x00 : 0x80; + ret |= (fdc->dor & 0x08); + ret |= (fdc->noprec << 2); + ret |= (fdc->rate & 0x03); + } else + ret = 0x00; + } else { + if (fdc->dor & (0x10 << drive)) { + if ((drive == 1) && (fdc->flags & FDC_FLAG_TOSHIBA)) + ret = 0x00; + else + ret = (fdd_changed[drive] || drive_empty[drive]) ? 0x80 : 0x00; + } else + ret = 0x00; + if (fdc->flags & FDC_FLAG_DISKCHG_ACTLOW) /*PC2086/3086 seem to reverse this bit*/ + ret ^= 0x80; - fdc->step = 0; - break; - default: - ret = 0xFF; + /* 0 = ????, 1 = Ext. FDD off, 2 = Ext. FDD = FDD A, 3 = Ext. FDD = FDD B */ + if (fdc->flags & FDC_FLAG_TOSHIBA) { + ret |= (3 << 5); + ret |= 0x01; + } else + ret |= 0x7F; + } + + fdc->step = 0; + break; + default: + ret = 0xFF; } // fdc_log("Read FDC %04X %02X\n", addr, ret); fdc_log("[%04X:%08X] Read FDC %04X %02X [%i:%02X]\n", CS, cpu_state.pc, addr, ret, drive, fdc->dor & (0x10 << drive)); @@ -1451,68 +1458,67 @@ fdc_poll_common_finish(fdc_t *fdc, int compare, int st5) { fdc_int(fdc, 1); if (!(fdc->flags & FDC_FLAG_PS1)) - fdc->fintr = 0; + fdc->fintr = 0; fdc->stat = 0xD0; fdc->st0 = fdc->res[4] = (fdd_get_head(real_drive(fdc, fdc->drive)) ? 4 : 0) | fdc->rw_drive; - fdc->res[5] = st5; - fdc->res[6] = 0; + fdc->res[5] = st5; + fdc->res[6] = 0; if (fdc->error) { - fdc->error = 0; + fdc->error = 0; fdc->st0 |= 0x40; - fdc->res[4] |= 0x40; - fdc->res[5] |= fdc->st5; - fdc->res[6] |= fdc->st6; + fdc->res[4] |= 0x40; + fdc->res[5] |= fdc->st5; + fdc->res[6] |= fdc->st6; } if (fdc->wrong_am) { - fdc->res[6] |= 0x40; - fdc->wrong_am = 0; + fdc->res[6] |= 0x40; + fdc->wrong_am = 0; } if (compare == 1) { - if (!fdc->satisfying_sectors) - fdc->res[6] |= 4; - else if (fdc->satisfying_sectors == (fdc->params[5] << ((fdc->command & 80) ? 1 : 0))) - fdc->res[6] |= 8; + if (!fdc->satisfying_sectors) + fdc->res[6] |= 4; + else if (fdc->satisfying_sectors == (fdc->params[5] << ((fdc->command & 80) ? 1 : 0))) + fdc->res[6] |= 8; } else if (compare == 2) { - if (fdc->satisfying_sectors & 1) - fdc->res[5] |= 0x20; - if (fdc->satisfying_sectors & 2) { - fdc->res[5] |= 0x20; - fdc->res[6] |= 0x20; - } - if (fdc->satisfying_sectors & 4) - fdc->res[5] |= 0x04; - if (fdc->satisfying_sectors & 8) { - fdc->res[5] |= 0x04; - fdc->res[6] |= 0x02; - } - if (fdc->satisfying_sectors & 0x10) { - fdc->res[5] |= 0x04; - fdc->res[6] |= 0x10; - } + if (fdc->satisfying_sectors & 1) + fdc->res[5] |= 0x20; + if (fdc->satisfying_sectors & 2) { + fdc->res[5] |= 0x20; + fdc->res[6] |= 0x20; + } + if (fdc->satisfying_sectors & 4) + fdc->res[5] |= 0x04; + if (fdc->satisfying_sectors & 8) { + fdc->res[5] |= 0x04; + fdc->res[6] |= 0x02; + } + if (fdc->satisfying_sectors & 0x10) { + fdc->res[5] |= 0x04; + fdc->res[6] |= 0x10; + } } - fdc->res[7]=fdc->rw_track; - fdc->res[8]=fdc->head; - fdc->res[9]=fdc->sector; - fdc->res[10]=fdc->params[4]; - fdc_log("Read/write finish (%02X %02X %02X %02X %02X %02X %02X)\n" , fdc->res[4], fdc->res[5], fdc->res[6], fdc->res[7], fdc->res[8], fdc->res[9], fdc->res[10]); + fdc->res[7] = fdc->rw_track; + fdc->res[8] = fdc->head; + fdc->res[9] = fdc->sector; + fdc->res[10] = fdc->params[4]; + fdc_log("Read/write finish (%02X %02X %02X %02X %02X %02X %02X)\n", fdc->res[4], fdc->res[5], fdc->res[6], fdc->res[7], fdc->res[8], fdc->res[9], fdc->res[10]); ui_sb_update_icon(SB_FLOPPY | real_drive(fdc, fdc->drive), 0); fdc->paramstogo = 7; + dma_set_drq(fdc->dma_ch, 0); } - static void fdc_poll_readwrite_finish(fdc_t *fdc, int compare) { if ((fdc->interrupt == 5) || (fdc->interrupt == 9)) - fdd_do_writeback(real_drive(fdc, fdc->drive)); + fdd_do_writeback(real_drive(fdc, fdc->drive)); - fdc->inread = 0; + fdc->inread = 0; fdc->interrupt = -2; fdc_poll_common_finish(fdc, compare, 0); } - static void fdc_no_dma_end(fdc_t *fdc, int compare) { @@ -1521,369 +1527,387 @@ fdc_no_dma_end(fdc_t *fdc, int compare) fdc_poll_common_finish(fdc, compare, 0x80); } - static void fdc_callback(void *priv) { - fdc_t *fdc = (fdc_t *) priv; - int compare = 0; - int drive_num = 0; - int old_sector = 0; + fdc_t *fdc = (fdc_t *) priv; + int compare = 0; + int drive_num = 0; + int old_sector = 0; fdc_log("fdc_callback(): %i\n", fdc->interrupt); switch (fdc->interrupt) { - case -3: /*End of command with interrupt*/ - case -4: /*Recalibrate/seek interrupt (PCjr only)*/ - fdc_int(fdc, fdc->interrupt & 1); - fdc->stat = (fdc->stat & 0xf) | 0x80; - return; - case -2: /*End of command*/ - fdc->stat = (fdc->stat & 0xf) | 0x80; - return; - case -1: /*Reset*/ - fdc_int(fdc, 1); - fdc->fintr = 0; - memset(fdc->pcn, 0, 4 * sizeof(int)); - fdc->reset_stat = 4; - return; - case 0x01: /* Mode */ - fdc->stat=0x80; - fdc->densel_force = (fdc->params[2] & 0xC0) >> 6; - return; - case 0x02: /* Read track */ - ui_sb_update_icon(SB_FLOPPY | real_drive(fdc, fdc->drive), 1); - fdc->eot[fdc->drive]--; - fdc->read_track_sector.id.r++; - if (!fdc->eot[fdc->drive] || fdc->tc) { - fdc_poll_readwrite_finish(fdc, 2); - return; - } else { - fdd_readsector(real_drive(fdc, fdc->drive), SECTOR_NEXT, fdc->rw_track, fdc->head, fdc->rate, fdc->params[4]); - if ((fdc->flags & FDC_FLAG_PCJR) || !fdc->dma) - fdc->stat = 0x70; - else - fdc->stat = 0x50; - } - fdc->inread = 1; - return; - case 0x04: /* Sense drive status */ - fdc->res[10] = (fdc->params[0] & 7) | 0x20; - if (fdd_is_double_sided(real_drive(fdc, fdc->drive))) - fdc->res[10] |= 0x08; - if ((real_drive(fdc, fdc->drive) != 1) || fdc->drv2en) { - if (fdd_track0(real_drive(fdc, fdc->drive))) - fdc->res[10] |= 0x10; - } - if (writeprot[fdc->drive]) - fdc->res[10] |= 0x40; + case -3: /*End of command with interrupt*/ + case -4: /*Recalibrate/seek interrupt (PCjr only)*/ + fdc_int(fdc, fdc->interrupt & 1); + fdc->stat = (fdc->stat & 0xf) | 0x80; + return; + case -2: /*End of command*/ + fdc->stat = (fdc->stat & 0xf) | 0x80; + return; + case -1: /*Reset*/ + fdc_int(fdc, 1); + fdc->fintr = 0; + memset(fdc->pcn, 0, 4 * sizeof(int)); + fdc->reset_stat = 4; + return; + case 0x01: /* Mode */ + fdc->stat = 0x80; + fdc->densel_force = (fdc->params[2] & 0xC0) >> 6; + return; + case 0x02: /* Read track */ + ui_sb_update_icon(SB_FLOPPY | real_drive(fdc, fdc->drive), 1); + fdc->eot[fdc->drive]--; + fdc->read_track_sector.id.r++; + if (!fdc->eot[fdc->drive] || fdc->tc) { + fdc_poll_readwrite_finish(fdc, 2); + return; + } else { + fdd_readsector(real_drive(fdc, fdc->drive), SECTOR_NEXT, fdc->rw_track, fdc->head, fdc->rate, fdc->params[4]); + if ((fdc->flags & FDC_FLAG_PCJR) || !fdc->dma) + fdc->stat = 0x70; + else { + dma_set_drq(fdc->dma_ch, 1); + fdc->stat = 0x50; + } + } + fdc->inread = 1; + return; + case 0x04: /* Sense drive status */ + fdc->res[10] = (fdc->params[0] & 7) | 0x20; + if (fdd_is_double_sided(real_drive(fdc, fdc->drive))) + fdc->res[10] |= 0x08; + if ((real_drive(fdc, fdc->drive) != 1) || fdc->drv2en) { + if (fdd_track0(real_drive(fdc, fdc->drive))) + fdc->res[10] |= 0x10; + } + if (writeprot[fdc->drive]) + fdc->res[10] |= 0x40; - fdc->stat = (fdc->stat & 0xf) | 0xd0; - fdc->paramstogo = 1; - fdc->interrupt = 0; - return; - case 0x05: /* Write data */ - case 0x09: /* Write deleted data */ - case 0x06: /* Read data */ - case 0x0c: /* Read deleted data */ - case 0x11: /* Scan equal */ - case 0x19: /* Scan low or equal */ - case 0x1c: /* Verify */ - case 0x1d: /* Scan high or equal */ - if ((fdc->interrupt == 0x11) || (fdc->interrupt == 0x19) || (fdc->interrupt == 0x1D)) - compare = 1; - else - compare = 0; - if ((fdc->interrupt == 6) || (fdc->interrupt == 0xC)) { - if (fdc->wrong_am && !(fdc->deleted & 0x20)) { - /* Mismatching data address mark and no skip, set TC. */ - fdc->tc = 1; - } - } - old_sector = fdc->sector; - if (fdc->tc) { - /* This is needed so that the correct results are returned - in case of TC. */ - if (fdc->sector == fdc->params[5]) { - if (!(fdc->command & 0x80)) { - fdc->rw_track++; - fdc->sector = 1; - } else { - if (fdc->head) - fdc->rw_track++; + fdc->stat = (fdc->stat & 0xf) | 0xd0; + fdc->paramstogo = 1; + fdc->interrupt = 0; + return; + case 0x05: /* Write data */ + case 0x09: /* Write deleted data */ + case 0x06: /* Read data */ + case 0x0c: /* Read deleted data */ + case 0x11: /* Scan equal */ + case 0x19: /* Scan low or equal */ + case 0x1c: /* Verify */ + case 0x1d: /* Scan high or equal */ + if ((fdc->interrupt == 0x11) || (fdc->interrupt == 0x19) || (fdc->interrupt == 0x1D)) + compare = 1; + else + compare = 0; + if ((fdc->interrupt == 6) || (fdc->interrupt == 0xC)) { + if (fdc->wrong_am && !(fdc->deleted & 0x20)) { + /* Mismatching data address mark and no skip, set TC. */ + fdc->tc = 1; + } + } + old_sector = fdc->sector; + if (fdc->tc) { + /* This is needed so that the correct results are returned + in case of TC. */ + if (fdc->sector == fdc->params[5]) { + if (!(fdc->command & 0x80)) { + fdc->rw_track++; + fdc->sector = 1; + } else { + if (fdc->head) + fdc->rw_track++; - fdc->head ^= 1; - fdd_set_head(real_drive(fdc, fdc->drive), fdc->head); - fdc->sector = 1; - } - } else - fdc->sector++; - fdc_poll_readwrite_finish(fdc, compare); - return; - } - if ((fdc->interrupt == 0x16) && (fdc->params[0] & 0x80)) { - /* VERIFY command, EC set */ - fdc->sc--; - if (!fdc->sc) { - fdc->sector++; - fdc_poll_readwrite_finish(fdc, 0); - return; - } - /* The rest is processed normally per MT flag and EOT. */ - } else if ((fdc->interrupt == 0x16) && !(fdc->params[0] & 0x80)) { - /* VERIFY command, EC clear */ - if ((fdc->sector == old_sector) && (fdc->head == (fdc->command & 0x80) ? 1 : 0)) { - fdc->sector++; - fdc_poll_readwrite_finish(fdc, 0); - return; - } - } - if (fdc->sector == fdc->params[5]) { - /* Reached end of track, MT bit is clear */ - if (!(fdc->command & 0x80)) { - fdc->rw_track++; - fdc->sector = 1; - if (!(fdc->flags & FDC_FLAG_PCJR) && fdc->dma && (old_sector == 255)) - fdc_no_dma_end(fdc, compare); - else - fdc_poll_readwrite_finish(fdc, compare); - return; - } - /* Reached end of track, MT bit is set, head is 1 */ - if (fdd_get_head(real_drive(fdc, fdc->drive)) == 1) { - fdc->rw_track++; - fdc->sector = 1; - fdc->head &= 0xFE; - fdd_set_head(real_drive(fdc, fdc->drive), 0); - if (!(fdc->flags & FDC_FLAG_PCJR) && fdc->dma && (old_sector == 255)) - fdc_no_dma_end(fdc, compare); - else - fdc_poll_readwrite_finish(fdc, compare); - return; - } - if ((fdd_get_head(real_drive(fdc, fdc->drive)) == 0)) { - fdc->sector = 1; - fdc->head |= 1; - fdd_set_head(real_drive(fdc, fdc->drive), 1); - if (!fdd_is_double_sided(real_drive(fdc, fdc->drive))) { - fdc_noidam(fdc); - return; - } - } - } else if (fdc->sector < fdc->params[5]) - fdc->sector++; - ui_sb_update_icon(SB_FLOPPY | real_drive(fdc, fdc->drive), 1); - switch (fdc->interrupt) { - case 5: - case 9: - fdd_writesector(real_drive(fdc, fdc->drive), fdc->sector, fdc->rw_track, fdc->head, fdc->rate, fdc->params[4]); - if ((fdc->flags & FDC_FLAG_PCJR) || !fdc->dma) - fdc->stat = 0xb0; - else - fdc->stat = 0x90; - break; - case 6: - case 0xC: - case 0x16: - fdd_readsector(real_drive(fdc, fdc->drive), fdc->sector, fdc->rw_track, fdc->head, fdc->rate, fdc->params[4]); - if ((fdc->flags & FDC_FLAG_PCJR) || !fdc->dma) - fdc->stat = 0x70; - else - fdc->stat = 0x50; - break; - case 0x11: - case 0x19: - case 0x1D: - fdd_comparesector(real_drive(fdc, fdc->drive), fdc->sector, fdc->rw_track, fdc->head, fdc->rate, fdc->params[4]); - if ((fdc->flags & FDC_FLAG_PCJR) || !fdc->dma) - fdc->stat = 0xb0; - else - fdc->stat = 0x90; - break; - } - fdc->inread = 1; - return; - case 0x07: /* Recalibrate */ - fdc->pcn[fdc->params[0] & 3] = 0; - drive_num = real_drive(fdc, fdc->rw_drive); - fdc->st0 = 0x20 | (fdc->params[0] & 3); - if (!fdd_track0(drive_num)) - fdc->st0 |= 0x50; - if (fdc->flags & FDC_FLAG_PCJR) { - fdc->fintr = 1; - fdc->interrupt = -4; - } else - fdc->interrupt = -3; - timer_set_delay_u64(&fdc->timer, 2048 * TIMER_USEC); - fdc->stat = 0x80 | (1 << fdc->rw_drive); - return; - case 0x0d: /*Format track*/ - if (fdc->format_state == 1) { - fdc->format_state = 2; - timer_set_delay_u64(&fdc->timer, 8 * TIMER_USEC); - } else if (fdc->format_state == 2) { - fdd_format(real_drive(fdc, fdc->drive), fdc->head, fdc->rate, fdc->params[4]); - fdc->format_state = 3; - } else { - fdc->interrupt = -2; - fdc_int(fdc, 1); - if (!(fdc->flags & FDC_FLAG_PS1)) - fdc->fintr = 0; - fdc->stat = 0xD0; - fdc->st0 = fdc->res[4] = (fdd_get_head(real_drive(fdc, fdc->drive)) ? 4 : 0) | fdc->drive; - fdc->res[5] = fdc->res[6] = 0; - fdc->res[7] = fdc->format_sector_id.id.c; - fdc->res[8] = fdc->format_sector_id.id.h; - fdc->res[9] = fdc->format_sector_id.id.r; - fdc->res[10] = fdc->format_sector_id.id.n; - fdc->paramstogo = 7; - fdc->format_state = 0; - return; - } - return; - case 0x0e: /*Dump registers*/ - fdc->stat = (fdc->stat & 0xf) | 0xd0; - fdc->res[1] = fdc->pcn[0]; - fdc->res[2] = fdc->pcn[1]; - fdc->res[3] = fdc->pcn[2]; - fdc->res[4] = fdc->pcn[3]; - fdc->res[5] = fdc->specify[0]; - fdc->res[6] = fdc->specify[1]; - fdc->res[7] = fdc->eot[fdc->drive]; - fdc->res[8] = (fdc->perp & 0x7f) | ((fdc->lock) ? 0x80 : 0); - fdc->res[9] = fdc->config; - fdc->res[10] = fdc->pretrk; - fdc->paramstogo = 10; - fdc->interrupt = 0; - return; - case 0x0f: /*Seek*/ - fdc->st0 = 0x20 | (fdc->params[0] & 3); - fdc->stat = 0x80 | (1 << fdc->rw_drive); - if (fdc->flags & FDC_FLAG_PCJR) { - fdc->fintr = 1; - fdc->interrupt = -4; - timer_set_delay_u64(&fdc->timer, 1024 * TIMER_USEC); - } else { - fdc->interrupt = -3; - fdc_callback(fdc); - } - return; - case 0x10: /*Version*/ - case 0x18: /*NSC*/ - fdc->stat = (fdc->stat & 0xf) | 0xd0; - fdc->res[10] = (fdc->interrupt & 0x08) ? 0x73 : 0x90; - fdc->paramstogo = 1; - fdc->interrupt = 0; - return; - case 0x13: /*Configure*/ - fdc->config = fdc->params[1]; - fdc->pretrk = fdc->params[2]; - fdc->fifo = (fdc->params[1] & 0x20) ? 0 : 1; - fdc->tfifo = (fdc->params[1] & 0xF); - fdc->stat = 0x80; - return; - case 0x14: /*Unlock*/ - case 0x94: /*Lock*/ - fdc->lock = (fdc->interrupt & 0x80) ? 1 : 0; - fdc->stat = (fdc->stat & 0xf) | 0xd0; - fdc->res[10] = (fdc->interrupt & 0x80) ? 0x10 : 0x00; - fdc->paramstogo = 1; - fdc->interrupt = 0; - return; - case 0xfc: /*Invalid*/ - fdc->dat = fdc->st0 = 0x80; - fdc->stat = (fdc->stat & 0xf) | 0xd0; - fdc->res[10] = fdc->st0; - fdc->paramstogo = 1; - fdc->interrupt = 0; - return; + fdc->head ^= 1; + fdd_set_head(real_drive(fdc, fdc->drive), fdc->head); + fdc->sector = 1; + } + } else + fdc->sector++; + fdc_poll_readwrite_finish(fdc, compare); + return; + } + if ((fdc->interrupt == 0x16) && (fdc->params[0] & 0x80)) { + /* VERIFY command, EC set */ + fdc->sc--; + if (!fdc->sc) { + fdc->sector++; + fdc_poll_readwrite_finish(fdc, 0); + return; + } + /* The rest is processed normally per MT flag and EOT. */ + } else if ((fdc->interrupt == 0x16) && !(fdc->params[0] & 0x80)) { + /* VERIFY command, EC clear */ + if ((fdc->sector == old_sector) && (fdc->head == (fdc->command & 0x80) ? 1 : 0)) { + fdc->sector++; + fdc_poll_readwrite_finish(fdc, 0); + return; + } + } + if (fdc->sector == fdc->params[5]) { + /* Reached end of track, MT bit is clear */ + if (!(fdc->command & 0x80)) { + fdc->rw_track++; + fdc->sector = 1; + if (!(fdc->flags & FDC_FLAG_PCJR) && fdc->dma && (old_sector == 255)) + fdc_no_dma_end(fdc, compare); + else + fdc_poll_readwrite_finish(fdc, compare); + return; + } + /* Reached end of track, MT bit is set, head is 1 */ + if (fdd_get_head(real_drive(fdc, fdc->drive)) == 1) { + fdc->rw_track++; + fdc->sector = 1; + fdc->head &= 0xFE; + fdd_set_head(real_drive(fdc, fdc->drive), 0); + if (!(fdc->flags & FDC_FLAG_PCJR) && fdc->dma && (old_sector == 255)) + fdc_no_dma_end(fdc, compare); + else + fdc_poll_readwrite_finish(fdc, compare); + return; + } + if (fdd_get_head(real_drive(fdc, fdc->drive)) == 0) { + fdc->sector = 1; + fdc->head |= 1; + fdd_set_head(real_drive(fdc, fdc->drive), 1); + if (!fdd_is_double_sided(real_drive(fdc, fdc->drive))) { + fdc_noidam(fdc); + return; + } + } + } else if (fdc->sector < fdc->params[5]) + fdc->sector++; + ui_sb_update_icon(SB_FLOPPY | real_drive(fdc, fdc->drive), 1); + switch (fdc->interrupt) { + case 5: + case 9: + fdd_writesector(real_drive(fdc, fdc->drive), fdc->sector, fdc->rw_track, fdc->head, fdc->rate, fdc->params[4]); + if ((fdc->flags & FDC_FLAG_PCJR) || !fdc->dma) + fdc->stat = 0xb0; + else { + dma_set_drq(fdc->dma_ch, 1); + fdc->stat = 0x90; + } + break; + case 6: + case 0xC: + case 0x16: + fdd_readsector(real_drive(fdc, fdc->drive), fdc->sector, fdc->rw_track, fdc->head, fdc->rate, fdc->params[4]); + if ((fdc->flags & FDC_FLAG_PCJR) || !fdc->dma) + fdc->stat = 0x70; + else { + dma_set_drq(fdc->dma_ch, 1); + fdc->stat = 0x50; + } + break; + case 0x11: + case 0x19: + case 0x1D: + fdd_comparesector(real_drive(fdc, fdc->drive), fdc->sector, fdc->rw_track, fdc->head, fdc->rate, fdc->params[4]); + if ((fdc->flags & FDC_FLAG_PCJR) || !fdc->dma) + fdc->stat = 0xb0; + else { + dma_set_drq(fdc->dma_ch, 1); + fdc->stat = 0x90; + } + break; + + default: + break; + } + fdc->inread = 1; + return; + case 0x07: /* Recalibrate */ + fdc->pcn[fdc->params[0] & 3] = 0; + drive_num = real_drive(fdc, fdc->rw_drive); + fdc->st0 = 0x20 | (fdc->params[0] & 3); + if (!fdd_track0(drive_num)) + fdc->st0 |= 0x50; + if (fdc->flags & FDC_FLAG_PCJR) { + fdc->fintr = 1; + fdc->interrupt = -4; + } else + fdc->interrupt = -3; + timer_set_delay_u64(&fdc->timer, 2048 * TIMER_USEC); + fdc->stat = 0x80 | (1 << fdc->rw_drive); + return; + case 0x0d: /*Format track*/ + if (fdc->format_state == 1) { + fdc->format_state = 2; + timer_set_delay_u64(&fdc->timer, 8 * TIMER_USEC); + } else if (fdc->format_state == 2) { + fdd_format(real_drive(fdc, fdc->drive), fdc->head, fdc->rate, fdc->params[4]); + fdc->format_state = 3; + } else { + fdc->interrupt = -2; + fdc_int(fdc, 1); + if (!(fdc->flags & FDC_FLAG_PS1)) + fdc->fintr = 0; + fdc->stat = 0xD0; + fdc->st0 = fdc->res[4] = (fdd_get_head(real_drive(fdc, fdc->drive)) ? 4 : 0) | fdc->drive; + fdc->res[5] = fdc->res[6] = 0; + fdc->res[7] = fdc->format_sector_id.id.c; + fdc->res[8] = fdc->format_sector_id.id.h; + fdc->res[9] = fdc->format_sector_id.id.r; + fdc->res[10] = fdc->format_sector_id.id.n; + fdc->paramstogo = 7; + fdc->format_state = 0; + return; + } + return; + case 0x0e: /*Dump registers*/ + fdc->stat = (fdc->stat & 0xf) | 0xd0; + fdc->res[1] = fdc->pcn[0]; + fdc->res[2] = fdc->pcn[1]; + fdc->res[3] = fdc->pcn[2]; + fdc->res[4] = fdc->pcn[3]; + fdc->res[5] = fdc->specify[0]; + fdc->res[6] = fdc->specify[1]; + fdc->res[7] = fdc->eot[fdc->drive]; + fdc->res[8] = (fdc->perp & 0x7f) | ((fdc->lock) ? 0x80 : 0); + fdc->res[9] = fdc->config; + fdc->res[10] = fdc->pretrk; + fdc->paramstogo = 10; + fdc->interrupt = 0; + return; + case 0x0f: /*Seek*/ + fdc->st0 = 0x20 | (fdc->params[0] & 3); + fdc->stat = 0x80 | (1 << fdc->rw_drive); + if (fdc->flags & FDC_FLAG_PCJR) { + fdc->fintr = 1; + fdc->interrupt = -4; + timer_set_delay_u64(&fdc->timer, 1024 * TIMER_USEC); + } else { + fdc->interrupt = -3; + fdc_callback(fdc); + } + return; + case 0x10: /*Version*/ + case 0x18: /*NSC*/ + fdc->stat = (fdc->stat & 0xf) | 0xd0; + fdc->res[10] = (fdc->interrupt & 0x08) ? 0x73 : 0x90; + fdc->paramstogo = 1; + fdc->interrupt = 0; + return; + case 0x17: /*Powerdown mode*/ + fdc->stat = (fdc->stat & 0xf) | 0xd0; + fdc->res[10] = fdc->params[0]; + fdc->paramstogo = 1; + fdc->interrupt = 0; + return; + case 0x13: /*Configure*/ + fdc->config = fdc->params[1]; + fdc->pretrk = fdc->params[2]; + fdc->fifo = (fdc->params[1] & 0x20) ? 0 : 1; + fdc->tfifo = (fdc->params[1] & 0xF); + fdc->stat = 0x80; + return; + case 0x14: /*Unlock*/ + case 0x94: /*Lock*/ + fdc->lock = (fdc->interrupt & 0x80) ? 1 : 0; + fdc->stat = (fdc->stat & 0xf) | 0xd0; + fdc->res[10] = (fdc->interrupt & 0x80) ? 0x10 : 0x00; + fdc->paramstogo = 1; + fdc->interrupt = 0; + return; + case 0xfc: /*Invalid*/ + fdc->dat = fdc->st0 = 0x80; + fdc->stat = (fdc->stat & 0xf) | 0xd0; + fdc->res[10] = fdc->st0; + fdc->paramstogo = 1; + fdc->interrupt = 0; + return; + + default: + break; } } - void fdc_error(fdc_t *fdc, int st5, int st6) { + dma_set_drq(fdc->dma_ch, 0); #if 1 timer_disable(&fdc->timer); fdc_int(fdc, 1); if (!(fdc->flags & FDC_FLAG_PS1)) - fdc->fintr = 0; + fdc->fintr = 0; fdc->stat = 0xD0; fdc->st0 = fdc->res[4] = 0x40 | (fdd_get_head(real_drive(fdc, fdc->drive)) ? 4 : 0) | fdc->rw_drive; if (fdc->head && !fdd_is_double_sided(real_drive(fdc, fdc->drive))) - fdc->st0 |= 0x08; + fdc->st0 |= 0x08; fdc->res[5] = st5; fdc->res[6] = st6; fdc_log("FDC Error: %02X %02X %02X\n", fdc->res[4], fdc->res[5], fdc->res[6]); - switch(fdc->interrupt) { - case 0x02: - case 0x05: - case 0x06: - case 0x09: - case 0x0C: - case 0x11: - case 0x16: - case 0x19: - case 0x1D: - fdc->res[7]=fdc->rw_track; - fdc->res[8]=fdc->head; - fdc->res[9]=fdc->sector; - fdc->res[10]=fdc->params[4]; - break; - default: - fdc->res[7]=0; - fdc->res[8]=0; - fdc->res[9]=0; - fdc->res[10]=0; - break; + switch (fdc->interrupt) { + case 0x02: + case 0x05: + case 0x06: + case 0x09: + case 0x0C: + case 0x11: + case 0x16: + case 0x19: + case 0x1D: + fdc->res[7] = fdc->rw_track; + fdc->res[8] = fdc->head; + fdc->res[9] = fdc->sector; + fdc->res[10] = fdc->params[4]; + break; + default: + fdc->res[7] = 0; + fdc->res[8] = 0; + fdc->res[9] = 0; + fdc->res[10] = 0; + break; } ui_sb_update_icon(SB_FLOPPY | real_drive(fdc, fdc->drive), 0); fdc->paramstogo = 7; #else - switch(fdc->interrupt) { - case 0x02: - case 0x05: - case 0x06: - case 0x09: - case 0x0C: - case 0x11: - case 0x16: - case 0x19: - case 0x1D: - fdc->error = 1; - fdc->st5 = st5; - fdc->st6 = st6; - fdc->tc = 1; - fdc->stat = 0x10; - fdc_callback(fdc); - break; - default: - timer_disable(&fdc->timer); + switch (fdc->interrupt) { + case 0x02: + case 0x05: + case 0x06: + case 0x09: + case 0x0C: + case 0x11: + case 0x16: + case 0x19: + case 0x1D: + fdc->error = 1; + fdc->st5 = st5; + fdc->st6 = st6; + fdc->tc = 1; + fdc->stat = 0x10; + fdc_callback(fdc); + break; + default: + timer_disable(&fdc->timer); - fdc_int(fdc, 1); - if (!(fdc->flags & FDC_FLAG_PS1)) - fdc->fintr = 0; - fdc->stat = 0xD0; - fdc->st0 = fdc->res[4] = 0x40 | (fdd_get_head(real_drive(fdc, fdc->drive)) ? 4 : 0) | fdc->rw_drive; - if (fdc->head && !fdd_is_double_sided(real_drive(fdc, fdc->drive))) - fdc->st0 |= 0x08; - fdc->res[5] = st5; - fdc->res[6] = st6; - fdc_log("FDC Error: %02X %02X %02X\n", fdc->res[4], fdc->res[5], fdc->res[6]); + fdc_int(fdc, 1); + if (!(fdc->flags & FDC_FLAG_PS1)) + fdc->fintr = 0; + fdc->stat = 0xD0; + fdc->st0 = fdc->res[4] = 0x40 | (fdd_get_head(real_drive(fdc, fdc->drive)) ? 4 : 0) | fdc->rw_drive; + if (fdc->head && !fdd_is_double_sided(real_drive(fdc, fdc->drive))) + fdc->st0 |= 0x08; + fdc->res[5] = st5; + fdc->res[6] = st6; + fdc_log("FDC Error: %02X %02X %02X\n", fdc->res[4], fdc->res[5], fdc->res[6]); - fdc->res[7]=0; - fdc->res[8]=0; - fdc->res[9]=0; - fdc->res[10]=0; + fdc->res[7] = 0; + fdc->res[8] = 0; + fdc->res[9] = 0; + fdc->res[10] = 0; - ui_sb_update_icon(SB_FLOPPY | real_drive(fdc, fdc->drive), 0); - fdc->paramstogo = 7; - break; + ui_sb_update_icon(SB_FLOPPY | real_drive(fdc, fdc->drive), 0); + fdc->paramstogo = 7; + break; } #endif } - void fdc_overrun(fdc_t *fdc) { @@ -1892,98 +1916,100 @@ fdc_overrun(fdc_t *fdc) fdc_error(fdc, 0x10, 0); } - int fdc_is_verify(fdc_t *fdc) { return (fdc->deleted & 2) ? 1 : 0; } - int fdc_data(fdc_t *fdc, uint8_t data, int last) { - int i, result = 0; + int result = 0; int n; if (fdc->deleted & 2) { - /* We're in a VERIFY command, so return with 0. */ - return 0; + /* We're in a VERIFY command, so return with 0. */ + return 0; } if ((fdc->flags & FDC_FLAG_PCJR) || !fdc->dma) { - if (fdc->tc) - return 0; + if (fdc->tc) + return 0; - if (fdc->data_ready) { - fdc_overrun(fdc); - return -1; - } + if (fdc->data_ready) { + fdc_overrun(fdc); + return -1; + } - if ((fdc->flags & FDC_FLAG_PCJR) || !fdc->fifo || (fdc->tfifo < 1)) { - fdc->dat = data; - fdc->data_ready = 1; - fdc->stat = 0xf0; - } else { - /* FIFO enabled */ - fdc_fifo_buf_write(fdc, data); - if (fdc->fifobufpos == 0) { - /* We have wrapped around, means FIFO is over */ - fdc->data_ready = 1; - fdc->stat = 0xf0; - } - } + if ((fdc->flags & FDC_FLAG_PCJR) || !fdc->fifo || (fdc->tfifo < 1)) { + fdc->dat = data; + fdc->data_ready = 1; + fdc->stat = 0xf0; + } else { + /* FIFO enabled */ + fdc_fifo_buf_write(fdc, data); + if (fdc->fifobufpos == 0) { + /* We have wrapped around, means FIFO is over */ + fdc->data_ready = 1; + fdc->stat = 0xf0; + } + } } else { - if (fdc->tc) - return -1; + if (fdc->tc) + return -1; - if (!fdc->fifo || (fdc->tfifo < 1)) { - fdc->data_ready = 1; - fdc->stat = 0xd0; + if (!fdc->fifo || (fdc->tfifo < 1)) { + fdc->data_ready = 1; + fdc->stat = 0xd0; + dma_set_drq(fdc->dma_ch, 1); - fdc->fifobufpos = 0; + fdc->fifobufpos = 0; - result = dma_channel_write(fdc->dma_ch, data); + result = dma_channel_write(fdc->dma_ch, data); - if (result & DMA_OVER) { - fdc->tc = 1; - return -1; - } - } else { - /* FIFO enabled */ - fdc_fifo_buf_write(fdc, data); - if (last || (fdc->fifobufpos == 0)) { - /* We have wrapped around, means FIFO is over */ - fdc->data_ready = 1; - fdc->stat = 0xd0; + if (result & DMA_OVER) { + dma_set_drq(fdc->dma_ch, 0); + fdc->tc = 1; + return -1; + } + dma_set_drq(fdc->dma_ch, 0); + } else { + /* FIFO enabled */ + fdc_fifo_buf_write(fdc, data); + if (last || (fdc->fifobufpos == 0)) { + /* We have wrapped around, means FIFO is over */ + fdc->data_ready = 1; + fdc->stat = 0xd0; + dma_set_drq(fdc->dma_ch, 1); - n = (fdc->fifobufpos > 0) ? (fdc->fifobufpos - 1) : fdc->tfifo; - if (fdc->fifobufpos > 0) - fdc->fifobufpos = 0; + n = (fdc->fifobufpos > 0) ? (fdc->fifobufpos - 1) : fdc->tfifo; + if (fdc->fifobufpos > 0) + fdc->fifobufpos = 0; - for (i = 0; i <= n; i++) { - result = dma_channel_write(fdc->dma_ch, fdc->fifobuf[i]); + for (int i = 0; i <= n; i++) { + result = dma_channel_write(fdc->dma_ch, fdc->fifobuf[i]); - if (result & DMA_OVER) { - fdc->tc = 1; - return -1; - } - } - } - } + if (result & DMA_OVER) { + dma_set_drq(fdc->dma_ch, 0); + fdc->tc = 1; + return -1; + } + } + dma_set_drq(fdc->dma_ch, 0); + } + } } return 0; } - void fdc_finishread(fdc_t *fdc) { fdc->inread = 0; } - void fdc_track_finishread(fdc_t *fdc, int condition) { @@ -1993,27 +2019,24 @@ fdc_track_finishread(fdc_t *fdc, int condition) fdc_callback(fdc); } - void fdc_sector_finishcompare(fdc_t *fdc, int satisfying) { fdc->stat = 0x10; if (satisfying) - fdc->satisfying_sectors++; + fdc->satisfying_sectors++; fdc->inread = 0; fdc_callback(fdc); } - void fdc_sector_finishread(fdc_t *fdc) { - fdc->stat = 0x10; + fdc->stat = 0x10; fdc->inread = 0; fdc_callback(fdc); } - /* There is no sector ID. */ void fdc_noidam(fdc_t *fdc) @@ -2021,256 +2044,246 @@ fdc_noidam(fdc_t *fdc) fdc_error(fdc, 1, 0); } - /* Sector ID's are there, but there is no sector. */ -void fdc_nosector(fdc_t *fdc) +void +fdc_nosector(fdc_t *fdc) { fdc_error(fdc, 4, 0); } - /* There is no sector data. */ -void fdc_nodataam(fdc_t *fdc) +void +fdc_nodataam(fdc_t *fdc) { fdc_error(fdc, 1, 1); } - /* Abnormal termination with both status 1 and 2 set to 0, used when abnormally terminating the fdc_t FORMAT TRACK command. */ -void fdc_cannotformat(fdc_t *fdc) +void +fdc_cannotformat(fdc_t *fdc) { fdc_error(fdc, 0, 0); } - void fdc_datacrcerror(fdc_t *fdc) { fdc_error(fdc, 0x20, 0x20); } - void fdc_headercrcerror(fdc_t *fdc) { fdc_error(fdc, 0x20, 0); } - void fdc_wrongcylinder(fdc_t *fdc) { fdc_error(fdc, 4, 0x10); } - void fdc_badcylinder(fdc_t *fdc) { fdc_error(fdc, 4, 0x02); } - void fdc_writeprotect(fdc_t *fdc) { fdc_error(fdc, 0x02, 0); } - -int fdc_getdata(fdc_t *fdc, int last) +int +fdc_getdata(fdc_t *fdc, int last) { - int i, data = 0; + int data = 0; if ((fdc->flags & FDC_FLAG_PCJR) || !fdc->dma) { - if ((fdc->flags & FDC_FLAG_PCJR) || !fdc->fifo || (fdc->tfifo < 1)) { - data = fdc->dat; + if ((fdc->flags & FDC_FLAG_PCJR) || !fdc->fifo || (fdc->tfifo < 1)) { + data = fdc->dat; - if (!last) - fdc->stat = 0xb0; - } else { - data = fdc_fifo_buf_read(fdc); + if (!last) + fdc->stat = 0xb0; + } else { + data = fdc_fifo_buf_read(fdc); - if (!last && (fdc->fifobufpos == 0)) - fdc->stat = 0xb0; - } + if (!last && (fdc->fifobufpos == 0)) + fdc->stat = 0xb0; + } } else { - if (!fdc->fifo || (fdc->tfifo < 1)) { - data = dma_channel_read(fdc->dma_ch); + if (!fdc->fifo || (fdc->tfifo < 1)) { + data = dma_channel_read(fdc->dma_ch); + dma_set_drq(fdc->dma_ch, 0); - if (data & DMA_OVER) - fdc->tc = 1; + if (data & DMA_OVER) + fdc->tc = 1; - if (!last) - fdc->stat = 0x90; - } else { - if (fdc->fifobufpos == 0) { - for (i = 0; i <= fdc->tfifo; i++) { - data = dma_channel_read(fdc->dma_ch); - fdc->fifobuf[i] = data; + if (!last) { + fdc->stat = 0x90; + dma_set_drq(fdc->dma_ch, 1); + } + } else { + if (fdc->fifobufpos == 0) { + for (int i = 0; i <= fdc->tfifo; i++) { + data = dma_channel_read(fdc->dma_ch); + fdc->fifobuf[i] = data; - if (data & DMA_OVER) { - fdc->tc = 1; - break; - } - } - } + if (data & DMA_OVER) { + dma_set_drq(fdc->dma_ch, 0); + fdc->tc = 1; + break; + } + } + dma_set_drq(fdc->dma_ch, 0); + } - data = fdc_fifo_buf_read(fdc); + data = fdc_fifo_buf_read(fdc); - if (!last && (fdc->fifobufpos == 0)) - fdc->stat = 0x90; - } + if (!last && (fdc->fifobufpos == 0)) { + dma_set_drq(fdc->dma_ch, 1); + fdc->stat = 0x90; + } + } } return data & 0xff; } - void -fdc_sectorid(fdc_t *fdc, uint8_t track, uint8_t side, uint8_t sector, uint8_t size, uint8_t crc1, uint8_t crc2) +fdc_sectorid(fdc_t *fdc, uint8_t track, uint8_t side, uint8_t sector, uint8_t size, UNUSED(uint8_t crc1), UNUSED(uint8_t crc2)) { fdc_int(fdc, 1); fdc->stat = 0xD0; fdc->st0 = fdc->res[4] = (fdd_get_head(real_drive(fdc, fdc->drive)) ? 4 : 0) | fdc->drive; - fdc->res[5] = 0; - fdc->res[6] = 0; - fdc->res[7] = track; - fdc->res[8] = side; - fdc->res[9] = sector; - fdc->res[10] = size; + fdc->res[5] = 0; + fdc->res[6] = 0; + fdc->res[7] = track; + fdc->res[8] = side; + fdc->res[9] = sector; + fdc->res[10] = size; ui_sb_update_icon(SB_FLOPPY | real_drive(fdc, fdc->drive), 0); fdc->paramstogo = 7; + dma_set_drq(fdc->dma_ch, 0); } - uint8_t fdc_get_swwp(fdc_t *fdc) { return fdc->swwp; } - void fdc_set_swwp(fdc_t *fdc, uint8_t swwp) { fdc->swwp = swwp; } - uint8_t fdc_get_diswr(fdc_t *fdc) { if (!fdc) - return 0; + return 0; return fdc->disable_write; } - void fdc_set_diswr(fdc_t *fdc, uint8_t diswr) { fdc->disable_write = diswr; } - uint8_t fdc_get_swap(fdc_t *fdc) { return fdc->swap; } - void fdc_set_swap(fdc_t *fdc, uint8_t swap) { fdc->swap = swap; } - void fdc_set_irq(fdc_t *fdc, int irq) { fdc->irq = irq; } - void fdc_set_dma_ch(fdc_t *fdc, int dma_ch) { fdc->dma_ch = dma_ch; } - void fdc_set_base(fdc_t *fdc, int base) { int super_io = (fdc->flags & FDC_FLAG_SUPERIO); - if (fdc->flags & FDC_FLAG_NSC) { - io_sethandler(base + 2, 0x0001, fdc_read, NULL, NULL, fdc_write, NULL, NULL, fdc); - io_sethandler(base + 4, 0x0002, fdc_read, NULL, NULL, fdc_write, NULL, NULL, fdc); - io_sethandler(base + 7, 0x0001, fdc_read, NULL, NULL, fdc_write, NULL, NULL, fdc); - } else { - if ((fdc->flags & FDC_FLAG_AT) || (fdc->flags & FDC_FLAG_AMSTRAD)) { - io_sethandler(base + (super_io ? 2 : 0), super_io ? 0x0004 : 0x0006, fdc_read, NULL, NULL, fdc_write, NULL, NULL, fdc); - io_sethandler(base + 7, 0x0001, fdc_read, NULL, NULL, fdc_write, NULL, NULL, fdc); + if (fdc->flags & FDC_FLAG_NSC) { + io_sethandler(base + 2, 0x0001, fdc_read, NULL, NULL, fdc_write, NULL, NULL, fdc); + io_sethandler(base + 4, 0x0002, fdc_read, NULL, NULL, fdc_write, NULL, NULL, fdc); + io_sethandler(base + 7, 0x0001, fdc_read, NULL, NULL, fdc_write, NULL, NULL, fdc); } else { - if (fdc->flags & FDC_FLAG_PCJR) - io_sethandler(base, 0x0010, fdc_read, NULL, NULL, fdc_write, NULL, NULL, fdc); - else { - if(fdc->flags & FDC_FLAG_UMC) - io_sethandler(base + 0x0001, 0x0001, fdc_read, NULL, NULL, NULL, NULL, NULL, fdc); - io_sethandler(base + 0x0002, 0x0001, NULL, NULL, NULL, fdc_write, NULL, NULL, fdc); - io_sethandler(base + 0x0004, 0x0001, fdc_read, NULL, NULL, NULL, NULL, NULL, fdc); - io_sethandler(base + 0x0005, 0x0001, fdc_read, NULL, NULL, fdc_write, NULL, NULL, fdc); - if ((fdc->flags & FDC_FLAG_TOSHIBA) || (fdc->flags & FDC_FLAG_UMC)) - io_sethandler(base + 0x0007, 0x0001, fdc_read, NULL, NULL, fdc_write, NULL, NULL, fdc); - } + if ((fdc->flags & FDC_FLAG_AT) || (fdc->flags & FDC_FLAG_AMSTRAD)) { + io_sethandler(base + (super_io ? 2 : 0), super_io ? 0x0004 : 0x0006, fdc_read, NULL, NULL, fdc_write, NULL, NULL, fdc); + io_sethandler(base + 7, 0x0001, fdc_read, NULL, NULL, fdc_write, NULL, NULL, fdc); + } else { + if (fdc->flags & FDC_FLAG_PCJR) + io_sethandler(base, 0x0010, fdc_read, NULL, NULL, fdc_write, NULL, NULL, fdc); + else { + if (fdc->flags & FDC_FLAG_UMC) + io_sethandler(base + 0x0001, 0x0001, fdc_read, NULL, NULL, NULL, NULL, NULL, fdc); + io_sethandler(base + 0x0002, 0x0001, NULL, NULL, NULL, fdc_write, NULL, NULL, fdc); + io_sethandler(base + 0x0004, 0x0001, fdc_read, NULL, NULL, NULL, NULL, NULL, fdc); + io_sethandler(base + 0x0005, 0x0001, fdc_read, NULL, NULL, fdc_write, NULL, NULL, fdc); + if ((fdc->flags & FDC_FLAG_TOSHIBA) || (fdc->flags & FDC_FLAG_UMC)) + io_sethandler(base + 0x0007, 0x0001, fdc_read, NULL, NULL, fdc_write, NULL, NULL, fdc); + } + } } - } fdc->base_address = base; fdc_log("FDC Base address set%s (%04X)\n", super_io ? " for Super I/O" : "", fdc->base_address); } - void fdc_remove(fdc_t *fdc) { int super_io = (fdc->flags & FDC_FLAG_SUPERIO); fdc_log("FDC Removed (%04X)\n", fdc->base_address); - if (fdc->flags & FDC_FLAG_NSC) { - io_removehandler(fdc->base_address + 2, 0x0001, fdc_read, NULL, NULL, fdc_write, NULL, NULL, fdc); - io_removehandler(fdc->base_address + 4, 0x0002, fdc_read, NULL, NULL, fdc_write, NULL, NULL, fdc); - io_removehandler(fdc->base_address + 7, 0x0001, fdc_read, NULL, NULL, fdc_write, NULL, NULL, fdc); - } else { - if ((fdc->flags & FDC_FLAG_AT) || (fdc->flags & FDC_FLAG_AMSTRAD)) { - io_removehandler(fdc->base_address + (super_io ? 2 : 0), super_io ? 0x0004 : 0x0006, fdc_read, NULL, NULL, fdc_write, NULL, NULL, fdc); - io_removehandler(fdc->base_address + 7, 0x0001, fdc_read, NULL, NULL, fdc_write, NULL, NULL, fdc); + if (fdc->flags & FDC_FLAG_NSC) { + io_removehandler(fdc->base_address + 2, 0x0001, fdc_read, NULL, NULL, fdc_write, NULL, NULL, fdc); + io_removehandler(fdc->base_address + 4, 0x0002, fdc_read, NULL, NULL, fdc_write, NULL, NULL, fdc); + io_removehandler(fdc->base_address + 7, 0x0001, fdc_read, NULL, NULL, fdc_write, NULL, NULL, fdc); } else { - if (fdc->flags & FDC_FLAG_PCJR) - io_removehandler(fdc->base_address, 0x0010, fdc_read, NULL, NULL, fdc_write, NULL, NULL, fdc); - else { - if(fdc->flags & FDC_FLAG_UMC) - io_removehandler(fdc->base_address + 0x0001, 0x0001, fdc_read, NULL, NULL, NULL, NULL, NULL, fdc); - io_removehandler(fdc->base_address + 0x0002, 0x0001, NULL, NULL, NULL, fdc_write, NULL, NULL, fdc); - io_removehandler(fdc->base_address + 0x0004, 0x0001, fdc_read, NULL, NULL, NULL, NULL, NULL, fdc); - io_removehandler(fdc->base_address + 0x0005, 0x0001, fdc_read, NULL, NULL, fdc_write, NULL, NULL, fdc); - if ((fdc->flags & FDC_FLAG_TOSHIBA) || (fdc->flags & FDC_FLAG_UMC)) - io_removehandler(fdc->base_address + 0x0007, 0x0001, fdc_read, NULL, NULL, fdc_write, NULL, NULL, fdc); - } + if ((fdc->flags & FDC_FLAG_AT) || (fdc->flags & FDC_FLAG_AMSTRAD)) { + io_removehandler(fdc->base_address + (super_io ? 2 : 0), super_io ? 0x0004 : 0x0006, fdc_read, NULL, NULL, fdc_write, NULL, NULL, fdc); + io_removehandler(fdc->base_address + 7, 0x0001, fdc_read, NULL, NULL, fdc_write, NULL, NULL, fdc); + } else { + if (fdc->flags & FDC_FLAG_PCJR) + io_removehandler(fdc->base_address, 0x0010, fdc_read, NULL, NULL, fdc_write, NULL, NULL, fdc); + else { + if (fdc->flags & FDC_FLAG_UMC) + io_removehandler(fdc->base_address + 0x0001, 0x0001, fdc_read, NULL, NULL, NULL, NULL, NULL, fdc); + io_removehandler(fdc->base_address + 0x0002, 0x0001, NULL, NULL, NULL, fdc_write, NULL, NULL, fdc); + io_removehandler(fdc->base_address + 0x0004, 0x0001, fdc_read, NULL, NULL, NULL, NULL, NULL, fdc); + io_removehandler(fdc->base_address + 0x0005, 0x0001, fdc_read, NULL, NULL, fdc_write, NULL, NULL, fdc); + if ((fdc->flags & FDC_FLAG_TOSHIBA) || (fdc->flags & FDC_FLAG_UMC)) + io_removehandler(fdc->base_address + 0x0007, 0x0001, fdc_read, NULL, NULL, fdc_write, NULL, NULL, fdc); + } + } } } -} - void fdc_reset(void *priv) { - int i = 0; uint8_t default_rwc; fdc_t *fdc = (fdc_t *) priv; @@ -2281,13 +2294,13 @@ fdc_reset(void *priv) fdc_update_enh_mode(fdc, 0); if (fdc->flags & FDC_FLAG_PS1) - fdc_update_densel_polarity(fdc, 0); + fdc_update_densel_polarity(fdc, 0); else - fdc_update_densel_polarity(fdc, 1); + fdc_update_densel_polarity(fdc, 1); if (fdc->flags & FDC_FLAG_NSC) - fdc_update_densel_force(fdc, 3); + fdc_update_densel_force(fdc, 3); else - fdc_update_densel_force(fdc, 0); + fdc_update_densel_force(fdc, 0); fdc_update_rwc(fdc, 0, default_rwc); fdc_update_rwc(fdc, 1, default_rwc); fdc_update_rwc(fdc, 2, default_rwc); @@ -2299,20 +2312,29 @@ fdc_reset(void *priv) fdc_update_drv2en(fdc, 1); fdc_update_rates(fdc); - fdc->fifo = 0; + fdc->fifo = 0; fdc->tfifo = 1; if (fdc->flags & FDC_FLAG_PCJR) { - fdc->dma = 0; - fdc->specify[1] = 1; + fdc->dma = 0; + fdc->specify[1] = 1; + } else if (fdc->flags & FDC_FLAG_SEC) { + fdc->dma = 1; + fdc->specify[1] = 0; + } else if (fdc->flags & FDC_FLAG_TER) { + fdc->dma = 1; + fdc->specify[1] = 0; + } else if (fdc->flags & FDC_FLAG_QUA) { + fdc->dma = 1; + fdc->specify[1] = 0; } else { - fdc->dma = 1; - fdc->specify[1] = 0; + fdc->dma = 1; + fdc->specify[1] = 0; } fdc->config = 0x20; fdc->pretrk = 0; - fdc->swwp = 0; + fdc->swwp = 0; fdc->disable_write = 0; fdc_ctrl_reset(fdc); @@ -2320,15 +2342,22 @@ fdc_reset(void *priv) fdc->max_track = (fdc->flags & FDC_FLAG_MORE_TRACKS) ? 85 : 79; fdc_remove(fdc); - fdc_set_base(fdc, (fdc->flags & FDC_FLAG_PCJR) ? FDC_PRIMARY_PCJR_ADDR : FDC_PRIMARY_ADDR); + if (fdc->flags & FDC_FLAG_SEC) { + fdc_set_base(fdc, FDC_SECONDARY_ADDR); + } else if (fdc->flags & FDC_FLAG_TER) { + fdc_set_base(fdc, FDC_TERTIARY_ADDR); + } else if (fdc->flags & FDC_FLAG_QUA) { + fdc_set_base(fdc, FDC_QUATERNARY_ADDR); + } else { + fdc_set_base(fdc, (fdc->flags & FDC_FLAG_PCJR) ? FDC_PRIMARY_PCJR_ADDR : FDC_PRIMARY_ADDR); + } current_drive = 0; - for (i = 0; i < FDD_NUM; i++) - ui_sb_update_icon(SB_FLOPPY | i, 0); + for (uint8_t i = 0; i < FDD_NUM; i++) + ui_sb_update_icon(SB_FLOPPY | i, 0); } - static void fdc_close(void *priv) { @@ -2342,7 +2371,6 @@ fdc_close(void *priv) free(fdc); } - static void * fdc_init(const device_t *info) { @@ -2351,12 +2379,25 @@ fdc_init(const device_t *info) fdc->flags = info->local; - fdc->irq = FDC_PRIMARY_IRQ; + if (fdc->flags & FDC_FLAG_SEC) + fdc->irq = FDC_SECONDARY_IRQ; + else if (fdc->flags & FDC_FLAG_TER) + fdc->irq = FDC_TERTIARY_IRQ; + else if (fdc->flags & FDC_FLAG_QUA) + fdc->irq = FDC_QUATERNARY_IRQ; + else + fdc->irq = FDC_PRIMARY_IRQ; if (fdc->flags & FDC_FLAG_PCJR) - timer_add(&fdc->watchdog_timer, fdc_watchdog_poll, fdc, 0); + timer_add(&fdc->watchdog_timer, fdc_watchdog_poll, fdc, 0); + else if (fdc->flags & FDC_FLAG_SEC) + fdc->dma_ch = FDC_SECONDARY_DMA; + else if (fdc->flags & FDC_FLAG_TER) + fdc->dma_ch = FDC_TERTIARY_DMA; + else if (fdc->flags & FDC_FLAG_QUA) + fdc->dma_ch = FDC_QUATERNARY_DMA; else - fdc->dma_ch = FDC_PRIMARY_DMA; + fdc->dma_ch = FDC_PRIMARY_DMA; fdc_log("FDC added: %04X (flags: %08X)\n", fdc->base_address, fdc->flags); @@ -2374,156 +2415,288 @@ fdc_init(const device_t *info) return fdc; } - void fdc_3f1_enable(fdc_t *fdc, int enable) { fdc->enable_3f1 = enable; } - - - const device_t fdc_xt_device = { - "PC/XT Floppy Drive Controller", - "fdc_xt", - 0, - 0, - fdc_init, - fdc_close, - fdc_reset, - { NULL }, NULL, NULL + .name = "PC/XT Floppy Drive Controller", + .internal_name = "fdc_xt", + .flags = 0, + .local = 0, + .init = fdc_init, + .close = fdc_close, + .reset = fdc_reset, + { .available = NULL }, + .speed_changed = NULL, + .force_redraw = NULL, + .config = NULL +}; + +const device_t fdc_xt_sec_device = { + .name = "PC/XT Floppy Drive Controller (Secondary)", + .internal_name = "fdc_xt_sec", + .flags = FDC_FLAG_SEC, + .local = 0, + .init = fdc_init, + .close = fdc_close, + .reset = fdc_reset, + { .available = NULL }, + .speed_changed = NULL, + .force_redraw = NULL, + .config = NULL +}; + +const device_t fdc_xt_ter_device = { + .name = "PC/XT Floppy Drive Controller (Tertiary)", + .internal_name = "fdc_xt_ter", + .flags = FDC_FLAG_TER, + .local = 0, + .init = fdc_init, + .close = fdc_close, + .reset = fdc_reset, + { .available = NULL }, + .speed_changed = NULL, + .force_redraw = NULL, + .config = NULL +}; + +const device_t fdc_xt_qua_device = { + .name = "PC/XT Floppy Drive Controller (Quaternary)", + .internal_name = "fdc_xt_qua", + .flags = FDC_FLAG_QUA, + .local = 0, + .init = fdc_init, + .close = fdc_close, + .reset = fdc_reset, + { .available = NULL }, + .speed_changed = NULL, + .force_redraw = NULL, + .config = NULL }; const device_t fdc_xt_t1x00_device = { - "PC/XT Floppy Drive Controller (Toshiba)", - "fdc_xt_t1x00", - 0, - FDC_FLAG_TOSHIBA, - fdc_init, - fdc_close, - fdc_reset, - { NULL }, NULL, NULL + .name = "PC/XT Floppy Drive Controller (Toshiba)", + .internal_name = "fdc_xt_t1x00", + .flags = 0, + .local = FDC_FLAG_TOSHIBA, + .init = fdc_init, + .close = fdc_close, + .reset = fdc_reset, + { .available = NULL }, + .speed_changed = NULL, + .force_redraw = NULL, + .config = NULL }; const device_t fdc_xt_amstrad_device = { - "PC/XT Floppy Drive Controller (Amstrad)", - "fdc_xt_amstrad", - 0, - FDC_FLAG_DISKCHG_ACTLOW | FDC_FLAG_AMSTRAD, - fdc_init, - fdc_close, - fdc_reset, - { NULL }, NULL, NULL + .name = "PC/XT Floppy Drive Controller (Amstrad)", + .internal_name = "fdc_xt_amstrad", + .flags = 0, + .local = FDC_FLAG_DISKCHG_ACTLOW | FDC_FLAG_AMSTRAD, + .init = fdc_init, + .close = fdc_close, + .reset = fdc_reset, + { .available = NULL }, + .speed_changed = NULL, + .force_redraw = NULL, + .config = NULL }; const device_t fdc_xt_tandy_device = { - "PC/XT Floppy Drive Controller (Tandy)", - "fdc_xt_tandy", - 0, - FDC_FLAG_AMSTRAD, - fdc_init, - fdc_close, - fdc_reset, - { NULL }, NULL, NULL + .name = "PC/XT Floppy Drive Controller (Tandy)", + .internal_name = "fdc_xt_tandy", + .flags = 0, + .local = FDC_FLAG_AMSTRAD, + .init = fdc_init, + .close = fdc_close, + .reset = fdc_reset, + { .available = NULL }, + .speed_changed = NULL, + .force_redraw = NULL, + .config = NULL }; - const device_t fdc_pcjr_device = { - "PCjr Floppy Drive Controller", - "fdc_pcjr", - 0, - FDC_FLAG_PCJR, - fdc_init, - fdc_close, - fdc_reset, - { NULL }, NULL, NULL + .name = "PCjr Floppy Drive Controller", + .internal_name = "fdc_pcjr", + .flags = 0, + .local = FDC_FLAG_PCJR, + .init = fdc_init, + .close = fdc_close, + .reset = fdc_reset, + { .available = NULL }, + .speed_changed = NULL, + .force_redraw = NULL, + .config = NULL }; const device_t fdc_at_device = { - "PC/AT Floppy Drive Controller", - "fdc_at", - 0, - FDC_FLAG_AT, - fdc_init, - fdc_close, - fdc_reset, - { NULL }, NULL, NULL + .name = "PC/AT Floppy Drive Controller", + .internal_name = "fdc_at", + .flags = 0, + .local = FDC_FLAG_AT, + .init = fdc_init, + .close = fdc_close, + .reset = fdc_reset, + { .available = NULL }, + .speed_changed = NULL, + .force_redraw = NULL, + .config = NULL +}; + +const device_t fdc_at_sec_device = { + .name = "PC/AT Floppy Drive Controller (Secondary)", + .internal_name = "fdc_at_sec", + .flags = 0, + .local = FDC_FLAG_AT | FDC_FLAG_SEC, + .init = fdc_init, + .close = fdc_close, + .reset = fdc_reset, + { .available = NULL }, + .speed_changed = NULL, + .force_redraw = NULL, + .config = NULL +}; + +const device_t fdc_at_ter_device = { + .name = "PC/AT Floppy Drive Controller (Tertiary)", + .internal_name = "fdc_at_ter", + .flags = 0, + .local = FDC_FLAG_AT | FDC_FLAG_TER, + .init = fdc_init, + .close = fdc_close, + .reset = fdc_reset, + { .available = NULL }, + .speed_changed = NULL, + .force_redraw = NULL, + .config = NULL +}; + +const device_t fdc_at_qua_device = { + .name = "PC/AT Floppy Drive Controller (Quaternary)", + .internal_name = "fdc_at_qua", + .flags = 0, + .local = FDC_FLAG_AT | FDC_FLAG_QUA, + .init = fdc_init, + .close = fdc_close, + .reset = fdc_reset, + { .available = NULL }, + .speed_changed = NULL, + .force_redraw = NULL, + .config = NULL }; const device_t fdc_at_actlow_device = { - "PC/AT Floppy Drive Controller (Active low)", - "fdc_at_actlow", - 0, - FDC_FLAG_DISKCHG_ACTLOW | FDC_FLAG_AT, - fdc_init, - fdc_close, - fdc_reset, - { NULL }, NULL, NULL + .name = "PC/AT Floppy Drive Controller (Active low)", + .internal_name = "fdc_at_actlow", + .flags = 0, + .local = FDC_FLAG_DISKCHG_ACTLOW | FDC_FLAG_AT, + .init = fdc_init, + .close = fdc_close, + .reset = fdc_reset, + { .available = NULL }, + .speed_changed = NULL, + .force_redraw = NULL, + .config = NULL }; const device_t fdc_at_ps1_device = { - "PC/AT Floppy Drive Controller (PS/1, PS/2 ISA)", - "fdc_at_ps1", - 0, - FDC_FLAG_DISKCHG_ACTLOW | FDC_FLAG_AT | FDC_FLAG_PS1, - fdc_init, - fdc_close, - fdc_reset, - { NULL }, NULL, NULL + .name = "PC/AT Floppy Drive Controller (PS/1, PS/2 ISA)", + .internal_name = "fdc_at_ps1", + .flags = 0, + .local = FDC_FLAG_DISKCHG_ACTLOW | FDC_FLAG_AT | FDC_FLAG_PS1, + .init = fdc_init, + .close = fdc_close, + .reset = fdc_reset, + { .available = NULL }, + .speed_changed = NULL, + .force_redraw = NULL, + .config = NULL }; const device_t fdc_at_smc_device = { - "PC/AT Floppy Drive Controller (SM(s)C FDC37Cxxx)", - "fdc_at_smc", - 0, - FDC_FLAG_AT | FDC_FLAG_SUPERIO, - fdc_init, - fdc_close, - fdc_reset, - { NULL }, NULL, NULL + .name = "PC/AT Floppy Drive Controller (SM(s)C FDC37Cxxx)", + .internal_name = "fdc_at_smc", + .flags = 0, + .local = FDC_FLAG_AT | FDC_FLAG_SUPERIO, + .init = fdc_init, + .close = fdc_close, + .reset = fdc_reset, + { .available = NULL }, + .speed_changed = NULL, + .force_redraw = NULL, + .config = NULL +}; + +const device_t fdc_at_ali_device = { + .name = "PC/AT Floppy Drive Controller (ALi M512x/M1543C)", + .internal_name = "fdc_at_ali", + .flags = 0, + .local = FDC_FLAG_AT | FDC_FLAG_SUPERIO | FDC_FLAG_ALI, + .init = fdc_init, + .close = fdc_close, + .reset = fdc_reset, + { .available = NULL }, + .speed_changed = NULL, + .force_redraw = NULL, + .config = NULL }; const device_t fdc_at_winbond_device = { - "PC/AT Floppy Drive Controller (Winbond W83x77F)", - "fdc_at_winbond", - 0, - FDC_FLAG_AT | FDC_FLAG_SUPERIO | FDC_FLAG_START_RWC_1 | FDC_FLAG_MORE_TRACKS, - fdc_init, - fdc_close, - fdc_reset, - { NULL }, NULL, NULL + .name = "PC/AT Floppy Drive Controller (Winbond W83x77F)", + .internal_name = "fdc_at_winbond", + .flags = 0, + .local = FDC_FLAG_AT | FDC_FLAG_SUPERIO | FDC_FLAG_START_RWC_1 | FDC_FLAG_MORE_TRACKS, + .init = fdc_init, + .close = fdc_close, + .reset = fdc_reset, + { .available = NULL }, + .speed_changed = NULL, + .force_redraw = NULL, + .config = NULL }; const device_t fdc_at_nsc_device = { - "PC/AT Floppy Drive Controller (NSC PC8730x)", - "fdc_at_nsc", - 0, - FDC_FLAG_AT | FDC_FLAG_MORE_TRACKS | FDC_FLAG_NSC, - fdc_init, - fdc_close, - fdc_reset, - { NULL }, NULL, NULL + .name = "PC/AT Floppy Drive Controller (NSC PC8730x)", + .internal_name = "fdc_at_nsc", + .flags = 0, + .local = FDC_FLAG_AT | FDC_FLAG_MORE_TRACKS | FDC_FLAG_NSC, + .init = fdc_init, + .close = fdc_close, + .reset = fdc_reset, + { .available = NULL }, + .speed_changed = NULL, + .force_redraw = NULL, + .config = NULL }; const device_t fdc_dp8473_device = { - "NS DP8473 Floppy Drive Controller", - "fdc_dp8473", - 0, - FDC_FLAG_AT | FDC_FLAG_NSC, - fdc_init, - fdc_close, - fdc_reset, - { NULL }, NULL, NULL + .name = "NS DP8473 Floppy Drive Controller", + .internal_name = "fdc_dp8473", + .flags = 0, + .local = FDC_FLAG_AT | FDC_FLAG_NSC, + .init = fdc_init, + .close = fdc_close, + .reset = fdc_reset, + { .available = NULL }, + .speed_changed = NULL, + .force_redraw = NULL, + .config = NULL }; const device_t fdc_um8398_device = { - "UMC UM8398 Floppy Drive Controller", - "fdc_um8398", - 0, - FDC_FLAG_UMC, - fdc_init, - fdc_close, - fdc_reset, - { NULL }, NULL, NULL + .name = "UMC UM8398 Floppy Drive Controller", + .internal_name = "fdc_um8398", + .flags = 0, + .local = FDC_FLAG_UMC, + .init = fdc_init, + .close = fdc_close, + .reset = fdc_reset, + { .available = NULL }, + .speed_changed = NULL, + .force_redraw = NULL, + .config = NULL }; diff --git a/src/floppy/fdc_magitronic.c b/src/floppy/fdc_magitronic.c index e0845ae7d..084ce8c81 100644 --- a/src/floppy/fdc_magitronic.c +++ b/src/floppy/fdc_magitronic.c @@ -1,17 +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. + * 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. + * This file is part of the 86Box distribution. * - * Implementation of the Magitronic B215 XT-FDC Controller. + * Implementation of the Magitronic B215 XT-FDC Controller. * - * Authors: Tiseno100 - * - * Copyright 2021 Tiseno100 + * Authors: Tiseno100 * + * Copyright 2021 Tiseno100 */ #include @@ -30,21 +29,21 @@ #include <86box/fdd.h> #include <86box/fdc.h> #include <86box/fdc_ext.h> +#include <86box/plat_unused.h> -#define ROM_B215 "roms/floppy/magitronic/Magitronic B215 - BIOS ROM.bin" -#define ROM_ADDR (uint32_t)(device_get_config_hex20("bios_addr") & 0x000fffff) +#define ROM_B215 "roms/floppy/magitronic/Magitronic B215 - BIOS ROM.bin" +#define ROM_ADDR (uint32_t)(device_get_config_hex20("bios_addr") & 0x000fffff) -#define DRIVE_SELECT (int)(real_drive(dev->fdc_controller, i)) -typedef struct -{ +#define DRIVE_SELECT (int) (real_drive(dev->fdc_controller, i)) +typedef struct b215_t { fdc_t *fdc_controller; - rom_t rom; + rom_t rom; } b215_t; static uint8_t -b215_read(uint16_t addr, void *priv) +b215_read(UNUSED(uint16_t addr), void *priv) { - b215_t *dev = (b215_t *)priv; + b215_t *dev = (b215_t *) priv; /* Register 3F0h @@ -59,19 +58,15 @@ b215_read(uint16_t addr, void *priv) */ int drive_spec[2]; - for (int i = 0; i <= 1; i++) - { - if (fdd_is_525(DRIVE_SELECT)) - { + for (uint8_t i = 0; i <= 1; i++) { + if (fdd_is_525(DRIVE_SELECT)) { if (!fdd_is_dd(DRIVE_SELECT)) drive_spec[i] = 1; else if (fdd_doublestep_40(DRIVE_SELECT)) drive_spec[i] = 2; else drive_spec[i] = 0; - } - else - { + } else { if (fdd_is_dd(DRIVE_SELECT) && !fdd_is_double_sided(DRIVE_SELECT)) drive_spec[i] = 0; else if (fdd_is_dd(DRIVE_SELECT) && fdd_is_double_sided(DRIVE_SELECT)) @@ -87,15 +82,15 @@ b215_read(uint16_t addr, void *priv) static void b215_close(void *priv) { - b215_t *dev = (b215_t *)priv; + b215_t *dev = (b215_t *) priv; free(dev); } static void * -b215_init(const device_t *info) +b215_init(UNUSED(const device_t *info)) { - b215_t *dev = (b215_t *)malloc(sizeof(b215_t)); + b215_t *dev = (b215_t *) malloc(sizeof(b215_t)); memset(dev, 0, sizeof(b215_t)); rom_init(&dev->rom, ROM_B215, ROM_ADDR, 0x2000, 0x1fff, 0, MEM_MAPPING_EXTERNAL); @@ -106,40 +101,42 @@ b215_init(const device_t *info) return dev; } -static int b215_available(void) +static int +b215_available(void) { return rom_present(ROM_B215); } static const device_config_t b215_config[] = { + // clang-format off { - "bios_addr", "BIOS Address:", CONFIG_HEX20, "", 0xca000, "", { 0 }, - { - { - "CA00H", 0xca000 - }, - { - "CC00H", 0xcc000 - }, - { - "" - } - } + .name = "bios_addr", + .description = "BIOS Address:", + .type = CONFIG_HEX20, + .default_string = "", + .default_int = 0xca000, + .file_filter = "", + .spinner = { 0 }, + .selection = { + { .description = "CA00H", .value = 0xca000 }, + { .description = "CC00H", .value = 0xcc000 }, + { .description = "" } + } }, - { - "", "", -1 - } + { .name = "", .description = "", .type = CONFIG_END } + // clang-format on }; const device_t fdc_b215_device = { - "Magitronic B215", - "b215", - DEVICE_ISA, - 0, - b215_init, - b215_close, - NULL, - {b215_available}, - NULL, - NULL, - b215_config}; + .name = "Magitronic B215", + .internal_name = "b215", + .flags = DEVICE_ISA, + .local = 0, + .init = b215_init, + .close = b215_close, + .reset = NULL, + { .available = b215_available }, + .speed_changed = NULL, + .force_redraw = NULL, + .config = b215_config +}; diff --git a/src/floppy/fdc_monster.c b/src/floppy/fdc_monster.c new file mode 100644 index 000000000..1629ac1c4 --- /dev/null +++ b/src/floppy/fdc_monster.c @@ -0,0 +1,224 @@ +/* + * 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 Sergey Kiselev's Monster Floppy Disk Controller. + * + * + * + * Authors: Jasmine Iwanek, + * + * Copyright 2022 Jasmine Iwanek. + */ + +#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/rom.h> +#include <86box/machine.h> +#include <86box/timer.h> +#include <86box/fdd.h> +#include <86box/fdc.h> +#include <86box/fdc_ext.h> +#include <86box/plat_unused.h> + +#define BIOS_ADDR (uint32_t)(device_get_config_hex20("bios_addr") & 0x000fffff) +#define ROM_MONSTER_FDC "roms/floppy/monster-fdc/floppy_bios.bin" + +typedef struct monster_fdc_t { + rom_t bios_rom; + fdc_t *fdc_pri; + fdc_t *fdc_sec; +} monster_fdc_t; + +static void +monster_fdc_close(void *priv) +{ + monster_fdc_t *dev = (monster_fdc_t *) priv; + + free(dev); +} + +static void * +monster_fdc_init(UNUSED(const device_t *info)) +{ + monster_fdc_t *dev; + + dev = (monster_fdc_t *) malloc(sizeof(monster_fdc_t)); + memset(dev, 0, sizeof(monster_fdc_t)); + +#if 0 + uint8_t sec_irq = device_get_config_int("sec_irq"); + uint8_t sec_dma = device_get_config_int("sec_dma"); +#endif + + if (BIOS_ADDR != 0) + rom_init(&dev->bios_rom, ROM_MONSTER_FDC, BIOS_ADDR, 0x2000, 0x1ffff, 0, MEM_MAPPING_EXTERNAL); + + // Primary FDC + dev->fdc_pri = device_add(&fdc_at_device); + +#if 0 + // Secondary FDC + uint8_t sec_enabled = device_get_config_int("sec_enabled"); + if (sec_enabled) + dev->fdc_sec = device_add(&fdc_at_sec_device); + fdc_set_irq(dev->fdc_sec, sec_irq); + fdc_set_dma_ch(dev->fdc_sec, sec_dma); +#endif + +#if 0 + uint8_t rom_writes_enabled = device_get_config_int("rom_writes_enabled"); +#endif + + return dev; +} + +static int +monster_fdc_available(void) +{ + return rom_present(ROM_MONSTER_FDC); +} + +static const device_config_t monster_fdc_config[] = { + // clang-format off +#if 0 + { + .name = "sec_enabled", + .description = "Enable Secondary Controller", + .type = CONFIG_BINARY, + .default_string = "", + .default_int = 0 + }, + { + .name = "sec_irq", + .description = "Secondary Controller IRQ", + .type = CONFIG_SELECTION, + .default_string = "", + .default_int = 6, + .file_filter = "", + .spinner = { 0 }, + .selection = { + { + .description = "IRQ 2", + .value = 2 + }, + { + .description = "IRQ 3", + .value = 3 + }, + { + .description = "IRQ 4", + .value = 4 + }, + { + .description = "IRQ 5", + .value = 5 + }, + { + .description = "IRQ 6", + .value = 6 + }, + { + .description = "IRQ 7", + .value = 7 + }, + { .description = "" } + } + }, + { + .name = "sec_dma", + .description = "Secondary Controller DMA", + .type = CONFIG_SELECTION, + .default_string = "", + .default_int = 2, + .file_filter = "", + .spinner = { 0 }, + .selection = { + { + .description = "DMA 1", + .value = 1 + }, + { + .description = "DMA 2", + .value = 2 + }, + { + .description = "DMA 3", + .value = 3 + }, + { .description = "" } + } + }, +#endif + { + .name = "bios_addr", + .description = "BIOS Address:", + .type = CONFIG_HEX20, + .default_string = "", + .default_int = 0xc8000, + .file_filter = "", + .spinner = { 0 }, + .selection = { + { .description = "Disabled", .value = 0 }, + { .description = "C000H", .value = 0xc0000 }, + { .description = "C800H", .value = 0xc8000 }, + { .description = "D000H", .value = 0xd0000 }, + { .description = "D800H", .value = 0xd8000 }, + { .description = "E000H", .value = 0xe0000 }, + { .description = "E800H", .value = 0xe8000 }, + { .description = "" } + } + }, +#if 0 + { + .name = "bios_size", + .description = "BIOS Size:", + .type = CONFIG_HEX20, + .default_string = "32", + .default_int = 0xc8000, + .file_filter = "", + .spinner = { 0 }, + .selection = { + { .description = "8K", .value = 8 }, + { .description = "32K", .value = 32 }, + { .description = "" } + } + }, + { + .name = "rom_writes_enabled", + .description = "Enable BIOS extension ROM Writes", + .type = CONFIG_BINARY, + .default_string = "", + .default_int = 0 + }, +#endif + { .name = "", .description = "", .type = CONFIG_END } + // clang-format on +}; + +const device_t fdc_monster_device = { + .name = "Monster FDC Floppy Drive Controller", + .internal_name = "monster_fdc", + .flags = DEVICE_ISA, + .local = 0, + .init = monster_fdc_init, + .close = monster_fdc_close, + .reset = NULL, + { .available = monster_fdc_available }, + .speed_changed = NULL, + .force_redraw = NULL, + .config = monster_fdc_config +}; diff --git a/src/floppy/fdc_pii15xb.c b/src/floppy/fdc_pii15xb.c index 3339aa6a1..5fd38d250 100644 --- a/src/floppy/fdc_pii15xb.c +++ b/src/floppy/fdc_pii15xb.c @@ -1,48 +1,46 @@ /* - * VARCem Virtual ARchaeological Computer EMulator. - * An emulator of (mostly) x86-based PC systems and devices, - * using the ISA,EISA,VLB,MCA and PCI system buses, roughly - * spanning the era between 1981 and 1995. + * VARCem Virtual ARchaeological Computer EMulator. + * An emulator of (mostly) x86-based PC systems and devices, + * using the ISA,EISA,VLB,MCA and PCI system buses, roughly + * spanning the era between 1981 and 1995. * - * This file is part of the VARCem Project. + * Implementation of the DTK MiniMicro series of Floppy Disk Controllers. + * Original code from VARCem. Fully rewritten, fixed and improved for 86Box. * - * Implementation of the DTK MiniMicro series of Floppy Disk Controllers. - * Original code from VARCem. Fully rewritten, fixed and improved for 86Box. - * - * Author: Fred N. van Kempen, , + * Authors: Fred N. van Kempen, , * Tiseno100 * - * Copyright 2019 Fred N. van Kempen. - * Copyright 2021 Tiseno100 + * Copyright 2019 Fred N. van Kempen. + * Copyright 2021 Tiseno100 * - * Redistribution and use in source and binary forms, with - * or without modification, are permitted provided that the - * following conditions are met: + * Redistribution and use in source and binary forms, with + * or without modification, are permitted provided that the + * following conditions are met: * - * 1. Redistributions of source code must retain the entire - * above notice, this list of conditions and the following - * disclaimer. + * 1. Redistributions of source code must retain the entire + * above notice, this list of conditions and the following + * disclaimer. * - * 2. Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the - * following disclaimer in the documentation and/or other - * materials provided with the distribution. + * 2. Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the + * following disclaimer in the documentation and/or other + * materials provided with the distribution. * - * 3. Neither the name of the copyright holder nor the names - * of its contributors may be used to endorse or promote - * products derived from this software without specific - * prior written permission. + * 3. Neither the name of the copyright holder nor the names + * of its contributors may be used to endorse or promote + * products derived from this software without specific + * prior written permission. * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A - * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ @@ -76,21 +74,20 @@ MiniMicro 4 also won't work with the XT FDC which the Zilog claims to be. #include <86box/fdc.h> #include <86box/fdc_ext.h> -#define DTK_VARIANT ((info->local == 158) ? ROM_PII_158B : ROM_PII_151B) -#define DTK_CHIP ((info->local == 158) ? &fdc_xt_device : &fdc_dp8473_device) -#define BIOS_ADDR (uint32_t)(device_get_config_hex20("bios_addr") & 0x000fffff) +#define DTK_VARIANT ((info->local == 158) ? ROM_PII_158B : ROM_PII_151B) +#define DTK_CHIP ((info->local == 158) ? &fdc_xt_device : &fdc_dp8473_device) +#define BIOS_ADDR (uint32_t)(device_get_config_hex20("bios_addr") & 0x000fffff) #define ROM_PII_151B "roms/floppy/dtk/pii-151b.rom" #define ROM_PII_158B "roms/floppy/dtk/pii-158b.rom" -typedef struct -{ +typedef struct pii_t { rom_t bios_rom; } pii_t; static void pii_close(void *priv) { - pii_t *dev = (pii_t *)priv; + pii_t *dev = (pii_t *) priv; free(dev); } @@ -100,7 +97,7 @@ pii_init(const device_t *info) { pii_t *dev; - dev = (pii_t *)malloc(sizeof(pii_t)); + dev = (pii_t *) malloc(sizeof(pii_t)); memset(dev, 0, sizeof(pii_t)); if (BIOS_ADDR != 0) @@ -111,64 +108,64 @@ pii_init(const device_t *info) return dev; } -static int pii_151b_available(void) +static int +pii_151b_available(void) { return rom_present(ROM_PII_151B); } -static int pii_158_available(void) +static int +pii_158_available(void) { return rom_present(ROM_PII_158B); } static const device_config_t pii_config[] = { + // clang-format off { - "bios_addr", "BIOS Address:", CONFIG_HEX20, "", 0xce000, "", { 0 }, - { - { - "Disabled", 0 - }, - { - "CA00H", 0xca000 - }, - { - "CC00H", 0xcc000 - }, - { - "CE00H", 0xce000 - }, - { - "" - } - } + .name = "bios_addr", + .description = "BIOS Address:", + .type = CONFIG_HEX20, + .default_string = "", + .default_int = 0xce000, + .file_filter = "", + .spinner = { 0 }, + .selection = { + { .description = "Disabled", .value = 0 }, + { .description = "CA00H", .value = 0xca000 }, + { .description = "CC00H", .value = 0xcc000 }, + { .description = "CE00H", .value = 0xce000 }, + { .description = "" } + } }, - { - "", "", -1 - } + { .name = "", .description = "", .type = CONFIG_END } + // clang-format on }; const device_t fdc_pii151b_device = { - "DTK PII-151B (MiniMicro) Floppy Drive Controller", - "dtk_pii151b", - DEVICE_ISA, - 151, - pii_init, - pii_close, - NULL, - {pii_151b_available}, - NULL, - NULL, - pii_config}; + .name = "DTK PII-151B (MiniMicro) Floppy Drive Controller", + .internal_name = "dtk_pii151b", + .flags = DEVICE_ISA, + .local = 151, + .init = pii_init, + .close = pii_close, + .reset = NULL, + { .available = pii_151b_available }, + .speed_changed = NULL, + .force_redraw = NULL, + .config = pii_config +}; const device_t fdc_pii158b_device = { - "DTK PII-158B (MiniMicro4) Floppy Drive Controller", - "dtk_pii158b", - DEVICE_ISA, - 158, - pii_init, - pii_close, - NULL, - {pii_158_available}, - NULL, - NULL, - pii_config}; + .name = "DTK PII-158B (MiniMicro4) Floppy Drive Controller", + .internal_name = "dtk_pii158b", + .flags = DEVICE_ISA, + .local = 158, + .init = pii_init, + .close = pii_close, + .reset = NULL, + { .available = pii_158_available }, + .speed_changed = NULL, + .force_redraw = NULL, + .config = pii_config +}; diff --git a/src/floppy/fdd.c b/src/floppy/fdd.c index 72f79940b..09e791c4e 100644 --- a/src/floppy/fdd.c +++ b/src/floppy/fdd.c @@ -1,22 +1,22 @@ /* - * 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. + * 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. + * This file is part of the 86Box distribution. * - * Implementation of the floppy drive emulation. + * Implementation of the floppy drive emulation. * * * - * Authors: Sarah Walker, - * Miran Grca, - * Fred N. van Kempen, + * Authors: Sarah Walker, + * Miran Grca, + * Fred N. van Kempen, * - * Copyright 2008-2019 Sarah Walker. - * Copyright 2016-2019 Miran Grca. - * Copyright 2018,2019 Fred N. van Kempen. + * Copyright 2008-2019 Sarah Walker. + * Copyright 2016-2019 Miran Grca. + * Copyright 2018-2019 Fred N. van Kempen. */ #include #include @@ -26,6 +26,7 @@ #define HAVE_STDARG_H #include <86box/86box.h> #include <86box/timer.h> +#include <86box/path.h> #include <86box/plat.h> #include <86box/ui.h> #include <86box/fdd.h> @@ -38,34 +39,32 @@ #include <86box/fdd_td0.h> #include <86box/fdc.h> - /* Flags: - Bit 0: 300 rpm supported; - Bit 1: 360 rpm supported; - Bit 2: size (0 = 3.5", 1 = 5.25"); - Bit 3: sides (0 = 1, 1 = 2); - Bit 4: double density supported; - Bit 5: high density supported; - Bit 6: extended density supported; - Bit 7: double step for 40-track media; - Bit 8: invert DENSEL polarity; - Bit 9: ignore DENSEL; - Bit 10: drive is a PS/2 drive; + Bit 0: 300 rpm supported; + Bit 1: 360 rpm supported; + Bit 2: size (0 = 3.5", 1 = 5.25"); + Bit 3: sides (0 = 1, 1 = 2); + Bit 4: double density supported; + Bit 5: high density supported; + Bit 6: extended density supported; + Bit 7: double step for 40-track media; + Bit 8: invert DENSEL polarity; + Bit 9: ignore DENSEL; + Bit 10: drive is a PS/2 drive; */ -#define FLAG_RPM_300 1 -#define FLAG_RPM_360 2 -#define FLAG_525 4 -#define FLAG_DS 8 -#define FLAG_HOLE0 16 -#define FLAG_HOLE1 32 -#define FLAG_HOLE2 64 -#define FLAG_DOUBLE_STEP 128 -#define FLAG_INVERT_DENSEL 256 -#define FLAG_IGNORE_DENSEL 512 -#define FLAG_PS2 1024 +#define FLAG_RPM_300 1 +#define FLAG_RPM_360 2 +#define FLAG_525 4 +#define FLAG_DS 8 +#define FLAG_HOLE0 16 +#define FLAG_HOLE1 32 +#define FLAG_HOLE2 64 +#define FLAG_DOUBLE_STEP 128 +#define FLAG_INVERT_DENSEL 256 +#define FLAG_IGNORE_DENSEL 512 +#define FLAG_PS2 1024 - -typedef struct { +typedef struct fdd_t { int type; int track; int densel; @@ -74,28 +73,29 @@ typedef struct { int check_bpb; } fdd_t; +fdd_t fdd[FDD_NUM]; -fdd_t fdd[FDD_NUM]; +char floppyfns[FDD_NUM][512]; +char *fdd_image_history[FDD_NUM][FLOPPY_IMAGE_HISTORY]; -char floppyfns[FDD_NUM][512]; +pc_timer_t fdd_poll_time[FDD_NUM]; -pc_timer_t fdd_poll_time[FDD_NUM]; +static int fdd_notfound = 0; +static int driveloaders[FDD_NUM]; -static int fdd_notfound = 0, - driveloaders[FDD_NUM]; +int writeprot[FDD_NUM]; +int fwriteprot[FDD_NUM]; +int fdd_changed[FDD_NUM]; +int ui_writeprot[FDD_NUM] = { 0, 0, 0, 0 }; +int drive_empty[FDD_NUM] = { 1, 1, 1, 1 }; -int writeprot[FDD_NUM], fwriteprot[FDD_NUM], - fdd_changed[FDD_NUM], ui_writeprot[FDD_NUM] = {0, 0, 0, 0}, - drive_empty[FDD_NUM] = {1, 1, 1, 1}; +DRIVE drives[FDD_NUM]; -DRIVE drives[FDD_NUM]; +uint64_t motoron[FDD_NUM]; -uint64_t motoron[FDD_NUM]; - -fdc_t *fdd_fdc; - -d86f_handler_t d86f_handler[FDD_NUM]; +fdc_t *fdd_fdc; +d86f_handler_t d86f_handler[FDD_NUM]; static const struct { @@ -103,254 +103,237 @@ static const struct void (*load)(int drive, char *fn); void (*close)(int drive); int size; -} loaders[]= -{ - {"001", img_load, img_close, -1}, - {"002", img_load, img_close, -1}, - {"003", img_load, img_close, -1}, - {"004", img_load, img_close, -1}, - {"005", img_load, img_close, -1}, - {"006", img_load, img_close, -1}, - {"007", img_load, img_close, -1}, - {"008", img_load, img_close, -1}, - {"009", img_load, img_close, -1}, - {"010", img_load, img_close, -1}, - {"12", img_load, img_close, -1}, - {"144", img_load, img_close, -1}, - {"360", img_load, img_close, -1}, - {"720", img_load, img_close, -1}, - {"86F", d86f_load, d86f_close, -1}, - {"BIN", img_load, img_close, -1}, - {"CQ", img_load, img_close, -1}, - {"CQM", img_load, img_close, -1}, - {"DDI", img_load, img_close, -1}, - {"DSK", img_load, img_close, -1}, - {"FDI", fdi_load, fdi_close, -1}, - {"FDF", img_load, img_close, -1}, - {"FLP", img_load, img_close, -1}, - {"HDM", img_load, img_close, -1}, - {"IMA", img_load, img_close, -1}, - {"IMD", imd_load, imd_close, -1}, - {"IMG", img_load, img_close, -1}, - {"JSON", json_load, json_close, -1}, - {"MFM", mfm_load, mfm_close, -1}, - {"TD0", td0_load, td0_close, -1}, - {"VFD", img_load, img_close, -1}, - {"XDF", img_load, img_close, -1}, - {0, 0, 0, 0} +} loaders[] = { + {"001", img_load, img_close, -1}, + { "002", img_load, img_close, -1}, + { "003", img_load, img_close, -1}, + { "004", img_load, img_close, -1}, + { "005", img_load, img_close, -1}, + { "006", img_load, img_close, -1}, + { "007", img_load, img_close, -1}, + { "008", img_load, img_close, -1}, + { "009", img_load, img_close, -1}, + { "010", img_load, img_close, -1}, + { "12", img_load, img_close, -1}, + { "144", img_load, img_close, -1}, + { "360", img_load, img_close, -1}, + { "720", img_load, img_close, -1}, + { "86F", d86f_load, d86f_close, -1}, + { "BIN", img_load, img_close, -1}, + { "CQ", img_load, img_close, -1}, + { "CQM", img_load, img_close, -1}, + { "DDI", img_load, img_close, -1}, + { "DSK", img_load, img_close, -1}, + { "FDI", fdi_load, fdi_close, -1}, + { "FDF", img_load, img_close, -1}, + { "FLP", img_load, img_close, -1}, + { "HDM", img_load, img_close, -1}, + { "IMA", img_load, img_close, -1}, + { "IMD", imd_load, imd_close, -1}, + { "IMG", img_load, img_close, -1}, + { "JSON", json_load, json_close, -1}, + { "MFM", mfm_load, mfm_close, -1}, + { "TD0", td0_load, td0_close, -1}, + { "VFD", img_load, img_close, -1}, + { "XDF", img_load, img_close, -1}, + { 0, 0, 0, 0 } }; - static const struct { - int max_track; - int flags; + int max_track; + int flags; const char *name; const char *internal_name; } drive_types[] = { { /*None*/ - 0, 0, "None", "none" + 0, 0, "None", "none" }, { /*5.25" 1DD*/ - 43, FLAG_RPM_300 | FLAG_525 | FLAG_HOLE0, "5.25\" 180k", "525_1dd" + 43, FLAG_RPM_300 | FLAG_525 | FLAG_HOLE0, "5.25\" 180k", "525_1dd" }, { /*5.25" DD*/ - 43, FLAG_RPM_300 | FLAG_525 | FLAG_DS | FLAG_HOLE0, "5.25\" 360k", "525_2dd" + 43, FLAG_RPM_300 | FLAG_525 | FLAG_DS | FLAG_HOLE0, "5.25\" 360k", "525_2dd" }, { /*5.25" QD*/ - 86, FLAG_RPM_300 | FLAG_525 | FLAG_DS | FLAG_HOLE0 | FLAG_DOUBLE_STEP, "5.25\" 720k", "525_2qd" + 86, FLAG_RPM_300 | FLAG_525 | FLAG_DS | FLAG_HOLE0 | FLAG_DOUBLE_STEP, "5.25\" 720k", "525_2qd" }, { /*5.25" HD PS/2*/ - 86, FLAG_RPM_360 | FLAG_525 | FLAG_DS | FLAG_HOLE0 | FLAG_HOLE1 | FLAG_DOUBLE_STEP | FLAG_INVERT_DENSEL | FLAG_PS2, "5.25\" 1.2M PS/2", "525_2hd_ps2" + 86, FLAG_RPM_360 | FLAG_525 | FLAG_DS | FLAG_HOLE0 | FLAG_HOLE1 | FLAG_DOUBLE_STEP | FLAG_INVERT_DENSEL | FLAG_PS2, "5.25\" 1.2M PS/2", "525_2hd_ps2" }, { /*5.25" HD*/ - 86, FLAG_RPM_360 | FLAG_525 | FLAG_DS | FLAG_HOLE0 | FLAG_HOLE1 | FLAG_DOUBLE_STEP, "5.25\" 1.2M", "525_2hd" + 86, FLAG_RPM_360 | FLAG_525 | FLAG_DS | FLAG_HOLE0 | FLAG_HOLE1 | FLAG_DOUBLE_STEP, "5.25\" 1.2M", "525_2hd" }, { /*5.25" HD Dual RPM*/ - 86, FLAG_RPM_300 | FLAG_RPM_360 | FLAG_525 | FLAG_DS | FLAG_HOLE0 | FLAG_HOLE1 | FLAG_DOUBLE_STEP, "5.25\" 1.2M 300/360 RPM", "525_2hd_dualrpm" + 86, FLAG_RPM_300 | FLAG_RPM_360 | FLAG_525 | FLAG_DS | FLAG_HOLE0 | FLAG_HOLE1 | FLAG_DOUBLE_STEP, "5.25\" 1.2M 300/360 RPM", "525_2hd_dualrpm" }, { /*3.5" 1DD*/ - 86, FLAG_RPM_300 | FLAG_HOLE0 | FLAG_DOUBLE_STEP, "3.5\" 360k", "35_1dd" + 86, FLAG_RPM_300 | FLAG_HOLE0 | FLAG_DOUBLE_STEP, "3.5\" 360k", "35_1dd" }, { /*3.5" DD*/ - 86, FLAG_RPM_300 | FLAG_DS | FLAG_HOLE0 | FLAG_DOUBLE_STEP, "3.5\" 720k", "35_2dd" + 86, FLAG_RPM_300 | FLAG_DS | FLAG_HOLE0 | FLAG_DOUBLE_STEP, "3.5\" 720k", "35_2dd" }, { /*3.5" HD PS/2*/ - 86, FLAG_RPM_300 | FLAG_DS | FLAG_HOLE0 | FLAG_HOLE1 | FLAG_DOUBLE_STEP | FLAG_INVERT_DENSEL | FLAG_PS2, "3.5\" 1.44M PS/2", "35_2hd_ps2" + 86, FLAG_RPM_300 | FLAG_DS | FLAG_HOLE0 | FLAG_HOLE1 | FLAG_DOUBLE_STEP | FLAG_INVERT_DENSEL | FLAG_PS2, "3.5\" 1.44M PS/2", "35_2hd_ps2" }, { /*3.5" HD*/ - 86, FLAG_RPM_300 | FLAG_DS | FLAG_HOLE0 | FLAG_HOLE1 | FLAG_DOUBLE_STEP, "3.5\" 1.44M", "35_2hd" + 86, FLAG_RPM_300 | FLAG_DS | FLAG_HOLE0 | FLAG_HOLE1 | FLAG_DOUBLE_STEP, "3.5\" 1.44M", "35_2hd" }, { /*3.5" HD PC-98*/ - 86, FLAG_RPM_300 | FLAG_RPM_360 | FLAG_DS | FLAG_HOLE0 | FLAG_HOLE1 | FLAG_DOUBLE_STEP | FLAG_INVERT_DENSEL, "3.5\" 1.25M PC-98", "35_2hd_nec" + 86, FLAG_RPM_300 | FLAG_RPM_360 | FLAG_DS | FLAG_HOLE0 | FLAG_HOLE1 | FLAG_DOUBLE_STEP | FLAG_INVERT_DENSEL, "3.5\" 1.25M PC-98", "35_2hd_nec" }, { /*3.5" HD 3-Mode*/ - 86, FLAG_RPM_300 | FLAG_RPM_360 | FLAG_DS | FLAG_HOLE0 | FLAG_HOLE1 | FLAG_DOUBLE_STEP, "3.5\" 1.44M 300/360 RPM", "35_2hd_3mode" + 86, FLAG_RPM_300 | FLAG_RPM_360 | FLAG_DS | FLAG_HOLE0 | FLAG_HOLE1 | FLAG_DOUBLE_STEP, "3.5\" 1.44M 300/360 RPM", "35_2hd_3mode" }, { /*3.5" ED*/ - 86, FLAG_RPM_300 | FLAG_DS | FLAG_HOLE0 | FLAG_HOLE1 | FLAG_HOLE2 | FLAG_DOUBLE_STEP, "3.5\" 2.88M", "35_2ed" + 86, FLAG_RPM_300 | FLAG_DS | FLAG_HOLE0 | FLAG_HOLE1 | FLAG_HOLE2 | FLAG_DOUBLE_STEP, "3.5\" 2.88M", "35_2ed" }, { /*End of list*/ - -1, -1, "", "" + -1, -1, "", "" } }; - #ifdef ENABLE_FDD_LOG int fdd_do_log = ENABLE_FDD_LOG; - static void fdd_log(const char *fmt, ...) { - va_list ap; + va_list ap; - if (fdd_do_log) - { - va_start(ap, fmt); - pclog_ex(fmt, ap); - va_end(ap); - } + if (fdd_do_log) { + va_start(ap, fmt); + pclog_ex(fmt, ap); + va_end(ap); + } } #else -#define fdd_log(fmt, ...) +# define fdd_log(fmt, ...) #endif - char * fdd_getname(int type) { - return (char *)drive_types[type].name; + return (char *) drive_types[type].name; } - char * fdd_get_internal_name(int type) { - return (char *)drive_types[type].internal_name; + return (char *) drive_types[type].internal_name; } - int fdd_get_from_internal_name(char *s) { int c = 0; while (strlen(drive_types[c].internal_name)) { - if (!strcmp((char *)drive_types[c].internal_name, s)) - return c; - c++; + if (!strcmp((char *) drive_types[c].internal_name, s)) + return c; + c++; } return 0; } - /* This is needed for the dump as 86F feature. */ void fdd_do_seek(int drive, int track) { if (drives[drive].seek) - drives[drive].seek(drive, track); + drives[drive].seek(drive, track); } - void fdd_forced_seek(int drive, int track_diff) { fdd[drive].track += track_diff; if (fdd[drive].track < 0) - fdd[drive].track = 0; + fdd[drive].track = 0; if (fdd[drive].track > drive_types[fdd[drive].type].max_track) - fdd[drive].track = drive_types[fdd[drive].type].max_track; + fdd[drive].track = drive_types[fdd[drive].type].max_track; fdd_do_seek(drive, fdd[drive].track); } - void fdd_seek(int drive, int track_diff) { if (!track_diff) - return; + return; fdd[drive].track += track_diff; if (fdd[drive].track < 0) - fdd[drive].track = 0; + fdd[drive].track = 0; if (fdd[drive].track > drive_types[fdd[drive].type].max_track) - fdd[drive].track = drive_types[fdd[drive].type].max_track; + fdd[drive].track = drive_types[fdd[drive].type].max_track; fdd_changed[drive] = 0; fdd_do_seek(drive, fdd[drive].track); } - int fdd_track0(int drive) { /* If drive is disabled, TRK0 never gets set. */ - if (!drive_types[fdd[drive].type].max_track) return 0; + if (!drive_types[fdd[drive].type].max_track) + return 0; return !fdd[drive].track; } - int fdd_current_track(int drive) { return fdd[drive].track; } - void fdd_set_densel(int densel) { - int i = 0; - - for (i = 0; i < 4; i++) { - if (drive_types[fdd[i].type].flags & FLAG_INVERT_DENSEL) - fdd[i].densel = densel ^ 1; - else - fdd[i].densel = densel; + for (uint8_t i = 0; i < FDD_NUM; i++) { + if (drive_types[fdd[i].type].flags & FLAG_INVERT_DENSEL) + fdd[i].densel = densel ^ 1; + else + fdd[i].densel = densel; } } - int fdd_getrpm(int drive) { int densel = 0; int hole; - hole = fdd_hole(drive); + hole = fdd_hole(drive); densel = fdd[drive].densel; if (drive_types[fdd[drive].type].flags & FLAG_INVERT_DENSEL) - densel ^= 1; + densel ^= 1; if (!(drive_types[fdd[drive].type].flags & FLAG_RPM_360)) - return 300; + return 300; if (!(drive_types[fdd[drive].type].flags & FLAG_RPM_300)) - return 360; + return 360; if (drive_types[fdd[drive].type].flags & FLAG_525) - return densel ? 360 : 300; + return densel ? 360 : 300; else { - /* fdd_hole(drive) returns 0 for double density media, 1 for high density, and 2 for extended density. */ - if (hole == 1) - return densel ? 300 : 360; - else - return 300; + /* fdd_hole(drive) returns 0 for double density media, 1 for high density, and 2 for extended density. */ + if (hole == 1) + return densel ? 300 : 360; + else + return 300; } } - int fdd_can_read_medium(int drive) { @@ -361,51 +344,50 @@ fdd_can_read_medium(int drive) return !!(drive_types[fdd[drive].type].flags & hole); } - int fdd_doublestep_40(int drive) { return !!(drive_types[fdd[drive].type].flags & FLAG_DOUBLE_STEP); } - void fdd_set_type(int drive, int type) { - int old_type = fdd[drive].type; + int old_type = fdd[drive].type; fdd[drive].type = type; if ((drive_types[old_type].flags ^ drive_types[type].flags) & FLAG_INVERT_DENSEL) - fdd[drive].densel ^= 1; + fdd[drive].densel ^= 1; } - int fdd_get_type(int drive) { return fdd[drive].type; } - int fdd_get_flags(int drive) { return drive_types[fdd[drive].type].flags; } - int fdd_is_525(int drive) { return drive_types[fdd[drive].type].flags & FLAG_525; } - int fdd_is_dd(int drive) { return (drive_types[fdd[drive].type].flags & 0x70) == 0x10; } +int +fdd_is_hd(int drive) +{ + return drive_types[fdd[drive].type].flags & FLAG_HOLE1; +} int fdd_is_ed(int drive) @@ -413,299 +395,279 @@ fdd_is_ed(int drive) return drive_types[fdd[drive].type].flags & FLAG_HOLE2; } - int fdd_is_double_sided(int drive) { return drive_types[fdd[drive].type].flags & FLAG_DS; } - void fdd_set_head(int drive, int head) { if (head && !fdd_is_double_sided(drive)) - fdd[drive].head = 0; + fdd[drive].head = 0; else - fdd[drive].head = head; + fdd[drive].head = head; } - int fdd_get_head(int drive) { if (!fdd_is_double_sided(drive)) - return 0; + return 0; return fdd[drive].head; } - void fdd_set_turbo(int drive, int turbo) { fdd[drive].turbo = turbo; } - int fdd_get_turbo(int drive) { return fdd[drive].turbo; } - -void fdd_set_check_bpb(int drive, int check_bpb) +void +fdd_set_check_bpb(int drive, int check_bpb) { fdd[drive].check_bpb = check_bpb; } - int fdd_get_check_bpb(int drive) { return fdd[drive].check_bpb; } - int fdd_get_densel(int drive) { return fdd[drive].densel; } - void fdd_load(int drive, char *fn) { - int c = 0, size; - char *p; - FILE *f; + int c = 0; + int size; + const char *p; + FILE * fp; fdd_log("FDD: loading drive %d with '%s'\n", drive, fn); if (!fn) - return; - p = plat_get_extension(fn); + return; + p = path_get_extension(fn); if (!p) - return; - f = plat_fopen(fn, "rb"); - if (f) { - if (fseek(f, -1, SEEK_END) == -1) - fatal("fdd_load(): Error seeking to the end of the file\n"); - size = ftell(f) + 1; - fclose(f); - while (loaders[c].ext) { - if (!strcasecmp(p, (char *) loaders[c].ext) && (size == loaders[c].size || loaders[c].size == -1)) { - driveloaders[drive] = c; - if (floppyfns[drive] != fn) strcpy(floppyfns[drive], fn); - d86f_setup(drive); - loaders[c].load(drive, floppyfns[drive]); - drive_empty[drive] = 0; - fdd_forced_seek(drive, 0); - fdd_changed[drive] = 1; - return; - } - c++; - } + return; + fp = plat_fopen(fn, "rb"); + if (fp) { + if (fseek(fp, -1, SEEK_END) == -1) + fatal("fdd_load(): Error seeking to the end of the file\n"); + size = ftell(fp) + 1; + fclose(fp); + while (loaders[c].ext) { + if (!strcasecmp(p, (char *) loaders[c].ext) && (size == loaders[c].size || loaders[c].size == -1)) { + driveloaders[drive] = c; + if (floppyfns[drive] != fn) + strcpy(floppyfns[drive], fn); + d86f_setup(drive); + loaders[c].load(drive, floppyfns[drive]); + drive_empty[drive] = 0; + fdd_forced_seek(drive, 0); + fdd_changed[drive] = 1; + return; + } + c++; + } } - fdd_log("FDD: could not load '%s' %s\n",fn,p); + fdd_log("FDD: could not load '%s' %s\n", fn, p); drive_empty[drive] = 1; fdd_set_head(drive, 0); memset(floppyfns[drive], 0, sizeof(floppyfns[drive])); ui_sb_update_icon_state(SB_FLOPPY | drive, 1); } - void fdd_close(int drive) { fdd_log("FDD: closing drive %d\n", drive); - d86f_stop(drive); /* Call this first of all to make sure the 86F poll is back to idle state. */ + d86f_stop(drive); /* Call this first of all to make sure the 86F poll is back to idle state. */ if (loaders[driveloaders[drive]].close) - loaders[driveloaders[drive]].close(drive); + loaders[driveloaders[drive]].close(drive); drive_empty[drive] = 1; fdd_set_head(drive, 0); - floppyfns[drive][0] = 0; - drives[drive].hole = NULL; - drives[drive].poll = NULL; - drives[drive].seek = NULL; - drives[drive].readsector = NULL; - drives[drive].writesector = NULL; + floppyfns[drive][0] = 0; + drives[drive].hole = NULL; + drives[drive].poll = NULL; + drives[drive].seek = NULL; + drives[drive].readsector = NULL; + drives[drive].writesector = NULL; drives[drive].comparesector = NULL; - drives[drive].readaddress = NULL; - drives[drive].format = NULL; - drives[drive].byteperiod = NULL; - drives[drive].stop = NULL; + drives[drive].readaddress = NULL; + drives[drive].format = NULL; + drives[drive].byteperiod = NULL; + drives[drive].stop = NULL; d86f_destroy(drive); ui_sb_update_icon_state(SB_FLOPPY | drive, 1); } - int fdd_hole(int drive) { if (drives[drive].hole) - return drives[drive].hole(drive); + return drives[drive].hole(drive); else - return 0; + return 0; } - static __inline uint64_t fdd_byteperiod(int drive) { if (!fdd_get_turbo(drive) && drives[drive].byteperiod) - return drives[drive].byteperiod(drive); + return drives[drive].byteperiod(drive); else - return 32ULL * TIMER_USEC; + return 32ULL * TIMER_USEC; } - void fdd_set_motor_enable(int drive, int motor_enable) { /* I think here is where spin-up and spin-down should be implemented. */ if (motor_enable && !motoron[drive]) - timer_set_delay_u64(&fdd_poll_time[drive], fdd_byteperiod(drive)); + timer_set_delay_u64(&fdd_poll_time[drive], fdd_byteperiod(drive)); else if (!motor_enable) - timer_disable(&fdd_poll_time[drive]); + timer_disable(&fdd_poll_time[drive]); motoron[drive] = motor_enable; } - static void fdd_poll(void *priv) { - int drive; - DRIVE *drv = (DRIVE *) priv; + int drive; + const DRIVE *drv = (DRIVE *) priv; drive = drv->id; if (drive >= FDD_NUM) - fatal("Attempting to poll floppy drive %i that is not supposed to be there\n", drive); + fatal("Attempting to poll floppy drive %i that is not supposed to be there\n", drive); timer_advance_u64(&fdd_poll_time[drive], fdd_byteperiod(drive)); if (drv->poll) - drv->poll(drive); + drv->poll(drive); if (fdd_notfound) { - fdd_notfound--; - if (!fdd_notfound) - fdc_noidam(fdd_fdc); + fdd_notfound--; + if (!fdd_notfound) + fdc_noidam(fdd_fdc); } } - int fdd_get_bitcell_period(int rate) { int bit_rate = 250; switch (rate) { - case 0: /*High density*/ - bit_rate = 500; - break; - case 1: /*Double density (360 rpm)*/ - bit_rate = 300; - break; - case 2: /*Double density*/ - bit_rate = 250; - break; - case 3: /*Extended density*/ - bit_rate = 1000; - break; + case 0: /*High density*/ + bit_rate = 500; + break; + case 1: /*Double density (360 rpm)*/ + bit_rate = 300; + break; + case 2: /*Double density*/ + bit_rate = 250; + break; + case 3: /*Extended density*/ + bit_rate = 1000; + break; + + default: + break; } - return 1000000 / bit_rate*2; /*Bitcell period in ns*/ + return 1000000 / bit_rate * 2; /*Bitcell period in ns*/ } - void fdd_reset(void) { - int i; - - for (i = 0; i < 4; i++) { - drives[i].id = i; - timer_add(&(fdd_poll_time[i]), fdd_poll, &drives[i], 0); + for (uint8_t i = 0; i < FDD_NUM; i++) { + drives[i].id = i; + timer_add(&(fdd_poll_time[i]), fdd_poll, &drives[i], 0); } } - void fdd_readsector(int drive, int sector, int track, int side, int density, int sector_size) { if (drives[drive].readsector) - drives[drive].readsector(drive, sector, track, side, density, sector_size); + drives[drive].readsector(drive, sector, track, side, density, sector_size); else - fdd_notfound = 1000; + fdd_notfound = 1000; } - void fdd_writesector(int drive, int sector, int track, int side, int density, int sector_size) { if (drives[drive].writesector) - drives[drive].writesector(drive, sector, track, side, density, sector_size); + drives[drive].writesector(drive, sector, track, side, density, sector_size); else - fdd_notfound = 1000; + fdd_notfound = 1000; } - void fdd_comparesector(int drive, int sector, int track, int side, int density, int sector_size) { if (drives[drive].comparesector) - drives[drive].comparesector(drive, sector, track, side, density, sector_size); + drives[drive].comparesector(drive, sector, track, side, density, sector_size); else - fdd_notfound = 1000; + fdd_notfound = 1000; } - void fdd_readaddress(int drive, int side, int density) { if (drives[drive].readaddress) - drives[drive].readaddress(drive, side, density); + drives[drive].readaddress(drive, side, density); } - void fdd_format(int drive, int side, int density, uint8_t fill) { if (drives[drive].format) - drives[drive].format(drive, side, density, fill); + drives[drive].format(drive, side, density, fill); else - fdd_notfound = 1000; + fdd_notfound = 1000; } - void fdd_stop(int drive) { if (drives[drive].stop) - drives[drive].stop(drive); + drives[drive].stop(drive); } - void fdd_set_fdc(void *fdc) { fdd_fdc = (fdc_t *) fdc; } - void fdd_init(void) { int i; - for (i = 0; i < 4; i++) { - drives[i].poll = 0; - drives[i].seek = 0; - drives[i].readsector = 0; + for (i = 0; i < FDD_NUM; i++) { + drives[i].poll = 0; + drives[i].seek = 0; + drives[i].readsector = 0; } img_init(); @@ -714,13 +676,11 @@ fdd_init(void) imd_init(); json_init(); - fdd_load(0, floppyfns[0]); - fdd_load(1, floppyfns[1]); - fdd_load(2, floppyfns[2]); - fdd_load(3, floppyfns[3]); + for (i = 0; i < FDD_NUM; i++) { + fdd_load(i, floppyfns[i]); + } } - void fdd_do_writeback(int drive) { diff --git a/src/floppy/fdd_86f.c b/src/floppy/fdd_86f.c index ac4de1ee4..08e57c09b 100644 --- a/src/floppy/fdd_86f.c +++ b/src/floppy/fdd_86f.c @@ -1,22 +1,22 @@ /* - * 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. + * 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. + * This file is part of the 86Box distribution. * - * Implementation of the 86F floppy image format (stores the - * data in the form of FM/MFM-encoded transitions) which also - * forms the core of the emulator's floppy disk emulation. + * Implementation of the 86F floppy image format (stores the + * data in the form of FM/MFM-encoded transitions) which also + * forms the core of the emulator's floppy disk emulation. * * * - * Authors: Miran Grca, - * Fred N. van Kempen, + * Authors: Miran Grca, + * Fred N. van Kempen, * - * Copyright 2016-2019 Miran Grca. - * Copyright 2018,2019 Fred N. van Kempen. + * Copyright 2016-2019 Miran Grca. + * Copyright 2018-2019 Fred N. van Kempen. */ #include #include @@ -37,10 +37,9 @@ #include <86box/fdc.h> #include <86box/fdd_86f.h> #ifdef D86F_COMPRESS -#include +# include #endif - /* * Let's give this some more logic: * @@ -54,54 +53,54 @@ enum { STATE_SECTOR_NOT_FOUND, /* 1 00 00 ??? */ - STATE_0A_FIND_ID = 0x80, /* READ SECTOR ID */ + STATE_0A_FIND_ID = 0x80, /* READ SECTOR ID */ STATE_0A_READ_ID, /* 1 01 00 ??? */ - STATE_06_FIND_ID = 0xA0, /* READ DATA */ + STATE_06_FIND_ID = 0xA0, /* READ DATA */ STATE_06_READ_ID, STATE_06_FIND_DATA, STATE_06_READ_DATA, /* 1 01 01 ??? */ - STATE_05_FIND_ID = 0xA8, /* WRITE DATA */ + STATE_05_FIND_ID = 0xA8, /* WRITE DATA */ STATE_05_READ_ID, STATE_05_FIND_DATA, STATE_05_WRITE_DATA, /* 1 01 10 ??? */ - STATE_11_FIND_ID = 0xB0, /* SCAN EQUAL,SCAN LOW/EQUAL,SCAN HIGH/EQUAL */ + STATE_11_FIND_ID = 0xB0, /* SCAN EQUAL,SCAN LOW/EQUAL,SCAN HIGH/EQUAL */ STATE_11_READ_ID, STATE_11_FIND_DATA, STATE_11_SCAN_DATA, /* 1 01 11 ??? */ - STATE_16_FIND_ID = 0xB8, /* VERIFY */ + STATE_16_FIND_ID = 0xB8, /* VERIFY */ STATE_16_READ_ID, STATE_16_FIND_DATA, STATE_16_VERIFY_DATA, /* 1 10 00 ??? */ - STATE_0C_FIND_ID = 0xC0, /* READ DELETED DATA */ + STATE_0C_FIND_ID = 0xC0, /* READ DELETED DATA */ STATE_0C_READ_ID, STATE_0C_FIND_DATA, STATE_0C_READ_DATA, /* 1 10 01 ??? */ - STATE_09_FIND_ID = 0xC8, /* WRITE DELETED DATA */ + STATE_09_FIND_ID = 0xC8, /* WRITE DELETED DATA */ STATE_09_READ_ID, STATE_09_FIND_DATA, STATE_09_WRITE_DATA, /* 1 11 00 ??? */ - STATE_02_SPIN_TO_INDEX = 0xE0, /* READ TRACK */ + STATE_02_SPIN_TO_INDEX = 0xE0, /* READ TRACK */ STATE_02_FIND_ID, STATE_02_READ_ID, STATE_02_FIND_DATA, STATE_02_READ_DATA, /* 1 11 01 ??? */ - STATE_0D_SPIN_TO_INDEX = 0xE8, /* FORMAT TRACK */ + STATE_0D_SPIN_TO_INDEX = 0xE8, /* FORMAT TRACK */ STATE_0D_FORMAT_TRACK, }; @@ -126,90 +125,106 @@ enum { FMT_POSTTRK_GAP4 }; - -typedef struct { - uint8_t buffer[10]; - uint32_t pos; - uint32_t len; +typedef struct sliding_buffer_t { + uint8_t buffer[10]; + uint32_t pos; + uint32_t len; } sliding_buffer_t; -typedef struct { - uint32_t bits_obtained; - uint16_t bytes_obtained; - uint16_t sync_marks; - uint32_t sync_pos; +typedef struct find_t { + uint32_t bits_obtained; + uint16_t bytes_obtained; + uint16_t sync_marks; + uint32_t sync_pos; } find_t; -typedef struct { - unsigned nibble0 :4; - unsigned nibble1 :4; +typedef struct split_byte_t { + unsigned nibble0 : 4; + unsigned nibble1 : 4; } split_byte_t; -typedef union { - uint8_t byte; +typedef union decoded_t { + uint8_t byte; split_byte_t nibbles; } decoded_t; -typedef struct { - uint8_t c, h, r, n; - uint8_t flags, pad, pad0, pad1; - void *prev; +typedef struct sector_t { + uint8_t c; + uint8_t h; + uint8_t r; + uint8_t n; + uint8_t flags; + uint8_t pad; + uint8_t pad0; + uint8_t pad1; + void *prev; } sector_t; /* Disk flags: - * Bit 0 Has surface data (1 = yes, 0 = no) - * Bits 2, 1 Hole (3 = ED + 2000 kbps, 2 = ED, 1 = HD, 0 = DD) - * Bit 3 Sides (1 = 2 sides, 0 = 1 side) - * Bit 4 Write protect (1 = yes, 0 = no) - * Bits 6, 5 RPM slowdown (3 = 2%, 2 = 1.5%, 1 = 1%, 0 = 0%) - * Bit 7 Bitcell mode (1 = Extra bitcells count specified after - * disk flags, 0 = No extra bitcells) - * The maximum number of extra bitcells is 1024 (which - * after decoding translates to 64 bytes) - * Bit 8 Disk type (1 = Zoned, 0 = Fixed RPM) - * Bits 10, 9 Zone type (3 = Commodore 64 zoned, 2 = Apple zoned, - * 1 = Pre-Apple zoned #2, 0 = Pre-Apple zoned #1) - * Bit 11 Data and surface bits are stored in reverse byte endianness - * Bit 12 If bits 6, 5 are not 0, they specify % of speedup instead - * of slowdown; - * If bits 6, 5 are 0, and bit 7 is 1, the extra bitcell count - * specifies the entire bitcell count + * Bit 0 Has surface data (1 = yes, 0 = no) + * Bits 2, 1 Hole (3 = ED + 2000 kbps, 2 = ED, 1 = HD, 0 = DD) + * Bit 3 Sides (1 = 2 sides, 0 = 1 side) + * Bit 4 Write protect (1 = yes, 0 = no) + * Bits 6, 5 RPM slowdown (3 = 2%, 2 = 1.5%, 1 = 1%, 0 = 0%) + * Bit 7 Bitcell mode (1 = Extra bitcells count specified after + * disk flags, 0 = No extra bitcells) + * The maximum number of extra bitcells is 1024 (which + * after decoding translates to 64 bytes) + * Bit 8 Disk type (1 = Zoned, 0 = Fixed RPM) + * Bits 10, 9 Zone type (3 = Commodore 64 zoned, 2 = Apple zoned, + * 1 = Pre-Apple zoned #2, 0 = Pre-Apple zoned #1) + * Bit 11 Data and surface bits are stored in reverse byte endianness + * Bit 12 If bits 6, 5 are not 0, they specify % of speedup instead + * of slowdown; + * If bits 6, 5 are 0, and bit 7 is 1, the extra bitcell count + * specifies the entire bitcell count */ -typedef struct { - FILE *f; - uint8_t state, fill, sector_count, format_state, - error_condition, id_found; - uint16_t version, disk_flags, satisfying_bytes, turbo_pos; - uint16_t cur_track; - uint16_t track_encoded_data[2][53048]; - uint16_t *track_surface_data[2]; - uint16_t thin_track_encoded_data[2][2][53048]; - uint16_t *thin_track_surface_data[2][2]; - uint16_t side_flags[2]; - uint16_t preceding_bit[2]; - uint16_t current_byte[2]; - uint16_t current_bit[2]; - uint16_t last_word[2]; +typedef struct d86f_t { + FILE *fp; + uint8_t state; + uint8_t fill; + uint8_t sector_count; + uint8_t format_state; + uint8_t error_condition; + uint8_t id_found; + uint16_t version; + uint16_t disk_flags; + uint16_t satisfying_bytes; + uint16_t turbo_pos; + uint16_t cur_track; + uint16_t track_encoded_data[2][53048]; + uint16_t *track_surface_data[2]; + uint16_t thin_track_encoded_data[2][2][53048]; + uint16_t *thin_track_surface_data[2][2]; + uint16_t side_flags[2]; + uint16_t preceding_bit[2]; + uint16_t current_byte[2]; + uint16_t current_bit[2]; + uint16_t last_word[2]; #ifdef D86F_COMPRESS - int is_compressed; + int is_compressed; #endif - int32_t extra_bit_cells[2]; - uint32_t file_size, index_count, track_pos, datac, - id_pos, dma_over; - uint32_t index_hole_pos[2]; - uint32_t track_offset[512]; - sector_id_t last_sector; - sector_id_t req_sector; - find_t id_find; - find_t data_find; - crc_t calc_crc; - crc_t track_crc; - char original_file_name[2048]; - uint8_t *filebuf, *outbuf; - sector_t *last_side_sector[2]; + int32_t extra_bit_cells[2]; + uint32_t file_size; + uint32_t index_count; + uint32_t track_pos; + uint32_t datac; + uint32_t id_pos; + uint32_t dma_over; + uint32_t index_hole_pos[2]; + uint32_t track_offset[512]; + sector_id_t last_sector; + sector_id_t req_sector; + find_t id_find; + find_t data_find; + crc_t calc_crc; + crc_t track_crc; + char original_file_name[2048]; + uint8_t *filebuf; + uint8_t *outbuf; + sector_t *last_side_sector[2]; } d86f_t; - static const uint8_t encoded_fm[64] = { 0xaa, 0xab, 0xae, 0xaf, 0xba, 0xbb, 0xbe, 0xbf, 0xea, 0xeb, 0xee, 0xef, 0xfa, 0xfb, 0xfe, 0xff, @@ -231,23 +246,20 @@ static const uint8_t encoded_mfm[64] = { 0x4a, 0x49, 0x44, 0x45, 0x52, 0x51, 0x54, 0x55 }; -static d86f_t *d86f[FDD_NUM]; -static uint16_t CRCTable[256]; -static fdc_t *d86f_fdc; -uint64_t poly = 0x42F0E1EBA9EA3693ll; /* ECMA normal */ - +static d86f_t *d86f[FDD_NUM]; +static uint16_t CRCTable[256]; +static fdc_t *d86f_fdc; +uint64_t poly = 0x42F0E1EBA9EA3693LL; /* ECMA normal */ uint16_t d86f_side_flags(int drive); -int d86f_is_mfm(int drive); -void d86f_writeback(int drive); -uint8_t d86f_poll_read_data(int drive, int side, uint16_t pos); -void d86f_poll_write_data(int drive, int side, uint16_t pos, uint8_t data); -int d86f_format_conditions(int drive); - +int d86f_is_mfm(int drive); +void d86f_writeback(int drive); +uint8_t d86f_poll_read_data(int drive, int side, uint16_t pos); +void d86f_poll_write_data(int drive, int side, uint16_t pos, uint8_t data); +int d86f_format_conditions(int drive); #ifdef ENABLE_D86F_LOG -int d86f_do_log = ENABLE_D86F_LOG; - +int d86f_do_log = ENABLE_D86F_LOG; static void d86f_log(const char *fmt, ...) @@ -255,180 +267,164 @@ d86f_log(const char *fmt, ...) va_list ap; if (d86f_do_log) { - va_start(ap, fmt); - pclog_ex(fmt, ap); - va_end(ap); + va_start(ap, fmt); + pclog_ex(fmt, ap); + va_end(ap); } } #else -#define d86f_log(fmt, ...) +# define d86f_log(fmt, ...) #endif - static void setup_crc(uint16_t poly) { - int c = 256, bc; + int c = 256; + int bc; uint16_t temp; - while(c--) { - temp = c << 8; - bc = 8; + while (c--) { + temp = c << 8; + bc = 8; - while (bc--) { - if (temp & 0x8000) - temp = (temp << 1) ^ poly; - else - temp <<= 1; + while (bc--) { + if (temp & 0x8000) + temp = (temp << 1) ^ poly; + else + temp <<= 1; - CRCTable[c] = temp; - } + CRCTable[c] = temp; + } } } - void d86f_destroy_linked_lists(int drive, int side) { - d86f_t *dev = d86f[drive]; - sector_t *s, *t; + d86f_t *dev = d86f[drive]; + sector_t *s; + sector_t *t; - if (dev == NULL) return; + if (dev == NULL) + return; if (dev->last_side_sector[side]) { - s = dev->last_side_sector[side]; - while (s) { - t = s->prev; - free(s); - s = NULL; - if (! t) - break; - s = t; - } - dev->last_side_sector[side] = NULL; + s = dev->last_side_sector[side]; + while (s) { + t = s->prev; + free(s); + s = NULL; + if (!t) + break; + s = t; + } + dev->last_side_sector[side] = NULL; } } - static int d86f_has_surface_desc(int drive) { return (d86f_handler[drive].disk_flags(drive) & 1); } - int d86f_get_sides(int drive) { return ((d86f_handler[drive].disk_flags(drive) >> 3) & 1) + 1; } - int d86f_get_rpm_mode(int drive) { return (d86f_handler[drive].disk_flags(drive) & 0x60) >> 5; } - int d86f_get_speed_shift_dir(int drive) { return (d86f_handler[drive].disk_flags(drive) & 0x1000) >> 12; } - int d86f_reverse_bytes(int drive) { return (d86f_handler[drive].disk_flags(drive) & 0x800) >> 11; } - uint16_t d86f_disk_flags(int drive) { - d86f_t *dev = d86f[drive]; + const d86f_t *dev = d86f[drive]; return dev->disk_flags; } - uint32_t d86f_index_hole_pos(int drive, int side) { - d86f_t *dev = d86f[drive]; + const d86f_t *dev = d86f[drive]; return dev->index_hole_pos[side]; } - uint32_t -null_index_hole_pos(int drive, int side) +null_index_hole_pos(UNUSED(int drive), UNUSED(int side)) { return 0; } - uint16_t -null_disk_flags(int drive) +null_disk_flags(UNUSED(int drive)) { return 0x09; } - uint16_t -null_side_flags(int drive) +null_side_flags(UNUSED(int drive)) { return 0x0A; } - void -null_writeback(int drive) +null_writeback(UNUSED(int drive)) { return; } - void -null_set_sector(int drive, int side, uint8_t c, uint8_t h, uint8_t r, uint8_t n) +null_set_sector(UNUSED(int drive), UNUSED(int side), UNUSED(uint8_t c), UNUSED(uint8_t h), UNUSED(uint8_t r), UNUSED(uint8_t n)) { return; } - void -null_write_data(int drive, int side, uint16_t pos, uint8_t data) +null_write_data(UNUSED(int drive), UNUSED(int side), UNUSED(uint16_t pos), UNUSED(uint8_t data)) { return; } - int -null_format_conditions(int drive) +null_format_conditions(UNUSED(int drive)) { return 0; } - int32_t d86f_extra_bit_cells(int drive, int side) { - d86f_t *dev = d86f[drive]; + const d86f_t *dev = d86f[drive]; return dev->extra_bit_cells[side]; } - int32_t -null_extra_bit_cells(int drive, int side) +null_extra_bit_cells(UNUSED(int drive), UNUSED(int side)) { return 0; } - -uint16_t* +uint16_t * common_encoded_data(int drive, int side) { d86f_t *dev = d86f[drive]; @@ -436,30 +432,29 @@ common_encoded_data(int drive, int side) return dev->track_encoded_data[side]; } - void -common_read_revolution(int drive) +common_read_revolution(UNUSED(int drive)) { return; } - uint16_t d86f_side_flags(int drive) { - d86f_t *dev = d86f[drive]; - int side; + const d86f_t *dev = d86f[drive]; + int side; side = fdd_get_head(drive); return dev->side_flags[side]; } - uint16_t d86f_track_flags(int drive) { - uint16_t dr, rr, tf; + uint16_t dr; + uint16_t rr; + uint16_t tf; tf = d86f_handler[drive].side_flags(drive); rr = tf & 0x67; @@ -467,102 +462,104 @@ d86f_track_flags(int drive) tf &= ~0x67; switch (rr) { - case 0x02: - case 0x21: - /* 1 MB unformatted medium, treat these two as equivalent. */ - switch (dr) { - case 0x06: - /* 5.25" Single-RPM HD drive, treat as 300 kbps, 360 rpm. */ - tf |= 0x21; - break; + case 0x02: + case 0x21: + /* 1 MB unformatted medium, treat these two as equivalent. */ + switch (dr) { + case 0x06: + /* 5.25" Single-RPM HD drive, treat as 300 kbps, 360 rpm. */ + tf |= 0x21; + break; - default: - /* Any other drive, treat as 250 kbps, 300 rpm. */ - tf |= 0x02; - break; - } - break; + default: + /* Any other drive, treat as 250 kbps, 300 rpm. */ + tf |= 0x02; + break; + } + break; - default: - tf |= rr; - break; + default: + tf |= rr; + break; } return tf; } - uint32_t common_get_raw_size(int drive, int side) { - double rate = 0.0; - double rpm, rpm_diff; - double size = 100000.0; - int mfm; - int rm, ssd; + double rate = 0.0; + double rpm; + double rpm_diff; + double size = 100000.0; + int mfm; + int rm; + int ssd; uint32_t extra_bc = 0; - mfm = d86f_is_mfm(drive); - rpm = ((d86f_track_flags(drive) & 0xE0) == 0x20) ? 360.0 : 300.0; + mfm = d86f_is_mfm(drive); + rpm = ((d86f_track_flags(drive) & 0xE0) == 0x20) ? 360.0 : 300.0; rpm_diff = 1.0; - rm = d86f_get_rpm_mode(drive); - ssd = d86f_get_speed_shift_dir(drive); + rm = d86f_get_rpm_mode(drive); + ssd = d86f_get_speed_shift_dir(drive); /* 0% speed shift and shift direction 1: special case where extra bit cells are the entire track size. */ if (!rm && ssd) - extra_bc = d86f_handler[drive].extra_bit_cells(drive, side); + extra_bc = d86f_handler[drive].extra_bit_cells(drive, side); if (extra_bc) - return extra_bc; + return extra_bc; switch (rm) { - case 1: - rpm_diff = 1.01; - break; + case 1: + rpm_diff = 1.01; + break; - case 2: - rpm_diff = 1.015; - break; + case 2: + rpm_diff = 1.015; + break; - case 3: - rpm_diff = 1.02; - break; + case 3: + rpm_diff = 1.02; + break; - default: - rpm_diff = 1.0; - break; + default: + rpm_diff = 1.0; + break; } if (ssd) - rpm_diff = 1.0 / rpm_diff; + rpm_diff = 1.0 / rpm_diff; switch (d86f_track_flags(drive) & 7) { - case 0: - rate = 500.0; - break; + case 0: + rate = 500.0; + break; - case 1: - rate = 300.0; - break; + case 1: + rate = 300.0; + break; - case 2: - rate = 250.0; - break; + case 2: + rate = 250.0; + break; - case 3: - rate = 1000.0; - break; + case 3: + rate = 1000.0; + break; - case 5: - rate = 2000.0; - break; + case 5: + rate = 2000.0; + break; - default: - rate = 250.0; - break; + default: + rate = 250.0; + break; } - if (! mfm) rate /= 2.0; + if (!mfm) + rate /= 2.0; size = (size / 250.0) * rate; size = (size * 300.0) / rpm; @@ -575,7 +572,6 @@ common_get_raw_size(int drive, int side) return ((((uint32_t) size) >> 4) << 4) + d86f_handler[drive].extra_bit_cells(drive, side); } - void d86f_set_version(int drive, uint16_t version) { @@ -584,352 +580,359 @@ d86f_set_version(int drive, uint16_t version) dev->version = version; } - void d86f_unregister(int drive) { d86f_t *dev = d86f[drive]; - if (dev == NULL) return; + if (dev == NULL) + return; - d86f_handler[drive].disk_flags = null_disk_flags; - d86f_handler[drive].side_flags = null_side_flags; - d86f_handler[drive].writeback = null_writeback; - d86f_handler[drive].set_sector = null_set_sector; - d86f_handler[drive].write_data = null_write_data; + d86f_handler[drive].disk_flags = null_disk_flags; + d86f_handler[drive].side_flags = null_side_flags; + d86f_handler[drive].writeback = null_writeback; + d86f_handler[drive].set_sector = null_set_sector; + d86f_handler[drive].write_data = null_write_data; d86f_handler[drive].format_conditions = null_format_conditions; - d86f_handler[drive].extra_bit_cells = null_extra_bit_cells; - d86f_handler[drive].encoded_data = common_encoded_data; - d86f_handler[drive].read_revolution = common_read_revolution; - d86f_handler[drive].index_hole_pos = null_index_hole_pos; - d86f_handler[drive].get_raw_size = common_get_raw_size; - d86f_handler[drive].check_crc = 0; + d86f_handler[drive].extra_bit_cells = null_extra_bit_cells; + d86f_handler[drive].encoded_data = common_encoded_data; + d86f_handler[drive].read_revolution = common_read_revolution; + d86f_handler[drive].index_hole_pos = null_index_hole_pos; + d86f_handler[drive].get_raw_size = common_get_raw_size; + d86f_handler[drive].check_crc = 0; - dev->version = 0x0063; /* Proxied formats report as version 0.99. */ + dev->version = 0x0063; /* Proxied formats report as version 0.99. */ } - void d86f_register_86f(int drive) { - d86f_handler[drive].disk_flags = d86f_disk_flags; - d86f_handler[drive].side_flags = d86f_side_flags; - d86f_handler[drive].writeback = d86f_writeback; - d86f_handler[drive].set_sector = null_set_sector; - d86f_handler[drive].write_data = null_write_data; + d86f_handler[drive].disk_flags = d86f_disk_flags; + d86f_handler[drive].side_flags = d86f_side_flags; + d86f_handler[drive].writeback = d86f_writeback; + d86f_handler[drive].set_sector = null_set_sector; + d86f_handler[drive].write_data = null_write_data; d86f_handler[drive].format_conditions = d86f_format_conditions; - d86f_handler[drive].extra_bit_cells = d86f_extra_bit_cells; - d86f_handler[drive].encoded_data = common_encoded_data; - d86f_handler[drive].read_revolution = common_read_revolution; - d86f_handler[drive].index_hole_pos = d86f_index_hole_pos; - d86f_handler[drive].get_raw_size = common_get_raw_size; - d86f_handler[drive].check_crc = 1; + d86f_handler[drive].extra_bit_cells = d86f_extra_bit_cells; + d86f_handler[drive].encoded_data = common_encoded_data; + d86f_handler[drive].read_revolution = common_read_revolution; + d86f_handler[drive].index_hole_pos = d86f_index_hole_pos; + d86f_handler[drive].get_raw_size = common_get_raw_size; + d86f_handler[drive].check_crc = 1; } - int d86f_get_array_size(int drive, int side, int words) { int array_size; - int hole, rm; + int hole; + int rm; int ssd; - rm = d86f_get_rpm_mode(drive); - ssd = d86f_get_speed_shift_dir(drive); + rm = d86f_get_rpm_mode(drive); + ssd = d86f_get_speed_shift_dir(drive); hole = (d86f_handler[drive].disk_flags(drive) & 6) >> 1; - if (!rm && ssd) /* Special case - extra bit cells size specifies entire array size. */ - array_size = 0; - else switch (hole) { - case 0: - case 1: - default: - array_size = 12500; - switch (rm) { - case 1: - array_size = ssd ? 12376 : 12625; - break; + if (!rm && ssd) /* Special case - extra bit cells size specifies entire array size. */ + array_size = 0; + else + switch (hole) { + default: + case 0: + case 1: + array_size = 12500; + switch (rm) { + case 1: + array_size = ssd ? 12376 : 12625; + break; - case 2: - array_size = ssd ? 12315 : 12687; - break; + case 2: + array_size = ssd ? 12315 : 12687; + break; - case 3: - array_size = ssd ? 12254 : 12750; - break; + case 3: + array_size = ssd ? 12254 : 12750; + break; - default: - break; - } - break; + default: + break; + } + break; - case 2: - array_size = 25000; - switch (rm) { - case 1: - array_size = ssd ? 24752 : 25250; - break; + case 2: + array_size = 25000; + switch (rm) { + case 1: + array_size = ssd ? 24752 : 25250; + break; - case 2: - array_size = ssd ? 24630 : 25375; - break; + case 2: + array_size = ssd ? 24630 : 25375; + break; - case 3: - array_size = ssd ? 24509 : 25500; - break; + case 3: + array_size = ssd ? 24509 : 25500; + break; - default: - break; - } - break; + default: + break; + } + break; - case 3: - array_size = 50000; - switch (rm) { - case 1: - array_size = ssd ? 49504 : 50500; - break; + case 3: + array_size = 50000; + switch (rm) { + case 1: + array_size = ssd ? 49504 : 50500; + break; - case 2: - array_size = ssd ? 49261 : 50750; - break; + case 2: + array_size = ssd ? 49261 : 50750; + break; - case 3: - array_size = ssd ? 49019 : 51000; - break; + case 3: + array_size = ssd ? 49019 : 51000; + break; - default: - break; - } - break; - } + default: + break; + } + break; + } array_size <<= 4; array_size += d86f_handler[drive].extra_bit_cells(drive, side); if (array_size & 15) - array_size = (array_size >> 4) + 1; + array_size = (array_size >> 4) + 1; else - array_size = (array_size >> 4); + array_size = (array_size >> 4); if (!words) - array_size <<= 1; + array_size <<= 1; return array_size; } - int d86f_valid_bit_rate(int drive) { - int hole, rate; + int hole; + int rate; rate = fdc_get_bit_rate(d86f_fdc); hole = (d86f_handler[drive].disk_flags(drive) & 6) >> 1; switch (hole) { - case 0: /* DD */ - if (!rate && (fdd_get_flags(drive) & 0x10)) return 1; - if ((rate < 1) || (rate > 2)) return 0; - return 1; + case 0: /* DD */ + if (!rate && (fdd_get_flags(drive) & 0x10)) + return 1; + if ((rate < 1) || (rate > 2)) + return 0; + return 1; - case 1: /* HD */ - if (rate != 0) return 0; - return 1; + case 1: /* HD */ + if (rate != 0) + return 0; + return 1; - case 2: /* ED */ - if (rate != 3) return 0; - return 1; + case 2: /* ED */ + if (rate != 3) + return 0; + return 1; - case 3: /* ED with 2000 kbps support */ - if (rate < 3) return 0; - return 1; + case 3: /* ED with 2000 kbps support */ + if (rate < 3) + return 0; + return 1; - default: - break; + default: + break; } return 0; } - int d86f_hole(int drive) { if (((d86f_handler[drive].disk_flags(drive) >> 1) & 3) == 3) - return 2; + return 2; return (d86f_handler[drive].disk_flags(drive) >> 1) & 3; } - uint8_t d86f_get_encoding(int drive) { return (d86f_track_flags(drive) & 0x18) >> 3; } - uint64_t d86f_byteperiod(int drive) { double dusec = (double) TIMER_USEC; - double p = 2.0; + double p = 2.0; switch (d86f_track_flags(drive) & 0x0f) { - case 0x02: /* 125 kbps, FM */ - p = 4.0; - break; - case 0x01: /* 150 kbps, FM */ - p = 20.0 / 6.0; - break; - case 0x0a: /* 250 kbps, MFM */ - case 0x00: /* 250 kbps, FM */ - default: - p = 2.0; - break; - case 0x09: /* 300 kbps, MFM */ - p = 10.0 / 6.0; - break; - case 0x08: /* 500 kbps, MFM */ - p = 1.0; - break; - case 0x0b: /* 1000 kbps, MFM */ - p = 0.5; - break; - case 0x0d: /* 2000 kbps, MFM */ - p = 0.25; - break; + case 0x02: /* 125 kbps, FM */ + p = 4.0; + break; + case 0x01: /* 150 kbps, FM */ + p = 20.0 / 6.0; + break; + case 0x0a: /* 250 kbps, MFM */ + case 0x00: /* 250 kbps, FM */ + default: + p = 2.0; + break; + case 0x09: /* 300 kbps, MFM */ + p = 10.0 / 6.0; + break; + case 0x08: /* 500 kbps, MFM */ + p = 1.0; + break; + case 0x0b: /* 1000 kbps, MFM */ + p = 0.5; + break; + case 0x0d: /* 2000 kbps, MFM */ + p = 0.25; + break; } return (uint64_t) (p * dusec); } - int d86f_is_mfm(int drive) { return ((d86f_track_flags(drive) & 0x18) == 0x08) ? 1 : 0; } - uint32_t d86f_get_data_len(int drive) { - d86f_t *dev = d86f[drive]; - uint32_t i, ret = 128; + const d86f_t *dev = d86f[drive]; + uint32_t i; + uint32_t ret = 128; if (dev->req_sector.id.n) - ret = (uint32_t)128 << dev->req_sector.id.n; + ret = (uint32_t) 128 << dev->req_sector.id.n; else if ((i = fdc_get_dtl(d86f_fdc)) < 128) - ret = i; + ret = i; return ret; } - uint32_t d86f_has_extra_bit_cells(int drive) { return (d86f_handler[drive].disk_flags(drive) >> 7) & 1; } - uint32_t -d86f_header_size(int drive) +d86f_header_size(UNUSED(int drive)) { return 8; } - static uint16_t d86f_encode_get_data(uint8_t dat) { uint16_t temp; temp = 0; - if (dat & 0x01) temp |= 1; - if (dat & 0x02) temp |= 4; - if (dat & 0x04) temp |= 16; - if (dat & 0x08) temp |= 64; - if (dat & 0x10) temp |= 256; - if (dat & 0x20) temp |= 1024; - if (dat & 0x40) temp |= 4096; - if (dat & 0x80) temp |= 16384; + if (dat & 0x01) + temp |= 1; + if (dat & 0x02) + temp |= 4; + if (dat & 0x04) + temp |= 16; + if (dat & 0x08) + temp |= 64; + if (dat & 0x10) + temp |= 256; + if (dat & 0x20) + temp |= 1024; + if (dat & 0x40) + temp |= 4096; + if (dat & 0x80) + temp |= 16384; return temp; } - static uint16_t d86f_encode_get_clock(uint8_t dat) { uint16_t temp; temp = 0; - if (dat & 0x01) temp |= 2; - if (dat & 0x02) temp |= 8; - if (dat & 0x40) temp |= 32; - if (dat & 0x08) temp |= 128; - if (dat & 0x10) temp |= 512; - if (dat & 0x20) temp |= 2048; - if (dat & 0x40) temp |= 8192; - if (dat & 0x80) temp |= 32768; + if (dat & 0x01) + temp |= 2; + if (dat & 0x02) + temp |= 8; + if (dat & 0x40) + temp |= 32; + if (dat & 0x08) + temp |= 128; + if (dat & 0x10) + temp |= 512; + if (dat & 0x20) + temp |= 2048; + if (dat & 0x40) + temp |= 8192; + if (dat & 0x80) + temp |= 32768; return temp; } - int d86f_format_conditions(int drive) { return d86f_valid_bit_rate(drive); } - int d86f_wrong_densel(int drive) { int is_3mode = 0; if ((fdd_get_flags(drive) & 7) == 3) - is_3mode = 1; + is_3mode = 1; switch (d86f_hole(drive)) { - case 0: - default: - if (fdd_is_dd(drive)) - return 0; - if (fdd_get_densel(drive)) - return 1; - else - return 0; - break; + default: + case 0: + if (fdd_is_dd(drive)) + return 0; + if (fdd_get_densel(drive)) + return 1; + else + return 0; - case 1: - if (fdd_is_dd(drive)) - return 1; - if (fdd_get_densel(drive)) - return 0; - else { - if (is_3mode) - return 0; - else - return 1; - } - break; + case 1: + if (fdd_is_dd(drive)) + return 1; + if (fdd_get_densel(drive)) + return 0; + else { + if (is_3mode) + return 0; + else + return 1; + } - case 2: - if (fdd_is_dd(drive) || !fdd_is_ed(drive)) - return 1; - if (fdd_get_densel(drive)) - return 0; - else - return 1; - break; + case 2: + if (fdd_is_dd(drive) || !fdd_is_ed(drive)) + return 1; + if (fdd_get_densel(drive)) + return 0; + else + return 1; } } - int d86f_can_format(int drive) { @@ -938,76 +941,82 @@ d86f_can_format(int drive) temp = !writeprot[drive]; temp = temp && !fdc_get_swwp(d86f_fdc); temp = temp && fdd_can_read_medium(real_drive(d86f_fdc, drive)); - temp = temp && d86f_handler[drive].format_conditions(drive); /* Allows proxied formats to add their own extra conditions to formatting. */ + temp = temp && d86f_handler[drive].format_conditions(drive); /* Allows proxied formats to add their own extra conditions to formatting. */ temp = temp && !d86f_wrong_densel(drive); return temp; } - uint16_t d86f_encode_byte(int drive, int sync, decoded_t b, decoded_t prev_b) { - uint8_t encoding = d86f_get_encoding(drive); - uint8_t bits89AB = prev_b.nibbles.nibble0; - uint8_t bits7654 = b.nibbles.nibble1; - uint8_t bits3210 = b.nibbles.nibble0; - uint16_t encoded_7654, encoded_3210, result; + uint8_t encoding = d86f_get_encoding(drive); + uint8_t bits89AB = prev_b.nibbles.nibble0; + uint8_t bits7654 = b.nibbles.nibble1; + uint8_t bits3210 = b.nibbles.nibble0; + uint16_t encoded_7654; + uint16_t encoded_3210; + uint16_t result; if (encoding > 1) - return 0xffff; + return 0xffff; if (sync) { - result = d86f_encode_get_data(b.byte); - if (encoding) { - switch(b.byte) { - case 0xa1: - return result | d86f_encode_get_clock(0x0a); + result = d86f_encode_get_data(b.byte); + if (encoding) { + switch (b.byte) { + case 0xa1: + return result | d86f_encode_get_clock(0x0a); - case 0xc2: - return result | d86f_encode_get_clock(0x14); + case 0xc2: + return result | d86f_encode_get_clock(0x14); - case 0xf8: - return result | d86f_encode_get_clock(0x03); + case 0xf8: + return result | d86f_encode_get_clock(0x03); - case 0xfb: - case 0xfe: - return result | d86f_encode_get_clock(0x00); + case 0xfb: + case 0xfe: + return result | d86f_encode_get_clock(0x00); - case 0xfc: - return result | d86f_encode_get_clock(0x01); - } - } else { - switch(b.byte) { - case 0xf8: - case 0xfb: - case 0xfe: - return result | d86f_encode_get_clock(0xc7); + case 0xfc: + return result | d86f_encode_get_clock(0x01); - case 0xfc: - return result | d86f_encode_get_clock(0xd7); - } - } + default: + break; + } + } else { + switch (b.byte) { + case 0xf8: + case 0xfb: + case 0xfe: + return result | d86f_encode_get_clock(0xc7); + + case 0xfc: + return result | d86f_encode_get_clock(0xd7); + + default: + break; + } + } } bits3210 += ((bits7654 & 3) << 4); bits7654 += ((bits89AB & 3) << 4); encoded_3210 = (encoding == 1) ? encoded_mfm[bits3210] : encoded_fm[bits3210]; encoded_7654 = (encoding == 1) ? encoded_mfm[bits7654] : encoded_fm[bits7654]; - result = (encoded_7654 << 8) | encoded_3210; + result = (encoded_7654 << 8) | encoded_3210; return result; } - static int d86f_get_bitcell_period(int drive) { - double rate = 0.0; - int mfm = 0; - int tflags = 0; - double rpm = 0; - double size = 8000.0; + double rate = 0.0; + int mfm = 0; + int tflags = 0; + double rpm = 0; + double size = 8000.0; tflags = d86f_track_flags(drive); @@ -1015,37 +1024,39 @@ d86f_get_bitcell_period(int drive) rpm = ((tflags & 0xE0) == 0x20) ? 360.0 : 300.0; switch (tflags & 7) { - case 0: - rate = 500.0; - break; + case 0: + rate = 500.0; + break; - case 1: - rate = 300.0; - break; + case 1: + rate = 300.0; + break; - case 2: - rate = 250.0; - break; + case 2: + rate = 250.0; + break; - case 3: - rate = 1000.0; - break; + case 3: + rate = 1000.0; + break; - case 5: - rate = 2000.0; - break; + case 5: + rate = 2000.0; + break; + + default: + break; } - if (! mfm) - rate /= 2.0; + if (!mfm) + rate /= 2.0; size = (size * 250.0) / rate; size = (size * 300.0) / rpm; size = (size * fdd_getrpm(real_drive(d86f_fdc, drive))) / 300.0; - return (int)size; + return (int) size; } - int d86f_can_read_address(int drive) { @@ -1059,11 +1070,10 @@ d86f_can_read_address(int drive) return temp; } - void d86f_get_bit(int drive, int side) { - d86f_t *dev = d86f[drive]; + d86f_t *dev = d86f[drive]; uint32_t track_word; uint32_t track_bit; uint16_t encoded_data; @@ -1077,45 +1087,44 @@ d86f_get_bit(int drive, int side) track_bit = 15 - (dev->track_pos & 15); if (d86f_reverse_bytes(drive)) { - /* Image is in reverse endianness, read the data as is. */ - encoded_data = d86f_handler[drive].encoded_data(drive, side)[track_word]; + /* Image is in reverse endianness, read the data as is. */ + encoded_data = d86f_handler[drive].encoded_data(drive, side)[track_word]; } else { - /* We store the words as big endian, so we need to convert them to little endian when reading. */ - encoded_data = (d86f_handler[drive].encoded_data(drive, side)[track_word] & 0xFF) << 8; - encoded_data |= (d86f_handler[drive].encoded_data(drive, side)[track_word] >> 8); + /* We store the words as big endian, so we need to convert them to little endian when reading. */ + encoded_data = (d86f_handler[drive].encoded_data(drive, side)[track_word] & 0xFF) << 8; + encoded_data |= (d86f_handler[drive].encoded_data(drive, side)[track_word] >> 8); } /* In some cases, misindentification occurs so we need to make sure the surface data array is not not NULL. */ if (d86f_has_surface_desc(drive) && dev->track_surface_data[side]) { - if (d86f_reverse_bytes(drive)) { - surface_data = dev->track_surface_data[side][track_word] & 0xFF; - } else { - surface_data = (dev->track_surface_data[side][track_word] & 0xFF) << 8; - surface_data |= (dev->track_surface_data[side][track_word] >> 8); - } + if (d86f_reverse_bytes(drive)) { + surface_data = dev->track_surface_data[side][track_word] & 0xFF; + } else { + surface_data = (dev->track_surface_data[side][track_word] & 0xFF) << 8; + surface_data |= (dev->track_surface_data[side][track_word] >> 8); + } } current_bit = (encoded_data >> track_bit) & 1; dev->last_word[side] <<= 1; if (d86f_has_surface_desc(drive) && dev->track_surface_data[side]) { - surface_bit = (surface_data >> track_bit) & 1; - if (! surface_bit) - dev->last_word[side] |= current_bit; - else { - /* Bit is either 0 or 1 and is set to fuzzy, we randomly generate it. */ - dev->last_word[side] |= (random_generate() & 1); - } + surface_bit = (surface_data >> track_bit) & 1; + if (!surface_bit) + dev->last_word[side] |= current_bit; + else { + /* Bit is either 0 or 1 and is set to fuzzy, we randomly generate it. */ + dev->last_word[side] |= (random_generate() & 1); + } } else - dev->last_word[side] |= current_bit; + dev->last_word[side] |= current_bit; } - void d86f_put_bit(int drive, int side, int bit) { - d86f_t *dev = d86f[drive]; + d86f_t *dev = d86f[drive]; uint32_t track_word; uint32_t track_bit; uint16_t encoded_data; @@ -1124,7 +1133,7 @@ d86f_put_bit(int drive, int side, int bit) uint16_t surface_bit; if (fdc_get_diswr(d86f_fdc)) - return; + return; track_word = dev->track_pos >> 4; @@ -1132,67 +1141,66 @@ d86f_put_bit(int drive, int side, int bit) track_bit = 15 - (dev->track_pos & 15); if (d86f_reverse_bytes(drive)) { - /* Image is in reverse endianness, read the data as is. */ - encoded_data = d86f_handler[drive].encoded_data(drive, side)[track_word]; + /* Image is in reverse endianness, read the data as is. */ + encoded_data = d86f_handler[drive].encoded_data(drive, side)[track_word]; } else { - /* We store the words as big endian, so we need to convert them to little endian when reading. */ - encoded_data = (d86f_handler[drive].encoded_data(drive, side)[track_word] & 0xFF) << 8; - encoded_data |= (d86f_handler[drive].encoded_data(drive, side)[track_word] >> 8); + /* We store the words as big endian, so we need to convert them to little endian when reading. */ + encoded_data = (d86f_handler[drive].encoded_data(drive, side)[track_word] & 0xFF) << 8; + encoded_data |= (d86f_handler[drive].encoded_data(drive, side)[track_word] >> 8); } if (d86f_has_surface_desc(drive)) { - if (d86f_reverse_bytes(drive)) { - surface_data = dev->track_surface_data[side][track_word] & 0xFF; - } else { - surface_data = (dev->track_surface_data[side][track_word] & 0xFF) << 8; - surface_data |= (dev->track_surface_data[side][track_word] >> 8); - } + if (d86f_reverse_bytes(drive)) { + surface_data = dev->track_surface_data[side][track_word] & 0xFF; + } else { + surface_data = (dev->track_surface_data[side][track_word] & 0xFF) << 8; + surface_data |= (dev->track_surface_data[side][track_word] >> 8); + } } current_bit = (encoded_data >> track_bit) & 1; dev->last_word[side] <<= 1; if (d86f_has_surface_desc(drive)) { - surface_bit = (surface_data >> track_bit) & 1; - if (! surface_bit) { - dev->last_word[side] |= bit; - current_bit = bit; - } else { - if (current_bit) { - /* Bit is 1 and is set to fuzzy, we overwrite it with a non-fuzzy bit. */ - dev->last_word[side] |= bit; - current_bit = bit; - surface_bit = 0; - } - } + surface_bit = (surface_data >> track_bit) & 1; + if (!surface_bit) { + dev->last_word[side] |= bit; + current_bit = bit; + } else { + if (current_bit) { + /* Bit is 1 and is set to fuzzy, we overwrite it with a non-fuzzy bit. */ + dev->last_word[side] |= bit; + current_bit = bit; + surface_bit = 0; + } + } - surface_data &= ~(1 << track_bit); - surface_data |= (surface_bit << track_bit); - if (d86f_reverse_bytes(drive)) { - dev->track_surface_data[side][track_word] = surface_data; - } else { - dev->track_surface_data[side][track_word] = (surface_data & 0xFF) << 8; - dev->track_surface_data[side][track_word] |= (surface_data >> 8); - } + surface_data &= ~(1 << track_bit); + surface_data |= (surface_bit << track_bit); + if (d86f_reverse_bytes(drive)) { + dev->track_surface_data[side][track_word] = surface_data; + } else { + dev->track_surface_data[side][track_word] = (surface_data & 0xFF) << 8; + dev->track_surface_data[side][track_word] |= (surface_data >> 8); + } } else { - dev->last_word[side] |= bit; - current_bit = bit; + dev->last_word[side] |= bit; + current_bit = bit; } encoded_data &= ~(1 << track_bit); encoded_data |= (current_bit << track_bit); if (d86f_reverse_bytes(drive)) { - d86f_handler[drive].encoded_data(drive, side)[track_word] = encoded_data; + d86f_handler[drive].encoded_data(drive, side)[track_word] = encoded_data; } else { - d86f_handler[drive].encoded_data(drive, side)[track_word] = (encoded_data & 0xFF) << 8; - d86f_handler[drive].encoded_data(drive, side)[track_word] |= (encoded_data >> 8); + d86f_handler[drive].encoded_data(drive, side)[track_word] = (encoded_data & 0xFF) << 8; + d86f_handler[drive].encoded_data(drive, side)[track_word] |= (encoded_data >> 8); } } - static uint8_t -decodefm(int drive, uint16_t dat) +decodefm(UNUSED(int drive), uint16_t dat) { uint8_t temp = 0; @@ -1200,42 +1208,46 @@ decodefm(int drive, uint16_t dat) * We write the encoded bytes in big endian, so we * process the two 8-bit halves swapped here. */ - if (dat & 0x0001) temp |= 1; - if (dat & 0x0004) temp |= 2; - if (dat & 0x0010) temp |= 4; - if (dat & 0x0040) temp |= 8; - if (dat & 0x0100) temp |= 16; - if (dat & 0x0400) temp |= 32; - if (dat & 0x1000) temp |= 64; - if (dat & 0x4000) temp |= 128; + if (dat & 0x0001) + temp |= 1; + if (dat & 0x0004) + temp |= 2; + if (dat & 0x0010) + temp |= 4; + if (dat & 0x0040) + temp |= 8; + if (dat & 0x0100) + temp |= 16; + if (dat & 0x0400) + temp |= 32; + if (dat & 0x1000) + temp |= 64; + if (dat & 0x4000) + temp |= 128; return temp; } - void fdd_calccrc(uint8_t byte, crc_t *crc_var) { - crc_var->word = (crc_var->word << 8) ^ - CRCTable[(crc_var->word >> 8)^byte]; + crc_var->word = (crc_var->word << 8) ^ CRCTable[(crc_var->word >> 8) ^ byte]; } - static void d86f_calccrc(d86f_t *dev, uint8_t byte) { fdd_calccrc(byte, &(dev->calc_crc)); } - int d86f_word_is_aligned(int drive, int side, uint32_t base_pos) { - d86f_t *dev = d86f[drive]; - uint32_t adjusted_track_pos = dev->track_pos; + const d86f_t *dev = d86f[drive]; + uint32_t adjusted_track_pos = dev->track_pos; if (base_pos == 0xFFFFFFFF) - return 0; + return 0; /* * This is very important, it makes sure alignment is detected @@ -1243,15 +1255,14 @@ d86f_word_is_aligned(int drive, int side, uint32_t base_pos) * is not divisible by 16. */ if (adjusted_track_pos < base_pos) - adjusted_track_pos += d86f_handler[drive].get_raw_size(drive, side); + adjusted_track_pos += d86f_handler[drive].get_raw_size(drive, side); if ((adjusted_track_pos & 15) == (base_pos & 15)) - return 1; + return 1; return 0; } - /* State 1: Find sector ID */ void d86f_find_address_mark_fm(int drive, int side, find_t *find, uint16_t req_am, uint16_t other_am, uint16_t wrong_am, uint16_t ignore_other_am) @@ -1261,42 +1272,41 @@ d86f_find_address_mark_fm(int drive, int side, find_t *find, uint16_t req_am, ui d86f_get_bit(drive, side); if (dev->last_word[side] == req_am) { - dev->calc_crc.word = 0xFFFF; - fdd_calccrc(decodefm(drive, dev->last_word[side]), &(dev->calc_crc)); - find->sync_marks = find->bits_obtained = find->bytes_obtained = 0; - find->sync_pos = 0xFFFFFFFF; - dev->preceding_bit[side] = dev->last_word[side] & 1; - dev->state++; - return; + dev->calc_crc.word = 0xFFFF; + fdd_calccrc(decodefm(drive, dev->last_word[side]), &(dev->calc_crc)); + find->sync_marks = find->bits_obtained = find->bytes_obtained = 0; + find->sync_pos = 0xFFFFFFFF; + dev->preceding_bit[side] = dev->last_word[side] & 1; + dev->state++; + return; } - if ((wrong_am) && (dev->last_word[side] == wrong_am)) { - dev->data_find.sync_marks = dev->data_find.bits_obtained = dev->data_find.bytes_obtained = 0; - dev->error_condition = 0; - dev->state = STATE_IDLE; - fdc_finishread(d86f_fdc); - fdc_nodataam(d86f_fdc); - return; + if (wrong_am && (dev->last_word[side] == wrong_am)) { + dev->data_find.sync_marks = dev->data_find.bits_obtained = dev->data_find.bytes_obtained = 0; + dev->error_condition = 0; + dev->state = STATE_IDLE; + fdc_finishread(d86f_fdc); + fdc_nodataam(d86f_fdc); + return; } if ((ignore_other_am & 2) && (dev->last_word[side] == other_am)) { - dev->calc_crc.word = 0xFFFF; - fdd_calccrc(decodefm(drive, dev->last_word[side]), &(dev->calc_crc)); - find->sync_marks = find->bits_obtained = find->bytes_obtained = 0; - find->sync_pos = 0xFFFFFFFF; - if (ignore_other_am & 1) { - /* Skip mode, let's go back to finding ID. */ - dev->state -= 2; - } else { - /* Not skip mode, process the sector anyway. */ - fdc_set_wrong_am(d86f_fdc); - dev->preceding_bit[side] = dev->last_word[side] & 1; - dev->state++; - } + dev->calc_crc.word = 0xFFFF; + fdd_calccrc(decodefm(drive, dev->last_word[side]), &(dev->calc_crc)); + find->sync_marks = find->bits_obtained = find->bytes_obtained = 0; + find->sync_pos = 0xFFFFFFFF; + if (ignore_other_am & 1) { + /* Skip mode, let's go back to finding ID. */ + dev->state -= 2; + } else { + /* Not skip mode, process the sector anyway. */ + fdc_set_wrong_am(d86f_fdc); + dev->preceding_bit[side] = dev->last_word[side] & 1; + dev->state++; + } } } - /* When writing in FM mode, we find the beginning of the address mark by looking for 352 (22 * 16) set bits (gap fill = 0xFF, 0xFFFF FM-encoded). */ void d86f_write_find_address_mark_fm(int drive, int side, find_t *find) @@ -1306,24 +1316,23 @@ d86f_write_find_address_mark_fm(int drive, int side, find_t *find) d86f_get_bit(drive, side); if (dev->last_word[side] & 1) { - find->sync_marks++; - if (find->sync_marks == 352) { - dev->calc_crc.word = 0xFFFF; - dev->preceding_bit[side] = 1; - find->sync_marks = 0; - dev->state++; - return; - } + find->sync_marks++; + if (find->sync_marks == 352) { + dev->calc_crc.word = 0xFFFF; + dev->preceding_bit[side] = 1; + find->sync_marks = 0; + dev->state++; + return; + } } /* If we hadn't found enough set bits but have found a clear bit, null the counter of set bits. */ if (!(dev->last_word[side] & 1)) { - find->sync_marks = find->bits_obtained = find->bytes_obtained = 0; - find->sync_pos = 0xFFFFFFFF; + find->sync_marks = find->bits_obtained = find->bytes_obtained = 0; + find->sync_pos = 0xFFFFFFFF; } } - void d86f_find_address_mark_mfm(int drive, int side, find_t *find, uint16_t req_am, uint16_t other_am, uint16_t wrong_am, uint16_t ignore_other_am) { @@ -1332,60 +1341,59 @@ d86f_find_address_mark_mfm(int drive, int side, find_t *find, uint16_t req_am, u d86f_get_bit(drive, side); if (dev->last_word[side] == 0x4489) { - find->sync_marks++; - find->sync_pos = dev->track_pos; - return; + find->sync_marks++; + find->sync_pos = dev->track_pos; + return; } - if ((wrong_am) && (dev->last_word[side] == wrong_am) && (find->sync_marks >= 3)) { - dev->data_find.sync_marks = dev->data_find.bits_obtained = dev->data_find.bytes_obtained = 0; - dev->error_condition = 0; - dev->state = STATE_IDLE; - fdc_finishread(d86f_fdc); - fdc_nodataam(d86f_fdc); - return; + if (wrong_am && (dev->last_word[side] == wrong_am) && (find->sync_marks >= 3)) { + dev->data_find.sync_marks = dev->data_find.bits_obtained = dev->data_find.bytes_obtained = 0; + dev->error_condition = 0; + dev->state = STATE_IDLE; + fdc_finishread(d86f_fdc); + fdc_nodataam(d86f_fdc); + return; } if ((dev->last_word[side] == req_am) && (find->sync_marks >= 3)) { - if (d86f_word_is_aligned(drive, side, find->sync_pos)) { - dev->calc_crc.word = 0xCDB4; - fdd_calccrc(decodefm(drive, dev->last_word[side]), &(dev->calc_crc)); - find->sync_marks = find->bits_obtained = find->bytes_obtained = 0; - find->sync_pos = 0xFFFFFFFF; - dev->preceding_bit[side] = dev->last_word[side] & 1; - dev->state++; - return; - } + if (d86f_word_is_aligned(drive, side, find->sync_pos)) { + dev->calc_crc.word = 0xCDB4; + fdd_calccrc(decodefm(drive, dev->last_word[side]), &(dev->calc_crc)); + find->sync_marks = find->bits_obtained = find->bytes_obtained = 0; + find->sync_pos = 0xFFFFFFFF; + dev->preceding_bit[side] = dev->last_word[side] & 1; + dev->state++; + return; + } } if ((ignore_other_am & 2) && (dev->last_word[side] == other_am) && (find->sync_marks >= 3)) { - if (d86f_word_is_aligned(drive, side, find->sync_pos)) { - dev->calc_crc.word = 0xCDB4; - fdd_calccrc(decodefm(drive, dev->last_word[side]), &(dev->calc_crc)); - find->sync_marks = find->bits_obtained = find->bytes_obtained = 0; - find->sync_pos = 0xFFFFFFFF; - if (ignore_other_am & 1) { - /* Skip mode, let's go back to finding ID. */ - dev->state -= 2; - } else { - /* Not skip mode, process the sector anyway. */ - fdc_set_wrong_am(d86f_fdc); - dev->preceding_bit[side] = dev->last_word[side] & 1; - dev->state++; - } - return; - } + if (d86f_word_is_aligned(drive, side, find->sync_pos)) { + dev->calc_crc.word = 0xCDB4; + fdd_calccrc(decodefm(drive, dev->last_word[side]), &(dev->calc_crc)); + find->sync_marks = find->bits_obtained = find->bytes_obtained = 0; + find->sync_pos = 0xFFFFFFFF; + if (ignore_other_am & 1) { + /* Skip mode, let's go back to finding ID. */ + dev->state -= 2; + } else { + /* Not skip mode, process the sector anyway. */ + fdc_set_wrong_am(d86f_fdc); + dev->preceding_bit[side] = dev->last_word[side] & 1; + dev->state++; + } + return; + } } if (dev->last_word[side] != 0x4489) { - if (d86f_word_is_aligned(drive, side, find->sync_pos)) { - find->sync_marks = find->bits_obtained = find->bytes_obtained = 0; - find->sync_pos = 0xFFFFFFFF; - } + if (d86f_word_is_aligned(drive, side, find->sync_pos)) { + find->sync_marks = find->bits_obtained = find->bytes_obtained = 0; + find->sync_pos = 0xFFFFFFFF; + } } } - /* When writing in MFM mode, we find the beginning of the address mark by looking for 3 0xA1 sync bytes. */ void d86f_write_find_address_mark_mfm(int drive, int side, find_t *find) @@ -1395,27 +1403,26 @@ d86f_write_find_address_mark_mfm(int drive, int side, find_t *find) d86f_get_bit(drive, side); if (dev->last_word[side] == 0x4489) { - find->sync_marks++; - find->sync_pos = dev->track_pos; - if (find->sync_marks == 3) { - dev->calc_crc.word = 0xCDB4; - dev->preceding_bit[side] = 1; - find->sync_marks = 0; - dev->state++; - return; - } + find->sync_marks++; + find->sync_pos = dev->track_pos; + if (find->sync_marks == 3) { + dev->calc_crc.word = 0xCDB4; + dev->preceding_bit[side] = 1; + find->sync_marks = 0; + dev->state++; + return; + } } /* If we hadn't found enough address mark sync marks, null the counter. */ if (dev->last_word[side] != 0x4489) { - if (d86f_word_is_aligned(drive, side, find->sync_pos)) { - find->sync_marks = find->bits_obtained = find->bytes_obtained = 0; - find->sync_pos = 0xFFFFFFFF; - } + if (d86f_word_is_aligned(drive, side, find->sync_pos)) { + find->sync_marks = find->bits_obtained = find->bytes_obtained = 0; + find->sync_pos = 0xFFFFFFFF; + } } } - /* State 2: Read sector ID and CRC*/ void d86f_read_sector_id(int drive, int side, int match) @@ -1423,69 +1430,69 @@ d86f_read_sector_id(int drive, int side, int match) d86f_t *dev = d86f[drive]; if (dev->id_find.bits_obtained) { - if (! (dev->id_find.bits_obtained & 15)) { - /* We've got a byte. */ - if (dev->id_find.bytes_obtained < 4) { - dev->last_sector.byte_array[dev->id_find.bytes_obtained] = decodefm(drive, dev->last_word[side]); - fdd_calccrc(dev->last_sector.byte_array[dev->id_find.bytes_obtained], &(dev->calc_crc)); - } else if ((dev->id_find.bytes_obtained >= 4) && (dev->id_find.bytes_obtained < 6)) { - dev->track_crc.bytes[(dev->id_find.bytes_obtained & 1) ^ 1] = decodefm(drive, dev->last_word[side]); - } - dev->id_find.bytes_obtained++; + if (!(dev->id_find.bits_obtained & 15)) { + /* We've got a byte. */ + if (dev->id_find.bytes_obtained < 4) { + dev->last_sector.byte_array[dev->id_find.bytes_obtained] = decodefm(drive, dev->last_word[side]); + fdd_calccrc(dev->last_sector.byte_array[dev->id_find.bytes_obtained], &(dev->calc_crc)); + } else if ((dev->id_find.bytes_obtained >= 4) && (dev->id_find.bytes_obtained < 6)) { + dev->track_crc.bytes[(dev->id_find.bytes_obtained & 1) ^ 1] = decodefm(drive, dev->last_word[side]); + } + dev->id_find.bytes_obtained++; - if (dev->id_find.bytes_obtained == 6) { - /* We've got the ID. */ - if ((dev->calc_crc.word != dev->track_crc.word) && (dev->last_sector.dword == dev->req_sector.dword)) { - dev->id_find.sync_marks = dev->id_find.bits_obtained = dev->id_find.bytes_obtained = 0; - d86f_log("86F: ID CRC error: %04X != %04X (%08X)\n", dev->track_crc.word, dev->calc_crc.word, dev->last_sector.dword); - if ((dev->state != STATE_02_READ_ID) && (dev->state != STATE_0A_READ_ID)) { - dev->error_condition = 0; - dev->state = STATE_IDLE; - fdc_finishread(d86f_fdc); - fdc_headercrcerror(d86f_fdc); - } else if (dev->state == STATE_0A_READ_ID) - dev->state--; - else { - dev->error_condition |= 1; /* Mark that there was an ID CRC error. */ - dev->state++; - } - } else if ((dev->calc_crc.word == dev->track_crc.word) && (dev->state == STATE_0A_READ_ID)) { - /* CRC is valid and this is a read sector ID command. */ - dev->id_find.sync_marks = dev->id_find.bits_obtained = dev->id_find.bytes_obtained = dev->error_condition = 0; - fdc_sectorid(d86f_fdc, dev->last_sector.id.c, dev->last_sector.id.h, dev->last_sector.id.r, dev->last_sector.id.n, 0, 0); - dev->state = STATE_IDLE; - } else { - /* CRC is valid. */ - dev->id_find.sync_marks = dev->id_find.bits_obtained = dev->id_find.bytes_obtained = 0; - dev->id_found |= 1; - if ((dev->last_sector.dword == dev->req_sector.dword) || !match) { - d86f_handler[drive].set_sector(drive, side, dev->last_sector.id.c, dev->last_sector.id.h, dev->last_sector.id.r, dev->last_sector.id.n); - if (dev->state == STATE_02_READ_ID) { - /* READ TRACK command, we need some special handling here. */ - /* Code corrected: Only the C, H, and N portions of the sector ID are compared, the R portion (the sector number) is ignored. */ - if ((dev->last_sector.id.c != fdc_get_read_track_sector(d86f_fdc).id.c) || (dev->last_sector.id.h != fdc_get_read_track_sector(d86f_fdc).id.h) || (dev->last_sector.id.n != fdc_get_read_track_sector(d86f_fdc).id.n)) { - dev->error_condition |= 4; /* Mark that the sector ID is not the one expected by the FDC. */ - /* Make sure we use the sector size from the FDC. */ - dev->last_sector.id.n = fdc_get_read_track_sector(d86f_fdc).id.n; - } + if (dev->id_find.bytes_obtained == 6) { + /* We've got the ID. */ + if ((dev->calc_crc.word != dev->track_crc.word) && (dev->last_sector.dword == dev->req_sector.dword)) { + dev->id_find.sync_marks = dev->id_find.bits_obtained = dev->id_find.bytes_obtained = 0; + d86f_log("86F: ID CRC error: %04X != %04X (%08X)\n", dev->track_crc.word, dev->calc_crc.word, dev->last_sector.dword); + if ((dev->state != STATE_02_READ_ID) && (dev->state != STATE_0A_READ_ID)) { + dev->error_condition = 0; + dev->state = STATE_IDLE; + fdc_finishread(d86f_fdc); + fdc_headercrcerror(d86f_fdc); + } else if (dev->state == STATE_0A_READ_ID) + dev->state--; + else { + dev->error_condition |= 1; /* Mark that there was an ID CRC error. */ + dev->state++; + } + } else if ((dev->calc_crc.word == dev->track_crc.word) && (dev->state == STATE_0A_READ_ID)) { + /* CRC is valid and this is a read sector ID command. */ + dev->id_find.sync_marks = dev->id_find.bits_obtained = dev->id_find.bytes_obtained = dev->error_condition = 0; + fdc_sectorid(d86f_fdc, dev->last_sector.id.c, dev->last_sector.id.h, dev->last_sector.id.r, dev->last_sector.id.n, 0, 0); + dev->state = STATE_IDLE; + } else { + /* CRC is valid. */ + dev->id_find.sync_marks = dev->id_find.bits_obtained = dev->id_find.bytes_obtained = 0; + dev->id_found |= 1; + if ((dev->last_sector.dword == dev->req_sector.dword) || !match) { + d86f_handler[drive].set_sector(drive, side, dev->last_sector.id.c, dev->last_sector.id.h, dev->last_sector.id.r, dev->last_sector.id.n); + if (dev->state == STATE_02_READ_ID) { + /* READ TRACK command, we need some special handling here. */ + /* Code corrected: Only the C, H, and N portions of the sector ID are compared, the R portion (the sector number) is ignored. */ + if ((dev->last_sector.id.c != fdc_get_read_track_sector(d86f_fdc).id.c) || (dev->last_sector.id.h != fdc_get_read_track_sector(d86f_fdc).id.h) || (dev->last_sector.id.n != fdc_get_read_track_sector(d86f_fdc).id.n)) { + dev->error_condition |= 4; /* Mark that the sector ID is not the one expected by the FDC. */ + /* Make sure we use the sector size from the FDC. */ + dev->last_sector.id.n = fdc_get_read_track_sector(d86f_fdc).id.n; + } - /* If the two ID's are identical, then we do not need to do anything regarding the sector size. */ - } - dev->state++; - } else { - if (dev->last_sector.id.c != dev->req_sector.id.c) { - if (dev->last_sector.id.c == 0xFF) { - dev->error_condition |= 8; - } else { - dev->error_condition |= 0x10; - } - } + /* If the two ID's are identical, then we do not need to do anything regarding the sector size. */ + } + dev->state++; + } else { + if (dev->last_sector.id.c != dev->req_sector.id.c) { + if (dev->last_sector.id.c == 0xFF) { + dev->error_condition |= 8; + } else { + dev->error_condition |= 0x10; + } + } - dev->state--; - } - } - } - } + dev->state--; + } + } + } + } } d86f_get_bit(drive, side); @@ -1493,135 +1500,135 @@ d86f_read_sector_id(int drive, int side, int match) dev->id_find.bits_obtained++; } - uint8_t d86f_get_data(int drive, int base) { d86f_t *dev = d86f[drive]; - int data, byte_count; + int data; + int byte_count; if (fdd_get_turbo(drive) && (dev->version == 0x0063)) - byte_count = dev->turbo_pos; + byte_count = dev->turbo_pos; else - byte_count = dev->data_find.bytes_obtained; + byte_count = dev->data_find.bytes_obtained; if (byte_count < (d86f_get_data_len(drive) + base)) { - data = fdc_getdata(d86f_fdc, byte_count == (d86f_get_data_len(drive) + base - 1)); - if ((data & DMA_OVER) || (data == -1)) { - dev->dma_over++; - if (data == -1) - data = 0; - else - data &= 0xff; - } + data = fdc_getdata(d86f_fdc, byte_count == (d86f_get_data_len(drive) + base - 1)); + if ((data & DMA_OVER) || (data == -1)) { + dev->dma_over++; + if (data == -1) + data = 0; + else + data &= 0xff; + } } else { - data = 0; + data = 0; } return data; } - void d86f_compare_byte(int drive, uint8_t received_byte, uint8_t disk_byte) { d86f_t *dev = d86f[drive]; - switch(fdc_get_compare_condition(d86f_fdc)) { - case 0: /* SCAN EQUAL */ - if ((received_byte == disk_byte) || (received_byte == 0xFF)) - dev->satisfying_bytes++; - break; + switch (fdc_get_compare_condition(d86f_fdc)) { + case 0: /* SCAN EQUAL */ + if ((received_byte == disk_byte) || (received_byte == 0xFF)) + dev->satisfying_bytes++; + break; - case 1: /* SCAN LOW OR EQUAL */ - if ((received_byte <= disk_byte) || (received_byte == 0xFF)) - dev->satisfying_bytes++; - break; + case 1: /* SCAN LOW OR EQUAL */ + if ((received_byte <= disk_byte) || (received_byte == 0xFF)) + dev->satisfying_bytes++; + break; - case 2: /* SCAN HIGH OR EQUAL */ - if ((received_byte >= disk_byte) || (received_byte == 0xFF)) - dev->satisfying_bytes++; - break; + case 2: /* SCAN HIGH OR EQUAL */ + if ((received_byte >= disk_byte) || (received_byte == 0xFF)) + dev->satisfying_bytes++; + break; + + default: + break; } } - /* State 4: Read sector data and CRC*/ void d86f_read_sector_data(int drive, int side) { - d86f_t *dev = d86f[drive]; - int data = 0; - int recv_data = 0; - int read_status = 0; - uint32_t sector_len = dev->last_sector.id.n; - uint32_t crc_pos = 0; - sector_len = 1 << (7 + sector_len); - crc_pos = sector_len + 2; + d86f_t *dev = d86f[drive]; + int data = 0; + int recv_data = 0; + int read_status = 0; + uint32_t sector_len = dev->last_sector.id.n; + uint32_t crc_pos = 0; + sector_len = 1 << (7 + sector_len); + crc_pos = sector_len + 2; if (dev->data_find.bits_obtained) { - if (!(dev->data_find.bits_obtained & 15)) { - /* We've got a byte. */ - d86f_log("86F: We've got a byte.\n"); - if (dev->data_find.bytes_obtained < sector_len) { - if (d86f_handler[drive].read_data != NULL) - data = d86f_handler[drive].read_data(drive, side, dev->data_find.bytes_obtained); - else { + if (!(dev->data_find.bits_obtained & 15)) { + /* We've got a byte. */ + d86f_log("86F: We've got a byte.\n"); + if (dev->data_find.bytes_obtained < sector_len) { + if (d86f_handler[drive].read_data != NULL) + data = d86f_handler[drive].read_data(drive, side, dev->data_find.bytes_obtained); + else { #ifdef HACK_FOR_DBASE_III - if ((dev->last_sector.id.c == 39) && (dev->last_sector.id.h == 0) && - (dev->last_sector.id.r == 5) && (dev->data_find.bytes_obtained >= 272)) - data = (random_generate() & 0xff); - else + if ((dev->last_sector.id.c == 39) && (dev->last_sector.id.h == 0) && (dev->last_sector.id.r == 5) && (dev->data_find.bytes_obtained >= 272)) + data = (random_generate() & 0xff); + else #endif - data = decodefm(drive, dev->last_word[side]); - } - if (dev->state == STATE_11_SCAN_DATA) { - /* Scan/compare command. */ - recv_data = d86f_get_data(drive, 0); - d86f_compare_byte(drive, recv_data, data); - } else { - if (dev->data_find.bytes_obtained < d86f_get_data_len(drive)) { - if (dev->state != STATE_16_VERIFY_DATA) { - read_status = fdc_data(d86f_fdc, data, dev->data_find.bytes_obtained == (d86f_get_data_len(drive) - 1)); - if (read_status == -1) - dev->dma_over++; - } - } - } - fdd_calccrc(data, &(dev->calc_crc)); - } else if (dev->data_find.bytes_obtained < crc_pos) - dev->track_crc.bytes[(dev->data_find.bytes_obtained - sector_len) ^ 1] = decodefm(drive, dev->last_word[side]); - dev->data_find.bytes_obtained++; + data = decodefm(drive, dev->last_word[side]); + } + if (dev->state == STATE_11_SCAN_DATA) { + /* Scan/compare command. */ + recv_data = d86f_get_data(drive, 0); + d86f_compare_byte(drive, recv_data, data); + } else { + if (dev->data_find.bytes_obtained < d86f_get_data_len(drive)) { + if (dev->state != STATE_16_VERIFY_DATA) { + read_status = fdc_data(d86f_fdc, data, dev->data_find.bytes_obtained == (d86f_get_data_len(drive) - 1)); + if (read_status == -1) + dev->dma_over++; + } + } + } + fdd_calccrc(data, &(dev->calc_crc)); + } else if (dev->data_find.bytes_obtained < crc_pos) + dev->track_crc.bytes[(dev->data_find.bytes_obtained - sector_len) ^ 1] = decodefm(drive, dev->last_word[side]); + dev->data_find.bytes_obtained++; - if (dev->data_find.bytes_obtained == (crc_pos + fdc_get_gap(d86f_fdc))) { - /* We've got the data. */ - if ((dev->calc_crc.word != dev->track_crc.word) && (dev->state != STATE_02_READ_DATA)) { - d86f_log("86F: Data CRC error: %04X != %04X (%08X)\n", dev->track_crc.word, dev->calc_crc.word, dev->last_sector.dword); - dev->data_find.sync_marks = dev->data_find.bits_obtained = dev->data_find.bytes_obtained = 0; - dev->error_condition = 0; - dev->state = STATE_IDLE; - fdc_finishread(d86f_fdc); - fdc_datacrcerror(d86f_fdc); - } else if ((dev->calc_crc.word != dev->track_crc.word) && (dev->state == STATE_02_READ_DATA)) { - dev->data_find.sync_marks = dev->data_find.bits_obtained = dev->data_find.bytes_obtained = 0; - dev->error_condition |= 2; /* Mark that there was a data error. */ - dev->state = STATE_IDLE; - fdc_track_finishread(d86f_fdc, dev->error_condition); - } else { - /* CRC is valid. */ - d86f_log("86F: Data CRC OK: %04X == %04X (%08X)\n", dev->track_crc.word, dev->calc_crc.word, dev->last_sector.dword); - dev->data_find.sync_marks = dev->data_find.bits_obtained = dev->data_find.bytes_obtained = 0; - dev->error_condition = 0; - dev->state = STATE_IDLE; - if (dev->state == STATE_02_READ_DATA) - fdc_track_finishread(d86f_fdc, dev->error_condition); - else if (dev->state == STATE_11_SCAN_DATA) - fdc_sector_finishcompare(d86f_fdc, (dev->satisfying_bytes == ((128 << ((uint32_t) dev->last_sector.id.n)) - 1)) ? 1 : 0); - else - fdc_sector_finishread(d86f_fdc); - } - } - } + if (dev->data_find.bytes_obtained == (crc_pos + fdc_get_gap(d86f_fdc))) { + /* We've got the data. */ + if ((dev->calc_crc.word != dev->track_crc.word) && (dev->state != STATE_02_READ_DATA)) { + d86f_log("86F: Data CRC error: %04X != %04X (%08X)\n", dev->track_crc.word, dev->calc_crc.word, dev->last_sector.dword); + dev->data_find.sync_marks = dev->data_find.bits_obtained = dev->data_find.bytes_obtained = 0; + dev->error_condition = 0; + dev->state = STATE_IDLE; + fdc_finishread(d86f_fdc); + fdc_datacrcerror(d86f_fdc); + } else if ((dev->calc_crc.word != dev->track_crc.word) && (dev->state == STATE_02_READ_DATA)) { + dev->data_find.sync_marks = dev->data_find.bits_obtained = dev->data_find.bytes_obtained = 0; + dev->error_condition |= 2; /* Mark that there was a data error. */ + dev->state = STATE_IDLE; + fdc_track_finishread(d86f_fdc, dev->error_condition); + } else { + /* CRC is valid. */ + d86f_log("86F: Data CRC OK: %04X == %04X (%08X)\n", dev->track_crc.word, dev->calc_crc.word, dev->last_sector.dword); + dev->data_find.sync_marks = dev->data_find.bits_obtained = dev->data_find.bytes_obtained = 0; + dev->error_condition = 0; + dev->state = STATE_IDLE; + if (dev->state == STATE_02_READ_DATA) + fdc_track_finishread(d86f_fdc, dev->error_condition); + else if (dev->state == STATE_11_SCAN_DATA) + fdc_sector_finishcompare(d86f_fdc, (dev->satisfying_bytes == ((128 << ((uint32_t) dev->last_sector.id.n)) - 1)) ? 1 : 0); + else + fdc_sector_finishread(d86f_fdc); + } + } + } } d86f_get_bit(drive, side); @@ -1629,106 +1636,105 @@ d86f_read_sector_data(int drive, int side) dev->data_find.bits_obtained++; } - void d86f_write_sector_data(int drive, int side, int mfm, uint16_t am) { - d86f_t *dev = d86f[drive]; + d86f_t *dev = d86f[drive]; uint16_t bit_pos; uint16_t temp; uint32_t sector_len = dev->last_sector.id.n; - uint32_t crc_pos = 0; - sector_len = (1 << (7 + sector_len)) + 1; - crc_pos = sector_len + 2; + uint32_t crc_pos = 0; + sector_len = (1 << (7 + sector_len)) + 1; + crc_pos = sector_len + 2; - if (! (dev->data_find.bits_obtained & 15)) { - if (dev->data_find.bytes_obtained < crc_pos) { - if (! dev->data_find.bytes_obtained) { - /* We're writing the address mark. */ - dev->current_byte[side] = am; - } else if (dev->data_find.bytes_obtained < sector_len) { - /* We're in the data field of the sector, read byte from FDC and request new byte. */ - dev->current_byte[side] = d86f_get_data(drive, 1); - if (! fdc_get_diswr(d86f_fdc)) - d86f_handler[drive].write_data(drive, side, dev->data_find.bytes_obtained - 1, dev->current_byte[side]); - } else { - /* We're in the data field of the sector, use a CRC byte. */ - dev->current_byte[side] = dev->calc_crc.bytes[(dev->data_find.bytes_obtained & 1)]; - } + if (!(dev->data_find.bits_obtained & 15)) { + if (dev->data_find.bytes_obtained < crc_pos) { + if (!dev->data_find.bytes_obtained) { + /* We're writing the address mark. */ + dev->current_byte[side] = am; + } else if (dev->data_find.bytes_obtained < sector_len) { + /* We're in the data field of the sector, read byte from FDC and request new byte. */ + dev->current_byte[side] = d86f_get_data(drive, 1); + if (!fdc_get_diswr(d86f_fdc)) + d86f_handler[drive].write_data(drive, side, dev->data_find.bytes_obtained - 1, dev->current_byte[side]); + } else { + /* We're in the data field of the sector, use a CRC byte. */ + dev->current_byte[side] = dev->calc_crc.bytes[dev->data_find.bytes_obtained & 1]; + } - dev->current_bit[side] = (15 - (dev->data_find.bits_obtained & 15)) >> 1; + dev->current_bit[side] = (15 - (dev->data_find.bits_obtained & 15)) >> 1; - /* Write the bit. */ - temp = (dev->current_byte[side] >> dev->current_bit[side]) & 1; - if ((!temp && !dev->preceding_bit[side]) || !mfm) { - temp |= 2; - } + /* Write the bit. */ + temp = (dev->current_byte[side] >> dev->current_bit[side]) & 1; + if ((!temp && !dev->preceding_bit[side]) || !mfm) { + temp |= 2; + } - /* This is an even bit, so write the clock. */ - if (! dev->data_find.bytes_obtained) { - /* Address mark, write bit directly. */ - d86f_put_bit(drive, side, am >> 15); - } else { - d86f_put_bit(drive, side, temp >> 1); - } + /* This is an even bit, so write the clock. */ + if (!dev->data_find.bytes_obtained) { + /* Address mark, write bit directly. */ + d86f_put_bit(drive, side, am >> 15); + } else { + d86f_put_bit(drive, side, temp >> 1); + } - if (dev->data_find.bytes_obtained < sector_len) { - /* This is a data byte, so CRC it. */ - if (! dev->data_find.bytes_obtained) { - fdd_calccrc(decodefm(drive, am), &(dev->calc_crc)); - } else { - fdd_calccrc(dev->current_byte[side], &(dev->calc_crc)); - } - } - } + if (dev->data_find.bytes_obtained < sector_len) { + /* This is a data byte, so CRC it. */ + if (!dev->data_find.bytes_obtained) { + fdd_calccrc(decodefm(drive, am), &(dev->calc_crc)); + } else { + fdd_calccrc(dev->current_byte[side], &(dev->calc_crc)); + } + } + } } else { - if (dev->data_find.bytes_obtained < crc_pos) { - /* Encode the bit. */ - bit_pos = 15 - (dev->data_find.bits_obtained & 15); - dev->current_bit[side] = bit_pos >> 1; + if (dev->data_find.bytes_obtained < crc_pos) { + /* Encode the bit. */ + bit_pos = 15 - (dev->data_find.bits_obtained & 15); + dev->current_bit[side] = bit_pos >> 1; - temp = (dev->current_byte[side] >> dev->current_bit[side]) & 1; - if ((!temp && !dev->preceding_bit[side]) || !mfm) { - temp |= 2; - } + temp = (dev->current_byte[side] >> dev->current_bit[side]) & 1; + if ((!temp && !dev->preceding_bit[side]) || !mfm) { + temp |= 2; + } - if (! dev->data_find.bytes_obtained) { - /* Address mark, write directly. */ - d86f_put_bit(drive, side, am >> bit_pos); - if (! (bit_pos & 1)) { - dev->preceding_bit[side] = am >> bit_pos; - } - } else { - if (bit_pos & 1) { - /* Clock bit */ - d86f_put_bit(drive, side, temp >> 1); - } else { - /* Data bit */ - d86f_put_bit(drive, side, temp & 1); - dev->preceding_bit[side] = temp & 1; - } - } - } + if (!dev->data_find.bytes_obtained) { + /* Address mark, write directly. */ + d86f_put_bit(drive, side, am >> bit_pos); + if (!(bit_pos & 1)) { + dev->preceding_bit[side] = am >> bit_pos; + } + } else { + if (bit_pos & 1) { + /* Clock bit */ + d86f_put_bit(drive, side, temp >> 1); + } else { + /* Data bit */ + d86f_put_bit(drive, side, temp & 1); + dev->preceding_bit[side] = temp & 1; + } + } + } - if ((dev->data_find.bits_obtained & 15) == 15) { - dev->data_find.bytes_obtained++; + if ((dev->data_find.bits_obtained & 15) == 15) { + dev->data_find.bytes_obtained++; - if (dev->data_find.bytes_obtained == (crc_pos + fdc_get_gap(d86f_fdc))) { - /* We've written the data. */ - dev->data_find.sync_marks = dev->data_find.bits_obtained = dev->data_find.bytes_obtained = 0; - dev->error_condition = 0; - dev->state = STATE_IDLE; - fdc_sector_finishread(d86f_fdc); - return; - } - } + if (dev->data_find.bytes_obtained == (crc_pos + fdc_get_gap(d86f_fdc))) { + /* We've written the data. */ + dev->data_find.sync_marks = dev->data_find.bits_obtained = dev->data_find.bytes_obtained = 0; + dev->error_condition = 0; + dev->state = STATE_IDLE; + fdc_sector_finishread(d86f_fdc); + return; + } + } } dev->data_find.bits_obtained++; } - -void d86f_advance_bit(int drive, int side) +void +d86f_advance_bit(int drive, int side) { d86f_t *dev = d86f[drive]; @@ -1736,14 +1742,13 @@ void d86f_advance_bit(int drive, int side) dev->track_pos %= d86f_handler[drive].get_raw_size(drive, side); if (dev->track_pos == d86f_handler[drive].index_hole_pos(drive, side)) { - d86f_handler[drive].read_revolution(drive); + d86f_handler[drive].read_revolution(drive); - if (dev->state != STATE_IDLE) - dev->index_count++; + if (dev->state != STATE_IDLE) + dev->index_count++; } } - void d86f_advance_word(int drive, int side) { @@ -1753,10 +1758,9 @@ d86f_advance_word(int drive, int side) dev->track_pos %= d86f_handler[drive].get_raw_size(drive, side); if ((dev->track_pos == d86f_handler[drive].index_hole_pos(drive, side)) && (dev->state != STATE_IDLE)) - dev->index_count++; + dev->index_count++; } - void d86f_spin_to_index(int drive, int side) { @@ -1768,77 +1772,80 @@ d86f_spin_to_index(int drive, int side) d86f_advance_bit(drive, side); if (dev->track_pos == d86f_handler[drive].index_hole_pos(drive, side)) { - if (dev->state == STATE_0D_SPIN_TO_INDEX) { - /* When starting format, reset format state to the beginning. */ - dev->preceding_bit[side] = 1; - dev->format_state = FMT_PRETRK_GAP0; - } + if (dev->state == STATE_0D_SPIN_TO_INDEX) { + /* When starting format, reset format state to the beginning. */ + dev->preceding_bit[side] = 1; + dev->format_state = FMT_PRETRK_GAP0; + } - /* This is to make sure both READ TRACK and FORMAT TRACK command don't end prematurely. */ - dev->index_count = 0; - dev->state++; + /* This is to make sure both READ TRACK and FORMAT TRACK command don't end prematurely. */ + dev->index_count = 0; + dev->state++; } } - void d86f_write_direct_common(int drive, int side, uint16_t byte, uint8_t type, uint32_t pos) { - d86f_t *dev = d86f[drive]; - uint16_t encoded_byte = 0, mask_data, mask_surface, mask_hole, mask_fuzzy; - decoded_t dbyte, dpbyte; + d86f_t *dev = d86f[drive]; + uint16_t encoded_byte = 0; + uint16_t mask_data; + uint16_t mask_surface; + uint16_t mask_hole; + uint16_t mask_fuzzy; + decoded_t dbyte; + decoded_t dpbyte; - if (fdc_get_diswr(d86f_fdc)) return; + if (fdc_get_diswr(d86f_fdc)) + return; - dbyte.byte = byte & 0xff; + dbyte.byte = byte & 0xff; dpbyte.byte = dev->preceding_bit[side] & 0xff; if (type == 0) { - /* Byte write. */ - encoded_byte = d86f_encode_byte(drive, 0, dbyte, dpbyte); - if (! d86f_reverse_bytes(drive)) { - mask_data = encoded_byte >> 8; - encoded_byte &= 0xFF; - encoded_byte <<= 8; - encoded_byte |= mask_data; - } + /* Byte write. */ + encoded_byte = d86f_encode_byte(drive, 0, dbyte, dpbyte); + if (!d86f_reverse_bytes(drive)) { + mask_data = encoded_byte >> 8; + encoded_byte &= 0xFF; + encoded_byte <<= 8; + encoded_byte |= mask_data; + } } else { - /* Word write. */ - encoded_byte = byte; - if (d86f_reverse_bytes(drive)) { - mask_data = encoded_byte >> 8; - encoded_byte &= 0xFF; - encoded_byte <<= 8; - encoded_byte |= mask_data; - } + /* Word write. */ + encoded_byte = byte; + if (d86f_reverse_bytes(drive)) { + mask_data = encoded_byte >> 8; + encoded_byte &= 0xFF; + encoded_byte <<= 8; + encoded_byte |= mask_data; + } } dev->preceding_bit[side] = encoded_byte & 1; if (d86f_has_surface_desc(drive)) { - mask_data = dev->track_encoded_data[side][pos] ^= 0xFFFF; - mask_surface = dev->track_surface_data[side][pos]; - mask_hole = (mask_surface & mask_data) ^ 0xFFFF; /* This will retain bits that are both fuzzy and 0, therefore physical holes. */ - encoded_byte &= mask_hole; /* Filter out physical hole bits from the encoded data. */ - mask_data ^= 0xFFFF; /* Invert back so bits 1 are 1 again. */ - mask_fuzzy = (mask_surface & mask_data) ^ 0xFFFF; /* All fuzzy bits are 0. */ - dev->track_surface_data[side][pos] &= mask_fuzzy; /* Remove fuzzy bits (but not hole bits) from the surface mask, making them regular again. */ + mask_data = dev->track_encoded_data[side][pos] ^= 0xFFFF; + mask_surface = dev->track_surface_data[side][pos]; + mask_hole = (mask_surface & mask_data) ^ 0xFFFF; /* This will retain bits that are both fuzzy and 0, therefore physical holes. */ + encoded_byte &= mask_hole; /* Filter out physical hole bits from the encoded data. */ + mask_data ^= 0xFFFF; /* Invert back so bits 1 are 1 again. */ + mask_fuzzy = (mask_surface & mask_data) ^ 0xFFFF; /* All fuzzy bits are 0. */ + dev->track_surface_data[side][pos] &= mask_fuzzy; /* Remove fuzzy bits (but not hole bits) from the surface mask, making them regular again. */ } dev->track_encoded_data[side][pos] = encoded_byte; - dev->last_word[side] = encoded_byte; + dev->last_word[side] = encoded_byte; } - void d86f_write_direct(int drive, int side, uint16_t byte, uint8_t type) { - d86f_t *dev = d86f[drive]; + const d86f_t *dev = d86f[drive]; d86f_write_direct_common(drive, side, byte, type, dev->track_pos >> 4); } - uint16_t endian_swap(uint16_t word) { @@ -1851,196 +1858,193 @@ endian_swap(uint16_t word) return temp; } - void -d86f_format_finish(int drive, int side, int mfm, uint16_t sc, uint16_t gap_fill, int do_write) +d86f_format_finish(int drive, int side, int mfm, UNUSED(uint16_t sc), uint16_t gap_fill, int do_write) { d86f_t *dev = d86f[drive]; if (mfm && do_write) { - if (do_write && (dev->track_pos == d86f_handler[drive].index_hole_pos(drive, side))) { - d86f_write_direct_common(drive, side, gap_fill, 0, 0); - } + if (do_write && (dev->track_pos == d86f_handler[drive].index_hole_pos(drive, side))) { + d86f_write_direct_common(drive, side, gap_fill, 0, 0); + } } dev->state = STATE_IDLE; if (do_write) - d86f_handler[drive].writeback(drive); + d86f_handler[drive].writeback(drive); dev->error_condition = 0; - dev->datac = 0; + dev->datac = 0; fdc_sector_finishread(d86f_fdc); } - void -d86f_format_turbo_finish(int drive, int side, int do_write) +d86f_format_turbo_finish(int drive, UNUSED(int side), int do_write) { d86f_t *dev = d86f[drive]; dev->state = STATE_IDLE; if (do_write) - d86f_handler[drive].writeback(drive); + d86f_handler[drive].writeback(drive); dev->error_condition = 0; - dev->datac = 0; + dev->datac = 0; fdc_sector_finishread(d86f_fdc); } - void d86f_format_track(int drive, int side, int do_write) { - d86f_t *dev = d86f[drive]; - int data; + d86f_t *dev = d86f[drive]; + int data; uint16_t max_len; - int mfm; - uint16_t sc = 0; - uint16_t dtl = 0; - int gap_sizes[4] = { 0, 0, 0, 0 }; - int am_len = 0; - int sync_len = 0; - uint16_t iam_mfm[4] = { 0x2452, 0x2452, 0x2452, 0x5255 }; - uint16_t idam_mfm[4] = { 0x8944, 0x8944, 0x8944, 0x5455 }; + int mfm; + uint16_t sc = 0; + uint16_t dtl = 0; + int gap_sizes[4] = { 0, 0, 0, 0 }; + int am_len = 0; + int sync_len = 0; + uint16_t iam_mfm[4] = { 0x2452, 0x2452, 0x2452, 0x5255 }; + uint16_t idam_mfm[4] = { 0x8944, 0x8944, 0x8944, 0x5455 }; uint16_t dataam_mfm[4] = { 0x8944, 0x8944, 0x8944, 0x4555 }; - uint16_t iam_fm = 0xFAF7; - uint16_t idam_fm = 0x7EF5; - uint16_t dataam_fm = 0x6FF5; - uint16_t gap_fill = 0x4E; + uint16_t iam_fm = 0xFAF7; + uint16_t idam_fm = 0x7EF5; + uint16_t dataam_fm = 0x6FF5; + uint16_t gap_fill = 0x4E; - mfm = d86f_is_mfm(drive); - am_len = mfm ? 4 : 1; + mfm = d86f_is_mfm(drive); + am_len = mfm ? 4 : 1; gap_sizes[0] = mfm ? 80 : 40; gap_sizes[1] = mfm ? 50 : 26; gap_sizes[2] = fdc_get_gap2(d86f_fdc, real_drive(d86f_fdc, drive)); gap_sizes[3] = fdc_get_gap(d86f_fdc); - sync_len = mfm ? 12 : 6; - sc = fdc_get_format_sectors(d86f_fdc); - dtl = 128 << fdc_get_format_n(d86f_fdc); - gap_fill = mfm ? 0x4E : 0xFF; + sync_len = mfm ? 12 : 6; + sc = fdc_get_format_sectors(d86f_fdc); + dtl = 128 << fdc_get_format_n(d86f_fdc); + gap_fill = mfm ? 0x4E : 0xFF; - switch(dev->format_state) { - case FMT_POSTTRK_GAP4: - max_len = 60000; - if (do_write) - d86f_write_direct(drive, side, gap_fill, 0); - break; + switch (dev->format_state) { + case FMT_POSTTRK_GAP4: + max_len = 60000; + if (do_write) + d86f_write_direct(drive, side, gap_fill, 0); + break; - case FMT_PRETRK_GAP0: - max_len = gap_sizes[0]; - if (do_write) - d86f_write_direct(drive, side, gap_fill, 0); - break; + case FMT_PRETRK_GAP0: + max_len = gap_sizes[0]; + if (do_write) + d86f_write_direct(drive, side, gap_fill, 0); + break; - case FMT_SECTOR_ID_SYNC: - max_len = sync_len; - if (dev->datac <= 3) { - data = fdc_getdata(d86f_fdc, 0); - if (data != -1) - data &= 0xff; - if ((data == -1) && (dev->datac < 3)) - data = 0; - d86f_fdc->format_sector_id.byte_array[dev->datac] = data & 0xff; - if (dev->datac == 3) - fdc_stop_id_request(d86f_fdc); - } - /*FALLTHROUGH*/ + case FMT_SECTOR_ID_SYNC: + max_len = sync_len; + if (dev->datac <= 3) { + data = fdc_getdata(d86f_fdc, 0); + if (data != -1) + data &= 0xff; + if ((data == -1) && (dev->datac < 3)) + data = 0; + d86f_fdc->format_sector_id.byte_array[dev->datac] = data & 0xff; + if (dev->datac == 3) + fdc_stop_id_request(d86f_fdc); + } + fallthrough; - case FMT_PRETRK_SYNC: - case FMT_SECTOR_DATA_SYNC: - max_len = sync_len; - if (do_write) - d86f_write_direct(drive, side, 0x00, 0); - break; + case FMT_PRETRK_SYNC: + case FMT_SECTOR_DATA_SYNC: + max_len = sync_len; + if (do_write) + d86f_write_direct(drive, side, 0x00, 0); + break; - case FMT_PRETRK_IAM: - max_len = am_len; - if (do_write) { - if (mfm) - d86f_write_direct(drive, side, iam_mfm[dev->datac], 1); - else - d86f_write_direct(drive, side, iam_fm, 1); - } - break; + case FMT_PRETRK_IAM: + max_len = am_len; + if (do_write) { + if (mfm) + d86f_write_direct(drive, side, iam_mfm[dev->datac], 1); + else + d86f_write_direct(drive, side, iam_fm, 1); + } + break; - case FMT_PRETRK_GAP1: - max_len = gap_sizes[1]; - if (do_write) - d86f_write_direct(drive, side, gap_fill, 0); - break; + case FMT_PRETRK_GAP1: + max_len = gap_sizes[1]; + if (do_write) + d86f_write_direct(drive, side, gap_fill, 0); + break; - case FMT_SECTOR_IDAM: - max_len = am_len; - if (mfm) { - if (do_write) - d86f_write_direct(drive, side, idam_mfm[dev->datac], 1); - d86f_calccrc(dev, (dev->datac < 3) ? 0xA1 : 0xFE); - } else { - if (do_write) - d86f_write_direct(drive, side, idam_fm, 1); - d86f_calccrc(dev, 0xFE); - } - break; + case FMT_SECTOR_IDAM: + max_len = am_len; + if (mfm) { + if (do_write) + d86f_write_direct(drive, side, idam_mfm[dev->datac], 1); + d86f_calccrc(dev, (dev->datac < 3) ? 0xA1 : 0xFE); + } else { + if (do_write) + d86f_write_direct(drive, side, idam_fm, 1); + d86f_calccrc(dev, 0xFE); + } + break; - case FMT_SECTOR_ID: - max_len = 4; - if (do_write) { - d86f_write_direct(drive, side, d86f_fdc->format_sector_id.byte_array[dev->datac], 0); - d86f_calccrc(dev, d86f_fdc->format_sector_id.byte_array[dev->datac]); - } else { - if (dev->datac == 3) { - d86f_handler[drive].set_sector(drive, side, d86f_fdc->format_sector_id.id.c, d86f_fdc->format_sector_id.id.h, d86f_fdc->format_sector_id.id.r, d86f_fdc->format_sector_id.id.n); - } - } - break; + case FMT_SECTOR_ID: + max_len = 4; + if (do_write) { + d86f_write_direct(drive, side, d86f_fdc->format_sector_id.byte_array[dev->datac], 0); + d86f_calccrc(dev, d86f_fdc->format_sector_id.byte_array[dev->datac]); + } else { + if (dev->datac == 3) { + d86f_handler[drive].set_sector(drive, side, d86f_fdc->format_sector_id.id.c, d86f_fdc->format_sector_id.id.h, d86f_fdc->format_sector_id.id.r, d86f_fdc->format_sector_id.id.n); + } + } + break; - case FMT_SECTOR_ID_CRC: - case FMT_SECTOR_DATA_CRC: - max_len = 2; - if (do_write) - d86f_write_direct(drive, side, dev->calc_crc.bytes[dev->datac ^ 1], 0); - break; + case FMT_SECTOR_ID_CRC: + case FMT_SECTOR_DATA_CRC: + max_len = 2; + if (do_write) + d86f_write_direct(drive, side, dev->calc_crc.bytes[dev->datac ^ 1], 0); + break; - case FMT_SECTOR_GAP2: - max_len = gap_sizes[2]; - if (do_write) - d86f_write_direct(drive, side, gap_fill, 0); - break; + case FMT_SECTOR_GAP2: + max_len = gap_sizes[2]; + if (do_write) + d86f_write_direct(drive, side, gap_fill, 0); + break; - case FMT_SECTOR_DATAAM: - max_len = am_len; - if (mfm) { - if (do_write) - d86f_write_direct(drive, side, dataam_mfm[dev->datac], 1); - d86f_calccrc(dev, (dev->datac < 3) ? 0xA1 : 0xFB); - } else { - if (do_write) - d86f_write_direct(drive, side, dataam_fm, 1); - d86f_calccrc(dev, 0xFB); - } - break; + case FMT_SECTOR_DATAAM: + max_len = am_len; + if (mfm) { + if (do_write) + d86f_write_direct(drive, side, dataam_mfm[dev->datac], 1); + d86f_calccrc(dev, (dev->datac < 3) ? 0xA1 : 0xFB); + } else { + if (do_write) + d86f_write_direct(drive, side, dataam_fm, 1); + d86f_calccrc(dev, 0xFB); + } + break; - case FMT_SECTOR_DATA: - max_len = dtl; - if (do_write) { - d86f_write_direct(drive, side, dev->fill, 0); - d86f_handler[drive].write_data(drive, side, dev->datac, dev->fill); - } - d86f_calccrc(dev, dev->fill); - break; + case FMT_SECTOR_DATA: + max_len = dtl; + if (do_write) { + d86f_write_direct(drive, side, dev->fill, 0); + d86f_handler[drive].write_data(drive, side, dev->datac, dev->fill); + } + d86f_calccrc(dev, dev->fill); + break; - case FMT_SECTOR_GAP3: - max_len = gap_sizes[3]; - if (do_write) - d86f_write_direct(drive, side, gap_fill, 0); - break; + case FMT_SECTOR_GAP3: + max_len = gap_sizes[3]; + if (do_write) + d86f_write_direct(drive, side, gap_fill, 0); + break; - default: - max_len = 0; - break; + default: + max_len = 0; + break; } dev->datac++; @@ -2048,46 +2052,46 @@ d86f_format_track(int drive, int side, int do_write) d86f_advance_word(drive, side); if ((dev->index_count) && ((dev->format_state < FMT_SECTOR_ID_SYNC) || (dev->format_state > FMT_SECTOR_GAP3))) { - d86f_format_finish(drive, side, mfm, sc, gap_fill, do_write); - return; + d86f_format_finish(drive, side, mfm, sc, gap_fill, do_write); + return; } if (dev->datac >= max_len) { - dev->datac = 0; - dev->format_state++; + dev->datac = 0; + dev->format_state++; - switch (dev->format_state) { - case FMT_SECTOR_ID_SYNC: - fdc_request_next_sector_id(d86f_fdc); - break; + switch (dev->format_state) { + case FMT_SECTOR_ID_SYNC: + fdc_request_next_sector_id(d86f_fdc); + break; - case FMT_SECTOR_IDAM: - case FMT_SECTOR_DATAAM: - dev->calc_crc.word = 0xffff; - break; + case FMT_SECTOR_IDAM: + case FMT_SECTOR_DATAAM: + dev->calc_crc.word = 0xffff; + break; - case FMT_POSTTRK_CHECK: - if (dev->index_count) { - d86f_format_finish(drive, side, mfm, sc, gap_fill, do_write); - return; - } - dev->sector_count++; - if (dev->sector_count < sc) { - /* Sector within allotted amount, change state to SECTOR_ID_SYNC. */ - dev->format_state = FMT_SECTOR_ID_SYNC; - fdc_request_next_sector_id(d86f_fdc); - break; - } else { - dev->format_state = FMT_POSTTRK_GAP4; - dev->sector_count = 0; - break; - } - break; - } + case FMT_POSTTRK_CHECK: + if (dev->index_count) { + d86f_format_finish(drive, side, mfm, sc, gap_fill, do_write); + return; + } + dev->sector_count++; + if (dev->sector_count < sc) { + /* Sector within allotted amount, change state to SECTOR_ID_SYNC. */ + dev->format_state = FMT_SECTOR_ID_SYNC; + fdc_request_next_sector_id(d86f_fdc); + } else { + dev->format_state = FMT_POSTTRK_GAP4; + dev->sector_count = 0; + } + break; + + default: + break; + } } } - void d86f_initialize_last_sector_id(int drive, int c, int h, int r, int n) { @@ -2099,92 +2103,90 @@ d86f_initialize_last_sector_id(int drive, int c, int h, int r, int n) dev->last_sector.id.n = n; } - static uint8_t d86f_sector_flags(int drive, int side, uint8_t c, uint8_t h, uint8_t r, uint8_t n) { - d86f_t *dev = d86f[drive]; - sector_t *s, *t; + const d86f_t *dev = d86f[drive]; + sector_t *s; + sector_t *t; if (dev->last_side_sector[side]) { - s = dev->last_side_sector[side]; - while (s) { - if ((s->c == c) && (s->h == h) && (s->r == r) && (s->n == n)) - return s->flags; - if (! s->prev) - break; - t = s->prev; - s = t; - } + s = dev->last_side_sector[side]; + while (s) { + if ((s->c == c) && (s->h == h) && (s->r == r) && (s->n == n)) + return s->flags; + if (!s->prev) + break; + t = s->prev; + s = t; + } } return 0x00; } - void d86f_turbo_read(int drive, int side) { - d86f_t *dev = d86f[drive]; - uint8_t dat = 0; - int recv_data = 0; - int read_status = 0; - uint8_t flags = d86f_sector_flags(drive, side, dev->req_sector.id.c, dev->req_sector.id.h, dev->req_sector.id.r, dev->req_sector.id.n); + d86f_t *dev = d86f[drive]; + uint8_t dat = 0; + int recv_data = 0; + int read_status = 0; + uint8_t flags = d86f_sector_flags(drive, side, dev->req_sector.id.c, dev->req_sector.id.h, dev->req_sector.id.r, dev->req_sector.id.n); if (d86f_handler[drive].read_data != NULL) - dat = d86f_handler[drive].read_data(drive, side, dev->turbo_pos); + dat = d86f_handler[drive].read_data(drive, side, dev->turbo_pos); else - dat = (random_generate() & 0xff); + dat = (random_generate() & 0xff); if (dev->state == STATE_11_SCAN_DATA) { - /* Scan/compare command. */ - recv_data = d86f_get_data(drive, 0); - d86f_compare_byte(drive, recv_data, dat); + /* Scan/compare command. */ + recv_data = d86f_get_data(drive, 0); + d86f_compare_byte(drive, recv_data, dat); } else { - if (dev->turbo_pos < (128UL << dev->req_sector.id.n)) { - if (dev->state != STATE_16_VERIFY_DATA) { - read_status = fdc_data(d86f_fdc, dat, dev->turbo_pos == ((128UL << dev->req_sector.id.n) - 1)); - if (read_status == -1) - dev->dma_over++; - } - } + if (dev->turbo_pos < (128UL << dev->req_sector.id.n)) { + if (dev->state != STATE_16_VERIFY_DATA) { + read_status = fdc_data(d86f_fdc, dat, dev->turbo_pos == ((128UL << dev->req_sector.id.n) - 1)); + if (read_status == -1) + dev->dma_over++; + } + } } dev->turbo_pos++; if (dev->turbo_pos >= (128UL << dev->req_sector.id.n)) { - dev->data_find.sync_marks = dev->data_find.bits_obtained = dev->data_find.bytes_obtained = 0; - if ((flags & SECTOR_CRC_ERROR) && (dev->state != STATE_02_READ_DATA)) { + dev->data_find.sync_marks = dev->data_find.bits_obtained = dev->data_find.bytes_obtained = 0; + if ((flags & SECTOR_CRC_ERROR) && (dev->state != STATE_02_READ_DATA)) { #ifdef ENABLE_D86F_LOG - d86f_log("86F: Data CRC error in turbo mode (%02X)\n", dev->state); + d86f_log("86F: Data CRC error in turbo mode (%02X)\n", dev->state); #endif - dev->error_condition = 0; - dev->state = STATE_IDLE; - fdc_finishread(d86f_fdc); - fdc_datacrcerror(d86f_fdc); - } else if ((flags & SECTOR_CRC_ERROR) && (dev->state == STATE_02_READ_DATA)) { + dev->error_condition = 0; + dev->state = STATE_IDLE; + fdc_finishread(d86f_fdc); + fdc_datacrcerror(d86f_fdc); + } else if ((flags & SECTOR_CRC_ERROR) && (dev->state == STATE_02_READ_DATA)) { #ifdef ENABLE_D86F_LOG - d86f_log("86F: Data CRC error in turbo mode at READ TRACK command\n"); + d86f_log("86F: Data CRC error in turbo mode at READ TRACK command\n"); #endif - dev->error_condition |= 2; /* Mark that there was a data error. */ - dev->state = STATE_IDLE; - fdc_track_finishread(d86f_fdc, dev->error_condition); - } else { - /* CRC is valid. */ + dev->error_condition |= 2; /* Mark that there was a data error. */ + dev->state = STATE_IDLE; + fdc_track_finishread(d86f_fdc, dev->error_condition); + } else { + /* CRC is valid. */ #ifdef ENABLE_D86F_LOG - d86f_log("86F: Data CRC OK in turbo mode\n"); + d86f_log("86F: Data CRC OK in turbo mode\n"); #endif - dev->error_condition = 0; - dev->state = STATE_IDLE; - if (dev->state == STATE_11_SCAN_DATA) - fdc_sector_finishcompare(d86f_fdc, (dev->satisfying_bytes == ((128 << ((uint32_t) dev->last_sector.id.n)) - 1)) ? 1 : 0); - else - fdc_sector_finishread(d86f_fdc); - } + dev->error_condition = 0; + dev->state = STATE_IDLE; + if (dev->state == STATE_11_SCAN_DATA) + fdc_sector_finishcompare(d86f_fdc, (dev->satisfying_bytes == ((128 << ((uint32_t) dev->last_sector.id.n)) - 1)) ? 1 : 0); + else + fdc_sector_finishread(d86f_fdc); + } } } - void d86f_turbo_write(int drive, int side) { @@ -2197,396 +2199,392 @@ d86f_turbo_write(int drive, int side) dev->turbo_pos++; if (dev->turbo_pos >= (128 << dev->last_sector.id.n)) { - /* We've written the data. */ - dev->data_find.sync_marks = dev->data_find.bits_obtained = dev->data_find.bytes_obtained = 0; - dev->error_condition = 0; - dev->state = STATE_IDLE; - d86f_handler[drive].writeback(drive); - fdc_sector_finishread(d86f_fdc); + /* We've written the data. */ + dev->data_find.sync_marks = dev->data_find.bits_obtained = dev->data_find.bytes_obtained = 0; + dev->error_condition = 0; + dev->state = STATE_IDLE; + d86f_handler[drive].writeback(drive); + fdc_sector_finishread(d86f_fdc); } } - void d86f_turbo_format(int drive, int side, int nop) { - d86f_t *dev = d86f[drive]; - int dat; + d86f_t *dev = d86f[drive]; + int dat; uint16_t sc; uint16_t dtl; - int i; - sc = fdc_get_format_sectors(d86f_fdc); + sc = fdc_get_format_sectors(d86f_fdc); dtl = 128 << fdc_get_format_n(d86f_fdc); if (dev->datac <= 3) { - dat = fdc_getdata(d86f_fdc, 0); - if (dat != -1) - dat &= 0xff; - if ((dat == -1) && (dev->datac < 3)) - dat = 0; - d86f_fdc->format_sector_id.byte_array[dev->datac] = dat & 0xff; - if (dev->datac == 3) { - fdc_stop_id_request(d86f_fdc); - d86f_handler[drive].set_sector(drive, side, d86f_fdc->format_sector_id.id.c, d86f_fdc->format_sector_id.id.h, d86f_fdc->format_sector_id.id.r, d86f_fdc->format_sector_id.id.n); - } + dat = fdc_getdata(d86f_fdc, 0); + if (dat != -1) + dat &= 0xff; + if ((dat == -1) && (dev->datac < 3)) + dat = 0; + d86f_fdc->format_sector_id.byte_array[dev->datac] = dat & 0xff; + if (dev->datac == 3) { + fdc_stop_id_request(d86f_fdc); + d86f_handler[drive].set_sector(drive, side, d86f_fdc->format_sector_id.id.c, d86f_fdc->format_sector_id.id.h, d86f_fdc->format_sector_id.id.r, d86f_fdc->format_sector_id.id.n); + } } else if (dev->datac == 4) { - if (! nop) { - for (i = 0; i < dtl; i++) - d86f_handler[drive].write_data(drive, side, i, dev->fill); - } + if (!nop) { + for (uint16_t i = 0; i < dtl; i++) + d86f_handler[drive].write_data(drive, side, i, dev->fill); + } - dev->sector_count++; + dev->sector_count++; } dev->datac++; if (dev->datac == 6) { - dev->datac = 0; + dev->datac = 0; - if (dev->sector_count < sc) { - /* Sector within allotted amount. */ - fdc_request_next_sector_id(d86f_fdc); - } else { - dev->state = STATE_IDLE; - d86f_format_turbo_finish(drive, side, nop); - } + if (dev->sector_count < sc) { + /* Sector within allotted amount. */ + fdc_request_next_sector_id(d86f_fdc); + } else { + dev->state = STATE_IDLE; + d86f_format_turbo_finish(drive, side, nop); + } } } - int d86f_sector_is_present(int drive, int side, uint8_t c, uint8_t h, uint8_t r, uint8_t n) { - d86f_t *dev = d86f[drive]; - sector_t *s, *t; + const d86f_t *dev = d86f[drive]; + sector_t *s; + sector_t *t; if (dev->last_side_sector[side]) { - s = dev->last_side_sector[side]; - while (s) { - if ((s->c == c) && (s->h == h) && (s->r == r) && (s->n == n)) - return 1; - if (! s->prev) - break; - t = s->prev; - s = t; - } + s = dev->last_side_sector[side]; + while (s) { + if ((s->c == c) && (s->h == h) && (s->r == r) && (s->n == n)) + return 1; + if (!s->prev) + break; + t = s->prev; + s = t; + } } return 0; } - void d86f_turbo_poll(int drive, int side) { d86f_t *dev = d86f[drive]; if ((dev->state != STATE_IDLE) && (dev->state != STATE_SECTOR_NOT_FOUND) && ((dev->state & 0xF8) != 0xE8)) { - if (! d86f_can_read_address(drive)) { - dev->id_find.sync_marks = dev->id_find.bits_obtained = dev->id_find.bytes_obtained = dev->error_condition = 0; - fdc_noidam(d86f_fdc); - dev->state = STATE_IDLE; - return; - } + if (!d86f_can_read_address(drive)) { + dev->id_find.sync_marks = dev->id_find.bits_obtained = dev->id_find.bytes_obtained = dev->error_condition = 0; + fdc_noidam(d86f_fdc); + dev->state = STATE_IDLE; + return; + } } - switch(dev->state) { - case STATE_0D_SPIN_TO_INDEX: - dev->sector_count = 0; - dev->datac = 5; - /*FALLTHROUGH*/ + switch (dev->state) { + case STATE_0D_SPIN_TO_INDEX: + dev->sector_count = 0; + dev->datac = 5; + fallthrough; - case STATE_02_SPIN_TO_INDEX: - dev->state++; - return; + case STATE_02_SPIN_TO_INDEX: + dev->state++; + return; - case STATE_02_FIND_ID: - if (! d86f_sector_is_present(drive, side, fdc_get_read_track_sector(d86f_fdc).id.c, fdc_get_read_track_sector(d86f_fdc).id.h, - fdc_get_read_track_sector(d86f_fdc).id.r, fdc_get_read_track_sector(d86f_fdc).id.n)) { - dev->id_find.sync_marks = dev->id_find.bits_obtained = dev->id_find.bytes_obtained = dev->error_condition = 0; - fdc_nosector(d86f_fdc); - dev->state = STATE_IDLE; - return; - } - dev->last_sector.id.c = fdc_get_read_track_sector(d86f_fdc).id.c; - dev->last_sector.id.h = fdc_get_read_track_sector(d86f_fdc).id.h; - dev->last_sector.id.r = fdc_get_read_track_sector(d86f_fdc).id.r; - dev->last_sector.id.n = fdc_get_read_track_sector(d86f_fdc).id.n; - d86f_handler[drive].set_sector(drive, side, dev->last_sector.id.c, dev->last_sector.id.h, dev->last_sector.id.r, dev->last_sector.id.n); - dev->turbo_pos = 0; - dev->state++; - return; + case STATE_02_FIND_ID: + if (!d86f_sector_is_present(drive, side, fdc_get_read_track_sector(d86f_fdc).id.c, fdc_get_read_track_sector(d86f_fdc).id.h, + fdc_get_read_track_sector(d86f_fdc).id.r, fdc_get_read_track_sector(d86f_fdc).id.n)) { + dev->id_find.sync_marks = dev->id_find.bits_obtained = dev->id_find.bytes_obtained = dev->error_condition = 0; + fdc_nosector(d86f_fdc); + dev->state = STATE_IDLE; + return; + } + dev->last_sector.id.c = fdc_get_read_track_sector(d86f_fdc).id.c; + dev->last_sector.id.h = fdc_get_read_track_sector(d86f_fdc).id.h; + dev->last_sector.id.r = fdc_get_read_track_sector(d86f_fdc).id.r; + dev->last_sector.id.n = fdc_get_read_track_sector(d86f_fdc).id.n; + d86f_handler[drive].set_sector(drive, side, dev->last_sector.id.c, dev->last_sector.id.h, dev->last_sector.id.r, dev->last_sector.id.n); + dev->turbo_pos = 0; + dev->state++; + return; - case STATE_05_FIND_ID: - case STATE_09_FIND_ID: - case STATE_06_FIND_ID: - case STATE_0C_FIND_ID: - case STATE_11_FIND_ID: - case STATE_16_FIND_ID: - if (! d86f_sector_is_present(drive, side, dev->req_sector.id.c, dev->req_sector.id.h, dev->req_sector.id.r, dev->req_sector.id.n)) { - dev->id_find.sync_marks = dev->id_find.bits_obtained = dev->id_find.bytes_obtained = dev->error_condition = 0; - fdc_nosector(d86f_fdc); - dev->state = STATE_IDLE; - return; - } else if (d86f_sector_flags(drive, side, dev->req_sector.id.c, dev->req_sector.id.h, dev->req_sector.id.r, dev->req_sector.id.n) & SECTOR_NO_ID) { - dev->id_find.sync_marks = dev->id_find.bits_obtained = dev->id_find.bytes_obtained = dev->error_condition = 0; - fdc_noidam(d86f_fdc); - dev->state = STATE_IDLE; - return; - } - dev->last_sector.id.c = dev->req_sector.id.c; - dev->last_sector.id.h = dev->req_sector.id.h; - dev->last_sector.id.r = dev->req_sector.id.r; - dev->last_sector.id.n = dev->req_sector.id.n; - d86f_handler[drive].set_sector(drive, side, dev->last_sector.id.c, dev->last_sector.id.h, dev->last_sector.id.r, dev->last_sector.id.n); - /*FALLTHROUGH*/ + case STATE_05_FIND_ID: + case STATE_09_FIND_ID: + case STATE_06_FIND_ID: + case STATE_0C_FIND_ID: + case STATE_11_FIND_ID: + case STATE_16_FIND_ID: + if (!d86f_sector_is_present(drive, side, dev->req_sector.id.c, dev->req_sector.id.h, dev->req_sector.id.r, dev->req_sector.id.n)) { + dev->id_find.sync_marks = dev->id_find.bits_obtained = dev->id_find.bytes_obtained = dev->error_condition = 0; + fdc_nosector(d86f_fdc); + dev->state = STATE_IDLE; + return; + } else if (d86f_sector_flags(drive, side, dev->req_sector.id.c, dev->req_sector.id.h, dev->req_sector.id.r, dev->req_sector.id.n) & SECTOR_NO_ID) { + dev->id_find.sync_marks = dev->id_find.bits_obtained = dev->id_find.bytes_obtained = dev->error_condition = 0; + fdc_noidam(d86f_fdc); + dev->state = STATE_IDLE; + return; + } + dev->last_sector.id.c = dev->req_sector.id.c; + dev->last_sector.id.h = dev->req_sector.id.h; + dev->last_sector.id.r = dev->req_sector.id.r; + dev->last_sector.id.n = dev->req_sector.id.n; + d86f_handler[drive].set_sector(drive, side, dev->last_sector.id.c, dev->last_sector.id.h, dev->last_sector.id.r, dev->last_sector.id.n); + fallthrough; - case STATE_0A_FIND_ID: - dev->turbo_pos = 0; - dev->state++; - return; + case STATE_0A_FIND_ID: + dev->turbo_pos = 0; + dev->state++; + return; - case STATE_0A_READ_ID: - dev->id_find.sync_marks = dev->id_find.bits_obtained = dev->id_find.bytes_obtained = dev->error_condition = 0; - fdc_sectorid(d86f_fdc, dev->last_sector.id.c, dev->last_sector.id.h, dev->last_sector.id.r, dev->last_sector.id.n, 0, 0); - dev->state = STATE_IDLE; - break; + case STATE_0A_READ_ID: + dev->id_find.sync_marks = dev->id_find.bits_obtained = dev->id_find.bytes_obtained = dev->error_condition = 0; + fdc_sectorid(d86f_fdc, dev->last_sector.id.c, dev->last_sector.id.h, dev->last_sector.id.r, dev->last_sector.id.n, 0, 0); + dev->state = STATE_IDLE; + break; - case STATE_02_READ_ID: - case STATE_05_READ_ID: - case STATE_09_READ_ID: - case STATE_06_READ_ID: - case STATE_0C_READ_ID: - case STATE_11_READ_ID: - case STATE_16_READ_ID: - dev->state++; - break; + case STATE_02_READ_ID: + case STATE_05_READ_ID: + case STATE_09_READ_ID: + case STATE_06_READ_ID: + case STATE_0C_READ_ID: + case STATE_11_READ_ID: + case STATE_16_READ_ID: + dev->state++; + break; - case STATE_02_FIND_DATA: - case STATE_06_FIND_DATA: - case STATE_11_FIND_DATA: - case STATE_16_FIND_DATA: - case STATE_05_FIND_DATA: - case STATE_09_FIND_DATA: - case STATE_0C_FIND_DATA: - dev->state++; - break; + case STATE_02_FIND_DATA: + case STATE_06_FIND_DATA: + case STATE_11_FIND_DATA: + case STATE_16_FIND_DATA: + case STATE_05_FIND_DATA: + case STATE_09_FIND_DATA: + case STATE_0C_FIND_DATA: + dev->state++; + break; - case STATE_02_READ_DATA: - case STATE_06_READ_DATA: - case STATE_0C_READ_DATA: - case STATE_11_SCAN_DATA: - case STATE_16_VERIFY_DATA: - d86f_turbo_read(drive, side); - break; + case STATE_02_READ_DATA: + case STATE_06_READ_DATA: + case STATE_0C_READ_DATA: + case STATE_11_SCAN_DATA: + case STATE_16_VERIFY_DATA: + d86f_turbo_read(drive, side); + break; - case STATE_05_WRITE_DATA: - case STATE_09_WRITE_DATA: - d86f_turbo_write(drive, side); - break; + case STATE_05_WRITE_DATA: + case STATE_09_WRITE_DATA: + d86f_turbo_write(drive, side); + break; - case STATE_0D_FORMAT_TRACK: - d86f_turbo_format(drive, side, (side && (d86f_get_sides(drive) != 2))); - return; + case STATE_0D_FORMAT_TRACK: + d86f_turbo_format(drive, side, (side && (d86f_get_sides(drive) != 2))); + return; - case STATE_IDLE: - case STATE_SECTOR_NOT_FOUND: - default: - break; + case STATE_IDLE: + case STATE_SECTOR_NOT_FOUND: + default: + break; } } - void d86f_poll(int drive) { d86f_t *dev = d86f[drive]; - int mfm, side; + int mfm; + int side; side = fdd_get_head(drive); - if (! fdd_is_double_sided(drive)) - side = 0; + if (!fdd_is_double_sided(drive)) + side = 0; mfm = fdc_is_mfm(d86f_fdc); if ((dev->state & 0xF8) == 0xE8) { - if (! d86f_can_format(drive)) - dev->state = STATE_SECTOR_NOT_FOUND; + if (!d86f_can_format(drive)) + dev->state = STATE_SECTOR_NOT_FOUND; } if (fdd_get_turbo(drive) && (dev->version == 0x0063)) { - d86f_turbo_poll(drive, side); - return; + d86f_turbo_poll(drive, side); + return; } if ((dev->state != STATE_IDLE) && (dev->state != STATE_SECTOR_NOT_FOUND) && ((dev->state & 0xF8) != 0xE8)) { - if (! d86f_can_read_address(drive)) - dev->state = STATE_SECTOR_NOT_FOUND; + if (!d86f_can_read_address(drive)) + dev->state = STATE_SECTOR_NOT_FOUND; } if ((dev->state != STATE_02_SPIN_TO_INDEX) && (dev->state != STATE_0D_SPIN_TO_INDEX)) - d86f_get_bit(drive, side ^ 1); + d86f_get_bit(drive, side ^ 1); - switch(dev->state) { - case STATE_02_SPIN_TO_INDEX: - case STATE_0D_SPIN_TO_INDEX: - d86f_spin_to_index(drive, side); - return; + switch (dev->state) { + case STATE_02_SPIN_TO_INDEX: + case STATE_0D_SPIN_TO_INDEX: + d86f_spin_to_index(drive, side); + return; - case STATE_02_FIND_ID: - case STATE_05_FIND_ID: - case STATE_09_FIND_ID: - case STATE_06_FIND_ID: - case STATE_0A_FIND_ID: - case STATE_0C_FIND_ID: - case STATE_11_FIND_ID: - case STATE_16_FIND_ID: - if (mfm) - d86f_find_address_mark_mfm(drive, side, &(dev->id_find), 0x5554, 0, 0, 0); - else - d86f_find_address_mark_fm(drive, side, &(dev->id_find), 0xF57E, 0, 0, 0); - break; + case STATE_02_FIND_ID: + case STATE_05_FIND_ID: + case STATE_09_FIND_ID: + case STATE_06_FIND_ID: + case STATE_0A_FIND_ID: + case STATE_0C_FIND_ID: + case STATE_11_FIND_ID: + case STATE_16_FIND_ID: + if (mfm) + d86f_find_address_mark_mfm(drive, side, &(dev->id_find), 0x5554, 0, 0, 0); + else + d86f_find_address_mark_fm(drive, side, &(dev->id_find), 0xF57E, 0, 0, 0); + break; - case STATE_0A_READ_ID: - case STATE_02_READ_ID: - d86f_read_sector_id(drive, side, 0); - break; + case STATE_0A_READ_ID: + case STATE_02_READ_ID: + d86f_read_sector_id(drive, side, 0); + break; - case STATE_05_READ_ID: - case STATE_09_READ_ID: - case STATE_06_READ_ID: - case STATE_0C_READ_ID: - case STATE_11_READ_ID: - case STATE_16_READ_ID: - d86f_read_sector_id(drive, side, 1); - break; + case STATE_05_READ_ID: + case STATE_09_READ_ID: + case STATE_06_READ_ID: + case STATE_0C_READ_ID: + case STATE_11_READ_ID: + case STATE_16_READ_ID: + d86f_read_sector_id(drive, side, 1); + break; - case STATE_02_FIND_DATA: - if (mfm) - d86f_find_address_mark_mfm(drive, side, &(dev->data_find), 0x5545, 0x554A, 0x5554, 2); - else - d86f_find_address_mark_fm(drive, side, &(dev->data_find), 0xF56F, 0xF56A, 0xF57E, 2); - break; + case STATE_02_FIND_DATA: + if (mfm) + d86f_find_address_mark_mfm(drive, side, &(dev->data_find), 0x5545, 0x554A, 0x5554, 2); + else + d86f_find_address_mark_fm(drive, side, &(dev->data_find), 0xF56F, 0xF56A, 0xF57E, 2); + break; - case STATE_06_FIND_DATA: - case STATE_11_FIND_DATA: - case STATE_16_FIND_DATA: - if (mfm) - d86f_find_address_mark_mfm(drive, side, &(dev->data_find), 0x5545, 0x554A, 0x5554, fdc_is_sk(d86f_fdc) | 2); - else - d86f_find_address_mark_fm(drive, side, &(dev->data_find), 0xF56F, 0xF56A, 0xF57E, fdc_is_sk(d86f_fdc) | 2); - break; + case STATE_06_FIND_DATA: + case STATE_11_FIND_DATA: + case STATE_16_FIND_DATA: + if (mfm) + d86f_find_address_mark_mfm(drive, side, &(dev->data_find), 0x5545, 0x554A, 0x5554, fdc_is_sk(d86f_fdc) | 2); + else + d86f_find_address_mark_fm(drive, side, &(dev->data_find), 0xF56F, 0xF56A, 0xF57E, fdc_is_sk(d86f_fdc) | 2); + break; - case STATE_05_FIND_DATA: - case STATE_09_FIND_DATA: - if (mfm) - d86f_write_find_address_mark_mfm(drive, side, &(dev->data_find)); - else - d86f_write_find_address_mark_fm(drive, side, &(dev->data_find)); - break; + case STATE_05_FIND_DATA: + case STATE_09_FIND_DATA: + if (mfm) + d86f_write_find_address_mark_mfm(drive, side, &(dev->data_find)); + else + d86f_write_find_address_mark_fm(drive, side, &(dev->data_find)); + break; - case STATE_0C_FIND_DATA: - if (mfm) - d86f_find_address_mark_mfm(drive, side, &(dev->data_find), 0x554A, 0x5545, 0x5554, fdc_is_sk(d86f_fdc) | 2); - else - d86f_find_address_mark_fm(drive, side, &(dev->data_find), 0xF56A, 0xF56F, 0xF57E, fdc_is_sk(d86f_fdc) | 2); - break; + case STATE_0C_FIND_DATA: + if (mfm) + d86f_find_address_mark_mfm(drive, side, &(dev->data_find), 0x554A, 0x5545, 0x5554, fdc_is_sk(d86f_fdc) | 2); + else + d86f_find_address_mark_fm(drive, side, &(dev->data_find), 0xF56A, 0xF56F, 0xF57E, fdc_is_sk(d86f_fdc) | 2); + break; - case STATE_02_READ_DATA: - case STATE_06_READ_DATA: - case STATE_0C_READ_DATA: - case STATE_11_SCAN_DATA: - case STATE_16_VERIFY_DATA: - d86f_read_sector_data(drive, side); - break; + case STATE_02_READ_DATA: + case STATE_06_READ_DATA: + case STATE_0C_READ_DATA: + case STATE_11_SCAN_DATA: + case STATE_16_VERIFY_DATA: + d86f_read_sector_data(drive, side); + break; - case STATE_05_WRITE_DATA: - if (mfm) - d86f_write_sector_data(drive, side, mfm, 0x5545); - else - d86f_write_sector_data(drive, side, mfm, 0xF56F); - break; + case STATE_05_WRITE_DATA: + if (mfm) + d86f_write_sector_data(drive, side, mfm, 0x5545); + else + d86f_write_sector_data(drive, side, mfm, 0xF56F); + break; - case STATE_09_WRITE_DATA: - if (mfm) - d86f_write_sector_data(drive, side, mfm, 0x554A); - else - d86f_write_sector_data(drive, side, mfm, 0xF56A); - break; + case STATE_09_WRITE_DATA: + if (mfm) + d86f_write_sector_data(drive, side, mfm, 0x554A); + else + d86f_write_sector_data(drive, side, mfm, 0xF56A); + break; - case STATE_0D_FORMAT_TRACK: - if (! (dev->track_pos & 15)) - d86f_format_track(drive, side, (!side || (d86f_get_sides(drive) == 2)) && (dev->version == D86FVER)); - return; + case STATE_0D_FORMAT_TRACK: + if (!(dev->track_pos & 15)) + d86f_format_track(drive, side, (!side || (d86f_get_sides(drive) == 2)) && (dev->version == D86FVER)); + return; - case STATE_IDLE: - case STATE_SECTOR_NOT_FOUND: - default: - d86f_get_bit(drive, side); - break; + case STATE_IDLE: + case STATE_SECTOR_NOT_FOUND: + default: + d86f_get_bit(drive, side); + break; } d86f_advance_bit(drive, side); if (d86f_wrong_densel(drive) && (dev->state != STATE_IDLE)) { - dev->state = STATE_IDLE; - fdc_noidam(d86f_fdc); - return; + dev->state = STATE_IDLE; + fdc_noidam(d86f_fdc); + return; } if ((dev->index_count == 2) && (dev->state != STATE_IDLE)) { - switch(dev->state) { - case STATE_0A_FIND_ID: - case STATE_SECTOR_NOT_FOUND: - dev->state = STATE_IDLE; - fdc_noidam(d86f_fdc); - break; + switch (dev->state) { + case STATE_0A_FIND_ID: + case STATE_SECTOR_NOT_FOUND: + dev->state = STATE_IDLE; + fdc_noidam(d86f_fdc); + break; - case STATE_02_FIND_DATA: - case STATE_06_FIND_DATA: - case STATE_11_FIND_DATA: - case STATE_16_FIND_DATA: - case STATE_05_FIND_DATA: - case STATE_09_FIND_DATA: - case STATE_0C_FIND_DATA: - dev->state = STATE_IDLE; - fdc_nodataam(d86f_fdc); - break; + case STATE_02_FIND_DATA: + case STATE_06_FIND_DATA: + case STATE_11_FIND_DATA: + case STATE_16_FIND_DATA: + case STATE_05_FIND_DATA: + case STATE_09_FIND_DATA: + case STATE_0C_FIND_DATA: + dev->state = STATE_IDLE; + fdc_nodataam(d86f_fdc); + break; - case STATE_02_SPIN_TO_INDEX: - case STATE_02_READ_DATA: - case STATE_05_WRITE_DATA: - case STATE_06_READ_DATA: - case STATE_09_WRITE_DATA: - case STATE_0C_READ_DATA: - case STATE_0D_SPIN_TO_INDEX: - case STATE_0D_FORMAT_TRACK: - case STATE_11_SCAN_DATA: - case STATE_16_VERIFY_DATA: - /* In these states, we should *NEVER* care about how many index pulses there have been. */ - break; + case STATE_02_SPIN_TO_INDEX: + case STATE_02_READ_DATA: + case STATE_05_WRITE_DATA: + case STATE_06_READ_DATA: + case STATE_09_WRITE_DATA: + case STATE_0C_READ_DATA: + case STATE_0D_SPIN_TO_INDEX: + case STATE_0D_FORMAT_TRACK: + case STATE_11_SCAN_DATA: + case STATE_16_VERIFY_DATA: + /* In these states, we should *NEVER* care about how many index pulses there have been. */ + break; - default: - dev->state = STATE_IDLE; - if (dev->id_found) { - if (dev->error_condition & 0x18) { - if ((dev->error_condition & 0x18) == 0x08) - fdc_badcylinder(d86f_fdc); - if ((dev->error_condition & 0x10) == 0x10) - fdc_wrongcylinder(d86f_fdc); - else - fdc_nosector(d86f_fdc); - } else - fdc_nosector(d86f_fdc); - } else - fdc_noidam(d86f_fdc); - break; - } + default: + dev->state = STATE_IDLE; + if (dev->id_found) { + if (dev->error_condition & 0x18) { + if ((dev->error_condition & 0x18) == 0x08) + fdc_badcylinder(d86f_fdc); + if ((dev->error_condition & 0x10) == 0x10) + fdc_wrongcylinder(d86f_fdc); + else + fdc_nosector(d86f_fdc); + } else + fdc_nosector(d86f_fdc); + } else + fdc_noidam(d86f_fdc); + break; + } } } - void d86f_reset_index_hole_pos(int drive, int side) { @@ -2595,102 +2593,100 @@ d86f_reset_index_hole_pos(int drive, int side) dev->index_hole_pos[side] = 0; } - uint16_t d86f_prepare_pretrack(int drive, int side, int iso) { - d86f_t *dev = d86f[drive]; - uint16_t i, pos; - int mfm; - int real_gap0_len; - int sync_len; - int real_gap1_len; + d86f_t *dev = d86f[drive]; + uint16_t pos; + int mfm; + int real_gap0_len; + int sync_len; + int real_gap1_len; uint16_t gap_fill; uint32_t raw_size; - uint16_t iam_fm = 0xFAF7; + uint16_t iam_fm = 0xFAF7; uint16_t iam_mfm = 0x5255; - mfm = d86f_is_mfm(drive); + mfm = d86f_is_mfm(drive); real_gap0_len = mfm ? 80 : 40; - sync_len = mfm ? 12 : 6; + sync_len = mfm ? 12 : 6; real_gap1_len = mfm ? 50 : 26; - gap_fill = mfm ? 0x4E : 0xFF; - raw_size = d86f_handler[drive].get_raw_size(drive, side); + gap_fill = mfm ? 0x4E : 0xFF; + raw_size = d86f_handler[drive].get_raw_size(drive, side); if (raw_size & 15) - raw_size = (raw_size >> 4) + 1; + raw_size = (raw_size >> 4) + 1; else - raw_size = (raw_size >> 4); + raw_size = (raw_size >> 4); dev->index_hole_pos[side] = 0; d86f_destroy_linked_lists(drive, side); - for (i = 0; i < raw_size; i++) - d86f_write_direct_common(drive, side, gap_fill, 0, i); + for (uint32_t i = 0; i < raw_size; i++) + d86f_write_direct_common(drive, side, gap_fill, 0, i); pos = 0; - if (! iso) { - for (i = 0; i < real_gap0_len; i++) { - d86f_write_direct_common(drive, side, gap_fill, 0, pos); - pos = (pos + 1) % raw_size; - } - for (i = 0; i < sync_len; i++) { - d86f_write_direct_common(drive, side, 0, 0, pos); - pos = (pos + 1) % raw_size; - } - if (mfm) { - for (i = 0; i < 3; i++) { - d86f_write_direct_common(drive, side, 0x2452, 1, pos); - pos = (pos + 1) % raw_size; - } - } + if (!iso) { + for (int i = 0; i < real_gap0_len; i++) { + d86f_write_direct_common(drive, side, gap_fill, 0, pos); + pos = (pos + 1) % raw_size; + } + for (int i = 0; i < sync_len; i++) { + d86f_write_direct_common(drive, side, 0, 0, pos); + pos = (pos + 1) % raw_size; + } + if (mfm) { + for (uint8_t i = 0; i < 3; i++) { + d86f_write_direct_common(drive, side, 0x2452, 1, pos); + pos = (pos + 1) % raw_size; + } + } - d86f_write_direct_common(drive, side, mfm ? iam_mfm : iam_fm, 1, pos); - pos = (pos + 1) % raw_size; + d86f_write_direct_common(drive, side, mfm ? iam_mfm : iam_fm, 1, pos); + pos = (pos + 1) % raw_size; } - for (i = 0; i < real_gap1_len; i++) { - d86f_write_direct_common(drive, side, gap_fill, 0, pos); - pos = (pos + 1) % raw_size; + for (int i = 0; i < real_gap1_len; i++) { + d86f_write_direct_common(drive, side, gap_fill, 0, pos); + pos = (pos + 1) % raw_size; } return pos; } - uint16_t d86f_prepare_sector(int drive, int side, int prev_pos, uint8_t *id_buf, uint8_t *data_buf, int data_len, int gap2, int gap3, int flags) { - d86f_t *dev = d86f[drive]; - uint16_t pos; - int i; + d86f_t *dev = d86f[drive]; + uint16_t pos; + int i; sector_t *s; - int real_gap2_len = gap2; - int real_gap3_len = gap3; - int mfm; - int sync_len; + int real_gap2_len = gap2; + int real_gap3_len = gap3; + int mfm; + int sync_len; uint16_t gap_fill; uint32_t raw_size; - uint16_t idam_fm = 0x7EF5; - uint16_t dataam_fm = 0x6FF5; - uint16_t datadam_fm = 0x6AF5; - uint16_t idam_mfm = 0x5455; - uint16_t dataam_mfm = 0x4555; + uint16_t idam_fm = 0x7EF5; + uint16_t dataam_fm = 0x6FF5; + uint16_t datadam_fm = 0x6AF5; + uint16_t idam_mfm = 0x5455; + uint16_t dataam_mfm = 0x4555; uint16_t datadam_mfm = 0x4A55; if (fdd_get_turbo(drive) && (dev->version == 0x0063)) { - s = (sector_t *) malloc(sizeof(sector_t)); - memset(s, 0, sizeof(sector_t)); - s->c = id_buf[0]; - s->h = id_buf[1]; - s->r = id_buf[2]; - s->n = id_buf[3]; - s->flags = flags; - if (dev->last_side_sector[side]) - s->prev = dev->last_side_sector[side]; - dev->last_side_sector[side] = s; + s = (sector_t *) malloc(sizeof(sector_t)); + memset(s, 0, sizeof(sector_t)); + s->c = id_buf[0]; + s->h = id_buf[1]; + s->r = id_buf[2]; + s->n = id_buf[3]; + s->flags = flags; + if (dev->last_side_sector[side]) + s->prev = dev->last_side_sector[side]; + dev->last_side_sector[side] = s; } mfm = d86f_is_mfm(drive); @@ -2698,85 +2694,84 @@ d86f_prepare_sector(int drive, int side, int prev_pos, uint8_t *id_buf, uint8_t gap_fill = mfm ? 0x4E : 0xFF; raw_size = d86f_handler[drive].get_raw_size(drive, side); if (raw_size & 15) - raw_size = (raw_size >> 4) + 1; + raw_size = (raw_size >> 4) + 1; else - raw_size = (raw_size >> 4); + raw_size = (raw_size >> 4); pos = prev_pos; sync_len = mfm ? 12 : 6; if (!(flags & SECTOR_NO_ID)) { - for (i = 0; i < sync_len; i++) { - d86f_write_direct_common(drive, side, 0, 0, pos); - pos = (pos + 1) % raw_size; - } + for (i = 0; i < sync_len; i++) { + d86f_write_direct_common(drive, side, 0, 0, pos); + pos = (pos + 1) % raw_size; + } - dev->calc_crc.word = 0xffff; - if (mfm) { - for (i = 0; i < 3; i++) { - d86f_write_direct_common(drive, side, 0x8944, 1, pos); - pos = (pos + 1) % raw_size; - d86f_calccrc(dev, 0xA1); - } - } - d86f_write_direct_common(drive, side, mfm ? idam_mfm : idam_fm, 1, pos); - pos = (pos + 1) % raw_size; - d86f_calccrc(dev, 0xFE); - for (i = 0; i < 4; i++) { - d86f_write_direct_common(drive, side, id_buf[i], 0, pos); - pos = (pos + 1) % raw_size; - d86f_calccrc(dev, id_buf[i]); - } - for (i = 1; i >= 0; i--) { - d86f_write_direct_common(drive, side, dev->calc_crc.bytes[i], 0, pos); - pos = (pos + 1) % raw_size; - } - for (i = 0; i < real_gap2_len; i++) { - d86f_write_direct_common(drive, side, gap_fill, 0, pos); - pos = (pos + 1) % raw_size; - } + dev->calc_crc.word = 0xffff; + if (mfm) { + for (i = 0; i < 3; i++) { + d86f_write_direct_common(drive, side, 0x8944, 1, pos); + pos = (pos + 1) % raw_size; + d86f_calccrc(dev, 0xA1); + } + } + d86f_write_direct_common(drive, side, mfm ? idam_mfm : idam_fm, 1, pos); + pos = (pos + 1) % raw_size; + d86f_calccrc(dev, 0xFE); + for (i = 0; i < 4; i++) { + d86f_write_direct_common(drive, side, id_buf[i], 0, pos); + pos = (pos + 1) % raw_size; + d86f_calccrc(dev, id_buf[i]); + } + for (i = 1; i >= 0; i--) { + d86f_write_direct_common(drive, side, dev->calc_crc.bytes[i], 0, pos); + pos = (pos + 1) % raw_size; + } + for (i = 0; i < real_gap2_len; i++) { + d86f_write_direct_common(drive, side, gap_fill, 0, pos); + pos = (pos + 1) % raw_size; + } } if (!(flags & SECTOR_NO_DATA)) { - for (i = 0; i < sync_len; i++) { - d86f_write_direct_common(drive, side, 0, 0, pos); - pos = (pos + 1) % raw_size; - } - dev->calc_crc.word = 0xffff; - if (mfm) { - for (i = 0; i < 3; i++) { - d86f_write_direct_common(drive, side, 0x8944, 1, pos); - pos = (pos + 1) % raw_size; - d86f_calccrc(dev, 0xA1); - } - } - d86f_write_direct_common(drive, side, mfm ? ((flags & SECTOR_DELETED_DATA) ? datadam_mfm : dataam_mfm) : ((flags & SECTOR_DELETED_DATA) ? datadam_fm : dataam_fm), 1, pos); - pos = (pos + 1) % raw_size; - d86f_calccrc(dev, (flags & SECTOR_DELETED_DATA) ? 0xF8 : 0xFB); - if (data_len > 0) { - for (i = 0; i < data_len; i++) { - d86f_write_direct_common(drive, side, data_buf[i], 0, pos); - pos = (pos + 1) % raw_size; - d86f_calccrc(dev, data_buf[i]); - } - if (!(flags & SECTOR_CRC_ERROR)) { - for (i = 1; i >= 0; i--) { - d86f_write_direct_common(drive, side, dev->calc_crc.bytes[i], 0, pos); - pos = (pos + 1) % raw_size; - } - } - for (i = 0; i < real_gap3_len; i++) { - d86f_write_direct_common(drive, side, gap_fill, 0, pos); - pos = (pos + 1) % raw_size; - } - } + for (i = 0; i < sync_len; i++) { + d86f_write_direct_common(drive, side, 0, 0, pos); + pos = (pos + 1) % raw_size; + } + dev->calc_crc.word = 0xffff; + if (mfm) { + for (i = 0; i < 3; i++) { + d86f_write_direct_common(drive, side, 0x8944, 1, pos); + pos = (pos + 1) % raw_size; + d86f_calccrc(dev, 0xA1); + } + } + d86f_write_direct_common(drive, side, mfm ? ((flags & SECTOR_DELETED_DATA) ? datadam_mfm : dataam_mfm) : ((flags & SECTOR_DELETED_DATA) ? datadam_fm : dataam_fm), 1, pos); + pos = (pos + 1) % raw_size; + d86f_calccrc(dev, (flags & SECTOR_DELETED_DATA) ? 0xF8 : 0xFB); + if (data_len > 0) { + for (i = 0; i < data_len; i++) { + d86f_write_direct_common(drive, side, data_buf[i], 0, pos); + pos = (pos + 1) % raw_size; + d86f_calccrc(dev, data_buf[i]); + } + if (!(flags & SECTOR_CRC_ERROR)) { + for (i = 1; i >= 0; i--) { + d86f_write_direct_common(drive, side, dev->calc_crc.bytes[i], 0, pos); + pos = (pos + 1) % raw_size; + } + } + for (i = 0; i < real_gap3_len; i++) { + d86f_write_direct_common(drive, side, gap_fill, 0, pos); + pos = (pos + 1) % raw_size; + } + } } return pos; } - /* * Note on handling of tracks on thick track drives: * @@ -2784,14 +2779,14 @@ d86f_prepare_sector(int drive, int side, int prev_pos, uint8_t *id_buf, uint8_t * ((track << 1) + 1); * * - Any bits that differ are treated as thus: - * - Both are regular but contents differ -> Output is fuzzy; - * - One is regular and one is fuzzy -> Output is fuzzy; - * - Both are fuzzy -> Output is fuzzy; - * - Both are physical holes -> Output is a physical hole; - * - One is regular and one is a physical hole -> Output is fuzzy, - * the hole half is handled appropriately on writeback; - * - One is fuzzy and one is a physical hole -> Output is fuzzy, - * the hole half is handled appropriately on writeback; + * - Both are regular but contents differ -> Output is fuzzy; + * - One is regular and one is fuzzy -> Output is fuzzy; + * - Both are fuzzy -> Output is fuzzy; + * - Both are physical holes -> Output is a physical hole; + * - One is regular and one is a physical hole -> Output is fuzzy, + * the hole half is handled appropriately on writeback; + * - One is fuzzy and one is a physical hole -> Output is fuzzy, + * the hole half is handled appropriately on writeback; * - On write back, apart from the above notes, the final two tracks * are written; * - Destination ALWAYS has surface data even if the image does not. @@ -2801,248 +2796,248 @@ d86f_prepare_sector(int drive, int side, int prev_pos, uint8_t *id_buf, uint8_t void d86f_construct_encoded_buffer(int drive, int side) { - d86f_t *dev = d86f[drive]; - uint32_t i = 0; + d86f_t *dev = d86f[drive]; /* *_fuzm are fuzzy bit masks, *_holm are hole masks, dst_neim are masks is mask for bits that are neither fuzzy nor holes in both, and src1_d and src2_d are filtered source data. */ - uint16_t src1_fuzm, src2_fuzm, dst_fuzm, src1_holm, src2_holm, dst_holm, dst_neim, src1_d, src2_d; - uint32_t len; - uint16_t *dst = dev->track_encoded_data[side]; - uint16_t *dst_s = dev->track_surface_data[side]; - uint16_t *src1 = dev->thin_track_encoded_data[0][side]; - uint16_t *src1_s = dev->thin_track_surface_data[0][side]; - uint16_t *src2 = dev->thin_track_encoded_data[1][side]; - uint16_t *src2_s = dev->thin_track_surface_data[1][side]; - len = d86f_get_array_size(drive, side, 1); + uint16_t src1_fuzm; + uint16_t src2_fuzm; + uint16_t dst_fuzm; + uint16_t src1_holm; + uint16_t src2_holm; + uint16_t dst_holm; + uint16_t dst_neim; + uint16_t src1_d; + uint16_t src2_d; + uint32_t len; + uint16_t *dst = dev->track_encoded_data[side]; + uint16_t *dst_s = dev->track_surface_data[side]; + const uint16_t *src1 = dev->thin_track_encoded_data[0][side]; + const uint16_t *src1_s = dev->thin_track_surface_data[0][side]; + const uint16_t *src2 = dev->thin_track_encoded_data[1][side]; + const uint16_t *src2_s = dev->thin_track_surface_data[1][side]; + len = d86f_get_array_size(drive, side, 1); - for (i = 0; i < len; i++) { - /* The two bits differ. */ - if (d86f_has_surface_desc(drive)) { - /* Source image has surface description data, so we have some more handling to do. */ - src1_fuzm = src1[i] & src1_s[i]; - src2_fuzm = src2[i] & src2_s[i]; - dst_fuzm = src1_fuzm | src2_fuzm; /* The bits that remain set are fuzzy in either one or - the other or both. */ - src1_holm = src1[i] | (src1_s[i] ^ 0xffff); - src2_holm = src2[i] | (src2_s[i] ^ 0xffff); - dst_holm = (src1_holm & src2_holm) ^ 0xffff; /* The bits that remain set are holes in both. */ - dst_neim = (dst_fuzm | dst_holm) ^ 0xffff; /* The bits that remain set are those that are neither - fuzzy nor are holes in both. */ - src1_d = src1[i] & dst_neim; - src2_d = src2[i] & dst_neim; + for (uint32_t i = 0; i < len; i++) { + /* The two bits differ. */ + if (d86f_has_surface_desc(drive)) { + /* Source image has surface description data, so we have some more handling to do. */ + src1_fuzm = src1[i] & src1_s[i]; + src2_fuzm = src2[i] & src2_s[i]; + dst_fuzm = src1_fuzm | src2_fuzm; /* The bits that remain set are fuzzy in either one or + the other or both. */ + src1_holm = src1[i] | (src1_s[i] ^ 0xffff); + src2_holm = src2[i] | (src2_s[i] ^ 0xffff); + dst_holm = (src1_holm & src2_holm) ^ 0xffff; /* The bits that remain set are holes in both. */ + dst_neim = (dst_fuzm | dst_holm) ^ 0xffff; /* The bits that remain set are those that are neither + fuzzy nor are holes in both. */ + src1_d = src1[i] & dst_neim; + src2_d = src2[i] & dst_neim; - dst_s[i] = (dst_neim ^ 0xffff); /* The set bits are those that are either fuzzy or are - holes in both. */ - dst[i] = (src1_d | src2_d); /* Initial data is remaining data from Source 1 and - Source 2. */ - dst[i] |= dst_fuzm; /* Add to it the fuzzy bytes (holes have surface bit set - but data bit clear). */ - } else { - /* No surface data, the handling is much simpler - a simple OR. */ - dst[i] = src1[i] | src2[i]; - dst_s[i] = 0; - } + dst_s[i] = (dst_neim ^ 0xffff); /* The set bits are those that are either fuzzy or are + holes in both. */ + dst[i] = (src1_d | src2_d); /* Initial data is remaining data from Source 1 and + Source 2. */ + dst[i] |= dst_fuzm; /* Add to it the fuzzy bytes (holes have surface bit set + but data bit clear). */ + } else { + /* No surface data, the handling is much simpler - a simple OR. */ + dst[i] = src1[i] | src2[i]; + dst_s[i] = 0; + } } } - /* Decomposition is easier since we at most have to care about the holes. */ void d86f_decompose_encoded_buffer(int drive, int side) { - d86f_t *dev = d86f[drive]; - uint32_t i = 0; - uint16_t temp, temp2; - uint32_t len; - uint16_t *dst = dev->track_encoded_data[side]; - uint16_t *src1 = dev->thin_track_encoded_data[0][side]; - uint16_t *src1_s = dev->thin_track_surface_data[0][side]; - uint16_t *src2 = dev->thin_track_encoded_data[1][side]; - uint16_t *src2_s = dev->thin_track_surface_data[1][side]; - dst = d86f_handler[drive].encoded_data(drive, side); - len = d86f_get_array_size(drive, side, 1); + d86f_t *dev = d86f[drive]; + uint16_t temp; + uint16_t temp2; + uint32_t len; + const uint16_t *dst = dev->track_encoded_data[side]; + uint16_t *src1 = dev->thin_track_encoded_data[0][side]; + uint16_t *src1_s = dev->thin_track_surface_data[0][side]; + uint16_t *src2 = dev->thin_track_encoded_data[1][side]; + uint16_t *src2_s = dev->thin_track_surface_data[1][side]; + dst = d86f_handler[drive].encoded_data(drive, side); + len = d86f_get_array_size(drive, side, 1); - for (i = 0; i < len; i++) { - if (d86f_has_surface_desc(drive)) { - /* Source image has surface description data, so we have some more handling to do. - We need hole masks for both buffers. Holes have data bit clear and surface bit set. */ - temp = src1[i] & (src1_s[i] ^ 0xffff); - temp2 = src2[i] & (src2_s[i] ^ 0xffff); - src1[i] = dst[i] & temp; - src1_s[i] = temp ^ 0xffff; - src2[i] = dst[i] & temp2; - src2_s[i] = temp2 ^ 0xffff; - } else { - src1[i] = src2[i] = dst[i]; - } + for (uint32_t i = 0; i < len; i++) { + if (d86f_has_surface_desc(drive)) { + /* Source image has surface description data, so we have some more handling to do. + We need hole masks for both buffers. Holes have data bit clear and surface bit set. */ + temp = src1[i] & (src1_s[i] ^ 0xffff); + temp2 = src2[i] & (src2_s[i] ^ 0xffff); + src1[i] = dst[i] & temp; + src1_s[i] = temp ^ 0xffff; + src2[i] = dst[i] & temp2; + src2_s[i] = temp2 ^ 0xffff; + } else { + src1[i] = src2[i] = dst[i]; + } } } - int d86f_track_header_size(int drive) { int temp = 6; if (d86f_has_extra_bit_cells(drive)) - temp += 4; + temp += 4; return temp; } - void d86f_read_track(int drive, int track, int thin_track, int side, uint16_t *da, uint16_t *sa) { - d86f_t *dev = d86f[drive]; - int logical_track = 0; - int array_size = 0; + d86f_t *dev = d86f[drive]; + int logical_track = 0; + int array_size = 0; if (d86f_get_sides(drive) == 2) - logical_track = ((track + thin_track) << 1) + side; - else - logical_track = track + thin_track; + logical_track = ((track + thin_track) << 1) + side; + else + logical_track = track + thin_track; if (dev->track_offset[logical_track]) { - if (! thin_track) { - if (fseek(dev->f, dev->track_offset[logical_track], SEEK_SET) == -1) - fatal("d86f_read_track(): Error seeking to offset dev->track_offset[logical_track]\n"); - if (fread(&(dev->side_flags[side]), 1, 2, dev->f) != 2) - fatal("d86f_read_track(): Error reading side flags\n"); - if (d86f_has_extra_bit_cells(drive)) { - if (fread(&(dev->extra_bit_cells[side]), 1, 4, dev->f) != 4) - fatal("d86f_read_track(): Error reading number of extra bit cells\n"); - /* If RPM shift is 0% and direction is 1, do not adjust extra bit cells, - as that is the whole track length. */ - if (d86f_get_rpm_mode(drive) || !d86f_get_speed_shift_dir(drive)) { - if (dev->extra_bit_cells[side] < -32768) - dev->extra_bit_cells[side] = -32768; - if (dev->extra_bit_cells[side] > 32768) - dev->extra_bit_cells[side] = 32768; - } - } else - dev->extra_bit_cells[side] = 0; - fread(&(dev->index_hole_pos[side]), 4, 1, dev->f); - } else - fseek(dev->f, dev->track_offset[logical_track] + d86f_track_header_size(drive), SEEK_SET); - array_size = d86f_get_array_size(drive, side, 0); - fread(da, 1, array_size, dev->f); - if (d86f_has_surface_desc(drive)) - fread(sa, 1, array_size, dev->f); + if (!thin_track) { + if (fseek(dev->fp, dev->track_offset[logical_track], SEEK_SET) == -1) + fatal("d86f_read_track(): Error seeking to offset dev->track_offset[logical_track]\n"); + if (fread(&(dev->side_flags[side]), 1, 2, dev->fp) != 2) + fatal("d86f_read_track(): Error reading side flags\n"); + if (d86f_has_extra_bit_cells(drive)) { + if (fread(&(dev->extra_bit_cells[side]), 1, 4, dev->fp) != 4) + fatal("d86f_read_track(): Error reading number of extra bit cells\n"); + /* If RPM shift is 0% and direction is 1, do not adjust extra bit cells, + as that is the whole track length. */ + if (d86f_get_rpm_mode(drive) || !d86f_get_speed_shift_dir(drive)) { + if (dev->extra_bit_cells[side] < -32768) + dev->extra_bit_cells[side] = -32768; + if (dev->extra_bit_cells[side] > 32768) + dev->extra_bit_cells[side] = 32768; + } + } else + dev->extra_bit_cells[side] = 0; + (void) !fread(&(dev->index_hole_pos[side]), 4, 1, dev->fp); + } else + fseek(dev->fp, dev->track_offset[logical_track] + d86f_track_header_size(drive), SEEK_SET); + array_size = d86f_get_array_size(drive, side, 0); + (void) !fread(da, 1, array_size, dev->fp); + if (d86f_has_surface_desc(drive)) + (void) !fread(sa, 1, array_size, dev->fp); } else { - if (! thin_track) { - switch((dev->disk_flags >> 1) & 3) { - case 0: - default: - dev->side_flags[side] = 0x0A; - break; + if (!thin_track) { + switch ((dev->disk_flags >> 1) & 3) { + default: + case 0: + dev->side_flags[side] = 0x0A; + break; - case 1: - dev->side_flags[side] = 0x00; - break; + case 1: + dev->side_flags[side] = 0x00; + break; - case 2: - case 3: - dev->side_flags[side] = 0x03; - break; - } - dev->extra_bit_cells[side] = 0; - } + case 2: + case 3: + dev->side_flags[side] = 0x03; + break; + } + dev->extra_bit_cells[side] = 0; + } } } - void d86f_zero_track(int drive) { d86f_t *dev = d86f[drive]; - int sides, side; + int sides; sides = d86f_get_sides(drive); - for (side = 0; side < sides; side++) { - if (d86f_has_surface_desc(drive)) - memset(dev->track_surface_data[side], 0, 106096); - memset(dev->track_encoded_data[side], 0, 106096); + for (int side = 0; side < sides; side++) { + if (d86f_has_surface_desc(drive)) + memset(dev->track_surface_data[side], 0, 106096); + memset(dev->track_encoded_data[side], 0, 106096); } } - void d86f_seek(int drive, int track) { d86f_t *dev = d86f[drive]; - int sides; - int side, thin_track; + int sides; + int side; + int thin_track; sides = d86f_get_sides(drive); /* If the drive has thick tracks, shift the track number by 1. */ - if (! fdd_doublestep_40(drive)) { - track <<= 1; + if (!fdd_doublestep_40(drive)) { + track <<= 1; - for (thin_track = 0; thin_track < sides; thin_track++) { - for (side = 0; side < sides; side++) { - if (d86f_has_surface_desc(drive)) - memset(dev->thin_track_surface_data[thin_track][side], 0, 106096); - memset(dev->thin_track_encoded_data[thin_track][side], 0, 106096); - } - } + for (thin_track = 0; thin_track < sides; thin_track++) { + for (side = 0; side < sides; side++) { + if (d86f_has_surface_desc(drive)) + memset(dev->thin_track_surface_data[thin_track][side], 0, 106096); + memset(dev->thin_track_encoded_data[thin_track][side], 0, 106096); + } + } } d86f_zero_track(drive); dev->cur_track = track; - if (! fdd_doublestep_40(drive)) { - for (side = 0; side < sides; side++) { - for (thin_track = 0; thin_track < 2; thin_track++) - d86f_read_track(drive, track, thin_track, side, dev->thin_track_encoded_data[thin_track][side], dev->thin_track_surface_data[thin_track][side]); + if (!fdd_doublestep_40(drive)) { + for (side = 0; side < sides; side++) { + for (thin_track = 0; thin_track < 2; thin_track++) + d86f_read_track(drive, track, thin_track, side, dev->thin_track_encoded_data[thin_track][side], dev->thin_track_surface_data[thin_track][side]); - d86f_construct_encoded_buffer(drive, side); - } + d86f_construct_encoded_buffer(drive, side); + } } else { - for (side = 0; side < sides; side++) - d86f_read_track(drive, track, 0, side, dev->track_encoded_data[side], dev->track_surface_data[side]); + for (side = 0; side < sides; side++) + d86f_read_track(drive, track, 0, side, dev->track_encoded_data[side], dev->track_surface_data[side]); } dev->state = STATE_IDLE; } - void -d86f_write_track(int drive, FILE **f, int side, uint16_t *da0, uint16_t *sa0) +d86f_write_track(int drive, FILE **fp, int side, uint16_t *da0, uint16_t *sa0) { - uint32_t array_size = d86f_get_array_size(drive, side, 0); - uint16_t side_flags = d86f_handler[drive].side_flags(drive); + uint32_t array_size = d86f_get_array_size(drive, side, 0); + uint16_t side_flags = d86f_handler[drive].side_flags(drive); uint32_t extra_bit_cells = d86f_handler[drive].extra_bit_cells(drive, side); - uint32_t index_hole_pos = d86f_handler[drive].index_hole_pos(drive, side); + uint32_t index_hole_pos = d86f_handler[drive].index_hole_pos(drive, side); - fwrite(&side_flags, 1, 2, *f); + fwrite(&side_flags, 1, 2, *fp); if (d86f_has_extra_bit_cells(drive)) - fwrite(&extra_bit_cells, 1, 4, *f); + fwrite(&extra_bit_cells, 1, 4, *fp); - fwrite(&index_hole_pos, 1, 4, *f); + fwrite(&index_hole_pos, 1, 4, *fp); - fwrite(da0, 1, array_size, *f); + fwrite(da0, 1, array_size, *fp); if (d86f_has_surface_desc(drive)) - fwrite(sa0, 1, array_size, *f); + fwrite(sa0, 1, array_size, *fp); } - int d86f_get_track_table_size(int drive) { int temp = 2048; if (d86f_get_sides(drive) == 1) - temp >>= 1; + temp >>= 1; return temp; } - void d86f_set_cur_track(int drive, int track) { @@ -3051,146 +3046,145 @@ d86f_set_cur_track(int drive, int track) dev->cur_track = track; } - void -d86f_write_tracks(int drive, FILE **f, uint32_t *track_table) +d86f_write_tracks(int drive, FILE **fp, uint32_t *track_table) { - d86f_t *dev = d86f[drive]; - int sides, fdd_side; - int side, thin_track; - int logical_track = 0; + d86f_t *dev = d86f[drive]; + int sides; + int fdd_side; + int side; + int logical_track = 0; uint32_t *tbl; - tbl = dev->track_offset; + tbl = dev->track_offset; fdd_side = fdd_get_head(drive); - sides = d86f_get_sides(drive); + sides = d86f_get_sides(drive); if (track_table != NULL) - tbl = track_table; + tbl = track_table; if (!fdd_doublestep_40(drive)) { - d86f_decompose_encoded_buffer(drive, 0); - if (sides == 2) - d86f_decompose_encoded_buffer(drive, 1); + d86f_decompose_encoded_buffer(drive, 0); + if (sides == 2) + d86f_decompose_encoded_buffer(drive, 1); - for (thin_track = 0; thin_track < 2; thin_track++) { - for (side = 0; side < sides; side++) { - fdd_set_head(drive, side); + for (uint8_t thin_track = 0; thin_track < 2; thin_track++) { + for (side = 0; side < sides; side++) { + fdd_set_head(drive, side); - if (sides == 2) - logical_track = ((dev->cur_track + thin_track) << 1) + side; - else - logical_track = dev->cur_track + thin_track; + if (sides == 2) + logical_track = ((dev->cur_track + thin_track) << 1) + side; + else + logical_track = dev->cur_track + thin_track; - if (track_table && !tbl[logical_track]) { - fseek(*f, 0, SEEK_END); - tbl[logical_track] = ftell(*f); - } + if (track_table && !tbl[logical_track]) { + fseek(*fp, 0, SEEK_END); + tbl[logical_track] = ftell(*fp); + } - if (tbl[logical_track]) { - fseek(*f, tbl[logical_track], SEEK_SET); - d86f_write_track(drive, f, side, dev->thin_track_encoded_data[thin_track][side], dev->thin_track_surface_data[thin_track][side]); - } - } - } + if (tbl[logical_track]) { + fseek(*fp, tbl[logical_track], SEEK_SET); + d86f_write_track(drive, fp, side, dev->thin_track_encoded_data[thin_track][side], dev->thin_track_surface_data[thin_track][side]); + } + } + } } else { - for (side = 0; side < sides; side++) { - fdd_set_head(drive, side); - if (sides == 2) - logical_track = (dev->cur_track << 1) + side; - else - logical_track = dev->cur_track; + for (side = 0; side < sides; side++) { + fdd_set_head(drive, side); + if (sides == 2) + logical_track = (dev->cur_track << 1) + side; + else + logical_track = dev->cur_track; - if (track_table && !tbl[logical_track]) { - fseek(*f, 0, SEEK_END); - tbl[logical_track] = ftell(*f); - } + if (track_table && !tbl[logical_track]) { + fseek(*fp, 0, SEEK_END); + tbl[logical_track] = ftell(*fp); + } - if (tbl[logical_track]) { - if (fseek(*f, tbl[logical_track], SEEK_SET) == -1) - fatal("d86f_write_tracks(): Error seeking to offset tbl[logical_track]\n"); - d86f_write_track(drive, f, side, d86f_handler[drive].encoded_data(drive, side), dev->track_surface_data[side]); - } - } + if (tbl[logical_track]) { + if (fseek(*fp, tbl[logical_track], SEEK_SET) == -1) + fatal("d86f_write_tracks(): Error seeking to offset tbl[logical_track]\n"); + d86f_write_track(drive, fp, side, d86f_handler[drive].encoded_data(drive, side), dev->track_surface_data[side]); + } + } } fdd_set_head(drive, fdd_side); } - void d86f_writeback(int drive) { d86f_t *dev = d86f[drive]; uint8_t header[32]; - int header_size, size; + int header_size; + int size; #ifdef D86F_COMPRESS uint32_t len; - int ret = 0; - FILE *cf; + int ret = 0; + FILE *cf; #endif header_size = d86f_header_size(drive); - if (! dev->f) return; + if (!dev->fp) + return; /* First write the track offsets table. */ - if (fseek(dev->f, 0, SEEK_SET) == -1) - fatal("86F write_back(): Error seeking to the beginning of the file\n"); - if (fread(header, 1, header_size, dev->f) != header_size) - fatal("86F write_back(): Error reading header size\n"); + if (fseek(dev->fp, 0, SEEK_SET) == -1) + fatal("86F write_back(): Error seeking to the beginning of the file\n"); + if (fread(header, 1, header_size, dev->fp) != header_size) + fatal("86F write_back(): Error reading header size\n"); - if (fseek(dev->f, 8, SEEK_SET) == -1) - fatal("86F write_back(): Error seeking\n"); + if (fseek(dev->fp, 8, SEEK_SET) == -1) + fatal("86F write_back(): Error seeking\n"); size = d86f_get_track_table_size(drive); - if (fwrite(dev->track_offset, 1, size, dev->f) != size) - fatal("86F write_back(): Error writing data\n"); + if (fwrite(dev->track_offset, 1, size, dev->fp) != size) + fatal("86F write_back(): Error writing data\n"); - d86f_write_tracks(drive, &dev->f, NULL); + d86f_write_tracks(drive, &dev->fp, NULL); #ifdef D86F_COMPRESS if (dev->is_compressed) { - /* The image is compressed. */ + /* The image is compressed. */ - /* Open the original, compressed file. */ - cf = plat_fopen(dev->original_file_name, L"wb"); + /* Open the original, compressed file. */ + cf = plat_fopen(dev->original_file_name, L"wb"); - /* Write the header to the original file. */ - fwrite(header, 1, header_size, cf); + /* Write the header to the original file. */ + fwrite(header, 1, header_size, cf); - fseek(dev->f, 0, SEEK_END); - len = ftell(dev->f); - len -= header_size; + fseek(dev->fp, 0, SEEK_END); + len = ftell(dev->fp); + len -= header_size; - fseek(dev->f, header_size, SEEK_SET); + fseek(dev->fp, header_size, SEEK_SET); - /* Compress data from the temporary uncompressed file to the original, compressed file. */ - dev->filebuf = (uint8_t *) malloc(len); - dev->outbuf = (uint8_t *) malloc(len - 1); - fread(dev->filebuf, 1, len, dev->f); - ret = lzf_compress(dev->filebuf, len, dev->outbuf, len - 1); + /* Compress data from the temporary uncompressed file to the original, compressed file. */ + dev->filebuf = (uint8_t *) malloc(len); + dev->outbuf = (uint8_t *) malloc(len - 1); + fread(dev->filebuf, 1, len, dev->fp); + ret = lzf_compress(dev->filebuf, len, dev->outbuf, len - 1); - if (! ret) - d86f_log("86F: Error compressing file\n"); + if (!ret) + d86f_log("86F: Error compressing file\n"); - fwrite(dev->outbuf, 1, ret, cf); - free(dev->outbuf); - free(dev->filebuf); + fwrite(dev->outbuf, 1, ret, cf); + free(dev->outbuf); + free(dev->filebuf); } #endif } - void d86f_stop(int drive) { d86f_t *dev = d86f[drive]; if (dev) - dev->state = STATE_IDLE; + dev->state = STATE_IDLE; } - int -d86f_common_command(int drive, int sector, int track, int side, int rate, int sector_size) +d86f_common_command(int drive, int sector, int track, int side, UNUSED(int rate), int sector_size) { d86f_t *dev = d86f[drive]; @@ -3199,288 +3193,279 @@ d86f_common_command(int drive, int sector, int track, int side, int rate, int se dev->req_sector.id.c = track; dev->req_sector.id.h = side; if (sector == SECTOR_FIRST) - dev->req_sector.id.r = 1; + dev->req_sector.id.r = 1; else if (sector == SECTOR_NEXT) - dev->req_sector.id.r++; + dev->req_sector.id.r++; else - dev->req_sector.id.r = sector; + dev->req_sector.id.r = sector; dev->req_sector.id.n = sector_size; if (fdd_get_head(drive) && (d86f_get_sides(drive) == 1)) { - fdc_noidam(d86f_fdc); - dev->state = STATE_IDLE; - dev->index_count = 0; - return 0; + fdc_noidam(d86f_fdc); + dev->state = STATE_IDLE; + dev->index_count = 0; + return 0; } dev->id_find.sync_marks = dev->id_find.bits_obtained = dev->id_find.bytes_obtained = 0; dev->data_find.sync_marks = dev->data_find.bits_obtained = dev->data_find.bytes_obtained = 0; dev->index_count = dev->error_condition = dev->satisfying_bytes = 0; - dev->id_found = 0; - dev->dma_over = 0; + dev->id_found = 0; + dev->dma_over = 0; return 1; } - void d86f_readsector(int drive, int sector, int track, int side, int rate, int sector_size) { d86f_t *dev = d86f[drive]; - int ret = 0; + int ret = 0; ret = d86f_common_command(drive, sector, track, side, rate, sector_size); - if (! ret) - return; + if (!ret) + return; if (sector == SECTOR_FIRST) - dev->state = STATE_02_SPIN_TO_INDEX; + dev->state = STATE_02_SPIN_TO_INDEX; else if (sector == SECTOR_NEXT) - dev->state = STATE_02_FIND_ID; + dev->state = STATE_02_FIND_ID; else - dev->state = fdc_is_deleted(d86f_fdc) ? STATE_0C_FIND_ID : (fdc_is_verify(d86f_fdc) ? STATE_16_FIND_ID : STATE_06_FIND_ID); + dev->state = fdc_is_deleted(d86f_fdc) ? STATE_0C_FIND_ID : (fdc_is_verify(d86f_fdc) ? STATE_16_FIND_ID : STATE_06_FIND_ID); } - void d86f_writesector(int drive, int sector, int track, int side, int rate, int sector_size) { d86f_t *dev = d86f[drive]; - int ret = 0; + int ret = 0; if (writeprot[drive]) { - fdc_writeprotect(d86f_fdc); - dev->state = STATE_IDLE; - dev->index_count = 0; - return; + fdc_writeprotect(d86f_fdc); + dev->state = STATE_IDLE; + dev->index_count = 0; + return; } ret = d86f_common_command(drive, sector, track, side, rate, sector_size); - if (! ret) return; + if (!ret) + return; dev->state = fdc_is_deleted(d86f_fdc) ? STATE_09_FIND_ID : STATE_05_FIND_ID; } - void d86f_comparesector(int drive, int sector, int track, int side, int rate, int sector_size) { d86f_t *dev = d86f[drive]; - int ret = 0; + int ret = 0; ret = d86f_common_command(drive, sector, track, side, rate, sector_size); - if (! ret) return; + if (!ret) + return; dev->state = STATE_11_FIND_ID; } - void -d86f_readaddress(int drive, int side, int rate) +d86f_readaddress(int drive, UNUSED(int side), UNUSED(int rate)) { d86f_t *dev = d86f[drive]; if (fdd_get_head(drive) && (d86f_get_sides(drive) == 1)) { - fdc_noidam(d86f_fdc); - dev->state = STATE_IDLE; - dev->index_count = 0; - return; + fdc_noidam(d86f_fdc); + dev->state = STATE_IDLE; + dev->index_count = 0; + return; } dev->id_find.sync_marks = dev->id_find.bits_obtained = dev->id_find.bytes_obtained = 0; dev->data_find.sync_marks = dev->data_find.bits_obtained = dev->data_find.bytes_obtained = 0; dev->index_count = dev->error_condition = dev->satisfying_bytes = 0; - dev->id_found = 0; - dev->dma_over = 0; + dev->id_found = 0; + dev->dma_over = 0; dev->state = STATE_0A_FIND_ID; } - void d86f_add_track(int drive, int track, int side) { - d86f_t *dev = d86f[drive]; + d86f_t *dev = d86f[drive]; uint32_t array_size; - int logical_track; + int logical_track; array_size = d86f_get_array_size(drive, side, 0); if (d86f_get_sides(drive) == 2) { - logical_track = (track << 1) + side; + logical_track = (track << 1) + side; } else { - if (side) - return; - logical_track = track; + if (side) + return; + logical_track = track; } - if (! dev->track_offset[logical_track]) { - /* Track is absent from the file, let's add it. */ - dev->track_offset[logical_track] = dev->file_size; + if (!dev->track_offset[logical_track]) { + /* Track is absent from the file, let's add it. */ + dev->track_offset[logical_track] = dev->file_size; - dev->file_size += (array_size + 6); - if (d86f_has_extra_bit_cells(drive)) - dev->file_size += 4; - if (d86f_has_surface_desc(drive)) - dev->file_size += array_size; + dev->file_size += (array_size + 6); + if (d86f_has_extra_bit_cells(drive)) + dev->file_size += 4; + if (d86f_has_surface_desc(drive)) + dev->file_size += array_size; } } - void -d86f_common_format(int drive, int side, int rate, uint8_t fill, int proxy) +d86f_common_format(int drive, int side, UNUSED(int rate), uint8_t fill, int proxy) { - d86f_t *dev = d86f[drive]; - uint32_t i = 0; - uint16_t temp, temp2; + d86f_t *dev = d86f[drive]; + uint16_t temp; + uint16_t temp2; uint32_t array_size; if (writeprot[drive]) { - fdc_writeprotect(d86f_fdc); - dev->state = STATE_IDLE; - dev->index_count = 0; - return; + fdc_writeprotect(d86f_fdc); + dev->state = STATE_IDLE; + dev->index_count = 0; + return; } - if (! d86f_can_format(drive)) { - fdc_cannotformat(d86f_fdc); - dev->state = STATE_IDLE; - dev->index_count = 0; - return; + if (!d86f_can_format(drive)) { + fdc_cannotformat(d86f_fdc); + dev->state = STATE_IDLE; + dev->index_count = 0; + return; } if (!side || (d86f_get_sides(drive) == 2)) { - if (! proxy) { - d86f_reset_index_hole_pos(drive, side); + if (!proxy) { + d86f_reset_index_hole_pos(drive, side); - if (dev->cur_track > 256) { - fdc_writeprotect(d86f_fdc); - dev->state = STATE_IDLE; - dev->index_count = 0; - return; - } + if (dev->cur_track > 256) { + fdc_writeprotect(d86f_fdc); + dev->state = STATE_IDLE; + dev->index_count = 0; + return; + } - array_size = d86f_get_array_size(drive, side, 0); + array_size = d86f_get_array_size(drive, side, 0); - if (d86f_has_surface_desc(drive)) { - /* Preserve the physical holes but get rid of the fuzzy bytes. */ - for (i = 0; i < array_size; i++) { - temp = dev->track_encoded_data[side][i] ^ 0xffff; - temp2 = dev->track_surface_data[side][i]; - temp &= temp2; - dev->track_surface_data[side][i] = temp; - } - } + if (d86f_has_surface_desc(drive)) { + /* Preserve the physical holes but get rid of the fuzzy bytes. */ + for (uint32_t i = 0; i < array_size; i++) { + temp = dev->track_encoded_data[side][i] ^ 0xffff; + temp2 = dev->track_surface_data[side][i]; + temp &= temp2; + dev->track_surface_data[side][i] = temp; + } + } - /* Zero the data buffer. */ - memset(dev->track_encoded_data[side], 0, array_size); + /* Zero the data buffer. */ + memset(dev->track_encoded_data[side], 0, array_size); - d86f_add_track(drive, dev->cur_track, side); - if (! fdd_doublestep_40(drive)) - d86f_add_track(drive, dev->cur_track + 1, side); - } + d86f_add_track(drive, dev->cur_track, side); + if (!fdd_doublestep_40(drive)) + d86f_add_track(drive, dev->cur_track + 1, side); + } } - dev->fill = fill; + dev->fill = fill; - if (! proxy) { - dev->side_flags[side] = 0; - dev->side_flags[side] |= (fdd_getrpm(real_drive(d86f_fdc, drive)) == 360) ? 0x20 : 0; - dev->side_flags[side] |= fdc_get_bit_rate(d86f_fdc); - dev->side_flags[side] |= fdc_is_mfm(d86f_fdc) ? 8 : 0; + if (!proxy) { + dev->side_flags[side] = 0; + dev->side_flags[side] |= (fdd_getrpm(real_drive(d86f_fdc, drive)) == 360) ? 0x20 : 0; + dev->side_flags[side] |= fdc_get_bit_rate(d86f_fdc); + dev->side_flags[side] |= fdc_is_mfm(d86f_fdc) ? 8 : 0; - dev->index_hole_pos[side] = 0; + dev->index_hole_pos[side] = 0; } dev->id_find.sync_marks = dev->id_find.bits_obtained = dev->id_find.bytes_obtained = 0; dev->data_find.sync_marks = dev->data_find.bits_obtained = dev->data_find.bytes_obtained = 0; dev->index_count = dev->error_condition = dev->satisfying_bytes = dev->sector_count = 0; - dev->dma_over = 0; + dev->dma_over = 0; dev->state = STATE_0D_SPIN_TO_INDEX; } - void d86f_proxy_format(int drive, int side, int rate, uint8_t fill) { d86f_common_format(drive, side, rate, fill, 1); } - void d86f_format(int drive, int side, int rate, uint8_t fill) { d86f_common_format(drive, side, rate, fill, 0); } - void d86f_common_handlers(int drive) { - drives[drive].readsector = d86f_readsector; - drives[drive].writesector = d86f_writesector; - drives[drive].comparesector =d86f_comparesector; - drives[drive].readaddress = d86f_readaddress; - drives[drive].byteperiod = d86f_byteperiod; - drives[drive].poll = d86f_poll; - drives[drive].format = d86f_proxy_format; - drives[drive].stop = d86f_stop; + drives[drive].readsector = d86f_readsector; + drives[drive].writesector = d86f_writesector; + drives[drive].comparesector = d86f_comparesector; + drives[drive].readaddress = d86f_readaddress; + drives[drive].byteperiod = d86f_byteperiod; + drives[drive].poll = d86f_poll; + drives[drive].format = d86f_proxy_format; + drives[drive].stop = d86f_stop; } - int d86f_export(int drive, char *fn) { uint32_t tt[512]; - d86f_t *dev = d86f[drive]; - d86f_t *temp86; - FILE *f; - int tracks = 86; - int i; - int inc = 1; - uint32_t magic = 0x46423638; - uint16_t version = 0x020C; + d86f_t *dev = d86f[drive]; + d86f_t *temp86; + FILE *fp; + int tracks = 86; + int inc = 1; + uint32_t magic = 0x46423638; + uint16_t version = 0x020C; uint16_t disk_flags = d86f_handler[drive].disk_flags(drive); memset(tt, 0, 512 * sizeof(uint32_t)); - f = plat_fopen(fn, "wb"); - if (!f) - return 0; + fp = plat_fopen(fn, "wb"); + if (!fp) + return 0; /* Allocate a temporary drive for conversion. */ - temp86 = (d86f_t *)malloc(sizeof(d86f_t)); + temp86 = (d86f_t *) malloc(sizeof(d86f_t)); memcpy(temp86, dev, sizeof(d86f_t)); - fwrite(&magic, 4, 1, f); - fwrite(&version, 2, 1, f); - fwrite(&disk_flags, 2, 1, f); + fwrite(&magic, 4, 1, fp); + fwrite(&version, 2, 1, fp); + fwrite(&disk_flags, 2, 1, fp); - fwrite(tt, 1, ((d86f_get_sides(drive) == 2) ? 2048 : 1024), f); + fwrite(tt, 1, ((d86f_get_sides(drive) == 2) ? 2048 : 1024), fp); /* In the case of a thick track drive, always increment track by two, since two tracks are going to get output at once. */ if (!fdd_doublestep_40(drive)) - inc = 2; + inc = 2; - for (i = 0; i < tracks; i += inc) { - if (inc == 2) - fdd_do_seek(drive, i >> 1); - else - fdd_do_seek(drive, i); - dev->cur_track = i; - d86f_write_tracks(drive, &f, tt); + for (int i = 0; i < tracks; i += inc) { + if (inc == 2) + fdd_do_seek(drive, i >> 1); + else + fdd_do_seek(drive, i); + dev->cur_track = i; + d86f_write_tracks(drive, &fp, tt); } - fclose(f); + fclose(fp); - f = plat_fopen(fn, "rb+"); + fp = plat_fopen(fn, "rb+"); - fseek(f, 8, SEEK_SET); - fwrite(tt, 1, ((d86f_get_sides(drive) == 2) ? 2048 : 1024), f); + fseek(fp, 8, SEEK_SET); + fwrite(tt, 1, ((d86f_get_sides(drive) == 2) ? 2048 : 1024), fp); - fclose(f); + fclose(fp); fdd_do_seek(drive, fdd_current_track(drive)); @@ -3491,95 +3476,93 @@ d86f_export(int drive, char *fn) return 1; } - void d86f_load(int drive, char *fn) { - d86f_t *dev = d86f[drive]; + d86f_t *dev = d86f[drive]; uint32_t magic = 0; - uint32_t len = 0; - int i = 0, j = 0; + uint32_t len = 0; #ifdef D86F_COMPRESS - char temp_file_name[2048]; + char temp_file_name[2048]; uint16_t temp = 0; - FILE *tf; + FILE *tf; #endif d86f_unregister(drive); writeprot[drive] = 0; - dev->f = plat_fopen(fn, "rb+"); - if (! dev->f) { - dev->f = plat_fopen(fn, "rb"); - if (! dev->f) { - memset(floppyfns[drive], 0, sizeof(floppyfns[drive])); - free(dev); - return; - } - writeprot[drive] = 1; + dev->fp = plat_fopen(fn, "rb+"); + if (!dev->fp) { + dev->fp = plat_fopen(fn, "rb"); + if (!dev->fp) { + memset(floppyfns[drive], 0, sizeof(floppyfns[drive])); + free(dev); + return; + } + writeprot[drive] = 1; } if (ui_writeprot[drive]) { - writeprot[drive] = 1; + writeprot[drive] = 1; } fwriteprot[drive] = writeprot[drive]; - fseek(dev->f, 0, SEEK_END); - len = ftell(dev->f); - fseek(dev->f, 0, SEEK_SET); + fseek(dev->fp, 0, SEEK_END); + len = ftell(dev->fp); + fseek(dev->fp, 0, SEEK_SET); - fread(&magic, 4, 1, dev->f); + (void) !fread(&magic, 4, 1, dev->fp); if (len < 16) { - /* File is WAY too small, abort. */ - fclose(dev->f); - dev->f = NULL; - memset(floppyfns[drive], 0, sizeof(floppyfns[drive])); - free(dev); - return; + /* File is WAY too small, abort. */ + fclose(dev->fp); + dev->fp = NULL; + memset(floppyfns[drive], 0, sizeof(floppyfns[drive])); + free(dev); + return; } if ((magic != 0x46423638) && (magic != 0x66623638)) { - /* File is not of the valid format, abort. */ - d86f_log("86F: Unrecognized magic bytes: %08X\n", magic); - fclose(dev->f); - memset(floppyfns[drive], 0, sizeof(floppyfns[drive])); - free(dev); - return; + /* File is not of the valid format, abort. */ + d86f_log("86F: Unrecognized magic bytes: %08X\n", magic); + fclose(dev->fp); + memset(floppyfns[drive], 0, sizeof(floppyfns[drive])); + free(dev); + return; } - if (fread(&(dev->version), 1, 2, dev->f) != 2) - fatal("d86f_load(): Error reading format version\n"); + if (fread(&(dev->version), 1, 2, dev->fp) != 2) + fatal("d86f_load(): Error reading format version\n"); if (dev->version != D86FVER) { - /* File is not of a recognized format version, abort. */ - if (dev->version == 0x0063) { - d86f_log("86F: File has emulator-internal version 0.99, this version is not valid in a file\n"); - } else if ((dev->version >= 0x0100) && (dev->version < D86FVER)) { - d86f_log("86F: No longer supported development file version: %i.%02i\n", dev->version >> 8, dev->version & 0xff); - } else { - d86f_log("86F: Unrecognized file version: %i.%02i\n", dev->version >> 8, dev->version & 0xff); - } - fclose(dev->f); - dev->f = NULL; - memset(floppyfns[drive], 0, sizeof(floppyfns[drive])); - free(dev); - return; + /* File is not of a recognized format version, abort. */ + if (dev->version == 0x0063) { + d86f_log("86F: File has emulator-internal version 0.99, this version is not valid in a file\n"); + } else if ((dev->version >= 0x0100) && (dev->version < D86FVER)) { + d86f_log("86F: No longer supported development file version: %i.%02i\n", dev->version >> 8, dev->version & 0xff); + } else { + d86f_log("86F: Unrecognized file version: %i.%02i\n", dev->version >> 8, dev->version & 0xff); + } + fclose(dev->fp); + dev->fp = NULL; + memset(floppyfns[drive], 0, sizeof(floppyfns[drive])); + free(dev); + return; } else { - d86f_log("86F: Recognized file version: %i.%02i\n", dev->version >> 8, dev->version & 0xff); + d86f_log("86F: Recognized file version: %i.%02i\n", dev->version >> 8, dev->version & 0xff); } - fread(&(dev->disk_flags), 2, 1, dev->f); + (void) !fread(&(dev->disk_flags), 2, 1, dev->fp); if (d86f_has_surface_desc(drive)) { - for (i = 0; i < 2; i++) - dev->track_surface_data[i] = (uint16_t *) malloc(53048 * sizeof(uint16_t)); + for (uint8_t i = 0; i < 2; i++) + dev->track_surface_data[i] = (uint16_t *) malloc(53048 * sizeof(uint16_t)); - for (i = 0; i < 2; i++) { - for (j = 0; j < 2; j++) - dev->thin_track_surface_data[i][j] = (uint16_t *) malloc(53048 * sizeof(uint16_t)); - } + for (uint8_t i = 0; i < 2; i++) { + for (uint8_t j = 0; j < 2; j++) + dev->thin_track_surface_data[i][j] = (uint16_t *) malloc(53048 * sizeof(uint16_t)); + } } #ifdef D86F_COMPRESS @@ -3588,216 +3571,220 @@ d86f_load(int drive, char *fn) #else if (len < 51052) { #endif - /* File too small, abort. */ - fclose(dev->f); - dev->f = NULL; - memset(floppyfns[drive], 0, sizeof(floppyfns[drive])); - free(dev); - return; + /* File too small, abort. */ + fclose(dev->fp); + dev->fp = NULL; + memset(floppyfns[drive], 0, sizeof(floppyfns[drive])); + free(dev); + return; } #ifdef DO_CRC64 - fseek(dev->f, 8, SEEK_SET); - fread(&read_crc64, 1, 8, dev->f); + fseek(dev->fp, 8, SEEK_SET); + fread(&read_crc64, 1, 8, dev->fp); - fseek(dev->f, 0, SEEK_SET); + fseek(dev->fp, 0, SEEK_SET); crc64 = 0xffffffffffffffff; dev->filebuf = malloc(len); - fread(dev->filebuf, 1, len, dev->f); + fread(dev->filebuf, 1, len, dev->fp); *(uint64_t *) &(dev->filebuf[8]) = 0xffffffffffffffff; - crc64 = (uint64_t) crc64speed(0, dev->filebuf, len); + crc64 = (uint64_t) crc64speed(0, dev->filebuf, len); free(dev->filebuf); if (crc64 != read_crc64) { - d86f_log("86F: CRC64 error\n"); - fclose(dev->f); - dev->f = NULL; - memset(floppyfns[drive], 0, sizeof(floppyfns[drive])); - free(dev); - return; + d86f_log("86F: CRC64 error\n"); + fclose(dev->fp); + dev->fp = NULL; + memset(floppyfns[drive], 0, sizeof(floppyfns[drive])); + free(dev); + return; } #endif #ifdef D86F_COMPRESS if (dev->is_compressed) { - memcpy(temp_file_name, drive ? nvr_path("TEMP$$$1.$$$") : nvr_path("TEMP$$$0.$$$"), 256); - memcpy(dev->original_file_name, fn, strlen(fn) + 1); + memcpy(temp_file_name, drive ? nvr_path("TEMP$$$1.$$$") : nvr_path("TEMP$$$0.$$$"), 256); + memcpy(dev->original_file_name, fn, strlen(fn) + 1); - fclose(dev->f); - dev->f = NULL; + fclose(dev->fp); + dev->fp = NULL; - dev->f = plat_fopen(temp_file_name, "wb"); - if (! dev->f) { - d86f_log("86F: Unable to create temporary decompressed file\n"); - memset(floppyfns[drive], 0, sizeof(floppyfns[drive])); - free(dev); - return; - } + dev->fp = plat_fopen(temp_file_name, "wb"); + if (!dev->fp) { + d86f_log("86F: Unable to create temporary decompressed file\n"); + memset(floppyfns[drive], 0, sizeof(floppyfns[drive])); + free(dev); + return; + } - tf = plat_fopen(fn, "rb"); + tf = plat_fopen(fn, "rb"); - for (i = 0; i < 8; i++) { - fread(&temp, 1, 2, tf); - fwrite(&temp, 1, 2, dev->f); - } + for (uint8_t i = 0; i < 8; i++) { + fread(&temp, 1, 2, tf); + fwrite(&temp, 1, 2, dev->fp); + } - dev->filebuf = (uint8_t *) malloc(len); - dev->outbuf = (uint8_t *) malloc(67108864); - fread(dev->filebuf, 1, len, tf); - temp = lzf_decompress(dev->filebuf, len, dev->outbuf, 67108864); - if (temp) { - fwrite(dev->outbuf, 1, temp, dev->f); - } - free(dev->outbuf); - free(dev->filebuf); + dev->filebuf = (uint8_t *) malloc(len); + dev->outbuf = (uint8_t *) malloc(67108864); + fread(dev->filebuf, 1, len, tf); + temp = lzf_decompress(dev->filebuf, len, dev->outbuf, 67108864); + if (temp) { + fwrite(dev->outbuf, 1, temp, dev->fp); + } + free(dev->outbuf); + free(dev->filebuf); - fclose(tf); - fclose(dev->f); - dev->f = NULL; + fclose(tf); + fclose(dev->fp); + dev->fp = NULL; - if (! temp) { - d86f_log("86F: Error decompressing file\n"); - plat_remove(temp_file_name); - memset(floppyfns[drive], 0, sizeof(floppyfns[drive])); - free(dev); - return; - } + if (!temp) { + d86f_log("86F: Error decompressing file\n"); + plat_remove(temp_file_name); + memset(floppyfns[drive], 0, sizeof(floppyfns[drive])); + free(dev); + return; + } - dev->f = plat_fopen(temp_file_name, "rb+"); + dev->fp = plat_fopen(temp_file_name, "rb+"); } #endif if (dev->disk_flags & 0x100) { - /* Zoned disk. */ - d86f_log("86F: Disk is zoned (Apple or Sony)\n"); - fclose(dev->f); - dev->f = NULL; + /* Zoned disk. */ + d86f_log("86F: Disk is zoned (Apple or Sony)\n"); + fclose(dev->fp); + dev->fp = NULL; #ifdef D86F_COMPRESS - if (dev->is_compressed) - plat_remove(temp_file_name); + if (dev->is_compressed) + plat_remove(temp_file_name); #endif - memset(floppyfns[drive], 0, sizeof(floppyfns[drive])); - free(dev); - return; + memset(floppyfns[drive], 0, sizeof(floppyfns[drive])); + free(dev); + return; } if (dev->disk_flags & 0x600) { - /* Zone type is not 0 but the disk is fixed-RPM. */ - d86f_log("86F: Disk is fixed-RPM but zone type is not 0\n"); - fclose(dev->f); - dev->f = NULL; + /* Zone type is not 0 but the disk is fixed-RPM. */ + d86f_log("86F: Disk is fixed-RPM but zone type is not 0\n"); + fclose(dev->fp); + dev->fp = NULL; #ifdef D86F_COMPRESS - if (dev->is_compressed) - plat_remove(temp_file_name); + if (dev->is_compressed) + plat_remove(temp_file_name); #endif - memset(floppyfns[drive], 0, sizeof(floppyfns[drive])); - free(dev); - return; + memset(floppyfns[drive], 0, sizeof(floppyfns[drive])); + free(dev); + return; } if (!writeprot[drive]) { - writeprot[drive] = (dev->disk_flags & 0x10) ? 1 : 0; - fwriteprot[drive] = writeprot[drive]; + writeprot[drive] = (dev->disk_flags & 0x10) ? 1 : 0; + fwriteprot[drive] = writeprot[drive]; } if (writeprot[drive]) { - fclose(dev->f); - dev->f = NULL; + fclose(dev->fp); + dev->fp = NULL; #ifdef D86F_COMPRESS - if (dev->is_compressed) - dev->f = plat_fopen(temp_file_name, "rb"); - else + if (dev->is_compressed) + dev->fp = plat_fopen(temp_file_name, "rb"); + else #endif - dev->f = plat_fopen(fn, "rb"); + dev->fp = plat_fopen(fn, "rb"); } /* OK, set the drive data, other code needs it. */ d86f[drive] = dev; - fseek(dev->f, 8, SEEK_SET); + fseek(dev->fp, 8, SEEK_SET); - fread(dev->track_offset, 1, d86f_get_track_table_size(drive), dev->f); + (void) !fread(dev->track_offset, 1, d86f_get_track_table_size(drive), dev->fp); - if (! (dev->track_offset[0])) { - /* File has no track 0 side 0, abort. */ - d86f_log("86F: No Track 0 side 0\n"); - fclose(dev->f); - dev->f = NULL; - memset(floppyfns[drive], 0, sizeof(floppyfns[drive])); - free(dev); - d86f[drive] = NULL; - return; + if (!(dev->track_offset[0])) { + /* File has no track 0 side 0, abort. */ + d86f_log("86F: No Track 0 side 0\n"); + fclose(dev->fp); + dev->fp = NULL; + memset(floppyfns[drive], 0, sizeof(floppyfns[drive])); + free(dev); + d86f[drive] = NULL; + return; } if ((d86f_get_sides(drive) == 2) && !(dev->track_offset[1])) { - /* File is 2-sided but has no track 0 side 1, abort. */ - d86f_log("86F: No Track 0 side 1\n"); - fclose(dev->f); - dev->f = NULL; - memset(floppyfns[drive], 0, sizeof(floppyfns[drive])); - free(dev); - d86f[drive] = NULL; - return; + /* File is 2-sided but has no track 0 side 1, abort. */ + d86f_log("86F: No Track 0 side 1\n"); + fclose(dev->fp); + dev->fp = NULL; + memset(floppyfns[drive], 0, sizeof(floppyfns[drive])); + free(dev); + d86f[drive] = NULL; + return; } /* Load track 0 flags as default. */ - if (fseek(dev->f, dev->track_offset[0], SEEK_SET) == -1) - fatal("d86f_load(): Track 0: Error seeking to the beginning of the file\n"); - if (fread(&(dev->side_flags[0]), 1, 2, dev->f) != 2) - fatal("d86f_load(): Track 0: Error reading side flags\n"); + if (fseek(dev->fp, dev->track_offset[0], SEEK_SET) == -1) + fatal("d86f_load(): Track 0: Error seeking to the beginning of the file\n"); + if (fread(&(dev->side_flags[0]), 1, 2, dev->fp) != 2) + fatal("d86f_load(): Track 0: Error reading side flags\n"); if (dev->disk_flags & 0x80) { - if (fread(&(dev->extra_bit_cells[0]), 1, 4, dev->f) != 4) - fatal("d86f_load(): Track 0: Error reading the amount of extra bit cells\n"); - if ((dev->disk_flags & 0x1060) != 0x1000) { - if (dev->extra_bit_cells[0] < -32768) dev->extra_bit_cells[0] = -32768; - if (dev->extra_bit_cells[0] > 32768) dev->extra_bit_cells[0] = 32768; - } + if (fread(&(dev->extra_bit_cells[0]), 1, 4, dev->fp) != 4) + fatal("d86f_load(): Track 0: Error reading the amount of extra bit cells\n"); + if ((dev->disk_flags & 0x1060) != 0x1000) { + if (dev->extra_bit_cells[0] < -32768) + dev->extra_bit_cells[0] = -32768; + if (dev->extra_bit_cells[0] > 32768) + dev->extra_bit_cells[0] = 32768; + } } else { - dev->extra_bit_cells[0] = 0; + dev->extra_bit_cells[0] = 0; } if (d86f_get_sides(drive) == 2) { - if (fseek(dev->f, dev->track_offset[1], SEEK_SET) == -1) - fatal("d86f_load(): Track 1: Error seeking to the beginning of the file\n"); - if (fread(&(dev->side_flags[1]), 1, 2, dev->f) != 2) - fatal("d86f_load(): Track 1: Error reading side flags\n"); - if (dev->disk_flags & 0x80) { - if (fread(&(dev->extra_bit_cells[1]), 1, 4, dev->f) != 4) - fatal("d86f_load(): Track 4: Error reading the amount of extra bit cells\n"); - if ((dev->disk_flags & 0x1060) != 0x1000) { - if (dev->extra_bit_cells[1] < -32768) dev->extra_bit_cells[1] = -32768; - if (dev->extra_bit_cells[1] > 32768) dev->extra_bit_cells[1] = 32768; - } - } else { - dev->extra_bit_cells[1] = 0; - } + if (fseek(dev->fp, dev->track_offset[1], SEEK_SET) == -1) + fatal("d86f_load(): Track 1: Error seeking to the beginning of the file\n"); + if (fread(&(dev->side_flags[1]), 1, 2, dev->fp) != 2) + fatal("d86f_load(): Track 1: Error reading side flags\n"); + if (dev->disk_flags & 0x80) { + if (fread(&(dev->extra_bit_cells[1]), 1, 4, dev->fp) != 4) + fatal("d86f_load(): Track 4: Error reading the amount of extra bit cells\n"); + if ((dev->disk_flags & 0x1060) != 0x1000) { + if (dev->extra_bit_cells[1] < -32768) + dev->extra_bit_cells[1] = -32768; + if (dev->extra_bit_cells[1] > 32768) + dev->extra_bit_cells[1] = 32768; + } + } else { + dev->extra_bit_cells[1] = 0; + } } else { - switch ((dev->disk_flags >> 1) >> 3) { - case 0: - default: - dev->side_flags[1] = 0x0a; - break; + switch ((dev->disk_flags >> 1) >> 3) { + default: + case 0: + dev->side_flags[1] = 0x0a; + break; - case 1: - dev->side_flags[1] = 0x00; - break; + case 1: + dev->side_flags[1] = 0x00; + break; - case 2: - case 3: - dev->side_flags[1] = 0x03; - break; - } + case 2: + case 3: + dev->side_flags[1] = 0x03; + break; + } - dev->extra_bit_cells[1] = 0; + dev->extra_bit_cells[1] = 0; } - fseek(dev->f, 0, SEEK_END); - dev->file_size = ftell(dev->f); + fseek(dev->fp, 0, SEEK_END); + dev->file_size = ftell(dev->fp); - fseek(dev->f, 0, SEEK_SET); + fseek(dev->fp, 0, SEEK_SET); d86f_register_86f(drive); @@ -3807,76 +3794,69 @@ d86f_load(int drive, char *fn) #ifdef D86F_COMPRESS d86f_log("86F: Disk is %scompressed and does%s have surface description data\n", - dev->is_compressed ? "" : "not ", - d86f_has_surface_desc(drive) ? "" : " not"); + dev->is_compressed ? "" : "not ", + d86f_has_surface_desc(drive) ? "" : " not"); #else d86f_log("86F: Disk does%s have surface description data\n", - d86f_has_surface_desc(drive) ? "" : " not"); + d86f_has_surface_desc(drive) ? "" : " not"); #endif } - void d86f_init(void) { - int i; - setup_crc(0x1021); - for (i = 0; i < FDD_NUM; i++) - d86f[i] = NULL; + for (uint8_t i = 0; i < FDD_NUM; i++) + d86f[i] = NULL; } - void d86f_set_fdc(void *fdc) { d86f_fdc = (fdc_t *) fdc; } - void d86f_close(int drive) { - int i, j; - - char temp_file_name[2048]; + char temp_file_name[2048]; d86f_t *dev = d86f[drive]; /* Make sure the drive is alive. */ - if (dev == NULL) return; + if (dev == NULL) + return; memcpy(temp_file_name, drive ? nvr_path("TEMP$$$1.$$$") : nvr_path("TEMP$$$0.$$$"), 26); if (d86f_has_surface_desc(drive)) { - for (i = 0; i < 2; i++) { - if (dev->track_surface_data[i]) { - free(dev->track_surface_data[i]); - dev->track_surface_data[i] = NULL; - } - } + for (uint8_t i = 0; i < 2; i++) { + if (dev->track_surface_data[i]) { + free(dev->track_surface_data[i]); + dev->track_surface_data[i] = NULL; + } + } - for (i = 0; i < 2; i++) { - for (j = 0; j < 2; j++) { - if (dev->thin_track_surface_data[i][j]) { - free(dev->thin_track_surface_data[i][j]); - dev->thin_track_surface_data[i][j] = NULL; - } - } - } + for (uint8_t i = 0; i < 2; i++) { + for (uint8_t j = 0; j < 2; j++) { + if (dev->thin_track_surface_data[i][j]) { + free(dev->thin_track_surface_data[i][j]); + dev->thin_track_surface_data[i][j] = NULL; + } + } + } } - if (dev->f) { - fclose(dev->f); - dev->f = NULL; + if (dev->fp) { + fclose(dev->fp); + dev->fp = NULL; } #ifdef D86F_COMPRESS if (dev->is_compressed) - plat_remove(temp_file_name); + plat_remove(temp_file_name); #endif } - /* When an FDD is mounted, set up the D86F data structures. */ void d86f_setup(int drive) @@ -3884,7 +3864,7 @@ d86f_setup(int drive) d86f_t *dev; /* Allocate a drive structure. */ - dev = (d86f_t *)malloc(sizeof(d86f_t)); + dev = (d86f_t *) malloc(sizeof(d86f_t)); memset(dev, 0x00, sizeof(d86f_t)); dev->state = STATE_IDLE; @@ -3895,33 +3875,31 @@ d86f_setup(int drive) d86f[drive] = dev; } - /* If an FDD is unmounted, unlink the D86F data structures. */ void d86f_destroy(int drive) { - int i, j; - d86f_t *dev = d86f[drive]; - if (dev == NULL) return; + if (dev == NULL) + return; if (d86f_has_surface_desc(drive)) { - for (i = 0; i < 2; i++) { - if (dev->track_surface_data[i]) { - free(dev->track_surface_data[i]); - dev->track_surface_data[i] = NULL; - } - } + for (uint8_t i = 0; i < 2; i++) { + if (dev->track_surface_data[i]) { + free(dev->track_surface_data[i]); + dev->track_surface_data[i] = NULL; + } + } - for (i = 0; i < 2; i++) { - for (j = 0; j < 2; j++) { - if (dev->thin_track_surface_data[i][j]) { - free(dev->thin_track_surface_data[i][j]); - dev->thin_track_surface_data[i][j] = NULL; - } - } - } + for (uint8_t i = 0; i < 2; i++) { + for (uint8_t j = 0; j < 2; j++) { + if (dev->thin_track_surface_data[i][j]) { + free(dev->thin_track_surface_data[i][j]); + dev->thin_track_surface_data[i][j] = NULL; + } + } + } } d86f_destroy_linked_lists(drive, 0); diff --git a/src/floppy/fdd_common.c b/src/floppy/fdd_common.c index 4536a8683..d0659d990 100644 --- a/src/floppy/fdd_common.c +++ b/src/floppy/fdd_common.c @@ -1,18 +1,18 @@ /* - * 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. + * 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. + * This file is part of the 86Box distribution. * - * Shared code for all the floppy modules. + * Shared code for all the floppy modules. * * * - * Author: Fred N. van Kempen, + * Authors: Fred N. van Kempen, * - * Copyright 2017,2018 Fred N. van Kempen. + * Copyright 2017-2018 Fred N. van Kempen. */ #include #include @@ -24,7 +24,6 @@ #include <86box/fdd.h> #include <86box/fdd_common.h> - const uint8_t fdd_holes[6] = { 0, 0, 0, 1, 1, 2 }; const uint8_t fdd_rates[6] = { 2, 2, 1, 4, 0, 3 }; @@ -49,393 +48,390 @@ const double fdd_bit_rates_300[6] = { * single-RPM drive by setting the rate to 300 kbps. */ const uint8_t fdd_max_sectors[8][6] = { - { 26, 31, 38, 53, 64, 118 }, /* 128 */ - { 15, 19, 23, 32, 38, 73 }, /* 256 */ - { 7, 10, 12, 17, 22, 41 }, /* 512 */ - { 3, 5, 6, 9, 11, 22 }, /* 1024 */ - { 2, 2, 3, 4, 5, 11 }, /* 2048 */ - { 1, 1, 1, 2, 2, 5 }, /* 4096 */ - { 0, 0, 0, 1, 1, 3 }, /* 8192 */ - { 0, 0, 0, 0, 0, 1 } /* 16384 */ + { 26, 31, 38, 53, 64, 118 }, /* 128 */ + { 15, 19, 23, 32, 38, 73 }, /* 256 */ + { 7, 10, 12, 17, 22, 41 }, /* 512 */ + { 3, 5, 6, 9, 11, 22 }, /* 1024 */ + { 2, 2, 3, 4, 5, 11 }, /* 2048 */ + { 1, 1, 1, 2, 2, 5 }, /* 4096 */ + { 0, 0, 0, 1, 1, 3 }, /* 8192 */ + { 0, 0, 0, 0, 0, 1 } /* 16384 */ }; -const uint8_t fdd_dmf_r[21] = { - 12,2,13,3,14,4,15,5,16,6,17,7,18,8,19,9,20,10,21,11,1 +const uint8_t fdd_dmf_r[21] = { + 12, 2, 13, 3, 14, 4, 15, 5, 16, 6, 17, 7, 18, 8, 19, 9, 20, 10, 21, 11, 1 }; - static const uint8_t fdd_gap3_sizes[5][8][48] = { - { { 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* [0][0] */ - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 }, + { + { 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* [0][0] */ + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 }, - { 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* [0][1] */ - 0x54,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 }, + { 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* [0][1] */ + 0x54,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 }, - { 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* [0][2] */ - 0x00,0x00,0x6C,0x48,0x2A,0x08,0x02,0x01, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 }, + { 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* [0][2] */ + 0x00,0x00,0x6C,0x48,0x2A,0x08,0x02,0x01, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 }, - { 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x83,0x26,0x00,0x00,0x00,0x00, /* [0][3] */ - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 }, + { 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x83,0x26,0x00,0x00,0x00,0x00, /* [0][3] */ + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 }, - { 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* [0][4] */ - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 }, + { 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* [0][4] */ + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 }, - { 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* [0][5] */ - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 }, + { 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* [0][5] */ + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 }, - { 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* [0][6] */ - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 }, + { 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* [0][6] */ + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 }, - { 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* [0][7] */ - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 } + { 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* [0][7] */ + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 } }, - { { 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* [1][0] */ - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 }, + { + { 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* [1][0] */ + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 }, - { 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* [1][1] */ - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 }, + { 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* [1][1] */ + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 }, - { 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x54,0x1C,0x0E,0x00,0x00, /* [1][2] */ - 0x00,0x00,0x6C,0x48,0x2A,0x08,0x02,0x01, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 }, + { 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x54,0x1C,0x0E,0x00,0x00, /* [1][2] */ + 0x00,0x00,0x6C,0x48,0x2A,0x08,0x02,0x01, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 }, - { 0x00,0x00,0x00,0x00,0x00,0x00,0x79,0x06, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* [1][3] */ - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 }, + { 0x00,0x00,0x00,0x00,0x00,0x00,0x79,0x06, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* [1][3] */ + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 }, - { 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* [1][4] */ - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 }, + { 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* [1][4] */ + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 }, - { 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* [1][5] */ - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 }, + { 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* [1][5] */ + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 }, - { 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* [1][6] */ - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 }, + { 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* [1][6] */ + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 }, - { 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* [1][7] */ - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 } + { 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* [1][7] */ + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 } }, - { { 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* [2][0] */ - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 }, + { + { 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* [2][0] */ + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 }, - { 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x32,0x0C,0x00,0x00,0x00,0x36, /* [2][1] */ - 0x32,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 }, + { 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x32,0x0C,0x00,0x00,0x00,0x36, /* [2][1] */ + 0x32,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 }, - { 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x58,0x50,0x2E,0x00,0x00,0x00,0x00,0x00, /* [2][2] */ - 0x00,0x00,0x00,0x00,0x00,0x1C,0x1C,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 }, + { 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x58,0x50,0x2E,0x00,0x00,0x00,0x00,0x00, /* [2][2] */ + 0x00,0x00,0x00,0x00,0x00,0x1C,0x1C,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 }, - { 0x00,0x00,0x00,0x00,0xF0,0x74,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* [2][3] */ - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 }, + { 0x00,0x00,0x00,0x00,0xF0,0x74,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* [2][3] */ + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 }, - { 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* [2][4] */ - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 }, + { 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* [2][4] */ + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 }, - { 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* [2][5] */ - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 }, + { 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* [2][5] */ + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 }, - { 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* [2][6] */ - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 }, + { 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* [2][6] */ + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 }, - { 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* [2][7] */ - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 } + { 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* [2][7] */ + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 } }, - { { 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* [3][0] */ - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 }, + { + { 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* [3][0] */ + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 }, - { 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* [3][1] */ - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 }, + { 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* [3][1] */ + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 }, - { 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* [3][2] */ - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x53,0x4E,0x3D,0x2C, - 0x1C,0x0D,0x02,0x00,0x00,0x00,0x01,0x00 }, + { 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* [3][2] */ + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x53,0x4E,0x3D,0x2C, + 0x1C,0x0D,0x02,0x00,0x00,0x00,0x01,0x00 }, - { 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* [3][3] */ - 0x00,0x00,0xF7,0xAF,0x6F,0x55,0x1F,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 }, + { 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* [3][3] */ + 0x00,0x00,0xF7,0xAF,0x6F,0x55,0x1F,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 }, - { 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* [3][4] */ - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 }, + { 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* [3][4] */ + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 }, - { 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* [3][5] */ - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 }, + { 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* [3][5] */ + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 }, - { 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* [3][6] */ - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 }, + { 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* [3][6] */ + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 }, - { 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* [3][7] */ - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 } + { 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* [3][7] */ + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 } }, - { { 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* [4][0] */ - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 }, + { + { 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* [4][0] */ + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 }, - { 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* [4][1] */ - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x36,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 }, + { 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* [4][1] */ + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x36,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 }, - { 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x92,0x54, /* [4][2] */ - 0x38,0x23,0x00,0x01,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 }, + { 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x92,0x54, /* [4][2] */ + 0x38,0x23,0x00,0x01,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 }, - { 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x74,0x24,0x00,0x00,0x00,0x00,0x00,0x00, /* [4][3] */ - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 }, + { 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x74,0x24,0x00,0x00,0x00,0x00,0x00,0x00, /* [4][3] */ + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 }, - { 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* [4][4] */ - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 }, + { 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* [4][4] */ + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 }, - { 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* [4][5] */ - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 }, + { 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* [4][5] */ + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 }, - { 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* [4][6] */ - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 }, + { 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* [4][6] */ + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 }, - { 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* [4][7] */ - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 } + { 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* [4][7] */ + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 } } }; - int fdd_get_gap3_size(int rate, int size, int sector) { - return(fdd_gap3_sizes[rate][size][sector]); + return (fdd_gap3_sizes[rate][size][sector]); } - uint8_t fdd_sector_size_code(int size) { - int ret = 2; + uint8_t ret = 2; - switch(size) { - case 128: - ret = 0; - break; + switch (size) { + case 128: + ret = 0; + break; - case 256: - ret = 1; - break; + case 256: + ret = 1; + break; - case 512: - ret = 2; - break; + case 512: + ret = 2; + break; - case 1024: - ret = 3; - break; + case 1024: + ret = 3; + break; - case 2048: - ret = 4; - break; + case 2048: + ret = 4; + break; - case 4096: - ret = 5; - break; + case 4096: + ret = 5; + break; - case 8192: - ret = 6; - break; + case 8192: + ret = 6; + break; - case 16384: - ret = 7; - break; + case 16384: + ret = 7; + break; - default: - break; + default: + break; } - return(ret); + return ret; } - int fdd_sector_code_size(uint8_t code) { - return(128 << code); + return (128 << code); } - int fdd_bps_valid(uint16_t bps) { - int i; - - for (i=0; i<=8; i++) { - if (bps == (128 << i)) { - return 1; - } + for (uint8_t i = 0; i <= 8; i++) { + if (bps == (128 << i)) { + return 1; + } } - return(0); + return 0; } - int fdd_interleave(int sector, int skew, int spt) { - uint32_t add = (spt & 1); + uint32_t add = (spt & 1); uint32_t adjust = (spt >> 1); uint32_t adjusted_r; uint32_t skewed_i; - skewed_i = (sector + skew) % spt; + skewed_i = (sector + skew) % spt; adjusted_r = (skewed_i >> 1) + 1; if (skewed_i & 1) { - adjusted_r += (adjust + add); + adjusted_r += (adjust + add); } - return(adjusted_r); + return adjusted_r; } diff --git a/src/floppy/fdd_fdi.c b/src/floppy/fdd_fdi.c index 897fcfcdf..f14bf2cd4 100644 --- a/src/floppy/fdd_fdi.c +++ b/src/floppy/fdd_fdi.c @@ -1,23 +1,23 @@ /* - * 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. + * 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. + * This file is part of the 86Box distribution. * - * Implementation of the FDI floppy stream image format - * interface to the FDI2RAW module. + * Implementation of the FDI floppy stream image format + * interface to the FDI2RAW module. * * * - * Authors: Sarah Walker, - * Miran Grca, - * Fred N. van Kempen, + * Authors: Sarah Walker, + * Miran Grca, + * Fred N. van Kempen, * - * Copyright 2008-2018 Sarah Walker. - * Copyright 2016-2018 Miran Grca. - * Copyright 2018 Fred N. van Kempen. + * Copyright 2008-2018 Sarah Walker. + * Copyright 2016-2018 Miran Grca. + * Copyright 2018 Fred N. van Kempen. */ #include #include @@ -36,73 +36,67 @@ #include <86box/fdc.h> #include +typedef struct fdi_t { + FILE *fp; + FDI *h; -typedef struct { - FILE *f; - FDI *h; + int lasttrack; + int sides; + int track; + int tracklen[2][4]; + int trackindex[2][4]; - int lasttrack; - int sides; - int track; - int tracklen[2][4]; - int trackindex[2][4]; - - uint8_t track_data[2][4][256*1024]; - uint8_t track_timing[2][4][256*1024]; + uint8_t track_data[2][4][256 * 1024]; + uint8_t track_timing[2][4][256 * 1024]; } fdi_t; - -static fdi_t *fdi[FDD_NUM]; -static fdc_t *fdi_fdc; - +static fdi_t *fdi[FDD_NUM]; +static fdc_t *fdi_fdc; #ifdef ENABLE_FDI_LOG int fdi_do_log = ENABLE_FDI_LOG; - static void fdi_log(const char *fmt, ...) { - va_list ap; + va_list ap; - if (fdi_do_log) - { - va_start(ap, fmt); - pclog_ex(fmt, ap); - va_end(ap); - } + if (fdi_do_log) { + va_start(ap, fmt); + pclog_ex(fmt, ap); + va_end(ap); + } } #else -#define fdi_log(fmt, ...) +# define fdi_log(fmt, ...) #endif - static uint16_t disk_flags(int drive) { - fdi_t *dev = fdi[drive]; - uint16_t temp_disk_flags = 0x80; /* We ALWAYS claim to have extra bit cells, even if the actual amount is 0. */ + fdi_t *dev = fdi[drive]; + uint16_t temp_disk_flags = 0x80; /* We ALWAYS claim to have extra bit cells, even if the actual amount is 0. */ switch (fdi2raw_get_bit_rate(dev->h)) { - case 500: - temp_disk_flags |= 2; - break; + case 500: + temp_disk_flags |= 2; + break; - case 300: - case 250: - temp_disk_flags |= 0; - break; + case 300: + case 250: + temp_disk_flags |= 0; + break; - case 1000: - temp_disk_flags |= 4; - break; + case 1000: + temp_disk_flags |= 4; + break; - default: - temp_disk_flags |= 0; + default: + temp_disk_flags |= 0; } if (dev->sides == 2) - temp_disk_flags |= 8; + temp_disk_flags |= 8; /* * Tell the 86F handler that we will handle our @@ -110,39 +104,38 @@ disk_flags(int drive) */ temp_disk_flags |= 0x800; - return(temp_disk_flags); + return temp_disk_flags; } - static uint16_t side_flags(int drive) { - fdi_t *dev = fdi[drive]; + fdi_t *dev = fdi[drive]; uint16_t temp_side_flags = 0; switch (fdi2raw_get_bit_rate(dev->h)) { - case 500: - temp_side_flags = 0; - break; + case 500: + temp_side_flags = 0; + break; - case 300: - temp_side_flags = 1; - break; + case 300: + temp_side_flags = 1; + break; - case 250: - temp_side_flags = 2; - break; + case 250: + temp_side_flags = 2; + break; - case 1000: - temp_side_flags = 3; - break; + case 1000: + temp_side_flags = 3; + break; - default: - temp_side_flags = 2; + default: + temp_side_flags = 2; } if (fdi2raw_get_rotation(dev->h) == 360) - temp_side_flags |= 0x20; + temp_side_flags |= 0x20; /* * Set the encoding value to match that provided by the FDC. @@ -150,167 +143,163 @@ side_flags(int drive) */ temp_side_flags |= 0x08; - return(temp_side_flags); + return temp_side_flags; } - static int fdi_density(void) { - if (! fdc_is_mfm(fdi_fdc)) return(0); + if (!fdc_is_mfm(fdi_fdc)) + return 0; switch (fdc_get_bit_rate(fdi_fdc)) { - case 0: - return(2); + case 0: + return 2; - case 1: - return(1); + case 1: + return 1; - case 2: - return(1); + case 2: + return 1; - case 3: - case 5: - return(3); + case 3: + case 5: + return 3; - default: - break; + default: + break; } - return(1); + return 1; } - static int32_t extra_bit_cells(int drive, int side) { - fdi_t *dev = fdi[drive]; - int density = 0; - int raw_size = 0; - int is_300_rpm = 0; + const fdi_t *dev = fdi[drive]; + int density = 0; + int raw_size = 0; + int is_300_rpm = 0; density = fdi_density(); is_300_rpm = (fdd_getrpm(drive) == 300); switch (fdc_get_bit_rate(fdi_fdc)) { - case 0: - raw_size = is_300_rpm ? 200000 : 166666; - break; + case 0: + raw_size = is_300_rpm ? 200000 : 166666; + break; - case 1: - raw_size = is_300_rpm ? 120000 : 100000; - break; + case 1: + raw_size = is_300_rpm ? 120000 : 100000; + break; - case 2: - raw_size = is_300_rpm ? 100000 : 83333; - break; + case 2: + raw_size = is_300_rpm ? 100000 : 83333; + break; - case 3: - case 5: - raw_size = is_300_rpm ? 400000 : 333333; - break; + case 3: + case 5: + raw_size = is_300_rpm ? 400000 : 333333; + break; - default: - raw_size = is_300_rpm ? 100000 : 83333; + default: + raw_size = is_300_rpm ? 100000 : 83333; } - return((dev->tracklen[side][density] - raw_size)); + return (dev->tracklen[side][density] - raw_size); } - static void read_revolution(int drive) { fdi_t *dev = fdi[drive]; - int c, den, side; - int track = dev->track; + int c; + int den; + int track = dev->track; if (track > dev->lasttrack) { - for (den = 0; den < 4; den++) { - memset(dev->track_data[0][den], 0, 106096); - memset(dev->track_data[1][den], 0, 106096); - dev->tracklen[0][den] = dev->tracklen[1][den] = 100000; - } - return; + for (den = 0; den < 4; den++) { + memset(dev->track_data[0][den], 0, 106096); + memset(dev->track_data[1][den], 0, 106096); + dev->tracklen[0][den] = dev->tracklen[1][den] = 100000; + } + return; } for (den = 0; den < 4; den++) { - for (side = 0; side < dev->sides; side++) { - c = fdi2raw_loadtrack(dev->h, - (uint16_t *)dev->track_data[side][den], - (uint16_t *)dev->track_timing[side][den], - (track * dev->sides) + side, - &dev->tracklen[side][den], - &dev->trackindex[side][den], NULL, den); - if (! c) - memset(dev->track_data[side][den], 0, dev->tracklen[side][den]); - } + for (int side = 0; side < dev->sides; side++) { + c = fdi2raw_loadtrack(dev->h, + (uint16_t *) dev->track_data[side][den], + (uint16_t *) dev->track_timing[side][den], + (track * dev->sides) + side, + &dev->tracklen[side][den], + &dev->trackindex[side][den], NULL, den); + if (!c) + memset(dev->track_data[side][den], 0, dev->tracklen[side][den]); + } - if (dev->sides == 1) { - memset(dev->track_data[1][den], 0, 106096); - dev->tracklen[1][den] = 100000; - } + if (dev->sides == 1) { + memset(dev->track_data[1][den], 0, 106096); + dev->tracklen[1][den] = 100000; + } } } - static uint32_t index_hole_pos(int drive, int side) { - fdi_t *dev = fdi[drive]; - int density; + const fdi_t *dev = fdi[drive]; + int density; density = fdi_density(); - return(dev->trackindex[side][density]); + return (dev->trackindex[side][density]); } - static uint32_t get_raw_size(int drive, int side) { - fdi_t *dev = fdi[drive]; - int density; + const fdi_t *dev = fdi[drive]; + int density; density = fdi_density(); - return(dev->tracklen[side][density]); + return (dev->tracklen[side][density]); } - static uint16_t * encoded_data(int drive, int side) { - fdi_t *dev = fdi[drive]; - int density = 0; + fdi_t *dev = fdi[drive]; + int density = 0; density = fdi_density(); - return((uint16_t *)dev->track_data[side][density]); + return ((uint16_t *) dev->track_data[side][density]); } - void fdi_seek(int drive, int track) { fdi_t *dev = fdi[drive]; if (fdd_doublestep_40(drive)) { - if (fdi2raw_get_tpi(dev->h) < 2) - track /= 2; + if (fdi2raw_get_tpi(dev->h) < 2) + track /= 2; } d86f_set_cur_track(drive, track); - if (dev->f == NULL) return; + if (dev->fp == NULL) + return; if (track < 0) - track = 0; + track = 0; #if 0 if (track > dev->lasttrack) - track = dev->lasttrack - 1; + track = dev->lasttrack - 1; #endif dev->track = track; @@ -318,62 +307,61 @@ fdi_seek(int drive, int track) read_revolution(drive); } - void fdi_load(int drive, char *fn) { - char header[26]; + char header[26]; fdi_t *dev; writeprot[drive] = fwriteprot[drive] = 1; /* Allocate a drive block. */ - dev = (fdi_t *)malloc(sizeof(fdi_t)); + dev = (fdi_t *) malloc(sizeof(fdi_t)); if (dev == NULL) { - memset(floppyfns[drive], 0, sizeof(floppyfns[drive])); - return; + memset(floppyfns[drive], 0, sizeof(floppyfns[drive])); + return; } memset(dev, 0x00, sizeof(fdi_t)); d86f_unregister(drive); - dev->f = plat_fopen(fn, "rb"); - if (fread(header, 1, 25, dev->f) != 25) - fatal("fdi_load(): Error reading header\n"); - if (fseek(dev->f, 0, SEEK_SET) == -1) - fatal("fdi_load(): Error seeking to the beginning of the file\n"); + dev->fp = plat_fopen(fn, "rb"); + if (fread(header, 1, 25, dev->fp) != 25) + fatal("fdi_load(): Error reading header\n"); + if (fseek(dev->fp, 0, SEEK_SET) == -1) + fatal("fdi_load(): Error seeking to the beginning of the file\n"); header[25] = 0; if (strcmp(header, "Formatted Disk Image file") != 0) { - /* This is a Japanese FDI file. */ - fdi_log("fdi_load(): Japanese FDI file detected, redirecting to IMG loader\n"); - fclose(dev->f); - free(dev); - img_load(drive, fn); - return; + /* This is a Japanese FDI file. */ + fdi_log("fdi_load(): Japanese FDI file detected, redirecting to IMG loader\n"); + fclose(dev->fp); + free(dev); + img_load(drive, fn); + return; } /* Set up the drive unit. */ fdi[drive] = dev; - dev->h = fdi2raw_header(dev->f); + dev->h = fdi2raw_header(dev->fp); dev->lasttrack = fdi2raw_get_last_track(dev->h); - dev->sides = fdi2raw_get_last_head(dev->h) + 1; + dev->sides = fdi2raw_get_last_head(dev->h) + 1; /* Attach this format to the D86F engine. */ - d86f_handler[drive].disk_flags = disk_flags; - d86f_handler[drive].side_flags = side_flags; - d86f_handler[drive].writeback = null_writeback; - d86f_handler[drive].set_sector = null_set_sector; - d86f_handler[drive].write_data = null_write_data; + d86f_handler[drive].disk_flags = disk_flags; + d86f_handler[drive].side_flags = side_flags; + d86f_handler[drive].writeback = null_writeback; + d86f_handler[drive].set_sector = null_set_sector; + d86f_handler[drive].write_data = null_write_data; d86f_handler[drive].format_conditions = null_format_conditions; - d86f_handler[drive].extra_bit_cells = extra_bit_cells; - d86f_handler[drive].encoded_data = encoded_data; - d86f_handler[drive].read_revolution = read_revolution; - d86f_handler[drive].index_hole_pos = index_hole_pos; - d86f_handler[drive].get_raw_size = get_raw_size; - d86f_handler[drive].check_crc = 1; + d86f_handler[drive].extra_bit_cells = extra_bit_cells; + d86f_handler[drive].encoded_data = encoded_data; + d86f_handler[drive].read_revolution = read_revolution; + d86f_handler[drive].index_hole_pos = index_hole_pos; + d86f_handler[drive].get_raw_size = get_raw_size; + d86f_handler[drive].check_crc = 1; d86f_set_version(drive, D86FVER); d86f_common_handlers(drive); @@ -383,32 +371,31 @@ fdi_load(int drive, char *fn) fdi_log("Loaded as FDI\n"); } - void fdi_close(int drive) { fdi_t *dev = fdi[drive]; - if (dev == NULL) return; + if (dev == NULL) + return; d86f_unregister(drive); drives[drive].seek = NULL; if (dev->h) - fdi2raw_header_free(dev->h); + fdi2raw_header_free(dev->h); - if (dev->f) - fclose(dev->f); + if (dev->fp) + fclose(dev->fp); /* Release the memory. */ free(dev); fdi[drive] = NULL; } - void fdi_set_fdc(void *fdc) { - fdi_fdc = (fdc_t *)fdc; + fdi_fdc = (fdc_t *) fdc; } diff --git a/src/floppy/fdd_imd.c b/src/floppy/fdd_imd.c index 5315f7e97..a5cd8f056 100644 --- a/src/floppy/fdd_imd.c +++ b/src/floppy/fdd_imd.c @@ -1,20 +1,20 @@ /* - * 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. + * 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. + * This file is part of the 86Box distribution. * - * Implementation of the IMD floppy image format. + * Implementation of the IMD floppy image format. * * * - * Authors: Fred N. van Kempen, - * Miran Grca, + * Authors: Fred N. van Kempen, + * Miran Grca, * - * Copyright 2016-2019 Miran Grca. - * Copyright 2018,2019 Fred N. van Kempen. + * Copyright 2016-2019 Miran Grca. + * Copyright 2018-2019 Fred N. van Kempen. */ #include #include @@ -31,290 +31,289 @@ #include <86box/fdd_imd.h> #include <86box/fdc.h> - -typedef struct { - uint8_t is_present; - uint32_t file_offs; - uint8_t params[5]; - uint32_t r_map_offs; - uint32_t c_map_offs; - uint32_t h_map_offs; - uint32_t n_map_offs; - uint32_t data_offs; - uint32_t sector_data_offs[255]; - uint32_t sector_data_size[255]; - uint32_t gap3_len; - uint16_t side_flags; - uint8_t max_sector_size; +typedef struct imd_track_t { + uint8_t is_present; + uint32_t file_offs; + uint8_t params[5]; + uint32_t r_map_offs; + uint32_t c_map_offs; + uint32_t h_map_offs; + uint32_t n_map_offs; + uint32_t data_offs; + uint32_t sector_data_offs[255]; + uint32_t sector_data_size[255]; + uint32_t gap3_len; + uint16_t side_flags; + uint8_t max_sector_size; } imd_track_t; -typedef struct { - FILE *f; - char *buffer; - uint32_t start_offs; - int track_count, sides; - int track; - uint16_t disk_flags; - int track_width; - imd_track_t tracks[256][2]; - uint16_t current_side_flags[2]; - uint8_t xdf_ordered_pos[256][2]; - uint8_t interleave_ordered_pos[256][2]; - char *current_data[2]; - uint8_t track_buffer[2][25000]; +typedef struct imd_t { + FILE *fp; + char *buffer; + uint32_t start_offs; + int track_count; + int sides; + int track; + uint16_t disk_flags; + int track_width; + imd_track_t tracks[256][2]; + uint16_t current_side_flags[2]; + uint8_t xdf_ordered_pos[256][2]; + uint8_t interleave_ordered_pos[256][2]; + char *current_data[2]; + uint8_t track_buffer[2][25000]; } imd_t; - -static imd_t *imd[FDD_NUM]; -static fdc_t *imd_fdc; - +static imd_t *imd[FDD_NUM]; +static fdc_t *imd_fdc; #ifdef ENABLE_IMD_LOG int imd_do_log = ENABLE_IMD_LOG; - static void imd_log(const char *fmt, ...) { - va_list ap; + va_list ap; - if (imd_do_log) - { - va_start(ap, fmt); - pclog_ex(fmt, ap); - va_end(ap); - } + if (imd_do_log) { + va_start(ap, fmt); + pclog_ex(fmt, ap); + va_end(ap); + } } #else -#define imd_log(fmt, ...) +# define imd_log(fmt, ...) #endif - static uint32_t get_raw_tsize(int side_flags, int slower_rpm) { uint32_t size; - switch(side_flags & 0x27) { - case 0x22: - size = slower_rpm ? 5314 : 5208; - break; + switch (side_flags & 0x27) { + case 0x22: + size = slower_rpm ? 5314 : 5208; + break; - default: - case 0x02: - case 0x21: - size = slower_rpm ? 6375 : 6250; - break; + default: + case 0x02: + case 0x21: + size = slower_rpm ? 6375 : 6250; + break; - case 0x01: - size = slower_rpm ? 7650 : 7500; - break; + case 0x01: + size = slower_rpm ? 7650 : 7500; + break; - case 0x20: - size = slower_rpm ? 10629 : 10416; - break; + case 0x20: + size = slower_rpm ? 10629 : 10416; + break; - case 0x00: - size = slower_rpm ? 12750 : 12500; - break; + case 0x00: + size = slower_rpm ? 12750 : 12500; + break; - case 0x23: - size = slower_rpm ? 21258 : 20833; - break; + case 0x23: + size = slower_rpm ? 21258 : 20833; + break; - case 0x03: - size = slower_rpm ? 25500 : 25000; - break; + case 0x03: + size = slower_rpm ? 25500 : 25000; + break; - case 0x25: - size = slower_rpm ? 42517 : 41666; - break; + case 0x25: + size = slower_rpm ? 42517 : 41666; + break; - case 0x05: - size = slower_rpm ? 51000 : 50000; - break; + case 0x05: + size = slower_rpm ? 51000 : 50000; + break; } - return(size); + return size; } - static int track_is_xdf(int drive, int side, int track) { - imd_t *dev = imd[drive]; - int i, effective_sectors, xdf_sectors; - int high_sectors, low_sectors; - int max_high_id, expected_high_count, expected_low_count; - uint8_t *r_map; - uint8_t *n_map; - char *data_base; - char *cur_data; + imd_t *dev = imd[drive]; + int effective_sectors; + int xdf_sectors; + int high_sectors; + int low_sectors; + int max_high_id; + int expected_high_count; + int expected_low_count; + const uint8_t *r_map; + const uint8_t *n_map; effective_sectors = xdf_sectors = high_sectors = low_sectors = 0; - for (i = 0; i < 256; i++) - dev->xdf_ordered_pos[i][side] = 0; + for (uint16_t i = 0; i < 256; i++) + dev->xdf_ordered_pos[i][side] = 0; - if (dev->tracks[track][side].params[2] & 0xC0) return(0); + if (dev->tracks[track][side].params[2] & 0xC0) + return 0; - if ((dev->tracks[track][side].params[3] != 16) && - (dev->tracks[track][side].params[3] != 19)) return(0); + if ((dev->tracks[track][side].params[3] != 16) && (dev->tracks[track][side].params[3] != 19)) + return 0; - r_map = (uint8_t *)(dev->buffer + dev->tracks[track][side].r_map_offs); - data_base = dev->buffer + dev->tracks[track][side].data_offs; + r_map = (uint8_t *) (dev->buffer + dev->tracks[track][side].r_map_offs); - if (! track) { - if (dev->tracks[track][side].params[4] != 2) return(0); + if (!track) { + if (dev->tracks[track][side].params[4] != 2) + return 0; - if (! side) { - max_high_id = (dev->tracks[track][side].params[3] == 19) ? 0x8B : 0x88; - expected_high_count = (dev->tracks[track][side].params[3] == 19) ? 0x0B : 0x08; - expected_low_count = 8; - } else { - max_high_id = (dev->tracks[track][side].params[3] == 19) ? 0x93 : 0x90; - expected_high_count = (dev->tracks[track][side].params[3] == 19) ? 0x13 : 0x10; - expected_low_count = 0; - } + if (!side) { + max_high_id = (dev->tracks[track][side].params[3] == 19) ? 0x8B : 0x88; + expected_high_count = (dev->tracks[track][side].params[3] == 19) ? 0x0B : 0x08; + expected_low_count = 8; + } else { + max_high_id = (dev->tracks[track][side].params[3] == 19) ? 0x93 : 0x90; + expected_high_count = (dev->tracks[track][side].params[3] == 19) ? 0x13 : 0x10; + expected_low_count = 0; + } - for (i = 0; i < dev->tracks[track][side].params[3]; i++) { - if ((r_map[i] >= 0x81) && (r_map[i] <= max_high_id)) { - high_sectors++; - dev->xdf_ordered_pos[(int) r_map[i]][side] = i; - } - if ((r_map[i] >= 0x01) && (r_map[i] <= 0x08)) { - low_sectors++; - dev->xdf_ordered_pos[(int) r_map[i]][side] = i; - } - if ((high_sectors == expected_high_count) && (low_sectors == expected_low_count)) { - dev->current_side_flags[side] = (dev->tracks[track][side].params[3] == 19) ? 0x08 : 0x28; - return((dev->tracks[track][side].params[3] == 19) ? 2 : 1); - } - } - return(0); + for (uint8_t i = 0; i < dev->tracks[track][side].params[3]; i++) { + if ((r_map[i] >= 0x81) && (r_map[i] <= max_high_id)) { + high_sectors++; + dev->xdf_ordered_pos[(int) r_map[i]][side] = i; + } + if ((r_map[i] >= 0x01) && (r_map[i] <= 0x08)) { + low_sectors++; + dev->xdf_ordered_pos[(int) r_map[i]][side] = i; + } + if ((high_sectors == expected_high_count) && (low_sectors == expected_low_count)) { + dev->current_side_flags[side] = (dev->tracks[track][side].params[3] == 19) ? 0x08 : 0x28; + return ((dev->tracks[track][side].params[3] == 19) ? 2 : 1); + } + } + return 0; } else { - if (dev->tracks[track][side].params[4] != 0xFF) return(0); + if (dev->tracks[track][side].params[4] != 0xFF) + return 0; - n_map = (uint8_t *) (dev->buffer + dev->tracks[track][side].n_map_offs); + n_map = (uint8_t *) (dev->buffer + dev->tracks[track][side].n_map_offs); - cur_data = data_base; - for (i = 0; i < dev->tracks[track][side].params[3]; i++) { - effective_sectors++; - if (!(r_map[i]) && !(n_map[i])) - effective_sectors--; + for (uint8_t i = 0; i < dev->tracks[track][side].params[3]; i++) { + effective_sectors++; + if (!(r_map[i]) && !(n_map[i])) + effective_sectors--; - if (r_map[i] == (n_map[i] | 0x80)) { - xdf_sectors++; - dev->xdf_ordered_pos[(int) r_map[i]][side] = i; - } - cur_data += (128 << ((uint32_t) n_map[i])); - } + if (r_map[i] == (n_map[i] | 0x80)) { + xdf_sectors++; + dev->xdf_ordered_pos[(int) r_map[i]][side] = i; + } + } - if ((effective_sectors == 3) && (xdf_sectors == 3)) { - dev->current_side_flags[side] = 0x28; - return(1); /* 5.25" 2HD XDF */ - } + if ((effective_sectors == 3) && (xdf_sectors == 3)) { + dev->current_side_flags[side] = 0x28; + return 1; /* 5.25" 2HD XDF */ + } - if ((effective_sectors == 4) && (xdf_sectors == 4)) { - dev->current_side_flags[side] = 0x08; - return(2); /* 3.5" 2HD XDF */ - } + if ((effective_sectors == 4) && (xdf_sectors == 4)) { + dev->current_side_flags[side] = 0x08; + return 2; /* 3.5" 2HD XDF */ + } - return(0); + return 0; } - - return(0); } - static int track_is_interleave(int drive, int side, int track) { - imd_t *dev = imd[drive]; - int i, effective_sectors; - char *r_map; - int track_spt; + imd_t *dev = imd[drive]; + int effective_sectors; + const char *r_map; + int track_spt; effective_sectors = 0; - for (i = 0; i < 256; i++) - dev->interleave_ordered_pos[i][side] = 0; + for (uint16_t i = 0; i < 256; i++) + dev->interleave_ordered_pos[i][side] = 0; track_spt = dev->tracks[track][side].params[3]; r_map = dev->buffer + dev->tracks[track][side].r_map_offs; - if (dev->tracks[track][side].params[2] & 0xC0) return(0); + if (dev->tracks[track][side].params[2] & 0xC0) + return 0; - if (track_spt != 21) return(0); + if (track_spt != 21) + return 0; - if (dev->tracks[track][side].params[4] != 2) return(0); + if (dev->tracks[track][side].params[4] != 2) + return 0; - for (i = 0; i < track_spt; i++) { - if ((r_map[i] >= 1) && (r_map[i] <= track_spt)) { - effective_sectors++; - dev->interleave_ordered_pos[(int) r_map[i]][side] = i; - } + for (int i = 0; i < track_spt; i++) { + if ((r_map[i] >= 1) && (r_map[i] <= track_spt)) { + effective_sectors++; + dev->interleave_ordered_pos[(int) r_map[i]][side] = i; + } } - if (effective_sectors == track_spt) return(1); + if (effective_sectors == track_spt) + return 1; - return(0); + return 0; } - static void sector_to_buffer(int drive, int track, int side, uint8_t *buffer, int sector, int len) { - imd_t *dev = imd[drive]; - int type = dev->buffer[dev->tracks[track][side].sector_data_offs[sector]]; - uint8_t fill_char; + const imd_t *dev = imd[drive]; + int type = dev->buffer[dev->tracks[track][side].sector_data_offs[sector]]; + uint8_t fill_char; if (type == 0) - memset(buffer, 0x00, len); - else { - if (type & 1) - memcpy(buffer, &(dev->buffer[dev->tracks[track][side].sector_data_offs[sector] + 1]), len); - else { - fill_char = dev->buffer[dev->tracks[track][side].sector_data_offs[sector] + 1]; - memset(buffer, fill_char, len); - } + memset(buffer, 0x00, len); + else { + if (type & 1) + memcpy(buffer, &(dev->buffer[dev->tracks[track][side].sector_data_offs[sector] + 1]), len); + else { + fill_char = dev->buffer[dev->tracks[track][side].sector_data_offs[sector] + 1]; + memset(buffer, fill_char, len); + } } } - static void imd_seek(int drive, int track) { - uint32_t track_buf_pos[2] = { 0, 0 }; - uint8_t id[4] = { 0, 0, 0, 0 }; - uint8_t type; - imd_t *dev = imd[drive]; - int sector, current_pos; - int side, c = 0, h, n; - int ssize = 512; - int track_rate = 0; - int track_gap2 = 22; - int track_gap3 = 12; - int xdf_type = 0; - int interleave_type = 0; - int is_trackx = 0; - int xdf_spt = 0; - int xdf_sector = 0; - int ordered_pos = 0; - int real_sector = 0; - int actual_sector = 0; - char *c_map = NULL; - char *h_map = NULL; - char *r_map; - char *n_map = NULL; - uint8_t *data; - int flags = 0x00; + uint32_t track_buf_pos[2] = { 0, 0 }; + uint8_t id[4] = { 0, 0, 0, 0 }; + uint8_t type; + imd_t *dev = imd[drive]; + int sector; + int current_pos; + int c = 0; + int h; + int n; + int ssize = 512; + int track_rate = 0; + int track_gap2 = 22; + int track_gap3 = 12; + int xdf_type = 0; + int interleave_type = 0; + int is_trackx = 0; + int xdf_spt = 0; + int xdf_sector = 0; + int ordered_pos = 0; + int real_sector = 0; + int actual_sector = 0; + const char *c_map = NULL; + const char *h_map = NULL; + const char *r_map; + const char *n_map = NULL; + uint8_t *data; + int flags = 0x00; - if (dev->f == NULL) return; + if (dev->fp == NULL) + return; if (!dev->track_width && fdd_doublestep_40(drive)) - track /= 2; + track /= 2; d86f_set_cur_track(drive, track); @@ -331,584 +330,588 @@ imd_seek(int drive, int track) d86f_destroy_linked_lists(drive, 0); d86f_destroy_linked_lists(drive, 1); - d86f_zero_track(drive); + d86f_zero_track(drive); if (track > dev->track_count) - return; + return; - for (side = 0; side < dev->sides; side++) { - if (!dev->tracks[track][side].is_present) - continue; + for (int side = 0; side < dev->sides; side++) { + if (!dev->tracks[track][side].is_present) + continue; - track_rate = dev->current_side_flags[side] & 7; - if (!track_rate && (dev->current_side_flags[side] & 0x20)) - track_rate = 4; - if ((dev->current_side_flags[side] & 0x27) == 0x21) - track_rate = 2; + track_rate = dev->current_side_flags[side] & 7; + if (!track_rate && (dev->current_side_flags[side] & 0x20)) + track_rate = 4; + if ((dev->current_side_flags[side] & 0x27) == 0x21) + track_rate = 2; - r_map = dev->buffer + dev->tracks[track][side].r_map_offs; - h = dev->tracks[track][side].params[2]; - if (h & 0x80) - c_map = dev->buffer + dev->tracks[track][side].c_map_offs; - else - c = dev->tracks[track][side].params[1]; + r_map = dev->buffer + dev->tracks[track][side].r_map_offs; + h = dev->tracks[track][side].params[2]; + if (h & 0x80) + c_map = dev->buffer + dev->tracks[track][side].c_map_offs; + else + c = dev->tracks[track][side].params[1]; - if (h & 0x40) - h_map = dev->buffer + dev->tracks[track][side].h_map_offs; + if (h & 0x40) + h_map = dev->buffer + dev->tracks[track][side].h_map_offs; - n = dev->tracks[track][side].params[4]; - if (n == 0xFF) { - n_map = dev->buffer + dev->tracks[track][side].n_map_offs; - track_gap3 = gap3_sizes[track_rate][(int) n_map[0]][dev->tracks[track][side].params[3]]; - } else { - track_gap3 = gap3_sizes[track_rate][n][dev->tracks[track][side].params[3]]; - } + n = dev->tracks[track][side].params[4]; + if (n == 0xFF) { + n_map = dev->buffer + dev->tracks[track][side].n_map_offs; + track_gap3 = gap3_sizes[track_rate][(int) n_map[0]][dev->tracks[track][side].params[3]]; + } else { + track_gap3 = gap3_sizes[track_rate][n][dev->tracks[track][side].params[3]]; + } - if (! track_gap3) - track_gap3 = dev->tracks[track][side].gap3_len; + if (!track_gap3) + track_gap3 = dev->tracks[track][side].gap3_len; - xdf_type = track_is_xdf(drive, side, track); + xdf_type = track_is_xdf(drive, side, track); - interleave_type = track_is_interleave(drive, side, track); + interleave_type = track_is_interleave(drive, side, track); - current_pos = d86f_prepare_pretrack(drive, side, 0); + current_pos = d86f_prepare_pretrack(drive, side, 0); - if (! xdf_type) { - for (sector = 0; sector < dev->tracks[track][side].params[3]; sector++) { - if (interleave_type == 0) { - real_sector = r_map[sector]; - actual_sector = sector; - } else { - real_sector = dmf_r[sector]; - actual_sector = dev->interleave_ordered_pos[real_sector][side]; - } - id[0] = (h & 0x80) ? c_map[actual_sector] : c; - id[1] = (h & 0x40) ? h_map[actual_sector] : (h & 1); - id[2] = real_sector; - id[3] = (n == 0xFF) ? n_map[actual_sector] : n; - data = dev->track_buffer[side] + track_buf_pos[side]; - type = dev->buffer[dev->tracks[track][side].sector_data_offs[actual_sector]]; - type = (type >> 1) & 7; - flags = 0x00; - if ((type == 2) || (type == 4)) - flags |= SECTOR_DELETED_DATA; - if ((type == 3) || (type == 4)) - flags |= SECTOR_CRC_ERROR; + if (!xdf_type) { + for (sector = 0; sector < dev->tracks[track][side].params[3]; sector++) { + if (interleave_type == 0) { + real_sector = r_map[sector]; + actual_sector = sector; + } else { + real_sector = dmf_r[sector]; + actual_sector = dev->interleave_ordered_pos[real_sector][side]; + } + id[0] = (h & 0x80) ? c_map[actual_sector] : c; + id[1] = (h & 0x40) ? h_map[actual_sector] : (h & 1); + id[2] = real_sector; + id[3] = (n == 0xFF) ? n_map[actual_sector] : n; + data = dev->track_buffer[side] + track_buf_pos[side]; + type = dev->buffer[dev->tracks[track][side].sector_data_offs[actual_sector]]; + type = (type >> 1) & 7; + flags = 0x00; + if ((type == 2) || (type == 4)) + flags |= SECTOR_DELETED_DATA; + if ((type == 3) || (type == 4)) + flags |= SECTOR_CRC_ERROR; - if (((flags & 0x02) || (id[3] > dev->tracks[track][side].max_sector_size)) && !fdd_get_turbo(drive)) - ssize = 3; - else - ssize = 128 << ((uint32_t) id[3]); + if (((flags & 0x02) || (id[3] > dev->tracks[track][side].max_sector_size)) && !fdd_get_turbo(drive)) + ssize = 3; + else + ssize = 128 << ((uint32_t) id[3]); - sector_to_buffer(drive, track, side, data, actual_sector, ssize); + sector_to_buffer(drive, track, side, data, actual_sector, ssize); - current_pos = d86f_prepare_sector(drive, side, current_pos, id, data, ssize, 22, track_gap3, flags); - track_buf_pos[side] += ssize; + current_pos = d86f_prepare_sector(drive, side, current_pos, id, data, ssize, 22, track_gap3, flags); + track_buf_pos[side] += ssize; - if (sector == 0) - d86f_initialize_last_sector_id(drive, id[0], id[1], id[2], id[3]); - } - } else { - xdf_type--; - xdf_spt = xdf_physical_sectors[xdf_type][is_trackx]; - for (sector = 0; sector < xdf_spt; sector++) { - xdf_sector = (side * xdf_spt) + sector; - id[0] = track; - id[1] = side; - id[2] = xdf_disk_layout[xdf_type][is_trackx][xdf_sector].id.r; - id[3] = is_trackx ? (id[2] & 7) : 2; - ordered_pos = dev->xdf_ordered_pos[id[2]][side]; + if (sector == 0) + d86f_initialize_last_sector_id(drive, id[0], id[1], id[2], id[3]); + } + } else { + xdf_type--; + xdf_spt = xdf_physical_sectors[xdf_type][is_trackx]; + for (sector = 0; sector < xdf_spt; sector++) { + xdf_sector = (side * xdf_spt) + sector; + id[0] = track; + id[1] = side; + id[2] = xdf_disk_layout[xdf_type][is_trackx][xdf_sector].id.r; + id[3] = is_trackx ? (id[2] & 7) : 2; + ordered_pos = dev->xdf_ordered_pos[id[2]][side]; - data = dev->track_buffer[side] + track_buf_pos[side]; - type = dev->buffer[dev->tracks[track][side].sector_data_offs[ordered_pos]]; - type = ((type - 1) >> 1) & 7; - flags = 0x00; - if (type & 0x01) - flags |= SECTOR_DELETED_DATA; - if (type & 0x02) - flags |= SECTOR_CRC_ERROR; + data = dev->track_buffer[side] + track_buf_pos[side]; + type = dev->buffer[dev->tracks[track][side].sector_data_offs[ordered_pos]]; + type = ((type - 1) >> 1) & 7; + flags = 0x00; + if (type & 0x01) + flags |= SECTOR_DELETED_DATA; + if (type & 0x02) + flags |= SECTOR_CRC_ERROR; - if (((flags & 0x02) || (id[3] > dev->tracks[track][side].max_sector_size)) && !fdd_get_turbo(drive)) - ssize = 3; - else - ssize = 128 << ((uint32_t) id[3]); + if (((flags & 0x02) || (id[3] > dev->tracks[track][side].max_sector_size)) && !fdd_get_turbo(drive)) + ssize = 3; + else + ssize = 128 << ((uint32_t) id[3]); - sector_to_buffer(drive, track, side, data, ordered_pos, ssize); + sector_to_buffer(drive, track, side, data, ordered_pos, ssize); - if (is_trackx) - current_pos = d86f_prepare_sector(drive, side, xdf_trackx_spos[xdf_type][xdf_sector], id, data, ssize, track_gap2, xdf_gap3_sizes[xdf_type][is_trackx], flags); - else - current_pos = d86f_prepare_sector(drive, side, current_pos, id, data, ssize, track_gap2, xdf_gap3_sizes[xdf_type][is_trackx], flags); + if (is_trackx) + current_pos = d86f_prepare_sector(drive, side, xdf_trackx_spos[xdf_type][xdf_sector], id, data, ssize, track_gap2, xdf_gap3_sizes[xdf_type][is_trackx], flags); + else + current_pos = d86f_prepare_sector(drive, side, current_pos, id, data, ssize, track_gap2, xdf_gap3_sizes[xdf_type][is_trackx], flags); - track_buf_pos[side] += ssize; + track_buf_pos[side] += ssize; - if (sector == 0) - d86f_initialize_last_sector_id(drive, id[0], id[1], id[2], id[3]); - } - } + if (sector == 0) + d86f_initialize_last_sector_id(drive, id[0], id[1], id[2], id[3]); + } + } } } - static uint16_t disk_flags(int drive) { - imd_t *dev = imd[drive]; + const imd_t *dev = imd[drive]; - return(dev->disk_flags); + return (dev->disk_flags); } - static uint16_t side_flags(int drive) { - imd_t *dev = imd[drive]; - int side = 0; - uint16_t sflags = 0; + const imd_t *dev = imd[drive]; + int side = 0; + uint16_t sflags = 0; - side = fdd_get_head(drive); + side = fdd_get_head(drive); sflags = dev->current_side_flags[side]; - return(sflags); + return sflags; } - static void set_sector(int drive, int side, uint8_t c, uint8_t h, uint8_t r, uint8_t n) { - imd_t *dev = imd[drive]; - int track = dev->track; - int i, sc, sh, sn; - char *c_map = NULL, *h_map = NULL, *r_map = NULL, *n_map = NULL; - uint8_t id[4] = { 0, 0, 0, 0 }; - sc = dev->tracks[track][side].params[1]; - sh = dev->tracks[track][side].params[2]; - sn = dev->tracks[track][side].params[4]; + imd_t *dev = imd[drive]; + int track = dev->track; + int sc; + int sh; + int sn; + const char *c_map = NULL; + const char *h_map = NULL; + const char *r_map = NULL; + const char *n_map = NULL; + uint8_t id[4] = { 0, 0, 0, 0 }; + sc = dev->tracks[track][side].params[1]; + sh = dev->tracks[track][side].params[2]; + sn = dev->tracks[track][side].params[4]; if (sh & 0x80) - c_map = dev->buffer + dev->tracks[track][side].c_map_offs; + c_map = dev->buffer + dev->tracks[track][side].c_map_offs; if (sh & 0x40) - h_map = dev->buffer + dev->tracks[track][side].h_map_offs; + h_map = dev->buffer + dev->tracks[track][side].h_map_offs; r_map = dev->buffer + dev->tracks[track][side].r_map_offs; if (sn == 0xFF) - n_map = dev->buffer + dev->tracks[track][side].n_map_offs; + n_map = dev->buffer + dev->tracks[track][side].n_map_offs; - if (c != dev->track) return; + if (c != dev->track) + return; - for (i = 0; i < dev->tracks[track][side].params[3]; i++) { - id[0] = (sh & 0x80) ? c_map[i] : sc; - id[1] = (sh & 0x40) ? h_map[i] : (sh & 1); - id[2] = r_map[i]; - id[3] = (sn == 0xFF) ? n_map[i] : sn; - if ((id[0] == c) && (id[1] == h) && (id[2] == r) && (id[3] == n)) { - dev->current_data[side] = dev->buffer + dev->tracks[track][side].sector_data_offs[i]; - } + for (uint8_t i = 0; i < dev->tracks[track][side].params[3]; i++) { + id[0] = (sh & 0x80) ? c_map[i] : sc; + id[1] = (sh & 0x40) ? h_map[i] : (sh & 1); + id[2] = r_map[i]; + id[3] = (sn == 0xFF) ? n_map[i] : sn; + if ((id[0] == c) && (id[1] == h) && (id[2] == r) && (id[3] == n)) { + dev->current_data[side] = dev->buffer + dev->tracks[track][side].sector_data_offs[i]; + } } } - static void imd_writeback(int drive) { - imd_t *dev = imd[drive]; - int side; - int track = dev->track; - int i = 0; - char *n_map = 0; - uint8_t h, n, spt; - uint32_t ssize; + imd_t *dev = imd[drive]; + int track = dev->track; + const char *n_map = 0; + uint8_t h; + uint8_t n; + uint8_t spt; + uint32_t ssize; - if (writeprot[drive]) return; + if (writeprot[drive]) + return; - for (side = 0; side < dev->sides; side++) { - if (dev->tracks[track][side].is_present) { - fseek(dev->f, dev->tracks[track][side].file_offs, SEEK_SET); - h = dev->tracks[track][side].params[2]; - spt = dev->tracks[track][side].params[3]; - n = dev->tracks[track][side].params[4]; - fwrite(dev->tracks[track][side].params, 1, 5, dev->f); + for (int side = 0; side < dev->sides; side++) { + if (dev->tracks[track][side].is_present) { + fseek(dev->fp, dev->tracks[track][side].file_offs, SEEK_SET); + h = dev->tracks[track][side].params[2]; + spt = dev->tracks[track][side].params[3]; + n = dev->tracks[track][side].params[4]; + fwrite(dev->tracks[track][side].params, 1, 5, dev->fp); - if (h & 0x80) - fwrite(dev->buffer + dev->tracks[track][side].c_map_offs, 1, spt, dev->f); + if (h & 0x80) + fwrite(dev->buffer + dev->tracks[track][side].c_map_offs, 1, spt, dev->fp); - if (h & 0x40) - fwrite(dev->buffer + dev->tracks[track][side].h_map_offs, 1, spt, dev->f); + if (h & 0x40) + fwrite(dev->buffer + dev->tracks[track][side].h_map_offs, 1, spt, dev->fp); - if (n == 0xFF) { - n_map = dev->buffer + dev->tracks[track][side].n_map_offs; - fwrite(n_map, 1, spt, dev->f); - } - for (i = 0; i < spt; i++) { - ssize = (n == 0xFF) ? n_map[i] : n; - ssize = 128 << ssize; - fwrite(dev->buffer + dev->tracks[track][side].sector_data_offs[i], 1, ssize, dev->f); - } - } + if (n == 0xFF) { + n_map = dev->buffer + dev->tracks[track][side].n_map_offs; + fwrite(n_map, 1, spt, dev->fp); + } + for (uint8_t i = 0; i < spt; i++) { + ssize = (n == 0xFF) ? n_map[i] : n; + ssize = 128 << ssize; + fwrite(dev->buffer + dev->tracks[track][side].sector_data_offs[i], 1, ssize, dev->fp); + } + } } } - static uint8_t poll_read_data(int drive, int side, uint16_t pos) { - imd_t *dev = imd[drive]; - int type = dev->current_data[side][0]; + const imd_t *dev = imd[drive]; + int type = dev->current_data[side][0]; - if ((type == 0) || (type > 8)) return(0xf6); /* Should never happen. */ + if ((type == 0) || (type > 8)) + return 0xf6; /* Should never happen. */ if (type & 1) - return(dev->current_data[side][pos + 1]); + return (dev->current_data[side][pos + 1]); else - return(dev->current_data[side][1]); + return (dev->current_data[side][1]); } - static void poll_write_data(int drive, int side, uint16_t pos, uint8_t data) { - imd_t *dev = imd[drive]; - int type = dev->current_data[side][0]; + const imd_t *dev = imd[drive]; + int type = dev->current_data[side][0]; - if (writeprot[drive]) return; + if (writeprot[drive]) + return; - if ((type & 1) || (type == 0) || (type > 8)) return; /* Should never happen. */ + if ((type & 1) || (type == 0) || (type > 8)) + return; /* Should never happen. */ dev->current_data[side][pos + 1] = data; } - static int format_conditions(int drive) { - imd_t *dev = imd[drive]; - int track = dev->track; - int side, temp; + const imd_t *dev = imd[drive]; + int track = dev->track; + int side; + int temp; side = fdd_get_head(drive); temp = (fdc_get_format_sectors(imd_fdc) == dev->tracks[track][side].params[3]); temp = temp && (fdc_get_format_n(imd_fdc) == dev->tracks[track][side].params[4]); - return(temp); + return temp; } - void imd_init(void) { memset(imd, 0x00, sizeof(imd)); } - void imd_load(int drive, char *fn) { - uint32_t magic = 0; - uint32_t fsize = 0; - char *buffer; - char *buffer2; - imd_t *dev; - int i = 0; - int track_spt = 0; - int sector_size = 0; - int track = 0; - int side = 0; - int extra = 0; - uint32_t last_offset = 0; - uint32_t data_size = 512; - uint32_t mfm = 0; - uint32_t pre_sector = 0; - uint32_t track_total = 0; - uint32_t raw_tsize = 0; - uint32_t minimum_gap3 = 0; - uint32_t minimum_gap4 = 0; - uint8_t converted_rate; - uint8_t type; - int size_diff, gap_sum; + uint32_t magic = 0; + uint32_t fsize = 0; + const char *buffer; + const char *buffer2; + imd_t *dev; + int track_spt = 0; + int sector_size = 0; + int track = 0; + int side = 0; + int extra = 0; + uint32_t last_offset = 0; + uint32_t data_size = 512; + uint32_t mfm = 0; + uint32_t pre_sector = 0; + uint32_t track_total = 0; + uint32_t raw_tsize = 0; + uint32_t minimum_gap3 = 0; + uint32_t minimum_gap4 = 0; + uint8_t converted_rate; + uint8_t type; + int size_diff; + int gap_sum; d86f_unregister(drive); writeprot[drive] = 0; /* Allocate a drive block. */ - dev = (imd_t *)malloc(sizeof(imd_t)); + dev = (imd_t *) malloc(sizeof(imd_t)); memset(dev, 0x00, sizeof(imd_t)); - dev->f = plat_fopen(fn, "rb+"); - if (dev->f == NULL) { - dev->f = plat_fopen(fn, "rb"); - if (dev->f == NULL) { - memset(floppyfns[drive], 0, sizeof(floppyfns[drive])); - free(dev); - return; - } - writeprot[drive] = 1; + dev->fp = plat_fopen(fn, "rb+"); + if (dev->fp == NULL) { + dev->fp = plat_fopen(fn, "rb"); + if (dev->fp == NULL) { + memset(floppyfns[drive], 0, sizeof(floppyfns[drive])); + free(dev); + return; + } + writeprot[drive] = 1; } if (ui_writeprot[drive]) - writeprot[drive] = 1; + writeprot[drive] = 1; fwriteprot[drive] = writeprot[drive]; - if (fseek(dev->f, 0, SEEK_SET) == -1) - fatal("imd_load(): Error seeking to the beginning of the file\n"); - if (fread(&magic, 1, 4, dev->f) != 4) - fatal("imd_load(): Error reading the magic number\n"); + if (fseek(dev->fp, 0, SEEK_SET) == -1) + fatal("imd_load(): Error seeking to the beginning of the file\n"); + if (fread(&magic, 1, 4, dev->fp) != 4) + fatal("imd_load(): Error reading the magic number\n"); if (magic != 0x20444D49) { - imd_log("IMD: Not a valid ImageDisk image\n"); - fclose(dev->f); - free(dev); - memset(floppyfns[drive], 0, sizeof(floppyfns[drive])); - return; + imd_log("IMD: Not a valid ImageDisk image\n"); + fclose(dev->fp); + free(dev); + memset(floppyfns[drive], 0, sizeof(floppyfns[drive])); + return; } else - imd_log("IMD: Valid ImageDisk image\n"); + imd_log("IMD: Valid ImageDisk image\n"); - if (fseek(dev->f, 0, SEEK_END) == -1) - fatal("imd_load(): Error seeking to the end of the file\n"); - fsize = ftell(dev->f); + if (fseek(dev->fp, 0, SEEK_END) == -1) + fatal("imd_load(): Error seeking to the end of the file\n"); + fsize = ftell(dev->fp); if (fsize <= 0) { - imd_log("IMD: Too small ImageDisk image\n"); - fclose(dev->f); - free(dev); - memset(floppyfns[drive], 0, sizeof(floppyfns[drive])); - return; + imd_log("IMD: Too small ImageDisk image\n"); + fclose(dev->fp); + free(dev); + memset(floppyfns[drive], 0, sizeof(floppyfns[drive])); + return; } - if (fseek(dev->f, 0, SEEK_SET) == -1) - fatal("imd_load(): Error seeking to the beginning of the file again\n"); + if (fseek(dev->fp, 0, SEEK_SET) == -1) + fatal("imd_load(): Error seeking to the beginning of the file again\n"); dev->buffer = malloc(fsize); - if (fread(dev->buffer, 1, fsize, dev->f) != fsize) - fatal("imd_load(): Error reading data\n"); + if (fread(dev->buffer, 1, fsize, dev->fp) != fsize) + fatal("imd_load(): Error reading data\n"); buffer = dev->buffer; buffer2 = memchr(buffer, 0x1A, fsize); if (buffer2 == NULL) { - imd_log("IMD: No ASCII EOF character\n"); - fclose(dev->f); - free(dev); - memset(floppyfns[drive], 0, sizeof(floppyfns[drive])); - return; + imd_log("IMD: No ASCII EOF character\n"); + fclose(dev->fp); + free(dev); + memset(floppyfns[drive], 0, sizeof(floppyfns[drive])); + return; } else { - imd_log("IMD: ASCII EOF character found at offset %08X\n", buffer2 - buffer); + imd_log("IMD: ASCII EOF character found at offset %08X\n", buffer2 - buffer); } buffer2++; if ((buffer2 - buffer) == fsize) { - imd_log("IMD: File ends after ASCII EOF character\n"); - fclose(dev->f); - free(dev); - memset(floppyfns[drive], 0, sizeof(floppyfns[drive])); - return; + imd_log("IMD: File ends after ASCII EOF character\n"); + fclose(dev->fp); + free(dev); + memset(floppyfns[drive], 0, sizeof(floppyfns[drive])); + return; } else { - imd_log("IMD: File continues after ASCII EOF character\n"); + imd_log("IMD: File continues after ASCII EOF character\n"); } - dev->start_offs = (buffer2 - buffer); - dev->disk_flags = 0x00; + dev->start_offs = (buffer2 - buffer); + dev->disk_flags = 0x00; dev->track_count = 0; - dev->sides = 1; + dev->sides = 1; /* Set up the drive unit. */ imd[drive] = dev; - while(1) { - track = buffer2[1]; - side = buffer2[2]; - if (side & 1) - dev->sides = 2; - extra = side & 0xC0; - side &= 0x3F; + while (1) { + track = buffer2[1]; + side = buffer2[2]; + if (side & 1) + dev->sides = 2; + extra = side & 0xC0; + side &= 0x3F; - dev->tracks[track][side].side_flags = (buffer2[0] % 3); - if (! dev->tracks[track][side].side_flags) - dev->disk_flags |= (0x02); - dev->tracks[track][side].side_flags |= (!(buffer2[0] - dev->tracks[track][side].side_flags) ? 0 : 8); - mfm = dev->tracks[track][side].side_flags & 8; - track_total = mfm ? 146 : 73; - pre_sector = mfm ? 60 : 42; + dev->tracks[track][side].side_flags = (buffer2[0] % 3); + if (!dev->tracks[track][side].side_flags) + dev->disk_flags |= 0x02; + dev->tracks[track][side].side_flags |= (!(buffer2[0] - dev->tracks[track][side].side_flags) ? 0 : 8); + mfm = dev->tracks[track][side].side_flags & 8; + track_total = mfm ? 146 : 73; + pre_sector = mfm ? 60 : 42; - track_spt = buffer2[3]; - sector_size = buffer2[4]; - if ((track_spt == 15) && (sector_size == 2)) - dev->tracks[track][side].side_flags |= 0x20; - if ((track_spt == 16) && (sector_size == 2)) - dev->tracks[track][side].side_flags |= 0x20; - if ((track_spt == 17) && (sector_size == 2)) - dev->tracks[track][side].side_flags |= 0x20; - if ((track_spt == 8) && (sector_size == 3)) - dev->tracks[track][side].side_flags |= 0x20; - if ((dev->tracks[track][side].side_flags & 7) == 1) - dev->tracks[track][side].side_flags |= 0x20; - if ((dev->tracks[track][side].side_flags & 0x07) == 0x00) - dev->tracks[track][side].max_sector_size = 6; - else - dev->tracks[track][side].max_sector_size = 5; - if (!mfm) - dev->tracks[track][side].max_sector_size--; - imd_log("Side flags for (%02i)(%01i): %02X\n", track, side, dev->tracks[track][side].side_flags); - dev->tracks[track][side].is_present = 1; - dev->tracks[track][side].file_offs = (buffer2 - buffer); - memcpy(dev->tracks[track][side].params, buffer2, 5); - dev->tracks[track][side].r_map_offs = dev->tracks[track][side].file_offs + 5; - last_offset = dev->tracks[track][side].r_map_offs + track_spt; + track_spt = buffer2[3]; + sector_size = buffer2[4]; + if ((track_spt == 15) && (sector_size == 2)) + dev->tracks[track][side].side_flags |= 0x20; + if ((track_spt == 16) && (sector_size == 2)) + dev->tracks[track][side].side_flags |= 0x20; + if ((track_spt == 17) && (sector_size == 2)) + dev->tracks[track][side].side_flags |= 0x20; + if ((track_spt == 8) && (sector_size == 3)) + dev->tracks[track][side].side_flags |= 0x20; + if ((dev->tracks[track][side].side_flags & 7) == 1) + dev->tracks[track][side].side_flags |= 0x20; + if ((dev->tracks[track][side].side_flags & 0x07) == 0x00) + dev->tracks[track][side].max_sector_size = 6; + else + dev->tracks[track][side].max_sector_size = 5; + if (!mfm) + dev->tracks[track][side].max_sector_size--; + imd_log("Side flags for (%02i)(%01i): %02X\n", track, side, dev->tracks[track][side].side_flags); + dev->tracks[track][side].is_present = 1; + dev->tracks[track][side].file_offs = (buffer2 - buffer); + memcpy(dev->tracks[track][side].params, buffer2, 5); + dev->tracks[track][side].r_map_offs = dev->tracks[track][side].file_offs + 5; + last_offset = dev->tracks[track][side].r_map_offs + track_spt; - if (extra & 0x80) { - dev->tracks[track][side].c_map_offs = last_offset; - last_offset += track_spt; - } + if (extra & 0x80) { + dev->tracks[track][side].c_map_offs = last_offset; + last_offset += track_spt; + } - if (extra & 0x40) { - dev->tracks[track][side].h_map_offs = last_offset; - last_offset += track_spt; - } + if (extra & 0x40) { + dev->tracks[track][side].h_map_offs = last_offset; + last_offset += track_spt; + } - if (track_spt == 0x00) { - dev->tracks[track][side].n_map_offs = last_offset; - buffer2 = buffer + last_offset; - last_offset += track_spt; - dev->tracks[track][side].is_present = 0; - } else if (sector_size == 0xFF) { - dev->tracks[track][side].n_map_offs = last_offset; - buffer2 = buffer + last_offset; - last_offset += track_spt; + if (track_spt == 0x00) { + dev->tracks[track][side].n_map_offs = last_offset; + buffer2 = buffer + last_offset; + last_offset += track_spt; + dev->tracks[track][side].is_present = 0; + } else if (sector_size == 0xFF) { + dev->tracks[track][side].n_map_offs = last_offset; + buffer2 = buffer + last_offset; + last_offset += track_spt; - dev->tracks[track][side].data_offs = last_offset; + dev->tracks[track][side].data_offs = last_offset; - for (i = 0; i < track_spt; i++) { - data_size = buffer2[i]; - data_size = 128 << data_size; - dev->tracks[track][side].sector_data_offs[i] = last_offset; - dev->tracks[track][side].sector_data_size[i] = 1; - if (dev->buffer[dev->tracks[track][side].sector_data_offs[i]] > 0x08) { - /* Invalid sector data type, possibly a malformed HxC IMG image (it outputs data errored - sectors with a variable amount of bytes, against the specification). */ - imd_log("IMD: Invalid sector data type %02X\n", dev->buffer[dev->tracks[track][side].sector_data_offs[i]]); - fclose(dev->f); - free(dev); - imd[drive] = NULL; - memset(floppyfns[drive], 0, sizeof(floppyfns[drive])); - return; - } - if (buffer[dev->tracks[track][side].sector_data_offs[i]] != 0) - dev->tracks[track][side].sector_data_size[i] += (buffer[dev->tracks[track][side].sector_data_offs[i]] & 1) ? data_size : 1; - last_offset += dev->tracks[track][side].sector_data_size[i]; - if (!(buffer[dev->tracks[track][side].sector_data_offs[i]] & 1)) - fwriteprot[drive] = writeprot[drive] = 1; - type = dev->buffer[dev->tracks[track][side].sector_data_offs[i]]; - if (type != 0x00) { - type = ((type - 1) >> 1) & 7; - if (data_size > (128 << dev->tracks[track][side].max_sector_size)) - track_total += (pre_sector + 3); - else - track_total += (pre_sector + data_size + 2); - } - } - } else { - dev->tracks[track][side].data_offs = last_offset; + for (int i = 0; i < track_spt; i++) { + data_size = buffer2[i]; + data_size = 128 << data_size; + dev->tracks[track][side].sector_data_offs[i] = last_offset; + dev->tracks[track][side].sector_data_size[i] = 1; + if (dev->buffer[dev->tracks[track][side].sector_data_offs[i]] > 0x08) { + /* Invalid sector data type, possibly a malformed HxC IMG image (it outputs data errored + sectors with a variable amount of bytes, against the specification). */ + imd_log("IMD: Invalid sector data type %02X\n", dev->buffer[dev->tracks[track][side].sector_data_offs[i]]); + fclose(dev->fp); + free(dev); + imd[drive] = NULL; + memset(floppyfns[drive], 0, sizeof(floppyfns[drive])); + return; + } + if (buffer[dev->tracks[track][side].sector_data_offs[i]] != 0) + dev->tracks[track][side].sector_data_size[i] += (buffer[dev->tracks[track][side].sector_data_offs[i]] & 1) ? data_size : 1; + last_offset += dev->tracks[track][side].sector_data_size[i]; + if (!(buffer[dev->tracks[track][side].sector_data_offs[i]] & 1)) + fwriteprot[drive] = writeprot[drive] = 1; + type = dev->buffer[dev->tracks[track][side].sector_data_offs[i]]; + if (type != 0x00) { + type = ((type - 1) >> 1) & 7; + if (data_size > (128 << dev->tracks[track][side].max_sector_size)) + track_total += (pre_sector + 3); + else + track_total += (pre_sector + data_size + 2); + } + } + } else { + dev->tracks[track][side].data_offs = last_offset; - for (i = 0; i < track_spt; i++) { - data_size = sector_size; - data_size = 128 << data_size; - dev->tracks[track][side].sector_data_offs[i] = last_offset; - dev->tracks[track][side].sector_data_size[i] = 1; - if (dev->buffer[dev->tracks[track][side].sector_data_offs[i]] > 0x08) { - /* Invalid sector data type, possibly a malformed HxC IMG image (it outputs data errored - sectors with a variable amount of bytes, against the specification). */ - imd_log("IMD: Invalid sector data type %02X\n", dev->buffer[dev->tracks[track][side].sector_data_offs[i]]); - fclose(dev->f); - free(dev); - imd[drive] = NULL; - memset(floppyfns[drive], 0, sizeof(floppyfns[drive])); - return; - } - if (buffer[dev->tracks[track][side].sector_data_offs[i]] != 0) - dev->tracks[track][side].sector_data_size[i] += (buffer[dev->tracks[track][side].sector_data_offs[i]] & 1) ? data_size : 1; - last_offset += dev->tracks[track][side].sector_data_size[i]; - if (!(buffer[dev->tracks[track][side].sector_data_offs[i]] & 1)) - fwriteprot[drive] = writeprot[drive] = 1; - type = dev->buffer[dev->tracks[track][side].sector_data_offs[i]]; - if (type != 0x00) { - type = ((type - 1) >> 1) & 7; - if (data_size > (128 << dev->tracks[track][side].max_sector_size)) - track_total += (pre_sector + 3); - else - track_total += (pre_sector + data_size + 2); - } - } - } + for (int i = 0; i < track_spt; i++) { + data_size = sector_size; + data_size = 128 << data_size; + dev->tracks[track][side].sector_data_offs[i] = last_offset; + dev->tracks[track][side].sector_data_size[i] = 1; + if (dev->buffer[dev->tracks[track][side].sector_data_offs[i]] > 0x08) { + /* Invalid sector data type, possibly a malformed HxC IMG image (it outputs data errored + sectors with a variable amount of bytes, against the specification). */ + imd_log("IMD: Invalid sector data type %02X\n", dev->buffer[dev->tracks[track][side].sector_data_offs[i]]); + fclose(dev->fp); + free(dev); + imd[drive] = NULL; + memset(floppyfns[drive], 0, sizeof(floppyfns[drive])); + return; + } + if (buffer[dev->tracks[track][side].sector_data_offs[i]] != 0) + dev->tracks[track][side].sector_data_size[i] += (buffer[dev->tracks[track][side].sector_data_offs[i]] & 1) ? data_size : 1; + last_offset += dev->tracks[track][side].sector_data_size[i]; + if (!(buffer[dev->tracks[track][side].sector_data_offs[i]] & 1)) + fwriteprot[drive] = writeprot[drive] = 1; + type = dev->buffer[dev->tracks[track][side].sector_data_offs[i]]; + if (type != 0x00) { + type = ((type - 1) >> 1) & 7; + if (data_size > (128 << dev->tracks[track][side].max_sector_size)) + track_total += (pre_sector + 3); + else + track_total += (pre_sector + data_size + 2); + } + } + } - buffer2 = buffer + last_offset; + buffer2 = buffer + last_offset; - /* Leaving even GAP4: 80 : 40 */ - /* Leaving only GAP1: 96 : 47 */ - /* Not leaving even GAP1: 146 : 73 */ - raw_tsize = get_raw_tsize(dev->tracks[track][side].side_flags, 0); - minimum_gap3 = 12 * track_spt; + /* Leaving even GAP4: 80 : 40 */ + /* Leaving only GAP1: 96 : 47 */ + /* Not leaving even GAP1: 146 : 73 */ + raw_tsize = get_raw_tsize(dev->tracks[track][side].side_flags, 0); + minimum_gap3 = 12 * track_spt; - if ((dev->tracks[track][side].side_flags == 0x0A) || (dev->tracks[track][side].side_flags == 0x29)) - converted_rate = 2; - else if (dev->tracks[track][side].side_flags == 0x28) - converted_rate = 4; - else - converted_rate = dev->tracks[track][side].side_flags & 0x03; + if ((dev->tracks[track][side].side_flags == 0x0A) || (dev->tracks[track][side].side_flags == 0x29)) + converted_rate = 2; + else if (dev->tracks[track][side].side_flags == 0x28) + converted_rate = 4; + else + converted_rate = dev->tracks[track][side].side_flags & 0x03; - if ((track_spt != 0x00) && (gap3_sizes[converted_rate][sector_size][track_spt] == 0x00)) { - size_diff = raw_tsize - track_total; - gap_sum = minimum_gap3 + minimum_gap4; - if (size_diff < gap_sum) { - /* If we can't fit the sectors with a reasonable minimum gap at perfect RPM, let's try 2% slower. */ - raw_tsize = get_raw_tsize(dev->tracks[track][side].side_flags, 1); - /* Set disk flags so that rotation speed is 2% slower. */ - dev->disk_flags |= (3 << 5); - size_diff = raw_tsize - track_total; - if (size_diff < gap_sum) { - /* If we can't fit the sectors with a reasonable minimum gap even at 2% slower RPM, abort. */ - imd_log("IMD: Unable to fit the %i sectors in a track\n", track_spt); - fclose(dev->f); - free(dev); - imd[drive] = NULL; - memset(floppyfns[drive], 0, sizeof(floppyfns[drive])); - return; - } - } + if ((track_spt != 0x00) && (gap3_sizes[converted_rate][sector_size][track_spt] == 0x00)) { + size_diff = raw_tsize - track_total; + gap_sum = minimum_gap3 + minimum_gap4; + if (size_diff < gap_sum) { + /* If we can't fit the sectors with a reasonable minimum gap at perfect RPM, let's try 2% slower. */ + raw_tsize = get_raw_tsize(dev->tracks[track][side].side_flags, 1); + /* Set disk flags so that rotation speed is 2% slower. */ + dev->disk_flags |= (3 << 5); + size_diff = raw_tsize - track_total; + if (size_diff < gap_sum) { + /* If we can't fit the sectors with a reasonable minimum gap even at 2% slower RPM, abort. */ + imd_log("IMD: Unable to fit the %i sectors in a track\n", track_spt); + fclose(dev->fp); + free(dev); + imd[drive] = NULL; + memset(floppyfns[drive], 0, sizeof(floppyfns[drive])); + return; + } + } - dev->tracks[track][side].gap3_len = (size_diff - minimum_gap4) / track_spt; - } else if ((track_spt == 0x00) || (gap3_sizes[converted_rate][sector_size][track_spt] != 0x00)) - dev->tracks[track][side].gap3_len = gap3_sizes[converted_rate][sector_size][track_spt]; + dev->tracks[track][side].gap3_len = (size_diff - minimum_gap4) / track_spt; + } else if ((track_spt == 0x00) || (gap3_sizes[converted_rate][sector_size][track_spt] != 0x00)) + dev->tracks[track][side].gap3_len = gap3_sizes[converted_rate][sector_size][track_spt]; - /* imd_log("GAP3 length for (%02i)(%01i): %i bytes\n", track, side, dev->tracks[track][side].gap3_len); */ + /* imd_log("GAP3 length for (%02i)(%01i): %i bytes\n", track, side, dev->tracks[track][side].gap3_len); */ - if (track > dev->track_count) - dev->track_count = track; + if (track > dev->track_count) + dev->track_count = track; - if (last_offset >= fsize) - break; + if (last_offset >= fsize) + break; } /* If more than 43 tracks, then the tracks are thin (96 tpi). */ dev->track_count++; dev->track_width = 0; if (dev->track_count > 43) - dev->track_width = 1; + dev->track_width = 1; /* If 2 sides, mark it as such. */ if (dev->sides == 2) - dev->disk_flags |= 8; + dev->disk_flags |= 8; - /* imd_log("%i tracks, %i sides\n", dev->track_count, dev->sides); */ +#if 0 + imd_log("%i tracks, %i sides\n", dev->track_count, dev->sides); +#endif /* Attach this format to the D86F engine. */ - d86f_handler[drive].disk_flags = disk_flags; - d86f_handler[drive].side_flags = side_flags; - d86f_handler[drive].writeback = imd_writeback; - d86f_handler[drive].set_sector = set_sector; - d86f_handler[drive].read_data = poll_read_data; - d86f_handler[drive].write_data = poll_write_data; + d86f_handler[drive].disk_flags = disk_flags; + d86f_handler[drive].side_flags = side_flags; + d86f_handler[drive].writeback = imd_writeback; + d86f_handler[drive].set_sector = set_sector; + d86f_handler[drive].read_data = poll_read_data; + d86f_handler[drive].write_data = poll_write_data; d86f_handler[drive].format_conditions = format_conditions; - d86f_handler[drive].extra_bit_cells = null_extra_bit_cells; - d86f_handler[drive].encoded_data = common_encoded_data; - d86f_handler[drive].read_revolution = common_read_revolution; - d86f_handler[drive].index_hole_pos = null_index_hole_pos; - d86f_handler[drive].get_raw_size = common_get_raw_size; - d86f_handler[drive].check_crc = 1; + d86f_handler[drive].extra_bit_cells = null_extra_bit_cells; + d86f_handler[drive].encoded_data = common_encoded_data; + d86f_handler[drive].read_revolution = common_read_revolution; + d86f_handler[drive].index_hole_pos = null_index_hole_pos; + d86f_handler[drive].get_raw_size = common_get_raw_size; + d86f_handler[drive].check_crc = 1; d86f_set_version(drive, 0x0063); drives[drive].seek = imd_seek; @@ -916,20 +919,20 @@ imd_load(int drive, char *fn) d86f_common_handlers(drive); } - void imd_close(int drive) { imd_t *dev = imd[drive]; - if (dev == NULL) return; + if (dev == NULL) + return; d86f_unregister(drive); - if (dev->f != NULL) { - free(dev->buffer); + if (dev->fp != NULL) { + free(dev->buffer); - fclose(dev->f); + fclose(dev->fp); } /* Release the memory. */ @@ -937,7 +940,6 @@ imd_close(int drive) imd[drive] = NULL; } - void imd_set_fdc(void *fdc) { diff --git a/src/floppy/fdd_img.c b/src/floppy/fdd_img.c index aec27415f..404cbf9fa 100644 --- a/src/floppy/fdd_img.c +++ b/src/floppy/fdd_img.c @@ -1,27 +1,27 @@ /* - * 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. + * 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. + * This file is part of the 86Box distribution. * - * Implementation of the raw sector-based floppy image format, - * as well as the Japanese FDI, CopyQM, and FDF formats. + * Implementation of the raw sector-based floppy image format, + * as well as the Japanese FDI, CopyQM, and FDF formats. * - * NOTE: This file is still a disaster, needs to be cleaned up and - * re-merged with the other files. Much of it is generic to - * all formats. + * NOTE: This file is still a disaster, needs to be cleaned up and + * re-merged with the other files. Much of it is generic to + * all formats. * * * - * Authors: Sarah Walker, - * Miran Grca, - * Fred N. van Kempen, + * Authors: Sarah Walker, + * Miran Grca, + * Fred N. van Kempen, * - * Copyright 2008-2019 Sarah Walker. - * Copyright 2016-2019 Miran Grca. - * Copyright 2018,2019 Fred N. van Kempen. + * Copyright 2008-2019 Sarah Walker. + * Copyright 2016-2019 Miran Grca. + * Copyright 2018-2019 Fred N. van Kempen. */ #include #include @@ -33,54 +33,54 @@ #include <86box/86box.h> #include <86box/timer.h> #include <86box/config.h> +#include <86box/path.h> #include <86box/plat.h> #include <86box/fdd.h> #include <86box/fdd_86f.h> #include <86box/fdd_img.h> #include <86box/fdc.h> - -typedef struct { - FILE *f; - uint8_t track_data[2][50000]; - int sectors, tracks, sides; - uint8_t sector_size; - int xdf_type; /* 0 = not XDF, 1-5 = one of the five XDF types */ - int dmf; - int track; - int track_width; - uint32_t base; - uint8_t gap2_size; - uint8_t gap3_size; - uint16_t disk_flags; - uint16_t track_flags; - uint8_t sector_pos_side[256][256]; - uint16_t sector_pos[256][256]; - uint8_t current_sector_pos_side; - uint16_t current_sector_pos; - uint8_t *disk_data; - uint8_t is_cqm; - uint8_t disk_at_once; - uint8_t interleave; - uint8_t skew; +typedef struct img_t { + FILE *fp; + uint8_t track_data[2][688128]; + int sectors, tracks, sides; + uint8_t sector_size; + int xdf_type; /* 0 = not XDF, 1-5 = one of the five XDF types */ + int dmf; + int track; + int track_width; + uint32_t base; + uint8_t gap2_size; + uint8_t gap3_size; + uint16_t disk_flags; + uint16_t track_flags; + uint8_t sector_pos_side[256][256]; + uint16_t sector_pos[256][256]; + uint8_t current_sector_pos_side; + uint16_t current_sector_pos; + uint8_t *disk_data; + uint8_t is_cqm; + uint8_t disk_at_once; + uint8_t interleave; + uint8_t skew; } img_t; -static img_t *img[FDD_NUM]; -static fdc_t *img_fdc; +static img_t *img[FDD_NUM]; +static fdc_t *img_fdc; -static double bit_rate_300; -static char *ext; -static uint8_t first_byte, - second_byte, - third_byte, - fourth_byte; -static uint8_t fdf_suppress_final_byte = 0; /* This is hard-coded to 0 - - * if you really need to read - * those NT 3.1 Beta floppy - * images, change this to 1 - * and recompile. - */ +static double bit_rate_300; +static char *ext; +static uint8_t first_byte; +static uint8_t second_byte; +static uint8_t third_byte; +static uint8_t fourth_byte; +static uint8_t fdf_suppress_final_byte = 0; /* This is hard-coded to 0 - + * if you really need to read + * those NT 3.1 Beta floppy + * images, change this to 1 + * and recompile. + */ const uint8_t dmf_r[21] = { 12, 2, 13, 3, 14, 4, 15, 5, 16, 6, 17, 7, 18, 8, 19, 9, 20, 10, 21, 11, 1 }; @@ -90,420 +90,448 @@ const uint8_t xdf_gap3_sizes[2][2] = { { 60, 69 }, { 60, 50 } }; const uint16_t xdf_trackx_spos[2][8] = { { 0xA7F, 0xF02, 0x11B7, 0xB66, 0xE1B, 0x129E }, { 0x302, 0x7E2, 0xA52, 0x12DA, 0x572, 0xDFA, 0x106A, 0x154A } }; /* XDF: Layout of the sectors in the image. */ -const xdf_sector_t xdf_img_layout[2][2][46] = { { { {0x8100}, {0x8200}, {0x8300}, {0x8400}, {0x8500}, {0x8600}, {0x8700}, {0x8800}, - {0x8101}, {0x8201}, {0x0100}, {0x0200}, {0x0300}, {0x0400}, {0x0500}, {0x0600}, - {0x0700}, {0x0800}, { 0}, - {0x8301}, {0x8401}, {0x8501}, {0x8601}, {0x8701}, {0x8801}, {0x8901}, {0x8A01}, - {0x8B01}, {0x8C01}, {0x8D01}, {0x8E01}, {0x8F01}, {0x9001}, { 0}, { 0}, - { 0}, { 0}, { 0} }, - { {0x8300}, {0x8600}, {0x8201}, {0x8200}, {0x8601}, {0x8301} } - }, /* 5.25" 2HD */ - { { {0x8100}, {0x8200}, {0x8300}, {0x8400}, {0x8500}, {0x8600}, {0x8700}, {0x8800}, - {0x8900}, {0x8A00}, {0x8B00}, {0x8101}, {0x0100}, {0x0200}, {0x0300}, {0x0400}, - {0x0500}, {0x0600}, {0x0700}, {0x0800}, { 0}, { 0}, { 0}, - {0x8201}, {0x8301}, {0x8401}, {0x8501}, {0x8601}, {0x8701}, {0x8801}, {0x8901}, - {0x8A01}, {0x8B01}, {0x8C01}, {0x8D01}, {0x8E01}, {0x8F01}, { 0}, { 0}, - { 0}, { 0}, { 0}, {0x9001}, {0x9101}, {0x9201}, {0x9301} }, - { {0x8300}, {0x8400}, {0x8601}, {0x8200}, {0x8201}, {0x8600}, {0x8401}, {0x8301} } - } /* 3.5" 2HD */ - }; +const xdf_sector_t xdf_img_layout[2][2][46] = { + { + { + {0x8100}, {0x8200}, {0x8300}, {0x8400}, {0x8500}, {0x8600}, {0x8700}, {0x8800}, + {0x8101}, {0x8201}, {0x0100}, {0x0200}, {0x0300}, {0x0400}, {0x0500}, {0x0600}, + {0x0700}, {0x0800}, { 0}, + {0x8301}, {0x8401}, {0x8501}, {0x8601}, {0x8701}, {0x8801}, {0x8901}, {0x8A01}, + {0x8B01}, {0x8C01}, {0x8D01}, {0x8E01}, {0x8F01}, {0x9001}, { 0}, { 0}, + { 0}, { 0}, { 0} + }, + { {0x8300}, {0x8600}, {0x8201}, {0x8200}, {0x8601}, {0x8301} } + }, /* 5.25" 2HD */ + { + { + {0x8100}, {0x8200}, {0x8300}, {0x8400}, {0x8500}, {0x8600}, {0x8700}, {0x8800}, + {0x8900}, {0x8A00}, {0x8B00}, {0x8101}, {0x0100}, {0x0200}, {0x0300}, {0x0400}, + {0x0500}, {0x0600}, {0x0700}, {0x0800}, { 0}, { 0}, { 0}, + {0x8201}, {0x8301}, {0x8401}, {0x8501}, {0x8601}, {0x8701}, {0x8801}, {0x8901}, + {0x8A01}, {0x8B01}, {0x8C01}, {0x8D01}, {0x8E01}, {0x8F01}, { 0}, { 0}, + { 0}, { 0}, { 0}, {0x9001}, {0x9101}, {0x9201}, {0x9301} + }, + { {0x8300}, {0x8400}, {0x8601}, {0x8200}, {0x8201}, {0x8600}, {0x8401}, {0x8301} } + } /* 3.5" 2HD */ +}; /* XDF: Layout of the sectors on the disk's track. */ -const xdf_sector_t xdf_disk_layout[2][2][38] = { { { {0x0100}, {0x0200}, {0x8100}, {0x8800}, {0x8200}, {0x0300}, {0x8300}, {0x0400}, - {0x8400}, {0x0500}, {0x8500}, {0x0600}, {0x8600}, {0x0700}, {0x8700}, {0x0800}, - {0x8D01}, {0x8501}, {0x8E01}, {0x8601}, {0x8F01}, {0x8701}, {0x9001}, {0x8801}, - {0x8101}, {0x8901}, {0x8201}, {0x8A01}, {0x8301}, {0x8B01}, {0x8401}, {0x8C01} }, - { {0x8300}, {0x8200}, {0x8600}, {0x8201}, {0x8301}, {0x8601} } - }, /* 5.25" 2HD */ - { { {0x0100}, {0x8A00}, {0x8100}, {0x8B00}, {0x8200}, {0x0200}, {0x8300}, {0x0300}, - {0x8400}, {0x0400}, {0x8500}, {0x0500}, {0x8600}, {0x0600}, {0x8700}, {0x0700}, - {0x8800}, {0x0800}, {0x8900}, - {0x9001}, {0x8701}, {0x9101}, {0x8801}, {0x9201}, {0x8901}, {0x9301}, {0x8A01}, - {0x8101}, {0x8B01}, {0x8201}, {0x8C01}, {0x8301}, {0x8D01}, {0x8401}, {0x8E01}, - {0x8501}, {0x8F01}, {0x8601} }, - { {0x8300}, {0x8200}, {0x8400}, {0x8600}, {0x8401}, {0x8201}, {0x8301}, {0x8601} }, - }, /* 3.5" 2HD */ - }; +const xdf_sector_t xdf_disk_layout[2][2][38] = { + { + { + {0x0100}, {0x0200}, {0x8100}, {0x8800}, {0x8200}, {0x0300}, {0x8300}, {0x0400}, + {0x8400}, {0x0500}, {0x8500}, {0x0600}, {0x8600}, {0x0700}, {0x8700}, {0x0800}, + {0x8D01}, {0x8501}, {0x8E01}, {0x8601}, {0x8F01}, {0x8701}, {0x9001}, {0x8801}, + {0x8101}, {0x8901}, {0x8201}, {0x8A01}, {0x8301}, {0x8B01}, {0x8401}, {0x8C01} + }, + { {0x8300}, {0x8200}, {0x8600}, {0x8201}, {0x8301}, {0x8601} } + }, /* 5.25" 2HD */ + { + { + {0x0100}, {0x8A00}, {0x8100}, {0x8B00}, {0x8200}, {0x0200}, {0x8300}, {0x0300}, + {0x8400}, {0x0400}, {0x8500}, {0x0500}, {0x8600}, {0x0600}, {0x8700}, {0x0700}, + {0x8800}, {0x0800}, {0x8900}, + {0x9001}, {0x8701}, {0x9101}, {0x8801}, {0x9201}, {0x8901}, {0x9301}, {0x8A01}, + {0x8101}, {0x8B01}, {0x8201}, {0x8C01}, {0x8301}, {0x8D01}, {0x8401}, {0x8E01}, + {0x8501}, {0x8F01}, {0x8601} + }, + { {0x8300}, {0x8200}, {0x8400}, {0x8600}, {0x8401}, {0x8201}, {0x8301}, {0x8601} }, + }, /* 3.5" 2HD */ +}; /* First dimension is possible sector sizes (0 = 128, 7 = 16384), second is possible bit rates (250/360, 250, 300, 500/360, 500, 1000). */ /* Disks formatted at 250 kbps @ 360 RPM can be read with a 360 RPM single-RPM 5.25" drive by setting the rate to 250 kbps. Disks formatted at 300 kbps @ 300 RPM can be read with any 300 RPM single-RPM drive by setting the rate rate to 300 kbps. */ -static const uint8_t maximum_sectors[8][6] = { { 26, 31, 38, 53, 64, 118 }, /* 128 */ - { 15, 19, 23, 32, 38, 73 }, /* 256 */ - { 7, 10, 12, 17, 22, 41 }, /* 512 */ - { 3, 5, 6, 9, 11, 22 }, /* 1024 */ - { 2, 2, 3, 4, 5, 11 }, /* 2048 */ - { 1, 1, 1, 2, 2, 5 }, /* 4096 */ - { 0, 0, 0, 1, 1, 3 }, /* 8192 */ - { 0, 0, 0, 0, 0, 1 } }; /* 16384 */ +static const uint8_t maximum_sectors[8][6] = { + { 26, 31, 38, 53, 64, 118 }, /* 128 */ + { 15, 19, 23, 32, 38, 73 }, /* 256 */ + { 7, 10, 12, 17, 22, 41 }, /* 512 */ + { 3, 5, 6, 9, 11, 22 }, /* 1024 */ + { 2, 2, 3, 4, 5, 11 }, /* 2048 */ + { 1, 1, 1, 2, 2, 5 }, /* 4096 */ + { 0, 0, 0, 1, 1, 3 }, /* 8192 */ + { 0, 0, 0, 0, 0, 1 } /* 16384 */ +}; -static const uint8_t xdf_sectors[8][6] = { { 0, 0, 0, 0, 0, 0 }, /* 128 */ - { 0, 0, 0, 0, 0, 0 }, /* 256 */ - { 0, 0, 0, 19, 23, 0 }, /* 512 */ - { 0, 0, 0, 0, 0, 0 }, /* 1024 */ - { 0, 0, 0, 0, 0, 0 }, /* 2048 */ - { 0, 0, 0, 0, 0, 0 }, /* 4096 */ - { 0, 0, 0, 0, 0, 0 }, /* 8192 */ - { 0, 0, 0, 0, 0, 0 } }; /* 16384 */ +static const uint8_t xdf_sectors[8][6] = { + { 0, 0, 0, 0, 0, 0 }, /* 128 */ + { 0, 0, 0, 0, 0, 0 }, /* 256 */ + { 0, 0, 0, 19, 23, 0 }, /* 512 */ + { 0, 0, 0, 0, 0, 0 }, /* 1024 */ + { 0, 0, 0, 0, 0, 0 }, /* 2048 */ + { 0, 0, 0, 0, 0, 0 }, /* 4096 */ + { 0, 0, 0, 0, 0, 0 }, /* 8192 */ + { 0, 0, 0, 0, 0, 0 } /* 16384 */ +}; -static const uint8_t xdf_types[8][6] = { { 0, 0, 0, 0, 0, 0 }, /* 128 */ - { 0, 0, 0, 0, 0, 0 }, /* 256 */ - { 0, 0, 0, 1, 2, 0 }, /* 512 */ - { 0, 0, 0, 0, 0, 0 }, /* 1024 */ - { 0, 0, 0, 0, 0, 0 }, /* 2048 */ - { 0, 0, 0, 0, 0, 0 }, /* 4096 */ - { 0, 0, 0, 0, 0, 0 }, /* 8192 */ - { 0, 0, 0, 0, 0, 0 } }; /* 16384 */ +static const uint8_t xdf_types[8][6] = { + { 0, 0, 0, 0, 0, 0 }, /* 128 */ + { 0, 0, 0, 0, 0, 0 }, /* 256 */ + { 0, 0, 0, 1, 2, 0 }, /* 512 */ + { 0, 0, 0, 0, 0, 0 }, /* 1024 */ + { 0, 0, 0, 0, 0, 0 }, /* 2048 */ + { 0, 0, 0, 0, 0, 0 }, /* 4096 */ + { 0, 0, 0, 0, 0, 0 }, /* 8192 */ + { 0, 0, 0, 0, 0, 0 } /* 16384 */ +}; -static const double bit_rates_300[6] = { (250.0 * 300.0) / 360.0, 250.0, 300.0, (500.0 * 300.0) / 360.0, 500.0, 1000.0 }; +static const double bit_rates_300[6] = { (250.0 * 300.0) / 360.0, 250.0, 300.0, (500.0 * 300.0) / 360.0, 500.0, 1000.0 }; -static const uint8_t rates[6] = { 2, 2, 1, 4, 0, 3 }; +static const uint8_t rates[6] = { 2, 2, 1, 4, 0, 3 }; -static const uint8_t holes[6] = { 0, 0, 0, 1, 1, 2 }; - -const int gap3_sizes[5][8][48] = { { { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* [0][0] */ - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, - { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* [0][1] */ - 0x54, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, - { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* [0][2] */ - 0x00, 0x00, 0x6C, 0x48, 0x2A, 0x08, 0x02, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, - { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x83, 0x26, 0x00, 0x00, 0x00, 0x00, /* [0][3] */ - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, - { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* [0][4] */ - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, - { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* [0][5] */ - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, - { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* [0][6] */ - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, - { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* [0][7] */ - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } }, - { { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* [1][0] */ - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, - { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* [1][1] */ - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, - { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x54, 0x1C, 0x0E, 0x00, 0x00, /* [1][2] */ - 0x00, 0x00, 0x6C, 0x48, 0x2A, 0x08, 0x02, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, - { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x79, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* [1][3] */ - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, - { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* [1][4] */ - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, - { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* [1][5] */ - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, - { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* [1][6] */ - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, - { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* [1][7] */ - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } }, - { { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* [2][0] */ - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, - { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x32, 0x0C, 0x00, 0x00, 0x00, 0x36, /* [2][1] */ - 0x32, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, - { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x58, 0x50, 0x2E, 0x00, 0x00, 0x00, 0x00, 0x00, /* [2][2] */ - 0x00, 0x00, 0x00, 0x00, 0x00, 0x1C, 0x1C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, - { 0x00, 0x00, 0x00, 0x00, 0xF0, 0x74, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* [2][3] */ - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, - { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* [2][4] */ - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, - { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* [2][5] */ - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, - { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* [2][6] */ - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, - { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* [2][7] */ - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } }, - { { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* [3][0] */ - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, - { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* [3][1] */ - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, - { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* [3][2] */ - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x53, 0x4E, 0x3D, 0x2C, 0x1C, 0x0D, 0x02, 0x00, 0x00, 0x00, 0x01, 0x00 }, - { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* [3][3] */ - 0x00, 0x00, 0xF7, 0xAF, 0x6F, 0x55, 0x1F, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, - { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* [3][4] */ - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, - { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* [3][5] */ - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, - { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* [3][6] */ - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, - { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* [3][7] */ - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } }, - { { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* [4][0] */ - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, - { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* [4][1] */ - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x36, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, - { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x92, 0x54, /* [4][2] */ - 0x38, 0x23, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, - { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x74, 0x24, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* [4][3] */ - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, - { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* [4][4] */ - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, - { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* [4][5] */ - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, - { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* [4][6] */ - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, - { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* [4][7] */ - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } } }; +static const uint8_t holes[6] = { 0, 0, 0, 1, 1, 2 }; +const int gap3_sizes[5][8][48] = { + { + { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* [0][0] */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 + }, + { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* [0][1] */ + 0x54, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, + { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* [0][2] */ + 0x00, 0x00, 0x6C, 0x48, 0x2A, 0x08, 0x02, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, + { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x83, 0x26, 0x00, 0x00, 0x00, 0x00, /* [0][3] */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, + { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* [0][4] */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, + { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* [0][5] */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, + { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* [0][6] */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, + { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* [0][7] */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } + }, + { + { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* [1][0] */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, + { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* [1][1] */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, + { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x54, 0x1C, 0x0E, 0x00, 0x00, /* [1][2] */ + 0x00, 0x00, 0x6C, 0x48, 0x2A, 0x08, 0x02, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, + { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x79, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* [1][3] */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, + { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* [1][4] */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, + { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* [1][5] */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, + { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* [1][6] */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, + { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* [1][7] */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } + }, + { + { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* [2][0] */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, + { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x32, 0x0C, 0x00, 0x00, 0x00, 0x36, /* [2][1] */ + 0x32, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, + { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x58, 0x50, 0x2E, 0x00, 0x00, 0x00, 0x00, 0x00, /* [2][2] */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x1C, 0x1C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, + { 0x00, 0x00, 0x00, 0x00, 0xF0, 0x74, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* [2][3] */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, + { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* [2][4] */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, + { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* [2][5] */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, + { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* [2][6] */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, + { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* [2][7] */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } + }, + { + { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* [3][0] */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, + { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* [3][1] */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, + { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* [3][2] */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x53, 0x4E, 0x3D, 0x2C, 0x1C, 0x0D, 0x02, 0x00, 0x00, 0x00, 0x01, 0x00 }, + { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* [3][3] */ + 0x00, 0x00, 0xF7, 0xAF, 0x6F, 0x55, 0x1F, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, + { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* [3][4] */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, + { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* [3][5] */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, + { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* [3][6] */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, + { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* [3][7] */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } + }, + { + { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* [4][0] */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, + { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* [4][1] */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x36, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, + { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x92, 0x54, /* [4][2] */ + 0x38, 0x23, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, + { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x74, 0x24, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* [4][3] */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, + { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* [4][4] */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, + { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* [4][5] */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, + { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* [4][6] */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, + { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* [4][7] */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } + } +}; #ifdef ENABLE_IMG_LOG int img_do_log = ENABLE_IMG_LOG; - static void img_log(const char *fmt, ...) { - va_list ap; + va_list ap; - if (img_do_log) - { - va_start(ap, fmt); - pclog_ex(fmt, ap); - va_end(ap); - } + if (img_do_log) { + va_start(ap, fmt); + pclog_ex(fmt, ap); + va_end(ap); + } } #else -#define img_log(fmt, ...) +# define img_log(fmt, ...) #endif - /* Generic */ static int sector_size_code(int sector_size) { - switch(sector_size) { - case 128: - return(0); + switch (sector_size) { + case 128: + return 0; - case 256: - return(1); + case 256: + return 1; - default: - case 512: - return(2); + default: + case 512: + return 2; - case 1024: - return(3); + case 1024: + return 3; - case 2048: - return(4); + case 2048: + return 4; - case 4096: - return(5); + case 4096: + return 5; - case 8192: - return(6); + case 8192: + return 6; - case 16384: - return(7); + case 16384: + return 7; } } - static int bps_is_valid(uint16_t bps) { - int i; - - for (i = 0; i <= 8; i++) { - if (bps == (128 << i)) return(1); + for (uint8_t i = 0; i <= 8; i++) { + if (bps == (128 << i)) + return 1; } - return(0); + return 0; } - static int first_byte_is_valid(uint8_t first_byte) { - switch(first_byte) { - case 0x60: - case 0xE9: - case 0xEB: - return(1); + switch (first_byte) { + case 0x60: + case 0xE9: + case 0xEB: + return 1; - default: - break; + default: + break; } - return(0); + return 0; } - -#define xdf_img_sector xdf_img_layout[current_xdft][!is_t0][sector] +#define xdf_img_sector xdf_img_layout[current_xdft][!is_t0][sector] #define xdf_disk_sector xdf_disk_layout[current_xdft][!is_t0][array_sector] - static int interleave(int sector, int skew, int track_spt) { uint32_t skewed_i; uint32_t adjusted_r; - uint32_t add = (track_spt & 1); + uint32_t add = (track_spt & 1); uint32_t adjust = (track_spt >> 1); - skewed_i = (sector + skew) % track_spt; + skewed_i = (sector + skew) % track_spt; adjusted_r = (skewed_i >> 1) + 1; if (skewed_i & 1) - adjusted_r += (adjust + add); + adjusted_r += (adjust + add); - return(adjusted_r); + return adjusted_r; } - static void write_back(int drive) { - img_t *dev = img[drive]; - int ssize = 128 << ((int) dev->sector_size); - int side, size; + img_t *dev = img[drive]; + int ssize = 128 << ((int) dev->sector_size); + int size; - if (dev->f == NULL) return; + if (dev->fp == NULL) + return; - if (dev->disk_at_once) return; - - if (fseek(dev->f, dev->base + (dev->track * dev->sectors * ssize * dev->sides), SEEK_SET) == -1) - pclog("IMG write_back(): Error seeking to the beginning of the file\n"); - for (side = 0; side < dev->sides; side++) { - size = dev->sectors * ssize; - if (fwrite(dev->track_data[side], 1, size, dev->f) != size) - fatal("IMG write_back(): Error writing data\n"); + if (dev->disk_at_once) + return; + + if (fseek(dev->fp, dev->base + (dev->track * dev->sectors * ssize * dev->sides), SEEK_SET) == -1) + pclog("IMG write_back(): Error seeking to the beginning of the file\n"); + for (int side = 0; side < dev->sides; side++) { + size = dev->sectors * ssize; + if (fwrite(dev->track_data[side], 1, size, dev->fp) != size) + fatal("IMG write_back(): Error writing data\n"); } } - static uint16_t disk_flags(int drive) { - img_t *dev = img[drive]; + const img_t *dev = img[drive]; - return(dev->disk_flags); + return (dev->disk_flags); } - static uint16_t side_flags(int drive) { - img_t *dev = img[drive]; + const img_t *dev = img[drive]; - return(dev->track_flags); + return (dev->track_flags); } - static void -set_sector(int drive, int side, uint8_t c, uint8_t h, uint8_t r, uint8_t n) +set_sector(int drive, UNUSED(int side), UNUSED(uint8_t c), uint8_t h, uint8_t r, UNUSED(uint8_t n)) { img_t *dev = img[drive]; dev->current_sector_pos_side = dev->sector_pos_side[h][r]; - dev->current_sector_pos = dev->sector_pos[h][r]; + dev->current_sector_pos = dev->sector_pos[h][r]; } - static uint8_t -poll_read_data(int drive, int side, uint16_t pos) +poll_read_data(int drive, UNUSED(int side), uint16_t pos) { - img_t *dev = img[drive]; + const img_t *dev = img[drive]; - return(dev->track_data[dev->current_sector_pos_side][dev->current_sector_pos + pos]); + return (dev->track_data[dev->current_sector_pos_side][dev->current_sector_pos + pos]); } - static void -poll_write_data(int drive, int side, uint16_t pos, uint8_t data) +poll_write_data(int drive, UNUSED(int side), uint16_t pos, uint8_t data) { img_t *dev = img[drive]; dev->track_data[dev->current_sector_pos_side][dev->current_sector_pos + pos] = data; } - static int format_conditions(int drive) { - img_t *dev = img[drive]; - int temp = (fdc_get_format_sectors(img_fdc) == dev->sectors); + const img_t *dev = img[drive]; + int temp = (fdc_get_format_sectors(img_fdc) == dev->sectors); temp = temp && (fdc_get_format_n(img_fdc) == dev->sector_size); temp = temp && (dev->xdf_type == 0); - return(temp); + return temp; } - static void img_seek(int drive, int track) { - img_t *dev = img[drive]; - int side; - int current_xdft = dev->xdf_type - 1; - int read_bytes = 0; - uint8_t id[4] = { 0, 0, 0, 0 }; - int is_t0, sector, current_pos, img_pos, sr, sside, total, array_sector, buf_side, buf_pos; - int ssize = 128 << ((int) dev->sector_size); + img_t *dev = img[drive]; + int side; + int current_xdft = dev->xdf_type - 1; + int read_bytes = 0; + uint8_t id[4] = { 0, 0, 0, 0 }; + int is_t0; + int sector; + int current_pos; + int img_pos; + int sr; + int sside; + int total; + int array_sector; + int buf_side; + int buf_pos; + int ssize = 128 << ((int) dev->sector_size); uint32_t cur_pos = 0; - if (dev->f == NULL) return; + if (dev->fp == NULL) + return; if (!dev->track_width && fdd_doublestep_40(drive)) - track /= 2; + track /= 2; dev->track = track; d86f_set_cur_track(drive, track); is_t0 = (track == 0) ? 1 : 0; - if (! dev->disk_at_once) { - if (fseek(dev->f, dev->base + (track * dev->sectors * ssize * dev->sides), SEEK_SET) == -1) - fatal("img_seek(): Error seeking\n"); + if (!dev->disk_at_once) { + if (fseek(dev->fp, dev->base + (track * dev->sectors * ssize * dev->sides), SEEK_SET) == -1) + fatal("img_seek(): Error seeking\n"); } for (side = 0; side < dev->sides; side++) { - if (dev->disk_at_once) { - cur_pos = (track * dev->sectors * ssize * dev->sides) + (side * dev->sectors * ssize); - memcpy(dev->track_data[side], dev->disk_data + cur_pos, dev->sectors * ssize); - } else { - read_bytes = fread(dev->track_data[side], 1, dev->sectors * ssize, dev->f); - if (read_bytes < (dev->sectors * ssize)) - memset(dev->track_data[side] + read_bytes, 0xf6, (dev->sectors * ssize) - read_bytes); - } + if (dev->disk_at_once) { + cur_pos = (track * dev->sectors * ssize * dev->sides) + (side * dev->sectors * ssize); + memcpy(dev->track_data[side], dev->disk_data + cur_pos, (size_t) dev->sectors * ssize); + } else { + read_bytes = fread(dev->track_data[side], 1, (size_t) dev->sectors * ssize, dev->fp); + if (read_bytes < (dev->sectors * ssize)) + memset(dev->track_data[side] + read_bytes, 0xf6, (dev->sectors * ssize) - read_bytes); + } } d86f_reset_index_hole_pos(drive, 0); @@ -513,706 +541,707 @@ img_seek(int drive, int track) d86f_destroy_linked_lists(drive, 1); if (track > dev->tracks) { - d86f_zero_track(drive); - return; + d86f_zero_track(drive); + return; } if (!dev->xdf_type || dev->is_cqm) { - for (side = 0; side < dev->sides; side++) { - current_pos = d86f_prepare_pretrack(drive, side, 0); + for (side = 0; side < dev->sides; side++) { + current_pos = d86f_prepare_pretrack(drive, side, 0); - for (sector = 0; sector < dev->sectors; sector++) { - if (dev->is_cqm) { - if (dev->interleave) - sr = interleave(sector, dev->skew, dev->sectors); - else { - sr = sector + 1; - sr += dev->skew; - if (sr > dev->sectors) - sr -= dev->sectors; - } - } else { - if (dev->gap3_size < 68) - sr = interleave(sector, 1, dev->sectors); - else - sr = dev->dmf ? (dmf_r[sector]) : (sector + 1); - } - id[0] = track; - id[1] = side; - id[2] = sr; - id[3] = dev->sector_size; - dev->sector_pos_side[side][sr] = side; - dev->sector_pos[side][sr] = (sr - 1) * ssize; - current_pos = d86f_prepare_sector(drive, side, current_pos, id, &dev->track_data[side][(sr - 1) * ssize], ssize, dev->gap2_size, dev->gap3_size, 0); + for (sector = 0; sector < dev->sectors; sector++) { + if (dev->is_cqm) { + if (dev->interleave) + sr = interleave(sector, dev->skew, dev->sectors); + else { + sr = sector + 1; + sr += dev->skew; + if (sr > dev->sectors) + sr -= dev->sectors; + } + } else { + if (dev->gap3_size < 68) + sr = interleave(sector, 1, dev->sectors); + else + sr = dev->dmf ? (dmf_r[sector]) : (sector + 1); + } + id[0] = track; + id[1] = side; + id[2] = sr; + id[3] = dev->sector_size; + dev->sector_pos_side[side][sr] = side; + dev->sector_pos[side][sr] = (sr - 1) * ssize; + current_pos = d86f_prepare_sector(drive, side, current_pos, id, &dev->track_data[side][(sr - 1) * ssize], ssize, dev->gap2_size, dev->gap3_size, 0); - if (sector == 0) - d86f_initialize_last_sector_id(drive, id[0], id[1], id[2], id[3]); - } - } + if (sector == 0) + d86f_initialize_last_sector_id(drive, id[0], id[1], id[2], id[3]); + } + } } else { - total = dev->sectors; - img_pos = 0; - sside = 0; + total = dev->sectors; + img_pos = 0; + sside = 0; - /* Pass 1, get sector positions in the image. */ - for (sector = 0; sector < xdf_logical_sectors[current_xdft][!is_t0]; sector++) { - if (is_t0) { - img_pos = (sector % total) << 9; - sside = (sector >= total) ? 1 : 0; - } + /* Pass 1, get sector positions in the image. */ + for (sector = 0; sector < xdf_logical_sectors[current_xdft][!is_t0]; sector++) { + if (is_t0) { + img_pos = (sector % total) << 9; + sside = (sector >= total) ? 1 : 0; + } - if (xdf_img_sector.word) { - dev->sector_pos_side[xdf_img_sector.id.h][xdf_img_sector.id.r] = sside; - dev->sector_pos[xdf_img_sector.id.h][xdf_img_sector.id.r] = img_pos; - } + if (xdf_img_sector.word) { + dev->sector_pos_side[xdf_img_sector.id.h][xdf_img_sector.id.r] = sside; + dev->sector_pos[xdf_img_sector.id.h][xdf_img_sector.id.r] = img_pos; + } - if (! is_t0) { - img_pos += (128 << (xdf_img_sector.id.r & 7)); - if (img_pos >= (total << 9)) sside = 1; - img_pos %= (total << 9); - } - } + if (!is_t0) { + img_pos += (128 << (xdf_img_sector.id.r & 7)); + if (img_pos >= (total << 9)) + sside = 1; + img_pos %= (total << 9); + } + } - /* Pass 2, prepare the actual track. */ - for (side = 0; side < dev->sides; side++) { - current_pos = d86f_prepare_pretrack(drive, side, 0); + /* Pass 2, prepare the actual track. */ + for (side = 0; side < dev->sides; side++) { + current_pos = d86f_prepare_pretrack(drive, side, 0); - for (sector = 0; sector < xdf_physical_sectors[current_xdft][!is_t0]; sector++) { - array_sector = (side * xdf_physical_sectors[current_xdft][!is_t0]) + sector; - buf_side = dev->sector_pos_side[xdf_disk_sector.id.h][xdf_disk_sector.id.r]; - buf_pos = dev->sector_pos[xdf_disk_sector.id.h][xdf_disk_sector.id.r]; + for (sector = 0; sector < xdf_physical_sectors[current_xdft][!is_t0]; sector++) { + array_sector = (side * xdf_physical_sectors[current_xdft][!is_t0]) + sector; + buf_side = dev->sector_pos_side[xdf_disk_sector.id.h][xdf_disk_sector.id.r]; + buf_pos = dev->sector_pos[xdf_disk_sector.id.h][xdf_disk_sector.id.r]; - id[0] = track; - id[1] = xdf_disk_sector.id.h; - id[2] = xdf_disk_sector.id.r; + id[0] = track; + id[1] = xdf_disk_sector.id.h; + id[2] = xdf_disk_sector.id.r; - if (is_t0) { - id[3] = 2; - current_pos = d86f_prepare_sector(drive, side, current_pos, id, &dev->track_data[buf_side][buf_pos], ssize, dev->gap2_size, xdf_gap3_sizes[current_xdft][!is_t0], 0); - } else { - id[3] = id[2] & 7; - ssize = (128 << id[3]); - current_pos = d86f_prepare_sector(drive, side, xdf_trackx_spos[current_xdft][array_sector], id, &dev->track_data[buf_side][buf_pos], ssize, dev->gap2_size, xdf_gap3_sizes[current_xdft][!is_t0], 0); - } + if (is_t0) { + id[3] = 2; + current_pos = d86f_prepare_sector(drive, side, current_pos, id, &dev->track_data[buf_side][buf_pos], ssize, dev->gap2_size, xdf_gap3_sizes[current_xdft][!is_t0], 0); + } else { + id[3] = id[2] & 7; + ssize = (128 << id[3]); + current_pos = d86f_prepare_sector(drive, side, xdf_trackx_spos[current_xdft][array_sector], id, &dev->track_data[buf_side][buf_pos], ssize, dev->gap2_size, xdf_gap3_sizes[current_xdft][!is_t0], 0); + } - if (sector == 0) - d86f_initialize_last_sector_id(drive, id[0], id[1], id[2], id[3]); - } - } + if (sector == 0) + d86f_initialize_last_sector_id(drive, id[0], id[1], id[2], id[3]); + } + } } } - void img_init(void) { memset(img, 0x00, sizeof(img)); } - int is_divisible(uint16_t total, uint8_t what) { if ((total != 0) && (what != 0)) - return ((total % what) == 0); + return ((total % what) == 0); else - return 0; + return 0; } - void img_load(int drive, char *fn) { uint16_t bpb_bps; uint16_t bpb_total; - uint8_t bpb_mid; /* Media type ID. */ - uint8_t bpb_sectors; - uint8_t bpb_sides; - uint8_t cqm, ddi, fdf, fdi; + uint8_t bpb_mid; /* Media type ID. */ + uint8_t bpb_sectors; + uint8_t bpb_sides; + uint8_t cqm; + uint8_t ddi; + uint8_t fdf; + uint8_t fdi; uint16_t comment_len = 0; - int16_t block_len = 0; - uint32_t cur_pos = 0; - uint8_t rep_byte = 0; - uint8_t run = 0; - uint8_t real_run = 0; + int16_t block_len = 0; + uint32_t cur_pos = 0; + uint8_t rep_byte = 0; + uint8_t run = 0; + uint8_t real_run = 0; uint8_t *bpos; uint16_t track_bytes = 0; uint8_t *literal; - img_t *dev; - int temp_rate; - int guess = 0; - int size; - int i; + img_t *dev; + int temp_rate = 0; + int guess = 0; + int size; - ext = plat_get_extension(fn); + ext = path_get_extension(fn); d86f_unregister(drive); writeprot[drive] = 0; /* Allocate a drive block. */ - dev = (img_t *)malloc(sizeof(img_t)); + dev = (img_t *) malloc(sizeof(img_t)); memset(dev, 0x00, sizeof(img_t)); - dev->f = plat_fopen(fn, "rb+"); - if (dev->f == NULL) { - dev->f = plat_fopen(fn, "rb"); - if (dev->f == NULL) { - free(dev); - memset(floppyfns[drive], 0, sizeof(floppyfns[drive])); - return; - } - writeprot[drive] = 1; + dev->fp = plat_fopen(fn, "rb+"); + if (dev->fp == NULL) { + dev->fp = plat_fopen(fn, "rb"); + if (dev->fp == NULL) { + free(dev); + memset(floppyfns[drive], 0, sizeof(floppyfns[drive])); + return; + } + writeprot[drive] = 1; } if (ui_writeprot[drive]) - writeprot[drive] = 1; + writeprot[drive] = 1; fwriteprot[drive] = writeprot[drive]; cqm = ddi = fdf = fdi = 0; dev->interleave = dev->skew = 0; - if (! strcasecmp(ext, "DDI")) { - ddi = 1; - dev->base = 0x2400; + if (!strcasecmp(ext, "DDI")) { + ddi = 1; + dev->base = 0x2400; } else - dev->base = 0; + dev->base = 0; - if (! strcasecmp(ext, "FDI")) { - /* This is a Japanese FDI image, so let's read the header */ - img_log("img_load(): File is a Japanese FDI image...\n"); - fseek(dev->f, 0x10, SEEK_SET); - (void)fread(&bpb_bps, 1, 2, dev->f); - fseek(dev->f, 0x0C, SEEK_SET); - (void)fread(&size, 1, 4, dev->f); - bpb_total = size / bpb_bps; - fseek(dev->f, 0x08, SEEK_SET); - (void)fread(&(dev->base), 1, 4, dev->f); - fseek(dev->f, dev->base + 0x15, SEEK_SET); - bpb_mid = fgetc(dev->f); - if (bpb_mid < 0xF0) - bpb_mid = 0xF0; - fseek(dev->f, 0x14, SEEK_SET); - bpb_sectors = fgetc(dev->f); - fseek(dev->f, 0x18, SEEK_SET); - bpb_sides = fgetc(dev->f); - fseek(dev->f, dev->base, SEEK_SET); - first_byte = fgetc(dev->f); + if (!strcasecmp(ext, "FDI")) { + /* This is a Japanese FDI image, so let's read the header */ + img_log("img_load(): File is a Japanese FDI image...\n"); + fseek(dev->fp, 0x10, SEEK_SET); + (void) !fread(&bpb_bps, 1, 2, dev->fp); + fseek(dev->fp, 0x0C, SEEK_SET); + (void) !fread(&size, 1, 4, dev->fp); + bpb_total = size / bpb_bps; + fseek(dev->fp, 0x08, SEEK_SET); + (void) !fread(&(dev->base), 1, 4, dev->fp); + fseek(dev->fp, dev->base + 0x15, SEEK_SET); + bpb_mid = fgetc(dev->fp); + if (bpb_mid < 0xF0) + bpb_mid = 0xF0; + fseek(dev->fp, 0x14, SEEK_SET); + bpb_sectors = fgetc(dev->fp); + fseek(dev->fp, 0x18, SEEK_SET); + bpb_sides = fgetc(dev->fp); + fseek(dev->fp, dev->base, SEEK_SET); + first_byte = fgetc(dev->fp); - fdi = 1; - cqm = 0; - dev->disk_at_once = 0; - fdf = 0; + fdi = 1; + cqm = 0; + dev->disk_at_once = 0; + fdf = 0; } else { - /* Read the first four bytes. */ - fseek(dev->f, 0x00, SEEK_SET); - first_byte = fgetc(dev->f); - fseek(dev->f, 0x01, SEEK_SET); - second_byte = fgetc(dev->f); - fseek(dev->f, 0x02, SEEK_SET); - third_byte = fgetc(dev->f); - fseek(dev->f, 0x03, SEEK_SET); - fourth_byte = fgetc(dev->f); + /* Read the first four bytes. */ + fseek(dev->fp, 0x00, SEEK_SET); + first_byte = fgetc(dev->fp); + fseek(dev->fp, 0x01, SEEK_SET); + second_byte = fgetc(dev->fp); + fseek(dev->fp, 0x02, SEEK_SET); + third_byte = fgetc(dev->fp); + fseek(dev->fp, 0x03, SEEK_SET); + fourth_byte = fgetc(dev->fp); - if ((first_byte == 0x1A) && (second_byte == 'F') && - (third_byte == 'D') && (fourth_byte == 'F')) { - /* This is a FDF image. */ - img_log("img_load(): File is a FDF image...\n"); - fwriteprot[drive] = writeprot[drive] = 1; - fclose(dev->f); - dev->f = plat_fopen(fn, "rb"); + if ((first_byte == 0x1A) && (second_byte == 'F') && (third_byte == 'D') && (fourth_byte == 'F')) { + /* This is a FDF image. */ + img_log("img_load(): File is a FDF image...\n"); + fwriteprot[drive] = writeprot[drive] = 1; + fclose(dev->fp); + dev->fp = plat_fopen(fn, "rb"); - fdf = 1; - cqm = 0; - dev->disk_at_once = 1; + fdf = 1; + cqm = 0; + dev->disk_at_once = 1; - fseek(dev->f, 0x50, SEEK_SET); - (void)fread(&dev->tracks, 1, 4, dev->f); + fseek(dev->fp, 0x50, SEEK_SET); + (void) !fread(&dev->tracks, 1, 4, dev->fp); - /* Decode the entire file - pass 1, no write to buffer, determine length. */ - fseek(dev->f, 0x80, SEEK_SET); - size = 0; - track_bytes = 0; - bpos = dev->disk_data; - while (! feof(dev->f)) { - if (! track_bytes) { - /* Skip first 3 bytes - their meaning is unknown to us but could be a checksum. */ - first_byte = fgetc(dev->f); - fread(&track_bytes, 1, 2, dev->f); - img_log("Block header: %02X %04X ", first_byte, track_bytes); - /* Read the length of encoded data block. */ - fread(&track_bytes, 1, 2, dev->f); - img_log("%04X\n", track_bytes); - } + /* Decode the entire file - pass 1, no write to buffer, determine length. */ + fseek(dev->fp, 0x80, SEEK_SET); + size = 0; + track_bytes = 0; + bpos = dev->disk_data; + while (!feof(dev->fp)) { + if (!track_bytes) { + /* Skip first 3 bytes - their meaning is unknown to us but could be a checksum. */ + first_byte = fgetc(dev->fp); + (void) !fread(&track_bytes, 1, 2, dev->fp); + img_log("Block header: %02X %04X ", first_byte, track_bytes); + /* Read the length of encoded data block. */ + (void) !fread(&track_bytes, 1, 2, dev->fp); + img_log("%04X\n", track_bytes); + } - if (feof(dev->f)) break; + if (feof(dev->fp)) + break; - if (first_byte == 0xFF) break; + if (first_byte == 0xFF) + break; - if (first_byte) { - run = fgetc(dev->f); + if (first_byte) { + run = fgetc(dev->fp); - /* I *HAVE* to read something because fseek tries to be smart and never hits EOF, causing an infinite loop. */ - track_bytes--; + /* I *HAVE* to read something because fseek tries to be smart and never hits EOF, causing an infinite loop. */ + track_bytes--; - if (run & 0x80) { - /* Repeat. */ - track_bytes--; - rep_byte = fgetc(dev->f); - } else { - /* Literal. */ - track_bytes -= (run & 0x7f); - literal = (uint8_t *)malloc(run & 0x7f); - fread(literal, 1, (run & 0x7f), dev->f); - free(literal); - } - size += (run & 0x7f); - if (!track_bytes) - size -= fdf_suppress_final_byte; - } else { - /* Literal block. */ - size += (track_bytes - fdf_suppress_final_byte); - literal = (uint8_t *)malloc(track_bytes); - fread(literal, 1, track_bytes, dev->f); - free(literal); - track_bytes = 0; - } + if (run & 0x80) { + /* Repeat. */ + track_bytes--; + rep_byte = fgetc(dev->fp); + } else { + /* Literal. */ + track_bytes -= (run & 0x7f); + literal = (uint8_t *) malloc(run & 0x7f); + (void) !fread(literal, 1, (run & 0x7f), dev->fp); + free(literal); + } + size += (run & 0x7f); + if (!track_bytes) + size -= fdf_suppress_final_byte; + } else { + /* Literal block. */ + size += (track_bytes - fdf_suppress_final_byte); + literal = (uint8_t *) malloc(track_bytes); + (void) !fread(literal, 1, track_bytes, dev->fp); + free(literal); + track_bytes = 0; + } - if (feof(dev->f)) break; - } + if (feof(dev->fp)) + break; + } - /* Allocate the buffer. */ - dev->disk_data = (uint8_t *)malloc(size); + /* Allocate the buffer. */ + dev->disk_data = (uint8_t *) malloc(size); - /* Decode the entire file - pass 2, write to buffer. */ - fseek(dev->f, 0x80, SEEK_SET); - track_bytes = 0; - bpos = dev->disk_data; - while(! feof(dev->f)) { - if (! track_bytes) { - /* Skip first 3 bytes - their meaning is unknown to us but could be a checksum. */ - first_byte = fgetc(dev->f); - fread(&track_bytes, 1, 2, dev->f); - img_log("Block header: %02X %04X ", first_byte, track_bytes); - /* Read the length of encoded data block. */ - fread(&track_bytes, 1, 2, dev->f); - img_log("%04X\n", track_bytes); - } + /* Decode the entire file - pass 2, write to buffer. */ + fseek(dev->fp, 0x80, SEEK_SET); + track_bytes = 0; + bpos = dev->disk_data; + while (!feof(dev->fp)) { + if (!track_bytes) { + /* Skip first 3 bytes - their meaning is unknown to us but could be a checksum. */ + first_byte = fgetc(dev->fp); + (void) !fread(&track_bytes, 1, 2, dev->fp); + img_log("Block header: %02X %04X ", first_byte, track_bytes); + /* Read the length of encoded data block. */ + (void) !fread(&track_bytes, 1, 2, dev->fp); + img_log("%04X\n", track_bytes); + } - if (feof(dev->f)) break; + if (feof(dev->fp)) + break; - if (first_byte == 0xFF) break; + if (first_byte == 0xFF) + break; - if (first_byte) { - run = fgetc(dev->f); - real_run = (run & 0x7f); + if (first_byte) { + run = fgetc(dev->fp); + real_run = (run & 0x7f); - /* I *HAVE* to read something because fseek tries to be smart and never hits EOF, causing an infinite loop. */ - track_bytes--; + /* I *HAVE* to read something because fseek tries to be smart and never hits EOF, causing an infinite loop. */ + track_bytes--; - if (run & 0x80) { - /* Repeat. */ - track_bytes--; - if (! track_bytes) - real_run -= fdf_suppress_final_byte; - rep_byte = fgetc(dev->f); - if (real_run) - memset(bpos, rep_byte, real_run); - } else { - /* Literal. */ - track_bytes -= real_run; - literal = (uint8_t *) malloc(real_run); - fread(literal, 1, real_run, dev->f); - if (! track_bytes) - real_run -= fdf_suppress_final_byte; - if (run & 0x7f) - memcpy(bpos, literal, real_run); - free(literal); - } - bpos += real_run; - } else { - /* Literal block. */ - literal = (uint8_t *) malloc(track_bytes); - fread(literal, 1, track_bytes, dev->f); - memcpy(bpos, literal, track_bytes - fdf_suppress_final_byte); - free(literal); - bpos += (track_bytes - fdf_suppress_final_byte); - track_bytes = 0; - } + if (run & 0x80) { + /* Repeat. */ + track_bytes--; + if (!track_bytes) + real_run -= fdf_suppress_final_byte; + rep_byte = fgetc(dev->fp); + if (real_run) + memset(bpos, rep_byte, real_run); + } else { + /* Literal. */ + track_bytes -= real_run; + literal = (uint8_t *) malloc(real_run); + (void) !fread(literal, 1, real_run, dev->fp); + if (!track_bytes) + real_run -= fdf_suppress_final_byte; + if (run & 0x7f) + memcpy(bpos, literal, real_run); + free(literal); + } + bpos += real_run; + } else { + /* Literal block. */ + literal = (uint8_t *) malloc(track_bytes); + (void) !fread(literal, 1, track_bytes, dev->fp); + memcpy(bpos, literal, track_bytes - fdf_suppress_final_byte); + free(literal); + bpos += (track_bytes - fdf_suppress_final_byte); + track_bytes = 0; + } - if (feof(dev->f)) break; - } + if (feof(dev->fp)) + break; + } - first_byte = *dev->disk_data; + first_byte = *dev->disk_data; - bpb_bps = *(uint16_t *)(dev->disk_data + 0x0B); - bpb_total = *(uint16_t *)(dev->disk_data + 0x13); - bpb_mid = *(dev->disk_data + 0x15); - bpb_sectors = *(dev->disk_data + 0x18); - bpb_sides = *(dev->disk_data + 0x1A); + bpb_bps = *(uint16_t *) (dev->disk_data + 0x0B); + bpb_total = *(uint16_t *) (dev->disk_data + 0x13); + bpb_mid = *(dev->disk_data + 0x15); + bpb_sectors = *(dev->disk_data + 0x18); + bpb_sides = *(dev->disk_data + 0x1A); - /* Jump ahead to determine the image's geometry. */ - goto jump_if_fdf; - } + /* Jump ahead to determine the image's geometry. */ + goto jump_if_fdf; + } - if (((first_byte == 'C') && (second_byte == 'Q')) || - ((first_byte == 'c') && (second_byte == 'q'))) { - img_log("img_load(): File is a CopyQM image...\n"); - fwriteprot[drive] = writeprot[drive] = 1; - fclose(dev->f); - dev->f = plat_fopen(fn, "rb"); + if (((first_byte == 'C') && (second_byte == 'Q')) || ((first_byte == 'c') && (second_byte == 'q'))) { + img_log("img_load(): File is a CopyQM image...\n"); + fwriteprot[drive] = writeprot[drive] = 1; + fclose(dev->fp); + dev->fp = plat_fopen(fn, "rb"); - fseek(dev->f, 0x03, SEEK_SET); - fread(&bpb_bps, 1, 2, dev->f); + fseek(dev->fp, 0x03, SEEK_SET); + (void) !fread(&bpb_bps, 1, 2, dev->fp); #if 0 - fseek(dev->f, 0x0B, SEEK_SET); - fread(&bpb_total, 1, 2, dev->f); + fseek(dev->fp, 0x0B, SEEK_SET); + (void) !fread(&bpb_total, 1, 2, dev->fp); #endif - fseek(dev->f, 0x10, SEEK_SET); - bpb_sectors = fgetc(dev->f); - fseek(dev->f, 0x12, SEEK_SET); - bpb_sides = fgetc(dev->f); - fseek(dev->f, 0x5B, SEEK_SET); - dev->tracks = fgetc(dev->f); + fseek(dev->fp, 0x10, SEEK_SET); + bpb_sectors = fgetc(dev->fp); + fseek(dev->fp, 0x12, SEEK_SET); + bpb_sides = fgetc(dev->fp); + fseek(dev->fp, 0x5B, SEEK_SET); + dev->tracks = fgetc(dev->fp); - bpb_total = ((uint16_t)bpb_sectors) * ((uint16_t) bpb_sides) * dev->tracks; + bpb_total = ((uint16_t) bpb_sectors) * ((uint16_t) bpb_sides) * dev->tracks; - fseek(dev->f, 0x74, SEEK_SET); - dev->interleave = fgetc(dev->f); - fseek(dev->f, 0x76, SEEK_SET); - dev->skew = fgetc(dev->f); + fseek(dev->fp, 0x74, SEEK_SET); + dev->interleave = fgetc(dev->fp); + fseek(dev->fp, 0x76, SEEK_SET); + dev->skew = fgetc(dev->fp); - dev->disk_data = (uint8_t *) malloc(((uint32_t) bpb_total) * ((uint32_t) bpb_bps)); - memset(dev->disk_data, 0xf6, ((uint32_t) bpb_total) * ((uint32_t) bpb_bps)); + dev->disk_data = (uint8_t *) malloc(((uint32_t) bpb_total) * ((uint32_t) bpb_bps)); + memset(dev->disk_data, 0xf6, ((uint32_t) bpb_total) * ((uint32_t) bpb_bps)); - fseek(dev->f, 0x6F, SEEK_SET); - fread(&comment_len, 1, 2, dev->f); + fseek(dev->fp, 0x6F, SEEK_SET); + (void) !fread(&comment_len, 1, 2, dev->fp); - fseek(dev->f, -1, SEEK_END); - size = ftell(dev->f) + 1; + fseek(dev->fp, -1, SEEK_END); + size = ftell(dev->fp) + 1; - fseek(dev->f, 133 + comment_len, SEEK_SET); + fseek(dev->fp, 133 + comment_len, SEEK_SET); - cur_pos = 0; + cur_pos = 0; - while(! feof(dev->f)) { - fread(&block_len, 1, 2, dev->f); + while (!feof(dev->fp)) { + (void) !fread(&block_len, 1, 2, dev->fp); - if (! feof(dev->f)) { - if (block_len < 0) { - rep_byte = fgetc(dev->f); - block_len = -block_len; - if ((cur_pos + block_len) > ((uint32_t) bpb_total) * ((uint32_t) bpb_bps)) { - block_len = ((uint32_t) bpb_total) * ((uint32_t) bpb_bps) - cur_pos; - memset(dev->disk_data + cur_pos, rep_byte, block_len); - break; - } else { - memset(dev->disk_data + cur_pos, rep_byte, block_len); - cur_pos += block_len; - } - } else if (block_len > 0) { - if ((cur_pos + block_len) > ((uint32_t) bpb_total) * ((uint32_t) bpb_bps)) { - block_len = ((uint32_t) bpb_total) * ((uint32_t) bpb_bps) - cur_pos; - fread(dev->disk_data + cur_pos, 1, block_len, dev->f); - break; - } else { - fread(dev->disk_data + cur_pos, 1, block_len, dev->f); - cur_pos += block_len; - } - } - } - } - img_log("Finished reading CopyQM image data\n"); + if (!feof(dev->fp)) { + if (block_len < 0) { + rep_byte = fgetc(dev->fp); + block_len = -block_len; + if ((cur_pos + block_len) > ((uint32_t) bpb_total) * ((uint32_t) bpb_bps)) { + block_len = ((uint32_t) bpb_total) * ((uint32_t) bpb_bps) - cur_pos; + memset(dev->disk_data + cur_pos, rep_byte, block_len); + break; + } else { + memset(dev->disk_data + cur_pos, rep_byte, block_len); + cur_pos += block_len; + } + } else if (block_len > 0) { + if ((cur_pos + block_len) > ((uint32_t) bpb_total) * ((uint32_t) bpb_bps)) { + block_len = ((uint32_t) bpb_total) * ((uint32_t) bpb_bps) - cur_pos; + (void) !fread(dev->disk_data + cur_pos, 1, block_len, dev->fp); + break; + } else { + (void) !fread(dev->disk_data + cur_pos, 1, block_len, dev->fp); + cur_pos += block_len; + } + } + } + } + img_log("Finished reading CopyQM image data\n"); - cqm = 1; - dev->disk_at_once = 1; - fdf = 0; - first_byte = *dev->disk_data; - } else { - dev->disk_at_once = 0; - /* Read the BPB */ - if (ddi) { - img_log("img_load(): File is a DDI image...\n"); - fwriteprot[drive] = writeprot[drive] = 1; - } else - img_log("img_load(): File is a raw image...\n"); - fseek(dev->f, dev->base + 0x0B, SEEK_SET); - fread(&bpb_bps, 1, 2, dev->f); - fseek(dev->f, dev->base + 0x13, SEEK_SET); - fread(&bpb_total, 1, 2, dev->f); - fseek(dev->f, dev->base + 0x15, SEEK_SET); - bpb_mid = fgetc(dev->f); - fseek(dev->f, dev->base + 0x18, SEEK_SET); - bpb_sectors = fgetc(dev->f); - fseek(dev->f, dev->base + 0x1A, SEEK_SET); - bpb_sides = fgetc(dev->f); + cqm = 1; + dev->disk_at_once = 1; + fdf = 0; + first_byte = *dev->disk_data; + } else { + dev->disk_at_once = 0; + /* Read the BPB */ + if (ddi) { + img_log("img_load(): File is a DDI image...\n"); + fwriteprot[drive] = writeprot[drive] = 1; + } else + img_log("img_load(): File is a raw image...\n"); + fseek(dev->fp, dev->base + 0x0B, SEEK_SET); + (void) !fread(&bpb_bps, 1, 2, dev->fp); + fseek(dev->fp, dev->base + 0x13, SEEK_SET); + (void) !fread(&bpb_total, 1, 2, dev->fp); + fseek(dev->fp, dev->base + 0x15, SEEK_SET); + bpb_mid = fgetc(dev->fp); + fseek(dev->fp, dev->base + 0x18, SEEK_SET); + bpb_sectors = fgetc(dev->fp); + fseek(dev->fp, dev->base + 0x1A, SEEK_SET); + bpb_sides = fgetc(dev->fp); - cqm = 0; - } + cqm = 0; + } - fseek(dev->f, -1, SEEK_END); - size = ftell(dev->f) + 1; - if (ddi) - size -= 0x2400; + fseek(dev->fp, -1, SEEK_END); + size = ftell(dev->fp) + 1; + if (ddi) + size -= 0x2400; jump_if_fdf: - if (!ddi) - dev->base = 0; - fdi = 0; + if (!ddi) + dev->base = 0; + fdi = 0; } - dev->sides = 2; + dev->sides = 2; dev->sector_size = 2; img_log("BPB reports %i sides and %i bytes per sector (%i sectors total)\n", - bpb_sides, bpb_bps, bpb_total); + bpb_sides, bpb_bps, bpb_total); - /* Invalid conditions: */ - guess = (bpb_sides < 1); /* Sides < 1; */ - guess = guess || (bpb_sides > 2); /* Sides > 2; */ - guess = guess || !bps_is_valid(bpb_bps); /* Invalid number of bytes per sector; */ - guess = guess || !first_byte_is_valid(first_byte); /* Invalid first bytes; */ - guess = guess || !is_divisible(bpb_total, bpb_sectors); /* Total sectors not divisible by sectors per track; */ - guess = guess || !is_divisible(bpb_total, bpb_sides); /* Total sectors not divisible by sides. */ + /* Invalid conditions: */ + guess = (bpb_sides < 1); /* Sides < 1; */ + guess = guess || (bpb_sides > 2); /* Sides > 2; */ + guess = guess || !bps_is_valid(bpb_bps); /* Invalid number of bytes per sector; */ + guess = guess || !first_byte_is_valid(first_byte); /* Invalid first bytes; */ + guess = guess || !is_divisible(bpb_total, bpb_sectors); /* Total sectors not divisible by sectors per track; */ + guess = guess || !is_divisible(bpb_total, bpb_sides); /* Total sectors not divisible by sides. */ guess = guess || !fdd_get_check_bpb(drive); guess = guess && !fdi; guess = guess && !cqm; if (guess) { - /* - * The BPB is giving us a wacky number of sides and/or bytes - * per sector, therefore it is most probably not a BPB at all, - * so we have to guess the parameters from file size. - */ - if (size <= (160*1024)) { - dev->sectors = 8; - dev->tracks = 40; - dev->sides = 1; - } else if (size <= (180*1024)) { - dev->sectors = 9; - dev->tracks = 40; - dev->sides = 1; - } else if (size <= (315*1024)) { - dev->sectors = 9; - dev->tracks = 70; - dev->sides = 1; - } else if (size <= (320*1024)) { - dev->sectors = 8; - dev->tracks = 40; - } else if (size <= (320*1024)) { - dev->sectors = 8; - dev->tracks = 40; - } else if (size <= (360*1024)) { /*DD 360K*/ - dev->sectors = 9; - dev->tracks = 40; - } else if (size <= (400*1024)) { /*DEC RX50*/ - dev->sectors = 10; - dev->tracks = 80; - dev->sides = 1; - } else if (size <= (640*1024)) { /*DD 640K*/ - dev->sectors = 8; - dev->tracks = 80; - } else if (size <= (720*1024)) { /*DD 720K*/ - dev->sectors = 9; - dev->tracks = 80; - } else if (size <= (800*1024)) { /*DD*/ - dev->sectors = 10; - dev->tracks = 80; - } else if (size <= (880*1024)) { /*DD*/ - dev->sectors = 11; - dev->tracks = 80; - } else if (size <= (960*1024)) { /*DD*/ - dev->sectors = 12; - dev->tracks = 80; - } else if (size <= (1040*1024)) { /*DD*/ - dev->sectors = 13; - dev->tracks = 80; - } else if (size <= (1120*1024)) { /*DD*/ - dev->sectors = 14; - dev->tracks = 80; - } else if (size <= 1228800) { /*HD 1.2MB*/ - dev->sectors = 15; - dev->tracks = 80; - } else if (size <= 1261568) { /*HD 1.25MB Japanese*/ - dev->sectors = 8; - dev->tracks = 77; - dev->sector_size = 3; - } else if (size <= 1474560) { /*HD 1.44MB*/ - dev->sectors = 18; - dev->tracks = 80; - } else if (size <= 1556480) { /*HD*/ - dev->sectors = 19; - dev->tracks = 80; - } else if (size <= 1638400) { /*HD 1024 sector*/ - dev->sectors = 10; - dev->tracks = 80; - dev->sector_size = 3; - } else if (size <= 1720320) { /*DMF (Windows 95) */ - dev->sectors = 21; - dev->tracks = 80; - } else if (size <= 1741824) { - dev->sectors = 21; - dev->tracks = 81; - } else if (size <= 1763328) { - dev->sectors = 21; - dev->tracks = 82; - } else if (size <= 1802240) { /*HD 1024 sector*/ - dev->sectors = 22; - dev->tracks = 80; - dev->sector_size = 3; - } else if (size == 1884160) { /*XDF (OS/2 Warp)*/ - dev->sectors = 23; - dev->tracks = 80; - } else if (size <= 2949120) { /*ED*/ - dev->sectors = 36; - dev->tracks = 80; - } else if (size <= 3194880) { /*ED*/ - dev->sectors = 39; - dev->tracks = 80; - } else if (size <= 3276800) { /*ED*/ - dev->sectors = 40; - dev->tracks = 80; - } else if (size <= 3358720) { /*ED, maximum possible size*/ - dev->sectors = 41; - dev->tracks = 80; - } else if (size <= 3440640) { /*ED, maximum possible size*/ - dev->sectors = 42; - dev->tracks = 80; + /* + * The BPB is giving us a wacky number of sides and/or bytes + * per sector, therefore it is most probably not a BPB at all, + * so we have to guess the parameters from file size. + */ + if (size <= (160 * 1024)) { + dev->sectors = 8; + dev->tracks = 40; + dev->sides = 1; + } else if (size <= (180 * 1024)) { + dev->sectors = 9; + dev->tracks = 40; + dev->sides = 1; + } else if (size <= (315 * 1024)) { + dev->sectors = 9; + dev->tracks = 70; + dev->sides = 1; + } else if (size <= (320 * 1024)) { + dev->sectors = 8; + dev->tracks = 40; + } else if (size <= (360 * 1024)) { /*DD 360K*/ + dev->sectors = 9; + dev->tracks = 40; + } else if (size <= (400 * 1024)) { /*DEC RX50*/ + dev->sectors = 10; + dev->tracks = 80; + dev->sides = 1; + } else if (size <= (640 * 1024)) { /*DD 640K*/ + dev->sectors = 8; + dev->tracks = 80; + } else if (size <= (720 * 1024)) { /*DD 720K*/ + dev->sectors = 9; + dev->tracks = 80; + } else if (size <= (800 * 1024)) { /*DD*/ + dev->sectors = 10; + dev->tracks = 80; + } else if (size <= (880 * 1024)) { /*DD*/ + dev->sectors = 11; + dev->tracks = 80; + } else if (size <= (960 * 1024)) { /*DD*/ + dev->sectors = 12; + dev->tracks = 80; + } else if (size <= (1040 * 1024)) { /*DD*/ + dev->sectors = 13; + dev->tracks = 80; + } else if (size <= (1120 * 1024)) { /*DD*/ + dev->sectors = 14; + dev->tracks = 80; + } else if (size <= 1228800) { /*HD 1.2MB*/ + dev->sectors = 15; + dev->tracks = 80; + } else if (size <= 1261568) { /*HD 1.25MB Japanese*/ + dev->sectors = 8; + dev->tracks = 77; + dev->sector_size = 3; + } else if (size <= 1474560) { /*HD 1.44MB*/ + dev->sectors = 18; + dev->tracks = 80; + } else if (size <= 1556480) { /*HD*/ + dev->sectors = 19; + dev->tracks = 80; + } else if (size <= 1638400) { /*HD 1024 sector*/ + dev->sectors = 10; + dev->tracks = 80; + dev->sector_size = 3; + } else if (size <= 1720320) { /*DMF (Windows 95) */ + dev->sectors = 21; + dev->tracks = 80; + } else if (size <= 1741824) { + dev->sectors = 21; + dev->tracks = 81; + } else if (size <= 1763328) { + dev->sectors = 21; + dev->tracks = 82; + } else if (size <= 1802240) { /*HD 1024 sector*/ + dev->sectors = 22; + dev->tracks = 80; + dev->sector_size = 3; + } else if (size == 1884160) { /*XDF (OS/2 Warp)*/ + dev->sectors = 23; + dev->tracks = 80; + } else if (size <= 2949120) { /*ED*/ + dev->sectors = 36; + dev->tracks = 80; + } else if (size <= 3194880) { /*ED*/ + dev->sectors = 39; + dev->tracks = 80; + } else if (size <= 3276800) { /*ED*/ + dev->sectors = 40; + dev->tracks = 80; + } else if (size <= 3358720) { /*ED, maximum possible size*/ + dev->sectors = 41; + dev->tracks = 80; + } else if (size <= 3440640) { /*ED, maximum possible size*/ + dev->sectors = 42; + dev->tracks = 80; #if 0 - } else if (size <= 3440640) { /*HD 1024 sector*/ - dev->sectors = 21; - dev->tracks = 80; - dev->sector_size = 3; + } else if (size <= 3440640) { /*HD 1024 sector*/ + dev->sectors = 21; + dev->tracks = 80; + dev->sector_size = 3; #endif - } else if (size <= 3604480) { /*HD 1024 sector*/ - dev->sectors = 22; - dev->tracks = 80; - dev->sector_size = 3; - } else if (size <= 3610624) { /*ED, maximum possible size*/ - dev->sectors = 41; - dev->tracks = 86; - } else if (size <= 3698688) { /*ED, maximum possible size*/ - dev->sectors = 42; - dev->tracks = 86; - } else { - img_log("Image is bigger than can fit on an ED floppy, ejecting...\n"); - fclose(dev->f); - free(dev); - memset(floppyfns[drive], 0, sizeof(floppyfns[drive])); - return; - } + } else if (size <= 3604480) { /*HD 1024 sector*/ + dev->sectors = 22; + dev->tracks = 80; + dev->sector_size = 3; + } else if (size <= 3610624) { /*ED, maximum possible size*/ + dev->sectors = 41; + dev->tracks = 86; + } else if (size <= 3698688) { /*ED, maximum possible size*/ + dev->sectors = 42; + dev->tracks = 86; + } else { + img_log("Image is bigger than can fit on an ED floppy, ejecting...\n"); + fclose(dev->fp); + free(dev); + memset(floppyfns[drive], 0, sizeof(floppyfns[drive])); + return; + } - bpb_sides = dev->sides; - bpb_sectors = dev->sectors; - bpb_total = size >> (dev->sector_size + 7); + bpb_sides = dev->sides; + bpb_sectors = dev->sectors; + bpb_total = size >> (dev->sector_size + 7); } else { - /* The BPB readings appear to be valid, so let's set the values. */ - if (fdi) { - /* The image is a Japanese FDI, therefore we read the number of tracks from the header. */ - if (fseek(dev->f, 0x1C, SEEK_SET) == -1) - fatal("Japanese FDI: Failed when seeking to 0x1C\n"); - fread(&(dev->tracks), 1, 4, dev->f); - } else { - if (!cqm && !fdf) { - /* Number of tracks = number of total sectors divided by sides times sectors per track. */ - dev->tracks = ((uint32_t) bpb_total) / (((uint32_t) bpb_sides) * ((uint32_t) bpb_sectors)); - } - } + /* The BPB readings appear to be valid, so let's set the values. */ + if (fdi) { + /* The image is a Japanese FDI, therefore we read the number of tracks from the header. */ + if (fseek(dev->fp, 0x1C, SEEK_SET) == -1) + fatal("Japanese FDI: Failed when seeking to 0x1C\n"); + (void) !fread(&(dev->tracks), 1, 4, dev->fp); + } else { + if (!cqm && !fdf) { + /* Number of tracks = number of total sectors divided by sides times sectors per track. */ + dev->tracks = ((uint32_t) bpb_total) / (((uint32_t) bpb_sides) * ((uint32_t) bpb_sectors)); + } + } - /* The rest we just set directly from the BPB. */ - dev->sectors = bpb_sectors; - dev->sides = bpb_sides; + /* The rest we just set directly from the BPB. */ + dev->sectors = bpb_sectors; + dev->sides = bpb_sides; - /* The sector size. */ - dev->sector_size = sector_size_code(bpb_bps); + /* The sector size. */ + dev->sector_size = sector_size_code(bpb_bps); - temp_rate = 0xFF; + temp_rate = 0xFF; } - for (i = 0; i < 6; i++) { - if ((dev->sectors <= maximum_sectors[dev->sector_size][i]) || (dev->sectors == xdf_sectors[dev->sector_size][i])) { - bit_rate_300 = bit_rates_300[i]; - temp_rate = rates[i]; - dev->disk_flags = holes[i] << 1; - dev->xdf_type = (dev->sectors == xdf_sectors[dev->sector_size][i]) ? xdf_types[dev->sector_size][i] : 0; - if ((bit_rate_300 == 500.0) && (dev->sectors == 21) && (dev->sector_size == 2) && (dev->tracks >= 80) && (dev->tracks <= 82) && (dev->sides == 2)) { - /* This is a DMF floppy, set the flag so we know to interleave the sectors. */ - dev->dmf = 1; - } else { - if ((bit_rate_300 == 500.0) && (dev->sectors == 22) && (dev->sector_size == 2) && (dev->tracks >= 80) && (dev->tracks <= 82) && (dev->sides == 2)) { - /* This is marked specially because of the track flag (a RPM slow down is needed). */ - dev->interleave = 2; - } - dev->dmf = 0; - } + for (uint8_t i = 0; i < 6; i++) { + if ((dev->sectors <= maximum_sectors[dev->sector_size][i]) || (dev->sectors == xdf_sectors[dev->sector_size][i])) { + bit_rate_300 = bit_rates_300[i]; + temp_rate = rates[i]; + dev->disk_flags = holes[i] << 1; + dev->xdf_type = (dev->sectors == xdf_sectors[dev->sector_size][i]) ? xdf_types[dev->sector_size][i] : 0; + if ((bit_rate_300 == 500.0) && (dev->sectors == 21) && (dev->sector_size == 2) && (dev->tracks >= 80) && (dev->tracks <= 82) && (dev->sides == 2)) { + /* This is a DMF floppy, set the flag so we know to interleave the sectors. */ + dev->dmf = 1; + } else { + if ((bit_rate_300 == 500.0) && (dev->sectors == 22) && (dev->sector_size == 2) && (dev->tracks >= 80) && (dev->tracks <= 82) && (dev->sides == 2)) { + /* This is marked specially because of the track flag (a RPM slow down is needed). */ + dev->interleave = 2; + } + dev->dmf = 0; + } - img_log("Image parameters: bit rate 300: %f, temporary rate: %i, hole: %i, DMF: %i, XDF type: %i\n", bit_rate_300, temp_rate, dev->disk_flags >> 1, dev->dmf, dev->xdf_type); - break; - } + img_log("Image parameters: bit rate 300: %f, temporary rate: %i, hole: %i, DMF: %i, XDF type: %i\n", bit_rate_300, temp_rate, dev->disk_flags >> 1, dev->dmf, dev->xdf_type); + break; + } } if (temp_rate == 0xFF) { - img_log("Image is bigger than can fit on an ED floppy, ejecting...\n"); - fclose(dev->f); - free(dev); - memset(floppyfns[drive], 0, sizeof(floppyfns[drive])); - return; + img_log("Image is bigger than can fit on an ED floppy, ejecting...\n"); + fclose(dev->fp); + free(dev); + memset(floppyfns[drive], 0, sizeof(floppyfns[drive])); + return; } dev->gap2_size = (temp_rate == 3) ? 41 : 22; if (dev->dmf) - dev->gap3_size = 8; + dev->gap3_size = 8; else { - if (dev->sectors == -1) - dev->gap3_size = 8; - else - dev->gap3_size = gap3_sizes[temp_rate][dev->sector_size][dev->sectors]; + if (dev->sectors == -1) + dev->gap3_size = 8; + else + dev->gap3_size = gap3_sizes[temp_rate][dev->sector_size][dev->sectors]; } - if (! dev->gap3_size) { - img_log("ERROR: Floppy image of unknown format was inserted into drive %c:!\n", drive + 0x41); - fclose(dev->f); - free(dev); - memset(floppyfns[drive], 0, sizeof(floppyfns[drive])); - return; + if (!dev->gap3_size) { + img_log("ERROR: Floppy image of unknown format was inserted into drive %c:!\n", drive + 0x41); + fclose(dev->fp); + free(dev); + memset(floppyfns[drive], 0, sizeof(floppyfns[drive])); + return; } dev->track_width = 0; if (dev->tracks > 43) - dev->track_width = 1; /* If the image has more than 43 tracks, then the tracks are thin (96 tpi). */ + dev->track_width = 1; /* If the image has more than 43 tracks, then the tracks are thin (96 tpi). */ if (dev->sides == 2) - dev->disk_flags |= 8; /* If the has 2 sides, mark it as such. */ + dev->disk_flags |= 8; /* If the has 2 sides, mark it as such. */ if (dev->interleave == 2) { - dev->interleave = 1; - dev->disk_flags |= 0x60; + dev->interleave = 1; + dev->disk_flags |= 0x60; } - dev->track_flags = 0x08; /* IMG files are always assumed to be MFM-encoded. */ - dev->track_flags |= temp_rate & 3; /* Data rate. */ + dev->track_flags = 0x08; /* IMG files are always assumed to be MFM-encoded. */ + dev->track_flags |= temp_rate & 3; /* Data rate. */ if (temp_rate & 4) - dev->track_flags |= 0x20; /* RPM. */ + dev->track_flags |= 0x20; /* RPM. */ dev->is_cqm = cqm; img_log("Disk flags: %i, track flags: %i\n", - dev->disk_flags, dev->track_flags); + dev->disk_flags, dev->track_flags); /* Set up the drive unit. */ img[drive] = dev; /* Attach this format to the D86F engine. */ - d86f_handler[drive].disk_flags = disk_flags; - d86f_handler[drive].side_flags = side_flags; - d86f_handler[drive].writeback = write_back; - d86f_handler[drive].set_sector = set_sector; - d86f_handler[drive].read_data = poll_read_data; - d86f_handler[drive].write_data = poll_write_data; + d86f_handler[drive].disk_flags = disk_flags; + d86f_handler[drive].side_flags = side_flags; + d86f_handler[drive].writeback = write_back; + d86f_handler[drive].set_sector = set_sector; + d86f_handler[drive].read_data = poll_read_data; + d86f_handler[drive].write_data = poll_write_data; d86f_handler[drive].format_conditions = format_conditions; - d86f_handler[drive].extra_bit_cells = null_extra_bit_cells; - d86f_handler[drive].encoded_data = common_encoded_data; - d86f_handler[drive].read_revolution = common_read_revolution; - d86f_handler[drive].index_hole_pos = null_index_hole_pos; - d86f_handler[drive].get_raw_size = common_get_raw_size; - d86f_handler[drive].check_crc = 1; + d86f_handler[drive].extra_bit_cells = null_extra_bit_cells; + d86f_handler[drive].encoded_data = common_encoded_data; + d86f_handler[drive].read_revolution = common_read_revolution; + d86f_handler[drive].index_hole_pos = null_index_hole_pos; + d86f_handler[drive].get_raw_size = common_get_raw_size; + d86f_handler[drive].check_crc = 1; d86f_set_version(drive, 0x0063); drives[drive].seek = img_seek; @@ -1220,30 +1249,29 @@ jump_if_fdf: d86f_common_handlers(drive); } - void img_close(int drive) { img_t *dev = img[drive]; - if (dev == NULL) return; + if (dev == NULL) + return; d86f_unregister(drive); - if (dev->f != NULL) { - fclose(dev->f); - dev->f = NULL; + if (dev->fp != NULL) { + fclose(dev->fp); + dev->fp = NULL; } if (dev->disk_data != NULL) - free(dev->disk_data); + free(dev->disk_data); /* Release the memory. */ free(dev); img[drive] = NULL; } - void img_set_fdc(void *fdc) { diff --git a/src/floppy/fdd_json.c b/src/floppy/fdd_json.c index 69252e1c8..36a041a68 100644 --- a/src/floppy/fdd_json.c +++ b/src/floppy/fdd_json.c @@ -1,36 +1,34 @@ /* - * VARCem Virtual ARchaeological Computer EMulator. - * An emulator of (mostly) x86-based PC systems and devices, - * using the ISA,EISA,VLB,MCA and PCI system buses, roughly - * spanning the era between 1981 and 1995. + * VARCem Virtual ARchaeological Computer EMulator. + * An emulator of (mostly) x86-based PC systems and devices, + * using the ISA,EISA,VLB,MCA and PCI system buses, roughly + * spanning the era between 1981 and 1995. * - * This file is part of the VARCem Project. - * - * Implementation of the PCjs JSON floppy image format. + * Implementation of the PCjs JSON floppy image format. * * * - * Author: Fred N. van Kempen, + * Authors: Fred N. van Kempen, * - * Copyright 2017-2019 Fred N. van Kempen. + * Copyright 2017-2019 Fred N. van Kempen. * - * Redistribution and use in source and binary forms, with - * or without modification, are permitted provided that the - * following conditions are met: + * Redistribution and use in source and binary forms, with + * or without modification, are permitted provided that the + * following conditions are met: * - * 1. Redistributions of source code must retain the entire - * above notice, this list of conditions and the following - * disclaimer. + * 1. Redistributions of source code must retain the entire + * above notice, this list of conditions and the following + * disclaimer. * - * 2. Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the - * following disclaimer in the documentation and/or other - * materials provided with the distribution. + * 2. Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the + * following disclaimer in the documentation and/or other + * materials provided with the distribution. * - * 3. Neither the name of the copyright holder nor the names - * of its contributors may be used to endorse or promote - * products derived from this software without specific - * prior written permission. + * 3. Neither the name of the copyright holder nor the names + * of its contributors may be used to endorse or promote + * products derived from this software without specific + * prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT @@ -60,350 +58,355 @@ #include <86box/fdd_common.h> #include <86box/fdd_json.h> +#define NTRACKS 256 +#define NSIDES 2 +#define NSECTORS 256 -#define NTRACKS 256 -#define NSIDES 2 -#define NSECTORS 256 - - -typedef struct { - uint8_t track, /* ID: track number */ - side, /* side number */ - sector; /* sector number 1.. */ - uint16_t size; /* encoded size of sector */ - uint8_t *data; /* allocated data for it */ +typedef struct sector_t { + uint8_t track; /* ID: track number */ + uint8_t side; /* side number */ + uint8_t sector; /* sector number 1.. */ + uint16_t size; /* encoded size of sector */ + uint8_t *data; /* allocated data for it */ } sector_t; -typedef struct { - FILE *f; +typedef struct json_t { + FILE *fp; /* Geometry. */ - uint8_t tracks, /* number of tracks */ - sides, /* number of sides */ - sectors, /* number of sectors per track */ - spt[NTRACKS][NSIDES]; /* number of sectors per track */ + uint8_t tracks; /* number of tracks */ + uint8_t sides; /* number of sides */ + uint8_t sectors; /* number of sectors per track */ + uint8_t spt[NTRACKS][NSIDES]; /* number of sectors per track */ - uint8_t track, /* current track */ - side, /* current side */ - sector[NSIDES]; /* current sector */ + uint8_t track; /* current track */ + uint8_t side; /* current side */ + uint8_t sector[NSIDES]; /* current sector */ - uint8_t dmf; /* disk is DMF format */ - uint8_t interleave; + uint8_t dmf; /* disk is DMF format */ + uint8_t interleave; #if 0 - uint8_t skew; + uint8_t skew; #endif - uint8_t gap2_len; - uint8_t gap3_len; - int track_width; + uint8_t gap2_len; + uint8_t gap3_len; + int track_width; - uint16_t disk_flags, /* flags for the entire disk */ - track_flags; /* flags for the current track */ + uint16_t disk_flags; /* flags for the entire disk */ + uint16_t track_flags; /* flags for the current track */ - uint8_t interleave_ordered[NTRACKS][NSIDES]; + uint8_t interleave_ordered[NTRACKS][NSIDES]; - sector_t sects[NTRACKS][NSIDES][NSECTORS]; + sector_t sects[NTRACKS][NSIDES][NSECTORS]; } json_t; - -static json_t *images[FDD_NUM]; - +static json_t *images[FDD_NUM]; #define ENABLE_JSON_LOG 1 #ifdef ENABLE_JSON_LOG int json_do_log = ENABLE_JSON_LOG; - static void json_log(const char *fmt, ...) { - va_list ap; + va_list ap; - if (json_do_log) - { - va_start(ap, fmt); - pclog_ex(fmt, ap); - va_end(ap); - } + if (json_do_log) { + va_start(ap, fmt); + pclog_ex(fmt, ap); + va_end(ap); + } } #else -#define json_log(fmt, ...) +# define json_log(fmt, ...) #endif - static void handle(json_t *dev, char *name, char *str) { sector_t *sec = NULL; - uint32_t l, pat; - uint8_t *p; - char *sp; - int i, s; + uint32_t l; + uint32_t pat; + uint8_t *p; + char *sp; + int s; /* Point to the currently selected sector. */ - sec = &dev->sects[dev->track][dev->side][dev->dmf-1]; + sec = &dev->sects[dev->track][dev->side][dev->dmf - 1]; /* If no name given, assume sector is done. */ if (name == NULL) { - /* If no buffer, assume one with 00's. */ - if (sec->data == NULL) { - sec->data = (uint8_t *)malloc(sec->size); - memset(sec->data, 0x00, sec->size); - } + /* If no buffer, assume one with 00's. */ + if (sec->data == NULL) { + sec->data = (uint8_t *) malloc(sec->size); + memset(sec->data, 0x00, sec->size); + } - /* Encode the sector size. */ - sec->size = fdd_sector_size_code(sec->size); + /* Encode the sector size. */ + sec->size = fdd_sector_size_code(sec->size); - /* Set up the rest of the Sector ID. */ - sec->track = dev->track; - sec->side = dev->side; + /* Set up the rest of the Sector ID. */ + sec->track = dev->track; + sec->side = dev->side; - return; + return; } - if (! strcmp(name, "sector")) { - sec->sector = atoi(str); - sec->size = 512; - } else if (! strcmp(name, "length")) { - sec->size = atoi(str); - } else if (! strcmp(name, "pattern")) { - pat = atol(str); + if (!strcmp(name, "sector")) { + sec->sector = atoi(str); + sec->size = 512; + } else if (!strcmp(name, "length")) { + sec->size = atoi(str); + } else if (!strcmp(name, "pattern")) { + pat = atol(str); - if (sec->data == NULL) - sec->data = (uint8_t *)malloc(sec->size); - p = sec->data; - s = (sec->size / sizeof(uint32_t)); - for (i=0; i>= 8; - *p++ = (l & 0x000000ff); - l >>= 8; - *p++ = (l & 0x000000ff); - l >>= 8; - *p++ = (l & 0x000000ff); - } - } else if (! strcmp(name, "data")) { - if (sec->data == NULL) - sec->data = (uint8_t *)malloc(sec->size); - p = sec->data; - while (str && *str) { - sp = strchr(str, ','); - if (sp != NULL) *sp++ = '\0'; - l = atol(str); + if (sec->data == NULL) + sec->data = (uint8_t *) malloc(sec->size); + p = sec->data; + s = (sec->size / sizeof(uint32_t)); + for (int i = 0; i < s; i++) { + l = pat; + *p++ = (l & 0x000000ff); + l >>= 8; + *p++ = (l & 0x000000ff); + l >>= 8; + *p++ = (l & 0x000000ff); + l >>= 8; + *p++ = (l & 0x000000ff); + } + } else if (!strcmp(name, "data")) { + if (sec->data == NULL) + sec->data = (uint8_t *) malloc(sec->size); + p = sec->data; + while (str && *str) { + sp = strchr(str, ','); + if (sp != NULL) + *sp++ = '\0'; + l = atol(str); - *p++ = (l & 0x000000ff); - l >>= 8; - *p++ = (l & 0x000000ff); - l >>= 8; - *p++ = (l & 0x000000ff); - l >>= 8; - *p++ = (l & 0x000000ff); + *p++ = (l & 0x000000ff); + l >>= 8; + *p++ = (l & 0x000000ff); + l >>= 8; + *p++ = (l & 0x000000ff); + l >>= 8; + *p++ = (l & 0x000000ff); - str = sp; - } + str = sp; + } } } - static int unexpect(int c, int state, int level) { json_log("JSON: Unexpected '%c' in state %d/%d.\n", c, state, level); - return(-1); + return (-1); } - static int load_image(json_t *dev) { - char buff[4096], name[32]; - int c, i, j, state, level; + char buff[4096]; + char name[32]; + int c; + int state; + int level; char *ptr; - if (dev->f == NULL) { - json_log("JSON: no file loaded!\n"); - return(0); + if (dev->fp == NULL) { + json_log("JSON: no file loaded!\n"); + return 0; } /* Initialize. */ - for (i=0; isects[i][j], 0x00, sizeof(sector_t)); + for (uint16_t i = 0; i < NTRACKS; i++) { + for (uint8_t j = 0; j < NSIDES; j++) + memset(dev->sects[i][j], 0x00, sizeof(sector_t)); } - dev->track = dev->side = dev->dmf = 0; /* "dmf" is "sector#" */ + dev->track = dev->side = dev->dmf = 0; /* "dmf" is "sector#" */ /* Now run the state machine. */ - ptr = NULL; + ptr = NULL; level = state = 0; while (state >= 0) { - /* Get a character from the input. */ - c = fgetc(dev->f); - if ((c == EOF) || ferror(dev->f)) { - state = -1; - break; - } + /* Get a character from the input. */ + c = fgetc(dev->fp); + if ((c == EOF) || ferror(dev->fp)) { + state = -1; + break; + } - /* Process it. */ - switch(state) { - case 0: /* read level header */ - dev->dmf = 1; - if ((c != '[') && (c != '{') && (c != '\r') && (c != '\n')) { - state = unexpect(c, state, level); - } else if (c == '[') { - if (++level == 3) - state++; - } - break; + /* Process it. */ + switch (state) { + case 0: /* read level header */ + dev->dmf = 1; + if ((c != '[') && (c != '{') && (c != '\r') && (c != '\n')) { + state = unexpect(c, state, level); + } else if (c == '[') { + if (++level == 3) + state++; + } + break; - case 1: /* read sector header */ - if (c != '{') - state = unexpect(c, state, level); - else - state++; - break; + case 1: /* read sector header */ + if (c != '{') + state = unexpect(c, state, level); + else + state++; + break; - case 2: /* begin sector data name */ - if (c != '\"') { - state = unexpect(c, state, level); - } else { - ptr = name; - state++; - } - break; + case 2: /* begin sector data name */ + if (c != '\"') { + state = unexpect(c, state, level); + } else { + ptr = name; + state++; + } + break; - case 3: /* read sector data name */ - if (c == '\"') { - *ptr = '\0'; - state++; - } else { - *ptr++ = c; - } - break; + case 3: /* read sector data name */ + if (c == '\"') { + *ptr = '\0'; + state++; + } else { + *ptr++ = c; + } + break; - case 4: /* end of sector data name */ - if (c != ':') { - state = unexpect(c, state, level); - } else { - ptr = buff; - state++; - } - break; + case 4: /* end of sector data name */ + if (c != ':') { + state = unexpect(c, state, level); + } else { + ptr = buff; + state++; + } + break; - case 5: /* read sector value data */ - switch(c) { - case ',': - case '}': - *ptr = '\0'; - handle(dev, name, buff); + case 5: /* read sector value data */ + switch (c) { + case ',': + case '}': + *ptr = '\0'; + handle(dev, name, buff); - if (c == '}') - state = 7; /* done */ - else - state = 2; /* word */ - break; + if (c == '}') + state = 7; /* done */ + else + state = 2; /* word */ + break; - case '[': - state++; - break; + case '[': + state++; + break; - default: - *ptr++ = c; - } - break; + default: + *ptr++ = c; + } + break; - case 6: /* read sector data complex */ - if (c != ']') - *ptr++ = c; - else - state = 5; - break; + case 6: /* read sector data complex */ + if (c != ']') + *ptr++ = c; + else + state = 5; + break; - case 7: /* sector done */ - handle(dev, NULL, NULL); - switch(c) { - case ',': /* next sector */ - dev->dmf++; - state = 1; - break; + case 7: /* sector done */ + handle(dev, NULL, NULL); + switch (c) { + case ',': /* next sector */ + dev->dmf++; + state = 1; + break; - case ']': /* all sectors done */ - if (--level == 0) - state = -1; - else state++; - break; + case ']': /* all sectors done */ + if (--level == 0) + state = -1; + else + state++; + break; - default: - state = unexpect(c, state, level); - } - break; + default: + state = unexpect(c, state, level); + } + break; - case 8: /* side done */ - switch(c) { - case ',': /* next side */ - state = 0; - break; + case 8: /* side done */ + switch (c) { + case ',': /* next side */ + state = 0; + break; - case ']': /* all sides done */ - if (--level == 0) - state = -1; - else state++; - break; + case ']': /* all sides done */ + if (--level == 0) + state = -1; + else + state++; + break; - default: - state = unexpect(c, state, level); - } - dev->spt[dev->track][dev->side] = dev->dmf; - dev->side++; - break; + default: + state = unexpect(c, state, level); + } + dev->spt[dev->track][dev->side] = dev->dmf; + dev->side++; + break; - case 9: /* track done */ - switch(c) { - case ',': /* next track */ - dev->side = 0; - state = 0; - break; + case 9: /* track done */ + switch (c) { + case ',': /* next track */ + dev->side = 0; + state = 0; + break; - case ']': /* all tracks done */ - if (--level == 0) - state = -1; - else state++; - break; + case ']': /* all tracks done */ + if (--level == 0) + state = -1; + else + state++; + break; - default: - state = unexpect(c, state, level); - } - dev->track++; - break; - } + default: + state = unexpect(c, state, level); + } + dev->track++; + break; + default: + break; + } } /* Save derived values. */ dev->tracks = dev->track; - dev->sides = dev->side; + dev->sides = dev->side; - return(1); + return 1; } - /* Seek the heads to a track, and prepare to read data from that track. */ static void json_seek(int drive, int track) { - uint8_t id[4] = { 0,0,0,0 }; - json_t *dev = images[drive]; - int side, sector; - int rate, gap2, gap3, pos; - int ssize, rsec, asec; + uint8_t id[4] = { 0, 0, 0, 0 }; + json_t *dev = images[drive]; + int rate; + int gap2; + int gap3; + int pos; + int ssize; + int rsec; + int asec; - if (dev->f == NULL) { - json_log("JSON: seek: no file loaded!\n"); - return; + if (dev->fp == NULL) { + json_log("JSON: seek: no file loaded!\n"); + return; } /* Allow for doublestepping tracks. */ - if (! dev->track_width && fdd_doublestep_40(drive)) track /= 2; + if (!dev->track_width && fdd_doublestep_40(drive)) + track /= 2; /* Set the new track. */ dev->track = track; @@ -416,134 +419,125 @@ json_seek(int drive, int track) d86f_destroy_linked_lists(drive, 1); if (track > dev->tracks) { - d86f_zero_track(drive); - return; + d86f_zero_track(drive); + return; } - for (side=0; sidesides; side++) { - /* Get transfer rate for this side. */ - rate = dev->track_flags & 0x07; - if (!rate && (dev->track_flags & 0x20)) rate = 4; + for (uint8_t side = 0; side < dev->sides; side++) { + /* Get transfer rate for this side. */ + rate = dev->track_flags & 0x07; + if (!rate && (dev->track_flags & 0x20)) + rate = 4; - /* Get correct GAP3 value for this side. */ - gap3 = fdd_get_gap3_size(rate, - dev->sects[track][side][0].size, - dev->spt[track][side]); + /* Get correct GAP3 value for this side. */ + gap3 = fdd_get_gap3_size(rate, + dev->sects[track][side][0].size, + dev->spt[track][side]); - /* Get correct GAP2 value for this side. */ - gap2 = ((dev->track_flags & 0x07) >= 3) ? 41 : 22; + /* Get correct GAP2 value for this side. */ + gap2 = ((dev->track_flags & 0x07) >= 3) ? 41 : 22; - pos = d86f_prepare_pretrack(drive, side, 0); + pos = d86f_prepare_pretrack(drive, side, 0); - for (sector=0; sectorspt[track][side]; sector++) { - rsec = dev->sects[track][side][sector].sector; - asec = sector; + for (uint8_t sector = 0; sector < dev->spt[track][side]; sector++) { + rsec = dev->sects[track][side][sector].sector; + asec = sector; - id[0] = track; - id[1] = side; - id[2] = rsec; - if (dev->sects[track][side][asec].size > 255) - perror("fdd_json.c: json_seek: sector size too big."); - id[3] = dev->sects[track][side][asec].size & 0xff; - ssize = fdd_sector_code_size(dev->sects[track][side][asec].size & 0xff); + id[0] = track; + id[1] = side; + id[2] = rsec; + if (dev->sects[track][side][asec].size > 255) + perror("fdd_json.c: json_seek: sector size too big."); + id[3] = dev->sects[track][side][asec].size & 0xff; + ssize = fdd_sector_code_size(dev->sects[track][side][asec].size & 0xff); - pos = d86f_prepare_sector( - drive, side, pos, id, - dev->sects[track][side][asec].data, - ssize, gap2, gap3, - 0 /*flags*/ - ); + pos = d86f_prepare_sector( + drive, side, pos, id, + dev->sects[track][side][asec].data, + ssize, gap2, gap3, + 0 /*flags*/ + ); - if (sector == 0) - d86f_initialize_last_sector_id(drive,id[0],id[1],id[2],id[3]); - } + if (sector == 0) + d86f_initialize_last_sector_id(drive, id[0], id[1], id[2], id[3]); + } } } - static uint16_t disk_flags(int drive) { - json_t *dev = images[drive]; + const json_t *dev = images[drive]; - return(dev->disk_flags); + return (dev->disk_flags); } - static uint16_t track_flags(int drive) { - json_t *dev = images[drive]; + const json_t *dev = images[drive]; - return(dev->track_flags); + return (dev->track_flags); } - static void set_sector(int drive, int side, uint8_t c, uint8_t h, uint8_t r, uint8_t n) { json_t *dev = images[drive]; - int i; dev->sector[side] = 0; /* Make sure we are on the desired track. */ - if (c != dev->track) return; + if (c != dev->track) + return; /* Set the desired side. */ dev->side = side; /* Now loop over all sector ID's on this side to find our sector. */ - for (i=0; ispt[c][side]; i++) { - if ((dev->sects[dev->track][side][i].track == c) && - (dev->sects[dev->track][side][i].side == h) && - (dev->sects[dev->track][side][i].sector == r) && - (dev->sects[dev->track][side][i].size == n)) { - dev->sector[side] = i; - } + for (uint8_t i = 0; i < dev->spt[c][side]; i++) { + if ((dev->sects[dev->track][side][i].track == c) && (dev->sects[dev->track][side][i].side == h) && (dev->sects[dev->track][side][i].sector == r) && (dev->sects[dev->track][side][i].size == n)) { + dev->sector[side] = i; + } } } - static uint8_t poll_read_data(int drive, int side, uint16_t pos) { - json_t *dev = images[drive]; - uint8_t sec = dev->sector[side]; + const json_t *dev = images[drive]; + uint8_t sec = dev->sector[side]; - return(dev->sects[dev->track][side][sec].data[pos]); + return (dev->sects[dev->track][side][sec].data[pos]); } - void json_init(void) { memset(images, 0x00, sizeof(images)); } - void json_load(int drive, char *fn) { - double bit_rate; - int temp_rate; - sector_t *sec; - json_t *dev; - int i; + double bit_rate; + int temp_rate; + const sector_t *sec; + json_t *dev; /* Just in case- remove ourselves from 86F. */ d86f_unregister(drive); /* Allocate a drive block. */ - dev = (json_t *)malloc(sizeof(json_t)); + dev = (json_t *) malloc(sizeof(json_t)); memset(dev, 0x00, sizeof(json_t)); /* Open the image file. */ - dev->f = plat_fopen(fn, "rb"); - if (dev->f == NULL) { - free(dev); - memset(fn, 0x00, sizeof(char)); - return; + dev->fp = plat_fopen(fn, "rb"); + if (dev->fp == NULL) { + free(dev); + memset(fn, 0x00, sizeof(char)); + return; } /* Our images are always RO. */ @@ -553,17 +547,17 @@ json_load(int drive, char *fn) images[drive] = dev; /* Load all sectors from the image file. */ - if (! load_image(dev)) { - json_log("JSON: failed to initialize\n"); - (void)fclose(dev->f); - free(dev); - images[drive] = NULL; - memset(fn, 0x00, sizeof(char)); - return; + if (!load_image(dev)) { + json_log("JSON: failed to initialize\n"); + (void) fclose(dev->fp); + free(dev); + images[drive] = NULL; + memset(fn, 0x00, sizeof(char)); + return; } json_log("JSON(%d): %s (%i tracks, %i sides, %i sectors)\n", - drive, fn, dev->tracks, dev->sides, dev->spt[0][0]); + drive, fn, dev->tracks, dev->sides, dev->spt[0][0]); /* * If the image has more than 43 tracks, then @@ -574,7 +568,7 @@ json_load(int drive, char *fn) /* If the image has 2 sides, mark it as such. */ dev->disk_flags = 0x00; if (dev->sides == 2) - dev->disk_flags |= 0x08; + dev->disk_flags |= 0x08; /* JSON files are always assumed to be MFM-encoded. */ dev->track_flags = 0x08; @@ -585,94 +579,91 @@ json_load(int drive, char *fn) #endif temp_rate = 0xff; - sec = &dev->sects[0][0][0]; - for (i=0; i<6; i++) { - if (dev->spt[0][0] > fdd_max_sectors[sec->size][i]) continue; + sec = &dev->sects[0][0][0]; + for (uint8_t i = 0; i < 6; i++) { + if (dev->spt[0][0] > fdd_max_sectors[sec->size][i]) + continue; - bit_rate = fdd_bit_rates_300[i]; - temp_rate = fdd_rates[i]; - dev->disk_flags |= (fdd_holes[i] << 1); + bit_rate = fdd_bit_rates_300[i]; + temp_rate = fdd_rates[i]; + dev->disk_flags |= (fdd_holes[i] << 1); - if ((bit_rate == 500.0) && (dev->spt[0][0] == 21) && - (sec->size == 2) && (dev->tracks >= 80) && - (dev->tracks <= 82) && (dev->sides == 2)) { - /* - * This is a DMF floppy, set the flag so - * we know to interleave the sectors. - */ - dev->dmf = 1; - } else { - if ((bit_rate == 500.0) && (dev->spt[0][0] == 22) && - (sec->size == 2) && (dev->tracks >= 80) && - (dev->tracks <= 82) && (dev->sides == 2)) { - /* - * This is marked specially because of the - * track flag (a RPM slow down is needed). - */ - dev->interleave = 2; - } + if ((bit_rate == 500.0) && (dev->spt[0][0] == 21) && (sec->size == 2) && (dev->tracks >= 80) && (dev->tracks <= 82) && (dev->sides == 2)) { + /* + * This is a DMF floppy, set the flag so + * we know to interleave the sectors. + */ + dev->dmf = 1; + } else { + if ((bit_rate == 500.0) && (dev->spt[0][0] == 22) && (sec->size == 2) && (dev->tracks >= 80) && (dev->tracks <= 82) && (dev->sides == 2)) { + /* + * This is marked specially because of the + * track flag (a RPM slow down is needed). + */ + dev->interleave = 2; + } - dev->dmf = 0; - } + dev->dmf = 0; + } - break; + break; } if (temp_rate == 0xff) { - json_log("JSON: invalid image (temp_rate=0xff)\n"); - (void)fclose(dev->f); - dev->f = NULL; - free(dev); - images[drive] = NULL; - memset(fn, 0x00, sizeof(char)); - return; + json_log("JSON: invalid image (temp_rate=0xff)\n"); + (void) fclose(dev->fp); + dev->fp = NULL; + free(dev); + images[drive] = NULL; + memset(fn, 0x00, sizeof(char)); + return; } if (dev->interleave == 2) { - dev->interleave = 1; - dev->disk_flags |= 0x60; + dev->interleave = 1; + dev->disk_flags |= 0x60; } dev->gap2_len = (temp_rate == 3) ? 41 : 22; if (dev->dmf) - dev->gap3_len = 8; - else - dev->gap3_len = fdd_get_gap3_size(temp_rate,sec->size,dev->spt[0][0]); + dev->gap3_len = 8; + else + dev->gap3_len = fdd_get_gap3_size(temp_rate, sec->size, dev->spt[0][0]); - if (! dev->gap3_len) { - json_log("JSON: image of unknown format was inserted into drive %c:!\n", - 'C'+drive); - (void)fclose(dev->f); - dev->f = NULL; - free(dev); - images[drive] = NULL; - memset(fn, 0x00, sizeof(char)); - return; + if (!dev->gap3_len) { + json_log("JSON: image of unknown format was inserted into drive %c:!\n", + 'C' + drive); + (void) fclose(dev->fp); + dev->fp = NULL; + free(dev); + images[drive] = NULL; + memset(fn, 0x00, sizeof(char)); + return; } - dev->track_flags |= (temp_rate & 0x03); /* data rate */ + dev->track_flags |= (temp_rate & 0x03); /* data rate */ if (temp_rate & 0x04) - dev->track_flags |= 0x20; /* RPM */ + dev->track_flags |= 0x20; /* RPM */ json_log(" disk_flags: 0x%02x, track_flags: 0x%02x, GAP3 length: %i\n", - dev->disk_flags, dev->track_flags, dev->gap3_len); + dev->disk_flags, dev->track_flags, dev->gap3_len); json_log(" bit rate 300: %.2f, temporary rate: %i, hole: %i, DMF: %i\n", - bit_rate, temp_rate, (dev->disk_flags >> 1), dev->dmf); + bit_rate, temp_rate, (dev->disk_flags >> 1), dev->dmf); /* Set up handlers for 86F layer. */ - d86f_handler[drive].disk_flags = disk_flags; - d86f_handler[drive].side_flags = track_flags; - d86f_handler[drive].writeback = null_writeback; - d86f_handler[drive].set_sector = set_sector; - d86f_handler[drive].read_data = poll_read_data; - d86f_handler[drive].write_data = null_write_data; + d86f_handler[drive].disk_flags = disk_flags; + d86f_handler[drive].side_flags = track_flags; + d86f_handler[drive].writeback = null_writeback; + d86f_handler[drive].set_sector = set_sector; + d86f_handler[drive].read_data = poll_read_data; + d86f_handler[drive].write_data = null_write_data; d86f_handler[drive].format_conditions = null_format_conditions; - d86f_handler[drive].extra_bit_cells = null_extra_bit_cells; - d86f_handler[drive].encoded_data = common_encoded_data; - d86f_handler[drive].read_revolution = common_read_revolution; - d86f_handler[drive].index_hole_pos = null_index_hole_pos; - d86f_handler[drive].get_raw_size = common_get_raw_size; - d86f_handler[drive].check_crc = 1; + d86f_handler[drive].extra_bit_cells = null_extra_bit_cells; + d86f_handler[drive].encoded_data = common_encoded_data; + d86f_handler[drive].read_revolution = common_read_revolution; + d86f_handler[drive].index_hole_pos = null_index_hole_pos; + d86f_handler[drive].get_raw_size = common_get_raw_size; + d86f_handler[drive].check_crc = 1; d86f_set_version(drive, 0x0063); d86f_common_handlers(drive); @@ -680,33 +671,32 @@ json_load(int drive, char *fn) drives[drive].seek = json_seek; } - /* Close the image. */ void json_close(int drive) { json_t *dev = images[drive]; - int t, h, s; - if (dev == NULL) return; + if (dev == NULL) + return; /* Unlink image from the system. */ d86f_unregister(drive); /* Release all the sector buffers. */ - for (t=0; t<256; t++) { - for (h=0; h<2; h++) { - memset(dev->sects[t][h], 0x00, sizeof(sector_t)); - for (s=0; s<256; s++) { - if (dev->sects[t][h][s].data != NULL) - free(dev->sects[t][h][s].data); - dev->sects[t][h][s].data = NULL; - } - } + for (uint16_t t = 0; t < 256; t++) { + for (uint8_t h = 0; h < 2; h++) { + memset(dev->sects[t][h], 0x00, sizeof(sector_t)); + for (uint16_t s = 0; s < 256; s++) { + if (dev->sects[t][h][s].data != NULL) + free(dev->sects[t][h][s].data); + dev->sects[t][h][s].data = NULL; + } + } } - if (dev->f != NULL) - (void)fclose(dev->f); + if (dev->fp != NULL) + (void) fclose(dev->fp); /* Release the memory. */ free(dev); diff --git a/src/floppy/fdd_mfm.c b/src/floppy/fdd_mfm.c index a16314ba2..b4c859d5d 100644 --- a/src/floppy/fdd_mfm.c +++ b/src/floppy/fdd_mfm.c @@ -1,18 +1,18 @@ /* - * 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. + * 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. + * This file is part of the 86Box distribution. * - * Implementation of the HxC MFM image format. + * Implementation of the HxC MFM image format. * * * - * Authors: Miran Grca, + * Authors: Miran Grca, * - * Copyright 2018,2019 Miran Grca. + * Copyright 2018-2019 Miran Grca. */ #include #include @@ -31,227 +31,219 @@ #include <86box/fdd_mfm.h> #include <86box/fdc.h> +#pragma pack(push, 1) +typedef struct mfm_header_t { + uint8_t hdr_name[7]; -#pragma pack(push,1) -typedef struct { - uint8_t hdr_name[7]; + uint16_t tracks_no; + uint8_t sides_no; - uint16_t tracks_no; - uint8_t sides_no; + uint16_t rpm; + uint16_t bit_rate; + uint8_t if_type; - uint16_t rpm; - uint16_t bit_rate; - uint8_t if_type; - - uint32_t track_list_offset; + uint32_t track_list_offset; } mfm_header_t; -typedef struct { - uint16_t track_no; - uint8_t side_no; - uint32_t track_size; - uint32_t track_offset; +typedef struct mfm_track_t { + uint16_t track_no; + uint8_t side_no; + uint32_t track_size; + uint32_t track_offset; } mfm_track_t; -typedef struct { - uint16_t track_no; - uint8_t side_no; - uint16_t rpm; - uint16_t bit_rate; - uint32_t track_size; - uint32_t track_offset; +typedef struct mfm_adv_track_t { + uint16_t track_no; + uint8_t side_no; + uint16_t rpm; + uint16_t bit_rate; + uint32_t track_size; + uint32_t track_offset; } mfm_adv_track_t; #pragma pack(pop) -typedef struct { - FILE *f; +typedef struct mfm_t { + FILE *fp; - mfm_header_t hdr; - mfm_track_t *tracks; - mfm_adv_track_t *adv_tracks; + mfm_header_t hdr; + mfm_track_t *tracks; + mfm_adv_track_t *adv_tracks; - uint16_t disk_flags, pad; - uint16_t side_flags[2]; + uint16_t disk_flags; + uint16_t pad; + uint16_t side_flags[2]; - int br_rounded, rpm_rounded, - total_tracks, cur_track; + int br_rounded; + int rpm_rounded; + int total_tracks; + int cur_track; - uint8_t track_data[2][256*1024]; + uint8_t track_data[2][256 * 1024]; } mfm_t; - -static mfm_t *mfm[FDD_NUM]; -static fdc_t *mfm_fdc; - +static mfm_t *mfm[FDD_NUM]; +static fdc_t *mfm_fdc; #ifdef ENABLE_MFM_LOG int mfm_do_log = ENABLE_MFM_LOG; - static void mfm_log(const char *fmt, ...) { - va_list ap; + va_list ap; - if (mfm_do_log) - { - va_start(ap, fmt); - pclog_ex(fmt, ap); - va_end(ap); - } + if (mfm_do_log) { + va_start(ap, fmt); + pclog_ex(fmt, ap); + va_end(ap); + } } #else -#define mfm_log(fmt, ...) +# define mfm_log(fmt, ...) #endif - static int get_track_index(int drive, int side, int track) { - mfm_t *dev = mfm[drive]; - int i, ret = -1; + const mfm_t *dev = mfm[drive]; + int ret = -1; - for (i = 0; i < dev->total_tracks; i++) { - if ((dev->tracks[i].track_no == track) && - (dev->tracks[i].side_no == side)) { - ret = i; - break; - } + for (int i = 0; i < dev->total_tracks; i++) { + if ((dev->tracks[i].track_no == track) && (dev->tracks[i].side_no == side)) { + ret = i; + break; + } } return ret; } - static int get_adv_track_index(int drive, int side, int track) { - mfm_t *dev = mfm[drive]; - int i, ret = -1; + const mfm_t *dev = mfm[drive]; + int ret = -1; - for (i = 0; i < dev->total_tracks; i++) { - if ((dev->adv_tracks[i].track_no == track) && - (dev->adv_tracks[i].side_no == side)) { - ret = i; - break; - } + for (int i = 0; i < dev->total_tracks; i++) { + if ((dev->adv_tracks[i].track_no == track) && (dev->adv_tracks[i].side_no == side)) { + ret = i; + break; + } } return ret; } - static void get_adv_track_bitrate(int drive, int side, int track, int *br, int *rpm) { - mfm_t *dev = mfm[drive]; - int track_index; - double dbr; + const mfm_t *dev = mfm[drive]; + int track_index; + double dbr; track_index = get_adv_track_index(drive, side, track); if (track_index == -1) { - *br = 250; - *rpm = 300; + *br = 250; + *rpm = 300; } else { - dbr = round(((double) dev->adv_tracks[track_index].bit_rate) / 50.0) * 50.0; - *br = ((int) dbr); - dbr = round(((double) dev->adv_tracks[track_index].rpm) / 60.0) * 60.0; - *rpm = ((int) dbr); + dbr = round(((double) dev->adv_tracks[track_index].bit_rate) / 50.0) * 50.0; + *br = ((int) dbr); + dbr = round(((double) dev->adv_tracks[track_index].rpm) / 60.0) * 60.0; + *rpm = ((int) dbr); } } - static void set_disk_flags(int drive) { - int br = 250, rpm = 300; - mfm_t *dev = mfm[drive]; - uint16_t temp_disk_flags = 0x1080; /* We ALWAYS claim to have extra bit cells, even if the actual amount is 0; - Bit 12 = 1, bits 6, 5 = 0 - extra bit cells field specifies the entire - amount of bit cells per track. */ + int br = 250; + int rpm = 300; + mfm_t *dev = mfm[drive]; + uint16_t temp_disk_flags = 0x1080; /* We ALWAYS claim to have extra bit cells, even if the actual amount is 0; + Bit 12 = 1, bits 6, 5 = 0 - extra bit cells field specifies the entire + amount of bit cells per track. */ /* If this is the modified MFM format, get bit rate (and RPM) from track 0 instead. */ if (dev->hdr.if_type & 0x80) - get_adv_track_bitrate(drive, 0, 0, &br, &rpm); + get_adv_track_bitrate(drive, 0, 0, &br, &rpm); else { - br = dev->br_rounded; - rpm = dev->rpm_rounded; + br = dev->br_rounded; + rpm = dev->rpm_rounded; } switch (br) { - case 500: - temp_disk_flags |= 2; - break; + default: + case 250: + case 300: + temp_disk_flags |= 0; + break; - case 300: - case 250: - default: - temp_disk_flags |= 0; - break; + case 500: + temp_disk_flags |= 2; + break; - case 1000: - temp_disk_flags |= 4; - break; + case 1000: + temp_disk_flags |= 4; + break; } if (dev->hdr.sides_no == 2) - temp_disk_flags |= 8; + temp_disk_flags |= 8; dev->disk_flags = temp_disk_flags; } - static uint16_t disk_flags(int drive) { - mfm_t *dev = mfm[drive]; + const mfm_t *dev = mfm[drive]; return dev->disk_flags; } - static void set_side_flags(int drive, int side) { - mfm_t *dev = mfm[drive]; + mfm_t *dev = mfm[drive]; uint16_t temp_side_flags = 0; - int br = 250, rpm = 300; + int br = 250; + int rpm = 300; if (dev->hdr.if_type & 0x80) - get_adv_track_bitrate(drive, side, dev->cur_track, &br, &rpm); + get_adv_track_bitrate(drive, side, dev->cur_track, &br, &rpm); else { - br = dev->br_rounded; - rpm = dev->rpm_rounded; + br = dev->br_rounded; + rpm = dev->rpm_rounded; } /* 300 kbps @ 360 rpm = 250 kbps @ 200 rpm */ if ((br == 300) && (rpm == 360)) { - br = 250; - rpm = 300; + br = 250; + rpm = 300; } switch (br) { - case 500: - temp_side_flags = 0; - break; + case 500: + temp_side_flags = 0; + break; - case 300: - temp_side_flags = 1; - break; + case 300: + temp_side_flags = 1; + break; - case 250: - default: - temp_side_flags = 2; - break; + case 250: + default: + temp_side_flags = 2; + break; - case 1000: - temp_side_flags = 3; - break; + case 1000: + temp_side_flags = 3; + break; } if (rpm == 360) - temp_side_flags |= 0x20; + temp_side_flags |= 0x20; /* * Set the encoding value to match that provided by the FDC. @@ -262,112 +254,110 @@ set_side_flags(int drive, int side) dev->side_flags[side] = temp_side_flags; } - static uint16_t side_flags(int drive) { - mfm_t *dev = mfm[drive]; - int side; + const mfm_t *dev = mfm[drive]; + int side; side = fdd_get_head(drive); return dev->side_flags[side]; } - static uint32_t get_raw_size(int drive, int side) { - mfm_t *dev = mfm[drive]; - int track_index, is_300_rpm; - int br = 250, rpm = 300; + const mfm_t *dev = mfm[drive]; + int track_index; + int is_300_rpm; + int br = 250; + int rpm = 300; if (dev->hdr.if_type & 0x80) { - track_index = get_adv_track_index(drive, side, dev->cur_track); - get_adv_track_bitrate(drive, 0, 0, &br, &rpm); + track_index = get_adv_track_index(drive, side, dev->cur_track); + get_adv_track_bitrate(drive, 0, 0, &br, &rpm); } else { - track_index = get_track_index(drive, side, dev->cur_track); - br = dev->br_rounded; - rpm = dev->rpm_rounded; + track_index = get_track_index(drive, side, dev->cur_track); + br = dev->br_rounded; + rpm = dev->rpm_rounded; } is_300_rpm = (rpm == 300); if (track_index == -1) { - mfm_log("MFM: Unable to find track (%i, %i)\n", dev->cur_track, side); - switch (br) { - case 250: - default: - return is_300_rpm ? 100000 : 83333; - case 300: - return is_300_rpm ? 120000 : 100000; - case 500: - return is_300_rpm ? 200000 : 166666; - case 1000: - return is_300_rpm ? 400000 : 333333; - } + mfm_log("MFM: Unable to find track (%i, %i)\n", dev->cur_track, side); + switch (br) { + default: + case 250: + return is_300_rpm ? 100000 : 83333; + case 300: + return is_300_rpm ? 120000 : 100000; + case 500: + return is_300_rpm ? 200000 : 166666; + case 1000: + return is_300_rpm ? 400000 : 333333; + } } /* Bit 7 on - my extension of the HxC MFM format to output exact bitcell counts for each track instead of rounded byte counts. */ if (dev->hdr.if_type & 0x80) - return dev->adv_tracks[track_index].track_size; + return dev->adv_tracks[track_index].track_size; else - return dev->tracks[track_index].track_size * 8; + return dev->tracks[track_index].track_size * 8; } - static int32_t extra_bit_cells(int drive, int side) { return (int32_t) get_raw_size(drive, side); } - static uint16_t * encoded_data(int drive, int side) { mfm_t *dev = mfm[drive]; - return((uint16_t *)dev->track_data[side]); + return ((uint16_t *) dev->track_data[side]); } - void mfm_read_side(int drive, int side) { mfm_t *dev = mfm[drive]; - int track_index, track_size; - int track_bytes, ret; + int track_index; + int track_size; + int track_bytes; + int ret; if (dev->hdr.if_type & 0x80) - track_index = get_adv_track_index(drive, side, dev->cur_track); + track_index = get_adv_track_index(drive, side, dev->cur_track); else - track_index = get_track_index(drive, side, dev->cur_track); + track_index = get_track_index(drive, side, dev->cur_track); - track_size = get_raw_size(drive, side); + track_size = get_raw_size(drive, side); track_bytes = track_size >> 3; if (track_size & 0x07) - track_bytes++; + track_bytes++; if (track_index == -1) - memset(dev->track_data[side], 0x00, track_bytes); + memset(dev->track_data[side], 0x00, track_bytes); else { - if (dev->hdr.if_type & 0x80) - ret = fseek(dev->f, dev->adv_tracks[track_index].track_offset, SEEK_SET); - else - ret = fseek(dev->f, dev->tracks[track_index].track_offset, SEEK_SET); - if (ret == -1) - fatal("mfm_read_side(): Error seeking to the beginning of the file\n"); - if (fread(dev->track_data[side], 1, track_bytes, dev->f) != track_bytes) - fatal("mfm_read_side(): Error reading track bytes\n"); + if (dev->hdr.if_type & 0x80) + ret = fseek(dev->fp, dev->adv_tracks[track_index].track_offset, SEEK_SET); + else + ret = fseek(dev->fp, dev->tracks[track_index].track_offset, SEEK_SET); + if (ret == -1) + fatal("mfm_read_side(): Error seeking to the beginning of the file\n"); + if (fread(dev->track_data[side], 1, track_bytes, dev->fp) != track_bytes) + fatal("mfm_read_side(): Error reading track bytes\n"); } mfm_log("drive = %i, side = %i, dev->cur_track = %i, track_index = %i, track_size = %i\n", - drive, side, dev->cur_track, track_index, track_size); + drive, side, dev->cur_track, track_index, track_size); } - void mfm_seek(int drive, int track) { @@ -376,18 +366,18 @@ mfm_seek(int drive, int track) mfm_log("mfm_seek(%i, %i)\n", drive, track); if (fdd_doublestep_40(drive)) { - if (dev->hdr.tracks_no <= 43) - track /= 2; + if (dev->hdr.tracks_no <= 43) + track /= 2; } dev->cur_track = track; d86f_set_cur_track(drive, track); - if (dev->f == NULL) - return; + if (dev->fp == NULL) + return; if (track < 0) - track = 0; + track = 0; mfm_read_side(drive, 0); mfm_read_side(drive, 1); @@ -396,46 +386,45 @@ mfm_seek(int drive, int track) set_side_flags(drive, 1); } - void mfm_load(int drive, char *fn) { mfm_t *dev; double dbr; - int i, size; + int size; writeprot[drive] = fwriteprot[drive] = 1; /* Allocate a drive block. */ - dev = (mfm_t *)malloc(sizeof(mfm_t)); + dev = (mfm_t *) malloc(sizeof(mfm_t)); memset(dev, 0x00, sizeof(mfm_t)); - dev->f = plat_fopen(fn, "rb"); - if (dev->f == NULL) { - free(dev); - memset(floppyfns[drive], 0, sizeof(floppyfns[drive])); - return; + dev->fp = plat_fopen(fn, "rb"); + if (dev->fp == NULL) { + free(dev); + memset(floppyfns[drive], 0, sizeof(floppyfns[drive])); + return; } d86f_unregister(drive); /* Read the header. */ size = sizeof(mfm_header_t); - if (fread(&dev->hdr, 1, size, dev->f) != size) - fatal("mfm_load(): Error reading header\n"); + if (fread(&dev->hdr, 1, size, dev->fp) != size) + fatal("mfm_load(): Error reading header\n"); /* Calculate tracks * sides, allocate the tracks array, and read it. */ dev->total_tracks = dev->hdr.tracks_no * dev->hdr.sides_no; if (dev->hdr.if_type & 0x80) { - dev->adv_tracks = (mfm_adv_track_t *) malloc(dev->total_tracks * sizeof(mfm_adv_track_t)); - size = dev->total_tracks * sizeof(mfm_adv_track_t); - if (fread(dev->adv_tracks, 1, size, dev->f) != size) - fatal("mfm_load(): Error reading advanced tracks\n"); + dev->adv_tracks = (mfm_adv_track_t *) malloc(dev->total_tracks * sizeof(mfm_adv_track_t)); + size = dev->total_tracks * sizeof(mfm_adv_track_t); + if (fread(dev->adv_tracks, 1, size, dev->fp) != size) + fatal("mfm_load(): Error reading advanced tracks\n"); } else { - dev->tracks = (mfm_track_t *) malloc(dev->total_tracks * sizeof(mfm_track_t)); - size = dev->total_tracks * sizeof(mfm_track_t); - if (fread(dev->tracks, 1, size, dev->f) != size) - fatal("mfm_load(): Error reading tracks\n"); + dev->tracks = (mfm_track_t *) malloc(dev->total_tracks * sizeof(mfm_track_t)); + size = dev->total_tracks * sizeof(mfm_track_t); + if (fread(dev->tracks, 1, size, dev->fp) != size) + fatal("mfm_load(): Error reading tracks\n"); } /* The chances of finding a HxC MFM image of a single-sided thin track @@ -444,30 +433,30 @@ mfm_load(int drive, char *fn) side and 80+ tracks instead of 2 sides and <= 43 tracks, so if we have detected such an image, convert the track numbers. */ if ((dev->hdr.tracks_no > 43) && (dev->hdr.sides_no == 1)) { - dev->hdr.tracks_no >>= 1; - dev->hdr.sides_no <<= 1; + dev->hdr.tracks_no >>= 1; + dev->hdr.sides_no <<= 1; - for (i = 0; i < dev->total_tracks; i++) { - if (dev->hdr.if_type & 0x80) { - dev->adv_tracks[i].side_no <<= 1; - dev->adv_tracks[i].side_no |= (dev->adv_tracks[i].track_no & 1); - dev->adv_tracks[i].track_no >>= 1; - } else { - dev->tracks[i].side_no <<= 1; - dev->tracks[i].side_no |= (dev->tracks[i].track_no & 1); - dev->tracks[i].track_no >>= 1; - } - } + for (int i = 0; i < dev->total_tracks; i++) { + if (dev->hdr.if_type & 0x80) { + dev->adv_tracks[i].side_no <<= 1; + dev->adv_tracks[i].side_no |= (dev->adv_tracks[i].track_no & 1); + dev->adv_tracks[i].track_no >>= 1; + } else { + dev->tracks[i].side_no <<= 1; + dev->tracks[i].side_no |= (dev->tracks[i].track_no & 1); + dev->tracks[i].track_no >>= 1; + } + } } if (!(dev->hdr.if_type & 0x80)) { - dbr = round(((double) dev->hdr.bit_rate) / 50.0) * 50.0; - dev->br_rounded = (int) dbr; - mfm_log("Rounded bit rate: %i kbps\n", dev->br_rounded); + dbr = round(((double) dev->hdr.bit_rate) / 50.0) * 50.0; + dev->br_rounded = (int) dbr; + mfm_log("Rounded bit rate: %i kbps\n", dev->br_rounded); - dbr = round(((double) dev->hdr.rpm) / 60.0) * 60.0; - dev->rpm_rounded = (int) dbr; - mfm_log("Rounded RPM: %i kbps\n", dev->rpm_rounded); + dbr = round(((double) dev->hdr.rpm) / 60.0) * 60.0; + dev->rpm_rounded = (int) dbr; + mfm_log("Rounded RPM: %i kbps\n", dev->rpm_rounded); } /* Set up the drive unit. */ @@ -476,18 +465,18 @@ mfm_load(int drive, char *fn) set_disk_flags(drive); /* Attach this format to the D86F engine. */ - d86f_handler[drive].disk_flags = disk_flags; - d86f_handler[drive].side_flags = side_flags; - d86f_handler[drive].writeback = null_writeback; - d86f_handler[drive].set_sector = null_set_sector; - d86f_handler[drive].write_data = null_write_data; + d86f_handler[drive].disk_flags = disk_flags; + d86f_handler[drive].side_flags = side_flags; + d86f_handler[drive].writeback = null_writeback; + d86f_handler[drive].set_sector = null_set_sector; + d86f_handler[drive].write_data = null_write_data; d86f_handler[drive].format_conditions = null_format_conditions; - d86f_handler[drive].extra_bit_cells = extra_bit_cells; - d86f_handler[drive].encoded_data = encoded_data; - d86f_handler[drive].read_revolution = common_read_revolution; - d86f_handler[drive].index_hole_pos = null_index_hole_pos; - d86f_handler[drive].get_raw_size = get_raw_size; - d86f_handler[drive].check_crc = 1; + d86f_handler[drive].extra_bit_cells = extra_bit_cells; + d86f_handler[drive].encoded_data = encoded_data; + d86f_handler[drive].read_revolution = common_read_revolution; + d86f_handler[drive].index_hole_pos = null_index_hole_pos; + d86f_handler[drive].get_raw_size = get_raw_size; + d86f_handler[drive].check_crc = 1; d86f_set_version(drive, D86FVER); d86f_common_handlers(drive); @@ -497,35 +486,34 @@ mfm_load(int drive, char *fn) mfm_log("Loaded as MFM\n"); } - void mfm_close(int drive) { mfm_t *dev = mfm[drive]; - if (dev == NULL) return; + if (dev == NULL) + return; d86f_unregister(drive); drives[drive].seek = NULL; if (dev->tracks) - free(dev->tracks); + free(dev->tracks); if (dev->adv_tracks) - free(dev->adv_tracks); + free(dev->adv_tracks); - if (dev->f) - fclose(dev->f); + if (dev->fp) + fclose(dev->fp); /* Release the memory. */ free(dev); mfm[drive] = NULL; } - void mfm_set_fdc(void *fdc) { - mfm_fdc = (fdc_t *)fdc; + mfm_fdc = (fdc_t *) fdc; } diff --git a/src/floppy/fdd_td0.c b/src/floppy/fdd_td0.c index 6fa4ab96d..46e29343b 100644 --- a/src/floppy/fdd_td0.c +++ b/src/floppy/fdd_td0.c @@ -1,32 +1,32 @@ /* - * 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. + * 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. + * This file is part of the 86Box distribution. * - * Implementation of the Teledisk floppy image format. + * Implementation of the Teledisk floppy image format. * * * - * Authors: Milodrag Milanovic, - * Haruhiko OKUMURA, - * Haruyasu YOSHIZAKI, - * Kenji RIKITAKE, - * Miran Grca, - * Fred N. van Kempen, + * Authors: Milodrag Milanovic, + * Haruhiko OKUMURA, + * Haruyasu YOSHIZAKI, + * Kenji RIKITAKE, + * Miran Grca, + * Fred N. van Kempen, * - * Based on Japanese version 29-NOV-1988 - * LZSS coded by Haruhiko OKUMURA - * Adaptive Huffman Coding coded by Haruyasu YOSHIZAKI - * Edited and translated to English by Kenji RIKITAKE + * Based on Japanese version 29-NOV-1988 + * LZSS coded by Haruhiko OKUMURA + * Adaptive Huffman Coding coded by Haruyasu YOSHIZAKI + * Edited and translated to English by Kenji RIKITAKE * - * Copyright 2013-2019 Milodrag Milanovic. - * Copyright 1988-2019 Haruhiko OKUMURA. - * Copyright 1988-2019 Haruyasu YOSHIZAKI. - * Copyright 1988-2019 Kenji RIKITAKE. - * Copyright 2016-2019 Miran Grca. + * Copyright 2013-2019 Milodrag Milanovic. + * Copyright 1988-2019 Haruhiko OKUMURA. + * Copyright 1988-2019 Haruyasu YOSHIZAKI. + * Copyright 1988-2019 Kenji RIKITAKE. + * Copyright 2016-2019 Miran Grca. */ #include #include @@ -43,90 +43,91 @@ #include <86box/fdd_td0.h> #include <86box/fdc.h> - -#define BUFSZ 512 /* new input buffer */ -#define TD0_MAX_BUFSZ (1024UL*1024UL*4UL) +#define BUFSZ 512 /* new input buffer */ +#define TD0_MAX_BUFSZ (1024UL * 1024UL * 4UL) /* LZSS Parameters */ -#define N 4096 /* Size of string buffer */ -#define F 60 /* Size of look-ahead buffer */ -#define THRESHOLD 2 -#define NIL N /* End of tree's node */ +#define N 4096 /* Size of string buffer */ +#define F 60 /* Size of look-ahead buffer */ +#define THRESHOLD 2 +#define NIL N /* End of tree's node */ /* Huffman coding parameters */ -#define N_CHAR (256-THRESHOLD+F) /* code (= 0..N_CHAR-1) */ -#define T (N_CHAR*2-1) /* Size of table */ -#define R (T-1) /* root position */ -#define MAX_FREQ 0x8000 - /* update when cumulative frequency */ - /* reaches to this value */ +#define N_CHAR (256 - THRESHOLD + F) /* code (= 0..N_CHAR-1) */ +#define T (N_CHAR * 2 - 1) /* Size of table */ +#define R (T - 1) /* root position */ +#define MAX_FREQ 0x8000 +/* update when cumulative frequency */ +/* reaches to this value */ -typedef struct { - uint16_t r, - bufcnt,bufndx,bufpos, /* string buffer */ - /* the following to allow block reads - from input in next_word() */ - ibufcnt,ibufndx; /* input buffer counters */ - uint8_t inbuf[BUFSZ]; /* input buffer */ +typedef struct tdlzhuf_t { + uint16_t r; + uint16_t bufcnt; /* string buffer */ + uint16_t bufndx; /* string buffer */ + uint16_t bufpos; /* string buffer */ + /* the following to allow block reads + from input in next_word() */ + uint16_t ibufcnt; /* input buffer counters */ + uint16_t ibufndx; /* input buffer counters */ + uint8_t inbuf[BUFSZ]; /* input buffer */ } tdlzhuf; -typedef struct { - FILE *fdd_file; - off_t fdd_file_offset; +typedef struct td0dsk_t { + FILE *fdd_file; + off_t fdd_file_offset; - tdlzhuf tdctl; - uint8_t text_buf[N + F - 1]; - uint16_t freq[T + 1]; /* cumulative freq table */ + tdlzhuf tdctl; + uint8_t text_buf[N + F - 1]; + uint16_t freq[T + 1]; /* cumulative freq table */ /* * pointing parent nodes. * area [T..(T + N_CHAR - 1)] are pointers for leaves */ - int16_t prnt[T + N_CHAR]; + int16_t prnt[T + N_CHAR]; /* pointing children nodes (son[], son[] + 1)*/ - int16_t son[T]; + int16_t son[T]; - uint16_t getbuf; - uint8_t getlen; + uint16_t getbuf; + uint8_t getlen; } td0dsk_t; -typedef struct { - uint8_t track; - uint8_t head; - uint8_t sector; - uint8_t size; - uint8_t flags; - uint8_t fm; - uint8_t *data; +typedef struct td0_sector_t { + uint8_t track; + uint8_t head; + uint8_t sector; + uint8_t size; + uint8_t flags; + uint8_t fm; + uint8_t *data; } td0_sector_t; -typedef struct { - FILE *f; +typedef struct td0_t { + FILE *fp; - int tracks; - int track_width; - int sides; - uint16_t disk_flags; - uint16_t default_track_flags; - uint16_t side_flags[256][2]; - uint8_t max_sector_size; - uint8_t track_in_file[256][2]; + int tracks; + int track_width; + int sides; + uint16_t disk_flags; + uint16_t default_track_flags; + uint16_t side_flags[256][2]; + uint8_t max_sector_size; + uint8_t track_in_file[256][2]; td0_sector_t sects[256][2][256]; - uint8_t track_spt[256][2]; - uint8_t gap3_len; - uint16_t current_side_flags[2]; - int track; - int current_sector_index[2]; - uint8_t calculated_gap3_lengths[256][2]; - uint8_t xdf_ordered_pos[256][2]; - uint8_t interleave_ordered_pos[256][2]; + uint8_t track_spt[256][2]; + uint8_t gap3_len; + uint16_t current_side_flags[2]; + int track; + int current_sector_index[2]; + uint8_t calculated_gap3_lengths[256][2]; + uint8_t xdf_ordered_pos[256][2]; + uint8_t interleave_ordered_pos[256][2]; - uint8_t *imagebuf; - uint8_t *processed_buf; + uint8_t *imagebuf; + uint8_t *processed_buf; } td0_t; - /* * Tables for encoding/decoding upper 6 bits of * sliding dictionary pointer @@ -201,58 +202,51 @@ static const uint8_t d_len[256] = { 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, }; - -static td0_t *td0[FDD_NUM]; - +static td0_t *td0[FDD_NUM]; #ifdef ENABLE_TD0_LOG int td0_do_log = ENABLE_TD0_LOG; - static void td0_log(const char *fmt, ...) { - va_list ap; + va_list ap; - if (td0_do_log) - { - va_start(ap, fmt); - pclog_ex(fmt, ap); - va_end(ap); - } + if (td0_do_log) { + va_start(ap, fmt); + pclog_ex(fmt, ap); + va_end(ap); + } } #else -#define td0_log(fmt, ...) +# define td0_log(fmt, ...) #endif - static void fdd_image_read(int drive, char *buffer, uint32_t offset, uint32_t len) { td0_t *dev = td0[drive]; - if (fseek(dev->f, offset, SEEK_SET) == -1) - fatal("fdd_image_read(): Error seeking to the beginning of the file\n"); - if (fread(buffer, 1, len, dev->f) != len) - fatal("fdd_image_read(): Error reading data\n"); + if (fseek(dev->fp, offset, SEEK_SET) == -1) + fatal("fdd_image_read(): Error seeking to the beginning of the file\n"); + if (fread(buffer, 1, len, dev->fp) != len) + fatal("fdd_image_read(): Error reading data\n"); } - static int dsk_identify(int drive) { char header[2]; fdd_image_read(drive, header, 0, 2); - if (header[0]=='T' && header[1]=='D') - return(1); - else if (header[0]=='t' && header[1]=='d') - return(1); + if (header[0] == 'T' && header[1] == 'D') + return 1; + else if (header[0] == 't' && header[1] == 'd') + return 1; - return(0); + return 0; } - static int state_data_read(td0dsk_t *state, uint8_t *buf, uint16_t size) { @@ -261,36 +255,34 @@ state_data_read(td0dsk_t *state, uint8_t *buf, uint16_t size) fseek(state->fdd_file, 0, SEEK_END); image_size = ftell(state->fdd_file); if (size > image_size - state->fdd_file_offset) - size = (image_size - state->fdd_file_offset) & 0xffff; + size = (image_size - state->fdd_file_offset) & 0xffff; if (fseek(state->fdd_file, state->fdd_file_offset, SEEK_SET) == -1) - fatal("TD0: Failed to seek in state_data_read()\n"); + fatal("TD0: Failed to seek in state_data_read()\n"); if (fread(buf, 1, size, state->fdd_file) != size) - fatal("TD0: Error reading data in state_data_read()\n"); + fatal("TD0: Error reading data in state_data_read()\n"); state->fdd_file_offset += size; - return(size); + return size; } - static int state_next_word(td0dsk_t *state) { if (state->tdctl.ibufndx >= state->tdctl.ibufcnt) { - state->tdctl.ibufndx = 0; - state->tdctl.ibufcnt = state_data_read(state, state->tdctl.inbuf,BUFSZ); - if (state->tdctl.ibufcnt == 0) - return(-1); + state->tdctl.ibufndx = 0; + state->tdctl.ibufcnt = state_data_read(state, state->tdctl.inbuf, BUFSZ); + if (state->tdctl.ibufcnt == 0) + return (-1); } while (state->getlen <= 8) { /* typically reads a word at a time */ - state->getbuf |= state->tdctl.inbuf[state->tdctl.ibufndx++] << (8 - state->getlen); - state->getlen += 8; + state->getbuf |= state->tdctl.inbuf[state->tdctl.ibufndx++] << (8 - state->getlen); + state->getlen += 8; } - return(0); + return 0; } - /* get one bit */ static int state_GetBit(td0dsk_t *state) @@ -298,18 +290,17 @@ state_GetBit(td0dsk_t *state) int16_t i; if (state_next_word(state) < 0) - return(-1); + return (-1); i = state->getbuf; state->getbuf <<= 1; state->getlen--; if (i < 0) - return(1); + return 1; - return(0); + return 0; } - /* get a byte */ static int state_GetByte(td0dsk_t *state) @@ -317,126 +308,133 @@ state_GetByte(td0dsk_t *state) uint16_t i; if (state_next_word(state) != 0) - return(-1); + return -1; i = state->getbuf; state->getbuf <<= 8; state->getlen -= 8; i = i >> 8; - return((int) i); + return ((int) i); } - /* initialize freq tree */ static void state_StartHuff(td0dsk_t *state) { - int i, j; + int i; + int j; for (i = 0; i < N_CHAR; i++) { - state->freq[i] = 1; - state->son[i] = i + T; - state->prnt[i + T] = i; + state->freq[i] = 1; + state->son[i] = i + T; + state->prnt[i + T] = i; } - i = 0; j = N_CHAR; + i = 0; + j = N_CHAR; while (j <= R) { - state->freq[j] = state->freq[i] + state->freq[i + 1]; - state->son[j] = i; - state->prnt[i] = state->prnt[i + 1] = j; - i += 2; j++; + state->freq[j] = state->freq[i] + state->freq[i + 1]; + state->son[j] = i; + state->prnt[i] = state->prnt[i + 1] = j; + i += 2; + j++; } state->freq[T] = 0xffff; state->prnt[R] = 0; } - /* reconstruct freq tree */ static void state_reconst(td0dsk_t *state) { - int16_t i, j, k; - uint16_t f, l; + int16_t i; + int16_t j; + int16_t k; + uint16_t f; + uint16_t l; /* halven cumulative freq for leaf nodes */ j = 0; for (i = 0; i < T; i++) { - if (state->son[i] >= T) { - state->freq[j] = (state->freq[i] + 1) / 2; - state->son[j] = state->son[i]; - j++; - } + if (state->son[i] >= T) { + state->freq[j] = (state->freq[i] + 1) / 2; + state->son[j] = state->son[i]; + j++; + } } /* make a tree : first, connect children nodes */ for (i = 0, j = N_CHAR; j < T; i += 2, j++) { - k = i + 1; - f = state->freq[j] = state->freq[i] + state->freq[k]; - for (k = j - 1; f < state->freq[k]; k--) {}; - k++; - l = (j - k) * 2; + k = i + 1; + f = state->freq[j] = state->freq[i] + state->freq[k]; + for (k = j - 1; f < state->freq[k]; k--) { } + k++; + l = (j - k) * 2; - /* These *HAVE* to be memmove's as destination and source - can overlap, which memcpy can't handle. */ - memmove(&state->freq[k + 1], &state->freq[k], l); - state->freq[k] = f; - memmove(&state->son[k + 1], &state->son[k], l); - state->son[k] = i; + /* These *HAVE* to be memmove's as destination and source + can overlap, which memcpy can't handle. */ + memmove(&state->freq[k + 1], &state->freq[k], l); + state->freq[k] = f; + memmove(&state->son[k + 1], &state->son[k], l); + state->son[k] = i; } /* connect parent nodes */ for (i = 0; i < T; i++) { - if ((k = state->son[i]) >= T) - state->prnt[k] = i; - else - state->prnt[k] = state->prnt[k + 1] = i; + if ((k = state->son[i]) >= T) + state->prnt[k] = i; + else + state->prnt[k] = state->prnt[k + 1] = i; } } - /* update freq tree */ static void state_update(td0dsk_t *state, int c) { - int i, j, k, l; + int i; + int j; + int k; + int l; if (state->freq[R] == MAX_FREQ) - state_reconst(state); + state_reconst(state); c = state->prnt[c + T]; /* do it until reaching the root */ do { - k = ++state->freq[c]; + k = ++state->freq[c]; - /* swap nodes to keep the tree freq-ordered */ - if (k > state->freq[l = c + 1]) { - while (k > state->freq[++l]) {}; - l--; - state->freq[c] = state->freq[l]; - state->freq[l] = k; + /* swap nodes to keep the tree freq-ordered */ + if (k > state->freq[l = c + 1]) { + while (k > state->freq[++l]) { } + l--; + state->freq[c] = state->freq[l]; + state->freq[l] = k; - i = state->son[c]; - state->prnt[i] = l; - if (i < T) state->prnt[i + 1] = l; + i = state->son[c]; + state->prnt[i] = l; + if (i < T) + state->prnt[i + 1] = l; - j = state->son[l]; - state->son[l] = i; + j = state->son[l]; + state->son[l] = i; - state->prnt[j] = c; - if (j < T) state->prnt[j + 1] = c; - state->son[c] = j; + state->prnt[j] = c; + if (j < T) + state->prnt[j + 1] = c; + state->son[c] = j; - c = l; - } + c = l; + } } while ((c = state->prnt[c]) != 0); } - static int16_t state_DecodeChar(td0dsk_t *state) { - int ret; + int ret; uint16_t c; c = state->son[R]; @@ -447,236 +445,239 @@ state_DecodeChar(td0dsk_t *state) * else choose #(son[]+1) (input bit == 1) */ while (c < T) { - if ((ret = state_GetBit(state)) < 0) - return(-1); - c += (unsigned) ret; - c = state->son[c]; + if ((ret = state_GetBit(state)) < 0) + return (-1); + c += (unsigned) ret; + c = state->son[c]; } c -= T; state_update(state, c); - return(c); + return c; } - static int16_t state_DecodePosition(td0dsk_t *state) { - int16_t bit; - uint16_t i, j, c; + int16_t bit; + uint16_t i; + uint16_t j; + uint16_t c; /* decode upper 6 bits from given table */ if ((bit = state_GetByte(state)) < 0) - return(-1); + return (-1); i = (uint16_t) bit; - c = (uint16_t)d_code[i] << 6; + c = (uint16_t) d_code[i] << 6; j = d_len[i]; /* input lower 6 bits directly */ j -= 2; while (j--) { - if ((bit = state_GetBit(state)) < 0) - return(-1); - i = (i << 1) + bit; + if ((bit = state_GetBit(state)) < 0) + return (-1); + i = (i << 1) + bit; } - return(c | (i & 0x3f)); + return (c | (i & 0x3f)); } - /* DeCompression - split out initialization code to init_Decode() */ static void state_init_Decode(td0dsk_t *state) { - int i; - - state->getbuf = 0; - state->getlen = 0; - state->tdctl.ibufcnt= state->tdctl.ibufndx = 0; /* input buffer is empty */ - state->tdctl.bufcnt = 0; + state->getbuf = 0; + state->getlen = 0; + state->tdctl.ibufcnt = state->tdctl.ibufndx = 0; /* input buffer is empty */ + state->tdctl.bufcnt = 0; state_StartHuff(state); - for (i = 0; i < N - F; i++) - state->text_buf[i] = ' '; + for (uint16_t i = 0; i < N - F; i++) + state->text_buf[i] = ' '; state->tdctl.r = N - F; } - /* Decoding/Uncompressing */ static int state_Decode(td0dsk_t *state, uint8_t *buf, int len) { - int16_t c, pos; - int count; /* was an unsigned long, seems unnecessary */ + int16_t c; + int16_t pos; + int count; /* was an unsigned long, seems unnecessary */ - for (count = 0; count < len; ) { - if (state->tdctl.bufcnt == 0) { - if ((c = state_DecodeChar(state)) < 0) - return(count); /* fatal error */ - if (c < 256) { - *(buf++) = c & 0xff; - state->text_buf[state->tdctl.r++] = c & 0xff; - state->tdctl.r &= (N - 1); - count++; - } else { - if ((pos = state_DecodePosition(state)) < 0) - return(count); /* fatal error */ - state->tdctl.bufpos = (state->tdctl.r - pos - 1) & (N - 1); - state->tdctl.bufcnt = c - 255 + THRESHOLD; - state->tdctl.bufndx = 0; - } - } else { - /* still chars from last string */ - while (state->tdctl.bufndx < state->tdctl.bufcnt && count < len) { - c = state->text_buf[(state->tdctl.bufpos + state->tdctl.bufndx) & (N - 1)]; - *(buf++) = c & 0xff; - state->tdctl.bufndx++; - state->text_buf[state->tdctl.r++] = c & 0xff; - state->tdctl.r &= (N - 1); - count++; - } + for (count = 0; count < len;) { + if (state->tdctl.bufcnt == 0) { + if ((c = state_DecodeChar(state)) < 0) + return count; /* fatal error */ + if (c < 256) { + *(buf++) = c & 0xff; + state->text_buf[state->tdctl.r++] = c & 0xff; + state->tdctl.r &= (N - 1); + count++; + } else { + if ((pos = state_DecodePosition(state)) < 0) + return count; /* fatal error */ + state->tdctl.bufpos = (state->tdctl.r - pos - 1) & (N - 1); + state->tdctl.bufcnt = c - 255 + THRESHOLD; + state->tdctl.bufndx = 0; + } + } else { + /* still chars from last string */ + while (state->tdctl.bufndx < state->tdctl.bufcnt && count < len) { + c = state->text_buf[(state->tdctl.bufpos + state->tdctl.bufndx) & (N - 1)]; + *(buf++) = c & 0xff; + state->tdctl.bufndx++; + state->text_buf[state->tdctl.r++] = c & 0xff; + state->tdctl.r &= (N - 1); + count++; + } - /* reset bufcnt after copy string from text_buf[] */ - if (state->tdctl.bufndx >= state->tdctl.bufcnt) - state->tdctl.bufndx = state->tdctl.bufcnt = 0; - } + /* reset bufcnt after copy string from text_buf[] */ + if (state->tdctl.bufndx >= state->tdctl.bufcnt) + state->tdctl.bufndx = state->tdctl.bufcnt = 0; + } } - return(count); /* count == len, success */ + return count; /* count == len, success */ } - static uint32_t get_raw_tsize(int side_flags, int slower_rpm) { uint32_t size; - switch(side_flags & 0x27) { - case 0x22: - size = slower_rpm ? 5314 : 5208; - break; + switch (side_flags & 0x27) { + case 0x22: + size = slower_rpm ? 5314 : 5208; + break; - default: - case 0x02: - case 0x21: - size = slower_rpm ? 6375 : 6250; - break; + default: + case 0x02: + case 0x21: + size = slower_rpm ? 6375 : 6250; + break; - case 0x01: - size = slower_rpm ? 7650 : 7500; - break; + case 0x01: + size = slower_rpm ? 7650 : 7500; + break; - case 0x20: - size = slower_rpm ? 10629 : 10416; - break; + case 0x20: + size = slower_rpm ? 10629 : 10416; + break; - case 0x00: - size = slower_rpm ? 12750 : 12500; - break; + case 0x00: + size = slower_rpm ? 12750 : 12500; + break; - case 0x23: - size = slower_rpm ? 21258 : 20833; - break; + case 0x23: + size = slower_rpm ? 21258 : 20833; + break; - case 0x03: - size = slower_rpm ? 25500 : 25000; - break; + case 0x03: + size = slower_rpm ? 25500 : 25000; + break; - case 0x25: - size = slower_rpm ? 42517 : 41666; - break; + case 0x25: + size = slower_rpm ? 42517 : 41666; + break; - case 0x05: - size = slower_rpm ? 51000 : 50000; - break; + case 0x05: + size = slower_rpm ? 51000 : 50000; + break; } - return(size); + return size; } - static int td0_initialize(int drive) { - td0_t *dev = td0[drive]; - uint8_t header[12]; - int fm, head, track; - int track_count = 0; - int head_count = 0; - int track_spt, track_spt_adjusted; - int offset = 0; - int density = 0; - int temp_rate = 0; - uint32_t file_size; - uint16_t len, rep; - td0dsk_t disk_decode; - uint8_t *hs; - uint16_t size; - uint8_t *dbuf = dev->processed_buf; - uint32_t total_size = 0; - uint32_t id_field = 0; - uint32_t pre_sector = 0; - int32_t track_size = 0; - int32_t raw_tsize = 0; - uint32_t minimum_gap3 = 0; - uint32_t minimum_gap4 = 0; - int i, j, k; - int size_diff, gap_sum; + td0_t *dev = td0[drive]; + uint8_t header[12]; + int fm; + int head; + int track; + int track_count = 0; + int head_count = 0; + int track_spt; + int track_spt_adjusted; + int offset = 0; + int density = 0; + int temp_rate = 0; + uint32_t file_size; + uint16_t len; + uint16_t rep; + td0dsk_t disk_decode; + const uint8_t *hs; + uint16_t size; + uint8_t *dbuf = dev->processed_buf; + uint32_t total_size = 0; + uint32_t id_field = 0; + uint32_t pre_sector = 0; + int32_t track_size = 0; + int32_t raw_tsize = 0; + uint32_t minimum_gap3 = 0; + uint32_t minimum_gap4 = 0; + int i; + int j; + int k; + int size_diff; + int gap_sum; - if (dev->f == NULL) { - td0_log("TD0: Attempted to initialize without loading a file first\n"); - return(0); + if (dev->fp == NULL) { + td0_log("TD0: Attempted to initialize without loading a file first\n"); + return 0; } - fseek(dev->f, 0, SEEK_END); - file_size = ftell(dev->f); + fseek(dev->fp, 0, SEEK_END); + file_size = ftell(dev->fp); if (file_size < 12) { - td0_log("TD0: File is too small to even contain the header\n"); - return(0); + td0_log("TD0: File is too small to even contain the header\n"); + return 0; } if (file_size > TD0_MAX_BUFSZ) { - td0_log("TD0: File exceeds the maximum size\n"); - return(0); + td0_log("TD0: File exceeds the maximum size\n"); + return 0; } - fseek(dev->f, 0, SEEK_SET); - fread(header, 1, 12, dev->f); + fseek(dev->fp, 0, SEEK_SET); + (void) !fread(header, 1, 12, dev->fp); head_count = header[9]; if (header[0] == 't') { - td0_log("TD0: File is compressed\n"); - disk_decode.fdd_file = dev->f; - state_init_Decode(&disk_decode); - disk_decode.fdd_file_offset = 12; - state_Decode(&disk_decode, dev->imagebuf, TD0_MAX_BUFSZ); + td0_log("TD0: File is compressed\n"); + disk_decode.fdd_file = dev->fp; + state_init_Decode(&disk_decode); + disk_decode.fdd_file_offset = 12; + state_Decode(&disk_decode, dev->imagebuf, TD0_MAX_BUFSZ); } else { - td0_log("TD0: File is uncompressed\n"); - if (fseek(dev->f, 12, SEEK_SET) == -1) - fatal("td0_initialize(): Error seeking to offet 12\n"); - if (fread(dev->imagebuf, 1, file_size - 12, dev->f) != (file_size - 12)) - fatal("td0_initialize(): Error reading image buffer\n"); + td0_log("TD0: File is uncompressed\n"); + if (fseek(dev->fp, 12, SEEK_SET) == -1) + fatal("td0_initialize(): Error seeking to offet 12\n"); + if (fread(dev->imagebuf, 1, file_size - 12, dev->fp) != (file_size - 12)) + fatal("td0_initialize(): Error reading image buffer\n"); } if (header[7] & 0x80) - offset = 10 + dev->imagebuf[2] + (dev->imagebuf[3] << 8); + offset = 10 + dev->imagebuf[2] + (dev->imagebuf[3] << 8); track_spt = dev->imagebuf[offset]; if (track_spt == 255) { - /* Empty file? */ - td0_log("TD0: File has no tracks\n"); - return(0); + /* Empty file? */ + td0_log("TD0: File has no tracks\n"); + return 0; } density = (header[5] >> 1) & 3; if (density == 3) { - td0_log("TD0: Unknown density\n"); - return(0); + td0_log("TD0: Unknown density\n"); + return 0; } /* @@ -685,30 +686,33 @@ td0_initialize(int drive) * from the CMOS. */ switch (header[6]) { - case 0: /* 5.25" 360k in 1.2M drive: 360 rpm - CMOS Drive type: None, value probably - reused by Teledisk */ - case 2: /* 5.25" 1.2M 360 rpm */ - case 5: /* 8"/5.25"/3.5" 1.25M 360 rpm */ - dev->default_track_flags = (density == 1) ? 0x20 : 0x21; - dev->max_sector_size = (density == 1) ? 6 : 5; /* 8192 or 4096 bytes. */ - break; + case 0: /* 5.25" 360k in 1.2M drive: 360 rpm + CMOS Drive type: None, value probably + reused by Teledisk */ + case 2: /* 5.25" 1.2M: 360 rpm */ + case 5: /* 8"/5.25"/3.5" 1.25M: 360 rpm */ + dev->default_track_flags = (density == 1) ? 0x20 : 0x21; + dev->max_sector_size = (density == 1) ? 6 : 5; /* 8192 or 4096 bytes. */ + break; - case 1: /* 5.25" 360k: 300 rpm */ - case 3: /* 3.5" 720k: 300 rpm */ - dev->default_track_flags = 0x02; - dev->max_sector_size = 5; /* 4096 bytes. */ - break; + case 1: /* 5.25" 360k: 300 rpm */ + case 3: /* 3.5" 720k: 300 rpm */ + dev->default_track_flags = 0x02; + dev->max_sector_size = 5; /* 4096 bytes. */ + break; - case 4: /* 3.5" 1.44M: 300 rpm */ - dev->default_track_flags = (density == 1) ? 0x00 : 0x02; - dev->max_sector_size = (density == 1) ? 6 : 5; /* 8192 or 4096 bytes. */ - break; + case 4: /* 3.5" 1.44M: 300 rpm */ + dev->default_track_flags = (density == 1) ? 0x00 : 0x02; + dev->max_sector_size = (density == 1) ? 6 : 5; /* 8192 or 4096 bytes. */ + break; - case 6: /* 3.5" 2.88M: 300 rpm */ - dev->default_track_flags = (density == 1) ? 0x00 : ((density == 2) ? 0x03 : 0x02); - dev->max_sector_size = (density == 1) ? 6 : ((density == 2) ? 7 : 5); /* 16384, 8192, or 4096 bytes. */ - break; + case 6: /* 3.5" 2.88M: 300 rpm */ + dev->default_track_flags = (density == 1) ? 0x00 : ((density == 2) ? 0x03 : 0x02); + dev->max_sector_size = (density == 1) ? 6 : ((density == 2) ? 7 : 5); /* 16384, 8192, or 4096 bytes. */ + break; + + default: + break; } dev->disk_flags = header[5] & 0x06; @@ -716,161 +720,161 @@ td0_initialize(int drive) dev->track_width = (header[7] & 1) ^ 1; for (i = 0; i < 256; i++) { - memset(dev->side_flags[i], 0, 4); - memset(dev->track_in_file[i], 0, 2); - memset(dev->calculated_gap3_lengths[i], 0, 2); - for (j = 0; j < 2; j++) - memset(dev->sects[i][j], 0, sizeof(td0_sector_t)); + memset(dev->side_flags[i], 0, 4); + memset(dev->track_in_file[i], 0, 2); + memset(dev->calculated_gap3_lengths[i], 0, 2); + for (j = 0; j < 2; j++) + memset(dev->sects[i][j], 0, sizeof(td0_sector_t)); } while (track_spt != 255) { - track_spt_adjusted = track_spt; + track_spt_adjusted = track_spt; - track = dev->imagebuf[offset + 1]; - head = dev->imagebuf[offset + 2] & 1; - fm = (header[5] & 0x80) || (dev->imagebuf[offset + 2] & 0x80); /* ? */ - dev->side_flags[track][head] = dev->default_track_flags | (fm ? 0 : 8); - dev->track_in_file[track][head] = 1; - offset += 4; - track_size = fm ? 73 : 146; - if (density == 2) - id_field = fm ? 54 : 63; - else - id_field = fm ? 35 : 44; - pre_sector = id_field + (fm ? 7 : 16); + track = dev->imagebuf[offset + 1]; + head = dev->imagebuf[offset + 2] & 1; + fm = (header[5] & 0x80) || (dev->imagebuf[offset + 2] & 0x80); /* ? */ + dev->side_flags[track][head] = dev->default_track_flags | (fm ? 0 : 8); + dev->track_in_file[track][head] = 1; + offset += 4; + track_size = fm ? 73 : 146; + if (density == 2) + id_field = fm ? 54 : 63; + else + id_field = fm ? 35 : 44; + pre_sector = id_field + (fm ? 7 : 16); - for (i = 0; i < track_spt; i++) { - hs = &dev->imagebuf[offset]; - offset += 6; + for (i = 0; i < track_spt; i++) { + hs = &dev->imagebuf[offset]; + offset += 6; - dev->sects[track][head][i].track = hs[0]; - dev->sects[track][head][i].head = hs[1]; - dev->sects[track][head][i].sector = hs[2]; - dev->sects[track][head][i].size = hs[3]; - dev->sects[track][head][i].flags = hs[4]; - dev->sects[track][head][i].fm = !!fm; - dev->sects[track][head][i].data = dbuf; + dev->sects[track][head][i].track = hs[0]; + dev->sects[track][head][i].head = hs[1]; + dev->sects[track][head][i].sector = hs[2]; + dev->sects[track][head][i].size = hs[3]; + dev->sects[track][head][i].flags = hs[4]; + dev->sects[track][head][i].fm = !!fm; + dev->sects[track][head][i].data = dbuf; - size = 128 << hs[3]; - if ((total_size + size) >= TD0_MAX_BUFSZ) { - td0_log("TD0: Processed buffer overflow\n"); - return(0); - } + size = 128 << hs[3]; + if ((total_size + size) >= TD0_MAX_BUFSZ) { + td0_log("TD0: Processed buffer overflow\n"); + return 0; + } - if (hs[4] & 0x30) - memset(dbuf, (hs[4] & 0x10) ? 0xf6 : 0x00, size); - else { - offset += 3; - switch (hs[8]) { - default: - td0_log("TD0: Image uses an unsupported sector data encoding: %i\n", hs[8]); - return(0); + if (hs[4] & 0x30) + memset(dbuf, (hs[4] & 0x10) ? 0xf6 : 0x00, size); + else { + offset += 3; + switch (hs[8]) { + default: + td0_log("TD0: Image uses an unsupported sector data encoding: %i\n", hs[8]); + return 0; - case 0: - memcpy(dbuf, &dev->imagebuf[offset], size); - offset += size; - break; + case 0: + memcpy(dbuf, &dev->imagebuf[offset], size); + offset += size; + break; - case 1: - offset += 4; - k = (hs[9] + (hs[10] << 8)) * 2; - k = (k <= size) ? k : size; - for(j = 0; j < k; j += 2) { - dbuf[j] = hs[11]; - dbuf[j + 1] = hs[12]; - } - if (k < size) - memset(&(dbuf[k]), 0, size - k); - break; + case 1: + offset += 4; + k = (hs[9] + (hs[10] << 8)) * 2; + k = (k <= size) ? k : size; + for (j = 0; j < k; j += 2) { + dbuf[j] = hs[11]; + dbuf[j + 1] = hs[12]; + } + if (k < size) + memset(&(dbuf[k]), 0, size - k); + break; - case 2: - k = 0; - while (k < size) { - len = dev->imagebuf[offset]; - rep = dev->imagebuf[offset + 1]; - offset += 2; - if (! len) { - memcpy(&(dbuf[k]), &dev->imagebuf[offset], rep); - offset += rep; - k += rep; - } else { - len = (1 << len); - rep = len * rep; - rep = ((rep + k) <= size) ? rep : (size - k); - for(j = 0; j < rep; j += len) - memcpy(&(dbuf[j + k]), &dev->imagebuf[offset], len); - k += rep; - offset += len; - } - } - break; - } - } + case 2: + k = 0; + while (k < size) { + len = dev->imagebuf[offset]; + rep = dev->imagebuf[offset + 1]; + offset += 2; + if (!len) { + memcpy(&(dbuf[k]), &dev->imagebuf[offset], rep); + offset += rep; + k += rep; + } else { + len = (1 << len); + rep = len * rep; + rep = ((rep + k) <= size) ? rep : (size - k); + for (j = 0; j < rep; j += len) + memcpy(&(dbuf[j + k]), &dev->imagebuf[offset], len); + k += rep; + offset += len; + } + } + break; + } + } - dbuf += size; - total_size += size; + dbuf += size; + total_size += size; - if (hs[4] & 0x20) { - track_size += id_field; - track_spt_adjusted--; - } else if (hs[4] & 0x40) - track_size += (pre_sector - id_field + 3); - else { - if ((hs[4] & 0x02) || (hs[3] > (dev->max_sector_size - fm))) - track_size += (pre_sector + 3); - else - track_size += (pre_sector + size + 2); - } - } + if (hs[4] & 0x20) { + track_size += id_field; + track_spt_adjusted--; + } else if (hs[4] & 0x40) + track_size += (pre_sector - id_field + 3); + else { + if ((hs[4] & 0x02) || (hs[3] > (dev->max_sector_size - fm))) + track_size += (pre_sector + 3); + else + track_size += (pre_sector + size + 2); + } + } - if (track > track_count) - track_count = track; + if (track > track_count) + track_count = track; - if (track_spt != 255) { - dev->track_spt[track][head] = track_spt; + if (track_spt != 255) { + dev->track_spt[track][head] = track_spt; - if ((dev->track_spt[track][head] == 8) && (dev->sects[track][head][0].size == 3)) - dev->side_flags[track][head] = (dev->side_flags[track][head] & ~0x67) | 0x20; + if ((dev->track_spt[track][head] == 8) && (dev->sects[track][head][0].size == 3)) + dev->side_flags[track][head] = (dev->side_flags[track][head] & ~0x67) | 0x20; - raw_tsize = get_raw_tsize(dev->side_flags[track][head], 0); - minimum_gap3 = 12 * track_spt_adjusted; - size_diff = raw_tsize - track_size; - gap_sum = minimum_gap3 + minimum_gap4; - if (size_diff < gap_sum) { - /* If we can't fit the sectors with a reasonable minimum gap at perfect RPM, let's try 2% slower. */ - raw_tsize = get_raw_tsize(dev->side_flags[track][head], 1); - /* Set disk flags so that rotation speed is 2% slower. */ - dev->disk_flags |= (3 << 5); - size_diff = raw_tsize - track_size; - if ((size_diff < gap_sum) && !fdd_get_turbo(drive)) { - /* If we can't fit the sectors with a reasonable minimum gap even at 2% slower RPM, abort. */ - td0_log("TD0: Unable to fit the %i sectors into drive %i, track %i, side %i\n", track_spt_adjusted, drive, track, head); - return 0; - } - } - dev->calculated_gap3_lengths[track][head] = (size_diff - minimum_gap4) / track_spt_adjusted; + raw_tsize = get_raw_tsize(dev->side_flags[track][head], 0); + minimum_gap3 = 12 * track_spt_adjusted; + size_diff = raw_tsize - track_size; + gap_sum = minimum_gap3 + minimum_gap4; + if (size_diff < gap_sum) { + /* If we can't fit the sectors with a reasonable minimum gap at perfect RPM, let's try 2% slower. */ + raw_tsize = get_raw_tsize(dev->side_flags[track][head], 1); + /* Set disk flags so that rotation speed is 2% slower. */ + dev->disk_flags |= (3 << 5); + size_diff = raw_tsize - track_size; + if ((size_diff < gap_sum) && !fdd_get_turbo(drive)) { + /* If we can't fit the sectors with a reasonable minimum gap even at 2% slower RPM, abort. */ + td0_log("TD0: Unable to fit the %i sectors into drive %i, track %i, side %i\n", track_spt_adjusted, drive, track, head); + return 0; + } + } + dev->calculated_gap3_lengths[track][head] = (size_diff - minimum_gap4) / track_spt_adjusted; - track_spt = dev->imagebuf[offset]; - } + track_spt = dev->imagebuf[offset]; + } } if ((dev->disk_flags & 0x60) == 0x60) - td0_log("TD0: Disk will rotate 2% below perfect RPM\n"); + td0_log("TD0: Disk will rotate 2% below perfect RPM\n"); dev->tracks = track_count + 1; temp_rate = dev->default_track_flags & 7; if ((dev->default_track_flags & 0x27) == 0x20) - temp_rate = 4; + temp_rate = 4; dev->gap3_len = gap3_sizes[temp_rate][dev->sects[0][0][0].size][dev->track_spt[0][0]]; - if (! dev->gap3_len) - dev->gap3_len = dev->calculated_gap3_lengths[0][0]; /* If we can't determine the GAP3 length, assume the smallest one we possibly know of. */ + if (!dev->gap3_len) + dev->gap3_len = dev->calculated_gap3_lengths[0][0]; /* If we can't determine the GAP3 length, assume the smallest one we possibly know of. */ if (head_count == 2) - dev->disk_flags |= 8; /* 2 sides */ + dev->disk_flags |= 8; /* 2 sides */ if (dev->tracks <= 43) - dev->track_width &= ~1; + dev->track_width &= ~1; dev->sides = head_count; @@ -879,198 +883,199 @@ td0_initialize(int drive) td0_log("TD0: File loaded: %i tracks, %i sides, disk flags: %02X, side flags: %02X, %02X, GAP3 length: %02X\n", dev->tracks, dev->sides, dev->disk_flags, dev->current_side_flags[0], dev->current_side_flags[1], dev->gap3_len); - return(1); + return 1; } - static uint16_t disk_flags(int drive) { - td0_t *dev = td0[drive]; + const td0_t *dev = td0[drive]; - return(dev->disk_flags); + return (dev->disk_flags); } - static uint16_t side_flags(int drive) { - td0_t *dev = td0[drive]; - int side = 0; - uint16_t sflags = 0; + const td0_t *dev = td0[drive]; + int side = 0; + uint16_t sflags = 0; - side = fdd_get_head(drive); + side = fdd_get_head(drive); sflags = dev->current_side_flags[side]; - return(sflags); + return sflags; } - static void set_sector(int drive, int side, uint8_t c, uint8_t h, uint8_t r, uint8_t n) { td0_t *dev = td0[drive]; - int i = 0, cyl = c; + int cyl = c; dev->current_sector_index[side] = 0; - if (cyl != dev->track) return; - for (i = 0; i < dev->track_spt[cyl][side]; i++) { - if ((dev->sects[cyl][side][i].track == c) && - (dev->sects[cyl][side][i].head == h) && - (dev->sects[cyl][side][i].sector == r) && - (dev->sects[cyl][side][i].size == n)) { - dev->current_sector_index[side] = i; - } + if (cyl != dev->track) + return; + for (uint8_t i = 0; i < dev->track_spt[cyl][side]; i++) { + if ((dev->sects[cyl][side][i].track == c) && (dev->sects[cyl][side][i].head == h) && (dev->sects[cyl][side][i].sector == r) && (dev->sects[cyl][side][i].size == n)) { + dev->current_sector_index[side] = i; + } } } - static uint8_t poll_read_data(int drive, int side, uint16_t pos) { - td0_t *dev = td0[drive]; + const td0_t *dev = td0[drive]; - return(dev->sects[dev->track][side][dev->current_sector_index[side]].data[pos]); + return (dev->sects[dev->track][side][dev->current_sector_index[side]].data[pos]); } - static int track_is_xdf(int drive, int side, int track) { - td0_t *dev = td0[drive]; + td0_t *dev = td0[drive]; uint8_t id[4] = { 0, 0, 0, 0 }; - int i, effective_sectors, xdf_sectors; - int high_sectors, low_sectors; - int max_high_id, expected_high_count, expected_low_count; + int i; + int effective_sectors; + int xdf_sectors; + int high_sectors; + int low_sectors; + int max_high_id; + int expected_high_count; + int expected_low_count; effective_sectors = xdf_sectors = high_sectors = low_sectors = 0; memset(dev->xdf_ordered_pos[side], 0, 256); - if (! track) { - if ((dev->track_spt[track][side] == 16) || (dev->track_spt[track][side] == 19)) { - if (! side) { - max_high_id = (dev->track_spt[track][side] == 19) ? 0x8B : 0x88; - expected_high_count = (dev->track_spt[track][side] == 19) ? 0x0B : 0x08; - expected_low_count = 8; - } else { - max_high_id = (dev->track_spt[track][side] == 19) ? 0x93 : 0x90; - expected_high_count = (dev->track_spt[track][side] == 19) ? 0x13 : 0x10; - expected_low_count = 0; - } + if (!track) { + if ((dev->track_spt[track][side] == 16) || (dev->track_spt[track][side] == 19)) { + if (!side) { + max_high_id = (dev->track_spt[track][side] == 19) ? 0x8B : 0x88; + expected_high_count = (dev->track_spt[track][side] == 19) ? 0x0B : 0x08; + expected_low_count = 8; + } else { + max_high_id = (dev->track_spt[track][side] == 19) ? 0x93 : 0x90; + expected_high_count = (dev->track_spt[track][side] == 19) ? 0x13 : 0x10; + expected_low_count = 0; + } - for (i = 0; i < dev->track_spt[track][side]; i++) { - id[0] = dev->sects[track][side][i].track; - id[1] = dev->sects[track][side][i].head; - id[2] = dev->sects[track][side][i].sector; - id[3] = dev->sects[track][side][i].size; - if (!(id[0]) && (id[1] == side) && (id[3] == 2)) { - if ((id[2] >= 0x81) && (id[2] <= max_high_id)) { - high_sectors++; - dev->xdf_ordered_pos[id[2]][side] = i; - } + for (i = 0; i < dev->track_spt[track][side]; i++) { + id[0] = dev->sects[track][side][i].track; + id[1] = dev->sects[track][side][i].head; + id[2] = dev->sects[track][side][i].sector; + id[3] = dev->sects[track][side][i].size; + if (!(id[0]) && (id[1] == side) && (id[3] == 2)) { + if ((id[2] >= 0x81) && (id[2] <= max_high_id)) { + high_sectors++; + dev->xdf_ordered_pos[id[2]][side] = i; + } - if ((id[2] >= 0x01) && (id[2] <= 0x08)) { - low_sectors++; - dev->xdf_ordered_pos[id[2]][side] = i; - } - } - } + if ((id[2] >= 0x01) && (id[2] <= 0x08)) { + low_sectors++; + dev->xdf_ordered_pos[id[2]][side] = i; + } + } + } - if ((high_sectors == expected_high_count) && (low_sectors == expected_low_count)) { - dev->current_side_flags[side] = (dev->track_spt[track][side] == 19) ? 0x08 : 0x28; - return((dev->track_spt[track][side] == 19) ? 2 : 1); - } - } + if ((high_sectors == expected_high_count) && (low_sectors == expected_low_count)) { + dev->current_side_flags[side] = (dev->track_spt[track][side] == 19) ? 0x08 : 0x28; + return ((dev->track_spt[track][side] == 19) ? 2 : 1); + } + } } else { - for (i = 0; i < dev->track_spt[track][side]; i++) { - id[0] = dev->sects[track][side][i].track; - id[1] = dev->sects[track][side][i].head; - id[2] = dev->sects[track][side][i].sector; - id[3] = dev->sects[track][side][i].size; - effective_sectors++; - if ((id[0] == track) && (id[1] == side) && !(id[2]) && !(id[3])) { - effective_sectors--; - } - if ((id[0] == track) && (id[1] == side) && (id[2] == (id[3] | 0x80))) { - xdf_sectors++; - dev->xdf_ordered_pos[id[2]][side] = i; - } - } + for (i = 0; i < dev->track_spt[track][side]; i++) { + id[0] = dev->sects[track][side][i].track; + id[1] = dev->sects[track][side][i].head; + id[2] = dev->sects[track][side][i].sector; + id[3] = dev->sects[track][side][i].size; + effective_sectors++; + if ((id[0] == track) && (id[1] == side) && !(id[2]) && !(id[3])) { + effective_sectors--; + } + if ((id[0] == track) && (id[1] == side) && (id[2] == (id[3] | 0x80))) { + xdf_sectors++; + dev->xdf_ordered_pos[id[2]][side] = i; + } + } - if ((effective_sectors == 3) && (xdf_sectors == 3)) { - dev->current_side_flags[side] = 0x28; - return(1); /* 5.25" 2HD XDF */ - } + if ((effective_sectors == 3) && (xdf_sectors == 3)) { + dev->current_side_flags[side] = 0x28; + return 1; /* 5.25" 2HD XDF */ + } - if ((effective_sectors == 4) && (xdf_sectors == 4)) { - dev->current_side_flags[side] = 0x08; - return(2); /* 3.5" 2HD XDF */ - } + if ((effective_sectors == 4) && (xdf_sectors == 4)) { + dev->current_side_flags[side] = 0x08; + return 2; /* 3.5" 2HD XDF */ + } } - return(0); + return 0; } - static int track_is_interleave(int drive, int side, int track) { td0_t *dev = td0[drive]; - int i, effective_sectors; - int track_spt; + int i; + int effective_sectors; + int track_spt; effective_sectors = 0; for (i = 0; i < 256; i++) - dev->interleave_ordered_pos[i][side] = 0; + dev->interleave_ordered_pos[i][side] = 0; track_spt = dev->track_spt[track][side]; - if (track_spt != 21) return(0); + if (track_spt != 21) + return 0; for (i = 0; i < track_spt; i++) { - if ((dev->sects[track][side][i].track == track) && (dev->sects[track][side][i].head == side) && (dev->sects[track][side][i].sector >= 1) && (dev->sects[track][side][i].sector <= track_spt) && (dev->sects[track][side][i].size == 2)) { - effective_sectors++; - dev->interleave_ordered_pos[dev->sects[track][side][i].sector][side] = i; - } + if ((dev->sects[track][side][i].track == track) && (dev->sects[track][side][i].head == side) && (dev->sects[track][side][i].sector >= 1) && (dev->sects[track][side][i].sector <= track_spt) && (dev->sects[track][side][i].size == 2)) { + effective_sectors++; + dev->interleave_ordered_pos[dev->sects[track][side][i].sector][side] = i; + } } - if (effective_sectors == track_spt) return(1); + if (effective_sectors == track_spt) + return 1; - return(0); + return 0; } - static void td0_seek(int drive, int track) { - td0_t *dev = td0[drive]; - int side; + td0_t *dev = td0[drive]; uint8_t id[4] = { 0, 0, 0, 0 }; - int sector, current_pos; - int ssize = 512; - int track_rate = 0; - int track_gap2 = 22; - int track_gap3 = 12; - int xdf_type = 0; - int interleave_type = 0; - int is_trackx = 0; - int xdf_spt = 0; - int xdf_sector = 0; - int ordered_pos = 0; - int real_sector = 0; - int actual_sector = 0; - int fm, sector_adjusted; + int sector; + int current_pos; + int ssize = 512; + int track_rate = 0; + int track_gap2 = 22; + int track_gap3 = 12; + int xdf_type = 0; + int interleave_type = 0; + int is_trackx = 0; + int xdf_spt = 0; + int xdf_sector = 0; + int ordered_pos = 0; + int real_sector = 0; + int actual_sector = 0; + int fm; + int sector_adjusted; - if (dev->f == NULL) return; + if (dev->fp == NULL) + return; if (!dev->track_width && fdd_doublestep_40(drive)) - track /= 2; + track /= 2; d86f_set_cur_track(drive, track); - is_trackx = (track == 0) ? 0 : 1; + is_trackx = (track == 0) ? 0 : 1; dev->track = track; dev->current_side_flags[0] = dev->side_flags[track][0]; @@ -1083,172 +1088,169 @@ td0_seek(int drive, int track) d86f_destroy_linked_lists(drive, 1); if (track > dev->tracks) { - d86f_zero_track(drive); - return; + d86f_zero_track(drive); + return; } - for (side = 0; side < dev->sides; side++) { - track_rate = dev->current_side_flags[side] & 7; - /* Make sure 300 kbps @ 360 rpm is treated the same as 250 kbps @ 300 rpm. */ - if (!track_rate && (dev->current_side_flags[side] & 0x20)) - track_rate = 4; - if ((dev->current_side_flags[side] & 0x27) == 0x21) - track_rate = 2; - track_gap3 = gap3_sizes[track_rate][dev->sects[track][side][0].size][dev->track_spt[track][side]]; - if (! track_gap3) - track_gap3 = dev->calculated_gap3_lengths[track][side]; + for (int side = 0; side < dev->sides; side++) { + track_rate = dev->current_side_flags[side] & 7; + /* Make sure 300 kbps @ 360 rpm is treated the same as 250 kbps @ 300 rpm. */ + if (!track_rate && (dev->current_side_flags[side] & 0x20)) + track_rate = 4; + if ((dev->current_side_flags[side] & 0x27) == 0x21) + track_rate = 2; + track_gap3 = gap3_sizes[track_rate][dev->sects[track][side][0].size][dev->track_spt[track][side]]; + if (!track_gap3) + track_gap3 = dev->calculated_gap3_lengths[track][side]; - track_gap2 = ((dev->current_side_flags[side] & 7) >= 3) ? 41 : 22; + track_gap2 = ((dev->current_side_flags[side] & 7) >= 3) ? 41 : 22; - xdf_type = track_is_xdf(drive, side, track); + xdf_type = track_is_xdf(drive, side, track); - interleave_type = track_is_interleave(drive, side, track); + interleave_type = track_is_interleave(drive, side, track); - current_pos = d86f_prepare_pretrack(drive, side, 0); - sector_adjusted = 0; + current_pos = d86f_prepare_pretrack(drive, side, 0); + sector_adjusted = 0; - if (! xdf_type) { - for (sector = 0; sector < dev->track_spt[track][side]; sector++) { - if (interleave_type == 0) { - real_sector = dev->sects[track][side][sector].sector; - actual_sector = sector; - } else { - real_sector = dmf_r[sector]; - actual_sector = dev->interleave_ordered_pos[real_sector][side]; - } + if (!xdf_type) { + for (sector = 0; sector < dev->track_spt[track][side]; sector++) { + if (interleave_type == 0) { + real_sector = dev->sects[track][side][sector].sector; + actual_sector = sector; + } else { + real_sector = dmf_r[sector]; + actual_sector = dev->interleave_ordered_pos[real_sector][side]; + } - id[0] = dev->sects[track][side][actual_sector].track; - id[1] = dev->sects[track][side][actual_sector].head; - id[2] = real_sector; - id[3] = dev->sects[track][side][actual_sector].size; - pclog("track %i, side %i, %i,%i,%i,%i %i\n", track, side, id[0], id[1], id[2], id[3], dev->sects[track][side][actual_sector].flags); - fm = dev->sects[track][side][actual_sector].fm; - if (((dev->sects[track][side][actual_sector].flags & 0x42) || (id[3] > (dev->max_sector_size - fm))) && !fdd_get_turbo(drive)) - ssize = 3; - else - ssize = 128 << ((uint32_t) id[3]); - current_pos = d86f_prepare_sector(drive, side, current_pos, id, dev->sects[track][side][actual_sector].data, ssize, track_gap2, track_gap3, dev->sects[track][side][actual_sector].flags); + id[0] = dev->sects[track][side][actual_sector].track; + id[1] = dev->sects[track][side][actual_sector].head; + id[2] = real_sector; + id[3] = dev->sects[track][side][actual_sector].size; + td0_log("track %i, side %i, %i,%i,%i,%i %i\n", track, side, id[0], id[1], id[2], id[3], dev->sects[track][side][actual_sector].flags); + fm = dev->sects[track][side][actual_sector].fm; + if (((dev->sects[track][side][actual_sector].flags & 0x42) || (id[3] > (dev->max_sector_size - fm))) && !fdd_get_turbo(drive)) + ssize = 3; + else + ssize = 128 << ((uint32_t) id[3]); + current_pos = d86f_prepare_sector(drive, side, current_pos, id, dev->sects[track][side][actual_sector].data, ssize, track_gap2, track_gap3, dev->sects[track][side][actual_sector].flags); - if (sector_adjusted == 0) - d86f_initialize_last_sector_id(drive, id[0], id[1], id[2], id[3]); + if (sector_adjusted == 0) + d86f_initialize_last_sector_id(drive, id[0], id[1], id[2], id[3]); - if (!(dev->sects[track][side][actual_sector].flags & 0x40)) - sector_adjusted++; - } - } else { - xdf_type--; - xdf_spt = xdf_physical_sectors[xdf_type][is_trackx]; - for (sector = 0; sector < xdf_spt; sector++) { - xdf_sector = (side * xdf_spt) + sector; - id[0] = track; - id[1] = side; - id[2] = xdf_disk_layout[xdf_type][is_trackx][xdf_sector].id.r; - id[3] = is_trackx ? (id[2] & 7) : 2; - ordered_pos = dev->xdf_ordered_pos[id[2]][side]; - fm = dev->sects[track][side][ordered_pos].fm; - if (((dev->sects[track][side][ordered_pos].flags & 0x42) || (id[3] > (dev->max_sector_size - fm))) && !fdd_get_turbo(drive)) - ssize = 3; - else - ssize = 128 << ((uint32_t) id[3]); - if (is_trackx) - current_pos = d86f_prepare_sector(drive, side, xdf_trackx_spos[xdf_type][xdf_sector], id, dev->sects[track][side][ordered_pos].data, ssize, track_gap2, xdf_gap3_sizes[xdf_type][is_trackx], dev->sects[track][side][ordered_pos].flags); - else - current_pos = d86f_prepare_sector(drive, side, current_pos, id, dev->sects[track][side][ordered_pos].data, ssize, track_gap2, xdf_gap3_sizes[xdf_type][is_trackx], dev->sects[track][side][ordered_pos].flags); + if (!(dev->sects[track][side][actual_sector].flags & 0x40)) + sector_adjusted++; + } + } else { + xdf_type--; + xdf_spt = xdf_physical_sectors[xdf_type][is_trackx]; + for (sector = 0; sector < xdf_spt; sector++) { + xdf_sector = (side * xdf_spt) + sector; + id[0] = track; + id[1] = side; + id[2] = xdf_disk_layout[xdf_type][is_trackx][xdf_sector].id.r; + id[3] = is_trackx ? (id[2] & 7) : 2; + ordered_pos = dev->xdf_ordered_pos[id[2]][side]; + fm = dev->sects[track][side][ordered_pos].fm; + if (((dev->sects[track][side][ordered_pos].flags & 0x42) || (id[3] > (dev->max_sector_size - fm))) && !fdd_get_turbo(drive)) + ssize = 3; + else + ssize = 128 << ((uint32_t) id[3]); + if (is_trackx) + current_pos = d86f_prepare_sector(drive, side, xdf_trackx_spos[xdf_type][xdf_sector], id, dev->sects[track][side][ordered_pos].data, ssize, track_gap2, xdf_gap3_sizes[xdf_type][is_trackx], dev->sects[track][side][ordered_pos].flags); + else + current_pos = d86f_prepare_sector(drive, side, current_pos, id, dev->sects[track][side][ordered_pos].data, ssize, track_gap2, xdf_gap3_sizes[xdf_type][is_trackx], dev->sects[track][side][ordered_pos].flags); - if (sector_adjusted == 0) - d86f_initialize_last_sector_id(drive, id[0], id[1], id[2], id[3]); + if (sector_adjusted == 0) + d86f_initialize_last_sector_id(drive, id[0], id[1], id[2], id[3]); - if (!(dev->sects[track][side][ordered_pos].flags & 0x40)) - sector_adjusted++; - } - } + if (!(dev->sects[track][side][ordered_pos].flags & 0x40)) + sector_adjusted++; + } + } } } - void td0_init(void) { memset(td0, 0x00, sizeof(td0)); } - void td0_abort(int drive) { td0_t *dev = td0[drive]; if (dev->imagebuf) - free(dev->imagebuf); + free(dev->imagebuf); if (dev->processed_buf) - free(dev->processed_buf); - if (dev->f) - fclose(dev->f); + free(dev->processed_buf); + if (dev->fp) + fclose(dev->fp); memset(floppyfns[drive], 0, sizeof(floppyfns[drive])); free(dev); td0[drive] = NULL; } - void td0_load(int drive, char *fn) { - td0_t *dev; + td0_t *dev; uint32_t i; d86f_unregister(drive); writeprot[drive] = 1; - dev = (td0_t *)malloc(sizeof(td0_t)); + dev = (td0_t *) malloc(sizeof(td0_t)); memset(dev, 0x00, sizeof(td0_t)); td0[drive] = dev; - dev->f = plat_fopen(fn, "rb"); - if (dev->f == NULL) { - memset(floppyfns[drive], 0, sizeof(floppyfns[drive])); - return; + dev->fp = plat_fopen(fn, "rb"); + if (dev->fp == NULL) { + memset(floppyfns[drive], 0, sizeof(floppyfns[drive])); + return; } fwriteprot[drive] = writeprot[drive]; - if (! dsk_identify(drive)) { - td0_log("TD0: Not a valid Teledisk image\n"); - td0_abort(drive); - return; + if (!dsk_identify(drive)) { + td0_log("TD0: Not a valid Teledisk image\n"); + td0_abort(drive); + return; } else { - td0_log("TD0: Valid Teledisk image\n"); + td0_log("TD0: Valid Teledisk image\n"); } /* Allocate the processing buffers. */ - i = 1024UL * 1024UL * 4UL; - dev->imagebuf = (uint8_t *)malloc(i); + i = 1024UL * 1024UL * 4UL; + dev->imagebuf = (uint8_t *) malloc(i); memset(dev->imagebuf, 0x00, i); - dev->processed_buf = (uint8_t *)malloc(i); + dev->processed_buf = (uint8_t *) malloc(i); memset(dev->processed_buf, 0x00, i); - if (! td0_initialize(drive)) { - td0_log("TD0: Failed to initialize\n"); - td0_abort(drive); - return; + if (!td0_initialize(drive)) { + td0_log("TD0: Failed to initialize\n"); + td0_abort(drive); + return; } else { - td0_log("TD0: Initialized successfully\n"); + td0_log("TD0: Initialized successfully\n"); } /* Attach this format to the D86F engine. */ - d86f_handler[drive].disk_flags = disk_flags; - d86f_handler[drive].side_flags = side_flags; - d86f_handler[drive].writeback = null_writeback; - d86f_handler[drive].set_sector = set_sector; - d86f_handler[drive].read_data = poll_read_data; - d86f_handler[drive].write_data = null_write_data; + d86f_handler[drive].disk_flags = disk_flags; + d86f_handler[drive].side_flags = side_flags; + d86f_handler[drive].writeback = null_writeback; + d86f_handler[drive].set_sector = set_sector; + d86f_handler[drive].read_data = poll_read_data; + d86f_handler[drive].write_data = null_write_data; d86f_handler[drive].format_conditions = null_format_conditions; - d86f_handler[drive].extra_bit_cells = null_extra_bit_cells; - d86f_handler[drive].encoded_data = common_encoded_data; - d86f_handler[drive].read_revolution = common_read_revolution; - d86f_handler[drive].index_hole_pos = null_index_hole_pos; - d86f_handler[drive].get_raw_size = common_get_raw_size; - d86f_handler[drive].check_crc = 1; + d86f_handler[drive].extra_bit_cells = null_extra_bit_cells; + d86f_handler[drive].encoded_data = common_encoded_data; + d86f_handler[drive].read_revolution = common_read_revolution; + d86f_handler[drive].index_hole_pos = null_index_hole_pos; + d86f_handler[drive].get_raw_size = common_get_raw_size; + d86f_handler[drive].check_crc = 1; d86f_set_version(drive, 0x0063); drives[drive].seek = td0_seek; @@ -1256,39 +1258,38 @@ td0_load(int drive, char *fn) d86f_common_handlers(drive); } - void td0_close(int drive) { td0_t *dev = td0[drive]; - int i, j, k; - if (dev == NULL) return; + if (dev == NULL) + return; d86f_unregister(drive); if (dev->imagebuf) - free(dev->imagebuf); + free(dev->imagebuf); if (dev->processed_buf) - free(dev->processed_buf); + free(dev->processed_buf); - for (i = 0; i < 256; i++) { - for (j = 0; j < 2; j++) { - for (k = 0; k < 256; k++) - dev->sects[i][j][k].data = NULL; - } + for (uint16_t i = 0; i < 256; i++) { + for (uint8_t j = 0; j < 2; j++) { + for (uint16_t k = 0; k < 256; k++) + dev->sects[i][j][k].data = NULL; + } } - for (i = 0; i < 256; i++) { - memset(dev->side_flags[i], 0, 4); - memset(dev->track_in_file[i], 0, 2); - memset(dev->calculated_gap3_lengths[i], 0, 2); - for (j = 0; j < 2; j++) - memset(dev->sects[i][j], 0, sizeof(td0_sector_t)); + for (uint16_t i = 0; i < 256; i++) { + memset(dev->side_flags[i], 0, 4); + memset(dev->track_in_file[i], 0, 2); + memset(dev->calculated_gap3_lengths[i], 0, 2); + for (uint8_t j = 0; j < 2; j++) + memset(dev->sects[i][j], 0, sizeof(td0_sector_t)); } - if (dev->f != NULL) - fclose(dev->f); + if (dev->fp != NULL) + fclose(dev->fp); /* Release resources. */ free(dev); diff --git a/src/floppy/fdi2raw.c b/src/floppy/fdi2raw.c index ffa722d74..c6a41a52d 100644 --- a/src/floppy/fdi2raw.c +++ b/src/floppy/fdi2raw.c @@ -1,26 +1,26 @@ /* - * 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. + * 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. + * This file is part of the 86Box distribution. * - * FDI to raw bit stream converter - * FDI format created by Vincent "ApH" Joguin - * Tiny changes - function type fixes, multiple drives, - * addition of get_last_head and C++ callability by Thomas - * Harte. + * FDI to raw bit stream converter + * FDI format created by Vincent "ApH" Joguin + * Tiny changes - function type fixes, multiple drives, + * addition of get_last_head and C++ callability by Thomas + * Harte. * * * - * Authors: Toni Wilen, - * and Vincent Joguin, - * Thomas Harte, + * Authors: Toni Wilen, + * and Vincent Joguin, + * Thomas Harte, * - * Copyright 2001-2004 Toni Wilen. - * Copyright 2001-2004 Vincent Joguin. - * Copyright 2001 Thomas Harte. + * Copyright 2001-2004 Toni Wilen. + * Copyright 2001-2004 Vincent Joguin. + * Copyright 2001-2016 Thomas Harte. */ #define STATIC_INLINE #include @@ -30,555 +30,615 @@ #include #include -/* IF UAE */ -/*#include "sysconfig.h" -#include "sysdeps.h" -#include "zfile.h"*/ -/* ELSE */ #define xmalloc malloc #define HAVE_STDARG_H #include <86box/86box.h> #include +#include <86box/plat_unused.h> - +#ifdef DEBUG #undef DEBUG +#endif #define VERBOSE #undef VERBOSE - #ifdef ENABLE_FDI2RAW_LOG int fdi2raw_do_log = ENABLE_FDI2RAW_LOG; - static void fdi2raw_log(const char *fmt, ...) { - va_list ap; + va_list ap; - if (fdi2raw_do_log) - { - va_start(ap, fmt); - pclog_ex(fmt, ap); - va_end(ap); - } + if (fdi2raw_do_log) { + va_start(ap, fmt); + pclog_ex(fmt, ap); + va_end(ap); + } } #else -#define fdi2raw_log(fmt, ...) +# define fdi2raw_log(fmt, ...) #endif - #ifdef ENABLE_FDI2RAW_LOG -#ifdef DEBUG -static char *datalog(uae_u8 *src, int len) +# ifdef DEBUG +static char * +datalog(uint8_t *src, int len) { - static char buf[1000]; - static int offset; - int i = 0, offset2; + static char buf[1000]; + static int offset; + int i = 0; + int offset2; - offset2 = offset; - buf[offset++]='\''; - while(len--) { - sprintf (buf + offset, "%02.2X", src[i]); - offset += 2; - i++; - if (i > 10) break; - } - buf[offset++]='\''; - buf[offset++] = 0; - if (offset >= 900) offset = 0; - return buf + offset2; + offset2 = offset; + buf[offset++] = '\''; + while (len--) { + sprintf(buf + offset, "%02.2X", src[i]); + offset += 2; + i++; + if (i > 10) + break; + } + buf[offset++] = '\''; + buf[offset++] = 0; + if (offset >= 900) + offset = 0; + return buf + offset2; } -#else -static char *datalog(uae_u8 *src, int len) { return ""; } -#endif +# else +static char * +datalog(uint8_t *src, int len) +{ + return ""; +} +# endif static int fdi_allocated; #endif #ifdef DEBUG -static void fdi_free (void *p) +static void +fdi_free(void *priv) { - int size; - if (!p) - return; - size = ((int*)p)[-1]; - fdi_allocated -= size; - write_log ("%d freed (%d)\n", size, fdi_allocated); - free ((int*)p - 1); + int size; + if (!priv) + return; + size = ((int *) priv)[-1]; + fdi_allocated -= size; + write_log("%d freed (%d)\n", size, fdi_allocated); + free((int *) priv - 1); } -static void *fdi_malloc (int size) +static void * +fdi_malloc(int size) { - void *p = xmalloc (size + sizeof (int)); - ((int*)p)[0] = size; - fdi_allocated += size; - write_log ("%d allocated (%d)\n", size, fdi_allocated); - return (int*)p + 1; + void *priv = xmalloc(size + sizeof(int)); + ((int *) prv)[0] = size; + fdi_allocated += size; + write_log("%d allocated (%d)\n", size, fdi_allocated); + return (int *) priv + 1; } #else -#define fdi_free free -#define fdi_malloc xmalloc +# define fdi_free free +# define fdi_malloc xmalloc #endif -#define MAX_SRC_BUFFER 4194304 -#define MAX_DST_BUFFER 40000 +#define MAX_SRC_BUFFER 4194304 +#define MAX_DST_BUFFER 40000 #define MAX_MFM_SYNC_BUFFER 60000 -#define MAX_TIMING_BUFFER 400000 -#define MAX_TRACKS 166 +#define MAX_TIMING_BUFFER 400000 +#define MAX_TRACKS 166 struct fdi_cache { - uae_u32 *avgp, *minp, *maxp; - uae_u8 *idxp; - int avg_free, idx_free, min_free, max_free; - uae_u32 totalavg, pulses, maxidx, indexoffset; - int weakbits; - int lowlevel; + uint32_t *avgp, *minp, *maxp; + uint8_t *idxp; + int avg_free, idx_free, min_free, max_free; + uint32_t totalavg, pulses, maxidx, indexoffset; + int weakbits; + int lowlevel; }; struct fdi { - uae_u8 *track_src_buffer; - uae_u8 *track_src; - int track_src_len; - uae_u8 *track_dst_buffer; - uae_u8 *track_dst; - uae_u16 *track_dst_buffer_timing; - uae_u8 track_len; - uae_u8 track_type; - int current_track; - int last_track; - int last_head; - int rotation_speed; - int bit_rate; - int disk_type; - int write_protect; - int err; - uae_u8 header[2048]; - int track_offsets[MAX_TRACKS]; - FILE *file; - int out; - int mfmsync_offset; - int *mfmsync_buffer; - /* sector described only */ - int index_offset; - int encoding_type; - /* bit handling */ - int nextdrop; - struct fdi_cache cache[MAX_TRACKS]; + uint8_t *track_src_buffer; + uint8_t *track_src; + int32_t track_src_len; + uint8_t *track_dst_buffer; + uint8_t *track_dst; + uint16_t *track_dst_buffer_timing; + uint8_t track_len; + uint8_t track_type; + int current_track; + int last_track; + int last_head; + int rotation_speed; + int bit_rate; + int disk_type; + bool write_protect; + int reversed_side; + int err; + uint8_t header[2048]; + int32_t track_offsets[MAX_TRACKS]; + FILE *file; + int out; + int mfmsync_offset; + int *mfmsync_buffer; + /* sector described only */ + int index_offset; + int encoding_type; + /* bit handling */ + int nextdrop; + struct fdi_cache cache[MAX_TRACKS]; }; -#define get_u32(x) ((((x)[0])<<24)|(((x)[1])<<16)|(((x)[2])<<8)|((x)[3])) -#define get_u24(x) ((((x)[0])<<16)|(((x)[1])<<8)|((x)[2])) -STATIC_INLINE void put_u32 (uae_u8 *d, uae_u32 v) +#define get_u32(x) ((((x)[0]) << 24) | (((x)[1]) << 16) | (((x)[2]) << 8) | ((x)[3])) +#define get_u24(x) ((((x)[0]) << 16) | (((x)[1]) << 8) | ((x)[2])) +STATIC_INLINE void +put_u32(uint8_t *d, uint32_t v) { - d[0] = v >> 24; - d[1] = v >> 16; - d[2] = v >> 8; - d[3] = v; + d[0] = v >> 24; + d[1] = v >> 16; + d[2] = v >> 8; + d[3] = v; } struct node { - uae_u16 v; - struct node *left; - struct node *right; + uint16_t v; + struct node *left; + struct node *right; }; typedef struct node NODE; -static uae_u8 temp, temp2; +static uint8_t temp; +static uint8_t temp2; -static uae_u8 *expand_tree (uae_u8 *stream, NODE *node) +static uint8_t * +expand_tree(uint8_t *stream, NODE *node) { - if (temp & temp2) { - if (node->left) { - fdi_free (node->left); - node->left = 0; - } - if (node->right) { - fdi_free (node->right); - node->right = 0; - } - temp2 >>= 1; - if (!temp2) { - temp = *stream++; - temp2 = 0x80; - } - return stream; - } else { - uae_u8 *stream_temp; - temp2 >>= 1; - if (!temp2) { - temp = *stream++; - temp2 = 0x80; - } - node->left = fdi_malloc (sizeof (NODE)); - memset (node->left, 0, sizeof (NODE)); - stream_temp = expand_tree (stream, node->left); - node->right = fdi_malloc (sizeof (NODE)); - memset (node->right, 0, sizeof (NODE)); - return expand_tree (stream_temp, node->right); - } + if (temp & temp2) { + if (node->left) { + fdi_free(node->left); + node->left = 0; + } + if (node->right) { + fdi_free(node->right); + node->right = 0; + } + temp2 >>= 1; + if (!temp2) { + temp = *stream++; + temp2 = 0x80; + } + return stream; + } else { + uint8_t *stream_temp; + temp2 >>= 1; + if (!temp2) { + temp = *stream++; + temp2 = 0x80; + } + node->left = fdi_malloc(sizeof(NODE)); + memset(node->left, 0, sizeof(NODE)); + stream_temp = expand_tree(stream, node->left); + node->right = fdi_malloc(sizeof(NODE)); + memset(node->right, 0, sizeof(NODE)); + return expand_tree(stream_temp, node->right); + } } -static uae_u8 *values_tree8 (uae_u8 *stream, NODE *node) +static uint8_t * +values_tree8(uint8_t *stream, NODE *node) { - if (node->left == 0) { - node->v = *stream++; - return stream; - } else { - uae_u8 *stream_temp = values_tree8 (stream, node->left); - return values_tree8 (stream_temp, node->right); - } + if (node->left == 0) { + node->v = *stream++; + return stream; + } else { + uint8_t *stream_temp = values_tree8(stream, node->left); + return values_tree8(stream_temp, node->right); + } } -static uae_u8 *values_tree16 (uae_u8 *stream, NODE *node) +static uint8_t * +values_tree16(uint8_t *stream, NODE *node) { - if (node->left == 0) { - uae_u16 high_8_bits = (*stream++) << 8; - node->v = high_8_bits | (*stream++); - return stream; - } else { - uae_u8 *stream_temp = values_tree16 (stream, node->left); - return values_tree16 (stream_temp, node->right); - } + if (node->left == 0) { + uint16_t high_8_bits = (*stream++) << 8; + node->v = high_8_bits | (*stream++); + return stream; + } else { + uint8_t *stream_temp = values_tree16(stream, node->left); + return values_tree16(stream_temp, node->right); + } } -static void free_nodes (NODE *node) +static void +free_nodes(NODE *node) { - if (node) { - free_nodes (node->left); - free_nodes (node->right); - fdi_free (node); - } + if (node) { + free_nodes(node->left); + free_nodes(node->right); + fdi_free(node); + } } -static uae_u32 sign_extend16 (uae_u32 v) +/// @returns the 32-bit sign extended version of the 16-bit value in the low part of @c v. +static uint32_t +sign_extend16(uint32_t v) { - if (v & 0x8000) - v |= 0xffff0000; - return v; + if (v & 0x8000) + v |= 0xffff0000; + return v; } -static uae_u32 sign_extend8 (uae_u32 v) +/// @returns the 32-bit sign extended version of the 8-bit value in the low part of @c v. +static uint32_t +sign_extend8(uint32_t v) { - if (v & 0x80) - v |= 0xffffff00; - return v; + if (v & 0x80) + v |= 0xffffff00; + return v; } -static void fdi_decode (uae_u8 *stream, int size, uae_u8 *out) +static void +fdi_decode(uint8_t *stream, int size, uint8_t *out) { - int i; - uae_u8 sign_extend, sixteen_bit, sub_stream_shift; - NODE root; - NODE *current_node; + uint8_t sign_extend; + uint8_t sixteen_bit; + uint8_t sub_stream_shift; + NODE root; + NODE *current_node; - memset (out, 0, size * 4); - sub_stream_shift = 1; - while (sub_stream_shift) { + memset(out, 0, size * 4); + sub_stream_shift = 1; + while (sub_stream_shift) { - /* sub-stream header decode */ - sign_extend = *stream++; - sub_stream_shift = sign_extend & 0x7f; - sign_extend &= 0x80; - sixteen_bit = (*stream++) & 0x80; + /* sub-stream header decode */ + sign_extend = *stream++; + sub_stream_shift = sign_extend & 0x7f; + sign_extend &= 0x80; + sixteen_bit = (*stream++) & 0x80; - /* huffman tree architecture decode */ - temp = *stream++; - temp2 = 0x80; - stream = expand_tree (stream, &root); - if (temp2 == 0x80) - stream--; + /* huffman tree architecture decode */ + temp = *stream++; + temp2 = 0x80; + stream = expand_tree(stream, &root); + if (temp2 == 0x80) + stream--; - /* huffman output values decode */ - if (sixteen_bit) - stream = values_tree16 (stream, &root); - else - stream = values_tree8 (stream, &root); + /* huffman output values decode */ + if (sixteen_bit) + stream = values_tree16(stream, &root); + else + stream = values_tree8(stream, &root); - /* sub-stream data decode */ - temp2 = 0; - for (i = 0; i < size; i++) { - uae_u32 v; - uae_u8 decode = 1; - current_node = &root; - while (decode) { - if (current_node->left == 0) { - decode = 0; - } else { - temp2 >>= 1; - if (!temp2) { - temp2 = 0x80; - temp = *stream++; - } - if (temp & temp2) - current_node = current_node->right; - else - current_node = current_node->left; - } - } - v = ((uae_u32*)out)[i]; - if (sign_extend) { - if (sixteen_bit) - v |= sign_extend16 (current_node->v) << sub_stream_shift; - else - v |= sign_extend8 (current_node->v) << sub_stream_shift; - } else { - v |= current_node->v << sub_stream_shift; - } - ((uae_u32*)out)[i] = v; - } - free_nodes (root.left); - root.left = 0; - free_nodes (root.right); - root.right = 0; - } + /* sub-stream data decode */ + temp2 = 0; + for (int i = 0; i < size; i++) { + uint32_t v; + uint8_t decode = 1; + current_node = &root; + while (decode) { + if (current_node->left == 0) { + decode = 0; + } else { + temp2 >>= 1; + if (!temp2) { + temp2 = 0x80; + temp = *stream++; + } + if (temp & temp2) + current_node = current_node->right; + else + current_node = current_node->left; + } + } + v = ((uint32_t *) out)[i]; + if (sign_extend) { + if (sixteen_bit) + v |= sign_extend16(current_node->v) << sub_stream_shift; + else + v |= sign_extend8(current_node->v) << sub_stream_shift; + } else { + v |= current_node->v << sub_stream_shift; + } + ((uint32_t *) out)[i] = v; + } + free_nodes(root.left); + root.left = 0; + free_nodes(root.right); + root.right = 0; + } } - -static int decode_raw_track (FDI *fdi) +static int +decode_raw_track(FDI *fdi) { - int size = get_u32(fdi->track_src); - memcpy (fdi->track_dst, fdi->track_src, (size + 7) >> 3); - fdi->track_src += (size + 7) >> 3; - return size; + int size = get_u32(fdi->track_src); + memcpy(fdi->track_dst, fdi->track_src, (size + 7) >> 3); + fdi->track_src += (size + 7) >> 3; + return size; } /* unknown track */ -static void zxx (FDI *fdi) +static void +zxx(UNUSED(FDI *fdi)) { - fdi2raw_log("track %d: unknown track type 0x%02.2X\n", fdi->current_track, fdi->track_type); + fdi2raw_log("track %d: unknown track type 0x%02.2X\n", fdi->current_track, fdi->track_type); } /* unsupported track */ #if 0 static void zyy (FDI *fdi) { - fdi2raw_log("track %d: unsupported track type 0x%02.2X\n", fdi->current_track, fdi->track_type); + fdi2raw_log("track %d: unsupported track type 0x%02.2X\n", fdi->current_track, fdi->track_type); } #endif /* empty track */ -static void track_empty (FDI *fdi) +static void +track_empty(UNUSED(FDI *fdi)) { - return; + return; } /* unknown sector described type */ -static void dxx (FDI *fdi) +static void +dxx(FDI *fdi) { - fdi2raw_log("\ntrack %d: unknown sector described type 0x%02.2X\n", fdi->current_track, fdi->track_type); - fdi->err = 1; + fdi2raw_log("\ntrack %d: unknown sector described type 0x%02.2X\n", fdi->current_track, fdi->track_type); + fdi->err = 1; } /* add position of mfm sync bit */ -static void add_mfm_sync_bit (FDI *fdi) +static void +add_mfm_sync_bit(FDI *fdi) { - if (fdi->nextdrop) { - fdi->nextdrop = 0; - return; - } - fdi->mfmsync_buffer[fdi->mfmsync_offset++] = fdi->out; - if (fdi->out == 0) { - fdi2raw_log("illegal position for mfm sync bit, offset=%d\n",fdi->out); - fdi->err = 1; - } - if (fdi->mfmsync_offset >= MAX_MFM_SYNC_BUFFER) { - fdi->mfmsync_offset = 0; - fdi2raw_log("mfmsync buffer overflow\n"); - fdi->err = 1; - } - fdi->out++; + if (fdi->nextdrop) { + fdi->nextdrop = 0; + return; + } + fdi->mfmsync_buffer[fdi->mfmsync_offset++] = fdi->out; + if (fdi->out == 0) { + fdi2raw_log("illegal position for mfm sync bit, offset=%d\n", fdi->out); + fdi->err = 1; + } + if (fdi->mfmsync_offset >= MAX_MFM_SYNC_BUFFER) { + fdi->mfmsync_offset = 0; + fdi2raw_log("mfmsync buffer overflow\n"); + fdi->err = 1; + } + fdi->out++; } #define BIT_BYTEOFFSET ((fdi->out) >> 3) -#define BIT_BITOFFSET (7-((fdi->out)&7)) +#define BIT_BITOFFSET (7 - ((fdi->out) & 7)) /* add one bit */ -static void bit_add (FDI *fdi, int bit) +static void +bit_add(FDI *fdi, int bit) { - if (fdi->nextdrop) { - fdi->nextdrop = 0; - return; - } - fdi->track_dst[BIT_BYTEOFFSET] &= ~(1 << BIT_BITOFFSET); - if (bit) - fdi->track_dst[BIT_BYTEOFFSET] |= (1 << BIT_BITOFFSET); - fdi->out++; - if (fdi->out >= MAX_DST_BUFFER * 8) { - fdi2raw_log("destination buffer overflow\n"); - fdi->err = 1; - fdi->out = 1; - } + if (fdi->nextdrop) { + fdi->nextdrop = 0; + return; + } + fdi->track_dst[BIT_BYTEOFFSET] &= ~(1 << BIT_BITOFFSET); + if (bit) + fdi->track_dst[BIT_BYTEOFFSET] |= (1 << BIT_BITOFFSET); + fdi->out++; + if (fdi->out >= MAX_DST_BUFFER * 8) { + fdi2raw_log("destination buffer overflow\n"); + fdi->err = 1; + fdi->out = 1; + } } /* add bit and mfm sync bit */ -static void bit_mfm_add (FDI *fdi, int bit) +static void +bit_mfm_add(FDI *fdi, int bit) { - add_mfm_sync_bit (fdi); - bit_add (fdi, bit); + add_mfm_sync_bit(fdi); + bit_add(fdi, bit); } /* remove following bit */ -static void bit_drop_next (FDI *fdi) +static void +bit_drop_next(FDI *fdi) { - if (fdi->nextdrop > 0) { - fdi2raw_log("multiple bit_drop_next() called"); - } else if (fdi->nextdrop < 0) { - fdi->nextdrop = 0; - fdi2raw_log(":DNN:"); - return; - } - fdi2raw_log(":DN:"); - fdi->nextdrop = 1; + if (fdi->nextdrop > 0) { + fdi2raw_log("multiple bit_drop_next() called"); + } else if (fdi->nextdrop < 0) { + fdi->nextdrop = 0; + fdi2raw_log(":DNN:"); + return; + } + fdi2raw_log(":DN:"); + fdi->nextdrop = 1; } /* ignore next bit_drop_next() */ -static void bit_dedrop (FDI *fdi) +static void +bit_dedrop(FDI *fdi) { - if (fdi->nextdrop) { - fdi2raw_log("bit_drop_next called before bit_dedrop"); - } - fdi->nextdrop = -1; - fdi2raw_log(":BDD:"); + if (fdi->nextdrop) { + fdi2raw_log("bit_drop_next called before bit_dedrop"); + } + fdi->nextdrop = -1; + fdi2raw_log(":BDD:"); } /* add one byte */ -static void byte_add (FDI *fdi, uae_u8 v) +static void +byte_add(FDI *fdi, uint8_t v) { - int i; - for (i = 7; i >= 0; i--) - bit_add (fdi, v & (1 << i)); + for (int8_t i = 7; i >= 0; i--) + bit_add(fdi, v & (1 << i)); } /* add one word */ -static void word_add (FDI *fdi, uae_u16 v) +static void +word_add(FDI *fdi, uint16_t v) { - byte_add (fdi, (uae_u8)(v >> 8)); - byte_add (fdi, (uae_u8)v); + byte_add(fdi, (uint8_t) (v >> 8)); + byte_add(fdi, (uint8_t) v); } /* add one byte and mfm encode it */ -static void byte_mfm_add (FDI *fdi, uae_u8 v) +static void +byte_mfm_add(FDI *fdi, uint8_t v) { - int i; - for (i = 7; i >= 0; i--) - bit_mfm_add (fdi, v & (1 << i)); + for (int8_t i = 7; i >= 0; i--) + bit_mfm_add(fdi, v & (1 << i)); } /* add multiple bytes and mfm encode them */ -static void bytes_mfm_add (FDI *fdi, uae_u8 v, int len) +static void +bytes_mfm_add(FDI *fdi, uint8_t v, int len) { - int i; - for (i = 0; i < len; i++) byte_mfm_add (fdi, v); + for (int i = 0; i < len; i++) + byte_mfm_add(fdi, v); } /* add one mfm encoded word and re-mfm encode it */ -static void word_post_mfm_add (FDI *fdi, uae_u16 v) +static void +word_post_mfm_add(FDI *fdi, uint16_t v) { - int i; - for (i = 14; i >= 0; i -= 2) - bit_mfm_add (fdi, v & (1 << i)); + for (int8_t i = 14; i >= 0; i -= 2) + bit_mfm_add(fdi, v & (1 << i)); } /* bit 0 */ -static void s00(FDI *fdi) { bit_add (fdi, 0); } -/* bit 1*/ -static void s01(FDI *fdi) { bit_add (fdi, 1); } -/* 4489 */ -static void s02(FDI *fdi) { word_add (fdi, 0x4489); } -/* 5224 */ -static void s03(FDI *fdi) { word_add (fdi, 0x5224); } -/* mfm sync bit */ -static void s04(FDI *fdi) { add_mfm_sync_bit (fdi); } -/* RLE MFM-encoded data */ -static void s08(FDI *fdi) +static void +s00(FDI *fdi) { - int bytes = *fdi->track_src++; - uae_u8 byte = *fdi->track_src++; - if (bytes == 0) bytes = 256; - fdi2raw_log("s08:len=%d,data=%02.2X",bytes,byte); - while(bytes--) byte_add (fdi, byte); + bit_add(fdi, 0); +} +/* bit 1*/ +static void +s01(FDI *fdi) +{ + bit_add(fdi, 1); +} +/* 4489 */ +static void +s02(FDI *fdi) +{ + word_add(fdi, 0x4489); +} +/* 5224 */ +static void +s03(FDI *fdi) +{ + word_add(fdi, 0x5224); +} +/* mfm sync bit */ +static void +s04(FDI *fdi) +{ + add_mfm_sync_bit(fdi); +} +/* RLE MFM-encoded data */ +static void +s08(FDI *fdi) +{ + int bytes = *fdi->track_src++; + uint8_t byte = *fdi->track_src++; + if (bytes == 0) + bytes = 256; + fdi2raw_log("s08:len=%d,data=%02.2X", bytes, byte); + while (bytes--) + byte_add(fdi, byte); } /* RLE MFM-decoded data */ -static void s09(FDI *fdi) +static void +s09(FDI *fdi) { - int bytes = *fdi->track_src++; - uae_u8 byte = *fdi->track_src++; - if (bytes == 0) bytes = 256; - bit_drop_next (fdi); - fdi2raw_log("s09:len=%d,data=%02.2X",bytes,byte); - while(bytes--) byte_mfm_add (fdi, byte); + int bytes = *fdi->track_src++; + uint8_t byte = *fdi->track_src++; + if (bytes == 0) + bytes = 256; + bit_drop_next(fdi); + fdi2raw_log("s09:len=%d,data=%02.2X", bytes, byte); + while (bytes--) + byte_mfm_add(fdi, byte); } /* MFM-encoded data */ -static void s0a(FDI *fdi) +static void +s0a(FDI *fdi) { - int i, bits = (fdi->track_src[0] << 8) | fdi->track_src[1]; - uae_u8 b; - fdi->track_src += 2; - fdi2raw_log("s0a:bits=%d,data=%s", bits, datalog(fdi->track_src, (bits + 7) / 8)); - while (bits >= 8) { - byte_add (fdi, *fdi->track_src++); - bits -= 8; - } - if (bits > 0) { - i = 7; - b = *fdi->track_src++; - while (bits--) { - bit_add (fdi, b & (1 << i)); - i--; - } - } + int i; + int bits = (fdi->track_src[0] << 8) | fdi->track_src[1]; + uint8_t b; + fdi->track_src += 2; + fdi2raw_log("s0a:bits=%d,data=%s", bits, datalog(fdi->track_src, (bits + 7) / 8)); + while (bits >= 8) { + byte_add(fdi, *fdi->track_src++); + bits -= 8; + } + if (bits > 0) { + i = 7; + b = *fdi->track_src++; + while (bits--) { + bit_add(fdi, b & (1 << i)); + i--; + } + } } /* MFM-encoded data */ -static void s0b(FDI *fdi) +static void +s0b(FDI *fdi) { - int i, bits = ((fdi->track_src[0] << 8) | fdi->track_src[1]) + 65536; - uae_u8 b; - fdi->track_src += 2; - fdi2raw_log("s0b:bits=%d,data=%s", bits, datalog(fdi->track_src, (bits + 7) / 8)); - while (bits >= 8) { - byte_add (fdi, *fdi->track_src++); - bits -= 8; - } - if (bits > 0) { - i = 7; - b = *fdi->track_src++; - while (bits--) { - bit_add (fdi, b & (1 << i)); - i--; - } - } + int i; + int bits = ((fdi->track_src[0] << 8) | fdi->track_src[1]) + 65536; + uint8_t b; + fdi->track_src += 2; + fdi2raw_log("s0b:bits=%d,data=%s", bits, datalog(fdi->track_src, (bits + 7) / 8)); + while (bits >= 8) { + byte_add(fdi, *fdi->track_src++); + bits -= 8; + } + if (bits > 0) { + i = 7; + b = *fdi->track_src++; + while (bits--) { + bit_add(fdi, b & (1 << i)); + i--; + } + } } /* MFM-decoded data */ -static void s0c(FDI *fdi) +static void +s0c(FDI *fdi) { - int i, bits = (fdi->track_src[0] << 8) | fdi->track_src[1]; - uae_u8 b; - fdi->track_src += 2; - bit_drop_next (fdi); - fdi2raw_log("s0c:bits=%d,data=%s", bits, datalog(fdi->track_src, (bits + 7) / 8)); - while (bits >= 8) { - byte_mfm_add (fdi, *fdi->track_src++); - bits -= 8; - } - if (bits > 0) { - i = 7; - b = *fdi->track_src++; - while(bits--) { - bit_mfm_add (fdi, b & (1 << i)); - i--; - } - } + int i; + int bits = (fdi->track_src[0] << 8) | fdi->track_src[1]; + uint8_t b; + fdi->track_src += 2; + bit_drop_next(fdi); + fdi2raw_log("s0c:bits=%d,data=%s", bits, datalog(fdi->track_src, (bits + 7) / 8)); + while (bits >= 8) { + byte_mfm_add(fdi, *fdi->track_src++); + bits -= 8; + } + if (bits > 0) { + i = 7; + b = *fdi->track_src++; + while (bits--) { + bit_mfm_add(fdi, b & (1 << i)); + i--; + } + } } /* MFM-decoded data */ -static void s0d(FDI *fdi) +static void +s0d(FDI *fdi) { - int i, bits = ((fdi->track_src[0] << 8) | fdi->track_src[1]) + 65536; - uae_u8 b; - fdi->track_src += 2; - bit_drop_next (fdi); - fdi2raw_log("s0d:bits=%d,data=%s", bits, datalog(fdi->track_src, (bits + 7) / 8)); - while (bits >= 8) { - byte_mfm_add (fdi, *fdi->track_src++); - bits -= 8; - } - if (bits > 0) { - i = 7; - b = *fdi->track_src++; - while(bits--) { - bit_mfm_add (fdi, b & (1 << i)); - i--; - } - } + int i; + int bits = ((fdi->track_src[0] << 8) | fdi->track_src[1]) + 65536; + uint8_t b; + fdi->track_src += 2; + bit_drop_next(fdi); + fdi2raw_log("s0d:bits=%d,data=%s", bits, datalog(fdi->track_src, (bits + 7) / 8)); + while (bits >= 8) { + byte_mfm_add(fdi, *fdi->track_src++); + bits -= 8; + } + if (bits > 0) { + i = 7; + b = *fdi->track_src++; + while (bits--) { + bit_mfm_add(fdi, b & (1 << i)); + i--; + } + } } /* ***** */ @@ -586,1627 +646,1715 @@ static void s0d(FDI *fdi) /* ***** */ /* just for testing integrity of Amiga sectors */ - -/*static void rotateonebit (uae_u8 *start, uae_u8 *end, int shift) +#if 0 +static void +rotateonebit (uint8_t *start, uint8_t *end, int shift) { - if (shift == 0) - return; - while (start <= end) { - start[0] <<= shift; - start[0] |= start[1] >> (8 - shift); - start++; - } -}*/ + if (shift == 0) + return; + while (start <= end) { + start[0] <<= shift; + start[0] |= start[1] >> (8 - shift); + start++; + } +} -/*static uae_u16 getmfmword (uae_u8 *mbuf) +static uint16_t +getmfmword (uint8_t *mbuf) { - uae_u32 v; + uint32_t v; - v = (mbuf[0] << 8) | (mbuf[1] << 0); - if (check_offset == 0) - return v; - v <<= 8; - v |= mbuf[2]; - v >>= check_offset; - return v; -}*/ + v = (mbuf[0] << 8) | (mbuf[1] << 0); + if (check_offset == 0) + return (uint16_t)v; + v <<= 8; + v |= mbuf[2]; + v >>= check_offset; + return (uint16_t)v; +} #define MFMMASK 0x55555555 -/*static uae_u32 getmfmlong (uae_u8 * mbuf) +static uint32_t +getmfmlong (uint8_t * mbuf) { - return ((getmfmword (mbuf) << 16) | getmfmword (mbuf + 2)) & MFMMASK; -}*/ + return ((getmfmword (mbuf) << 16) | getmfmword (mbuf + 2)) & MFMMASK; +} +#endif #if 0 static int amiga_check_track (FDI *fdi) { - int i, j, secwritten = 0; - int fwlen = fdi->out / 8; - int length = 2 * fwlen; - int drvsec = 11; - uae_u32 odd, even, chksum, id, dlong; - uae_u8 *secdata; - uae_u8 secbuf[544]; - uae_u8 bigmfmbuf[60000]; - uae_u8 *mbuf, *mbuf2, *mend; - char sectable[22]; - uae_u8 *raw = fdi->track_dst_buffer; - int slabel, off; - int ok = 1; + int i, j, secwritten = 0; + int fwlen = fdi->out / 8; + int length = 2 * fwlen; + int drvsec = 11; + uint32_t odd, even, chksum, id, dlong; + uint8_t *secdata; + uint8_t secbuf[544]; + uint8_t bigmfmbuf[60000]; + uint8_t *mbuf, *mbuf2, *mend; + char sectable[22]; + uint8_t *raw = fdi->track_dst_buffer; + int slabel, off; + int ok = 1; - memset (bigmfmbuf, 0, sizeof (bigmfmbuf)); - mbuf = bigmfmbuf; - check_offset = 0; - for (i = 0; i < (fdi->out + 7) / 8; i++) - *mbuf++ = raw[i]; - off = fdi->out & 7; -#if 1 - if (off > 0) { - mbuf--; - *mbuf &= ~((1 << (8 - off)) - 1); - } - j = 0; - while (i < (fdi->out + 7) / 8 + 600) { - *mbuf++ |= (raw[j] >> off) | ((raw[j + 1]) << (8 - off)); - j++; - i++; - } -#endif - mbuf = bigmfmbuf; + memset (bigmfmbuf, 0, sizeof (bigmfmbuf)); + mbuf = bigmfmbuf; + check_offset = 0; + for (i = 0; i < (fdi->out + 7) / 8; i++) + *mbuf++ = raw[i]; + off = fdi->out & 7; +# if 1 + if (off > 0) { + mbuf--; + *mbuf &= ~((1 << (8 - off)) - 1); + } + j = 0; + while (i < (fdi->out + 7) / 8 + 600) { + *mbuf++ |= (raw[j] >> off) | ((raw[j + 1]) << (8 - off)); + j++; + i++; + } +# endif + mbuf = bigmfmbuf; - memset (sectable, 0, sizeof (sectable)); - mend = bigmfmbuf + length; - mend -= (4 + 16 + 8 + 512); + memset (sectable, 0, sizeof (sectable)); + mend = bigmfmbuf + length; + mend -= (4 + 16 + 8 + 512); - while (secwritten < drvsec) { - int trackoffs; + while (secwritten < drvsec) { + int trackoffs; - for (;;) { - rotateonebit (bigmfmbuf, mend, 1); - if (getmfmword (mbuf) == 0) - break; - if (secwritten == 10) { - mbuf[0] = 0x44; - mbuf[1] = 0x89; - } - if (check_offset > 7) { - check_offset = 0; - mbuf++; - if (mbuf >= mend || *mbuf == 0) - break; - } - if (getmfmword (mbuf) == 0x4489) - break; - } - if (mbuf >= mend || *mbuf == 0) - break; + for (;;) { + rotateonebit (bigmfmbuf, mend, 1); + if (getmfmword (mbuf) == 0) + break; + if (secwritten == 10) { + mbuf[0] = 0x44; + mbuf[1] = 0x89; + } + if (check_offset > 7) { + check_offset = 0; + mbuf++; + if (mbuf >= mend || *mbuf == 0) + break; + } + if (getmfmword (mbuf) == 0x4489) + break; + } + if (mbuf >= mend || *mbuf == 0) + break; - rotateonebit (bigmfmbuf, mend, check_offset); - check_offset = 0; + rotateonebit (bigmfmbuf, mend, check_offset); + check_offset = 0; - while (getmfmword (mbuf) == 0x4489) - mbuf+= 1 * 2; - mbuf2 = mbuf + 8; + while (getmfmword (mbuf) == 0x4489) + mbuf+= 1 * 2; + mbuf2 = mbuf + 8; - odd = getmfmlong (mbuf); - even = getmfmlong (mbuf + 2 * 2); - mbuf += 4 * 2; - id = (odd << 1) | even; + odd = getmfmlong (mbuf); + even = getmfmlong (mbuf + 2 * 2); + mbuf += 4 * 2; + id = (odd << 1) | even; - trackoffs = (id & 0xff00) >> 8; - if (trackoffs + 1 > drvsec) { - fdi2raw_log("illegal sector offset %d\n",trackoffs); - ok = 0; - mbuf = mbuf2; - continue; - } - if ((id >> 24) != 0xff) { - fdi2raw_log("sector %d format type %02.2X?\n", trackoffs, id >> 24); - ok = 0; - } - chksum = odd ^ even; - slabel = 0; - for (i = 0; i < 4; i++) { - odd = getmfmlong (mbuf); - even = getmfmlong (mbuf + 8 * 2); - mbuf += 2* 2; + trackoffs = (id & 0xff00) >> 8; + if (trackoffs + 1 > drvsec) { + fdi2raw_log("illegal sector offset %d\n",trackoffs); + ok = 0; + mbuf = mbuf2; + continue; + } + if ((id >> 24) != 0xff) { + fdi2raw_log("sector %d format type %02.2X?\n", trackoffs, id >> 24); + ok = 0; + } + chksum = odd ^ even; + slabel = 0; + for (i = 0; i < 4; i++) { + odd = getmfmlong (mbuf); + even = getmfmlong (mbuf + 8 * 2); + mbuf += 2* 2; - dlong = (odd << 1) | even; - if (dlong) slabel = 1; - chksum ^= odd ^ even; - } - mbuf += 8 * 2; - odd = getmfmlong (mbuf); - even = getmfmlong (mbuf + 2 * 2); - mbuf += 4 * 2; - if (((odd << 1) | even) != chksum) { - fdi2raw_log("sector %d header crc error\n", trackoffs); - ok = 0; - mbuf = mbuf2; - continue; - } - fdi2raw_log("sector %d header crc ok\n", trackoffs); - if (((id & 0x00ff0000) >> 16) != (uae_u32)fdi->current_track) { - fdi2raw_log("illegal track number %d <> %d\n",fdi->current_track,(id & 0x00ff0000) >> 16); - ok++; - mbuf = mbuf2; - continue; - } - odd = getmfmlong (mbuf); - even = getmfmlong (mbuf + 2 * 2); - mbuf += 4 * 2; - chksum = (odd << 1) | even; - secdata = secbuf + 32; - for (i = 0; i < 128; i++) { - odd = getmfmlong (mbuf); - even = getmfmlong (mbuf + 256 * 2); - mbuf += 2 * 2; - dlong = (odd << 1) | even; - *secdata++ = (uae_u8) (dlong >> 24); - *secdata++ = (uae_u8) (dlong >> 16); - *secdata++ = (uae_u8) (dlong >> 8); - *secdata++ = (uae_u8) dlong; - chksum ^= odd ^ even; - } - mbuf += 256 * 2; - if (chksum) { - fdi2raw_log("sector %d data checksum error\n",trackoffs); - ok = 0; - } else if (sectable[trackoffs]) { - fdi2raw_log("sector %d already found?\n", trackoffs); - mbuf = mbuf2; - } else { - fdi2raw_log("sector %d ok\n",trackoffs); - if (slabel) fdi2raw_log("(non-empty sector header)\n"); - sectable[trackoffs] = 1; - secwritten++; - if (trackoffs == 9) - mbuf += 0x228; - } - } - for (i = 0; i < drvsec; i++) { - if (!sectable[i]) { - fdi2raw_log("sector %d missing\n", i); - ok = 0; - } - } - return ok; + dlong = (odd << 1) | even; + if (dlong) slabel = 1; + chksum ^= odd ^ even; + } + mbuf += 8 * 2; + odd = getmfmlong (mbuf); + even = getmfmlong (mbuf + 2 * 2); + mbuf += 4 * 2; + if (((odd << 1) | even) != chksum) { + fdi2raw_log("sector %d header crc error\n", trackoffs); + ok = 0; + mbuf = mbuf2; + continue; + } + fdi2raw_log("sector %d header crc ok\n", trackoffs); + if (((id & 0x00ff0000) >> 16) != (uint32_t)fdi->current_track) { + fdi2raw_log("illegal track number %d <> %d\n",fdi->current_track,(id & 0x00ff0000) >> 16); + ok++; + mbuf = mbuf2; + continue; + } + odd = getmfmlong (mbuf); + even = getmfmlong (mbuf + 2 * 2); + mbuf += 4 * 2; + chksum = (odd << 1) | even; + secdata = secbuf + 32; + for (i = 0; i < 128; i++) { + odd = getmfmlong (mbuf); + even = getmfmlong (mbuf + 256 * 2); + mbuf += 2 * 2; + dlong = (odd << 1) | even; + *secdata++ = (uint8_t) (dlong >> 24); + *secdata++ = (uint8_t) (dlong >> 16); + *secdata++ = (uint8_t) (dlong >> 8); + *secdata++ = (uint8_t) dlong; + chksum ^= odd ^ even; + } + mbuf += 256 * 2; + if (chksum) { + fdi2raw_log("sector %d data checksum error\n",trackoffs); + ok = 0; + } else if (sectable[trackoffs]) { + fdi2raw_log("sector %d already found?\n", trackoffs); + mbuf = mbuf2; + } else { + fdi2raw_log("sector %d ok\n",trackoffs); + if (slabel) fdi2raw_log("(non-empty sector header)\n"); + sectable[trackoffs] = 1; + secwritten++; + if (trackoffs == 9) + mbuf += 0x228; + } + } + for (i = 0; i < drvsec; i++) { + if (!sectable[i]) { + fdi2raw_log("sector %d missing\n", i); + ok = 0; + } + } + return ok; } #endif -static void amiga_data_raw (FDI *fdi, uae_u8 *secbuf, uae_u8 *crc, int len) +static void +amiga_data_raw(FDI *fdi, uint8_t *secbuf, uint8_t *crc, int len) { - int i; - uae_u8 crcbuf[4]; + int i; + uint8_t crcbuf[4]; - if (!crc) { - memset (crcbuf, 0, 4); - } else { - memcpy (crcbuf, crc ,4); - } - for (i = 0; i < 4; i++) - byte_mfm_add (fdi, crcbuf[i]); - for (i = 0; i < len; i++) - byte_mfm_add (fdi, secbuf[i]); + if (!crc) { + memset(crcbuf, 0, 4); + } else { + memcpy(crcbuf, crc, 4); + } + for (i = 0; i < 4; i++) + byte_mfm_add(fdi, crcbuf[i]); + for (i = 0; i < len; i++) + byte_mfm_add(fdi, secbuf[i]); } -static void amiga_data (FDI *fdi, uae_u8 *secbuf) +static void +amiga_data(FDI *fdi, uint8_t *secbuf) { - uae_u16 mfmbuf[4 + 512]; - uae_u32 dodd, deven, dck; - int i; + uint16_t mfmbuf[4 + 512]; + uint32_t dodd; + uint32_t deven; + uint32_t dck; - for (i = 0; i < 512; i += 4) { - deven = ((secbuf[i + 0] << 24) | (secbuf[i + 1] << 16) - | (secbuf[i + 2] << 8) | (secbuf[i + 3])); - dodd = deven >> 1; - deven &= 0x55555555; - dodd &= 0x55555555; - mfmbuf[(i >> 1) + 4] = (uae_u16) (dodd >> 16); - mfmbuf[(i >> 1) + 5] = (uae_u16) dodd; - mfmbuf[(i >> 1) + 256 + 4] = (uae_u16) (deven >> 16); - mfmbuf[(i >> 1) + 256 + 5] = (uae_u16) deven; - } - dck = 0; - for (i = 4; i < 4 + 512; i += 2) - dck ^= (mfmbuf[i] << 16) | mfmbuf[i + 1]; - deven = dodd = dck; - dodd >>= 1; - deven &= 0x55555555; - dodd &= 0x55555555; - mfmbuf[0] = (uae_u16) (dodd >> 16); - mfmbuf[1] = (uae_u16) dodd; - mfmbuf[2] = (uae_u16) (deven >> 16); - mfmbuf[3] = (uae_u16) deven; + for (uint16_t i = 0; i < 512; i += 4) { + deven = ((secbuf[i + 0] << 24) | (secbuf[i + 1] << 16) + | (secbuf[i + 2] << 8) | (secbuf[i + 3])); + dodd = deven >> 1; + deven &= 0x55555555; + dodd &= 0x55555555; + mfmbuf[(i >> 1) + 4] = (uint16_t) (dodd >> 16); + mfmbuf[(i >> 1) + 5] = (uint16_t) dodd; + mfmbuf[(i >> 1) + 256 + 4] = (uint16_t) (deven >> 16); + mfmbuf[(i >> 1) + 256 + 5] = (uint16_t) deven; + } + dck = 0; + for (uint32_t i = 4; i < 4 + 512; i += 2) + dck ^= (mfmbuf[i] << 16) | mfmbuf[i + 1]; + deven = dodd = dck; + dodd >>= 1; + deven &= 0x55555555; + dodd &= 0x55555555; + mfmbuf[0] = (uint16_t) (dodd >> 16); + mfmbuf[1] = (uint16_t) dodd; + mfmbuf[2] = (uint16_t) (deven >> 16); + mfmbuf[3] = (uint16_t) deven; - for (i = 0; i < 4 + 512; i ++) - word_post_mfm_add (fdi, mfmbuf[i]); + for (uint32_t i = 0; i < 4 + 512; i++) + word_post_mfm_add(fdi, mfmbuf[i]); } -static void amiga_sector_header (FDI *fdi, uae_u8 *header, uae_u8 *data, int sector, int untilgap) +static void +amiga_sector_header(FDI *fdi, uint8_t *header, uint8_t *data, int sector, int untilgap) { - uae_u8 headerbuf[4], databuf[16]; - uae_u32 deven, dodd, hck; - uae_u16 mfmbuf[24]; - int i; + uint8_t headerbuf[4]; + uint8_t databuf[16]; + uint32_t deven; + uint32_t dodd; + uint32_t hck; + uint16_t mfmbuf[24]; - byte_mfm_add (fdi, 0); - byte_mfm_add (fdi, 0); - word_add (fdi, 0x4489); - word_add (fdi, 0x4489); - if (header) { - memcpy (headerbuf, header, 4); - } else { - headerbuf[0] = 0xff; - headerbuf[1] = (uae_u8)fdi->current_track; - headerbuf[2] = (uae_u8)sector; - headerbuf[3] = (uae_u8)untilgap; - } - if (data) - memcpy (databuf, data, 16); - else - memset (databuf, 0, 16); + byte_mfm_add(fdi, 0); + byte_mfm_add(fdi, 0); + word_add(fdi, 0x4489); + word_add(fdi, 0x4489); + if (header) { + memcpy(headerbuf, header, 4); + } else { + headerbuf[0] = 0xff; + headerbuf[1] = (uint8_t) fdi->current_track; + headerbuf[2] = (uint8_t) sector; + headerbuf[3] = (uint8_t) untilgap; + } + if (data) + memcpy(databuf, data, 16); + else + memset(databuf, 0, 16); - deven = ((headerbuf[0] << 24) | (headerbuf[1] << 16) - | (headerbuf[2] << 8) | (headerbuf[3])); - dodd = deven >> 1; - deven &= 0x55555555; - dodd &= 0x55555555; - mfmbuf[0] = (uae_u16) (dodd >> 16); - mfmbuf[1] = (uae_u16) dodd; - mfmbuf[2] = (uae_u16) (deven >> 16); - mfmbuf[3] = (uae_u16) deven; - for (i = 0; i < 16; i += 4) { - deven = ((databuf[i] << 24) | (databuf[i + 1] << 16) - | (databuf[i + 2] << 8) | (databuf[i + 3])); - dodd = deven >> 1; - deven &= 0x55555555; - dodd &= 0x55555555; - mfmbuf[(i >> 1) + 0 + 4] = (uae_u16) (dodd >> 16); - mfmbuf[(i >> 1) + 0 + 5] = (uae_u16) dodd; - mfmbuf[(i >> 1) + 8 + 4] = (uae_u16) (deven >> 16); - mfmbuf[(i >> 1) + 8 + 5] = (uae_u16) deven; - } - hck = 0; - for (i = 0; i < 4 + 16; i += 2) - hck ^= (mfmbuf[i] << 16) | mfmbuf[i + 1]; - deven = dodd = hck; - dodd >>= 1; - deven &= 0x55555555; - dodd &= 0x55555555; - mfmbuf[20] = (uae_u16) (dodd >> 16); - mfmbuf[21] = (uae_u16) dodd; - mfmbuf[22] = (uae_u16) (deven >> 16); - mfmbuf[23] = (uae_u16) deven; + deven = ((headerbuf[0] << 24) | (headerbuf[1] << 16) + | (headerbuf[2] << 8) | (headerbuf[3])); + dodd = deven >> 1; + deven &= 0x55555555; + dodd &= 0x55555555; + mfmbuf[0] = (uint16_t) (dodd >> 16); + mfmbuf[1] = (uint16_t) dodd; + mfmbuf[2] = (uint16_t) (deven >> 16); + mfmbuf[3] = (uint16_t) deven; + for (uint8_t i = 0; i < 16; i += 4) { + deven = ((databuf[i] << 24) | (databuf[i + 1] << 16) + | (databuf[i + 2] << 8) | (databuf[i + 3])); + dodd = deven >> 1; + deven &= 0x55555555; + dodd &= 0x55555555; + mfmbuf[(i >> 1) + 0 + 4] = (uint16_t) (dodd >> 16); + mfmbuf[(i >> 1) + 0 + 5] = (uint16_t) dodd; + mfmbuf[(i >> 1) + 8 + 4] = (uint16_t) (deven >> 16); + mfmbuf[(i >> 1) + 8 + 5] = (uint16_t) deven; + } + hck = 0; + for (uint32_t i = 0; i < 4 + 16; i += 2) + hck ^= (mfmbuf[i] << 16) | mfmbuf[i + 1]; + deven = dodd = hck; + dodd >>= 1; + deven &= 0x55555555; + dodd &= 0x55555555; + mfmbuf[20] = (uint16_t) (dodd >> 16); + mfmbuf[21] = (uint16_t) dodd; + mfmbuf[22] = (uint16_t) (deven >> 16); + mfmbuf[23] = (uint16_t) deven; - for (i = 0; i < 4 + 16 + 4; i ++) - word_post_mfm_add (fdi, mfmbuf[i]); + for (uint32_t i = 0; i < 4 + 16 + 4; i++) + word_post_mfm_add(fdi, mfmbuf[i]); } /* standard super-extended Amiga sector header */ -static void s20(FDI *fdi) +static void +s20(FDI *fdi) { - bit_drop_next (fdi); - fdi2raw_log("s20:header=%s,data=%s", datalog(fdi->track_src, 4), datalog(fdi->track_src + 4, 16)); - amiga_sector_header (fdi, fdi->track_src, fdi->track_src + 4, 0, 0); - fdi->track_src += 4 + 16; + bit_drop_next(fdi); + fdi2raw_log("s20:header=%s,data=%s", datalog(fdi->track_src, 4), datalog(fdi->track_src + 4, 16)); + amiga_sector_header(fdi, fdi->track_src, fdi->track_src + 4, 0, 0); + fdi->track_src += 4 + 16; } /* standard extended Amiga sector header */ -static void s21(FDI *fdi) +static void +s21(FDI *fdi) { - bit_drop_next (fdi); - fdi2raw_log("s21:header=%s", datalog(fdi->track_src, 4)); - amiga_sector_header (fdi, fdi->track_src, 0, 0, 0); - fdi->track_src += 4; + bit_drop_next(fdi); + fdi2raw_log("s21:header=%s", datalog(fdi->track_src, 4)); + amiga_sector_header(fdi, fdi->track_src, 0, 0, 0); + fdi->track_src += 4; } /* standard Amiga sector header */ -static void s22(FDI *fdi) +static void +s22(FDI *fdi) { - bit_drop_next (fdi); - fdi2raw_log("s22:sector=%d,untilgap=%d", fdi->track_src[0], fdi->track_src[1]); - amiga_sector_header (fdi, 0, 0, fdi->track_src[0], fdi->track_src[1]); - fdi->track_src += 2; + bit_drop_next(fdi); + fdi2raw_log("s22:sector=%d,untilgap=%d", fdi->track_src[0], fdi->track_src[1]); + amiga_sector_header(fdi, 0, 0, fdi->track_src[0], fdi->track_src[1]); + fdi->track_src += 2; } /* standard 512-byte, CRC-correct Amiga data */ -static void s23(FDI *fdi) +static void +s23(FDI *fdi) { - fdi2raw_log("s23:data=%s", datalog (fdi->track_src, 512)); - amiga_data (fdi, fdi->track_src); - fdi->track_src += 512; + fdi2raw_log("s23:data=%s", datalog(fdi->track_src, 512)); + amiga_data(fdi, fdi->track_src); + fdi->track_src += 512; } /* not-decoded, 128*2^x-byte, CRC-correct Amiga data */ -static void s24(FDI *fdi) +static void +s24(FDI *fdi) { - int shift = *fdi->track_src++; - fdi2raw_log("s24:shift=%d,data=%s", shift, datalog (fdi->track_src, 128 << shift)); - amiga_data_raw (fdi, fdi->track_src, 0, 128 << shift); - fdi->track_src += 128 << shift; + int shift = *fdi->track_src++; + fdi2raw_log("s24:shift=%d,data=%s", shift, datalog(fdi->track_src, 128 << shift)); + amiga_data_raw(fdi, fdi->track_src, 0, 128 << shift); + fdi->track_src += 128 << shift; } /* not-decoded, 128*2^x-byte, CRC-incorrect Amiga data */ -static void s25(FDI *fdi) +static void +s25(FDI *fdi) { - int shift = *fdi->track_src++; - fdi2raw_log("s25:shift=%d,crc=%s,data=%s", shift, datalog (fdi->track_src, 4), datalog (fdi->track_src + 4, 128 << shift)); - amiga_data_raw (fdi, fdi->track_src + 4, fdi->track_src, 128 << shift); - fdi->track_src += 4 + (128 << shift); + int shift = *fdi->track_src++; + fdi2raw_log("s25:shift=%d,crc=%s,data=%s", shift, datalog(fdi->track_src, 4), datalog(fdi->track_src + 4, 128 << shift)); + amiga_data_raw(fdi, fdi->track_src + 4, fdi->track_src, 128 << shift); + fdi->track_src += 4 + (128 << shift); } /* standard extended Amiga sector */ -static void s26(FDI *fdi) +static void +s26(FDI *fdi) { - s21 (fdi); - fdi2raw_log("s26:data=%s", datalog (fdi->track_src, 512)); - amiga_data (fdi, fdi->track_src); - fdi->track_src += 512; + s21(fdi); + fdi2raw_log("s26:data=%s", datalog(fdi->track_src, 512)); + amiga_data(fdi, fdi->track_src); + fdi->track_src += 512; } /* standard short Amiga sector */ -static void s27(FDI *fdi) +static void +s27(FDI *fdi) { - s22 (fdi); - fdi2raw_log("s27:data=%s", datalog (fdi->track_src, 512)); - amiga_data (fdi, fdi->track_src); - fdi->track_src += 512; + s22(fdi); + fdi2raw_log("s27:data=%s", datalog(fdi->track_src, 512)); + amiga_data(fdi, fdi->track_src); + fdi->track_src += 512; } /* *** */ /* IBM */ /* *** */ -static uae_u16 ibm_crc (uae_u8 byte, int reset) +static uint16_t +ibm_crc(uint8_t byte, int reset) { - static uae_u16 crc; - int i; + static uint16_t crc; - if (reset) crc = 0xcdb4; - for (i = 0; i < 8; i++) { - if (crc & 0x8000) { - crc <<= 1; - if (!(byte & 0x80)) crc ^= 0x1021; - } else { - crc <<= 1; - if (byte & 0x80) crc ^= 0x1021; - } - byte <<= 1; - } - return crc; + if (reset) + crc = 0xcdb4; + for (uint8_t i = 0; i < 8; i++) { + if (crc & 0x8000) { + crc <<= 1; + if (!(byte & 0x80)) + crc ^= 0x1021; + } else { + crc <<= 1; + if (byte & 0x80) + crc ^= 0x1021; + } + byte <<= 1; + } + return crc; } -static void ibm_data (FDI *fdi, uae_u8 *data, uae_u8 *crc, int len) +static void +ibm_data(FDI *fdi, uint8_t *data, uint8_t *crc, int len) { - int i; - uae_u8 crcbuf[2]; - uae_u16 crcv = 0; + uint8_t crcbuf[2]; + uint16_t crcv = 0; - word_add (fdi, 0x4489); - word_add (fdi, 0x4489); - word_add (fdi, 0x4489); - byte_mfm_add (fdi, 0xfb); - ibm_crc (0xfb, 1); - for (i = 0; i < len; i++) { - byte_mfm_add (fdi, data[i]); - crcv = ibm_crc (data[i], 0); - } - if (!crc) { - crc = crcbuf; - crc[0] = (uae_u8)(crcv >> 8); - crc[1] = (uae_u8)crcv; - } - byte_mfm_add (fdi, crc[0]); - byte_mfm_add (fdi, crc[1]); + word_add(fdi, 0x4489); + word_add(fdi, 0x4489); + word_add(fdi, 0x4489); + byte_mfm_add(fdi, 0xfb); + ibm_crc(0xfb, 1); + for (int i = 0; i < len; i++) { + byte_mfm_add(fdi, data[i]); + crcv = ibm_crc(data[i], 0); + } + if (!crc) { + crc = crcbuf; + crc[0] = (uint8_t) (crcv >> 8); + crc[1] = (uint8_t) crcv; + } + byte_mfm_add(fdi, crc[0]); + byte_mfm_add(fdi, crc[1]); } -static void ibm_sector_header (FDI *fdi, uae_u8 *data, uae_u8 *crc, int secnum, int pre) +static void +ibm_sector_header(FDI *fdi, uint8_t *data, uint8_t *crc, int secnum, int pre) { - uae_u8 secbuf[5]; - uae_u8 crcbuf[2]; - uae_u16 crcv; - int i; + uint8_t secbuf[5]; + uint8_t crcbuf[2]; + uint16_t crcv; - if (pre) - bytes_mfm_add (fdi, 0, 12); - word_add (fdi, 0x4489); - word_add (fdi, 0x4489); - word_add (fdi, 0x4489); - secbuf[0] = 0xfe; - if (secnum >= 0) { - secbuf[1] = (uae_u8)(fdi->current_track/2); - secbuf[2] = (uae_u8)(fdi->current_track%2); - secbuf[3] = (uae_u8)secnum; - secbuf[4] = 2; - } else { - memcpy (secbuf + 1, data, 4); - } - ibm_crc (secbuf[0], 1); - ibm_crc (secbuf[1], 0); - ibm_crc (secbuf[2], 0); - ibm_crc (secbuf[3], 0); - crcv = ibm_crc (secbuf[4], 0); - if (crc) { - memcpy (crcbuf, crc, 2); - } else { - crcbuf[0] = (uae_u8)(crcv >> 8); - crcbuf[1] = (uae_u8)crcv; - } - /* data */ - for (i = 0;i < 5; i++) - byte_mfm_add (fdi, secbuf[i]); - /* crc */ - byte_mfm_add (fdi, crcbuf[0]); - byte_mfm_add (fdi, crcbuf[1]); + if (pre) + bytes_mfm_add(fdi, 0, 12); + word_add(fdi, 0x4489); + word_add(fdi, 0x4489); + word_add(fdi, 0x4489); + secbuf[0] = 0xfe; + if (secnum >= 0) { + secbuf[1] = (uint8_t) (fdi->current_track / 2); + secbuf[2] = (uint8_t) (fdi->current_track % 2); + secbuf[3] = (uint8_t) secnum; + secbuf[4] = 2; + } else { + memcpy(secbuf + 1, data, 4); + } + ibm_crc(secbuf[0], 1); + ibm_crc(secbuf[1], 0); + ibm_crc(secbuf[2], 0); + ibm_crc(secbuf[3], 0); + crcv = ibm_crc(secbuf[4], 0); + if (crc) { + memcpy(crcbuf, crc, 2); + } else { + crcbuf[0] = (uint8_t) (crcv >> 8); + crcbuf[1] = (uint8_t) crcv; + } + /* data */ + for (uint8_t i = 0; i < 5; i++) + byte_mfm_add(fdi, secbuf[i]); + /* crc */ + byte_mfm_add(fdi, crcbuf[0]); + byte_mfm_add(fdi, crcbuf[1]); } /* standard IBM index address mark */ -static void s10(FDI *fdi) +static void +s10(FDI *fdi) { - bit_drop_next (fdi); - bytes_mfm_add (fdi, 0, 12); - word_add (fdi, 0x5224); - word_add (fdi, 0x5224); - word_add (fdi, 0x5224); - byte_mfm_add (fdi, 0xfc); + bit_drop_next(fdi); + bytes_mfm_add(fdi, 0, 12); + word_add(fdi, 0x5224); + word_add(fdi, 0x5224); + word_add(fdi, 0x5224); + byte_mfm_add(fdi, 0xfc); } /* standard IBM pre-gap */ -static void s11(FDI *fdi) +static void +s11(FDI *fdi) { - bit_drop_next (fdi); - bytes_mfm_add (fdi, 0x4e, 78); - bit_dedrop (fdi); - s10 (fdi); - bytes_mfm_add (fdi, 0x4e, 50); + bit_drop_next(fdi); + bytes_mfm_add(fdi, 0x4e, 78); + bit_dedrop(fdi); + s10(fdi); + bytes_mfm_add(fdi, 0x4e, 50); } /* standard ST pre-gap */ -static void s12(FDI *fdi) +static void +s12(FDI *fdi) { - bit_drop_next (fdi); - bytes_mfm_add (fdi, 0x4e, 78); + bit_drop_next(fdi); + bytes_mfm_add(fdi, 0x4e, 78); } /* standard extended IBM sector header */ -static void s13(FDI *fdi) +static void +s13(FDI *fdi) { - bit_drop_next (fdi); - fdi2raw_log("s13:header=%s", datalog (fdi->track_src, 4)); - ibm_sector_header (fdi, fdi->track_src, 0, -1, 1); - fdi->track_src += 4; + bit_drop_next(fdi); + fdi2raw_log("s13:header=%s", datalog(fdi->track_src, 4)); + ibm_sector_header(fdi, fdi->track_src, 0, -1, 1); + fdi->track_src += 4; } /* standard mini-extended IBM sector header */ -static void s14(FDI *fdi) +static void +s14(FDI *fdi) { - fdi2raw_log("s14:header=%s", datalog (fdi->track_src, 4)); - ibm_sector_header (fdi, fdi->track_src, 0, -1, 0); - fdi->track_src += 4; + fdi2raw_log("s14:header=%s", datalog(fdi->track_src, 4)); + ibm_sector_header(fdi, fdi->track_src, 0, -1, 0); + fdi->track_src += 4; } /* standard short IBM sector header */ -static void s15(FDI *fdi) +static void +s15(FDI *fdi) { - bit_drop_next (fdi); - fdi2raw_log("s15:sector=%d", *fdi->track_src); - ibm_sector_header (fdi, 0, 0, *fdi->track_src++, 1); + bit_drop_next(fdi); + fdi2raw_log("s15:sector=%d", *fdi->track_src); + ibm_sector_header(fdi, 0, 0, *fdi->track_src++, 1); } /* standard mini-short IBM sector header */ -static void s16(FDI *fdi) +static void +s16(FDI *fdi) { - fdi2raw_log("s16:track=%d", *fdi->track_src); - ibm_sector_header (fdi, 0, 0, *fdi->track_src++, 0); + fdi2raw_log("s16:track=%d", *fdi->track_src); + ibm_sector_header(fdi, 0, 0, *fdi->track_src++, 0); } /* standard CRC-incorrect mini-extended IBM sector header */ -static void s17(FDI *fdi) +static void +s17(FDI *fdi) { - fdi2raw_log("s17:header=%s,crc=%s", datalog (fdi->track_src, 4), datalog (fdi->track_src + 4, 2)); - ibm_sector_header (fdi, fdi->track_src, fdi->track_src + 4, -1, 0); - fdi->track_src += 4 + 2; + fdi2raw_log("s17:header=%s,crc=%s", datalog(fdi->track_src, 4), datalog(fdi->track_src + 4, 2)); + ibm_sector_header(fdi, fdi->track_src, fdi->track_src + 4, -1, 0); + fdi->track_src += 4 + 2; } /* standard CRC-incorrect mini-short IBM sector header */ -static void s18(FDI *fdi) +static void +s18(FDI *fdi) { - fdi2raw_log("s18:sector=%d,header=%s", *fdi->track_src, datalog (fdi->track_src + 1, 4)); - ibm_sector_header (fdi, 0, fdi->track_src + 1, *fdi->track_src, 0); - fdi->track_src += 1 + 4; + fdi2raw_log("s18:sector=%d,header=%s", *fdi->track_src, datalog(fdi->track_src + 1, 4)); + ibm_sector_header(fdi, 0, fdi->track_src + 1, *fdi->track_src, 0); + fdi->track_src += 1 + 4; } /* standard 512-byte CRC-correct IBM data */ -static void s19(FDI *fdi) +static void +s19(FDI *fdi) { - fdi2raw_log("s19:data=%s", datalog (fdi->track_src , 512)); - ibm_data (fdi, fdi->track_src, 0, 512); - fdi->track_src += 512; + fdi2raw_log("s19:data=%s", datalog(fdi->track_src, 512)); + ibm_data(fdi, fdi->track_src, 0, 512); + fdi->track_src += 512; } /* standard 128*2^x-byte-byte CRC-correct IBM data */ -static void s1a(FDI *fdi) +static void +s1a(FDI *fdi) { - int shift = *fdi->track_src++; - fdi2raw_log("s1a:shift=%d,data=%s", shift, datalog (fdi->track_src , 128 << shift)); - ibm_data (fdi, fdi->track_src, 0, 128 << shift); - fdi->track_src += 128 << shift; + int shift = *fdi->track_src++; + fdi2raw_log("s1a:shift=%d,data=%s", shift, datalog(fdi->track_src, 128 << shift)); + ibm_data(fdi, fdi->track_src, 0, 128 << shift); + fdi->track_src += 128 << shift; } /* standard 128*2^x-byte-byte CRC-incorrect IBM data */ -static void s1b(FDI *fdi) +static void +s1b(FDI *fdi) { - int shift = *fdi->track_src++; - fdi2raw_log("s1b:shift=%d,crc=%s,data=%s", shift, datalog (fdi->track_src + (128 << shift), 2), datalog (fdi->track_src , 128 << shift)); - ibm_data (fdi, fdi->track_src, fdi->track_src + (128 << shift), 128 << shift); - fdi->track_src += (128 << shift) + 2; + int shift = *fdi->track_src++; + fdi2raw_log("s1b:shift=%d,crc=%s,data=%s", shift, datalog(fdi->track_src + (128 << shift), 2), datalog(fdi->track_src, 128 << shift)); + ibm_data(fdi, fdi->track_src, fdi->track_src + (128 << shift), 128 << shift); + fdi->track_src += (128 << shift) + 2; } /* standard extended IBM sector */ -static void s1c(FDI *fdi) +static void +s1c(FDI *fdi) { - int shift = fdi->track_src[3]; - s13 (fdi); - bytes_mfm_add (fdi, 0x4e, 22); - bytes_mfm_add (fdi, 0x00, 12); - ibm_data (fdi, fdi->track_src, 0, 128 << shift); - fdi->track_src += 128 << shift; + int shift = fdi->track_src[3]; + s13(fdi); + bytes_mfm_add(fdi, 0x4e, 22); + bytes_mfm_add(fdi, 0x00, 12); + ibm_data(fdi, fdi->track_src, 0, 128 << shift); + fdi->track_src += 128 << shift; } /* standard short IBM sector */ -static void s1d(FDI *fdi) +static void +s1d(FDI *fdi) { - s15 (fdi); - bytes_mfm_add (fdi, 0x4e, 22); - bytes_mfm_add (fdi, 0x00, 12); - s19 (fdi); + s15(fdi); + bytes_mfm_add(fdi, 0x4e, 22); + bytes_mfm_add(fdi, 0x00, 12); + s19(fdi); } /* end marker */ -static void sff(FDI *fdi) +static void +sff(UNUSED(FDI *fdi)) { } -typedef void (*decode_described_track_func)(FDI*); +typedef void (*decode_described_track_func)(FDI *); -static decode_described_track_func decode_sectors_described_track[] = -{ - s00,s01,s02,s03,s04,dxx,dxx,dxx,s08,s09,s0a,s0b,s0c,s0d,dxx,dxx, /* 00-0F */ - s10,s11,s12,s13,s14,s15,s16,s17,s18,s19,s1a,s1b,s1c,s1d,dxx,dxx, /* 10-1F */ - s20,s21,s22,s23,s24,s25,s26,s27,dxx,dxx,dxx,dxx,dxx,dxx,dxx,dxx, /* 20-2F */ - dxx,dxx,dxx,dxx,dxx,dxx,dxx,dxx,dxx,dxx,dxx,dxx,dxx,dxx,dxx,dxx, /* 30-3F */ - dxx,dxx,dxx,dxx,dxx,dxx,dxx,dxx,dxx,dxx,dxx,dxx,dxx,dxx,dxx,dxx, /* 40-4F */ - dxx,dxx,dxx,dxx,dxx,dxx,dxx,dxx,dxx,dxx,dxx,dxx,dxx,dxx,dxx,dxx, /* 50-5F */ - dxx,dxx,dxx,dxx,dxx,dxx,dxx,dxx,dxx,dxx,dxx,dxx,dxx,dxx,dxx,dxx, /* 60-6F */ - dxx,dxx,dxx,dxx,dxx,dxx,dxx,dxx,dxx,dxx,dxx,dxx,dxx,dxx,dxx,dxx, /* 70-7F */ - dxx,dxx,dxx,dxx,dxx,dxx,dxx,dxx,dxx,dxx,dxx,dxx,dxx,dxx,dxx,dxx, /* 80-8F */ - dxx,dxx,dxx,dxx,dxx,dxx,dxx,dxx,dxx,dxx,dxx,dxx,dxx,dxx,dxx,dxx, /* 90-9F */ - dxx,dxx,dxx,dxx,dxx,dxx,dxx,dxx,dxx,dxx,dxx,dxx,dxx,dxx,dxx,dxx, /* A0-AF */ - dxx,dxx,dxx,dxx,dxx,dxx,dxx,dxx,dxx,dxx,dxx,dxx,dxx,dxx,dxx,dxx, /* B0-BF */ - dxx,dxx,dxx,dxx,dxx,dxx,dxx,dxx,dxx,dxx,dxx,dxx,dxx,dxx,dxx,dxx, /* C0-CF */ - dxx,dxx,dxx,dxx,dxx,dxx,dxx,dxx,dxx,dxx,dxx,dxx,dxx,dxx,dxx,dxx, /* D0-DF */ - dxx,dxx,dxx,dxx,dxx,dxx,dxx,dxx,dxx,dxx,dxx,dxx,dxx,dxx,dxx,dxx, /* E0-EF */ - dxx,dxx,dxx,dxx,dxx,dxx,dxx,dxx,dxx,dxx,dxx,dxx,dxx,dxx,dxx,sff /* F0-FF */ +static decode_described_track_func decode_sectors_described_track[] = { + s00, s01, s02, s03, s04, dxx, dxx, dxx, s08, s09, s0a, s0b, s0c, s0d, dxx, dxx, /* 00-0F */ + s10, s11, s12, s13, s14, s15, s16, s17, s18, s19, s1a, s1b, s1c, s1d, dxx, dxx, /* 10-1F */ + s20, s21, s22, s23, s24, s25, s26, s27, dxx, dxx, dxx, dxx, dxx, dxx, dxx, dxx, /* 20-2F */ + dxx, dxx, dxx, dxx, dxx, dxx, dxx, dxx, dxx, dxx, dxx, dxx, dxx, dxx, dxx, dxx, /* 30-3F */ + dxx, dxx, dxx, dxx, dxx, dxx, dxx, dxx, dxx, dxx, dxx, dxx, dxx, dxx, dxx, dxx, /* 40-4F */ + dxx, dxx, dxx, dxx, dxx, dxx, dxx, dxx, dxx, dxx, dxx, dxx, dxx, dxx, dxx, dxx, /* 50-5F */ + dxx, dxx, dxx, dxx, dxx, dxx, dxx, dxx, dxx, dxx, dxx, dxx, dxx, dxx, dxx, dxx, /* 60-6F */ + dxx, dxx, dxx, dxx, dxx, dxx, dxx, dxx, dxx, dxx, dxx, dxx, dxx, dxx, dxx, dxx, /* 70-7F */ + dxx, dxx, dxx, dxx, dxx, dxx, dxx, dxx, dxx, dxx, dxx, dxx, dxx, dxx, dxx, dxx, /* 80-8F */ + dxx, dxx, dxx, dxx, dxx, dxx, dxx, dxx, dxx, dxx, dxx, dxx, dxx, dxx, dxx, dxx, /* 90-9F */ + dxx, dxx, dxx, dxx, dxx, dxx, dxx, dxx, dxx, dxx, dxx, dxx, dxx, dxx, dxx, dxx, /* A0-AF */ + dxx, dxx, dxx, dxx, dxx, dxx, dxx, dxx, dxx, dxx, dxx, dxx, dxx, dxx, dxx, dxx, /* B0-BF */ + dxx, dxx, dxx, dxx, dxx, dxx, dxx, dxx, dxx, dxx, dxx, dxx, dxx, dxx, dxx, dxx, /* C0-CF */ + dxx, dxx, dxx, dxx, dxx, dxx, dxx, dxx, dxx, dxx, dxx, dxx, dxx, dxx, dxx, dxx, /* D0-DF */ + dxx, dxx, dxx, dxx, dxx, dxx, dxx, dxx, dxx, dxx, dxx, dxx, dxx, dxx, dxx, dxx, /* E0-EF */ + dxx, dxx, dxx, dxx, dxx, dxx, dxx, dxx, dxx, dxx, dxx, dxx, dxx, dxx, dxx, sff /* F0-FF */ }; -static void track_amiga (struct fdi *fdi, int first_sector, int max_sector) +static void +track_amiga(struct fdi *fdi, int first_sector, int max_sector) { - int i; - - bit_add (fdi, 0); - bit_drop_next (fdi); - for (i = 0; i < max_sector; i++) { - amiga_sector_header (fdi, 0, 0, first_sector, max_sector - i); - amiga_data (fdi, fdi->track_src + first_sector * 512); - first_sector++; - if (first_sector >= max_sector) first_sector = 0; - } - bytes_mfm_add (fdi, 0, 260); /* gap */ + bit_add(fdi, 0); + bit_drop_next(fdi); + for (int i = 0; i < max_sector; i++) { + amiga_sector_header(fdi, 0, 0, first_sector, max_sector - i); + amiga_data(fdi, fdi->track_src + first_sector * 512); + first_sector++; + if (first_sector >= max_sector) + first_sector = 0; + } + bytes_mfm_add(fdi, 0, 260); /* gap */ } -static void track_atari_st (struct fdi *fdi, int max_sector) +static void +track_atari_st(struct fdi *fdi, int max_sector) { - int i, gap3 = 0; - uae_u8 *p = fdi->track_src; + int gap3 = 0; + uint8_t *p = fdi->track_src; - switch (max_sector) - { - case 9: - gap3 = 40; - break; - case 10: - gap3 = 24; - break; - } - s15 (fdi); - for (i = 0; i < max_sector; i++) { - byte_mfm_add (fdi, 0x4e); - byte_mfm_add (fdi, 0x4e); - ibm_sector_header (fdi, 0, 0, fdi->current_track, 1); - ibm_data (fdi, p + i * 512, 0, 512); - bytes_mfm_add (fdi, 0x4e, gap3); - } - bytes_mfm_add (fdi, 0x4e, 660 - gap3); - fdi->track_src += fdi->track_len * 256; + switch (max_sector) { + case 9: + gap3 = 40; + break; + case 10: + gap3 = 24; + break; + + default: + break; + } + s15(fdi); + for (int i = 0; i < max_sector; i++) { + byte_mfm_add(fdi, 0x4e); + byte_mfm_add(fdi, 0x4e); + ibm_sector_header(fdi, 0, 0, fdi->current_track, 1); + ibm_data(fdi, p + i * 512, 0, 512); + bytes_mfm_add(fdi, 0x4e, gap3); + } + bytes_mfm_add(fdi, 0x4e, 660 - gap3); + fdi->track_src += fdi->track_len * 256; } -static void track_pc (struct fdi *fdi, int max_sector) +static void +track_pc(struct fdi *fdi, int max_sector) { - int i, gap3; - uae_u8 *p = fdi->track_src; + int gap3; + uint8_t *p = fdi->track_src; - switch (max_sector) - { - case 8: - gap3 = 116; - break; - case 9: - gap3 = 54; - break; - default: - gap3 = 100; /* fixme */ - break; - } - s11 (fdi); - for (i = 0; i < max_sector; i++) { - byte_mfm_add (fdi, 0x4e); - byte_mfm_add (fdi, 0x4e); - ibm_sector_header (fdi, 0, 0, fdi->current_track, 1); - ibm_data (fdi, p + i * 512, 0, 512); - bytes_mfm_add (fdi, 0x4e, gap3); - } - bytes_mfm_add (fdi, 0x4e, 600 - gap3); - fdi->track_src += fdi->track_len * 256; + switch (max_sector) { + case 8: + gap3 = 116; + break; + case 9: + gap3 = 54; + break; + default: + gap3 = 100; /* fixme */ + break; + } + s11(fdi); + for (int i = 0; i < max_sector; i++) { + byte_mfm_add(fdi, 0x4e); + byte_mfm_add(fdi, 0x4e); + ibm_sector_header(fdi, 0, 0, fdi->current_track, 1); + ibm_data(fdi, p + i * 512, 0, 512); + bytes_mfm_add(fdi, 0x4e, gap3); + } + bytes_mfm_add(fdi, 0x4e, 600 - gap3); + fdi->track_src += fdi->track_len * 256; } /* amiga dd */ -static void track_amiga_dd (struct fdi *fdi) +static void +track_amiga_dd(struct fdi *fdi) { - uae_u8 *p = fdi->track_src; - track_amiga (fdi, fdi->track_len >> 4, 11); - fdi->track_src = p + (fdi->track_len & 15) * 512; + uint8_t *p = fdi->track_src; + track_amiga(fdi, fdi->track_len >> 4, 11); + fdi->track_src = p + (fdi->track_len & 15) * 512; } /* amiga hd */ -static void track_amiga_hd (struct fdi *fdi) +static void +track_amiga_hd(struct fdi *fdi) { - uae_u8 *p = fdi->track_src; - track_amiga (fdi, 0, 22); - fdi->track_src = p + fdi->track_len * 256; + uint8_t *p = fdi->track_src; + track_amiga(fdi, 0, 22); + fdi->track_src = p + fdi->track_len * 256; } /* atari st 9 sector */ -static void track_atari_st_9 (struct fdi *fdi) +static void +track_atari_st_9(struct fdi *fdi) { - track_atari_st (fdi, 9); + track_atari_st(fdi, 9); } /* atari st 10 sector */ -static void track_atari_st_10 (struct fdi *fdi) +static void +track_atari_st_10(struct fdi *fdi) { - track_atari_st (fdi, 10); + track_atari_st(fdi, 10); } /* pc 8 sector */ -static void track_pc_8 (struct fdi *fdi) +static void +track_pc_8(struct fdi *fdi) { - track_pc (fdi, 8); + track_pc(fdi, 8); } /* pc 9 sector */ -static void track_pc_9 (struct fdi *fdi) +static void +track_pc_9(struct fdi *fdi) { - track_pc (fdi, 9); + track_pc(fdi, 9); } /* pc 15 sector */ -static void track_pc_15 (struct fdi *fdi) +static void +track_pc_15(struct fdi *fdi) { - track_pc (fdi, 15); + track_pc(fdi, 15); } /* pc 18 sector */ -static void track_pc_18 (struct fdi *fdi) +static void +track_pc_18(struct fdi *fdi) { - track_pc (fdi, 18); + track_pc(fdi, 18); } /* pc 36 sector */ -static void track_pc_36 (struct fdi *fdi) +static void +track_pc_36(struct fdi *fdi) { - track_pc (fdi, 36); + track_pc(fdi, 36); } -typedef void (*decode_normal_track_func)(FDI*); +typedef void (*decode_normal_track_func)(FDI *); -static decode_normal_track_func decode_normal_track[] = -{ - track_empty, /* 0 */ - track_amiga_dd, track_amiga_hd, /* 1-2 */ - track_atari_st_9, track_atari_st_10, /* 3-4 */ - track_pc_8, track_pc_9, track_pc_15, track_pc_18, track_pc_36, /* 5-9 */ - zxx,zxx,zxx,zxx,zxx /* A-F */ +static decode_normal_track_func decode_normal_track[] = { + track_empty, /* 0 */ + track_amiga_dd, track_amiga_hd, /* 1-2 */ + track_atari_st_9, track_atari_st_10, /* 3-4 */ + track_pc_8, track_pc_9, track_pc_15, track_pc_18, track_pc_36, /* 5-9 */ + zxx, zxx, zxx, zxx, zxx /* A-F */ }; -static void fix_mfm_sync (FDI *fdi) +static void +fix_mfm_sync(FDI *fdi) { - int i, pos, off1, off2, off3, mask1, mask2, mask3; + int pos; + int off1; + int off2; + int off3; + int mask1; + int mask2; + int mask3; - for (i = 0; i < fdi->mfmsync_offset; i++) { - pos = fdi->mfmsync_buffer[i]; - off1 = (pos - 1) >> 3; - off2 = (pos + 1) >> 3; - off3 = pos >> 3; - mask1 = 1 << (7 - ((pos - 1) & 7)); - mask2 = 1 << (7 - ((pos + 1) & 7)); - mask3 = 1 << (7 - (pos & 7)); - if (!(fdi->track_dst[off1] & mask1) && !(fdi->track_dst[off2] & mask2)) - fdi->track_dst[off3] |= mask3; - else - fdi->track_dst[off3] &= ~mask3; - } + for (int i = 0; i < fdi->mfmsync_offset; i++) { + pos = fdi->mfmsync_buffer[i]; + off1 = (pos - 1) >> 3; + off2 = (pos + 1) >> 3; + off3 = pos >> 3; + mask1 = 1 << (7 - ((pos - 1) & 7)); + mask2 = 1 << (7 - ((pos + 1) & 7)); + mask3 = 1 << (7 - (pos & 7)); + if (!(fdi->track_dst[off1] & mask1) && !(fdi->track_dst[off2] & mask2)) + fdi->track_dst[off3] |= mask3; + else + fdi->track_dst[off3] &= ~mask3; + } } -static int handle_sectors_described_track (FDI *fdi) +static int +handle_sectors_described_track(FDI *fdi) { #ifdef ENABLE_FDI2RAW_LOG - int oldout; - uae_u8 *start_src = fdi->track_src ; + int oldout; + uint8_t *start_src = fdi->track_src; #endif - fdi->encoding_type = *fdi->track_src++; - fdi->index_offset = get_u32(fdi->track_src); - fdi->index_offset >>= 8; - fdi->track_src += 3; - fdi2raw_log("sectors_described, index offset: %d\n",fdi->index_offset); + fdi->encoding_type = *fdi->track_src++; + fdi->index_offset = get_u32(fdi->track_src); + fdi->index_offset >>= 8; + fdi->track_src += 3; + fdi2raw_log("sectors_described, index offset: %d\n", fdi->index_offset); - do { - fdi->track_type = *fdi->track_src++; - fdi2raw_log("%06.6X %06.6X %02.2X:",fdi->track_src - start_src + 0x200, fdi->out/8, fdi->track_type); + do { + fdi->track_type = *fdi->track_src++; + fdi2raw_log("%06.6X %06.6X %02.2X:", fdi->track_src - start_src + 0x200, fdi->out / 8, fdi->track_type); #ifdef ENABLE_FDI2RAW_LOG - oldout = fdi->out; + oldout = fdi->out; #endif - decode_sectors_described_track[fdi->track_type](fdi); - fdi2raw_log(" %d\n", fdi->out - oldout); + decode_sectors_described_track[fdi->track_type](fdi); + fdi2raw_log(" %d\n", fdi->out - oldout); #ifdef ENABLE_FDI2RAW_LOG - oldout = fdi->out; + oldout = fdi->out; #endif - if (fdi->out < 0 || fdi->err) { - fdi2raw_log("\nin %d bytes, out %d bits\n", fdi->track_src - fdi->track_src_buffer, fdi->out); - return -1; - } - if (fdi->track_src - fdi->track_src_buffer >= fdi->track_src_len) { - fdi2raw_log("source buffer overrun, previous type: %02.2X\n", fdi->track_type); - return -1; - } - } while (fdi->track_type != 0xff); - fdi2raw_log("\n"); - fix_mfm_sync (fdi); - return fdi->out; + if (fdi->out < 0 || fdi->err) { + fdi2raw_log("\nin %d bytes, out %d bits\n", fdi->track_src - fdi->track_src_buffer, fdi->out); + return -1; + } + if (fdi->track_src - fdi->track_src_buffer >= fdi->track_src_len) { + fdi2raw_log("source buffer overrun, previous type: %02.2X\n", fdi->track_type); + return -1; + } + } while (fdi->track_type != 0xff); + fdi2raw_log("\n"); + fix_mfm_sync(fdi); + return fdi->out; } -static uae_u8 *fdi_decompress (int pulses, uae_u8 *sizep, uae_u8 *src, int *dofree) +static uint8_t * +fdi_decompress(int pulses, uint8_t *sizep, uint8_t *src, int *dofree) { - uae_u32 size = get_u24 (sizep); - uae_u32 *dst2; - int len = size & 0x3fffff; - uae_u8 *dst; - int mode = size >> 22, i; + uint32_t size = get_u24(sizep); + uint32_t *dst2; + int len = size & 0x3fffff; + uint8_t *dst; + int mode = size >> 22; - *dofree = 0; - if (mode == 0 && pulses * 2 > len) - mode = 1; - if (mode == 0) { - dst2 = (uae_u32*)src; - dst = src; - for (i = 0; i < pulses; i++) { - *dst2++ = get_u32 (src); - src += 4; - } - } else if (mode == 1) { - dst = fdi_malloc (pulses *4); - *dofree = 1; - fdi_decode (src, pulses, dst); - } else { - dst = 0; - } - return dst; + *dofree = 0; + if (mode == 0 && pulses * 2 > len) + mode = 1; + if (mode == 0) { + dst2 = (uint32_t *) src; + dst = src; + for (int i = 0; i < pulses; i++) { + *dst2++ = get_u32(src); + src += 4; + } + } else if (mode == 1) { + dst = fdi_malloc(pulses * 4); + *dofree = 1; + fdi_decode(src, pulses, dst); + } else { + dst = 0; + } + return dst; } -static void dumpstream(int track, uae_u8 *stream, int len) +static void +dumpstream(UNUSED(int track), UNUSED(uint8_t *stream), UNUSED(int len)) { #if 0 char name[100]; - FILE *f; + FILE *fp; sprintf (name, "track_%d.raw", track); - f = fopen(name, "wb"); - fwrite (stream, 1, len * 4, f); - fclose (f); + fp = fopen(name, "wb"); + fwrite (stream, 1, len * 4, fp); + fclose (fp); #endif } static int bitoffset; -STATIC_INLINE void addbit (uae_u8 *p, int bit) +static inline void +addbit(uint8_t *p, int bit) { - int off1 = bitoffset / 8; - int off2 = bitoffset % 8; - p[off1] |= bit << (7 - off2); - bitoffset++; + int off1 = bitoffset / 8; + int off2 = bitoffset % 8; + p[off1] |= bit << (7 - off2); + bitoffset++; } - struct pulse_sample { - uint32_t size; - int number_of_bits; + uint32_t size; + int number_of_bits; }; - -#define FDI_MAX_ARRAY 10 /* change this value as you want */ -static int pulse_limitval = 15; /* tolerance of 15% */ +#define FDI_MAX_ARRAY 10 /* change this value as you want */ +static int pulse_limitval = 15; /* tolerance of 15% */ static struct pulse_sample psarray[FDI_MAX_ARRAY]; -static int array_index; -static unsigned long total; -static int totaldiv; +static int array_index; +static uint32_t total; +static int totaldiv; -static void init_array(uint32_t standard_MFM_2_bit_cell_size, int nb_of_bits) +static void +init_array(uint32_t standard_MFM_2_bit_cell_size, int nb_of_bits) { - int i; - - for (i = 0; i < FDI_MAX_ARRAY; i++) { - psarray[i].size = standard_MFM_2_bit_cell_size; /* That is (total track length / 50000) for Amiga double density */ - total += psarray[i].size; - psarray[i].number_of_bits = nb_of_bits; - totaldiv += psarray[i].number_of_bits; - } - array_index = 0; + for (uint8_t i = 0; i < FDI_MAX_ARRAY; i++) { + psarray[i].size = standard_MFM_2_bit_cell_size; /* That is (total track length / 50000) for Amiga double density */ + total += psarray[i].size; + psarray[i].number_of_bits = nb_of_bits; + totaldiv += psarray[i].number_of_bits; + } + array_index = 0; } #if 0 -static void fdi2_decode (FDI *fdi, uint32_t totalavg, uae_u32 *avgp, uae_u32 *minp, uae_u32 *maxp, uae_u8 *idx, int maxidx, int *indexoffsetp, int pulses, int mfm) +static void fdi2_decode (FDI *fdi, uint32_t totalavg, uint32_t *avgp, uint32_t *minp, uint32_t *maxp, uint8_t *idx, int maxidx, int *indexoffsetp, int pulses, int mfm) { - uint32_t adjust; - uint32_t adjusted_pulse; - uint32_t standard_MFM_2_bit_cell_size = totalavg / 50000; - uint32_t standard_MFM_8_bit_cell_size = totalavg / 12500; - int real_size, i, j, eodat, outstep; - int indexoffset = *indexoffsetp; - uae_u8 *d = fdi->track_dst_buffer; - uae_u16 *pt = fdi->track_dst_buffer_timing; - uae_u32 ref_pulse, pulse; + uint32_t adjust; + uint32_t adjusted_pulse; + uint32_t standard_MFM_2_bit_cell_size = totalavg / 50000; + uint32_t standard_MFM_8_bit_cell_size = totalavg / 12500; + int real_size, i, j, eodat, outstep; + int indexoffset = *indexoffsetp; + uint8_t *d = fdi->track_dst_buffer; + uint16_t *pt = fdi->track_dst_buffer_timing; + uint32_t ref_pulse, pulse; - /* detects a long-enough stable pulse coming just after another stable pulse */ - i = 1; - while ( (i < pulses) && ( (idx[i] < maxidx) - || (idx[i - 1] < maxidx) - || (avgp[i] < (standard_MFM_2_bit_cell_size - (standard_MFM_2_bit_cell_size / 4))) ) ) - i++; - if (i == pulses) { - fdi2raw_log("No stable and long-enough pulse in track.\n"); - return; - } - i--; - eodat = i; - adjust = 0; - total = 0; - totaldiv = 0; - init_array(standard_MFM_2_bit_cell_size, 2); - bitoffset = 0; - ref_pulse = 0; - outstep = 0; - while (outstep < 2) { + /* detects a long-enough stable pulse coming just after another stable pulse */ + i = 1; + while ( (i < pulses) && ( (idx[i] < maxidx) + || (idx[i - 1] < maxidx) + || (avgp[i] < (standard_MFM_2_bit_cell_size - (standard_MFM_2_bit_cell_size / 4))) ) ) + i++; + if (i == pulses) { + fdi2raw_log("No stable and long-enough pulse in track.\n"); + return; + } + i--; + eodat = i; + adjust = 0; + total = 0; + totaldiv = 0; + init_array(standard_MFM_2_bit_cell_size, 2); + bitoffset = 0; + ref_pulse = 0; + outstep = 0; + while (outstep < 2) { - /* calculates the current average bitrate from previous decoded data */ - uae_u32 avg_size = (total << 3) / totaldiv; /* this is the new average size for one MFM bit */ - /* uae_u32 avg_size = (uae_u32)((((float)total)*8.0) / ((float)totaldiv)); */ - /* you can try tighter ranges than 25%, or wider ranges. I would probably go for tighter... */ - if ((avg_size < (standard_MFM_8_bit_cell_size - (pulse_limitval * standard_MFM_8_bit_cell_size / 100))) || - (avg_size > (standard_MFM_8_bit_cell_size + (pulse_limitval * standard_MFM_8_bit_cell_size / 100)))) { - avg_size = standard_MFM_8_bit_cell_size; - } - /* this is to prevent the average value from going too far - * from the theoretical value, otherwise it could progressively go to (2 * - * real value), or (real value / 2), etc. */ + /* calculates the current average bitrate from previous decoded data */ + uint32_t avg_size = (total << 3) / totaldiv; /* this is the new average size for one MFM bit */ + /* uint32_t avg_size = (uint32_t)((((float)total)*8.0) / ((float)totaldiv)); */ + /* you can try tighter ranges than 25%, or wider ranges. I would probably go for tighter... */ + if ((avg_size < (standard_MFM_8_bit_cell_size - (pulse_limitval * standard_MFM_8_bit_cell_size / 100))) || + (avg_size > (standard_MFM_8_bit_cell_size + (pulse_limitval * standard_MFM_8_bit_cell_size / 100)))) { + avg_size = standard_MFM_8_bit_cell_size; + } + /* this is to prevent the average value from going too far + * from the theoretical value, otherwise it could progressively go to (2 * + * real value), or (real value / 2), etc. */ - /* gets the next long-enough pulse (this may require more than one pulse) */ - pulse = 0; - while (pulse < ((avg_size / 4) - (avg_size / 16))) { - int indx; - i++; - if (i >= pulses) - i = 0; - indx = idx[i]; - if (rand() <= (indx * RAND_MAX) / maxidx) { - pulse += avgp[i] - ref_pulse; - if (indx >= maxidx) - ref_pulse = 0; - else - ref_pulse = avgp[i]; - } - if (i == eodat) - outstep++; - if (outstep == 1 && indexoffset == i) - *indexoffsetp = bitoffset; - } + /* gets the next long-enough pulse (this may require more than one pulse) */ + pulse = 0; + while (pulse < ((avg_size / 4) - (avg_size / 16))) { + int indx; + i++; + if (i >= pulses) + i = 0; + indx = idx[i]; + if (rand() <= (indx * RAND_MAX) / maxidx) { + pulse += avgp[i] - ref_pulse; + if (indx >= maxidx) + ref_pulse = 0; + else + ref_pulse = avgp[i]; + } + if (i == eodat) + outstep++; + if (outstep == 1 && indexoffset == i) + *indexoffsetp = bitoffset; + } - /* gets the size in bits from the pulse width, considering the current average bitrate */ - adjusted_pulse = pulse; - real_size = 0; - while (adjusted_pulse >= avg_size) { - real_size += 4; - adjusted_pulse -= avg_size / 2; - } - adjusted_pulse <<= 3; - while (adjusted_pulse >= ((avg_size * 4) + (avg_size / 4))) { - real_size += 2; - adjusted_pulse -= avg_size * 2; - } - if (adjusted_pulse >= ((avg_size * 3) + (avg_size / 4))) { - if (adjusted_pulse <= ((avg_size * 4) - (avg_size / 4))) { - if ((2 * ((adjusted_pulse >> 2) - adjust)) <= ((2 * avg_size) - (avg_size / 4))) - real_size += 3; - else - real_size += 4; - } else - real_size += 4; - } else { - if (adjusted_pulse > ((avg_size * 3) - (avg_size / 4))) { - real_size += 3; - } else { - if (adjusted_pulse >= ((avg_size * 2) + (avg_size / 4))) { - if ((2 * ((adjusted_pulse >> 2) - adjust)) < (avg_size + (avg_size / 4))) - real_size += 2; - else - real_size += 3; - } else - real_size += 2; - } - } + /* gets the size in bits from the pulse width, considering the current average bitrate */ + adjusted_pulse = pulse; + real_size = 0; + while (adjusted_pulse >= avg_size) { + real_size += 4; + adjusted_pulse -= avg_size / 2; + } + adjusted_pulse <<= 3; + while (adjusted_pulse >= ((avg_size * 4) + (avg_size / 4))) { + real_size += 2; + adjusted_pulse -= avg_size * 2; + } + if (adjusted_pulse >= ((avg_size * 3) + (avg_size / 4))) { + if (adjusted_pulse <= ((avg_size * 4) - (avg_size / 4))) { + if ((2 * ((adjusted_pulse >> 2) - adjust)) <= ((2 * avg_size) - (avg_size / 4))) + real_size += 3; + else + real_size += 4; + } else + real_size += 4; + } else { + if (adjusted_pulse > ((avg_size * 3) - (avg_size / 4))) { + real_size += 3; + } else { + if (adjusted_pulse >= ((avg_size * 2) + (avg_size / 4))) { + if ((2 * ((adjusted_pulse >> 2) - adjust)) < (avg_size + (avg_size / 4))) + real_size += 2; + else + real_size += 3; + } else + real_size += 2; + } + } - if (outstep == 1) { - for (j = real_size; j > 1; j--) - addbit (d, 0); - addbit (d, 1); - for (j = 0; j < real_size; j++) - *pt++ = (uae_u16)(pulse / real_size); - } + if (outstep == 1) { + for (j = real_size; j > 1; j--) + addbit (d, 0); + addbit (d, 1); + for (j = 0; j < real_size; j++) + *pt++ = (uint16_t)(pulse / real_size); + } - /* prepares for the next pulse */ - adjust = ((real_size * avg_size)/8) - pulse; - total -= psarray[array_index].size; - totaldiv -= psarray[array_index].number_of_bits; - psarray[array_index].size = pulse; - psarray[array_index].number_of_bits = real_size; - total += pulse; - totaldiv += real_size; - array_index++; - if (array_index >= FDI_MAX_ARRAY) - array_index = 0; - } + /* prepares for the next pulse */ + adjust = ((real_size * avg_size)/8) - pulse; + total -= psarray[array_index].size; + totaldiv -= psarray[array_index].number_of_bits; + psarray[array_index].size = pulse; + psarray[array_index].number_of_bits = real_size; + total += pulse; + totaldiv += real_size; + array_index++; + if (array_index >= FDI_MAX_ARRAY) + array_index = 0; + } - fdi->out = bitoffset; + fdi->out = bitoffset; } #else -static void fdi2_decode (FDI *fdi, uint32_t totalavg, uae_u32 *avgp, uae_u32 *minp, uae_u32 *maxp, uae_u8 *idx, int maxidx, int *indexoffsetp, int pulses, int mfm) +static void +fdi2_decode(FDI *fdi, uint32_t totalavg, uint32_t *avgp, uint32_t *minp, uint32_t *maxp, uint8_t *idx, int maxidx, int *indexoffsetp, int pulses, int mfm) { - uint32_t adjust; - uint32_t adjusted_pulse; - uint32_t standard_MFM_2_bit_cell_size = totalavg / 50000; - uint32_t standard_MFM_8_bit_cell_size = totalavg / 12500; - int real_size, i, j, nexti, eodat, outstep, randval; - int indexoffset = *indexoffsetp; - uae_u8 *d = fdi->track_dst_buffer; - uae_u16 *pt = fdi->track_dst_buffer_timing; - uae_u32 ref_pulse, pulse; - long jitter; + uint32_t adjust; + uint32_t adjusted_pulse; + uint32_t standard_MFM_2_bit_cell_size = totalavg / 50000; + uint32_t standard_MFM_8_bit_cell_size = totalavg / 12500; + int real_size; + int i; + int j; + int nexti; + int eodat; + int outstep; + int randval; + int indexoffset = *indexoffsetp; + uint8_t *d = fdi->track_dst_buffer; + uint16_t *pt = fdi->track_dst_buffer_timing; + uint32_t ref_pulse; + uint32_t pulse; + int32_t jitter; - /* detects a long-enough stable pulse coming just after another stable pulse */ - i = 1; - while ( (i < pulses) && ( (idx[i] < maxidx) - || (idx[i - 1] < maxidx) - || (minp[i] < (standard_MFM_2_bit_cell_size - (standard_MFM_2_bit_cell_size / 4))) ) ) - i++; - if (i == pulses) { - fdi2raw_log("FDI: No stable and long-enough pulse in track.\n"); - return; - } - nexti = i; - eodat = i; - i--; - adjust = 0; - total = 0; - totaldiv = 0; - init_array(standard_MFM_2_bit_cell_size, 1 + mfm); - bitoffset = 0; - ref_pulse = 0; - jitter = 0; - outstep = -1; - while (outstep < 2) { + /* detects a long-enough stable pulse coming just after another stable pulse */ + i = 1; + while ((i < pulses) && ((idx[i] < maxidx) || (idx[i - 1] < maxidx) || (minp[i] < (standard_MFM_2_bit_cell_size - (standard_MFM_2_bit_cell_size / 4))))) + i++; + if (i == pulses) { + fdi2raw_log("FDI: No stable and long-enough pulse in track.\n"); + return; + } + nexti = i; + eodat = i; + i--; + adjust = 0; + total = 0; + totaldiv = 0; + init_array(standard_MFM_2_bit_cell_size, 1 + mfm); + bitoffset = 0; + ref_pulse = 0; + jitter = 0; + outstep = -1; + while (outstep < 2) { - /* calculates the current average bitrate from previous decoded data */ - uae_u32 avg_size = (total << (2 + mfm)) / totaldiv; /* this is the new average size for one MFM bit */ - /* uae_u32 avg_size = (uae_u32)((((float)total)*((float)(mfm+1))*4.0) / ((float)totaldiv)); */ - /* you can try tighter ranges than 25%, or wider ranges. I would probably go for tighter... */ - if ((avg_size < (standard_MFM_8_bit_cell_size - (pulse_limitval * standard_MFM_8_bit_cell_size / 100))) || - (avg_size > (standard_MFM_8_bit_cell_size + (pulse_limitval * standard_MFM_8_bit_cell_size / 100)))) { - avg_size = standard_MFM_8_bit_cell_size; - } - /* this is to prevent the average value from going too far - * from the theoretical value, otherwise it could progressively go to (2 * - * real value), or (real value / 2), etc. */ + /* calculates the current average bitrate from previous decoded data */ + uint32_t avg_size = (uint32_t) ((total << (2 + mfm)) / totaldiv); /* this is the new average size for one MFM bit */ +#if 0 + uint32_t avg_size = (uint32_t)((((float)total)*((float)(mfm+1))*4.0) / ((float)totaldiv)); +#endif + /* you can try tighter ranges than 25%, or wider ranges. I would probably go for tighter... */ + if ((avg_size < (standard_MFM_8_bit_cell_size - (pulse_limitval * standard_MFM_8_bit_cell_size / 100))) || (avg_size > (standard_MFM_8_bit_cell_size + (pulse_limitval * standard_MFM_8_bit_cell_size / 100)))) { + avg_size = standard_MFM_8_bit_cell_size; + } + /* this is to prevent the average value from going too far + * from the theoretical value, otherwise it could progressively go to (2 * + * real value), or (real value / 2), etc. */ - /* gets the next long-enough pulse (this may require more than one pulse) */ - pulse = 0; - while (pulse < ((avg_size / 4) - (avg_size / 16))) { - uae_u32 avg_pulse, min_pulse, max_pulse; - i++; - if (i >= pulses) - i = 0; - if (i == nexti) { - do { - nexti++; - if (nexti >= pulses) - nexti = 0; - } while (idx[nexti] < maxidx); - } - if (idx[i] >= maxidx) { /* stable pulse */ - avg_pulse = avgp[i] - jitter; - min_pulse = minp[i]; - max_pulse = maxp[i]; - if (jitter >= 0) - max_pulse -= jitter; - else - min_pulse -= jitter; - if ((maxp[nexti] - avgp[nexti]) < (avg_pulse - min_pulse)) - min_pulse = avg_pulse - (maxp[nexti] - avgp[nexti]); - if ((avgp[nexti] - minp[nexti]) < (max_pulse - avg_pulse)) - max_pulse = avg_pulse + (avgp[nexti] - minp[nexti]); - if (min_pulse < ref_pulse) - min_pulse = ref_pulse; - randval = rand(); - if (randval < (RAND_MAX / 2)) { - if (randval > (RAND_MAX / 4)) { - if (randval <= (((3LL*RAND_MAX) / 8))) - randval = (2 * randval) - (RAND_MAX /4); - else - randval = (4 * randval) - RAND_MAX; - } - jitter = 0 - (randval * (avg_pulse - min_pulse)) / RAND_MAX; - } else { - randval -= RAND_MAX / 2; - if (randval > (RAND_MAX / 4)) { - if (randval <= (((3LL*RAND_MAX) / 8))) - randval = (2 * randval) - (RAND_MAX /4); - else - randval = (4 * randval) - RAND_MAX; - } - jitter = (randval * (max_pulse - avg_pulse)) / RAND_MAX; - } - avg_pulse += jitter; - if ((avg_pulse < min_pulse) || (avg_pulse > max_pulse)) { - fdi2raw_log("FDI: avg_pulse outside bounds! avg=%u min=%u max=%u\n", avg_pulse, min_pulse, max_pulse); - fdi2raw_log("FDI: avgp=%u (%u) minp=%u (%u) maxp=%u (%u) jitter=%d i=%d ni=%d\n", - avgp[i], avgp[nexti], minp[i], minp[nexti], maxp[i], maxp[nexti], jitter, i, nexti); - } - if (avg_pulse < ref_pulse) - fdi2raw_log("FDI: avg_pulse < ref_pulse! (%u < %u)\n", avg_pulse, ref_pulse); - pulse += avg_pulse - ref_pulse; - ref_pulse = 0; - if (i == eodat) - outstep++; - } else if (rand() <= ((idx[i] * RAND_MAX) / maxidx)) { - avg_pulse = avgp[i]; - min_pulse = minp[i]; - max_pulse = maxp[i]; - randval = rand(); - if (randval < (RAND_MAX / 2)) { - if (randval > (RAND_MAX / 4)) { - if (randval <= (((3LL*RAND_MAX) / 8))) - randval = (2 * randval) - (RAND_MAX /4); - else - randval = (4 * randval) - RAND_MAX; - } - avg_pulse -= (randval * (avg_pulse - min_pulse)) / RAND_MAX; - } else { - randval -= RAND_MAX / 2; - if (randval > (RAND_MAX / 4)) { - if (randval <= (((3LL*RAND_MAX) / 8))) - randval = (2 * randval) - (RAND_MAX /4); - else - randval = (4 * randval) - RAND_MAX; - } - avg_pulse += (randval * (max_pulse - avg_pulse)) / RAND_MAX; - } - if ((avg_pulse > ref_pulse) && (avg_pulse < (avgp[nexti] - jitter))) { - pulse += avg_pulse - ref_pulse; - ref_pulse = avg_pulse; - } - } - if (outstep == 1 && indexoffset == i) - *indexoffsetp = bitoffset; - } + /* gets the next long-enough pulse (this may require more than one pulse) */ + pulse = 0; + while (pulse < ((avg_size / 4) - (avg_size / 16))) { + uint32_t avg_pulse; + uint32_t min_pulse; + uint32_t max_pulse; + i++; + if (i >= pulses) + i = 0; + if (i == nexti) { + do { + nexti++; + if (nexti >= pulses) + nexti = 0; + } while (idx[nexti] < maxidx); + } + if (idx[i] >= maxidx) { /* stable pulse */ + avg_pulse = avgp[i] - jitter; + min_pulse = minp[i]; + max_pulse = maxp[i]; + if (jitter >= 0) + max_pulse -= jitter; + else + min_pulse -= jitter; + if ((maxp[nexti] - avgp[nexti]) < (avg_pulse - min_pulse)) + min_pulse = avg_pulse - (maxp[nexti] - avgp[nexti]); + if ((avgp[nexti] - minp[nexti]) < (max_pulse - avg_pulse)) + max_pulse = avg_pulse + (avgp[nexti] - minp[nexti]); + if (min_pulse < ref_pulse) + min_pulse = ref_pulse; + randval = rand(); + if (randval < (RAND_MAX / 2)) { + if (randval > (RAND_MAX / 4)) { + if (randval <= ((3LL * (uint64_t) RAND_MAX) / 8)) + randval = (2 * randval) - (RAND_MAX / 4); + else + randval = (4 * randval) - RAND_MAX; + } + jitter = 0 - (randval * (avg_pulse - min_pulse)) / RAND_MAX; + } else { + randval -= RAND_MAX / 2; + if (randval > (RAND_MAX / 4)) { + if (randval <= ((3LL * (uint64_t) RAND_MAX) / 8)) + randval = (2 * randval) - (RAND_MAX / 4); + else + randval = (4 * randval) - RAND_MAX; + } + jitter = (randval * (max_pulse - avg_pulse)) / RAND_MAX; + } + avg_pulse += jitter; + if ((avg_pulse < min_pulse) || (avg_pulse > max_pulse)) { + fdi2raw_log("FDI: avg_pulse outside bounds! avg=%u min=%u max=%u\n", avg_pulse, min_pulse, max_pulse); + fdi2raw_log("FDI: avgp=%u (%u) minp=%u (%u) maxp=%u (%u) jitter=%d i=%d ni=%d\n", + avgp[i], avgp[nexti], minp[i], minp[nexti], maxp[i], maxp[nexti], jitter, i, nexti); + } + if (avg_pulse < ref_pulse) + fdi2raw_log("FDI: avg_pulse < ref_pulse! (%u < %u)\n", avg_pulse, ref_pulse); + pulse += avg_pulse - ref_pulse; + ref_pulse = 0; + if (i == eodat) + outstep++; + } else if (rand() <= ((idx[i] * RAND_MAX) / maxidx)) { + avg_pulse = avgp[i]; + min_pulse = minp[i]; + max_pulse = maxp[i]; + randval = rand(); + if (randval < (RAND_MAX / 2)) { + if (randval > (RAND_MAX / 4)) { + if (randval <= ((3LL * (uint64_t) RAND_MAX) / 8)) + randval = (2 * randval) - (RAND_MAX / 4); + else + randval = (4 * randval) - RAND_MAX; + } + avg_pulse -= (randval * (avg_pulse - min_pulse)) / RAND_MAX; + } else { + randval -= RAND_MAX / 2; + if (randval > (RAND_MAX / 4)) { + if (randval <= ((3LL * (uint64_t) RAND_MAX) / 8)) + randval = (2 * randval) - (RAND_MAX / 4); + else + randval = (4 * randval) - RAND_MAX; + } + avg_pulse += (randval * (max_pulse - avg_pulse)) / RAND_MAX; + } + if ((avg_pulse > ref_pulse) && (avg_pulse < (avgp[nexti] - jitter))) { + pulse += avg_pulse - ref_pulse; + ref_pulse = avg_pulse; + } + } + if (outstep == 1 && indexoffset == i) + *indexoffsetp = bitoffset; + } - /* gets the size in bits from the pulse width, considering the current average bitrate */ - adjusted_pulse = pulse; - real_size = 0; - if (mfm) { - while (adjusted_pulse >= avg_size) { - real_size += 4; - adjusted_pulse -= avg_size / 2; - } - adjusted_pulse <<= 3; - while (adjusted_pulse >= ((avg_size * 4) + (avg_size / 4))) { - real_size += 2; - adjusted_pulse -= avg_size * 2; - } - if (adjusted_pulse >= ((avg_size * 3) + (avg_size / 4))) { - if (adjusted_pulse <= ((avg_size * 4) - (avg_size / 4))) { - if ((2 * ((adjusted_pulse >> 2) - adjust)) <= ((2 * avg_size) - (avg_size / 4))) - real_size += 3; - else - real_size += 4; - } else - real_size += 4; - } else { - if (adjusted_pulse > ((avg_size * 3) - (avg_size / 4))) { - real_size += 3; - } else { - if (adjusted_pulse >= ((avg_size * 2) + (avg_size / 4))) { - if ((2 * ((adjusted_pulse >> 2) - adjust)) < (avg_size + (avg_size / 4))) - real_size += 2; - else - real_size += 3; - } else - real_size += 2; - } - } - } else { - while (adjusted_pulse >= (2*avg_size)) - { - real_size+=4; - adjusted_pulse-=avg_size; - } - adjusted_pulse<<=2; - while (adjusted_pulse >= ((avg_size*3)+(avg_size/4))) - { - real_size+=2; - adjusted_pulse-=avg_size*2; - } - if (adjusted_pulse >= ((avg_size*2)+(avg_size/4))) - { - if (adjusted_pulse <= ((avg_size*3)-(avg_size/4))) - { - if (((adjusted_pulse>>1)-adjust) < (avg_size+(avg_size/4))) - real_size+=2; - else - real_size+=3; - } - else - real_size+=3; - } - else - { - if (adjusted_pulse > ((avg_size*2)-(avg_size/4))) - real_size+=2; - else - { - if (adjusted_pulse >= (avg_size+(avg_size/4))) - { - if (((adjusted_pulse>>1)-adjust) <= (avg_size-(avg_size/4))) - real_size++; - else - real_size+=2; - } - else - real_size++; - } - } - } + /* gets the size in bits from the pulse width, considering the current average bitrate */ + adjusted_pulse = pulse; + real_size = 0; + if (mfm) { + while (adjusted_pulse >= avg_size) { + real_size += 4; + adjusted_pulse -= avg_size / 2; + } + adjusted_pulse <<= 3; + while (adjusted_pulse >= ((avg_size * 4) + (avg_size / 4))) { + real_size += 2; + adjusted_pulse -= avg_size * 2; + } + if (adjusted_pulse >= ((avg_size * 3) + (avg_size / 4))) { + if (adjusted_pulse <= ((avg_size * 4) - (avg_size / 4))) { + if ((2 * ((adjusted_pulse >> 2) - adjust)) <= ((2 * avg_size) - (avg_size / 4))) + real_size += 3; + else + real_size += 4; + } else + real_size += 4; + } else { + if (adjusted_pulse > ((avg_size * 3) - (avg_size / 4))) { + real_size += 3; + } else { + if (adjusted_pulse >= ((avg_size * 2) + (avg_size / 4))) { + if ((2 * ((adjusted_pulse >> 2) - adjust)) < (avg_size + (avg_size / 4))) + real_size += 2; + else + real_size += 3; + } else + real_size += 2; + } + } + } else { + while (adjusted_pulse >= (2 * avg_size)) { + real_size += 4; + adjusted_pulse -= avg_size; + } + adjusted_pulse <<= 2; + while (adjusted_pulse >= ((avg_size * 3) + (avg_size / 4))) { + real_size += 2; + adjusted_pulse -= avg_size * 2; + } + if (adjusted_pulse >= ((avg_size * 2) + (avg_size / 4))) { + if (adjusted_pulse <= ((avg_size * 3) - (avg_size / 4))) { + if (((adjusted_pulse >> 1) - adjust) < (avg_size + (avg_size / 4))) + real_size += 2; + else + real_size += 3; + } else + real_size += 3; + } else { + if (adjusted_pulse > ((avg_size * 2) - (avg_size / 4))) + real_size += 2; + else { + if (adjusted_pulse >= (avg_size + (avg_size / 4))) { + if (((adjusted_pulse >> 1) - adjust) <= (avg_size - (avg_size / 4))) + real_size++; + else + real_size += 2; + } else + real_size++; + } + } + } - /* after one pass to correctly initialize the average bitrate, outputs the bits */ - if (outstep == 1) { - for (j = real_size; j > 1; j--) - addbit (d, 0); - addbit (d, 1); - for (j = 0; j < real_size; j++) - *pt++ = (uae_u16)(pulse / real_size); - } + /* after one pass to correctly initialize the average bitrate, outputs the bits */ + if (outstep == 1) { + for (j = real_size; j > 1; j--) + addbit(d, 0); + addbit(d, 1); + for (j = 0; j < real_size; j++) + *pt++ = (uint16_t) (pulse / real_size); + } - /* prepares for the next pulse */ - adjust = ((real_size * avg_size) / (4 << mfm)) - pulse; - total -= psarray[array_index].size; - totaldiv -= psarray[array_index].number_of_bits; - psarray[array_index].size = pulse; - psarray[array_index].number_of_bits = real_size; - total += pulse; - totaldiv += real_size; - array_index++; - if (array_index >= FDI_MAX_ARRAY) - array_index = 0; - } + /* prepares for the next pulse */ + adjust = ((real_size * avg_size) / (4 << mfm)) - pulse; + total -= psarray[array_index].size; + totaldiv -= psarray[array_index].number_of_bits; + psarray[array_index].size = pulse; + psarray[array_index].number_of_bits = real_size; + total += pulse; + totaldiv += real_size; + array_index++; + if (array_index >= FDI_MAX_ARRAY) + array_index = 0; + } - fdi->out = bitoffset; + fdi->out = bitoffset; } #endif -static void fdi2_celltiming (FDI *fdi, uint32_t totalavg, int bitoffset, uae_u16 *out) +static void +fdi2_celltiming(FDI *fdi, uint32_t totalavg, int bitoffset, uint16_t *out) { - uae_u16 *pt2, *pt; - double avg_bit_len; - int i; + const uint16_t *pt2; + uint16_t *pt; + double avg_bit_len; - avg_bit_len = (double)totalavg / (double)bitoffset; - pt2 = fdi->track_dst_buffer_timing; - pt = out; - for (i = 0; i < bitoffset / 8; i++) { - double v = (pt2[0] + pt2[1] + pt2[2] + pt2[3] + pt2[4] + pt2[5] + pt2[6] + pt2[7]) / 8.0; - v = 1000.0 * v / avg_bit_len; - *pt++ = (uae_u16)v; - pt2 += 8; - } - *pt++ = out[0]; - *pt = out[0]; + avg_bit_len = (double) totalavg / (double) bitoffset; + pt2 = fdi->track_dst_buffer_timing; + pt = out; + for (int i = 0; i < bitoffset / 8; i++) { + double v = (pt2[0] + pt2[1] + pt2[2] + pt2[3] + pt2[4] + pt2[5] + pt2[6] + pt2[7]) / 8.0; + v = 1000.0 * v / avg_bit_len; + *pt++ = (uint16_t) v; + pt2 += 8; + } + *pt++ = out[0]; + *pt = out[0]; } -static int decode_lowlevel_track (FDI *fdi, int track, struct fdi_cache *cache) +static int +decode_lowlevel_track(FDI *fdi, int track, struct fdi_cache *cache) { - uae_u8 *p1; - uae_u32 *p2; - uae_u32 *avgp, *minp = 0, *maxp = 0; - uae_u8 *idxp = 0; - uae_u32 maxidx, totalavg, weakbits; - int i, j, len, pulses, indexoffset; - int avg_free, min_free = 0, max_free = 0, idx_free; - int idx_off1 = 0, idx_off2 = 0, idx_off3 = 0; + uint8_t *p1; + const uint32_t *p2; + uint32_t *avgp; + uint32_t *minp = 0; + uint32_t *maxp = 0; + uint8_t *idxp = 0; + uint32_t maxidx; + uint32_t totalavg; + uint32_t weakbits; + int j; + int k; + int len; + int pulses; + int indexoffset; + int avg_free; + int min_free = 0; + int max_free = 0; + int idx_free; + int idx_off1 = 0; + int idx_off2 = 0; + int idx_off3 = 0; - p1 = fdi->track_src; - pulses = get_u32 (p1); - if (!pulses) - return -1; - p1 += 4; - len = 12; - avgp = (uae_u32*)fdi_decompress (pulses, p1 + 0, p1 + len, &avg_free); - dumpstream(track, (uae_u8*)avgp, pulses); - len += get_u24 (p1 + 0) & 0x3fffff; - if (!avgp) - return -1; - if (get_u24 (p1 + 3) && get_u24 (p1 + 6)) { - minp = (uae_u32*)fdi_decompress (pulses, p1 + 3, p1 + len, &min_free); - len += get_u24 (p1 + 3) & 0x3fffff; - maxp = (uae_u32*)fdi_decompress (pulses, p1 + 6, p1 + len, &max_free); - len += get_u24 (p1 + 6) & 0x3fffff; - /* Computes the real min and max values */ - for (i = 0; i < pulses; i++) { - maxp[i] = avgp[i] + minp[i] - maxp[i]; - minp[i] = avgp[i] - minp[i]; - } - } else { - minp = avgp; - maxp = avgp; - } - if (get_u24 (p1 + 9)) { - idx_off1 = 0; - idx_off2 = 1; - idx_off3 = 2; - idxp = fdi_decompress (pulses, p1 + 9, p1 + len, &idx_free); - if (idx_free) { - if (idxp[0] == 0 && idxp[1] == 0) { - idx_off1 = 2; - idx_off2 = 3; - } else { - idx_off1 = 1; - idx_off2 = 0; - } - idx_off3 = 4; - } - } else { - idxp = fdi_malloc (pulses * 2); - idx_free = 1; - for (i = 0; i < pulses; i++) { - idxp[i * 2 + 0] = 2; - idxp[i * 2 + 1] = 0; - } - idxp[0] = 1; - idxp[1] = 1; - } + p1 = fdi->track_src; + pulses = get_u32(p1); + if (!pulses) + return -1; + p1 += 4; + len = 12; + avgp = (uint32_t *) fdi_decompress(pulses, p1 + 0, p1 + len, &avg_free); + dumpstream(track, (uint8_t *) avgp, pulses); + len += get_u24(p1 + 0) & 0x3fffff; + if (!avgp) + return -1; + if (get_u24(p1 + 3) && get_u24(p1 + 6)) { + minp = (uint32_t *) fdi_decompress(pulses, p1 + 3, p1 + len, &min_free); + len += get_u24(p1 + 3) & 0x3fffff; + maxp = (uint32_t *) fdi_decompress(pulses, p1 + 6, p1 + len, &max_free); + len += get_u24(p1 + 6) & 0x3fffff; + /* Computes the real min and max values */ + for (int i = 0; i < pulses; i++) { + maxp[i] = avgp[i] + minp[i] - maxp[i]; + minp[i] = avgp[i] - minp[i]; + } + } else { + minp = avgp; + maxp = avgp; + } + if (get_u24(p1 + 9)) { + idx_off1 = 0; + idx_off2 = 1; + idx_off3 = 2; + idxp = fdi_decompress(pulses, p1 + 9, p1 + len, &idx_free); + if (idx_free) { + if (idxp[0] == 0 && idxp[1] == 0) { + idx_off1 = 2; + idx_off2 = 3; + } else { + idx_off1 = 1; + idx_off2 = 0; + } + idx_off3 = 4; + } + } else { + idxp = fdi_malloc(pulses * 2); + idx_free = 1; + for (int i = 0; i < pulses; i++) { + idxp[i * 2 + 0] = 2; + idxp[i * 2 + 1] = 0; + } + idxp[0] = 1; + idxp[1] = 1; + } - maxidx = 0; - indexoffset = 0; - p1 = idxp; - for (i = 0; i < pulses; i++) { - if ((uint32_t)p1[idx_off1] + (uint32_t)p1[idx_off2] > maxidx) - maxidx = p1[idx_off1] + p1[idx_off2]; - p1 += idx_off3; - } - p1 = idxp; - for (i = 0; (i < pulses) && (p1[idx_off2] != 0); i++) /* falling edge, replace with idx_off1 for rising edge */ - p1 += idx_off3; - if (i < pulses) { - j = i; - do { - i++; - p1 += idx_off3; - if (i >= pulses) { - i = 0; - p1 = idxp; - } - } while ((i != j) && (p1[idx_off2] == 0)); /* falling edge, replace with idx_off1 for rising edge */ - if (i != j) /* index pulse detected */ - { - while ((i != j) && (p1[idx_off1] > p1[idx_off2])) { /* falling edge, replace with "<" for rising edge */ - i++; - p1 += idx_off3; - if (i >= pulses) { - i = 0; - p1 = idxp; - } - } - if (i != j) - indexoffset = i; /* index position detected */ - } - } - p1 = idxp; - p2 = avgp; - totalavg = 0; - weakbits = 0; - for (i = 0; i < pulses; i++) { - uint32_t sum = p1[idx_off1] + p1[idx_off2]; - if (sum >= maxidx) { - totalavg += *p2; - } else { - weakbits++; - } - p2++; - p1 += idx_off3; - idxp[i] = sum; - } - len = totalavg / 100000; - /* fdi2raw_log("totalavg=%u index=%d (%d) maxidx=%d weakbits=%d len=%d\n", - totalavg, indexoffset, maxidx, weakbits, len); */ - cache->avgp = avgp; - cache->idxp = idxp; - cache->minp = minp; - cache->maxp = maxp; - cache->avg_free = avg_free; - cache->idx_free = idx_free; - cache->min_free = min_free; - cache->max_free = max_free; - cache->totalavg = totalavg; - cache->pulses = pulses; - cache->maxidx = maxidx; - cache->indexoffset = indexoffset; - cache->weakbits = weakbits; - cache->lowlevel = 1; + maxidx = 0; + indexoffset = 0; + p1 = idxp; + for (int i = 0; i < pulses; i++) { + if ((uint32_t) p1[idx_off1] + (uint32_t) p1[idx_off2] > maxidx) + maxidx = p1[idx_off1] + p1[idx_off2]; + p1 += idx_off3; + } + p1 = idxp; + for (k = 0; (k < pulses) && (p1[idx_off2] != 0); k++) /* falling edge, replace with idx_off1 for rising edge */ + p1 += idx_off3; + if (k < pulses) { + j = k; + do { + k++; + p1 += idx_off3; + if (k >= pulses) { + k = 0; + p1 = idxp; + } + } while ((k != j) && (p1[idx_off2] == 0)); /* falling edge, replace with idx_off1 for rising edge */ + if (k != j) /* index pulse detected */ + { + while ((k != j) && (p1[idx_off1] > p1[idx_off2])) { /* falling edge, replace with "<" for rising edge */ + k++; + p1 += idx_off3; + if (k >= pulses) { + k = 0; + p1 = idxp; + } + } + if (k != j) + indexoffset = k; /* index position detected */ + } + } + p1 = idxp; + p2 = avgp; + totalavg = 0; + weakbits = 0; + for (int i = 0; i < pulses; i++) { + uint32_t sum = p1[idx_off1] + p1[idx_off2]; + if (sum >= maxidx) { + totalavg += *p2; + } else { + weakbits++; + } + p2++; + p1 += idx_off3; + idxp[i] = sum; + } + len = totalavg / 100000; +#if 0 + fdi2raw_log("totalavg=%u index=%d (%d) maxidx=%d weakbits=%d len=%d\n", + totalavg, indexoffset, maxidx, weakbits, len); +#endif + cache->avgp = avgp; + cache->idxp = idxp; + cache->minp = minp; + cache->maxp = maxp; + cache->avg_free = avg_free; + cache->idx_free = idx_free; + cache->min_free = min_free; + cache->max_free = max_free; + cache->totalavg = totalavg; + cache->pulses = pulses; + cache->maxidx = maxidx; + cache->indexoffset = indexoffset; + cache->weakbits = weakbits; + cache->lowlevel = 1; - return 1; + return 1; } -static unsigned char fdiid[]={"Formatted Disk Image file"}; -static int bit_rate_table[16] = { 125,150,250,300,500,1000 }; +static unsigned char fdiid[] = { "Formatted Disk Image file" }; +static int bit_rate_table[16] = { 125, 150, 250, 300, 500, 1000 }; -void fdi2raw_header_free (FDI *fdi) +void +fdi2raw_header_free(FDI *fdi) { - int i; - - fdi_free (fdi->mfmsync_buffer); - fdi_free (fdi->track_src_buffer); - fdi_free (fdi->track_dst_buffer); - fdi_free (fdi->track_dst_buffer_timing); - for (i = 0; i < MAX_TRACKS; i++) { - struct fdi_cache *c = &fdi->cache[i]; - if (c->idx_free) - fdi_free (c->idxp); - if (c->avg_free) - fdi_free (c->avgp); - if (c->min_free) - fdi_free (c->minp); - if (c->max_free) - fdi_free (c->maxp); - } - fdi_free (fdi); - fdi2raw_log("FREE: memory allocated %d\n", fdi_allocated); + fdi_free(fdi->mfmsync_buffer); + fdi_free(fdi->track_src_buffer); + fdi_free(fdi->track_dst_buffer); + fdi_free(fdi->track_dst_buffer_timing); + for (uint8_t i = 0; i < MAX_TRACKS; i++) { + struct fdi_cache *c = &fdi->cache[i]; + if (c->idx_free) + fdi_free(c->idxp); + if (c->avg_free) + fdi_free(c->avgp); + if (c->min_free) + fdi_free(c->minp); + if (c->max_free) + fdi_free(c->maxp); + } + fdi_free(fdi); + fdi2raw_log("FREE: memory allocated %d\n", fdi_allocated); } -int fdi2raw_get_last_track (FDI *fdi) +int +fdi2raw_get_last_track(FDI *fdi) { - return fdi->last_track; + return fdi->last_track; } -int fdi2raw_get_num_sector (FDI *fdi) +int +fdi2raw_get_num_sector(FDI *fdi) { - if (fdi->header[152] == 0x02) - return 22; - return 11; + if (fdi->header[152] == 0x02) + return 22; + return 11; } -int fdi2raw_get_last_head (FDI *fdi) +int +fdi2raw_get_last_head(FDI *fdi) { - return fdi->last_head; + return fdi->last_head; } -int fdi2raw_get_rotation (FDI *fdi) +int +fdi2raw_get_rotation(FDI *fdi) { - return fdi->rotation_speed; + return fdi->rotation_speed; } -int fdi2raw_get_bit_rate (FDI *fdi) +int +fdi2raw_get_bit_rate(FDI *fdi) { - return fdi->bit_rate; + return fdi->bit_rate; } -int fdi2raw_get_type (FDI *fdi) +FDI2RawDiskType +fdi2raw_get_type(FDI *fdi) { - return fdi->disk_type; + return fdi->disk_type; } -int fdi2raw_get_write_protect (FDI *fdi) +bool +fdi2raw_get_write_protect(FDI *fdi) { - return fdi->write_protect; + return fdi->write_protect; } -int fdi2raw_get_tpi (FDI *fdi) +int +fdi2raw_get_tpi(FDI *fdi) { - return fdi->header[148]; + return fdi->header[148]; } -FDI *fdi2raw_header(FILE *f) +FDI * +fdi2raw_header(FILE *fp) { - int i, offset, oldseek; - uae_u8 type, size; - FDI *fdi; + long i; + long offset; + long oldseek; + uint8_t type; + uint8_t size; + FDI *fdi; - fdi2raw_log("ALLOC: memory allocated %d\n", fdi_allocated); - fdi = fdi_malloc(sizeof(FDI)); - memset (fdi, 0, sizeof (FDI)); - fdi->file = f; - oldseek = ftell (fdi->file); - if (oldseek == -1) { - fdi_free(fdi); - return NULL; - } - if (fseek (fdi->file, 0, SEEK_SET) == -1) - fatal("fdi2raw_header(): Error seeking to the beginning of the file\n"); - if (fread (fdi->header, 1, 2048, fdi->file) != 2048) - fatal("fdi2raw_header(): Error reading header\n"); - if (fseek (fdi->file, oldseek, SEEK_SET) == -1) - fatal("fdi2raw_header(): Error seeking to offset oldseek\n"); - if (memcmp (fdiid, fdi->header, strlen ((char *)fdiid)) ) { - fdi_free(fdi); - return NULL; - } - if ((fdi->header[140] != 1 && fdi->header[140] != 2) || (fdi->header[141] != 0 && !(fdi->header[140]==2 && fdi->header[141]==1))) { - fdi_free(fdi); - return NULL; - } + fdi2raw_log("ALLOC: memory allocated %d\n", fdi_allocated); + fdi = fdi_malloc(sizeof(FDI)); + memset(fdi, 0, sizeof(FDI)); + fdi->file = fp; + oldseek = ftell(fdi->file); + if (oldseek == -1) { + fdi_free(fdi); + return NULL; + } + if (fseek(fdi->file, 0, SEEK_SET) == -1) + fatal("fdi2raw_header(): Error seeking to the beginning of the file\n"); + if (fread(fdi->header, 1, 2048, fdi->file) != 2048) + fatal("fdi2raw_header(): Error reading header\n"); + if (fseek(fdi->file, oldseek, SEEK_SET) == -1) + fatal("fdi2raw_header(): Error seeking to offset oldseek\n"); + if (memcmp(fdiid, fdi->header, strlen((char *) fdiid))) { + fdi_free(fdi); + return NULL; + } + if ((fdi->header[140] != 1 && fdi->header[140] != 2) || (fdi->header[141] != 0 && !(fdi->header[140] == 2 && fdi->header[141] == 1))) { + fdi_free(fdi); + return NULL; + } - fdi->mfmsync_buffer = fdi_malloc (MAX_MFM_SYNC_BUFFER * sizeof(int)); - fdi->track_src_buffer = fdi_malloc (MAX_SRC_BUFFER); - fdi->track_dst_buffer = fdi_malloc (MAX_DST_BUFFER); - fdi->track_dst_buffer_timing = fdi_malloc (MAX_TIMING_BUFFER); + fdi->mfmsync_buffer = fdi_malloc(MAX_MFM_SYNC_BUFFER * sizeof(int)); + fdi->track_src_buffer = fdi_malloc(MAX_SRC_BUFFER); + fdi->track_dst_buffer = fdi_malloc(MAX_DST_BUFFER); + fdi->track_dst_buffer_timing = fdi_malloc(MAX_TIMING_BUFFER); - fdi->last_track = ((fdi->header[142] << 8) + fdi->header[143]) + 1; - fdi->last_track *= fdi->header[144] + 1; - if (fdi->last_track > MAX_TRACKS) - fdi->last_track = MAX_TRACKS; - fdi->last_head = fdi->header[144]; - fdi->disk_type = fdi->header[145]; - fdi->rotation_speed = fdi->header[146] + 128; - fdi->write_protect = fdi->header[147] & 1; - fdi2raw_log("FDI version %d.%d\n", fdi->header[140], fdi->header[141]); - fdi2raw_log("last_track=%d rotation_speed=%d\n",fdi->last_track,fdi->rotation_speed); + fdi->last_track = ((fdi->header[142] << 8) + fdi->header[143]) + 1; + fdi->last_track *= fdi->header[144] + 1; + if (fdi->last_track > MAX_TRACKS) + fdi->last_track = MAX_TRACKS; + fdi->last_head = fdi->header[144]; + fdi->disk_type = fdi->header[145]; + fdi->rotation_speed = fdi->header[146] + 128; + fdi->write_protect = !!(fdi->header[147] & 1); + fdi2raw_log("FDI version %d.%d\n", fdi->header[140], fdi->header[141]); + fdi2raw_log("last_track=%d rotation_speed=%d\n", fdi->last_track, fdi->rotation_speed); - offset = 512; - i = fdi->last_track; - if (i > 180) { - offset += 512; - i -= 180; - while (i > 256) { - offset += 512; - i -= 256; - } - } - for (i = 0; i < fdi->last_track; i++) { - fdi->track_offsets[i] = offset; - type = fdi->header[152 + i * 2]; - size = fdi->header[152 + i * 2 + 1]; - if (type == 1) - offset += (size & 15) * 512; - else if ((type & 0xc0) == 0x80) - offset += (((type & 0x3f) << 8) | size) * 256; - else - offset += size * 256; - } - fdi->track_offsets[i] = offset; + offset = 512; + i = fdi->last_track; + if (i > 180) { + offset += 512; + i -= 180; + while (i > 256) { + offset += 512; + i -= 256; + } + } + for (i = 0; i < fdi->last_track; i++) { + fdi->track_offsets[i] = offset; + type = fdi->header[152 + i * 2]; + size = fdi->header[152 + i * 2 + 1]; + if (type == 1) + offset += (size & 15) * 512; + else if ((type & 0xc0) == 0x80) + offset += (((type & 0x3f) << 8) | size) * 256; + else + offset += size * 256; + } + fdi->track_offsets[i] = offset; - return fdi; + return fdi; } - -int fdi2raw_loadrevolution_2 (FDI *fdi, uae_u16 *mfmbuf, uae_u16 *tracktiming, int track, int *tracklength, int *indexoffsetp, int *multirev, int mfm) +static int +fdi2raw_loadrevolution_2(FDI *fdi, uint16_t *mfmbuf, uint16_t *tracktiming, int track, int *tracklength, int *indexoffsetp, int *multirev, int mfm) { - struct fdi_cache *cache = &fdi->cache[track]; - int len, i, idx; + struct fdi_cache *cache = &fdi->cache[track]; + int len; + int idx; - memset (fdi->track_dst_buffer, 0, MAX_DST_BUFFER); - idx = cache->indexoffset; - fdi2_decode (fdi, cache->totalavg, - cache->avgp, cache->minp, cache->maxp, cache->idxp, - cache->maxidx, &idx, cache->pulses, mfm); - /* fdi2raw_log("track %d: nbits=%d avg len=%.2f weakbits=%d idx=%d\n", - track, bitoffset, (double)cache->totalavg / bitoffset, cache->weakbits, cache->indexoffset); */ - len = fdi->out; - if (cache->weakbits >= 10 && multirev) - *multirev = 1; - *tracklength = len; + memset(fdi->track_dst_buffer, 0, MAX_DST_BUFFER); + idx = cache->indexoffset; + fdi2_decode(fdi, cache->totalavg, + cache->avgp, cache->minp, cache->maxp, cache->idxp, + cache->maxidx, &idx, cache->pulses, mfm); +#if 0 + fdi2raw_log("track %d: nbits=%d avg len=%.2f weakbits=%d idx=%d\n", + track, bitoffset, (double)cache->totalavg / bitoffset, cache->weakbits, cache->indexoffset); +#endif + len = fdi->out; + if (cache->weakbits >= 10 && multirev) + *multirev = 1; + *tracklength = len; - for (i = 0; i < (len + 15) / (2 * 8); i++) { - uae_u8 *data = fdi->track_dst_buffer + i * 2; - *mfmbuf++ = 256 * *data + *(data + 1); - } - fdi2_celltiming (fdi, cache->totalavg, len, tracktiming); - if (indexoffsetp) - *indexoffsetp = idx; - return 1; + for (int i = 0; i < (len + 15) / (2 * 8); i++) { + const uint8_t *data = fdi->track_dst_buffer + i * 2; + *mfmbuf++ = 256 * *data + *(data + 1); + } + fdi2_celltiming(fdi, cache->totalavg, len, tracktiming); + if (indexoffsetp) + *indexoffsetp = idx; + return 1; } -int fdi2raw_loadrevolution (FDI *fdi, uae_u16 *mfmbuf, uae_u16 *tracktiming, int track, int *tracklength, int mfm) +int +fdi2raw_loadrevolution(FDI *fdi, uint16_t *mfmbuf, uint16_t *tracktiming, int track, int *tracklength, int mfm) { - return fdi2raw_loadrevolution_2 (fdi, mfmbuf, tracktiming, track, tracklength, 0, 0, mfm); + track ^= fdi->reversed_side; + return fdi2raw_loadrevolution_2(fdi, mfmbuf, tracktiming, track, tracklength, 0, 0, mfm); } -int fdi2raw_loadtrack (FDI *fdi, uae_u16 *mfmbuf, uae_u16 *tracktiming, int track, int *tracklength, int *indexoffsetp, int *multirev, int mfm) +int +fdi2raw_loadtrack(FDI *fdi, uint16_t *mfmbuf, uint16_t *tracktiming, int track, int *tracklength, int *indexoffsetp, int *multirev, int mfm) { - uae_u8 *p; - int outlen, i; - struct fdi_cache *cache = &fdi->cache[track]; + const uint8_t *p; + int outlen; + struct fdi_cache *cache = &fdi->cache[track]; - if (cache->lowlevel) - return fdi2raw_loadrevolution_2 (fdi, mfmbuf, tracktiming, track, tracklength, indexoffsetp, multirev, mfm); + track ^= fdi->reversed_side; + if (cache->lowlevel) + return fdi2raw_loadrevolution_2(fdi, mfmbuf, tracktiming, track, tracklength, indexoffsetp, multirev, mfm); - fdi->err = 0; - fdi->track_src_len = fdi->track_offsets[track + 1] - fdi->track_offsets[track]; - if (fseek (fdi->file, fdi->track_offsets[track], SEEK_SET) == -1) - fatal("fdi2raw_loadtrack(): Error seeking to the beginning of the file\n"); - if (fread (fdi->track_src_buffer, 1, fdi->track_src_len, fdi->file) != fdi->track_src_len) - fatal("fdi2raw_loadtrack(): Error reading data\n"); - memset (fdi->track_dst_buffer, 0, MAX_DST_BUFFER); - fdi->track_dst_buffer_timing[0] = 0; + fdi->err = 0; + fdi->track_src_len = fdi->track_offsets[track + 1] - fdi->track_offsets[track]; + if (fseek(fdi->file, fdi->track_offsets[track], SEEK_SET) == -1) + fatal("fdi2raw_loadtrack(): Error seeking to the beginning of the file\n"); + if (fread(fdi->track_src_buffer, 1, fdi->track_src_len, fdi->file) != fdi->track_src_len) + fatal("fdi2raw_loadtrack(): Error reading data\n"); + memset(fdi->track_dst_buffer, 0, MAX_DST_BUFFER); + fdi->track_dst_buffer_timing[0] = 0; - fdi->current_track = track; - fdi->track_src = fdi->track_src_buffer; - fdi->track_dst = fdi->track_dst_buffer; - p = fdi->header + 152 + fdi->current_track * 2; - fdi->track_type = *p++; - fdi->track_len = *p++; - fdi->bit_rate = 0; - fdi->out = 0; - fdi->mfmsync_offset = 0; + fdi->current_track = track; + fdi->track_src = fdi->track_src_buffer; + fdi->track_dst = fdi->track_dst_buffer; + p = fdi->header + 152 + fdi->current_track * 2; + fdi->track_type = *p++; + fdi->track_len = *p++; + fdi->bit_rate = 0; + fdi->out = 0; + fdi->mfmsync_offset = 0; - if ((fdi->track_type & 0xf0) == 0xf0 || (fdi->track_type & 0xf0) == 0xe0) - fdi->bit_rate = bit_rate_table[fdi->track_type & 0x0f]; - else - fdi->bit_rate = 250; + if ((fdi->track_type & 0xf0) == 0xf0 || (fdi->track_type & 0xf0) == 0xe0) + fdi->bit_rate = bit_rate_table[fdi->track_type & 0x0f]; + else + fdi->bit_rate = 250; - /* fdi2raw_log("track %d: srclen: %d track_type: %02.2X, bitrate: %d\n", - fdi->current_track, fdi->track_src_len, fdi->track_type, fdi->bit_rate); */ +#if 0 + fdi2raw_log("track %d: srclen: %d track_type: %02.2X, bitrate: %d\n", + fdi->current_track, fdi->track_src_len, fdi->track_type, fdi->bit_rate); +#endif - if ((fdi->track_type & 0xc0) == 0x80) { + if ((fdi->track_type & 0xc0) == 0x80) { - outlen = decode_lowlevel_track (fdi, track, cache); + outlen = decode_lowlevel_track(fdi, track, cache); - } else if ((fdi->track_type & 0xf0) == 0xf0) { + } else if ((fdi->track_type & 0xf0) == 0xf0) { - outlen = decode_raw_track (fdi); + outlen = decode_raw_track(fdi); - } else if ((fdi->track_type & 0xf0) == 0xe0) { + } else if ((fdi->track_type & 0xf0) == 0xe0) { - outlen = handle_sectors_described_track (fdi); + outlen = handle_sectors_described_track(fdi); - } else if ((fdi->track_type & 0xf0)) { + } else if (fdi->track_type & 0xf0) { - zxx (fdi); - outlen = -1; + zxx(fdi); + outlen = -1; - } else if (fdi->track_type < 0x0f) { + } else if (fdi->track_type < 0x0f) { - decode_normal_track[fdi->track_type](fdi); - fix_mfm_sync (fdi); - outlen = fdi->out; + decode_normal_track[fdi->track_type](fdi); + fix_mfm_sync(fdi); + outlen = fdi->out; - } else { + } else { - zxx (fdi); - outlen = -1; + zxx(fdi); + outlen = -1; + } - } + if (fdi->err) + return 0; - if (fdi->err) - return 0; - - if (outlen > 0) { - if (cache->lowlevel) - return fdi2raw_loadrevolution_2 (fdi, mfmbuf, tracktiming, track, tracklength, indexoffsetp, multirev, mfm); - *tracklength = fdi->out; - for (i = 0; i < ((*tracklength) + 15) / (2 * 8); i++) { - uae_u8 *data = fdi->track_dst_buffer + i * 2; - *mfmbuf++ = 256 * *data + *(data + 1); - } - } - return outlen; + if (outlen > 0) { + if (cache->lowlevel) + return fdi2raw_loadrevolution_2(fdi, mfmbuf, tracktiming, track, tracklength, indexoffsetp, multirev, mfm); + *tracklength = fdi->out; + for (int i = 0; i < ((*tracklength) + 15) / (2 * 8); i++) { + const uint8_t *data = fdi->track_dst_buffer + i * 2; + *mfmbuf++ = 256 * *data + *(data + 1); + } + } + return outlen; } - diff --git a/src/floppy/lzf/LICENSE b/src/floppy/lzf/LICENSE index ee54ff717..b3a284d08 100644 --- a/src/floppy/lzf/LICENSE +++ b/src/floppy/lzf/LICENSE @@ -24,4 +24,3 @@ OF THE POSSIBILITY OF SUCH DAMAGE. Alternatively, the following files carry an additional notice that explicitly allows relicensing under the GPLv2: lzf.c lzf.h lzfP.h lzf_c.c lzf_d.c - diff --git a/src/floppy/lzf/README b/src/floppy/lzf/README index 0734ebe06..ebfd97e07 100644 --- a/src/floppy/lzf/README +++ b/src/floppy/lzf/README @@ -25,5 +25,3 @@ DESCRIPTION AUTHOR This library was written by Marc Lehmann (See also http://software.schmorp.de/pkg/liblzf). - - diff --git a/src/floppy/lzf/crc32.h b/src/floppy/lzf/crc32.h index cf8f6d409..5a88cd5ff 100644 --- a/src/floppy/lzf/crc32.h +++ b/src/floppy/lzf/crc32.h @@ -62,4 +62,3 @@ static const u32 crc_32_tab[] = #define crc32(crc,byte) (crc_32_tab[(u8)(crc) ^ (u8)(byte)] ^ ((crc) >> 8)) #endif - diff --git a/src/floppy/lzf/lzf.c b/src/floppy/lzf/lzf.c index bedfdb6fe..657bc4b04 100644 --- a/src/floppy/lzf/lzf.c +++ b/src/floppy/lzf/lzf.c @@ -1,16 +1,16 @@ /* * Copyright (c) 2006 Stefan Traby - * + * * Redistribution and use in source and binary forms, with or without modifica- * tion, are permitted provided that the following conditions are met: - * + * * 1. Redistributions of source code must retain the above copyright notice, * this list of conditions and the following disclaimer. - * + * * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. - * + * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MER- * CHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO @@ -534,4 +534,3 @@ main (int argc, char *argv[]) exit (rc ? 1 : 0); } - diff --git a/src/floppy/lzf/lzf.h b/src/floppy/lzf/lzf.h index 919b6e6be..061d4cea9 100644 --- a/src/floppy/lzf/lzf.h +++ b/src/floppy/lzf/lzf.h @@ -1,16 +1,16 @@ /* * Copyright (c) 2000-2008 Marc Alexander Lehmann - * + * * Redistribution and use in source and binary forms, with or without modifica- * tion, are permitted provided that the following conditions are met: - * + * * 1. Redistributions of source code must retain the above copyright notice, * this list of conditions and the following disclaimer. - * + * * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. - * + * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MER- * CHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO @@ -73,7 +73,7 @@ * and lzf_c.c. * */ -unsigned int +unsigned int lzf_compress (const void *const in_data, unsigned int in_len, void *out_data, unsigned int out_len); @@ -92,9 +92,8 @@ lzf_compress (const void *const in_data, unsigned int in_len, * * This function is very fast, about as fast as a copying loop. */ -unsigned int +unsigned int lzf_decompress (const void *const in_data, unsigned int in_len, void *out_data, unsigned int out_len); #endif - diff --git a/src/floppy/lzf/lzfP.h b/src/floppy/lzf/lzfP.h index 11c965ca3..6bb81d562 100644 --- a/src/floppy/lzf/lzfP.h +++ b/src/floppy/lzf/lzfP.h @@ -1,16 +1,16 @@ /* * Copyright (c) 2000-2007 Marc Alexander Lehmann - * + * * Redistribution and use in source and binary forms, with or without modifica- * tion, are permitted provided that the following conditions are met: - * + * * 1. Redistributions of source code must retain the above copyright notice, * this list of conditions and the following disclaimer. - * + * * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. - * + * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MER- * CHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO @@ -182,4 +182,3 @@ typedef LZF_HSLOT LZF_STATE[1 << (HLOG)]; #endif #endif - diff --git a/src/floppy/lzf/lzf_c.c b/src/floppy/lzf/lzf_c.c index 8ba4d0b84..8a52d68c0 100644 --- a/src/floppy/lzf/lzf_c.c +++ b/src/floppy/lzf/lzf_c.c @@ -1,16 +1,16 @@ /* * Copyright (c) 2000-2010 Marc Alexander Lehmann - * + * * Redistribution and use in source and binary forms, with or without modifica- * tion, are permitted provided that the following conditions are met: - * + * * 1. Redistributions of source code must retain the above copyright notice, * this list of conditions and the following disclaimer. - * + * * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. - * + * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MER- * CHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO @@ -290,4 +290,3 @@ lzf_compress (const void *const in_data, unsigned int in_len, return op - (u8 *)out_data; } - diff --git a/src/floppy/lzf/lzf_d.c b/src/floppy/lzf/lzf_d.c index 8433b8f1f..f838ba674 100644 --- a/src/floppy/lzf/lzf_d.c +++ b/src/floppy/lzf/lzf_d.c @@ -1,16 +1,16 @@ /* * Copyright (c) 2000-2010 Marc Alexander Lehmann - * + * * Redistribution and use in source and binary forms, with or without modifica- * tion, are permitted provided that the following conditions are met: - * + * * 1. Redistributions of source code must retain the above copyright notice, * this list of conditions and the following disclaimer. - * + * * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. - * + * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MER- * CHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO @@ -52,7 +52,7 @@ #endif #endif -unsigned int +unsigned int lzf_decompress (const void *const in_data, unsigned int in_len, void *out_data, unsigned int out_len) { @@ -182,4 +182,3 @@ lzf_decompress (const void *const in_data, unsigned int in_len, return op - (u8 *)out_data; } - diff --git a/src/game/CMakeLists.txt b/src/game/CMakeLists.txt index c8fbb41ff..83dcd4836 100644 --- a/src/game/CMakeLists.txt +++ b/src/game/CMakeLists.txt @@ -1,17 +1,17 @@ # -# 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. +# 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. +# This file is part of the 86Box distribution. # -# CMake build script. +# CMake build script. # -# Authors: David HrdliÄka, +# Authors: David HrdliÄka, # -# Copyright 2020,2021 David HrdliÄka. +# Copyright 2020-2021 David HrdliÄka. # add_library(game OBJECT gameport.c joystick_standard.c - joystick_ch_flightstick_pro.c joystick_sw_pad.c joystick_tm_fcs.c) \ No newline at end of file + joystick_ch_flightstick_pro.c joystick_sw_pad.c joystick_tm_fcs.c) diff --git a/src/game/gameport.c b/src/game/gameport.c index cbd4ec4ba..323555984 100644 --- a/src/game/gameport.c +++ b/src/game/gameport.c @@ -1,22 +1,22 @@ /* - * 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. + * 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. + * This file is part of the 86Box distribution. * - * Implementation of a generic Game Port. + * Implementation of a generic Game Port. * * * - * Authors: Miran Grca, - * Sarah Walker, - * RichardG, + * Authors: Miran Grca, + * Sarah Walker, + * RichardG, * - * Copyright 2016-2018 Miran Grca. - * Copyright 2008-2018 Sarah Walker. - * Copyright 2021 RichardG. + * Copyright 2016-2018 Miran Grca. + * Copyright 2008-2018 Sarah Walker. + * Copyright 2021 RichardG. */ #include #include @@ -35,206 +35,195 @@ #include <86box/joystick_standard.h> #include <86box/joystick_sw_pad.h> #include <86box/joystick_tm_fcs.h> +#include <86box/plat_unused.h> - -typedef struct { - pc_timer_t timer; - int axis_nr; +typedef struct g_axis_t { + pc_timer_t timer; + int axis_nr; struct _joystick_instance_ *joystick; } g_axis_t; typedef struct _gameport_ { - uint16_t addr; - uint8_t len; + uint16_t addr; + uint8_t len; struct _joystick_instance_ *joystick; - struct _gameport_ *next; + struct _gameport_ *next; } gameport_t; typedef struct _joystick_instance_ { - uint8_t state; - g_axis_t axis[4]; + uint8_t state; + g_axis_t axis[4]; const joystick_if_t *intf; - void *dat; + void *dat; } joystick_instance_t; - -int joystick_type = 0; - +int joystick_type = JS_TYPE_NONE; static const joystick_if_t joystick_none = { - "None", - "none", - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - 0, - 0, - 0 + .name = "None", + .internal_name = "none", + .init = NULL, + .close = NULL, + .read = NULL, + .write = NULL, + .read_axis = NULL, + .a0_over = NULL, + .axis_count = 0, + .button_count = 0, + .pov_count = 0, + .max_joysticks = 0, + .axis_names = { NULL }, + .button_names = { NULL }, + .pov_names = { NULL } }; - static const struct { - const joystick_if_t *joystick; + const joystick_if_t *joystick; } joysticks[] = { - { &joystick_none }, - { &joystick_2axis_2button }, - { &joystick_2axis_4button }, - { &joystick_2axis_6button }, - { &joystick_2axis_8button }, - { &joystick_3axis_2button }, - { &joystick_3axis_4button }, - { &joystick_4axis_4button }, - { &joystick_ch_flightstick_pro }, - { &joystick_sw_pad }, - { &joystick_tm_fcs }, - { NULL } + { &joystick_none }, + { &joystick_2axis_2button }, + { &joystick_2axis_4button }, + { &joystick_2axis_6button }, + { &joystick_2axis_8button }, + { &joystick_3axis_2button }, + { &joystick_3axis_4button }, + { &joystick_4axis_4button }, + { &joystick_ch_flightstick_pro }, + { &joystick_sw_pad }, + { &joystick_tm_fcs }, + { NULL } }; + static joystick_instance_t *joystick_instance = NULL; - static uint8_t gameport_pnp_rom[] = { - 0x09, 0xf8, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, /* BOX0002, dummy checksum (filled in by isapnp_add_card) */ - 0x0a, 0x10, 0x10, /* PnP version 1.0, vendor version 1.0 */ + 0x09, 0xf8, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, /* BOX0002, dummy checksum (filled in by isapnp_add_card) */ + 0x0a, 0x10, 0x10, /* PnP version 1.0, vendor version 1.0 */ 0x82, 0x09, 0x00, 'G', 'a', 'm', 'e', ' ', 'P', 'o', 'r', 't', /* ANSI identifier */ - 0x15, 0x09, 0xf8, 0x00, 0x02, 0x01, /* logical device BOX0002, can participate in boot */ - 0x1c, 0x41, 0xd0, 0xb0, 0x2f, /* compatible device PNPB02F */ - 0x31, 0x00, /* start dependent functions, preferred */ - 0x47, 0x01, 0x00, 0x02, 0x00, 0x02, 0x08, 0x08, /* I/O 0x200, decodes 16-bit, 8-byte alignment, 8 addresses */ - 0x30, /* start dependent functions, acceptable */ - 0x47, 0x01, 0x08, 0x02, 0x08, 0x02, 0x08, 0x08, /* I/O 0x208, decodes 16-bit, 8-byte alignment, 8 addresses */ - 0x31, 0x02, /* start dependent functions, sub-optimal */ - 0x47, 0x01, 0x00, 0x01, 0xf8, 0xff, 0x08, 0x08, /* I/O 0x100-0xFFF8, decodes 16-bit, 8-byte alignment, 8 addresses */ - 0x38, /* end dependent functions */ + 0x15, 0x09, 0xf8, 0x00, 0x02, 0x01, /* logical device BOX0002, can participate in boot */ + 0x1c, 0x41, 0xd0, 0xb0, 0x2f, /* compatible device PNPB02F */ + 0x31, 0x00, /* start dependent functions, preferred */ + 0x47, 0x01, 0x00, 0x02, 0x00, 0x02, 0x08, 0x08, /* I/O 0x200, decodes 16-bit, 8-byte alignment, 8 addresses */ + 0x30, /* start dependent functions, acceptable */ + 0x47, 0x01, 0x08, 0x02, 0x08, 0x02, 0x08, 0x08, /* I/O 0x208, decodes 16-bit, 8-byte alignment, 8 addresses */ + 0x31, 0x02, /* start dependent functions, sub-optimal */ + 0x47, 0x01, 0x00, 0x01, 0xf8, 0xff, 0x08, 0x08, /* I/O 0x100-0xFFF8, decodes 16-bit, 8-byte alignment, 8 addresses */ + 0x38, /* end dependent functions */ 0x79, 0x00 /* end tag, dummy checksum (filled in by isapnp_add_card) */ }; static const isapnp_device_config_t gameport_pnp_defaults[] = { - { - .activate = 1, - .io = { { .base = 0x200 }, } + {.activate = 1, + .io = { + { .base = 0x200 }, + } } }; - -const device_t *standalone_gameport_type; -int gameport_instance_id = 0; +const device_t *standalone_gameport_type; +int gameport_instance_id = 0; /* Linked list of active game ports. Only the top port responds to reads or writes, and ports at the standard 200h location are prioritized. */ -static gameport_t *active_gameports = NULL; +static gameport_t *active_gameports = NULL; - -char * +const char * joystick_get_name(int js) { if (!joysticks[js].joystick) - return NULL; - return (char *) joysticks[js].joystick->name; + return NULL; + return joysticks[js].joystick->name; } - -char * +const char * joystick_get_internal_name(int js) { if (joysticks[js].joystick == NULL) - return ""; + return ""; - return (char *) joysticks[js].joystick->internal_name; + return joysticks[js].joystick->internal_name; } - int joystick_get_from_internal_name(char *s) { int c = 0; while (joysticks[c].joystick != NULL) { - if (!strcmp((char *) joysticks[c].joystick->internal_name, s)) - return c; - c++; + if (!strcmp(joysticks[c].joystick->internal_name, s)) + return c; + c++; } return 0; } - int joystick_get_max_joysticks(int js) { return joysticks[js].joystick->max_joysticks; } - int joystick_get_axis_count(int js) { return joysticks[js].joystick->axis_count; } - int joystick_get_button_count(int js) { return joysticks[js].joystick->button_count; } - int joystick_get_pov_count(int js) { return joysticks[js].joystick->pov_count; } - -char * +const char * joystick_get_axis_name(int js, int id) { - return (char *) joysticks[js].joystick->axis_names[id]; + return joysticks[js].joystick->axis_names[id]; } - -char * +const char * joystick_get_button_name(int js, int id) { - return (char *) joysticks[js].joystick->button_names[id]; + return joysticks[js].joystick->button_names[id]; } - -char * +const char * joystick_get_pov_name(int js, int id) { - return (char *) joysticks[js].joystick->pov_names[id]; + return joysticks[js].joystick->pov_names[id]; } - static void gameport_time(joystick_instance_t *joystick, int nr, int axis) { if (axis == AXIS_NOT_PRESENT) - timer_disable(&joystick->axis[nr].timer); + timer_disable(&joystick->axis[nr].timer); else { - /* Convert axis value to 555 timing. */ - axis += 32768; - axis = (axis * 100) / 65; /* axis now in ohms */ - axis = (axis * 11) / 1000; - timer_set_delay_u64(&joystick->axis[nr].timer, TIMER_USEC * (axis + 24)); /* max = 11.115 ms */ + /* Convert axis value to 555 timing. */ + axis += 32768; + axis = (axis * 100) / 65; /* axis now in ohms */ + axis = (axis * 11) / 1000; + timer_set_delay_u64(&joystick->axis[nr].timer, TIMER_USEC * (axis + 24)); /* max = 11.115 ms */ } } - static void -gameport_write(uint16_t addr, uint8_t val, void *priv) +gameport_write(UNUSED(uint16_t addr), UNUSED(uint8_t val), void *priv) { - gameport_t *dev = (gameport_t *) priv; + gameport_t *dev = (gameport_t *) priv; joystick_instance_t *joystick = dev->joystick; /* Respond only if a joystick is present and this port is at the top of the active ports list. */ if (!joystick || (active_gameports != dev)) - return; + return; /* Read all axes. */ joystick->state |= 0x0f; @@ -250,16 +239,15 @@ gameport_write(uint16_t addr, uint8_t val, void *priv) cycles -= ISA_CYCLES(8); } - static uint8_t -gameport_read(uint16_t addr, void *priv) +gameport_read(UNUSED(uint16_t addr), void *priv) { - gameport_t *dev = (gameport_t *) priv; + gameport_t *dev = (gameport_t *) priv; joystick_instance_t *joystick = dev->joystick; /* Respond only if a joystick is present and this port is at the top of the active ports list. */ if (!joystick || (active_gameports != dev)) - return 0xff; + return 0xff; /* Merge axis state with button state. */ uint8_t ret = joystick->state | joystick->intf->read(joystick->dat); @@ -269,7 +257,6 @@ gameport_read(uint16_t addr, void *priv) return ret; } - static void timer_over(void *priv) { @@ -279,79 +266,77 @@ timer_over(void *priv) /* Notify the joystick when the first axis' period is finished. */ if (axis == &axis->joystick->axis[0]) - axis->joystick->intf->a0_over(axis->joystick->dat); + axis->joystick->intf->a0_over(axis->joystick->dat); } - void gameport_update_joystick_type(void) { /* Add a standalone game port if a joystick is enabled but no other game ports exist. */ if (standalone_gameport_type) - gameport_add(standalone_gameport_type); + gameport_add(standalone_gameport_type); /* Reset the joystick interface. */ if (joystick_instance) { - joystick_instance->intf->close(joystick_instance->dat); - joystick_instance->intf = joysticks[joystick_type].joystick; - joystick_instance->dat = joystick_instance->intf->init(); + joystick_instance->intf->close(joystick_instance->dat); + joystick_instance->intf = joysticks[joystick_type].joystick; + joystick_instance->dat = joystick_instance->intf->init(); } } - void gameport_remap(void *priv, uint16_t address) { - gameport_t *dev = (gameport_t *) priv, *other_dev; + gameport_t *dev = (gameport_t *) priv; + gameport_t *other_dev; if (dev->addr) { - /* Remove this port from the active ports list. */ - if (active_gameports == dev) { - active_gameports = dev->next; - dev->next = NULL; - } else { - other_dev = active_gameports; - while (other_dev) { - if (other_dev->next == dev) { - other_dev->next = dev->next; - dev->next = NULL; - break; - } - other_dev = other_dev->next; - } - } + /* Remove this port from the active ports list. */ + if (active_gameports == dev) { + active_gameports = dev->next; + dev->next = NULL; + } else { + other_dev = active_gameports; + while (other_dev) { + if (other_dev->next == dev) { + other_dev->next = dev->next; + dev->next = NULL; + break; + } + other_dev = other_dev->next; + } + } - io_removehandler(dev->addr, dev->len, - gameport_read, NULL, NULL, gameport_write, NULL, NULL, dev); + io_removehandler(dev->addr, dev->len, + gameport_read, NULL, NULL, gameport_write, NULL, NULL, dev); } dev->addr = address; if (dev->addr) { - /* Add this port to the active ports list. */ - if (!active_gameports || ((dev->addr & 0xfff8) == 0x200)) { - /* No ports have been added yet, or port within 200-207h: add to top. */ - dev->next = active_gameports; - active_gameports = dev; - } else { - /* Port at other addresses: add to bottom. */ - other_dev = active_gameports; - while (other_dev->next) - other_dev = other_dev->next; - other_dev->next = dev; - } + /* Add this port to the active ports list. */ + if (!active_gameports || ((dev->addr & 0xfff8) == 0x200)) { + /* No ports have been added yet, or port within 200-207h: add to top. */ + dev->next = active_gameports; + active_gameports = dev; + } else { + /* Port at other addresses: add to bottom. */ + other_dev = active_gameports; + while (other_dev->next) + other_dev = other_dev->next; + other_dev->next = dev; + } - io_sethandler(dev->addr, dev->len, - gameport_read, NULL, NULL, gameport_write, NULL, NULL, dev); + io_sethandler(dev->addr, dev->len, + gameport_read, NULL, NULL, gameport_write, NULL, NULL, dev); } } - static void gameport_pnp_config_changed(uint8_t ld, isapnp_device_config_t *config, void *priv) { if (ld > 0) - return; + return; gameport_t *dev = (gameport_t *) priv; @@ -359,20 +344,18 @@ gameport_pnp_config_changed(uint8_t ld, isapnp_device_config_t *config, void *pr gameport_remap(dev, (config->activate && (config->io[0].base != ISAPNP_IO_DISABLED)) ? config->io[0].base : 0); } - void * gameport_add(const device_t *gameport_type) { /* Prevent a standalone game port from being added later on, unless this is an unused Super I/O game port (no MACHINE_GAMEPORT machine flag). */ if (!(gameport_type->local & GAMEPORT_SIO) || machine_has_flags(machine, MACHINE_GAMEPORT)) - standalone_gameport_type = NULL; + standalone_gameport_type = NULL; /* Add game port device. */ return device_add_inst(gameport_type, gameport_instance_id++); } - static void * gameport_init(const device_t *info) { @@ -383,26 +366,26 @@ gameport_init(const device_t *info) /* Allocate global instance. */ if (!joystick_instance && joystick_type) { - joystick_instance = malloc(sizeof(joystick_instance_t)); - memset(joystick_instance, 0x00, sizeof(joystick_instance_t)); + joystick_instance = malloc(sizeof(joystick_instance_t)); + memset(joystick_instance, 0x00, sizeof(joystick_instance_t)); - joystick_instance->axis[0].joystick = joystick_instance; - joystick_instance->axis[1].joystick = joystick_instance; - joystick_instance->axis[2].joystick = joystick_instance; - joystick_instance->axis[3].joystick = joystick_instance; + joystick_instance->axis[0].joystick = joystick_instance; + joystick_instance->axis[1].joystick = joystick_instance; + joystick_instance->axis[2].joystick = joystick_instance; + joystick_instance->axis[3].joystick = joystick_instance; - joystick_instance->axis[0].axis_nr = 0; - joystick_instance->axis[1].axis_nr = 1; - joystick_instance->axis[2].axis_nr = 2; - joystick_instance->axis[3].axis_nr = 3; + joystick_instance->axis[0].axis_nr = 0; + joystick_instance->axis[1].axis_nr = 1; + joystick_instance->axis[2].axis_nr = 2; + joystick_instance->axis[3].axis_nr = 3; - timer_add(&joystick_instance->axis[0].timer, timer_over, &joystick_instance->axis[0], 0); - timer_add(&joystick_instance->axis[1].timer, timer_over, &joystick_instance->axis[1], 0); - timer_add(&joystick_instance->axis[2].timer, timer_over, &joystick_instance->axis[2], 0); - timer_add(&joystick_instance->axis[3].timer, timer_over, &joystick_instance->axis[3], 0); + timer_add(&joystick_instance->axis[0].timer, timer_over, &joystick_instance->axis[0], 0); + timer_add(&joystick_instance->axis[1].timer, timer_over, &joystick_instance->axis[1], 0); + timer_add(&joystick_instance->axis[2].timer, timer_over, &joystick_instance->axis[2], 0); + timer_add(&joystick_instance->axis[3].timer, timer_over, &joystick_instance->axis[3], 0); - joystick_instance->intf = joysticks[joystick_type].joystick; - joystick_instance->dat = joystick_instance->intf->init(); + joystick_instance->intf = joysticks[joystick_type].joystick; + joystick_instance->dat = joystick_instance->intf->init(); } dev->joystick = joystick_instance; @@ -413,11 +396,58 @@ gameport_init(const device_t *info) /* Register ISAPnP if this is a standard game port card. */ if ((info->local & 0xffff) == 0x200) - isapnp_set_device_defaults(isapnp_add_card(gameport_pnp_rom, sizeof(gameport_pnp_rom), gameport_pnp_config_changed, NULL, NULL, NULL, dev), 0, gameport_pnp_defaults); + isapnp_set_device_defaults(isapnp_add_card(gameport_pnp_rom, sizeof(gameport_pnp_rom), gameport_pnp_config_changed, NULL, NULL, NULL, dev), 0, gameport_pnp_defaults); return dev; } +static void * +tmacm_init(UNUSED(const device_t *info)) +{ + uint16_t port = 0x0000; + gameport_t *dev = NULL; + + dev = malloc(sizeof(gameport_t)); + memset(dev, 0x00, sizeof(gameport_t)); + + port = (uint16_t) device_get_config_hex16("port1_addr"); + switch (port) { + case 0x201: + dev = gameport_add(&gameport_201_device); + break; + case 0x203: + dev = gameport_add(&gameport_203_device); + break; + case 0x205: + dev = gameport_add(&gameport_205_device); + break; + case 0x207: + dev = gameport_add(&gameport_207_device); + break; + default: + break; + } + + port = (uint16_t) device_get_config_hex16("port2_addr"); + switch (port) { + case 0x209: + dev = gameport_add(&gameport_209_device); + break; + case 0x20b: + dev = gameport_add(&gameport_20b_device); + break; + case 0x20d: + dev = gameport_add(&gameport_20d_device); + break; + case 0x20f: + dev = gameport_add(&gameport_20f_device); + break; + default: + break; + } + + return dev; +} static void gameport_close(void *priv) @@ -429,82 +459,261 @@ gameport_close(void *priv) /* Free the global instance here, if it wasn't already freed. */ if (joystick_instance) { - joystick_instance->intf->close(joystick_instance->dat); + joystick_instance->intf->close(joystick_instance->dat); - free(joystick_instance); - joystick_instance = NULL; + free(joystick_instance); + joystick_instance = NULL; } free(dev); } - const device_t gameport_device = { - "Game port", - "gameport", - 0, 0x080200, - gameport_init, - gameport_close, - NULL, { NULL }, NULL, - NULL + .name = "Game port", + .internal_name = "gameport", + .flags = 0, + .local = 0x080200, + .init = gameport_init, + .close = gameport_close, + .reset = NULL, + { .available = NULL }, + .speed_changed = NULL, + .force_redraw = NULL, + .config = NULL }; const device_t gameport_201_device = { - "Game port (Port 201h only)", - "gameport_201", - 0, 0x010201, - gameport_init, - gameport_close, - NULL, { NULL }, NULL, - NULL + .name = "Game port (Port 201h only)", + .internal_name = "gameport_201", + .flags = 0, + .local = 0x010201, + .init = gameport_init, + .close = gameport_close, + .reset = NULL, + { .available = NULL }, + .speed_changed = NULL, + .force_redraw = NULL, + .config = NULL +}; + +const device_t gameport_203_device = { + .name = "Game port (Port 203h only)", + .internal_name = "gameport_203", + .flags = 0, + .local = 0x010203, + .init = gameport_init, + .close = gameport_close, + .reset = NULL, + { .available = NULL }, + .speed_changed = NULL, + .force_redraw = NULL, + .config = NULL +}; + +const device_t gameport_205_device = { + .name = "Game port (Port 205h only)", + .internal_name = "gameport_205", + .flags = 0, + .local = 0x010205, + .init = gameport_init, + .close = gameport_close, + .reset = NULL, + { .available = NULL }, + .speed_changed = NULL, + .force_redraw = NULL, + .config = NULL +}; + +const device_t gameport_207_device = { + .name = "Game port (Port 207h only)", + .internal_name = "gameport_207", + .flags = 0, + .local = 0x010207, + .init = gameport_init, + .close = gameport_close, + .reset = NULL, + { .available = NULL }, + .speed_changed = NULL, + .force_redraw = NULL, + .config = NULL }; const device_t gameport_208_device = { - "Game port (Port 208h-20fh)", - "gameport_208", - 0, 0x080208, - gameport_init, - gameport_close, - NULL, { NULL }, NULL, - NULL + .name = "Game port (Port 208h-20fh)", + .internal_name = "gameport_208", + .flags = 0, + .local = 0x080208, + .init = gameport_init, + .close = gameport_close, + .reset = NULL, + { .available = NULL }, + .speed_changed = NULL, + .force_redraw = NULL, + .config = NULL }; const device_t gameport_209_device = { - "Game port (Port 209h only)", - "gameport_209", - 0, 0x010209, - gameport_init, - gameport_close, - NULL, { NULL }, NULL, - NULL + .name = "Game port (Port 209h only)", + .internal_name = "gameport_209", + .flags = 0, + .local = 0x010209, + .init = gameport_init, + .close = gameport_close, + .reset = NULL, + { .available = NULL }, + .speed_changed = NULL, + .force_redraw = NULL, + .config = NULL +}; + +const device_t gameport_20b_device = { + .name = "Game port (Port 20Bh only)", + .internal_name = "gameport_20b", + .flags = 0, + .local = 0x01020B, + .init = gameport_init, + .close = gameport_close, + .reset = NULL, + { .available = NULL }, + .speed_changed = NULL, + .force_redraw = NULL, + .config = NULL +}; + +const device_t gameport_20d_device = { + .name = "Game port (Port 20Dh only)", + .internal_name = "gameport_20d", + .flags = 0, + .local = 0x01020D, + .init = gameport_init, + .close = gameport_close, + .reset = NULL, + { .available = NULL }, + .speed_changed = NULL, + .force_redraw = NULL, + .config = NULL +}; + +const device_t gameport_20f_device = { + .name = "Game port (Port 20Fh only)", + .internal_name = "gameport_20f", + .flags = 0, + .local = 0x01020F, + .init = gameport_init, + .close = gameport_close, + .reset = NULL, + { .available = NULL }, + .speed_changed = NULL, + .force_redraw = NULL, + .config = NULL +}; + +static const device_config_t tmacm_config[] = { + // clang-format off + { + .name = "port1_addr", + .description = "Port 1 Address", + .type = CONFIG_HEX16, + .default_string = "", + .default_int = 0x0201, + .file_filter = "", + .spinner = { 0 }, + .selection = { + { .description = "201h", .value = 0x0201 }, + { .description = "203h", .value = 0x0203 }, + { .description = "205h", .value = 0x0205 }, + { .description = "207h", .value = 0x0207 }, + { .description = "Disabled", .value = 0x0000 }, + { "" } + } + }, + { + .name = "port2_addr", + .description = "Port 2 Address", + .type = CONFIG_HEX16, + .default_string = "", + .default_int = 0x0209, + .file_filter = "", + .spinner = { 0 }, + .selection = { + { .description = "209h", .value = 0x0209 }, + { .description = "20Bh", .value = 0x020B }, + { .description = "20Dh", .value = 0x020D }, + { .description = "20Fh", .value = 0x020F }, + { .description = "Disabled", .value = 0x0000 }, + { "" } + } + }, + { "", "", -1 } + // clang-format on +}; + +const device_t gameport_tm_acm_device = { + .name = "Game port (ThrustMaster ACM)", + .internal_name = "gameport_tmacm", + .flags = DEVICE_ISA, + .local = 0, + .init = tmacm_init, + .close = NULL, + .reset = NULL, + { .available = NULL }, + .speed_changed = NULL, + .force_redraw = NULL, + .config = tmacm_config }; const device_t gameport_pnp_device = { - "Game port (Plug and Play only)", - "gameport_pnp", - 0, 0x080000, - gameport_init, - gameport_close, - NULL, { NULL }, NULL, - NULL + .name = "Game port (Plug and Play only)", + .internal_name = "gameport_pnp", + .flags = 0, + .local = 0x080000, + .init = gameport_init, + .close = gameport_close, + .reset = NULL, + { .available = NULL }, + .speed_changed = NULL, + .force_redraw = NULL, + .config = NULL }; const device_t gameport_pnp_6io_device = { - "Game port (Plug and Play only, 6 I/O ports)", - "gameport_pnp_6io", - 0, 0x060000, - gameport_init, - gameport_close, - NULL, { NULL }, NULL, - NULL + .name = "Game port (Plug and Play only, 6 I/O ports)", + .internal_name = "gameport_pnp_6io", + .flags = 0, + .local = 0x060000, + .init = gameport_init, + .close = gameport_close, + .reset = NULL, + { .available = NULL }, + .speed_changed = NULL, + .force_redraw = NULL, + .config = NULL }; const device_t gameport_sio_device = { - "Game port (Super I/O)", - "gameport_sio", - 0, 0x1080000, - gameport_init, - gameport_close, - NULL, { NULL }, NULL, - NULL + .name = "Game port (Super I/O)", + .internal_name = "gameport_sio", + .flags = 0, + .local = 0x1080000, + .init = gameport_init, + .close = gameport_close, + .reset = NULL, + { .available = NULL }, + .speed_changed = NULL, + .force_redraw = NULL, + .config = NULL +}; + +const device_t gameport_sio_1io_device = { + .name = "Game port (Super I/O, 1 I/O port)", + .internal_name = "gameport_sio", + .flags = 0, + .local = 0x1010000, + .init = gameport_init, + .close = gameport_close, + .reset = NULL, + { .available = NULL }, + .speed_changed = NULL, + .force_redraw = NULL, + .config = NULL }; diff --git a/src/game/joystick_ch_flightstick_pro.c b/src/game/joystick_ch_flightstick_pro.c index b6cd8911f..49ce824bc 100644 --- a/src/game/joystick_ch_flightstick_pro.c +++ b/src/game/joystick_ch_flightstick_pro.c @@ -1,20 +1,20 @@ /* - * VARCem Virtual ARchaeological Computer EMulator. - * An emulator of (mostly) x86-based PC systems and devices, - * using the ISA,EISA,VLB,MCA and PCI system buses, roughly - * spanning the era between 1981 and 1995. + * 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 VARCem Project. + * This file is part of the 86Box distribution. * - * Implementation of the Flight Stick Pro. + * Implementation of the Flight Stick Pro. * * * - * Authors: Miran Grca, - * Sarah Walker, + * Authors: Miran Grca, + * Sarah Walker, * - * Copyright 2016-2018 Miran Grca. - * Copyright 2008-2018 Sarah Walker. + * Copyright 2016-2018 Miran Grca. + * Copyright 2008-2018 Sarah Walker. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -44,90 +44,95 @@ #include <86box/timer.h> #include <86box/gameport.h> #include <86box/joystick_standard.h> +#include <86box/plat_unused.h> - -static void *ch_flightstick_pro_init(void) +static void * +ch_flightstick_pro_init(void) { - return NULL; + return NULL; } -static void ch_flightstick_pro_close(void *p) +static void +ch_flightstick_pro_close(UNUSED(void *priv)) { + // } -static uint8_t ch_flightstick_pro_read(void *p) +static uint8_t +ch_flightstick_pro_read(UNUSED(void *priv)) { - uint8_t ret = 0xf0; - - if (JOYSTICK_PRESENT(0)) - { - if (joystick_state[0].button[0]) - ret &= ~0x10; - if (joystick_state[0].button[1]) - ret &= ~0x20; - if (joystick_state[0].button[2]) - ret &= ~0x40; - if (joystick_state[0].button[3]) - ret &= ~0x80; - if (joystick_state[0].pov[0] != -1) - { - if (joystick_state[0].pov[0] > 315 || joystick_state[0].pov[0] < 45) - ret &= ~0xf0; - else if (joystick_state[0].pov[0] >= 45 && joystick_state[0].pov[0] < 135) - ret &= ~0xb0; - else if (joystick_state[0].pov[0] >= 135 && joystick_state[0].pov[0] < 225) - ret &= ~0x70; - else if (joystick_state[0].pov[0] >= 225 && joystick_state[0].pov[0] < 315) - ret &= ~0x30; - } + uint8_t ret = 0xf0; + + if (JOYSTICK_PRESENT(0)) { + if (joystick_state[0].button[0]) + ret &= ~0x10; + if (joystick_state[0].button[1]) + ret &= ~0x20; + if (joystick_state[0].button[2]) + ret &= ~0x40; + if (joystick_state[0].button[3]) + ret &= ~0x80; + if (joystick_state[0].pov[0] != -1) { + if (joystick_state[0].pov[0] > 315 || joystick_state[0].pov[0] < 45) + ret &= ~0xf0; + else if (joystick_state[0].pov[0] >= 45 && joystick_state[0].pov[0] < 135) + ret &= ~0xb0; + else if (joystick_state[0].pov[0] >= 135 && joystick_state[0].pov[0] < 225) + ret &= ~0x70; + else if (joystick_state[0].pov[0] >= 225 && joystick_state[0].pov[0] < 315) + ret &= ~0x30; } + } - return ret; + return ret; } -static void ch_flightstick_pro_write(void *p) +static void +ch_flightstick_pro_write(UNUSED(void *priv)) { + // } -static int ch_flightstick_pro_read_axis(void *p, int axis) +static int +ch_flightstick_pro_read_axis(UNUSED(void *priv), int axis) { - if (!JOYSTICK_PRESENT(0)) - return AXIS_NOT_PRESENT; + if (!JOYSTICK_PRESENT(0)) + return AXIS_NOT_PRESENT; - switch (axis) - { - case 0: - return joystick_state[0].axis[0]; - case 1: - return joystick_state[0].axis[1]; - case 2: - return 0; - case 3: - return joystick_state[0].axis[2]; - default: - return 0; - } + switch (axis) { + case 0: + return joystick_state[0].axis[0]; + case 1: + return joystick_state[0].axis[1]; + case 2: + return 0; + case 3: + return joystick_state[0].axis[2]; + default: + return 0; + } } -static void ch_flightstick_pro_a0_over(void *p) +static void +ch_flightstick_pro_a0_over(UNUSED(void *priv)) { + // } -const joystick_if_t joystick_ch_flightstick_pro = -{ - "CH Flightstick Pro", - "ch_flightstick_pro", - ch_flightstick_pro_init, - ch_flightstick_pro_close, - ch_flightstick_pro_read, - ch_flightstick_pro_write, - ch_flightstick_pro_read_axis, - ch_flightstick_pro_a0_over, - 3, - 4, - 1, - 1, - {"X axis", "Y axis", "Throttle"}, - {"Button 1", "Button 2", "Button 3", "Button 4"}, - {"POV"} +const joystick_if_t joystick_ch_flightstick_pro = { + .name = "CH Flightstick Pro", + .internal_name = "ch_flightstick_pro", + .init = ch_flightstick_pro_init, + .close = ch_flightstick_pro_close, + .read = ch_flightstick_pro_read, + .write = ch_flightstick_pro_write, + .read_axis = ch_flightstick_pro_read_axis, + .a0_over = ch_flightstick_pro_a0_over, + .axis_count = 3, + .button_count = 4, + .pov_count = 1, + .max_joysticks = 1, + .axis_names = { "X axis", "Y axis", "Throttle" }, + .button_names = { "Button 1", "Button 2", "Button 3", "Button 4" }, + .pov_names = { "POV" } }; diff --git a/src/game/joystick_standard.c b/src/game/joystick_standard.c index c06540b15..b9c449f99 100644 --- a/src/game/joystick_standard.c +++ b/src/game/joystick_standard.c @@ -1,20 +1,20 @@ /* - * VARCem Virtual ARchaeological Computer EMulator. - * An emulator of (mostly) x86-based PC systems and devices, - * using the ISA,EISA,VLB,MCA and PCI system buses, roughly - * spanning the era between 1981 and 1995. + * 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 VARCem Project. + * This file is part of the 86Box distribution. * - * Implementation of a standard joystick. + * Implementation of a standard joystick. * * * - * Authors: Miran Grca, - * Sarah Walker, + * Authors: Miran Grca, + * Sarah Walker, * - * Copyright 2016-2018 Miran Grca. - * Copyright 2008-2018 Sarah Walker. + * Copyright 2016-2018 Miran Grca. + * Copyright 2008-2018 Sarah Walker. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -44,314 +44,326 @@ #include <86box/timer.h> #include <86box/gameport.h> #include <86box/joystick_standard.h> +#include <86box/plat_unused.h> - -static void *joystick_standard_init(void) +static void * +joystick_standard_init(void) { - return NULL; + return NULL; } -static void joystick_standard_close(void *p) +static void +joystick_standard_close(UNUSED(void *priv)) { + // } -static uint8_t joystick_standard_read(void *p) +static uint8_t +joystick_standard_read(UNUSED(void *priv)) { - uint8_t ret = 0xf0; - - if (JOYSTICK_PRESENT(0)) - { - if (joystick_state[0].button[0]) - ret &= ~0x10; - if (joystick_state[0].button[1]) - ret &= ~0x20; - } - if (JOYSTICK_PRESENT(1)) - { - if (joystick_state[1].button[0]) - ret &= ~0x40; - if (joystick_state[1].button[1]) - ret &= ~0x80; - } - - return ret; + uint8_t ret = 0xf0; + + if (JOYSTICK_PRESENT(0)) { + if (joystick_state[0].button[0]) + ret &= ~0x10; + if (joystick_state[0].button[1]) + ret &= ~0x20; + } + if (JOYSTICK_PRESENT(1)) { + if (joystick_state[1].button[0]) + ret &= ~0x40; + if (joystick_state[1].button[1]) + ret &= ~0x80; + } + + return ret; } -static uint8_t joystick_standard_read_4button(void *p) +static uint8_t +joystick_standard_read_4button(UNUSED(void *priv)) { - uint8_t ret = 0xf0; - - if (JOYSTICK_PRESENT(0)) - { - if (joystick_state[0].button[0]) - ret &= ~0x10; - if (joystick_state[0].button[1]) - ret &= ~0x20; - if (joystick_state[0].button[2]) - ret &= ~0x40; - if (joystick_state[0].button[3]) - ret &= ~0x80; - } - - return ret; + uint8_t ret = 0xf0; + + if (JOYSTICK_PRESENT(0)) { + if (joystick_state[0].button[0]) + ret &= ~0x10; + if (joystick_state[0].button[1]) + ret &= ~0x20; + if (joystick_state[0].button[2]) + ret &= ~0x40; + if (joystick_state[0].button[3]) + ret &= ~0x80; + } + + return ret; } -static void joystick_standard_write(void *p) +static void +joystick_standard_write(UNUSED(void *priv)) { + // } -static int joystick_standard_read_axis(void *p, int axis) +static int +joystick_standard_read_axis(UNUSED(void *priv), int axis) { - switch (axis) - { - case 0: - if (!JOYSTICK_PRESENT(0)) - return AXIS_NOT_PRESENT; - return joystick_state[0].axis[0]; - case 1: - if (!JOYSTICK_PRESENT(0)) - return AXIS_NOT_PRESENT; - return joystick_state[0].axis[1]; - case 2: - if (!JOYSTICK_PRESENT(1)) - return AXIS_NOT_PRESENT; - return joystick_state[1].axis[0]; - case 3: - if (!JOYSTICK_PRESENT(1)) - return AXIS_NOT_PRESENT; - return joystick_state[1].axis[1]; - default: - return 0; - } -} - -static int joystick_standard_read_axis_4button(void *p, int axis) -{ - if (!JOYSTICK_PRESENT(0)) + switch (axis) { + case 0: + if (!JOYSTICK_PRESENT(0)) return AXIS_NOT_PRESENT; - - switch (axis) - { - case 0: - return joystick_state[0].axis[0]; - case 1: - return joystick_state[0].axis[1]; - case 2: - return 0; - case 3: - return 0; - default: - return 0; - } -} - -static int joystick_standard_read_axis_3axis(void *p, int axis) -{ - if (!JOYSTICK_PRESENT(0)) + return joystick_state[0].axis[0]; + case 1: + if (!JOYSTICK_PRESENT(0)) return AXIS_NOT_PRESENT; - - switch (axis) - { - case 0: - return joystick_state[0].axis[0]; - case 1: - return joystick_state[0].axis[1]; - case 2: - return joystick_state[0].axis[2]; - case 3: - return 0; + return joystick_state[0].axis[1]; + case 2: + if (!JOYSTICK_PRESENT(1)) + return AXIS_NOT_PRESENT; + return joystick_state[1].axis[0]; + case 3: + if (!JOYSTICK_PRESENT(1)) + return AXIS_NOT_PRESENT; + return joystick_state[1].axis[1]; default: - return 0; - } + return 0; + } } -static int joystick_standard_read_axis_4axis(void *p, int axis) +static int +joystick_standard_read_axis_4button(UNUSED(void *priv), int axis) { - if (!JOYSTICK_PRESENT(0)) - return AXIS_NOT_PRESENT; + if (!JOYSTICK_PRESENT(0)) + return AXIS_NOT_PRESENT; - switch (axis) - { - case 0: - return joystick_state[0].axis[0]; - case 1: - return joystick_state[0].axis[1]; - case 2: - return joystick_state[0].axis[2]; - case 3: - return joystick_state[0].axis[3]; + switch (axis) { + case 0: + return joystick_state[0].axis[0]; + case 1: + return joystick_state[0].axis[1]; + case 2: + return 0; + case 3: + return 0; default: - return 0; - } + return 0; + } } -static int joystick_standard_read_axis_6button(void *p, int axis) +static int +joystick_standard_read_axis_3axis(UNUSED(void *priv), int axis) { - if (!JOYSTICK_PRESENT(0)) - return AXIS_NOT_PRESENT; + if (!JOYSTICK_PRESENT(0)) + return AXIS_NOT_PRESENT; - switch (axis) - { - case 0: - return joystick_state[0].axis[0]; - case 1: - return joystick_state[0].axis[1]; - case 2: - return joystick_state[0].button[4] ? -32767 : 32768; - case 3: - return joystick_state[0].button[5] ? -32767 : 32768; - default: - return 0; - } -} -static int joystick_standard_read_axis_8button(void *p, int axis) -{ - if (!JOYSTICK_PRESENT(0)) - return AXIS_NOT_PRESENT; - - switch (axis) - { - case 0: - return joystick_state[0].axis[0]; - case 1: - return joystick_state[0].axis[1]; - case 2: - if (joystick_state[0].button[4]) - return -32767; - if (joystick_state[0].button[6]) - return 32768; - return 0; - case 3: - if (joystick_state[0].button[5]) - return -32767; - if (joystick_state[0].button[7]) - return 32768; - return 0; - default: - return 0; - } + switch (axis) { + case 0: + return joystick_state[0].axis[0]; + case 1: + return joystick_state[0].axis[1]; + case 2: + return joystick_state[0].axis[2]; + case 3: + return 0; + default: + return 0; + } } -static void joystick_standard_a0_over(void *p) +static int +joystick_standard_read_axis_4axis(UNUSED(void *priv), int axis) { + if (!JOYSTICK_PRESENT(0)) + return AXIS_NOT_PRESENT; + + switch (axis) { + case 0: + return joystick_state[0].axis[0]; + case 1: + return joystick_state[0].axis[1]; + case 2: + return joystick_state[0].axis[2]; + case 3: + return joystick_state[0].axis[3]; + default: + return 0; + } } -const joystick_if_t joystick_2axis_2button = +static int +joystick_standard_read_axis_6button(UNUSED(void *priv), int axis) { - "2-axis, 2-button joystick(s)", - "2axis_2button", - joystick_standard_init, - joystick_standard_close, - joystick_standard_read, - joystick_standard_write, - joystick_standard_read_axis, - joystick_standard_a0_over, - 2, - 2, - 0, - 2, - {"X axis", "Y axis"}, - {"Button 1", "Button 2"} -}; -const joystick_if_t joystick_2axis_4button = + if (!JOYSTICK_PRESENT(0)) + return AXIS_NOT_PRESENT; + + switch (axis) { + case 0: + return joystick_state[0].axis[0]; + case 1: + return joystick_state[0].axis[1]; + case 2: + return joystick_state[0].button[4] ? -32767 : 32768; + case 3: + return joystick_state[0].button[5] ? -32767 : 32768; + default: + return 0; + } +} +static int +joystick_standard_read_axis_8button(UNUSED(void *priv), int axis) { - "2-axis, 4-button joystick", - "2axis_4button", - joystick_standard_init, - joystick_standard_close, - joystick_standard_read_4button, - joystick_standard_write, - joystick_standard_read_axis_4button, - joystick_standard_a0_over, - 2, - 4, - 0, - 1, - {"X axis", "Y axis"}, - {"Button 1", "Button 2", "Button 3", "Button 4"} -}; -const joystick_if_t joystick_3axis_2button = + if (!JOYSTICK_PRESENT(0)) + return AXIS_NOT_PRESENT; + + switch (axis) { + case 0: + return joystick_state[0].axis[0]; + case 1: + return joystick_state[0].axis[1]; + case 2: + if (joystick_state[0].button[4]) + return -32767; + if (joystick_state[0].button[6]) + return 32768; + return 0; + case 3: + if (joystick_state[0].button[5]) + return -32767; + if (joystick_state[0].button[7]) + return 32768; + return 0; + default: + return 0; + } +} + +static void +joystick_standard_a0_over(UNUSED(void *priv)) { - "3-axis, 2-button joystick", - "3axis_2button", - joystick_standard_init, - joystick_standard_close, - joystick_standard_read, - joystick_standard_write, - joystick_standard_read_axis_3axis, - joystick_standard_a0_over, - 3, - 2, - 0, - 1, - {"X axis", "Y axis", "Z axis"}, - {"Button 1", "Button 2"} + // +} + +const joystick_if_t joystick_2axis_2button = { + .name = "2-axis, 2-button joystick(s)", + .internal_name = "2axis_2button", + .init = joystick_standard_init, + .close = joystick_standard_close, + .read = joystick_standard_read, + .write = joystick_standard_write, + .read_axis = joystick_standard_read_axis, + .a0_over = joystick_standard_a0_over, + .axis_count = 2, + .button_count = 2, + .pov_count = 0, + .max_joysticks = 2, + .axis_names = { "X axis", "Y axis" }, + .button_names = { "Button 1", "Button 2" }, + .pov_names = { NULL } }; -const joystick_if_t joystick_3axis_4button = -{ - "3-axis, 4-button joystick", - "3axis_4button", - joystick_standard_init, - joystick_standard_close, - joystick_standard_read_4button, - joystick_standard_write, - joystick_standard_read_axis_3axis, - joystick_standard_a0_over, - 3, - 4, - 0, - 1, - {"X axis", "Y axis", "Z axis"}, - {"Button 1", "Button 2", "Button 3", "Button 4"} + +const joystick_if_t joystick_2axis_4button = { + .name = "2-axis, 4-button joystick", + .internal_name = "2axis_4button", + .init = joystick_standard_init, + .close = joystick_standard_close, + .read = joystick_standard_read_4button, + .write = joystick_standard_write, + .read_axis = joystick_standard_read_axis_4button, + .a0_over = joystick_standard_a0_over, + .axis_count = 2, + .button_count = 4, + .pov_count = 0, + .max_joysticks = 1, + .axis_names = { "X axis", "Y axis" }, + .button_names = { "Button 1", "Button 2", "Button 3", "Button 4" }, + .pov_names = { NULL } }; -const joystick_if_t joystick_4axis_4button = -{ - "4-axis, 4-button joystick", - "4axis_4button", - joystick_standard_init, - joystick_standard_close, - joystick_standard_read_4button, - joystick_standard_write, - joystick_standard_read_axis_4axis, - joystick_standard_a0_over, - 4, - 4, - 0, - 1, - {"X axis", "Y axis", "Z axis", "zX axis"}, - {"Button 1", "Button 2", "Button 3", "Button 4"} + +const joystick_if_t joystick_3axis_2button = { + .name = "3-axis, 2-button joystick", + .internal_name = "3axis_2button", + .init = joystick_standard_init, + .close = joystick_standard_close, + .read = joystick_standard_read, + .write = joystick_standard_write, + .read_axis = joystick_standard_read_axis_3axis, + .a0_over = joystick_standard_a0_over, + .axis_count = 3, + .button_count = 2, + .pov_count = 0, + .max_joysticks = 1, + .axis_names = { "X axis", "Y axis", "Z axis" }, + .button_names = { "Button 1", "Button 2" }, + .pov_names = { NULL } }; -const joystick_if_t joystick_2axis_6button = -{ - "2-axis, 6-button joystick", - "2axis_6button", - joystick_standard_init, - joystick_standard_close, - joystick_standard_read_4button, - joystick_standard_write, - joystick_standard_read_axis_6button, - joystick_standard_a0_over, - 2, - 6, - 0, - 1, - {"X axis", "Y axis"}, - {"Button 1", "Button 2", "Button 3", "Button 4", "Button 5", "Button 6"} + +const joystick_if_t joystick_3axis_4button = { + .name = "3-axis, 4-button joystick", + .internal_name = "3axis_4button", + .init = joystick_standard_init, + .close = joystick_standard_close, + .read = joystick_standard_read_4button, + .write = joystick_standard_write, + .read_axis = joystick_standard_read_axis_3axis, + .a0_over = joystick_standard_a0_over, + .axis_count = 3, + .button_count = 4, + .pov_count = 0, + .max_joysticks = 1, + .axis_names = { "X axis", "Y axis", "Z axis" }, + .button_names = { "Button 1", "Button 2", "Button 3", "Button 4" }, + .pov_names = { NULL } }; -const joystick_if_t joystick_2axis_8button = -{ - "2-axis, 8-button joystick", - "2axis_8button", - joystick_standard_init, - joystick_standard_close, - joystick_standard_read_4button, - joystick_standard_write, - joystick_standard_read_axis_8button, - joystick_standard_a0_over, - 2, - 8, - 0, - 1, - {"X axis", "Y axis"}, - {"Button 1", "Button 2", "Button 3", "Button 4", "Button 5", "Button 6", "Button 7", "Button 8"} + +const joystick_if_t joystick_4axis_4button = { + .name = "4-axis, 4-button joystick", + .internal_name = "4axis_4button", + .init = joystick_standard_init, + .close = joystick_standard_close, + .read = joystick_standard_read_4button, + .write = joystick_standard_write, + .read_axis = joystick_standard_read_axis_4axis, + .a0_over = joystick_standard_a0_over, + .axis_count = 4, + .button_count = 4, + .pov_count = 0, + .max_joysticks = 1, + .axis_names = { "X axis", "Y axis", "Z axis", "zX axis" }, + .button_names = { "Button 1", "Button 2", "Button 3", "Button 4" }, + .pov_names = { NULL } +}; + +const joystick_if_t joystick_2axis_6button = { + .name = "2-axis, 6-button joystick", + .internal_name = "2axis_6button", + .init = joystick_standard_init, + .close = joystick_standard_close, + .read = joystick_standard_read_4button, + .write = joystick_standard_write, + .read_axis = joystick_standard_read_axis_6button, + .a0_over = joystick_standard_a0_over, + .axis_count = 2, + .button_count = 6, + .pov_count = 0, + .max_joysticks = 1, + .axis_names = { "X axis", "Y axis" }, + .button_names = { "Button 1", "Button 2", "Button 3", "Button 4", "Button 5", "Button 6" }, + .pov_names = { NULL } +}; + +const joystick_if_t joystick_2axis_8button = { + .name = "2-axis, 8-button joystick", + .internal_name = "2axis_8button", + .init = joystick_standard_init, + .close = joystick_standard_close, + .read = joystick_standard_read_4button, + .write = joystick_standard_write, + .read_axis = joystick_standard_read_axis_8button, + .a0_over = joystick_standard_a0_over, + .axis_count = 2, + .button_count = 8, + .pov_count = 0, + .max_joysticks = 1, + .axis_names = { "X axis", "Y axis" }, + .button_names = { "Button 1", "Button 2", "Button 3", "Button 4", "Button 5", "Button 6", "Button 7", "Button 8" }, + .pov_names = { NULL } }; diff --git a/src/game/joystick_sw_pad.c b/src/game/joystick_sw_pad.c index 31e0c8624..5c91ee1e9 100644 --- a/src/game/joystick_sw_pad.c +++ b/src/game/joystick_sw_pad.c @@ -1,41 +1,41 @@ /* - * VARCem Virtual ARchaeological Computer EMulator. - * An emulator of (mostly) x86-based PC systems and devices, - * using the ISA,EISA,VLB,MCA and PCI system buses, roughly - * spanning the era between 1981 and 1995. + * 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 VARCem Project. + * This file is part of the 86Box distribution. * - * Implementation of a Side Winder GamePad. + * Implementation of a Side Winder GamePad. * - * Notes: - Write to 0x201 starts packet transfer (5*N or 15*N bits) - * - Currently alternates between Mode A and Mode B (is there - * any way of actually controlling which is used?) - * - Windows 9x drivers require Mode B when more than 1 pad - * connected - * - Packet preceeded by high data (currently 50us), and - * followed by low data (currently 160us) - timings are - * probably wrong, but good enough for everything I've tried - * - Analog inputs are only used to time ID packet request. - * If A0 timing out is followed after ~64us by another 0x201 - * write then an ID packet is triggered - * - Sidewinder game pad ID is 'H0003' - * - ID is sent in Mode A (1 bit per clock), but data bit 2 - * must change during ID packet transfer, or Windows 9x - * drivers won't use Mode B. I don't know if it oscillates, - * mirrors the data transfer, or something else - the drivers - * only check that it changes at least 10 times during the - * transfer - * - Some DOS stuff will write to 0x201 while a packet is - * being transferred. This seems to be ignored. + * Notes: - Write to 0x201 starts packet transfer (5*N or 15*N bits) + * - Currently alternates between Mode A and Mode B (is there + * any way of actually controlling which is used?) + * - Windows 9x drivers require Mode B when more than 1 pad + * connected + * - Packet preceeded by high data (currently 50us), and + * followed by low data (currently 160us) - timings are + * probably wrong, but good enough for everything I've tried + * - Analog inputs are only used to time ID packet request. + * If A0 timing out is followed after ~64us by another 0x201 + * write then an ID packet is triggered + * - Sidewinder game pad ID is 'H0003' + * - ID is sent in Mode A (1 bit per clock), but data bit 2 + * must change during ID packet transfer, or Windows 9x + * drivers won't use Mode B. I don't know if it oscillates, + * mirrors the data transfer, or something else - the drivers + * only check that it changes at least 10 times during the + * transfer + * - Some DOS stuff will write to 0x201 while a packet is + * being transferred. This seems to be ignored. * * * - * Authors: Miran Grca, - * Sarah Walker, + * Authors: Miran Grca, + * Sarah Walker, * - * Copyright 2016-2018 Miran Grca. - * Copyright 2008-2018 Sarah Walker. + * Copyright 2016-2018 Miran Grca. + * Copyright 2008-2018 Sarah Walker. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -65,217 +65,205 @@ #include <86box/timer.h> #include <86box/gameport.h> #include <86box/joystick_sw_pad.h> +#include <86box/plat_unused.h> +typedef struct sw_data { + pc_timer_t poll_timer; + int poll_left; + int poll_clock; + uint64_t poll_data; + int poll_mode; -typedef struct -{ - pc_timer_t poll_timer; - int poll_left; - int poll_clock; - uint64_t poll_data; - int poll_mode; - - pc_timer_t trigger_timer; - int data_mode; + pc_timer_t trigger_timer; + int data_mode; } sw_data; -static void sw_timer_over(void *p) +static void +sw_timer_over(void *priv) { - sw_data *sw = (sw_data *)p; - - sw->poll_clock = !sw->poll_clock; + sw_data *sw = (sw_data *) priv; - if (sw->poll_clock) - { - sw->poll_data >>= (sw->poll_mode ? 3 : 1); - sw->poll_left--; - } + sw->poll_clock = !sw->poll_clock; - if (sw->poll_left == 1 && !sw->poll_clock) - timer_advance_u64(&sw->poll_timer, TIMER_USEC * 160); - else if (sw->poll_left) - timer_advance_u64(&sw->poll_timer, TIMER_USEC * 5); - else - timer_disable(&sw->poll_timer); + if (sw->poll_clock) { + sw->poll_data >>= (sw->poll_mode ? 3 : 1); + sw->poll_left--; + } + + if (sw->poll_left == 1 && !sw->poll_clock) + timer_advance_u64(&sw->poll_timer, TIMER_USEC * 160); + else if (sw->poll_left) + timer_advance_u64(&sw->poll_timer, TIMER_USEC * 5); + else + timer_disable(&sw->poll_timer); } -static void sw_trigger_timer_over(void *p) +static void +sw_trigger_timer_over(void *priv) { - sw_data *sw = (sw_data *)p; + sw_data *sw = (sw_data *) priv; - timer_disable(&sw->trigger_timer); + timer_disable(&sw->trigger_timer); } -static int sw_parity(uint16_t data) +static int +sw_parity(uint16_t data) { - int bits_set = 0; - - while (data) - { - bits_set++; - data &= (data - 1); + int bits_set = 0; + + while (data) { + bits_set++; + data &= (data - 1); + } + + return bits_set & 1; +} + +static void * +sw_init(void) +{ + sw_data *sw = (sw_data *) malloc(sizeof(sw_data)); + memset(sw, 0, sizeof(sw_data)); + + timer_add(&sw->poll_timer, sw_timer_over, sw, 0); + timer_add(&sw->trigger_timer, sw_trigger_timer_over, sw, 0); + + return sw; +} + +static void +sw_close(void *priv) +{ + sw_data *sw = (sw_data *) priv; + + free(sw); +} + +static uint8_t +sw_read(void *priv) +{ + sw_data *sw = (sw_data *) priv; + uint8_t temp = 0; + + if (!JOYSTICK_PRESENT(0)) + return 0xff; + + if (timer_is_enabled(&sw->poll_timer)) { + if (sw->poll_clock) + temp |= 0x10; + + if (sw->poll_mode) + temp |= (sw->poll_data & 7) << 5; + else { + temp |= ((sw->poll_data & 1) << 5) | 0xc0; + if (sw->poll_left > 31 && !(sw->poll_left & 1)) + temp &= ~0x80; } - - return bits_set & 1; + } else + temp |= 0xf0; + + return temp; } -static void *sw_init(void) +static void +sw_write(void *priv) { - sw_data *sw = (sw_data *)malloc(sizeof(sw_data)); - memset(sw, 0, sizeof(sw_data)); + sw_data *sw = (sw_data *) priv; + int64_t time_since_last = timer_get_remaining_us(&sw->trigger_timer); - timer_add(&sw->poll_timer, sw_timer_over, sw, 0); - timer_add(&sw->trigger_timer, sw_trigger_timer_over, sw, 0); + if (!JOYSTICK_PRESENT(0)) + return; - return sw; -} + timer_process(); -static void sw_close(void *p) -{ - sw_data *sw = (sw_data *)p; - - free(sw); -} + if (!sw->poll_left) { + sw->poll_clock = 1; + timer_set_delay_u64(&sw->poll_timer, TIMER_USEC * 50); -static uint8_t sw_read(void *p) -{ - sw_data *sw = (sw_data *)p; - uint8_t temp = 0; + if (time_since_last > 9900 && time_since_last < 9940) { + sw->poll_mode = 0; + sw->poll_left = 49; + sw->poll_data = 0x2400ULL | (0x1830ULL << 15) | (0x19b0ULL << 30); + } else { + sw->poll_mode = sw->data_mode; + sw->data_mode = !sw->data_mode; - if (!JOYSTICK_PRESENT(0)) - return 0xff; + if (sw->poll_mode) { + sw->poll_left = 1; + sw->poll_data = 7; + } else { + sw->poll_left = 1; + sw->poll_data = 1; + } - if (timer_is_enabled(&sw->poll_timer)) - { - if (sw->poll_clock) - temp |= 0x10; - - if (sw->poll_mode) - temp |= (sw->poll_data & 7) << 5; - else - { - temp |= ((sw->poll_data & 1) << 5) | 0xc0; - if (sw->poll_left > 31 && !(sw->poll_left & 1)) - temp &= ~0x80; + for (uint8_t c = 0; c < 4; c++) { + uint16_t data = 0x3fff; + + if (!JOYSTICK_PRESENT(c)) + break; + + if (joystick_state[c].axis[1] < -16383) + data &= ~1; + if (joystick_state[c].axis[1] > 16383) + data &= ~2; + if (joystick_state[c].axis[0] > 16383) + data &= ~4; + if (joystick_state[c].axis[0] < -16383) + data &= ~8; + + for (uint8_t b = 0; b < 10; b++) { + if (joystick_state[c].button[b]) + data &= ~(1 << (b + 4)); } + + if (sw_parity(data)) + data |= 0x4000; + + if (sw->poll_mode) { + sw->poll_left += 5; + sw->poll_data |= (data << (c * 15 + 3)); + } else { + sw->poll_left += 15; + sw->poll_data |= (data << (c * 15 + 1)); + } + } } - else - temp |= 0xf0; + } - return temp; + timer_disable(&sw->trigger_timer); } -static void sw_write(void *p) +static int +sw_read_axis(UNUSED(void *priv), UNUSED(int axis)) { - sw_data *sw = (sw_data *)p; - int64_t time_since_last = timer_get_remaining_us(&sw->trigger_timer); + if (!JOYSTICK_PRESENT(0)) + return AXIS_NOT_PRESENT; - if (!JOYSTICK_PRESENT(0)) - return; - - timer_process(); - - if (!sw->poll_left) - { - sw->poll_clock = 1; - timer_set_delay_u64(&sw->poll_timer, TIMER_USEC * 50); - - if (time_since_last > 9900 && time_since_last < 9940) - { - sw->poll_mode = 0; - sw->poll_left = 49; - sw->poll_data = 0x2400ull | (0x1830ull << 15) | (0x19b0ull << 30); - } - else - { - int c; - - sw->poll_mode = sw->data_mode; - sw->data_mode = !sw->data_mode; - - if (sw->poll_mode) - { - sw->poll_left = 1; - sw->poll_data = 7; - } - else - { - sw->poll_left = 1; - sw->poll_data = 1; - } - - for (c = 0; c < 4; c++) - { - uint16_t data = 0x3fff; - int b; - - if (!JOYSTICK_PRESENT(c)) - break; - - if (joystick_state[c].axis[1] < -16383) - data &= ~1; - if (joystick_state[c].axis[1] > 16383) - data &= ~2; - if (joystick_state[c].axis[0] > 16383) - data &= ~4; - if (joystick_state[c].axis[0] < -16383) - data &= ~8; - - for (b = 0; b < 10; b++) - { - if (joystick_state[c].button[b]) - data &= ~(1 << (b + 4)); - } - - if (sw_parity(data)) - data |= 0x4000; - - if (sw->poll_mode) - { - sw->poll_left += 5; - sw->poll_data |= (data << (c*15 + 3)); - } - else - { - sw->poll_left += 15; - sw->poll_data |= (data << (c*15 + 1)); - } - } - } - } - - timer_disable(&sw->trigger_timer); + return 0; /*No analogue support on Sidewinder game pad*/ } -static int sw_read_axis(void *p, int axis) +static void +sw_a0_over(void *priv) { - if (!JOYSTICK_PRESENT(0)) - return AXIS_NOT_PRESENT; - - return 0; /*No analogue support on Sidewinder game pad*/ + sw_data *sw = (sw_data *) priv; + + timer_set_delay_u64(&sw->trigger_timer, TIMER_USEC * 10000); } -static void sw_a0_over(void *p) -{ - sw_data *sw = (sw_data *)p; - - timer_set_delay_u64(&sw->trigger_timer, TIMER_USEC * 10000); -} - -const joystick_if_t joystick_sw_pad = -{ - "Microsoft SideWinder Pad", - "sidewinder_pad", - sw_init, - sw_close, - sw_read, - sw_write, - sw_read_axis, - sw_a0_over, - 2, - 10, - 0, - 4, - {"X axis", "Y axis"}, - {"A", "B", "C", "X", "Y", "Z", "L", "R", "Start", "M"} +const joystick_if_t joystick_sw_pad = { + .name = "Microsoft SideWinder Pad", + .internal_name = "sidewinder_pad", + .init = sw_init, + .close = sw_close, + .read = sw_read, + .write = sw_write, + .read_axis = sw_read_axis, + .a0_over = sw_a0_over, + .axis_count = 2, + .button_count = 10, + .pov_count = 0, + .max_joysticks = 4, + .axis_names = { "X axis", "Y axis" }, + .button_names = { "A", "B", "C", "X", "Y", "Z", "L", "R", "Start", "M" }, + .pov_names = { NULL } }; diff --git a/src/game/joystick_tm_fcs.c b/src/game/joystick_tm_fcs.c index 2c6a7d90f..d54d0e37d 100644 --- a/src/game/joystick_tm_fcs.c +++ b/src/game/joystick_tm_fcs.c @@ -1,20 +1,20 @@ /* - * VARCem Virtual ARchaeological Computer EMulator. - * An emulator of (mostly) x86-based PC systems and devices, - * using the ISA,EISA,VLB,MCA and PCI system buses, roughly - * spanning the era between 1981 and 1995. + * 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 VARCem Project. + * This file is part of the 86Box distribution. * - * Implementation of Thrust Master Flight Control System. + * Implementation of Thrust Master Flight Control System. * * * - * Authors: Miran Grca, - * Sarah Walker, + * Authors: Miran Grca, + * Sarah Walker, * - * Copyright 2016-2018 Miran Grca. - * Copyright 2008-2018 Sarah Walker. + * Copyright 2016-2018 Miran Grca. + * Copyright 2008-2018 Sarah Walker. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -44,89 +44,95 @@ #include <86box/timer.h> #include <86box/gameport.h> #include <86box/joystick_standard.h> +#include <86box/plat_unused.h> - -static void *tm_fcs_init(void) +static void * +tm_fcs_init(void) { - return NULL; + return NULL; } -static void tm_fcs_close(void *p) +static void +tm_fcs_close(UNUSED(void *priv)) { + // } -static uint8_t tm_fcs_read(void *p) +static uint8_t +tm_fcs_read(UNUSED(void *priv)) { - uint8_t ret = 0xf0; - - if (JOYSTICK_PRESENT(0)) - { - if (joystick_state[0].button[0]) - ret &= ~0x10; - if (joystick_state[0].button[1]) - ret &= ~0x20; - if (joystick_state[0].button[2]) - ret &= ~0x40; - if (joystick_state[0].button[3]) - ret &= ~0x80; - } + uint8_t ret = 0xf0; - return ret; + if (JOYSTICK_PRESENT(0)) { + if (joystick_state[0].button[0]) + ret &= ~0x10; + if (joystick_state[0].button[1]) + ret &= ~0x20; + if (joystick_state[0].button[2]) + ret &= ~0x40; + if (joystick_state[0].button[3]) + ret &= ~0x80; + } + + return ret; } -static void tm_fcs_write(void *p) +static void +tm_fcs_write(UNUSED(void *priv)) { + // } -static int tm_fcs_read_axis(void *p, int axis) +static int +tm_fcs_read_axis(UNUSED(void *priv), int axis) { - if (!JOYSTICK_PRESENT(0)) - return AXIS_NOT_PRESENT; + if (!JOYSTICK_PRESENT(0)) + return AXIS_NOT_PRESENT; - switch (axis) - { - case 0: - return joystick_state[0].axis[0]; - case 1: - return joystick_state[0].axis[1]; - case 2: + switch (axis) { + case 0: + return joystick_state[0].axis[0]; + case 1: + return joystick_state[0].axis[1]; + case 2: + return 0; + case 3: + if (joystick_state[0].pov[0] == -1) + return 32767; + if (joystick_state[0].pov[0] > 315 || joystick_state[0].pov[0] < 45) + return -32768; + if (joystick_state[0].pov[0] >= 45 && joystick_state[0].pov[0] < 135) + return -16384; + if (joystick_state[0].pov[0] >= 135 && joystick_state[0].pov[0] < 225) return 0; - case 3: - if (joystick_state[0].pov[0] == -1) - return 32767; - if (joystick_state[0].pov[0] > 315 || joystick_state[0].pov[0] < 45) - return -32768; - if (joystick_state[0].pov[0] >= 45 && joystick_state[0].pov[0] < 135) - return -16384; - if (joystick_state[0].pov[0] >= 135 && joystick_state[0].pov[0] < 225) - return 0; - if (joystick_state[0].pov[0] >= 225 && joystick_state[0].pov[0] < 315) - return 16384; - return 0; - default: - return 0; - } + if (joystick_state[0].pov[0] >= 225 && joystick_state[0].pov[0] < 315) + return 16384; + return 0; + default: + return 0; + } } -static void tm_fcs_a0_over(void *p) +static void +tm_fcs_a0_over(UNUSED(void *priv)) { + // } -const joystick_if_t joystick_tm_fcs = -{ - "Thrustmaster Flight Control System", - "thrustmaster_fcs", - tm_fcs_init, - tm_fcs_close, - tm_fcs_read, - tm_fcs_write, - tm_fcs_read_axis, - tm_fcs_a0_over, - 2, - 4, - 1, - 1, - {"X axis", "Y axis"}, - {"Button 1", "Button 2", "Button 3", "Button 4"}, - {"POV"} +const joystick_if_t joystick_tm_fcs = { + .name = "Thrustmaster Flight Control System", + .internal_name = "thrustmaster_fcs", + .init = tm_fcs_init, + .close = tm_fcs_close, + .read = tm_fcs_read, + .write = tm_fcs_write, + .read_axis = tm_fcs_read_axis, + .a0_over = tm_fcs_a0_over, + .axis_count = 2, + .button_count = 4, + .pov_count = 1, + .max_joysticks = 1, + .axis_names = { "X axis", "Y axis" }, + .button_names = { "Button 1", "Button 2", "Button 3", "Button 4" }, + .pov_names = { "POV" } }; diff --git a/src/gdbstub.c b/src/gdbstub.c new file mode 100644 index 000000000..703637422 --- /dev/null +++ b/src/gdbstub.c @@ -0,0 +1,1851 @@ +/* + * 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. + * + * GDB stub server for remote debugging. + * + * + * + * Authors: RichardG, + * + * Copyright 2022 RichardG. + */ +#include +#include +#include +#include +#include +#include +#ifdef _WIN32 +# ifndef __clang__ +# include +# else +# include +# define ssize_t long +# define strtok_r(a, b, c) strtok_s(a, b, c) +# endif +# include +# include +#else +# include +# include +# include +# include +#endif +#define HAVE_STDARG_H +#include <86box/86box.h> +#include "cpu.h" +#include "x86seg.h" +#include "x87.h" +#include "x87_ops_conv.h" +#include <86box/io.h> +#include <86box/mem.h> +#include <86box/plat.h> +#include <86box/thread.h> +#include <86box/gdbstub.h> + +#define FAST_RESPONSE(s) \ + strcpy(client->response, s); \ + client->response_pos = sizeof(s) - 1; +#define FAST_RESPONSE_HEX(s) gdbstub_client_respond_hex(client, (uint8_t *) s, sizeof(s)); + +enum { + GDB_SIGINT = 2, + GDB_SIGTRAP = 5 +}; + +enum { + GDB_REG_EAX = 0, + GDB_REG_ECX, + GDB_REG_EDX, + GDB_REG_EBX, + GDB_REG_ESP, + GDB_REG_EBP, + GDB_REG_ESI, + GDB_REG_EDI, + GDB_REG_EIP, + GDB_REG_EFLAGS, + GDB_REG_CS, + GDB_REG_SS, + GDB_REG_DS, + GDB_REG_ES, + GDB_REG_FS, + GDB_REG_GS, +#if 0 + GDB_REG_FS_BASE, + GDB_REG_GS_BASE, +#endif + GDB_REG_CR0, + GDB_REG_CR2, + GDB_REG_CR3, + GDB_REG_CR4, + GDB_REG_EFER, + GDB_REG_ST0, + GDB_REG_ST1, + GDB_REG_ST2, + GDB_REG_ST3, + GDB_REG_ST4, + GDB_REG_ST5, + GDB_REG_ST6, + GDB_REG_ST7, + GDB_REG_FCTRL, + GDB_REG_FSTAT, + GDB_REG_FTAG, + GDB_REG_FISEG, + GDB_REG_FIOFF, + GDB_REG_FOSEG, + GDB_REG_FOOFF, + GDB_REG_FOP, + GDB_REG_MM0, + GDB_REG_MM1, + GDB_REG_MM2, + GDB_REG_MM3, + GDB_REG_MM4, + GDB_REG_MM5, + GDB_REG_MM6, + GDB_REG_MM7, + GDB_REG_MAX +}; + +enum { + GDB_MODE_BASE10 = 0, + GDB_MODE_HEX, + GDB_MODE_OCT, + GDB_MODE_BIN +}; + +typedef struct _gdbstub_client_ { + int socket; + struct sockaddr_in addr; + + char packet[16384], response[16384]; + uint8_t has_packet : 1; + uint8_t first_packet_received : 1; + uint8_t ida_mode : 1; + uint8_t waiting_stop : 1; + int packet_pos; + int response_pos; + + event_t *processed_event; + event_t *response_event; + + uint16_t last_io_base; + uint16_t last_io_len; + uint16_t last_io_value; + + struct _gdbstub_client_ *next; +} gdbstub_client_t; + +typedef struct _gdbstub_breakpoint_ { + uint32_t addr; + union { + uint8_t orig_val; + uint32_t end; + }; + + struct _gdbstub_breakpoint_ *next; +} gdbstub_breakpoint_t; + +#ifdef ENABLE_GDBSTUB_LOG +int gdbstub_do_log = ENABLE_GDBSTUB_LOG; + +static void +gdbstub_log(const char *fmt, ...) +{ + va_list ap; + + if (gdbstub_do_log) { + va_start(ap, fmt); + pclog_ex(fmt, ap); + va_end(ap); + } +} +#else +# define gdbstub_log(fmt, ...) +#endif + +static x86seg *segment_regs[] = { &cpu_state.seg_cs, &cpu_state.seg_ss, &cpu_state.seg_ds, &cpu_state.seg_es, &cpu_state.seg_fs, &cpu_state.seg_gs }; +static uint32_t *cr_regs[] = { &cpu_state.CR0.l, &cr2, &cr3, &cr4 }; +static void *fpu_regs[] = { &cpu_state.npxc, &cpu_state.npxs, NULL, &x87_pc_seg, &x87_pc_off, &x87_op_seg, &x87_op_off }; +static char target_xml[] = /* QEMU gdb-xml/i386-32bit.xml with modifications (described in comments) */ + // clang-format off + "" + "" + "" + "" /* patched in here (length must be kept) */ + "" + "" + "" + "" + "" + "" + "" + "" + "" + "" + "" + "" + "" + "" + "" + "" + "" + "" + "" + "" + "" + "" + "" + "" + "" + "" + "" + "" + "" + "" + "" + "" + "" + "" + "" + "" + "" + "" + "" + "" + "" + "" + "" + "" + "" +#if 0 + "" + "" +#endif + "" + "" + "" + "" + "" + "" + "" + "" + "" + "" + "" + "" + "" + "" + "" + "" + "" + "" + "" + "" + "" + "" + "" + "" + "" + "" + "" + "" + "" + "" + "" + "" + "" + "" + "" + "" + "" + "" + "" + "" + "" + "" + "" + "" + "" + "" + "" + "" + "" + "" + "" + "" + "" + "" + "" + "" + "" + "" + "" + "" + "" + "" + "" + "" + "" + "" + "" + "" + "" + "" + "" + "" + "" + "" + "" + "" + "" + "" + "" + "" + "" + "" + "" + "" + "" + "" + "" + "" + "" + "" + "" + "" + "" + "" + "" + "" + "" + "" + "" + "" + "" + ""; +// clang-format on + +#ifdef _WIN32 +static WSADATA wsa; +#endif +static int gdbstub_socket = -1; +static int stop_reason_len = 0; +static int in_gdbstub = 0; +static uint32_t watch_addr; +static char stop_reason[2048]; + +static gdbstub_client_t *first_client = NULL; +static gdbstub_client_t *last_client = NULL; +static mutex_t *client_list_mutex; + +static void (*cpu_exec_shadow)(int32_t cycs); +static gdbstub_breakpoint_t *first_swbreak = NULL; +static gdbstub_breakpoint_t *first_hwbreak = NULL; +static gdbstub_breakpoint_t *first_rwatch = NULL; +static gdbstub_breakpoint_t *first_wwatch = NULL; +static gdbstub_breakpoint_t *first_awatch = NULL; + +int gdbstub_step = 0; +int gdbstub_next_asap = 0; +uint64_t gdbstub_watch_pages[(((uint32_t) -1) >> (MEM_GRANULARITY_BITS + 6)) + 1]; + +static void +gdbstub_break(void) +{ + /* Pause CPU execution as soon as possible. */ + if (gdbstub_step <= GDBSTUB_EXEC) + gdbstub_step = GDBSTUB_BREAK; +} + +static void +gdbstub_jump(uint32_t new_pc) +{ + /* Nasty hack; qemu always uses the full 32-bit EIP internally... */ + if (cpu_state.op32 || ((new_pc >= cs) && (new_pc < (cs + 65536)))) { + cpu_state.pc = new_pc - cs; + } else { + loadseg((new_pc >> 4) & 0xf000, &cpu_state.seg_cs); + cpu_state.pc = new_pc & 0xffff; + } + flushmmucache(); +} + +static inline int +gdbstub_hex_decode(int c) +{ + if ((c >= '0') && (c <= '9')) + return c - '0'; + else if ((c >= 'A') && (c <= 'F')) + return c - 'A' + 10; + else if ((c >= 'a') && (c <= 'f')) + return c - 'a' + 10; + else + return 0; +} + +static inline int +gdbstub_hex_encode(int c) +{ + if (c < 10) + return c + '0'; + else + return c - 10 + 'a'; +} + +static int +gdbstub_num_decode(char *p, int *dest, int mode) +{ + /* Stop if the pointer is invalid. */ + if (!p) + return 0; + + /* Read sign. */ + int sign = 1; + if ((p[0] == '+') || (p[0] == '-')) { + if (p[0] == '-') + sign = -1; + p++; + } + + /* Read type identifer if present (0x/0o/0b/0n) */ + if (p[0] == '0') { + switch (p[1]) { + case 'x': + mode = GDB_MODE_HEX; + break; + + case '0' ... '7': + p -= 1; + /* fall-through */ + + case 'o': + mode = GDB_MODE_OCT; + break; + + case 'b': + mode = GDB_MODE_BIN; + break; + + case 'n': + mode = GDB_MODE_BASE10; + break; + + default: + p -= 2; + break; + } + p += 2; + } + + /* Parse each character. */ + *dest = 0; + while (*p) { + switch (mode) { + case GDB_MODE_BASE10: + if ((*p >= '0') && (*p <= '9')) + *dest = ((*dest) * 10) + ((*p) - '0'); + else + return 0; + break; + + case GDB_MODE_HEX: + if (((*p >= '0') && (*p <= '9')) || ((*p >= 'A') && (*p <= 'F')) || ((*p >= 'a') && (*p <= 'f'))) + *dest = ((*dest) << 4) | gdbstub_hex_decode(*p); + else + return 0; + break; + + case GDB_MODE_OCT: + if ((*p >= '0') && (*p <= '7')) + *dest = ((*dest) << 3) | ((*p) - '0'); + else + return 0; + break; + + case GDB_MODE_BIN: + if ((*p == '0') || (*p == '1')) + *dest = ((*dest) << 1) | ((*p) - '0'); + else + return 0; + break; + + default: + break; + } + p++; + } + + /* Apply sign. */ + if (sign < 0) + *dest = -(*dest); + + /* Return success. */ + return 1; +} + +static int +gdbstub_client_read_word(gdbstub_client_t *client, int *dest) +{ + const char *p = &client->packet[client->packet_pos]; + const char *q = p; + while (((*p >= '0') && (*p <= '9')) || ((*p >= 'A') && (*p <= 'F')) || ((*p >= 'a') && (*p <= 'f'))) + *dest = ((*dest) << 4) | gdbstub_hex_decode(*p++); + return p - q; +} + +static int +gdbstub_client_read_hex(gdbstub_client_t *client, uint8_t *buf, int size) +{ + int pp = client->packet_pos; + while (size-- && (pp < (sizeof(client->packet) - 2))) { + *buf = gdbstub_hex_decode(client->packet[pp++]) << 4; + *buf++ |= gdbstub_hex_decode(client->packet[pp++]); + } + return pp - client->packet_pos; +} + +static int +gdbstub_client_read_string(gdbstub_client_t *client, char *buf, int size, char terminator) +{ + int pp = client->packet_pos; + char c; + while (size-- && (pp < (sizeof(client->packet) - 1))) { + c = client->packet[pp]; + if ((c == terminator) || (c == '\0')) { + *buf = '\0'; + break; + } + pp++; + *buf++ = c; + } + return pp - client->packet_pos; +} + +static int +gdbstub_client_write_reg(int index, uint8_t *buf) +{ + int width = 4; + switch (index) { + case GDB_REG_EAX ... GDB_REG_EDI: + cpu_state.regs[index - GDB_REG_EAX].l = *((uint32_t *) buf); + break; + + case GDB_REG_EIP: + gdbstub_jump(*((uint32_t *) buf)); + break; + + case GDB_REG_EFLAGS: + cpu_state.flags = *((uint16_t *) &buf[0]); + cpu_state.eflags = *((uint16_t *) &buf[2]); + break; + + case GDB_REG_CS ... GDB_REG_GS: + width = 2; + loadseg(*((uint16_t *) buf), segment_regs[index - GDB_REG_CS]); + flushmmucache(); + break; + +#if 0 + case GDB_REG_FS_BASE ... GDB_REG_GS_BASE: + /* Do what qemu does and just load the base. */ + segment_regs[(index - 16) + (GDB_REG_FS - GDB_REG_CS)]->base = *((uint32_t *) buf); + break; +#endif + + case GDB_REG_CR0 ... GDB_REG_CR4: + *cr_regs[index - GDB_REG_CR0] = *((uint32_t *) buf); + flushmmucache(); + break; + + case GDB_REG_EFER: + msr.amd_efer = *((uint64_t *) buf); + break; + + case GDB_REG_ST0 ... GDB_REG_ST7: + width = 10; + x87_conv_t conv = { + .eind = { .ll = *((uint64_t *) &buf[0]) }, + .begin = *((uint16_t *) &buf[8]) + }; + cpu_state.ST[(cpu_state.TOP + (index - GDB_REG_ST0)) & 7] = x87_from80(&conv); + break; + + case GDB_REG_FCTRL: + case GDB_REG_FISEG: + case GDB_REG_FOSEG: + width = 2; + *((uint16_t *) fpu_regs[index - GDB_REG_FCTRL]) = *((uint16_t *) buf); + if (index >= GDB_REG_FISEG) + flushmmucache(); + break; + + case GDB_REG_FSTAT: + case GDB_REG_FOP: + width = 2; + break; + + case GDB_REG_FTAG: + width = 2; + x87_settag(*((uint16_t *) buf)); + break; + + case GDB_REG_FIOFF: + case GDB_REG_FOOFF: + *((uint32_t *) fpu_regs[index - GDB_REG_FCTRL]) = *((uint32_t *) buf); + break; + + case GDB_REG_MM0 ... GDB_REG_MM7: + width = 8; + cpu_state.MM[index - GDB_REG_MM0].q = *((uint64_t *) buf); + break; + + default: + width = 0; + } + +#ifdef ENABLE_GDBSTUB_LOG + char logbuf[256], *p = logbuf + sprintf(logbuf, "GDB Stub: Setting register %d to ", index); + for (int i = width - 1; i >= 0; i--) + p += sprintf(p, "%02X", buf[i]); + sprintf(p, "\n"); + gdbstub_log(logbuf); +#endif + + return width; +} + +static void +gdbstub_client_respond(gdbstub_client_t *client) +{ + /* Calculate checksum. */ + int checksum = 0; + int i; + for (i = 0; i < client->response_pos; i++) + checksum += client->response[i]; + + /* Send response packet. */ + client->response[client->response_pos] = '\0'; +#ifdef ENABLE_GDBSTUB_LOG + i = client->response[994]; /* pclog_ex buffer too small */ + client->response[994] = '\0'; + gdbstub_log("GDB Stub: Sending response: %s\n", client->response); + client->response[994] = i; +#endif + send(client->socket, "$", 1, 0); + send(client->socket, client->response, client->response_pos, 0); + char response_cksum[3] = { '#', gdbstub_hex_encode((checksum >> 4) & 0x0f), gdbstub_hex_encode(checksum & 0x0f) }; + send(client->socket, response_cksum, sizeof(response_cksum), 0); +} + +static void +gdbstub_client_respond_partial(gdbstub_client_t *client) +{ + /* Send response. */ + gdbstub_client_respond(client); + + /* Wait for the response to be acknowledged. */ + thread_wait_event(client->response_event, -1); + thread_reset_event(client->response_event); +} + +static void +gdbstub_client_respond_hex(gdbstub_client_t *client, uint8_t *buf, int size) +{ + while (size-- && (client->response_pos < (sizeof(client->response) - 2))) { + client->response[client->response_pos++] = gdbstub_hex_encode((*buf) >> 4); + client->response[client->response_pos++] = gdbstub_hex_encode((*buf++) & 0x0f); + } +} + +static int +gdbstub_client_read_reg(int index, uint8_t *buf) +{ + int width = 4; + switch (index) { + case GDB_REG_EAX ... GDB_REG_EDI: + *((uint32_t *) buf) = cpu_state.regs[index].l; + break; + + case GDB_REG_EIP: + *((uint32_t *) buf) = cs + cpu_state.pc; + break; + + case GDB_REG_EFLAGS: + *((uint16_t *) &buf[0]) = cpu_state.flags; + *((uint16_t *) &buf[2]) = cpu_state.eflags; + break; + + case GDB_REG_CS ... GDB_REG_GS: + *((uint16_t *) buf) = segment_regs[index - GDB_REG_CS]->seg; + break; + +#if 0 + case GDB_REG_FS_BASE ... GDB_REG_GS_BASE: + *((uint32_t *) buf) = segment_regs[(index - 16) + (GDB_REG_FS - GDB_REG_CS)]->base; + break; +#endif + + case GDB_REG_CR0 ... GDB_REG_CR4: + *((uint32_t *) buf) = *cr_regs[index - GDB_REG_CR0]; + break; + + case GDB_REG_EFER: + *((uint64_t *) buf) = msr.amd_efer; + break; + + case GDB_REG_ST0 ... GDB_REG_ST7: + width = 10; + x87_conv_t conv; + x87_to80(cpu_state.ST[(cpu_state.TOP + (index - GDB_REG_ST0)) & 7], &conv); + *((uint64_t *) &buf[0]) = conv.eind.ll; + *((uint16_t *) &buf[8]) = conv.begin; + break; + + case GDB_REG_FCTRL ... GDB_REG_FSTAT: + case GDB_REG_FISEG: + case GDB_REG_FOSEG: + width = 2; + *((uint16_t *) buf) = *((uint16_t *) fpu_regs[index - GDB_REG_FCTRL]); + break; + + case GDB_REG_FTAG: + width = 2; + *((uint16_t *) buf) = x87_gettag(); + break; + + case GDB_REG_FIOFF: + case GDB_REG_FOOFF: + *((uint32_t *) buf) = *((uint32_t *) fpu_regs[index - GDB_REG_FCTRL]); + break; + + case GDB_REG_FOP: + width = 2; + *((uint16_t *) buf) = 0; /* we don't store the FPU opcode */ + break; + + case GDB_REG_MM0 ... GDB_REG_MM7: + width = 8; + *((uint64_t *) buf) = cpu_state.MM[index - GDB_REG_MM0].q; + break; + + default: + width = 0; + } + + return width; +} + +static void +gdbstub_client_packet(gdbstub_client_t *client) +{ + gdbstub_breakpoint_t *breakpoint; + gdbstub_breakpoint_t *prev_breakpoint = NULL; + gdbstub_breakpoint_t **first_breakpoint = NULL; + +#ifdef GDBSTUB_CHECK_CHECKSUM /* msys2 gdb 11.1 transmits qSupported and H with invalid checksum... */ + uint8_t rcv_checksum = 0, checksum = 0; +#endif + int i; + int j = 0; + int k = 0; + int l; + uint8_t buf[10] = { 0 }; + char *p; + + /* Validate checksum. */ + client->packet_pos -= 2; +#ifdef GDBSTUB_CHECK_CHECKSUM + gdbstub_client_read_hex(client, &rcv_checksum, 1); +#endif + *((uint16_t *) &client->packet[--client->packet_pos]) = 0; +#ifdef GDBSTUB_CHECK_CHECKSUM + for (i = 0; i < client->packet_pos; i++) + checksum += client->packet[i]; + + if (checksum != rcv_checksum) { + /* Send negative acknowledgement. */ +# ifdef ENABLE_GDBSTUB_LOG + i = client->packet[953]; /* pclog_ex buffer too small */ + client->packet[953] = '\0'; + gdbstub_log("GDB Stub: Received packet with invalid checksum (expected %02X got %02X): %s\n", checksum, rcv_checksum, client->packet); + client->packet[953] = i; +# endif + send(client->socket, "-", 1, 0); + return; + } +#endif + + /* Send positive acknowledgement. */ +#ifdef ENABLE_GDBSTUB_LOG + i = client->packet[996]; /* pclog_ex buffer too small */ + client->packet[996] = '\0'; + gdbstub_log("GDB Stub: Received packet: %s\n", client->packet); + client->packet[996] = i; +#endif + send(client->socket, "+", 1, 0); + + /* Block other responses from being written while this one (if any is produced) isn't acknowledged. */ + if ((client->packet[0] != 'c') && (client->packet[0] != 's') && (client->packet[0] != 'v')) { + thread_wait_event(client->response_event, -1); + thread_reset_event(client->response_event); + } + client->response_pos = 0; + client->packet_pos = 1; + + /* Handle IDA-specific hacks. */ + if (!client->first_packet_received) { + client->first_packet_received = 1; + if (!strcmp(client->packet, "qSupported:xmlRegisters=i386,arm,mips")) { + gdbstub_log("GDB Stub: Enabling IDA mode\n"); + client->ida_mode = 1; + } + } + + /* Parse command. */ + switch (client->packet[0]) { + case '?': /* stop reason */ + /* Respond with a stop reply packet if one is present. */ + if (stop_reason_len) { + strcpy(client->response, stop_reason); + client->response_pos = strlen(client->response); + } + break; + + case 'c': /* continue */ + case 's': /* step */ + /* Flag that the client is waiting for a stop reason. */ + client->waiting_stop = 1; + + /* Jump to address if specified. */ + if (client->packet[1] && gdbstub_client_read_word(client, &j)) + gdbstub_jump(j); + + /* Resume CPU. */ + gdbstub_step = gdbstub_next_asap = (client->packet[0] == 's') ? GDBSTUB_SSTEP : GDBSTUB_EXEC; + return; + + case 'D': /* detach */ + /* Resume emulation. */ + gdbstub_step = GDBSTUB_EXEC; + + /* Respond positively. */ +ok: + FAST_RESPONSE("OK"); + break; + + case 'g': /* read all registers */ + /* Output the values of all registers. */ + for (i = 0; i < GDB_REG_MAX; i++) + gdbstub_client_respond_hex(client, buf, gdbstub_client_read_reg(i, buf)); + break; + + case 'G': /* write all registers */ + /* Write the values of all registers. */ + for (i = 0; i < GDB_REG_MAX; i++) { + if (i == GDB_REG_MAX) + goto e22; + if (!gdbstub_client_read_hex(client, buf, sizeof(buf))) + break; + client->packet_pos += gdbstub_client_write_reg(i, buf) << 1; + } + + /* Respond positively. */ + goto ok; + + case 'H': /* set thread */ + /* Read operation type and thread ID. */ + if ((client->packet[1] == '\0') || (client->packet[2] == '\0')) { +e22: + FAST_RESPONSE("E22"); + break; + } + + /* Respond positively only on thread 1. */ + if ((client->packet[2] == '1') && !client->packet[3]) + goto ok; + else + goto e22; + + case 'm': /* read memory */ + /* Read address and length. */ + if (!(i = gdbstub_client_read_word(client, &j))) + goto e22; + client->packet_pos += i + 1; + gdbstub_client_read_word(client, &k); + if (!k) + goto e22; + + /* Clamp length. */ + if (k >= (sizeof(client->response) >> 1)) + k = (sizeof(client->response) >> 1) - 1; + + /* Read by qwords, then by dwords, then by words, then by bytes. */ + i = 0; + if (is386) { + for (; i < (k & ~7); i += 8) { + *((uint64_t *) buf) = readmemql(j); + j += 8; + gdbstub_client_respond_hex(client, buf, 8); + } + for (; i < (k & ~3); i += 4) { + *((uint32_t *) buf) = readmemll(j); + j += 4; + gdbstub_client_respond_hex(client, buf, 4); + } + } + for (; i < (k & ~1); i += 2) { + *((uint16_t *) buf) = readmemwl(j); + j += 2; + gdbstub_client_respond_hex(client, buf, 2); + } + for (; i < k; i++) { + buf[0] = readmembl(j++); + gdbstub_client_respond_hex(client, buf, 1); + } + break; + + case 'M': /* write memory */ + case 'X': /* write memory binary */ + /* Read address and length. */ + if (!(i = gdbstub_client_read_word(client, &j))) + goto e22; + client->packet_pos += i + 1; + client->packet_pos += gdbstub_client_read_word(client, &k) + 1; + if (!k) + goto e22; + + /* Clamp length. */ + if (k >= ((sizeof(client->response) >> 1) - client->packet_pos)) + k = (sizeof(client->response) >> 1) - client->packet_pos - 1; + + /* Decode the data. */ + if (client->packet[0] == 'M') { /* hex encoded */ + gdbstub_client_read_hex(client, (uint8_t *) client->packet, k); + } else { /* binary encoded */ + i = 0; + while (i < k) { + if (client->packet[client->packet_pos] == '}') { + client->packet_pos++; + client->packet[i++] = client->packet[client->packet_pos++] ^ 0x20; + } else { + client->packet[i++] = client->packet[client->packet_pos++]; + } + } + } + + /* Write by qwords, then by dwords, then by words, then by bytes. */ + p = client->packet; + i = 0; + if (is386) { + for (; i < (k & ~7); i += 8) { + writememql(j, *((uint64_t *) p)); + j += 8; + p += 8; + } + for (; i < (k & ~3); i += 4) { + writememll(j, *((uint32_t *) p)); + j += 4; + p += 4; + } + } + for (; i < (k & ~1); i += 2) { + writememwl(j, *((uint16_t *) p)); + j += 2; + p += 2; + } + for (; i < k; i++) { + writemembl(j++, p[0]); + p++; + } + + /* Respond positively. */ + goto ok; + + case 'p': /* read register */ + /* Read register index. */ + if (!gdbstub_client_read_word(client, &j)) { +e14: + FAST_RESPONSE("E14"); + break; + } + + /* Read the register's value. */ + if (!(i = gdbstub_client_read_reg(j, buf))) + goto e14; + + /* Return value. */ + gdbstub_client_respond_hex(client, buf, i); + break; + + case 'P': /* write register */ + /* Read register index and value. */ + if (!(i = gdbstub_client_read_word(client, &j))) + goto e14; + client->packet_pos += i + 1; + if (!gdbstub_client_read_hex(client, buf, sizeof(buf))) + goto e14; + + /* Write the value to the register. */ + if (!gdbstub_client_write_reg(j, buf)) + goto e14; + + /* Respond positively. */ + goto ok; + + case 'q': /* query */ + /* Erase response, as we'll use it as a scratch buffer. */ + memset(client->response, 0, sizeof(client->response)); + + /* Read the query type. */ + client->packet_pos += gdbstub_client_read_string(client, client->response, sizeof(client->response) - 1, + (client->packet[1] == 'R') ? ',' : ':') + + 1; + + /* Perform the query. */ + if (!strcmp(client->response, "Supported")) { + /* Go through the feature list and negate ones we don't support. */ + while ((client->response_pos < (sizeof(client->response) - 1)) && (i = gdbstub_client_read_string(client, &client->response[client->response_pos], sizeof(client->response) - client->response_pos - 1, ';'))) { + client->packet_pos += i + 1; + if (strncmp(&client->response[client->response_pos], "PacketSize", 10) && strcmp(&client->response[client->response_pos], "swbreak") && strcmp(&client->response[client->response_pos], "hwbreak") && strncmp(&client->response[client->response_pos], "xmlRegisters", 12) && strcmp(&client->response[client->response_pos], "qXfer:features:read")) { + gdbstub_log("GDB Stub: Feature \"%s\" is not supported\n", &client->response[client->response_pos]); + client->response_pos += i; + client->response[client->response_pos++] = '-'; + client->response[client->response_pos++] = ';'; + } else { + gdbstub_log("GDB Stub: Feature \"%s\" is supported\n", &client->response[client->response_pos]); + } + } + + /* Add our supported features to the end. */ + if (client->response_pos < (sizeof(client->response) - 1)) + client->response_pos += snprintf(&client->response[client->response_pos], sizeof(client->response) - client->response_pos, + "PacketSize=%X;swbreak+;hwbreak+;qXfer:features:read+", (int) (sizeof(client->packet) - 1)); + break; + } else if (!strcmp(client->response, "Xfer")) { + /* Read the transfer object. */ + client->packet_pos += gdbstub_client_read_string(client, client->response, sizeof(client->response) - 1, ':') + 1; + if (!strcmp(client->response, "features")) { + /* Read the transfer operation. */ + client->packet_pos += gdbstub_client_read_string(client, client->response, sizeof(client->response) - 1, ':') + 1; + if (!strcmp(client->response, "read")) { + /* Read the transfer annex. */ + client->packet_pos += gdbstub_client_read_string(client, client->response, sizeof(client->response) - 1, ':') + 1; + if (!strcmp(client->response, "target.xml")) { + /* Patch architecture for IDA. */ + p = strstr(target_xml, ""); + if (p) { + if (client->ida_mode) + memcpy(p, "i386 ", 35); /* make IDA not complain about i8086 being unknown */ + else + memcpy(p, "i8086 ", 35); /* start in 16-bit mode to work around known GDB bug preventing 32->16 switching */ + } + + /* Send target XML. */ + p = target_xml; + } else { + p = NULL; + } + + /* Stop if the file wasn't found. */ + if (!p) { +e00: + FAST_RESPONSE("E00"); + break; + } + + /* Read offset and length. */ + if (!(i = gdbstub_client_read_word(client, &j))) + goto e22; + client->packet_pos += i + 1; + client->packet_pos += gdbstub_client_read_word(client, &k) + 1; + if (!k) + goto e22; + + /* Check if the offset is valid. */ + l = strlen(p); + if (j > l) + goto e00; + p += j; + + /* Return the more/less flag while also clamping the length. */ + if (k >= ((sizeof(client->response) >> 1) - 2)) + k = (sizeof(client->response) >> 1) - 3; + if (k < (l - j)) { + client->response[client->response_pos++] = 'm'; + } else { + client->response[client->response_pos++] = 'l'; + k = l - j; + } + + /* Encode the data. */ + while (k--) { + i = *p++; + if ((i == '\0') || (i == '#') || (i == '$') || (i == '*') || (i == '}')) { + client->response[client->response_pos++] = '}'; + client->response[client->response_pos++] = i ^ 0x20; + } else { + client->response[client->response_pos++] = i; + } + } + break; + } + } + } else if (!strncmp(client->response, "Attached", 8)) { + FAST_RESPONSE("1"); + } else if (!strcmp(client->response, "C")) { + FAST_RESPONSE("QC1"); + } else if (!strcmp(client->response, "fThreadInfo")) { + FAST_RESPONSE("m1"); + } else if (!strcmp(client->response, "sThreadInfo")) { + FAST_RESPONSE("l"); + } else if (!strcmp(client->response, "Rcmd")) { + /* Read and decode command in-place. */ + i = gdbstub_client_read_hex(client, (uint8_t *) client->packet, strlen(client->packet) - client->packet_pos); + client->packet[i] = 0; + gdbstub_log("GDB Stub: Monitor command: %s\n", client->packet); + + /* Parse the command name. */ + char *strtok_save; + p = strtok_r(client->packet, " ", &strtok_save); + if (!p) + goto ok; + i = strlen(p) - 1; /* get last character offset */ + + /* Interpret the command. */ + if (p[0] == 'i') { + /* Read I/O operation width. */ + l = (i < 1) ? '\0' : p[i]; + + /* Read optional I/O port. */ + if (!(p = strtok_r(NULL, " ", &strtok_save)) || !gdbstub_num_decode(p, &j, GDB_MODE_HEX) || (j < 0) || (j >= 65536)) + j = client->last_io_base; + else + client->last_io_base = j; + + /* Read optional length. */ + if (!(p = strtok_r(NULL, " ", &strtok_save)) || !gdbstub_num_decode(p, &k, GDB_MODE_BASE10)) + k = client->last_io_len; + else + client->last_io_len = k; + + /* Clamp length. */ + if (k < 1) + k = 1; + if (k > (65536 - j)) + k = 65536 - j; + + /* Read ports. */ + i = 0; + while (i < k) { + if ((i % 16) == 0) { + if (i) { + client->packet[client->packet_pos++] = '\n'; + + /* Provide partial response with the last line. */ + client->response_pos = 0; + client->response[client->response_pos++] = 'O'; + gdbstub_client_respond_hex(client, (uint8_t *) client->packet, client->packet_pos); + gdbstub_client_respond_partial(client); + } + client->packet_pos = sprintf(client->packet, "%04X:", j + i); + } + /* Act according to I/O operation width. */ + switch (l) { + case 'd': + case 'l': + client->packet_pos += sprintf(&client->packet[client->packet_pos], " %08X", inl(j + i)); + i += 4; + break; + + case 'w': + client->packet_pos += sprintf(&client->packet[client->packet_pos], " %04X", inw(j + i)); + i += 2; + break; + + case 'b': + case '\0': + client->packet_pos += sprintf(&client->packet[client->packet_pos], " %02X", inb(j + i)); + i++; + break; + + default: + goto unknown; + } + } + client->packet[client->packet_pos++] = '\n'; + + /* Respond with the final line. */ + client->response_pos = 0; + gdbstub_client_respond_hex(client, (uint8_t *) &client->packet, client->packet_pos); + break; + } else if (p[0] == 'o') { + /* Read I/O operation width. */ + l = (i < 1) ? '\0' : p[i]; + + /* Read optional I/O port. */ + if (!(p = strtok_r(NULL, " ", &strtok_save)) || !gdbstub_num_decode(p, &j, GDB_MODE_HEX) || (j < 0) || (j >= 65536)) + j = -1; + + /* Read optional value. */ + if (!(p = strtok_r(NULL, " ", &strtok_save)) || !gdbstub_num_decode(p, &k, GDB_MODE_HEX)) { + if (j == -1) + k = client->last_io_value; + else + k = j; /* only one specified = treat as value on last port */ + j = -1; + } + if (j == -1) + j = client->last_io_base; + else + client->last_io_base = j; + client->last_io_value = k; + + /* Write port. */ + switch (l) { + case 'd': + case 'l': + outl(j, k); + break; + + case 'w': + outw(j, k); + break; + + case 'b': + case 't': + case '\0': + outb(j, k); + break; + + default: + goto unknown; + } + } else if (p[0] == 'r') { + pc_reset_hard(); + } else if ((p[0] == '?') || !strcmp(p, "help")) { + FAST_RESPONSE_HEX( + "Commands:\n" + "- ib/iw/il [port [length]] - Read {length} (default 1) I/O ports starting from {port} (default last)\n" + "- ob/ow/ol [[port] value] - Write {value} to I/O {port} (both default last)\n" + "- r - Hard reset the emulated machine\n"); + break; + } else { +unknown: + FAST_RESPONSE_HEX("Unknown command\n"); + break; + } + + goto ok; + } + break; + + case 'z': /* remove break/watchpoint */ + case 'Z': /* insert break/watchpoint */ + + /* Parse breakpoint type. */ + switch (client->packet[1]) { + case '0': /* software breakpoint */ + first_breakpoint = &first_swbreak; + break; + + case '1': /* hardware breakpoint */ + first_breakpoint = &first_hwbreak; + break; + + case '2': /* write watchpoint */ + first_breakpoint = &first_wwatch; + break; + + case '3': /* read watchpoint */ + first_breakpoint = &first_rwatch; + break; + + case '4': /* access watchpoint */ + first_breakpoint = &first_awatch; + break; + + default: /* unknown type */ + client->packet[2] = '\0'; /* force address check to fail */ + break; + } + + /* Read address. */ + if (client->packet[2] != ',') + break; + client->packet_pos = 3; + if (!(i = gdbstub_client_read_word(client, &j))) + break; + client->packet_pos += i; + if (client->packet[client->packet_pos++] == ',') + gdbstub_client_read_word(client, &k); + else + k = 1; + + /* Test writability of software breakpoint. */ + if (client->packet[1] == '0') { + buf[0] = readmembl(j); + writemembl(j, 0xcc); + buf[1] = readmembl(j); + writemembl(j, buf[0]); + if (buf[1] != 0xcc) + goto end; + } + + /* Find an existing breakpoint with this address. */ + breakpoint = *first_breakpoint; + while (breakpoint) { + if (breakpoint->addr == j) + break; + prev_breakpoint = breakpoint; + breakpoint = breakpoint->next; + } + + /* Check if the breakpoint is already present (when inserting) or not found (when removing). */ + if ((!!breakpoint) ^ (client->packet[0] == 'z')) + goto e22; + + /* Insert or remove the breakpoint. */ + if (client->packet[0] != 'z') { + /* Allocate a new breakpoint. */ + breakpoint = malloc(sizeof(gdbstub_breakpoint_t)); + breakpoint->addr = j; + breakpoint->end = j + k; + breakpoint->next = NULL; + + /* Add the new breakpoint to the list. */ + if (!(*first_breakpoint)) + *first_breakpoint = breakpoint; + else if (prev_breakpoint) + prev_breakpoint->next = breakpoint; + } else { + /* Remove breakpoint from the list. */ + if (breakpoint == *first_breakpoint) + *first_breakpoint = breakpoint->next; + else if (prev_breakpoint) + prev_breakpoint->next = breakpoint->next; + + /* De-allocate breakpoint. */ + free(breakpoint); + } + + /* Update the page watchpoint map if we're dealing with a watchpoint. */ + if (client->packet[1] >= '2') { + /* Clear this watchpoint's corresponding page map groups, + as everything is going to be recomputed soon anyway. */ + memset(&gdbstub_watch_pages[j >> (MEM_GRANULARITY_BITS + 6)], 0, + (((k - 1) >> (MEM_GRANULARITY_BITS + 6)) + 1) * sizeof(gdbstub_watch_pages[0])); + + /* Go through all watchpoint lists. */ + l = 0; + breakpoint = first_rwatch; + while (1) { + if (breakpoint) { + /* Flag this watchpoint's corresponding pages as having a watchpoint. */ + k = (breakpoint->end - 1) >> MEM_GRANULARITY_BITS; + for (i = breakpoint->addr >> MEM_GRANULARITY_BITS; i <= k; i++) + gdbstub_watch_pages[i >> 6] |= (1ULL << (i & 63)); + + breakpoint = breakpoint->next; + } else { + /* Jump from list to list as a shortcut. */ + if (l == 0) + breakpoint = first_wwatch; + else if (l == 1) + breakpoint = first_awatch; + else + break; + l++; + } + } + } + + /* Respond positively. */ + goto ok; + } +end: + /* Send response. */ + gdbstub_client_respond(client); +} + +static void +gdbstub_cpu_exec(int32_t cycs) +{ + /* Flag that we're now in the debugger context to avoid triggering watchpoints. */ + in_gdbstub = 1; + + /* Handle CPU execution if it isn't paused. */ + if (gdbstub_step <= GDBSTUB_SSTEP) { + /* Swap in any software breakpoints. */ + gdbstub_breakpoint_t *swbreak = first_swbreak; + while (swbreak) { + /* Swap the INT 3 opcode into the address. */ + swbreak->orig_val = readmembl(swbreak->addr); + writemembl(swbreak->addr, 0xcc); + swbreak = swbreak->next; + } + + /* Call the original cpu_exec function outside the debugger context. */ + if ((gdbstub_step == GDBSTUB_SSTEP) && ((cycles + cycs) <= 0)) + cycs += -(cycles + cycs) + 1; + in_gdbstub = 0; + cpu_exec_shadow(cycs); + in_gdbstub = 1; + + /* Swap out any software breakpoints. */ + swbreak = first_swbreak; + while (swbreak) { + if (readmembl(swbreak->addr) == 0xcc) + writemembl(swbreak->addr, swbreak->orig_val); + swbreak = swbreak->next; + } + } + + /* Populate stop reason if we have stopped. */ + stop_reason_len = 0; + if (gdbstub_step > GDBSTUB_EXEC) { + /* Assemble stop reason manually, avoiding sprintf and friends for performance. */ + stop_reason[stop_reason_len++] = 'T'; + stop_reason[stop_reason_len++] = '0'; + stop_reason[stop_reason_len++] = '0' + ((gdbstub_step == GDBSTUB_BREAK) ? GDB_SIGINT : GDB_SIGTRAP); + + /* Add extended break reason. */ + if (gdbstub_step >= GDBSTUB_BREAK_RWATCH) { + if (gdbstub_step != GDBSTUB_BREAK_WWATCH) + stop_reason[stop_reason_len++] = (gdbstub_step == GDBSTUB_BREAK_RWATCH) ? 'r' : 'a'; + stop_reason[stop_reason_len++] = 'w'; + stop_reason[stop_reason_len++] = 'a'; + stop_reason[stop_reason_len++] = 't'; + stop_reason[stop_reason_len++] = 'c'; + stop_reason[stop_reason_len++] = 'h'; + stop_reason[stop_reason_len++] = ':'; + stop_reason_len += sprintf(&stop_reason[stop_reason_len], "%X;", watch_addr); + } else if (gdbstub_step >= GDBSTUB_BREAK_SW) { + stop_reason[stop_reason_len++] = (gdbstub_step == GDBSTUB_BREAK_SW) ? 's' : 'h'; + stop_reason[stop_reason_len++] = 'w'; + stop_reason[stop_reason_len++] = 'b'; + stop_reason[stop_reason_len++] = 'r'; + stop_reason[stop_reason_len++] = 'e'; + stop_reason[stop_reason_len++] = 'a'; + stop_reason[stop_reason_len++] = 'k'; + stop_reason[stop_reason_len++] = ':'; + stop_reason[stop_reason_len++] = ';'; + } + + /* Add register dump. */ + uint8_t buf[10] = { 0 }; + int j; + for (int i = 0; i < GDB_REG_MAX; i++) { + if (i >= 0x10) + stop_reason[stop_reason_len++] = gdbstub_hex_encode(i >> 4); + stop_reason[stop_reason_len++] = gdbstub_hex_encode(i & 0x0f); + stop_reason[stop_reason_len++] = ':'; + j = gdbstub_client_read_reg(i, buf); + for (int k = 0; k < j; k++) { + stop_reason[stop_reason_len++] = gdbstub_hex_encode(buf[k] >> 4); + stop_reason[stop_reason_len++] = gdbstub_hex_encode(buf[k] & 0x0f); + } + stop_reason[stop_reason_len++] = ';'; + } + + /* Don't execute the CPU any further if single-stepping. */ + gdbstub_step = GDBSTUB_BREAK; + } + + /* Return the framerate to normal. */ + gdbstub_next_asap = 0; + + /* Process client packets. */ + thread_wait_mutex(client_list_mutex); + gdbstub_client_t *client = first_client; + while (client) { + /* Report stop reason if the client is waiting for one. */ + if (client->waiting_stop && stop_reason_len) { + client->waiting_stop = 0; + + /* Wait for any pending responses to be acknowledged. */ + if (!thread_wait_event(client->response_event, -1)) { + /* Block other responses from being written while this one isn't acknowledged. */ + thread_reset_event(client->response_event); + + /* Write stop reason response. */ + strcpy(client->response, stop_reason); + client->response_pos = stop_reason_len; + gdbstub_client_respond(client); + } else { + gdbstub_log("GDB Stub: Timed out waiting for client %s:%d\n", inet_ntoa(client->addr.sin_addr), client->addr.sin_port); + } + } + + if (client->has_packet) { + gdbstub_client_packet(client); + client->has_packet = client->packet_pos = 0; + thread_set_event(client->processed_event); + } + +#ifdef GDBSTUB_ALLOW_MULTI_CLIENTS + client = client->next; +#else + break; +#endif + } + thread_release_mutex(client_list_mutex); + + /* Flag that we're now out of the debugger context. */ + in_gdbstub = 0; +} + +static void +gdbstub_client_thread(void *priv) +{ + gdbstub_client_t *client = (gdbstub_client_t *) priv; + uint8_t buf[256]; + ssize_t bytes_read; + + gdbstub_log("GDB Stub: New connection from %s:%d\n", inet_ntoa(client->addr.sin_addr), client->addr.sin_port); + + /* Allow packets to be processed. */ + thread_set_event(client->processed_event); + + /* Read data from client. */ + while ((bytes_read = recv(client->socket, (char *) buf, sizeof(buf), 0)) > 0) { + for (ssize_t i = 0; i < bytes_read; i++) { + switch (buf[i]) { + case '$': /* packet start */ + /* Wait for any existing packets to be processed. */ + thread_wait_event(client->processed_event, -1); + + client->packet_pos = 0; + break; + + case '-': /* negative acknowledgement */ + /* Retransmit the current response. */ + gdbstub_client_respond(client); + break; + + case '+': /* positive acknowledgement */ + /* Allow another response to be written. */ + thread_set_event(client->response_event); + break; + + case 0x03: /* break */ + /* Wait for any existing packets to be processed. */ + thread_wait_event(client->processed_event, -1); + + /* Break immediately. */ + gdbstub_log("GDB Stub: Break requested\n"); + gdbstub_break(); + break; + + default: + /* Wait for any existing packets to be processed, just in case. */ + thread_wait_event(client->processed_event, -1); + + if (client->packet_pos < (sizeof(client->packet) - 1)) { + /* Append byte to the packet. */ + client->packet[client->packet_pos++] = buf[i]; + + /* Check if we're at the end of a packet. */ + if ((client->packet_pos >= 3) && (client->packet[client->packet_pos - 3] == '#')) { /* packet checksum start */ + /* Small hack to speed up IDA instruction trace mode. */ + if (*((uint32_t *) client->packet) == ('H' | ('c' << 8) | ('1' << 16) | ('#' << 24))) { + /* Send pre-computed response. */ + send(client->socket, "+$OK#9A", 7, 0); + + /* Skip processing. */ + continue; + } + + /* Flag that a packet should be processed. */ + client->packet[client->packet_pos] = '\0'; + thread_reset_event(client->processed_event); + gdbstub_next_asap = client->has_packet = 1; + } + } + break; + } + } + } + + gdbstub_log("GDB Stub: Connection with %s:%d broken\n", inet_ntoa(client->addr.sin_addr), client->addr.sin_port); + + /* Close socket. */ + if (client->socket != -1) { + close(client->socket); + client->socket = -1; + } + + /* Unblock anyone waiting on the response event. */ + thread_set_event(client->response_event); + + /* Remove this client from the list. */ + thread_wait_mutex(client_list_mutex); +#ifdef GDBSTUB_ALLOW_MULTI_CLIENTS + if (client == first_client) { +#endif + first_client = client->next; + if (first_client == NULL) { + last_client = NULL; + gdbstub_step = GDBSTUB_EXEC; /* unpause CPU when all clients are disconnected */ + } +#ifdef GDBSTUB_ALLOW_MULTI_CLIENTS + } else { + other_client = first_client; + while (other_client) { + if (other_client->next == client) { + if (last_client == client) + last_client = other_client; + other_client->next = client->next; + break; + } + other_client = other_client->next; + } + } +#endif + + free(client); + thread_release_mutex(client_list_mutex); +} + +static void +gdbstub_server_thread(void *priv) +{ + /* Listen on GDB socket. */ + listen(gdbstub_socket, 1); + + /* Accept connections. */ + gdbstub_client_t *client; + socklen_t sl = sizeof(struct sockaddr_in); + while (1) { + /* Allocate client structure. */ + client = malloc(sizeof(gdbstub_client_t)); + memset(client, 0, sizeof(gdbstub_client_t)); + client->processed_event = thread_create_event(); + client->response_event = thread_create_event(); + + /* Accept connection. */ + client->socket = accept(gdbstub_socket, (struct sockaddr *) &client->addr, &sl); + if (client->socket < 0) + break; + + /* Add to client list. */ + thread_wait_mutex(client_list_mutex); + if (first_client) { +#ifdef GDBSTUB_ALLOW_MULTI_CLIENTS + last_client->next = client; + last_client = client; +#else + first_client->next = last_client = client; + close(first_client->socket); +#endif + } else { + first_client = last_client = client; + } + thread_release_mutex(client_list_mutex); + + /* Pause CPU execution. */ + gdbstub_break(); + + /* Start client thread. */ + thread_create(gdbstub_client_thread, client); + } + + /* Deallocate the redundant client structure. */ + thread_destroy_event(client->processed_event); + thread_destroy_event(client->response_event); + free(client); +} + +void +gdbstub_cpu_init(void) +{ + /* Replace cpu_exec with our own function if the GDB stub is active. */ + if ((gdbstub_socket != -1) && (cpu_exec != gdbstub_cpu_exec)) { + cpu_exec_shadow = cpu_exec; + cpu_exec = gdbstub_cpu_exec; + } +} + +int +gdbstub_instruction(void) +{ + /* Check hardware breakpoints if any are present. */ + gdbstub_breakpoint_t *breakpoint = first_hwbreak; + if (breakpoint) { + /* Calculate the current instruction's address. */ + uint32_t wanted_addr = cs + cpu_state.pc; + + /* Go through the list of software breakpoints. */ + do { + /* Check if the breakpoint coincides with this address. */ + if (breakpoint->addr == wanted_addr) { + gdbstub_log("GDB Stub: Hardware breakpoint at %08X\n", wanted_addr); + + /* Flag that we're in a hardware breakpoint. */ + gdbstub_step = GDBSTUB_BREAK_HW; + + /* Pause execution. */ + return 1; + } + + breakpoint = breakpoint->next; + } while (breakpoint); + } + + /* No breakpoint found, continue execution or stop if execution is paused. */ + return gdbstub_step - GDBSTUB_EXEC; +} + +int +gdbstub_int3(void) +{ + /* Check software breakpoints if any are present. */ + gdbstub_breakpoint_t *breakpoint = first_swbreak; + if (breakpoint) { + /* Calculate the breakpoint instruction's address. */ + uint32_t new_pc = cpu_state.pc - 1; + if (cpu_state.op32) + new_pc &= 0xffff; + uint32_t wanted_addr = cs + new_pc; + + /* Go through the list of software breakpoints. */ + do { + /* Check if the breakpoint coincides with this address. */ + if (breakpoint->addr == wanted_addr) { + gdbstub_log("GDB Stub: Software breakpoint at %08X\n", wanted_addr); + + /* Move EIP back to where the break instruction was. */ + cpu_state.pc = new_pc; + + /* Flag that we're in a software breakpoint. */ + gdbstub_step = GDBSTUB_BREAK_SW; + + /* Abort INT 3 execution. */ + return 1; + } + + breakpoint = breakpoint->next; + } while (breakpoint); + } + + /* No breakpoint found, continue INT 3 execution as normal. */ + return 0; +} + +void +gdbstub_mem_access(uint32_t *addrs, int access) +{ + /* Stop if we're in the debugger context. */ + if (in_gdbstub) + return; + + int width = access & (GDBSTUB_MEM_WRITE - 1); + int i; + + /* Go through the lists of watchpoints for this type of access. */ + gdbstub_breakpoint_t *watchpoint = (access & GDBSTUB_MEM_WRITE) ? first_wwatch : first_rwatch; + while (1) { + if (watchpoint) { + /* Check if any component of this address is within the breakpoint's range. */ + for (i = 0; i < width; i++) { + if ((addrs[i] >= watchpoint->addr) && (addrs[i] < watchpoint->end)) { + watch_addr = addrs[i]; + break; + } + } + if (i < width) { + gdbstub_log("GDB Stub: %s watchpoint at %08X\n", (access & GDBSTUB_MEM_AWATCH) ? "Access" : ((access & GDBSTUB_MEM_WRITE) ? "Write" : "Read"), watch_addr); + + /* Flag that we're in a read/write watchpoint. */ + gdbstub_step = (access & GDBSTUB_MEM_AWATCH) ? GDBSTUB_BREAK_AWATCH : ((access & GDBSTUB_MEM_WRITE) ? GDBSTUB_BREAK_WWATCH : GDBSTUB_BREAK_RWATCH); + + /* Stop looking. */ + return; + } + + watchpoint = watchpoint->next; + } else { + /* Jump from list to list as a shortcut. */ + if (access & GDBSTUB_MEM_AWATCH) { + break; + } else { + watchpoint = first_awatch; + access |= GDBSTUB_MEM_AWATCH; + } + } + } +} + +void +gdbstub_init(void) +{ +#ifdef _WIN32 + WSAStartup(MAKEWORD(2, 2), &wsa); +#endif + + /* Create GDB server socket. */ + if ((gdbstub_socket = socket(AF_INET, SOCK_STREAM, 0)) == -1) { + pclog("GDB Stub: Failed to create socket\n"); + return; + } + + /* Bind GDB server socket. */ + int port = 12345; + struct sockaddr_in bind_addr = { + .sin_family = AF_INET, + .sin_addr = { .s_addr = INADDR_ANY }, + .sin_port = htons(port) + }; + if (bind(gdbstub_socket, (struct sockaddr *) &bind_addr, sizeof(bind_addr)) == -1) { + pclog("GDB Stub: Failed to bind on port %d (%d)\n", port, +#ifdef _WIN32 + WSAGetLastError() +#else + errno +#endif + ); + gdbstub_socket = -1; + return; + } + + /* Create client list mutex. */ + client_list_mutex = thread_create_mutex(); + + /* Clear watchpoint page map. */ + memset(gdbstub_watch_pages, 0, sizeof(gdbstub_watch_pages)); + + /* Start server thread. */ + pclog("GDB Stub: Listening on port %d\n", port); + thread_create(gdbstub_server_thread, NULL); + + /* Start the CPU paused. */ + gdbstub_step = GDBSTUB_BREAK; +} + +void +gdbstub_close(void) +{ + /* Stop if the GDB server hasn't initialized. */ + if (gdbstub_socket < 0) + return; + + /* Close GDB server socket. */ + close(gdbstub_socket); + + /* Clear client list. */ + thread_wait_mutex(client_list_mutex); + gdbstub_client_t *client = first_client; + int socket; + while (client) { + socket = client->socket; + client->socket = -1; + close(socket); + client = client->next; + } + thread_release_mutex(client_list_mutex); + thread_close_mutex(client_list_mutex); +} diff --git a/src/include/86box/86box.h b/src/include/86box/86box.h index 62aaddc99..ae2ea260c 100644 --- a/src/include/86box/86box.h +++ b/src/include/86box/86box.h @@ -1,193 +1,230 @@ /* - * 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. + * 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. + * This file is part of the 86Box distribution. * - * Main include file for the application. + * Main include file for the application. * * * - * Authors: Miran Grca, - *f Fred N. van Kempen, + * Authors: Miran Grca, + * Fred N. van Kempen, * - * Copyright 2016-2020 Miran Grca. - * Copyright 2017-2020 Fred N. van Kempen. - * Copyright 2021 Laci bá' + * Copyright 2016-2020 Miran Grca. + * Copyright 2017-2020 Fred N. van Kempen. + * Copyright 2021 Laci bá' */ #ifndef EMU_86BOX_H -# define EMU_86BOX_H - +#define EMU_86BOX_H /* Configuration values. */ -#define SERIAL_MAX 4 -#define PARALLEL_MAX 4 -#define SCREEN_RES_X 640 -#define SCREEN_RES_Y 480 +#define SERIAL_MAX 4 +#define PARALLEL_MAX 4 +#define SCREEN_RES_X 640 +#define SCREEN_RES_Y 480 /* Filename and pathname info. */ -#define CONFIG_FILE "86box.cfg" +#define CONFIG_FILE "86box.cfg" #define NVR_PATH "nvr" #define SCREENSHOT_PATH "screenshots" +/* Recently used images */ +#define MAX_PREV_IMAGES 4 +#define MAX_IMAGE_PATH_LEN 256 /* Default language 0xFFFF = from system, 0x409 = en-US */ #define DEFAULT_LANGUAGE 0x0409 +#define POSTCARDS_NUM 4 +#define POSTCARD_MASK (POSTCARDS_NUM - 1) + #ifdef MIN -#undef MIN +# undef MIN #endif #ifdef MAX -#undef MAX +# undef MAX +#endif +#ifdef ABS +# undef ABS +#endif +#ifdef ABSD +# undef ABSD #endif -#define MIN(a, b) ((a) < (b) ? (a) : (b)) -#define MAX(a, b) ((a) > (b) ? (a) : (b)) -#define ABS(x) ((x) > 0 ? (x) : -(x)) -#define BCD8(x) ((((x) / 10) << 4) | ((x) % 10)) -#define BCD16(x) ((((x) / 1000) << 12) | (((x) / 100) << 8) | BCD8(x)) -#define BCD32(x) ((((x) / 10000000) << 28) | (((x) / 1000000) << 24) | (((x) / 100000) << 20) | (((x) / 10000) << 16) | BCD16(x)) +#define MIN(a, b) ((a) < (b) ? (a) : (b)) +#define MAX(a, b) ((a) > (b) ? (a) : (b)) +#define ABS(x) ((x) > 0 ? (x) : -(x)) +#define ABSD(x) ((x) > 0.0 ? (x) : -(x)) +#define BCD8(x) ((((x) / 10) << 4) | ((x) % 10)) +#define BCD16(x) ((((x) / 1000) << 12) | (((x) / 100) << 8) | BCD8(x)) +#define BCD32(x) ((((x) / 10000000) << 28) | (((x) / 1000000) << 24) | (((x) / 100000) << 20) | (((x) / 10000) << 16) | BCD16(x)) + +#if defined(__GNUC__) || defined(__clang__) +# define UNLIKELY(x) __builtin_expect((x), 0) +# define LIKELY(x) __builtin_expect((x), 1) +#else +# define UNLIKELY(x) (x) +# define LIKELY(x) (x) +#endif #ifdef __cplusplus extern "C" { #endif /* Global variables. */ -extern uint32_t lang_sys; /* (-) system language code */ +extern uint32_t lang_sys; /* (-) system language code */ -extern int dump_on_exit; /* (O) dump regs on exit*/ -extern int do_dump_config; /* (O) dump cfg after load */ -extern int start_in_fullscreen; /* (O) start in fullscreen */ +extern int dump_on_exit; /* (O) dump regs on exit*/ +extern int start_in_fullscreen; /* (O) start in fullscreen */ #ifdef _WIN32 -extern int force_debug; /* (O) force debug output */ +extern int force_debug; /* (O) force debug output */ #endif #ifdef USE_WX -extern int video_fps; /* (O) render speed in fps */ +extern int video_fps; /* (O) render speed in fps */ #endif -extern int settings_only; /* (O) show only the settings dialog */ -extern int confirm_exit_cmdl; /* (O) do not ask for confirmation on quit if set to 0 */ +extern int settings_only; /* (O) show only the settings dialog */ +extern int confirm_exit_cmdl; /* (O) do not ask for confirmation on quit if set to 0 */ #ifdef _WIN32 -extern uint64_t unique_id; -extern uint64_t source_hwnd; +extern uint64_t unique_id; +extern uint64_t source_hwnd; +#endif +extern char rom_path[1024]; /* (O) full path to ROMs */ +extern char log_path[1024]; /* (O) full path of logfile */ +extern char vm_name[1024]; /* (O) display name of the VM */ +#ifdef USE_INSTRUMENT +extern uint8_t instru_enabled; +extern uint64_t instru_run_ms; #endif -extern char rom_path[1024]; /* (O) full path to ROMs */ -extern char log_path[1024]; /* (O) full path of logfile */ -extern char vm_name[1024]; /* (O) display name of the VM */ +#define window_x monitor_settings[0].mon_window_x +#define window_y monitor_settings[0].mon_window_y +#define window_w monitor_settings[0].mon_window_w +#define window_h monitor_settings[0].mon_window_h +extern int window_remember; +extern int vid_resize; /* (C) allow resizing */ +extern int invert_display; /* (C) invert the display */ +extern int suppress_overscan; /* (C) suppress overscans */ +extern uint32_t lang_id; /* (C) language code identifier */ +extern char icon_set[256]; /* (C) iconset identifier */ +extern int scale; /* (C) screen scale factor */ +extern int dpi_scale; /* (C) DPI scaling of the emulated screen */ +extern int vid_api; /* (C) video renderer */ +extern int vid_cga_contrast; /* (C) video */ +extern int video_fullscreen; /* (C) video */ +extern int video_fullscreen_first; /* (C) video */ +extern int video_fullscreen_scale; /* (C) video */ +extern int enable_overscan; /* (C) video */ +extern int force_43; /* (C) video */ +extern int video_filter_method; /* (C) video */ +extern int video_vsync; /* (C) video */ +extern int video_framerate; /* (C) video */ +extern int gfxcard[2]; /* (C) graphics/video card */ +extern char video_shader[512]; /* (C) video */ +extern int bugger_enabled; /* (C) enable ISAbugger */ +extern int postcard_enabled; /* (C) enable POST card */ +extern int isamem_type[]; /* (C) enable ISA mem cards */ +extern int isartc_type; /* (C) enable ISA RTC card */ +extern int sound_is_float; /* (C) sound uses FP values */ +extern int voodoo_enabled; /* (C) video option */ +extern int ibm8514_standalone_enabled; /* (C) video option */ +extern int xga_standalone_enabled; /* (C) video option */ +extern uint32_t mem_size; /* (C) memory size (Installed on system board) */ +extern uint32_t isa_mem_size; /* (C) memory size (ISA Memory Cards) */ +extern int cpu; /* (C) cpu type */ +extern int cpu_use_dynarec; /* (C) cpu uses/needs Dyna */ +extern int fpu_type; /* (C) fpu type */ +extern int fpu_softfloat; /* (C) fpu uses softfloat */ +extern int time_sync; /* (C) enable time sync */ +extern int hdd_format_type; /* (C) hard disk file format */ +extern int confirm_reset; /* (C) enable reset confirmation */ +extern int confirm_exit; /* (C) enable exit confirmation */ +extern int confirm_save; /* (C) enable save confirmation */ +extern int enable_discord; /* (C) enable Discord integration */ -extern int window_w, window_h, /* (C) window size and */ - window_x, window_y, /* position info */ - window_remember, - vid_resize, /* (C) allow resizing */ - invert_display, /* (C) invert the display */ - suppress_overscan; /* (C) suppress overscans */ -extern uint32_t lang_id; /* (C) language code identifier */ -extern char icon_set[256]; /* (C) iconset identifier */ -extern int scale; /* (C) screen scale factor */ -extern int dpi_scale; /* (C) DPI scaling of the emulated screen */ -extern int vid_api; /* (C) video renderer */ -extern int vid_cga_contrast, /* (C) video */ - video_fullscreen, /* (C) video */ - video_fullscreen_first, /* (C) video */ - video_fullscreen_scale, /* (C) video */ - enable_overscan, /* (C) video */ - force_43, /* (C) video */ - video_filter_method, /* (C) video */ - video_vsync, /* (C) video */ - video_framerate, /* (C) video */ - gfxcard; /* (C) graphics/video card */ -extern char video_shader[512]; /* (C) video */ -extern int serial_enabled[], /* (C) enable serial ports */ - bugger_enabled, /* (C) enable ISAbugger */ - postcard_enabled, /* (C) enable POST card */ - isamem_type[], /* (C) enable ISA mem cards */ - isartc_type; /* (C) enable ISA RTC card */ -extern int sound_is_float, /* (C) sound uses FP values */ - GAMEBLASTER, /* (C) sound option */ - GUS, GUSMAX, /* (C) sound option */ - SSI2001, /* (C) sound option */ - voodoo_enabled; /* (C) video option */ -extern uint32_t mem_size; /* (C) memory size (Installed on system board) */ -extern uint32_t isa_mem_size; /* (C) memory size (ISA Memory Cards) */ -extern int cpu, /* (C) cpu type */ - cpu_use_dynarec, /* (C) cpu uses/needs Dyna */ - fpu_type; /* (C) fpu type */ -extern int time_sync; /* (C) enable time sync */ -extern int network_type; /* (C) net provider type */ -extern int network_card; /* (C) net interface num */ -extern char network_host[522]; /* (C) host network intf */ -extern int hdd_format_type; /* (C) hard disk file format */ -extern int confirm_reset, /* (C) enable reset confirmation */ - confirm_exit, /* (C) enable exit confirmation */ - confirm_save; /* (C) enable save confirmation */ -extern int enable_discord; /* (C) enable Discord integration */ -extern int enable_crashdump; /* (C) enable crash dump */ +extern int fixed_size_x; +extern int fixed_size_y; +extern int do_auto_pause; /* (C) Auto-pause the emulator on focus loss */ +extern int auto_paused; +extern double mouse_sensitivity; /* (C) Mouse sensitivity scale */ +#ifdef _Atomic +extern _Atomic double mouse_x_error; /* Mouse error accumulator - Y */ +extern _Atomic double mouse_y_error; /* Mouse error accumulator - Y */ +#endif +extern int pit_mode; /* (C) force setting PIT mode */ +extern int fm_driver; /* (C) select FM sound driver */ -extern int is_pentium; /* TODO: Move back to cpu/cpu.h when it's figured out, - how to remove that hack from the ET4000/W32p. */ -extern int fixed_size_x, fixed_size_y; +/* Keyboard variables for future key combination redefinition. */ +extern uint16_t key_prefix_1_1; +extern uint16_t key_prefix_1_2; +extern uint16_t key_prefix_2_1; +extern uint16_t key_prefix_2_2; +extern uint16_t key_uncapture_1; +extern uint16_t key_uncapture_2; - -extern char exe_path[2048]; /* path (dir) of executable */ -extern char usr_path[1024]; /* path (dir) of user data */ -extern char cfg_path[1024]; /* full path of config file */ +extern char exe_path[2048]; /* path (dir) of executable */ +extern char usr_path[1024]; /* path (dir) of user data */ +extern char cfg_path[1024]; /* full path of config file */ +extern int open_dir_usr_path; /* default file open dialog directory of usr_path */ #ifndef USE_NEW_DYNAREC -extern FILE *stdlog; /* file to log output to */ +extern FILE *stdlog; /* file to log output to */ #endif -extern int scrnsz_x, /* current screen size, X */ - scrnsz_y; /* current screen size, Y */ -extern int efscrnsz_y; -extern int config_changed; /* config has changed */ - +extern int config_changed; /* config has changed */ /* Function prototypes. */ #ifdef HAVE_STDARG_H -extern void pclog_ex(const char *fmt, va_list); -extern void fatal_ex(const char *fmt, va_list); +extern void pclog_ex(const char *fmt, va_list); +extern void fatal_ex(const char *fmt, va_list); #endif -extern void pclog_toggle_suppr(void); -extern void pclog(const char *fmt, ...); -extern void fatal(const char *fmt, ...); -extern void set_screen_size(int x, int y); -extern void reset_screen_size(void); -extern void set_screen_size_natural(void); -extern void update_mouse_msg(); +extern void pclog_toggle_suppr(void); +extern void pclog(const char *fmt, ...) __attribute__ ((format (printf, 1, 2))); +extern void fatal(const char *fmt, ...) __attribute__ ((format (printf, 1, 2))); +extern void set_screen_size(int x, int y); +extern void set_screen_size_monitor(int x, int y, int monitor_index); +extern void reset_screen_size(void); +extern void reset_screen_size_monitor(int monitor_index); +extern void set_screen_size_natural(void); +extern void update_mouse_msg(void); #if 0 -extern void pc_reload(wchar_t *fn); +extern void pc_reload(wchar_t *fn); #endif -extern int pc_init_modules(void); -extern int pc_init(int argc, char *argv[]); -extern void pc_close(void *threadid); -extern void pc_reset_hard_close(void); -extern void pc_reset_hard_init(void); -extern void pc_reset_hard(void); -extern void pc_full_speed(void); -extern void pc_speed_changed(void); -extern void pc_send_cad(void); -extern void pc_send_cae(void); -extern void pc_send_cab(void); -extern void pc_run(void); -extern void pc_start(void); -extern void pc_onesec(void); +extern int pc_init_modules(void); +extern int pc_init(int argc, char *argv[]); +extern void pc_close(void *threadid); +extern void pc_reset_hard_close(void); +extern void pc_reset_hard_init(void); +extern void pc_reset_hard(void); +extern void pc_full_speed(void); +extern void pc_speed_changed(void); +extern void pc_send_cad(void); +extern void pc_send_cae(void); +extern void pc_send_cab(void); +extern void pc_run(void); +extern void pc_start(void); +extern void pc_onesec(void); -extern uint16_t get_last_addr(void); +extern uint16_t get_last_addr(void); /* This is for external subtraction of cycles; should be in cpu.c but I put it here to avoid - having to include cpu.c everywhere. */ -extern void sub_cycles(int c); -extern void resub_cycles(int old_cycles); + having to include cpu.h everywhere. */ +extern void sub_cycles(int c); +extern void resub_cycles(int old_cycles); -extern double isa_timing; -extern int io_delay, framecountx; +extern void ack_pause(void); +extern void do_pause(int p); -extern volatile int cpu_thread_run; +extern double isa_timing; +extern int io_delay; +extern int framecountx; + +extern volatile int cpu_thread_run; +extern uint8_t postcard_codes[POSTCARDS_NUM]; #ifdef __cplusplus } #endif - -#endif /*EMU_86BOX_H*/ +#endif /*EMU_86BOX_H*/ diff --git a/src/include/86box/acpi.h b/src/include/86box/acpi.h index 10facb21e..2b8a6396f 100644 --- a/src/include/86box/acpi.h +++ b/src/include/86box/acpi.h @@ -1,139 +1,171 @@ /* - * 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. + * 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. + * This file is part of the 86Box distribution. * - * Definitions for the ACPI emulation. + * Definitions for the ACPI emulation. * * * - * Authors: Miran Grca, + * Authors: Miran Grca, * - * Copyright 2020 Miran Grca. + * Copyright 2020 Miran Grca. */ #ifndef ACPI_H -# define ACPI_H - +#define ACPI_H #ifdef __cplusplus +#include +using atomic_int = std::atomic_int; extern "C" { +#else +#include #endif -#define ACPI_TIMER_FREQ 3579545 -#define PM_FREQ ACPI_TIMER_FREQ +#define ACPI_TIMER_FREQ 3579545 +#define PM_FREQ ACPI_TIMER_FREQ -#define RSM_STS (1 << 15) -#define PWRBTN_STS (1 << 8) -#define GBL_STS (1 << 5) -#define BM_STS (1 << 4) -#define TMROF_STS (1 << 0) +#define RSM_STS (1 << 15) +#define PWRBTN_STS (1 << 8) +#define GBL_STS (1 << 5) +#define BM_STS (1 << 4) +#define TMROF_STS (1 << 0) -#define RTC_EN (1 << 10) -#define PWRBTN_EN (1 << 8) -#define GBL_EN (1 << 5) -#define TMROF_EN (1 << 0) +#define RTC_EN (1 << 10) +#define PWRBTN_EN (1 << 8) +#define GBL_EN (1 << 5) +#define TMROF_EN (1 << 0) -#define SCI_EN (1 << 0) -#define SUS_EN (1 << 13) +#define SCI_EN (1 << 0) +#define SUS_EN (1 << 13) -#define SUS_POWER_OFF (1 << 0) -#define SUS_SUSPEND (1 << 1) -#define SUS_NVR (1 << 2) -#define SUS_RESET_CPU (1 << 3) -#define SUS_RESET_CACHE (1 << 4) -#define SUS_RESET_PCI (1 << 5) +#define SUS_POWER_OFF (1 << 0) +#define SUS_SUSPEND (1 << 1) +#define SUS_NVR (1 << 2) +#define SUS_RESET_CPU (1 << 3) +#define SUS_RESET_CACHE (1 << 4) +#define SUS_RESET_PCI (1 << 5) -#define ACPI_ENABLE 0xf1 -#define ACPI_DISABLE 0xf0 +#define ACPI_ENABLE 0xf1 +#define ACPI_DISABLE 0xf0 -#define VEN_ALI 0x010b9 -#define VEN_INTEL 0x08086 -#define VEN_SIS 0x01039 -#define VEN_SMC 0x01055 -#define VEN_VIA 0x01106 -#define VEN_VIA_596B 0x11106 +#define VEN_ALI 0x010b9 +#define VEN_INTEL 0x08086 +#define VEN_SIS 0x01039 +#define VEN_SMC 0x01055 +#define VEN_VIA 0x01106 +#define VEN_VIA_596B 0x11106 - -typedef struct -{ - uint8_t acpitst, auxen, auxsts, plvl2, plvl3, - smicmd, gpio_dir, - gpio_val, muxcntrl, ali_soft_smi, - timer32, smireg, - gpireg[3], gporeg[4], - extiotrapsts, extiotrapen; - uint16_t pmsts, pmen, - pmcntrl, gpsts, gpsts1, - gpen, gpen1, gpscien, - gpcntrl, gplvl, gpmux, - gpsel, gpsmien, pscntrl, - gpscists; - int smi_lock, smi_active; - uint32_t pcntrl, p2cntrl, glbsts, - devsts, glben, - glbctl, devctl, - padsts, paden, - gptren, gptimer, timer_val, - gpo_val, gpi_val, - extsmi_val, pad0; - uint64_t tmr_overflow_time; +typedef struct acpi_regs_t { + uint8_t acpitst; + uint8_t auxen; + uint8_t auxsts; + uint8_t plvl2; + uint8_t plvl3; + uint8_t smicmd; + uint8_t gpio_dir; + uint8_t gpio_val; + uint8_t muxcntrl; + uint8_t ali_soft_smi; + uint8_t timer32; + uint8_t smireg; + uint8_t gpireg[3]; + uint8_t gporeg[4]; + uint8_t extiotrapsts; + uint8_t extiotrapen; + uint16_t pmsts; + uint16_t pmen; + uint16_t pmcntrl; + uint16_t gpsts; + uint16_t gpsts1; + uint16_t gpen; + uint16_t gpen1; + uint16_t gpscien; + uint16_t gpcntrl; + uint16_t gplvl; + uint16_t gpmux; + uint16_t gpsel; + uint16_t gpsmien; + uint16_t pscntrl; + uint16_t gpscists; + int smi_lock; + int smi_active; + uint32_t pcntrl; + uint32_t p2cntrl; + uint32_t glbsts; + uint32_t devsts; + uint32_t glben; + uint32_t glbctl; + uint32_t devctl; + uint32_t padsts; + uint32_t paden; + uint32_t gptren; + uint32_t gptimer; + uint32_t gpo_val; + uint32_t gpi_val; + uint32_t extsmi_val; + uint32_t pad0; } acpi_regs_t; - -typedef struct -{ - acpi_regs_t regs; - uint8_t gpireg2_default, pad[3], - gporeg_default[4], - suspend_types[8]; - uint16_t io_base, aux_io_base; - int vendor, - slot, irq_mode, - irq_pin, irq_line, - mirq_is_level; - pc_timer_t timer, resume_timer; - nvr_t *nvr; - apm_t *apm; - void *i2c, - (*trap_update)(void *priv), *trap_priv; +typedef struct acpi_t { + acpi_regs_t regs; + uint8_t gpireg2_default; + uint8_t irq_state; + uint8_t pad[2]; + uint8_t gporeg_default[4]; + uint8_t suspend_types[8]; + uint16_t io_base; + uint16_t aux_io_base; + int vendor; + int slot; + int irq_mode; + int irq_pin; + int irq_line; + int mirq_is_level; + pc_timer_t timer; + pc_timer_t resume_timer; + pc_timer_t pwrbtn_timer; + nvr_t *nvr; + apm_t *apm; + void *i2c; + void (*trap_update)(void *priv); + void *trap_priv; } acpi_t; - /* Global variables. */ -extern int acpi_rtc_status; - -extern const device_t acpi_ali_device; -extern const device_t acpi_intel_device; -extern const device_t acpi_sis_device; -extern const device_t acpi_smc_device; -extern const device_t acpi_via_device; -extern const device_t acpi_via_596b_device; +extern int acpi_rtc_status; +extern atomic_int acpi_pwrbut_pressed; +extern int acpi_enabled; +extern const device_t acpi_ali_device; +extern const device_t acpi_intel_device; +extern const device_t acpi_smc_device; +extern const device_t acpi_via_device; +extern const device_t acpi_via_596b_device; /* Functions */ -extern void acpi_update_irq(acpi_t *dev); -extern void acpi_raise_smi(void *priv, int do_smi); -extern void acpi_update_io_mapping(acpi_t *dev, uint32_t base, int chipset_en); -extern void acpi_update_aux_io_mapping(acpi_t *dev, uint32_t base, int chipset_en); -extern void acpi_init_gporeg(acpi_t *dev, uint8_t val0, uint8_t val1, uint8_t val2, uint8_t val3); -extern void acpi_set_timer32(acpi_t *dev, uint8_t timer32); -extern void acpi_set_slot(acpi_t *dev, int slot); -extern void acpi_set_irq_mode(acpi_t *dev, int irq_mode); -extern void acpi_set_irq_pin(acpi_t *dev, int irq_pin); -extern void acpi_set_irq_line(acpi_t *dev, int irq_line); -extern void acpi_set_mirq_is_level(acpi_t *dev, int mirq_is_level); -extern void acpi_set_gpireg2_default(acpi_t *dev, uint8_t gpireg2_default); -extern void acpi_set_nvr(acpi_t *dev, nvr_t *nvr); -extern void acpi_set_trap_update(acpi_t *dev, void (*update)(void *priv), void *priv); -extern uint8_t acpi_ali_soft_smi_status_read(acpi_t *dev); -extern void acpi_ali_soft_smi_status_write(acpi_t *dev, uint8_t soft_smi); +extern void acpi_update_irq(acpi_t *dev); +extern void acpi_raise_smi(void *priv, int do_smi); +extern void acpi_update_io_mapping(acpi_t *dev, uint32_t base, int chipset_en); +extern void acpi_update_aux_io_mapping(acpi_t *dev, uint32_t base, int chipset_en); +extern void acpi_init_gporeg(acpi_t *dev, uint8_t val0, uint8_t val1, uint8_t val2, uint8_t val3); +extern void acpi_set_timer32(acpi_t *dev, uint8_t timer32); +extern void acpi_set_slot(acpi_t *dev, int slot); +extern void acpi_set_irq_mode(acpi_t *dev, int irq_mode); +extern void acpi_set_irq_pin(acpi_t *dev, int irq_pin); +extern void acpi_set_irq_line(acpi_t *dev, int irq_line); +extern void acpi_set_mirq_is_level(acpi_t *dev, int mirq_is_level); +extern void acpi_set_gpireg2_default(acpi_t *dev, uint8_t gpireg2_default); +extern void acpi_set_nvr(acpi_t *dev, nvr_t *nvr); +extern void acpi_set_trap_update(acpi_t *dev, void (*update)(void *priv), void *priv); +extern uint8_t acpi_ali_soft_smi_status_read(acpi_t *dev); +extern void acpi_ali_soft_smi_status_write(acpi_t *dev, uint8_t soft_smi); #ifdef __cplusplus } #endif - -#endif /*ACPI_H*/ +#endif /*ACPI_H*/ diff --git a/src/include/86box/agpgart.h b/src/include/86box/agpgart.h new file mode 100644 index 000000000..d3ed35c88 --- /dev/null +++ b/src/include/86box/agpgart.h @@ -0,0 +1,38 @@ +/* + * 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. + * + * AGP Graphics Address Remapping Table remapping emulation. + * + * + * + * Authors: RichardG, + * + * Copyright 2021 RichardG. + */ + +#ifndef EMU_AGPGART_H +#define EMU_AGPGART_H + +typedef struct agpgart_s { + int aperture_enable; + uint32_t aperture_base; + uint32_t aperture_size; + uint32_t aperture_mask; + uint32_t gart_base; + mem_mapping_t aperture_mapping; +} agpgart_t; + +extern void agpgart_set_aperture(agpgart_t *dev, uint32_t base, uint32_t size, int enable); +extern void agpgart_set_gart(agpgart_t *dev, uint32_t base); + +#ifdef EMU_DEVICE_H +/* AGP GART */ +extern const device_t agpgart_device; +#endif + +#endif /*EMU_AGPGART_H*/ diff --git a/src/include/86box/apm.h b/src/include/86box/apm.h index 1fd985951..2d5f0f117 100644 --- a/src/include/86box/apm.h +++ b/src/include/86box/apm.h @@ -1,47 +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. + * 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. + * This file is part of the 86Box distribution. * - * Definitions for the Advanced Power Management emulation. + * Definitions for the Advanced Power Management emulation. * * * - * Authors: Miran Grca, + * Authors: Miran Grca, * - * Copyright 2019 Miran Grca. + * Copyright 2019 Miran Grca. */ #ifndef APM_H -# define APM_H - +#define APM_H #ifdef __cplusplus extern "C" { #endif -typedef struct -{ - uint8_t cmd, - stat, do_smi; +typedef struct apm_t { + uint8_t cmd; + uint8_t stat; + uint8_t do_smi; } apm_t; - /* Global variables. */ -extern const device_t apm_device; - -extern const device_t apm_pci_device; -extern const device_t apm_pci_acpi_device; +extern const device_t apm_device; +extern const device_t apm_pci_device; +extern const device_t apm_pci_acpi_device; /* Functions. */ -extern void apm_set_do_smi(apm_t *dev, uint8_t do_smi); +extern void apm_set_do_smi(apm_t *dev, uint8_t do_smi); #ifdef __cplusplus } #endif - -#endif /*APM_H*/ +#endif /*APM_H*/ diff --git a/src/include/86box/bswap.h b/src/include/86box/bswap.h index a49c4f1bc..ac758b20a 100644 --- a/src/include/86box/bswap.h +++ b/src/include/86box/bswap.h @@ -1,20 +1,20 @@ /* - * VARCem Virtual ARchaeological Computer EMulator. - * An emulator of (mostly) x86-based PC systems and devices, - * using the ISA,EISA,VLB,MCA and PCI system buses, roughly - * spanning the era between 1981 and 1995. + * 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 VARCem Project. + * This file is part of the 86Box distribution. * - * Various definitions for portable byte-swapping. + * Various definitions for portable byte-swapping. * * * - * Authors: Fred N. van Kempen, - * neozeed, + * Authors: Fred N. van Kempen, + * neozeed, * - * Copyright 2017,2018 Fred N. van Kempen. - * Copyright 2016-2018 neozeed. + * Copyright 2017-2018 Fred N. van Kempen. + * Copyright 2016-2018 neozeed. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -34,116 +34,158 @@ * Boston, MA 02111-1307 * USA. */ + #ifndef BSWAP_H #define BSWAP_H #include #ifdef HAVE_BYTESWAP_H -#include +# include #else # define bswap_16(x) \ - ( \ - ((uint16_t)( \ - (((uint16_t)(x) & (uint16_t)0x00ffU) << 8) | \ - (((uint16_t)(x) & (uint16_t)0xff00U) >> 8) )) \ - ) + ( \ + ((uint16_t)( \ + (((uint16_t)(x) & (uint16_t)0x00ffU) << 8) | \ + (((uint16_t)(x) & (uint16_t)0xff00U) >> 8) )) \ + ) # define bswap_32(x) \ - ( \ - ((uint32_t)( \ - (((uint32_t)(x) & (uint32_t)0x000000ffUL) << 24) | \ - (((uint32_t)(x) & (uint32_t)0x0000ff00UL) << 8) | \ - (((uint32_t)(x) & (uint32_t)0x00ff0000UL) >> 8) | \ - (((uint32_t)(x) & (uint32_t)0xff000000UL) >> 24) )) \ - ) + ( \ + ((uint32_t)( \ + (((uint32_t)(x) & (uint32_t)0x000000ffUL) << 24) | \ + (((uint32_t)(x) & (uint32_t)0x0000ff00UL) << 8) | \ + (((uint32_t)(x) & (uint32_t)0x00ff0000UL) >> 8) | \ + (((uint32_t)(x) & (uint32_t)0xff000000UL) >> 24) )) \ + ) # define bswap_64(x) \ - ( \ - ((uint64_t)( \ - (uint64_t)(((uint64_t)(x) & (uint64_t)0x00000000000000ffULL) << 56) | \ - (uint64_t)(((uint64_t)(x) & (uint64_t)0x000000000000ff00ULL) << 40) | \ - (uint64_t)(((uint64_t)(x) & (uint64_t)0x0000000000ff0000ULL) << 24) | \ - (uint64_t)(((uint64_t)(x) & (uint64_t)0x00000000ff000000ULL) << 8) | \ - (uint64_t)(((uint64_t)(x) & (uint64_t)0x000000ff00000000ULL) >> 8) | \ - (uint64_t)(((uint64_t)(x) & (uint64_t)0x0000ff0000000000ULL) >> 24) | \ - (uint64_t)(((uint64_t)(x) & (uint64_t)0x00ff000000000000ULL) >> 40) | \ - (uint64_t)(((uint64_t)(x) & (uint64_t)0xff00000000000000ULL) >> 56) )) \ - ) -#endif /*HAVE_BYTESWAP_H*/ + ( \ + ((uint64_t)( \ + (uint64_t)(((uint64_t)(x) & (uint64_t)0x00000000000000ffULL) << 56) | \ + (uint64_t)(((uint64_t)(x) & (uint64_t)0x000000000000ff00ULL) << 40) | \ + (uint64_t)(((uint64_t)(x) & (uint64_t)0x0000000000ff0000ULL) << 24) | \ + (uint64_t)(((uint64_t)(x) & (uint64_t)0x00000000ff000000ULL) << 8) | \ + (uint64_t)(((uint64_t)(x) & (uint64_t)0x000000ff00000000ULL) >> 8) | \ + (uint64_t)(((uint64_t)(x) & (uint64_t)0x0000ff0000000000ULL) >> 24) | \ + (uint64_t)(((uint64_t)(x) & (uint64_t)0x00ff000000000000ULL) >> 40) | \ + (uint64_t)(((uint64_t)(x) & (uint64_t)0xff00000000000000ULL) >> 56) )) \ + ) +#endif /*HAVE_BYTESWAP_H*/ +#if __GNUC__ >= 10 +#if defined __has_builtin && __has_builtin(__builtin_bswap16) +#define bswap16(x) __builtin_bswap16(x) +#else static __inline uint16_t bswap16(uint16_t x) { return bswap_16(x); } +# endif +#else +static __inline uint16_t +bswap16(uint16_t x) +{ + return bswap_16(x); +} +#endif -static __inline uint32_t bswap32(uint32_t x) +#if __GNUC__ >= 10 +# if defined __has_builtin && __has_builtin(__builtin_bswap32) +# define bswap32(x) __builtin_bswap32(x) +# else +static __inline uint32_t +bswap32(uint32_t x) { return bswap_32(x); } +# endif +#else +static __inline uint32_t +bswap32(uint32_t x) +{ + return bswap_32(x); +} +#endif -static __inline uint64_t bswap64(uint64_t x) +#if __GNUC__ >= 10 +# if defined __has_builtin && __has_builtin(__builtin_bswap64) +# define bswap64(x) __builtin_bswap64(x) +# else +static __inline uint64_t +bswap64(uint64_t x) { return bswap_64(x); } +# endif +#else +static __inline uint64_t +bswap64(uint64_t x) +{ + return bswap_64(x); +} +#endif -static __inline void bswap16s(uint16_t *s) +static __inline void +bswap16s(uint16_t *s) { *s = bswap16(*s); } -static __inline void bswap32s(uint32_t *s) +static __inline void +bswap32s(uint32_t *s) { *s = bswap32(*s); } -static __inline void bswap64s(uint64_t *s) +static __inline void +bswap64s(uint64_t *s) { *s = bswap64(*s); } #if defined(WORDS_BIGENDIAN) -# define be_bswap(v, size) (v) -# define le_bswap(v, size) bswap ## size(v) -# define be_bswaps(v, size) -# define le_bswaps(p, size) *p = bswap ## size(*p); +# define be_bswap(v, size) (v) +# define le_bswap(v, size) bswap##size(v) +# define be_bswaps(v, size) +# define le_bswaps(p, size) *p = bswap##size(*p); #else -# define le_bswap(v, size) (v) -# define be_bswap(v, size) bswap ## size(v) -# define le_bswaps(v, size) -# define be_bswaps(p, size) *p = bswap ## size(*p); +# define le_bswap(v, size) (v) +# define be_bswap(v, size) bswap##size(v) +# define le_bswaps(v, size) +# define be_bswaps(p, size) *p = bswap##size(*p); #endif -#define CPU_CONVERT(endian, size, type)\ -static __inline type endian ## size ## _to_cpu(type v)\ -{\ - return endian ## _bswap(v, size);\ -}\ -\ -static __inline type cpu_to_ ## endian ## size(type v)\ -{\ - return endian ## _bswap(v, size);\ -}\ -\ -static __inline void endian ## size ## _to_cpus(type *p)\ -{\ - endian ## _bswaps(p, size)\ -}\ -\ -static __inline void cpu_to_ ## endian ## size ## s(type *p)\ -{\ - endian ## _bswaps(p, size)\ -}\ -\ -static __inline type endian ## size ## _to_cpup(const type *p)\ -{\ - return endian ## size ## _to_cpu(*p);\ -}\ -\ -static __inline void cpu_to_ ## endian ## size ## w(type *p, type v)\ -{\ - *p = cpu_to_ ## endian ## size(v);\ -} +#define CPU_CONVERT(endian, size, type) \ + static __inline type endian##size##_to_cpu(type v) \ + { \ + return endian##_bswap(v, size); \ + } \ + \ + static __inline type cpu_to_##endian##size(type v) \ + { \ + return endian##_bswap(v, size); \ + } \ + \ + static __inline void endian##size##_to_cpus(type *p) \ + { \ + endian##_bswaps(p, size) \ + } \ + \ + static __inline void cpu_to_##endian##size##s(type *p) \ + { \ + endian##_bswaps(p, size) \ + } \ + \ + static __inline type endian##size##_to_cpup(const type *p) \ + { \ + return endian##size##_to_cpu(*p); \ + } \ + \ + static __inline void cpu_to_##endian##size##w(type *p, type v) \ + { \ + *p = cpu_to_##endian##size(v); \ + } CPU_CONVERT(be, 16, uint16_t) CPU_CONVERT(be, 32, uint32_t) @@ -157,27 +199,29 @@ CPU_CONVERT(le, 64, uint64_t) #if defined(__i386__) || defined(__powerpc__) -#define cpu_to_le16wu(p, v) cpu_to_le16w(p, v) -#define cpu_to_le32wu(p, v) cpu_to_le32w(p, v) -#define le16_to_cpupu(p) le16_to_cpup(p) -#define le32_to_cpupu(p) le32_to_cpup(p) +# define cpu_to_le16wu(p, v) cpu_to_le16w(p, v) +# define cpu_to_le32wu(p, v) cpu_to_le32w(p, v) +# define le16_to_cpupu(p) le16_to_cpup(p) +# define le32_to_cpupu(p) le32_to_cpup(p) -#define cpu_to_be16wu(p, v) cpu_to_be16w(p, v) -#define cpu_to_be32wu(p, v) cpu_to_be32w(p, v) +# define cpu_to_be16wu(p, v) cpu_to_be16w(p, v) +# define cpu_to_be32wu(p, v) cpu_to_be32w(p, v) #else -static __inline void cpu_to_le16wu(uint16_t *p, uint16_t v) +static __inline void +cpu_to_le16wu(uint16_t *p, uint16_t v) { - uint8_t *p1 = (uint8_t *)p; + uint8_t *p1 = (uint8_t *) p; p1[0] = v & 0xff; p1[1] = v >> 8; } -static __inline void cpu_to_le32wu(uint32_t *p, uint32_t v) +static __inline void +cpu_to_le32wu(uint32_t *p, uint32_t v) { - uint8_t *p1 = (uint8_t *)p; + uint8_t *p1 = (uint8_t *) p; p1[0] = v; p1[1] = v >> 8; @@ -185,29 +229,33 @@ static __inline void cpu_to_le32wu(uint32_t *p, uint32_t v) p1[3] = v >> 24; } -static __inline uint16_t le16_to_cpupu(const uint16_t *p) +static __inline uint16_t +le16_to_cpupu(const uint16_t *p) { - const uint8_t *p1 = (const uint8_t *)p; + const uint8_t *p1 = (const uint8_t *) p; return p1[0] | (p1[1] << 8); } -static __inline uint32_t le32_to_cpupu(const uint32_t *p) +static __inline uint32_t +le32_to_cpupu(const uint32_t *p) { - const uint8_t *p1 = (const uint8_t *)p; + const uint8_t *p1 = (const uint8_t *) p; return p1[0] | (p1[1] << 8) | (p1[2] << 16) | (p1[3] << 24); } -static __inline void cpu_to_be16wu(uint16_t *p, uint16_t v) +static __inline void +cpu_to_be16wu(uint16_t *p, uint16_t v) { - uint8_t *p1 = (uint8_t *)p; + uint8_t *p1 = (uint8_t *) p; p1[0] = v >> 8; p1[1] = v & 0xff; } -static __inline void cpu_to_be32wu(uint32_t *p, uint32_t v) +static __inline void +cpu_to_be32wu(uint32_t *p, uint32_t v) { - uint8_t *p1 = (uint8_t *)p; + uint8_t *p1 = (uint8_t *) p; p1[0] = v >> 24; p1[1] = v >> 16; @@ -218,9 +266,9 @@ static __inline void cpu_to_be32wu(uint32_t *p, uint32_t v) #endif #ifdef WORDS_BIGENDIAN -#define cpu_to_32wu cpu_to_be32wu +# define cpu_to_32wu cpu_to_be32wu #else -#define cpu_to_32wu cpu_to_le32wu +# define cpu_to_32wu cpu_to_le32wu #endif #undef le_bswap @@ -228,4 +276,4 @@ static __inline void cpu_to_be32wu(uint32_t *p, uint32_t v) #undef le_bswaps #undef be_bswaps -#endif /* BSWAP_H */ +#endif /*BSWAP_H*/ diff --git a/src/include/86box/bugger.h b/src/include/86box/bugger.h index 985f13d2f..57dabd172 100644 --- a/src/include/86box/bugger.h +++ b/src/include/86box/bugger.h @@ -1,34 +1,32 @@ /* - * 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. + * 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. + * This file is part of the 86Box distribution. * - * Implementation of the ISA Bus (de)Bugger expansion card - * sold as a DIY kit in the late 1980's in The Netherlands. - * This card was a assemble-yourself 8bit ISA addon card for - * PC and AT systems that had several tools to aid in low- - * level debugging (mostly for faulty BIOSes, bootloaders - * and system kernels...) + * Implementation of the ISA Bus (de)Bugger expansion card + * sold as a DIY kit in the late 1980's in The Netherlands. + * This card was a assemble-yourself 8bit ISA addon card for + * PC and AT systems that had several tools to aid in low- + * level debugging (mostly for faulty BIOSes, bootloaders + * and system kernels...) * - * Definitions for the BUGGER card. + * Definitions for the BUGGER card. * * * - * Author: Fred N. van Kempen, + * Authors: Fred N. van Kempen, * - * Copyright 1989-2018 Fred N. van Kempen. + * Copyright 1989-2018 Fred N. van Kempen. */ #ifndef BUGGER_H -# define BUGGER_H - +#define BUGGER_H /* I/O port range used. */ -#define BUGGER_ADDR 0x007a -#define BUGGER_ADDRLEN 4 - +#define BUGGER_ADDR 0x007a +#define BUGGER_ADDRLEN 4 #ifdef __cplusplus extern "C" { @@ -37,12 +35,10 @@ extern "C" { /* Global variables. */ extern const device_t bugger_device; - /* Functions. */ #ifdef __cplusplus } #endif - -#endif /*BUGGER_H*/ +#endif /*BUGGER_H*/ diff --git a/src/include/86box/cartridge.h b/src/include/86box/cartridge.h index 390604e79..2fa0a9358 100644 --- a/src/include/86box/cartridge.h +++ b/src/include/86box/cartridge.h @@ -1,40 +1,35 @@ /* - * 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. + * 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. + * This file is part of the 86Box distribution. * - * Definitions for the PCjr cartridge emulation. + * Definitions for the PCjr cartridge emulation. * * * - * Authors: Miran Grca, + * Authors: Miran Grca, * - * Copyright 2021 Miran Grca. + * Copyright 2021 Miran Grca. */ #ifndef EMU_CARTRIDGE_H -# define EMU_CARTRIDGE_H - +#define EMU_CARTRIDGE_H #ifdef __cplusplus extern "C" { #endif +extern char cart_fns[2][512]; -extern char cart_fns[2][512]; - - -extern void cart_load(int drive, char *fn); -extern void cart_close(int drive); - -extern void cart_reset(void); +extern void cart_load(int drive, char *fn); +extern void cart_close(int drive); +extern void cart_reset(void); #ifdef __cplusplus } #endif - -#endif /*EMU_CARTRIDGE_H*/ +#endif /*EMU_CARTRIDGE_H*/ diff --git a/src/include/86box/cassette.h b/src/include/86box/cassette.h index a22b4c41f..3706ca632 100644 --- a/src/include/86box/cassette.h +++ b/src/include/86box/cassette.h @@ -19,155 +19,151 @@ * Public License for more details. * *****************************************************************************/ - #ifndef PCE_IBMPC_CASSETTE_H #define PCE_IBMPC_CASSETTE_H 1 - #include +typedef struct pc_cassette_t { + char save; + char pcm; -typedef struct { - char save; - char pcm; + unsigned char motor; - unsigned char motor; + unsigned long position; - unsigned long position; + unsigned long position_save; + unsigned long position_load; - unsigned long position_save; - unsigned long position_load; + unsigned char data_out; + unsigned char data_inp; - unsigned char data_out; - unsigned char data_inp; + int pcm_out_vol; + int pcm_out_val; - int pcm_out_vol; - int pcm_out_val; + unsigned cas_out_cnt; + unsigned char cas_out_buf; - unsigned cas_out_cnt; - unsigned char cas_out_buf; + unsigned cas_inp_cnt; + unsigned char cas_inp_buf; + unsigned char cas_inp_bit; - unsigned cas_inp_cnt; - unsigned char cas_inp_buf; - unsigned char cas_inp_bit; + int pcm_inp_fir[3]; - int pcm_inp_fir[3]; + unsigned long clk; - unsigned long clk; + unsigned long clk_pcm; - unsigned long clk_pcm; + unsigned long clk_out; + unsigned long clk_inp; - unsigned long clk_out; - unsigned long clk_inp; + unsigned long srate; - unsigned long srate; - - char close; - char *fname; - FILE *fp; - pc_timer_t timer; + char close; + char *fname; + FILE *fp; + pc_timer_t timer; } pc_cassette_t; +void pc_cas_init(pc_cassette_t *cas); +void pc_cas_free(pc_cassette_t *cas); -void pc_cas_init (pc_cassette_t *cas); -void pc_cas_free (pc_cassette_t *cas); - -pc_cassette_t *pc_cas_new (void); -void pc_cas_del (pc_cassette_t *cas); +pc_cassette_t *pc_cas_new(void); +void pc_cas_del(pc_cassette_t *cas); /*!*************************************************************************** * @short Set the cassette file * @return True on error, false otherwise *****************************************************************************/ -int pc_cas_set_fname (pc_cassette_t *cas, const char *fname); +int pc_cas_set_fname(pc_cassette_t *cas, const char *fname); /*!*************************************************************************** * @short Get the cassette mode * @return True if in save mode, false if in load mode *****************************************************************************/ -int pc_cas_get_mode (const pc_cassette_t *cas); +int pc_cas_get_mode(const pc_cassette_t *cas); /*!*************************************************************************** * @short Set the cassette mode * @param save If true set save mode, otherwise set load mode *****************************************************************************/ -void pc_cas_set_mode (pc_cassette_t *cas, int save); +void pc_cas_set_mode(pc_cassette_t *cas, int save); /*!*************************************************************************** * @short Get the cassette pcm mode * @return True if in pcm mode, false if in binary mode *****************************************************************************/ -int pc_cas_get_pcm (const pc_cassette_t *cas); +int pc_cas_get_pcm(const pc_cassette_t *cas); /*!*************************************************************************** * @short Set the cassette pcm mode * @param pcm If true set pcm mode, otherwise set binary mode *****************************************************************************/ -void pc_cas_set_pcm (pc_cassette_t *cas, int pcm); +void pc_cas_set_pcm(pc_cassette_t *cas, int pcm); /*!*************************************************************************** * @short Get the pcm sample rate * @return The sample rate in Hz *****************************************************************************/ -unsigned long pc_cas_get_srate (const pc_cassette_t *cas); +unsigned long pc_cas_get_srate(const pc_cassette_t *cas); /*!*************************************************************************** * @short Set the pcm sample rate * @param pcm The sample rate in Hz *****************************************************************************/ -void pc_cas_set_srate (pc_cassette_t *cas, unsigned long srate); +void pc_cas_set_srate(pc_cassette_t *cas, unsigned long srate); /*!*************************************************************************** * @short Rewind the cassette *****************************************************************************/ -void pc_cas_rewind (pc_cassette_t *cas); +void pc_cas_rewind(pc_cassette_t *cas); /*!*************************************************************************** * @short Fast forward to the end of the cassette *****************************************************************************/ -void pc_cas_append (pc_cassette_t *cas); +void pc_cas_append(pc_cassette_t *cas); /*!*************************************************************************** * @short Get the current load/save position *****************************************************************************/ -unsigned long pc_cas_get_position (const pc_cassette_t *cas); +unsigned long pc_cas_get_position(const pc_cassette_t *cas); /*!*************************************************************************** * @short Set the current load/save position *****************************************************************************/ -int pc_cas_set_position (pc_cassette_t *cas, unsigned long pos); +int pc_cas_set_position(pc_cassette_t *cas, unsigned long pos); /*!*************************************************************************** * @short Set the cassette motor status *****************************************************************************/ -void pc_cas_set_motor (pc_cassette_t *cas, unsigned char val); +void pc_cas_set_motor(pc_cassette_t *cas, unsigned char val); /*!*************************************************************************** * @short Get the current input from the cassette *****************************************************************************/ -unsigned char pc_cas_get_inp (const pc_cassette_t *cas); +unsigned char pc_cas_get_inp(const pc_cassette_t *cas); /*!*************************************************************************** * @short Set the current output to the cassette *****************************************************************************/ -void pc_cas_set_out (pc_cassette_t *cas, unsigned char val); +void pc_cas_set_out(pc_cassette_t *cas, unsigned char val); -void pc_cas_print_state (const pc_cassette_t *cas); +void pc_cas_print_state(const pc_cassette_t *cas); -void pc_cas_clock (pc_cassette_t *cas, unsigned long cnt); -void pc_cas_advance (pc_cassette_t *cas); +void pc_cas_clock(pc_cassette_t *cas, unsigned long cnt); +void pc_cas_advance(pc_cassette_t *cas); +extern pc_cassette_t *cassette; -extern pc_cassette_t * cassette; +extern char cassette_fname[512]; +extern char cassette_mode[512]; +extern unsigned long cassette_pos; +extern unsigned long cassette_srate; +extern int cassette_enable; +extern int cassette_append; +extern int cassette_pcm; +extern int cassette_ui_writeprot; -extern char cassette_fname[512]; -extern char cassette_mode[512]; -extern unsigned long cassette_pos, cassette_srate; -extern int cassette_enable; -extern int cassette_append, cassette_pcm; -extern int cassette_ui_writeprot; +extern const device_t cassette_device; -extern const device_t cassette_device; - - -#endif +#endif /*PCE_IBMPC_CASSETTE_H*/ diff --git a/src/include/86box/cdrom.h b/src/include/86box/cdrom.h index 4245a0a66..d188c9243 100644 --- a/src/include/86box/cdrom.h +++ b/src/include/86box/cdrom.h @@ -1,182 +1,328 @@ /* - * 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. + * 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. + * This file is part of the 86Box distribution. * - * Generic CD-ROM drive core header. + * Generic CD-ROM drive core header. * + * Authors: Miran Grca, * - * - * Author: Miran Grca, - * - * Copyright 2016-2019 Miran Grca. + * Copyright 2016-2019 Miran Grca. */ #ifndef EMU_CDROM_H #define EMU_CDROM_H +#define CDROM_NUM 8 -#define CDROM_NUM 4 - -#define CD_STATUS_EMPTY 0 -#define CD_STATUS_DATA_ONLY 1 -#define CD_STATUS_PAUSED 2 -#define CD_STATUS_PLAYING 3 -#define CD_STATUS_STOPPED 4 -#define CD_STATUS_PLAYING_COMPLETED 5 +#define CD_STATUS_EMPTY 0 +#define CD_STATUS_DATA_ONLY 1 +#define CD_STATUS_PAUSED 2 +#define CD_STATUS_PLAYING 3 +#define CD_STATUS_STOPPED 4 +#define CD_STATUS_PLAYING_COMPLETED 5 /* Medium changed flag. */ -#define CD_STATUS_MEDIUM_CHANGED 0x80 +#define CD_STATUS_MEDIUM_CHANGED 0x80 -#define CD_TRACK_AUDIO 0x08 -#define CD_TRACK_MODE2 0x04 +#define CD_TRACK_AUDIO 0x08 +#define CD_TRACK_MODE2 0x04 -#define CD_READ_DATA 0 -#define CD_READ_AUDIO 1 -#define CD_READ_RAW 2 +#define CD_READ_DATA 0 +#define CD_READ_AUDIO 1 +#define CD_READ_RAW 2 -#define CD_TOC_NORMAL 0 -#define CD_TOC_SESSION 1 -#define CD_TOC_RAW 2 +#define CD_TOC_NORMAL 0 +#define CD_TOC_SESSION 1 +#define CD_TOC_RAW 2 -#define BUF_SIZE 32768 +#define CD_IMAGE_HISTORY 4 -#define CDROM_IMAGE 200 +#define BUF_SIZE 32768 + +#define CDROM_IMAGE 200 /* This is so that if/when this is changed to something else, changing this one define will be enough. */ #define CDROM_EMPTY !dev->host_drive - #ifdef __cplusplus extern "C" { #endif enum { CDROM_BUS_DISABLED = 0, - CDROM_BUS_ATAPI = 5, - CDROM_BUS_SCSI, - CDROM_BUS_USB + CDROM_BUS_ATAPI = 5, + CDROM_BUS_SCSI = 6, + CDROM_BUS_MITSUMI = 7, + CDROM_BUS_USB = 8 }; +enum +{ + CDROM_TYPE_86BOX_100, + CDROM_TYPE_AZT_CDA46802I_115, + CDROM_TYPE_BTC_BCD36XH_U10, + CDROM_TYPE_GOLDSTAR_CRD_8160B_314, + CDROM_TYPE_HITACHI_CDR_8130_0020, + CDROM_TYPE_KENWOOD_UCR_421_208E, + CDROM_TYPE_MATSHITA_587_7S13, + CDROM_TYPE_MATSHITA_588_LS15, + CDROM_TYPE_MATSHITA_571_10e, + CDROM_TYPE_MATSHITA_572_10j, + CDROM_TYPE_MITSUMI_FX4820T_D02A, + CDROM_TYPE_NEC_260_100, + CDROM_TYPE_NEC_260_101, + CDROM_TYPE_NEC_273_420, + CDROM_TYPE_NEC_280_105, + CDROM_TYPE_NEC_280_308, + CDROM_TYPE_PHILIPS_PCA403CD_U31P, + CDROM_TYPE_SONY_CDU76_10i, + CDROM_TYPE_SONY_CDU311_30h, + CDROM_TYPE_TOSHIBA_5302TA_0305, + CDROM_TYPE_TOSHIBA_5702B_TA70, + CDROM_TYPE_CHINON_CDS431_H42, + CDROM_TYPE_DEC_RRD45_0436, + CDROM_TYPE_MATSHITA_501_10b, + CDROM_TYPE_NEC_25_10a, + CDROM_TYPE_NEC_38_103, + CDROM_TYPE_NEC_75_103, + CDROM_TYPE_NEC_77_106, + CDROM_TYPE_NEC_211_100, + CDROM_TYPE_NEC_464_105, + CDROM_TYPE_SONY_CDU541_10i, + CDROM_TYPE_SONY_CDU561_18k, + CDROM_TYPE_SONY_CDU76S_100, + CDROM_TYPE_PHILIPS_CDD2600_107, + CDROM_TYPE_PIONEER_DRM604X_2403, + CDROM_TYPE_PLEXTOR_PX32TS_103, + CDROM_TYPE_TEAC_CD50_100, + CDROM_TYPE_TEAC_R55S_10R, + CDROM_TYPE_TEXEL_DMXX24_100, + CDROM_TYPE_TOSHIBA_XM_3433, + CDROM_TYPE_TOSHIBA_XM3201B_3232, + CDROM_TYPE_TOSHIBA_XM3301TA_0272, + CDROM_TYPE_TOSHIBA_XM5701TA_3136, + CDROM_TYPE_TOSHIBA_SDM1401_1008, + CDROM_TYPES_NUM +}; + +#define KNOWN_CDROM_DRIVE_TYPES CDROM_TYPES_NUM +#define BUS_TYPE_IDE CDROM_BUS_ATAPI +#define BUS_TYPE_SCSI CDROM_BUS_SCSI +#define BUS_TYPE_BOTH -2 +#define BUS_TYPE_NONE -1 + +static const struct +{ + const char vendor[9]; + const char model[17]; + const char revision[5]; + const char *name; + const char *internal_name; + const int bus_type; +} cdrom_drive_types[] = { + { "86BOX", "CD-ROM", "1.00", "86BOX CD-ROM 1.00", "86BOX_CD-ROM_1.00", BUS_TYPE_BOTH }, + { "AZT", "CDA46802I", "1.15", "AZT CDA46802I 1.15", "AZT_CDA46802I_1.15", BUS_TYPE_IDE }, + { "BTC", "CD-ROM BCD36XH", "U1.0", "BTC CD-ROM BCD36XH U1.0", "BTC_CD-ROM_BCD36XH_U1.0", BUS_TYPE_IDE }, + { "GOLDSTAR", "CRD-8160B", "3.14", "GOLDSTAR CRD-8160B 3.14", "GOLDSTAR_CRD-8160B_3.14", BUS_TYPE_IDE }, + { "HITACHI", "CDR-8130", "0020", "HITACHI CDR-8130 0020", "HITACHI_CDR-8130_0020", BUS_TYPE_IDE }, + { "KENWOOD", "CD-ROM UCR-421", "208E", "KENWOOD CD-ROM UCR-421 208E", "KENWOOD_CD-ROM_UCR-421_208E", BUS_TYPE_IDE }, + { "MATSHITA", "CD-ROM CR-587", "7S13", "MATSHITA CD-ROM CR-587 7S13", "MATSHITA_CD-ROM_CR-587_7S13", BUS_TYPE_IDE }, + { "MATSHITA", "CD-ROM CR-588", "LS15", "MATSHITA CD-ROM CR-588 LS15", "MATSHITA_CD-ROM_CR-588_LS15", BUS_TYPE_IDE }, + { "MATSHITA", "CR-571", "1.0e", "MATSHITA CR-571 1.0e", "MATSHITA_CR-571_1.0e", BUS_TYPE_IDE }, + { "MATSHITA", "CR-572", "1.0j", "MATSHITA CR-572 1.0j", "MATSHITA_CR-572_1.0j", BUS_TYPE_IDE }, + { "MITSUMI", "CRMC-FX4820T", "D02A", "MITSUMI CRMC-FX4820T D02A", "MITSUMI_CRMC-FX4820T_D02A", BUS_TYPE_IDE }, + { "NEC", "CD-ROM DRIVE:260", "1.00", "NEC CD-ROM DRIVE:260 1.00", "NEC_CD-ROM_DRIVE260_1.00", BUS_TYPE_IDE }, + { "NEC", "CD-ROM DRIVE:260", "1.01", "NEC CD-ROM DRIVE:260 1.01", "NEC_CD-ROM_DRIVE260_1.01", BUS_TYPE_IDE }, + { "NEC", "CD-ROM DRIVE:273", "4.20", "NEC CD-ROM DRIVE:273 4.20", "NEC_CD-ROM_DRIVE273_4.20", BUS_TYPE_IDE }, + { "NEC", "CD-ROM DRIVE:280", "1.05", "NEC CD-ROM DRIVE:280 1.05", "NEC_CD-ROM_DRIVE280_1.05", BUS_TYPE_IDE }, + { "NEC", "CD-ROM DRIVE:280", "3.08", "NEC CD-ROM DRIVE:280 3.08", "NEC_CD-ROM_DRIVE280_3.08", BUS_TYPE_IDE }, + { "PHILIPS", "CD-ROM PCA403CD", "U31P", "PHILIPS CD-ROM PCA403CD U31P", "PHILIPS_CD-ROM_PCA403CD_U31P", BUS_TYPE_IDE }, + { "SONY", "CD-ROM CDU76", "1.0i", "SONY CD-ROM CDU76 1.0i", "SONY_CD-ROM_CDU76_1.0i", BUS_TYPE_IDE }, + { "SONY", "CD-ROM CDU311", "3.0h", "SONY CD-ROM CDU311 3.0h", "SONY_CD-ROM_CDU311_3.0h", BUS_TYPE_IDE }, + { "TOSHIBA", "CD-ROM XM-5302TA", "0305", "TOSHIBA CD-ROM XM-5302TA 0305", "TOSHIBA_CD-ROM_XM-5302TA_0305", BUS_TYPE_IDE }, + { "TOSHIBA", "CD-ROM XM-5702B", "TA70", "TOSHIBA CD-ROM XM-5702B TA70", "TOSHIBA_CD-ROM_XM-5702B_TA70", BUS_TYPE_IDE }, + { "CHINON", "CD-ROM CDS-431", "H42 ", "CHINON CD-ROM CDS-431 H42", "CHINON_CD-ROM_CDS-431_H42", BUS_TYPE_SCSI }, + { "DEC", "RRD45 (C) DEC", "0436", "DEC RRD45 0436", "DEC_RRD45_0436", BUS_TYPE_SCSI }, + { "MATSHITA", "CD-ROM CR-501", "1.0b", "MATSHITA CD-ROM CR-501 1.0b", "MATSHITA_CD-ROM_CR-501_1.0b", BUS_TYPE_SCSI }, + { "NEC", "CD-ROM DRIVE:25", "1.0a", "NEC CD-ROM DRIVE:25 1.0a", "NEC_CD-ROM_DRIVE25_1.0a", BUS_TYPE_SCSI }, + { "NEC", "CD-ROM DRIVE:38", "1.00", "NEC CD-ROM DRIVE:38 1.00", "NEC_CD-ROM_DRIVE38_1.00", BUS_TYPE_SCSI }, + { "NEC", "CD-ROM DRIVE:75", "1.03", "NEC CD-ROM DRIVE:75 1.03", "NEC_CD-ROM_DRIVE75_1.03", BUS_TYPE_SCSI }, + { "NEC", "CD-ROM DRIVE:77", "1.06", "NEC CD-ROM DRIVE:77 1.06", "NEC_CD-ROM_DRIVE77_1.06", BUS_TYPE_SCSI }, + { "NEC", "CD-ROM DRIVE:211", "1.00", "NEC CD-ROM DRIVE:211 1.00", "NEC_CD-ROM_DRIVE211_1.00", BUS_TYPE_SCSI }, + { "NEC", "CD-ROM DRIVE:464", "1.05", "NEC CD-ROM DRIVE:464 1.05", "NEC_CD-ROM_DRIVE464_1.05", BUS_TYPE_SCSI }, + { "SONY", "CD-ROM CDU-541", "1.0i", "SONY CD-ROM CDU-541 1.0i", "SONY_CD-ROM_CDU-541_1.0i", BUS_TYPE_SCSI }, + { "SONY", "CD-ROM CDU-561", "1.8k", "SONY CD-ROM CDU-561 1.8k", "SONY_CD-ROM_CDU-561_1.8k", BUS_TYPE_SCSI }, + { "SONY", "CD-ROM CDU-76S", "1.00", "SONY CD-ROM CDU-76S 1.00", "SONY_CD-ROM_CDU-76S_1.00", BUS_TYPE_SCSI }, + { "PHILIPS", "CDD2600", "1.07", "PHILIPS CDD2600 1.07", "PHILIPS_CDD2600_1.07", BUS_TYPE_SCSI }, + { "PIONEER", "CD-ROM DRM-604X", "2403", "PIONEER CD-ROM DRM-604X 2403", "PIONEER_CD-ROM_DRM-604X_2403", BUS_TYPE_SCSI }, + { "PLEXTOR", "CD-ROM PX-32TS", "1.03", "PLEXTOR CD-ROM PX-32TS 1.03", "PLEXTOR_CD-ROM_PX-32TS_1.03", BUS_TYPE_SCSI }, + { "TEAC", "CD 50", "1.00", "TEAC CD 50 1.00", "TEAC_CD_50_1.00", BUS_TYPE_SCSI }, + { "TEAC", "CD-ROM R55S", "1.0R", "TEAC CD-ROM R55S 1.0R", "TEAC_CD-ROM_R55S_1.0R", BUS_TYPE_SCSI }, + { "TEXEL", "CD-ROM DM-XX24", "1.00", "TEXEL CD-ROM DM-XX24 1.00", "TEXEL_CD-ROM_DM-XX24_1.00", BUS_TYPE_SCSI }, + { "TOSHIBA", "CD-ROM DRIVE:XM", "3433", "TOSHIBA CD-ROM DRIVE:XM 3433", "TOSHIBA_CD-ROM_DRIVEXM_3433", BUS_TYPE_SCSI }, + { "TOSHIBA", "CD-ROM XM-3201B", "3232", "TOSHIBA CD-ROM XM-3201B 3232", "TOSHIBA_CD-ROM_XM-3201B_3232", BUS_TYPE_SCSI }, + { "TOSHIBA", "CD-ROM XM-3301TA", "0272", "TOSHIBA CD-ROM XM-3301TA 0272", "TOSHIBA_CD-ROM_XM-3301TA_0272", BUS_TYPE_SCSI }, + { "TOSHIBA", "CD-ROM XM-5701TA", "3136", "TOSHIBA CD-ROM XM-5701TA 3136", "TOSHIBA_CD-ROM_XM-5701TA_3136", BUS_TYPE_SCSI }, + { "TOSHIBA", "DVD-ROM SD-M1401", "1008", "TOSHIBA DVD-ROM SD-M1401 1008", "TOSHIBA_DVD-ROM_SD-M1401_1008", BUS_TYPE_SCSI }, + { "", "", "", "", "", BUS_TYPE_NONE }, +}; /* To shut up the GCC compilers. */ struct cdrom; - -typedef struct { - uint8_t attr, track, - index, - abs_m, abs_s, abs_f, - rel_m, rel_s, rel_f; +typedef struct subchannel_t { + uint8_t attr; + uint8_t track; + uint8_t index; + uint8_t abs_m; + uint8_t abs_s; + uint8_t abs_f; + uint8_t rel_m; + uint8_t rel_s; + uint8_t rel_f; } subchannel_t; -typedef struct { - int number; - uint8_t attr, m, s, f; +typedef struct track_info_t { + int number; + uint8_t attr; + uint8_t m; + uint8_t s; + uint8_t f; } track_info_t; /* Define the various CD-ROM drive operations (ops). */ -typedef struct { - void (*get_tracks)(struct cdrom *dev, int *first, int *last); - void (*get_track_info)(struct cdrom *dev, uint32_t track, int end, track_info_t *ti); - void (*get_subchannel)(struct cdrom *dev, uint32_t lba, subchannel_t *subc); - int (*is_track_pre)(struct cdrom *dev, uint32_t lba); - int (*sector_size)(struct cdrom *dev, uint32_t lba); - int (*read_sector)(struct cdrom *dev, int type, uint8_t *b, uint32_t lba); - int (*track_type)(struct cdrom *dev, uint32_t lba); - void (*exit)(struct cdrom *dev); +typedef struct cdrom_ops_t { + void (*get_tracks)(struct cdrom *dev, int *first, int *last); + void (*get_track_info)(struct cdrom *dev, uint32_t track, int end, track_info_t *ti); + void (*get_subchannel)(struct cdrom *dev, uint32_t lba, subchannel_t *subc); + int (*is_track_pre)(struct cdrom *dev, uint32_t lba); + int (*sector_size)(struct cdrom *dev, uint32_t lba); + int (*read_sector)(struct cdrom *dev, int type, uint8_t *b, uint32_t lba); + int (*track_type)(struct cdrom *dev, uint32_t lba); + void (*exit)(struct cdrom *dev); } cdrom_ops_t; typedef struct cdrom { uint8_t id; union { - uint8_t res, res0, /* Reserved for other ID's. */ - res1, - ide_channel, scsi_device_id; + uint8_t res; + uint8_t res0; /* Reserved for other ID's. */ + uint8_t res1; + uint8_t ide_channel; + uint8_t scsi_device_id; }; - uint8_t bus_type, /* 0 = ATAPI, 1 = SCSI */ - bus_mode, /* Bit 0 = PIO suported; - Bit 1 = DMA supportd. */ - cd_status, /* Struct variable reserved for - media status. */ - speed, cur_speed; + uint8_t bus_type; /* 0 = ATAPI, 1 = SCSI */ + uint8_t bus_mode; /* Bit 0 = PIO suported; + Bit 1 = DMA supportd. */ + uint8_t cd_status; /* Struct variable reserved for + media status. */ + uint8_t speed; + uint8_t cur_speed; - FILE* img_fp; + int is_dir; void *priv; - char image_path[1024], - prev_image_path[1024]; + char image_path[1024]; + char prev_image_path[1024]; - uint32_t sound_on, cdrom_capacity, - pad, seek_pos, - seek_diff, cd_end; + char *image_history[CD_IMAGE_HISTORY]; - int host_drive, prev_host_drive, - cd_buflen, noplay; + uint32_t sound_on; + uint32_t cdrom_capacity; + uint32_t seek_pos; + uint32_t seek_diff; + uint32_t cd_end; + uint32_t type; - const cdrom_ops_t *ops; + int host_drive; + int prev_host_drive; + int cd_buflen; + int audio_op; + int sony_msf; - void *image; + const cdrom_ops_t *ops; - void (*insert)(void *p); - void (*close)(void *p); - uint32_t (*get_volume)(void *p, int channel); - uint32_t (*get_channel)(void *p, int channel); + void *image; + + void (*insert)(void *priv); + void (*close)(void *priv); + uint32_t (*get_volume)(void *p, int channel); + uint32_t (*get_channel)(void *p, int channel); int16_t cd_buffer[BUF_SIZE]; } cdrom_t; +extern cdrom_t cdrom[CDROM_NUM]; -extern cdrom_t cdrom[CDROM_NUM]; +extern char *cdrom_getname(int type); -extern int cdrom_lba_to_msf_accurate(int lba); -extern double cdrom_seek_time(cdrom_t *dev); -extern void cdrom_stop(cdrom_t *dev); -extern int cdrom_is_pre(cdrom_t *dev, uint32_t lba); -extern int cdrom_audio_callback(cdrom_t *dev, int16_t *output, int len); -extern uint8_t cdrom_audio_play(cdrom_t *dev, uint32_t pos, uint32_t len, int ismsf); -extern uint8_t cdrom_audio_track_search(cdrom_t *dev, uint32_t pos, int type, uint8_t playbit); -extern uint8_t cdrom_toshiba_audio_play(cdrom_t *dev, uint32_t pos, int type); -extern void cdrom_audio_pause_resume(cdrom_t *dev, uint8_t resume); -extern uint8_t cdrom_get_current_subchannel(cdrom_t *dev, uint8_t *b, int msf); -extern uint8_t cdrom_get_current_subcodeq_playstatus(cdrom_t *dev, uint8_t *b); -extern int cdrom_read_toc(cdrom_t *dev, unsigned char *b, int type, - unsigned char start_track, int msf, int max_len); -extern void cdrom_get_track_buffer(cdrom_t *dev, uint8_t *buf); -extern int cdrom_readsector_raw(cdrom_t *dev, uint8_t *buffer, int sector, int ismsf, - int cdrom_sector_type, int cdrom_sector_flags, int *len); -extern void cdrom_read_disc_info_toc(cdrom_t *dev, unsigned char *b, unsigned char track, int type); +extern char *cdrom_get_internal_name(int type); +extern int cdrom_get_from_internal_name(char *s); +extern void cdrom_set_type(int model, int type); +extern int cdrom_get_type(int model); -extern void cdrom_seek(cdrom_t *dev, uint32_t pos); +extern int cdrom_lba_to_msf_accurate(int lba); +extern double cdrom_seek_time(cdrom_t *dev); +extern void cdrom_stop(cdrom_t *dev); +extern int cdrom_is_pre(cdrom_t *dev, uint32_t lba); +extern int cdrom_audio_callback(cdrom_t *dev, int16_t *output, int len); +extern uint8_t cdrom_audio_play(cdrom_t *dev, uint32_t pos, uint32_t len, int ismsf); +extern uint8_t cdrom_audio_track_search(cdrom_t *dev, uint32_t pos, int type, uint8_t playbit); +extern uint8_t cdrom_audio_track_search_pioneer(cdrom_t *dev, uint32_t pos, uint8_t playbit); +extern uint8_t cdrom_audio_play_pioneer(cdrom_t *dev, uint32_t pos); +extern uint8_t cdrom_audio_play_toshiba(cdrom_t *dev, uint32_t pos, int type); +extern void cdrom_audio_pause_resume(cdrom_t *dev, uint8_t resume); +extern uint8_t cdrom_audio_scan(cdrom_t *dev, uint32_t pos, int type); +extern uint8_t cdrom_get_audio_status_pioneer(cdrom_t *dev, uint8_t *b); +extern uint8_t cdrom_get_audio_status_sony(cdrom_t *dev, uint8_t *b, int msf); +extern uint8_t cdrom_get_current_subchannel(cdrom_t *dev, uint8_t *b, int msf); +extern void cdrom_get_current_subchannel_sony(cdrom_t *dev, uint8_t *b, int msf); +extern void cdrom_get_current_subcodeq(cdrom_t *dev, uint8_t *b); +extern uint8_t cdrom_get_current_subcodeq_playstatus(cdrom_t *dev, uint8_t *b); +extern int cdrom_read_toc(cdrom_t *dev, unsigned char *b, int type, + unsigned char start_track, int msf, int max_len); +extern int cdrom_read_toc_sony(cdrom_t *dev, unsigned char *b, unsigned char start_track, int msf, int max_len); +extern void cdrom_get_track_buffer(cdrom_t *dev, uint8_t *buf); +extern void cdrom_get_q(cdrom_t *dev, uint8_t *buf, int *curtoctrk, uint8_t mode); +extern uint8_t cdrom_mitsumi_audio_play(cdrom_t *dev, uint32_t pos, uint32_t len); +extern int cdrom_readsector_raw(cdrom_t *dev, uint8_t *buffer, int sector, int ismsf, + int cdrom_sector_type, int cdrom_sector_flags, int *len, uint8_t vendor_type); +extern uint8_t cdrom_read_disc_info_toc(cdrom_t *dev, unsigned char *b, unsigned char track, int type); -extern void cdrom_close_handler(uint8_t id); -extern void cdrom_insert(uint8_t id); -extern void cdrom_eject(uint8_t id); -extern void cdrom_reload(uint8_t id); +extern void cdrom_seek(cdrom_t *dev, uint32_t pos, uint8_t vendor_type); -extern int cdrom_image_open(cdrom_t *dev, const char *fn); -extern void cdrom_image_close(cdrom_t *dev); -extern void cdrom_image_reset(cdrom_t *dev); +extern void cdrom_close_handler(uint8_t id); +extern void cdrom_insert(uint8_t id); +extern void cdrom_eject(uint8_t id); +extern void cdrom_reload(uint8_t id); -extern void cdrom_update_cdb(uint8_t *cdb, int lba_pos, - int number_of_blocks); +extern int cdrom_image_open(cdrom_t *dev, const char *fn); +extern void cdrom_image_close(cdrom_t *dev); +extern void cdrom_image_reset(cdrom_t *dev); -extern int find_cdrom_for_scsi_id(uint8_t scsi_id); +extern void cdrom_ioctl_eject(void); +extern void cdrom_ioctl_load(void); +extern int cdrom_ioctl_open(cdrom_t *dev, const char d); -extern void cdrom_close(void); -extern void cdrom_global_init(void); -extern void cdrom_global_reset(void); -extern void cdrom_hard_reset(void); -extern void scsi_cdrom_drive_reset(int c); +extern void cdrom_update_cdb(uint8_t *cdb, int lba_pos, + int number_of_blocks); + +extern int find_cdrom_for_scsi_id(uint8_t scsi_id); + +extern void cdrom_close(void); +extern void cdrom_global_init(void); +extern void cdrom_global_reset(void); +extern void cdrom_hard_reset(void); +extern void scsi_cdrom_drive_reset(int c); #ifdef __cplusplus } #endif - -#endif /*EMU_CDROM_H*/ +#endif /*EMU_CDROM_H*/ diff --git a/src/include/86box/cdrom_image.h b/src/include/86box/cdrom_image.h index 415956e56..c848af50d 100644 --- a/src/include/86box/cdrom_image.h +++ b/src/include/86box/cdrom_image.h @@ -1,6 +1,20 @@ -/* Copyright holders: RichardG867, Tenshi - see COPYING for more details -*/ +/* + * 86Box A hypervisor and IBM PC system emulator that specializes in + * running old operating systems and software designed for IBM + * PC systems and compatibles from 1981 through fairly recent + * system designs based on the PCI bus. + * + * This file is part of the 86Box distribution. + * + * CD-ROM image file handling module header, translated to C + * from cdrom_dosbox.h. + * + * Authors: RichardG, + * Miran Grca, + * + * Copyright 2016-2022 RichardG. + * Copyright 2016-2022 Miran Grca. + */ #ifndef CDROM_IMAGE_H #define CDROM_IMAGE_H @@ -11,16 +25,16 @@ extern "C" { #endif -extern int image_open(uint8_t id, wchar_t *fn); +extern int image_open(uint8_t id, wchar_t *fn); extern void image_reset(uint8_t id); extern void image_close(uint8_t id); -void update_status_bar_icon_state(int tag, int state); +void update_status_bar_icon_state(int tag, int state); extern void cdrom_set_null_handler(uint8_t id); #ifdef __cplusplus } #endif -#endif /* ! CDROM_IMAGE_H */ +#endif /*CDROM_IMAGE_H*/ diff --git a/src/include/86box/cdrom_image_backend.h b/src/include/86box/cdrom_image_backend.h index 74be1df69..39faf9f33 100644 --- a/src/include/86box/cdrom_image_backend.h +++ b/src/include/86box/cdrom_image_backend.h @@ -1,96 +1,105 @@ /* - * 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. + * 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. + * This file is part of the 86Box distribution. * - * CD-ROM image file handling module header , translated to C - * from cdrom_dosbox.h. + * CD-ROM image file handling module header , translated to C + * from cdrom_dosbox.h. * + * Authors: Miran Grca, + * Fred N. van Kempen, + * The DOSBox Team, * - * - * Authors: Miran Grca, - * Fred N. van Kempen, - * The DOSBox Team, - * - * Copyright 2016-2020 Miran Grca. - * Copyright 2017-2020 Fred N. van Kempen. - * Copyright 2002-2020 The DOSBox Team. + * Copyright 2016-2020 Miran Grca. + * Copyright 2017-2020 Fred N. van Kempen. + * Copyright 2002-2020 The DOSBox Team. */ #ifndef CDROM_IMAGE_BACKEND_H #define CDROM_IMAGE_BACKEND_H -#define RAW_SECTOR_SIZE 2352 -#define COOKED_SECTOR_SIZE 2048 +#define RAW_SECTOR_SIZE 2352 +#define COOKED_SECTOR_SIZE 2048 -#define DATA_TRACK 0x14 -#define AUDIO_TRACK 0x10 - -#define CD_FPS 75 -#define FRAMES_TO_MSF(f, M,S,F) { \ - uint64_t value = f; \ - *(F) = (value%CD_FPS) & 0xff; \ - value /= CD_FPS; \ - *(S) = (value%60) & 0xff; \ - value /= 60; \ - *(M) = value & 0xff; \ -} -#define MSF_TO_FRAMES(M, S, F) ((M)*60*CD_FPS+(S)*CD_FPS+(F)) +#define DATA_TRACK 0x14 +#define AUDIO_TRACK 0x10 +#define CD_FPS 75 +#define FRAMES_TO_MSF(f, M, S, F) \ + { \ + uint64_t value = f; \ + *(F) = (value % CD_FPS) & 0xff; \ + value /= CD_FPS; \ + *(S) = (value % 60) & 0xff; \ + value /= 60; \ + *(M) = value & 0xff; \ + } +#define MSF_TO_FRAMES(M, S, F) ((M) *60 * CD_FPS + (S) *CD_FPS + (F)) typedef struct SMSF { - uint16_t min; - uint8_t sec; - uint8_t fr; + uint16_t min; + uint8_t sec; + uint8_t fr; } TMSF; /* Track file struct. */ -typedef struct { - int (*read)(void *p, uint8_t *buffer, uint64_t seek, size_t count); - uint64_t (*get_length)(void *p); - void (*close)(void *p); +typedef struct track_file_t { + int (*read)(void *priv, uint8_t *buffer, uint64_t seek, size_t count); + uint64_t (*get_length)(void *priv); + void (*close)(void *priv); - char fn[260]; - FILE *file; + char fn[260]; + FILE *fp; + void *priv; } track_file_t; -typedef struct { - int number, track_number, attr, sector_size, - mode2, form, pre, pad; - uint64_t start, length, - skip; - track_file_t *file; +typedef struct track_t { + int number; + int track_number; + int attr; + int sector_size; + int mode2; + int form; + int pre; + int pad; + uint64_t start; + uint64_t length; + uint64_t skip; + track_file_t *file; } track_t; -typedef struct { - int tracks_num; - track_t *tracks; +typedef struct cd_img_t { + int tracks_num; + track_t *tracks; } cd_img_t; - /* Binary file functions. */ -extern void cdi_close(cd_img_t *cdi); -extern int cdi_set_device(cd_img_t *cdi, const char *path); -extern int cdi_get_audio_tracks(cd_img_t *cdi, int *st_track, int *end, TMSF *lead_out); -extern int cdi_get_audio_tracks_lba(cd_img_t *cdi, int *st_track, int *end, uint32_t *lead_out); -extern int cdi_get_audio_track_pre(cd_img_t *cdi, int track); -extern int cdi_get_audio_track_info(cd_img_t *cdi, int end, int track, int *track_num, TMSF *start, uint8_t *attr); -extern int cdi_get_audio_track_info_lba(cd_img_t *cdi, int end, int track, int *track_num, uint32_t *start, uint8_t *attr); -extern int cdi_get_track(cd_img_t *cdi, uint32_t sector); -extern int cdi_get_audio_sub(cd_img_t *cdi, uint32_t sector, uint8_t *attr, uint8_t *track, uint8_t *index, TMSF *rel_pos, TMSF *abs_pos); -extern int cdi_read_sector(cd_img_t *cdi, uint8_t *buffer, int raw, uint32_t sector); -extern int cdi_read_sectors(cd_img_t *cdi, uint8_t *buffer, int raw, uint32_t sector, uint32_t num); -extern int cdi_read_sector_sub(cd_img_t *cdi, uint8_t *buffer, uint32_t sector); -extern int cdi_get_sector_size(cd_img_t *cdi, uint32_t sector); -extern int cdi_is_mode2(cd_img_t *cdi, uint32_t sector); -extern int cdi_get_mode2_form(cd_img_t *cdi, uint32_t sector); -extern int cdi_load_iso(cd_img_t *cdi, const char *filename); -extern int cdi_load_cue(cd_img_t *cdi, const char *cuefile); -extern int cdi_has_data_track(cd_img_t *cdi); -extern int cdi_has_audio_track(cd_img_t *cdi); +extern void cdi_close(cd_img_t *cdi); +extern int cdi_set_device(cd_img_t *cdi, const char *path); +extern int cdi_get_audio_tracks(cd_img_t *cdi, int *st_track, int *end, TMSF *lead_out); +extern int cdi_get_audio_tracks_lba(cd_img_t *cdi, int *st_track, int *end, uint32_t *lead_out); +extern int cdi_get_audio_track_pre(cd_img_t *cdi, int track); +extern int cdi_get_audio_track_info(cd_img_t *cdi, int end, int track, int *track_num, TMSF *start, uint8_t *attr); +extern int cdi_get_audio_track_info_lba(cd_img_t *cdi, int end, int track, int *track_num, uint32_t *start, uint8_t *attr); +extern int cdi_get_track(cd_img_t *cdi, uint32_t sector); +extern int cdi_get_audio_sub(cd_img_t *cdi, uint32_t sector, uint8_t *attr, uint8_t *track, uint8_t *index, TMSF *rel_pos, TMSF *abs_pos); +extern int cdi_read_sector(cd_img_t *cdi, uint8_t *buffer, int raw, uint32_t sector); +extern int cdi_read_sectors(cd_img_t *cdi, uint8_t *buffer, int raw, uint32_t sector, uint32_t num); +extern int cdi_read_sector_sub(cd_img_t *cdi, uint8_t *buffer, uint32_t sector); +extern int cdi_get_sector_size(cd_img_t *cdi, uint32_t sector); +extern int cdi_is_mode2(cd_img_t *cdi, uint32_t sector); +extern int cdi_get_mode2_form(cd_img_t *cdi, uint32_t sector); +extern int cdi_load_iso(cd_img_t *cdi, const char *filename); +extern int cdi_load_cue(cd_img_t *cdi, const char *cuefile); +extern int cdi_has_data_track(cd_img_t *cdi); +extern int cdi_has_audio_track(cd_img_t *cdi); +/* Virtual ISO functions. */ +extern int viso_read(void *priv, uint8_t *buffer, uint64_t seek, size_t count); +extern uint64_t viso_get_length(void *priv); +extern void viso_close(void *priv); +extern track_file_t *viso_init(const char *dirname, int *error); - -#endif /* ! CDROM_IMAGE_BACKEND_H */ +#endif /*CDROM_IMAGE_BACKEND_H*/ diff --git a/src/include/86box/cdrom_interface.h b/src/include/86box/cdrom_interface.h new file mode 100644 index 000000000..081f758f6 --- /dev/null +++ b/src/include/86box/cdrom_interface.h @@ -0,0 +1,31 @@ +/* + * 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. + * + * Definitions for the common CD-ROM interface controller handler. + * + * + * + * Authors: TheCollector1995 + * + * Copyright 2022 TheCollector1995. + */ +#ifndef EMU_CDROM_INTERFACE_H +#define EMU_CDROM_INTERFACE_H + +extern int cdrom_interface_current; + +extern void cdrom_interface_reset(void); + +extern const char *cdrom_interface_get_internal_name(int cdinterface); +extern int cdrom_interface_get_from_internal_name(char *s); +extern int cdrom_interface_has_config(int cdinterface); +extern const device_t *cdrom_interface_get_device(int cdinterface); +extern int cdrom_interface_get_flags(int cdinterface); +extern int cdrom_interface_available(int cdinterface); + +#endif /*EMU_CDROM_INTERFACE_H*/ diff --git a/src/include/86box/cdrom_mitsumi.h b/src/include/86box/cdrom_mitsumi.h new file mode 100644 index 000000000..0b8a3a250 --- /dev/null +++ b/src/include/86box/cdrom_mitsumi.h @@ -0,0 +1,22 @@ +/* + * 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. + * + * Mitsumi CD-ROM emulation for the ISA bus. + * + * + * + * Authors: Miran Grca, + * + * Copyright 2022 Miran Grca. + */ +#ifndef CDROM_MITSUMI_H +#define CDROM_MITSUMI_H + +extern const device_t mitsumi_cdrom_device; + +#endif /*CDROM_MITSUMI_H*/ diff --git a/src/include/86box/chipset.h b/src/include/86box/chipset.h index edeaa3bc1..95440a172 100644 --- a/src/include/86box/chipset.h +++ b/src/include/86box/chipset.h @@ -1,173 +1,183 @@ /* - * 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. + * 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. + * This file is part of the 86Box distribution. * - * Handling of the emulated chipsets. + * Handling of the emulated chipsets. * * * - * Authors: Miran Grca, + * Authors: Miran Grca, * - * Copyright 2019,2020 Miran Grca. + * Copyright 2019-2020 Miran Grca. */ #ifndef EMU_CHIPSET_H -# define EMU_CHIPSET_H - +#define EMU_CHIPSET_H /* ACC */ -extern const device_t acc2168_device; +extern const device_t acc2168_device; /* ALi */ -extern const device_t ali1217_device; -extern const device_t ali1429_device; -extern const device_t ali1429g_device; -extern const device_t ali1489_device; -extern const device_t ali1531_device; -extern const device_t ali1541_device; -extern const device_t ali1543_device; -extern const device_t ali1543c_device; -extern const device_t ali1621_device; -extern const device_t ali6117d_device; +extern const device_t ali1217_device; +extern const device_t ali1429_device; +extern const device_t ali1429g_device; +extern const device_t ali1435_device; +extern const device_t ali1489_device; +extern const device_t ali1531_device; +extern const device_t ali1541_device; +extern const device_t ali1543_device; +extern const device_t ali1543c_device; +extern const device_t ali1621_device; +extern const device_t ali6117d_device; /* AMD */ -extern const device_t amd640_device; +extern const device_t amd640_device; + +/* Compaq */ +extern const device_t compaq_386_device; /* Contaq/Cypress */ -extern const device_t contaq_82c596a_device; -extern const device_t contaq_82c597_device; +extern const device_t contaq_82c596a_device; +extern const device_t contaq_82c597_device; /* C&T */ -extern const device_t ct_82c100_device; -extern const device_t neat_device; -extern const device_t scat_device; -extern const device_t scat_4_device; -extern const device_t scat_sx_device; -extern const device_t cs8230_device; -extern const device_t cs4031_device; +extern const device_t ct_82c100_device; +extern const device_t neat_device; +extern const device_t scat_device; +extern const device_t scat_4_device; +extern const device_t scat_sx_device; +extern const device_t cs8230_device; +extern const device_t cs4031_device; /* G2 */ -extern const device_t gc100_device; -extern const device_t gc100a_device; +extern const device_t gc100_device; +extern const device_t gc100a_device; /* Headland */ -extern const device_t headland_gc10x_device; -extern const device_t headland_ht18a_device; -extern const device_t headland_ht18b_device; -extern const device_t headland_ht18c_device; +extern const device_t headland_gc10x_device; +extern const device_t headland_gc113_device; +extern const device_t headland_ht18a_device; +extern const device_t headland_ht18b_device; +extern const device_t headland_ht18c_device; +extern const device_t headland_ht21c_d_device; +extern const device_t headland_ht21e_device; /* IMS */ -extern const device_t ims8848_device; +extern const device_t ims8848_device; /* Intel */ -extern const device_t intel_82335_device; -extern const device_t i420ex_device; -extern const device_t i420ex_ide_device; -extern const device_t i420tx_device; -extern const device_t i420zx_device; -extern const device_t i430lx_device; -extern const device_t i430nx_device; -extern const device_t i430fx_device; -extern const device_t i430fx_old_device; -extern const device_t i430fx_rev02_device; -extern const device_t i430hx_device; -extern const device_t i430vx_device; -extern const device_t i430tx_device; -extern const device_t i440fx_device; -extern const device_t i440lx_device; -extern const device_t i440ex_device; -extern const device_t i440bx_device; -extern const device_t i440bx_no_agp_device; -extern const device_t i440gx_device; -extern const device_t i440zx_device; -extern const device_t i450kx_device; +extern const device_t intel_82335_device; +extern const device_t i420ex_device; +extern const device_t i420ex_ide_device; +extern const device_t i420tx_device; +extern const device_t i420zx_device; +extern const device_t i430lx_device; +extern const device_t i430nx_device; +extern const device_t i430fx_device; +extern const device_t i430fx_old_device; +extern const device_t i430fx_rev02_device; +extern const device_t i430hx_device; +extern const device_t i430vx_device; +extern const device_t i430tx_device; +extern const device_t i440fx_device; +extern const device_t i440lx_device; +extern const device_t i440ex_device; +extern const device_t i440bx_device; +extern const device_t i440bx_no_agp_device; +extern const device_t i440gx_device; +extern const device_t i440zx_device; +extern const device_t i450kx_device; -extern const device_t sio_device; -extern const device_t sio_zb_device; +extern const device_t sio_device; +extern const device_t sio_zb_device; -extern const device_t piix_device; -extern const device_t piix_old_device; -extern const device_t piix_rev02_device; -extern const device_t piix3_device; -extern const device_t piix3_ioapic_device; -extern const device_t piix4_device; -extern const device_t piix4e_device; -extern const device_t slc90e66_device; +extern const device_t piix_device; +extern const device_t piix_no_mirq_device; +extern const device_t piix_old_device; +extern const device_t piix_rev02_device; +extern const device_t piix3_device; +extern const device_t piix3_ioapic_device; +extern const device_t piix4_device; +extern const device_t piix4e_device; +extern const device_t slc90e66_device; -extern const device_t ioapic_device; +extern const device_t ioapic_device; /* OPTi */ -extern const device_t opti283_device; -extern const device_t opti291_device; -extern const device_t opti493_device; -extern const device_t opti495_device; -extern const device_t opti802g_device; -extern const device_t opti822_device; -extern const device_t opti895_device; +extern const device_t opti283_device; +extern const device_t opti291_device; +extern const device_t opti493_device; +extern const device_t opti495_device; +extern const device_t opti601_device; +extern const device_t opti602_device; +extern const device_t opti802g_device; +extern const device_t opti802g_pci_device; +extern const device_t opti822_device; +extern const device_t opti895_device; -extern const device_t opti5x7_device; +extern const device_t opti5x7_device; +extern const device_t opti5x7_pci_device; /* SiS */ -extern const device_t rabbit_device; -extern const device_t sis_85c401_device; -extern const device_t sis_85c460_device; -extern const device_t sis_85c461_device; -extern const device_t sis_85c471_device; -extern const device_t sis_85c496_device; -extern const device_t sis_85c496_ls486e_device; -extern const device_t sis_85c50x_device; -extern const device_t sis_5511_device; -extern const device_t sis_5571_device; +extern const device_t rabbit_device; +extern const device_t sis_85c401_device; +extern const device_t sis_85c460_device; +extern const device_t sis_85c461_device; +extern const device_t sis_85c471_device; +extern const device_t sis_85c496_device; +extern const device_t sis_85c496_ls486e_device; +extern const device_t sis_85c50x_device; +extern const device_t sis_5511_device; +extern const device_t sis_5571_device; /* ST */ -extern const device_t stpc_client_device; -extern const device_t stpc_consumer2_device; -extern const device_t stpc_elite_device; -extern const device_t stpc_atlas_device; -extern const device_t stpc_serial_device; -extern const device_t stpc_lpt_device; +extern const device_t stpc_client_device; +extern const device_t stpc_consumer2_device; +extern const device_t stpc_elite_device; +extern const device_t stpc_atlas_device; +extern const device_t stpc_serial_device; +extern const device_t stpc_lpt_device; /* UMC */ -extern const device_t umc_um82c49x_device; -extern const device_t umc_8886f_device; -extern const device_t umc_8886af_device; -extern const device_t umc_hb4_device; +extern const device_t umc_8886f_device; +extern const device_t umc_8886af_device; +extern const device_t umc_hb4_device; /* VIA */ -extern const device_t via_vt82c49x_device; -extern const device_t via_vt82c49x_pci_device; -extern const device_t via_vt82c49x_pci_ide_device; -extern const device_t via_vt82c505_device; -extern const device_t via_vpx_device; -extern const device_t via_vp3_device; -extern const device_t via_mvp3_device; -extern const device_t via_apro_device; -extern const device_t via_apro133_device; -extern const device_t via_apro133a_device; -extern const device_t via_vt8601_device; -extern const device_t via_vt82c586b_device; -extern const device_t via_vt82c596a_device; -extern const device_t via_vt82c596b_device; -extern const device_t via_vt82c686a_device; -extern const device_t via_vt82c686b_device; -extern const device_t via_vt8231_device; +extern const device_t via_vt82c49x_device; +extern const device_t via_vt82c49x_pci_device; +extern const device_t via_vt82c49x_pci_ide_device; +extern const device_t via_vt82c505_device; +extern const device_t via_vpx_device; +extern const device_t via_vp3_device; +extern const device_t via_mvp3_device; +extern const device_t via_apro_device; +extern const device_t via_apro133_device; +extern const device_t via_apro133a_device; +extern const device_t via_vt8601_device; +extern const device_t via_vt82c586b_device; +extern const device_t via_vt82c596a_device; +extern const device_t via_vt82c596b_device; +extern const device_t via_vt82c686a_device; +extern const device_t via_vt82c686b_device; +extern const device_t via_vt8231_device; /* VLSI */ -extern const device_t vl82c480_device; -extern const device_t vl82c486_device; -extern const device_t vlsi_scamp_device; +extern const device_t vl82c480_device; +extern const device_t vl82c486_device; +extern const device_t vlsi_scamp_device; /* WD */ -extern const device_t wd76c10_device; +extern const device_t wd76c10_device; /* Miscellaneous Hardware */ -extern const device_t phoenix_486_jumper_device; -extern const device_t phoenix_486_jumper_pci_device; +extern const device_t phoenix_486_jumper_device; +extern const device_t phoenix_486_jumper_pci_device; #if defined(DEV_BRANCH) && defined(USE_OLIVETTI) -extern const device_t olivetti_eva_device; +extern const device_t olivetti_eva_device; #endif -#endif /*EMU_CHIPSET_H*/ +#endif /*EMU_CHIPSET_H*/ diff --git a/src/include/86box/clock.h b/src/include/86box/clock.h index 7d2be9f05..10155eabc 100644 --- a/src/include/86box/clock.h +++ b/src/include/86box/clock.h @@ -1,21 +1,21 @@ /* - * 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. + * 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. + * This file is part of the 86Box distribution. * - * Definitions for clock generator chips. + * Definitions for clock generator chips. * * * - * Authors: RichardG, + * Authors: RichardG, * - * Copyright 2020 RichardG. + * Copyright 2020 RichardG. */ #ifndef EMU_CLOCK_H -# define EMU_CLOCK_H +#define EMU_CLOCK_H /* clock_ics9xxx.c */ enum { @@ -54,9 +54,7 @@ enum { ICS9xxx_MAX }; - /* clock_ics9xxx.c */ -extern device_t *ics9xxx_get(uint8_t model); +extern device_t *ics9xxx_get(uint8_t model); - -#endif /*EMU_CLOCK_H*/ +#endif /*EMU_CLOCK_H*/ diff --git a/src/include/86box/config.h b/src/include/86box/config.h index b630d0c80..80c987162 100644 --- a/src/include/86box/config.h +++ b/src/include/86box/config.h @@ -1,169 +1,171 @@ /* - * 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. + * 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. + * This file is part of the 86Box distribution. * - * Configuration file handler header. + * Configuration file handler header. * * * - * Authors: Sarah Walker, - * Miran Grca, - * Fred N. van Kempen, - * Overdoze, + * Authors: Sarah Walker, + * Miran Grca, + * Fred N. van Kempen, + * Overdoze, * - * Copyright 2008-2017 Sarah Walker. - * Copyright 2016,2017 Miran Grca. - * Copyright 2017 Fred N. van Kempen. + * Copyright 2008-2017 Sarah Walker. + * Copyright 2016-2017 Miran Grca. + * Copyright 2017 Fred N. van Kempen. */ #ifndef EMU_CONFIG_H -# define EMU_CONFIG_H - +#define EMU_CONFIG_H #ifdef __cplusplus extern "C" { #endif #if 0 -typedef struct { - uint8_t id, - uint8_t bus_type, /* Bus type: IDE, SCSI, etc. */ - bus, :4, /* ID of the bus (for example, for IDE, - 0 = primary, 1 = secondary, etc. */ - bus_id, :4, /* ID of the device on the bus */ - uint8_t type, /* Type flags, interpretation depends - on the device */ - uint8_t is_image; /* This is only used for CD-ROM: - 0 = Image; - 1 = Host drive */ +typedef struct storage_cfg_t { + uint8_t id; + uint8_t bus_type; /* Bus type: IDE, SCSI, etc. */ + uint8_t bus : 4; /* ID of the bus (for example, for IDE, + 0 = primary, 1 = secondary, etc. */ + uint8_t bus_id : 4; /* ID of the device on the bus */ + uint8_t type; /* Type flags, interpretation depends + on the device */ + uint8_t is_image; /* This is only used for CD-ROM: + 0 = Image; + 1 = Host drive */ - wchar_t path[1024]; /* Name of current image file or - host drive */ + wchar_t path[1024]; /* Name of current image file or + host drive */ - uint32_t spt, /* Physical geometry parameters */ - hpc, - tracks; + uint32_t spt; /* Physical geometry parameters */ + uint32_t hpc; + uint32_t tracks; } storage_cfg_t; -typedef struct { +typedef struct config_t { /* General configuration */ - int vid_resize, /* Window is resizable or not */ - vid_renderer, /* Renderer */ - vid_fullscreen_scale, /* Full screen scale type */ - vid_fullscreen_start, /* Start emulator in full screen */ - vid_force_43, /* Force 4:3 display ratio in windowed mode */ - vid_scale, /* Windowed mode scale */ - vid_overscan, /* EGA/(S)VGA overscan enabled */ - vid_cga_contrast, /* CGA alternate contrast enabled */ - vid_grayscale, /* Video is grayscale */ - vid_grayscale_type, /* Video grayscale type */ - vid_invert_display, /* Invert display */ - rctrl_is_lalt, /* Right CTRL is left ALT */ - update_icons, /* Update status bar icons */ - window_remember, /* Remember window position and size */ - window_w, /* Window coordinates */ - window_h, - window_x, - window_y, - sound_gain; /* Sound gain */ -#ifdef USE_LANGUAGE - uint16_t language_id; /* Language ID (0x0409 = English (US)) */ -#endif + int vid_resize; /* Window is resizable or not */ + int vid_renderer; /* Renderer */ + int vid_fullscreen_scale; /* Full screen scale type */ + int vid_fullscreen_start; /* Start emulator in full screen */ + int vid_force_43; /* Force 4:3 display ratio in windowed mode */ + int vid_scale; /* Windowed mode scale */ + int vid_overscan; /* EGA/(S)VGA overscan enabled */ + int vid_cga_contrast; /* CGA alternate contrast enabled */ + int vid_grayscale; /* Video is grayscale */ + int vid_grayscale_type; /* Video grayscale type */ + int vid_invert_display; /* Invert display */ + int rctrl_is_lalt; /* Right CTRL is left ALT */ + int update_icons; /* Update status bar icons */ + int window_remember; /* Remember window position and size */ + int window_w; /* Window coordinates */ + int window_h; + int window_x; + int window_y; + int sound_gain; /* Sound gain */ +# ifdef USE_LANGUAGE + uint16_t language_id; /* Language ID (0x0409 = English (US)) */ +# endif /* Machine cateogory */ - int machine, /* Machine */ - cpu, /* CPU */ -#ifdef USE_DYNAREC - cpu_use_dynarec, /* CPU recompiler enabled */ -#endif - wait_states, /* CPU wait states */ - enable_external_fpu, /* FPU enabled */ - time_sync; /* Time sync enabled */ - uint32_t mem_size; /* Memory size */ + int machine; /* Machine */ + int cpu; /* CPU */ +# ifdef USE_DYNAREC + int cpu_use_dynarec; /* CPU recompiler enabled */ +# endif + int wait_states; /* CPU wait states */ + int enable_external_fpu; /* FPU enabled */ + int time_sync; /* Time sync enabled */ + uint32_t mem_size; /* Memory size */ /* Video category */ - int video_card, /* Video card */ - voodoo_enabled; /* Voodoo enabled */ + int video_card; /* Video card */ + int voodoo_enabled; /* Voodoo enabled */ /* Input devices category */ - int mouse_type, /* Mouse type */ - joystick_type; /* Joystick type */ + int mouse_type; /* Mouse type */ + int joystick_type; /* Joystick type */ /* Sound category */ - int sound_card, /* Sound card */ - midi_device, /* Midi device */ - mpu_401, /* Standalone MPU-401 enabled */ - ssi_2001_enabled, /* SSI-2001 enabled */ - game_blaster_enabled, /* Game blaster enabled */ - gus_enabled, /* Gravis Ultrasound enabled */ - opl_type, /* OPL emulation type */ - sound_is_float; /* Sound is 32-bit float or 16-bit integer */ + int sound_card; /* Sound card */ + int midi_device; /* Midi device */ + int mpu_401; /* Standalone MPU-401 enabled */ + int ssi_2001_enabled; /* SSI-2001 enabled */ + int game_blaster_enabled; /* Game blaster enabled */ + int gus_enabled; /* Gravis Ultrasound enabled */ + int opl_type; /* OPL emulation type */ + int sound_is_float; /* Sound is 32-bit float or 16-bit integer */ /* Network category */ - int network_type, /* Network type (SLiRP or PCap) */ - network_card; /* Network card */ - char network_host[520]; /* PCap device */ + int network_type; /* Network type (SLiRP or PCap) */ + int network_card; /* Network card */ + char network_host[520]; /* PCap device */ /* Ports category */ - char parallel_devices[3][32]; /* LPT device names */ -#ifdef USE_SERIAL_DEVICES - char serial_devices[4][32]; /* Serial device names */ -#endif - int serial_enabled[4], /* Serial ports 1 and 2 enabled */ - parallel_enabled[3]; /* LPT1, LPT2, LPT3 enabled */ + char parallel_devices[PARALLEL_MAX][32]; /* LPT device names */ +# ifdef USE_SERIAL_DEVICES + char serial_devices[SERIAL_MAX][32]; /* Serial device names */ +# endif /* Other peripherals category */ - int fdc_type, /* Floppy disk controller type */ - hdc, /* Hard disk controller */ - scsi_card, /* SCSI controller */ - ide_ter_enabled, /* Tertiary IDE controller enabled */ - ide_qua_enabled, /* Quaternary IDE controller enabled */ - bugger_enabled, /* ISA bugger device enabled */ - isa_rtc_type, /* ISA RTC card */ - isa_mem_type[ISAMEM_MAX]; /* ISA memory boards */ + int fdc_type; /* Floppy disk controller type */ + int hdc; /* Hard disk controller */ + int scsi_card; /* SCSI controller */ + int ide_ter_enabled; /* Tertiary IDE controller enabled */ + int ide_qua_enabled; /* Quaternary IDE controller enabled */ + int bugger_enabled; /* ISA bugger device enabled */ + int isa_rtc_type; /* ISA RTC card */ + int isa_mem_type[ISAMEM_MAX]; /* ISA memory boards */ /* Hard disks category */ - storage_cfg_t hdd[HDD_NUM]; /* Hard disk drives */ + storage_cfg_t hdd[HDD_NUM]; /* Hard disk drives */ /* Floppy drives category */ - storage_cfg_t fdd[FDD_NUM]; /* Floppy drives */ + storage_cfg_t fdd[FDD_NUM]; /* Floppy drives */ /* Other removable devices category */ - storage_cfg_t cdrom[CDROM_NUM], /* CD-ROM drives */ - storage_cfg_t rdisk[ZIP_NUM]; /* Removable disk drives */ + storage_cfg_t cdrom[CDROM_NUM]; /* CD-ROM drives */ + storage_cfg_t rdisk[ZIP_NUM]; /* Removable disk drives */ } config_t; #endif -extern void config_load(void); -extern void config_save(void); -extern void config_write(char *fn); -extern void config_dump(void); +extern void config_load(void); +extern void config_save(void); -extern void config_delete_var(char *head, char *name); -extern int config_get_int(char *head, char *name, int def); -extern double config_get_double(char *head, char *name, double def); -extern int config_get_hex16(char *head, char *name, int def); -extern int config_get_hex20(char *head, char *name, int def); -extern int config_get_mac(char *head, char *name, int def); -extern char *config_get_string(char *head, char *name, char *def); -extern wchar_t *config_get_wstring(char *head, char *name, wchar_t *def); -extern void config_set_int(char *head, char *name, int val); -extern void config_set_double(char *head, char *name, double val); -extern void config_set_hex16(char *head, char *name, int val); -extern void config_set_hex20(char *head, char *name, int val); -extern void config_set_mac(char *head, char *name, int val); -extern void config_set_string(char *head, char *name, char *val); -extern void config_set_wstring(char *head, char *name, wchar_t *val); +#ifdef EMU_INI_H +extern ini_t config_get_ini(void); +#else +extern void *config_get_ini(void); +#endif -extern void * config_find_section(char *name); -extern void config_rename_section(void *priv, char *name); +#define config_delete_var(head, name) ini_delete_var(config_get_ini(), head, name) + +#define config_get_int(head, name, def) ini_get_int(config_get_ini(), head, name, def) +#define config_get_double(head, name, def) ini_get_double(config_get_ini(), head, name, def) +#define config_get_hex16(head, name, def) ini_get_hex16(config_get_ini(), head, name, def) +#define config_get_hex20(head, name, def) ini_get_hex20(config_get_ini(), head, name, def) +#define config_get_mac(head, name, def) ini_get_mac(config_get_ini(), head, name, def) +#define config_get_string(head, name, def) ini_get_string(config_get_ini(), head, name, def) +#define config_get_wstring(head, name, def) ini_get_wstring(config_get_ini(), head, name, def) + +#define config_set_int(head, name, val) ini_set_int(config_get_ini(), head, name, val) +#define config_set_double(head, name, val) ini_set_double(config_get_ini(), head, name, val) +#define config_set_hex16(head, name, val) ini_set_hex16(config_get_ini(), head, name, val) +#define config_set_hex20(head, name, val) ini_set_hex20(config_get_ini(), head, name, val) +#define config_set_mac(head, name, val) ini_set_mac(config_get_ini(), head, name, val) +#define config_set_string(head, name, val) ini_set_string(config_get_ini(), head, name, val) +#define config_set_wstring(head, name, val) ini_set_wstring(config_get_ini(), head, name, val) + +#define config_find_section(name) ini_find_section(config_get_ini(), name) +#define config_rename_section ini_rename_section #ifdef __cplusplus } #endif - -#endif /*EMU_CONFIG_H*/ +#endif /*EMU_CONFIG_H*/ diff --git a/src/include/86box/ddma.h b/src/include/86box/ddma.h index 64642f2ae..01c2e980d 100644 --- a/src/include/86box/ddma.h +++ b/src/include/86box/ddma.h @@ -1,49 +1,44 @@ /* - * 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. + * 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. + * This file is part of the 86Box distribution. * - * Definitions for the Distributed DMA emulation. + * Definitions for the Distributed DMA emulation. * * * - * Authors: Miran Grca, + * Authors: Miran Grca, * - * Copyright 2020 Miran Grca. + * Copyright 2020 Miran Grca. */ #ifndef DDMA_H -# define DDMA_H - +#define DDMA_H #ifdef __cplusplus extern "C" { #endif -typedef struct -{ - uint16_t io_base; - int channel, enable; +typedef struct ddma_channel_t { + uint16_t io_base; + int channel; + int enable; } ddma_channel_t; -typedef struct -{ - ddma_channel_t channels[8]; +typedef struct ddma_t { + ddma_channel_t channels[8]; } ddma_t; - /* Global variables. */ -extern const device_t ddma_device; - +extern const device_t ddma_device; /* Functions. */ -extern void ddma_update_io_mapping(ddma_t *dev, int ch, uint8_t base_l, uint8_t base_h, int enable); +extern void ddma_update_io_mapping(ddma_t *dev, int ch, uint8_t base_l, uint8_t base_h, int enable); #ifdef __cplusplus } #endif - -#endif /*DDMA_H*/ +#endif /*DDMA_H*/ diff --git a/src/include/86box/device.h b/src/include/86box/device.h index eaae682f4..b2d7a05ed 100644 --- a/src/include/86box/device.h +++ b/src/include/86box/device.h @@ -1,22 +1,24 @@ /* - * VARCem Virtual ARchaeological Computer EMulator. - * An emulator of (mostly) x86-based PC systems and devices, - * using the ISA,EISA,VLB,MCA and PCI system buses, roughly - * spanning the era between 1981 and 1995. + * 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 VARCem Project. + * This file is part of the 86Box distribution. * - * Definitions for the device handler. + * Definitions for the device handler. * * * - * Authors: Fred N. van Kempen, - * Miran Grca, - * Sarah Walker, + * Authors: Fred N. van Kempen, + * Miran Grca, + * Sarah Walker, * - * Copyright 2017-2019 Fred N. van Kempen. - * Copyright 2016-2019 Miran Grca. - * Copyright 2008-2019 Sarah Walker. + * Copyright 2017-2019 Fred N. van Kempen. + * Copyright 2016-2019 Miran Grca. + * Copyright 2008-2019 Sarah Walker. + * Copyright 2021 Andreas J. Reichel. + * Copyright 2021-2022 Jasmine Iwanek. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -37,137 +39,189 @@ * USA. */ #ifndef EMU_DEVICE_H -# define EMU_DEVICE_H +#define EMU_DEVICE_H +#define CONFIG_END -1 +#define CONFIG_STRING 0 +#define CONFIG_INT 1 +#define CONFIG_BINARY 2 +#define CONFIG_SELECTION 3 +#define CONFIG_MIDI_OUT 4 +#define CONFIG_FNAME 5 +#define CONFIG_SPINNER 6 +#define CONFIG_HEX16 7 +#define CONFIG_HEX20 8 +#define CONFIG_MAC 9 +#define CONFIG_MIDI_IN 10 +#define CONFIG_BIOS 11 +#define CONFIG_SERPORT 12 -#define CONFIG_STRING 0 -#define CONFIG_INT 1 -#define CONFIG_BINARY 2 -#define CONFIG_SELECTION 3 -#define CONFIG_MIDI 4 -#define CONFIG_FNAME 5 -#define CONFIG_SPINNER 6 -#define CONFIG_HEX16 7 -#define CONFIG_HEX20 8 -#define CONFIG_MAC 9 -#define CONFIG_MIDI_IN 10 - +#define CONFIG_ONBOARD 256 /* only avaialble on the on-board variant */ +#define CONFIG_STANDALONE 257 /* not available on the on-board variant */ enum { - DEVICE_NOT_WORKING = 1, /* does not currently work correctly and will be disabled in a release build */ - DEVICE_PCJR = 2, /* requires an IBM PCjr */ - DEVICE_AT = 4, /* requires an AT-compatible system */ - DEVICE_PS2 = 8, /* requires a PS/1 or PS/2 system */ - DEVICE_ISA = 0x10, /* requires the ISA bus */ - DEVICE_CBUS = 0x20, /* requires the C-BUS bus */ - DEVICE_MCA = 0x40, /* requires the MCA bus */ - DEVICE_EISA = 0x80, /* requires the EISA bus */ - DEVICE_VLB = 0x100, /* requires the PCI bus */ - DEVICE_PCI = 0x200, /* requires the VLB bus */ - DEVICE_AGP = 0x400, /* requires the AGP bus */ - DEVICE_AC97 = 0x800, /* requires the AC'97 bus */ - DEVICE_COM = 0x1000, /* requires a serial port */ - DEVICE_LPT = 0x2000 /* requires a parallel port */ + DEVICE_PCJR = 2, /* requires an IBM PCjr */ + DEVICE_XTKBC = 4, /* requires an XT-compatible keyboard controller */ + DEVICE_AT = 8, /* requires an AT-compatible system */ + DEVICE_ATKBC = 0x10, /* requires an AT-compatible keyboard controller */ + DEVICE_PS2 = 0x20, /* requires a PS/1 or PS/2 system */ + DEVICE_ISA = 0x40, /* requires the ISA bus */ + DEVICE_CBUS = 0x80, /* requires the C-BUS bus */ + DEVICE_PCMCIA = 0x100, /* requires the PCMCIA bus */ + DEVICE_MCA = 0x200, /* requires the MCA bus */ + DEVICE_HIL = 0x400, /* requires the HP HIL bus */ + DEVICE_EISA = 0x800, /* requires the EISA bus */ + DEVICE_AT32 = 0x1000, /* requires the Mylex AT/32 local bus */ + DEVICE_OLB = 0x2000, /* requires the OPTi local bus */ + DEVICE_VLB = 0x4000, /* requires the VLB bus */ + DEVICE_PCI = 0x8000, /* requires the PCI bus */ + DEVICE_CARDBUS = 0x10000, /* requires the CardBus bus */ + DEVICE_USB = 0x20000, /* requires the USB bus */ + DEVICE_AGP = 0x40000, /* requires the AGP bus */ + DEVICE_AC97 = 0x80000, /* requires the AC'97 bus */ + DEVICE_COM = 0x100000, /* requires a serial port */ + DEVICE_LPT = 0x200000, /* requires a parallel port */ + DEVICE_KBC = 0x400000, /* is a keyboard controller */ + + DEVICE_ONBOARD = 0x20000000, /* is on-board */ + DEVICE_EXTPARAMS = 0x40000000, /* accepts extended parameters */ + + DEVICE_PIT = 0x80000000, /* device is a PIT */ + + DEVICE_ALL = 0xffffffff /* match all devices */ }; +#define BIOS_NORMAL 0 +#define BIOS_INTERLEAVED 1 +#define BIOS_INTERLEAVED_SINGLEFILE 2 +#define BIOS_INTERLEAVED_QUAD 3 +#define BIOS_INTERLEAVED_QUAD_SINGLEFILE 4 +#define BIOS_INTEL_AMI 5 +#define BIOS_INTERLEAVED_INVERT 8 +#define BIOS_HIGH_BIT_INVERT 16 -typedef struct { +typedef struct device_config_selection_t { const char *description; - int value; + int value; } device_config_selection_t; -typedef struct { +typedef struct device_config_bios_t { + const char *name; + const char *internal_name; + int bios_type; + int files_no; + uint32_t local; + uint32_t size; + void *dev1; + void *dev2; + const char *files[9]; +} device_config_bios_t; + +typedef struct device_config_spinner_t { int16_t min; int16_t max; int16_t step; } device_config_spinner_t; -typedef struct { - const char *name; - const char *description; - int type; - const char *default_string; - int default_int; - const char *file_filter; - device_config_spinner_t spinner; - const device_config_selection_t selection[16]; +typedef struct device_config_t { + const char *name; + const char *description; + int type; + const char *default_string; + int default_int; + const char *file_filter; + const device_config_spinner_t spinner; + const device_config_selection_t selection[32]; + const device_config_bios_t bios[32]; } device_config_t; typedef struct _device_ { - const char *name; + const char *name; const char *internal_name; - uint32_t flags; /* system flags */ - uint32_t local; /* flags local to device */ + uint32_t flags; /* system flags */ + uintptr_t local; /* flags local to device */ - void *(*init)(const struct _device_ *); - void (*close)(void *priv); - void (*reset)(void *priv); union { - int (*available)(void); - int (*poll)(int x, int y, int z, int b, void *priv); - void (*register_pci_slot)(int device, int type, int inta, int intb, int intc, int intd, void *priv); + void *(*init)(const struct _device_ *); + void *(*init_ext)(const struct _device_ *, void*); }; - void (*speed_changed)(void *priv); - void (*force_redraw)(void *priv); + void (*close)(void *priv); + void (*reset)(void *priv); + union { + int (*available)(void); + int (*poll)(void *priv); + }; + void (*speed_changed)(void *priv); + void (*force_redraw)(void *priv); const device_config_t *config; } device_t; -typedef struct { - const device_t *dev; - char name[2048]; +typedef struct device_context_t { + const device_t *dev; + char name[2048]; + int instance; } device_context_t; - #ifdef __cplusplus extern "C" { #endif -extern void device_init(void); -extern void device_set_context(device_context_t *c, const device_t *d, int inst); -extern void device_context(const device_t *d); -extern void device_context_inst(const device_t *d, int inst); -extern void device_context_restore(void); -extern void *device_add(const device_t *d); -extern void device_add_ex(const device_t *d, void *priv); -extern void *device_add_inst(const device_t *d, int inst); -extern void device_add_inst_ex(const device_t *d, void *priv, int inst); -extern void *device_cadd(const device_t *d, const device_t *cd); -extern void device_cadd_ex(const device_t *d, const device_t *cd, void *priv); -extern void *device_cadd_inst(const device_t *d, const device_t *cd, int inst); -extern void device_cadd_inst_ex(const device_t *d, const device_t *cd, void *priv, int inst); -extern void device_close_all(void); -extern void device_reset_all(void); -extern void device_reset_all_pci(void); -extern void *device_get_priv(const device_t *d); -extern int device_available(const device_t *d); -extern int device_poll(const device_t *d, int x, int y, int z, int b); -extern void device_register_pci_slot(const device_t *d, int device, int type, int inta, int intb, int intc, int intd); -extern void device_speed_changed(void); -extern void device_force_redraw(void); -extern void device_get_name(const device_t *d, int bus, char *name); +extern void device_init(void); +extern void device_set_context(device_context_t *c, const device_t *dev, int inst); +extern void device_context(const device_t *dev); +extern void device_context_inst(const device_t *dev, int inst); +extern void device_context_restore(void); +extern void *device_add(const device_t *d); +extern void *device_add_parameters(const device_t *dev, void *params); +extern void device_add_ex(const device_t *dev, void *priv); +extern void device_add_ex_parameters(const device_t *dev, void *priv, void *params); +extern void *device_add_inst(const device_t *dev, int inst); +extern void *device_add_inst_parameters(const device_t *dev, int inst, void *params); +extern void device_add_inst_ex(const device_t *dev, void *priv, int inst); +extern void device_add_inst_ex_parameters(const device_t *dev, void *priv, int inst, void *params); +extern void *device_cadd(const device_t *dev, const device_t *cd); +extern void *device_cadd_parameters(const device_t *dev, const device_t *cd, void *params); +extern void device_cadd_ex(const device_t *dev, const device_t *cd, void *priv); +extern void device_cadd_ex_parameters(const device_t *dev, const device_t *cd, void *priv, void *params); +extern void *device_cadd_inst(const device_t *dev, const device_t *cd, int inst); +extern void *device_cadd_inst_parameters(const device_t *dev, const device_t *cd, int inst, void *params); +extern void device_cadd_inst_ex(const device_t *dev, const device_t *cd, void *priv, int inst); +extern void device_cadd_inst_ex_parameters(const device_t *dev, const device_t *cd, void *priv, int inst, void *params); +extern void device_close_all(void); +extern void device_reset_all(uint32_t match_flags); +extern void *device_find_first_priv(uint32_t match_flags); +extern void *device_get_priv(const device_t *dev); +extern int device_available(const device_t *dev); +extern int device_poll(const device_t *dev); +extern void device_speed_changed(void); +extern void device_force_redraw(void); +extern void device_get_name(const device_t *dev, int bus, char *name); +extern int device_has_config(const device_t *dev); +extern const char *device_get_bios_file(const device_t *dev, const char *internal_name, int file_no); -extern int device_is_valid(const device_t *, int m); +extern int device_is_valid(const device_t *, int m); -extern int device_get_config_int(const char *name); -extern int device_get_config_int_ex(const char *s, int dflt_int); -extern int device_get_config_hex16(const char *name); -extern int device_get_config_hex20(const char *name); -extern int device_get_config_mac(const char *name, int dflt_int); -extern void device_set_config_int(const char *s, int val); -extern void device_set_config_hex16(const char *s, int val); -extern void device_set_config_hex20(const char *s, int val); -extern void device_set_config_mac(const char *s, int val); -extern const char *device_get_config_string(const char *name); +extern int device_get_config_int(const char *name); +extern int device_get_config_int_ex(const char *s, int dflt_int); +extern int device_get_config_hex16(const char *name); +extern int device_get_config_hex20(const char *name); +extern int device_get_config_mac(const char *name, int dflt_int); +extern void device_set_config_int(const char *s, int val); +extern void device_set_config_hex16(const char *s, int val); +extern void device_set_config_hex20(const char *s, int val); +extern void device_set_config_mac(const char *s, int val); +extern const char *device_get_config_string(const char *name); +extern const int device_get_instance(void); +#define device_get_config_bios device_get_config_string -extern char * device_get_internal_name(const device_t *d); +extern const char *device_get_internal_name(const device_t *dev); -extern int machine_get_config_int(char *s); -extern char *machine_get_config_string(char *s); +extern int machine_get_config_int(char *s); +extern char *machine_get_config_string(char *s); #ifdef __cplusplus } #endif - -#endif /*EMU_DEVICE_H*/ +#endif /*EMU_DEVICE_H*/ diff --git a/src/include/86box/discord.h b/src/include/86box/discord.h index 90621e16d..358c95c9b 100644 --- a/src/include/86box/discord.h +++ b/src/include/86box/discord.h @@ -1,34 +1,33 @@ /* - * 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. + * 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. + * This file is part of the 86Box distribution. * - * Definitions for the Discord integration module. + * Definitions for the Discord integration module. * * * - * Authors: David HrdliÄka, + * Authors: David HrdliÄka, * - * Copyright 2019 David HrdliÄka. + * Copyright 2019 David HrdliÄka. */ #ifndef WIN_DISCORD_H -# define WIN_DISCORD_H +#define WIN_DISCORD_H #ifdef __cplusplus -extern "C" -{ +extern "C" { #endif -extern int discord_loaded; +extern int discord_loaded; -extern int discord_load(); -extern void discord_init(); -extern void discord_close(); -extern void discord_update_activity(int paused); -extern void discord_run_callbacks(); +extern int discord_load(void); +extern void discord_init(void); +extern void discord_close(void); +extern void discord_update_activity(int paused); +extern void discord_run_callbacks(void); #ifdef __cplusplus } diff --git a/src/include/86box/disksizes.h b/src/include/86box/disksizes.h new file mode 100644 index 000000000..b5cd1bc30 --- /dev/null +++ b/src/include/86box/disksizes.h @@ -0,0 +1,74 @@ +/* + * 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. + * + * Header of the emulation of the PC speaker. + * + * + * + * Authors: Jasmine Iwanek + * + * Copyright 2022 Jasmine Iwanek + */ + +#ifndef DISK_SIZES_H +#define DISK_SIZES_H + +#ifdef __cplusplus +extern "C" { +#endif + +typedef struct disk_size_t { + int hole; + int sides; + int data_rate; + int encoding; + int rpm; + int tracks; + int sectors; /* For IMG and Japanese FDI only. */ + int sector_len; /* For IMG and Japanese FDI only. */ + int media_desc; + int spc; + int num_fats; + int spfat; + int root_dir_entries; +} disk_size_t; + +static const disk_size_t disk_sizes[14] = { +// clang-format off +#if 0 + { 1, 1, 2, 1, 1, 77, 26, 0, 0, 4, 2, 6, 68 }, /* 250k 8" */ + { 1, 2, 2, 1, 1, 77, 26, 0, 0, 4, 2, 6, 68 }, /* 500k 8" */ + { 1, 1, 2, 1, 1, 77, 8, 3, 0, 1, 2, 2, 192 }, /* 616k 8" */ + { 1, 2, 0, 1, 1, 77, 8, 3, 0, 1, 2, 2, 192 }, /* 1232k 8" */ +#endif + { 0, 1, 2, 1, 0, 40, 8, 2, 0xfe, 2, 2, 1, 64 }, /* 160k */ + { 0, 1, 2, 1, 0, 40, 9, 2, 0xfc, 2, 2, 1, 64 }, /* 180k */ + { 0, 2, 2, 1, 0, 40, 8, 2, 0xff, 2, 2, 1, 112 }, /* 320k */ + { 0, 2, 2, 1, 0, 40, 9, 2, 0xfd, 2, 2, 2, 112 }, /* 360k */ + { 0, 2, 2, 1, 0, 80, 8, 2, 0xfb, 2, 2, 2, 112 }, /* 640k */ + { 0, 2, 2, 1, 0, 80, 9, 2, 0xf9, 2, 2, 3, 112 }, /* 720k */ + { 1, 2, 0, 1, 1, 80, 15, 2, 0xf9, 1, 2, 7, 224 }, /* 1.2M */ + { 1, 2, 0, 1, 1, 77, 8, 3, 0xfe, 1, 2, 2, 192 }, /* 1.25M */ + { 1, 2, 0, 1, 0, 80, 18, 2, 0xf0, 1, 2, 9, 224 }, /* 1.44M */ + { 1, 2, 0, 1, 0, 80, 21, 2, 0xf0, 2, 2, 5, 16 }, /* DMF cluster 1024 */ + { 1, 2, 0, 1, 0, 80, 21, 2, 0xf0, 4, 2, 3, 16 }, /* DMF cluster 2048 */ + { 2, 2, 3, 1, 0, 80, 36, 2, 0xf0, 2, 2, 9, 240 }, /* 2.88M */ + { 0, 64, 0, 0, 0, 96, 32, 2, 0, 0, 0, 0, 0 }, /* ZIP 100 */ + { 0, 64, 0, 0, 0, 239, 32, 2, 0, 0, 0, 0, 0 }, /* ZIP 250 */ +#if 0 + { 0, 8, 0, 0, 0, 963, 32, 2, 0, 0, 0, 0, 0 }, /* LS-120 */ + { 0, 32, 0, 0, 0, 262, 56, 2, 0, 0, 0, 0, 0 } /* LS-240 */ +#endif +// clang-format on +}; + +#ifdef __cplusplus +} +#endif + +#endif /*DISK_SIZES_H*/ diff --git a/src/include/86box/dma.h b/src/include/86box/dma.h index fc6a0b388..7ead53ba0 100644 --- a/src/include/86box/dma.h +++ b/src/include/86box/dma.h @@ -1,22 +1,22 @@ /* - * VARCem Virtual ARchaeological Computer EMulator. - * An emulator of (mostly) x86-based PC systems and devices, - * using the ISA,EISA,VLB,MCA and PCI system buses, roughly - * spanning the era between 1981 and 1995. + * 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 VARCem Project. + * This file is part of the 86Box distribution. * - * Definitions for the Intel DMA controller. + * Definitions for the Intel DMA controller. * * * - * Authors: Fred N. van Kempen, - * Miran Grca, - * Sarah Walker, + * Authors: Fred N. van Kempen, + * Miran Grca, + * Sarah Walker, * - * Copyright 2017-2020 Fred N. van Kempen. - * Copyright 2016-2020 Miran Grca. - * Copyright 2008-2020 Sarah Walker. + * Copyright 2017-2020 Fred N. van Kempen. + * Copyright 2016-2020 Miran Grca. + * Copyright 2008-2020 Sarah Walker. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -37,74 +37,85 @@ * USA. */ #ifndef EMU_DMA_H -# define EMU_DMA_H +#define EMU_DMA_H +#define DMA_NODATA -1 +#define DMA_OVER 0x10000 +#define DMA_VERIFY 0x20000 -#define DMA_NODATA -1 -#define DMA_OVER 0x10000 -#define DMA_VERIFY 0x20000 - - -typedef struct { - uint8_t m, mode, page, stat, - stat_rq, command, - ps2_mode, arb_level, - sg_command, sg_status, - ptr0, enabled, - ext_mode, page_l, - page_h, pad; - uint16_t cb, io_addr, - base, transfer_mode; - uint32_t ptr, ptr_cur, - addr, - ab, ac; - int cc, wp, - size, count, - eot; +typedef struct dma_t { + uint8_t m; + uint8_t mode; + uint8_t page; + uint8_t stat; + uint8_t stat_rq; + uint8_t command; + uint8_t ps2_mode; + uint8_t arb_level; + uint8_t sg_command; + uint8_t sg_status; + uint8_t ptr0; + uint8_t enabled; + uint8_t ext_mode; + uint8_t page_l; + uint8_t page_h; + uint8_t pad; + uint16_t cb; + uint16_t io_addr; + uint16_t base; + uint16_t transfer_mode; + uint32_t ptr; + uint32_t ptr_cur; + uint32_t addr; + uint32_t ab; + uint32_t ac; + int cc; + int wp; + int size; + int count; + int eot; } dma_t; +extern dma_t dma[8]; +extern uint8_t dma_e; +extern uint8_t dma_m; -extern dma_t dma[8]; -extern uint8_t dma_e; +extern void dma_init(void); +extern void dma16_init(void); +extern void ps2_dma_init(void); +extern void dma_reset(void); +extern int dma_mode(int channel); +extern void readdma0(void); +extern int readdma1(void); +extern uint8_t readdma2(void); +extern int readdma3(void); -extern void dma_init(void); -extern void dma16_init(void); -extern void ps2_dma_init(void); -extern void dma_reset(void); -extern int dma_mode(int channel); +extern void writedma2(uint8_t temp); -extern void readdma0(void); -extern int readdma1(void); -extern uint8_t readdma2(void); -extern int readdma3(void); +extern int dma_get_drq(int channel); +extern void dma_set_drq(int channel, int set); -extern void writedma2(uint8_t temp); +extern int dma_channel_read(int channel); +extern int dma_channel_write(int channel, uint16_t val); -extern int dma_get_drq(int channel); -extern void dma_set_drq(int channel, int set); +extern void dma_alias_set(void); +extern void dma_alias_set_piix(void); +extern void dma_alias_remove(void); +extern void dma_alias_remove_piix(void); -extern int dma_channel_read(int channel); -extern int dma_channel_write(int channel, uint16_t val); +extern void dma_bm_read(uint32_t PhysAddress, uint8_t *DataRead, uint32_t TotalSize, int TransferSize); +extern void dma_bm_write(uint32_t PhysAddress, const uint8_t *DataWrite, uint32_t TotalSize, int TransferSize); -extern void dma_alias_set(void); -extern void dma_alias_set_piix(void); -extern void dma_alias_remove(void); -extern void dma_alias_remove_piix(void); +void dma_set_params(uint8_t advanced, uint32_t mask); +void dma_set_mask(uint32_t mask); -extern void dma_bm_read(uint32_t PhysAddress, uint8_t *DataRead, uint32_t TotalSize, int TransferSize); -extern void dma_bm_write(uint32_t PhysAddress, const uint8_t *DataWrite, uint32_t TotalSize, int TransferSize); +void dma_set_at(uint8_t at); -void dma_set_params(uint8_t advanced, uint32_t mask); -void dma_set_mask(uint32_t mask); +void dma_ext_mode_init(void); +void dma_high_page_init(void); -void dma_set_at(uint8_t at); +void dma_remove_sg(void); +void dma_set_sg_base(uint8_t sg_base); -void dma_ext_mode_init(void); -void dma_high_page_init(void); - -void dma_remove_sg(void); -void dma_set_sg_base(uint8_t sg_base); - - -#endif /*EMU_DMA_H*/ +#endif /*EMU_DMA_H*/ diff --git a/src/include/86box/fdc.h b/src/include/86box/fdc.h index f50e82b58..9441bdfc4 100644 --- a/src/include/86box/fdc.h +++ b/src/include/86box/fdc.h @@ -1,203 +1,251 @@ /* - * 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. + * 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. + * This file is part of the 86Box distribution. * - * Implementation of the NEC uPD-765 and compatible floppy disk - * controller. + * Implementation of the NEC uPD-765 and compatible floppy disk + * controller. * * * - * Authors: Sarah Walker, - * Miran Grca, - * Fred N. van Kempen, + * Authors: Sarah Walker, + * Miran Grca, + * Fred N. van Kempen, * - * Copyright 2008-2020 Sarah Walker. - * Copyright 2016-2020 Miran Grca. - * Copyright 2018-2020 Fred N. van Kempen. + * Copyright 2008-2020 Sarah Walker. + * Copyright 2016-2020 Miran Grca. + * Copyright 2018-2020 Fred N. van Kempen. */ #ifndef EMU_FDC_H -# define EMU_FDC_H +#define EMU_FDC_H extern int fdc_type; -#define FDC_PRIMARY_ADDR 0x03f0 -#define FDC_PRIMARY_IRQ 6 -#define FDC_PRIMARY_DMA 2 -#define FDC_PRIMARY_PCJR_ADDR 0x00f0 -#define FDC_PRIMARY_PCJR_IRQ 6 -#define FDC_PRIMARY_PCJR_DMA 2 -#define FDC_SECONDARY_ADDR 0x0370 -#define FDC_SECONDARY_IRQ 6 -#define FDC_SECONDARY_DMA 2 -#define FDC_TERTIARY_ADDR 0x0360 -#define FDC_TERTIARY_IRQ 6 -#define FDC_TERTIARY_DMA 2 -#define FDC_QUATERNARY_ADDR 0x03e0 -#define FDC_QUATERNARY_IRQ 6 -#define FDC_QUATERNARY_DMA 2 +#define FDC_PRIMARY_ADDR 0x03f0 +#define FDC_PRIMARY_IRQ 6 +#define FDC_PRIMARY_DMA 2 +#define FDC_PRIMARY_PCJR_ADDR 0x00f0 +#define FDC_PRIMARY_PCJR_IRQ 6 +#define FDC_PRIMARY_PCJR_DMA 2 +#define FDC_SECONDARY_ADDR 0x0370 +#define FDC_SECONDARY_IRQ 6 +#define FDC_SECONDARY_DMA 2 +#define FDC_TERTIARY_ADDR 0x0360 +#define FDC_TERTIARY_IRQ 6 +#define FDC_TERTIARY_DMA 2 +#define FDC_QUATERNARY_ADDR 0x03e0 +#define FDC_QUATERNARY_IRQ 6 +#define FDC_QUATERNARY_DMA 2 -#define FDC_FLAG_PCJR 0x01 /* PCjr */ -#define FDC_FLAG_DISKCHG_ACTLOW 0x02 /* Amstrad, PS/1, PS/2 ISA */ -#define FDC_FLAG_AT 0x04 /* AT+, PS/x */ -#define FDC_FLAG_PS1 0x08 /* PS/1, PS/2 ISA */ -#define FDC_FLAG_SUPERIO 0x10 /* Super I/O chips */ -#define FDC_FLAG_START_RWC_1 0x20 /* W83877F, W83977F */ -#define FDC_FLAG_MORE_TRACKS 0x40 /* W83877F, W83977F, PC87306, PC87309 */ -#define FDC_FLAG_NSC 0x80 /* PC87306, PC87309 */ -#define FDC_FLAG_TOSHIBA 0x100 /* T1000, T1200 */ -#define FDC_FLAG_AMSTRAD 0x200 /* Non-AT Amstrad machines */ -#define FDC_FLAG_UMC 0x400 /* UMC UM8398 */ +#define FDC_FLAG_PCJR 0x01 /* PCjr */ +#define FDC_FLAG_DISKCHG_ACTLOW 0x02 /* Amstrad, PS/1, PS/2 ISA */ +#define FDC_FLAG_AT 0x04 /* AT+, PS/x */ +#define FDC_FLAG_PS1 0x08 /* PS/1, PS/2 ISA */ +#define FDC_FLAG_SUPERIO 0x10 /* Super I/O chips */ +#define FDC_FLAG_START_RWC_1 0x20 /* W83877F, W83977F */ +#define FDC_FLAG_MORE_TRACKS 0x40 /* W83877F, W83977F, PC87306, PC87309 */ +#define FDC_FLAG_NSC 0x80 /* PC87306, PC87309 */ +#define FDC_FLAG_TOSHIBA 0x100 /* T1000, T1200 */ +#define FDC_FLAG_AMSTRAD 0x200 /* Non-AT Amstrad machines */ +#define FDC_FLAG_UMC 0x400 /* UMC UM8398 */ +#define FDC_FLAG_ALI 0x800 /* ALi M512x / M1543C */ +#define FDC_FLAG_SEC 0x1000 /* Is Secondary */ +#define FDC_FLAG_TER 0x2000 /* Is Tertiary */ +#define FDC_FLAG_QUA 0x3000 /* Is Quaternary */ +typedef struct fdc_t { + uint8_t dor; + uint8_t stat; + uint8_t command; + uint8_t processed_cmd; + uint8_t dat; + uint8_t st0; + uint8_t swap; + uint8_t dtl; + uint8_t swwp; + uint8_t disable_write; + uint8_t st5; + uint8_t st6; + uint8_t error; + uint8_t params[8]; + uint8_t res[11]; + uint8_t specify[2]; + uint8_t config; + uint8_t pretrk; + uint8_t fifobuf[16]; -typedef struct { - uint8_t dor, stat, command, processed_cmd, dat, st0, swap, dtl; - uint8_t swwp, disable_write, st5, st6, error; - uint8_t params[8], res[11]; - uint8_t specify[2]; - uint8_t config, pretrk; - uint8_t fifobuf[16]; + uint16_t base_address; - uint16_t base_address; + int head; + int sector; + int drive; + int lastdrive; + int pcn[4]; + int eot[4]; + int rw_track; + int pos; + int pnum; + int ptot; + int rate; + int reset_stat; + int lock; + int perp; + int format_state; + int format_n; + int step; + int seek_dir; + int tc; + int noprec; - int head, sector, drive, lastdrive; - int pcn[4], eot[4]; - int rw_track, pos; - int pnum, ptot; - int rate, reset_stat; - int lock, perp; - int format_state, format_n; - int step, seek_dir; - int tc, noprec; + int data_ready; + int inread; + int bitcell_period; + int enh_mode; + int rwc[4]; + int drvrate[4]; + int boot_drive; + int dma; + int densel_polarity; + int densel_force; + int fifo; + int tfifo; + int fifobufpos; + int drv2en; - int data_ready, inread; - int bitcell_period, enh_mode; - int rwc[4], drvrate[4]; - int boot_drive, dma; - int densel_polarity, densel_force; - int fifo, tfifo; - int fifobufpos, drv2en; + int gap; + int enable_3f1; + int format_sectors; + int max_track; + int mfm; + int deleted; + int wrong_am; + int sc; + int satisfying_sectors; + int fintr; + int rw_drive; - int gap; - int enable_3f1, format_sectors; - int max_track, mfm; - int deleted, wrong_am; - int sc, satisfying_sectors; - int fintr, rw_drive; + int flags; + int interrupt; - int flags, interrupt; + int irq; /* Should be 6 by default. */ + int dma_ch; /* Should be 2 by default. */ - int irq; /* Should be 6 by default. */ - int dma_ch; /* Should be 2 by default. */ + int bit_rate; /* Should be 250 at start. */ + int paramstogo; - int bit_rate; /* Should be 250 at start. */ - int paramstogo; + sector_id_t read_track_sector; + sector_id_t format_sector_id; - sector_id_t read_track_sector, format_sector_id; + uint64_t watchdog_count; - uint64_t watchdog_count; - - pc_timer_t timer, watchdog_timer; + pc_timer_t timer; + pc_timer_t watchdog_timer; } fdc_t; - -extern void fdc_remove(fdc_t *fdc); -extern void fdc_poll(fdc_t *fdc); -extern void fdc_abort(fdc_t *fdc); -extern void fdc_set_dskchg_activelow(fdc_t *fdc); -extern void fdc_3f1_enable(fdc_t *fdc, int enable); -extern int fdc_get_bit_rate(fdc_t *fdc); -extern int fdc_get_bitcell_period(fdc_t *fdc); +extern void fdc_remove(fdc_t *fdc); +extern void fdc_poll(fdc_t *fdc); +extern void fdc_abort(fdc_t *fdc); +extern void fdc_set_dskchg_activelow(fdc_t *fdc); +extern void fdc_3f1_enable(fdc_t *fdc, int enable); +extern int fdc_get_bit_rate(fdc_t *fdc); +extern int fdc_get_bitcell_period(fdc_t *fdc); /* A few functions to communicate between Super I/O chips and the FDC. */ -extern void fdc_update_enh_mode(fdc_t *fdc, int enh_mode); -extern int fdc_get_rwc(fdc_t *fdc, int drive); -extern void fdc_update_rwc(fdc_t *fdc, int drive, int rwc); -extern int fdc_get_boot_drive(fdc_t *fdc); -extern void fdc_update_boot_drive(fdc_t *fdc, int boot_drive); -extern void fdc_update_densel_polarity(fdc_t *fdc, int densel_polarity); -extern uint8_t fdc_get_densel_polarity(fdc_t *fdc); -extern void fdc_update_densel_force(fdc_t *fdc, int densel_force); -extern void fdc_update_drvrate(fdc_t *fdc, int drive, int drvrate); -extern void fdc_update_drv2en(fdc_t *fdc, int drv2en); +extern void fdc_update_enh_mode(fdc_t *fdc, int enh_mode); +extern int fdc_get_rwc(fdc_t *fdc, int drive); +extern void fdc_update_rwc(fdc_t *fdc, int drive, int rwc); +extern int fdc_get_boot_drive(fdc_t *fdc); +extern void fdc_update_boot_drive(fdc_t *fdc, int boot_drive); +extern void fdc_update_densel_polarity(fdc_t *fdc, int densel_polarity); +extern uint8_t fdc_get_densel_polarity(fdc_t *fdc); +extern void fdc_update_densel_force(fdc_t *fdc, int densel_force); +extern void fdc_update_drvrate(fdc_t *fdc, int drive, int drvrate); +extern void fdc_update_drv2en(fdc_t *fdc, int drv2en); -extern void fdc_noidam(fdc_t *fdc); -extern void fdc_nosector(fdc_t *fdc); -extern void fdc_nodataam(fdc_t *fdc); -extern void fdc_cannotformat(fdc_t *fdc); -extern void fdc_wrongcylinder(fdc_t *fdc); -extern void fdc_badcylinder(fdc_t *fdc); -extern void fdc_writeprotect(fdc_t *fdc); -extern void fdc_datacrcerror(fdc_t *fdc); -extern void fdc_headercrcerror(fdc_t *fdc); -extern void fdc_nosector(fdc_t *fdc); +extern void fdc_noidam(fdc_t *fdc); +extern void fdc_nosector(fdc_t *fdc); +extern void fdc_nodataam(fdc_t *fdc); +extern void fdc_cannotformat(fdc_t *fdc); +extern void fdc_wrongcylinder(fdc_t *fdc); +extern void fdc_badcylinder(fdc_t *fdc); +extern void fdc_writeprotect(fdc_t *fdc); +extern void fdc_datacrcerror(fdc_t *fdc); +extern void fdc_headercrcerror(fdc_t *fdc); +extern void fdc_nosector(fdc_t *fdc); -extern int real_drive(fdc_t *fdc, int drive); +extern int real_drive(fdc_t *fdc, int drive); extern sector_id_t fdc_get_read_track_sector(fdc_t *fdc); -extern int fdc_get_compare_condition(fdc_t *fdc); -extern int fdc_is_deleted(fdc_t *fdc); -extern int fdc_is_sk(fdc_t *fdc); -extern void fdc_set_wrong_am(fdc_t *fdc); -extern int fdc_get_drive(fdc_t *fdc); -extern int fdc_get_perp(fdc_t *fdc); -extern int fdc_get_format_n(fdc_t *fdc); -extern int fdc_is_mfm(fdc_t *fdc); -extern double fdc_get_hut(fdc_t *fdc); -extern double fdc_get_hlt(fdc_t *fdc); -extern void fdc_request_next_sector_id(fdc_t *fdc); -extern void fdc_stop_id_request(fdc_t *fdc); -extern int fdc_get_gap(fdc_t *fdc); -extern int fdc_get_gap2(fdc_t *fdc, int drive); -extern int fdc_get_dtl(fdc_t *fdc); -extern int fdc_get_format_sectors(fdc_t *fdc); -extern uint8_t fdc_get_swwp(fdc_t *fdc); -extern void fdc_set_swwp(fdc_t *fdc, uint8_t swwp); -extern uint8_t fdc_get_diswr(fdc_t *fdc); -extern void fdc_set_diswr(fdc_t *fdc, uint8_t diswr); -extern uint8_t fdc_get_swap(fdc_t *fdc); -extern void fdc_set_swap(fdc_t *fdc, uint8_t swap); +extern int fdc_get_compare_condition(fdc_t *fdc); +extern int fdc_is_deleted(fdc_t *fdc); +extern int fdc_is_sk(fdc_t *fdc); +extern void fdc_set_wrong_am(fdc_t *fdc); +extern int fdc_get_drive(fdc_t *fdc); +extern int fdc_get_perp(fdc_t *fdc); +extern int fdc_get_format_n(fdc_t *fdc); +extern int fdc_is_mfm(fdc_t *fdc); +extern double fdc_get_hut(fdc_t *fdc); +extern double fdc_get_hlt(fdc_t *fdc); +extern void fdc_request_next_sector_id(fdc_t *fdc); +extern void fdc_stop_id_request(fdc_t *fdc); +extern int fdc_get_gap(fdc_t *fdc); +extern int fdc_get_gap2(fdc_t *fdc, int drive); +extern int fdc_get_dtl(fdc_t *fdc); +extern int fdc_get_format_sectors(fdc_t *fdc); +extern uint8_t fdc_get_swwp(fdc_t *fdc); +extern void fdc_set_swwp(fdc_t *fdc, uint8_t swwp); +extern uint8_t fdc_get_diswr(fdc_t *fdc); +extern void fdc_set_diswr(fdc_t *fdc, uint8_t diswr); +extern uint8_t fdc_get_swap(fdc_t *fdc); +extern void fdc_set_swap(fdc_t *fdc, uint8_t swap); -extern void fdc_finishcompare(fdc_t *fdc, int satisfying); -extern void fdc_finishread(fdc_t *fdc); -extern void fdc_sector_finishcompare(fdc_t *fdc, int satisfying); -extern void fdc_sector_finishread(fdc_t *fdc); -extern void fdc_track_finishread(fdc_t *fdc, int condition); -extern int fdc_is_verify(fdc_t *fdc); +extern void fdc_finishcompare(fdc_t *fdc, int satisfying); +extern void fdc_finishread(fdc_t *fdc); +extern void fdc_sector_finishcompare(fdc_t *fdc, int satisfying); +extern void fdc_sector_finishread(fdc_t *fdc); +extern void fdc_track_finishread(fdc_t *fdc, int condition); +extern int fdc_is_verify(fdc_t *fdc); -extern void fdc_overrun(fdc_t *fdc); -extern void fdc_set_base(fdc_t *fdc, int base); -extern void fdc_set_irq(fdc_t *fdc, int irq); -extern void fdc_set_dma_ch(fdc_t *fdc, int dma_ch); -extern int fdc_getdata(fdc_t *fdc, int last); -extern int fdc_data(fdc_t *fdc, uint8_t data, int last); +extern void fdc_overrun(fdc_t *fdc); +extern void fdc_set_base(fdc_t *fdc, int base); +extern void fdc_set_irq(fdc_t *fdc, int irq); +extern void fdc_set_dma_ch(fdc_t *fdc, int dma_ch); +extern int fdc_getdata(fdc_t *fdc, int last); +extern int fdc_data(fdc_t *fdc, uint8_t data, int last); -extern void fdc_sectorid(fdc_t *fdc, uint8_t track, uint8_t side, - uint8_t sector, uint8_t size, uint8_t crc1, - uint8_t crc2); +extern void fdc_sectorid(fdc_t *fdc, uint8_t track, uint8_t side, + uint8_t sector, uint8_t size, uint8_t crc1, + uint8_t crc2); -extern uint8_t fdc_read(uint16_t addr, void *priv); -extern void fdc_reset(void *priv); +extern uint8_t fdc_read(uint16_t addr, void *priv); +extern void fdc_reset(void *priv); -extern uint8_t fdc_get_current_drive(void); +extern uint8_t fdc_get_current_drive(void); #ifdef EMU_DEVICE_H -extern const device_t fdc_xt_device; -extern const device_t fdc_xt_t1x00_device; -extern const device_t fdc_xt_tandy_device; -extern const device_t fdc_xt_amstrad_device; -extern const device_t fdc_pcjr_device; -extern const device_t fdc_at_device; -extern const device_t fdc_at_actlow_device; -extern const device_t fdc_at_ps1_device; -extern const device_t fdc_at_smc_device; -extern const device_t fdc_at_winbond_device; -extern const device_t fdc_at_nsc_device; -extern const device_t fdc_dp8473_device; -extern const device_t fdc_um8398_device; +extern const device_t fdc_xt_device; +extern const device_t fdc_xt_sec_device; +extern const device_t fdc_xt_ter_device; +extern const device_t fdc_xt_qua_device; +extern const device_t fdc_xt_t1x00_device; +extern const device_t fdc_xt_tandy_device; +extern const device_t fdc_xt_amstrad_device; +extern const device_t fdc_pcjr_device; +extern const device_t fdc_at_device; +extern const device_t fdc_at_sec_device; +extern const device_t fdc_at_ter_device; +extern const device_t fdc_at_qua_device; +extern const device_t fdc_at_actlow_device; +extern const device_t fdc_at_ps1_device; +extern const device_t fdc_at_smc_device; +extern const device_t fdc_at_ali_device; +extern const device_t fdc_at_winbond_device; +extern const device_t fdc_at_nsc_device; +extern const device_t fdc_dp8473_device; +extern const device_t fdc_um8398_device; #endif -#endif /*EMU_FDC_H*/ +#endif /*EMU_FDC_H*/ diff --git a/src/include/86box/fdc_ext.h b/src/include/86box/fdc_ext.h index c87786dc0..0d821ac11 100644 --- a/src/include/86box/fdc_ext.h +++ b/src/include/86box/fdc_ext.h @@ -1,42 +1,44 @@ /* - * 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. + * 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. + * This file is part of the 86Box distribution. * - * Implementation of the NEC uPD-765 and compatible floppy disk - * controller. + * Implementation of the NEC uPD-765 and compatible floppy disk + * controller. * * * - * Authors: Sarah Walker, - * Miran Grca, - * Fred N. van Kempen, + * Authors: Sarah Walker, + * Miran Grca, + * Fred N. van Kempen, * - * Copyright 2008-2020 Sarah Walker. - * Copyright 2016-2020 Miran Grca. - * Copyright 2018-2020 Fred N. van Kempen. + * Copyright 2008-2020 Sarah Walker. + * Copyright 2016-2020 Miran Grca. + * Copyright 2018-2020 Fred N. van Kempen. */ #ifndef EMU_FDC_EXT_H -# define EMU_FDC_EXT_H +#define EMU_FDC_EXT_H extern int fdc_type; /* Controller types. */ -#define FDC_INTERNAL 0 +#define FDC_INTERNAL 0 extern const device_t fdc_b215_device; extern const device_t fdc_pii151b_device; extern const device_t fdc_pii158b_device; +extern const device_t fdc_monster_device; + extern void fdc_card_init(void); -extern char *fdc_card_get_internal_name(int card); -extern int fdc_card_get_from_internal_name(char *s); +extern const char *fdc_card_get_internal_name(int card); +extern int fdc_card_get_from_internal_name(char *s); extern const device_t *fdc_card_getdevice(int card); -extern int fdc_card_has_config(int card); -extern int fdc_card_available(int card); +extern int fdc_card_has_config(int card); +extern int fdc_card_available(int card); -#endif /*EMU_FDC_H*/ +#endif /*EMU_FDC_H*/ diff --git a/src/include/86box/fdd.h b/src/include/86box/fdd.h index ea0102cbd..0331f4fcc 100644 --- a/src/include/86box/fdd.h +++ b/src/include/86box/fdd.h @@ -1,196 +1,193 @@ /* - * 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. + * 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. + * This file is part of the 86Box distribution. * - * Definitions for the floppy drive emulation. + * Definitions for the floppy drive emulation. * * * - * Authors: Sarah Walker, - * Miran Grca, - * Fred N. van Kempen, + * Authors: Sarah Walker, + * Miran Grca, + * Fred N. van Kempen, * - * Copyright 2008-2018 Sarah Walker. - * Copyright 2016-2018 Miran Grca. - * Copyright 2018 Fred N. van Kempen. + * Copyright 2008-2018 Sarah Walker. + * Copyright 2016-2018 Miran Grca. + * Copyright 2018 Fred N. van Kempen. */ #ifndef EMU_FDD_H -# define EMU_FDD_H - - -#define FDD_NUM 4 -#define SEEK_RECALIBRATE -999 +#define EMU_FDD_H +#define FDD_NUM 4 +#define FLOPPY_IMAGE_HISTORY 4 +#define SEEK_RECALIBRATE -999 #ifdef __cplusplus extern "C" { #endif -extern int fdd_swap; +extern int fdd_swap; -extern void fdd_set_motor_enable(int drive, int motor_enable); -extern void fdd_do_seek(int drive, int track); -extern void fdd_forced_seek(int drive, int track_diff); -extern void fdd_seek(int drive, int track_diff); -extern int fdd_track0(int drive); -extern int fdd_getrpm(int drive); -extern void fdd_set_densel(int densel); -extern int fdd_can_read_medium(int drive); -extern int fdd_doublestep_40(int drive); -extern int fdd_is_525(int drive); -extern int fdd_is_dd(int drive); -extern int fdd_is_ed(int drive); -extern int fdd_is_double_sided(int drive); -extern void fdd_set_head(int drive, int head); -extern int fdd_get_head(int drive); -extern void fdd_set_turbo(int drive, int turbo); -extern int fdd_get_turbo(int drive); -extern void fdd_set_check_bpb(int drive, int check_bpb); -extern int fdd_get_check_bpb(int drive); +extern void fdd_set_motor_enable(int drive, int motor_enable); +extern void fdd_do_seek(int drive, int track); +extern void fdd_forced_seek(int drive, int track_diff); +extern void fdd_seek(int drive, int track_diff); +extern int fdd_track0(int drive); +extern int fdd_getrpm(int drive); +extern void fdd_set_densel(int densel); +extern int fdd_can_read_medium(int drive); +extern int fdd_doublestep_40(int drive); +extern int fdd_is_525(int drive); +extern int fdd_is_dd(int drive); +extern int fdd_is_hd(int drive); +extern int fdd_is_ed(int drive); +extern int fdd_is_double_sided(int drive); +extern void fdd_set_head(int drive, int head); +extern int fdd_get_head(int drive); +extern void fdd_set_turbo(int drive, int turbo); +extern int fdd_get_turbo(int drive); +extern void fdd_set_check_bpb(int drive, int check_bpb); +extern int fdd_get_check_bpb(int drive); -extern void fdd_set_type(int drive, int type); -extern int fdd_get_type(int drive); +extern void fdd_set_type(int drive, int type); +extern int fdd_get_type(int drive); -extern int fdd_get_flags(int drive); -extern int fdd_get_densel(int drive); +extern int fdd_get_flags(int drive); +extern int fdd_get_densel(int drive); -extern char *fdd_getname(int type); +extern char *fdd_getname(int type); -extern char *fdd_get_internal_name(int type); -extern int fdd_get_from_internal_name(char *s); +extern char *fdd_get_internal_name(int type); +extern int fdd_get_from_internal_name(char *s); -extern int fdd_current_track(int drive); +extern int fdd_current_track(int drive); +typedef struct DRIVE { + int id; -typedef struct { - int id; - - void (*seek)(int drive, int track); - void (*readsector)(int drive, int sector, int track, int side, - int density, int sector_size); - void (*writesector)(int drive, int sector, int track, int side, - int density, int sector_size); - void (*comparesector)(int drive, int sector, int track, int side, - int density, int sector_size); - void (*readaddress)(int drive, int side, int density); - void (*format)(int drive, int side, int density, uint8_t fill); - int (*hole)(int drive); - uint64_t (*byteperiod)(int drive); - void (*stop)(int drive); - void (*poll)(int drive); + void (*seek)(int drive, int track); + void (*readsector)(int drive, int sector, int track, int side, + int density, int sector_size); + void (*writesector)(int drive, int sector, int track, int side, + int density, int sector_size); + void (*comparesector)(int drive, int sector, int track, int side, + int density, int sector_size); + void (*readaddress)(int drive, int side, int density); + void (*format)(int drive, int side, int density, uint8_t fill); + int (*hole)(int drive); + uint64_t (*byteperiod)(int drive); + void (*stop)(int drive); + void (*poll)(int drive); } DRIVE; +extern DRIVE drives[FDD_NUM]; +extern char floppyfns[FDD_NUM][512]; +extern char *fdd_image_history[FDD_NUM][FLOPPY_IMAGE_HISTORY]; +extern pc_timer_t fdd_poll_time[FDD_NUM]; +extern int ui_writeprot[FDD_NUM]; -extern DRIVE drives[FDD_NUM]; -extern char floppyfns[FDD_NUM][512]; -extern pc_timer_t fdd_poll_time[FDD_NUM]; -extern int ui_writeprot[FDD_NUM]; +extern int curdrive; -extern int curdrive; +extern int fdd_time; +extern int64_t floppytime; -extern int fdd_time; -extern int64_t floppytime; +extern void fdd_load(int drive, char *fn); +extern void fdd_new(int drive, char *fn); +extern void fdd_close(int drive); +extern void fdd_init(void); +extern void fdd_reset(void); +extern void fdd_seek(int drive, int track); +extern void fdd_readsector(int drive, int sector, int track, + int side, int density, int sector_size); +extern void fdd_writesector(int drive, int sector, int track, + int side, int density, int sector_size); +extern void fdd_comparesector(int drive, int sector, int track, + int side, int density, int sector_size); +extern void fdd_readaddress(int drive, int side, int density); +extern void fdd_format(int drive, int side, int density, uint8_t fill); +extern int fdd_hole(int drive); +extern void fdd_stop(int drive); +extern void fdd_do_writeback(int drive); +extern int motorspin; +extern uint64_t motoron[FDD_NUM]; -extern void fdd_load(int drive, char *fn); -extern void fdd_new(int drive, char *fn); -extern void fdd_close(int drive); -extern void fdd_init(void); -extern void fdd_reset(void); -extern void fdd_seek(int drive, int track); -extern void fdd_readsector(int drive, int sector, int track, - int side, int density, int sector_size); -extern void fdd_writesector(int drive, int sector, int track, - int side, int density, int sector_size); -extern void fdd_comparesector(int drive, int sector, int track, - int side, int density, int sector_size); -extern void fdd_readaddress(int drive, int side, int density); -extern void fdd_format(int drive, int side, int density, uint8_t fill); -extern int fdd_hole(int drive); -extern void fdd_stop(int drive); -extern void fdd_do_writeback(int drive); +extern int swwp; +extern int disable_write; -extern int motorspin; -extern uint64_t motoron[FDD_NUM]; +extern int defaultwriteprot; -extern int swwp; -extern int disable_write; - -extern int defaultwriteprot; - -extern int writeprot[FDD_NUM], fwriteprot[FDD_NUM]; -extern int fdd_changed[FDD_NUM]; -extern int drive_empty[FDD_NUM]; +extern int writeprot[FDD_NUM]; +extern int fwriteprot[FDD_NUM]; +extern int fdd_changed[FDD_NUM]; +extern int drive_empty[FDD_NUM]; /*Used in the Read A Track command. Only valid for fdd_readsector(). */ #define SECTOR_FIRST -2 #define SECTOR_NEXT -1 typedef union { - uint16_t word; - uint8_t bytes[2]; + uint16_t word; + uint8_t bytes[2]; } crc_t; void fdd_calccrc(uint8_t byte, crc_t *crc_var); -typedef struct { - uint16_t (*disk_flags)(int drive); - uint16_t (*side_flags)(int drive); - void (*writeback)(int drive); - void (*set_sector)(int drive, int side, uint8_t c, uint8_t h, - uint8_t r, uint8_t n); - uint8_t (*read_data)(int drive, int side, uint16_t pos); - void (*write_data)(int drive, int side, uint16_t pos, - uint8_t data); - int (*format_conditions)(int drive); - int32_t (*extra_bit_cells)(int drive, int side); - uint16_t* (*encoded_data)(int drive, int side); - void (*read_revolution)(int drive); - uint32_t (*index_hole_pos)(int drive, int side); - uint32_t (*get_raw_size)(int drive, int side); +typedef struct d86f_handler_t { + uint16_t (*disk_flags)(int drive); + uint16_t (*side_flags)(int drive); + void (*writeback)(int drive); + void (*set_sector)(int drive, int side, uint8_t c, uint8_t h, + uint8_t r, uint8_t n); + uint8_t (*read_data)(int drive, int side, uint16_t pos); + void (*write_data)(int drive, int side, uint16_t pos, + uint8_t data); + int (*format_conditions)(int drive); + int32_t (*extra_bit_cells)(int drive, int side); + uint16_t *(*encoded_data)(int drive, int side); + void (*read_revolution)(int drive); + uint32_t (*index_hole_pos)(int drive, int side); + uint32_t (*get_raw_size)(int drive, int side); uint8_t check_crc; } d86f_handler_t; -extern const int gap3_sizes[5][8][48]; +extern const int gap3_sizes[5][8][48]; -extern const uint8_t dmf_r[21]; -extern const uint8_t xdf_physical_sectors[2][2]; -extern const uint8_t xdf_gap3_sizes[2][2]; -extern const uint16_t xdf_trackx_spos[2][8]; +extern const uint8_t dmf_r[21]; +extern const uint8_t xdf_physical_sectors[2][2]; +extern const uint8_t xdf_gap3_sizes[2][2]; +extern const uint16_t xdf_trackx_spos[2][8]; -typedef struct { - uint8_t h; - uint8_t r; +typedef struct xdf_id_t { + uint8_t h; + uint8_t r; } xdf_id_t; typedef union { - uint16_t word; - xdf_id_t id; + uint16_t word; + xdf_id_t id; } xdf_sector_t; extern const xdf_sector_t xdf_img_layout[2][2][46]; extern const xdf_sector_t xdf_disk_layout[2][2][38]; - -typedef struct { - uint8_t c; - uint8_t h; - uint8_t r; - uint8_t n; +typedef struct sector_id_fields_t { + uint8_t c; + uint8_t h; + uint8_t r; + uint8_t n; } sector_id_fields_t; -typedef union { - uint32_t dword; - uint8_t byte_array[4]; +typedef union sector_id_t { + uint32_t dword; + uint8_t byte_array[4]; sector_id_fields_t id; } sector_id_t; - void d86f_set_fdc(void *fdc); void fdi_set_fdc(void *fdc); void fdd_set_fdc(void *fdc); @@ -198,10 +195,8 @@ void imd_set_fdc(void *fdc); void img_set_fdc(void *fdc); void mfm_set_fdc(void *fdc); - #ifdef __cplusplus } #endif - -#endif /*EMU_FDD_H*/ +#endif /*EMU_FDD_H*/ diff --git a/src/include/86box/fdd_86f.h b/src/include/86box/fdd_86f.h index 81ac9ed0f..cc8035965 100644 --- a/src/include/86box/fdd_86f.h +++ b/src/include/86box/fdd_86f.h @@ -1,110 +1,106 @@ /* - * 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. + * 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. + * This file is part of the 86Box distribution. * - * Definitions for the 86F floppy image format. + * Definitions for the 86F floppy image format. * * * - * Authors: Miran Grca, - * Fred N. van Kempen, + * Authors: Miran Grca, + * Fred N. van Kempen, * - * Copyright 2016-2019 Miran Grca. - * Copyright 2018,2019 Fred N. van Kempen. + * Copyright 2016-2019 Miran Grca. + * Copyright 2018-2019 Fred N. van Kempen. */ #ifndef EMU_FLOPPY_86F_H -# define EMU_FLOPPY_86F_H +#define EMU_FLOPPY_86F_H - -#define D86FVER 0x020C +#define D86FVER 0x020C /* Thesere were borrowed from TeleDisk. */ -#define SECTOR_DUPLICATED 0x01 -#define SECTOR_CRC_ERROR 0x02 -#define SECTOR_DELETED_DATA 0x04 -#define SECTOR_DATA_SKIPPED 0x10 -#define SECTOR_NO_DATA 0x20 -#define SECTOR_NO_ID 0x40 +#define SECTOR_DUPLICATED 0x01 +#define SECTOR_CRC_ERROR 0x02 +#define SECTOR_DELETED_DATA 0x04 +#define SECTOR_DATA_SKIPPED 0x10 +#define SECTOR_NO_DATA 0x20 +#define SECTOR_NO_ID 0x40 -#define length_gap0 80 -#define length_gap1 50 -#define length_sync 12 -#define length_am 4 -#define length_crc 2 +#define length_gap0 80 +#define length_gap1 50 +#define length_sync 12 +#define length_am 4 +#define length_crc 2 #define IBM #define MFM #ifdef IBM -#define pre_gap1 length_gap0 + length_sync + length_am +# define pre_gap1 length_gap0 + length_sync + length_am #else -#define pre_gap1 0 +# define pre_gap1 0 #endif - -#define pre_track pre_gap1 + length_gap1 -#define pre_gap length_sync + length_am + 4 + length_crc -#define pre_data length_sync + length_am -#define post_gap length_crc +#define pre_track pre_gap1 + length_gap1 +#define pre_gap length_sync + length_am + 4 + length_crc +#define pre_data length_sync + length_am +#define post_gap length_crc -extern d86f_handler_t d86f_handler[FDD_NUM]; +extern d86f_handler_t d86f_handler[FDD_NUM]; +extern void d86f_init(void); +extern void d86f_load(int drive, char *fn); +extern void d86f_close(int drive); +extern void d86f_seek(int drive, int track); +extern int d86f_hole(int drive); +extern uint64_t d86f_byteperiod(int drive); +extern void d86f_stop(int drive); +extern void d86f_poll(int drive); +extern int d86f_realtrack(int track, int drive); +extern void d86f_reset(int drive, int side); +extern void d86f_readsector(int drive, int sector, int track, int side, int density, int sector_size); +extern void d86f_writesector(int drive, int sector, int track, int side, int density, int sector_size); +extern void d86f_comparesector(int drive, int sector, int track, int side, int rate, int sector_size); +extern void d86f_readaddress(int drive, int side, int density); +extern void d86f_format(int drive, int side, int density, uint8_t fill); -extern void d86f_init(void); -extern void d86f_load(int drive, char *fn); -extern void d86f_close(int drive); -extern void d86f_seek(int drive, int track); -extern int d86f_hole(int drive); -extern uint64_t d86f_byteperiod(int drive); -extern void d86f_stop(int drive); -extern void d86f_poll(int drive); -extern int d86f_realtrack(int track, int drive); -extern void d86f_reset(int drive, int side); -extern void d86f_readsector(int drive, int sector, int track, int side, int density, int sector_size); -extern void d86f_writesector(int drive, int sector, int track, int side, int density, int sector_size); -extern void d86f_comparesector(int drive, int sector, int track, int side, int rate, int sector_size); -extern void d86f_readaddress(int drive, int side, int density); -extern void d86f_format(int drive, int side, int density, uint8_t fill); +extern void d86f_prepare_track_layout(int drive, int side); +extern void d86f_set_version(int drive, uint16_t version); +extern uint16_t d86f_side_flags(int drive); +extern uint16_t d86f_track_flags(int drive); +extern void d86f_initialize_last_sector_id(int drive, int c, int h, int r, int n); +extern void d86f_initialize_linked_lists(int drive); +extern void d86f_destroy_linked_lists(int drive, int side); -extern void d86f_prepare_track_layout(int drive, int side); -extern void d86f_set_version(int drive, uint16_t version); -extern uint16_t d86f_side_flags(int drive); -extern uint16_t d86f_track_flags(int drive); -extern void d86f_initialize_last_sector_id(int drive, int c, int h, int r, int n); -extern void d86f_initialize_linked_lists(int drive); -extern void d86f_destroy_linked_lists(int drive, int side); +extern uint16_t d86f_prepare_sector(int drive, int side, int prev_pos, uint8_t *id_buf, uint8_t *data_buf, + int data_len, int gap2, int gap3, int flags); +extern void d86f_setup(int drive); +extern void d86f_destroy(int drive); +extern int d86f_export(int drive, char *fn); +extern void d86f_unregister(int drive); +extern void d86f_common_handlers(int drive); +extern void d86f_set_version(int drive, uint16_t version); +extern int d86f_is_40_track(int drive); +extern void d86f_reset_index_hole_pos(int drive, int side); +extern uint16_t d86f_prepare_pretrack(int drive, int side, int iso); +extern void d86f_set_track_pos(int drive, uint32_t track_pos); +extern void d86f_set_cur_track(int drive, int track); +extern void d86f_zero_track(int drive); +extern void d86f_initialize_last_sector_id(int drive, int c, int h, int r, int n); +extern void d86f_initialize_linked_lists(int drive); +extern void d86f_destroy_linked_lists(int drive, int side); -extern uint16_t d86f_prepare_sector(int drive, int side, int prev_pos, uint8_t *id_buf, uint8_t *data_buf, - int data_len, int gap2, int gap3, int flags); -extern void d86f_setup(int drive); -extern void d86f_destroy(int drive); -extern int d86f_export(int drive, char *fn); -extern void d86f_unregister(int drive); -extern void d86f_common_handlers(int drive); -extern void d86f_set_version(int drive, uint16_t version); -extern int d86f_is_40_track(int drive); -extern void d86f_reset_index_hole_pos(int drive, int side); -extern uint16_t d86f_prepare_pretrack(int drive, int side, int iso); -extern void d86f_set_track_pos(int drive, uint32_t track_pos); -extern void d86f_set_cur_track(int drive, int track); -extern void d86f_zero_track(int drive); -extern void d86f_initialize_last_sector_id(int drive, int c, int h, int r, int n); -extern void d86f_initialize_linked_lists(int drive); -extern void d86f_destroy_linked_lists(int drive, int side); +extern uint16_t *common_encoded_data(int drive, int side); +extern void common_read_revolution(int drive); +extern uint32_t common_get_raw_size(int drive, int side); -extern uint16_t *common_encoded_data(int drive, int side); -extern void common_read_revolution(int drive); -extern uint32_t common_get_raw_size(int drive, int side); +extern void null_writeback(int drive); +extern void null_write_data(int drive, int side, uint16_t pos, uint8_t data); +extern int null_format_conditions(int drive); +extern int32_t null_extra_bit_cells(int drive, int side); +extern void null_set_sector(int drive, int side, uint8_t c, uint8_t h, uint8_t r, uint8_t n); +extern uint32_t null_index_hole_pos(int drive, int side); -extern void null_writeback(int drive); -extern void null_write_data(int drive, int side, uint16_t pos, uint8_t data); -extern int null_format_conditions(int drive); -extern int32_t null_extra_bit_cells(int drive, int side); -extern void null_set_sector(int drive, int side, uint8_t c, uint8_t h, uint8_t r, uint8_t n); -extern uint32_t null_index_hole_pos(int drive, int side); - - -#endif /*EMU_FLOPPY_86F_H*/ +#endif /*EMU_FLOPPY_86F_H*/ diff --git a/src/include/86box/fdd_common.h b/src/include/86box/fdd_common.h index e904aaaa6..7673d9684 100644 --- a/src/include/86box/fdd_common.h +++ b/src/include/86box/fdd_common.h @@ -1,35 +1,32 @@ /* - * 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. + * 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. + * This file is part of the 86Box distribution. * - * Shared code for all the floppy modules. + * Shared code for all the floppy modules. * * * - * Author: Fred N. van Kempen, + * Authors: Fred N. van Kempen, * - * Copyright 2017,2018 Fred N. van Kempen. + * Copyright 2017-2018 Fred N. van Kempen. */ #ifndef FDD_COMMON_H -# define FDD_COMMON_H +#define FDD_COMMON_H +extern const uint8_t fdd_holes[6]; +extern const uint8_t fdd_rates[6]; +extern const double fdd_bit_rates_300[6]; +extern const uint8_t fdd_max_sectors[8][6]; +extern const uint8_t fdd_dmf_r[21]; -extern const uint8_t fdd_holes[6]; -extern const uint8_t fdd_rates[6]; -extern const double fdd_bit_rates_300[6]; -extern const uint8_t fdd_max_sectors[8][6]; -extern const uint8_t fdd_dmf_r[21]; +extern int fdd_get_gap3_size(int rate, int size, int sector); +extern uint8_t fdd_sector_size_code(int size); +extern int fdd_sector_code_size(uint8_t code); +extern int fdd_bps_valid(uint16_t bps); +extern int fdd_interleave(int sector, int skew, int spt); - -extern int fdd_get_gap3_size(int rate, int size, int sector); -extern uint8_t fdd_sector_size_code(int size); -extern int fdd_sector_code_size(uint8_t code); -extern int fdd_bps_valid(uint16_t bps); -extern int fdd_interleave(int sector, int skew, int spt); - - -#endif /*FDD_COMMON_H*/ +#endif /*FDD_COMMON_H*/ diff --git a/src/include/86box/fdd_fdi.h b/src/include/86box/fdd_fdi.h index e6d75c664..6b9461bad 100644 --- a/src/include/86box/fdd_fdi.h +++ b/src/include/86box/fdd_fdi.h @@ -1,31 +1,29 @@ /* - * 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. + * 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. + * This file is part of the 86Box distribution. * - * Implementation of the FDI floppy stream image format - * interface to the FDI2RAW module. + * Implementation of the FDI floppy stream image format + * interface to the FDI2RAW module. * * * - * Authors: Sarah Walker, - * Miran Grca, - * Fred N. van Kempen, + * Authors: Sarah Walker, + * Miran Grca, + * Fred N. van Kempen, * - * Copyright 2008-2018 Sarah Walker. - * Copyright 2016-2018 Miran Grca. - * Copyright 2018 Fred N. van Kempen. + * Copyright 2008-2018 Sarah Walker. + * Copyright 2016-2018 Miran Grca. + * Copyright 2018 Fred N. van Kempen. */ #ifndef EMU_FLOPPY_FDI_H -# define EMU_FLOPPY_FDI_H +#define EMU_FLOPPY_FDI_H +extern void fdi_seek(int drive, int track); +extern void fdi_load(int drive, char *fn); +extern void fdi_close(int drive); -extern void fdi_seek(int drive, int track); -extern void fdi_load(int drive, char *fn); -extern void fdi_close(int drive); - - -#endif /*EMU_FLOPPY_FDI_H*/ +#endif /*EMU_FLOPPY_FDI_H*/ diff --git a/src/include/86box/fdd_imd.h b/src/include/86box/fdd_imd.h index 3c20025d2..f50ad865e 100644 --- a/src/include/86box/fdd_imd.h +++ b/src/include/86box/fdd_imd.h @@ -1,20 +1,20 @@ /* - * 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. + * 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. + * This file is part of the 86Box distribution. * - * Definitions for the IMD floppy image format. + * Definitions for the IMD floppy image format. * * * - * Authors: Miran Grca, - * Fred N. van Kempen, + * Authors: Miran Grca, + * Fred N. van Kempen, * - * Copyright 2016-2018 Miran Grca. - * Copyright 2018 Fred N. van Kempen. + * Copyright 2016-2018 Miran Grca. + * Copyright 2018 Fred N. van Kempen. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -35,12 +35,10 @@ * USA. */ #ifndef EMU_FLOPPY_IMD_H -# define EMU_FLOPPY_IMD_H - +#define EMU_FLOPPY_IMD_H extern void imd_init(void); extern void imd_load(int drive, char *fn); extern void imd_close(int drive); - -#endif /*EMU_FLOPPY_IMD_H*/ +#endif /*EMU_FLOPPY_IMD_H*/ diff --git a/src/include/86box/fdd_img.h b/src/include/86box/fdd_img.h index bb39fed09..f0a639d88 100644 --- a/src/include/86box/fdd_img.h +++ b/src/include/86box/fdd_img.h @@ -1,31 +1,29 @@ /* - * 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. + * 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. + * This file is part of the 86Box distribution. * - * Implementation of the raw sector-based floppy image format, - * as well as the Japanese FDI, CopyQM, and FDF formats. + * Implementation of the raw sector-based floppy image format, + * as well as the Japanese FDI, CopyQM, and FDF formats. * * * - * Authors: Sarah Walker, - * Miran Grca, - * Fred N. van Kempen, + * Authors: Sarah Walker, + * Miran Grca, + * Fred N. van Kempen, * - * Copyright 2008-2018 Sarah Walker. - * Copyright 2016-2018 Miran Grca. - * Copyright 2018 Fred N. van Kempen. + * Copyright 2008-2018 Sarah Walker. + * Copyright 2016-2018 Miran Grca. + * Copyright 2018 Fred N. van Kempen. */ #ifndef EMU_FLOPPY_IMG_H -# define EMU_FLOPPY_IMG_H +#define EMU_FLOPPY_IMG_H +extern void img_init(void); +extern void img_load(int drive, char *fn); +extern void img_close(int drive); -extern void img_init(void); -extern void img_load(int drive, char *fn); -extern void img_close(int drive); - - -#endif /*EMU_FLOPPY_IMG_H*/ +#endif /*EMU_FLOPPY_IMG_H*/ diff --git a/src/include/86box/fdd_json.h b/src/include/86box/fdd_json.h index 4a62c089b..7f3c9adb4 100644 --- a/src/include/86box/fdd_json.h +++ b/src/include/86box/fdd_json.h @@ -1,36 +1,34 @@ /* - * VARCem Virtual ARchaeological Computer EMulator. - * An emulator of (mostly) x86-based PC systems and devices, - * using the ISA,EISA,VLB,MCA and PCI system buses, roughly - * spanning the era between 1981 and 1995. + * VARCem Virtual ARchaeological Computer EMulator. + * An emulator of (mostly) x86-based PC systems and devices, + * using the ISA,EISA,VLB,MCA and PCI system buses, roughly + * spanning the era between 1981 and 1995. * - * This file is part of the VARCem Project. - * - * Definitions for the PCjs JSON floppy image format. + * Definitions for the PCjs JSON floppy image format. * * * - * Author: Fred N. van Kempen, + * Authors: Fred N. van Kempen, * - * Copyright 2017,2018 Fred N. van Kempen. + * Copyright 2017-2018 Fred N. van Kempen. * - * Redistribution and use in source and binary forms, with - * or without modification, are permitted provided that the - * following conditions are met: + * Redistribution and use in source and binary forms, with + * or without modification, are permitted provided that the + * following conditions are met: * - * 1. Redistributions of source code must retain the entire - * above notice, this list of conditions and the following - * disclaimer. + * 1. Redistributions of source code must retain the entire + * above notice, this list of conditions and the following + * disclaimer. * - * 2. Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the - * following disclaimer in the documentation and/or other - * materials provided with the distribution. + * 2. Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the + * following disclaimer in the documentation and/or other + * materials provided with the distribution. * - * 3. Neither the name of the copyright holder nor the names - * of its contributors may be used to endorse or promote - * products derived from this software without specific - * prior written permission. + * 3. Neither the name of the copyright holder nor the names + * of its contributors may be used to endorse or promote + * products derived from this software without specific + * prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT @@ -45,12 +43,10 @@ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #ifndef EMU_FLOPPY_JSON_H -# define EMU_FLOPPY_JSON_H +#define EMU_FLOPPY_JSON_H +extern void json_init(void); +extern void json_load(int drive, char *fn); +extern void json_close(int drive); -extern void json_init(void); -extern void json_load(int drive, char *fn); -extern void json_close(int drive); - - -#endif /*EMU_FLOPPY_JSON_H*/ +#endif /*EMU_FLOPPY_JSON_H*/ diff --git a/src/include/86box/fdd_mfm.h b/src/include/86box/fdd_mfm.h index 5fd664b05..3a8494a26 100644 --- a/src/include/86box/fdd_mfm.h +++ b/src/include/86box/fdd_mfm.h @@ -1,26 +1,24 @@ /* - * 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. + * 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. + * This file is part of the 86Box distribution. * - * Implementation of the HxC MFM image format. + * Implementation of the HxC MFM image format. * * * - * Authors: Miran Grca, + * Authors: Miran Grca, * - * Copyright 2018 Miran Grca. + * Copyright 2018 Miran Grca. */ #ifndef EMU_FLOPPY_MFM_H -# define EMU_FLOPPY_MFM_H +#define EMU_FLOPPY_MFM_H +extern void mfm_seek(int drive, int track); +extern void mfm_load(int drive, char *fn); +extern void mfm_close(int drive); -extern void mfm_seek(int drive, int track); -extern void mfm_load(int drive, char *fn); -extern void mfm_close(int drive); - - -#endif /*EMU_FLOPPY_MFM_H*/ +#endif /*EMU_FLOPPY_MFM_H*/ diff --git a/src/include/86box/fdd_td0.h b/src/include/86box/fdd_td0.h index 6dd79a8ce..add6a07dd 100644 --- a/src/include/86box/fdd_td0.h +++ b/src/include/86box/fdd_td0.h @@ -1,28 +1,26 @@ /* - * 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. + * 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. + * This file is part of the 86Box distribution. * - * Definitions for the Teledisk floppy image format. + * Definitions for the Teledisk floppy image format. * * * - * Authors: Miran Grca, - * Fred N. van Kempen, + * Authors: Miran Grca, + * Fred N. van Kempen, * - * Copyright 2016-2018 Miran Grca. - * Copyright 2017,2018 Fred N. van Kempen. + * Copyright 2016-2018 Miran Grca. + * Copyright 2017-2018 Fred N. van Kempen. */ #ifndef EMU_FLOPPY_TD0_H -# define EMU_FLOPPY_TD0_H - +#define EMU_FLOPPY_TD0_H extern void td0_init(void); extern void td0_load(int drive, char *fn); extern void td0_close(int drive); - -#endif /*EMU_FLOPPY_TD0_H*/ +#endif /*EMU_FLOPPY_TD0_H*/ diff --git a/src/include/86box/fifo.h b/src/include/86box/fifo.h new file mode 100644 index 000000000..e76189d8a --- /dev/null +++ b/src/include/86box/fifo.h @@ -0,0 +1,73 @@ +/* + * 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. + * + * FIFO infrastructure header. + * + * Authors: Miran Grca, + * + * Copyright 2023 Miran Grca. + */ +#define FIFO(size) \ + typedef struct { \ + int start; \ + int end; \ + int trigger_len; \ + int len; \ + int empty; \ + int overrun; \ + int full; \ + int ready; \ + int d_empty; \ + int d_overrun; \ + int d_full; \ + int d_ready; \ + \ + void *priv; \ + \ + void (*d_empty_evt)(void *); \ + void (*d_overrun_evt)(void *); \ + void (*d_full_evt)(void *); \ + void (*d_ready_evt)(void *); \ + \ + uint8_t buf[size]; \ + } fifo## size ##_t; + +FIFO() + +FIFO(16) +#define fifo16_init() fifo_init(16) + +FIFO(64) +#define fifo64_init() fifo_init(64) + +extern int fifo_get_count(void *priv); +extern void fifo_write(uint8_t val, void *priv); +extern void fifo_write_evt(uint8_t val, void *priv); +extern uint8_t fifo_read(void *priv); +extern uint8_t fifo_read_evt(void *priv); +extern void fifo_clear_overrun(void *priv); +extern int fifo_get_full(void *priv); +extern int fifo_get_d_full(void *priv); +extern int fifo_get_empty(void *priv); +extern int fifo_get_d_empty(void *priv); +extern int fifo_get_overrun(void *priv); +extern int fifo_get_d_overrun(void *priv); +extern int fifo_get_ready(void *priv); +extern int fifo_get_d_ready(void *priv); +extern int fifo_get_trigger_len(void *priv); +extern void fifo_set_trigger_len(void *priv, int trigger_len); +extern void fifo_set_len(void *priv, int len); +extern void fifo_set_d_full_evt(void *priv, void (*d_full_evt)(void *)); +extern void fifo_set_d_empty_evt(void *priv, void (*d_empty_evt)(void *)); +extern void fifo_set_d_overrun_evt(void *priv, void (*d_overrun_evt)(void *)); +extern void fifo_set_d_ready_evt(void *priv, void (*d_ready_evt)(void *)); +extern void fifo_set_priv(void *priv, void *sub_priv); +extern void fifo_reset(void *priv); +extern void fifo_reset_evt(void *priv); +extern void fifo_close(void *priv); +extern void *fifo_init(int len); diff --git a/src/include/86box/fifo8.h b/src/include/86box/fifo8.h index d1c32fdd7..9f88ec408 100644 --- a/src/include/86box/fifo8.h +++ b/src/include/86box/fifo8.h @@ -1,8 +1,7 @@ #ifndef EMU_FIFO8_H #define EMU_FIFO8_H - -typedef struct { +typedef struct Fifo8 { /* All fields are private */ uint8_t *data; uint32_t capacity; @@ -26,7 +25,7 @@ extern void fifo8_create(Fifo8 *fifo, uint32_t capacity); * @fifo: FIFO to cleanup * * Cleanup a FIFO created with fifo8_create(). Frees memory created for FIFO - *storage. The FIFO is no longer usable after this has been called. + *storage. The FIFO is no longer usable after this has been called. */ extern void fifo8_destroy(Fifo8 *fifo); diff --git a/src/include/86box/filters.h b/src/include/86box/filters.h index 98eff66e2..dfe19c654 100644 --- a/src/include/86box/filters.h +++ b/src/include/86box/filters.h @@ -1,132 +1,143 @@ +#ifndef EMU_FILTERS_H +#define EMU_FILTERS_H + #define NCoef 2 /* fc=150Hz */ -static inline float adgold_highpass_iir(int i, float NewSample) { - float ACoef[NCoef+1] = { +static inline float +adgold_highpass_iir(int i, float NewSample) +{ + float ACoef[NCoef + 1] = { 0.98657437157334349000, -1.97314874314668700000, 0.98657437157334349000 }; - float BCoef[NCoef+1] = { + float BCoef[NCoef + 1] = { 1.00000000000000000000, -1.97223372919758360000, 0.97261396931534050000 }; - static float y[2][NCoef+1]; /* output samples */ - static float x[2][NCoef+1]; /* input samples */ - int n; + static float y[2][NCoef + 1]; /* output samples */ + static float x[2][NCoef + 1]; /* input samples */ + int n; /* shift the old samples */ - for(n=NCoef; n>0; n--) { - x[i][n] = x[i][n-1]; - y[i][n] = y[i][n-1]; + for (n = NCoef; n > 0; n--) { + x[i][n] = x[i][n - 1]; + y[i][n] = y[i][n - 1]; } /* Calculate the new output */ x[i][0] = NewSample; y[i][0] = ACoef[0] * x[i][0]; - for(n=1; n<=NCoef; n++) + for (n = 1; n <= NCoef; n++) y[i][0] += ACoef[n] * x[i][n] - BCoef[n] * y[i][n]; - + return y[i][0]; } /* fc=150Hz */ -static inline float adgold_lowpass_iir(int i, float NewSample) { - float ACoef[NCoef+1] = { +static inline float +adgold_lowpass_iir(int i, float NewSample) +{ + float ACoef[NCoef + 1] = { 0.00009159473951071446, 0.00018318947902142891, 0.00009159473951071446 }; - float BCoef[NCoef+1] = { + float BCoef[NCoef + 1] = { 1.00000000000000000000, -1.97223372919526560000, 0.97261396931306277000 }; - static float y[2][NCoef+1]; /* output samples */ - static float x[2][NCoef+1]; /* input samples */ - int n; + static float y[2][NCoef + 1]; /* output samples */ + static float x[2][NCoef + 1]; /* input samples */ + int n; /* shift the old samples */ - for(n=NCoef; n>0; n--) { - x[i][n] = x[i][n-1]; - y[i][n] = y[i][n-1]; + for (n = NCoef; n > 0; n--) { + x[i][n] = x[i][n - 1]; + y[i][n] = y[i][n - 1]; } /* Calculate the new output */ x[i][0] = NewSample; y[i][0] = ACoef[0] * x[i][0]; - for(n=1; n<=NCoef; n++) + for (n = 1; n <= NCoef; n++) y[i][0] += ACoef[n] * x[i][n] - BCoef[n] * y[i][n]; - + return y[i][0]; } /* fc=56Hz */ -static inline float adgold_pseudo_stereo_iir(float NewSample) { - float ACoef[NCoef+1] = { +static inline float +adgold_pseudo_stereo_iir(float NewSample) +{ + float ACoef[NCoef + 1] = { 0.00001409030866231767, 0.00002818061732463533, 0.00001409030866231767 }; - float BCoef[NCoef+1] = { + float BCoef[NCoef + 1] = { 1.00000000000000000000, -1.98733021473466760000, 0.98738361004063568000 }; - static float y[NCoef+1]; /* output samples */ - static float x[NCoef+1]; /* input samples */ - int n; + static float y[NCoef + 1]; /* output samples */ + static float x[NCoef + 1]; /* input samples */ + int n; /* shift the old samples */ - for(n=NCoef; n>0; n--) { - x[n] = x[n-1]; - y[n] = y[n-1]; + for (n = NCoef; n > 0; n--) { + x[n] = x[n - 1]; + y[n] = y[n - 1]; } /* Calculate the new output */ x[0] = NewSample; y[0] = ACoef[0] * x[0]; - for(n=1; n<=NCoef; n++) + for (n = 1; n <= NCoef; n++) y[0] += ACoef[n] * x[n] - BCoef[n] * y[n]; - + return y[0]; } /* fc=3.2kHz - probably incorrect */ -static inline float dss_iir(float NewSample) { - float ACoef[NCoef+1] = { +static inline float +dss_iir(float NewSample) +{ + float ACoef[NCoef + 1] = { 0.03356837051492005100, 0.06713674102984010200, 0.03356837051492005100 }; - float BCoef[NCoef+1] = { + float BCoef[NCoef + 1] = { 1.00000000000000000000, -1.41898265221812010000, 0.55326988968868285000 }; - - static float y[NCoef+1]; /* output samples */ - static float x[NCoef+1]; /* input samples */ - int n; + + static float y[NCoef + 1]; /* output samples */ + static float x[NCoef + 1]; /* input samples */ + int n; /* shift the old samples */ - for(n=NCoef; n>0; n--) { - x[n] = x[n-1]; - y[n] = y[n-1]; + for (n = NCoef; n > 0; n--) { + x[n] = x[n - 1]; + y[n] = y[n - 1]; } /* Calculate the new output */ x[0] = NewSample; y[0] = ACoef[0] * x[0]; - for(n=1; n<=NCoef; n++) + for (n = 1; n <= NCoef; n++) y[0] += ACoef[n] * x[n] - BCoef[n] * y[n]; return y[0]; @@ -135,197 +146,208 @@ static inline float dss_iir(float NewSample) { #undef NCoef #define NCoef 1 /*Basic high pass to remove DC bias. fc=10Hz*/ -static inline float dac_iir(int i, float NewSample) { - float ACoef[NCoef+1] = { +static inline float +dac_iir(int i, float NewSample) +{ + float ACoef[NCoef + 1] = { 0.99901119820285345000, -0.99901119820285345000 }; - float BCoef[NCoef+1] = { + float BCoef[NCoef + 1] = { 1.00000000000000000000, -0.99869185905052738000 }; - static float y[2][NCoef+1]; /* output samples */ - static float x[2][NCoef+1]; /* input samples */ - int n; + static float y[2][NCoef + 1]; /* output samples */ + static float x[2][NCoef + 1]; /* input samples */ + int n; /* shift the old samples */ - for(n=NCoef; n>0; n--) { - x[i][n] = x[i][n-1]; - y[i][n] = y[i][n-1]; + for (n = NCoef; n > 0; n--) { + x[i][n] = x[i][n - 1]; + y[i][n] = y[i][n - 1]; } /* Calculate the new output */ x[i][0] = NewSample; y[i][0] = ACoef[0] * x[i][0]; - for(n=1; n<=NCoef; n++) + for (n = 1; n <= NCoef; n++) y[i][0] += ACoef[n] * x[i][n] - BCoef[n] * y[i][n]; - + return y[i][0]; } - #undef NCoef #define NCoef 2 /* fc=350Hz */ -static inline double low_iir(int c, int i, double NewSample) { - double ACoef[NCoef+1] = { +static inline double +low_iir(int c, int i, double NewSample) +{ + double ACoef[NCoef + 1] = { 0.00049713569693400649, 0.00099427139386801299, 0.00049713569693400649 }; - double BCoef[NCoef+1] = { + double BCoef[NCoef + 1] = { 1.00000000000000000000, -1.93522955470669530000, 0.93726236021404663000 }; - static double y[2][2][NCoef+1]; /* output samples */ - static double x[2][2][NCoef+1]; /* input samples */ - int n; + static double y[3][2][NCoef + 1]; /* output samples */ + static double x[3][2][NCoef + 1]; /* input samples */ + int n; /* shift the old samples */ - for(n=NCoef; n>0; n--) { - x[c][i][n] = x[c][i][n-1]; - y[c][i][n] = y[c][i][n-1]; + for (n = NCoef; n > 0; n--) { + x[c][i][n] = x[c][i][n - 1]; + y[c][i][n] = y[c][i][n - 1]; } /* Calculate the new output */ x[c][i][0] = NewSample; y[c][i][0] = ACoef[0] * x[c][i][0]; - for(n=1; n<=NCoef; n++) + for (n = 1; n <= NCoef; n++) y[c][i][0] += ACoef[n] * x[c][i][n] - BCoef[n] * y[c][i][n]; return y[c][i][0]; } /* fc=350Hz */ -static inline double low_cut_iir(int c, int i, double NewSample) { - double ACoef[NCoef+1] = { +static inline double +low_cut_iir(int c, int i, double NewSample) +{ + double ACoef[NCoef + 1] = { 0.96839970114733542000, -1.93679940229467080000, 0.96839970114733542000 }; - double BCoef[NCoef+1] = { + double BCoef[NCoef + 1] = { 1.00000000000000000000, -1.93522955471202770000, 0.93726236021916731000 }; - static double y[2][2][NCoef+1]; /* output samples */ - static double x[2][2][NCoef+1]; /* input samples */ - int n; + static double y[3][2][NCoef + 1]; /* output samples */ + static double x[3][2][NCoef + 1]; /* input samples */ + int n; /* shift the old samples */ - for(n=NCoef; n>0; n--) { - x[c][i][n] = x[c][i][n-1]; - y[c][i][n] = y[c][i][n-1]; + for (n = NCoef; n > 0; n--) { + x[c][i][n] = x[c][i][n - 1]; + y[c][i][n] = y[c][i][n - 1]; } /* Calculate the new output */ x[c][i][0] = NewSample; y[c][i][0] = ACoef[0] * x[c][i][0]; - for(n=1; n<=NCoef; n++) + for (n = 1; n <= NCoef; n++) y[c][i][0] += ACoef[n] * x[c][i][n] - BCoef[n] * y[c][i][n]; return y[c][i][0]; } /* fc=3.5kHz */ -static inline double high_iir(int c, int i, double NewSample) { - double ACoef[NCoef+1] = { +static inline double +high_iir(int c, int i, double NewSample) +{ + double ACoef[NCoef + 1] = { 0.72248704753064896000, -1.44497409506129790000, 0.72248704753064896000 }; - double BCoef[NCoef+1] = { + double BCoef[NCoef + 1] = { 1.00000000000000000000, -1.36640781670578510000, 0.52352474706139873000 }; - static double y[2][2][NCoef+1]; /* output samples */ - static double x[2][2][NCoef+1]; /* input samples */ - int n; + static double y[3][2][NCoef + 1]; /* output samples */ + static double x[3][2][NCoef + 1]; /* input samples */ + int n; /* shift the old samples */ - for(n=NCoef; n>0; n--) { - x[c][i][n] = x[c][i][n-1]; - y[c][i][n] = y[c][i][n-1]; + for (n = NCoef; n > 0; n--) { + x[c][i][n] = x[c][i][n - 1]; + y[c][i][n] = y[c][i][n - 1]; } /* Calculate the new output */ x[c][i][0] = NewSample; y[c][i][0] = ACoef[0] * x[c][i][0]; - for(n=1; n<=NCoef; n++) + for (n = 1; n <= NCoef; n++) y[c][i][0] += ACoef[n] * x[c][i][n] - BCoef[n] * y[c][i][n]; return y[c][i][0]; } /* fc=3.5kHz */ -static inline double high_cut_iir(int c, int i, double NewSample) { - double ACoef[NCoef+1] = { +static inline double +high_cut_iir(int c, int i, double NewSample) +{ + double ACoef[NCoef + 1] = { 0.03927726802250377400, 0.07855453604500754700, 0.03927726802250377400 }; - double BCoef[NCoef+1] = { + double BCoef[NCoef + 1] = { 1.00000000000000000000, -1.36640781666419950000, 0.52352474703279628000 }; - static double y[2][2][NCoef+1]; /* output samples */ - static double x[2][2][NCoef+1]; /* input samples */ - int n; + static double y[3][2][NCoef + 1]; /* output samples */ + static double x[3][2][NCoef + 1]; /* input samples */ + int n; /* shift the old samples */ - for(n=NCoef; n>0; n--) { - x[c][i][n] = x[c][i][n-1]; - y[c][i][n] = y[c][i][n-1]; + for (n = NCoef; n > 0; n--) { + x[c][i][n] = x[c][i][n - 1]; + y[c][i][n] = y[c][i][n - 1]; } /* Calculate the new output */ x[c][i][0] = NewSample; y[c][i][0] = ACoef[0] * x[c][i][0]; - for(n=1; n<=NCoef; n++) + for (n = 1; n <= NCoef; n++) y[c][i][0] += ACoef[n] * x[c][i][n] - BCoef[n] * y[c][i][n]; return y[c][i][0]; } /* fc=5.283kHz, gain=-9.477dB, width=0.4845 */ -static inline double deemph_iir(int i, double NewSample) { - double ACoef[NCoef+1] = { +static inline double +deemph_iir(int i, double NewSample) +{ + double ACoef[NCoef + 1] = { 0.46035077886318842566, -0.28440821191249848754, 0.03388877229118691936 }; - double BCoef[NCoef+1] = { + double BCoef[NCoef + 1] = { 1.00000000000000000000, -1.05429146278569141337, 0.26412280202756849290 }; - static double y[2][NCoef+1]; /* output samples */ - static double x[2][NCoef+1]; /* input samples */ - int n; + static double y[3][NCoef + 1]; /* output samples */ + static double x[3][NCoef + 1]; /* input samples */ + int n; /* shift the old samples */ - for(n=NCoef; n>0; n--) { - x[i][n] = x[i][n-1]; - y[i][n] = y[i][n-1]; + for (n = NCoef; n > 0; n--) { + x[i][n] = x[i][n - 1]; + y[i][n] = y[i][n - 1]; } /* Calculate the new output */ x[i][0] = NewSample; y[i][0] = ACoef[0] * x[i][0]; - for(n=1; n<=NCoef; n++) + for (n = 1; n <= NCoef; n++) y[i][0] += ACoef[n] * x[i][n] - BCoef[n] * y[i][n]; return y[i][0]; @@ -335,67 +357,69 @@ static inline double deemph_iir(int i, double NewSample) { #define NCoef 2 /* fc=3.2kHz */ -static inline double sb_iir(int c, int i, double NewSample) { - double ACoef[NCoef+1] = { +static inline double +sb_iir(int c, int i, double NewSample) +{ + double ACoef[NCoef + 1] = { 0.03356837051492005100, 0.06713674102984010200, 0.03356837051492005100 }; - double BCoef[NCoef+1] = { + double BCoef[NCoef + 1] = { 1.00000000000000000000, -1.41898265221812010000, 0.55326988968868285000 }; - - static double y[2][2][NCoef+1]; /* output samples */ - static double x[2][2][NCoef+1]; /* input samples */ - int n; + + static double y[3][2][NCoef + 1]; /* output samples */ + static double x[3][2][NCoef + 1]; /* input samples */ + int n; /* shift the old samples */ - for(n=NCoef; n>0; n--) { - x[c][i][n] = x[c][i][n-1]; - y[c][i][n] = y[c][i][n-1]; + for (n = NCoef; n > 0; n--) { + x[c][i][n] = x[c][i][n - 1]; + y[c][i][n] = y[c][i][n - 1]; } /* Calculate the new output */ x[c][i][0] = NewSample; y[c][i][0] = ACoef[0] * x[c][i][0]; - for(n=1; n<=NCoef; n++) + for (n = 1; n <= NCoef; n++) y[c][i][0] += ACoef[n] * x[c][i][n] - BCoef[n] * y[c][i][n]; return y[c][i][0]; } - - #undef NCoef -#define NCoef 1 +#define NCoef 1 #define SB16_NCoef 51 -extern double low_fir_sb16_coef[2][SB16_NCoef]; +extern double low_fir_sb16_coef[3][SB16_NCoef]; -static inline double low_fir_sb16(int c, int i, double NewSample) +static inline double +low_fir_sb16(int c, int i, double NewSample) { - static double x[2][2][SB16_NCoef+1]; //input samples - static int pos[2] = { 0, 0 }; - double out = 0.0; - int n; + static double x[3][2][SB16_NCoef + 1]; // input samples + static int pos[3] = { 0, 0 }; + double out = 0.0; + int n; - /* Calculate the new output */ - x[c][i][pos[c]] = NewSample; + /* Calculate the new output */ + x[c][i][pos[c]] = NewSample; - for (n = 0; n < ((SB16_NCoef+1)-pos[c]) && n < SB16_NCoef; n++) - out += low_fir_sb16_coef[c][n] * x[c][i][n+pos[c]]; - for (; n < SB16_NCoef; n++) - out += low_fir_sb16_coef[c][n] * x[c][i][(n+pos[c]) - (SB16_NCoef+1)]; + for (n = 0; n < ((SB16_NCoef + 1) - pos[c]) && n < SB16_NCoef; n++) + out += low_fir_sb16_coef[c][n] * x[c][i][n + pos[c]]; + for (; n < SB16_NCoef; n++) + out += low_fir_sb16_coef[c][n] * x[c][i][(n + pos[c]) - (SB16_NCoef + 1)]; - if (i == 1) - { - pos[c]++; - if (pos[c] > SB16_NCoef) - pos[c] = 0; - } - - return out; + if (i == 1) { + pos[c]++; + if (pos[c] > SB16_NCoef) + pos[c] = 0; + } + + return out; } + +#endif /*EMU_FILTERS_H*/ diff --git a/src/include/86box/flash.h b/src/include/86box/flash.h index d16814b75..d161d416b 100644 --- a/src/include/86box/flash.h +++ b/src/include/86box/flash.h @@ -1,19 +1,25 @@ /* - * 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. + * 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. + * This file is part of the 86Box distribution. * - * Handling of the emulated flash devices. + * Handling of the emulated flash devices. * * * - * Author: Miran Grca, - * Copyright 2020 Miran Grca. + * Authors: Miran Grca, + * Jasmine Iwanek, + * + * Copyright 2020 Miran Grca. + * Copyright 2022-2023 Jasmine Iwanek. */ +#ifndef EMU_FLASH_H +#define EMU_FLASH_H + extern const device_t catalyst_flash_device; extern const device_t intel_flash_bxt_ami_device; @@ -22,7 +28,36 @@ extern const device_t intel_flash_bxb_device; extern const device_t sst_flash_29ee010_device; extern const device_t sst_flash_29ee020_device; + +extern const device_t winbond_flash_w29c512_device; +extern const device_t winbond_flash_w29c010_device; extern const device_t winbond_flash_w29c020_device; +extern const device_t winbond_flash_w29c040_device; + +extern const device_t sst_flash_39sf512_device; extern const device_t sst_flash_39sf010_device; extern const device_t sst_flash_39sf020_device; -extern const device_t sst_flash_39sf040_device; \ No newline at end of file +extern const device_t sst_flash_39sf040_device; + +extern const device_t sst_flash_39lf512_device; +extern const device_t sst_flash_39lf010_device; +extern const device_t sst_flash_39lf020_device; +extern const device_t sst_flash_39lf040_device; +extern const device_t sst_flash_39lf080_device; +extern const device_t sst_flash_39lf016_device; + +extern const device_t sst_flash_49lf002_device; +extern const device_t sst_flash_49lf020_device; +extern const device_t sst_flash_49lf020a_device; +extern const device_t sst_flash_49lf003_device; +extern const device_t sst_flash_49lf030_device; +extern const device_t sst_flash_49lf004_device; +extern const device_t sst_flash_49lf004c_device; +extern const device_t sst_flash_49lf040_device; +extern const device_t sst_flash_49lf008_device; +extern const device_t sst_flash_49lf008c_device; +extern const device_t sst_flash_49lf080_device; +extern const device_t sst_flash_49lf016_device; +extern const device_t sst_flash_49lf160_device; + +#endif /*EMU_FLASH_H*/ diff --git a/src/include/86box/gameport.h b/src/include/86box/gameport.h index 4bd409d3d..ba3568464 100644 --- a/src/include/86box/gameport.h +++ b/src/include/86box/gameport.h @@ -1,152 +1,165 @@ /* - * 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. + * 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. + * This file is part of the 86Box distribution. * - * Definitions for the generic game port handlers. + * Definitions for the generic game port handlers. * * * - * Authors: Miran Grca, - * Sarah Walker, - * RichardG, + * Authors: Miran Grca, + * Sarah Walker, + * RichardG, * - * Copyright 2016-2018 Miran Grca. - * Copyright 2008-2018 Sarah Walker. - * Copyright 2021 RichardG. + * Copyright 2016-2018 Miran Grca. + * Copyright 2008-2018 Sarah Walker. + * Copyright 2021 RichardG. */ #ifndef EMU_GAMEPORT_H -# define EMU_GAMEPORT_H +#define EMU_GAMEPORT_H + +#define MAX_PLAT_JOYSTICKS 8 +#define MAX_JOYSTICKS 4 + +#define JS_TYPE_NONE 0 +#define JS_TYPE_2AXIS_4BUTTON 1 +#define JS_TYPE_2AXIS_6BUTTON 2 +#define JS_TYPE_2AXIS_8BUTTON 3 +#define JS_TYPE_4AXIS_4BUTTON 4 +#define JS_TYPE_CH_FLIGHTSTICK_PRO 5 +#define JS_TYPE_SIDEWINDER_PAD 6 +#define JS_TYPE_THRUSTMASTER_FCS 7 -#define MAX_PLAT_JOYSTICKS 8 -#define MAX_JOYSTICKS 4 +#define POV_X 0x80000000 +#define POV_Y 0x40000000 +#define SLIDER 0x20000000 -#define POV_X 0x80000000 -#define POV_Y 0x40000000 -#define SLIDER 0x20000000 +#define AXIS_NOT_PRESENT -99999 -#define AXIS_NOT_PRESENT -99999 +#define JOYSTICK_PRESENT(n) (joystick_state[n].plat_joystick_nr != 0) -#define JOYSTICK_PRESENT(n) (joystick_state[n].plat_joystick_nr != 0) +#define GAMEPORT_SIO 0x1000000 -#define GAMEPORT_SIO 0x1000000 +typedef struct plat_joystick_t { + char name[260]; -typedef struct { - char name[260]; - - int a[8]; - int b[32]; - int p[4]; - int s[2]; + int a[8]; + int b[32]; + int p[4]; + int s[2]; struct { - char name[260]; - int id; - } axis[8]; + char name[260]; + int id; + } axis[8]; struct { - char name[260]; - int id; - } button[32]; + char name[260]; + int id; + } button[32]; struct { - char name[260]; - int id; - } pov[4]; + char name[260]; + int id; + } pov[4]; - struct - { - char name[260]; - int id; - } slider[2]; + struct { + char name[260]; + int id; + } slider[2]; - int nr_axes; - int nr_buttons; - int nr_povs; - int nr_sliders; + int nr_axes; + int nr_buttons; + int nr_povs; + int nr_sliders; } plat_joystick_t; -typedef struct { - int axis[8]; - int button[32]; - int pov[4]; +typedef struct joystick_t { + int axis[8]; + int button[32]; + int pov[4]; - int plat_joystick_nr; - int axis_mapping[8]; - int button_mapping[32]; - int pov_mapping[4][2]; + int plat_joystick_nr; + int axis_mapping[8]; + int button_mapping[32]; + int pov_mapping[4][2]; } joystick_t; -typedef struct { +typedef struct joystick_if_t { const char *name; const char *internal_name; - void *(*init)(void); - void (*close)(void *p); - uint8_t (*read)(void *p); - void (*write)(void *p); - int (*read_axis)(void *p, int axis); - void (*a0_over)(void *p); + void *(*init)(void); + void (*close)(void *priv); + uint8_t (*read)(void *priv); + void (*write)(void *priv); + int (*read_axis)(void *priv, int axis); + void (*a0_over)(void *priv); - int axis_count, - button_count, - pov_count; - int max_joysticks; - const char *axis_names[8]; - const char *button_names[32]; - const char *pov_names[4]; + int axis_count; + int button_count; + int pov_count; + int max_joysticks; + const char *axis_names[8]; + const char *button_names[32]; + const char *pov_names[4]; } joystick_if_t; - #ifdef __cplusplus extern "C" { #endif #ifdef EMU_DEVICE_H -extern const device_t gameport_device; -extern const device_t gameport_201_device; -extern const device_t gameport_208_device; -extern const device_t gameport_209_device; -extern const device_t gameport_pnp_device; -extern const device_t gameport_pnp_6io_device; -extern const device_t gameport_sio_device; +extern const device_t gameport_device; +extern const device_t gameport_201_device; +extern const device_t gameport_203_device; +extern const device_t gameport_205_device; +extern const device_t gameport_207_device; +extern const device_t gameport_208_device; +extern const device_t gameport_209_device; +extern const device_t gameport_20b_device; +extern const device_t gameport_20d_device; +extern const device_t gameport_20f_device; +extern const device_t gameport_tm_acm_device; +extern const device_t gameport_pnp_device; +extern const device_t gameport_pnp_6io_device; +extern const device_t gameport_sio_device; +extern const device_t gameport_sio_1io_device; -extern const device_t *standalone_gameport_type; +extern const device_t *standalone_gameport_type; #endif -extern int gameport_instance_id; -extern plat_joystick_t plat_joystick_state[MAX_PLAT_JOYSTICKS]; -extern joystick_t joystick_state[MAX_JOYSTICKS]; -extern int joysticks_present; +extern int gameport_instance_id; +extern plat_joystick_t plat_joystick_state[MAX_PLAT_JOYSTICKS]; +extern joystick_t joystick_state[MAX_JOYSTICKS]; +extern int joysticks_present; -extern int joystick_type; +extern int joystick_type; +extern void joystick_init(void); +extern void joystick_close(void); +extern void joystick_process(void); -extern void joystick_init(void); -extern void joystick_close(void); -extern void joystick_process(void); +extern const char *joystick_get_name(int js); +extern const char *joystick_get_internal_name(int js); +extern int joystick_get_from_internal_name(char *s); +extern int joystick_get_max_joysticks(int js); +extern int joystick_get_axis_count(int js); +extern int joystick_get_button_count(int js); +extern int joystick_get_pov_count(int js); +extern const char *joystick_get_axis_name(int js, int id); +extern const char *joystick_get_button_name(int js, int id); +extern const char *joystick_get_pov_name(int js, int id); -extern char *joystick_get_name(int js); -extern char *joystick_get_internal_name(int js); -extern int joystick_get_from_internal_name(char *s); -extern int joystick_get_max_joysticks(int js); -extern int joystick_get_axis_count(int js); -extern int joystick_get_button_count(int js); -extern int joystick_get_pov_count(int js); -extern char *joystick_get_axis_name(int js, int id); -extern char *joystick_get_button_name(int js, int id); -extern char *joystick_get_pov_name(int js, int id); - -extern void gameport_update_joystick_type(void); -extern void gameport_remap(void *priv, uint16_t address); -extern void *gameport_add(const device_t *gameport_type); +extern void gameport_update_joystick_type(void); +extern void gameport_remap(void *priv, uint16_t address); +extern void *gameport_add(const device_t *gameport_type); #ifdef __cplusplus } #endif - -#endif /*EMU_GAMEPORT_H*/ +#endif /*EMU_GAMEPORT_H*/ diff --git a/src/include/86box/gdbstub.h b/src/include/86box/gdbstub.h new file mode 100644 index 000000000..c58a58bf5 --- /dev/null +++ b/src/include/86box/gdbstub.h @@ -0,0 +1,79 @@ +/* + * 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. + * + * Definitions for the GDB stub server. + * + * + * + * Authors: RichardG, + * + * Copyright 2022 RichardG. + */ +#ifndef EMU_GDBSTUB_H +#define EMU_GDBSTUB_H +#include +#include <86box/mem.h> + +#define GDBSTUB_MEM_READ 0 +#define GDBSTUB_MEM_WRITE 16 +#define GDBSTUB_MEM_AWATCH 32 + +enum { + GDBSTUB_EXEC = 0, + GDBSTUB_SSTEP = 1, + GDBSTUB_BREAK = 2, + GDBSTUB_BREAK_SW = 3, + GDBSTUB_BREAK_HW = 4, + GDBSTUB_BREAK_RWATCH = 5, + GDBSTUB_BREAK_WWATCH = 6, + GDBSTUB_BREAK_AWATCH = 7 +}; + +#ifdef USE_GDBSTUB + +# define GDBSTUB_MEM_ACCESS(addr, access, width) \ + uint32_t gdbstub_page = (addr) >> MEM_GRANULARITY_BITS; \ + if (gdbstub_watch_pages[gdbstub_page >> 6] & (1ULL << (gdbstub_page & 63))) { \ + uint32_t gdbstub_addrs[(width)]; \ + for (int gdbstub_i = 0; gdbstub_i < (width); gdbstub_i++) \ + gdbstub_addrs[gdbstub_i] = (addr) + gdbstub_i; \ + gdbstub_mem_access(gdbstub_addrs, (access) | (width)); \ + } + +# define GDBSTUB_MEM_ACCESS_FAST(addrs, access, width) \ + uint32_t gdbstub_page = (addrs)[0] >> MEM_GRANULARITY_BITS; \ + if (gdbstub_watch_pages[gdbstub_page >> 6] & (1ULL << (gdbstub_page & 63))) \ + gdbstub_mem_access((addrs), (access) | (width)); + +extern int gdbstub_step, gdbstub_next_asap; +extern uint64_t gdbstub_watch_pages[(((uint32_t) -1) >> (MEM_GRANULARITY_BITS + 6)) + 1]; + +extern void gdbstub_cpu_init(void); +extern int gdbstub_instruction(void); +extern int gdbstub_int3(void); +extern void gdbstub_mem_access(uint32_t *addrs, int access); +extern void gdbstub_init(void); +extern void gdbstub_close(void); + +#else + +# define GDBSTUB_MEM_ACCESS(addr, access, width) +# define GDBSTUB_MEM_ACCESS_FAST(addrs, access, width) + +# define gdbstub_step 0 +# define gdbstub_next_asap 0 + +# define gdbstub_cpu_init() +# define gdbstub_instruction() 0 +# define gdbstub_int3() 0 +# define gdbstub_init() +# define gdbstub_close() + +#endif + +#endif diff --git a/src/include/86box/hdc.h b/src/include/86box/hdc.h index 1008b38c9..8ede3e786 100644 --- a/src/include/86box/hdc.h +++ b/src/include/86box/hdc.h @@ -1,91 +1,105 @@ /* - * 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. + * 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. + * This file is part of the 86Box distribution. * - * Definitions for the common disk controller handler. + * Definitions for the common disk controller handler. * * * - * Authors: Miran Grca, - * Fred N. van Kempen, + * Authors: Miran Grca, + * Fred N. van Kempen, * - * Copyright 2016-2020 Miran Grca. - * Copyright 2017-2020 Fred N. van Kempen. + * Copyright 2016-2020 Miran Grca. + * Copyright 2017-2020 Fred N. van Kempen. */ #ifndef EMU_HDC_H -# define EMU_HDC_H +#define EMU_HDC_H +#define MFM_NUM 2 /* 2 drives per controller supported */ +#define ESDI_NUM 2 /* 2 drives per controller supported */ +#define XTA_NUM 2 /* 2 drives per controller supported */ +#define IDE_NUM 10 /* 8 drives per AT IDE + 2 for XT IDE */ +#define ATAPI_NUM 8 /* 8 drives per AT IDE */ +#define SCSI_NUM 16 /* theoretically the controller can have at \ + * least 7 devices, with each device being \ + * able to support 8 units, but hey... */ -#define MFM_NUM 2 /* 2 drives per controller supported */ -#define ESDI_NUM 2 /* 2 drives per controller supported */ -#define XTA_NUM 2 /* 2 drives per controller supported */ -#define IDE_NUM 10 /* 8 drives per AT IDE + 2 for XT IDE */ -#define ATAPI_NUM 8 /* 8 drives per AT IDE */ -#define SCSI_NUM 16 /* theoretically the controller can have at - * least 7 devices, with each device being - * able to support 8 units, but hey... */ +/* Controller types. */ +#define HDC_NONE 0 +#define HDC_INTERNAL 1 -extern int hdc_current; +extern int hdc_current; +extern const device_t st506_xt_xebec_device; /* st506_xt_xebec */ +extern const device_t st506_xt_wdxt_gen_device; /* st506_xt_wdxt_gen */ +extern const device_t st506_xt_dtc5150x_device; /* st506_xt_dtc */ +extern const device_t st506_xt_st11_m_device; /* st506_xt_st11_m */ +extern const device_t st506_xt_st11_r_device; /* st506_xt_st11_m */ +extern const device_t st506_xt_wd1002a_wx1_device; /* st506_xt_wd1002a_wx1 */ +extern const device_t st506_xt_wd1002a_wx1_nobios_device; /* st506_xt_wd1002a_wx1 */ +extern const device_t st506_xt_wd1002a_27x_device; /* st506_xt_wd1002a_27x */ +extern const device_t st506_at_wd1003_device; /* st506_at_wd1003 */ +extern const device_t st506_xt_wd1004a_wx1_device; /* st506_xt_wd1004a_wx1 */ +extern const device_t st506_xt_wd1004_27x_device; /* st506_xt_wd1004_27x */ +extern const device_t st506_xt_wd1004a_27x_device; /* st506_xt_wd1004a_27x */ +extern const device_t st506_xt_victor_v86p_device; /* st506_xt_victor_v86p */ +extern const device_t st506_xt_toshiba_t1200_device; /* st506_xt_toshiba_t1200 */ -extern const device_t st506_xt_xebec_device; /* st506_xt_xebec */ -extern const device_t st506_xt_dtc5150x_device; /* st506_xt_dtc */ -extern const device_t st506_xt_st11_m_device; /* st506_xt_st11_m */ -extern const device_t st506_xt_st11_r_device; /* st506_xt_st11_m */ -extern const device_t st506_xt_wd1002a_wx1_device; /* st506_xt_wd1002a_wx1 */ -extern const device_t st506_xt_wd1002a_27x_device; /* st506_xt_wd1002a_27x */ -extern const device_t st506_at_wd1003_device; /* st506_at_wd1003 */ +extern const device_t esdi_at_wd1007vse1_device; /* esdi_at */ +extern const device_t esdi_ps2_device; /* esdi_mca */ -extern const device_t esdi_at_wd1007vse1_device; /* esdi_at */ -extern const device_t esdi_ps2_device; /* esdi_mca */ +extern const device_t ide_isa_device; /* isa_ide */ +extern const device_t ide_isa_2ch_device; /* isa_ide_2ch */ +extern const device_t ide_isa_2ch_opt_device; /* isa_ide_2ch_opt */ +extern const device_t ide_vlb_device; /* vlb_ide */ +extern const device_t ide_vlb_2ch_device; /* vlb_ide_2ch */ +extern const device_t ide_pci_device; /* pci_ide */ +extern const device_t ide_pci_2ch_device; /* pci_ide_2ch */ -extern const device_t ide_isa_device; /* isa_ide */ -extern const device_t ide_isa_2ch_device; /* isa_ide_2ch */ -extern const device_t ide_isa_2ch_opt_device; /* isa_ide_2ch_opt */ -extern const device_t ide_vlb_device; /* vlb_ide */ -extern const device_t ide_vlb_2ch_device; /* vlb_ide_2ch */ -extern const device_t ide_pci_device; /* pci_ide */ -extern const device_t ide_pci_2ch_device; /* pci_ide_2ch */ +extern const device_t ide_cmd640_vlb_device; /* CMD PCI-640B VLB */ +extern const device_t ide_cmd640_vlb_178_device; /* CMD PCI-640B VLB (Port 178h) */ +extern const device_t ide_cmd640_vlb_pri_device; /* CMD PCI-640B VLB (Only primary channel) */ +extern const device_t ide_cmd640_vlb_pri_178_device; /* CMD PCI-640B VLB (Only primary channel) (Port 178h) */ +extern const device_t ide_cmd640_vlb_sec_device; /* CMD PCI-640B VLB (Only secondary channel) */ +extern const device_t ide_cmd640_vlb_sec_178_device; /* CMD PCI-640B VLB (Only secondary channel) (Port 178h) */ +extern const device_t ide_cmd640_pci_device; /* CMD PCI-640B PCI */ +extern const device_t ide_cmd640_pci_legacy_only_device; /* CMD PCI-640B PCI (Legacy Mode Only) */ +extern const device_t ide_cmd640_pci_single_channel_device; /* CMD PCI-640B PCI (Only primary channel) */ +extern const device_t ide_cmd640_pci_single_channel_sec_device; /* CMD PCI-640B PCI (Only secondary channel) */ +extern const device_t ide_cmd646_device; /* CMD PCI-646 */ +extern const device_t ide_cmd646_legacy_only_device; /* CMD PCI-646 (Legacy Mode Only) */ +extern const device_t ide_cmd646_single_channel_device; /* CMD PCI-646 (Only primary channel) */ -extern const device_t ide_cmd640_vlb_device; /* CMD PCI-640B VLB */ -extern const device_t ide_cmd640_vlb_178_device; /* CMD PCI-640B VLB (Port 178h) */ -extern const device_t ide_cmd640_pci_device; /* CMD PCI-640B PCI */ -extern const device_t ide_cmd640_pci_legacy_only_device; /* CMD PCI-640B PCI (Legacy Mode Only) */ -extern const device_t ide_cmd640_pci_single_channel_device; /* CMD PCI-640B PCI (Only primary channel) */ -extern const device_t ide_cmd646_device; /* CMD PCI-646 */ -extern const device_t ide_cmd646_legacy_only_device; /* CMD PCI-646 (Legacy Mode Only) */ -extern const device_t ide_cmd646_single_channel_device; /* CMD PCI-646 (Only primary channel) */ +extern const device_t ide_opti611_vlb_device; /* OPTi 82c611/611A VLB */ +extern const device_t ide_opti611_vlb_sec_device; /* OPTi 82c611/611A VLB (Secondary channel) */ -extern const device_t ide_opti611_vlb_device; /* OPTi 82c611/611A VLB */ +extern const device_t ide_ter_device; +extern const device_t ide_ter_pnp_device; +extern const device_t ide_qua_device; +extern const device_t ide_qua_pnp_device; -extern const device_t ide_ter_device; -extern const device_t ide_ter_pnp_device; -extern const device_t ide_qua_device; -extern const device_t ide_qua_pnp_device; +extern const device_t xta_wdxt150_device; /* xta_wdxt150 */ +extern const device_t xta_hd20_device; /* EuroPC internal */ -extern const device_t xta_wdxt150_device; /* xta_wdxt150 */ -extern const device_t xta_hd20_device; /* EuroPC internal */ +extern const device_t xtide_device; /* xtide_xt */ +extern const device_t xtide_plus_device; /* xtide_xt_plus */ +extern const device_t xtide_at_device; /* xtide_at */ +extern const device_t xtide_at_386_device; /* xtide_at_386 */ +extern const device_t xtide_acculogic_device; /* xtide_ps2 */ +extern const device_t xtide_at_ps2_device; /* xtide_at_ps2 */ -extern const device_t xtide_device; /* xtide_xt */ -extern const device_t xtide_at_device; /* xtide_at */ -extern const device_t xtide_at_386_device; /* xtide_at_386 */ -extern const device_t xtide_acculogic_device; /* xtide_ps2 */ -extern const device_t xtide_at_ps2_device; /* xtide_at_ps2 */ +extern void hdc_init(void); +extern void hdc_reset(void); +extern const char *hdc_get_internal_name(int hdc); +extern int hdc_get_from_internal_name(char *s); +extern int hdc_has_config(int hdc); +extern const device_t *hdc_get_device(int hdc); +extern int hdc_get_flags(int hdc); +extern int hdc_available(int hdc); -extern void hdc_init(void); -extern void hdc_reset(void); - -extern char *hdc_get_internal_name(int hdc); -extern int hdc_get_from_internal_name(char *s); -extern int hdc_has_config(int hdc); -extern const device_t *hdc_get_device(int hdc); -extern int hdc_get_flags(int hdc); -extern int hdc_available(int hdc); - - -#endif /*EMU_HDC_H*/ +#endif /*EMU_HDC_H*/ diff --git a/src/include/86box/hdc_ide.h b/src/include/86box/hdc_ide.h index d6914b905..291dec303 100644 --- a/src/include/86box/hdc_ide.h +++ b/src/include/86box/hdc_ide.h @@ -1,160 +1,241 @@ /* - * 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. + * 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. + * This file is part of the 86Box distribution. * - * Implementation of the IDE emulation for hard disks and ATAPI - * CD-ROM devices. + * Implementation of the IDE emulation for hard disks and ATAPI + * CD-ROM devices. * * * - * Authors: Sarah Walker, - * Miran Grca, - * Copyright 2008-2019 Sarah Walker. - * Copyright 2016-2019 Miran Grca. + * Authors: Sarah Walker, + * Miran Grca, + * Copyright 2008-2019 Sarah Walker. + * Copyright 2016-2019 Miran Grca. */ #ifndef EMU_IDE_H -# define EMU_IDE_H +#define EMU_IDE_H +#define IDE_BUS_MAX 4 +#define IDE_CHAN_MAX 2 -enum -{ - IDE_NONE = 0, - IDE_HDD, - IDE_ATAPI +#define HDC_PRIMARY_BASE 0x01F0 +#define HDC_PRIMARY_SIDE 0x03F6 +#define HDC_PRIMARY_IRQ 14 +#define HDC_SECONDARY_BASE 0x0170 +#define HDC_SECONDARY_SIDE 0x0376 +#define HDC_SECONDARY_IRQ 15 +#define HDC_TERTIARY_BASE 0x01E8 +#define HDC_TERTIARY_SIDE 0x03EE +#define HDC_TERTIARY_IRQ 11 +#define HDC_QUATERNARY_BASE 0x0168 +#define HDC_QUATERNARY_SIDE 0x036E +#define HDC_QUATERNARY_IRQ 10 + +enum { + IDE_NONE = 0, /* Absent master or both. */ + IDE_HDD, /* Hard disk. */ + IDE_ATAPI, /* ATAPI device. */ + IDE_RESERVED, /* Reserved, do not use. */ + IDE_SHADOW, /* Shadow flag, do not assign on is own. */ + IDE_HDD_SHADOW, /* Shadow of a hard disk. */ + IDE_ATAPI_SHADOW /* Shadow of an ATAPI device. */ }; -#ifdef SCSI_DEVICE_H +typedef struct ide_tf_s { + union { + uint8_t cylprecomp; + uint8_t features; + }; + union { + uint8_t secount; + uint8_t phase; + }; + union { + uint16_t cylinder; + uint16_t request_length; + }; + union { + uint8_t atastat; + uint8_t status; + }; + uint8_t error; + uint8_t sector; + union { + uint8_t drvsel; + struct { + uint8_t head :4; + uint8_t pad :2; + uint8_t lba :1; + uint8_t pad0 :1; + }; + }; + uint32_t pos; +} ide_tf_t; + +#ifdef _TIMER_H_ typedef struct ide_s { - uint8_t selected, - atastat, error, - command, fdisk; - int type, board, - irqstat, service, - blocksize, blockcount, - hdd_num, channel, - pos, sector_pos, - lba, skip512, - reset, mdma_mode, - do_initial_read; - uint32_t secount, sector, - cylinder, head, - drive, cylprecomp, - cfg_spt, cfg_hpc, - lba_addr, tracks, - spt, hpc; + /* The rest. */ + uint8_t selected; + uint8_t command; + uint8_t head; + uint8_t pad; + int type; + int board; + int irqstat; + int service; + int blocksize; + int blockcount; + int hdd_num; + int channel; + int sector_pos; + int reset; + int mdma_mode; + int do_initial_read; + uint32_t drive; + uint32_t cfg_spt; + uint32_t cfg_hpc; + uint32_t lba_addr; + uint32_t tracks; + uint32_t spt; + uint32_t hpc; uint16_t *buffer; - uint8_t *sector_buffer; + uint8_t *sector_buffer; - pc_timer_t timer; + pc_timer_t timer; + + /* Task file. */ + ide_tf_t * tf; /* Stuff mostly used by ATAPI */ - scsi_common_t *sc; - int interrupt_drq; +#ifdef SCSI_DEVICE_H + scsi_common_t *sc; +#else + void * sc; +#endif + int interrupt_drq; + double pending_delay; - int (*get_max)(int ide_has_dma, int type); - int (*get_timings)(int ide_has_dma, int type); - void (*identify)(struct ide_s *ide, int ide_has_dma); - void (*stop)(scsi_common_t *sc); - void (*packet_command)(scsi_common_t *sc, uint8_t *cdb); - void (*device_reset)(scsi_common_t *sc); - uint8_t (*phase_data_out)(scsi_common_t *sc); - void (*command_stop)(scsi_common_t *sc); - void (*bus_master_error)(scsi_common_t *sc); +#ifdef SCSI_DEVICE_H + int (*get_max)(int ide_has_dma, int type); + int (*get_timings)(int ide_has_dma, int type); + void (*identify)(struct ide_s *ide, int ide_has_dma); + void (*stop)(scsi_common_t *sc); + void (*packet_command)(scsi_common_t *sc, uint8_t *cdb); + void (*device_reset)(scsi_common_t *sc); + uint8_t (*phase_data_out)(scsi_common_t *sc); + void (*command_stop)(scsi_common_t *sc); + void (*bus_master_error)(scsi_common_t *sc); +#else + void * get_max; + void * get_timings; + void * identify; + void * stop; + void * device_reset; + void * phase_data_out; + void * command_stop; + void * bus_master_error; +#endif } ide_t; -extern ide_t *ide_drives[IDE_NUM]; +#ifdef EMU_HDC_H +extern ide_t *ide_drives[IDE_NUM]; +#endif #endif /* Type: - 0 = PIO, - 1 = SDMA, - 2 = MDMA, - 3 = UDMA + 0 = PIO, + 1 = SDMA, + 2 = MDMA, + 3 = UDMA Return: - -1 = Not supported, - Anything else = maximum mode + -1 = Not supported, + Anything else = maximum mode This will eventually be hookable. */ enum { - TYPE_PIO = 0, - TYPE_SDMA, - TYPE_MDMA, - TYPE_UDMA + TYPE_PIO = 0, + TYPE_SDMA = 1, + TYPE_MDMA = 2, + TYPE_UDMA = 3 }; /* Return: - 0 = Not supported, - Anything else = timings + 0 = Not supported, + Anything else = timings This will eventually be hookable. */ enum { - TIMINGS_DMA = 0, - TIMINGS_PIO, - TIMINGS_PIO_FC + TIMINGS_DMA = 0, + TIMINGS_PIO = 1, + TIMINGS_PIO_FC = 2 }; - -extern int ide_ter_enabled, ide_qua_enabled; - +extern int ide_ter_enabled; +extern int ide_qua_enabled; #ifdef SCSI_DEVICE_H -extern ide_t * ide_get_drive(int ch); -extern void ide_irq_raise(ide_t *ide); -extern void ide_irq_lower(ide_t *ide); -extern void ide_allocate_buffer(ide_t *dev); -extern void ide_atapi_attach(ide_t *dev); +extern ide_t *ide_get_drive(int ch); +extern void ide_irq(ide_t *ide, int set, int log); +extern void ide_allocate_buffer(ide_t *dev); +extern void ide_atapi_attach(ide_t *dev); #endif -extern void * ide_xtide_init(void); -extern void ide_xtide_close(void); +extern void *ide_xtide_init(void); +extern void ide_xtide_close(void); -extern void ide_writew(uint16_t addr, uint16_t val, void *priv); -extern void ide_write_devctl(uint16_t addr, uint8_t val, void *priv); -extern void ide_writeb(uint16_t addr, uint8_t val, void *priv); -extern uint8_t ide_readb(uint16_t addr, void *priv); -extern uint8_t ide_read_alt_status(uint16_t addr, void *priv); -extern uint16_t ide_readw(uint16_t addr, void *priv); +extern void ide_writew(uint16_t addr, uint16_t val, void *priv); +extern void ide_write_devctl(uint16_t addr, uint8_t val, void *priv); +extern void ide_writeb(uint16_t addr, uint8_t val, void *priv); +extern uint8_t ide_readb(uint16_t addr, void *priv); +extern uint8_t ide_read_alt_status(uint16_t addr, void *priv); +extern uint16_t ide_readw(uint16_t addr, void *priv); -extern void ide_set_bus_master(int board, - int (*dma)(int channel, uint8_t *data, int transfer_length, int out, void *priv), - void (*set_irq)(int channel, void *priv), void *priv); +extern void ide_set_bus_master(int board, + int (*dma)(uint8_t *data, int transfer_length, int out, void *priv), + void (*set_irq)(uint8_t status, void *priv), void *priv); -extern void win_cdrom_eject(uint8_t id); -extern void win_cdrom_reload(uint8_t id); +extern void win_cdrom_eject(uint8_t id); +extern void win_cdrom_reload(uint8_t id); -extern void ide_set_base(int board, uint16_t port); -extern void ide_set_side(int board, uint16_t port); +extern void ide_set_base_addr(int board, int base, uint16_t port); -extern void ide_pri_enable(void); -extern void ide_pri_disable(void); -extern void ide_sec_enable(void); -extern void ide_sec_disable(void); +extern void ide_handlers(uint8_t board, int set); -extern void ide_board_set_force_ata3(int board, int force_ata3); +extern void ide_board_set_force_ata3(int board, int force_ata3); #ifdef EMU_ISAPNP_H -extern void ide_pnp_config_changed(uint8_t ld, isapnp_device_config_t *config, void *priv); +extern void ide_pnp_config_changed(uint8_t ld, isapnp_device_config_t *config, void *priv); #endif -extern double ide_atapi_get_period(uint8_t channel); +extern double ide_atapi_get_period(uint8_t channel); #ifdef SCSI_DEVICE_H -extern void ide_set_callback(ide_t *ide, double callback); +extern void ide_set_callback(ide_t *ide, double callback); #endif -extern void ide_set_board_callback(uint8_t board, double callback); +extern void ide_set_board_callback(uint8_t board, double callback); -extern void ide_padstr(char *str, const char *src, int len); -extern void ide_padstr8(uint8_t *buf, int buf_size, const char *src); +extern void ide_padstr(char *str, const char *src, int len); +extern void ide_padstr8(uint8_t *buf, int buf_size, const char *src); -extern int (*ide_bus_master_dma)(int channel, uint8_t *data, int transfer_length, int out, void *priv); -extern void (*ide_bus_master_set_irq)(int channel, void *priv); -extern void *ide_bus_master_priv[2]; +extern uint8_t ide_read_ali_75(void); +extern uint8_t ide_read_ali_76(void); -extern uint8_t ide_read_ali_75(void); -extern uint8_t ide_read_ali_76(void); +/* Legacy #define's. */ +#define ide_irq_raise(ide) ide_irq(ide, 1, 1) +#define ide_irq_lower(ide) ide_irq(ide, 0, 1) +#define ide_set_base(board, port) ide_set_base_addr(board, 0, port) +#define ide_set_side(board, port) ide_set_base_addr(board, 1, port) -#endif /*EMU_IDE_H*/ +#define ide_pri_enable() ide_handlers(0, 1) +#define ide_pri_disable() ide_handlers(0, 0) +#define ide_sec_enable() ide_handlers(1, 1) +#define ide_sec_disable() ide_handlers(1, 0) + +#define ide_set_handlers(board) ide_handlers(board, 1) +#define ide_remove_handlers(board) ide_handlers(board, 0) + +#endif /*EMU_IDE_H*/ diff --git a/src/include/86box/hdc_ide_sff8038i.h b/src/include/86box/hdc_ide_sff8038i.h index 700684dae..2283497bb 100644 --- a/src/include/86box/hdc_ide_sff8038i.h +++ b/src/include/86box/hdc_ide_sff8038i.h @@ -1,58 +1,81 @@ /* - * 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. + * 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. * - * Emulation of the SFF-8038i IDE Bus Master. + * This file is part of the 86Box distribution. * - * Emulation core dispatcher. + * Emulation of the SFF-8038i IDE Bus Master. * * * - * Authors: Sarah Walker, - * Miran Grca, - * Copyright 2008-2020 Sarah Walker. - * Copyright 2016-2020 Miran Grca. + * Authors: Sarah Walker, + * Miran Grca, + * + * Copyright 2008-2020 Sarah Walker. + * Copyright 2016-2020 Miran Grca. */ -typedef struct -{ - uint8_t command, status, - ptr0, enabled, - dma_mode, pad, - pad0, pad1; - uint16_t base, pad2; - uint32_t ptr, ptr_cur, - addr; - int count, eot, - slot, - irq_mode[2], irq_level[2], - irq_pin, irq_line; -} sff8038i_t; +#ifndef EMU_HDC_IDE_SFF8038I_H +#define EMU_HDC_IDE_SFF8038I_H +enum +{ + IRQ_MODE_LEGACY = 0, + IRQ_MODE_PCI_IRQ_PIN, + IRQ_MODE_PCI_IRQ_LINE, + IRQ_MODE_ALI_ALADDIN, + IRQ_MODE_MIRQ_0, + IRQ_MODE_MIRQ_1, + IRQ_MODE_MIRQ_2, + IRQ_MODE_MIRQ_3, + IRQ_MODE_SIS_551X +}; + +typedef struct sff8038i_t +{ + uint8_t command; + uint8_t status; + uint8_t ptr0; + uint8_t enabled; + uint8_t dma_mode; + uint8_t irq_state; + uint8_t channel; + uint8_t irq_line; + uint16_t base; + uint16_t pad; + uint32_t ptr; + uint32_t ptr_cur; + uint32_t addr; + int count; + int eot; + int slot; + int irq_mode; + int irq_level; + int irq_pin; + int pci_irq_line; +} sff8038i_t; extern const device_t sff8038i_device; -extern void sff_bus_master_handler(sff8038i_t *dev, int enabled, uint16_t base); +extern void sff_bus_master_handler(sff8038i_t *dev, int enabled, uint16_t base); -extern int sff_bus_master_dma_read(int channel, uint8_t *data, int transfer_length, void *priv); -extern int sff_bus_master_dma_write(int channel, uint8_t *data, int transfer_length, void *priv); +extern void sff_bus_master_set_irq(uint8_t status, void *priv); +extern int sff_bus_master_dma(uint8_t *data, int transfer_length, int out, void *priv); -extern void sff_bus_master_set_irq(int channel, void *priv); +extern void sff_bus_master_write(uint16_t port, uint8_t val, void *priv); +extern uint8_t sff_bus_master_read(uint16_t port, void *priv); -extern int sff_bus_master_dma(int channel, uint8_t *data, int transfer_length, int out, void *priv); +extern void sff_bus_master_reset(sff8038i_t *dev); -extern void sff_bus_master_write(uint16_t port, uint8_t val, void *priv); -extern uint8_t sff_bus_master_read(uint16_t port, void *priv); +extern void sff_set_slot(sff8038i_t *dev, int slot); -extern void sff_bus_master_reset(sff8038i_t *dev, uint16_t old_base); +extern void sff_set_irq_line(sff8038i_t *dev, int irq_line); -extern void sff_set_slot(sff8038i_t *dev, int slot); +extern void sff_set_irq_mode(sff8038i_t *dev, int irq_mode); +extern void sff_set_irq_pin(sff8038i_t *dev, int irq_pin); -extern void sff_set_irq_line(sff8038i_t *dev, int irq_line); +extern void sff_set_irq_level(sff8038i_t *dev, int irq_level); -extern void sff_set_irq_mode(sff8038i_t *dev, int channel, int irq_mode); -extern void sff_set_irq_pin(sff8038i_t *dev, int irq_pin); - -extern void sff_set_irq_level(sff8038i_t *dev, int channel, int irq_level); +#endif /*EMU_HDC_IDE_SFF8038I_H*/ diff --git a/src/include/86box/hdd.h b/src/include/86box/hdd.h index 96afcdde0..8c82209c7 100644 --- a/src/include/86box/hdd.h +++ b/src/include/86box/hdd.h @@ -1,26 +1,32 @@ /* - * 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. + * 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. + * This file is part of the 86Box distribution. * - * Definitions for the hard disk image handler. + * Definitions for the hard disk image handler. * * * - * Authors: Miran Grca, - * Fred N. van Kempen, - * Copyright 2016-2018 Miran Grca. - * Copyright 2017,2018 Fred N. van Kempen. + * Authors: Miran Grca, + * Fred N. van Kempen, + * + * Copyright 2016-2018 Miran Grca. + * Copyright 2017-2018 Fred N. van Kempen. */ #ifndef EMU_HDD_H -# define EMU_HDD_H +#define EMU_HDD_H +#define IMG_FMT_RAW 0 +#define IMG_FMT_HDI 1 +#define IMG_FMT_HDX 2 +#define IMG_FMT_VHD_FIXED 3 +#define IMG_FMT_VHD_DYNAMIC 4 +#define IMG_FMT_VHD_DIFF 5 -#define HDD_NUM 88 /* total of 88 images supported */ - +#define HDD_NUM 88 /* total of 88 images supported */ /* Hard Disk bus types. */ #if 0 @@ -28,108 +34,194 @@ Bit 5 = Removable (0 = no, 1 yes). */ enum { - BUS_DISABLED = 0x00, + BUS_DISABLED = 0x00, - BUS_MFM = 0x01, /* These four are for hard disk only. */ - BUS_XIDE = 0x02, - BUS_XTA = 0x03, - BUS_ESDI = 0x04, + BUS_MFM = 0x01, /* These four are for hard disk only. */ + BUS_XIDE = 0x02, + BUS_XTA = 0x03, + BUS_ESDI = 0x04, - BUS_PANASONIC = 0x21, / These four are for CD-ROM only. */ - BUS_PHILIPS = 0x22, - BUS_SONY = 0x23, - BUS_MITSUMI = 0x24, + BUS_PANASONIC = 0x21, / These four are for CD-ROM only. */ + BUS_PHILIPS = 0x22, + BUS_SONY = 0x23, + BUS_MITSUMI = 0x24, - BUS_IDE_PIO_ONLY = 0x05, - BUS_IDE_PIO_AND_DMA = 0x15, - BUS_IDE_R_PIO_ONLY = 0x25, - BUS_IDE_R_PIO_AND_DMA = 0x35, + BUS_IDE_PIO_ONLY = 0x05, + BUS_IDE_PIO_AND_DMA = 0x15, + BUS_IDE_R_PIO_ONLY = 0x25, + BUS_IDE_R_PIO_AND_DMA = 0x35, - BUS_ATAPI_PIO_ONLY = 0x06, - BUS_ATAPI_PIO_AND_DMA = 0x16, - BUS_ATAPI_R_PIO_ONLY = 0x26, - BUS_ATAPI_R_PIO_AND_DMA = 0x36, + BUS_ATAPI_PIO_ONLY = 0x06, + BUS_ATAPI_PIO_AND_DMA = 0x16, + BUS_ATAPI_R_PIO_ONLY = 0x26, + BUS_ATAPI_R_PIO_AND_DMA = 0x36, - BUS_SASI = 0x07, - BUS_SASI_R = 0x27, + BUS_SASI = 0x07, + BUS_SASI_R = 0x27, - BUS_SCSI = 0x08, - BUS_SCSI_R = 0x28, + BUS_SCSI = 0x08, + BUS_SCSI_R = 0x28, - BUS_USB = 0x09, - BUS_USB_R = 0x29 + BUS_USB = 0x09, + BUS_USB_R = 0x29 }; #else enum { HDD_BUS_DISABLED = 0, - HDD_BUS_MFM, - HDD_BUS_XTA, - HDD_BUS_ESDI, - HDD_BUS_IDE, - HDD_BUS_ATAPI, - HDD_BUS_SCSI, - HDD_BUS_USB + HDD_BUS_MFM = 1, + HDD_BUS_XTA = 2, + HDD_BUS_ESDI = 3, + HDD_BUS_IDE = 4, + HDD_BUS_ATAPI = 5, + HDD_BUS_SCSI = 6, + HDD_BUS_USB = 7 }; #endif +enum { + HDD_OP_SEEK = 0, + HDD_OP_READ = 2, + HDD_OP_WRITE = 3 +}; + +#define HDD_MAX_ZONES 16 +#define HDD_MAX_CACHE_SEG 16 + +typedef struct hdd_preset_t { + const char *name; + const char *internal_name; + uint32_t zones; + uint32_t avg_spt; + uint32_t heads; + uint32_t rpm; + uint32_t rcache_num_seg; + uint32_t rcache_seg_size; + uint32_t max_multiple; + double full_stroke_ms; + double track_seek_ms; +} hdd_preset_t; + +typedef struct hdd_cache_seg_t { + uint32_t id; + uint32_t lba_addr; + uint32_t ra_addr; + uint32_t host_addr; + uint8_t lru; + uint8_t valid; +} hdd_cache_seg_t; + +typedef struct hdd_cache_t { + // Read cache + hdd_cache_seg_t segments[HDD_MAX_CACHE_SEG]; + uint32_t num_segments; + uint32_t segment_size; + uint32_t ra_segment; + uint8_t ra_ongoing; + uint64_t ra_start_time; + + // Write cache + uint32_t write_addr; + uint32_t write_pending; + uint32_t write_size; + uint64_t write_start_time; +} hdd_cache_t; + +typedef struct hdd_zone_t { + uint32_t cylinders; + uint32_t sectors_per_track; + double sector_time_usec; + uint32_t start_sector; + uint32_t end_sector; + uint32_t start_track; +} hdd_zone_t; /* Define the virtual Hard Disk. */ -typedef struct { - uint8_t id; +typedef struct hard_disk_t { + uint8_t id; union { - uint8_t channel; /* Needed for Settings to reduce the number of if's */ + uint8_t channel; /* Needed for Settings to reduce the number of if's */ - uint8_t mfm_channel; /* Should rename and/or unionize */ - uint8_t esdi_channel; - uint8_t xta_channel; - uint8_t ide_channel; - uint8_t scsi_id; + uint8_t mfm_channel; /* Should rename and/or unionize */ + uint8_t esdi_channel; + uint8_t xta_channel; + uint8_t ide_channel; + uint8_t scsi_id; }; - uint8_t bus, - res; /* Reserved for bus mode */ - uint8_t wp; /* Disk has been mounted READ-ONLY */ - uint8_t pad, pad0; + uint8_t bus; + uint8_t bus_mode; /* Bit 0 = PIO suported; + Bit 1 = DMA supportd. */ + uint8_t wp; /* Disk has been mounted READ-ONLY */ + uint8_t pad; + uint8_t pad0; - void *priv; + void *priv; - char fn[1024], /* Name of current image file */ - prev_fn[1024]; /* Name of previous image file */ + char fn[1024]; /* Name of current image file */ + char vhd_parent[1041]; /* Differential VHD parent file */ - uint32_t res0, pad1, - base, - spt, - hpc, /* Physical geometry parameters */ - tracks; + uint32_t res0; + uint32_t pad1; + uint32_t base; + uint32_t spt; + uint32_t hpc; /* Physical geometry parameters */ + uint32_t tracks; + + hdd_zone_t zones[HDD_MAX_ZONES]; + uint32_t num_zones; + hdd_cache_t cache; + uint32_t phy_cyl; + uint32_t phy_heads; + uint32_t rpm; + uint8_t max_multiple_block; + + uint32_t cur_cylinder; + uint32_t cur_track; + uint32_t cur_addr; + + uint32_t speed_preset; + uint32_t vhd_blocksize; + + double avg_rotation_lat_usec; + double full_stroke_usec; + double head_switch_usec; + double cyl_switch_usec; } hard_disk_t; +extern hard_disk_t hdd[HDD_NUM]; +extern unsigned int hdd_table[128][3]; -extern hard_disk_t hdd[HDD_NUM]; -extern unsigned int hdd_table[128][3]; +extern int hdd_init(void); +extern int hdd_string_to_bus(char *str, int cdrom); +extern char *hdd_bus_to_string(int bus, int cdrom); +extern int hdd_is_valid(int c); -extern int hdd_init(void); -extern int hdd_string_to_bus(char *str, int cdrom); -extern char *hdd_bus_to_string(int bus, int cdrom); -extern int hdd_is_valid(int c); +extern void hdd_image_init(void); +extern int hdd_image_load(int id); +extern void hdd_image_seek(uint8_t id, uint32_t sector); +extern void hdd_image_read(uint8_t id, uint32_t sector, uint32_t count, uint8_t *buffer); +extern int hdd_image_read_ex(uint8_t id, uint32_t sector, uint32_t count, uint8_t *buffer); +extern void hdd_image_write(uint8_t id, uint32_t sector, uint32_t count, uint8_t *buffer); +extern int hdd_image_write_ex(uint8_t id, uint32_t sector, uint32_t count, uint8_t *buffer); +extern void hdd_image_zero(uint8_t id, uint32_t sector, uint32_t count); +extern int hdd_image_zero_ex(uint8_t id, uint32_t sector, uint32_t count); +extern uint32_t hdd_image_get_last_sector(uint8_t id); +extern uint32_t hdd_image_get_pos(uint8_t id); +extern uint8_t hdd_image_get_type(uint8_t id); +extern void hdd_image_unload(uint8_t id, int fn_preserve); +extern void hdd_image_close(uint8_t id); +extern void hdd_image_calc_chs(uint32_t *c, uint32_t *h, uint32_t *s, uint32_t size); -extern void hdd_image_init(void); -extern int hdd_image_load(int id); -extern void hdd_image_seek(uint8_t id, uint32_t sector); -extern void hdd_image_read(uint8_t id, uint32_t sector, uint32_t count, uint8_t *buffer); -extern int hdd_image_read_ex(uint8_t id, uint32_t sector, uint32_t count, uint8_t *buffer); -extern void hdd_image_write(uint8_t id, uint32_t sector, uint32_t count, uint8_t *buffer); -extern int hdd_image_write_ex(uint8_t id, uint32_t sector, uint32_t count, uint8_t *buffer); -extern void hdd_image_zero(uint8_t id, uint32_t sector, uint32_t count); -extern int hdd_image_zero_ex(uint8_t id, uint32_t sector, uint32_t count); -extern uint32_t hdd_image_get_last_sector(uint8_t id); -extern uint32_t hdd_image_get_pos(uint8_t id); -extern uint8_t hdd_image_get_type(uint8_t id); -extern void hdd_image_unload(uint8_t id, int fn_preserve); -extern void hdd_image_close(uint8_t id); -extern void hdd_image_calc_chs(uint32_t *c, uint32_t *h, uint32_t *s, uint32_t size); +extern int image_is_hdi(const char *s); +extern int image_is_hdx(const char *s, int check_signature); +extern int image_is_vhd(const char *s, int check_signature); -extern int image_is_hdi(const char *s); -extern int image_is_hdx(const char *s, int check_signature); -extern int image_is_vhd(const char *s, int check_signature); +extern double hdd_timing_write(hard_disk_t *hdd, uint32_t addr, uint32_t len); +extern double hdd_timing_read(hard_disk_t *hdd, uint32_t addr, uint32_t len); +extern double hdd_seek_get_time(hard_disk_t *hdd, uint32_t dst_addr, uint8_t operation, uint8_t continuous, double max_seek_time); +int hdd_preset_get_num(void); +const char *hdd_preset_getname(int preset); +extern const char *hdd_preset_get_internal_name(int preset); +extern int hdd_preset_get_from_internal_name(char *s); +extern void hdd_preset_apply(int hdd_id); - -#endif /*EMU_HDD_H*/ +#endif /*EMU_HDD_H*/ diff --git a/src/include/86box/hwm.h b/src/include/86box/hwm.h index ef5621da6..b1b1d8c25 100644 --- a/src/include/86box/hwm.h +++ b/src/include/86box/hwm.h @@ -1,78 +1,74 @@ /* - * 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. + * 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. + * This file is part of the 86Box distribution. * - * Definitions for hardware monitoring chips. + * Definitions for hardware monitoring chips. * * * - * Author: RichardG, + * Authors: RichardG, * - * Copyright 2020 RichardG. + * Copyright 2020 RichardG. */ #ifndef EMU_HWM_H -# define EMU_HWM_H -# include - +#define EMU_HWM_H +#include #define RESISTOR_DIVIDER(v, r1, r2) (((v) * (r2)) / ((r1) + (r2))) - -typedef struct { - uint16_t fans[4]; - uint8_t temperatures[4]; - uint16_t voltages[13]; +typedef struct hwm_values_t { + uint16_t fans[4]; + uint8_t temperatures[4]; + uint16_t voltages[13]; } hwm_values_t; -typedef struct { - uint32_t local; +typedef struct lm75_t { + uint32_t local; hwm_values_t *values; - void *as99127f; + void *as99127f; - uint8_t regs[8]; - uint8_t addr_register; - uint8_t i2c_addr: 7, i2c_state: 2; - uint8_t i2c_enabled: 1; + uint8_t regs[8]; + uint8_t addr_register; + uint8_t i2c_addr : 7; + uint8_t i2c_state : 2; + uint8_t i2c_enabled : 1; } lm75_t; - /* hwm.c */ -extern uint16_t hwm_get_vcore(); +extern uint16_t hwm_get_vcore(void); /* hwm_lm75.c */ -extern void lm75_remap(lm75_t *dev, uint8_t addr); -extern uint8_t lm75_read(lm75_t *dev, uint8_t reg); -extern uint8_t lm75_write(lm75_t *dev, uint8_t reg, uint8_t val); +extern void lm75_remap(lm75_t *dev, uint8_t addr); +extern uint8_t lm75_read(lm75_t *dev, uint8_t reg); +extern uint8_t lm75_write(lm75_t *dev, uint8_t reg, uint8_t val); /* hwm_lm78.c */ -extern uint8_t lm78_as99127f_read(void *priv, uint8_t reg); -extern uint8_t lm78_as99127f_write(void *priv, uint8_t reg, uint8_t val); +extern uint8_t lm78_as99127f_read(void *priv, uint8_t reg); +extern uint8_t lm78_as99127f_write(void *priv, uint8_t reg, uint8_t val); /* hwm_vt82c686.c */ -extern void vt82c686_hwm_write(uint8_t addr, uint8_t val, void *priv); - +extern void vt82c686_hwm_write(uint8_t addr, uint8_t val, void *priv); /* Refer to specific hardware monitor implementations for the meaning of hwm_values. */ -extern hwm_values_t hwm_values; +extern hwm_values_t hwm_values; -extern const device_t lm75_1_4a_device; -extern const device_t lm75_w83781d_device; +extern const device_t lm75_1_4a_device; +extern const device_t lm75_w83781d_device; -extern const device_t lm78_device; -extern const device_t w83781d_device; -extern const device_t w83781d_p5a_device; -extern const device_t as99127f_device; -extern const device_t as99127f_rev2_device; -extern const device_t w83782d_device; +extern const device_t lm78_device; +extern const device_t w83781d_device; +extern const device_t w83781d_p5a_device; +extern const device_t as99127f_device; +extern const device_t as99127f_rev2_device; +extern const device_t w83782d_device; -extern const device_t gl518sm_2c_device; -extern const device_t gl518sm_2d_device; +extern const device_t gl518sm_2c_device; +extern const device_t gl518sm_2d_device; -extern const device_t via_vt82c686_hwm_device; +extern const device_t via_vt82c686_hwm_device; - -#endif /*EMU_HWM_H*/ +#endif /*EMU_HWM_H*/ diff --git a/src/include/86box/i2c.h b/src/include/86box/i2c.h index b47754d64..20e2f8b30 100644 --- a/src/include/86box/i2c.h +++ b/src/include/86box/i2c.h @@ -1,70 +1,67 @@ /* - * 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. + * 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. + * This file is part of the 86Box distribution. * - * Definitions for the I2C handler. + * Definitions for the I2C handler. * * * - * Authors: RichardG, + * Authors: RichardG, * - * Copyright 2020 RichardG. + * Copyright 2020 RichardG. */ #ifndef EMU_I2C_H -# define EMU_I2C_H - +#define EMU_I2C_H /* i2c.c */ -extern void *i2c_smbus; - +extern void *i2c_smbus; /* i2c.c */ -extern void *i2c_addbus(char *name); -extern void i2c_removebus(void *bus_handle); -extern char *i2c_getbusname(void *bus_handle); +extern void *i2c_addbus(char *name); +extern void i2c_removebus(void *bus_handle); +extern char *i2c_getbusname(void *bus_handle); -extern void i2c_sethandler(void *bus_handle, uint8_t base, int size, - uint8_t (*start)(void *bus, uint8_t addr, uint8_t read, void *priv), - uint8_t (*read)(void *bus, uint8_t addr, void *priv), - uint8_t (*write)(void *bus, uint8_t addr, uint8_t data, void *priv), - void (*stop)(void *bus, uint8_t addr, void *priv), - void *priv); +extern void i2c_sethandler(void *bus_handle, uint8_t base, int size, + uint8_t (*start)(void *bus, uint8_t addr, uint8_t read, void *priv), + uint8_t (*read)(void *bus, uint8_t addr, void *priv), + uint8_t (*write)(void *bus, uint8_t addr, uint8_t data, void *priv), + void (*stop)(void *bus, uint8_t addr, void *priv), + void *priv); -extern void i2c_removehandler(void *bus_handle, uint8_t base, int size, - uint8_t (*start)(void *bus, uint8_t addr, uint8_t read, void *priv), - uint8_t (*read)(void *bus, uint8_t addr, void *priv), - uint8_t (*write)(void *bus, uint8_t addr, uint8_t data, void *priv), - void (*stop)(void *bus, uint8_t addr, void *priv), - void *priv); +extern void i2c_removehandler(void *bus_handle, uint8_t base, int size, + uint8_t (*start)(void *bus, uint8_t addr, uint8_t read, void *priv), + uint8_t (*read)(void *bus, uint8_t addr, void *priv), + uint8_t (*write)(void *bus, uint8_t addr, uint8_t data, void *priv), + void (*stop)(void *bus, uint8_t addr, void *priv), + void *priv); -extern void i2c_handler(int set, void *bus_handle, uint8_t base, int size, - uint8_t (*start)(void *bus, uint8_t addr, uint8_t read, void *priv), - uint8_t (*read)(void *bus, uint8_t addr, void *priv), - uint8_t (*write)(void *bus, uint8_t addr, uint8_t data, void *priv), - void (*stop)(void *bus, uint8_t addr, void *priv), - void *priv); +extern void i2c_handler(int set, void *bus_handle, uint8_t base, int size, + uint8_t (*start)(void *bus, uint8_t addr, uint8_t read, void *priv), + uint8_t (*read)(void *bus, uint8_t addr, void *priv), + uint8_t (*write)(void *bus, uint8_t addr, uint8_t data, void *priv), + void (*stop)(void *bus, uint8_t addr, void *priv), + void *priv); -extern uint8_t i2c_start(void *bus_handle, uint8_t addr, uint8_t read); -extern uint8_t i2c_read(void *bus_handle, uint8_t addr); -extern uint8_t i2c_write(void *bus_handle, uint8_t addr, uint8_t data); -extern void i2c_stop(void *bus_handle, uint8_t addr); +extern uint8_t i2c_start(void *bus_handle, uint8_t addr, uint8_t read); +extern uint8_t i2c_read(void *bus_handle, uint8_t addr); +extern uint8_t i2c_write(void *bus_handle, uint8_t addr, uint8_t data); +extern void i2c_stop(void *bus_handle, uint8_t addr); /* i2c_eeprom.c */ -extern uint8_t log2i(uint32_t i); -extern void *i2c_eeprom_init(void *i2c, uint8_t addr, uint8_t *data, uint32_t size, uint8_t writable); -extern void i2c_eeprom_close(void *dev_handle); +extern uint8_t log2i(uint32_t i); +extern void *i2c_eeprom_init(void *i2c, uint8_t addr, uint8_t *data, uint32_t size, uint8_t writable); +extern void i2c_eeprom_close(void *dev_handle); /* i2c_gpio.c */ -extern void *i2c_gpio_init(char *bus_name); -extern void i2c_gpio_close(void *dev_handle); -extern void i2c_gpio_set(void *dev_handle, uint8_t scl, uint8_t sda); -extern uint8_t i2c_gpio_get_scl(void *dev_handle); -extern uint8_t i2c_gpio_get_sda(void *dev_handle); -extern void *i2c_gpio_get_bus(); +extern void *i2c_gpio_init(char *bus_name); +extern void i2c_gpio_close(void *dev_handle); +extern void i2c_gpio_set(void *dev_handle, uint8_t scl, uint8_t sda); +extern uint8_t i2c_gpio_get_scl(void *dev_handle); +extern uint8_t i2c_gpio_get_sda(void *dev_handle); +extern void *i2c_gpio_get_bus(void *dev_handle); - -#endif /*EMU_I2C_H*/ +#endif /*EMU_I2C_H*/ diff --git a/src/include/86box/i8080.h b/src/include/86box/i8080.h new file mode 100644 index 000000000..9a25b5d1b --- /dev/null +++ b/src/include/86box/i8080.h @@ -0,0 +1,69 @@ +/* + * 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. + * + * 8080 CPU emulation (header). + * + * + * + * Authors: Cacodemon345 + * + * Copyright 2022 Cacodemon345 + */ + +#include + +typedef struct i8080 { + union { + uint16_t af; /* Intended in case we also go for μPD9002 emulation, which also has a Z80 emulation mode. */ + struct { + uint8_t a; + uint8_t flags; + }; + }; + union { + uint16_t bc; + struct { + uint8_t b; + uint8_t c; + }; + }; + union { + uint16_t de; + struct { + uint8_t d; + uint8_t e; + }; + }; + union { + uint16_t hl; + struct { + uint8_t h; + uint8_t l; + }; + }; + uint16_t pc; + uint16_t sp; + uint16_t oldpc; + uint16_t ei; + uint32_t pmembase; + uint32_t dmembase; /* Base from where i8080 starts. */ + uint8_t emulated; /* 0 = not emulated, use separate registers, 1 = emulated, use x86 registers. */ + uint16_t *cpu_flags; + void (*writemembyte)(uint32_t, uint8_t); + uint8_t (*readmembyte)(uint32_t); + void (*startclock)(void); + void (*endclock)(void); + void (*checkinterrupts)(void); + uint8_t (*fetchinstruction)(void *); +} i8080; + +#define C_FLAG_I8080 (1 << 0) +#define P_FLAG_I8080 (1 << 2) +#define AC_FLAG_I8080 (1 << 4) +#define Z_FLAG_I8080 (1 << 6) +#define S_FLAG_I8080 (1 << 7) diff --git a/src/include/86box/i82335.h b/src/include/86box/i82335.h index 7cb4c4ef3..709760070 100644 --- a/src/include/86box/i82335.h +++ b/src/include/86box/i82335.h @@ -1 +1,6 @@ +#ifndef EMU_I82335_H +#define EMU_I82335_H + extern void i82335_init(void); + +#endif /*EMU_I82335_H*/ diff --git a/src/include/86box/ibm_5161.h b/src/include/86box/ibm_5161.h index 69f9d23a8..e189826a8 100644 --- a/src/include/86box/ibm_5161.h +++ b/src/include/86box/ibm_5161.h @@ -1,15 +1,23 @@ /* - * 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. + * 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. * - * Emulation of the IBM Expansion Unit (5161). + * This file is part of the 86Box distribution. + * + * Emulation of the IBM Expansion Unit (5161). * * * - * Author: Miran Grca, - * Copyright 2016-2018 Miran Grca. + * Authors: Miran Grca, + * + * Copyright 2016-2018 Miran Grca. */ +#ifndef EMU_IBM_5161_H +#define EMU_IBM_5161_H + extern const device_t ibm_5161_device; + +#endif /*EMU_IBM_5151_H*/ diff --git a/src/include/86box/ini.h b/src/include/86box/ini.h new file mode 100644 index 000000000..d52620f69 --- /dev/null +++ b/src/include/86box/ini.h @@ -0,0 +1,97 @@ +/* + * 86Box A hypervisor and IBM PC system emulator that specializes in + * running old operating systems and software designed for IBM + * PC systems and compatibles from 1981 through fairly recent + * system designs based on the PCI bus. + * + * This file is part of the 86Box distribution. + * + * Configuration file handler header. + * + * + * + * Authors: Sarah Walker, + * Miran Grca, + * Fred N. van Kempen, + * Overdoze, + * + * Copyright 2008-2017 Sarah Walker. + * Copyright 2016-2017 Miran Grca. + * + */ +#ifndef EMU_INI_H +#define EMU_INI_H + +#ifdef __cplusplus +extern "C" { +#endif + +typedef void *ini_t; +typedef void *ini_section_t; + +extern ini_t ini_new(void); +extern ini_t ini_read(const char *fn); +extern void ini_write(ini_t ini, const char *fn); +extern void ini_dump(ini_t ini); +extern void ini_close(ini_t ini); + +extern void ini_section_delete_var(ini_section_t section, const char *name); +extern int ini_section_get_int(ini_section_t section, const char *name, int def); +extern uint32_t ini_section_get_uint(ini_section_t section, const char *name, uint32_t def); +#if 0 +extern float ini_section_get_float(ini_section_t section, const char *name, float def); +#endif +extern double ini_section_get_double(ini_section_t section, const char *name, double def); +extern int ini_section_get_hex16(ini_section_t section, const char *name, int def); +extern int ini_section_get_hex20(ini_section_t section, const char *name, int def); +extern int ini_section_get_mac(ini_section_t section, const char *name, int def); +extern char *ini_section_get_string(ini_section_t section, const char *name, char *def); +extern wchar_t *ini_section_get_wstring(ini_section_t section, const char *name, wchar_t *def); +extern void ini_section_set_int(ini_section_t section, const char *name, int val); +extern void ini_section_set_uint(ini_section_t section, const char *name, uint32_t val); +#if 0 +extern void ini_section_set_float(ini_section_t section, const char *name, float val); +#endif +extern void ini_section_set_double(ini_section_t section, const char *name, double val); +extern void ini_section_set_hex16(ini_section_t section, const char *name, int val); +extern void ini_section_set_hex20(ini_section_t section, const char *name, int val); +extern void ini_section_set_mac(ini_section_t section, const char *name, int val); +extern void ini_section_set_string(ini_section_t section, const char *name, const char *val); +extern void ini_section_set_wstring(ini_section_t section, const char *name, wchar_t *val); + +#define ini_delete_var(ini, head, name) ini_section_delete_var(ini_find_section(ini, head), name) + +#define ini_get_int(ini, head, name, def) ini_section_get_int(ini_find_section(ini, head), name, def) +#define ini_get_uint(ini, head, name, def) ini_section_get_uint(ini_find_section(ini, head), name, def) +#if 0 +#define ini_get_float(ini, head, name, def) ini_section_get_float(ini_find_section(ini, head), name, def) +#endif +#define ini_get_double(ini, head, name, def) ini_section_get_double(ini_find_section(ini, head), name, def) +#define ini_get_hex16(ini, head, name, def) ini_section_get_hex16(ini_find_section(ini, head), name, def) +#define ini_get_hex20(ini, head, name, def) ini_section_get_hex20(ini_find_section(ini, head), name, def) +#define ini_get_mac(ini, head, name, def) ini_section_get_mac(ini_find_section(ini, head), name, def) +#define ini_get_string(ini, head, name, def) ini_section_get_string(ini_find_section(ini, head), name, def) +#define ini_get_wstring(ini, head, name, def) ini_section_get_wstring(ini_find_section(ini, head), name, def) + +#define ini_set_int(ini, head, name, val) ini_section_set_int(ini_find_or_create_section(ini, head), name, val) +#define ini_set_uint(ini, head, name, val) ini_section_set_uint(ini_find_or_create_section(ini, head), name, val) +#if 0 +#define ini_set_float(ini, head, name, val) ini_section_set_float(ini_find_or_create_section(ini, head), name, val) +#endif +#define ini_set_double(ini, head, name, val) ini_section_set_double(ini_find_or_create_section(ini, head), name, val) +#define ini_set_hex16(ini, head, name, val) ini_section_set_hex16(ini_find_or_create_section(ini, head), name, val) +#define ini_set_hex20(ini, head, name, val) ini_section_set_hex20(ini_find_or_create_section(ini, head), name, val) +#define ini_set_mac(ini, head, name, val) ini_section_set_mac(ini_find_or_create_section(ini, head), name, val) +#define ini_set_string(ini, head, name, val) ini_section_set_string(ini_find_or_create_section(ini, head), name, val) +#define ini_set_wstring(ini, head, name, val) ini_section_set_wstring(ini_find_or_create_section(ini, head), name, val) + +extern ini_section_t ini_find_section(ini_t ini, const char *name); +extern ini_section_t ini_find_or_create_section(ini_t ini, const char *name); +extern void ini_rename_section(ini_section_t section, const char *name); +extern void ini_delete_section_if_empty(ini_t ini, ini_section_t section); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/src/include/86box/io.h b/src/include/86box/io.h index c483819ce..b80b37a39 100644 --- a/src/include/86box/io.h +++ b/src/include/86box/io.h @@ -1,120 +1,118 @@ /* - * 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. + * 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. + * This file is part of the 86Box distribution. * - * Definitions for the I/O handler. + * Definitions for the I/O handler. * * * - * Authors: Sarah Walker, - * Miran Grca, - * Fred N. van Kempen, + * Authors: Sarah Walker, + * Miran Grca, + * Fred N. van Kempen, * - * Copyright 2008-2017 Sarah Walker. - * Copyright 2016,2017 Miran Grca. + * Copyright 2008-2017 Sarah Walker. + * Copyright 2016-2017 Miran Grca. */ #ifndef EMU_IO_H -# define EMU_IO_H +#define EMU_IO_H +extern void io_init(void); -extern void io_init(void); +extern void io_sethandler_common(uint16_t base, int size, + uint8_t (*inb)(uint16_t addr, void *priv), + uint16_t (*inw)(uint16_t addr, void *priv), + uint32_t (*inl)(uint16_t addr, void *priv), + void (*outb)(uint16_t addr, uint8_t val, void *priv), + void (*outw)(uint16_t addr, uint16_t val, void *priv), + void (*outl)(uint16_t addr, uint32_t val, void *priv), + void *priv, int step); -extern void io_sethandler_common(uint16_t base, int size, - uint8_t (*inb)(uint16_t addr, void *priv), - uint16_t (*inw)(uint16_t addr, void *priv), - uint32_t (*inl)(uint16_t addr, void *priv), - void (*outb)(uint16_t addr, uint8_t val, void *priv), - void (*outw)(uint16_t addr, uint16_t val, void *priv), - void (*outl)(uint16_t addr, uint32_t val, void *priv), - void *priv, int step); +extern void io_removehandler_common(uint16_t base, int size, + uint8_t (*inb)(uint16_t addr, void *priv), + uint16_t (*inw)(uint16_t addr, void *priv), + uint32_t (*inl)(uint16_t addr, void *priv), + void (*outb)(uint16_t addr, uint8_t val, void *priv), + void (*outw)(uint16_t addr, uint16_t val, void *priv), + void (*outl)(uint16_t addr, uint32_t val, void *priv), + void *priv, int step); -extern void io_removehandler_common(uint16_t base, int size, - uint8_t (*inb)(uint16_t addr, void *priv), - uint16_t (*inw)(uint16_t addr, void *priv), - uint32_t (*inl)(uint16_t addr, void *priv), - void (*outb)(uint16_t addr, uint8_t val, void *priv), - void (*outw)(uint16_t addr, uint16_t val, void *priv), - void (*outl)(uint16_t addr, uint32_t val, void *priv), - void *priv, int step); +extern void io_handler_common(int set, uint16_t base, int size, + uint8_t (*inb)(uint16_t addr, void *priv), + uint16_t (*inw)(uint16_t addr, void *priv), + uint32_t (*inl)(uint16_t addr, void *priv), + void (*outb)(uint16_t addr, uint8_t val, void *priv), + void (*outw)(uint16_t addr, uint16_t val, void *priv), + void (*outl)(uint16_t addr, uint32_t val, void *priv), + void *priv, int step); -extern void io_handler_common(int set, uint16_t base, int size, - uint8_t (*inb)(uint16_t addr, void *priv), - uint16_t (*inw)(uint16_t addr, void *priv), - uint32_t (*inl)(uint16_t addr, void *priv), - void (*outb)(uint16_t addr, uint8_t val, void *priv), - void (*outw)(uint16_t addr, uint16_t val, void *priv), - void (*outl)(uint16_t addr, uint32_t val, void *priv), - void *priv, int step); +extern void io_sethandler(uint16_t base, int size, + uint8_t (*inb)(uint16_t addr, void *priv), + uint16_t (*inw)(uint16_t addr, void *priv), + uint32_t (*inl)(uint16_t addr, void *priv), + void (*outb)(uint16_t addr, uint8_t val, void *priv), + void (*outw)(uint16_t addr, uint16_t val, void *priv), + void (*outl)(uint16_t addr, uint32_t val, void *priv), + void *priv); -extern void io_sethandler(uint16_t base, int size, - uint8_t (*inb)(uint16_t addr, void *priv), - uint16_t (*inw)(uint16_t addr, void *priv), - uint32_t (*inl)(uint16_t addr, void *priv), - void (*outb)(uint16_t addr, uint8_t val, void *priv), - void (*outw)(uint16_t addr, uint16_t val, void *priv), - void (*outl)(uint16_t addr, uint32_t val, void *priv), - void *priv); +extern void io_removehandler(uint16_t base, int size, + uint8_t (*inb)(uint16_t addr, void *priv), + uint16_t (*inw)(uint16_t addr, void *priv), + uint32_t (*inl)(uint16_t addr, void *priv), + void (*outb)(uint16_t addr, uint8_t val, void *priv), + void (*outw)(uint16_t addr, uint16_t val, void *priv), + void (*outl)(uint16_t addr, uint32_t val, void *priv), + void *priv); -extern void io_removehandler(uint16_t base, int size, - uint8_t (*inb)(uint16_t addr, void *priv), - uint16_t (*inw)(uint16_t addr, void *priv), - uint32_t (*inl)(uint16_t addr, void *priv), - void (*outb)(uint16_t addr, uint8_t val, void *priv), - void (*outw)(uint16_t addr, uint16_t val, void *priv), - void (*outl)(uint16_t addr, uint32_t val, void *priv), - void *priv); +extern void io_handler(int set, uint16_t base, int size, + uint8_t (*inb)(uint16_t addr, void *priv), + uint16_t (*inw)(uint16_t addr, void *priv), + uint32_t (*inl)(uint16_t addr, void *priv), + void (*outb)(uint16_t addr, uint8_t val, void *priv), + void (*outw)(uint16_t addr, uint16_t val, void *priv), + void (*outl)(uint16_t addr, uint32_t val, void *priv), + void *priv); -extern void io_handler(int set, uint16_t base, int size, - uint8_t (*inb)(uint16_t addr, void *priv), - uint16_t (*inw)(uint16_t addr, void *priv), - uint32_t (*inl)(uint16_t addr, void *priv), - void (*outb)(uint16_t addr, uint8_t val, void *priv), - void (*outw)(uint16_t addr, uint16_t val, void *priv), - void (*outl)(uint16_t addr, uint32_t val, void *priv), - void *priv); +extern void io_sethandler_interleaved(uint16_t base, int size, + uint8_t (*inb)(uint16_t addr, void *priv), + uint16_t (*inw)(uint16_t addr, void *priv), + uint32_t (*inl)(uint16_t addr, void *priv), + void (*outb)(uint16_t addr, uint8_t val, void *priv), + void (*outw)(uint16_t addr, uint16_t val, void *priv), + void (*outl)(uint16_t addr, uint32_t val, void *priv), + void *priv); -extern void io_sethandler_interleaved(uint16_t base, int size, - uint8_t (*inb)(uint16_t addr, void *priv), - uint16_t (*inw)(uint16_t addr, void *priv), - uint32_t (*inl)(uint16_t addr, void *priv), - void (*outb)(uint16_t addr, uint8_t val, void *priv), - void (*outw)(uint16_t addr, uint16_t val, void *priv), - void (*outl)(uint16_t addr, uint32_t val, void *priv), - void *priv); +extern void io_removehandler_interleaved(uint16_t base, int size, + uint8_t (*inb)(uint16_t addr, void *priv), + uint16_t (*inw)(uint16_t addr, void *priv), + uint32_t (*inl)(uint16_t addr, void *priv), + void (*outb)(uint16_t addr, uint8_t val, void *priv), + void (*outw)(uint16_t addr, uint16_t val, void *priv), + void (*outl)(uint16_t addr, uint32_t val, void *priv), + void *priv); -extern void io_removehandler_interleaved(uint16_t base, int size, - uint8_t (*inb)(uint16_t addr, void *priv), - uint16_t (*inw)(uint16_t addr, void *priv), - uint32_t (*inl)(uint16_t addr, void *priv), - void (*outb)(uint16_t addr, uint8_t val, void *priv), - void (*outw)(uint16_t addr, uint16_t val, void *priv), - void (*outl)(uint16_t addr, uint32_t val, void *priv), - void *priv); +extern void io_handler_interleaved(int set, uint16_t base, int size, + uint8_t (*inb)(uint16_t addr, void *priv), + uint16_t (*inw)(uint16_t addr, void *priv), + uint32_t (*inl)(uint16_t addr, void *priv), + void (*outb)(uint16_t addr, uint8_t val, void *priv), + void (*outw)(uint16_t addr, uint16_t val, void *priv), + void (*outl)(uint16_t addr, uint32_t val, void *priv), + void *priv); -extern void io_handler_interleaved(int set, uint16_t base, int size, - uint8_t (*inb)(uint16_t addr, void *priv), - uint16_t (*inw)(uint16_t addr, void *priv), - uint32_t (*inl)(uint16_t addr, void *priv), - void (*outb)(uint16_t addr, uint8_t val, void *priv), - void (*outw)(uint16_t addr, uint16_t val, void *priv), - void (*outl)(uint16_t addr, uint32_t val, void *priv), - void *priv); +extern uint8_t inb(uint16_t port); +extern void outb(uint16_t port, uint8_t val); +extern uint16_t inw(uint16_t port); +extern void outw(uint16_t port, uint16_t val); +extern uint32_t inl(uint16_t port); +extern void outl(uint16_t port, uint32_t val); -extern uint8_t inb(uint16_t port); -extern void outb(uint16_t port, uint8_t val); -extern uint16_t inw(uint16_t port); -extern void outw(uint16_t port, uint16_t val); -extern uint32_t inl(uint16_t port); -extern void outl(uint16_t port, uint32_t val); +extern void *io_trap_add(void (*func)(int size, uint16_t addr, uint8_t write, uint8_t val, void *priv), + void *priv); +extern void io_trap_remap(void *handle, int enable, uint16_t addr, uint16_t size); +extern void io_trap_remove(void *handle); -extern void *io_trap_add(void (*func)(int size, uint16_t addr, uint8_t write, uint8_t val, void *priv), - void *priv); -extern void io_trap_remap(void *handle, int enable, uint16_t addr, uint16_t size); -extern void io_trap_remove(void *handle); - - -#endif /*EMU_IO_H*/ +#endif /*EMU_IO_H*/ diff --git a/src/include/86box/isamem.h b/src/include/86box/isamem.h index 90d7666ec..9a1841c53 100644 --- a/src/include/86box/isamem.h +++ b/src/include/86box/isamem.h @@ -1,36 +1,34 @@ /* - * VARCem Virtual ARchaeological Computer EMulator. - * An emulator of (mostly) x86-based PC systems and devices, - * using the ISA,EISA,VLB,MCA and PCI system buses, roughly - * spanning the era between 1981 and 1995. + * VARCem Virtual ARchaeological Computer EMulator. + * An emulator of (mostly) x86-based PC systems and devices, + * using the ISA,EISA,VLB,MCA and PCI system buses, roughly + * spanning the era between 1981 and 1995. * - * This file is part of the VARCem Project. - * - * Definitions for the ISAMEM cards. + * Definitions for the ISAMEM cards. * * * - * Authors: Fred N. van Kempen, + * Authors: Fred N. van Kempen, * - * Copyright 2018 Fred N. van Kempen. + * Copyright 2018 Fred N. van Kempen. * - * Redistribution and use in source and binary forms, with - * or without modification, are permitted provided that the - * following conditions are met: + * Redistribution and use in source and binary forms, with + * or without modification, are permitted provided that the + * following conditions are met: * - * 1. Redistributions of source code must retain the entire - * above notice, this list of conditions and the following - * disclaimer. + * 1. Redistributions of source code must retain the entire + * above notice, this list of conditions and the following + * disclaimer. * - * 2. Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the - * following disclaimer in the documentation and/or other - * materials provided with the distribution. + * 2. Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the + * following disclaimer in the documentation and/or other + * materials provided with the distribution. * - * 3. Neither the name of the copyright holder nor the names - * of its contributors may be used to endorse or promote - * products derived from this software without specific - * prior written permission. + * 3. Neither the name of the copyright holder nor the names + * of its contributors may be used to endorse or promote + * products derived from this software without specific + * prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT @@ -44,12 +42,11 @@ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -#ifndef ISAMEM_H -# define ISAMEM_H +#ifndef EMU_ISAMEM_H +#define EMU_ISAMEM_H -#define ISAMEM_MAX 4 /* max #cards in system */ - +#define ISAMEM_MAX 4 /* max #cards in system */ #ifdef __cplusplus extern "C" { @@ -60,18 +57,16 @@ extern const device_t isamem_device; extern const device_t isamem_brat80_device; extern const device_t isamem_ev159_device; - /* Functions. */ -extern void isamem_reset(void); +extern void isamem_reset(void); -extern const char *isamem_get_name(int t); -extern const char *isamem_get_internal_name(int t); -extern int isamem_get_from_internal_name(const char *s); -extern const device_t *isamem_get_device(int t); +extern const char *isamem_get_name(int t); +extern const char *isamem_get_internal_name(int t); +extern int isamem_get_from_internal_name(const char *s); +extern const device_t *isamem_get_device(int t); #ifdef __cplusplus } #endif - -#endif /*ISAMEM_H*/ +#endif /*EMU_ISAMEM_H*/ diff --git a/src/include/86box/isapnp.h b/src/include/86box/isapnp.h index 38fc59d07..71c1bb29a 100644 --- a/src/include/86box/isapnp.h +++ b/src/include/86box/isapnp.h @@ -1,69 +1,70 @@ /* - * 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. + * 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. + * This file is part of the 86Box distribution. * - * Definitions for ISA Plug and Play. + * Definitions for ISA Plug and Play. * * * - * Author: RichardG, + * Authors: RichardG, * - * Copyright 2021 RichardG. + * Copyright 2021 RichardG. */ + #ifndef EMU_ISAPNP_H -# define EMU_ISAPNP_H -# include - - -#define ISAPNP_MEM_DISABLED 0 -#define ISAPNP_IO_DISABLED 0 -#define ISAPNP_IRQ_DISABLED 0 -#define ISAPNP_DMA_DISABLED 4 +#define EMU_ISAPNP_H +#include +#define ISAPNP_MEM_DISABLED 0 +#define ISAPNP_IO_DISABLED 0 +#define ISAPNP_IRQ_DISABLED 0 +#define ISAPNP_DMA_DISABLED 4 enum { - ISAPNP_CARD_DISABLE = 0, - ISAPNP_CARD_ENABLE = 1, - ISAPNP_CARD_FORCE_CONFIG /* cheat code for UMC UM8669F */ + ISAPNP_CARD_DISABLE = 0, + ISAPNP_CARD_ENABLE = 1, + ISAPNP_CARD_FORCE_CONFIG = 2, /* cheat code for UMC UM8669F */ + ISAPNP_CARD_NO_KEY = 3 /* cheat code for Crystal CS423x */ }; - -typedef struct { - uint8_t activate; - struct { - uint32_t base: 24, size: 24; +typedef struct isapnp_device_config_t { + uint8_t activate; + struct pnp_mem_t { + uint32_t base : 24; + uint32_t size : 24; } mem[4]; - struct { - uint32_t base, size; + struct pnp_mem32_t { + uint32_t base; + uint32_t size; } mem32[4]; - struct { - uint16_t base; + struct pnp_io_t { + uint16_t base; } io[8]; - struct { - uint8_t irq: 4, level: 1, type: 1; + struct pnp_irq_t { + uint8_t irq : 4; + uint8_t level : 1; + uint8_t type : 1; } irq[2]; - struct { - uint8_t dma: 3; + struct pnp_dma_t { + uint8_t dma : 3; } dma[2]; } isapnp_device_config_t; +void *isapnp_add_card(uint8_t *rom, uint16_t rom_size, + void (*config_changed)(uint8_t ld, isapnp_device_config_t *config, void *priv), + void (*csn_changed)(uint8_t csn, void *priv), + uint8_t (*read_vendor_reg)(uint8_t ld, uint8_t reg, void *priv), + void (*write_vendor_reg)(uint8_t ld, uint8_t reg, uint8_t val, void *priv), + void *priv); +void isapnp_update_card_rom(void *priv, uint8_t *rom, uint16_t rom_size); +void isapnp_enable_card(void *priv, uint8_t enable); +void isapnp_set_csn(void *priv, uint8_t csn); +void isapnp_set_device_defaults(void *priv, uint8_t ldn, const isapnp_device_config_t *config); +void isapnp_reset_card(void *priv); +void isapnp_reset_device(void *priv, uint8_t ld); -void *isapnp_add_card(uint8_t *rom, uint16_t rom_size, - void (*config_changed)(uint8_t ld, isapnp_device_config_t *config, void *priv), - void (*csn_changed)(uint8_t csn, void *priv), - uint8_t (*read_vendor_reg)(uint8_t ld, uint8_t reg, void *priv), - void (*write_vendor_reg)(uint8_t ld, uint8_t reg, uint8_t val, void *priv), - void *priv); -void isapnp_update_card_rom(void *priv, uint8_t *rom, uint16_t rom_size); -void isapnp_enable_card(void *priv, uint8_t enable); -void isapnp_set_csn(void *priv, uint8_t csn); -void isapnp_set_device_defaults(void *priv, uint8_t ldn, const isapnp_device_config_t *config); -void isapnp_reset_card(void *priv); -void isapnp_reset_device(void *priv, uint8_t ld); - - -#endif /*EMU_ISAPNP_H*/ +#endif /*EMU_ISAPNP_H*/ diff --git a/src/include/86box/isartc.h b/src/include/86box/isartc.h index e2cb82b97..92c58e350 100644 --- a/src/include/86box/isartc.h +++ b/src/include/86box/isartc.h @@ -1,36 +1,34 @@ /* - * VARCem Virtual ARchaeological Computer EMulator. - * An emulator of (mostly) x86-based PC systems and devices, - * using the ISA,EISA,VLB,MCA and PCI system buses, roughly - * spanning the era between 1981 and 1995. + * VARCem Virtual ARchaeological Computer EMulator. + * An emulator of (mostly) x86-based PC systems and devices, + * using the ISA,EISA,VLB,MCA and PCI system buses, roughly + * spanning the era between 1981 and 1995. * - * This file is part of the VARCem Project. - * - * Definitions for the ISARTC cards. + * Definitions for the ISARTC cards. * * * - * Authors: Fred N. van Kempen, + * Authors: Fred N. van Kempen, * - * Copyright 2018 Fred N. van Kempen. + * Copyright 2018 Fred N. van Kempen. * - * Redistribution and use in source and binary forms, with - * or without modification, are permitted provided that the - * following conditions are met: + * Redistribution and use in source and binary forms, with + * or without modification, are permitted provided that the + * following conditions are met: * - * 1. Redistributions of source code must retain the entire - * above notice, this list of conditions and the following - * disclaimer. + * 1. Redistributions of source code must retain the entire + * above notice, this list of conditions and the following + * disclaimer. * - * 2. Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the - * following disclaimer in the documentation and/or other - * materials provided with the distribution. + * 2. Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the + * following disclaimer in the documentation and/or other + * materials provided with the distribution. * - * 3. Neither the name of the copyright holder nor the names - * of its contributors may be used to endorse or promote - * products derived from this software without specific - * prior written permission. + * 3. Neither the name of the copyright holder nor the names + * of its contributors may be used to endorse or promote + * products derived from this software without specific + * prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT @@ -44,9 +42,9 @@ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -#ifndef ISARTC_H -# define ISARTC_H +#ifndef EMU_ISARTC_H +#define EMU_ISARTC_H #ifdef __cplusplus extern "C" { @@ -54,17 +52,15 @@ extern "C" { /* Global variables. */ - /* Functions. */ -extern void isartc_reset(void); +extern void isartc_reset(void); -extern char *isartc_get_internal_name(int t); -extern int isartc_get_from_internal_name(char *s); -extern const device_t *isartc_get_device(int t); +extern const char *isartc_get_internal_name(int t); +extern int isartc_get_from_internal_name(char *s); +extern const device_t *isartc_get_device(int t); #ifdef __cplusplus } #endif - -#endif /*ISARTC_H*/ +#endif /*EMU_ISARTC_H*/ diff --git a/src/include/86box/joystick_ch_flightstick_pro.h b/src/include/86box/joystick_ch_flightstick_pro.h index 1358f9d69..b49800ecb 100644 --- a/src/include/86box/joystick_ch_flightstick_pro.h +++ b/src/include/86box/joystick_ch_flightstick_pro.h @@ -1,20 +1,20 @@ /* - * VARCem Virtual ARchaeological Computer EMulator. - * An emulator of (mostly) x86-based PC systems and devices, - * using the ISA,EISA,VLB,MCA and PCI system buses, roughly - * spanning the era between 1981 and 1995. + * 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 VARCem Project. + * This file is part of the 86Box distribution. * - * Definitions for the Flight Stick Pro driver. + * Definitions for the Flight Stick Pro driver. * * * - * Authors: Miran Grca, - * Sarah Walker, + * Authors: Miran Grca, + * Sarah Walker, * - * Copyright 2016-2018 Miran Grca. - * Copyright 2008-2018 Sarah Walker. + * Copyright 2016-2018 Miran Grca. + * Copyright 2008-2018 Sarah Walker. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -35,4 +35,9 @@ * USA. */ +#ifndef EMU_JOYSTICK_CH_FLIGHTSTICK_PRO_H +#define EMU_JOYSTICK_CH_FLIGHTSTICK_PRO_H + extern const joystick_if_t joystick_ch_flightstick_pro; + +#endif /*EMU_JOYSTICK_CH_FLIGHTSTICK_PRO_H*/ diff --git a/src/include/86box/joystick_standard.h b/src/include/86box/joystick_standard.h index 9bc86b204..c874677ea 100644 --- a/src/include/86box/joystick_standard.h +++ b/src/include/86box/joystick_standard.h @@ -1,20 +1,20 @@ /* - * VARCem Virtual ARchaeological Computer EMulator. - * An emulator of (mostly) x86-based PC systems and devices, - * using the ISA,EISA,VLB,MCA and PCI system buses, roughly - * spanning the era between 1981 and 1995. + * 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 VARCem Project. + * This file is part of the 86Box distribution. * - * Definitions for the joystick driver. + * Definitions for the joystick driver. * * * - * Authors: Miran Grca, - * Sarah Walker, + * Authors: Miran Grca, + * Sarah Walker, * - * Copyright 2016-2018 Miran Grca. - * Copyright 2008-2018 Sarah Walker. + * Copyright 2016-2018 Miran Grca. + * Copyright 2008-2018 Sarah Walker. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -35,6 +35,9 @@ * USA. */ +#ifndef EMU_JOYSTICK_STANDARD_H +#define EMU_JOYSTICK_STANDARD_H + extern const joystick_if_t joystick_2axis_2button; extern const joystick_if_t joystick_2axis_4button; extern const joystick_if_t joystick_3axis_2button; @@ -42,3 +45,5 @@ extern const joystick_if_t joystick_3axis_4button; extern const joystick_if_t joystick_4axis_4button; extern const joystick_if_t joystick_2axis_6button; extern const joystick_if_t joystick_2axis_8button; + +#endif /*EMU_JOYSTICK_STANDARD_H*/ diff --git a/src/include/86box/joystick_sw_pad.h b/src/include/86box/joystick_sw_pad.h index 2f62aab19..a75d802de 100644 --- a/src/include/86box/joystick_sw_pad.h +++ b/src/include/86box/joystick_sw_pad.h @@ -1,20 +1,20 @@ /* - * VARCem Virtual ARchaeological Computer EMulator. - * An emulator of (mostly) x86-based PC systems and devices, - * using the ISA,EISA,VLB,MCA and PCI system buses, roughly - * spanning the era between 1981 and 1995. + * 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 VARCem Project. + * This file is part of the 86Box distribution. * - * Definitions for the Sidewinder Pro driver. + * Definitions for the Sidewinder Pro driver. * * * - * Authors: Miran Grca, - * Sarah Walker, + * Authors: Miran Grca, + * Sarah Walker, * - * Copyright 2016-2018 Miran Grca. - * Copyright 2008-2018 Sarah Walker. + * Copyright 2016-2018 Miran Grca. + * Copyright 2008-2018 Sarah Walker. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -35,4 +35,9 @@ * USA. */ +#ifndef EMU_JOYSTICK_SW_PAD_H +#define EMU_JOYSTICK_SW_PAD_H + extern const joystick_if_t joystick_sw_pad; + +#endif /*EMU_JOYSTICK_SW_PAD_H*/ diff --git a/src/include/86box/joystick_tm_fcs.h b/src/include/86box/joystick_tm_fcs.h index 60067d88a..65e734a40 100644 --- a/src/include/86box/joystick_tm_fcs.h +++ b/src/include/86box/joystick_tm_fcs.h @@ -1,20 +1,20 @@ /* - * VARCem Virtual ARchaeological Computer EMulator. - * An emulator of (mostly) x86-based PC systems and devices, - * using the ISA,EISA,VLB,MCA and PCI system buses, roughly - * spanning the era between 1981 and 1995. + * 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 VARCem Project. + * This file is part of the 86Box distribution. * - * Definitions for the Flight Control System driver. + * Definitions for the Flight Control System driver. * * * - * Authors: Miran Grca, - * Sarah Walker, + * Authors: Miran Grca, + * Sarah Walker, * - * Copyright 2016-2018 Miran Grca. - * Copyright 2008-2018 Sarah Walker. + * Copyright 2016-2018 Miran Grca. + * Copyright 2008-2018 Sarah Walker. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -35,4 +35,9 @@ * USA. */ +#ifndef EMU_JOYSTICK_TM_FCS_H +#define EMU_JOYSTICK_TM_FCS_H + extern const joystick_if_t joystick_tm_fcs; + +#endif /*EMU_JOYSTICK_TM_FCS_H*/ diff --git a/src/include/86box/keyboard.h b/src/include/86box/keyboard.h index 206feeefc..a4b079760 100644 --- a/src/include/86box/keyboard.h +++ b/src/include/86box/keyboard.h @@ -1,127 +1,287 @@ /* - * 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. + * 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. + * This file is part of the 86Box distribution. * - * Definitions for the keyboard interface. + * Definitions for the keyboard interface. * * * - * Authors: Sarah Walker, - * Miran Grca, - * Fred N. van Kempen, + * Authors: Sarah Walker, + * Miran Grca, + * Fred N. van Kempen, * - * Copyright 2008-2019 Sarah Walker. - * Copyright 2016-2019 Miran Grca. - * Copyright 2017-2019 Fred N. van Kempen. + * Copyright 2008-2019 Sarah Walker. + * Copyright 2016-2019 Miran Grca. + * Copyright 2017-2019 Fred N. van Kempen. */ + #ifndef EMU_KEYBOARD_H -# define EMU_KEYBOARD_H +#define EMU_KEYBOARD_H +enum { + DEV_KBD = 0, + DEV_AUX = 1 +}; -typedef struct { - const uint8_t mk[4]; - const uint8_t brk[4]; +enum { + DEV_STATE_MAIN_1 = 0, + DEV_STATE_MAIN_OUT = 1, + DEV_STATE_MAIN_2 = 2, + DEV_STATE_MAIN_CMD = 3, + DEV_STATE_MAIN_WANT_IN = 4, + DEV_STATE_MAIN_IN = 5, + DEV_STATE_EXECUTE_BAT = 6, + DEV_STATE_MAIN_WANT_EXECUTE_BAT = 7 +}; + +/* Used by the AT / PS/2 keyboard controller, common device, keyboard, and mouse. */ +typedef struct kbc_at_port_t { + uint8_t wantcmd; + uint8_t dat; + + int16_t out_new; + + void *priv; + + void (*poll)(void *priv); +} kbc_at_port_t; + +/* Used by the AT / PS/2 common device, keyboard, and mouse. */ +typedef struct atkbc_dev_t { + const char *name; /* name of this device */ + + uint8_t type; + uint8_t command; + uint8_t last_scan_code; + uint8_t state; + uint8_t resolution; + uint8_t rate; + uint8_t cmd_queue_start; + uint8_t cmd_queue_end; + uint8_t queue_start; + uint8_t queue_end; + + uint16_t flags; + + /* Internal FIFO, not present on real devices, needed for commands that + output multiple bytes. */ + uint8_t cmd_queue[16]; + + uint8_t queue[64]; + + int fifo_mask; + int mode; + int x; + int y; + int z; + int b; + + int *scan; + + void (*process_cmd)(void *priv); + void (*execute_bat)(void *priv); + + kbc_at_port_t *port; +} atkbc_dev_t; + +typedef struct scancode { + const uint8_t mk[4]; + const uint8_t brk[4]; } scancode; +#define STATE_SHIFT_MASK 0x22 +#define STATE_RSHIFT 0x20 +#define STATE_LSHIFT 0x02 -#define STATE_SHIFT_MASK 0x22 -#define STATE_RSHIFT 0x20 -#define STATE_LSHIFT 0x02 - -#define FAKE_LSHIFT_ON 0x100 -#define FAKE_LSHIFT_OFF 0x101 -#define LSHIFT_ON 0x102 -#define LSHIFT_OFF 0x103 -#define RSHIFT_ON 0x104 -#define RSHIFT_OFF 0x105 +#define FAKE_LSHIFT_ON 0x100 +#define FAKE_LSHIFT_OFF 0x101 +#define LSHIFT_ON 0x102 +#define LSHIFT_OFF 0x103 +#define RSHIFT_ON 0x104 +#define RSHIFT_OFF 0x105 +/* KBC #define's */ +/* IBM-style controllers */ +#define KBC_IBM_PC_XT 0x0000 /* IBM PC/XT */ +#define KBC_IBM_PCJR 0x0001 /* IBM PCjr */ +#define KBC_IBM_TYPE_1 0x0002 /* IBM AT / PS/2 Type 1 */ +#define KBC_IBM_TYPE_2 0x0003 /* IBM PS/2 Type 2 */ +#define KBC_AMI_ACCESS_METHODS 0x0004 /* Access Methods AMI */ +#define KBC_JU_JET 0x0005 /* Ju-Jet */ +/* OEM proprietary */ +#define KBC_TANDY 0x0011 /* Tandy 1000/1000HX */ +#define KBC_TANDY_SL2 0x0012 /* Tandy 1000SL2 */ +#define KBC_AMSTRAD 0x0013 /* Amstrad */ +#define KBC_OLIVETTI_XT 0x0014 /* Olivetti XT */ +#define KBC_OLIVETTI 0x0015 /* Olivetti AT */ +#define KBC_TOSHIBA 0x0016 /* Toshiba AT */ +#define KBC_COMPAQ 0x0017 /* Compaq */ +#define KBC_NCR 0x0018 /* NCR */ +#define KBC_QUADTEL 0x0019 /* Quadtel */ +#define KBC_SIEMENS 0x001A /* Siemens */ +/* Phoenix MultiKey/42 */ +#define PHOENIX_MK42_105 0x0521 /* Phoenix MultiKey/42 1.05 */ +#define PHOENIX_MK42_129 0x2921 /* Phoenix MultiKey/42 1.29 */ +#define PHOENIX_MK42_138 0x3821 /* Phoenix MultiKey/42 1.38 */ +#define PHOENIX_MK42_140 0x3821 /* Phoenix MultiKey/42 1.40 */ +#define PHOENIX_MKC42_214 0x1422 /* Phoenix MultiKey/C42 2.14 */ +#define PHOENIX_MK42I_416 0x1624 /* Phoenix MultiKey/42i 4.16 */ +#define PHOENIX_MK42I_419 0x1924 /* Phoenix MultiKey/42i 4.19 */ +/* AMI 0x3x */ +#define KBC_ACER_V30 0x0030 /* Acer (0xA1 returns nothing, 0xAF returns 0x00) */ +#define KBC_AMI_MEGAKEY_SUPER_IO 0x0035 /* AMI '5' MegaKey 1994 NSC (and SM(S)C?) */ +#define KBC_AMI_8 0x0038 /* AMI '8' */ +/* AMI 0x4x */ +#define KBC_AMI_B 0x0042 /* AMI 'B' */ +#define KBC_AMI_D 0x0044 /* AMI 'D' */ +#define KBC_AMI_E 0x0045 /* AMI 'E' */ +#define KBC_AMIKEY 0x0046 /* AMI 'F'/AMIKEY */ +#define KBC_AMIKEY_2 0x0048 /* AMI 'H'/AMIEY-2 */ +#define KBC_MR 0x004D /* MR 'M' - Temporary classification until we get a dump */ +/* AMI 0x5x */ +#define KBC_AMI_MEGAKEY_1993 0x0050 /* AMI 'P' MegaKey 1993 */ +#define KBC_AMI_MEGAKEY_1994 0x0052 /* AMI 'R' MegaKey 1994 - 0xA0 returns 1993 copyright */ +#define KBC_AMI_TRIGEM 0x005A /* TriGem AMI 'Z' (1990 AMI copyright) */ +/* AMI 0x6x */ +#define KBC_TANDON 0x0061 /* Tandon 'a' - Temporary classification until we get a dump */ +/* Holtek */ +#define KBC_HT_REGIONAL_6542 0x1046 /* Holtek 'F' (Regional 6542) */ +#define KBC_HT_HT6542B_BESTKEY 0x1048 /* Holtek 'H' (Holtek HT6542B, BestKey) */ +/* AMI 0x0x clone without command 0xA0 */ +#define KBC_UNK_00 0x2000 /* Unknown 0x00 */ +#define KBC_UNK_01 0x2001 /* Unknown 0x01 */ +/* AMI 0x3x clone without command 0xA0 */ +#define KBC_UNK_7 0x2037 /* Unknown '7' - Temporary classification until we get a dump */ +#define KBC_UNK_9 0x2037 /* Unknown '9' - Temporary classification until we get a dump */ +#define KBC_JETKEY_NO_VER 0x2038 /* No-version JetKey '8' */ +/* AMI 0x4x clone without command 0xA0 */ +#define KBC_UNK_A 0x2041 /* Unknown 'A' - Temporary classification until we get a dump */ +#define KBC_JETKEY_5_W83C42 0x2046 /* JetKey 5.0 'F' and Winbond W83C42 */ +#define KBC_UNK_G 0x2047 /* Unknown 'G' - Temporary classification until we get a dump */ +#define KBC_MB_300E_SIS 0x2048 /* MB-300E Non-VIA 'H' and SiS 5582/559x */ +#define KBC_UNK_L 0x204C /* Unknown 'L' - Temporary classification until we get a dump */ +/* AMI 0x0x clone with command 0xA0 (Get Copyright String) only returning 0x00 */ +#define KBC_VPC_2007 0x3000 /* Microsoft Virtual PC 2007 - everything returns 0x00 */ +/* AMI 0x4x clone with command 0xA0 (Get Copyright String) only returning 0x00 */ +#define KBC_ALI_M148X 0x3045 /* ALi M148x 'E'/'U' (0xA1 actually returns 'F' but BIOS shows 'E' or 'U') */ +#define KBC_LANCE_UTRON 0x3046 /* Lance LT38C41 'F', Utron */ +/* AMI 0x5x clone with command 0xA0 (Get Copyright String) only returning 0x00 */ +#define KBC_SARC_6042 0x3055 /* SARC 6042 'U' */ +/* Award and clones */ +#define KBC_AWARD 0x4200 /* Award (0xA1 returns 0x00) - Temporary classification until we get \ + the real 0xAF return */ +#define KBC_VIA_VT82C4XN 0x4246 /* VIA VT82C41N, VT82C4N (0xA1 returns 'F') */ +#define KBC_VIA_VT82C586A 0x4346 /* VIA VT82C586A (0xA1 returns 'F') */ +#define KBC_VIA_VT82C586B 0x4446 /* VIA VT82C586B (0xA1 returns 'F') */ +#define KBC_VIA_VT82C686B 0x4546 /* VIA VT82C686B (0xA1 returns 'F') */ +/* UMC */ +#define KBC_UMC_UM8886 0x5048 /* UMC UM8886 'H' */ +/* IBM-style controllers with inverted P1 video type bit polarity */ +#define KBC_IBM_TYPE_1_XI8088 0x8000 /* Xi8088: IBM Type 1 */ +/* AMI (this is the 0xA1 revision byte) with inverted P1 video type bit polarity */ +#define KBC_ACER_V30_INV 0x8030 /* Acer (0xA1 returns nothing, 0xAF returns 0x00) */ +/* Holtek with inverted P1 video type bit polarity */ +#define KBC_HT_HT6542B_XI8088 0x9048 /* Xi8088: Holtek 'H' (Holtek HT6542B, BestKey) */ +/* Award and clones with inverted P1 video type bit polarity */ +#define KBC_VIA_VT82C4XN_XI8088 0xC246 /* Xi8088: VIA VT82C41N, VT82C4N (0xA1 returns 'F') */ #ifdef __cplusplus extern "C" { #endif -extern uint8_t keyboard_mode; -extern int keyboard_scan; +extern uint8_t keyboard_mode; +extern int keyboard_scan; -extern void (*keyboard_send)(uint16_t val); -extern void kbd_adddata_process(uint16_t val, void (*adddata)(uint16_t val)); +extern void (*keyboard_send)(uint16_t val); +extern void kbd_adddata_process(uint16_t val, void (*adddata)(uint16_t val)); -extern const scancode scancode_xt[512]; +extern const scancode scancode_xt[512]; -extern uint8_t keyboard_set3_flags[512]; -extern uint8_t keyboard_set3_all_repeat; -extern uint8_t keyboard_set3_all_break; -extern int mouse_queue_start, mouse_queue_end; -extern int mouse_scan; +extern uint8_t keyboard_set3_flags[512]; +extern uint8_t keyboard_set3_all_repeat; +extern uint8_t keyboard_set3_all_break; +extern int mouse_queue_start; +extern int mouse_queue_end; +extern int mouse_cmd_queue_start; +extern int mouse_cmd_queue_end; +extern int mouse_scan; + +extern kbc_at_port_t *kbc_at_ports[2]; #ifdef EMU_DEVICE_H -extern const device_t keyboard_pc_device; -extern const device_t keyboard_pc82_device; -extern const device_t keyboard_xt_device; -extern const device_t keyboard_xt86_device; -extern const device_t keyboard_xt_compaq_device; -extern const device_t keyboard_tandy_device; -#if defined(DEV_BRANCH) && defined(USE_LASERXT) -extern const device_t keyboard_xt_lxt3_device; -#endif -extern const device_t keyboard_xt_olivetti_device; -extern const device_t keyboard_xt_zenith_device; -extern const device_t keyboard_at_device; -extern const device_t keyboard_at_ami_device; -extern const device_t keyboard_at_toshiba_device; -extern const device_t keyboard_at_olivetti_device; -extern const device_t keyboard_at_ncr_device; -extern const device_t keyboard_ps2_device; -extern const device_t keyboard_ps2_ps1_device; -extern const device_t keyboard_ps2_ps1_pci_device; -extern const device_t keyboard_ps2_xi8088_device; -extern const device_t keyboard_ps2_ami_device; -extern const device_t keyboard_ps2_olivetti_device; -extern const device_t keyboard_ps2_mca_device; -extern const device_t keyboard_ps2_mca_2_device; -extern const device_t keyboard_ps2_quadtel_device; -extern const device_t keyboard_ps2_pci_device; -extern const device_t keyboard_ps2_ami_pci_device; -extern const device_t keyboard_ps2_intel_ami_pci_device; -extern const device_t keyboard_ps2_acer_pci_device; -#endif +extern const device_t keyboard_pc_device; +extern const device_t keyboard_pc82_device; +extern const device_t keyboard_pravetz_device; +extern const device_t keyboard_xt_device; +extern const device_t keyboard_xt86_device; +extern const device_t keyboard_xt_compaq_device; +extern const device_t keyboard_xt_t1x00_device; +extern const device_t keyboard_tandy_device; +# if defined(DEV_BRANCH) && defined(USE_LASERXT) +extern const device_t keyboard_xt_lxt3_device; +# endif /*defined(DEV_BRANCH) && defined(USE_LASERXT) */ +extern const device_t keyboard_xt_olivetti_device; +extern const device_t keyboard_xt_zenith_device; +extern const device_t keyboard_xt_hyundai_device; +extern const device_t keyboard_xtclone_device; +extern const device_t keyboard_at_device; +extern const device_t keyboard_at_siemens_device; +extern const device_t keyboard_at_ami_device; +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; +extern const device_t keyboard_ps2_xi8088_device; +extern const device_t keyboard_ps2_ami_device; +extern const device_t keyboard_ps2_tg_ami_device; +extern const device_t keyboard_ps2_tg_ami_green_device; +extern const device_t keyboard_ps2_olivetti_device; +extern const device_t keyboard_ps2_mca_2_device; +extern const device_t keyboard_ps2_quadtel_device; +extern const device_t keyboard_ps2_pci_device; +extern const device_t keyboard_ps2_ami_pci_device; +extern const device_t keyboard_ps2_intel_ami_pci_device; +extern const device_t keyboard_ps2_acer_pci_device; +extern const device_t keyboard_ps2_ali_pci_device; +extern const device_t keyboard_ps2_tg_ami_pci_device; -extern void keyboard_init(void); -extern void keyboard_close(void); -extern void keyboard_set_table(const scancode *ptr); -extern void keyboard_poll_host(void); -extern void keyboard_process(void); -extern uint16_t keyboard_convert(int ch); -extern void keyboard_input(int down, uint16_t scan); -extern void keyboard_update_states(uint8_t cl, uint8_t nl, uint8_t sl); -extern uint8_t keyboard_get_shift(void); -extern void keyboard_get_states(uint8_t *cl, uint8_t *nl, uint8_t *sl); -extern void keyboard_set_states(uint8_t cl, uint8_t nl, uint8_t sl); -extern int keyboard_recv(uint16_t key); -extern int keyboard_isfsexit(void); -extern int keyboard_ismsexit(void); -extern void keyboard_set_is_amstrad(int ams); +extern const device_t keyboard_at_generic_device; +#endif /*EMU_DEVICE_H*/ -extern void keyboard_at_adddata_mouse(uint8_t val); -extern void keyboard_at_adddata_mouse_direct(uint8_t val); -extern void keyboard_at_adddata_mouse_cmd(uint8_t val); -extern void keyboard_at_mouse_reset(void); -extern uint8_t keyboard_at_mouse_pos(void); -extern int keyboard_at_fixed_channel(void); -extern void keyboard_at_set_mouse(void (*mouse_write)(uint8_t val,void *), void *); -extern void keyboard_at_set_a20_key(int state); -extern void keyboard_at_set_mode(int ps2); -extern uint8_t keyboard_at_get_mouse_scan(void); -extern void keyboard_at_set_mouse_scan(uint8_t val); -extern void keyboard_at_reset(void); +extern void keyboard_init(void); +extern void keyboard_close(void); +extern void keyboard_set_table(const scancode *ptr); +extern void keyboard_poll_host(void); +extern void keyboard_process(void); +extern uint16_t keyboard_convert(int ch); +extern void keyboard_input(int down, uint16_t scan); +extern void keyboard_update_states(uint8_t cl, uint8_t nl, uint8_t sl); +extern uint8_t keyboard_get_shift(void); +extern void keyboard_get_states(uint8_t *cl, uint8_t *nl, uint8_t *sl); +extern void keyboard_set_states(uint8_t cl, uint8_t nl, uint8_t sl); +extern int keyboard_recv(uint16_t key); +extern int keyboard_isfsenter(void); +extern int keyboard_isfsenter_up(void); +extern int keyboard_isfsexit(void); +extern int keyboard_isfsexit_up(void); +extern int keyboard_ismsexit(void); +extern void keyboard_set_is_amstrad(int ams); + +extern uint8_t kbc_at_dev_queue_pos(atkbc_dev_t *dev, uint8_t main); +extern void kbc_at_dev_queue_add(atkbc_dev_t *dev, uint8_t val, uint8_t main); +extern void kbc_at_dev_reset(atkbc_dev_t *dev, int do_fa); +extern atkbc_dev_t *kbc_at_dev_init(uint8_t inst); #ifdef __cplusplus } #endif - -#endif /*EMU_KEYBOARD_H*/ +#endif /*EMU_KEYBOARD_H*/ diff --git a/src/include/86box/language.h b/src/include/86box/language.h index 9a5397c6b..af459c0ff 100644 --- a/src/include/86box/language.h +++ b/src/include/86box/language.h @@ -1,258 +1,284 @@ /* - * 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. + * 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. + * This file is part of the 86Box distribution. * - * Definitions for the language management module. - * - * NOTE: FIXME: Strings 2176 and 2193 are same. + * Definitions for the language management module. * * * - * Author: Fred N. van Kempen, + * Authors: Fred N. van Kempen, * - * Copyright 2017,2018 Fred N. van Kempen. + * Copyright 2017-2018 Fred N. van Kempen. + * Copyright 2022 Jasmine Iwanek. */ -#ifndef LANG_UAGE_H -# define LANG_UAGE_H +#ifndef LANG_UAGE_H +#define LANG_UAGE_H /* String IDs. */ -#define IDS_STRINGS 2048 // "86Box" -#define IDS_2049 2049 // "Error" -#define IDS_2050 2050 // "Fatal error" -#define IDS_2051 2051 // " - PAUSED" -#define IDS_2052 2052 // "Press Ctrl+Alt+PgDn..." -#define IDS_2053 2053 // "Speed" -#define IDS_2054 2054 // "ZIP %i (%03i): %ls" -#define IDS_2055 2055 // "ZIP images (*.IM?)\0*.IM..." -#define IDS_2056 2056 // "No usable ROM images found!" -#define IDS_2057 2057 // "(empty)" -#define IDS_2058 2058 // "ZIP images (*.IM?)\0*.IM..." -#define IDS_2059 2059 // "(Turbo)" -#define IDS_2060 2060 // "On" -#define IDS_2061 2061 // "Off" -#define IDS_2062 2062 // "All floppy images (*.DSK..." -#define IDS_2063 2063 // "Machine ""%hs"" is not..." -#define IDS_2064 2064 // "Video card ""%hs"" is not..." -#define IDS_2065 2065 // "Machine" -#define IDS_2066 2066 // "Display" -#define IDS_2067 2067 // "Input devices" -#define IDS_2068 2068 // "Sound" -#define IDS_2069 2069 // "Network" -#define IDS_2070 2070 // "Ports (COM & LPT)" -#define IDS_2071 2071 // "Storage controllers" -#define IDS_2072 2072 // "Hard disks" -#define IDS_2073 2073 // "Floppy and CD-ROM drives" -#define IDS_2074 2074 // "Other removable devices" -#define IDS_2075 2075 // "Other peripherals" -#define IDS_2076 2076 // "Surface-based images (*.8.." -#define IDS_2077 2077 // "Click to capture mouse" -#define IDS_2078 2078 // "Press F12-F8 to release mouse" -#define IDS_2079 2079 // "Press F12-F8 or middle button.." -#define IDS_2080 2080 // "Unable to initialize Flui.." -#define IDS_2081 2081 // "Bus" -#define IDS_2082 2082 // "File" -#define IDS_2083 2083 // "C" -#define IDS_2084 2084 // "H" -#define IDS_2085 2085 // "S" -#define IDS_2086 2086 // "MB" -#define IDS_2087 2087 // "Check BPB" -#define IDS_2088 2088 // "KB" -#define IDS_2089 2089 // "Could not initialize the video..." -#define IDS_2090 2090 // "Default" -#define IDS_2091 2091 // "%i Wait state(s)" -#define IDS_2092 2092 // "Type" -#define IDS_2093 2093 // "PCap failed to set up.." -#define IDS_2094 2094 // "No PCap devices found" -#define IDS_2095 2095 // "Invalid PCap device" -#define IDS_2096 2096 // "Standard 2-button joystick(s)" -#define IDS_2097 2097 // "Standard 4-button joystick" -#define IDS_2098 2098 // "Standard 6-button joystick" -#define IDS_2099 2099 // "Standard 8-button joystick" -#define IDS_2100 2100 // "CH Flightstick Pro" -#define IDS_2101 2101 // "Microsoft SideWinder Pad" -#define IDS_2102 2102 // "Thrustmaster Flight Cont.." -#define IDS_2103 2103 // "None" -#define IDS_2104 2104 // "Unable to load keyboard..." -#define IDS_2105 2105 // "Unable to register raw input." -#define IDS_2106 2106 // "%u" -#define IDS_2107 2107 // "%u MB (CHS: %i, %i, %i)" -#define IDS_2108 2108 // "Floppy %i (%s): %ls" -#define IDS_2109 2109 // "All floppy images (*.0??;*.." -#define IDS_2110 2110 // "Unable to initialize Free.." -#define IDS_2111 2111 // "Unable to initialize SDL..." -#define IDS_2112 2112 // "Are you sure you want to..." -#define IDS_2113 2113 // "Are you sure you want to..." -#define IDS_2114 2114 // "Unable to initialize Ghostscript..." -#define IDS_2115 2115 // "MO %i (%03i): %ls" -#define IDS_2116 2116 // "MO images (*.IM?)\0*.IM..." -#define IDS_2117 2117 // "Welcome to 86Box!" -#define IDS_2118 2118 // "Internal controller" -#define IDS_2119 2119 // "Exit" -#define IDS_2120 2120 // "No ROMs found" -#define IDS_2121 2121 // "Do you want to save the settings?" -#define IDS_2122 2122 // "This will hard reset the emulated..." -#define IDS_2123 2123 // "Save" -#define IDS_2124 2124 // "About 86Box" -#define IDS_2125 2125 // "86Box v" EMU_VERSION -#define IDS_2126 2126 // "An emulator of old computers..." -#define IDS_2127 2127 // "OK" -#define IDS_2128 2128 // "Hardware not available" -#define IDS_2129 2129 // "Make sure " LIB_NAME_PCAP "..." -#define IDS_2130 2130 // "Invalid configuration" -#define IDS_2131 2131 // LIB_NAME_FREETYPE " is required..." -#define IDS_2132 2132 // LIB_NAME_GS " is required for... -#define IDS_2133 2133 // LIB_NAME_FLUIDSYNTH " is required..." -#define IDS_2134 2134 // "Entering fullscreen mode" -#define IDS_2135 2135 // "Don't show this message again" -#define IDS_2136 2136 // "Don't exit" -#define IDS_2137 2137 // "Reset" -#define IDS_2138 2138 // "Don't reset" -#define IDS_2139 2139 // "MO images (*.IM?)\0*.IM?..." -#define IDS_2140 2140 // "CD-ROM images (*.ISO;*.CU.." -#define IDS_2141 2141 // "%hs Device Configuration" -#define IDS_2142 2142 // "Monitor in sleep mode" -#define IDS_2143 2143 // "OpenGL Shaders (*.GLSL)..." -#define IDS_2144 2144 // "OpenGL options" -#define IDS_2145 2145 // "You are loading an unsupported..." -#define IDS_2146 2146 // "CPU type filtering based on..." -#define IDS_2147 2147 // "Continue" -#define IDS_2148 2148 // "Cassette: %s" -#define IDS_2149 2149 // "Cassette images (*.PCM;*.RAW;*..." -#define IDS_2150 2150 // "Cartridge %i: %ls" -#define IDS_2151 2151 // "Cartridge images (*.JRC)\0*.JRC\0..." -#define IDS_2152 2152 // "Error initializing renderer" -#define IDS_2153 2153 // "OpenGL (3.0 Core) renderer could not be initialized. Use another renderer." -#define IDS_2154 2154 // "Resume execution" -#define IDS_2155 2155 // "Pause execution" -#define IDS_2156 2156 // "Press Ctrl+Alt+Del" -#define IDS_2157 2157 // "Press Ctrl+Alt+Esc" -#define IDS_2158 2158 // "Hard reset" -#define IDS_2159 2159 // "ACPI shutdown" -#define IDS_2160 2160 // "Settings" +#define IDS_STRINGS 2048 // "86Box" +#define IDS_2049 2049 // "Error" +#define IDS_2050 2050 // "Fatal error" +#define IDS_2051 2051 // " - PAUSED" +#define IDS_2052 2052 // "Press Ctrl+Alt+PgDn..." +#define IDS_2053 2053 // "Speed" +#define IDS_2054 2054 // "ZIP %i (%03i): %ls" +#define IDS_2055 2055 // "ZIP images (*.IM?)\0*.IM..." +#define IDS_2056 2056 // "No usable ROM images found!" +#define IDS_2057 2057 // "(empty)" +#define IDS_2058 2058 // "ZIP images (*.IM?)\0*.IM..." +#define IDS_2059 2059 // "(Turbo)" +#define IDS_2060 2060 // "On" +#define IDS_2061 2061 // "Off" +#define IDS_2062 2062 // "All floppy images (*.DSK..." +#define IDS_2063 2063 // "Machine ""%hs"" is not..." +#define IDS_2064 2064 // "Video card ""%hs"" is not..." +#define IDS_2065 2065 // "Machine" +#define IDS_2066 2066 // "Display" +#define IDS_2067 2067 // "Input devices" +#define IDS_2068 2068 // "Sound" +#define IDS_2069 2069 // "Network" +#define IDS_2070 2070 // "Ports (COM & LPT)" +#define IDS_2071 2071 // "Storage controllers" +#define IDS_2072 2072 // "Hard disks" +#define IDS_2073 2073 // "Floppy and CD-ROM drives" +#define IDS_2074 2074 // "Other removable devices" +#define IDS_2075 2075 // "Other peripherals" +#define IDS_2076 2076 // "Surface-based images (*.8.." +#define IDS_2077 2077 // "Click to capture mouse" +#define IDS_2078 2078 // "Press F12-F8 to release mouse" +#define IDS_2079 2079 // "Press F12-F8 or middle button.." +#define IDS_2081 2081 // "Bus" +#define IDS_BUS IDS_2081 // "Bus" +#define IDS_2082 2082 // "File" +#define IDS_2083 2083 // "C" +#define IDS_2084 2084 // "H" +#define IDS_2085 2085 // "S" +#define IDS_2086 2086 // "MB" +#define IDS_MB IDS_2086 // "MB" +#define IDS_2087 2087 // "Speed" -#define IDS_4096 4096 // "Hard disk (%s)" -#define IDS_4097 4097 // "%01i:%01i" -#define IDS_4098 4098 // "%i" -#define IDS_4099 4099 // "MFM/RLL or ESDI CD-ROM driv.." -#define IDS_4100 4100 // "Custom..." -#define IDS_4101 4101 // "Custom (large)..." -#define IDS_4102 4102 // "Add New Hard Disk" -#define IDS_4103 4103 // "Add Existing Hard Disk" -#define IDS_4104 4104 // "HDI disk images cannot be..." -#define IDS_4105 4105 // "Disk images cannot be larger..." -#define IDS_4106 4106 // "Hard disk images (*.HDI;*.HD.." -#define IDS_4107 4107 // "Unable to open the file for read" -#define IDS_4108 4108 // "Unable to open the file for write" -#define IDS_4109 4109 // "HDI or HDX image with a sect.." -#define IDS_4110 4110 // "USB is not yet supported" -#define IDS_4111 4111 // "Disk image file already exists" -#define IDS_4112 4112 // "Please specify a valid file name." -#define IDS_4113 4113 // "Remember to partition and fo.." -#define IDS_4114 4114 // "Make sure the file exists and..." -#define IDS_4115 4115 // "Make sure the file is being..." -#define IDS_4116 4116 // "Disk image too large" -#define IDS_4117 4117 // "Remember to partition and format..." -#define IDS_4118 4118 // "The selected file will be..." -#define IDS_4119 4119 // "Unsupported disk image" -#define IDS_4120 4120 // "Overwrite" -#define IDS_4121 4121 // "Don't overwrite" -#define IDS_4122 4122 // "Raw image (.img)" -#define IDS_4123 4123 // "HDI image (.hdi)" -#define IDS_4124 4124 // "HDX image (.hdx)" -#define IDS_4125 4125 // "Fixed-size VHD (.vhd)" -#define IDS_4126 4126 // "Dynamic-size VHD (.vhd)" -#define IDS_4127 4127 // "Differencing VHD (.vhd)" -#define IDS_4128 4128 // "Large blocks (2 MB)" -#define IDS_4129 4129 // "Small blocks (512 KB)" -#define IDS_4130 4130 // "VHD files (*.VHD)\0*.VHD\0All..." -#define IDS_4131 4131 // "Select the parent VHD" -#define IDS_4132 4132 // "This could mean that the parent..." -#define IDS_4133 4133 // "Parent and child disk timestamps..." -#define IDS_4134 4134 // "Could not fix VHD timestamp." -#define IDS_4135 4135 // "%01i:%02i" +#define IDS_2088 2088 // "Check BPB" +#define IDS_BPB IDS_2088 // "Check BPB" -#define IDS_4352 4352 // "MFM/RLL" -#define IDS_4353 4353 // "XT IDE" -#define IDS_4354 4354 // "ESDI" -#define IDS_4355 4355 // "IDE" -#define IDS_4356 4356 // "ATAPI" -#define IDS_4357 4357 // "SCSI" +#define IDS_2089 2089 // "KB" +#define IDS_KB IDS_2089 // "KB" -#define IDS_4608 4608 // "MFM/RLL (%01i:%01i)" -#define IDS_4609 4609 // "XT IDE (%01i:%01i)" -#define IDS_4610 4610 // "ESDI (%01i:%01i)" -#define IDS_4611 4611 // "IDE (%01i:%01i)" -#define IDS_4612 4612 // "ATAPI (%01i:%01i)" -#define IDS_4613 4613 // "SCSI (%02i:%02i)" +#define IDS_2090 2090 // "Could not initialize the video..." -#define IDS_5120 5120 // "CD-ROM %i (%s): %s" +#define IDS_2091 2091 // "Default" +#define IDS_DEFAULT IDS_2091 // "Default" -#define IDS_5376 5376 // "Disabled" -#define IDS_5377 5377 // -#define IDS_5378 5378 // -#define IDS_5379 5379 // -#define IDS_5380 5380 // -#define IDS_5381 5381 // "ATAPI" -#define IDS_5382 5382 // "SCSI" +#define IDS_2092 2092 // "%i Wait state(s)" +#define IDS_WS IDS_2092 // "%i Wait state(s)" -#define IDS_5632 5632 // "Disabled" -#define IDS_5633 5633 // -#define IDS_5634 5634 // -#define IDS_5635 5635 // -#define IDS_5636 5636 // -#define IDS_5637 5637 // "ATAPI (%01i:%01i)" -#define IDS_5638 5638 // "SCSI (%02i:%02i)" +#define IDS_2093 2093 // "Type" +#define IDS_TYPE IDS_2093 // "Type" -#define IDS_5888 5888 // "160 kB" -#define IDS_5889 5889 // "180 kB" -#define IDS_5890 5890 // "320 kB" -#define IDS_5891 5891 // "360 kB" -#define IDS_5892 5892 // "640 kB" -#define IDS_5893 5893 // "720 kB" -#define IDS_5894 5894 // "1.2 MB" -#define IDS_5895 5895 // "1.25 MB" -#define IDS_5896 5896 // "1.44 MB" -#define IDS_5897 5897 // "DMF (cluster 1024)" -#define IDS_5898 5898 // "DMF (cluster 2048)" -#define IDS_5899 5899 // "2.88 MB" -#define IDS_5900 5900 // "ZIP 100" -#define IDS_5901 5901 // "ZIP 250" -#define IDS_5902 5902 // "3.5\" 128 MB (ISO 10090)" -#define IDS_5903 5903 // "3.5\" 230 MB (ISO 13963)" -#define IDS_5904 5904 // "3.5\" 540 MB (ISO 15498)" -#define IDS_5905 5905 // "3.5\" 640 MB (ISO 15498)" -#define IDS_5906 5906 // "3.5\" 1.3 GB (GigaMO)" -#define IDS_5907 5907 // "3.5\" 2.3 GB (GigaMO 2)" -#define IDS_5908 5908 // "5.25\" 600 MB" -#define IDS_5909 5909 // "5.25\" 650 MB" -#define IDS_5910 5910 // "5.25\" 1 GB" -#define IDS_5911 5911 // "5.25\" 1.3 GB" +/* TODO */ +#define IDS_2094 2094 // "PCap failed to set up.." +#define IDS_2095 2095 // "No PCap devices found" +#define IDS_2096 2096 // "Invalid PCap device" +#define IDS_2097 2097 // "Standard 2-button joystick(s)" +#define IDS_2098 2098 // "Standard 4-button joystick" +#define IDS_2099 2099 // "Standard 6-button joystick" +#define IDS_2100 2100 // "Standard 8-button joystick" +#define IDS_2101 2101 // "CH Flightstick Pro" +#define IDS_2102 2102 // "Microsoft SideWinder Pad" +#define IDS_2103 2103 // "Thrustmaster Flight Cont.." +#define IDS_2104 2104 // "None" +#define IDS_2105 2105 // "Unable to load keyboard..." +#define IDS_2106 2106 // "Unable to register raw input." +#define IDS_2107 2107 // "%u" +#define IDS_2108 2108 // "%u MB (CHS: %i, %i, %i)" +#define IDS_2109 2109 // "Floppy %i (%s): %ls" +#define IDS_2110 2110 // "All floppy images (*.0??;*.." +#define IDS_2112 2112 // "Unable to initialize SDL..." +#define IDS_2113 2113 // "Are you sure you want to..." +#define IDS_2114 2114 // "Are you sure you want to..." +#define IDS_2115 2115 // "Unable to initialize Ghostscript..." +#define IDS_2116 2116 // "MO %i (%03i): %ls" +#define IDS_2117 2117 // "MO images (*.IM?)\0*.IM..." +#define IDS_2118 2118 // "Welcome to 86Box!" +#define IDS_2119 2119 // "Internal controller" +#define IDS_2120 2120 // "Exit" +#define IDS_2121 2121 // "No ROMs found" +#define IDS_2122 2122 // "Do you want to save the settings?" +#define IDS_2123 2123 // "This will hard reset the emulated..." +#define IDS_2124 2124 // "Save" +#define IDS_2125 2125 // "About 86Box" +#define IDS_2126 2126 // "86Box v" EMU_VERSION +#define IDS_2127 2127 // "An emulator of old computers..." +#define IDS_2128 2128 // "OK" +#define IDS_2129 2129 // "Hardware not available" +#define IDS_2130 2130 // "Make sure " LIB_NAME_PCAP "..." +#define IDS_2131 2131 // "Invalid configuration" +#define IDS_2133 2133 // LIB_NAME_GS " is required for... +#define IDS_2135 2135 // "Entering fullscreen mode" +#define IDS_2136 2136 // "Don't show this message again" +#define IDS_2137 2137 // "Don't exit" +#define IDS_2138 2138 // "Reset" +#define IDS_2139 2139 // "Don't reset" +#define IDS_2140 2140 // "MO images (*.IM?)\0*.IM?..." +#define IDS_2141 2141 // "CD-ROM images (*.ISO;*.CU.." +#define IDS_2142 2142 // "%hs Device Configuration" +#define IDS_2143 2143 // "Monitor in sleep mode" +#define IDS_2144 2144 // "OpenGL Shaders (*.GLSL)..." +#define IDS_2145 2145 // "OpenGL options" +#define IDS_2146 2146 // "You are loading an unsupported..." +#define IDS_2147 2147 // "CPU type filtering based on..." +#define IDS_2148 2148 // "Continue" +#define IDS_2149 2149 // "Cassette: %s" +#define IDS_2150 2150 // "Cassette images (*.PCM;*.RAW;*..." +#define IDS_2151 2151 // "Cartridge %i: %ls" +#define IDS_2152 2152 // "Cartridge images (*.JRC)\0*.JRC\0..." +#define IDS_2153 2153 // "Error initializing renderer" +#define IDS_2154 2154 // "OpenGL (3.0 Core) renderer could not be initialized. Use another renderer." +#define IDS_2155 2155 // "Resume execution" +#define IDS_2156 2156 // "Pause execution" +#define IDS_2157 2157 // "Press Ctrl+Alt+Del" +#define IDS_2158 2158 // "Press Ctrl+Alt+Esc" +#define IDS_2159 2159 // "Hard reset" +#define IDS_2160 2160 // "ACPI shutdown" +#define IDS_2161 2161 // "Settings" +#define IDS_2162 2162 // "Early drive" +#define IDS_2163 2163 // "no dynarec" +#define IDS_2164 2164 // "old dynarec" +#define IDS_2165 2165 // "new dynarec" +#ifdef USE_DYNAREC +# ifdef USE_NEW_DYNAREC +# define IDS_DYNAREC IDS_2165 +# else +# define IDS_DYNAREC IDS_2164 +# endif +#else +# define IDS_DYNAREC IDS_2163 +#endif +#define IDS_2166 2166 // "Video card #2 ""%hs"" is not..." +#define IDS_2167 2167 // "Network driver initialization failed" +#define IDS_2168 2168 // "The network configuration will be switched to the null driver" -#define IDS_6144 6144 // "Perfect RPM" -#define IDS_6145 6145 // "1%% below perfect RPM" -#define IDS_6146 6146 // "1.5%% below perfect RPM" -#define IDS_6147 6147 // "2%% below perfect RPM" +#define IDS_4096 4096 // "Hard disk (%s)" +#define IDS_4097 4097 // "%01i:%01i" +#define IDS_4098 4098 // "%i" +#define IDS_4099 4099 // "MFM/RLL or ESDI CD-ROM driv.." +#define IDS_4100 4100 // "Custom..." +#define IDS_4101 4101 // "Custom (large)..." +#define IDS_4102 4102 // "Add New Hard Disk" +#define IDS_4103 4103 // "Add Existing Hard Disk" +#define IDS_4104 4104 // "HDI disk images cannot be..." +#define IDS_4105 4105 // "Disk images cannot be larger..." +#define IDS_4106 4106 // "Hard disk images (*.HDI;*.HD.." +#define IDS_4107 4107 // "Unable to open the file for read" +#define IDS_4108 4108 // "Unable to open the file for write" +#define IDS_4109 4109 // "HDI or HDX image with a sect.." +#define IDS_4110 4110 // "USB is not yet supported" +#define IDS_4111 4111 // "Disk image file already exists" +#define IDS_4112 4112 // "Please specify a valid file name." +#define IDS_4113 4113 // "Remember to partition and fo.." +#define IDS_4114 4114 // "Make sure the file exists and..." +#define IDS_4115 4115 // "Make sure the file is being..." +#define IDS_4116 4116 // "Disk image too large" +#define IDS_4117 4117 // "Remember to partition and format..." +#define IDS_4118 4118 // "The selected file will be..." +#define IDS_4119 4119 // "Unsupported disk image" +#define IDS_4120 4120 // "Overwrite" +#define IDS_4121 4121 // "Don't overwrite" +#define IDS_4122 4122 // "Raw image (.img)" +#define IDS_4123 4123 // "HDI image (.hdi)" +#define IDS_4124 4124 // "HDX image (.hdx)" +#define IDS_4125 4125 // "Fixed-size VHD (.vhd)" +#define IDS_4126 4126 // "Dynamic-size VHD (.vhd)" +#define IDS_4127 4127 // "Differencing VHD (.vhd)" +#define IDS_4128 4128 // "Large blocks (2 MB)" +#define IDS_4129 4129 // "Small blocks (512 KB)" +#define IDS_4130 4130 // "VHD files (*.VHD)\0*.VHD\0All..." +#define IDS_4131 4131 // "Select the parent VHD" +#define IDS_4132 4132 // "This could mean that the parent..." +#define IDS_4133 4133 // "Parent and child disk timestamps..." +#define IDS_4134 4134 // "Could not fix VHD timestamp." +#define IDS_4135 4135 // "%01i:%02i" -#define IDS_7168 7168 // "(System Default)" +#define IDS_4352 4352 // "MFM/RLL" +#define IDS_4353 4353 // "XT IDE" +#define IDS_4354 4354 // "ESDI" +#define IDS_4355 4355 // "IDE" +#define IDS_4356 4356 // "ATAPI" +#define IDS_4357 4357 // "SCSI" -#define IDS_LANG_ENUS IDS_7168 +#define IDS_4608 4608 // "MFM/RLL (%01i:%01i)" +#define IDS_4609 4609 // "XT IDE (%01i:%01i)" +#define IDS_4610 4610 // "ESDI (%01i:%01i)" +#define IDS_4611 4611 // "IDE (%01i:%01i)" +#define IDS_4612 4612 // "ATAPI (%01i:%01i)" +#define IDS_4613 4613 // "SCSI (%02i:%02i)" -#define STR_NUM_2048 106 -#define STR_NUM_3072 11 -#define STR_NUM_4096 40 -#define STR_NUM_4352 6 -#define STR_NUM_4608 6 -#define STR_NUM_5120 1 -#define STR_NUM_5376 7 -#define STR_NUM_5632 7 -#define STR_NUM_5888 24 -#define STR_NUM_6144 4 -#define STR_NUM_7168 1 +#define IDS_5120 5120 // "CD-ROM %i (%s): %s" +#define IDS_5376 5376 // "Disabled" +#define IDS_5377 5377 // +#define IDS_5378 5378 // +#define IDS_5379 5379 // +#define IDS_5380 5380 // +#define IDS_5381 5381 // "ATAPI" +#define IDS_5382 5382 // "SCSI" -#endif /*LANG_UAGE_H*/ +#define IDS_5632 5632 // "Disabled" +#define IDS_5633 5633 // +#define IDS_5634 5634 // +#define IDS_5635 5635 // +#define IDS_5636 5636 // +#define IDS_5637 5637 // "ATAPI (%01i:%01i)" +#define IDS_5638 5638 // "SCSI (%02i:%02i)" + +#define IDS_5888 5888 // "160 kB" +#define IDS_5889 5889 // "180 kB" +#define IDS_5890 5890 // "320 kB" +#define IDS_5891 5891 // "360 kB" +#define IDS_5892 5892 // "640 kB" +#define IDS_5893 5893 // "720 kB" +#define IDS_5894 5894 // "1.2 MB" +#define IDS_5895 5895 // "1.25 MB" +#define IDS_5896 5896 // "1.44 MB" +#define IDS_5897 5897 // "DMF (cluster 1024)" +#define IDS_5898 5898 // "DMF (cluster 2048)" +#define IDS_5899 5899 // "2.88 MB" +#define IDS_5900 5900 // "ZIP 100" +#define IDS_5901 5901 // "ZIP 250" +#define IDS_5902 5902 // "3.5\" 128 MB (ISO 10090)" +#define IDS_5903 5903 // "3.5\" 230 MB (ISO 13963)" +#define IDS_5904 5904 // "3.5\" 540 MB (ISO 15498)" +#define IDS_5905 5905 // "3.5\" 640 MB (ISO 15498)" +#define IDS_5906 5906 // "3.5\" 1.3 GB (GigaMO)" +#define IDS_5907 5907 // "3.5\" 2.3 GB (GigaMO 2)" +#define IDS_5908 5908 // "5.25\" 600 MB" +#define IDS_5909 5909 // "5.25\" 650 MB" +#define IDS_5910 5910 // "5.25\" 1 GB" +#define IDS_5911 5911 // "5.25\" 1.3 GB" + +#define IDS_6144 6144 // "Perfect RPM" +#define IDS_6145 6145 // "1%% below perfect RPM" +#define IDS_6146 6146 // "1.5%% below perfect RPM" +#define IDS_6147 6147 // "2%% below perfect RPM" + +#define IDS_7168 7168 // "(System Default)" + +#define IDS_LANG_ENUS IDS_7168 + +#define STR_NUM_2048 121 +// UNUSED: #define STR_NUM_3072 11 +#define STR_NUM_4096 40 +#define STR_NUM_4352 6 +#define STR_NUM_4608 6 +#define STR_NUM_5120 1 +#define STR_NUM_5376 7 +#define STR_NUM_5632 7 +#define STR_NUM_5888 24 +#define STR_NUM_6144 4 +#define STR_NUM_7168 1 + +#endif /*LANG_UAGE_H*/ diff --git a/src/include/86box/log.h b/src/include/86box/log.h index 210f2c5a7..9d3568069 100644 --- a/src/include/86box/log.h +++ b/src/include/86box/log.h @@ -1,46 +1,47 @@ /* - * 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. + * 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. + * This file is part of the 86Box distribution. * - * Main include file for the application. + * Main include file for the application. * * * - * Authors: Miran Grca, - * Fred N. van Kempen, + * Authors: Miran Grca, + * Fred N. van Kempen, * - * Copyright 2021 Miran Grca. - * Copyright 2021 Fred N. van Kempen. + * Copyright 2021 Miran Grca. + * Copyright 2021 Fred N. van Kempen. */ + #ifndef EMU_LOG_H -# define EMU_LOG_H +#define EMU_LOG_H #ifndef RELEASE_BUILD -#ifdef __cplusplus +# ifdef __cplusplus extern "C" { -#endif +# endif /* Function prototypes. */ -extern void log_set_suppr_seen(void *priv, int suppr_seen); -extern void log_set_dev_name(void *priv, char *dev_name); -#ifdef HAVE_STDARG_H -extern void log_out(void *priv, const char *fmt, va_list); -extern void log_fatal(void *priv, const char *fmt, ...); -#endif -extern void * log_open(char *dev_name); -extern void log_close(void *priv); +extern void log_set_suppr_seen(void *priv, int suppr_seen); +extern void log_set_dev_name(void *priv, char *dev_name); +# ifdef HAVE_STDARG_H +extern void log_out(void *priv, const char *fmt, va_list); +extern void log_fatal(void *priv, const char *fmt, ...); +# endif +extern void *log_open(char *dev_name); +extern void log_close(void *priv); -#ifdef __cplusplus +# ifdef __cplusplus } -#endif +# endif #else -#define log_fatal(priv, fmt, ...) fatal(fmt, ...) -#endif /*RELEASE_BUILD*/ +# define log_fatal(priv, fmt, ...) fatal(fmt, ...) +#endif /*RELEASE_BUILD*/ -#endif /*EMU_LOG_H*/ +#endif /*EMU_LOG_H*/ diff --git a/src/include/86box/lpt.h b/src/include/86box/lpt.h index ae1a63388..a9a9eac65 100644 --- a/src/include/86box/lpt.h +++ b/src/include/86box/lpt.h @@ -1,77 +1,95 @@ #ifndef EMU_LPT_H -# define EMU_LPT_H +#define EMU_LPT_H -typedef struct -{ +#define LPT1_ADDR 0x0378 +#define LPT1_IRQ 7 +#define LPT2_ADDR 0x0278 +#define LPT2_IRQ 5 +// LPT 1 on machines when installed +#define LPT_MDA_ADDR 0x03bc +#define LPT_MDA_IRQ 7 +#define LPT4_ADDR 0x0268 +#define LPT4_IRQ 5 +#if 0 +#define LPT5_ADDR 0x027c +#define LPT5_IRQ 7 +#define LPT6_ADDR 0x026c +#define LPT6_IRQ 5 +#endif + +typedef struct lpt_device_t { const char *name; + const char *internal_name; - void * (*init)(void *lpt); - void (*close)(void *p); - void (*write_data)(uint8_t val, void *p); - void (*write_ctrl)(uint8_t val, void *p); - uint8_t (*read_data)(void *p); - uint8_t (*read_status)(void *p); - uint8_t (*read_ctrl)(void *p); + void *(*init)(void *lpt); + void (*close)(void *priv); + void (*write_data)(uint8_t val, void *priv); + void (*write_ctrl)(uint8_t val, void *priv); + uint8_t (*read_data)(void *priv); + uint8_t (*read_status)(void *priv); + uint8_t (*read_ctrl)(void *priv); } lpt_device_t; - extern void lpt_init(void); extern void lpt_port_init(int i, uint16_t port); extern void lpt_port_irq(int i, uint8_t irq); extern void lpt_port_remove(int i); extern void lpt1_remove_ams(void); -#define lpt1_init(a) lpt_port_init(0, a) -#define lpt1_irq(a) lpt_port_irq(0, a) -#define lpt1_remove() lpt_port_remove(0) +#define lpt1_init(a) lpt_port_init(0, a) +#define lpt1_irq(a) lpt_port_irq(0, a) +#define lpt1_remove() lpt_port_remove(0) -#define lpt2_init(a) lpt_port_init(1, a) -#define lpt2_irq(a) lpt_port_irq(1, a) -#define lpt2_remove() lpt_port_remove(1) +#define lpt2_init(a) lpt_port_init(1, a) +#define lpt2_irq(a) lpt_port_irq(1, a) +#define lpt2_remove() lpt_port_remove(1) -#define lpt3_init(a) lpt_port_init(2, a) -#define lpt3_irq(a) lpt_port_irq(2, a) -#define lpt3_remove() lpt_port_remove(2) +#define lpt3_init(a) lpt_port_init(2, a) +#define lpt3_irq(a) lpt_port_irq(2, a) +#define lpt3_remove() lpt_port_remove(2) -#define lpt4_init(a) lpt_port_init(3, a) -#define lpt4_irq(a) lpt_port_irq(3, a) -#define lpt4_remove() lpt_port_remove(3) +#define lpt4_init(a) lpt_port_init(3, a) +#define lpt4_irq(a) lpt_port_irq(3, a) +#define lpt4_remove() lpt_port_remove(3) -/* -#define lpt5_init(a) lpt_port_init(4, a) -#define lpt5_irq(a) lpt_port_irq(4, a) -#define lpt5_remove() lpt_port_remove(4) - -#define lpt6_init(a) lpt_port_init(5, a) -#define lpt6_irq(a) lpt_port_irq(5, a) -#define lpt6_remove() lpt_port_remove(5) -*/ +#if 0 +#define lpt5_init(a) lpt_port_init(4, a) +#define lpt5_irq(a) lpt_port_irq(4, a) +#define lpt5_remove() lpt_port_remove(4) +#define lpt6_init(a) lpt_port_init(5, a) +#define lpt6_irq(a) lpt_port_irq(5, a) +#define lpt6_remove() lpt_port_remove(5) +#endif void lpt_devices_init(void); void lpt_devices_close(void); - -typedef struct { - uint8_t enabled, irq, - dat, ctrl; - uint16_t addr, pad0; - int device, enable_irq; - lpt_device_t * dt; - void * priv; +typedef struct lpt_port_t { + uint8_t enabled; + uint8_t irq; + uint8_t dat; + uint8_t ctrl; + uint16_t addr; + uint16_t pad0; + int device; + int enable_irq; + lpt_device_t *dt; + void *priv; } lpt_port_t; -extern lpt_port_t lpt_ports[PARALLEL_MAX]; +extern lpt_port_t lpt_ports[PARALLEL_MAX]; -extern void lpt_write(uint16_t port, uint8_t val, void *priv); -extern uint8_t lpt_read(uint16_t port, void *priv); +extern void lpt_write(uint16_t port, uint8_t val, void *priv); +extern uint8_t lpt_read(uint16_t port, void *priv); -extern void lpt_irq(void *priv, int raise); +extern uint8_t lpt_read_status(int port); +extern void lpt_irq(void *priv, int raise); -extern char * lpt_device_get_name(int id); -extern char * lpt_device_get_internal_name(int id); +extern const char *lpt_device_get_name(int id); +extern const char *lpt_device_get_internal_name(int id); -extern int lpt_device_get_from_internal_name(char *s); +extern int lpt_device_get_from_internal_name(char *s); extern const lpt_device_t lpt_dac_device; extern const lpt_device_t lpt_dac_stereo_device; diff --git a/src/include/86box/m_amstrad.h b/src/include/86box/m_amstrad.h index b190ab0a5..ef4e8b9ea 100644 --- a/src/include/86box/m_amstrad.h +++ b/src/include/86box/m_amstrad.h @@ -1,26 +1,31 @@ /* - * 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. + * 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. + * This file is part of the 86Box distribution. * - * Header of the emulation of the Amstrad series of PC's: - * PC1512, PC1640 and PC200, including their keyboard, mouse and - * video devices, as well as the PC2086 and PC3086 systems. + * Header of the emulation of the Amstrad series of PC's: + * PC1512, PC1640 and PC200, including their keyboard, mouse and + * video devices, as well as the PC2086 and PC3086 systems. * * * - * Authors: Sarah Walker, + * Authors: Sarah Walker, * - * Copyright 2008-2019 Sarah Walker. + * Copyright 2008-2019 Sarah Walker. */ -extern int amstrad_latch; -enum -{ +#ifndef MACHINE_AMSTRAD_H +#define MACHINE_AMSTRAD_H + +extern uint32_t amstrad_latch; + +enum { AMSTRAD_NOLATCH, AMSTRAD_SW9, AMSTRAD_SW10 }; + +#endif /*MACHINE_AMSTRAD.H*/ diff --git a/src/include/86box/m_at_t3100e.h b/src/include/86box/m_at_t3100e.h index 216f490e2..b9c2e24df 100644 --- a/src/include/86box/m_at_t3100e.h +++ b/src/include/86box/m_at_t3100e.h @@ -1,22 +1,22 @@ /* - * VARCem Virtual ARchaeological Computer EMulator. - * An emulator of (mostly) x86-based PC systems and devices, - * using the ISA,EISA,VLB,MCA and PCI system buses, roughly - * spanning the era between 1981 and 1995. + * 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 VARCem Project. + * This file is part of the 86Box distribution. * - * Definitions for the Toshiba T3100e system. + * Definitions for the Toshiba T3100e system. * * * - * Authors: Fred N. van Kempen, - * Miran Grca, - * Sarah Walker, + * Authors: Fred N. van Kempen, + * Miran Grca, + * John Elliott, * - * Copyright 2017,2018 Fred N. van Kempen. - * Copyright 2016-2018 Miran Grca. - * Copyright 2008-2018 Sarah Walker. + * Copyright 2017-2018 Fred N. van Kempen. + * Copyright 2016-2018 Miran Grca. + * Copyright 2008-2018 John Elliott. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -36,23 +36,21 @@ * Boston, MA 02111-1307 * USA. */ -#ifndef MACHINE_T3100E_H -# define MACHINE_T3100E_H +#ifndef MACHINE_T3100E_H +#define MACHINE_T3100E_H extern const device_t t3100e_device; +extern void t3100e_notify_set(uint8_t value); +extern void t3100e_display_set(uint8_t value); +extern uint8_t t3100e_display_get(void); +extern uint8_t t3100e_config_get(void); +extern void t3100e_turbo_set(uint8_t value); +extern uint8_t t3100e_mono_get(void); +extern void t3100e_mono_set(uint8_t value); -extern void t3100e_notify_set(uint8_t value); -extern void t3100e_display_set(uint8_t value); -extern uint8_t t3100e_display_get(void); -extern uint8_t t3100e_config_get(void); -extern void t3100e_turbo_set(uint8_t value); -extern uint8_t t3100e_mono_get(void); -extern void t3100e_mono_set(uint8_t value); +extern void t3100e_video_options_set(uint8_t options); +extern void t3100e_display_set(uint8_t internal); -extern void t3100e_video_options_set(uint8_t options); -extern void t3100e_display_set(uint8_t internal); - - -#endif /*MACHINE_T3100E_H*/ +#endif /*MACHINE_T3100E_H*/ diff --git a/src/include/86box/m_xt_t1000.h b/src/include/86box/m_xt_t1000.h index 8945b24e8..90916444c 100644 --- a/src/include/86box/m_xt_t1000.h +++ b/src/include/86box/m_xt_t1000.h @@ -1,22 +1,22 @@ /* - * VARCem Virtual ARchaeological Computer EMulator. - * An emulator of (mostly) x86-based PC systems and devices, - * using the ISA,EISA,VLB,MCA and PCI system buses, roughly - * spanning the era between 1981 and 1995. + * 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 VARCem Project. + * This file is part of the 86Box distribution. * - * Definitions for the Toshiba T1000/T1200 machines. + * Definitions for the Toshiba T1000/T1200 machines. * * * - * Authors: Fred N. van Kempen, - * Miran Grca, - * Sarah Walker, + * Authors: Fred N. van Kempen, + * Miran Grca, + * John Elliott, * - * Copyright 2017,2018 Fred N. van Kempen. - * Copyright 2016-2018 Miran Grca. - * Copyright 2008-2018 Sarah Walker. + * Copyright 2017-2018 Fred N. van Kempen. + * Copyright 2016-2018 Miran Grca. + * Copyright 2008-2018 John Elliott. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -36,25 +36,23 @@ * Boston, MA 02111-1307 * USA. */ -#ifndef MACHINE_T1000_H -# define MACHINE_T1000_H +#ifndef MACHINE_T1000_H +#define MACHINE_T1000_H extern const device_t t1000_video_device; extern const device_t t1200_video_device; - -extern void t1000_video_options_set(uint8_t options); +extern void t1000_video_options_set(uint8_t options); extern void t1000_video_enable(uint8_t enabled); -extern void t1000_display_set(uint8_t internal); +extern void t1000_display_set(uint8_t internal); -extern void t1000_syskey(uint8_t amask, uint8_t omask, uint8_t xmask); +extern void t1000_syskey(uint8_t amask, uint8_t omask, uint8_t xmask); -extern void t1000_nvr_load(void); -extern void t1000_nvr_save(void); +extern void t1000_nvr_load(void); +extern void t1000_nvr_save(void); -extern void t1200_nvr_load(void); -extern void t1200_nvr_save(void); +extern void t1200_nvr_load(void); +extern void t1200_nvr_save(void); - -#endif /*MACHINE_T1000_H*/ +#endif /*MACHINE_T1000_H*/ diff --git a/src/include/86box/m_xt_xi8088.h b/src/include/86box/m_xt_xi8088.h index f263e385d..d9c963047 100644 --- a/src/include/86box/m_xt_xi8088.h +++ b/src/include/86box/m_xt_xi8088.h @@ -1,8 +1,13 @@ +#ifndef MACHINE_XI80888_H +#define MACHINE_XI80888_H + #include <86box/device.h> extern const device_t xi8088_device; -uint8_t xi8088_turbo_get(); -void xi8088_turbo_set(uint8_t value); -void xi8088_bios_128kb_set(int val); -int xi8088_bios_128kb(); +uint8_t xi8088_turbo_get(void); +void xi8088_turbo_set(uint8_t value); +void xi8088_bios_128kb_set(int val); +int xi8088_bios_128kb(void); + +#endif /*MACHINE_XI80888_H*/ diff --git a/src/include/86box/machine.h b/src/include/86box/machine.h index f3fb0928f..61f4d0ee9 100644 --- a/src/include/86box/machine.h +++ b/src/include/86box/machine.h @@ -1,746 +1,883 @@ /* - * 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. + * 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. + * This file is part of the 86Box distribution. * - * Handling of the emulated machines. + * Handling of the emulated machines. * * * - * Authors: Sarah Walker, - * Miran Grca, - * Fred N. van Kempen, + * Authors: Sarah Walker, + * Miran Grca, + * Fred N. van Kempen, * - * Copyright 2008-2020 Sarah Walker. - * Copyright 2016-2020 Miran Grca. - * Copyright 2017-2020 Fred N. van Kempen. + * Copyright 2008-2020 Sarah Walker. + * Copyright 2016-2020 Miran Grca. + * Copyright 2017-2020 Fred N. van Kempen. */ -#ifndef EMU_MACHINE_H -# define EMU_MACHINE_H +#ifndef EMU_MACHINE_H +#define EMU_MACHINE_H /* Machine feature flags. */ -// #define MACHINE_PC 0x00000000 /* PC architecture */ -/* Feature flags for features. */ -#define MACHINE_NONMI 0x00000001 /* sys does not have NMI's */ +#define MACHINE_BUS_NONE 0x00000000 /* sys has no bus */ /* Feature flags for BUS'es. */ -#define MACHINE_BUS_ISA 0x00000004 /* sys has ISA bus */ -#define MACHINE_BUS_ISA16 0x00000008 /* sys has ISA16 bus - PC/AT architecture */ -#define MACHINE_BUS_CBUS 0x00000010 /* sys has C-BUS bus */ -#define MACHINE_BUS_PS2 0x00000020 /* system has PS/2 keyboard and mouse ports */ -#define MACHINE_BUS_EISA 0x00000040 /* sys has EISA bus */ -#define MACHINE_BUS_VLB 0x00000080 /* sys has VL bus */ -#define MACHINE_BUS_MCA 0x00000100 /* sys has MCA bus */ -#define MACHINE_BUS_PCI 0x00000200 /* sys has PCI bus */ -#define MACHINE_BUS_PCMCIA 0x00000400 /* sys has PCMCIA bus */ -#define MACHINE_BUS_AGP 0x00000800 /* sys has AGP bus */ -#define MACHINE_BUS_AC97 0x00080000 /* sys has AC97 bus (ACR/AMR/CNR slot) */ +#define MACHINE_BUS_ISA 0x00000001 /* sys has ISA bus */ +#define MACHINE_BUS_CASSETTE 0x00000002 /* sys has cassette port */ +#define MACHINE_BUS_CARTRIDGE 0x00000004 /* sys has two cartridge bays */ +#define MACHINE_BUS_PCJR 0x00000008 /* sys has PCjr sidecar bus */ +#define MACHINE_BUS_DM_KBC 0x00000010 /* system has keyboard controller that supports + both XT and AT keyboards */ +#define MACHINE_BUS_ISA16 0x00000020 /* sys has ISA16 bus - PC/AT architecture */ +#define MACHINE_BUS_CBUS 0x00000040 /* sys has C-BUS bus */ +#define MACHINE_BUS_PCMCIA 0x00000080 /* sys has PCMCIA bus */ +#define MACHINE_BUS_PS2_LATCH 0x00000100 /* system has PS/2 keyboard controller IRQ latch */ +#define MACHINE_BUS_PS2_PORTS 0x00000200 /* system has PS/2 keyboard and mouse ports */ +#define MACHINE_BUS_PS2 (MACHINE_BUS_PS2_LATCH | MACHINE_BUS_PS2_PORTS) +#define MACHINE_BUS_HIL 0x00000400 /* system has HP HIL keyboard and mouse ports */ +#define MACHINE_BUS_EISA 0x00000800 /* sys has EISA bus */ +#define MACHINE_BUS_AT32 0x00001000 /* sys has Mylex AT/32 local bus */ +#define MACHINE_BUS_OLB 0x00002000 /* sys has OPTi local bus */ +#define MACHINE_BUS_VLB 0x00004000 /* sys has VL bus */ +#define MACHINE_BUS_MCA 0x00008000 /* sys has MCA bus */ +#define MACHINE_BUS_PCI 0x00010000 /* sys has PCI bus */ +#define MACHINE_BUS_CARDBUS 0x00020000 /* sys has CardBus bus */ +#define MACHINE_BUS_USB 0x00040000 /* sys has USB bus */ +#define MACHINE_BUS_AGP 0x00080000 /* sys has AGP bus */ +#define MACHINE_BUS_AC97 0x00100000 /* sys has AC97 bus (ACR/AMR/CNR slot) */ +/* Aliases. */ +#define MACHINE_CASSETTE (MACHINE_BUS_CASSETTE) /* sys has cassette port */ +#define MACHINE_CARTRIDGE (MACHINE_BUS_CARTRIDGE) /* sys has two cartridge bays */ /* Combined flags. */ -#define MACHINE_PC 0x00000004 /* sys is PC/XT-compatible (ISA) */ -#define MACHINE_AT 0x0000000C /* sys is AT-compatible (ISA + ISA16) */ -#define MACHINE_PC98 0x00000010 /* sys is NEC PC-98x1 series */ -#define MACHINE_EISA 0x0000004C /* sys is AT-compatible with EISA */ -#define MACHINE_VLB 0x0000008C /* sys is AT-compatible with VLB */ -#define MACHINE_VLB98 0x00000090 /* sys is NEC PC-98x1 series with VLB (did that even exist?) */ -#define MACHINE_VLBE 0x000000CC /* sys is AT-compatible with EISA and VLB */ -#define MACHINE_MCA 0x00000100 /* sys is MCA */ -#define MACHINE_PCI 0x0000020C /* sys is AT-compatible with PCI */ -#define MACHINE_PCI98 0x00000210 /* sys is NEC PC-98x1 series with PCI */ -#define MACHINE_PCIE 0x0000024C /* sys is AT-compatible with PCI, and EISA */ -#define MACHINE_PCIV 0x0000028C /* sys is AT-compatible with PCI and VLB */ -#define MACHINE_PCIVE 0x000002CC /* sys is AT-compatible with PCI, VLB, and EISA */ -#define MACHINE_PCMCIA 0x00000400 /* sys is AT-compatible laptop with PCMCIA */ -#define MACHINE_AGP 0x00000A0C /* sys is AT-compatible with AGP */ -#define MACHINE_AGP98 0x00000A10 /* sys is NEC PC-98x1 series with AGP (did that even exist?) */ +#define MACHINE_PC (MACHINE_BUS_ISA) /* sys is PC/XT-compatible (ISA) */ +#define MACHINE_AT (MACHINE_BUS_ISA | MACHINE_BUS_ISA16) /* sys is AT-compatible (ISA + ISA16) */ +#define MACHINE_PC98 (MACHINE_BUS_CBUS) /* sys is NEC PC-98x1 series */ +#define MACHINE_EISA (MACHINE_BUS_EISA | MACHINE_AT) /* sys is AT-compatible with EISA */ +#define MACHINE_VLB (MACHINE_BUS_VLB | MACHINE_AT) /* sys is AT-compatible with VLB */ +#define MACHINE_VLB98 (MACHINE_BUS_VLB | MACHINE_PC98) /* sys is NEC PC-98x1 series with VLB (did that even exist?) */ +#define MACHINE_VLBE (MACHINE_BUS_VLB | MACHINE_EISA) /* sys is AT-compatible with EISA and VLB */ +#define MACHINE_MCA (MACHINE_BUS_MCA) /* sys is MCA */ +#define MACHINE_PCI (MACHINE_BUS_PCI | MACHINE_AT) /* sys is AT-compatible with PCI */ +#define MACHINE_PCI98 (MACHINE_BUS_PCI | MACHINE_PC98) /* sys is NEC PC-98x1 series with PCI */ +#define MACHINE_PCIE (MACHINE_BUS_PCI | MACHINE_EISA) /* sys is AT-compatible with PCI, and EISA */ +#define MACHINE_PCIV (MACHINE_BUS_PCI | MACHINE_VLB) /* sys is AT-compatible with PCI and VLB */ +#define MACHINE_PCIVE (MACHINE_BUS_PCI | MACHINE_VLBE) /* sys is AT-compatible with PCI, VLB, and EISA */ +#define MACHINE_PCMCIA (MACHINE_BUS_PCMCIA | MACHINE_AT) /* sys is AT-compatible laptop with PCMCIA */ +#define MACHINE_AGP (MACHINE_BUS_AGP | MACHINE_PCI) /* sys is AT-compatible with AGP */ +#define MACHINE_AGP98 (MACHINE_BUS_AGP | MACHINE_PCI98) /* sys is NEC PC-98x1 series with AGP (did that even exist?) */ + +#define MACHINE_PC5150 (MACHINE_PC | MACHINE_CASSETTE) /* sys is IBM PC 5150 */ +#define MACHINE_PCJR (MACHINE_PC | MACHINE_CASSETTE | MACHINE_CARTRIDGE) /* sys is PCjr */ +#define MACHINE_PS2 (MACHINE_AT | MACHINE_BUS_PS2) /* sys is PS/2 */ +#define MACHINE_PS2_MCA (MACHINE_MCA | MACHINE_BUS_PS2) /* sys is MCA PS/2 */ +#define MACHINE_PS2_VLB (MACHINE_VLB | MACHINE_BUS_PS2) /* sys is VLB PS/2 */ +#define MACHINE_PS2_PCI (MACHINE_PCI | MACHINE_BUS_PS2) /* sys is PCI PS/2 */ +#define MACHINE_PS2_PCIV (MACHINE_PCIV | MACHINE_BUS_PS2) /* sys is VLB/PCI PS/2 */ +#define MACHINE_PS2_AGP (MACHINE_AGP | MACHINE_BUS_PS2) /* sys is AGP PS/2 */ +#define MACHINE_PS2_A97 (MACHINE_PS2_AGP | MACHINE_BUS_AC97) /* sys is AGP/AC97 PS/2 */ +#define MACHINE_PS2_NOISA (MACHINE_PS2_AGP & ~MACHINE_AT) /* sys is AGP PS/2 without ISA */ +#define MACHINE_PS2_NOI97 (MACHINE_PS2_A97 & ~MACHINE_AT) /* sys is AGP/AC97 PS/2 without ISA */ /* Feature flags for miscellaneous internal devices. */ -#define MACHINE_VIDEO 0x00001000 /* sys has int video */ -#define MACHINE_VIDEO_ONLY 0x00002000 /* sys has fixed video */ -#define MACHINE_MOUSE 0x00004000 /* sys has int mouse */ -#define MACHINE_SOUND 0x00008000 /* sys has int sound */ -#define MACHINE_FDC 0x00010000 /* sys has int FDC */ -#define MACHINE_NIC 0x00020000 /* sys has int NIC */ -#define MACHINE_GAMEPORT 0x00040000 /* sys has int game port */ -/* Combined flags. */ -#define MACHINE_VIDEO_FIXED 0x00003000 /* sys has fixed int video */ +#define MACHINE_FLAGS_NONE 0x00000000 /* sys has no int devices */ +#define MACHINE_SOFTFLOAT_ONLY 0x00000001 /* sys requires SoftFloat FPU */ +#define MACHINE_VIDEO 0x00000002 /* sys has int video */ +#define MACHINE_VIDEO_8514A 0x00000004 /* sys has int video */ +#define MACHINE_VIDEO_XGA 0x00000008 /* sys has int video */ +#define MACHINE_VIDEO_ONLY 0x00000010 /* sys has fixed video */ +#define MACHINE_MOUSE 0x00000020 /* sys has int mouse */ +#define MACHINE_FDC 0x00000040 /* sys has int FDC */ +#define MACHINE_LPT_PRI 0x00000080 /* sys has int pri LPT */ +#define MACHINE_LPT_SEC 0x00000100 /* sys has int sec LPT */ +#define MACHINE_LPT_TER 0x00000200 /* sys has int ter LPT */ +#define MACHINE_LPT_QUA 0x00000400 /* sys has int qua LPT */ +#define MACHINE_UART_PRI 0x00000800 /* sys has int pri UART */ +#define MACHINE_UART_SEC 0x00001000 /* sys has int sec UART */ +#define MACHINE_UART_TER 0x00002000 /* sys has int ter UART */ +#define MACHINE_UART_QUA 0x00004000 /* sys has int qua UART */ +#define MACHINE_GAMEPORT 0x00008000 /* sys has int game port */ +#define MACHINE_SOUND 0x00010000 /* sys has int sound */ +#define MACHINE_NIC 0x00020000 /* sys has int NIC */ +#define MACHINE_MODEM 0x00040000 /* sys has int modem */ +/* Feature flags for advanced devices. */ +#define MACHINE_APM 0x00080000 /* sys has APM */ +#define MACHINE_ACPI 0x00100000 /* sys has ACPI */ +#define MACHINE_HWM 0x00200000 /* sys has hw monitor */ +#define MACHINE_COREBOOT 0x00400000 /* sys has coreboot BIOS */ /* Feature flags for internal storage controllers. */ -#define MACHINE_HDC 0x07FC0000 /* sys has int HDC */ -#define MACHINE_MFM 0x00100000 /* sys has int MFM/RLL */ -#define MACHINE_XTA 0x00200000 /* sys has int XTA */ -#define MACHINE_ESDI 0x00400000 /* sys has int ESDI */ -#define MACHINE_IDE_PRI 0x00800000 /* sys has int pri IDE/ATAPI */ -#define MACHINE_IDE_SEC 0x01000000 /* sys has int sec IDE/ATAPI */ -#define MACHINE_IDE_TER 0x02000000 /* sys has int ter IDE/ATAPI */ -#define MACHINE_IDE_QUA 0x04000000 /* sys has int qua IDE/ATAPI */ -#define MACHINE_SCSI_PRI 0x08000000 /* sys has int pri SCSI */ -#define MACHINE_SCSI_SEC 0x10000000 /* sys has int sec SCSI */ -#define MACHINE_USB 0x20000000 /* sys has int USB */ +#define MACHINE_MFM 0x00800000 /* sys has int MFM/RLL */ +#define MACHINE_XTA 0x01000000 /* sys has int XTA */ +#define MACHINE_ESDI 0x02000000 /* sys has int ESDI */ +#define MACHINE_IDE_PRI 0x04000000 /* sys has int pri IDE/ATAPI */ +#define MACHINE_IDE_SEC 0x08000000 /* sys has int sec IDE/ATAPI */ +#define MACHINE_IDE_TER 0x10000000 /* sys has int ter IDE/ATAPI */ +#define MACHINE_IDE_QUA 0x20000000 /* sys has int qua IDE/ATAPI */ +#define MACHINE_SCSI 0x40000000 /* sys has int SCSI */ +#define MACHINE_USB 0x80000000 /* sys has int USB */ /* Combined flags. */ -#define MACHINE_IDE 0x00800000 /* sys has int single IDE/ATAPI - mark as pri IDE/ATAPI */ -#define MACHINE_IDE_DUAL 0x01800000 /* sys has int dual IDE/ATAPI - mark as both pri and sec IDE/ATAPI */ -#define MACHINE_IDE_QUAD 0x07800000 /* sys has int quad IDE/ATAPI - mark as dual + both ter and and qua IDE/ATAPI */ -#define MACHINE_SCSI 0x08000000 /* sys has int single SCSI - mark as pri SCSI */ -#define MACHINE_SCSI_DUAL 0x18000000 /* sys has int dual SCSI - mark as both pri and sec SCSI */ -#define MACHINE_CARTRIDGE 0x20000000 /* sys has two cartridge bays */ +#define MACHINE_LPT (MACHINE_LPT-PRI | MACHINE_LPT_SEC | \ + MACHINE_LPT_TER | MACHINE_LPT_QUA) +#define MACHINE_UART (MACHINE_UART_PRI | MACHINE_UART_SEC | \ + MACHINE_UART_TER | MACHINE_UART_QUA) +#define MACHINE_VIDEO_FIXED (MACHINE_VIDEO | MACHINE_VIDEO_ONLY) /* sys has fixed int video */ +#define MACHINE_SUPER_IO (MACHINE_FDC | MACHINE_LPT_PRI | MACHINE_UART_PRI | MACHINE_UART_SEC) +#define MACHINE_SUPER_IO_GAME (MACHINE_SUPER_IO | MACHINE_GAMEPORT) +#define MACHINE_SUPER_IO_DUAL (MACHINE_SUPER_IO | MACHINE_LPT_SEC | \ + MACHINE_UART_TER | MACHINE_UART_QUA) +#define MACHINE_AV (MACHINE_VIDEO | MACHINE_SOUND) /* sys has video and sound */ +#define MACHINE_AG (MACHINE_SOUND | MACHINE_GAMEPORT) /* sys has sound and game port */ +/* Combined flag for internal storage controllerss. */ +#define MACHINE_IDE (MACHINE_IDE_PRI) /* sys has int single IDE/ATAPI - mark as pri IDE/ATAPI */ +#define MACHINE_IDE_DUAL (MACHINE_IDE_PRI | MACHINE_IDE_SEC) /* sys has int dual IDE/ATAPI - mark as both pri and sec IDE/ATAPI */ +#define MACHINE_IDE_DUALTQ (MACHINE_IDE_TER | MACHINE_IDE_QUA) +#define MACHINE_IDE_QUAD (MACHINE_IDE_DUAL | MACHINE_IDE_DUALTQ) /* sys has int quad IDE/ATAPI - mark as dual + both ter and and qua IDE/ATAPI */ +#define MACHINE_HDC (MACHINE_MFM | MACHINE_XTA | \ + MACHINE_ESDI | MACHINE_IDE_QUAD | \ + MACHINE_SCSI | MACHINE_USB) +/* Special combined flags. */ +#define MACHINE_PIIX (MACHINE_IDE_DUAL) +#define MACHINE_PIIX3 (MACHINE_PIIX | MACHINE_USB) +#define MACHINE_PIIX4 (MACHINE_PIIX3 | MACHINE_ACPI) -#define IS_ARCH(m, a) ((machines[m].flags & (a)) ? 1 : 0) -#define IS_AT(m) (((machines[m].flags & 0x00000FC8) && !(machines[m].flags & MACHINE_PC98)) ? 1 : 0) +#define IS_ARCH(m, a) ((machines[m].bus_flags & (a)) ? 1 : 0) +#define IS_AT(m) (((machines[m].bus_flags & (MACHINE_BUS_ISA16 | MACHINE_BUS_EISA | MACHINE_BUS_VLB | MACHINE_BUS_MCA | MACHINE_BUS_PCI | MACHINE_BUS_PCMCIA | MACHINE_BUS_AGP | MACHINE_BUS_AC97)) && !(machines[m].bus_flags & MACHINE_PC98)) ? 1 : 0) -#define CPU_BLOCK(...) (const uint8_t[]) {__VA_ARGS__, 0} -#define MACHINE_MULTIPLIER_FIXED -1, -1 +#define CPU_BLOCK(...) \ + (const uint8_t[]) \ + { \ + __VA_ARGS__, 0 \ + } +#define MACHINE_MULTIPLIER_FIXED -1 +#define CPU_BLOCK_NONE 0 + +/* Make sure it's always an invalid value to avoid misdetections. */ +#if (defined __amd64__ || defined _M_X64 || defined __aarch64__ || defined _M_ARM64) +# define MACHINE_AVAILABLE 0xffffffffffffffffULL +#else +# define MACHINE_AVAILABLE 0xffffffff +#endif enum { - MACHINE_TYPE_NONE = 0, - MACHINE_TYPE_8088, - MACHINE_TYPE_8086, - MACHINE_TYPE_286, - MACHINE_TYPE_386SX, - MACHINE_TYPE_486SLC, - MACHINE_TYPE_386DX, - MACHINE_TYPE_386DX_486, - MACHINE_TYPE_486, - MACHINE_TYPE_486_S2, - MACHINE_TYPE_486_S3, - MACHINE_TYPE_486_MISC, - MACHINE_TYPE_SOCKET4, - MACHINE_TYPE_SOCKET5, - MACHINE_TYPE_SOCKET7_3V, - MACHINE_TYPE_SOCKET7, - MACHINE_TYPE_SOCKETS7, - MACHINE_TYPE_SOCKET8, - MACHINE_TYPE_SLOT1, - MACHINE_TYPE_SLOT1_2, - MACHINE_TYPE_SLOT1_370, - MACHINE_TYPE_SLOT2, - MACHINE_TYPE_SOCKET370, - MACHINE_TYPE_MISC, - MACHINE_TYPE_MAX + MACHINE_TYPE_NONE = 0, + MACHINE_TYPE_8088 = 1, + MACHINE_TYPE_8086 = 2, + MACHINE_TYPE_286 = 3, + MACHINE_TYPE_386SX = 4, + MACHINE_TYPE_486SLC = 5, + MACHINE_TYPE_386DX = 6, + MACHINE_TYPE_386DX_486 = 7, + MACHINE_TYPE_486 = 8, + MACHINE_TYPE_486_S2 = 9, + MACHINE_TYPE_486_S3 = 10, + MACHINE_TYPE_486_MISC = 11, + MACHINE_TYPE_SOCKET4 = 12, + MACHINE_TYPE_SOCKET5 = 13, + MACHINE_TYPE_SOCKET7_3V = 14, + MACHINE_TYPE_SOCKET7 = 15, + MACHINE_TYPE_SOCKETS7 = 16, + MACHINE_TYPE_SOCKET8 = 17, + MACHINE_TYPE_SLOT1 = 18, + MACHINE_TYPE_SLOT1_2 = 19, + MACHINE_TYPE_SLOT1_370 = 20, + MACHINE_TYPE_SLOT2 = 21, + MACHINE_TYPE_SOCKET370 = 22, + MACHINE_TYPE_MISC = 23, + MACHINE_TYPE_MAX = 24 }; +enum { + MACHINE_CHIPSET_NONE = 0, + MACHINE_CHIPSET_DISCRETE, + MACHINE_CHIPSET_PROPRIETARY, + MACHINE_CHIPSET_GC100A, + MACHINE_CHIPSET_GC103, + MACHINE_CHIPSET_HT18, + MACHINE_CHIPSET_ACC_2168, + MACHINE_CHIPSET_ALI_M1217, + MACHINE_CHIPSET_ALI_M6117, + MACHINE_CHIPSET_ALI_M1409, + MACHINE_CHIPSET_ALI_M1429, + MACHINE_CHIPSET_ALI_M1429G, + MACHINE_CHIPSET_ALI_M1489, + MACHINE_CHIPSET_ALI_ALADDIN_IV_PLUS, + MACHINE_CHIPSET_ALI_ALADDIN_V, + MACHINE_CHIPSET_ALI_ALADDIN_PRO_II, + MACHINE_CHIPSET_SCAT, + MACHINE_CHIPSET_NEAT, + MACHINE_CHIPSET_CT_386, + MACHINE_CHIPSET_CT_CS4031, + MACHINE_CHIPSET_CONTAQ_82C596, + MACHINE_CHIPSET_CONTAQ_82C597, + MACHINE_CHIPSET_IMS_8848, + MACHINE_CHIPSET_INTEL_82335, + MACHINE_CHIPSET_INTEL_420TX, + MACHINE_CHIPSET_INTEL_420ZX, + MACHINE_CHIPSET_INTEL_420EX, + MACHINE_CHIPSET_INTEL_430LX, + MACHINE_CHIPSET_INTEL_430NX, + MACHINE_CHIPSET_INTEL_430FX, + MACHINE_CHIPSET_INTEL_430HX, + MACHINE_CHIPSET_INTEL_430VX, + MACHINE_CHIPSET_INTEL_430TX, + MACHINE_CHIPSET_INTEL_450KX, + MACHINE_CHIPSET_INTEL_440FX, + MACHINE_CHIPSET_INTEL_440EX, + MACHINE_CHIPSET_INTEL_440LX, + MACHINE_CHIPSET_INTEL_440BX, + MACHINE_CHIPSET_INTEL_440ZX, + MACHINE_CHIPSET_INTEL_440GX, + MACHINE_CHIPSET_OPTI_283, + MACHINE_CHIPSET_OPTI_291, + MACHINE_CHIPSET_OPTI_493, + MACHINE_CHIPSET_OPTI_495, + MACHINE_CHIPSET_OPTI_499, + MACHINE_CHIPSET_OPTI_895_802G, + MACHINE_CHIPSET_OPTI_547_597, + MACHINE_CHIPSET_SARC_RC2016A, + MACHINE_CHIPSET_SIS_310, + MACHINE_CHIPSET_SIS_401, + MACHINE_CHIPSET_SIS_460, + MACHINE_CHIPSET_SIS_461, + MACHINE_CHIPSET_SIS_471, + MACHINE_CHIPSET_SIS_496, + MACHINE_CHIPSET_SIS_501, + MACHINE_CHIPSET_SIS_5511, + MACHINE_CHIPSET_SIS_5571, + MACHINE_CHIPSET_SMSC_VICTORYBX_66, + MACHINE_CHIPSET_STPC_CLIENT, + MACHINE_CHIPSET_STPC_CONSUMER_II, + MACHINE_CHIPSET_STPC_ELITE, + MACHINE_CHIPSET_STPC_ATLAS, + MACHINE_CHIPSET_SYMPHONY_SL82C460, + MACHINE_CHIPSET_UMC_UM82C480, + MACHINE_CHIPSET_UMC_UM82C491, + MACHINE_CHIPSET_UMC_UM8881, + MACHINE_CHIPSET_UMC_UM8890BF, + MACHINE_CHIPSET_VIA_VT82C495, + MACHINE_CHIPSET_VIA_VT82C496G, + MACHINE_CHIPSET_VIA_APOLLO_VPX, + MACHINE_CHIPSET_VIA_APOLLO_VP3, + MACHINE_CHIPSET_VIA_APOLLO_MVP3, + MACHINE_CHIPSET_VIA_APOLLO_PRO, + MACHINE_CHIPSET_VIA_APOLLO_PRO_133, + MACHINE_CHIPSET_VIA_APOLLO_PRO_133A, + MACHINE_CHIPSET_VLSI_SCAMP, + MACHINE_CHIPSET_VLSI_VL82C480, + MACHINE_CHIPSET_VLSI_VL82C481, + MACHINE_CHIPSET_VLSI_VL82C486, + MACHINE_CHIPSET_WD76C10, + MACHINE_CHIPSET_MAX +}; -typedef struct _machine_type_ { - const char *name; +typedef struct _machine_filter_ { + const char *name; const char id; -} machine_type_t; +} machine_filter_t; +typedef struct _machine_cpu_ { + uint32_t package; + const uint8_t *block; + uint32_t min_bus; + uint32_t max_bus; + uint16_t min_voltage; + uint16_t max_voltage; + float min_multi; + float max_multi; +} machine_cpu_t; + +typedef struct _machine_memory_ { + uint32_t min; + uint32_t max; + int step; +} machine_memory_t; -#ifdef NEW_STRUCT typedef struct _machine_ { - const char *name; - const char *internal_name; - const char type; + const char *name; + const char *internal_name; + uint32_t type; + uintptr_t chipset; + int (*init)(const struct _machine_ *); + uint8_t (*p1_handler)(uint8_t write, uint8_t val); + uint32_t (*gpio_handler)(uint8_t write, uint32_t val); + uintptr_t available_flag; + uint32_t (*gpio_acpi_handler)(uint8_t write, uint32_t val); + const machine_cpu_t cpu; + uintptr_t bus_flags; + uintptr_t flags; + const machine_memory_t ram; + int ram_granularity; + int nvrmask; #ifdef EMU_DEVICE_H - const device_t *device; + const device_t *kbc_device; #else - void *device; -#endif - struct { - const char *name; -#ifdef EMU_CPU_H - CPU *cpus; -#else - void *cpus; -#endif - } cpu[5]; - int flags; - uint32_t min_ram, max_ram; - int ram_granularity; - int nvrmask; -} machine_t; -#else -typedef struct _machine_ { - const char *name; - const char *internal_name; - const char type; - uint32_t cpu_package; - const uint8_t *cpu_block; - uint32_t cpu_min_bus; - uint32_t cpu_max_bus; - uint16_t cpu_min_voltage; - uint16_t cpu_max_voltage; - double cpu_min_multi; - double cpu_max_multi; - int flags; - uint32_t min_ram, max_ram; - int ram_granularity; - int nvrmask; - int (*init)(const struct _machine_ *); + void *kbc_device; +#endif /* EMU_DEVICE_H */ + uint8_t kbc_p1; + uint32_t gpio; + uint32_t gpio_acpi; #ifdef EMU_DEVICE_H - const device_t *(*get_device)(void); + const device_t *device; + const device_t *fdc_device; + const device_t *sio_device; + const device_t *vid_device; + const device_t *snd_device; + const device_t *net_device; #else - void *get_device; + void *device; + void *fdc_device; + void *sio_device; + void *vid_device; + void *snd_device; + void *net_device; #endif } machine_t; -#endif - /* Global variables. */ -extern const machine_type_t machine_types[]; -extern const machine_t machines[]; -extern int bios_only; -extern int machine; - +extern const machine_filter_t machine_types[]; +extern const machine_filter_t machine_chipsets[]; +extern const machine_t machines[]; +extern int bios_only; +extern int machine; +extern void * machine_snd; /* Core functions. */ -extern int machine_count(void); -extern int machine_available(int m); -extern char *machine_getname(void); -extern char *machine_getname_ex(int m); -extern char *machine_get_internal_name(void); -extern int machine_get_machine_from_internal_name(char *s); -extern void machine_init(void); +extern int machine_count(void); +extern int machine_available(int m); +extern const char *machine_getname(void); +extern const char *machine_getname_ex(int m); +extern const char *machine_get_internal_name(void); +extern int machine_get_machine_from_internal_name(const char *s); +extern void machine_init(void); #ifdef EMU_DEVICE_H -extern const device_t *machine_getdevice(int m); +extern const device_t *machine_get_kbc_device(int m); +extern const device_t *machine_get_device(int m); +extern const device_t *machine_get_fdc_device(int m); +extern const device_t *machine_get_sio_device(int m); +extern const device_t *machine_get_vid_device(int m); +extern const device_t *machine_get_snd_device(int m); +extern const device_t *machine_get_net_device(int m); #endif -extern char *machine_get_internal_name_ex(int m); -extern int machine_get_nvrmask(int m); -extern int machine_has_flags(int m, int flags); -extern int machine_has_bus(int m, int bus_flags); -extern int machine_has_cartridge(int m); -extern int machine_get_min_ram(int m); -extern int machine_get_max_ram(int m); -extern int machine_get_ram_granularity(int m); -extern int machine_get_type(int m); -extern void machine_close(void); +extern const char *machine_get_internal_name_ex(int m); +extern int machine_get_nvrmask(int m); +extern int machine_has_flags(int m, int flags); +extern int machine_has_bus(int m, int bus_flags); +extern int machine_has_cartridge(int m); +extern int machine_get_min_ram(int m); +extern int machine_get_max_ram(int m); +extern int machine_get_ram_granularity(int m); +extern int machine_get_type(int m); +extern void machine_close(void); +extern int machine_has_mouse(void); +extern int machine_is_sony(void); +extern uint8_t machine_get_p1_default(void); +extern uint8_t machine_get_p1(void); +extern void machine_set_p1_default(uint8_t val); +extern void machine_set_p1(uint8_t val); +extern void machine_and_p1(uint8_t val); +extern void machine_init_p1(void); +extern uint8_t machine_handle_p1(uint8_t write, uint8_t val); +extern uint32_t machine_get_gpio_default(void); +extern uint32_t machine_get_gpio(void); +extern void machine_set_gpio_default(uint32_t val); +extern void machine_set_gpio(uint32_t val); +extern void machine_and_gpio(uint32_t val); +extern void machine_init_gpio(void); +extern uint32_t machine_handle_gpio(uint8_t write, uint32_t val); +extern uint32_t machine_get_gpio_acpi_default(void); +extern uint32_t machine_get_gpio_acpi(void); +extern void machine_set_gpio_acpi_default(uint32_t val); +extern void machine_set_gpio_acpi(uint32_t val); +extern void machine_and_gpio_acpi(uint32_t val); +extern void machine_init_gpio_acpi(void); +extern uint32_t machine_handle_gpio_acpi(uint8_t write, uint32_t val); /* Initialization functions for boards and systems. */ -extern void machine_common_init(const machine_t *); +extern void machine_common_init(const machine_t *); /* m_amstrad.c */ -extern int machine_pc1512_init(const machine_t *); -extern int machine_pc1640_init(const machine_t *); -extern int machine_pc200_init(const machine_t *); -extern int machine_ppc512_init(const machine_t *); -extern int machine_pc2086_init(const machine_t *); -extern int machine_pc3086_init(const machine_t *); - -#ifdef EMU_DEVICE_H -extern const device_t *pc1512_get_device(void); -extern const device_t *pc1640_get_device(void); -extern const device_t *pc200_get_device(void); -extern const device_t *ppc512_get_device(void); -extern const device_t *pc2086_get_device(void); -extern const device_t *pc3086_get_device(void); -#endif +extern int machine_pc1512_init(const machine_t *); +extern int machine_pc1640_init(const machine_t *); +extern int machine_pc200_init(const machine_t *); +extern int machine_ppc512_init(const machine_t *); +extern int machine_pc2086_init(const machine_t *); +extern int machine_pc3086_init(const machine_t *); /* m_at.c */ -extern void machine_at_common_init_ex(const machine_t *, int type); -extern void machine_at_common_init(const machine_t *); -extern void machine_at_init(const machine_t *); -extern void machine_at_ps2_init(const machine_t *); -extern void machine_at_common_ide_init(const machine_t *); -extern void machine_at_ibm_common_ide_init(const machine_t *); -extern void machine_at_ide_init(const machine_t *); -extern void machine_at_ps2_ide_init(const machine_t *); +extern void machine_at_common_init_ex(const machine_t *, int type); +extern void machine_at_common_init(const machine_t *); +extern void machine_at_init(const machine_t *); +extern void machine_at_ps2_init(const machine_t *); +extern void machine_at_common_ide_init(const machine_t *); +extern void machine_at_ibm_common_ide_init(const machine_t *); +extern void machine_at_ide_init(const machine_t *); +extern void machine_at_ps2_ide_init(const machine_t *); -extern int machine_at_ibm_init(const machine_t *); +extern int machine_at_ibm_init(const machine_t *); -//IBM AT with custom BIOS -extern int machine_at_ibmatami_init(const machine_t *); // IBM AT with AMI BIOS -extern int machine_at_ibmatpx_init(const machine_t *); //IBM AT with Phoenix BIOS -extern int machine_at_ibmatquadtel_init(const machine_t *); // IBM AT with Quadtel BIOS +// IBM AT with custom BIOS +extern int machine_at_ibmatami_init(const machine_t *); // IBM AT with AMI BIOS +extern int machine_at_ibmatpx_init(const machine_t *); // IBM AT with Phoenix BIOS +extern int machine_at_ibmatquadtel_init(const machine_t *); // IBM AT with Quadtel BIOS -extern int machine_at_ibmxt286_init(const machine_t *); +extern int machine_at_ibmxt286_init(const machine_t *); -extern int machine_at_siemens_init(const machine_t *); //Siemens PCD-2L. N82330 discrete machine. It segfaults in some places +extern int machine_at_siemens_init(const machine_t *); // Siemens PCD-2L. N82330 discrete machine. It segfaults in some places #if defined(DEV_BRANCH) && defined(USE_OPEN_AT) -extern int machine_at_openat_init(const machine_t *); +extern int machine_at_openat_init(const machine_t *); #endif /* m_at_286_386sx.c */ -extern int machine_at_tg286m_init(const machine_t *); -extern int machine_at_ama932j_init(const machine_t *); -extern int machine_at_px286_init(const machine_t *); -extern int machine_at_quadt286_init(const machine_t *); -extern int machine_at_mr286_init(const machine_t *); +extern int machine_at_tg286m_init(const machine_t *); +extern int machine_at_ama932j_init(const machine_t *); +extern int machine_at_px286_init(const machine_t *); +extern int machine_at_quadt286_init(const machine_t *); +extern int machine_at_mr286_init(const machine_t *); -extern int machine_at_neat_init(const machine_t *); -extern int machine_at_neat_ami_init(const machine_t *); +extern int machine_at_neat_init(const machine_t *); +extern int machine_at_neat_ami_init(const machine_t *); -extern int machine_at_quadt386sx_init(const machine_t *); +extern int machine_at_quadt386sx_init(const machine_t *); -extern int machine_at_award286_init(const machine_t *); -extern int machine_at_gdc212m_init(const machine_t *); -extern int machine_at_gw286ct_init(const machine_t *); -extern int machine_at_super286tr_init(const machine_t *); -extern int machine_at_spc4200p_init(const machine_t *); -extern int machine_at_spc4216p_init(const machine_t *); -extern int machine_at_spc4620p_init(const machine_t *); -extern int machine_at_kmxc02_init(const machine_t *); -extern int machine_at_deskmaster286_init(const machine_t *); +extern int machine_at_award286_init(const machine_t *); +extern int machine_at_gdc212m_init(const machine_t *); +extern int machine_at_gw286ct_init(const machine_t *); +extern int machine_at_super286tr_init(const machine_t *); +extern int machine_at_spc4200p_init(const machine_t *); +extern int machine_at_spc4216p_init(const machine_t *); +extern int machine_at_spc4620p_init(const machine_t *); +extern int machine_at_kmxc02_init(const machine_t *); +extern int machine_at_deskmaster286_init(const machine_t *); -extern int machine_at_pc8_init(const machine_t *); -extern int machine_at_3302_init(const machine_t *); +extern int machine_at_pc8_init(const machine_t *); +extern int machine_at_3302_init(const machine_t *); #if defined(DEV_BRANCH) && defined(USE_OLIVETTI) -extern int machine_at_m290_init(const machine_t *); +extern int machine_at_m290_init(const machine_t *); #endif -extern int machine_at_shuttle386sx_init(const machine_t *); -extern int machine_at_adi386sx_init(const machine_t *); -extern int machine_at_cmdsl386sx16_init(const machine_t *); -extern int machine_at_cmdsl386sx25_init(const machine_t *); -extern int machine_at_dataexpert386sx_init(const machine_t *); -extern int machine_at_spc6033p_init(const machine_t *); -extern int machine_at_wd76c10_init(const machine_t *); -extern int machine_at_arb1374_init(const machine_t *); -extern int machine_at_sbc350a_init(const machine_t *); -extern int machine_at_flytech386_init(const machine_t *); -extern int machine_at_mr1217_init(const machine_t *); -extern int machine_at_pja511m_init(const machine_t *); -extern int machine_at_prox1332_init(const machine_t *); +extern int machine_at_shuttle386sx_init(const machine_t *); +extern int machine_at_adi386sx_init(const machine_t *); +extern int machine_at_cmdsl386sx16_init(const machine_t *); +extern int machine_at_cmdsl386sx25_init(const machine_t *); +extern int machine_at_dataexpert386sx_init(const machine_t *); +extern int machine_at_spc6033p_init(const machine_t *); +extern int machine_at_wd76c10_init(const machine_t *); +extern int machine_at_arb1374_init(const machine_t *); +extern int machine_at_sbc350a_init(const machine_t *); +extern int machine_at_flytech386_init(const machine_t *); +extern int machine_at_mr1217_init(const machine_t *); +extern int machine_at_pja511m_init(const machine_t *); +extern int machine_at_prox1332_init(const machine_t *); -extern int machine_at_awardsx_init(const machine_t *); +extern int machine_at_awardsx_init(const machine_t *); -extern int machine_at_pc916sx_init(const machine_t *); - -#ifdef EMU_DEVICE_H -extern const device_t *at_ama932j_get_device(void); -extern const device_t *at_flytech386_get_device(void); -extern const device_t *at_cmdsl386sx25_get_device(void); -extern const device_t *at_spc4620p_get_device(void); -extern const device_t *at_spc6033p_get_device(void); -#endif +extern int machine_at_pc916sx_init(const machine_t *); /* m_at_386dx_486.c */ -extern int machine_at_acc386_init(const machine_t *); -extern int machine_at_asus386_init(const machine_t *); -extern int machine_at_ecs386_init(const machine_t *); -extern int machine_at_spc6000a_init(const machine_t *); -extern int machine_at_micronics386_init(const machine_t *); +extern int machine_at_acc386_init(const machine_t *); +extern int machine_at_asus386_init(const machine_t *); +extern int machine_at_ecs386_init(const machine_t *); +extern int machine_at_spc6000a_init(const machine_t *); +extern int machine_at_micronics386_init(const machine_t *); -extern int machine_at_rycleopardlx_init(const machine_t *); +extern int machine_at_rycleopardlx_init(const machine_t *); -extern int machine_at_486vchd_init(const machine_t *); +extern int machine_at_486vchd_init(const machine_t *); -extern int machine_at_cs4031_init(const machine_t *); +extern int machine_at_cs4031_init(const machine_t *); -extern int machine_at_pb410a_init(const machine_t *); +extern int machine_at_pb410a_init(const machine_t *); -extern int machine_at_decpclpv_init(const machine_t *); -extern int machine_at_acerv10_init(const machine_t *); +extern int machine_at_decpclpv_init(const machine_t *); +extern int machine_at_acerv10_init(const machine_t *); -extern int machine_at_acera1g_init(const machine_t *); -extern int machine_at_ali1429_init(const machine_t *); -extern int machine_at_winbios1429_init(const machine_t *); +extern int machine_at_acera1g_init(const machine_t *); +extern int machine_at_ali1429_init(const machine_t *); +extern int machine_at_winbios1429_init(const machine_t *); -extern int machine_at_opti495_init(const machine_t *); -extern int machine_at_opti495_ami_init(const machine_t *); -extern int machine_at_opti495_mr_init(const machine_t *); +extern int machine_at_opti495_init(const machine_t *); +extern int machine_at_opti495_ami_init(const machine_t *); +extern int machine_at_opti495_mr_init(const machine_t *); -extern int machine_at_vect486vl_init(const machine_t *); -extern int machine_at_d824_init(const machine_t *); +extern int machine_at_vect486vl_init(const machine_t *); +extern int machine_at_d824_init(const machine_t *); -extern int machine_at_403tg_init(const machine_t *); -extern int machine_at_403tg_d_init(const machine_t *); -extern int machine_at_403tg_d_mr_init(const machine_t *); -extern int machine_at_pc330_6573_init(const machine_t *); -extern int machine_at_mvi486_init(const machine_t *); +extern int machine_at_403tg_init(const machine_t *); +extern int machine_at_403tg_d_init(const machine_t *); +extern int machine_at_403tg_d_mr_init(const machine_t *); +extern int machine_at_pc330_6573_init(const machine_t *); +extern int machine_at_mvi486_init(const machine_t *); -extern int machine_at_sis401_init(const machine_t *); -extern int machine_at_isa486_init(const machine_t *); -extern int machine_at_av4_init(const machine_t *); -extern int machine_at_valuepoint433_init(const machine_t *); +extern int machine_at_sis401_init(const machine_t *); +extern int machine_at_isa486_init(const machine_t *); +extern int machine_at_av4_init(const machine_t *); +extern int machine_at_valuepoint433_init(const machine_t *); -extern int machine_at_vli486sv2g_init(const machine_t *); -extern int machine_at_ami471_init(const machine_t *); -extern int machine_at_dtk486_init(const machine_t *); -extern int machine_at_px471_init(const machine_t *); -extern int machine_at_win471_init(const machine_t *); -extern int machine_at_vi15g_init(const machine_t *); -extern int machine_at_greenb_init(const machine_t *); +extern int machine_at_vli486sv2g_init(const machine_t *); +extern int machine_at_ami471_init(const machine_t *); +extern int machine_at_dtk486_init(const machine_t *); +extern int machine_at_px471_init(const machine_t *); +extern int machine_at_win471_init(const machine_t *); +extern int machine_at_vi15g_init(const machine_t *); +extern int machine_at_greenb_init(const machine_t *); -extern int machine_at_r418_init(const machine_t *); -extern int machine_at_ls486e_init(const machine_t *); -extern int machine_at_4dps_init(const machine_t *); -extern int machine_at_4saw2_init(const machine_t *); -extern int machine_at_m4li_init(const machine_t *); -extern int machine_at_alfredo_init(const machine_t *); -extern int machine_at_ninja_init(const machine_t *); -extern int machine_at_486sp3_init(const machine_t *); -extern int machine_at_486sp3c_init(const machine_t *); -extern int machine_at_486sp3g_init(const machine_t *); -extern int machine_at_486ap4_init(const machine_t *); -extern int machine_at_g486vpa_init(const machine_t *); -extern int machine_at_486vipio2_init(const machine_t *); -extern int machine_at_abpb4_init(const machine_t *); -extern int machine_at_win486pci_init(const machine_t *); -extern int machine_at_ms4145_init(const machine_t *); -extern int machine_at_sbc490_init(const machine_t *); -extern int machine_at_tf486_init(const machine_t *); +extern int machine_at_r418_init(const machine_t *); +extern int machine_at_ls486e_init(const machine_t *); +extern int machine_at_4dps_init(const machine_t *); +extern int machine_at_4saw2_init(const machine_t *); +extern int machine_at_m4li_init(const machine_t *); +extern int machine_at_alfredo_init(const machine_t *); +extern int machine_at_ninja_init(const machine_t *); +extern int machine_at_486sp3_init(const machine_t *); +extern int machine_at_486sp3c_init(const machine_t *); +extern int machine_at_486sp3g_init(const machine_t *); +extern int machine_at_486ap4_init(const machine_t *); +extern int machine_at_g486vpa_init(const machine_t *); +extern int machine_at_486vipio2_init(const machine_t *); +extern int machine_at_abpb4_init(const machine_t *); +extern int machine_at_win486pci_init(const machine_t *); +extern int machine_at_ms4145_init(const machine_t *); +extern int machine_at_sbc490_init(const machine_t *); +extern int machine_at_tf486_init(const machine_t *); -extern int machine_at_pci400cb_init(const machine_t *); -extern int machine_at_g486ip_init(const machine_t *); +extern int machine_at_pci400cb_init(const machine_t *); +extern int machine_at_g486ip_init(const machine_t *); -extern int machine_at_itoxstar_init(const machine_t *); -extern int machine_at_arb1423c_init(const machine_t *); -extern int machine_at_arb1479_init(const machine_t *); -extern int machine_at_pcm9340_init(const machine_t *); -extern int machine_at_pcm5330_init(const machine_t *); +extern int machine_at_itoxstar_init(const machine_t *); +extern int machine_at_arb1423c_init(const machine_t *); +extern int machine_at_arb1479_init(const machine_t *); +extern int machine_at_pcm9340_init(const machine_t *); +extern int machine_at_pcm5330_init(const machine_t *); -extern int machine_at_ecs486_init(const machine_t *); -extern int machine_at_hot433_init(const machine_t *); -extern int machine_at_atc1415_init(const machine_t *); -extern int machine_at_actionpc2600_init(const machine_t *); -extern int machine_at_m919_init(const machine_t *); -extern int machine_at_spc7700plw_init(const machine_t *); - -#ifdef EMU_DEVICE_H -extern const device_t *at_acera1g_get_device(void); -extern const device_t *at_vect486vl_get_device(void); -extern const device_t *at_d824_get_device(void); -extern const device_t *at_pcs46c_get_device(void); -extern const device_t *at_valuepoint433_get_device(void); -extern const device_t *at_sbc490_get_device(void); -#endif +extern int machine_at_ecs486_init(const machine_t *); +extern int machine_at_hot433_init(const machine_t *); +extern int machine_at_atc1415_init(const machine_t *); +extern int machine_at_actionpc2600_init(const machine_t *); +extern int machine_at_m919_init(const machine_t *); +extern int machine_at_spc7700plw_init(const machine_t *); +extern int machine_at_ms4134_init(const machine_t *); +extern int machine_at_tg486gp_init(const machine_t *); +extern int machine_at_tg486g_init(const machine_t *); /* m_at_commodore.c */ -extern int machine_at_cmdpc_init(const machine_t *); +extern int machine_at_cmdpc_init(const machine_t *); /* m_at_compaq.c */ -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 *); -#ifdef EMU_DEVICE_H -extern const device_t *at_cpqiii_get_device(void); -#endif +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 *); +extern int machine_at_deskpro386_init(const machine_t *); +extern int machine_at_deskpro386_05_1988_init(const machine_t *); /* m_at_socket4.c */ -extern void machine_at_premiere_common_init(const machine_t *, int); -extern void machine_at_award_common_init(const machine_t *); +extern void machine_at_premiere_common_init(const machine_t *, int); +extern void machine_at_award_common_init(const machine_t *); -extern void machine_at_sp4_common_init(const machine_t *model); +extern void machine_at_sp4_common_init(const machine_t *model); -extern int machine_at_excaliburpci_init(const machine_t *); -extern int machine_at_p5mp3_init(const machine_t *); -extern int machine_at_dellxp60_init(const machine_t *); -extern int machine_at_opti560l_init(const machine_t *); -extern int machine_at_ambradp60_init(const machine_t *); -extern int machine_at_valuepointp60_init(const machine_t *); -extern int machine_at_revenge_init(const machine_t *); -extern int machine_at_586mc1_init(const machine_t *); -extern int machine_at_pb520r_init(const machine_t *); +extern int machine_at_excaliburpci_init(const machine_t *); +extern int machine_at_p5mp3_init(const machine_t *); +extern int machine_at_dellxp60_init(const machine_t *); +extern int machine_at_opti560l_init(const machine_t *); +extern int machine_at_ambradp60_init(const machine_t *); +extern int machine_at_valuepointp60_init(const machine_t *); +extern int machine_at_revenge_init(const machine_t *); +extern int machine_at_586mc1_init(const machine_t *); +extern int machine_at_pb520r_init(const machine_t *); -extern int machine_at_excalibur_init(const machine_t *); +extern int machine_at_excalibur_init(const machine_t *); -extern int machine_at_p5vl_init(const machine_t *); +extern int machine_at_p5vl_init(const machine_t *); -extern int machine_at_excaliburpci2_init(const machine_t *); -extern int machine_at_p5sp4_init(const machine_t *); - -#ifdef EMU_DEVICE_H -extern const device_t *at_pb520r_get_device(void); -#endif +extern int machine_at_excaliburpci2_init(const machine_t *); +extern int machine_at_p5sp4_init(const machine_t *); /* m_at_socket5.c */ -extern int machine_at_plato_init(const machine_t *); -extern int machine_at_ambradp90_init(const machine_t *); -extern int machine_at_430nx_init(const machine_t *); +extern int machine_at_plato_init(const machine_t *); +extern int machine_at_ambradp90_init(const machine_t *); +extern int machine_at_430nx_init(const machine_t *); -extern int machine_at_acerv30_init(const machine_t *); -extern int machine_at_apollo_init(const machine_t *); -extern int machine_at_exp8551_init(const machine_t *); -extern int machine_at_zappa_init(const machine_t *); -extern int machine_at_powermatev_init(const machine_t *); -extern int machine_at_mb500n_init(const machine_t *); -extern int machine_at_hawk_init(const machine_t *); +extern int machine_at_acerv30_init(const machine_t *); +extern int machine_at_apollo_init(const machine_t *); +extern int machine_at_zappa_init(const machine_t *); +extern int machine_at_powermatev_init(const machine_t *); +extern int machine_at_hawk_init(const machine_t *); -extern int machine_at_pat54pv_init(const machine_t *); +extern int machine_at_pat54pv_init(const machine_t *); -extern int machine_at_hot543_init(const machine_t *); - -extern int machine_at_p54sp4_init(const machine_t *); -extern int machine_at_sq588_init(const machine_t *); +extern int machine_at_hot543_init(const machine_t *); +extern int machine_at_p54sp4_init(const machine_t *); +extern int machine_at_sq588_init(const machine_t *); +extern int machine_at_p54sps_init(const machine_t *); /* m_at_socket7_3v.c */ -extern int machine_at_p54tp4xe_init(const machine_t *); -extern int machine_at_p54tp4xe_mr_init(const machine_t *); -extern int machine_at_gw2katx_init(const machine_t *); -extern int machine_at_thor_init(const machine_t *); -extern int machine_at_mrthor_init(const machine_t *); -extern int machine_at_endeavor_init(const machine_t *); -extern int machine_at_ms5119_init(const machine_t *); -extern int machine_at_pb640_init(const machine_t *); -extern int machine_at_fmb_init(const machine_t *); +extern int machine_at_p54tp4xe_init(const machine_t *); +extern int machine_at_p54tp4xe_mr_init(const machine_t *); +extern int machine_at_exp8551_init(const machine_t *); +extern int machine_at_gw2katx_init(const machine_t *); +extern int machine_at_thor_init(const machine_t *); +extern int machine_at_mrthor_init(const machine_t *); +extern uint32_t machine_at_endeavor_gpio_handler(uint8_t write, uint32_t val); +extern int machine_at_endeavor_init(const machine_t *); +extern int machine_at_ms5119_init(const machine_t *); +extern int machine_at_pb640_init(const machine_t *); +extern int machine_at_mb500n_init(const machine_t *); +extern int machine_at_fmb_init(const machine_t *); -extern int machine_at_acerm3a_init(const machine_t *); -extern int machine_at_ap53_init(const machine_t *); -extern int machine_at_8500tuc_init(const machine_t *); -extern int machine_at_p55t2s_init(const machine_t *); +extern int machine_at_acerm3a_init(const machine_t *); +extern int machine_at_ap53_init(const machine_t *); +extern int machine_at_8500tuc_init(const machine_t *); +extern int machine_at_p55t2s_init(const machine_t *); -extern int machine_at_p5vxb_init(const machine_t *); -extern int machine_at_gw2kte_init(const machine_t *); +extern int machine_at_p5vxb_init(const machine_t *); +extern int machine_at_gw2kte_init(const machine_t *); -extern int machine_at_ap5s_init(const machine_t *); -extern int machine_at_vectra54_init(const machine_t *); - -#ifdef EMU_DEVICE_H -extern const device_t *at_endeavor_get_device(void); -#define at_vectra54_get_device at_endeavor_get_device -extern const device_t *at_thor_get_device(void); -#define at_mrthor_get_device at_thor_get_device -extern const device_t *at_pb640_get_device(void); -#endif +extern int machine_at_ap5s_init(const machine_t *); +extern int machine_at_ms5124_init(const machine_t *); +extern int machine_at_vectra54_init(const machine_t *); /* m_at_socket7.c */ -extern int machine_at_acerv35n_init(const machine_t *); -extern int machine_at_p55t2p4_init(const machine_t *); -extern int machine_at_m7shi_init(const machine_t *); -extern int machine_at_tc430hx_init(const machine_t *); -extern int machine_at_equium5200_init(const machine_t *); -extern int machine_at_pcv90_init(const machine_t *); -extern int machine_at_p65up5_cp55t2d_init(const machine_t *); +extern int machine_at_acerv35n_init(const machine_t *); +extern int machine_at_p55t2p4_init(const machine_t *); +extern int machine_at_m7shi_init(const machine_t *); +extern int machine_at_tc430hx_init(const machine_t *); +extern int machine_at_infinia7200_init(const machine_t *); +extern int machine_at_cu430hx_init(const machine_t *); +extern int machine_at_equium5200_init(const machine_t *); +extern int machine_at_pcv90_init(const machine_t *); +extern int machine_at_p65up5_cp55t2d_init(const machine_t *); -extern int machine_at_ap5vm_init(const machine_t *); -extern int machine_at_p55tvp4_init(const machine_t *); -extern int machine_at_5ivg_init(const machine_t *); -extern int machine_at_8500tvxa_init(const machine_t *); -extern int machine_at_presario2240_init(const machine_t *); -extern int machine_at_presario4500_init(const machine_t *); -extern int machine_at_p55va_init(const machine_t *); -extern int machine_at_brio80xx_init(const machine_t *); -extern int machine_at_pb680_init(const machine_t *); -extern int machine_at_mb520n_init(const machine_t *); -extern int machine_at_i430vx_init(const machine_t *); +extern int machine_at_ap5vm_init(const machine_t *); +extern int machine_at_p55tvp4_init(const machine_t *); +extern int machine_at_5ivg_init(const machine_t *); +extern int machine_at_8500tvxa_init(const machine_t *); +extern int machine_at_presario2240_init(const machine_t *); +extern int machine_at_presario4500_init(const machine_t *); +extern int machine_at_p55va_init(const machine_t *); +extern int machine_at_brio80xx_init(const machine_t *); +extern int machine_at_pb680_init(const machine_t *); +extern int machine_at_pb810_init(const machine_t *); +extern int machine_at_mb520n_init(const machine_t *); +extern int machine_at_i430vx_init(const machine_t *); -extern int machine_at_nupro592_init(const machine_t *); -extern int machine_at_tx97_init(const machine_t *); -#if defined(DEV_BRANCH) && defined(NO_SIO) -extern int machine_at_an430tx_init(const machine_t *); +extern int machine_at_nupro592_init(const machine_t *); +extern int machine_at_tx97_init(const machine_t *); +#if defined(DEV_BRANCH) && defined(USE_AN430TX) +extern int machine_at_an430tx_init(const machine_t *); #endif -extern int machine_at_ym430tx_init(const machine_t *); -extern int machine_at_mb540n_init(const machine_t *); -extern int machine_at_p5mms98_init(const machine_t *); +extern int machine_at_ym430tx_init(const machine_t *); +extern int machine_at_mb540n_init(const machine_t *); +extern int machine_at_56a5_init(const machine_t *); +extern int machine_at_p5mms98_init(const machine_t *); -extern int machine_at_ficva502_init(const machine_t *); +extern int machine_at_ficva502_init(const machine_t *); -extern int machine_at_ficpa2012_init(const machine_t *); +extern int machine_at_ficpa2012_init(const machine_t *); -extern int machine_at_r534f_init(const machine_t *); -extern int machine_at_ms5146_init(const machine_t *); +extern int machine_at_r534f_init(const machine_t *); +extern int machine_at_ms5146_init(const machine_t *); -extern int machine_at_m560_init(const machine_t *); -extern int machine_at_ms5164_init(const machine_t *); - -#ifdef EMU_DEVICE_H -extern const device_t *at_presario2240_get_device(void); -#define at_presario4500_get_device at_presario2240_get_device -#endif +extern int machine_at_m560_init(const machine_t *); +extern int machine_at_ms5164_init(const machine_t *); /* m_at_sockets7.c */ -extern int machine_at_p5a_init(const machine_t *); -extern int machine_at_m579_init(const machine_t *); -extern int machine_at_5aa_init(const machine_t *); -extern int machine_at_5ax_init(const machine_t *); +extern int machine_at_p5a_init(const machine_t *); +extern int machine_at_m579_init(const machine_t *); +extern int machine_at_5aa_init(const machine_t *); +extern int machine_at_5ax_init(const machine_t *); -extern int machine_at_ax59pro_init(const machine_t *); -extern int machine_at_mvp3_init(const machine_t *); -extern int machine_at_ficva503a_init(const machine_t *); -extern int machine_at_5emapro_init(const machine_t *); +extern int machine_at_ax59pro_init(const machine_t *); +extern int machine_at_mvp3_init(const machine_t *); +extern int machine_at_ficva503a_init(const machine_t *); +extern int machine_at_5emapro_init(const machine_t *); /* m_at_socket8.c */ -extern int machine_at_p6rp4_init(const machine_t *); +extern int machine_at_p6rp4_init(const machine_t *); +extern int machine_at_aurora_init(const machine_t *); -extern int machine_at_686nx_init(const machine_t *); -extern int machine_at_acerv60n_init(const machine_t *); -extern int machine_at_vs440fx_init(const machine_t *); -extern int machine_at_ap440fx_init(const machine_t *); -extern int machine_at_mb600n_init(const machine_t *); -extern int machine_at_8600ttc_init(const machine_t *); -extern int machine_at_m6mi_init(const machine_t *); +extern int machine_at_686nx_init(const machine_t *); +extern int machine_at_acerv60n_init(const machine_t *); +extern int machine_at_vs440fx_init(const machine_t *); +extern int machine_at_ap440fx_init(const machine_t *); +extern int machine_at_mb600n_init(const machine_t *); +extern int machine_at_8600ttc_init(const machine_t *); +extern int machine_at_m6mi_init(const machine_t *); #ifdef EMU_DEVICE_H -extern void machine_at_p65up5_common_init(const machine_t *, const device_t *northbridge); +extern void machine_at_p65up5_common_init(const machine_t *, const device_t *northbridge); #endif -extern int machine_at_p65up5_cp6nd_init(const machine_t *); +extern int machine_at_p65up5_cp6nd_init(const machine_t *); /* m_at_slot1.c */ -extern int machine_at_m729_init(const machine_t *); +extern int machine_at_m729_init(const machine_t *); -extern int machine_at_p65up5_cpknd_init(const machine_t *); -extern int machine_at_kn97_init(const machine_t *); +extern int machine_at_p65up5_cpknd_init(const machine_t *); +extern int machine_at_kn97_init(const machine_t *); -extern int machine_at_lx6_init(const machine_t *); -extern int machine_at_spitfire_init(const machine_t *); +extern int machine_at_lx6_init(const machine_t *); +extern int machine_at_spitfire_init(const machine_t *); -extern int machine_at_p6i440e2_init(const machine_t *); +extern int machine_at_p6i440e2_init(const machine_t *); -extern int machine_at_p2bls_init(const machine_t *); -extern int machine_at_p3bf_init(const machine_t *); -extern int machine_at_bf6_init(const machine_t *); -extern int machine_at_ax6bc_init(const machine_t *); -extern int machine_at_atc6310bxii_init(const machine_t *); -extern int machine_at_686bx_init(const machine_t *); -extern int machine_at_s1846_init(const machine_t *); -extern int machine_at_p6sba_init(const machine_t *); -extern int machine_at_ficka6130_init(const machine_t *); -extern int machine_at_p3v133_init(const machine_t *); -extern int machine_at_p3v4x_init(const machine_t *); +extern int machine_at_p2bls_init(const machine_t *); +extern int machine_at_p3bf_init(const machine_t *); +extern int machine_at_bf6_init(const machine_t *); +extern int machine_at_ax6bc_init(const machine_t *); +extern int machine_at_atc6310bxii_init(const machine_t *); +extern int machine_at_686bx_init(const machine_t *); +extern int machine_at_s1846_init(const machine_t *); +extern int machine_at_p6sba_init(const machine_t *); +extern int machine_at_ficka6130_init(const machine_t *); +extern int machine_at_p3v133_init(const machine_t *); +extern int machine_at_p3v4x_init(const machine_t *); +extern int machine_at_gt694va_init(const machine_t *); -extern int machine_at_vei8_init(const machine_t *); +extern int machine_at_vei8_init(const machine_t *); -extern int machine_at_borapro_init(const machine_t *); -extern int machine_at_ms6168_init(const machine_t *); - -#ifdef EMU_DEVICE_H -extern const device_t *at_s1846_get_device(void); -#define at_s1857_get_device at_s1846_get_device -#define at_gt694va_get_device at_s1846_get_device -extern const device_t *at_ms6168_get_device(void); -#define at_borapro_get_device at_ms6168_get_device -#endif +extern int machine_at_borapro_init(const machine_t *); +extern int machine_at_ms6168_init(const machine_t *); /* m_at_slot2.c */ -extern int machine_at_6gxu_init(const machine_t *); -extern int machine_at_s2dge_init(const machine_t *); -extern int machine_at_fw6400gx_init(const machine_t *); +extern int machine_at_6gxu_init(const machine_t *); +extern int machine_at_s2dge_init(const machine_t *); +extern int machine_at_fw6400gx_init(const machine_t *); /* m_at_socket370.c */ -extern int machine_at_s370slm_init(const machine_t *); +extern int machine_at_s370slm_init(const machine_t *); -extern int machine_at_cubx_init(const machine_t *); -extern int machine_at_atc7020bxii_init(const machine_t *); -extern int machine_at_ambx133_init(const machine_t *); -extern int machine_at_awo671r_init(const machine_t *); -extern int machine_at_63a1_init(const machine_t *); -extern int machine_at_s370sba_init(const machine_t *); -extern int machine_at_apas3_init(const machine_t *); -extern int machine_at_gt694va_init(const machine_t *); -extern int machine_at_cuv4xls_init(const machine_t *); -extern int machine_at_6via90ap_init(const machine_t *); -extern int machine_at_s1857_init(const machine_t *); -extern int machine_at_p6bap_init(const machine_t *); +extern int machine_at_cubx_init(const machine_t *); +extern int machine_at_atc7020bxii_init(const machine_t *); +extern int machine_at_ambx133_init(const machine_t *); +extern int machine_at_awo671r_init(const machine_t *); +extern int machine_at_63a1_init(const machine_t *); +extern int machine_at_s370sba_init(const machine_t *); +extern int machine_at_apas3_init(const machine_t *); +extern int machine_at_cuv4xls_init(const machine_t *); +extern int machine_at_6via90ap_init(const machine_t *); +extern int machine_at_s1857_init(const machine_t *); +extern int machine_at_p6bap_init(const machine_t *); +extern int machine_at_p6bat_init(const machine_t *); /* m_at_misc.c */ -extern int machine_at_vpc2007_init(const machine_t *); +extern int machine_at_vpc2007_init(const machine_t *); /* m_at_t3100e.c */ -extern int machine_at_t3100e_init(const machine_t *); +extern int machine_at_t3100e_init(const machine_t *); + +/* m_elt.c */ +extern int machine_elt_init(const machine_t *); /* m_europc.c */ -extern int machine_europc_init(const machine_t *); +extern int machine_europc_init(const machine_t *); #ifdef EMU_DEVICE_H extern const device_t europc_device; #endif /* m_xt_olivetti.c */ -extern int machine_xt_m24_init(const machine_t *); -#ifdef EMU_DEVICE_H -extern const device_t *m24_get_device(void); -#endif -extern int machine_xt_m240_init(const machine_t *); -extern int machine_xt_m19_init(const machine_t *); -#ifdef EMU_DEVICE_H -extern const device_t *m19_get_device(void); -#endif +extern int machine_xt_m24_init(const machine_t *); +extern int machine_xt_m240_init(const machine_t *); +extern int machine_xt_m19_init(const machine_t *); /* m_pcjr.c */ -extern int machine_pcjr_init(const machine_t *); - -#ifdef EMU_DEVICE_H -extern const device_t *pcjr_get_device(void); -#endif +extern int machine_pcjr_init(const machine_t *); /* m_ps1.c */ -extern int machine_ps1_m2011_init(const machine_t *); -extern int machine_ps1_m2121_init(const machine_t *); +extern int machine_ps1_m2011_init(const machine_t *); +extern int machine_ps1_m2121_init(const machine_t *); /* m_ps1_hdc.c */ #ifdef EMU_DEVICE_H -extern void ps1_hdc_inform(void *, uint8_t *); +extern void ps1_hdc_inform(void *, uint8_t *); extern const device_t ps1_hdc_device; #endif /* m_ps2_isa.c */ -extern int machine_ps2_m30_286_init(const machine_t *); +extern int machine_ps2_m30_286_init(const machine_t *); /* m_ps2_mca.c */ -extern int machine_ps2_model_50_init(const machine_t *); -extern int machine_ps2_model_55sx_init(const machine_t *); -extern int machine_ps2_model_70_type3_init(const machine_t *); -extern int machine_ps2_model_80_init(const machine_t *); -extern int machine_ps2_model_80_axx_init(const machine_t *); +extern int machine_ps2_model_50_init(const machine_t *); +extern int machine_ps2_model_60_init(const machine_t *); +extern int machine_ps2_model_55sx_init(const machine_t *); +extern int machine_ps2_model_65sx_init(const machine_t *); +extern int machine_ps2_model_70_type3_init(const machine_t *); +extern int machine_ps2_model_80_init(const machine_t *); +extern int machine_ps2_model_80_axx_init(const machine_t *); +extern int machine_ps2_model_70_type4_init(const machine_t *); /* m_tandy.c */ -extern int tandy1k_eeprom_read(void); -extern int machine_tandy_init(const machine_t *); -extern int machine_tandy1000hx_init(const machine_t *); -extern int machine_tandy1000sl2_init(const machine_t *); +extern int tandy1k_eeprom_read(void); +extern int machine_tandy_init(const machine_t *); +extern int machine_tandy1000hx_init(const machine_t *); +extern int machine_tandy1000sl2_init(const machine_t *); /* m_v86p.c */ -extern int machine_v86p_init(const machine_t *); - -#ifdef EMU_DEVICE_H -extern const device_t *tandy1k_get_device(void); -extern const device_t *tandy1k_hx_get_device(void); -extern const device_t *tandy1k_sl_get_device(void); -#endif +extern int machine_v86p_init(const machine_t *); /* m_xt.c */ -extern int machine_pc_init(const machine_t *); -extern int machine_pc82_init(const machine_t *); +extern int machine_pc_init(const machine_t *); +extern int machine_pc82_init(const machine_t *); -extern int machine_xt_init(const machine_t *); -extern int machine_genxt_init(const machine_t *); +extern int machine_xt_init(const machine_t *); +extern int machine_genxt_init(const machine_t *); -extern int machine_xt86_init(const machine_t *); +extern int machine_xt86_init(const machine_t *); -extern int machine_xt_americxt_init(const machine_t *); -extern int machine_xt_amixt_init(const machine_t *); -extern int machine_xt_dtk_init(const machine_t *); -extern int machine_xt_jukopc_init(const machine_t *); -extern int machine_xt_openxt_init(const machine_t *); -extern int machine_xt_pcxt_init(const machine_t *); -extern int machine_xt_pxxt_init(const machine_t *); -extern int machine_xt_pc4i_init(const machine_t *); -extern int machine_xt_mpc1600_init(const machine_t *); -extern int machine_xt_pcspirit_init(const machine_t *); -extern int machine_xt_pc700_init(const machine_t *); -extern int machine_xt_pc500_init(const machine_t *); +extern int machine_xt_americxt_init(const machine_t *); +extern int machine_xt_amixt_init(const machine_t *); +extern int machine_xt_dtk_init(const machine_t *); +extern int machine_xt_jukopc_init(const machine_t *); +extern int machine_xt_openxt_init(const machine_t *); +extern int machine_xt_pcxt_init(const machine_t *); +extern int machine_xt_pxxt_init(const machine_t *); +extern int machine_xt_pc4i_init(const machine_t *); +extern int machine_xt_mpc1600_init(const machine_t *); +extern int machine_xt_pcspirit_init(const machine_t *); +extern int machine_xt_pc700_init(const machine_t *); +extern int machine_xt_pc500_init(const machine_t *); +extern int machine_xt_vendex_init(const machine_t *); +extern int machine_xt_znic_init(const machine_t *); +extern int machine_xt_super16t_init(const machine_t *); +extern int machine_xt_super16te_init(const machine_t *); +extern int machine_xt_top88_init(const machine_t *); +extern int machine_xt_kaypropc_init(const machine_t *); +extern int machine_xt_sansx16_init(const machine_t *); +extern int machine_xt_bw230_init(const machine_t *); +extern int machine_xt_pb8810_init(const machine_t *); -extern int machine_xt_iskra3104_init(const machine_t *); +extern int machine_xt_v20xt_init(const machine_t *); + +extern int machine_xt_iskra3104_init(const machine_t *); +extern int machine_xt_pravetz16_imko4_init(const machine_t *); +extern int machine_xt_micoms_xl7turbo_init(const machine_t *); /* m_xt_compaq.c */ -extern int machine_xt_compaq_deskpro_init(const machine_t *); -extern int machine_xt_compaq_portable_init(const machine_t *); +extern int machine_xt_compaq_deskpro_init(const machine_t *); +extern int machine_xt_compaq_portable_init(const machine_t *); /* m_xt_laserxt.c */ #if defined(DEV_BRANCH) && defined(USE_LASERXT) -extern int machine_xt_laserxt_init(const machine_t *); -extern int machine_xt_lxt3_init(const machine_t *); +extern int machine_xt_laserxt_init(const machine_t *); +extern int machine_xt_lxt3_init(const machine_t *); #endif /* m_xt_philips.c */ -extern int machine_xt_p3105_init(const machine_t *); -extern int machine_xt_p3120_init(const machine_t *); +extern int machine_xt_p3105_init(const machine_t *); +extern int machine_xt_p3120_init(const machine_t *); /* m_xt_t1000.c */ -extern int machine_xt_t1000_init(const machine_t *); -extern int machine_xt_t1200_init(const machine_t *); - -#ifdef EMU_DEVICE_H -extern const device_t *t1000_get_device(void); -extern const device_t *t1200_get_device(void); -#endif +extern int machine_xt_t1000_init(const machine_t *); +extern int machine_xt_t1200_init(const machine_t *); /* m_xt_zenith.c */ -extern int machine_xt_z184_init(const machine_t *); -#ifdef EMU_DEVICE_H -extern const device_t *z184_get_device(void); -#endif -extern int machine_xt_z151_init(const machine_t *); -extern int machine_xt_z159_init(const machine_t *); +extern int machine_xt_z184_init(const machine_t *); +extern int machine_xt_z151_init(const machine_t *); +extern int machine_xt_z159_init(const machine_t *); /* m_xt_xi8088.c */ -extern int machine_xt_xi8088_init(const machine_t *); +extern int machine_xt_xi8088_init(const machine_t *); -#ifdef EMU_DEVICE_H -extern const device_t *xi8088_get_device(void); -#endif - - -#endif /*EMU_MACHINE_H*/ +#endif /*EMU_MACHINE_H*/ diff --git a/src/include/86box/machine_status.h b/src/include/86box/machine_status.h new file mode 100644 index 000000000..e7c57881b --- /dev/null +++ b/src/include/86box/machine_status.h @@ -0,0 +1,32 @@ +#ifndef EMU_MACHINE_STATUS_H +#define EMU_MACHINE_STATUS_H + +typedef struct dev_status_empty_active_t { + atomic_bool_t empty; + atomic_bool_t active; +} dev_status_empty_active_t; + +typedef struct dev_status_active_t { + atomic_bool_t active; +} dev_status_active_t; + +typedef struct dev_status_empty_t { + atomic_bool_t empty; +} dev_status_empty_t; + +typedef struct machine_status_t { + dev_status_empty_active_t fdd[FDD_NUM]; + dev_status_empty_active_t cdrom[CDROM_NUM]; + dev_status_empty_active_t zip[ZIP_NUM]; + dev_status_empty_active_t mo[MO_NUM]; + dev_status_empty_active_t cassette; + dev_status_active_t hdd[HDD_BUS_USB]; + dev_status_empty_active_t net[NET_CARD_MAX]; + dev_status_empty_t cartridge[2]; +} machine_status_t; + +extern machine_status_t machine_status; + +extern void machine_status_init(void); + +#endif /*EMU_MACHINE_STATUS_H*/ \ No newline at end of file diff --git a/src/include/86box/mca.h b/src/include/86box/mca.h index e0def3fe5..e048a6131 100644 --- a/src/include/86box/mca.h +++ b/src/include/86box/mca.h @@ -1,9 +1,16 @@ -extern void mca_init(int nr_cards); -extern void mca_add(uint8_t (*read)(int addr, void *priv), void (*write)(int addr, uint8_t val, void *priv), uint8_t (*feedb)(void *priv), void (*reset)(void *priv), void *priv); -extern void mca_set_index(int index); -extern uint8_t mca_read(uint16_t port); -extern void mca_write(uint16_t port, uint8_t val); -extern uint8_t mca_feedb(void); -extern void mca_reset(void); +#ifndef EMU_MCA_H +#define EMU_MCA_H -extern void ps2_cache_clean(void); \ No newline at end of file +extern void mca_init(int nr_cards); +extern void mca_add(uint8_t (*read)(int addr, void *priv), void (*write)(int addr, uint8_t val, void *priv), uint8_t (*feedb)(void *priv), void (*reset)(void *priv), void *priv); +extern void mca_set_index(int index); +extern uint8_t mca_read(uint16_t port); +extern uint8_t mca_read_index(uint16_t port, int index); +extern void mca_write(uint16_t port, uint8_t val); +extern uint8_t mca_feedb(void); +extern int mca_get_nr_cards(void); +extern void mca_reset(void); + +extern void ps2_cache_clean(void); + +#endif /*EMU_MCA_H*/ diff --git a/src/include/86box/mem.h b/src/include/86box/mem.h index 5d1f6848c..69a2b5de8 100644 --- a/src/include/86box/mem.h +++ b/src/include/86box/mem.h @@ -1,77 +1,77 @@ /* - * 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. + * 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. + * This file is part of the 86Box distribution. * - * Definitions for the memory interface. + * Definitions for the memory interface. * * * - * Authors: Sarah Walker, - * Fred N. van Kempen, - * Miran Grca, + * Authors: Sarah Walker, + * Fred N. van Kempen, + * Miran Grca, * - * Copyright 2008-2020 Sarah Walker. - * Copyright 2017-2020 Fred N. van Kempen. - * Copyright 2016-2020 Miran Grca. + * Copyright 2008-2020 Sarah Walker. + * Copyright 2017-2020 Fred N. van Kempen. + * Copyright 2016-2020 Miran Grca. */ -#ifndef EMU_MEM_H -# define EMU_MEM_H +#ifndef EMU_MEM_H +#define EMU_MEM_H #define MEM_MAP_TO_SHADOW_RAM_MASK 1 #define MEM_MAP_TO_RAM_ADDR_MASK 2 -#define STATE_CPU 0 -#define STATE_BUS 2 +#define STATE_CPU 0 +#define STATE_BUS 2 -#define ACCESS_CPU 1 /* Update CPU non-SMM access. */ -#define ACCESS_CPU_SMM 2 /* Update CPU SMM access. */ -#define ACCESS_BUS 4 /* Update bus access. */ -#define ACCESS_BUS_SMM 8 /* Update bus SMM access. */ -#define ACCESS_NORMAL 5 /* Update CPU and bus non-SMM accesses. */ -#define ACCESS_SMM 10 /* Update CPU and bus SMM accesses. */ -#define ACCESS_CPU_BOTH 3 /* Update CPU non-SMM and SMM accesses. */ -#define ACCESS_BUS_BOTH 12 /* Update bus non-SMM and SMM accesses. */ -#define ACCESS_ALL 15 /* Update all accesses. */ +#define ACCESS_CPU 1 /* Update CPU non-SMM access. */ +#define ACCESS_CPU_SMM 2 /* Update CPU SMM access. */ +#define ACCESS_BUS 4 /* Update bus access. */ +#define ACCESS_BUS_SMM 8 /* Update bus SMM access. */ +#define ACCESS_NORMAL 5 /* Update CPU and bus non-SMM accesses. */ +#define ACCESS_SMM 10 /* Update CPU and bus SMM accesses. */ +#define ACCESS_CPU_BOTH 3 /* Update CPU non-SMM and SMM accesses. */ +#define ACCESS_BUS_BOTH 12 /* Update bus non-SMM and SMM accesses. */ +#define ACCESS_ALL 15 /* Update all accesses. */ -#define ACCESS_INTERNAL 1 -#define ACCESS_ROMCS 2 -#define ACCESS_SMRAM 4 -#define ACCESS_CACHE 8 -#define ACCESS_DISABLED 16 +#define ACCESS_INTERNAL 1 +#define ACCESS_ROMCS 2 +#define ACCESS_SMRAM 4 +#define ACCESS_CACHE 8 +#define ACCESS_DISABLED 16 -#define ACCESS_X_INTERNAL 1 -#define ACCESS_X_ROMCS 2 -#define ACCESS_X_SMRAM 4 -#define ACCESS_X_CACHE 8 -#define ACCESS_X_DISABLED 16 -#define ACCESS_W_INTERNAL 32 -#define ACCESS_W_ROMCS 64 -#define ACCESS_W_SMRAM 128 -#define ACCESS_W_CACHE 256 -#define ACCESS_W_DISABLED 512 -#define ACCESS_R_INTERNAL 1024 -#define ACCESS_R_ROMCS 2048 -#define ACCESS_R_SMRAM 4096 -#define ACCESS_R_CACHE 8192 -#define ACCESS_R_DISABLED 16384 +#define ACCESS_X_INTERNAL 1 +#define ACCESS_X_ROMCS 2 +#define ACCESS_X_SMRAM 4 +#define ACCESS_X_CACHE 8 +#define ACCESS_X_DISABLED 16 +#define ACCESS_W_INTERNAL 32 +#define ACCESS_W_ROMCS 64 +#define ACCESS_W_SMRAM 128 +#define ACCESS_W_CACHE 256 +#define ACCESS_W_DISABLED 512 +#define ACCESS_R_INTERNAL 1024 +#define ACCESS_R_ROMCS 2048 +#define ACCESS_R_SMRAM 4096 +#define ACCESS_R_CACHE 8192 +#define ACCESS_R_DISABLED 16384 -#define ACCESS_EXECUTE 0 -#define ACCESS_READ 1 -#define ACCESS_WRITE 2 +#define ACCESS_EXECUTE 0 +#define ACCESS_READ 1 +#define ACCESS_WRITE 2 -#define ACCESS_SMRAM_OFF 0 -#define ACCESS_SMRAM_X 1 -#define ACCESS_SMRAM_W 2 -#define ACCESS_SMRAM_WX 3 -#define ACCESS_SMRAM_R 4 -#define ACCESS_SMRAM_RX 5 -#define ACCESS_SMRAM_RW 6 -#define ACCESS_SMRAM_RWX 7 +#define ACCESS_SMRAM_OFF 0 +#define ACCESS_SMRAM_X 1 +#define ACCESS_SMRAM_W 2 +#define ACCESS_SMRAM_WX 3 +#define ACCESS_SMRAM_R 4 +#define ACCESS_SMRAM_RX 5 +#define ACCESS_SMRAM_RW 6 +#define ACCESS_SMRAM_RWX 7 /* Conversion #define's - we need these to seamlessly convert the old mem_set_mem_state() calls to the new stuff in order to make this a drop in replacement. @@ -79,406 +79,431 @@ Read here includes execute access since the old code also used read access for execute access, with some exceptions. */ -#define MEM_READ_DISABLED (ACCESS_X_DISABLED | ACCESS_R_DISABLED) -#define MEM_READ_INTERNAL (ACCESS_X_INTERNAL | ACCESS_R_INTERNAL) -#define MEM_READ_EXTERNAL 0 +#define MEM_READ_DISABLED (ACCESS_X_DISABLED | ACCESS_R_DISABLED) +#define MEM_READ_INTERNAL (ACCESS_X_INTERNAL | ACCESS_R_INTERNAL) +#define MEM_READ_EXTERNAL 0 /* These two are going to be identical - on real hardware, chips that don't care about ROMCS#, are not magically disabled. */ -#define MEM_READ_ROMCS (ACCESS_X_ROMCS | ACCESS_R_ROMCS) -#define MEM_READ_EXTANY MEM_READ_ROMCS +#define MEM_READ_ROMCS (ACCESS_X_ROMCS | ACCESS_R_ROMCS) +#define MEM_READ_EXTANY MEM_READ_ROMCS /* Internal execute access, external read access. */ -#define MEM_READ_EXTERNAL_EX 0 -#define MEM_READ_SMRAM (ACCESS_X_SMRAM | ACCESS_R_SMRAM) -#define MEM_READ_CACHE (ACCESS_X_CACHE | ACCESS_R_CACHE) -#define MEM_READ_SMRAM_EX (ACCESS_X_SMRAM) -#define MEM_EXEC_SMRAM MEM_READ_SMRAM_EX -#define MEM_READ_SMRAM_2 (ACCESS_R_SMRAM) +#define MEM_READ_EXTERNAL_EX 0 +#define MEM_READ_SMRAM (ACCESS_X_SMRAM | ACCESS_R_SMRAM) +#define MEM_READ_CACHE (ACCESS_X_CACHE | ACCESS_R_CACHE) +#define MEM_READ_SMRAM_EX (ACCESS_X_SMRAM) +#define MEM_EXEC_SMRAM MEM_READ_SMRAM_EX +#define MEM_READ_SMRAM_2 (ACCESS_R_SMRAM) /* Theese two are going to be identical. */ -#define MEM_READ_DISABLED_EX MEM_READ_DISABLED -#define MEM_READ_MASK 0x7c1f +#define MEM_READ_DISABLED_EX MEM_READ_DISABLED +#define MEM_READ_MASK 0x7c1f -#define MEM_WRITE_DISABLED (ACCESS_W_DISABLED) -#define MEM_WRITE_INTERNAL (ACCESS_W_INTERNAL) -#define MEM_WRITE_EXTERNAL 0 +#define MEM_WRITE_DISABLED (ACCESS_W_DISABLED) +#define MEM_WRITE_INTERNAL (ACCESS_W_INTERNAL) +#define MEM_WRITE_EXTERNAL 0 /* These two are going to be identical - on real hardware, chips that don't care about ROMCS#, are not magically disabled. */ -#define MEM_WRITE_ROMCS (ACCESS_W_ROMCS) -#define MEM_WRITE_EXTANY (ACCESS_W_ROMCS) -#define MEM_WRITE_SMRAM (ACCESS_W_SMRAM) -#define MEM_WRITE_CACHE (ACCESS_W_CACHE) +#define MEM_WRITE_ROMCS (ACCESS_W_ROMCS) +#define MEM_WRITE_EXTANY (ACCESS_W_ROMCS) +#define MEM_WRITE_SMRAM (ACCESS_W_SMRAM) +#define MEM_WRITE_CACHE (ACCESS_W_CACHE) /* Theese two are going to be identical. */ -#define MEM_WRITE_DISABLED_EX MEM_READ_DISABLED -#define MEM_WRITE_MASK 0x03e0 +#define MEM_WRITE_DISABLED_EX MEM_READ_DISABLED +#define MEM_WRITE_MASK 0x03e0 -#define MEM_MAPPING_EXTERNAL 1 /* On external bus (ISA/PCI). */ -#define MEM_MAPPING_INTERNAL 2 /* On internal bus (RAM). */ -#define MEM_MAPPING_ROM_WS 4 /* Executing from ROM may involve additional wait states. */ -#define MEM_MAPPING_IS_ROM 8 /* Responds to ROMCS#. */ -#define MEM_MAPPING_ROM (MEM_MAPPING_ROM_WS | MEM_MAPPING_IS_ROM) -#define MEM_MAPPING_ROMCS 16 /* If it responds to ROMCS#, it requires ROMCS# asserted. */ -#define MEM_MAPPING_SMRAM 32 /* On internal bus (RAM) but SMRAM. */ -#define MEM_MAPPING_CACHE 64 /* Cache or MTRR - please avoid such mappings unless - stricly necessary (eg. for CoreBoot). */ +#define MEM_MAPPING_EXTERNAL 1 /* On external bus (ISA/PCI). */ +#define MEM_MAPPING_INTERNAL 2 /* On internal bus (RAM). */ +#define MEM_MAPPING_ROM_WS 4 /* Executing from ROM may involve additional wait states. */ +#define MEM_MAPPING_IS_ROM 8 /* Responds to ROMCS#. */ +#define MEM_MAPPING_ROM (MEM_MAPPING_ROM_WS | MEM_MAPPING_IS_ROM) +#define MEM_MAPPING_ROMCS 16 /* If it responds to ROMCS#, it requires ROMCS# asserted. */ +#define MEM_MAPPING_SMRAM 32 /* On internal bus (RAM) but SMRAM. */ +#define MEM_MAPPING_CACHE 64 /* Cache or MTRR - please avoid such mappings unless \ + stricly necessary (eg. for CoreBoot). */ /* #define's for memory granularity, currently 4k, less does not work because of internal 4k pages. */ -#define MEM_GRANULARITY_BITS 12 -#define MEM_GRANULARITY_SIZE (1 << MEM_GRANULARITY_BITS) -#define MEM_GRANULARITY_HBOUND (MEM_GRANULARITY_SIZE - 2) -#define MEM_GRANULARITY_QBOUND (MEM_GRANULARITY_SIZE - 4) -#define MEM_GRANULARITY_MASK (MEM_GRANULARITY_SIZE - 1) -#define MEM_GRANULARITY_HMASK ((1 << (MEM_GRANULARITY_BITS - 1)) - 1) -#define MEM_GRANULARITY_QMASK ((1 << (MEM_GRANULARITY_BITS - 2)) - 1) -#define MEM_GRANULARITY_PMASK ((1 << (MEM_GRANULARITY_BITS - 3)) - 1) -#define MEM_MAPPINGS_NO ((0x100000 >> MEM_GRANULARITY_BITS) << 12) -#define MEM_GRANULARITY_PAGE (MEM_GRANULARITY_MASK & ~0xfff) -#define MEM_GRANULARITY_BASE (~MEM_GRANULARITY_MASK) +#define MEM_GRANULARITY_BITS 12 +#define MEM_GRANULARITY_SIZE (1 << MEM_GRANULARITY_BITS) +#define MEM_GRANULARITY_HBOUND (MEM_GRANULARITY_SIZE - 2) +#define MEM_GRANULARITY_QBOUND (MEM_GRANULARITY_SIZE - 4) +#define MEM_GRANULARITY_MASK (MEM_GRANULARITY_SIZE - 1) +#define MEM_GRANULARITY_HMASK ((1 << (MEM_GRANULARITY_BITS - 1)) - 1) +#define MEM_GRANULARITY_QMASK ((1 << (MEM_GRANULARITY_BITS - 2)) - 1) +#define MEM_GRANULARITY_PMASK ((1 << (MEM_GRANULARITY_BITS - 3)) - 1) +#define MEM_MAPPINGS_NO ((0x100000 >> MEM_GRANULARITY_BITS) << 12) +#define MEM_GRANULARITY_PAGE (MEM_GRANULARITY_MASK & ~0xfff) +#define MEM_GRANULARITY_BASE (~MEM_GRANULARITY_MASK) /* Compatibility #defines. */ #define mem_set_state(smm, mode, base, size, access) \ - mem_set_access((smm ? ACCESS_SMM : ACCESS_NORMAL), mode, base, size, access) + mem_set_access((smm ? ACCESS_SMM : ACCESS_NORMAL), mode, base, size, access) #define mem_set_mem_state_common(smm, base, size, access) \ - mem_set_access((smm ? ACCESS_SMM : ACCESS_NORMAL), 0, base, size, access) + mem_set_access((smm ? ACCESS_SMM : ACCESS_NORMAL), 0, base, size, access) #define mem_set_mem_state(base, size, access) \ - mem_set_access(ACCESS_NORMAL, 0, base, size, access) + mem_set_access(ACCESS_NORMAL, 0, base, size, access) #define mem_set_mem_state_smm(base, size, access) \ - mem_set_access(ACCESS_SMM, 0, base, size, access) + mem_set_access(ACCESS_SMM, 0, base, size, access) #define mem_set_mem_state_both(base, size, access) \ - mem_set_access(ACCESS_ALL, 0, base, size, access) + mem_set_access(ACCESS_ALL, 0, base, size, access) #define mem_set_mem_state_cpu_both(base, size, access) \ - mem_set_access(ACCESS_CPU_BOTH, 0, base, size, access) + mem_set_access(ACCESS_CPU_BOTH, 0, base, size, access) #define mem_set_mem_state_bus_both(base, size, access) \ - mem_set_access(ACCESS_BUS_BOTH, 0, base, size, access) + mem_set_access(ACCESS_BUS_BOTH, 0, base, size, access) #define mem_set_mem_state_smram(smm, base, size, is_smram) \ - mem_set_access((smm ? ACCESS_SMM : ACCESS_NORMAL), 1, base, size, is_smram) + mem_set_access((smm ? ACCESS_SMM : ACCESS_NORMAL), 1, base, size, is_smram) #define mem_set_mem_state_smram_ex(smm, base, size, is_smram) \ - mem_set_access((smm ? ACCESS_SMM : ACCESS_NORMAL), 2, base, size, is_smram) + mem_set_access((smm ? ACCESS_SMM : ACCESS_NORMAL), 2, base, size, is_smram) #define mem_set_access_smram_cpu(smm, base, size, is_smram) \ - mem_set_access((smm ? ACCESS_CPU_SMM : ACCESS_CPU), 1, base, size, is_smram) + mem_set_access((smm ? ACCESS_CPU_SMM : ACCESS_CPU), 1, base, size, is_smram) #define mem_set_access_smram_bus(smm, base, size, is_smram) \ - mem_set_access((smm ? ACCESS_BUS_SMM : ACCESS_BUS), 1, base, size, is_smram) -#define flushmmucache_cr3 \ - flushmmucache_nopc + mem_set_access((smm ? ACCESS_BUS_SMM : ACCESS_BUS), 1, base, size, is_smram) - -typedef struct { - uint16_t x :5, - w :5, - r :5, - pad :1; +typedef struct state_t { + uint16_t x : 5; + uint16_t w : 5; + uint16_t r : 5; + uint16_t pad : 1; } state_t; -typedef union { - uint16_t vals[4]; - state_t states[4]; +typedef union mem_state_t { + uint16_t vals[4]; + state_t states[4]; } mem_state_t; typedef struct _mem_mapping_ { - struct _mem_mapping_ *prev, *next; + struct _mem_mapping_ *prev; + struct _mem_mapping_ *next; - int enable; + int enable; - uint32_t base; - uint32_t size; + uint32_t base; + uint32_t size; - uint8_t (*read_b)(uint32_t addr, void *priv); - uint16_t (*read_w)(uint32_t addr, void *priv); - uint32_t (*read_l)(uint32_t addr, void *priv); - void (*write_b)(uint32_t addr, uint8_t val, void *priv); - void (*write_w)(uint32_t addr, uint16_t val, void *priv); - void (*write_l)(uint32_t addr, uint32_t val, void *priv); + uint32_t mask; - uint8_t *exec; + uint8_t (*read_b)(uint32_t addr, void *priv); + uint16_t (*read_w)(uint32_t addr, void *priv); + uint32_t (*read_l)(uint32_t addr, void *priv); + void (*write_b)(uint32_t addr, uint8_t val, void *priv); + void (*write_w)(uint32_t addr, uint16_t val, void *priv); + void (*write_l)(uint32_t addr, uint32_t val, void *priv); - uint32_t flags; + uint8_t *exec; + + uint32_t flags; /* There is never a needed to pass a pointer to the mapping itself, it is much preferable to prepare a structure with the requires data (usually, the base address and mask) instead. */ - void *p; /* backpointer to device */ + void *priv; /* backpointer to device */ } mem_mapping_t; #ifdef USE_NEW_DYNAREC extern uint64_t *byte_dirty_mask; extern uint64_t *byte_code_present_mask; -#define PAGE_BYTE_MASK_SHIFT 6 -#define PAGE_BYTE_MASK_OFFSET_MASK 63 -#define PAGE_BYTE_MASK_MASK 63 +# define PAGE_BYTE_MASK_SHIFT 6 +# define PAGE_BYTE_MASK_OFFSET_MASK 63 +# define PAGE_BYTE_MASK_MASK 63 -#define EVICT_NOT_IN_LIST ((uint32_t)-1) -typedef struct page_t -{ - void (*write_b)(uint32_t addr, uint8_t val, struct page_t *p); - void (*write_w)(uint32_t addr, uint16_t val, struct page_t *p); - void (*write_l)(uint32_t addr, uint32_t val, struct page_t *p); +# define EVICT_NOT_IN_LIST ((uint32_t) -1) +typedef struct page_t { + void (*write_b)(uint32_t addr, uint8_t val, struct page_t *page); + void (*write_w)(uint32_t addr, uint16_t val, struct page_t *page); + void (*write_l)(uint32_t addr, uint32_t val, struct page_t *page); - uint8_t *mem; + uint8_t *mem; - uint16_t block, block_2; + uint16_t block, block_2; /*Head of codeblock tree associated with this page*/ uint16_t head; - uint64_t code_present_mask, dirty_mask; + uint64_t code_present_mask; + uint64_t dirty_mask; - uint32_t evict_prev, evict_next; + uint32_t evict_prev; + uint32_t evict_next; uint64_t *byte_dirty_mask; uint64_t *byte_code_present_mask; } page_t; extern uint32_t purgable_page_list_head; -static inline int -page_in_evict_list(page_t *p) +__attribute__((always_inline)) static inline int +page_in_evict_list(page_t *page) { - return (p->evict_prev != EVICT_NOT_IN_LIST); + return (page->evict_prev != EVICT_NOT_IN_LIST); } -void page_remove_from_evict_list(page_t *p); -void page_add_to_evict_list(page_t *p); +void page_remove_from_evict_list(page_t *page); +void page_add_to_evict_list(page_t *page); #else typedef struct _page_ { - void (*write_b)(uint32_t addr, uint8_t val, struct _page_ *p); - void (*write_w)(uint32_t addr, uint16_t val, struct _page_ *p); - void (*write_l)(uint32_t addr, uint32_t val, struct _page_ *p); + void (*write_b)(uint32_t addr, uint8_t val, struct _page_ *page); + void (*write_w)(uint32_t addr, uint16_t val, struct _page_ *page); + void (*write_l)(uint32_t addr, uint32_t val, struct _page_ *page); - uint8_t *mem; + uint8_t *mem; - uint64_t code_present_mask[4], - dirty_mask[4]; + uint64_t code_present_mask[4]; + uint64_t dirty_mask[4]; - struct codeblock_t *block[4], *block_2[4]; + struct codeblock_t *block[4]; + struct codeblock_t *block_2[4]; /*Head of codeblock tree associated with this page*/ struct codeblock_t *head; } page_t; #endif +extern uint8_t *ram; +extern uint8_t *ram2; +extern uint32_t rammask; -extern uint8_t *ram, *ram2; -extern uint32_t rammask; +extern uint8_t *rom; +extern uint32_t biosmask; +extern uint32_t biosaddr; -extern uint8_t *rom; -extern uint32_t biosmask, biosaddr; +extern int readlookup[256]; +extern uintptr_t *readlookup2; +extern uintptr_t old_rl2; +extern uint8_t uncached; +extern int readlnext; +extern int writelookup[256]; +extern uintptr_t *writelookup2; +extern int writelnext; +extern uint32_t ram_mapped_addr[64]; +extern uint8_t page_ff[4096]; -extern int readlookup[256]; -extern uintptr_t * readlookup2; -extern uintptr_t old_rl2; -extern uint8_t uncached; -extern int readlnext; -extern int writelookup[256]; -extern uintptr_t * writelookup2; -extern int writelnext; -extern uint32_t ram_mapped_addr[64]; - -extern mem_mapping_t ram_low_mapping, +extern mem_mapping_t ram_low_mapping; #if 1 - ram_mid_mapping, +extern mem_mapping_t ram_mid_mapping; #endif - ram_remapped_mapping, - ram_high_mapping, - ram_2gb_mapping, - bios_mapping, - bios_high_mapping; +extern mem_mapping_t ram_remapped_mapping; +extern mem_mapping_t ram_high_mapping; +extern mem_mapping_t ram_2gb_mapping; +extern mem_mapping_t bios_mapping; +extern mem_mapping_t bios_high_mapping; -extern uint32_t mem_logical_addr; +extern uint32_t mem_logical_addr; -extern page_t *pages, - **page_lookup; +extern page_t *pages; +extern page_t **page_lookup; -extern uint32_t get_phys_virt, get_phys_phys; +extern uint32_t get_phys_virt; +extern uint32_t get_phys_phys; -extern int shadowbios, - shadowbios_write; -extern int readlnum, - writelnum; +extern int shadowbios; +extern int shadowbios_write; +extern int readlnum; +extern int writelnum; -extern int memspeed[11]; +extern int memspeed[11]; -extern int mmu_perm; -extern uint8_t high_page; /* if a high (> 4 gb) page was detected */ +extern int mmu_perm; +extern uint8_t high_page; /* if a high (> 4 gb) page was detected */ -extern int mem_a20_state, - mem_a20_alt, - mem_a20_key; +extern uint32_t pages_sz; /* #pages in table */ +extern int mem_a20_state; +extern int mem_a20_alt; +extern int mem_a20_key; -extern uint8_t read_mem_b(uint32_t addr); -extern uint16_t read_mem_w(uint32_t addr); -extern void write_mem_b(uint32_t addr, uint8_t val); -extern void write_mem_w(uint32_t addr, uint16_t val); +extern uint8_t read_mem_b(uint32_t addr); +extern uint16_t read_mem_w(uint32_t addr); +extern void write_mem_b(uint32_t addr, uint8_t val); +extern void write_mem_w(uint32_t addr, uint16_t val); -extern uint8_t readmembl(uint32_t addr); -extern void writemembl(uint32_t addr, uint8_t val); -extern uint16_t readmemwl(uint32_t addr); -extern void writememwl(uint32_t addr, uint16_t val); -extern uint32_t readmemll(uint32_t addr); -extern void writememll(uint32_t addr, uint32_t val); -extern uint64_t readmemql(uint32_t addr); -extern void writememql(uint32_t addr, uint64_t val); +extern uint8_t readmembl(uint32_t addr); +extern void writemembl(uint32_t addr, uint8_t val); +extern uint16_t readmemwl(uint32_t addr); +extern void writememwl(uint32_t addr, uint16_t val); +extern uint32_t readmemll(uint32_t addr); +extern void writememll(uint32_t addr, uint32_t val); +extern uint64_t readmemql(uint32_t addr); +extern void writememql(uint32_t addr, uint64_t val); -extern uint8_t readmembl_no_mmut(uint32_t addr, uint32_t a64); -extern void writemembl_no_mmut(uint32_t addr, uint32_t a64, uint8_t val); -extern uint16_t readmemwl_no_mmut(uint32_t addr, uint32_t *a64); -extern void writememwl_no_mmut(uint32_t addr, uint32_t *a64, uint16_t val); -extern uint32_t readmemll_no_mmut(uint32_t addr, uint32_t *a64); -extern void writememll_no_mmut(uint32_t addr, uint32_t *a64, uint32_t val); +extern uint8_t readmembl_no_mmut(uint32_t addr, uint32_t a64); +extern void writemembl_no_mmut(uint32_t addr, uint32_t a64, uint8_t val); +extern uint16_t readmemwl_no_mmut(uint32_t addr, uint32_t *a64); +extern void writememwl_no_mmut(uint32_t addr, uint32_t *a64, uint16_t val); +extern uint32_t readmemll_no_mmut(uint32_t addr, uint32_t *a64); +extern void writememll_no_mmut(uint32_t addr, uint32_t *a64, uint32_t val); -extern void do_mmutranslate(uint32_t addr, uint32_t *a64, int num, int write); +extern void do_mmutranslate(uint32_t addr, uint32_t *a64, int num, int write); -extern uint8_t *getpccache(uint32_t a); -extern uint64_t mmutranslatereal(uint32_t addr, int rw); -extern uint32_t mmutranslatereal32(uint32_t addr, int rw); -extern void addreadlookup(uint32_t virt, uint32_t phys); -extern void addwritelookup(uint32_t virt, uint32_t phys); +extern uint8_t readmembl_2386(uint32_t addr); +extern void writemembl_2386(uint32_t addr, uint8_t val); +extern uint16_t readmemwl_2386(uint32_t addr); +extern void writememwl_2386(uint32_t addr, uint16_t val); +extern uint32_t readmemll_2386(uint32_t addr); +extern void writememll_2386(uint32_t addr, uint32_t val); +extern uint64_t readmemql_2386(uint32_t addr); +extern void writememql_2386(uint32_t addr, uint64_t val); -extern void mem_mapping_set(mem_mapping_t *, - uint32_t base, - uint32_t size, - uint8_t (*read_b)(uint32_t addr, void *p), - uint16_t (*read_w)(uint32_t addr, void *p), - uint32_t (*read_l)(uint32_t addr, void *p), - void (*write_b)(uint32_t addr, uint8_t val, void *p), - void (*write_w)(uint32_t addr, uint16_t val, void *p), - void (*write_l)(uint32_t addr, uint32_t val, void *p), - uint8_t *exec, - uint32_t flags, - void *p); -extern void mem_mapping_add(mem_mapping_t *, - uint32_t base, - uint32_t size, - uint8_t (*read_b)(uint32_t addr, void *p), - uint16_t (*read_w)(uint32_t addr, void *p), - uint32_t (*read_l)(uint32_t addr, void *p), - void (*write_b)(uint32_t addr, uint8_t val, void *p), - void (*write_w)(uint32_t addr, uint16_t val, void *p), - void (*write_l)(uint32_t addr, uint32_t val, void *p), - uint8_t *exec, - uint32_t flags, - void *p); +extern uint8_t readmembl_no_mmut_2386(uint32_t addr, uint32_t a64); +extern void writemembl_no_mmut_2386(uint32_t addr, uint32_t a64, uint8_t val); +extern uint16_t readmemwl_no_mmut_2386(uint32_t addr, uint32_t *a64); +extern void writememwl_no_mmut_2386(uint32_t addr, uint32_t *a64, uint16_t val); +extern uint32_t readmemll_no_mmut_2386(uint32_t addr, uint32_t *a64); +extern void writememll_no_mmut_2386(uint32_t addr, uint32_t *a64, uint32_t val); -extern void mem_mapping_set_handler(mem_mapping_t *, - uint8_t (*read_b)(uint32_t addr, void *p), - uint16_t (*read_w)(uint32_t addr, void *p), - uint32_t (*read_l)(uint32_t addr, void *p), - void (*write_b)(uint32_t addr, uint8_t val, void *p), - void (*write_w)(uint32_t addr, uint16_t val, void *p), - void (*write_l)(uint32_t addr, uint32_t val, void *p)); +extern void do_mmutranslate_2386(uint32_t addr, uint32_t *a64, int num, int write); -extern void mem_mapping_set_p(mem_mapping_t *, void *p); +extern uint8_t *getpccache(uint32_t a); +extern uint64_t mmutranslatereal(uint32_t addr, int rw); +extern uint32_t mmutranslatereal32(uint32_t addr, int rw); +extern void addreadlookup(uint32_t virt, uint32_t phys); +extern void addwritelookup(uint32_t virt, uint32_t phys); -extern void mem_mapping_set_addr(mem_mapping_t *, - uint32_t base, uint32_t size); -extern void mem_mapping_set_exec(mem_mapping_t *, uint8_t *exec); -extern void mem_mapping_disable(mem_mapping_t *); -extern void mem_mapping_enable(mem_mapping_t *); -extern void mem_mapping_recalc(uint64_t base, uint64_t size); +extern void mem_mapping_set(mem_mapping_t *, + uint32_t base, + uint32_t size, + uint8_t (*read_b)(uint32_t addr, void *priv), + uint16_t (*read_w)(uint32_t addr, void *priv), + uint32_t (*read_l)(uint32_t addr, void *priv), + void (*write_b)(uint32_t addr, uint8_t val, void *priv), + void (*write_w)(uint32_t addr, uint16_t val, void *priv), + void (*write_l)(uint32_t addr, uint32_t val, void *priv), + uint8_t *exec, + uint32_t flags, + void *priv); +extern void mem_mapping_add(mem_mapping_t *, + uint32_t base, + uint32_t size, + uint8_t (*read_b)(uint32_t addr, void *priv), + uint16_t (*read_w)(uint32_t addr, void *priv), + uint32_t (*read_l)(uint32_t addr, void *priv), + void (*write_b)(uint32_t addr, uint8_t val, void *priv), + void (*write_w)(uint32_t addr, uint16_t val, void *priv), + void (*write_l)(uint32_t addr, uint32_t val, void *priv), + uint8_t *exec, + uint32_t flags, + void *priv); -extern void mem_set_access(uint8_t bitmap, int mode, uint32_t base, uint32_t size, uint16_t access); +extern void mem_mapping_set_handler(mem_mapping_t *, + uint8_t (*read_b)(uint32_t addr, void *priv), + uint16_t (*read_w)(uint32_t addr, void *priv), + uint32_t (*read_l)(uint32_t addr, void *priv), + void (*write_b)(uint32_t addr, uint8_t val, void *priv), + void (*write_w)(uint32_t addr, uint16_t val, void *priv), + void (*write_l)(uint32_t addr, uint32_t val, void *priv)); -extern uint8_t mem_readb_phys(uint32_t addr); -extern uint16_t mem_readw_phys(uint32_t addr); -extern uint32_t mem_readl_phys(uint32_t addr); -extern void mem_read_phys(void *dest, uint32_t addr, int tranfer_size); -extern void mem_writeb_phys(uint32_t addr, uint8_t val); -extern void mem_writew_phys(uint32_t addr, uint16_t val); -extern void mem_writel_phys(uint32_t addr, uint32_t val); -extern void mem_write_phys(void *src, uint32_t addr, int tranfer_size); +extern void mem_mapping_set_p(mem_mapping_t *, void *priv); -extern uint8_t mem_read_ram(uint32_t addr, void *priv); -extern uint16_t mem_read_ramw(uint32_t addr, void *priv); -extern uint32_t mem_read_raml(uint32_t addr, void *priv); -extern void mem_write_ram(uint32_t addr, uint8_t val, void *priv); -extern void mem_write_ramw(uint32_t addr, uint16_t val, void *priv); -extern void mem_write_raml(uint32_t addr, uint32_t val, void *priv); +extern void mem_mapping_set_addr(mem_mapping_t *, + uint32_t base, uint32_t size); +extern void mem_mapping_set_exec(mem_mapping_t *, uint8_t *exec); +extern void mem_mapping_set_mask(mem_mapping_t *, uint32_t mask); +extern void mem_mapping_disable(mem_mapping_t *); +extern void mem_mapping_enable(mem_mapping_t *); +extern void mem_mapping_recalc(uint64_t base, uint64_t size); -extern uint8_t mem_read_ram_2gb(uint32_t addr, void *priv); -extern uint16_t mem_read_ram_2gbw(uint32_t addr, void *priv); -extern uint32_t mem_read_ram_2gbl(uint32_t addr, void *priv); -extern void mem_write_ram_2gb(uint32_t addr, uint8_t val, void *priv); -extern void mem_write_ram_2gbw(uint32_t addr, uint16_t val, void *priv); -extern void mem_write_ram_2gbl(uint32_t addr, uint32_t val, void *priv); +extern void mem_set_access(uint8_t bitmap, int mode, uint32_t base, uint32_t size, uint16_t access); -extern int mem_addr_is_ram(uint32_t addr); +extern uint8_t mem_readb_phys(uint32_t addr); +extern uint16_t mem_readw_phys(uint32_t addr); +extern uint32_t mem_readl_phys(uint32_t addr); +extern void mem_read_phys(void *dest, uint32_t addr, int tranfer_size); +extern void mem_writeb_phys(uint32_t addr, uint8_t val); +extern void mem_writew_phys(uint32_t addr, uint16_t val); +extern void mem_writel_phys(uint32_t addr, uint32_t val); +extern void mem_write_phys(void *src, uint32_t addr, int tranfer_size); -extern uint64_t mmutranslate_noabrt(uint32_t addr, int rw); +extern uint8_t mem_read_ram(uint32_t addr, void *priv); +extern uint16_t mem_read_ramw(uint32_t addr, void *priv); +extern uint32_t mem_read_raml(uint32_t addr, void *priv); +extern void mem_write_ram(uint32_t addr, uint8_t val, void *priv); +extern void mem_write_ramw(uint32_t addr, uint16_t val, void *priv); +extern void mem_write_raml(uint32_t addr, uint32_t val, void *priv); -extern void mem_invalidate_range(uint32_t start_addr, uint32_t end_addr); +extern uint8_t mem_read_ram_2gb(uint32_t addr, void *priv); +extern uint16_t mem_read_ram_2gbw(uint32_t addr, void *priv); +extern uint32_t mem_read_ram_2gbl(uint32_t addr, void *priv); +extern void mem_write_ram_2gb(uint32_t addr, uint8_t val, void *priv); +extern void mem_write_ram_2gbw(uint32_t addr, uint16_t val, void *priv); +extern void mem_write_ram_2gbl(uint32_t addr, uint32_t val, void *priv); -extern void mem_write_ramb_page(uint32_t addr, uint8_t val, page_t *p); -extern void mem_write_ramw_page(uint32_t addr, uint16_t val, page_t *p); -extern void mem_write_raml_page(uint32_t addr, uint32_t val, page_t *p); -extern void mem_flush_write_page(uint32_t addr, uint32_t virt); +extern int mem_addr_is_ram(uint32_t addr); -extern void mem_reset_page_blocks(void); +extern uint64_t mmutranslate_noabrt(uint32_t addr, int rw); -extern void flushmmucache(void); -extern void flushmmucache_nopc(void); -extern void mmu_invalidate(uint32_t addr); +extern void mem_invalidate_range(uint32_t start_addr, uint32_t end_addr); -extern void mem_a20_init(void); -extern void mem_a20_recalc(void); +extern void mem_write_ramb_page(uint32_t addr, uint8_t val, page_t *page); +extern void mem_write_ramw_page(uint32_t addr, uint16_t val, page_t *page); +extern void mem_write_raml_page(uint32_t addr, uint32_t val, page_t *page); +extern void mem_flush_write_page(uint32_t addr, uint32_t virt); -extern void mem_init(void); -extern void mem_close(void); -extern void mem_reset(void); -extern void mem_remap_top(int kb); +extern void mem_reset_page_blocks(void); +extern void flushmmucache(void); +extern void flushmmucache_nopc(void); + +extern void mem_a20_init(void); +extern void mem_a20_recalc(void); + +extern void mem_init(void); +extern void mem_close(void); +extern void mem_reset(void); +extern void mem_remap_top(int kb); + +extern mem_mapping_t *read_mapping[MEM_MAPPINGS_NO]; +extern mem_mapping_t *write_mapping[MEM_MAPPINGS_NO]; #ifdef EMU_CPU_H -static __inline uint32_t get_phys(uint32_t addr) +static __inline uint32_t +get_phys(uint32_t addr) { uint64_t pa64; if (!((addr ^ get_phys_virt) & ~0xfff)) - return get_phys_phys | (addr & 0xfff); + return get_phys_phys | (addr & 0xfff); get_phys_virt = addr; - + if (!(cr0 >> 31)) { - get_phys_phys = (addr & rammask) & ~0xfff; - return addr & rammask; + get_phys_phys = (addr & rammask) & ~0xfff; + return addr & rammask; } if (((int) (readlookup2[addr >> 12])) != -1) - get_phys_phys = ((uintptr_t)readlookup2[addr >> 12] + (addr & ~0xfff)) - (uintptr_t)ram; + get_phys_phys = ((uintptr_t) readlookup2[addr >> 12] + (addr & ~0xfff)) - (uintptr_t) ram; else { - pa64 = mmutranslatereal(addr, 0); - if (pa64 > 0xffffffffULL) - get_phys_phys = 0xffffffff; - else - get_phys_phys = (uint32_t) pa64; - get_phys_phys = (get_phys_phys & rammask) & ~0xfff; - if (!cpu_state.abrt && mem_addr_is_ram(get_phys_phys)) - addreadlookup(get_phys_virt, get_phys_phys); + pa64 = mmutranslatereal(addr, 0); + if (pa64 > 0xffffffffULL) + get_phys_phys = 0xffffffff; + else + get_phys_phys = (uint32_t) pa64; + get_phys_phys = (get_phys_phys & rammask) & ~0xfff; + if (!cpu_state.abrt && mem_addr_is_ram(get_phys_phys)) + addreadlookup(get_phys_virt, get_phys_phys); } return get_phys_phys | (addr & 0xfff); } - -static __inline uint32_t get_phys_noabrt(uint32_t addr) +static __inline uint32_t +get_phys_noabrt(uint32_t addr) { uint64_t phys_addr; uint32_t phys_addr32; if (!(cr0 >> 31)) - return addr & rammask; + return addr & rammask; if (((int) (readlookup2[addr >> 12])) != -1) - return ((uintptr_t)readlookup2[addr >> 12] + addr) - (uintptr_t)ram; + return ((uintptr_t) readlookup2[addr >> 12] + addr) - (uintptr_t) ram; - phys_addr = mmutranslate_noabrt(addr, 0); + phys_addr = mmutranslate_noabrt(addr, 0); phys_addr32 = (uint32_t) phys_addr; - if ((phys_addr != 0xffffffffffffffffULL) && (phys_addr <= 0xffffffffULL) && - mem_addr_is_ram(phys_addr32 & rammask)) - addreadlookup(addr, phys_addr32 & rammask); + if ((phys_addr != 0xffffffffffffffffULL) && (phys_addr <= 0xffffffffULL) && mem_addr_is_ram(phys_addr32 & rammask)) + addreadlookup(addr, phys_addr32 & rammask); if (phys_addr > 0xffffffffULL) - phys_addr32 = 0xffffffff; + phys_addr32 = 0xffffffff; return phys_addr32; } #endif - -#endif /*EMU_MEM_H*/ +#endif /*EMU_MEM_H*/ diff --git a/src/include/86box/midi.h b/src/include/86box/midi.h index 155965b5a..97ed1f6ca 100644 --- a/src/include/86box/midi.h +++ b/src/include/86box/midi.h @@ -1,109 +1,116 @@ #ifndef EMU_SOUND_MIDI_H -# define EMU_SOUND_MIDI_H - +#define EMU_SOUND_MIDI_H #define SYSEX_SIZE 8192 extern uint8_t MIDI_InSysexBuf[SYSEX_SIZE]; extern uint8_t MIDI_evt_len[256]; -extern int midi_device_current; +extern int midi_output_device_current; extern int midi_input_device_current; -extern void (*input_msg)(void *p, uint8_t *msg, uint32_t len); -extern int (*input_sysex)(void *p, uint8_t *buf, uint32_t len, int abort); +extern void (*input_msg)(void *priv, uint8_t *msg, uint32_t len); +extern int (*input_sysex)(void *priv, uint8_t *buf, uint32_t len, int abort); extern void *midi_in_p; -extern int midi_device_available(int card); -extern int midi_in_device_available(int card); +extern int midi_out_device_available(int card); +extern int midi_in_device_available(int card); #ifdef EMU_DEVICE_H -const device_t *midi_device_getdevice(int card); +const device_t *midi_out_device_getdevice(int card); const device_t *midi_in_device_getdevice(int card); #endif -extern int midi_device_has_config(int card); -extern int midi_in_device_has_config(int card); -extern char * midi_device_get_internal_name(int card); -extern char * midi_in_device_get_internal_name(int card); -extern int midi_device_get_from_internal_name(char *s); -extern int midi_in_device_get_from_internal_name(char *s); -extern void midi_device_init(); -extern void midi_in_device_init(); +extern int midi_out_device_has_config(int card); +extern int midi_in_device_has_config(int card); +extern const char *midi_out_device_get_internal_name(int card); +extern const char *midi_in_device_get_internal_name(int card); +extern int midi_out_device_get_from_internal_name(char *s); +extern int midi_in_device_get_from_internal_name(char *s); +extern void midi_out_device_init(void); +extern void midi_in_device_init(void); - -typedef struct midi_device_t -{ +typedef struct midi_device_t { void (*play_sysex)(uint8_t *sysex, unsigned int len); void (*play_msg)(uint8_t *msg); - void (*poll)(); + void (*poll)(void); int (*write)(uint8_t val); } midi_device_t; -typedef struct midi_in_handler_t -{ +typedef struct midi_in_handler_t { uint8_t *buf; - int cnt; + int cnt; uint32_t len; - void (*msg)(void *p, uint8_t *msg, uint32_t len); - int (*sysex)(void *p, uint8_t *buffer, uint32_t len, int abort); - struct midi_in_handler_t *p; - struct midi_in_handler_t *prev, *next; + void (*msg)(void *priv, uint8_t *msg, uint32_t len); + int (*sysex)(void *priv, uint8_t *buffer, uint32_t len, int abort); + struct midi_in_handler_t *priv; + struct midi_in_handler_t *prev; + struct midi_in_handler_t *next; } midi_in_handler_t; -typedef struct midi_t -{ - uint8_t midi_rt_buf[8], midi_cmd_buf[8], - midi_status, midi_sysex_data[SYSEX_SIZE]; - int midi_cmd_pos, midi_cmd_len, midi_cmd_r, - midi_realtime, thruchan, midi_clockout; - unsigned int midi_sysex_start, midi_sysex_delay, - midi_pos; - midi_device_t *m_out_device, *m_in_device; +typedef struct midi_t { + uint8_t midi_rt_buf[8]; + uint8_t midi_cmd_buf[8]; + uint8_t midi_status; + uint8_t midi_sysex_data[SYSEX_SIZE]; + int midi_cmd_pos; + int midi_cmd_len; + int midi_cmd_r; + int midi_realtime; + int thruchan; + int midi_clockout; + unsigned int midi_sysex_start; + unsigned int midi_sysex_delay; + unsigned int midi_pos; + midi_device_t *m_out_device; + midi_device_t *m_in_device; } midi_t; -extern midi_t *midi, *midi_in; +extern midi_t *midi_out; +extern midi_t *midi_in; -extern void midi_init(midi_device_t* device); -extern void midi_in_init(midi_device_t* device, midi_t **mididev); -extern void midi_close(); -extern void midi_in_close(void); -extern void midi_raw_out_rt_byte(uint8_t val); -extern void midi_raw_out_thru_rt_byte(uint8_t val); -extern void midi_raw_out_byte(uint8_t val); -extern void midi_clear_buffer(void); -extern void midi_poll(); +extern void midi_out_init(midi_device_t *device); +extern void midi_in_init(midi_device_t *device, midi_t **mididev); +extern void midi_out_close(void); +extern void midi_in_close(void); +extern void midi_raw_out_rt_byte(uint8_t val); +extern void midi_raw_out_thru_rt_byte(uint8_t val); +extern void midi_raw_out_byte(uint8_t val); +extern void midi_clear_buffer(void); +extern void midi_poll(void); -extern void midi_in_handler(int set, void (*msg)(void *p, uint8_t *msg, uint32_t len), int (*sysex)(void *p, uint8_t *buffer, uint32_t len, int abort), void *p); -extern void midi_in_handlers_clear(void); -extern void midi_in_msg(uint8_t *msg, uint32_t len); -extern void midi_in_sysex(uint8_t *buffer, uint32_t len); +extern void midi_in_handler(int set, void (*msg)(void *priv, uint8_t *msg, uint32_t len), int (*sysex)(void *priv, uint8_t *buffer, uint32_t len, int abort), void *priv); +extern void midi_in_handlers_clear(void); +extern void midi_in_msg(uint8_t *msg, uint32_t len); +extern void midi_in_sysex(uint8_t *buffer, uint32_t len); #if 0 -#ifdef _WIN32 -#define SYSTEM_MIDI_NAME "Windows MIDI" -#define SYSTEM_MIDI_INTERNAL_NAME "windows_midi" +# ifdef _WIN32 +# define SYSTEM_MIDI_NAME "Windows MIDI" +# define SYSTEM_MIDI_INTERNAL_NAME "windows_midi" +# else +# define SYSTEM_MIDI_NAME "System MIDI" +# define SYSTEM_MIDI_INTERNAL_NAME "system_midi" +# endif #else -#define SYSTEM_MIDI_NAME "System MIDI" -#define SYSTEM_MIDI_INTERNAL_NAME "system_midi" -#endif -#else -#define SYSTEM_MIDI_NAME "System MIDI" -#define SYSTEM_MIDI_INTERNAL_NAME "system_midi" +# define SYSTEM_MIDI_NAME "System MIDI" +# define SYSTEM_MIDI_INTERNAL_NAME "system_midi" #endif -#define MIDI_INPUT_NAME "MIDI Input Device" +#define MIDI_INPUT_NAME "MIDI Input Device" #define MIDI_INPUT_INTERNAL_NAME "midi_in" #ifdef EMU_DEVICE_H -extern const device_t rtmidi_device; +extern const device_t rtmidi_output_device; extern const device_t rtmidi_input_device; -#ifdef USE_FLUIDSYNTH +# ifdef USE_FLUIDSYNTH extern const device_t fluidsynth_device; -#endif -#ifdef USE_MUNT -extern const device_t mt32_device; +# endif +# ifdef USE_MUNT +extern const device_t mt32_old_device; +extern const device_t mt32_new_device; extern const device_t cm32l_device; -#endif +extern const device_t cm32ln_device; +# endif #endif -#endif /*EMU_SOUND_MIDI_H*/ +#endif /*EMU_SOUND_MIDI_H*/ diff --git a/src/include/86box/midi_rtmidi.h b/src/include/86box/midi_rtmidi.h index beaccdf54..fb2074302 100644 --- a/src/include/86box/midi_rtmidi.h +++ b/src/include/86box/midi_rtmidi.h @@ -1,13 +1,17 @@ +#ifndef EMU_SOUND_RTMIDI_H +#define EMU_SOUND_RTMIDI_H + #ifdef __cplusplus -extern "C" -{ +extern "C" { #endif -extern int rtmidi_get_num_devs(void); -extern void rtmidi_get_dev_name(int num, char *s); -extern int rtmidi_in_get_num_devs(void); -extern void rtmidi_in_get_dev_name(int num, char *s); +extern int rtmidi_out_get_num_devs(void); +extern void rtmidi_out_get_dev_name(int num, char *s); +extern int rtmidi_in_get_num_devs(void); +extern void rtmidi_in_get_dev_name(int num, char *s); #ifdef __cplusplus } -#endif \ No newline at end of file +#endif + +#endif /*EMU_SOUND_RTMIDI*/ diff --git a/src/include/86box/mo.h b/src/include/86box/mo.h index caf5f2417..5d4b723f3 100644 --- a/src/include/86box/mo.h +++ b/src/include/86box/mo.h @@ -1,181 +1,208 @@ /* - * 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. + * 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. + * This file is part of the 86Box distribution. * - * Implementation of a generic Magneto-Optical Disk drive - * commands, for both ATAPI and SCSI usage. + * Implementation of a generic Magneto-Optical Disk drive + * commands, for both ATAPI and SCSI usage. * * * - * Authors: Natalia Portillo + * Authors: Natalia Portillo * Fred N. van Kempen, - * Miran Grca, + * Miran Grca, * - * Copyright 2020 Miran Grca. + * Copyright 2020 Miran Grca. */ + #ifndef EMU_MO_H #define EMU_MO_H - -#define MO_NUM 4 +#define MO_NUM 4 #define BUF_SIZE 32768 -#define MO_TIME 10.0 +#define MO_TIME 10.0 +#define MO_IMAGE_HISTORY 4 -typedef struct { - uint32_t sectors; - uint16_t bytes_per_sector; +typedef struct mo_type_t { + uint32_t sectors; + uint16_t bytes_per_sector; } mo_type_t; #define KNOWN_MO_TYPES 10 static const mo_type_t mo_types[KNOWN_MO_TYPES] = { - // 3.5" standard M.O. disks - { 248826, 512 }, - { 446325, 512 }, - { 1041500, 512 }, - { 310352, 2048 }, - { 605846, 2048 }, - { 1063146, 2048 }, - // 5.25" M.O. disks - {573624, 512 }, - {314568, 1024 }, - {904995, 512 }, - {637041, 1024 }, + // 3.5" standard M.O. disks + { 248826, 512 }, + { 446325, 512 }, + { 1041500, 512 }, + { 310352, 2048 }, + { 605846, 2048 }, + { 1063146, 2048 }, + // 5.25" M.O. disks + { 573624, 512 }, + { 314568, 1024 }, + { 904995, 512 }, + { 637041, 1024 }, }; -typedef struct -{ +typedef struct mo_drive_type_t { const char vendor[9]; const char model[16]; const char revision[5]; - int8_t supported_media[KNOWN_MO_TYPES]; + int8_t supported_media[KNOWN_MO_TYPES]; } mo_drive_type_t; #define KNOWN_MO_DRIVE_TYPES 22 static const mo_drive_type_t mo_drive_types[KNOWN_MO_DRIVE_TYPES] = { - {"86BOX", "MAGNETO OPTICAL", "1.00",{1, 1, 1, 1, 1, 1, 1, 1, 1, 1}}, - {"FUJITSU", "M2512A", "1314",{1, 1, 0, 0, 0, 0, 0, 0, 0}}, - {"FUJITSU", "M2513-MCC3064SS", "1.00",{1, 1, 1, 1, 0, 0, 0, 0, 0, 0}}, - {"FUJITSU", "MCE3130SS", "0070",{1, 1, 1, 1, 1, 0, 0, 0, 0, 0}}, - {"FUJITSU", "MCF3064SS", "0030",{1, 1, 1, 1, 0, 0, 0, 0, 0, 0}}, - {"FUJITSU", "MCJ3230UB-S", "0040",{1, 1, 1, 1, 1, 1, 0, 0, 0, 0}}, - {"HP", "S6300.65", "1.00",{0, 0, 0, 0, 0, 0, 1, 1, 0, 0}}, - {"HP", "C1716C", "1.00",{0, 0, 0, 0, 0, 0, 1, 1, 0, 1}}, - {"IBM", "0632AAA", "1.00",{0, 0, 0, 0, 0, 0, 1, 1, 0, 0}}, - {"IBM", "0632CHC", "1.00",{0, 0, 0, 0, 0, 0, 1, 1, 0, 1}}, - {"IBM", "0632CHX", "1.00",{0, 0, 0, 0, 0, 0, 1, 1, 0, 1}}, - {"IBM", "MD3125A", "1.00",{1, 0, 0, 0, 0, 0, 0, 0, 0, 0}}, - {"IBM", "MD3125B", "1.00",{1, 0, 0, 0, 0, 0, 0, 0, 0, 0}}, - {"IBM", "MTA-3127", "1.00",{1, 0, 0, 0, 0, 0, 0, 0, 0, 0}}, - {"IBM", "MTA-3230", "1.00",{1, 1, 0, 0, 0, 0, 0, 0, 0, 0}}, - {"MATSHITA", "LF-3000", "1.00",{1, 0, 0, 0, 0, 0, 0, 0, 0, 0}}, - {"MOST", "RMD-5100", "1.00",{1, 0, 0, 0, 0, 0, 0, 0, 0, 0}}, - {"RICOH", "RO-5031E", "1.00",{0, 0, 0, 0, 0, 0, 1, 1, 0, 0}}, - {"SONY", "SMO-C301", "1.00",{1, 0, 0, 0, 0, 0, 0, 0, 0, 0}}, - {"SONY", "SMO-C501", "1.00",{0, 0, 0, 0, 0, 0, 1, 1, 0, 0}}, - {"TEAC", "OD-3000", "1.00",{1, 0, 0, 0, 0, 0, 0, 0, 0, 0}}, - {"TOSHIBA", "OD-D300", "1.00",{1, 0, 0, 0, 0, 0, 0, 0, 0, 0}}, + {"86BOX", "MAGNETO OPTICAL", "1.00", { 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 }}, + { "FUJITSU", "M2512A", "1314", { 1, 1, 0, 0, 0, 0, 0, 0, 0, 0 }}, + { "FUJITSU", "M2513-MCC3064SS", "1.00", { 1, 1, 1, 1, 0, 0, 0, 0, 0, 0 }}, + { "FUJITSU", "MCE3130SS", "0070", { 1, 1, 1, 1, 1, 0, 0, 0, 0, 0 }}, + { "FUJITSU", "MCF3064SS", "0030", { 1, 1, 1, 1, 0, 0, 0, 0, 0, 0 }}, + { "FUJITSU", "MCJ3230UB-S", "0040", { 1, 1, 1, 1, 1, 1, 0, 0, 0, 0 }}, + { "HP", "S6300.65", "1.00", { 0, 0, 0, 0, 0, 0, 1, 1, 0, 0 }}, + { "HP", "C1716C", "1.00", { 0, 0, 0, 0, 0, 0, 1, 1, 0, 1 }}, + { "IBM", "0632AAA", "1.00", { 0, 0, 0, 0, 0, 0, 1, 1, 0, 0 }}, + { "IBM", "0632CHC", "1.00", { 0, 0, 0, 0, 0, 0, 1, 1, 0, 1 }}, + { "IBM", "0632CHX", "1.00", { 0, 0, 0, 0, 0, 0, 1, 1, 0, 1 }}, + { "IBM", "MD3125A", "1.00", { 1, 0, 0, 0, 0, 0, 0, 0, 0, 0 }}, + { "IBM", "MD3125B", "1.00", { 1, 0, 0, 0, 0, 0, 0, 0, 0, 0 }}, + { "IBM", "MTA-3127", "1.00", { 1, 0, 0, 0, 0, 0, 0, 0, 0, 0 }}, + { "IBM", "MTA-3230", "1.00", { 1, 1, 0, 0, 0, 0, 0, 0, 0, 0 }}, + { "MATSHITA", "LF-3000", "1.00", { 1, 0, 0, 0, 0, 0, 0, 0, 0, 0 }}, + { "MOST", "RMD-5100", "1.00", { 1, 0, 0, 0, 0, 0, 0, 0, 0, 0 }}, + { "RICOH", "RO-5031E", "1.00", { 0, 0, 0, 0, 0, 0, 1, 1, 0, 0 }}, + { "SONY", "SMO-C301", "1.00", { 1, 0, 0, 0, 0, 0, 0, 0, 0, 0 }}, + { "SONY", "SMO-C501", "1.00", { 0, 0, 0, 0, 0, 0, 1, 1, 0, 0 }}, + { "TEAC", "OD-3000", "1.00", { 1, 0, 0, 0, 0, 0, 0, 0, 0, 0 }}, + { "TOSHIBA", "OD-D300", "1.00", { 1, 0, 0, 0, 0, 0, 0, 0, 0, 0 }}, }; enum { MO_BUS_DISABLED = 0, - MO_BUS_ATAPI = 5, - MO_BUS_SCSI, - MO_BUS_USB + MO_BUS_ATAPI = 5, + MO_BUS_SCSI = 6, + MO_BUS_USB = 7 }; -typedef struct { - uint8_t id; +typedef struct mo_drive_t { + uint8_t id; union { - uint8_t res, res0, /* Reserved for other ID's. */ - res1, - ide_channel, scsi_device_id; + uint8_t res; + uint8_t res0; /* Reserved for other ID's. */ + uint8_t res1; + uint8_t ide_channel; + uint8_t scsi_device_id; }; - uint8_t bus_type, /* 0 = ATAPI, 1 = SCSI */ - bus_mode, /* Bit 0 = PIO suported; - Bit 1 = DMA supportd. */ - read_only, /* Struct variable reserved for - media status. */ - pad, pad0; + uint8_t bus_type; /* 0 = ATAPI, 1 = SCSI */ + uint8_t bus_mode; /* Bit 0 = PIO suported; + Bit 1 = DMA supportd. */ + uint8_t read_only; /* Struct variable reserved for + media status. */ + uint8_t pad; + uint8_t pad0; - FILE *f; - void *priv; + FILE *fp; + void *priv; - char image_path[1024], - prev_image_path[1024]; + char image_path[1024]; + char prev_image_path[1024]; - uint32_t type, medium_size, - base; - uint16_t sector_size; + char *image_history[MO_IMAGE_HISTORY]; + + uint32_t type; + uint32_t medium_size; + uint32_t base; + uint16_t sector_size; } mo_drive_t; -typedef struct { - mode_sense_pages_t ms_pages_saved; +typedef struct mo_t { + mode_sense_pages_t ms_pages_saved; mo_drive_t *drv; +#ifdef EMU_IDE_H + ide_tf_t * tf; +#else + void * tf; +#endif - uint8_t *buffer, - atapi_cdb[16], - current_cdb[16], - sense[256]; + uint8_t *buffer; + uint8_t atapi_cdb[16]; + uint8_t current_cdb[16]; + uint8_t sense[256]; - uint8_t status, phase, - error, id, - features, cur_lun, - pad0, pad1; +#ifdef ANCIENT_CODE + /* Task file. */ + uint8_t features; + uint8_t phase; + uint16_t request_length; + uint8_t status; + uint8_t error; + uint16_t pad; + uint32_t pos; +#endif - uint16_t request_length, max_transfer_len; + uint8_t id; + uint8_t cur_lun; + uint8_t pad0; + uint8_t pad1; - int requested_blocks, packet_status, - total_length, do_page_save, - unit_attention, request_pos, - old_len, pad3; + uint16_t max_transfer_len; + uint16_t pad2; - uint32_t sector_pos, sector_len, - packet_len, pos; + int requested_blocks; + int packet_status; + int total_length; + int do_page_save; + int unit_attention; + int request_pos; + int old_len; + int pad3; + + uint32_t sector_pos; + uint32_t sector_len; + uint32_t packet_len; double callback; } mo_t; - -extern mo_t *mo[MO_NUM]; -extern mo_drive_t mo_drives[MO_NUM]; -extern uint8_t atapi_mo_drives[8]; -extern uint8_t scsi_mo_drives[16]; +extern mo_t *mo[MO_NUM]; +extern mo_drive_t mo_drives[MO_NUM]; +#if 0 +extern uint8_t atapi_mo_drives[8]; +extern uint8_t scsi_mo_drives[16]; +#endif #define mo_sense_error dev->sense[0] -#define mo_sense_key dev->sense[2] -#define mo_asc dev->sense[12] -#define mo_ascq dev->sense[13] - +#define mo_sense_key dev->sense[2] +#define mo_asc dev->sense[12] +#define mo_ascq dev->sense[13] #ifdef __cplusplus extern "C" { #endif -extern void mo_disk_close(mo_t *dev); -extern void mo_disk_reload(mo_t *dev); -extern void mo_insert(mo_t *dev); +extern void mo_disk_close(mo_t *dev); +extern void mo_disk_reload(mo_t *dev); +extern void mo_insert(mo_t *dev); -extern void mo_global_init(void); -extern void mo_hard_reset(void); +extern void mo_global_init(void); +extern void mo_hard_reset(void); -extern void mo_reset(scsi_common_t *sc); -extern int mo_load(mo_t *dev, char *fn); -extern void mo_close(); +extern void mo_reset(scsi_common_t *sc); +extern int mo_load(mo_t *dev, char *fn); +extern void mo_close(void); #ifdef __cplusplus } #endif - -#endif /*EMU_MO_H*/ +#endif /*EMU_MO_H*/ diff --git a/src/include/86box/mouse.h b/src/include/86box/mouse.h index a3e192c46..3ed6b2126 100644 --- a/src/include/86box/mouse.h +++ b/src/include/86box/mouse.h @@ -1,92 +1,127 @@ /* - * 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. + * 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. + * This file is part of the 86Box distribution. * - * Definitions for the mouse driver. + * Definitions for the mouse driver. * * * - * Authors: Miran Grca, - * Fred N. van Kempen, + * Authors: Miran Grca, + * Fred N. van Kempen, * - * Copyright 2016-2019 Miran Grca. - * Copyright 2017-2019 Fred N. van Kempen. + * Copyright 2016-2019 Miran Grca. + * Copyright 2017-2019 Fred N. van Kempen. */ + #ifndef EMU_MOUSE_H -# define EMU_MOUSE_H +#define EMU_MOUSE_H - -#define MOUSE_TYPE_NONE 0 /* no mouse configured */ -#define MOUSE_TYPE_INTERNAL 1 /* machine has internal mouse */ -#define MOUSE_TYPE_LOGIBUS 2 /* Logitech/ATI Bus Mouse */ -#define MOUSE_TYPE_INPORT 3 /* Microsoft InPort Mouse */ -#if 0 -# define MOUSE_TYPE_GENIBUS 4 /* Genius Bus Mouse */ +#ifndef __cplusplus +/* Yes, a big no-no, but I'm saving myself time here. */ +#include #endif -#define MOUSE_TYPE_MSYSTEMS 5 /* Mouse Systems mouse */ -#define MOUSE_TYPE_MICROSOFT 6 /* Microsoft 2-button Serial Mouse */ -#define MOUSE_TYPE_MS3BUTTON 7 /* Microsoft 3-button Serial Mouse */ -#define MOUSE_TYPE_MSWHEEL 8 /* Microsoft Serial Wheel Mouse */ -#define MOUSE_TYPE_LOGITECH 9 /* Logitech 2-button Serial Mouse */ -#define MOUSE_TYPE_LT3BUTTON 10 /* Logitech 3-button Serial Mouse */ -#define MOUSE_TYPE_PS2 11 /* PS/2 series Bus Mouse */ -#define MOUSE_TYPE_ONBOARD 0x80 /* Mouse is an on-board version of one of the above. */ +#define MOUSE_TYPE_NONE 0 /* no mouse configured */ +#define MOUSE_TYPE_INTERNAL 1 /* achine has internal mouse */ +#define MOUSE_TYPE_LOGIBUS 2 /* Logitech/ATI Bus Mouse */ +#define MOUSE_TYPE_INPORT 3 /* Microsoft InPort Mouse */ +#if 0 +# define MOUSE_TYPE_GENIBUS 4 /* Genius Bus Mouse */ +#endif +#define MOUSE_TYPE_MSYSTEMS 5 /* Mouse Systems mouse */ +#define MOUSE_TYPE_MICROSOFT 6 /* Microsoft 2-button Serial Mouse */ +#define MOUSE_TYPE_MS3BUTTON 7 /* Microsoft 3-button Serial Mouse */ +#define MOUSE_TYPE_MSWHEEL 8 /* Microsoft Serial Wheel Mouse */ +#define MOUSE_TYPE_LOGITECH 9 /* Logitech 2-button Serial Mouse */ +#define MOUSE_TYPE_LT3BUTTON 10 /* Logitech 3-button Serial Mouse */ +#define MOUSE_TYPE_PS2 11 /* PS/2 series Bus Mouse */ +#define MOUSE_TYPE_WACOM 12 /* WACOM tablet */ +#define MOUSE_TYPE_WACOMARTP 13 /* WACOM tablet (ArtPad) */ + +#define MOUSE_TYPE_ONBOARD 0x80 /* Mouse is an on-board version of one of the above. */ #ifdef __cplusplus extern "C" { #endif -extern int mouse_type; -extern int mouse_x, mouse_y, mouse_z; -extern int mouse_buttons; - +extern int mouse_type; +extern int mouse_input_mode; /* 1 = Absolute, 0 = Relative */ +extern int mouse_timed; /* 1 = Timed, 0 = Constant */ +extern int mouse_tablet_in_proximity; +extern double mouse_x_abs; +extern double mouse_y_abs; +extern int tablet_tool_type; +extern double mouse_sensitivity; #ifdef EMU_DEVICE_H -extern const device_t *mouse_get_device(int mouse); -extern void *mouse_ps2_init(const device_t *); +extern void *mouse_ps2_init(const device_t *); -extern const device_t mouse_logibus_device; -extern const device_t mouse_logibus_onboard_device; -extern const device_t mouse_msinport_device; -#if 0 -extern const device_t mouse_genibus_device; -#endif -extern const device_t mouse_mssystems_device; -extern const device_t mouse_msserial_device; -extern const device_t mouse_ltserial_device; -extern const device_t mouse_ps2_device; +extern const device_t mouse_logibus_device; +extern const device_t mouse_logibus_onboard_device; +extern const device_t mouse_msinport_device; +# ifdef USE_GENIBUS +extern const device_t mouse_genibus_device; +# endif +extern const device_t mouse_mssystems_device; +extern const device_t mouse_msserial_device; +extern const device_t mouse_ltserial_device; +extern const device_t mouse_ps2_device; +extern const device_t mouse_wacom_device; +extern const device_t mouse_wacom_artpad_device; #endif -extern void mouse_init(void); -extern void mouse_close(void); -extern void mouse_reset(void); -extern void mouse_set_buttons(int buttons); -extern void mouse_process(void); -extern void mouse_set_poll(int (*f)(int,int,int,int,void *), void *); -extern void mouse_poll(void); +extern void mouse_clear_x(void); +extern void mouse_clear_y(void); +extern void mouse_clear_coords(void); +extern void mouse_clear_buttons(void); +extern void mouse_subtract_x(int *delta_x, int *o_x, int min, int max, int abs); +extern void mouse_subtract_y(int *delta_y, int *o_y, int min, int max, int invert, int abs); +extern void mouse_subtract_coords(int *delta_x, int *delta_y, int *o_x, int *o_y, + int min, int max, int invert, int abs); +extern int mouse_wheel_moved(void); +extern int mouse_moved(void); +extern int mouse_state_changed(void); +extern int mouse_mbut_changed(void); +extern void mouse_scale_fx(double x); +extern void mouse_scale_fy(double y); +extern void mouse_scale_x(int x); +extern void mouse_scale_y(int y); +extern void mouse_scalef(double x, double y); +extern void mouse_scale(int x, int y); +extern void mouse_set_z(int z); +extern void mouse_clear_z(void); +extern void mouse_subtract_z(int *delta_z, int min, int max, int invert); +extern void mouse_set_buttons_ex(int b); +extern int mouse_get_buttons_ex(void); +extern void mouse_set_sample_rate(double new_rate); +extern void mouse_set_buttons(int buttons); +extern void mouse_get_abs_coords(double *x_abs, double *y_abs); +extern void mouse_process(void); +extern void mouse_set_poll_ex(void (*poll_ex)(void)); +extern void mouse_set_poll(int (*f)(void *), void *); +extern const char * mouse_get_name(int mouse); +extern const char * mouse_get_internal_name(int mouse); +extern int mouse_get_from_internal_name(char *s); +extern int mouse_has_config(int mouse); +#ifdef EMU_DEVICE_H +extern const device_t *mouse_get_device(int mouse); +#endif +extern int mouse_get_buttons(void); +extern int mouse_get_ndev(void); +extern void mouse_set_raw(int raw); +extern void mouse_reset(void); +extern void mouse_close(void); +extern void mouse_init(void); -extern void mouse_bus_set_irq(void *priv, int irq); - - -extern char *mouse_get_name(int mouse); -extern char *mouse_get_internal_name(int mouse); -extern int mouse_get_from_internal_name(char *s); -extern int mouse_has_config(int mouse); -extern int mouse_get_type(int mouse); -extern int mouse_get_ndev(void); -extern int mouse_get_buttons(void); - -extern void mouse_clear_data(void *priv); +extern void mouse_bus_set_irq(void *priv, int irq); #ifdef __cplusplus } #endif - -#endif /*EMU_MOUSE_H*/ +#endif /*EMU_MOUSE_H*/ diff --git a/src/include/86box/net_3c501.h b/src/include/86box/net_3c501.h new file mode 100644 index 000000000..c55151ab8 --- /dev/null +++ b/src/include/86box/net_3c501.h @@ -0,0 +1,45 @@ +/* + * 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 Project. + * + * Implementation of the following network controller: + * - 3Com Etherlink 3c500/3c501 (ISA 8-bit). + * + * + * + * Based on @(#)Dev3C501.cpp Oracle (VirtualBox) + * + * Authors: TheCollector1995, + * Oracle + * + * Copyright 2022 TheCollector1995. + * Portions Copyright (C) 2022 Oracle and/or its affilitates. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the: + * + * Free Software Foundation, Inc. + * 59 Temple Place - Suite 330 + * Boston, MA 02111-1307 + * USA. + */ +#ifndef NET_3C501_H +#define NET_3C501_H + +extern const device_t threec501_device; + +#endif /*NET_3C501_H*/ diff --git a/src/include/86box/net_3c503.h b/src/include/86box/net_3c503.h index 6cc656b9f..44024850f 100644 --- a/src/include/86box/net_3c503.h +++ b/src/include/86box/net_3c503.h @@ -1,7 +1,49 @@ +/* + * 86Box A hypervisor and IBM PC system emulator that specializes in + * running old operating systems and software designed for IBM + * PC systems and compatibles from 1981 through fairly recent + * system designs based on the PCI bus. + * + * This file is part of the 86Box distribution. + * + * Implementation of the following network controllers: + * - 3Com Etherlink II 3c503 (ISA 8-bit). + * + * + * + * Based on @(#)3c503.cpp Carl (MAME) + * + * Authors: TheCollector1995, + * Miran Grca, + * Fred N. van Kempen, + * Carl, + * + * Copyright 2018 TheCollector1995. + * Copyright 2018 Miran Grca. + * Copyright 2017-2018 Fred N. van Kempen. + * Portions Copyright (C) 2018 MAME Project + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the: + * + * Free Software Foundation, Inc. + * 59 Temple Place - Suite 330 + * Boston, MA 02111-1307 + * USA. + */ #ifndef NET_3C503_H -# define NET_3C503_H +#define NET_3C503_H -extern const device_t threec503_device; +extern const device_t threec503_device; - -#endif /*NET_3C503_H*/ +#endif /*NET_3C503_H*/ diff --git a/src/include/86box/net_dp8390.h b/src/include/86box/net_dp8390.h index 1365f7ec8..e9e1e6c71 100644 --- a/src/include/86box/net_dp8390.h +++ b/src/include/86box/net_dp8390.h @@ -1,152 +1,153 @@ /* - * 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. + * 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. * - * Header of the emulation of the DP8390 Network Interface - * Controller used by the WD family, NE1000/NE2000 family, and - * 3Com 3C503 NIC's. + * Header of the emulation of the DP8390 Network Interface + * Controller used by the WD family, NE1000/NE2000 family, and + * 3Com 3C503 NIC's. * * * - * Authors: Miran Grca, - * Bochs project, + * Authors: Miran Grca, + * Bochs project, * - * Copyright 2016-2018 Miran Grca. - * Copyright 2008-2018 Bochs project. + * Copyright 2016-2018 Miran Grca. + * Copyright 2008-2018 Bochs project. */ + #ifndef NET_DP8390_H -# define NET_DP8390_H +#define NET_DP8390_H /* Never completely fill the ne2k ring so that we never hit the unclear completely full buffer condition. */ #define DP8390_NEVER_FULL_RING (1) -#define DP8390_DWORD_MEMSIZ (32*1024) -#define DP8390_DWORD_MEMSTART (16*1024) -#define DP8390_DWORD_MEMEND (DP8390_DWORD_MEMSTART+DP8390_DWORD_MEMSIZ) +#define DP8390_DWORD_MEMSIZ (32 * 1024) +#define DP8390_DWORD_MEMSTART (16 * 1024) +#define DP8390_DWORD_MEMEND (DP8390_DWORD_MEMSTART + DP8390_DWORD_MEMSIZ) -#define DP8390_WORD_MEMSIZ (16*1024) -#define DP8390_WORD_MEMSTART (8*1024) -#define DP8390_WORD_MEMEND (DP8390_WORD_MEMSTART+DP8390_WORD_MEMSIZ) +#define DP8390_WORD_MEMSIZ (16 * 1024) +#define DP8390_WORD_MEMSTART (8 * 1024) +#define DP8390_WORD_MEMEND (DP8390_WORD_MEMSTART + DP8390_WORD_MEMSIZ) -#define DP8390_FLAG_EVEN_MAC 0x01 -#define DP8390_FLAG_CHECK_CR 0x02 -#define DP8390_FLAG_CLEAR_IRQ 0x04 +#define DP8390_FLAG_EVEN_MAC 0x01 +#define DP8390_FLAG_CHECK_CR 0x02 +#define DP8390_FLAG_CLEAR_IRQ 0x04 -typedef struct { +typedef struct dp8390_t { /* Page 0 */ /* Command Register - 00h read/write */ struct CR_t { - int stop; /* STP - Software Reset command */ - int start; /* START - start the NIC */ - int tx_packet; /* TXP - initiate packet transmission */ - uint8_t rdma_cmd; /* RD0,RD1,RD2 - Remote DMA command */ - uint8_t pgsel; /* PS0,PS1 - Page select */ - } CR; + int stop; /* STP - Software Reset command */ + int start; /* START - start the NIC */ + int tx_packet; /* TXP - initiate packet transmission */ + uint8_t rdma_cmd; /* RD0,RD1,RD2 - Remote DMA command */ + uint8_t pgsel; /* PS0,PS1 - Page select */ + } CR; /* Interrupt Status Register - 07h read/write */ struct ISR_t { - int pkt_rx; /* PRX - packet received with no errors */ - int pkt_tx; /* PTX - packet txed with no errors */ - int rx_err; /* RXE - packet rxed with 1 or more errors */ - int tx_err; /* TXE - packet txed " " " " " */ - int overwrite; /* OVW - rx buffer resources exhausted */ - int cnt_oflow; /* CNT - network tally counter MSB's set */ - int rdma_done; /* RDC - remote DMA complete */ - int reset; /* RST - reset status */ - } ISR; + int pkt_rx; /* PRX - packet received with no errors */ + int pkt_tx; /* PTX - packet txed with no errors */ + int rx_err; /* RXE - packet rxed with 1 or more errors */ + int tx_err; /* TXE - packet txed " " " " " */ + int overwrite; /* OVW - rx buffer resources exhausted */ + int cnt_oflow; /* CNT - network tally counter MSB's set */ + int rdma_done; /* RDC - remote DMA complete */ + int reset; /* RST - reset status */ + } ISR; /* Interrupt Mask Register - 0fh write */ struct IMR_t { - int rx_inte; /* PRXE - packet rx interrupt enable */ - int tx_inte; /* PTXE - packet tx interrput enable */ - int rxerr_inte; /* RXEE - rx error interrupt enable */ - int txerr_inte; /* TXEE - tx error interrupt enable */ - int overw_inte; /* OVWE - overwrite warn int enable */ - int cofl_inte; /* CNTE - counter o'flow int enable */ - int rdma_inte; /* RDCE - remote DMA complete int enable */ - int reserved; /* D7 - reserved */ - } IMR; + int rx_inte; /* PRXE - packet rx interrupt enable */ + int tx_inte; /* PTXE - packet tx interrput enable */ + int rxerr_inte; /* RXEE - rx error interrupt enable */ + int txerr_inte; /* TXEE - tx error interrupt enable */ + int overw_inte; /* OVWE - overwrite warn int enable */ + int cofl_inte; /* CNTE - counter o'flow int enable */ + int rdma_inte; /* RDCE - remote DMA complete int enable */ + int reserved; /* D7 - reserved */ + } IMR; /* Data Configuration Register - 0eh write */ struct DCR_t { - int wdsize; /* WTS - 8/16-bit select */ - int endian; /* BOS - byte-order select */ - int longaddr; /* LAS - long-address select */ - int loop; /* LS - loopback select */ - int auto_rx; /* AR - auto-remove rx pkts with remote DMA */ - uint8_t fifo_size; /* FT0,FT1 - fifo threshold */ - } DCR; + int wdsize; /* WTS - 8/16-bit select */ + int endian; /* BOS - byte-order select */ + int longaddr; /* LAS - long-address select */ + int loop; /* LS - loopback select */ + int auto_rx; /* AR - auto-remove rx pkts with remote DMA */ + uint8_t fifo_size; /* FT0,FT1 - fifo threshold */ + } DCR; /* Transmit Configuration Register - 0dh write */ struct TCR_t { - int crc_disable; /* CRC - inhibit tx CRC */ - uint8_t loop_cntl; /* LB0,LB1 - loopback control */ - int ext_stoptx; /* ATD - allow tx disable by external mcast */ - int coll_prio; /* OFST - backoff algorithm select */ - uint8_t reserved; /* D5,D6,D7 - reserved */ - } TCR; + int crc_disable; /* CRC - inhibit tx CRC */ + uint8_t loop_cntl; /* LB0,LB1 - loopback control */ + int ext_stoptx; /* ATD - allow tx disable by external mcast */ + int coll_prio; /* OFST - backoff algorithm select */ + uint8_t reserved; /* D5,D6,D7 - reserved */ + } TCR; /* Transmit Status Register - 04h read */ struct TSR_t { - int tx_ok; /* PTX - tx complete without error */ - int reserved; /* D1 - reserved */ - int collided; /* COL - tx collided >= 1 times */ - int aborted; /* ABT - aborted due to excessive collisions */ - int no_carrier; /* CRS - carrier-sense lost */ - int fifo_ur; /* FU - FIFO underrun */ - int cd_hbeat; /* CDH - no tx cd-heartbeat from transceiver */ - int ow_coll; /* OWC - out-of-window collision */ - } TSR; + int tx_ok; /* PTX - tx complete without error */ + int reserved; /* D1 - reserved */ + int collided; /* COL - tx collided >= 1 times */ + int aborted; /* ABT - aborted due to excessive collisions */ + int no_carrier; /* CRS - carrier-sense lost */ + int fifo_ur; /* FU - FIFO underrun */ + int cd_hbeat; /* CDH - no tx cd-heartbeat from transceiver */ + int ow_coll; /* OWC - out-of-window collision */ + } TSR; /* Receive Configuration Register - 0ch write */ struct RCR_t { - int errors_ok; /* SEP - accept pkts with rx errors */ - int runts_ok; /* AR - accept < 64-byte runts */ - int broadcast; /* AB - accept eth broadcast address */ - int multicast; /* AM - check mcast hash array */ - int promisc; /* PRO - accept all packets */ - int monitor; /* MON - check pkts, but don't rx */ - uint8_t reserved; /* D6,D7 - reserved */ - } RCR; + int errors_ok; /* SEP - accept pkts with rx errors */ + int runts_ok; /* AR - accept < 64-byte runts */ + int broadcast; /* AB - accept eth broadcast address */ + int multicast; /* AM - check mcast hash array */ + int promisc; /* PRO - accept all packets */ + int monitor; /* MON - check pkts, but don't rx */ + uint8_t reserved; /* D6,D7 - reserved */ + } RCR; /* Receive Status Register - 0ch read */ struct RSR_t { - int rx_ok; /* PRX - rx complete without error */ - int bad_crc; /* CRC - Bad CRC detected */ - int bad_falign; /* FAE - frame alignment error */ - int fifo_or; /* FO - FIFO overrun */ - int rx_missed; /* MPA - missed packet error */ - int rx_mbit; /* PHY - unicast or mcast/bcast address match */ - int rx_disabled; /* DIS - set when in monitor mode */ - int deferred; /* DFR - collision active */ - } RSR; + int rx_ok; /* PRX - rx complete without error */ + int bad_crc; /* CRC - Bad CRC detected */ + int bad_falign; /* FAE - frame alignment error */ + int fifo_or; /* FO - FIFO overrun */ + int rx_missed; /* MPA - missed packet error */ + int rx_mbit; /* PHY - unicast or mcast/bcast address match */ + int rx_disabled; /* DIS - set when in monitor mode */ + int deferred; /* DFR - collision active */ + } RSR; - uint16_t local_dma; /* 01,02h read ; current local DMA addr */ - uint8_t page_start; /* 01h write ; page start regr */ - uint8_t page_stop; /* 02h write ; page stop regr */ - uint8_t bound_ptr; /* 03h read/write ; boundary pointer */ - uint8_t tx_page_start; /* 04h write ; transmit page start reg */ - uint8_t num_coll; /* 05h read ; number-of-collisions reg */ - uint16_t tx_bytes; /* 05,06h write ; transmit byte-count reg */ - uint8_t fifo; /* 06h read ; FIFO */ - uint16_t remote_dma; /* 08,09h read ; current remote DMA addr */ - uint16_t remote_start; /* 08,09h write ; remote start address reg */ - uint16_t remote_bytes; /* 0a,0bh write ; remote byte-count reg */ - uint8_t tallycnt_0; /* 0dh read ; tally ctr 0 (frame align errs) */ - uint8_t tallycnt_1; /* 0eh read ; tally ctr 1 (CRC errors) */ - uint8_t tallycnt_2; /* 0fh read ; tally ctr 2 (missed pkt errs) */ + uint16_t local_dma; /* 01,02h read ; current local DMA addr */ + uint8_t page_start; /* 01h write ; page start regr */ + uint8_t page_stop; /* 02h write ; page stop regr */ + uint8_t bound_ptr; /* 03h read/write ; boundary pointer */ + uint8_t tx_page_start; /* 04h write ; transmit page start reg */ + uint8_t num_coll; /* 05h read ; number-of-collisions reg */ + uint16_t tx_bytes; /* 05,06h write ; transmit byte-count reg */ + uint8_t fifo; /* 06h read ; FIFO */ + uint16_t remote_dma; /* 08,09h read ; current remote DMA addr */ + uint16_t remote_start; /* 08,09h write ; remote start address reg */ + uint16_t remote_bytes; /* 0a,0bh write ; remote byte-count reg */ + uint8_t tallycnt_0; /* 0dh read ; tally ctr 0 (frame align errs) */ + uint8_t tallycnt_1; /* 0eh read ; tally ctr 1 (CRC errors) */ + uint8_t tallycnt_2; /* 0fh read ; tally ctr 2 (missed pkt errs) */ /* Page 1 */ /* Command Register 00h (repeated) */ - uint8_t physaddr[6]; /* 01-06h read/write ; MAC address */ - uint8_t curr_page; /* 07h read/write ; current page register */ - uint8_t mchash[8]; /* 08-0fh read/write ; multicast hash array */ + uint8_t physaddr[6]; /* 01-06h read/write ; MAC address */ + uint8_t curr_page; /* 07h read/write ; current page register */ + uint8_t mchash[8]; /* 08-0fh read/write ; multicast hash array */ /* Page 2 - diagnostic use only */ @@ -161,55 +162,58 @@ typedef struct { * Data Configuration Register 0eh read (repeated) * Interrupt Mask Register 0fh read (repeated) */ - uint8_t rempkt_ptr; /* 03h read/write ; rmt next-pkt ptr */ - uint8_t localpkt_ptr; /* 05h read/write ; lcl next-pkt ptr */ - uint16_t address_cnt; /* 06,07h read/write ; address cter */ + uint8_t rempkt_ptr; /* 03h read/write ; rmt next-pkt ptr */ + uint8_t localpkt_ptr; /* 05h read/write ; lcl next-pkt ptr */ + uint16_t address_cnt; /* 06,07h read/write ; address cter */ /* Page 3 - should never be modified. */ /* DP8390 memory */ - uint8_t *mem; /* on-chip packet memory */ + uint8_t *mem; /* on-chip packet memory */ - uint8_t macaddr[32]; /* ASIC ROM'd MAC address, even bytes */ - uint8_t macaddr_size, /* Defaults to 16 but can be 32 */ - flags, /* Flags affecting some behaviors. */ - id0, /* 0x50 for the Realtek NIC's, otherwise - 0xFF. */ - id1; /* 0x70 for the RTL8019AS, 0x43 for the - RTL8029AS, otherwise 0xFF. */ - int mem_size, mem_start, mem_end; + uint8_t macaddr[32]; /* ASIC ROM'd MAC address, even bytes */ + uint8_t macaddr_size, /* Defaults to 16 but can be 32 */ + flags, /* Flags affecting some behaviors. */ + id0, /* 0x50 for the Realtek NIC's, otherwise + 0xFF. */ + id1; /* 0x70 for the RTL8019AS, 0x43 for the + RTL8029AS, otherwise 0xFF. */ + uint32_t mem_size; + uint32_t mem_start; + uint32_t mem_end; + uint32_t mem_wrap; - int tx_timer_index; - int tx_timer_active; + int tx_timer_index; + int tx_timer_active; - void *priv; + void *priv; + netcard_t *card; - void (*interrupt)(void *priv, int set); + void (*interrupt)(void *priv, int set); } dp8390_t; -extern const device_t dp8390_device; +extern const device_t dp8390_device; +extern int dp3890_inst; +extern uint32_t dp8390_chipmem_read(dp8390_t *dev, uint32_t addr, unsigned int len); +extern void dp8390_chipmem_write(dp8390_t *dev, uint32_t addr, uint32_t val, unsigned len); -extern uint32_t dp8390_chipmem_read(dp8390_t *dev, uint32_t addr, unsigned int len); -extern void dp8390_chipmem_write(dp8390_t *dev, uint32_t addr, uint32_t val, unsigned len); +extern uint32_t dp8390_read_cr(dp8390_t *dev); +extern void dp8390_write_cr(dp8390_t *dev, uint32_t val); -extern uint32_t dp8390_read_cr(dp8390_t *dev); -extern void dp8390_write_cr(dp8390_t *dev, uint32_t val); +extern int dp8390_rx(void *priv, uint8_t *buf, int io_len); -extern int dp8390_rx(void *priv, uint8_t *buf, int io_len); - -extern uint32_t dp8390_page0_read(dp8390_t *dev, uint32_t off, unsigned int len); -extern void dp8390_page0_write(dp8390_t *dev, uint32_t off, uint32_t val, unsigned len); -extern uint32_t dp8390_page1_read(dp8390_t *dev, uint32_t off, unsigned int len); -extern void dp8390_page1_write(dp8390_t *dev, uint32_t off, uint32_t val, unsigned len); -extern uint32_t dp8390_page2_read(dp8390_t *dev, uint32_t off, unsigned int len); -extern void dp8390_page2_write(dp8390_t *dev, uint32_t off, uint32_t val, unsigned len); - -extern void dp8390_set_defaults(dp8390_t *dev, uint8_t flags); -extern void dp8390_mem_alloc(dp8390_t *dev, uint32_t start, uint32_t size); -extern void dp8390_set_id(dp8390_t *dev, uint8_t id0, uint8_t id1); -extern void dp8390_reset(dp8390_t *dev); -extern void dp8390_soft_reset(dp8390_t *dev); +extern uint32_t dp8390_page0_read(dp8390_t *dev, uint32_t off, unsigned int len); +extern void dp8390_page0_write(dp8390_t *dev, uint32_t off, uint32_t val, unsigned len); +extern uint32_t dp8390_page1_read(dp8390_t *dev, uint32_t off, unsigned int len); +extern void dp8390_page1_write(dp8390_t *dev, uint32_t off, uint32_t val, unsigned len); +extern uint32_t dp8390_page2_read(dp8390_t *dev, uint32_t off, unsigned int len); +extern void dp8390_page2_write(dp8390_t *dev, uint32_t off, uint32_t val, unsigned len); +extern void dp8390_set_defaults(dp8390_t *dev, uint8_t flags); +extern void dp8390_mem_alloc(dp8390_t *dev, uint32_t start, uint32_t size); +extern void dp8390_set_id(dp8390_t *dev, uint8_t id0, uint8_t id1); +extern void dp8390_reset(dp8390_t *dev); +extern void dp8390_soft_reset(dp8390_t *dev); #endif /*NET_DP8390_H*/ diff --git a/src/include/86box/net_event.h b/src/include/86box/net_event.h new file mode 100644 index 000000000..48580a359 --- /dev/null +++ b/src/include/86box/net_event.h @@ -0,0 +1,22 @@ +#ifndef EMU_NET_EVENT_H +#define EMU_NET_EVENT_H + +typedef struct net_evt_t { +#ifdef _WIN32 + HANDLE handle; +#else + int fds[2]; +#endif +} net_evt_t; + +extern void net_event_init(net_evt_t *event); +extern void net_event_set(net_evt_t *event); +extern void net_event_clear(net_evt_t *event); +extern void net_event_close(net_evt_t *event); +#ifdef _WIN32 +extern HANDLE net_event_get_handle(net_evt_t *event); +#else +extern int net_event_get_fd(net_evt_t *event); +#endif + +#endif \ No newline at end of file diff --git a/src/include/86box/net_ne2000.h b/src/include/86box/net_ne2000.h index b2581e98e..350668ccb 100644 --- a/src/include/86box/net_ne2000.h +++ b/src/include/86box/net_ne2000.h @@ -1,18 +1,18 @@ /* - * VARCem Virtual ARchaeological Computer EMulator. - * An emulator of (mostly) x86-based PC systems and devices, - * using the ISA,EISA,VLB,MCA and PCI system buses, roughly - * spanning the era between 1981 and 1995. + * 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 VARCem Project. + * This file is part of the 86Box distribution. * - * Definitions for the NE2000 ethernet controller. + * Definitions for the NE2000 ethernet controller. * * * - * Authors: Fred N. van Kempen, + * Authors: Fred N. van Kempen, * - * Copyright 2017,2018 Fred N. van Kempen. + * Copyright 2017-2018 Fred N. van Kempen. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -32,25 +32,23 @@ * Boston, MA 02111-1307 * USA. */ -#ifndef NET_NE2000_H -# define NET_NE2000_H +#ifndef NET_NE2000_H +#define NET_NE2000_H enum { - NE2K_NONE = 0, - NE2K_NE1000 = 1, /* 8-bit ISA NE1000 */ - NE2K_NE2000 = 2, /* 16-bit ISA NE2000 */ - NE2K_ETHERNEXT_MC = 3, /* 16-bit MCA EtherNext/MC */ - NE2K_RTL8019AS = 4, /* 16-bit ISA PnP Realtek 8019AS */ - NE2K_RTL8029AS = 5 /* 32-bit PCI Realtek 8029AS */ + NE2K_NONE = 0, + NE2K_NE1000 = 1, /* 8-bit ISA NE1000 */ + NE2K_NE2000 = 2, /* 16-bit ISA NE2000 */ + NE2K_ETHERNEXT_MC = 3, /* 16-bit MCA EtherNext/MC */ + NE2K_RTL8019AS = 4, /* 16-bit ISA PnP Realtek 8019AS */ + NE2K_RTL8029AS = 5 /* 32-bit PCI Realtek 8029AS */ }; +extern const device_t ne1000_device; +extern const device_t ne2000_device; +extern const device_t ethernext_mc_device; +extern const device_t rtl8019as_device; +extern const device_t rtl8029as_device; -extern const device_t ne1000_device; -extern const device_t ne2000_device; -extern const device_t ethernext_mc_device; -extern const device_t rtl8019as_device; -extern const device_t rtl8029as_device; - - -#endif /*NET_NE2000_H*/ +#endif /*NET_NE2000_H*/ diff --git a/src/include/86box/net_pcnet.h b/src/include/86box/net_pcnet.h index 651a62198..ccdc7e832 100644 --- a/src/include/86box/net_pcnet.h +++ b/src/include/86box/net_pcnet.h @@ -1,40 +1,40 @@ /* - * 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. + * 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. * - * Emulation of the AMD PCnet LANCE NIC controller for both the ISA - * and PCI buses. + * Emulation of the AMD PCnet LANCE NIC controller for both the ISA + * and PCI buses. * * * - * Authors: Miran Grca, - * TheCollector1995, - * Antony T Curtis + * Authors: Miran Grca, + * TheCollector1995, + * Antony T Curtis * - * Copyright 2004-2019 Antony T Curtis - * Copyright 2016-2019 Miran Grca. + * Copyright 2004-2019 Antony T Curtis + * Copyright 2016-2019 Miran Grca. */ + #ifndef NET_PCNET_H -# define NET_PCNET_H +#define NET_PCNET_H enum { - DEV_NONE = 0, - DEV_AM79C960 = 1, /* PCnet-ISA (ISA, 10 Mbps, NE2100/NE1500T compatible) */ + DEV_NONE = 0, + DEV_AM79C960 = 1, /* PCnet-ISA (ISA, 10 Mbps, NE2100/NE1500T compatible) */ DEV_AM79C960_EB = 2, /* PCnet-ISA (ISA, 10 Mbps, Racal InterLan EtherBlaster compatible) */ DEV_AM79C960_VLB = 3, /* PCnet-VLB (VLB, 10 Mbps, NE2100/NE1500T compatible) */ - DEV_AM79C961 = 4, /* PCnet-ISA+ (ISA, 10 Mbps, NE2100/NE1500T compatible, Plug and Play) */ - DEV_AM79C970A = 5, /* PCnet-PCI II (PCI, 10 Mbps) */ - DEV_AM79C973 = 6 /* PCnet-FAST III (PCI, 10/100 Mbps) */ + DEV_AM79C961 = 4, /* PCnet-ISA+ (ISA, 10 Mbps, NE2100/NE1500T compatible, Plug and Play) */ + DEV_AM79C970A = 5, /* PCnet-PCI II (PCI, 10 Mbps) */ + DEV_AM79C973 = 6 /* PCnet-FAST III (PCI, 10/100 Mbps) */ }; +extern const device_t pcnet_am79c960_device; +extern const device_t pcnet_am79c960_eb_device; +extern const device_t pcnet_am79c960_vlb_device; +extern const device_t pcnet_am79c961_device; +extern const device_t pcnet_am79c970a_device; +extern const device_t pcnet_am79c973_device; -extern const device_t pcnet_am79c960_device; -extern const device_t pcnet_am79c960_eb_device; -extern const device_t pcnet_am79c960_vlb_device; -extern const device_t pcnet_am79c961_device; -extern const device_t pcnet_am79c970a_device; -extern const device_t pcnet_am79c973_device; - -#endif /*NET_PCNET_H*/ +#endif /*NET_PCNET_H*/ diff --git a/src/include/86box/net_plip.h b/src/include/86box/net_plip.h index d45b80091..83c33e4c6 100644 --- a/src/include/86box/net_plip.h +++ b/src/include/86box/net_plip.h @@ -1,24 +1,26 @@ /* - * 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. + * 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. + * This file is part of the 86Box distribution. * - * Definitions for the PLIP parallel port network device. + * Definitions for the PLIP parallel port network device. * * * - * Author: RichardG, - * Copyright 2020 RichardG. + * Authors: RichardG, + * + * Copyright 2020 RichardG. */ + #ifndef NET_PLIP_H -# define NET_PLIP_H -# include <86box/device.h> -# include <86box/lpt.h> +#define NET_PLIP_H +#include <86box/device.h> +#include <86box/lpt.h> extern const lpt_device_t lpt_plip_device; -extern const device_t plip_device; +extern const device_t plip_device; #endif /*NET_PLIP_H*/ diff --git a/src/include/86box/net_wd8003.h b/src/include/86box/net_wd8003.h index 5b6e2113e..726510cdb 100644 --- a/src/include/86box/net_wd8003.h +++ b/src/include/86box/net_wd8003.h @@ -1,26 +1,26 @@ /* - * 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. + * 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. + * This file is part of the 86Box distribution. * - * Implementation of the following network controllers: - * - SMC/WD 8003E (ISA 8-bit); - * - SMC/WD 8013EBT (ISA 16-bit); - * - SMC/WD 8013EP/A (MCA). + * Implementation of the following network controllers: + * - SMC/WD 8003E (ISA 8-bit); + * - SMC/WD 8013EBT (ISA 16-bit); + * - SMC/WD 8013EP/A (MCA). * * * - * Authors: Fred N. van Kempen, - * TheCollector1995, - * Miran Grca, - * Peter Grehan, + * Authors: Fred N. van Kempen, + * TheCollector1995, + * Miran Grca, + * Peter Grehan, * - * Copyright 2017,2018 Fred N. van Kempen. - * Copyright 2016-2018 Miran Grca. - * Portions Copyright (C) 2002 MandrakeSoft S.A. + * Copyright 2017-2018 Fred N. van Kempen. + * Copyright 2016-2018 Miran Grca. + * Portions Copyright (C) 2002 MandrakeSoft S.A. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -40,22 +40,25 @@ * Boston, MA 02111-1307 * USA. */ + #ifndef NET_WD8003_H -# define NET_WD8003_H +#define NET_WD8003_H enum { - WD_NONE = 0, - WD8003E, /* WD8003E : 8-bit ISA, no interface chip */ - WD8003EB, /* WD8003EB : 8-bit ISA, 5x3 interface chip */ - WD8013EBT, /* WD8013EBT : 16-bit ISA, no interface chip */ - WD8003ETA, /* WD8003ET/A: 16-bit MCA, no interface chip */ - WD8003EA /* WD8003E/A : 16-bit MCA, 5x3 interface chip */ + WD_NONE = 0, + WD8003E = 1, /* WD8003E : 8-bit ISA, no interface chip */ + WD8003EB = 2, /* WD8003EB : 8-bit ISA, 5x3 interface chip */ + WD8013EBT = 3, /* WD8013EBT : 16-bit ISA, no interface chip */ + WD8003ETA = 4, /* WD8003ET/A: 16-bit MCA, no interface chip */ + WD8003EA = 5, /* WD8003E/A : 16-bit MCA, 5x3 interface chip */ + WD8013EPA = 6 }; -extern const device_t wd8003e_device; -extern const device_t wd8003eb_device; -extern const device_t wd8013ebt_device; -extern const device_t wd8003eta_device; -extern const device_t wd8003ea_device; +extern const device_t wd8003e_device; +extern const device_t wd8003eb_device; +extern const device_t wd8013ebt_device; +extern const device_t wd8003eta_device; +extern const device_t wd8003ea_device; +extern const device_t wd8013epa_device; -#endif /*NET_WD8003_H*/ +#endif /*NET_WD8003_H*/ diff --git a/src/include/86box/network.h b/src/include/86box/network.h index 015eb6a34..e9b703ee0 100644 --- a/src/include/86box/network.h +++ b/src/include/86box/network.h @@ -1,36 +1,34 @@ /* - * VARCem Virtual ARchaeological Computer EMulator. - * An emulator of (mostly) x86-based PC systems and devices, - * using the ISA,EISA,VLB,MCA and PCI system buses, roughly - * spanning the era between 1981 and 1995. + * VARCem Virtual ARchaeological Computer EMulator. + * An emulator of (mostly) x86-based PC systems and devices, + * using the ISA,EISA,VLB,MCA and PCI system buses, roughly + * spanning the era between 1981 and 1995. * - * This file is part of the VARCem Project. - * - * Definitions for the network module. + * Definitions for the network module. * * * - * Author: Fred N. van Kempen, + * Authors: Fred N. van Kempen, * - * Copyright 2017-2019 Fred N. van Kempen. + * Copyright 2017-2019 Fred N. van Kempen. * - * Redistribution and use in source and binary forms, with - * or without modification, are permitted provided that the - * following conditions are met: + * Redistribution and use in source and binary forms, with + * or without modification, are permitted provided that the + * following conditions are met: * - * 1. Redistributions of source code must retain the entire - * above notice, this list of conditions and the following - * disclaimer. + * 1. Redistributions of source code must retain the entire + * above notice, this list of conditions and the following + * disclaimer. * - * 2. Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the - * following disclaimer in the documentation and/or other - * materials provided with the distribution. + * 2. Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the + * following disclaimer in the documentation and/or other + * materials provided with the distribution. * - * 3. Neither the name of the copyright holder nor the names - * of its contributors may be used to endorse or promote - * products derived from this software without specific - * prior written permission. + * 3. Neither the name of the copyright holder nor the names + * of its contributors may be used to endorse or promote + * products derived from this software without specific + * prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT @@ -44,108 +42,164 @@ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -#ifndef EMU_NETWORK_H -# define EMU_NETWORK_H -# include +#ifndef EMU_NETWORK_H +#define EMU_NETWORK_H +#include /* Network provider types. */ -#define NET_TYPE_NONE 0 /* networking disabled */ -#define NET_TYPE_PCAP 1 /* use the (Win)Pcap API */ -#define NET_TYPE_SLIRP 2 /* use the SLiRP port forwarder */ +#define NET_TYPE_NONE 0 /* use the null network driver */ +#define NET_TYPE_SLIRP 1 /* use the SLiRP port forwarder */ +#define NET_TYPE_PCAP 2 /* use the (Win)Pcap API */ +#define NET_TYPE_VDE 3 /* use the VDE plug API */ + +#define NET_MAX_FRAME 1518 +/* Queue size must be a power of 2 */ +#define NET_QUEUE_LEN 16 +#define NET_QUEUE_LEN_MASK (NET_QUEUE_LEN - 1) +#define NET_QUEUE_COUNT 3 +#define NET_CARD_MAX 4 +#define NET_HOST_INTF_MAX 64 + +#define NET_PERIOD_10M 0.8 +#define NET_PERIOD_100M 0.08 + +/* Error buffers for network driver init */ +#define NET_DRV_ERRBUF_SIZE 384 -/* Supported network cards. */ enum { - NONE = 0, - NE1000, - NE2000, - RTL8019AS, - RTL8029AS + NET_LINK_DOWN = (1 << 1), + NET_LINK_TEMP_DOWN = (1 << 2), + NET_LINK_10_HD = (1 << 3), + NET_LINK_10_FD = (1 << 4), + NET_LINK_100_HD = (1 << 5), + NET_LINK_100_FD = (1 << 6), + NET_LINK_1000_HD = (1 << 7), + NET_LINK_1000_FD = (1 << 8), }; +enum { + NET_NONE = 0, + NET_INTERNAL +}; + +enum { + NET_QUEUE_RX = 0, + NET_QUEUE_TX_VM = 1, + NET_QUEUE_TX_HOST = 2 +}; + +typedef struct netcard_conf_t { + uint16_t device_num; + int net_type; + char host_dev_name[128]; + uint32_t link_state; +} netcard_conf_t; + +extern netcard_conf_t net_cards_conf[NET_CARD_MAX]; +extern uint16_t net_card_current; typedef int (*NETRXCB)(void *, uint8_t *, int); -typedef int (*NETWAITCB)(void *); -typedef int (*NETSETLINKSTATE)(void *); - +typedef int (*NETSETLINKSTATE)(void *, uint32_t link_state); typedef struct netpkt { - void *priv; - uint8_t data[65536]; /* Maximum length + 1 to round up to the nearest power of 2. */ - int len; - - struct netpkt *prev, *next; + uint8_t *data; + int len; } netpkt_t; -typedef struct { - const device_t *device; - void *priv; - int (*poll)(void *); - NETRXCB rx; - NETWAITCB wait; - NETSETLINKSTATE set_link_state; -} netcard_t; +typedef struct netqueue_t { + netpkt_t packets[NET_QUEUE_LEN]; + int head; + int tail; +} netqueue_t; + +typedef struct _netcard_t netcard_t; + +typedef struct netdrv_t { + void (*notify_in)(void *priv); + void *(*init)(const netcard_t *card, const uint8_t *mac_addr, void *priv, char *netdrv_errbuf); + void (*close)(void *priv); + void *priv; +} netdrv_t; + +extern const netdrv_t net_pcap_drv; +extern const netdrv_t net_slirp_drv; +extern const netdrv_t net_vde_drv; +extern const netdrv_t net_null_drv; + +struct _netcard_t { + const device_t *device; + void *card_drv; + struct netdrv_t host_drv; + NETRXCB rx; + NETSETLINKSTATE set_link_state; + netqueue_t queues[NET_QUEUE_COUNT]; + netpkt_t queued_pkt; + mutex_t *tx_mutex; + mutex_t *rx_mutex; + pc_timer_t timer; + uint16_t card_num; + double byte_period; + uint32_t led_timer; + uint32_t led_state; + uint32_t link_state; +}; typedef struct { - char device[128]; - char description[128]; + char device[128]; + char description[128]; } netdev_t; +typedef struct { + int has_slirp; + int has_pcap; + int has_vde; +} network_devmap_t; + + +#define HAS_NOSLIRP_NET(x) (x.has_pcap || x.has_vde) #ifdef __cplusplus extern "C" { #endif /* Global variables. */ -extern int nic_do_log; /* config */ -extern int network_ndev; -extern int network_rx_pause; -extern netdev_t network_devs[32]; +extern int nic_do_log; // config +extern network_devmap_t network_devmap; +extern int network_ndev; // Number of pcap devices +extern network_devmap_t network_devmap; // Bitmap of available network types +extern netdev_t network_devs[NET_HOST_INTF_MAX]; /* Function prototypes. */ -extern void network_wait(uint8_t wait); -extern void network_poll(void); -extern void network_busy(uint8_t set); -extern void network_end(void); +extern void network_init(void); +extern netcard_t *network_attach(void *card_drv, uint8_t *mac, NETRXCB rx, NETSETLINKSTATE set_link_state); +extern void netcard_close(netcard_t *card); +extern void network_close(void); +extern void network_reset(void); +extern int network_available(void); +extern void network_tx(netcard_t *card, uint8_t *, int); -extern void network_init(void); -extern void network_attach(void *, uint8_t *, NETRXCB, NETWAITCB, NETSETLINKSTATE); -extern void network_close(void); -extern void network_reset(void); -extern int network_available(void); -extern void network_tx(uint8_t *, int); -extern void network_do_tx(void); -extern int network_tx_queue_check(void); +extern int net_pcap_prepare(netdev_t *); +extern int net_vde_prepare(void); -extern int net_pcap_prepare(netdev_t *); -extern int net_pcap_init(void); -extern int net_pcap_reset(const netcard_t *, uint8_t *); -extern void net_pcap_close(void); -extern void net_pcap_in(uint8_t *, int); -extern int net_slirp_init(void); -extern int net_slirp_reset(const netcard_t *, uint8_t *); -extern void net_slirp_close(void); -extern void net_slirp_in(uint8_t *, int); - -extern int network_dev_to_id(char *); -extern int network_card_available(int); -extern int network_card_has_config(int); -extern char *network_card_get_internal_name(int); -extern int network_card_get_from_internal_name(char *); -extern const device_t *network_card_getdevice(int); - -extern void network_set_wait(int wait); -extern int network_get_wait(void); - -extern void network_timer_stop(void); - -extern void network_queue_put(int tx, void *priv, uint8_t *data, int len); +extern void network_connect(int id, int connect); +extern int network_is_connected(int id); +extern int network_dev_available(int); +extern int network_dev_to_id(char *); +extern int network_card_available(int); +extern int network_card_has_config(int); +extern const char *network_card_get_internal_name(int); +extern int network_card_get_from_internal_name(char *); +extern const device_t *network_card_getdevice(int); +extern int network_tx_pop(netcard_t *card, netpkt_t *out_pkt); +extern int network_tx_popv(netcard_t *card, netpkt_t *pkt_vec, int vec_size); +extern int network_rx_put(netcard_t *card, uint8_t *bufp, int len); +extern int network_rx_put_pkt(netcard_t *card, netpkt_t *pkt); #ifdef __cplusplus } #endif - -#endif /*EMU_NETWORK_H*/ +#endif /*EMU_NETWORK_H*/ diff --git a/src/include/86box/nmi.h b/src/include/86box/nmi.h index 72c2f507f..79aa68346 100644 --- a/src/include/86box/nmi.h +++ b/src/include/86box/nmi.h @@ -1,11 +1,16 @@ /* Copyright holders: Sarah Walker see COPYING for more details */ + +#ifndef EMU_NMI_H +#define EMU_NMI_H + extern int nmi_mask; extern int nmi; extern int nmi_auto_clear; - extern void nmi_init(void); -extern void nmi_write(uint16_t port, uint8_t val, void *p); +extern void nmi_write(uint16_t port, uint8_t val, void *priv); + +#endif /*EMU_NMI_H*/ diff --git a/src/include/86box/nvr.h b/src/include/86box/nvr.h index b841d7e6a..d24ca903c 100644 --- a/src/include/86box/nvr.h +++ b/src/include/86box/nvr.h @@ -1,130 +1,134 @@ -/* - * VARCem Virtual ARchaeological Computer EMulator. - * An emulator of (mostly) x86-based PC systems and devices, - * using the ISA,EISA,VLB,MCA and PCI system buses, roughly - * spanning the era between 1981 and 1995. - * - * This file is part of the VARCem Project. - * - * Definitions for the generic NVRAM/CMOS driver. - * - * - * - * Author: Fred N. van Kempen, , - * David HrdliÄka, - * - * Copyright 2017-2020 Fred N. van Kempen. - * Copyright 2018-2020 David HrdliÄka. - * - * Redistribution and use in source and binary forms, with - * or without modification, are permitted provided that the - * following conditions are met: - * - * 1. Redistributions of source code must retain the entire - * above notice, this list of conditions and the following - * disclaimer. - * - * 2. Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the - * following disclaimer in the documentation and/or other - * materials provided with the distribution. - * - * 3. Neither the name of the copyright holder nor the names - * of its contributors may be used to endorse or promote - * products derived from this software without specific - * prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A - * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ -#ifndef EMU_NVR_H -# define EMU_NVR_H - - -#define NVR_MAXSIZE 512 /* max size of NVR data */ - -/* Conversion from BCD to Binary and vice versa. */ -#define RTC_BCD(x) (((x) % 10) | (((x) / 10) << 4)) -#define RTC_DCB(x) ((((x) & 0xf0) >> 4) * 10 + ((x) & 0x0f)) -#define RTC_BCDINC(x,y) RTC_BCD(RTC_DCB(x) + y) - -/* Time sync options */ -#define TIME_SYNC_DISABLED 0 -#define TIME_SYNC_ENABLED 1 -#define TIME_SYNC_UTC 2 - - -/* Define a generic RTC/NVRAM device. */ -typedef struct _nvr_ { - char *fn; /* pathname of image file */ - uint16_t size; /* device configuration */ - int8_t irq, is_new; - - uint8_t onesec_cnt; - pc_timer_t onesec_time; - - void *data; /* local data */ - - /* Hooks to device functions. */ - void (*reset)(struct _nvr_ *); - void (*start)(struct _nvr_ *); - void (*tick)(struct _nvr_ *); - void (*ven_save)(void); - - uint8_t regs[NVR_MAXSIZE]; /* these are the registers */ -} nvr_t; - - -extern int nvr_dosave; -#ifdef EMU_DEVICE_H -extern const device_t at_nvr_old_device; -extern const device_t at_nvr_device; -extern const device_t ps_nvr_device; -extern const device_t amstrad_nvr_device; -extern const device_t ibmat_nvr_device; -extern const device_t piix4_nvr_device; -extern const device_t ami_1992_nvr_device; -extern const device_t ami_1994_nvr_device; -extern const device_t ami_1995_nvr_device; -extern const device_t via_nvr_device; -extern const device_t p6rp4_nvr_device; -#endif - - -extern void rtc_tick(void); - -extern void nvr_init(nvr_t *); -extern char *nvr_path(char *str); -extern FILE *nvr_fopen(char *str, char *mode); -extern int nvr_load(void); -extern void nvr_close(void); -extern void nvr_set_ven_save(void (*ven_save)(void)); -extern int nvr_save(void); - -extern int nvr_is_leap(int year); -extern int nvr_get_days(int month, int year); -extern void nvr_time_sync(); -extern void nvr_time_get(struct tm *); -extern void nvr_time_set(struct tm *); - -extern void nvr_reg_write(uint16_t reg, uint8_t val, void *priv); -extern void nvr_at_handler(int set, uint16_t base, nvr_t *nvr); -extern void nvr_at_sec_handler(int set, uint16_t base, nvr_t *nvr); -extern void nvr_read_addr_set(int set, nvr_t *nvr); -extern void nvr_wp_set(int set, int h, nvr_t *nvr); -extern void nvr_via_wp_set(int set, int reg, nvr_t *nvr); -extern void nvr_bank_set(int base, uint8_t bank, nvr_t *nvr); -extern void nvr_lock_set(int base, int size, int lock, nvr_t *nvr); -extern void nvr_irq_set(int irq, nvr_t *nvr); - - -#endif /*EMU_NVR_H*/ +/* + * VARCem Virtual ARchaeological Computer EMulator. + * An emulator of (mostly) x86-based PC systems and devices, + * using the ISA,EISA,VLB,MCA and PCI system buses, roughly + * spanning the era between 1981 and 1995. + * + * Definitions for the generic NVRAM/CMOS driver. + * + * + * + * Authors: Fred N. van Kempen, , + * David HrdliÄka, + * + * Copyright 2017-2020 Fred N. van Kempen. + * Copyright 2018-2020 David HrdliÄka. + * + * Redistribution and use in source and binary forms, with + * or without modification, are permitted provided that the + * following conditions are met: + * + * 1. Redistributions of source code must retain the entire + * above notice, this list of conditions and the following + * disclaimer. + * + * 2. Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the + * following disclaimer in the documentation and/or other + * materials provided with the distribution. + * + * 3. Neither the name of the copyright holder nor the names + * of its contributors may be used to endorse or promote + * products derived from this software without specific + * prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A + * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef EMU_NVR_H +#define EMU_NVR_H + +#define NVR_MAXSIZE 512 /* max size of NVR data */ + +/* Conversion from BCD to Binary and vice versa. */ +#define RTC_BCD(x) (((x) % 10) | (((x) / 10) << 4)) +#define RTC_DCB(x) ((((x) &0xf0) >> 4) * 10 + ((x) &0x0f)) +#define RTC_BCDINC(x, y) RTC_BCD(RTC_DCB(x) + y) + +/* Time sync options */ +#define TIME_SYNC_DISABLED 0 +#define TIME_SYNC_ENABLED 1 +#define TIME_SYNC_UTC 2 + +/* Define a generic RTC/NVRAM device. */ +typedef struct _nvr_ { + char *fn; /* pathname of image file */ + uint16_t size; /* device configuration */ + int8_t irq; + int8_t is_new; + + uint8_t onesec_cnt; + pc_timer_t onesec_time; + + void *data; /* local data */ + + /* Hooks to device functions. */ + void (*reset)(struct _nvr_ *); + void (*start)(struct _nvr_ *); + void (*tick)(struct _nvr_ *); + void (*ven_save)(void); + + uint8_t regs[NVR_MAXSIZE]; /* these are the registers */ +} nvr_t; + +extern int nvr_dosave; +#ifdef EMU_DEVICE_H +extern const device_t at_nvr_old_device; +extern const device_t at_nvr_device; +extern const device_t at_mb_nvr_device; +extern const device_t ps_nvr_device; +extern const device_t amstrad_nvr_device; +extern const device_t amstrad_megapc_nvr_device; +extern const device_t ibmat_nvr_device; +extern const device_t piix4_nvr_device; +extern const device_t ps_no_nmi_nvr_device; +extern const device_t amstrad_no_nmi_nvr_device; +extern const device_t ami_1992_nvr_device; +extern const device_t ami_1994_nvr_device; +extern const device_t ami_1995_nvr_device; +extern const device_t via_nvr_device; +extern const device_t p6rp4_nvr_device; +extern const device_t elt_nvr_device; +#endif + +extern void rtc_tick(void); + +extern void nvr_init(nvr_t *); +extern char *nvr_path(char *str); +extern FILE *nvr_fopen(char *str, char *mode); +extern int nvr_load(void); +extern void nvr_close(void); +extern void nvr_set_ven_save(void (*ven_save)(void)); +extern int nvr_save(void); + +extern int nvr_is_leap(int year); +extern int nvr_get_days(int month, int year); +extern void nvr_time_sync(void); +extern void nvr_time_get(struct tm *); +extern void nvr_time_set(struct tm *); + +extern void nvr_reg_write(uint16_t reg, uint8_t val, void *priv); +extern void nvr_at_handler(int set, uint16_t base, nvr_t *nvr); +extern void nvr_at_sec_handler(int set, uint16_t base, nvr_t *nvr); +extern void nvr_at_index_read_handler(int set, uint16_t base, nvr_t *nvr); +extern void nvr_read_addr_set(int set, nvr_t *nvr); +extern void nvr_wp_set(int set, int h, nvr_t *nvr); +extern void nvr_via_wp_set(int set, int reg, nvr_t *nvr); +extern void nvr_bank_set(int base, uint8_t bank, nvr_t *nvr); +extern void nvr_lock_set(int base, int size, int lock, nvr_t *nvr); +extern void nvr_irq_set(int irq, nvr_t *nvr); +extern void nvr_smi_enable(int enable, nvr_t *nvr); +extern uint8_t nvr_smi_status(nvr_t *nvr); +extern void nvr_smi_status_clear(nvr_t *nvr); + +#endif /*EMU_NVR_H*/ diff --git a/src/include/86box/nvr_ps2.h b/src/include/86box/nvr_ps2.h index f0058d9b1..478d1be44 100644 --- a/src/include/86box/nvr_ps2.h +++ b/src/include/86box/nvr_ps2.h @@ -1,20 +1,20 @@ /* - * VARCem Virtual ARchaeological Computer EMulator. - * An emulator of (mostly) x86-based PC systems and devices, - * using the ISA,EISA,VLB,MCA and PCI system buses, roughly - * spanning the era between 1981 and 1995. + * 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 VARCem Project. + * This file is part of the 86Box distribution. * - * Definitions for the PS/2 cmos/nvr device. + * Definitions for the PS/2 cmos/nvr device. * * * - * Authors: Fred N. van Kempen, - * Sarah Walker, + * Authors: Fred N. van Kempen, + * Sarah Walker, * - * Copyright 2017,2018 Fred N. van Kempen. - * Copyright 2008-2018 Sarah Walker. + * Copyright 2017-2018 Fred N. van Kempen. + * Copyright 2008-2018 Sarah Walker. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -34,11 +34,11 @@ * Boston, MA 02111-1307 * USA. */ + #ifndef EMU_NVRPS2_H -# define EMU_NVRPS2_H +#define EMU_NVRPS2_H +extern const device_t ps2_nvr_device; +extern const device_t ps2_nvr_55ls_device; -extern const device_t ps2_nvr_device; - - -#endif /*EMU_NVRPS2_H*/ +#endif /*EMU_NVRPS2_H*/ diff --git a/src/include/86box/path.h b/src/include/86box/path.h new file mode 100644 index 000000000..f1c5e4177 --- /dev/null +++ b/src/include/86box/path.h @@ -0,0 +1,8 @@ +extern void path_get_dirname(char *dest, const char *path); +extern char *path_get_filename(char *s); +extern char *path_get_extension(char *s); +extern void path_append_filename(char *dest, const char *s1, const char *s2); +extern void path_slash(char *path); +extern const char *path_get_slash(char *path); +extern void path_normalize(char *path); +extern int path_abs(char *path); \ No newline at end of file diff --git a/src/include/86box/pci.h b/src/include/86box/pci.h index 919f14ac2..17f9f6687 100644 --- a/src/include/86box/pci.h +++ b/src/include/86box/pci.h @@ -1,132 +1,277 @@ /* - * 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. + * 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. + * This file is part of the 86Box distribution. * - * Definitions for the PCI handler module. + * Definitions for the PCI handler module. * * * - * Authors: Miran Grca, - * Fred N. van Kempen, - * Sarah Walker, + * Authors: Miran Grca, * - * Copyright 2016-2020 Miran Grca. - * Copyright 2017-2020 Fred N. van Kempen. - * Copyright 2008-2020 Sarah Walker. + * Copyright 2023 Miran Grca. */ #ifndef EMU_PCI_H -# define EMU_PCI_H +#define EMU_PCI_H +#define PCI_REG_VENDOR_ID_L 0x00 +#define PCI_REG_VENDOR_ID_H 0x01 +#define PCI_REG_DEVICE_ID_L 0x02 +#define PCI_REG_DEVICE_ID_H 0x03 +#define PCI_REG_COMMAND_L 0x04 +#define PCI_REG_COMMAND_H 0x05 +#define PCI_REG_STATUS_L 0x06 +#define PCI_REG_STATUS_H 0x07 +#define PCI_REG_REVISION 0x08 +#define PCI_REG_PROG_IF 0x09 +#define PCI_REG_SUBCLASS 0x0a +#define PCI_REG_CLASS 0x0b +#define PCI_REG_CACHELINE_SIZE 0x0c +#define PCI_REG_LATENCY_TIMER 0x0d +#define PCI_REG_HEADER_TYPE 0x0e +#define PCI_REG_BIST 0x0f -#define PCI_REG_COMMAND 0x04 +#define PCI_COMMAND_L_IO 0x01 +#define PCI_COMMAND_L_MEM 0x02 +#define PCI_COMMAND_L_BM 0x04 +#define PCI_COMMAND_L_SPECIAL 0x08 +#define PCI_COMMAND_L_MEM_WIEN 0x10 +#define PCI_COMMAND_L_VGASNOOP 0x20 +#define PCI_COMMAND_L_PARITY 0x40 -#define PCI_COMMAND_IO 0x01 -#define PCI_COMMAND_MEM 0x02 +#define PCI_COMMAND_H_SERR 0x01 +#define PCI_COMMAND_H_FAST_B2B 0x02 +#define PCI_COMMAND_H_INT_DIS 0x04 -#define PCI_NO_IRQ_STEERING 0x8000 -#define PCI_CAN_SWITCH_TYPE 0x10000 -#define PCI_NO_BRIDGES 0x20000 +#define PCI_STATUS_L_INT 0x08 +#define PCI_STATUS_L_CAPAB 0x10 +#define PCI_STATUS_L_66MHZ 0x20 +#define PCI_STATUS_L_FAST_B2B 0x80 -#define PCI_CONFIG_TYPE_1 1 -#define PCI_CONFIG_TYPE_2 2 +#define PCI_STATUS_H_MDPERR 0x01 /* Master Data Parity Error */ +#define PCI_STATUS_H_DEVSEL 0x06 +#define PCI_STATUS_H_STA 0x08 /* Signaled Target Abort */ +#define PCI_STATUS_H_RTA 0x10 /* Received Target Abort */ +#define PCI_STATUS_H_RMA 0x20 /* Received Master Abort */ +#define PCI_STATUS_H_SSE 0x40 /* Signaled System Error */ +#define PCI_STATUS_H_DPERR 0x80 /* Detected Parity Error */ -#define PCI_CONFIG_TYPE_MASK 0x7fff +#define PCI_DEVSEL_FAST 0x00 +#define PCI_DEVSEL_MEDIUM 0x02 +#define PCI_DEVSEL_SLOW 0x04 -#define PCI_INTA 1 -#define PCI_INTB 2 -#define PCI_INTC 3 -#define PCI_INTD 4 +#define FLAG_MECHANISM_1 0x00000001 +#define FLAG_MECHANISM_2 0x00000002 +#define FLAG_MECHANISM_SWITCH 0x00000004 +#define FLAG_CONFIG_IO_ON 0x00000008 +#define FLAG_CONFIG_DEV0_IO_ON 0x00000010 +#define FLAG_CONFIG_M1_IO_ON 0x00000020 +#define FLAG_NO_IRQ_STEERING 0x00000040 +#define FLAG_NO_BRIDGES 0x00000080 -#define PCI_MIRQ0 0 -#define PCI_MIRQ1 1 -#define PCI_MIRQ2 2 -#define PCI_MIRQ3 3 -#define PCI_MIRQ4 4 -#define PCI_MIRQ5 5 -#define PCI_MIRQ6 6 -#define PCI_MIRQ7 7 +#define FLAG_MECHANISM_MASK FLAG_MECHANISM_1 | FLAG_MECHANISM_2 +#define FLAG_MASK 0x0000007f -#define PCI_IRQ_DISABLED -1 +#define PCI_INTA 1 +#define PCI_INTB 2 +#define PCI_INTC 3 +#define PCI_INTD 4 -#define PCI_ADD_STRICT 0x80 +#define PCI_MIRQ0 0 +#define PCI_MIRQ1 1 +#define PCI_MIRQ2 2 +#define PCI_MIRQ3 3 +#define PCI_MIRQ4 4 +#define PCI_MIRQ5 5 +#define PCI_MIRQ6 6 +#define PCI_MIRQ7 7 + +#define PCI_IRQ_DISABLED -1 + +#define PCI_ADD_STRICT 0x40 +#define PCI_ADD_MASK (PCI_ADD_STRICT - 1) +#define PCI_ADD_VFIO 0x80 +#define PCI_ADD_VFIO_MASK (PCI_ADD_VFIO - 1) + +#define PCI_CARD_VFIO PCI_ADD_VFIO + +#define PCI_BUS_INVALID 0xff + +#define PCI_IGNORE_NO_SLOT 0xff + +/* The number of an invalid PCI card. */ +#define PCI_CARD_INVALID 0xef +/* PCI cards (currently 32). */ +#define PCI_CARDS_NUM 0x20 +#define PCI_CARD_MAX (PCI_CARDS_NUM - 1) +/* The number of PCI card INT pins - always at 4 per the PCI specification. */ +#define PCI_INT_PINS_NUM 4 +/* The base for MIRQ lines accepted by pci_irq(). */ +#define PCI_MIRQ_BASE PCI_CARDS_NUM +/* PCI MIRQ lines (currently 8, this many are needed by the ALi M1543(C). */ +#define PCI_MIRQS_NUM 8 +#define PCI_MIRQ_MAX (PCI_MIRQS_NUM - 1) +/* The base for direct IRQ lines accepted by pci_irq(). */ +#define PCI_DIRQ_BASE 0xf0 +/* PCI direct IRQ lines (currently 16 because we only emulate the legacy PIC). */ +#define PCI_DIRQS_NUM 16 +#define PCI_DIRQ_MAX (PCI_DIRQS_NUM - 1) +/* PCI IRQ routings (currently 16, this many are needed by the OPTi 822). */ +#define PCI_IRQS_NUM 16 +#define PCI_IRQ_MAX (PCI_IRQS_NUM - 1) + +/* Legacy flags. */ +#define PCI_REG_COMMAND PCI_REG_COMMAND_L + +#define PCI_COMMAND_IO PCI_COMMAND_L_IO +#define PCI_COMMAND_MEM PCI_COMMAND_L_MEM + +#define PCI_CONFIG_TYPE_1 FLAG_MECHANISM_1 +#define PCI_CONFIG_TYPE_2 FLAG_MECHANISM_2 + +#define PCI_CAN_SWITCH_TYPE FLAG_MECHANISM_SWITCH +#define PCI_ALWAYS_EXPOSE_DEV0 FLAG_CONFIG_DEV0_IO_ON +#define PCI_NO_IRQ_STEERING FLAG_NO_IRQ_STEERING +#define PCI_NO_BRIDGES FLAG_NO_BRIDGES + +#define PCI_CONFIG_TYPE_MASK FLAG_MECHANISM_MASK + +#define bar_t pci_bar_t +#define trc_init pci_trc_init + +#define pci_register_slot(card, type, inta, intb, intc, intd) \ + pci_register_bus_slot(0, card, type, inta, intb, intc, intd) + +#define pci_set_mirq(mirq, level, irq_state) \ + pci_irq(PCI_MIRQ_BASE | (mirq), 0, level, 1, irq_state) +#define pci_set_dirq(irq, irq_state) \ + pci_irq(PCI_DIRQ_BASE | (irq), 0, 1, 1, irq_state) +#define pci_set_irq(slot, pci_int, irq_state) \ + pci_irq(slot, pci_int, 0, 1, irq_state) +#define pci_clear_mirq(mirq, level, irq_state) \ + pci_irq(PCI_MIRQ_BASE | (mirq), 0, level, 0, irq_state) +#define pci_clear_dirq(dirq, irq_state) \ + pci_irq(PCI_DIRQ_BASE | (irq), 0, 1, 0, irq_state) +#define pci_clear_irq(slot, pci_int, irq_state) \ + pci_irq(slot, pci_int, 0, 0, irq_state) enum { - PCI_CARD_NORTHBRIDGE = 0, - PCI_CARD_AGPBRIDGE, - PCI_CARD_SOUTHBRIDGE, - PCI_CARD_AGP = 0x0f, - PCI_CARD_NORMAL = 0x10, - PCI_CARD_VIDEO, - PCI_CARD_SCSI, - PCI_CARD_SOUND, - PCI_CARD_IDE, - PCI_CARD_NETWORK, - PCI_CARD_BRIDGE, + PCI_CARD_NORTHBRIDGE = 0, + PCI_CARD_NORTHBRIDGE_SEC = 1, + PCI_CARD_AGPBRIDGE = 2, + PCI_CARD_SOUTHBRIDGE = 3, + PCI_CARD_SOUTHBRIDGE_IDE = 4, + PCI_CARD_SOUTHBRIDGE_PMU = 5, + PCI_CARD_SOUTHBRIDGE_USB = 6, + PCI_CARD_AGP = 0x0f, + PCI_CARD_NORMAL = 0x10, + PCI_CARD_VIDEO = 0x11, + PCI_CARD_HANGUL = 0x12, + PCI_CARD_IDE = 0x13, + PCI_CARD_SCSI = 0x14, + PCI_CARD_SOUND = 0x15, + PCI_CARD_MODEM = 0x16, + PCI_CARD_NETWORK = 0x17, + PCI_CARD_UART = 0x18, + PCI_CARD_USB = 0x19, + PCI_CARD_BRIDGE = 0x1a }; enum { - PCI_ADD_NORTHBRIDGE = 0, - PCI_ADD_AGPBRIDGE, - PCI_ADD_SOUTHBRIDGE, - PCI_ADD_AGP = 0x0f, - PCI_ADD_NORMAL = 0x10, - PCI_ADD_VIDEO, - PCI_ADD_SCSI, - PCI_ADD_SOUND, - PCI_ADD_IDE, - PCI_ADD_NETWORK, - PCI_ADD_BRIDGE + PCI_ADD_NORTHBRIDGE = 0, + PCI_ADD_NORTHBRIDGE_SEC = 1, + PCI_ADD_AGPBRIDGE = 2, + PCI_ADD_SOUTHBRIDGE = 3, + PCI_ADD_SOUTHBRIDGE_IDE = 4, + PCI_ADD_SOUTHBRIDGE_PMU = 5, + PCI_ADD_SOUTHBRIDGE_USB = 6, + PCI_ADD_AGP = 0x0f, + PCI_ADD_NORMAL = 0x10, + PCI_ADD_VIDEO = 0x11, + PCI_ADD_HANGUL = 0x12, + PCI_ADD_IDE = 0x13, + PCI_ADD_SCSI = 0x14, + PCI_ADD_SOUND = 0x15, + PCI_ADD_MODEM = 0x16, + PCI_ADD_NETWORK = 0x17, + PCI_ADD_UART = 0x18, + PCI_ADD_USB = 0x19, + PCI_ADD_BRIDGE = 0x1a }; typedef union { uint32_t addr; uint8_t addr_regs[4]; -} bar_t; +} pci_bar_t; +extern int pci_burst_time; +extern int agp_burst_time; +extern int pci_nonburst_time; +extern int agp_nonburst_time; -extern int pci_burst_time, agp_burst_time, - pci_nonburst_time, agp_nonburst_time; +extern int pci_flags; +extern uint32_t pci_base; +extern uint32_t pci_size; -extern void pci_set_irq_routing(int pci_int, int irq); -extern void pci_set_irq_level(int pci_int, int level); +extern void pci_set_irq_routing(int pci_int, int irq); +extern void pci_set_irq_level(int pci_int, int level); +extern void pci_enable_mirq(int mirq); +extern void pci_set_mirq_routing(int mirq, uint8_t irq); +extern uint8_t pci_get_mirq_level(int mirq); +extern void pci_set_mirq_level(int mirq, uint8_t irq); -extern void pci_enable_mirq(int mirq); -extern void pci_set_mirq_routing(int mirq, int irq); +/* PCI raise IRQ: the first parameter is slot if < PCI_MIRQ_BASE, MIRQ if >= PCI_MIRQ_BASE + and < PCI_DIRQ_BASE, and direct IRQ line if >= PCI_DIRQ_BASE (RichardG's + hack that may no longer be needed). */ +extern void pci_irq(uint8_t slot, uint8_t pci_int, int level, int set, uint8_t *irq_state); -extern int pci_irq_is_level(int irq); +extern uint8_t pci_get_int(uint8_t slot, uint8_t pci_int); -extern void pci_set_mirq(uint8_t mirq, int level); -extern void pci_set_irq(uint8_t card, uint8_t pci_int); -extern void pci_clear_mirq(uint8_t mirq, int level); -extern void pci_clear_irq(uint8_t card, uint8_t pci_int); -extern uint8_t pci_get_int(uint8_t card, uint8_t pci_int); +/* Relocate a PCI device to a new slot, required for the configurable + IDSEL's of ALi M1543(c). */ +extern void pci_relocate_slot(int type, int new_slot); -extern void pci_reset(void); -extern void pci_init(int type); -extern uint8_t pci_register_bus(); -extern void pci_set_pmc(uint8_t pmc); -extern void pci_remap_bus(uint8_t bus_index, uint8_t bus_number); -extern void pci_register_slot(int card, int type, - int inta, int intb, int intc, int intd); -extern void pci_register_bus_slot(int bus, int card, int type, - int inta, int intb, int intc, int intd); -extern void pci_close(void); -extern uint8_t pci_add_card(uint8_t add_type, uint8_t (*read)(int func, int addr, void *priv), void (*write)(int func, int addr, uint8_t val, void *priv), void *priv); +/* Write PCI enable/disable key, split for the ALi M1435. */ +extern void pci_key_write(uint8_t val); -extern void trc_init(void); +/* Set PMC (ie. change PCI configuration mechanism), 0 = #2, 1 = #1. */ +extern void pci_set_pmc(uint8_t pmc); -extern uint8_t trc_read(uint16_t port, void *priv); -extern void trc_write(uint16_t port, uint8_t val, void *priv); +extern void pci_pic_reset(void); +extern void pci_reset(void); -extern void pci_bridge_set_ctl(void *priv, uint8_t ctl); +/* Needed for the io.c handling of configuration mechanism #2 ports C000-CFFF. */ +extern void pci_write(uint16_t port, uint8_t val, void *priv); +extern void pci_writew(uint16_t port, uint16_t val, void *priv); +extern void pci_writel(uint16_t port, uint32_t val, void *priv); +extern uint8_t pci_read(uint16_t port, void *priv); +extern uint16_t pci_readw(uint16_t port, void *priv); +extern uint32_t pci_readl(uint16_t port, void *priv); -extern void pci_pic_reset(void); +extern uint8_t pci_register_bus(void); +extern void pci_remap_bus(uint8_t bus_index, uint8_t bus_number); +extern void pci_register_bus_slot(int bus, int card, int type, int inta, int intb, int intc, int intd); +/* Add a PCI card. */ +extern void pci_add_card(uint8_t add_type, uint8_t (*read)(int func, int addr, void *priv), + void (*write)(int func, int addr, uint8_t val, void *priv), void *priv, uint8_t *slot); + +/* Add an instance of the PCI bridge. */ +extern void pci_add_bridge(uint8_t agp, uint8_t (*read)(int func, int addr, void *priv), + void (*write)(int func, int addr, uint8_t val, void *priv), void *priv, + uint8_t *slot); + +/* Register the cards that have been added into slots. */ +extern void pci_register_cards(void); + +extern void pci_init(int flags); + +/* PCI bridge stuff. */ +extern void pci_bridge_set_ctl(void *priv, uint8_t ctl); #ifdef EMU_DEVICE_H extern const device_t dec21150_device; @@ -142,5 +287,4 @@ extern const device_t via_apro_agp_device; extern const device_t via_vt8601_agp_device; #endif - -#endif /*EMU_PCI_H*/ +#endif /*EMU_PCI_H*/ diff --git a/src/include/86box/pci_dummy.h b/src/include/86box/pci_dummy.h index 45e1299bc..104437b6e 100644 --- a/src/include/86box/pci_dummy.h +++ b/src/include/86box/pci_dummy.h @@ -1 +1,6 @@ -extern void pci_dummy_init(void); +#ifndef EMU_PCI_DUMMY_H +#define EMU_PCI_DUMMY_H + +extern void pci_dummy_init(int min_slot, int max_slot, int nb_slot, int sb_slot); + +#endif /*EMU_PCI_DUMMY_H*/ diff --git a/src/include/86box/pic.h b/src/include/86box/pic.h index 73b316f2e..798cc3357 100644 --- a/src/include/86box/pic.h +++ b/src/include/86box/pic.h @@ -1,65 +1,105 @@ /* - * 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. + * 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. + * This file is part of the 86Box distribution. * - * Header of the implementation of the Intel PIC chip emulation, - * partially ported from reenigne's XTCE. + * Header of the implementation of the Intel PIC chip emulation, + * partially ported from reenigne's XTCE. * - * Authors: Andrew Jenner, - * Miran Grca, + * Authors: Andrew Jenner, + * Miran Grca, * - * Copyright 2015-2020 Andrew Jenner. - * Copyright 2016-2020 Miran Grca. + * Copyright 2015-2020 Andrew Jenner. + * Copyright 2016-2020 Miran Grca. */ -#ifndef EMU_PIC_H -# define EMU_PIC_H +#ifndef EMU_PIC_H +#define EMU_PIC_H + +typedef struct pic_latch { + uint8_t d; + uint8_t e; + uint8_t q; + uint8_t nq; +} pic_latch_t; typedef struct pic { - uint8_t icw1, icw2, icw3, icw4, - imr, isr, irr, ocw2, - ocw3, int_pending, is_master, elcr, - state, ack_bytes, priority, special_mask_mode, - auto_eoi_rotate, interrupt, lines, data_bus; - uint32_t at; - struct pic *slaves[8]; + uint8_t icw1; + uint8_t icw2; + uint8_t icw3; + uint8_t icw4; + uint8_t imr; + uint8_t isr; + uint8_t irr; + uint8_t ocw2; + uint8_t ocw3; + uint8_t int_pending; + uint8_t is_master; + uint8_t elcr; + uint8_t state; + uint8_t ack_bytes; + uint8_t priority; + uint8_t special_mask_mode; + uint8_t auto_eoi_rotate; + uint8_t interrupt; + uint8_t data_bus; + uint8_t irq_latch; + uint8_t has_slaves; + uint8_t flags; + uint8_t edge_lines; + uint8_t pad; + uint32_t lines[8]; + uint32_t at; + struct pic *slaves[8]; } pic_t; +extern pic_t pic; +extern pic_t pic2; -extern pic_t pic, pic2; +extern void pic_reset_smi_irq_mask(void); +extern void pic_set_smi_irq_mask(int irq, int set); +extern uint16_t pic_get_smi_irq_status(void); +extern void pic_clear_smi_irq_status(int irq); +extern int pic_elcr_get_enabled(void); +extern void pic_elcr_set_enabled(int enabled); +extern void pic_elcr_io_handler(int set); +extern void pic_elcr_write(uint16_t port, uint8_t val, void *priv); +extern uint8_t pic_elcr_read(uint16_t port, void *priv); -extern void pic_reset_smi_irq_mask(void); -extern void pic_set_smi_irq_mask(int irq, int set); -extern uint16_t pic_get_smi_irq_status(void); -extern void pic_clear_smi_irq_status(int irq); +extern void pic_set_shadow(int sh); +extern int pic_get_pci_flag(void); +extern void pic_set_pci_flag(int pci); +extern void pic_set_pci(void); +extern void pic_kbd_latch(int enable); +extern void pic_mouse_latch(int enable); +extern void pic_init(void); +extern void pic_init_pcjr(void); +extern void pic2_init(void); +extern void pic_reset(void); -extern int pic_elcr_get_enabled(void); -extern void pic_elcr_set_enabled(int enabled); -extern void pic_elcr_io_handler(int set); -extern void pic_elcr_write(uint16_t port, uint8_t val, void *priv); -extern uint8_t pic_elcr_read(uint16_t port, void *priv); +extern uint8_t pic_read_icw(uint8_t pic_id, uint8_t icw); +extern uint8_t pic_read_ocw(uint8_t pic_id, uint8_t ocw); +extern int picint_is_level(int irq); +extern void picint_common(uint16_t num, int level, int set, uint8_t *irq_state); +extern int picinterrupt(void); -extern void pic_set_shadow(int sh); -extern void pic_set_pci_flag(int pci); -extern void pic_set_pci(void); -extern void pic_init(void); -extern void pic_init_pcjr(void); -extern void pic2_init(void); -extern void pic_reset(void); +#define PIC_IRQ_EDGE 0 +#define PIC_IRQ_LEVEL 1 -extern int picint_is_level(int irq); -extern void picint_common(uint16_t num, int level, int set); -extern void picint(uint16_t num); -extern void picintlevel(uint16_t num); -extern void picintc(uint16_t num); -extern int picinterrupt(void); +#define PIC_SLAVE_PENDING 0x01 +#define PIC_FREEZE 0x02 +#define PIC_MASTER_CLEAR 0x04 -extern uint8_t pic_irq_ack(void); +/* Legacy defines. */ +#define picint(num) picint_common(num, PIC_IRQ_EDGE, 1, NULL) +#define picintlevel(num, irq_state) picint_common(num, PIC_IRQ_LEVEL, 1, irq_state) +#define picintc(num) picint_common(num, PIC_IRQ_EDGE, 0, NULL) +#define picintclevel(num, irq_state) picint_common(num, PIC_IRQ_LEVEL, 0, irq_state) +extern uint8_t pic_irq_ack(void); -#endif /*EMU_PIC_H*/ +#endif /*EMU_PIC_H*/ diff --git a/src/include/86box/pit.h b/src/include/86box/pit.h index bf8d71048..d288b7e6c 100644 --- a/src/include/86box/pit.h +++ b/src/include/86box/pit.h @@ -1,118 +1,144 @@ /* - * 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. + * 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. + * This file is part of the 86Box distribution. * - * Header of the implementation of the Intel 8253/8254 - * Programmable Interval Timer. + * Header of the implementation of the Intel 8253/8254 + * Programmable Interval Timer. * * * - * Author: Miran Grca, - * Copyright 2019,2020 Miran Grca. + * Authors: Miran Grca, + * + * Copyright 2019-2020 Miran Grca. */ + #ifndef EMU_PIT_H -# define EMU_PIT_H +#define EMU_PIT_H +typedef struct ctr_t { + uint8_t m; + uint8_t ctrl; + uint8_t read_status; + uint8_t latch; + uint8_t s1_det; + uint8_t l_det; + uint8_t bcd; + uint8_t incomplete; -typedef struct { - uint8_t m, ctrl, - read_status, latch, - s1_det, l_det, - bcd, pad; + uint16_t rl; - uint16_t rl; - - int rm, wm, gate, out, - newcount, clock, using_timer, latched, - state, null_count, do_read_status; + int rm; + int wm; + int gate; + int out; + int newcount; + int clock; + int using_timer; + int latched; + int state; + int null_count; + int do_read_status; union { - int count; - struct { - int units :4; - int tens :4; - int hundreds :4; - int thousands :4; - int myriads :4; - }; + int32_t count; + struct { + int32_t units : 4; + int32_t tens : 4; + int32_t hundreds : 4; + int32_t thousands : 4; + int32_t myriads : 4; + }; }; - uint32_t l; + uint32_t l; - void (*load_func)(uint8_t new_m, int new_count); - void (*out_func)(int new_out, int old_out); + void (*load_func)(uint8_t new_m, int new_count); + void (*out_func)(int new_out, int old_out); } ctr_t; - typedef struct PIT { - int flags, clock; - pc_timer_t callback_timer; + int flags; + int clock; + pc_timer_t callback_timer; - ctr_t counters[3]; + ctr_t counters[3]; - uint8_t ctrl; + uint8_t ctrl; } pit_t; +enum { + PIT_8253 = 0, + PIT_8254 = 1, + PIT_8253_FAST = 2, + PIT_8254_FAST = 3 +}; -extern pit_t *pit, - *pit2; +typedef struct pit_intf_t { + uint8_t (*read)(uint16_t addr, void *priv); + void (*write)(uint16_t addr, uint8_t val, void *priv); + /* Gets a counter's count. */ + uint16_t (*get_count)(void *data, int counter_id); + /* Sets a counter's GATE input. */ + void (*set_gate)(void *data, int counter_id, int gate); + /* Sets if a counter's CLOCK input is from the timer or not - used by PCjr. */ + void (*set_using_timer)(void *data, int counter_id, int using_timer); + /* Sets a counter's OUT output handler. */ + void (*set_out_func)(void *data, int counter_id, void (*func)(int new_out, int old_out)); + /* Sets a counter's load count handler. */ + void (*set_load_func)(void *data, int counter_id, void (*func)(uint8_t new_m, int new_count)); + void (*ctr_clock)(void *data, int counter_id); + void *data; +} pit_intf_t; -extern double SYSCLK, PCICLK, AGPCLK; +extern pit_intf_t pit_devs[2]; +extern const pit_intf_t pit_classic_intf; -extern uint64_t PITCONST, ISACONST, - CGACONST, - MDACONST, - HERCCONST, - VGACONST1, - VGACONST2, - RTCCONST, ACPICONST; +extern double SYSCLK; +extern double PCICLK; +extern double AGPCLK; -extern int refresh_at_enable; +extern uint64_t PITCONST; +extern uint64_t ISACONST; +extern uint64_t CGACONST; +extern uint64_t MDACONST; +extern uint64_t HERCCONST; +extern uint64_t VGACONST1; +extern uint64_t VGACONST2; +extern uint64_t RTCCONST; +extern int refresh_at_enable; -/* Gets a counter's count. */ -extern uint16_t pit_ctr_get_count(ctr_t *ctr); -/* Sets a counter's load count handler. */ -extern void pit_ctr_set_load_func(ctr_t *ctr, void (*func)(uint8_t new_m, int new_count)); -/* Sets a counter's OUT output handler. */ -extern void pit_ctr_set_out_func(ctr_t *ctr, void (*func)(int new_out, int old_out)); -/* Sets a counter's GATE input. */ -extern void pit_ctr_set_gate(ctr_t *ctr, int gate); /* Sets a counter's CLOCK input. */ -extern void pit_ctr_set_clock(ctr_t *ctr, int clock); -/* Sets if a counter's CLOCK input is from the timer or not - used by PCjr. */ -extern void pit_ctr_set_using_timer(ctr_t *ctr, int using_timer); +extern void pit_ctr_set_clock(ctr_t *ctr, int clock); -extern pit_t * pit_common_init(int type, void (*out0)(int new_out, int old_out), void (*out1)(int new_out, int old_out)); -extern pit_t * pit_ps2_init(void); -extern void pit_reset(pit_t *dev); +extern pit_t *pit_common_init(int type, void (*out0)(int new_out, int old_out), void (*out1)(int new_out, int old_out)); +extern pit_t *pit_ps2_init(int type); +extern void pit_reset(pit_t *dev); -extern void pit_irq0_timer(int new_out, int old_out); -extern void pit_irq0_timer_pcjr(int new_out, int old_out); -extern void pit_irq0_timer_ps2(int new_out, int old_out); +extern void pit_irq0_timer_ps2(int new_out, int old_out); -extern void pit_refresh_timer_xt(int new_out, int old_out); -extern void pit_refresh_timer_at(int new_out, int old_out); +extern void pit_refresh_timer_xt(int new_out, int old_out); +extern void pit_refresh_timer_at(int new_out, int old_out); -extern void pit_speaker_timer(int new_out, int old_out); +extern void pit_speaker_timer(int new_out, int old_out); -extern void pit_nmi_timer_ps2(int new_out, int old_out); +extern void pit_nmi_timer_ps2(int new_out, int old_out); -extern void pit_set_clock(int clock); -extern void pit_handler(int set, uint16_t base, int size, void *priv); +extern void pit_set_clock(uint32_t clock); +extern void pit_handler(int set, uint16_t base, int size, void *priv); +extern uint8_t pit_read_reg(void *priv, uint8_t reg); #ifdef EMU_DEVICE_H -extern const device_t i8253_device; -extern const device_t i8254_device; -extern const device_t i8254_sec_device; -extern const device_t i8254_ext_io_device; -extern const device_t i8254_ps2_device; +extern const device_t i8253_device; +extern const device_t i8254_device; +extern const device_t i8254_sec_device; +extern const device_t i8254_ext_io_device; +extern const device_t i8254_ps2_device; #endif - -#endif /*EMU_PIT_H*/ +#endif /*EMU_PIT_H*/ diff --git a/src/include/86box/pit_fast.h b/src/include/86box/pit_fast.h new file mode 100644 index 000000000..2485a360c --- /dev/null +++ b/src/include/86box/pit_fast.h @@ -0,0 +1,84 @@ +/* + * 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. + * + * Header of the implementation of the Intel 8253/8254 + * Programmable Interval Timer. + * + * + * + * Authors: Miran Grca, + * + * Copyright 2019-2020 Miran Grca. + */ + +#ifndef EMU_PIT_FAST_H +#define EMU_PIT_FAST_H + +typedef struct ctrf_t { + uint8_t m; + uint8_t ctrl; + uint8_t read_status; + uint8_t latch; + uint8_t bcd; + + uint16_t rl; + + int rm; + int wm; + int gate; + int out; + int newcount; + int clock; + int using_timer; + int latched; + int do_read_status; + int enabled; + int disabled; + int initial; + int thit; + int running; + int rereadlatch; + + union { + int32_t count; + struct { + int32_t units : 4; + int32_t tens : 4; + int32_t hundreds : 4; + int32_t thousands : 4; + int32_t myriads : 4; + }; + }; + + uint32_t l; + pc_timer_t timer; + + void (*load_func)(uint8_t new_m, int new_count); + void (*out_func)(int new_out, int old_out); +} ctrf_t; + +typedef struct pitf_t { + int flags; + ctrf_t counters[3]; + + uint8_t ctrl; +} pitf_t; + +extern uint8_t pitf_read_reg(void *priv, uint8_t reg); + +extern const pit_intf_t pit_fast_intf; + +#ifdef EMU_DEVICE_H +extern const device_t i8253_fast_device; +extern const device_t i8254_fast_device; +extern const device_t i8254_sec_fast_device; +extern const device_t i8254_ext_io_fast_device; +extern const device_t i8254_ps2_fast_device; +#endif + +#endif /*EMU_PIT_FAST_H*/ diff --git a/src/include/86box/plat.h b/src/include/86box/plat.h index d00bc1b87..0d5b17a3c 100644 --- a/src/include/86box/plat.h +++ b/src/include/86box/plat.h @@ -1,29 +1,32 @@ /* - * 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. + * 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. + * This file is part of the 86Box distribution. * - * Define the various platform support functions. + * Define the various platform support functions. * * * - * Authors: Miran Grca, - * Fred N. van Kempen, + * Authors: Miran Grca, + * Fred N. van Kempen, * - * Copyright 2016-2019 Miran Grca. - * Copyright 2017-2019 Fred N. van Kempen. - * Copyright 2021 Laci bá' + * Copyright 2016-2019 Miran Grca. + * Copyright 2017-2019 Fred N. van Kempen. + * Copyright 2021 Laci bá' */ -#ifndef EMU_PLAT_H -# define EMU_PLAT_H +#ifndef EMU_PLAT_H +#define EMU_PLAT_H + +#include +#include #include "86box/device.h" #include "86box/machine.h" #ifndef GLOBAL -# define GLOBAL extern +# define GLOBAL extern #endif /* String ID numbers. */ @@ -31,190 +34,160 @@ /* The Win32 API uses _wcsicmp. */ #ifdef _WIN32 -# define wcscasecmp _wcsicmp -# define strcasecmp _stricmp +# define wcscasecmp _wcsicmp +# define strcasecmp _stricmp #else /* Declare these functions to avoid warnings. They will redirect to strcasecmp and strncasecmp respectively. */ -extern int stricmp(const char* s1, const char* s2); -extern int strnicmp(const char* s1, const char* s2, size_t n); +extern int stricmp(const char *s1, const char *s2); +extern int strnicmp(const char *s1, const char *s2, size_t n); #endif -#if (defined(__unix__) || defined(__APPLE__)) && !defined(__linux__) +#if (defined(__HAIKU__) || defined(__unix__) || defined(__APPLE__)) && !defined(__linux__) /* FreeBSD has largefile by default. */ -# define fopen64 fopen -# define fseeko64 fseeko -# define ftello64 ftello -# define off64_t off_t +# define fopen64 fopen +# define fseeko64 fseeko +# define ftello64 ftello +# define off64_t off_t #elif defined(_MSC_VER) -//# define fopen64 fopen -# define fseeko64 _fseeki64 -# define ftello64 _ftelli64 -# define off64_t off_t +// # define fopen64 fopen +# define fseeko64 _fseeki64 +# define ftello64 _ftelli64 +# define off64_t off_t #endif - #ifdef _MSC_VER -# define UNUSED(arg) arg +# define UNUSED(arg) arg #else - /* A hack (GCC-specific?) to allow us to ignore unused parameters. */ -# define UNUSED(arg) __attribute__((unused))arg +/* A hack (GCC-specific?) to allow us to ignore unused parameters. */ +# define UNUSED(arg) __attribute__((unused)) arg #endif /* Return the size (in wchar's) of a wchar_t array. */ -#define sizeof_w(x) (sizeof((x)) / sizeof(wchar_t)) - +#define sizeof_w(x) (sizeof((x)) / sizeof(wchar_t)) #ifdef __cplusplus -#include -#define atomic_flag_t std::atomic_flag +# include +# define atomic_flag_t std::atomic_flag +# define atomic_bool_t std::atomic_bool extern "C" { #else -#include -#define atomic_flag_t atomic_flag +# include +# define atomic_flag_t atomic_flag +# define atomic_bool_t atomic_bool +#endif + +#if defined(_MSC_VER) +# define ssize_t intptr_t +#endif + +#ifdef _MSC_VER +# define fallthrough do {} while (0) /* fallthrough */ +#else +# if __has_attribute(fallthrough) +# define fallthrough __attribute__((fallthrough)) +# else +# if __has_attribute(__fallthrough__) +# define fallthrough __attribute__((__fallthrough__)) +# endif +# define fallthrough do {} while (0) /* fallthrough */ +# endif #endif /* Global variables residing in the platform module. */ -extern int dopause, /* system is paused */ - mouse_capture; /* mouse is captured in app */ -extern atomic_flag_t doresize; /* screen resize requested */ -extern volatile int is_quit; /* system exit requested */ +extern int dopause; /* system is paused */ +extern int mouse_capture; /* mouse is captured in app */ +extern volatile int is_quit; /* system exit requested */ #ifdef MTR_ENABLED extern int tracing_on; #endif -extern uint64_t timer_freq; -extern int infocus; -extern char emu_version[200]; /* version ID string */ -extern int rctrl_is_lalt; -extern int update_icons; -extern int status_icons_fullscreen; +extern uint64_t timer_freq; +extern int infocus; +extern char emu_version[200]; /* version ID string */ +extern int rctrl_is_lalt; +extern int update_icons; +extern int status_icons_fullscreen; -extern int unscaled_size_x, /* current unscaled size X */ - unscaled_size_y; /* current unscaled size Y */ - -extern int kbd_req_capture, hide_status_bar, hide_tool_bar; +extern int kbd_req_capture; +extern int hide_status_bar; +extern int hide_tool_bar; /* System-related functions. */ -extern char *fix_exe_path(char *str); -extern FILE *plat_fopen(const char *path, const char *mode); -extern FILE *plat_fopen64(const char *path, const char *mode); -extern void plat_remove(char *path); -extern int plat_getcwd(char *bufp, int max); -extern int plat_chdir(char *path); -extern void plat_tempfile(char *bufp, char *prefix, char *suffix); -extern void plat_get_exe_name(char *s, int size); -extern char *plat_get_basename(const char *path); -extern void plat_get_dirname(char *dest, const char *path); -extern char *plat_get_filename(char *s); -extern char *plat_get_extension(char *s); -extern void plat_append_filename(char *dest, const char *s1, const char *s2); -extern void plat_put_backslash(char *s); -extern void plat_path_slash(char *path); -extern int plat_path_abs(char *path); -extern int plat_dir_check(char *path); -extern int plat_dir_create(char *path); -extern void *plat_mmap(size_t size, uint8_t executable); -extern void plat_munmap(void *ptr, size_t size); -extern uint64_t plat_timer_read(void); -extern uint32_t plat_get_ticks(void); -extern uint32_t plat_get_micro_ticks(void); -extern void plat_delay_ms(uint32_t count); -extern void plat_pause(int p); -extern void plat_mouse_capture(int on); -extern int plat_vidapi(char *name); -extern char *plat_vidapi_name(int api); -extern int plat_setvid(int api); -extern void plat_vidsize(int x, int y); -extern void plat_setfullscreen(int on); -extern void plat_resize(int x, int y); -extern void plat_vidapi_enable(int enabled); -extern void plat_vidapi_reload(void); -extern void plat_vid_reload_options(void); -extern uint32_t plat_language_code(char* langcode); -extern void plat_language_code_r(uint32_t lcid, char* outbuf, int len); +extern char *fix_exe_path(char *str); +extern FILE *plat_fopen(const char *path, const char *mode); +extern FILE *plat_fopen64(const char *path, const char *mode); +extern void plat_remove(char *path); +extern int plat_getcwd(char *bufp, int max); +extern int plat_chdir(char *path); +extern void plat_tempfile(char *bufp, char *prefix, char *suffix); +extern void plat_get_exe_name(char *s, int size); +extern void plat_get_global_config_dir(char* strptr); +extern void plat_init_rom_paths(void); +extern int plat_dir_check(char *path); +extern int plat_dir_create(char *path); +extern void *plat_mmap(size_t size, uint8_t executable); +extern void plat_munmap(void *ptr, size_t size); +extern uint64_t plat_timer_read(void); +extern uint32_t plat_get_ticks(void); +extern uint32_t plat_get_micro_ticks(void); +extern void plat_delay_ms(uint32_t count); +extern void plat_pause(int p); +extern void plat_mouse_capture(int on); +extern int plat_vidapi(char *name); +extern char *plat_vidapi_name(int api); +extern int plat_setvid(int api); +extern void plat_vidsize(int x, int y); +extern void plat_setfullscreen(int on); +extern void plat_resize_monitor(int x, int y, int monitor_index); +extern void plat_resize_request(int x, int y, int monitor_index); +extern void plat_resize(int x, int y); +extern void plat_vidapi_enable(int enabled); +extern void plat_vidapi_reload(void); +extern void plat_vid_reload_options(void); +extern uint32_t plat_language_code(char *langcode); +extern void plat_language_code_r(uint32_t lcid, char *outbuf, int len); +extern void plat_get_cpu_string(char *outbuf, uint8_t len); +extern double plat_get_dpi(void); /* Resource management. */ -extern void set_language(uint32_t id); -extern wchar_t *plat_get_string(int id); - +extern void set_language(uint32_t id); +extern wchar_t *plat_get_string(int id); /* Emulator start/stop support functions. */ -extern void do_start(void); -extern void do_stop(void); - +extern void do_start(void); +extern void do_stop(void); /* Power off. */ -extern void plat_power_off(void); - +extern void plat_power_off(void); /* Platform-specific device support. */ -extern void cassette_mount(char *fn, uint8_t wp); -extern void cassette_eject(void); -extern void cartridge_mount(uint8_t id, char *fn, uint8_t wp); -extern void cartridge_eject(uint8_t id); -extern void floppy_mount(uint8_t id, char *fn, uint8_t wp); -extern void floppy_eject(uint8_t id); -extern void cdrom_mount(uint8_t id, char *fn); -extern void plat_cdrom_ui_update(uint8_t id, uint8_t reload); -extern void zip_eject(uint8_t id); -extern void zip_mount(uint8_t id, char *fn, uint8_t wp); -extern void zip_reload(uint8_t id); -extern void mo_eject(uint8_t id); -extern void mo_mount(uint8_t id, char *fn, uint8_t wp); -extern void mo_reload(uint8_t id); -extern int ioctl_open(uint8_t id, char d); -extern void ioctl_reset(uint8_t id); -extern void ioctl_close(uint8_t id); - -#ifdef __APPLE__ -#define thread_t plat_thread_t -#define event_t plat_event_t -#define mutex_t plat_mutex_t - -#define thread_create plat_thread_create -#define thread_wait plat_thread_wait -#define thread_create_event plat_thread_create_event -#define thread_set_event plat_thread_set_event -#define thread_reset_event plat_thread_reset_event -#define thread_wait_event plat_thread_wait_event -#define thread_destroy_event plat_thread_destroy_event - -#define thread_create_mutex plat_thread_create_mutex -#define thread_create_mutex_with_spin_count plat_thread_create_mutex_with_spin_count -#define thread_close_mutex plat_thread_close_mutex -#define thread_wait_mutex plat_thread_wait_mutex -#define thread_release_mutex plat_thread_release_mutex -#endif - -/* Thread support. */ -typedef void thread_t; -typedef void event_t; -typedef void mutex_t; - -extern thread_t *thread_create(void (*thread_func)(void *param), void *param); -extern int thread_wait(thread_t *arg); -extern event_t *thread_create_event(void); -extern void thread_set_event(event_t *arg); -extern void thread_reset_event(event_t *arg); -extern int thread_wait_event(event_t *arg, int timeout); -extern void thread_destroy_event(event_t *arg); - -#define MUTEX_DEFAULT_SPIN_COUNT 1024 - -extern mutex_t *thread_create_mutex(void); -extern void thread_close_mutex(mutex_t *arg); -extern int thread_wait_mutex(mutex_t *arg); -extern int thread_release_mutex(mutex_t *mutex); +extern void cassette_mount(char *fn, uint8_t wp); +extern void cassette_eject(void); +extern void cartridge_mount(uint8_t id, char *fn, uint8_t wp); +extern void cartridge_eject(uint8_t id); +extern void floppy_mount(uint8_t id, char *fn, uint8_t wp); +extern void floppy_eject(uint8_t id); +extern void cdrom_mount(uint8_t id, char *fn); +extern void plat_cdrom_ui_update(uint8_t id, uint8_t reload); +extern void zip_eject(uint8_t id); +extern void zip_mount(uint8_t id, char *fn, uint8_t wp); +extern void zip_reload(uint8_t id); +extern void mo_eject(uint8_t id); +extern void mo_mount(uint8_t id, char *fn, uint8_t wp); +extern void mo_reload(uint8_t id); +extern int ioctl_open(uint8_t id, char d); +extern void ioctl_reset(uint8_t id); +extern void ioctl_close(uint8_t id); /* Other stuff. */ -extern void startblit(void); -extern void endblit(void); -extern void take_screenshot(void); +extern void startblit(void); +extern void endblit(void); +extern void take_screenshot(void); /* Conversion between UTF-8 and UTF-16. */ -extern size_t mbstoc16s(uint16_t dst[], const char src[], int len); -extern size_t c16stombs(char dst[], const uint16_t src[], int len); +extern size_t mbstoc16s(uint16_t dst[], const char src[], int len); +extern size_t c16stombs(char dst[], const uint16_t src[], int len); #ifdef MTR_ENABLED extern void init_trace(void); @@ -225,5 +198,4 @@ extern void shutdown_trace(void); } #endif - -#endif /*EMU_PLAT_H*/ +#endif /*EMU_PLAT_H*/ diff --git a/src/include/86box/plat_dir.h b/src/include/86box/plat_dir.h index b8280404c..965483d26 100644 --- a/src/include/86box/plat_dir.h +++ b/src/include/86box/plat_dir.h @@ -1,76 +1,74 @@ /* - * 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. + * 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. + * This file is part of the 86Box distribution. * - * Definitions for the platform OpenDir module. + * Definitions for the platform OpenDir module. * * * - * Author: Fred N. van Kempen, - * Copyright 2017 Fred N. van Kempen. + * Authors: Fred N. van Kempen, + * + * Copyright 2017 Fred N. van Kempen. */ + #ifndef PLAT_DIR_H -# define PLAT_DIR_H - - -#ifdef _MAX_FNAME -# define MAXNAMLEN _MAX_FNAME -#else -# define MAXNAMLEN 15 -#endif -# define MAXDIRLEN 127 +#define PLAT_DIR_H +/* Windows and Termux needs the POSIX re-implementations */ +#if defined(_WIN32) || defined(__TERMUX__) +# ifdef _MAX_FNAME +# define MAXNAMLEN _MAX_FNAME +# else +# define MAXNAMLEN 15 +# endif +# define MAXDIRLEN 127 struct dirent { - long d_ino; - unsigned short d_reclen; - unsigned short d_off; -#ifdef UNICODE - wchar_t d_name[MAXNAMLEN + 1]; -#else - char d_name[MAXNAMLEN + 1]; -#endif + long d_ino; + unsigned short d_reclen; + unsigned short d_off; +# ifdef UNICODE + wchar_t d_name[MAXNAMLEN + 1]; +# else + char d_name[MAXNAMLEN + 1]; +# endif }; -#define d_namlen d_reclen +# define d_namlen d_reclen - -typedef struct { - short flags; /* internal flags */ - short offset; /* offset of entry into dir */ - long handle; /* open handle to Win32 system */ - short sts; /* last known status code */ - char *dta; /* internal work data */ -#ifdef UNICODE - wchar_t dir[MAXDIRLEN+1]; /* open dir */ -#else - char dir[MAXDIRLEN+1]; /* open dir */ -#endif - struct dirent dent; /* actual directory entry */ +typedef struct DIR_t { + short flags; /* internal flags */ + short offset; /* offset of entry into dir */ + long handle; /* open handle to Win32 system */ + short sts; /* last known status code */ + char *dta; /* internal work data */ +# ifdef UNICODE + wchar_t dir[MAXDIRLEN + 1]; /* open dir */ +# else + char dir[MAXDIRLEN + 1]; /* open dir */ +# endif + struct dirent dent; /* actual directory entry */ } DIR; - /* Directory routine flags. */ -#define DIR_F_LOWER 0x0001 /* force to lowercase */ -#define DIR_F_SANE 0x0002 /* force this to sane path */ -#define DIR_F_ISROOT 0x0010 /* this is the root directory */ - +# define DIR_F_LOWER 0x0001 /* force to lowercase */ +# define DIR_F_SANE 0x0002 /* force this to sane path */ +# define DIR_F_ISROOT 0x0010 /* this is the root directory */ /* Function prototypes. */ -#ifdef UNICODE -extern DIR *opendirw(const wchar_t *); +extern DIR *opendir(const char *); +extern struct dirent *readdir(DIR *); +extern long telldir(DIR *); +extern void seekdir(DIR *, long); +extern int closedir(DIR *); + +# define rewinddir(dirp) seekdir(dirp, 0L) #else -extern DIR *opendir(const char *); +/* On linux and macOS, use the standard functions and types */ +# include #endif -extern struct dirent *readdir(DIR *); -extern long telldir(DIR *); -extern void seekdir(DIR *, long); -extern int closedir(DIR *); -#define rewinddir(dirp) seekdir(dirp, 0L) - - -#endif /*PLAT_DIR_H*/ +#endif /*PLAT_DIR_H*/ diff --git a/src/include/86box/plat_dynld.h b/src/include/86box/plat_dynld.h index 0eb8f33c2..44891d4ac 100644 --- a/src/include/86box/plat_dynld.h +++ b/src/include/86box/plat_dynld.h @@ -1,38 +1,37 @@ /* - * 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. + * 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. + * This file is part of the 86Box distribution. * - * Define the Dynamic Module Loader interface. + * Define the Dynamic Module Loader interface. * * * - * Author: Fred N. van Kempen, - * Copyright 2017 Fred N. van Kempen + * Authors: Fred N. van Kempen, + * + * Copyright 2017 Fred N. van Kempen */ + #ifndef PLAT_DYNLD_H -# define PLAT_DYNLD_H +#define PLAT_DYNLD_H - -typedef struct { - const char *name; - void *func; +typedef struct dllimp_t { + const char *name; + void *func; } dllimp_t; - #ifdef __cplusplus extern "C" { #endif -extern void *dynld_module(const char *, dllimp_t *); -extern void dynld_close(void *); +extern void *dynld_module(const char *, dllimp_t *); +extern void dynld_close(void *); #ifdef __cplusplus } #endif - -#endif /*PLAT_DYNLD_H*/ +#endif /*PLAT_DYNLD_H*/ diff --git a/src/include/86box/plat_fallthrough.h b/src/include/86box/plat_fallthrough.h new file mode 100644 index 000000000..6165b266c --- /dev/null +++ b/src/include/86box/plat_fallthrough.h @@ -0,0 +1,36 @@ +/* + * 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. + * + * Define the various platform support functions. + * + * + * + * Authors: Jasmine Iwanek, + * + * Copyright 2023 Jasmine Iwanek + */ + +#ifndef EMU_PLAT_FALLTHROUGH_H +#define EMU_PLAT_FALLTHROUGH_H + +#ifndef EMU_PLAT_H +#ifdef _MSC_VER +# define fallthrough do {} while (0) /* fallthrough */ +#else +# if __has_attribute(fallthrough) +# define fallthrough __attribute__((fallthrough)) +# else +# if __has_attribute(__fallthrough__) +# define fallthrough __attribute__((__fallthrough__)) +# endif +# define fallthrough do {} while (0) /* fallthrough */ +# endif +#endif +#endif + +#endif /*EMU_PLAT_FALLTHROUGH_H*/ diff --git a/src/include/86box/plat_serial_passthrough.h b/src/include/86box/plat_serial_passthrough.h new file mode 100644 index 000000000..60674ea58 --- /dev/null +++ b/src/include/86box/plat_serial_passthrough.h @@ -0,0 +1,38 @@ +/* + * 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. + * + * Definitions for platform specific serial to host passthrough. + * + * + * Authors: Andreas J. Reichel , + * Jasmine Iwanek + * + * Copyright 2021 Andreas J. Reichel. + * Copyright 2021-2022 Jasmine Iwanek. + */ + +#ifndef PLAT_SERIAL_PASSTHROUGH_H +#define PLAT_SERIAL_PASSTHROUGH_H + +#include + +#ifdef __cplusplus +extern "C" { +#endif + +extern void plat_serpt_write(void *priv, uint8_t data); +extern int plat_serpt_read(void *priv, uint8_t *data); +extern int plat_serpt_open_device(void *priv); +extern void plat_serpt_close(void *priv); +extern void plat_serpt_set_params(void *priv); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/src/include/86box/plat_unused.h b/src/include/86box/plat_unused.h new file mode 100644 index 000000000..226cf677d --- /dev/null +++ b/src/include/86box/plat_unused.h @@ -0,0 +1,33 @@ +/* + * 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. + * + * Define the various platform support functions. + * + * + * + * Authors: Miran Grca, + * Fred N. van Kempen, + * + * Copyright 2016-2019 Miran Grca. + * Copyright 2017-2019 Fred N. van Kempen. + * Copyright 2021 Laci bá' + */ + +#ifndef EMU_PLAT_UNUSED_H +#define EMU_PLAT_UNUSED_H + +#ifndef EMU_PLAT_H +#ifdef _MSC_VER +# define UNUSED(arg) arg +#else +/* A hack (GCC-specific?) to allow us to ignore unused parameters. */ +# define UNUSED(arg) __attribute__((unused)) arg +#endif +#endif + +#endif /*EMU_PLAT_UNUSED_H*/ diff --git a/src/include/86box/png_struct.h b/src/include/86box/png_struct.h index 893cc5f64..cbbcc5be8 100644 --- a/src/include/86box/png_struct.h +++ b/src/include/86box/png_struct.h @@ -1,36 +1,34 @@ /* - * VARCem Virtual ARchaeological Computer EMulator. - * An emulator of (mostly) x86-based PC systems and devices, - * using the ISA,EISA,VLB,MCA and PCI system buses, roughly - * spanning the era between 1981 and 1995. + * VARCem Virtual ARchaeological Computer EMulator. + * An emulator of (mostly) x86-based PC systems and devices, + * using the ISA,EISA,VLB,MCA and PCI system buses, roughly + * spanning the era between 1981 and 1995. * - * This file is part of the VARCem Project. - * - * Definitions for the centralized PNG image handler. + * Definitions for the centralized PNG image handler. * * * - * Author: Fred N. van Kempen, + * Authors: Fred N. van Kempen, * - * Copyright 2018 Fred N. van Kempen. + * Copyright 2018 Fred N. van Kempen. * - * Redistribution and use in source and binary forms, with - * or without modification, are permitted provided that the - * following conditions are met: + * Redistribution and use in source and binary forms, with + * or without modification, are permitted provided that the + * following conditions are met: * - * 1. Redistributions of source code must retain the entire - * above notice, this list of conditions and the following - * disclaimer. + * 1. Redistributions of source code must retain the entire + * above notice, this list of conditions and the following + * disclaimer. * - * 2. Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the - * following disclaimer in the documentation and/or other - * materials provided with the distribution. + * 2. Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the + * following disclaimer in the documentation and/or other + * materials provided with the distribution. * - * 3. Neither the name of the copyright holder nor the names - * of its contributors may be used to endorse or promote - * products derived from this software without specific - * prior written permission. + * 3. Neither the name of the copyright holder nor the names + * of its contributors may be used to endorse or promote + * products derived from this software without specific + * prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT @@ -44,23 +42,22 @@ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -#ifndef EMU_PNG_STRUCT_H -# define EMU_PNG_STRUCT_H +#ifndef EMU_PNG_STRUCT_H +#define EMU_PNG_STRUCT_H #ifdef __cplusplus extern "C" { #endif -extern int png_write_gray(char *path, int invert, - uint8_t *pix, int16_t w, int16_t h); +extern int png_write_gray(char *path, int invert, + uint8_t *pix, int16_t w, int16_t h); -extern void png_write_rgb(char *fn, - uint8_t *pix, int16_t w, int16_t h, uint16_t pitch, PALETTE palcol); +extern void png_write_rgb(char *fn, + uint8_t *pix, int16_t w, int16_t h, uint16_t pitch, PALETTE palcol); #ifdef __cplusplus } #endif - -#endif /*EMU_PNG_STRUCT_H*/ +#endif /*EMU_PNG_STRUCT_H*/ diff --git a/src/include/86box/port_6x.h b/src/include/86box/port_6x.h index 74172728a..e0c4b0508 100644 --- a/src/include/86box/port_6x.h +++ b/src/include/86box/port_6x.h @@ -1,38 +1,36 @@ /* - * 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. + * 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. + * This file is part of the 86Box distribution. * - * Header for the implementation of Port 6x used by various - * machines. + * Header for the implementation of Port 6x used by various + * machines. * * * - * Authors: Miran Grca, + * Authors: Miran Grca, * - * Copyright 2021 Miran Grca. + * Copyright 2021 Miran Grca. */ -#ifndef EMU_PORT_6X_H -# define EMU_PORT_6X_H +#ifndef EMU_PORT_6X_H +#define EMU_PORT_6X_H #ifdef _TIMER_H_ -typedef struct -{ - uint8_t refresh, flags; +typedef struct port_6x_t { + uint8_t refresh; + uint8_t flags; - pc_timer_t refresh_timer; + pc_timer_t refresh_timer; } port_6x_t; #endif +extern const device_t port_6x_device; +extern const device_t port_6x_xi8088_device; +extern const device_t port_6x_ps2_device; +extern const device_t port_6x_olivetti_device; -extern const device_t port_6x_device; -extern const device_t port_6x_xi8088_device; -extern const device_t port_6x_ps2_device; -extern const device_t port_6x_olivetti_device; - - -#endif /*EMU_PORT_6X_H*/ +#endif /*EMU_PORT_6X_H*/ diff --git a/src/include/86box/port_92.h b/src/include/86box/port_92.h index 52812edb8..2dd4319be 100644 --- a/src/include/86box/port_92.h +++ b/src/include/86box/port_92.h @@ -1,47 +1,44 @@ /* - * 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. + * 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. + * This file is part of the 86Box distribution. * - * Header for the implementation of Port 92 used by PS/2 - * machines and 386+ clones. + * Header for the implementation of Port 92 used by PS/2 + * machines and 386+ clones. * * * - * Authors: Miran Grca, + * Authors: Miran Grca, * - * Copyright 2019 Miran Grca. + * Copyright 2019 Miran Grca. */ -#ifndef EMU_PORT_92_H -# define EMU_PORT_92_H +#ifndef EMU_PORT_92_H +#define EMU_PORT_92_H #ifdef _TIMER_H_ -typedef struct -{ - uint8_t reg, flags; +typedef struct port_92_t { + uint8_t reg; + uint8_t flags; - pc_timer_t pulse_timer; + pc_timer_t pulse_timer; - uint64_t pulse_period; + uint64_t pulse_period; } port_92_t; #endif +extern void port_92_set_period(void *priv, uint64_t pulse_period); +extern void port_92_set_features(void *priv, int reset, int a20); -extern void port_92_set_period(void *priv, uint64_t pulse_period); -extern void port_92_set_features(void *priv, int reset, int a20); +extern void port_92_add(void *priv); +extern void port_92_remove(void *priv); -extern void port_92_add(void *priv); -extern void port_92_remove(void *priv); +extern const device_t port_92_device; +extern const device_t port_92_inv_device; +extern const device_t port_92_word_device; +extern const device_t port_92_pci_device; - -extern const device_t port_92_device; -extern const device_t port_92_inv_device; -extern const device_t port_92_word_device; -extern const device_t port_92_pci_device; - - -#endif /*EMU_PORT_92_H*/ +#endif /*EMU_PORT_92_H*/ diff --git a/src/include/86box/postcard.h b/src/include/86box/postcard.h index 8cf1d1c54..5ceb64ae3 100644 --- a/src/include/86box/postcard.h +++ b/src/include/86box/postcard.h @@ -1,22 +1,22 @@ /* - * 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. + * 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. + * This file is part of the 86Box distribution. * - * Implementation of a port 80h POST diagnostic card. + * Implementation of a port 80h POST diagnostic card. * * * - * Author: RichardG, + * Authors: RichardG, * - * Copyright 2020 RichardG. + * Copyright 2020 RichardG. */ -#ifndef POSTCARD_H -# define POSTCARD_H +#ifndef POSTCARD_H +#define POSTCARD_H #ifdef __cplusplus extern "C" { @@ -25,12 +25,10 @@ extern "C" { /* Global variables. */ extern const device_t postcard_device; - /* Functions. */ #ifdef __cplusplus } #endif - -#endif /*POSTCARD_H*/ +#endif /*POSTCARD_H*/ diff --git a/src/include/86box/ppi.h b/src/include/86box/ppi.h index a46a407f5..d5649bcc8 100644 --- a/src/include/86box/ppi.h +++ b/src/include/86box/ppi.h @@ -1,18 +1,15 @@ #ifndef EMU_PPI_H -# define EMU_PPI_H - +#define EMU_PPI_H typedef struct PPI { - int s2; - uint8_t pa,pb; + int s2; + uint8_t pa; + uint8_t pb; } PPI; +extern int ppispeakon; +extern PPI ppi; -extern int ppispeakon; -extern PPI ppi; +extern void ppi_reset(void); - -extern void ppi_reset(void); - - -#endif /*EMU_PPI_H*/ +#endif /*EMU_PPI_H*/ diff --git a/src/include/86box/printer.h b/src/include/86box/printer.h index 78193e18e..eb6eb4a75 100644 --- a/src/include/86box/printer.h +++ b/src/include/86box/printer.h @@ -1,36 +1,34 @@ /* - * VARCem Virtual ARchaeological Computer EMulator. - * An emulator of (mostly) x86-based PC systems and devices, - * using the ISA,EISA,VLB,MCA and PCI system buses, roughly - * spanning the era between 1981 and 1995. + * VARCem Virtual ARchaeological Computer EMulator. + * An emulator of (mostly) x86-based PC systems and devices, + * using the ISA,EISA,VLB,MCA and PCI system buses, roughly + * spanning the era between 1981 and 1995. * - * This file is part of the VARCem Project. - * - * Definitions for the printers module. + * Definitions for the printers module. * * * - * Author: Fred N. van Kempen, + * Authors: Fred N. van Kempen, * - * Copyright 2018 Fred N. van Kempen. + * Copyright 2018 Fred N. van Kempen. * - * Redistribution and use in source and binary forms, with - * or without modification, are permitted provided that the - * following conditions are met: + * Redistribution and use in source and binary forms, with + * or without modification, are permitted provided that the + * following conditions are met: * - * 1. Redistributions of source code must retain the entire - * above notice, this list of conditions and the following - * disclaimer. + * 1. Redistributions of source code must retain the entire + * above notice, this list of conditions and the following + * disclaimer. * - * 2. Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the - * following disclaimer in the documentation and/or other - * materials provided with the distribution. + * 2. Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the + * following disclaimer in the documentation and/or other + * materials provided with the distribution. * - * 3. Neither the name of the copyright holder nor the names - * of its contributors may be used to endorse or promote - * products derived from this software without specific - * prior written permission. + * 3. Neither the name of the copyright holder nor the names + * of its contributors may be used to endorse or promote + * products derived from this software without specific + * prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT @@ -44,22 +42,20 @@ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ + #ifndef PRINTER_H -# define PRINTER_H +#define PRINTER_H +#define FONT_FILE_DOTMATRIX "dotmatrix.ttf" -#define FONT_FILE_DOTMATRIX "dotmatrix.ttf" - -#define FONT_FILE_ROMAN "roman.ttf" -#define FONT_FILE_SANSSERIF "sansserif.ttf" -#define FONT_FILE_COURIER "courier.ttf" -#define FONT_FILE_SCRIPT "script.ttf" -#define FONT_FILE_OCRA "ocra.ttf" -#define FONT_FILE_OCRB "ocra.ttf" - +#define FONT_FILE_ROMAN "roman.ttf" +#define FONT_FILE_SANSSERIF "sansserif.ttf" +#define FONT_FILE_COURIER "courier.ttf" +#define FONT_FILE_SCRIPT "script.ttf" +#define FONT_FILE_OCRA "ocra.ttf" +#define FONT_FILE_OCRB "ocra.ttf" extern void select_codepage(uint16_t code, uint16_t *curmap); - -#endif /*PRINTER_H*/ +#endif /*PRINTER_H*/ diff --git a/src/include/86box/prt_devs.h b/src/include/86box/prt_devs.h index 7ef25e5cd..3d9d6673a 100644 --- a/src/include/86box/prt_devs.h +++ b/src/include/86box/prt_devs.h @@ -1,3 +1,8 @@ -extern const lpt_device_t lpt_prt_text_device; -extern const lpt_device_t lpt_prt_escp_device; -extern const lpt_device_t lpt_prt_ps_device; \ No newline at end of file +#ifndef EMU_PRT_DEVS_H +#define EMU_PRT_DEVS_H + +extern const lpt_device_t lpt_prt_text_device; +extern const lpt_device_t lpt_prt_escp_device; +extern const lpt_device_t lpt_prt_ps_device; + +#endif /*EMU_PRT_DEVS_H*/ diff --git a/src/include/86box/random.h b/src/include/86box/random.h index 75ceb4c13..021969a54 100644 --- a/src/include/86box/random.h +++ b/src/include/86box/random.h @@ -1,25 +1,25 @@ /* - * 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. + * 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. + * This file is part of the 86Box distribution. * - * A better random number generation, used for floppy weak bits - * and network MAC address generation. + * A better random number generation, used for floppy weak bits + * and network MAC address generation. * * * - * Author: Miran Grca, - * Copyright 2016,2017 Miran Grca. + * Authors: Miran Grca, + * + * Copyright 2016-2017 Miran Grca. */ + #ifndef EMU_RANDOM_H -# define EMU_RANDOM_H +#define EMU_RANDOM_H +extern uint8_t random_generate(void); +extern void random_init(void); -extern uint8_t random_generate(void); -extern void random_init(void); - - -#endif /*EMU_RANDOM_H*/ +#endif /*EMU_RANDOM_H*/ diff --git a/src/include/86box/resource.h b/src/include/86box/resource.h index 242b6c9b4..20067aa40 100644 --- a/src/include/86box/resource.h +++ b/src/include/86box/resource.h @@ -1,468 +1,524 @@ /* - * 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. + * 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. + * This file is part of the 86Box distribution. * - * Windows resource defines. + * Windows resource defines. * * * - * Authors: Sarah Walker, - * Miran Grca, - * Fred N. van Kempen, - * David HrdliÄka, + * Authors: Sarah Walker, + * Miran Grca, + * Fred N. van Kempen, + * David HrdliÄka, * - * Copyright 2008-2019 Sarah Walker. - * Copyright 2016-2019 Miran Grca. - * Copyright 2018,2019 David HrdliÄka. + * Copyright 2008-2019 Sarah Walker. + * Copyright 2016-2019 Miran Grca. + * Copyright 2018-2019 David HrdliÄka. + * Copyright 2021-2022 Jasmine Iwanek. */ -#ifndef WIN_RESOURCE_H -# define WIN_RESOURCE_H +#ifndef WIN_RESOURCE_H +#define WIN_RESOURCE_H /* Dialog IDs. */ -#define DLG_ABOUT 101 /* top-level dialog */ -#define DLG_STATUS 102 /* top-level dialog */ -#define DLG_SND_GAIN 103 /* top-level dialog */ -#define DLG_NEW_FLOPPY 104 /* top-level dialog */ -#define DLG_SPECIFY_DIM 105 /* top-level dialog */ -#define DLG_PREFERENCES 106 /* top-level dialog */ -#define DLG_CONFIG 110 /* top-level dialog */ -#define DLG_CFG_MACHINE 111 /* sub-dialog of config */ -#define DLG_CFG_VIDEO 112 /* sub-dialog of config */ -#define DLG_CFG_INPUT 113 /* sub-dialog of config */ -#define DLG_CFG_SOUND 114 /* sub-dialog of config */ -#define DLG_CFG_NETWORK 115 /* sub-dialog of config */ -#define DLG_CFG_PORTS 116 /* sub-dialog of config */ -#define DLG_CFG_STORAGE 117 /* sub-dialog of config */ -#define DLG_CFG_HARD_DISKS 118 /* sub-dialog of config */ -#define DLG_CFG_HARD_DISKS_ADD 119 /* sub-dialog of config */ -#define DLG_CFG_FLOPPY_AND_CDROM_DRIVES 120 /* sub-dialog of config */ -#define DLG_CFG_OTHER_REMOVABLE_DEVICES 121 /* sub-dialog of config */ -#define DLG_CFG_PERIPHERALS 122 /* sub-dialog of config */ +#define DLG_ABOUT 101 /* top-level dialog */ +#define DLG_STATUS 102 /* top-level dialog */ +#define DLG_SND_GAIN 103 /* top-level dialog */ +#define DLG_NEW_FLOPPY 104 /* top-level dialog */ +#define DLG_SPECIFY_DIM 105 /* top-level dialog */ +#define DLG_PREFERENCES 106 /* top-level dialog */ +#define DLG_CONFIG 110 /* top-level dialog */ +#define DLG_CFG_MACHINE 111 /* sub-dialog of config */ +#define DLG_CFG_VIDEO 112 /* sub-dialog of config */ +#define DLG_CFG_INPUT 113 /* sub-dialog of config */ +#define DLG_CFG_SOUND 114 /* sub-dialog of config */ +#define DLG_CFG_NETWORK 115 /* sub-dialog of config */ +#define DLG_CFG_PORTS 116 /* sub-dialog of config */ +#define DLG_CFG_STORAGE 117 /* sub-dialog of config */ +#define DLG_CFG_HARD_DISKS 118 /* sub-dialog of config */ +#define DLG_CFG_HARD_DISKS_ADD 119 /* sub-dialog of config */ +#define DLG_CFG_FLOPPY_AND_CDROM_DRIVES 120 /* sub-dialog of config */ +#define DLG_CFG_OTHER_REMOVABLE_DEVICES 121 /* sub-dialog of config */ +#define DLG_CFG_PERIPHERALS 122 /* sub-dialog of config */ /* Static text label IDs. */ /* DLG_SND_GAIN */ -#define IDT_GAIN 1700 /* Gain */ +#define IDT_GAIN 1700 /* Gain */ /* DLG_NEW_FLOPPY */ -#define IDT_FLP_FILE_NAME 1701 /* File name: */ -#define IDT_FLP_DISK_SIZE 1702 /* Disk size: */ -#define IDT_FLP_RPM_MODE 1703 /* RPM mode: */ -#define IDT_FLP_PROGRESS 1704 /* Progress: */ +#define IDT_FLP_FILE_NAME 1701 /* File name: */ +#define IDT_FLP_DISK_SIZE 1702 /* Disk size: */ +#define IDT_FLP_RPM_MODE 1703 /* RPM mode: */ +#define IDT_FLP_PROGRESS 1704 /* Progress: */ /* DLG_SPECIFY_DIM */ -#define IDT_WIDTH 1705 /* ??? */ -#define IDT_HEIGHT 1706 /* ??? */ +#define IDT_WIDTH 1705 /* ??? */ +#define IDT_HEIGHT 1706 /* ??? */ /* DLG_CFG_MACHINE */ -#define IDT_MACHINE_TYPE 1707 /* Machine type: */ -#define IDT_MACHINE 1708 /* Machine: */ -#define IDT_CPU_TYPE 1709 /* CPU type: */ -#define IDT_CPU_SPEED 1710 /* CPU speed: */ -#define IDT_FPU 1711 /* FPU: */ -#define IDT_WAIT_STATES 1712 /* Wait states: */ -#define IDT_MB 1713 /* MB == IDC_TEXT_MB */ -#define IDT_MEMORY 1714 /* Memory: */ +#define IDT_MACHINE_TYPE 1707 /* Machine type: */ +#define IDT_MACHINE 1708 /* Machine: */ +#define IDT_CPU_TYPE 1709 /* CPU type: */ +#define IDT_CPU_SPEED 1710 /* CPU speed: */ +#define IDT_FPU 1711 /* FPU: */ +#define IDT_WAIT_STATES 1712 /* Wait states: */ +#define IDT_MB 1713 /* MB == IDC_TEXT_MB */ +#define IDT_MEMORY 1714 /* Memory: */ /* DLG_CFG_VIDEO */ -#define IDT_VIDEO 1715 /* Video: */ +#define IDT_VIDEO 1715 /* Video: */ +#define IDT_VIDEO_2 1716 /* Video 2: */ /* DLG_CFG_INPUT */ -#define IDT_MOUSE 1716 /* Mouse: */ -#define IDT_JOYSTICK 1717 /* Joystick: */ +#define IDT_MOUSE 1717 /* Mouse: */ +#define IDT_JOYSTICK 1718 /* Joystick: */ /* DLG_CFG_SOUND */ -#define IDT_SOUND 1718 /* Sound card: */ -#define IDT_MIDI_OUT 1719 /* MIDI Out Device: */ -#define IDT_MIDI_IN 1720 /* MIDI In Device: */ +#define IDT_SOUND1 1719 /* Sound card 1: */ +#define IDT_SOUND2 1720 /* Sound card 2: */ +#define IDT_SOUND3 1721 /* Sound card 3: */ +#define IDT_SOUND4 1722 /* Sound card 4: */ +#define IDT_MIDI_OUT 1723 /* MIDI Out Device: */ +#define IDT_MIDI_IN 1724 /* MIDI In Device: */ /* DLG_CFG_NETWORK */ -#define IDT_NET_TYPE 1721 /* Network type: */ -#define IDT_PCAP 1722 /* PCap device: */ -#define IDT_NET 1723 /* Network adapter: */ +#define IDT_NET_TYPE 1725 /* Network type: */ +#define IDT_PCAP 1726 /* PCap device: */ +#define IDT_NET 1727 /* Network adapter: */ +#define IDT_NET1 1728 /* Network adapter 1: */ +#define IDT_NET2 1729 /* Network adapter 2: */ +#define IDT_NET3 1730 /* Network adapter 3: */ +#define IDT_NET4 1731 /* Network adapter 4: */ /* DLG_CFG_PORTS */ -#define IDT_COM1 1724 /* COM1 Device: */ -#define IDT_COM2 1725 /* COM1 Device: */ -#define IDT_COM3 1726 /* COM1 Device: */ -#define IDT_COM4 1727 /* COM1 Device: */ +#define IDT_COM1 1732 /* COM1 Device: */ +#define IDT_COM2 1733 /* COM1 Device: */ +#define IDT_COM3 1734 /* COM1 Device: */ +#define IDT_COM4 1735 /* COM1 Device: */ -#define IDT_LPT1 1728 /* LPT1 Device: */ -#define IDT_LPT2 1729 /* LPT2 Device: */ -#define IDT_LPT3 1730 /* LPT3 Device: */ -#define IDT_LPT4 1731 /* LPT4 Device: */ +#define IDT_LPT1 1736 /* LPT1 Device: */ +#define IDT_LPT2 1737 /* LPT2 Device: */ +#define IDT_LPT3 1738 /* LPT3 Device: */ +#define IDT_LPT4 1739 /* LPT4 Device: */ /* DLG_CFG_STORAGE */ -#define IDT_HDC 1732 /* HD Controller: */ -#define IDT_FDC 1733 /* Ext FD Controller: */ -#define IDT_SCSI_1 1734 /* SCSI Board #1: */ -#define IDT_SCSI_2 1735 /* SCSI Board #2: */ -#define IDT_SCSI_3 1736 /* SCSI Board #3: */ -#define IDT_SCSI_4 1737 /* SCSI Board #4: */ +#define IDT_HDC 1740 /* HD Controller: */ +#define IDT_FDC 1741 /* Ext FD Controller: */ +#define IDT_SCSI_1 1742 /* SCSI Board #1: */ +#define IDT_SCSI_2 1743 /* SCSI Board #2: */ +#define IDT_SCSI_3 1744 /* SCSI Board #3: */ +#define IDT_SCSI_4 1745 /* SCSI Board #4: */ /* DLG_CFG_HARD_DISKS */ -#define IDT_HDD 1738 /* Hard disks: */ -#define IDT_BUS 1739 /* Bus: */ -#define IDT_CHANNEL 1740 /* Channel: */ -#define IDT_ID 1741 /* ID: */ -#define IDT_LUN 1742 /* LUN: */ +#define IDT_HDD 1746 /* Hard disks: */ +#define IDT_BUS 1747 /* Bus: */ +#define IDT_CHANNEL 1748 /* Channel: */ +#define IDT_ID 1749 /* ID: */ +#define IDT_LUN 1750 /* LUN: */ +#define IDT_SPEED 1751 /* Speed: */ /* DLG_CFG_HARD_DISKS_ADD */ -#define IDT_SECTORS 1743 /* Sectors: */ -#define IDT_HEADS 1744 /* Heads: */ -#define IDT_CYLS 1745 /* Cylinders: */ -#define IDT_SIZE_MB 1746 /* Size (MB): */ -#define IDT_TYPE 1747 /* Type: */ -#define IDT_FILE_NAME 1748 /* File name: */ -#define IDT_IMG_FORMAT 1749 /* Image Format: */ -#define IDT_BLOCK_SIZE 1750 /* Block Size: */ -#define IDT_PROGRESS 1751 /* Progress: */ +#define IDT_SECTORS 1752 /* Sectors: */ +#define IDT_HEADS 1753 /* Heads: */ +#define IDT_CYLS 1754 /* Cylinders: */ +#define IDT_SIZE_MB 1755 /* Size (MB): */ +#define IDT_TYPE 1756 /* Type: */ +#define IDT_FILE_NAME 1757 /* File name: */ +#define IDT_IMG_FORMAT 1758 /* Image Format: */ +#define IDT_BLOCK_SIZE 1759 /* Block Size: */ +#define IDT_PROGRESS 1760 /* Progress: */ /* DLG_CFG_FLOPPY_AND_CDROM_DRIVES */ -#define IDT_FLOPPY_DRIVES 1752 /* Floppy drives: */ -#define IDT_FDD_TYPE 1753 /* Type: */ -#define IDT_CD_DRIVES 1754 /* CD-ROM drives: */ -#define IDT_CD_BUS 1755 /* Bus: */ -#define IDT_CD_ID 1756 /* ID: */ -#define IDT_CD_LUN 1757 /* LUN: */ -#define IDT_CD_CHANNEL 1758 /* Channel: */ -#define IDT_CD_SPEED 1759 /* Speed: */ +#define IDT_FLOPPY_DRIVES 1761 /* Floppy drives: */ +#define IDT_FDD_TYPE 1762 /* Type: */ +#define IDT_CD_DRIVES 1763 /* CD-ROM drives: */ +#define IDT_CD_BUS 1764 /* Bus: */ +#define IDT_CD_ID 1765 /* ID: */ +#define IDT_CD_LUN 1766 /* LUN: */ +#define IDT_CD_CHANNEL 1767 /* Channel: */ +#define IDT_CD_SPEED 1768 /* Speed: */ +#define IDT_CD_TYPE 1769 /* Type: */ /* DLG_CFG_OTHER_REMOVABLE_DEVICES */ -#define IDT_MO_DRIVES 1760 /* MO drives: */ -#define IDT_MO_BUS 1761 /* Bus: */ -#define IDT_MO_ID 1762 /* ID: */ -#define IDT_MO_CHANNEL 1763 /* Channel */ -#define IDT_MO_TYPE 1764 /* Type: */ +#define IDT_MO_DRIVES 1770 /* MO drives: */ +#define IDT_MO_BUS 1771 /* Bus: */ +#define IDT_MO_ID 1772 /* ID: */ +#define IDT_MO_CHANNEL 1773 /* Channel */ +#define IDT_MO_TYPE 1774 /* Type: */ -#define IDT_ZIP_DRIVES 1765 /* ZIP drives: */ -#define IDT_ZIP_BUS 1766 /* Bus: */ -#define IDT_ZIP_ID 1767 /* ID: */ -#define IDT_ZIP_LUN 1768 /* LUN: */ -#define IDT_ZIP_CHANNEL 1769 /* Channel: */ +#define IDT_ZIP_DRIVES 1775 /* ZIP drives: */ +#define IDT_ZIP_BUS 1776 /* Bus: */ +#define IDT_ZIP_ID 1777 /* ID: */ +#define IDT_ZIP_LUN 1778 /* LUN: */ +#define IDT_ZIP_CHANNEL 1779 /* Channel: */ /* DLG_CFG_PERIPHERALS */ -#define IDT_ISARTC 1770 /* ISA RTC: */ -#define IDT_ISAMEM_1 1771 /* ISAMEM Board #1: */ -#define IDT_ISAMEM_2 1772 /* ISAMEM Board #2: */ -#define IDT_ISAMEM_3 1773 /* ISAMEM Board #3: */ -#define IDT_ISAMEM_4 1774 /* ISAMEM Board #4: */ +#define IDT_ISARTC 1780 /* ISA RTC: */ +#define IDT_ISAMEM_1 1781 /* ISAMEM Board #1: */ +#define IDT_ISAMEM_2 1782 /* ISAMEM Board #2: */ +#define IDT_ISAMEM_3 1783 /* ISAMEM Board #3: */ +#define IDT_ISAMEM_4 1784 /* ISAMEM Board #4: */ /* * To try to keep these organized, we now group the * constants per dialog, as this allows easy adding * and deleting items. */ -#define IDC_SETTINGSCATLIST 1001 /* generic config */ -#define IDC_CFILE 1002 /* Select File dialog */ -#define IDC_TIME_SYNC 1005 -#define IDC_RADIO_TS_DISABLED 1006 -#define IDC_RADIO_TS_LOCAL 1007 -#define IDC_RADIO_TS_UTC 1008 +#define IDC_SETTINGSCATLIST 1001 /* generic config */ +#define IDC_CFILE 1002 /* Select File dialog */ +#define IDC_TIME_SYNC 1005 +#define IDC_RADIO_TS_DISABLED 1006 +#define IDC_RADIO_TS_LOCAL 1007 +#define IDC_RADIO_TS_UTC 1008 -#define IDC_COMBO_MACHINE_TYPE 1010 -#define IDC_COMBO_MACHINE 1011 /* machine/cpu config */ -#define IDC_CONFIGURE_MACHINE 1012 -#define IDC_COMBO_CPU_TYPE 1013 -#define IDC_COMBO_CPU_SPEED 1014 -#define IDC_COMBO_FPU 1015 -#define IDC_COMBO_WS 1016 +#define IDC_COMBO_MACHINE_TYPE 1010 +#define IDC_COMBO_MACHINE 1011 /* machine/cpu config */ +#define IDC_CONFIGURE_MACHINE 1012 +#define IDC_COMBO_CPU_TYPE 1013 +#define IDC_COMBO_CPU_SPEED 1014 +#define IDC_COMBO_FPU 1015 +#define IDC_COMBO_WS 1016 #ifdef USE_DYNAREC -#define IDC_CHECK_DYNAREC 1017 +# define IDC_CHECK_DYNAREC 1017 #endif -#define IDC_MEMTEXT 1018 -#define IDC_MEMSPIN 1019 -#define IDC_TEXT_MB IDT_MB +#define IDC_CHECK_SOFTFLOAT 1018 +#define IDC_MEMTEXT 1019 +#define IDC_MEMSPIN 1020 +#define IDC_TEXT_MB IDT_MB -#define IDC_VIDEO 1020 /* video config */ -#define IDC_COMBO_VIDEO 1021 -#define IDC_CHECK_VOODOO 1022 -#define IDC_BUTTON_VOODOO 1023 +#define IDC_VIDEO 1021 /* video config */ +#define IDC_COMBO_VIDEO 1022 +#define IDC_VIDEO_2 1023 +#define IDC_COMBO_VIDEO_2 1024 +#define IDC_CHECK_VOODOO 1025 +#define IDC_BUTTON_VOODOO 1026 +#define IDC_CHECK_IBM8514 1027 +#define IDC_CHECK_XGA 1028 +#define IDC_BUTTON_XGA 1029 -#define IDC_INPUT 1030 /* input config */ -#define IDC_COMBO_MOUSE 1031 -#define IDC_COMBO_JOYSTICK 1032 -#define IDC_COMBO_JOY 1033 -#define IDC_CONFIGURE_MOUSE 1034 +#define IDC_INPUT 1030 /* input config */ +#define IDC_COMBO_MOUSE 1031 +#define IDC_COMBO_JOYSTICK 1032 +#define IDC_COMBO_JOY 1033 +#define IDC_CONFIGURE_MOUSE 1034 -#define IDC_SOUND 1040 /* sound config */ -#define IDC_COMBO_SOUND 1041 -#define IDC_CHECK_SSI 1042 -#define IDC_CHECK_CMS 1043 -#define IDC_CHECK_GUS 1044 -#define IDC_COMBO_MIDI_OUT 1045 -#define IDC_CHECK_MPU401 1046 -#define IDC_CONFIGURE_MPU401 1047 -#define IDC_CHECK_FLOAT 1048 -#define IDC_CONFIGURE_GUS 1049 -#define IDC_COMBO_MIDI_IN 1050 -#define IDC_CONFIGURE_CMS 1051 -#define IDC_CONFIGURE_SSI 1052 +#define IDC_SOUND 1040 /* sound config */ +#define IDC_COMBO_SOUND1 1041 +#define IDC_COMBO_SOUND2 1042 +#define IDC_COMBO_SOUND3 1043 +#define IDC_COMBO_SOUND4 1044 +#define IDC_COMBO_MIDI_OUT 1045 +#define IDC_CHECK_MPU401 1046 +#define IDC_CONFIGURE_MPU401 1047 +#define IDC_CHECK_FLOAT 1048 +#define IDC_CONFIGURE_GUS 1049 +#define IDC_COMBO_MIDI_IN 1050 +#define IDC_CONFIGURE_CMS 1051 +#define IDC_CONFIGURE_SSI 1052 +#define IDC_FM_DRIVER 1053 +#define IDC_RADIO_FM_DRV_NUKED 1054 +#define IDC_RADIO_FM_DRV_YMFM 1055 -#define IDC_COMBO_NET_TYPE 1060 /* network config */ -#define IDC_COMBO_PCAP 1061 -#define IDC_COMBO_NET 1062 +#define IDC_COMBO_NET1_TYPE 1060 /* network config */ +#define IDC_COMBO_NET2_TYPE 1061 +#define IDC_COMBO_NET3_TYPE 1062 +#define IDC_COMBO_NET4_TYPE 1063 +#define IDC_COMBO_PCAP1 1064 +#define IDC_COMBO_PCAP2 1065 +#define IDC_COMBO_PCAP3 1066 +#define IDC_COMBO_PCAP4 1067 +#define IDC_COMBO_NET1 1068 +#define IDC_COMBO_NET2 1069 +#define IDC_COMBO_NET3 1070 +#define IDC_COMBO_NET4 1071 -#define IDC_COMBO_LPT1 1070 /* ports config */ -#define IDC_COMBO_LPT2 1071 -#define IDC_COMBO_LPT3 1072 -#define IDC_COMBO_LPT4 1073 -#define IDC_CHECK_SERIAL1 1074 -#define IDC_CHECK_SERIAL2 1075 -#define IDC_CHECK_SERIAL3 1076 -#define IDC_CHECK_SERIAL4 1077 -#define IDC_CHECK_PARALLEL1 1078 -#define IDC_CHECK_PARALLEL2 1079 -#define IDC_CHECK_PARALLEL3 1080 -#define IDC_CHECK_PARALLEL4 1081 +#define IDC_COMBO_LPT1 1080 /* ports config */ +#define IDC_COMBO_LPT2 1081 +#define IDC_COMBO_LPT3 1082 +#define IDC_COMBO_LPT4 1083 +#define IDC_CHECK_SERIAL1 1084 +#define IDC_CHECK_SERIAL2 1085 +#define IDC_CHECK_SERIAL3 1086 +#define IDC_CHECK_SERIAL4 1087 +#define IDC_CHECK_PARALLEL1 1088 +#define IDC_CHECK_PARALLEL2 1089 +#define IDC_CHECK_PARALLEL3 1090 +#define IDC_CHECK_PARALLEL4 1091 +#define IDC_CHECK_SERIAL_PASS1 1092 +#define IDC_CHECK_SERIAL_PASS2 1093 +#define IDC_CHECK_SERIAL_PASS3 1094 +#define IDC_CHECK_SERIAL_PASS4 1095 -#define IDC_OTHER_PERIPH 1082 /* storage controllers config */ -#define IDC_COMBO_HDC 1083 -#define IDC_CONFIGURE_HDC 1084 -#define IDC_CHECK_IDE_TER 1085 -#define IDC_BUTTON_IDE_TER 1086 -#define IDC_CHECK_IDE_QUA 1087 -#define IDC_BUTTON_IDE_QUA 1088 -#define IDC_GROUP_SCSI 1089 -#define IDC_COMBO_SCSI_1 1090 -#define IDC_COMBO_SCSI_2 1091 -#define IDC_COMBO_SCSI_3 1092 -#define IDC_COMBO_SCSI_4 1093 -#define IDC_CONFIGURE_SCSI_1 1094 -#define IDC_CONFIGURE_SCSI_2 1095 -#define IDC_CONFIGURE_SCSI_3 1096 -#define IDC_CONFIGURE_SCSI_4 1097 -#define IDC_CHECK_CASSETTE 1098 +#define IDC_OTHER_PERIPH 1110 /* storage controllers config */ +#define IDC_COMBO_HDC 1111 +#define IDC_CONFIGURE_HDC 1112 +#define IDC_CHECK_IDE_TER 1113 +#define IDC_BUTTON_IDE_TER 1114 +#define IDC_CHECK_IDE_QUA 1115 +#define IDC_BUTTON_IDE_QUA 1116 +#define IDC_GROUP_SCSI 1117 +#define IDC_COMBO_SCSI_1 1118 +#define IDC_COMBO_SCSI_2 1119 +#define IDC_COMBO_SCSI_3 1120 +#define IDC_COMBO_SCSI_4 1121 +#define IDC_CONFIGURE_SCSI_1 1122 +#define IDC_CONFIGURE_SCSI_2 1123 +#define IDC_CONFIGURE_SCSI_3 1124 +#define IDC_CONFIGURE_SCSI_4 1125 +#define IDC_CHECK_CASSETTE 1126 -#define IDC_HARD_DISKS 1100 /* hard disks config */ -#define IDC_LIST_HARD_DISKS 1101 -#define IDC_BUTTON_HDD_ADD_NEW 1102 -#define IDC_BUTTON_HDD_ADD 1103 -#define IDC_BUTTON_HDD_REMOVE 1104 -#define IDC_COMBO_HD_BUS 1105 -#define IDC_COMBO_HD_CHANNEL 1106 -#define IDC_COMBO_HD_ID 1107 -#define IDC_COMBO_HD_LUN 1108 -#define IDC_COMBO_HD_CHANNEL_IDE 1109 +#define IDC_HARD_DISKS 1130 /* hard disks config */ +#define IDC_LIST_HARD_DISKS 1131 +#define IDC_BUTTON_HDD_ADD_NEW 1132 +#define IDC_BUTTON_HDD_ADD 1133 +#define IDC_BUTTON_HDD_REMOVE 1134 +#define IDC_COMBO_HD_BUS 1135 +#define IDC_COMBO_HD_CHANNEL 1136 +#define IDC_COMBO_HD_ID 1137 +#define IDC_COMBO_HD_SPEED 1138 +#define IDC_COMBO_HD_CHANNEL_IDE 1139 -#define IDC_EDIT_HD_FILE_NAME 1110 /* add hard disk dialog */ -#define IDC_EDIT_HD_SPT 1111 -#define IDC_EDIT_HD_HPC 1112 -#define IDC_EDIT_HD_CYL 1113 -#define IDC_EDIT_HD_SIZE 1114 -#define IDC_COMBO_HD_TYPE 1115 -#define IDC_PBAR_IMG_CREATE 1116 -#define IDC_COMBO_HD_IMG_FORMAT 1117 -#define IDC_COMBO_HD_BLOCK_SIZE 1118 +#define IDC_EDIT_HD_FILE_NAME 1140 /* add hard disk dialog */ +#define IDC_EDIT_HD_SPT 1141 +#define IDC_EDIT_HD_HPC 1142 +#define IDC_EDIT_HD_CYL 1143 +#define IDC_EDIT_HD_SIZE 1144 +#define IDC_COMBO_HD_TYPE 1145 +#define IDC_PBAR_IMG_CREATE 1146 +#define IDC_COMBO_HD_IMG_FORMAT 1147 +#define IDC_COMBO_HD_BLOCK_SIZE 1148 -#define IDC_REMOV_DEVICES 1120 /* floppy and cd-rom drives config */ -#define IDC_LIST_FLOPPY_DRIVES 1121 -#define IDC_COMBO_FD_TYPE 1122 -#define IDC_CHECKTURBO 1123 -#define IDC_CHECKBPB 1124 -#define IDC_LIST_CDROM_DRIVES 1125 -#define IDC_COMBO_CD_BUS 1126 -#define IDC_COMBO_CD_ID 1127 -#define IDC_COMBO_CD_LUN 1128 -#define IDC_COMBO_CD_CHANNEL_IDE 1129 +#define IDC_REMOV_DEVICES 1150 /* floppy and cd-rom drives config */ +#define IDC_LIST_FLOPPY_DRIVES 1151 +#define IDC_COMBO_FD_TYPE 1152 +#define IDC_CHECKTURBO 1153 +#define IDC_CHECKBPB 1154 +#define IDC_LIST_CDROM_DRIVES 1155 +#define IDC_COMBO_CD_BUS 1156 +#define IDC_COMBO_CD_ID 1157 +#define IDC_COMBO_CD_LUN 1158 +#define IDC_COMBO_CD_CHANNEL_IDE 1159 +#define IDC_COMBO_CD_TYPE 1160 -#define IDC_LIST_ZIP_DRIVES 1130 /* other removable devices config */ -#define IDC_COMBO_ZIP_BUS 1131 -#define IDC_COMBO_ZIP_ID 1132 -#define IDC_COMBO_ZIP_LUN 1133 -#define IDC_COMBO_ZIP_CHANNEL_IDE 1134 -#define IDC_CHECK250 1135 -#define IDC_COMBO_CD_SPEED 1136 -#define IDC_LIST_MO_DRIVES 1137 -#define IDC_COMBO_MO_BUS 1138 -#define IDC_COMBO_MO_ID 1139 -#define IDC_COMBO_MO_LUN 1140 -#define IDC_COMBO_MO_CHANNEL_IDE 1141 -#define IDC_COMBO_MO_TYPE 1142 +#define IDC_LIST_ZIP_DRIVES 1170 /* other removable devices config */ +#define IDC_COMBO_ZIP_BUS 1171 +#define IDC_COMBO_ZIP_ID 1172 +#define IDC_COMBO_ZIP_LUN 1173 +#define IDC_COMBO_ZIP_CHANNEL_IDE 1174 +#define IDC_CHECK250 1175 +#define IDC_COMBO_CD_SPEED 1176 +#define IDC_LIST_MO_DRIVES 1177 +#define IDC_COMBO_MO_BUS 1178 +#define IDC_COMBO_MO_ID 1179 +#define IDC_COMBO_MO_LUN 1170 +#define IDC_COMBO_MO_CHANNEL_IDE 1181 +#define IDC_COMBO_MO_TYPE 1182 -#define IDC_CHECK_BUGGER 1150 /* other periph config */ -#define IDC_CHECK_POSTCARD 1151 -#define IDC_COMBO_ISARTC 1152 -#define IDC_CONFIGURE_ISARTC 1153 -#define IDC_COMBO_FDC 1154 -#define IDC_CONFIGURE_FDC 1155 -#define IDC_GROUP_ISAMEM 1156 -#define IDC_COMBO_ISAMEM_1 1157 -#define IDC_COMBO_ISAMEM_2 1158 -#define IDC_COMBO_ISAMEM_3 1159 -#define IDC_COMBO_ISAMEM_4 1160 -#define IDC_CONFIGURE_ISAMEM_1 1161 -#define IDC_CONFIGURE_ISAMEM_2 1162 -#define IDC_CONFIGURE_ISAMEM_3 1163 -#define IDC_CONFIGURE_ISAMEM_4 1164 +#define IDC_CHECK_BUGGER 1190 /* other periph config */ +#define IDC_CHECK_POSTCARD 1191 +#define IDC_COMBO_ISARTC 1192 +#define IDC_CONFIGURE_ISARTC 1193 +#define IDC_COMBO_FDC 1194 +#define IDC_CONFIGURE_FDC 1195 +#define IDC_GROUP_ISAMEM 1196 +#define IDC_COMBO_ISAMEM_1 1197 +#define IDC_COMBO_ISAMEM_2 1198 +#define IDC_COMBO_ISAMEM_3 1199 +#define IDC_COMBO_ISAMEM_4 1200 +#define IDC_CONFIGURE_ISAMEM_1 1201 +#define IDC_CONFIGURE_ISAMEM_2 1202 +#define IDC_CONFIGURE_ISAMEM_3 1203 +#define IDC_CONFIGURE_ISAMEM_4 1204 -#define IDC_SLIDER_GAIN 1170 /* sound gain dialog */ +#define IDC_SLIDER_GAIN 1210 /* sound gain dialog */ -#define IDC_EDIT_FILE_NAME 1200 /* new floppy image dialog */ -#define IDC_COMBO_DISK_SIZE 1201 -#define IDC_COMBO_RPM_MODE 1202 +#define IDC_EDIT_FILE_NAME 1220 /* new floppy image dialog */ +#define IDC_COMBO_DISK_SIZE 1221 +#define IDC_COMBO_RPM_MODE 1222 -#define IDC_COMBO_LANG 1009 /* change language dialog */ -#define IDC_COMBO_ICON 1010 -#define IDC_CHECKBOX_GLOBAL 1300 -#define IDC_BUTTON_DEFAULT 1302 -#define IDC_BUTTON_DEFICON 1304 +#define IDC_COMBO_LANG 1009 /* change language dialog */ +#define IDC_COMBO_ICON 1010 +#define IDC_CHECKBOX_GLOBAL 1300 +#define IDC_BUTTON_DEFAULT 1302 +#define IDC_BUTTON_DEFICON 1304 /* For the DeviceConfig code, re-do later. */ -#define IDC_CONFIG_BASE 1300 -#define IDC_CONFIGURE_VID 1300 -#define IDC_CONFIGURE_SND 1301 -#define IDC_CONFIGURE_VOODOO 1302 -#define IDC_CONFIGURE_MOD 1303 -#define IDC_CONFIGURE_NET_TYPE 1304 -#define IDC_CONFIGURE_BUSLOGIC 1305 -#define IDC_CONFIGURE_PCAP 1306 -#define IDC_CONFIGURE_NET 1307 -#define IDC_CONFIGURE_MIDI_OUT 1308 -#define IDC_CONFIGURE_MIDI_IN 1309 -#define IDC_JOY1 1310 -#define IDC_JOY2 1311 -#define IDC_JOY3 1312 -#define IDC_JOY4 1313 -#define IDC_HDTYPE 1380 -#define IDC_RENDER 1381 -#define IDC_STATUS 1382 +#define IDC_CONFIG_BASE 1300 +#define IDC_CONFIGURE_VID 1300 +#define IDC_CONFIGURE_VID_2 1301 +#define IDC_CONFIGURE_SND1 1302 +#define IDC_CONFIGURE_SND2 1303 +#define IDC_CONFIGURE_SND3 1304 +#define IDC_CONFIGURE_SND4 1305 +#define IDC_CONFIGURE_VOODOO 1306 +#define IDC_CONFIGURE_NET1_TYPE 1310 +#define IDC_CONFIGURE_NET2_TYPE 1311 +#define IDC_CONFIGURE_NET3_TYPE 1312 +#define IDC_CONFIGURE_NET4_TYPE 1313 +#define IDC_CONFIGURE_PCAP1 1314 +#define IDC_CONFIGURE_PCAP2 1315 +#define IDC_CONFIGURE_PCAP3 1316 +#define IDC_CONFIGURE_PCAP4 1317 +#define IDC_CONFIGURE_NET1 1318 +#define IDC_CONFIGURE_NET2 1319 +#define IDC_CONFIGURE_NET3 1320 +#define IDC_CONFIGURE_NET4 1321 +#define IDC_CONFIGURE_MIDI_OUT 1322 +#define IDC_CONFIGURE_MIDI_IN 1323 +#define IDC_CONFIGURE_SERIAL_PASS1 1324 +#define IDC_CONFIGURE_SERIAL_PASS2 1325 +#define IDC_CONFIGURE_SERIAL_PASS3 1326 +#define IDC_CONFIGURE_SERIAL_PASS4 1327 +#define IDC_JOY1 1330 +#define IDC_JOY2 1331 +#define IDC_JOY3 1332 +#define IDC_JOY4 1333 +#define IDC_HDTYPE 1380 +#define IDC_RENDER 1381 +#define IDC_STATUS 1382 -#define IDC_EDIT_WIDTH 1400 /* specify main window dimensions dialog */ -#define IDC_WIDTHSPIN 1401 -#define IDC_EDIT_HEIGHT 1402 -#define IDC_HEIGHTSPIN 1403 -#define IDC_CHECK_LOCK_SIZE 1404 +#define IDC_EDIT_WIDTH 1400 /* specify main window dimensions dialog */ +#define IDC_WIDTHSPIN 1401 +#define IDC_EDIT_HEIGHT 1402 +#define IDC_HEIGHTSPIN 1403 +#define IDC_CHECK_LOCK_SIZE 1404 -#define IDM_ABOUT 40001 -#define IDC_ABOUT_ICON 65535 -#define IDM_ACTION_KBD_REQ_CAPTURE 40010 -#define IDM_ACTION_RCTRL_IS_LALT 40011 -#define IDM_ACTION_SCREENSHOT 40012 -#define IDM_ACTION_HRESET 40013 -#define IDM_ACTION_RESET_CAD 40014 -#define IDM_ACTION_EXIT 40015 -#define IDM_ACTION_CTRL_ALT_ESC 40016 -#define IDM_ACTION_PAUSE 40017 +#define IDM_ABOUT 40001 +#define IDC_ABOUT_ICON 65535 +#define IDM_ACTION_KBD_REQ_CAPTURE 40010 +#define IDM_ACTION_RCTRL_IS_LALT 40011 +#define IDM_ACTION_SCREENSHOT 40012 +#define IDM_ACTION_HRESET 40013 +#define IDM_ACTION_RESET_CAD 40014 +#define IDM_ACTION_EXIT 40015 +#define IDM_ACTION_CTRL_ALT_ESC 40016 +#define IDM_ACTION_PAUSE 40017 #ifdef MTR_ENABLED -#define IDM_ACTION_BEGIN_TRACE 40018 -#define IDM_ACTION_END_TRACE 40019 -#define IDM_ACTION_TRACE 40020 +# define IDM_ACTION_BEGIN_TRACE 40018 +# define IDM_ACTION_END_TRACE 40019 +# define IDM_ACTION_TRACE 40020 #endif -#define IDM_CONFIG 40020 -#define IDM_VID_HIDE_STATUS_BAR 40021 -#define IDM_VID_HIDE_TOOLBAR 40022 -#define IDM_UPDATE_ICONS 40030 -#define IDM_SND_GAIN 40031 -#define IDM_VID_RESIZE 40040 -#define IDM_VID_REMEMBER 40041 -#define IDM_VID_SDL_SW 40050 -#define IDM_VID_SDL_HW 40051 -#define IDM_VID_SDL_OPENGL 40052 -#define IDM_VID_OPENGL_CORE 40053 +#define IDM_CONFIG 40021 +#define IDM_VID_HIDE_STATUS_BAR 40022 +#define IDM_VID_HIDE_TOOLBAR 40023 +#define IDM_UPDATE_ICONS 40030 +#define IDM_SND_GAIN 40031 +#define IDM_VID_MONITORS 40040 +#define IDM_VID_RESIZE 40041 +#define IDM_VID_REMEMBER 40042 +#define IDM_VID_SDL_SW 40050 +#define IDM_VID_SDL_HW 40051 +#define IDM_VID_SDL_OPENGL 40052 +#define IDM_VID_OPENGL_CORE 40053 #ifdef USE_VNC -#define IDM_VID_VNC 40054 +# define IDM_VID_VNC 40054 #endif -#define IDM_VID_SCALE_1X 40055 -#define IDM_VID_SCALE_2X 40056 -#define IDM_VID_SCALE_3X 40057 -#define IDM_VID_SCALE_4X 40058 -#define IDM_VID_HIDPI 40059 -#define IDM_VID_FULLSCREEN 40060 -#define IDM_VID_FS_FULL 40061 -#define IDM_VID_FS_43 40062 -#define IDM_VID_FS_KEEPRATIO 40063 -#define IDM_VID_FS_INT 40064 -#define IDM_VID_SPECIFY_DIM 40065 -#define IDM_VID_FORCE43 40066 -#define IDM_VID_OVERSCAN 40067 -#define IDM_VID_INVERT 40069 -#define IDM_VID_CGACON 40070 -#define IDM_VID_GRAYCT_601 40075 -#define IDM_VID_GRAYCT_709 40076 -#define IDM_VID_GRAYCT_AVE 40077 -#define IDM_VID_GRAY_RGB 40080 -#define IDM_VID_GRAY_MONO 40081 -#define IDM_VID_GRAY_AMBER 40082 -#define IDM_VID_GRAY_GREEN 40083 -#define IDM_VID_GRAY_WHITE 40084 -#define IDM_VID_FILTER_NEAREST 40085 -#define IDM_VID_FILTER_LINEAR 40086 +#define IDM_VID_SCALE_1X 40055 +#define IDM_VID_SCALE_2X 40056 +#define IDM_VID_SCALE_3X 40057 +#define IDM_VID_SCALE_4X 40058 +#define IDM_VID_SCALE_5X 40059 +#define IDM_VID_SCALE_6X 40060 +#define IDM_VID_SCALE_7X 40061 +#define IDM_VID_SCALE_8X 40062 +#define IDM_VID_SCALE_9X 40063 +#define IDM_VID_SCALE_10X 40064 -#define IDM_MEDIA 40087 -#define IDM_DOCS 40088 +#define IDM_VID_HIDPI 40065 +#define IDM_VID_FULLSCREEN 40066 +#define IDM_VID_FS_FULL 40067 +#define IDM_VID_FS_43 40068 +#define IDM_VID_FS_KEEPRATIO 40069 +#define IDM_VID_FS_INT 40070 +#define IDM_VID_SPECIFY_DIM 40071 +#define IDM_VID_FORCE43 40072 +#define IDM_VID_OVERSCAN 40073 +#define IDM_VID_INVERT 40074 +#define IDM_VID_CGACON 40075 +#define IDM_VID_GRAYCT_601 40076 +#define IDM_VID_GRAYCT_709 40077 +#define IDM_VID_GRAYCT_AVE 40078 +#define IDM_VID_GRAY_RGB 40080 +#define IDM_VID_GRAY_MONO 40081 +#define IDM_VID_GRAY_AMBER 40082 +#define IDM_VID_GRAY_GREEN 40083 +#define IDM_VID_GRAY_WHITE 40084 +#define IDM_VID_FILTER_NEAREST 40085 +#define IDM_VID_FILTER_LINEAR 40086 -#define IDM_DISCORD 40090 +#define IDM_MEDIA 40087 +#define IDM_DOCS 40088 -#define IDM_PREFERENCES 40091 +#define IDM_DISCORD 40090 -#define IDM_VID_GL_FPS_BLITTER 40100 -#define IDM_VID_GL_FPS_25 40101 -#define IDM_VID_GL_FPS_30 40102 -#define IDM_VID_GL_FPS_50 40103 -#define IDM_VID_GL_FPS_60 40104 -#define IDM_VID_GL_FPS_75 40105 -#define IDM_VID_GL_VSYNC 40106 -#define IDM_VID_GL_SHADER 40107 -#define IDM_VID_GL_NOSHADER 40108 +#define IDM_PREFERENCES 40091 + +#define IDM_VID_GL_FPS_BLITTER 40100 +#define IDM_VID_GL_FPS_25 40101 +#define IDM_VID_GL_FPS_30 40102 +#define IDM_VID_GL_FPS_50 40103 +#define IDM_VID_GL_FPS_60 40104 +#define IDM_VID_GL_FPS_75 40105 +#define IDM_VID_GL_VSYNC 40106 +#define IDM_VID_GL_SHADER 40107 +#define IDM_VID_GL_NOSHADER 40108 /* * We need 7 bits for CDROM (2 bits ID and 5 bits for host drive), * and 5 bits for Removable Disks (5 bits for ID), so we use an * 8bit (256 entries) space for these devices. */ -#define IDM_CASSETTE_IMAGE_NEW 0x1200 -#define IDM_CASSETTE_IMAGE_EXISTING 0x1300 -#define IDM_CASSETTE_IMAGE_EXISTING_WP 0x1400 -#define IDM_CASSETTE_RECORD 0x1500 -#define IDM_CASSETTE_PLAY 0x1600 -#define IDM_CASSETTE_REWIND 0x1700 -#define IDM_CASSETTE_FAST_FORWARD 0x1800 -#define IDM_CASSETTE_EJECT 0x1900 +#define IDM_CASSETTE_IMAGE_NEW 0x1200 +#define IDM_CASSETTE_IMAGE_EXISTING 0x1300 +#define IDM_CASSETTE_IMAGE_EXISTING_WP 0x1400 +#define IDM_CASSETTE_RECORD 0x1500 +#define IDM_CASSETTE_PLAY 0x1600 +#define IDM_CASSETTE_REWIND 0x1700 +#define IDM_CASSETTE_FAST_FORWARD 0x1800 +#define IDM_CASSETTE_EJECT 0x1900 -#define IDM_CARTRIDGE_IMAGE 0x2200 -#define IDM_CARTRIDGE_EJECT 0x2300 +#define IDM_CARTRIDGE_IMAGE 0x2200 +#define IDM_CARTRIDGE_EJECT 0x2300 -#define IDM_FLOPPY_IMAGE_NEW 0x3200 -#define IDM_FLOPPY_IMAGE_EXISTING 0x3300 -#define IDM_FLOPPY_IMAGE_EXISTING_WP 0x3400 -#define IDM_FLOPPY_EXPORT_TO_86F 0x3500 -#define IDM_FLOPPY_EJECT 0x3600 +#define IDM_FLOPPY_IMAGE_NEW 0x3200 +#define IDM_FLOPPY_IMAGE_EXISTING 0x3300 +#define IDM_FLOPPY_IMAGE_EXISTING_WP 0x3400 +#define IDM_FLOPPY_EXPORT_TO_86F 0x3500 +#define IDM_FLOPPY_EJECT 0x3600 -#define IDM_CDROM_MUTE 0x4200 -#define IDM_CDROM_EMPTY 0x4300 -#define IDM_CDROM_RELOAD 0x4400 -#define IDM_CDROM_IMAGE 0x4500 -#define IDM_CDROM_HOST_DRIVE 0x4600 +#define IDM_CDROM_MUTE 0x4200 +#define IDM_CDROM_EMPTY 0x4300 +#define IDM_CDROM_RELOAD 0x4400 +#define IDM_CDROM_IMAGE 0x4500 +#define IDM_CDROM_DIR 0x4600 +#define IDM_CDROM_HOST_DRIVE 0x4700 -#define IDM_ZIP_IMAGE_NEW 0x5200 -#define IDM_ZIP_IMAGE_EXISTING 0x5300 -#define IDM_ZIP_IMAGE_EXISTING_WP 0x5400 -#define IDM_ZIP_EJECT 0x5500 -#define IDM_ZIP_RELOAD 0x5600 - -#define IDM_MO_IMAGE_NEW 0x6200 -#define IDM_MO_IMAGE_EXISTING 0x6300 -#define IDM_MO_IMAGE_EXISTING_WP 0x6400 -#define IDM_MO_EJECT 0x6500 -#define IDM_MO_RELOAD 0x6600 +#define IDM_ZIP_IMAGE_NEW 0x5200 +#define IDM_ZIP_IMAGE_EXISTING 0x5300 +#define IDM_ZIP_IMAGE_EXISTING_WP 0x5400 +#define IDM_ZIP_EJECT 0x5500 +#define IDM_ZIP_RELOAD 0x5600 +#define IDM_MO_IMAGE_NEW 0x6200 +#define IDM_MO_IMAGE_EXISTING 0x6300 +#define IDM_MO_IMAGE_EXISTING_WP 0x6400 +#define IDM_MO_EJECT 0x6500 +#define IDM_MO_RELOAD 0x6600 /* Next default values for new objects */ #ifdef APSTUDIO_INVOKED -# ifndef APSTUDIO_READONLY_SYMBOLS -# define _APS_NO_MFC 1 -# define _APS_NEXT_RESOURCE_VALUE 1400 -# define _APS_NEXT_COMMAND_VALUE 55000 -# define _APS_NEXT_CONTROL_VALUE 1800 -# define _APS_NEXT_SYMED_VALUE 200 -# endif +# ifndef APSTUDIO_READONLY_SYMBOLS +# define _APS_NO_MFC 1 +# define _APS_NEXT_RESOURCE_VALUE 1400 +# define _APS_NEXT_COMMAND_VALUE 55000 +# define _APS_NEXT_CONTROL_VALUE 1800 +# define _APS_NEXT_SYMED_VALUE 200 +# endif #endif - -#endif /*WIN_RESOURCE_H*/ +#endif /*WIN_RESOURCE_H*/ diff --git a/src/include/86box/rom.h b/src/include/86box/rom.h index 08ab241cf..1f6e611b1 100644 --- a/src/include/86box/rom.h +++ b/src/include/86box/rom.h @@ -1,84 +1,90 @@ /* - * 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. + * 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. + * This file is part of the 86Box distribution. * - * Definitions for the ROM image handler. + * Definitions for the ROM image handler. * * * - * Author: Fred N. van Kempen, - * Copyright 2018,2019 Fred N. van Kempen. + * Authors: Fred N. van Kempen, + * + * Copyright 2018-2019 Fred N. van Kempen. */ + #ifndef EMU_ROM_H -# define EMU_ROM_H +#define EMU_ROM_H +#define FLAG_INT 1 +#define FLAG_INV 2 +#define FLAG_AUX 4 +#define FLAG_REP 8 -#define FLAG_INT 1 -#define FLAG_INV 2 -#define FLAG_AUX 4 -#define FLAG_REP 8 +#define bios_load_linear(a, b, c, d) bios_load(a, NULL, b, c, d, 0) +#define bios_load_linearr(a, b, c, d) bios_load(a, NULL, b, c, d, FLAG_REP) +#define bios_load_aux_linear(a, b, c, d) bios_load(a, NULL, b, c, d, FLAG_AUX) +#define bios_load_linear_inverted(a, b, c, d) bios_load(a, NULL, b, c, d, FLAG_INV) +#define bios_load_aux_linear_inverted(a, b, c, d) bios_load(a, NULL, b, c, d, FLAG_INV | FLAG_AUX) +#define bios_load_interleaved(a, b, c, d, e) bios_load(a, b, c, d, e, FLAG_INT) +#define bios_load_interleavedr(a, b, c, d, e) bios_load(a, b, c, d, e, FLAG_INT | FLAG_REP) +#define bios_load_aux_interleaved(a, b, c, d, e) bios_load(a, b, c, d, e, FLAG_INT | FLAG_AUX) - -#define bios_load_linear(a, b, c, d) bios_load(a, NULL, b, c, d, 0) -#define bios_load_linearr(a, b, c, d) bios_load(a, NULL, b, c, d, FLAG_REP) -#define bios_load_aux_linear(a, b, c, d) bios_load(a, NULL, b, c, d, FLAG_AUX) -#define bios_load_linear_inverted(a, b, c, d) bios_load(a, NULL, b, c, d, FLAG_INV) -#define bios_load_aux_linear_inverted(a, b, c, d) bios_load(a, NULL, b, c, d, FLAG_INV | FLAG_AUX) -#define bios_load_interleaved(a, b, c, d, e) bios_load(a, b, c, d, e, FLAG_INT) -#define bios_load_interleavedr(a, b, c, d, e) bios_load(a, b, c, d, e, FLAG_INT | FLAG_REP) -#define bios_load_aux_interleaved(a, b, c, d, e) bios_load(a, b, c, d, e, FLAG_INT | FLAG_AUX) - - -typedef struct { - uint8_t *rom; - int sz; - uint32_t mask; - mem_mapping_t mapping; +typedef struct rom_t { + uint8_t *rom; + int sz; + uint32_t mask; + mem_mapping_t mapping; } rom_t; +typedef struct rom_path_t { + char path[1024]; + struct rom_path_t *next; +} rom_path_t; -extern uint8_t rom_read(uint32_t addr, void *p); -extern uint16_t rom_readw(uint32_t addr, void *p); -extern uint32_t rom_readl(uint32_t addr, void *p); +extern rom_path_t rom_paths; -extern FILE *rom_fopen(char *fn, char *mode); -extern int rom_getfile(char *fn, char *s, int size); -extern int rom_present(char *fn); +extern void rom_add_path(const char *path); -extern int rom_load_linear_oddeven(char *fn, uint32_t addr, int sz, - int off, uint8_t *ptr); -extern int rom_load_linear(char *fn, uint32_t addr, int sz, - int off, uint8_t *ptr); -extern int rom_load_interleaved(char *fnl, char *fnh, uint32_t addr, - int sz, int off, uint8_t *ptr); +extern uint8_t rom_read(uint32_t addr, void *priv); +extern uint16_t rom_readw(uint32_t addr, void *priv); +extern uint32_t rom_readl(uint32_t addr, void *priv); -extern uint8_t bios_read(uint32_t addr, void *priv); -extern uint16_t bios_readw(uint32_t addr, void *priv); -extern uint32_t bios_readl(uint32_t addr, void *priv); +extern FILE *rom_fopen(const char *fn, char *mode); +extern int rom_getfile(char *fn, char *s, int size); +extern int rom_present(const char *fn); -extern int bios_load(char *fn1, char *fn2, uint32_t addr, int sz, - int off, int flags); -extern int bios_load_linear_combined(char *fn1, char *fn2, - int sz, int off); -extern int bios_load_linear_combined2(char *fn1, char *fn2, - char *fn3, char *fn4, char *fn5, - int sz, int off); -extern int bios_load_linear_combined2_ex(char *fn1, char *fn2, - char *fn3, char *fn4, char *fn5, - int sz, int off); +extern int rom_load_linear_oddeven(const char *fn, uint32_t addr, int sz, + int off, uint8_t *ptr); +extern int rom_load_linear(const char *fn, uint32_t addr, int sz, + int off, uint8_t *ptr); +extern int rom_load_interleaved(const char *fnl, const char *fnh, uint32_t addr, + int sz, int off, uint8_t *ptr); -extern int rom_init(rom_t *rom, char *fn, uint32_t address, int size, - int mask, int file_offset, uint32_t flags); -extern int rom_init_oddeven(rom_t *rom, char *fn, uint32_t address, int size, - int mask, int file_offset, uint32_t flags); -extern int rom_init_interleaved(rom_t *rom, char *fn_low, - char *fn_high, uint32_t address, - int size, int mask, int file_offset, - uint32_t flags); +extern uint8_t bios_read(uint32_t addr, void *priv); +extern uint16_t bios_readw(uint32_t addr, void *priv); +extern uint32_t bios_readl(uint32_t addr, void *priv); +extern int bios_load(const char *fn1, const char *fn2, uint32_t addr, int sz, + int off, int flags); +extern int bios_load_linear_combined(const char *fn1, const char *fn2, + int sz, int off); +extern int bios_load_linear_combined2(const char *fn1, const char *fn2, + const char *fn3, const char *fn4, const char *fn5, + int sz, int off); +extern int bios_load_linear_combined2_ex(const char *fn1, const char *fn2, + const char *fn3, const char *fn4, const char *fn5, + int sz, int off); -#endif /*EMU_ROM_H*/ +extern int rom_init(rom_t *rom, const char *fn, uint32_t address, int size, + int mask, int file_offset, uint32_t flags); +extern int rom_init_oddeven(rom_t *rom, const char *fn, uint32_t address, int size, + int mask, int file_offset, uint32_t flags); +extern int rom_init_interleaved(rom_t *rom, const char *fn_low, + const char *fn_high, uint32_t address, + int size, int mask, int file_offset, + uint32_t flags); + +#endif /*EMU_ROM_H*/ diff --git a/src/include/86box/row.h b/src/include/86box/row.h new file mode 100644 index 000000000..a70c94274 --- /dev/null +++ b/src/include/86box/row.h @@ -0,0 +1,42 @@ +/* + * 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. + * + * Definitions for the SMRAM interface. + * + * + * + * Authors: Miran Grca, + * + * Copyright 2016-2020 Miran Grca. + */ + +#ifndef EMU_ROW_H +# define EMU_ROW_H + +typedef struct _row_ { + struct _smram_ *prev; + struct _smram_ *next; + + uint8_t *buf; + + mem_mapping_t mapping; + + uint32_t host_base; + uint32_t host_size; + uint32_t ram_base; + uint32_t ram_size; + uint32_t ram_mask; + uint32_t boundary; +} row_t; + +extern void row_disable(uint8_t row_id); +extern void row_set_boundary(uint8_t row_id, uint32_t boundary); + +extern device_t row_device; + +#endif /*EMU_ROW_H*/ diff --git a/src/include/86box/scsi.h b/src/include/86box/scsi.h index 16d10bb98..376ac79b9 100644 --- a/src/include/86box/scsi.h +++ b/src/include/86box/scsi.h @@ -1,35 +1,41 @@ /* - * 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. + * 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. + * This file is part of the 86Box distribution. * - * SCSI controller handler header. + * SCSI controller handler header. * * * - * Authors: TheCollector1995, - * Miran Grca, - * Fred N. van Kempen, + * Authors: TheCollector1995, + * Miran Grca, + * Fred N. van Kempen, * - * Copyright 2016-2018 TheCollector1995. - * Copyright 2016-2018 Miran Grca. - * Copyright 2017,2018 Fred N. van Kempen. + * Copyright 2016-2018 TheCollector1995. + * Copyright 2016-2018 Miran Grca. + * Copyright 2017-2018 Fred N. van Kempen. */ #ifndef EMU_SCSI_H #define EMU_SCSI_H -extern int scsi_card_current[4]; +/* Configuration. */ +#define SCSI_BUS_MAX 4 /* currently we support up to 4 controllers */ -extern int scsi_card_available(int card); +#define SCSI_ID_MAX 16 /* 16 on wide buses */ +#define SCSI_LUN_MAX 8 /* always 8 */ + +extern int scsi_card_current[SCSI_BUS_MAX]; + +extern int scsi_card_available(int card); #ifdef EMU_DEVICE_H -extern const device_t *scsi_card_getdevice(int card); +extern const device_t *scsi_card_getdevice(int card); #endif -extern int scsi_card_has_config(int card); -extern char *scsi_card_get_internal_name(int card); -extern int scsi_card_get_from_internal_name(char *s); -extern void scsi_card_init(void); +extern int scsi_card_has_config(int card); +extern const char *scsi_card_get_internal_name(int card); +extern int scsi_card_get_from_internal_name(char *s); +extern void scsi_card_init(void); -#endif /*EMU_SCSI_H*/ +#endif /*EMU_SCSI_H*/ diff --git a/src/include/86box/scsi_aha154x.h b/src/include/86box/scsi_aha154x.h index ed9002ae7..800d2d72b 100644 --- a/src/include/86box/scsi_aha154x.h +++ b/src/include/86box/scsi_aha154x.h @@ -1,5 +1,5 @@ #ifndef SCSI_AHA154X_H -# define SCSI_AHA154X_H +#define SCSI_AHA154X_H extern const device_t aha154xa_device; extern const device_t aha154xb_device; @@ -8,7 +8,6 @@ extern const device_t aha154xcf_device; extern const device_t aha154xcp_device; extern const device_t aha1640_device; -extern void aha_device_reset(void *p); - - -#endif /*SCSI_AHA154X_H*/ +extern void aha_device_reset(void *priv); + +#endif /*SCSI_AHA154X_H*/ diff --git a/src/include/86box/scsi_buslogic.h b/src/include/86box/scsi_buslogic.h index 27ea5c10b..6de69e700 100644 --- a/src/include/86box/scsi_buslogic.h +++ b/src/include/86box/scsi_buslogic.h @@ -1,24 +1,24 @@ /* - * 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. + * 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. * - * Emulation of BusLogic BT-542B ISA and BT-958D PCI SCSI - * controllers. + * Emulation of BusLogic BT-542B ISA and BT-958D PCI SCSI + * controllers. * * * - * Authors: TheCollector1995, - * Miran Grca, - * Fred N. van Kempen, - * Copyright 2016-2018 Miran Grca. - * Copyright 2017,2018 Fred N. van Kempen. + * Authors: TheCollector1995, + * Miran Grca, + * Fred N. van Kempen, + * + * Copyright 2016-2018 Miran Grca. + * Copyright 2017-2018 Fred N. van Kempen. */ #ifndef SCSI_BUSLOGIC_H -# define SCSI_BUSLOGIC_H - +#define SCSI_BUSLOGIC_H extern const device_t buslogic_542b_device; extern const device_t buslogic_545s_device; @@ -29,7 +29,6 @@ extern const device_t buslogic_445s_device; extern const device_t buslogic_445c_device; extern const device_t buslogic_958d_pci_device; -extern void BuslogicDeviceReset(void *p); - - -#endif /*SCSI_BUSLOGIC_H*/ +extern void BuslogicDeviceReset(void *priv); + +#endif /*SCSI_BUSLOGIC_H*/ diff --git a/src/include/86box/scsi_cdrom.h b/src/include/86box/scsi_cdrom.h index 95f3634bf..dec537429 100644 --- a/src/include/86box/scsi_cdrom.h +++ b/src/include/86box/scsi_cdrom.h @@ -1,69 +1,91 @@ /* - * 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. + * 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. + * This file is part of the 86Box distribution. * - * Implementation of the CD-ROM drive with SCSI(-like) - * commands, for both ATAPI and SCSI usage. + * Implementation of the CD-ROM drive with SCSI(-like) + * commands, for both ATAPI and SCSI usage. * * * - * Author: Miran Grca, + * Authors: Miran Grca, * - * Copyright 2018,2019 Miran Grca. + * Copyright 2018-2019 Miran Grca. */ + #ifndef EMU_SCSI_CDROM_H #define EMU_SCSI_CDROM_H - -#define CDROM_TIME 10.0 - +#define CDROM_TIME 10.0 #ifdef SCSI_DEVICE_H -typedef struct { +typedef struct scsi_cdrom_t { /* Common block. */ mode_sense_pages_t ms_pages_saved; - cdrom_t *drv; + cdrom_t * drv; +#ifdef EMU_IDE_H + ide_tf_t *tf; +#else + void * tf; +#endif - uint8_t *buffer, - atapi_cdb[16], - current_cdb[16], - sense[256]; + uint8_t *buffer; + uint8_t atapi_cdb[16]; + uint8_t current_cdb[16]; + uint8_t sense[256]; - uint8_t status, phase, - error, id, - features, cur_lun, - pad0, pad1; +#ifdef ANCIENT_CODE + /* Task file. */ + uint8_t features; + uint8_t phase; + uint16_t request_length; + uint8_t status; + uint8_t error; + uint16_t pad; + uint32_t pos; +#endif - uint16_t request_length, max_transfer_len; + uint8_t id; + uint8_t cur_lun; + uint8_t early; + uint8_t pad1; - int requested_blocks, packet_status, - total_length, do_page_save, - unit_attention, request_pos, - old_len, media_status; + uint16_t max_transfer_len; + uint16_t pad2; - uint32_t sector_pos, sector_len, - packet_len, pos; + int requested_blocks; + int packet_status; + int total_length; + int do_page_save; + int unit_attention; + int request_pos; + int old_len; + int media_status; + + uint32_t sector_pos; + uint32_t sector_len; + uint32_t packet_len; double callback; + + mode_sense_pages_t ms_pages_saved_sony; + mode_sense_pages_t ms_drive_status_pages_saved; + int sony_vendor; } scsi_cdrom_t; #endif - -extern scsi_cdrom_t *scsi_cdrom[CDROM_NUM]; +extern scsi_cdrom_t *scsi_cdrom[CDROM_NUM]; #define scsi_cdrom_sense_error dev->sense[0] -#define scsi_cdrom_sense_key dev->sense[2] -#define scsi_cdrom_asc dev->sense[12] -#define scsi_cdrom_ascq dev->sense[13] -#define scsi_cdrom_drive cdrom_drives[id].host_drive +#define scsi_cdrom_sense_key dev->sense[2] +#define scsi_cdrom_asc dev->sense[12] +#define scsi_cdrom_ascq dev->sense[13] +#define scsi_cdrom_drive cdrom_drives[id].host_drive +extern void scsi_cdrom_reset(scsi_common_t *sc); -extern void scsi_cdrom_reset(scsi_common_t *sc); - - -#endif /*EMU_SCSI_CDROM_H*/ +#endif /*EMU_SCSI_CDROM_H*/ diff --git a/src/include/86box/scsi_device.h b/src/include/86box/scsi_device.h index 6e9223648..09f9ee2d9 100644 --- a/src/include/86box/scsi_device.h +++ b/src/include/86box/scsi_device.h @@ -1,223 +1,257 @@ /* - * 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. + * 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. + * This file is part of the 86Box distribution. * - * Definitions for the generic SCSI device command handler. + * Definitions for the generic SCSI device command handler. * * * - * Authors: Miran Grca, - * Fred N. van Kempen, + * Authors: Miran Grca, + * Fred N. van Kempen, * - * Copyright 2016-2019 Miran Grca. - * Copyright 2017-2019 Fred N. van Kempen. + * Copyright 2016-2019 Miran Grca. + * Copyright 2017-2019 Fred N. van Kempen. */ -#ifndef SCSI_DEVICE_H -# define SCSI_DEVICE_H +#ifndef SCSI_DEVICE_H +#define SCSI_DEVICE_H /* Configuration. */ -#define SCSI_BUS_MAX 4 /* currently we support up to 4 controllers */ -#define SCSI_ID_MAX 16 /* 16 on wide buses */ -#define SCSI_LUN_MAX 8 /* always 8 */ - -#define SCSI_LUN_USE_CDB 0xff +#define SCSI_LUN_USE_CDB 0xff #ifdef WALTJE -#define SCSI_TIME 50.0 +# define SCSI_TIME 50.0 #else -#define SCSI_TIME 500.0 +# define SCSI_TIME 500.0 #endif - /* Bits of 'status' */ -#define ERR_STAT 0x01 -#define DRQ_STAT 0x08 /* Data request */ -#define DSC_STAT 0x10 -#define SERVICE_STAT 0x10 -#define READY_STAT 0x40 -#define BUSY_STAT 0x80 +#define ERR_STAT 0x01 +#define DRQ_STAT 0x08 /* Data request */ +#define DSC_STAT 0x10 +#define SERVICE_STAT 0x10 +#define READY_STAT 0x40 +#define BUSY_STAT 0x80 /* Bits of 'error' */ -#define ABRT_ERR 0x04 /* Command aborted */ -#define MCR_ERR 0x08 /* Media change request */ +#define ABRT_ERR 0x04 /* Command aborted */ +#define MCR_ERR 0x08 /* Media change request */ /* SCSI commands. */ -#define GPCMD_TEST_UNIT_READY 0x00 -#define GPCMD_REZERO_UNIT 0x01 -#define GPCMD_REQUEST_SENSE 0x03 -#define GPCMD_FORMAT_UNIT 0x04 -#define GPCMD_IOMEGA_SENSE 0x06 -#define GPCMD_READ_6 0x08 -#define GPCMD_WRITE_6 0x0a -#define GPCMD_SEEK_6 0x0b -#define GPCMD_IOMEGA_SET_PROTECTION_MODE 0x0c -#define GPCMD_IOMEGA_EJECT 0x0d /* ATAPI only? */ -#define GPCMD_INQUIRY 0x12 -#define GPCMD_VERIFY_6 0x13 -#define GPCMD_MODE_SELECT_6 0x15 -#define GPCMD_SCSI_RESERVE 0x16 -#define GPCMD_SCSI_RELEASE 0x17 -#define GPCMD_MODE_SENSE_6 0x1a -#define GPCMD_START_STOP_UNIT 0x1b -#define GPCMD_SEND_DIAGNOSTIC 0x1d -#define GPCMD_PREVENT_REMOVAL 0x1e -#define GPCMD_READ_FORMAT_CAPACITIES 0x23 -#define GPCMD_READ_CDROM_CAPACITY 0x25 -#define GPCMD_READ_10 0x28 -#define GPCMD_READ_GENERATION 0x29 -#define GPCMD_WRITE_10 0x2a -#define GPCMD_SEEK_10 0x2b -#define GPCMD_ERASE_10 0x2c -#define GPCMD_WRITE_AND_VERIFY_10 0x2e -#define GPCMD_VERIFY_10 0x2f -#define GPCMD_READ_BUFFER 0x3c -#define GPCMD_WRITE_SAME_10 0x41 -#define GPCMD_READ_SUBCHANNEL 0x42 -#define GPCMD_READ_TOC_PMA_ATIP 0x43 -#define GPCMD_READ_HEADER 0x44 -#define GPCMD_PLAY_AUDIO_10 0x45 -#define GPCMD_GET_CONFIGURATION 0x46 -#define GPCMD_PLAY_AUDIO_MSF 0x47 -#define GPCMD_PLAY_AUDIO_TRACK_INDEX 0x48 -#define GPCMD_PLAY_AUDIO_TRACK_RELATIVE_10 0x49 -#define GPCMD_GET_EVENT_STATUS_NOTIFICATION 0x4a -#define GPCMD_PAUSE_RESUME 0x4b -#define GPCMD_STOP_PLAY_SCAN 0x4e -#define GPCMD_READ_DISC_INFORMATION 0x51 -#define GPCMD_READ_TRACK_INFORMATION 0x52 -#define GPCMD_MODE_SELECT_10 0x55 -#define GPCMD_MODE_SENSE_10 0x5a -#define GPCMD_PLAY_AUDIO_12 0xa5 -#define GPCMD_READ_12 0xa8 -#define GPCMD_PLAY_AUDIO_TRACK_RELATIVE_12 0xa9 -#define GPCMD_WRITE_12 0xaa -#define GPCMD_ERASE_12 0xac -#define GPCMD_READ_DVD_STRUCTURE 0xad /* For reading. */ -#define GPCMD_WRITE_AND_VERIFY_12 0xae -#define GPCMD_VERIFY_12 0xaf -#define GPCMD_PLAY_CD_OLD 0xb4 -#define GPCMD_READ_CD_OLD 0xb8 -#define GPCMD_READ_CD_MSF 0xb9 -#define GPCMD_SCAN 0xba -#define GPCMD_SET_SPEED 0xbb -#define GPCMD_PLAY_CD 0xbc -#define GPCMD_MECHANISM_STATUS 0xbd -#define GPCMD_READ_CD 0xbe -#define GPCMD_SEND_DVD_STRUCTURE 0xbf /* This is for writing only, irrelevant to 86Box. */ -#define GPCMD_AUDIO_TRACK_SEARCH 0xc0 /* Toshiba Vendor Unique command */ -#define GPCMD_TOSHIBA_PLAY_AUDIO 0xc1 /* Toshiba Vendor Unique command */ -#define GPCMD_PAUSE_RESUME_ALT 0xc2 -#define GPCMD_STILL 0xc2 /* Toshiba Vendor Unique command */ -#define GPCMD_CADDY_EJECT 0xc4 /* Toshiba Vendor Unique command */ -#define GPCMD_READ_SUBCODEQ_PLAYING_STATUS 0xc6 /* Toshiba Vendor Unique command */ -#define GPCMD_READ_DISC_INFORMATION_TOSHIBA 0xc7 /* Toshiba Vendor Unique command */ -#define GPCMD_SCAN_ALT 0xcd /* Should be equivalent to 0xba */ -#define GPCMD_SET_SPEED_ALT 0xda /* Should be equivalent to 0xbb */ +#define GPCMD_TEST_UNIT_READY 0x00 +#define GPCMD_REZERO_UNIT 0x01 +#define GPCMD_REQUEST_SENSE 0x03 +#define GPCMD_FORMAT_UNIT 0x04 +#define GPCMD_IOMEGA_SENSE 0x06 +#define GPCMD_READ_6 0x08 +#define GPCMD_WRITE_6 0x0a +#define GPCMD_SEEK_6 0x0b +#define GPCMD_IOMEGA_SET_PROTECTION_MODE 0x0c +#define GPCMD_IOMEGA_EJECT 0x0d /* ATAPI only? */ +#define GPCMD_NO_OPERATION_TOSHIBA 0x0d /* Toshiba Vendor Unique command */ +#define GPCMD_NO_OPERATION_NEC 0x0d /* NEC Vendor Unique command */ +#define GPCMD_INQUIRY 0x12 +#define GPCMD_VERIFY_6 0x13 +#define GPCMD_MODE_SELECT_6 0x15 +#define GPCMD_SCSI_RESERVE 0x16 +#define GPCMD_SCSI_RELEASE 0x17 +#define GPCMD_MODE_SENSE_6 0x1a +#define GPCMD_START_STOP_UNIT 0x1b +#define GPCMD_SEND_DIAGNOSTIC 0x1d +#define GPCMD_PREVENT_REMOVAL 0x1e +#define GPCMD_READ_FORMAT_CAPACITIES 0x23 +#define GPCMD_READ_CDROM_CAPACITY 0x25 +#define GPCMD_UNKNOWN_CHINON 0x26 /*Chinon Vendor Unique command*/ +#define GPCMD_READ_10 0x28 +#define GPCMD_READ_GENERATION 0x29 +#define GPCMD_WRITE_10 0x2a +#define GPCMD_SEEK_10 0x2b +#define GPCMD_ERASE_10 0x2c +#define GPCMD_WRITE_AND_VERIFY_10 0x2e +#define GPCMD_VERIFY_10 0x2f +#define GPCMD_READ_BUFFER 0x3c +#define GPCMD_WRITE_SAME_10 0x41 +#define GPCMD_READ_SUBCHANNEL 0x42 +#define GPCMD_READ_TOC_PMA_ATIP 0x43 +#define GPCMD_READ_HEADER 0x44 +#define GPCMD_PLAY_AUDIO_10 0x45 +#define GPCMD_GET_CONFIGURATION 0x46 +#define GPCMD_PLAY_AUDIO_MSF 0x47 +#define GPCMD_PLAY_AUDIO_TRACK_INDEX 0x48 +#define GPCMD_PLAY_AUDIO_TRACK_RELATIVE_10 0x49 +#define GPCMD_GET_EVENT_STATUS_NOTIFICATION 0x4a +#define GPCMD_PAUSE_RESUME 0x4b +#define GPCMD_STOP_PLAY_SCAN 0x4e +#define GPCMD_READ_DISC_INFORMATION 0x51 +#define GPCMD_READ_TRACK_INFORMATION 0x52 +#define GPCMD_MODE_SELECT_10 0x55 +#define GPCMD_MODE_SENSE_10 0x5a +#define GPCMD_PLAY_AUDIO_12 0xa5 +#define GPCMD_READ_12 0xa8 +#define GPCMD_PLAY_AUDIO_TRACK_RELATIVE_12 0xa9 +#define GPCMD_WRITE_12 0xaa +#define GPCMD_ERASE_12 0xac +#define GPCMD_READ_DVD_STRUCTURE 0xad /* For reading. */ +#define GPCMD_WRITE_AND_VERIFY_12 0xae +#define GPCMD_VERIFY_12 0xaf +#define GPCMD_PLAY_CD_OLD 0xb4 +#define GPCMD_READ_CD_OLD 0xb8 +#define GPCMD_READ_CD_MSF 0xb9 +#define GPCMD_AUDIO_SCAN 0xba +#define GPCMD_SET_SPEED 0xbb +#define GPCMD_PLAY_CD 0xbc +#define GPCMD_MECHANISM_STATUS 0xbd +#define GPCMD_READ_CD 0xbe +#define GPCMD_SEND_DVD_STRUCTURE 0xbf /* This is for writing only, irrelevant to 86Box. */ +#define GPCMD_EJECT_CHINON 0xc0 /* Chinon Vendor Unique command */ +#define GPCMD_AUDIO_TRACK_SEARCH_TOSHIBA 0xc0 /* Toshiba Vendor Unique command */ +#define GPCMD_UNKNOWN_SONY 0xc0 /* Sony Vendor Unique command */ +#define GPCMD_PLAY_AUDIO_TOSHIBA 0xc1 /* Toshiba Vendor Unique command */ +#define GPCMD_READ_TOC_SONY 0xc1 /* Sony Vendor Unique command */ +#define GPCMD_PAUSE_RESUME_ALT 0xc2 +#define GPCMD_READ_SUBCHANNEL_MATSUSHITA 0xc2 /* Matsushita Vendor Unique command */ +#define GPCMD_READ_SUBCHANNEL_SONY 0xc2 /* Sony Vendor Unique command */ +#define GPCMD_STILL_TOSHIBA 0xc2 /* Toshiba Vendor Unique command */ +#define GPCMD_READ_TOC_MATSUSHITA 0xc3 /* Matsushita Vendor Unique command */ +#define GPCMD_READ_HEADER_SONY 0xc3 /* Sony Vendor Unique command */ +#define GPCMD_SET_STOP_TIME_TOSHIBA 0xc3 /* Toshiba Vendor Unique command */ +#define GPCMD_READ_HEADER_MATSUSHITA 0xc4 /* Matsushita Vendor Unique command */ +#define GPCMD_PLAYBACK_STATUS_TOSHIBA 0xc4 /* Sony Vendor Unique command */ +#define GPCMD_CADDY_EJECT_TOSHIBA 0xc4 /* Toshiba Vendor Unique command */ +#define GPCMD_PAUSE_SONY 0xc5 /* Sony Vendor Unique command */ +#define GPCMD_PLAY_AUDIO_MATSUSHITA 0xc5 /* Matsushita Vendor Unique command */ +#define GPCMD_STOP_CHINON 0xc6 /* Chinon Vendor Unique command */ +#define GPCMD_PLAT_TRACK_SONY 0xc6 /* Sony Vendor Unique command */ +#define GPCMD_READ_SUBCODEQ_PLAYING_STATUS_TOSHIBA 0xc6 /* Toshiba Vendor Unique command */ +#define GPCMD_PLAY_AUDIO_MSF_MATSUSHITA 0xc7 /* Matsushita Vendor Unique command*/ +#define GPCMD_PLAY_MSF_SONY 0xc7 /* Sony Vendor Unique command*/ +#define GPCMD_READ_DISC_INFORMATION_TOSHIBA 0xc7 /* Toshiba Vendor Unique command */ +#define GPCMD_PLAY_AUDIO_TRACK_INDEX_MATSUSHITA 0xc8 /* Matsushita Vendor Unique command */ +#define GPCMD_PLAY_AUDIO_SONY 0xc8 /* Sony Vendor Unique command */ +#define GPCMD_PLAY_AUDIO_TRACK_RELATIVE_10_MATSUSHITA 0xc9 /*Matsushita Vendor Unique command */ +#define GPCMD_PLAYBACK_CONTROL_SONY 0xc9 /* Sony Vendor Unique command */ +#define GPCMD_PAUSE_RESUME_MATSUSHITA 0xcb /* Matsushita Vendor Unique command */ +#define GPCMD_SCAN_PIONEER 0xcd /* Should be equivalent to 0xba */ +#define GPCMD_AUDIO_TRACK_SEARCH_NEC 0xd8 /* NEC Vendor Unique command */ +#define GPCMD_PLAY_AUDIO_NEC 0xd9 /* NEC Vendor Unique command */ +#define GPCMD_STILL_NEC 0xda /* NEC Vendor Unique command */ +#define GPCMD_SET_SPEED_ALT 0xda /* Should be equivalent to 0xbb */ +#define GPCMD_SET_STOP_TIME_NEC 0xdb /* NEC Vendor Unique command */ +#define GPCMD_CADDY_EJECT_NEC 0xdc /* NEC Vendor Unique command */ +#define GPCMD_READ_SUBCODEQ_PLAYING_STATUS_NEC 0xdd /* NEC Vendor Unique command */ +#define GPCMD_READ_DISC_INFORMATION_NEC 0xde /* NEC Vendor Unique command */ +#define GPCMD_PLAY_AUDIO_12_MATSUSHITA 0xe5 /* Matsushita Vendor Unique command */ +#define GPCMD_PLAY_AUDIO_TRACK_RELATIVE_12_MATSUSHITA 0xe9 /* Matsushita Vendor Unique command */ /* Mode page codes for mode sense/set */ -#define GPMODE_R_W_ERROR_PAGE 0x01 -#define GPMODE_DISCONNECT_PAGE 0x02 /* Disconnect/reconnect page */ -#define GPMODE_FORMAT_DEVICE_PAGE 0x03 -#define GPMODE_RIGID_DISK_PAGE 0x04 /* Rigid disk geometry page */ -#define GPMODE_FLEXIBLE_DISK_PAGE 0x05 -#define GPMODE_CACHING_PAGE 0x08 -#define GPMODE_CDROM_PAGE 0x0d -#define GPMODE_CDROM_AUDIO_PAGE 0x0e -#define GPMODE_CAPABILITIES_PAGE 0x2a -#define GPMODE_IOMEGA_PAGE 0x2f -#define GPMODE_UNK_VENDOR_PAGE 0x30 -#define GPMODE_ALL_PAGES 0x3f +#define GPMODE_UNIT_ATN_PAGE 0x00 +#define GPMODE_R_W_ERROR_PAGE 0x01 +#define GPMODE_DISCONNECT_PAGE 0x02 /* Disconnect/reconnect page */ +#define GPMODE_FORMAT_DEVICE_PAGE 0x03 +#define GPMODE_RIGID_DISK_PAGE 0x04 /* Rigid disk geometry page */ +#define GPMODE_FLEXIBLE_DISK_PAGE 0x05 +#define GPMODE_CACHING_PAGE 0x08 +#define GPMODE_CDROM_PAGE_SONY 0x08 +#define GPMODE_CDROM_AUDIO_PAGE_SONY 0x09 +#define GPMODE_CDROM_PAGE 0x0d +#define GPMODE_CDROM_AUDIO_PAGE 0x0e +#define GPMODE_CAPABILITIES_PAGE 0x2a +#define GPMODE_IOMEGA_PAGE 0x2f +#define GPMODE_UNK_VENDOR_PAGE 0x30 +#define GPMODE_ALL_PAGES 0x3f /* Mode page codes for presence */ -#define GPMODEP_R_W_ERROR_PAGE 0x0000000000000002LL -#define GPMODEP_DISCONNECT_PAGE 0x0000000000000004LL -#define GPMODEP_FORMAT_DEVICE_PAGE 0x0000000000000008LL -#define GPMODEP_RIGID_DISK_PAGE 0x0000000000000010LL -#define GPMODEP_FLEXIBLE_DISK_PAGE 0x0000000000000020LL -#define GPMODEP_CACHING_PAGE 0x0000000000000100LL -#define GPMODEP_CDROM_PAGE 0x0000000000002000LL -#define GPMODEP_CDROM_AUDIO_PAGE 0x0000000000004000LL -#define GPMODEP_CAPABILITIES_PAGE 0x0000040000000000LL -#define GPMODEP_IOMEGA_PAGE 0x0000800000000000LL -#define GPMODEP_UNK_VENDOR_PAGE 0x0001000000000000LL -#define GPMODEP_ALL_PAGES 0x8000000000000000LL +#define GPMODEP_UNIT_ATN_PAGE 0x0000000000000001LL +#define GPMODEP_R_W_ERROR_PAGE 0x0000000000000002LL +#define GPMODEP_DISCONNECT_PAGE 0x0000000000000004LL +#define GPMODEP_FORMAT_DEVICE_PAGE 0x0000000000000008LL +#define GPMODEP_RIGID_DISK_PAGE 0x0000000000000010LL +#define GPMODEP_FLEXIBLE_DISK_PAGE 0x0000000000000020LL +#define GPMODEP_CACHING_PAGE 0x0000000000000100LL +#define GPMODEP_CDROM_PAGE_SONY 0x0000000000000200LL +#define GPMODEP_CDROM_AUDIO_PAGE_SONY 0x0000000000000400LL +#define GPMODEP_CDROM_PAGE 0x0000000000002000LL +#define GPMODEP_CDROM_AUDIO_PAGE 0x0000000000004000LL +#define GPMODEP_CAPABILITIES_PAGE 0x0000040000000000LL +#define GPMODEP_IOMEGA_PAGE 0x0000800000000000LL +#define GPMODEP_UNK_VENDOR_PAGE 0x0001000000000000LL +#define GPMODEP_ALL_PAGES 0x8000000000000000LL /* SCSI Status Codes */ -#define SCSI_STATUS_OK 0 -#define SCSI_STATUS_CHECK_CONDITION 2 +#define SCSI_STATUS_OK 0 +#define SCSI_STATUS_CHECK_CONDITION 2 /* SCSI Sense Keys */ -#define SENSE_NONE 0 -#define SENSE_NOT_READY 2 -#define SENSE_ILLEGAL_REQUEST 5 -#define SENSE_UNIT_ATTENTION 6 +#define SENSE_NONE 0 +#define SENSE_NOT_READY 2 +#define SENSE_ILLEGAL_REQUEST 5 +#define SENSE_UNIT_ATTENTION 6 /* SCSI Additional Sense Codes */ -#define ASC_NONE 0x00 -#define ASC_AUDIO_PLAY_OPERATION 0x00 -#define ASC_NOT_READY 0x04 -#define ASC_ILLEGAL_OPCODE 0x20 -#define ASC_LBA_OUT_OF_RANGE 0x21 -#define ASC_INV_FIELD_IN_CMD_PACKET 0x24 -#define ASC_INV_LUN 0x25 -#define ASC_INV_FIELD_IN_PARAMETER_LIST 0x26 -#define ASC_WRITE_PROTECTED 0x27 -#define ASC_MEDIUM_MAY_HAVE_CHANGED 0x28 -#define ASC_CAPACITY_DATA_CHANGED 0x2A -#define ASC_INCOMPATIBLE_FORMAT 0x30 -#define ASC_MEDIUM_NOT_PRESENT 0x3a -#define ASC_DATA_PHASE_ERROR 0x4b -#define ASC_ILLEGAL_MODE_FOR_THIS_TRACK 0x64 +#define ASC_NONE 0x00 +#define ASC_AUDIO_PLAY_OPERATION 0x00 +#define ASC_NOT_READY 0x04 +#define ASC_ILLEGAL_OPCODE 0x20 +#define ASC_LBA_OUT_OF_RANGE 0x21 +#define ASC_INV_FIELD_IN_CMD_PACKET 0x24 +#define ASC_INV_LUN 0x25 +#define ASC_INV_FIELD_IN_PARAMETER_LIST 0x26 +#define ASC_WRITE_PROTECTED 0x27 +#define ASC_MEDIUM_MAY_HAVE_CHANGED 0x28 +#define ASC_CAPACITY_DATA_CHANGED 0x2A +#define ASC_INCOMPATIBLE_FORMAT 0x30 +#define ASC_MEDIUM_NOT_PRESENT 0x3a +#define ASC_DATA_PHASE_ERROR 0x4b +#define ASC_ILLEGAL_MODE_FOR_THIS_TRACK 0x64 -#define ASCQ_NONE 0x00 -#define ASCQ_UNIT_IN_PROCESS_OF_BECOMING_READY 0x01 -#define ASCQ_INITIALIZING_COMMAND_REQUIRED 0x02 -#define ASCQ_CAPACITY_DATA_CHANGED 0x09 -#define ASCQ_AUDIO_PLAY_OPERATION_IN_PROGRESS 0x11 -#define ASCQ_AUDIO_PLAY_OPERATION_PAUSED 0x12 -#define ASCQ_AUDIO_PLAY_OPERATION_COMPLETED 0x13 +#define ASCQ_NONE 0x00 +#define ASCQ_UNIT_IN_PROCESS_OF_BECOMING_READY 0x01 +#define ASCQ_INITIALIZING_COMMAND_REQUIRED 0x02 +#define ASCQ_CAPACITY_DATA_CHANGED 0x09 +#define ASCQ_AUDIO_PLAY_OPERATION_IN_PROGRESS 0x11 +#define ASCQ_AUDIO_PLAY_OPERATION_PAUSED 0x12 +#define ASCQ_AUDIO_PLAY_OPERATION_COMPLETED 0x13 /* Tell RISC OS that we have a 4x CD-ROM drive (600kb/sec data, 706kb/sec raw). Not that it means anything */ -#define CDROM_SPEED 706 /* 0x2C2 */ +#define CDROM_SPEED 706 /* 0x2C2 */ -#define BUFFER_SIZE (256*1024) +#define BUFFER_SIZE (256 * 1024) -#define RW_DELAY (TIMER_USEC * 500) +#define RW_DELAY (TIMER_USEC * 500) /* Some generally useful CD-ROM information */ -#define CD_MINS 75 /* max. minutes per CD */ -#define CD_SECS 60 /* seconds per minute */ -#define CD_FRAMES 75 /* frames per second */ -#define CD_FRAMESIZE 2048 /* bytes per frame, "cooked" mode */ -#define CD_MAX_BYTES (CD_MINS * CD_SECS * CD_FRAMES * CD_FRAMESIZE) -#define CD_MAX_SECTORS (CD_MAX_BYTES / 512) - +#define CD_MINS 90 /* max. minutes per CD */ +#define CD_SECS 60 /* seconds per minute */ +#define CD_FRAMES 75 /* frames per second */ +#define CD_FRAMESIZE 2048 /* bytes per frame, "cooked" mode */ +#define CD_MAX_BYTES (CD_MINS * CD_SECS * CD_FRAMES * CD_FRAMESIZE) +#define CD_MAX_SECTORS (CD_MAX_BYTES / 2048) + /* Event notification classes for GET EVENT STATUS NOTIFICATION */ -#define GESN_NO_EVENTS 0 -#define GESN_OPERATIONAL_CHANGE 1 -#define GESN_POWER_MANAGEMENT 2 -#define GESN_EXTERNAL_REQUEST 3 -#define GESN_MEDIA 4 -#define GESN_MULTIPLE_HOSTS 5 -#define GESN_DEVICE_BUSY 6 +#define GESN_NO_EVENTS 0 +#define GESN_OPERATIONAL_CHANGE 1 +#define GESN_POWER_MANAGEMENT 2 +#define GESN_EXTERNAL_REQUEST 3 +#define GESN_MEDIA 4 +#define GESN_MULTIPLE_HOSTS 5 +#define GESN_DEVICE_BUSY 6 /* Event codes for MEDIA event status notification */ -#define MEC_NO_CHANGE 0 -#define MEC_EJECT_REQUESTED 1 -#define MEC_NEW_MEDIA 2 -#define MEC_MEDIA_REMOVAL 3 /* only for media changers */ -#define MEC_MEDIA_CHANGED 4 /* only for media changers */ -#define MEC_BG_FORMAT_COMPLETED 5 /* MRW or DVD+RW b/g format completed */ -#define MEC_BG_FORMAT_RESTARTED 6 /* MRW or DVD+RW b/g format restarted */ -#define MS_TRAY_OPEN 1 -#define MS_MEDIA_PRESENT 2 +#define MEC_NO_CHANGE 0 +#define MEC_EJECT_REQUESTED 1 +#define MEC_NEW_MEDIA 2 +#define MEC_MEDIA_REMOVAL 3 /* only for media changers */ +#define MEC_MEDIA_CHANGED 4 /* only for media changers */ +#define MEC_BG_FORMAT_COMPLETED 5 /* MRW or DVD+RW b/g format completed */ +#define MEC_BG_FORMAT_RESTARTED 6 /* MRW or DVD+RW b/g format restarted */ +#define MS_TRAY_OPEN 1 +#define MS_MEDIA_PRESENT 2 /* * The MMC values are not IDE specific and might need to be moved @@ -225,87 +259,88 @@ */ /* Profile list from MMC-6 revision 1 table 91 */ -#define MMC_PROFILE_NONE 0x0000 -#define MMC_PROFILE_CD_ROM 0x0008 -#define MMC_PROFILE_CD_R 0x0009 -#define MMC_PROFILE_CD_RW 0x000A -#define MMC_PROFILE_DVD_ROM 0x0010 -#define MMC_PROFILE_DVD_R_SR 0x0011 -#define MMC_PROFILE_DVD_RAM 0x0012 -#define MMC_PROFILE_DVD_RW_RO 0x0013 -#define MMC_PROFILE_DVD_RW_SR 0x0014 -#define MMC_PROFILE_DVD_R_DL_SR 0x0015 -#define MMC_PROFILE_DVD_R_DL_JR 0x0016 -#define MMC_PROFILE_DVD_RW_DL 0x0017 -#define MMC_PROFILE_DVD_DDR 0x0018 -#define MMC_PROFILE_DVD_PLUS_RW 0x001A -#define MMC_PROFILE_DVD_PLUS_R 0x001B -#define MMC_PROFILE_DVD_PLUS_RW_DL 0x002A -#define MMC_PROFILE_DVD_PLUS_R_DL 0x002B -#define MMC_PROFILE_BD_ROM 0x0040 -#define MMC_PROFILE_BD_R_SRM 0x0041 -#define MMC_PROFILE_BD_R_RRM 0x0042 -#define MMC_PROFILE_BD_RE 0x0043 -#define MMC_PROFILE_HDDVD_ROM 0x0050 -#define MMC_PROFILE_HDDVD_R 0x0051 -#define MMC_PROFILE_HDDVD_RAM 0x0052 -#define MMC_PROFILE_HDDVD_RW 0x0053 -#define MMC_PROFILE_HDDVD_R_DL 0x0058 -#define MMC_PROFILE_HDDVD_RW_DL 0x005A -#define MMC_PROFILE_INVALID 0xFFFF +#define MMC_PROFILE_NONE 0x0000 +#define MMC_PROFILE_CD_ROM 0x0008 +#define MMC_PROFILE_CD_R 0x0009 +#define MMC_PROFILE_CD_RW 0x000A +#define MMC_PROFILE_DVD_ROM 0x0010 +#define MMC_PROFILE_DVD_R_SR 0x0011 +#define MMC_PROFILE_DVD_RAM 0x0012 +#define MMC_PROFILE_DVD_RW_RO 0x0013 +#define MMC_PROFILE_DVD_RW_SR 0x0014 +#define MMC_PROFILE_DVD_R_DL_SR 0x0015 +#define MMC_PROFILE_DVD_R_DL_JR 0x0016 +#define MMC_PROFILE_DVD_RW_DL 0x0017 +#define MMC_PROFILE_DVD_DDR 0x0018 +#define MMC_PROFILE_DVD_PLUS_RW 0x001A +#define MMC_PROFILE_DVD_PLUS_R 0x001B +#define MMC_PROFILE_DVD_PLUS_RW_DL 0x002A +#define MMC_PROFILE_DVD_PLUS_R_DL 0x002B +#define MMC_PROFILE_BD_ROM 0x0040 +#define MMC_PROFILE_BD_R_SRM 0x0041 +#define MMC_PROFILE_BD_R_RRM 0x0042 +#define MMC_PROFILE_BD_RE 0x0043 +#define MMC_PROFILE_HDDVD_ROM 0x0050 +#define MMC_PROFILE_HDDVD_R 0x0051 +#define MMC_PROFILE_HDDVD_RAM 0x0052 +#define MMC_PROFILE_HDDVD_RW 0x0053 +#define MMC_PROFILE_HDDVD_R_DL 0x0058 +#define MMC_PROFILE_HDDVD_RW_DL 0x005A +#define MMC_PROFILE_INVALID 0xFFFF -#define SCSI_ONLY 32 -#define ATAPI_ONLY 16 -#define IMPLEMENTED 8 -#define NONDATA 4 -#define CHECK_READY 2 -#define ALLOW_UA 1 +#define EARLY_ONLY 64 +#define SCSI_ONLY 32 +#define ATAPI_ONLY 16 +#define IMPLEMENTED 8 +#define NONDATA 4 +#define CHECK_READY 2 +#define ALLOW_UA 1 -#define MSFtoLBA(m,s,f) ((((m * 60) + s) * 75) + f) +#define MSFtoLBA(m, s, f) ((((m * 60) + s) * 75) + f) -#define MSG_COMMAND_COMPLETE 0x00 +#define MSG_COMMAND_COMPLETE 0x00 -#define BUS_DBP 0x01 -#define BUS_SEL 0x02 -#define BUS_IO 0x04 -#define BUS_CD 0x08 -#define BUS_MSG 0x10 -#define BUS_REQ 0x20 -#define BUS_BSY 0x40 -#define BUS_RST 0x80 -#define BUS_ACK 0x200 -#define BUS_ATN 0x200 -#define BUS_ARB 0x8000 -#define BUS_SETDATA(val) ((uint32_t)val << 16) -#define BUS_GETDATA(val) ((val >> 16) & 0xff) -#define BUS_DATAMASK 0xff0000 +#define BUS_DBP 0x01 +#define BUS_SEL 0x02 +#define BUS_IO 0x04 +#define BUS_CD 0x08 +#define BUS_MSG 0x10 +#define BUS_REQ 0x20 +#define BUS_BSY 0x40 +#define BUS_RST 0x80 +#define BUS_ACK 0x200 +#define BUS_ATN 0x200 +#define BUS_ARB 0x8000 +#define BUS_SETDATA(val) ((uint32_t) val << 16) +#define BUS_GETDATA(val) ((val >> 16) & 0xff) +#define BUS_DATAMASK 0xff0000 -#define BUS_IDLE (1 << 31) +#define BUS_IDLE (1 << 31) -#define PHASE_IDLE 0x00 -#define PHASE_COMMAND 0x01 -#define PHASE_DATA_IN 0x02 -#define PHASE_DATA_OUT 0x03 -#define PHASE_DATA_IN_DMA 0x04 -#define PHASE_DATA_OUT_DMA 0x05 -#define PHASE_COMPLETE 0x06 -#define PHASE_ERROR 0x80 -#define PHASE_NONE 0xff +#define PHASE_IDLE 0x00 +#define PHASE_COMMAND 0x01 +#define PHASE_DATA_IN 0x02 +#define PHASE_DATA_OUT 0x03 +#define PHASE_DATA_IN_DMA 0x04 +#define PHASE_DATA_OUT_DMA 0x05 +#define PHASE_COMPLETE 0x06 +#define PHASE_ERROR 0x80 +#define PHASE_NONE 0xff -#define SCSI_PHASE_DATA_OUT 0 -#define SCSI_PHASE_DATA_IN BUS_IO -#define SCSI_PHASE_COMMAND BUS_CD -#define SCSI_PHASE_STATUS (BUS_CD | BUS_IO) -#define SCSI_PHASE_MESSAGE_OUT (BUS_MSG | BUS_CD) -#define SCSI_PHASE_MESSAGE_IN (BUS_MSG | BUS_CD | BUS_IO) +#define SCSI_PHASE_DATA_OUT 0 +#define SCSI_PHASE_DATA_IN BUS_IO +#define SCSI_PHASE_COMMAND BUS_CD +#define SCSI_PHASE_STATUS (BUS_CD | BUS_IO) +#define SCSI_PHASE_MESSAGE_OUT (BUS_MSG | BUS_CD) +#define SCSI_PHASE_MESSAGE_IN (BUS_MSG | BUS_CD | BUS_IO) -#define MODE_SELECT_PHASE_IDLE 0 -#define MODE_SELECT_PHASE_HEADER 1 -#define MODE_SELECT_PHASE_BLOCK_DESC 2 -#define MODE_SELECT_PHASE_PAGE_HEADER 3 -#define MODE_SELECT_PHASE_PAGE 4 +#define MODE_SELECT_PHASE_IDLE 0 +#define MODE_SELECT_PHASE_HEADER 1 +#define MODE_SELECT_PHASE_BLOCK_DESC 2 +#define MODE_SELECT_PHASE_PAGE_HEADER 3 +#define MODE_SELECT_PHASE_PAGE 4 -typedef struct { +typedef struct mode_sense_pages_t { uint8_t pages[0x40][0x40]; } mode_sense_pages_t; @@ -314,79 +349,106 @@ typedef struct { typedef struct scsi_common_s { mode_sense_pages_t ms_pages_saved; - void *p; + void * priv; +#ifdef EMU_IDE_H + ide_tf_t *tf; +#else + void * tf; +#endif - uint8_t *temp_buffer, - atapi_cdb[16], /* This is atapi_cdb in ATAPI-supporting devices, - and pad in SCSI-only devices. */ - current_cdb[16], - sense[256]; + uint8_t *temp_buffer; + uint8_t atapi_cdb[16]; /* This is atapi_cdb in ATAPI-supporting devices, + and pad in SCSI-only devices. */ + uint8_t current_cdb[16]; + uint8_t sense[256]; - uint8_t status, phase, - error, id, - features, cur_lun, - pad0, pad1; +#ifdef ANCIENT_CODE + /* Task file. */ + uint8_t features; + uint8_t phase; + uint16_t request_length; + uint8_t status; + uint8_t error; + uint16_t pad; + uint32_t pos; +#endif - uint16_t request_length, max_transfer_len; + uint8_t id; + uint8_t cur_lun; + uint8_t pad0; + uint8_t pad1; - int requested_blocks, packet_status, - total_length, do_page_save, - unit_attention, request_pos, - old_len, media_status; + uint16_t max_transfer_len; + uint16_t pad2; - uint32_t sector_pos, sector_len, - packet_len, pos; + int requested_blocks; + int packet_status; + int total_length; + int do_page_save; + int unit_attention; + int request_pos; + int old_len; + int media_status; + + uint32_t sector_pos; + uint32_t sector_len; + uint32_t packet_len; double callback; } scsi_common_t; -typedef struct { - int32_t buffer_length; +typedef struct scsi_device_t { + int32_t buffer_length; - uint8_t status, phase; - uint16_t type; + uint8_t status; + uint8_t phase; + uint16_t type; scsi_common_t *sc; - void (*command)(scsi_common_t *sc, uint8_t *cdb); - void (*request_sense)(scsi_common_t *sc, uint8_t *buffer, uint8_t alloc_length); - void (*reset)(scsi_common_t *sc); - uint8_t (*phase_data_out)(scsi_common_t *sc); - void (*command_stop)(scsi_common_t *sc); + void (*command)(scsi_common_t *sc, uint8_t *cdb); + void (*request_sense)(scsi_common_t *sc, uint8_t *buffer, uint8_t alloc_length); + void (*reset)(scsi_common_t *sc); + uint8_t (*phase_data_out)(scsi_common_t *sc); + void (*command_stop)(scsi_common_t *sc); } scsi_device_t; /* These are based on the INQUIRY values. */ -#define SCSI_NONE 0x0060 -#define SCSI_FIXED_DISK 0x0000 -#define SCSI_REMOVABLE_DISK 0x8000 +#define SCSI_NONE 0x0060 +#define SCSI_FIXED_DISK 0x0000 +#define SCSI_REMOVABLE_DISK 0x8000 #define SCSI_REMOVABLE_CDROM 0x8005 -extern scsi_device_t scsi_devices[SCSI_BUS_MAX][SCSI_ID_MAX]; +#ifdef EMU_SCSI_H +extern scsi_device_t scsi_devices[SCSI_BUS_MAX][SCSI_ID_MAX]; +#endif /* EMU_SCSI_H */ +extern int cdrom_add_error_and_subchannel(uint8_t *b, int real_sector_type); +extern int cdrom_LBAtoMSF_accurate(void); -extern int cdrom_add_error_and_subchannel(uint8_t *b, int real_sector_type); -extern int cdrom_LBAtoMSF_accurate(void); +extern int mode_select_init(uint8_t command, uint16_t pl_length, uint8_t do_save); +extern int mode_select_terminate(int force); +extern int mode_select_write(uint8_t val); -extern int mode_select_init(uint8_t command, uint16_t pl_length, uint8_t do_save); -extern int mode_select_terminate(int force); -extern int mode_select_write(uint8_t val); +extern uint8_t *scsi_device_sense(scsi_device_t *dev); +extern double scsi_device_get_callback(scsi_device_t *dev); +extern void scsi_device_request_sense(scsi_device_t *dev, uint8_t *buffer, + uint8_t alloc_length); +extern void scsi_device_reset(scsi_device_t *dev); +extern int scsi_device_present(scsi_device_t *dev); +extern int scsi_device_valid(scsi_device_t *dev); +extern int scsi_device_cdb_length(scsi_device_t *dev); +extern void scsi_device_command_phase0(scsi_device_t *dev, uint8_t *cdb); +extern void scsi_device_command_phase1(scsi_device_t *dev); +extern void scsi_device_command_stop(scsi_device_t *dev); +extern void scsi_device_identify(scsi_device_t *dev, uint8_t lun); +extern void scsi_device_close_all(void); +extern void scsi_device_init(void); -extern uint8_t *scsi_device_sense(scsi_device_t *dev); -extern double scsi_device_get_callback(scsi_device_t *dev); -extern void scsi_device_request_sense(scsi_device_t *dev, uint8_t *buffer, - uint8_t alloc_length); -extern void scsi_device_reset(scsi_device_t *dev); -extern int scsi_device_present(scsi_device_t *dev); -extern int scsi_device_valid(scsi_device_t *dev); -extern int scsi_device_cdb_length(scsi_device_t *dev); -extern void scsi_device_command_phase0(scsi_device_t *dev, uint8_t *cdb); -extern void scsi_device_command_phase1(scsi_device_t *dev); -extern void scsi_device_command_stop(scsi_device_t *dev); -extern void scsi_device_identify(scsi_device_t *dev, uint8_t lun); -extern void scsi_device_close_all(void); -extern void scsi_device_init(void); +extern void scsi_reset(void); +extern uint8_t scsi_get_bus(void); -extern void scsi_reset(void); -extern uint8_t scsi_get_bus(void); +extern void scsi_bus_set_speed(uint8_t bus, double speed); +extern double scsi_bus_get_speed(uint8_t bus); -#endif /*SCSI_DEVICE_H*/ +#endif /*SCSI_DEVICE_H*/ diff --git a/src/include/86box/scsi_disk.h b/src/include/86box/scsi_disk.h index 0caef4d26..eb4dc69a4 100644 --- a/src/include/86box/scsi_disk.h +++ b/src/include/86box/scsi_disk.h @@ -1,50 +1,76 @@ /* - * 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. + * 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. * - * Emulation of SCSI fixed and removable disks. + * Emulation of SCSI fixed and removable disks. * * * - * Author: Miran Grca, - * Copyright 2017,2018 Miran Grca. + * Authors: Miran Grca, + * + * Copyright 2017-2018 Miran Grca. */ +#ifndef SCSI_DISK_H +#define SCSI_DISK_H -typedef struct { +typedef struct scsi_disk_t { mode_sense_pages_t ms_pages_saved; hard_disk_t *drv; +#ifdef EMU_IDE_H + ide_tf_t * tf; +#else + void * tf; +#endif - uint8_t *temp_buffer, - pad[16], /* This is atapi_cdb in ATAPI-supporting devices, - and pad in SCSI-only devices. */ - current_cdb[16], - sense[256]; + uint8_t *temp_buffer; + uint8_t atapi_cdb[16]; + uint8_t current_cdb[16]; + uint8_t sense[256]; - uint8_t status, phase, - error, id, - pad0, cur_lun, - pad1, pad2; +#ifdef ANCIENT_CODE + /* Task file. */ + uint8_t features; + uint8_t phase; + uint16_t request_length; + uint8_t status; + uint8_t error; + uint16_t pad; + uint32_t pos; +#endif - uint16_t request_length, pad4; + uint8_t id; + uint8_t cur_lun; + uint8_t pad0; + uint8_t pad1; - int requested_blocks, packet_status, - total_length, do_page_save, - unit_attention, pad5, - pad6, pad7; + uint16_t max_transfer_len; + uint16_t pad2; - uint32_t sector_pos, sector_len, - packet_len, pos; + int requested_blocks; + int packet_status; + int total_length; + int do_page_save; + int unit_attention; + int request_pos; + int pad6; + int pad7; + + uint32_t sector_pos; + uint32_t sector_len; + uint32_t packet_len; double callback; } scsi_disk_t; - extern scsi_disk_t *scsi_disk[HDD_NUM]; +extern void scsi_disk_reset(scsi_common_t *sc); -extern void scsi_disk_hard_reset(void); -extern void scsi_disk_close(void); +extern void scsi_disk_hard_reset(void); +extern void scsi_disk_close(void); + +#endif /*SCSI_DISK_H*/ diff --git a/src/include/86box/scsi_ncr5380.h b/src/include/86box/scsi_ncr5380.h index b939162fd..ecf5660ef 100644 --- a/src/include/86box/scsi_ncr5380.h +++ b/src/include/86box/scsi_ncr5380.h @@ -1,36 +1,37 @@ /* - * 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. + * 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. + * This file is part of the 86Box distribution. * - * Implementation of the NCR 5380 series of SCSI Host Adapters - * made by NCR. These controllers were designed for - * the ISA bus. + * Implementation of the NCR 5380 series of SCSI Host Adapters + * made by NCR. These controllers were designed for + * the ISA bus. * * * - * Authors: Sarah Walker, - * TheCollector1995, - * Fred N. van Kempen, + * Authors: Sarah Walker, + * TheCollector1995, + * Fred N. van Kempen, * - * Copyright 2017-2018 Sarah Walker. - * Copyright 2017-2018 TheCollector1995. - * Copyright 2017,2018 Fred N. van Kempen. + * Copyright 2017-2018 Sarah Walker. + * Copyright 2017-2018 TheCollector1995. + * Copyright 2017-2018 Fred N. van Kempen. */ -#ifndef SCSI_NCR5380_H -# define SCSI_NCR5380_H +#ifndef SCSI_NCR5380_H +#define SCSI_NCR5380_H extern const device_t scsi_lcs6821n_device; extern const device_t scsi_rt1000b_device; +extern const device_t scsi_rt1000mc_device; extern const device_t scsi_t128_device; extern const device_t scsi_t130b_device; +extern const device_t scsi_ls2000_device; #if defined(DEV_BRANCH) && defined(USE_SUMO) extern const device_t scsi_scsiat_device; #endif - -#endif /*SCSI_NCR5380_H*/ +#endif /*SCSI_NCR5380_H*/ diff --git a/src/include/86box/scsi_ncr53c8xx.h b/src/include/86box/scsi_ncr53c8xx.h index 730da5fed..5149c2203 100644 --- a/src/include/86box/scsi_ncr53c8xx.h +++ b/src/include/86box/scsi_ncr53c8xx.h @@ -1,29 +1,29 @@ /* - * 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. + * 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. + * This file is part of the 86Box distribution. * - * Implementation of the NCR 53C810 and 53C875 SCSI Host - * Adapters made by NCR and later Symbios and LSI. These - * controllers were designed for the PCI bus. + * Implementation of the NCR 53C810 and 53C875 SCSI Host + * Adapters made by NCR and later Symbios and LSI. These + * controllers were designed for the PCI bus. * * * - * Authors: TheCollector1995, - * Miran Grca, - * Paul Brook (QEMU), - * Artyom Tarasenko (QEMU), + * Authors: TheCollector1995, + * Miran Grca, + * Paul Brook (QEMU), + * Artyom Tarasenko (QEMU), * - * Copyright 2006-2018 Paul Brook. - * Copyright 2009-2018 Artyom Tarasenko. - * Copyright 2017,2018 Miran Grca. + * Copyright 2006-2018 Paul Brook. + * Copyright 2009-2018 Artyom Tarasenko. + * Copyright 2017-2018 Miran Grca. */ -#ifndef SCSI_NCR53C8XX_H -# define SCSI_NCR53C8XX_H +#ifndef SCSI_NCR53C8XX_H +#define SCSI_NCR53C8XX_H extern const device_t ncr53c810_pci_device; extern const device_t ncr53c810_onboard_pci_device; @@ -33,5 +33,4 @@ extern const device_t ncr53c825a_pci_device; extern const device_t ncr53c860_pci_device; extern const device_t ncr53c875_pci_device; - -#endif /*SCSI_NCR53C8XX_H*/ +#endif /*SCSI_NCR53C8XX_H*/ diff --git a/src/include/86box/scsi_pcscsi.h b/src/include/86box/scsi_pcscsi.h index e21fa3801..0ce353d33 100644 --- a/src/include/86box/scsi_pcscsi.h +++ b/src/include/86box/scsi_pcscsi.h @@ -1,33 +1,31 @@ /* - * 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. + * 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. + * This file is part of the 86Box distribution. * - * Implementation of the AMD PCscsi and Tekram DC-390 SCSI - * controllers using the NCR 53c9x series of chips. + * Implementation of the AMD PCscsi and Tekram DC-390 SCSI + * controllers using the NCR 53c9x series of chips. * * * * - * Authors: Fabrice Bellard (QEMU) - * Herve Poussineau (QEMU) - * TheCollector1995, - * Miran Grca, + * Authors: Fabrice Bellard (QEMU) + * Herve Poussineau (QEMU) + * TheCollector1995, + * Miran Grca, * - * Copyright 2005-2018 Fabrice Bellard. - * Copyright 2012-2018 Herve Poussineau. - * Copyright 2017,2018 Miran Grca. + * Copyright 2005-2018 Fabrice Bellard. + * Copyright 2012-2018 Herve Poussineau. + * Copyright 2017-2018 Miran Grca. */ #ifndef SCSI_PCSCSI_H -# define SCSI_PCSCSI_H - +#define SCSI_PCSCSI_H extern const device_t dc390_pci_device; extern const device_t ncr53c90_mca_device; - - -#endif /*SCSI_BUSLOGIC_H*/ + +#endif /*SCSI_BUSLOGIC_H*/ diff --git a/src/include/86box/scsi_spock.h b/src/include/86box/scsi_spock.h index 959fe3d04..057271772 100644 --- a/src/include/86box/scsi_spock.h +++ b/src/include/86box/scsi_spock.h @@ -1,25 +1,27 @@ /* - * 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. + * 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. + * This file is part of the 86Box distribution. * - * Implementation of the IBM PS/2 SCSI controller with - * cache for MCA only. + * Implementation of the IBM PS/2 SCSI controller with + * cache for MCA only. * * * - * Authors: Sarah Walker, - * TheCollector1995, + * Authors: Sarah Walker, + * TheCollector1995, * - * Copyright 2020 Sarah Walker. - * Copyright 2020 TheCollector1995. + * Copyright 2020 Sarah Walker. + * Copyright 2020 TheCollector1995. */ + #ifndef SCSI_SPOCK_H -# define SCSI_SPOCK_H +#define SCSI_SPOCK_H extern const device_t spock_device; - -#endif /*SCSI_SPOCK_H*/ \ No newline at end of file +extern const device_t tribble_device; + +#endif /*SCSI_SPOCK_H*/ diff --git a/src/include/86box/scsi_x54x.h b/src/include/86box/scsi_x54x.h index af91ee7d2..0f1874302 100644 --- a/src/include/86box/scsi_x54x.h +++ b/src/include/86box/scsi_x54x.h @@ -1,64 +1,61 @@ /* - * 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. + * 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. + * This file is part of the 86Box distribution. * - * Header of the code common to the AHA-154x series of SCSI - * Host Adapters made by Adaptec, Inc. and the BusLogic series - * of SCSI Host Adapters made by Mylex. - * These controllers were designed for various buses. + * Header of the code common to the AHA-154x series of SCSI + * Host Adapters made by Adaptec, Inc. and the BusLogic series + * of SCSI Host Adapters made by Mylex. + * These controllers were designed for various buses. * * * - * Authors: TheCollector1995, - * Miran Grca, - * Fred N. van Kempen, + * Authors: TheCollector1995, + * Miran Grca, + * Fred N. van Kempen, * - * Copyright 2016-2018 Miran Grca. - * Copyright 2017,2018 Fred N. van Kempen. + * Copyright 2016-2018 Miran Grca. + * Copyright 2017-2018 Fred N. van Kempen. */ -#ifndef SCSI_X54X_H +#ifndef SCSI_X54X_H #define SCSI_X54X_H -#define SCSI_DELAY_TM 1 /* was 50 */ - - -#define ROM_SIZE 16384 /* one ROM is 16K */ -#define NVR_SIZE 256 /* size of NVR */ +#define SCSI_DELAY_TM 1 /* was 50 */ +#define ROM_SIZE 16384 /* one ROM is 16K */ +#define NVR_SIZE 256 /* size of NVR */ /* EEPROM map and bit definitions. */ -#define EE0_HOSTID 0x07 /* EE(0) [2:0] */ -#define EE0_ALTFLOP 0x80 /* EE(0) [7] FDC at 370h */ -#define EE1_IRQCH 0x07 /* EE(1) [3:0] */ -#define EE1_DMACH 0x70 /* EE(1) [7:4] */ -#define EE2_RMVOK 0x01 /* EE(2) [0] Support removable disks */ -#define EE2_HABIOS 0x02 /* EE(2) [1] HA Bios Space Reserved */ -#define EE2_INT19 0x04 /* EE(2) [2] HA Bios Controls INT19 */ -#define EE2_DYNSCAN 0x08 /* EE(2) [3] Dynamically scan bus */ -#define EE2_TWODRV 0x10 /* EE(2) [4] Allow more than 2 drives */ -#define EE2_SEEKRET 0x20 /* EE(2) [5] Immediate return on seek */ -#define EE2_EXT1G 0x80 /* EE(2) [7] Extended Translation >1GB */ -#define EE3_SPEED 0x00 /* EE(3) [7:0] DMA Speed */ -#define SPEED_33 0xFF -#define SPEED_50 0x00 -#define SPEED_56 0x04 -#define SPEED_67 0x01 -#define SPEED_80 0x02 -#define SPEED_10 0x03 -#define EE4_FLOPTOK 0x80 /* EE(4) [7] Support Flopticals */ -#define EE6_PARITY 0x01 /* EE(6) [0] parity check enable */ -#define EE6_TERM 0x02 /* EE(6) [1] host term enable */ -#define EE6_RSTBUS 0x04 /* EE(6) [2] reset SCSI bus on boot */ -#define EEE_SYNC 0x01 /* EE(E) [0] Enable Sync Negotiation */ -#define EEE_DISCON 0x02 /* EE(E) [1] Enable Disconnection */ -#define EEE_FAST 0x04 /* EE(E) [2] Enable FAST SCSI */ -#define EEE_START 0x08 /* EE(E) [3] Enable Start Unit */ - +#define EE0_HOSTID 0x07 /* EE(0) [2:0] */ +#define EE0_ALTFLOP 0x80 /* EE(0) [7] FDC at 370h */ +#define EE1_IRQCH 0x07 /* EE(1) [3:0] */ +#define EE1_DMACH 0x70 /* EE(1) [7:4] */ +#define EE2_RMVOK 0x01 /* EE(2) [0] Support removable disks */ +#define EE2_HABIOS 0x02 /* EE(2) [1] HA Bios Space Reserved */ +#define EE2_INT19 0x04 /* EE(2) [2] HA Bios Controls INT19 */ +#define EE2_DYNSCAN 0x08 /* EE(2) [3] Dynamically scan bus */ +#define EE2_TWODRV 0x10 /* EE(2) [4] Allow more than 2 drives */ +#define EE2_SEEKRET 0x20 /* EE(2) [5] Immediate return on seek */ +#define EE2_EXT1G 0x80 /* EE(2) [7] Extended Translation >1GB */ +#define EE3_SPEED 0x00 /* EE(3) [7:0] DMA Speed */ +#define SPEED_33 0xFF +#define SPEED_50 0x00 +#define SPEED_56 0x04 +#define SPEED_67 0x01 +#define SPEED_80 0x02 +#define SPEED_10 0x03 +#define EE4_FLOPTOK 0x80 /* EE(4) [7] Support Flopticals */ +#define EE6_PARITY 0x01 /* EE(6) [0] parity check enable */ +#define EE6_TERM 0x02 /* EE(6) [1] host term enable */ +#define EE6_RSTBUS 0x04 /* EE(6) [2] reset SCSI bus on boot */ +#define EEE_SYNC 0x01 /* EE(E) [0] Enable Sync Negotiation */ +#define EEE_DISCON 0x02 /* EE(E) [1] Enable Disconnection */ +#define EEE_FAST 0x04 /* EE(E) [2] Enable FAST SCSI */ +#define EEE_START 0x08 /* EE(E) [3] Enable Start Unit */ /* * Host Adapter I/O ports. @@ -76,66 +73,70 @@ */ /* WRITE CONTROL commands. */ -#define CTRL_HRST 0x80 /* Hard reset */ -#define CTRL_SRST 0x40 /* Soft reset */ -#define CTRL_IRST 0x20 /* interrupt reset */ -#define CTRL_SCRST 0x10 /* SCSI bus reset */ +#define CTRL_HRST 0x80 /* Hard reset */ +#define CTRL_SRST 0x40 /* Soft reset */ +#define CTRL_IRST 0x20 /* interrupt reset */ +#define CTRL_SCRST 0x10 /* SCSI bus reset */ /* READ STATUS. */ -#define STAT_STST 0x80 /* self-test in progress */ -#define STAT_DFAIL 0x40 /* internal diagnostic failure */ -#define STAT_INIT 0x20 /* mailbox initialization required */ -#define STAT_IDLE 0x10 /* HBA is idle */ -#define STAT_CDFULL 0x08 /* Command/Data output port is full */ -#define STAT_DFULL 0x04 /* Data input port is full */ -#define STAT_INVCMD 0x01 /* Invalid command */ +#define STAT_STST 0x80 /* self-test in progress */ +#define STAT_DFAIL 0x40 /* internal diagnostic failure */ +#define STAT_INIT 0x20 /* mailbox initialization required */ +#define STAT_IDLE 0x10 /* HBA is idle */ +#define STAT_CDFULL 0x08 /* Command/Data output port is full */ +#define STAT_DFULL 0x04 /* Data input port is full */ +#define STAT_INVCMD 0x01 /* Invalid command */ /* READ/WRITE DATA. */ -#define CMD_NOP 0x00 /* No operation */ -#define CMD_MBINIT 0x01 /* mailbox initialization */ -#define CMD_START_SCSI 0x02 /* Start SCSI command */ -#define CMD_BIOSCMD 0x03 /* Execute ROM BIOS command */ -#define CMD_INQUIRY 0x04 /* Adapter inquiry */ -#define CMD_EMBOI 0x05 /* enable Mailbox Out Interrupt */ -#define CMD_SELTIMEOUT 0x06 /* Set SEL timeout */ -#define CMD_BUSON_TIME 0x07 /* set bus-On time */ -#define CMD_BUSOFF_TIME 0x08 /* set bus-off time */ -#define CMD_DMASPEED 0x09 /* set ISA DMA speed */ -#define CMD_RETDEVS 0x0A /* return installed devices */ -#define CMD_RETCONF 0x0B /* return configuration data */ -#define CMD_TARGET 0x0C /* set HBA to target mode */ -#define CMD_RETSETUP 0x0D /* return setup data */ -#define CMD_WRITE_CH2 0x1A /* write channel 2 buffer */ -#define CMD_READ_CH2 0x1B /* read channel 2 buffer */ -#define CMD_ECHO 0x1F /* ECHO command data */ -#define CMD_OPTIONS 0x21 /* set adapter options */ +#define CMD_NOP 0x00 /* No operation */ +#define CMD_MBINIT 0x01 /* mailbox initialization */ +#define CMD_START_SCSI 0x02 /* Start SCSI command */ +#define CMD_BIOSCMD 0x03 /* Execute ROM BIOS command */ +#define CMD_INQUIRY 0x04 /* Adapter inquiry */ +#define CMD_EMBOI 0x05 /* enable Mailbox Out Interrupt */ +#define CMD_SELTIMEOUT 0x06 /* Set SEL timeout */ +#define CMD_BUSON_TIME 0x07 /* set bus-On time */ +#define CMD_BUSOFF_TIME 0x08 /* set bus-off time */ +#define CMD_DMASPEED 0x09 /* set ISA DMA speed */ +#define CMD_RETDEVS 0x0A /* return installed devices */ +#define CMD_RETCONF 0x0B /* return configuration data */ +#define CMD_TARGET 0x0C /* set HBA to target mode */ +#define CMD_RETSETUP 0x0D /* return setup data */ +#define CMD_WRITE_CH2 0x1A /* write channel 2 buffer */ +#define CMD_READ_CH2 0x1B /* read channel 2 buffer */ +#define CMD_ECHO 0x1F /* ECHO command data */ +#define CMD_OPTIONS 0x21 /* set adapter options */ /* READ INTERRUPT STATUS. */ -#define INTR_ANY 0x80 /* any interrupt */ -#define INTR_SRCD 0x08 /* SCSI reset detected */ -#define INTR_HACC 0x04 /* HA command complete */ -#define INTR_MBOA 0x02 /* MBO empty */ -#define INTR_MBIF 0x01 /* MBI full */ +#define INTR_ANY 0x80 /* any interrupt */ +#define INTR_SRCD 0x08 /* SCSI reset detected */ +#define INTR_HACC 0x04 /* HA command complete */ +#define INTR_MBOA 0x02 /* MBO empty */ +#define INTR_MBIF 0x01 /* MBI full */ - -#define ADDR_TO_U32(x) (((x).hi<<16)|((x).mid<<8)|((x).lo&0xFF)) -#define U32_TO_ADDR(a,x) do {(a).hi=(x)>>16;(a).mid=(x)>>8;(a).lo=(x)&0xFF;}while(0) +#define ADDR_TO_U32(x) (((x).hi << 16) | ((x).mid << 8) | ((x).lo & 0xFF)) +#define U32_TO_ADDR(a, x) \ + do { \ + (a).hi = (x) >> 16; \ + (a).mid = (x) >> 8; \ + (a).lo = (x) &0xFF; \ + } while (0) /* * Mailbox Definitions. * * Mailbox Out (MBO) command values. */ -#define MBO_FREE 0x00 -#define MBO_START 0x01 -#define MBO_ABORT 0x02 +#define MBO_FREE 0x00 +#define MBO_START 0x01 +#define MBO_ABORT 0x02 /* Mailbox In (MBI) status values. */ -#define MBI_FREE 0x00 -#define MBI_SUCCESS 0x01 -#define MBI_ABORT 0x02 -#define MBI_NOT_FOUND 0x03 -#define MBI_ERROR 0x04 +#define MBI_FREE 0x00 +#define MBI_SUCCESS 0x01 +#define MBI_ABORT 0x02 +#define MBI_NOT_FOUND 0x03 +#define MBI_ERROR 0x04 /* * @@ -146,46 +147,45 @@ * */ /* Byte 0 Command Control Block Operation Code */ -#define SCSI_INITIATOR_COMMAND 0x00 -#define TARGET_MODE_COMMAND 0x01 -#define SCATTER_GATHER_COMMAND 0x02 -#define SCSI_INITIATOR_COMMAND_RES 0x03 -#define SCATTER_GATHER_COMMAND_RES 0x04 -#define BUS_RESET 0x81 +#define SCSI_INITIATOR_COMMAND 0x00 +#define TARGET_MODE_COMMAND 0x01 +#define SCATTER_GATHER_COMMAND 0x02 +#define SCSI_INITIATOR_COMMAND_RES 0x03 +#define SCATTER_GATHER_COMMAND_RES 0x04 +#define BUS_RESET 0x81 /* Byte 1 Address and Direction Control */ -#define CCB_TARGET_ID_SHIFT 0x06 /* CCB Op Code = 00, 02 */ -#define CCB_INITIATOR_ID_SHIFT 0x06 /* CCB Op Code = 01 */ -#define CCB_DATA_XFER_IN 0x01 -#define CCB_DATA_XFER_OUT 0x02 -#define CCB_LUN_MASK 0x07 /* Logical Unit Number */ +#define CCB_TARGET_ID_SHIFT 0x06 /* CCB Op Code = 00, 02 */ +#define CCB_INITIATOR_ID_SHIFT 0x06 /* CCB Op Code = 01 */ +#define CCB_DATA_XFER_IN 0x01 +#define CCB_DATA_XFER_OUT 0x02 +#define CCB_LUN_MASK 0x07 /* Logical Unit Number */ /* Byte 2 SCSI_Command_Length - Length of SCSI CDB Byte 3 Request Sense Allocation Length */ -#define FOURTEEN_BYTES 0x00 /* Request Sense Buffer size */ -#define NO_AUTO_REQUEST_SENSE 0x01 /* No Request Sense Buffer */ +#define FOURTEEN_BYTES 0x00 /* Request Sense Buffer size */ +#define NO_AUTO_REQUEST_SENSE 0x01 /* No Request Sense Buffer */ -/* Bytes 4, 5 and 6 Data Length - Data transfer byte count */ -/* Bytes 7, 8 and 9 Data Pointer - SGD List or Data Buffer */ -/* Bytes 10, 11 and 12 Link Pointer - Next CCB in Linked List */ -/* Byte 13 Command Link ID - TBD (I don't know yet) */ -/* Byte 14 Host Status - Host Adapter status */ -#define CCB_COMPLETE 0x00 /* CCB completed without error */ -#define CCB_LINKED_COMPLETE 0x0A /* Linked command completed */ -#define CCB_LINKED_COMPLETE_INT 0x0B /* Linked complete with intr */ -#define CCB_SELECTION_TIMEOUT 0x11 /* Set SCSI selection timed out */ -#define CCB_DATA_OVER_UNDER_RUN 0x12 -#define CCB_UNEXPECTED_BUS_FREE 0x13 /* Trg dropped SCSI BSY */ -#define CCB_PHASE_SEQUENCE_FAIL 0x14 /* Trg bus phase sequence fail */ -#define CCB_BAD_MBO_COMMAND 0x15 /* MBO command not 0, 1 or 2 */ -#define CCB_INVALID_OP_CODE 0x16 /* CCB invalid operation code */ -#define CCB_BAD_LINKED_LUN 0x17 /* Linked CCB LUN diff from 1st */ -#define CCB_INVALID_DIRECTION 0x18 /* Invalid target direction */ -#define CCB_DUPLICATE_CCB 0x19 /* Duplicate CCB */ -#define CCB_INVALID_CCB 0x1A /* Invalid CCB - bad parameter */ +/* Bytes 4, 5 and 6 Data Length - Data transfer byte count */ +/* Bytes 7, 8 and 9 Data Pointer - SGD List or Data Buffer */ +/* Bytes 10, 11 and 12 Link Pointer - Next CCB in Linked List */ +/* Byte 13 Command Link ID - TBD (I don't know yet) */ +/* Byte 14 Host Status - Host Adapter status */ +#define CCB_COMPLETE 0x00 /* CCB completed without error */ +#define CCB_LINKED_COMPLETE 0x0A /* Linked command completed */ +#define CCB_LINKED_COMPLETE_INT 0x0B /* Linked complete with intr */ +#define CCB_SELECTION_TIMEOUT 0x11 /* Set SCSI selection timed out */ +#define CCB_DATA_OVER_UNDER_RUN 0x12 +#define CCB_UNEXPECTED_BUS_FREE 0x13 /* Trg dropped SCSI BSY */ +#define CCB_PHASE_SEQUENCE_FAIL 0x14 /* Trg bus phase sequence fail */ +#define CCB_BAD_MBO_COMMAND 0x15 /* MBO command not 0, 1 or 2 */ +#define CCB_INVALID_OP_CODE 0x16 /* CCB invalid operation code */ +#define CCB_BAD_LINKED_LUN 0x17 /* Linked CCB LUN diff from 1st */ +#define CCB_INVALID_DIRECTION 0x18 /* Invalid target direction */ +#define CCB_DUPLICATE_CCB 0x19 /* Duplicate CCB */ +#define CCB_INVALID_CCB 0x1A /* Invalid CCB - bad parameter */ -#define lba32_blk(p) ((uint32_t)(p->u.lba.lba0<<24) | (p->u.lba.lba1<<16) | \ - (p->u.lba.lba2<<8) | p->u.lba.lba3) +#define lba32_blk(p) ((uint32_t) (p->u.lba.lba0 << 24) | (p->u.lba.lba1 << 16) | (p->u.lba.lba2 << 8) | p->u.lba.lba3) /* * @@ -193,61 +193,60 @@ * * Adapter limits */ -#define MAX_SG_DESCRIPTORS 32 /* Always make the array 32 elements long, if less are used, that's not an issue. */ +#define MAX_SG_DESCRIPTORS 32 /* Always make the array 32 elements long, if less are used, that's not an issue. */ - -#pragma pack(push,1) -typedef struct { +#pragma pack(push, 1) +typedef struct addr24_s { uint8_t hi; uint8_t mid; uint8_t lo; -} addr24; +} addr24_t; /* Structure for the INQUIRE_SETUP_INFORMATION reply. */ -typedef struct { - uint8_t uOffset :4, - uTransferPeriod :3, - fSynchronous :1; +typedef struct ReplyInquireSetupInformationSynchronousValue_t { + uint8_t uOffset : 4; + uint8_t uTransferPeriod : 3; + uint8_t fSynchronous : 1; } ReplyInquireSetupInformationSynchronousValue; -typedef struct { - uint8_t fSynchronousInitiationEnabled :1, - fParityCheckingEnabled :1, - uReserved1 :6; - uint8_t uBusTransferRate; - uint8_t uPreemptTimeOnBus; - uint8_t uTimeOffBus; - uint8_t cMailbox; - addr24 MailboxAddress; +typedef struct ReplyInquireSetupInformation_t { + uint8_t fSynchronousInitiationEnabled : 1; + uint8_t fParityCheckingEnabled : 1; + uint8_t uReserved1 : 6; + uint8_t uBusTransferRate; + uint8_t uPreemptTimeOnBus; + uint8_t uTimeOffBus; + uint8_t cMailbox; + addr24_t MailboxAddress; ReplyInquireSetupInformationSynchronousValue SynchronousValuesId0To7[8]; - uint8_t uDisconnectPermittedId0To7; - uint8_t VendorSpecificData[28]; + uint8_t uDisconnectPermittedId0To7; + uint8_t VendorSpecificData[28]; } ReplyInquireSetupInformation; -typedef struct { - uint8_t Count; - addr24 Address; +typedef struct MailboxInit_t { + uint8_t Count; + addr24_t Address; } MailboxInit_t; -typedef struct { - uint8_t CmdStatus; - addr24 CCBPointer; +typedef struct Mailbox_t { + uint8_t CmdStatus; + addr24_t CCBPointer; } Mailbox_t; -typedef struct { - uint32_t CCBPointer; +typedef struct Mailbox32_t { + uint32_t CCBPointer; union { - struct { - uint8_t Reserved[3]; - uint8_t ActionCode; - } out; - struct { - uint8_t HostStatus; - uint8_t TargetStatus; - uint8_t Reserved; - uint8_t CompletionCode; - } in; - } u; + struct out_t { + uint8_t Reserved[3]; + uint8_t ActionCode; + } out; + struct in_t { + uint8_t HostStatus; + uint8_t TargetStatus; + uint8_t Reserved; + uint8_t CompletionCode; + } in; + } u; } Mailbox32_t; /* Byte 15 Target Status @@ -256,260 +255,284 @@ typedef struct { Bytes 16 and 17 Reserved (must be 0) Bytes 18 through 18+n-1, where n=size of CDB Command Descriptor Block */ -typedef struct { - uint8_t Opcode; - uint8_t Reserved1 :3, - ControlByte :2, - TagQueued :1, - QueueTag :2; - uint8_t CdbLength; - uint8_t RequestSenseLength; - uint32_t DataLength; - uint32_t DataPointer; - uint8_t Reserved2[2]; - uint8_t HostStatus; - uint8_t TargetStatus; - uint8_t Id; - uint8_t Lun :5, - LegacyTagEnable :1, - LegacyQueueTag :2; - uint8_t Cdb[12]; - uint8_t Reserved3[6]; - uint32_t SensePointer; +typedef struct CCB32_t { + uint8_t Opcode; + uint8_t Reserved1 : 3; + uint8_t ControlByte : 2; + uint8_t TagQueued : 1; + uint8_t QueueTag : 2; + uint8_t CdbLength; + uint8_t RequestSenseLength; + uint32_t DataLength; + uint32_t DataPointer; + uint8_t Reserved2[2]; + uint8_t HostStatus; + uint8_t TargetStatus; + uint8_t Id; + uint8_t Lun : 5; + uint8_t LegacyTagEnable : 1; + uint8_t LegacyQueueTag : 2; + uint8_t Cdb[12]; + uint8_t Reserved3[6]; + uint32_t SensePointer; } CCB32; -typedef struct { - uint8_t Opcode; - uint8_t Lun :3, - ControlByte :2, - Id :3; - uint8_t CdbLength; - uint8_t RequestSenseLength; - addr24 DataLength; - addr24 DataPointer; - addr24 LinkPointer; - uint8_t LinkId; - uint8_t HostStatus; - uint8_t TargetStatus; - uint8_t Reserved[2]; - uint8_t Cdb[12]; +typedef struct CCB_t { + uint8_t Opcode; + uint8_t Lun : 3; + uint8_t ControlByte : 2; + uint8_t Id : 3; + uint8_t CdbLength; + uint8_t RequestSenseLength; + addr24_t DataLength; + addr24_t DataPointer; + addr24_t LinkPointer; + uint8_t LinkId; + uint8_t HostStatus; + uint8_t TargetStatus; + uint8_t Reserved[2]; + uint8_t Cdb[12]; } CCB; -typedef struct { - uint8_t Opcode; - uint8_t Pad1 :3, - ControlByte :2, - Pad2 :3; - uint8_t CdbLength; - uint8_t RequestSenseLength; - uint8_t Pad3[9]; - uint8_t CompletionCode; /* Only used by the 1542C/CF(/CP?) BIOS mailboxes */ - uint8_t HostStatus; - uint8_t TargetStatus; - uint8_t Pad4[2]; - uint8_t Cdb[12]; +typedef struct CCBC_t { + uint8_t Opcode; + uint8_t Pad1 : 3; + uint8_t ControlByte : 2; + uint8_t Pad2 : 3; + uint8_t CdbLength; + uint8_t RequestSenseLength; + uint8_t Pad3[9]; + uint8_t CompletionCode; /* Only used by the 1542C/CF(/CP?) BIOS mailboxes */ + uint8_t HostStatus; + uint8_t TargetStatus; + uint8_t Pad4[2]; + uint8_t Cdb[12]; } CCBC; -typedef union { - CCB32 new; - CCB old; - CCBC common; +typedef union CCBU_t { + CCB32 new; + CCB old; + CCBC common; } CCBU; typedef struct { - CCBU CmdBlock; - uint8_t *RequestSenseBuffer; - uint32_t CCBPointer; - int Is24bit; - uint8_t TargetID, - LUN, - HostStatus, - TargetStatus, - MailboxCompletionCode; + CCBU CmdBlock; + uint8_t *RequestSenseBuffer; + uint32_t CCBPointer; + int Is24bit; + uint8_t TargetID; + uint8_t LUN; + uint8_t HostStatus; + uint8_t TargetStatus; + uint8_t MailboxCompletionCode; } Req_t; -typedef struct -{ - uint8_t command; - uint8_t lun:3, - reserved:2, - id:3; - union { - struct { - uint16_t cyl; - uint8_t head; - uint8_t sec; - } chs; - struct { - uint8_t lba0; /* MSB */ - uint8_t lba1; - uint8_t lba2; - uint8_t lba3; /* LSB */ - } lba; - } u; - uint8_t secount; - addr24 dma_address; +typedef struct BIOSCMD_t { + uint8_t command; + uint8_t lun : 3; + uint8_t reserved : 2; + uint8_t id : 3; + union { + struct chs_t { + uint16_t cyl; + uint8_t head; + uint8_t sec; + } chs; + struct lba_t { + uint8_t lba0; /* MSB */ + uint8_t lba1; + uint8_t lba2; + uint8_t lba3; /* LSB */ + } lba; + } u; + uint8_t secount; + addr24_t dma_address; } BIOSCMD; -typedef struct { - uint32_t Segment; - uint32_t SegmentPointer; +typedef struct SGE32_t { + uint32_t Segment; + uint32_t SegmentPointer; } SGE32; -typedef struct { - addr24 Segment; - addr24 SegmentPointer; +typedef struct SGE_t { + addr24_t Segment; + addr24_t SegmentPointer; } SGE; #pragma pack(pop) -#define X54X_CDROM_BOOT 1 -#define X54X_32BIT 2 -#define X54X_LBA_BIOS 4 -#define X54X_INT_GEOM_WRITABLE 8 -#define X54X_MBX_24BIT 16 -#define X54X_ISAPNP 32 +#define X54X_CDROM_BOOT 1 +#define X54X_32BIT 2 +#define X54X_LBA_BIOS 4 +#define X54X_INT_GEOM_WRITABLE 8 +#define X54X_MBX_24BIT 16 +#define X54X_ISAPNP 32 +#define X54X_HAS_SIGNATURE 64 -typedef struct { +typedef struct x54x_t { /* 32 bytes */ - char vendor[16], /* name of device vendor */ - name[16]; /* name of device */ + char vendor[16]; /* name of device vendor */ + char name[16]; /* name of device */ /* 24 bytes */ - int8_t type, /* type of device */ - IrqEnabled, Irq, - DmaChannel, - HostID; + int8_t type; /* type of device */ + int8_t IrqEnabled; + int8_t Irq; + int8_t DmaChannel; + int8_t HostID; - uint8_t callback_phase :4, - callback_sub_phase :4, - scsi_cmd_phase, bus, - sync, - parity, shram_mode, - Geometry, Control, - Command, CmdParam, - BusOnTime, BusOffTime, - ATBusSpeed, setup_info_len, - max_id, pci_slot, - temp_cdb[12]; + uint8_t callback_phase : 4; + uint8_t callback_sub_phase : 4; + uint8_t scsi_cmd_phase; + uint8_t bus; + uint8_t sync; + uint8_t parity; + uint8_t shram_mode; + uint8_t Geometry; + uint8_t Control; + uint8_t Command; + uint8_t CmdParam; + uint8_t BusOnTime; + uint8_t BusOffTime; + uint8_t ATBusSpeed; + uint8_t setup_info_len; + uint8_t max_id; + uint8_t pci_slot; + uint8_t irq_state; + uint8_t pad; + uint8_t pad0; + uint8_t pad1; + uint8_t temp_cdb[12]; - volatile uint8_t /* for multi-threading, keep */ - Status, Interrupt, /* these volatile */ - MailboxIsBIOS, ToRaise, - flags; + /* for multi-threading, keep these volatile */ + volatile uint8_t Status; + volatile uint8_t Interrupt; + volatile uint8_t MailboxIsBIOS; + volatile uint8_t ToRaise; + volatile uint8_t flags; /* 65928 bytes */ - uint8_t pos_regs[8], /* MCA */ - CmdBuf[128], - DataBuf[65536], - shadow_ram[128], - dma_buffer[128], - cmd_33_buf[4096]; + uint8_t pos_regs[8]; /* MCA */ + uint8_t CmdBuf[128]; + uint8_t DataBuf[65536]; + uint8_t shadow_ram[128]; + uint8_t dma_buffer[128]; + uint8_t cmd_33_buf[4096]; /* 16 bytes */ - char *fw_rev; /* The 4 bytes of the revision command information + 2 extra bytes for BusLogic */ + char *fw_rev; /* The 4 bytes of the revision command information + 2 extra bytes for BusLogic */ - uint8_t *rom1, /* main BIOS image */ - *rom2, /* SCSI-Select image */ - *nvr; /* EEPROM buffer */ + uint8_t *rom1; /* main BIOS image */ + uint8_t *rom2; /* SCSI-Select image */ + uint8_t *nvr; /* EEPROM buffer */ /* 6 words = 12 bytes */ - uint16_t DataReply, DataReplyLeft, - rom_ioaddr, /* offset in BIOS of I/O addr */ - rom_shram, /* index to shared RAM */ - rom_shramsz, /* size of shared RAM */ - rom_fwhigh, /* offset in BIOS of ver ID */ - pnp_len, /* length of the PnP ROM */ - pnp_offset, /* offset in the microcode ROM of the PnP ROM */ - cmd_33_len, /* length of the SCSISelect code decompressor program */ - cmd_33_offset; /* offset in the microcode ROM of the SCSISelect code decompressor program */ + uint16_t DataReply; + uint16_t DataReplyLeft; + uint16_t rom_ioaddr; /* offset in BIOS of I/O addr */ + uint16_t rom_shram; /* index to shared RAM */ + uint16_t rom_shramsz; /* size of shared RAM */ + uint16_t rom_fwhigh; /* offset in BIOS of ver ID */ + uint16_t pnp_len; /* length of the PnP ROM */ + uint16_t pnp_offset; /* offset in the microcode ROM of the PnP ROM */ + uint16_t cmd_33_len; /* length of the SCSISelect code decompressor program */ + uint16_t cmd_33_offset; /* offset in the microcode ROM of the SCSISelect code decompressor program */ /* 16 + 20 + 52 = 88 bytes */ - volatile int - MailboxOutInterrupts, - PendingInterrupt, Lock, - target_data_len, pad0; + volatile int MailboxOutInterrupts; + volatile int PendingInterrupt; + volatile int Lock; + volatile int target_data_len; + volatile int pad2; - uint32_t Base, fdc_address, rom_addr, /* address of BIOS ROM */ - CmdParamLeft, Outgoing, - transfer_size; + uint32_t Base; + uint32_t fdc_address; + uint32_t rom_addr; /* address of BIOS ROM */ + uint32_t CmdParamLeft; + uint32_t Outgoing; + uint32_t transfer_size; - volatile uint32_t - MailboxInit, MailboxCount, - MailboxOutAddr, MailboxOutPosCur, - MailboxInAddr, MailboxInPosCur, - MailboxReq, - BIOSMailboxInit, BIOSMailboxCount, - BIOSMailboxOutAddr, BIOSMailboxOutPosCur, - BIOSMailboxReq, - Residue, card_bus; /* Basically a copy of device flags */ + volatile uint32_t MailboxInit; + volatile uint32_t MailboxCount; + volatile uint32_t MailboxOutAddr; + volatile uint32_t MailboxOutPosCur; + volatile uint32_t MailboxInAddr; + volatile uint32_t MailboxInPosCur; + volatile uint32_t MailboxReq; + volatile uint32_t BIOSMailboxInit; + volatile uint32_t BIOSMailboxCount; + volatile uint32_t BIOSMailboxOutAddr; + volatile uint32_t BIOSMailboxOutPosCur; + volatile uint32_t BIOSMailboxReq; + volatile uint32_t Residue; + volatile uint32_t card_bus; /* Basically a copy of device flags */ /* 8 bytes */ - uint64_t temp_period; + uint64_t temp_period; /* 16 bytes */ - double media_period, ha_bps; /* bytes per second */ + double media_period; + double ha_bps; /* bytes per second */ /* 8 bytes */ - char *bios_path, /* path to BIOS image file */ - *mcode_path, /* path to microcode image file, needed by the AHA-1542CP */ - *nvr_path; /* path to NVR image file */ + char *bios_path; /* path to BIOS image file */ + char *mcode_path; /* path to microcode image file, needed by the AHA-1542CP */ + char *nvr_path; /* path to NVR image file */ /* 56 bytes */ /* Pointer to a structure of vendor-specific data that only the vendor-specific code can understand */ - void *ven_data; + void *ven_data; /* Pointer to a function that performs vendor-specific operation during the timer callback */ - void (*ven_callback)(void *p); + void (*ven_callback)(void *priv); /* Pointer to a function that executes the second parameter phase of the vendor-specific command */ - void (*ven_cmd_phase1)(void *p); + void (*ven_cmd_phase1)(void *priv); /* Pointer to a function that gets the host adapter ID in case it has to be read from a non-standard location */ - uint8_t (*ven_get_host_id)(void *p); + uint8_t (*ven_get_host_id)(void *priv); /* Pointer to a function that updates the IRQ in the vendor-specific space */ - uint8_t (*ven_get_irq)(void *p); + uint8_t (*ven_get_irq)(void *priv); /* Pointer to a function that updates the DMA channel in the vendor-specific space */ - uint8_t (*ven_get_dma)(void *p); + uint8_t (*ven_get_dma)(void *priv); /* Pointer to a function that returns whether command is fast */ - uint8_t (*ven_cmd_is_fast)(void *p); + uint8_t (*ven_cmd_is_fast)(void *priv); /* Pointer to a function that executes vendor-specific fast path commands */ - uint8_t (*ven_fast_cmds)(void *p, uint8_t cmd); + uint8_t (*ven_fast_cmds)(void *priv, uint8_t cmd); /* Pointer to a function that gets the parameter length for vendor-specific commands */ - uint8_t (*get_ven_param_len)(void *p); + uint8_t (*get_ven_param_len)(void *priv); /* Pointer to a function that executes vendor-specific commands and returns whether or not to suppress the IRQ */ - uint8_t (*ven_cmds)(void *p); + uint8_t (*ven_cmds)(void *priv); /* Pointer to a function that fills in the vendor-specific setup data */ - void (*get_ven_data)(void *p); + void (*get_ven_data)(void *priv); /* Pointer to a function that determines if the mode is aggressive */ - uint8_t (*is_aggressive_mode)(void *p); + uint8_t (*is_aggressive_mode)(void *priv); /* Pointer to a function that returns interrupt type (0 = edge, 1 = level) */ - uint8_t (*interrupt_type)(void *p); + uint8_t (*interrupt_type)(void *priv); /* Pointer to a function that resets vendor-specific data */ - void (*ven_reset)(void *p); + void (*ven_reset)(void *priv); - rom_t bios, /* BIOS memory descriptor */ - uppersck; /* BIOS memory descriptor */ + rom_t bios; /* BIOS memory descriptor */ + rom_t uppersck; /* BIOS memory descriptor */ mem_mapping_t mmio_mapping; - pc_timer_t timer, ResetCB; + pc_timer_t timer; + pc_timer_t ResetCB; - Req_t Req; - - fdc_t *fdc; + Req_t Req; + + fdc_t *fdc; } x54x_t; - -extern void x54x_reset_ctrl(x54x_t *dev, uint8_t Reset); -extern uint8_t x54x_mbo_process(x54x_t *dev); -extern void x54x_wait_for_poll(void); -extern void x54x_io_set(x54x_t *dev, uint32_t base, uint8_t len); -extern void x54x_io_remove(x54x_t *dev, uint32_t base, uint8_t len); -extern void x54x_mem_init(x54x_t *dev, uint32_t addr); -extern void x54x_mem_enable(x54x_t *dev); -extern void x54x_mem_set_addr(x54x_t *dev, uint32_t base); -extern void x54x_mem_disable(x54x_t *dev); -extern void *x54x_init(const device_t *info); -extern void x54x_close(void *priv); -extern void x54x_device_reset(void *priv); - +extern void x54x_reset_ctrl(x54x_t *dev, uint8_t Reset); +extern uint8_t x54x_mbo_process(x54x_t *dev); +extern void x54x_wait_for_poll(void); +extern void x54x_io_set(x54x_t *dev, uint32_t base, uint8_t len); +extern void x54x_io_remove(x54x_t *dev, uint32_t base, uint8_t len); +extern void x54x_mem_init(x54x_t *dev, uint32_t addr); +extern void x54x_mem_enable(x54x_t *dev); +extern void x54x_mem_set_addr(x54x_t *dev, uint32_t base); +extern void x54x_mem_disable(x54x_t *dev); +extern void *x54x_init(const device_t *info); +extern void x54x_close(void *priv); +extern void x54x_device_reset(void *priv); #endif diff --git a/src/include/86box/serial.h b/src/include/86box/serial.h index 5203c17f8..bd7e85a91 100644 --- a/src/include/86box/serial.h +++ b/src/include/86box/serial.h @@ -1,105 +1,142 @@ /* - * 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. + * 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. + * This file is part of the 86Box distribution. * - * Definitions for the NS8250/16450/16550/16650/16750/16850/16950 - * UART emulation. + * Definitions for the NS8250/16450/16550/16650/16750/16850/16950 + * UART emulation. * * * - * Author: Sarah Walker, - * Miran Grca, - * Fred N. van Kempen, + * Authors: Sarah Walker, + * Miran Grca, + * Fred N. van Kempen, * - * Copyright 2008-2020 Sarah Walker. - * Copyright 2016-2020 Miran Grca. - * Copyright 2017-2020 Fred N. van Kempen. + * Copyright 2008-2020 Sarah Walker. + * Copyright 2016-2020 Miran Grca. + * Copyright 2017-2020 Fred N. van Kempen. */ + #ifndef EMU_SERIAL_H -# define EMU_SERIAL_H +#define EMU_SERIAL_H +#define SERIAL_8250 0 +#define SERIAL_8250_PCJR 1 +#define SERIAL_16450 2 +#define SERIAL_16550 3 +#define SERIAL_16650 4 +#define SERIAL_16750 5 +#define SERIAL_16850 6 +#define SERIAL_16950 7 -#define SERIAL_8250 0 -#define SERIAL_8250_PCJR 1 -#define SERIAL_16450 2 -#define SERIAL_16550 3 -#define SERIAL_16650 4 -#define SERIAL_16750 5 -#define SERIAL_16850 6 -#define SERIAL_16950 7 - -#define SERIAL_FIFO_SIZE 16 +#define SERIAL_FIFO_SIZE 16 /* Default settings for the standard ports. */ -#define SERIAL1_ADDR 0x03f8 -#define SERIAL1_IRQ 4 -#define SERIAL2_ADDR 0x02f8 -#define SERIAL2_IRQ 3 -#define SERIAL3_ADDR 0x03e8 -#define SERIAL3_IRQ 4 -#define SERIAL4_ADDR 0x02e8 -#define SERIAL4_IRQ 3 - +#define COM1_ADDR 0x03f8 +#define COM1_IRQ 4 +#define COM2_ADDR 0x02f8 +#define COM2_IRQ 3 +#define COM3_ADDR 0x03e8 +#define COM3_IRQ 4 +#define COM4_ADDR 0x02e8 +#define COM4_IRQ 3 struct serial_device_s; struct serial_s; -typedef struct serial_s -{ - uint8_t lsr, thr, mctrl, rcr, - iir, ier, lcr, msr, - dat, int_status, scratch, fcr, - irq, type, inst, transmit_enabled, - fifo_enabled, rcvr_fifo_len, bits, data_bits, - baud_cycles, rcvr_fifo_full, txsr, pad; +typedef struct serial_s { + uint8_t lsr; + uint8_t thr; + uint8_t mctrl; + uint8_t rcr; + uint8_t iir; + uint8_t ier; + uint8_t lcr; + uint8_t msr; + uint8_t dat; + uint8_t int_status; + uint8_t scratch; + uint8_t fcr; + uint8_t irq; + uint8_t type; + uint8_t inst; + uint8_t transmit_enabled; + uint8_t fifo_enabled; + uint8_t bits; + uint8_t data_bits; + uint8_t baud_cycles; + uint8_t txsr; + uint8_t txsr_empty; + uint8_t msr_set; + uint8_t irq_state; - uint16_t dlab, base_address; + uint16_t dlab; + uint16_t base_address; + uint16_t out_new; + uint16_t thr_empty; - uint8_t rcvr_fifo_pos, xmit_fifo_pos, - pad0, pad1, - rcvr_fifo[SERIAL_FIFO_SIZE], xmit_fifo[SERIAL_FIFO_SIZE]; + void *rcvr_fifo; + void *xmit_fifo; - pc_timer_t transmit_timer, timeout_timer; - double clock_src, transmit_period; + pc_timer_t transmit_timer; + pc_timer_t timeout_timer; + pc_timer_t receive_timer; + double clock_src; + double transmit_period; - struct serial_device_s *sd; + struct serial_device_s *sd; } serial_t; -typedef struct serial_device_s -{ - void (*rcr_callback)(struct serial_s *serial, void *p); - void (*dev_write)(struct serial_s *serial, void *p, uint8_t data); - void *priv; +typedef struct serial_device_s { + void (*rcr_callback)(struct serial_s *serial, void *priv); + void (*dev_write)(struct serial_s *serial, void *priv, uint8_t data); + void (*lcr_callback)(struct serial_s *serial, void *priv, uint8_t lcr); + void (*transmit_period_callback)(struct serial_s *serial, void *priv, double transmit_period); + void *priv; serial_t *serial; } serial_device_t; +typedef struct serial_port_s { + uint8_t enabled; +} serial_port_t; -extern serial_t * serial_attach(int port, - void (*rcr_callback)(struct serial_s *serial, void *p), - void (*dev_write)(struct serial_s *serial, void *p, uint8_t data), - void *priv); -extern void serial_remove(serial_t *dev); -extern void serial_set_type(serial_t *dev, int type); -extern void serial_setup(serial_t *dev, uint16_t addr, uint8_t irq); -extern void serial_clear_fifo(serial_t *dev); -extern void serial_write_fifo(serial_t *dev, uint8_t dat); -extern void serial_set_next_inst(int ni); -extern void serial_standalone_init(void); -extern void serial_set_clock_src(serial_t *dev, double clock_src); -extern void serial_reset_port(serial_t *dev); +extern serial_port_t com_ports[SERIAL_MAX]; -extern const device_t ns8250_device; -extern const device_t ns8250_pcjr_device; -extern const device_t ns16450_device; -extern const device_t ns16550_device; -extern const device_t ns16650_device; -extern const device_t ns16750_device; -extern const device_t ns16850_device; -extern const device_t ns16950_device; +extern serial_t *serial_attach_ex(int port, + void (*rcr_callback)(struct serial_s *serial, void *priv), + void (*dev_write)(struct serial_s *serial, void *priv, uint8_t data), + void (*transmit_period_callback)(struct serial_s *serial, void *priv, double transmit_period), + void (*lcr_callback)(struct serial_s *serial, void *priv, uint8_t data_bits), + void *priv); +#define serial_attach(port, rcr_callback, dev_write, priv) \ + serial_attach_ex(port, rcr_callback, dev_write, NULL, NULL, priv); -#endif /*EMU_SERIAL_H*/ +extern void serial_remove(serial_t *dev); +extern void serial_set_type(serial_t *dev, int type); +extern void serial_setup(serial_t *dev, uint16_t addr, uint8_t irq); +extern void serial_clear_fifo(serial_t *dev); +extern void serial_write_fifo(serial_t *dev, uint8_t dat); +extern void serial_set_next_inst(int ni); +extern void serial_standalone_init(void); +extern void serial_set_clock_src(serial_t *dev, double clock_src); +extern void serial_reset_port(serial_t *dev); +extern void serial_device_timeout(void *priv); + +extern void serial_set_cts(serial_t *dev, uint8_t enabled); +extern void serial_set_dsr(serial_t *dev, uint8_t enabled); +extern void serial_set_dcd(serial_t *dev, uint8_t enabled); + +extern const device_t ns8250_device; +extern const device_t ns8250_pcjr_device; +extern const device_t ns16450_device; +extern const device_t ns16550_device; +extern const device_t ns16650_device; +extern const device_t ns16750_device; +extern const device_t ns16850_device; +extern const device_t ns16950_device; + +#endif /*EMU_SERIAL_H*/ diff --git a/src/include/86box/serial_passthrough.h b/src/include/86box/serial_passthrough.h new file mode 100644 index 000000000..7ca6479d6 --- /dev/null +++ b/src/include/86box/serial_passthrough.h @@ -0,0 +1,63 @@ +/* + * 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. + * + * Definition of Serial passthrough device. + * + * + * Authors: Andreas J. Reichel , + * Jasmine Iwanek + * + * Copyright 2021 Andreas J. Reichel. + * Copyright 2021-2022 Jasmine Iwanek. + */ + +#ifndef SERIAL_PASSTHROUGH_H +#define SERIAL_PASSTHROUGH_H + +#include +#include + +#include <86box/86box.h> +#include <86box/device.h> +#include <86box/timer.h> +#include <86box/serial.h> + +enum serial_passthrough_mode { + SERPT_MODE_VCON, /*Named Pipe (Server) / Pseudo Terminal/Virtual Console */ + SERPT_MODE_TCPSRV, /* TCP Server (TODO) */ + SERPT_MODE_TCPCLNT, /* TCP Client (TODO) */ + SERPT_MODE_HOSTSER, /* Host Serial Passthrough */ + SERPT_MODES_MAX, +}; + +extern const char *serpt_mode_names[SERPT_MODES_MAX]; + +typedef struct serial_passthrough_s { + enum serial_passthrough_mode mode; + pc_timer_t host_to_serial_timer; + pc_timer_t serial_to_host_timer; + serial_t *serial; + double baudrate; + uint8_t bits; + uint8_t data_bits; + uint8_t port; + uint8_t data; + char slave_pt[32]; /* used for pseudo term name of slave side */ + intptr_t master_fd; /* file desc for master pseudo terminal or + * socket or alike */ + char host_serial_path[1024]; /* Path to TTY/host serial port on the host */ + char named_pipe[1024]; /* (Windows only) Name of the pipe. */ + void *backend_priv; /* Private platform backend data */ +} serial_passthrough_t; + +extern bool serial_passthrough_enabled[SERIAL_MAX]; +extern const device_t serial_passthrough_device; + +extern void serial_passthrough_init(void); + +#endif diff --git a/src/include/86box/sio.h b/src/include/86box/sio.h index 667f39276..2736a4eb5 100644 --- a/src/include/86box/sio.h +++ b/src/include/86box/sio.h @@ -1,87 +1,90 @@ /* - * 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. + * 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. + * This file is part of the 86Box distribution. * - * Definitions for the Super I/O chips. + * Definitions for the Super I/O chips. * - * Author: Fred N. van Kempen, - * Copyright 2017-2020 Fred N. van Kempen. + * Authors: Fred N. van Kempen, + * + * Copyright 2017-2020 Fred N. van Kempen. */ + #ifndef EMU_SIO_H -# define EMU_SIO_H +#define EMU_SIO_H +extern void vt82c686_sio_write(uint8_t addr, uint8_t val, void *priv); -extern void vt82c686_sio_write(uint8_t addr, uint8_t val, void *priv); - - -extern const device_t acc3221_device; -extern const device_t f82c710_device; -extern const device_t f82c606_device; -extern const device_t fdc37c651_device; -extern const device_t fdc37c651_ide_device; -extern const device_t fdc37c661_device; -extern const device_t fdc37c663_device; -extern const device_t fdc37c663_ide_device; -extern const device_t fdc37c665_device; -extern const device_t fdc37c665_ide_device; -extern const device_t fdc37c666_device; -extern const device_t fdc37c67x_device; -extern const device_t fdc37c669_device; -extern const device_t fdc37c669_370_device; -extern const device_t fdc37c931apm_device; -extern const device_t fdc37c931apm_compaq_device; -extern const device_t fdc37c932fr_device; -extern const device_t fdc37c932qf_device; -extern const device_t fdc37c935_device; -extern const device_t fdc37m60x_device; -extern const device_t fdc37m60x_370_device; -extern const device_t it8661f_device; -extern const device_t i82091aa_device; -extern const device_t i82091aa_398_device; -extern const device_t i82091aa_ide_device; -extern const device_t pc87306_device; -extern const device_t pc87307_device; -extern const device_t pc87307_15c_device; -extern const device_t pc87307_both_device; -extern const device_t pc87309_device; -extern const device_t pc87309_15c_device; -extern const device_t pc87310_device; -extern const device_t pc87310_ide_device; -extern const device_t pc87311_device; -extern const device_t pc87311_ide_device; -extern const device_t pc87332_device; -extern const device_t pc87332_398_device; -extern const device_t pc87332_398_ide_device; -extern const device_t pc87332_398_ide_sec_device; -extern const device_t pc87332_398_ide_fdcon_device; -extern const device_t pc97307_device; -extern const device_t prime3b_device; -extern const device_t prime3b_ide_device; -extern const device_t prime3c_device; -extern const device_t prime3c_ide_device; -extern const device_t ps1_m2133_sio; +extern const device_t acc3221_device; +extern const device_t ali5123_device; +extern const device_t f82c710_device; +extern const device_t f82c606_device; +extern const device_t fdc37c651_device; +extern const device_t fdc37c651_ide_device; +extern const device_t fdc37c661_device; +extern const device_t fdc37c663_device; +extern const device_t fdc37c663_ide_device; +extern const device_t fdc37c665_device; +extern const device_t fdc37c665_ide_device; +extern const device_t fdc37c665_ide_pri_device; +extern const device_t fdc37c666_device; +extern const device_t fdc37c67x_device; +extern const device_t fdc37c669_device; +extern const device_t fdc37c669_370_device; +extern const device_t fdc37c931apm_device; +extern const device_t fdc37c931apm_compaq_device; +extern const device_t fdc37c932fr_device; +extern const device_t fdc37c932qf_device; +extern const device_t fdc37c935_device; +extern const device_t fdc37m60x_device; +extern const device_t fdc37m60x_370_device; +extern const device_t it8661f_device; +extern const device_t i82091aa_device; +extern const device_t i82091aa_398_device; +extern const device_t i82091aa_ide_pri_device; +extern const device_t i82091aa_ide_device; +extern const device_t pc87306_device; +extern const device_t pc87307_device; +extern const device_t pc87307_15c_device; +extern const device_t pc87307_both_device; +extern const device_t pc87309_device; +extern const device_t pc87309_15c_device; +extern const device_t pc87310_device; +extern const device_t pc87310_ide_device; +extern const device_t pc87311_device; +extern const device_t pc87311_ide_device; +extern const device_t pc87332_device; +extern const device_t pc87332_398_device; +extern const device_t pc87332_398_ide_device; +extern const device_t pc87332_398_ide_sec_device; +extern const device_t pc87332_398_ide_fdcon_device; +extern const device_t pc97307_device; +extern const device_t prime3b_device; +extern const device_t prime3b_ide_device; +extern const device_t prime3c_device; +extern const device_t prime3c_ide_device; +extern const device_t ps1_m2133_sio; #if defined(DEV_BRANCH) && defined(USE_SIO_DETECT) -extern const device_t sio_detect_device; +extern const device_t sio_detect_device; #endif -extern const device_t um8669f_device; -extern const device_t via_vt82c686_sio_device; -extern const device_t w83787f_device; -extern const device_t w83787f_ide_device; -extern const device_t w83787f_ide_en_device; -extern const device_t w83787f_ide_sec_device; -extern const device_t w83877f_device; -extern const device_t w83877f_president_device; -extern const device_t w83877tf_device; -extern const device_t w83877tf_acorp_device; -extern const device_t w83977f_device; -extern const device_t w83977f_370_device; -extern const device_t w83977tf_device; -extern const device_t w83977ef_device; -extern const device_t w83977ef_370_device; +extern const device_t um8669f_device; +extern const device_t via_vt82c686_sio_device; +extern const device_t w83787f_88h_device; +extern const device_t w83787f_device; +extern const device_t w83787f_ide_device; +extern const device_t w83787f_ide_en_device; +extern const device_t w83787f_ide_sec_device; +extern const device_t w83877f_device; +extern const device_t w83877f_president_device; +extern const device_t w83877tf_device; +extern const device_t w83877tf_acorp_device; +extern const device_t w83977f_device; +extern const device_t w83977f_370_device; +extern const device_t w83977tf_device; +extern const device_t w83977ef_device; +extern const device_t w83977ef_370_device; - -#endif /*EMU_SIO_H*/ +#endif /*EMU_SIO_H*/ diff --git a/src/include/86box/smbus.h b/src/include/86box/smbus.h index 6661a25c6..340d1d00e 100644 --- a/src/include/86box/smbus.h +++ b/src/include/86box/smbus.h @@ -1,63 +1,72 @@ /* - * 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. + * 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. + * This file is part of the 86Box distribution. * - * Definitions for the SMBus host controllers. + * Definitions for the SMBus host controllers. * * * - * Authors: RichardG, + * Authors: RichardG, * - * Copyright 2020 RichardG. + * Copyright 2020 RichardG. */ + #ifndef EMU_SMBUS_PIIX4_H -# define EMU_SMBUS_PIIX4_H +#define EMU_SMBUS_PIIX4_H +#define SMBUS_PIIX4_BLOCK_DATA_SIZE 32 +#define SMBUS_PIIX4_BLOCK_DATA_MASK (SMBUS_PIIX4_BLOCK_DATA_SIZE - 1) -#define SMBUS_PIIX4_BLOCK_DATA_SIZE 32 -#define SMBUS_PIIX4_BLOCK_DATA_MASK (SMBUS_PIIX4_BLOCK_DATA_SIZE - 1) - -#define SMBUS_ALI7101_BLOCK_DATA_SIZE 32 -#define SMBUS_ALI7101_BLOCK_DATA_MASK (SMBUS_ALI7101_BLOCK_DATA_SIZE - 1) - +#define SMBUS_ALI7101_BLOCK_DATA_SIZE 32 +#define SMBUS_ALI7101_BLOCK_DATA_MASK (SMBUS_ALI7101_BLOCK_DATA_SIZE - 1) enum { SMBUS_PIIX4 = 0, - SMBUS_VIA + SMBUS_VIA = 1 }; -typedef struct { - uint32_t local; - uint16_t io_base; - int clock; - double bit_period; - uint8_t stat, next_stat, ctl, cmd, addr, - data0, data1, - index, data[SMBUS_PIIX4_BLOCK_DATA_SIZE]; - pc_timer_t response_timer; - void *i2c; +typedef struct smbus_piix4_t { + uint32_t local; + uint16_t io_base; + int clock; + double bit_period; + uint8_t stat; + uint8_t next_stat; + uint8_t ctl; + uint8_t cmd; + uint8_t addr; + uint8_t data0; + uint8_t data1; + uint8_t index; + uint8_t data[SMBUS_PIIX4_BLOCK_DATA_SIZE]; + pc_timer_t response_timer; + void *i2c; } smbus_piix4_t; -typedef struct { - uint32_t local; - uint16_t io_base; - uint8_t stat, next_stat, ctl, cmd, addr, - data0, data1, - index, data[SMBUS_ALI7101_BLOCK_DATA_SIZE]; - pc_timer_t response_timer; - void *i2c; +typedef struct smbus_ali7101_t { + uint32_t local; + uint16_t io_base; + uint8_t stat; + uint8_t next_stat; + uint8_t ctl; + uint8_t cmd; + uint8_t addr; + uint8_t data0; + uint8_t data1; + uint8_t index; + uint8_t data[SMBUS_ALI7101_BLOCK_DATA_SIZE]; + pc_timer_t response_timer; + void *i2c; } smbus_ali7101_t; +extern void smbus_piix4_remap(smbus_piix4_t *dev, uint16_t new_io_base, uint8_t enable); +extern void smbus_piix4_setclock(smbus_piix4_t *dev, int clock); -extern void smbus_piix4_remap(smbus_piix4_t *dev, uint16_t new_io_base, uint8_t enable); -extern void smbus_piix4_setclock(smbus_piix4_t *dev, int clock); - -extern void smbus_ali7101_remap(smbus_ali7101_t *dev, uint16_t new_io_base, uint8_t enable); - +extern void smbus_ali7101_remap(smbus_ali7101_t *dev, uint16_t new_io_base, uint8_t enable); #ifdef EMU_DEVICE_H extern const device_t piix4_smbus_device; @@ -66,5 +75,4 @@ extern const device_t via_smbus_device; extern const device_t ali7101_smbus_device; #endif - -#endif /*EMU_SMBUS_PIIX4_H*/ +#endif /*EMU_SMBUS_PIIX4_H*/ diff --git a/src/include/86box/smbus_piix4.h b/src/include/86box/smbus_piix4.h deleted file mode 100644 index cf55dd210..000000000 --- a/src/include/86box/smbus_piix4.h +++ /dev/null @@ -1,53 +0,0 @@ -/* - * 86Box A hypervisor and IBM PC system emulator that specializes in - * running old operating systems and software designed for IBM - * PC systems and compatibles from 1981 through fairly recent - * system designs based on the PCI bus. - * - * This file is part of the 86Box distribution. - * - * Definitions for the generic PIIX4-compatible SMBus host controller. - * - * - * - * Authors: RichardG, - * - * Copyright 2020 RichardG. - */ -#ifndef EMU_SMBUS_PIIX4_H -# define EMU_SMBUS_PIIX4_H - - -#define SMBUS_PIIX4_BLOCK_DATA_SIZE 32 -#define SMBUS_PIIX4_BLOCK_DATA_MASK (SMBUS_PIIX4_BLOCK_DATA_SIZE - 1) - - -enum { - SMBUS_PIIX4 = 0, - SMBUS_VIA -}; - -typedef struct { - uint32_t local; - uint16_t io_base; - int clock; - double bit_period; - uint8_t stat, next_stat, ctl, cmd, addr, - data0, data1, - index, data[SMBUS_PIIX4_BLOCK_DATA_SIZE]; - pc_timer_t response_timer; - void *i2c; -} smbus_piix4_t; - - -extern void smbus_piix4_remap(smbus_piix4_t *dev, uint16_t new_io_base, uint8_t enable); -extern void smbus_piix4_setclock(smbus_piix4_t *dev, int clock); - - -#ifdef EMU_DEVICE_H -extern const device_t piix4_smbus_device; -extern const device_t via_smbus_device; -#endif - - -#endif /*EMU_SMBUS_PIIX4_H*/ diff --git a/src/include/86box/smram.h b/src/include/86box/smram.h index 996e5df30..707c967f5 100644 --- a/src/include/86box/smram.h +++ b/src/include/86box/smram.h @@ -1,66 +1,66 @@ /* - * 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. + * 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. + * This file is part of the 86Box distribution. * - * Definitions for the SMRAM interface. + * Definitions for the SMRAM interface. * * * - * Authors: Miran Grca, + * Authors: Miran Grca, * - * Copyright 2016-2020 Miran Grca. + * Copyright 2016-2020 Miran Grca. */ + #ifndef EMU_SMRAM_H -# define EMU_SMRAM_H +#define EMU_SMRAM_H +typedef struct _smram_ { + struct _smram_ *prev; + struct _smram_ *next; -typedef struct _smram_ -{ - struct _smram_ *prev, *next; + mem_mapping_t mapping; - mem_mapping_t mapping; - - uint32_t host_base, ram_base, - size, - old_host_base, old_size; + uint32_t host_base; + uint32_t ram_base; + uint32_t size; + uint32_t old_host_base; + uint32_t old_size; } smram_t; - /* Make a backup copy of host_base and size of all the SMRAM structs, needed so that if the SMRAM mappings change while in SMM, they will be recalculated on return. */ -extern void smram_backup_all(void); +extern void smram_backup_all(void); /* Recalculate any mappings, including the backup if returning from SMM. */ -extern void smram_recalc_all(int ret); +extern void smram_recalc_all(int ret); /* Delete a SMRAM mapping. */ -extern void smram_del(smram_t *smr); +extern void smram_del(smram_t *smr); /* Add a SMRAM mapping. */ extern smram_t *smram_add(void); /* Set memory state in the specified model (normal or SMM) according to the specified flags, separately for bus and CPU. */ -extern void smram_map_ex(int bus, int smm, uint32_t addr, uint32_t size, int is_smram); +extern void smram_map_ex(int bus, int smm, uint32_t addr, uint32_t size, int is_smram); /* Set memory state in the specified model (normal or SMM) according to the specified flags. */ -extern void smram_map(int smm, uint32_t addr, uint32_t size, int is_smram); +extern void smram_map(int smm, uint32_t addr, uint32_t size, int is_smram); /* Disable a specific SMRAM mapping. */ -extern void smram_disable(smram_t *smr); +extern void smram_disable(smram_t *smr); /* Disable all SMRAM mappings. */ -extern void smram_disable_all(void); +extern void smram_disable_all(void); /* Enable SMRAM mappings according to flags for both normal and SMM modes, separately for bus and CPU. */ extern void smram_enable_ex(smram_t *smr, uint32_t host_base, uint32_t ram_base, uint32_t size, - int flags_normal, int flags_normal_bus, int flags_smm, int flags_smm_bus); + int flags_normal, int flags_normal_bus, int flags_smm, int flags_smm_bus); /* Enable SMRAM mappings according to flags for both normal and SMM modes. */ -extern void smram_enable(smram_t *smr, uint32_t host_base, uint32_t ram_base, uint32_t size, - int flags_normal, int flags_smm); +extern void smram_enable(smram_t *smr, uint32_t host_base, uint32_t ram_base, uint32_t size, + int flags_normal, int flags_smm); /* Checks if a SMRAM mapping is enabled or not. */ -extern int smram_enabled(smram_t *smr); +extern int smram_enabled(smram_t *smr); /* Changes the SMRAM state. */ -extern void smram_state_change(smram_t *smr, int smm, int flags); +extern void smram_state_change(smram_t *smr, int smm, int flags); /* Enables or disables the use of a separate SMRAM for addresses below A0000. */ -extern void smram_set_separate_smram(uint8_t set); +extern void smram_set_separate_smram(uint8_t set); - -#endif /*EMU_SMRAM_H*/ +#endif /*EMU_SMRAM_H*/ diff --git a/src/include/86box/snd_ac97.h b/src/include/86box/snd_ac97.h index 0690cb52b..45a921863 100644 --- a/src/include/86box/snd_ac97.h +++ b/src/include/86box/snd_ac97.h @@ -1,157 +1,158 @@ /* - * 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. + * 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. + * This file is part of the 86Box distribution. * - * Definitions for AC'97 audio emulation. + * Definitions for AC'97 audio emulation. * * * - * Authors: RichardG, + * Authors: RichardG, * - * Copyright 2021 RichardG. + * Copyright 2021 RichardG. */ -#ifndef EMU_SND_AC97_H -# define EMU_SND_AC97_H +#ifndef SOUND_AC97_H +#define SOUND_AC97_H - -#define AC97_VENDOR_ID(f, s, t, dev) ((((f) & 0xff) << 24) | (((s) & 0xff) << 16) | (((t) & 0xff) << 8) | ((dev) & 0xff)) +#define AC97_VENDOR_ID(a, b, c, i) ((((a) &0xff) << 24) | (((b) &0xff) << 16) | (((c) &0xff) << 8) | ((i) &0xff)) /* Misc support bits (misc_flags). Most of these are not part of any registers, but control enabling/disabling of registers and bits. */ -#define AC97_MASTER_6B (1 << 0) /* register 02 bits [13,5] (ML5/MR5) */ -#define AC97_AUXOUT (1 << 1) /* register 04 */ -#define AC97_AUXOUT_6B (1 << 2) /* register 04 bits [13,5] (ML5/MR5) */ -#define AC97_MONOOUT (1 << 3) /* register 06 */ -#define AC97_MONOOUT_6B (1 << 4) /* register 06 bit 5 (MM5) */ -#define AC97_PCBEEP (1 << 5) /* register 0A */ -#define AC97_PCBEEP_GEN (1 << 6) /* register 0A bits [12:5] (F[7:0]) */ -#define AC97_PHONE (1 << 9) /* register 0C */ -#define AC97_VIDEO (1 << 10) /* register 14 */ -#define AC97_AUXIN (1 << 11) /* register 16 */ -#define AC97_POP (1 << 15) /* register 20 bit 15 (POP) - definition shared with General Purpose bits */ -#define AC97_MS (1 << 8) /* register 20 bit 8 (MS) - definition shared with General Purpose bits */ -#define AC97_LPBK (1 << 7) /* register 20 bit 7 (LPBK) - definition shared with General Purpose bits */ -#define AC97_DSA (1 << 12) /* register 28 bits [5:4] (DSA[1:0]) */ -#define AC97_LFE_6B (1 << 13) /* register 36 bit 13 (LFE5) */ -#define AC97_CENTER_6B (1 << 14) /* register 36 bit 5 (CNT5) */ -#define AC97_SURR_6B (1 << 16) /* register 38 bits [13,5] (LSR5/RSR5) */ +#define AC97_MASTER_6B (1 << 0) /* register 02 bits [13,5] (ML5/MR5) */ +#define AC97_AUXOUT (1 << 1) /* register 04 */ +#define AC97_AUXOUT_6B (1 << 2) /* register 04 bits [13,5] (ML5/MR5) */ +#define AC97_MONOOUT (1 << 3) /* register 06 */ +#define AC97_MONOOUT_6B (1 << 4) /* register 06 bit 5 (MM5) */ +#define AC97_PCBEEP (1 << 5) /* register 0A */ +#define AC97_PCBEEP_GEN (1 << 6) /* register 0A bits [12:5] (F[7:0]) */ +#define AC97_PHONE (1 << 9) /* register 0C */ +#define AC97_VIDEO (1 << 10) /* register 14 */ +#define AC97_AUXIN (1 << 11) /* register 16 */ +#define AC97_POP (1 << 15) /* register 20 bit 15 (POP) - definition shared with General Purpose bits */ +#define AC97_MS (1 << 8) /* register 20 bit 8 (MS) - definition shared with General Purpose bits */ +#define AC97_LPBK (1 << 7) /* register 20 bit 7 (LPBK) - definition shared with General Purpose bits */ +#define AC97_DSA (1 << 12) /* register 28 bits [5:4] (DSA[1:0]) */ +#define AC97_LFE_6B (1 << 13) /* register 36 bit 13 (LFE5) */ +#define AC97_CENTER_6B (1 << 14) /* register 36 bit 5 (CNT5) */ +#define AC97_SURR_6B (1 << 16) /* register 38 bits [13,5] (LSR5/RSR5) */ /* Reset bits (reset_flags), register 00. */ -#define AC97_MICPCM (1 << 0) -#define AC97_MODEMLINE (1 << 1) -#define AC97_TONECTL (1 << 2) -#define AC97_SIMSTEREO (1 << 3) -#define AC97_HPOUT (1 << 4) -#define AC97_LOUDNESS (1 << 5) -#define AC97_DAC_18B (1 << 6) -#define AC97_DAC_20B (1 << 7) -#define AC97_ADC_18B (1 << 8) -#define AC97_ADC_20B (1 << 9) -#define AC97_3D_SHIFT 10 +#define AC97_MICPCM (1 << 0) +#define AC97_MODEMLINE (1 << 1) +#define AC97_TONECTL (1 << 2) +#define AC97_SIMSTEREO (1 << 3) +#define AC97_HPOUT (1 << 4) +#define AC97_LOUDNESS (1 << 5) +#define AC97_DAC_18B (1 << 6) +#define AC97_DAC_20B (1 << 7) +#define AC97_ADC_18B (1 << 8) +#define AC97_ADC_20B (1 << 9) +#define AC97_3D_SHIFT 10 /* Extended Audio ID bits (extid_flags), register 28. */ -#define AC97_VRA (1 << 0) -#define AC97_DRA (1 << 1) -#define AC97_SPDIF (1 << 2) -#define AC97_VRM (1 << 3) -#define AC97_CDAC (1 << 6) -#define AC97_SDAC (1 << 7) -#define AC97_LDAC (1 << 8) -#define AC97_AMAP (1 << 9) -#define AC97_REV_2_1 (0 << 10) -#define AC97_REV_2_2 (1 << 10) -#define AC97_REV_2_3 (2 << 10) -#define AC97_REV_MASK (3 << 10) +#define AC97_VRA (1 << 0) +#define AC97_DRA (1 << 1) +#define AC97_SPDIF (1 << 2) +#define AC97_VRM (1 << 3) +#define AC97_CDAC (1 << 6) +#define AC97_SDAC (1 << 7) +#define AC97_LDAC (1 << 8) +#define AC97_AMAP (1 << 9) +#define AC97_REV_2_1 (0 << 10) +#define AC97_REV_2_2 (1 << 10) +#define AC97_REV_2_3 (2 << 10) +#define AC97_REV_MASK (3 << 10) /* Volume bits. */ -#define AC97_MUTE (1 << 15) -#define AC97_MUTE_L (1 << 15) -#define AC97_MUTE_R (1 << 7) +#define AC97_MUTE (1 << 15) +#define AC97_MUTE_L (1 << 15) +#define AC97_MUTE_R (1 << 7) /* General Purpose bits, register 20. */ /* POP already defined */ -#define AC97_ST (1 << 14) -#define AC97_3D (1 << 13) -#define AC97_LD (1 << 12) -#define AC97_DRSS_MASK (3 << 10) -#define AC97_MIX (1 << 9) +#define AC97_ST (1 << 14) +#define AC97_3D (1 << 13) +#define AC97_LD (1 << 12) +#define AC97_DRSS_MASK (3 << 10) +#define AC97_MIX (1 << 9) /* MS already defined */ /* LPBK already defined */ /* Extended Audio Status/Control bits, register 2A. */ -#define AC97_SPSA_SHIFT 4 -#define AC97_SPSA_MASK 3 -#define AC97_MADC (1 << 9) -#define AC97_SPCV (1 << 10) -#define AC97_PRI (1 << 11) -#define AC97_PRJ (1 << 12) -#define AC97_PRK (1 << 13) -#define AC97_PRL (1 << 14) +#define AC97_SPSA_SHIFT 4 +#define AC97_SPSA_MASK 3 +#define AC97_MADC (1 << 9) +#define AC97_SPCV (1 << 10) +#define AC97_PRI (1 << 11) +#define AC97_PRJ (1 << 12) +#define AC97_PRK (1 << 13) +#define AC97_PRL (1 << 14) +/* Codec IDs. */ +#define AC97_CODEC_AD1881 AC97_VENDOR_ID('A', 'D', 'S', 0x40) +#define AC97_CODEC_AK4540 AC97_VENDOR_ID('A', 'D', 'S', 0x40) +#define AC97_CODEC_ALC100 AC97_VENDOR_ID('A', 'L', 'C', 0x20) +#define AC97_CODEC_CS4297 AC97_VENDOR_ID('C', 'R', 'Y', 0x03) +#define AC97_CODEC_CS4297A AC97_VENDOR_ID('C', 'R', 'Y', 0x11) +#define AC97_CODEC_STAC9708 AC97_VENDOR_ID(0x83, 0x84, 0x76, 0x08) +#define AC97_CODEC_STAC9721 AC97_VENDOR_ID(0x83, 0x84, 0x76, 0x09) +#define AC97_CODEC_TR28023 AC97_VENDOR_ID('T', 'R', 'A', 0x03) +#define AC97_CODEC_WM9701A AC97_VENDOR_ID('W', 'M', 'L', 0x00) -/* New codecs should be added to the end of this enum to avoid breaking configs. */ -enum { - AC97_CODEC_AD1881 = 0, - AC97_CODEC_ALC100, - AC97_CODEC_CS4297, - AC97_CODEC_CS4297A, - AC97_CODEC_WM9701A, - AC97_CODEC_STAC9708, - AC97_CODEC_STAC9721, - AC97_CODEC_AK4540 -}; - - -typedef struct { - const uint16_t index, value, write_mask; +typedef struct ac97_vendor_reg_t { + uint8_t page; /* for paged registers [60:6F], 0 otherwise */ + uint8_t index; + uint16_t value; + uint16_t write_mask; } ac97_vendor_reg_t; -typedef struct { - uint32_t vendor_id, min_rate, max_rate, misc_flags; - uint16_t reset_flags, extid_flags, - powerdown_mask, regs[64]; - uint8_t codec_id, vendor_reg_page_max; +typedef struct ac97_codec_t { + int model; + uint16_t regs[64]; + uint8_t codec_id; + uint8_t vendor_reg_page_max; const ac97_vendor_reg_t *vendor_regs; - uint16_t *vendor_reg_pages; + uint16_t *vendor_reg_pages; } ac97_codec_t; +extern uint16_t ac97_codec_readw(ac97_codec_t *dev, uint8_t reg); +extern void ac97_codec_writew(ac97_codec_t *dev, uint8_t reg, uint16_t val); +extern void ac97_codec_reset(void *priv); +extern void ac97_codec_getattn(void *priv, uint8_t reg, int *l, int *r); +extern uint32_t ac97_codec_getrate(void *priv, uint8_t reg); +extern const device_t *ac97_codec_get(uint32_t id); -extern uint16_t ac97_codec_readw(ac97_codec_t *dev, uint8_t reg); -extern void ac97_codec_writew(ac97_codec_t *dev, uint8_t reg, uint16_t val); -extern void ac97_codec_reset(void *priv); -extern void ac97_codec_getattn(void *priv, uint8_t reg, int *l, int *r); -extern uint32_t ac97_codec_getrate(void *priv, uint8_t reg); -extern const device_t *ac97_codec_get(int model); +extern void ac97_via_set_slot(void *priv, int slot, int irq_pin); +extern uint8_t ac97_via_read_status(void *priv, uint8_t modem); +extern void ac97_via_write_control(void *priv, uint8_t modem, uint8_t val); +extern void ac97_via_remap_audio_sgd(void *priv, uint16_t new_io_base, uint8_t enable); +extern void ac97_via_remap_modem_sgd(void *priv, uint16_t new_io_base, uint8_t enable); +extern void ac97_via_remap_audio_codec(void *priv, uint16_t new_io_base, uint8_t enable); +extern void ac97_via_remap_modem_codec(void *priv, uint16_t new_io_base, uint8_t enable); -extern void ac97_via_set_slot(void *priv, int slot, int irq_pin); -extern uint8_t ac97_via_read_status(void *priv, uint8_t modem); -extern void ac97_via_write_control(void *priv, uint8_t modem, uint8_t val); -extern void ac97_via_remap_audio_sgd(void *priv, uint16_t new_io_base, uint8_t enable); -extern void ac97_via_remap_modem_sgd(void *priv, uint16_t new_io_base, uint8_t enable); -extern void ac97_via_remap_audio_codec(void *priv, uint16_t new_io_base, uint8_t enable); -extern void ac97_via_remap_modem_codec(void *priv, uint16_t new_io_base, uint8_t enable); - - -extern ac97_codec_t **ac97_codec, **ac97_modem_codec; -extern int ac97_codec_count, ac97_modem_codec_count, - ac97_codec_id, ac97_modem_codec_id; +extern ac97_codec_t **ac97_codec; +extern ac97_codec_t **ac97_modem_codec; +extern int ac97_codec_count; +extern int ac97_modem_codec_count; +extern int ac97_codec_id; +extern int ac97_modem_codec_id; #ifdef EMU_DEVICE_H -extern const device_t ad1881_device; -extern const device_t ak4540_device; -extern const device_t alc100_device; -extern const device_t cs4297_device; -extern const device_t cs4297a_device; -extern const device_t stac9708_device; -extern const device_t stac9721_device; -extern const device_t wm9701a_device; +extern const device_t ad1881_device; +extern const device_t ak4540_device; +extern const device_t alc100_device; +extern const device_t cs4297_device; +extern const device_t cs4297a_device; +# define ct1297_device tr28023_device +extern const device_t stac9708_device; +extern const device_t stac9721_device; +extern const device_t tr28023_device; +extern const device_t wm9701a_device; -extern const device_t ac97_via_device; +extern const device_t ac97_via_device; #endif - -#endif +#endif /*SOUND_AC97_H*/ diff --git a/src/include/86box/snd_ad1848.h b/src/include/86box/snd_ad1848.h index 3e61deea7..6bdd2bf40 100644 --- a/src/include/86box/snd_ad1848.h +++ b/src/include/86box/snd_ad1848.h @@ -1,63 +1,89 @@ /* - * 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. + * 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. + * This file is part of the 86Box distribution. * - * Definitions for AD1848 / CS4248 / CS4231 (Windows Sound System) codec emulation. + * Definitions for AD1848 / CS4248 / CS4231 (Windows Sound System) codec emulation. * * * - * Authors: Sarah Walker, - * TheCollector1995, - * RichardG, + * Authors: Sarah Walker, + * TheCollector1995, + * RichardG, * - * Copyright 2008-2020 Sarah Walker. - * Copyright 2018-2020 TheCollector1995. - * Copyright 2021 RichardG. + * Copyright 2008-2020 Sarah Walker. + * Copyright 2018-2020 TheCollector1995. + * Copyright 2021 RichardG. */ +#ifndef SOUND_AD1848_H +#define SOUND_AD1848_H + enum { AD1848_TYPE_DEFAULT = 0, - AD1848_TYPE_CS4248, - AD1848_TYPE_CS4231, - AD1848_TYPE_CS4236 + AD1848_TYPE_CS4248 = 1, + AD1848_TYPE_CS4231 = 2, + AD1848_TYPE_CS4235 = 3, + AD1848_TYPE_CS4236 = 4 }; +typedef struct ad1848_t { + uint8_t type; + uint8_t index; + uint8_t xindex; + uint8_t regs[32]; + uint8_t xregs[32]; + uint8_t status; /* 16 original registers + 16 CS4231A extensions + 32 CS4236 extensions */ -typedef struct { - uint8_t type, index, xindex, regs[32], xregs[32], status; /* 16 original registers + 16 CS4231A extensions + 32 CS4236 extensions */ + int count; + uint8_t trd; + uint8_t mce; + uint8_t wten : 1; - int count; - uint8_t trd, mce, wten: 1; - - int16_t out_l, out_r; - double cd_vol_l, cd_vol_r; - int fm_vol_l, fm_vol_r; - uint8_t fmt_mask, wave_vol_mask; + int16_t out_l; + int16_t out_r; + double cd_vol_l; + double cd_vol_r; + int fm_vol_l; + int fm_vol_r; + uint8_t fmt_mask; + uint8_t wave_vol_mask; - uint8_t enable: 1, irq: 4, dma: 3; - int freq; + uint8_t enable : 1; + uint8_t irq : 4; + uint8_t dma : 3; + uint8_t adpcm_ref; + int8_t adpcm_step; + int freq; + int adpcm_data; + int adpcm_pos; - pc_timer_t timer_count; - uint64_t timer_latch; + pc_timer_t timer_count; + uint64_t timer_latch; - int16_t buffer[SOUNDBUFLEN * 2]; - int pos; + int16_t buffer[SOUNDBUFLEN * 2]; + int pos; + + void *cram_priv; + void (*cram_write)(uint16_t addr, uint8_t val, void *priv); + uint8_t (*cram_read)(uint16_t addr, void *priv); } ad1848_t; +extern void ad1848_setirq(ad1848_t *ad1848, int irq); +extern void ad1848_setdma(ad1848_t *ad1848, int dma); +extern void ad1848_updatevolmask(ad1848_t *ad1848); -extern void ad1848_setirq(ad1848_t *ad1848, int irq); -extern void ad1848_setdma(ad1848_t *ad1848, int dma); -extern void ad1848_updatevolmask(ad1848_t *ad1848); +extern uint8_t ad1848_read(uint16_t addr, void *priv); +extern void ad1848_write(uint16_t addr, uint8_t val, void *priv); -extern uint8_t ad1848_read(uint16_t addr, void *priv); -extern void ad1848_write(uint16_t addr, uint8_t val, void *priv); +extern void ad1848_update(ad1848_t *ad1848); +extern void ad1848_speed_changed(ad1848_t *ad1848); +extern void ad1848_filter_cd_audio(int channel, double *buffer, void *priv); +extern void ad1848_filter_aux2(void* priv, double* out_l, double* out_r); -extern void ad1848_update(ad1848_t *ad1848); -extern void ad1848_speed_changed(ad1848_t *ad1848); -extern void ad1848_filter_cd_audio(int channel, double *buffer, void *priv); +extern void ad1848_init(ad1848_t *ad1848, uint8_t type); -extern void ad1848_init(ad1848_t *ad1848, uint8_t type); +#endif /*SOUND_AD1848_H*/ diff --git a/src/include/86box/snd_azt2316a.h b/src/include/86box/snd_azt2316a.h index 852de6c92..8aae3f1ff 100644 --- a/src/include/86box/snd_azt2316a.h +++ b/src/include/86box/snd_azt2316a.h @@ -1 +1,6 @@ -extern void azt2316a_enable_wss(uint8_t enable, void *p); \ No newline at end of file +#ifndef SOUND_AZT2316A_H +#define SOUND_AZT2316A_H + +extern void azt2316a_enable_wss(uint8_t enable, void *priv); + +#endif /*SOUND_AZT2316A*/ diff --git a/src/include/86box/snd_cms.h b/src/include/86box/snd_cms.h index 8700bf873..8eec22935 100644 --- a/src/include/86box/snd_cms.h +++ b/src/include/86box/snd_cms.h @@ -1,35 +1,33 @@ -#ifndef SOUND_SND_CMS_H -# define SOUND_SND_CMS_H +#ifndef SOUND_CMS_H +#define SOUND_CMS_H -#include #include <86box/sound.h> +#include #define MASTER_CLOCK 7159090 -typedef struct cms_t -{ - int addrs[2]; - uint8_t regs[2][32]; - uint16_t latch[2][6]; - int freq[2][6]; - float count[2][6]; - int vol[2][6][2]; - int stat[2][6]; - uint16_t noise[2][2]; - uint16_t noisefreq[2][2]; - int noisecount[2][2]; - int noisetype[2][2]; +typedef struct cms_t { + int addrs[2]; + uint8_t regs[2][32]; + uint16_t latch[2][6]; + int freq[2][6]; + float count[2][6]; + int vol[2][6][2]; + int stat[2][6]; + uint16_t noise[2][2]; + uint16_t noisefreq[2][2]; + int noisecount[2][2]; + int noisetype[2][2]; - uint8_t latched_data; + uint8_t latched_data; - int16_t buffer[SOUNDBUFLEN * 2]; + int16_t buffer[SOUNDBUFLEN * 2]; - int pos; + int pos; } cms_t; +extern void cms_update(cms_t *cms); +extern void cms_write(uint16_t addr, uint8_t val, void *priv); +extern uint8_t cms_read(uint16_t addr, void *priv); -extern void cms_update(cms_t *cms); -extern void cms_write(uint16_t addr, uint8_t val, void *p); -extern uint8_t cms_read(uint16_t addr, void *p); - -#endif /*SOUND_SND_CMS_H*/ +#endif /*SOUND_CMS_H*/ diff --git a/src/include/86box/snd_emu8k.h b/src/include/86box/snd_emu8k.h index effab0f79..090ab662a 100644 --- a/src/include/86box/snd_emu8k.h +++ b/src/include/86box/snd_emu8k.h @@ -1,40 +1,42 @@ +#ifndef SOUND_EMU8K_H +#define SOUND_EMU8K_H /* All these defines are in samples, not in bytes. */ -#define EMU8K_MEM_ADDRESS_MASK 0xFFFFFF -#define EMU8K_RAM_MEM_START 0x200000 -#define EMU8K_FM_MEM_ADDRESS 0xFFFFE0 -#define EMU8K_RAM_POINTERS_MASK 0x3F -#define EMU8K_LFOCHORUS_SIZE 0x4000 +#define EMU8K_MEM_ADDRESS_MASK 0xFFFFFF +#define EMU8K_RAM_MEM_START 0x200000 +#define EMU8K_FM_MEM_ADDRESS 0xFFFFE0 +#define EMU8K_RAM_POINTERS_MASK 0x3F +#define EMU8K_LFOCHORUS_SIZE 0x4000 /* * Everything in this file assumes little endian */ /* used for the increment of oscillator position*/ typedef struct emu8k_mem_internal_t { - union { - uint64_t addr; - struct { - uint16_t fract_lw_address; - uint16_t fract_address; - uint32_t int_address; - }; + union { + uint64_t addr; + struct { + uint16_t fract_lw_address; + uint16_t fract_address; + uint32_t int_address; }; + }; } emu8k_mem_internal_t; /* used for access to ram pointers from oscillator position. */ typedef struct emu8k_mem_pointers_t { - union { - uint32_t addr; - struct { - uint16_t lw_address; - uint8_t hb_address; - uint8_t unused_address; - }; + union { + uint32_t addr; + struct { + uint16_t lw_address; + uint8_t hb_address; + uint8_t unused_address; }; + }; } emu8k_mem_pointers_t; /* * From the Soundfount 2.0 fileformat Spec.: - * + * An envelope generates a control signal in six phases. When key-on occurs, a delay period begins during which the envelope value is zero. The envelope then rises in a convex curve to a value of one during the attack phase. @@ -44,25 +46,25 @@ typedef struct emu8k_mem_pointers_t { When a value of one is reached, the envelope enters a hold phase during which it remains at one. When the hold phase ends, the envelope enters a decay phase during which its value decreases linearly to a sustain level. " For the Volume Envelope, the decay phase linearly ramps toward the sustain level, causing a constant dB change for each time unit. " - When the sustain level is reached, the envelope enters sustain phase, during which the envelope stays at the sustain level. - + When the sustain level is reached, the envelope enters sustain phase, during which the envelope stays at the sustain level. + Whenever a key-off occurs, the envelope immediately enters a release phase during which the value linearly ramps from the current value to zero. " For the Volume Envelope, the release phase linearly ramps toward zero from the current level, causing a constant dB change for each time unit" When zero is reached, the envelope value remains at zero. - + Modulation of pitch and filter cutoff are in octaves, semitones, and cents. These parameters can be modulated to varying degree, either positively or negatively, by the modulation envelope. The degree of modulation is specified in cents for the full-scale attack peak. - + The volume envelope operates in dB, with the attack peak providing a full scale output, appropriately scaled by the initial volume. The zero value, however, is actually zero gain. The implementation in the EMU8000 provides for 96 dB of amplitude control. - When 96 dB of attenuation is reached in the final gain amplifier, an abrupt jump to zero gain + When 96 dB of attenuation is reached in the final gain amplifier, an abrupt jump to zero gain (infinite dB of attenuation) occurs. In a 16-bit system, this jump is inaudible */ /* It seems that the envelopes don't really have a decay/release stage, - * but instead they have a volume ramper that can be triggered + * but instead they have a volume ramper that can be triggered * automatically (after hold period), or manually (by activating release) * and the "sustain" value is the target of any of both cases. * Some programs like cubic player and AWEAmp use this, and it was @@ -75,51 +77,52 @@ typedef struct emu8k_mem_pointers_t { * contains the destination volume, and the lower byte contains the ramp time. */ -/* attack_amount is linear amplitude (added directly to value). +/* attack_amount is linear amplitude (added directly to value). * ramp_amount_db is linear dB (added directly to value too, but needs conversion to get linear amplitude). - * value range is 21bits for both, linear amplitude being 1<<21 = 0dBFS and 0 = -96dBFS (which is shortcut to silence), + * value range is 21bits for both, linear amplitude being 1<<21 = 0dBFS and 0 = -96dBFS (which is shortcut to silence), * and db amplutide being 0 = 0dBFS and -(1<<21) = -96dBFS (which is shortcut to silence). * This allows to operate db values by simply adding them. */ typedef struct emu8k_envelope_t { - int state; - int32_t delay_samples, hold_samples, attack_samples; - int32_t value_amp_hz, value_db_oct; - int32_t sustain_value_db_oct; - int32_t attack_amount_amp_hz, ramp_amount_db_oct; + int state; + int32_t delay_samples; + int32_t hold_samples; + int32_t attack_samples; + int32_t value_amp_hz; + int32_t value_db_oct; + int32_t sustain_value_db_oct; + int32_t attack_amount_amp_hz; + int32_t ramp_amount_db_oct; } emu8k_envelope_t; - - typedef struct emu8k_chorus_eng_t { - int32_t write; - int32_t feedback; - int32_t delay_samples_central; - double lfodepth_multip; - double delay_offset_samples_right; - emu8k_mem_internal_t lfo_inc; - emu8k_mem_internal_t lfo_pos; - - int32_t chorus_left_buffer[EMU8K_LFOCHORUS_SIZE]; - int32_t chorus_right_buffer[EMU8K_LFOCHORUS_SIZE]; + int32_t write; + int32_t feedback; + int32_t delay_samples_central; + double lfodepth_multip; + double delay_offset_samples_right; + emu8k_mem_internal_t lfo_inc; + emu8k_mem_internal_t lfo_pos; + + int32_t chorus_left_buffer[EMU8K_LFOCHORUS_SIZE]; + int32_t chorus_right_buffer[EMU8K_LFOCHORUS_SIZE]; } emu8k_chorus_eng_t; /* 32 * 242. 32 comes from the "right" room resso case.*/ #define MAX_REFL_SIZE 7744 - /* Reverb parameters description, extracted from AST sources. - Mix level - Decay - Link return amp + Mix level + Decay + Link return amp Link type Switches between normal or panned Room reso ( ms) L&R (Ref 6 +1) - Ref 1 x2 (11 ms)R - Ref 2 x4 (22 ms)R - Ref 3 x8 (44 ms)L - Ref 4 x13(71 ms)R - Ref 5 x19(105ms)L + Ref 1 x2 (11 ms)R + Ref 2 x4 (22 ms)R + Ref 3 x8 (44 ms)L + Ref 4 x13(71 ms)R + Ref 5 x19(105ms)L Ref 6 x ( ms)R (multiplier changes with room reso) Ref 1-6 filter L&R Ref 1-6 amp L&R @@ -129,269 +132,280 @@ typedef struct emu8k_chorus_eng_t { Ref 4 feedback L&R Ref 5 feedback L&R Ref 6 feedback L&R -*/ +*/ typedef struct emu8k_reverb_combfilter_t { - int read_pos; - int32_t reflection[MAX_REFL_SIZE]; - float output_gain; - float feedback; - float damp1; - float damp2; - int bufsize; - int32_t filterstore; + int read_pos; + int32_t reflection[MAX_REFL_SIZE]; + float output_gain; + float feedback; + float damp1; + float damp2; + int bufsize; + int32_t filterstore; } emu8k_reverb_combfilter_t; typedef struct emu8k_reverb_eng_t { - int16_t out_mix; - int16_t link_return_amp; /* tail part output gain ? */ - int8_t link_return_type; + int16_t out_mix; + int16_t link_return_amp; /* tail part output gain ? */ + int8_t link_return_type; - uint8_t refl_in_amp; + uint8_t refl_in_amp; - emu8k_reverb_combfilter_t reflections[6]; - emu8k_reverb_combfilter_t allpass[8]; - emu8k_reverb_combfilter_t tailL; - emu8k_reverb_combfilter_t tailR; - - emu8k_reverb_combfilter_t damper; + emu8k_reverb_combfilter_t reflections[6]; + emu8k_reverb_combfilter_t allpass[8]; + emu8k_reverb_combfilter_t tailL; + emu8k_reverb_combfilter_t tailR; + + emu8k_reverb_combfilter_t damper; } emu8k_reverb_eng_t; typedef struct emu8k_slide_t { - int32_t last; + int32_t last; } emu8k_slide_t; +typedef struct emu8k_voice_t { + union { + uint32_t cpf; + struct { + uint16_t cpf_curr_frac_addr; /* fractional part of the playing cursor. */ + uint16_t cpf_curr_pitch; /* 0x4000 = no shift. Linear increment */ + }; + }; + union { + uint32_t ptrx; + struct { + uint8_t ptrx_pan_aux; + uint8_t ptrx_revb_send; + uint16_t ptrx_pit_target; /* target pitch to which slide at curr_pitch speed. */ + }; + }; + union { + uint32_t cvcf; + struct { + uint16_t cvcf_curr_filt_ctoff; + uint16_t cvcf_curr_volume; + }; + }; + emu8k_slide_t volumeslide; + union { + uint32_t vtft; + struct { + uint16_t vtft_filter_target; + uint16_t vtft_vol_target; /* written to by the envelope engine. */ + }; + }; + /* These registers are used at least by the Windows drivers, and seem to be resetting + * something, similarly to targets and current, but... of what? + * what is curious is that if they are already zero, they are not written to, so it really + * looks like they are information about the status of the channel. (lfo position maybe?) */ + uint32_t unknown_data0_4; + uint32_t unknown_data0_5; + union { + uint32_t psst; + struct { + uint16_t psst_lw_address; + uint8_t psst_hw_address; + uint8_t psst_pan; + }; +#define PSST_LOOP_START_MASK 0x00FFFFFF /* In samples, i.e. uint16_t array[BOARD_RAM/2]; */ + }; + union { + uint32_t csl; + struct { + uint16_t csl_lw_address; + uint8_t csl_hw_address; + uint8_t csl_chor_send; + }; +#define CSL_LOOP_END_MASK 0x00FFFFFF /* In samples, i.e. uint16_t array[BOARD_RAM/2]; */ + }; + union { + uint32_t ccca; + struct { + uint16_t ccca_lw_addr; + uint8_t ccca_hb_addr; + uint8_t ccca_qcontrol; + }; + }; +#define CCCA_FILTQ_GET(ccca) (ccca >> 28) +#define CCCA_FILTQ_SET(ccca, q) ccca = (ccca & 0x0FFFFFFF) | (q << 28) +/* Bit 27 should always be zero */ +#define CCCA_DMA_ACTIVE(ccca) (ccca & 0x04000000) +#define CCCA_DMA_WRITE_MODE(ccca) (ccca & 0x02000000) +#define CCCA_DMA_WRITE_RIGHT(ccca) (ccca & 0x01000000) -typedef struct emu8k_voice_t -{ - union { - uint32_t cpf; - struct { - uint16_t cpf_curr_frac_addr; /* fractional part of the playing cursor. */ - uint16_t cpf_curr_pitch; /* 0x4000 = no shift. Linear increment */ - }; - }; - union { - uint32_t ptrx; - struct { - uint8_t ptrx_pan_aux; - uint8_t ptrx_revb_send; - uint16_t ptrx_pit_target; /* target pitch to which slide at curr_pitch speed. */ - }; - }; - union { - uint32_t cvcf; - struct { - uint16_t cvcf_curr_filt_ctoff; - uint16_t cvcf_curr_volume; - }; - }; - emu8k_slide_t volumeslide; - union { - uint32_t vtft; - struct { - uint16_t vtft_filter_target; - uint16_t vtft_vol_target; /* written to by the envelope engine. */ - }; - }; - /* These registers are used at least by the Windows drivers, and seem to be resetting - * something, similarly to targets and current, but... of what? - * what is curious is that if they are already zero, they are not written to, so it really - * looks like they are information about the status of the channel. (lfo position maybe?) */ - uint32_t unknown_data0_4; - uint32_t unknown_data0_5; - union { - uint32_t psst; - struct { - uint16_t psst_lw_address; - uint8_t psst_hw_address; - uint8_t psst_pan; - }; - #define PSST_LOOP_START_MASK 0x00FFFFFF /* In samples, i.e. uint16_t array[BOARD_RAM/2]; */ - }; - union { - uint32_t csl; - struct { - uint16_t csl_lw_address; - uint8_t csl_hw_address; - uint8_t csl_chor_send; - }; - #define CSL_LOOP_END_MASK 0x00FFFFFF /* In samples, i.e. uint16_t array[BOARD_RAM/2]; */ - }; - union { - uint32_t ccca; - struct { - uint16_t ccca_lw_addr; - uint8_t ccca_hb_addr; - uint8_t ccca_qcontrol; - }; - }; - #define CCCA_FILTQ_GET(ccca) (ccca>>28) - #define CCCA_FILTQ_SET(ccca,q) ccca = (ccca&0x0FFFFFFF) | (q<<28) - /* Bit 27 should always be zero */ - #define CCCA_DMA_ACTIVE(ccca) (ccca&0x04000000) - #define CCCA_DMA_WRITE_MODE(ccca) (ccca&0x02000000) - #define CCCA_DMA_WRITE_RIGHT(ccca) (ccca&0x01000000) - - uint16_t envvol; - #define ENVVOL_NODELAY(envol) (envvol&0x8000) - /* Verified with a soundfont bank. 7FFF is the minimum delay time, and 0 is the max delay time */ - #define ENVVOL_TO_EMU_SAMPLES(envvol) (envvol&0x8000) ? 0 : ((0x8000-(envvol&0x7FFF)) <<5) - - uint16_t dcysusv; - #define DCYSUSV_IS_RELEASE(dcysusv) (dcysusv&0x8000) - #define DCYSUSV_GENERATOR_ENGINE_ON(dcysusv) !(dcysusv&0x0080) - #define DCYSUSV_SUSVALUE_GET(dcysusv) ((dcysusv>>8)&0x7F) - /* Inverting the range compared to documentation because the envelope runs from 0dBFS = 0 to -96dBFS = (1 <<21) */ - #define DCYSUSV_SUS_TO_ENV_RANGE(susvalue) (((0x7F-susvalue) << 21)/0x7F) - #define DCYSUSV_DECAYRELEASE_GET(dcysusv) (dcysusv&0x7F) - - uint16_t envval; - #define ENVVAL_NODELAY(enval) (envval&0x8000) - /* Verified with a soundfont bank. 7FFF is the minimum delay time, and 0 is the max delay time */ - #define ENVVAL_TO_EMU_SAMPLES(envval)(envval&0x8000) ? 0 : ((0x8000-(envval&0x7FFF)) <<5) - - uint16_t dcysus; - #define DCYSUS_IS_RELEASE(dcysus) (dcysus&0x8000) - #define DCYSUS_SUSVALUE_GET(dcysus) ((dcysus>>8)&0x7F) - #define DCYSUS_SUS_TO_ENV_RANGE(susvalue) ((susvalue << 21)/0x7F) - #define DCYSUS_DECAYRELEASE_GET(dcysus) (dcysus&0x7F) - - uint16_t atkhldv; - #define ATKHLDV_TRIGGER(atkhldv) !(atkhldv&0x8000) - #define ATKHLDV_HOLD(atkhldv) ((atkhldv>>8)&0x7F) - #define ATKHLDV_HOLD_TO_EMU_SAMPLES(atkhldv) (4096*(0x7F-((atkhldv>>8)&0x7F))) - #define ATKHLDV_ATTACK(atkhldv) (atkhldv&0x7F) - - uint16_t lfo1val, lfo2val; - #define LFOxVAL_NODELAY(lfoxval) (lfoxval&0x8000) - #define LFOxVAL_TO_EMU_SAMPLES(lfoxval) (lfoxval&0x8000) ? 0 : ((0x8000-(lfoxval&0x7FFF)) <<5) - - uint16_t atkhld; - #define ATKHLD_TRIGGER(atkhld) !(atkhld&0x8000) - #define ATKHLD_HOLD(atkhld) ((atkhld>>8)&0x7F) - #define ATKHLD_HOLD_TO_EMU_SAMPLES(atkhld) (4096*(0x7F-((atkhld>>8)&0x7F))) - #define ATKHLD_ATTACK(atkhld) (atkhld&0x7F) - - - uint16_t ip; - #define INTIAL_PITCH_CENTER 0xE000 - #define INTIAL_PITCH_OCTAVE 0x1000 - - union { - uint16_t ifatn; - struct{ - uint8_t ifatn_attenuation; - uint8_t ifatn_init_filter; - }; - }; - union { - uint16_t pefe; - struct { - int8_t pefe_modenv_filter_height; - int8_t pefe_modenv_pitch_height; - }; - }; - union { - uint16_t fmmod; - struct { - int8_t fmmod_lfo1_filt_mod; - int8_t fmmod_lfo1_vibrato; - }; - }; - union { - uint16_t tremfrq; - struct { - uint8_t tremfrq_lfo1_freq; - int8_t tremfrq_lfo1_tremolo; - }; - }; - union { - uint16_t fm2frq2; - struct { - uint8_t fm2frq2_lfo2_freq; - int8_t fm2frq2_lfo2_vibrato; - }; - }; - - int env_engine_on; - - emu8k_mem_internal_t addr, loop_start, loop_end; - - int32_t initial_att; - int32_t initial_filter; + uint16_t envvol; +#define ENVVOL_NODELAY(envol) (envvol & 0x8000) +/* Verified with a soundfont bank. 7FFF is the minimum delay time, and 0 is the max delay time */ +#define ENVVOL_TO_EMU_SAMPLES(envvol) (envvol & 0x8000) ? 0 : ((0x8000 - (envvol & 0x7FFF)) << 5) - emu8k_envelope_t vol_envelope; - emu8k_envelope_t mod_envelope; - - int64_t lfo1_speed, lfo2_speed; - emu8k_mem_internal_t lfo1_count, lfo2_count; - int32_t lfo1_delay_samples, lfo2_delay_samples; - int vol_l, vol_r; + uint16_t dcysusv; +#define DCYSUSV_IS_RELEASE(dcysusv) (dcysusv & 0x8000) +#define DCYSUSV_GENERATOR_ENGINE_ON(dcysusv) !(dcysusv & 0x0080) +#define DCYSUSV_SUSVALUE_GET(dcysusv) ((dcysusv >> 8) & 0x7F) +/* Inverting the range compared to documentation because the envelope runs from 0dBFS = 0 to -96dBFS = (1 <<21) */ +#define DCYSUSV_SUS_TO_ENV_RANGE(susvalue) (((0x7F - susvalue) << 21) / 0x7F) +#define DCYSUSV_DECAYRELEASE_GET(dcysusv) (dcysusv & 0x7F) - int16_t fixed_modenv_filter_height; - int16_t fixed_modenv_pitch_height; - int16_t fixed_lfo1_filt_mod; - int16_t fixed_lfo1_vibrato; - int16_t fixed_lfo1_tremolo; - int16_t fixed_lfo2_vibrato; + uint16_t envval; +#define ENVVAL_NODELAY(enval) (envval & 0x8000) +/* Verified with a soundfont bank. 7FFF is the minimum delay time, and 0 is the max delay time */ +#define ENVVAL_TO_EMU_SAMPLES(envval) (envval & 0x8000) ? 0 : ((0x8000 - (envval & 0x7FFF)) << 5) - /* filter internal data. */ - int filterq_idx; - int32_t filt_att; - int64_t filt_buffer[5]; + uint16_t dcysus; +#define DCYSUS_IS_RELEASE(dcysus) (dcysus & 0x8000) +#define DCYSUS_SUSVALUE_GET(dcysus) ((dcysus >> 8) & 0x7F) +#define DCYSUS_SUS_TO_ENV_RANGE(susvalue) ((susvalue << 21) / 0x7F) +#define DCYSUS_DECAYRELEASE_GET(dcysus) (dcysus & 0x7F) + + uint16_t atkhldv; +#define ATKHLDV_TRIGGER(atkhldv) !(atkhldv & 0x8000) +#define ATKHLDV_HOLD(atkhldv) ((atkhldv >> 8) & 0x7F) +#define ATKHLDV_HOLD_TO_EMU_SAMPLES(atkhldv) (4096 * (0x7F - ((atkhldv >> 8) & 0x7F))) +#define ATKHLDV_ATTACK(atkhldv) (atkhldv & 0x7F) + + uint16_t lfo1val, lfo2val; +#define LFOxVAL_NODELAY(lfoxval) (lfoxval & 0x8000) +#define LFOxVAL_TO_EMU_SAMPLES(lfoxval) (lfoxval & 0x8000) ? 0 : ((0x8000 - (lfoxval & 0x7FFF)) << 5) + + uint16_t atkhld; +#define ATKHLD_TRIGGER(atkhld) !(atkhld & 0x8000) +#define ATKHLD_HOLD(atkhld) ((atkhld >> 8) & 0x7F) +#define ATKHLD_HOLD_TO_EMU_SAMPLES(atkhld) (4096 * (0x7F - ((atkhld >> 8) & 0x7F))) +#define ATKHLD_ATTACK(atkhld) (atkhld & 0x7F) + + uint16_t ip; +#define INTIAL_PITCH_CENTER 0xE000 +#define INTIAL_PITCH_OCTAVE 0x1000 + + union { + uint16_t ifatn; + struct { + uint8_t ifatn_attenuation; + uint8_t ifatn_init_filter; + }; + }; + union { + uint16_t pefe; + struct { + int8_t pefe_modenv_filter_height; + int8_t pefe_modenv_pitch_height; + }; + }; + union { + uint16_t fmmod; + struct { + int8_t fmmod_lfo1_filt_mod; + int8_t fmmod_lfo1_vibrato; + }; + }; + union { + uint16_t tremfrq; + struct { + uint8_t tremfrq_lfo1_freq; + int8_t tremfrq_lfo1_tremolo; + }; + }; + union { + uint16_t fm2frq2; + struct { + uint8_t fm2frq2_lfo2_freq; + int8_t fm2frq2_lfo2_vibrato; + }; + }; + + int env_engine_on; + + emu8k_mem_internal_t addr, loop_start, loop_end; + + int32_t initial_att; + int32_t initial_filter; + + emu8k_envelope_t vol_envelope; + emu8k_envelope_t mod_envelope; + + int64_t lfo1_speed; + int64_t lfo2_speed; + emu8k_mem_internal_t lfo1_count; + emu8k_mem_internal_t lfo2_count; + int32_t lfo1_delay_samples; + int32_t lfo2_delay_samples; + int vol_l; + int vol_r; + + int16_t fixed_modenv_filter_height; + int16_t fixed_modenv_pitch_height; + int16_t fixed_lfo1_filt_mod; + int16_t fixed_lfo1_vibrato; + int16_t fixed_lfo1_tremolo; + int16_t fixed_lfo2_vibrato; + + /* filter internal data. */ + int filterq_idx; + int32_t filt_att; + int64_t filt_buffer[5]; } emu8k_voice_t; -typedef struct emu8k_t -{ - emu8k_voice_t voice[32]; +typedef struct emu8k_t { + emu8k_voice_t voice[32]; - uint16_t hwcf1, hwcf2, hwcf3; - uint32_t hwcf4, hwcf5, hwcf6, hwcf7; + uint16_t hwcf1; + uint16_t hwcf2; + uint16_t hwcf3; + uint32_t hwcf4; + uint32_t hwcf5; + uint32_t hwcf6; + uint32_t hwcf7; - uint16_t init1[32], init2[32], init3[32], init4[32]; - - uint32_t smalr, smarr, smalw, smarw; - uint16_t smld_buffer, smrd_buffer; + uint16_t init1[32]; + uint16_t init2[32]; + uint16_t init3[32]; + uint16_t init4[32]; - uint16_t wc; - - uint16_t id; + uint32_t smalr; + uint32_t smarr; + uint32_t smalw; + uint32_t smarw; + uint16_t smld_buffer; + uint16_t smrd_buffer; - /* The empty block is used to act as an unallocated memory returning zero. */ - int16_t *ram, *rom, *empty; + uint16_t wc; - /* RAM pointers are a way to avoid checking ram boundaries on read */ - int16_t *ram_pointers[0x100]; - uint32_t ram_end_addr; + uint16_t id; - int cur_reg, cur_voice; - - int16_t out_l, out_r; - - emu8k_chorus_eng_t chorus_engine; - int32_t chorus_in_buffer[SOUNDBUFLEN]; - emu8k_reverb_eng_t reverb_engine; - int32_t reverb_in_buffer[SOUNDBUFLEN]; - - int pos; - int32_t buffer[SOUNDBUFLEN * 2]; + /* The empty block is used to act as an unallocated memory returning zero. */ + int16_t *ram; + int16_t *rom; + int16_t *empty; - uint16_t addr; + /* RAM pointers are a way to avoid checking ram boundaries on read */ + int16_t *ram_pointers[0x100]; + uint32_t ram_end_addr; + + int cur_reg; + int cur_voice; + + int16_t out_l; + int16_t out_r; + + emu8k_chorus_eng_t chorus_engine; + int32_t chorus_in_buffer[SOUNDBUFLEN]; + emu8k_reverb_eng_t reverb_engine; + int32_t reverb_in_buffer[SOUNDBUFLEN]; + + int pos; + int32_t buffer[SOUNDBUFLEN * 2]; + + uint16_t addr; } emu8k_t; - - void emu8k_change_addr(emu8k_t *emu8k, uint16_t emu_addr); void emu8k_init(emu8k_t *emu8k, uint16_t emu_addr, int onboard_ram); void emu8k_close(emu8k_t *emu8k); void emu8k_update(emu8k_t *emu8k); - - - /* Section E - Introduction to the EMU8000 Chip @@ -448,7 +462,7 @@ Section E - Introduction to the EMU8000 Chip Amplifier The amplifier determines the loudness of an audio signal. - + LFO1 An LFO, or Low Frequency Oscillator, is normally used to periodically modulate, that is, change a sound parameter, @@ -457,11 +471,11 @@ Section E - Introduction to the EMU8000 Chip modulation). It operates at sub-audio frequency from 0.042 Hz to 10.71 Hz. The LFO1 in the EMU8000 modulates the pitch, volume and filter cutoff simultaneously. - + LFO2 The LFO2 is similar to the LFO1, except that it modulates the pitch of the audio signal only. - + Resonance A filter alone would be like an equalizer, making a bright audio signal duller, but the addition of resonance @@ -470,7 +484,7 @@ Section E - Introduction to the EMU8000 Chip signals at the cutoff frequency, giving the audio signal a subtle wah-wah, that is, imagine a siren sound going from bright to dull to bright again periodically. - + LFO1 to Volume (Tremolo) The LFO1's output is routed to the amplifier, with the depth of oscillation determined by LFO1 to Volume. LFO1 @@ -484,7 +498,7 @@ Section E - Introduction to the EMU8000 Chip oscillating). An example of a GM instrument that makes use of LFO1 to Volume is instrument number 45, Tremolo Strings. - + LFO1 to Filter Cutoff (Wah-Wah) The LFO1's output is routed to the filter, with the depth of oscillation determined by LFO1 to Filter. LFO1 to @@ -502,7 +516,7 @@ Section E - Introduction to the EMU8000 Chip oscillator, producing a vibrato effect. An example of a GM instrument that makes use of LFO1 to Pitch is instrument number 57, Trumpet. - + LFO2 to Pitch (Vibrato) The LFO1 in the EMU8000 can simultaneously modulate pitch, volume and filter. LFO2, on the other hand, @@ -511,7 +525,7 @@ Section E - Introduction to the EMU8000 Chip periodic fluctuation in the pitch of the oscillator, producing a vibrato effect. When this is coupled with LFO1 to Pitch, a complex vibrato effect can be achieved. - + Volume Envelope The character of a musical instrument is largely determined by its volume envelope, the way in which the @@ -537,7 +551,7 @@ Section E - Introduction to the EMU8000 Chip as a key is held down. Release The time it takes the envelope to fall to the zero level after the key is released. - + Using these six parameters can yield very realistic reproduction of the volume envelope characteristics of many musical instruments. @@ -558,14 +572,14 @@ Section E - Introduction to the EMU8000 Chip useful in creating synthetic sci-fi sound textures. An example of a GM instrument that makes use of the filter envelope is instrument number 86, Pad 8 (Sweep). - + Pitch/Filter Envelope Modulation These two parameters determine the modulation depth of the pitch and filter envelope. In the wind instrument example above, a small amount of pitch envelope modulation is desirable to simulate its natural pitch characteristics. - + This rich modulation capability of the EMU8000 is fully exploited by the SB AWE32 MIDI drivers. The driver also provides you with a means to change these parameters over @@ -619,9 +633,9 @@ Section E - Introduction to the EMU8000 Chip Short Delay (feed back) This chorus variation simulates a short delay repeated (feedback) many times. - - - + + + Registers to write the Chorus Parameters to (all are 16-bit, unless noted): (codified as in register,port,voice. port 0=0x620, 2=0x622, 4=0xA20, 6=0xA22, 8=0xE20) ( 3409 = register 3, port A20, voice 9) @@ -654,12 +668,12 @@ Short Delay Short Delay + Feedback // Chorus Params typedef struct { - WORD FbkLevel; // Feedback Level (0xE600-0xE6FF) - WORD Delay; // Delay (0-0x0DA3) [1/44100 sec] - WORD LfoDepth; // LFO Depth (0xBC00-0xBCFF) - DWORD DelayR; // Right Delay (0-0xFFFFFFFF) [1/256/44100 sec] - DWORD LfoFreq; // LFO Frequency (0-0xFFFFFFFF) - } CHORUS_TYPE; + WORD FbkLevel; // Feedback Level (0xE600-0xE6FF) + WORD Delay; // Delay (0-0x0DA3) [1/44100 sec] + WORD LfoDepth; // LFO Depth (0xBC00-0xBCFF) + DWORD DelayR; // Right Delay (0-0xFFFFFFFF) [1/256/44100 sec] + DWORD LfoFreq; // LFO Frequency (0-0xFFFFFFFF) + } CHORUS_TYPE; Registers to write the Reverb Parameters to (they are all 16-bit): @@ -700,16 +714,16 @@ Hall 1: 0x7224,0x7224,0x7254,0x7284,0x4448,0x4548,0xA440,0xA540, 0x842B,0x852B,0x842B,0x852B,0x842A,0x852A,0x842A,0x852A, 0x8429,0x8529,0x8429,0x8529 - + Hall 2: - + 0xB488,0xA470,0x9570,0x84B5,0x383A,0x3EB5,0x7254,0x7234, 0x7224,0x7254,0x7264,0x7294,0x44C3,0x45C3,0xA404,0xA504, 0x842A,0x852A,0x842A,0x852A,0x8429,0x8529,0x8429,0x8529, -0x8428,0x8528,0x8428,0x8528 +0x8428,0x8528,0x8428,0x8528 Plate: - + 0xB4FF,0xA470,0x9570,0x84B5,0x383A,0x3EB5,0x7234,0x7234, 0x7234,0x7234,0x7234,0x7234,0x4448,0x4548,0xA440,0xA540, 0x842A,0x852A,0x842A,0x852A,0x8429,0x8529,0x8429,0x8529, @@ -776,3 +790,5 @@ Treble Parameters: 0xD308 0xD308 0xD308 0xD308 0xD308 0xD308 0xD3019 0xD32A 0xD34C 0xD36E 0xD36E 0xD36E 0x0001 0x0001 0x0001 0x0001 0x0001 0x0002 0x0002 0x0002 0x0002 0x0002 0x0002 0x0002 */ + +#endif /*SOUND_EMU8K_H*/ diff --git a/src/include/86box/snd_mpu401.h b/src/include/86box/snd_mpu401.h index 433bf09a1..8cd275af8 100644 --- a/src/include/86box/snd_mpu401.h +++ b/src/include/86box/snd_mpu401.h @@ -1,49 +1,49 @@ /* - * 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. + * 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. + * This file is part of the 86Box distribution. * - * Roland MPU-401 emulation. + * Roland MPU-401 emulation. * * * - * Author: Sarah Walker, - * DOSBox Team, - * Miran Grca, - * TheCollector1995, - * Copyright 2008-2020 Sarah Walker. - * Copyright 2008-2020 DOSBox Team. - * Copyright 2016-2020 Miran Grca. - * Copyright 2016-2020 TheCollector1995. + * Authors: Sarah Walker, + * DOSBox Team, + * Miran Grca, + * TheCollector1995, + * + * Copyright 2008-2020 Sarah Walker. + * Copyright 2008-2020 DOSBox Team. + * Copyright 2016-2020 Miran Grca. + * Copyright 2016-2020 TheCollector1995. */ -#ifndef SOUND_MPU401_H -# define SOUND_MPU401_H -#define MPU401_VERSION 0x15 -#define MPU401_REVISION 0x01 -#define MPU401_QUEUE 64 -#define MPU401_INPUT_QUEUE 1024 -#define MPU401_TIMECONSTANT (60000000/1000.0f) -#define MPU401_RESETBUSY 27.0f +#ifndef SOUND_MPU401_H +#define SOUND_MPU401_H + +#define MPU401_VERSION 0x15 +#define MPU401_REVISION 0x01 +#define MPU401_QUEUE 1024 +#define MPU401_INPUT_QUEUE 1024 +#define MPU401_TIMECONSTANT (60000000 / 1000.0f) +#define MPU401_RESETBUSY 27.0f /*helpers*/ -#define M_GETKEY key[key/32]&(1<<(key%32)) -#define M_SETKEY key[key/32]|=(1<<(key%32)) -#define M_DELKEY key[key/32]&=~(1<<(key%32)) +#define M_GETKEY key[key / 32] & (1 << (key % 32)) +#define M_SETKEY key[key / 32] |= (1 << (key % 32)) +#define M_DELKEY key[key / 32] &= ~(1 << (key % 32)) -typedef enum MpuMode -{ +typedef enum MpuMode { M_UART, M_INTELLIGENT } MpuMode; #define M_MCA 0x10 -typedef enum MpuDataType -{ +typedef enum MpuDataType { T_OVERFLOW, T_MARK, T_MIDI_SYS, @@ -51,117 +51,153 @@ typedef enum MpuDataType T_COMMAND } MpuDataType; -typedef enum RecState -{ - M_RECOFF, - M_RECSTB, - M_RECON +typedef enum RecState { + M_RECOFF, + M_RECSTB, + M_RECON } RecState; /* Messages sent to MPU-401 from host */ -#define MSG_EOX 0xf7 -#define MSG_OVERFLOW 0xf8 -#define MSG_MARK 0xfc +#define MSG_EOX 0xf7 +#define MSG_OVERFLOW 0xf8 +#define MSG_MARK 0xfc /* Messages sent to host from MPU-401 */ -#define MSG_MPU_OVERFLOW 0xf8 -#define MSG_MPU_COMMAND_REQ 0xf9 -#define MSG_MPU_END 0xfc -#define MSG_MPU_CLOCK 0xfd -#define MSG_MPU_ACK 0xfe +#define MSG_MPU_OVERFLOW 0xf8 +#define MSG_MPU_COMMAND_REQ 0xf9 +#define MSG_MPU_END 0xfc +#define MSG_MPU_CLOCK 0xfd +#define MSG_MPU_ACK 0xfe -typedef struct mpu_t -{ +typedef struct mpu_t { uint16_t addr; - int uart_mode, intelligent, - irq, midi_thru, - queue_pos, queue_used; - uint8_t rx_data, is_mca, - status, - queue[MPU401_QUEUE], pos_regs[8]; - MpuMode mode; - uint8_t rec_queue[MPU401_INPUT_QUEUE]; - int rec_queue_pos, rec_queue_used; - uint32_t ch_toref[16]; - struct track - { - int counter; - uint8_t value[3], sys_val, - vlength,length; - MpuDataType type; + int uart_mode; + int intelligent; + int irq; + int midi_thru; + int queue_pos; + int queue_used; + uint8_t rx_data; + uint8_t is_mca; + uint8_t status; + uint8_t queue[MPU401_QUEUE]; + uint8_t pos_regs[8]; + MpuMode mode; + uint8_t rec_queue[MPU401_INPUT_QUEUE]; + int rec_queue_pos; + int rec_queue_used; + uint32_t ch_toref[16]; + struct track { + int counter; + uint8_t value[3]; + uint8_t sys_val; + uint8_t vlength; + uint8_t length; + MpuDataType type; } playbuf[8], condbuf; struct { - int conductor, cond_req, - cond_set, block_ack, - playing, reset, - wsd, wsm, wsd_start, - run_irq, irq_pending, - track_req, - send_now, eoi_scheduled, - data_onoff, clock_to_host, - sync_in, sysex_in_finished, - rec_copy; - RecState rec; - uint8_t tmask, cmask, - amask, - last_rtcmd; - uint16_t midi_mask, req_mask; - uint32_t command_byte, cmd_pending, - track, old_track; + int conductor; + int cond_req; + int cond_set; + int block_ack; + int playing; + int reset; + int wsd; + int wsm; + int wsd_start; + int run_irq; + int irq_pending; + int track_req; + int send_now; + int eoi_scheduled; + int data_onoff; + int clock_to_host; + int sync_in; + int sysex_in_finished; + int rec_copy; + RecState rec; + uint8_t tmask; + uint8_t cmask; + uint8_t amask; + uint8_t last_rtcmd; + uint16_t midi_mask; + uint16_t req_mask; + uint32_t command_byte; + uint32_t cmd_pending; + uint32_t track; + uint32_t old_track; } state; struct { - uint8_t timebase, old_timebase, - tempo, old_tempo, - tempo_rel, old_tempo_rel, - tempo_grad, cth_rate[4], - cth_mode, midimetro, - metromeas; - uint32_t cth_counter, cth_old, - rec_counter; - int32_t measure_counter, meas_old, - freq; - int ticks_in, active; - float freq_mod; + uint8_t timebase; + uint8_t old_timebase; + uint8_t tempo; + uint8_t old_tempo; + uint8_t tempo_rel; + uint8_t old_tempo_rel; + uint8_t tempo_grad; + uint8_t cth_rate[4]; + uint8_t cth_mode; + uint8_t midimetro; + uint8_t metromeas; + uint32_t cth_counter; + uint32_t cth_old; + uint32_t rec_counter; + int32_t measure_counter; + int32_t meas_old; + int32_t freq; + int ticks_in; + int active; + float freq_mod; } clock; - struct { - int all_thru, midi_thru, - sysex_thru, commonmsgs_thru, - modemsgs_in, commonmsgs_in, - bender_in, sysex_in, - allnotesoff_out, rt_affection, - rt_out, rt_in, - timing_in_stop, data_in_stop, - rec_measure_end; - uint8_t prchg_buf[16]; - uint16_t prchg_mask; - } filter; - struct { - int on; - uint8_t chan, trmask; - uint32_t key[4]; - } chanref[5], inputref[16]; - pc_timer_t mpu401_event_callback, mpu401_eoi_callback, - mpu401_reset_callback; - void (*ext_irq_update)(void *priv, int set); - int (*ext_irq_pending)(void *priv); - void *priv; + struct { + int all_thru; + int midi_thru; + int sysex_thru; + int commonmsgs_thru; + int modemsgs_in; + int commonmsgs_in; + int bender_in; + int sysex_in; + int allnotesoff_out; + int rt_affection; + int rt_out; + int rt_in; + int timing_in_stop; + int data_in_stop; + int rec_measure_end; + uint8_t prchg_buf[16]; + uint16_t prchg_mask; + } filter; + struct { + int on; + uint8_t chan; + uint8_t trmask; + uint32_t key[4]; + } chanref[5], inputref[16]; + pc_timer_t mpu401_event_callback; + pc_timer_t mpu401_eoi_callback; + pc_timer_t mpu401_reset_callback; + void (*ext_irq_update)(void *priv, int set); + int (*ext_irq_pending)(void *priv); + void *priv; } mpu_t; -extern int mpu401_standalone_enable, mpu401_already_loaded; +extern int mpu401_standalone_enable; +extern int mpu401_already_loaded; -extern const device_t mpu401_device; -extern const device_t mpu401_mca_device; +extern const device_t mpu401_device; +extern const device_t mpu401_mca_device; +extern uint8_t MPU401_ReadData(mpu_t *mpu); +extern void mpu401_write(uint16_t addr, uint8_t val, void *priv); +extern uint8_t mpu401_read(uint16_t addr, void *priv); +extern void mpu401_setirq(mpu_t *mpu, int irq); +extern void mpu401_change_addr(mpu_t *mpu, uint16_t addr); +extern void mpu401_init(mpu_t *mpu, uint16_t addr, int irq, int mode, int receive_input); +extern void mpu401_device_add(void); +extern void mpu401_irq_attach(mpu_t *mpu, void (*ext_irq_update)(void *priv, int set), int (*ext_irq_pending)(void *priv), void *priv); -extern uint8_t MPU401_ReadData(mpu_t *mpu); -extern void mpu401_setirq(mpu_t *mpu, int irq); -extern void mpu401_change_addr(mpu_t *mpu, uint16_t addr); -extern void mpu401_init(mpu_t *mpu, uint16_t addr, int irq, int mode, int receive_input); -extern void mpu401_device_add(void); -extern void mpu401_irq_attach(mpu_t *mpu, void (*ext_irq_update)(void *priv, int set), int (*ext_irq_pending)(void *priv), void *priv); +extern int MPU401_InputSysex(void *priv, uint8_t *buffer, uint32_t len, int abort); +extern void MPU401_InputMsg(void *priv, uint8_t *msg, uint32_t len); -extern int MPU401_InputSysex(void *p, uint8_t *buffer, uint32_t len, int abort); -extern void MPU401_InputMsg(void *p, uint8_t *msg, uint32_t len); - - -#endif /*SOUND_MPU401_H*/ +#endif /*SOUND_MPU401_H*/ diff --git a/src/include/86box/snd_opl.h b/src/include/86box/snd_opl.h index f6e533e4a..e516b95f9 100644 --- a/src/include/86box/snd_opl.h +++ b/src/include/86box/snd_opl.h @@ -1,57 +1,58 @@ /* - * 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. + * 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. + * This file is part of the 86Box distribution. * - * Definitions for the OPL interface. + * Definitions for the OPL interface. * - * Authors: Fred N. van Kempen, - * Miran Grca, + * Authors: Fred N. van Kempen, + * Miran Grca, * - * Copyright 2017-2020 Fred N. van Kempen. - * Copyright 2016-2020 Miran Grca. + * Copyright 2017-2020 Fred N. van Kempen. + * Copyright 2016-2020 Miran Grca. */ #ifndef SOUND_OPL_H -# define SOUND_OPL_H +#define SOUND_OPL_H +enum fm_type { + FM_YM3812 = 0, /* OPL2 */ + FM_YMF262 = 1, /* OPL3 */ + FM_YMF289B = 2, /* OPL3-L */ + FM_YMF278B = 3, /* OPL 4 */ + FM_MAX = 4 +}; -typedef void (*tmrfunc)(void *priv, int timer, uint64_t period); +enum fm_driver { + FM_DRV_NUKED = 0, + FM_DRV_YMFM = 1, + FM_DRV_MAX = 2 +}; -/* Define an OPLx chip. */ -typedef struct { -#ifdef SOUND_OPL_NUKED_H - nuked_t *opl; -#else - void *opl; +typedef struct fm_drv_t { + uint8_t (*read)(uint16_t port, void *priv); + void (*write)(uint16_t port, uint8_t val, void *priv); + int32_t *(*update)(void *priv); + void (*reset_buffer)(void *priv); + void (*set_do_cycles)(void *priv, int8_t do_cycles); + void *priv; +} fm_drv_t; + +extern uint8_t fm_driver_get(int chip_id, fm_drv_t *drv); + +extern const fm_drv_t nuked_opl_drv; +extern const fm_drv_t ymfm_drv; + +#ifdef EMU_DEVICE_H +extern const device_t ym3812_nuked_device; +extern const device_t ymf262_nuked_device; + +extern const device_t ym3812_ymfm_device; +extern const device_t ymf262_ymfm_device; +extern const device_t ymf289b_ymfm_device; +extern const device_t ymf278b_ymfm_device; #endif - int8_t flags, pad; - uint16_t port; - uint8_t status, timer_ctrl; - uint16_t timer_count[2], - timer_cur_count[2]; - - pc_timer_t timers[2]; - - int pos; - int32_t buffer[SOUNDBUFLEN * 2]; -} opl_t; - - -extern void opl_set_do_cycles(opl_t *dev, int8_t do_cycles); - -extern uint8_t opl2_read(uint16_t port, void *); -extern void opl2_write(uint16_t port, uint8_t val, void *); -extern void opl2_init(opl_t *); -extern void opl2_update(opl_t *); - -extern uint8_t opl3_read(uint16_t port, void *); -extern void opl3_write(uint16_t port, uint8_t val, void *); -extern void opl3_init(opl_t *); -extern void opl3_update(opl_t *); - - -#endif /*SOUND_OPL_H*/ +#endif /*SOUND_OPL_H*/ diff --git a/src/include/86box/snd_opl_nuked.h b/src/include/86box/snd_opl_nuked.h index ff2e1db30..e53f860f1 100644 --- a/src/include/86box/snd_opl_nuked.h +++ b/src/include/86box/snd_opl_nuked.h @@ -1,35 +1,23 @@ /* - * 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. + * 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. + * This file is part of the 86Box distribution. * - * Definitions for the NukedOPL3 driver. + * Definitions for the NukedOPL3 driver. * - * Version: @(#)snd_opl_nuked.h 1.0.5 2020/07/16 + * Version: @(#)snd_opl_nuked.h 1.0.5 2020/07/16 * - * Authors: Fred N. van Kempen, - * Miran Grca, + * Authors: Fred N. van Kempen, + * Miran Grca, * - * Copyright 2017-2020 Fred N. van Kempen. - * Copyright 2016-2019 Miran Grca. + * Copyright 2017-2020 Fred N. van Kempen. + * Copyright 2016-2019 Miran Grca. */ + #ifndef SOUND_OPL_NUKED_H -# define SOUND_OPL_NUKED_H +#define SOUND_OPL_NUKED_H - -extern void * nuked_init(uint32_t sample_rate); -extern void nuked_close(void *); - -extern uint16_t nuked_write_addr(void *, uint16_t port, uint8_t val); -extern void nuked_write_reg(void *, uint16_t reg, uint8_t v); -extern void nuked_write_reg_buffered(void *, uint16_t reg, uint8_t v); - -extern void nuked_generate(void *, int32_t *buf); -extern void nuked_generate_resampled(void *, int32_t *buf); -extern void nuked_generate_stream(void *, int32_t *sndptr, uint32_t num); - - -#endif /*SOUND_OPL_NUKED_H*/ +#endif /*SOUND_OPL_NUKED_H*/ diff --git a/src/include/86box/snd_resid.h b/src/include/86box/snd_resid.h index 402ee0ceb..4ddaf9b91 100644 --- a/src/include/86box/snd_resid.h +++ b/src/include/86box/snd_resid.h @@ -1,12 +1,17 @@ +#ifndef SOUND_RESID_H +#define SOUND_RESID_H + #ifdef __cplusplus extern "C" { #endif - void *sid_init(); - void sid_close(void *p); - void sid_reset(void *p); - uint8_t sid_read(uint16_t addr, void *p); - void sid_write(uint16_t addr, uint8_t val, void *p); - void sid_fillbuf(int16_t *buf, int len, void *p); +void *sid_init(void); +void sid_close(void *priv); +void sid_reset(void *priv); +uint8_t sid_read(uint16_t addr, void *priv); +void sid_write(uint16_t addr, uint8_t val, void *priv); +void sid_fillbuf(int16_t *buf, int len, void *priv); #ifdef __cplusplus } #endif + +#endif /*SOUND_RESID_H*/ diff --git a/src/include/86box/snd_sb.h b/src/include/86box/snd_sb.h index 7291aa4d0..f433dd107 100644 --- a/src/include/86box/snd_sb.h +++ b/src/include/86box/snd_sb.h @@ -1,144 +1,173 @@ /* - * 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. + * 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. + * This file is part of the 86Box distribution. * - * Sound Blaster emulation. + * Sound Blaster emulation. * - * Authors: Sarah Walker, - * Miran Grca, - * TheCollector1995, + * Authors: Sarah Walker, + * Miran Grca, + * TheCollector1995, * - * Copyright 2008-2018 Sarah Walker. - * Copyright 2016-2018 Miran Grca. + * Copyright 2008-2018 Sarah Walker. + * Copyright 2016-2018 Miran Grca. */ -#ifndef SOUND_SND_SB_H -# define SOUND_SND_SB_H +#ifndef SOUND_SND_SB_H +#define SOUND_SND_SB_H + +#include <86box/snd_cms.h> #include <86box/snd_emu8k.h> #include <86box/snd_mpu401.h> #include <86box/snd_opl.h> #include <86box/snd_sb_dsp.h> -#include <86box/snd_cms.h> -#define SADLIB 1 /* No DSP */ -#define SB1 2 /* DSP v1.05 */ -#define SB15 3 /* DSP v2.00 */ -#define SB2 4 /* DSP v2.01 - needed for high-speed DMA */ -#define SBPRO 5 /* DSP v3.00 */ -#define SBPRO2 6 /* DSP v3.02 + OPL3 */ -#define SB16 7 /* DSP v4.05 + OPL3 */ -#define SBAWE32 8 /* DSP v4.13 + OPL3 */ -#define SBAWE64 9 /* DSP v4.16 + OPL3 */ +enum { + SADLIB = 1, /* No DSP */ + SB1, /* DSP v1.05 */ + SB15, /* DSP v2.00 */ + SB2, /* DSP v2.01 - needed for high-speed DMA */ + SBPRO, /* DSP v3.00 */ + SBPRO2, /* DSP v3.02 + OPL3 */ + SB16, /* DSP v4.05 + OPL3 */ + SBAWE32, /* DSP v4.12 + OPL3 */ + SBAWE32PNP, /* DSP v4.13 + OPL3 */ + SBAWE64 /* DSP v4.16 + OPL3 */ +}; /* SB 2.0 CD version */ -typedef struct sb_ct1335_mixer_t -{ - double master; - double voice; - double fm; - double cd; +typedef struct sb_ct1335_mixer_t { + double master; + double voice; + double fm; + double cd; - uint8_t index; - uint8_t regs[256]; + uint8_t index; + uint8_t regs[256]; } sb_ct1335_mixer_t; + /* SB PRO */ -typedef struct sb_ct1345_mixer_t -{ - double master_l, master_r; - double voice_l, voice_r; - double fm_l, fm_r; - double cd_l, cd_r; - double line_l, line_r; - double mic; - /*see sb_ct1745_mixer for values for input selector*/ - int32_t input_selector; - - int input_filter; - int in_filter_freq; - int output_filter; - - int stereo; - int stereo_isleft; - - uint8_t index; - uint8_t regs[256]; - +typedef struct sb_ct1345_mixer_t { + double master_l; + double master_r; + double voice_l; + double voice_r; + double fm_l; + double fm_r; + double cd_l; + double cd_r; + double line_l; + double line_r; + double mic; + /*see sb_ct1745_mixer for values for input selector*/ + int32_t input_selector; + + int input_filter; + int in_filter_freq; + int output_filter; + + int stereo; + int stereo_isleft; + + uint8_t index; + uint8_t regs[256]; } sb_ct1345_mixer_t; + /* SB16 and AWE32 */ -typedef struct sb_ct1745_mixer_t -{ - double master_l, master_r; - double voice_l, voice_r; - double fm_l, fm_r; - double cd_l, cd_r; - double line_l, line_r; - double mic; - double speaker; +typedef struct sb_ct1745_mixer_t { + double master_l; + double master_r; + double voice_l; + double voice_r; + double fm_l; + double fm_r; + double cd_l; + double cd_r; + double line_l; + double line_r; + double mic; + double speaker; - int bass_l, bass_r; - int treble_l, treble_r; - - int output_selector; - #define OUTPUT_MIC 1 - #define OUTPUT_CD_R 2 - #define OUTPUT_CD_L 4 - #define OUTPUT_LINE_R 8 - #define OUTPUT_LINE_L 16 + int bass_l; + int bass_r; + int treble_l; + int treble_r; - int input_selector_left; - int input_selector_right; - #define INPUT_MIC 1 - #define INPUT_CD_R 2 - #define INPUT_CD_L 4 - #define INPUT_LINE_R 8 - #define INPUT_LINE_L 16 - #define INPUT_MIDI_R 32 - #define INPUT_MIDI_L 64 + int output_selector; +#define OUTPUT_MIC 1 +#define OUTPUT_CD_R 2 +#define OUTPUT_CD_L 4 +#define OUTPUT_LINE_R 8 +#define OUTPUT_LINE_L 16 - int mic_agc; - - int32_t input_gain_L; - int32_t input_gain_R; - double output_gain_L; - double output_gain_R; - - uint8_t index; - uint8_t regs[256]; + int input_selector_left; + int input_selector_right; +#define INPUT_MIC 1 +#define INPUT_CD_R 2 +#define INPUT_CD_L 4 +#define INPUT_LINE_R 8 +#define INPUT_LINE_L 16 +#define INPUT_MIDI_R 32 +#define INPUT_MIDI_L 64 + + int mic_agc; + + int32_t input_gain_L; + int32_t input_gain_R; + double output_gain_L; + double output_gain_R; + + uint8_t index; + uint8_t regs[256]; + + int output_filter; /* for clones */ } sb_ct1745_mixer_t; -typedef struct sb_t -{ - uint8_t cms_enabled, opl_enabled, mixer_enabled; - cms_t cms; - opl_t opl, opl2; - sb_dsp_t dsp; - union { - sb_ct1335_mixer_t mixer_sb2; - sb_ct1345_mixer_t mixer_sbpro; - sb_ct1745_mixer_t mixer_sb16; - }; - mpu_t *mpu; - emu8k_t emu8k; - void *gameport; +typedef struct sb_t { + uint8_t cms_enabled; + uint8_t opl_enabled; + uint8_t mixer_enabled; + cms_t cms; + fm_drv_t opl; + fm_drv_t opl2; + sb_dsp_t dsp; + union { + sb_ct1335_mixer_t mixer_sb2; + sb_ct1345_mixer_t mixer_sbpro; + sb_ct1745_mixer_t mixer_sb16; + }; + mpu_t *mpu; + emu8k_t emu8k; + void *gameport; - int pos; - - uint8_t pos_regs[8], pnp_rom[512]; + int pos; + int pnp; - uint16_t opl_pnp_addr; + uint8_t pos_regs[8]; + uint8_t pnp_rom[512]; + + uint16_t opl_pnp_addr; + uint16_t gameport_addr; + + void *opl_mixer; + void (*opl_mix)(void*, double*, double*); } sb_t; -extern void sb_ct1345_mixer_write(uint16_t addr, uint8_t val, void *p); -extern uint8_t sb_ct1345_mixer_read(uint16_t addr, void *p); -extern void sb_ct1345_mixer_reset(sb_t* sb); +extern void sb_ct1345_mixer_write(uint16_t addr, uint8_t val, void *priv); +extern uint8_t sb_ct1345_mixer_read(uint16_t addr, void *priv); +extern void sb_ct1345_mixer_reset(sb_t *sb); -extern void sb_get_buffer_sbpro(int32_t *buffer, int len, void *p); -extern void sbpro_filter_cd_audio(int channel, double *buffer, void *p); -extern void sb_close(void *p); -extern void sb_speed_changed(void *p); +extern void sb_ct1745_mixer_write(uint16_t addr, uint8_t val, void *priv); +extern uint8_t sb_ct1745_mixer_read(uint16_t addr, void *priv); +extern void sb_ct1745_mixer_reset(sb_t *sb); -#endif /*SOUND_SND_SB_H*/ +extern void sb_get_buffer_sbpro(int32_t *buffer, int len, void *priv); +extern void sbpro_filter_cd_audio(int channel, double *buffer, void *priv); +extern void sb16_awe32_filter_cd_audio(int channel, double *buffer, void *priv); +extern void sb_close(void *priv); +extern void sb_speed_changed(void *priv); + +#endif /*SOUND_SND_SB_H*/ diff --git a/src/include/86box/snd_sb_dsp.h b/src/include/86box/snd_sb_dsp.h index 067e05b3e..ecabe426d 100644 --- a/src/include/86box/snd_sb_dsp.h +++ b/src/include/86box/snd_sb_dsp.h @@ -7,122 +7,168 @@ #define SB_SUBTYPE_CLONE_AZT1605_0X0C 2 /*Aztech Sound Galaxy Nova 16 Extra / Packard Bell Forte 16, DSP 2.1 - SBPRO2 clone*/ /* aztech-related */ -#define IS_AZTECH(dsp) ((dsp)->sb_subtype == SB_SUBTYPE_CLONE_AZT2316A_0X11 || (dsp)->sb_subtype == SB_SUBTYPE_CLONE_AZT1605_0X0C) /* check for future AZT cards here */ -#define AZTECH_EEPROM_SIZE 16 +#define IS_AZTECH(dsp) ((dsp)->sb_subtype == SB_SUBTYPE_CLONE_AZT2316A_0X11 || (dsp)->sb_subtype == SB_SUBTYPE_CLONE_AZT1605_0X0C) /* check for future AZT cards here */ +#define AZTECH_EEPROM_SIZE 16 -typedef struct sb_dsp_t -{ - int sb_type; - int sb_subtype; /* which clone */ - void *parent; /* "sb_t *" if default subtype, "azt2316a_t *" if aztech. */ +typedef struct sb_dsp_t { + int sb_type; + int sb_subtype; /* which clone */ + void *parent; /* "sb_t *" if default subtype, "azt2316a_t *" if aztech. */ - int sb_8_length, sb_8_format, sb_8_autoinit, sb_8_pause, sb_8_enable, sb_8_autolen, sb_8_output; - int sb_8_dmanum; - int sb_16_length, sb_16_format, sb_16_autoinit, sb_16_pause, sb_16_enable, sb_16_autolen, sb_16_output; - int sb_16_dmanum; - int sb_pausetime; + int sb_8_length; + int sb_8_origlength; + int sb_8_format; + int sb_8_autoinit; + int sb_8_pause; + int sb_8_enable; + int sb_8_autolen; + int sb_8_output; + int sb_8_dmanum; + int sb_16_length; + int sb_16_origlength; + int sb_16_format; + int sb_16_autoinit; + int sb_16_pause; + int sb_16_enable; + int sb_16_autolen; + int sb_16_output; + int sb_16_dmanum; + int sb_16_8_dmanum; + int sb_16_dma_enabled; + int sb_16_dma_supported; + int sb_16_dma_translate; + int sb_pausetime; + int (*dma_readb)(void *priv); + int (*dma_readw)(void *priv); + int (*dma_writeb)(void *priv, uint8_t val); + int (*dma_writew)(void *priv, uint16_t val); + void *dma_priv; - uint8_t sb_read_data[256]; - int sb_read_wp, sb_read_rp; - int sb_speaker; - int muted; + uint8_t sb_read_data[256]; + int sb_read_wp; + int sb_read_rp; + int sb_speaker; + int muted; - int sb_data_stat; + int sb_data_stat; - int midi_in_sysex; - int midi_in_poll; - int uart_midi; - int uart_irq; - int onebyte_midi; - int midi_in_timestamp; + int midi_in_sysex; + int midi_in_poll; + int uart_midi; + int uart_irq; + int onebyte_midi; + int midi_in_timestamp; - int sb_irqnum; + int sb_irqnum; + void (*irq_update)(void *priv, int set); + void *irq_priv; - uint8_t sbe2; - int sbe2count; + uint8_t sbe2; + int sbe2count; - uint8_t sb_data[8]; + uint8_t sb_data[8]; - int sb_freq; + int sb_freq; - int16_t sbdat; - int sbdat2; - int16_t sbdatl, sbdatr; + int16_t sbdat; + int sbdat2; + int16_t sbdatl; + int16_t sbdatr; - uint8_t sbref; - int8_t sbstep; + uint8_t sbref; + int8_t sbstep; - int sbdacpos; + int sbdacpos; - int sbleftright; + int sbleftright; + int sbleftright_default; - int sbreset; - uint8_t sbreaddat; - uint8_t sb_command; - uint8_t sb_test; - int sb_timei, sb_timeo; + int sbreset; + uint8_t sbreaddat; + uint8_t sb_command; + uint8_t sb_test; + int sb_timei; + int sb_timeo; - int sb_irq8, sb_irq16, sb_irq401; - int sb_irqm8, sb_irqm16, sb_irqm401; + int sb_irq8; + int sb_irq16; + int sb_irq401; + int sb_irqm8; + int sb_irqm16; + int sb_irqm401; - uint8_t sb_asp_regs[256]; - uint8_t sb_asp_mode; + uint8_t sb_asp_regs[256]; + uint8_t sb_asp_mode; - uint8_t sb_asp_ram[2048]; - int sb_asp_ram_index; + uint8_t sb_asp_ram[2048]; + int sb_asp_ram_index; - uint8_t sb_8051_ram[256]; + uint8_t sb_8051_ram[256]; - int sbenable, sb_enable_i; + int sbenable; + int sb_enable_i; - pc_timer_t output_timer, input_timer; + pc_timer_t output_timer; + pc_timer_t input_timer; - uint64_t sblatcho, sblatchi; + double sblatcho; + double sblatchi; - uint16_t sb_addr; + uint16_t sb_addr; - int stereo; + int stereo; - int asp_data_len; + int asp_data_len; - pc_timer_t wb_timer; - int wb_full; + pc_timer_t wb_timer; + int wb_full; - int busy_count; + int busy_count; - int record_pos_read; - int record_pos_write; - int16_t record_buffer[0xFFFF]; - int16_t buffer[SOUNDBUFLEN * 2]; - int pos; + int record_pos_read; + int record_pos_write; + int16_t record_buffer[0xFFFF]; + int16_t buffer[SOUNDBUFLEN * 2]; + int pos; - uint8_t azt_eeprom[AZTECH_EEPROM_SIZE]; /* the eeprom in the Aztech cards is attached to the DSP */ + uint8_t azt_eeprom[AZTECH_EEPROM_SIZE]; /* the eeprom in the Aztech cards is attached to the DSP */ - mpu_t *mpu; + mpu_t *mpu; } sb_dsp_t; +extern void sb_dsp_input_msg(void *priv, uint8_t *msg, uint32_t len); -void sb_dsp_input_msg(void *p, uint8_t *msg, uint32_t len); +extern int sb_dsp_input_sysex(void *priv, uint8_t *buffer, uint32_t len, int abort); -int sb_dsp_input_sysex(void *p, uint8_t *buffer, uint32_t len, int abort); +extern void sb_dsp_set_mpu(sb_dsp_t *dsp, mpu_t *src_mpu); -void sb_dsp_set_mpu(sb_dsp_t *dsp, mpu_t *src_mpu); +extern void sb_dsp_init(sb_dsp_t *dsp, int type, int subtype, void *parent); +extern void sb_dsp_close(sb_dsp_t *dsp); -void sb_dsp_init(sb_dsp_t *dsp, int type, int subtype, void *parent); -void sb_dsp_close(sb_dsp_t *dsp); +extern void sb_dsp_setirq(sb_dsp_t *dsp, int irq); +extern void sb_dsp_setdma8(sb_dsp_t *dsp, int dma); +extern void sb_dsp_setdma16(sb_dsp_t *dsp, int dma); +extern void sb_dsp_setdma16_8(sb_dsp_t *dsp, int dma); +extern void sb_dsp_setdma16_enabled(sb_dsp_t *dsp, int enabled); +extern void sb_dsp_setdma16_supported(sb_dsp_t *dsp, int supported); +extern void sb_dsp_setdma16_translate(sb_dsp_t *dsp, int translate); +extern void sb_dsp_setaddr(sb_dsp_t *dsp, uint16_t addr); -void sb_dsp_setirq(sb_dsp_t *dsp, int irq); -void sb_dsp_setdma8(sb_dsp_t *dsp, int dma); -void sb_dsp_setdma16(sb_dsp_t *dsp, int dma); -void sb_dsp_setaddr(sb_dsp_t *dsp, uint16_t addr); +extern void sb_dsp_speed_changed(sb_dsp_t *dsp); -void sb_dsp_speed_changed(sb_dsp_t *dsp); +extern void sb_dsp_poll(sb_dsp_t *dsp, int16_t *l, int16_t *r); -void sb_dsp_poll(sb_dsp_t *dsp, int16_t *l, int16_t *r); +extern void sb_dsp_set_stereo(sb_dsp_t *dsp, int stereo); -void sb_dsp_set_stereo(sb_dsp_t *dsp, int stereo); +extern void sb_dsp_update(sb_dsp_t *dsp); +extern void sb_update_mask(sb_dsp_t *dsp, int irqm8, int irqm16, int irqm401); -void sb_dsp_update(sb_dsp_t *dsp); -void sb_update_mask(sb_dsp_t *dsp, int irqm8, int irqm16, int irqm401); +extern void sb_dsp_irq_attach(sb_dsp_t *dsp, void (*irq_update)(void *priv, int set), void *priv); +extern void sb_dsp_dma_attach(sb_dsp_t *dsp, + int (*dma_readb)(void *priv), + int (*dma_readw)(void *priv), + int (*dma_writeb)(void *priv, uint8_t val), + int (*dma_writew)(void *priv, uint16_t val), + void *priv); -#endif /* SOUND_SND_SB_DSP_H */ \ No newline at end of file +#endif /* SOUND_SND_SB_DSP_H */ diff --git a/src/include/86box/snd_sn76489.h b/src/include/86box/snd_sn76489.h index 01d19e0e5..6e7399d54 100644 --- a/src/include/86box/snd_sn76489.h +++ b/src/include/86box/snd_sn76489.h @@ -1,8 +1,10 @@ -enum -{ - SN76496, - NCR8496, - PSSJ +#ifndef SOUND_SN76489_H +#define SOUND_SN76489_H + +enum { + SN76496, + NCR8496, + PSSJ }; extern const device_t sn76489_device; @@ -10,24 +12,27 @@ extern const device_t ncr8496_device; extern int sn76489_mute; -typedef struct sn76489_t -{ - int stat[4]; - int latch[4], count[4]; - int freqlo[4], freqhi[4]; - int vol[4]; - uint32_t shift; - uint8_t noise; - int lasttone; - uint8_t firstdat; - int type; - int extra_divide; - - int16_t buffer[SOUNDBUFLEN]; - int pos; - - double psgconst; +typedef struct sn76489_t { + int stat[4]; + int latch[4]; + int count[4]; + int freqlo[4]; + int freqhi[4]; + int vol[4]; + uint32_t shift; + uint8_t noise; + int lasttone; + uint8_t firstdat; + int type; + int extra_divide; + + int16_t buffer[SOUNDBUFLEN]; + int pos; + + double psgconst; } sn76489_t; void sn76489_init(sn76489_t *sn76489, uint16_t base, uint16_t size, int type, int freq); void sn74689_set_extra_divide(sn76489_t *sn76489, int enable); + +#endif /*SOUND_SN76489_H*/ diff --git a/src/include/86box/snd_speaker.h b/src/include/86box/snd_speaker.h index 91e3edfe3..fa1a6fe19 100644 --- a/src/include/86box/snd_speaker.h +++ b/src/include/86box/snd_speaker.h @@ -1,28 +1,34 @@ /* - * 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. + * 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. + * This file is part of the 86Box distribution. * - * Header of the emulation of the PC speaker. + * Header of the emulation of the PC speaker. * * * - * Authors: Sarah Walker, - * Miran Grca, + * Authors: Sarah Walker, + * Miran Grca, * - * Copyright 2008-2019 Sarah Walker. - * Copyright 2016-2019 Miran Grca. + * Copyright 2008-2019 Sarah Walker. + * Copyright 2016-2019 Miran Grca. */ -extern int speaker_mute; -extern int speaker_gated; -extern int speaker_enable, was_speaker_enable; +#ifndef SOUND_SPEAKER_H +#define SOUND_SPEAKER_H +extern int speaker_mute; -extern void speaker_init(); +extern int speaker_gated; +extern int speaker_enable; +extern int was_speaker_enable; -extern void speaker_set_count(uint8_t new_m, int new_count); -extern void speaker_update(void); +extern void speaker_init(void); + +extern void speaker_set_count(uint8_t new_m, int new_count); +extern void speaker_update(void); + +#endif /*SOUND_SPEAKER_H*/ diff --git a/src/include/86box/snd_ym7128.h b/src/include/86box/snd_ym7128.h index f71aa2f86..a0796b1fa 100644 --- a/src/include/86box/snd_ym7128.h +++ b/src/include/86box/snd_ym7128.h @@ -1,25 +1,36 @@ -typedef struct ym7128_t -{ - int a0, sci; - uint8_t dat; - - int reg_sel; - uint8_t regs[32]; - - int gl[8], gr[8]; - int vm, vc, vl, vr; - int c0, c1; - int t[9]; - - int16_t filter_dat; - int16_t prev_l, prev_r; - - int16_t delay_buffer[2400]; - int delay_pos; - - int16_t last_samp; +#ifndef SOUND_YM7128_H +#define SOUND_YM7128_H + +typedef struct ym7128_t { + int a0; + int sci; + uint8_t dat; + + int reg_sel; + uint8_t regs[32]; + + int gl[8]; + int gr[8]; + int vm; + int vc; + int vl; + int vr; + int c0; + int c1; + int t[9]; + + int16_t filter_dat; + int16_t prev_l; + int16_t prev_r; + + int16_t delay_buffer[2400]; + int delay_pos; + + int16_t last_samp; } ym7128_t; void ym7128_init(ym7128_t *ym7128); void ym7128_write(ym7128_t *ym7128, uint8_t val); void ym7128_apply(ym7128_t *ym7128, int16_t *buffer, int len); + +#endif /*SOUND_YM7128_H*/ diff --git a/src/include/86box/sound.h b/src/include/86box/sound.h index f7b3bca0a..60628ece8 100644 --- a/src/include/86box/sound.h +++ b/src/include/86box/sound.h @@ -1,78 +1,95 @@ /* - * 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. + * 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. + * This file is part of the 86Box distribution. * - * Sound emulation core. + * Sound emulation core. * * * - * Authors: Sarah Walker, - * Miran Grca, + * Authors: Sarah Walker, + * Miran Grca, * - * Copyright 2008-2018 Sarah Walker. - * Copyright 2016-2018 Miran Grca. + * Copyright 2008-2018 Sarah Walker. + * Copyright 2016-2018 Miran Grca. */ -#ifndef EMU_SOUND_H -# define EMU_SOUND_H +#ifndef EMU_SOUND_H +#define EMU_SOUND_H + +#define SOUND_CARD_MAX 4 /* currently we support up to 4 sound cards and a standalome MPU401 */ extern int sound_gain; -#define SOUNDBUFLEN (48000/50) +#define FREQ_44100 44100 +#define FREQ_48000 48000 +#define FREQ_49716 49716 +#define FREQ_88200 88200 +#define FREQ_96000 96000 -#define CD_FREQ 44100 -#define CD_BUFLEN (CD_FREQ / 10) +#define SOUND_FREQ FREQ_48000 +#define SOUNDBUFLEN (SOUND_FREQ / 50) +#define CD_FREQ FREQ_44100 +#define CD_BUFLEN (CD_FREQ / 10) enum { SOUND_NONE = 0, SOUND_INTERNAL }; +extern int ppispeakon; +extern int gated; +extern int speakval; +extern int speakon; -extern int ppispeakon; -extern int gated, - speakval, - speakon; +extern int sound_pos_global; +extern int sound_card_current[SOUND_CARD_MAX]; -extern int sound_pos_global; -extern int sound_card_current; +extern void sound_add_handler(void (*get_buffer)(int32_t *buffer, + int len, void *priv), + void *priv); +extern void sound_set_cd_audio_filter(void (*filter)(int channel, + double *buffer, void *priv), + void *priv); +extern void sound_set_pc_speaker_filter(void (*filter)(int channel, + double *buffer, void *priv), + void *priv); -extern void sound_add_handler(void (*get_buffer)(int32_t *buffer, \ - int len, void *p), void *p); -extern void sound_set_cd_audio_filter(void (*filter)(int channel, \ - double *buffer, void *p), void *p); +extern void (*filter_pc_speaker)(int channel, double *buffer, void *priv); +extern void *filter_pc_speaker_p; -extern int sound_card_available(int card); +extern int sound_card_available(int card); #ifdef EMU_DEVICE_H -extern const device_t *sound_card_getdevice(int card); +extern const device_t *sound_card_getdevice(int card); #endif -extern int sound_card_has_config(int card); -extern char *sound_card_get_internal_name(int card); -extern int sound_card_get_from_internal_name(char *s); -extern void sound_card_init(void); -extern void sound_set_cd_volume(unsigned int vol_l, unsigned int vol_r); +extern int sound_card_has_config(int card); +extern const char *sound_card_get_internal_name(int card); +extern int sound_card_get_from_internal_name(const char *s); +extern void sound_card_init(void); +extern void sound_set_cd_volume(unsigned int vol_l, unsigned int vol_r); -extern void sound_speed_changed(void); +extern void sound_speed_changed(void); -extern void sound_init(void); -extern void sound_reset(void); +extern void sound_init(void); +extern void sound_reset(void); -extern void sound_card_reset(void); +extern void sound_card_reset(void); -extern void sound_cd_thread_end(void); -extern void sound_cd_thread_reset(void); +extern void sound_cd_thread_end(void); +extern void sound_cd_thread_reset(void); -extern void closeal(void); -extern void inital(void); -extern void givealbuffer(void *buf); -extern void givealbuffer_cd(void *buf); +extern void closeal(void); +extern void inital(void); +extern void givealbuffer(void *buf); +extern void givealbuffer_cd(void *buf); +#define sb_vibra16c_onboard_relocate_base sb_vibra16s_onboard_relocate_base +extern void sb_vibra16s_onboard_relocate_base(uint16_t new_addr, void *priv); #ifdef EMU_DEVICE_H /* AdLib and AdLib Gold */ @@ -82,6 +99,8 @@ extern const device_t adgold_device; /* Aztech Sound Galaxy 16 */ extern const device_t azt2316a_device; +extern const device_t acermagic_s20_device; +extern const device_t mirosound_pcm10_device; extern const device_t azt1605_device; /* Ensoniq AudioPCI */ @@ -94,20 +113,20 @@ extern const device_t cms_device; /* Gravis UltraSound and UltraSound Max */ extern const device_t gus_device; -#if defined(DEV_BRANCH) && defined(USE_PAS16) +# if defined(DEV_BRANCH) && defined(USE_PAS16) /* Pro Audio Spectrum 16 */ extern const device_t pas16_device; -#endif +# endif /* IBM PS/1 Audio Card */ extern const device_t ps1snd_device; /* Tandy PSSJ */ extern const device_t pssj_device; -#if defined(DEV_BRANCH) && defined(USE_TANDY_ISA) extern const device_t pssj_isa_device; + +/* Tandy PSG */ extern const device_t tndy_device; -#endif /* Creative Labs Sound Blaster */ extern const device_t sb_1_device; @@ -119,7 +138,15 @@ extern const device_t sb_pro_v2_device; extern const device_t sb_pro_mcv_device; extern const device_t sb_pro_compat_device; extern const device_t sb_16_device; +extern const device_t sb_vibra16s_onboard_device; +extern const device_t sb_vibra16s_device; +extern const device_t sb_vibra16xv_device; +extern const device_t sb_vibra16c_onboard_device; +extern const device_t sb_vibra16c_device; extern const device_t sb_16_pnp_device; +extern const device_t sb_16_compat_device; +extern const device_t sb_16_compat_nompu_device; +extern const device_t sb_16_reply_mca_device; extern const device_t sb_32_pnp_device; extern const device_t sb_awe32_device; extern const device_t sb_awe32_pnp_device; @@ -135,9 +162,18 @@ extern const device_t wss_device; extern const device_t ncr_business_audio_device; /* Crystal CS423x */ +extern const device_t cs4235_device; +extern const device_t cs4235_onboard_device; extern const device_t cs4236b_device; extern const device_t cs4237b_device; extern const device_t cs4238b_device; + +/* C-Media CMI8x38 */ +extern const device_t cmi8338_device; +extern const device_t cmi8338_onboard_device; +extern const device_t cmi8738_device; +extern const device_t cmi8738_onboard_device; +extern const device_t cmi8738_6ch_onboard_device; #endif -#endif /*EMU_SOUND_H*/ +#endif /*EMU_SOUND_H*/ diff --git a/src/include/86box/spd.h b/src/include/86box/spd.h index 0e17d0da3..98eb4e178 100644 --- a/src/include/86box/spd.h +++ b/src/include/86box/spd.h @@ -1,114 +1,154 @@ /* - * 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. + * 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. + * This file is part of the 86Box distribution. * - * Emulation of SPD (Serial Presence Detect) devices. + * Emulation of SPD (Serial Presence Detect) devices. * * * - * Authors: RichardG, + * Authors: RichardG, * - * Copyright 2020 RichardG. + * Copyright 2020 RichardG. */ + #ifndef EMU_SPD_H -# define EMU_SPD_H +#define EMU_SPD_H +#define SPD_BASE_ADDR 0x50 +#define SPD_MAX_SLOTS 8 +#define SPD_DATA_SIZE 256 -#define SPD_BASE_ADDR 0x50 -#define SPD_MAX_SLOTS 8 -#define SPD_DATA_SIZE 256 +#define SPD_TYPE_FPM 0x01 +#define SPD_TYPE_EDO 0x02 +#define SPD_TYPE_SDRAM 0x04 -#define SPD_TYPE_FPM 0x01 -#define SPD_TYPE_EDO 0x02 -#define SPD_TYPE_SDRAM 0x04 +#define SPD_MIN_SIZE_EDO 8 +#define SPD_MIN_SIZE_SDRAM 8 -#define SPD_MIN_SIZE_EDO 8 -#define SPD_MIN_SIZE_SDRAM 8 +#define SPD_SIGNAL_LVTTL 0x01 -#define SPD_SIGNAL_LVTTL 0x01 +#define SPD_REFRESH_NORMAL 0x00 +#define SPD_SDR_REFRESH_SELF 0x80 -#define SPD_REFRESH_NORMAL 0x00 -#define SPD_SDR_REFRESH_SELF 0x80 +#define SPD_SDR_BURST_PAGE 0x80 -#define SPD_SDR_BURST_PAGE 0x80 +#define SPD_SDR_ATTR_BUFFERED 0x01 +#define SPD_SDR_ATTR_REGISTERED 0x02 -#define SPD_SDR_ATTR_BUFFERED 0x01 -#define SPD_SDR_ATTR_REGISTERED 0x02 +#define SPD_SDR_ATTR_EARLY_RAS 0x01 +#define SPD_SDR_ATTR_AUTO_PC 0x02 +#define SPD_SDR_ATTR_PC_ALL 0x04 +#define SPD_SDR_ATTR_W1R_BURST 0x08 +#define SPD_SDR_ATTR_VCC_LOW_5 0x10 +#define SPD_SDR_ATTR_VCC_HI_5 0x20 -#define SPD_SDR_ATTR_EARLY_RAS 0x01 -#define SPD_SDR_ATTR_AUTO_PC 0x02 -#define SPD_SDR_ATTR_PC_ALL 0x04 -#define SPD_SDR_ATTR_W1R_BURST 0x08 -#define SPD_SDR_ATTR_VCC_LOW_5 0x10 -#define SPD_SDR_ATTR_VCC_HI_5 0x20 - - -typedef struct { - uint8_t bytes_used, spd_size, mem_type, - row_bits, col_bits, banks, - data_width_lsb, data_width_msb, - signal_level, trac, tcac, - config, refresh_rate, - dram_width, ecc_width, - reserved[47], - spd_rev, checksum, - mfg_jedec[8], mfg_loc; - char part_no[18]; - uint8_t rev_code[2], - mfg_year, mfg_week, serial[4], mfg_specific[27], - vendor_specific[2], - other_data[127], - checksum2; +typedef struct spd_edo_t { + uint8_t bytes_used; + uint8_t spd_size; + uint8_t mem_type; + uint8_t row_bits; + uint8_t col_bits; + uint8_t banks; + uint8_t data_width_lsb; + uint8_t data_width_msb; + uint8_t signal_level; + uint8_t trac; + uint8_t tcac; + uint8_t config; + uint8_t refresh_rate; + uint8_t dram_width; + uint8_t ecc_width; + uint8_t reserved[47]; + uint8_t spd_rev; + uint8_t checksum; + uint8_t mfg_jedec[8]; + uint8_t mfg_loc; + char part_no[18]; + uint8_t rev_code[2]; + uint8_t mfg_year; + uint8_t mfg_week; + uint8_t serial[4]; + uint8_t mfg_specific[27]; + uint8_t vendor_specific[2]; + uint8_t other_data[127]; + uint8_t checksum2; } spd_edo_t; -typedef struct { - uint8_t bytes_used, spd_size, mem_type, - row_bits, col_bits, rows, - data_width_lsb, data_width_msb, - signal_level, tclk, tac, - config, refresh_rate, - sdram_width, ecc_width, - tccd, burst, banks, cas, cslat, we, - mod_attr, dev_attr, - tclk2, tac2, tclk3, tac3, - trp, trrd, trcd, tras, - bank_density, - ca_setup, ca_hold, data_setup, data_hold, - reserved[26], - spd_rev, checksum, - mfg_jedec[8], mfg_loc; - char part_no[18]; - uint8_t rev_code[2], - mfg_year, mfg_week, serial[4], mfg_specific[27], - freq, features, - other_data[127], - checksum2; +typedef struct spd_sdram_t { + uint8_t bytes_used; + uint8_t spd_size; + uint8_t mem_type; + uint8_t row_bits; + uint8_t col_bits; + uint8_t rows; + uint8_t data_width_lsb; + uint8_t data_width_msb; + uint8_t signal_level; + uint8_t tclk; + uint8_t tac; + uint8_t config; + uint8_t refresh_rate; + uint8_t sdram_width; + uint8_t ecc_width; + uint8_t tccd; + uint8_t burst; + uint8_t banks; + uint8_t cas; + uint8_t cslat; + uint8_t we; + uint8_t mod_attr; + uint8_t dev_attr; + uint8_t tclk2; + uint8_t tac2; + uint8_t tclk3; + uint8_t tac3; + uint8_t trp; + uint8_t trrd; + uint8_t trcd; + uint8_t tras; + uint8_t bank_density; + uint8_t ca_setup; + uint8_t ca_hold; + uint8_t data_setup; + uint8_t data_hold; + uint8_t reserved[26]; + uint8_t spd_rev, checksum; + uint8_t mfg_jedec[8]; + uint8_t mfg_loc; + char part_no[18]; + uint8_t rev_code[2]; + uint8_t mfg_year; + uint8_t mfg_week; + uint8_t serial[4]; + uint8_t mfg_specific[27]; + uint8_t freq; + uint8_t features; + uint8_t other_data[127]; + uint8_t checksum2; } spd_sdram_t; -typedef struct { - uint8_t slot; - uint16_t size; - uint16_t row1; - uint16_t row2; +typedef struct spd_t { + uint8_t slot; + uint16_t size; + uint16_t row1; + uint16_t row2; union { - uint8_t data[SPD_DATA_SIZE]; - spd_edo_t edo_data; - spd_sdram_t sdram_data; + uint8_t data[SPD_DATA_SIZE]; + spd_edo_t edo_data; + spd_sdram_t sdram_data; }; - void *eeprom; + void *eeprom; } spd_t; - extern void spd_register(uint8_t ram_type, uint8_t slot_mask, uint16_t max_module_size); extern void spd_write_drbs(uint8_t *regs, uint8_t reg_min, uint8_t reg_max, uint8_t drb_unit); extern void spd_write_drbs_with_ext(uint8_t *regs, uint8_t reg_min, uint8_t reg_max, uint8_t drb_unit); extern void spd_write_drbs_interleaved(uint8_t *regs, uint8_t reg_min, uint8_t reg_max, uint8_t drb_unit); extern void spd_write_drbs_ali1621(uint8_t *regs, uint8_t reg_min, uint8_t reg_max); - -#endif /*EMU_SPD_H*/ +#endif /*EMU_SPD_H*/ diff --git a/src/include/86box/thread.h b/src/include/86box/thread.h new file mode 100644 index 000000000..4d5584787 --- /dev/null +++ b/src/include/86box/thread.h @@ -0,0 +1,69 @@ +/* + * 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. + * + * Thread API header. + * + * + * + * Authors: Sarah Walker, + * Miran Grca, + * + * Copyright 2008-2023 Sarah Walker. + * Copyright 2016-2023 Miran Grca. + */ +#ifndef THREAD_H +# define THREAD_H + +#ifdef __cplusplus +extern "C" { +#endif + +#ifdef __APPLE__ +# define thread_t plat_thread_t +# define event_t plat_event_t +# define mutex_t plat_mutex_t + +# define thread_create plat_thread_create +# define thread_wait plat_thread_wait +# define thread_create_event plat_thread_create_event +# define thread_set_event plat_thread_set_event +# define thread_reset_event plat_thread_reset_event +# define thread_wait_event plat_thread_wait_event +# define thread_destroy_event plat_thread_destroy_event + +# define thread_create_mutex plat_thread_create_mutex +# define thread_create_mutex_with_spin_count plat_thread_create_mutex_with_spin_count +# define thread_close_mutex plat_thread_close_mutex +# define thread_wait_mutex plat_thread_wait_mutex +# define thread_release_mutex plat_thread_release_mutex +#endif + +/* Thread support. */ +typedef void thread_t; +typedef void event_t; +typedef void mutex_t; + +extern thread_t *thread_create(void (*thread_func)(void *param), void *param); +extern int thread_wait(thread_t *arg); +extern event_t *thread_create_event(void); +extern void thread_set_event(event_t *arg); +extern void thread_reset_event(event_t *arg); +extern int thread_wait_event(event_t *arg, int timeout); +extern void thread_destroy_event(event_t *arg); + +extern mutex_t *thread_create_mutex(void); +extern void thread_close_mutex(mutex_t *arg); +extern int thread_test_mutex(mutex_t *arg); +extern int thread_wait_mutex(mutex_t *arg); +extern int thread_release_mutex(mutex_t *mutex); + +#ifdef __cplusplus +} +#endif + +#endif /*THREAD_H*/ diff --git a/src/include/86box/timer.h b/src/include/86box/timer.h index 6c5531bd9..4ade8aab0 100644 --- a/src/include/86box/timer.h +++ b/src/include/86box/timer.h @@ -4,33 +4,30 @@ #include "cpu.h" /* Maximum period, currently 1 second. */ -#define MAX_USEC64 1000000ULL -#define MAX_USEC 1000000.0 +#define MAX_USEC64 1000000ULL +#define MAX_USEC 1000000.0 -#define TIMER_SPLIT 2 -#define TIMER_ENABLED 1 +#define TIMER_PROCESS 4 +#define TIMER_SPLIT 2 +#define TIMER_ENABLED 1 - -#pragma pack(push,1) -typedef struct -{ +#pragma pack(push, 1) +typedef struct ts_struct_t { uint32_t frac; uint32_t integer; } ts_struct_t; #pragma pack(pop) -typedef union -{ - uint64_t ts64; - ts_struct_t ts32; +typedef union ts_t { + uint64_t ts64; + ts_struct_t ts32; } ts_t; - /*Timers are based on the CPU Time Stamp Counter. Timer timestamps are in a 32:32 fixed point format, with the integer part compared against the TSC. The fractional part is used when advancing the timestamp to ensure a more accurate period. - + As the timer only stores 32 bits of integer timestamp, and the TSC is 64 bits, the timer period can only be at most 0x7fffffff CPU cycles. To allow room for (optimistic) CPU frequency growth, timer period must be at most 1 second. @@ -38,54 +35,58 @@ typedef union When a timer callback is called, the timer has been disabled. If the timer is to repeat, the callback must call timer_advance_u64(). This is a change from the old timer API.*/ -typedef struct pc_timer_t -{ +typedef struct pc_timer_t { #ifdef USE_PCEM_TIMER - uint32_t ts_integer; - uint32_t ts_frac; + uint32_t ts_integer; + uint32_t ts_frac; #else - ts_t ts; + ts_t ts; #endif - int flags, pad; /* The flags are defined above. */ - double period; /* This is used for large period timers to count - the microseconds and split the period. */ + int flags; /* The flags are defined above. */ + int pad; + double period; /* This is used for large period timers to count + the microseconds and split the period. */ - void (*callback)(void *p); - void *p; + void (*callback)(void *priv); + void *priv; - struct pc_timer_t *prev, *next; + struct pc_timer_t *prev; + struct pc_timer_t *next; } pc_timer_t; +#ifdef __cplusplus +extern "C" { +#endif + /*Timestamp of nearest enabled timer. CPU emulation must call timer_process() when TSC matches or exceeds this.*/ -extern uint32_t timer_target; +extern uint32_t timer_target; /*Enable timer, without updating timestamp*/ -extern void timer_enable(pc_timer_t *timer); +extern void timer_enable(pc_timer_t *timer); /*Disable timer*/ -extern void timer_disable(pc_timer_t *timer); +extern void timer_disable(pc_timer_t *timer); /*Process any pending timers*/ -extern void timer_process(void); +extern void timer_process(void); /*Reset timer system*/ -extern void timer_close(void); -extern void timer_init(void); +extern void timer_close(void); +extern void timer_init(void); /*Add new timer. If start_timer is set, timer will be enabled with a zero timestamp - this is useful for permanently enabled timers*/ -extern void timer_add(pc_timer_t *timer, void (*callback)(void *p), void *p, int start_timer); +extern void timer_add(pc_timer_t *timer, void (*callback)(void *priv), void *priv, int start_timer); /*1us in 32:32 format*/ -extern uint64_t TIMER_USEC; +extern uint64_t TIMER_USEC; /*True if timer a expires before timer b*/ -#define TIMER_LESS_THAN(a, b) ((int64_t)((a)->ts.ts64 - (b)->ts.ts64) <= 0) +#define TIMER_LESS_THAN(a, b) ((int64_t) ((a)->ts.ts64 - (b)->ts.ts64) <= 0) /*True if timer a expires before 32 bit integer timestamp b*/ -#define TIMER_LESS_THAN_VAL(a, b) ((int32_t)((a)->ts.ts32.integer - (b)) <= 0) +#define TIMER_LESS_THAN_VAL(a, b) ((int32_t) ((a)->ts.ts32.integer - (b)) <= 0) /*True if 32 bit integer timestamp a expires before 32 bit integer timestamp b*/ -#define TIMER_VAL_LESS_THAN_VAL(a, b) ((int32_t)((a) - (b)) <= 0) - +#define TIMER_VAL_LESS_THAN_VAL(a, b) ((int32_t) ((a) - (b)) <= 0) /*Advance timer by delay, specified in 32:32 format. This should be used to resume a recurring timer in a callback routine*/ @@ -97,20 +98,18 @@ timer_advance_u64(pc_timer_t *timer, uint64_t delay) timer_enable(timer); } - /*Set a timer to the given delay, specified in 32:32 format. This should be used when starting a timer*/ static __inline void timer_set_delay_u64(pc_timer_t *timer, uint64_t delay) { - timer->ts.ts64 = 0ULL; + timer->ts.ts64 = 0ULL; timer->ts.ts32.integer = tsc; timer->ts.ts64 += delay; timer_enable(timer); } - /*True if timer currently enabled*/ static __inline int timer_is_enabled(pc_timer_t *timer) @@ -118,6 +117,12 @@ timer_is_enabled(pc_timer_t *timer) return !!(timer->flags & TIMER_ENABLED); } +/*True if timer currently on*/ +static __inline int +timer_is_on(pc_timer_t *timer) +{ + return ((timer->flags & TIMER_SPLIT) && (timer->flags & TIMER_ENABLED)); +} /*Return integer timestamp of timer*/ static __inline uint32_t @@ -126,7 +131,6 @@ timer_get_ts_int(pc_timer_t *timer) return timer->ts.ts32.integer; } - /*Return remaining time before timer expires, in us. If the timer has already expired then return 0*/ static __inline uint32_t @@ -135,17 +139,16 @@ timer_get_remaining_us(pc_timer_t *timer) int64_t remaining; if (timer->flags & TIMER_ENABLED) { - remaining = (int64_t) (timer->ts.ts64 - (uint64_t)(tsc << 32)); + remaining = (int64_t) (timer->ts.ts64 - (uint64_t) (tsc << 32)); - if (remaining < 0) - return 0; - return remaining / TIMER_USEC; + if (remaining < 0) + return 0; + return remaining / TIMER_USEC; } return 0; } - /*Return remaining time before timer expires, in 32:32 timestamp format. If the timer has already expired then return 0*/ static __inline uint64_t @@ -154,87 +157,36 @@ timer_get_remaining_u64(pc_timer_t *timer) int64_t remaining; if (timer->flags & TIMER_ENABLED) { - remaining = (int64_t) (timer->ts.ts64 - (uint64_t)(tsc << 32)); + remaining = (int64_t) (timer->ts.ts64 - (uint64_t) (tsc << 32)); - if (remaining < 0) - return 0; - return remaining; + if (remaining < 0) + return 0; + return remaining; } return 0; } - /*Set timer callback function*/ static __inline void -timer_set_callback(pc_timer_t *timer, void (*callback)(void *p)) +timer_set_callback(pc_timer_t *timer, void (*callback)(void *priv)) { timer->callback = callback; } - /*Set timer private data*/ static __inline void -timer_set_p(pc_timer_t *timer, void *p) +timer_set_p(pc_timer_t *timer, void *priv) { - timer->p = p; + timer->priv = priv; } - /* The API for big timer periods starts here. */ -extern void timer_stop(pc_timer_t *timer); -extern void timer_advance_ex(pc_timer_t *timer, int start); -extern void timer_on(pc_timer_t *timer, double period, int start); -extern void timer_on_auto(pc_timer_t *timer, double period); +extern void timer_stop(pc_timer_t *timer); +extern void timer_on_auto(pc_timer_t *timer, double period); -extern void timer_remove_head(void); - - -extern pc_timer_t * timer_head; -extern int timer_inited; - - -static __inline void -timer_remove_head_inline(void) -{ - pc_timer_t *timer; - - if (timer_inited && timer_head) { - timer = timer_head; - timer_head = timer->next; - if (timer_head) { - timer_head->prev = NULL; - timer->next->prev = NULL; - } - timer->next = timer->prev = NULL; - timer->flags &= ~TIMER_ENABLED; - } -} - - -static __inline void -timer_process_inline(void) -{ - pc_timer_t *timer; - - if (!timer_inited || !timer_head) - return; - - while(1) { - timer = timer_head; - - if (!TIMER_LESS_THAN_VAL(timer, (uint32_t)tsc)) - break; - - timer_remove_head_inline(); - - if (timer->flags & TIMER_SPLIT) - timer_advance_ex(timer, 0); /* We're splitting a > 1 s period into multiple <= 1 s periods. */ - else if (timer->callback != NULL) /* Make sure it's no NULL, so that we can have a NULL callback when no operation is needed. */ - timer->callback(timer->p); - } - - timer_target = timer_head->ts.ts32.integer; +#ifdef __cplusplus } +#endif #endif /*_TIMER_H_*/ diff --git a/src/include/86box/ui.h b/src/include/86box/ui.h index 61e251eeb..9698f896c 100644 --- a/src/include/86box/ui.h +++ b/src/include/86box/ui.h @@ -1,84 +1,84 @@ /* - * 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. + * 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. + * This file is part of the 86Box distribution. * - * Define the various UI functions. + * Define the various UI functions. * * * - * Authors: Miran Grca, - * Fred N. van Kempen, + * Authors: Miran Grca, + * Fred N. van Kempen, * - * Copyright 2016-2019 Miran Grca. - * Copyright 2017-2019 Fred N. van Kempen. + * Copyright 2016-2019 Miran Grca. + * Copyright 2017-2019 Fred N. van Kempen. */ #ifndef EMU_UI_H -# define EMU_UI_H - +#define EMU_UI_H #ifdef __cplusplus extern "C" { #endif - #ifdef USE_WX -# define RENDER_FPS 30 /* default render speed */ +# define RENDER_FPS 30 /* default render speed */ #endif /* Message Box functions. */ -#define MBX_INFO 1 -#define MBX_ERROR 2 -#define MBX_QUESTION 3 -#define MBX_QUESTION_YN 4 -#define MBX_QUESTION_OK 8 -#define MBX_QMARK 0x10 -#define MBX_WARNING 0x20 -#define MBX_FATAL 0x40 -#define MBX_ANSI 0x80 -#define MBX_LINKS 0x100 -#define MBX_DONTASK 0x200 +#define MBX_INFO 1 +#define MBX_ERROR 2 +#define MBX_QUESTION 3 +#define MBX_QUESTION_YN 4 +#define MBX_QUESTION_OK 8 +#define MBX_QMARK 0x10 +#define MBX_WARNING 0x20 +#define MBX_FATAL 0x40 +#define MBX_ANSI 0x80 +#define MBX_LINKS 0x100 +#define MBX_DONTASK 0x200 -extern int ui_msgbox(int flags, void *message); -extern int ui_msgbox_header(int flags, void *header, void *message); -extern int ui_msgbox_ex(int flags, void *header, void *message, void *btn1, void *btn2, void *btn3); +extern int ui_msgbox(int flags, void *message); +extern int ui_msgbox_header(int flags, void *header, void *message); +extern int ui_msgbox_ex(int flags, void *header, void *message, void *btn1, void *btn2, void *btn3); -extern void ui_check_menu_item(int id, int checked); +extern void ui_check_menu_item(int id, int checked); /* Status Bar functions. */ -#define SB_ICON_WIDTH 24 -#define SB_CASSETTE 0x00 -#define SB_CARTRIDGE 0x10 -#define SB_FLOPPY 0x20 -#define SB_CDROM 0x30 -#define SB_ZIP 0x40 -#define SB_MO 0x50 -#define SB_HDD 0x60 -#define SB_NETWORK 0x70 -#define SB_SOUND 0x80 -#define SB_TEXT 0x90 +#define SB_ICON_WIDTH 24 +#define SB_CASSETTE 0x00 +#define SB_CARTRIDGE 0x10 +#define SB_FLOPPY 0x20 +#define SB_CDROM 0x30 +#define SB_ZIP 0x40 +#define SB_MO 0x50 +#define SB_HDD 0x60 +#define SB_NETWORK 0x70 +#define SB_SOUND 0x80 +#define SB_TEXT 0x90 -extern wchar_t *ui_window_title(wchar_t *s); -extern void ui_status_update(void); -extern int ui_sb_find_part(int tag); -extern void ui_sb_set_ready(int ready); -extern void ui_sb_update_panes(void); -extern void ui_sb_update_text(void); -extern void ui_sb_update_tip(int meaning); -extern void ui_sb_timer_callback(int pane); -extern void ui_sb_update_icon(int tag, int val); -extern void ui_sb_update_icon_state(int tag, int active); -extern void ui_sb_set_text_w(wchar_t *wstr); -extern void ui_sb_set_text(char *str); -extern void ui_sb_bugui(char *str); -extern void ui_sb_mt32lcd(char *str); +extern wchar_t *ui_window_title(wchar_t *s); +extern void ui_status_update(void); +extern void ui_hard_reset_completed(void); +extern void ui_init_monitor(int monitor_index); +extern void ui_deinit_monitor(int monitor_index); +extern int ui_sb_find_part(int tag); +extern void ui_sb_set_ready(int ready); +extern void ui_sb_update_panes(void); +extern void ui_sb_update_text(void); +extern void ui_sb_update_tip(int meaning); +extern void ui_sb_timer_callback(int pane); +extern void ui_sb_update_icon(int tag, int active); +extern void ui_sb_update_icon_state(int tag, int state); +extern void ui_sb_set_text_w(wchar_t *wstr); +extern void ui_sb_set_text(char *str); +extern void ui_sb_bugui(char *str); +extern void ui_sb_mt32lcd(char *str); #ifdef __cplusplus } #endif - -#endif /*EMU_UI_H*/ +#endif /*EMU_UI_H*/ diff --git a/src/include/86box/unix_sdl.h b/src/include/86box/unix_sdl.h index 7019f0b85..27d7ec0aa 100644 --- a/src/include/86box/unix_sdl.h +++ b/src/include/86box/unix_sdl.h @@ -1,12 +1,14 @@ #ifndef _UNIX_SDL_H #define _UNIX_SDL_H -extern void sdl_close(void); -extern int sdl_inits(); -extern int sdl_inith(); -extern int sdl_initho(); -extern int sdl_pause(void); -extern void sdl_resize(int x, int y); -extern void sdl_enable(int enable); -extern void sdl_set_fs(int fs); -extern void sdl_reload(void); -#endif \ No newline at end of file + +extern void sdl_close(void); +extern int sdl_inits(void); +extern int sdl_inith(void); +extern int sdl_initho(void); +extern int sdl_pause(void); +extern void sdl_resize(int x, int y); +extern void sdl_enable(int enable); +extern void sdl_set_fs(int fs); +extern void sdl_reload(void); + +#endif /*_UNIX_SDL_H*/ diff --git a/src/include/86box/usb.h b/src/include/86box/usb.h index 375fc89e7..623746829 100644 --- a/src/include/86box/usb.h +++ b/src/include/86box/usb.h @@ -14,35 +14,33 @@ * * Copyright 2020 Miran Grca. */ -#ifndef USB_H -# define USB_H +#ifndef USB_H +#define USB_H #ifdef __cplusplus extern "C" { #endif -typedef struct -{ - uint8_t uhci_io[32], ohci_mmio[4096]; - uint16_t uhci_io_base; - int uhci_enable, ohci_enable; - uint32_t ohci_mem_base; - mem_mapping_t ohci_mmio_mapping; +typedef struct usb_t { + uint8_t uhci_io[32]; + uint8_t ohci_mmio[4096]; + uint16_t uhci_io_base; + int uhci_enable; + int ohci_enable; + uint32_t ohci_mem_base; + mem_mapping_t ohci_mmio_mapping; } usb_t; - /* Global variables. */ -extern const device_t usb_device; - +extern const device_t usb_device; /* Functions. */ -extern void uhci_update_io_mapping(usb_t *dev, uint8_t base_l, uint8_t base_h, int enable); -extern void ohci_update_mem_mapping(usb_t *dev, uint8_t base1, uint8_t base2, uint8_t base3, int enable); +extern void uhci_update_io_mapping(usb_t *dev, uint8_t base_l, uint8_t base_h, int enable); +extern void ohci_update_mem_mapping(usb_t *dev, uint8_t base1, uint8_t base2, uint8_t base3, int enable); #ifdef __cplusplus } #endif - -#endif /*USB_H*/ +#endif /*USB_H*/ diff --git a/src/include/86box/version.h.in b/src/include/86box/version.h.in index 18ff9a00e..5ebf7dba9 100644 --- a/src/include/86box/version.h.in +++ b/src/include/86box/version.h.in @@ -1,58 +1,60 @@ /* - * 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. + * 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. + * This file is part of the 86Box distribution. * - * Definitions for project version, branding, and external links. + * Definitions for project version, branding, and external links. * - * Authors: Miran Grca, * - * Copyright 2020 Miran Grca. + * + * Authors: Miran Grca, + * + * Copyright 2020 Miran Grca. */ #define _LSTR(s) L ## s #define LSTR(s) _LSTR(s) /* Version info. */ -#define EMU_NAME "@CMAKE_PROJECT_NAME@" -#define EMU_NAME_W LSTR(EMU_NAME) +#define EMU_NAME "@CMAKE_PROJECT_NAME@" +#define EMU_NAME_W LSTR(EMU_NAME) -#define EMU_VERSION "@CMAKE_PROJECT_VERSION@" -#define EMU_VERSION_W LSTR(EMU_VERSION) -#define EMU_VERSION_EX "@CMAKE_PROJECT_VERSION_MAJOR@.@CMAKE_PROJECT_VERSION_MINOR@@CMAKE_PROJECT_VERSION_PATCH@" -#define EMU_VERSION_MAJ @CMAKE_PROJECT_VERSION_MAJOR@ -#define EMU_VERSION_MIN @CMAKE_PROJECT_VERSION_MINOR@ +#define EMU_VERSION "@CMAKE_PROJECT_VERSION@" +#define EMU_VERSION_W LSTR(EMU_VERSION) +#define EMU_VERSION_EX "3.50" /* frozen due to IDE re-detection behavior on Windows */ +#define EMU_VERSION_MAJ @CMAKE_PROJECT_VERSION_MAJOR@ +#define EMU_VERSION_MIN @CMAKE_PROJECT_VERSION_MINOR@ #define EMU_VERSION_PATCH @CMAKE_PROJECT_VERSION_PATCH@ -#cmakedefine EMU_BUILD "@EMU_BUILD@" -#define EMU_BUILD_NUM @EMU_BUILD_NUM@ -#cmakedefine EMU_GIT_HASH "@EMU_GIT_HASH@" +#cmakedefine EMU_BUILD "@EMU_BUILD@" +#define EMU_BUILD_NUM @EMU_BUILD_NUM@ +#cmakedefine EMU_GIT_HASH "@EMU_GIT_HASH@" #ifdef EMU_BUILD -# define EMU_BUILD_W LSTR(EMU_BUILD) -# define EMU_VERSION_FULL EMU_VERSION " [" EMU_BUILD "]" -# define EMU_VERSION_FULL_W EMU_VERSION_W L" [" EMU_BUILD_W L"]" +# define EMU_BUILD_W LSTR(EMU_BUILD) +# define EMU_VERSION_FULL EMU_VERSION " [" EMU_BUILD "]" +# define EMU_VERSION_FULL_W EMU_VERSION_W L" [" EMU_BUILD_W L"]" #else -# define EMU_VERSION_FULL EMU_VERSION -# define EMU_VERSION_FULL_W EMU_VERSION_W +# define EMU_VERSION_FULL EMU_VERSION +# define EMU_VERSION_FULL_W EMU_VERSION_W #endif #ifdef EMU_GIT_HASH -# define EMU_GIT_HASH_W LSTR(EMU_GIT_HASH) +# define EMU_GIT_HASH_W LSTR(EMU_GIT_HASH) #endif -#define COPYRIGHT_YEAR "@EMU_COPYRIGHT_YEAR@" +#define COPYRIGHT_YEAR "@EMU_COPYRIGHT_YEAR@" /* Web URL info. */ -#define EMU_SITE "86box.net" -#define EMU_SITE_W LSTR(EMU_SITE) -#define EMU_ROMS_URL "https://github.com/86Box/roms/releases/latest" -#define EMU_ROMS_URL_W LSTR(EMU_ROMS_URL) +#define EMU_SITE "86box.net" +#define EMU_SITE_W LSTR(EMU_SITE) +#define EMU_ROMS_URL "https://github.com/86Box/roms/releases/latest" +#define EMU_ROMS_URL_W LSTR(EMU_ROMS_URL) #ifdef RELEASE_BUILD -# define EMU_DOCS_URL "https://86box.readthedocs.io/en/v@CMAKE_PROJECT_VERSION_MAJOR@.@CMAKE_PROJECT_VERSION_MINOR@/" +# define EMU_DOCS_URL "https://86box.readthedocs.io/en/v@CMAKE_PROJECT_VERSION_MAJOR@.@CMAKE_PROJECT_VERSION_MINOR@/" #else -# define EMU_DOCS_URL "https://86box.readthedocs.io" +# define EMU_DOCS_URL "https://86box.readthedocs.io" #endif -#define EMU_DOCS_URL_W LSTR(EMU_DOCS_URL) +#define EMU_DOCS_URL_W LSTR(EMU_DOCS_URL) diff --git a/src/include/86box/vid_8514a.h b/src/include/86box/vid_8514a.h new file mode 100644 index 000000000..983e98cd1 --- /dev/null +++ b/src/include/86box/vid_8514a.h @@ -0,0 +1,206 @@ +/* + * 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 card from IBM for the MCA bus and + * generic ISA bus clones without vendor extensions. + * + * + * + * Authors: TheCollector1995 + * + * Copyright 2022 TheCollector1995. + */ +#ifndef VIDEO_8514A_H +#define VIDEO_8514A_H + +typedef struct hwcursor8514_t { + int ena; + int x; + int y; + int xoff; + int yoff; + int cur_xsize; + int cur_ysize; + int v_acc; + int h_acc; + uint32_t addr; + uint32_t pitch; +} hwcursor8514_t; + +typedef struct ibm8514_t { + hwcursor8514_t hwcursor; + hwcursor8514_t hwcursor_latch; + uint8_t pos_regs[8]; + + int force_old_addr; + int type; + int local; + int bpp; + int on; + int accel_bpp; + + uint32_t vram_size; + uint32_t vram_mask; + uint32_t pallook[512]; + + PALETTE vgapal; + uint8_t hwcursor_oddeven; + uint8_t dac_mask; + uint8_t dac_status; + uint32_t *map8; + int dac_addr; + int dac_pos; + int dac_r; + int dac_g; + int dac_b; + int internal_pitch; + int hwcursor_on; + + struct { + uint16_t subsys_cntl; + uint16_t setup_md; + uint8_t advfunc_cntl; + uint8_t ext_advfunc_cntl; + uint16_t cur_y; + uint16_t cur_y_bitres; + uint16_t cur_x; + uint16_t cur_x_bitres; + int16_t desty_axstp; + int16_t destx_distp; + int16_t err_term; + int16_t maj_axis_pcnt; + uint16_t cmd; + uint16_t cmd_back; + uint16_t short_stroke; + uint16_t bkgd_color; + uint16_t frgd_color; + uint16_t wrt_mask; + uint16_t rd_mask; + uint16_t color_cmp; + uint16_t bkgd_mix; + uint16_t frgd_mix; + uint16_t multifunc_cntl; + uint16_t multifunc[16]; + int16_t clip_left; + int16_t clip_top; + uint8_t pix_trans[2]; + int poly_draw; + int ssv_state; + int x1; + int x2; + int x3; + int y1; + int y2; + int sys_cnt; + int sys_cnt2; + int temp_cnt; + int16_t cx; + int16_t cy; + int16_t oldcy; + int16_t sx; + int16_t sy; + int16_t dx; + int16_t dy; + int16_t err; + uint32_t src; + uint32_t dest; + uint32_t newsrc_blt; + uint32_t newdest_blt; + uint32_t newdest_in; + uint32_t newdest_out; + uint8_t *writemono; + uint8_t *nibbleset; + int x_count; + int xx_count; + int y_count; + int input; + int output; + + uint16_t cur_x_bit12; + uint16_t cur_y_bit12; + int ssv_len; + uint8_t ssv_dir; + uint8_t ssv_draw; + int odd_in; + int odd_out; + + uint16_t scratch; + int fill_state; + int xdir; + int ydir; + uint32_t ge_offset; + } accel; + + uint16_t test; + int ibm_mode; + + int v_total; + int dispend; + int v_syncstart; + int split; + int h_disp; + int h_disp_old; + int h_total; + int h_disp_time; + int rowoffset; + int dispon; + int hdisp_on; + int linecountff; + int vc; + int linepos; + int oddeven; + int cursoron; + int blink; + int scrollcache; + int firstline; + int lastline; + int firstline_draw; + int lastline_draw; + int displine; + int fullchange; + uint32_t ma; + uint32_t maback; + + uint8_t *vram; + uint8_t *changedvram; + uint8_t linedbl; + + uint8_t data_available; + uint8_t data_available2; + uint8_t scanmodulos; + uint8_t rowcount; + int htotal; + int hdisp; + int vtadj; + int vdadj; + int vsadj; + int sc; + int vtb; + int vdb; + int vsb; + int vsyncstart; + int vsyncwidth; + int vtotal; + int vdisp; + int disp_cntl; + int interlace; + uint8_t subsys_cntl; + uint8_t subsys_stat; + + atomic_int force_busy; + atomic_int 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 24e0bff96..99af36eda 100644 --- a/src/include/86box/vid_ati_eeprom.h +++ b/src/include/86box/vid_ati_eeprom.h @@ -1,49 +1,54 @@ +#ifndef VIDEO_ATI_EEPROM_H +#define VIDEO_ATI_EEPROM_H + /* Copyright holders: Sarah Walker see COPYING for more details */ -enum -{ - EEPROM_IDLE, - EEPROM_WAIT, - EEPROM_OPCODE, - EEPROM_INPUT, - EEPROM_OUTPUT +enum { + EEPROM_IDLE, + EEPROM_WAIT, + EEPROM_OPCODE, + EEPROM_INPUT, + EEPROM_OUTPUT }; -enum -{ - EEPROM_OP_EW = 4, - EEPROM_OP_WRITE = 5, - EEPROM_OP_READ = 6, - EEPROM_OP_ERASE = 7, - - EEPROM_OP_WRALMAIN = -1 +enum { + EEPROM_OP_EW = 4, + EEPROM_OP_WRITE = 5, + EEPROM_OP_READ = 6, + EEPROM_OP_ERASE = 7, + + EEPROM_OP_WRALMAIN = -1 }; -enum -{ - EEPROM_OP_EWDS = 0, - EEPROM_OP_WRAL = 1, - EEPROM_OP_ERAL = 2, - EEPROM_OP_EWEN = 3 +enum { + EEPROM_OP_EWDS = 0, + EEPROM_OP_WRAL = 1, + EEPROM_OP_ERAL = 2, + EEPROM_OP_EWEN = 3 }; +typedef struct ati_eeprom_t { + uint16_t data[256]; -typedef struct ati_eeprom_t -{ - uint16_t data[256]; + int oldclk; + int oldena; + int opcode; + int state; + int count; + int out; + int wp; + uint32_t dat; + int type; + int address; - int oldclk, oldena; - int opcode, state, count, out; - int wp; - uint32_t dat; - int type; - int address; - - char fn[256]; + char fn[256]; } 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); +int ati_eeprom_read(ati_eeprom_t *eeprom); + +#endif /*VIDEO_ATI_EEPROM_H*/ diff --git a/src/include/86box/vid_cga.h b/src/include/86box/vid_cga.h index c8b1cca8c..f49fc73cc 100644 --- a/src/include/86box/vid_cga.h +++ b/src/include/86box/vid_cga.h @@ -1,71 +1,86 @@ /* - * 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. + * 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. + * This file is part of the 86Box distribution. * - * Emulation of the old and new IBM CGA graphics cards. + * Emulation of the old and new IBM CGA graphics cards. * * * - * Author: Sarah Walker, - * Miran Grca, - * Copyright 2008-2018 Sarah Walker. - * Copyright 2016-2018 Miran Grca. + * Authors: Sarah Walker, + * Miran Grca, + * + * Copyright 2008-2018 Sarah Walker. + * Copyright 2016-2018 Miran Grca. */ + #ifndef VIDEO_CGA_H -# define VIDEO_CGA_H +#define VIDEO_CGA_H -typedef struct cga_t -{ - mem_mapping_t mapping; - - int crtcreg; - uint8_t crtc[32]; - - uint8_t cgastat; - - uint8_t cgamode, cgacol; +typedef struct cga_t { + mem_mapping_t mapping; - int fontbase; - int linepos, displine; - int sc, vc; - int cgadispon; - int con, coff, cursoron, cgablink; - int vsynctime, vadj; - uint16_t ma, maback; - int oddeven; + int crtcreg; + uint8_t crtc[32]; - uint64_t dispontime, dispofftime; - pc_timer_t timer; - - int firstline, lastline; - - int drawcursor; - - uint8_t *vram; - - uint8_t charbuffer[256]; + uint8_t cgastat; - int revision; - int composite; - int snow_enabled; - int rgb_type; + uint8_t cgamode; + uint8_t cgacol; + + int fontbase; + int linepos; + int displine; + int sc; + int vc; + int cgadispon; + int con; + int coff; + int cursoron; + int cgablink; + int vsynctime; + int vadj; + uint16_t ma; + uint16_t maback; + int oddeven; + + uint64_t dispontime; + uint64_t dispofftime; + pc_timer_t timer; + + int firstline; + int lastline; + + int drawcursor; + + int fullchange; + + uint8_t *vram; + + uint8_t charbuffer[256]; + + int revision; + int composite; + int snow_enabled; + int rgb_type; } cga_t; void cga_init(cga_t *cga); -void cga_out(uint16_t addr, uint8_t val, void *p); -uint8_t cga_in(uint16_t addr, void *p); -void cga_write(uint32_t addr, uint8_t val, void *p); -uint8_t cga_read(uint32_t addr, void *p); +void cga_out(uint16_t addr, uint8_t val, void *priv); +uint8_t cga_in(uint16_t addr, void *priv); +void cga_write(uint32_t addr, uint8_t val, void *priv); +uint8_t cga_read(uint32_t addr, void *priv); void cga_recalctimings(cga_t *cga); -void cga_poll(void *p); +void cga_poll(void *priv); #ifdef EMU_DEVICE_H extern const device_config_t cga_config[]; + extern const device_t cga_device; +extern const device_t cga_pravetz_device; #endif -#endif /*VIDEO_CGA_H*/ +#endif /*VIDEO_CGA_H*/ diff --git a/src/include/86box/vid_cga_comp.h b/src/include/86box/vid_cga_comp.h index 6b1dc4062..291145291 100644 --- a/src/include/86box/vid_cga_comp.h +++ b/src/include/86box/vid_cga_comp.h @@ -1,31 +1,31 @@ /* - * 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. + * 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. + * This file is part of the 86Box distribution. * - * IBM CGA composite filter, borrowed from reenigne's DOSBox - * patch and ported to C. + * IBM CGA composite filter, borrowed from reenigne's DOSBox + * patch and ported to C. * * * - * Author: reenigne, - * Miran Grca, - * Copyright 2015-2018 reenigne. - * Copyright 2015-2018 Miran Grca. + * Authors: reenigne, + * Miran Grca, + * + * Copyright 2015-2018 reenigne. + * Copyright 2015-2018 Miran Grca. */ -#ifndef VIDEO_CGA_COMP_H -# define VIDEO_CGA_COMP_H -#define Bit8u uint8_t -#define Bit32u uint32_t +#ifndef VIDEO_CGA_COMP_H +#define VIDEO_CGA_COMP_H + #define Bitu unsigned int #define bool uint8_t -void update_cga16_color(uint8_t cgamode); -void cga_comp_init(int revision); -Bit32u * Composite_Process(uint8_t cgamode, Bit8u border, Bit32u blocks/*, bool doublewidth*/, Bit32u *TempLine); +void update_cga16_color(uint8_t cgamode); +void cga_comp_init(int revision); +Bit32u *Composite_Process(uint8_t cgamode, uint8_t border, uint32_t blocks /*, bool doublewidth*/, uint32_t *TempLine); -#endif /*VIDEO_CGA_COMP_H*/ +#endif /*VIDEO_CGA_COMP_H*/ diff --git a/src/include/86box/vid_colorplus.h b/src/include/86box/vid_colorplus.h index 07a96ff4f..5acd4c8a2 100644 --- a/src/include/86box/vid_colorplus.h +++ b/src/include/86box/vid_colorplus.h @@ -1,15 +1,19 @@ -typedef struct colorplus_t -{ - cga_t cga; - uint8_t control; +#ifndef VIDEO_COLORPLUS_H +#define VIDEO_COLORPLUS_H + +typedef struct colorplus_t { + cga_t cga; + uint8_t control; } colorplus_t; void colorplus_init(colorplus_t *colorplus); -void colorplus_out(uint16_t addr, uint8_t val, void *p); -uint8_t colorplus_in(uint16_t addr, void *p); -void colorplus_write(uint32_t addr, uint8_t val, void *p); -uint8_t colorplus_read(uint32_t addr, void *p); +void colorplus_out(uint16_t addr, uint8_t val, void *priv); +uint8_t colorplus_in(uint16_t addr, void *priv); +void colorplus_write(uint32_t addr, uint8_t val, void *priv); +uint8_t colorplus_read(uint32_t addr, void *priv); void colorplus_recalctimings(colorplus_t *colorplus); -void colorplus_poll(void *p); +void colorplus_poll(void *priv); extern const device_t colorplus_device; + +#endif /*VIDEO_COLORPLUS_H*/ diff --git a/src/include/86box/vid_ddc.h b/src/include/86box/vid_ddc.h index 223861436..144cca406 100644 --- a/src/include/86box/vid_ddc.h +++ b/src/include/86box/vid_ddc.h @@ -1,25 +1,26 @@ /* - * 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. + * 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. + * This file is part of the 86Box distribution. * - * DDC monitor emulation definitions. + * DDC monitor emulation definitions. * * * - * Authors: Sarah Walker, - * RichardG, + * Authors: Sarah Walker, + * RichardG, * - * Copyright 2008-2020 Sarah Walker. - * Copyright 2020 RichardG. + * Copyright 2008-2020 Sarah Walker. + * Copyright 2020 RichardG. */ + #ifndef EMU_VID_DDC_H -# define EMU_VID_DDC_H +#define EMU_VID_DDC_H -extern void *ddc_init(void *i2c); -extern void ddc_close(void *eeprom); +extern void *ddc_init(void *i2c); +extern void ddc_close(void *eeprom); -#endif /*EMU_VID_DDC_H*/ +#endif /*EMU_VID_DDC_H*/ diff --git a/src/include/86box/vid_ega.h b/src/include/86box/vid_ega.h index bc378704b..180803c8a 100644 --- a/src/include/86box/vid_ega.h +++ b/src/include/86box/vid_ega.h @@ -1,25 +1,25 @@ /* - * 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. + * 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. + * This file is part of the 86Box distribution. * - * Emulation of the EGA and Chips & Technologies SuperEGA - * graphics cards. + * Emulation of the EGA and Chips & Technologies SuperEGA + * graphics cards. * * * - * Authors: Sarah Walker, - * Miran Grca, + * Authors: Sarah Walker, + * Miran Grca, * - * Copyright 2008-2020 Sarah Walker. - * Copyright 2016-2020 Miran Grca. + * Copyright 2008-2020 Sarah Walker. + * Copyright 2016-2020 Miran Grca. */ -#ifndef VIDEO_EGA_H -# define VIDEO_EGA_H +#ifndef VIDEO_EGA_H +#define VIDEO_EGA_H #if defined(EMU_MEM_H) && defined(EMU_ROM_H) typedef struct ega_t { @@ -27,11 +27,26 @@ typedef struct ega_t { rom_t bios_rom; - uint8_t crtcreg, gdcaddr, attraddr, attrff, - attr_palette_enable, seqaddr, miscout, - writemask, la, lb, lc, ld, - stat, colourcompare, colournocare, scrblank, - plane_mask, pad, pad0, pad1; + uint8_t crtcreg; + uint8_t gdcaddr; + uint8_t attraddr; + uint8_t attrff; + uint8_t attr_palette_enable; + uint8_t seqaddr; + uint8_t miscout; + uint8_t writemask; + uint8_t la; + uint8_t lb; + uint8_t lc; + uint8_t ld; + uint8_t stat; + uint8_t colourcompare; + uint8_t colournocare; + uint8_t scrblank; + uint8_t plane_mask; + uint8_t ctl_mode; + uint8_t color_mux; + uint8_t dot; uint8_t crtc[32]; uint8_t gdcreg[16]; uint8_t attrregs[32]; @@ -41,36 +56,89 @@ typedef struct ega_t { uint8_t *vram; - int vidclock, fast, extvram, vres, - readmode, writemode, readplane, vrammask, - chain4, chain2_read, chain2_write, con, - oddeven_page, oddeven_chain, vc, sc, - dispon, hdisp_on, cursoron, blink, - linepos, vslines, linecountff, oddeven, - lowres, interlace, linedbl, lindebl, rowcount, - vtotal, dispend, vsyncstart, split, - hdisp, hdisp_old, htotal, hdisp_time, rowoffset, - vblankstart, scrollcache, firstline, lastline, - firstline_draw, lastline_draw, x_add, y_add, - displine, video_res_x, video_res_y, video_bpp, index; + int vidclock; + int fast; + int extvram; + int vres; + int readmode; + int writemode; + int readplane; + int vrammask; + int chain4; + int chain2_read; + int chain2_write; + int con; + int oddeven_page; + int oddeven_chain; + int vc; + int sc; + int dispon; + int hdisp_on; + int cursoron; + int blink; + int fullchange; + int linepos; + int vslines; + int linecountff; + int oddeven; + int lowres; + int interlace; + int linedbl; + int lindebl; + int rowcount; + int vtotal; + int dispend; + int vsyncstart; + int split; + int hdisp; + int hdisp_old; + int htotal; + int hdisp_time; + int rowoffset; + int vblankstart; + int scrollcache; + int firstline; + int lastline; + int firstline_draw; + int lastline_draw; + int x_add; + int y_add; + int displine; + int res_x; + int res_y; + int bpp; + int index; + int remap_required; - uint32_t charseta, charsetb, ma_latch, ma, - maback, ca, vram_limit, overscan_color; + uint32_t charseta; + uint32_t charsetb; + uint32_t ma_latch; + uint32_t ma; + uint32_t maback; + uint32_t ca; + uint32_t vram_limit; + uint32_t overscan_color; + uint32_t cca; uint32_t *pallook; - uint64_t dispontime, dispofftime; - pc_timer_t timer; + uint64_t dispontime; + uint64_t dispofftime; - double clock; + uint64_t dot_time; - void (*render)(struct ega_t *svga); + pc_timer_t timer; + pc_timer_t dot_timer; - void *eeprom; + double dot_clock; + + void * eeprom; + + uint32_t (*remap_func)(struct ega_t *ega, uint32_t in_addr); + void (*render)(struct ega_t *svga); } ega_t; #endif - #ifdef EMU_DEVICE_H extern const device_t ega_device; extern const device_t cpqega_device; @@ -82,36 +150,40 @@ extern const device_t et2000_device; extern int update_overscan; -#define DISPLAY_RGB 0 -#define DISPLAY_COMPOSITE 1 +#define DISPLAY_RGB 0 +#define DISPLAY_COMPOSITE 1 #define DISPLAY_RGB_NO_BROWN 2 -#define DISPLAY_GREEN 3 -#define DISPLAY_AMBER 4 -#define DISPLAY_WHITE 5 - +#define DISPLAY_GREEN 3 +#define DISPLAY_AMBER 4 +#define DISPLAY_WHITE 5 #if defined(EMU_MEM_H) && defined(EMU_ROM_H) -extern void ega_init(ega_t *ega, int monitor_type, int is_mono); -extern void ega_recalctimings(struct ega_t *ega); +extern void ega_init(ega_t *ega, int monitor_type, int is_mono); +extern void ega_recalctimings(struct ega_t *ega); +extern void ega_recalc_remap_func(struct ega_t *ega); #endif -extern void ega_out(uint16_t addr, uint8_t val, void *p); -extern uint8_t ega_in(uint16_t addr, void *p); -extern void ega_poll(void *p); -extern void ega_write(uint32_t addr, uint8_t val, void *p); -extern uint8_t ega_read(uint32_t addr, void *p); +extern void ega_out(uint16_t addr, uint8_t val, void *priv); +extern uint8_t ega_in(uint16_t addr, void *priv); +extern void ega_poll(void *priv); +extern void ega_write(uint32_t addr, uint8_t val, void *priv); +extern uint8_t ega_read(uint32_t addr, void *priv); - -extern int firstline_draw, lastline_draw; +extern int firstline_draw; +extern int lastline_draw; extern int displine; extern int sc; -extern uint32_t ma, ca; -extern int con, cursoron, cgablink; +extern uint32_t ma; +extern uint32_t ca; +extern int con; +extern int cursoron; +extern int cgablink; extern int scrollcache; extern uint8_t edatlookup[4][4]; +extern uint8_t egaremap2bpp[256]; #if defined(EMU_MEM_H) && defined(EMU_ROM_H) void ega_render_blank(ega_t *ega); @@ -119,15 +191,8 @@ void ega_render_blank(ega_t *ega); void ega_render_overscan_left(ega_t *ega); void ega_render_overscan_right(ega_t *ega); -void ega_render_text_40(ega_t *ega); -void ega_render_text_80(ega_t *ega); - -void ega_render_2bpp_lowres(ega_t *ega); -void ega_render_2bpp_highres(ega_t *ega); - -void ega_render_4bpp_lowres(ega_t *ega); -void ega_render_4bpp_highres(ega_t *ega); +void ega_render_text(ega_t *ega); +void ega_render_graphics(ega_t *ega); #endif - -#endif /*VIDEO_EGA_H*/ +#endif /*VIDEO_EGA_H*/ diff --git a/src/include/86box/vid_ega_render_remap.h b/src/include/86box/vid_ega_render_remap.h new file mode 100644 index 000000000..b01bb2b0e --- /dev/null +++ b/src/include/86box/vid_ega_render_remap.h @@ -0,0 +1,102 @@ +#ifndef VIDEO_EGA_RENDER_REMAP_H +#define VIDEO_EGA_RENDER_REMAP_H + +#define VAR_BYTE_MODE (0 << 0) +#define VAR_WORD_MODE_MA13 (1 << 0) +#define VAR_WORD_MODE_MA15 (2 << 0) +#define VAR_DWORD_MODE (3 << 0) +#define VAR_MODE_MASK (3 << 0) +#define VAR_ROW0_MA13 (1 << 2) +#define VAR_ROW1_MA14 (1 << 3) + +#define ADDRESS_REMAP_FUNC(nr) \ + static uint32_t address_remap_func_##nr(ega_t *ega, uint32_t in_addr) \ + { \ + uint32_t out_addr; \ + \ + switch (nr & VAR_MODE_MASK) { \ + case VAR_BYTE_MODE: \ + out_addr = in_addr; \ + break; \ + \ + case VAR_WORD_MODE_MA13: \ + out_addr = ((in_addr << 1) & 0x3fff8) | ((in_addr >> 13) & 0x4) | (in_addr & ~0x3ffff); \ + break; \ + \ + case VAR_WORD_MODE_MA15: \ + out_addr = ((in_addr << 1) & 0x3fff8) | ((in_addr >> 15) & 0x4) | (in_addr & ~0x3ffff); \ + break; \ + \ + case VAR_DWORD_MODE: \ + out_addr = ((in_addr << 2) & 0x3fff0) | ((in_addr >> 14) & 0xc) | (in_addr & ~0x3ffff); \ + break; \ + } \ + \ + if (nr & VAR_ROW0_MA13) \ + out_addr = (out_addr & ~0x8000) | ((ega->sc & 1) ? 0x8000 : 0); \ + if (nr & VAR_ROW1_MA14) \ + out_addr = (out_addr & ~0x10000) | ((ega->sc & 2) ? 0x10000 : 0); \ + \ + return out_addr; \ + } + +ADDRESS_REMAP_FUNC(0) +ADDRESS_REMAP_FUNC(1) +ADDRESS_REMAP_FUNC(2) +ADDRESS_REMAP_FUNC(3) +ADDRESS_REMAP_FUNC(4) +ADDRESS_REMAP_FUNC(5) +ADDRESS_REMAP_FUNC(6) +ADDRESS_REMAP_FUNC(7) +ADDRESS_REMAP_FUNC(8) +ADDRESS_REMAP_FUNC(9) +ADDRESS_REMAP_FUNC(10) +ADDRESS_REMAP_FUNC(11) +ADDRESS_REMAP_FUNC(12) +ADDRESS_REMAP_FUNC(13) +ADDRESS_REMAP_FUNC(14) +ADDRESS_REMAP_FUNC(15) + +static uint32_t (*address_remap_funcs[16])(ega_t *ega, uint32_t in_addr) = { + address_remap_func_0, + address_remap_func_1, + address_remap_func_2, + address_remap_func_3, + address_remap_func_4, + address_remap_func_5, + address_remap_func_6, + address_remap_func_7, + address_remap_func_8, + address_remap_func_9, + address_remap_func_10, + address_remap_func_11, + address_remap_func_12, + address_remap_func_13, + address_remap_func_14, + address_remap_func_15 +}; + +void +ega_recalc_remap_func(ega_t *ega) +{ + int func_nr; + + if (ega->crtc[0x14] & 0x40) + func_nr = VAR_DWORD_MODE; + else if (ega->crtc[0x17] & 0x40) + func_nr = VAR_BYTE_MODE; + else if ((ega->crtc[0x17] & 0x20) && ega->vram_limit > 64 * 1024) + func_nr = VAR_WORD_MODE_MA15; + else + func_nr = VAR_WORD_MODE_MA13; + + if (!(ega->crtc[0x17] & 0x01)) + func_nr |= VAR_ROW0_MA13; + if (!(ega->crtc[0x17] & 0x02)) + func_nr |= VAR_ROW1_MA14; + + ega->remap_required = (func_nr != 0); + ega->remap_func = address_remap_funcs[func_nr]; +} + +#endif /*VIDEO_RENDER_REMAP_H*/ diff --git a/src/include/86box/vid_hercules.h b/src/include/86box/vid_hercules.h index 8d44fdfe1..c58a50aa3 100644 --- a/src/include/86box/vid_hercules.h +++ b/src/include/86box/vid_hercules.h @@ -1,61 +1,79 @@ /* - * 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. + * 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. + * This file is part of the 86Box distribution. * - * Emulation of the Hercules graphics cards. + * Emulation of the Hercules graphics cards. * * * - * Author: Sarah Walker, - * Miran Grca, - * Copyright 2008-2019 Sarah Walker. - * Copyright 2016-2019 Miran Grca. - * Copyright 2021 Jasmine Iwanek. + * Authors: Sarah Walker, + * Miran Grca, + * Jasmine Iwanek, + * + * Copyright 2008-2019 Sarah Walker. + * Copyright 2016-2019 Miran Grca. + * Copyright 2021 Jasmine Iwanek. */ + #ifndef VIDEO_HERCULES_H -# define VIDEO_HERCULES_H +#define VIDEO_HERCULES_H typedef struct { - mem_mapping_t mapping; + mem_mapping_t mapping; - uint8_t crtc[32], charbuffer[4096]; - int crtcreg; + uint8_t crtc[32]; + uint8_t charbuffer[4096]; + int crtcreg; - uint8_t ctrl, - ctrl2, - stat; + uint8_t ctrl; + uint8_t ctrl2; + uint8_t stat; - uint64_t dispontime, - dispofftime; - pc_timer_t timer; + uint64_t dispontime; + uint64_t dispofftime; + pc_timer_t timer; - int firstline, - lastline; + int firstline; + int lastline; - int linepos, - displine; - int vc, - sc; - uint16_t ma, - maback; - int con, coff, - cursoron; - int dispon, - blink; - int vsynctime; - int vadj; + int linepos; + int displine; + int vc; + int sc; + uint16_t ma; + uint16_t maback; + int con; + int coff; + int cursoron; + int dispon; + int blink; + int vsynctime; + int vadj; - int lp_ff; + int lp_ff; + int fullchange; - int cols[256][2][2]; + int cols[256][2][2]; - uint8_t *vram; + uint8_t *vram; + int monitor_index; + int prev_monitor_index; } hercules_t; +#define VIDEO_MONITOR_PROLOGUE() \ + { \ + dev->prev_monitor_index = monitor_index_global; \ + monitor_index_global = dev->monitor_index; \ + } +#define VIDEO_MONITOR_EPILOGUE() \ + { \ + monitor_index_global = dev->prev_monitor_index; \ + } + static void *hercules_init(const device_t *info); -#endif /*VIDEO_HERCULES_H*/ +#endif /*VIDEO_HERCULES_H*/ diff --git a/src/include/86box/vid_mda.h b/src/include/86box/vid_mda.h index 82a8f5e19..d13c45a28 100644 --- a/src/include/86box/vid_mda.h +++ b/src/include/86box/vid_mda.h @@ -1,40 +1,67 @@ /* Copyright holders: Sarah Walker see COPYING for more details */ -typedef struct mda_t -{ - mem_mapping_t mapping; - - uint8_t crtc[32]; - int crtcreg; - - uint8_t ctrl, stat; - - uint64_t dispontime, dispofftime; - pc_timer_t timer; - - int firstline, lastline; - int linepos, displine; - int vc, sc; - uint16_t ma, maback; - int con, coff, cursoron; - int dispon, blink; - int vsynctime; - int vadj; +#ifndef VIDEO_MDA_H +#define VIDEO_MDA_H - uint8_t *vram; +typedef struct mda_t { + mem_mapping_t mapping; + + uint8_t crtc[32]; + int crtcreg; + + uint8_t ctrl; + uint8_t stat; + + uint64_t dispontime; + uint64_t dispofftime; + pc_timer_t timer; + + int firstline; + int lastline; + + int fontbase; + int linepos; + int displine; + int vc; + int sc; + uint16_t ma; + uint16_t maback; + int con; + int coff; + int cursoron; + int dispon; + int blink; + int vsynctime; + int vadj; + int monitor_index; + int prev_monitor_index; + + uint8_t *vram; } mda_t; +#define VIDEO_MONITOR_PROLOGUE() \ + { \ + mda->prev_monitor_index = monitor_index_global; \ + monitor_index_global = mda->monitor_index; \ + } +#define VIDEO_MONITOR_EPILOGUE() \ + { \ + monitor_index_global = mda->prev_monitor_index; \ + } + void mda_init(mda_t *mda); -void mda_setcol(int chr, int blink, int fg, uint8_t cga_ink); -void mda_out(uint16_t addr, uint8_t val, void *p); -uint8_t mda_in(uint16_t addr, void *p); -void mda_write(uint32_t addr, uint8_t val, void *p); -uint8_t mda_read(uint32_t addr, void *p); +void mda_setcol(int chr, int blink, int fg, uint8_t cga_ink); +void mda_out(uint16_t addr, uint8_t val, void *priv); +uint8_t mda_in(uint16_t addr, void *priv); +void mda_write(uint32_t addr, uint8_t val, void *priv); +uint8_t mda_read(uint32_t addr, void *priv); void mda_recalctimings(mda_t *mda); -void mda_poll(void *p); +void mda_poll(void *priv); #ifdef EMU_DEVICE_H extern const device_t mda_device; #endif + +#endif /*VIDEO_MDA_H*/ diff --git a/src/include/86box/vid_nga.h b/src/include/86box/vid_nga.h index 1c8bd786e..bbb5b3c95 100644 --- a/src/include/86box/vid_nga.h +++ b/src/include/86box/vid_nga.h @@ -1,34 +1,33 @@ /* - * 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. + * 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. + * This file is part of the 86Box distribution. * - * Emulation of the Olivetti OGC 8-bit ISA (GO708) and - * M21/M24/M28 16-bit bus (GO317/318/380/709) video cards. + * Emulation of the Olivetti OGC 8-bit ISA (GO708) and + * M21/M24/M28 16-bit bus (GO317/318/380/709) video cards. * * * - * Authors: Sarah Walker, - * Miran Grca, - * Fred N. van Kempen, - * EngiNerd, + * Authors: Miran Grca, + * EngiNerd, * - * Copyright 2008-2019 Sarah Walker. - * Copyright 2016-2019 Miran Grca. - * Copyright 2017-2019 Fred N. van Kempen. - * Copyright 2020 EngiNerd. + * Copyright 2016-2019 Miran Grca. + * Copyright 2020 EngiNerd. */ +#ifndef VIDEO_NGA_H +#define VIDEO_NGA_H + typedef struct nga_t { cga_t cga; - /* unused in OGC, required for M19 video card structure idiom */ - uint32_t base; - int lineff; - int page; - uint8_t *vram_64k; + /* unused in OGC, required for M19 video card structure idiom */ + uint32_t base; + int lineff; + int page; + uint8_t *vram_64k; mem_mapping_t mapping_64k; } nga_t; @@ -39,10 +38,11 @@ void nga_write(uint32_t addr, uint8_t val, void *priv); uint8_t nga_read(uint32_t addr, void *priv); void nga_poll(void *priv); void nga_close(void *priv); -void nga_mdaattr_rebuild(); - +void nga_mdaattr_rebuild(void); #ifdef EMU_DEVICE_H extern const device_config_t nga_config[]; -extern const device_t nga_device; +extern const device_t nga_device; #endif + +#endif /*VIDEO_NGA_H*/ diff --git a/src/include/86box/vid_ogc.h b/src/include/86box/vid_ogc.h index 2fffa65c3..839769e69 100644 --- a/src/include/86box/vid_ogc.h +++ b/src/include/86box/vid_ogc.h @@ -1,35 +1,34 @@ /* - * 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. + * 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. + * This file is part of the 86Box distribution. * - * Emulation of the Olivetti OGC 8-bit ISA (GO708) and - * M21/M24/M28 16-bit bus (GO317/318/380/709) video cards. + * Emulation of the Olivetti OGC 8-bit ISA (GO708) and + * M21/M24/M28 16-bit bus (GO317/318/380/709) video cards. * * * - * Authors: Sarah Walker, - * Miran Grca, - * Fred N. van Kempen, - * EngiNerd, + * Authors: Miran Grca, + * EngiNerd, * - * Copyright 2008-2019 Sarah Walker. - * Copyright 2016-2019 Miran Grca. - * Copyright 2017-2019 Fred N. van Kempen. - * Copyright 2020 EngiNerd. + * Copyright 2016-2019 Miran Grca. + * Copyright 2020 EngiNerd. */ +#ifndef VIDEO_OGC_H +#define VIDEO_OGC_H + typedef struct ogc_t { cga_t cga; - /* unused in OGC, required for M19 video card structure idiom */ - uint8_t ctrl_3dd; - uint8_t ctrl_3de; - uint32_t base; - int lineff; - int mono_display; + /* unused in OGC, required for M19 video card structure idiom */ + uint8_t ctrl_3dd; + uint8_t ctrl_3de; + uint32_t base; + int lineff; + int mono_display; } ogc_t; void ogc_recalctimings(ogc_t *ogc); @@ -39,10 +38,11 @@ void ogc_write(uint32_t addr, uint8_t val, void *priv); uint8_t ogc_read(uint32_t addr, void *priv); void ogc_poll(void *priv); void ogc_close(void *priv); -void ogc_mdaattr_rebuild(); - +void ogc_mdaattr_rebuild(void); #ifdef EMU_DEVICE_H extern const device_config_t ogc_config[]; -extern const device_t ogc_device; +extern const device_t ogc_device; #endif + +#endif /*VIDEO_OGC_H*/ diff --git a/src/include/86box/vid_pgc.h b/src/include/86box/vid_pgc.h index ecfc61c2b..35e2d9e42 100644 --- a/src/include/86box/vid_pgc.h +++ b/src/include/86box/vid_pgc.h @@ -1,24 +1,23 @@ /* - * 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. + * 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. + * This file is part of the 86Box distribution. * - * Definitions for the PGC driver. + * Definitions for the PGC driver. * * * - * Authors: Fred N. van Kempen, - * John Elliott, + * Authors: Fred N. van Kempen, + * John Elliott, * - * Copyright 2019 Fred N. van Kempen. - * Copyright 2019 John Elliott. + * Copyright 2019 Fred N. van Kempen. + * Copyright 2019 John Elliott. */ #ifndef VID_PGC_H -# define VID_PGC_H - +#define VID_PGC_H #define PGC_ERROR_RANGE 0x01 #define PGC_ERROR_INTEGER 0x02 @@ -32,154 +31,172 @@ #define PGC_ERROR_AREA 0x0A #define PGC_ERROR_MISSING 0x0B - struct pgc; typedef struct pgc_cl { - uint8_t *list; - uint32_t listmax; - uint32_t wrptr; - uint32_t rdptr; - uint32_t repeat; + uint8_t *list; + uint32_t listmax; + uint32_t wrptr; + uint32_t rdptr; + uint32_t repeat; struct pgc_cl *chain; } pgc_cl_t; typedef struct pgc_cmd { - char ascii[6]; - uint8_t hex; - void (*handler)(struct pgc *); - int (*parser) (struct pgc *, pgc_cl_t *, int); - int p; + char ascii[6]; + uint8_t hex; + void (*handler)(struct pgc *); + int (*parser)(struct pgc *, pgc_cl_t *, int); + int p; } pgc_cmd_t; typedef struct pgc { - int8_t type; /* board type */ - int8_t cga_enabled; - int8_t cga_selected; - volatile int8_t stopped; + int8_t type; /* board type */ + int8_t cga_enabled; + int8_t cga_selected; + volatile int8_t stopped; - mem_mapping_t mapping; - mem_mapping_t cga_mapping; + mem_mapping_t mapping; + mem_mapping_t cga_mapping; - pgc_cl_t *clist, - *clcur; - const pgc_cmd_t *master, - *commands; + pgc_cl_t *clist; + pgc_cl_t *clcur; + const pgc_cmd_t *master; + const pgc_cmd_t *commands; - uint8_t mapram[2048]; /* host <> PGC communication buffer */ - uint8_t *cga_vram; - uint8_t *vram; - char asc_command[7]; - uint8_t hex_command; - uint32_t palette[256]; - uint32_t userpal[256]; - uint32_t maxw, maxh; /* maximum framebuffer size */ - uint32_t visw, vish; /* maximum screen size */ - uint32_t screenw, screenh; - int16_t pan_x, pan_y; - uint16_t win_x1, win_x2, win_y1, win_y2; - uint16_t vp_x1, vp_x2, vp_y1, vp_y2; - int16_t fill_pattern[16]; - int16_t line_pattern; - uint8_t draw_mode; - uint8_t fill_mode; - uint8_t color; - uint8_t tjust_h; /* hor alignment 1=left 2=ctr 3=right*/ - uint8_t tjust_v; /* vert alignment 1=bottom 2=ctr 3=top*/ - int32_t tsize; /* horizontal spacing */ + uint8_t mapram[2048]; /* host <> PGC communication buffer */ + uint8_t *cga_vram; + uint8_t *vram; + char asc_command[7]; + uint8_t hex_command; + uint32_t palette[256]; + uint32_t userpal[256]; + uint32_t maxw; /* maximum framebuffer size - Width */ + uint32_t maxh; /* maximum framebuffer size - Height */ + uint32_t visw; /* maximum screen size - Width */ + uint32_t vish; /* maximum screen size - Height */ + uint32_t screenw; + uint32_t screenh; + int16_t pan_x; + int16_t pan_y; + uint16_t win_x1; + uint16_t win_x2; + uint16_t win_y1; + uint16_t win_y2; + uint16_t vp_x1; + uint16_t vp_x2; + uint16_t vp_y1; + uint16_t vp_y2; + int16_t fill_pattern[16]; + int16_t line_pattern; + uint8_t draw_mode; + uint8_t fill_mode; + uint8_t color; + uint8_t tjust_h; /* hor alignment 1=left 2=ctr 3=right*/ + uint8_t tjust_v; /* vert alignment 1=bottom 2=ctr 3=top*/ + int32_t tsize; /* horizontal spacing */ - int32_t x, y, z; /* drawing position */ + int32_t x; + int32_t y; + int32_t z; /* drawing position */ - thread_t *pgc_thread; - event_t *pgc_wake_thread; - pc_timer_t wake_timer; + thread_t *pgc_thread; + event_t *pgc_wake_thread; + pc_timer_t wake_timer; - int waiting_input_fifo; - int waiting_output_fifo; - int waiting_error_fifo; - int ascii_mode; - int result_count; - - int fontbase; - int linepos, - displine; - int vc; - int cgadispon; - int con, coff, cursoron, cgablink; - int vsynctime, vadj; - uint16_t ma, maback; - int oddeven; + int waiting_input_fifo; + int waiting_output_fifo; + int waiting_error_fifo; + int ascii_mode; + int result_count; - uint64_t dispontime, - dispofftime; - pc_timer_t timer; - double native_pixel_clock; + int fontbase; + int linepos; + int displine; + int vc; + int cgadispon; + int con; + int coff; + int cursoron; + int cgablink; + int vsynctime; + int vadj; + uint16_t ma; + uint16_t maback; + int oddeven; - int drawcursor; + uint64_t dispontime; + uint64_t dispofftime; + pc_timer_t timer; + double native_pixel_clock; - int (*inputbyte)(struct pgc *, uint8_t *result); + int drawcursor; + + int (*inputbyte)(struct pgc *, uint8_t *result); } pgc_t; - /* I/O functions and worker thread handlers. */ -extern void pgc_out(uint16_t addr, uint8_t val, void *priv); -extern uint8_t pgc_in(uint16_t addr, void *priv); -extern void pgc_write(uint32_t addr, uint8_t val, void *priv); -extern uint8_t pgc_read(uint32_t addr, void *priv); -extern void pgc_recalctimings(pgc_t *); -extern void pgc_poll(void *priv); -extern void pgc_reset(pgc_t *); -extern void pgc_wake(pgc_t *); -extern void pgc_sleep(pgc_t *); -extern void pgc_setdisplay(pgc_t *, int cga); -extern void pgc_speed_changed(void *priv); -extern void pgc_close_common(void *priv); -extern void pgc_close(void *priv); -extern void pgc_init(pgc_t *, - int maxw, int maxh, int visw, int vish, - int (*inpbyte)(pgc_t *, uint8_t *), double npc); +extern void pgc_out(uint16_t addr, uint8_t val, void *priv); +extern uint8_t pgc_in(uint16_t addr, void *priv); +extern void pgc_write(uint32_t addr, uint8_t val, void *priv); +extern uint8_t pgc_read(uint32_t addr, void *priv); +extern void pgc_recalctimings(pgc_t *); +extern void pgc_poll(void *priv); +extern void pgc_reset(pgc_t *); +extern void pgc_wake(pgc_t *); +extern void pgc_sleep(pgc_t *); +extern void pgc_setdisplay(pgc_t *, int cga); +extern void pgc_speed_changed(void *priv); +extern void pgc_close_common(void *priv); +extern void pgc_close(void *priv); +extern void pgc_init(pgc_t *, + int maxw, int maxh, int visw, int vish, + int (*inpbyte)(pgc_t *, uint8_t *), double npc); /* Misc support functions. */ -extern void pgc_sto_raster(pgc_t *, int16_t *x, int16_t *y); -extern void pgc_ito_raster(pgc_t *, int32_t *x, int32_t *y); -extern void pgc_dto_raster(pgc_t *, double *x, double *y); -//extern int pgc_input_byte(pgc_t *, uint8_t *val); -//extern int pgc_output_byte(pgc_t *, uint8_t val); -extern int pgc_output_string(pgc_t *, const char *val); -//extern int pgc_error_byte(pgc_t *, uint8_t val); -extern int pgc_error_string(pgc_t *, const char *val); -extern int pgc_error(pgc_t *, int err); +extern void pgc_sto_raster(pgc_t *, int16_t *x, int16_t *y); +extern void pgc_ito_raster(pgc_t *, int32_t *x, int32_t *y); +extern void pgc_dto_raster(pgc_t *, double *x, double *y); +#if 0 +extern int pgc_input_byte(pgc_t *, uint8_t *val); +extern int pgc_output_byte(pgc_t *, uint8_t val); +#endif +extern int pgc_output_string(pgc_t *, const char *val); +#if 0 +extern int pgc_error_byte(pgc_t *, uint8_t val); +#endif +extern int pgc_error_string(pgc_t *, const char *val); +extern int pgc_error(pgc_t *, int err); /* Graphics functions. */ -extern uint8_t *pgc_vram_addr(pgc_t *, int16_t x, int16_t y); -extern void pgc_write_pixel(pgc_t *, uint16_t x, uint16_t y, uint8_t ink); -extern uint8_t pgc_read_pixel(pgc_t *, uint16_t x, uint16_t y); -extern void pgc_plot(pgc_t *, uint16_t x, uint16_t y); -extern uint16_t pgc_draw_line_r(pgc_t *, int32_t x1, int32_t y1, - int32_t x2, int32_t y2, uint16_t linemask); -extern void pgc_fill_line_r(pgc_t *, int32_t x0, int32_t x1, int32_t y); -extern uint16_t pgc_draw_line(pgc_t *, int32_t x1, int32_t y1, - int32_t x2, int32_t y2, uint16_t linemask); -extern void pgc_draw_ellipse(pgc_t *, int32_t x, int32_t y); -extern void pgc_fill_polygon(pgc_t *, - unsigned corners, int32_t *x, int32_t *y); +extern uint8_t *pgc_vram_addr(pgc_t *, int16_t x, int16_t y); +extern void pgc_write_pixel(pgc_t *, uint16_t x, uint16_t y, uint8_t ink); +extern uint8_t pgc_read_pixel(pgc_t *, uint16_t x, uint16_t y); +extern void pgc_plot(pgc_t *, uint16_t x, uint16_t y); +extern uint16_t pgc_draw_line_r(pgc_t *, int32_t x1, int32_t y1, + int32_t x2, int32_t y2, uint16_t linemask); +extern void pgc_fill_line_r(pgc_t *, int32_t x0, int32_t x1, int32_t y); +extern uint16_t pgc_draw_line(pgc_t *, int32_t x1, int32_t y1, + int32_t x2, int32_t y2, uint16_t linemask); +extern void pgc_draw_ellipse(pgc_t *, int32_t x, int32_t y); +extern void pgc_fill_polygon(pgc_t *, + unsigned corners, int32_t *x, int32_t *y); /* Command and parameter handling functions. */ -extern int pgc_clist_byte(pgc_t *, uint8_t *val); -extern int pgc_cl_append(pgc_cl_t *, uint8_t v); -extern int pgc_parse_bytes(pgc_t *, pgc_cl_t *, int p); -extern int pgc_parse_words(pgc_t *, pgc_cl_t *, int p); -extern int pgc_parse_coords(pgc_t *, pgc_cl_t *, int p); -extern int pgc_param_byte(pgc_t *, uint8_t *val); -extern int pgc_param_word(pgc_t *, int16_t *val); -extern int pgc_param_coord(pgc_t *, int32_t *val); -extern int pgc_result_byte(pgc_t *, uint8_t val); -extern int pgc_result_word(pgc_t *, int16_t val); -extern int pgc_result_coord(pgc_t *, int32_t val); +extern int pgc_clist_byte(pgc_t *, uint8_t *val); +extern int pgc_cl_append(pgc_cl_t *, uint8_t v); +extern int pgc_parse_bytes(pgc_t *, pgc_cl_t *, int p); +extern int pgc_parse_words(pgc_t *, pgc_cl_t *, int p); +extern int pgc_parse_coords(pgc_t *, pgc_cl_t *, int p); +extern int pgc_param_byte(pgc_t *, uint8_t *val); +extern int pgc_param_word(pgc_t *, int16_t *val); +extern int pgc_param_coord(pgc_t *, int32_t *val); +extern int pgc_result_byte(pgc_t *, uint8_t val); +extern int pgc_result_word(pgc_t *, int16_t val); +extern int pgc_result_coord(pgc_t *, int32_t val); /* Special overload functions for non-IBM implementations. */ -extern void pgc_hndl_lut8(pgc_t *); -extern void pgc_hndl_lut8rd(pgc_t *); +extern void pgc_hndl_lut8(pgc_t *); +extern void pgc_hndl_lut8rd(pgc_t *); - -#endif /*VID_PGC_H*/ +#endif /*VID_PGC_H*/ diff --git a/src/include/86box/vid_pgc_palette.h b/src/include/86box/vid_pgc_palette.h index ccc9ac2bd..a242e0cbd 100644 --- a/src/include/86box/vid_pgc_palette.h +++ b/src/include/86box/vid_pgc_palette.h @@ -1,1579 +1,1578 @@ /* - * 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. + * 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. + * This file is part of the 86Box distribution. * - * Palette definitions for the PGC core. + * Palette definitions for the PGC core. * * * - * Authors: Fred N. van Kempen, - * John Elliott, + * Authors: Fred N. van Kempen, + * John Elliott, * - * Copyright 2019 Fred N. van Kempen. - * Copyright 2019 John Elliott. + * Copyright 2019 Fred N. van Kempen. + * Copyright 2019 John Elliott. */ -#ifndef VID_PGC_PALETTE_H -# define VID_PGC_PALETTE_H +#ifndef VID_PGC_PALETTE_H +#define VID_PGC_PALETTE_H /* Palette 0: Default */ - { - makecol(0x00,0x00,0x00), - makecol(0x11,0x11,0x11), - makecol(0x22,0x22,0x22), - makecol(0x33,0x33,0x33), - makecol(0x44,0x44,0x44), - makecol(0x55,0x55,0x55), - makecol(0x66,0x66,0x66), - makecol(0x77,0x77,0x77), - makecol(0x88,0x88,0x88), - makecol(0x99,0x99,0x99), - makecol(0xaa,0xaa,0xaa), - makecol(0xbb,0xbb,0xbb), - makecol(0xcc,0xcc,0xcc), - makecol(0xdd,0xdd,0xdd), - makecol(0xee,0xee,0xee), - makecol(0xff,0xff,0xff), - makecol(0x00,0x00,0x00), - makecol(0x00,0x22,0x00), - makecol(0x00,0x44,0x00), - makecol(0x00,0x66,0x00), - makecol(0x00,0x88,0x00), - makecol(0x00,0xaa,0x00), - makecol(0x00,0xcc,0x00), - makecol(0x00,0xee,0x00), - makecol(0x00,0xff,0x00), - makecol(0x22,0xff,0x22), - makecol(0x44,0xff,0x44), - makecol(0x66,0xff,0x66), - makecol(0x88,0xff,0x88), - makecol(0xaa,0xff,0xaa), - makecol(0xcc,0xff,0xcc), - makecol(0xee,0xff,0xee), - makecol(0x00,0x00,0x00), - makecol(0x00,0x22,0x11), - makecol(0x00,0x44,0x22), - makecol(0x00,0x66,0x33), - makecol(0x00,0x88,0x44), - makecol(0x00,0xaa,0x55), - makecol(0x00,0xcc,0x66), - makecol(0x00,0xee,0x77), - makecol(0x00,0xff,0x88), - makecol(0x22,0xff,0x99), - makecol(0x44,0xff,0xaa), - makecol(0x66,0xff,0xbb), - makecol(0x88,0xff,0xcc), - makecol(0xaa,0xff,0xdd), - makecol(0xcc,0xff,0xee), - makecol(0xee,0xff,0xff), - makecol(0x00,0x00,0x00), - makecol(0x00,0x22,0x22), - makecol(0x00,0x44,0x44), - makecol(0x00,0x66,0x66), - makecol(0x00,0x88,0x88), - makecol(0x00,0xaa,0xaa), - makecol(0x00,0xcc,0xcc), - makecol(0x00,0xee,0xee), - makecol(0x00,0xff,0xff), - makecol(0x22,0xff,0xff), - makecol(0x44,0xff,0xff), - makecol(0x66,0xff,0xff), - makecol(0x88,0xff,0xff), - makecol(0xaa,0xff,0xff), - makecol(0xcc,0xff,0xff), - makecol(0xee,0xff,0xff), - makecol(0x00,0x00,0x00), - makecol(0x00,0x11,0x22), - makecol(0x00,0x22,0x44), - makecol(0x00,0x33,0x66), - makecol(0x00,0x44,0x88), - makecol(0x00,0x55,0xaa), - makecol(0x00,0x66,0xcc), - makecol(0x00,0x77,0xee), - makecol(0x00,0x88,0xff), - makecol(0x22,0x99,0xff), - makecol(0x44,0xaa,0xff), - makecol(0x66,0xbb,0xff), - makecol(0x88,0xcc,0xff), - makecol(0xaa,0xdd,0xff), - makecol(0xcc,0xee,0xff), - makecol(0xee,0xff,0xff), - makecol(0x00,0x00,0x00), - makecol(0x00,0x00,0x22), - makecol(0x00,0x00,0x44), - makecol(0x00,0x00,0x66), - makecol(0x00,0x00,0x88), - makecol(0x00,0x00,0xaa), - makecol(0x00,0x00,0xcc), - makecol(0x00,0x00,0xee), - makecol(0x00,0x00,0xff), - makecol(0x22,0x22,0xff), - makecol(0x44,0x44,0xff), - makecol(0x66,0x66,0xff), - makecol(0x88,0x88,0xff), - makecol(0xaa,0xaa,0xff), - makecol(0xcc,0xcc,0xff), - makecol(0xee,0xee,0xff), - makecol(0x00,0x00,0x00), - makecol(0x11,0x00,0x22), - makecol(0x22,0x00,0x44), - makecol(0x33,0x00,0x66), - makecol(0x44,0x00,0x88), - makecol(0x55,0x00,0xaa), - makecol(0x66,0x00,0xcc), - makecol(0x77,0x00,0xee), - makecol(0x88,0x00,0xff), - makecol(0x99,0x22,0xff), - makecol(0xaa,0x44,0xff), - makecol(0xbb,0x66,0xff), - makecol(0xcc,0x88,0xff), - makecol(0xdd,0xaa,0xff), - makecol(0xee,0xcc,0xff), - makecol(0xff,0xee,0xff), - makecol(0x00,0x00,0x00), - makecol(0x22,0x00,0x22), - makecol(0x44,0x00,0x44), - makecol(0x66,0x00,0x66), - makecol(0x88,0x00,0x88), - makecol(0xaa,0x00,0xaa), - makecol(0xcc,0x00,0xcc), - makecol(0xee,0x00,0xee), - makecol(0xff,0x00,0xff), - makecol(0xff,0x22,0xff), - makecol(0xff,0x44,0xff), - makecol(0xff,0x66,0xff), - makecol(0xff,0x88,0xff), - makecol(0xff,0xaa,0xff), - makecol(0xff,0xcc,0xff), - makecol(0xff,0xee,0xff), - makecol(0x00,0x00,0x00), - makecol(0x22,0x00,0x11), - makecol(0x44,0x00,0x22), - makecol(0x66,0x00,0x33), - makecol(0x88,0x00,0x44), - makecol(0xaa,0x00,0x55), - makecol(0xcc,0x00,0x66), - makecol(0xee,0x00,0x77), - makecol(0xff,0x00,0x88), - makecol(0xff,0x22,0x99), - makecol(0xff,0x44,0xaa), - makecol(0xff,0x66,0xbb), - makecol(0xff,0x88,0xcc), - makecol(0xff,0xaa,0xdd), - makecol(0xff,0xcc,0xee), - makecol(0xff,0xee,0xff), - makecol(0x00,0x00,0x00), - makecol(0x22,0x00,0x00), - makecol(0x44,0x00,0x00), - makecol(0x66,0x00,0x00), - makecol(0x88,0x00,0x00), - makecol(0xaa,0x00,0x00), - makecol(0xcc,0x00,0x00), - makecol(0xee,0x00,0x00), - makecol(0xff,0x00,0x00), - makecol(0xff,0x22,0x22), - makecol(0xff,0x44,0x44), - makecol(0xff,0x66,0x66), - makecol(0xff,0x88,0x88), - makecol(0xff,0xaa,0xaa), - makecol(0xff,0xcc,0xcc), - makecol(0xff,0xee,0xee), - makecol(0x00,0x00,0x00), - makecol(0x22,0x11,0x00), - makecol(0x44,0x22,0x00), - makecol(0x66,0x33,0x00), - makecol(0x88,0x44,0x00), - makecol(0xaa,0x55,0x00), - makecol(0xcc,0x66,0x00), - makecol(0xee,0x77,0x00), - makecol(0xff,0x88,0x00), - makecol(0xff,0x99,0x22), - makecol(0xff,0xaa,0x44), - makecol(0xff,0xbb,0x66), - makecol(0xff,0xcc,0x88), - makecol(0xff,0xdd,0xaa), - makecol(0xff,0xee,0xcc), - makecol(0xff,0xff,0xee), - makecol(0x00,0x00,0x00), - makecol(0x22,0x22,0x00), - makecol(0x44,0x44,0x00), - makecol(0x66,0x66,0x00), - makecol(0x88,0x88,0x00), - makecol(0xaa,0xaa,0x00), - makecol(0xcc,0xcc,0x00), - makecol(0xee,0xee,0x00), - makecol(0xff,0xff,0x00), - makecol(0xff,0xff,0x22), - makecol(0xff,0xff,0x44), - makecol(0xff,0xff,0x66), - makecol(0xff,0xff,0x88), - makecol(0xff,0xff,0xaa), - makecol(0xff,0xff,0xcc), - makecol(0xff,0xff,0xee), - makecol(0x00,0x00,0x00), - makecol(0x11,0x22,0x00), - makecol(0x22,0x44,0x00), - makecol(0x33,0x66,0x00), - makecol(0x44,0x88,0x00), - makecol(0x55,0xaa,0x00), - makecol(0x66,0xcc,0x00), - makecol(0x77,0xee,0x00), - makecol(0x88,0xff,0x00), - makecol(0x99,0xff,0x22), - makecol(0xaa,0xff,0x44), - makecol(0xbb,0xff,0x66), - makecol(0xcc,0xff,0x88), - makecol(0xdd,0xff,0xaa), - makecol(0xee,0xff,0xcc), - makecol(0xff,0xff,0xee), - makecol(0x00,0x00,0x00), - makecol(0x00,0x11,0x00), - makecol(0x11,0x33,0x11), - makecol(0x11,0x44,0x11), - makecol(0x22,0x66,0x22), - makecol(0x22,0x77,0x22), - makecol(0x33,0x99,0x33), - makecol(0x33,0xaa,0x33), - makecol(0x44,0xcc,0x44), - makecol(0x55,0xcc,0x55), - makecol(0x77,0xdd,0x77), - makecol(0x88,0xdd,0x88), - makecol(0xaa,0xee,0xaa), - makecol(0xbb,0xee,0xbb), - makecol(0xdd,0xff,0xdd), - makecol(0xee,0xff,0xee), - makecol(0x00,0x00,0x00), - makecol(0x11,0x00,0x00), - makecol(0x33,0x11,0x11), - makecol(0x44,0x11,0x11), - makecol(0x66,0x22,0x22), - makecol(0x77,0x22,0x22), - makecol(0x99,0x33,0x33), - makecol(0xaa,0x33,0x33), - makecol(0xcc,0x44,0x44), - makecol(0xcc,0x55,0x55), - makecol(0xdd,0x77,0x77), - makecol(0xdd,0x88,0x88), - makecol(0xee,0xaa,0xaa), - makecol(0xee,0xbb,0xbb), - makecol(0xff,0xdd,0xdd), - makecol(0xff,0xee,0xee), - makecol(0x00,0x00,0x00), - makecol(0x00,0x00,0x11), - makecol(0x11,0x11,0x33), - makecol(0x11,0x11,0x44), - makecol(0x22,0x22,0x66), - makecol(0x22,0x22,0x77), - makecol(0x33,0x33,0x99), - makecol(0x33,0x33,0xaa), - makecol(0x44,0x44,0xcc), - makecol(0x55,0x55,0xcc), - makecol(0x77,0x77,0xdd), - makecol(0x88,0x88,0xdd), - makecol(0xaa,0xaa,0xee), - makecol(0xbb,0xbb,0xee), - makecol(0xdd,0xdd,0xff), - makecol(0xee,0xee,0xff), - }, -/* Palette 1: 16-colour palette */ - { - makecol(0x88,0x66,0xdd), - makecol(0x00,0x00,0x00), - makecol(0x44,0x77,0x22), - makecol(0x77,0xaa,0x44), - makecol(0x00,0x77,0x00), - makecol(0x00,0xff,0x00), - makecol(0x77,0xff,0x00), - makecol(0xff,0xff,0x00), - makecol(0xff,0xaa,0x00), - makecol(0xff,0x00,0x00), - makecol(0x77,0x00,0x00), - makecol(0x77,0x00,0x77), - makecol(0x00,0x00,0x77), - makecol(0x99,0xee,0x66), - makecol(0x77,0x77,0x77), - makecol(0xff,0xff,0xff), - makecol(0x00,0x00,0x00), - makecol(0x00,0x00,0x00), - makecol(0x00,0x00,0x00), - makecol(0x00,0x00,0x00), - makecol(0x00,0x00,0x00), - makecol(0x00,0x00,0x00), - makecol(0x00,0x00,0x00), - makecol(0x00,0x00,0x00), - makecol(0x00,0x00,0x00), - makecol(0x00,0x00,0x00), - makecol(0x00,0x00,0x00), - makecol(0x00,0x00,0x00), - makecol(0x00,0x00,0x00), - makecol(0x00,0x00,0x00), - makecol(0x00,0x00,0x00), - makecol(0x00,0x00,0x00), - makecol(0x44,0x77,0x22), - makecol(0x44,0x77,0x22), - makecol(0x44,0x77,0x22), - makecol(0x44,0x77,0x22), - makecol(0x44,0x77,0x22), - makecol(0x44,0x77,0x22), - makecol(0x44,0x77,0x22), - makecol(0x44,0x77,0x22), - makecol(0x44,0x77,0x22), - makecol(0x44,0x77,0x22), - makecol(0x44,0x77,0x22), - makecol(0x44,0x77,0x22), - makecol(0x44,0x77,0x22), - makecol(0x44,0x77,0x22), - makecol(0x44,0x77,0x22), - makecol(0x44,0x77,0x22), - makecol(0x77,0xaa,0x44), - makecol(0x77,0xaa,0x44), - makecol(0x77,0xaa,0x44), - makecol(0x77,0xaa,0x44), - makecol(0x77,0xaa,0x44), - makecol(0x77,0xaa,0x44), - makecol(0x77,0xaa,0x44), - makecol(0x77,0xaa,0x44), - makecol(0x77,0xaa,0x44), - makecol(0x77,0xaa,0x44), - makecol(0x77,0xaa,0x44), - makecol(0x77,0xaa,0x44), - makecol(0x77,0xaa,0x44), - makecol(0x77,0xaa,0x44), - makecol(0x77,0xaa,0x44), - makecol(0x77,0xaa,0x44), - makecol(0x00,0x77,0x00), - makecol(0x00,0x77,0x00), - makecol(0x00,0x77,0x00), - makecol(0x00,0x77,0x00), - makecol(0x00,0x77,0x00), - makecol(0x00,0x77,0x00), - makecol(0x00,0x77,0x00), - makecol(0x00,0x77,0x00), - makecol(0x00,0x77,0x00), - makecol(0x00,0x77,0x00), - makecol(0x00,0x77,0x00), - makecol(0x00,0x77,0x00), - makecol(0x00,0x77,0x00), - makecol(0x00,0x77,0x00), - makecol(0x00,0x77,0x00), - makecol(0x00,0x77,0x00), - makecol(0x00,0xff,0x00), - makecol(0x00,0xff,0x00), - makecol(0x00,0xff,0x00), - makecol(0x00,0xff,0x00), - makecol(0x00,0xff,0x00), - makecol(0x00,0xff,0x00), - makecol(0x00,0xff,0x00), - makecol(0x00,0xff,0x00), - makecol(0x00,0xff,0x00), - makecol(0x00,0xff,0x00), - makecol(0x00,0xff,0x00), - makecol(0x00,0xff,0x00), - makecol(0x00,0xff,0x00), - makecol(0x00,0xff,0x00), - makecol(0x00,0xff,0x00), - makecol(0x00,0xff,0x00), - makecol(0x77,0xff,0x00), - makecol(0x77,0xff,0x00), - makecol(0x77,0xff,0x00), - makecol(0x77,0xff,0x00), - makecol(0x77,0xff,0x00), - makecol(0x77,0xff,0x00), - makecol(0x77,0xff,0x00), - makecol(0x77,0xff,0x00), - makecol(0x77,0xff,0x00), - makecol(0x77,0xff,0x00), - makecol(0x77,0xff,0x00), - makecol(0x77,0xff,0x00), - makecol(0x77,0xff,0x00), - makecol(0x77,0xff,0x00), - makecol(0x77,0xff,0x00), - makecol(0x77,0xff,0x00), - makecol(0xff,0xff,0x00), - makecol(0xff,0xff,0x00), - makecol(0xff,0xff,0x00), - makecol(0xff,0xff,0x00), - makecol(0xff,0xff,0x00), - makecol(0xff,0xff,0x00), - makecol(0xff,0xff,0x00), - makecol(0xff,0xff,0x00), - makecol(0xff,0xff,0x00), - makecol(0xff,0xff,0x00), - makecol(0xff,0xff,0x00), - makecol(0xff,0xff,0x00), - makecol(0xff,0xff,0x00), - makecol(0xff,0xff,0x00), - makecol(0xff,0xff,0x00), - makecol(0xff,0xff,0x00), - makecol(0xff,0xaa,0x00), - makecol(0xff,0xaa,0x00), - makecol(0xff,0xaa,0x00), - makecol(0xff,0xaa,0x00), - makecol(0xff,0xaa,0x00), - makecol(0xff,0xaa,0x00), - makecol(0xff,0xaa,0x00), - makecol(0xff,0xaa,0x00), - makecol(0xff,0xaa,0x00), - makecol(0xff,0xaa,0x00), - makecol(0xff,0xaa,0x00), - makecol(0xff,0xaa,0x00), - makecol(0xff,0xaa,0x00), - makecol(0xff,0xaa,0x00), - makecol(0xff,0xaa,0x00), - makecol(0xff,0xaa,0x00), - makecol(0xff,0x00,0x00), - makecol(0xff,0x00,0x00), - makecol(0xff,0x00,0x00), - makecol(0xff,0x00,0x00), - makecol(0xff,0x00,0x00), - makecol(0xff,0x00,0x00), - makecol(0xff,0x00,0x00), - makecol(0xff,0x00,0x00), - makecol(0xff,0x00,0x00), - makecol(0xff,0x00,0x00), - makecol(0xff,0x00,0x00), - makecol(0xff,0x00,0x00), - makecol(0xff,0x00,0x00), - makecol(0xff,0x00,0x00), - makecol(0xff,0x00,0x00), - makecol(0xff,0x00,0x00), - makecol(0x77,0x00,0x00), - makecol(0x77,0x00,0x00), - makecol(0x77,0x00,0x00), - makecol(0x77,0x00,0x00), - makecol(0x77,0x00,0x00), - makecol(0x77,0x00,0x00), - makecol(0x77,0x00,0x00), - makecol(0x77,0x00,0x00), - makecol(0x77,0x00,0x00), - makecol(0x77,0x00,0x00), - makecol(0x77,0x00,0x00), - makecol(0x77,0x00,0x00), - makecol(0x77,0x00,0x00), - makecol(0x77,0x00,0x00), - makecol(0x77,0x00,0x00), - makecol(0x77,0x00,0x00), - makecol(0x77,0x00,0x77), - makecol(0x77,0x00,0x77), - makecol(0x77,0x00,0x77), - makecol(0x77,0x00,0x77), - makecol(0x77,0x00,0x77), - makecol(0x77,0x00,0x77), - makecol(0x77,0x00,0x77), - makecol(0x77,0x00,0x77), - makecol(0x77,0x00,0x77), - makecol(0x77,0x00,0x77), - makecol(0x77,0x00,0x77), - makecol(0x77,0x00,0x77), - makecol(0x77,0x00,0x77), - makecol(0x77,0x00,0x77), - makecol(0x77,0x00,0x77), - makecol(0x77,0x00,0x77), - makecol(0x00,0x00,0x77), - makecol(0x00,0x00,0x77), - makecol(0x00,0x00,0x77), - makecol(0x00,0x00,0x77), - makecol(0x00,0x00,0x77), - makecol(0x00,0x00,0x77), - makecol(0x00,0x00,0x77), - makecol(0x00,0x00,0x77), - makecol(0x00,0x00,0x77), - makecol(0x00,0x00,0x77), - makecol(0x00,0x00,0x77), - makecol(0x00,0x00,0x77), - makecol(0x00,0x00,0x77), - makecol(0x00,0x00,0x77), - makecol(0x00,0x00,0x77), - makecol(0x00,0x00,0x77), - makecol(0x99,0xee,0x66), - makecol(0x99,0xee,0x66), - makecol(0x99,0xee,0x66), - makecol(0x99,0xee,0x66), - makecol(0x99,0xee,0x66), - makecol(0x99,0xee,0x66), - makecol(0x99,0xee,0x66), - makecol(0x99,0xee,0x66), - makecol(0x99,0xee,0x66), - makecol(0x99,0xee,0x66), - makecol(0x99,0xee,0x66), - makecol(0x99,0xee,0x66), - makecol(0x99,0xee,0x66), - makecol(0x99,0xee,0x66), - makecol(0x99,0xee,0x66), - makecol(0x99,0xee,0x66), - makecol(0x77,0x77,0x77), - makecol(0x77,0x77,0x77), - makecol(0x77,0x77,0x77), - makecol(0x77,0x77,0x77), - makecol(0x77,0x77,0x77), - makecol(0x77,0x77,0x77), - makecol(0x77,0x77,0x77), - makecol(0x77,0x77,0x77), - makecol(0x77,0x77,0x77), - makecol(0x77,0x77,0x77), - makecol(0x77,0x77,0x77), - makecol(0x77,0x77,0x77), - makecol(0x77,0x77,0x77), - makecol(0x77,0x77,0x77), - makecol(0x77,0x77,0x77), - makecol(0x77,0x77,0x77), - makecol(0xff,0xff,0xff), - makecol(0xff,0xff,0xff), - makecol(0xff,0xff,0xff), - makecol(0xff,0xff,0xff), - makecol(0xff,0xff,0xff), - makecol(0xff,0xff,0xff), - makecol(0xff,0xff,0xff), - makecol(0xff,0xff,0xff), - makecol(0xff,0xff,0xff), - makecol(0xff,0xff,0xff), - makecol(0xff,0xff,0xff), - makecol(0xff,0xff,0xff), - makecol(0xff,0xff,0xff), - makecol(0xff,0xff,0xff), - makecol(0xff,0xff,0xff), - makecol(0xff,0xff,0xff), - }, -/* Palette 2: 2-3-3 truecolour */ - { - makecol(0x00,0x00,0x00), - makecol(0x00,0x00,0x33), - makecol(0x00,0x00,0x55), - makecol(0x00,0x00,0x77), - makecol(0x00,0x00,0x99), - makecol(0x00,0x00,0xbb), - makecol(0x00,0x00,0xdd), - makecol(0x00,0x00,0xff), - makecol(0x33,0x00,0x00), - makecol(0x33,0x00,0x33), - makecol(0x33,0x00,0x55), - makecol(0x33,0x00,0x77), - makecol(0x33,0x00,0x99), - makecol(0x33,0x00,0xbb), - makecol(0x33,0x00,0xdd), - makecol(0x33,0x00,0xff), - makecol(0x55,0x00,0x00), - makecol(0x55,0x00,0x33), - makecol(0x55,0x00,0x55), - makecol(0x55,0x00,0x77), - makecol(0x55,0x00,0x99), - makecol(0x55,0x00,0xbb), - makecol(0x55,0x00,0xdd), - makecol(0x55,0x00,0xff), - makecol(0x77,0x00,0x00), - makecol(0x77,0x00,0x33), - makecol(0x77,0x00,0x55), - makecol(0x77,0x00,0x77), - makecol(0x77,0x00,0x99), - makecol(0x77,0x00,0xbb), - makecol(0x77,0x00,0xdd), - makecol(0x77,0x00,0xff), - makecol(0x99,0x00,0x00), - makecol(0x99,0x00,0x33), - makecol(0x99,0x00,0x55), - makecol(0x99,0x00,0x77), - makecol(0x99,0x00,0x99), - makecol(0x99,0x00,0xbb), - makecol(0x99,0x00,0xdd), - makecol(0x99,0x00,0xff), - makecol(0xbb,0x00,0x00), - makecol(0xbb,0x00,0x33), - makecol(0xbb,0x00,0x55), - makecol(0xbb,0x00,0x77), - makecol(0xbb,0x00,0x99), - makecol(0xbb,0x00,0xbb), - makecol(0xbb,0x00,0xdd), - makecol(0xbb,0x00,0xff), - makecol(0xdd,0x00,0x00), - makecol(0xdd,0x00,0x33), - makecol(0xdd,0x00,0x55), - makecol(0xdd,0x00,0x77), - makecol(0xdd,0x00,0x99), - makecol(0xdd,0x00,0xbb), - makecol(0xdd,0x00,0xdd), - makecol(0xdd,0x00,0xff), - makecol(0xff,0x00,0x00), - makecol(0xff,0x00,0x33), - makecol(0xff,0x00,0x55), - makecol(0xff,0x00,0x77), - makecol(0xff,0x00,0x99), - makecol(0xff,0x00,0xbb), - makecol(0xff,0x00,0xdd), - makecol(0xff,0x00,0xff), - makecol(0x00,0x55,0x00), - makecol(0x00,0x55,0x33), - makecol(0x00,0x55,0x55), - makecol(0x00,0x55,0x77), - makecol(0x00,0x55,0x99), - makecol(0x00,0x55,0xbb), - makecol(0x00,0x55,0xdd), - makecol(0x00,0x55,0xff), - makecol(0x33,0x55,0x00), - makecol(0x33,0x55,0x33), - makecol(0x33,0x55,0x55), - makecol(0x33,0x55,0x77), - makecol(0x33,0x55,0x99), - makecol(0x33,0x55,0xbb), - makecol(0x33,0x55,0xdd), - makecol(0x33,0x55,0xff), - makecol(0x55,0x55,0x00), - makecol(0x55,0x55,0x33), - makecol(0x55,0x55,0x55), - makecol(0x55,0x55,0x77), - makecol(0x55,0x55,0x99), - makecol(0x55,0x55,0xbb), - makecol(0x55,0x55,0xdd), - makecol(0x55,0x55,0xff), - makecol(0x77,0x55,0x00), - makecol(0x77,0x55,0x33), - makecol(0x77,0x55,0x55), - makecol(0x77,0x55,0x77), - makecol(0x77,0x55,0x99), - makecol(0x77,0x55,0xbb), - makecol(0x77,0x55,0xdd), - makecol(0x77,0x55,0xff), - makecol(0x99,0x55,0x00), - makecol(0x99,0x55,0x33), - makecol(0x99,0x55,0x55), - makecol(0x99,0x55,0x77), - makecol(0x99,0x55,0x99), - makecol(0x99,0x55,0xbb), - makecol(0x99,0x55,0xdd), - makecol(0x99,0x55,0xff), - makecol(0xbb,0x55,0x00), - makecol(0xbb,0x55,0x33), - makecol(0xbb,0x55,0x55), - makecol(0xbb,0x55,0x77), - makecol(0xbb,0x55,0x99), - makecol(0xbb,0x55,0xbb), - makecol(0xbb,0x55,0xdd), - makecol(0xbb,0x55,0xff), - makecol(0xdd,0x55,0x00), - makecol(0xdd,0x55,0x33), - makecol(0xdd,0x55,0x55), - makecol(0xdd,0x55,0x77), - makecol(0xdd,0x55,0x99), - makecol(0xdd,0x55,0xbb), - makecol(0xdd,0x55,0xdd), - makecol(0xdd,0x55,0xff), - makecol(0xff,0x55,0x00), - makecol(0xff,0x55,0x33), - makecol(0xff,0x55,0x55), - makecol(0xff,0x55,0x77), - makecol(0xff,0x55,0x99), - makecol(0xff,0x55,0xbb), - makecol(0xff,0x55,0xdd), - makecol(0xff,0x55,0xff), - makecol(0x00,0xaa,0x00), - makecol(0x00,0xaa,0x33), - makecol(0x00,0xaa,0x55), - makecol(0x00,0xaa,0x77), - makecol(0x00,0xaa,0x99), - makecol(0x00,0xaa,0xbb), - makecol(0x00,0xaa,0xdd), - makecol(0x00,0xaa,0xff), - makecol(0x33,0xaa,0x00), - makecol(0x33,0xaa,0x33), - makecol(0x33,0xaa,0x55), - makecol(0x33,0xaa,0x77), - makecol(0x33,0xaa,0x99), - makecol(0x33,0xaa,0xbb), - makecol(0x33,0xaa,0xdd), - makecol(0x33,0xaa,0xff), - makecol(0x55,0xaa,0x00), - makecol(0x55,0xaa,0x33), - makecol(0x55,0xaa,0x55), - makecol(0x55,0xaa,0x77), - makecol(0x55,0xaa,0x99), - makecol(0x55,0xaa,0xbb), - makecol(0x55,0xaa,0xdd), - makecol(0x55,0xaa,0xff), - makecol(0x77,0xaa,0x00), - makecol(0x77,0xaa,0x33), - makecol(0x77,0xaa,0x55), - makecol(0x77,0xaa,0x77), - makecol(0x77,0xaa,0x99), - makecol(0x77,0xaa,0xbb), - makecol(0x77,0xaa,0xdd), - makecol(0x77,0xaa,0xff), - makecol(0x99,0xaa,0x00), - makecol(0x99,0xaa,0x33), - makecol(0x99,0xaa,0x55), - makecol(0x99,0xaa,0x77), - makecol(0x99,0xaa,0x99), - makecol(0x99,0xaa,0xbb), - makecol(0x99,0xaa,0xdd), - makecol(0x99,0xaa,0xff), - makecol(0xbb,0xaa,0x00), - makecol(0xbb,0xaa,0x33), - makecol(0xbb,0xaa,0x55), - makecol(0xbb,0xaa,0x77), - makecol(0xbb,0xaa,0x99), - makecol(0xbb,0xaa,0xbb), - makecol(0xbb,0xaa,0xdd), - makecol(0xbb,0xaa,0xff), - makecol(0xdd,0xaa,0x00), - makecol(0xdd,0xaa,0x33), - makecol(0xdd,0xaa,0x55), - makecol(0xdd,0xaa,0x77), - makecol(0xdd,0xaa,0x99), - makecol(0xdd,0xaa,0xbb), - makecol(0xdd,0xaa,0xdd), - makecol(0xdd,0xaa,0xff), - makecol(0xff,0xaa,0x00), - makecol(0xff,0xaa,0x33), - makecol(0xff,0xaa,0x55), - makecol(0xff,0xaa,0x77), - makecol(0xff,0xaa,0x99), - makecol(0xff,0xaa,0xbb), - makecol(0xff,0xaa,0xdd), - makecol(0xff,0xaa,0xee), - makecol(0x00,0xff,0x00), - makecol(0x00,0xff,0x33), - makecol(0x00,0xff,0x55), - makecol(0x00,0xff,0x77), - makecol(0x00,0xff,0x99), - makecol(0x00,0xff,0xbb), - makecol(0x00,0xff,0xdd), - makecol(0x00,0xff,0xff), - makecol(0x33,0xff,0x00), - makecol(0x33,0xff,0x33), - makecol(0x33,0xff,0x55), - makecol(0x33,0xff,0x77), - makecol(0x33,0xff,0x99), - makecol(0x33,0xff,0xbb), - makecol(0x33,0xff,0xdd), - makecol(0x33,0xff,0xff), - makecol(0x55,0xff,0x00), - makecol(0x55,0xff,0x33), - makecol(0x55,0xff,0x55), - makecol(0x55,0xff,0x77), - makecol(0x55,0xff,0x99), - makecol(0x55,0xff,0xbb), - makecol(0x55,0xff,0xdd), - makecol(0x55,0xff,0xff), - makecol(0x77,0xff,0x00), - makecol(0x77,0xff,0x33), - makecol(0x77,0xff,0x55), - makecol(0x77,0xff,0x77), - makecol(0x77,0xff,0x99), - makecol(0x77,0xff,0xbb), - makecol(0x77,0xff,0xdd), - makecol(0x77,0xff,0xff), - makecol(0x99,0xff,0x00), - makecol(0x99,0xff,0x33), - makecol(0x99,0xff,0x55), - makecol(0x99,0xff,0x77), - makecol(0x99,0xff,0x99), - makecol(0x99,0xff,0xbb), - makecol(0x99,0xff,0xdd), - makecol(0x99,0xff,0xff), - makecol(0xbb,0xff,0x00), - makecol(0xbb,0xff,0x33), - makecol(0xbb,0xff,0x55), - makecol(0xbb,0xff,0x77), - makecol(0xbb,0xff,0x99), - makecol(0xbb,0xff,0xbb), - makecol(0xbb,0xff,0xdd), - makecol(0xbb,0xff,0xff), - makecol(0xdd,0xff,0x00), - makecol(0xdd,0xff,0x33), - makecol(0xdd,0xff,0x55), - makecol(0xdd,0xff,0x77), - makecol(0xdd,0xff,0x99), - makecol(0xdd,0xff,0xbb), - makecol(0xdd,0xff,0xdd), - makecol(0xdd,0xff,0xff), - makecol(0xff,0xff,0x00), - makecol(0xff,0xff,0x33), - makecol(0xff,0xff,0x55), - makecol(0xff,0xff,0x77), - makecol(0xff,0xff,0x99), - makecol(0xff,0xff,0xbb), - makecol(0xff,0xff,0xdd), - makecol(0xff,0xff,0xff), - }, -/* Palette 3: 3-2-3 truecolour */ - { - makecol(0x00,0x00,0x00), - makecol(0x00,0x00,0x33), - makecol(0x00,0x00,0x55), - makecol(0x00,0x00,0x77), - makecol(0x00,0x00,0x99), - makecol(0x00,0x00,0xbb), - makecol(0x00,0x00,0xdd), - makecol(0x00,0x00,0xff), - makecol(0x55,0x00,0x00), - makecol(0x55,0x00,0x33), - makecol(0x55,0x00,0x55), - makecol(0x55,0x00,0x77), - makecol(0x55,0x00,0x99), - makecol(0x55,0x00,0xbb), - makecol(0x55,0x00,0xdd), - makecol(0x55,0x00,0xff), - makecol(0xaa,0x00,0x00), - makecol(0xaa,0x00,0x33), - makecol(0xaa,0x00,0x55), - makecol(0xaa,0x00,0x77), - makecol(0xaa,0x00,0x99), - makecol(0xaa,0x00,0xbb), - makecol(0xaa,0x00,0xdd), - makecol(0xaa,0x00,0xff), - makecol(0xff,0x00,0x00), - makecol(0xff,0x00,0x33), - makecol(0xff,0x00,0x55), - makecol(0xff,0x00,0x77), - makecol(0xff,0x00,0x99), - makecol(0xff,0x00,0xbb), - makecol(0xff,0x00,0xdd), - makecol(0xff,0x00,0xff), - makecol(0x00,0x33,0x00), - makecol(0x00,0x33,0x33), - makecol(0x00,0x33,0x55), - makecol(0x00,0x33,0x77), - makecol(0x00,0x33,0x99), - makecol(0x00,0x33,0xbb), - makecol(0x00,0x33,0xdd), - makecol(0x00,0x33,0xff), - makecol(0x55,0x33,0x00), - makecol(0x55,0x33,0x33), - makecol(0x55,0x33,0x55), - makecol(0x55,0x33,0x77), - makecol(0x55,0x33,0x99), - makecol(0x55,0x33,0xbb), - makecol(0x55,0x33,0xdd), - makecol(0x55,0x33,0xff), - makecol(0xaa,0x33,0x00), - makecol(0xaa,0x33,0x33), - makecol(0xaa,0x33,0x55), - makecol(0xaa,0x33,0x77), - makecol(0xaa,0x33,0x99), - makecol(0xaa,0x33,0xbb), - makecol(0xaa,0x33,0xdd), - makecol(0xaa,0x33,0xff), - makecol(0xff,0x33,0x00), - makecol(0xff,0x33,0x33), - makecol(0xff,0x33,0x55), - makecol(0xff,0x33,0x77), - makecol(0xff,0x33,0x99), - makecol(0xff,0x33,0xbb), - makecol(0xff,0x33,0xdd), - makecol(0xff,0x33,0xff), - makecol(0x00,0x55,0x00), - makecol(0x00,0x55,0x33), - makecol(0x00,0x55,0x55), - makecol(0x00,0x55,0x77), - makecol(0x00,0x55,0x99), - makecol(0x00,0x55,0xbb), - makecol(0x00,0x55,0xdd), - makecol(0x00,0x55,0xff), - makecol(0x55,0x55,0x00), - makecol(0x55,0x55,0x33), - makecol(0x55,0x55,0x55), - makecol(0x55,0x55,0x77), - makecol(0x55,0x55,0x99), - makecol(0x55,0x55,0xbb), - makecol(0x55,0x55,0xdd), - makecol(0x55,0x55,0xff), - makecol(0xaa,0x55,0x00), - makecol(0xaa,0x55,0x33), - makecol(0xaa,0x55,0x55), - makecol(0xaa,0x55,0x77), - makecol(0xaa,0x55,0x99), - makecol(0xaa,0x55,0xbb), - makecol(0xaa,0x55,0xdd), - makecol(0xaa,0x55,0xff), - makecol(0xff,0x55,0x00), - makecol(0xff,0x55,0x33), - makecol(0xff,0x55,0x55), - makecol(0xff,0x55,0x77), - makecol(0xff,0x55,0x99), - makecol(0xff,0x55,0xbb), - makecol(0xff,0x55,0xdd), - makecol(0xff,0x55,0xff), - makecol(0x00,0x77,0x00), - makecol(0x00,0x77,0x33), - makecol(0x00,0x77,0x55), - makecol(0x00,0x77,0x77), - makecol(0x00,0x77,0x99), - makecol(0x00,0x77,0xbb), - makecol(0x00,0x77,0xdd), - makecol(0x00,0x77,0xff), - makecol(0x55,0x77,0x00), - makecol(0x55,0x77,0x33), - makecol(0x55,0x77,0x55), - makecol(0x55,0x77,0x77), - makecol(0x55,0x77,0x99), - makecol(0x55,0x77,0xbb), - makecol(0x55,0x77,0xdd), - makecol(0x55,0x77,0xff), - makecol(0xaa,0x77,0x00), - makecol(0xaa,0x77,0x33), - makecol(0xaa,0x77,0x55), - makecol(0xaa,0x77,0x77), - makecol(0xaa,0x77,0x99), - makecol(0xaa,0x77,0xbb), - makecol(0xaa,0x77,0xdd), - makecol(0xaa,0x77,0xff), - makecol(0xff,0x77,0x00), - makecol(0xff,0x77,0x33), - makecol(0xff,0x77,0x55), - makecol(0xff,0x77,0x77), - makecol(0xff,0x77,0x99), - makecol(0xff,0x77,0xbb), - makecol(0xff,0x77,0xdd), - makecol(0xff,0x77,0xff), - makecol(0x00,0x99,0x00), - makecol(0x00,0x99,0x33), - makecol(0x00,0x99,0x55), - makecol(0x00,0x99,0x77), - makecol(0x00,0x99,0x99), - makecol(0x00,0x99,0xbb), - makecol(0x00,0x99,0xdd), - makecol(0x00,0x99,0xff), - makecol(0x55,0x99,0x00), - makecol(0x55,0x99,0x33), - makecol(0x55,0x99,0x55), - makecol(0x55,0x99,0x77), - makecol(0x55,0x99,0x99), - makecol(0x55,0x99,0xbb), - makecol(0x55,0x99,0xdd), - makecol(0x55,0x99,0xff), - makecol(0xaa,0x99,0x00), - makecol(0xaa,0x99,0x33), - makecol(0xaa,0x99,0x55), - makecol(0xaa,0x99,0x77), - makecol(0xaa,0x99,0x99), - makecol(0xaa,0x99,0xbb), - makecol(0xaa,0x99,0xdd), - makecol(0xaa,0x99,0xff), - makecol(0xff,0x99,0x00), - makecol(0xff,0x99,0x33), - makecol(0xff,0x99,0x55), - makecol(0xff,0x99,0x77), - makecol(0xff,0x99,0x99), - makecol(0xff,0x99,0xbb), - makecol(0xff,0x99,0xdd), - makecol(0xff,0x99,0xff), - makecol(0x00,0xbb,0x00), - makecol(0x00,0xbb,0x33), - makecol(0x00,0xbb,0x55), - makecol(0x00,0xbb,0x77), - makecol(0x00,0xbb,0x99), - makecol(0x00,0xbb,0xbb), - makecol(0x00,0xbb,0xdd), - makecol(0x00,0xbb,0xff), - makecol(0x55,0xbb,0x00), - makecol(0x55,0xbb,0x33), - makecol(0x55,0xbb,0x55), - makecol(0x55,0xbb,0x77), - makecol(0x55,0xbb,0x99), - makecol(0x55,0xbb,0xbb), - makecol(0x55,0xbb,0xdd), - makecol(0x55,0xbb,0xff), - makecol(0xaa,0xbb,0x00), - makecol(0xaa,0xbb,0x33), - makecol(0xaa,0xbb,0x55), - makecol(0xaa,0xbb,0x77), - makecol(0xaa,0xbb,0x99), - makecol(0xaa,0xbb,0xbb), - makecol(0xaa,0xbb,0xdd), - makecol(0xaa,0xbb,0xff), - makecol(0xff,0xbb,0x00), - makecol(0xff,0xbb,0x33), - makecol(0xff,0xbb,0x55), - makecol(0xff,0xbb,0x77), - makecol(0xff,0xbb,0x99), - makecol(0xff,0xbb,0xbb), - makecol(0xff,0xbb,0xdd), - makecol(0xff,0xbb,0xff), - makecol(0x00,0xdd,0x00), - makecol(0x00,0xdd,0x33), - makecol(0x00,0xdd,0x55), - makecol(0x00,0xdd,0x77), - makecol(0x00,0xdd,0x99), - makecol(0x00,0xdd,0xbb), - makecol(0x00,0xdd,0xdd), - makecol(0x00,0xdd,0xff), - makecol(0x55,0xdd,0x00), - makecol(0x55,0xdd,0x33), - makecol(0x55,0xdd,0x55), - makecol(0x55,0xdd,0x77), - makecol(0x55,0xdd,0x99), - makecol(0x55,0xdd,0xbb), - makecol(0x55,0xdd,0xdd), - makecol(0x55,0xdd,0xff), - makecol(0xaa,0xdd,0x00), - makecol(0xaa,0xdd,0x33), - makecol(0xaa,0xdd,0x55), - makecol(0xaa,0xdd,0x77), - makecol(0xaa,0xdd,0x99), - makecol(0xaa,0xdd,0xbb), - makecol(0xaa,0xdd,0xdd), - makecol(0xaa,0xdd,0xff), - makecol(0xff,0xdd,0x00), - makecol(0xff,0xdd,0x33), - makecol(0xff,0xdd,0x55), - makecol(0xff,0xdd,0x77), - makecol(0xff,0xdd,0x99), - makecol(0xff,0xdd,0xbb), - makecol(0xff,0xdd,0xdd), - makecol(0xff,0xdd,0xff), - makecol(0x00,0xff,0x00), - makecol(0x00,0xff,0x33), - makecol(0x00,0xff,0x55), - makecol(0x00,0xff,0x77), - makecol(0x00,0xff,0x99), - makecol(0x00,0xff,0xbb), - makecol(0x00,0xff,0xdd), - makecol(0x00,0xff,0xff), - makecol(0x55,0xff,0x00), - makecol(0x55,0xff,0x33), - makecol(0x55,0xff,0x55), - makecol(0x55,0xff,0x77), - makecol(0x55,0xff,0x99), - makecol(0x55,0xff,0xbb), - makecol(0x55,0xff,0xdd), - makecol(0x55,0xff,0xff), - makecol(0xaa,0xff,0x00), - makecol(0xaa,0xff,0x33), - makecol(0xaa,0xff,0x55), - makecol(0xaa,0xff,0x77), - makecol(0xaa,0xff,0x99), - makecol(0xaa,0xff,0xbb), - makecol(0xaa,0xff,0xdd), - makecol(0xaa,0xff,0xff), - makecol(0xff,0xff,0x00), - makecol(0xff,0xff,0x33), - makecol(0xff,0xff,0x55), - makecol(0xff,0xff,0x77), - makecol(0xff,0xff,0x99), - makecol(0xff,0xff,0xbb), - makecol(0xff,0xff,0xdd), - makecol(0xff,0xff,0xff), - }, -/* Palette 4: 3-3-2 truecolour */ - { - makecol(0x00, 0x00, 0x00), - makecol(0x00, 0x00, 0x55), - makecol(0x00, 0x00, 0xaa), - makecol(0x00, 0x00, 0xff), - makecol(0x00, 0x33, 0x00), - makecol(0x00, 0x33, 0x55), - makecol(0x00, 0x33, 0xaa), - makecol(0x00, 0x33, 0xff), - makecol(0x00, 0x55, 0x00), - makecol(0x00, 0x55, 0x55), - makecol(0x00, 0x55, 0xaa), - makecol(0x00, 0x55, 0xff), - makecol(0x00, 0x77, 0x00), - makecol(0x00, 0x77, 0x55), - makecol(0x00, 0x77, 0xaa), - makecol(0x00, 0x77, 0xff), - makecol(0x00, 0x99, 0x00), - makecol(0x00, 0x99, 0x55), - makecol(0x00, 0x99, 0xaa), - makecol(0x00, 0x99, 0xff), - makecol(0x00, 0xbb, 0x00), - makecol(0x00, 0xbb, 0x55), - makecol(0x00, 0xbb, 0xaa), - makecol(0x00, 0xbb, 0xff), - makecol(0x00, 0xdd, 0x00), - makecol(0x00, 0xdd, 0x55), - makecol(0x00, 0xdd, 0xaa), - makecol(0x00, 0xdd, 0xff), - makecol(0x00, 0xff, 0x00), - makecol(0x00, 0xff, 0x55), - makecol(0x00, 0xff, 0xaa), - makecol(0x00, 0xff, 0xff), - makecol(0x33, 0x00, 0x00), - makecol(0x33, 0x00, 0x55), - makecol(0x33, 0x00, 0xaa), - makecol(0x33, 0x00, 0xff), - makecol(0x33, 0x33, 0x00), - makecol(0x33, 0x33, 0x55), - makecol(0x33, 0x33, 0xaa), - makecol(0x33, 0x33, 0xff), - makecol(0x33, 0x55, 0x00), - makecol(0x33, 0x55, 0x55), - makecol(0x33, 0x55, 0xaa), - makecol(0x33, 0x55, 0xff), - makecol(0x33, 0x77, 0x00), - makecol(0x33, 0x77, 0x55), - makecol(0x33, 0x77, 0xaa), - makecol(0x33, 0x77, 0xff), - makecol(0x33, 0x99, 0x00), - makecol(0x33, 0x99, 0x55), - makecol(0x33, 0x99, 0xaa), - makecol(0x33, 0x99, 0xff), - makecol(0x33, 0xbb, 0x00), - makecol(0x33, 0xbb, 0x55), - makecol(0x33, 0xbb, 0xaa), - makecol(0x33, 0xbb, 0xff), - makecol(0x33, 0xdd, 0x00), - makecol(0x33, 0xdd, 0x55), - makecol(0x33, 0xdd, 0xaa), - makecol(0x33, 0xdd, 0xff), - makecol(0x33, 0xff, 0x00), - makecol(0x33, 0xff, 0x55), - makecol(0x33, 0xff, 0xaa), - makecol(0x33, 0xff, 0xff), - makecol(0x55, 0x00, 0x00), - makecol(0x55, 0x00, 0x55), - makecol(0x55, 0x00, 0xaa), - makecol(0x55, 0x00, 0xff), - makecol(0x55, 0x33, 0x00), - makecol(0x55, 0x33, 0x55), - makecol(0x55, 0x33, 0xaa), - makecol(0x55, 0x33, 0xff), - makecol(0x55, 0x55, 0x00), - makecol(0x55, 0x55, 0x55), - makecol(0x55, 0x55, 0xaa), - makecol(0x55, 0x55, 0xff), - makecol(0x55, 0x77, 0x00), - makecol(0x55, 0x77, 0x55), - makecol(0x55, 0x77, 0xaa), - makecol(0x55, 0x77, 0xff), - makecol(0x55, 0x99, 0x00), - makecol(0x55, 0x99, 0x55), - makecol(0x55, 0x99, 0xaa), - makecol(0x55, 0x99, 0xff), - makecol(0x55, 0xbb, 0x00), - makecol(0x55, 0xbb, 0x55), - makecol(0x55, 0xbb, 0xaa), - makecol(0x55, 0xbb, 0xff), - makecol(0x55, 0xdd, 0x00), - makecol(0x55, 0xdd, 0x55), - makecol(0x55, 0xdd, 0xaa), - makecol(0x55, 0xdd, 0xff), - makecol(0x55, 0xff, 0x00), - makecol(0x55, 0xff, 0x55), - makecol(0x55, 0xff, 0xaa), - makecol(0x55, 0xff, 0xff), - makecol(0x77, 0x00, 0x00), - makecol(0x77, 0x00, 0x55), - makecol(0x77, 0x00, 0xaa), - makecol(0x77, 0x00, 0xff), - makecol(0x77, 0x33, 0x00), - makecol(0x77, 0x33, 0x55), - makecol(0x77, 0x33, 0xaa), - makecol(0x77, 0x33, 0xff), - makecol(0x77, 0x55, 0x00), - makecol(0x77, 0x55, 0x55), - makecol(0x77, 0x55, 0xaa), - makecol(0x77, 0x55, 0xff), - makecol(0x77, 0x77, 0x00), - makecol(0x77, 0x77, 0x55), - makecol(0x77, 0x77, 0xaa), - makecol(0x77, 0x77, 0xff), - makecol(0x77, 0x99, 0x00), - makecol(0x77, 0x99, 0x55), - makecol(0x77, 0x99, 0xaa), - makecol(0x77, 0x99, 0xff), - makecol(0x77, 0xbb, 0x00), - makecol(0x77, 0xbb, 0x55), - makecol(0x77, 0xbb, 0xaa), - makecol(0x77, 0xbb, 0xff), - makecol(0x77, 0xdd, 0x00), - makecol(0x77, 0xdd, 0x55), - makecol(0x77, 0xdd, 0xaa), - makecol(0x77, 0xdd, 0xff), - makecol(0x77, 0xff, 0x00), - makecol(0x77, 0xff, 0x55), - makecol(0x77, 0xff, 0xaa), - makecol(0x77, 0xff, 0xff), - makecol(0x99, 0x00, 0x00), - makecol(0x99, 0x00, 0x55), - makecol(0x99, 0x00, 0xaa), - makecol(0x99, 0x00, 0xff), - makecol(0x99, 0x33, 0x00), - makecol(0x99, 0x33, 0x55), - makecol(0x99, 0x33, 0xaa), - makecol(0x99, 0x33, 0xff), - makecol(0x99, 0x55, 0x00), - makecol(0x99, 0x55, 0x55), - makecol(0x99, 0x55, 0xaa), - makecol(0x99, 0x55, 0xff), - makecol(0x99, 0x77, 0x00), - makecol(0x99, 0x77, 0x55), - makecol(0x99, 0x77, 0xaa), - makecol(0x99, 0x77, 0xff), - makecol(0x99, 0x99, 0x00), - makecol(0x99, 0x99, 0x55), - makecol(0x99, 0x99, 0xaa), - makecol(0x99, 0x99, 0xff), - makecol(0x99, 0xbb, 0x00), - makecol(0x99, 0xbb, 0x55), - makecol(0x99, 0xbb, 0xaa), - makecol(0x99, 0xbb, 0xff), - makecol(0x99, 0xdd, 0x00), - makecol(0x99, 0xdd, 0x55), - makecol(0x99, 0xdd, 0xaa), - makecol(0x99, 0xdd, 0xff), - makecol(0x99, 0xff, 0x00), - makecol(0x99, 0xff, 0x55), - makecol(0x99, 0xff, 0xaa), - makecol(0x99, 0xff, 0xff), - makecol(0xbb, 0x00, 0x00), - makecol(0xbb, 0x00, 0x55), - makecol(0xbb, 0x00, 0xaa), - makecol(0xbb, 0x00, 0xff), - makecol(0xbb, 0x33, 0x00), - makecol(0xbb, 0x33, 0x55), - makecol(0xbb, 0x33, 0xaa), - makecol(0xbb, 0x33, 0xff), - makecol(0xbb, 0x55, 0x00), - makecol(0xbb, 0x55, 0x55), - makecol(0xbb, 0x55, 0xaa), - makecol(0xbb, 0x55, 0xff), - makecol(0xbb, 0x77, 0x00), - makecol(0xbb, 0x77, 0x55), - makecol(0xbb, 0x77, 0xaa), - makecol(0xbb, 0x77, 0xff), - makecol(0xbb, 0x99, 0x00), - makecol(0xbb, 0x99, 0x55), - makecol(0xbb, 0x99, 0xaa), - makecol(0xbb, 0x99, 0xff), - makecol(0xbb, 0xbb, 0x00), - makecol(0xbb, 0xbb, 0x55), - makecol(0xbb, 0xbb, 0xaa), - makecol(0xbb, 0xbb, 0xff), - makecol(0xbb, 0xdd, 0x00), - makecol(0xbb, 0xdd, 0x55), - makecol(0xbb, 0xdd, 0xaa), - makecol(0xbb, 0xdd, 0xff), - makecol(0xbb, 0xff, 0x00), - makecol(0xbb, 0xff, 0x55), - makecol(0xbb, 0xff, 0xaa), - makecol(0xbb, 0xff, 0xff), - makecol(0xdd, 0x00, 0x00), - makecol(0xdd, 0x00, 0x55), - makecol(0xdd, 0x00, 0xaa), - makecol(0xdd, 0x00, 0xff), - makecol(0xdd, 0x33, 0x00), - makecol(0xdd, 0x33, 0x55), - makecol(0xdd, 0x33, 0xaa), - makecol(0xdd, 0x33, 0xff), - makecol(0xdd, 0x55, 0x00), - makecol(0xdd, 0x55, 0x55), - makecol(0xdd, 0x55, 0xaa), - makecol(0xdd, 0x55, 0xff), - makecol(0xdd, 0x77, 0x00), - makecol(0xdd, 0x77, 0x55), - makecol(0xdd, 0x77, 0xaa), - makecol(0xdd, 0x77, 0xff), - makecol(0xdd, 0x99, 0x00), - makecol(0xdd, 0x99, 0x55), - makecol(0xdd, 0x99, 0xaa), - makecol(0xdd, 0x99, 0xff), - makecol(0xdd, 0xbb, 0x00), - makecol(0xdd, 0xbb, 0x55), - makecol(0xdd, 0xbb, 0xaa), - makecol(0xdd, 0xbb, 0xff), - makecol(0xdd, 0xdd, 0x00), - makecol(0xdd, 0xdd, 0x55), - makecol(0xdd, 0xdd, 0xaa), - makecol(0xdd, 0xdd, 0xff), - makecol(0xdd, 0xff, 0x00), - makecol(0xdd, 0xff, 0x55), - makecol(0xdd, 0xff, 0xaa), - makecol(0xdd, 0xff, 0xff), - makecol(0xff, 0x00, 0x00), - makecol(0xff, 0x00, 0x55), - makecol(0xff, 0x00, 0xaa), - makecol(0xff, 0x00, 0xff), - makecol(0xff, 0x33, 0x00), - makecol(0xff, 0x33, 0x55), - makecol(0xff, 0x33, 0xaa), - makecol(0xff, 0x33, 0xff), - makecol(0xff, 0x55, 0x00), - makecol(0xff, 0x55, 0x55), - makecol(0xff, 0x55, 0xaa), - makecol(0xff, 0x55, 0xff), - makecol(0xff, 0x77, 0x00), - makecol(0xff, 0x77, 0x55), - makecol(0xff, 0x77, 0xaa), - makecol(0xff, 0x77, 0xff), - makecol(0xff, 0x99, 0x00), - makecol(0xff, 0x99, 0x55), - makecol(0xff, 0x99, 0xaa), - makecol(0xff, 0x99, 0xff), - makecol(0xff, 0xbb, 0x00), - makecol(0xff, 0xbb, 0x55), - makecol(0xff, 0xbb, 0xaa), - makecol(0xff, 0xbb, 0xff), - makecol(0xff, 0xdd, 0x00), - makecol(0xff, 0xdd, 0x55), - makecol(0xff, 0xdd, 0xaa), - makecol(0xff, 0xdd, 0xff), - makecol(0xff, 0xff, 0x00), - makecol(0xff, 0xff, 0x55), - makecol(0xff, 0xff, 0xaa), - makecol(0xff, 0xff, 0xff), - }, -/* Palette 5: 6x6x6 colour cube */ - { - makecol(0x00,0x00,0x00), - makecol(0x00,0x00,0x33), - makecol(0x00,0x00,0x66), - makecol(0x00,0x00,0x99), - makecol(0x00,0x00,0xcc), - makecol(0x00,0x00,0xff), - makecol(0x33,0x00,0x00), - makecol(0x33,0x00,0x33), - makecol(0x33,0x00,0x66), - makecol(0x33,0x00,0x99), - makecol(0x33,0x00,0xcc), - makecol(0x33,0x00,0xff), - makecol(0x66,0x00,0x00), - makecol(0x66,0x00,0x33), - makecol(0x66,0x00,0x66), - makecol(0x66,0x00,0x99), - makecol(0x66,0x00,0xcc), - makecol(0x66,0x00,0xff), - makecol(0x99,0x00,0x00), - makecol(0x99,0x00,0x33), - makecol(0x99,0x00,0x66), - makecol(0x99,0x00,0x99), - makecol(0x99,0x00,0xcc), - makecol(0x99,0x00,0xff), - makecol(0xcc,0x00,0x00), - makecol(0xcc,0x00,0x33), - makecol(0xcc,0x00,0x66), - makecol(0xcc,0x00,0x99), - makecol(0xcc,0x00,0xcc), - makecol(0xcc,0x00,0xff), - makecol(0xff,0x00,0x00), - makecol(0xff,0x00,0x33), - makecol(0xff,0x00,0x66), - makecol(0xff,0x00,0x99), - makecol(0xff,0x00,0xcc), - makecol(0xff,0x00,0xff), - makecol(0x00,0x33,0x00), - makecol(0x00,0x33,0x33), - makecol(0x00,0x33,0x66), - makecol(0x00,0x33,0x99), - makecol(0x00,0x33,0xcc), - makecol(0x00,0x33,0xff), - makecol(0x33,0x33,0x00), - makecol(0x33,0x33,0x33), - makecol(0x33,0x33,0x66), - makecol(0x33,0x33,0x99), - makecol(0x33,0x33,0xcc), - makecol(0x33,0x33,0xff), - makecol(0x66,0x33,0x00), - makecol(0x66,0x33,0x33), - makecol(0x66,0x33,0x66), - makecol(0x66,0x33,0x99), - makecol(0x66,0x33,0xcc), - makecol(0x66,0x33,0xff), - makecol(0x99,0x33,0x00), - makecol(0x99,0x33,0x33), - makecol(0x99,0x33,0x66), - makecol(0x99,0x33,0x99), - makecol(0x99,0x33,0xcc), - makecol(0x99,0x33,0xff), - makecol(0xcc,0x33,0x00), - makecol(0xcc,0x33,0x33), - makecol(0xcc,0x33,0x66), - makecol(0xcc,0x33,0x99), - makecol(0xcc,0x33,0xcc), - makecol(0xcc,0x33,0xff), - makecol(0xff,0x33,0x00), - makecol(0xff,0x33,0x33), - makecol(0xff,0x33,0x66), - makecol(0xff,0x33,0x99), - makecol(0xff,0x33,0xcc), - makecol(0xff,0x33,0xff), - makecol(0x00,0x66,0x00), - makecol(0x00,0x66,0x33), - makecol(0x00,0x66,0x66), - makecol(0x00,0x66,0x99), - makecol(0x00,0x66,0xcc), - makecol(0x00,0x66,0xff), - makecol(0x33,0x66,0x00), - makecol(0x33,0x66,0x33), - makecol(0x33,0x66,0x66), - makecol(0x33,0x66,0x99), - makecol(0x33,0x66,0xcc), - makecol(0x33,0x66,0xff), - makecol(0x66,0x66,0x00), - makecol(0x66,0x66,0x33), - makecol(0x66,0x66,0x66), - makecol(0x66,0x66,0x99), - makecol(0x66,0x66,0xcc), - makecol(0x66,0x66,0xff), - makecol(0x99,0x66,0x00), - makecol(0x99,0x66,0x33), - makecol(0x99,0x66,0x66), - makecol(0x99,0x66,0x99), - makecol(0x99,0x66,0xcc), - makecol(0x99,0x66,0xff), - makecol(0xcc,0x66,0x00), - makecol(0xcc,0x66,0x33), - makecol(0xcc,0x66,0x66), - makecol(0xcc,0x66,0x99), - makecol(0xcc,0x66,0xcc), - makecol(0xcc,0x66,0xff), - makecol(0xff,0x66,0x00), - makecol(0xff,0x66,0x33), - makecol(0xff,0x66,0x66), - makecol(0xff,0x66,0x99), - makecol(0xff,0x66,0xcc), - makecol(0xff,0x66,0xff), - makecol(0x00,0x99,0x00), - makecol(0x00,0x99,0x33), - makecol(0x00,0x99,0x66), - makecol(0x00,0x99,0x99), - makecol(0x00,0x99,0xcc), - makecol(0x00,0x99,0xff), - makecol(0x33,0x99,0x00), - makecol(0x33,0x99,0x33), - makecol(0x33,0x99,0x66), - makecol(0x33,0x99,0x99), - makecol(0x33,0x99,0xcc), - makecol(0x33,0x99,0xff), - makecol(0x66,0x99,0x00), - makecol(0x66,0x99,0x33), - makecol(0x66,0x99,0x66), - makecol(0x66,0x99,0x99), - makecol(0x66,0x99,0xcc), - makecol(0x66,0x99,0xff), - makecol(0x99,0x99,0x00), - makecol(0x99,0x99,0x33), - makecol(0x99,0x99,0x66), - makecol(0x99,0x99,0x99), - makecol(0x99,0x99,0xcc), - makecol(0x99,0x99,0xff), - makecol(0xcc,0x99,0x00), - makecol(0xcc,0x99,0x33), - makecol(0xcc,0x99,0x66), - makecol(0xcc,0x99,0x99), - makecol(0xcc,0x99,0xcc), - makecol(0xcc,0x99,0xff), - makecol(0xff,0x99,0x00), - makecol(0xff,0x99,0x33), - makecol(0xff,0x99,0x66), - makecol(0xff,0x99,0x99), - makecol(0xff,0x99,0xcc), - makecol(0xff,0x99,0xff), - makecol(0x00,0xcc,0x00), - makecol(0x00,0xcc,0x33), - makecol(0x00,0xcc,0x66), - makecol(0x00,0xcc,0x99), - makecol(0x00,0xcc,0xcc), - makecol(0x00,0xcc,0xff), - makecol(0x33,0xcc,0x00), - makecol(0x33,0xcc,0x33), - makecol(0x33,0xcc,0x66), - makecol(0x33,0xcc,0x99), - makecol(0x33,0xcc,0xcc), - makecol(0x33,0xcc,0xff), - makecol(0x66,0xcc,0x00), - makecol(0x66,0xcc,0x33), - makecol(0x66,0xcc,0x66), - makecol(0x66,0xcc,0x99), - makecol(0x66,0xcc,0xcc), - makecol(0x66,0xcc,0xff), - makecol(0x99,0xcc,0x00), - makecol(0x99,0xcc,0x33), - makecol(0x99,0xcc,0x66), - makecol(0x99,0xcc,0x99), - makecol(0x99,0xcc,0xcc), - makecol(0x99,0xcc,0xff), - makecol(0xcc,0xcc,0x00), - makecol(0xcc,0xcc,0x33), - makecol(0xcc,0xcc,0x66), - makecol(0xcc,0xcc,0x99), - makecol(0xcc,0xcc,0xcc), - makecol(0xcc,0xcc,0xff), - makecol(0xff,0xcc,0x00), - makecol(0xff,0xcc,0x33), - makecol(0xff,0xcc,0x66), - makecol(0xff,0xcc,0x99), - makecol(0xff,0xcc,0xcc), - makecol(0xff,0xcc,0xff), - makecol(0x00,0xff,0x00), - makecol(0x00,0xff,0x33), - makecol(0x00,0xff,0x66), - makecol(0x00,0xff,0x99), - makecol(0x00,0xff,0xcc), - makecol(0x00,0xff,0xff), - makecol(0x33,0xff,0x00), - makecol(0x33,0xff,0x33), - makecol(0x33,0xff,0x66), - makecol(0x33,0xff,0x99), - makecol(0x33,0xff,0xcc), - makecol(0x33,0xff,0xff), - makecol(0x66,0xff,0x00), - makecol(0x66,0xff,0x33), - makecol(0x66,0xff,0x66), - makecol(0x66,0xff,0x99), - makecol(0x66,0xff,0xcc), - makecol(0x66,0xff,0xff), - makecol(0x99,0xff,0x00), - makecol(0x99,0xff,0x33), - makecol(0x99,0xff,0x66), - makecol(0x99,0xff,0x99), - makecol(0x99,0xff,0xcc), - makecol(0x99,0xff,0xff), - makecol(0xcc,0xff,0x00), - makecol(0xcc,0xff,0x33), - makecol(0xcc,0xff,0x66), - makecol(0xcc,0xff,0x99), - makecol(0xcc,0xff,0xcc), - makecol(0xcc,0xff,0xff), - makecol(0xff,0xff,0x00), - makecol(0xff,0xff,0x33), - makecol(0xff,0xff,0x66), - makecol(0xff,0xff,0x99), - makecol(0xff,0xff,0xcc), - makecol(0xff,0xff,0xff), - makecol(0x00,0x00,0x00), - makecol(0x00,0x00,0x00), - makecol(0x00,0x00,0x00), - makecol(0x00,0x00,0x00), - makecol(0x00,0x00,0x00), - makecol(0x00,0x00,0x00), - makecol(0x00,0x00,0x00), - makecol(0x00,0x00,0x00), - makecol(0x00,0x00,0x00), - makecol(0x00,0x00,0x00), - makecol(0x00,0x00,0x00), - makecol(0x00,0x00,0x00), - makecol(0x00,0x00,0x00), - makecol(0x00,0x00,0x00), - makecol(0x00,0x00,0x00), - makecol(0x00,0x00,0x00), - makecol(0x00,0x00,0x00), - makecol(0x00,0x00,0x00), - makecol(0x00,0x00,0x00), - makecol(0x00,0x00,0x00), - makecol(0x00,0x00,0x00), - makecol(0x00,0x00,0x00), - makecol(0x00,0x00,0x00), - makecol(0x00,0x00,0x00), - makecol(0x00,0x00,0x00), - makecol(0x00,0x00,0x00), - makecol(0x00,0x00,0x00), - makecol(0x00,0x00,0x00), - makecol(0x00,0x00,0x00), - makecol(0x00,0x00,0x00), - makecol(0x00,0x00,0x00), - makecol(0x00,0x00,0x00), - makecol(0x00,0x00,0x00), - makecol(0x00,0x00,0x00), - makecol(0x00,0x00,0x00), - makecol(0x00,0x00,0x00), - makecol(0x00,0x00,0x00), - makecol(0x00,0x00,0x00), - makecol(0x00,0x00,0x00), - makecol(0x00,0x00,0x00), - }, +{ + makecol(0x00, 0x00, 0x00), + makecol(0x11, 0x11, 0x11), + makecol(0x22, 0x22, 0x22), + makecol(0x33, 0x33, 0x33), + makecol(0x44, 0x44, 0x44), + makecol(0x55, 0x55, 0x55), + makecol(0x66, 0x66, 0x66), + makecol(0x77, 0x77, 0x77), + makecol(0x88, 0x88, 0x88), + makecol(0x99, 0x99, 0x99), + makecol(0xaa, 0xaa, 0xaa), + makecol(0xbb, 0xbb, 0xbb), + makecol(0xcc, 0xcc, 0xcc), + makecol(0xdd, 0xdd, 0xdd), + makecol(0xee, 0xee, 0xee), + makecol(0xff, 0xff, 0xff), + makecol(0x00, 0x00, 0x00), + makecol(0x00, 0x22, 0x00), + makecol(0x00, 0x44, 0x00), + makecol(0x00, 0x66, 0x00), + makecol(0x00, 0x88, 0x00), + makecol(0x00, 0xaa, 0x00), + makecol(0x00, 0xcc, 0x00), + makecol(0x00, 0xee, 0x00), + makecol(0x00, 0xff, 0x00), + makecol(0x22, 0xff, 0x22), + makecol(0x44, 0xff, 0x44), + makecol(0x66, 0xff, 0x66), + makecol(0x88, 0xff, 0x88), + makecol(0xaa, 0xff, 0xaa), + makecol(0xcc, 0xff, 0xcc), + makecol(0xee, 0xff, 0xee), + makecol(0x00, 0x00, 0x00), + makecol(0x00, 0x22, 0x11), + makecol(0x00, 0x44, 0x22), + makecol(0x00, 0x66, 0x33), + makecol(0x00, 0x88, 0x44), + makecol(0x00, 0xaa, 0x55), + makecol(0x00, 0xcc, 0x66), + makecol(0x00, 0xee, 0x77), + makecol(0x00, 0xff, 0x88), + makecol(0x22, 0xff, 0x99), + makecol(0x44, 0xff, 0xaa), + makecol(0x66, 0xff, 0xbb), + makecol(0x88, 0xff, 0xcc), + makecol(0xaa, 0xff, 0xdd), + makecol(0xcc, 0xff, 0xee), + makecol(0xee, 0xff, 0xff), + makecol(0x00, 0x00, 0x00), + makecol(0x00, 0x22, 0x22), + makecol(0x00, 0x44, 0x44), + makecol(0x00, 0x66, 0x66), + makecol(0x00, 0x88, 0x88), + makecol(0x00, 0xaa, 0xaa), + makecol(0x00, 0xcc, 0xcc), + makecol(0x00, 0xee, 0xee), + makecol(0x00, 0xff, 0xff), + makecol(0x22, 0xff, 0xff), + makecol(0x44, 0xff, 0xff), + makecol(0x66, 0xff, 0xff), + makecol(0x88, 0xff, 0xff), + makecol(0xaa, 0xff, 0xff), + makecol(0xcc, 0xff, 0xff), + makecol(0xee, 0xff, 0xff), + makecol(0x00, 0x00, 0x00), + makecol(0x00, 0x11, 0x22), + makecol(0x00, 0x22, 0x44), + makecol(0x00, 0x33, 0x66), + makecol(0x00, 0x44, 0x88), + makecol(0x00, 0x55, 0xaa), + makecol(0x00, 0x66, 0xcc), + makecol(0x00, 0x77, 0xee), + makecol(0x00, 0x88, 0xff), + makecol(0x22, 0x99, 0xff), + makecol(0x44, 0xaa, 0xff), + makecol(0x66, 0xbb, 0xff), + makecol(0x88, 0xcc, 0xff), + makecol(0xaa, 0xdd, 0xff), + makecol(0xcc, 0xee, 0xff), + makecol(0xee, 0xff, 0xff), + makecol(0x00, 0x00, 0x00), + makecol(0x00, 0x00, 0x22), + makecol(0x00, 0x00, 0x44), + makecol(0x00, 0x00, 0x66), + makecol(0x00, 0x00, 0x88), + makecol(0x00, 0x00, 0xaa), + makecol(0x00, 0x00, 0xcc), + makecol(0x00, 0x00, 0xee), + makecol(0x00, 0x00, 0xff), + makecol(0x22, 0x22, 0xff), + makecol(0x44, 0x44, 0xff), + makecol(0x66, 0x66, 0xff), + makecol(0x88, 0x88, 0xff), + makecol(0xaa, 0xaa, 0xff), + makecol(0xcc, 0xcc, 0xff), + makecol(0xee, 0xee, 0xff), + makecol(0x00, 0x00, 0x00), + makecol(0x11, 0x00, 0x22), + makecol(0x22, 0x00, 0x44), + makecol(0x33, 0x00, 0x66), + makecol(0x44, 0x00, 0x88), + makecol(0x55, 0x00, 0xaa), + makecol(0x66, 0x00, 0xcc), + makecol(0x77, 0x00, 0xee), + makecol(0x88, 0x00, 0xff), + makecol(0x99, 0x22, 0xff), + makecol(0xaa, 0x44, 0xff), + makecol(0xbb, 0x66, 0xff), + makecol(0xcc, 0x88, 0xff), + makecol(0xdd, 0xaa, 0xff), + makecol(0xee, 0xcc, 0xff), + makecol(0xff, 0xee, 0xff), + makecol(0x00, 0x00, 0x00), + makecol(0x22, 0x00, 0x22), + makecol(0x44, 0x00, 0x44), + makecol(0x66, 0x00, 0x66), + makecol(0x88, 0x00, 0x88), + makecol(0xaa, 0x00, 0xaa), + makecol(0xcc, 0x00, 0xcc), + makecol(0xee, 0x00, 0xee), + makecol(0xff, 0x00, 0xff), + makecol(0xff, 0x22, 0xff), + makecol(0xff, 0x44, 0xff), + makecol(0xff, 0x66, 0xff), + makecol(0xff, 0x88, 0xff), + makecol(0xff, 0xaa, 0xff), + makecol(0xff, 0xcc, 0xff), + makecol(0xff, 0xee, 0xff), + makecol(0x00, 0x00, 0x00), + makecol(0x22, 0x00, 0x11), + makecol(0x44, 0x00, 0x22), + makecol(0x66, 0x00, 0x33), + makecol(0x88, 0x00, 0x44), + makecol(0xaa, 0x00, 0x55), + makecol(0xcc, 0x00, 0x66), + makecol(0xee, 0x00, 0x77), + makecol(0xff, 0x00, 0x88), + makecol(0xff, 0x22, 0x99), + makecol(0xff, 0x44, 0xaa), + makecol(0xff, 0x66, 0xbb), + makecol(0xff, 0x88, 0xcc), + makecol(0xff, 0xaa, 0xdd), + makecol(0xff, 0xcc, 0xee), + makecol(0xff, 0xee, 0xff), + makecol(0x00, 0x00, 0x00), + makecol(0x22, 0x00, 0x00), + makecol(0x44, 0x00, 0x00), + makecol(0x66, 0x00, 0x00), + makecol(0x88, 0x00, 0x00), + makecol(0xaa, 0x00, 0x00), + makecol(0xcc, 0x00, 0x00), + makecol(0xee, 0x00, 0x00), + makecol(0xff, 0x00, 0x00), + makecol(0xff, 0x22, 0x22), + makecol(0xff, 0x44, 0x44), + makecol(0xff, 0x66, 0x66), + makecol(0xff, 0x88, 0x88), + makecol(0xff, 0xaa, 0xaa), + makecol(0xff, 0xcc, 0xcc), + makecol(0xff, 0xee, 0xee), + makecol(0x00, 0x00, 0x00), + makecol(0x22, 0x11, 0x00), + makecol(0x44, 0x22, 0x00), + makecol(0x66, 0x33, 0x00), + makecol(0x88, 0x44, 0x00), + makecol(0xaa, 0x55, 0x00), + makecol(0xcc, 0x66, 0x00), + makecol(0xee, 0x77, 0x00), + makecol(0xff, 0x88, 0x00), + makecol(0xff, 0x99, 0x22), + makecol(0xff, 0xaa, 0x44), + makecol(0xff, 0xbb, 0x66), + makecol(0xff, 0xcc, 0x88), + makecol(0xff, 0xdd, 0xaa), + makecol(0xff, 0xee, 0xcc), + makecol(0xff, 0xff, 0xee), + makecol(0x00, 0x00, 0x00), + makecol(0x22, 0x22, 0x00), + makecol(0x44, 0x44, 0x00), + makecol(0x66, 0x66, 0x00), + makecol(0x88, 0x88, 0x00), + makecol(0xaa, 0xaa, 0x00), + makecol(0xcc, 0xcc, 0x00), + makecol(0xee, 0xee, 0x00), + makecol(0xff, 0xff, 0x00), + makecol(0xff, 0xff, 0x22), + makecol(0xff, 0xff, 0x44), + makecol(0xff, 0xff, 0x66), + makecol(0xff, 0xff, 0x88), + makecol(0xff, 0xff, 0xaa), + makecol(0xff, 0xff, 0xcc), + makecol(0xff, 0xff, 0xee), + makecol(0x00, 0x00, 0x00), + makecol(0x11, 0x22, 0x00), + makecol(0x22, 0x44, 0x00), + makecol(0x33, 0x66, 0x00), + makecol(0x44, 0x88, 0x00), + makecol(0x55, 0xaa, 0x00), + makecol(0x66, 0xcc, 0x00), + makecol(0x77, 0xee, 0x00), + makecol(0x88, 0xff, 0x00), + makecol(0x99, 0xff, 0x22), + makecol(0xaa, 0xff, 0x44), + makecol(0xbb, 0xff, 0x66), + makecol(0xcc, 0xff, 0x88), + makecol(0xdd, 0xff, 0xaa), + makecol(0xee, 0xff, 0xcc), + makecol(0xff, 0xff, 0xee), + makecol(0x00, 0x00, 0x00), + makecol(0x00, 0x11, 0x00), + makecol(0x11, 0x33, 0x11), + makecol(0x11, 0x44, 0x11), + makecol(0x22, 0x66, 0x22), + makecol(0x22, 0x77, 0x22), + makecol(0x33, 0x99, 0x33), + makecol(0x33, 0xaa, 0x33), + makecol(0x44, 0xcc, 0x44), + makecol(0x55, 0xcc, 0x55), + makecol(0x77, 0xdd, 0x77), + makecol(0x88, 0xdd, 0x88), + makecol(0xaa, 0xee, 0xaa), + makecol(0xbb, 0xee, 0xbb), + makecol(0xdd, 0xff, 0xdd), + makecol(0xee, 0xff, 0xee), + makecol(0x00, 0x00, 0x00), + makecol(0x11, 0x00, 0x00), + makecol(0x33, 0x11, 0x11), + makecol(0x44, 0x11, 0x11), + makecol(0x66, 0x22, 0x22), + makecol(0x77, 0x22, 0x22), + makecol(0x99, 0x33, 0x33), + makecol(0xaa, 0x33, 0x33), + makecol(0xcc, 0x44, 0x44), + makecol(0xcc, 0x55, 0x55), + makecol(0xdd, 0x77, 0x77), + makecol(0xdd, 0x88, 0x88), + makecol(0xee, 0xaa, 0xaa), + makecol(0xee, 0xbb, 0xbb), + makecol(0xff, 0xdd, 0xdd), + makecol(0xff, 0xee, 0xee), + makecol(0x00, 0x00, 0x00), + makecol(0x00, 0x00, 0x11), + makecol(0x11, 0x11, 0x33), + makecol(0x11, 0x11, 0x44), + makecol(0x22, 0x22, 0x66), + makecol(0x22, 0x22, 0x77), + makecol(0x33, 0x33, 0x99), + makecol(0x33, 0x33, 0xaa), + makecol(0x44, 0x44, 0xcc), + makecol(0x55, 0x55, 0xcc), + makecol(0x77, 0x77, 0xdd), + makecol(0x88, 0x88, 0xdd), + makecol(0xaa, 0xaa, 0xee), + makecol(0xbb, 0xbb, 0xee), + makecol(0xdd, 0xdd, 0xff), + makecol(0xee, 0xee, 0xff), +}, + /* Palette 1: 16-colour palette */ + { + makecol(0x88, 0x66, 0xdd), + makecol(0x00, 0x00, 0x00), + makecol(0x44, 0x77, 0x22), + makecol(0x77, 0xaa, 0x44), + makecol(0x00, 0x77, 0x00), + makecol(0x00, 0xff, 0x00), + makecol(0x77, 0xff, 0x00), + makecol(0xff, 0xff, 0x00), + makecol(0xff, 0xaa, 0x00), + makecol(0xff, 0x00, 0x00), + makecol(0x77, 0x00, 0x00), + makecol(0x77, 0x00, 0x77), + makecol(0x00, 0x00, 0x77), + makecol(0x99, 0xee, 0x66), + makecol(0x77, 0x77, 0x77), + makecol(0xff, 0xff, 0xff), + makecol(0x00, 0x00, 0x00), + makecol(0x00, 0x00, 0x00), + makecol(0x00, 0x00, 0x00), + makecol(0x00, 0x00, 0x00), + makecol(0x00, 0x00, 0x00), + makecol(0x00, 0x00, 0x00), + makecol(0x00, 0x00, 0x00), + makecol(0x00, 0x00, 0x00), + makecol(0x00, 0x00, 0x00), + makecol(0x00, 0x00, 0x00), + makecol(0x00, 0x00, 0x00), + makecol(0x00, 0x00, 0x00), + makecol(0x00, 0x00, 0x00), + makecol(0x00, 0x00, 0x00), + makecol(0x00, 0x00, 0x00), + makecol(0x00, 0x00, 0x00), + makecol(0x44, 0x77, 0x22), + makecol(0x44, 0x77, 0x22), + makecol(0x44, 0x77, 0x22), + makecol(0x44, 0x77, 0x22), + makecol(0x44, 0x77, 0x22), + makecol(0x44, 0x77, 0x22), + makecol(0x44, 0x77, 0x22), + makecol(0x44, 0x77, 0x22), + makecol(0x44, 0x77, 0x22), + makecol(0x44, 0x77, 0x22), + makecol(0x44, 0x77, 0x22), + makecol(0x44, 0x77, 0x22), + makecol(0x44, 0x77, 0x22), + makecol(0x44, 0x77, 0x22), + makecol(0x44, 0x77, 0x22), + makecol(0x44, 0x77, 0x22), + makecol(0x77, 0xaa, 0x44), + makecol(0x77, 0xaa, 0x44), + makecol(0x77, 0xaa, 0x44), + makecol(0x77, 0xaa, 0x44), + makecol(0x77, 0xaa, 0x44), + makecol(0x77, 0xaa, 0x44), + makecol(0x77, 0xaa, 0x44), + makecol(0x77, 0xaa, 0x44), + makecol(0x77, 0xaa, 0x44), + makecol(0x77, 0xaa, 0x44), + makecol(0x77, 0xaa, 0x44), + makecol(0x77, 0xaa, 0x44), + makecol(0x77, 0xaa, 0x44), + makecol(0x77, 0xaa, 0x44), + makecol(0x77, 0xaa, 0x44), + makecol(0x77, 0xaa, 0x44), + makecol(0x00, 0x77, 0x00), + makecol(0x00, 0x77, 0x00), + makecol(0x00, 0x77, 0x00), + makecol(0x00, 0x77, 0x00), + makecol(0x00, 0x77, 0x00), + makecol(0x00, 0x77, 0x00), + makecol(0x00, 0x77, 0x00), + makecol(0x00, 0x77, 0x00), + makecol(0x00, 0x77, 0x00), + makecol(0x00, 0x77, 0x00), + makecol(0x00, 0x77, 0x00), + makecol(0x00, 0x77, 0x00), + makecol(0x00, 0x77, 0x00), + makecol(0x00, 0x77, 0x00), + makecol(0x00, 0x77, 0x00), + makecol(0x00, 0x77, 0x00), + makecol(0x00, 0xff, 0x00), + makecol(0x00, 0xff, 0x00), + makecol(0x00, 0xff, 0x00), + makecol(0x00, 0xff, 0x00), + makecol(0x00, 0xff, 0x00), + makecol(0x00, 0xff, 0x00), + makecol(0x00, 0xff, 0x00), + makecol(0x00, 0xff, 0x00), + makecol(0x00, 0xff, 0x00), + makecol(0x00, 0xff, 0x00), + makecol(0x00, 0xff, 0x00), + makecol(0x00, 0xff, 0x00), + makecol(0x00, 0xff, 0x00), + makecol(0x00, 0xff, 0x00), + makecol(0x00, 0xff, 0x00), + makecol(0x00, 0xff, 0x00), + makecol(0x77, 0xff, 0x00), + makecol(0x77, 0xff, 0x00), + makecol(0x77, 0xff, 0x00), + makecol(0x77, 0xff, 0x00), + makecol(0x77, 0xff, 0x00), + makecol(0x77, 0xff, 0x00), + makecol(0x77, 0xff, 0x00), + makecol(0x77, 0xff, 0x00), + makecol(0x77, 0xff, 0x00), + makecol(0x77, 0xff, 0x00), + makecol(0x77, 0xff, 0x00), + makecol(0x77, 0xff, 0x00), + makecol(0x77, 0xff, 0x00), + makecol(0x77, 0xff, 0x00), + makecol(0x77, 0xff, 0x00), + makecol(0x77, 0xff, 0x00), + makecol(0xff, 0xff, 0x00), + makecol(0xff, 0xff, 0x00), + makecol(0xff, 0xff, 0x00), + makecol(0xff, 0xff, 0x00), + makecol(0xff, 0xff, 0x00), + makecol(0xff, 0xff, 0x00), + makecol(0xff, 0xff, 0x00), + makecol(0xff, 0xff, 0x00), + makecol(0xff, 0xff, 0x00), + makecol(0xff, 0xff, 0x00), + makecol(0xff, 0xff, 0x00), + makecol(0xff, 0xff, 0x00), + makecol(0xff, 0xff, 0x00), + makecol(0xff, 0xff, 0x00), + makecol(0xff, 0xff, 0x00), + makecol(0xff, 0xff, 0x00), + makecol(0xff, 0xaa, 0x00), + makecol(0xff, 0xaa, 0x00), + makecol(0xff, 0xaa, 0x00), + makecol(0xff, 0xaa, 0x00), + makecol(0xff, 0xaa, 0x00), + makecol(0xff, 0xaa, 0x00), + makecol(0xff, 0xaa, 0x00), + makecol(0xff, 0xaa, 0x00), + makecol(0xff, 0xaa, 0x00), + makecol(0xff, 0xaa, 0x00), + makecol(0xff, 0xaa, 0x00), + makecol(0xff, 0xaa, 0x00), + makecol(0xff, 0xaa, 0x00), + makecol(0xff, 0xaa, 0x00), + makecol(0xff, 0xaa, 0x00), + makecol(0xff, 0xaa, 0x00), + makecol(0xff, 0x00, 0x00), + makecol(0xff, 0x00, 0x00), + makecol(0xff, 0x00, 0x00), + makecol(0xff, 0x00, 0x00), + makecol(0xff, 0x00, 0x00), + makecol(0xff, 0x00, 0x00), + makecol(0xff, 0x00, 0x00), + makecol(0xff, 0x00, 0x00), + makecol(0xff, 0x00, 0x00), + makecol(0xff, 0x00, 0x00), + makecol(0xff, 0x00, 0x00), + makecol(0xff, 0x00, 0x00), + makecol(0xff, 0x00, 0x00), + makecol(0xff, 0x00, 0x00), + makecol(0xff, 0x00, 0x00), + makecol(0xff, 0x00, 0x00), + makecol(0x77, 0x00, 0x00), + makecol(0x77, 0x00, 0x00), + makecol(0x77, 0x00, 0x00), + makecol(0x77, 0x00, 0x00), + makecol(0x77, 0x00, 0x00), + makecol(0x77, 0x00, 0x00), + makecol(0x77, 0x00, 0x00), + makecol(0x77, 0x00, 0x00), + makecol(0x77, 0x00, 0x00), + makecol(0x77, 0x00, 0x00), + makecol(0x77, 0x00, 0x00), + makecol(0x77, 0x00, 0x00), + makecol(0x77, 0x00, 0x00), + makecol(0x77, 0x00, 0x00), + makecol(0x77, 0x00, 0x00), + makecol(0x77, 0x00, 0x00), + makecol(0x77, 0x00, 0x77), + makecol(0x77, 0x00, 0x77), + makecol(0x77, 0x00, 0x77), + makecol(0x77, 0x00, 0x77), + makecol(0x77, 0x00, 0x77), + makecol(0x77, 0x00, 0x77), + makecol(0x77, 0x00, 0x77), + makecol(0x77, 0x00, 0x77), + makecol(0x77, 0x00, 0x77), + makecol(0x77, 0x00, 0x77), + makecol(0x77, 0x00, 0x77), + makecol(0x77, 0x00, 0x77), + makecol(0x77, 0x00, 0x77), + makecol(0x77, 0x00, 0x77), + makecol(0x77, 0x00, 0x77), + makecol(0x77, 0x00, 0x77), + makecol(0x00, 0x00, 0x77), + makecol(0x00, 0x00, 0x77), + makecol(0x00, 0x00, 0x77), + makecol(0x00, 0x00, 0x77), + makecol(0x00, 0x00, 0x77), + makecol(0x00, 0x00, 0x77), + makecol(0x00, 0x00, 0x77), + makecol(0x00, 0x00, 0x77), + makecol(0x00, 0x00, 0x77), + makecol(0x00, 0x00, 0x77), + makecol(0x00, 0x00, 0x77), + makecol(0x00, 0x00, 0x77), + makecol(0x00, 0x00, 0x77), + makecol(0x00, 0x00, 0x77), + makecol(0x00, 0x00, 0x77), + makecol(0x00, 0x00, 0x77), + makecol(0x99, 0xee, 0x66), + makecol(0x99, 0xee, 0x66), + makecol(0x99, 0xee, 0x66), + makecol(0x99, 0xee, 0x66), + makecol(0x99, 0xee, 0x66), + makecol(0x99, 0xee, 0x66), + makecol(0x99, 0xee, 0x66), + makecol(0x99, 0xee, 0x66), + makecol(0x99, 0xee, 0x66), + makecol(0x99, 0xee, 0x66), + makecol(0x99, 0xee, 0x66), + makecol(0x99, 0xee, 0x66), + makecol(0x99, 0xee, 0x66), + makecol(0x99, 0xee, 0x66), + makecol(0x99, 0xee, 0x66), + makecol(0x99, 0xee, 0x66), + makecol(0x77, 0x77, 0x77), + makecol(0x77, 0x77, 0x77), + makecol(0x77, 0x77, 0x77), + makecol(0x77, 0x77, 0x77), + makecol(0x77, 0x77, 0x77), + makecol(0x77, 0x77, 0x77), + makecol(0x77, 0x77, 0x77), + makecol(0x77, 0x77, 0x77), + makecol(0x77, 0x77, 0x77), + makecol(0x77, 0x77, 0x77), + makecol(0x77, 0x77, 0x77), + makecol(0x77, 0x77, 0x77), + makecol(0x77, 0x77, 0x77), + makecol(0x77, 0x77, 0x77), + makecol(0x77, 0x77, 0x77), + makecol(0x77, 0x77, 0x77), + makecol(0xff, 0xff, 0xff), + makecol(0xff, 0xff, 0xff), + makecol(0xff, 0xff, 0xff), + makecol(0xff, 0xff, 0xff), + makecol(0xff, 0xff, 0xff), + makecol(0xff, 0xff, 0xff), + makecol(0xff, 0xff, 0xff), + makecol(0xff, 0xff, 0xff), + makecol(0xff, 0xff, 0xff), + makecol(0xff, 0xff, 0xff), + makecol(0xff, 0xff, 0xff), + makecol(0xff, 0xff, 0xff), + makecol(0xff, 0xff, 0xff), + makecol(0xff, 0xff, 0xff), + makecol(0xff, 0xff, 0xff), + makecol(0xff, 0xff, 0xff), + }, + /* Palette 2: 2-3-3 truecolour */ + { + makecol(0x00, 0x00, 0x00), + makecol(0x00, 0x00, 0x33), + makecol(0x00, 0x00, 0x55), + makecol(0x00, 0x00, 0x77), + makecol(0x00, 0x00, 0x99), + makecol(0x00, 0x00, 0xbb), + makecol(0x00, 0x00, 0xdd), + makecol(0x00, 0x00, 0xff), + makecol(0x33, 0x00, 0x00), + makecol(0x33, 0x00, 0x33), + makecol(0x33, 0x00, 0x55), + makecol(0x33, 0x00, 0x77), + makecol(0x33, 0x00, 0x99), + makecol(0x33, 0x00, 0xbb), + makecol(0x33, 0x00, 0xdd), + makecol(0x33, 0x00, 0xff), + makecol(0x55, 0x00, 0x00), + makecol(0x55, 0x00, 0x33), + makecol(0x55, 0x00, 0x55), + makecol(0x55, 0x00, 0x77), + makecol(0x55, 0x00, 0x99), + makecol(0x55, 0x00, 0xbb), + makecol(0x55, 0x00, 0xdd), + makecol(0x55, 0x00, 0xff), + makecol(0x77, 0x00, 0x00), + makecol(0x77, 0x00, 0x33), + makecol(0x77, 0x00, 0x55), + makecol(0x77, 0x00, 0x77), + makecol(0x77, 0x00, 0x99), + makecol(0x77, 0x00, 0xbb), + makecol(0x77, 0x00, 0xdd), + makecol(0x77, 0x00, 0xff), + makecol(0x99, 0x00, 0x00), + makecol(0x99, 0x00, 0x33), + makecol(0x99, 0x00, 0x55), + makecol(0x99, 0x00, 0x77), + makecol(0x99, 0x00, 0x99), + makecol(0x99, 0x00, 0xbb), + makecol(0x99, 0x00, 0xdd), + makecol(0x99, 0x00, 0xff), + makecol(0xbb, 0x00, 0x00), + makecol(0xbb, 0x00, 0x33), + makecol(0xbb, 0x00, 0x55), + makecol(0xbb, 0x00, 0x77), + makecol(0xbb, 0x00, 0x99), + makecol(0xbb, 0x00, 0xbb), + makecol(0xbb, 0x00, 0xdd), + makecol(0xbb, 0x00, 0xff), + makecol(0xdd, 0x00, 0x00), + makecol(0xdd, 0x00, 0x33), + makecol(0xdd, 0x00, 0x55), + makecol(0xdd, 0x00, 0x77), + makecol(0xdd, 0x00, 0x99), + makecol(0xdd, 0x00, 0xbb), + makecol(0xdd, 0x00, 0xdd), + makecol(0xdd, 0x00, 0xff), + makecol(0xff, 0x00, 0x00), + makecol(0xff, 0x00, 0x33), + makecol(0xff, 0x00, 0x55), + makecol(0xff, 0x00, 0x77), + makecol(0xff, 0x00, 0x99), + makecol(0xff, 0x00, 0xbb), + makecol(0xff, 0x00, 0xdd), + makecol(0xff, 0x00, 0xff), + makecol(0x00, 0x55, 0x00), + makecol(0x00, 0x55, 0x33), + makecol(0x00, 0x55, 0x55), + makecol(0x00, 0x55, 0x77), + makecol(0x00, 0x55, 0x99), + makecol(0x00, 0x55, 0xbb), + makecol(0x00, 0x55, 0xdd), + makecol(0x00, 0x55, 0xff), + makecol(0x33, 0x55, 0x00), + makecol(0x33, 0x55, 0x33), + makecol(0x33, 0x55, 0x55), + makecol(0x33, 0x55, 0x77), + makecol(0x33, 0x55, 0x99), + makecol(0x33, 0x55, 0xbb), + makecol(0x33, 0x55, 0xdd), + makecol(0x33, 0x55, 0xff), + makecol(0x55, 0x55, 0x00), + makecol(0x55, 0x55, 0x33), + makecol(0x55, 0x55, 0x55), + makecol(0x55, 0x55, 0x77), + makecol(0x55, 0x55, 0x99), + makecol(0x55, 0x55, 0xbb), + makecol(0x55, 0x55, 0xdd), + makecol(0x55, 0x55, 0xff), + makecol(0x77, 0x55, 0x00), + makecol(0x77, 0x55, 0x33), + makecol(0x77, 0x55, 0x55), + makecol(0x77, 0x55, 0x77), + makecol(0x77, 0x55, 0x99), + makecol(0x77, 0x55, 0xbb), + makecol(0x77, 0x55, 0xdd), + makecol(0x77, 0x55, 0xff), + makecol(0x99, 0x55, 0x00), + makecol(0x99, 0x55, 0x33), + makecol(0x99, 0x55, 0x55), + makecol(0x99, 0x55, 0x77), + makecol(0x99, 0x55, 0x99), + makecol(0x99, 0x55, 0xbb), + makecol(0x99, 0x55, 0xdd), + makecol(0x99, 0x55, 0xff), + makecol(0xbb, 0x55, 0x00), + makecol(0xbb, 0x55, 0x33), + makecol(0xbb, 0x55, 0x55), + makecol(0xbb, 0x55, 0x77), + makecol(0xbb, 0x55, 0x99), + makecol(0xbb, 0x55, 0xbb), + makecol(0xbb, 0x55, 0xdd), + makecol(0xbb, 0x55, 0xff), + makecol(0xdd, 0x55, 0x00), + makecol(0xdd, 0x55, 0x33), + makecol(0xdd, 0x55, 0x55), + makecol(0xdd, 0x55, 0x77), + makecol(0xdd, 0x55, 0x99), + makecol(0xdd, 0x55, 0xbb), + makecol(0xdd, 0x55, 0xdd), + makecol(0xdd, 0x55, 0xff), + makecol(0xff, 0x55, 0x00), + makecol(0xff, 0x55, 0x33), + makecol(0xff, 0x55, 0x55), + makecol(0xff, 0x55, 0x77), + makecol(0xff, 0x55, 0x99), + makecol(0xff, 0x55, 0xbb), + makecol(0xff, 0x55, 0xdd), + makecol(0xff, 0x55, 0xff), + makecol(0x00, 0xaa, 0x00), + makecol(0x00, 0xaa, 0x33), + makecol(0x00, 0xaa, 0x55), + makecol(0x00, 0xaa, 0x77), + makecol(0x00, 0xaa, 0x99), + makecol(0x00, 0xaa, 0xbb), + makecol(0x00, 0xaa, 0xdd), + makecol(0x00, 0xaa, 0xff), + makecol(0x33, 0xaa, 0x00), + makecol(0x33, 0xaa, 0x33), + makecol(0x33, 0xaa, 0x55), + makecol(0x33, 0xaa, 0x77), + makecol(0x33, 0xaa, 0x99), + makecol(0x33, 0xaa, 0xbb), + makecol(0x33, 0xaa, 0xdd), + makecol(0x33, 0xaa, 0xff), + makecol(0x55, 0xaa, 0x00), + makecol(0x55, 0xaa, 0x33), + makecol(0x55, 0xaa, 0x55), + makecol(0x55, 0xaa, 0x77), + makecol(0x55, 0xaa, 0x99), + makecol(0x55, 0xaa, 0xbb), + makecol(0x55, 0xaa, 0xdd), + makecol(0x55, 0xaa, 0xff), + makecol(0x77, 0xaa, 0x00), + makecol(0x77, 0xaa, 0x33), + makecol(0x77, 0xaa, 0x55), + makecol(0x77, 0xaa, 0x77), + makecol(0x77, 0xaa, 0x99), + makecol(0x77, 0xaa, 0xbb), + makecol(0x77, 0xaa, 0xdd), + makecol(0x77, 0xaa, 0xff), + makecol(0x99, 0xaa, 0x00), + makecol(0x99, 0xaa, 0x33), + makecol(0x99, 0xaa, 0x55), + makecol(0x99, 0xaa, 0x77), + makecol(0x99, 0xaa, 0x99), + makecol(0x99, 0xaa, 0xbb), + makecol(0x99, 0xaa, 0xdd), + makecol(0x99, 0xaa, 0xff), + makecol(0xbb, 0xaa, 0x00), + makecol(0xbb, 0xaa, 0x33), + makecol(0xbb, 0xaa, 0x55), + makecol(0xbb, 0xaa, 0x77), + makecol(0xbb, 0xaa, 0x99), + makecol(0xbb, 0xaa, 0xbb), + makecol(0xbb, 0xaa, 0xdd), + makecol(0xbb, 0xaa, 0xff), + makecol(0xdd, 0xaa, 0x00), + makecol(0xdd, 0xaa, 0x33), + makecol(0xdd, 0xaa, 0x55), + makecol(0xdd, 0xaa, 0x77), + makecol(0xdd, 0xaa, 0x99), + makecol(0xdd, 0xaa, 0xbb), + makecol(0xdd, 0xaa, 0xdd), + makecol(0xdd, 0xaa, 0xff), + makecol(0xff, 0xaa, 0x00), + makecol(0xff, 0xaa, 0x33), + makecol(0xff, 0xaa, 0x55), + makecol(0xff, 0xaa, 0x77), + makecol(0xff, 0xaa, 0x99), + makecol(0xff, 0xaa, 0xbb), + makecol(0xff, 0xaa, 0xdd), + makecol(0xff, 0xaa, 0xee), + makecol(0x00, 0xff, 0x00), + makecol(0x00, 0xff, 0x33), + makecol(0x00, 0xff, 0x55), + makecol(0x00, 0xff, 0x77), + makecol(0x00, 0xff, 0x99), + makecol(0x00, 0xff, 0xbb), + makecol(0x00, 0xff, 0xdd), + makecol(0x00, 0xff, 0xff), + makecol(0x33, 0xff, 0x00), + makecol(0x33, 0xff, 0x33), + makecol(0x33, 0xff, 0x55), + makecol(0x33, 0xff, 0x77), + makecol(0x33, 0xff, 0x99), + makecol(0x33, 0xff, 0xbb), + makecol(0x33, 0xff, 0xdd), + makecol(0x33, 0xff, 0xff), + makecol(0x55, 0xff, 0x00), + makecol(0x55, 0xff, 0x33), + makecol(0x55, 0xff, 0x55), + makecol(0x55, 0xff, 0x77), + makecol(0x55, 0xff, 0x99), + makecol(0x55, 0xff, 0xbb), + makecol(0x55, 0xff, 0xdd), + makecol(0x55, 0xff, 0xff), + makecol(0x77, 0xff, 0x00), + makecol(0x77, 0xff, 0x33), + makecol(0x77, 0xff, 0x55), + makecol(0x77, 0xff, 0x77), + makecol(0x77, 0xff, 0x99), + makecol(0x77, 0xff, 0xbb), + makecol(0x77, 0xff, 0xdd), + makecol(0x77, 0xff, 0xff), + makecol(0x99, 0xff, 0x00), + makecol(0x99, 0xff, 0x33), + makecol(0x99, 0xff, 0x55), + makecol(0x99, 0xff, 0x77), + makecol(0x99, 0xff, 0x99), + makecol(0x99, 0xff, 0xbb), + makecol(0x99, 0xff, 0xdd), + makecol(0x99, 0xff, 0xff), + makecol(0xbb, 0xff, 0x00), + makecol(0xbb, 0xff, 0x33), + makecol(0xbb, 0xff, 0x55), + makecol(0xbb, 0xff, 0x77), + makecol(0xbb, 0xff, 0x99), + makecol(0xbb, 0xff, 0xbb), + makecol(0xbb, 0xff, 0xdd), + makecol(0xbb, 0xff, 0xff), + makecol(0xdd, 0xff, 0x00), + makecol(0xdd, 0xff, 0x33), + makecol(0xdd, 0xff, 0x55), + makecol(0xdd, 0xff, 0x77), + makecol(0xdd, 0xff, 0x99), + makecol(0xdd, 0xff, 0xbb), + makecol(0xdd, 0xff, 0xdd), + makecol(0xdd, 0xff, 0xff), + makecol(0xff, 0xff, 0x00), + makecol(0xff, 0xff, 0x33), + makecol(0xff, 0xff, 0x55), + makecol(0xff, 0xff, 0x77), + makecol(0xff, 0xff, 0x99), + makecol(0xff, 0xff, 0xbb), + makecol(0xff, 0xff, 0xdd), + makecol(0xff, 0xff, 0xff), + }, + /* Palette 3: 3-2-3 truecolour */ + { + makecol(0x00, 0x00, 0x00), + makecol(0x00, 0x00, 0x33), + makecol(0x00, 0x00, 0x55), + makecol(0x00, 0x00, 0x77), + makecol(0x00, 0x00, 0x99), + makecol(0x00, 0x00, 0xbb), + makecol(0x00, 0x00, 0xdd), + makecol(0x00, 0x00, 0xff), + makecol(0x55, 0x00, 0x00), + makecol(0x55, 0x00, 0x33), + makecol(0x55, 0x00, 0x55), + makecol(0x55, 0x00, 0x77), + makecol(0x55, 0x00, 0x99), + makecol(0x55, 0x00, 0xbb), + makecol(0x55, 0x00, 0xdd), + makecol(0x55, 0x00, 0xff), + makecol(0xaa, 0x00, 0x00), + makecol(0xaa, 0x00, 0x33), + makecol(0xaa, 0x00, 0x55), + makecol(0xaa, 0x00, 0x77), + makecol(0xaa, 0x00, 0x99), + makecol(0xaa, 0x00, 0xbb), + makecol(0xaa, 0x00, 0xdd), + makecol(0xaa, 0x00, 0xff), + makecol(0xff, 0x00, 0x00), + makecol(0xff, 0x00, 0x33), + makecol(0xff, 0x00, 0x55), + makecol(0xff, 0x00, 0x77), + makecol(0xff, 0x00, 0x99), + makecol(0xff, 0x00, 0xbb), + makecol(0xff, 0x00, 0xdd), + makecol(0xff, 0x00, 0xff), + makecol(0x00, 0x33, 0x00), + makecol(0x00, 0x33, 0x33), + makecol(0x00, 0x33, 0x55), + makecol(0x00, 0x33, 0x77), + makecol(0x00, 0x33, 0x99), + makecol(0x00, 0x33, 0xbb), + makecol(0x00, 0x33, 0xdd), + makecol(0x00, 0x33, 0xff), + makecol(0x55, 0x33, 0x00), + makecol(0x55, 0x33, 0x33), + makecol(0x55, 0x33, 0x55), + makecol(0x55, 0x33, 0x77), + makecol(0x55, 0x33, 0x99), + makecol(0x55, 0x33, 0xbb), + makecol(0x55, 0x33, 0xdd), + makecol(0x55, 0x33, 0xff), + makecol(0xaa, 0x33, 0x00), + makecol(0xaa, 0x33, 0x33), + makecol(0xaa, 0x33, 0x55), + makecol(0xaa, 0x33, 0x77), + makecol(0xaa, 0x33, 0x99), + makecol(0xaa, 0x33, 0xbb), + makecol(0xaa, 0x33, 0xdd), + makecol(0xaa, 0x33, 0xff), + makecol(0xff, 0x33, 0x00), + makecol(0xff, 0x33, 0x33), + makecol(0xff, 0x33, 0x55), + makecol(0xff, 0x33, 0x77), + makecol(0xff, 0x33, 0x99), + makecol(0xff, 0x33, 0xbb), + makecol(0xff, 0x33, 0xdd), + makecol(0xff, 0x33, 0xff), + makecol(0x00, 0x55, 0x00), + makecol(0x00, 0x55, 0x33), + makecol(0x00, 0x55, 0x55), + makecol(0x00, 0x55, 0x77), + makecol(0x00, 0x55, 0x99), + makecol(0x00, 0x55, 0xbb), + makecol(0x00, 0x55, 0xdd), + makecol(0x00, 0x55, 0xff), + makecol(0x55, 0x55, 0x00), + makecol(0x55, 0x55, 0x33), + makecol(0x55, 0x55, 0x55), + makecol(0x55, 0x55, 0x77), + makecol(0x55, 0x55, 0x99), + makecol(0x55, 0x55, 0xbb), + makecol(0x55, 0x55, 0xdd), + makecol(0x55, 0x55, 0xff), + makecol(0xaa, 0x55, 0x00), + makecol(0xaa, 0x55, 0x33), + makecol(0xaa, 0x55, 0x55), + makecol(0xaa, 0x55, 0x77), + makecol(0xaa, 0x55, 0x99), + makecol(0xaa, 0x55, 0xbb), + makecol(0xaa, 0x55, 0xdd), + makecol(0xaa, 0x55, 0xff), + makecol(0xff, 0x55, 0x00), + makecol(0xff, 0x55, 0x33), + makecol(0xff, 0x55, 0x55), + makecol(0xff, 0x55, 0x77), + makecol(0xff, 0x55, 0x99), + makecol(0xff, 0x55, 0xbb), + makecol(0xff, 0x55, 0xdd), + makecol(0xff, 0x55, 0xff), + makecol(0x00, 0x77, 0x00), + makecol(0x00, 0x77, 0x33), + makecol(0x00, 0x77, 0x55), + makecol(0x00, 0x77, 0x77), + makecol(0x00, 0x77, 0x99), + makecol(0x00, 0x77, 0xbb), + makecol(0x00, 0x77, 0xdd), + makecol(0x00, 0x77, 0xff), + makecol(0x55, 0x77, 0x00), + makecol(0x55, 0x77, 0x33), + makecol(0x55, 0x77, 0x55), + makecol(0x55, 0x77, 0x77), + makecol(0x55, 0x77, 0x99), + makecol(0x55, 0x77, 0xbb), + makecol(0x55, 0x77, 0xdd), + makecol(0x55, 0x77, 0xff), + makecol(0xaa, 0x77, 0x00), + makecol(0xaa, 0x77, 0x33), + makecol(0xaa, 0x77, 0x55), + makecol(0xaa, 0x77, 0x77), + makecol(0xaa, 0x77, 0x99), + makecol(0xaa, 0x77, 0xbb), + makecol(0xaa, 0x77, 0xdd), + makecol(0xaa, 0x77, 0xff), + makecol(0xff, 0x77, 0x00), + makecol(0xff, 0x77, 0x33), + makecol(0xff, 0x77, 0x55), + makecol(0xff, 0x77, 0x77), + makecol(0xff, 0x77, 0x99), + makecol(0xff, 0x77, 0xbb), + makecol(0xff, 0x77, 0xdd), + makecol(0xff, 0x77, 0xff), + makecol(0x00, 0x99, 0x00), + makecol(0x00, 0x99, 0x33), + makecol(0x00, 0x99, 0x55), + makecol(0x00, 0x99, 0x77), + makecol(0x00, 0x99, 0x99), + makecol(0x00, 0x99, 0xbb), + makecol(0x00, 0x99, 0xdd), + makecol(0x00, 0x99, 0xff), + makecol(0x55, 0x99, 0x00), + makecol(0x55, 0x99, 0x33), + makecol(0x55, 0x99, 0x55), + makecol(0x55, 0x99, 0x77), + makecol(0x55, 0x99, 0x99), + makecol(0x55, 0x99, 0xbb), + makecol(0x55, 0x99, 0xdd), + makecol(0x55, 0x99, 0xff), + makecol(0xaa, 0x99, 0x00), + makecol(0xaa, 0x99, 0x33), + makecol(0xaa, 0x99, 0x55), + makecol(0xaa, 0x99, 0x77), + makecol(0xaa, 0x99, 0x99), + makecol(0xaa, 0x99, 0xbb), + makecol(0xaa, 0x99, 0xdd), + makecol(0xaa, 0x99, 0xff), + makecol(0xff, 0x99, 0x00), + makecol(0xff, 0x99, 0x33), + makecol(0xff, 0x99, 0x55), + makecol(0xff, 0x99, 0x77), + makecol(0xff, 0x99, 0x99), + makecol(0xff, 0x99, 0xbb), + makecol(0xff, 0x99, 0xdd), + makecol(0xff, 0x99, 0xff), + makecol(0x00, 0xbb, 0x00), + makecol(0x00, 0xbb, 0x33), + makecol(0x00, 0xbb, 0x55), + makecol(0x00, 0xbb, 0x77), + makecol(0x00, 0xbb, 0x99), + makecol(0x00, 0xbb, 0xbb), + makecol(0x00, 0xbb, 0xdd), + makecol(0x00, 0xbb, 0xff), + makecol(0x55, 0xbb, 0x00), + makecol(0x55, 0xbb, 0x33), + makecol(0x55, 0xbb, 0x55), + makecol(0x55, 0xbb, 0x77), + makecol(0x55, 0xbb, 0x99), + makecol(0x55, 0xbb, 0xbb), + makecol(0x55, 0xbb, 0xdd), + makecol(0x55, 0xbb, 0xff), + makecol(0xaa, 0xbb, 0x00), + makecol(0xaa, 0xbb, 0x33), + makecol(0xaa, 0xbb, 0x55), + makecol(0xaa, 0xbb, 0x77), + makecol(0xaa, 0xbb, 0x99), + makecol(0xaa, 0xbb, 0xbb), + makecol(0xaa, 0xbb, 0xdd), + makecol(0xaa, 0xbb, 0xff), + makecol(0xff, 0xbb, 0x00), + makecol(0xff, 0xbb, 0x33), + makecol(0xff, 0xbb, 0x55), + makecol(0xff, 0xbb, 0x77), + makecol(0xff, 0xbb, 0x99), + makecol(0xff, 0xbb, 0xbb), + makecol(0xff, 0xbb, 0xdd), + makecol(0xff, 0xbb, 0xff), + makecol(0x00, 0xdd, 0x00), + makecol(0x00, 0xdd, 0x33), + makecol(0x00, 0xdd, 0x55), + makecol(0x00, 0xdd, 0x77), + makecol(0x00, 0xdd, 0x99), + makecol(0x00, 0xdd, 0xbb), + makecol(0x00, 0xdd, 0xdd), + makecol(0x00, 0xdd, 0xff), + makecol(0x55, 0xdd, 0x00), + makecol(0x55, 0xdd, 0x33), + makecol(0x55, 0xdd, 0x55), + makecol(0x55, 0xdd, 0x77), + makecol(0x55, 0xdd, 0x99), + makecol(0x55, 0xdd, 0xbb), + makecol(0x55, 0xdd, 0xdd), + makecol(0x55, 0xdd, 0xff), + makecol(0xaa, 0xdd, 0x00), + makecol(0xaa, 0xdd, 0x33), + makecol(0xaa, 0xdd, 0x55), + makecol(0xaa, 0xdd, 0x77), + makecol(0xaa, 0xdd, 0x99), + makecol(0xaa, 0xdd, 0xbb), + makecol(0xaa, 0xdd, 0xdd), + makecol(0xaa, 0xdd, 0xff), + makecol(0xff, 0xdd, 0x00), + makecol(0xff, 0xdd, 0x33), + makecol(0xff, 0xdd, 0x55), + makecol(0xff, 0xdd, 0x77), + makecol(0xff, 0xdd, 0x99), + makecol(0xff, 0xdd, 0xbb), + makecol(0xff, 0xdd, 0xdd), + makecol(0xff, 0xdd, 0xff), + makecol(0x00, 0xff, 0x00), + makecol(0x00, 0xff, 0x33), + makecol(0x00, 0xff, 0x55), + makecol(0x00, 0xff, 0x77), + makecol(0x00, 0xff, 0x99), + makecol(0x00, 0xff, 0xbb), + makecol(0x00, 0xff, 0xdd), + makecol(0x00, 0xff, 0xff), + makecol(0x55, 0xff, 0x00), + makecol(0x55, 0xff, 0x33), + makecol(0x55, 0xff, 0x55), + makecol(0x55, 0xff, 0x77), + makecol(0x55, 0xff, 0x99), + makecol(0x55, 0xff, 0xbb), + makecol(0x55, 0xff, 0xdd), + makecol(0x55, 0xff, 0xff), + makecol(0xaa, 0xff, 0x00), + makecol(0xaa, 0xff, 0x33), + makecol(0xaa, 0xff, 0x55), + makecol(0xaa, 0xff, 0x77), + makecol(0xaa, 0xff, 0x99), + makecol(0xaa, 0xff, 0xbb), + makecol(0xaa, 0xff, 0xdd), + makecol(0xaa, 0xff, 0xff), + makecol(0xff, 0xff, 0x00), + makecol(0xff, 0xff, 0x33), + makecol(0xff, 0xff, 0x55), + makecol(0xff, 0xff, 0x77), + makecol(0xff, 0xff, 0x99), + makecol(0xff, 0xff, 0xbb), + makecol(0xff, 0xff, 0xdd), + makecol(0xff, 0xff, 0xff), + }, + /* Palette 4: 3-3-2 truecolour */ + { + makecol(0x00, 0x00, 0x00), + makecol(0x00, 0x00, 0x55), + makecol(0x00, 0x00, 0xaa), + makecol(0x00, 0x00, 0xff), + makecol(0x00, 0x33, 0x00), + makecol(0x00, 0x33, 0x55), + makecol(0x00, 0x33, 0xaa), + makecol(0x00, 0x33, 0xff), + makecol(0x00, 0x55, 0x00), + makecol(0x00, 0x55, 0x55), + makecol(0x00, 0x55, 0xaa), + makecol(0x00, 0x55, 0xff), + makecol(0x00, 0x77, 0x00), + makecol(0x00, 0x77, 0x55), + makecol(0x00, 0x77, 0xaa), + makecol(0x00, 0x77, 0xff), + makecol(0x00, 0x99, 0x00), + makecol(0x00, 0x99, 0x55), + makecol(0x00, 0x99, 0xaa), + makecol(0x00, 0x99, 0xff), + makecol(0x00, 0xbb, 0x00), + makecol(0x00, 0xbb, 0x55), + makecol(0x00, 0xbb, 0xaa), + makecol(0x00, 0xbb, 0xff), + makecol(0x00, 0xdd, 0x00), + makecol(0x00, 0xdd, 0x55), + makecol(0x00, 0xdd, 0xaa), + makecol(0x00, 0xdd, 0xff), + makecol(0x00, 0xff, 0x00), + makecol(0x00, 0xff, 0x55), + makecol(0x00, 0xff, 0xaa), + makecol(0x00, 0xff, 0xff), + makecol(0x33, 0x00, 0x00), + makecol(0x33, 0x00, 0x55), + makecol(0x33, 0x00, 0xaa), + makecol(0x33, 0x00, 0xff), + makecol(0x33, 0x33, 0x00), + makecol(0x33, 0x33, 0x55), + makecol(0x33, 0x33, 0xaa), + makecol(0x33, 0x33, 0xff), + makecol(0x33, 0x55, 0x00), + makecol(0x33, 0x55, 0x55), + makecol(0x33, 0x55, 0xaa), + makecol(0x33, 0x55, 0xff), + makecol(0x33, 0x77, 0x00), + makecol(0x33, 0x77, 0x55), + makecol(0x33, 0x77, 0xaa), + makecol(0x33, 0x77, 0xff), + makecol(0x33, 0x99, 0x00), + makecol(0x33, 0x99, 0x55), + makecol(0x33, 0x99, 0xaa), + makecol(0x33, 0x99, 0xff), + makecol(0x33, 0xbb, 0x00), + makecol(0x33, 0xbb, 0x55), + makecol(0x33, 0xbb, 0xaa), + makecol(0x33, 0xbb, 0xff), + makecol(0x33, 0xdd, 0x00), + makecol(0x33, 0xdd, 0x55), + makecol(0x33, 0xdd, 0xaa), + makecol(0x33, 0xdd, 0xff), + makecol(0x33, 0xff, 0x00), + makecol(0x33, 0xff, 0x55), + makecol(0x33, 0xff, 0xaa), + makecol(0x33, 0xff, 0xff), + makecol(0x55, 0x00, 0x00), + makecol(0x55, 0x00, 0x55), + makecol(0x55, 0x00, 0xaa), + makecol(0x55, 0x00, 0xff), + makecol(0x55, 0x33, 0x00), + makecol(0x55, 0x33, 0x55), + makecol(0x55, 0x33, 0xaa), + makecol(0x55, 0x33, 0xff), + makecol(0x55, 0x55, 0x00), + makecol(0x55, 0x55, 0x55), + makecol(0x55, 0x55, 0xaa), + makecol(0x55, 0x55, 0xff), + makecol(0x55, 0x77, 0x00), + makecol(0x55, 0x77, 0x55), + makecol(0x55, 0x77, 0xaa), + makecol(0x55, 0x77, 0xff), + makecol(0x55, 0x99, 0x00), + makecol(0x55, 0x99, 0x55), + makecol(0x55, 0x99, 0xaa), + makecol(0x55, 0x99, 0xff), + makecol(0x55, 0xbb, 0x00), + makecol(0x55, 0xbb, 0x55), + makecol(0x55, 0xbb, 0xaa), + makecol(0x55, 0xbb, 0xff), + makecol(0x55, 0xdd, 0x00), + makecol(0x55, 0xdd, 0x55), + makecol(0x55, 0xdd, 0xaa), + makecol(0x55, 0xdd, 0xff), + makecol(0x55, 0xff, 0x00), + makecol(0x55, 0xff, 0x55), + makecol(0x55, 0xff, 0xaa), + makecol(0x55, 0xff, 0xff), + makecol(0x77, 0x00, 0x00), + makecol(0x77, 0x00, 0x55), + makecol(0x77, 0x00, 0xaa), + makecol(0x77, 0x00, 0xff), + makecol(0x77, 0x33, 0x00), + makecol(0x77, 0x33, 0x55), + makecol(0x77, 0x33, 0xaa), + makecol(0x77, 0x33, 0xff), + makecol(0x77, 0x55, 0x00), + makecol(0x77, 0x55, 0x55), + makecol(0x77, 0x55, 0xaa), + makecol(0x77, 0x55, 0xff), + makecol(0x77, 0x77, 0x00), + makecol(0x77, 0x77, 0x55), + makecol(0x77, 0x77, 0xaa), + makecol(0x77, 0x77, 0xff), + makecol(0x77, 0x99, 0x00), + makecol(0x77, 0x99, 0x55), + makecol(0x77, 0x99, 0xaa), + makecol(0x77, 0x99, 0xff), + makecol(0x77, 0xbb, 0x00), + makecol(0x77, 0xbb, 0x55), + makecol(0x77, 0xbb, 0xaa), + makecol(0x77, 0xbb, 0xff), + makecol(0x77, 0xdd, 0x00), + makecol(0x77, 0xdd, 0x55), + makecol(0x77, 0xdd, 0xaa), + makecol(0x77, 0xdd, 0xff), + makecol(0x77, 0xff, 0x00), + makecol(0x77, 0xff, 0x55), + makecol(0x77, 0xff, 0xaa), + makecol(0x77, 0xff, 0xff), + makecol(0x99, 0x00, 0x00), + makecol(0x99, 0x00, 0x55), + makecol(0x99, 0x00, 0xaa), + makecol(0x99, 0x00, 0xff), + makecol(0x99, 0x33, 0x00), + makecol(0x99, 0x33, 0x55), + makecol(0x99, 0x33, 0xaa), + makecol(0x99, 0x33, 0xff), + makecol(0x99, 0x55, 0x00), + makecol(0x99, 0x55, 0x55), + makecol(0x99, 0x55, 0xaa), + makecol(0x99, 0x55, 0xff), + makecol(0x99, 0x77, 0x00), + makecol(0x99, 0x77, 0x55), + makecol(0x99, 0x77, 0xaa), + makecol(0x99, 0x77, 0xff), + makecol(0x99, 0x99, 0x00), + makecol(0x99, 0x99, 0x55), + makecol(0x99, 0x99, 0xaa), + makecol(0x99, 0x99, 0xff), + makecol(0x99, 0xbb, 0x00), + makecol(0x99, 0xbb, 0x55), + makecol(0x99, 0xbb, 0xaa), + makecol(0x99, 0xbb, 0xff), + makecol(0x99, 0xdd, 0x00), + makecol(0x99, 0xdd, 0x55), + makecol(0x99, 0xdd, 0xaa), + makecol(0x99, 0xdd, 0xff), + makecol(0x99, 0xff, 0x00), + makecol(0x99, 0xff, 0x55), + makecol(0x99, 0xff, 0xaa), + makecol(0x99, 0xff, 0xff), + makecol(0xbb, 0x00, 0x00), + makecol(0xbb, 0x00, 0x55), + makecol(0xbb, 0x00, 0xaa), + makecol(0xbb, 0x00, 0xff), + makecol(0xbb, 0x33, 0x00), + makecol(0xbb, 0x33, 0x55), + makecol(0xbb, 0x33, 0xaa), + makecol(0xbb, 0x33, 0xff), + makecol(0xbb, 0x55, 0x00), + makecol(0xbb, 0x55, 0x55), + makecol(0xbb, 0x55, 0xaa), + makecol(0xbb, 0x55, 0xff), + makecol(0xbb, 0x77, 0x00), + makecol(0xbb, 0x77, 0x55), + makecol(0xbb, 0x77, 0xaa), + makecol(0xbb, 0x77, 0xff), + makecol(0xbb, 0x99, 0x00), + makecol(0xbb, 0x99, 0x55), + makecol(0xbb, 0x99, 0xaa), + makecol(0xbb, 0x99, 0xff), + makecol(0xbb, 0xbb, 0x00), + makecol(0xbb, 0xbb, 0x55), + makecol(0xbb, 0xbb, 0xaa), + makecol(0xbb, 0xbb, 0xff), + makecol(0xbb, 0xdd, 0x00), + makecol(0xbb, 0xdd, 0x55), + makecol(0xbb, 0xdd, 0xaa), + makecol(0xbb, 0xdd, 0xff), + makecol(0xbb, 0xff, 0x00), + makecol(0xbb, 0xff, 0x55), + makecol(0xbb, 0xff, 0xaa), + makecol(0xbb, 0xff, 0xff), + makecol(0xdd, 0x00, 0x00), + makecol(0xdd, 0x00, 0x55), + makecol(0xdd, 0x00, 0xaa), + makecol(0xdd, 0x00, 0xff), + makecol(0xdd, 0x33, 0x00), + makecol(0xdd, 0x33, 0x55), + makecol(0xdd, 0x33, 0xaa), + makecol(0xdd, 0x33, 0xff), + makecol(0xdd, 0x55, 0x00), + makecol(0xdd, 0x55, 0x55), + makecol(0xdd, 0x55, 0xaa), + makecol(0xdd, 0x55, 0xff), + makecol(0xdd, 0x77, 0x00), + makecol(0xdd, 0x77, 0x55), + makecol(0xdd, 0x77, 0xaa), + makecol(0xdd, 0x77, 0xff), + makecol(0xdd, 0x99, 0x00), + makecol(0xdd, 0x99, 0x55), + makecol(0xdd, 0x99, 0xaa), + makecol(0xdd, 0x99, 0xff), + makecol(0xdd, 0xbb, 0x00), + makecol(0xdd, 0xbb, 0x55), + makecol(0xdd, 0xbb, 0xaa), + makecol(0xdd, 0xbb, 0xff), + makecol(0xdd, 0xdd, 0x00), + makecol(0xdd, 0xdd, 0x55), + makecol(0xdd, 0xdd, 0xaa), + makecol(0xdd, 0xdd, 0xff), + makecol(0xdd, 0xff, 0x00), + makecol(0xdd, 0xff, 0x55), + makecol(0xdd, 0xff, 0xaa), + makecol(0xdd, 0xff, 0xff), + makecol(0xff, 0x00, 0x00), + makecol(0xff, 0x00, 0x55), + makecol(0xff, 0x00, 0xaa), + makecol(0xff, 0x00, 0xff), + makecol(0xff, 0x33, 0x00), + makecol(0xff, 0x33, 0x55), + makecol(0xff, 0x33, 0xaa), + makecol(0xff, 0x33, 0xff), + makecol(0xff, 0x55, 0x00), + makecol(0xff, 0x55, 0x55), + makecol(0xff, 0x55, 0xaa), + makecol(0xff, 0x55, 0xff), + makecol(0xff, 0x77, 0x00), + makecol(0xff, 0x77, 0x55), + makecol(0xff, 0x77, 0xaa), + makecol(0xff, 0x77, 0xff), + makecol(0xff, 0x99, 0x00), + makecol(0xff, 0x99, 0x55), + makecol(0xff, 0x99, 0xaa), + makecol(0xff, 0x99, 0xff), + makecol(0xff, 0xbb, 0x00), + makecol(0xff, 0xbb, 0x55), + makecol(0xff, 0xbb, 0xaa), + makecol(0xff, 0xbb, 0xff), + makecol(0xff, 0xdd, 0x00), + makecol(0xff, 0xdd, 0x55), + makecol(0xff, 0xdd, 0xaa), + makecol(0xff, 0xdd, 0xff), + makecol(0xff, 0xff, 0x00), + makecol(0xff, 0xff, 0x55), + makecol(0xff, 0xff, 0xaa), + makecol(0xff, 0xff, 0xff), + }, + /* Palette 5: 6x6x6 colour cube */ + { + makecol(0x00, 0x00, 0x00), + makecol(0x00, 0x00, 0x33), + makecol(0x00, 0x00, 0x66), + makecol(0x00, 0x00, 0x99), + makecol(0x00, 0x00, 0xcc), + makecol(0x00, 0x00, 0xff), + makecol(0x33, 0x00, 0x00), + makecol(0x33, 0x00, 0x33), + makecol(0x33, 0x00, 0x66), + makecol(0x33, 0x00, 0x99), + makecol(0x33, 0x00, 0xcc), + makecol(0x33, 0x00, 0xff), + makecol(0x66, 0x00, 0x00), + makecol(0x66, 0x00, 0x33), + makecol(0x66, 0x00, 0x66), + makecol(0x66, 0x00, 0x99), + makecol(0x66, 0x00, 0xcc), + makecol(0x66, 0x00, 0xff), + makecol(0x99, 0x00, 0x00), + makecol(0x99, 0x00, 0x33), + makecol(0x99, 0x00, 0x66), + makecol(0x99, 0x00, 0x99), + makecol(0x99, 0x00, 0xcc), + makecol(0x99, 0x00, 0xff), + makecol(0xcc, 0x00, 0x00), + makecol(0xcc, 0x00, 0x33), + makecol(0xcc, 0x00, 0x66), + makecol(0xcc, 0x00, 0x99), + makecol(0xcc, 0x00, 0xcc), + makecol(0xcc, 0x00, 0xff), + makecol(0xff, 0x00, 0x00), + makecol(0xff, 0x00, 0x33), + makecol(0xff, 0x00, 0x66), + makecol(0xff, 0x00, 0x99), + makecol(0xff, 0x00, 0xcc), + makecol(0xff, 0x00, 0xff), + makecol(0x00, 0x33, 0x00), + makecol(0x00, 0x33, 0x33), + makecol(0x00, 0x33, 0x66), + makecol(0x00, 0x33, 0x99), + makecol(0x00, 0x33, 0xcc), + makecol(0x00, 0x33, 0xff), + makecol(0x33, 0x33, 0x00), + makecol(0x33, 0x33, 0x33), + makecol(0x33, 0x33, 0x66), + makecol(0x33, 0x33, 0x99), + makecol(0x33, 0x33, 0xcc), + makecol(0x33, 0x33, 0xff), + makecol(0x66, 0x33, 0x00), + makecol(0x66, 0x33, 0x33), + makecol(0x66, 0x33, 0x66), + makecol(0x66, 0x33, 0x99), + makecol(0x66, 0x33, 0xcc), + makecol(0x66, 0x33, 0xff), + makecol(0x99, 0x33, 0x00), + makecol(0x99, 0x33, 0x33), + makecol(0x99, 0x33, 0x66), + makecol(0x99, 0x33, 0x99), + makecol(0x99, 0x33, 0xcc), + makecol(0x99, 0x33, 0xff), + makecol(0xcc, 0x33, 0x00), + makecol(0xcc, 0x33, 0x33), + makecol(0xcc, 0x33, 0x66), + makecol(0xcc, 0x33, 0x99), + makecol(0xcc, 0x33, 0xcc), + makecol(0xcc, 0x33, 0xff), + makecol(0xff, 0x33, 0x00), + makecol(0xff, 0x33, 0x33), + makecol(0xff, 0x33, 0x66), + makecol(0xff, 0x33, 0x99), + makecol(0xff, 0x33, 0xcc), + makecol(0xff, 0x33, 0xff), + makecol(0x00, 0x66, 0x00), + makecol(0x00, 0x66, 0x33), + makecol(0x00, 0x66, 0x66), + makecol(0x00, 0x66, 0x99), + makecol(0x00, 0x66, 0xcc), + makecol(0x00, 0x66, 0xff), + makecol(0x33, 0x66, 0x00), + makecol(0x33, 0x66, 0x33), + makecol(0x33, 0x66, 0x66), + makecol(0x33, 0x66, 0x99), + makecol(0x33, 0x66, 0xcc), + makecol(0x33, 0x66, 0xff), + makecol(0x66, 0x66, 0x00), + makecol(0x66, 0x66, 0x33), + makecol(0x66, 0x66, 0x66), + makecol(0x66, 0x66, 0x99), + makecol(0x66, 0x66, 0xcc), + makecol(0x66, 0x66, 0xff), + makecol(0x99, 0x66, 0x00), + makecol(0x99, 0x66, 0x33), + makecol(0x99, 0x66, 0x66), + makecol(0x99, 0x66, 0x99), + makecol(0x99, 0x66, 0xcc), + makecol(0x99, 0x66, 0xff), + makecol(0xcc, 0x66, 0x00), + makecol(0xcc, 0x66, 0x33), + makecol(0xcc, 0x66, 0x66), + makecol(0xcc, 0x66, 0x99), + makecol(0xcc, 0x66, 0xcc), + makecol(0xcc, 0x66, 0xff), + makecol(0xff, 0x66, 0x00), + makecol(0xff, 0x66, 0x33), + makecol(0xff, 0x66, 0x66), + makecol(0xff, 0x66, 0x99), + makecol(0xff, 0x66, 0xcc), + makecol(0xff, 0x66, 0xff), + makecol(0x00, 0x99, 0x00), + makecol(0x00, 0x99, 0x33), + makecol(0x00, 0x99, 0x66), + makecol(0x00, 0x99, 0x99), + makecol(0x00, 0x99, 0xcc), + makecol(0x00, 0x99, 0xff), + makecol(0x33, 0x99, 0x00), + makecol(0x33, 0x99, 0x33), + makecol(0x33, 0x99, 0x66), + makecol(0x33, 0x99, 0x99), + makecol(0x33, 0x99, 0xcc), + makecol(0x33, 0x99, 0xff), + makecol(0x66, 0x99, 0x00), + makecol(0x66, 0x99, 0x33), + makecol(0x66, 0x99, 0x66), + makecol(0x66, 0x99, 0x99), + makecol(0x66, 0x99, 0xcc), + makecol(0x66, 0x99, 0xff), + makecol(0x99, 0x99, 0x00), + makecol(0x99, 0x99, 0x33), + makecol(0x99, 0x99, 0x66), + makecol(0x99, 0x99, 0x99), + makecol(0x99, 0x99, 0xcc), + makecol(0x99, 0x99, 0xff), + makecol(0xcc, 0x99, 0x00), + makecol(0xcc, 0x99, 0x33), + makecol(0xcc, 0x99, 0x66), + makecol(0xcc, 0x99, 0x99), + makecol(0xcc, 0x99, 0xcc), + makecol(0xcc, 0x99, 0xff), + makecol(0xff, 0x99, 0x00), + makecol(0xff, 0x99, 0x33), + makecol(0xff, 0x99, 0x66), + makecol(0xff, 0x99, 0x99), + makecol(0xff, 0x99, 0xcc), + makecol(0xff, 0x99, 0xff), + makecol(0x00, 0xcc, 0x00), + makecol(0x00, 0xcc, 0x33), + makecol(0x00, 0xcc, 0x66), + makecol(0x00, 0xcc, 0x99), + makecol(0x00, 0xcc, 0xcc), + makecol(0x00, 0xcc, 0xff), + makecol(0x33, 0xcc, 0x00), + makecol(0x33, 0xcc, 0x33), + makecol(0x33, 0xcc, 0x66), + makecol(0x33, 0xcc, 0x99), + makecol(0x33, 0xcc, 0xcc), + makecol(0x33, 0xcc, 0xff), + makecol(0x66, 0xcc, 0x00), + makecol(0x66, 0xcc, 0x33), + makecol(0x66, 0xcc, 0x66), + makecol(0x66, 0xcc, 0x99), + makecol(0x66, 0xcc, 0xcc), + makecol(0x66, 0xcc, 0xff), + makecol(0x99, 0xcc, 0x00), + makecol(0x99, 0xcc, 0x33), + makecol(0x99, 0xcc, 0x66), + makecol(0x99, 0xcc, 0x99), + makecol(0x99, 0xcc, 0xcc), + makecol(0x99, 0xcc, 0xff), + makecol(0xcc, 0xcc, 0x00), + makecol(0xcc, 0xcc, 0x33), + makecol(0xcc, 0xcc, 0x66), + makecol(0xcc, 0xcc, 0x99), + makecol(0xcc, 0xcc, 0xcc), + makecol(0xcc, 0xcc, 0xff), + makecol(0xff, 0xcc, 0x00), + makecol(0xff, 0xcc, 0x33), + makecol(0xff, 0xcc, 0x66), + makecol(0xff, 0xcc, 0x99), + makecol(0xff, 0xcc, 0xcc), + makecol(0xff, 0xcc, 0xff), + makecol(0x00, 0xff, 0x00), + makecol(0x00, 0xff, 0x33), + makecol(0x00, 0xff, 0x66), + makecol(0x00, 0xff, 0x99), + makecol(0x00, 0xff, 0xcc), + makecol(0x00, 0xff, 0xff), + makecol(0x33, 0xff, 0x00), + makecol(0x33, 0xff, 0x33), + makecol(0x33, 0xff, 0x66), + makecol(0x33, 0xff, 0x99), + makecol(0x33, 0xff, 0xcc), + makecol(0x33, 0xff, 0xff), + makecol(0x66, 0xff, 0x00), + makecol(0x66, 0xff, 0x33), + makecol(0x66, 0xff, 0x66), + makecol(0x66, 0xff, 0x99), + makecol(0x66, 0xff, 0xcc), + makecol(0x66, 0xff, 0xff), + makecol(0x99, 0xff, 0x00), + makecol(0x99, 0xff, 0x33), + makecol(0x99, 0xff, 0x66), + makecol(0x99, 0xff, 0x99), + makecol(0x99, 0xff, 0xcc), + makecol(0x99, 0xff, 0xff), + makecol(0xcc, 0xff, 0x00), + makecol(0xcc, 0xff, 0x33), + makecol(0xcc, 0xff, 0x66), + makecol(0xcc, 0xff, 0x99), + makecol(0xcc, 0xff, 0xcc), + makecol(0xcc, 0xff, 0xff), + makecol(0xff, 0xff, 0x00), + makecol(0xff, 0xff, 0x33), + makecol(0xff, 0xff, 0x66), + makecol(0xff, 0xff, 0x99), + makecol(0xff, 0xff, 0xcc), + makecol(0xff, 0xff, 0xff), + makecol(0x00, 0x00, 0x00), + makecol(0x00, 0x00, 0x00), + makecol(0x00, 0x00, 0x00), + makecol(0x00, 0x00, 0x00), + makecol(0x00, 0x00, 0x00), + makecol(0x00, 0x00, 0x00), + makecol(0x00, 0x00, 0x00), + makecol(0x00, 0x00, 0x00), + makecol(0x00, 0x00, 0x00), + makecol(0x00, 0x00, 0x00), + makecol(0x00, 0x00, 0x00), + makecol(0x00, 0x00, 0x00), + makecol(0x00, 0x00, 0x00), + makecol(0x00, 0x00, 0x00), + makecol(0x00, 0x00, 0x00), + makecol(0x00, 0x00, 0x00), + makecol(0x00, 0x00, 0x00), + makecol(0x00, 0x00, 0x00), + makecol(0x00, 0x00, 0x00), + makecol(0x00, 0x00, 0x00), + makecol(0x00, 0x00, 0x00), + makecol(0x00, 0x00, 0x00), + makecol(0x00, 0x00, 0x00), + makecol(0x00, 0x00, 0x00), + makecol(0x00, 0x00, 0x00), + makecol(0x00, 0x00, 0x00), + makecol(0x00, 0x00, 0x00), + makecol(0x00, 0x00, 0x00), + makecol(0x00, 0x00, 0x00), + makecol(0x00, 0x00, 0x00), + makecol(0x00, 0x00, 0x00), + makecol(0x00, 0x00, 0x00), + makecol(0x00, 0x00, 0x00), + makecol(0x00, 0x00, 0x00), + makecol(0x00, 0x00, 0x00), + makecol(0x00, 0x00, 0x00), + makecol(0x00, 0x00, 0x00), + makecol(0x00, 0x00, 0x00), + makecol(0x00, 0x00, 0x00), + makecol(0x00, 0x00, 0x00), + }, - -#endif /*VID_PGC_PALETTE_H*/ +#endif /*VID_PGC_PALETTE_H*/ diff --git a/src/include/86box/vid_svga.h b/src/include/86box/vid_svga.h index 348677477..f725996d8 100644 --- a/src/include/86box/vid_svga.h +++ b/src/include/86box/vid_svga.h @@ -1,71 +1,133 @@ /* - * 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. + * 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. + * This file is part of the 86Box distribution. * - * Generic SVGA handling. + * Generic SVGA handling. * * * - * Authors: Sarah Walker, - * Miran Grca, + * Authors: Sarah Walker, + * Miran Grca, * - * Copyright 2008-2020 Sarah Walker. - * Copyright 2016-2020 Miran Grca. + * Copyright 2008-2020 Sarah Walker. + * Copyright 2016-2020 Miran Grca. */ #ifndef VIDEO_SVGA_H -# define VIDEO_SVGA_H +# define VIDEO_SVGA_H +# define FLAG_EXTRA_BANKS 1 +# define FLAG_ADDR_BY8 2 +# define FLAG_EXT_WRITE 4 +# define FLAG_LATCH8 8 +# define FLAG_NOSKEW 16 +# define FLAG_ADDR_BY16 32 +# define FLAG_RAMDAC_SHIFT 64 +# define FLAG_ATI 128 +# define FLAG_S3_911_16BIT 256 +# define FLAG_512K_MASK 512 +struct monitor_t; -#define FLAG_EXTRA_BANKS 1 -#define FLAG_ADDR_BY8 2 -#define FLAG_EXT_WRITE 4 -#define FLAG_LATCH8 8 -#define FLAG_NOSKEW 16 -#define FLAG_ADDR_BY16 32 -#define FLAG_RAMDAC_SHIFT 64 -#define FLAG_128K_MASK 128 - -typedef struct { - int ena, - x, y, xoff, yoff, xsize, ysize, - v_acc, h_acc; - uint32_t addr, pitch; +typedef struct hwcursor_t { + int ena; + int x; + int y; + int xoff; + int yoff; + int cur_xsize; + int cur_ysize; + int v_acc; + int h_acc; + uint32_t addr; + uint32_t pitch; } hwcursor_t; typedef union { - uint64_t q; - uint32_t d[2]; - uint16_t w[4]; - uint8_t b[8]; + uint64_t q; + uint32_t d[2]; + uint16_t w[4]; + uint8_t b[8]; } latch_t; -typedef struct svga_t -{ +typedef struct svga_t { mem_mapping_t mapping; - uint8_t fast, chain4, chain2_write, chain2_read, - ext_overscan, bus_size, - lowres, interlace, linedbl, rowcount, - set_reset_disabled, bpp, ramdac_type, fb_only, - readmode, writemode, readplane, - hwcursor_oddeven, dac_hwcursor_oddeven, overlay_oddeven, - fcr, hblank_overscan; + uint8_t fast; + uint8_t chain4; + uint8_t chain2_write; + uint8_t chain2_read; + uint8_t ext_overscan; + uint8_t bus_size; + uint8_t lowres; + uint8_t interlace; + uint8_t linedbl; + uint8_t rowcount; + uint8_t set_reset_disabled; + uint8_t bpp; + uint8_t ramdac_type; + uint8_t fb_only; + uint8_t readmode; + uint8_t writemode; + uint8_t readplane; + uint8_t hwcursor_oddeven; + uint8_t dac_hwcursor_oddeven; + uint8_t overlay_oddeven; + uint8_t fcr; + uint8_t hblank_overscan; - int dac_addr, dac_pos, dac_r, dac_g, - vtotal, dispend, vsyncstart, split, vblankstart, - hdisp, hdisp_old, htotal, hdisp_time, rowoffset, - dispon, hdisp_on, - vc, sc, linepos, vslines, linecountff, oddeven, - con, cursoron, blink, scrollcache, char_width, - firstline, lastline, firstline_draw, lastline_draw, - displine, fullchange, x_add, y_add, pan, - vram_display_mask, vidclock, dots_per_clock, hblank_ext, - hwcursor_on, dac_hwcursor_on, overlay_on, set_override, - hblankstart, hblankend, hblank_sub, hblank_end_val, hblank_end_len; + int dac_addr; + int dac_pos; + int dac_r; + int dac_g; + int dac_b; + int vtotal; + int dispend; + int vsyncstart; + int split; + int vblankstart; + int hdisp; + int hdisp_old; + int htotal; + int hdisp_time; + int rowoffset; + int dispon; + int hdisp_on; + int vc; + int sc; + int linepos; + int vslines; + int linecountff; + int oddeven; + int con; + int cursoron; + int blink; + int scrollcache; + int char_width; + int firstline; + int lastline; + int firstline_draw; + int lastline_draw; + int displine; + int fullchange; + int x_add; + int y_add; + int pan; + int vram_display_mask; + int vidclock; + int dots_per_clock; + int hblank_ext; + int hwcursor_on; + int dac_hwcursor_on; + int overlay_on; + int set_override; + int hblankstart; + int hblankend; + int hblank_sub; + int hblank_end_val; + int hblank_end_len; /*The three variables below allow us to implement memory maps like that seen on a 1MB Trio64 : 0MB-1MB - VRAM @@ -76,35 +138,48 @@ typedef struct svga_t For the example memory map, decode_mask would be 4MB-1 (4MB address space), vram_max would be 2MB (present video memory only responds to first 2MB), vram_mask would be 1MB-1 (video memory wraps at 1MB) */ - uint32_t decode_mask, vram_max, - vram_mask, - charseta, charsetb, - adv_flags, ma_latch, - ca_adj, ma, maback, - write_bank, read_bank, - extra_banks[2], - banked_mask, - ca, overscan_color, - *map8, pallook[512]; + uint32_t decode_mask; + uint32_t vram_max; + uint32_t vram_mask; + uint32_t charseta; + uint32_t charsetb; + uint32_t adv_flags; + uint32_t ma_latch; + uint32_t ca_adj; + uint32_t ma; + uint32_t maback; + uint32_t write_bank; + uint32_t read_bank; + uint32_t extra_banks[2]; + uint32_t banked_mask; + uint32_t ca; + uint32_t overscan_color; + uint32_t *map8; + uint32_t pallook[512]; PALETTE vgapal; - uint64_t dispontime, dispofftime; - latch_t latch; + uint64_t dispontime; + uint64_t dispofftime; + latch_t latch; pc_timer_t timer; double clock; - hwcursor_t hwcursor, hwcursor_latch, - dac_hwcursor, dac_hwcursor_latch, - overlay, overlay_latch; + hwcursor_t hwcursor; + hwcursor_t hwcursor_latch; + hwcursor_t dac_hwcursor; + hwcursor_t dac_hwcursor_latch; + hwcursor_t overlay; + hwcursor_t overlay_latch; void (*render)(struct svga_t *svga); + void (*render8514)(struct svga_t *svga); void (*recalctimings_ex)(struct svga_t *svga); - void (*video_out)(uint16_t addr, uint8_t val, void *p); - uint8_t (*video_in) (uint16_t addr, void *p); + void (*video_out)(uint16_t addr, uint8_t val, void *priv); + uint8_t (*video_in)(uint16_t addr, void *priv); void (*hwcursor_draw)(struct svga_t *svga, int displine); @@ -115,171 +190,213 @@ typedef struct svga_t void (*vblank_start)(struct svga_t *svga); void (*ven_write)(struct svga_t *svga, uint8_t val, uint32_t addr); - float (*getclock)(int clock, void *p); + float (*getclock)(int clock, void *priv); /* Called when VC=R18 and friends. If this returns zero then MA resetting is skipped. Matrox Mystique in Power mode reuses this counter for vertical line interrupt*/ - int (*line_compare)(struct svga_t *svga); + int (*line_compare)(struct svga_t *svga); /*Called at the start of vertical sync*/ void (*vsync_callback)(struct svga_t *svga); - uint32_t (*translate_address)(uint32_t addr, void *p); + uint32_t (*translate_address)(uint32_t addr, void *priv); /*If set then another device is driving the monitor output and the SVGA card should not attempt to display anything */ - int override; - void *p; + int override; + void *priv; - uint8_t crtc[256], gdcreg[256], attrregs[32], seqregs[256], - egapal[16], - *vram, *changedvram; + uint8_t crtc[256]; + uint8_t gdcreg[256]; + uint8_t attrregs[32]; + uint8_t seqregs[256]; + uint8_t egapal[16]; + uint8_t *vram; + uint8_t *changedvram; - uint8_t crtcreg, gdcaddr, - attrff, attr_palette_enable, attraddr, seqaddr, - miscout, cgastat, scrblank, - plane_mask, writemask, - colourcompare, colournocare, - dac_mask, dac_status, - dpms, dpms_ui, - ksc5601_sbyte_mask, ksc5601_udc_area_msb[2]; + uint8_t crtcreg; + uint8_t gdcaddr; + uint8_t attrff; + uint8_t attr_palette_enable; + uint8_t attraddr; + uint8_t seqaddr; + uint8_t miscout; + uint8_t cgastat; + uint8_t scrblank; + uint8_t plane_mask; + uint8_t writemask; + uint8_t colourcompare; + uint8_t colournocare; + uint8_t dac_mask; + uint8_t dac_status; + uint8_t dpms; + uint8_t dpms_ui; + uint8_t ksc5601_sbyte_mask; + uint8_t ksc5601_udc_area_msb[2]; - int ksc5601_swap_mode; + int ksc5601_swap_mode; uint16_t ksc5601_english_font_type; int vertical_linedbl; - + /*Used to implement CRTC[0x17] bit 2 hsync divisor*/ int hsync_divisor; - /*Tseng-style chain4 mode - CRTC dword mode is the same as byte mode, chain4 - addresses are shifted to match*/ - int packed_chain4; + /*Tseng-style chain4 mode - CRTC dword mode is the same as byte mode, chain4 + addresses are shifted to match*/ + int packed_chain4; - /*Force CRTC to dword mode, regardless of CR14/CR17. Required for S3 enhanced mode*/ - int force_dword_mode; - int force_byte_mode; + /*Force CRTC to dword mode, regardless of CR14/CR17. Required for S3 enhanced mode*/ + int force_dword_mode; - int remap_required; - uint32_t (*remap_func)(struct svga_t *svga, uint32_t in_addr); + int force_old_addr; - void *ramdac, *clock_gen; + int remap_required; + uint32_t (*remap_func)(struct svga_t *svga, uint32_t in_addr); + + void *ramdac; + void *clock_gen; + + /* Monitor Index */ + uint8_t monitor_index; + + /* Pointer to monitor */ + monitor_t *monitor; + + void * dev8514; + void * xga; } svga_t; +extern int vga_on; -extern int svga_init(const device_t *info, svga_t *svga, void *p, int memsize, - void (*recalctimings_ex)(struct svga_t *svga), - uint8_t (*video_in) (uint16_t addr, void *p), - void (*video_out)(uint16_t addr, uint8_t val, void *p), - void (*hwcursor_draw)(struct svga_t *svga, int displine), - void (*overlay_draw)(struct svga_t *svga, int displine)); -extern void svga_recalctimings(svga_t *svga); -extern void svga_close(svga_t *svga); +extern void ibm8514_poll(void *priv, svga_t *svga); +extern void ibm8514_recalctimings(svga_t *svga); +extern uint8_t ibm8514_ramdac_in(uint16_t port, void *priv); +extern void ibm8514_ramdac_out(uint16_t port, uint8_t val, void *priv); +extern int ibm8514_cpu_src(svga_t *svga); +extern int ibm8514_cpu_dest(svga_t *svga); +extern void ibm8514_accel_out_pixtrans(svga_t *svga, uint16_t port, uint16_t val, int len); +extern void ibm8514_short_stroke_start(int count, int cpu_input, uint32_t mix_dat, uint32_t cpu_dat, svga_t *svga, uint8_t ssv, int len); +extern void ibm8514_accel_start(int count, int cpu_input, uint32_t mix_dat, uint32_t cpu_dat, svga_t *svga, int len); -uint8_t svga_read(uint32_t addr, void *p); -uint16_t svga_readw(uint32_t addr, void *p); -uint32_t svga_readl(uint32_t addr, void *p); -void svga_write(uint32_t addr, uint8_t val, void *p); -void svga_writew(uint32_t addr, uint16_t val, void *p); -void svga_writel(uint32_t addr, uint32_t val, void *p); -uint8_t svga_read_linear(uint32_t addr, void *p); -uint8_t svga_readb_linear(uint32_t addr, void *p); -uint16_t svga_readw_linear(uint32_t addr, void *p); -uint32_t svga_readl_linear(uint32_t addr, void *p); -void svga_write_linear(uint32_t addr, uint8_t val, void *p); -void svga_writeb_linear(uint32_t addr, uint8_t val, void *p); -void svga_writew_linear(uint32_t addr, uint16_t val, void *p); -void svga_writel_linear(uint32_t addr, uint32_t val, void *p); +extern void xga_poll(void *priv, svga_t *svga); +extern void xga_recalctimings(svga_t *svga); -void svga_add_status_info(char *s, int max_len, void *p); +extern int svga_init(const device_t *info, svga_t *svga, void *priv, int memsize, + void (*recalctimings_ex)(struct svga_t *svga), + uint8_t (*video_in)(uint16_t addr, void *priv), + void (*video_out)(uint16_t addr, uint8_t val, void *priv), + void (*hwcursor_draw)(struct svga_t *svga, int displine), + void (*overlay_draw)(struct svga_t *svga, int displine)); +extern void svga_recalctimings(svga_t *svga); +extern void svga_close(svga_t *svga); -extern uint8_t svga_rotate[8][256]; +uint8_t svga_read(uint32_t addr, void *priv); +uint16_t svga_readw(uint32_t addr, void *priv); +uint32_t svga_readl(uint32_t addr, void *priv); +void svga_write(uint32_t addr, uint8_t val, void *priv); +void svga_writew(uint32_t addr, uint16_t val, void *priv); +void svga_writel(uint32_t addr, uint32_t val, void *priv); +uint8_t svga_read_linear(uint32_t addr, void *priv); +uint8_t svga_readb_linear(uint32_t addr, void *priv); +uint16_t svga_readw_linear(uint32_t addr, void *priv); +uint32_t svga_readl_linear(uint32_t addr, void *priv); +void svga_write_linear(uint32_t addr, uint8_t val, void *priv); +void svga_writeb_linear(uint32_t addr, uint8_t val, void *priv); +void svga_writew_linear(uint32_t addr, uint16_t val, void *priv); +void svga_writel_linear(uint32_t addr, uint32_t val, void *priv); -void svga_out(uint16_t addr, uint8_t val, void *p); -uint8_t svga_in(uint16_t addr, void *p); +void svga_add_status_info(char *s, int max_len, void *priv); -svga_t *svga_get_pri(); -void svga_set_override(svga_t *svga, int val); +extern uint8_t svga_rotate[8][256]; -void svga_set_ramdac_type(svga_t *svga, int type); -void svga_close(svga_t *svga); +void svga_out(uint16_t addr, uint8_t val, void *priv); +uint8_t svga_in(uint16_t addr, void *priv); -uint32_t svga_mask_addr(uint32_t addr, svga_t *svga); -uint32_t svga_mask_changedaddr(uint32_t addr, svga_t *svga); +svga_t *svga_get_pri(void); +void svga_set_override(svga_t *svga, int val); -void svga_doblit(int wx, int wy, svga_t *svga); +void svga_set_ramdac_type(svga_t *svga, int type); +void svga_close(svga_t *svga); +uint32_t svga_mask_addr(uint32_t addr, svga_t *svga); +uint32_t svga_mask_changedaddr(uint32_t addr, svga_t *svga); + +void svga_doblit(int wx, int wy, svga_t *svga); enum { RAMDAC_6BIT = 0, RAMDAC_8BIT }; - /* We need a way to add a device with a pointer to a parent device so it can attach itself to it, and possibly also a second ATi 68860 RAM DAC type that auto-sets SVGA render on RAM DAC render change. */ -extern void ati68860_ramdac_out(uint16_t addr, uint8_t val, void *p, svga_t *svga); -extern uint8_t ati68860_ramdac_in(uint16_t addr, void *p, svga_t *svga); -extern void ati68860_set_ramdac_type(void *p, int type); -extern void ati68860_ramdac_set_render(void *p, svga_t *svga); -extern void ati68860_ramdac_set_pallook(void *p, int i, uint32_t col); -extern void ati68860_hwcursor_draw(svga_t *svga, int displine); +extern void ati68860_ramdac_out(uint16_t addr, uint8_t val, void *priv, svga_t *svga); +extern uint8_t ati68860_ramdac_in(uint16_t addr, void *priv, svga_t *svga); +extern void ati68860_set_ramdac_type(void *priv, int type); +extern void ati68860_ramdac_set_render(void *priv, svga_t *svga); +extern void ati68860_ramdac_set_pallook(void *priv, int i, uint32_t col); +extern void ati68860_hwcursor_draw(svga_t *svga, int displine); -extern void att49x_ramdac_out(uint16_t addr, int rs2, uint8_t val, void *p, svga_t *svga); -extern uint8_t att49x_ramdac_in(uint16_t addr, int rs2, void *p, svga_t *svga); +extern void ati68875_ramdac_out(uint16_t addr, int rs2, int rs3, uint8_t val, void *priv, svga_t *svga); +extern uint8_t ati68875_ramdac_in(uint16_t addr, int rs2, int rs3, void *priv, svga_t *svga); -extern void att498_ramdac_out(uint16_t addr, int rs2, uint8_t val, void *p, svga_t *svga); -extern uint8_t att498_ramdac_in(uint16_t addr, int rs2, void *p, svga_t *svga); -extern float av9194_getclock(int clock, void *p); +extern void att49x_ramdac_out(uint16_t addr, int rs2, uint8_t val, void *priv, svga_t *svga); +extern uint8_t att49x_ramdac_in(uint16_t addr, int rs2, void *priv, svga_t *svga); -extern void bt48x_ramdac_out(uint16_t addr, int rs2, int rs3, uint8_t val, void *p, svga_t *svga); -extern uint8_t bt48x_ramdac_in(uint16_t addr, int rs2, int rs3, void *p, svga_t *svga); -extern void bt48x_recalctimings(void *p, svga_t *svga); -extern void bt48x_hwcursor_draw(svga_t *svga, int displine); +extern void att498_ramdac_out(uint16_t addr, int rs2, uint8_t val, void *priv, svga_t *svga); +extern uint8_t att498_ramdac_in(uint16_t addr, int rs2, void *priv, svga_t *svga); +extern float av9194_getclock(int clock, void *priv); -extern void ibm_rgb528_ramdac_out(uint16_t addr, int rs2, uint8_t val, void *p, svga_t *svga); -extern uint8_t ibm_rgb528_ramdac_in(uint16_t addr, int rs2, void *p, svga_t *svga); -extern void ibm_rgb528_recalctimings(void *p, svga_t *svga); -extern void ibm_rgb528_hwcursor_draw(svga_t *svga, int displine); +extern void bt48x_ramdac_out(uint16_t addr, int rs2, int rs3, uint8_t val, void *priv, svga_t *svga); +extern uint8_t bt48x_ramdac_in(uint16_t addr, int rs2, int rs3, void *priv, svga_t *svga); +extern void bt48x_recalctimings(void *priv, svga_t *svga); +extern void bt48x_hwcursor_draw(svga_t *svga, int displine); -extern void icd2061_write(void *p, int val); -extern float icd2061_getclock(int clock, void *p); +extern void ibm_rgb528_ramdac_out(uint16_t addr, int rs2, uint8_t val, void *priv, svga_t *svga); +extern uint8_t ibm_rgb528_ramdac_in(uint16_t addr, int rs2, void *priv, svga_t *svga); +extern void ibm_rgb528_recalctimings(void *priv, svga_t *svga); +extern void ibm_rgb528_hwcursor_draw(svga_t *svga, int displine); + +extern void icd2061_write(void *priv, int val); +extern float icd2061_getclock(int clock, void *priv); /* The code is the same, the #define's are so that the correct name can be used. */ -#define ics9161_write icd2061_write -#define ics9161_getclock icd2061_getclock +# define ics9161_write icd2061_write +# define ics9161_getclock icd2061_getclock -extern float ics2494_getclock(int clock, void *p); +extern float ics2494_getclock(int clock, void *priv); -extern void ics2595_write(void *p, int strobe, int dat); -extern double ics2595_getclock(void *p); -extern void ics2595_setclock(void *p, double clock); +extern void ics2595_write(void *priv, int strobe, int dat); +extern double ics2595_getclock(void *priv); +extern void ics2595_setclock(void *priv, double clock); -extern void sc1148x_ramdac_out(uint16_t addr, int rs2, uint8_t val, void *p, svga_t *svga); -extern uint8_t sc1148x_ramdac_in(uint16_t addr, int rs2, void *p, svga_t *svga); +extern void sc1148x_ramdac_out(uint16_t addr, int rs2, uint8_t val, void *priv, svga_t *svga); +extern uint8_t sc1148x_ramdac_in(uint16_t addr, int rs2, void *priv, svga_t *svga); -extern void sc1502x_ramdac_out(uint16_t addr, uint8_t val, void *p, svga_t *svga); -extern uint8_t sc1502x_ramdac_in(uint16_t addr, void *p, svga_t *svga); +extern void sc1502x_ramdac_out(uint16_t addr, uint8_t val, void *priv, svga_t *svga); +extern uint8_t sc1502x_ramdac_in(uint16_t addr, void *priv, svga_t *svga); -extern void sdac_ramdac_out(uint16_t addr, int rs2, uint8_t val, void *p, svga_t *svga); -extern uint8_t sdac_ramdac_in(uint16_t addr, int rs2, void *p, svga_t *svga); -extern float sdac_getclock(int clock, void *p); +extern void sdac_ramdac_out(uint16_t addr, int rs2, uint8_t val, void *priv, svga_t *svga); +extern uint8_t sdac_ramdac_in(uint16_t addr, int rs2, void *priv, svga_t *svga); +extern float sdac_getclock(int clock, void *priv); -extern void stg_ramdac_out(uint16_t addr, uint8_t val, void *p, svga_t *svga); -extern uint8_t stg_ramdac_in(uint16_t addr, void *p, svga_t *svga); -extern float stg_getclock(int clock, void *p); +extern void stg_ramdac_out(uint16_t addr, uint8_t val, void *priv, svga_t *svga); +extern uint8_t stg_ramdac_in(uint16_t addr, void *priv, svga_t *svga); +extern float stg_getclock(int clock, void *priv); -extern void tkd8001_ramdac_out(uint16_t addr, uint8_t val, void *p, svga_t *svga); -extern uint8_t tkd8001_ramdac_in(uint16_t addr, void *p, svga_t *svga); +extern void tkd8001_ramdac_out(uint16_t addr, uint8_t val, void *priv, svga_t *svga); +extern uint8_t tkd8001_ramdac_in(uint16_t addr, void *priv, svga_t *svga); -extern void tvp3026_ramdac_out(uint16_t addr, int rs2, int rs3, uint8_t val, void *p, svga_t *svga); -extern uint8_t tvp3026_ramdac_in(uint16_t addr, int rs2, int rs3, void *p, svga_t *svga); -extern void tvp3026_recalctimings(void *p, svga_t *svga); -extern void tvp3026_hwcursor_draw(svga_t *svga, int displine); -extern float tvp3026_getclock(int clock, void *p); +extern void tvp3026_ramdac_out(uint16_t addr, int rs2, int rs3, uint8_t val, void *priv, svga_t *svga); +extern uint8_t tvp3026_ramdac_in(uint16_t addr, int rs2, int rs3, void *priv, svga_t *svga); +extern void tvp3026_recalctimings(void *priv, svga_t *svga); +extern void tvp3026_hwcursor_draw(svga_t *svga, int displine); +extern float tvp3026_getclock(int clock, void *priv); -#ifdef EMU_DEVICE_H +# ifdef EMU_DEVICE_H extern const device_t ati68860_ramdac_device; +extern const device_t ati68875_ramdac_device; extern const device_t att490_ramdac_device; extern const device_t att491_ramdac_device; extern const device_t att492_ramdac_device; @@ -293,6 +410,9 @@ extern const device_t bt485a_ramdac_device; extern const device_t gendac_ramdac_device; extern const device_t ibm_rgb528_ramdac_device; extern const device_t ics2494an_305_device; +extern const device_t ati18810_device; +extern const device_t ati18811_0_device; +extern const device_t ati18811_1_device; extern const device_t ics2595_device; extern const device_t icd2061_device; extern const device_t ics9161_device; @@ -307,6 +427,6 @@ extern const device_t tkd8001_ramdac_device; extern const device_t tseng_ics5301_ramdac_device; extern const device_t tseng_ics5341_ramdac_device; extern const device_t tvp3026_ramdac_device; -#endif +# endif -#endif /*VIDEO_SVGA_H*/ +#endif /*VIDEO_SVGA_H*/ diff --git a/src/include/86box/vid_svga_render.h b/src/include/86box/vid_svga_render.h index 1bae05385..0c48303c9 100644 --- a/src/include/86box/vid_svga_render.h +++ b/src/include/86box/vid_svga_render.h @@ -1,27 +1,35 @@ /* - * 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. + * 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. + * This file is part of the 86Box distribution. * - * SVGA renderers. + * SVGA renderers. * * * - * Author: Sarah Walker, - * Miran Grca, - * Copyright 2008-2018 Sarah Walker. - * Copyright 2016-2018 Miran Grca. + * Authors: Sarah Walker, + * Miran Grca, + * + * Copyright 2008-2018 Sarah Walker. + * Copyright 2016-2018 Miran Grca. */ -extern int firstline_draw, lastline_draw; +#ifndef VIDEO_SVGA_RENDER_H +#define VIDEO_SVGA_RENDER_H + +extern int firstline_draw; +extern int lastline_draw; extern int displine; extern int sc; -extern uint32_t ma, ca; -extern int con, cursoron, cgablink; +extern uint32_t ma; +extern uint32_t ca; +extern int con; +extern int cursoron; +extern int cgablink; extern int scrollcache; @@ -65,4 +73,15 @@ void svga_render_ABGR8888_highres(svga_t *svga); void svga_render_RGBA8888_lowres(svga_t *svga); void svga_render_RGBA8888_highres(svga_t *svga); +void ibm8514_render_8bpp(svga_t *svga); +void ibm8514_render_15bpp(svga_t *svga); +void ibm8514_render_16bpp(svga_t *svga); +void ibm8514_render_24bpp(svga_t *svga); +void ibm8514_render_BGR(svga_t *svga); +void ibm8514_render_32bpp(svga_t *svga); +void ibm8514_render_ABGR8888(svga_t *svga); +void ibm8514_render_RGBA8888(svga_t *svga); + extern void (*svga_render)(svga_t *svga); + +#endif /*VID_SVGA_RENDER_H*/ diff --git a/src/include/86box/vid_svga_render_remap.h b/src/include/86box/vid_svga_render_remap.h index 5b7f0fe18..ff9151c3c 100644 --- a/src/include/86box/vid_svga_render_remap.h +++ b/src/include/86box/vid_svga_render_remap.h @@ -6,12 +6,15 @@ row 1 -> MA14 */ -//S3 - enhanced mode mappings CR31.3 can force doubleword mode -//Cirrus Logic handles SVGA writes seperately -//S3, CL, TGUI blitters need checking +#ifndef VIDEO_SVGA_RENDER_REMAP_H +#define VIDEO_SVGA_RENDER_REMAP_H -//CL, S3, Mach64, ET4000, Banshee, TGUI all okay -//Still to check - ViRGE, HT216 +// S3 - enhanced mode mappings CR31.3 can force doubleword mode +// Cirrus Logic handles SVGA writes seperately +// S3, CL, TGUI blitters need checking + +// CL, S3, Mach64, ET4000, Banshee, TGUI all okay +// Still to check - ViRGE, HT216 #define VAR_BYTE_MODE (0 << 0) #define VAR_WORD_MODE_MA13 (1 << 0) #define VAR_WORD_MODE_MA15 (2 << 0) @@ -20,45 +23,36 @@ #define VAR_ROW0_MA13 (1 << 2) #define VAR_ROW1_MA14 (1 << 3) -#define ADDRESS_REMAP_FUNC(nr) \ - static uint32_t address_remap_func_ ## nr(svga_t *svga, uint32_t in_addr) \ - { \ - uint32_t out_addr; \ - \ - switch (nr & VAR_MODE_MASK) \ - { \ - case VAR_BYTE_MODE: \ - out_addr = in_addr; \ - break; \ - \ - case VAR_WORD_MODE_MA13: \ - out_addr = ((in_addr << 1) & 0x1fff8) | \ - ((in_addr >> 13) & 0x4) | \ - (in_addr & ~0x1ffff); \ - break; \ - \ - case VAR_WORD_MODE_MA15: \ - out_addr = ((in_addr << 1) & 0x1fff8) | \ - ((in_addr >> 15) & 0x4) | \ - (in_addr & ~0x1ffff); \ - break; \ - \ - case VAR_DWORD_MODE: \ - out_addr = ((in_addr << 2) & 0x3fff0) | \ - ((in_addr >> 14) & 0xc) | \ - (in_addr & ~0x3ffff); \ - break; \ - } \ - \ - if (nr & VAR_ROW0_MA13) \ - out_addr = (out_addr & ~0x8000) | \ - ((svga->sc & 1) ? 0x8000 : 0); \ - if (nr & VAR_ROW1_MA14) \ - out_addr = (out_addr & ~0x10000) | \ - ((svga->sc & 2) ? 0x10000 : 0); \ - \ - return out_addr; \ - } +#define ADDRESS_REMAP_FUNC(nr) \ + static uint32_t address_remap_func_##nr(svga_t *svga, uint32_t in_addr) \ + { \ + uint32_t out_addr; \ + \ + switch (nr & VAR_MODE_MASK) { \ + case VAR_BYTE_MODE: \ + out_addr = in_addr; \ + break; \ + \ + case VAR_WORD_MODE_MA13: \ + out_addr = ((in_addr << 1) & 0x1fff8) | ((in_addr >> 13) & 0x4) | (in_addr & ~0x1ffff); \ + break; \ + \ + case VAR_WORD_MODE_MA15: \ + out_addr = ((in_addr << 1) & 0x1fff8) | ((in_addr >> 15) & 0x4) | (in_addr & ~0x1ffff); \ + break; \ + \ + case VAR_DWORD_MODE: \ + out_addr = ((in_addr << 2) & 0x3fff0) | ((in_addr >> 14) & 0xc) | (in_addr & ~0x3ffff); \ + break; \ + } \ + \ + if (nr & VAR_ROW0_MA13) \ + out_addr = (out_addr & ~0x8000) | ((svga->sc & 1) ? 0x8000 : 0); \ + if (nr & VAR_ROW1_MA14) \ + out_addr = (out_addr & ~0x10000) | ((svga->sc & 2) ? 0x10000 : 0); \ + \ + return out_addr; \ + } ADDRESS_REMAP_FUNC(0) ADDRESS_REMAP_FUNC(1) @@ -77,50 +71,52 @@ ADDRESS_REMAP_FUNC(13) ADDRESS_REMAP_FUNC(14) ADDRESS_REMAP_FUNC(15) -static uint32_t (*address_remap_funcs[16])(svga_t *svga, uint32_t in_addr) = -{ - address_remap_func_0, - address_remap_func_1, - address_remap_func_2, - address_remap_func_3, - address_remap_func_4, - address_remap_func_5, - address_remap_func_6, - address_remap_func_7, - address_remap_func_8, - address_remap_func_9, - address_remap_func_10, - address_remap_func_11, - address_remap_func_12, - address_remap_func_13, - address_remap_func_14, - address_remap_func_15 +static uint32_t (*address_remap_funcs[16])(svga_t *svga, uint32_t in_addr) = { + address_remap_func_0, + address_remap_func_1, + address_remap_func_2, + address_remap_func_3, + address_remap_func_4, + address_remap_func_5, + address_remap_func_6, + address_remap_func_7, + address_remap_func_8, + address_remap_func_9, + address_remap_func_10, + address_remap_func_11, + address_remap_func_12, + address_remap_func_13, + address_remap_func_14, + address_remap_func_15 }; -void svga_recalc_remap_func(svga_t *svga) +void +svga_recalc_remap_func(svga_t *svga) { - int func_nr; - - if (svga->fb_only || svga->force_byte_mode) - func_nr = 0; - else { - if (svga->force_dword_mode) - func_nr = VAR_DWORD_MODE; - else if (svga->crtc[0x14] & 0x40) - func_nr = svga->packed_chain4 ? VAR_BYTE_MODE : VAR_DWORD_MODE; - else if (svga->crtc[0x17] & 0x40) - func_nr = VAR_BYTE_MODE; - else if (svga->crtc[0x17] & 0x20) - func_nr = VAR_WORD_MODE_MA15; - else - func_nr = VAR_WORD_MODE_MA13; - - if (!(svga->crtc[0x17] & 0x01)) - func_nr |= VAR_ROW0_MA13; - if (!(svga->crtc[0x17] & 0x02)) - func_nr |= VAR_ROW1_MA14; - } + int func_nr; - svga->remap_required = (func_nr != 0); - svga->remap_func = address_remap_funcs[func_nr]; + if (svga->fb_only) + func_nr = 0; + else { + if (svga->force_dword_mode) + func_nr = VAR_DWORD_MODE; + else if (svga->crtc[0x14] & 0x40) + func_nr = svga->packed_chain4 ? VAR_BYTE_MODE : VAR_DWORD_MODE; + else if (svga->crtc[0x17] & 0x40) + func_nr = VAR_BYTE_MODE; + else if (svga->crtc[0x17] & 0x20) + func_nr = VAR_WORD_MODE_MA15; + else + func_nr = VAR_WORD_MODE_MA13; + + if (!(svga->crtc[0x17] & 0x01)) + func_nr |= VAR_ROW0_MA13; + if (!(svga->crtc[0x17] & 0x02)) + func_nr |= VAR_ROW1_MA14; + } + + svga->remap_required = (func_nr != 0); + svga->remap_func = address_remap_funcs[func_nr]; } + +#endif /*VIDEO_RENDER_REMAP_H*/ diff --git a/src/include/86box/vid_vga.h b/src/include/86box/vid_vga.h index c8a9b132e..bc552b285 100644 --- a/src/include/86box/vid_vga.h +++ b/src/include/86box/vid_vga.h @@ -1,34 +1,36 @@ /* - * 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. + * 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. + * This file is part of the 86Box distribution. * - * Emulation of the IBM MDA + VGA graphics cards. + * Emulation of the IBM MDA + VGA graphics cards. * * * - * Author: Sarah Walker, - * Miran Grca, - * Copyright 2008-2018 Sarah Walker. - * Copyright 2016-2018 Miran Grca. - * Copyright 2021 Jasmine Iwanek. + * Authors: Sarah Walker, + * Miran Grca, + * Jasmine Iwanek, + * + * Copyright 2008-2018 Sarah Walker. + * Copyright 2016-2018 Miran Grca. + * Copyright 2021 Jasmine Iwanek. */ -#ifndef VIDEO_VGA_H -# define VIDEO_VGA_H -typedef struct vga_t -{ - svga_t svga; - - rom_t bios_rom; +#ifndef VIDEO_VGA_H +#define VIDEO_VGA_H + +typedef struct vga_t { + svga_t svga; + + rom_t bios_rom; } vga_t; -static video_timings_t timing_vga = {VIDEO_ISA, 8, 16, 32, 8, 16, 32}; +static video_timings_t timing_vga = { VIDEO_ISA, 8, 16, 32, 8, 16, 32 }; -void vga_out(uint16_t addr, uint8_t val, void *p); -uint8_t vga_in(uint16_t addr, void *p); +void vga_out(uint16_t addr, uint8_t val, void *priv); +uint8_t vga_in(uint16_t addr, void *priv); -#endif /*VIDEO_VGA_H*/ +#endif /*VIDEO_VGA_H*/ diff --git a/src/include/86box/vid_voodoo_banshee.h b/src/include/86box/vid_voodoo_banshee.h index 808c861c8..89298e94e 100644 --- a/src/include/86box/vid_voodoo_banshee.h +++ b/src/include/86box/vid_voodoo_banshee.h @@ -1,18 +1,23 @@ /* - * 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. + * 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. + * This file is part of the 86Box distribution. * - * Voodoo Banshee and 3 specific emulation. + * Voodoo Banshee and 3 specific emulation. * * * - * Authors: Sarah Walker, + * Authors: Sarah Walker, * - * Copyright 2008-2020 Sarah Walker. + * Copyright 2008-2020 Sarah Walker. */ -void banshee_set_overlay_addr(void *p, uint32_t addr); +#ifndef VIDEO_VOODOO_BANSHEE_H +#define VIDEO_VOODOO_BANSHEE_H + +void banshee_set_overlay_addr(void *priv, uint32_t addr); + +#endif /*VIDEO_VOODOO_BANSHEE_H*/ diff --git a/src/include/86box/vid_voodoo_banshee_blitter.h b/src/include/86box/vid_voodoo_banshee_blitter.h index 3d8c16a1b..2d36f1566 100644 --- a/src/include/86box/vid_voodoo_banshee_blitter.h +++ b/src/include/86box/vid_voodoo_banshee_blitter.h @@ -1,18 +1,23 @@ /* - * 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. + * 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. + * This file is part of the 86Box distribution. * - * Voodoo Banshee and 3 specific emulation. + * Voodoo Banshee and 3 specific emulation. * * * - * Authors: Sarah Walker, + * Authors: Sarah Walker, * - * Copyright 2008-2020 Sarah Walker. + * Copyright 2008-2020 Sarah Walker. */ +#ifndef VIDEO_VOODOO_BANSHEE_BLITTER_H +#define VIDEO_VOODOO_BANSHEE_BLITTER_H + void voodoo_2d_reg_writel(voodoo_t *voodoo, uint32_t addr, uint32_t val); + +#endif /*VIDEO_VOODOO_BANSHEE_BLITTER_H*/ diff --git a/src/include/86box/vid_voodoo_blitter.h b/src/include/86box/vid_voodoo_blitter.h index 63bd0a99e..261352157 100644 --- a/src/include/86box/vid_voodoo_blitter.h +++ b/src/include/86box/vid_voodoo_blitter.h @@ -1,20 +1,25 @@ /* - * 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. + * 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. + * This file is part of the 86Box distribution. * - * 3DFX Voodoo emulation. + * 3DFX Voodoo emulation. * * * - * Authors: Sarah Walker, + * Authors: Sarah Walker, * - * Copyright 2008-2020 Sarah Walker. + * Copyright 2008-2020 Sarah Walker. */ +#ifndef VIDEO_VOODOO_BLITTER_H +#define VIDEO_VOODOO_BLITTER_H + void voodoo_v2_blit_start(voodoo_t *voodoo); void voodoo_v2_blit_data(voodoo_t *voodoo, uint32_t data); void voodoo_fastfill(voodoo_t *voodoo, voodoo_params_t *params); + +#endif /*VIDEO_VOODOO_BLITTER_H*/ diff --git a/src/include/86box/vid_voodoo_codegen_x86-64.h b/src/include/86box/vid_voodoo_codegen_x86-64.h index 443edc2cd..dc0ebce72 100644 --- a/src/include/86box/vid_voodoo_codegen_x86-64.h +++ b/src/include/86box/vid_voodoo_codegen_x86-64.h @@ -1,2021 +1,1903 @@ /*Registers : - + alphaMode fbzMode & 0x1f3fff fbzColorPath */ +#ifndef VIDEO_VOODOO_CODEGEN_X86_64_H +#define VIDEO_VOODOO_CODEGEN_X86_64_H + #ifdef _MSC_VER -#include +# include #else -#include +# include #endif -#define BLOCK_NUM 8 -#define BLOCK_MASK (BLOCK_NUM-1) +#define BLOCK_NUM 8 +#define BLOCK_MASK (BLOCK_NUM - 1) #define BLOCK_SIZE 8192 -#define LOD_MASK (LOD_TMIRROR_S | LOD_TMIRROR_T) +#define LOD_MASK (LOD_TMIRROR_S | LOD_TMIRROR_T) -typedef struct voodoo_x86_data_t -{ - uint8_t code_block[BLOCK_SIZE]; - int xdir; - uint32_t alphaMode; - uint32_t fbzMode; - uint32_t fogMode; - uint32_t fbzColorPath; - uint32_t textureMode[2]; - uint32_t tLOD[2]; - uint32_t trexInit1; - int is_tiled; -} voodoo_x86_data_t; - -//static voodoo_x86_data_t voodoo_x86_data[2][BLOCK_NUM]; - -static int last_block[4] = {0, 0}; -static int next_block_to_write[4] = {0, 0}; - -#define addbyte(val) \ - do { \ - code_block[block_pos++] = val; \ - if (block_pos >= BLOCK_SIZE) \ - fatal("Over!\n"); \ - } while (0) - -#define addword(val) \ - do { \ - *(uint16_t *)&code_block[block_pos] = val; \ - block_pos += 2; \ - if (block_pos >= BLOCK_SIZE) \ - fatal("Over!\n"); \ - } while (0) - -#define addlong(val) \ - do { \ - *(uint32_t *)&code_block[block_pos] = val; \ - block_pos += 4; \ - if (block_pos >= BLOCK_SIZE) \ - fatal("Over!\n"); \ - } while (0) - -#define addquad(val) \ - do { \ - *(uint64_t *)&code_block[block_pos] = val; \ - block_pos += 8; \ - if (block_pos >= BLOCK_SIZE) \ - fatal("Over!\n"); \ - } while (0) - - -static __m128i xmm_01_w;// = 0x0001000100010001ull; -static __m128i xmm_ff_w;// = 0x00ff00ff00ff00ffull; -static __m128i xmm_ff_b;// = 0x00000000ffffffffull; - -static __m128i alookup[257], aminuslookup[256]; -static __m128i minus_254;// = 0xff02ff02ff02ff02ull; -static __m128i bilinear_lookup[256*2]; -static __m128i xmm_00_ff_w[2]; -static uint32_t i_00_ff_w[2] = {0, 0xff}; - -static inline int codegen_texture_fetch(uint8_t *code_block, voodoo_t *voodoo, voodoo_params_t *params, voodoo_state_t *state, int block_pos, int tmu) -{ - if (params->textureMode[tmu] & 1) - { - addbyte(0x48); /*MOV RBX, state->tmu0_s*/ - addbyte(0x8b); - addbyte(0x9f); - addlong(tmu ? offsetof(voodoo_state_t, tmu1_s) : offsetof(voodoo_state_t, tmu0_s)); - addbyte(0x48); /*MOV RAX, (1 << 48)*/ - addbyte(0xb8); - addquad(1ULL << 48); - addbyte(0x48); /*XOR RDX, RDX*/ - addbyte(0x31); - addbyte(0xd2); - addbyte(0x48); /*MOV RCX, state->tmu0_t*/ - addbyte(0x8b); - addbyte(0x8f); - addlong(tmu ? offsetof(voodoo_state_t, tmu1_t) : offsetof(voodoo_state_t, tmu0_t)); - addbyte(0x48); /*CMP state->tmu_w, 0*/ - addbyte(0x83); - addbyte(0xbf); - addlong(tmu ? offsetof(voodoo_state_t, tmu1_w) : offsetof(voodoo_state_t, tmu0_w)); - addbyte(0); - addbyte(0x74); /*JZ +*/ - addbyte(7); - addbyte(0x48); /*IDIV state->tmu_w*/ - addbyte(0xf7); - addbyte(0xbf); - addlong(tmu ? offsetof(voodoo_state_t, tmu1_w) : offsetof(voodoo_state_t, tmu0_w)); - addbyte(0x48); /*SAR RBX, 14*/ - addbyte(0xc1); - addbyte(0xfb); - addbyte(14); - addbyte(0x48); /*SAR RCX, 14*/ - addbyte(0xc1); - addbyte(0xf9); - addbyte(14); - addbyte(0x48); /*IMUL RBX, RAX*/ - addbyte(0x0f); - addbyte(0xaf); - addbyte(0xd8); - addbyte(0x48); /*IMUL RCX, RAX*/ - addbyte(0x0f); - addbyte(0xaf); - addbyte(0xc8); - addbyte(0x48); /*SAR RBX, 30*/ - addbyte(0xc1); - addbyte(0xfb); - addbyte(30); - addbyte(0x48); /*SAR RCX, 30*/ - addbyte(0xc1); - addbyte(0xf9); - addbyte(30); - addbyte(0x48); /*BSR EDX, RAX*/ - addbyte(0x0f); - addbyte(0xbd); - addbyte(0xd0); - addbyte(0x48); /*SHL RAX, 8*/ - addbyte(0xc1); - addbyte(0xe0); - addbyte(8); - addbyte(0x89); /*MOV state->tex_t, ECX*/ - addbyte(0x8f); - addlong(offsetof(voodoo_state_t, tex_t)); - addbyte(0x89); /*MOV ECX, EDX*/ - addbyte(0xd1); - addbyte(0x83); /*SUB EDX, 19*/ - addbyte(0xea); - addbyte(19); - addbyte(0x48); /*SHR RAX, CL*/ - addbyte(0xd3); - addbyte(0xe8); - addbyte(0xc1); /*SHL EDX, 8*/ - addbyte(0xe2); - addbyte(8); - addbyte(0x25); /*AND EAX, 0xff*/ - addlong(0xff); - addbyte(0x89); /*MOV state->tex_s, EBX*/ - addbyte(0x9f); - addlong(offsetof(voodoo_state_t, tex_s)); - addbyte(0x41); /*MOVZX EAX, R9(logtable)[RAX]*/ - addbyte(0x0f); - addbyte(0xb6); - addbyte(0x04); - addbyte(0x01); - addbyte(0x09); /*OR EAX, EDX*/ - addbyte(0xd0); - addbyte(0x03); /*ADD EAX, state->lod*/ - addbyte(0x87); - addlong(offsetof(voodoo_state_t, tmu[tmu].lod)); - addbyte(0x3b); /*CMP EAX, state->lod_min*/ - addbyte(0x87); - addlong(offsetof(voodoo_state_t, lod_min[tmu])); - addbyte(0x0f); /*CMOVL EAX, state->lod_min*/ - addbyte(0x4c); - addbyte(0x87); - addlong(offsetof(voodoo_state_t, lod_min[tmu])); - addbyte(0x3b); /*CMP EAX, state->lod_max*/ - addbyte(0x87); - addlong(offsetof(voodoo_state_t, lod_max[tmu])); - addbyte(0x0f); /*CMOVNL EAX, state->lod_max*/ - addbyte(0x4d); - addbyte(0x87); - addlong(offsetof(voodoo_state_t, lod_max[tmu])); - addbyte(0xc1); /*SHR EAX, 8*/ - addbyte(0xe8); - addbyte(8); - addbyte(0x89); /*MOV state->lod, EAX*/ - addbyte(0x87); - addlong(offsetof(voodoo_state_t, lod)); - } - else - { - addbyte(0x48); /*MOV RAX, state->tmu0_s*/ - addbyte(0x8b); - addbyte(0x87); - addlong(tmu ? offsetof(voodoo_state_t, tmu1_s) : offsetof(voodoo_state_t, tmu0_s)); - addbyte(0x48); /*MOV RCX, state->tmu0_t*/ - addbyte(0x8b); - addbyte(0x8f); - addlong(tmu ? offsetof(voodoo_state_t, tmu1_t) : offsetof(voodoo_state_t, tmu0_t)); - addbyte(0x48); /*SHR RAX, 28*/ - addbyte(0xc1); - addbyte(0xe8); - addbyte(28); - addbyte(0x8b); /*MOV EBX, state->lod_min*/ - addbyte(0x9f); - addlong(offsetof(voodoo_state_t, lod_min[tmu])); - addbyte(0x48); /*SHR RCX, 28*/ - addbyte(0xc1); - addbyte(0xe9); - addbyte(28); - addbyte(0x48); /*MOV state->tex_s, RAX*/ - addbyte(0x89); - addbyte(0x87); - addlong(offsetof(voodoo_state_t, tex_s)); - addbyte(0xc1); /*SHR EBX, 8*/ - addbyte(0xeb); - addbyte(8); - addbyte(0x48); /*MOV state->tex_t, RCX*/ - addbyte(0x89); - addbyte(0x8f); - addlong(offsetof(voodoo_state_t, tex_t)); - addbyte(0x89); /*MOV state->lod, EBX*/ - addbyte(0x9f); - addlong(offsetof(voodoo_state_t, lod)); - } - - if (params->fbzColorPath & FBZCP_TEXTURE_ENABLED) - { - if (voodoo->bilinear_enabled && (params->textureMode[tmu] & 6)) - { - addbyte(0xb2); /*MOV DL, 8*/ - addbyte(8); - addbyte(0x8b); /*MOV ECX, state->lod[RDI]*/ - addbyte(0x8f); - addlong(offsetof(voodoo_state_t, lod)); - addbyte(0xbd); /*MOV EBP, 1*/ - addlong(1); - addbyte(0x28); /*SUB DL, CL*/ - addbyte(0xca); -// addbyte(0x8a); /*MOV DL, params->tex_shift[RSI+ECX*4]*/ -// addbyte(0x94); -// addbyte(0x8e); -// addlong(offsetof(voodoo_params_t, tex_shift)); - addbyte(0xd3); /*SHL EBP, CL*/ - addbyte(0xe5); - addbyte(0x8b); /*MOV EAX, state->tex_s[RDI]*/ - addbyte(0x87); - addlong(offsetof(voodoo_state_t, tex_s)); - addbyte(0xc1); /*SHL EBP, 3*/ - addbyte(0xe5); - addbyte(3); - addbyte(0x8b); /*MOV EBX, state->tex_t[RDI]*/ - addbyte(0x9f); - addlong(offsetof(voodoo_state_t, tex_t)); - if (params->tLOD[tmu] & LOD_TMIRROR_S) - { - addbyte(0xa9); /*TEST EAX, 0x1000*/ - addlong(0x1000); - addbyte(0x74); /*JZ +*/ - addbyte(2); - addbyte(0xf7); /*NOT EAX*/ - addbyte(0xd0); - } - if (params->tLOD[tmu] & LOD_TMIRROR_T) - { - addbyte(0xf7); /*TEST EBX, 0x1000*/ - addbyte(0xc3); - addlong(0x1000); - addbyte(0x74); /*JZ +*/ - addbyte(2); - addbyte(0xf7); /*NOT EBX*/ - addbyte(0xd3); - } - addbyte(0x29); /*SUB EAX, EBP*/ - addbyte(0xe8); - addbyte(0x29); /*SUB EBX, EBP*/ - addbyte(0xeb); - addbyte(0xd3); /*SAR EAX, CL*/ - addbyte(0xf8); - addbyte(0xd3); /*SAR EBX, CL*/ - addbyte(0xfb); - addbyte(0x89); /*MOV EBP, EAX*/ - addbyte(0xc5); - addbyte(0x89); /*MOV ECX, EBX*/ - addbyte(0xd9); - addbyte(0x83); /*AND EBP, 0xf*/ - addbyte(0xe5); - addbyte(0xf); - addbyte(0xc1); /*SHL ECX, 4*/ - addbyte(0xe1); - addbyte(4); - addbyte(0xc1); /*SAR EAX, 4*/ - addbyte(0xf8); - addbyte(4); - addbyte(0x81); /*AND ECX, 0xf0*/ - addbyte(0xe1); - addlong(0xf0); - addbyte(0xc1); /*SAR EBX, 4*/ - addbyte(0xfb); - addbyte(4); - addbyte(0x09); /*OR EBP, ECX*/ - addbyte(0xcd); - addbyte(0x8b); /*MOV ECX, state->lod[RDI]*/ - addbyte(0x8f); - addlong(offsetof(voodoo_state_t, lod)); - addbyte(0xc1); /*SHL EBP, 5*/ - addbyte(0xe5); - addbyte(5); - /*EAX = S, EBX = T, ECX = LOD, EDX = tex_shift, ESI=params, EDI=state, EBP = bilinear shift*/ - addbyte(0x48); /*LEA RSI, [RSI+RCX*4]*/ - addbyte(0x8d); - addbyte(0x34); - addbyte(0x8e); - addbyte(0x89); /*MOV ebp_store, EBP*/ - addbyte(0xaf); - addlong(offsetof(voodoo_state_t, ebp_store)); - addbyte(0x48); /*MOV RBP, state->tex[RDI+RCX*8]*/ - addbyte(0x8b); - addbyte(0xac); - addbyte(0xcf); - addlong(offsetof(voodoo_state_t, tex[tmu])); - addbyte(0x88); /*MOV CL, DL*/ - addbyte(0xd1); - addbyte(0x89); /*MOV EDX, EBX*/ - addbyte(0xda); - if (!state->clamp_s[tmu]) - { - addbyte(0x23); /*AND EAX, params->tex_w_mask[ESI]*/ - addbyte(0x86); - addlong(offsetof(voodoo_params_t, tex_w_mask[tmu])); - } - addbyte(0x83); /*ADD EDX, 1*/ - addbyte(0xc2); - addbyte(1); - if (state->clamp_t[tmu]) - { - addbyte(0x41); /*CMOVS EDX, R10(alookup[0](zero))*/ - addbyte(0x0f); - addbyte(0x48); - addbyte(0x12); - addbyte(0x3b); /*CMP EDX, params->tex_h_mask[ESI]*/ - addbyte(0x96); - addlong(offsetof(voodoo_params_t, tex_h_mask[tmu])); - addbyte(0x0f); /*CMOVA EDX, params->tex_h_mask[ESI]*/ - addbyte(0x47); - addbyte(0x96); - addlong(offsetof(voodoo_params_t, tex_h_mask[tmu])); - addbyte(0x85); /*TEST EBX,EBX*/ - addbyte(0xdb); - addbyte(0x41); /*CMOVS EBX, R10(alookup[0](zero))*/ - addbyte(0x0f); - addbyte(0x48); - addbyte(0x1a); - addbyte(0x3b); /*CMP EBX, params->tex_h_mask[ESI]*/ - addbyte(0x9e); - addlong(offsetof(voodoo_params_t, tex_h_mask[tmu])); - addbyte(0x0f); /*CMOVA EBX, params->tex_h_mask[ESI]*/ - addbyte(0x47); - addbyte(0x9e); - addlong(offsetof(voodoo_params_t, tex_h_mask[tmu])); - } - else - { - addbyte(0x23); /*AND EDX, params->tex_h_mask[ESI]*/ - addbyte(0x96); - addlong(offsetof(voodoo_params_t, tex_h_mask[tmu])); - addbyte(0x23); /*AND EBX, params->tex_h_mask[ESI]*/ - addbyte(0x9e); - addlong(offsetof(voodoo_params_t, tex_h_mask[tmu])); - } - /*EAX = S, EBX = T0, EDX = T1*/ - addbyte(0xd3); /*SHL EBX, CL*/ - addbyte(0xe3); - addbyte(0xd3); /*SHL EDX, CL*/ - addbyte(0xe2); - addbyte(0x48); /*LEA RBX,[RBP+RBX*4]*/ - addbyte(0x8d); - addbyte(0x5c); - addbyte(0x9d); - addbyte(0); - addbyte(0x48); /*LEA RDX,[RBP+RDX*4]*/ - addbyte(0x8d); - addbyte(0x54); - addbyte(0x95); - addbyte(0); - if (state->clamp_s[tmu]) - { - addbyte(0x8b); /*MOV EBP, params->tex_w_mask[ESI]*/ - addbyte(0xae); - addlong(offsetof(voodoo_params_t, tex_w_mask[tmu])); - addbyte(0x85); /*TEST EAX, EAX*/ - addbyte(0xc0); - addbyte(0x8b); /*MOV ebp_store2, RSI*/ - addbyte(0xb7); - addlong(offsetof(voodoo_state_t, ebp_store)); - addbyte(0x41); /*CMOVS EAX, R10(alookup[0](zero))*/ - addbyte(0x0f); - addbyte(0x48); - addbyte(0x02); - addbyte(0x78); /*JS + - clamp on 0*/ - addbyte(2+3+2+ 5+5+2); - addbyte(0x3b); /*CMP EAX, EBP*/ - addbyte(0xc5); - addbyte(0x0f); /*CMOVAE EAX, EBP*/ - addbyte(0x43); - addbyte(0xc5); - addbyte(0x73); /*JAE + - clamp on +*/ - addbyte(5+5+2); - } - else - { - addbyte(0x3b); /*CMP EAX, params->tex_w_mask[ESI] - is S at texture edge (ie will wrap/clamp)?*/ - addbyte(0x86); - addlong(offsetof(voodoo_params_t, tex_w_mask[tmu])); - addbyte(0x8b); /*MOV ebp_store2, ESI*/ - addbyte(0xb7); - addlong(offsetof(voodoo_state_t, ebp_store)); - addbyte(0x74); /*JE +*/ - addbyte(5+5+2); - } - - addbyte(0xf3); /*MOVQ XMM0, [RBX+RAX*4]*/ - addbyte(0x0f); - addbyte(0x7e); - addbyte(0x04); - addbyte(0x83); - addbyte(0xf3); /*MOVQ XMM1, [RDX+RAX*4]*/ - addbyte(0x0f); - addbyte(0x7e); - addbyte(0x0c); - addbyte(0x82); - - if (state->clamp_s[tmu]) - { - addbyte(0xeb); /*JMP +*/ - addbyte(5+5+4+4); - - /*S clamped - the two S coordinates are the same*/ - addbyte(0x66); /*MOVD XMM0, [RBX+RAX*4]*/ - addbyte(0x0f); - addbyte(0x6e); - addbyte(0x04); - addbyte(0x83); - addbyte(0x66); /*MOVD XMM1, [RDX+RAX*4]*/ - addbyte(0x0f); - addbyte(0x6e); - addbyte(0x0c); - addbyte(0x82); - addbyte(0x66); /*PUNPCKLDQ XMM0, XMM0*/ - addbyte(0x0f); - addbyte(0x62); - addbyte(0xc0); - addbyte(0x66); /*PUNPCKLDQ XMM1, XMM1*/ - addbyte(0x0f); - addbyte(0x62); - addbyte(0xc9); - } - else - { - addbyte(0xeb); /*JMP +*/ - addbyte(5+5+5+5+6+6); - - /*S wrapped - the two S coordinates are not contiguous*/ - addbyte(0x66); /*MOVD XMM0, [RBX+EAX*4]*/ - addbyte(0x0f); - addbyte(0x6e); - addbyte(0x04); - addbyte(0x83); - addbyte(0x66); /*MOVD XMM1, [RDX+EAX*4]*/ - addbyte(0x0f); - addbyte(0x6e); - addbyte(0x0c); - addbyte(0x82); - addbyte(0x66); /*PINSRW XMM0, [RBX], 2*/ - addbyte(0x0f); - addbyte(0xc4); - addbyte(0x03); - addbyte(0x02); - addbyte(0x66); /*PINSRW XMM1, [RDX], 2*/ - addbyte(0x0f); - addbyte(0xc4); - addbyte(0x0a); - addbyte(0x02); - addbyte(0x66); /*PINSRW XMM0, 2[RBX], 3*/ - addbyte(0x0f); - addbyte(0xc4); - addbyte(0x43); - addbyte(0x02); - addbyte(0x03); - addbyte(0x66); /*PINSRW XMM1, 2[RDX], 3*/ - addbyte(0x0f); - addbyte(0xc4); - addbyte(0x4a); - addbyte(0x02); - addbyte(0x03); - } - - addbyte(0x49); /*MOV R8, bilinear_lookup*/ - addbyte(0xb8); - addquad((uintptr_t)bilinear_lookup); - - addbyte(0x66); /*PUNPCKLBW XMM0, XMM2*/ - addbyte(0x0f); - addbyte(0x60); - addbyte(0xc2); - addbyte(0x66); /*PUNPCKLBW XMM1, XMM2*/ - addbyte(0x0f); - addbyte(0x60); - addbyte(0xca); - - addbyte(0x4c); /*ADD RSI, R8*/ - addbyte(0x01); - addbyte(0xc6); - - addbyte(0x66); /*PMULLW XMM0, bilinear_lookup[ESI]*/ - addbyte(0x0f); - addbyte(0xd5); - addbyte(0x06); - addbyte(0x66); /*PMULLW XMM1, bilinear_lookup[ESI]+0x10*/ - addbyte(0x0f); - addbyte(0xd5); - addbyte(0x4e); - addbyte(0x10); - addbyte(0x66); /*PADDW XMM0, XMM1*/ - addbyte(0x0f); - addbyte(0xfd); - addbyte(0xc0 | 1 | (0 << 3)); - addbyte(0x66); /*MOV XMM1, XMM0*/ - addbyte(0x0f); - addbyte(0x6f); - addbyte(0xc0 | 0 | (1 << 3)); - addbyte(0x66); /*PSRLDQ XMM0, 64*/ - addbyte(0x0f); - addbyte(0x73); - addbyte(0xd8); - addbyte(8); - addbyte(0x66); /*PADDW XMM0, XMM1*/ - addbyte(0x0f); - addbyte(0xfd); - addbyte(0xc0 | 1 | (0 << 3)); - addbyte(0x66); /*PSRLW XMM0, 8*/ - addbyte(0x0f); - addbyte(0x71); - addbyte(0xd0 | 0); - addbyte(8); - addbyte(0x66); /*PACKUSWB XMM0, XMM0*/ - addbyte(0x0f); - addbyte(0x67); - addbyte(0xc0); - - addbyte(0x4c); /*MOV RSI, R15*/ - addbyte(0x89); - addbyte(0xfe); - - addbyte(0x66); /*MOV EAX, XMM0*/ - addbyte(0x0f); - addbyte(0x7e); - addbyte(0xc0); - } - else - { - addbyte(0xb2); /*MOV DL, 8*/ - addbyte(8); - addbyte(0x8b); /*MOV ECX, state->lod[RDI]*/ - addbyte(0x8f); - addlong(offsetof(voodoo_state_t, lod)); - addbyte(0x48); /*MOV RBP, state->tex[RDI+RCX*8]*/ - addbyte(0x8b); - addbyte(0xac); - addbyte(0xcf); - addlong(offsetof(voodoo_state_t, tex[tmu])); - addbyte(0x28); /*SUB DL, CL*/ - addbyte(0xca); - addbyte(0x80); /*ADD CL, 4*/ - addbyte(0xc1); - addbyte(4); - addbyte(0x8b); /*MOV EAX, state->tex_s[EDI]*/ - addbyte(0x87); - addlong(offsetof(voodoo_state_t, tex_s)); - addbyte(0x8b); /*MOV EBX, state->tex_t[EDI]*/ - addbyte(0x9f); - addlong(offsetof(voodoo_state_t, tex_t)); - if (params->tLOD[tmu] & LOD_TMIRROR_S) - { - addbyte(0xa9); /*TEST EAX, 0x1000*/ - addlong(0x1000); - addbyte(0x74); /*JZ +*/ - addbyte(2); - addbyte(0xf7); /*NOT EAX*/ - addbyte(0xd0); - } - if (params->tLOD[tmu] & LOD_TMIRROR_T) - { - addbyte(0xf7); /*TEST EBX, 0x1000*/ - addbyte(0xc3); - addlong(0x1000); - addbyte(0x74); /*JZ +*/ - addbyte(2); - addbyte(0xf7); /*NOT EBX*/ - addbyte(0xd3); - } - addbyte(0xd3); /*SHR EAX, CL*/ - addbyte(0xe8); - addbyte(0xd3); /*SHR EBX, CL*/ - addbyte(0xeb); - if (state->clamp_s[tmu]) - { - addbyte(0x85); /*TEST EAX, EAX*/ - addbyte(0xc0); - addbyte(0x41); /*CMOVS EAX, R10(alookup[0](zero))*/ - addbyte(0x0f); - addbyte(0x48); - addbyte(0x02); - addbyte(0x3b); /*CMP EAX, params->tex_w_mask[ESI+ECX*4]*/ - addbyte(0x84); - addbyte(0x8e); - addlong(offsetof(voodoo_params_t, tex_w_mask[tmu]) - 0x10); - addbyte(0x0f); /*CMOVAE EAX, params->tex_w_mask[ESI+ECX*4]*/ - addbyte(0x43); - addbyte(0x84); - addbyte(0x8e); - addlong(offsetof(voodoo_params_t, tex_w_mask[tmu]) - 0x10); - - } - else - { - addbyte(0x23); /*AND EAX, params->tex_w_mask-0x10[ESI+ECX*4]*/ - addbyte(0x84); - addbyte(0x8e); - addlong(offsetof(voodoo_params_t, tex_w_mask[tmu]) - 0x10); - } - if (state->clamp_t[tmu]) - { - addbyte(0x85); /*TEST EBX, EBX*/ - addbyte(0xdb); - addbyte(0x41); /*CMOVS EBX, R10(alookup[0](zero))*/ - addbyte(0x0f); - addbyte(0x48); - addbyte(0x1a); - addbyte(0x3b); /*CMP EBX, params->tex_h_mask[ESI+ECX*4]*/ - addbyte(0x9c); - addbyte(0x8e); - addlong(offsetof(voodoo_params_t, tex_h_mask[tmu]) - 0x10); - addbyte(0x0f); /*CMOVAE EBX, params->tex_h_mask[ESI+ECX*4]*/ - addbyte(0x43); - addbyte(0x9c); - addbyte(0x8e); - addlong(offsetof(voodoo_params_t, tex_h_mask[tmu]) - 0x10); - } - else - { - addbyte(0x23); /*AND EBX, params->tex_h_mask-0x10[ESI+ECX*4]*/ - addbyte(0x9c); - addbyte(0x8e); - addlong(offsetof(voodoo_params_t, tex_h_mask[tmu]) - 0x10); - } - addbyte(0x88); /*MOV CL, DL*/ - addbyte(0xd1); - addbyte(0xd3); /*SHL EBX, CL*/ - addbyte(0xe3); - addbyte(0x01); /*ADD EBX, EAX*/ - addbyte(0xc3); - - addbyte(0x8b); /*MOV EAX, [RBP+RBX*4]*/ - addbyte(0x44); - addbyte(0x9d); - addbyte(0); - } - } - - return block_pos; -} - -static inline void voodoo_generate(uint8_t *code_block, voodoo_t *voodoo, voodoo_params_t *params, voodoo_state_t *state, int depthop) -{ - int block_pos = 0; - int z_skip_pos = 0; - int a_skip_pos = 0; - int chroma_skip_pos = 0; - int depth_jump_pos = 0; - int depth_jump_pos2 = 0; - int loop_jump_pos = 0; -// xmm_01_w = (__m128i)0x0001000100010001ull; -// xmm_ff_w = (__m128i)0x00ff00ff00ff00ffull; -// xmm_ff_b = (__m128i)0x00000000ffffffffull; - xmm_01_w = _mm_set_epi32(0, 0, 0x00010001, 0x00010001); - xmm_ff_w = _mm_set_epi32(0, 0, 0x00ff00ff, 0x00ff00ff); - xmm_ff_b = _mm_set_epi32(0, 0, 0, 0x00ffffff); - minus_254 = _mm_set_epi32(0, 0, 0xff02ff02, 0xff02ff02); -// *(uint64_t *)&const_1_48 = 0x45b0000000000000ull; -// block_pos = 0; -// voodoo_get_depth = &code_block[block_pos]; - /*W at (%esp+4) - Z at (%esp+12) - new_depth at (%esp+16)*/ -// if ((params->fbzMode & FBZ_DEPTH_ENABLE) && (depth_op == DEPTHOP_NEVER)) -// { -// addbyte(0xC3); /*RET*/ -// return; -// } - addbyte(0x55); /*PUSH RBP*/ - addbyte(0x57); /*PUSH RDI*/ - addbyte(0x56); /*PUSH RSI*/ - addbyte(0x53); /*PUSH RBX*/ - addbyte(0x41); /*PUSH R12*/ - addbyte(0x54); - addbyte(0x41); /*PUSH R13*/ - addbyte(0x55); - addbyte(0x41); /*PUSH R14*/ - addbyte(0x56); - addbyte(0x41); /*PUSH R15*/ - addbyte(0x57); - - addbyte(0x49); /*MOV R15, xmm_01_w*/ - addbyte(0xbf); - addquad((uint64_t)(uintptr_t)&xmm_01_w); - addbyte(0x66); /*MOVDQA XMM8, [R15]*/ - addbyte(0x45); - addbyte(0x0f); - addbyte(0x6f); - addbyte(0x07 | (0 << 3)); - addbyte(0x49); /*MOV R15, xmm_ff_w*/ - addbyte(0xbf); - addquad((uint64_t)(uintptr_t)&xmm_ff_w); - addbyte(0x66); /*MOVDQA XMM9, [R15]*/ - addbyte(0x45); - addbyte(0x0f); - addbyte(0x6f); - addbyte(0x07 | (1 << 3)); - addbyte(0x49); /*MOV R15, xmm_ff_b*/ - addbyte(0xbf); - addquad((uint64_t)(uintptr_t)&xmm_ff_b); - addbyte(0x66); /*MOVDQA XMM10, [R15]*/ - addbyte(0x45); - addbyte(0x0f); - addbyte(0x6f); - addbyte(0x07 | (2 << 3)); - addbyte(0x49); /*MOV R15, minus_254*/ - addbyte(0xbf); - addquad((uint64_t)(uintptr_t)&minus_254); - addbyte(0x66); /*MOVDQA XMM11, [R15]*/ - addbyte(0x45); - addbyte(0x0f); - addbyte(0x6f); - addbyte(0x07 | (3 << 3)); - -#if _WIN64 - addbyte(0x48); /*MOV RDI, RCX (voodoo_state)*/ - addbyte(0x89); - addbyte(0xcf); - addbyte(0x49); /*MOV R15, RDX (voodoo_params)*/ - addbyte(0x89); - addbyte(0xd7); - addbyte(0x4d); /*MOV R14, R9 (real_y)*/ - addbyte(0x89); - addbyte(0xce); -#else - addbyte(0x49); /*MOV R14, RCX (real_y)*/ - addbyte(0x89); - addbyte(0xce); - addbyte(0x49); /*MOV R15, RSI (voodoo_state)*/ - addbyte(0x89); - addbyte(0xf7); +/* Suppress a false positive warning on gcc that causes excessive build log spam */ +#if __GNUC__ >= 10 +# pragma GCC diagnostic ignored "-Wstringop-overflow" #endif - addbyte(0x49); /*MOV R9, logtable*/ - addbyte(0xb8 | (9 & 7)); - addquad((uint64_t)(uintptr_t)&logtable); - addbyte(0x49); /*MOV R10, alookup*/ - addbyte(0xb8 | (10 & 7)); - addquad((uint64_t)(uintptr_t)&alookup); - addbyte(0x49); /*MOV R11, aminuslookup*/ - addbyte(0xb8 | (11 & 7)); - addquad((uint64_t)(uintptr_t)&aminuslookup); - addbyte(0x49); /*MOV R12, xmm_00_ff_w*/ - addbyte(0xb8 | (12 & 7)); - addquad((uint64_t)(uintptr_t)&xmm_00_ff_w); - addbyte(0x49); /*MOV R13, i_00_ff_w*/ - addbyte(0xb8 | (13 & 7)); - addquad((uint64_t)(uintptr_t)&i_00_ff_w); +typedef struct voodoo_x86_data_t { + uint8_t code_block[BLOCK_SIZE]; + int xdir; + uint32_t alphaMode; + uint32_t fbzMode; + uint32_t fogMode; + uint32_t fbzColorPath; + uint32_t textureMode[2]; + uint32_t tLOD[2]; + uint32_t trexInit1; + int is_tiled; +} voodoo_x86_data_t; - loop_jump_pos = block_pos; - addbyte(0x4c); /*MOV RSI, R15*/ - addbyte(0x89); - addbyte(0xfe); - if (params->col_tiled || params->aux_tiled) - { - addbyte(0x8b); /*MOV EAX, state->x[EDI]*/ - addbyte(0x87); - addlong(offsetof(voodoo_state_t, x)); - addbyte(0x89); /*MOV EBX, EAX*/ - addbyte(0xc3); - addbyte(0x83); /*AND EAX, 63*/ - addbyte(0xe0); - addbyte(63); - addbyte(0xc1); /*SHR EBX, 6*/ - addbyte(0xeb); - addbyte(6); - addbyte(0xc1); /*SHL EBX, 11 - tile is 128*32, << 12, div 2 because word index*/ - addbyte(0xe3); - addbyte(11); - addbyte(0x01); /*ADD EAX, EBX*/ - addbyte(0xd8); - addbyte(0x89); /*MOV state->x_tiled[EDI], EAX*/ - addbyte(0x87); - addlong(offsetof(voodoo_state_t, x_tiled)); - } - addbyte(0x66); /*PXOR XMM2, XMM2*/ - addbyte(0x0f); - addbyte(0xef); +#if 0 +static voodoo_x86_data_t voodoo_x86_data[2][BLOCK_NUM]; +#endif + +static int last_block[4] = { 0, 0 }; +static int next_block_to_write[4] = { 0, 0 }; + +#define addbyte(val) \ + do { \ + code_block[block_pos++] = val; \ + } while (0) + +#define addword(val) \ + do { \ + *(uint16_t *) &code_block[block_pos] = val; \ + block_pos += 2; \ + } while (0) + +#define addlong(val) \ + do { \ + *(uint32_t *) &code_block[block_pos] = val; \ + block_pos += 4; \ + } while (0) + +#define addquad(val) \ + do { \ + *(uint64_t *) &code_block[block_pos] = val; \ + block_pos += 8; \ + } while (0) + +static __m128i xmm_01_w; // = 0x0001000100010001ull; +static __m128i xmm_ff_w; // = 0x00ff00ff00ff00ffull; +static __m128i xmm_ff_b; // = 0x00000000ffffffffull; + +static __m128i alookup[257]; +static __m128i aminuslookup[256]; +static __m128i minus_254; // = 0xff02ff02ff02ff02ull; +static __m128i bilinear_lookup[256 * 2]; +static __m128i xmm_00_ff_w[2]; +static uint32_t i_00_ff_w[2] = { 0, 0xff }; + +static inline int +codegen_texture_fetch(uint8_t *code_block, voodoo_t *voodoo, voodoo_params_t *params, voodoo_state_t *state, int block_pos, int tmu) +{ + if (params->textureMode[tmu] & 1) { + addbyte(0x48); /*MOV RBX, state->tmu0_s*/ + addbyte(0x8b); + addbyte(0x9f); + addlong(tmu ? offsetof(voodoo_state_t, tmu1_s) : offsetof(voodoo_state_t, tmu0_s)); + addbyte(0x48); /*MOV RAX, (1 << 48)*/ + addbyte(0xb8); + addquad(1ULL << 48); + addbyte(0x48); /*XOR RDX, RDX*/ + addbyte(0x31); addbyte(0xd2); + addbyte(0x48); /*MOV RCX, state->tmu0_t*/ + addbyte(0x8b); + addbyte(0x8f); + addlong(tmu ? offsetof(voodoo_state_t, tmu1_t) : offsetof(voodoo_state_t, tmu0_t)); + addbyte(0x48); /*CMP state->tmu_w, 0*/ + addbyte(0x83); + addbyte(0xbf); + addlong(tmu ? offsetof(voodoo_state_t, tmu1_w) : offsetof(voodoo_state_t, tmu0_w)); + addbyte(0); + addbyte(0x74); /*JZ +*/ + addbyte(7); + addbyte(0x48); /*IDIV state->tmu_w*/ + addbyte(0xf7); + addbyte(0xbf); + addlong(tmu ? offsetof(voodoo_state_t, tmu1_w) : offsetof(voodoo_state_t, tmu0_w)); + addbyte(0x48); /*SAR RBX, 14*/ + addbyte(0xc1); + addbyte(0xfb); + addbyte(14); + addbyte(0x48); /*SAR RCX, 14*/ + addbyte(0xc1); + addbyte(0xf9); + addbyte(14); + addbyte(0x48); /*IMUL RBX, RAX*/ + addbyte(0x0f); + addbyte(0xaf); + addbyte(0xd8); + addbyte(0x48); /*IMUL RCX, RAX*/ + addbyte(0x0f); + addbyte(0xaf); + addbyte(0xc8); + addbyte(0x48); /*SAR RBX, 30*/ + addbyte(0xc1); + addbyte(0xfb); + addbyte(30); + addbyte(0x48); /*SAR RCX, 30*/ + addbyte(0xc1); + addbyte(0xf9); + addbyte(30); + addbyte(0x48); /*BSR EDX, RAX*/ + addbyte(0x0f); + addbyte(0xbd); + addbyte(0xd0); + addbyte(0x48); /*SHL RAX, 8*/ + addbyte(0xc1); + addbyte(0xe0); + addbyte(8); + addbyte(0x89); /*MOV state->tex_t, ECX*/ + addbyte(0x8f); + addlong(offsetof(voodoo_state_t, tex_t)); + addbyte(0x89); /*MOV ECX, EDX*/ + addbyte(0xd1); + addbyte(0x83); /*SUB EDX, 19*/ + addbyte(0xea); + addbyte(19); + addbyte(0x48); /*SHR RAX, CL*/ + addbyte(0xd3); + addbyte(0xe8); + addbyte(0xc1); /*SHL EDX, 8*/ + addbyte(0xe2); + addbyte(8); + addbyte(0x25); /*AND EAX, 0xff*/ + addlong(0xff); + addbyte(0x89); /*MOV state->tex_s, EBX*/ + addbyte(0x9f); + addlong(offsetof(voodoo_state_t, tex_s)); + addbyte(0x41); /*MOVZX EAX, R9(logtable)[RAX]*/ + addbyte(0x0f); + addbyte(0xb6); + addbyte(0x04); + addbyte(0x01); + addbyte(0x09); /*OR EAX, EDX*/ + addbyte(0xd0); + addbyte(0x03); /*ADD EAX, state->lod*/ + addbyte(0x87); + addlong(offsetof(voodoo_state_t, tmu[tmu].lod)); + addbyte(0x3b); /*CMP EAX, state->lod_min*/ + addbyte(0x87); + addlong(offsetof(voodoo_state_t, lod_min[tmu])); + addbyte(0x0f); /*CMOVL EAX, state->lod_min*/ + addbyte(0x4c); + addbyte(0x87); + addlong(offsetof(voodoo_state_t, lod_min[tmu])); + addbyte(0x3b); /*CMP EAX, state->lod_max*/ + addbyte(0x87); + addlong(offsetof(voodoo_state_t, lod_max[tmu])); + addbyte(0x0f); /*CMOVNL EAX, state->lod_max*/ + addbyte(0x4d); + addbyte(0x87); + addlong(offsetof(voodoo_state_t, lod_max[tmu])); + addbyte(0xc1); /*SHR EAX, 8*/ + addbyte(0xe8); + addbyte(8); + addbyte(0x89); /*MOV state->lod, EAX*/ + addbyte(0x87); + addlong(offsetof(voodoo_state_t, lod)); + } else { + addbyte(0x48); /*MOV RAX, state->tmu0_s*/ + addbyte(0x8b); + addbyte(0x87); + addlong(tmu ? offsetof(voodoo_state_t, tmu1_s) : offsetof(voodoo_state_t, tmu0_s)); + addbyte(0x48); /*MOV RCX, state->tmu0_t*/ + addbyte(0x8b); + addbyte(0x8f); + addlong(tmu ? offsetof(voodoo_state_t, tmu1_t) : offsetof(voodoo_state_t, tmu0_t)); + addbyte(0x48); /*SHR RAX, 28*/ + addbyte(0xc1); + addbyte(0xe8); + addbyte(28); + addbyte(0x8b); /*MOV EBX, state->lod_min*/ + addbyte(0x9f); + addlong(offsetof(voodoo_state_t, lod_min[tmu])); + addbyte(0x48); /*SHR RCX, 28*/ + addbyte(0xc1); + addbyte(0xe9); + addbyte(28); + addbyte(0x48); /*MOV state->tex_s, RAX*/ + addbyte(0x89); + addbyte(0x87); + addlong(offsetof(voodoo_state_t, tex_s)); + addbyte(0xc1); /*SHR EBX, 8*/ + addbyte(0xeb); + addbyte(8); + addbyte(0x48); /*MOV state->tex_t, RCX*/ + addbyte(0x89); + addbyte(0x8f); + addlong(offsetof(voodoo_state_t, tex_t)); + addbyte(0x89); /*MOV state->lod, EBX*/ + addbyte(0x9f); + addlong(offsetof(voodoo_state_t, lod)); + } - if ((params->fbzMode & FBZ_W_BUFFER) || (params->fogMode & (FOG_ENABLE|FOG_CONSTANT|FOG_Z|FOG_ALPHA)) == FOG_ENABLE) - { - addbyte(0xb8); /*MOV new_depth, 0*/ - addlong(0); - addbyte(0x66); /*TEST w+4, 0xffff*/ - addbyte(0xf7); - addbyte(0x87); - addlong(offsetof(voodoo_state_t, w)+4); - addword(0xffff); - addbyte(0x75); /*JNZ got_depth*/ - depth_jump_pos = block_pos; - addbyte(0); -// addbyte(4+5+2+3+2+5+5+3+2+2+2+/*3+*/3+2+6+4+5+2+3); - addbyte(0x8b); /*MOV EDX, w*/ - addbyte(0x97); - addlong(offsetof(voodoo_state_t, w)); - addbyte(0xb8); /*MOV new_depth, 0xf001*/ - addlong(0xf001); - addbyte(0x89); /*MOV EBX, EDX*/ - addbyte(0xd3); - addbyte(0xc1); /*SHR EDX, 16*/ - addbyte(0xea); - addbyte(16); - addbyte(0x74); /*JZ got_depth*/ - depth_jump_pos2 = block_pos; - addbyte(0); -// addbyte(5+5+3+2+2+2+/*3+*/3+2+6+4+5+2+3); - addbyte(0xb9); /*MOV ECX, 19*/ - addlong(19); - addbyte(0x0f); /*BSR EAX, EDX*/ - addbyte(0xbd); - addbyte(0xc2); - addbyte(0xba); /*MOV EDX, 15*/ - addlong(15); + if (params->fbzColorPath & FBZCP_TEXTURE_ENABLED) { + if (voodoo->bilinear_enabled && (params->textureMode[tmu] & 6)) { + addbyte(0xb2); /*MOV DL, 8*/ + addbyte(8); + addbyte(0x8b); /*MOV ECX, state->lod[RDI]*/ + addbyte(0x8f); + addlong(offsetof(voodoo_state_t, lod)); + addbyte(0xbd); /*MOV EBP, 1*/ + addlong(1); + addbyte(0x28); /*SUB DL, CL*/ + addbyte(0xca); +#if 0 + addbyte(0x8a); /*MOV DL, params->tex_shift[RSI+ECX*4]*/ + addbyte(0x94); + addbyte(0x8e); + addlong(offsetof(voodoo_params_t, tex_shift)); +#endif + addbyte(0xd3); /*SHL EBP, CL*/ + addbyte(0xe5); + addbyte(0x8b); /*MOV EAX, state->tex_s[RDI]*/ + addbyte(0x87); + addlong(offsetof(voodoo_state_t, tex_s)); + addbyte(0xc1); /*SHL EBP, 3*/ + addbyte(0xe5); + addbyte(3); + addbyte(0x8b); /*MOV EBX, state->tex_t[RDI]*/ + addbyte(0x9f); + addlong(offsetof(voodoo_state_t, tex_t)); + if (params->tLOD[tmu] & LOD_TMIRROR_S) { + addbyte(0xa9); /*TEST EAX, 0x1000*/ + addlong(0x1000); + addbyte(0x74); /*JZ +*/ + addbyte(2); + addbyte(0xf7); /*NOT EAX*/ + addbyte(0xd0); + } + if (params->tLOD[tmu] & LOD_TMIRROR_T) { + addbyte(0xf7); /*TEST EBX, 0x1000*/ + addbyte(0xc3); + addlong(0x1000); + addbyte(0x74); /*JZ +*/ + addbyte(2); addbyte(0xf7); /*NOT EBX*/ addbyte(0xd3); - addbyte(0x29); /*SUB EDX, EAX - EDX = exp*/ - addbyte(0xc2); - addbyte(0x29); /*SUB ECX, EDX*/ - addbyte(0xd1); - addbyte(0xc1); /*SHL EDX, 12*/ - addbyte(0xe2); - addbyte(12); - addbyte(0xd3); /*SHR EBX, CL*/ - addbyte(0xeb); - addbyte(0x81); /*AND EBX, 0xfff - EBX = mant*/ - addbyte(0xe3); - addlong(0xfff); - addbyte(0x67); /*LEA EAX, 1[EDX, EBX]*/ - addbyte(0x8d); - addbyte(0x44); - addbyte(0x13); - addbyte(1); - addbyte(0xbb); /*MOV EBX, 0xffff*/ - addlong(0xffff); - addbyte(0x39); /*CMP EAX, EBX*/ - addbyte(0xd8); - addbyte(0x0f); /*CMOVA EAX, EBX*/ + } + addbyte(0x29); /*SUB EAX, EBP*/ + addbyte(0xe8); + addbyte(0x29); /*SUB EBX, EBP*/ + addbyte(0xeb); + addbyte(0xd3); /*SAR EAX, CL*/ + addbyte(0xf8); + addbyte(0xd3); /*SAR EBX, CL*/ + addbyte(0xfb); + addbyte(0x89); /*MOV EBP, EAX*/ + addbyte(0xc5); + addbyte(0x89); /*MOV ECX, EBX*/ + addbyte(0xd9); + addbyte(0x83); /*AND EBP, 0xf*/ + addbyte(0xe5); + addbyte(0xf); + addbyte(0xc1); /*SHL ECX, 4*/ + addbyte(0xe1); + addbyte(4); + addbyte(0xc1); /*SAR EAX, 4*/ + addbyte(0xf8); + addbyte(4); + addbyte(0x81); /*AND ECX, 0xf0*/ + addbyte(0xe1); + addlong(0xf0); + addbyte(0xc1); /*SAR EBX, 4*/ + addbyte(0xfb); + addbyte(4); + addbyte(0x09); /*OR EBP, ECX*/ + addbyte(0xcd); + addbyte(0x8b); /*MOV ECX, state->lod[RDI]*/ + addbyte(0x8f); + addlong(offsetof(voodoo_state_t, lod)); + addbyte(0xc1); /*SHL EBP, 5*/ + addbyte(0xe5); + addbyte(5); + /*EAX = S, EBX = T, ECX = LOD, EDX = tex_shift, ESI=params, EDI=state, EBP = bilinear shift*/ + addbyte(0x48); /*LEA RSI, [RSI+RCX*4]*/ + addbyte(0x8d); + addbyte(0x34); + addbyte(0x8e); + addbyte(0x89); /*MOV ebp_store, EBP*/ + addbyte(0xaf); + addlong(offsetof(voodoo_state_t, ebp_store)); + addbyte(0x48); /*MOV RBP, state->tex[RDI+RCX*8]*/ + addbyte(0x8b); + addbyte(0xac); + addbyte(0xcf); + addlong(offsetof(voodoo_state_t, tex[tmu])); + addbyte(0x88); /*MOV CL, DL*/ + addbyte(0xd1); + addbyte(0x89); /*MOV EDX, EBX*/ + addbyte(0xda); + if (!state->clamp_s[tmu]) { + addbyte(0x23); /*AND EAX, params->tex_w_mask[ESI]*/ + addbyte(0x86); + addlong(offsetof(voodoo_params_t, tex_w_mask[tmu])); + } + addbyte(0x83); /*ADD EDX, 1*/ + addbyte(0xc2); + addbyte(1); + if (state->clamp_t[tmu]) { + addbyte(0x41); /*CMOVS EDX, R10(alookup[0](zero))*/ + addbyte(0x0f); + addbyte(0x48); + addbyte(0x12); + addbyte(0x3b); /*CMP EDX, params->tex_h_mask[ESI]*/ + addbyte(0x96); + addlong(offsetof(voodoo_params_t, tex_h_mask[tmu])); + addbyte(0x0f); /*CMOVA EDX, params->tex_h_mask[ESI]*/ addbyte(0x47); - addbyte(0xc3); + addbyte(0x96); + addlong(offsetof(voodoo_params_t, tex_h_mask[tmu])); + addbyte(0x85); /*TEST EBX,EBX*/ + addbyte(0xdb); + addbyte(0x41); /*CMOVS EBX, R10(alookup[0](zero))*/ + addbyte(0x0f); + addbyte(0x48); + addbyte(0x1a); + addbyte(0x3b); /*CMP EBX, params->tex_h_mask[ESI]*/ + addbyte(0x9e); + addlong(offsetof(voodoo_params_t, tex_h_mask[tmu])); + addbyte(0x0f); /*CMOVA EBX, params->tex_h_mask[ESI]*/ + addbyte(0x47); + addbyte(0x9e); + addlong(offsetof(voodoo_params_t, tex_h_mask[tmu])); + } else { + addbyte(0x23); /*AND EDX, params->tex_h_mask[ESI]*/ + addbyte(0x96); + addlong(offsetof(voodoo_params_t, tex_h_mask[tmu])); + addbyte(0x23); /*AND EBX, params->tex_h_mask[ESI]*/ + addbyte(0x9e); + addlong(offsetof(voodoo_params_t, tex_h_mask[tmu])); + } + /*EAX = S, EBX = T0, EDX = T1*/ + addbyte(0xd3); /*SHL EBX, CL*/ + addbyte(0xe3); + addbyte(0xd3); /*SHL EDX, CL*/ + addbyte(0xe2); + addbyte(0x48); /*LEA RBX,[RBP+RBX*4]*/ + addbyte(0x8d); + addbyte(0x5c); + addbyte(0x9d); + addbyte(0); + addbyte(0x48); /*LEA RDX,[RBP+RDX*4]*/ + addbyte(0x8d); + addbyte(0x54); + addbyte(0x95); + addbyte(0); + if (state->clamp_s[tmu]) { + addbyte(0x8b); /*MOV EBP, params->tex_w_mask[ESI]*/ + addbyte(0xae); + addlong(offsetof(voodoo_params_t, tex_w_mask[tmu])); + addbyte(0x85); /*TEST EAX, EAX*/ + addbyte(0xc0); + addbyte(0x8b); /*MOV ebp_store2, RSI*/ + addbyte(0xb7); + addlong(offsetof(voodoo_state_t, ebp_store)); + addbyte(0x41); /*CMOVS EAX, R10(alookup[0](zero))*/ + addbyte(0x0f); + addbyte(0x48); + addbyte(0x02); + addbyte(0x78); /*JS + - clamp on 0*/ + addbyte(2 + 3 + 2 + 5 + 5 + 2); + addbyte(0x3b); /*CMP EAX, EBP*/ + addbyte(0xc5); + addbyte(0x0f); /*CMOVAE EAX, EBP*/ + addbyte(0x43); + addbyte(0xc5); + addbyte(0x73); /*JAE + - clamp on +*/ + addbyte(5 + 5 + 2); + } else { + addbyte(0x3b); /*CMP EAX, params->tex_w_mask[ESI] - is S at texture edge (ie will wrap/clamp)?*/ + addbyte(0x86); + addlong(offsetof(voodoo_params_t, tex_w_mask[tmu])); + addbyte(0x8b); /*MOV ebp_store2, ESI*/ + addbyte(0xb7); + addlong(offsetof(voodoo_state_t, ebp_store)); + addbyte(0x74); /*JE +*/ + addbyte(5 + 5 + 2); + } - if (depth_jump_pos) - *(uint8_t *)&code_block[depth_jump_pos] = (block_pos - depth_jump_pos) - 1; - if (depth_jump_pos) - *(uint8_t *)&code_block[depth_jump_pos2] = (block_pos - depth_jump_pos2) - 1; - - if ((params->fogMode & (FOG_ENABLE|FOG_CONSTANT|FOG_Z|FOG_ALPHA)) == FOG_ENABLE) - { - addbyte(0x89); /*MOV state->w_depth[EDI], EAX*/ - addbyte(0x87); - addlong(offsetof(voodoo_state_t, w_depth)); - } + addbyte(0xf3); /*MOVQ XMM0, [RBX+RAX*4]*/ + addbyte(0x0f); + addbyte(0x7e); + addbyte(0x04); + addbyte(0x83); + addbyte(0xf3); /*MOVQ XMM1, [RDX+RAX*4]*/ + addbyte(0x0f); + addbyte(0x7e); + addbyte(0x0c); + addbyte(0x82); + + if (state->clamp_s[tmu]) { + addbyte(0xeb); /*JMP +*/ + addbyte(5 + 5 + 4 + 4); + + /*S clamped - the two S coordinates are the same*/ + addbyte(0x66); /*MOVD XMM0, [RBX+RAX*4]*/ + addbyte(0x0f); + addbyte(0x6e); + addbyte(0x04); + addbyte(0x83); + addbyte(0x66); /*MOVD XMM1, [RDX+RAX*4]*/ + addbyte(0x0f); + addbyte(0x6e); + addbyte(0x0c); + addbyte(0x82); + addbyte(0x66); /*PUNPCKLDQ XMM0, XMM0*/ + addbyte(0x0f); + addbyte(0x62); + addbyte(0xc0); + addbyte(0x66); /*PUNPCKLDQ XMM1, XMM1*/ + addbyte(0x0f); + addbyte(0x62); + addbyte(0xc9); + } else { + addbyte(0xeb); /*JMP +*/ + addbyte(5 + 5 + 5 + 5 + 6 + 6); + + /*S wrapped - the two S coordinates are not contiguous*/ + addbyte(0x66); /*MOVD XMM0, [RBX+EAX*4]*/ + addbyte(0x0f); + addbyte(0x6e); + addbyte(0x04); + addbyte(0x83); + addbyte(0x66); /*MOVD XMM1, [RDX+EAX*4]*/ + addbyte(0x0f); + addbyte(0x6e); + addbyte(0x0c); + addbyte(0x82); + addbyte(0x66); /*PINSRW XMM0, [RBX], 2*/ + addbyte(0x0f); + addbyte(0xc4); + addbyte(0x03); + addbyte(0x02); + addbyte(0x66); /*PINSRW XMM1, [RDX], 2*/ + addbyte(0x0f); + addbyte(0xc4); + addbyte(0x0a); + addbyte(0x02); + addbyte(0x66); /*PINSRW XMM0, 2[RBX], 3*/ + addbyte(0x0f); + addbyte(0xc4); + addbyte(0x43); + addbyte(0x02); + addbyte(0x03); + addbyte(0x66); /*PINSRW XMM1, 2[RDX], 3*/ + addbyte(0x0f); + addbyte(0xc4); + addbyte(0x4a); + addbyte(0x02); + addbyte(0x03); + } + + addbyte(0x49); /*MOV R8, bilinear_lookup*/ + addbyte(0xb8); + addquad((uintptr_t) bilinear_lookup); + + addbyte(0x66); /*PUNPCKLBW XMM0, XMM2*/ + addbyte(0x0f); + addbyte(0x60); + addbyte(0xc2); + addbyte(0x66); /*PUNPCKLBW XMM1, XMM2*/ + addbyte(0x0f); + addbyte(0x60); + addbyte(0xca); + + addbyte(0x4c); /*ADD RSI, R8*/ + addbyte(0x01); + addbyte(0xc6); + + addbyte(0x66); /*PMULLW XMM0, bilinear_lookup[ESI]*/ + addbyte(0x0f); + addbyte(0xd5); + addbyte(0x06); + addbyte(0x66); /*PMULLW XMM1, bilinear_lookup[ESI]+0x10*/ + addbyte(0x0f); + addbyte(0xd5); + addbyte(0x4e); + addbyte(0x10); + addbyte(0x66); /*PADDW XMM0, XMM1*/ + addbyte(0x0f); + addbyte(0xfd); + addbyte(0xc0 | 1 | (0 << 3)); + addbyte(0x66); /*MOV XMM1, XMM0*/ + addbyte(0x0f); + addbyte(0x6f); + addbyte(0xc0 | 0 | (1 << 3)); + addbyte(0x66); /*PSRLDQ XMM0, 64*/ + addbyte(0x0f); + addbyte(0x73); + addbyte(0xd8); + addbyte(8); + addbyte(0x66); /*PADDW XMM0, XMM1*/ + addbyte(0x0f); + addbyte(0xfd); + addbyte(0xc0 | 1 | (0 << 3)); + addbyte(0x66); /*PSRLW XMM0, 8*/ + addbyte(0x0f); + addbyte(0x71); + addbyte(0xd0 | 0); + addbyte(8); + addbyte(0x66); /*PACKUSWB XMM0, XMM0*/ + addbyte(0x0f); + addbyte(0x67); + addbyte(0xc0); + + addbyte(0x4c); /*MOV RSI, R15*/ + addbyte(0x89); + addbyte(0xfe); + + addbyte(0x66); /*MOV EAX, XMM0*/ + addbyte(0x0f); + addbyte(0x7e); + addbyte(0xc0); + } else { + addbyte(0xb2); /*MOV DL, 8*/ + addbyte(8); + addbyte(0x8b); /*MOV ECX, state->lod[RDI]*/ + addbyte(0x8f); + addlong(offsetof(voodoo_state_t, lod)); + addbyte(0x48); /*MOV RBP, state->tex[RDI+RCX*8]*/ + addbyte(0x8b); + addbyte(0xac); + addbyte(0xcf); + addlong(offsetof(voodoo_state_t, tex[tmu])); + addbyte(0x28); /*SUB DL, CL*/ + addbyte(0xca); + addbyte(0x80); /*ADD CL, 4*/ + addbyte(0xc1); + addbyte(4); + addbyte(0x8b); /*MOV EAX, state->tex_s[EDI]*/ + addbyte(0x87); + addlong(offsetof(voodoo_state_t, tex_s)); + addbyte(0x8b); /*MOV EBX, state->tex_t[EDI]*/ + addbyte(0x9f); + addlong(offsetof(voodoo_state_t, tex_t)); + if (params->tLOD[tmu] & LOD_TMIRROR_S) { + addbyte(0xa9); /*TEST EAX, 0x1000*/ + addlong(0x1000); + addbyte(0x74); /*JZ +*/ + addbyte(2); + addbyte(0xf7); /*NOT EAX*/ + addbyte(0xd0); + } + if (params->tLOD[tmu] & LOD_TMIRROR_T) { + addbyte(0xf7); /*TEST EBX, 0x1000*/ + addbyte(0xc3); + addlong(0x1000); + addbyte(0x74); /*JZ +*/ + addbyte(2); + addbyte(0xf7); /*NOT EBX*/ + addbyte(0xd3); + } + addbyte(0xd3); /*SHR EAX, CL*/ + addbyte(0xe8); + addbyte(0xd3); /*SHR EBX, CL*/ + addbyte(0xeb); + if (state->clamp_s[tmu]) { + addbyte(0x85); /*TEST EAX, EAX*/ + addbyte(0xc0); + addbyte(0x41); /*CMOVS EAX, R10(alookup[0](zero))*/ + addbyte(0x0f); + addbyte(0x48); + addbyte(0x02); + addbyte(0x3b); /*CMP EAX, params->tex_w_mask[ESI+ECX*4]*/ + addbyte(0x84); + addbyte(0x8e); + addlong(offsetof(voodoo_params_t, tex_w_mask[tmu]) - 0x10); + addbyte(0x0f); /*CMOVAE EAX, params->tex_w_mask[ESI+ECX*4]*/ + addbyte(0x43); + addbyte(0x84); + addbyte(0x8e); + addlong(offsetof(voodoo_params_t, tex_w_mask[tmu]) - 0x10); + + } else { + addbyte(0x23); /*AND EAX, params->tex_w_mask-0x10[ESI+ECX*4]*/ + addbyte(0x84); + addbyte(0x8e); + addlong(offsetof(voodoo_params_t, tex_w_mask[tmu]) - 0x10); + } + if (state->clamp_t[tmu]) { + addbyte(0x85); /*TEST EBX, EBX*/ + addbyte(0xdb); + addbyte(0x41); /*CMOVS EBX, R10(alookup[0](zero))*/ + addbyte(0x0f); + addbyte(0x48); + addbyte(0x1a); + addbyte(0x3b); /*CMP EBX, params->tex_h_mask[ESI+ECX*4]*/ + addbyte(0x9c); + addbyte(0x8e); + addlong(offsetof(voodoo_params_t, tex_h_mask[tmu]) - 0x10); + addbyte(0x0f); /*CMOVAE EBX, params->tex_h_mask[ESI+ECX*4]*/ + addbyte(0x43); + addbyte(0x9c); + addbyte(0x8e); + addlong(offsetof(voodoo_params_t, tex_h_mask[tmu]) - 0x10); + } else { + addbyte(0x23); /*AND EBX, params->tex_h_mask-0x10[ESI+ECX*4]*/ + addbyte(0x9c); + addbyte(0x8e); + addlong(offsetof(voodoo_params_t, tex_h_mask[tmu]) - 0x10); + } + addbyte(0x88); /*MOV CL, DL*/ + addbyte(0xd1); + addbyte(0xd3); /*SHL EBX, CL*/ + addbyte(0xe3); + addbyte(0x01); /*ADD EBX, EAX*/ + addbyte(0xc3); + + addbyte(0x8b); /*MOV EAX, [RBP+RBX*4]*/ + addbyte(0x44); + addbyte(0x9d); + addbyte(0); } - if (!(params->fbzMode & FBZ_W_BUFFER)) - { - addbyte(0x8b); /*MOV EAX, z*/ - addbyte(0x87); - addlong(offsetof(voodoo_state_t, z)); - addbyte(0xbb); /*MOV EBX, 0xffff*/ - addlong(0xffff); + } + + return block_pos; +} + +static inline void +voodoo_generate(uint8_t *code_block, voodoo_t *voodoo, voodoo_params_t *params, voodoo_state_t *state, int depthop) +{ + int block_pos = 0; + int z_skip_pos = 0; + int a_skip_pos = 0; + int chroma_skip_pos = 0; + int depth_jump_pos = 0; + int depth_jump_pos2 = 0; + int loop_jump_pos = 0; +#if 0 + xmm_01_w = (__m128i)0x0001000100010001ull; + xmm_ff_w = (__m128i)0x00ff00ff00ff00ffull; + xmm_ff_b = (__m128i)0x00000000ffffffffull; +#endif + xmm_01_w = _mm_set_epi32(0, 0, 0x00010001, 0x00010001); + xmm_ff_w = _mm_set_epi32(0, 0, 0x00ff00ff, 0x00ff00ff); + xmm_ff_b = _mm_set_epi32(0, 0, 0, 0x00ffffff); + minus_254 = _mm_set_epi32(0, 0, 0xff02ff02, 0xff02ff02); +#if 0 + *(uint64_t *)&const_1_48 = 0x45b0000000000000ull; + block_pos = 0; + voodoo_get_depth = &code_block[block_pos]; +#endif + /*W at (%esp+4) + Z at (%esp+12) + new_depth at (%esp+16)*/ +#if 0 + if ((params->fbzMode & FBZ_DEPTH_ENABLE) && (depth_op == DEPTHOP_NEVER)) { + addbyte(0xC3); /*RET*/ + return; + } +#endif + addbyte(0x55); /*PUSH RBP*/ + addbyte(0x57); /*PUSH RDI*/ + addbyte(0x56); /*PUSH RSI*/ + addbyte(0x53); /*PUSH RBX*/ + addbyte(0x41); /*PUSH R12*/ + addbyte(0x54); + addbyte(0x41); /*PUSH R13*/ + addbyte(0x55); + addbyte(0x41); /*PUSH R14*/ + addbyte(0x56); + addbyte(0x41); /*PUSH R15*/ + addbyte(0x57); + + addbyte(0x49); /*MOV R15, xmm_01_w*/ + addbyte(0xbf); + addquad((uint64_t) (uintptr_t) &xmm_01_w); + addbyte(0x66); /*MOVDQA XMM8, [R15]*/ + addbyte(0x45); + addbyte(0x0f); + addbyte(0x6f); + addbyte(0x07 | (0 << 3)); + addbyte(0x49); /*MOV R15, xmm_ff_w*/ + addbyte(0xbf); + addquad((uint64_t) (uintptr_t) &xmm_ff_w); + addbyte(0x66); /*MOVDQA XMM9, [R15]*/ + addbyte(0x45); + addbyte(0x0f); + addbyte(0x6f); + addbyte(0x07 | (1 << 3)); + addbyte(0x49); /*MOV R15, xmm_ff_b*/ + addbyte(0xbf); + addquad((uint64_t) (uintptr_t) &xmm_ff_b); + addbyte(0x66); /*MOVDQA XMM10, [R15]*/ + addbyte(0x45); + addbyte(0x0f); + addbyte(0x6f); + addbyte(0x07 | (2 << 3)); + addbyte(0x49); /*MOV R15, minus_254*/ + addbyte(0xbf); + addquad((uint64_t) (uintptr_t) &minus_254); + addbyte(0x66); /*MOVDQA XMM11, [R15]*/ + addbyte(0x45); + addbyte(0x0f); + addbyte(0x6f); + addbyte(0x07 | (3 << 3)); + +#if _WIN64 + addbyte(0x48); /*MOV RDI, RCX (voodoo_state)*/ + addbyte(0x89); + addbyte(0xcf); + addbyte(0x49); /*MOV R15, RDX (voodoo_params)*/ + addbyte(0x89); + addbyte(0xd7); + addbyte(0x4d); /*MOV R14, R9 (real_y)*/ + addbyte(0x89); + addbyte(0xce); +#else + addbyte(0x49); /*MOV R14, RCX (real_y)*/ + addbyte(0x89); + addbyte(0xce); + addbyte(0x49); /*MOV R15, RSI (voodoo_state)*/ + addbyte(0x89); + addbyte(0xf7); +#endif + + addbyte(0x49); /*MOV R9, logtable*/ + addbyte(0xb8 | (9 & 7)); + addquad((uint64_t) (uintptr_t) &logtable); + addbyte(0x49); /*MOV R10, alookup*/ + addbyte(0xb8 | (10 & 7)); + addquad((uint64_t) (uintptr_t) &alookup); + addbyte(0x49); /*MOV R11, aminuslookup*/ + addbyte(0xb8 | (11 & 7)); + addquad((uint64_t) (uintptr_t) &aminuslookup); + addbyte(0x49); /*MOV R12, xmm_00_ff_w*/ + addbyte(0xb8 | (12 & 7)); + addquad((uint64_t) (uintptr_t) &xmm_00_ff_w); + addbyte(0x49); /*MOV R13, i_00_ff_w*/ + addbyte(0xb8 | (13 & 7)); + addquad((uint64_t) (uintptr_t) &i_00_ff_w); + + loop_jump_pos = block_pos; + addbyte(0x4c); /*MOV RSI, R15*/ + addbyte(0x89); + addbyte(0xfe); + if (params->col_tiled || params->aux_tiled) { + addbyte(0x8b); /*MOV EAX, state->x[EDI]*/ + addbyte(0x87); + addlong(offsetof(voodoo_state_t, x)); + addbyte(0x89); /*MOV EBX, EAX*/ + addbyte(0xc3); + addbyte(0x83); /*AND EAX, 63*/ + addbyte(0xe0); + addbyte(63); + addbyte(0xc1); /*SHR EBX, 6*/ + addbyte(0xeb); + addbyte(6); + addbyte(0xc1); /*SHL EBX, 11 - tile is 128*32, << 12, div 2 because word index*/ + addbyte(0xe3); + addbyte(11); + addbyte(0x01); /*ADD EAX, EBX*/ + addbyte(0xd8); + addbyte(0x89); /*MOV state->x_tiled[EDI], EAX*/ + addbyte(0x87); + addlong(offsetof(voodoo_state_t, x_tiled)); + } + addbyte(0x66); /*PXOR XMM2, XMM2*/ + addbyte(0x0f); + addbyte(0xef); + addbyte(0xd2); + + if ((params->fbzMode & FBZ_W_BUFFER) || (params->fogMode & (FOG_ENABLE | FOG_CONSTANT | FOG_Z | FOG_ALPHA)) == FOG_ENABLE) { + addbyte(0xb8); /*MOV new_depth, 0*/ + addlong(0); + addbyte(0x66); /*TEST w+4, 0xffff*/ + addbyte(0xf7); + addbyte(0x87); + addlong(offsetof(voodoo_state_t, w) + 4); + addword(0xffff); + addbyte(0x75); /*JNZ got_depth*/ + depth_jump_pos = block_pos; + addbyte(0); +#if 0 + addbyte(4+5+2+3+2+5+5+3+2+2+2+/*3+*/3+2+6+4+5+2+3); +#endif + addbyte(0x8b); /*MOV EDX, w*/ + addbyte(0x97); + addlong(offsetof(voodoo_state_t, w)); + addbyte(0xb8); /*MOV new_depth, 0xf001*/ + addlong(0xf001); + addbyte(0x89); /*MOV EBX, EDX*/ + addbyte(0xd3); + addbyte(0xc1); /*SHR EDX, 16*/ + addbyte(0xea); + addbyte(16); + addbyte(0x74); /*JZ got_depth*/ + depth_jump_pos2 = block_pos; + addbyte(0); +#if 0 + addbyte(5+5+3+2+2+2+/*3+*/3+2+6+4+5+2+3); +#endif + addbyte(0xb9); /*MOV ECX, 19*/ + addlong(19); + addbyte(0x0f); /*BSR EAX, EDX*/ + addbyte(0xbd); + addbyte(0xc2); + addbyte(0xba); /*MOV EDX, 15*/ + addlong(15); + addbyte(0xf7); /*NOT EBX*/ + addbyte(0xd3); + addbyte(0x29); /*SUB EDX, EAX - EDX = exp*/ + addbyte(0xc2); + addbyte(0x29); /*SUB ECX, EDX*/ + addbyte(0xd1); + addbyte(0xc1); /*SHL EDX, 12*/ + addbyte(0xe2); + addbyte(12); + addbyte(0xd3); /*SHR EBX, CL*/ + addbyte(0xeb); + addbyte(0x81); /*AND EBX, 0xfff - EBX = mant*/ + addbyte(0xe3); + addlong(0xfff); + addbyte(0x67); /*LEA EAX, 1[EDX, EBX]*/ + addbyte(0x8d); + addbyte(0x44); + addbyte(0x13); + addbyte(1); + addbyte(0xbb); /*MOV EBX, 0xffff*/ + addlong(0xffff); + addbyte(0x39); /*CMP EAX, EBX*/ + addbyte(0xd8); + addbyte(0x0f); /*CMOVA EAX, EBX*/ + addbyte(0x47); + addbyte(0xc3); + + if (depth_jump_pos) + *(uint8_t *) &code_block[depth_jump_pos] = (block_pos - depth_jump_pos) - 1; + if (depth_jump_pos) + *(uint8_t *) &code_block[depth_jump_pos2] = (block_pos - depth_jump_pos2) - 1; + + if ((params->fogMode & (FOG_ENABLE | FOG_CONSTANT | FOG_Z | FOG_ALPHA)) == FOG_ENABLE) { + addbyte(0x89); /*MOV state->w_depth[EDI], EAX*/ + addbyte(0x87); + addlong(offsetof(voodoo_state_t, w_depth)); + } + } + if (!(params->fbzMode & FBZ_W_BUFFER)) { + addbyte(0x8b); /*MOV EAX, z*/ + addbyte(0x87); + addlong(offsetof(voodoo_state_t, z)); + addbyte(0xbb); /*MOV EBX, 0xffff*/ + addlong(0xffff); + addbyte(0x31); /*XOR ECX, ECX*/ + addbyte(0xc9); + addbyte(0xc1); /*SAR EAX, 12*/ + addbyte(0xf8); + addbyte(12); + addbyte(0x0f); /*CMOVS EAX, ECX*/ + addbyte(0x48); + addbyte(0xc1); + addbyte(0x39); /*CMP EAX, EBX*/ + addbyte(0xd8); + addbyte(0x0f); /*CMOVA EAX, EBX*/ + addbyte(0x47); + addbyte(0xc3); + } + + if (params->fbzMode & FBZ_DEPTH_BIAS) { + addbyte(0x03); /*ADD EAX, params->zaColor[ESI]*/ + addbyte(0x86); + addlong(offsetof(voodoo_params_t, zaColor)); + addbyte(0x25); /*AND EAX, 0xffff*/ + addlong(0xffff); + } + + addbyte(0x89); /*MOV state->new_depth[EDI], EAX*/ + addbyte(0x87); + addlong(offsetof(voodoo_state_t, new_depth)); + + if ((params->fbzMode & FBZ_DEPTH_ENABLE) && (depthop != DEPTHOP_ALWAYS) && (depthop != DEPTHOP_NEVER)) { + addbyte(0x8b); /*MOV EBX, state->x[EDI]*/ + addbyte(0x9f); + if (params->aux_tiled) + addlong(offsetof(voodoo_state_t, x_tiled)); + else + addlong(offsetof(voodoo_state_t, x)); + addbyte(0x48); /*MOV RCX, aux_mem[RDI]*/ + addbyte(0x8b); + addbyte(0x8f); + addlong(offsetof(voodoo_state_t, aux_mem)); + addbyte(0x0f); /*MOVZX EBX, [ECX+EBX*2]*/ + addbyte(0xb7); + addbyte(0x1c); + addbyte(0x59); + if (params->fbzMode & FBZ_DEPTH_SOURCE) { + addbyte(0x0f); /*MOVZX EAX, zaColor[RSI]*/ + addbyte(0xb7); + addbyte(0x86); + addlong(offsetof(voodoo_params_t, zaColor)); + } + addbyte(0x39); /*CMP EAX, EBX*/ + addbyte(0xd8); + if (depthop == DEPTHOP_LESSTHAN) { + addbyte(0x0f); /*JAE skip*/ + addbyte(0x83); + z_skip_pos = block_pos; + addlong(0); + } else if (depthop == DEPTHOP_EQUAL) { + addbyte(0x0f); /*JNE skip*/ + addbyte(0x85); + z_skip_pos = block_pos; + addlong(0); + } else if (depthop == DEPTHOP_LESSTHANEQUAL) { + addbyte(0x0f); /*JA skip*/ + addbyte(0x87); + z_skip_pos = block_pos; + addlong(0); + } else if (depthop == DEPTHOP_GREATERTHAN) { + addbyte(0x0f); /*JBE skip*/ + addbyte(0x86); + z_skip_pos = block_pos; + addlong(0); + } else if (depthop == DEPTHOP_NOTEQUAL) { + addbyte(0x0f); /*JE skip*/ + addbyte(0x84); + z_skip_pos = block_pos; + addlong(0); + } else if (depthop == DEPTHOP_GREATERTHANEQUAL) { + addbyte(0x0f); /*JB skip*/ + addbyte(0x82); + z_skip_pos = block_pos; + addlong(0); + } else + fatal("Bad depth_op\n"); + } else if ((params->fbzMode & FBZ_DEPTH_ENABLE) && (depthop == DEPTHOP_NEVER)) { + addbyte(0xC3); /*RET*/ + } + + /*XMM0 = colour*/ + /*XMM2 = 0 (for unpacking*/ + + /*EDI = state, ESI = params*/ + + if ((params->textureMode[0] & TEXTUREMODE_LOCAL_MASK) == TEXTUREMODE_LOCAL || !voodoo->dual_tmus) { + /*TMU0 only sampling local colour or only one TMU, only sample TMU0*/ + block_pos = codegen_texture_fetch(code_block, voodoo, params, state, block_pos, 0); + + addbyte(0x66); /*MOVD XMM0, EAX*/ + addbyte(0x0f); + addbyte(0x6e); + addbyte(0xc0); + addbyte(0xc1); /*SHR EAX, 24*/ + addbyte(0xe8); + addbyte(24); + addbyte(0x89); /*MOV state->tex_a[RDI], EAX*/ + addbyte(0x87); + addlong(offsetof(voodoo_state_t, tex_a)); + } else if ((params->textureMode[0] & TEXTUREMODE_MASK) == TEXTUREMODE_PASSTHROUGH) { + /*TMU0 in pass-through mode, only sample TMU1*/ + block_pos = codegen_texture_fetch(code_block, voodoo, params, state, block_pos, 1); + + addbyte(0x66); /*MOVD XMM0, EAX*/ + addbyte(0x0f); + addbyte(0x6e); + addbyte(0xc0); + addbyte(0xc1); /*SHR EAX, 24*/ + addbyte(0xe8); + addbyte(24); + addbyte(0x89); /*MOV state->tex_a[RDI], EAX*/ + addbyte(0x87); + addlong(offsetof(voodoo_state_t, tex_a)); + } else { + block_pos = codegen_texture_fetch(code_block, voodoo, params, state, block_pos, 1); + + addbyte(0x66); /*MOVD XMM3, EAX*/ + addbyte(0x0f); + addbyte(0x6e); + addbyte(0xd8); + if ((params->textureMode[1] & TEXTUREMODE_TRILINEAR) && tc_sub_clocal_1) { + addbyte(0x8b); /*MOV EAX, state->lod*/ + addbyte(0x87); + addlong(offsetof(voodoo_state_t, lod)); + if (!tc_reverse_blend_1) { + addbyte(0xbb); /*MOV EBX, 1*/ + addlong(1); + } else { + addbyte(0x31); /*XOR EBX, EBX*/ + addbyte(0xdb); + } + addbyte(0x83); /*AND EAX, 1*/ + addbyte(0xe0); + addbyte(1); + if (!tca_reverse_blend_1) { + addbyte(0xb9); /*MOV ECX, 1*/ + addlong(1); + } else { addbyte(0x31); /*XOR ECX, ECX*/ addbyte(0xc9); - addbyte(0xc1); /*SAR EAX, 12*/ - addbyte(0xf8); - addbyte(12); - addbyte(0x0f); /*CMOVS EAX, ECX*/ - addbyte(0x48); - addbyte(0xc1); - addbyte(0x39); /*CMP EAX, EBX*/ - addbyte(0xd8); - addbyte(0x0f); /*CMOVA EAX, EBX*/ - addbyte(0x47); - addbyte(0xc3); + } + addbyte(0x31); /*XOR EBX, EAX*/ + addbyte(0xc3); + addbyte(0x31); /*XOR ECX, EAX*/ + addbyte(0xc1); + addbyte(0xc1); /*SHL EBX, 4*/ + addbyte(0xe3); + addbyte(4); + /*EBX = tc_reverse_blend, ECX=tca_reverse_blend*/ } - - if (params->fbzMode & FBZ_DEPTH_BIAS) - { - addbyte(0x03); /*ADD EAX, params->zaColor[ESI]*/ - addbyte(0x86); - addlong(offsetof(voodoo_params_t, zaColor)); - addbyte(0x25); /*AND EAX, 0xffff*/ - addlong(0xffff); - } - - addbyte(0x89); /*MOV state->new_depth[EDI], EAX*/ - addbyte(0x87); - addlong(offsetof(voodoo_state_t, new_depth)); - - if ((params->fbzMode & FBZ_DEPTH_ENABLE) && (depthop != DEPTHOP_ALWAYS) && (depthop != DEPTHOP_NEVER)) - { - addbyte(0x8b); /*MOV EBX, state->x[EDI]*/ - addbyte(0x9f); - if (params->aux_tiled) - addlong(offsetof(voodoo_state_t, x_tiled)); - else - addlong(offsetof(voodoo_state_t, x)); - addbyte(0x48); /*MOV RCX, aux_mem[RDI]*/ - addbyte(0x8b); - addbyte(0x8f); - addlong(offsetof(voodoo_state_t, aux_mem)); - addbyte(0x0f); /*MOVZX EBX, [ECX+EBX*2]*/ - addbyte(0xb7); - addbyte(0x1c); - addbyte(0x59); - if (params->fbzMode & FBZ_DEPTH_SOURCE) - { - addbyte(0x0f); /*MOVZX EAX, zaColor[RSI]*/ - addbyte(0xb7); - addbyte(0x86); - addlong(offsetof(voodoo_params_t, zaColor)); - } - addbyte(0x39); /*CMP EAX, EBX*/ - addbyte(0xd8); - if (depthop == DEPTHOP_LESSTHAN) - { - addbyte(0x0f); /*JAE skip*/ - addbyte(0x83); - z_skip_pos = block_pos; - addlong(0); - } - else if (depthop == DEPTHOP_EQUAL) - { - addbyte(0x0f); /*JNE skip*/ - addbyte(0x85); - z_skip_pos = block_pos; - addlong(0); - } - else if (depthop == DEPTHOP_LESSTHANEQUAL) - { - addbyte(0x0f); /*JA skip*/ - addbyte(0x87); - z_skip_pos = block_pos; - addlong(0); - } - else if (depthop == DEPTHOP_GREATERTHAN) - { - addbyte(0x0f); /*JBE skip*/ - addbyte(0x86); - z_skip_pos = block_pos; - addlong(0); - } - else if (depthop == DEPTHOP_NOTEQUAL) - { - addbyte(0x0f); /*JE skip*/ - addbyte(0x84); - z_skip_pos = block_pos; - addlong(0); - } - else if (depthop == DEPTHOP_GREATERTHANEQUAL) - { - addbyte(0x0f); /*JB skip*/ - addbyte(0x82); - z_skip_pos = block_pos; - addlong(0); - } - else - fatal("Bad depth_op\n"); - } - else if ((params->fbzMode & FBZ_DEPTH_ENABLE) && (depthop == DEPTHOP_NEVER)) - { - addbyte(0xC3); /*RET*/ - } - - /*XMM0 = colour*/ - /*XMM2 = 0 (for unpacking*/ - - /*EDI = state, ESI = params*/ - - if ((params->textureMode[0] & TEXTUREMODE_LOCAL_MASK) == TEXTUREMODE_LOCAL || !voodoo->dual_tmus) - { - /*TMU0 only sampling local colour or only one TMU, only sample TMU0*/ - block_pos = codegen_texture_fetch(code_block, voodoo, params, state, block_pos, 0); - - addbyte(0x66); /*MOVD XMM0, EAX*/ - addbyte(0x0f); - addbyte(0x6e); - addbyte(0xc0); - addbyte(0xc1); /*SHR EAX, 24*/ - addbyte(0xe8); - addbyte(24); - addbyte(0x89); /*MOV state->tex_a[RDI], EAX*/ - addbyte(0x87); - addlong(offsetof(voodoo_state_t, tex_a)); - } - else if ((params->textureMode[0] & TEXTUREMODE_MASK) == TEXTUREMODE_PASSTHROUGH) - { - /*TMU0 in pass-through mode, only sample TMU1*/ - block_pos = codegen_texture_fetch(code_block, voodoo, params, state, block_pos, 1); - - addbyte(0x66); /*MOVD XMM0, EAX*/ - addbyte(0x0f); - addbyte(0x6e); - addbyte(0xc0); - addbyte(0xc1); /*SHR EAX, 24*/ - addbyte(0xe8); - addbyte(24); - addbyte(0x89); /*MOV state->tex_a[RDI], EAX*/ - addbyte(0x87); - addlong(offsetof(voodoo_state_t, tex_a)); - } - else - { - block_pos = codegen_texture_fetch(code_block, voodoo, params, state, block_pos, 1); - - addbyte(0x66); /*MOVD XMM3, EAX*/ - addbyte(0x0f); - addbyte(0x6e); - addbyte(0xd8); - if ((params->textureMode[1] & TEXTUREMODE_TRILINEAR) && tc_sub_clocal_1) - { - addbyte(0x8b); /*MOV EAX, state->lod*/ - addbyte(0x87); - addlong(offsetof(voodoo_state_t, lod)); - if (!tc_reverse_blend_1) - { - addbyte(0xbb); /*MOV EBX, 1*/ - addlong(1); - } - else - { - addbyte(0x31); /*XOR EBX, EBX*/ - addbyte(0xdb); - } - addbyte(0x83); /*AND EAX, 1*/ - addbyte(0xe0); - addbyte(1); - if (!tca_reverse_blend_1) - { - addbyte(0xb9); /*MOV ECX, 1*/ - addlong(1); - } - else - { - addbyte(0x31); /*XOR ECX, ECX*/ - addbyte(0xc9); - } - addbyte(0x31); /*XOR EBX, EAX*/ - addbyte(0xc3); - addbyte(0x31); /*XOR ECX, EAX*/ - addbyte(0xc1); - addbyte(0xc1); /*SHL EBX, 4*/ - addbyte(0xe3); - addbyte(4); - /*EBX = tc_reverse_blend, ECX=tca_reverse_blend*/ - } - addbyte(0x66); /*PUNPCKLBW XMM3, XMM2*/ - addbyte(0x0f); - addbyte(0x60); - addbyte(0xda); - if (tc_sub_clocal_1) - { - switch (tc_mselect_1) - { - case TC_MSELECT_ZERO: - addbyte(0x66); /*PXOR XMM0, XMM0*/ - addbyte(0x0f); - addbyte(0xef); - addbyte(0xc0); - break; - case TC_MSELECT_CLOCAL: - addbyte(0xf3); /*MOVQ XMM0, XMM3*/ - addbyte(0x0f); - addbyte(0x7e); - addbyte(0xc3); - break; - case TC_MSELECT_AOTHER: - addbyte(0x66); /*PXOR XMM0, XMM0*/ - addbyte(0x0f); - addbyte(0xef); - addbyte(0xc0); - break; - case TC_MSELECT_ALOCAL: - addbyte(0xf2); /*PSHUFLW XMM0, XMM3, 0xff*/ - addbyte(0x0f); - addbyte(0x70); - addbyte(0xc3); - addbyte(0xff); - break; - case TC_MSELECT_DETAIL: - addbyte(0xb8); /*MOV EAX, params->detail_bias[1]*/ - addlong(params->detail_bias[1]); - addbyte(0x2b); /*SUB EAX, state->lod*/ - addbyte(0x87); - addlong(offsetof(voodoo_state_t, lod)); - addbyte(0xba); /*MOV EDX, params->detail_max[1]*/ - addlong(params->detail_max[1]); - addbyte(0xc1); /*SHL EAX, params->detail_scale[1]*/ - addbyte(0xe0); - addbyte(params->detail_scale[1]); - addbyte(0x39); /*CMP EAX, EDX*/ - addbyte(0xd0); - addbyte(0x0f); /*CMOVNL EAX, EDX*/ - addbyte(0x4d); - addbyte(0xc2); - addbyte(0x66); /*MOVD XMM0, EAX*/ - addbyte(0x0f); - addbyte(0x6e); - addbyte(0xc0); - addbyte(0xf2); /*PSHUFLW XMM0, XMM0, 0*/ - addbyte(0x0f); - addbyte(0x70); - addbyte(0xc0); - addbyte(0); - break; - case TC_MSELECT_LOD_FRAC: - addbyte(0x66); /*MOVD XMM0, state->lod_frac[1]*/ - addbyte(0x0f); - addbyte(0x6e); - addbyte(0x87); - addlong(offsetof(voodoo_state_t, lod_frac[1])); - addbyte(0xf2); /*PSHUFLW XMM0, XMM0, 0*/ - addbyte(0x0f); - addbyte(0x70); - addbyte(0xc0); - addbyte(0); - break; - } - if (params->textureMode[1] & TEXTUREMODE_TRILINEAR) - { - addbyte(0x66); /*PXOR XMM0, R12(xmm_00_ff_w)[EBX]*/ - addbyte(0x41); - addbyte(0x0f); - addbyte(0xef); - addbyte(0x04); - addbyte(0x1c); - } - else if (!tc_reverse_blend_1) - { - addbyte(0x66); /*PXOR XMM0, XMM9(xmm_ff_w)*/ - addbyte(0x41); - addbyte(0x0f); - addbyte(0xef); - addbyte(0xc1); - } - addbyte(0x66); /*PADDW XMM0, XMM8(xmm_01_w)*/ - addbyte(0x41); - addbyte(0x0f); - addbyte(0xfd); - addbyte(0xc0); - addbyte(0xf3); /*MOVQ XMM1, XMM2*/ - addbyte(0x0f); - addbyte(0x7e); - addbyte(0xca); - addbyte(0xf3); /*MOVQ XMM5, XMM0*/ - addbyte(0x0f); - addbyte(0x7e); - addbyte(0xe8); - addbyte(0x66); /*PMULLW XMM0, XMM3*/ - addbyte(0x0f); - addbyte(0xd5); - addbyte(0xc3); - addbyte(0x66); /*PMULHW XMM5, XMM3*/ - addbyte(0x0f); - addbyte(0xe5); - addbyte(0xeb); - addbyte(0x66); /*PUNPCKLWD XMM0, XMM5*/ - addbyte(0x0f); - addbyte(0x61); - addbyte(0xc5); - addbyte(0x66); /*PSRAD XMM0, 8*/ - addbyte(0x0f); - addbyte(0x72); - addbyte(0xe0); - addbyte(8); - addbyte(0x66); /*PACKSSDW XMM0, XMM0*/ - addbyte(0x0f); - addbyte(0x6b); - addbyte(0xc0); - addbyte(0x66); /*PSUBW XMM1, XMM0*/ - addbyte(0x0f); - addbyte(0xf9); - addbyte(0xc8); - if (tc_add_clocal_1) - { - addbyte(0x66); /*PADDW XMM1, XMM3*/ - addbyte(0x0f); - addbyte(0xfd); - addbyte(0xcb); - } - else if (tc_add_alocal_1) - { - addbyte(0xf2); /*PSHUFLW XMM0, XMM3, 0xff*/ - addbyte(0x0f); - addbyte(0x70); - addbyte(0xc3); - addbyte(0xff); - addbyte(0x66); /*PADDW XMM1, XMM0*/ - addbyte(0x0f); - addbyte(0xfd); - addbyte(0xc8); - } - addbyte(0x66); /*PACKUSWB XMM3, XMM1*/ - addbyte(0x0f); - addbyte(0x67); - addbyte(0xd9); - if (tca_sub_clocal_1) - { - addbyte(0x66); /*MOVD EBX, XMM3*/ - addbyte(0x0f); - addbyte(0x7e); - addbyte(0xdb); - } - addbyte(0x66); /*PUNPCKLBW XMM3, XMM2*/ - addbyte(0x0f); - addbyte(0x60); - addbyte(0xda); - } - - if (tca_sub_clocal_1) - { - addbyte(0xc1); /*SHR EBX, 24*/ - addbyte(0xeb); - addbyte(24); - switch (tca_mselect_1) - { - case TCA_MSELECT_ZERO: - addbyte(0x31); /*XOR EAX, EAX*/ - addbyte(0xc0); - break; - case TCA_MSELECT_CLOCAL: - addbyte(0x89); /*MOV EAX, EBX*/ - addbyte(0xd8); - break; - case TCA_MSELECT_AOTHER: - addbyte(0x31); /*XOR EAX, EAX*/ - addbyte(0xc0); - break; - case TCA_MSELECT_ALOCAL: - addbyte(0x89); /*MOV EAX, EBX*/ - addbyte(0xd8); - break; - case TCA_MSELECT_DETAIL: - addbyte(0xb8); /*MOV EAX, params->detail_bias[1]*/ - addlong(params->detail_bias[1]); - addbyte(0x2b); /*SUB EAX, state->lod*/ - addbyte(0x87); - addlong(offsetof(voodoo_state_t, lod)); - addbyte(0xba); /*MOV EDX, params->detail_max[1]*/ - addlong(params->detail_max[1]); - addbyte(0xc1); /*SHL EAX, params->detail_scale[1]*/ - addbyte(0xe0); - addbyte(params->detail_scale[1]); - addbyte(0x39); /*CMP EAX, EDX*/ - addbyte(0xd0); - addbyte(0x0f); /*CMOVNL EAX, EDX*/ - addbyte(0x4d); - addbyte(0xc2); - break; - case TCA_MSELECT_LOD_FRAC: - addbyte(0x8b); /*MOV EAX, state->lod_frac[1]*/ - addbyte(0x87); - addlong(offsetof(voodoo_state_t, lod_frac[1])); - break; - } - if (params->textureMode[1] & TEXTUREMODE_TRILINEAR) - { - addbyte(0x41); /*XOR EAX, R13(i_00_ff_w)[ECX*4]*/ - addbyte(0x33); - addbyte(0x44); - addbyte(0x8d); - addbyte(0); - } - else if (!tc_reverse_blend_1) - { - addbyte(0x35); /*XOR EAX, 0xff*/ - addlong(0xff); - } - addbyte(0x8e); /*ADD EAX, 1*/ - addbyte(0xc0); - addbyte(1); - addbyte(0x0f); /*IMUL EAX, EBX*/ - addbyte(0xaf); - addbyte(0xc3); - addbyte(0xb9); /*MOV ECX, 0xff*/ - addlong(0xff); - addbyte(0xf7); /*NEG EAX*/ - addbyte(0xd8); - addbyte(0xc1); /*SAR EAX, 8*/ - addbyte(0xf8); - addbyte(8); - if (tca_add_clocal_1 || tca_add_alocal_1) - { - addbyte(0x01); /*ADD EAX, EBX*/ - addbyte(0xd8); - } - addbyte(0x39); /*CMP ECX, EAX*/ - addbyte(0xc1); - addbyte(0x0f); /*CMOVA ECX, EAX*/ - addbyte(0x47); - addbyte(0xc8); - addbyte(0x66); /*PINSRW 3, XMM3, XMM0*/ - addbyte(0x0f); - addbyte(0xc4); - addbyte(0xd8); - addbyte(3); - } - - block_pos = codegen_texture_fetch(code_block, voodoo, params, state, block_pos, 0); - - addbyte(0x66); /*MOVD XMM0, EAX*/ - addbyte(0x0f); - addbyte(0x6e); - addbyte(0xc0); - addbyte(0x66); /*MOVD XMM7, EAX*/ - addbyte(0x0f); - addbyte(0x6e); - addbyte(0xf8); - - if (params->textureMode[0] & TEXTUREMODE_TRILINEAR) - { - addbyte(0x8b); /*MOV EAX, state->lod*/ - addbyte(0x87); - addlong(offsetof(voodoo_state_t, lod)); - if (!tc_reverse_blend) - { - addbyte(0xbb); /*MOV EBX, 1*/ - addlong(1); - } - else - { - addbyte(0x31); /*XOR EBX, EBX*/ - addbyte(0xdb); - } - addbyte(0x83); /*AND EAX, 1*/ - addbyte(0xe0); - addbyte(1); - if (!tca_reverse_blend) - { - addbyte(0xb9); /*MOV ECX, 1*/ - addlong(1); - } - else - { - addbyte(0x31); /*XOR ECX, ECX*/ - addbyte(0xc9); - } - addbyte(0x31); /*XOR EBX, EAX*/ - addbyte(0xc3); - addbyte(0x31); /*XOR ECX, EAX*/ - addbyte(0xc1); - addbyte(0xc1); /*SHL EBX, 4*/ - addbyte(0xe3); - addbyte(4); - /*EBX = tc_reverse_blend, ECX=tca_reverse_blend*/ - } - - /*XMM0 = TMU0 output, XMM3 = TMU1 output*/ - - addbyte(0x66); /*PUNPCKLBW XMM0, XMM2*/ - addbyte(0x0f); - addbyte(0x60); - addbyte(0xc2); - if (tc_zero_other) - { - addbyte(0x66); /*PXOR XMM1, XMM1*/ - addbyte(0x0f); - addbyte(0xef); - addbyte(0xc9); - } - else - { - addbyte(0xf3); /*MOV XMM1, XMM3*/ - addbyte(0x0f); - addbyte(0x7e); - addbyte(0xcb); - } - if (tc_sub_clocal) - { - addbyte(0x66); /*PSUBW XMM1, XMM0*/ - addbyte(0x0f); - addbyte(0xf9); - addbyte(0xc8); - } - - switch (tc_mselect) - { - case TC_MSELECT_ZERO: - addbyte(0x66); /*PXOR XMM4, XMM4*/ - addbyte(0x0f); - addbyte(0xef); - addbyte(0xe4); - break; - case TC_MSELECT_CLOCAL: - addbyte(0xf3); /*MOV XMM4, XMM0*/ - addbyte(0x0f); - addbyte(0x7e); - addbyte(0xe0); - break; - case TC_MSELECT_AOTHER: - addbyte(0xf2); /*PSHUFLW XMM4, XMM3, 3, 3, 3, 3*/ - addbyte(0x0f); - addbyte(0x70); - addbyte(0xe3); - addbyte(0xff); - break; - case TC_MSELECT_ALOCAL: - addbyte(0xf2); /*PSHUFLW XMM4, XMM0, 3, 3, 3, 3*/ - addbyte(0x0f); - addbyte(0x70); - addbyte(0xe0); - addbyte(0xff); - break; - case TC_MSELECT_DETAIL: - addbyte(0xb8); /*MOV EAX, params->detail_bias[0]*/ - addlong(params->detail_bias[0]); - addbyte(0x2b); /*SUB EAX, state->lod*/ - addbyte(0x87); - addlong(offsetof(voodoo_state_t, lod)); - addbyte(0xba); /*MOV EDX, params->detail_max[0]*/ - addlong(params->detail_max[0]); - addbyte(0xc1); /*SHL EAX, params->detail_scale[0]*/ - addbyte(0xe0); - addbyte(params->detail_scale[0]); - addbyte(0x39); /*CMP EAX, EDX*/ - addbyte(0xd0); - addbyte(0x0f); /*CMOVNL EAX, EDX*/ - addbyte(0x4d); - addbyte(0xc2); - addbyte(0x66); /*MOVD XMM4, EAX*/ - addbyte(0x0f); - addbyte(0x6e); - addbyte(0xe0); - addbyte(0xf2); /*PSHUFLW XMM4, XMM4, 0*/ - addbyte(0x0f); - addbyte(0x70); - addbyte(0xe4); - addbyte(0); - break; - case TC_MSELECT_LOD_FRAC: - addbyte(0x66); /*MOVD XMM0, state->lod_frac[0]*/ - addbyte(0x0f); - addbyte(0x6e); - addbyte(0xa7); - addlong(offsetof(voodoo_state_t, lod_frac[0])); - addbyte(0xf2); /*PSHUFLW XMM0, XMM0, 0*/ - addbyte(0x0f); - addbyte(0x70); - addbyte(0xe4); - addbyte(0); - break; - } - if (params->textureMode[0] & TEXTUREMODE_TRILINEAR) - { - addbyte(0x66); /*PXOR XMM4, R12(xmm_00_ff_w)[EBX]*/ - addbyte(0x41); - addbyte(0x0f); - addbyte(0xef); - addbyte(0x24); - addbyte(0x1c); - } - else if (!tc_reverse_blend) - { - addbyte(0x66); /*PXOR XMM4, XMM9(xmm_ff_w)*/ - addbyte(0x41); - addbyte(0x0f); - addbyte(0xef); - addbyte(0xe1); - } - addbyte(0x66); /*PADDW XMM4, XMM8(xmm_01_w)*/ + addbyte(0x66); /*PUNPCKLBW XMM3, XMM2*/ + addbyte(0x0f); + addbyte(0x60); + addbyte(0xda); + if (tc_sub_clocal_1) { + switch (tc_mselect_1) { + case TC_MSELECT_ZERO: + addbyte(0x66); /*PXOR XMM0, XMM0*/ + addbyte(0x0f); + addbyte(0xef); + addbyte(0xc0); + break; + case TC_MSELECT_CLOCAL: + addbyte(0xf3); /*MOVQ XMM0, XMM3*/ + addbyte(0x0f); + addbyte(0x7e); + addbyte(0xc3); + break; + case TC_MSELECT_AOTHER: + addbyte(0x66); /*PXOR XMM0, XMM0*/ + addbyte(0x0f); + addbyte(0xef); + addbyte(0xc0); + break; + case TC_MSELECT_ALOCAL: + addbyte(0xf2); /*PSHUFLW XMM0, XMM3, 0xff*/ + addbyte(0x0f); + addbyte(0x70); + addbyte(0xc3); + addbyte(0xff); + break; + case TC_MSELECT_DETAIL: + addbyte(0xb8); /*MOV EAX, params->detail_bias[1]*/ + addlong(params->detail_bias[1]); + addbyte(0x2b); /*SUB EAX, state->lod*/ + addbyte(0x87); + addlong(offsetof(voodoo_state_t, lod)); + addbyte(0xba); /*MOV EDX, params->detail_max[1]*/ + addlong(params->detail_max[1]); + addbyte(0xc1); /*SHL EAX, params->detail_scale[1]*/ + addbyte(0xe0); + addbyte(params->detail_scale[1]); + addbyte(0x39); /*CMP EAX, EDX*/ + addbyte(0xd0); + addbyte(0x0f); /*CMOVNL EAX, EDX*/ + addbyte(0x4d); + addbyte(0xc2); + addbyte(0x66); /*MOVD XMM0, EAX*/ + addbyte(0x0f); + addbyte(0x6e); + addbyte(0xc0); + addbyte(0xf2); /*PSHUFLW XMM0, XMM0, 0*/ + addbyte(0x0f); + addbyte(0x70); + addbyte(0xc0); + addbyte(0); + break; + case TC_MSELECT_LOD_FRAC: + addbyte(0x66); /*MOVD XMM0, state->lod_frac[1]*/ + addbyte(0x0f); + addbyte(0x6e); + addbyte(0x87); + addlong(offsetof(voodoo_state_t, lod_frac[1])); + addbyte(0xf2); /*PSHUFLW XMM0, XMM0, 0*/ + addbyte(0x0f); + addbyte(0x70); + addbyte(0xc0); + addbyte(0); + break; + } + if (params->textureMode[1] & TEXTUREMODE_TRILINEAR) { + addbyte(0x66); /*PXOR XMM0, R12(xmm_00_ff_w)[EBX]*/ addbyte(0x41); addbyte(0x0f); + addbyte(0xef); + addbyte(0x04); + addbyte(0x1c); + } else if (!tc_reverse_blend_1) { + addbyte(0x66); /*PXOR XMM0, XMM9(xmm_ff_w)*/ + addbyte(0x41); + addbyte(0x0f); + addbyte(0xef); + addbyte(0xc1); + } + addbyte(0x66); /*PADDW XMM0, XMM8(xmm_01_w)*/ + addbyte(0x41); + addbyte(0x0f); + addbyte(0xfd); + addbyte(0xc0); + addbyte(0xf3); /*MOVQ XMM1, XMM2*/ + addbyte(0x0f); + addbyte(0x7e); + addbyte(0xca); + addbyte(0xf3); /*MOVQ XMM5, XMM0*/ + addbyte(0x0f); + addbyte(0x7e); + addbyte(0xe8); + addbyte(0x66); /*PMULLW XMM0, XMM3*/ + addbyte(0x0f); + addbyte(0xd5); + addbyte(0xc3); + addbyte(0x66); /*PMULHW XMM5, XMM3*/ + addbyte(0x0f); + addbyte(0xe5); + addbyte(0xeb); + addbyte(0x66); /*PUNPCKLWD XMM0, XMM5*/ + addbyte(0x0f); + addbyte(0x61); + addbyte(0xc5); + addbyte(0x66); /*PSRAD XMM0, 8*/ + addbyte(0x0f); + addbyte(0x72); + addbyte(0xe0); + addbyte(8); + addbyte(0x66); /*PACKSSDW XMM0, XMM0*/ + addbyte(0x0f); + addbyte(0x6b); + addbyte(0xc0); + addbyte(0x66); /*PSUBW XMM1, XMM0*/ + addbyte(0x0f); + addbyte(0xf9); + addbyte(0xc8); + if (tc_add_clocal_1) { + addbyte(0x66); /*PADDW XMM1, XMM3*/ + addbyte(0x0f); addbyte(0xfd); - addbyte(0xe0); - addbyte(0xf3); /*MOVQ XMM5, XMM1*/ + addbyte(0xcb); + } else if (tc_add_alocal_1) { + addbyte(0xf2); /*PSHUFLW XMM0, XMM3, 0xff*/ + addbyte(0x0f); + addbyte(0x70); + addbyte(0xc3); + addbyte(0xff); + addbyte(0x66); /*PADDW XMM1, XMM0*/ + addbyte(0x0f); + addbyte(0xfd); + addbyte(0xc8); + } + addbyte(0x66); /*PACKUSWB XMM3, XMM1*/ + addbyte(0x0f); + addbyte(0x67); + addbyte(0xd9); + if (tca_sub_clocal_1) { + addbyte(0x66); /*MOVD EBX, XMM3*/ addbyte(0x0f); addbyte(0x7e); - addbyte(0xe9); - addbyte(0x66); /*PMULLW XMM1, XMM4*/ - addbyte(0x0f); - addbyte(0xd5); - addbyte(0xcc); + addbyte(0xdb); + } + addbyte(0x66); /*PUNPCKLBW XMM3, XMM2*/ + addbyte(0x0f); + addbyte(0x60); + addbyte(0xda); + } - if (tca_sub_clocal) - { - addbyte(0x66); /*MOV EBX, XMM7*/ - addbyte(0x0f); - addbyte(0x7e); - addbyte(0xfb); - } + if (tca_sub_clocal_1) { + addbyte(0xc1); /*SHR EBX, 24*/ + addbyte(0xeb); + addbyte(24); + switch (tca_mselect_1) { + case TCA_MSELECT_ZERO: + addbyte(0x31); /*XOR EAX, EAX*/ + addbyte(0xc0); + break; + case TCA_MSELECT_CLOCAL: + addbyte(0x89); /*MOV EAX, EBX*/ + addbyte(0xd8); + break; + case TCA_MSELECT_AOTHER: + addbyte(0x31); /*XOR EAX, EAX*/ + addbyte(0xc0); + break; + case TCA_MSELECT_ALOCAL: + addbyte(0x89); /*MOV EAX, EBX*/ + addbyte(0xd8); + break; + case TCA_MSELECT_DETAIL: + addbyte(0xb8); /*MOV EAX, params->detail_bias[1]*/ + addlong(params->detail_bias[1]); + addbyte(0x2b); /*SUB EAX, state->lod*/ + addbyte(0x87); + addlong(offsetof(voodoo_state_t, lod)); + addbyte(0xba); /*MOV EDX, params->detail_max[1]*/ + addlong(params->detail_max[1]); + addbyte(0xc1); /*SHL EAX, params->detail_scale[1]*/ + addbyte(0xe0); + addbyte(params->detail_scale[1]); + addbyte(0x39); /*CMP EAX, EDX*/ + addbyte(0xd0); + addbyte(0x0f); /*CMOVNL EAX, EDX*/ + addbyte(0x4d); + addbyte(0xc2); + break; + case TCA_MSELECT_LOD_FRAC: + addbyte(0x8b); /*MOV EAX, state->lod_frac[1]*/ + addbyte(0x87); + addlong(offsetof(voodoo_state_t, lod_frac[1])); + break; + } + if (params->textureMode[1] & TEXTUREMODE_TRILINEAR) { + addbyte(0x41); /*XOR EAX, R13(i_00_ff_w)[ECX*4]*/ + addbyte(0x33); + addbyte(0x44); + addbyte(0x8d); + addbyte(0); + } else if (!tc_reverse_blend_1) { + addbyte(0x35); /*XOR EAX, 0xff*/ + addlong(0xff); + } + addbyte(0x8e); /*ADD EAX, 1*/ + addbyte(0xc0); + addbyte(1); + addbyte(0x0f); /*IMUL EAX, EBX*/ + addbyte(0xaf); + addbyte(0xc3); + addbyte(0xb9); /*MOV ECX, 0xff*/ + addlong(0xff); + addbyte(0xf7); /*NEG EAX*/ + addbyte(0xd8); + addbyte(0xc1); /*SAR EAX, 8*/ + addbyte(0xf8); + addbyte(8); + if (tca_add_clocal_1 || tca_add_alocal_1) { + addbyte(0x01); /*ADD EAX, EBX*/ + addbyte(0xd8); + } + addbyte(0x39); /*CMP ECX, EAX*/ + addbyte(0xc1); + addbyte(0x0f); /*CMOVA ECX, EAX*/ + addbyte(0x47); + addbyte(0xc8); + addbyte(0x66); /*PINSRW 3, XMM3, XMM0*/ + addbyte(0x0f); + addbyte(0xc4); + addbyte(0xd8); + addbyte(3); + } - addbyte(0x66); /*PMULHW XMM5, XMM4*/ + block_pos = codegen_texture_fetch(code_block, voodoo, params, state, block_pos, 0); + + addbyte(0x66); /*MOVD XMM0, EAX*/ + addbyte(0x0f); + addbyte(0x6e); + addbyte(0xc0); + addbyte(0x66); /*MOVD XMM7, EAX*/ + addbyte(0x0f); + addbyte(0x6e); + addbyte(0xf8); + + if (params->textureMode[0] & TEXTUREMODE_TRILINEAR) { + addbyte(0x8b); /*MOV EAX, state->lod*/ + addbyte(0x87); + addlong(offsetof(voodoo_state_t, lod)); + if (!tc_reverse_blend) { + addbyte(0xbb); /*MOV EBX, 1*/ + addlong(1); + } else { + addbyte(0x31); /*XOR EBX, EBX*/ + addbyte(0xdb); + } + addbyte(0x83); /*AND EAX, 1*/ + addbyte(0xe0); + addbyte(1); + if (!tca_reverse_blend) { + addbyte(0xb9); /*MOV ECX, 1*/ + addlong(1); + } else { + addbyte(0x31); /*XOR ECX, ECX*/ + addbyte(0xc9); + } + addbyte(0x31); /*XOR EBX, EAX*/ + addbyte(0xc3); + addbyte(0x31); /*XOR ECX, EAX*/ + addbyte(0xc1); + addbyte(0xc1); /*SHL EBX, 4*/ + addbyte(0xe3); + addbyte(4); + /*EBX = tc_reverse_blend, ECX=tca_reverse_blend*/ + } + + /*XMM0 = TMU0 output, XMM3 = TMU1 output*/ + + addbyte(0x66); /*PUNPCKLBW XMM0, XMM2*/ + addbyte(0x0f); + addbyte(0x60); + addbyte(0xc2); + if (tc_zero_other) { + addbyte(0x66); /*PXOR XMM1, XMM1*/ + addbyte(0x0f); + addbyte(0xef); + addbyte(0xc9); + } else { + addbyte(0xf3); /*MOV XMM1, XMM3*/ + addbyte(0x0f); + addbyte(0x7e); + addbyte(0xcb); + } + if (tc_sub_clocal) { + addbyte(0x66); /*PSUBW XMM1, XMM0*/ + addbyte(0x0f); + addbyte(0xf9); + addbyte(0xc8); + } + + switch (tc_mselect) { + case TC_MSELECT_ZERO: + addbyte(0x66); /*PXOR XMM4, XMM4*/ addbyte(0x0f); - addbyte(0xe5); - addbyte(0xec); - addbyte(0x66); /*PUNPCKLWD XMM1, XMM5*/ + addbyte(0xef); + addbyte(0xe4); + break; + case TC_MSELECT_CLOCAL: + addbyte(0xf3); /*MOV XMM4, XMM0*/ addbyte(0x0f); - addbyte(0x61); - addbyte(0xcd); - addbyte(0x66); /*PSRAD XMM1, 8*/ + addbyte(0x7e); + addbyte(0xe0); + break; + case TC_MSELECT_AOTHER: + addbyte(0xf2); /*PSHUFLW XMM4, XMM3, 3, 3, 3, 3*/ + addbyte(0x0f); + addbyte(0x70); + addbyte(0xe3); + addbyte(0xff); + break; + case TC_MSELECT_ALOCAL: + addbyte(0xf2); /*PSHUFLW XMM4, XMM0, 3, 3, 3, 3*/ + addbyte(0x0f); + addbyte(0x70); + addbyte(0xe0); + addbyte(0xff); + break; + case TC_MSELECT_DETAIL: + addbyte(0xb8); /*MOV EAX, params->detail_bias[0]*/ + addlong(params->detail_bias[0]); + addbyte(0x2b); /*SUB EAX, state->lod*/ + addbyte(0x87); + addlong(offsetof(voodoo_state_t, lod)); + addbyte(0xba); /*MOV EDX, params->detail_max[0]*/ + addlong(params->detail_max[0]); + addbyte(0xc1); /*SHL EAX, params->detail_scale[0]*/ + addbyte(0xe0); + addbyte(params->detail_scale[0]); + addbyte(0x39); /*CMP EAX, EDX*/ + addbyte(0xd0); + addbyte(0x0f); /*CMOVNL EAX, EDX*/ + addbyte(0x4d); + addbyte(0xc2); + addbyte(0x66); /*MOVD XMM4, EAX*/ + addbyte(0x0f); + addbyte(0x6e); + addbyte(0xe0); + addbyte(0xf2); /*PSHUFLW XMM4, XMM4, 0*/ + addbyte(0x0f); + addbyte(0x70); + addbyte(0xe4); + addbyte(0); + break; + case TC_MSELECT_LOD_FRAC: + addbyte(0x66); /*MOVD XMM0, state->lod_frac[0]*/ + addbyte(0x0f); + addbyte(0x6e); + addbyte(0xa7); + addlong(offsetof(voodoo_state_t, lod_frac[0])); + addbyte(0xf2); /*PSHUFLW XMM0, XMM0, 0*/ + addbyte(0x0f); + addbyte(0x70); + addbyte(0xe4); + addbyte(0); + break; + } + if (params->textureMode[0] & TEXTUREMODE_TRILINEAR) { + addbyte(0x66); /*PXOR XMM4, R12(xmm_00_ff_w)[EBX]*/ + addbyte(0x41); + addbyte(0x0f); + addbyte(0xef); + addbyte(0x24); + addbyte(0x1c); + } else if (!tc_reverse_blend) { + addbyte(0x66); /*PXOR XMM4, XMM9(xmm_ff_w)*/ + addbyte(0x41); + addbyte(0x0f); + addbyte(0xef); + addbyte(0xe1); + } + addbyte(0x66); /*PADDW XMM4, XMM8(xmm_01_w)*/ + addbyte(0x41); + addbyte(0x0f); + addbyte(0xfd); + addbyte(0xe0); + addbyte(0xf3); /*MOVQ XMM5, XMM1*/ + addbyte(0x0f); + addbyte(0x7e); + addbyte(0xe9); + addbyte(0x66); /*PMULLW XMM1, XMM4*/ + addbyte(0x0f); + addbyte(0xd5); + addbyte(0xcc); + + if (tca_sub_clocal) { + addbyte(0x66); /*MOV EBX, XMM7*/ + addbyte(0x0f); + addbyte(0x7e); + addbyte(0xfb); + } + + addbyte(0x66); /*PMULHW XMM5, XMM4*/ + addbyte(0x0f); + addbyte(0xe5); + addbyte(0xec); + addbyte(0x66); /*PUNPCKLWD XMM1, XMM5*/ + addbyte(0x0f); + addbyte(0x61); + addbyte(0xcd); + addbyte(0x66); /*PSRAD XMM1, 8*/ + addbyte(0x0f); + addbyte(0x72); + addbyte(0xe1); + addbyte(8); + addbyte(0x66); /*PACKSSDW XMM1, XMM1*/ + addbyte(0x0f); + addbyte(0x6b); + addbyte(0xc9); + + if (tca_sub_clocal) { + addbyte(0xc1); /*SHR EBX, 24*/ + addbyte(0xeb); + addbyte(24); + } + + if (tc_add_clocal) { + addbyte(0x66); /*PADDW XMM1, XMM0*/ + addbyte(0x0f); + addbyte(0xfd); + addbyte(0xc8); + } else if (tc_add_alocal) { + addbyte(0xf2); /*PSHUFLW XMM4, XMM0, 3, 3, 3, 3*/ + addbyte(0x0f); + addbyte(0x70); + addbyte(0xe0); + addbyte(0xff); + addbyte(0x66); /*PADDW XMM1, XMM4*/ + addbyte(0x0f); + addbyte(0xfc); + addbyte(0xcc); + } + if (tc_invert_output) { + addbyte(0x66); /*PXOR XMM1, XMM9(xmm_ff_w)*/ + addbyte(0x41); + addbyte(0x0f); + addbyte(0xef); + addbyte(0xc9); + } + + addbyte(0x66); /*PACKUSWB XMM0, XMM0*/ + addbyte(0x0f); + addbyte(0x67); + addbyte(0xc0); + addbyte(0x66); /*PACKUSWB XMM3, XMM3*/ + addbyte(0x0f); + addbyte(0x67); + addbyte(0xdb); + addbyte(0x66); /*PACKUSWB XMM1, XMM1*/ + addbyte(0x0f); + addbyte(0x67); + addbyte(0xc9); + + if (tca_zero_other) { + addbyte(0x31); /*XOR EAX, EAX*/ + addbyte(0xc0); + } else { + addbyte(0x66); /*MOV EAX, XMM3*/ + addbyte(0x0f); + addbyte(0x7e); + addbyte(0xd8); + addbyte(0xc1); /*SHR EAX, 24*/ + addbyte(0xe8); + addbyte(24); + } + if (tca_sub_clocal) { + addbyte(0x29); /*SUB EAX, EBX*/ + addbyte(0xd8); + } + switch (tca_mselect) { + case TCA_MSELECT_ZERO: + addbyte(0x31); /*XOR EBX, EBX*/ + addbyte(0xdb); + break; + case TCA_MSELECT_CLOCAL: + addbyte(0x66); /*MOV EBX, XMM7*/ + addbyte(0x0f); + addbyte(0x7e); + addbyte(0xfb); + addbyte(0xc1); /*SHR EBX, 24*/ + addbyte(0xeb); + addbyte(24); + break; + case TCA_MSELECT_AOTHER: + addbyte(0x66); /*MOV EBX, XMM3*/ + addbyte(0x0f); + addbyte(0x7e); + addbyte(0xdb); + addbyte(0xc1); /*SHR EBX, 24*/ + addbyte(0xeb); + addbyte(24); + break; + case TCA_MSELECT_ALOCAL: + addbyte(0x66); /*MOV EBX, XMM7*/ + addbyte(0x0f); + addbyte(0x7e); + addbyte(0xfb); + addbyte(0xc1); /*SHR EBX, 24*/ + addbyte(0xeb); + addbyte(24); + break; + case TCA_MSELECT_DETAIL: + addbyte(0xbb); /*MOV EBX, params->detail_bias[1]*/ + addlong(params->detail_bias[1]); + addbyte(0x2b); /*SUB EBX, state->lod*/ + addbyte(0x9f); + addlong(offsetof(voodoo_state_t, lod)); + addbyte(0xba); /*MOV EDX, params->detail_max[1]*/ + addlong(params->detail_max[1]); + addbyte(0xc1); /*SHL EBX, params->detail_scale[1]*/ + addbyte(0xe3); + addbyte(params->detail_scale[1]); + addbyte(0x39); /*CMP EBX, EDX*/ + addbyte(0xd3); + addbyte(0x0f); /*CMOVNL EBX, EDX*/ + addbyte(0x4d); + addbyte(0xda); + break; + case TCA_MSELECT_LOD_FRAC: + addbyte(0x8b); /*MOV EBX, state->lod_frac[0]*/ + addbyte(0x9f); + addlong(offsetof(voodoo_state_t, lod_frac[0])); + break; + } + if (params->textureMode[0] & TEXTUREMODE_TRILINEAR) { + addbyte(0x41); /*XOR EBX, R13(i_00_ff_w)[ECX*4]*/ + addbyte(0x33); + addbyte(0x5c); + addbyte(0x8d); + addbyte(0); + } else if (!tca_reverse_blend) { + addbyte(0x81); /*XOR EBX, 0xFF*/ + addbyte(0xf3); + addlong(0xff); + } + + addbyte(0x83); /*ADD EBX, 1*/ + addbyte(0xc3); + addbyte(1); + addbyte(0x0f); /*IMUL EAX, EBX*/ + addbyte(0xaf); + addbyte(0xc3); + addbyte(0x31); /*XOR EDX, EDX*/ + addbyte(0xd2); + addbyte(0xc1); /*SAR EAX, 8*/ + addbyte(0xf8); + addbyte(8); + if (tca_add_clocal || tca_add_alocal) { + addbyte(0x66); /*MOV EBX, XMM7*/ + addbyte(0x0f); + addbyte(0x7e); + addbyte(0xfb); + addbyte(0xc1); /*SHR EBX, 24*/ + addbyte(0xeb); + addbyte(24); + addbyte(0x01); /*ADD EAX, EBX*/ + addbyte(0xd8); + } + addbyte(0x0f); /*CMOVS EAX, EDX*/ + addbyte(0x48); + addbyte(0xc2); + addbyte(0xba); /*MOV EDX, 0xff*/ + addlong(0xff); + addbyte(0x3d); /*CMP EAX, 0xff*/ + addlong(0xff); + addbyte(0x0f); /*CMOVA EAX, EDX*/ + addbyte(0x47); + addbyte(0xc2); + if (tca_invert_output) { + addbyte(0x35); /*XOR EAX, 0xff*/ + addlong(0xff); + } + + addbyte(0x89); /*MOV state->tex_a[EDI], EAX*/ + addbyte(0x87); + addlong(offsetof(voodoo_state_t, tex_a)); + + addbyte(0xf3); /*MOVQ XMM0, XMM1*/ + addbyte(0x0f); + addbyte(0x7e); + addbyte(0xc1); + } + if (cc_mselect == CC_MSELECT_TEXRGB) { + addbyte(0xf3); /*MOVD XMM4, XMM0*/ + addbyte(0x0f); + addbyte(0x7e); + addbyte(0xe0); + } + + if ((params->fbzMode & FBZ_CHROMAKEY)) { + switch (_rgb_sel) { + case CC_LOCALSELECT_ITER_RGB: + addbyte(0xf3); /*MOVDQU XMM0, ib*/ /* ir, ig and ib must be in same dqword!*/ + addbyte(0x0f); + addbyte(0x6f); + addbyte(0x87); + addlong(offsetof(voodoo_state_t, ib)); + addbyte(0x66); /*PSRAD XMM0, 12*/ addbyte(0x0f); addbyte(0x72); - addbyte(0xe1); - addbyte(8); - addbyte(0x66); /*PACKSSDW XMM1, XMM1*/ + addbyte(0xe0); + addbyte(12); + addbyte(0x66); /*PACKSSDW XMM0, XMM0*/ addbyte(0x0f); addbyte(0x6b); - addbyte(0xc9); - - if (tca_sub_clocal) - { - addbyte(0xc1); /*SHR EBX, 24*/ - addbyte(0xeb); - addbyte(24); - } - - if (tc_add_clocal) - { - addbyte(0x66); /*PADDW XMM1, XMM0*/ - addbyte(0x0f); - addbyte(0xfd); - addbyte(0xc8); - } - else if (tc_add_alocal) - { - addbyte(0xf2); /*PSHUFLW XMM4, XMM0, 3, 3, 3, 3*/ - addbyte(0x0f); - addbyte(0x70); - addbyte(0xe0); - addbyte(0xff); - addbyte(0x66); /*PADDW XMM1, XMM4*/ - addbyte(0x0f); - addbyte(0xfc); - addbyte(0xcc); - } - if (tc_invert_output) - { - addbyte(0x66); /*PXOR XMM1, XMM9(xmm_ff_w)*/ - addbyte(0x41); - addbyte(0x0f); - addbyte(0xef); - addbyte(0xc9); - } - + addbyte(0xc0); addbyte(0x66); /*PACKUSWB XMM0, XMM0*/ addbyte(0x0f); addbyte(0x67); addbyte(0xc0); - addbyte(0x66); /*PACKUSWB XMM3, XMM3*/ + addbyte(0x66); /*MOVD EAX, XMM0*/ addbyte(0x0f); - addbyte(0x67); + addbyte(0x7e); + addbyte(0xc0); + break; + case CC_LOCALSELECT_COLOR1: + addbyte(0x8b); /*MOV EAX, params->color1[RSI]*/ + addbyte(0x86); + addlong(offsetof(voodoo_params_t, color1)); + break; + case CC_LOCALSELECT_TEX: + addbyte(0x66); /*MOVD EAX, XMM0*/ + addbyte(0x0f); + addbyte(0x7e); + addbyte(0xc0); + break; + } + addbyte(0x8b); /*MOV EBX, params->chromaKey[ESI]*/ + addbyte(0x9e); + addlong(offsetof(voodoo_params_t, chromaKey)); + addbyte(0x31); /*XOR EBX, EAX*/ + addbyte(0xc3); + addbyte(0x81); /*AND EBX, 0xffffff*/ + addbyte(0xe3); + addlong(0xffffff); + addbyte(0x0f); /*JE skip*/ + addbyte(0x84); + chroma_skip_pos = block_pos; + addlong(0); + } + + if (voodoo->trexInit1[0] & (1 << 18)) { + addbyte(0xb8); /*MOV EAX, tmuConfig*/ + addlong(voodoo->tmuConfig); + addbyte(0x66); /*MOVD XMM0, EAX*/ + addbyte(0x0f); + addbyte(0x6e); + addbyte(0xc0); + } + + if (params->alphaMode & ((1 << 0) | (1 << 4))) { + /*EBX = a_other*/ + switch (a_sel) { + case A_SEL_ITER_A: + addbyte(0x8b); /*MOV EBX, state->ia*/ + addbyte(0x9f); + addlong(offsetof(voodoo_state_t, ia)); + addbyte(0x31); /*XOR EAX, EAX*/ + addbyte(0xc0); + addbyte(0xba); /*MOV EDX, 0xff*/ + addlong(0xff); + addbyte(0xc1); /*SAR EBX, 12*/ + addbyte(0xfb); + addbyte(12); + addbyte(0x0f); /*CMOVS EBX, EAX*/ + addbyte(0x48); + addbyte(0xd8); + addbyte(0x39); /*CMP EBX, EDX*/ + addbyte(0xd3); + addbyte(0x0f); /*CMOVA EBX, EDX*/ + addbyte(0x47); + addbyte(0xda); + break; + case A_SEL_TEX: + addbyte(0x8b); /*MOV EBX, state->tex_a*/ + addbyte(0x9f); + addlong(offsetof(voodoo_state_t, tex_a)); + break; + case A_SEL_COLOR1: + addbyte(0x0f); /*MOVZX EBX, params->color1+3*/ + addbyte(0xb6); + addbyte(0x9e); + addlong(offsetof(voodoo_params_t, color1) + 3); + break; + default: + addbyte(0x31); /*XOR EBX, EBX*/ addbyte(0xdb); + break; + } + /*ECX = a_local*/ + switch (cca_localselect) { + case CCA_LOCALSELECT_ITER_A: + if (a_sel == A_SEL_ITER_A) { + addbyte(0x89); /*MOV ECX, EBX*/ + addbyte(0xd9); + } else { + addbyte(0x8b); /*MOV ECX, state->ia*/ + addbyte(0x8f); + addlong(offsetof(voodoo_state_t, ia)); + addbyte(0x31); /*XOR EAX, EAX*/ + addbyte(0xc0); + addbyte(0xba); /*MOV EDX, 0xff*/ + addlong(0xff); + addbyte(0xc1); /*SAR ECX, 12*/ + addbyte(0xf9); + addbyte(12); + addbyte(0x0f); /*CMOVS ECX, EAX*/ + addbyte(0x48); + addbyte(0xc8); + addbyte(0x39); /*CMP ECX, EDX*/ + addbyte(0xd1); + addbyte(0x0f); /*CMOVA ECX, EDX*/ + addbyte(0x47); + addbyte(0xca); + } + break; + case CCA_LOCALSELECT_COLOR0: + addbyte(0x0f); /*MOVZX ECX, params->color0+3*/ + addbyte(0xb6); + addbyte(0x8e); + addlong(offsetof(voodoo_params_t, color0) + 3); + break; + case CCA_LOCALSELECT_ITER_Z: + addbyte(0x8b); /*MOV ECX, state->z*/ + addbyte(0x8f); + addlong(offsetof(voodoo_state_t, z)); + if (a_sel != A_SEL_ITER_A) { + addbyte(0x31); /*XOR EAX, EAX*/ + addbyte(0xc0); + addbyte(0xba); /*MOV EDX, 0xff*/ + addlong(0xff); + } + addbyte(0xc1); /*SAR ECX, 20*/ + addbyte(0xf9); + addbyte(20); + addbyte(0x0f); /*CMOVS ECX, EAX*/ + addbyte(0x48); + addbyte(0xc8); + addbyte(0x39); /*CMP ECX, EDX*/ + addbyte(0xd1); + addbyte(0x0f); /*CMOVA ECX, EDX*/ + addbyte(0x47); + addbyte(0xca); + break; + + default: + addbyte(0xb9); /*MOV ECX, 0xff*/ + addlong(0xff); + break; + } + + if (cca_zero_other) { + addbyte(0x31); /*XOR EDX, EDX*/ + addbyte(0xd2); + } else { + addbyte(0x89); /*MOV EDX, EBX*/ + addbyte(0xda); + } + + if (cca_sub_clocal) { + addbyte(0x29); /*SUB EDX, ECX*/ + addbyte(0xca); + } + } + + if (cc_sub_clocal || cc_mselect == 1 || cc_add == 1) { + /*XMM1 = local*/ + if (!cc_localselect_override) { + if (cc_localselect) { + addbyte(0x66); /*MOVD XMM1, params->color0*/ + addbyte(0x0f); + addbyte(0x6e); + addbyte(0x8e); + addlong(offsetof(voodoo_params_t, color0)); + } else { + addbyte(0xf3); /*MOVDQU XMM1, ib*/ /* ir, ig and ib must be in same dqword!*/ + addbyte(0x0f); + addbyte(0x6f); + addbyte(0x8f); + addlong(offsetof(voodoo_state_t, ib)); + addbyte(0x66); /*PSRAD XMM1, 12*/ + addbyte(0x0f); + addbyte(0x72); + addbyte(0xe1); + addbyte(12); + addbyte(0x66); /*PACKSSDW XMM1, XMM1*/ + addbyte(0x0f); + addbyte(0x6b); + addbyte(0xc9); addbyte(0x66); /*PACKUSWB XMM1, XMM1*/ addbyte(0x0f); addbyte(0x67); addbyte(0xc9); - - if (tca_zero_other) - { - addbyte(0x31); /*XOR EAX, EAX*/ - addbyte(0xc0); - } - else - { - addbyte(0x66); /*MOV EAX, XMM3*/ - addbyte(0x0f); - addbyte(0x7e); - addbyte(0xd8); - addbyte(0xc1); /*SHR EAX, 24*/ - addbyte(0xe8); - addbyte(24); - } - if (tca_sub_clocal) - { - addbyte(0x29); /*SUB EAX, EBX*/ - addbyte(0xd8); - } - switch (tca_mselect) - { - case TCA_MSELECT_ZERO: - addbyte(0x31); /*XOR EBX, EBX*/ - addbyte(0xdb); - break; - case TCA_MSELECT_CLOCAL: - addbyte(0x66); /*MOV EBX, XMM7*/ - addbyte(0x0f); - addbyte(0x7e); - addbyte(0xfb); - addbyte(0xc1); /*SHR EBX, 24*/ - addbyte(0xeb); - addbyte(24); - break; - case TCA_MSELECT_AOTHER: - addbyte(0x66); /*MOV EBX, XMM3*/ - addbyte(0x0f); - addbyte(0x7e); - addbyte(0xdb); - addbyte(0xc1); /*SHR EBX, 24*/ - addbyte(0xeb); - addbyte(24); - break; - case TCA_MSELECT_ALOCAL: - addbyte(0x66); /*MOV EBX, XMM7*/ - addbyte(0x0f); - addbyte(0x7e); - addbyte(0xfb); - addbyte(0xc1); /*SHR EBX, 24*/ - addbyte(0xeb); - addbyte(24); - break; - case TCA_MSELECT_DETAIL: - addbyte(0xbb); /*MOV EBX, params->detail_bias[1]*/ - addlong(params->detail_bias[1]); - addbyte(0x2b); /*SUB EBX, state->lod*/ - addbyte(0x9f); - addlong(offsetof(voodoo_state_t, lod)); - addbyte(0xba); /*MOV EDX, params->detail_max[1]*/ - addlong(params->detail_max[1]); - addbyte(0xc1); /*SHL EBX, params->detail_scale[1]*/ - addbyte(0xe3); - addbyte(params->detail_scale[1]); - addbyte(0x39); /*CMP EBX, EDX*/ - addbyte(0xd3); - addbyte(0x0f); /*CMOVNL EBX, EDX*/ - addbyte(0x4d); - addbyte(0xda); - break; - case TCA_MSELECT_LOD_FRAC: - addbyte(0x8b); /*MOV EBX, state->lod_frac[0]*/ - addbyte(0x9f); - addlong(offsetof(voodoo_state_t, lod_frac[0])); - break; - } - if (params->textureMode[0] & TEXTUREMODE_TRILINEAR) - { - addbyte(0x41); /*XOR EBX, R13(i_00_ff_w)[ECX*4]*/ - addbyte(0x33); - addbyte(0x5c); - addbyte(0x8d); - addbyte(0); - } - else if (!tca_reverse_blend) - { - addbyte(0x81); /*XOR EBX, 0xFF*/ - addbyte(0xf3); - addlong(0xff); - } - - addbyte(0x83); /*ADD EBX, 1*/ - addbyte(0xc3); - addbyte(1); - addbyte(0x0f); /*IMUL EAX, EBX*/ - addbyte(0xaf); - addbyte(0xc3); - addbyte(0x31); /*XOR EDX, EDX*/ - addbyte(0xd2); - addbyte(0xc1); /*SAR EAX, 8*/ - addbyte(0xf8); - addbyte(8); - if (tca_add_clocal || tca_add_alocal) - { - addbyte(0x66); /*MOV EBX, XMM7*/ - addbyte(0x0f); - addbyte(0x7e); - addbyte(0xfb); - addbyte(0xc1); /*SHR EBX, 24*/ - addbyte(0xeb); - addbyte(24); - addbyte(0x01); /*ADD EAX, EBX*/ - addbyte(0xd8); - } - addbyte(0x0f); /*CMOVS EAX, EDX*/ - addbyte(0x48); - addbyte(0xc2); - addbyte(0xba); /*MOV EDX, 0xff*/ - addlong(0xff); - addbyte(0x3d); /*CMP EAX, 0xff*/ - addlong(0xff); - addbyte(0x0f); /*CMOVA EAX, EDX*/ - addbyte(0x47); - addbyte(0xc2); - if (tca_invert_output) - { - addbyte(0x35); /*XOR EAX, 0xff*/ - addlong(0xff); - } - - addbyte(0x89); /*MOV state->tex_a[EDI], EAX*/ - addbyte(0x87); - addlong(offsetof(voodoo_state_t, tex_a)); - - addbyte(0xf3); /*MOVQ XMM0, XMM1*/ - addbyte(0x0f); - addbyte(0x7e); - addbyte(0xc1); + } + } else { + addbyte(0xf6); /*TEST state->tex_a, 0x80*/ + addbyte(0x87); + addbyte(0x23); + addlong(offsetof(voodoo_state_t, tex_a)); + addbyte(0x80); + addbyte(0x74); /*JZ !cc_localselect*/ + addbyte(8 + 2); + addbyte(0x66); /*MOVD XMM1, params->color0*/ + addbyte(0x0f); + addbyte(0x6e); + addbyte(0x8e); + addlong(offsetof(voodoo_params_t, color0)); + addbyte(0xeb); /*JMP +*/ + addbyte(8 + 5 + 4 + 4); + /*!cc_localselect:*/ + addbyte(0xf3); /*MOVDQU XMM1, ib*/ /* ir, ig and ib must be in same dqword!*/ + addbyte(0x0f); + addbyte(0x6f); + addbyte(0x8f); + addlong(offsetof(voodoo_state_t, ib)); + addbyte(0x66); /*PSRAD XMM1, 12*/ + addbyte(0x0f); + addbyte(0x72); + addbyte(0xe1); + addbyte(12); + addbyte(0x66); /*PACKSSDW XMM1, XMM1*/ + addbyte(0x0f); + addbyte(0x6b); + addbyte(0xc9); + addbyte(0x66); /*PACKUSWB XMM1, XMM1*/ + addbyte(0x0f); + addbyte(0x67); + addbyte(0xc9); } - if (cc_mselect == CC_MSELECT_TEXRGB) - { - addbyte(0xf3); /*MOVD XMM4, XMM0*/ - addbyte(0x0f); - addbyte(0x7e); - addbyte(0xe0); - } - - if ((params->fbzMode & FBZ_CHROMAKEY)) - { - switch (_rgb_sel) - { - case CC_LOCALSELECT_ITER_RGB: - addbyte(0xf3); /*MOVDQU XMM0, ib*/ /* ir, ig and ib must be in same dqword!*/ - addbyte(0x0f); - addbyte(0x6f); - addbyte(0x87); - addlong(offsetof(voodoo_state_t, ib)); - addbyte(0x66); /*PSRAD XMM0, 12*/ - addbyte(0x0f); - addbyte(0x72); - addbyte(0xe0); - addbyte(12); - addbyte(0x66); /*PACKSSDW XMM0, XMM0*/ - addbyte(0x0f); - addbyte(0x6b); - addbyte(0xc0); - addbyte(0x66); /*PACKUSWB XMM0, XMM0*/ - addbyte(0x0f); - addbyte(0x67); - addbyte(0xc0); - addbyte(0x66); /*MOVD EAX, XMM0*/ - addbyte(0x0f); - addbyte(0x7e); - addbyte(0xc0); - break; - case CC_LOCALSELECT_COLOR1: - addbyte(0x8b); /*MOV EAX, params->color1[RSI]*/ - addbyte(0x86); - addlong(offsetof(voodoo_params_t, color1)); - break; - case CC_LOCALSELECT_TEX: - addbyte(0x66); /*MOVD EAX, XMM0*/ - addbyte(0x0f); - addbyte(0x7e); - addbyte(0xc0); - break; - } - addbyte(0x8b); /*MOV EBX, params->chromaKey[ESI]*/ - addbyte(0x9e); - addlong(offsetof(voodoo_params_t, chromaKey)); - addbyte(0x31); /*XOR EBX, EAX*/ - addbyte(0xc3); - addbyte(0x81); /*AND EBX, 0xffffff*/ - addbyte(0xe3); - addlong(0xffffff); - addbyte(0x0f); /*JE skip*/ - addbyte(0x84); - chroma_skip_pos = block_pos; - addlong(0); - } - - if (voodoo->trexInit1[0] & (1 << 18)) - { - addbyte(0xb8); /*MOV EAX, tmuConfig*/ - addlong(voodoo->tmuConfig); - addbyte(0x66); /*MOVD XMM0, EAX*/ - addbyte(0x0f); - addbyte(0x6e); - addbyte(0xc0); - } - - if (params->alphaMode & ((1 << 0) | (1 << 4))) - { - /*EBX = a_other*/ - switch (a_sel) - { - case A_SEL_ITER_A: - addbyte(0x8b); /*MOV EBX, state->ia*/ - addbyte(0x9f); - addlong(offsetof(voodoo_state_t, ia)); - addbyte(0x31); /*XOR EAX, EAX*/ - addbyte(0xc0); - addbyte(0xba); /*MOV EDX, 0xff*/ - addlong(0xff); - addbyte(0xc1); /*SAR EBX, 12*/ - addbyte(0xfb); - addbyte(12); - addbyte(0x0f); /*CMOVS EBX, EAX*/ - addbyte(0x48); - addbyte(0xd8); - addbyte(0x39); /*CMP EBX, EDX*/ - addbyte(0xd3); - addbyte(0x0f); /*CMOVA EBX, EDX*/ - addbyte(0x47); - addbyte(0xda); - break; - case A_SEL_TEX: - addbyte(0x8b); /*MOV EBX, state->tex_a*/ - addbyte(0x9f); - addlong(offsetof(voodoo_state_t, tex_a)); - break; - case A_SEL_COLOR1: - addbyte(0x0f); /*MOVZX EBX, params->color1+3*/ - addbyte(0xb6); - addbyte(0x9e); - addlong(offsetof(voodoo_params_t, color1)+3); - break; - default: - addbyte(0x31); /*XOR EBX, EBX*/ - addbyte(0xdb); - break; - } - /*ECX = a_local*/ - switch (cca_localselect) - { - case CCA_LOCALSELECT_ITER_A: - if (a_sel == A_SEL_ITER_A) - { - addbyte(0x89); /*MOV ECX, EBX*/ - addbyte(0xd9); - } - else - { - addbyte(0x8b); /*MOV ECX, state->ia*/ - addbyte(0x8f); - addlong(offsetof(voodoo_state_t, ia)); - addbyte(0x31); /*XOR EAX, EAX*/ - addbyte(0xc0); - addbyte(0xba); /*MOV EDX, 0xff*/ - addlong(0xff); - addbyte(0xc1);/*SAR ECX, 12*/ - addbyte(0xf9); - addbyte(12); - addbyte(0x0f); /*CMOVS ECX, EAX*/ - addbyte(0x48); - addbyte(0xc8); - addbyte(0x39); /*CMP ECX, EDX*/ - addbyte(0xd1); - addbyte(0x0f); /*CMOVA ECX, EDX*/ - addbyte(0x47); - addbyte(0xca); - } - break; - case CCA_LOCALSELECT_COLOR0: - addbyte(0x0f); /*MOVZX ECX, params->color0+3*/ - addbyte(0xb6); - addbyte(0x8e); - addlong(offsetof(voodoo_params_t, color0)+3); - break; - case CCA_LOCALSELECT_ITER_Z: - addbyte(0x8b); /*MOV ECX, state->z*/ - addbyte(0x8f); - addlong(offsetof(voodoo_state_t, z)); - if (a_sel != A_SEL_ITER_A) - { - addbyte(0x31); /*XOR EAX, EAX*/ - addbyte(0xc0); - addbyte(0xba); /*MOV EDX, 0xff*/ - addlong(0xff); - } - addbyte(0xc1);/*SAR ECX, 20*/ - addbyte(0xf9); - addbyte(20); - addbyte(0x0f); /*CMOVS ECX, EAX*/ - addbyte(0x48); - addbyte(0xc8); - addbyte(0x39); /*CMP ECX, EDX*/ - addbyte(0xd1); - addbyte(0x0f); /*CMOVA ECX, EDX*/ - addbyte(0x47); - addbyte(0xca); - break; - - default: - addbyte(0xb9); /*MOV ECX, 0xff*/ - addlong(0xff); - break; - } - - if (cca_zero_other) - { - addbyte(0x31); /*XOR EDX, EDX*/ - addbyte(0xd2); - } - else - { - addbyte(0x89); /*MOV EDX, EBX*/ - addbyte(0xda); - } - - if (cca_sub_clocal) - { - addbyte(0x29); /*SUB EDX, ECX*/ - addbyte(0xca); - } - } - - if (cc_sub_clocal || cc_mselect == 1 || cc_add == 1) - { - /*XMM1 = local*/ - if (!cc_localselect_override) - { - if (cc_localselect) - { - addbyte(0x66); /*MOVD XMM1, params->color0*/ - addbyte(0x0f); - addbyte(0x6e); - addbyte(0x8e); - addlong(offsetof(voodoo_params_t, color0)); - } - else - { - addbyte(0xf3); /*MOVDQU XMM1, ib*/ /* ir, ig and ib must be in same dqword!*/ - addbyte(0x0f); - addbyte(0x6f); - addbyte(0x8f); - addlong(offsetof(voodoo_state_t, ib)); - addbyte(0x66); /*PSRAD XMM1, 12*/ - addbyte(0x0f); - addbyte(0x72); - addbyte(0xe1); - addbyte(12); - addbyte(0x66); /*PACKSSDW XMM1, XMM1*/ - addbyte(0x0f); - addbyte(0x6b); - addbyte(0xc9); - addbyte(0x66); /*PACKUSWB XMM1, XMM1*/ - addbyte(0x0f); - addbyte(0x67); - addbyte(0xc9); - } - } - else - { - addbyte(0xf6); /*TEST state->tex_a, 0x80*/ - addbyte(0x87); - addbyte(0x23); - addlong(offsetof(voodoo_state_t, tex_a)); - addbyte(0x80); - addbyte(0x74);/*JZ !cc_localselect*/ - addbyte(8+2); - addbyte(0x66); /*MOVD XMM1, params->color0*/ - addbyte(0x0f); - addbyte(0x6e); - addbyte(0x8e); - addlong(offsetof(voodoo_params_t, color0)); - addbyte(0xeb); /*JMP +*/ - addbyte(8+5+4+4); - /*!cc_localselect:*/ - addbyte(0xf3); /*MOVDQU XMM1, ib*/ /* ir, ig and ib must be in same dqword!*/ - addbyte(0x0f); - addbyte(0x6f); - addbyte(0x8f); - addlong(offsetof(voodoo_state_t, ib)); - addbyte(0x66); /*PSRAD XMM1, 12*/ - addbyte(0x0f); - addbyte(0x72); - addbyte(0xe1); - addbyte(12); - addbyte(0x66); /*PACKSSDW XMM1, XMM1*/ - addbyte(0x0f); - addbyte(0x6b); - addbyte(0xc9); - addbyte(0x66); /*PACKUSWB XMM1, XMM1*/ - addbyte(0x0f); - addbyte(0x67); - addbyte(0xc9); - } - addbyte(0x66); /*PUNPCKLBW XMM1, XMM2*/ - addbyte(0x0f); - addbyte(0x60); - addbyte(0xca); - } - if (!cc_zero_other) - { - if (_rgb_sel == CC_LOCALSELECT_ITER_RGB) - { - addbyte(0xf3); /*MOVDQU XMM0, ib*/ /* ir, ig and ib must be in same dqword!*/ - addbyte(0x0f); - addbyte(0x6f); - addbyte(0x87); - addlong(offsetof(voodoo_state_t, ib)); - addbyte(0x66); /*PSRAD XMM0, 12*/ - addbyte(0x0f); - addbyte(0x72); - addbyte(0xe0); - addbyte(12); - addbyte(0x66); /*PACKSSDW XMM0, XMM0*/ - addbyte(0x0f); - addbyte(0x6b); - addbyte(0xc0); - addbyte(0x66); /*PACKUSWB XMM0, XMM0*/ - addbyte(0x0f); - addbyte(0x67); - addbyte(0xc0); - } - else if (_rgb_sel == CC_LOCALSELECT_TEX) - { + addbyte(0x66); /*PUNPCKLBW XMM1, XMM2*/ + addbyte(0x0f); + addbyte(0x60); + addbyte(0xca); + } + if (!cc_zero_other) { + if (_rgb_sel == CC_LOCALSELECT_ITER_RGB) { + addbyte(0xf3); /*MOVDQU XMM0, ib*/ /* ir, ig and ib must be in same dqword!*/ + addbyte(0x0f); + addbyte(0x6f); + addbyte(0x87); + addlong(offsetof(voodoo_state_t, ib)); + addbyte(0x66); /*PSRAD XMM0, 12*/ + addbyte(0x0f); + addbyte(0x72); + addbyte(0xe0); + addbyte(12); + addbyte(0x66); /*PACKSSDW XMM0, XMM0*/ + addbyte(0x0f); + addbyte(0x6b); + addbyte(0xc0); + addbyte(0x66); /*PACKUSWB XMM0, XMM0*/ + addbyte(0x0f); + addbyte(0x67); + addbyte(0xc0); + } else if (_rgb_sel == CC_LOCALSELECT_TEX) { #if 0 addbyte(0xf3); /*MOVDQU XMM0, state->tex_b*/ addbyte(0x0f); @@ -2031,1422 +1913,1347 @@ static inline void voodoo_generate(uint8_t *code_block, voodoo_t *voodoo, voodoo addbyte(0x67); addbyte(0xc0); #endif - } - else if (_rgb_sel == CC_LOCALSELECT_COLOR1) - { - addbyte(0x66); /*MOVD XMM0, params->color1*/ - addbyte(0x0f); - addbyte(0x6e); - addbyte(0x86); - addlong(offsetof(voodoo_params_t, color1)); - } - else - { - /*MOVD XMM0, src_r*/ - } - addbyte(0x66); /*PUNPCKLBW XMM0, XMM2*/ - addbyte(0x0f); - addbyte(0x60); - addbyte(0xc2); - if (cc_sub_clocal) - { - addbyte(0x66); /*PSUBW XMM0, XMM1*/ - addbyte(0x0f); - addbyte(0xf9); - addbyte(0xc1); - } + } else if (_rgb_sel == CC_LOCALSELECT_COLOR1) { + addbyte(0x66); /*MOVD XMM0, params->color1*/ + addbyte(0x0f); + addbyte(0x6e); + addbyte(0x86); + addlong(offsetof(voodoo_params_t, color1)); + } else { + /*MOVD XMM0, src_r*/ } - else - { - addbyte(0x66); /*PXOR XMM0, XMM0*/ + addbyte(0x66); /*PUNPCKLBW XMM0, XMM2*/ + addbyte(0x0f); + addbyte(0x60); + addbyte(0xc2); + if (cc_sub_clocal) { + addbyte(0x66); /*PSUBW XMM0, XMM1*/ + addbyte(0x0f); + addbyte(0xf9); + addbyte(0xc1); + } + } else { + addbyte(0x66); /*PXOR XMM0, XMM0*/ + addbyte(0x0f); + addbyte(0xef); + addbyte(0xc0); + if (cc_sub_clocal) { + addbyte(0x66); /*PSUBW XMM0, XMM1*/ + addbyte(0x0f); + addbyte(0xf9); + addbyte(0xc1); + } + } + + if (params->alphaMode & ((1 << 0) | (1 << 4))) { + if (!(cca_mselect == 0 && cca_reverse_blend == 0)) { + switch (cca_mselect) { + case CCA_MSELECT_ALOCAL: + addbyte(0x89); /*MOV EAX, ECX*/ + addbyte(0xc8); + break; + case CCA_MSELECT_AOTHER: + addbyte(0x89); /*MOV EAX, EBX*/ + addbyte(0xd8); + break; + case CCA_MSELECT_ALOCAL2: + addbyte(0x89); /*MOV EAX, ECX*/ + addbyte(0xc8); + break; + case CCA_MSELECT_TEX: + addbyte(0x0f); /*MOVZX EAX, state->tex_a*/ + addbyte(0xb6); + addbyte(0x87); + addlong(offsetof(voodoo_state_t, tex_a)); + break; + + case CCA_MSELECT_ZERO: + default: + addbyte(0x31); /*XOR EAX, EAX*/ + addbyte(0xc0); + break; + } + if (!cca_reverse_blend) { + addbyte(0x35); /*XOR EAX, 0xff*/ + addlong(0xff); + } + addbyte(0x83); /*ADD EAX, 1*/ + addbyte(0xc0); + addbyte(1); + addbyte(0x0f); /*IMUL EDX, EAX*/ + addbyte(0xaf); + addbyte(0xd0); + addbyte(0xc1); /*SHR EDX, 8*/ + addbyte(0xea); + addbyte(8); + } + } + + if ((params->alphaMode & ((1 << 0) | (1 << 4)))) { + addbyte(0x31); /*XOR EAX, EAX*/ + addbyte(0xc0); + } + + if (!(cc_mselect == 0 && cc_reverse_blend == 0) && cc_mselect == CC_MSELECT_AOTHER) { + /*Copy a_other to XMM3 before it gets modified*/ + addbyte(0x66); /*MOVD XMM3, EDX*/ + addbyte(0x0f); + addbyte(0x6e); + addbyte(0xda); + addbyte(0xf2); /*PSHUFLW XMM3, XMM3, 0*/ + addbyte(0x0f); + addbyte(0x70); + addbyte(0xdb); + addbyte(0x00); + } + + if (cca_add && (params->alphaMode & ((1 << 0) | (1 << 4)))) { + addbyte(0x01); /*ADD EDX, ECX*/ + addbyte(0xca); + } + + if ((params->alphaMode & ((1 << 0) | (1 << 4)))) { + addbyte(0x85); /*TEST EDX, EDX*/ + addbyte(0xd2); + addbyte(0x0f); /*CMOVS EDX, EAX*/ + addbyte(0x48); + addbyte(0xd0); + addbyte(0xb8); /*MOV EAX, 0xff*/ + addlong(0xff); + addbyte(0x81); /*CMP EDX, 0xff*/ + addbyte(0xfa); + addlong(0xff); + addbyte(0x0f); /*CMOVA EDX, EAX*/ + addbyte(0x47); + addbyte(0xd0); + if (cca_invert_output) { + addbyte(0x81); /*XOR EDX, 0xff*/ + addbyte(0xf2); + addlong(0xff); + } + } + + if (!(cc_mselect == 0 && cc_reverse_blend == 0)) { + switch (cc_mselect) { + case CC_MSELECT_ZERO: + addbyte(0x66); /*PXOR XMM3, XMM3*/ addbyte(0x0f); addbyte(0xef); - addbyte(0xc0); - if (cc_sub_clocal) - { - addbyte(0x66); /*PSUBW XMM0, XMM1*/ - addbyte(0x0f); - addbyte(0xf9); - addbyte(0xc1); - } - } - - if (params->alphaMode & ((1 << 0) | (1 << 4))) - { - if (!(cca_mselect == 0 && cca_reverse_blend == 0)) - { - switch (cca_mselect) - { - case CCA_MSELECT_ALOCAL: - addbyte(0x89); /*MOV EAX, ECX*/ - addbyte(0xc8); - break; - case CCA_MSELECT_AOTHER: - addbyte(0x89); /*MOV EAX, EBX*/ - addbyte(0xd8); - break; - case CCA_MSELECT_ALOCAL2: - addbyte(0x89); /*MOV EAX, ECX*/ - addbyte(0xc8); - break; - case CCA_MSELECT_TEX: - addbyte(0x0f); /*MOVZX EAX, state->tex_a*/ - addbyte(0xb6); - addbyte(0x87); - addlong(offsetof(voodoo_state_t, tex_a)); - break; - - case CCA_MSELECT_ZERO: - default: - addbyte(0x31); /*XOR EAX, EAX*/ - addbyte(0xc0); - break; - } - if (!cca_reverse_blend) - { - addbyte(0x35); /*XOR EAX, 0xff*/ - addlong(0xff); - } - addbyte(0x83); /*ADD EAX, 1*/ - addbyte(0xc0); - addbyte(1); - addbyte(0x0f); /*IMUL EDX, EAX*/ - addbyte(0xaf); - addbyte(0xd0); - addbyte(0xc1); /*SHR EDX, 8*/ - addbyte(0xea); - addbyte(8); - } - } - - if ((params->alphaMode & ((1 << 0) | (1 << 4)))) - { - addbyte(0x31); /*XOR EAX, EAX*/ - addbyte(0xc0); - } - - if (!(cc_mselect == 0 && cc_reverse_blend == 0) && cc_mselect == CC_MSELECT_AOTHER) - { - /*Copy a_other to XMM3 before it gets modified*/ - addbyte(0x66); /*MOVD XMM3, EDX*/ + addbyte(0xdb); + break; + case CC_MSELECT_CLOCAL: + addbyte(0xf3); /*MOV XMM3, XMM1*/ + addbyte(0x0f); + addbyte(0x7e); + addbyte(0xd9); + break; + case CC_MSELECT_ALOCAL: + addbyte(0x66); /*MOVD XMM3, ECX*/ addbyte(0x0f); addbyte(0x6e); - addbyte(0xda); + addbyte(0xd9); addbyte(0xf2); /*PSHUFLW XMM3, XMM3, 0*/ addbyte(0x0f); addbyte(0x70); addbyte(0xdb); addbyte(0x00); - } - - if (cca_add && (params->alphaMode & ((1 << 0) | (1 << 4)))) - { - addbyte(0x01); /*ADD EDX, ECX*/ - addbyte(0xca); - } - - if ((params->alphaMode & ((1 << 0) | (1 << 4)))) - { - addbyte(0x85); /*TEST EDX, EDX*/ - addbyte(0xd2); - addbyte(0x0f); /*CMOVS EDX, EAX*/ - addbyte(0x48); - addbyte(0xd0); - addbyte(0xb8); /*MOV EAX, 0xff*/ - addlong(0xff); - addbyte(0x81); /*CMP EDX, 0xff*/ - addbyte(0xfa); - addlong(0xff); - addbyte(0x0f); /*CMOVA EDX, EAX*/ - addbyte(0x47); - addbyte(0xd0); - if (cca_invert_output) - { - addbyte(0x81); /*XOR EDX, 0xff*/ - addbyte(0xf2); - addlong(0xff); - } - } - - if (!(cc_mselect == 0 && cc_reverse_blend == 0)) - { - switch (cc_mselect) - { - case CC_MSELECT_ZERO: - addbyte(0x66); /*PXOR XMM3, XMM3*/ - addbyte(0x0f); - addbyte(0xef); - addbyte(0xdb); - break; - case CC_MSELECT_CLOCAL: - addbyte(0xf3); /*MOV XMM3, XMM1*/ - addbyte(0x0f); - addbyte(0x7e); - addbyte(0xd9); - break; - case CC_MSELECT_ALOCAL: - addbyte(0x66); /*MOVD XMM3, ECX*/ - addbyte(0x0f); - addbyte(0x6e); - addbyte(0xd9); - addbyte(0xf2); /*PSHUFLW XMM3, XMM3, 0*/ - addbyte(0x0f); - addbyte(0x70); - addbyte(0xdb); - addbyte(0x00); - break; - case CC_MSELECT_AOTHER: - /*Handled above*/ - break; - case CC_MSELECT_TEX: - addbyte(0x66); /*PINSRW XMM3, state->tex_a, 0*/ - addbyte(0x0f); - addbyte(0xc4); - addbyte(0x9f); - addlong(offsetof(voodoo_state_t, tex_a)); - addbyte(0); - addbyte(0x66); /*PINSRW XMM3, state->tex_a, 1*/ - addbyte(0x0f); - addbyte(0xc4); - addbyte(0x9f); - addlong(offsetof(voodoo_state_t, tex_a)); - addbyte(1); - addbyte(0x66); /*PINSRW XMM3, state->tex_a, 2*/ - addbyte(0x0f); - addbyte(0xc4); - addbyte(0x9f); - addlong(offsetof(voodoo_state_t, tex_a)); - addbyte(2); - break; - case CC_MSELECT_TEXRGB: - addbyte(0x66); /*PUNPCKLBW XMM4, XMM2*/ - addbyte(0x0f); - addbyte(0x60); - addbyte(0xe2); - addbyte(0xf3); /*MOVQ XMM3, XMM4*/ - addbyte(0x0f); - addbyte(0x7e); - addbyte(0xdc); - break; - default: - addbyte(0x66); /*PXOR XMM3, XMM3*/ - addbyte(0x0f); - addbyte(0xef); - addbyte(0xdb); - break; - } - addbyte(0xf3); /*MOV XMM4, XMM0*/ + break; + case CC_MSELECT_AOTHER: + /*Handled above*/ + break; + case CC_MSELECT_TEX: + addbyte(0x66); /*PINSRW XMM3, state->tex_a, 0*/ + addbyte(0x0f); + addbyte(0xc4); + addbyte(0x9f); + addlong(offsetof(voodoo_state_t, tex_a)); + addbyte(0); + addbyte(0x66); /*PINSRW XMM3, state->tex_a, 1*/ + addbyte(0x0f); + addbyte(0xc4); + addbyte(0x9f); + addlong(offsetof(voodoo_state_t, tex_a)); + addbyte(1); + addbyte(0x66); /*PINSRW XMM3, state->tex_a, 2*/ + addbyte(0x0f); + addbyte(0xc4); + addbyte(0x9f); + addlong(offsetof(voodoo_state_t, tex_a)); + addbyte(2); + break; + case CC_MSELECT_TEXRGB: + addbyte(0x66); /*PUNPCKLBW XMM4, XMM2*/ + addbyte(0x0f); + addbyte(0x60); + addbyte(0xe2); + addbyte(0xf3); /*MOVQ XMM3, XMM4*/ addbyte(0x0f); addbyte(0x7e); - addbyte(0xe0); - if (!cc_reverse_blend) - { - addbyte(0x66); /*PXOR XMM3, XMM9(xmm_ff_w)*/ - addbyte(0x41); - addbyte(0x0f); - addbyte(0xef); - addbyte(0xd9); - } - addbyte(0x66); /*PADDW XMM3, XMM8(xmm_01_w)*/ + addbyte(0xdc); + break; + default: + addbyte(0x66); /*PXOR XMM3, XMM3*/ + addbyte(0x0f); + addbyte(0xef); + addbyte(0xdb); + break; + } + addbyte(0xf3); /*MOV XMM4, XMM0*/ + addbyte(0x0f); + addbyte(0x7e); + addbyte(0xe0); + if (!cc_reverse_blend) { + addbyte(0x66); /*PXOR XMM3, XMM9(xmm_ff_w)*/ + addbyte(0x41); + addbyte(0x0f); + addbyte(0xef); + addbyte(0xd9); + } + addbyte(0x66); /*PADDW XMM3, XMM8(xmm_01_w)*/ + addbyte(0x41); + addbyte(0x0f); + addbyte(0xfd); + addbyte(0xd8); + addbyte(0x66); /*PMULLW XMM0, XMM3*/ + addbyte(0x0f); + addbyte(0xd5); + addbyte(0xc3); + addbyte(0x66); /*PMULHW XMM4, XMM3*/ + addbyte(0x0f); + addbyte(0xe5); + addbyte(0xe3); + addbyte(0x66); /*PUNPCKLWD XMM0, XMM4*/ + addbyte(0x0f); + addbyte(0x61); + addbyte(0xc4); + addbyte(0x66); /*PSRLD XMM0, 8*/ + addbyte(0x0f); + addbyte(0x72); + addbyte(0xe0); + addbyte(8); + addbyte(0x66); /*PACKSSDW XMM0, XMM0*/ + addbyte(0x0f); + addbyte(0x6b); + addbyte(0xc0); + } + + if (cc_add == 1) { + addbyte(0x66); /*PADDW XMM0, XMM1*/ + addbyte(0x0f); + addbyte(0xfd); + addbyte(0xc1); + } + + addbyte(0x66); /*PACKUSWB XMM0, XMM0*/ + addbyte(0x0f); + addbyte(0x67); + addbyte(0xc0); + + if (cc_invert_output) { + addbyte(0x66); /*PXOR XMM0, XMM10(xmm_ff_b)*/ + addbyte(0x41); + addbyte(0x0f); + addbyte(0xef); + addbyte(0xc2); + } + + if (params->fogMode & FOG_ENABLE) { + if (params->fogMode & FOG_CONSTANT) { + addbyte(0x66); /*MOVD XMM3, params->fogColor[ESI]*/ + addbyte(0x0f); + addbyte(0x6e); + addbyte(0x9e); + addlong(offsetof(voodoo_params_t, fogColor)); + addbyte(0x66); /*PADDUSB XMM0, XMM3*/ + addbyte(0x0f); + addbyte(0xdc); + addbyte(0xc3); + } else { + addbyte(0x66); /*PUNPCKLBW XMM0, XMM2*/ + addbyte(0x0f); + addbyte(0x60); + addbyte(0xc2); + + if (!(params->fogMode & FOG_ADD)) { + addbyte(0x66); /*MOVD XMM3, params->fogColor[ESI]*/ + addbyte(0x0f); + addbyte(0x6e); + addbyte(0x9e); + addlong(offsetof(voodoo_params_t, fogColor)); + addbyte(0x66); /*PUNPCKLBW XMM3, XMM2*/ + addbyte(0x0f); + addbyte(0x60); + addbyte(0xda); + } else { + addbyte(0x66); /*PXOR XMM3, XMM3*/ + addbyte(0x0f); + addbyte(0xef); + addbyte(0xdb); + } + + if (!(params->fogMode & FOG_MULT)) { + addbyte(0x66); /*PSUBW XMM3, XMM0*/ + addbyte(0x0f); + addbyte(0xf9); + addbyte(0xd8); + } + + /*Divide by 2 to prevent overflow on multiply*/ + addbyte(0x66); /*PSRAW XMM3, 1*/ + addbyte(0x0f); + addbyte(0x71); + addbyte(0xe3); + addbyte(1); + + switch (params->fogMode & (FOG_Z | FOG_ALPHA)) { + case 0: + addbyte(0x8b); /*MOV EBX, state->w_depth[EDI]*/ + addbyte(0x9f); + addlong(offsetof(voodoo_state_t, w_depth)); + addbyte(0x89); /*MOV EAX, EBX*/ + addbyte(0xd8); + addbyte(0xc1); /*SHR EBX, 10*/ + addbyte(0xeb); + addbyte(10); + addbyte(0xc1); /*SHR EAX, 2*/ + addbyte(0xe8); + addbyte(2); + addbyte(0x83); /*AND EBX, 0x3f*/ + addbyte(0xe3); + addbyte(0x3f); + addbyte(0x25); /*AND EAX, 0xff*/ + addlong(0xff); + addbyte(0xf6); /*MUL params->fogTable+1[ESI+EBX*2]*/ + addbyte(0xa4); + addbyte(0x5e); + addlong(offsetof(voodoo_params_t, fogTable) + 1); + addbyte(0x0f); /*MOVZX EBX, params->fogTable[ESI+EBX*2]*/ + addbyte(0xb6); + addbyte(0x9c); + addbyte(0x5e); + addlong(offsetof(voodoo_params_t, fogTable)); + addbyte(0xc1); /*SHR EAX, 10*/ + addbyte(0xe8); + addbyte(10); + addbyte(0x01); /*ADD EAX, EBX*/ + addbyte(0xd8); +#if 0 + int fog_idx = (w_depth >> 10) & 0x3f; + + fog_a = params->fogTable[fog_idx].fog; + fog_a += (params->fogTable[fog_idx].dfog * ((w_depth >> 2) & 0xff)) >> 10; +#endif + break; + + case FOG_Z: + addbyte(0x8b); /*MOV EAX, state->z[EDI]*/ + addbyte(0x87); + addlong(offsetof(voodoo_state_t, z)); + addbyte(0xc1); /*SHR EAX, 12*/ + addbyte(0xe8); + addbyte(12); + addbyte(0x25); /*AND EAX, 0xff*/ + addlong(0xff); +#if 0 + fog_a = (z >> 20) & 0xff; +#endif + break; + + case FOG_ALPHA: + addbyte(0x8b); /*MOV EAX, state->ia[EDI]*/ + addbyte(0x87); + addlong(offsetof(voodoo_state_t, ia)); + addbyte(0x31); /*XOR EBX, EBX*/ + addbyte(0xdb); + addbyte(0xc1); /*SAR EAX, 12*/ + addbyte(0xf8); + addbyte(12); + addbyte(0x0f); /*CMOVS EAX, EBX*/ + addbyte(0x48); + addbyte(0xc3); + addbyte(0xbb); /*MOV EBX, 0xff*/ + addlong(0xff); + addbyte(0x3d); /*CMP EAX, 0xff*/ + addlong(0xff); + addbyte(0x0f); /*CMOVAE EAX, EBX*/ + addbyte(0x43); + addbyte(0xc3); +#if 0 + fog_a = CLAMP(ia >> 12); +#endif + break; + + case FOG_W: + addbyte(0x8b); /*MOV EAX, state->w[EDI]+4*/ + addbyte(0x87); + addlong(offsetof(voodoo_state_t, w) + 4); + addbyte(0x31); /*XOR EBX, EBX*/ + addbyte(0xdb); + addbyte(0x09); /*OR EAX, EAX*/ + addbyte(0xc0); + addbyte(0x0f); /*CMOVS EAX, EBX*/ + addbyte(0x48); + addbyte(0xc3); + addbyte(0xbb); /*MOV EBX, 0xff*/ + addlong(0xff); + addbyte(0x3d); /*CMP EAX, 0xff*/ + addlong(0xff); + addbyte(0x0f); /*CMOVAE EAX, EBX*/ + addbyte(0x43); + addbyte(0xc3); +#if 0 + fog_a = CLAMP(w >> 32); +#endif + break; + } + addbyte(0x01); /*ADD EAX, EAX*/ + addbyte(0xc0); + + addbyte(0x66); /*PMULLW XMM3, alookup+4[EAX*8]*/ + addbyte(0x41); + addbyte(0x0f); + addbyte(0xd5); + addbyte(0x5c); + addbyte(0xc2); + addbyte(16); + addbyte(0x66); /*PSRAW XMM3, 7*/ + addbyte(0x0f); + addbyte(0x71); + addbyte(0xe3); + addbyte(7); + + if (params->fogMode & FOG_MULT) { + addbyte(0xf3); /*MOV XMM0, XMM3*/ + addbyte(0x0f); + addbyte(0x7e); + addbyte(0xc3); + } else { + addbyte(0x66); /*PADDW XMM0, XMM3*/ + addbyte(0x0f); + addbyte(0xfd); + addbyte(0xc3); + } + addbyte(0x66); /*PACKUSWB XMM0, XMM0*/ + addbyte(0x0f); + addbyte(0x67); + addbyte(0xc0); + } + } + + if ((params->alphaMode & 1) && (alpha_func != AFUNC_NEVER) && (alpha_func != AFUNC_ALWAYS)) { + addbyte(0x0f); /*MOVZX ECX, params->alphaMode+3*/ + addbyte(0xb6); + addbyte(0x8e); + addlong(offsetof(voodoo_params_t, alphaMode) + 3); + addbyte(0x39); /*CMP EDX, ECX*/ + addbyte(0xca); + + switch (alpha_func) { + case AFUNC_LESSTHAN: + addbyte(0x0f); /*JAE skip*/ + addbyte(0x83); + a_skip_pos = block_pos; + addlong(0); + break; + case AFUNC_EQUAL: + addbyte(0x0f); /*JNE skip*/ + addbyte(0x85); + a_skip_pos = block_pos; + addlong(0); + break; + case AFUNC_LESSTHANEQUAL: + addbyte(0x0f); /*JA skip*/ + addbyte(0x87); + a_skip_pos = block_pos; + addlong(0); + break; + case AFUNC_GREATERTHAN: + addbyte(0x0f); /*JBE skip*/ + addbyte(0x86); + a_skip_pos = block_pos; + addlong(0); + break; + case AFUNC_NOTEQUAL: + addbyte(0x0f); /*JE skip*/ + addbyte(0x84); + a_skip_pos = block_pos; + addlong(0); + break; + case AFUNC_GREATERTHANEQUAL: + addbyte(0x0f); /*JB skip*/ + addbyte(0x82); + a_skip_pos = block_pos; + addlong(0); + break; + } + } else if ((params->alphaMode & 1) && (alpha_func == AFUNC_NEVER)) { + addbyte(0xC3); /*RET*/ + } + + if (params->alphaMode & (1 << 4)) { + addbyte(0x49); /*MOV R8, rgb565*/ + addbyte(0xb8); + addquad((uintptr_t) rgb565); + addbyte(0x8b); /*MOV EAX, state->x[EDI]*/ + addbyte(0x87); + if (params->col_tiled) + addlong(offsetof(voodoo_state_t, x_tiled)); + else + addlong(offsetof(voodoo_state_t, x)); + addbyte(0x48); /*MOV RBP, fb_mem*/ + addbyte(0x8b); + addbyte(0xaf); + addlong(offsetof(voodoo_state_t, fb_mem)); + addbyte(0x01); /*ADD EDX, EDX*/ + addbyte(0xd2); + addbyte(0x0f); /*MOVZX EAX, [RBP+RAX*2]*/ + addbyte(0xb7); + addbyte(0x44); + addbyte(0x45); + addbyte(0); + addbyte(0x66); /*PUNPCKLBW XMM0, XMM2*/ + addbyte(0x0f); + addbyte(0x60); + addbyte(0xc2); + addbyte(0x66); /*MOVD XMM4, rgb565[EAX*4]*/ + addbyte(0x41); + addbyte(0x0f); + addbyte(0x6e); + addbyte(0x24); + addbyte(0x80); + addbyte(0x66); /*PUNPCKLBW XMM4, XMM2*/ + addbyte(0x0f); + addbyte(0x60); + addbyte(0xe2); + addbyte(0xf3); /*MOV XMM6, XMM4*/ + addbyte(0x0f); + addbyte(0x7e); + addbyte(0xf4); + + switch (dest_afunc) { + case AFUNC_AZERO: + addbyte(0x66); /*PXOR XMM4, XMM4*/ + addbyte(0x0f); + addbyte(0xef); + addbyte(0xe4); + break; + case AFUNC_ASRC_ALPHA: + addbyte(0x66); /*PMULLW XMM4, R10(alookup)[EDX*8]*/ + addbyte(0x41); + addbyte(0x0f); + addbyte(0xd5); + addbyte(0x24); + addbyte(0xd2); + addbyte(0xf3); /*MOVQ XMM5, XMM4*/ + addbyte(0x0f); + addbyte(0x7e); + addbyte(0xec); + addbyte(0x66); /*PADDW XMM4, R10(alookup)[1*8]*/ addbyte(0x41); addbyte(0x0f); addbyte(0xfd); - addbyte(0xd8); - addbyte(0x66); /*PMULLW XMM0, XMM3*/ + addbyte(0x62); + addbyte(8 * 2); + addbyte(0x66); /*PSRLW XMM5, 8*/ addbyte(0x0f); + addbyte(0x71); addbyte(0xd5); - addbyte(0xc3); - addbyte(0x66); /*PMULHW XMM4, XMM3*/ - addbyte(0x0f); - addbyte(0xe5); - addbyte(0xe3); - addbyte(0x66); /*PUNPCKLWD XMM0, XMM4*/ - addbyte(0x0f); - addbyte(0x61); - addbyte(0xc4); - addbyte(0x66); /*PSRLD XMM0, 8*/ - addbyte(0x0f); - addbyte(0x72); - addbyte(0xe0); addbyte(8); - addbyte(0x66); /*PACKSSDW XMM0, XMM0*/ - addbyte(0x0f); - addbyte(0x6b); - addbyte(0xc0); - } - - if (cc_add == 1) - { - addbyte(0x66); /*PADDW XMM0, XMM1*/ + addbyte(0x66); /*PADDW XMM4, XMM5*/ addbyte(0x0f); addbyte(0xfd); - addbyte(0xc1); + addbyte(0xe5); + addbyte(0x66); /*PSRLW XMM4, 8*/ + addbyte(0x0f); + addbyte(0x71); + addbyte(0xd4); + addbyte(8); + break; + case AFUNC_A_COLOR: + addbyte(0x66); /*PMULLW XMM4, XMM0*/ + addbyte(0x0f); + addbyte(0xd5); + addbyte(0xe0); + addbyte(0xf3); /*MOVQ XMM5, XMM4*/ + addbyte(0x0f); + addbyte(0x7e); + addbyte(0xec); + addbyte(0x66); /*PADDW XMM4, R10(alookup)[1*8]*/ + addbyte(0x41); + addbyte(0x0f); + addbyte(0xfd); + addbyte(0x62); + addbyte(8 * 2); + addbyte(0x66); /*PSRLW XMM5, 8*/ + addbyte(0x0f); + addbyte(0x71); + addbyte(0xd5); + addbyte(8); + addbyte(0x66); /*PADDW XMM4, XMM5*/ + addbyte(0x0f); + addbyte(0xfd); + addbyte(0xe5); + addbyte(0x66); /*PSRLW XMM4, 8*/ + addbyte(0x0f); + addbyte(0x71); + addbyte(0xd4); + addbyte(8); + break; + case AFUNC_ADST_ALPHA: + break; + case AFUNC_AONE: + break; + case AFUNC_AOMSRC_ALPHA: + addbyte(0x66); /*PMULLW XMM4, R11(aminuslookup)[EDX*8]*/ + addbyte(0x41); + addbyte(0x0f); + addbyte(0xd5); + addbyte(0x24); + addbyte(0xd3); + addbyte(0xf3); /*MOVQ XMM5, XMM4*/ + addbyte(0x0f); + addbyte(0x7e); + addbyte(0xec); + addbyte(0x66); /*PADDW XMM4, R10(alookup)[1*8]*/ + addbyte(0x41); + addbyte(0x0f); + addbyte(0xfd); + addbyte(0x62); + addbyte(8 * 2); + addbyte(0x66); /*PSRLW XMM5, 8*/ + addbyte(0x0f); + addbyte(0x71); + addbyte(0xd5); + addbyte(8); + addbyte(0x66); /*PADDW XMM4, XMM5*/ + addbyte(0x0f); + addbyte(0xfd); + addbyte(0xe5); + addbyte(0x66); /*PSRLW XMM4, 8*/ + addbyte(0x0f); + addbyte(0x71); + addbyte(0xd4); + addbyte(8); + break; + case AFUNC_AOM_COLOR: + addbyte(0xf3); /*MOVQ XMM5, XMM9(xmm_ff_w)*/ + addbyte(0x41); + addbyte(0x0f); + addbyte(0x7e); + addbyte(0xe9); + addbyte(0x66); /*PSUBW XMM5, XMM0*/ + addbyte(0x0f); + addbyte(0xf9); + addbyte(0xe8); + addbyte(0x66); /*PMULLW XMM4, XMM5*/ + addbyte(0x0f); + addbyte(0xd5); + addbyte(0xe5); + addbyte(0xf3); /*MOVQ XMM5, XMM4*/ + addbyte(0x0f); + addbyte(0x7e); + addbyte(0xec); + addbyte(0x66); /*PADDW XMM4, alookup[1*8]*/ + addbyte(0x41); + addbyte(0x0f); + addbyte(0xfd); + addbyte(0x62); + addbyte(8 * 2); + addbyte(0x66); /*PSRLW XMM5, 8*/ + addbyte(0x0f); + addbyte(0x71); + addbyte(0xd5); + addbyte(8); + addbyte(0x66); /*PADDW XMM4, XMM5*/ + addbyte(0x0f); + addbyte(0xfd); + addbyte(0xe5); + addbyte(0x66); /*PSRLW XMM4, 8*/ + addbyte(0x0f); + addbyte(0x71); + addbyte(0xd4); + addbyte(8); + break; + case AFUNC_AOMDST_ALPHA: + addbyte(0x66); /*PXOR XMM4, XMM4*/ + addbyte(0x0f); + addbyte(0xef); + addbyte(0xe4); + break; + case AFUNC_ASATURATE: + addbyte(0x66); /*PMULLW XMM4, XMM11(minus_254)*/ + addbyte(0x41); + addbyte(0x0f); + addbyte(0xd5); + addbyte(0xe3); + addbyte(0xf3); /*MOVQ XMM5, XMM4*/ + addbyte(0x0f); + addbyte(0x7e); + addbyte(0xec); + addbyte(0x66); /*PADDW XMM4, alookup[1*8]*/ + addbyte(0x41); + addbyte(0x0f); + addbyte(0xfd); + addbyte(0x62); + addbyte(8 * 2); + addbyte(0x66); /*PSRLW XMM5, 8*/ + addbyte(0x0f); + addbyte(0x71); + addbyte(0xd5); + addbyte(8); + addbyte(0x66); /*PADDW XMM4, XMM5*/ + addbyte(0x0f); + addbyte(0xfd); + addbyte(0xe5); + addbyte(0x66); /*PSRLW XMM4, 8*/ + addbyte(0x0f); + addbyte(0x71); + addbyte(0xd4); + addbyte(8); } + switch (src_afunc) { + case AFUNC_AZERO: + addbyte(0x66); /*PXOR XMM0, XMM0*/ + addbyte(0x0f); + addbyte(0xef); + addbyte(0xc0); + break; + case AFUNC_ASRC_ALPHA: + addbyte(0x66); /*PMULLW XMM0, R10(alookup)[EDX*8]*/ + addbyte(0x41); + addbyte(0x0f); + addbyte(0xd5); + addbyte(0x04); + addbyte(0xd2); + addbyte(0xf3); /*MOVQ XMM5, XMM0*/ + addbyte(0x0f); + addbyte(0x7e); + addbyte(0xe8); + addbyte(0x66); /*PADDW XMM0, R10(alookup)[1*8]*/ + addbyte(0x41); + addbyte(0x0f); + addbyte(0xfd); + addbyte(0x42); + addbyte(8 * 2); + addbyte(0x66); /*PSRLW XMM5, 8*/ + addbyte(0x0f); + addbyte(0x71); + addbyte(0xd5); + addbyte(8); + addbyte(0x66); /*PADDW XMM0, XMM5*/ + addbyte(0x0f); + addbyte(0xfd); + addbyte(0xc5); + addbyte(0x66); /*PSRLW XMM0, 8*/ + addbyte(0x0f); + addbyte(0x71); + addbyte(0xd0); + addbyte(8); + break; + case AFUNC_A_COLOR: + addbyte(0x66); /*PMULLW XMM0, XMM6*/ + addbyte(0x0f); + addbyte(0xd5); + addbyte(0xc6); + addbyte(0xf3); /*MOVQ XMM5, XMM0*/ + addbyte(0x0f); + addbyte(0x7e); + addbyte(0xe8); + addbyte(0x66); /*PADDW XMM0, R10(alookup)[1*8]*/ + addbyte(0x41); + addbyte(0x0f); + addbyte(0xfd); + addbyte(0x42); + addbyte(8 * 2); + addbyte(0x66); /*PSRLW XMM5, 8*/ + addbyte(0x0f); + addbyte(0x71); + addbyte(0xd5); + addbyte(8); + addbyte(0x66); /*PADDW XMM0, XMM5*/ + addbyte(0x0f); + addbyte(0xfd); + addbyte(0xc5); + addbyte(0x66); /*PSRLW XMM0, 8*/ + addbyte(0x0f); + addbyte(0x71); + addbyte(0xd0); + addbyte(8); + break; + case AFUNC_ADST_ALPHA: + break; + case AFUNC_AONE: + break; + case AFUNC_AOMSRC_ALPHA: + addbyte(0x66); /*PMULLW XMM0, R11(aminuslookup)[EDX*8]*/ + addbyte(0x41); + addbyte(0x0f); + addbyte(0xd5); + addbyte(0x04); + addbyte(0xd3); + addbyte(0xf3); /*MOVQ XMM5, XMM0*/ + addbyte(0x0f); + addbyte(0x7e); + addbyte(0xe8); + addbyte(0x66); /*PADDW XMM0, alookup[1*8]*/ + addbyte(0x41); + addbyte(0x0f); + addbyte(0xfd); + addbyte(0x42); + addbyte(8 * 2); + addbyte(0x66); /*PSRLW XMM5, 8*/ + addbyte(0x0f); + addbyte(0x71); + addbyte(0xd5); + addbyte(8); + addbyte(0x66); /*PADDW XMM0, XMM5*/ + addbyte(0x0f); + addbyte(0xfd); + addbyte(0xc5); + addbyte(0x66); /*PSRLW XMM0, 8*/ + addbyte(0x0f); + addbyte(0x71); + addbyte(0xd0); + addbyte(8); + break; + case AFUNC_AOM_COLOR: + addbyte(0xf3); /*MOVQ XMM5, XMM9(xmm_ff_w)*/ + addbyte(0x41); + addbyte(0x0f); + addbyte(0x7e); + addbyte(0xe9); + addbyte(0x66); /*PSUBW XMM5, XMM6*/ + addbyte(0x0f); + addbyte(0xf9); + addbyte(0xee); + addbyte(0x66); /*PMULLW XMM0, XMM5*/ + addbyte(0x0f); + addbyte(0xd5); + addbyte(0xc5); + addbyte(0xf3); /*MOVQ XMM5, XMM0*/ + addbyte(0x0f); + addbyte(0x7e); + addbyte(0xe8); + addbyte(0x66); /*PADDW XMM0, alookup[1*8]*/ + addbyte(0x41); + addbyte(0x0f); + addbyte(0xfd); + addbyte(0x42); + addbyte(8 * 2); + addbyte(0x66); /*PSRLW XMM5, 8*/ + addbyte(0x0f); + addbyte(0x71); + addbyte(0xd5); + addbyte(8); + addbyte(0x66); /*PADDW XMM0, XMM5*/ + addbyte(0x0f); + addbyte(0xfd); + addbyte(0xc5); + addbyte(0x66); /*PSRLW XMM0, 8*/ + addbyte(0x0f); + addbyte(0x71); + addbyte(0xd0); + addbyte(8); + break; + case AFUNC_AOMDST_ALPHA: + addbyte(0x66); /*PXOR XMM0, XMM0*/ + addbyte(0x0f); + addbyte(0xef); + addbyte(0xc0); + break; + case AFUNC_ACOLORBEFOREFOG: + break; + } + + addbyte(0x66); /*PADDW XMM0, XMM4*/ + addbyte(0x0f); + addbyte(0xfd); + addbyte(0xc4); + addbyte(0x66); /*PACKUSWB XMM0, XMM0*/ addbyte(0x0f); addbyte(0x67); addbyte(0xc0); + } - if (cc_invert_output) - { - addbyte(0x66); /*PXOR XMM0, XMM10(xmm_ff_b)*/ - addbyte(0x41); - addbyte(0x0f); - addbyte(0xef); - addbyte(0xc2); - } + addbyte(0x8b); /*MOV EDX, state->x[EDI]*/ + addbyte(0x97); + if (params->col_tiled) + addlong(offsetof(voodoo_state_t, x_tiled)); + else + addlong(offsetof(voodoo_state_t, x)); - if (params->fogMode & FOG_ENABLE) - { - if (params->fogMode & FOG_CONSTANT) - { - addbyte(0x66); /*MOVD XMM3, params->fogColor[ESI]*/ - addbyte(0x0f); - addbyte(0x6e); - addbyte(0x9e); - addlong(offsetof(voodoo_params_t, fogColor)); - addbyte(0x66); /*PADDUSB XMM0, XMM3*/ - addbyte(0x0f); - addbyte(0xdc); - addbyte(0xc3); - } - else - { - addbyte(0x66); /*PUNPCKLBW XMM0, XMM2*/ - addbyte(0x0f); - addbyte(0x60); - addbyte(0xc2); + addbyte(0x66); /*MOV EAX, XMM0*/ + addbyte(0x0f); + addbyte(0x7e); + addbyte(0xc0); - if (!(params->fogMode & FOG_ADD)) - { - addbyte(0x66); /*MOVD XMM3, params->fogColor[ESI]*/ - addbyte(0x0f); - addbyte(0x6e); - addbyte(0x9e); - addlong(offsetof(voodoo_params_t, fogColor)); - addbyte(0x66); /*PUNPCKLBW XMM3, XMM2*/ - addbyte(0x0f); - addbyte(0x60); - addbyte(0xda); - } - else - { - addbyte(0x66); /*PXOR XMM3, XMM3*/ - addbyte(0x0f); - addbyte(0xef); - addbyte(0xdb); - } - - if (!(params->fogMode & FOG_MULT)) - { - addbyte(0x66); /*PSUBW XMM3, XMM0*/ - addbyte(0x0f); - addbyte(0xf9); - addbyte(0xd8); - } - - /*Divide by 2 to prevent overflow on multiply*/ - addbyte(0x66); /*PSRAW XMM3, 1*/ - addbyte(0x0f); - addbyte(0x71); - addbyte(0xe3); - addbyte(1); - - switch (params->fogMode & (FOG_Z|FOG_ALPHA)) - { - case 0: - addbyte(0x8b); /*MOV EBX, state->w_depth[EDI]*/ - addbyte(0x9f); - addlong(offsetof(voodoo_state_t, w_depth)); - addbyte(0x89); /*MOV EAX, EBX*/ - addbyte(0xd8); - addbyte(0xc1); /*SHR EBX, 10*/ - addbyte(0xeb); - addbyte(10); - addbyte(0xc1); /*SHR EAX, 2*/ - addbyte(0xe8); - addbyte(2); - addbyte(0x83); /*AND EBX, 0x3f*/ - addbyte(0xe3); - addbyte(0x3f); - addbyte(0x25); /*AND EAX, 0xff*/ - addlong(0xff); - addbyte(0xf6); /*MUL params->fogTable+1[ESI+EBX*2]*/ - addbyte(0xa4); - addbyte(0x5e); - addlong(offsetof(voodoo_params_t, fogTable)+1); - addbyte(0x0f); /*MOVZX EBX, params->fogTable[ESI+EBX*2]*/ - addbyte(0xb6); - addbyte(0x9c); - addbyte(0x5e); - addlong(offsetof(voodoo_params_t, fogTable)); - addbyte(0xc1); /*SHR EAX, 10*/ - addbyte(0xe8); - addbyte(10); - addbyte(0x01); /*ADD EAX, EBX*/ - addbyte(0xd8); -/* int fog_idx = (w_depth >> 10) & 0x3f; - - fog_a = params->fogTable[fog_idx].fog; - fog_a += (params->fogTable[fog_idx].dfog * ((w_depth >> 2) & 0xff)) >> 10;*/ - break; - - case FOG_Z: - addbyte(0x8b); /*MOV EAX, state->z[EDI]*/ - addbyte(0x87); - addlong(offsetof(voodoo_state_t, z)); - addbyte(0xc1); /*SHR EAX, 12*/ - addbyte(0xe8); - addbyte(12); - addbyte(0x25); /*AND EAX, 0xff*/ - addlong(0xff); -// fog_a = (z >> 20) & 0xff; - break; - - case FOG_ALPHA: - addbyte(0x8b); /*MOV EAX, state->ia[EDI]*/ - addbyte(0x87); - addlong(offsetof(voodoo_state_t, ia)); - addbyte(0x31); /*XOR EBX, EBX*/ - addbyte(0xdb); - addbyte(0xc1); /*SAR EAX, 12*/ - addbyte(0xf8); - addbyte(12); - addbyte(0x0f); /*CMOVS EAX, EBX*/ - addbyte(0x48); - addbyte(0xc3); - addbyte(0xbb); /*MOV EBX, 0xff*/ - addlong(0xff); - addbyte(0x3d); /*CMP EAX, 0xff*/ - addlong(0xff); - addbyte(0x0f); /*CMOVAE EAX, EBX*/ - addbyte(0x43); - addbyte(0xc3); -// fog_a = CLAMP(ia >> 12); - break; - - case FOG_W: - addbyte(0x8b); /*MOV EAX, state->w[EDI]+4*/ - addbyte(0x87); - addlong(offsetof(voodoo_state_t, w)+4); - addbyte(0x31); /*XOR EBX, EBX*/ - addbyte(0xdb); - addbyte(0x09); /*OR EAX, EAX*/ - addbyte(0xc0); - addbyte(0x0f); /*CMOVS EAX, EBX*/ - addbyte(0x48); - addbyte(0xc3); - addbyte(0xbb); /*MOV EBX, 0xff*/ - addlong(0xff); - addbyte(0x3d); /*CMP EAX, 0xff*/ - addlong(0xff); - addbyte(0x0f); /*CMOVAE EAX, EBX*/ - addbyte(0x43); - addbyte(0xc3); -// fog_a = CLAMP(w >> 32); - break; - } - addbyte(0x01); /*ADD EAX, EAX*/ - addbyte(0xc0); - - addbyte(0x66); /*PMULLW XMM3, alookup+4[EAX*8]*/ - addbyte(0x41); - addbyte(0x0f); - addbyte(0xd5); - addbyte(0x5c); - addbyte(0xc2); - addbyte(16); - addbyte(0x66); /*PSRAW XMM3, 7*/ - addbyte(0x0f); - addbyte(0x71); - addbyte(0xe3); - addbyte(7); - - if (params->fogMode & FOG_MULT) - { - addbyte(0xf3); /*MOV XMM0, XMM3*/ - addbyte(0x0f); - addbyte(0x7e); - addbyte(0xc3); - } - else - { - addbyte(0x66); /*PADDW XMM0, XMM3*/ - addbyte(0x0f); - addbyte(0xfd); - addbyte(0xc3); - } - addbyte(0x66); /*PACKUSWB XMM0, XMM0*/ - addbyte(0x0f); - addbyte(0x67); - addbyte(0xc0); - } - } - - if ((params->alphaMode & 1) && (alpha_func != AFUNC_NEVER) && (alpha_func != AFUNC_ALWAYS)) - { - addbyte(0x0f); /*MOVZX ECX, params->alphaMode+3*/ - addbyte(0xb6); - addbyte(0x8e); - addlong(offsetof(voodoo_params_t, alphaMode) + 3); - addbyte(0x39); /*CMP EDX, ECX*/ - addbyte(0xca); - - switch (alpha_func) - { - case AFUNC_LESSTHAN: - addbyte(0x0f); /*JAE skip*/ - addbyte(0x83); - a_skip_pos = block_pos; - addlong(0); - break; - case AFUNC_EQUAL: - addbyte(0x0f); /*JNE skip*/ - addbyte(0x85); - a_skip_pos = block_pos; - addlong(0); - break; - case AFUNC_LESSTHANEQUAL: - addbyte(0x0f); /*JA skip*/ - addbyte(0x87); - a_skip_pos = block_pos; - addlong(0); - break; - case AFUNC_GREATERTHAN: - addbyte(0x0f); /*JBE skip*/ - addbyte(0x86); - a_skip_pos = block_pos; - addlong(0); - break; - case AFUNC_NOTEQUAL: - addbyte(0x0f); /*JE skip*/ - addbyte(0x84); - a_skip_pos = block_pos; - addlong(0); - break; - case AFUNC_GREATERTHANEQUAL: - addbyte(0x0f); /*JB skip*/ - addbyte(0x82); - a_skip_pos = block_pos; - addlong(0); - break; - } - } - else if ((params->alphaMode & 1) && (alpha_func == AFUNC_NEVER)) - { - addbyte(0xC3); /*RET*/ - } - - if (params->alphaMode & (1 << 4)) - { - addbyte(0x49); /*MOV R8, rgb565*/ - addbyte(0xb8); - addquad((uintptr_t)rgb565); - addbyte(0x8b); /*MOV EAX, state->x[EDI]*/ - addbyte(0x87); - if (params->col_tiled) - addlong(offsetof(voodoo_state_t, x_tiled)); - else - addlong(offsetof(voodoo_state_t, x)); - addbyte(0x48); /*MOV RBP, fb_mem*/ - addbyte(0x8b); - addbyte(0xaf); - addlong(offsetof(voodoo_state_t, fb_mem)); - addbyte(0x01); /*ADD EDX, EDX*/ - addbyte(0xd2); - addbyte(0x0f); /*MOVZX EAX, [RBP+RAX*2]*/ - addbyte(0xb7); - addbyte(0x44); - addbyte(0x45); - addbyte(0); - addbyte(0x66); /*PUNPCKLBW XMM0, XMM2*/ - addbyte(0x0f); - addbyte(0x60); - addbyte(0xc2); - addbyte(0x66); /*MOVD XMM4, rgb565[EAX*4]*/ - addbyte(0x41); - addbyte(0x0f); - addbyte(0x6e); - addbyte(0x24); - addbyte(0x80); - addbyte(0x66); /*PUNPCKLBW XMM4, XMM2*/ - addbyte(0x0f); - addbyte(0x60); + if (params->fbzMode & FBZ_RGB_WMASK) { + if (dither) { + addbyte(0x49); /*MOV R8, dither_rb*/ + addbyte(0xb8); + addquad(dither2x2 ? (uintptr_t) dither_rb2x2 : (uintptr_t) dither_rb); + addbyte(0x4c); /*MOV ESI, real_y (R14)*/ + addbyte(0x89); + addbyte(0xf6); + addbyte(0x0f); /*MOVZX EBX, AH*/ /*G*/ + addbyte(0xb6); + addbyte(0xdc); + if (dither2x2) { + addbyte(0x83); /*AND EDX, 1*/ addbyte(0xe2); - addbyte(0xf3); /*MOV XMM6, XMM4*/ - addbyte(0x0f); - addbyte(0x7e); - addbyte(0xf4); - - switch (dest_afunc) - { - case AFUNC_AZERO: - addbyte(0x66); /*PXOR XMM4, XMM4*/ - addbyte(0x0f); - addbyte(0xef); - addbyte(0xe4); - break; - case AFUNC_ASRC_ALPHA: - addbyte(0x66); /*PMULLW XMM4, R10(alookup)[EDX*8]*/ - addbyte(0x41); - addbyte(0x0f); - addbyte(0xd5); - addbyte(0x24); - addbyte(0xd2); - addbyte(0xf3); /*MOVQ XMM5, XMM4*/ - addbyte(0x0f); - addbyte(0x7e); - addbyte(0xec); - addbyte(0x66); /*PADDW XMM4, R10(alookup)[1*8]*/ - addbyte(0x41); - addbyte(0x0f); - addbyte(0xfd); - addbyte(0x62); - addbyte(8*2); - addbyte(0x66); /*PSRLW XMM5, 8*/ - addbyte(0x0f); - addbyte(0x71); - addbyte(0xd5); - addbyte(8); - addbyte(0x66); /*PADDW XMM4, XMM5*/ - addbyte(0x0f); - addbyte(0xfd); - addbyte(0xe5); - addbyte(0x66); /*PSRLW XMM4, 8*/ - addbyte(0x0f); - addbyte(0x71); - addbyte(0xd4); - addbyte(8); - break; - case AFUNC_A_COLOR: - addbyte(0x66); /*PMULLW XMM4, XMM0*/ - addbyte(0x0f); - addbyte(0xd5); - addbyte(0xe0); - addbyte(0xf3); /*MOVQ XMM5, XMM4*/ - addbyte(0x0f); - addbyte(0x7e); - addbyte(0xec); - addbyte(0x66); /*PADDW XMM4, R10(alookup)[1*8]*/ - addbyte(0x41); - addbyte(0x0f); - addbyte(0xfd); - addbyte(0x62); - addbyte(8*2); - addbyte(0x66); /*PSRLW XMM5, 8*/ - addbyte(0x0f); - addbyte(0x71); - addbyte(0xd5); - addbyte(8); - addbyte(0x66); /*PADDW XMM4, XMM5*/ - addbyte(0x0f); - addbyte(0xfd); - addbyte(0xe5); - addbyte(0x66); /*PSRLW XMM4, 8*/ - addbyte(0x0f); - addbyte(0x71); - addbyte(0xd4); - addbyte(8); - break; - case AFUNC_ADST_ALPHA: - break; - case AFUNC_AONE: - break; - case AFUNC_AOMSRC_ALPHA: - addbyte(0x66); /*PMULLW XMM4, R11(aminuslookup)[EDX*8]*/ - addbyte(0x41); - addbyte(0x0f); - addbyte(0xd5); - addbyte(0x24); - addbyte(0xd3); - addbyte(0xf3); /*MOVQ XMM5, XMM4*/ - addbyte(0x0f); - addbyte(0x7e); - addbyte(0xec); - addbyte(0x66); /*PADDW XMM4, R10(alookup)[1*8]*/ - addbyte(0x41); - addbyte(0x0f); - addbyte(0xfd); - addbyte(0x62); - addbyte(8*2); - addbyte(0x66); /*PSRLW XMM5, 8*/ - addbyte(0x0f); - addbyte(0x71); - addbyte(0xd5); - addbyte(8); - addbyte(0x66); /*PADDW XMM4, XMM5*/ - addbyte(0x0f); - addbyte(0xfd); - addbyte(0xe5); - addbyte(0x66); /*PSRLW XMM4, 8*/ - addbyte(0x0f); - addbyte(0x71); - addbyte(0xd4); - addbyte(8); - break; - case AFUNC_AOM_COLOR: - addbyte(0xf3); /*MOVQ XMM5, XMM9(xmm_ff_w)*/ - addbyte(0x41); - addbyte(0x0f); - addbyte(0x7e); - addbyte(0xe9); - addbyte(0x66); /*PSUBW XMM5, XMM0*/ - addbyte(0x0f); - addbyte(0xf9); - addbyte(0xe8); - addbyte(0x66); /*PMULLW XMM4, XMM5*/ - addbyte(0x0f); - addbyte(0xd5); - addbyte(0xe5); - addbyte(0xf3); /*MOVQ XMM5, XMM4*/ - addbyte(0x0f); - addbyte(0x7e); - addbyte(0xec); - addbyte(0x66); /*PADDW XMM4, alookup[1*8]*/ - addbyte(0x41); - addbyte(0x0f); - addbyte(0xfd); - addbyte(0x62); - addbyte(8*2); - addbyte(0x66); /*PSRLW XMM5, 8*/ - addbyte(0x0f); - addbyte(0x71); - addbyte(0xd5); - addbyte(8); - addbyte(0x66); /*PADDW XMM4, XMM5*/ - addbyte(0x0f); - addbyte(0xfd); - addbyte(0xe5); - addbyte(0x66); /*PSRLW XMM4, 8*/ - addbyte(0x0f); - addbyte(0x71); - addbyte(0xd4); - addbyte(8); - break; - case AFUNC_AOMDST_ALPHA: - addbyte(0x66); /*PXOR XMM4, XMM4*/ - addbyte(0x0f); - addbyte(0xef); - addbyte(0xe4); - break; - case AFUNC_ASATURATE: - addbyte(0x66); /*PMULLW XMM4, XMM11(minus_254)*/ - addbyte(0x41); - addbyte(0x0f); - addbyte(0xd5); - addbyte(0xe3); - addbyte(0xf3); /*MOVQ XMM5, XMM4*/ - addbyte(0x0f); - addbyte(0x7e); - addbyte(0xec); - addbyte(0x66); /*PADDW XMM4, alookup[1*8]*/ - addbyte(0x41); - addbyte(0x0f); - addbyte(0xfd); - addbyte(0x62); - addbyte(8*2); - addbyte(0x66); /*PSRLW XMM5, 8*/ - addbyte(0x0f); - addbyte(0x71); - addbyte(0xd5); - addbyte(8); - addbyte(0x66); /*PADDW XMM4, XMM5*/ - addbyte(0x0f); - addbyte(0xfd); - addbyte(0xe5); - addbyte(0x66); /*PSRLW XMM4, 8*/ - addbyte(0x0f); - addbyte(0x71); - addbyte(0xd4); - addbyte(8); - } - - switch (src_afunc) - { - case AFUNC_AZERO: - addbyte(0x66); /*PXOR XMM0, XMM0*/ - addbyte(0x0f); - addbyte(0xef); - addbyte(0xc0); - break; - case AFUNC_ASRC_ALPHA: - addbyte(0x66); /*PMULLW XMM0, R10(alookup)[EDX*8]*/ - addbyte(0x41); - addbyte(0x0f); - addbyte(0xd5); - addbyte(0x04); - addbyte(0xd2); - addbyte(0xf3); /*MOVQ XMM5, XMM0*/ - addbyte(0x0f); - addbyte(0x7e); - addbyte(0xe8); - addbyte(0x66); /*PADDW XMM0, R10(alookup)[1*8]*/ - addbyte(0x41); - addbyte(0x0f); - addbyte(0xfd); - addbyte(0x42); - addbyte(8*2); - addbyte(0x66); /*PSRLW XMM5, 8*/ - addbyte(0x0f); - addbyte(0x71); - addbyte(0xd5); - addbyte(8); - addbyte(0x66); /*PADDW XMM0, XMM5*/ - addbyte(0x0f); - addbyte(0xfd); - addbyte(0xc5); - addbyte(0x66); /*PSRLW XMM0, 8*/ - addbyte(0x0f); - addbyte(0x71); - addbyte(0xd0); - addbyte(8); - break; - case AFUNC_A_COLOR: - addbyte(0x66); /*PMULLW XMM0, XMM6*/ - addbyte(0x0f); - addbyte(0xd5); - addbyte(0xc6); - addbyte(0xf3); /*MOVQ XMM5, XMM0*/ - addbyte(0x0f); - addbyte(0x7e); - addbyte(0xe8); - addbyte(0x66); /*PADDW XMM0, R10(alookup)[1*8]*/ - addbyte(0x41); - addbyte(0x0f); - addbyte(0xfd); - addbyte(0x42); - addbyte(8*2); - addbyte(0x66); /*PSRLW XMM5, 8*/ - addbyte(0x0f); - addbyte(0x71); - addbyte(0xd5); - addbyte(8); - addbyte(0x66); /*PADDW XMM0, XMM5*/ - addbyte(0x0f); - addbyte(0xfd); - addbyte(0xc5); - addbyte(0x66); /*PSRLW XMM0, 8*/ - addbyte(0x0f); - addbyte(0x71); - addbyte(0xd0); - addbyte(8); - break; - case AFUNC_ADST_ALPHA: - break; - case AFUNC_AONE: - break; - case AFUNC_AOMSRC_ALPHA: - addbyte(0x66); /*PMULLW XMM0, R11(aminuslookup)[EDX*8]*/ - addbyte(0x41); - addbyte(0x0f); - addbyte(0xd5); - addbyte(0x04); - addbyte(0xd3); - addbyte(0xf3); /*MOVQ XMM5, XMM0*/ - addbyte(0x0f); - addbyte(0x7e); - addbyte(0xe8); - addbyte(0x66); /*PADDW XMM0, alookup[1*8]*/ - addbyte(0x41); - addbyte(0x0f); - addbyte(0xfd); - addbyte(0x42); - addbyte(8*2); - addbyte(0x66); /*PSRLW XMM5, 8*/ - addbyte(0x0f); - addbyte(0x71); - addbyte(0xd5); - addbyte(8); - addbyte(0x66); /*PADDW XMM0, XMM5*/ - addbyte(0x0f); - addbyte(0xfd); - addbyte(0xc5); - addbyte(0x66); /*PSRLW XMM0, 8*/ - addbyte(0x0f); - addbyte(0x71); - addbyte(0xd0); - addbyte(8); - break; - case AFUNC_AOM_COLOR: - addbyte(0xf3); /*MOVQ XMM5, XMM9(xmm_ff_w)*/ - addbyte(0x41); - addbyte(0x0f); - addbyte(0x7e); - addbyte(0xe9); - addbyte(0x66); /*PSUBW XMM5, XMM6*/ - addbyte(0x0f); - addbyte(0xf9); - addbyte(0xee); - addbyte(0x66); /*PMULLW XMM0, XMM5*/ - addbyte(0x0f); - addbyte(0xd5); - addbyte(0xc5); - addbyte(0xf3); /*MOVQ XMM5, XMM0*/ - addbyte(0x0f); - addbyte(0x7e); - addbyte(0xe8); - addbyte(0x66); /*PADDW XMM0, alookup[1*8]*/ - addbyte(0x41); - addbyte(0x0f); - addbyte(0xfd); - addbyte(0x42); - addbyte(8*2); - addbyte(0x66); /*PSRLW XMM5, 8*/ - addbyte(0x0f); - addbyte(0x71); - addbyte(0xd5); - addbyte(8); - addbyte(0x66); /*PADDW XMM0, XMM5*/ - addbyte(0x0f); - addbyte(0xfd); - addbyte(0xc5); - addbyte(0x66); /*PSRLW XMM0, 8*/ - addbyte(0x0f); - addbyte(0x71); - addbyte(0xd0); - addbyte(8); - break; - case AFUNC_AOMDST_ALPHA: - addbyte(0x66); /*PXOR XMM0, XMM0*/ - addbyte(0x0f); - addbyte(0xef); - addbyte(0xc0); - break; - case AFUNC_ACOLORBEFOREFOG: - break; - } - - addbyte(0x66); /*PADDW XMM0, XMM4*/ - addbyte(0x0f); - addbyte(0xfd); - addbyte(0xc4); - - addbyte(0x66); /*PACKUSWB XMM0, XMM0*/ - addbyte(0x0f); - addbyte(0x67); - addbyte(0xc0); + addbyte(1); + addbyte(0x83); /*AND ESI, 1*/ + addbyte(0xe6); + addbyte(1); + addbyte(0xc1); /*SHL EBX, 2*/ + addbyte(0xe3); + addbyte(2); + } else { + addbyte(0x83); /*AND EDX, 3*/ + addbyte(0xe2); + addbyte(3); + addbyte(0x83); /*AND ESI, 3*/ + addbyte(0xe6); + addbyte(3); + addbyte(0xc1); /*SHL EBX, 4*/ + addbyte(0xe3); + addbyte(4); + } + addbyte(0x0f); /*MOVZX ECX, AL*/ /*R*/ + addbyte(0xb6); + addbyte(0xc8); + if (dither2x2) { + addbyte(0xc1); /*SHR EAX, 14*/ + addbyte(0xe8); + addbyte(14); + addbyte(0x8d); /*LEA ESI, RDX+RSI*2*/ + addbyte(0x34); + addbyte(0x72); + } else { + addbyte(0xc1); /*SHR EAX, 12*/ + addbyte(0xe8); + addbyte(12); + addbyte(0x8d); /*LEA ESI, RDX+RSI*4*/ + addbyte(0x34); + addbyte(0xb2); + } + addbyte(0x8b); /*MOV EDX, state->x[EDI]*/ + addbyte(0x97); + if (voodoo->col_tiled) + addlong(offsetof(voodoo_state_t, x_tiled)); + else + addlong(offsetof(voodoo_state_t, x)); + addbyte(0x4c); /*ADD RSI, R8*/ + addbyte(0x01); + addbyte(0xc6); + if (dither2x2) { + addbyte(0xc1); /*SHL ECX, 2*/ + addbyte(0xe1); + addbyte(2); + addbyte(0x25); /*AND EAX, 0x3fc*/ /*B*/ + addlong(0x3fc); + } else { + addbyte(0xc1); /*SHL ECX, 4*/ + addbyte(0xe1); + addbyte(4); + addbyte(0x25); /*AND EAX, 0xff0*/ /*B*/ + addlong(0xff0); + } + addbyte(0x0f); /*MOVZX EBX, dither_g[EBX+ESI]*/ + addbyte(0xb6); + addbyte(0x9c); + addbyte(0x1e); + addlong(dither2x2 ? ((uintptr_t) dither_g2x2 - (uintptr_t) dither_rb2x2) : ((uintptr_t) dither_g - (uintptr_t) dither_rb)); + addbyte(0x0f); /*MOVZX ECX, dither_rb[RCX+RSI]*/ + addbyte(0xb6); + addbyte(0x0c); + addbyte(0x0e); + addbyte(0x0f); /*MOVZX EAX, dither_rb[RAX+RSI]*/ + addbyte(0xb6); + addbyte(0x04); + addbyte(0x06); + addbyte(0xc1); /*SHL EBX, 5*/ + addbyte(0xe3); + addbyte(5); + addbyte(0xc1); /*SHL EAX, 11*/ + addbyte(0xe0); + addbyte(11); + addbyte(0x09); /*OR EAX, EBX*/ + addbyte(0xd8); + addbyte(0x09); /*OR EAX, ECX*/ + addbyte(0xc8); + } else { + addbyte(0x89); /*MOV EBX, EAX*/ + addbyte(0xc3); + addbyte(0x0f); /*MOVZX ECX, AH*/ + addbyte(0xb6); + addbyte(0xcc); + addbyte(0xc1); /*SHR EAX, 3*/ + addbyte(0xe8); + addbyte(3); + addbyte(0xc1); /*SHR EBX, 8*/ + addbyte(0xeb); + addbyte(8); + addbyte(0xc1); /*SHL ECX, 3*/ + addbyte(0xe1); + addbyte(3); + addbyte(0x81); /*AND EAX, 0x001f*/ + addbyte(0xe0); + addlong(0x001f); + addbyte(0x81); /*AND EBX, 0xf800*/ + addbyte(0xe3); + addlong(0xf800); + addbyte(0x81); /*AND ECX, 0x07e0*/ + addbyte(0xe1); + addlong(0x07e0); + addbyte(0x09); /*OR EAX, EBX*/ + addbyte(0xd8); + addbyte(0x09); /*OR EAX, ECX*/ + addbyte(0xc8); } + addbyte(0x48); /*MOV RSI, fb_mem*/ + addbyte(0x8b); + addbyte(0xb7); + addlong(offsetof(voodoo_state_t, fb_mem)); + addbyte(0x66); /*MOV [ESI+EDX*2], AX*/ + addbyte(0x89); + addbyte(0x04); + addbyte(0x56); + } + if ((params->fbzMode & (FBZ_DEPTH_WMASK | FBZ_DEPTH_ENABLE)) == (FBZ_DEPTH_WMASK | FBZ_DEPTH_ENABLE)) { addbyte(0x8b); /*MOV EDX, state->x[EDI]*/ addbyte(0x97); - if (params->col_tiled) - addlong(offsetof(voodoo_state_t, x_tiled)); + if (params->aux_tiled) + addlong(offsetof(voodoo_state_t, x_tiled)); else - addlong(offsetof(voodoo_state_t, x)); - - addbyte(0x66); /*MOV EAX, XMM0*/ - addbyte(0x0f); - addbyte(0x7e); - addbyte(0xc0); - - if (params->fbzMode & FBZ_RGB_WMASK) - { - if (dither) - { - addbyte(0x49); /*MOV R8, dither_rb*/ - addbyte(0xb8); - addquad(dither2x2 ? (uintptr_t)dither_rb2x2 : (uintptr_t)dither_rb); - addbyte(0x4c); /*MOV ESI, real_y (R14)*/ - addbyte(0x89); - addbyte(0xf6); - addbyte(0x0f); /*MOVZX EBX, AH*/ /*G*/ - addbyte(0xb6); - addbyte(0xdc); - if (dither2x2) - { - addbyte(0x83); /*AND EDX, 1*/ - addbyte(0xe2); - addbyte(1); - addbyte(0x83); /*AND ESI, 1*/ - addbyte(0xe6); - addbyte(1); - addbyte(0xc1); /*SHL EBX, 2*/ - addbyte(0xe3); - addbyte(2); - } - else - { - addbyte(0x83); /*AND EDX, 3*/ - addbyte(0xe2); - addbyte(3); - addbyte(0x83); /*AND ESI, 3*/ - addbyte(0xe6); - addbyte(3); - addbyte(0xc1); /*SHL EBX, 4*/ - addbyte(0xe3); - addbyte(4); - } - addbyte(0x0f); /*MOVZX ECX, AL*/ /*R*/ - addbyte(0xb6); - addbyte(0xc8); - if (dither2x2) - { - addbyte(0xc1); /*SHR EAX, 14*/ - addbyte(0xe8); - addbyte(14); - addbyte(0x8d); /*LEA ESI, RDX+RSI*2*/ - addbyte(0x34); - addbyte(0x72); - } - else - { - addbyte(0xc1); /*SHR EAX, 12*/ - addbyte(0xe8); - addbyte(12); - addbyte(0x8d); /*LEA ESI, RDX+RSI*4*/ - addbyte(0x34); - addbyte(0xb2); - } - addbyte(0x8b); /*MOV EDX, state->x[EDI]*/ - addbyte(0x97); - if (voodoo->col_tiled) - addlong(offsetof(voodoo_state_t, x_tiled)); - else - addlong(offsetof(voodoo_state_t, x)); - addbyte(0x4c); /*ADD RSI, R8*/ - addbyte(0x01); - addbyte(0xc6); - if (dither2x2) - { - addbyte(0xc1); /*SHL ECX, 2*/ - addbyte(0xe1); - addbyte(2); - addbyte(0x25); /*AND EAX, 0x3fc*/ /*B*/ - addlong(0x3fc); - } - else - { - addbyte(0xc1); /*SHL ECX, 4*/ - addbyte(0xe1); - addbyte(4); - addbyte(0x25); /*AND EAX, 0xff0*/ /*B*/ - addlong(0xff0); - } - addbyte(0x0f); /*MOVZX EBX, dither_g[EBX+ESI]*/ - addbyte(0xb6); - addbyte(0x9c); - addbyte(0x1e); - addlong(dither2x2 ? ((uintptr_t)dither_g2x2 - (uintptr_t)dither_rb2x2) : ((uintptr_t)dither_g - (uintptr_t)dither_rb)); - addbyte(0x0f); /*MOVZX ECX, dither_rb[RCX+RSI]*/ - addbyte(0xb6); - addbyte(0x0c); - addbyte(0x0e); - addbyte(0x0f); /*MOVZX EAX, dither_rb[RAX+RSI]*/ - addbyte(0xb6); - addbyte(0x04); - addbyte(0x06); - addbyte(0xc1); /*SHL EBX, 5*/ - addbyte(0xe3); - addbyte(5); - addbyte(0xc1); /*SHL EAX, 11*/ - addbyte(0xe0); - addbyte(11); - addbyte(0x09); /*OR EAX, EBX*/ - addbyte(0xd8); - addbyte(0x09); /*OR EAX, ECX*/ - addbyte(0xc8); - } - else - { - addbyte(0x89); /*MOV EBX, EAX*/ - addbyte(0xc3); - addbyte(0x0f); /*MOVZX ECX, AH*/ - addbyte(0xb6); - addbyte(0xcc); - addbyte(0xc1); /*SHR EAX, 3*/ - addbyte(0xe8); - addbyte(3); - addbyte(0xc1); /*SHR EBX, 8*/ - addbyte(0xeb); - addbyte(8); - addbyte(0xc1); /*SHL ECX, 3*/ - addbyte(0xe1); - addbyte(3); - addbyte(0x81); /*AND EAX, 0x001f*/ - addbyte(0xe0); - addlong(0x001f); - addbyte(0x81); /*AND EBX, 0xf800*/ - addbyte(0xe3); - addlong(0xf800); - addbyte(0x81); /*AND ECX, 0x07e0*/ - addbyte(0xe1); - addlong(0x07e0); - addbyte(0x09); /*OR EAX, EBX*/ - addbyte(0xd8); - addbyte(0x09); /*OR EAX, ECX*/ - addbyte(0xc8); - } - addbyte(0x48); /*MOV RSI, fb_mem*/ - addbyte(0x8b); - addbyte(0xb7); - addlong(offsetof(voodoo_state_t, fb_mem)); - addbyte(0x66); /*MOV [ESI+EDX*2], AX*/ - addbyte(0x89); - addbyte(0x04); - addbyte(0x56); - } - - if ((params->fbzMode & (FBZ_DEPTH_WMASK | FBZ_DEPTH_ENABLE)) == (FBZ_DEPTH_WMASK | FBZ_DEPTH_ENABLE)) - { - addbyte(0x8b); /*MOV EDX, state->x[EDI]*/ - addbyte(0x97); - if (params->aux_tiled) - addlong(offsetof(voodoo_state_t, x_tiled)); - else - addlong(offsetof(voodoo_state_t, x)); - addbyte(0x66); /*MOV AX, new_depth*/ - addbyte(0x8b); - addbyte(0x87); - addlong(offsetof(voodoo_state_t, new_depth)); - addbyte(0x48); /*MOV RSI, aux_mem*/ - addbyte(0x8b); - addbyte(0xb7); - addlong(offsetof(voodoo_state_t, aux_mem)); - addbyte(0x66); /*MOV [ESI+EDX*2], AX*/ - addbyte(0x89); - addbyte(0x04); - addbyte(0x56); - } - - if (z_skip_pos) - *(uint32_t *)&code_block[z_skip_pos] = (block_pos - z_skip_pos) - 4; - if (a_skip_pos) - *(uint32_t *)&code_block[a_skip_pos] = (block_pos - a_skip_pos) - 4; - if (chroma_skip_pos) - *(uint32_t *)&code_block[chroma_skip_pos] = (block_pos - chroma_skip_pos) - 4; - - addbyte(0x4c); /*MOV RSI, R15*/ + addlong(offsetof(voodoo_state_t, x)); + addbyte(0x66); /*MOV AX, new_depth*/ + addbyte(0x8b); + addbyte(0x87); + addlong(offsetof(voodoo_state_t, new_depth)); + addbyte(0x48); /*MOV RSI, aux_mem*/ + addbyte(0x8b); + addbyte(0xb7); + addlong(offsetof(voodoo_state_t, aux_mem)); + addbyte(0x66); /*MOV [ESI+EDX*2], AX*/ addbyte(0x89); - addbyte(0xfe); + addbyte(0x04); + addbyte(0x56); + } - addbyte(0xf3); /*MOVDQU XMM1, state->ib[EDI]*/ + if (z_skip_pos) + *(uint32_t *) &code_block[z_skip_pos] = (block_pos - z_skip_pos) - 4; + if (a_skip_pos) + *(uint32_t *) &code_block[a_skip_pos] = (block_pos - a_skip_pos) - 4; + if (chroma_skip_pos) + *(uint32_t *) &code_block[chroma_skip_pos] = (block_pos - chroma_skip_pos) - 4; + + addbyte(0x4c); /*MOV RSI, R15*/ + addbyte(0x89); + addbyte(0xfe); + + addbyte(0xf3); /*MOVDQU XMM1, state->ib[EDI]*/ + addbyte(0x0f); + addbyte(0x6f); + addbyte(0x8f); + addlong(offsetof(voodoo_state_t, ib)); + addbyte(0xf3); /*MOVDQU XMM3, state->tmu0_s[EDI]*/ + addbyte(0x0f); + addbyte(0x6f); + addbyte(0x9f); + addlong(offsetof(voodoo_state_t, tmu0_s)); + addbyte(0xf3); /*MOVQ XMM4, state->tmu0_w[EDI]*/ + addbyte(0x0f); + addbyte(0x7e); + addbyte(0xa7); + addlong(offsetof(voodoo_state_t, tmu0_w)); + addbyte(0xf3); /*MOVDQU XMM0, params->dBdX[ESI]*/ + addbyte(0x0f); + addbyte(0x6f); + addbyte(0x86); + addlong(offsetof(voodoo_params_t, dBdX)); + addbyte(0x8b); /*MOV EAX, params->dZdX[ESI]*/ + addbyte(0x86); + addlong(offsetof(voodoo_params_t, dZdX)); + addbyte(0xf3); /*MOVDQU XMM5, params->tmu[0].dSdX[ESI]*/ + addbyte(0x0f); + addbyte(0x6f); + addbyte(0xae); + addlong(offsetof(voodoo_params_t, tmu[0].dSdX)); + addbyte(0xf3); /*MOVQ XMM6, params->tmu[0].dWdX[ESI]*/ + addbyte(0x0f); + addbyte(0x7e); + addbyte(0xb6); + addlong(offsetof(voodoo_params_t, tmu[0].dWdX)); + + if (state->xdir > 0) { + addbyte(0x66); /*PADDD XMM1, XMM0*/ addbyte(0x0f); - addbyte(0x6f); - addbyte(0x8f); - addlong(offsetof(voodoo_state_t, ib)); - addbyte(0xf3); /*MOVDQU XMM3, state->tmu0_s[EDI]*/ + addbyte(0xfe); + addbyte(0xc8); + } else { + addbyte(0x66); /*PSUBD XMM1, XMM0*/ addbyte(0x0f); - addbyte(0x6f); - addbyte(0x9f); - addlong(offsetof(voodoo_state_t, tmu0_s)); - addbyte(0xf3); /*MOVQ XMM4, state->tmu0_w[EDI]*/ + addbyte(0xfa); + addbyte(0xc8); + } + + addbyte(0xf3); /*MOVQ XMM0, state->w*/ + addbyte(0x0f); + addbyte(0x7e); + addbyte(0x87); + addlong(offsetof(voodoo_state_t, w)); + addbyte(0xf3); /*MOVDQU state->ib, XMM1*/ + addbyte(0x0f); + addbyte(0x7f); + addbyte(0x8f); + addlong(offsetof(voodoo_state_t, ib)); + addbyte(0xf3); /*MOVQ XMM7, params->dWdX*/ + addbyte(0x0f); + addbyte(0x7e); + addbyte(0xbe); + addlong(offsetof(voodoo_params_t, dWdX)); + + if (state->xdir > 0) { + addbyte(0x66); /*PADDQ XMM3, XMM5*/ addbyte(0x0f); - addbyte(0x7e); - addbyte(0xa7); - addlong(offsetof(voodoo_state_t, tmu0_w)); - addbyte(0xf3); /*MOVDQU XMM0, params->dBdX[ESI]*/ + addbyte(0xd4); + addbyte(0xdd); + addbyte(0x66); /*PADDQ XMM4, XMM6*/ addbyte(0x0f); - addbyte(0x6f); - addbyte(0x86); - addlong(offsetof(voodoo_params_t, dBdX)); - addbyte(0x8b); /*MOV EAX, params->dZdX[ESI]*/ - addbyte(0x86); - addlong(offsetof(voodoo_params_t, dZdX)); - addbyte(0xf3); /*MOVDQU XMM5, params->tmu[0].dSdX[ESI]*/ + addbyte(0xd4); + addbyte(0xe6); + addbyte(0x66); /*PADDQ XMM0, XMM7*/ + addbyte(0x0f); + addbyte(0xd4); + addbyte(0xc7); + addbyte(0x01); /*ADD state->z[EDI], EAX*/ + addbyte(0x87); + addlong(offsetof(voodoo_state_t, z)); + } else { + addbyte(0x66); /*PSUBQ XMM3, XMM5*/ + addbyte(0x0f); + addbyte(0xfb); + addbyte(0xdd); + addbyte(0x66); /*PSUBQ XMM4, XMM6*/ + addbyte(0x0f); + addbyte(0xfb); + addbyte(0xe6); + addbyte(0x66); /*PSUBQ XMM0, XMM7*/ + addbyte(0x0f); + addbyte(0xfb); + addbyte(0xc7); + addbyte(0x29); /*SUB state->z[EDI], EAX*/ + addbyte(0x87); + addlong(offsetof(voodoo_state_t, z)); + } + + if (voodoo->dual_tmus) { + addbyte(0xf3); /*MOVDQU XMM5, params->tmu[1].dSdX[ESI]*/ addbyte(0x0f); addbyte(0x6f); addbyte(0xae); - addlong(offsetof(voodoo_params_t, tmu[0].dSdX)); - addbyte(0xf3); /*MOVQ XMM6, params->tmu[0].dWdX[ESI]*/ + addlong(offsetof(voodoo_params_t, tmu[1].dSdX)); + addbyte(0xf3); /*MOVQ XMM6, params->tmu[1].dWdX[ESI]*/ addbyte(0x0f); addbyte(0x7e); addbyte(0xb6); - addlong(offsetof(voodoo_params_t, tmu[0].dWdX)); + addlong(offsetof(voodoo_params_t, tmu[1].dWdX)); + } - if (state->xdir > 0) - { - addbyte(0x66); /*PADDD XMM1, XMM0*/ - addbyte(0x0f); - addbyte(0xfe); - addbyte(0xc8); - } - else - { - addbyte(0x66); /*PSUBD XMM1, XMM0*/ - addbyte(0x0f); - addbyte(0xfa); - addbyte(0xc8); - } + addbyte(0xf3); /*MOVDQU state->tmu0_s, XMM3*/ + addbyte(0x0f); + addbyte(0x7f); + addbyte(0x9f); + addlong(offsetof(voodoo_state_t, tmu0_s)); + addbyte(0x66); /*MOVQ state->tmu0_w, XMM4*/ + addbyte(0x0f); + addbyte(0xd6); + addbyte(0xa7); + addlong(offsetof(voodoo_state_t, tmu0_w)); + addbyte(0x66); /*MOVQ state->w, XMM0*/ + addbyte(0x0f); + addbyte(0xd6); + addbyte(0x87); + addlong(offsetof(voodoo_state_t, w)); - addbyte(0xf3); /*MOVQ XMM0, state->w*/ + if (voodoo->dual_tmus) { + addbyte(0xf3); /*MOVDQU XMM3, state->tmu1_s[EDI]*/ + addbyte(0x0f); + addbyte(0x6f); + addbyte(0x9f); + addlong(offsetof(voodoo_state_t, tmu1_s)); + addbyte(0xf3); /*MOVQ XMM4, state->tmu1_w[EDI]*/ addbyte(0x0f); addbyte(0x7e); - addbyte(0x87); - addlong(offsetof(voodoo_state_t, w)); - addbyte(0xf3); /*MOVDQU state->ib, XMM1*/ - addbyte(0x0f); - addbyte(0x7f); - addbyte(0x8f); - addlong(offsetof(voodoo_state_t, ib)); - addbyte(0xf3); /*MOVQ XMM7, params->dWdX*/ - addbyte(0x0f); - addbyte(0x7e); - addbyte(0xbe); - addlong(offsetof(voodoo_params_t, dWdX)); + addbyte(0xa7); + addlong(offsetof(voodoo_state_t, tmu1_w)); - if (state->xdir > 0) - { - addbyte(0x66); /*PADDQ XMM3, XMM5*/ - addbyte(0x0f); - addbyte(0xd4); - addbyte(0xdd); - addbyte(0x66); /*PADDQ XMM4, XMM6*/ - addbyte(0x0f); - addbyte(0xd4); - addbyte(0xe6); - addbyte(0x66); /*PADDQ XMM0, XMM7*/ - addbyte(0x0f); - addbyte(0xd4); - addbyte(0xc7); - addbyte(0x01); /*ADD state->z[EDI], EAX*/ - addbyte(0x87); - addlong(offsetof(voodoo_state_t, z)); - } - else - { - addbyte(0x66); /*PSUBQ XMM3, XMM5*/ - addbyte(0x0f); - addbyte(0xfb); - addbyte(0xdd); - addbyte(0x66); /*PSUBQ XMM4, XMM6*/ - addbyte(0x0f); - addbyte(0xfb); - addbyte(0xe6); - addbyte(0x66); /*PSUBQ XMM0, XMM7*/ - addbyte(0x0f); - addbyte(0xfb); - addbyte(0xc7); - addbyte(0x29); /*SUB state->z[EDI], EAX*/ - addbyte(0x87); - addlong(offsetof(voodoo_state_t, z)); + if (state->xdir > 0) { + addbyte(0x66); /*PADDQ XMM3, XMM5*/ + addbyte(0x0f); + addbyte(0xd4); + addbyte(0xdd); + addbyte(0x66); /*PADDQ XMM4, XMM6*/ + addbyte(0x0f); + addbyte(0xd4); + addbyte(0xe6); + } else { + addbyte(0x66); /*PSUBQ XMM3, XMM5*/ + addbyte(0x0f); + addbyte(0xfb); + addbyte(0xdd); + addbyte(0x66); /*PSUBQ XMM4, XMM6*/ + addbyte(0x0f); + addbyte(0xfb); + addbyte(0xe6); } - if (voodoo->dual_tmus) - { - addbyte(0xf3); /*MOVDQU XMM5, params->tmu[1].dSdX[ESI]*/ - addbyte(0x0f); - addbyte(0x6f); - addbyte(0xae); - addlong(offsetof(voodoo_params_t, tmu[1].dSdX)); - addbyte(0xf3); /*MOVQ XMM6, params->tmu[1].dWdX[ESI]*/ - addbyte(0x0f); - addbyte(0x7e); - addbyte(0xb6); - addlong(offsetof(voodoo_params_t, tmu[1].dWdX)); - } - - addbyte(0xf3); /*MOVDQU state->tmu0_s, XMM3*/ + addbyte(0xf3); /*MOVDQU state->tmu1_s, XMM3*/ addbyte(0x0f); addbyte(0x7f); addbyte(0x9f); - addlong(offsetof(voodoo_state_t, tmu0_s)); - addbyte(0x66); /*MOVQ state->tmu0_w, XMM4*/ + addlong(offsetof(voodoo_state_t, tmu1_s)); + addbyte(0x66); /*MOVQ state->tmu1_w, XMM4*/ addbyte(0x0f); addbyte(0xd6); addbyte(0xa7); - addlong(offsetof(voodoo_state_t, tmu0_w)); - addbyte(0x66); /*MOVQ state->w, XMM0*/ - addbyte(0x0f); - addbyte(0xd6); - addbyte(0x87); - addlong(offsetof(voodoo_state_t, w)); + addlong(offsetof(voodoo_state_t, tmu1_w)); + } - if (voodoo->dual_tmus) - { - addbyte(0xf3); /*MOVDQU XMM3, state->tmu1_s[EDI]*/ - addbyte(0x0f); - addbyte(0x6f); - addbyte(0x9f); - addlong(offsetof(voodoo_state_t, tmu1_s)); - addbyte(0xf3); /*MOVQ XMM4, state->tmu1_w[EDI]*/ - addbyte(0x0f); - addbyte(0x7e); - addbyte(0xa7); - addlong(offsetof(voodoo_state_t, tmu1_w)); + addbyte(0x83); /*ADD state->pixel_count[EDI], 1*/ + addbyte(0x87); + addlong(offsetof(voodoo_state_t, pixel_count)); + addbyte(1); - if (state->xdir > 0) - { - addbyte(0x66); /*PADDQ XMM3, XMM5*/ - addbyte(0x0f); - addbyte(0xd4); - addbyte(0xdd); - addbyte(0x66); /*PADDQ XMM4, XMM6*/ - addbyte(0x0f); - addbyte(0xd4); - addbyte(0xe6); - } - else - { - addbyte(0x66); /*PSUBQ XMM3, XMM5*/ - addbyte(0x0f); - addbyte(0xfb); - addbyte(0xdd); - addbyte(0x66); /*PSUBQ XMM4, XMM6*/ - addbyte(0x0f); - addbyte(0xfb); - addbyte(0xe6); - } - - addbyte(0xf3); /*MOVDQU state->tmu1_s, XMM3*/ - addbyte(0x0f); - addbyte(0x7f); - addbyte(0x9f); - addlong(offsetof(voodoo_state_t, tmu1_s)); - addbyte(0x66); /*MOVQ state->tmu1_w, XMM4*/ - addbyte(0x0f); - addbyte(0xd6); - addbyte(0xa7); - addlong(offsetof(voodoo_state_t, tmu1_w)); + if (params->fbzColorPath & FBZCP_TEXTURE_ENABLED) { + if ((params->textureMode[0] & TEXTUREMODE_MASK) == TEXTUREMODE_PASSTHROUGH || (params->textureMode[0] & TEXTUREMODE_LOCAL_MASK) == TEXTUREMODE_LOCAL) { + addbyte(0x83); /*ADD state->texel_count[EDI], 1*/ + addbyte(0x87); + addlong(offsetof(voodoo_state_t, texel_count)); + addbyte(1); + } else { + addbyte(0x83); /*ADD state->texel_count[EDI], 2*/ + addbyte(0x87); + addlong(offsetof(voodoo_state_t, texel_count)); + addbyte(2); } - - addbyte(0x83); /*ADD state->pixel_count[EDI], 1*/ - addbyte(0x87); - addlong(offsetof(voodoo_state_t, pixel_count)); - addbyte(1); + } - if (params->fbzColorPath & FBZCP_TEXTURE_ENABLED) - { - if ((params->textureMode[0] & TEXTUREMODE_MASK) == TEXTUREMODE_PASSTHROUGH || - (params->textureMode[0] & TEXTUREMODE_LOCAL_MASK) == TEXTUREMODE_LOCAL) - { - addbyte(0x83); /*ADD state->texel_count[EDI], 1*/ - addbyte(0x87); - addlong(offsetof(voodoo_state_t, texel_count)); - addbyte(1); - } - else - { - addbyte(0x83); /*ADD state->texel_count[EDI], 2*/ - addbyte(0x87); - addlong(offsetof(voodoo_state_t, texel_count)); - addbyte(2); - } - } + addbyte(0x8b); /*MOV EAX, state->x[EDI]*/ + addbyte(0x87); + addlong(offsetof(voodoo_state_t, x)); - addbyte(0x8b); /*MOV EAX, state->x[EDI]*/ + if (state->xdir > 0) { + addbyte(0x83); /*ADD state->x[EDI], 1*/ addbyte(0x87); addlong(offsetof(voodoo_state_t, x)); - - if (state->xdir > 0) - { - addbyte(0x83); /*ADD state->x[EDI], 1*/ - addbyte(0x87); - addlong(offsetof(voodoo_state_t, x)); - addbyte(1); - } - else - { - addbyte(0x83); /*SUB state->x[EDI], 1*/ - addbyte(0xaf); - addlong(offsetof(voodoo_state_t, x)); - addbyte(1); - } + addbyte(1); + } else { + addbyte(0x83); /*SUB state->x[EDI], 1*/ + addbyte(0xaf); + addlong(offsetof(voodoo_state_t, x)); + addbyte(1); + } - addbyte(0x3b); /*CMP EAX, state->x2[EDI]*/ - addbyte(0x87); - addlong(offsetof(voodoo_state_t, x2)); - addbyte(0x0f); /*JNZ loop_jump_pos*/ - addbyte(0x85); - addlong(loop_jump_pos - (block_pos + 4)); + addbyte(0x3b); /*CMP EAX, state->x2[EDI]*/ + addbyte(0x87); + addlong(offsetof(voodoo_state_t, x2)); + addbyte(0x0f); /*JNZ loop_jump_pos*/ + addbyte(0x85); + addlong(loop_jump_pos - (block_pos + 4)); - addbyte(0x41); /*POP R15*/ - addbyte(0x5f); - addbyte(0x41); /*POP R14*/ - addbyte(0x5e); - addbyte(0x41); /*POP R13*/ - addbyte(0x5d); - addbyte(0x41); /*POP R12*/ - addbyte(0x5c); - addbyte(0x5b); /*POP RBX*/ - addbyte(0x5e); /*POP RSI*/ - addbyte(0x5f); /*POP RDI*/ - addbyte(0x5d); /*POP RBP*/ - - addbyte(0xC3); /*RET*/ + addbyte(0x41); /*POP R15*/ + addbyte(0x5f); + addbyte(0x41); /*POP R14*/ + addbyte(0x5e); + addbyte(0x41); /*POP R13*/ + addbyte(0x5d); + addbyte(0x41); /*POP R12*/ + addbyte(0x5c); + addbyte(0x5b); /*POP RBX*/ + addbyte(0x5e); /*POP RSI*/ + addbyte(0x5f); /*POP RDI*/ + addbyte(0x5d); /*POP RBP*/ + + addbyte(0xC3); /*RET*/ } int voodoo_recomp = 0; -static inline void *voodoo_get_block(voodoo_t *voodoo, voodoo_params_t *params, voodoo_state_t *state, int odd_even) +static inline void * +voodoo_get_block(voodoo_t *voodoo, voodoo_params_t *params, voodoo_state_t *state, int odd_even) { - int c; - int b = last_block[odd_even]; - voodoo_x86_data_t *voodoo_x86_data = voodoo->codegen_data; - voodoo_x86_data_t *data; - - for (c = 0; c < 8; c++) - { - data = &voodoo_x86_data[odd_even + c*4]; //&voodoo_x86_data[odd_even][b]; - - if (state->xdir == data->xdir && - params->alphaMode == data->alphaMode && - params->fbzMode == data->fbzMode && - params->fogMode == data->fogMode && - params->fbzColorPath == data->fbzColorPath && - (voodoo->trexInit1[0] & (1 << 18)) == data->trexInit1 && - params->textureMode[0] == data->textureMode[0] && - params->textureMode[1] == data->textureMode[1] && - (params->tLOD[0] & LOD_MASK) == data->tLOD[0] && - (params->tLOD[1] & LOD_MASK) == data->tLOD[1] && - ((params->col_tiled || params->aux_tiled) ? 1 : 0) == data->is_tiled) - { - last_block[odd_even] = b; - return data->code_block; - } - - b = (b + 1) & 7; + int b = last_block[odd_even]; + voodoo_x86_data_t *voodoo_x86_data = voodoo->codegen_data; + voodoo_x86_data_t *data; + + for (uint8_t c = 0; c < 8; c++) { + data = &voodoo_x86_data[odd_even + c * 4]; //&voodoo_x86_data[odd_even][b]; + + if (state->xdir == data->xdir && params->alphaMode == data->alphaMode && params->fbzMode == data->fbzMode && params->fogMode == data->fogMode && params->fbzColorPath == data->fbzColorPath && (voodoo->trexInit1[0] & (1 << 18)) == data->trexInit1 && params->textureMode[0] == data->textureMode[0] && params->textureMode[1] == data->textureMode[1] && (params->tLOD[0] & LOD_MASK) == data->tLOD[0] && (params->tLOD[1] & LOD_MASK) == data->tLOD[1] && ((params->col_tiled || params->aux_tiled) ? 1 : 0) == data->is_tiled) { + last_block[odd_even] = b; + return data->code_block; } -voodoo_recomp++; - data = &voodoo_x86_data[odd_even + next_block_to_write[odd_even]*4]; -// code_block = data->code_block; - - voodoo_generate(data->code_block, voodoo, params, state, depth_op); - data->xdir = state->xdir; - data->alphaMode = params->alphaMode; - data->fbzMode = params->fbzMode; - data->fogMode = params->fogMode; - data->fbzColorPath = params->fbzColorPath; - data->trexInit1 = voodoo->trexInit1[0] & (1 << 18); - data->textureMode[0] = params->textureMode[0]; - data->textureMode[1] = params->textureMode[1]; - data->tLOD[0] = params->tLOD[0] & LOD_MASK; - data->tLOD[1] = params->tLOD[1] & LOD_MASK; - data->is_tiled = (params->col_tiled || params->aux_tiled) ? 1 : 0; + b = (b + 1) & 7; + } + voodoo_recomp++; + data = &voodoo_x86_data[odd_even + next_block_to_write[odd_even] * 4]; +#if 0 + code_block = data->code_block; +#endif - next_block_to_write[odd_even] = (next_block_to_write[odd_even] + 1) & 7; - - return data->code_block; + voodoo_generate(data->code_block, voodoo, params, state, depth_op); + + data->xdir = state->xdir; + data->alphaMode = params->alphaMode; + data->fbzMode = params->fbzMode; + data->fogMode = params->fogMode; + data->fbzColorPath = params->fbzColorPath; + data->trexInit1 = voodoo->trexInit1[0] & (1 << 18); + data->textureMode[0] = params->textureMode[0]; + data->textureMode[1] = params->textureMode[1]; + data->tLOD[0] = params->tLOD[0] & LOD_MASK; + data->tLOD[1] = params->tLOD[1] & LOD_MASK; + data->is_tiled = (params->col_tiled || params->aux_tiled) ? 1 : 0; + + next_block_to_write[odd_even] = (next_block_to_write[odd_even] + 1) & 7; + + return data->code_block; } -void voodoo_codegen_init(voodoo_t *voodoo) +void +voodoo_codegen_init(voodoo_t *voodoo) { - int c; + voodoo->codegen_data = plat_mmap(sizeof(voodoo_x86_data_t) * BLOCK_NUM * 4, 1); - voodoo->codegen_data = plat_mmap(sizeof(voodoo_x86_data_t) * BLOCK_NUM*4, 1); + for (uint16_t c = 0; c < 256; c++) { + int d[4]; + int _ds = c & 0xf; + int dt = c >> 4; - for (c = 0; c < 256; c++) - { - int d[4]; - int _ds = c & 0xf; - int dt = c >> 4; - - alookup[c] = _mm_set_epi32(0, 0, c | (c << 16), c | (c << 16)); - aminuslookup[c] = _mm_set_epi32(0, 0, (255-c) | ((255-c) << 16), (255-c) | ((255-c) << 16)); + alookup[c] = _mm_set_epi32(0, 0, c | (c << 16), c | (c << 16)); + aminuslookup[c] = _mm_set_epi32(0, 0, (255 - c) | ((255 - c) << 16), (255 - c) | ((255 - c) << 16)); - d[0] = (16 - _ds) * (16 - dt); - d[1] = _ds * (16 - dt); - d[2] = (16 - _ds) * dt; - d[3] = _ds * dt; + d[0] = (16 - _ds) * (16 - dt); + d[1] = _ds * (16 - dt); + d[2] = (16 - _ds) * dt; + d[3] = _ds * dt; - bilinear_lookup[c*2] = _mm_set_epi32(d[1] | (d[1] << 16), d[1] | (d[1] << 16), d[0] | (d[0] << 16), d[0] | (d[0] << 16)); - bilinear_lookup[c*2 + 1] = _mm_set_epi32(d[3] | (d[3] << 16), d[3] | (d[3] << 16), d[2] | (d[2] << 16), d[2] | (d[2] << 16)); - } - alookup[256] = _mm_set_epi32(0, 0, 256 | (256 << 16), 256 | (256 << 16)); - xmm_00_ff_w[0] = _mm_set_epi32(0, 0, 0, 0); - xmm_00_ff_w[1] = _mm_set_epi32(0, 0, 0xff | (0xff << 16), 0xff | (0xff << 16)); + bilinear_lookup[c * 2] = _mm_set_epi32(d[1] | (d[1] << 16), d[1] | (d[1] << 16), d[0] | (d[0] << 16), d[0] | (d[0] << 16)); + bilinear_lookup[c * 2 + 1] = _mm_set_epi32(d[3] | (d[3] << 16), d[3] | (d[3] << 16), d[2] | (d[2] << 16), d[2] | (d[2] << 16)); + } + alookup[256] = _mm_set_epi32(0, 0, 256 | (256 << 16), 256 | (256 << 16)); + xmm_00_ff_w[0] = _mm_set_epi32(0, 0, 0, 0); + xmm_00_ff_w[1] = _mm_set_epi32(0, 0, 0xff | (0xff << 16), 0xff | (0xff << 16)); } -void voodoo_codegen_close(voodoo_t *voodoo) +void +voodoo_codegen_close(voodoo_t *voodoo) { - plat_munmap(voodoo->codegen_data, sizeof(voodoo_x86_data_t) * BLOCK_NUM*4); + plat_munmap(voodoo->codegen_data, sizeof(voodoo_x86_data_t) * BLOCK_NUM * 4); } + +#endif /*VIDEO_VOODOO_CODEGEN_X86_64_H*/ diff --git a/src/include/86box/vid_voodoo_codegen_x86.h b/src/include/86box/vid_voodoo_codegen_x86.h index b6d60e5ff..996bd28f1 100644 --- a/src/include/86box/vid_voodoo_codegen_x86.h +++ b/src/include/86box/vid_voodoo_codegen_x86.h @@ -1,1955 +1,1830 @@ /*Registers : - + alphaMode fbzMode & 0x1f3fff fbzColorPath */ +#ifndef VIDEO_VOODOO_CODEGEN_X86_H +#define VIDEO_VOODOO_CODEGEN_X86_H + #ifdef _MSC_VER -#include +# include #else -#include +# include #endif -#define BLOCK_NUM 8 -#define BLOCK_MASK (BLOCK_NUM-1) +#define BLOCK_NUM 8 +#define BLOCK_MASK (BLOCK_NUM - 1) #define BLOCK_SIZE 8192 -#define LOD_MASK (LOD_TMIRROR_S | LOD_TMIRROR_T) +#define LOD_MASK (LOD_TMIRROR_S | LOD_TMIRROR_T) -typedef struct voodoo_x86_data_t -{ - uint8_t code_block[BLOCK_SIZE]; - int xdir; - uint32_t alphaMode; - uint32_t fbzMode; - uint32_t fogMode; - uint32_t fbzColorPath; - uint32_t textureMode[2]; - uint32_t tLOD[2]; - uint32_t trexInit1; - int is_tiled; +/* Suppress a false positive warning on gcc that causes excessive build log spam */ +#if __GNUC__ >= 10 +# pragma GCC diagnostic ignored "-Wstringop-overflow" +#endif + +typedef struct voodoo_x86_data_t { + uint8_t code_block[BLOCK_SIZE]; + int xdir; + uint32_t alphaMode; + uint32_t fbzMode; + uint32_t fogMode; + uint32_t fbzColorPath; + uint32_t textureMode[2]; + uint32_t tLOD[2]; + uint32_t trexInit1; + int is_tiled; } voodoo_x86_data_t; -static int last_block[4] = {0, 0}; -static int next_block_to_write[4] = {0, 0}; +static int last_block[4] = { 0, 0 }; +static int next_block_to_write[4] = { 0, 0 }; -#define addbyte(val) \ - do { \ - code_block[block_pos++] = val; \ - if (block_pos >= BLOCK_SIZE) \ - fatal("Over!\n"); \ - } while (0) +#define addbyte(val) \ + do { \ + code_block[block_pos++] = val; \ + } while (0) -#define addword(val) \ - do { \ - *(uint16_t *)&code_block[block_pos] = val; \ - block_pos += 2; \ - if (block_pos >= BLOCK_SIZE) \ - fatal("Over!\n"); \ - } while (0) +#define addword(val) \ + do { \ + *(uint16_t *) &code_block[block_pos] = val; \ + block_pos += 2; \ + } while (0) -#define addlong(val) \ - do { \ - *(uint32_t *)&code_block[block_pos] = val; \ - block_pos += 4; \ - if (block_pos >= BLOCK_SIZE) \ - fatal("Over!\n"); \ - } while (0) +#define addlong(val) \ + do { \ + *(uint32_t *) &code_block[block_pos] = val; \ + block_pos += 4; \ + } while (0) -#define addquad(val) \ - do { \ - *(uint64_t *)&code_block[block_pos] = val; \ - block_pos += 8; \ - if (block_pos >= BLOCK_SIZE) \ - fatal("Over!\n"); \ - } while (0) +#define addquad(val) \ + do { \ + *(uint64_t *) &code_block[block_pos] = val; \ + block_pos += 8; \ + } while (0) +static __m128i xmm_01_w; // = 0x0001000100010001ull; +static __m128i xmm_ff_w; // = 0x00ff00ff00ff00ffull; +static __m128i xmm_ff_b; // = 0x00000000ffffffffull; -static __m128i xmm_01_w;// = 0x0001000100010001ull; -static __m128i xmm_ff_w;// = 0x00ff00ff00ff00ffull; -static __m128i xmm_ff_b;// = 0x00000000ffffffffull; +static uint32_t zero = 0; +static double const_1_48 = (double) (1ULL << 4); -static uint32_t zero = 0; -static double const_1_48 = (double)(1ull << 4); +static __m128i alookup[257]; +static __m128i aminuslookup[256]; +static __m128i minus_254; // = 0xff02ff02ff02ff02ull; +static __m128i bilinear_lookup[256 * 2]; +static __m128i xmm_00_ff_w[2]; +static uint32_t i_00_ff_w[2] = { 0, 0xff }; -static __m128i alookup[257], aminuslookup[256]; -static __m128i minus_254;// = 0xff02ff02ff02ff02ull; -static __m128i bilinear_lookup[256*2]; -static __m128i xmm_00_ff_w[2]; -static uint32_t i_00_ff_w[2] = {0, 0xff}; - -static inline int codegen_texture_fetch(uint8_t *code_block, voodoo_t *voodoo, voodoo_params_t *params, voodoo_state_t *state, int block_pos, int tmu) +static inline int +codegen_texture_fetch(uint8_t *code_block, voodoo_t *voodoo, voodoo_params_t *params, voodoo_state_t *state, int block_pos, int tmu) { - if (params->textureMode[tmu] & 1) - { - addbyte(0xdf); /*FILDq state->tmu0_w*/ - addbyte(0xaf); - addlong(tmu ? offsetof(voodoo_state_t, tmu1_w) : offsetof(voodoo_state_t, tmu0_w)); - addbyte(0xdd); /*FLDq const_1_48*/ - addbyte(0x05); - addlong((uint32_t)&const_1_48); - addbyte(0xde); /*FDIV ST(1)*/ - addbyte(0xf1); - addbyte(0xdf); /*FILDq state->tmu0_s*/ - addbyte(0xaf); - addlong(tmu ? offsetof(voodoo_state_t, tmu1_s) : offsetof(voodoo_state_t, tmu0_s)); - addbyte(0xdf); /*FILDq state->tmu0_t*/ /*ST(0)=t, ST(1)=s, ST(2)=1/w*/ - addbyte(0xaf); - addlong(tmu ? offsetof(voodoo_state_t, tmu1_t) : offsetof(voodoo_state_t, tmu0_t)); - addbyte(0xd9); /*FXCH ST(1)*/ /*ST(0)=s, ST(1)=t, ST(2)=1/w*/ - addbyte(0xc9); - addbyte(0xd8); /*FMUL ST(2)*/ /*ST(0)=s/w, ST(1)=t, ST(2)=1/w*/ - addbyte(0xca); - addbyte(0xd9); /*FXCH ST(1)*/ /*ST(0)=t, ST(1)=s/w, ST(2)=1/w*/ - addbyte(0xc9); - addbyte(0xd8); /*FMUL ST(2)*/ /*ST(0)=t/w, ST(1)=s/w, ST(2)=1/w*/ - addbyte(0xca); - addbyte(0xd9); /*FXCH ST(2)*/ /*ST(0)=1/w, ST(1)=s/w, ST(2)=t/w*/ - addbyte(0xca); - addbyte(0xd9); /*FSTPs log_temp*/ /*ST(0)=s/w, ST(1)=t/w*/ - addbyte(0x9f); - addlong(offsetof(voodoo_state_t, log_temp)); - addbyte(0xdf); /*FSITPq state->tex_s*/ - addbyte(0xbf); - addlong(offsetof(voodoo_state_t, tex_s)); - addbyte(0x8b); /*MOV EAX, log_temp*/ - addbyte(0x87); - addlong(offsetof(voodoo_state_t, log_temp)); - addbyte(0xdf); /*FSITPq state->tex_t*/ - addbyte(0xbf); - addlong(offsetof(voodoo_state_t, tex_t)); - addbyte(0xc1); /*SHR EAX, 23-8*/ - addbyte(0xe8); - addbyte(15); - addbyte(0x0f); /*MOVZX EBX, AL*/ - addbyte(0xb6); - addbyte(0xd8); - addbyte(0x25); /*AND EAX, 0xff00*/ - addlong(0xff00); - addbyte(0x2d); /*SUB EAX, (127-44)<<8*/ - addlong((127-44+19) << 8); - addbyte(0x0f); /*MOVZX EBX, logtable[EBX]*/ - addbyte(0xb6); - addbyte(0x9b); - addlong((uint32_t)logtable); - addbyte(0x09); /*OR EAX, EBX*/ - addbyte(0xd8); - addbyte(0x03); /*ADD EAX, state->lod*/ - addbyte(0x87); - addlong(offsetof(voodoo_state_t, tmu[tmu].lod)); - addbyte(0x3b); /*CMP EAX, state->lod_min*/ - addbyte(0x87); - addlong(offsetof(voodoo_state_t, lod_min[tmu])); - addbyte(0x0f); /*CMOVL EAX, state->lod_min*/ - addbyte(0x4c); - addbyte(0x87); - addlong(offsetof(voodoo_state_t, lod_min[tmu])); - addbyte(0x3b); /*CMP EAX, state->lod_max*/ - addbyte(0x87); - addlong(offsetof(voodoo_state_t, lod_max[tmu])); - addbyte(0x0f); /*CMOVNL EAX, state->lod_max*/ - addbyte(0x4d); - addbyte(0x87); - addlong(offsetof(voodoo_state_t, lod_max[tmu])); - addbyte(0x0f); /*MOVZX EBX, AL*/ - addbyte(0xb6); - addbyte(0xd8); - addbyte(0xc1); /*SHR EAX, 8*/ - addbyte(0xe8); - addbyte(8); - addbyte(0x89); /*MOV state->lod_frac[tmu], EBX*/ - addbyte(0x9f); - addlong(offsetof(voodoo_state_t, lod_frac[tmu])); - addbyte(0x89); /*MOV state->lod, EAX*/ - addbyte(0x87); - addlong(offsetof(voodoo_state_t, lod)); - } - else - { - addbyte(0xf3); /*MOVQ XMM4, state->tmu0_s*/ - addbyte(0x0f); - addbyte(0x7e); - addbyte(0xa7); - addlong(tmu ? offsetof(voodoo_state_t, tmu1_s) : offsetof(voodoo_state_t, tmu0_s)); - addbyte(0xf3); /*MOVQ XMM5, state->tmu0_t*/ - addbyte(0x0f); - addbyte(0x7e); - addbyte(0xaf); - addlong(tmu ? offsetof(voodoo_state_t, tmu1_t) : offsetof(voodoo_state_t, tmu0_t)); - addbyte(0xc7); /*MOV state->lod[tmu], 0*/ - addbyte(0x87); - addlong(offsetof(voodoo_state_t, lod_frac[tmu])); - addlong(0); - addbyte(0x8b); /*MOV EAX, state->lod_min*/ - addbyte(0x87); - addlong(offsetof(voodoo_state_t, lod_min[tmu])); - addbyte(0x66); /*SHRQ XMM4, 28*/ - addbyte(0x0f); - addbyte(0x73); - addbyte(0xd4); - addbyte(28); - addbyte(0x66); /*SHRQ XMM5, 28*/ - addbyte(0x0f); - addbyte(0x73); - addbyte(0xd5); - addbyte(28); - addbyte(0x0f); /*MOVZX EBX, AL*/ - addbyte(0xb6); - addbyte(0xd8); - addbyte(0xc1); /*SHR EAX, 8*/ - addbyte(0xe8); - addbyte(8); - addbyte(0x66); /*MOVQ state->tex_s, XMM4*/ - addbyte(0x0f); - addbyte(0xd6); - addbyte(0xa7); - addlong(offsetof(voodoo_state_t, tex_s)); - addbyte(0x66); /*MOVQ state->tex_t, XMM5*/ - addbyte(0x0f); - addbyte(0xd6); - addbyte(0xaf); - addlong(offsetof(voodoo_state_t, tex_t)); - addbyte(0x89); /*MOV state->lod_frac[tmu], EBX*/ - addbyte(0x9f); - addlong(offsetof(voodoo_state_t, lod_frac[tmu])); - addbyte(0x89); /*MOV state->lod, EAX*/ - addbyte(0x87); - addlong(offsetof(voodoo_state_t, lod)); - } - /*EAX = state->lod*/ - if (params->fbzColorPath & FBZCP_TEXTURE_ENABLED) - { - if (voodoo->bilinear_enabled && (params->textureMode[tmu] & 6)) - { - addbyte(0x8b); /*MOV ECX, state->tex_lod[tmu]*/ - addbyte(0x8f); - addlong(offsetof(voodoo_state_t, tex_lod[tmu])); - addbyte(0xb2); /*MOV DL, 8*/ - addbyte(8); - addbyte(0x8b); /*MOV ECX, [ECX+EAX*4]*/ - addbyte(0x0c); - addbyte(0x81); - addbyte(0xbd); /*MOV EBP, 8*/ - addlong(8); - addbyte(0x28); /*SUB DL, CL*/ - addbyte(0xca); - addbyte(0xd3); /*SHL EBP, CL*/ - addbyte(0xe5); - addbyte(0x8b); /*MOV EAX, state->tex_s[EDI]*/ - addbyte(0x87); - addlong(offsetof(voodoo_state_t, tex_s)); - addbyte(0x8b); /*MOV EBX, state->tex_t[EDI]*/ - addbyte(0x9f); - addlong(offsetof(voodoo_state_t, tex_t)); - if (params->tLOD[tmu] & LOD_TMIRROR_S) - { - addbyte(0xa9); /*TEST EAX, 0x1000*/ - addlong(0x1000); - addbyte(0x74); /*JZ +*/ - addbyte(2); - addbyte(0xf7); /*NOT EAX*/ - addbyte(0xd0); - } - if (params->tLOD[tmu] & LOD_TMIRROR_T) - { - addbyte(0xf7); /*TEST EBX, 0x1000*/ - addbyte(0xc3); - addlong(0x1000); - addbyte(0x74); /*JZ +*/ - addbyte(2); - addbyte(0xf7); /*NOT EBX*/ - addbyte(0xd3); - } - addbyte(0x29); /*SUB EAX, EBP*/ - addbyte(0xe8); - addbyte(0x29); /*SUB EBX, EBP*/ - addbyte(0xeb); - addbyte(0xd3); /*SAR EAX, CL*/ - addbyte(0xf8); - addbyte(0xd3); /*SAR EBX, CL*/ - addbyte(0xfb); - addbyte(0x89); /*MOV EBP, EAX*/ - addbyte(0xc5); - addbyte(0x89); /*MOV ECX, EBX*/ - addbyte(0xd9); - addbyte(0x83); /*AND EBP, 0xf*/ - addbyte(0xe5); - addbyte(0xf); - addbyte(0xc1); /*SHL ECX, 4*/ - addbyte(0xe1); - addbyte(4); - addbyte(0xc1); /*SAR EAX, 4*/ - addbyte(0xf8); - addbyte(4); - addbyte(0x81); /*AND ECX, 0xf0*/ - addbyte(0xe1); - addlong(0xf0); - addbyte(0xc1); /*SAR EBX, 4*/ - addbyte(0xfb); - addbyte(4); - addbyte(0x09); /*OR EBP, ECX*/ - addbyte(0xcd); - addbyte(0x8b); /*MOV ECX, state->lod[EDI]*/ - addbyte(0x8f); - addlong(offsetof(voodoo_state_t, lod)); - addbyte(0xc1); /*SHL EBP, 5*/ - addbyte(0xe5); - addbyte(5); - /*EAX = S, EBX = T, ECX = LOD, EDX = tex_shift, ESI=params, EDI=state, EBP = bilinear shift*/ - addbyte(0x8d); /*LEA ESI, [ESI+ECX*4]*/ - addbyte(0x34); - addbyte(0x8e); - addbyte(0x89); /*MOV ebp_store, EBP*/ - addbyte(0xaf); - addlong(offsetof(voodoo_state_t, ebp_store)); - addbyte(0x8b); /*MOV EBP, state->tex[EDI+ECX*4]*/ - addbyte(0xac); - addbyte(0x8f); - addlong(offsetof(voodoo_state_t, tex[tmu])); - addbyte(0x88); /*MOV CL, DL*/ - addbyte(0xd1); - addbyte(0x89); /*MOV EDX, EBX*/ - addbyte(0xda); - if (!state->clamp_s[tmu]) - { - addbyte(0x23); /*AND EAX, params->tex_w_mask[ESI]*/ - addbyte(0x86); - addlong(offsetof(voodoo_params_t, tex_w_mask[tmu])); - } - addbyte(0x83); /*ADD EDX, 1*/ - addbyte(0xc2); - addbyte(1); - if (state->clamp_t[tmu]) - { - addbyte(0x0f); /*CMOVS EDX, zero*/ - addbyte(0x48); - addbyte(0x15); - addlong((uint32_t)&zero); - addbyte(0x3b); /*CMP EDX, params->tex_h_mask[ESI]*/ - addbyte(0x96); - addlong(offsetof(voodoo_params_t, tex_h_mask[tmu])); - addbyte(0x0f); /*CMOVA EDX, params->tex_h_mask[ESI]*/ - addbyte(0x47); - addbyte(0x96); - addlong(offsetof(voodoo_params_t, tex_h_mask[tmu])); - addbyte(0x85); /*TEST EBX,EBX*/ - addbyte(0xdb); - addbyte(0x0f); /*CMOVS EBX, zero*/ - addbyte(0x48); - addbyte(0x1d); - addlong((uint32_t)&zero); - addbyte(0x3b); /*CMP EBX, params->tex_h_mask[ESI]*/ - addbyte(0x9e); - addlong(offsetof(voodoo_params_t, tex_h_mask[tmu])); - addbyte(0x0f); /*CMOVA EBX, params->tex_h_mask[ESI]*/ - addbyte(0x47); - addbyte(0x9e); - addlong(offsetof(voodoo_params_t, tex_h_mask[tmu])); - } - else - { - addbyte(0x23); /*AND EDX, params->tex_h_mask[ESI]*/ - addbyte(0x96); - addlong(offsetof(voodoo_params_t, tex_h_mask[tmu])); - addbyte(0x23); /*AND EBX, params->tex_h_mask[ESI]*/ - addbyte(0x9e); - addlong(offsetof(voodoo_params_t, tex_h_mask[tmu])); - } - /*EAX = S, EBX = T0, EDX = T1*/ - addbyte(0xd3); /*SHL EBX, CL*/ - addbyte(0xe3); - addbyte(0xd3); /*SHL EDX, CL*/ - addbyte(0xe2); - addbyte(0x8d); /*LEA EBX,[EBP+EBX*2]*/ - addbyte(0x5c); - addbyte(0x9d); - addbyte(0); - addbyte(0x8d); /*LEA EDX,[EBP+EDX*2]*/ - addbyte(0x54); - addbyte(0x95); - addbyte(0); - if (state->clamp_s[tmu]) - { - addbyte(0x8b); /*MOV EBP, params->tex_w_mask[ESI]*/ - addbyte(0xae); - addlong(offsetof(voodoo_params_t, tex_w_mask[tmu])); - addbyte(0x85); /*TEST EAX, EAX*/ - addbyte(0xc0); - addbyte(0x8b); /*MOV ESI, ebp_store*/ - addbyte(0xb7); - addlong(offsetof(voodoo_state_t, ebp_store)); - addbyte(0x0f); /*CMOVS EAX, zero*/ - addbyte(0x48); - addbyte(0x05); - addlong((uint32_t)&zero); - addbyte(0x78); /*JS + - clamp on 0*/ - addbyte(2+3+2+ 5+5+2); - addbyte(0x3b); /*CMP EAX, EBP*/ - addbyte(0xc5); - addbyte(0x0f); /*CMOVAE EAX, EBP*/ - addbyte(0x43); - addbyte(0xc5); - addbyte(0x73); /*JAE + - clamp on +*/ - addbyte(5+5+2); - } - else - { - addbyte(0x3b); /*CMP EAX, params->tex_w_mask[ESI] - is S at texture edge (ie will wrap/clamp)?*/ - addbyte(0x86); - addlong(offsetof(voodoo_params_t, tex_w_mask[tmu])); - addbyte(0x8b); /*MOV ESI, ebp_store*/ - addbyte(0xb7); - addlong(offsetof(voodoo_state_t, ebp_store)); - addbyte(0x74); /*JE +*/ - addbyte(5+5+2); - } - - addbyte(0xf3); /*MOVQ XMM0, [EBX+EAX*4]*/ - addbyte(0x0f); - addbyte(0x7e); - addbyte(0x04); - addbyte(0x83); - addbyte(0xf3); /*MOVQ XMM1, [EDX+EAX*4]*/ - addbyte(0x0f); - addbyte(0x7e); - addbyte(0x0c); - addbyte(0x82); - - if (state->clamp_s[tmu]) - { - addbyte(0xeb); /*JMP +*/ - addbyte(5+5+4+4); - - /*S clamped - the two S coordinates are the same*/ - addbyte(0x66); /*MOVD XMM0, [EBX+EAX*4]*/ - addbyte(0x0f); - addbyte(0x6e); - addbyte(0x04); - addbyte(0x83); - addbyte(0x66); /*MOVD XMM1, [EDX+EAX*4]*/ - addbyte(0x0f); - addbyte(0x6e); - addbyte(0x0c); - addbyte(0x82); - addbyte(0x66); /*PUNPCKLDQ XMM0, XMM0*/ - addbyte(0x0f); - addbyte(0x62); - addbyte(0xc0); - addbyte(0x66); /*PUNPCKLDQ XMM1, XMM1*/ - addbyte(0x0f); - addbyte(0x62); - addbyte(0xc9); - } - else - { - addbyte(0xeb); /*JMP +*/ - addbyte(5+5+5+5+6+6); - - /*S wrapped - the two S coordinates are not contiguous*/ - addbyte(0x66); /*MOVD XMM0, [EBX+EAX*4]*/ - addbyte(0x0f); - addbyte(0x6e); - addbyte(0x04); - addbyte(0x83); - addbyte(0x66); /*MOVD XMM1, [EDX+EAX*4]*/ - addbyte(0x0f); - addbyte(0x6e); - addbyte(0x0c); - addbyte(0x82); - addbyte(0x66); /*PINSRW XMM0, [EBX], 2*/ - addbyte(0x0f); - addbyte(0xc4); - addbyte(0x03); - addbyte(0x02); - addbyte(0x66); /*PINSRW XMM1, [EDX], 2*/ - addbyte(0x0f); - addbyte(0xc4); - addbyte(0x0a); - addbyte(0x02); - addbyte(0x66); /*PINSRW XMM0, 2[EBX], 3*/ - addbyte(0x0f); - addbyte(0xc4); - addbyte(0x43); - addbyte(0x02); - addbyte(0x03); - addbyte(0x66); /*PINSRW XMM1, 2[EDX], 3*/ - addbyte(0x0f); - addbyte(0xc4); - addbyte(0x4a); - addbyte(0x02); - addbyte(0x03); - } - - addbyte(0x66); /*PUNPCKLBW XMM0, XMM2*/ - addbyte(0x0f); - addbyte(0x60); - addbyte(0xc2); - addbyte(0x66); /*PUNPCKLBW XMM1, XMM2*/ - addbyte(0x0f); - addbyte(0x60); - addbyte(0xca); - - addbyte(0x81); /*ADD ESI, bilinear_lookup*/ - addbyte(0xc6); - addlong((uint32_t)bilinear_lookup); - - addbyte(0x66); /*PMULLW XMM0, bilinear_lookup[ESI]*/ - addbyte(0x0f); - addbyte(0xd5); - addbyte(0x06); - addbyte(0x66); /*PMULLW XMM1, bilinear_lookup[ESI]+0x10*/ - addbyte(0x0f); - addbyte(0xd5); - addbyte(0x4e); - addbyte(0x10); - addbyte(0x66); /*PADDW XMM0, XMM1*/ - addbyte(0x0f); - addbyte(0xfd); - addbyte(0xc0 | 1 | (0 << 3)); - addbyte(0x66); /*MOV XMM1, XMM0*/ - addbyte(0x0f); - addbyte(0x6f); - addbyte(0xc0 | 0 | (1 << 3)); - addbyte(0x66); /*PSRLDQ XMM0, 64*/ - addbyte(0x0f); - addbyte(0x73); - addbyte(0xd8); - addbyte(8); - addbyte(0x66); /*PADDW XMM0, XMM1*/ - addbyte(0x0f); - addbyte(0xfd); - addbyte(0xc0 | 1 | (0 << 3)); - addbyte(0x66); /*PSRLW XMM0, 8*/ - addbyte(0x0f); - addbyte(0x71); - addbyte(0xd0 | 0); - addbyte(8); - addbyte(0x66); /*PACKUSWB XMM0, XMM0*/ - addbyte(0x0f); - addbyte(0x67); - addbyte(0xc0); - - addbyte(0x8b); /*MOV ESI, [ESP+8]*/ - addbyte(0x74); - addbyte(0x24); - addbyte(8+16); /*CHECK!*/ - - addbyte(0x66); /*MOV EAX, XMM0*/ - addbyte(0x0f); - addbyte(0x7e); - addbyte(0xc0); - } - else - { - addbyte(0x8b); /*MOV ECX, state->tex_lod[tmu]*/ - addbyte(0x8f); - addlong(offsetof(voodoo_state_t, tex_lod[tmu])); - addbyte(0xb2); /*MOV DL, 8*/ - addbyte(8); - addbyte(0x8b); /*MOV ECX, [ECX+EAX*4]*/ - addbyte(0x0c); - addbyte(0x81); - addbyte(0x8b); /*MOV EBP, state->tex[EDI+ECX*4]*/ - addbyte(0xac); - addbyte(0x8f); - addlong(offsetof(voodoo_state_t, tex[tmu])); - addbyte(0x28); /*SUB DL, CL*/ - addbyte(0xca); - addbyte(0x80); /*ADD CL, 4*/ - addbyte(0xc1); - addbyte(4); - addbyte(0x8b); /*MOV EAX, state->tex_s[EDI]*/ - addbyte(0x87); - addlong(offsetof(voodoo_state_t, tex_s)); - addbyte(0x8b); /*MOV EBX, state->tex_t[EDI]*/ - addbyte(0x9f); - addlong(offsetof(voodoo_state_t, tex_t)); - if (params->tLOD[tmu] & LOD_TMIRROR_S) - { - addbyte(0xa9); /*TEST EAX, 0x1000*/ - addlong(0x1000); - addbyte(0x74); /*JZ +*/ - addbyte(2); - addbyte(0xf7); /*NOT EAX*/ - addbyte(0xd0); - } - if (params->tLOD[tmu] & LOD_TMIRROR_T) - { - addbyte(0xf7); /*TEST EBX, 0x1000*/ - addbyte(0xc3); - addlong(0x1000); - addbyte(0x74); /*JZ +*/ - addbyte(2); - addbyte(0xf7); /*NOT EBX*/ - addbyte(0xd3); - } - addbyte(0xd3); /*SHR EAX, CL*/ - addbyte(0xe8); - addbyte(0xd3); /*SHR EBX, CL*/ - addbyte(0xeb); - if (state->clamp_s[tmu]) - { - addbyte(0x85); /*TEST EAX, EAX*/ - addbyte(0xc0); - addbyte(0x0f); /*CMOVS EAX, zero*/ - addbyte(0x48); - addbyte(0x05); - addlong((uint32_t)&zero); - addbyte(0x3b); /*CMP EAX, params->tex_w_mask[ESI+ECX*4]*/ - addbyte(0x84); - addbyte(0x8e); - addlong(offsetof(voodoo_params_t, tex_w_mask[tmu]) - 0x10); - addbyte(0x0f); /*CMOVAE EAX, params->tex_w_mask[ESI+ECX*4]*/ - addbyte(0x43); - addbyte(0x84); - addbyte(0x8e); - addlong(offsetof(voodoo_params_t, tex_w_mask[tmu]) - 0x10); - - } - else - { - addbyte(0x23); /*AND EAX, params->tex_w_mask-0x10[ESI+ECX*4]*/ - addbyte(0x84); - addbyte(0x8e); - addlong(offsetof(voodoo_params_t, tex_w_mask[tmu]) - 0x10); - } - if (state->clamp_t[tmu]) - { - addbyte(0x85); /*TEST EBX, EBX*/ - addbyte(0xdb); - addbyte(0x0f); /*CMOVS EBX, zero*/ - addbyte(0x48); - addbyte(0x1d); - addlong((uint32_t)&zero); - addbyte(0x3b); /*CMP EBX, params->tex_h_mask[ESI+ECX*4]*/ - addbyte(0x9c); - addbyte(0x8e); - addlong(offsetof(voodoo_params_t, tex_h_mask[tmu]) - 0x10); - addbyte(0x0f); /*CMOVAE EBX, params->tex_h_mask[ESI+ECX*4]*/ - addbyte(0x43); - addbyte(0x9c); - addbyte(0x8e); - addlong(offsetof(voodoo_params_t, tex_h_mask[tmu]) - 0x10); - } - else - { - addbyte(0x23); /*AND EBX, params->tex_h_mask-0x10[ESI+ECX*4]*/ - addbyte(0x9c); - addbyte(0x8e); - addlong(offsetof(voodoo_params_t, tex_h_mask[tmu]) - 0x10); - } - addbyte(0x88); /*MOV CL, DL*/ - addbyte(0xd1); - addbyte(0xd3); /*SHL EBX, CL*/ - addbyte(0xe3); - addbyte(0x01); /*ADD EBX, EAX*/ - addbyte(0xc3); - - addbyte(0x8b); /*MOV EAX,[EBP+EBX*4]*/ - addbyte(0x44); - addbyte(0x9d); - addbyte(0); - } - } - - return block_pos; -} - -static inline void voodoo_generate(uint8_t *code_block, voodoo_t *voodoo, voodoo_params_t *params, voodoo_state_t *state, int depthop) -{ - int block_pos = 0; - int z_skip_pos = 0; - int a_skip_pos = 0; - int chroma_skip_pos = 0; - int depth_jump_pos = 0; - int depth_jump_pos2 = 0; - int loop_jump_pos = 0; -// xmm_01_w = (__m128i)0x0001000100010001ull; -// xmm_ff_w = (__m128i)0x00ff00ff00ff00ffull; -// xmm_ff_b = (__m128i)0x00000000ffffffffull; - xmm_01_w = _mm_set_epi32(0, 0, 0x00010001, 0x00010001); - xmm_ff_w = _mm_set_epi32(0, 0, 0x00ff00ff, 0x00ff00ff); - xmm_ff_b = _mm_set_epi32(0, 0, 0, 0x00ffffff); - minus_254 = _mm_set_epi32(0, 0, 0xff02ff02, 0xff02ff02); -// *(uint64_t *)&const_1_48 = 0x45b0000000000000ull; -// block_pos = 0; -// voodoo_get_depth = &code_block[block_pos]; - /*W at (%esp+4) - Z at (%esp+12) - new_depth at (%esp+16)*/ -// if ((params->fbzMode & FBZ_DEPTH_ENABLE) && (depth_op == DEPTHOP_NEVER)) -// { -// addbyte(0xC3); /*RET*/ -// return; -// } - addbyte(0x55); /*PUSH EBP*/ - addbyte(0x57); /*PUSH EDI*/ - addbyte(0x56); /*PUSH ESI*/ - addbyte(0x53); /*PUSH EBX*/ - - addbyte(0x8b); /*MOV EDI, [ESP+4]*/ - addbyte(0x7c); - addbyte(0x24); - addbyte(4+16); - loop_jump_pos = block_pos; - addbyte(0x8b); /*MOV ESI, [ESP+8]*/ - addbyte(0x74); - addbyte(0x24); - addbyte(8+16); - if (params->col_tiled || params->aux_tiled) - { - addbyte(0x8b); /*MOV EAX, state->x[EDI]*/ - addbyte(0x87); - addlong(offsetof(voodoo_state_t, x)); - addbyte(0x89); /*MOV EBX, EAX*/ - addbyte(0xc3); - addbyte(0x83); /*AND EAX, 63*/ - addbyte(0xe0); - addbyte(63); - addbyte(0xc1); /*SHR EBX, 6*/ - addbyte(0xeb); - addbyte(6); - addbyte(0xc1); /*SHL EBX, 11 - tile is 128*32, << 12, div 2 because word index*/ - addbyte(0xe3); - addbyte(11); - addbyte(0x01); /*ADD EAX, EBX*/ - addbyte(0xd8); - addbyte(0x89); /*MOV state->x_tiled[EDI], EAX*/ - addbyte(0x87); - addlong(offsetof(voodoo_state_t, x_tiled)); - } - addbyte(0x66); /*PXOR XMM2, XMM2*/ + if (params->textureMode[tmu] & 1) { + addbyte(0xdf); /*FILDq state->tmu0_w*/ + addbyte(0xaf); + addlong(tmu ? offsetof(voodoo_state_t, tmu1_w) : offsetof(voodoo_state_t, tmu0_w)); + addbyte(0xdd); /*FLDq const_1_48*/ + addbyte(0x05); + addlong((uint32_t) &const_1_48); + addbyte(0xde); /*FDIV ST(1)*/ + addbyte(0xf1); + addbyte(0xdf); /*FILDq state->tmu0_s*/ + addbyte(0xaf); + addlong(tmu ? offsetof(voodoo_state_t, tmu1_s) : offsetof(voodoo_state_t, tmu0_s)); + addbyte(0xdf); /*FILDq state->tmu0_t*/ /*ST(0)=t, ST(1)=s, ST(2)=1/w*/ + addbyte(0xaf); + addlong(tmu ? offsetof(voodoo_state_t, tmu1_t) : offsetof(voodoo_state_t, tmu0_t)); + addbyte(0xd9); /*FXCH ST(1)*/ /*ST(0)=s, ST(1)=t, ST(2)=1/w*/ + addbyte(0xc9); + addbyte(0xd8); /*FMUL ST(2)*/ /*ST(0)=s/w, ST(1)=t, ST(2)=1/w*/ + addbyte(0xca); + addbyte(0xd9); /*FXCH ST(1)*/ /*ST(0)=t, ST(1)=s/w, ST(2)=1/w*/ + addbyte(0xc9); + addbyte(0xd8); /*FMUL ST(2)*/ /*ST(0)=t/w, ST(1)=s/w, ST(2)=1/w*/ + addbyte(0xca); + addbyte(0xd9); /*FXCH ST(2)*/ /*ST(0)=1/w, ST(1)=s/w, ST(2)=t/w*/ + addbyte(0xca); + addbyte(0xd9); /*FSTPs log_temp*/ /*ST(0)=s/w, ST(1)=t/w*/ + addbyte(0x9f); + addlong(offsetof(voodoo_state_t, log_temp)); + addbyte(0xdf); /*FSITPq state->tex_s*/ + addbyte(0xbf); + addlong(offsetof(voodoo_state_t, tex_s)); + addbyte(0x8b); /*MOV EAX, log_temp*/ + addbyte(0x87); + addlong(offsetof(voodoo_state_t, log_temp)); + addbyte(0xdf); /*FSITPq state->tex_t*/ + addbyte(0xbf); + addlong(offsetof(voodoo_state_t, tex_t)); + addbyte(0xc1); /*SHR EAX, 23-8*/ + addbyte(0xe8); + addbyte(15); + addbyte(0x0f); /*MOVZX EBX, AL*/ + addbyte(0xb6); + addbyte(0xd8); + addbyte(0x25); /*AND EAX, 0xff00*/ + addlong(0xff00); + addbyte(0x2d); /*SUB EAX, (127-44)<<8*/ + addlong((127 - 44 + 19) << 8); + addbyte(0x0f); /*MOVZX EBX, logtable[EBX]*/ + addbyte(0xb6); + addbyte(0x9b); + addlong((uint32_t) logtable); + addbyte(0x09); /*OR EAX, EBX*/ + addbyte(0xd8); + addbyte(0x03); /*ADD EAX, state->lod*/ + addbyte(0x87); + addlong(offsetof(voodoo_state_t, tmu[tmu].lod)); + addbyte(0x3b); /*CMP EAX, state->lod_min*/ + addbyte(0x87); + addlong(offsetof(voodoo_state_t, lod_min[tmu])); + addbyte(0x0f); /*CMOVL EAX, state->lod_min*/ + addbyte(0x4c); + addbyte(0x87); + addlong(offsetof(voodoo_state_t, lod_min[tmu])); + addbyte(0x3b); /*CMP EAX, state->lod_max*/ + addbyte(0x87); + addlong(offsetof(voodoo_state_t, lod_max[tmu])); + addbyte(0x0f); /*CMOVNL EAX, state->lod_max*/ + addbyte(0x4d); + addbyte(0x87); + addlong(offsetof(voodoo_state_t, lod_max[tmu])); + addbyte(0x0f); /*MOVZX EBX, AL*/ + addbyte(0xb6); + addbyte(0xd8); + addbyte(0xc1); /*SHR EAX, 8*/ + addbyte(0xe8); + addbyte(8); + addbyte(0x89); /*MOV state->lod_frac[tmu], EBX*/ + addbyte(0x9f); + addlong(offsetof(voodoo_state_t, lod_frac[tmu])); + addbyte(0x89); /*MOV state->lod, EAX*/ + addbyte(0x87); + addlong(offsetof(voodoo_state_t, lod)); + } else { + addbyte(0xf3); /*MOVQ XMM4, state->tmu0_s*/ addbyte(0x0f); - addbyte(0xef); - addbyte(0xd2); - - if ((params->fbzMode & FBZ_W_BUFFER) || (params->fogMode & (FOG_ENABLE|FOG_CONSTANT|FOG_Z|FOG_ALPHA)) == FOG_ENABLE) - { - addbyte(0xb8); /*MOV new_depth, 0*/ - addlong(0); - addbyte(0x66); /*TEST w+4, 0xffff*/ - addbyte(0xf7); - addbyte(0x87); - addlong(offsetof(voodoo_state_t, w)+4); - addword(0xffff); - addbyte(0x75); /*JNZ got_depth*/ - depth_jump_pos = block_pos; - addbyte(0); -// addbyte(4+5+2+3+2+5+5+3+2+2+2+/*3+*/3+2+6+4+5+2+3); - addbyte(0x8b); /*MOV EDX, w*/ - addbyte(0x97); - addlong(offsetof(voodoo_state_t, w)); - addbyte(0xb8); /*MOV new_depth, 0xf001*/ - addlong(0xf001); - addbyte(0x89); /*MOV EBX, EDX*/ - addbyte(0xd3); - addbyte(0xc1); /*SHR EDX, 16*/ - addbyte(0xea); - addbyte(16); - addbyte(0x74); /*JZ got_depth*/ - depth_jump_pos2 = block_pos; - addbyte(0); -// addbyte(5+5+3+2+2+2+/*3+*/3+2+6+4+5+2+3); - addbyte(0xb9); /*MOV ECX, 19*/ - addlong(19); - addbyte(0x0f); /*BSR EAX, EDX*/ - addbyte(0xbd); - addbyte(0xc2); - addbyte(0xba); /*MOV EDX, 15*/ - addlong(15); + addbyte(0x7e); + addbyte(0xa7); + addlong(tmu ? offsetof(voodoo_state_t, tmu1_s) : offsetof(voodoo_state_t, tmu0_s)); + addbyte(0xf3); /*MOVQ XMM5, state->tmu0_t*/ + addbyte(0x0f); + addbyte(0x7e); + addbyte(0xaf); + addlong(tmu ? offsetof(voodoo_state_t, tmu1_t) : offsetof(voodoo_state_t, tmu0_t)); + addbyte(0xc7); /*MOV state->lod[tmu], 0*/ + addbyte(0x87); + addlong(offsetof(voodoo_state_t, lod_frac[tmu])); + addlong(0); + addbyte(0x8b); /*MOV EAX, state->lod_min*/ + addbyte(0x87); + addlong(offsetof(voodoo_state_t, lod_min[tmu])); + addbyte(0x66); /*SHRQ XMM4, 28*/ + addbyte(0x0f); + addbyte(0x73); + addbyte(0xd4); + addbyte(28); + addbyte(0x66); /*SHRQ XMM5, 28*/ + addbyte(0x0f); + addbyte(0x73); + addbyte(0xd5); + addbyte(28); + addbyte(0x0f); /*MOVZX EBX, AL*/ + addbyte(0xb6); + addbyte(0xd8); + addbyte(0xc1); /*SHR EAX, 8*/ + addbyte(0xe8); + addbyte(8); + addbyte(0x66); /*MOVQ state->tex_s, XMM4*/ + addbyte(0x0f); + addbyte(0xd6); + addbyte(0xa7); + addlong(offsetof(voodoo_state_t, tex_s)); + addbyte(0x66); /*MOVQ state->tex_t, XMM5*/ + addbyte(0x0f); + addbyte(0xd6); + addbyte(0xaf); + addlong(offsetof(voodoo_state_t, tex_t)); + addbyte(0x89); /*MOV state->lod_frac[tmu], EBX*/ + addbyte(0x9f); + addlong(offsetof(voodoo_state_t, lod_frac[tmu])); + addbyte(0x89); /*MOV state->lod, EAX*/ + addbyte(0x87); + addlong(offsetof(voodoo_state_t, lod)); + } + /*EAX = state->lod*/ + if (params->fbzColorPath & FBZCP_TEXTURE_ENABLED) { + if (voodoo->bilinear_enabled && (params->textureMode[tmu] & 6)) { + addbyte(0x8b); /*MOV ECX, state->tex_lod[tmu]*/ + addbyte(0x8f); + addlong(offsetof(voodoo_state_t, tex_lod[tmu])); + addbyte(0xb2); /*MOV DL, 8*/ + addbyte(8); + addbyte(0x8b); /*MOV ECX, [ECX+EAX*4]*/ + addbyte(0x0c); + addbyte(0x81); + addbyte(0xbd); /*MOV EBP, 8*/ + addlong(8); + addbyte(0x28); /*SUB DL, CL*/ + addbyte(0xca); + addbyte(0xd3); /*SHL EBP, CL*/ + addbyte(0xe5); + addbyte(0x8b); /*MOV EAX, state->tex_s[EDI]*/ + addbyte(0x87); + addlong(offsetof(voodoo_state_t, tex_s)); + addbyte(0x8b); /*MOV EBX, state->tex_t[EDI]*/ + addbyte(0x9f); + addlong(offsetof(voodoo_state_t, tex_t)); + if (params->tLOD[tmu] & LOD_TMIRROR_S) { + addbyte(0xa9); /*TEST EAX, 0x1000*/ + addlong(0x1000); + addbyte(0x74); /*JZ +*/ + addbyte(2); + addbyte(0xf7); /*NOT EAX*/ + addbyte(0xd0); + } + if (params->tLOD[tmu] & LOD_TMIRROR_T) { + addbyte(0xf7); /*TEST EBX, 0x1000*/ + addbyte(0xc3); + addlong(0x1000); + addbyte(0x74); /*JZ +*/ + addbyte(2); addbyte(0xf7); /*NOT EBX*/ addbyte(0xd3); - addbyte(0x29); /*SUB EDX, EAX - EDX = exp*/ - addbyte(0xc2); - addbyte(0x29); /*SUB ECX, EDX*/ - addbyte(0xd1); - addbyte(0xc1); /*SHL EDX, 12*/ - addbyte(0xe2); - addbyte(12); - addbyte(0xd3); /*SHR EBX, CL*/ - addbyte(0xeb); - addbyte(0x81); /*AND EBX, 0xfff - EBX = mant*/ - addbyte(0xe3); - addlong(0xfff); - addbyte(0x8d); /*LEA EAX, 1[EDX, EBX]*/ - addbyte(0x44); - addbyte(0x13); - addbyte(1); - addbyte(0xbb); /*MOV EBX, 0xffff*/ - addlong(0xffff); - addbyte(0x39); /*CMP EAX, EBX*/ - addbyte(0xd8); - addbyte(0x0f); /*CMOVA EAX, EBX*/ + } + addbyte(0x29); /*SUB EAX, EBP*/ + addbyte(0xe8); + addbyte(0x29); /*SUB EBX, EBP*/ + addbyte(0xeb); + addbyte(0xd3); /*SAR EAX, CL*/ + addbyte(0xf8); + addbyte(0xd3); /*SAR EBX, CL*/ + addbyte(0xfb); + addbyte(0x89); /*MOV EBP, EAX*/ + addbyte(0xc5); + addbyte(0x89); /*MOV ECX, EBX*/ + addbyte(0xd9); + addbyte(0x83); /*AND EBP, 0xf*/ + addbyte(0xe5); + addbyte(0xf); + addbyte(0xc1); /*SHL ECX, 4*/ + addbyte(0xe1); + addbyte(4); + addbyte(0xc1); /*SAR EAX, 4*/ + addbyte(0xf8); + addbyte(4); + addbyte(0x81); /*AND ECX, 0xf0*/ + addbyte(0xe1); + addlong(0xf0); + addbyte(0xc1); /*SAR EBX, 4*/ + addbyte(0xfb); + addbyte(4); + addbyte(0x09); /*OR EBP, ECX*/ + addbyte(0xcd); + addbyte(0x8b); /*MOV ECX, state->lod[EDI]*/ + addbyte(0x8f); + addlong(offsetof(voodoo_state_t, lod)); + addbyte(0xc1); /*SHL EBP, 5*/ + addbyte(0xe5); + addbyte(5); + /*EAX = S, EBX = T, ECX = LOD, EDX = tex_shift, ESI=params, EDI=state, EBP = bilinear shift*/ + addbyte(0x8d); /*LEA ESI, [ESI+ECX*4]*/ + addbyte(0x34); + addbyte(0x8e); + addbyte(0x89); /*MOV ebp_store, EBP*/ + addbyte(0xaf); + addlong(offsetof(voodoo_state_t, ebp_store)); + addbyte(0x8b); /*MOV EBP, state->tex[EDI+ECX*4]*/ + addbyte(0xac); + addbyte(0x8f); + addlong(offsetof(voodoo_state_t, tex[tmu])); + addbyte(0x88); /*MOV CL, DL*/ + addbyte(0xd1); + addbyte(0x89); /*MOV EDX, EBX*/ + addbyte(0xda); + if (!state->clamp_s[tmu]) { + addbyte(0x23); /*AND EAX, params->tex_w_mask[ESI]*/ + addbyte(0x86); + addlong(offsetof(voodoo_params_t, tex_w_mask[tmu])); + } + addbyte(0x83); /*ADD EDX, 1*/ + addbyte(0xc2); + addbyte(1); + if (state->clamp_t[tmu]) { + addbyte(0x0f); /*CMOVS EDX, zero*/ + addbyte(0x48); + addbyte(0x15); + addlong((uint32_t) &zero); + addbyte(0x3b); /*CMP EDX, params->tex_h_mask[ESI]*/ + addbyte(0x96); + addlong(offsetof(voodoo_params_t, tex_h_mask[tmu])); + addbyte(0x0f); /*CMOVA EDX, params->tex_h_mask[ESI]*/ addbyte(0x47); - addbyte(0xc3); + addbyte(0x96); + addlong(offsetof(voodoo_params_t, tex_h_mask[tmu])); + addbyte(0x85); /*TEST EBX,EBX*/ + addbyte(0xdb); + addbyte(0x0f); /*CMOVS EBX, zero*/ + addbyte(0x48); + addbyte(0x1d); + addlong((uint32_t) &zero); + addbyte(0x3b); /*CMP EBX, params->tex_h_mask[ESI]*/ + addbyte(0x9e); + addlong(offsetof(voodoo_params_t, tex_h_mask[tmu])); + addbyte(0x0f); /*CMOVA EBX, params->tex_h_mask[ESI]*/ + addbyte(0x47); + addbyte(0x9e); + addlong(offsetof(voodoo_params_t, tex_h_mask[tmu])); + } else { + addbyte(0x23); /*AND EDX, params->tex_h_mask[ESI]*/ + addbyte(0x96); + addlong(offsetof(voodoo_params_t, tex_h_mask[tmu])); + addbyte(0x23); /*AND EBX, params->tex_h_mask[ESI]*/ + addbyte(0x9e); + addlong(offsetof(voodoo_params_t, tex_h_mask[tmu])); + } + /*EAX = S, EBX = T0, EDX = T1*/ + addbyte(0xd3); /*SHL EBX, CL*/ + addbyte(0xe3); + addbyte(0xd3); /*SHL EDX, CL*/ + addbyte(0xe2); + addbyte(0x8d); /*LEA EBX,[EBP+EBX*2]*/ + addbyte(0x5c); + addbyte(0x9d); + addbyte(0); + addbyte(0x8d); /*LEA EDX,[EBP+EDX*2]*/ + addbyte(0x54); + addbyte(0x95); + addbyte(0); + if (state->clamp_s[tmu]) { + addbyte(0x8b); /*MOV EBP, params->tex_w_mask[ESI]*/ + addbyte(0xae); + addlong(offsetof(voodoo_params_t, tex_w_mask[tmu])); + addbyte(0x85); /*TEST EAX, EAX*/ + addbyte(0xc0); + addbyte(0x8b); /*MOV ESI, ebp_store*/ + addbyte(0xb7); + addlong(offsetof(voodoo_state_t, ebp_store)); + addbyte(0x0f); /*CMOVS EAX, zero*/ + addbyte(0x48); + addbyte(0x05); + addlong((uint32_t) &zero); + addbyte(0x78); /*JS + - clamp on 0*/ + addbyte(2 + 3 + 2 + 5 + 5 + 2); + addbyte(0x3b); /*CMP EAX, EBP*/ + addbyte(0xc5); + addbyte(0x0f); /*CMOVAE EAX, EBP*/ + addbyte(0x43); + addbyte(0xc5); + addbyte(0x73); /*JAE + - clamp on +*/ + addbyte(5 + 5 + 2); + } else { + addbyte(0x3b); /*CMP EAX, params->tex_w_mask[ESI] - is S at texture edge (ie will wrap/clamp)?*/ + addbyte(0x86); + addlong(offsetof(voodoo_params_t, tex_w_mask[tmu])); + addbyte(0x8b); /*MOV ESI, ebp_store*/ + addbyte(0xb7); + addlong(offsetof(voodoo_state_t, ebp_store)); + addbyte(0x74); /*JE +*/ + addbyte(5 + 5 + 2); + } - if (depth_jump_pos) - *(uint8_t *)&code_block[depth_jump_pos] = (block_pos - depth_jump_pos) - 1; - if (depth_jump_pos) - *(uint8_t *)&code_block[depth_jump_pos2] = (block_pos - depth_jump_pos2) - 1; - - if ((params->fogMode & (FOG_ENABLE|FOG_CONSTANT|FOG_Z|FOG_ALPHA)) == FOG_ENABLE) - { - addbyte(0x89); /*MOV state->w_depth[EDI], EAX*/ - addbyte(0x87); - addlong(offsetof(voodoo_state_t, w_depth)); - } + addbyte(0xf3); /*MOVQ XMM0, [EBX+EAX*4]*/ + addbyte(0x0f); + addbyte(0x7e); + addbyte(0x04); + addbyte(0x83); + addbyte(0xf3); /*MOVQ XMM1, [EDX+EAX*4]*/ + addbyte(0x0f); + addbyte(0x7e); + addbyte(0x0c); + addbyte(0x82); + + if (state->clamp_s[tmu]) { + addbyte(0xeb); /*JMP +*/ + addbyte(5 + 5 + 4 + 4); + + /*S clamped - the two S coordinates are the same*/ + addbyte(0x66); /*MOVD XMM0, [EBX+EAX*4]*/ + addbyte(0x0f); + addbyte(0x6e); + addbyte(0x04); + addbyte(0x83); + addbyte(0x66); /*MOVD XMM1, [EDX+EAX*4]*/ + addbyte(0x0f); + addbyte(0x6e); + addbyte(0x0c); + addbyte(0x82); + addbyte(0x66); /*PUNPCKLDQ XMM0, XMM0*/ + addbyte(0x0f); + addbyte(0x62); + addbyte(0xc0); + addbyte(0x66); /*PUNPCKLDQ XMM1, XMM1*/ + addbyte(0x0f); + addbyte(0x62); + addbyte(0xc9); + } else { + addbyte(0xeb); /*JMP +*/ + addbyte(5 + 5 + 5 + 5 + 6 + 6); + + /*S wrapped - the two S coordinates are not contiguous*/ + addbyte(0x66); /*MOVD XMM0, [EBX+EAX*4]*/ + addbyte(0x0f); + addbyte(0x6e); + addbyte(0x04); + addbyte(0x83); + addbyte(0x66); /*MOVD XMM1, [EDX+EAX*4]*/ + addbyte(0x0f); + addbyte(0x6e); + addbyte(0x0c); + addbyte(0x82); + addbyte(0x66); /*PINSRW XMM0, [EBX], 2*/ + addbyte(0x0f); + addbyte(0xc4); + addbyte(0x03); + addbyte(0x02); + addbyte(0x66); /*PINSRW XMM1, [EDX], 2*/ + addbyte(0x0f); + addbyte(0xc4); + addbyte(0x0a); + addbyte(0x02); + addbyte(0x66); /*PINSRW XMM0, 2[EBX], 3*/ + addbyte(0x0f); + addbyte(0xc4); + addbyte(0x43); + addbyte(0x02); + addbyte(0x03); + addbyte(0x66); /*PINSRW XMM1, 2[EDX], 3*/ + addbyte(0x0f); + addbyte(0xc4); + addbyte(0x4a); + addbyte(0x02); + addbyte(0x03); + } + + addbyte(0x66); /*PUNPCKLBW XMM0, XMM2*/ + addbyte(0x0f); + addbyte(0x60); + addbyte(0xc2); + addbyte(0x66); /*PUNPCKLBW XMM1, XMM2*/ + addbyte(0x0f); + addbyte(0x60); + addbyte(0xca); + + addbyte(0x81); /*ADD ESI, bilinear_lookup*/ + addbyte(0xc6); + addlong((uint32_t) bilinear_lookup); + + addbyte(0x66); /*PMULLW XMM0, bilinear_lookup[ESI]*/ + addbyte(0x0f); + addbyte(0xd5); + addbyte(0x06); + addbyte(0x66); /*PMULLW XMM1, bilinear_lookup[ESI]+0x10*/ + addbyte(0x0f); + addbyte(0xd5); + addbyte(0x4e); + addbyte(0x10); + addbyte(0x66); /*PADDW XMM0, XMM1*/ + addbyte(0x0f); + addbyte(0xfd); + addbyte(0xc0 | 1 | (0 << 3)); + addbyte(0x66); /*MOV XMM1, XMM0*/ + addbyte(0x0f); + addbyte(0x6f); + addbyte(0xc0 | 0 | (1 << 3)); + addbyte(0x66); /*PSRLDQ XMM0, 64*/ + addbyte(0x0f); + addbyte(0x73); + addbyte(0xd8); + addbyte(8); + addbyte(0x66); /*PADDW XMM0, XMM1*/ + addbyte(0x0f); + addbyte(0xfd); + addbyte(0xc0 | 1 | (0 << 3)); + addbyte(0x66); /*PSRLW XMM0, 8*/ + addbyte(0x0f); + addbyte(0x71); + addbyte(0xd0 | 0); + addbyte(8); + addbyte(0x66); /*PACKUSWB XMM0, XMM0*/ + addbyte(0x0f); + addbyte(0x67); + addbyte(0xc0); + + addbyte(0x8b); /*MOV ESI, [ESP+8]*/ + addbyte(0x74); + addbyte(0x24); + addbyte(8 + 16); /*CHECK!*/ + + addbyte(0x66); /*MOV EAX, XMM0*/ + addbyte(0x0f); + addbyte(0x7e); + addbyte(0xc0); + } else { + addbyte(0x8b); /*MOV ECX, state->tex_lod[tmu]*/ + addbyte(0x8f); + addlong(offsetof(voodoo_state_t, tex_lod[tmu])); + addbyte(0xb2); /*MOV DL, 8*/ + addbyte(8); + addbyte(0x8b); /*MOV ECX, [ECX+EAX*4]*/ + addbyte(0x0c); + addbyte(0x81); + addbyte(0x8b); /*MOV EBP, state->tex[EDI+ECX*4]*/ + addbyte(0xac); + addbyte(0x8f); + addlong(offsetof(voodoo_state_t, tex[tmu])); + addbyte(0x28); /*SUB DL, CL*/ + addbyte(0xca); + addbyte(0x80); /*ADD CL, 4*/ + addbyte(0xc1); + addbyte(4); + addbyte(0x8b); /*MOV EAX, state->tex_s[EDI]*/ + addbyte(0x87); + addlong(offsetof(voodoo_state_t, tex_s)); + addbyte(0x8b); /*MOV EBX, state->tex_t[EDI]*/ + addbyte(0x9f); + addlong(offsetof(voodoo_state_t, tex_t)); + if (params->tLOD[tmu] & LOD_TMIRROR_S) { + addbyte(0xa9); /*TEST EAX, 0x1000*/ + addlong(0x1000); + addbyte(0x74); /*JZ +*/ + addbyte(2); + addbyte(0xf7); /*NOT EAX*/ + addbyte(0xd0); + } + if (params->tLOD[tmu] & LOD_TMIRROR_T) { + addbyte(0xf7); /*TEST EBX, 0x1000*/ + addbyte(0xc3); + addlong(0x1000); + addbyte(0x74); /*JZ +*/ + addbyte(2); + addbyte(0xf7); /*NOT EBX*/ + addbyte(0xd3); + } + addbyte(0xd3); /*SHR EAX, CL*/ + addbyte(0xe8); + addbyte(0xd3); /*SHR EBX, CL*/ + addbyte(0xeb); + if (state->clamp_s[tmu]) { + addbyte(0x85); /*TEST EAX, EAX*/ + addbyte(0xc0); + addbyte(0x0f); /*CMOVS EAX, zero*/ + addbyte(0x48); + addbyte(0x05); + addlong((uint32_t) &zero); + addbyte(0x3b); /*CMP EAX, params->tex_w_mask[ESI+ECX*4]*/ + addbyte(0x84); + addbyte(0x8e); + addlong(offsetof(voodoo_params_t, tex_w_mask[tmu]) - 0x10); + addbyte(0x0f); /*CMOVAE EAX, params->tex_w_mask[ESI+ECX*4]*/ + addbyte(0x43); + addbyte(0x84); + addbyte(0x8e); + addlong(offsetof(voodoo_params_t, tex_w_mask[tmu]) - 0x10); + + } else { + addbyte(0x23); /*AND EAX, params->tex_w_mask-0x10[ESI+ECX*4]*/ + addbyte(0x84); + addbyte(0x8e); + addlong(offsetof(voodoo_params_t, tex_w_mask[tmu]) - 0x10); + } + if (state->clamp_t[tmu]) { + addbyte(0x85); /*TEST EBX, EBX*/ + addbyte(0xdb); + addbyte(0x0f); /*CMOVS EBX, zero*/ + addbyte(0x48); + addbyte(0x1d); + addlong((uint32_t) &zero); + addbyte(0x3b); /*CMP EBX, params->tex_h_mask[ESI+ECX*4]*/ + addbyte(0x9c); + addbyte(0x8e); + addlong(offsetof(voodoo_params_t, tex_h_mask[tmu]) - 0x10); + addbyte(0x0f); /*CMOVAE EBX, params->tex_h_mask[ESI+ECX*4]*/ + addbyte(0x43); + addbyte(0x9c); + addbyte(0x8e); + addlong(offsetof(voodoo_params_t, tex_h_mask[tmu]) - 0x10); + } else { + addbyte(0x23); /*AND EBX, params->tex_h_mask-0x10[ESI+ECX*4]*/ + addbyte(0x9c); + addbyte(0x8e); + addlong(offsetof(voodoo_params_t, tex_h_mask[tmu]) - 0x10); + } + addbyte(0x88); /*MOV CL, DL*/ + addbyte(0xd1); + addbyte(0xd3); /*SHL EBX, CL*/ + addbyte(0xe3); + addbyte(0x01); /*ADD EBX, EAX*/ + addbyte(0xc3); + + addbyte(0x8b); /*MOV EAX,[EBP+EBX*4]*/ + addbyte(0x44); + addbyte(0x9d); + addbyte(0); } - if (!(params->fbzMode & FBZ_W_BUFFER)) - { - addbyte(0x8b); /*MOV EAX, z*/ - addbyte(0x87); - addlong(offsetof(voodoo_state_t, z)); - addbyte(0xbb); /*MOV EBX, 0xffff*/ - addlong(0xffff); + } + + return block_pos; +} + +static inline void +voodoo_generate(uint8_t *code_block, voodoo_t *voodoo, voodoo_params_t *params, voodoo_state_t *state, int depthop) +{ + int block_pos = 0; + int z_skip_pos = 0; + int a_skip_pos = 0; + int chroma_skip_pos = 0; + int depth_jump_pos = 0; + int depth_jump_pos2 = 0; + int loop_jump_pos = 0; +#if 0 + xmm_01_w = (__m128i)0x0001000100010001ull; + xmm_ff_w = (__m128i)0x00ff00ff00ff00ffull; + xmm_ff_b = (__m128i)0x00000000ffffffffull; +#endif + xmm_01_w = _mm_set_epi32(0, 0, 0x00010001, 0x00010001); + xmm_ff_w = _mm_set_epi32(0, 0, 0x00ff00ff, 0x00ff00ff); + xmm_ff_b = _mm_set_epi32(0, 0, 0, 0x00ffffff); + minus_254 = _mm_set_epi32(0, 0, 0xff02ff02, 0xff02ff02); +#if 0 + *(uint64_t *)&const_1_48 = 0x45b0000000000000ull; + block_pos = 0; + voodoo_get_depth = &code_block[block_pos]; +#endif + /*W at (%esp+4) + Z at (%esp+12) + new_depth at (%esp+16)*/ +#if 0 + if ((params->fbzMode & FBZ_DEPTH_ENABLE) && (depth_op == DEPTHOP_NEVER)) { + addbyte(0xC3); /*RET*/ + return; + } +#endif + addbyte(0x55); /*PUSH EBP*/ + addbyte(0x57); /*PUSH EDI*/ + addbyte(0x56); /*PUSH ESI*/ + addbyte(0x53); /*PUSH EBX*/ + + addbyte(0x8b); /*MOV EDI, [ESP+4]*/ + addbyte(0x7c); + addbyte(0x24); + addbyte(4 + 16); + loop_jump_pos = block_pos; + addbyte(0x8b); /*MOV ESI, [ESP+8]*/ + addbyte(0x74); + addbyte(0x24); + addbyte(8 + 16); + if (params->col_tiled || params->aux_tiled) { + addbyte(0x8b); /*MOV EAX, state->x[EDI]*/ + addbyte(0x87); + addlong(offsetof(voodoo_state_t, x)); + addbyte(0x89); /*MOV EBX, EAX*/ + addbyte(0xc3); + addbyte(0x83); /*AND EAX, 63*/ + addbyte(0xe0); + addbyte(63); + addbyte(0xc1); /*SHR EBX, 6*/ + addbyte(0xeb); + addbyte(6); + addbyte(0xc1); /*SHL EBX, 11 - tile is 128*32, << 12, div 2 because word index*/ + addbyte(0xe3); + addbyte(11); + addbyte(0x01); /*ADD EAX, EBX*/ + addbyte(0xd8); + addbyte(0x89); /*MOV state->x_tiled[EDI], EAX*/ + addbyte(0x87); + addlong(offsetof(voodoo_state_t, x_tiled)); + } + addbyte(0x66); /*PXOR XMM2, XMM2*/ + addbyte(0x0f); + addbyte(0xef); + addbyte(0xd2); + + if ((params->fbzMode & FBZ_W_BUFFER) || (params->fogMode & (FOG_ENABLE | FOG_CONSTANT | FOG_Z | FOG_ALPHA)) == FOG_ENABLE) { + addbyte(0xb8); /*MOV new_depth, 0*/ + addlong(0); + addbyte(0x66); /*TEST w+4, 0xffff*/ + addbyte(0xf7); + addbyte(0x87); + addlong(offsetof(voodoo_state_t, w) + 4); + addword(0xffff); + addbyte(0x75); /*JNZ got_depth*/ + depth_jump_pos = block_pos; + addbyte(0); + // addbyte(4+5+2+3+2+5+5+3+2+2+2+/*3+*/3+2+6+4+5+2+3); + addbyte(0x8b); /*MOV EDX, w*/ + addbyte(0x97); + addlong(offsetof(voodoo_state_t, w)); + addbyte(0xb8); /*MOV new_depth, 0xf001*/ + addlong(0xf001); + addbyte(0x89); /*MOV EBX, EDX*/ + addbyte(0xd3); + addbyte(0xc1); /*SHR EDX, 16*/ + addbyte(0xea); + addbyte(16); + addbyte(0x74); /*JZ got_depth*/ + depth_jump_pos2 = block_pos; + addbyte(0); + // addbyte(5+5+3+2+2+2+/*3+*/3+2+6+4+5+2+3); + addbyte(0xb9); /*MOV ECX, 19*/ + addlong(19); + addbyte(0x0f); /*BSR EAX, EDX*/ + addbyte(0xbd); + addbyte(0xc2); + addbyte(0xba); /*MOV EDX, 15*/ + addlong(15); + addbyte(0xf7); /*NOT EBX*/ + addbyte(0xd3); + addbyte(0x29); /*SUB EDX, EAX - EDX = exp*/ + addbyte(0xc2); + addbyte(0x29); /*SUB ECX, EDX*/ + addbyte(0xd1); + addbyte(0xc1); /*SHL EDX, 12*/ + addbyte(0xe2); + addbyte(12); + addbyte(0xd3); /*SHR EBX, CL*/ + addbyte(0xeb); + addbyte(0x81); /*AND EBX, 0xfff - EBX = mant*/ + addbyte(0xe3); + addlong(0xfff); + addbyte(0x8d); /*LEA EAX, 1[EDX, EBX]*/ + addbyte(0x44); + addbyte(0x13); + addbyte(1); + addbyte(0xbb); /*MOV EBX, 0xffff*/ + addlong(0xffff); + addbyte(0x39); /*CMP EAX, EBX*/ + addbyte(0xd8); + addbyte(0x0f); /*CMOVA EAX, EBX*/ + addbyte(0x47); + addbyte(0xc3); + + if (depth_jump_pos) + *(uint8_t *) &code_block[depth_jump_pos] = (block_pos - depth_jump_pos) - 1; + if (depth_jump_pos) + *(uint8_t *) &code_block[depth_jump_pos2] = (block_pos - depth_jump_pos2) - 1; + + if ((params->fogMode & (FOG_ENABLE | FOG_CONSTANT | FOG_Z | FOG_ALPHA)) == FOG_ENABLE) { + addbyte(0x89); /*MOV state->w_depth[EDI], EAX*/ + addbyte(0x87); + addlong(offsetof(voodoo_state_t, w_depth)); + } + } + if (!(params->fbzMode & FBZ_W_BUFFER)) { + addbyte(0x8b); /*MOV EAX, z*/ + addbyte(0x87); + addlong(offsetof(voodoo_state_t, z)); + addbyte(0xbb); /*MOV EBX, 0xffff*/ + addlong(0xffff); + addbyte(0x31); /*XOR ECX, ECX*/ + addbyte(0xc9); + addbyte(0xc1); /*SAR EAX, 12*/ + addbyte(0xf8); + addbyte(12); + addbyte(0x0f); /*CMOVS EAX, ECX*/ + addbyte(0x48); + addbyte(0xc1); + addbyte(0x39); /*CMP EAX, EBX*/ + addbyte(0xd8); + addbyte(0x0f); /*CMOVA EAX, EBX*/ + addbyte(0x47); + addbyte(0xc3); + } + + if (params->fbzMode & FBZ_DEPTH_BIAS) { + addbyte(0x0f); /*MOVSX EDX, params->zaColor[ESI]*/ + addbyte(0xbf); + addbyte(0x96); + addlong(offsetof(voodoo_params_t, zaColor)); + if (params->fbzMode & FBZ_W_BUFFER) { + addbyte(0xbb); /*MOV EBX, 0xffff*/ + addlong(0xffff); + addbyte(0x31); /*XOR ECX, ECX*/ + addbyte(0xc9); + } + addbyte(0x01); /*ADD EAX, EDX*/ + addbyte(0xd0); + addbyte(0x0f); /*CMOVS EAX, ECX*/ + addbyte(0x48); + addbyte(0xc1); + addbyte(0x39); /*CMP EAX, EBX*/ + addbyte(0xd8); + addbyte(0x0f); /*CMOVA EAX, EBX*/ + addbyte(0x47); + addbyte(0xc3); + } + + addbyte(0x89); /*MOV state->new_depth[EDI], EAX*/ + addbyte(0x87); + addlong(offsetof(voodoo_state_t, new_depth)); + + if ((params->fbzMode & FBZ_DEPTH_ENABLE) && (depthop != DEPTHOP_ALWAYS) && (depthop != DEPTHOP_NEVER)) { + addbyte(0x8b); /*MOV EBX, state->x[EDI]*/ + addbyte(0x9f); + if (voodoo->aux_tiled) + addlong(offsetof(voodoo_state_t, x_tiled)); + else + addlong(offsetof(voodoo_state_t, x)); + addbyte(0x8b); /*MOV ECX, aux_mem[EDI]*/ + addbyte(0x8f); + addlong(offsetof(voodoo_state_t, aux_mem)); + addbyte(0x0f); /*MOVZX EBX, [ECX+EBX*2]*/ + addbyte(0xb7); + addbyte(0x1c); + addbyte(0x59); + if (params->fbzMode & FBZ_DEPTH_SOURCE) { + addbyte(0x0f); /*MOVZX EAX, zaColor[ESI]*/ + addbyte(0xb7); + addbyte(0x86); + addlong(offsetof(voodoo_params_t, zaColor)); + } + addbyte(0x39); /*CMP EAX, EBX*/ + addbyte(0xd8); + if (depthop == DEPTHOP_LESSTHAN) { + addbyte(0x0f); /*JAE skip*/ + addbyte(0x83); + z_skip_pos = block_pos; + addlong(0); + } else if (depthop == DEPTHOP_EQUAL) { + addbyte(0x0f); /*JNE skip*/ + addbyte(0x85); + z_skip_pos = block_pos; + addlong(0); + } else if (depthop == DEPTHOP_LESSTHANEQUAL) { + addbyte(0x0f); /*JA skip*/ + addbyte(0x87); + z_skip_pos = block_pos; + addlong(0); + } else if (depthop == DEPTHOP_GREATERTHAN) { + addbyte(0x0f); /*JBE skip*/ + addbyte(0x86); + z_skip_pos = block_pos; + addlong(0); + } else if (depthop == DEPTHOP_NOTEQUAL) { + addbyte(0x0f); /*JE skip*/ + addbyte(0x84); + z_skip_pos = block_pos; + addlong(0); + } else if (depthop == DEPTHOP_GREATERTHANEQUAL) { + addbyte(0x0f); /*JB skip*/ + addbyte(0x82); + z_skip_pos = block_pos; + addlong(0); + } else + fatal("Bad depth_op\n"); + } else if ((params->fbzMode & FBZ_DEPTH_ENABLE) && (depthop == DEPTHOP_NEVER)) { + addbyte(0xC3); /*RET*/ +#if 0 + addbyte(0x30); /*XOR EAX, EAX*/ + addbyte(0xc0); +#endif + } +#if 0 + else { + addbyte(0xb0); /*MOV AL, 1*/ + addbyte(1); + } + + voodoo_combine = &code_block[block_pos]; +#endif + /*XMM0 = colour*/ + /*XMM2 = 0 (for unpacking*/ + + /*EDI = state, ESI = params*/ + + if ((params->textureMode[0] & TEXTUREMODE_LOCAL_MASK) == TEXTUREMODE_LOCAL || !voodoo->dual_tmus) { + /*TMU0 only sampling local colour or only one TMU, only sample TMU0*/ + block_pos = codegen_texture_fetch(code_block, voodoo, params, state, block_pos, 0); + + addbyte(0x66); /*MOVD XMM0, EAX*/ + addbyte(0x0f); + addbyte(0x6e); + addbyte(0xc0); + addbyte(0xc1); /*SHR EAX, 24*/ + addbyte(0xe8); + addbyte(24); + addbyte(0x89); /*MOV state->tex_a[EDI], EAX*/ + addbyte(0x87); + addlong(offsetof(voodoo_state_t, tex_a)); + } else if ((params->textureMode[0] & TEXTUREMODE_MASK) == TEXTUREMODE_PASSTHROUGH) { + /*TMU0 in pass-through mode, only sample TMU1*/ + block_pos = codegen_texture_fetch(code_block, voodoo, params, state, block_pos, 1); + + addbyte(0x66); /*MOVD XMM0, EAX*/ + addbyte(0x0f); + addbyte(0x6e); + addbyte(0xc0); + addbyte(0xc1); /*SHR EAX, 24*/ + addbyte(0xe8); + addbyte(24); + addbyte(0x89); /*MOV state->tex_a[EDI], EAX*/ + addbyte(0x87); + addlong(offsetof(voodoo_state_t, tex_a)); + } else { + block_pos = codegen_texture_fetch(code_block, voodoo, params, state, block_pos, 1); + + addbyte(0x66); /*MOVD XMM3, EAX*/ + addbyte(0x0f); + addbyte(0x6e); + addbyte(0xd8); + if ((params->textureMode[1] & TEXTUREMODE_TRILINEAR) && tc_sub_clocal_1) { + addbyte(0x8b); /*MOV EAX, state->lod*/ + addbyte(0x87); + addlong(offsetof(voodoo_state_t, lod)); + if (!tc_reverse_blend_1) { + addbyte(0xbb); /*MOV EBX, 1*/ + addlong(1); + } else { + addbyte(0x31); /*XOR EBX, EBX*/ + addbyte(0xdb); + } + addbyte(0x83); /*AND EAX, 1*/ + addbyte(0xe0); + addbyte(1); + if (!tca_reverse_blend_1) { + addbyte(0xb9); /*MOV ECX, 1*/ + addlong(1); + } else { addbyte(0x31); /*XOR ECX, ECX*/ addbyte(0xc9); - addbyte(0xc1); /*SAR EAX, 12*/ - addbyte(0xf8); - addbyte(12); - addbyte(0x0f); /*CMOVS EAX, ECX*/ - addbyte(0x48); - addbyte(0xc1); - addbyte(0x39); /*CMP EAX, EBX*/ - addbyte(0xd8); - addbyte(0x0f); /*CMOVA EAX, EBX*/ - addbyte(0x47); - addbyte(0xc3); + } + addbyte(0x31); /*XOR EBX, EAX*/ + addbyte(0xc3); + addbyte(0x31); /*XOR ECX, EAX*/ + addbyte(0xc1); + addbyte(0xc1); /*SHL EBX, 4*/ + addbyte(0xe3); + addbyte(4); + /*EBX = tc_reverse_blend, ECX=tca_reverse_blend*/ } - - if (params->fbzMode & FBZ_DEPTH_BIAS) - { - addbyte(0x0f); /*MOVSX EDX, params->zaColor[ESI]*/ - addbyte(0xbf); - addbyte(0x96); - addlong(offsetof(voodoo_params_t, zaColor)); - if (params->fbzMode & FBZ_W_BUFFER) - { - addbyte(0xbb); /*MOV EBX, 0xffff*/ - addlong(0xffff); - addbyte(0x31); /*XOR ECX, ECX*/ - addbyte(0xc9); - } - addbyte(0x01); /*ADD EAX, EDX*/ - addbyte(0xd0); - addbyte(0x0f); /*CMOVS EAX, ECX*/ - addbyte(0x48); - addbyte(0xc1); - addbyte(0x39); /*CMP EAX, EBX*/ - addbyte(0xd8); - addbyte(0x0f); /*CMOVA EAX, EBX*/ - addbyte(0x47); - addbyte(0xc3); - } - - addbyte(0x89); /*MOV state->new_depth[EDI], EAX*/ - addbyte(0x87); - addlong(offsetof(voodoo_state_t, new_depth)); - - if ((params->fbzMode & FBZ_DEPTH_ENABLE) && (depthop != DEPTHOP_ALWAYS) && (depthop != DEPTHOP_NEVER)) - { - addbyte(0x8b); /*MOV EBX, state->x[EDI]*/ - addbyte(0x9f); - if (voodoo->aux_tiled) - addlong(offsetof(voodoo_state_t, x_tiled)); - else - addlong(offsetof(voodoo_state_t, x)); - addbyte(0x8b);/*MOV ECX, aux_mem[EDI]*/ - addbyte(0x8f); - addlong(offsetof(voodoo_state_t, aux_mem)); - addbyte(0x0f); /*MOVZX EBX, [ECX+EBX*2]*/ - addbyte(0xb7); - addbyte(0x1c); - addbyte(0x59); - if (params->fbzMode & FBZ_DEPTH_SOURCE) - { - addbyte(0x0f); /*MOVZX EAX, zaColor[ESI]*/ - addbyte(0xb7); - addbyte(0x86); - addlong(offsetof(voodoo_params_t, zaColor)); - } - addbyte(0x39); /*CMP EAX, EBX*/ - addbyte(0xd8); - if (depthop == DEPTHOP_LESSTHAN) - { - addbyte(0x0f); /*JAE skip*/ - addbyte(0x83); - z_skip_pos = block_pos; - addlong(0); - } - else if (depthop == DEPTHOP_EQUAL) - { - addbyte(0x0f); /*JNE skip*/ - addbyte(0x85); - z_skip_pos = block_pos; - addlong(0); - } - else if (depthop == DEPTHOP_LESSTHANEQUAL) - { - addbyte(0x0f); /*JA skip*/ - addbyte(0x87); - z_skip_pos = block_pos; - addlong(0); - } - else if (depthop == DEPTHOP_GREATERTHAN) - { - addbyte(0x0f); /*JBE skip*/ - addbyte(0x86); - z_skip_pos = block_pos; - addlong(0); - } - else if (depthop == DEPTHOP_NOTEQUAL) - { - addbyte(0x0f); /*JE skip*/ - addbyte(0x84); - z_skip_pos = block_pos; - addlong(0); - } - else if (depthop == DEPTHOP_GREATERTHANEQUAL) - { - addbyte(0x0f); /*JB skip*/ - addbyte(0x82); - z_skip_pos = block_pos; - addlong(0); - } - else - fatal("Bad depth_op\n"); - } - else if ((params->fbzMode & FBZ_DEPTH_ENABLE) && (depthop == DEPTHOP_NEVER)) - { - addbyte(0xC3); /*RET*/ -// addbyte(0x30); /*XOR EAX, EAX*/ -// addbyte(0xc0); - } -// else -// { -// addbyte(0xb0); /*MOV AL, 1*/ -// addbyte(1); -// } - - -// voodoo_combine = &code_block[block_pos]; - /*XMM0 = colour*/ - /*XMM2 = 0 (for unpacking*/ - - /*EDI = state, ESI = params*/ - - if ((params->textureMode[0] & TEXTUREMODE_LOCAL_MASK) == TEXTUREMODE_LOCAL || !voodoo->dual_tmus) - { - /*TMU0 only sampling local colour or only one TMU, only sample TMU0*/ - block_pos = codegen_texture_fetch(code_block, voodoo, params, state, block_pos, 0); - - addbyte(0x66); /*MOVD XMM0, EAX*/ + addbyte(0x66); /*PUNPCKLBW XMM3, XMM2*/ + addbyte(0x0f); + addbyte(0x60); + addbyte(0xda); + if (tc_sub_clocal_1) { + switch (tc_mselect_1) { + case TC_MSELECT_ZERO: + addbyte(0x66); /*PXOR XMM0, XMM0*/ + addbyte(0x0f); + addbyte(0xef); + addbyte(0xc0); + break; + case TC_MSELECT_CLOCAL: + addbyte(0xf3); /*MOVQ XMM0, XMM3*/ + addbyte(0x0f); + addbyte(0x7e); + addbyte(0xc3); + break; + case TC_MSELECT_AOTHER: + addbyte(0x66); /*PXOR XMM0, XMM0*/ + addbyte(0x0f); + addbyte(0xef); + addbyte(0xc0); + break; + case TC_MSELECT_ALOCAL: + addbyte(0xf2); /*PSHUFLW XMM0, XMM3, 0xff*/ + addbyte(0x0f); + addbyte(0x70); + addbyte(0xc3); + addbyte(0xff); + break; + case TC_MSELECT_DETAIL: + addbyte(0xb8); /*MOV EAX, params->detail_bias[1]*/ + addlong(params->detail_bias[1]); + addbyte(0x2b); /*SUB EAX, state->lod*/ + addbyte(0x87); + addlong(offsetof(voodoo_state_t, lod)); + addbyte(0xba); /*MOV EDX, params->detail_max[1]*/ + addlong(params->detail_max[1]); + addbyte(0xc1); /*SHL EAX, params->detail_scale[1]*/ + addbyte(0xe0); + addbyte(params->detail_scale[1]); + addbyte(0x39); /*CMP EAX, EDX*/ + addbyte(0xd0); + addbyte(0x0f); /*CMOVNL EAX, EDX*/ + addbyte(0x4d); + addbyte(0xc2); + addbyte(0x66); /*MOVD XMM0, EAX*/ + addbyte(0x0f); + addbyte(0x6e); + addbyte(0xc0); + addbyte(0xf2); /*PSHUFLW XMM0, XMM0, 0*/ + addbyte(0x0f); + addbyte(0x70); + addbyte(0xc0); + addbyte(0); + break; + case TC_MSELECT_LOD_FRAC: + addbyte(0x66); /*MOVD XMM0, state->lod_frac[1]*/ + addbyte(0x0f); + addbyte(0x6e); + addbyte(0x87); + addlong(offsetof(voodoo_state_t, lod_frac[1])); + addbyte(0xf2); /*PSHUFLW XMM0, XMM0, 0*/ + addbyte(0x0f); + addbyte(0x70); + addbyte(0xc0); + addbyte(0); + break; + } + if (params->textureMode[1] & TEXTUREMODE_TRILINEAR) { + addbyte(0x66); /*PXOR XMM0, xmm_00_ff_w[EBX]*/ addbyte(0x0f); - addbyte(0x6e); - addbyte(0xc0); - addbyte(0xc1); /*SHR EAX, 24*/ - addbyte(0xe8); - addbyte(24); - addbyte(0x89); /*MOV state->tex_a[EDI], EAX*/ - addbyte(0x87); - addlong(offsetof(voodoo_state_t, tex_a)); - } - else if ((params->textureMode[0] & TEXTUREMODE_MASK) == TEXTUREMODE_PASSTHROUGH) - { - /*TMU0 in pass-through mode, only sample TMU1*/ - block_pos = codegen_texture_fetch(code_block, voodoo, params, state, block_pos, 1); - - addbyte(0x66); /*MOVD XMM0, EAX*/ + addbyte(0xef); + addbyte(0x83); + addlong((uint32_t) &xmm_00_ff_w[0]); + } else if (!tc_reverse_blend_1) { + addbyte(0x66); /*PXOR XMM0, xmm_ff_w*/ addbyte(0x0f); - addbyte(0x6e); - addbyte(0xc0); - addbyte(0xc1); /*SHR EAX, 24*/ - addbyte(0xe8); - addbyte(24); - addbyte(0x89); /*MOV state->tex_a[EDI], EAX*/ - addbyte(0x87); - addlong(offsetof(voodoo_state_t, tex_a)); - } - else - { - block_pos = codegen_texture_fetch(code_block, voodoo, params, state, block_pos, 1); - - addbyte(0x66); /*MOVD XMM3, EAX*/ - addbyte(0x0f); - addbyte(0x6e); - addbyte(0xd8); - if ((params->textureMode[1] & TEXTUREMODE_TRILINEAR) && tc_sub_clocal_1) - { - addbyte(0x8b); /*MOV EAX, state->lod*/ - addbyte(0x87); - addlong(offsetof(voodoo_state_t, lod)); - if (!tc_reverse_blend_1) - { - addbyte(0xbb); /*MOV EBX, 1*/ - addlong(1); - } - else - { - addbyte(0x31); /*XOR EBX, EBX*/ - addbyte(0xdb); - } - addbyte(0x83); /*AND EAX, 1*/ - addbyte(0xe0); - addbyte(1); - if (!tca_reverse_blend_1) - { - addbyte(0xb9); /*MOV ECX, 1*/ - addlong(1); - } - else - { - addbyte(0x31); /*XOR ECX, ECX*/ - addbyte(0xc9); - } - addbyte(0x31); /*XOR EBX, EAX*/ - addbyte(0xc3); - addbyte(0x31); /*XOR ECX, EAX*/ - addbyte(0xc1); - addbyte(0xc1); /*SHL EBX, 4*/ - addbyte(0xe3); - addbyte(4); - /*EBX = tc_reverse_blend, ECX=tca_reverse_blend*/ - } - addbyte(0x66); /*PUNPCKLBW XMM3, XMM2*/ - addbyte(0x0f); - addbyte(0x60); - addbyte(0xda); - if (tc_sub_clocal_1) - { - switch (tc_mselect_1) - { - case TC_MSELECT_ZERO: - addbyte(0x66); /*PXOR XMM0, XMM0*/ - addbyte(0x0f); - addbyte(0xef); - addbyte(0xc0); - break; - case TC_MSELECT_CLOCAL: - addbyte(0xf3); /*MOVQ XMM0, XMM3*/ - addbyte(0x0f); - addbyte(0x7e); - addbyte(0xc3); - break; - case TC_MSELECT_AOTHER: - addbyte(0x66); /*PXOR XMM0, XMM0*/ - addbyte(0x0f); - addbyte(0xef); - addbyte(0xc0); - break; - case TC_MSELECT_ALOCAL: - addbyte(0xf2); /*PSHUFLW XMM0, XMM3, 0xff*/ - addbyte(0x0f); - addbyte(0x70); - addbyte(0xc3); - addbyte(0xff); - break; - case TC_MSELECT_DETAIL: - addbyte(0xb8); /*MOV EAX, params->detail_bias[1]*/ - addlong(params->detail_bias[1]); - addbyte(0x2b); /*SUB EAX, state->lod*/ - addbyte(0x87); - addlong(offsetof(voodoo_state_t, lod)); - addbyte(0xba); /*MOV EDX, params->detail_max[1]*/ - addlong(params->detail_max[1]); - addbyte(0xc1); /*SHL EAX, params->detail_scale[1]*/ - addbyte(0xe0); - addbyte(params->detail_scale[1]); - addbyte(0x39); /*CMP EAX, EDX*/ - addbyte(0xd0); - addbyte(0x0f); /*CMOVNL EAX, EDX*/ - addbyte(0x4d); - addbyte(0xc2); - addbyte(0x66); /*MOVD XMM0, EAX*/ - addbyte(0x0f); - addbyte(0x6e); - addbyte(0xc0); - addbyte(0xf2); /*PSHUFLW XMM0, XMM0, 0*/ - addbyte(0x0f); - addbyte(0x70); - addbyte(0xc0); - addbyte(0); - break; - case TC_MSELECT_LOD_FRAC: - addbyte(0x66); /*MOVD XMM0, state->lod_frac[1]*/ - addbyte(0x0f); - addbyte(0x6e); - addbyte(0x87); - addlong(offsetof(voodoo_state_t, lod_frac[1])); - addbyte(0xf2); /*PSHUFLW XMM0, XMM0, 0*/ - addbyte(0x0f); - addbyte(0x70); - addbyte(0xc0); - addbyte(0); - break; - } - if (params->textureMode[1] & TEXTUREMODE_TRILINEAR) - { - addbyte(0x66); /*PXOR XMM0, xmm_00_ff_w[EBX]*/ - addbyte(0x0f); - addbyte(0xef); - addbyte(0x83); - addlong((uint32_t)&xmm_00_ff_w[0]); - } - else if (!tc_reverse_blend_1) - { - addbyte(0x66); /*PXOR XMM0, xmm_ff_w*/ - addbyte(0x0f); - addbyte(0xef); - addbyte(0x05); - addlong((uint32_t)&xmm_ff_w); - } - addbyte(0x66); /*PADD XMM0, xmm_01_w*/ - addbyte(0x0f); - addbyte(0xfd); - addbyte(0x05); - addlong((uint32_t)&xmm_01_w); - addbyte(0xf3); /*MOVQ XMM1, XMM2*/ - addbyte(0x0f); - addbyte(0x7e); - addbyte(0xca); - addbyte(0xf3); /*MOVQ XMM5, XMM0*/ - addbyte(0x0f); - addbyte(0x7e); - addbyte(0xe8); - addbyte(0x66); /*PMULLW XMM0, XMM3*/ - addbyte(0x0f); - addbyte(0xd5); - addbyte(0xc3); - addbyte(0x66); /*PMULHW XMM5, XMM3*/ - addbyte(0x0f); - addbyte(0xe5); - addbyte(0xeb); - addbyte(0x66); /*PUNPCKLWD XMM0, XMM5*/ - addbyte(0x0f); - addbyte(0x61); - addbyte(0xc5); - addbyte(0x66); /*PSRAD XMM0, 8*/ - addbyte(0x0f); - addbyte(0x72); - addbyte(0xe0); - addbyte(8); - addbyte(0x66); /*PACKSSDW XMM0, XMM0*/ - addbyte(0x0f); - addbyte(0x6b); - addbyte(0xc0); - addbyte(0x66); /*PSUBW XMM1, XMM0*/ - addbyte(0x0f); - addbyte(0xf9); - addbyte(0xc8); - if (tc_add_clocal_1) - { - addbyte(0x66); /*PADDW XMM1, XMM3*/ - addbyte(0x0f); - addbyte(0xfd); - addbyte(0xcb); - } - else if (tc_add_alocal_1) - { - addbyte(0xf2); /*PSHUFLW XMM0, XMM3, 0xff*/ - addbyte(0x0f); - addbyte(0x70); - addbyte(0xc3); - addbyte(0xff); - addbyte(0x66); /*PADDW XMM1, XMM0*/ - addbyte(0x0f); - addbyte(0xfd); - addbyte(0xc8); - } - addbyte(0xf3); /*MOVD XMM3, XMM1*/ - addbyte(0x0f); - addbyte(0x7e); - addbyte(0xd9); - addbyte(0x66); /*PACKUSWB XMM3, XMM3*/ - addbyte(0x0f); - addbyte(0x67); - addbyte(0xdb); - if (tca_sub_clocal_1) - { - addbyte(0x66); /*MOVD EBX, XMM3*/ - addbyte(0x0f); - addbyte(0x7e); - addbyte(0xdb); - } - addbyte(0x66); /*PUNPCKLBW XMM3, XMM2*/ - addbyte(0x0f); - addbyte(0x60); - addbyte(0xda); - } - - if (tca_sub_clocal_1) - { - addbyte(0xc1); /*SHR EBX, 24*/ - addbyte(0xeb); - addbyte(24); - switch (tca_mselect_1) - { - case TCA_MSELECT_ZERO: - addbyte(0x31); /*XOR EAX, EAX*/ - addbyte(0xc0); - break; - case TCA_MSELECT_CLOCAL: - addbyte(0x89); /*MOV EAX, EBX*/ - addbyte(0xd8); - break; - case TCA_MSELECT_AOTHER: - addbyte(0x31); /*XOR EAX, EAX*/ - addbyte(0xc0); - break; - case TCA_MSELECT_ALOCAL: - addbyte(0x89); /*MOV EAX, EBX*/ - addbyte(0xd8); - break; - case TCA_MSELECT_DETAIL: - addbyte(0xb8); /*MOV EAX, params->detail_bias[1]*/ - addlong(params->detail_bias[1]); - addbyte(0x2b); /*SUB EAX, state->lod*/ - addbyte(0x87); - addlong(offsetof(voodoo_state_t, lod)); - addbyte(0xba); /*MOV EDX, params->detail_max[1]*/ - addlong(params->detail_max[1]); - addbyte(0xc1); /*SHL EAX, params->detail_scale[1]*/ - addbyte(0xe0); - addbyte(params->detail_scale[1]); - addbyte(0x39); /*CMP EAX, EDX*/ - addbyte(0xd0); - addbyte(0x0f); /*CMOVNL EAX, EDX*/ - addbyte(0x4d); - addbyte(0xc2); - break; - case TCA_MSELECT_LOD_FRAC: - addbyte(0x8b); /*MOV EAX, state->lod_frac[1]*/ - addbyte(0x87); - addlong(offsetof(voodoo_state_t, lod_frac[1])); - break; - } - if (params->textureMode[1] & TEXTUREMODE_TRILINEAR) - { - addbyte(0x33); /*XOR EAX, i_00_ff_w[ECX*4]*/ - addbyte(0x04); - addbyte(0x8d); - addlong((uint32_t)i_00_ff_w); - } - else if (!tc_reverse_blend_1) - { - addbyte(0x35); /*XOR EAX, 0xff*/ - addlong(0xff); - } - addbyte(0x83); /*ADD EAX, 1*/ - addbyte(0xc0); - addbyte(1); - addbyte(0x0f); /*IMUL EAX, EBX*/ - addbyte(0xaf); - addbyte(0xc3); - addbyte(0xb9); /*MOV ECX, 0xff*/ - addlong(0xff); - addbyte(0xf7); /*NEG EAX*/ - addbyte(0xd8); - addbyte(0xc1); /*SAR EAX, 8*/ - addbyte(0xf8); - addbyte(8); - if (tca_add_clocal_1 || tca_add_alocal_1) - { - addbyte(0x01); /*ADD EAX, EBX*/ - addbyte(0xd8); - } - addbyte(0x39); /*CMP ECX, EAX*/ - addbyte(0xc1); - addbyte(0x0f); /*CMOVA ECX, EAX*/ - addbyte(0x47); - addbyte(0xc8); - addbyte(0x66); /*PINSRW 3, XMM3, XMM0*/ - addbyte(0x0f); - addbyte(0xc4); - addbyte(0xd8); - addbyte(3); - } - - block_pos = codegen_texture_fetch(code_block, voodoo, params, state, block_pos, 0); - - addbyte(0x66); /*MOVD XMM0, EAX*/ - addbyte(0x0f); - addbyte(0x6e); - addbyte(0xc0); - addbyte(0x66); /*MOVD XMM7, EAX*/ - addbyte(0x0f); - addbyte(0x6e); - addbyte(0xf8); - - if (params->textureMode[0] & TEXTUREMODE_TRILINEAR) - { - addbyte(0x8b); /*MOV EAX, state->lod*/ - addbyte(0x87); - addlong(offsetof(voodoo_state_t, lod)); - if (!tc_reverse_blend) - { - addbyte(0xbb); /*MOV EBX, 1*/ - addlong(1); - } - else - { - addbyte(0x31); /*XOR EBX, EBX*/ - addbyte(0xdb); - } - addbyte(0x83); /*AND EAX, 1*/ - addbyte(0xe0); - addbyte(1); - if (!tca_reverse_blend) - { - addbyte(0xb9); /*MOV ECX, 1*/ - addlong(1); - } - else - { - addbyte(0x31); /*XOR ECX, ECX*/ - addbyte(0xc9); - } - addbyte(0x31); /*XOR EBX, EAX*/ - addbyte(0xc3); - addbyte(0x31); /*XOR ECX, EAX*/ - addbyte(0xc1); - addbyte(0xc1); /*SHL EBX, 4*/ - addbyte(0xe3); - addbyte(4); - /*EBX = tc_reverse_blend, ECX=tca_reverse_blend*/ - } - - /*XMM0 = TMU0 output, XMM3 = TMU1 output*/ - - addbyte(0x66); /*PUNPCKLBW XMM0, XMM2*/ - addbyte(0x0f); - addbyte(0x60); - addbyte(0xc2); - if (tc_zero_other) - { - addbyte(0x66); /*PXOR XMM1, XMM1*/ - addbyte(0x0f); - addbyte(0xef); - addbyte(0xc9); - } - else - { - addbyte(0xf3); /*MOV XMM1, XMM3*/ - addbyte(0x0f); - addbyte(0x7e); - addbyte(0xcb); - } - if (tc_sub_clocal) - { - addbyte(0x66); /*PSUBW XMM1, XMM0*/ - addbyte(0x0f); - addbyte(0xf9); - addbyte(0xc8); - } - - switch (tc_mselect) - { - case TC_MSELECT_ZERO: - addbyte(0x66); /*PXOR XMM4, XMM4*/ - addbyte(0x0f); - addbyte(0xef); - addbyte(0xe4); - break; - case TC_MSELECT_CLOCAL: - addbyte(0xf3); /*MOV XMM4, XMM0*/ - addbyte(0x0f); - addbyte(0x7e); - addbyte(0xe0); - break; - case TC_MSELECT_AOTHER: - addbyte(0xf2); /*PSHUFLW XMM4, XMM3, 3, 3, 3, 3*/ - addbyte(0x0f); - addbyte(0x70); - addbyte(0xe3); - addbyte(0xff); - break; - case TC_MSELECT_ALOCAL: - addbyte(0xf2); /*PSHUFLW XMM4, XMM0, 3, 3, 3, 3*/ - addbyte(0x0f); - addbyte(0x70); - addbyte(0xe0); - addbyte(0xff); - break; - case TC_MSELECT_DETAIL: - addbyte(0xb8); /*MOV EAX, params->detail_bias[0]*/ - addlong(params->detail_bias[0]); - addbyte(0x2b); /*SUB EAX, state->lod*/ - addbyte(0x87); - addlong(offsetof(voodoo_state_t, lod)); - addbyte(0xba); /*MOV EDX, params->detail_max[0]*/ - addlong(params->detail_max[0]); - addbyte(0xc1); /*SHL EAX, params->detail_scale[0]*/ - addbyte(0xe0); - addbyte(params->detail_scale[0]); - addbyte(0x39); /*CMP EAX, EDX*/ - addbyte(0xd0); - addbyte(0x0f); /*CMOVNL EAX, EDX*/ - addbyte(0x4d); - addbyte(0xc2); - addbyte(0x66); /*MOVD XMM4, EAX*/ - addbyte(0x0f); - addbyte(0x6e); - addbyte(0xe0); - addbyte(0xf2); /*PSHUFLW XMM4, XMM4, 0*/ - addbyte(0x0f); - addbyte(0x70); - addbyte(0xe4); - addbyte(0); - break; - case TC_MSELECT_LOD_FRAC: - addbyte(0x66); /*MOVD XMM0, state->lod_frac[0]*/ - addbyte(0x0f); - addbyte(0x6e); - addbyte(0xa7); - addlong(offsetof(voodoo_state_t, lod_frac[0])); - addbyte(0xf2); /*PSHUFLW XMM0, XMM0, 0*/ - addbyte(0x0f); - addbyte(0x70); - addbyte(0xe4); - addbyte(0); - break; - } - if (params->textureMode[0] & TEXTUREMODE_TRILINEAR) - { - addbyte(0x66); /*PXOR XMM4, xmm_00_ff_w[EBX]*/ - addbyte(0x0f); - addbyte(0xef); - addbyte(0xa3); - addlong((uint32_t)&xmm_00_ff_w[0]); - } - else if (!tc_reverse_blend) - { - addbyte(0x66); /*PXOR XMM4, FF*/ - addbyte(0x0f); - addbyte(0xef); - addbyte(0x25); - addlong((uint32_t)&xmm_ff_w); - } - addbyte(0x66); /*PADDW XMM4, 1*/ + addbyte(0xef); + addbyte(0x05); + addlong((uint32_t) &xmm_ff_w); + } + addbyte(0x66); /*PADD XMM0, xmm_01_w*/ + addbyte(0x0f); + addbyte(0xfd); + addbyte(0x05); + addlong((uint32_t) &xmm_01_w); + addbyte(0xf3); /*MOVQ XMM1, XMM2*/ + addbyte(0x0f); + addbyte(0x7e); + addbyte(0xca); + addbyte(0xf3); /*MOVQ XMM5, XMM0*/ + addbyte(0x0f); + addbyte(0x7e); + addbyte(0xe8); + addbyte(0x66); /*PMULLW XMM0, XMM3*/ + addbyte(0x0f); + addbyte(0xd5); + addbyte(0xc3); + addbyte(0x66); /*PMULHW XMM5, XMM3*/ + addbyte(0x0f); + addbyte(0xe5); + addbyte(0xeb); + addbyte(0x66); /*PUNPCKLWD XMM0, XMM5*/ + addbyte(0x0f); + addbyte(0x61); + addbyte(0xc5); + addbyte(0x66); /*PSRAD XMM0, 8*/ + addbyte(0x0f); + addbyte(0x72); + addbyte(0xe0); + addbyte(8); + addbyte(0x66); /*PACKSSDW XMM0, XMM0*/ + addbyte(0x0f); + addbyte(0x6b); + addbyte(0xc0); + addbyte(0x66); /*PSUBW XMM1, XMM0*/ + addbyte(0x0f); + addbyte(0xf9); + addbyte(0xc8); + if (tc_add_clocal_1) { + addbyte(0x66); /*PADDW XMM1, XMM3*/ addbyte(0x0f); addbyte(0xfd); - addbyte(0x25); - addlong((uint32_t)&xmm_01_w); - addbyte(0xf3); /*MOVQ XMM5, XMM1*/ + addbyte(0xcb); + } else if (tc_add_alocal_1) { + addbyte(0xf2); /*PSHUFLW XMM0, XMM3, 0xff*/ + addbyte(0x0f); + addbyte(0x70); + addbyte(0xc3); + addbyte(0xff); + addbyte(0x66); /*PADDW XMM1, XMM0*/ + addbyte(0x0f); + addbyte(0xfd); + addbyte(0xc8); + } + addbyte(0xf3); /*MOVD XMM3, XMM1*/ + addbyte(0x0f); + addbyte(0x7e); + addbyte(0xd9); + addbyte(0x66); /*PACKUSWB XMM3, XMM3*/ + addbyte(0x0f); + addbyte(0x67); + addbyte(0xdb); + if (tca_sub_clocal_1) { + addbyte(0x66); /*MOVD EBX, XMM3*/ addbyte(0x0f); addbyte(0x7e); - addbyte(0xe9); - addbyte(0x66); /*PMULLW XMM1, XMM4*/ - addbyte(0x0f); - addbyte(0xd5); - addbyte(0xcc); + addbyte(0xdb); + } + addbyte(0x66); /*PUNPCKLBW XMM3, XMM2*/ + addbyte(0x0f); + addbyte(0x60); + addbyte(0xda); + } - if (tca_sub_clocal) - { - addbyte(0x66); /*MOV EBX, XMM7*/ - addbyte(0x0f); - addbyte(0x7e); - addbyte(0xfb); - } + if (tca_sub_clocal_1) { + addbyte(0xc1); /*SHR EBX, 24*/ + addbyte(0xeb); + addbyte(24); + switch (tca_mselect_1) { + case TCA_MSELECT_ZERO: + addbyte(0x31); /*XOR EAX, EAX*/ + addbyte(0xc0); + break; + case TCA_MSELECT_CLOCAL: + addbyte(0x89); /*MOV EAX, EBX*/ + addbyte(0xd8); + break; + case TCA_MSELECT_AOTHER: + addbyte(0x31); /*XOR EAX, EAX*/ + addbyte(0xc0); + break; + case TCA_MSELECT_ALOCAL: + addbyte(0x89); /*MOV EAX, EBX*/ + addbyte(0xd8); + break; + case TCA_MSELECT_DETAIL: + addbyte(0xb8); /*MOV EAX, params->detail_bias[1]*/ + addlong(params->detail_bias[1]); + addbyte(0x2b); /*SUB EAX, state->lod*/ + addbyte(0x87); + addlong(offsetof(voodoo_state_t, lod)); + addbyte(0xba); /*MOV EDX, params->detail_max[1]*/ + addlong(params->detail_max[1]); + addbyte(0xc1); /*SHL EAX, params->detail_scale[1]*/ + addbyte(0xe0); + addbyte(params->detail_scale[1]); + addbyte(0x39); /*CMP EAX, EDX*/ + addbyte(0xd0); + addbyte(0x0f); /*CMOVNL EAX, EDX*/ + addbyte(0x4d); + addbyte(0xc2); + break; + case TCA_MSELECT_LOD_FRAC: + addbyte(0x8b); /*MOV EAX, state->lod_frac[1]*/ + addbyte(0x87); + addlong(offsetof(voodoo_state_t, lod_frac[1])); + break; + } + if (params->textureMode[1] & TEXTUREMODE_TRILINEAR) { + addbyte(0x33); /*XOR EAX, i_00_ff_w[ECX*4]*/ + addbyte(0x04); + addbyte(0x8d); + addlong((uint32_t) i_00_ff_w); + } else if (!tc_reverse_blend_1) { + addbyte(0x35); /*XOR EAX, 0xff*/ + addlong(0xff); + } + addbyte(0x83); /*ADD EAX, 1*/ + addbyte(0xc0); + addbyte(1); + addbyte(0x0f); /*IMUL EAX, EBX*/ + addbyte(0xaf); + addbyte(0xc3); + addbyte(0xb9); /*MOV ECX, 0xff*/ + addlong(0xff); + addbyte(0xf7); /*NEG EAX*/ + addbyte(0xd8); + addbyte(0xc1); /*SAR EAX, 8*/ + addbyte(0xf8); + addbyte(8); + if (tca_add_clocal_1 || tca_add_alocal_1) { + addbyte(0x01); /*ADD EAX, EBX*/ + addbyte(0xd8); + } + addbyte(0x39); /*CMP ECX, EAX*/ + addbyte(0xc1); + addbyte(0x0f); /*CMOVA ECX, EAX*/ + addbyte(0x47); + addbyte(0xc8); + addbyte(0x66); /*PINSRW 3, XMM3, XMM0*/ + addbyte(0x0f); + addbyte(0xc4); + addbyte(0xd8); + addbyte(3); + } - addbyte(0x66); /*PMULHW XMM5, XMM4*/ + block_pos = codegen_texture_fetch(code_block, voodoo, params, state, block_pos, 0); + + addbyte(0x66); /*MOVD XMM0, EAX*/ + addbyte(0x0f); + addbyte(0x6e); + addbyte(0xc0); + addbyte(0x66); /*MOVD XMM7, EAX*/ + addbyte(0x0f); + addbyte(0x6e); + addbyte(0xf8); + + if (params->textureMode[0] & TEXTUREMODE_TRILINEAR) { + addbyte(0x8b); /*MOV EAX, state->lod*/ + addbyte(0x87); + addlong(offsetof(voodoo_state_t, lod)); + if (!tc_reverse_blend) { + addbyte(0xbb); /*MOV EBX, 1*/ + addlong(1); + } else { + addbyte(0x31); /*XOR EBX, EBX*/ + addbyte(0xdb); + } + addbyte(0x83); /*AND EAX, 1*/ + addbyte(0xe0); + addbyte(1); + if (!tca_reverse_blend) { + addbyte(0xb9); /*MOV ECX, 1*/ + addlong(1); + } else { + addbyte(0x31); /*XOR ECX, ECX*/ + addbyte(0xc9); + } + addbyte(0x31); /*XOR EBX, EAX*/ + addbyte(0xc3); + addbyte(0x31); /*XOR ECX, EAX*/ + addbyte(0xc1); + addbyte(0xc1); /*SHL EBX, 4*/ + addbyte(0xe3); + addbyte(4); + /*EBX = tc_reverse_blend, ECX=tca_reverse_blend*/ + } + + /*XMM0 = TMU0 output, XMM3 = TMU1 output*/ + + addbyte(0x66); /*PUNPCKLBW XMM0, XMM2*/ + addbyte(0x0f); + addbyte(0x60); + addbyte(0xc2); + if (tc_zero_other) { + addbyte(0x66); /*PXOR XMM1, XMM1*/ + addbyte(0x0f); + addbyte(0xef); + addbyte(0xc9); + } else { + addbyte(0xf3); /*MOV XMM1, XMM3*/ + addbyte(0x0f); + addbyte(0x7e); + addbyte(0xcb); + } + if (tc_sub_clocal) { + addbyte(0x66); /*PSUBW XMM1, XMM0*/ + addbyte(0x0f); + addbyte(0xf9); + addbyte(0xc8); + } + + switch (tc_mselect) { + case TC_MSELECT_ZERO: + addbyte(0x66); /*PXOR XMM4, XMM4*/ addbyte(0x0f); - addbyte(0xe5); - addbyte(0xec); - addbyte(0x66); /*PUNPCKLWD XMM1, XMM5*/ + addbyte(0xef); + addbyte(0xe4); + break; + case TC_MSELECT_CLOCAL: + addbyte(0xf3); /*MOV XMM4, XMM0*/ addbyte(0x0f); - addbyte(0x61); - addbyte(0xcd); - addbyte(0x66); /*PSRAD XMM1, 8*/ + addbyte(0x7e); + addbyte(0xe0); + break; + case TC_MSELECT_AOTHER: + addbyte(0xf2); /*PSHUFLW XMM4, XMM3, 3, 3, 3, 3*/ + addbyte(0x0f); + addbyte(0x70); + addbyte(0xe3); + addbyte(0xff); + break; + case TC_MSELECT_ALOCAL: + addbyte(0xf2); /*PSHUFLW XMM4, XMM0, 3, 3, 3, 3*/ + addbyte(0x0f); + addbyte(0x70); + addbyte(0xe0); + addbyte(0xff); + break; + case TC_MSELECT_DETAIL: + addbyte(0xb8); /*MOV EAX, params->detail_bias[0]*/ + addlong(params->detail_bias[0]); + addbyte(0x2b); /*SUB EAX, state->lod*/ + addbyte(0x87); + addlong(offsetof(voodoo_state_t, lod)); + addbyte(0xba); /*MOV EDX, params->detail_max[0]*/ + addlong(params->detail_max[0]); + addbyte(0xc1); /*SHL EAX, params->detail_scale[0]*/ + addbyte(0xe0); + addbyte(params->detail_scale[0]); + addbyte(0x39); /*CMP EAX, EDX*/ + addbyte(0xd0); + addbyte(0x0f); /*CMOVNL EAX, EDX*/ + addbyte(0x4d); + addbyte(0xc2); + addbyte(0x66); /*MOVD XMM4, EAX*/ + addbyte(0x0f); + addbyte(0x6e); + addbyte(0xe0); + addbyte(0xf2); /*PSHUFLW XMM4, XMM4, 0*/ + addbyte(0x0f); + addbyte(0x70); + addbyte(0xe4); + addbyte(0); + break; + case TC_MSELECT_LOD_FRAC: + addbyte(0x66); /*MOVD XMM0, state->lod_frac[0]*/ + addbyte(0x0f); + addbyte(0x6e); + addbyte(0xa7); + addlong(offsetof(voodoo_state_t, lod_frac[0])); + addbyte(0xf2); /*PSHUFLW XMM0, XMM0, 0*/ + addbyte(0x0f); + addbyte(0x70); + addbyte(0xe4); + addbyte(0); + break; + } + if (params->textureMode[0] & TEXTUREMODE_TRILINEAR) { + addbyte(0x66); /*PXOR XMM4, xmm_00_ff_w[EBX]*/ + addbyte(0x0f); + addbyte(0xef); + addbyte(0xa3); + addlong((uint32_t) &xmm_00_ff_w[0]); + } else if (!tc_reverse_blend) { + addbyte(0x66); /*PXOR XMM4, FF*/ + addbyte(0x0f); + addbyte(0xef); + addbyte(0x25); + addlong((uint32_t) &xmm_ff_w); + } + addbyte(0x66); /*PADDW XMM4, 1*/ + addbyte(0x0f); + addbyte(0xfd); + addbyte(0x25); + addlong((uint32_t) &xmm_01_w); + addbyte(0xf3); /*MOVQ XMM5, XMM1*/ + addbyte(0x0f); + addbyte(0x7e); + addbyte(0xe9); + addbyte(0x66); /*PMULLW XMM1, XMM4*/ + addbyte(0x0f); + addbyte(0xd5); + addbyte(0xcc); + + if (tca_sub_clocal) { + addbyte(0x66); /*MOV EBX, XMM7*/ + addbyte(0x0f); + addbyte(0x7e); + addbyte(0xfb); + } + + addbyte(0x66); /*PMULHW XMM5, XMM4*/ + addbyte(0x0f); + addbyte(0xe5); + addbyte(0xec); + addbyte(0x66); /*PUNPCKLWD XMM1, XMM5*/ + addbyte(0x0f); + addbyte(0x61); + addbyte(0xcd); + addbyte(0x66); /*PSRAD XMM1, 8*/ + addbyte(0x0f); + addbyte(0x72); + addbyte(0xe1); + addbyte(8); + addbyte(0x66); /*PACKSSDW XMM1, XMM1*/ + addbyte(0x0f); + addbyte(0x6b); + addbyte(0xc9); + + if (tca_sub_clocal) { + addbyte(0xc1); /*SHR EBX, 24*/ + addbyte(0xeb); + addbyte(24); + } + + if (tc_add_clocal) { + addbyte(0x66); /*PADDW XMM1, XMM0*/ + addbyte(0x0f); + addbyte(0xfd); + addbyte(0xc8); + } else if (tc_add_alocal) { + addbyte(0xf2); /*PSHUFLW XMM4, XMM0, 3, 3, 3, 3*/ + addbyte(0x0f); + addbyte(0x70); + addbyte(0xe0); + addbyte(0xff); + addbyte(0x66); /*PADDW XMM1, XMM4*/ + addbyte(0x0f); + addbyte(0xfd); + addbyte(0xcc); + } + + addbyte(0x66); /*PACKUSWB XMM0, XMM0*/ + addbyte(0x0f); + addbyte(0x67); + addbyte(0xc0); + addbyte(0x66); /*PACKUSWB XMM3, XMM3*/ + addbyte(0x0f); + addbyte(0x67); + addbyte(0xdb); + addbyte(0x66); /*PACKUSWB XMM1, XMM1*/ + addbyte(0x0f); + addbyte(0x67); + addbyte(0xc9); + if (tc_invert_output) { + addbyte(0x66); /*PXOR XMM1, FF*/ + addbyte(0x0f); + addbyte(0xef); + addbyte(0x0d); + addlong((uint32_t) &xmm_ff_b); + } + + if (tca_zero_other) { + addbyte(0x31); /*XOR EAX, EAX*/ + addbyte(0xc0); + } else { + addbyte(0x66); /*MOV EAX, XMM3*/ + addbyte(0x0f); + addbyte(0x7e); + addbyte(0xd8); + addbyte(0xc1); /*SHR EAX, 24*/ + addbyte(0xe8); + addbyte(24); + } + if (tca_sub_clocal) { + addbyte(0x29); /*SUB EAX, EBX*/ + addbyte(0xd8); + } + switch (tca_mselect) { + case TCA_MSELECT_ZERO: + addbyte(0x31); /*XOR EBX, EBX*/ + addbyte(0xdb); + break; + case TCA_MSELECT_CLOCAL: + addbyte(0x66); /*MOV EBX, XMM7*/ + addbyte(0x0f); + addbyte(0x7e); + addbyte(0xfb); + addbyte(0xc1); /*SHR EBX, 24*/ + addbyte(0xeb); + addbyte(24); + break; + case TCA_MSELECT_AOTHER: + addbyte(0x66); /*MOV EBX, XMM3*/ + addbyte(0x0f); + addbyte(0x7e); + addbyte(0xdb); + addbyte(0xc1); /*SHR EBX, 24*/ + addbyte(0xeb); + addbyte(24); + break; + case TCA_MSELECT_ALOCAL: + addbyte(0x66); /*MOV EBX, XMM7*/ + addbyte(0x0f); + addbyte(0x7e); + addbyte(0xfb); + addbyte(0xc1); /*SHR EBX, 24*/ + addbyte(0xeb); + addbyte(24); + break; + case TCA_MSELECT_DETAIL: + addbyte(0xbb); /*MOV EBX, params->detail_bias[1]*/ + addlong(params->detail_bias[1]); + addbyte(0x2b); /*SUB EBX, state->lod*/ + addbyte(0x9f); + addlong(offsetof(voodoo_state_t, lod)); + addbyte(0xba); /*MOV EDX, params->detail_max[1]*/ + addlong(params->detail_max[1]); + addbyte(0xc1); /*SHL EBX, params->detail_scale[1]*/ + addbyte(0xe3); + addbyte(params->detail_scale[1]); + addbyte(0x39); /*CMP EBX, EDX*/ + addbyte(0xd3); + addbyte(0x0f); /*CMOVNL EBX, EDX*/ + addbyte(0x4d); + addbyte(0xda); + break; + case TCA_MSELECT_LOD_FRAC: + addbyte(0x8b); /*MOV EBX, state->lod_frac[0]*/ + addbyte(0x9f); + addlong(offsetof(voodoo_state_t, lod_frac[0])); + break; + } + if (params->textureMode[0] & TEXTUREMODE_TRILINEAR) { + addbyte(0x33); /*XOR EBX, i_00_ff_w[ECX*4]*/ + addbyte(0x1c); + addbyte(0x8d); + addlong((uint32_t) i_00_ff_w); + } else if (!tca_reverse_blend) { + addbyte(0x81); /*XOR EBX, 0xFF*/ + addbyte(0xf3); + addlong(0xff); + } + + addbyte(0x83); /*ADD EBX, 1*/ + addbyte(0xc3); + addbyte(1); + addbyte(0x0f); /*IMUL EAX, EBX*/ + addbyte(0xaf); + addbyte(0xc3); + addbyte(0x31); /*XOR EDX, EDX*/ + addbyte(0xd2); + addbyte(0xc1); /*SAR EAX, 8*/ + addbyte(0xf8); + addbyte(8); + if (tca_add_clocal || tca_add_alocal) { + addbyte(0x66); /*MOV EBX, XMM7*/ + addbyte(0x0f); + addbyte(0x7e); + addbyte(0xfb); + addbyte(0xc1); /*SHR EBX, 24*/ + addbyte(0xeb); + addbyte(24); + addbyte(0x01); /*ADD EAX, EBX*/ + addbyte(0xd8); + } + addbyte(0x0f); /*CMOVS EAX, EDX*/ + addbyte(0x48); + addbyte(0xc2); + addbyte(0xba); /*MOV EDX, 0xff*/ + addlong(0xff); + addbyte(0x3d); /*CMP EAX, 0xff*/ + addlong(0xff); + addbyte(0x0f); /*CMOVA EAX, EDX*/ + addbyte(0x47); + addbyte(0xc2); + if (tca_invert_output) { + addbyte(0x35); /*XOR EAX, 0xff*/ + addlong(0xff); + } + + addbyte(0x89); /*MOV state->tex_a[EDI], EAX*/ + addbyte(0x87); + addlong(offsetof(voodoo_state_t, tex_a)); + + addbyte(0xf3); /*MOVQ XMM0, XMM1*/ + addbyte(0x0f); + addbyte(0x7e); + addbyte(0xc1); + } + if (cc_mselect == CC_MSELECT_TEXRGB) { + addbyte(0xf3); /*MOVD XMM4, XMM0*/ + addbyte(0x0f); + addbyte(0x7e); + addbyte(0xe0); + } + + if ((params->fbzMode & FBZ_CHROMAKEY)) { + switch (_rgb_sel) { + case CC_LOCALSELECT_ITER_RGB: + addbyte(0xf3); /*MOVDQU XMM0, ib*/ /* ir, ig and ib must be in same dqword!*/ + addbyte(0x0f); + addbyte(0x6f); + addbyte(0x87); + addlong(offsetof(voodoo_state_t, ib)); + addbyte(0x66); /*PSRAD XMM0, 12*/ addbyte(0x0f); addbyte(0x72); - addbyte(0xe1); - addbyte(8); - addbyte(0x66); /*PACKSSDW XMM1, XMM1*/ + addbyte(0xe0); + addbyte(12); + addbyte(0x66); /*PACKSSDW XMM0, XMM0*/ addbyte(0x0f); addbyte(0x6b); - addbyte(0xc9); - - if (tca_sub_clocal) - { - addbyte(0xc1); /*SHR EBX, 24*/ - addbyte(0xeb); - addbyte(24); - } - - if (tc_add_clocal) - { - addbyte(0x66); /*PADDW XMM1, XMM0*/ - addbyte(0x0f); - addbyte(0xfd); - addbyte(0xc8); - } - else if (tc_add_alocal) - { - addbyte(0xf2); /*PSHUFLW XMM4, XMM0, 3, 3, 3, 3*/ - addbyte(0x0f); - addbyte(0x70); - addbyte(0xe0); - addbyte(0xff); - addbyte(0x66); /*PADDW XMM1, XMM4*/ - addbyte(0x0f); - addbyte(0xfd); - addbyte(0xcc); - } - + addbyte(0xc0); addbyte(0x66); /*PACKUSWB XMM0, XMM0*/ addbyte(0x0f); addbyte(0x67); addbyte(0xc0); - addbyte(0x66); /*PACKUSWB XMM3, XMM3*/ + addbyte(0x66); /*MOVD EAX, XMM0*/ addbyte(0x0f); - addbyte(0x67); + addbyte(0x7e); + addbyte(0xc0); + break; + case CC_LOCALSELECT_COLOR1: + addbyte(0x8b); /*MOV EAX, params->color1[ESI]*/ + addbyte(0x86); + addlong(offsetof(voodoo_params_t, color1)); + break; + case CC_LOCALSELECT_TEX: + addbyte(0x66); /*MOVD EAX, XMM0*/ + addbyte(0x0f); + addbyte(0x7e); + addbyte(0xc0); + break; + } + addbyte(0x8b); /*MOV EBX, params->chromaKey[ESI]*/ + addbyte(0x9e); + addlong(offsetof(voodoo_params_t, chromaKey)); + addbyte(0x31); /*XOR EBX, EAX*/ + addbyte(0xc3); + addbyte(0x81); /*AND EBX, 0xffffff*/ + addbyte(0xe3); + addlong(0xffffff); + addbyte(0x0f); /*JE skip*/ + addbyte(0x84); + chroma_skip_pos = block_pos; + addlong(0); + } + + if (voodoo->trexInit1[0] & (1 << 18)) { + addbyte(0xb8); /*MOV EAX, tmuConfig*/ + addlong(voodoo->tmuConfig); + addbyte(0x66); /*MOVD XMM0, EAX*/ + addbyte(0x0f); + addbyte(0x6e); + addbyte(0xc0); + } + + if ((params->alphaMode & ((1 << 0) | (1 << 4))) || (!(cc_mselect == 0 && cc_reverse_blend == 0) && (cc_mselect == CC_MSELECT_AOTHER || cc_mselect == CC_MSELECT_ALOCAL))) { + /*EBX = a_other*/ + switch (a_sel) { + case A_SEL_ITER_A: + addbyte(0x8b); /*MOV EBX, state->ia*/ + addbyte(0x9f); + addlong(offsetof(voodoo_state_t, ia)); + addbyte(0x31); /*XOR EAX, EAX*/ + addbyte(0xc0); + addbyte(0xba); /*MOV EDX, 0xff*/ + addlong(0xff); + addbyte(0xc1); /*SAR EBX, 12*/ + addbyte(0xfb); + addbyte(12); + addbyte(0x0f); /*CMOVS EBX, EAX*/ + addbyte(0x48); + addbyte(0xd8); + addbyte(0x39); /*CMP EBX, EDX*/ + addbyte(0xd3); + addbyte(0x0f); /*CMOVA EBX, EDX*/ + addbyte(0x47); + addbyte(0xda); + break; + case A_SEL_TEX: + addbyte(0x8b); /*MOV EBX, state->tex_a*/ + addbyte(0x9f); + addlong(offsetof(voodoo_state_t, tex_a)); + break; + case A_SEL_COLOR1: + addbyte(0x0f); /*MOVZX EBX, params->color1+3*/ + addbyte(0xb6); + addbyte(0x9e); + addlong(offsetof(voodoo_params_t, color1) + 3); + break; + default: + addbyte(0x31); /*XOR EBX, EBX*/ addbyte(0xdb); + break; + } + /*ECX = a_local*/ + switch (cca_localselect) { + case CCA_LOCALSELECT_ITER_A: + if (a_sel == A_SEL_ITER_A) { + addbyte(0x89); /*MOV ECX, EBX*/ + addbyte(0xd9); + } else { + addbyte(0x8b); /*MOV ECX, state->ia*/ + addbyte(0x8f); + addlong(offsetof(voodoo_state_t, ia)); + addbyte(0x31); /*XOR EAX, EAX*/ + addbyte(0xc0); + addbyte(0xba); /*MOV EDX, 0xff*/ + addlong(0xff); + addbyte(0xc1); /*SAR ECX, 12*/ + addbyte(0xf9); + addbyte(12); + addbyte(0x0f); /*CMOVS ECX, EAX*/ + addbyte(0x48); + addbyte(0xc8); + addbyte(0x39); /*CMP ECX, EDX*/ + addbyte(0xd1); + addbyte(0x0f); /*CMOVA ECX, EDX*/ + addbyte(0x47); + addbyte(0xca); + } + break; + case CCA_LOCALSELECT_COLOR0: + addbyte(0x0f); /*MOVZX ECX, params->color0+3*/ + addbyte(0xb6); + addbyte(0x8e); + addlong(offsetof(voodoo_params_t, color0) + 3); + break; + case CCA_LOCALSELECT_ITER_Z: + addbyte(0x8b); /*MOV ECX, state->z*/ + addbyte(0x8f); + addlong(offsetof(voodoo_state_t, z)); + if (a_sel != A_SEL_ITER_A) { + addbyte(0x31); /*XOR EAX, EAX*/ + addbyte(0xc0); + addbyte(0xba); /*MOV EDX, 0xff*/ + addlong(0xff); + } + addbyte(0xc1); /*SAR ECX, 20*/ + addbyte(0xf9); + addbyte(20); + addbyte(0x0f); /*CMOVS ECX, EAX*/ + addbyte(0x48); + addbyte(0xc8); + addbyte(0x39); /*CMP ECX, EDX*/ + addbyte(0xd1); + addbyte(0x0f); /*CMOVA ECX, EDX*/ + addbyte(0x47); + addbyte(0xca); + break; + + default: + addbyte(0xb9); /*MOV ECX, 0xff*/ + addlong(0xff); + break; + } + + if (cca_zero_other) { + addbyte(0x31); /*XOR EDX, EDX*/ + addbyte(0xd2); + } else { + addbyte(0x89); /*MOV EDX, EBX*/ + addbyte(0xda); + } + + if (cca_sub_clocal) { + addbyte(0x29); /*SUB EDX, ECX*/ + addbyte(0xca); + } + } + + if (cc_sub_clocal || cc_mselect == 1 || cc_add == 1) { + /*XMM1 = local*/ + if (!cc_localselect_override) { + if (cc_localselect) { + addbyte(0x66); /*MOVD XMM1, params->color0*/ + addbyte(0x0f); + addbyte(0x6e); + addbyte(0x8e); + addlong(offsetof(voodoo_params_t, color0)); + } else { + addbyte(0xf3); /*MOVDQU XMM1, ib*/ /* ir, ig and ib must be in same dqword!*/ + addbyte(0x0f); + addbyte(0x6f); + addbyte(0x8f); + addlong(offsetof(voodoo_state_t, ib)); + addbyte(0x66); /*PSRAD XMM1, 12*/ + addbyte(0x0f); + addbyte(0x72); + addbyte(0xe1); + addbyte(12); + addbyte(0x66); /*PACKSSDW XMM1, XMM1*/ + addbyte(0x0f); + addbyte(0x6b); + addbyte(0xc9); addbyte(0x66); /*PACKUSWB XMM1, XMM1*/ addbyte(0x0f); addbyte(0x67); addbyte(0xc9); - if (tc_invert_output) - { - addbyte(0x66); /*PXOR XMM1, FF*/ - addbyte(0x0f); - addbyte(0xef); - addbyte(0x0d); - addlong((uint32_t)&xmm_ff_b); - } - - if (tca_zero_other) - { - addbyte(0x31); /*XOR EAX, EAX*/ - addbyte(0xc0); - } - else - { - addbyte(0x66); /*MOV EAX, XMM3*/ - addbyte(0x0f); - addbyte(0x7e); - addbyte(0xd8); - addbyte(0xc1); /*SHR EAX, 24*/ - addbyte(0xe8); - addbyte(24); - } - if (tca_sub_clocal) - { - addbyte(0x29); /*SUB EAX, EBX*/ - addbyte(0xd8); - } - switch (tca_mselect) - { - case TCA_MSELECT_ZERO: - addbyte(0x31); /*XOR EBX, EBX*/ - addbyte(0xdb); - break; - case TCA_MSELECT_CLOCAL: - addbyte(0x66); /*MOV EBX, XMM7*/ - addbyte(0x0f); - addbyte(0x7e); - addbyte(0xfb); - addbyte(0xc1); /*SHR EBX, 24*/ - addbyte(0xeb); - addbyte(24); - break; - case TCA_MSELECT_AOTHER: - addbyte(0x66); /*MOV EBX, XMM3*/ - addbyte(0x0f); - addbyte(0x7e); - addbyte(0xdb); - addbyte(0xc1); /*SHR EBX, 24*/ - addbyte(0xeb); - addbyte(24); - break; - case TCA_MSELECT_ALOCAL: - addbyte(0x66); /*MOV EBX, XMM7*/ - addbyte(0x0f); - addbyte(0x7e); - addbyte(0xfb); - addbyte(0xc1); /*SHR EBX, 24*/ - addbyte(0xeb); - addbyte(24); - break; - case TCA_MSELECT_DETAIL: - addbyte(0xbb); /*MOV EBX, params->detail_bias[1]*/ - addlong(params->detail_bias[1]); - addbyte(0x2b); /*SUB EBX, state->lod*/ - addbyte(0x9f); - addlong(offsetof(voodoo_state_t, lod)); - addbyte(0xba); /*MOV EDX, params->detail_max[1]*/ - addlong(params->detail_max[1]); - addbyte(0xc1); /*SHL EBX, params->detail_scale[1]*/ - addbyte(0xe3); - addbyte(params->detail_scale[1]); - addbyte(0x39); /*CMP EBX, EDX*/ - addbyte(0xd3); - addbyte(0x0f); /*CMOVNL EBX, EDX*/ - addbyte(0x4d); - addbyte(0xda); - break; - case TCA_MSELECT_LOD_FRAC: - addbyte(0x8b); /*MOV EBX, state->lod_frac[0]*/ - addbyte(0x9f); - addlong(offsetof(voodoo_state_t, lod_frac[0])); - break; - } - if (params->textureMode[0] & TEXTUREMODE_TRILINEAR) - { - addbyte(0x33); /*XOR EBX, i_00_ff_w[ECX*4]*/ - addbyte(0x1c); - addbyte(0x8d); - addlong((uint32_t)i_00_ff_w); - } - else if (!tca_reverse_blend) - { - addbyte(0x81); /*XOR EBX, 0xFF*/ - addbyte(0xf3); - addlong(0xff); - } - - addbyte(0x83); /*ADD EBX, 1*/ - addbyte(0xc3); - addbyte(1); - addbyte(0x0f); /*IMUL EAX, EBX*/ - addbyte(0xaf); - addbyte(0xc3); - addbyte(0x31); /*XOR EDX, EDX*/ - addbyte(0xd2); - addbyte(0xc1); /*SAR EAX, 8*/ - addbyte(0xf8); - addbyte(8); - if (tca_add_clocal || tca_add_alocal) - { - addbyte(0x66); /*MOV EBX, XMM7*/ - addbyte(0x0f); - addbyte(0x7e); - addbyte(0xfb); - addbyte(0xc1); /*SHR EBX, 24*/ - addbyte(0xeb); - addbyte(24); - addbyte(0x01); /*ADD EAX, EBX*/ - addbyte(0xd8); - } - addbyte(0x0f); /*CMOVS EAX, EDX*/ - addbyte(0x48); - addbyte(0xc2); - addbyte(0xba); /*MOV EDX, 0xff*/ - addlong(0xff); - addbyte(0x3d); /*CMP EAX, 0xff*/ - addlong(0xff); - addbyte(0x0f); /*CMOVA EAX, EDX*/ - addbyte(0x47); - addbyte(0xc2); - if (tca_invert_output) - { - addbyte(0x35); /*XOR EAX, 0xff*/ - addlong(0xff); - } - - addbyte(0x89); /*MOV state->tex_a[EDI], EAX*/ - addbyte(0x87); - addlong(offsetof(voodoo_state_t, tex_a)); - - addbyte(0xf3); /*MOVQ XMM0, XMM1*/ - addbyte(0x0f); - addbyte(0x7e); - addbyte(0xc1); + } + } else { + addbyte(0xf6); /*TEST state->tex_a, 0x80*/ + addbyte(0x87); + addlong(offsetof(voodoo_state_t, tex_a)); + addbyte(0x80); + addbyte(0x74); /*JZ !cc_localselect*/ + addbyte(8 + 2); + addbyte(0x66); /*MOVD XMM1, params->color0*/ + addbyte(0x0f); + addbyte(0x6e); + addbyte(0x8e); + addlong(offsetof(voodoo_params_t, color0)); + addbyte(0xeb); /*JMP +*/ + addbyte(8 + 5 + 4 + 4); + /*!cc_localselect:*/ + addbyte(0xf3); /*MOVDQU XMM1, ib*/ /* ir, ig and ib must be in same dqword!*/ + addbyte(0x0f); + addbyte(0x6f); + addbyte(0x8f); + addlong(offsetof(voodoo_state_t, ib)); + addbyte(0x66); /*PSRAD XMM1, 12*/ + addbyte(0x0f); + addbyte(0x72); + addbyte(0xe1); + addbyte(12); + addbyte(0x66); /*PACKSSDW XMM1, XMM1*/ + addbyte(0x0f); + addbyte(0x6b); + addbyte(0xc9); + addbyte(0x66); /*PACKUSWB XMM1, XMM1*/ + addbyte(0x0f); + addbyte(0x67); + addbyte(0xc9); } - if (cc_mselect == CC_MSELECT_TEXRGB) - { - addbyte(0xf3); /*MOVD XMM4, XMM0*/ - addbyte(0x0f); - addbyte(0x7e); - addbyte(0xe0); - } - - if ((params->fbzMode & FBZ_CHROMAKEY)) - { - switch (_rgb_sel) - { - case CC_LOCALSELECT_ITER_RGB: - addbyte(0xf3); /*MOVDQU XMM0, ib*/ /* ir, ig and ib must be in same dqword!*/ - addbyte(0x0f); - addbyte(0x6f); - addbyte(0x87); - addlong(offsetof(voodoo_state_t, ib)); - addbyte(0x66); /*PSRAD XMM0, 12*/ - addbyte(0x0f); - addbyte(0x72); - addbyte(0xe0); - addbyte(12); - addbyte(0x66); /*PACKSSDW XMM0, XMM0*/ - addbyte(0x0f); - addbyte(0x6b); - addbyte(0xc0); - addbyte(0x66); /*PACKUSWB XMM0, XMM0*/ - addbyte(0x0f); - addbyte(0x67); - addbyte(0xc0); - addbyte(0x66); /*MOVD EAX, XMM0*/ - addbyte(0x0f); - addbyte(0x7e); - addbyte(0xc0); - break; - case CC_LOCALSELECT_COLOR1: - addbyte(0x8b); /*MOV EAX, params->color1[ESI]*/ - addbyte(0x86); - addlong(offsetof(voodoo_params_t, color1)); - break; - case CC_LOCALSELECT_TEX: - addbyte(0x66); /*MOVD EAX, XMM0*/ - addbyte(0x0f); - addbyte(0x7e); - addbyte(0xc0); - break; - } - addbyte(0x8b); /*MOV EBX, params->chromaKey[ESI]*/ - addbyte(0x9e); - addlong(offsetof(voodoo_params_t, chromaKey)); - addbyte(0x31); /*XOR EBX, EAX*/ - addbyte(0xc3); - addbyte(0x81); /*AND EBX, 0xffffff*/ - addbyte(0xe3); - addlong(0xffffff); - addbyte(0x0f); /*JE skip*/ - addbyte(0x84); - chroma_skip_pos = block_pos; - addlong(0); - } - - if (voodoo->trexInit1[0] & (1 << 18)) - { - addbyte(0xb8); /*MOV EAX, tmuConfig*/ - addlong(voodoo->tmuConfig); - addbyte(0x66); /*MOVD XMM0, EAX*/ - addbyte(0x0f); - addbyte(0x6e); - addbyte(0xc0); - } - - if ((params->alphaMode & ((1 << 0) | (1 << 4))) || (!(cc_mselect == 0 && cc_reverse_blend == 0) && (cc_mselect == CC_MSELECT_AOTHER || cc_mselect == CC_MSELECT_ALOCAL))) - { - /*EBX = a_other*/ - switch (a_sel) - { - case A_SEL_ITER_A: - addbyte(0x8b); /*MOV EBX, state->ia*/ - addbyte(0x9f); - addlong(offsetof(voodoo_state_t, ia)); - addbyte(0x31); /*XOR EAX, EAX*/ - addbyte(0xc0); - addbyte(0xba); /*MOV EDX, 0xff*/ - addlong(0xff); - addbyte(0xc1); /*SAR EBX, 12*/ - addbyte(0xfb); - addbyte(12); - addbyte(0x0f); /*CMOVS EBX, EAX*/ - addbyte(0x48); - addbyte(0xd8); - addbyte(0x39); /*CMP EBX, EDX*/ - addbyte(0xd3); - addbyte(0x0f); /*CMOVA EBX, EDX*/ - addbyte(0x47); - addbyte(0xda); - break; - case A_SEL_TEX: - addbyte(0x8b); /*MOV EBX, state->tex_a*/ - addbyte(0x9f); - addlong(offsetof(voodoo_state_t, tex_a)); - break; - case A_SEL_COLOR1: - addbyte(0x0f); /*MOVZX EBX, params->color1+3*/ - addbyte(0xb6); - addbyte(0x9e); - addlong(offsetof(voodoo_params_t, color1)+3); - break; - default: - addbyte(0x31); /*XOR EBX, EBX*/ - addbyte(0xdb); - break; - } - /*ECX = a_local*/ - switch (cca_localselect) - { - case CCA_LOCALSELECT_ITER_A: - if (a_sel == A_SEL_ITER_A) - { - addbyte(0x89); /*MOV ECX, EBX*/ - addbyte(0xd9); - } - else - { - addbyte(0x8b); /*MOV ECX, state->ia*/ - addbyte(0x8f); - addlong(offsetof(voodoo_state_t, ia)); - addbyte(0x31); /*XOR EAX, EAX*/ - addbyte(0xc0); - addbyte(0xba); /*MOV EDX, 0xff*/ - addlong(0xff); - addbyte(0xc1);/*SAR ECX, 12*/ - addbyte(0xf9); - addbyte(12); - addbyte(0x0f); /*CMOVS ECX, EAX*/ - addbyte(0x48); - addbyte(0xc8); - addbyte(0x39); /*CMP ECX, EDX*/ - addbyte(0xd1); - addbyte(0x0f); /*CMOVA ECX, EDX*/ - addbyte(0x47); - addbyte(0xca); - } - break; - case CCA_LOCALSELECT_COLOR0: - addbyte(0x0f); /*MOVZX ECX, params->color0+3*/ - addbyte(0xb6); - addbyte(0x8e); - addlong(offsetof(voodoo_params_t, color0)+3); - break; - case CCA_LOCALSELECT_ITER_Z: - addbyte(0x8b); /*MOV ECX, state->z*/ - addbyte(0x8f); - addlong(offsetof(voodoo_state_t, z)); - if (a_sel != A_SEL_ITER_A) - { - addbyte(0x31); /*XOR EAX, EAX*/ - addbyte(0xc0); - addbyte(0xba); /*MOV EDX, 0xff*/ - addlong(0xff); - } - addbyte(0xc1);/*SAR ECX, 20*/ - addbyte(0xf9); - addbyte(20); - addbyte(0x0f); /*CMOVS ECX, EAX*/ - addbyte(0x48); - addbyte(0xc8); - addbyte(0x39); /*CMP ECX, EDX*/ - addbyte(0xd1); - addbyte(0x0f); /*CMOVA ECX, EDX*/ - addbyte(0x47); - addbyte(0xca); - break; - - default: - addbyte(0xb9); /*MOV ECX, 0xff*/ - addlong(0xff); - break; - } - - if (cca_zero_other) - { - addbyte(0x31); /*XOR EDX, EDX*/ - addbyte(0xd2); - } - else - { - addbyte(0x89); /*MOV EDX, EBX*/ - addbyte(0xda); - } - - if (cca_sub_clocal) - { - addbyte(0x29); /*SUB EDX, ECX*/ - addbyte(0xca); - } - } - - if (cc_sub_clocal || cc_mselect == 1 || cc_add == 1) - { - /*XMM1 = local*/ - if (!cc_localselect_override) - { - if (cc_localselect) - { - addbyte(0x66); /*MOVD XMM1, params->color0*/ - addbyte(0x0f); - addbyte(0x6e); - addbyte(0x8e); - addlong(offsetof(voodoo_params_t, color0)); - } - else - { - addbyte(0xf3); /*MOVDQU XMM1, ib*/ /* ir, ig and ib must be in same dqword!*/ - addbyte(0x0f); - addbyte(0x6f); - addbyte(0x8f); - addlong(offsetof(voodoo_state_t, ib)); - addbyte(0x66); /*PSRAD XMM1, 12*/ - addbyte(0x0f); - addbyte(0x72); - addbyte(0xe1); - addbyte(12); - addbyte(0x66); /*PACKSSDW XMM1, XMM1*/ - addbyte(0x0f); - addbyte(0x6b); - addbyte(0xc9); - addbyte(0x66); /*PACKUSWB XMM1, XMM1*/ - addbyte(0x0f); - addbyte(0x67); - addbyte(0xc9); - } - } - else - { - addbyte(0xf6); /*TEST state->tex_a, 0x80*/ - addbyte(0x87); - addlong(offsetof(voodoo_state_t, tex_a)); - addbyte(0x80); - addbyte(0x74);/*JZ !cc_localselect*/ - addbyte(8+2); - addbyte(0x66); /*MOVD XMM1, params->color0*/ - addbyte(0x0f); - addbyte(0x6e); - addbyte(0x8e); - addlong(offsetof(voodoo_params_t, color0)); - addbyte(0xeb); /*JMP +*/ - addbyte(8+5+4+4); - /*!cc_localselect:*/ - addbyte(0xf3); /*MOVDQU XMM1, ib*/ /* ir, ig and ib must be in same dqword!*/ - addbyte(0x0f); - addbyte(0x6f); - addbyte(0x8f); - addlong(offsetof(voodoo_state_t, ib)); - addbyte(0x66); /*PSRAD XMM1, 12*/ - addbyte(0x0f); - addbyte(0x72); - addbyte(0xe1); - addbyte(12); - addbyte(0x66); /*PACKSSDW XMM1, XMM1*/ - addbyte(0x0f); - addbyte(0x6b); - addbyte(0xc9); - addbyte(0x66); /*PACKUSWB XMM1, XMM1*/ - addbyte(0x0f); - addbyte(0x67); - addbyte(0xc9); - } - addbyte(0x66); /*PUNPCKLBW XMM1, XMM2*/ - addbyte(0x0f); - addbyte(0x60); - addbyte(0xca); - } - if (!cc_zero_other) - { - if (_rgb_sel == CC_LOCALSELECT_ITER_RGB) - { - addbyte(0xf3); /*MOVDQU XMM0, ib*/ /* ir, ig and ib must be in same dqword!*/ - addbyte(0x0f); - addbyte(0x6f); - addbyte(0x87); - addlong(offsetof(voodoo_state_t, ib)); - addbyte(0x66); /*PSRAD XMM0, 12*/ - addbyte(0x0f); - addbyte(0x72); - addbyte(0xe0); - addbyte(12); - addbyte(0x66); /*PACKSSDW XMM0, XMM0*/ - addbyte(0x0f); - addbyte(0x6b); - addbyte(0xc0); - addbyte(0x66); /*PACKUSWB XMM0, XMM0*/ - addbyte(0x0f); - addbyte(0x67); - addbyte(0xc0); - } - else if (_rgb_sel == CC_LOCALSELECT_TEX) - { + addbyte(0x66); /*PUNPCKLBW XMM1, XMM2*/ + addbyte(0x0f); + addbyte(0x60); + addbyte(0xca); + } + if (!cc_zero_other) { + if (_rgb_sel == CC_LOCALSELECT_ITER_RGB) { + addbyte(0xf3); /*MOVDQU XMM0, ib*/ /* ir, ig and ib must be in same dqword!*/ + addbyte(0x0f); + addbyte(0x6f); + addbyte(0x87); + addlong(offsetof(voodoo_state_t, ib)); + addbyte(0x66); /*PSRAD XMM0, 12*/ + addbyte(0x0f); + addbyte(0x72); + addbyte(0xe0); + addbyte(12); + addbyte(0x66); /*PACKSSDW XMM0, XMM0*/ + addbyte(0x0f); + addbyte(0x6b); + addbyte(0xc0); + addbyte(0x66); /*PACKUSWB XMM0, XMM0*/ + addbyte(0x0f); + addbyte(0x67); + addbyte(0xc0); + } else if (_rgb_sel == CC_LOCALSELECT_TEX) { #if 0 addbyte(0xf3); /*MOVDQU XMM0, state->tex_b*/ addbyte(0x0f); @@ -1965,1428 +1840,1371 @@ static inline void voodoo_generate(uint8_t *code_block, voodoo_t *voodoo, voodoo addbyte(0x67); addbyte(0xc0); #endif - } - else if (_rgb_sel == CC_LOCALSELECT_COLOR1) - { - addbyte(0x66); /*MOVD XMM0, params->color1*/ - addbyte(0x0f); - addbyte(0x6e); - addbyte(0x86); - addlong(offsetof(voodoo_params_t, color1)); - } - else - { - /*MOVD XMM0, src_r*/ - } - addbyte(0x66); /*PUNPCKLBW XMM0, XMM2*/ - addbyte(0x0f); - addbyte(0x60); - addbyte(0xc2); - if (cc_sub_clocal) - { - addbyte(0x66); /*PSUBW XMM0, XMM1*/ - addbyte(0x0f); - addbyte(0xf9); - addbyte(0xc1); - } + } else if (_rgb_sel == CC_LOCALSELECT_COLOR1) { + addbyte(0x66); /*MOVD XMM0, params->color1*/ + addbyte(0x0f); + addbyte(0x6e); + addbyte(0x86); + addlong(offsetof(voodoo_params_t, color1)); + } else { + /*MOVD XMM0, src_r*/ } - else - { - addbyte(0x66); /*PXOR XMM0, XMM0*/ + addbyte(0x66); /*PUNPCKLBW XMM0, XMM2*/ + addbyte(0x0f); + addbyte(0x60); + addbyte(0xc2); + if (cc_sub_clocal) { + addbyte(0x66); /*PSUBW XMM0, XMM1*/ + addbyte(0x0f); + addbyte(0xf9); + addbyte(0xc1); + } + } else { + addbyte(0x66); /*PXOR XMM0, XMM0*/ + addbyte(0x0f); + addbyte(0xef); + addbyte(0xc0); + if (cc_sub_clocal) { + addbyte(0x66); /*PSUBW XMM0, XMM1*/ + addbyte(0x0f); + addbyte(0xf9); + addbyte(0xc1); + } + } + + if (params->alphaMode & ((1 << 0) | (1 << 4))) { + if (!(cca_mselect == 0 && cca_reverse_blend == 0)) { + switch (cca_mselect) { + case CCA_MSELECT_ALOCAL: + addbyte(0x89); /*MOV EAX, ECX*/ + addbyte(0xc8); + break; + case CCA_MSELECT_AOTHER: + addbyte(0x89); /*MOV EAX, EBX*/ + addbyte(0xd8); + break; + case CCA_MSELECT_ALOCAL2: + addbyte(0x89); /*MOV EAX, ECX*/ + addbyte(0xc8); + break; + case CCA_MSELECT_TEX: + addbyte(0x0f); /*MOVZX EAX, state->tex_a*/ + addbyte(0xb6); + addbyte(0x87); + addlong(offsetof(voodoo_state_t, tex_a)); + break; + + case CCA_MSELECT_ZERO: + default: + addbyte(0x31); /*XOR EAX, EAX*/ + addbyte(0xc0); + break; + } + if (!cca_reverse_blend) { + addbyte(0x35); /*XOR EAX, 0xff*/ + addlong(0xff); + } + addbyte(0x83); /*ADD EAX, 1*/ + addbyte(0xc0); + addbyte(1); + addbyte(0x0f); /*IMUL EDX, EAX*/ + addbyte(0xaf); + addbyte(0xd0); + addbyte(0xc1); /*SHR EDX, 8*/ + addbyte(0xea); + addbyte(8); + } + } + + if ((params->alphaMode & ((1 << 0) | (1 << 4)))) { + addbyte(0x31); /*XOR EAX, EAX*/ + addbyte(0xc0); + } + + if (!(cc_mselect == 0 && cc_reverse_blend == 0) && cc_mselect == CC_MSELECT_AOTHER) { + /*Copy a_other to XMM3 before it gets modified*/ + addbyte(0x66); /*MOVD XMM3, EDX*/ + addbyte(0x0f); + addbyte(0x6e); + addbyte(0xda); + addbyte(0xf2); /*PSHUFLW XMM3, XMM3, 0*/ + addbyte(0x0f); + addbyte(0x70); + addbyte(0xdb); + addbyte(0x00); + } + + if (cca_add && (params->alphaMode & ((1 << 0) | (1 << 4)))) { + addbyte(0x01); /*ADD EDX, ECX*/ + addbyte(0xca); + } + + if ((params->alphaMode & ((1 << 0) | (1 << 4)))) { + addbyte(0x85); /*TEST EDX, EDX*/ + addbyte(0xd2); + addbyte(0x0f); /*CMOVS EDX, EAX*/ + addbyte(0x48); + addbyte(0xd0); + addbyte(0xb8); /*MOV EAX, 0xff*/ + addlong(0xff); + addbyte(0x81); /*CMP EDX, 0xff*/ + addbyte(0xfa); + addlong(0xff); + addbyte(0x0f); /*CMOVA EDX, EAX*/ + addbyte(0x47); + addbyte(0xd0); + + if (cca_invert_output) { + addbyte(0x81); /*XOR EDX, 0xff*/ + addbyte(0xf2); + addlong(0xff); + } + } + + if (!(cc_mselect == 0 && cc_reverse_blend == 0)) { + switch (cc_mselect) { + case CC_MSELECT_ZERO: + addbyte(0x66); /*PXOR XMM3, XMM3*/ addbyte(0x0f); addbyte(0xef); - addbyte(0xc0); - if (cc_sub_clocal) - { - addbyte(0x66); /*PSUBW XMM0, XMM1*/ - addbyte(0x0f); - addbyte(0xf9); - addbyte(0xc1); - } - } - - if (params->alphaMode & ((1 << 0) | (1 << 4))) - { - if (!(cca_mselect == 0 && cca_reverse_blend == 0)) - { - switch (cca_mselect) - { - case CCA_MSELECT_ALOCAL: - addbyte(0x89); /*MOV EAX, ECX*/ - addbyte(0xc8); - break; - case CCA_MSELECT_AOTHER: - addbyte(0x89); /*MOV EAX, EBX*/ - addbyte(0xd8); - break; - case CCA_MSELECT_ALOCAL2: - addbyte(0x89); /*MOV EAX, ECX*/ - addbyte(0xc8); - break; - case CCA_MSELECT_TEX: - addbyte(0x0f); /*MOVZX EAX, state->tex_a*/ - addbyte(0xb6); - addbyte(0x87); - addlong(offsetof(voodoo_state_t, tex_a)); - break; - - case CCA_MSELECT_ZERO: - default: - addbyte(0x31); /*XOR EAX, EAX*/ - addbyte(0xc0); - break; - } - if (!cca_reverse_blend) - { - addbyte(0x35); /*XOR EAX, 0xff*/ - addlong(0xff); - } - addbyte(0x83); /*ADD EAX, 1*/ - addbyte(0xc0); - addbyte(1); - addbyte(0x0f); /*IMUL EDX, EAX*/ - addbyte(0xaf); - addbyte(0xd0); - addbyte(0xc1); /*SHR EDX, 8*/ - addbyte(0xea); - addbyte(8); - } - } - - if ((params->alphaMode & ((1 << 0) | (1 << 4)))) - { - addbyte(0x31); /*XOR EAX, EAX*/ - addbyte(0xc0); - } - - if (!(cc_mselect == 0 && cc_reverse_blend == 0) && cc_mselect == CC_MSELECT_AOTHER) - { - /*Copy a_other to XMM3 before it gets modified*/ - addbyte(0x66); /*MOVD XMM3, EDX*/ + addbyte(0xdb); + break; + case CC_MSELECT_CLOCAL: + addbyte(0xf3); /*MOV XMM3, XMM1*/ + addbyte(0x0f); + addbyte(0x7e); + addbyte(0xd9); + break; + case CC_MSELECT_ALOCAL: + addbyte(0x66); /*MOVD XMM3, ECX*/ addbyte(0x0f); addbyte(0x6e); - addbyte(0xda); + addbyte(0xd9); addbyte(0xf2); /*PSHUFLW XMM3, XMM3, 0*/ addbyte(0x0f); addbyte(0x70); addbyte(0xdb); addbyte(0x00); - } - - if (cca_add && (params->alphaMode & ((1 << 0) | (1 << 4)))) - { - addbyte(0x01); /*ADD EDX, ECX*/ - addbyte(0xca); - } - - if ((params->alphaMode & ((1 << 0) | (1 << 4)))) - { - addbyte(0x85); /*TEST EDX, EDX*/ - addbyte(0xd2); - addbyte(0x0f); /*CMOVS EDX, EAX*/ - addbyte(0x48); - addbyte(0xd0); - addbyte(0xb8); /*MOV EAX, 0xff*/ - addlong(0xff); - addbyte(0x81); /*CMP EDX, 0xff*/ - addbyte(0xfa); - addlong(0xff); - addbyte(0x0f); /*CMOVA EDX, EAX*/ - addbyte(0x47); - addbyte(0xd0); - - if (cca_invert_output) - { - addbyte(0x81); /*XOR EDX, 0xff*/ - addbyte(0xf2); - addlong(0xff); - } - } - - if (!(cc_mselect == 0 && cc_reverse_blend == 0)) - { - switch (cc_mselect) - { - case CC_MSELECT_ZERO: - addbyte(0x66); /*PXOR XMM3, XMM3*/ - addbyte(0x0f); - addbyte(0xef); - addbyte(0xdb); - break; - case CC_MSELECT_CLOCAL: - addbyte(0xf3); /*MOV XMM3, XMM1*/ - addbyte(0x0f); - addbyte(0x7e); - addbyte(0xd9); - break; - case CC_MSELECT_ALOCAL: - addbyte(0x66); /*MOVD XMM3, ECX*/ - addbyte(0x0f); - addbyte(0x6e); - addbyte(0xd9); - addbyte(0xf2); /*PSHUFLW XMM3, XMM3, 0*/ - addbyte(0x0f); - addbyte(0x70); - addbyte(0xdb); - addbyte(0x00); - break; - case CC_MSELECT_AOTHER: - /*Handled above*/ - break; - case CC_MSELECT_TEX: - addbyte(0x66); /*PINSRW XMM3, state->tex_a, 0*/ - addbyte(0x0f); - addbyte(0xc4); - addbyte(0x9f); - addlong(offsetof(voodoo_state_t, tex_a)); - addbyte(0); - addbyte(0x66); /*PINSRW XMM3, state->tex_a, 1*/ - addbyte(0x0f); - addbyte(0xc4); - addbyte(0x9f); - addlong(offsetof(voodoo_state_t, tex_a)); - addbyte(1); - addbyte(0x66); /*PINSRW XMM3, state->tex_a, 2*/ - addbyte(0x0f); - addbyte(0xc4); - addbyte(0x9f); - addlong(offsetof(voodoo_state_t, tex_a)); - addbyte(2); - break; - case CC_MSELECT_TEXRGB: - addbyte(0x66); /*PUNPCKLBW XMM4, XMM2*/ - addbyte(0x0f); - addbyte(0x60); - addbyte(0xe2); - addbyte(0xf3); /*MOVQ XMM3, XMM4*/ - addbyte(0x0f); - addbyte(0x7e); - addbyte(0xdc); - break; - default: - addbyte(0x66); /*PXOR XMM3, XMM3*/ - addbyte(0x0f); - addbyte(0xef); - addbyte(0xdb); - break; - } - addbyte(0xf3); /*MOV XMM4, XMM0*/ + break; + case CC_MSELECT_AOTHER: + /*Handled above*/ + break; + case CC_MSELECT_TEX: + addbyte(0x66); /*PINSRW XMM3, state->tex_a, 0*/ + addbyte(0x0f); + addbyte(0xc4); + addbyte(0x9f); + addlong(offsetof(voodoo_state_t, tex_a)); + addbyte(0); + addbyte(0x66); /*PINSRW XMM3, state->tex_a, 1*/ + addbyte(0x0f); + addbyte(0xc4); + addbyte(0x9f); + addlong(offsetof(voodoo_state_t, tex_a)); + addbyte(1); + addbyte(0x66); /*PINSRW XMM3, state->tex_a, 2*/ + addbyte(0x0f); + addbyte(0xc4); + addbyte(0x9f); + addlong(offsetof(voodoo_state_t, tex_a)); + addbyte(2); + break; + case CC_MSELECT_TEXRGB: + addbyte(0x66); /*PUNPCKLBW XMM4, XMM2*/ + addbyte(0x0f); + addbyte(0x60); + addbyte(0xe2); + addbyte(0xf3); /*MOVQ XMM3, XMM4*/ addbyte(0x0f); addbyte(0x7e); - addbyte(0xe0); - if (!cc_reverse_blend) - { - addbyte(0x66); /*PXOR XMM3, 0xff*/ - addbyte(0x0f); - addbyte(0xef); - addbyte(0x1d); - addlong((uint32_t)&xmm_ff_w); - } - addbyte(0x66); /*PADDW XMM3, 1*/ + addbyte(0xdc); + break; + default: + addbyte(0x66); /*PXOR XMM3, XMM3*/ + addbyte(0x0f); + addbyte(0xef); + addbyte(0xdb); + break; + } + addbyte(0xf3); /*MOV XMM4, XMM0*/ + addbyte(0x0f); + addbyte(0x7e); + addbyte(0xe0); + if (!cc_reverse_blend) { + addbyte(0x66); /*PXOR XMM3, 0xff*/ + addbyte(0x0f); + addbyte(0xef); + addbyte(0x1d); + addlong((uint32_t) &xmm_ff_w); + } + addbyte(0x66); /*PADDW XMM3, 1*/ + addbyte(0x0f); + addbyte(0xfd); + addbyte(0x1d); + addlong((uint32_t) &xmm_01_w); + addbyte(0x66); /*PMULLW XMM0, XMM3*/ + addbyte(0x0f); + addbyte(0xd5); + addbyte(0xc3); + addbyte(0x66); /*PMULHW XMM4, XMM3*/ + addbyte(0x0f); + addbyte(0xe5); + addbyte(0xe3); + addbyte(0x66); /*PUNPCKLWD XMM0, XMM4*/ + addbyte(0x0f); + addbyte(0x61); + addbyte(0xc4); + addbyte(0x66); /*PSRLD XMM0, 8*/ + addbyte(0x0f); + addbyte(0x72); + addbyte(0xe0); + addbyte(8); + addbyte(0x66); /*PACKSSDW XMM0, XMM0*/ + addbyte(0x0f); + addbyte(0x6b); + addbyte(0xc0); + } + + if (cc_add == 1) { + addbyte(0x66); /*PADDW XMM0, XMM1*/ + addbyte(0x0f); + addbyte(0xfd); + addbyte(0xc1); + } + + addbyte(0x66); /*PACKUSWB XMM0, XMM0*/ + addbyte(0x0f); + addbyte(0x67); + addbyte(0xc0); + + if (cc_invert_output) { + addbyte(0x66); /*PXOR XMM0, 0xff*/ + addbyte(0x0f); + addbyte(0xef); + addbyte(0x05); + addlong((uint32_t) &xmm_ff_b); + } +#if 0 + addbyte(0x66); /*MOVD state->out[EDI], XMM0*/ + addbyte(0x0f); + addbyte(0x7e); + addbyte(0x87); + addlong(offsetof(voodoo_state_t, out)); +#endif + if (params->fogMode & FOG_ENABLE) { + if (params->fogMode & FOG_CONSTANT) { + addbyte(0x66); /*MOVD XMM3, params->fogColor[ESI]*/ + addbyte(0x0f); + addbyte(0x6e); + addbyte(0x9e); + addlong(offsetof(voodoo_params_t, fogColor)); + addbyte(0x66); /*PADDUSB XMM0, XMM3*/ + addbyte(0x0f); + addbyte(0xdc); + addbyte(0xc3); +#if 0 + src_r += params->fogColor.r; + src_g += params->fogColor.g; + src_b += params->fogColor.b; */ +#endif + } else { +#if 0 + int fog_r; + int fog_g; + int fog_b; + int fog_a; +#endif + + addbyte(0x66); /*PUNPCKLBW XMM0, XMM2*/ + addbyte(0x0f); + addbyte(0x60); + addbyte(0xc2); + + if (!(params->fogMode & FOG_ADD)) { + addbyte(0x66); /*MOVD XMM3, params->fogColor[ESI]*/ + addbyte(0x0f); + addbyte(0x6e); + addbyte(0x9e); + addlong(offsetof(voodoo_params_t, fogColor)); + addbyte(0x66); /*PUNPCKLBW XMM3, XMM2*/ + addbyte(0x0f); + addbyte(0x60); + addbyte(0xda); + } else { + addbyte(0x66); /*PXOR XMM3, XMM3*/ + addbyte(0x0f); + addbyte(0xef); + addbyte(0xdb); + } + + if (!(params->fogMode & FOG_MULT)) { + addbyte(0x66); /*PSUBW XMM3, XMM0*/ + addbyte(0x0f); + addbyte(0xf9); + addbyte(0xd8); + } + + /*Divide by 2 to prevent overflow on multiply*/ + addbyte(0x66); /*PSRAW XMM3, 1*/ + addbyte(0x0f); + addbyte(0x71); + addbyte(0xe3); + addbyte(1); + + switch (params->fogMode & (FOG_Z | FOG_ALPHA)) { + case 0: + addbyte(0x8b); /*MOV EBX, state->w_depth[EDI]*/ + addbyte(0x9f); + addlong(offsetof(voodoo_state_t, w_depth)); + addbyte(0x89); /*MOV EAX, EBX*/ + addbyte(0xd8); + addbyte(0xc1); /*SHR EBX, 10*/ + addbyte(0xeb); + addbyte(10); + addbyte(0xc1); /*SHR EAX, 2*/ + addbyte(0xe8); + addbyte(2); + addbyte(0x83); /*AND EBX, 0x3f*/ + addbyte(0xe3); + addbyte(0x3f); + addbyte(0x25); /*AND EAX, 0xff*/ + addlong(0xff); + addbyte(0xf6); /*MUL params->fogTable+1[ESI+EBX*2]*/ + addbyte(0xa4); + addbyte(0x5e); + addlong(offsetof(voodoo_params_t, fogTable) + 1); + addbyte(0x0f); /*MOVZX EBX, params->fogTable[ESI+EBX*2]*/ + addbyte(0xb6); + addbyte(0x9c); + addbyte(0x5e); + addlong(offsetof(voodoo_params_t, fogTable)); + addbyte(0xc1); /*SHR EAX, 10*/ + addbyte(0xe8); + addbyte(10); + addbyte(0x01); /*ADD EAX, EBX*/ + addbyte(0xd8); + +#if 0 + int fog_idx = (w_depth >> 10) & 0x3f; + + fog_a = params->fogTable[fog_idx].fog; + fog_a += (params->fogTable[fog_idx].dfog * ((w_depth >> 2) & 0xff)) >> 10; +#endif + break; + + case FOG_Z: + addbyte(0x8b); /*MOV EAX, state->z[EDI]*/ + addbyte(0x87); + addlong(offsetof(voodoo_state_t, z)); + addbyte(0xc1); /*SHR EAX, 12*/ + addbyte(0xe8); + addbyte(12); + addbyte(0x25); /*AND EAX, 0xff*/ + addlong(0xff); +#if 0 + fog_a = (z >> 20) & 0xff; +#endif + break; + + case FOG_ALPHA: + addbyte(0x8b); /*MOV EAX, state->ia[EDI]*/ + addbyte(0x87); + addlong(offsetof(voodoo_state_t, ia)); + addbyte(0x31); /*XOR EBX, EBX*/ + addbyte(0xdb); + addbyte(0xc1); /*SAR EAX, 12*/ + addbyte(0xf8); + addbyte(12); + addbyte(0x0f); /*CMOVS EAX, EBX*/ + addbyte(0x48); + addbyte(0xc3); + addbyte(0xbb); /*MOV EBX, 0xff*/ + addlong(0xff); + addbyte(0x3d); /*CMP EAX, 0xff*/ + addlong(0xff); + addbyte(0x0f); /*CMOVAE EAX, EBX*/ + addbyte(0x43); + addbyte(0xc3); +#if 0 + fog_a = CLAMP(ia >> 12); +#endif + break; + + case FOG_W: + addbyte(0x8b); /*MOV EAX, state->w[EDI]+4*/ + addbyte(0x87); + addlong(offsetof(voodoo_state_t, w) + 4); + addbyte(0x31); /*XOR EBX, EBX*/ + addbyte(0xdb); + addbyte(0x09); /*OR EAX, EAX*/ + addbyte(0xc0); + addbyte(0x0f); /*CMOVS EAX, EBX*/ + addbyte(0x48); + addbyte(0xc3); + addbyte(0xbb); /*MOV EBX, 0xff*/ + addlong(0xff); + addbyte(0x3d); /*CMP EAX, 0xff*/ + addlong(0xff); + addbyte(0x0f); /*CMOVAE EAX, EBX*/ + addbyte(0x43); + addbyte(0xc3); +#if 0 + fog_a = CLAMP(w >> 32); +#endif + break; + } + addbyte(0x01); /*ADD EAX, EAX*/ + addbyte(0xc0); +#if 0 + fog_a++; +#endif + addbyte(0x66); /*PMULLW XMM3, alookup+4[EAX*8]*/ + addbyte(0x0f); + addbyte(0xd5); + addbyte(0x1c); + addbyte(0xc5); + addlong(((uintptr_t) alookup) + 16); + addbyte(0x66); /*PSRAW XMM3, 7*/ + addbyte(0x0f); + addbyte(0x71); + addbyte(0xe3); + addbyte(7); +#if 0 + fog_r = (fog_r * fog_a) >> 8; + fog_g = (fog_g * fog_a) >> 8; + fog_b = (fog_b * fog_a) >> 8; +#endif + + if (params->fogMode & FOG_MULT) { + addbyte(0xf3); /*MOV XMM0, XMM3*/ + addbyte(0x0f); + addbyte(0x7e); + addbyte(0xc3); + } else { + addbyte(0x66); /*PADDW XMM0, XMM3*/ addbyte(0x0f); addbyte(0xfd); - addbyte(0x1d); - addlong((uint32_t)&xmm_01_w); - addbyte(0x66); /*PMULLW XMM0, XMM3*/ + addbyte(0xc3); +#if 0 + src_r += fog_r; + src_g += fog_g; + src_b += fog_b; +#endif + } + addbyte(0x66); /*PACKUSWB XMM0, XMM0*/ + addbyte(0x0f); + addbyte(0x67); + addbyte(0xc0); + } + +#if 0 + src_r = CLAMP(src_r); + src_g = CLAMP(src_g); + src_b = CLAMP(src_b); +#endif + } + + if ((params->alphaMode & 1) && (alpha_func != AFUNC_NEVER) && (alpha_func != AFUNC_ALWAYS)) { + addbyte(0x0f); /*MOVZX ECX, params->alphaMode+3*/ + addbyte(0xb6); + addbyte(0x8e); + addlong(offsetof(voodoo_params_t, alphaMode) + 3); + addbyte(0x39); /*CMP EDX, ECX*/ + addbyte(0xca); + + switch (alpha_func) { + case AFUNC_LESSTHAN: + addbyte(0x0f); /*JAE skip*/ + addbyte(0x83); + a_skip_pos = block_pos; + addlong(0); + break; + case AFUNC_EQUAL: + addbyte(0x0f); /*JNE skip*/ + addbyte(0x85); + a_skip_pos = block_pos; + addlong(0); + break; + case AFUNC_LESSTHANEQUAL: + addbyte(0x0f); /*JA skip*/ + addbyte(0x87); + a_skip_pos = block_pos; + addlong(0); + break; + case AFUNC_GREATERTHAN: + addbyte(0x0f); /*JBE skip*/ + addbyte(0x86); + a_skip_pos = block_pos; + addlong(0); + break; + case AFUNC_NOTEQUAL: + addbyte(0x0f); /*JE skip*/ + addbyte(0x84); + a_skip_pos = block_pos; + addlong(0); + break; + case AFUNC_GREATERTHANEQUAL: + addbyte(0x0f); /*JB skip*/ + addbyte(0x82); + a_skip_pos = block_pos; + addlong(0); + break; + } + } else if ((params->alphaMode & 1) && (alpha_func == AFUNC_NEVER)) { + addbyte(0xC3); /*RET*/ + } + + if (params->alphaMode & (1 << 4)) { + addbyte(0x8b); /*MOV EAX, state->x[EDI]*/ + addbyte(0x87); + if (params->col_tiled) + addlong(offsetof(voodoo_state_t, x_tiled)); + else + addlong(offsetof(voodoo_state_t, x)); + addbyte(0x8b); /*MOV EBP, fb_mem*/ + addbyte(0xaf); + addlong(offsetof(voodoo_state_t, fb_mem)); + addbyte(0x01); /*ADD EDX, EDX*/ + addbyte(0xd2); + addbyte(0x0f); /*MOVZX EAX, [EBP+EAX*2]*/ + addbyte(0xb7); + addbyte(0x44); + addbyte(0x45); + addbyte(0); + addbyte(0x66); /*PUNPCKLBW XMM0, XMM2*/ + addbyte(0x0f); + addbyte(0x60); + addbyte(0xc2); + addbyte(0x66); /*MOVD XMM4, rgb565[EAX*4]*/ + addbyte(0x0f); + addbyte(0x6e); + addbyte(0x24); + addbyte(0x85); + addlong((uint32_t) rgb565); + addbyte(0x66); /*PUNPCKLBW XMM4, XMM2*/ + addbyte(0x0f); + addbyte(0x60); + addbyte(0xe2); + addbyte(0xf3); /*MOV XMM6, XMM4*/ + addbyte(0x0f); + addbyte(0x7e); + addbyte(0xf4); + + switch (dest_afunc) { + case AFUNC_AZERO: + addbyte(0x66); /*PXOR XMM4, XMM4*/ + addbyte(0x0f); + addbyte(0xef); + addbyte(0xe4); + break; + case AFUNC_ASRC_ALPHA: + addbyte(0x66); /*PMULLW XMM4, alookup[EDX*8]*/ addbyte(0x0f); addbyte(0xd5); - addbyte(0xc3); - addbyte(0x66); /*PMULHW XMM4, XMM3*/ + addbyte(0x24); + addbyte(0xd5); + addlong((uint32_t) alookup); + addbyte(0xf3); /*MOVQ XMM5, XMM4*/ addbyte(0x0f); - addbyte(0xe5); - addbyte(0xe3); - addbyte(0x66); /*PUNPCKLWD XMM0, XMM4*/ - addbyte(0x0f); - addbyte(0x61); - addbyte(0xc4); - addbyte(0x66); /*PSRLD XMM0, 8*/ - addbyte(0x0f); - addbyte(0x72); - addbyte(0xe0); - addbyte(8); - addbyte(0x66); /*PACKSSDW XMM0, XMM0*/ - addbyte(0x0f); - addbyte(0x6b); - addbyte(0xc0); - } - - if (cc_add == 1) - { - addbyte(0x66); /*PADDW XMM0, XMM1*/ + addbyte(0x7e); + addbyte(0xec); + addbyte(0x66); /*PADDW XMM4, alookup[1*8]*/ addbyte(0x0f); addbyte(0xfd); - addbyte(0xc1); + addbyte(0x25); + addlong((uint32_t) alookup + 16); + addbyte(0x66); /*PSRLW XMM5, 8*/ + addbyte(0x0f); + addbyte(0x71); + addbyte(0xd5); + addbyte(8); + addbyte(0x66); /*PADDW XMM4, XMM5*/ + addbyte(0x0f); + addbyte(0xfd); + addbyte(0xe5); + addbyte(0x66); /*PSRLW XMM4, 8*/ + addbyte(0x0f); + addbyte(0x71); + addbyte(0xd4); + addbyte(8); + break; + case AFUNC_A_COLOR: + addbyte(0x66); /*PMULLW XMM4, XMM0*/ + addbyte(0x0f); + addbyte(0xd5); + addbyte(0xe0); + addbyte(0xf3); /*MOVQ XMM5, XMM4*/ + addbyte(0x0f); + addbyte(0x7e); + addbyte(0xec); + addbyte(0x66); /*PADDW XMM4, alookup[1*8]*/ + addbyte(0x0f); + addbyte(0xfd); + addbyte(0x25); + addlong((uint32_t) alookup + 16); + addbyte(0x66); /*PSRLW XMM5, 8*/ + addbyte(0x0f); + addbyte(0x71); + addbyte(0xd5); + addbyte(8); + addbyte(0x66); /*PADDW XMM4, XMM5*/ + addbyte(0x0f); + addbyte(0xfd); + addbyte(0xe5); + addbyte(0x66); /*PSRLW XMM4, 8*/ + addbyte(0x0f); + addbyte(0x71); + addbyte(0xd4); + addbyte(8); + break; + case AFUNC_ADST_ALPHA: + break; + case AFUNC_AONE: + break; + case AFUNC_AOMSRC_ALPHA: + addbyte(0x66); /*PMULLW XMM4, aminuslookup[EDX*8]*/ + addbyte(0x0f); + addbyte(0xd5); + addbyte(0x24); + addbyte(0xd5); + addlong((uint32_t) aminuslookup); + addbyte(0xf3); /*MOVQ XMM5, XMM4*/ + addbyte(0x0f); + addbyte(0x7e); + addbyte(0xec); + addbyte(0x66); /*PADDW XMM4, alookup[1*8]*/ + addbyte(0x0f); + addbyte(0xfd); + addbyte(0x25); + addlong((uint32_t) alookup + 16); + addbyte(0x66); /*PSRLW XMM5, 8*/ + addbyte(0x0f); + addbyte(0x71); + addbyte(0xd5); + addbyte(8); + addbyte(0x66); /*PADDW XMM4, XMM5*/ + addbyte(0x0f); + addbyte(0xfd); + addbyte(0xe5); + addbyte(0x66); /*PSRLW XMM4, 8*/ + addbyte(0x0f); + addbyte(0x71); + addbyte(0xd4); + addbyte(8); + break; + case AFUNC_AOM_COLOR: + addbyte(0xf3); /*MOVQ XMM5, xmm_ff_w*/ + addbyte(0x0f); + addbyte(0x7e); + addbyte(0x2d); + addlong((uint32_t) &xmm_ff_w); + addbyte(0x66); /*PSUBW XMM5, XMM0*/ + addbyte(0x0f); + addbyte(0xf9); + addbyte(0xe8); + addbyte(0x66); /*PMULLW XMM4, XMM5*/ + addbyte(0x0f); + addbyte(0xd5); + addbyte(0xe5); + addbyte(0xf3); /*MOVQ XMM5, XMM4*/ + addbyte(0x0f); + addbyte(0x7e); + addbyte(0xec); + addbyte(0x66); /*PADDW XMM4, alookup[1*8]*/ + addbyte(0x0f); + addbyte(0xfd); + addbyte(0x25); + addlong((uint32_t) alookup + 16); + addbyte(0x66); /*PSRLW XMM5, 8*/ + addbyte(0x0f); + addbyte(0x71); + addbyte(0xd5); + addbyte(8); + addbyte(0x66); /*PADDW XMM4, XMM5*/ + addbyte(0x0f); + addbyte(0xfd); + addbyte(0xe5); + addbyte(0x66); /*PSRLW XMM4, 8*/ + addbyte(0x0f); + addbyte(0x71); + addbyte(0xd4); + addbyte(8); + break; + case AFUNC_AOMDST_ALPHA: + addbyte(0x66); /*PXOR XMM4, XMM4*/ + addbyte(0x0f); + addbyte(0xef); + addbyte(0xe4); + break; + case AFUNC_ASATURATE: + addbyte(0x66); /*PMULLW XMM4, minus_254*/ + addbyte(0x0f); + addbyte(0xd5); + addbyte(0x25); + addlong((uint32_t) &minus_254); + addbyte(0xf3); /*MOVQ XMM5, XMM4*/ + addbyte(0x0f); + addbyte(0x7e); + addbyte(0xec); + addbyte(0x66); /*PADDW XMM4, alookup[1*8]*/ + addbyte(0x0f); + addbyte(0xfd); + addbyte(0x25); + addlong((uint32_t) alookup + 16); + addbyte(0x66); /*PSRLW XMM5, 8*/ + addbyte(0x0f); + addbyte(0x71); + addbyte(0xd5); + addbyte(8); + addbyte(0x66); /*PADDW XMM4, XMM5*/ + addbyte(0x0f); + addbyte(0xfd); + addbyte(0xe5); + addbyte(0x66); /*PSRLW XMM4, 8*/ + addbyte(0x0f); + addbyte(0x71); + addbyte(0xd4); + addbyte(8); } + switch (src_afunc) { + case AFUNC_AZERO: + addbyte(0x66); /*PXOR XMM0, XMM0*/ + addbyte(0x0f); + addbyte(0xef); + addbyte(0xc0); + break; + case AFUNC_ASRC_ALPHA: + addbyte(0x66); /*PMULLW XMM0, alookup[EDX*8]*/ + addbyte(0x0f); + addbyte(0xd5); + addbyte(0x04); + addbyte(0xd5); + addlong((uint32_t) alookup); + addbyte(0xf3); /*MOVQ XMM5, XMM0*/ + addbyte(0x0f); + addbyte(0x7e); + addbyte(0xe8); + addbyte(0x66); /*PADDW XMM0, alookup[1*8]*/ + addbyte(0x0f); + addbyte(0xfd); + addbyte(0x05); + addlong((uint32_t) alookup + 16); + addbyte(0x66); /*PSRLW XMM5, 8*/ + addbyte(0x0f); + addbyte(0x71); + addbyte(0xd5); + addbyte(8); + addbyte(0x66); /*PADDW XMM0, XMM5*/ + addbyte(0x0f); + addbyte(0xfd); + addbyte(0xc5); + addbyte(0x66); /*PSRLW XMM0, 8*/ + addbyte(0x0f); + addbyte(0x71); + addbyte(0xd0); + addbyte(8); + break; + case AFUNC_A_COLOR: + addbyte(0x66); /*PMULLW XMM0, XMM6*/ + addbyte(0x0f); + addbyte(0xd5); + addbyte(0xc6); + addbyte(0xf3); /*MOVQ XMM5, XMM0*/ + addbyte(0x0f); + addbyte(0x7e); + addbyte(0xe8); + addbyte(0x66); /*PADDW XMM0, alookup[1*8]*/ + addbyte(0x0f); + addbyte(0xfd); + addbyte(0x05); + addlong((uint32_t) alookup + 16); + addbyte(0x66); /*PSRLW XMM5, 8*/ + addbyte(0x0f); + addbyte(0x71); + addbyte(0xd5); + addbyte(8); + addbyte(0x66); /*PADDW XMM0, XMM5*/ + addbyte(0x0f); + addbyte(0xfd); + addbyte(0xc5); + addbyte(0x66); /*PSRLW XMM0, 8*/ + addbyte(0x0f); + addbyte(0x71); + addbyte(0xd0); + addbyte(8); + break; + case AFUNC_ADST_ALPHA: + break; + case AFUNC_AONE: + break; + case AFUNC_AOMSRC_ALPHA: + addbyte(0x66); /*PMULLW XMM0, aminuslookup[EDX*8]*/ + addbyte(0x0f); + addbyte(0xd5); + addbyte(0x04); + addbyte(0xd5); + addlong((uint32_t) aminuslookup); + addbyte(0xf3); /*MOVQ XMM5, XMM0*/ + addbyte(0x0f); + addbyte(0x7e); + addbyte(0xe8); + addbyte(0x66); /*PADDW XMM0, alookup[1*8]*/ + addbyte(0x0f); + addbyte(0xfd); + addbyte(0x05); + addlong((uint32_t) alookup + 16); + addbyte(0x66); /*PSRLW XMM5, 8*/ + addbyte(0x0f); + addbyte(0x71); + addbyte(0xd5); + addbyte(8); + addbyte(0x66); /*PADDW XMM0, XMM5*/ + addbyte(0x0f); + addbyte(0xfd); + addbyte(0xc5); + addbyte(0x66); /*PSRLW XMM0, 8*/ + addbyte(0x0f); + addbyte(0x71); + addbyte(0xd0); + addbyte(8); + break; + case AFUNC_AOM_COLOR: + addbyte(0xf3); /*MOVQ XMM5, xmm_ff_w*/ + addbyte(0x0f); + addbyte(0x7e); + addbyte(0x2d); + addlong((uint32_t) &xmm_ff_w); + addbyte(0x66); /*PSUBW XMM5, XMM6*/ + addbyte(0x0f); + addbyte(0xf9); + addbyte(0xee); + addbyte(0x66); /*PMULLW XMM0, XMM5*/ + addbyte(0x0f); + addbyte(0xd5); + addbyte(0xc5); + addbyte(0xf3); /*MOVQ XMM5, XMM0*/ + addbyte(0x0f); + addbyte(0x7e); + addbyte(0xe8); + addbyte(0x66); /*PADDW XMM0, alookup[1*8]*/ + addbyte(0x0f); + addbyte(0xfd); + addbyte(0x05); + addlong((uint32_t) alookup + 16); + addbyte(0x66); /*PSRLW XMM5, 8*/ + addbyte(0x0f); + addbyte(0x71); + addbyte(0xd5); + addbyte(8); + addbyte(0x66); /*PADDW XMM0, XMM5*/ + addbyte(0x0f); + addbyte(0xfd); + addbyte(0xc5); + addbyte(0x66); /*PSRLW XMM0, 8*/ + addbyte(0x0f); + addbyte(0x71); + addbyte(0xd0); + addbyte(8); + break; + case AFUNC_AOMDST_ALPHA: + addbyte(0x66); /*PXOR XMM0, XMM0*/ + addbyte(0x0f); + addbyte(0xef); + addbyte(0xc0); + break; + case AFUNC_ACOLORBEFOREFOG: + break; + } + + addbyte(0x66); /*PADDW XMM0, XMM4*/ + addbyte(0x0f); + addbyte(0xfd); + addbyte(0xc4); + addbyte(0x66); /*PACKUSWB XMM0, XMM0*/ addbyte(0x0f); addbyte(0x67); addbyte(0xc0); + } - if (cc_invert_output) - { - addbyte(0x66); /*PXOR XMM0, 0xff*/ - addbyte(0x0f); - addbyte(0xef); - addbyte(0x05); - addlong((uint32_t)&xmm_ff_b); - } -//#if 0 -// addbyte(0x66); /*MOVD state->out[EDI], XMM0*/ -// addbyte(0x0f); -// addbyte(0x7e); -// addbyte(0x87); -// addlong(offsetof(voodoo_state_t, out)); - if (params->fogMode & FOG_ENABLE) - { - if (params->fogMode & FOG_CONSTANT) - { - addbyte(0x66); /*MOVD XMM3, params->fogColor[ESI]*/ - addbyte(0x0f); - addbyte(0x6e); - addbyte(0x9e); - addlong(offsetof(voodoo_params_t, fogColor)); - addbyte(0x66); /*PADDUSB XMM0, XMM3*/ - addbyte(0x0f); - addbyte(0xdc); - addbyte(0xc3); -/* src_r += params->fogColor.r; - src_g += params->fogColor.g; - src_b += params->fogColor.b; */ - } - else - { - /*int fog_r, fog_g, fog_b, fog_a; */ - - addbyte(0x66); /*PUNPCKLBW XMM0, XMM2*/ - addbyte(0x0f); - addbyte(0x60); - addbyte(0xc2); +#if 0 + addbyte(0x8b); /*MOV EDX, x (ESP+12)*/ + addbyte(0x54); + addbyte(0x24); + addbyte(12); +#endif - if (!(params->fogMode & FOG_ADD)) - { - addbyte(0x66); /*MOVD XMM3, params->fogColor[ESI]*/ - addbyte(0x0f); - addbyte(0x6e); - addbyte(0x9e); - addlong(offsetof(voodoo_params_t, fogColor)); - addbyte(0x66); /*PUNPCKLBW XMM3, XMM2*/ - addbyte(0x0f); - addbyte(0x60); - addbyte(0xda); - } - else - { - addbyte(0x66); /*PXOR XMM3, XMM3*/ - addbyte(0x0f); - addbyte(0xef); - addbyte(0xdb); - } - - if (!(params->fogMode & FOG_MULT)) - { - addbyte(0x66); /*PSUBW XMM3, XMM0*/ - addbyte(0x0f); - addbyte(0xf9); - addbyte(0xd8); - } + addbyte(0x8b); /*MOV EDX, state->x[EDI]*/ + addbyte(0x97); + if (params->col_tiled) + addlong(offsetof(voodoo_state_t, x_tiled)); + else + addlong(offsetof(voodoo_state_t, x)); - /*Divide by 2 to prevent overflow on multiply*/ - addbyte(0x66); /*PSRAW XMM3, 1*/ - addbyte(0x0f); - addbyte(0x71); - addbyte(0xe3); - addbyte(1); + addbyte(0x66); /*MOV EAX, XMM0*/ + addbyte(0x0f); + addbyte(0x7e); + addbyte(0xc0); - switch (params->fogMode & (FOG_Z|FOG_ALPHA)) - { - case 0: - addbyte(0x8b); /*MOV EBX, state->w_depth[EDI]*/ - addbyte(0x9f); - addlong(offsetof(voodoo_state_t, w_depth)); - addbyte(0x89); /*MOV EAX, EBX*/ - addbyte(0xd8); - addbyte(0xc1); /*SHR EBX, 10*/ - addbyte(0xeb); - addbyte(10); - addbyte(0xc1); /*SHR EAX, 2*/ - addbyte(0xe8); - addbyte(2); - addbyte(0x83); /*AND EBX, 0x3f*/ - addbyte(0xe3); - addbyte(0x3f); - addbyte(0x25); /*AND EAX, 0xff*/ - addlong(0xff); - addbyte(0xf6); /*MUL params->fogTable+1[ESI+EBX*2]*/ - addbyte(0xa4); - addbyte(0x5e); - addlong(offsetof(voodoo_params_t, fogTable)+1); - addbyte(0x0f); /*MOVZX EBX, params->fogTable[ESI+EBX*2]*/ - addbyte(0xb6); - addbyte(0x9c); - addbyte(0x5e); - addlong(offsetof(voodoo_params_t, fogTable)); - addbyte(0xc1); /*SHR EAX, 10*/ - addbyte(0xe8); - addbyte(10); - addbyte(0x01); /*ADD EAX, EBX*/ - addbyte(0xd8); + if (params->fbzMode & FBZ_RGB_WMASK) { +#if 0 + addbyte(0x89); /*MOV state->rgb_out[EDI], EAX*/ + addbyte(0x87); + addlong(offsetof(voodoo_state_t, rgb_out)); +#endif -/* int fog_idx = (w_depth >> 10) & 0x3f; - - fog_a = params->fogTable[fog_idx].fog; - fog_a += (params->fogTable[fog_idx].dfog * ((w_depth >> 2) & 0xff)) >> 10;*/ - break; - - case FOG_Z: - addbyte(0x8b); /*MOV EAX, state->z[EDI]*/ - addbyte(0x87); - addlong(offsetof(voodoo_state_t, z)); - addbyte(0xc1); /*SHR EAX, 12*/ - addbyte(0xe8); - addbyte(12); - addbyte(0x25); /*AND EAX, 0xff*/ - addlong(0xff); -// fog_a = (z >> 20) & 0xff; - break; - - case FOG_ALPHA: - addbyte(0x8b); /*MOV EAX, state->ia[EDI]*/ - addbyte(0x87); - addlong(offsetof(voodoo_state_t, ia)); - addbyte(0x31); /*XOR EBX, EBX*/ - addbyte(0xdb); - addbyte(0xc1); /*SAR EAX, 12*/ - addbyte(0xf8); - addbyte(12); - addbyte(0x0f); /*CMOVS EAX, EBX*/ - addbyte(0x48); - addbyte(0xc3); - addbyte(0xbb); /*MOV EBX, 0xff*/ - addlong(0xff); - addbyte(0x3d); /*CMP EAX, 0xff*/ - addlong(0xff); - addbyte(0x0f); /*CMOVAE EAX, EBX*/ - addbyte(0x43); - addbyte(0xc3); -// fog_a = CLAMP(ia >> 12); - break; - - case FOG_W: - addbyte(0x8b); /*MOV EAX, state->w[EDI]+4*/ - addbyte(0x87); - addlong(offsetof(voodoo_state_t, w)+4); - addbyte(0x31); /*XOR EBX, EBX*/ - addbyte(0xdb); - addbyte(0x09); /*OR EAX, EAX*/ - addbyte(0xc0); - addbyte(0x0f); /*CMOVS EAX, EBX*/ - addbyte(0x48); - addbyte(0xc3); - addbyte(0xbb); /*MOV EBX, 0xff*/ - addlong(0xff); - addbyte(0x3d); /*CMP EAX, 0xff*/ - addlong(0xff); - addbyte(0x0f); /*CMOVAE EAX, EBX*/ - addbyte(0x43); - addbyte(0xc3); -// fog_a = CLAMP(w >> 32); - break; - } - addbyte(0x01); /*ADD EAX, EAX*/ - addbyte(0xc0); -// fog_a++; - - addbyte(0x66); /*PMULLW XMM3, alookup+4[EAX*8]*/ - addbyte(0x0f); - addbyte(0xd5); - addbyte(0x1c); - addbyte(0xc5); - addlong(((uintptr_t)alookup) + 16); - addbyte(0x66); /*PSRAW XMM3, 7*/ - addbyte(0x0f); - addbyte(0x71); - addbyte(0xe3); - addbyte(7); -/* fog_r = (fog_r * fog_a) >> 8; - fog_g = (fog_g * fog_a) >> 8; - fog_b = (fog_b * fog_a) >> 8;*/ - - if (params->fogMode & FOG_MULT) - { - addbyte(0xf3); /*MOV XMM0, XMM3*/ - addbyte(0x0f); - addbyte(0x7e); - addbyte(0xc3); - } - else - { - addbyte(0x66); /*PADDW XMM0, XMM3*/ - addbyte(0x0f); - addbyte(0xfd); - addbyte(0xc3); -/* src_r += fog_r; - src_g += fog_g; - src_b += fog_b;*/ - } - addbyte(0x66); /*PACKUSWB XMM0, XMM0*/ - addbyte(0x0f); - addbyte(0x67); - addbyte(0xc0); - } - -/* src_r = CLAMP(src_r); - src_g = CLAMP(src_g); - src_b = CLAMP(src_b);*/ - } - - if ((params->alphaMode & 1) && (alpha_func != AFUNC_NEVER) && (alpha_func != AFUNC_ALWAYS)) - { - addbyte(0x0f); /*MOVZX ECX, params->alphaMode+3*/ - addbyte(0xb6); - addbyte(0x8e); - addlong(offsetof(voodoo_params_t, alphaMode) + 3); - addbyte(0x39); /*CMP EDX, ECX*/ - addbyte(0xca); - - switch (alpha_func) - { - case AFUNC_LESSTHAN: - addbyte(0x0f); /*JAE skip*/ - addbyte(0x83); - a_skip_pos = block_pos; - addlong(0); - break; - case AFUNC_EQUAL: - addbyte(0x0f); /*JNE skip*/ - addbyte(0x85); - a_skip_pos = block_pos; - addlong(0); - break; - case AFUNC_LESSTHANEQUAL: - addbyte(0x0f); /*JA skip*/ - addbyte(0x87); - a_skip_pos = block_pos; - addlong(0); - break; - case AFUNC_GREATERTHAN: - addbyte(0x0f); /*JBE skip*/ - addbyte(0x86); - a_skip_pos = block_pos; - addlong(0); - break; - case AFUNC_NOTEQUAL: - addbyte(0x0f); /*JE skip*/ - addbyte(0x84); - a_skip_pos = block_pos; - addlong(0); - break; - case AFUNC_GREATERTHANEQUAL: - addbyte(0x0f); /*JB skip*/ - addbyte(0x82); - a_skip_pos = block_pos; - addlong(0); - break; - } - } - else if ((params->alphaMode & 1) && (alpha_func == AFUNC_NEVER)) - { - addbyte(0xC3); /*RET*/ - } - - if (params->alphaMode & (1 << 4)) - { - addbyte(0x8b); /*MOV EAX, state->x[EDI]*/ - addbyte(0x87); - if (params->col_tiled) - addlong(offsetof(voodoo_state_t, x_tiled)); - else - addlong(offsetof(voodoo_state_t, x)); - addbyte(0x8b); /*MOV EBP, fb_mem*/ - addbyte(0xaf); - addlong(offsetof(voodoo_state_t, fb_mem)); - addbyte(0x01); /*ADD EDX, EDX*/ - addbyte(0xd2); - addbyte(0x0f); /*MOVZX EAX, [EBP+EAX*2]*/ - addbyte(0xb7); - addbyte(0x44); - addbyte(0x45); - addbyte(0); - addbyte(0x66); /*PUNPCKLBW XMM0, XMM2*/ - addbyte(0x0f); - addbyte(0x60); - addbyte(0xc2); - addbyte(0x66); /*MOVD XMM4, rgb565[EAX*4]*/ - addbyte(0x0f); - addbyte(0x6e); - addbyte(0x24); - addbyte(0x85); - addlong((uint32_t)rgb565); - addbyte(0x66); /*PUNPCKLBW XMM4, XMM2*/ - addbyte(0x0f); - addbyte(0x60); + if (dither) { + addbyte(0x8b); /*MOV ESI, real_y (ESP+16)*/ + addbyte(0x74); + addbyte(0x24); + addbyte(16 + 16); + addbyte(0x0f); /*MOVZX EBX, AH*/ /*G*/ + addbyte(0xb6); + addbyte(0xdc); + if (dither2x2) { + addbyte(0x83); /*AND EDX, 1*/ addbyte(0xe2); - addbyte(0xf3); /*MOV XMM6, XMM4*/ - addbyte(0x0f); - addbyte(0x7e); - addbyte(0xf4); - - switch (dest_afunc) - { - case AFUNC_AZERO: - addbyte(0x66); /*PXOR XMM4, XMM4*/ - addbyte(0x0f); - addbyte(0xef); - addbyte(0xe4); - break; - case AFUNC_ASRC_ALPHA: - addbyte(0x66); /*PMULLW XMM4, alookup[EDX*8]*/ - addbyte(0x0f); - addbyte(0xd5); - addbyte(0x24); - addbyte(0xd5); - addlong((uint32_t)alookup); - addbyte(0xf3); /*MOVQ XMM5, XMM4*/ - addbyte(0x0f); - addbyte(0x7e); - addbyte(0xec); - addbyte(0x66); /*PADDW XMM4, alookup[1*8]*/ - addbyte(0x0f); - addbyte(0xfd); - addbyte(0x25); - addlong((uint32_t)alookup + 16); - addbyte(0x66); /*PSRLW XMM5, 8*/ - addbyte(0x0f); - addbyte(0x71); - addbyte(0xd5); - addbyte(8); - addbyte(0x66); /*PADDW XMM4, XMM5*/ - addbyte(0x0f); - addbyte(0xfd); - addbyte(0xe5); - addbyte(0x66); /*PSRLW XMM4, 8*/ - addbyte(0x0f); - addbyte(0x71); - addbyte(0xd4); - addbyte(8); - break; - case AFUNC_A_COLOR: - addbyte(0x66); /*PMULLW XMM4, XMM0*/ - addbyte(0x0f); - addbyte(0xd5); - addbyte(0xe0); - addbyte(0xf3); /*MOVQ XMM5, XMM4*/ - addbyte(0x0f); - addbyte(0x7e); - addbyte(0xec); - addbyte(0x66); /*PADDW XMM4, alookup[1*8]*/ - addbyte(0x0f); - addbyte(0xfd); - addbyte(0x25); - addlong((uint32_t)alookup + 16); - addbyte(0x66); /*PSRLW XMM5, 8*/ - addbyte(0x0f); - addbyte(0x71); - addbyte(0xd5); - addbyte(8); - addbyte(0x66); /*PADDW XMM4, XMM5*/ - addbyte(0x0f); - addbyte(0xfd); - addbyte(0xe5); - addbyte(0x66); /*PSRLW XMM4, 8*/ - addbyte(0x0f); - addbyte(0x71); - addbyte(0xd4); - addbyte(8); - break; - case AFUNC_ADST_ALPHA: - break; - case AFUNC_AONE: - break; - case AFUNC_AOMSRC_ALPHA: - addbyte(0x66); /*PMULLW XMM4, aminuslookup[EDX*8]*/ - addbyte(0x0f); - addbyte(0xd5); - addbyte(0x24); - addbyte(0xd5); - addlong((uint32_t)aminuslookup); - addbyte(0xf3); /*MOVQ XMM5, XMM4*/ - addbyte(0x0f); - addbyte(0x7e); - addbyte(0xec); - addbyte(0x66); /*PADDW XMM4, alookup[1*8]*/ - addbyte(0x0f); - addbyte(0xfd); - addbyte(0x25); - addlong((uint32_t)alookup + 16); - addbyte(0x66); /*PSRLW XMM5, 8*/ - addbyte(0x0f); - addbyte(0x71); - addbyte(0xd5); - addbyte(8); - addbyte(0x66); /*PADDW XMM4, XMM5*/ - addbyte(0x0f); - addbyte(0xfd); - addbyte(0xe5); - addbyte(0x66); /*PSRLW XMM4, 8*/ - addbyte(0x0f); - addbyte(0x71); - addbyte(0xd4); - addbyte(8); - break; - case AFUNC_AOM_COLOR: - addbyte(0xf3); /*MOVQ XMM5, xmm_ff_w*/ - addbyte(0x0f); - addbyte(0x7e); - addbyte(0x2d); - addlong((uint32_t)&xmm_ff_w); - addbyte(0x66); /*PSUBW XMM5, XMM0*/ - addbyte(0x0f); - addbyte(0xf9); - addbyte(0xe8); - addbyte(0x66); /*PMULLW XMM4, XMM5*/ - addbyte(0x0f); - addbyte(0xd5); - addbyte(0xe5); - addbyte(0xf3); /*MOVQ XMM5, XMM4*/ - addbyte(0x0f); - addbyte(0x7e); - addbyte(0xec); - addbyte(0x66); /*PADDW XMM4, alookup[1*8]*/ - addbyte(0x0f); - addbyte(0xfd); - addbyte(0x25); - addlong((uint32_t)alookup + 16); - addbyte(0x66); /*PSRLW XMM5, 8*/ - addbyte(0x0f); - addbyte(0x71); - addbyte(0xd5); - addbyte(8); - addbyte(0x66); /*PADDW XMM4, XMM5*/ - addbyte(0x0f); - addbyte(0xfd); - addbyte(0xe5); - addbyte(0x66); /*PSRLW XMM4, 8*/ - addbyte(0x0f); - addbyte(0x71); - addbyte(0xd4); - addbyte(8); - break; - case AFUNC_AOMDST_ALPHA: - addbyte(0x66); /*PXOR XMM4, XMM4*/ - addbyte(0x0f); - addbyte(0xef); - addbyte(0xe4); - break; - case AFUNC_ASATURATE: - addbyte(0x66); /*PMULLW XMM4, minus_254*/ - addbyte(0x0f); - addbyte(0xd5); - addbyte(0x25); - addlong((uint32_t)&minus_254); - addbyte(0xf3); /*MOVQ XMM5, XMM4*/ - addbyte(0x0f); - addbyte(0x7e); - addbyte(0xec); - addbyte(0x66); /*PADDW XMM4, alookup[1*8]*/ - addbyte(0x0f); - addbyte(0xfd); - addbyte(0x25); - addlong((uint32_t)alookup + 16); - addbyte(0x66); /*PSRLW XMM5, 8*/ - addbyte(0x0f); - addbyte(0x71); - addbyte(0xd5); - addbyte(8); - addbyte(0x66); /*PADDW XMM4, XMM5*/ - addbyte(0x0f); - addbyte(0xfd); - addbyte(0xe5); - addbyte(0x66); /*PSRLW XMM4, 8*/ - addbyte(0x0f); - addbyte(0x71); - addbyte(0xd4); - addbyte(8); - } - - switch (src_afunc) - { - case AFUNC_AZERO: - addbyte(0x66); /*PXOR XMM0, XMM0*/ - addbyte(0x0f); - addbyte(0xef); - addbyte(0xc0); - break; - case AFUNC_ASRC_ALPHA: - addbyte(0x66); /*PMULLW XMM0, alookup[EDX*8]*/ - addbyte(0x0f); - addbyte(0xd5); - addbyte(0x04); - addbyte(0xd5); - addlong((uint32_t)alookup); - addbyte(0xf3); /*MOVQ XMM5, XMM0*/ - addbyte(0x0f); - addbyte(0x7e); - addbyte(0xe8); - addbyte(0x66); /*PADDW XMM0, alookup[1*8]*/ - addbyte(0x0f); - addbyte(0xfd); - addbyte(0x05); - addlong((uint32_t)alookup + 16); - addbyte(0x66); /*PSRLW XMM5, 8*/ - addbyte(0x0f); - addbyte(0x71); - addbyte(0xd5); - addbyte(8); - addbyte(0x66); /*PADDW XMM0, XMM5*/ - addbyte(0x0f); - addbyte(0xfd); - addbyte(0xc5); - addbyte(0x66); /*PSRLW XMM0, 8*/ - addbyte(0x0f); - addbyte(0x71); - addbyte(0xd0); - addbyte(8); - break; - case AFUNC_A_COLOR: - addbyte(0x66); /*PMULLW XMM0, XMM6*/ - addbyte(0x0f); - addbyte(0xd5); - addbyte(0xc6); - addbyte(0xf3); /*MOVQ XMM5, XMM0*/ - addbyte(0x0f); - addbyte(0x7e); - addbyte(0xe8); - addbyte(0x66); /*PADDW XMM0, alookup[1*8]*/ - addbyte(0x0f); - addbyte(0xfd); - addbyte(0x05); - addlong((uint32_t)alookup + 16); - addbyte(0x66); /*PSRLW XMM5, 8*/ - addbyte(0x0f); - addbyte(0x71); - addbyte(0xd5); - addbyte(8); - addbyte(0x66); /*PADDW XMM0, XMM5*/ - addbyte(0x0f); - addbyte(0xfd); - addbyte(0xc5); - addbyte(0x66); /*PSRLW XMM0, 8*/ - addbyte(0x0f); - addbyte(0x71); - addbyte(0xd0); - addbyte(8); - break; - case AFUNC_ADST_ALPHA: - break; - case AFUNC_AONE: - break; - case AFUNC_AOMSRC_ALPHA: - addbyte(0x66); /*PMULLW XMM0, aminuslookup[EDX*8]*/ - addbyte(0x0f); - addbyte(0xd5); - addbyte(0x04); - addbyte(0xd5); - addlong((uint32_t)aminuslookup); - addbyte(0xf3); /*MOVQ XMM5, XMM0*/ - addbyte(0x0f); - addbyte(0x7e); - addbyte(0xe8); - addbyte(0x66); /*PADDW XMM0, alookup[1*8]*/ - addbyte(0x0f); - addbyte(0xfd); - addbyte(0x05); - addlong((uint32_t)alookup + 16); - addbyte(0x66); /*PSRLW XMM5, 8*/ - addbyte(0x0f); - addbyte(0x71); - addbyte(0xd5); - addbyte(8); - addbyte(0x66); /*PADDW XMM0, XMM5*/ - addbyte(0x0f); - addbyte(0xfd); - addbyte(0xc5); - addbyte(0x66); /*PSRLW XMM0, 8*/ - addbyte(0x0f); - addbyte(0x71); - addbyte(0xd0); - addbyte(8); - break; - case AFUNC_AOM_COLOR: - addbyte(0xf3); /*MOVQ XMM5, xmm_ff_w*/ - addbyte(0x0f); - addbyte(0x7e); - addbyte(0x2d); - addlong((uint32_t)&xmm_ff_w); - addbyte(0x66); /*PSUBW XMM5, XMM6*/ - addbyte(0x0f); - addbyte(0xf9); - addbyte(0xee); - addbyte(0x66); /*PMULLW XMM0, XMM5*/ - addbyte(0x0f); - addbyte(0xd5); - addbyte(0xc5); - addbyte(0xf3); /*MOVQ XMM5, XMM0*/ - addbyte(0x0f); - addbyte(0x7e); - addbyte(0xe8); - addbyte(0x66); /*PADDW XMM0, alookup[1*8]*/ - addbyte(0x0f); - addbyte(0xfd); - addbyte(0x05); - addlong((uint32_t)alookup + 16); - addbyte(0x66); /*PSRLW XMM5, 8*/ - addbyte(0x0f); - addbyte(0x71); - addbyte(0xd5); - addbyte(8); - addbyte(0x66); /*PADDW XMM0, XMM5*/ - addbyte(0x0f); - addbyte(0xfd); - addbyte(0xc5); - addbyte(0x66); /*PSRLW XMM0, 8*/ - addbyte(0x0f); - addbyte(0x71); - addbyte(0xd0); - addbyte(8); - break; - case AFUNC_AOMDST_ALPHA: - addbyte(0x66); /*PXOR XMM0, XMM0*/ - addbyte(0x0f); - addbyte(0xef); - addbyte(0xc0); - break; - case AFUNC_ACOLORBEFOREFOG: - break; - } - - addbyte(0x66); /*PADDW XMM0, XMM4*/ - addbyte(0x0f); - addbyte(0xfd); - addbyte(0xc4); - - addbyte(0x66); /*PACKUSWB XMM0, XMM0*/ - addbyte(0x0f); - addbyte(0x67); - addbyte(0xc0); + addbyte(1); + addbyte(0x83); /*AND ESI, 1*/ + addbyte(0xe6); + addbyte(1); + addbyte(0xc1); /*SHL EBX, 2*/ + addbyte(0xe3); + addbyte(2); + } else { + addbyte(0x83); /*AND EDX, 3*/ + addbyte(0xe2); + addbyte(3); + addbyte(0x83); /*AND ESI, 3*/ + addbyte(0xe6); + addbyte(3); + addbyte(0xc1); /*SHL EBX, 4*/ + addbyte(0xe3); + addbyte(4); + } + addbyte(0x0f); /*MOVZX ECX, AL*/ /*R*/ + addbyte(0xb6); + addbyte(0xc8); + if (dither2x2) { + addbyte(0xc1); /*SHR EAX, 14*/ + addbyte(0xe8); + addbyte(14); + addbyte(0x8d); /*LEA ESI, EDX+ESI*2*/ + addbyte(0x34); + addbyte(0x72); + } else { + addbyte(0xc1); /*SHR EAX, 12*/ + addbyte(0xe8); + addbyte(12); + addbyte(0x8d); /*LEA ESI, EDX+ESI*4*/ + addbyte(0x34); + addbyte(0xb2); + } + addbyte(0x8b); /*MOV EDX, state->x[EDI]*/ + addbyte(0x97); + if (params->col_tiled) + addlong(offsetof(voodoo_state_t, x_tiled)); + else + addlong(offsetof(voodoo_state_t, x)); + if (dither2x2) { + addbyte(0xc1); /*SHL ECX, 2*/ + addbyte(0xe1); + addbyte(2); + addbyte(0x25); /*AND EAX, 0x3fc*/ /*B*/ + addlong(0x3fc); + } else { + addbyte(0xc1); /*SHL ECX, 4*/ + addbyte(0xe1); + addbyte(4); + addbyte(0x25); /*AND EAX, 0xff0*/ /*B*/ + addlong(0xff0); + } + addbyte(0x0f); /*MOVZX EBX, dither_g[EBX+ESI]*/ + addbyte(0xb6); + addbyte(0x9c); + addbyte(0x33); + addlong(dither2x2 ? (uint32_t) dither_g2x2 : (uint32_t) dither_g); + addbyte(0x0f); /*MOVZX ECX, dither_rb[ECX+ESI]*/ + addbyte(0xb6); + addbyte(0x8c); + addbyte(0x31); + addlong(dither2x2 ? (uint32_t) dither_rb2x2 : (uint32_t) dither_rb); + addbyte(0x0f); /*MOVZX EAX, dither_rb[EAX+ESI]*/ + addbyte(0xb6); + addbyte(0x84); + addbyte(0x30); + addlong(dither2x2 ? (uint32_t) dither_rb2x2 : (uint32_t) dither_rb); + addbyte(0xc1); /*SHL EBX, 5*/ + addbyte(0xe3); + addbyte(5); + addbyte(0xc1); /*SHL EAX, 11*/ + addbyte(0xe0); + addbyte(11); + addbyte(0x09); /*OR EAX, EBX*/ + addbyte(0xd8); + addbyte(0x09); /*OR EAX, ECX*/ + addbyte(0xc8); + } else { + addbyte(0x89); /*MOV EBX, EAX*/ + addbyte(0xc3); + addbyte(0x0f); /*MOVZX ECX, AH*/ + addbyte(0xb6); + addbyte(0xcc); + addbyte(0xc1); /*SHR EAX, 3*/ + addbyte(0xe8); + addbyte(3); + addbyte(0xc1); /*SHR EBX, 8*/ + addbyte(0xeb); + addbyte(8); + addbyte(0xc1); /*SHL ECX, 3*/ + addbyte(0xe1); + addbyte(3); + addbyte(0x81); /*AND EAX, 0x001f*/ + addbyte(0xe0); + addlong(0x001f); + addbyte(0x81); /*AND EBX, 0xf800*/ + addbyte(0xe3); + addlong(0xf800); + addbyte(0x81); /*AND ECX, 0x07e0*/ + addbyte(0xe1); + addlong(0x07e0); + addbyte(0x09); /*OR EAX, EBX*/ + addbyte(0xd8); + addbyte(0x09); /*OR EAX, ECX*/ + addbyte(0xc8); } -//#endif - -// addbyte(0x8b); /*MOV EDX, x (ESP+12)*/ -// addbyte(0x54); -// addbyte(0x24); -// addbyte(12); - + addbyte(0x8b); /*MOV ESI, fb_mem*/ + addbyte(0xb7); + addlong(offsetof(voodoo_state_t, fb_mem)); + addbyte(0x66); /*MOV [ESI+EDX*2], AX*/ + addbyte(0x89); + addbyte(0x04); + addbyte(0x56); + } + if ((params->fbzMode & (FBZ_DEPTH_WMASK | FBZ_DEPTH_ENABLE)) == (FBZ_DEPTH_WMASK | FBZ_DEPTH_ENABLE)) { addbyte(0x8b); /*MOV EDX, state->x[EDI]*/ addbyte(0x97); - if (params->col_tiled) - addlong(offsetof(voodoo_state_t, x_tiled)); + if (params->aux_tiled) + addlong(offsetof(voodoo_state_t, x_tiled)); else - addlong(offsetof(voodoo_state_t, x)); + addlong(offsetof(voodoo_state_t, x)); + addbyte(0x66); /*MOV AX, new_depth*/ + addbyte(0x8b); + addbyte(0x87); + addlong(offsetof(voodoo_state_t, new_depth)); + addbyte(0x8b); /*MOV ESI, aux_mem*/ + addbyte(0xb7); + addlong(offsetof(voodoo_state_t, aux_mem)); + addbyte(0x66); /*MOV [ESI+EDX*2], AX*/ + addbyte(0x89); + addbyte(0x04); + addbyte(0x56); + } - addbyte(0x66); /*MOV EAX, XMM0*/ - addbyte(0x0f); - addbyte(0x7e); - addbyte(0xc0); - - if (params->fbzMode & FBZ_RGB_WMASK) - { -// addbyte(0x89); /*MOV state->rgb_out[EDI], EAX*/ -// addbyte(0x87); -// addlong(offsetof(voodoo_state_t, rgb_out)); - - if (dither) - { - addbyte(0x8b); /*MOV ESI, real_y (ESP+16)*/ - addbyte(0x74); - addbyte(0x24); - addbyte(16+16); - addbyte(0x0f); /*MOVZX EBX, AH*/ /*G*/ - addbyte(0xb6); - addbyte(0xdc); - if (dither2x2) - { - addbyte(0x83); /*AND EDX, 1*/ - addbyte(0xe2); - addbyte(1); - addbyte(0x83); /*AND ESI, 1*/ - addbyte(0xe6); - addbyte(1); - addbyte(0xc1); /*SHL EBX, 2*/ - addbyte(0xe3); - addbyte(2); - } - else - { - addbyte(0x83); /*AND EDX, 3*/ - addbyte(0xe2); - addbyte(3); - addbyte(0x83); /*AND ESI, 3*/ - addbyte(0xe6); - addbyte(3); - addbyte(0xc1); /*SHL EBX, 4*/ - addbyte(0xe3); - addbyte(4); - } - addbyte(0x0f); /*MOVZX ECX, AL*/ /*R*/ - addbyte(0xb6); - addbyte(0xc8); - if (dither2x2) - { - addbyte(0xc1); /*SHR EAX, 14*/ - addbyte(0xe8); - addbyte(14); - addbyte(0x8d); /*LEA ESI, EDX+ESI*2*/ - addbyte(0x34); - addbyte(0x72); - } - else - { - addbyte(0xc1); /*SHR EAX, 12*/ - addbyte(0xe8); - addbyte(12); - addbyte(0x8d); /*LEA ESI, EDX+ESI*4*/ - addbyte(0x34); - addbyte(0xb2); - } - addbyte(0x8b); /*MOV EDX, state->x[EDI]*/ - addbyte(0x97); - if (params->col_tiled) - addlong(offsetof(voodoo_state_t, x_tiled)); - else - addlong(offsetof(voodoo_state_t, x)); - if (dither2x2) - { - addbyte(0xc1); /*SHL ECX, 2*/ - addbyte(0xe1); - addbyte(2); - addbyte(0x25); /*AND EAX, 0x3fc*/ /*B*/ - addlong(0x3fc); - } - else - { - addbyte(0xc1); /*SHL ECX, 4*/ - addbyte(0xe1); - addbyte(4); - addbyte(0x25); /*AND EAX, 0xff0*/ /*B*/ - addlong(0xff0); - } - addbyte(0x0f); /*MOVZX EBX, dither_g[EBX+ESI]*/ - addbyte(0xb6); - addbyte(0x9c); - addbyte(0x33); - addlong(dither2x2 ? (uint32_t)dither_g2x2 : (uint32_t)dither_g); - addbyte(0x0f); /*MOVZX ECX, dither_rb[ECX+ESI]*/ - addbyte(0xb6); - addbyte(0x8c); - addbyte(0x31); - addlong(dither2x2 ? (uint32_t)dither_rb2x2 : (uint32_t)dither_rb); - addbyte(0x0f); /*MOVZX EAX, dither_rb[EAX+ESI]*/ - addbyte(0xb6); - addbyte(0x84); - addbyte(0x30); - addlong(dither2x2 ? (uint32_t)dither_rb2x2 : (uint32_t)dither_rb); - addbyte(0xc1); /*SHL EBX, 5*/ - addbyte(0xe3); - addbyte(5); - addbyte(0xc1); /*SHL EAX, 11*/ - addbyte(0xe0); - addbyte(11); - addbyte(0x09); /*OR EAX, EBX*/ - addbyte(0xd8); - addbyte(0x09); /*OR EAX, ECX*/ - addbyte(0xc8); - } - else - { - addbyte(0x89); /*MOV EBX, EAX*/ - addbyte(0xc3); - addbyte(0x0f); /*MOVZX ECX, AH*/ - addbyte(0xb6); - addbyte(0xcc); - addbyte(0xc1); /*SHR EAX, 3*/ - addbyte(0xe8); - addbyte(3); - addbyte(0xc1); /*SHR EBX, 8*/ - addbyte(0xeb); - addbyte(8); - addbyte(0xc1); /*SHL ECX, 3*/ - addbyte(0xe1); - addbyte(3); - addbyte(0x81); /*AND EAX, 0x001f*/ - addbyte(0xe0); - addlong(0x001f); - addbyte(0x81); /*AND EBX, 0xf800*/ - addbyte(0xe3); - addlong(0xf800); - addbyte(0x81); /*AND ECX, 0x07e0*/ - addbyte(0xe1); - addlong(0x07e0); - addbyte(0x09); /*OR EAX, EBX*/ - addbyte(0xd8); - addbyte(0x09); /*OR EAX, ECX*/ - addbyte(0xc8); - } - addbyte(0x8b); /*MOV ESI, fb_mem*/ - addbyte(0xb7); - addlong(offsetof(voodoo_state_t, fb_mem)); - addbyte(0x66); /*MOV [ESI+EDX*2], AX*/ - addbyte(0x89); - addbyte(0x04); - addbyte(0x56); - } + if (z_skip_pos) + *(uint32_t *) &code_block[z_skip_pos] = (block_pos - z_skip_pos) - 4; + if (a_skip_pos) + *(uint32_t *) &code_block[a_skip_pos] = (block_pos - a_skip_pos) - 4; + if (chroma_skip_pos) + *(uint32_t *) &code_block[chroma_skip_pos] = (block_pos - chroma_skip_pos) - 4; - if ((params->fbzMode & (FBZ_DEPTH_WMASK | FBZ_DEPTH_ENABLE)) == (FBZ_DEPTH_WMASK | FBZ_DEPTH_ENABLE)) - { - addbyte(0x8b); /*MOV EDX, state->x[EDI]*/ - addbyte(0x97); - if (params->aux_tiled) - addlong(offsetof(voodoo_state_t, x_tiled)); - else - addlong(offsetof(voodoo_state_t, x)); - addbyte(0x66); /*MOV AX, new_depth*/ - addbyte(0x8b); - addbyte(0x87); - addlong(offsetof(voodoo_state_t, new_depth)); - addbyte(0x8b); /*MOV ESI, aux_mem*/ - addbyte(0xb7); - addlong(offsetof(voodoo_state_t, aux_mem)); - addbyte(0x66); /*MOV [ESI+EDX*2], AX*/ - addbyte(0x89); - addbyte(0x04); - addbyte(0x56); - } + addbyte(0x8b); /*MOV ESI, [ESP+8]*/ + addbyte(0x74); + addbyte(0x24); + addbyte(8 + 16); - if (z_skip_pos) - *(uint32_t *)&code_block[z_skip_pos] = (block_pos - z_skip_pos) - 4; - if (a_skip_pos) - *(uint32_t *)&code_block[a_skip_pos] = (block_pos - a_skip_pos) - 4; - if (chroma_skip_pos) - *(uint32_t *)&code_block[chroma_skip_pos] = (block_pos - chroma_skip_pos) - 4; - - - addbyte(0x8b); /*MOV ESI, [ESP+8]*/ - addbyte(0x74); - addbyte(0x24); - addbyte(8+16); - - if (voodoo->dual_tmus) - { - addbyte(0xf3); /*MOVDQU XMM3, state->tmu1_s[EDI]*/ - addbyte(0x0f); - addbyte(0x6f); - addbyte(0x9f); - addlong(offsetof(voodoo_state_t, tmu1_s)); - addbyte(0xf3); /*MOVQ XMM4, state->tmu1_w[EDI]*/ - addbyte(0x0f); - addbyte(0x7e); - addbyte(0xa7); - addlong(offsetof(voodoo_state_t, tmu1_w)); - addbyte(0xf3); /*MOVDQU XMM5, params->tmu[1].dSdX[ESI]*/ - addbyte(0x0f); - addbyte(0x6f); - addbyte(0xae); - addlong(offsetof(voodoo_params_t, tmu[1].dSdX)); - addbyte(0xf3); /*MOVQ XMM6, params->tmu[1].dWdX[ESI]*/ - addbyte(0x0f); - addbyte(0x7e); - addbyte(0xb6); - addlong(offsetof(voodoo_params_t, tmu[1].dWdX)); - if (state->xdir > 0) - { - addbyte(0x66); /*PADDQ XMM3, XMM5*/ - addbyte(0x0f); - addbyte(0xd4); - addbyte(0xdd); - addbyte(0x66); /*PADDQ XMM4, XMM6*/ - addbyte(0x0f); - addbyte(0xd4); - addbyte(0xe6); - } - else - { - addbyte(0x66); /*PSUBQ XMM3, XMM5*/ - addbyte(0x0f); - addbyte(0xfb); - addbyte(0xdd); - addbyte(0x66); /*PSUBQ XMM4, XMM6*/ - addbyte(0x0f); - addbyte(0xfb); - addbyte(0xe6); - } - addbyte(0xf3); /*MOVDQU state->tmu1_s, XMM3*/ - addbyte(0x0f); - addbyte(0x7f); - addbyte(0x9f); - addlong(offsetof(voodoo_state_t, tmu1_s)); - addbyte(0x66); /*MOVQ state->tmu1_w, XMM4*/ - addbyte(0x0f); - addbyte(0xd6); - addbyte(0xa7); - addlong(offsetof(voodoo_state_t, tmu1_w)); - } - - addbyte(0xf3); /*MOVDQU XMM1, state->ib[EDI]*/ - addbyte(0x0f); - addbyte(0x6f); - addbyte(0x8f); - addlong(offsetof(voodoo_state_t, ib)); - addbyte(0xf3); /*MOVDQU XMM3, state->tmu0_s[EDI]*/ + if (voodoo->dual_tmus) { + addbyte(0xf3); /*MOVDQU XMM3, state->tmu1_s[EDI]*/ addbyte(0x0f); addbyte(0x6f); addbyte(0x9f); - addlong(offsetof(voodoo_state_t, tmu0_s)); - addbyte(0xf3); /*MOVQ XMM4, state->tmu0_w[EDI]*/ + addlong(offsetof(voodoo_state_t, tmu1_s)); + addbyte(0xf3); /*MOVQ XMM4, state->tmu1_w[EDI]*/ addbyte(0x0f); addbyte(0x7e); addbyte(0xa7); - addlong(offsetof(voodoo_state_t, tmu0_w)); - addbyte(0xf3); /*MOVDQU XMM0, params->dBdX[ESI]*/ - addbyte(0x0f); - addbyte(0x6f); - addbyte(0x86); - addlong(offsetof(voodoo_params_t, dBdX)); - addbyte(0x8b); /*MOV EAX, params->dZdX[ESI]*/ - addbyte(0x86); - addlong(offsetof(voodoo_params_t, dZdX)); - addbyte(0xf3); /*MOVDQU XMM5, params->tmu[0].dSdX[ESI]*/ + addlong(offsetof(voodoo_state_t, tmu1_w)); + addbyte(0xf3); /*MOVDQU XMM5, params->tmu[1].dSdX[ESI]*/ addbyte(0x0f); addbyte(0x6f); addbyte(0xae); - addlong(offsetof(voodoo_params_t, tmu[0].dSdX)); - addbyte(0xf3); /*MOVQ XMM6, params->tmu[0].dWdX[ESI]*/ + addlong(offsetof(voodoo_params_t, tmu[1].dSdX)); + addbyte(0xf3); /*MOVQ XMM6, params->tmu[1].dWdX[ESI]*/ addbyte(0x0f); addbyte(0x7e); addbyte(0xb6); - addlong(offsetof(voodoo_params_t, tmu[0].dWdX)); - - if (state->xdir > 0) - { - addbyte(0x66); /*PADDD XMM1, XMM0*/ - addbyte(0x0f); - addbyte(0xfe); - addbyte(0xc8); + addlong(offsetof(voodoo_params_t, tmu[1].dWdX)); + if (state->xdir > 0) { + addbyte(0x66); /*PADDQ XMM3, XMM5*/ + addbyte(0x0f); + addbyte(0xd4); + addbyte(0xdd); + addbyte(0x66); /*PADDQ XMM4, XMM6*/ + addbyte(0x0f); + addbyte(0xd4); + addbyte(0xe6); + } else { + addbyte(0x66); /*PSUBQ XMM3, XMM5*/ + addbyte(0x0f); + addbyte(0xfb); + addbyte(0xdd); + addbyte(0x66); /*PSUBQ XMM4, XMM6*/ + addbyte(0x0f); + addbyte(0xfb); + addbyte(0xe6); } - else - { - addbyte(0x66); /*PSUBD XMM1, XMM0*/ - addbyte(0x0f); - addbyte(0xfa); - addbyte(0xc8); - } - - addbyte(0xf3); /*MOVQ XMM0, state->w*/ - addbyte(0x0f); - addbyte(0x7e); - addbyte(0x87); - addlong(offsetof(voodoo_state_t, w)); - addbyte(0xf3); /*MOVDQU state->ib, XMM1*/ - addbyte(0x0f); - addbyte(0x7f); - addbyte(0x8f); - addlong(offsetof(voodoo_state_t, ib)); - addbyte(0xf3); /*MOVQ XMM7, params->dWdX*/ - addbyte(0x0f); - addbyte(0x7e); - addbyte(0xbe); - addlong(offsetof(voodoo_params_t, dWdX)); - - if (state->xdir > 0) - { - addbyte(0x66); /*PADDQ XMM3, XMM5*/ - addbyte(0x0f); - addbyte(0xd4); - addbyte(0xdd); - addbyte(0x66); /*PADDQ XMM4, XMM6*/ - addbyte(0x0f); - addbyte(0xd4); - addbyte(0xe6); - addbyte(0x66); /*PADDQ XMM0, XMM7*/ - addbyte(0x0f); - addbyte(0xd4); - addbyte(0xc7); - addbyte(0x01); /*ADD state->z[EDI], EAX*/ - addbyte(0x87); - addlong(offsetof(voodoo_state_t, z)); - } - else - { - addbyte(0x66); /*PSUBQ XMM3, XMM5*/ - addbyte(0x0f); - addbyte(0xfb); - addbyte(0xdd); - addbyte(0x66); /*PSUBQ XMM4, XMM6*/ - addbyte(0x0f); - addbyte(0xfb); - addbyte(0xe6); - addbyte(0x66); /*PSUBQ XMM0, XMM7*/ - addbyte(0x0f); - addbyte(0xfb); - addbyte(0xc7); - addbyte(0x29); /*SUB state->z[EDI], EAX*/ - addbyte(0x87); - addlong(offsetof(voodoo_state_t, z)); - } - - addbyte(0xf3); /*MOVDQU state->tmu0_s, XMM3*/ + addbyte(0xf3); /*MOVDQU state->tmu1_s, XMM3*/ addbyte(0x0f); addbyte(0x7f); addbyte(0x9f); - addlong(offsetof(voodoo_state_t, tmu0_s)); - addbyte(0x66); /*MOVQ state->tmu0_w, XMM4*/ + addlong(offsetof(voodoo_state_t, tmu1_s)); + addbyte(0x66); /*MOVQ state->tmu1_w, XMM4*/ addbyte(0x0f); addbyte(0xd6); addbyte(0xa7); - addlong(offsetof(voodoo_state_t, tmu0_w)); - addbyte(0x66); /*MOVQ state->w, XMM0*/ - addbyte(0x0f); - addbyte(0xd6); - addbyte(0x87); - addlong(offsetof(voodoo_state_t, w)); - - addbyte(0x83); /*ADD state->pixel_count[EDI], 1*/ - addbyte(0x87); - addlong(offsetof(voodoo_state_t, pixel_count)); - addbyte(1); + addlong(offsetof(voodoo_state_t, tmu1_w)); + } - if (params->fbzColorPath & FBZCP_TEXTURE_ENABLED) - { - if ((params->textureMode[0] & TEXTUREMODE_MASK) == TEXTUREMODE_PASSTHROUGH || - (params->textureMode[0] & TEXTUREMODE_LOCAL_MASK) == TEXTUREMODE_LOCAL) - { - addbyte(0x83); /*ADD state->texel_count[EDI], 1*/ - addbyte(0x87); - addlong(offsetof(voodoo_state_t, texel_count)); - addbyte(1); - } - else - { - addbyte(0x83); /*ADD state->texel_count[EDI], 2*/ - addbyte(0x87); - addlong(offsetof(voodoo_state_t, texel_count)); - addbyte(2); - } + addbyte(0xf3); /*MOVDQU XMM1, state->ib[EDI]*/ + addbyte(0x0f); + addbyte(0x6f); + addbyte(0x8f); + addlong(offsetof(voodoo_state_t, ib)); + addbyte(0xf3); /*MOVDQU XMM3, state->tmu0_s[EDI]*/ + addbyte(0x0f); + addbyte(0x6f); + addbyte(0x9f); + addlong(offsetof(voodoo_state_t, tmu0_s)); + addbyte(0xf3); /*MOVQ XMM4, state->tmu0_w[EDI]*/ + addbyte(0x0f); + addbyte(0x7e); + addbyte(0xa7); + addlong(offsetof(voodoo_state_t, tmu0_w)); + addbyte(0xf3); /*MOVDQU XMM0, params->dBdX[ESI]*/ + addbyte(0x0f); + addbyte(0x6f); + addbyte(0x86); + addlong(offsetof(voodoo_params_t, dBdX)); + addbyte(0x8b); /*MOV EAX, params->dZdX[ESI]*/ + addbyte(0x86); + addlong(offsetof(voodoo_params_t, dZdX)); + addbyte(0xf3); /*MOVDQU XMM5, params->tmu[0].dSdX[ESI]*/ + addbyte(0x0f); + addbyte(0x6f); + addbyte(0xae); + addlong(offsetof(voodoo_params_t, tmu[0].dSdX)); + addbyte(0xf3); /*MOVQ XMM6, params->tmu[0].dWdX[ESI]*/ + addbyte(0x0f); + addbyte(0x7e); + addbyte(0xb6); + addlong(offsetof(voodoo_params_t, tmu[0].dWdX)); + + if (state->xdir > 0) { + addbyte(0x66); /*PADDD XMM1, XMM0*/ + addbyte(0x0f); + addbyte(0xfe); + addbyte(0xc8); + } else { + addbyte(0x66); /*PSUBD XMM1, XMM0*/ + addbyte(0x0f); + addbyte(0xfa); + addbyte(0xc8); + } + + addbyte(0xf3); /*MOVQ XMM0, state->w*/ + addbyte(0x0f); + addbyte(0x7e); + addbyte(0x87); + addlong(offsetof(voodoo_state_t, w)); + addbyte(0xf3); /*MOVDQU state->ib, XMM1*/ + addbyte(0x0f); + addbyte(0x7f); + addbyte(0x8f); + addlong(offsetof(voodoo_state_t, ib)); + addbyte(0xf3); /*MOVQ XMM7, params->dWdX*/ + addbyte(0x0f); + addbyte(0x7e); + addbyte(0xbe); + addlong(offsetof(voodoo_params_t, dWdX)); + + if (state->xdir > 0) { + addbyte(0x66); /*PADDQ XMM3, XMM5*/ + addbyte(0x0f); + addbyte(0xd4); + addbyte(0xdd); + addbyte(0x66); /*PADDQ XMM4, XMM6*/ + addbyte(0x0f); + addbyte(0xd4); + addbyte(0xe6); + addbyte(0x66); /*PADDQ XMM0, XMM7*/ + addbyte(0x0f); + addbyte(0xd4); + addbyte(0xc7); + addbyte(0x01); /*ADD state->z[EDI], EAX*/ + addbyte(0x87); + addlong(offsetof(voodoo_state_t, z)); + } else { + addbyte(0x66); /*PSUBQ XMM3, XMM5*/ + addbyte(0x0f); + addbyte(0xfb); + addbyte(0xdd); + addbyte(0x66); /*PSUBQ XMM4, XMM6*/ + addbyte(0x0f); + addbyte(0xfb); + addbyte(0xe6); + addbyte(0x66); /*PSUBQ XMM0, XMM7*/ + addbyte(0x0f); + addbyte(0xfb); + addbyte(0xc7); + addbyte(0x29); /*SUB state->z[EDI], EAX*/ + addbyte(0x87); + addlong(offsetof(voodoo_state_t, z)); + } + + addbyte(0xf3); /*MOVDQU state->tmu0_s, XMM3*/ + addbyte(0x0f); + addbyte(0x7f); + addbyte(0x9f); + addlong(offsetof(voodoo_state_t, tmu0_s)); + addbyte(0x66); /*MOVQ state->tmu0_w, XMM4*/ + addbyte(0x0f); + addbyte(0xd6); + addbyte(0xa7); + addlong(offsetof(voodoo_state_t, tmu0_w)); + addbyte(0x66); /*MOVQ state->w, XMM0*/ + addbyte(0x0f); + addbyte(0xd6); + addbyte(0x87); + addlong(offsetof(voodoo_state_t, w)); + + addbyte(0x83); /*ADD state->pixel_count[EDI], 1*/ + addbyte(0x87); + addlong(offsetof(voodoo_state_t, pixel_count)); + addbyte(1); + + if (params->fbzColorPath & FBZCP_TEXTURE_ENABLED) { + if ((params->textureMode[0] & TEXTUREMODE_MASK) == TEXTUREMODE_PASSTHROUGH || (params->textureMode[0] & TEXTUREMODE_LOCAL_MASK) == TEXTUREMODE_LOCAL) { + addbyte(0x83); /*ADD state->texel_count[EDI], 1*/ + addbyte(0x87); + addlong(offsetof(voodoo_state_t, texel_count)); + addbyte(1); + } else { + addbyte(0x83); /*ADD state->texel_count[EDI], 2*/ + addbyte(0x87); + addlong(offsetof(voodoo_state_t, texel_count)); + addbyte(2); } - addbyte(0x8b); /*MOV EAX, state->x[EDI]*/ + } + addbyte(0x8b); /*MOV EAX, state->x[EDI]*/ + addbyte(0x87); + addlong(offsetof(voodoo_state_t, x)); + + if (state->xdir > 0) { + addbyte(0x83); /*ADD state->x[EDI], 1*/ addbyte(0x87); addlong(offsetof(voodoo_state_t, x)); - - if (state->xdir > 0) - { - addbyte(0x83); /*ADD state->x[EDI], 1*/ - addbyte(0x87); - addlong(offsetof(voodoo_state_t, x)); - addbyte(1); - } - else - { - addbyte(0x83); /*SUB state->x[EDI], 1*/ - addbyte(0xaf); - addlong(offsetof(voodoo_state_t, x)); - addbyte(1); - } + addbyte(1); + } else { + addbyte(0x83); /*SUB state->x[EDI], 1*/ + addbyte(0xaf); + addlong(offsetof(voodoo_state_t, x)); + addbyte(1); + } - addbyte(0x3b); /*CMP EAX, state->x2[EDI]*/ - addbyte(0x87); - addlong(offsetof(voodoo_state_t, x2)); - addbyte(0x0f); /*JNZ loop_jump_pos*/ - addbyte(0x85); - addlong(loop_jump_pos - (block_pos + 4)); - - addbyte(0x5b); /*POP EBX*/ - addbyte(0x5e); /*POP ESI*/ - addbyte(0x5f); /*POP EDI*/ - addbyte(0x5d); /*POP EBP*/ - - addbyte(0xC3); /*RET*/ - - if (params->textureMode[1] & TEXTUREMODE_TRILINEAR) - cs = cs; + addbyte(0x3b); /*CMP EAX, state->x2[EDI]*/ + addbyte(0x87); + addlong(offsetof(voodoo_state_t, x2)); + addbyte(0x0f); /*JNZ loop_jump_pos*/ + addbyte(0x85); + addlong(loop_jump_pos - (block_pos + 4)); + + addbyte(0x5b); /*POP EBX*/ + addbyte(0x5e); /*POP ESI*/ + addbyte(0x5f); /*POP EDI*/ + addbyte(0x5d); /*POP EBP*/ + + addbyte(0xC3); /*RET*/ + + if (params->textureMode[1] & TEXTUREMODE_TRILINEAR) + cs = cs; } int voodoo_recomp = 0; -static inline void *voodoo_get_block(voodoo_t *voodoo, voodoo_params_t *params, voodoo_state_t *state, int odd_even) +static inline void * +voodoo_get_block(voodoo_t *voodoo, voodoo_params_t *params, voodoo_state_t *state, int odd_even) { - int c; - int b = last_block[odd_even]; - voodoo_x86_data_t *data; - voodoo_x86_data_t *codegen_data = voodoo->codegen_data; - - for (c = 0; c < 8; c++) - { - data = &codegen_data[odd_even + b*4]; - - if (state->xdir == data->xdir && - params->alphaMode == data->alphaMode && - params->fbzMode == data->fbzMode && - params->fogMode == data->fogMode && - params->fbzColorPath == data->fbzColorPath && - (voodoo->trexInit1[0] & (1 << 18)) == data->trexInit1 && - params->textureMode[0] == data->textureMode[0] && - params->textureMode[1] == data->textureMode[1] && - (params->tLOD[0] & LOD_MASK) == data->tLOD[0] && - (params->tLOD[1] & LOD_MASK) == data->tLOD[1] && - ((params->col_tiled || params->aux_tiled) ? 1 : 0) == data->is_tiled) - { - last_block[odd_even] = b; - return data->code_block; - } - - b = (b + 1) & 7; + int c; + int b = last_block[odd_even]; + voodoo_x86_data_t *data; + voodoo_x86_data_t *codegen_data = voodoo->codegen_data; + + for (c = 0; c < 8; c++) { + data = &codegen_data[odd_even + b * 4]; + + if (state->xdir == data->xdir && params->alphaMode == data->alphaMode && params->fbzMode == data->fbzMode && params->fogMode == data->fogMode && params->fbzColorPath == data->fbzColorPath && (voodoo->trexInit1[0] & (1 << 18)) == data->trexInit1 && params->textureMode[0] == data->textureMode[0] && params->textureMode[1] == data->textureMode[1] && (params->tLOD[0] & LOD_MASK) == data->tLOD[0] && (params->tLOD[1] & LOD_MASK) == data->tLOD[1] && ((params->col_tiled || params->aux_tiled) ? 1 : 0) == data->is_tiled) { + last_block[odd_even] = b; + return data->code_block; } -voodoo_recomp++; - data = &codegen_data[odd_even + next_block_to_write[odd_even]*4]; -// code_block = data->code_block; - - voodoo_generate(data->code_block, voodoo, params, state, depth_op); - data->xdir = state->xdir; - data->alphaMode = params->alphaMode; - data->fbzMode = params->fbzMode; - data->fogMode = params->fogMode; - data->fbzColorPath = params->fbzColorPath; - data->trexInit1 = voodoo->trexInit1[0] & (1 << 18); - data->textureMode[0] = params->textureMode[0]; - data->textureMode[1] = params->textureMode[1]; - data->tLOD[0] = params->tLOD[0] & LOD_MASK; - data->tLOD[1] = params->tLOD[1] & LOD_MASK; - data->is_tiled = (params->col_tiled || params->aux_tiled) ? 1 : 0; + b = (b + 1) & 7; + } + voodoo_recomp++; + data = &codegen_data[odd_even + next_block_to_write[odd_even] * 4]; +#if 0 + code_block = data->code_block; +#endif - next_block_to_write[odd_even] = (next_block_to_write[odd_even] + 1) & 7; - - return data->code_block; + voodoo_generate(data->code_block, voodoo, params, state, depth_op); + + data->xdir = state->xdir; + data->alphaMode = params->alphaMode; + data->fbzMode = params->fbzMode; + data->fogMode = params->fogMode; + data->fbzColorPath = params->fbzColorPath; + data->trexInit1 = voodoo->trexInit1[0] & (1 << 18); + data->textureMode[0] = params->textureMode[0]; + data->textureMode[1] = params->textureMode[1]; + data->tLOD[0] = params->tLOD[0] & LOD_MASK; + data->tLOD[1] = params->tLOD[1] & LOD_MASK; + data->is_tiled = (params->col_tiled || params->aux_tiled) ? 1 : 0; + + next_block_to_write[odd_even] = (next_block_to_write[odd_even] + 1) & 7; + + return data->code_block; } -void voodoo_codegen_init(voodoo_t *voodoo) +void +voodoo_codegen_init(voodoo_t *voodoo) { - int c; + voodoo->codegen_data = plat_mmap(sizeof(voodoo_x86_data_t) * BLOCK_NUM * 4, 1); - voodoo->codegen_data = plat_mmap(sizeof(voodoo_x86_data_t) * BLOCK_NUM*4, 1); + for (uint16_t c = 0; c < 256; c++) { + int d[4]; + int _ds = c & 0xf; + int dt = c >> 4; - for (c = 0; c < 256; c++) - { - int d[4]; - int _ds = c & 0xf; - int dt = c >> 4; - - alookup[c] = _mm_set_epi32(0, 0, c | (c << 16), c | (c << 16)); - aminuslookup[c] = _mm_set_epi32(0, 0, (255-c) | ((255-c) << 16), (255-c) | ((255-c) << 16)); + alookup[c] = _mm_set_epi32(0, 0, c | (c << 16), c | (c << 16)); + aminuslookup[c] = _mm_set_epi32(0, 0, (255 - c) | ((255 - c) << 16), (255 - c) | ((255 - c) << 16)); - d[0] = (16 - _ds) * (16 - dt); - d[1] = _ds * (16 - dt); - d[2] = (16 - _ds) * dt; - d[3] = _ds * dt; + d[0] = (16 - _ds) * (16 - dt); + d[1] = _ds * (16 - dt); + d[2] = (16 - _ds) * dt; + d[3] = _ds * dt; - bilinear_lookup[c*2] = _mm_set_epi32(d[1] | (d[1] << 16), d[1] | (d[1] << 16), d[0] | (d[0] << 16), d[0] | (d[0] << 16)); - bilinear_lookup[c*2 + 1] = _mm_set_epi32(d[3] | (d[3] << 16), d[3] | (d[3] << 16), d[2] | (d[2] << 16), d[2] | (d[2] << 16)); - } - alookup[256] = _mm_set_epi32(0, 0, 256 | (256 << 16), 256 | (256 << 16)); - xmm_00_ff_w[0] = _mm_set_epi32(0, 0, 0, 0); - xmm_00_ff_w[1] = _mm_set_epi32(0, 0, 0xff | (0xff << 16), 0xff | (0xff << 16)); + bilinear_lookup[c * 2] = _mm_set_epi32(d[1] | (d[1] << 16), d[1] | (d[1] << 16), d[0] | (d[0] << 16), d[0] | (d[0] << 16)); + bilinear_lookup[c * 2 + 1] = _mm_set_epi32(d[3] | (d[3] << 16), d[3] | (d[3] << 16), d[2] | (d[2] << 16), d[2] | (d[2] << 16)); + } + alookup[256] = _mm_set_epi32(0, 0, 256 | (256 << 16), 256 | (256 << 16)); + xmm_00_ff_w[0] = _mm_set_epi32(0, 0, 0, 0); + xmm_00_ff_w[1] = _mm_set_epi32(0, 0, 0xff | (0xff << 16), 0xff | (0xff << 16)); } -void voodoo_codegen_close(voodoo_t *voodoo) +void +voodoo_codegen_close(voodoo_t *voodoo) { - plat_munmap(voodoo->codegen_data, sizeof(voodoo_x86_data_t) * BLOCK_NUM*4); + plat_munmap(voodoo->codegen_data, sizeof(voodoo_x86_data_t) * BLOCK_NUM * 4); } + +#endif /*VIDEO_VOODOO_CODEGEN_X86_H*/ diff --git a/src/include/86box/vid_voodoo_common.h b/src/include/86box/vid_voodoo_common.h index 8000f30c9..96865ac6d 100644 --- a/src/include/86box/vid_voodoo_common.h +++ b/src/include/86box/vid_voodoo_common.h @@ -1,92 +1,103 @@ /* - * 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. + * 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. + * This file is part of the 86Box distribution. * - * Voodoo Graphics, 2, Banshee, 3 emulation. + * Voodoo Graphics, 2, Banshee, 3 emulation. * * * - * Authors: Sarah Walker, - * leilei + * Authors: Sarah Walker, + * leilei * - * Copyright 2008-2020 Sarah Walker. + * Copyright 2008-2020 Sarah Walker. */ +#ifndef VIDEO_VOODOO_COMMON_H +#define VIDEO_VOODOO_COMMON_H + #ifdef CLAMP -#undef CLAMP +# undef CLAMP #endif -#define CLAMP(x) (((x) < 0) ? 0 : (((x) > 0xff) ? 0xff : (x))) -#define CLAMP16(x) (((x) < 0) ? 0 : (((x) > 0xffff) ? 0xffff : (x))) +#define CLAMP(x) (((x) < 0) ? 0 : (((x) > 0xff) ? 0xff : (x))) +#define CLAMP16(x) (((x) < 0) ? 0 : (((x) > 0xffff) ? 0xffff : (x))) - -#define LOD_MAX 8 +#define LOD_MAX 8 #define TEX_DIRTY_SHIFT 10 -#define TEX_CACHE_MAX 64 +#define TEX_CACHE_MAX 64 -enum -{ - VOODOO_1 = 0, - VOODOO_SB50, - VOODOO_2, - VOODOO_BANSHEE, - VOODOO_3 +#ifdef __cplusplus +# include +using atomic_int = std::atomic; +#else +# include +#endif + +enum { + VOODOO_1 = 0, + VOODOO_SB50, + VOODOO_2, + VOODOO_BANSHEE, + VOODOO_3 }; -typedef union int_float -{ - uint32_t i; - float f; +typedef union int_float { + uint32_t i; + float f; } int_float; -typedef struct rgbvoodoo_t -{ - uint8_t b, g, r; - uint8_t pad; +typedef struct rgbvoodoo_t { + uint8_t b; + uint8_t g; + uint8_t r; + uint8_t pad; } rgbvoodoo_t; -typedef struct rgba8_t -{ - uint8_t b, g, r, a; +typedef struct rgba8_t { + uint8_t b; + uint8_t g; + uint8_t r; + uint8_t a; } rgba8_t; -typedef union rgba_u -{ - struct - { - uint8_t b, g, r, a; - } rgba; - uint32_t u; +typedef union rgba_u { + struct + { + uint8_t b; + uint8_t g; + uint8_t r; + uint8_t a; + } rgba; + uint32_t u; } rgba_u; -#define FIFO_SIZE 65536 -#define FIFO_MASK (FIFO_SIZE - 1) +#define FIFO_SIZE 65536 +#define FIFO_MASK (FIFO_SIZE - 1) #define FIFO_ENTRY_SIZE (1 << 31) -#define FIFO_ENTRIES (voodoo->fifo_write_idx - voodoo->fifo_read_idx) -#define FIFO_FULL ((voodoo->fifo_write_idx - voodoo->fifo_read_idx) >= FIFO_SIZE-4) -#define FIFO_EMPTY (voodoo->fifo_read_idx == voodoo->fifo_write_idx) +#define FIFO_ENTRIES (voodoo->fifo_write_idx - voodoo->fifo_read_idx) +#define FIFO_FULL ((voodoo->fifo_write_idx - voodoo->fifo_read_idx) >= FIFO_SIZE - 4) +#define FIFO_EMPTY (voodoo->fifo_read_idx == voodoo->fifo_write_idx) -#define FIFO_TYPE 0xff000000 -#define FIFO_ADDR 0x00ffffff +#define FIFO_TYPE 0xff000000 +#define FIFO_ADDR 0x00ffffff -enum -{ - FIFO_INVALID = (0x00 << 24), - FIFO_WRITEL_REG = (0x01 << 24), - FIFO_WRITEW_FB = (0x02 << 24), - FIFO_WRITEL_FB = (0x03 << 24), - FIFO_WRITEL_TEX = (0x04 << 24), - FIFO_WRITEL_2DREG = (0x05 << 24) +enum { + FIFO_INVALID = (0x00 << 24), + FIFO_WRITEL_REG = (0x01 << 24), + FIFO_WRITEW_FB = (0x02 << 24), + FIFO_WRITEL_FB = (0x03 << 24), + FIFO_WRITEL_TEX = (0x04 << 24), + FIFO_WRITEL_2DREG = (0x05 << 24) }; -#define PARAM_SIZE 1024 -#define PARAM_MASK (PARAM_SIZE - 1) +#define PARAM_SIZE 1024 +#define PARAM_MASK (PARAM_SIZE - 1) #define PARAM_ENTRY_SIZE (1 << 31) #define PARAM_ENTRIES(x) (voodoo->params_write_idx - voodoo->params_read_idx[x]) @@ -95,431 +106,585 @@ enum typedef struct { - uint32_t addr_type; - uint32_t val; + uint32_t addr_type; + uint32_t val; } fifo_entry_t; -typedef struct voodoo_params_t -{ - int command; +typedef struct voodoo_params_t { + int command; - int32_t vertexAx, vertexAy, vertexBx, vertexBy, vertexCx, vertexCy; + int32_t vertexAx; + int32_t vertexAy; + int32_t vertexBx; + int32_t vertexBy; + int32_t vertexCx; + int32_t vertexCy; - uint32_t startR, startG, startB, startZ, startA; + uint32_t startR; + uint32_t startG; + uint32_t startB; + uint32_t startZ; + uint32_t startA; - int32_t dBdX, dGdX, dRdX, dAdX, dZdX; + int32_t dBdX; + int32_t dGdX; + int32_t dRdX; + int32_t dAdX; + int32_t dZdX; - int32_t dBdY, dGdY, dRdY, dAdY, dZdY; + int32_t dBdY; + int32_t dGdY; + int32_t dRdY; + int32_t dAdY; + int32_t dZdY; - int64_t startW, dWdX, dWdY; + int64_t startW; + int64_t dWdX; + int64_t dWdY; - struct - { - int64_t startS, startT, startW, p1; - int64_t dSdX, dTdX, dWdX, p2; - int64_t dSdY, dTdY, dWdY, p3; - } tmu[2]; + struct + { + int64_t startS; + int64_t startT; + int64_t startW; + int64_t p1; + int64_t dSdX; + int64_t dTdX; + int64_t dWdX; + int64_t p2; + int64_t dSdY; + int64_t dTdY; + int64_t dWdY; + int64_t p3; + } tmu[2]; - uint32_t color0, color1; + uint32_t color0; + uint32_t color1; - uint32_t fbzMode; - uint32_t fbzColorPath; + uint32_t fbzMode; + uint32_t fbzColorPath; - uint32_t fogMode; - rgbvoodoo_t fogColor; - struct - { - uint8_t fog, dfog; - } fogTable[64]; + uint32_t fogMode; + rgbvoodoo_t fogColor; + struct + { + uint8_t fog; + uint8_t dfog; + } fogTable[64]; - uint32_t alphaMode; + uint32_t alphaMode; - uint32_t zaColor; + uint32_t zaColor; - int chromaKey_r, chromaKey_g, chromaKey_b; - uint32_t chromaKey; + int chromaKey_r; + int chromaKey_g; + int chromaKey_b; + uint32_t chromaKey; - uint32_t textureMode[2]; - uint32_t tLOD[2]; + uint32_t textureMode[2]; + uint32_t tLOD[2]; - uint32_t texBaseAddr[2], texBaseAddr1[2], texBaseAddr2[2], texBaseAddr38[2]; + uint32_t texBaseAddr[2]; + uint32_t texBaseAddr1[2]; + uint32_t texBaseAddr2[2]; + uint32_t texBaseAddr38[2]; - uint32_t tex_base[2][LOD_MAX+2]; - uint32_t tex_end[2][LOD_MAX+2]; - int tex_width[2]; - int tex_w_mask[2][LOD_MAX+2]; - int tex_w_nmask[2][LOD_MAX+2]; - int tex_h_mask[2][LOD_MAX+2]; - int tex_shift[2][LOD_MAX+2]; - int tex_lod[2][LOD_MAX+2]; - int tex_entry[2]; - int detail_max[2], detail_bias[2], detail_scale[2]; + uint32_t tex_base[2][LOD_MAX + 2]; + uint32_t tex_end[2][LOD_MAX + 2]; + int tex_width[2]; + int tex_w_mask[2][LOD_MAX + 2]; + int tex_w_nmask[2][LOD_MAX + 2]; + int tex_h_mask[2][LOD_MAX + 2]; + int tex_shift[2][LOD_MAX + 2]; + int tex_lod[2][LOD_MAX + 2]; + int tex_entry[2]; + int detail_max[2]; + int detail_bias[2]; + int detail_scale[2]; - uint32_t draw_offset, aux_offset; + uint32_t draw_offset; + uint32_t aux_offset; - int tformat[2]; + int tformat[2]; - int clipLeft, clipRight, clipLowY, clipHighY; - int clipLeft1, clipRight1, clipLowY1, clipHighY1; + int clipLeft; + int clipRight; + int clipLowY; + int clipHighY; + int clipLeft1; + int clipRight1; + int clipLowY1; + int clipHighY1; - int sign; + int sign; - uint32_t front_offset; + uint32_t front_offset; - uint32_t swapbufferCMD; + uint32_t swapbufferCMD; - uint32_t stipple; + uint32_t stipple; - int col_tiled, aux_tiled; - int row_width, aux_row_width; + int col_tiled; + int aux_tiled; + int row_width; + int aux_row_width; } voodoo_params_t; -typedef struct texture_t -{ - uint32_t base; - uint32_t tLOD; - volatile int refcount, refcount_r[4]; - int is16; - uint32_t palette_checksum; - uint32_t addr_start[4], addr_end[4]; - uint32_t *data; +typedef struct texture_t { + uint32_t base; + uint32_t tLOD; + atomic_int refcount; + atomic_int refcount_r[4]; + int is16; + uint32_t palette_checksum; + uint32_t addr_start[4]; + uint32_t addr_end[4]; + uint32_t *data; } texture_t; -typedef struct vert_t -{ - float sVx, sVy; - float sRed, sGreen, sBlue, sAlpha; - float sVz, sWb; - float sW0, sS0, sT0; - float sW1, sS1, sT1; +typedef struct vert_t { + float sVx; + float sVy; + float sRed; + float sGreen; + float sBlue; + float sAlpha; + float sVz; + float sWb; + float sW0; + float sS0; + float sT0; + float sW1; + float sS1; + float sT1; } vert_t; -typedef struct clip_t -{ - int x_min, x_max; - int y_min, y_max; +typedef struct clip_t { + int x_min; + int x_max; + int y_min; + int y_max; } clip_t; -typedef struct voodoo_t -{ - mem_mapping_t mapping; +typedef struct voodoo_t { + mem_mapping_t mapping; - int pci_enable; + int pci_enable; - uint8_t dac_data[8]; - int dac_reg, dac_reg_ff; - uint8_t dac_readdata; - uint16_t dac_pll_regs[16]; + uint8_t pci_slot; - float pixel_clock; - uint64_t line_time; + uint8_t dac_data[8]; + int dac_reg; + int dac_reg_ff; + uint8_t dac_readdata; + uint16_t dac_pll_regs[16]; - voodoo_params_t params; + float pixel_clock; + uint64_t line_time; - uint32_t fbiInit0, fbiInit1, fbiInit2, fbiInit3, fbiInit4; - uint32_t fbiInit5, fbiInit6, fbiInit7; /*Voodoo 2*/ + voodoo_params_t params; - uint32_t initEnable; + uint32_t fbiInit0; + uint32_t fbiInit1; + uint32_t fbiInit2; + uint32_t fbiInit3; + uint32_t fbiInit4; + uint32_t fbiInit5; + uint32_t fbiInit6; + uint32_t fbiInit7; /*Voodoo 2*/ - uint32_t lfbMode; + uint32_t initEnable; - uint32_t memBaseAddr; + uint32_t lfbMode; - int_float fvertexAx, fvertexAy, fvertexBx, fvertexBy, fvertexCx, fvertexCy; + uint32_t memBaseAddr; - uint32_t front_offset, back_offset; + int_float fvertexAx; + int_float fvertexAy; + int_float fvertexBx; + int_float fvertexBy; + int_float fvertexCx; + int_float fvertexCy; - uint32_t fb_read_offset, fb_write_offset; + uint32_t front_offset; + uint32_t back_offset; - int row_width, aux_row_width; - int block_width; - - int col_tiled, aux_tiled; + uint32_t fb_read_offset; + uint32_t fb_write_offset; - uint8_t *fb_mem, *tex_mem[2]; - uint16_t *tex_mem_w[2]; + int row_width; + int aux_row_width; + int block_width; - int rgb_sel; + int col_tiled; + int aux_tiled; - uint32_t trexInit1[2]; + uint8_t *fb_mem; + uint8_t *tex_mem[2]; + uint16_t *tex_mem_w[2]; + + int rgb_sel; + + uint32_t trexInit1[2]; + + uint32_t tmuConfig; - uint32_t tmuConfig; + mutex_t *swap_mutex; + int swap_count; + + int disp_buffer; + int draw_buffer; + pc_timer_t timer; + + int line; + svga_t *svga; + + uint32_t backPorch; + uint32_t videoDimensions; + uint32_t hSync; + uint32_t vSync; - mutex_t *swap_mutex; - int swap_count; - - int disp_buffer, draw_buffer; - pc_timer_t timer; - - int line; - svga_t *svga; - - uint32_t backPorch; - uint32_t videoDimensions; - uint32_t hSync, vSync; - - int h_total, v_total, v_disp; - int h_disp; - int v_retrace; - - struct - { - uint32_t y[4], i[4], q[4]; - } nccTable[2][2]; - - rgba_u palette[2][256]; - - rgba_u ncc_lookup[2][2][256]; - int ncc_dirty[2]; - - thread_t *fifo_thread; - thread_t *render_thread[4]; - event_t *wake_fifo_thread; - event_t *wake_main_thread; - event_t *fifo_not_full_event; - event_t *render_not_full_event[4]; - event_t *wake_render_thread[4]; - - int voodoo_busy; - int render_voodoo_busy[4]; - - int render_threads; - int odd_even_mask; - - int pixel_count[4], texel_count[4], tri_count, frame_count; - int pixel_count_old[4], texel_count_old[4]; - int wr_count, rd_count, tex_count; - - int retrace_count; - int swap_interval; - uint32_t swap_offset; - int swap_pending; - - int bilinear_enabled; - int dithersub_enabled; - - int fb_size; - uint32_t fb_mask; - - int texture_size; - uint32_t texture_mask; - - int dual_tmus; - int type; - - fifo_entry_t fifo[FIFO_SIZE]; - volatile int fifo_read_idx, fifo_write_idx; - volatile int cmd_read, cmd_written, cmd_written_fifo; - - voodoo_params_t params_buffer[PARAM_SIZE]; - volatile int params_read_idx[4], params_write_idx; - - uint32_t cmdfifo_base, cmdfifo_end, cmdfifo_size; - int cmdfifo_rp, cmdfifo_ret_addr; - int cmdfifo_in_sub; - volatile int cmdfifo_depth_rd, cmdfifo_depth_wr; - volatile int cmdfifo_enabled; - uint32_t cmdfifo_amin, cmdfifo_amax; - int cmdfifo_holecount; - - uint32_t sSetupMode; - vert_t verts[4]; - unsigned int vertex_ages[3]; - unsigned int vertex_next_age; - int num_verticies; - int cull_pingpong; - - int flush; - - int scrfilter; - int scrfilterEnabled; - int scrfilterThreshold; - int scrfilterThresholdOld; - - uint32_t last_write_addr; - - uint32_t fbiPixelsIn; - uint32_t fbiChromaFail; - uint32_t fbiZFuncFail; - uint32_t fbiAFuncFail; - uint32_t fbiPixelsOut; - - uint32_t bltSrcBaseAddr; - uint32_t bltDstBaseAddr; - int bltSrcXYStride, bltDstXYStride; - uint32_t bltSrcChromaRange, bltDstChromaRange; - int bltSrcChromaMinR, bltSrcChromaMinG, bltSrcChromaMinB; - int bltSrcChromaMaxR, bltSrcChromaMaxG, bltSrcChromaMaxB; - int bltDstChromaMinR, bltDstChromaMinG, bltDstChromaMinB; - int bltDstChromaMaxR, bltDstChromaMaxG, bltDstChromaMaxB; - - int bltClipRight, bltClipLeft; - int bltClipHighY, bltClipLowY; - - int bltSrcX, bltSrcY; - int bltDstX, bltDstY; - int bltSizeX, bltSizeY; - int bltRop[4]; - uint16_t bltColorFg, bltColorBg; - - uint32_t bltCommand; - - uint32_t leftOverlayBuf; - - struct - { - int dst_x, dst_y; - int cur_x; - int size_x, size_y; - int x_dir, y_dir; - int dst_stride; - } blt; - - struct - { - uint32_t bresError0, bresError1; - uint32_t clip0Min, clip0Max; - uint32_t clip1Min, clip1Max; - uint32_t colorBack, colorFore; - uint32_t command, commandExtra; - uint32_t dstBaseAddr; - uint32_t dstFormat; - uint32_t dstSize; - uint32_t dstXY; - uint32_t lineStipple; - uint32_t lineStyle; - uint32_t rop; - uint32_t srcBaseAddr; - uint32_t srcFormat; - uint32_t srcSize; - uint32_t srcXY; - - uint32_t colorPattern[64]; - - int bres_error_0, bres_error_1; - uint32_t colorPattern8[64], colorPattern16[64], colorPattern24[64]; - int cur_x, cur_y; - uint32_t dstBaseAddr_tiled; - uint32_t dstColorkeyMin, dstColorkeyMax; - int dstSizeX, dstSizeY; - int dstX, dstY; - int dst_stride; - int patoff_x, patoff_y; - uint8_t rops[4]; - uint32_t srcBaseAddr_tiled; - uint32_t srcColorkeyMin, srcColorkeyMax; - int srcSizeX, srcSizeY; - int srcX, srcY; - int src_stride; - int old_srcX; - - /*Used for handling packed 24bpp host data*/ - int host_data_remainder; - uint32_t old_host_data; - - /*Polyfill coordinates*/ - int lx[2], rx[2]; - int ly[2], ry[2]; - - /*Polyfill state*/ - int error[2]; - int dx[2], dy[2]; - int x_inc[2]; /*y_inc is always 1 for polyfill*/ - int lx_cur, rx_cur; - - clip_t clip[2]; - - uint8_t host_data[16384]; - int host_data_count; - int host_data_size_src, host_data_size_dest; - int src_stride_src, src_stride_dest; - - int src_bpp; - - int line_pix_pos, line_bit_pos; - int line_rep_cnt, line_bit_mask_size; - } banshee_blt; - - struct - { - uint32_t vidOverlayStartCoords; - uint32_t vidOverlayEndScreenCoords; - uint32_t vidOverlayDudx, vidOverlayDudxOffsetSrcWidth; - uint32_t vidOverlayDvdy, vidOverlayDvdyOffset; - //uint32_t vidDesktopOverlayStride; - - int start_x, start_y; - int end_x, end_y; - int size_x, size_y; - int overlay_bytes; - - unsigned int src_y; - } overlay; - - rgbvoodoo_t clutData[33]; - int clutData_dirty; - rgbvoodoo_t clutData256[256]; - uint32_t video_16to32[0x10000]; - - uint8_t dirty_line[2048]; - int dirty_line_low, dirty_line_high; - - int fb_write_buffer, fb_draw_buffer; - int buffer_cutoff; - - uint32_t tile_base, tile_stride; - int tile_stride_shift, tile_x, tile_x_real; - - int y_origin_swap; - - int read_time, write_time, burst_time; - - pc_timer_t wake_timer; - - /* screen filter tables */ - uint8_t thefilter[256][256]; - uint8_t thefilterg[256][256]; - uint8_t thefilterb[256][256]; - uint16_t purpleline[256][3]; - - texture_t texture_cache[2][TEX_CACHE_MAX]; - uint8_t texture_present[2][16384]; - int texture_last_removed; - - uint32_t palette_checksum[2]; - int palette_dirty[2]; - - uint64_t time; - int render_time[4]; - - int force_blit_count; - int can_blit; - mutex_t* force_blit_mutex; - - int use_recompiler; - void *codegen_data; - - struct voodoo_set_t *set; - - uint8_t fifo_thread_run, render_thread_run[4]; - - uint8_t *vram, *changedvram; - - void *p; + int h_total; + int v_total; + int v_disp; + int h_disp; + int v_retrace; + + struct { + uint32_t y[4]; + uint32_t i[4]; + uint32_t q[4]; + } nccTable[2][2]; + + rgba_u palette[2][256]; + + rgba_u ncc_lookup[2][2][256]; + int ncc_dirty[2]; + + thread_t *fifo_thread; + thread_t *render_thread[4]; + event_t *wake_fifo_thread; + event_t *wake_main_thread; + event_t *fifo_not_full_event; + event_t *render_not_full_event[4]; + event_t *wake_render_thread[4]; + + int voodoo_busy; + int render_voodoo_busy[4]; + + int render_threads; + int odd_even_mask; + + int pixel_count[4]; + int texel_count[4]; + int tri_count; + int frame_count; + int pixel_count_old[4]; + int texel_count_old[4]; + int wr_count; + int rd_count; + int tex_count; + + int retrace_count; + int swap_interval; + uint32_t swap_offset; + int swap_pending; + + int bilinear_enabled; + int dithersub_enabled; + + int fb_size; + uint32_t fb_mask; + + int texture_size; + uint32_t texture_mask; + + int dual_tmus; + int type; + + fifo_entry_t fifo[FIFO_SIZE]; + atomic_int fifo_read_idx; + atomic_int fifo_write_idx; + atomic_int cmd_read; + atomic_int cmd_written; + atomic_int cmd_written_fifo; + + voodoo_params_t params_buffer[PARAM_SIZE]; + atomic_int params_read_idx[4]; + atomic_int params_write_idx; + + uint32_t cmdfifo_base; + uint32_t cmdfifo_end; + uint32_t cmdfifo_size; + int cmdfifo_rp; + int cmdfifo_ret_addr; + int cmdfifo_in_sub; + atomic_int cmdfifo_depth_rd; + atomic_int cmdfifo_depth_wr; + atomic_int cmdfifo_enabled; + uint32_t cmdfifo_amin; + uint32_t cmdfifo_amax; + int cmdfifo_holecount; + + atomic_uint cmd_status; + + uint32_t sSetupMode; + vert_t verts[4]; + unsigned int vertex_ages[3]; + unsigned int vertex_next_age; + int num_verticies; + int cull_pingpong; + + int flush; + + int scrfilter; + int scrfilterEnabled; + int scrfilterThreshold; + int scrfilterThresholdOld; + + uint32_t last_write_addr; + + uint32_t fbiPixelsIn; + uint32_t fbiChromaFail; + uint32_t fbiZFuncFail; + uint32_t fbiAFuncFail; + uint32_t fbiPixelsOut; + + uint32_t bltSrcBaseAddr; + uint32_t bltDstBaseAddr; + int bltSrcXYStride; + int bltDstXYStride; + uint32_t bltSrcChromaRange; + uint32_t bltDstChromaRange; + int bltSrcChromaMinR; + int bltSrcChromaMinG; + int bltSrcChromaMinB; + int bltSrcChromaMaxR; + int bltSrcChromaMaxG; + int bltSrcChromaMaxB; + int bltDstChromaMinR; + int bltDstChromaMinG; + int bltDstChromaMinB; + int bltDstChromaMaxR; + int bltDstChromaMaxG; + int bltDstChromaMaxB; + + int bltClipRight; + int bltClipLeft; + int bltClipHighY; + int bltClipLowY; + + int bltSrcX; + int bltSrcY; + int bltDstX; + int bltDstY; + int bltSizeX; + int bltSizeY; + int bltRop[4]; + uint16_t bltColorFg; + uint16_t bltColorBg; + + uint32_t bltCommand; + + uint32_t leftOverlayBuf; + + struct { + int dst_x; + int dst_y; + int cur_x; + int size_x; + int size_y; + int x_dir; + int y_dir; + int dst_stride; + } blt; + + struct { + uint32_t bresError0; + uint32_t bresError1; + uint32_t clip0Min; + uint32_t clip0Max; + uint32_t clip1Min; + uint32_t clip1Max; + uint32_t colorBack; + uint32_t colorFore; + uint32_t command; + uint32_t commandExtra; + uint32_t dstBaseAddr; + uint32_t dstFormat; + uint32_t dstSize; + uint32_t dstXY; + uint32_t lineStipple; + uint32_t lineStyle; + uint32_t rop; + uint32_t srcBaseAddr; + uint32_t srcFormat; + uint32_t srcSize; + uint32_t srcXY; + + uint32_t colorPattern[64]; + + int bres_error_0; + int bres_error_1; + uint32_t colorPattern8[64]; + uint32_t colorPattern16[64]; + uint32_t colorPattern24[64]; + int cur_x; + int cur_y; + uint32_t dstBaseAddr_tiled; + uint32_t dstColorkeyMin; + uint32_t dstColorkeyMax; + int dstSizeX; + int dstSizeY; + int dstX; + int dstY; + int dst_stride; + int patoff_x; + int patoff_y; + uint8_t rops[4]; + uint32_t srcBaseAddr_tiled; + uint32_t srcColorkeyMin; + uint32_t srcColorkeyMax; + int srcSizeX; + int srcSizeY; + int srcX; + int srcY; + int src_stride; + int old_srcX; + + /*Used for handling packed 24bpp host data*/ + int host_data_remainder; + uint32_t old_host_data; + + /*Polyfill coordinates*/ + int lx[2]; + int rx[2]; + int ly[2]; + int ry[2]; + + /*Polyfill state*/ + int error[2]; + int dx[2]; + int dy[2]; + int x_inc[2]; /*y_inc is always 1 for polyfill*/ + int lx_cur; + int rx_cur; + + clip_t clip[2]; + + uint8_t host_data[16384]; + int host_data_count; + int host_data_size_src; + int host_data_size_dest; + int src_stride_src; + int src_stride_dest; + + int src_bpp; + + int line_pix_pos; + int line_bit_pos; + int line_rep_cnt; + int line_bit_mask_size; + } banshee_blt; + + struct { + uint32_t vidOverlayStartCoords; + uint32_t vidOverlayEndScreenCoords; + uint32_t vidOverlayDudx; + uint32_t vidOverlayDudxOffsetSrcWidth; + uint32_t vidOverlayDvdy; + uint32_t vidOverlayDvdyOffset; +#if 0 + uint32_t vidDesktopOverlayStride; +#endif + + int start_x; + int start_y; + int end_x; + int end_y; + int size_x; + int size_y; + int overlay_bytes; + + unsigned int src_y; + } overlay; + + rgbvoodoo_t clutData[33]; + int clutData_dirty; + rgbvoodoo_t clutData256[256]; + uint32_t video_16to32[0x10000]; + + uint8_t dirty_line[2048]; + int dirty_line_low; + int dirty_line_high; + + int fb_write_buffer; + int fb_draw_buffer; + int buffer_cutoff; + + uint32_t tile_base; + uint32_t tile_stride; + int tile_stride_shift; + int tile_x; + int tile_x_real; + + int y_origin_swap; + + int read_time; + int write_time; + int burst_time; + + pc_timer_t wake_timer; + + /* screen filter tables */ + uint8_t thefilter[256][256]; + uint8_t thefilterg[256][256]; + uint8_t thefilterb[256][256]; + uint16_t purpleline[256][3]; + + texture_t texture_cache[2][TEX_CACHE_MAX]; + uint8_t texture_present[2][16384]; + int texture_last_removed; + + uint32_t palette_checksum[2]; + int palette_dirty[2]; + + uint64_t time; + int render_time[4]; + + int force_blit_count; + int can_blit; + mutex_t *force_blit_mutex; + + int use_recompiler; + void *codegen_data; + + struct voodoo_set_t *set; + + uint8_t fifo_thread_run; + uint8_t render_thread_run[4]; + + uint8_t *vram; + uint8_t *changedvram; + + void *priv; + uint8_t monitor_index; } voodoo_t; -typedef struct voodoo_set_t -{ - voodoo_t *voodoos[2]; +typedef struct voodoo_set_t { + voodoo_t *voodoos[2]; - mem_mapping_t snoop_mapping; + mem_mapping_t snoop_mapping; - int nr_cards; + int nr_cards; } voodoo_set_t; - -extern rgba8_t rgb332[0x100], ai44[0x100], rgb565[0x10000], argb1555[0x10000], argb4444[0x10000], ai88[0x10000]; - +extern rgba8_t rgb332[0x100]; +extern rgba8_t ai44[0x100]; +extern rgba8_t rgb565[0x10000]; +extern rgba8_t argb1555[0x10000]; +extern rgba8_t argb4444[0x10000]; +extern rgba8_t ai88[0x10000]; void voodoo_generate_vb_filters(voodoo_t *voodoo, int fcr, int fcg); @@ -527,4 +692,6 @@ void voodoo_recalc(voodoo_t *voodoo); void voodoo_update_ncc(voodoo_t *voodoo, int tmu); void *voodoo_2d3d_card_init(int type); -void voodoo_card_close(voodoo_t *voodoo); +void voodoo_card_close(voodoo_t *voodoo); + +#endif /*VIDEO_VOODOO_COMMON_H*/ diff --git a/src/include/86box/vid_voodoo_display.h b/src/include/86box/vid_voodoo_display.h index 4768a2b62..f046263bf 100644 --- a/src/include/86box/vid_voodoo_display.h +++ b/src/include/86box/vid_voodoo_display.h @@ -1,24 +1,29 @@ /* - * 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. + * 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. + * This file is part of the 86Box distribution. * - * Voodoo Graphics, 2, Banshee, 3 emulation. + * Voodoo Graphics, 2, Banshee, 3 emulation. * * * - * Authors: Sarah Walker, - * leilei + * Authors: Sarah Walker, + * leilei * - * Copyright 2008-2020 Sarah Walker. + * Copyright 2008-2020 Sarah Walker. */ +#ifndef VIDEO_VOODOO_DISPLAY_H +#define VIDEO_VOODOO_DISPLAY_H + void voodoo_update_ncc(voodoo_t *voodoo, int tmu); void voodoo_pixelclock_update(voodoo_t *voodoo); void voodoo_generate_filter_v1(voodoo_t *voodoo); void voodoo_generate_filter_v2(voodoo_t *voodoo); void voodoo_threshold_check(voodoo_t *voodoo); -void voodoo_callback(void *p); +void voodoo_callback(void *priv); + +#endif /*VIDEO_VOODOO_DISPLAY_H*/ diff --git a/src/include/86box/vid_voodoo_dither.h b/src/include/86box/vid_voodoo_dither.h index 6457ac8c6..51ec91f2e 100644 --- a/src/include/86box/vid_voodoo_dither.h +++ b/src/include/86box/vid_voodoo_dither.h @@ -1,5160 +1,5158 @@ /* - * 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. + * 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. + * This file is part of the 86Box distribution. * - * Voodoo Graphics and 2 specific emulation. + * Voodoo Graphics and 2 specific emulation. * * * - * Authors: Sarah Walker, - * leilei + * Authors: Sarah Walker, + * leilei * - * Copyright 2008-2020 Sarah Walker. + * Copyright 2008-2020 Sarah Walker. */ -static const uint8_t dither_rb[256][4][4] = -{ - { - {0, 0, 0, 0}, - {0, 0, 0, 0}, - {0, 0, 0, 0}, - {0, 0, 0, 0}, - }, - { - {0, 0, 0, 0}, - {0, 0, 1, 0}, - {0, 0, 0, 0}, - {1, 0, 0, 0}, - }, - { - {0, 0, 0, 0}, - {1, 0, 1, 0}, - {0, 0, 0, 0}, - {1, 0, 1, 0}, - }, - { - {0, 0, 0, 1}, - {1, 0, 1, 0}, - {0, 1, 0, 0}, - {1, 0, 1, 0}, - }, - { - {0, 1, 0, 1}, - {1, 0, 1, 0}, - {0, 1, 0, 1}, - {1, 0, 1, 0}, - }, - { - {0, 1, 0, 1}, - {1, 0, 1, 1}, - {0, 1, 0, 1}, - {1, 1, 1, 0}, - }, - { - {0, 1, 0, 1}, - {1, 1, 1, 1}, - {0, 1, 0, 1}, - {1, 1, 1, 1}, - }, - { - {0, 1, 1, 1}, - {1, 1, 1, 1}, - {1, 1, 0, 1}, - {1, 1, 1, 1}, - }, - { - {1, 1, 1, 1}, - {1, 1, 1, 1}, - {1, 1, 1, 1}, - {1, 1, 1, 1}, - }, - { - {1, 1, 1, 1}, - {1, 1, 2, 1}, - {1, 1, 1, 1}, - {2, 1, 1, 1}, - }, - { - {1, 1, 1, 1}, - {2, 1, 2, 1}, - {1, 1, 1, 1}, - {2, 1, 2, 1}, - }, - { - {1, 1, 1, 2}, - {2, 1, 2, 1}, - {1, 2, 1, 1}, - {2, 1, 2, 1}, - }, - { - {1, 2, 1, 2}, - {2, 1, 2, 1}, - {1, 2, 1, 2}, - {2, 1, 2, 1}, - }, - { - {1, 2, 1, 2}, - {2, 1, 2, 2}, - {1, 2, 1, 2}, - {2, 2, 2, 1}, - }, - { - {1, 2, 1, 2}, - {2, 2, 2, 2}, - {1, 2, 1, 2}, - {2, 2, 2, 2}, - }, - { - {1, 2, 2, 2}, - {2, 2, 2, 2}, - {2, 2, 1, 2}, - {2, 2, 2, 2}, - }, - { - {1, 2, 2, 2}, - {2, 2, 2, 2}, - {2, 2, 2, 2}, - {2, 2, 2, 2}, - }, - { - {2, 2, 2, 2}, - {2, 2, 2, 2}, - {2, 2, 2, 2}, - {3, 2, 2, 2}, - }, - { - {2, 2, 2, 2}, - {2, 2, 3, 2}, - {2, 2, 2, 2}, - {3, 2, 3, 2}, - }, - { - {2, 2, 2, 2}, - {3, 2, 3, 2}, - {2, 3, 2, 2}, - {3, 2, 3, 2}, - }, - { - {2, 2, 2, 3}, - {3, 2, 3, 2}, - {2, 3, 2, 3}, - {3, 2, 3, 2}, - }, - { - {2, 3, 2, 3}, - {3, 2, 3, 2}, - {2, 3, 2, 3}, - {3, 3, 3, 2}, - }, - { - {2, 3, 2, 3}, - {3, 2, 3, 3}, - {2, 3, 2, 3}, - {3, 3, 3, 3}, - }, - { - {2, 3, 2, 3}, - {3, 3, 3, 3}, - {3, 3, 2, 3}, - {3, 3, 3, 3}, - }, - { - {2, 3, 3, 3}, - {3, 3, 3, 3}, - {3, 3, 3, 3}, - {3, 3, 3, 3}, - }, - { - {3, 3, 3, 3}, - {3, 3, 3, 3}, - {3, 3, 3, 3}, - {4, 3, 3, 3}, - }, - { - {3, 3, 3, 3}, - {3, 3, 4, 3}, - {3, 3, 3, 3}, - {4, 3, 4, 3}, - }, - { - {3, 3, 3, 3}, - {4, 3, 4, 3}, - {3, 4, 3, 3}, - {4, 3, 4, 3}, - }, - { - {3, 3, 3, 4}, - {4, 3, 4, 3}, - {3, 4, 3, 4}, - {4, 3, 4, 3}, - }, - { - {3, 4, 3, 4}, - {4, 3, 4, 3}, - {3, 4, 3, 4}, - {4, 4, 4, 3}, - }, - { - {3, 4, 3, 4}, - {4, 3, 4, 4}, - {3, 4, 3, 4}, - {4, 4, 4, 4}, - }, - { - {3, 4, 3, 4}, - {4, 4, 4, 4}, - {4, 4, 3, 4}, - {4, 4, 4, 4}, - }, - { - {3, 4, 4, 4}, - {4, 4, 4, 4}, - {4, 4, 3, 4}, - {4, 4, 4, 4}, - }, - { - {4, 4, 4, 4}, - {4, 4, 4, 4}, - {4, 4, 4, 4}, - {4, 4, 4, 4}, - }, - { - {4, 4, 4, 4}, - {4, 4, 5, 4}, - {4, 4, 4, 4}, - {5, 4, 4, 4}, - }, - { - {4, 4, 4, 4}, - {5, 4, 5, 4}, - {4, 4, 4, 4}, - {5, 4, 5, 4}, - }, - { - {4, 4, 4, 5}, - {5, 4, 5, 4}, - {4, 5, 4, 4}, - {5, 4, 5, 4}, - }, - { - {4, 5, 4, 5}, - {5, 4, 5, 4}, - {4, 5, 4, 5}, - {5, 4, 5, 4}, - }, - { - {4, 5, 4, 5}, - {5, 4, 5, 5}, - {4, 5, 4, 5}, - {5, 5, 5, 4}, - }, - { - {4, 5, 4, 5}, - {5, 5, 5, 5}, - {4, 5, 4, 5}, - {5, 5, 5, 5}, - }, - { - {4, 5, 5, 5}, - {5, 5, 5, 5}, - {5, 5, 4, 5}, - {5, 5, 5, 5}, - }, - { - {5, 5, 5, 5}, - {5, 5, 5, 5}, - {5, 5, 5, 5}, - {5, 5, 5, 5}, - }, - { - {5, 5, 5, 5}, - {5, 5, 6, 5}, - {5, 5, 5, 5}, - {6, 5, 5, 5}, - }, - { - {5, 5, 5, 5}, - {6, 5, 6, 5}, - {5, 5, 5, 5}, - {6, 5, 6, 5}, - }, - { - {5, 5, 5, 6}, - {6, 5, 6, 5}, - {5, 6, 5, 5}, - {6, 5, 6, 5}, - }, - { - {5, 6, 5, 6}, - {6, 5, 6, 5}, - {5, 6, 5, 6}, - {6, 5, 6, 5}, - }, - { - {5, 6, 5, 6}, - {6, 5, 6, 6}, - {5, 6, 5, 6}, - {6, 6, 6, 5}, - }, - { - {5, 6, 5, 6}, - {6, 6, 6, 6}, - {5, 6, 5, 6}, - {6, 6, 6, 6}, - }, - { - {5, 6, 5, 6}, - {6, 6, 6, 6}, - {6, 6, 5, 6}, - {6, 6, 6, 6}, - }, - { - {5, 6, 6, 6}, - {6, 6, 6, 6}, - {6, 6, 6, 6}, - {6, 6, 6, 6}, - }, - { - {6, 6, 6, 6}, - {6, 6, 6, 6}, - {6, 6, 6, 6}, - {7, 6, 6, 6}, - }, - { - {6, 6, 6, 6}, - {6, 6, 7, 6}, - {6, 6, 6, 6}, - {7, 6, 7, 6}, - }, - { - {6, 6, 6, 6}, - {7, 6, 7, 6}, - {6, 7, 6, 6}, - {7, 6, 7, 6}, - }, - { - {6, 6, 6, 7}, - {7, 6, 7, 6}, - {6, 7, 6, 7}, - {7, 6, 7, 6}, - }, - { - {6, 7, 6, 7}, - {7, 6, 7, 6}, - {6, 7, 6, 7}, - {7, 7, 7, 6}, - }, - { - {6, 7, 6, 7}, - {7, 6, 7, 7}, - {6, 7, 6, 7}, - {7, 7, 7, 7}, - }, - { - {6, 7, 6, 7}, - {7, 7, 7, 7}, - {7, 7, 6, 7}, - {7, 7, 7, 7}, - }, - { - {6, 7, 7, 7}, - {7, 7, 7, 7}, - {7, 7, 7, 7}, - {7, 7, 7, 7}, - }, - { - {7, 7, 7, 7}, - {7, 7, 7, 7}, - {7, 7, 7, 7}, - {8, 7, 7, 7}, - }, - { - {7, 7, 7, 7}, - {7, 7, 8, 7}, - {7, 7, 7, 7}, - {8, 7, 8, 7}, - }, - { - {7, 7, 7, 7}, - {8, 7, 8, 7}, - {7, 8, 7, 7}, - {8, 7, 8, 7}, - }, - { - {7, 7, 7, 8}, - {8, 7, 8, 7}, - {7, 8, 7, 8}, - {8, 7, 8, 7}, - }, - { - {7, 8, 7, 8}, - {8, 7, 8, 7}, - {7, 8, 7, 8}, - {8, 8, 8, 7}, - }, - { - {7, 8, 7, 8}, - {8, 7, 8, 8}, - {7, 8, 7, 8}, - {8, 8, 8, 8}, - }, - { - {7, 8, 7, 8}, - {8, 8, 8, 8}, - {7, 8, 7, 8}, - {8, 8, 8, 8}, - }, - { - {7, 8, 8, 8}, - {8, 8, 8, 8}, - {8, 8, 7, 8}, - {8, 8, 8, 8}, - }, - { - {8, 8, 8, 8}, - {8, 8, 8, 8}, - {8, 8, 8, 8}, - {8, 8, 8, 8}, - }, - { - {8, 8, 8, 8}, - {8, 8, 9, 8}, - {8, 8, 8, 8}, - {9, 8, 8, 8}, - }, - { - {8, 8, 8, 8}, - {9, 8, 9, 8}, - {8, 8, 8, 8}, - {9, 8, 9, 8}, - }, - { - {8, 8, 8, 9}, - {9, 8, 9, 8}, - {8, 9, 8, 8}, - {9, 8, 9, 8}, - }, - { - {8, 9, 8, 9}, - {9, 8, 9, 8}, - {8, 9, 8, 9}, - {9, 8, 9, 8}, - }, - { - {8, 9, 8, 9}, - {9, 8, 9, 9}, - {8, 9, 8, 9}, - {9, 9, 9, 8}, - }, - { - {8, 9, 8, 9}, - {9, 9, 9, 9}, - {8, 9, 8, 9}, - {9, 9, 9, 9}, - }, - { - {8, 9, 9, 9}, - {9, 9, 9, 9}, - {9, 9, 8, 9}, - {9, 9, 9, 9}, - }, - { - {9, 9, 9, 9}, - {9, 9, 9, 9}, - {9, 9, 9, 9}, - {9, 9, 9, 9}, - }, - { - {9, 9, 9, 9}, - {9, 9, 10, 9}, - {9, 9, 9, 9}, - {10, 9, 9, 9}, - }, - { - {9, 9, 9, 9}, - {10, 9, 10, 9}, - {9, 9, 9, 9}, - {10, 9, 10, 9}, - }, - { - {9, 9, 9, 10}, - {10, 9, 10, 9}, - {9, 10, 9, 9}, - {10, 9, 10, 9}, - }, - { - {9, 10, 9, 10}, - {10, 9, 10, 9}, - {9, 10, 9, 10}, - {10, 9, 10, 9}, - }, - { - {9, 10, 9, 10}, - {10, 9, 10, 10}, - {9, 10, 9, 10}, - {10, 10, 10, 9}, - }, - { - {9, 10, 9, 10}, - {10, 9, 10, 10}, - {9, 10, 9, 10}, - {10, 10, 10, 10}, - }, - { - {9, 10, 9, 10}, - {10, 10, 10, 10}, - {10, 10, 9, 10}, - {10, 10, 10, 10}, - }, - { - {9, 10, 10, 10}, - {10, 10, 10, 10}, - {10, 10, 10, 10}, - {10, 10, 10, 10}, - }, - { - {10, 10, 10, 10}, - {10, 10, 10, 10}, - {10, 10, 10, 10}, - {11, 10, 10, 10}, - }, - { - {10, 10, 10, 10}, - {10, 10, 11, 10}, - {10, 10, 10, 10}, - {11, 10, 11, 10}, - }, - { - {10, 10, 10, 10}, - {11, 10, 11, 10}, - {10, 11, 10, 10}, - {11, 10, 11, 10}, - }, - { - {10, 10, 10, 11}, - {11, 10, 11, 10}, - {10, 11, 10, 11}, - {11, 10, 11, 10}, - }, - { - {10, 11, 10, 11}, - {11, 10, 11, 10}, - {10, 11, 10, 11}, - {11, 11, 11, 10}, - }, - { - {10, 11, 10, 11}, - {11, 10, 11, 11}, - {10, 11, 10, 11}, - {11, 11, 11, 11}, - }, - { - {10, 11, 10, 11}, - {11, 11, 11, 11}, - {11, 11, 10, 11}, - {11, 11, 11, 11}, - }, - { - {10, 11, 11, 11}, - {11, 11, 11, 11}, - {11, 11, 11, 11}, - {11, 11, 11, 11}, - }, - { - {11, 11, 11, 11}, - {11, 11, 11, 11}, - {11, 11, 11, 11}, - {12, 11, 11, 11}, - }, - { - {11, 11, 11, 11}, - {11, 11, 12, 11}, - {11, 11, 11, 11}, - {12, 11, 12, 11}, - }, - { - {11, 11, 11, 11}, - {12, 11, 12, 11}, - {11, 12, 11, 11}, - {12, 11, 12, 11}, - }, - { - {11, 11, 11, 12}, - {12, 11, 12, 11}, - {11, 12, 11, 12}, - {12, 11, 12, 11}, - }, - { - {11, 12, 11, 12}, - {12, 11, 12, 11}, - {11, 12, 11, 12}, - {12, 12, 12, 11}, - }, - { - {11, 12, 11, 12}, - {12, 11, 12, 12}, - {11, 12, 11, 12}, - {12, 12, 12, 11}, - }, - { - {11, 12, 11, 12}, - {12, 12, 12, 12}, - {11, 12, 11, 12}, - {12, 12, 12, 12}, - }, - { - {11, 12, 12, 12}, - {12, 12, 12, 12}, - {12, 12, 11, 12}, - {12, 12, 12, 12}, - }, - { - {12, 12, 12, 12}, - {12, 12, 12, 12}, - {12, 12, 12, 12}, - {12, 12, 12, 12}, - }, - { - {12, 12, 12, 12}, - {12, 12, 13, 12}, - {12, 12, 12, 12}, - {13, 12, 12, 12}, - }, - { - {12, 12, 12, 12}, - {13, 12, 13, 12}, - {12, 12, 12, 12}, - {13, 12, 13, 12}, - }, - { - {12, 12, 12, 13}, - {13, 12, 13, 12}, - {12, 13, 12, 12}, - {13, 12, 13, 12}, - }, - { - {12, 13, 12, 13}, - {13, 12, 13, 12}, - {12, 13, 12, 13}, - {13, 12, 13, 12}, - }, - { - {12, 13, 12, 13}, - {13, 12, 13, 13}, - {12, 13, 12, 13}, - {13, 13, 13, 12}, - }, - { - {12, 13, 12, 13}, - {13, 13, 13, 13}, - {12, 13, 12, 13}, - {13, 13, 13, 13}, - }, - { - {12, 13, 13, 13}, - {13, 13, 13, 13}, - {13, 13, 12, 13}, - {13, 13, 13, 13}, - }, - { - {13, 13, 13, 13}, - {13, 13, 13, 13}, - {13, 13, 13, 13}, - {13, 13, 13, 13}, - }, - { - {13, 13, 13, 13}, - {13, 13, 14, 13}, - {13, 13, 13, 13}, - {14, 13, 13, 13}, - }, - { - {13, 13, 13, 13}, - {14, 13, 14, 13}, - {13, 13, 13, 13}, - {14, 13, 14, 13}, - }, - { - {13, 13, 13, 14}, - {14, 13, 14, 13}, - {13, 14, 13, 13}, - {14, 13, 14, 13}, - }, - { - {13, 14, 13, 14}, - {14, 13, 14, 13}, - {13, 14, 13, 14}, - {14, 13, 14, 13}, - }, - { - {13, 14, 13, 14}, - {14, 13, 14, 13}, - {13, 14, 13, 14}, - {14, 14, 14, 13}, - }, - { - {13, 14, 13, 14}, - {14, 13, 14, 14}, - {13, 14, 13, 14}, - {14, 14, 14, 14}, - }, - { - {13, 14, 13, 14}, - {14, 14, 14, 14}, - {14, 14, 13, 14}, - {14, 14, 14, 14}, - }, - { - {13, 14, 14, 14}, - {14, 14, 14, 14}, - {14, 14, 14, 14}, - {14, 14, 14, 14}, - }, - { - {14, 14, 14, 14}, - {14, 14, 14, 14}, - {14, 14, 14, 14}, - {15, 14, 14, 14}, - }, - { - {14, 14, 14, 14}, - {14, 14, 15, 14}, - {14, 14, 14, 14}, - {15, 14, 15, 14}, - }, - { - {14, 14, 14, 14}, - {15, 14, 15, 14}, - {14, 15, 14, 14}, - {15, 14, 15, 14}, - }, - { - {14, 14, 14, 15}, - {15, 14, 15, 14}, - {14, 15, 14, 15}, - {15, 14, 15, 14}, - }, - { - {14, 15, 14, 15}, - {15, 14, 15, 14}, - {14, 15, 14, 15}, - {15, 15, 15, 14}, - }, - { - {14, 15, 14, 15}, - {15, 14, 15, 15}, - {14, 15, 14, 15}, - {15, 15, 15, 15}, - }, - { - {14, 15, 14, 15}, - {15, 15, 15, 15}, - {15, 15, 14, 15}, - {15, 15, 15, 15}, - }, - { - {14, 15, 15, 15}, - {15, 15, 15, 15}, - {15, 15, 15, 15}, - {15, 15, 15, 15}, - }, - { - {15, 15, 15, 15}, - {15, 15, 15, 15}, - {15, 15, 15, 15}, - {16, 15, 15, 15}, - }, - { - {15, 15, 15, 15}, - {15, 15, 16, 15}, - {15, 15, 15, 15}, - {16, 15, 16, 15}, - }, - { - {15, 15, 15, 15}, - {16, 15, 16, 15}, - {15, 16, 15, 15}, - {16, 15, 16, 15}, - }, - { - {15, 15, 15, 16}, - {16, 15, 16, 15}, - {15, 16, 15, 16}, - {16, 15, 16, 15}, - }, - { - {15, 16, 15, 16}, - {16, 15, 16, 15}, - {15, 16, 15, 16}, - {16, 16, 16, 15}, - }, - { - {15, 16, 15, 16}, - {16, 15, 16, 16}, - {15, 16, 15, 16}, - {16, 16, 16, 16}, - }, - { - {15, 16, 15, 16}, - {16, 16, 16, 16}, - {16, 16, 15, 16}, - {16, 16, 16, 16}, - }, - { - {15, 16, 16, 16}, - {16, 16, 16, 16}, - {16, 16, 16, 16}, - {16, 16, 16, 16}, - }, - { - {16, 16, 16, 16}, - {16, 16, 16, 16}, - {16, 16, 16, 16}, - {17, 16, 16, 16}, - }, - { - {16, 16, 16, 16}, - {16, 16, 17, 16}, - {16, 16, 16, 16}, - {17, 16, 17, 16}, - }, - { - {16, 16, 16, 16}, - {17, 16, 17, 16}, - {16, 17, 16, 16}, - {17, 16, 17, 16}, - }, - { - {16, 16, 16, 17}, - {17, 16, 17, 16}, - {16, 17, 16, 17}, - {17, 16, 17, 16}, - }, - { - {16, 17, 16, 17}, - {17, 16, 17, 16}, - {16, 17, 16, 17}, - {17, 17, 17, 16}, - }, - { - {16, 17, 16, 17}, - {17, 16, 17, 17}, - {16, 17, 16, 17}, - {17, 17, 17, 17}, - }, - { - {16, 17, 16, 17}, - {17, 17, 17, 17}, - {17, 17, 16, 17}, - {17, 17, 17, 17}, - }, - { - {16, 17, 17, 17}, - {17, 17, 17, 17}, - {17, 17, 17, 17}, - {17, 17, 17, 17}, - }, - { - {17, 17, 17, 17}, - {17, 17, 17, 17}, - {17, 17, 17, 17}, - {18, 17, 17, 17}, - }, - { - {17, 17, 17, 17}, - {17, 17, 18, 17}, - {17, 17, 17, 17}, - {18, 17, 18, 17}, - }, - { - {17, 17, 17, 17}, - {18, 17, 18, 17}, - {17, 18, 17, 17}, - {18, 17, 18, 17}, - }, - { - {17, 17, 17, 18}, - {18, 17, 18, 17}, - {17, 18, 17, 18}, - {18, 17, 18, 17}, - }, - { - {17, 18, 17, 18}, - {18, 17, 18, 17}, - {17, 18, 17, 18}, - {18, 17, 18, 17}, - }, - { - {17, 18, 17, 18}, - {18, 17, 18, 18}, - {17, 18, 17, 18}, - {18, 18, 18, 17}, - }, - { - {17, 18, 17, 18}, - {18, 18, 18, 18}, - {17, 18, 17, 18}, - {18, 18, 18, 18}, - }, - { - {17, 18, 18, 18}, - {18, 18, 18, 18}, - {18, 18, 17, 18}, - {18, 18, 18, 18}, - }, - { - {18, 18, 18, 18}, - {18, 18, 18, 18}, - {18, 18, 18, 18}, - {18, 18, 18, 18}, - }, - { - {18, 18, 18, 18}, - {18, 18, 19, 18}, - {18, 18, 18, 18}, - {19, 18, 18, 18}, - }, - { - {18, 18, 18, 18}, - {19, 18, 19, 18}, - {18, 18, 18, 18}, - {19, 18, 19, 18}, - }, - { - {18, 18, 18, 19}, - {19, 18, 19, 18}, - {18, 19, 18, 18}, - {19, 18, 19, 18}, - }, - { - {18, 19, 18, 19}, - {19, 18, 19, 18}, - {18, 19, 18, 19}, - {19, 18, 19, 18}, - }, - { - {18, 19, 18, 19}, - {19, 18, 19, 19}, - {18, 19, 18, 19}, - {19, 19, 19, 18}, - }, - { - {18, 19, 18, 19}, - {19, 19, 19, 19}, - {18, 19, 18, 19}, - {19, 19, 19, 19}, - }, - { - {18, 19, 19, 19}, - {19, 19, 19, 19}, - {19, 19, 18, 19}, - {19, 19, 19, 19}, - }, - { - {19, 19, 19, 19}, - {19, 19, 19, 19}, - {19, 19, 19, 19}, - {19, 19, 19, 19}, - }, - { - {19, 19, 19, 19}, - {19, 19, 20, 19}, - {19, 19, 19, 19}, - {20, 19, 19, 19}, - }, - { - {19, 19, 19, 19}, - {20, 19, 20, 19}, - {19, 19, 19, 19}, - {20, 19, 20, 19}, - }, - { - {19, 19, 19, 20}, - {20, 19, 20, 19}, - {19, 20, 19, 19}, - {20, 19, 20, 19}, - }, - { - {19, 19, 19, 20}, - {20, 19, 20, 19}, - {19, 20, 19, 20}, - {20, 19, 20, 19}, - }, - { - {19, 20, 19, 20}, - {20, 19, 20, 19}, - {19, 20, 19, 20}, - {20, 20, 20, 19}, - }, - { - {19, 20, 19, 20}, - {20, 19, 20, 20}, - {19, 20, 19, 20}, - {20, 20, 20, 20}, - }, - { - {19, 20, 19, 20}, - {20, 20, 20, 20}, - {20, 20, 19, 20}, - {20, 20, 20, 20}, - }, - { - {19, 20, 20, 20}, - {20, 20, 20, 20}, - {20, 20, 20, 20}, - {20, 20, 20, 20}, - }, - { - {20, 20, 20, 20}, - {20, 20, 20, 20}, - {20, 20, 20, 20}, - {21, 20, 20, 20}, - }, - { - {20, 20, 20, 20}, - {20, 20, 21, 20}, - {20, 20, 20, 20}, - {21, 20, 21, 20}, - }, - { - {20, 20, 20, 20}, - {21, 20, 21, 20}, - {20, 21, 20, 20}, - {21, 20, 21, 20}, - }, - { - {20, 20, 20, 21}, - {21, 20, 21, 20}, - {20, 21, 20, 21}, - {21, 20, 21, 20}, - }, - { - {20, 21, 20, 21}, - {21, 20, 21, 20}, - {20, 21, 20, 21}, - {21, 21, 21, 20}, - }, - { - {20, 21, 20, 21}, - {21, 20, 21, 21}, - {20, 21, 20, 21}, - {21, 21, 21, 21}, - }, - { - {20, 21, 20, 21}, - {21, 21, 21, 21}, - {21, 21, 20, 21}, - {21, 21, 21, 21}, - }, - { - {20, 21, 21, 21}, - {21, 21, 21, 21}, - {21, 21, 21, 21}, - {21, 21, 21, 21}, - }, - { - {21, 21, 21, 21}, - {21, 21, 21, 21}, - {21, 21, 21, 21}, - {22, 21, 21, 21}, - }, - { - {21, 21, 21, 21}, - {21, 21, 22, 21}, - {21, 21, 21, 21}, - {22, 21, 22, 21}, - }, - { - {21, 21, 21, 21}, - {22, 21, 22, 21}, - {21, 22, 21, 21}, - {22, 21, 22, 21}, - }, - { - {21, 21, 21, 22}, - {22, 21, 22, 21}, - {21, 22, 21, 21}, - {22, 21, 22, 21}, - }, - { - {21, 22, 21, 22}, - {22, 21, 22, 21}, - {21, 22, 21, 22}, - {22, 21, 22, 21}, - }, - { - {21, 22, 21, 22}, - {22, 21, 22, 22}, - {21, 22, 21, 22}, - {22, 22, 22, 21}, - }, - { - {21, 22, 21, 22}, - {22, 22, 22, 22}, - {21, 22, 21, 22}, - {22, 22, 22, 22}, - }, - { - {21, 22, 22, 22}, - {22, 22, 22, 22}, - {22, 22, 21, 22}, - {22, 22, 22, 22}, - }, - { - {22, 22, 22, 22}, - {22, 22, 22, 22}, - {22, 22, 22, 22}, - {22, 22, 22, 22}, - }, - { - {22, 22, 22, 22}, - {22, 22, 23, 22}, - {22, 22, 22, 22}, - {23, 22, 22, 22}, - }, - { - {22, 22, 22, 22}, - {23, 22, 23, 22}, - {22, 22, 22, 22}, - {23, 22, 23, 22}, - }, - { - {22, 22, 22, 23}, - {23, 22, 23, 22}, - {22, 23, 22, 22}, - {23, 22, 23, 22}, - }, - { - {22, 23, 22, 23}, - {23, 22, 23, 22}, - {22, 23, 22, 23}, - {23, 22, 23, 22}, - }, - { - {22, 23, 22, 23}, - {23, 22, 23, 23}, - {22, 23, 22, 23}, - {23, 23, 23, 22}, - }, - { - {22, 23, 22, 23}, - {23, 23, 23, 23}, - {22, 23, 22, 23}, - {23, 23, 23, 23}, - }, - { - {22, 23, 23, 23}, - {23, 23, 23, 23}, - {23, 23, 22, 23}, - {23, 23, 23, 23}, - }, - { - {23, 23, 23, 23}, - {23, 23, 23, 23}, - {23, 23, 23, 23}, - {23, 23, 23, 23}, - }, - { - {23, 23, 23, 23}, - {23, 23, 24, 23}, - {23, 23, 23, 23}, - {24, 23, 23, 23}, - }, - { - {23, 23, 23, 23}, - {24, 23, 24, 23}, - {23, 23, 23, 23}, - {24, 23, 24, 23}, - }, - { - {23, 23, 23, 23}, - {24, 23, 24, 23}, - {23, 24, 23, 23}, - {24, 23, 24, 23}, - }, - { - {23, 23, 23, 24}, - {24, 23, 24, 23}, - {23, 24, 23, 24}, - {24, 23, 24, 23}, - }, - { - {23, 24, 23, 24}, - {24, 23, 24, 23}, - {23, 24, 23, 24}, - {24, 24, 24, 23}, - }, - { - {23, 24, 23, 24}, - {24, 23, 24, 24}, - {23, 24, 23, 24}, - {24, 24, 24, 24}, - }, - { - {23, 24, 23, 24}, - {24, 24, 24, 24}, - {24, 24, 23, 24}, - {24, 24, 24, 24}, - }, - { - {23, 24, 24, 24}, - {24, 24, 24, 24}, - {24, 24, 24, 24}, - {24, 24, 24, 24}, - }, - { - {24, 24, 24, 24}, - {24, 24, 24, 24}, - {24, 24, 24, 24}, - {25, 24, 24, 24}, - }, - { - {24, 24, 24, 24}, - {24, 24, 25, 24}, - {24, 24, 24, 24}, - {25, 24, 25, 24}, - }, - { - {24, 24, 24, 24}, - {25, 24, 25, 24}, - {24, 25, 24, 24}, - {25, 24, 25, 24}, - }, - { - {24, 24, 24, 25}, - {25, 24, 25, 24}, - {24, 25, 24, 25}, - {25, 24, 25, 24}, - }, - { - {24, 25, 24, 25}, - {25, 24, 25, 24}, - {24, 25, 24, 25}, - {25, 25, 25, 24}, - }, - { - {24, 25, 24, 25}, - {25, 24, 25, 25}, - {24, 25, 24, 25}, - {25, 25, 25, 25}, - }, - { - {24, 25, 24, 25}, - {25, 25, 25, 25}, - {25, 25, 24, 25}, - {25, 25, 25, 25}, - }, - { - {24, 25, 25, 25}, - {25, 25, 25, 25}, - {25, 25, 25, 25}, - {25, 25, 25, 25}, - }, - { - {25, 25, 25, 25}, - {25, 25, 25, 25}, - {25, 25, 25, 25}, - {26, 25, 25, 25}, - }, - { - {25, 25, 25, 25}, - {25, 25, 26, 25}, - {25, 25, 25, 25}, - {26, 25, 26, 25}, - }, - { - {25, 25, 25, 25}, - {26, 25, 26, 25}, - {25, 25, 25, 25}, - {26, 25, 26, 25}, - }, - { - {25, 25, 25, 26}, - {26, 25, 26, 25}, - {25, 26, 25, 25}, - {26, 25, 26, 25}, - }, - { - {25, 26, 25, 26}, - {26, 25, 26, 25}, - {25, 26, 25, 26}, - {26, 25, 26, 25}, - }, - { - {25, 26, 25, 26}, - {26, 25, 26, 26}, - {25, 26, 25, 26}, - {26, 26, 26, 25}, - }, - { - {25, 26, 25, 26}, - {26, 26, 26, 26}, - {25, 26, 25, 26}, - {26, 26, 26, 26}, - }, - { - {25, 26, 26, 26}, - {26, 26, 26, 26}, - {26, 26, 25, 26}, - {26, 26, 26, 26}, - }, - { - {26, 26, 26, 26}, - {26, 26, 26, 26}, - {26, 26, 26, 26}, - {26, 26, 26, 26}, - }, - { - {26, 26, 26, 26}, - {26, 26, 27, 26}, - {26, 26, 26, 26}, - {27, 26, 26, 26}, - }, - { - {26, 26, 26, 26}, - {27, 26, 27, 26}, - {26, 26, 26, 26}, - {27, 26, 27, 26}, - }, - { - {26, 26, 26, 27}, - {27, 26, 27, 26}, - {26, 27, 26, 26}, - {27, 26, 27, 26}, - }, - { - {26, 27, 26, 27}, - {27, 26, 27, 26}, - {26, 27, 26, 27}, - {27, 26, 27, 26}, - }, - { - {26, 27, 26, 27}, - {27, 26, 27, 27}, - {26, 27, 26, 27}, - {27, 27, 27, 26}, - }, - { - {26, 27, 26, 27}, - {27, 27, 27, 27}, - {26, 27, 26, 27}, - {27, 27, 27, 27}, - }, - { - {26, 27, 27, 27}, - {27, 27, 27, 27}, - {27, 27, 26, 27}, - {27, 27, 27, 27}, - }, - { - {27, 27, 27, 27}, - {27, 27, 27, 27}, - {27, 27, 27, 27}, - {27, 27, 27, 27}, - }, - { - {27, 27, 27, 27}, - {27, 27, 28, 27}, - {27, 27, 27, 27}, - {28, 27, 27, 27}, - }, - { - {27, 27, 27, 27}, - {27, 27, 28, 27}, - {27, 27, 27, 27}, - {28, 27, 28, 27}, - }, - { - {27, 27, 27, 27}, - {28, 27, 28, 27}, - {27, 28, 27, 27}, - {28, 27, 28, 27}, - }, - { - {27, 27, 27, 28}, - {28, 27, 28, 27}, - {27, 28, 27, 28}, - {28, 27, 28, 27}, - }, - { - {27, 28, 27, 28}, - {28, 27, 28, 27}, - {27, 28, 27, 28}, - {28, 28, 28, 27}, - }, - { - {27, 28, 27, 28}, - {28, 27, 28, 28}, - {27, 28, 27, 28}, - {28, 28, 28, 28}, - }, - { - {27, 28, 27, 28}, - {28, 28, 28, 28}, - {28, 28, 27, 28}, - {28, 28, 28, 28}, - }, - { - {27, 28, 28, 28}, - {28, 28, 28, 28}, - {28, 28, 28, 28}, - {28, 28, 28, 28}, - }, - { - {28, 28, 28, 28}, - {28, 28, 28, 28}, - {28, 28, 28, 28}, - {29, 28, 28, 28}, - }, - { - {28, 28, 28, 28}, - {28, 28, 29, 28}, - {28, 28, 28, 28}, - {29, 28, 29, 28}, - }, - { - {28, 28, 28, 28}, - {29, 28, 29, 28}, - {28, 29, 28, 28}, - {29, 28, 29, 28}, - }, - { - {28, 28, 28, 29}, - {29, 28, 29, 28}, - {28, 29, 28, 29}, - {29, 28, 29, 28}, - }, - { - {28, 29, 28, 29}, - {29, 28, 29, 28}, - {28, 29, 28, 29}, - {29, 29, 29, 28}, - }, - { - {28, 29, 28, 29}, - {29, 28, 29, 29}, - {28, 29, 28, 29}, - {29, 29, 29, 29}, - }, - { - {28, 29, 28, 29}, - {29, 29, 29, 29}, - {29, 29, 28, 29}, - {29, 29, 29, 29}, - }, - { - {28, 29, 29, 29}, - {29, 29, 29, 29}, - {29, 29, 29, 29}, - {29, 29, 29, 29}, - }, - { - {29, 29, 29, 29}, - {29, 29, 29, 29}, - {29, 29, 29, 29}, - {30, 29, 29, 29}, - }, - { - {29, 29, 29, 29}, - {29, 29, 30, 29}, - {29, 29, 29, 29}, - {30, 29, 29, 29}, - }, - { - {29, 29, 29, 29}, - {30, 29, 30, 29}, - {29, 29, 29, 29}, - {30, 29, 30, 29}, - }, - { - {29, 29, 29, 30}, - {30, 29, 30, 29}, - {29, 30, 29, 29}, - {30, 29, 30, 29}, - }, - { - {29, 30, 29, 30}, - {30, 29, 30, 29}, - {29, 30, 29, 30}, - {30, 29, 30, 29}, - }, - { - {29, 30, 29, 30}, - {30, 29, 30, 30}, - {29, 30, 29, 30}, - {30, 30, 30, 29}, - }, - { - {29, 30, 29, 30}, - {30, 30, 30, 30}, - {29, 30, 29, 30}, - {30, 30, 30, 30}, - }, - { - {29, 30, 30, 30}, - {30, 30, 30, 30}, - {30, 30, 29, 30}, - {30, 30, 30, 30}, - }, - { - {30, 30, 30, 30}, - {30, 30, 30, 30}, - {30, 30, 30, 30}, - {30, 30, 30, 30}, - }, - { - {30, 30, 30, 30}, - {30, 30, 31, 30}, - {30, 30, 30, 30}, - {31, 30, 30, 30}, - }, - { - {30, 30, 30, 30}, - {31, 30, 31, 30}, - {30, 30, 30, 30}, - {31, 30, 31, 30}, - }, - { - {30, 30, 30, 31}, - {31, 30, 31, 30}, - {30, 31, 30, 30}, - {31, 30, 31, 30}, - }, - { - {30, 31, 30, 31}, - {31, 30, 31, 30}, - {30, 31, 30, 31}, - {31, 30, 31, 30}, - }, - { - {30, 31, 30, 31}, - {31, 30, 31, 31}, - {30, 31, 30, 31}, - {31, 31, 31, 30}, - }, - { - {30, 31, 30, 31}, - {31, 31, 31, 31}, - {30, 31, 30, 31}, - {31, 31, 31, 31}, - }, - { - {30, 31, 31, 31}, - {31, 31, 31, 31}, - {31, 31, 30, 31}, - {31, 31, 31, 31}, - }, - { - {31, 31, 31, 31}, - {31, 31, 31, 31}, - {31, 31, 31, 31}, - {31, 31, 31, 31}, - }, +#ifndef VIDEO_VOODOO_DITHER_H +#define VIDEO_VOODOO_DITHER_H + +static const uint8_t dither_rb[256][4][4] = { + { + {0, 0, 0, 0}, + {0, 0, 0, 0}, + {0, 0, 0, 0}, + {0, 0, 0, 0}, + }, + { + {0, 0, 0, 0}, + {0, 0, 1, 0}, + {0, 0, 0, 0}, + {1, 0, 0, 0}, + }, + { + {0, 0, 0, 0}, + {1, 0, 1, 0}, + {0, 0, 0, 0}, + {1, 0, 1, 0}, + }, + { + {0, 0, 0, 1}, + {1, 0, 1, 0}, + {0, 1, 0, 0}, + {1, 0, 1, 0}, + }, + { + {0, 1, 0, 1}, + {1, 0, 1, 0}, + {0, 1, 0, 1}, + {1, 0, 1, 0}, + }, + { + {0, 1, 0, 1}, + {1, 0, 1, 1}, + {0, 1, 0, 1}, + {1, 1, 1, 0}, + }, + { + {0, 1, 0, 1}, + {1, 1, 1, 1}, + {0, 1, 0, 1}, + {1, 1, 1, 1}, + }, + { + {0, 1, 1, 1}, + {1, 1, 1, 1}, + {1, 1, 0, 1}, + {1, 1, 1, 1}, + }, + { + {1, 1, 1, 1}, + {1, 1, 1, 1}, + {1, 1, 1, 1}, + {1, 1, 1, 1}, + }, + { + {1, 1, 1, 1}, + {1, 1, 2, 1}, + {1, 1, 1, 1}, + {2, 1, 1, 1}, + }, + { + {1, 1, 1, 1}, + {2, 1, 2, 1}, + {1, 1, 1, 1}, + {2, 1, 2, 1}, + }, + { + {1, 1, 1, 2}, + {2, 1, 2, 1}, + {1, 2, 1, 1}, + {2, 1, 2, 1}, + }, + { + {1, 2, 1, 2}, + {2, 1, 2, 1}, + {1, 2, 1, 2}, + {2, 1, 2, 1}, + }, + { + {1, 2, 1, 2}, + {2, 1, 2, 2}, + {1, 2, 1, 2}, + {2, 2, 2, 1}, + }, + { + {1, 2, 1, 2}, + {2, 2, 2, 2}, + {1, 2, 1, 2}, + {2, 2, 2, 2}, + }, + { + {1, 2, 2, 2}, + {2, 2, 2, 2}, + {2, 2, 1, 2}, + {2, 2, 2, 2}, + }, + { + {1, 2, 2, 2}, + {2, 2, 2, 2}, + {2, 2, 2, 2}, + {2, 2, 2, 2}, + }, + { + {2, 2, 2, 2}, + {2, 2, 2, 2}, + {2, 2, 2, 2}, + {3, 2, 2, 2}, + }, + { + {2, 2, 2, 2}, + {2, 2, 3, 2}, + {2, 2, 2, 2}, + {3, 2, 3, 2}, + }, + { + {2, 2, 2, 2}, + {3, 2, 3, 2}, + {2, 3, 2, 2}, + {3, 2, 3, 2}, + }, + { + {2, 2, 2, 3}, + {3, 2, 3, 2}, + {2, 3, 2, 3}, + {3, 2, 3, 2}, + }, + { + {2, 3, 2, 3}, + {3, 2, 3, 2}, + {2, 3, 2, 3}, + {3, 3, 3, 2}, + }, + { + {2, 3, 2, 3}, + {3, 2, 3, 3}, + {2, 3, 2, 3}, + {3, 3, 3, 3}, + }, + { + {2, 3, 2, 3}, + {3, 3, 3, 3}, + {3, 3, 2, 3}, + {3, 3, 3, 3}, + }, + { + {2, 3, 3, 3}, + {3, 3, 3, 3}, + {3, 3, 3, 3}, + {3, 3, 3, 3}, + }, + { + {3, 3, 3, 3}, + {3, 3, 3, 3}, + {3, 3, 3, 3}, + {4, 3, 3, 3}, + }, + { + {3, 3, 3, 3}, + {3, 3, 4, 3}, + {3, 3, 3, 3}, + {4, 3, 4, 3}, + }, + { + {3, 3, 3, 3}, + {4, 3, 4, 3}, + {3, 4, 3, 3}, + {4, 3, 4, 3}, + }, + { + {3, 3, 3, 4}, + {4, 3, 4, 3}, + {3, 4, 3, 4}, + {4, 3, 4, 3}, + }, + { + {3, 4, 3, 4}, + {4, 3, 4, 3}, + {3, 4, 3, 4}, + {4, 4, 4, 3}, + }, + { + {3, 4, 3, 4}, + {4, 3, 4, 4}, + {3, 4, 3, 4}, + {4, 4, 4, 4}, + }, + { + {3, 4, 3, 4}, + {4, 4, 4, 4}, + {4, 4, 3, 4}, + {4, 4, 4, 4}, + }, + { + {3, 4, 4, 4}, + {4, 4, 4, 4}, + {4, 4, 3, 4}, + {4, 4, 4, 4}, + }, + { + {4, 4, 4, 4}, + {4, 4, 4, 4}, + {4, 4, 4, 4}, + {4, 4, 4, 4}, + }, + { + {4, 4, 4, 4}, + {4, 4, 5, 4}, + {4, 4, 4, 4}, + {5, 4, 4, 4}, + }, + { + {4, 4, 4, 4}, + {5, 4, 5, 4}, + {4, 4, 4, 4}, + {5, 4, 5, 4}, + }, + { + {4, 4, 4, 5}, + {5, 4, 5, 4}, + {4, 5, 4, 4}, + {5, 4, 5, 4}, + }, + { + {4, 5, 4, 5}, + {5, 4, 5, 4}, + {4, 5, 4, 5}, + {5, 4, 5, 4}, + }, + { + {4, 5, 4, 5}, + {5, 4, 5, 5}, + {4, 5, 4, 5}, + {5, 5, 5, 4}, + }, + { + {4, 5, 4, 5}, + {5, 5, 5, 5}, + {4, 5, 4, 5}, + {5, 5, 5, 5}, + }, + { + {4, 5, 5, 5}, + {5, 5, 5, 5}, + {5, 5, 4, 5}, + {5, 5, 5, 5}, + }, + { + {5, 5, 5, 5}, + {5, 5, 5, 5}, + {5, 5, 5, 5}, + {5, 5, 5, 5}, + }, + { + {5, 5, 5, 5}, + {5, 5, 6, 5}, + {5, 5, 5, 5}, + {6, 5, 5, 5}, + }, + { + {5, 5, 5, 5}, + {6, 5, 6, 5}, + {5, 5, 5, 5}, + {6, 5, 6, 5}, + }, + { + {5, 5, 5, 6}, + {6, 5, 6, 5}, + {5, 6, 5, 5}, + {6, 5, 6, 5}, + }, + { + {5, 6, 5, 6}, + {6, 5, 6, 5}, + {5, 6, 5, 6}, + {6, 5, 6, 5}, + }, + { + {5, 6, 5, 6}, + {6, 5, 6, 6}, + {5, 6, 5, 6}, + {6, 6, 6, 5}, + }, + { + {5, 6, 5, 6}, + {6, 6, 6, 6}, + {5, 6, 5, 6}, + {6, 6, 6, 6}, + }, + { + {5, 6, 5, 6}, + {6, 6, 6, 6}, + {6, 6, 5, 6}, + {6, 6, 6, 6}, + }, + { + {5, 6, 6, 6}, + {6, 6, 6, 6}, + {6, 6, 6, 6}, + {6, 6, 6, 6}, + }, + { + {6, 6, 6, 6}, + {6, 6, 6, 6}, + {6, 6, 6, 6}, + {7, 6, 6, 6}, + }, + { + {6, 6, 6, 6}, + {6, 6, 7, 6}, + {6, 6, 6, 6}, + {7, 6, 7, 6}, + }, + { + {6, 6, 6, 6}, + {7, 6, 7, 6}, + {6, 7, 6, 6}, + {7, 6, 7, 6}, + }, + { + {6, 6, 6, 7}, + {7, 6, 7, 6}, + {6, 7, 6, 7}, + {7, 6, 7, 6}, + }, + { + {6, 7, 6, 7}, + {7, 6, 7, 6}, + {6, 7, 6, 7}, + {7, 7, 7, 6}, + }, + { + {6, 7, 6, 7}, + {7, 6, 7, 7}, + {6, 7, 6, 7}, + {7, 7, 7, 7}, + }, + { + {6, 7, 6, 7}, + {7, 7, 7, 7}, + {7, 7, 6, 7}, + {7, 7, 7, 7}, + }, + { + {6, 7, 7, 7}, + {7, 7, 7, 7}, + {7, 7, 7, 7}, + {7, 7, 7, 7}, + }, + { + {7, 7, 7, 7}, + {7, 7, 7, 7}, + {7, 7, 7, 7}, + {8, 7, 7, 7}, + }, + { + {7, 7, 7, 7}, + {7, 7, 8, 7}, + {7, 7, 7, 7}, + {8, 7, 8, 7}, + }, + { + {7, 7, 7, 7}, + {8, 7, 8, 7}, + {7, 8, 7, 7}, + {8, 7, 8, 7}, + }, + { + {7, 7, 7, 8}, + {8, 7, 8, 7}, + {7, 8, 7, 8}, + {8, 7, 8, 7}, + }, + { + {7, 8, 7, 8}, + {8, 7, 8, 7}, + {7, 8, 7, 8}, + {8, 8, 8, 7}, + }, + { + {7, 8, 7, 8}, + {8, 7, 8, 8}, + {7, 8, 7, 8}, + {8, 8, 8, 8}, + }, + { + {7, 8, 7, 8}, + {8, 8, 8, 8}, + {7, 8, 7, 8}, + {8, 8, 8, 8}, + }, + { + {7, 8, 8, 8}, + {8, 8, 8, 8}, + {8, 8, 7, 8}, + {8, 8, 8, 8}, + }, + { + {8, 8, 8, 8}, + {8, 8, 8, 8}, + {8, 8, 8, 8}, + {8, 8, 8, 8}, + }, + { + {8, 8, 8, 8}, + {8, 8, 9, 8}, + {8, 8, 8, 8}, + {9, 8, 8, 8}, + }, + { + {8, 8, 8, 8}, + {9, 8, 9, 8}, + {8, 8, 8, 8}, + {9, 8, 9, 8}, + }, + { + {8, 8, 8, 9}, + {9, 8, 9, 8}, + {8, 9, 8, 8}, + {9, 8, 9, 8}, + }, + { + {8, 9, 8, 9}, + {9, 8, 9, 8}, + {8, 9, 8, 9}, + {9, 8, 9, 8}, + }, + { + {8, 9, 8, 9}, + {9, 8, 9, 9}, + {8, 9, 8, 9}, + {9, 9, 9, 8}, + }, + { + {8, 9, 8, 9}, + {9, 9, 9, 9}, + {8, 9, 8, 9}, + {9, 9, 9, 9}, + }, + { + {8, 9, 9, 9}, + {9, 9, 9, 9}, + {9, 9, 8, 9}, + {9, 9, 9, 9}, + }, + { + {9, 9, 9, 9}, + {9, 9, 9, 9}, + {9, 9, 9, 9}, + {9, 9, 9, 9}, + }, + { + {9, 9, 9, 9}, + {9, 9, 10, 9}, + {9, 9, 9, 9}, + {10, 9, 9, 9}, + }, + { + {9, 9, 9, 9}, + {10, 9, 10, 9}, + {9, 9, 9, 9}, + {10, 9, 10, 9}, + }, + { + {9, 9, 9, 10}, + {10, 9, 10, 9}, + {9, 10, 9, 9}, + {10, 9, 10, 9}, + }, + { + {9, 10, 9, 10}, + {10, 9, 10, 9}, + {9, 10, 9, 10}, + {10, 9, 10, 9}, + }, + { + {9, 10, 9, 10}, + {10, 9, 10, 10}, + {9, 10, 9, 10}, + {10, 10, 10, 9}, + }, + { + {9, 10, 9, 10}, + {10, 9, 10, 10}, + {9, 10, 9, 10}, + {10, 10, 10, 10}, + }, + { + {9, 10, 9, 10}, + {10, 10, 10, 10}, + {10, 10, 9, 10}, + {10, 10, 10, 10}, + }, + { + {9, 10, 10, 10}, + {10, 10, 10, 10}, + {10, 10, 10, 10}, + {10, 10, 10, 10}, + }, + { + {10, 10, 10, 10}, + {10, 10, 10, 10}, + {10, 10, 10, 10}, + {11, 10, 10, 10}, + }, + { + {10, 10, 10, 10}, + {10, 10, 11, 10}, + {10, 10, 10, 10}, + {11, 10, 11, 10}, + }, + { + {10, 10, 10, 10}, + {11, 10, 11, 10}, + {10, 11, 10, 10}, + {11, 10, 11, 10}, + }, + { + {10, 10, 10, 11}, + {11, 10, 11, 10}, + {10, 11, 10, 11}, + {11, 10, 11, 10}, + }, + { + {10, 11, 10, 11}, + {11, 10, 11, 10}, + {10, 11, 10, 11}, + {11, 11, 11, 10}, + }, + { + {10, 11, 10, 11}, + {11, 10, 11, 11}, + {10, 11, 10, 11}, + {11, 11, 11, 11}, + }, + { + {10, 11, 10, 11}, + {11, 11, 11, 11}, + {11, 11, 10, 11}, + {11, 11, 11, 11}, + }, + { + {10, 11, 11, 11}, + {11, 11, 11, 11}, + {11, 11, 11, 11}, + {11, 11, 11, 11}, + }, + { + {11, 11, 11, 11}, + {11, 11, 11, 11}, + {11, 11, 11, 11}, + {12, 11, 11, 11}, + }, + { + {11, 11, 11, 11}, + {11, 11, 12, 11}, + {11, 11, 11, 11}, + {12, 11, 12, 11}, + }, + { + {11, 11, 11, 11}, + {12, 11, 12, 11}, + {11, 12, 11, 11}, + {12, 11, 12, 11}, + }, + { + {11, 11, 11, 12}, + {12, 11, 12, 11}, + {11, 12, 11, 12}, + {12, 11, 12, 11}, + }, + { + {11, 12, 11, 12}, + {12, 11, 12, 11}, + {11, 12, 11, 12}, + {12, 12, 12, 11}, + }, + { + {11, 12, 11, 12}, + {12, 11, 12, 12}, + {11, 12, 11, 12}, + {12, 12, 12, 11}, + }, + { + {11, 12, 11, 12}, + {12, 12, 12, 12}, + {11, 12, 11, 12}, + {12, 12, 12, 12}, + }, + { + {11, 12, 12, 12}, + {12, 12, 12, 12}, + {12, 12, 11, 12}, + {12, 12, 12, 12}, + }, + { + {12, 12, 12, 12}, + {12, 12, 12, 12}, + {12, 12, 12, 12}, + {12, 12, 12, 12}, + }, + { + {12, 12, 12, 12}, + {12, 12, 13, 12}, + {12, 12, 12, 12}, + {13, 12, 12, 12}, + }, + { + {12, 12, 12, 12}, + {13, 12, 13, 12}, + {12, 12, 12, 12}, + {13, 12, 13, 12}, + }, + { + {12, 12, 12, 13}, + {13, 12, 13, 12}, + {12, 13, 12, 12}, + {13, 12, 13, 12}, + }, + { + {12, 13, 12, 13}, + {13, 12, 13, 12}, + {12, 13, 12, 13}, + {13, 12, 13, 12}, + }, + { + {12, 13, 12, 13}, + {13, 12, 13, 13}, + {12, 13, 12, 13}, + {13, 13, 13, 12}, + }, + { + {12, 13, 12, 13}, + {13, 13, 13, 13}, + {12, 13, 12, 13}, + {13, 13, 13, 13}, + }, + { + {12, 13, 13, 13}, + {13, 13, 13, 13}, + {13, 13, 12, 13}, + {13, 13, 13, 13}, + }, + { + {13, 13, 13, 13}, + {13, 13, 13, 13}, + {13, 13, 13, 13}, + {13, 13, 13, 13}, + }, + { + {13, 13, 13, 13}, + {13, 13, 14, 13}, + {13, 13, 13, 13}, + {14, 13, 13, 13}, + }, + { + {13, 13, 13, 13}, + {14, 13, 14, 13}, + {13, 13, 13, 13}, + {14, 13, 14, 13}, + }, + { + {13, 13, 13, 14}, + {14, 13, 14, 13}, + {13, 14, 13, 13}, + {14, 13, 14, 13}, + }, + { + {13, 14, 13, 14}, + {14, 13, 14, 13}, + {13, 14, 13, 14}, + {14, 13, 14, 13}, + }, + { + {13, 14, 13, 14}, + {14, 13, 14, 13}, + {13, 14, 13, 14}, + {14, 14, 14, 13}, + }, + { + {13, 14, 13, 14}, + {14, 13, 14, 14}, + {13, 14, 13, 14}, + {14, 14, 14, 14}, + }, + { + {13, 14, 13, 14}, + {14, 14, 14, 14}, + {14, 14, 13, 14}, + {14, 14, 14, 14}, + }, + { + {13, 14, 14, 14}, + {14, 14, 14, 14}, + {14, 14, 14, 14}, + {14, 14, 14, 14}, + }, + { + {14, 14, 14, 14}, + {14, 14, 14, 14}, + {14, 14, 14, 14}, + {15, 14, 14, 14}, + }, + { + {14, 14, 14, 14}, + {14, 14, 15, 14}, + {14, 14, 14, 14}, + {15, 14, 15, 14}, + }, + { + {14, 14, 14, 14}, + {15, 14, 15, 14}, + {14, 15, 14, 14}, + {15, 14, 15, 14}, + }, + { + {14, 14, 14, 15}, + {15, 14, 15, 14}, + {14, 15, 14, 15}, + {15, 14, 15, 14}, + }, + { + {14, 15, 14, 15}, + {15, 14, 15, 14}, + {14, 15, 14, 15}, + {15, 15, 15, 14}, + }, + { + {14, 15, 14, 15}, + {15, 14, 15, 15}, + {14, 15, 14, 15}, + {15, 15, 15, 15}, + }, + { + {14, 15, 14, 15}, + {15, 15, 15, 15}, + {15, 15, 14, 15}, + {15, 15, 15, 15}, + }, + { + {14, 15, 15, 15}, + {15, 15, 15, 15}, + {15, 15, 15, 15}, + {15, 15, 15, 15}, + }, + { + {15, 15, 15, 15}, + {15, 15, 15, 15}, + {15, 15, 15, 15}, + {16, 15, 15, 15}, + }, + { + {15, 15, 15, 15}, + {15, 15, 16, 15}, + {15, 15, 15, 15}, + {16, 15, 16, 15}, + }, + { + {15, 15, 15, 15}, + {16, 15, 16, 15}, + {15, 16, 15, 15}, + {16, 15, 16, 15}, + }, + { + {15, 15, 15, 16}, + {16, 15, 16, 15}, + {15, 16, 15, 16}, + {16, 15, 16, 15}, + }, + { + {15, 16, 15, 16}, + {16, 15, 16, 15}, + {15, 16, 15, 16}, + {16, 16, 16, 15}, + }, + { + {15, 16, 15, 16}, + {16, 15, 16, 16}, + {15, 16, 15, 16}, + {16, 16, 16, 16}, + }, + { + {15, 16, 15, 16}, + {16, 16, 16, 16}, + {16, 16, 15, 16}, + {16, 16, 16, 16}, + }, + { + {15, 16, 16, 16}, + {16, 16, 16, 16}, + {16, 16, 16, 16}, + {16, 16, 16, 16}, + }, + { + {16, 16, 16, 16}, + {16, 16, 16, 16}, + {16, 16, 16, 16}, + {17, 16, 16, 16}, + }, + { + {16, 16, 16, 16}, + {16, 16, 17, 16}, + {16, 16, 16, 16}, + {17, 16, 17, 16}, + }, + { + {16, 16, 16, 16}, + {17, 16, 17, 16}, + {16, 17, 16, 16}, + {17, 16, 17, 16}, + }, + { + {16, 16, 16, 17}, + {17, 16, 17, 16}, + {16, 17, 16, 17}, + {17, 16, 17, 16}, + }, + { + {16, 17, 16, 17}, + {17, 16, 17, 16}, + {16, 17, 16, 17}, + {17, 17, 17, 16}, + }, + { + {16, 17, 16, 17}, + {17, 16, 17, 17}, + {16, 17, 16, 17}, + {17, 17, 17, 17}, + }, + { + {16, 17, 16, 17}, + {17, 17, 17, 17}, + {17, 17, 16, 17}, + {17, 17, 17, 17}, + }, + { + {16, 17, 17, 17}, + {17, 17, 17, 17}, + {17, 17, 17, 17}, + {17, 17, 17, 17}, + }, + { + {17, 17, 17, 17}, + {17, 17, 17, 17}, + {17, 17, 17, 17}, + {18, 17, 17, 17}, + }, + { + {17, 17, 17, 17}, + {17, 17, 18, 17}, + {17, 17, 17, 17}, + {18, 17, 18, 17}, + }, + { + {17, 17, 17, 17}, + {18, 17, 18, 17}, + {17, 18, 17, 17}, + {18, 17, 18, 17}, + }, + { + {17, 17, 17, 18}, + {18, 17, 18, 17}, + {17, 18, 17, 18}, + {18, 17, 18, 17}, + }, + { + {17, 18, 17, 18}, + {18, 17, 18, 17}, + {17, 18, 17, 18}, + {18, 17, 18, 17}, + }, + { + {17, 18, 17, 18}, + {18, 17, 18, 18}, + {17, 18, 17, 18}, + {18, 18, 18, 17}, + }, + { + {17, 18, 17, 18}, + {18, 18, 18, 18}, + {17, 18, 17, 18}, + {18, 18, 18, 18}, + }, + { + {17, 18, 18, 18}, + {18, 18, 18, 18}, + {18, 18, 17, 18}, + {18, 18, 18, 18}, + }, + { + {18, 18, 18, 18}, + {18, 18, 18, 18}, + {18, 18, 18, 18}, + {18, 18, 18, 18}, + }, + { + {18, 18, 18, 18}, + {18, 18, 19, 18}, + {18, 18, 18, 18}, + {19, 18, 18, 18}, + }, + { + {18, 18, 18, 18}, + {19, 18, 19, 18}, + {18, 18, 18, 18}, + {19, 18, 19, 18}, + }, + { + {18, 18, 18, 19}, + {19, 18, 19, 18}, + {18, 19, 18, 18}, + {19, 18, 19, 18}, + }, + { + {18, 19, 18, 19}, + {19, 18, 19, 18}, + {18, 19, 18, 19}, + {19, 18, 19, 18}, + }, + { + {18, 19, 18, 19}, + {19, 18, 19, 19}, + {18, 19, 18, 19}, + {19, 19, 19, 18}, + }, + { + {18, 19, 18, 19}, + {19, 19, 19, 19}, + {18, 19, 18, 19}, + {19, 19, 19, 19}, + }, + { + {18, 19, 19, 19}, + {19, 19, 19, 19}, + {19, 19, 18, 19}, + {19, 19, 19, 19}, + }, + { + {19, 19, 19, 19}, + {19, 19, 19, 19}, + {19, 19, 19, 19}, + {19, 19, 19, 19}, + }, + { + {19, 19, 19, 19}, + {19, 19, 20, 19}, + {19, 19, 19, 19}, + {20, 19, 19, 19}, + }, + { + {19, 19, 19, 19}, + {20, 19, 20, 19}, + {19, 19, 19, 19}, + {20, 19, 20, 19}, + }, + { + {19, 19, 19, 20}, + {20, 19, 20, 19}, + {19, 20, 19, 19}, + {20, 19, 20, 19}, + }, + { + {19, 19, 19, 20}, + {20, 19, 20, 19}, + {19, 20, 19, 20}, + {20, 19, 20, 19}, + }, + { + {19, 20, 19, 20}, + {20, 19, 20, 19}, + {19, 20, 19, 20}, + {20, 20, 20, 19}, + }, + { + {19, 20, 19, 20}, + {20, 19, 20, 20}, + {19, 20, 19, 20}, + {20, 20, 20, 20}, + }, + { + {19, 20, 19, 20}, + {20, 20, 20, 20}, + {20, 20, 19, 20}, + {20, 20, 20, 20}, + }, + { + {19, 20, 20, 20}, + {20, 20, 20, 20}, + {20, 20, 20, 20}, + {20, 20, 20, 20}, + }, + { + {20, 20, 20, 20}, + {20, 20, 20, 20}, + {20, 20, 20, 20}, + {21, 20, 20, 20}, + }, + { + {20, 20, 20, 20}, + {20, 20, 21, 20}, + {20, 20, 20, 20}, + {21, 20, 21, 20}, + }, + { + {20, 20, 20, 20}, + {21, 20, 21, 20}, + {20, 21, 20, 20}, + {21, 20, 21, 20}, + }, + { + {20, 20, 20, 21}, + {21, 20, 21, 20}, + {20, 21, 20, 21}, + {21, 20, 21, 20}, + }, + { + {20, 21, 20, 21}, + {21, 20, 21, 20}, + {20, 21, 20, 21}, + {21, 21, 21, 20}, + }, + { + {20, 21, 20, 21}, + {21, 20, 21, 21}, + {20, 21, 20, 21}, + {21, 21, 21, 21}, + }, + { + {20, 21, 20, 21}, + {21, 21, 21, 21}, + {21, 21, 20, 21}, + {21, 21, 21, 21}, + }, + { + {20, 21, 21, 21}, + {21, 21, 21, 21}, + {21, 21, 21, 21}, + {21, 21, 21, 21}, + }, + { + {21, 21, 21, 21}, + {21, 21, 21, 21}, + {21, 21, 21, 21}, + {22, 21, 21, 21}, + }, + { + {21, 21, 21, 21}, + {21, 21, 22, 21}, + {21, 21, 21, 21}, + {22, 21, 22, 21}, + }, + { + {21, 21, 21, 21}, + {22, 21, 22, 21}, + {21, 22, 21, 21}, + {22, 21, 22, 21}, + }, + { + {21, 21, 21, 22}, + {22, 21, 22, 21}, + {21, 22, 21, 21}, + {22, 21, 22, 21}, + }, + { + {21, 22, 21, 22}, + {22, 21, 22, 21}, + {21, 22, 21, 22}, + {22, 21, 22, 21}, + }, + { + {21, 22, 21, 22}, + {22, 21, 22, 22}, + {21, 22, 21, 22}, + {22, 22, 22, 21}, + }, + { + {21, 22, 21, 22}, + {22, 22, 22, 22}, + {21, 22, 21, 22}, + {22, 22, 22, 22}, + }, + { + {21, 22, 22, 22}, + {22, 22, 22, 22}, + {22, 22, 21, 22}, + {22, 22, 22, 22}, + }, + { + {22, 22, 22, 22}, + {22, 22, 22, 22}, + {22, 22, 22, 22}, + {22, 22, 22, 22}, + }, + { + {22, 22, 22, 22}, + {22, 22, 23, 22}, + {22, 22, 22, 22}, + {23, 22, 22, 22}, + }, + { + {22, 22, 22, 22}, + {23, 22, 23, 22}, + {22, 22, 22, 22}, + {23, 22, 23, 22}, + }, + { + {22, 22, 22, 23}, + {23, 22, 23, 22}, + {22, 23, 22, 22}, + {23, 22, 23, 22}, + }, + { + {22, 23, 22, 23}, + {23, 22, 23, 22}, + {22, 23, 22, 23}, + {23, 22, 23, 22}, + }, + { + {22, 23, 22, 23}, + {23, 22, 23, 23}, + {22, 23, 22, 23}, + {23, 23, 23, 22}, + }, + { + {22, 23, 22, 23}, + {23, 23, 23, 23}, + {22, 23, 22, 23}, + {23, 23, 23, 23}, + }, + { + {22, 23, 23, 23}, + {23, 23, 23, 23}, + {23, 23, 22, 23}, + {23, 23, 23, 23}, + }, + { + {23, 23, 23, 23}, + {23, 23, 23, 23}, + {23, 23, 23, 23}, + {23, 23, 23, 23}, + }, + { + {23, 23, 23, 23}, + {23, 23, 24, 23}, + {23, 23, 23, 23}, + {24, 23, 23, 23}, + }, + { + {23, 23, 23, 23}, + {24, 23, 24, 23}, + {23, 23, 23, 23}, + {24, 23, 24, 23}, + }, + { + {23, 23, 23, 23}, + {24, 23, 24, 23}, + {23, 24, 23, 23}, + {24, 23, 24, 23}, + }, + { + {23, 23, 23, 24}, + {24, 23, 24, 23}, + {23, 24, 23, 24}, + {24, 23, 24, 23}, + }, + { + {23, 24, 23, 24}, + {24, 23, 24, 23}, + {23, 24, 23, 24}, + {24, 24, 24, 23}, + }, + { + {23, 24, 23, 24}, + {24, 23, 24, 24}, + {23, 24, 23, 24}, + {24, 24, 24, 24}, + }, + { + {23, 24, 23, 24}, + {24, 24, 24, 24}, + {24, 24, 23, 24}, + {24, 24, 24, 24}, + }, + { + {23, 24, 24, 24}, + {24, 24, 24, 24}, + {24, 24, 24, 24}, + {24, 24, 24, 24}, + }, + { + {24, 24, 24, 24}, + {24, 24, 24, 24}, + {24, 24, 24, 24}, + {25, 24, 24, 24}, + }, + { + {24, 24, 24, 24}, + {24, 24, 25, 24}, + {24, 24, 24, 24}, + {25, 24, 25, 24}, + }, + { + {24, 24, 24, 24}, + {25, 24, 25, 24}, + {24, 25, 24, 24}, + {25, 24, 25, 24}, + }, + { + {24, 24, 24, 25}, + {25, 24, 25, 24}, + {24, 25, 24, 25}, + {25, 24, 25, 24}, + }, + { + {24, 25, 24, 25}, + {25, 24, 25, 24}, + {24, 25, 24, 25}, + {25, 25, 25, 24}, + }, + { + {24, 25, 24, 25}, + {25, 24, 25, 25}, + {24, 25, 24, 25}, + {25, 25, 25, 25}, + }, + { + {24, 25, 24, 25}, + {25, 25, 25, 25}, + {25, 25, 24, 25}, + {25, 25, 25, 25}, + }, + { + {24, 25, 25, 25}, + {25, 25, 25, 25}, + {25, 25, 25, 25}, + {25, 25, 25, 25}, + }, + { + {25, 25, 25, 25}, + {25, 25, 25, 25}, + {25, 25, 25, 25}, + {26, 25, 25, 25}, + }, + { + {25, 25, 25, 25}, + {25, 25, 26, 25}, + {25, 25, 25, 25}, + {26, 25, 26, 25}, + }, + { + {25, 25, 25, 25}, + {26, 25, 26, 25}, + {25, 25, 25, 25}, + {26, 25, 26, 25}, + }, + { + {25, 25, 25, 26}, + {26, 25, 26, 25}, + {25, 26, 25, 25}, + {26, 25, 26, 25}, + }, + { + {25, 26, 25, 26}, + {26, 25, 26, 25}, + {25, 26, 25, 26}, + {26, 25, 26, 25}, + }, + { + {25, 26, 25, 26}, + {26, 25, 26, 26}, + {25, 26, 25, 26}, + {26, 26, 26, 25}, + }, + { + {25, 26, 25, 26}, + {26, 26, 26, 26}, + {25, 26, 25, 26}, + {26, 26, 26, 26}, + }, + { + {25, 26, 26, 26}, + {26, 26, 26, 26}, + {26, 26, 25, 26}, + {26, 26, 26, 26}, + }, + { + {26, 26, 26, 26}, + {26, 26, 26, 26}, + {26, 26, 26, 26}, + {26, 26, 26, 26}, + }, + { + {26, 26, 26, 26}, + {26, 26, 27, 26}, + {26, 26, 26, 26}, + {27, 26, 26, 26}, + }, + { + {26, 26, 26, 26}, + {27, 26, 27, 26}, + {26, 26, 26, 26}, + {27, 26, 27, 26}, + }, + { + {26, 26, 26, 27}, + {27, 26, 27, 26}, + {26, 27, 26, 26}, + {27, 26, 27, 26}, + }, + { + {26, 27, 26, 27}, + {27, 26, 27, 26}, + {26, 27, 26, 27}, + {27, 26, 27, 26}, + }, + { + {26, 27, 26, 27}, + {27, 26, 27, 27}, + {26, 27, 26, 27}, + {27, 27, 27, 26}, + }, + { + {26, 27, 26, 27}, + {27, 27, 27, 27}, + {26, 27, 26, 27}, + {27, 27, 27, 27}, + }, + { + {26, 27, 27, 27}, + {27, 27, 27, 27}, + {27, 27, 26, 27}, + {27, 27, 27, 27}, + }, + { + {27, 27, 27, 27}, + {27, 27, 27, 27}, + {27, 27, 27, 27}, + {27, 27, 27, 27}, + }, + { + {27, 27, 27, 27}, + {27, 27, 28, 27}, + {27, 27, 27, 27}, + {28, 27, 27, 27}, + }, + { + {27, 27, 27, 27}, + {27, 27, 28, 27}, + {27, 27, 27, 27}, + {28, 27, 28, 27}, + }, + { + {27, 27, 27, 27}, + {28, 27, 28, 27}, + {27, 28, 27, 27}, + {28, 27, 28, 27}, + }, + { + {27, 27, 27, 28}, + {28, 27, 28, 27}, + {27, 28, 27, 28}, + {28, 27, 28, 27}, + }, + { + {27, 28, 27, 28}, + {28, 27, 28, 27}, + {27, 28, 27, 28}, + {28, 28, 28, 27}, + }, + { + {27, 28, 27, 28}, + {28, 27, 28, 28}, + {27, 28, 27, 28}, + {28, 28, 28, 28}, + }, + { + {27, 28, 27, 28}, + {28, 28, 28, 28}, + {28, 28, 27, 28}, + {28, 28, 28, 28}, + }, + { + {27, 28, 28, 28}, + {28, 28, 28, 28}, + {28, 28, 28, 28}, + {28, 28, 28, 28}, + }, + { + {28, 28, 28, 28}, + {28, 28, 28, 28}, + {28, 28, 28, 28}, + {29, 28, 28, 28}, + }, + { + {28, 28, 28, 28}, + {28, 28, 29, 28}, + {28, 28, 28, 28}, + {29, 28, 29, 28}, + }, + { + {28, 28, 28, 28}, + {29, 28, 29, 28}, + {28, 29, 28, 28}, + {29, 28, 29, 28}, + }, + { + {28, 28, 28, 29}, + {29, 28, 29, 28}, + {28, 29, 28, 29}, + {29, 28, 29, 28}, + }, + { + {28, 29, 28, 29}, + {29, 28, 29, 28}, + {28, 29, 28, 29}, + {29, 29, 29, 28}, + }, + { + {28, 29, 28, 29}, + {29, 28, 29, 29}, + {28, 29, 28, 29}, + {29, 29, 29, 29}, + }, + { + {28, 29, 28, 29}, + {29, 29, 29, 29}, + {29, 29, 28, 29}, + {29, 29, 29, 29}, + }, + { + {28, 29, 29, 29}, + {29, 29, 29, 29}, + {29, 29, 29, 29}, + {29, 29, 29, 29}, + }, + { + {29, 29, 29, 29}, + {29, 29, 29, 29}, + {29, 29, 29, 29}, + {30, 29, 29, 29}, + }, + { + {29, 29, 29, 29}, + {29, 29, 30, 29}, + {29, 29, 29, 29}, + {30, 29, 29, 29}, + }, + { + {29, 29, 29, 29}, + {30, 29, 30, 29}, + {29, 29, 29, 29}, + {30, 29, 30, 29}, + }, + { + {29, 29, 29, 30}, + {30, 29, 30, 29}, + {29, 30, 29, 29}, + {30, 29, 30, 29}, + }, + { + {29, 30, 29, 30}, + {30, 29, 30, 29}, + {29, 30, 29, 30}, + {30, 29, 30, 29}, + }, + { + {29, 30, 29, 30}, + {30, 29, 30, 30}, + {29, 30, 29, 30}, + {30, 30, 30, 29}, + }, + { + {29, 30, 29, 30}, + {30, 30, 30, 30}, + {29, 30, 29, 30}, + {30, 30, 30, 30}, + }, + { + {29, 30, 30, 30}, + {30, 30, 30, 30}, + {30, 30, 29, 30}, + {30, 30, 30, 30}, + }, + { + {30, 30, 30, 30}, + {30, 30, 30, 30}, + {30, 30, 30, 30}, + {30, 30, 30, 30}, + }, + { + {30, 30, 30, 30}, + {30, 30, 31, 30}, + {30, 30, 30, 30}, + {31, 30, 30, 30}, + }, + { + {30, 30, 30, 30}, + {31, 30, 31, 30}, + {30, 30, 30, 30}, + {31, 30, 31, 30}, + }, + { + {30, 30, 30, 31}, + {31, 30, 31, 30}, + {30, 31, 30, 30}, + {31, 30, 31, 30}, + }, + { + {30, 31, 30, 31}, + {31, 30, 31, 30}, + {30, 31, 30, 31}, + {31, 30, 31, 30}, + }, + { + {30, 31, 30, 31}, + {31, 30, 31, 31}, + {30, 31, 30, 31}, + {31, 31, 31, 30}, + }, + { + {30, 31, 30, 31}, + {31, 31, 31, 31}, + {30, 31, 30, 31}, + {31, 31, 31, 31}, + }, + { + {30, 31, 31, 31}, + {31, 31, 31, 31}, + {31, 31, 30, 31}, + {31, 31, 31, 31}, + }, + { + {31, 31, 31, 31}, + {31, 31, 31, 31}, + {31, 31, 31, 31}, + {31, 31, 31, 31}, + }, }; -static const uint8_t dither_g[256][4][4] = -{ - { - {0, 0, 0, 0}, - {0, 0, 0, 0}, - {0, 0, 0, 0}, - {0, 0, 0, 0}, - }, - { - {0, 0, 0, 0}, - {1, 0, 1, 0}, - {0, 0, 0, 0}, - {1, 0, 1, 0}, - }, - { - {0, 1, 0, 1}, - {1, 0, 1, 0}, - {0, 1, 0, 1}, - {1, 0, 1, 0}, - }, - { - {0, 1, 0, 1}, - {1, 1, 1, 1}, - {0, 1, 0, 1}, - {1, 1, 1, 1}, - }, - { - {1, 1, 1, 1}, - {1, 1, 1, 1}, - {1, 1, 1, 1}, - {1, 1, 1, 1}, - }, - { - {1, 1, 1, 1}, - {2, 1, 2, 1}, - {1, 1, 1, 1}, - {2, 1, 2, 1}, - }, - { - {1, 2, 1, 2}, - {2, 1, 2, 1}, - {1, 2, 1, 2}, - {2, 1, 2, 1}, - }, - { - {1, 2, 1, 2}, - {2, 2, 2, 2}, - {1, 2, 1, 2}, - {2, 2, 2, 2}, - }, - { - {2, 2, 2, 2}, - {2, 2, 2, 2}, - {2, 2, 2, 2}, - {2, 2, 2, 2}, - }, - { - {2, 2, 2, 2}, - {3, 2, 3, 2}, - {2, 2, 2, 2}, - {3, 2, 3, 2}, - }, - { - {2, 3, 2, 3}, - {3, 2, 3, 2}, - {2, 3, 2, 3}, - {3, 2, 3, 2}, - }, - { - {2, 3, 2, 3}, - {3, 3, 3, 3}, - {2, 3, 2, 3}, - {3, 3, 3, 3}, - }, - { - {3, 3, 3, 3}, - {3, 3, 3, 3}, - {3, 3, 3, 3}, - {3, 3, 3, 3}, - }, - { - {3, 3, 3, 3}, - {4, 3, 4, 3}, - {3, 3, 3, 3}, - {4, 3, 4, 3}, - }, - { - {3, 4, 3, 4}, - {4, 3, 4, 3}, - {3, 4, 3, 4}, - {4, 3, 4, 3}, - }, - { - {3, 4, 3, 4}, - {4, 4, 4, 4}, - {3, 4, 3, 4}, - {4, 4, 4, 4}, - }, - { - {3, 4, 4, 4}, - {4, 4, 4, 4}, - {4, 4, 4, 4}, - {4, 4, 4, 4}, - }, - { - {4, 4, 4, 4}, - {4, 4, 5, 4}, - {4, 4, 4, 4}, - {5, 4, 5, 4}, - }, - { - {4, 4, 4, 5}, - {5, 4, 5, 4}, - {4, 5, 4, 5}, - {5, 4, 5, 4}, - }, - { - {4, 5, 4, 5}, - {5, 4, 5, 5}, - {4, 5, 4, 5}, - {5, 5, 5, 5}, - }, - { - {4, 5, 5, 5}, - {5, 5, 5, 5}, - {5, 5, 5, 5}, - {5, 5, 5, 5}, - }, - { - {5, 5, 5, 5}, - {5, 5, 6, 5}, - {5, 5, 5, 5}, - {6, 5, 6, 5}, - }, - { - {5, 5, 5, 6}, - {6, 5, 6, 5}, - {5, 6, 5, 6}, - {6, 5, 6, 5}, - }, - { - {5, 6, 5, 6}, - {6, 5, 6, 6}, - {5, 6, 5, 6}, - {6, 6, 6, 6}, - }, - { - {5, 6, 6, 6}, - {6, 6, 6, 6}, - {6, 6, 6, 6}, - {6, 6, 6, 6}, - }, - { - {6, 6, 6, 6}, - {6, 6, 7, 6}, - {6, 6, 6, 6}, - {7, 6, 7, 6}, - }, - { - {6, 6, 6, 7}, - {7, 6, 7, 6}, - {6, 7, 6, 7}, - {7, 6, 7, 6}, - }, - { - {6, 7, 6, 7}, - {7, 6, 7, 7}, - {6, 7, 6, 7}, - {7, 7, 7, 7}, - }, - { - {6, 7, 7, 7}, - {7, 7, 7, 7}, - {7, 7, 7, 7}, - {7, 7, 7, 7}, - }, - { - {7, 7, 7, 7}, - {7, 7, 8, 7}, - {7, 7, 7, 7}, - {8, 7, 8, 7}, - }, - { - {7, 7, 7, 8}, - {8, 7, 8, 7}, - {7, 8, 7, 8}, - {8, 7, 8, 7}, - }, - { - {7, 8, 7, 8}, - {8, 7, 8, 8}, - {7, 8, 7, 8}, - {8, 8, 8, 8}, - }, - { - {7, 8, 8, 8}, - {8, 8, 8, 8}, - {8, 8, 7, 8}, - {8, 8, 8, 8}, - }, - { - {8, 8, 8, 8}, - {8, 8, 9, 8}, - {8, 8, 8, 8}, - {9, 8, 8, 8}, - }, - { - {8, 8, 8, 9}, - {9, 8, 9, 8}, - {8, 9, 8, 8}, - {9, 8, 9, 8}, - }, - { - {8, 9, 8, 9}, - {9, 8, 9, 9}, - {8, 9, 8, 9}, - {9, 9, 9, 8}, - }, - { - {8, 9, 9, 9}, - {9, 9, 9, 9}, - {9, 9, 8, 9}, - {9, 9, 9, 9}, - }, - { - {9, 9, 9, 9}, - {9, 9, 10, 9}, - {9, 9, 9, 9}, - {10, 9, 9, 9}, - }, - { - {9, 9, 9, 10}, - {10, 9, 10, 9}, - {9, 10, 9, 9}, - {10, 9, 10, 9}, - }, - { - {9, 10, 9, 10}, - {10, 9, 10, 10}, - {9, 10, 9, 10}, - {10, 10, 10, 9}, - }, - { - {9, 10, 10, 10}, - {10, 10, 10, 10}, - {10, 10, 9, 10}, - {10, 10, 10, 10}, - }, - { - {10, 10, 10, 10}, - {10, 10, 11, 10}, - {10, 10, 10, 10}, - {11, 10, 10, 10}, - }, - { - {10, 10, 10, 11}, - {11, 10, 11, 10}, - {10, 11, 10, 10}, - {11, 10, 11, 10}, - }, - { - {10, 11, 10, 11}, - {11, 10, 11, 11}, - {10, 11, 10, 11}, - {11, 11, 11, 10}, - }, - { - {10, 11, 11, 11}, - {11, 11, 11, 11}, - {11, 11, 10, 11}, - {11, 11, 11, 11}, - }, - { - {11, 11, 11, 11}, - {11, 11, 12, 11}, - {11, 11, 11, 11}, - {12, 11, 11, 11}, - }, - { - {11, 11, 11, 12}, - {12, 11, 12, 11}, - {11, 12, 11, 11}, - {12, 11, 12, 11}, - }, - { - {11, 12, 11, 12}, - {12, 11, 12, 12}, - {11, 12, 11, 12}, - {12, 12, 12, 11}, - }, - { - {11, 12, 11, 12}, - {12, 12, 12, 12}, - {12, 12, 11, 12}, - {12, 12, 12, 12}, - }, - { - {12, 12, 12, 12}, - {12, 12, 12, 12}, - {12, 12, 12, 12}, - {13, 12, 12, 12}, - }, - { - {12, 12, 12, 12}, - {13, 12, 13, 12}, - {12, 13, 12, 12}, - {13, 12, 13, 12}, - }, - { - {12, 13, 12, 13}, - {13, 12, 13, 12}, - {12, 13, 12, 13}, - {13, 13, 13, 12}, - }, - { - {12, 13, 12, 13}, - {13, 13, 13, 13}, - {13, 13, 12, 13}, - {13, 13, 13, 13}, - }, - { - {13, 13, 13, 13}, - {13, 13, 13, 13}, - {13, 13, 13, 13}, - {14, 13, 13, 13}, - }, - { - {13, 13, 13, 13}, - {14, 13, 14, 13}, - {13, 14, 13, 13}, - {14, 13, 14, 13}, - }, - { - {13, 14, 13, 14}, - {14, 13, 14, 13}, - {13, 14, 13, 14}, - {14, 14, 14, 13}, - }, - { - {13, 14, 13, 14}, - {14, 14, 14, 14}, - {14, 14, 13, 14}, - {14, 14, 14, 14}, - }, - { - {14, 14, 14, 14}, - {14, 14, 14, 14}, - {14, 14, 14, 14}, - {15, 14, 14, 14}, - }, - { - {14, 14, 14, 14}, - {15, 14, 15, 14}, - {14, 15, 14, 14}, - {15, 14, 15, 14}, - }, - { - {14, 15, 14, 15}, - {15, 14, 15, 14}, - {14, 15, 14, 15}, - {15, 15, 15, 14}, - }, - { - {14, 15, 14, 15}, - {15, 15, 15, 15}, - {15, 15, 14, 15}, - {15, 15, 15, 15}, - }, - { - {15, 15, 15, 15}, - {15, 15, 15, 15}, - {15, 15, 15, 15}, - {16, 15, 15, 15}, - }, - { - {15, 15, 15, 15}, - {16, 15, 16, 15}, - {15, 16, 15, 15}, - {16, 15, 16, 15}, - }, - { - {15, 16, 15, 16}, - {16, 15, 16, 15}, - {15, 16, 15, 16}, - {16, 16, 16, 15}, - }, - { - {15, 16, 15, 16}, - {16, 16, 16, 16}, - {16, 16, 15, 16}, - {16, 16, 16, 16}, - }, - { - {16, 16, 16, 16}, - {16, 16, 16, 16}, - {16, 16, 16, 16}, - {17, 16, 16, 16}, - }, - { - {16, 16, 16, 16}, - {17, 16, 17, 16}, - {16, 17, 16, 16}, - {17, 16, 17, 16}, - }, - { - {16, 17, 16, 17}, - {17, 16, 17, 16}, - {16, 17, 16, 17}, - {17, 17, 17, 16}, - }, - { - {16, 17, 16, 17}, - {17, 17, 17, 17}, - {17, 17, 16, 17}, - {17, 17, 17, 17}, - }, - { - {17, 17, 17, 17}, - {17, 17, 17, 17}, - {17, 17, 17, 17}, - {18, 17, 17, 17}, - }, - { - {17, 17, 17, 17}, - {18, 17, 18, 17}, - {17, 18, 17, 17}, - {18, 17, 18, 17}, - }, - { - {17, 18, 17, 18}, - {18, 17, 18, 17}, - {17, 18, 17, 18}, - {18, 18, 18, 17}, - }, - { - {17, 18, 17, 18}, - {18, 18, 18, 18}, - {18, 18, 17, 18}, - {18, 18, 18, 18}, - }, - { - {18, 18, 18, 18}, - {18, 18, 18, 18}, - {18, 18, 18, 18}, - {19, 18, 18, 18}, - }, - { - {18, 18, 18, 18}, - {19, 18, 19, 18}, - {18, 19, 18, 18}, - {19, 18, 19, 18}, - }, - { - {18, 19, 18, 19}, - {19, 18, 19, 18}, - {18, 19, 18, 19}, - {19, 19, 19, 18}, - }, - { - {18, 19, 18, 19}, - {19, 19, 19, 19}, - {19, 19, 18, 19}, - {19, 19, 19, 19}, - }, - { - {19, 19, 19, 19}, - {19, 19, 19, 19}, - {19, 19, 19, 19}, - {20, 19, 19, 19}, - }, - { - {19, 19, 19, 19}, - {20, 19, 20, 19}, - {19, 20, 19, 19}, - {20, 19, 20, 19}, - }, - { - {19, 20, 19, 20}, - {20, 19, 20, 19}, - {19, 20, 19, 20}, - {20, 20, 20, 19}, - }, - { - {19, 20, 19, 20}, - {20, 20, 20, 20}, - {19, 20, 19, 20}, - {20, 20, 20, 20}, - }, - { - {20, 20, 20, 20}, - {20, 20, 20, 20}, - {20, 20, 20, 20}, - {20, 20, 20, 20}, - }, - { - {20, 20, 20, 20}, - {21, 20, 21, 20}, - {20, 20, 20, 20}, - {21, 20, 21, 20}, - }, - { - {20, 21, 20, 21}, - {21, 20, 21, 20}, - {20, 21, 20, 21}, - {21, 20, 21, 20}, - }, - { - {20, 21, 20, 21}, - {21, 21, 21, 21}, - {20, 21, 20, 21}, - {21, 21, 21, 21}, - }, - { - {21, 21, 21, 21}, - {21, 21, 21, 21}, - {21, 21, 21, 21}, - {21, 21, 21, 21}, - }, - { - {21, 21, 21, 21}, - {22, 21, 22, 21}, - {21, 21, 21, 21}, - {22, 21, 22, 21}, - }, - { - {21, 22, 21, 22}, - {22, 21, 22, 21}, - {21, 22, 21, 22}, - {22, 21, 22, 21}, - }, - { - {21, 22, 21, 22}, - {22, 22, 22, 22}, - {21, 22, 21, 22}, - {22, 22, 22, 22}, - }, - { - {22, 22, 22, 22}, - {22, 22, 22, 22}, - {22, 22, 22, 22}, - {22, 22, 22, 22}, - }, - { - {22, 22, 22, 22}, - {23, 22, 23, 22}, - {22, 22, 22, 22}, - {23, 22, 23, 22}, - }, - { - {22, 23, 22, 23}, - {23, 22, 23, 22}, - {22, 23, 22, 23}, - {23, 22, 23, 22}, - }, - { - {22, 23, 22, 23}, - {23, 23, 23, 23}, - {22, 23, 22, 23}, - {23, 23, 23, 23}, - }, - { - {23, 23, 23, 23}, - {23, 23, 23, 23}, - {23, 23, 23, 23}, - {23, 23, 23, 23}, - }, - { - {23, 23, 23, 23}, - {24, 23, 24, 23}, - {23, 23, 23, 23}, - {24, 23, 24, 23}, - }, - { - {23, 24, 23, 24}, - {24, 23, 24, 23}, - {23, 24, 23, 24}, - {24, 23, 24, 23}, - }, - { - {23, 24, 23, 24}, - {24, 23, 24, 24}, - {23, 24, 23, 24}, - {24, 24, 24, 24}, - }, - { - {23, 24, 24, 24}, - {24, 24, 24, 24}, - {24, 24, 24, 24}, - {24, 24, 24, 24}, - }, - { - {24, 24, 24, 24}, - {24, 24, 25, 24}, - {24, 24, 24, 24}, - {25, 24, 25, 24}, - }, - { - {24, 24, 24, 25}, - {25, 24, 25, 24}, - {24, 25, 24, 25}, - {25, 24, 25, 24}, - }, - { - {24, 25, 24, 25}, - {25, 24, 25, 25}, - {24, 25, 24, 25}, - {25, 25, 25, 25}, - }, - { - {24, 25, 25, 25}, - {25, 25, 25, 25}, - {25, 25, 25, 25}, - {25, 25, 25, 25}, - }, - { - {25, 25, 25, 25}, - {25, 25, 26, 25}, - {25, 25, 25, 25}, - {26, 25, 26, 25}, - }, - { - {25, 25, 25, 26}, - {26, 25, 26, 25}, - {25, 26, 25, 26}, - {26, 25, 26, 25}, - }, - { - {25, 26, 25, 26}, - {26, 25, 26, 26}, - {25, 26, 25, 26}, - {26, 26, 26, 26}, - }, - { - {25, 26, 26, 26}, - {26, 26, 26, 26}, - {26, 26, 26, 26}, - {26, 26, 26, 26}, - }, - { - {26, 26, 26, 26}, - {26, 26, 27, 26}, - {26, 26, 26, 26}, - {27, 26, 27, 26}, - }, - { - {26, 26, 26, 27}, - {27, 26, 27, 26}, - {26, 27, 26, 27}, - {27, 26, 27, 26}, - }, - { - {26, 27, 26, 27}, - {27, 26, 27, 27}, - {26, 27, 26, 27}, - {27, 27, 27, 27}, - }, - { - {26, 27, 27, 27}, - {27, 27, 27, 27}, - {27, 27, 27, 27}, - {27, 27, 27, 27}, - }, - { - {27, 27, 27, 27}, - {27, 27, 28, 27}, - {27, 27, 27, 27}, - {28, 27, 28, 27}, - }, - { - {27, 27, 27, 28}, - {28, 27, 28, 27}, - {27, 28, 27, 28}, - {28, 27, 28, 27}, - }, - { - {27, 28, 27, 28}, - {28, 27, 28, 28}, - {27, 28, 27, 28}, - {28, 28, 28, 27}, - }, - { - {27, 28, 28, 28}, - {28, 28, 28, 28}, - {28, 28, 27, 28}, - {28, 28, 28, 28}, - }, - { - {28, 28, 28, 28}, - {28, 28, 29, 28}, - {28, 28, 28, 28}, - {29, 28, 28, 28}, - }, - { - {28, 28, 28, 29}, - {29, 28, 29, 28}, - {28, 29, 28, 28}, - {29, 28, 29, 28}, - }, - { - {28, 29, 28, 29}, - {29, 28, 29, 29}, - {28, 29, 28, 29}, - {29, 29, 29, 28}, - }, - { - {28, 29, 29, 29}, - {29, 29, 29, 29}, - {29, 29, 28, 29}, - {29, 29, 29, 29}, - }, - { - {29, 29, 29, 29}, - {29, 29, 30, 29}, - {29, 29, 29, 29}, - {30, 29, 29, 29}, - }, - { - {29, 29, 29, 30}, - {30, 29, 30, 29}, - {29, 30, 29, 29}, - {30, 29, 30, 29}, - }, - { - {29, 30, 29, 30}, - {30, 29, 30, 30}, - {29, 30, 29, 30}, - {30, 30, 30, 29}, - }, - { - {29, 30, 30, 30}, - {30, 30, 30, 30}, - {30, 30, 29, 30}, - {30, 30, 30, 30}, - }, - { - {30, 30, 30, 30}, - {30, 30, 31, 30}, - {30, 30, 30, 30}, - {31, 30, 30, 30}, - }, - { - {30, 30, 30, 31}, - {31, 30, 31, 30}, - {30, 31, 30, 30}, - {31, 30, 31, 30}, - }, - { - {30, 31, 30, 31}, - {31, 30, 31, 31}, - {30, 31, 30, 31}, - {31, 31, 31, 30}, - }, - { - {30, 31, 31, 31}, - {31, 31, 31, 31}, - {31, 31, 30, 31}, - {31, 31, 31, 31}, - }, - { - {31, 31, 31, 31}, - {31, 31, 32, 31}, - {31, 31, 31, 31}, - {32, 31, 31, 31}, - }, - { - {31, 31, 31, 32}, - {32, 31, 32, 31}, - {31, 32, 31, 31}, - {32, 31, 32, 31}, - }, - { - {31, 32, 31, 32}, - {32, 31, 32, 32}, - {31, 32, 31, 32}, - {32, 32, 32, 31}, - }, - { - {31, 32, 32, 32}, - {32, 32, 32, 32}, - {32, 32, 31, 32}, - {32, 32, 32, 32}, - }, - { - {32, 32, 32, 32}, - {32, 32, 33, 32}, - {32, 32, 32, 32}, - {33, 32, 32, 32}, - }, - { - {32, 32, 32, 33}, - {33, 32, 33, 32}, - {32, 33, 32, 32}, - {33, 32, 33, 32}, - }, - { - {32, 33, 32, 33}, - {33, 32, 33, 33}, - {32, 33, 32, 33}, - {33, 33, 33, 32}, - }, - { - {32, 33, 33, 33}, - {33, 33, 33, 33}, - {33, 33, 32, 33}, - {33, 33, 33, 33}, - }, - { - {33, 33, 33, 33}, - {33, 33, 34, 33}, - {33, 33, 33, 33}, - {34, 33, 33, 33}, - }, - { - {33, 33, 33, 34}, - {34, 33, 34, 33}, - {33, 34, 33, 33}, - {34, 33, 34, 33}, - }, - { - {33, 34, 33, 34}, - {34, 33, 34, 34}, - {33, 34, 33, 34}, - {34, 34, 34, 33}, - }, - { - {33, 34, 34, 34}, - {34, 34, 34, 34}, - {34, 34, 33, 34}, - {34, 34, 34, 34}, - }, - { - {34, 34, 34, 34}, - {34, 34, 35, 34}, - {34, 34, 34, 34}, - {35, 34, 34, 34}, - }, - { - {34, 34, 34, 35}, - {35, 34, 35, 34}, - {34, 35, 34, 34}, - {35, 34, 35, 34}, - }, - { - {34, 35, 34, 35}, - {35, 34, 35, 35}, - {34, 35, 34, 35}, - {35, 35, 35, 34}, - }, - { - {34, 35, 35, 35}, - {35, 35, 35, 35}, - {35, 35, 34, 35}, - {35, 35, 35, 35}, - }, - { - {35, 35, 35, 35}, - {35, 35, 36, 35}, - {35, 35, 35, 35}, - {36, 35, 35, 35}, - }, - { - {35, 35, 35, 36}, - {36, 35, 36, 35}, - {35, 36, 35, 35}, - {36, 35, 36, 35}, - }, - { - {35, 36, 35, 36}, - {36, 35, 36, 35}, - {35, 36, 35, 36}, - {36, 36, 36, 35}, - }, - { - {35, 36, 35, 36}, - {36, 36, 36, 36}, - {36, 36, 35, 36}, - {36, 36, 36, 36}, - }, - { - {36, 36, 36, 36}, - {36, 36, 36, 36}, - {36, 36, 36, 36}, - {37, 36, 36, 36}, - }, - { - {36, 36, 36, 36}, - {37, 36, 37, 36}, - {36, 37, 36, 36}, - {37, 36, 37, 36}, - }, - { - {36, 37, 36, 37}, - {37, 36, 37, 36}, - {36, 37, 36, 37}, - {37, 37, 37, 36}, - }, - { - {36, 37, 36, 37}, - {37, 37, 37, 37}, - {37, 37, 36, 37}, - {37, 37, 37, 37}, - }, - { - {37, 37, 37, 37}, - {37, 37, 37, 37}, - {37, 37, 37, 37}, - {38, 37, 37, 37}, - }, - { - {37, 37, 37, 37}, - {38, 37, 38, 37}, - {37, 38, 37, 37}, - {38, 37, 38, 37}, - }, - { - {37, 38, 37, 38}, - {38, 37, 38, 37}, - {37, 38, 37, 38}, - {38, 38, 38, 37}, - }, - { - {37, 38, 37, 38}, - {38, 38, 38, 38}, - {38, 38, 37, 38}, - {38, 38, 38, 38}, - }, - { - {38, 38, 38, 38}, - {38, 38, 38, 38}, - {38, 38, 38, 38}, - {39, 38, 38, 38}, - }, - { - {38, 38, 38, 38}, - {39, 38, 39, 38}, - {38, 39, 38, 38}, - {39, 38, 39, 38}, - }, - { - {38, 39, 38, 39}, - {39, 38, 39, 38}, - {38, 39, 38, 39}, - {39, 39, 39, 38}, - }, - { - {38, 39, 38, 39}, - {39, 39, 39, 39}, - {39, 39, 38, 39}, - {39, 39, 39, 39}, - }, - { - {39, 39, 39, 39}, - {39, 39, 39, 39}, - {39, 39, 39, 39}, - {40, 39, 39, 39}, - }, - { - {39, 39, 39, 39}, - {40, 39, 40, 39}, - {39, 40, 39, 39}, - {40, 39, 40, 39}, - }, - { - {39, 40, 39, 40}, - {40, 39, 40, 39}, - {39, 40, 39, 40}, - {40, 39, 40, 39}, - }, - { - {39, 40, 39, 40}, - {40, 40, 40, 40}, - {39, 40, 39, 40}, - {40, 40, 40, 40}, - }, - { - {40, 40, 40, 40}, - {40, 40, 40, 40}, - {40, 40, 40, 40}, - {40, 40, 40, 40}, - }, - { - {40, 40, 40, 40}, - {41, 40, 41, 40}, - {40, 40, 40, 40}, - {41, 40, 41, 40}, - }, - { - {40, 41, 40, 41}, - {41, 40, 41, 40}, - {40, 41, 40, 41}, - {41, 40, 41, 40}, - }, - { - {40, 41, 40, 41}, - {41, 41, 41, 41}, - {40, 41, 40, 41}, - {41, 41, 41, 41}, - }, - { - {41, 41, 41, 41}, - {41, 41, 41, 41}, - {41, 41, 41, 41}, - {41, 41, 41, 41}, - }, - { - {41, 41, 41, 41}, - {42, 41, 42, 41}, - {41, 41, 41, 41}, - {42, 41, 42, 41}, - }, - { - {41, 42, 41, 42}, - {42, 41, 42, 41}, - {41, 42, 41, 42}, - {42, 41, 42, 41}, - }, - { - {41, 42, 41, 42}, - {42, 42, 42, 42}, - {41, 42, 41, 42}, - {42, 42, 42, 42}, - }, - { - {42, 42, 42, 42}, - {42, 42, 42, 42}, - {42, 42, 42, 42}, - {42, 42, 42, 42}, - }, - { - {42, 42, 42, 42}, - {43, 42, 43, 42}, - {42, 42, 42, 42}, - {43, 42, 43, 42}, - }, - { - {42, 43, 42, 43}, - {43, 42, 43, 42}, - {42, 43, 42, 43}, - {43, 42, 43, 42}, - }, - { - {42, 43, 42, 43}, - {43, 43, 43, 43}, - {42, 43, 42, 43}, - {43, 43, 43, 43}, - }, - { - {43, 43, 43, 43}, - {43, 43, 43, 43}, - {43, 43, 43, 43}, - {43, 43, 43, 43}, - }, - { - {43, 43, 43, 43}, - {44, 43, 44, 43}, - {43, 43, 43, 43}, - {44, 43, 44, 43}, - }, - { - {43, 43, 43, 44}, - {44, 43, 44, 43}, - {43, 44, 43, 44}, - {44, 43, 44, 43}, - }, - { - {43, 44, 43, 44}, - {44, 43, 44, 44}, - {43, 44, 43, 44}, - {44, 44, 44, 44}, - }, - { - {43, 44, 44, 44}, - {44, 44, 44, 44}, - {44, 44, 44, 44}, - {44, 44, 44, 44}, - }, - { - {44, 44, 44, 44}, - {44, 44, 45, 44}, - {44, 44, 44, 44}, - {45, 44, 45, 44}, - }, - { - {44, 44, 44, 45}, - {45, 44, 45, 44}, - {44, 45, 44, 45}, - {45, 44, 45, 44}, - }, - { - {44, 45, 44, 45}, - {45, 44, 45, 45}, - {44, 45, 44, 45}, - {45, 45, 45, 45}, - }, - { - {44, 45, 45, 45}, - {45, 45, 45, 45}, - {45, 45, 45, 45}, - {45, 45, 45, 45}, - }, - { - {45, 45, 45, 45}, - {45, 45, 46, 45}, - {45, 45, 45, 45}, - {46, 45, 46, 45}, - }, - { - {45, 45, 45, 46}, - {46, 45, 46, 45}, - {45, 46, 45, 46}, - {46, 45, 46, 45}, - }, - { - {45, 46, 45, 46}, - {46, 45, 46, 46}, - {45, 46, 45, 46}, - {46, 46, 46, 46}, - }, - { - {45, 46, 46, 46}, - {46, 46, 46, 46}, - {46, 46, 46, 46}, - {46, 46, 46, 46}, - }, - { - {46, 46, 46, 46}, - {46, 46, 47, 46}, - {46, 46, 46, 46}, - {47, 46, 47, 46}, - }, - { - {46, 46, 46, 47}, - {47, 46, 47, 46}, - {46, 47, 46, 47}, - {47, 46, 47, 46}, - }, - { - {46, 47, 46, 47}, - {47, 46, 47, 47}, - {46, 47, 46, 47}, - {47, 47, 47, 47}, - }, - { - {46, 47, 47, 47}, - {47, 47, 47, 47}, - {47, 47, 47, 47}, - {47, 47, 47, 47}, - }, - { - {47, 47, 47, 47}, - {47, 47, 48, 47}, - {47, 47, 47, 47}, - {48, 47, 48, 47}, - }, - { - {47, 47, 47, 48}, - {48, 47, 48, 47}, - {47, 48, 47, 48}, - {48, 47, 48, 47}, - }, - { - {47, 48, 47, 48}, - {48, 47, 48, 48}, - {47, 48, 47, 48}, - {48, 48, 48, 48}, - }, - { - {47, 48, 48, 48}, - {48, 48, 48, 48}, - {48, 48, 48, 48}, - {48, 48, 48, 48}, - }, - { - {48, 48, 48, 48}, - {48, 48, 49, 48}, - {48, 48, 48, 48}, - {49, 48, 49, 48}, - }, - { - {48, 48, 48, 49}, - {49, 48, 49, 48}, - {48, 49, 48, 49}, - {49, 48, 49, 48}, - }, - { - {48, 49, 48, 49}, - {49, 48, 49, 49}, - {48, 49, 48, 49}, - {49, 49, 49, 49}, - }, - { - {48, 49, 49, 49}, - {49, 49, 49, 49}, - {49, 49, 49, 49}, - {49, 49, 49, 49}, - }, - { - {49, 49, 49, 49}, - {49, 49, 50, 49}, - {49, 49, 49, 49}, - {50, 49, 50, 49}, - }, - { - {49, 49, 49, 50}, - {50, 49, 50, 49}, - {49, 50, 49, 50}, - {50, 49, 50, 49}, - }, - { - {49, 50, 49, 50}, - {50, 49, 50, 50}, - {49, 50, 49, 50}, - {50, 50, 50, 50}, - }, - { - {49, 50, 50, 50}, - {50, 50, 50, 50}, - {50, 50, 50, 50}, - {50, 50, 50, 50}, - }, - { - {50, 50, 50, 50}, - {50, 50, 51, 50}, - {50, 50, 50, 50}, - {51, 50, 51, 50}, - }, - { - {50, 50, 50, 51}, - {51, 50, 51, 50}, - {50, 51, 50, 51}, - {51, 50, 51, 50}, - }, - { - {50, 51, 50, 51}, - {51, 50, 51, 51}, - {50, 51, 50, 51}, - {51, 51, 51, 51}, - }, - { - {50, 51, 51, 51}, - {51, 51, 51, 51}, - {51, 51, 51, 51}, - {51, 51, 51, 51}, - }, - { - {51, 51, 51, 51}, - {51, 51, 52, 51}, - {51, 51, 51, 51}, - {52, 51, 52, 51}, - }, - { - {51, 51, 51, 52}, - {52, 51, 52, 51}, - {51, 52, 51, 51}, - {52, 51, 52, 51}, - }, - { - {51, 52, 51, 52}, - {52, 51, 52, 52}, - {51, 52, 51, 52}, - {52, 52, 52, 51}, - }, - { - {51, 52, 52, 52}, - {52, 52, 52, 52}, - {52, 52, 51, 52}, - {52, 52, 52, 52}, - }, - { - {52, 52, 52, 52}, - {52, 52, 53, 52}, - {52, 52, 52, 52}, - {53, 52, 52, 52}, - }, - { - {52, 52, 52, 53}, - {53, 52, 53, 52}, - {52, 53, 52, 52}, - {53, 52, 53, 52}, - }, - { - {52, 53, 52, 53}, - {53, 52, 53, 53}, - {52, 53, 52, 53}, - {53, 53, 53, 52}, - }, - { - {52, 53, 53, 53}, - {53, 53, 53, 53}, - {53, 53, 52, 53}, - {53, 53, 53, 53}, - }, - { - {53, 53, 53, 53}, - {53, 53, 54, 53}, - {53, 53, 53, 53}, - {54, 53, 53, 53}, - }, - { - {53, 53, 53, 54}, - {54, 53, 54, 53}, - {53, 54, 53, 53}, - {54, 53, 54, 53}, - }, - { - {53, 54, 53, 54}, - {54, 53, 54, 54}, - {53, 54, 53, 54}, - {54, 54, 54, 53}, - }, - { - {53, 54, 54, 54}, - {54, 54, 54, 54}, - {54, 54, 53, 54}, - {54, 54, 54, 54}, - }, - { - {54, 54, 54, 54}, - {54, 54, 55, 54}, - {54, 54, 54, 54}, - {55, 54, 54, 54}, - }, - { - {54, 54, 54, 55}, - {55, 54, 55, 54}, - {54, 55, 54, 54}, - {55, 54, 55, 54}, - }, - { - {54, 55, 54, 55}, - {55, 54, 55, 55}, - {54, 55, 54, 55}, - {55, 55, 55, 54}, - }, - { - {54, 55, 55, 55}, - {55, 55, 55, 55}, - {55, 55, 54, 55}, - {55, 55, 55, 55}, - }, - { - {55, 55, 55, 55}, - {55, 55, 56, 55}, - {55, 55, 55, 55}, - {56, 55, 55, 55}, - }, - { - {55, 55, 55, 55}, - {56, 55, 56, 55}, - {55, 56, 55, 55}, - {56, 55, 56, 55}, - }, - { - {55, 56, 55, 56}, - {56, 55, 56, 55}, - {55, 56, 55, 56}, - {56, 56, 56, 55}, - }, - { - {55, 56, 55, 56}, - {56, 56, 56, 56}, - {56, 56, 55, 56}, - {56, 56, 56, 56}, - }, - { - {56, 56, 56, 56}, - {56, 56, 56, 56}, - {56, 56, 56, 56}, - {57, 56, 56, 56}, - }, - { - {56, 56, 56, 56}, - {57, 56, 57, 56}, - {56, 57, 56, 56}, - {57, 56, 57, 56}, - }, - { - {56, 57, 56, 57}, - {57, 56, 57, 56}, - {56, 57, 56, 57}, - {57, 57, 57, 56}, - }, - { - {56, 57, 56, 57}, - {57, 57, 57, 57}, - {57, 57, 56, 57}, - {57, 57, 57, 57}, - }, - { - {57, 57, 57, 57}, - {57, 57, 57, 57}, - {57, 57, 57, 57}, - {58, 57, 57, 57}, - }, - { - {57, 57, 57, 57}, - {58, 57, 58, 57}, - {57, 58, 57, 57}, - {58, 57, 58, 57}, - }, - { - {57, 58, 57, 58}, - {58, 57, 58, 57}, - {57, 58, 57, 58}, - {58, 58, 58, 57}, - }, - { - {57, 58, 57, 58}, - {58, 58, 58, 58}, - {58, 58, 57, 58}, - {58, 58, 58, 58}, - }, - { - {58, 58, 58, 58}, - {58, 58, 58, 58}, - {58, 58, 58, 58}, - {59, 58, 58, 58}, - }, - { - {58, 58, 58, 58}, - {59, 58, 59, 58}, - {58, 59, 58, 58}, - {59, 58, 59, 58}, - }, - { - {58, 59, 58, 59}, - {59, 58, 59, 58}, - {58, 59, 58, 59}, - {59, 59, 59, 58}, - }, - { - {58, 59, 58, 59}, - {59, 59, 59, 59}, - {59, 59, 58, 59}, - {59, 59, 59, 59}, - }, - { - {59, 59, 59, 59}, - {59, 59, 59, 59}, - {59, 59, 59, 59}, - {60, 59, 59, 59}, - }, - { - {59, 59, 59, 59}, - {60, 59, 60, 59}, - {59, 59, 59, 59}, - {60, 59, 60, 59}, - }, - { - {59, 60, 59, 60}, - {60, 59, 60, 59}, - {59, 60, 59, 60}, - {60, 59, 60, 59}, - }, - { - {59, 60, 59, 60}, - {60, 60, 60, 60}, - {59, 60, 59, 60}, - {60, 60, 60, 60}, - }, - { - {60, 60, 60, 60}, - {60, 60, 60, 60}, - {60, 60, 60, 60}, - {60, 60, 60, 60}, - }, - { - {60, 60, 60, 60}, - {61, 60, 61, 60}, - {60, 60, 60, 60}, - {61, 60, 61, 60}, - }, - { - {60, 61, 60, 61}, - {61, 60, 61, 60}, - {60, 61, 60, 61}, - {61, 60, 61, 60}, - }, - { - {60, 61, 60, 61}, - {61, 61, 61, 61}, - {60, 61, 60, 61}, - {61, 61, 61, 61}, - }, - { - {61, 61, 61, 61}, - {61, 61, 61, 61}, - {61, 61, 61, 61}, - {61, 61, 61, 61}, - }, - { - {61, 61, 61, 61}, - {62, 61, 62, 61}, - {61, 61, 61, 61}, - {62, 61, 62, 61}, - }, - { - {61, 62, 61, 62}, - {62, 61, 62, 61}, - {61, 62, 61, 62}, - {62, 61, 62, 61}, - }, - { - {61, 62, 61, 62}, - {62, 62, 62, 62}, - {61, 62, 61, 62}, - {62, 62, 62, 62}, - }, - { - {62, 62, 62, 62}, - {62, 62, 62, 62}, - {62, 62, 62, 62}, - {62, 62, 62, 62}, - }, - { - {62, 62, 62, 62}, - {63, 62, 63, 62}, - {62, 62, 62, 62}, - {63, 62, 63, 62}, - }, - { - {62, 63, 62, 63}, - {63, 62, 63, 62}, - {62, 63, 62, 63}, - {63, 62, 63, 62}, - }, - { - {62, 63, 62, 63}, - {63, 63, 63, 63}, - {62, 63, 62, 63}, - {63, 63, 63, 63}, - }, - { - {63, 63, 63, 63}, - {63, 63, 63, 63}, - {63, 63, 63, 63}, - {63, 63, 63, 63}, - }, +static const uint8_t dither_g[256][4][4] = { + { + {0, 0, 0, 0}, + {0, 0, 0, 0}, + {0, 0, 0, 0}, + {0, 0, 0, 0}, + }, + { + {0, 0, 0, 0}, + {1, 0, 1, 0}, + {0, 0, 0, 0}, + {1, 0, 1, 0}, + }, + { + {0, 1, 0, 1}, + {1, 0, 1, 0}, + {0, 1, 0, 1}, + {1, 0, 1, 0}, + }, + { + {0, 1, 0, 1}, + {1, 1, 1, 1}, + {0, 1, 0, 1}, + {1, 1, 1, 1}, + }, + { + {1, 1, 1, 1}, + {1, 1, 1, 1}, + {1, 1, 1, 1}, + {1, 1, 1, 1}, + }, + { + {1, 1, 1, 1}, + {2, 1, 2, 1}, + {1, 1, 1, 1}, + {2, 1, 2, 1}, + }, + { + {1, 2, 1, 2}, + {2, 1, 2, 1}, + {1, 2, 1, 2}, + {2, 1, 2, 1}, + }, + { + {1, 2, 1, 2}, + {2, 2, 2, 2}, + {1, 2, 1, 2}, + {2, 2, 2, 2}, + }, + { + {2, 2, 2, 2}, + {2, 2, 2, 2}, + {2, 2, 2, 2}, + {2, 2, 2, 2}, + }, + { + {2, 2, 2, 2}, + {3, 2, 3, 2}, + {2, 2, 2, 2}, + {3, 2, 3, 2}, + }, + { + {2, 3, 2, 3}, + {3, 2, 3, 2}, + {2, 3, 2, 3}, + {3, 2, 3, 2}, + }, + { + {2, 3, 2, 3}, + {3, 3, 3, 3}, + {2, 3, 2, 3}, + {3, 3, 3, 3}, + }, + { + {3, 3, 3, 3}, + {3, 3, 3, 3}, + {3, 3, 3, 3}, + {3, 3, 3, 3}, + }, + { + {3, 3, 3, 3}, + {4, 3, 4, 3}, + {3, 3, 3, 3}, + {4, 3, 4, 3}, + }, + { + {3, 4, 3, 4}, + {4, 3, 4, 3}, + {3, 4, 3, 4}, + {4, 3, 4, 3}, + }, + { + {3, 4, 3, 4}, + {4, 4, 4, 4}, + {3, 4, 3, 4}, + {4, 4, 4, 4}, + }, + { + {3, 4, 4, 4}, + {4, 4, 4, 4}, + {4, 4, 4, 4}, + {4, 4, 4, 4}, + }, + { + {4, 4, 4, 4}, + {4, 4, 5, 4}, + {4, 4, 4, 4}, + {5, 4, 5, 4}, + }, + { + {4, 4, 4, 5}, + {5, 4, 5, 4}, + {4, 5, 4, 5}, + {5, 4, 5, 4}, + }, + { + {4, 5, 4, 5}, + {5, 4, 5, 5}, + {4, 5, 4, 5}, + {5, 5, 5, 5}, + }, + { + {4, 5, 5, 5}, + {5, 5, 5, 5}, + {5, 5, 5, 5}, + {5, 5, 5, 5}, + }, + { + {5, 5, 5, 5}, + {5, 5, 6, 5}, + {5, 5, 5, 5}, + {6, 5, 6, 5}, + }, + { + {5, 5, 5, 6}, + {6, 5, 6, 5}, + {5, 6, 5, 6}, + {6, 5, 6, 5}, + }, + { + {5, 6, 5, 6}, + {6, 5, 6, 6}, + {5, 6, 5, 6}, + {6, 6, 6, 6}, + }, + { + {5, 6, 6, 6}, + {6, 6, 6, 6}, + {6, 6, 6, 6}, + {6, 6, 6, 6}, + }, + { + {6, 6, 6, 6}, + {6, 6, 7, 6}, + {6, 6, 6, 6}, + {7, 6, 7, 6}, + }, + { + {6, 6, 6, 7}, + {7, 6, 7, 6}, + {6, 7, 6, 7}, + {7, 6, 7, 6}, + }, + { + {6, 7, 6, 7}, + {7, 6, 7, 7}, + {6, 7, 6, 7}, + {7, 7, 7, 7}, + }, + { + {6, 7, 7, 7}, + {7, 7, 7, 7}, + {7, 7, 7, 7}, + {7, 7, 7, 7}, + }, + { + {7, 7, 7, 7}, + {7, 7, 8, 7}, + {7, 7, 7, 7}, + {8, 7, 8, 7}, + }, + { + {7, 7, 7, 8}, + {8, 7, 8, 7}, + {7, 8, 7, 8}, + {8, 7, 8, 7}, + }, + { + {7, 8, 7, 8}, + {8, 7, 8, 8}, + {7, 8, 7, 8}, + {8, 8, 8, 8}, + }, + { + {7, 8, 8, 8}, + {8, 8, 8, 8}, + {8, 8, 7, 8}, + {8, 8, 8, 8}, + }, + { + {8, 8, 8, 8}, + {8, 8, 9, 8}, + {8, 8, 8, 8}, + {9, 8, 8, 8}, + }, + { + {8, 8, 8, 9}, + {9, 8, 9, 8}, + {8, 9, 8, 8}, + {9, 8, 9, 8}, + }, + { + {8, 9, 8, 9}, + {9, 8, 9, 9}, + {8, 9, 8, 9}, + {9, 9, 9, 8}, + }, + { + {8, 9, 9, 9}, + {9, 9, 9, 9}, + {9, 9, 8, 9}, + {9, 9, 9, 9}, + }, + { + {9, 9, 9, 9}, + {9, 9, 10, 9}, + {9, 9, 9, 9}, + {10, 9, 9, 9}, + }, + { + {9, 9, 9, 10}, + {10, 9, 10, 9}, + {9, 10, 9, 9}, + {10, 9, 10, 9}, + }, + { + {9, 10, 9, 10}, + {10, 9, 10, 10}, + {9, 10, 9, 10}, + {10, 10, 10, 9}, + }, + { + {9, 10, 10, 10}, + {10, 10, 10, 10}, + {10, 10, 9, 10}, + {10, 10, 10, 10}, + }, + { + {10, 10, 10, 10}, + {10, 10, 11, 10}, + {10, 10, 10, 10}, + {11, 10, 10, 10}, + }, + { + {10, 10, 10, 11}, + {11, 10, 11, 10}, + {10, 11, 10, 10}, + {11, 10, 11, 10}, + }, + { + {10, 11, 10, 11}, + {11, 10, 11, 11}, + {10, 11, 10, 11}, + {11, 11, 11, 10}, + }, + { + {10, 11, 11, 11}, + {11, 11, 11, 11}, + {11, 11, 10, 11}, + {11, 11, 11, 11}, + }, + { + {11, 11, 11, 11}, + {11, 11, 12, 11}, + {11, 11, 11, 11}, + {12, 11, 11, 11}, + }, + { + {11, 11, 11, 12}, + {12, 11, 12, 11}, + {11, 12, 11, 11}, + {12, 11, 12, 11}, + }, + { + {11, 12, 11, 12}, + {12, 11, 12, 12}, + {11, 12, 11, 12}, + {12, 12, 12, 11}, + }, + { + {11, 12, 11, 12}, + {12, 12, 12, 12}, + {12, 12, 11, 12}, + {12, 12, 12, 12}, + }, + { + {12, 12, 12, 12}, + {12, 12, 12, 12}, + {12, 12, 12, 12}, + {13, 12, 12, 12}, + }, + { + {12, 12, 12, 12}, + {13, 12, 13, 12}, + {12, 13, 12, 12}, + {13, 12, 13, 12}, + }, + { + {12, 13, 12, 13}, + {13, 12, 13, 12}, + {12, 13, 12, 13}, + {13, 13, 13, 12}, + }, + { + {12, 13, 12, 13}, + {13, 13, 13, 13}, + {13, 13, 12, 13}, + {13, 13, 13, 13}, + }, + { + {13, 13, 13, 13}, + {13, 13, 13, 13}, + {13, 13, 13, 13}, + {14, 13, 13, 13}, + }, + { + {13, 13, 13, 13}, + {14, 13, 14, 13}, + {13, 14, 13, 13}, + {14, 13, 14, 13}, + }, + { + {13, 14, 13, 14}, + {14, 13, 14, 13}, + {13, 14, 13, 14}, + {14, 14, 14, 13}, + }, + { + {13, 14, 13, 14}, + {14, 14, 14, 14}, + {14, 14, 13, 14}, + {14, 14, 14, 14}, + }, + { + {14, 14, 14, 14}, + {14, 14, 14, 14}, + {14, 14, 14, 14}, + {15, 14, 14, 14}, + }, + { + {14, 14, 14, 14}, + {15, 14, 15, 14}, + {14, 15, 14, 14}, + {15, 14, 15, 14}, + }, + { + {14, 15, 14, 15}, + {15, 14, 15, 14}, + {14, 15, 14, 15}, + {15, 15, 15, 14}, + }, + { + {14, 15, 14, 15}, + {15, 15, 15, 15}, + {15, 15, 14, 15}, + {15, 15, 15, 15}, + }, + { + {15, 15, 15, 15}, + {15, 15, 15, 15}, + {15, 15, 15, 15}, + {16, 15, 15, 15}, + }, + { + {15, 15, 15, 15}, + {16, 15, 16, 15}, + {15, 16, 15, 15}, + {16, 15, 16, 15}, + }, + { + {15, 16, 15, 16}, + {16, 15, 16, 15}, + {15, 16, 15, 16}, + {16, 16, 16, 15}, + }, + { + {15, 16, 15, 16}, + {16, 16, 16, 16}, + {16, 16, 15, 16}, + {16, 16, 16, 16}, + }, + { + {16, 16, 16, 16}, + {16, 16, 16, 16}, + {16, 16, 16, 16}, + {17, 16, 16, 16}, + }, + { + {16, 16, 16, 16}, + {17, 16, 17, 16}, + {16, 17, 16, 16}, + {17, 16, 17, 16}, + }, + { + {16, 17, 16, 17}, + {17, 16, 17, 16}, + {16, 17, 16, 17}, + {17, 17, 17, 16}, + }, + { + {16, 17, 16, 17}, + {17, 17, 17, 17}, + {17, 17, 16, 17}, + {17, 17, 17, 17}, + }, + { + {17, 17, 17, 17}, + {17, 17, 17, 17}, + {17, 17, 17, 17}, + {18, 17, 17, 17}, + }, + { + {17, 17, 17, 17}, + {18, 17, 18, 17}, + {17, 18, 17, 17}, + {18, 17, 18, 17}, + }, + { + {17, 18, 17, 18}, + {18, 17, 18, 17}, + {17, 18, 17, 18}, + {18, 18, 18, 17}, + }, + { + {17, 18, 17, 18}, + {18, 18, 18, 18}, + {18, 18, 17, 18}, + {18, 18, 18, 18}, + }, + { + {18, 18, 18, 18}, + {18, 18, 18, 18}, + {18, 18, 18, 18}, + {19, 18, 18, 18}, + }, + { + {18, 18, 18, 18}, + {19, 18, 19, 18}, + {18, 19, 18, 18}, + {19, 18, 19, 18}, + }, + { + {18, 19, 18, 19}, + {19, 18, 19, 18}, + {18, 19, 18, 19}, + {19, 19, 19, 18}, + }, + { + {18, 19, 18, 19}, + {19, 19, 19, 19}, + {19, 19, 18, 19}, + {19, 19, 19, 19}, + }, + { + {19, 19, 19, 19}, + {19, 19, 19, 19}, + {19, 19, 19, 19}, + {20, 19, 19, 19}, + }, + { + {19, 19, 19, 19}, + {20, 19, 20, 19}, + {19, 20, 19, 19}, + {20, 19, 20, 19}, + }, + { + {19, 20, 19, 20}, + {20, 19, 20, 19}, + {19, 20, 19, 20}, + {20, 20, 20, 19}, + }, + { + {19, 20, 19, 20}, + {20, 20, 20, 20}, + {19, 20, 19, 20}, + {20, 20, 20, 20}, + }, + { + {20, 20, 20, 20}, + {20, 20, 20, 20}, + {20, 20, 20, 20}, + {20, 20, 20, 20}, + }, + { + {20, 20, 20, 20}, + {21, 20, 21, 20}, + {20, 20, 20, 20}, + {21, 20, 21, 20}, + }, + { + {20, 21, 20, 21}, + {21, 20, 21, 20}, + {20, 21, 20, 21}, + {21, 20, 21, 20}, + }, + { + {20, 21, 20, 21}, + {21, 21, 21, 21}, + {20, 21, 20, 21}, + {21, 21, 21, 21}, + }, + { + {21, 21, 21, 21}, + {21, 21, 21, 21}, + {21, 21, 21, 21}, + {21, 21, 21, 21}, + }, + { + {21, 21, 21, 21}, + {22, 21, 22, 21}, + {21, 21, 21, 21}, + {22, 21, 22, 21}, + }, + { + {21, 22, 21, 22}, + {22, 21, 22, 21}, + {21, 22, 21, 22}, + {22, 21, 22, 21}, + }, + { + {21, 22, 21, 22}, + {22, 22, 22, 22}, + {21, 22, 21, 22}, + {22, 22, 22, 22}, + }, + { + {22, 22, 22, 22}, + {22, 22, 22, 22}, + {22, 22, 22, 22}, + {22, 22, 22, 22}, + }, + { + {22, 22, 22, 22}, + {23, 22, 23, 22}, + {22, 22, 22, 22}, + {23, 22, 23, 22}, + }, + { + {22, 23, 22, 23}, + {23, 22, 23, 22}, + {22, 23, 22, 23}, + {23, 22, 23, 22}, + }, + { + {22, 23, 22, 23}, + {23, 23, 23, 23}, + {22, 23, 22, 23}, + {23, 23, 23, 23}, + }, + { + {23, 23, 23, 23}, + {23, 23, 23, 23}, + {23, 23, 23, 23}, + {23, 23, 23, 23}, + }, + { + {23, 23, 23, 23}, + {24, 23, 24, 23}, + {23, 23, 23, 23}, + {24, 23, 24, 23}, + }, + { + {23, 24, 23, 24}, + {24, 23, 24, 23}, + {23, 24, 23, 24}, + {24, 23, 24, 23}, + }, + { + {23, 24, 23, 24}, + {24, 23, 24, 24}, + {23, 24, 23, 24}, + {24, 24, 24, 24}, + }, + { + {23, 24, 24, 24}, + {24, 24, 24, 24}, + {24, 24, 24, 24}, + {24, 24, 24, 24}, + }, + { + {24, 24, 24, 24}, + {24, 24, 25, 24}, + {24, 24, 24, 24}, + {25, 24, 25, 24}, + }, + { + {24, 24, 24, 25}, + {25, 24, 25, 24}, + {24, 25, 24, 25}, + {25, 24, 25, 24}, + }, + { + {24, 25, 24, 25}, + {25, 24, 25, 25}, + {24, 25, 24, 25}, + {25, 25, 25, 25}, + }, + { + {24, 25, 25, 25}, + {25, 25, 25, 25}, + {25, 25, 25, 25}, + {25, 25, 25, 25}, + }, + { + {25, 25, 25, 25}, + {25, 25, 26, 25}, + {25, 25, 25, 25}, + {26, 25, 26, 25}, + }, + { + {25, 25, 25, 26}, + {26, 25, 26, 25}, + {25, 26, 25, 26}, + {26, 25, 26, 25}, + }, + { + {25, 26, 25, 26}, + {26, 25, 26, 26}, + {25, 26, 25, 26}, + {26, 26, 26, 26}, + }, + { + {25, 26, 26, 26}, + {26, 26, 26, 26}, + {26, 26, 26, 26}, + {26, 26, 26, 26}, + }, + { + {26, 26, 26, 26}, + {26, 26, 27, 26}, + {26, 26, 26, 26}, + {27, 26, 27, 26}, + }, + { + {26, 26, 26, 27}, + {27, 26, 27, 26}, + {26, 27, 26, 27}, + {27, 26, 27, 26}, + }, + { + {26, 27, 26, 27}, + {27, 26, 27, 27}, + {26, 27, 26, 27}, + {27, 27, 27, 27}, + }, + { + {26, 27, 27, 27}, + {27, 27, 27, 27}, + {27, 27, 27, 27}, + {27, 27, 27, 27}, + }, + { + {27, 27, 27, 27}, + {27, 27, 28, 27}, + {27, 27, 27, 27}, + {28, 27, 28, 27}, + }, + { + {27, 27, 27, 28}, + {28, 27, 28, 27}, + {27, 28, 27, 28}, + {28, 27, 28, 27}, + }, + { + {27, 28, 27, 28}, + {28, 27, 28, 28}, + {27, 28, 27, 28}, + {28, 28, 28, 27}, + }, + { + {27, 28, 28, 28}, + {28, 28, 28, 28}, + {28, 28, 27, 28}, + {28, 28, 28, 28}, + }, + { + {28, 28, 28, 28}, + {28, 28, 29, 28}, + {28, 28, 28, 28}, + {29, 28, 28, 28}, + }, + { + {28, 28, 28, 29}, + {29, 28, 29, 28}, + {28, 29, 28, 28}, + {29, 28, 29, 28}, + }, + { + {28, 29, 28, 29}, + {29, 28, 29, 29}, + {28, 29, 28, 29}, + {29, 29, 29, 28}, + }, + { + {28, 29, 29, 29}, + {29, 29, 29, 29}, + {29, 29, 28, 29}, + {29, 29, 29, 29}, + }, + { + {29, 29, 29, 29}, + {29, 29, 30, 29}, + {29, 29, 29, 29}, + {30, 29, 29, 29}, + }, + { + {29, 29, 29, 30}, + {30, 29, 30, 29}, + {29, 30, 29, 29}, + {30, 29, 30, 29}, + }, + { + {29, 30, 29, 30}, + {30, 29, 30, 30}, + {29, 30, 29, 30}, + {30, 30, 30, 29}, + }, + { + {29, 30, 30, 30}, + {30, 30, 30, 30}, + {30, 30, 29, 30}, + {30, 30, 30, 30}, + }, + { + {30, 30, 30, 30}, + {30, 30, 31, 30}, + {30, 30, 30, 30}, + {31, 30, 30, 30}, + }, + { + {30, 30, 30, 31}, + {31, 30, 31, 30}, + {30, 31, 30, 30}, + {31, 30, 31, 30}, + }, + { + {30, 31, 30, 31}, + {31, 30, 31, 31}, + {30, 31, 30, 31}, + {31, 31, 31, 30}, + }, + { + {30, 31, 31, 31}, + {31, 31, 31, 31}, + {31, 31, 30, 31}, + {31, 31, 31, 31}, + }, + { + {31, 31, 31, 31}, + {31, 31, 32, 31}, + {31, 31, 31, 31}, + {32, 31, 31, 31}, + }, + { + {31, 31, 31, 32}, + {32, 31, 32, 31}, + {31, 32, 31, 31}, + {32, 31, 32, 31}, + }, + { + {31, 32, 31, 32}, + {32, 31, 32, 32}, + {31, 32, 31, 32}, + {32, 32, 32, 31}, + }, + { + {31, 32, 32, 32}, + {32, 32, 32, 32}, + {32, 32, 31, 32}, + {32, 32, 32, 32}, + }, + { + {32, 32, 32, 32}, + {32, 32, 33, 32}, + {32, 32, 32, 32}, + {33, 32, 32, 32}, + }, + { + {32, 32, 32, 33}, + {33, 32, 33, 32}, + {32, 33, 32, 32}, + {33, 32, 33, 32}, + }, + { + {32, 33, 32, 33}, + {33, 32, 33, 33}, + {32, 33, 32, 33}, + {33, 33, 33, 32}, + }, + { + {32, 33, 33, 33}, + {33, 33, 33, 33}, + {33, 33, 32, 33}, + {33, 33, 33, 33}, + }, + { + {33, 33, 33, 33}, + {33, 33, 34, 33}, + {33, 33, 33, 33}, + {34, 33, 33, 33}, + }, + { + {33, 33, 33, 34}, + {34, 33, 34, 33}, + {33, 34, 33, 33}, + {34, 33, 34, 33}, + }, + { + {33, 34, 33, 34}, + {34, 33, 34, 34}, + {33, 34, 33, 34}, + {34, 34, 34, 33}, + }, + { + {33, 34, 34, 34}, + {34, 34, 34, 34}, + {34, 34, 33, 34}, + {34, 34, 34, 34}, + }, + { + {34, 34, 34, 34}, + {34, 34, 35, 34}, + {34, 34, 34, 34}, + {35, 34, 34, 34}, + }, + { + {34, 34, 34, 35}, + {35, 34, 35, 34}, + {34, 35, 34, 34}, + {35, 34, 35, 34}, + }, + { + {34, 35, 34, 35}, + {35, 34, 35, 35}, + {34, 35, 34, 35}, + {35, 35, 35, 34}, + }, + { + {34, 35, 35, 35}, + {35, 35, 35, 35}, + {35, 35, 34, 35}, + {35, 35, 35, 35}, + }, + { + {35, 35, 35, 35}, + {35, 35, 36, 35}, + {35, 35, 35, 35}, + {36, 35, 35, 35}, + }, + { + {35, 35, 35, 36}, + {36, 35, 36, 35}, + {35, 36, 35, 35}, + {36, 35, 36, 35}, + }, + { + {35, 36, 35, 36}, + {36, 35, 36, 35}, + {35, 36, 35, 36}, + {36, 36, 36, 35}, + }, + { + {35, 36, 35, 36}, + {36, 36, 36, 36}, + {36, 36, 35, 36}, + {36, 36, 36, 36}, + }, + { + {36, 36, 36, 36}, + {36, 36, 36, 36}, + {36, 36, 36, 36}, + {37, 36, 36, 36}, + }, + { + {36, 36, 36, 36}, + {37, 36, 37, 36}, + {36, 37, 36, 36}, + {37, 36, 37, 36}, + }, + { + {36, 37, 36, 37}, + {37, 36, 37, 36}, + {36, 37, 36, 37}, + {37, 37, 37, 36}, + }, + { + {36, 37, 36, 37}, + {37, 37, 37, 37}, + {37, 37, 36, 37}, + {37, 37, 37, 37}, + }, + { + {37, 37, 37, 37}, + {37, 37, 37, 37}, + {37, 37, 37, 37}, + {38, 37, 37, 37}, + }, + { + {37, 37, 37, 37}, + {38, 37, 38, 37}, + {37, 38, 37, 37}, + {38, 37, 38, 37}, + }, + { + {37, 38, 37, 38}, + {38, 37, 38, 37}, + {37, 38, 37, 38}, + {38, 38, 38, 37}, + }, + { + {37, 38, 37, 38}, + {38, 38, 38, 38}, + {38, 38, 37, 38}, + {38, 38, 38, 38}, + }, + { + {38, 38, 38, 38}, + {38, 38, 38, 38}, + {38, 38, 38, 38}, + {39, 38, 38, 38}, + }, + { + {38, 38, 38, 38}, + {39, 38, 39, 38}, + {38, 39, 38, 38}, + {39, 38, 39, 38}, + }, + { + {38, 39, 38, 39}, + {39, 38, 39, 38}, + {38, 39, 38, 39}, + {39, 39, 39, 38}, + }, + { + {38, 39, 38, 39}, + {39, 39, 39, 39}, + {39, 39, 38, 39}, + {39, 39, 39, 39}, + }, + { + {39, 39, 39, 39}, + {39, 39, 39, 39}, + {39, 39, 39, 39}, + {40, 39, 39, 39}, + }, + { + {39, 39, 39, 39}, + {40, 39, 40, 39}, + {39, 40, 39, 39}, + {40, 39, 40, 39}, + }, + { + {39, 40, 39, 40}, + {40, 39, 40, 39}, + {39, 40, 39, 40}, + {40, 39, 40, 39}, + }, + { + {39, 40, 39, 40}, + {40, 40, 40, 40}, + {39, 40, 39, 40}, + {40, 40, 40, 40}, + }, + { + {40, 40, 40, 40}, + {40, 40, 40, 40}, + {40, 40, 40, 40}, + {40, 40, 40, 40}, + }, + { + {40, 40, 40, 40}, + {41, 40, 41, 40}, + {40, 40, 40, 40}, + {41, 40, 41, 40}, + }, + { + {40, 41, 40, 41}, + {41, 40, 41, 40}, + {40, 41, 40, 41}, + {41, 40, 41, 40}, + }, + { + {40, 41, 40, 41}, + {41, 41, 41, 41}, + {40, 41, 40, 41}, + {41, 41, 41, 41}, + }, + { + {41, 41, 41, 41}, + {41, 41, 41, 41}, + {41, 41, 41, 41}, + {41, 41, 41, 41}, + }, + { + {41, 41, 41, 41}, + {42, 41, 42, 41}, + {41, 41, 41, 41}, + {42, 41, 42, 41}, + }, + { + {41, 42, 41, 42}, + {42, 41, 42, 41}, + {41, 42, 41, 42}, + {42, 41, 42, 41}, + }, + { + {41, 42, 41, 42}, + {42, 42, 42, 42}, + {41, 42, 41, 42}, + {42, 42, 42, 42}, + }, + { + {42, 42, 42, 42}, + {42, 42, 42, 42}, + {42, 42, 42, 42}, + {42, 42, 42, 42}, + }, + { + {42, 42, 42, 42}, + {43, 42, 43, 42}, + {42, 42, 42, 42}, + {43, 42, 43, 42}, + }, + { + {42, 43, 42, 43}, + {43, 42, 43, 42}, + {42, 43, 42, 43}, + {43, 42, 43, 42}, + }, + { + {42, 43, 42, 43}, + {43, 43, 43, 43}, + {42, 43, 42, 43}, + {43, 43, 43, 43}, + }, + { + {43, 43, 43, 43}, + {43, 43, 43, 43}, + {43, 43, 43, 43}, + {43, 43, 43, 43}, + }, + { + {43, 43, 43, 43}, + {44, 43, 44, 43}, + {43, 43, 43, 43}, + {44, 43, 44, 43}, + }, + { + {43, 43, 43, 44}, + {44, 43, 44, 43}, + {43, 44, 43, 44}, + {44, 43, 44, 43}, + }, + { + {43, 44, 43, 44}, + {44, 43, 44, 44}, + {43, 44, 43, 44}, + {44, 44, 44, 44}, + }, + { + {43, 44, 44, 44}, + {44, 44, 44, 44}, + {44, 44, 44, 44}, + {44, 44, 44, 44}, + }, + { + {44, 44, 44, 44}, + {44, 44, 45, 44}, + {44, 44, 44, 44}, + {45, 44, 45, 44}, + }, + { + {44, 44, 44, 45}, + {45, 44, 45, 44}, + {44, 45, 44, 45}, + {45, 44, 45, 44}, + }, + { + {44, 45, 44, 45}, + {45, 44, 45, 45}, + {44, 45, 44, 45}, + {45, 45, 45, 45}, + }, + { + {44, 45, 45, 45}, + {45, 45, 45, 45}, + {45, 45, 45, 45}, + {45, 45, 45, 45}, + }, + { + {45, 45, 45, 45}, + {45, 45, 46, 45}, + {45, 45, 45, 45}, + {46, 45, 46, 45}, + }, + { + {45, 45, 45, 46}, + {46, 45, 46, 45}, + {45, 46, 45, 46}, + {46, 45, 46, 45}, + }, + { + {45, 46, 45, 46}, + {46, 45, 46, 46}, + {45, 46, 45, 46}, + {46, 46, 46, 46}, + }, + { + {45, 46, 46, 46}, + {46, 46, 46, 46}, + {46, 46, 46, 46}, + {46, 46, 46, 46}, + }, + { + {46, 46, 46, 46}, + {46, 46, 47, 46}, + {46, 46, 46, 46}, + {47, 46, 47, 46}, + }, + { + {46, 46, 46, 47}, + {47, 46, 47, 46}, + {46, 47, 46, 47}, + {47, 46, 47, 46}, + }, + { + {46, 47, 46, 47}, + {47, 46, 47, 47}, + {46, 47, 46, 47}, + {47, 47, 47, 47}, + }, + { + {46, 47, 47, 47}, + {47, 47, 47, 47}, + {47, 47, 47, 47}, + {47, 47, 47, 47}, + }, + { + {47, 47, 47, 47}, + {47, 47, 48, 47}, + {47, 47, 47, 47}, + {48, 47, 48, 47}, + }, + { + {47, 47, 47, 48}, + {48, 47, 48, 47}, + {47, 48, 47, 48}, + {48, 47, 48, 47}, + }, + { + {47, 48, 47, 48}, + {48, 47, 48, 48}, + {47, 48, 47, 48}, + {48, 48, 48, 48}, + }, + { + {47, 48, 48, 48}, + {48, 48, 48, 48}, + {48, 48, 48, 48}, + {48, 48, 48, 48}, + }, + { + {48, 48, 48, 48}, + {48, 48, 49, 48}, + {48, 48, 48, 48}, + {49, 48, 49, 48}, + }, + { + {48, 48, 48, 49}, + {49, 48, 49, 48}, + {48, 49, 48, 49}, + {49, 48, 49, 48}, + }, + { + {48, 49, 48, 49}, + {49, 48, 49, 49}, + {48, 49, 48, 49}, + {49, 49, 49, 49}, + }, + { + {48, 49, 49, 49}, + {49, 49, 49, 49}, + {49, 49, 49, 49}, + {49, 49, 49, 49}, + }, + { + {49, 49, 49, 49}, + {49, 49, 50, 49}, + {49, 49, 49, 49}, + {50, 49, 50, 49}, + }, + { + {49, 49, 49, 50}, + {50, 49, 50, 49}, + {49, 50, 49, 50}, + {50, 49, 50, 49}, + }, + { + {49, 50, 49, 50}, + {50, 49, 50, 50}, + {49, 50, 49, 50}, + {50, 50, 50, 50}, + }, + { + {49, 50, 50, 50}, + {50, 50, 50, 50}, + {50, 50, 50, 50}, + {50, 50, 50, 50}, + }, + { + {50, 50, 50, 50}, + {50, 50, 51, 50}, + {50, 50, 50, 50}, + {51, 50, 51, 50}, + }, + { + {50, 50, 50, 51}, + {51, 50, 51, 50}, + {50, 51, 50, 51}, + {51, 50, 51, 50}, + }, + { + {50, 51, 50, 51}, + {51, 50, 51, 51}, + {50, 51, 50, 51}, + {51, 51, 51, 51}, + }, + { + {50, 51, 51, 51}, + {51, 51, 51, 51}, + {51, 51, 51, 51}, + {51, 51, 51, 51}, + }, + { + {51, 51, 51, 51}, + {51, 51, 52, 51}, + {51, 51, 51, 51}, + {52, 51, 52, 51}, + }, + { + {51, 51, 51, 52}, + {52, 51, 52, 51}, + {51, 52, 51, 51}, + {52, 51, 52, 51}, + }, + { + {51, 52, 51, 52}, + {52, 51, 52, 52}, + {51, 52, 51, 52}, + {52, 52, 52, 51}, + }, + { + {51, 52, 52, 52}, + {52, 52, 52, 52}, + {52, 52, 51, 52}, + {52, 52, 52, 52}, + }, + { + {52, 52, 52, 52}, + {52, 52, 53, 52}, + {52, 52, 52, 52}, + {53, 52, 52, 52}, + }, + { + {52, 52, 52, 53}, + {53, 52, 53, 52}, + {52, 53, 52, 52}, + {53, 52, 53, 52}, + }, + { + {52, 53, 52, 53}, + {53, 52, 53, 53}, + {52, 53, 52, 53}, + {53, 53, 53, 52}, + }, + { + {52, 53, 53, 53}, + {53, 53, 53, 53}, + {53, 53, 52, 53}, + {53, 53, 53, 53}, + }, + { + {53, 53, 53, 53}, + {53, 53, 54, 53}, + {53, 53, 53, 53}, + {54, 53, 53, 53}, + }, + { + {53, 53, 53, 54}, + {54, 53, 54, 53}, + {53, 54, 53, 53}, + {54, 53, 54, 53}, + }, + { + {53, 54, 53, 54}, + {54, 53, 54, 54}, + {53, 54, 53, 54}, + {54, 54, 54, 53}, + }, + { + {53, 54, 54, 54}, + {54, 54, 54, 54}, + {54, 54, 53, 54}, + {54, 54, 54, 54}, + }, + { + {54, 54, 54, 54}, + {54, 54, 55, 54}, + {54, 54, 54, 54}, + {55, 54, 54, 54}, + }, + { + {54, 54, 54, 55}, + {55, 54, 55, 54}, + {54, 55, 54, 54}, + {55, 54, 55, 54}, + }, + { + {54, 55, 54, 55}, + {55, 54, 55, 55}, + {54, 55, 54, 55}, + {55, 55, 55, 54}, + }, + { + {54, 55, 55, 55}, + {55, 55, 55, 55}, + {55, 55, 54, 55}, + {55, 55, 55, 55}, + }, + { + {55, 55, 55, 55}, + {55, 55, 56, 55}, + {55, 55, 55, 55}, + {56, 55, 55, 55}, + }, + { + {55, 55, 55, 55}, + {56, 55, 56, 55}, + {55, 56, 55, 55}, + {56, 55, 56, 55}, + }, + { + {55, 56, 55, 56}, + {56, 55, 56, 55}, + {55, 56, 55, 56}, + {56, 56, 56, 55}, + }, + { + {55, 56, 55, 56}, + {56, 56, 56, 56}, + {56, 56, 55, 56}, + {56, 56, 56, 56}, + }, + { + {56, 56, 56, 56}, + {56, 56, 56, 56}, + {56, 56, 56, 56}, + {57, 56, 56, 56}, + }, + { + {56, 56, 56, 56}, + {57, 56, 57, 56}, + {56, 57, 56, 56}, + {57, 56, 57, 56}, + }, + { + {56, 57, 56, 57}, + {57, 56, 57, 56}, + {56, 57, 56, 57}, + {57, 57, 57, 56}, + }, + { + {56, 57, 56, 57}, + {57, 57, 57, 57}, + {57, 57, 56, 57}, + {57, 57, 57, 57}, + }, + { + {57, 57, 57, 57}, + {57, 57, 57, 57}, + {57, 57, 57, 57}, + {58, 57, 57, 57}, + }, + { + {57, 57, 57, 57}, + {58, 57, 58, 57}, + {57, 58, 57, 57}, + {58, 57, 58, 57}, + }, + { + {57, 58, 57, 58}, + {58, 57, 58, 57}, + {57, 58, 57, 58}, + {58, 58, 58, 57}, + }, + { + {57, 58, 57, 58}, + {58, 58, 58, 58}, + {58, 58, 57, 58}, + {58, 58, 58, 58}, + }, + { + {58, 58, 58, 58}, + {58, 58, 58, 58}, + {58, 58, 58, 58}, + {59, 58, 58, 58}, + }, + { + {58, 58, 58, 58}, + {59, 58, 59, 58}, + {58, 59, 58, 58}, + {59, 58, 59, 58}, + }, + { + {58, 59, 58, 59}, + {59, 58, 59, 58}, + {58, 59, 58, 59}, + {59, 59, 59, 58}, + }, + { + {58, 59, 58, 59}, + {59, 59, 59, 59}, + {59, 59, 58, 59}, + {59, 59, 59, 59}, + }, + { + {59, 59, 59, 59}, + {59, 59, 59, 59}, + {59, 59, 59, 59}, + {60, 59, 59, 59}, + }, + { + {59, 59, 59, 59}, + {60, 59, 60, 59}, + {59, 59, 59, 59}, + {60, 59, 60, 59}, + }, + { + {59, 60, 59, 60}, + {60, 59, 60, 59}, + {59, 60, 59, 60}, + {60, 59, 60, 59}, + }, + { + {59, 60, 59, 60}, + {60, 60, 60, 60}, + {59, 60, 59, 60}, + {60, 60, 60, 60}, + }, + { + {60, 60, 60, 60}, + {60, 60, 60, 60}, + {60, 60, 60, 60}, + {60, 60, 60, 60}, + }, + { + {60, 60, 60, 60}, + {61, 60, 61, 60}, + {60, 60, 60, 60}, + {61, 60, 61, 60}, + }, + { + {60, 61, 60, 61}, + {61, 60, 61, 60}, + {60, 61, 60, 61}, + {61, 60, 61, 60}, + }, + { + {60, 61, 60, 61}, + {61, 61, 61, 61}, + {60, 61, 60, 61}, + {61, 61, 61, 61}, + }, + { + {61, 61, 61, 61}, + {61, 61, 61, 61}, + {61, 61, 61, 61}, + {61, 61, 61, 61}, + }, + { + {61, 61, 61, 61}, + {62, 61, 62, 61}, + {61, 61, 61, 61}, + {62, 61, 62, 61}, + }, + { + {61, 62, 61, 62}, + {62, 61, 62, 61}, + {61, 62, 61, 62}, + {62, 61, 62, 61}, + }, + { + {61, 62, 61, 62}, + {62, 62, 62, 62}, + {61, 62, 61, 62}, + {62, 62, 62, 62}, + }, + { + {62, 62, 62, 62}, + {62, 62, 62, 62}, + {62, 62, 62, 62}, + {62, 62, 62, 62}, + }, + { + {62, 62, 62, 62}, + {63, 62, 63, 62}, + {62, 62, 62, 62}, + {63, 62, 63, 62}, + }, + { + {62, 63, 62, 63}, + {63, 62, 63, 62}, + {62, 63, 62, 63}, + {63, 62, 63, 62}, + }, + { + {62, 63, 62, 63}, + {63, 63, 63, 63}, + {62, 63, 62, 63}, + {63, 63, 63, 63}, + }, + { + {63, 63, 63, 63}, + {63, 63, 63, 63}, + {63, 63, 63, 63}, + {63, 63, 63, 63}, + }, }; -static const uint8_t dither_rb2x2[256][2][2] = -{ - { - {0, 0}, - {0, 0}, - }, - { - {0, 0}, - {1, 0}, - }, - { - {0, 0}, - {1, 0}, - }, - { - {0, 1}, - {1, 0}, - }, - { - {0, 1}, - {1, 0}, - }, - { - {0, 1}, - {1, 1}, - }, - { - {0, 1}, - {1, 1}, - }, - { - {1, 1}, - {1, 1}, - }, - { - {1, 1}, - {1, 1}, - }, - { - {1, 1}, - {2, 1}, - }, - { - {1, 1}, - {2, 1}, - }, - { - {1, 2}, - {2, 1}, - }, - { - {1, 2}, - {2, 1}, - }, - { - {1, 2}, - {2, 2}, - }, - { - {1, 2}, - {2, 2}, - }, - { - {2, 2}, - {2, 2}, - }, - { - {2, 2}, - {2, 2}, - }, - { - {2, 2}, - {2, 2}, - }, - { - {2, 2}, - {3, 2}, - }, - { - {2, 2}, - {3, 2}, - }, - { - {2, 3}, - {3, 2}, - }, - { - {2, 3}, - {3, 2}, - }, - { - {2, 3}, - {3, 3}, - }, - { - {2, 3}, - {3, 3}, - }, - { - {3, 3}, - {3, 3}, - }, - { - {3, 3}, - {3, 3}, - }, - { - {3, 3}, - {4, 3}, - }, - { - {3, 3}, - {4, 3}, - }, - { - {3, 4}, - {4, 3}, - }, - { - {3, 4}, - {4, 3}, - }, - { - {3, 4}, - {4, 4}, - }, - { - {3, 4}, - {4, 4}, - }, - { - {4, 4}, - {4, 4}, - }, - { - {4, 4}, - {4, 4}, - }, - { - {4, 4}, - {5, 4}, - }, - { - {4, 4}, - {5, 4}, - }, - { - {4, 5}, - {5, 4}, - }, - { - {4, 5}, - {5, 4}, - }, - { - {4, 5}, - {5, 5}, - }, - { - {4, 5}, - {5, 5}, - }, - { - {5, 5}, - {5, 5}, - }, - { - {5, 5}, - {5, 5}, - }, - { - {5, 5}, - {6, 5}, - }, - { - {5, 5}, - {6, 5}, - }, - { - {5, 6}, - {6, 5}, - }, - { - {5, 6}, - {6, 5}, - }, - { - {5, 6}, - {6, 6}, - }, - { - {5, 6}, - {6, 6}, - }, - { - {5, 6}, - {6, 6}, - }, - { - {6, 6}, - {6, 6}, - }, - { - {6, 6}, - {6, 6}, - }, - { - {6, 6}, - {7, 6}, - }, - { - {6, 6}, - {7, 6}, - }, - { - {6, 7}, - {7, 6}, - }, - { - {6, 7}, - {7, 6}, - }, - { - {6, 7}, - {7, 7}, - }, - { - {6, 7}, - {7, 7}, - }, - { - {7, 7}, - {7, 7}, - }, - { - {7, 7}, - {7, 7}, - }, - { - {7, 7}, - {8, 7}, - }, - { - {7, 7}, - {8, 7}, - }, - { - {7, 8}, - {8, 7}, - }, - { - {7, 8}, - {8, 7}, - }, - { - {7, 8}, - {8, 8}, - }, - { - {7, 8}, - {8, 8}, - }, - { - {8, 8}, - {8, 8}, - }, - { - {8, 8}, - {8, 8}, - }, - { - {8, 8}, - {9, 8}, - }, - { - {8, 8}, - {9, 8}, - }, - { - {8, 9}, - {9, 8}, - }, - { - {8, 9}, - {9, 8}, - }, - { - {8, 9}, - {9, 9}, - }, - { - {8, 9}, - {9, 9}, - }, - { - {9, 9}, - {9, 9}, - }, - { - {9, 9}, - {9, 9}, - }, - { - {9, 9}, - {10, 9}, - }, - { - {9, 9}, - {10, 9}, - }, - { - {9, 10}, - {10, 9}, - }, - { - {9, 10}, - {10, 9}, - }, - { - {9, 10}, - {10, 10}, - }, - { - {9, 10}, - {10, 10}, - }, - { - {9, 10}, - {10, 10}, - }, - { - {10, 10}, - {10, 10}, - }, - { - {10, 10}, - {10, 10}, - }, - { - {10, 10}, - {11, 10}, - }, - { - {10, 10}, - {11, 10}, - }, - { - {10, 11}, - {11, 10}, - }, - { - {10, 11}, - {11, 10}, - }, - { - {10, 11}, - {11, 11}, - }, - { - {10, 11}, - {11, 11}, - }, - { - {11, 11}, - {11, 11}, - }, - { - {11, 11}, - {11, 11}, - }, - { - {11, 11}, - {12, 11}, - }, - { - {11, 11}, - {12, 11}, - }, - { - {11, 12}, - {12, 11}, - }, - { - {11, 12}, - {12, 11}, - }, - { - {11, 12}, - {12, 12}, - }, - { - {11, 12}, - {12, 12}, - }, - { - {12, 12}, - {12, 12}, - }, - { - {12, 12}, - {12, 12}, - }, - { - {12, 12}, - {13, 12}, - }, - { - {12, 12}, - {13, 12}, - }, - { - {12, 13}, - {13, 12}, - }, - { - {12, 13}, - {13, 12}, - }, - { - {12, 13}, - {13, 13}, - }, - { - {12, 13}, - {13, 13}, - }, - { - {13, 13}, - {13, 13}, - }, - { - {13, 13}, - {13, 13}, - }, - { - {13, 13}, - {14, 13}, - }, - { - {13, 13}, - {14, 13}, - }, - { - {13, 14}, - {14, 13}, - }, - { - {13, 14}, - {14, 13}, - }, - { - {13, 14}, - {14, 13}, - }, - { - {13, 14}, - {14, 14}, - }, - { - {13, 14}, - {14, 14}, - }, - { - {14, 14}, - {14, 14}, - }, - { - {14, 14}, - {14, 14}, - }, - { - {14, 14}, - {15, 14}, - }, - { - {14, 14}, - {15, 14}, - }, - { - {14, 15}, - {15, 14}, - }, - { - {14, 15}, - {15, 14}, - }, - { - {14, 15}, - {15, 15}, - }, - { - {14, 15}, - {15, 15}, - }, - { - {15, 15}, - {15, 15}, - }, - { - {15, 15}, - {15, 15}, - }, - { - {15, 15}, - {16, 15}, - }, - { - {15, 15}, - {16, 15}, - }, - { - {15, 16}, - {16, 15}, - }, - { - {15, 16}, - {16, 15}, - }, - { - {15, 16}, - {16, 16}, - }, - { - {15, 16}, - {16, 16}, - }, - { - {16, 16}, - {16, 16}, - }, - { - {16, 16}, - {16, 16}, - }, - { - {16, 16}, - {17, 16}, - }, - { - {16, 16}, - {17, 16}, - }, - { - {16, 17}, - {17, 16}, - }, - { - {16, 17}, - {17, 16}, - }, - { - {16, 17}, - {17, 17}, - }, - { - {16, 17}, - {17, 17}, - }, - { - {17, 17}, - {17, 17}, - }, - { - {17, 17}, - {17, 17}, - }, - { - {17, 17}, - {18, 17}, - }, - { - {17, 17}, - {18, 17}, - }, - { - {17, 18}, - {18, 17}, - }, - { - {17, 18}, - {18, 17}, - }, - { - {17, 18}, - {18, 18}, - }, - { - {17, 18}, - {18, 18}, - }, - { - {18, 18}, - {18, 18}, - }, - { - {18, 18}, - {18, 18}, - }, - { - {18, 18}, - {19, 18}, - }, - { - {18, 18}, - {19, 18}, - }, - { - {18, 19}, - {19, 18}, - }, - { - {18, 19}, - {19, 18}, - }, - { - {18, 19}, - {19, 19}, - }, - { - {18, 19}, - {19, 19}, - }, - { - {19, 19}, - {19, 19}, - }, - { - {19, 19}, - {19, 19}, - }, - { - {19, 19}, - {20, 19}, - }, - { - {19, 19}, - {20, 19}, - }, - { - {19, 20}, - {20, 19}, - }, - { - {19, 20}, - {20, 19}, - }, - { - {19, 20}, - {20, 19}, - }, - { - {19, 20}, - {20, 20}, - }, - { - {19, 20}, - {20, 20}, - }, - { - {20, 20}, - {20, 20}, - }, - { - {20, 20}, - {20, 20}, - }, - { - {20, 20}, - {21, 20}, - }, - { - {20, 20}, - {21, 20}, - }, - { - {20, 21}, - {21, 20}, - }, - { - {20, 21}, - {21, 20}, - }, - { - {20, 21}, - {21, 21}, - }, - { - {20, 21}, - {21, 21}, - }, - { - {21, 21}, - {21, 21}, - }, - { - {21, 21}, - {21, 21}, - }, - { - {21, 21}, - {22, 21}, - }, - { - {21, 21}, - {22, 21}, - }, - { - {21, 22}, - {22, 21}, - }, - { - {21, 22}, - {22, 21}, - }, - { - {21, 22}, - {22, 22}, - }, - { - {21, 22}, - {22, 22}, - }, - { - {22, 22}, - {22, 22}, - }, - { - {22, 22}, - {22, 22}, - }, - { - {22, 22}, - {23, 22}, - }, - { - {22, 22}, - {23, 22}, - }, - { - {22, 23}, - {23, 22}, - }, - { - {22, 23}, - {23, 22}, - }, - { - {22, 23}, - {23, 23}, - }, - { - {22, 23}, - {23, 23}, - }, - { - {23, 23}, - {23, 23}, - }, - { - {23, 23}, - {23, 23}, - }, - { - {23, 23}, - {24, 23}, - }, - { - {23, 23}, - {24, 23}, - }, - { - {23, 23}, - {24, 23}, - }, - { - {23, 24}, - {24, 23}, - }, - { - {23, 24}, - {24, 23}, - }, - { - {23, 24}, - {24, 24}, - }, - { - {23, 24}, - {24, 24}, - }, - { - {24, 24}, - {24, 24}, - }, - { - {24, 24}, - {24, 24}, - }, - { - {24, 24}, - {25, 24}, - }, - { - {24, 24}, - {25, 24}, - }, - { - {24, 25}, - {25, 24}, - }, - { - {24, 25}, - {25, 24}, - }, - { - {24, 25}, - {25, 25}, - }, - { - {24, 25}, - {25, 25}, - }, - { - {25, 25}, - {25, 25}, - }, - { - {25, 25}, - {25, 25}, - }, - { - {25, 25}, - {26, 25}, - }, - { - {25, 25}, - {26, 25}, - }, - { - {25, 26}, - {26, 25}, - }, - { - {25, 26}, - {26, 25}, - }, - { - {25, 26}, - {26, 26}, - }, - { - {25, 26}, - {26, 26}, - }, - { - {26, 26}, - {26, 26}, - }, - { - {26, 26}, - {26, 26}, - }, - { - {26, 26}, - {27, 26}, - }, - { - {26, 26}, - {27, 26}, - }, - { - {26, 27}, - {27, 26}, - }, - { - {26, 27}, - {27, 26}, - }, - { - {26, 27}, - {27, 27}, - }, - { - {26, 27}, - {27, 27}, - }, - { - {27, 27}, - {27, 27}, - }, - { - {27, 27}, - {27, 27}, - }, - { - {27, 27}, - {28, 27}, - }, - { - {27, 27}, - {28, 27}, - }, - { - {27, 27}, - {28, 27}, - }, - { - {27, 28}, - {28, 27}, - }, - { - {27, 28}, - {28, 27}, - }, - { - {27, 28}, - {28, 28}, - }, - { - {27, 28}, - {28, 28}, - }, - { - {28, 28}, - {28, 28}, - }, - { - {28, 28}, - {28, 28}, - }, - { - {28, 28}, - {29, 28}, - }, - { - {28, 28}, - {29, 28}, - }, - { - {28, 29}, - {29, 28}, - }, - { - {28, 29}, - {29, 28}, - }, - { - {28, 29}, - {29, 29}, - }, - { - {28, 29}, - {29, 29}, - }, - { - {29, 29}, - {29, 29}, - }, - { - {29, 29}, - {29, 29}, - }, - { - {29, 29}, - {30, 29}, - }, - { - {29, 29}, - {30, 29}, - }, - { - {29, 30}, - {30, 29}, - }, - { - {29, 30}, - {30, 29}, - }, - { - {29, 30}, - {30, 30}, - }, - { - {29, 30}, - {30, 30}, - }, - { - {30, 30}, - {30, 30}, - }, - { - {30, 30}, - {30, 30}, - }, - { - {30, 30}, - {31, 30}, - }, - { - {30, 30}, - {31, 30}, - }, - { - {30, 31}, - {31, 30}, - }, - { - {30, 31}, - {31, 30}, - }, - { - {30, 31}, - {31, 31}, - }, - { - {30, 31}, - {31, 31}, - }, - { - {31, 31}, - {31, 31}, - }, - { - {31, 31}, - {31, 31}, - }, +static const uint8_t dither_rb2x2[256][2][2] = { + { + {0, 0}, + {0, 0}, + }, + { + {0, 0}, + {1, 0}, + }, + { + {0, 0}, + {1, 0}, + }, + { + {0, 1}, + {1, 0}, + }, + { + {0, 1}, + {1, 0}, + }, + { + {0, 1}, + {1, 1}, + }, + { + {0, 1}, + {1, 1}, + }, + { + {1, 1}, + {1, 1}, + }, + { + {1, 1}, + {1, 1}, + }, + { + {1, 1}, + {2, 1}, + }, + { + {1, 1}, + {2, 1}, + }, + { + {1, 2}, + {2, 1}, + }, + { + {1, 2}, + {2, 1}, + }, + { + {1, 2}, + {2, 2}, + }, + { + {1, 2}, + {2, 2}, + }, + { + {2, 2}, + {2, 2}, + }, + { + {2, 2}, + {2, 2}, + }, + { + {2, 2}, + {2, 2}, + }, + { + {2, 2}, + {3, 2}, + }, + { + {2, 2}, + {3, 2}, + }, + { + {2, 3}, + {3, 2}, + }, + { + {2, 3}, + {3, 2}, + }, + { + {2, 3}, + {3, 3}, + }, + { + {2, 3}, + {3, 3}, + }, + { + {3, 3}, + {3, 3}, + }, + { + {3, 3}, + {3, 3}, + }, + { + {3, 3}, + {4, 3}, + }, + { + {3, 3}, + {4, 3}, + }, + { + {3, 4}, + {4, 3}, + }, + { + {3, 4}, + {4, 3}, + }, + { + {3, 4}, + {4, 4}, + }, + { + {3, 4}, + {4, 4}, + }, + { + {4, 4}, + {4, 4}, + }, + { + {4, 4}, + {4, 4}, + }, + { + {4, 4}, + {5, 4}, + }, + { + {4, 4}, + {5, 4}, + }, + { + {4, 5}, + {5, 4}, + }, + { + {4, 5}, + {5, 4}, + }, + { + {4, 5}, + {5, 5}, + }, + { + {4, 5}, + {5, 5}, + }, + { + {5, 5}, + {5, 5}, + }, + { + {5, 5}, + {5, 5}, + }, + { + {5, 5}, + {6, 5}, + }, + { + {5, 5}, + {6, 5}, + }, + { + {5, 6}, + {6, 5}, + }, + { + {5, 6}, + {6, 5}, + }, + { + {5, 6}, + {6, 6}, + }, + { + {5, 6}, + {6, 6}, + }, + { + {5, 6}, + {6, 6}, + }, + { + {6, 6}, + {6, 6}, + }, + { + {6, 6}, + {6, 6}, + }, + { + {6, 6}, + {7, 6}, + }, + { + {6, 6}, + {7, 6}, + }, + { + {6, 7}, + {7, 6}, + }, + { + {6, 7}, + {7, 6}, + }, + { + {6, 7}, + {7, 7}, + }, + { + {6, 7}, + {7, 7}, + }, + { + {7, 7}, + {7, 7}, + }, + { + {7, 7}, + {7, 7}, + }, + { + {7, 7}, + {8, 7}, + }, + { + {7, 7}, + {8, 7}, + }, + { + {7, 8}, + {8, 7}, + }, + { + {7, 8}, + {8, 7}, + }, + { + {7, 8}, + {8, 8}, + }, + { + {7, 8}, + {8, 8}, + }, + { + {8, 8}, + {8, 8}, + }, + { + {8, 8}, + {8, 8}, + }, + { + {8, 8}, + {9, 8}, + }, + { + {8, 8}, + {9, 8}, + }, + { + {8, 9}, + {9, 8}, + }, + { + {8, 9}, + {9, 8}, + }, + { + {8, 9}, + {9, 9}, + }, + { + {8, 9}, + {9, 9}, + }, + { + {9, 9}, + {9, 9}, + }, + { + {9, 9}, + {9, 9}, + }, + { + {9, 9}, + {10, 9}, + }, + { + {9, 9}, + {10, 9}, + }, + { + {9, 10}, + {10, 9}, + }, + { + {9, 10}, + {10, 9}, + }, + { + {9, 10}, + {10, 10}, + }, + { + {9, 10}, + {10, 10}, + }, + { + {9, 10}, + {10, 10}, + }, + { + {10, 10}, + {10, 10}, + }, + { + {10, 10}, + {10, 10}, + }, + { + {10, 10}, + {11, 10}, + }, + { + {10, 10}, + {11, 10}, + }, + { + {10, 11}, + {11, 10}, + }, + { + {10, 11}, + {11, 10}, + }, + { + {10, 11}, + {11, 11}, + }, + { + {10, 11}, + {11, 11}, + }, + { + {11, 11}, + {11, 11}, + }, + { + {11, 11}, + {11, 11}, + }, + { + {11, 11}, + {12, 11}, + }, + { + {11, 11}, + {12, 11}, + }, + { + {11, 12}, + {12, 11}, + }, + { + {11, 12}, + {12, 11}, + }, + { + {11, 12}, + {12, 12}, + }, + { + {11, 12}, + {12, 12}, + }, + { + {12, 12}, + {12, 12}, + }, + { + {12, 12}, + {12, 12}, + }, + { + {12, 12}, + {13, 12}, + }, + { + {12, 12}, + {13, 12}, + }, + { + {12, 13}, + {13, 12}, + }, + { + {12, 13}, + {13, 12}, + }, + { + {12, 13}, + {13, 13}, + }, + { + {12, 13}, + {13, 13}, + }, + { + {13, 13}, + {13, 13}, + }, + { + {13, 13}, + {13, 13}, + }, + { + {13, 13}, + {14, 13}, + }, + { + {13, 13}, + {14, 13}, + }, + { + {13, 14}, + {14, 13}, + }, + { + {13, 14}, + {14, 13}, + }, + { + {13, 14}, + {14, 13}, + }, + { + {13, 14}, + {14, 14}, + }, + { + {13, 14}, + {14, 14}, + }, + { + {14, 14}, + {14, 14}, + }, + { + {14, 14}, + {14, 14}, + }, + { + {14, 14}, + {15, 14}, + }, + { + {14, 14}, + {15, 14}, + }, + { + {14, 15}, + {15, 14}, + }, + { + {14, 15}, + {15, 14}, + }, + { + {14, 15}, + {15, 15}, + }, + { + {14, 15}, + {15, 15}, + }, + { + {15, 15}, + {15, 15}, + }, + { + {15, 15}, + {15, 15}, + }, + { + {15, 15}, + {16, 15}, + }, + { + {15, 15}, + {16, 15}, + }, + { + {15, 16}, + {16, 15}, + }, + { + {15, 16}, + {16, 15}, + }, + { + {15, 16}, + {16, 16}, + }, + { + {15, 16}, + {16, 16}, + }, + { + {16, 16}, + {16, 16}, + }, + { + {16, 16}, + {16, 16}, + }, + { + {16, 16}, + {17, 16}, + }, + { + {16, 16}, + {17, 16}, + }, + { + {16, 17}, + {17, 16}, + }, + { + {16, 17}, + {17, 16}, + }, + { + {16, 17}, + {17, 17}, + }, + { + {16, 17}, + {17, 17}, + }, + { + {17, 17}, + {17, 17}, + }, + { + {17, 17}, + {17, 17}, + }, + { + {17, 17}, + {18, 17}, + }, + { + {17, 17}, + {18, 17}, + }, + { + {17, 18}, + {18, 17}, + }, + { + {17, 18}, + {18, 17}, + }, + { + {17, 18}, + {18, 18}, + }, + { + {17, 18}, + {18, 18}, + }, + { + {18, 18}, + {18, 18}, + }, + { + {18, 18}, + {18, 18}, + }, + { + {18, 18}, + {19, 18}, + }, + { + {18, 18}, + {19, 18}, + }, + { + {18, 19}, + {19, 18}, + }, + { + {18, 19}, + {19, 18}, + }, + { + {18, 19}, + {19, 19}, + }, + { + {18, 19}, + {19, 19}, + }, + { + {19, 19}, + {19, 19}, + }, + { + {19, 19}, + {19, 19}, + }, + { + {19, 19}, + {20, 19}, + }, + { + {19, 19}, + {20, 19}, + }, + { + {19, 20}, + {20, 19}, + }, + { + {19, 20}, + {20, 19}, + }, + { + {19, 20}, + {20, 19}, + }, + { + {19, 20}, + {20, 20}, + }, + { + {19, 20}, + {20, 20}, + }, + { + {20, 20}, + {20, 20}, + }, + { + {20, 20}, + {20, 20}, + }, + { + {20, 20}, + {21, 20}, + }, + { + {20, 20}, + {21, 20}, + }, + { + {20, 21}, + {21, 20}, + }, + { + {20, 21}, + {21, 20}, + }, + { + {20, 21}, + {21, 21}, + }, + { + {20, 21}, + {21, 21}, + }, + { + {21, 21}, + {21, 21}, + }, + { + {21, 21}, + {21, 21}, + }, + { + {21, 21}, + {22, 21}, + }, + { + {21, 21}, + {22, 21}, + }, + { + {21, 22}, + {22, 21}, + }, + { + {21, 22}, + {22, 21}, + }, + { + {21, 22}, + {22, 22}, + }, + { + {21, 22}, + {22, 22}, + }, + { + {22, 22}, + {22, 22}, + }, + { + {22, 22}, + {22, 22}, + }, + { + {22, 22}, + {23, 22}, + }, + { + {22, 22}, + {23, 22}, + }, + { + {22, 23}, + {23, 22}, + }, + { + {22, 23}, + {23, 22}, + }, + { + {22, 23}, + {23, 23}, + }, + { + {22, 23}, + {23, 23}, + }, + { + {23, 23}, + {23, 23}, + }, + { + {23, 23}, + {23, 23}, + }, + { + {23, 23}, + {24, 23}, + }, + { + {23, 23}, + {24, 23}, + }, + { + {23, 23}, + {24, 23}, + }, + { + {23, 24}, + {24, 23}, + }, + { + {23, 24}, + {24, 23}, + }, + { + {23, 24}, + {24, 24}, + }, + { + {23, 24}, + {24, 24}, + }, + { + {24, 24}, + {24, 24}, + }, + { + {24, 24}, + {24, 24}, + }, + { + {24, 24}, + {25, 24}, + }, + { + {24, 24}, + {25, 24}, + }, + { + {24, 25}, + {25, 24}, + }, + { + {24, 25}, + {25, 24}, + }, + { + {24, 25}, + {25, 25}, + }, + { + {24, 25}, + {25, 25}, + }, + { + {25, 25}, + {25, 25}, + }, + { + {25, 25}, + {25, 25}, + }, + { + {25, 25}, + {26, 25}, + }, + { + {25, 25}, + {26, 25}, + }, + { + {25, 26}, + {26, 25}, + }, + { + {25, 26}, + {26, 25}, + }, + { + {25, 26}, + {26, 26}, + }, + { + {25, 26}, + {26, 26}, + }, + { + {26, 26}, + {26, 26}, + }, + { + {26, 26}, + {26, 26}, + }, + { + {26, 26}, + {27, 26}, + }, + { + {26, 26}, + {27, 26}, + }, + { + {26, 27}, + {27, 26}, + }, + { + {26, 27}, + {27, 26}, + }, + { + {26, 27}, + {27, 27}, + }, + { + {26, 27}, + {27, 27}, + }, + { + {27, 27}, + {27, 27}, + }, + { + {27, 27}, + {27, 27}, + }, + { + {27, 27}, + {28, 27}, + }, + { + {27, 27}, + {28, 27}, + }, + { + {27, 27}, + {28, 27}, + }, + { + {27, 28}, + {28, 27}, + }, + { + {27, 28}, + {28, 27}, + }, + { + {27, 28}, + {28, 28}, + }, + { + {27, 28}, + {28, 28}, + }, + { + {28, 28}, + {28, 28}, + }, + { + {28, 28}, + {28, 28}, + }, + { + {28, 28}, + {29, 28}, + }, + { + {28, 28}, + {29, 28}, + }, + { + {28, 29}, + {29, 28}, + }, + { + {28, 29}, + {29, 28}, + }, + { + {28, 29}, + {29, 29}, + }, + { + {28, 29}, + {29, 29}, + }, + { + {29, 29}, + {29, 29}, + }, + { + {29, 29}, + {29, 29}, + }, + { + {29, 29}, + {30, 29}, + }, + { + {29, 29}, + {30, 29}, + }, + { + {29, 30}, + {30, 29}, + }, + { + {29, 30}, + {30, 29}, + }, + { + {29, 30}, + {30, 30}, + }, + { + {29, 30}, + {30, 30}, + }, + { + {30, 30}, + {30, 30}, + }, + { + {30, 30}, + {30, 30}, + }, + { + {30, 30}, + {31, 30}, + }, + { + {30, 30}, + {31, 30}, + }, + { + {30, 31}, + {31, 30}, + }, + { + {30, 31}, + {31, 30}, + }, + { + {30, 31}, + {31, 31}, + }, + { + {30, 31}, + {31, 31}, + }, + { + {31, 31}, + {31, 31}, + }, + { + {31, 31}, + {31, 31}, + }, }; -static const uint8_t dither_g2x2[256][2][2] = -{ - { - {0, 0}, - {0, 0}, - }, - { - {0, 0}, - {1, 0}, - }, - { - {0, 1}, - {1, 0}, - }, - { - {0, 1}, - {1, 1}, - }, - { - {1, 1}, - {1, 1}, - }, - { - {1, 1}, - {2, 1}, - }, - { - {1, 2}, - {2, 1}, - }, - { - {1, 2}, - {2, 2}, - }, - { - {2, 2}, - {2, 2}, - }, - { - {2, 2}, - {3, 2}, - }, - { - {2, 3}, - {3, 2}, - }, - { - {2, 3}, - {3, 3}, - }, - { - {3, 3}, - {3, 3}, - }, - { - {3, 3}, - {4, 3}, - }, - { - {3, 4}, - {4, 3}, - }, - { - {3, 4}, - {4, 4}, - }, - { - {4, 4}, - {4, 4}, - }, - { - {4, 4}, - {5, 4}, - }, - { - {4, 5}, - {5, 4}, - }, - { - {4, 5}, - {5, 5}, - }, - { - {5, 5}, - {5, 5}, - }, - { - {5, 5}, - {6, 5}, - }, - { - {5, 6}, - {6, 5}, - }, - { - {5, 6}, - {6, 6}, - }, - { - {6, 6}, - {6, 6}, - }, - { - {6, 6}, - {7, 6}, - }, - { - {6, 7}, - {7, 6}, - }, - { - {6, 7}, - {7, 7}, - }, - { - {7, 7}, - {7, 7}, - }, - { - {7, 7}, - {8, 7}, - }, - { - {7, 8}, - {8, 7}, - }, - { - {7, 8}, - {8, 8}, - }, - { - {8, 8}, - {8, 8}, - }, - { - {8, 8}, - {9, 8}, - }, - { - {8, 9}, - {9, 8}, - }, - { - {8, 9}, - {9, 9}, - }, - { - {9, 9}, - {9, 9}, - }, - { - {9, 9}, - {10, 9}, - }, - { - {9, 10}, - {10, 9}, - }, - { - {9, 10}, - {10, 10}, - }, - { - {10, 10}, - {10, 10}, - }, - { - {10, 10}, - {11, 10}, - }, - { - {10, 11}, - {11, 10}, - }, - { - {10, 11}, - {11, 11}, - }, - { - {11, 11}, - {11, 11}, - }, - { - {11, 11}, - {12, 11}, - }, - { - {11, 12}, - {12, 11}, - }, - { - {11, 12}, - {12, 12}, - }, - { - {11, 12}, - {12, 12}, - }, - { - {12, 12}, - {12, 12}, - }, - { - {12, 12}, - {13, 12}, - }, - { - {12, 13}, - {13, 12}, - }, - { - {12, 13}, - {13, 13}, - }, - { - {13, 13}, - {13, 13}, - }, - { - {13, 13}, - {14, 13}, - }, - { - {13, 14}, - {14, 13}, - }, - { - {13, 14}, - {14, 14}, - }, - { - {14, 14}, - {14, 14}, - }, - { - {14, 14}, - {15, 14}, - }, - { - {14, 15}, - {15, 14}, - }, - { - {14, 15}, - {15, 15}, - }, - { - {15, 15}, - {15, 15}, - }, - { - {15, 15}, - {16, 15}, - }, - { - {15, 16}, - {16, 15}, - }, - { - {15, 16}, - {16, 16}, - }, - { - {16, 16}, - {16, 16}, - }, - { - {16, 16}, - {17, 16}, - }, - { - {16, 17}, - {17, 16}, - }, - { - {16, 17}, - {17, 17}, - }, - { - {17, 17}, - {17, 17}, - }, - { - {17, 17}, - {18, 17}, - }, - { - {17, 18}, - {18, 17}, - }, - { - {17, 18}, - {18, 18}, - }, - { - {18, 18}, - {18, 18}, - }, - { - {18, 18}, - {19, 18}, - }, - { - {18, 19}, - {19, 18}, - }, - { - {18, 19}, - {19, 19}, - }, - { - {19, 19}, - {19, 19}, - }, - { - {19, 19}, - {20, 19}, - }, - { - {19, 20}, - {20, 19}, - }, - { - {19, 20}, - {20, 20}, - }, - { - {20, 20}, - {20, 20}, - }, - { - {20, 20}, - {21, 20}, - }, - { - {20, 21}, - {21, 20}, - }, - { - {20, 21}, - {21, 21}, - }, - { - {21, 21}, - {21, 21}, - }, - { - {21, 21}, - {22, 21}, - }, - { - {21, 22}, - {22, 21}, - }, - { - {21, 22}, - {22, 22}, - }, - { - {22, 22}, - {22, 22}, - }, - { - {22, 22}, - {23, 22}, - }, - { - {22, 23}, - {23, 22}, - }, - { - {22, 23}, - {23, 23}, - }, - { - {23, 23}, - {23, 23}, - }, - { - {23, 23}, - {24, 23}, - }, - { - {23, 24}, - {24, 23}, - }, - { - {23, 24}, - {24, 24}, - }, - { - {24, 24}, - {24, 24}, - }, - { - {24, 24}, - {25, 24}, - }, - { - {24, 25}, - {25, 24}, - }, - { - {24, 25}, - {25, 25}, - }, - { - {25, 25}, - {25, 25}, - }, - { - {25, 25}, - {26, 25}, - }, - { - {25, 26}, - {26, 25}, - }, - { - {25, 26}, - {26, 26}, - }, - { - {26, 26}, - {26, 26}, - }, - { - {26, 26}, - {27, 26}, - }, - { - {26, 27}, - {27, 26}, - }, - { - {26, 27}, - {27, 27}, - }, - { - {27, 27}, - {27, 27}, - }, - { - {27, 27}, - {28, 27}, - }, - { - {27, 28}, - {28, 27}, - }, - { - {27, 28}, - {28, 28}, - }, - { - {28, 28}, - {28, 28}, - }, - { - {28, 28}, - {29, 28}, - }, - { - {28, 29}, - {29, 28}, - }, - { - {28, 29}, - {29, 29}, - }, - { - {29, 29}, - {29, 29}, - }, - { - {29, 29}, - {30, 29}, - }, - { - {29, 30}, - {30, 29}, - }, - { - {29, 30}, - {30, 30}, - }, - { - {30, 30}, - {30, 30}, - }, - { - {30, 30}, - {31, 30}, - }, - { - {30, 31}, - {31, 30}, - }, - { - {30, 31}, - {31, 31}, - }, - { - {31, 31}, - {31, 31}, - }, - { - {31, 31}, - {32, 31}, - }, - { - {31, 32}, - {32, 31}, - }, - { - {31, 32}, - {32, 32}, - }, - { - {32, 32}, - {32, 32}, - }, - { - {32, 32}, - {33, 32}, - }, - { - {32, 33}, - {33, 32}, - }, - { - {32, 33}, - {33, 33}, - }, - { - {33, 33}, - {33, 33}, - }, - { - {33, 33}, - {34, 33}, - }, - { - {33, 34}, - {34, 33}, - }, - { - {33, 34}, - {34, 34}, - }, - { - {34, 34}, - {34, 34}, - }, - { - {34, 34}, - {35, 34}, - }, - { - {34, 35}, - {35, 34}, - }, - { - {34, 35}, - {35, 35}, - }, - { - {35, 35}, - {35, 35}, - }, - { - {35, 35}, - {36, 35}, - }, - { - {35, 36}, - {36, 35}, - }, - { - {35, 36}, - {36, 35}, - }, - { - {35, 36}, - {36, 36}, - }, - { - {36, 36}, - {36, 36}, - }, - { - {36, 36}, - {37, 36}, - }, - { - {36, 37}, - {37, 36}, - }, - { - {36, 37}, - {37, 37}, - }, - { - {37, 37}, - {37, 37}, - }, - { - {37, 37}, - {38, 37}, - }, - { - {37, 38}, - {38, 37}, - }, - { - {37, 38}, - {38, 38}, - }, - { - {38, 38}, - {38, 38}, - }, - { - {38, 38}, - {39, 38}, - }, - { - {38, 39}, - {39, 38}, - }, - { - {38, 39}, - {39, 39}, - }, - { - {39, 39}, - {39, 39}, - }, - { - {39, 39}, - {40, 39}, - }, - { - {39, 40}, - {40, 39}, - }, - { - {39, 40}, - {40, 40}, - }, - { - {40, 40}, - {40, 40}, - }, - { - {40, 40}, - {41, 40}, - }, - { - {40, 41}, - {41, 40}, - }, - { - {40, 41}, - {41, 41}, - }, - { - {41, 41}, - {41, 41}, - }, - { - {41, 41}, - {42, 41}, - }, - { - {41, 42}, - {42, 41}, - }, - { - {41, 42}, - {42, 42}, - }, - { - {42, 42}, - {42, 42}, - }, - { - {42, 42}, - {43, 42}, - }, - { - {42, 43}, - {43, 42}, - }, - { - {42, 43}, - {43, 43}, - }, - { - {43, 43}, - {43, 43}, - }, - { - {43, 43}, - {44, 43}, - }, - { - {43, 44}, - {44, 43}, - }, - { - {43, 44}, - {44, 44}, - }, - { - {44, 44}, - {44, 44}, - }, - { - {44, 44}, - {45, 44}, - }, - { - {44, 45}, - {45, 44}, - }, - { - {44, 45}, - {45, 45}, - }, - { - {45, 45}, - {45, 45}, - }, - { - {45, 45}, - {46, 45}, - }, - { - {45, 46}, - {46, 45}, - }, - { - {45, 46}, - {46, 46}, - }, - { - {46, 46}, - {46, 46}, - }, - { - {46, 46}, - {47, 46}, - }, - { - {46, 47}, - {47, 46}, - }, - { - {46, 47}, - {47, 47}, - }, - { - {47, 47}, - {47, 47}, - }, - { - {47, 47}, - {48, 47}, - }, - { - {47, 48}, - {48, 47}, - }, - { - {47, 48}, - {48, 48}, - }, - { - {48, 48}, - {48, 48}, - }, - { - {48, 48}, - {49, 48}, - }, - { - {48, 49}, - {49, 48}, - }, - { - {48, 49}, - {49, 49}, - }, - { - {49, 49}, - {49, 49}, - }, - { - {49, 49}, - {50, 49}, - }, - { - {49, 50}, - {50, 49}, - }, - { - {49, 50}, - {50, 50}, - }, - { - {50, 50}, - {50, 50}, - }, - { - {50, 50}, - {51, 50}, - }, - { - {50, 51}, - {51, 50}, - }, - { - {50, 51}, - {51, 51}, - }, - { - {51, 51}, - {51, 51}, - }, - { - {51, 51}, - {52, 51}, - }, - { - {51, 52}, - {52, 51}, - }, - { - {51, 52}, - {52, 52}, - }, - { - {52, 52}, - {52, 52}, - }, - { - {52, 52}, - {53, 52}, - }, - { - {52, 53}, - {53, 52}, - }, - { - {52, 53}, - {53, 53}, - }, - { - {53, 53}, - {53, 53}, - }, - { - {53, 53}, - {54, 53}, - }, - { - {53, 54}, - {54, 53}, - }, - { - {53, 54}, - {54, 54}, - }, - { - {54, 54}, - {54, 54}, - }, - { - {54, 54}, - {55, 54}, - }, - { - {54, 55}, - {55, 54}, - }, - { - {54, 55}, - {55, 55}, - }, - { - {55, 55}, - {55, 55}, - }, - { - {55, 55}, - {56, 55}, - }, - { - {55, 55}, - {56, 55}, - }, - { - {55, 56}, - {56, 55}, - }, - { - {55, 56}, - {56, 56}, - }, - { - {56, 56}, - {56, 56}, - }, - { - {56, 56}, - {57, 56}, - }, - { - {56, 57}, - {57, 56}, - }, - { - {56, 57}, - {57, 57}, - }, - { - {57, 57}, - {57, 57}, - }, - { - {57, 57}, - {58, 57}, - }, - { - {57, 58}, - {58, 57}, - }, - { - {57, 58}, - {58, 58}, - }, - { - {58, 58}, - {58, 58}, - }, - { - {58, 58}, - {59, 58}, - }, - { - {58, 59}, - {59, 58}, - }, - { - {58, 59}, - {59, 59}, - }, - { - {59, 59}, - {59, 59}, - }, - { - {59, 59}, - {60, 59}, - }, - { - {59, 60}, - {60, 59}, - }, - { - {59, 60}, - {60, 60}, - }, - { - {60, 60}, - {60, 60}, - }, - { - {60, 60}, - {61, 60}, - }, - { - {60, 61}, - {61, 60}, - }, - { - {60, 61}, - {61, 61}, - }, - { - {61, 61}, - {61, 61}, - }, - { - {61, 61}, - {62, 61}, - }, - { - {61, 62}, - {62, 61}, - }, - { - {61, 62}, - {62, 62}, - }, - { - {62, 62}, - {62, 62}, - }, - { - {62, 62}, - {63, 62}, - }, - { - {62, 63}, - {63, 62}, - }, - { - {62, 63}, - {63, 63}, - }, - { - {63, 63}, - {63, 63}, - }, +static const uint8_t dither_g2x2[256][2][2] = { + { + {0, 0}, + {0, 0}, + }, + { + {0, 0}, + {1, 0}, + }, + { + {0, 1}, + {1, 0}, + }, + { + {0, 1}, + {1, 1}, + }, + { + {1, 1}, + {1, 1}, + }, + { + {1, 1}, + {2, 1}, + }, + { + {1, 2}, + {2, 1}, + }, + { + {1, 2}, + {2, 2}, + }, + { + {2, 2}, + {2, 2}, + }, + { + {2, 2}, + {3, 2}, + }, + { + {2, 3}, + {3, 2}, + }, + { + {2, 3}, + {3, 3}, + }, + { + {3, 3}, + {3, 3}, + }, + { + {3, 3}, + {4, 3}, + }, + { + {3, 4}, + {4, 3}, + }, + { + {3, 4}, + {4, 4}, + }, + { + {4, 4}, + {4, 4}, + }, + { + {4, 4}, + {5, 4}, + }, + { + {4, 5}, + {5, 4}, + }, + { + {4, 5}, + {5, 5}, + }, + { + {5, 5}, + {5, 5}, + }, + { + {5, 5}, + {6, 5}, + }, + { + {5, 6}, + {6, 5}, + }, + { + {5, 6}, + {6, 6}, + }, + { + {6, 6}, + {6, 6}, + }, + { + {6, 6}, + {7, 6}, + }, + { + {6, 7}, + {7, 6}, + }, + { + {6, 7}, + {7, 7}, + }, + { + {7, 7}, + {7, 7}, + }, + { + {7, 7}, + {8, 7}, + }, + { + {7, 8}, + {8, 7}, + }, + { + {7, 8}, + {8, 8}, + }, + { + {8, 8}, + {8, 8}, + }, + { + {8, 8}, + {9, 8}, + }, + { + {8, 9}, + {9, 8}, + }, + { + {8, 9}, + {9, 9}, + }, + { + {9, 9}, + {9, 9}, + }, + { + {9, 9}, + {10, 9}, + }, + { + {9, 10}, + {10, 9}, + }, + { + {9, 10}, + {10, 10}, + }, + { + {10, 10}, + {10, 10}, + }, + { + {10, 10}, + {11, 10}, + }, + { + {10, 11}, + {11, 10}, + }, + { + {10, 11}, + {11, 11}, + }, + { + {11, 11}, + {11, 11}, + }, + { + {11, 11}, + {12, 11}, + }, + { + {11, 12}, + {12, 11}, + }, + { + {11, 12}, + {12, 12}, + }, + { + {11, 12}, + {12, 12}, + }, + { + {12, 12}, + {12, 12}, + }, + { + {12, 12}, + {13, 12}, + }, + { + {12, 13}, + {13, 12}, + }, + { + {12, 13}, + {13, 13}, + }, + { + {13, 13}, + {13, 13}, + }, + { + {13, 13}, + {14, 13}, + }, + { + {13, 14}, + {14, 13}, + }, + { + {13, 14}, + {14, 14}, + }, + { + {14, 14}, + {14, 14}, + }, + { + {14, 14}, + {15, 14}, + }, + { + {14, 15}, + {15, 14}, + }, + { + {14, 15}, + {15, 15}, + }, + { + {15, 15}, + {15, 15}, + }, + { + {15, 15}, + {16, 15}, + }, + { + {15, 16}, + {16, 15}, + }, + { + {15, 16}, + {16, 16}, + }, + { + {16, 16}, + {16, 16}, + }, + { + {16, 16}, + {17, 16}, + }, + { + {16, 17}, + {17, 16}, + }, + { + {16, 17}, + {17, 17}, + }, + { + {17, 17}, + {17, 17}, + }, + { + {17, 17}, + {18, 17}, + }, + { + {17, 18}, + {18, 17}, + }, + { + {17, 18}, + {18, 18}, + }, + { + {18, 18}, + {18, 18}, + }, + { + {18, 18}, + {19, 18}, + }, + { + {18, 19}, + {19, 18}, + }, + { + {18, 19}, + {19, 19}, + }, + { + {19, 19}, + {19, 19}, + }, + { + {19, 19}, + {20, 19}, + }, + { + {19, 20}, + {20, 19}, + }, + { + {19, 20}, + {20, 20}, + }, + { + {20, 20}, + {20, 20}, + }, + { + {20, 20}, + {21, 20}, + }, + { + {20, 21}, + {21, 20}, + }, + { + {20, 21}, + {21, 21}, + }, + { + {21, 21}, + {21, 21}, + }, + { + {21, 21}, + {22, 21}, + }, + { + {21, 22}, + {22, 21}, + }, + { + {21, 22}, + {22, 22}, + }, + { + {22, 22}, + {22, 22}, + }, + { + {22, 22}, + {23, 22}, + }, + { + {22, 23}, + {23, 22}, + }, + { + {22, 23}, + {23, 23}, + }, + { + {23, 23}, + {23, 23}, + }, + { + {23, 23}, + {24, 23}, + }, + { + {23, 24}, + {24, 23}, + }, + { + {23, 24}, + {24, 24}, + }, + { + {24, 24}, + {24, 24}, + }, + { + {24, 24}, + {25, 24}, + }, + { + {24, 25}, + {25, 24}, + }, + { + {24, 25}, + {25, 25}, + }, + { + {25, 25}, + {25, 25}, + }, + { + {25, 25}, + {26, 25}, + }, + { + {25, 26}, + {26, 25}, + }, + { + {25, 26}, + {26, 26}, + }, + { + {26, 26}, + {26, 26}, + }, + { + {26, 26}, + {27, 26}, + }, + { + {26, 27}, + {27, 26}, + }, + { + {26, 27}, + {27, 27}, + }, + { + {27, 27}, + {27, 27}, + }, + { + {27, 27}, + {28, 27}, + }, + { + {27, 28}, + {28, 27}, + }, + { + {27, 28}, + {28, 28}, + }, + { + {28, 28}, + {28, 28}, + }, + { + {28, 28}, + {29, 28}, + }, + { + {28, 29}, + {29, 28}, + }, + { + {28, 29}, + {29, 29}, + }, + { + {29, 29}, + {29, 29}, + }, + { + {29, 29}, + {30, 29}, + }, + { + {29, 30}, + {30, 29}, + }, + { + {29, 30}, + {30, 30}, + }, + { + {30, 30}, + {30, 30}, + }, + { + {30, 30}, + {31, 30}, + }, + { + {30, 31}, + {31, 30}, + }, + { + {30, 31}, + {31, 31}, + }, + { + {31, 31}, + {31, 31}, + }, + { + {31, 31}, + {32, 31}, + }, + { + {31, 32}, + {32, 31}, + }, + { + {31, 32}, + {32, 32}, + }, + { + {32, 32}, + {32, 32}, + }, + { + {32, 32}, + {33, 32}, + }, + { + {32, 33}, + {33, 32}, + }, + { + {32, 33}, + {33, 33}, + }, + { + {33, 33}, + {33, 33}, + }, + { + {33, 33}, + {34, 33}, + }, + { + {33, 34}, + {34, 33}, + }, + { + {33, 34}, + {34, 34}, + }, + { + {34, 34}, + {34, 34}, + }, + { + {34, 34}, + {35, 34}, + }, + { + {34, 35}, + {35, 34}, + }, + { + {34, 35}, + {35, 35}, + }, + { + {35, 35}, + {35, 35}, + }, + { + {35, 35}, + {36, 35}, + }, + { + {35, 36}, + {36, 35}, + }, + { + {35, 36}, + {36, 35}, + }, + { + {35, 36}, + {36, 36}, + }, + { + {36, 36}, + {36, 36}, + }, + { + {36, 36}, + {37, 36}, + }, + { + {36, 37}, + {37, 36}, + }, + { + {36, 37}, + {37, 37}, + }, + { + {37, 37}, + {37, 37}, + }, + { + {37, 37}, + {38, 37}, + }, + { + {37, 38}, + {38, 37}, + }, + { + {37, 38}, + {38, 38}, + }, + { + {38, 38}, + {38, 38}, + }, + { + {38, 38}, + {39, 38}, + }, + { + {38, 39}, + {39, 38}, + }, + { + {38, 39}, + {39, 39}, + }, + { + {39, 39}, + {39, 39}, + }, + { + {39, 39}, + {40, 39}, + }, + { + {39, 40}, + {40, 39}, + }, + { + {39, 40}, + {40, 40}, + }, + { + {40, 40}, + {40, 40}, + }, + { + {40, 40}, + {41, 40}, + }, + { + {40, 41}, + {41, 40}, + }, + { + {40, 41}, + {41, 41}, + }, + { + {41, 41}, + {41, 41}, + }, + { + {41, 41}, + {42, 41}, + }, + { + {41, 42}, + {42, 41}, + }, + { + {41, 42}, + {42, 42}, + }, + { + {42, 42}, + {42, 42}, + }, + { + {42, 42}, + {43, 42}, + }, + { + {42, 43}, + {43, 42}, + }, + { + {42, 43}, + {43, 43}, + }, + { + {43, 43}, + {43, 43}, + }, + { + {43, 43}, + {44, 43}, + }, + { + {43, 44}, + {44, 43}, + }, + { + {43, 44}, + {44, 44}, + }, + { + {44, 44}, + {44, 44}, + }, + { + {44, 44}, + {45, 44}, + }, + { + {44, 45}, + {45, 44}, + }, + { + {44, 45}, + {45, 45}, + }, + { + {45, 45}, + {45, 45}, + }, + { + {45, 45}, + {46, 45}, + }, + { + {45, 46}, + {46, 45}, + }, + { + {45, 46}, + {46, 46}, + }, + { + {46, 46}, + {46, 46}, + }, + { + {46, 46}, + {47, 46}, + }, + { + {46, 47}, + {47, 46}, + }, + { + {46, 47}, + {47, 47}, + }, + { + {47, 47}, + {47, 47}, + }, + { + {47, 47}, + {48, 47}, + }, + { + {47, 48}, + {48, 47}, + }, + { + {47, 48}, + {48, 48}, + }, + { + {48, 48}, + {48, 48}, + }, + { + {48, 48}, + {49, 48}, + }, + { + {48, 49}, + {49, 48}, + }, + { + {48, 49}, + {49, 49}, + }, + { + {49, 49}, + {49, 49}, + }, + { + {49, 49}, + {50, 49}, + }, + { + {49, 50}, + {50, 49}, + }, + { + {49, 50}, + {50, 50}, + }, + { + {50, 50}, + {50, 50}, + }, + { + {50, 50}, + {51, 50}, + }, + { + {50, 51}, + {51, 50}, + }, + { + {50, 51}, + {51, 51}, + }, + { + {51, 51}, + {51, 51}, + }, + { + {51, 51}, + {52, 51}, + }, + { + {51, 52}, + {52, 51}, + }, + { + {51, 52}, + {52, 52}, + }, + { + {52, 52}, + {52, 52}, + }, + { + {52, 52}, + {53, 52}, + }, + { + {52, 53}, + {53, 52}, + }, + { + {52, 53}, + {53, 53}, + }, + { + {53, 53}, + {53, 53}, + }, + { + {53, 53}, + {54, 53}, + }, + { + {53, 54}, + {54, 53}, + }, + { + {53, 54}, + {54, 54}, + }, + { + {54, 54}, + {54, 54}, + }, + { + {54, 54}, + {55, 54}, + }, + { + {54, 55}, + {55, 54}, + }, + { + {54, 55}, + {55, 55}, + }, + { + {55, 55}, + {55, 55}, + }, + { + {55, 55}, + {56, 55}, + }, + { + {55, 55}, + {56, 55}, + }, + { + {55, 56}, + {56, 55}, + }, + { + {55, 56}, + {56, 56}, + }, + { + {56, 56}, + {56, 56}, + }, + { + {56, 56}, + {57, 56}, + }, + { + {56, 57}, + {57, 56}, + }, + { + {56, 57}, + {57, 57}, + }, + { + {57, 57}, + {57, 57}, + }, + { + {57, 57}, + {58, 57}, + }, + { + {57, 58}, + {58, 57}, + }, + { + {57, 58}, + {58, 58}, + }, + { + {58, 58}, + {58, 58}, + }, + { + {58, 58}, + {59, 58}, + }, + { + {58, 59}, + {59, 58}, + }, + { + {58, 59}, + {59, 59}, + }, + { + {59, 59}, + {59, 59}, + }, + { + {59, 59}, + {60, 59}, + }, + { + {59, 60}, + {60, 59}, + }, + { + {59, 60}, + {60, 60}, + }, + { + {60, 60}, + {60, 60}, + }, + { + {60, 60}, + {61, 60}, + }, + { + {60, 61}, + {61, 60}, + }, + { + {60, 61}, + {61, 61}, + }, + { + {61, 61}, + {61, 61}, + }, + { + {61, 61}, + {62, 61}, + }, + { + {61, 62}, + {62, 61}, + }, + { + {61, 62}, + {62, 62}, + }, + { + {62, 62}, + {62, 62}, + }, + { + {62, 62}, + {63, 62}, + }, + { + {62, 63}, + {63, 62}, + }, + { + {62, 63}, + {63, 63}, + }, + { + {63, 63}, + {63, 63}, + }, }; /* Dither subtraction */ -static const uint8_t dithersub_rb[256][4][4] = -{ +static const uint8_t dithersub_rb[256][4][4] = { { {0, 0, 0, 0}, {0, 0, 0, 0}, @@ -6693,8 +6691,7 @@ static const uint8_t dithersub_rb[256][4][4] = }, }; -static const uint8_t dithersub_g[256][4][4] = -{ +static const uint8_t dithersub_g[256][4][4] = { { {0, 0, 0, 0}, {0, 0, 0, 0}, @@ -8233,8 +8230,7 @@ static const uint8_t dithersub_g[256][4][4] = }, }; -static const uint8_t dithersub_g2x2[256][2][2] = -{ +static const uint8_t dithersub_g2x2[256][2][2] = { { {0, 0}, {0, 0}, @@ -9261,8 +9257,7 @@ static const uint8_t dithersub_g2x2[256][2][2] = }, }; -static const uint8_t dithersub_rb2x2[256][2][2] = -{ +static const uint8_t dithersub_rb2x2[256][2][2] = { { {0, 0}, {0, 0}, @@ -10288,3 +10283,5 @@ static const uint8_t dithersub_rb2x2[256][2][2] = {253, 255}, }, }; + +#endif /* VIDEO_VOODOO_DITHER_H*/ diff --git a/src/include/86box/vid_voodoo_fb.h b/src/include/86box/vid_voodoo_fb.h index 95a223324..8a59b30ef 100644 --- a/src/include/86box/vid_voodoo_fb.h +++ b/src/include/86box/vid_voodoo_fb.h @@ -1,22 +1,27 @@ /* - * 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. + * 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. + * This file is part of the 86Box distribution. * - * Voodoo Graphics, 2, Banshee, 3 emulation. + * Voodoo Graphics, 2, Banshee, 3 emulation. * * * - * Authors: Sarah Walker, - * leilei + * Authors: Sarah Walker, + * leilei * - * Copyright 2008-2020 Sarah Walker. + * Copyright 2008-2020 Sarah Walker. */ -uint16_t voodoo_fb_readw(uint32_t addr, void *p); -uint32_t voodoo_fb_readl(uint32_t addr, void *p); -void voodoo_fb_writew(uint32_t addr, uint16_t val, void *p); -void voodoo_fb_writel(uint32_t addr, uint32_t val, void *p); +#ifndef VIDEO_VOODOO_FB_H +#define VIDEO_VOODOO_FB_H + +uint16_t voodoo_fb_readw(uint32_t addr, void *priv); +uint32_t voodoo_fb_readl(uint32_t addr, void *priv); +void voodoo_fb_writew(uint32_t addr, uint16_t val, void *priv); +void voodoo_fb_writel(uint32_t addr, uint32_t val, void *priv); + +#endif /*VIDEO_VOODOO_FB_H*/ diff --git a/src/include/86box/vid_voodoo_fifo.h b/src/include/86box/vid_voodoo_fifo.h index 0ba2f6920..e78d0dd6b 100644 --- a/src/include/86box/vid_voodoo_fifo.h +++ b/src/include/86box/vid_voodoo_fifo.h @@ -1,26 +1,31 @@ /* - * 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. + * 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. + * This file is part of the 86Box distribution. * - * Voodoo Graphics, 2, Banshee, 3 emulation. + * Voodoo Graphics, 2, Banshee, 3 emulation. * * * - * Authors: Sarah Walker, - * leilei + * Authors: Sarah Walker, + * leilei * - * Copyright 2008-2020 Sarah Walker. + * Copyright 2008-2020 Sarah Walker. */ +#ifndef VIDEO_VOODOO_FIFO_H +#define VIDEO_VOODOO_FIFO_H + void voodoo_wake_fifo_thread(voodoo_t *voodoo); void voodoo_wake_fifo_thread_now(voodoo_t *voodoo); -void voodoo_wake_timer(void *p); +void voodoo_wake_timer(void *priv); void voodoo_queue_command(voodoo_t *voodoo, uint32_t addr_type, uint32_t val); void voodoo_flush(voodoo_t *voodoo); void voodoo_wake_fifo_threads(voodoo_set_t *set, voodoo_t *voodoo); void voodoo_wait_for_swap_complete(voodoo_t *voodoo); void voodoo_fifo_thread(void *param); + +#endif /*VIDEO_VOODOO_FIFO_H*/ diff --git a/src/include/86box/vid_voodoo_reg.h b/src/include/86box/vid_voodoo_reg.h index 49fac4877..3dff4498c 100644 --- a/src/include/86box/vid_voodoo_reg.h +++ b/src/include/86box/vid_voodoo_reg.h @@ -1,19 +1,24 @@ /* - * 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. + * 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. + * This file is part of the 86Box distribution. * - * Voodoo Graphics, 2, Banshee, 3 emulation. + * Voodoo Graphics, 2, Banshee, 3 emulation. * * * - * Authors: Sarah Walker, - * leilei + * Authors: Sarah Walker, + * leilei * - * Copyright 2008-2020 Sarah Walker. + * Copyright 2008-2020 Sarah Walker. */ -void voodoo_reg_writel(uint32_t addr, uint32_t val, void *p); +#ifndef VIDEO_VOODOO_REG_H +#define VIDEO_VOODOO_REG_H + +void voodoo_reg_writel(uint32_t addr, uint32_t val, void *priv); + +#endif /*VIDEO_VOODOO_REG_H*/ diff --git a/src/include/86box/vid_voodoo_regs.h b/src/include/86box/vid_voodoo_regs.h index dfb924acf..f05029a8d 100644 --- a/src/include/86box/vid_voodoo_regs.h +++ b/src/include/86box/vid_voodoo_regs.h @@ -1,693 +1,660 @@ -enum -{ - SST_status = 0x000, - SST_intrCtrl = 0x004, +#ifndef VIDEO_VOODOO_REGS_H +#define VIDEO_VOODOO_REGS_H - SST_vertexAx = 0x008, - SST_vertexAy = 0x00c, - SST_vertexBx = 0x010, - SST_vertexBy = 0x014, - SST_vertexCx = 0x018, - SST_vertexCy = 0x01c, +enum { + SST_status = 0x000, + SST_intrCtrl = 0x004, - SST_startR = 0x0020, - SST_startG = 0x0024, - SST_startB = 0x0028, - SST_startZ = 0x002c, - SST_startA = 0x0030, - SST_startS = 0x0034, - SST_startT = 0x0038, - SST_startW = 0x003c, + SST_vertexAx = 0x008, + SST_vertexAy = 0x00c, + SST_vertexBx = 0x010, + SST_vertexBy = 0x014, + SST_vertexCx = 0x018, + SST_vertexCy = 0x01c, - SST_dRdX = 0x0040, - SST_dGdX = 0x0044, - SST_dBdX = 0x0048, - SST_dZdX = 0x004c, - SST_dAdX = 0x0050, - SST_dSdX = 0x0054, - SST_dTdX = 0x0058, - SST_dWdX = 0x005c, + SST_startR = 0x0020, + SST_startG = 0x0024, + SST_startB = 0x0028, + SST_startZ = 0x002c, + SST_startA = 0x0030, + SST_startS = 0x0034, + SST_startT = 0x0038, + SST_startW = 0x003c, - SST_dRdY = 0x0060, - SST_dGdY = 0x0064, - SST_dBdY = 0x0068, - SST_dZdY = 0x006c, - SST_dAdY = 0x0070, - SST_dSdY = 0x0074, - SST_dTdY = 0x0078, - SST_dWdY = 0x007c, + SST_dRdX = 0x0040, + SST_dGdX = 0x0044, + SST_dBdX = 0x0048, + SST_dZdX = 0x004c, + SST_dAdX = 0x0050, + SST_dSdX = 0x0054, + SST_dTdX = 0x0058, + SST_dWdX = 0x005c, - SST_triangleCMD = 0x0080, + SST_dRdY = 0x0060, + SST_dGdY = 0x0064, + SST_dBdY = 0x0068, + SST_dZdY = 0x006c, + SST_dAdY = 0x0070, + SST_dSdY = 0x0074, + SST_dTdY = 0x0078, + SST_dWdY = 0x007c, - SST_fvertexAx = 0x088, - SST_fvertexAy = 0x08c, - SST_fvertexBx = 0x090, - SST_fvertexBy = 0x094, - SST_fvertexCx = 0x098, - SST_fvertexCy = 0x09c, + SST_triangleCMD = 0x0080, - SST_fstartR = 0x00a0, - SST_fstartG = 0x00a4, - SST_fstartB = 0x00a8, - SST_fstartZ = 0x00ac, - SST_fstartA = 0x00b0, - SST_fstartS = 0x00b4, - SST_fstartT = 0x00b8, - SST_fstartW = 0x00bc, + SST_fvertexAx = 0x088, + SST_fvertexAy = 0x08c, + SST_fvertexBx = 0x090, + SST_fvertexBy = 0x094, + SST_fvertexCx = 0x098, + SST_fvertexCy = 0x09c, - SST_fdRdX = 0x00c0, - SST_fdGdX = 0x00c4, - SST_fdBdX = 0x00c8, - SST_fdZdX = 0x00cc, - SST_fdAdX = 0x00d0, - SST_fdSdX = 0x00d4, - SST_fdTdX = 0x00d8, - SST_fdWdX = 0x00dc, + SST_fstartR = 0x00a0, + SST_fstartG = 0x00a4, + SST_fstartB = 0x00a8, + SST_fstartZ = 0x00ac, + SST_fstartA = 0x00b0, + SST_fstartS = 0x00b4, + SST_fstartT = 0x00b8, + SST_fstartW = 0x00bc, - SST_fdRdY = 0x00e0, - SST_fdGdY = 0x00e4, - SST_fdBdY = 0x00e8, - SST_fdZdY = 0x00ec, - SST_fdAdY = 0x00f0, - SST_fdSdY = 0x00f4, - SST_fdTdY = 0x00f8, - SST_fdWdY = 0x00fc, + SST_fdRdX = 0x00c0, + SST_fdGdX = 0x00c4, + SST_fdBdX = 0x00c8, + SST_fdZdX = 0x00cc, + SST_fdAdX = 0x00d0, + SST_fdSdX = 0x00d4, + SST_fdTdX = 0x00d8, + SST_fdWdX = 0x00dc, - SST_ftriangleCMD = 0x0100, + SST_fdRdY = 0x00e0, + SST_fdGdY = 0x00e4, + SST_fdBdY = 0x00e8, + SST_fdZdY = 0x00ec, + SST_fdAdY = 0x00f0, + SST_fdSdY = 0x00f4, + SST_fdTdY = 0x00f8, + SST_fdWdY = 0x00fc, - SST_fbzColorPath = 0x104, - SST_fogMode = 0x108, + SST_ftriangleCMD = 0x0100, - SST_alphaMode = 0x10c, - SST_fbzMode = 0x110, - SST_lfbMode = 0x114, + SST_fbzColorPath = 0x104, + SST_fogMode = 0x108, - SST_clipLeftRight = 0x118, - SST_clipLowYHighY = 0x11c, + SST_alphaMode = 0x10c, + SST_fbzMode = 0x110, + SST_lfbMode = 0x114, - SST_nopCMD = 0x120, - SST_fastfillCMD = 0x124, - SST_swapbufferCMD = 0x128, + SST_clipLeftRight = 0x118, + SST_clipLowYHighY = 0x11c, - SST_fogColor = 0x12c, - SST_zaColor = 0x130, - SST_chromaKey = 0x134, + SST_nopCMD = 0x120, + SST_fastfillCMD = 0x124, + SST_swapbufferCMD = 0x128, - SST_userIntrCMD = 0x13c, - SST_stipple = 0x140, - SST_color0 = 0x144, - SST_color1 = 0x148, + SST_fogColor = 0x12c, + SST_zaColor = 0x130, + SST_chromaKey = 0x134, - SST_fbiPixelsIn = 0x14c, - SST_fbiChromaFail = 0x150, - SST_fbiZFuncFail = 0x154, - SST_fbiAFuncFail = 0x158, - SST_fbiPixelsOut = 0x15c, + SST_userIntrCMD = 0x13c, + SST_stipple = 0x140, + SST_color0 = 0x144, + SST_color1 = 0x148, - SST_fogTable00 = 0x160, - SST_fogTable01 = 0x164, - SST_fogTable02 = 0x168, - SST_fogTable03 = 0x16c, - SST_fogTable04 = 0x170, - SST_fogTable05 = 0x174, - SST_fogTable06 = 0x178, - SST_fogTable07 = 0x17c, - SST_fogTable08 = 0x180, - SST_fogTable09 = 0x184, - SST_fogTable0a = 0x188, - SST_fogTable0b = 0x18c, - SST_fogTable0c = 0x190, - SST_fogTable0d = 0x194, - SST_fogTable0e = 0x198, - SST_fogTable0f = 0x19c, - SST_fogTable10 = 0x1a0, - SST_fogTable11 = 0x1a4, - SST_fogTable12 = 0x1a8, - SST_fogTable13 = 0x1ac, - SST_fogTable14 = 0x1b0, - SST_fogTable15 = 0x1b4, - SST_fogTable16 = 0x1b8, - SST_fogTable17 = 0x1bc, - SST_fogTable18 = 0x1c0, - SST_fogTable19 = 0x1c4, - SST_fogTable1a = 0x1c8, - SST_fogTable1b = 0x1cc, - SST_fogTable1c = 0x1d0, - SST_fogTable1d = 0x1d4, - SST_fogTable1e = 0x1d8, - SST_fogTable1f = 0x1dc, + SST_fbiPixelsIn = 0x14c, + SST_fbiChromaFail = 0x150, + SST_fbiZFuncFail = 0x154, + SST_fbiAFuncFail = 0x158, + SST_fbiPixelsOut = 0x15c, - SST_cmdFifoBaseAddr = 0x1e0, - SST_cmdFifoBump = 0x1e4, - SST_cmdFifoRdPtr = 0x1e8, - SST_cmdFifoAMin = 0x1ec, - SST_cmdFifoAMax = 0x1f0, - SST_cmdFifoDepth = 0x1f4, - SST_cmdFifoHoles = 0x1f8, - - SST_colBufferAddr = 0x1ec, /*Banshee*/ - SST_colBufferStride = 0x1f0, /*Banshee*/ - SST_auxBufferAddr = 0x1f4, /*Banshee*/ - SST_auxBufferStride = 0x1f8, /*Banshee*/ + SST_fogTable00 = 0x160, + SST_fogTable01 = 0x164, + SST_fogTable02 = 0x168, + SST_fogTable03 = 0x16c, + SST_fogTable04 = 0x170, + SST_fogTable05 = 0x174, + SST_fogTable06 = 0x178, + SST_fogTable07 = 0x17c, + SST_fogTable08 = 0x180, + SST_fogTable09 = 0x184, + SST_fogTable0a = 0x188, + SST_fogTable0b = 0x18c, + SST_fogTable0c = 0x190, + SST_fogTable0d = 0x194, + SST_fogTable0e = 0x198, + SST_fogTable0f = 0x19c, + SST_fogTable10 = 0x1a0, + SST_fogTable11 = 0x1a4, + SST_fogTable12 = 0x1a8, + SST_fogTable13 = 0x1ac, + SST_fogTable14 = 0x1b0, + SST_fogTable15 = 0x1b4, + SST_fogTable16 = 0x1b8, + SST_fogTable17 = 0x1bc, + SST_fogTable18 = 0x1c0, + SST_fogTable19 = 0x1c4, + SST_fogTable1a = 0x1c8, + SST_fogTable1b = 0x1cc, + SST_fogTable1c = 0x1d0, + SST_fogTable1d = 0x1d4, + SST_fogTable1e = 0x1d8, + SST_fogTable1f = 0x1dc, - SST_clipLeftRight1 = 0x200, /*Banshee*/ - SST_clipTopBottom1 = 0x204, /*Banshee*/ + SST_cmdFifoBaseAddr = 0x1e0, + SST_cmdFifoBump = 0x1e4, + SST_cmdFifoRdPtr = 0x1e8, + SST_cmdFifoAMin = 0x1ec, + SST_cmdFifoAMax = 0x1f0, + SST_cmdFifoDepth = 0x1f4, + SST_cmdFifoHoles = 0x1f8, - SST_fbiInit4 = 0x200, - SST_vRetrace = 0x204, - SST_backPorch = 0x208, - SST_videoDimensions = 0x20c, - SST_fbiInit0 = 0x210, - SST_fbiInit1 = 0x214, - SST_fbiInit2 = 0x218, - SST_fbiInit3 = 0x21c, - SST_hSync = 0x220, - SST_vSync = 0x224, - SST_clutData = 0x228, - SST_dacData = 0x22c, + SST_colBufferAddr = 0x1ec, /*Banshee*/ + SST_colBufferStride = 0x1f0, /*Banshee*/ + SST_auxBufferAddr = 0x1f4, /*Banshee*/ + SST_auxBufferStride = 0x1f8, /*Banshee*/ - SST_scrFilter = 0x230, + SST_clipLeftRight1 = 0x200, /*Banshee*/ + SST_clipTopBottom1 = 0x204, /*Banshee*/ - SST_hvRetrace = 0x240, - SST_fbiInit5 = 0x244, - SST_fbiInit6 = 0x248, - SST_fbiInit7 = 0x24c, - - SST_swapPending = 0x24c, /*Banshee*/ - SST_leftOverlayBuf = 0x250, /*Banshee*/ - - SST_sSetupMode = 0x260, - SST_sVx = 0x264, - SST_sVy = 0x268, - SST_sARGB = 0x26c, - SST_sRed = 0x270, - SST_sGreen = 0x274, - SST_sBlue = 0x278, - SST_sAlpha = 0x27c, - SST_sVz = 0x280, - SST_sWb = 0x284, - SST_sW0 = 0x288, - SST_sS0 = 0x28c, - SST_sT0 = 0x290, - SST_sW1 = 0x294, - SST_sS1 = 0x298, - SST_sT1 = 0x29c, + SST_fbiInit4 = 0x200, + SST_vRetrace = 0x204, + SST_backPorch = 0x208, + SST_videoDimensions = 0x20c, + SST_fbiInit0 = 0x210, + SST_fbiInit1 = 0x214, + SST_fbiInit2 = 0x218, + SST_fbiInit3 = 0x21c, + SST_hSync = 0x220, + SST_vSync = 0x224, + SST_clutData = 0x228, + SST_dacData = 0x22c, - SST_sDrawTriCMD = 0x2a0, - SST_sBeginTriCMD = 0x2a4, + SST_scrFilter = 0x230, - SST_bltSrcBaseAddr = 0x2c0, - SST_bltDstBaseAddr = 0x2c4, - SST_bltXYStrides = 0x2c8, - SST_bltSrcChromaRange = 0x2cc, - SST_bltDstChromaRange = 0x2d0, - SST_bltClipX = 0x2d4, - SST_bltClipY = 0x2d8, + SST_hvRetrace = 0x240, + SST_fbiInit5 = 0x244, + SST_fbiInit6 = 0x248, + SST_fbiInit7 = 0x24c, - SST_bltSrcXY = 0x2e0, - SST_bltDstXY = 0x2e4, - SST_bltSize = 0x2e8, - SST_bltRop = 0x2ec, - SST_bltColor = 0x2f0, + SST_swapPending = 0x24c, /*Banshee*/ + SST_leftOverlayBuf = 0x250, /*Banshee*/ - SST_bltCommand = 0x2f8, - SST_bltData = 0x2fc, + SST_sSetupMode = 0x260, + SST_sVx = 0x264, + SST_sVy = 0x268, + SST_sARGB = 0x26c, + SST_sRed = 0x270, + SST_sGreen = 0x274, + SST_sBlue = 0x278, + SST_sAlpha = 0x27c, + SST_sVz = 0x280, + SST_sWb = 0x284, + SST_sW0 = 0x288, + SST_sS0 = 0x28c, + SST_sT0 = 0x290, + SST_sW1 = 0x294, + SST_sS1 = 0x298, + SST_sT1 = 0x29c, - SST_textureMode = 0x300, - SST_tLOD = 0x304, - SST_tDetail = 0x308, - SST_texBaseAddr = 0x30c, - SST_texBaseAddr1 = 0x310, - SST_texBaseAddr2 = 0x314, - SST_texBaseAddr38 = 0x318, + SST_sDrawTriCMD = 0x2a0, + SST_sBeginTriCMD = 0x2a4, - SST_trexInit1 = 0x320, + SST_bltSrcBaseAddr = 0x2c0, + SST_bltDstBaseAddr = 0x2c4, + SST_bltXYStrides = 0x2c8, + SST_bltSrcChromaRange = 0x2cc, + SST_bltDstChromaRange = 0x2d0, + SST_bltClipX = 0x2d4, + SST_bltClipY = 0x2d8, - SST_nccTable0_Y0 = 0x324, - SST_nccTable0_Y1 = 0x328, - SST_nccTable0_Y2 = 0x32c, - SST_nccTable0_Y3 = 0x330, - SST_nccTable0_I0 = 0x334, - SST_nccTable0_I1 = 0x338, - SST_nccTable0_I2 = 0x33c, - SST_nccTable0_I3 = 0x340, - SST_nccTable0_Q0 = 0x344, - SST_nccTable0_Q1 = 0x348, - SST_nccTable0_Q2 = 0x34c, - SST_nccTable0_Q3 = 0x350, + SST_bltSrcXY = 0x2e0, + SST_bltDstXY = 0x2e4, + SST_bltSize = 0x2e8, + SST_bltRop = 0x2ec, + SST_bltColor = 0x2f0, - SST_nccTable1_Y0 = 0x354, - SST_nccTable1_Y1 = 0x358, - SST_nccTable1_Y2 = 0x35c, - SST_nccTable1_Y3 = 0x360, - SST_nccTable1_I0 = 0x364, - SST_nccTable1_I1 = 0x368, - SST_nccTable1_I2 = 0x36c, - SST_nccTable1_I3 = 0x370, - SST_nccTable1_Q0 = 0x374, - SST_nccTable1_Q1 = 0x378, - SST_nccTable1_Q2 = 0x37c, - SST_nccTable1_Q3 = 0x380, + SST_bltCommand = 0x2f8, + SST_bltData = 0x2fc, - SST_remap_status = 0x000 | 0x400, + SST_textureMode = 0x300, + SST_tLOD = 0x304, + SST_tDetail = 0x308, + SST_texBaseAddr = 0x30c, + SST_texBaseAddr1 = 0x310, + SST_texBaseAddr2 = 0x314, + SST_texBaseAddr38 = 0x318, - SST_remap_vertexAx = 0x008 | 0x400, - SST_remap_vertexAy = 0x00c | 0x400, - SST_remap_vertexBx = 0x010 | 0x400, - SST_remap_vertexBy = 0x014 | 0x400, - SST_remap_vertexCx = 0x018 | 0x400, - SST_remap_vertexCy = 0x01c | 0x400, + SST_trexInit1 = 0x320, - SST_remap_startR = 0x0020 | 0x400, - SST_remap_startG = 0x002c | 0x400, - SST_remap_startB = 0x0038 | 0x400, - SST_remap_startZ = 0x0044 | 0x400, - SST_remap_startA = 0x0050 | 0x400, - SST_remap_startS = 0x005c | 0x400, - SST_remap_startT = 0x0068 | 0x400, - SST_remap_startW = 0x0074 | 0x400, + SST_nccTable0_Y0 = 0x324, + SST_nccTable0_Y1 = 0x328, + SST_nccTable0_Y2 = 0x32c, + SST_nccTable0_Y3 = 0x330, + SST_nccTable0_I0 = 0x334, + SST_nccTable0_I1 = 0x338, + SST_nccTable0_I2 = 0x33c, + SST_nccTable0_I3 = 0x340, + SST_nccTable0_Q0 = 0x344, + SST_nccTable0_Q1 = 0x348, + SST_nccTable0_Q2 = 0x34c, + SST_nccTable0_Q3 = 0x350, - SST_remap_dRdX = 0x0024 | 0x400, - SST_remap_dGdX = 0x0030 | 0x400, - SST_remap_dBdX = 0x003c | 0x400, - SST_remap_dZdX = 0x0048 | 0x400, - SST_remap_dAdX = 0x0054 | 0x400, - SST_remap_dSdX = 0x0060 | 0x400, - SST_remap_dTdX = 0x006c | 0x400, - SST_remap_dWdX = 0x0078 | 0x400, + SST_nccTable1_Y0 = 0x354, + SST_nccTable1_Y1 = 0x358, + SST_nccTable1_Y2 = 0x35c, + SST_nccTable1_Y3 = 0x360, + SST_nccTable1_I0 = 0x364, + SST_nccTable1_I1 = 0x368, + SST_nccTable1_I2 = 0x36c, + SST_nccTable1_I3 = 0x370, + SST_nccTable1_Q0 = 0x374, + SST_nccTable1_Q1 = 0x378, + SST_nccTable1_Q2 = 0x37c, + SST_nccTable1_Q3 = 0x380, - SST_remap_dRdY = 0x0028 | 0x400, - SST_remap_dGdY = 0x0034 | 0x400, - SST_remap_dBdY = 0x0040 | 0x400, - SST_remap_dZdY = 0x004c | 0x400, - SST_remap_dAdY = 0x0058 | 0x400, - SST_remap_dSdY = 0x0064 | 0x400, - SST_remap_dTdY = 0x0070 | 0x400, - SST_remap_dWdY = 0x007c | 0x400, + SST_remap_status = 0x000 | 0x400, - SST_remap_triangleCMD = 0x0080 | 0x400, + SST_remap_vertexAx = 0x008 | 0x400, + SST_remap_vertexAy = 0x00c | 0x400, + SST_remap_vertexBx = 0x010 | 0x400, + SST_remap_vertexBy = 0x014 | 0x400, + SST_remap_vertexCx = 0x018 | 0x400, + SST_remap_vertexCy = 0x01c | 0x400, - SST_remap_fvertexAx = 0x088 | 0x400, - SST_remap_fvertexAy = 0x08c | 0x400, - SST_remap_fvertexBx = 0x090 | 0x400, - SST_remap_fvertexBy = 0x094 | 0x400, - SST_remap_fvertexCx = 0x098 | 0x400, - SST_remap_fvertexCy = 0x09c | 0x400, + SST_remap_startR = 0x0020 | 0x400, + SST_remap_startG = 0x002c | 0x400, + SST_remap_startB = 0x0038 | 0x400, + SST_remap_startZ = 0x0044 | 0x400, + SST_remap_startA = 0x0050 | 0x400, + SST_remap_startS = 0x005c | 0x400, + SST_remap_startT = 0x0068 | 0x400, + SST_remap_startW = 0x0074 | 0x400, - SST_remap_fstartR = 0x00a0 | 0x400, - SST_remap_fstartG = 0x00ac | 0x400, - SST_remap_fstartB = 0x00b8 | 0x400, - SST_remap_fstartZ = 0x00c4 | 0x400, - SST_remap_fstartA = 0x00d0 | 0x400, - SST_remap_fstartS = 0x00dc | 0x400, - SST_remap_fstartT = 0x00e8 | 0x400, - SST_remap_fstartW = 0x00f4 | 0x400, + SST_remap_dRdX = 0x0024 | 0x400, + SST_remap_dGdX = 0x0030 | 0x400, + SST_remap_dBdX = 0x003c | 0x400, + SST_remap_dZdX = 0x0048 | 0x400, + SST_remap_dAdX = 0x0054 | 0x400, + SST_remap_dSdX = 0x0060 | 0x400, + SST_remap_dTdX = 0x006c | 0x400, + SST_remap_dWdX = 0x0078 | 0x400, - SST_remap_fdRdX = 0x00a4 | 0x400, - SST_remap_fdGdX = 0x00b0 | 0x400, - SST_remap_fdBdX = 0x00bc | 0x400, - SST_remap_fdZdX = 0x00c8 | 0x400, - SST_remap_fdAdX = 0x00d4 | 0x400, - SST_remap_fdSdX = 0x00e0 | 0x400, - SST_remap_fdTdX = 0x00ec | 0x400, - SST_remap_fdWdX = 0x00f8 | 0x400, + SST_remap_dRdY = 0x0028 | 0x400, + SST_remap_dGdY = 0x0034 | 0x400, + SST_remap_dBdY = 0x0040 | 0x400, + SST_remap_dZdY = 0x004c | 0x400, + SST_remap_dAdY = 0x0058 | 0x400, + SST_remap_dSdY = 0x0064 | 0x400, + SST_remap_dTdY = 0x0070 | 0x400, + SST_remap_dWdY = 0x007c | 0x400, - SST_remap_fdRdY = 0x00a8 | 0x400, - SST_remap_fdGdY = 0x00b4 | 0x400, - SST_remap_fdBdY = 0x00c0 | 0x400, - SST_remap_fdZdY = 0x00cc | 0x400, - SST_remap_fdAdY = 0x00d8 | 0x400, - SST_remap_fdSdY = 0x00e4 | 0x400, - SST_remap_fdTdY = 0x00f0 | 0x400, - SST_remap_fdWdY = 0x00fc | 0x400, + SST_remap_triangleCMD = 0x0080 | 0x400, + + SST_remap_fvertexAx = 0x088 | 0x400, + SST_remap_fvertexAy = 0x08c | 0x400, + SST_remap_fvertexBx = 0x090 | 0x400, + SST_remap_fvertexBy = 0x094 | 0x400, + SST_remap_fvertexCx = 0x098 | 0x400, + SST_remap_fvertexCy = 0x09c | 0x400, + + SST_remap_fstartR = 0x00a0 | 0x400, + SST_remap_fstartG = 0x00ac | 0x400, + SST_remap_fstartB = 0x00b8 | 0x400, + SST_remap_fstartZ = 0x00c4 | 0x400, + SST_remap_fstartA = 0x00d0 | 0x400, + SST_remap_fstartS = 0x00dc | 0x400, + SST_remap_fstartT = 0x00e8 | 0x400, + SST_remap_fstartW = 0x00f4 | 0x400, + + SST_remap_fdRdX = 0x00a4 | 0x400, + SST_remap_fdGdX = 0x00b0 | 0x400, + SST_remap_fdBdX = 0x00bc | 0x400, + SST_remap_fdZdX = 0x00c8 | 0x400, + SST_remap_fdAdX = 0x00d4 | 0x400, + SST_remap_fdSdX = 0x00e0 | 0x400, + SST_remap_fdTdX = 0x00ec | 0x400, + SST_remap_fdWdX = 0x00f8 | 0x400, + + SST_remap_fdRdY = 0x00a8 | 0x400, + SST_remap_fdGdY = 0x00b4 | 0x400, + SST_remap_fdBdY = 0x00c0 | 0x400, + SST_remap_fdZdY = 0x00cc | 0x400, + SST_remap_fdAdY = 0x00d8 | 0x400, + SST_remap_fdSdY = 0x00e4 | 0x400, + SST_remap_fdTdY = 0x00f0 | 0x400, + SST_remap_fdWdY = 0x00fc | 0x400, }; -enum -{ - LFB_WRITE_FRONT = 0x0000, - LFB_WRITE_BACK = 0x0010, - LFB_WRITE_MASK = 0x0030 +enum { + LFB_WRITE_FRONT = 0x0000, + LFB_WRITE_BACK = 0x0010, + LFB_WRITE_MASK = 0x0030 }; -enum -{ - LFB_READ_FRONT = 0x0000, - LFB_READ_BACK = 0x0040, - LFB_READ_AUX = 0x0080, - LFB_READ_MASK = 0x00c0 +enum { + LFB_READ_FRONT = 0x0000, + LFB_READ_BACK = 0x0040, + LFB_READ_AUX = 0x0080, + LFB_READ_MASK = 0x00c0 }; -enum -{ - LFB_FORMAT_RGB565 = 0, - LFB_FORMAT_RGB555 = 1, - LFB_FORMAT_ARGB1555 = 2, - LFB_FORMAT_ARGB8888 = 5, - LFB_FORMAT_DEPTH = 15, - LFB_FORMAT_MASK = 15 +enum { + LFB_FORMAT_RGB565 = 0, + LFB_FORMAT_RGB555 = 1, + LFB_FORMAT_ARGB1555 = 2, + LFB_FORMAT_ARGB8888 = 5, + LFB_FORMAT_DEPTH = 15, + LFB_FORMAT_MASK = 15 }; -enum -{ - LFB_WRITE_COLOUR = 1, - LFB_WRITE_DEPTH = 2 +enum { + LFB_WRITE_COLOUR = 1, + LFB_WRITE_DEPTH = 2 }; -enum -{ - FBZ_CHROMAKEY = (1 << 1), - FBZ_W_BUFFER = (1 << 3), - FBZ_DEPTH_ENABLE = (1 << 4), +enum { + FBZ_CHROMAKEY = (1 << 1), + FBZ_W_BUFFER = (1 << 3), + FBZ_DEPTH_ENABLE = (1 << 4), - FBZ_DITHER = (1 << 8), - FBZ_RGB_WMASK = (1 << 9), - FBZ_DEPTH_WMASK = (1 << 10), - FBZ_DITHER_2x2 = (1 << 11), + FBZ_DITHER = (1 << 8), + FBZ_RGB_WMASK = (1 << 9), + FBZ_DEPTH_WMASK = (1 << 10), + FBZ_DITHER_2x2 = (1 << 11), - FBZ_DRAW_FRONT = 0x0000, - FBZ_DRAW_BACK = 0x4000, - FBZ_DRAW_MASK = 0xc000, + FBZ_DRAW_FRONT = 0x0000, + FBZ_DRAW_BACK = 0x4000, + FBZ_DRAW_MASK = 0xc000, - FBZ_DEPTH_BIAS = (1 << 16), - FBZ_DITHER_SUB = (1 << 19), + FBZ_DEPTH_BIAS = (1 << 16), + FBZ_DITHER_SUB = (1 << 19), - FBZ_DEPTH_SOURCE = (1 << 20), + FBZ_DEPTH_SOURCE = (1 << 20), - FBZ_PARAM_ADJUST = (1 << 26) + FBZ_PARAM_ADJUST = (1 << 26) }; -enum -{ - TEX_RGB332 = 0x0, - TEX_Y4I2Q2 = 0x1, - TEX_A8 = 0x2, - TEX_I8 = 0x3, - TEX_AI8 = 0x4, - TEX_PAL8 = 0x5, - TEX_APAL8 = 0x6, - TEX_ARGB8332 = 0x8, - TEX_A8Y4I2Q2 = 0x9, - TEX_R5G6B5 = 0xa, - TEX_ARGB1555 = 0xb, - TEX_ARGB4444 = 0xc, - TEX_A8I8 = 0xd, - TEX_APAL88 = 0xe +enum { + TEX_RGB332 = 0x0, + TEX_Y4I2Q2 = 0x1, + TEX_A8 = 0x2, + TEX_I8 = 0x3, + TEX_AI8 = 0x4, + TEX_PAL8 = 0x5, + TEX_APAL8 = 0x6, + TEX_ARGB8332 = 0x8, + TEX_A8Y4I2Q2 = 0x9, + TEX_R5G6B5 = 0xa, + TEX_ARGB1555 = 0xb, + TEX_ARGB4444 = 0xc, + TEX_A8I8 = 0xd, + TEX_APAL88 = 0xe }; -enum -{ - TEXTUREMODE_NCC_SEL = (1 << 5), - TEXTUREMODE_TCLAMPS = (1 << 6), - TEXTUREMODE_TCLAMPT = (1 << 7), - TEXTUREMODE_TRILINEAR = (1 << 30) +enum { + TEXTUREMODE_NCC_SEL = (1 << 5), + TEXTUREMODE_TCLAMPS = (1 << 6), + TEXTUREMODE_TCLAMPT = (1 << 7), + TEXTUREMODE_TRILINEAR = (1 << 30) }; -enum -{ - FBIINIT0_VGA_PASS = 1, - FBIINIT0_GRAPHICS_RESET = (1 << 1) +enum { + FBIINIT0_VGA_PASS = 1, + FBIINIT0_GRAPHICS_RESET = (1 << 1) }; -enum -{ - FBIINIT1_MULTI_SST = (1 << 2), /*Voodoo Graphics only*/ - FBIINIT1_VIDEO_RESET = (1 << 8), - FBIINIT1_SLI_ENABLE = (1 << 23) +enum { + FBIINIT1_MULTI_SST = (1 << 2), /*Voodoo Graphics only*/ + FBIINIT1_VIDEO_RESET = (1 << 8), + FBIINIT1_SLI_ENABLE = (1 << 23) }; -enum -{ - FBIINIT2_SWAP_ALGORITHM_MASK = (3 << 9) +enum { + FBIINIT2_SWAP_ALGORITHM_MASK = (3 << 9) }; -enum -{ - FBIINIT2_SWAP_ALGORITHM_DAC_VSYNC = (0 << 9), - FBIINIT2_SWAP_ALGORITHM_DAC_DATA = (1 << 9), - FBIINIT2_SWAP_ALGORITHM_PCI_FIFO_STALL = (2 << 9), - FBIINIT2_SWAP_ALGORITHM_SLI_SYNC = (3 << 9) +enum { + FBIINIT2_SWAP_ALGORITHM_DAC_VSYNC = (0 << 9), + FBIINIT2_SWAP_ALGORITHM_DAC_DATA = (1 << 9), + FBIINIT2_SWAP_ALGORITHM_PCI_FIFO_STALL = (2 << 9), + FBIINIT2_SWAP_ALGORITHM_SLI_SYNC = (3 << 9) }; -enum -{ - FBIINIT3_REMAP = 1 +enum { + FBIINIT3_REMAP = 1 }; -enum -{ - FBIINIT5_MULTI_CVG = (1 << 14) +enum { + FBIINIT5_MULTI_CVG = (1 << 14) }; -enum -{ - FBIINIT7_CMDFIFO_ENABLE = (1 << 8) +enum { + FBIINIT7_CMDFIFO_ENABLE = (1 << 8) }; -enum -{ - CC_LOCALSELECT_ITER_RGB = 0, - CC_LOCALSELECT_TEX = 1, - CC_LOCALSELECT_COLOR1 = 2, - CC_LOCALSELECT_LFB = 3 +enum { + CC_LOCALSELECT_ITER_RGB = 0, + CC_LOCALSELECT_TEX = 1, + CC_LOCALSELECT_COLOR1 = 2, + CC_LOCALSELECT_LFB = 3 }; -enum -{ - CCA_LOCALSELECT_ITER_A = 0, - CCA_LOCALSELECT_COLOR0 = 1, - CCA_LOCALSELECT_ITER_Z = 2 +enum { + CCA_LOCALSELECT_ITER_A = 0, + CCA_LOCALSELECT_COLOR0 = 1, + CCA_LOCALSELECT_ITER_Z = 2 }; -enum -{ - C_SEL_ITER_RGB = 0, - C_SEL_TEX = 1, - C_SEL_COLOR1 = 2, - C_SEL_LFB = 3 +enum { + C_SEL_ITER_RGB = 0, + C_SEL_TEX = 1, + C_SEL_COLOR1 = 2, + C_SEL_LFB = 3 }; -enum -{ - A_SEL_ITER_A = 0, - A_SEL_TEX = 1, - A_SEL_COLOR1 = 2, - A_SEL_LFB = 3 +enum { + A_SEL_ITER_A = 0, + A_SEL_TEX = 1, + A_SEL_COLOR1 = 2, + A_SEL_LFB = 3 }; -enum -{ - CC_MSELECT_ZERO = 0, - CC_MSELECT_CLOCAL = 1, - CC_MSELECT_AOTHER = 2, - CC_MSELECT_ALOCAL = 3, - CC_MSELECT_TEX = 4, - CC_MSELECT_TEXRGB = 5 +enum { + CC_MSELECT_ZERO = 0, + CC_MSELECT_CLOCAL = 1, + CC_MSELECT_AOTHER = 2, + CC_MSELECT_ALOCAL = 3, + CC_MSELECT_TEX = 4, + CC_MSELECT_TEXRGB = 5 }; -enum -{ - CCA_MSELECT_ZERO = 0, - CCA_MSELECT_ALOCAL = 1, - CCA_MSELECT_AOTHER = 2, - CCA_MSELECT_ALOCAL2 = 3, - CCA_MSELECT_TEX = 4 +enum { + CCA_MSELECT_ZERO = 0, + CCA_MSELECT_ALOCAL = 1, + CCA_MSELECT_AOTHER = 2, + CCA_MSELECT_ALOCAL2 = 3, + CCA_MSELECT_TEX = 4 }; -enum -{ - TC_MSELECT_ZERO = 0, - TC_MSELECT_CLOCAL = 1, - TC_MSELECT_AOTHER = 2, - TC_MSELECT_ALOCAL = 3, - TC_MSELECT_DETAIL = 4, - TC_MSELECT_LOD_FRAC = 5 +enum { + TC_MSELECT_ZERO = 0, + TC_MSELECT_CLOCAL = 1, + TC_MSELECT_AOTHER = 2, + TC_MSELECT_ALOCAL = 3, + TC_MSELECT_DETAIL = 4, + TC_MSELECT_LOD_FRAC = 5 }; -enum -{ - TCA_MSELECT_ZERO = 0, - TCA_MSELECT_CLOCAL = 1, - TCA_MSELECT_AOTHER = 2, - TCA_MSELECT_ALOCAL = 3, - TCA_MSELECT_DETAIL = 4, - TCA_MSELECT_LOD_FRAC = 5 +enum { + TCA_MSELECT_ZERO = 0, + TCA_MSELECT_CLOCAL = 1, + TCA_MSELECT_AOTHER = 2, + TCA_MSELECT_ALOCAL = 3, + TCA_MSELECT_DETAIL = 4, + TCA_MSELECT_LOD_FRAC = 5 }; -enum -{ - CC_ADD_CLOCAL = 1, - CC_ADD_ALOCAL = 2 +enum { + CC_ADD_CLOCAL = 1, + CC_ADD_ALOCAL = 2 }; -enum -{ - CCA_ADD_CLOCAL = 1, - CCA_ADD_ALOCAL = 2 +enum { + CCA_ADD_CLOCAL = 1, + CCA_ADD_ALOCAL = 2 }; -enum -{ - AFUNC_AZERO = 0x0, - AFUNC_ASRC_ALPHA = 0x1, - AFUNC_A_COLOR = 0x2, - AFUNC_ADST_ALPHA = 0x3, - AFUNC_AONE = 0x4, - AFUNC_AOMSRC_ALPHA = 0x5, - AFUNC_AOM_COLOR = 0x6, - AFUNC_AOMDST_ALPHA = 0x7, - AFUNC_ASATURATE = 0xf +enum { + AFUNC_AZERO = 0x0, + AFUNC_ASRC_ALPHA = 0x1, + AFUNC_A_COLOR = 0x2, + AFUNC_ADST_ALPHA = 0x3, + AFUNC_AONE = 0x4, + AFUNC_AOMSRC_ALPHA = 0x5, + AFUNC_AOM_COLOR = 0x6, + AFUNC_AOMDST_ALPHA = 0x7, + AFUNC_ASATURATE = 0xf }; -enum -{ - AFUNC_ACOLORBEFOREFOG = 0xf +enum { + AFUNC_ACOLORBEFOREFOG = 0xf }; -enum -{ - AFUNC_NEVER = 0, - AFUNC_LESSTHAN = 1, - AFUNC_EQUAL = 2, - AFUNC_LESSTHANEQUAL = 3, - AFUNC_GREATERTHAN = 4, - AFUNC_NOTEQUAL = 5, - AFUNC_GREATERTHANEQUAL = 6, - AFUNC_ALWAYS = 7 +enum { + AFUNC_NEVER = 0, + AFUNC_LESSTHAN = 1, + AFUNC_EQUAL = 2, + AFUNC_LESSTHANEQUAL = 3, + AFUNC_GREATERTHAN = 4, + AFUNC_NOTEQUAL = 5, + AFUNC_GREATERTHANEQUAL = 6, + AFUNC_ALWAYS = 7 }; -enum -{ - DEPTHOP_NEVER = 0, - DEPTHOP_LESSTHAN = 1, - DEPTHOP_EQUAL = 2, - DEPTHOP_LESSTHANEQUAL = 3, - DEPTHOP_GREATERTHAN = 4, - DEPTHOP_NOTEQUAL = 5, - DEPTHOP_GREATERTHANEQUAL = 6, - DEPTHOP_ALWAYS = 7 +enum { + DEPTHOP_NEVER = 0, + DEPTHOP_LESSTHAN = 1, + DEPTHOP_EQUAL = 2, + DEPTHOP_LESSTHANEQUAL = 3, + DEPTHOP_GREATERTHAN = 4, + DEPTHOP_NOTEQUAL = 5, + DEPTHOP_GREATERTHANEQUAL = 6, + DEPTHOP_ALWAYS = 7 }; -enum -{ - FOG_ENABLE = 0x01, - FOG_ADD = 0x02, - FOG_MULT = 0x04, - FOG_ALPHA = 0x08, - FOG_Z = 0x10, - FOG_W = 0x18, - FOG_CONSTANT = 0x20 +enum { + FOG_ENABLE = 0x01, + FOG_ADD = 0x02, + FOG_MULT = 0x04, + FOG_ALPHA = 0x08, + FOG_Z = 0x10, + FOG_W = 0x18, + FOG_CONSTANT = 0x20 }; -enum -{ - LOD_ODD = (1 << 18), - LOD_SPLIT = (1 << 19), - LOD_S_IS_WIDER = (1 << 20), - LOD_TMULTIBASEADDR = (1 << 24), - LOD_TMIRROR_S = (1 << 28), - LOD_TMIRROR_T = (1 << 29) +enum { + LOD_ODD = (1 << 18), + LOD_SPLIT = (1 << 19), + LOD_S_IS_WIDER = (1 << 20), + LOD_TMULTIBASEADDR = (1 << 24), + LOD_TMIRROR_S = (1 << 28), + LOD_TMIRROR_T = (1 << 29) }; -enum -{ - CMD_INVALID = 0, - CMD_DRAWTRIANGLE, - CMD_FASTFILL, - CMD_SWAPBUF +enum { + CMD_INVALID = 0, + CMD_DRAWTRIANGLE, + CMD_FASTFILL, + CMD_SWAPBUF }; -enum -{ - FBZCP_TEXTURE_ENABLED = (1 << 27) +enum { + FBZCP_TEXTURE_ENABLED = (1 << 27) }; -enum -{ - BLTCMD_SRC_TILED = (1 << 14), - BLTCMD_DST_TILED = (1 << 15) +enum { + BLTCMD_SRC_TILED = (1 << 14), + BLTCMD_DST_TILED = (1 << 15) }; -enum -{ - INITENABLE_SLI_MASTER_SLAVE = (1 << 11) +enum { + INITENABLE_SLI_MASTER_SLAVE = (1 << 11) }; -enum -{ - SETUPMODE_RGB = (1 << 0), - SETUPMODE_ALPHA = (1 << 1), - SETUPMODE_Z = (1 << 2), - SETUPMODE_Wb = (1 << 3), - SETUPMODE_W0 = (1 << 4), - SETUPMODE_S0_T0 = (1 << 5), - SETUPMODE_W1 = (1 << 6), - SETUPMODE_S1_T1 = (1 << 7), +enum { + SETUPMODE_RGB = (1 << 0), + SETUPMODE_ALPHA = (1 << 1), + SETUPMODE_Z = (1 << 2), + SETUPMODE_Wb = (1 << 3), + SETUPMODE_W0 = (1 << 4), + SETUPMODE_S0_T0 = (1 << 5), + SETUPMODE_W1 = (1 << 6), + SETUPMODE_S1_T1 = (1 << 7), - SETUPMODE_STRIP_MODE = (1 << 16), - SETUPMODE_CULLING_ENABLE = (1 << 17), - SETUPMODE_CULLING_SIGN = (1 << 18), - SETUPMODE_DISABLE_PINGPONG = (1 << 19) + SETUPMODE_STRIP_MODE = (1 << 16), + SETUPMODE_CULLING_ENABLE = (1 << 17), + SETUPMODE_CULLING_SIGN = (1 << 18), + SETUPMODE_DISABLE_PINGPONG = (1 << 19) }; -#define TEXTUREMODE_MASK 0x3ffff000 +#define TEXTUREMODE_MASK 0x3ffff000 #define TEXTUREMODE_PASSTHROUGH 0 -#define TEXTUREMODE_LOCAL_MASK 0x00643000 -#define TEXTUREMODE_LOCAL 0x00241000 +#define TEXTUREMODE_LOCAL_MASK 0x00643000 +#define TEXTUREMODE_LOCAL 0x00241000 +#define SLI_ENABLED (voodoo->fbiInit1 & FBIINIT1_SLI_ENABLE) +#define TRIPLE_BUFFER ((voodoo->fbiInit2 & 0x10) || (voodoo->fbiInit5 & 0x600) == 0x400) -#define SLI_ENABLED (voodoo->fbiInit1 & FBIINIT1_SLI_ENABLE) -#define TRIPLE_BUFFER ((voodoo->fbiInit2 & 0x10) || (voodoo->fbiInit5 & 0x600) == 0x400) +#define _rgb_sel (params->fbzColorPath & 3) +#define a_sel ((params->fbzColorPath >> 2) & 3) +#define cc_localselect (params->fbzColorPath & (1 << 4)) +#define cca_localselect ((params->fbzColorPath >> 5) & 3) +#define cc_localselect_override (params->fbzColorPath & (1 << 7)) +#define cc_zero_other (params->fbzColorPath & (1 << 8)) +#define cc_sub_clocal (params->fbzColorPath & (1 << 9)) +#define cc_mselect ((params->fbzColorPath >> 10) & 7) +#define cc_reverse_blend (params->fbzColorPath & (1 << 13)) +#define cc_add ((params->fbzColorPath >> 14) & 3) +#define cc_add_alocal (params->fbzColorPath & (1 << 15)) +#define cc_invert_output (params->fbzColorPath & (1 << 16)) +#define cca_zero_other (params->fbzColorPath & (1 << 17)) +#define cca_sub_clocal (params->fbzColorPath & (1 << 18)) +#define cca_mselect ((params->fbzColorPath >> 19) & 7) +#define cca_reverse_blend (params->fbzColorPath & (1 << 22)) +#define cca_add ((params->fbzColorPath >> 23) & 3) +#define cca_invert_output (params->fbzColorPath & (1 << 25)) +#define tc_zero_other (params->textureMode[0] & (1 << 12)) +#define tc_sub_clocal (params->textureMode[0] & (1 << 13)) +#define tc_mselect ((params->textureMode[0] >> 14) & 7) +#define tc_reverse_blend (params->textureMode[0] & (1 << 17)) +#define tc_add_clocal (params->textureMode[0] & (1 << 18)) +#define tc_add_alocal (params->textureMode[0] & (1 << 19)) +#define tc_invert_output (params->textureMode[0] & (1 << 20)) +#define tca_zero_other (params->textureMode[0] & (1 << 21)) +#define tca_sub_clocal (params->textureMode[0] & (1 << 22)) +#define tca_mselect ((params->textureMode[0] >> 23) & 7) +#define tca_reverse_blend (params->textureMode[0] & (1 << 26)) +#define tca_add_clocal (params->textureMode[0] & (1 << 27)) +#define tca_add_alocal (params->textureMode[0] & (1 << 28)) +#define tca_invert_output (params->textureMode[0] & (1 << 29)) +#define tc_sub_clocal_1 (params->textureMode[1] & (1 << 13)) +#define tc_mselect_1 ((params->textureMode[1] >> 14) & 7) +#define tc_reverse_blend_1 (params->textureMode[1] & (1 << 17)) +#define tc_add_clocal_1 (params->textureMode[1] & (1 << 18)) +#define tc_add_alocal_1 (params->textureMode[1] & (1 << 19)) +#define tca_sub_clocal_1 (params->textureMode[1] & (1 << 22)) +#define tca_mselect_1 ((params->textureMode[1] >> 23) & 7) +#define tca_reverse_blend_1 (params->textureMode[1] & (1 << 26)) +#define tca_add_clocal_1 (params->textureMode[1] & (1 << 27)) +#define tca_add_alocal_1 (params->textureMode[1] & (1 << 28)) -#define _rgb_sel ( params->fbzColorPath & 3) -#define a_sel ( (params->fbzColorPath >> 2) & 3) -#define cc_localselect ( params->fbzColorPath & (1 << 4)) -#define cca_localselect ( (params->fbzColorPath >> 5) & 3) -#define cc_localselect_override ( params->fbzColorPath & (1 << 7)) -#define cc_zero_other ( params->fbzColorPath & (1 << 8)) -#define cc_sub_clocal ( params->fbzColorPath & (1 << 9)) -#define cc_mselect ( (params->fbzColorPath >> 10) & 7) -#define cc_reverse_blend ( params->fbzColorPath & (1 << 13)) -#define cc_add ( (params->fbzColorPath >> 14) & 3) -#define cc_add_alocal ( params->fbzColorPath & (1 << 15)) -#define cc_invert_output ( params->fbzColorPath & (1 << 16)) -#define cca_zero_other ( params->fbzColorPath & (1 << 17)) -#define cca_sub_clocal ( params->fbzColorPath & (1 << 18)) -#define cca_mselect ( (params->fbzColorPath >> 19) & 7) -#define cca_reverse_blend ( params->fbzColorPath & (1 << 22)) -#define cca_add ( (params->fbzColorPath >> 23) & 3) -#define cca_invert_output ( params->fbzColorPath & (1 << 25)) -#define tc_zero_other (params->textureMode[0] & (1 << 12)) -#define tc_sub_clocal (params->textureMode[0] & (1 << 13)) -#define tc_mselect ((params->textureMode[0] >> 14) & 7) -#define tc_reverse_blend (params->textureMode[0] & (1 << 17)) -#define tc_add_clocal (params->textureMode[0] & (1 << 18)) -#define tc_add_alocal (params->textureMode[0] & (1 << 19)) -#define tc_invert_output (params->textureMode[0] & (1 << 20)) -#define tca_zero_other (params->textureMode[0] & (1 << 21)) -#define tca_sub_clocal (params->textureMode[0] & (1 << 22)) -#define tca_mselect ((params->textureMode[0] >> 23) & 7) -#define tca_reverse_blend (params->textureMode[0] & (1 << 26)) -#define tca_add_clocal (params->textureMode[0] & (1 << 27)) -#define tca_add_alocal (params->textureMode[0] & (1 << 28)) -#define tca_invert_output (params->textureMode[0] & (1 << 29)) +#define src_afunc ((params->alphaMode >> 8) & 0xf) +#define dest_afunc ((params->alphaMode >> 12) & 0xf) +#define alpha_func ((params->alphaMode >> 1) & 7) +#define a_ref (params->alphaMode >> 24) +#define depth_op ((params->fbzMode >> 5) & 7) +#define dither (params->fbzMode & FBZ_DITHER) +#define dither2x2 (params->fbzMode & FBZ_DITHER_2x2) +#define dithersub (params->fbzMode & FBZ_DITHER_SUB) -#define tc_sub_clocal_1 (params->textureMode[1] & (1 << 13)) -#define tc_mselect_1 ((params->textureMode[1] >> 14) & 7) -#define tc_reverse_blend_1 (params->textureMode[1] & (1 << 17)) -#define tc_add_clocal_1 (params->textureMode[1] & (1 << 18)) -#define tc_add_alocal_1 (params->textureMode[1] & (1 << 19)) -#define tca_sub_clocal_1 (params->textureMode[1] & (1 << 22)) -#define tca_mselect_1 ((params->textureMode[1] >> 23) & 7) -#define tca_reverse_blend_1 (params->textureMode[1] & (1 << 26)) -#define tca_add_clocal_1 (params->textureMode[1] & (1 << 27)) -#define tca_add_alocal_1 (params->textureMode[1] & (1 << 28)) - -#define src_afunc ( (params->alphaMode >> 8) & 0xf) -#define dest_afunc ( (params->alphaMode >> 12) & 0xf) -#define alpha_func ( (params->alphaMode >> 1) & 7) -#define a_ref ( params->alphaMode >> 24) -#define depth_op ( (params->fbzMode >> 5) & 7) -#define dither ( params->fbzMode & FBZ_DITHER) -#define dither2x2 (params->fbzMode & FBZ_DITHER_2x2) -#define dithersub (params->fbzMode & FBZ_DITHER_SUB) \ No newline at end of file +#endif /*VIDEO_VOODOO_REGS_H*/ diff --git a/src/include/86box/vid_voodoo_render.h b/src/include/86box/vid_voodoo_render.h index 4596c59bb..cd1962430 100644 --- a/src/include/86box/vid_voodoo_render.h +++ b/src/include/86box/vid_voodoo_render.h @@ -1,5 +1,8 @@ +#ifndef VIDEO_VOODOO_RENDER_H +#define VIDEO_VOODOO_RENDER_H + #if !(defined i386 || defined __i386 || defined __i386__ || defined _X86_ || defined _M_IX86 || defined __amd64__ || defined _M_X64) -#define NO_CODEGEN +# define NO_CODEGEN #endif #ifndef NO_CODEGEN @@ -7,295 +10,263 @@ void voodoo_codegen_init(voodoo_t *voodoo); void voodoo_codegen_close(voodoo_t *voodoo); #endif -#define DEPTH_TEST(comp_depth) \ - do \ - { \ - switch (depth_op) \ - { \ - case DEPTHOP_NEVER: \ - voodoo->fbiZFuncFail++; \ - goto skip_pixel; \ - case DEPTHOP_LESSTHAN: \ - if (!(comp_depth < old_depth)) \ - { \ - voodoo->fbiZFuncFail++; \ - goto skip_pixel; \ - } \ - break; \ - case DEPTHOP_EQUAL: \ - if (!(comp_depth == old_depth)) \ - { \ - voodoo->fbiZFuncFail++; \ - goto skip_pixel; \ - } \ - break; \ - case DEPTHOP_LESSTHANEQUAL: \ - if (!(comp_depth <= old_depth)) \ - { \ - voodoo->fbiZFuncFail++; \ - goto skip_pixel; \ - } \ - break; \ - case DEPTHOP_GREATERTHAN: \ - if (!(comp_depth > old_depth)) \ - { \ - voodoo->fbiZFuncFail++; \ - goto skip_pixel; \ - } \ - break; \ - case DEPTHOP_NOTEQUAL: \ - if (!(comp_depth != old_depth)) \ - { \ - voodoo->fbiZFuncFail++; \ - goto skip_pixel; \ - } \ - break; \ - case DEPTHOP_GREATERTHANEQUAL: \ - if (!(comp_depth >= old_depth)) \ - { \ - voodoo->fbiZFuncFail++; \ - goto skip_pixel; \ - } \ - break; \ - case DEPTHOP_ALWAYS: \ - break; \ - } \ - } while (0) +#define DEPTH_TEST(comp_depth) \ + do { \ + switch (depth_op) { \ + case DEPTHOP_NEVER: \ + voodoo->fbiZFuncFail++; \ + goto skip_pixel; \ + case DEPTHOP_LESSTHAN: \ + if (!(comp_depth < old_depth)) { \ + voodoo->fbiZFuncFail++; \ + goto skip_pixel; \ + } \ + break; \ + case DEPTHOP_EQUAL: \ + if (!(comp_depth == old_depth)) { \ + voodoo->fbiZFuncFail++; \ + goto skip_pixel; \ + } \ + break; \ + case DEPTHOP_LESSTHANEQUAL: \ + if (!(comp_depth <= old_depth)) { \ + voodoo->fbiZFuncFail++; \ + goto skip_pixel; \ + } \ + break; \ + case DEPTHOP_GREATERTHAN: \ + if (!(comp_depth > old_depth)) { \ + voodoo->fbiZFuncFail++; \ + goto skip_pixel; \ + } \ + break; \ + case DEPTHOP_NOTEQUAL: \ + if (!(comp_depth != old_depth)) { \ + voodoo->fbiZFuncFail++; \ + goto skip_pixel; \ + } \ + break; \ + case DEPTHOP_GREATERTHANEQUAL: \ + if (!(comp_depth >= old_depth)) { \ + voodoo->fbiZFuncFail++; \ + goto skip_pixel; \ + } \ + break; \ + case DEPTHOP_ALWAYS: \ + break; \ + } \ + } while (0) -#define APPLY_FOG(src_r, src_g, src_b, z, ia, w) \ - do \ - { \ - if (params->fogMode & FOG_CONSTANT) \ - { \ - src_r += params->fogColor.r; \ - src_g += params->fogColor.g; \ - src_b += params->fogColor.b; \ - } \ - else \ - { \ - int fog_r, fog_g, fog_b, fog_a = 0; \ - int fog_idx; \ - \ - if (!(params->fogMode & FOG_ADD)) \ - { \ - fog_r = params->fogColor.r; \ - fog_g = params->fogColor.g; \ - fog_b = params->fogColor.b; \ - } \ - else \ - fog_r = fog_g = fog_b = 0; \ - \ - if (!(params->fogMode & FOG_MULT)) \ - { \ - fog_r -= src_r; \ - fog_g -= src_g; \ - fog_b -= src_b; \ - } \ - \ - switch (params->fogMode & (FOG_Z|FOG_ALPHA)) \ - { \ - case 0: \ - fog_idx = (w_depth >> 10) & 0x3f; \ - \ - fog_a = params->fogTable[fog_idx].fog; \ - fog_a += (params->fogTable[fog_idx].dfog * ((w_depth >> 2) & 0xff)) >> 10; \ - break; \ - case FOG_Z: \ - fog_a = (z >> 20) & 0xff; \ - break; \ - case FOG_ALPHA: \ - fog_a = CLAMP(ia >> 12); \ - break; \ - case FOG_W: \ - fog_a = CLAMP((w >> 32) & 0xff); \ - break; \ - } \ - fog_a++; \ - \ - fog_r = (fog_r * fog_a) >> 8; \ - fog_g = (fog_g * fog_a) >> 8; \ - fog_b = (fog_b * fog_a) >> 8; \ - \ - if (params->fogMode & FOG_MULT) \ - { \ - src_r = fog_r; \ - src_g = fog_g; \ - src_b = fog_b; \ - } \ - else \ - { \ - src_r += fog_r; \ - src_g += fog_g; \ - src_b += fog_b; \ - } \ - } \ - \ - src_r = CLAMP(src_r); \ - src_g = CLAMP(src_g); \ - src_b = CLAMP(src_b); \ - } while (0) - -#define ALPHA_TEST(src_a) \ - do \ - { \ - switch (alpha_func) \ - { \ - case AFUNC_NEVER: \ - voodoo->fbiAFuncFail++; \ - goto skip_pixel; \ - case AFUNC_LESSTHAN: \ - if (!(src_a < a_ref)) \ - { \ - voodoo->fbiAFuncFail++; \ - goto skip_pixel; \ - } \ - break; \ - case AFUNC_EQUAL: \ - if (!(src_a == a_ref)) \ - { \ - voodoo->fbiAFuncFail++; \ - goto skip_pixel; \ - } \ - break; \ - case AFUNC_LESSTHANEQUAL: \ - if (!(src_a <= a_ref)) \ - { \ - voodoo->fbiAFuncFail++; \ - goto skip_pixel; \ - } \ - break; \ - case AFUNC_GREATERTHAN: \ - if (!(src_a > a_ref)) \ - { \ - voodoo->fbiAFuncFail++; \ - goto skip_pixel; \ - } \ - break; \ - case AFUNC_NOTEQUAL: \ - if (!(src_a != a_ref)) \ - { \ - voodoo->fbiAFuncFail++; \ - goto skip_pixel; \ - } \ - break; \ - case AFUNC_GREATERTHANEQUAL: \ - if (!(src_a >= a_ref)) \ - { \ - voodoo->fbiAFuncFail++; \ - goto skip_pixel; \ - } \ - break; \ - case AFUNC_ALWAYS: \ - break; \ - } \ - } while (0) - -#define ALPHA_BLEND(src_r, src_g, src_b, src_a) \ - do \ - { \ - int _a; \ - int newdest_r = 0, newdest_g = 0, newdest_b = 0; \ - \ - switch (dest_afunc) \ - { \ - case AFUNC_AZERO: \ - newdest_r = newdest_g = newdest_b = 0; \ - break; \ - case AFUNC_ASRC_ALPHA: \ - newdest_r = (dest_r * src_a) / 255; \ - newdest_g = (dest_g * src_a) / 255; \ - newdest_b = (dest_b * src_a) / 255; \ - break; \ - case AFUNC_A_COLOR: \ - newdest_r = (dest_r * src_r) / 255; \ - newdest_g = (dest_g * src_g) / 255; \ - newdest_b = (dest_b * src_b) / 255; \ - break; \ - case AFUNC_ADST_ALPHA: \ - newdest_r = (dest_r * dest_a) / 255; \ - newdest_g = (dest_g * dest_a) / 255; \ - newdest_b = (dest_b * dest_a) / 255; \ - break; \ - case AFUNC_AONE: \ - newdest_r = dest_r; \ - newdest_g = dest_g; \ - newdest_b = dest_b; \ - break; \ - case AFUNC_AOMSRC_ALPHA: \ - newdest_r = (dest_r * (255-src_a)) / 255; \ - newdest_g = (dest_g * (255-src_a)) / 255; \ - newdest_b = (dest_b * (255-src_a)) / 255; \ - break; \ - case AFUNC_AOM_COLOR: \ - newdest_r = (dest_r * (255-src_r)) / 255; \ - newdest_g = (dest_g * (255-src_g)) / 255; \ - newdest_b = (dest_b * (255-src_b)) / 255; \ - break; \ - case AFUNC_AOMDST_ALPHA: \ - newdest_r = (dest_r * (255-dest_a)) / 255; \ - newdest_g = (dest_g * (255-dest_a)) / 255; \ - newdest_b = (dest_b * (255-dest_a)) / 255; \ - break; \ - case AFUNC_ASATURATE: \ - _a = MIN(src_a, 1-dest_a); \ - newdest_r = (dest_r * _a) / 255; \ - newdest_g = (dest_g * _a) / 255; \ - newdest_b = (dest_b * _a) / 255; \ - break; \ - } \ - \ - switch (src_afunc) \ - { \ - case AFUNC_AZERO: \ - src_r = src_g = src_b = 0; \ - break; \ - case AFUNC_ASRC_ALPHA: \ - src_r = (src_r * src_a) / 255; \ - src_g = (src_g * src_a) / 255; \ - src_b = (src_b * src_a) / 255; \ - break; \ - case AFUNC_A_COLOR: \ - src_r = (src_r * dest_r) / 255; \ - src_g = (src_g * dest_g) / 255; \ - src_b = (src_b * dest_b) / 255; \ - break; \ - case AFUNC_ADST_ALPHA: \ - src_r = (src_r * dest_a) / 255; \ - src_g = (src_g * dest_a) / 255; \ - src_b = (src_b * dest_a) / 255; \ - break; \ - case AFUNC_AONE: \ - break; \ - case AFUNC_AOMSRC_ALPHA: \ - src_r = (src_r * (255-src_a)) / 255; \ - src_g = (src_g * (255-src_a)) / 255; \ - src_b = (src_b * (255-src_a)) / 255; \ - break; \ - case AFUNC_AOM_COLOR: \ - src_r = (src_r * (255-dest_r)) / 255; \ - src_g = (src_g * (255-dest_g)) / 255; \ - src_b = (src_b * (255-dest_b)) / 255; \ - break; \ - case AFUNC_AOMDST_ALPHA: \ - src_r = (src_r * (255-dest_a)) / 255; \ - src_g = (src_g * (255-dest_a)) / 255; \ - src_b = (src_b * (255-dest_a)) / 255; \ - break; \ - case AFUNC_ACOLORBEFOREFOG: \ - fatal("AFUNC_ACOLORBEFOREFOG\n"); \ - break; \ - } \ - \ - src_r += newdest_r; \ - src_g += newdest_g; \ - src_b += newdest_b; \ - \ - src_r = CLAMP(src_r); \ - src_g = CLAMP(src_g); \ - src_b = CLAMP(src_b); \ - } while(0) +#define APPLY_FOG(src_r, src_g, src_b, z, ia, w) \ + do { \ + if (params->fogMode & FOG_CONSTANT) { \ + src_r += params->fogColor.r; \ + src_g += params->fogColor.g; \ + src_b += params->fogColor.b; \ + } else { \ + int fog_r, fog_g, fog_b, fog_a = 0; \ + int fog_idx; \ + \ + if (!(params->fogMode & FOG_ADD)) { \ + fog_r = params->fogColor.r; \ + fog_g = params->fogColor.g; \ + fog_b = params->fogColor.b; \ + } else \ + fog_r = fog_g = fog_b = 0; \ + \ + if (!(params->fogMode & FOG_MULT)) { \ + fog_r -= src_r; \ + fog_g -= src_g; \ + fog_b -= src_b; \ + } \ + \ + switch (params->fogMode & (FOG_Z | FOG_ALPHA)) { \ + case 0: \ + fog_idx = (w_depth >> 10) & 0x3f; \ + \ + fog_a = params->fogTable[fog_idx].fog; \ + fog_a += (params->fogTable[fog_idx].dfog * ((w_depth >> 2) & 0xff)) >> 10; \ + break; \ + case FOG_Z: \ + fog_a = (z >> 20) & 0xff; \ + break; \ + case FOG_ALPHA: \ + fog_a = CLAMP(ia >> 12); \ + break; \ + case FOG_W: \ + fog_a = CLAMP((w >> 32) & 0xff); \ + break; \ + } \ + fog_a++; \ + \ + fog_r = (fog_r * fog_a) >> 8; \ + fog_g = (fog_g * fog_a) >> 8; \ + fog_b = (fog_b * fog_a) >> 8; \ + \ + if (params->fogMode & FOG_MULT) { \ + src_r = fog_r; \ + src_g = fog_g; \ + src_b = fog_b; \ + } else { \ + src_r += fog_r; \ + src_g += fog_g; \ + src_b += fog_b; \ + } \ + } \ + \ + src_r = CLAMP(src_r); \ + src_g = CLAMP(src_g); \ + src_b = CLAMP(src_b); \ + } while (0) +#define ALPHA_TEST(src_a) \ + do { \ + switch (alpha_func) { \ + case AFUNC_NEVER: \ + voodoo->fbiAFuncFail++; \ + goto skip_pixel; \ + case AFUNC_LESSTHAN: \ + if (!(src_a < a_ref)) { \ + voodoo->fbiAFuncFail++; \ + goto skip_pixel; \ + } \ + break; \ + case AFUNC_EQUAL: \ + if (!(src_a == a_ref)) { \ + voodoo->fbiAFuncFail++; \ + goto skip_pixel; \ + } \ + break; \ + case AFUNC_LESSTHANEQUAL: \ + if (!(src_a <= a_ref)) { \ + voodoo->fbiAFuncFail++; \ + goto skip_pixel; \ + } \ + break; \ + case AFUNC_GREATERTHAN: \ + if (!(src_a > a_ref)) { \ + voodoo->fbiAFuncFail++; \ + goto skip_pixel; \ + } \ + break; \ + case AFUNC_NOTEQUAL: \ + if (!(src_a != a_ref)) { \ + voodoo->fbiAFuncFail++; \ + goto skip_pixel; \ + } \ + break; \ + case AFUNC_GREATERTHANEQUAL: \ + if (!(src_a >= a_ref)) { \ + voodoo->fbiAFuncFail++; \ + goto skip_pixel; \ + } \ + break; \ + case AFUNC_ALWAYS: \ + break; \ + } \ + } while (0) +#define ALPHA_BLEND(src_r, src_g, src_b, src_a) \ + do { \ + int _a; \ + int newdest_r = 0, newdest_g = 0, newdest_b = 0; \ + \ + switch (dest_afunc) { \ + case AFUNC_AZERO: \ + newdest_r = newdest_g = newdest_b = 0; \ + break; \ + case AFUNC_ASRC_ALPHA: \ + newdest_r = (dest_r * src_a) / 255; \ + newdest_g = (dest_g * src_a) / 255; \ + newdest_b = (dest_b * src_a) / 255; \ + break; \ + case AFUNC_A_COLOR: \ + newdest_r = (dest_r * src_r) / 255; \ + newdest_g = (dest_g * src_g) / 255; \ + newdest_b = (dest_b * src_b) / 255; \ + break; \ + case AFUNC_ADST_ALPHA: \ + newdest_r = (dest_r * dest_a) / 255; \ + newdest_g = (dest_g * dest_a) / 255; \ + newdest_b = (dest_b * dest_a) / 255; \ + break; \ + case AFUNC_AONE: \ + newdest_r = dest_r; \ + newdest_g = dest_g; \ + newdest_b = dest_b; \ + break; \ + case AFUNC_AOMSRC_ALPHA: \ + newdest_r = (dest_r * (255 - src_a)) / 255; \ + newdest_g = (dest_g * (255 - src_a)) / 255; \ + newdest_b = (dest_b * (255 - src_a)) / 255; \ + break; \ + case AFUNC_AOM_COLOR: \ + newdest_r = (dest_r * (255 - src_r)) / 255; \ + newdest_g = (dest_g * (255 - src_g)) / 255; \ + newdest_b = (dest_b * (255 - src_b)) / 255; \ + break; \ + case AFUNC_AOMDST_ALPHA: \ + newdest_r = (dest_r * (255 - dest_a)) / 255; \ + newdest_g = (dest_g * (255 - dest_a)) / 255; \ + newdest_b = (dest_b * (255 - dest_a)) / 255; \ + break; \ + case AFUNC_ASATURATE: \ + _a = MIN(src_a, 1 - dest_a); \ + newdest_r = (dest_r * _a) / 255; \ + newdest_g = (dest_g * _a) / 255; \ + newdest_b = (dest_b * _a) / 255; \ + break; \ + } \ + \ + switch (src_afunc) { \ + case AFUNC_AZERO: \ + src_r = src_g = src_b = 0; \ + break; \ + case AFUNC_ASRC_ALPHA: \ + src_r = (src_r * src_a) / 255; \ + src_g = (src_g * src_a) / 255; \ + src_b = (src_b * src_a) / 255; \ + break; \ + case AFUNC_A_COLOR: \ + src_r = (src_r * dest_r) / 255; \ + src_g = (src_g * dest_g) / 255; \ + src_b = (src_b * dest_b) / 255; \ + break; \ + case AFUNC_ADST_ALPHA: \ + src_r = (src_r * dest_a) / 255; \ + src_g = (src_g * dest_a) / 255; \ + src_b = (src_b * dest_a) / 255; \ + break; \ + case AFUNC_AONE: \ + break; \ + case AFUNC_AOMSRC_ALPHA: \ + src_r = (src_r * (255 - src_a)) / 255; \ + src_g = (src_g * (255 - src_a)) / 255; \ + src_b = (src_b * (255 - src_a)) / 255; \ + break; \ + case AFUNC_AOM_COLOR: \ + src_r = (src_r * (255 - dest_r)) / 255; \ + src_g = (src_g * (255 - dest_g)) / 255; \ + src_b = (src_b * (255 - dest_b)) / 255; \ + break; \ + case AFUNC_AOMDST_ALPHA: \ + src_r = (src_r * (255 - dest_a)) / 255; \ + src_g = (src_g * (255 - dest_a)) / 255; \ + src_b = (src_b * (255 - dest_a)) / 255; \ + break; \ + case AFUNC_ACOLORBEFOREFOG: \ + fatal("AFUNC_ACOLORBEFOREFOG\n"); \ + break; \ + } \ + \ + src_r += newdest_r; \ + src_g += newdest_g; \ + src_b += newdest_b; \ + \ + src_r = CLAMP(src_r); \ + src_g = CLAMP(src_g); \ + src_b = CLAMP(src_b); \ + } while (0) void voodoo_render_thread_1(void *param); void voodoo_render_thread_2(void *param); @@ -306,33 +277,32 @@ void voodoo_queue_triangle(voodoo_t *voodoo, voodoo_params_t *params); extern int voodoo_recomp; extern int tris; -static __inline void voodoo_wake_render_thread(voodoo_t *voodoo) +static __inline void +voodoo_wake_render_thread(voodoo_t *voodoo) { - thread_set_event(voodoo->wake_render_thread[0]); /*Wake up render thread if moving from idle*/ - if (voodoo->render_threads >= 2) - thread_set_event(voodoo->wake_render_thread[1]); /*Wake up render thread if moving from idle*/ - if (voodoo->render_threads == 4) - { - thread_set_event(voodoo->wake_render_thread[2]); /*Wake up render thread if moving from idle*/ - thread_set_event(voodoo->wake_render_thread[3]); /*Wake up render thread if moving from idle*/ - } + thread_set_event(voodoo->wake_render_thread[0]); /*Wake up render thread if moving from idle*/ + if (voodoo->render_threads >= 2) + thread_set_event(voodoo->wake_render_thread[1]); /*Wake up render thread if moving from idle*/ + if (voodoo->render_threads == 4) { + thread_set_event(voodoo->wake_render_thread[2]); /*Wake up render thread if moving from idle*/ + thread_set_event(voodoo->wake_render_thread[3]); /*Wake up render thread if moving from idle*/ + } } -static __inline void voodoo_wait_for_render_thread_idle(voodoo_t *voodoo) +static __inline void +voodoo_wait_for_render_thread_idle(voodoo_t *voodoo) { - while (!PARAM_EMPTY(0) || (voodoo->render_threads >= 2 && !PARAM_EMPTY(1)) || - (voodoo->render_threads == 4 && (!PARAM_EMPTY(2) || !PARAM_EMPTY(3))) || - voodoo->render_voodoo_busy[0] || (voodoo->render_threads >= 2 && voodoo->render_voodoo_busy[1]) || - (voodoo->render_threads == 4 && (voodoo->render_voodoo_busy[2] || voodoo->render_voodoo_busy[3]))) - { - voodoo_wake_render_thread(voodoo); - if (!PARAM_EMPTY(0) || voodoo->render_voodoo_busy[0]) - thread_wait_event(voodoo->render_not_full_event[0], 1); - if (voodoo->render_threads >= 2 && (!PARAM_EMPTY(1) || voodoo->render_voodoo_busy[1])) - thread_wait_event(voodoo->render_not_full_event[1], 1); - if (voodoo->render_threads == 4 && (!PARAM_EMPTY(2) || voodoo->render_voodoo_busy[2])) - thread_wait_event(voodoo->render_not_full_event[2], 1); - if (voodoo->render_threads == 4 && (!PARAM_EMPTY(3) || voodoo->render_voodoo_busy[3])) - thread_wait_event(voodoo->render_not_full_event[3], 1); - } + while (!PARAM_EMPTY(0) || (voodoo->render_threads >= 2 && !PARAM_EMPTY(1)) || (voodoo->render_threads == 4 && (!PARAM_EMPTY(2) || !PARAM_EMPTY(3))) || voodoo->render_voodoo_busy[0] || (voodoo->render_threads >= 2 && voodoo->render_voodoo_busy[1]) || (voodoo->render_threads == 4 && (voodoo->render_voodoo_busy[2] || voodoo->render_voodoo_busy[3]))) { + voodoo_wake_render_thread(voodoo); + if (!PARAM_EMPTY(0) || voodoo->render_voodoo_busy[0]) + thread_wait_event(voodoo->render_not_full_event[0], 1); + if (voodoo->render_threads >= 2 && (!PARAM_EMPTY(1) || voodoo->render_voodoo_busy[1])) + thread_wait_event(voodoo->render_not_full_event[1], 1); + if (voodoo->render_threads == 4 && (!PARAM_EMPTY(2) || voodoo->render_voodoo_busy[2])) + thread_wait_event(voodoo->render_not_full_event[2], 1); + if (voodoo->render_threads == 4 && (!PARAM_EMPTY(3) || voodoo->render_voodoo_busy[3])) + thread_wait_event(voodoo->render_not_full_event[3], 1); + } } + +#endif /*VIDEO_VOODOO_RENDER_H*/ diff --git a/src/include/86box/vid_voodoo_setup.h b/src/include/86box/vid_voodoo_setup.h index 19056dd6b..d8820a7cb 100644 --- a/src/include/86box/vid_voodoo_setup.h +++ b/src/include/86box/vid_voodoo_setup.h @@ -1,18 +1,24 @@ /* - * 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. + * 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. + * This file is part of the 86Box distribution. * - * Voodoo Graphics, 2, Banshee, 3 emulation. + * Voodoo Graphics, 2, Banshee, 3 emulation. * * * - * Authors: Sarah Walker, - * leilei + * Authors: Sarah Walker, + * leilei * - * Copyright 2008-2020 Sarah Walker. + * Copyright 2008-2020 Sarah Walker. */ + +#ifndef VIDEO_VOODOO_SETUP_H +#define VIDEO_VOODOO_SETUP_H + void voodoo_triangle_setup(voodoo_t *voodoo); + +#endif /*VIDEO_VOODOO_SETUP_H*/ diff --git a/src/include/86box/vid_voodoo_texture.h b/src/include/86box/vid_voodoo_texture.h index 40c2b739a..6f325426a 100644 --- a/src/include/86box/vid_voodoo_texture.h +++ b/src/include/86box/vid_voodoo_texture.h @@ -1,36 +1,42 @@ /* - * 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. + * 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. + * This file is part of the 86Box distribution. * - * Voodoo Graphics, 2, Banshee, 3 emulation. + * Voodoo Graphics, 2, Banshee, 3 emulation. * * * - * Authors: Sarah Walker, - * leilei + * Authors: Sarah Walker, + * leilei * - * Copyright 2008-2020 Sarah Walker. + * Copyright 2008-2020 Sarah Walker. */ -static const uint32_t texture_offset[LOD_MAX+3] = -{ - 0, - 256*256, - 256*256 + 128*128, - 256*256 + 128*128 + 64*64, - 256*256 + 128*128 + 64*64 + 32*32, - 256*256 + 128*128 + 64*64 + 32*32 + 16*16, - 256*256 + 128*128 + 64*64 + 32*32 + 16*16 + 8*8, - 256*256 + 128*128 + 64*64 + 32*32 + 16*16 + 8*8 + 4*4, - 256*256 + 128*128 + 64*64 + 32*32 + 16*16 + 8*8 + 4*4 + 2*2, - 256*256 + 128*128 + 64*64 + 32*32 + 16*16 + 8*8 + 4*4 + 2*2 + 1*1, - 256*256 + 128*128 + 64*64 + 32*32 + 16*16 + 8*8 + 4*4 + 2*2 + 1*1 + 1 + +#ifndef VIDEO_VOODOO_TEXTURE_H +#define VIDEO_VOODOO_TEXTURE_H + +static const uint32_t texture_offset[LOD_MAX + 3] = { + 0, + 256 * 256, + 256 * 256 + 128 * 128, + 256 * 256 + 128 * 128 + 64 * 64, + 256 * 256 + 128 * 128 + 64 * 64 + 32 * 32, + 256 * 256 + 128 * 128 + 64 * 64 + 32 * 32 + 16 * 16, + 256 * 256 + 128 * 128 + 64 * 64 + 32 * 32 + 16 * 16 + 8 * 8, + 256 * 256 + 128 * 128 + 64 * 64 + 32 * 32 + 16 * 16 + 8 * 8 + 4 * 4, + 256 * 256 + 128 * 128 + 64 * 64 + 32 * 32 + 16 * 16 + 8 * 8 + 4 * 4 + 2 * 2, + 256 * 256 + 128 * 128 + 64 * 64 + 32 * 32 + 16 * 16 + 8 * 8 + 4 * 4 + 2 * 2 + 1 * 1, + 256 * 256 + 128 * 128 + 64 * 64 + 32 * 32 + 16 * 16 + 8 * 8 + 4 * 4 + 2 * 2 + 1 * 1 + 1 }; -void voodoo_recalc_tex(voodoo_t *voodoo, int tmu); +void voodoo_recalc_tex12(voodoo_t *voodoo, int tmu); +void voodoo_recalc_tex3(voodoo_t *voodoo, int tmu); void voodoo_use_texture(voodoo_t *voodoo, voodoo_params_t *params, int tmu); -void voodoo_tex_writel(uint32_t addr, uint32_t val, void *p); +void voodoo_tex_writel(uint32_t addr, uint32_t val, void *priv); void flush_texture_cache(voodoo_t *voodoo, uint32_t dirty_addr, int tmu); + +#endif /* VIDEO_VOODOO_TEXTURE_H*/ diff --git a/src/include/86box/vid_xga.h b/src/include/86box/vid_xga.h new file mode 100644 index 000000000..e5248b309 --- /dev/null +++ b/src/include/86box/vid_xga.h @@ -0,0 +1,235 @@ +/* + * 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. + * + * IBM XGA emulation. + * + * + * + * Authors: TheCollector1995. + * + * Copyright 2022 TheCollector1995. + */ +#ifndef VIDEO_XGA_H +#define VIDEO_XGA_H + +#include <86box/rom.h> + +typedef struct xga_hwcursor_t { + int ena; + int x; + int y; + int xoff; + int yoff; + int cur_xsize; + int cur_ysize; + uint32_t addr; +} xga_hwcursor_t; + +typedef struct xga_t { + mem_mapping_t memio_mapping; + mem_mapping_t linear_mapping; + mem_mapping_t video_mapping; + rom_t bios_rom; + rom_t vga_bios_rom; + xga_hwcursor_t hwcursor; + xga_hwcursor_t hwcursor_latch; + PALETTE extpal; + + uint8_t test; + uint8_t test2; + uint8_t atest[2]; + uint8_t testpixel; + + uint8_t pos_regs[8]; + uint8_t disp_addr; + uint8_t cfg_reg; + uint8_t instance; + uint8_t op_mode; + uint8_t aperture_cntl; + uint8_t ap_idx; + uint8_t access_mode; + uint8_t regs[0x100]; + uint8_t regs_idx; + uint8_t hwc_hotspot_x; + uint8_t hwc_hotspot_y; + uint8_t disp_cntl_1; + uint8_t disp_cntl_2; + uint8_t clk_sel_1; + uint8_t clk_sel_2; + uint8_t hwc_control; + uint8_t bus_arb; + uint8_t isa_pos_enable; + uint8_t hwcursor_oddeven; + uint8_t cfg_reg_instance; + uint8_t rowcount; + uint8_t pal_idx; + uint8_t pal_idx_prefetch; + uint8_t pal_seq; + uint8_t pal_mask; + uint8_t pal_r; + uint8_t pal_r_prefetch; + uint8_t pal_g; + uint8_t pal_g_prefetch; + uint8_t pal_b; + uint8_t pal_b_prefetch; + uint8_t sprite_data[1024]; + uint8_t scrollcache; + uint8_t border_color; + uint8_t direct_color; + uint8_t dma_channel; + uint8_t instance_isa; + uint8_t instance_num; + uint8_t ext_mem_addr; + uint8_t *vram; + uint8_t *changedvram; + + int16_t hwc_pos_x; + int16_t hwc_pos_y; + + uint16_t pos_idx; + uint16_t htotal; + uint16_t sprite_idx; + uint16_t sprite_idx_prefetch; + uint16_t hdisp; + uint16_t vtotal; + uint16_t vdispend; + uint16_t vblankstart; + uint16_t vsyncstart; + uint16_t linecmp; + uint16_t pix_map_width; + uint16_t sprite_pal_addr_idx; + uint16_t old_pal_addr_idx; + uint16_t sprite_pal_addr_idx_prefetch; + + int v_total; + int dispend; + int v_syncstart; + int split; + int v_blankstart; + int h_disp; + int h_disp_old; + int h_total; + int h_disp_time; + int rowoffset; + int dispon; + int h_disp_on; + int vc; + int sc; + int linepos; + int oddeven; + int firstline; + int lastline; + int firstline_draw; + int lastline_draw; + int displine; + int fullchange; + int interlace; + int char_width; + int hwcursor_on; + int pal_pos; + int pal_pos_prefetch; + int on; + int op_mode_reset; + int linear_endian_reverse; + int sprite_pos; + int sprite_pos_prefetch; + int cursor_data_on; + int pal_test; + int a5_test; + int type; + int bus; + + uint32_t linear_base; + uint32_t linear_size; + uint32_t banked_mask; + uint32_t base_addr_1mb; + uint32_t hwc_color0; + uint32_t hwc_color1; + uint32_t disp_start_addr; + uint32_t ma_latch; + uint32_t vram_size; + uint32_t vram_mask; + uint32_t rom_addr; + uint32_t ma; + uint32_t maback; + uint32_t read_bank; + uint32_t write_bank; + uint32_t px_map_base; + uint32_t pallook[512]; + + uint64_t dispontime; + uint64_t dispofftime; + + struct { + uint8_t control; + uint8_t px_map_idx; + uint8_t frgd_mix; + uint8_t bkgd_mix; + uint8_t cc_cond; + uint8_t octant; + uint8_t draw_mode; + uint8_t mask_mode; + uint8_t short_stroke_vector1; + uint8_t short_stroke_vector2; + uint8_t short_stroke_vector3; + uint8_t short_stroke_vector4; + + int16_t bres_err_term; + int16_t bres_k1; + int16_t bres_k2; + + uint16_t blt_width; + uint16_t blt_height; + uint16_t mask_map_origin_x_off; + uint16_t mask_map_origin_y_off; + uint16_t src_map_x; + uint16_t src_map_y; + uint16_t dst_map_x; + uint16_t dst_map_y; + uint16_t pat_map_x; + uint16_t pat_map_y; + + int ssv_state; + int pat_src; + int src_map; + int dst_map; + int bkgd_src; + int fore_src; + int oldx; + int oldy; + int x; + int y; + int sx; + int sy; + int dx; + int dy; + int px; + int py; + int pattern; + int command_len; + int filling; + + uint32_t short_stroke; + uint32_t color_cmp; + uint32_t carry_chain; + uint32_t plane_mask; + uint32_t frgd_color; + uint32_t bkgd_color; + uint32_t command; + uint32_t dir_cmd; + + uint8_t px_map_format[4]; + uint16_t px_map_width[4]; + uint16_t px_map_height[4]; + uint32_t px_map_base[4]; + } accel; + + int big_endian_linear; +} xga_t; + +#endif /*VIDEO_XGA_H*/ diff --git a/src/include/86box/vid_xga_device.h b/src/include/86box/vid_xga_device.h new file mode 100644 index 000000000..e337ef9d3 --- /dev/null +++ b/src/include/86box/vid_xga_device.h @@ -0,0 +1,26 @@ +/* + * 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. + * + * IBM XGA emulation. + * + * + * + * Authors: TheCollector1995. + * + * Copyright 2022 TheCollector1995. + */ + +#ifndef VIDEO_XGA_DEVICE_H +#define VIDEO_XGA_DEVICE_H + +#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 05b7055b3..1858fc246 100644 --- a/src/include/86box/video.h +++ b/src/include/86box/video.h @@ -1,30 +1,37 @@ /* - * 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. + * 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. + * This file is part of the 86Box distribution. * - * Definitions for the video controller module. + * Definitions for the video controller module. * * * - * Authors: Sarah Walker, - * Miran Grca, - * Fred N. van Kempen, + * Authors: Sarah Walker, + * Miran Grca, + * Fred N. van Kempen, * - * Copyright 2008-2019 Sarah Walker. - * Copyright 2016-2019 Miran Grca. - * Copyright 2017-2019 Fred N. van Kempen. + * Copyright 2008-2019 Sarah Walker. + * Copyright 2016-2019 Miran Grca. + * Copyright 2017-2019 Fred N. van Kempen. */ + #ifndef EMU_VIDEO_H -# define EMU_VIDEO_H +#define EMU_VIDEO_H +#ifdef __cplusplus +# include +using atomic_bool = std::atomic_bool; +using atomic_int = std::atomic_int; +#else +# include +#endif -#define makecol(r, g, b) ((b) | ((g) << 8) | ((r) << 16)) -#define makecol32(r, g, b) ((b) | ((g) << 8) | ((r) << 16)) - +#define makecol(r, g, b) ((b) | ((g) << 8) | ((r) << 16)) +#define makecol32(r, g, b) ((b) | ((g) << 8) | ((r) << 16)) enum { VID_NONE = 0, @@ -35,15 +42,14 @@ enum { FULLSCR_SCALE_FULL = 0, FULLSCR_SCALE_43, FULLSCR_SCALE_KEEPRATIO, - FULLSCR_SCALE_INT + FULLSCR_SCALE_INT, + FULLSCR_SCALE_INT43 }; - #ifdef __cplusplus extern "C" { #endif - enum { VIDEO_ISA = 0, VIDEO_MCA, @@ -55,150 +61,255 @@ 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 { - int type; - int write_b, write_w, write_l; - int read_b, read_w, read_l; +typedef struct video_timings_t { + int type; + int write_b; + int write_w; + int write_l; + int read_b; + int read_w; + int read_l; } video_timings_t; -typedef struct { - int w, h; - uint32_t *dat; - uint32_t *line[2112]; +typedef struct bitmap_t { + int w; + int h; + uint32_t *dat; + uint32_t *line[2112]; } bitmap_t; -typedef struct { - uint8_t r, g, b; +typedef struct rgb_t { + uint8_t r; + uint8_t g; + uint8_t b; } rgb_t; -typedef struct { - uint8_t chr[32]; +typedef struct dbcs_font_t { + uint8_t chr[32]; } dbcs_font_t; +struct blit_data_struct; + +typedef struct monitor_t { + char name[512]; + int mon_xsize; + int mon_ysize; + int mon_scrnsz_x; + int mon_scrnsz_y; + int mon_efscrnsz_y; + int mon_unscaled_size_x; + int mon_unscaled_size_y; + double mon_res_x; + double mon_res_y; + int mon_bpp; + bitmap_t *target_buffer; + int mon_video_timing_read_b; + int mon_video_timing_read_w; + int mon_video_timing_read_l; + int mon_video_timing_write_b; + int mon_video_timing_write_w; + int mon_video_timing_write_l; + int mon_overscan_x; + int mon_overscan_y; + int mon_force_resize; + int mon_fullchange; + int mon_changeframecount; + atomic_int mon_screenshots; + uint32_t *mon_pal_lookup; + int *mon_cga_palette; + int mon_pal_lookup_static; /* Whether it should not be freed by the API. */ + int mon_cga_palette_static; /* Whether it should not be freed by the API. */ + const video_timings_t *mon_vid_timings; + int mon_vid_type; + struct blit_data_struct *mon_blit_data_ptr; +} monitor_t; + +typedef struct monitor_settings_t { + int mon_window_x; /* (C) window size and position info. */ + int mon_window_y; + int mon_window_w; + int mon_window_h; + int mon_window_maximized; +} monitor_settings_t; + +#define MONITORS_NUM 2 +extern monitor_t monitors[MONITORS_NUM]; +extern monitor_settings_t monitor_settings[MONITORS_NUM]; +extern atomic_bool doresize_monitors[MONITORS_NUM]; +extern int monitor_index_global; +extern int show_second_monitors; +extern int video_fullscreen_scale_maximized; + typedef rgb_t PALETTE[256]; - -extern int changeframecount; +#if 0 +extern int changeframecount; +#endif extern volatile int screenshots; -extern bitmap_t *buffer32; -extern PALETTE cgapal, - cgapal_mono[6]; -extern uint32_t pal_lookup[256]; -extern int video_fullscreen, - video_fullscreen_scale, - video_fullscreen_first; -extern int fullchange; -extern uint8_t fontdat[2048][8]; -extern uint8_t fontdatm[2048][16]; -extern uint8_t fontdatw[512][32]; -extern uint8_t fontdat8x12[256][16]; -extern uint8_t fontdat12x18[256][36]; -extern dbcs_font_t *fontdatksc5601; -extern dbcs_font_t *fontdatksc5601_user; -extern uint32_t *video_6to8, - *video_8togs, - *video_8to32, - *video_15to32, - *video_16to32; -extern int xsize,ysize; -extern int enable_overscan; -extern int overscan_x, - overscan_y; -extern int force_43; -extern int video_timing_read_b, - video_timing_read_w, - video_timing_read_l; -extern int video_timing_write_b, - video_timing_write_w, - video_timing_write_l; -extern int video_res_x, - video_res_y, - video_bpp; -extern int vid_resize; -extern int cga_palette, - herc_blend; -extern int vid_cga_contrast; -extern int video_grayscale; -extern int video_graytype; - -extern double cpuclock; -extern int emu_fps, - frames; -extern int readflash; +#if 0 +extern bitmap_t *buffer32; +#endif +#define buffer32 (monitors[monitor_index_global].target_buffer) +#define pal_lookup (monitors[monitor_index_global].mon_pal_lookup) +#define overscan_x (monitors[monitor_index_global].mon_overscan_x) +#define overscan_y (monitors[monitor_index_global].mon_overscan_y) +#define video_timing_read_b (monitors[monitor_index_global].mon_video_timing_read_b) +#define video_timing_read_l (monitors[monitor_index_global].mon_video_timing_read_l) +#define video_timing_read_w (monitors[monitor_index_global].mon_video_timing_read_w) +#define video_timing_write_b (monitors[monitor_index_global].mon_video_timing_write_b) +#define video_timing_write_l (monitors[monitor_index_global].mon_video_timing_write_l) +#define video_timing_write_w (monitors[monitor_index_global].mon_video_timing_write_w) +#define video_res_x (monitors[monitor_index_global].mon_res_x) +#define video_res_y (monitors[monitor_index_global].mon_res_y) +#define video_bpp (monitors[monitor_index_global].mon_bpp) +#define xsize (monitors[monitor_index_global].mon_xsize) +#define ysize (monitors[monitor_index_global].mon_ysize) +#define cga_palette (*monitors[monitor_index_global].mon_cga_palette) +#define changeframecount (monitors[monitor_index_global].mon_changeframecount) +#define scrnsz_x (monitors[monitor_index_global].mon_scrnsz_x) +#define scrnsz_y (monitors[monitor_index_global].mon_scrnsz_y) +#define efscrnsz_y (monitors[monitor_index_global].mon_efscrnsz_y) +#define unscaled_size_x (monitors[monitor_index_global].mon_unscaled_size_x) +#define unscaled_size_y (monitors[monitor_index_global].mon_unscaled_size_y) +extern PALETTE cgapal; +extern PALETTE cgapal_mono[6]; +#if 0 +extern uint32_t pal_lookup[256]; +#endif +extern int video_fullscreen; +extern int video_fullscreen_scale; +extern int video_fullscreen_first; +extern uint8_t fontdat[2048][8]; +extern uint8_t fontdatm[2048][16]; +extern uint8_t fontdat2[2048][8]; +extern uint8_t fontdatm2[2048][16]; +extern uint8_t fontdatw[512][32]; +extern uint8_t fontdat8x12[256][16]; +extern uint8_t fontdat12x18[256][36]; +extern dbcs_font_t *fontdatksc5601; +extern dbcs_font_t *fontdatksc5601_user; +extern uint32_t *video_6to8; +extern uint32_t *video_8togs; +extern uint32_t *video_8to32; +extern uint32_t *video_15to32; +extern uint32_t *video_16to32; +extern int enable_overscan; +extern int force_43; +extern int vid_resize; +extern int herc_blend; +extern int vid_cga_contrast; +extern int video_grayscale; +extern int video_graytype; +extern double cpuclock; +extern int emu_fps; +extern int frames; +extern int readflash; +extern int ibm8514_active; +extern int xga_active; /* Function handler pointers. */ -extern void (*video_recalctimings)(void); -extern void video_screenshot(uint32_t *buf, int start_x, int start_y, int row_len); +extern void (*video_recalctimings)(void); +extern void video_screenshot_monitor(uint32_t *buf, int start_x, int start_y, int row_len, int monitor_index); +extern void video_screenshot(uint32_t *buf, int start_x, int start_y, int row_len); #ifdef _WIN32 -extern void * __cdecl (*video_copy)(void *_Dst, const void *_Src, size_t _Size); -extern void * __cdecl video_transform_copy(void *_Dst, const void *_Src, size_t _Size); +extern void *__cdecl (*video_copy)(void *_Dst, const void *_Src, size_t _Size); +extern void *__cdecl video_transform_copy(void *_Dst, const void *_Src, size_t _Size); #else -extern void * (*video_copy)(void *__restrict _Dst, const void *__restrict _Src, size_t _Size); -extern void * video_transform_copy(void *__restrict _Dst, const void *__restrict _Src, size_t _Size); +extern void *(*video_copy)(void *__restrict _Dst, const void *__restrict _Src, size_t _Size); +extern void *video_transform_copy(void *__restrict _Dst, const void *__restrict _Src, size_t _Size); #endif - /* Table functions. */ -extern int video_card_available(int card); +extern int video_card_available(int card); #ifdef EMU_DEVICE_H -extern const device_t *video_card_getdevice(int card); +extern const device_t *video_card_getdevice(int card); #endif -extern int video_card_has_config(int card); -extern char *video_get_internal_name(int card); -extern int video_get_video_from_internal_name(char *s); -extern int video_is_mda(void); -extern int video_is_cga(void); -extern int video_is_ega_vga(void); -extern void video_inform(int type, const video_timings_t *ptr); -extern int video_get_type(void); +extern int video_card_has_config(int card); +extern const char *video_get_internal_name(int card); +extern int video_get_video_from_internal_name(char *s); +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); +extern void video_setblit(void (*blit)(int, int, int, int, int)); +extern void video_blend(int x, int y); +extern void video_blit_memtoscreen_8(int x, int y, int w, int h); +extern void video_blend_monitor(int x, int y, int monitor_index); +extern void video_process_8_monitor(int x, int y, int monitor_index); +extern void video_blit_memtoscreen_monitor(int x, int y, int w, int h, int monitor_index); +extern void video_blit_complete_monitor(int monitor_index); +extern void video_wait_for_blit_monitor(int monitor_index); +extern void video_wait_for_buffer_monitor(int monitor_index); -extern void video_setblit(void(*blit)(int,int,int,int)); -extern void video_blend(int x, int y); -extern void video_blit_memtoscreen_8(int x, int y, int w, int h); -extern void video_blit_memtoscreen(int x, int y, int w, int h); -extern void video_blit_complete(void); -extern void video_wait_for_blit(void); -extern void video_wait_for_buffer(void); +extern bitmap_t *create_bitmap(int w, int h); +extern void destroy_bitmap(bitmap_t *b); +extern void cgapal_rebuild_monitor(int monitor_index); +extern void hline(bitmap_t *b, int x1, int y, int x2, uint32_t col); +extern void updatewindowsize(int x, int y); -extern bitmap_t *create_bitmap(int w, int h); -extern void destroy_bitmap(bitmap_t *b); -extern void cgapal_rebuild(void); -extern void hline(bitmap_t *b, int x1, int y, int x2, uint32_t col); -extern void updatewindowsize(int x, int y); +extern void video_monitor_init(int); +extern void video_monitor_close(int); +extern void video_init(void); +extern void video_close(void); +extern void video_reset_close(void); +extern void video_pre_reset(int card); +extern void video_reset(int card); +extern void video_post_reset(void); +extern void video_voodoo_init(void); +extern uint8_t video_force_resize_get_monitor(int monitor_index); +extern void video_force_resize_set_monitor(uint8_t res, int monitor_index); +extern void video_update_timing(void); -extern void video_init(void); -extern void video_close(void); -extern void video_reset_close(void); -extern void video_pre_reset(int card); -extern void video_reset(int card); -extern uint8_t video_force_resize_get(void); -extern void video_force_resize_set(uint8_t res); -extern void video_update_timing(void); +extern void loadfont_ex(char *s, int format, int offset); +extern void loadfont(char *s, int format); -extern void loadfont_ex(char *s, int format, int offset); -extern void loadfont(char *s, int format); +extern int get_actual_size_x(void); +extern int get_actual_size_y(void); -extern int get_actual_size_x(void); -extern int get_actual_size_y(void); +extern uint32_t video_color_transform(uint32_t color); -extern uint32_t video_color_transform(uint32_t color); - -extern void agpgart_set_aperture(void *handle, uint32_t base, uint32_t size, int enable); -extern void agpgart_set_gart(void *handle, uint32_t base); +#define video_inform(type, video_timings_ptr) video_inform_monitor(type, video_timings_ptr, monitor_index_global) +#define video_get_type() video_get_type_monitor(0) +#define video_blend(x, y) video_blend_monitor(x, y, monitor_index_global) +#define video_blit_memtoscreen(x, y, w, h) video_blit_memtoscreen_monitor(x, y, w, h, monitor_index_global) +#define video_process_8(x, y) video_process_8_monitor(x, y, monitor_index_global) +#define video_blit_complete() video_blit_complete_monitor(monitor_index_global) +#define video_wait_for_blit() video_wait_for_blit_monitor(monitor_index_global) +#define video_wait_for_buffer() video_wait_for_buffer_monitor(monitor_index_global) +#define cgapal_rebuild() cgapal_rebuild_monitor(monitor_index_global) +#define video_force_resize_get() video_force_resize_get_monitor(monitor_index_global) +#define video_force_resize_set(val) video_force_resize_set_monitor(val, monitor_index_global) #ifdef __cplusplus } #endif - #ifdef EMU_DEVICE_H +/* IBM XGA */ +extern void xga_device_add(void); + +/* 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_mca_device; +extern const device_t mach32_pci_device; +extern const device_t mach32_onboard_pci_device; + /* ATi Mach64 */ extern const device_t mach64gx_isa_device; extern const device_t mach64gx_vlb_device; @@ -206,9 +317,9 @@ extern const device_t mach64gx_pci_device; extern const device_t mach64vt2_device; /* ATi 18800 */ -#if defined(DEV_BRANCH) && defined(USE_VGAWONDER) +# if defined(DEV_BRANCH) && defined(USE_VGAWONDER) extern const device_t ati18800_wonder_device; -#endif +# endif extern const device_t ati18800_vga88_device; extern const device_t ati18800_device; @@ -218,9 +329,9 @@ extern const device_t ati28800k_device; extern const device_t ati28800k_spc4620p_device; extern const device_t ati28800k_spc6033p_device; extern const device_t compaq_ati28800_device; -#if defined(DEV_BRANCH) && defined(USE_XL24) +# if defined(DEV_BRANCH) && defined(USE_XL24) extern const device_t ati28800_wonderxl24_device; -#endif +# endif /* Cirrus Logic GD54xx */ extern const device_t gd5401_isa_device; @@ -236,12 +347,17 @@ extern const device_t gd5426_onboard_device; extern const device_t gd5428_isa_device; extern const device_t gd5428_vlb_device; extern const device_t gd5428_diamond_speedstar_pro_b1_vlb_device; +extern const device_t gd5428_boca_isa_device; extern const device_t gd5428_mca_device; +extern const device_t gd5426_mca_device; extern const device_t gd5428_onboard_device; extern const device_t gd5429_isa_device; extern const device_t gd5429_vlb_device; extern const device_t gd5430_diamond_speedstar_pro_se_a8_vlb_device; +extern const device_t gd5430_vlb_device; +extern const device_t gd5430_onboard_vlb_device; extern const device_t gd5430_pci_device; +extern const device_t gd5430_onboard_pci_device; extern const device_t gd5434_isa_device; extern const device_t gd5434_diamond_speedstar_64_a3_isa_device; extern const device_t gd5434_onboard_pci_device; @@ -284,6 +400,8 @@ extern const device_t et4000w32_device; extern const device_t et4000w32_onboard_device; extern const device_t et4000w32i_isa_device; extern const device_t et4000w32i_vlb_device; +extern const device_t et4000w32p_videomagic_revb_vlb_device; +extern const device_t et4000w32p_videomagic_revb_pci_device; extern const device_t et4000w32p_revc_vlb_device; extern const device_t et4000w32p_revc_pci_device; extern const device_t et4000w32p_vlb_device; @@ -313,12 +431,12 @@ extern const device_t ht216_32_standalone_device; extern const device_t im1024_device; extern const device_t pgc_device; -#if defined(DEV_BRANCH) && defined(USE_MGA) +# if defined(DEV_BRANCH) && defined(USE_MGA) /* Matrox MGA */ extern const device_t millennium_device; extern const device_t mystique_device; extern const device_t mystique_220_device; -#endif +# endif /* Oak OTI-0x7 */ extern const device_t oti037c_device; @@ -347,6 +465,7 @@ extern const device_t s3_metheus_86c928_isa_device; extern const device_t s3_metheus_86c928_vlb_device; extern const device_t s3_spea_mercury_lite_86c928_pci_device; extern const device_t s3_spea_mirage_86c801_isa_device; +extern const device_t s3_86c805_onboard_vlb_device; extern const device_t s3_spea_mirage_86c805_vlb_device; extern const device_t s3_mirocrystal_8s_805_vlb_device; extern const device_t s3_mirocrystal_10sd_805_vlb_device; @@ -421,6 +540,7 @@ extern const device_t ibm_ps1_2121_device; extern const device_t tvga8900b_device; extern const device_t tvga8900d_device; extern const device_t tvga9000b_device; +extern const device_t nec_sv9000_device; /* IBM VGA */ extern const device_t vga_device; @@ -431,19 +551,24 @@ extern const device_t ps1vga_mca_device; extern const device_t voodoo_device; extern const device_t voodoo_banshee_device; extern const device_t creative_voodoo_banshee_device; +extern const device_t voodoo_3_1000_device; +extern const device_t voodoo_3_1000_agp_device; extern const device_t voodoo_3_2000_device; extern const device_t voodoo_3_2000_agp_device; extern const device_t voodoo_3_2000_agp_onboard_8m_device; extern const device_t voodoo_3_3000_device; extern const device_t voodoo_3_3000_agp_device; +extern const device_t voodoo_3_3500_agp_ntsc_device; +extern const device_t voodoo_3_3500_agp_pal_device; +extern const device_t compaq_voodoo_3_3500_agp_device; +extern const device_t voodoo_3_3500_se_agp_device; +extern const device_t voodoo_3_3500_si_agp_device; extern const device_t velocity_100_agp_device; +extern const device_t velocity_200_agp_device; /* Wyse 700 */ extern const device_t wy700_device; -/* AGP GART */ -extern const device_t agpgart_device; #endif - -#endif /*EMU_VIDEO_H*/ +#endif /*EMU_VIDEO_H*/ diff --git a/src/include/86box/vnc.h b/src/include/86box/vnc.h index 2d3dea3cd..a63c53403 100644 --- a/src/include/86box/vnc.h +++ b/src/include/86box/vnc.h @@ -1,39 +1,38 @@ /* - * 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. + * 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. + * This file is part of the 86Box distribution. * - * Definitions for the VNC renderer. + * Definitions for the VNC renderer. * * * - * Author: Fred N. van Kempen, + * Authors: Fred N. van Kempen, * - * Copyright 2017 Fred N. van Kempen. + * Copyright 2017 Fred N. van Kempen. */ -#ifndef EMU_VNC_H -# define EMU_VNC_H +#ifndef EMU_VNC_H +#define EMU_VNC_H #ifdef __cplusplus extern "C" { #endif -extern int vnc_init(void *); -extern void vnc_close(void); -extern void vnc_resize(int x, int y); -extern int vnc_pause(void); +extern int vnc_init(void *); +extern void vnc_close(void); +extern void vnc_resize(int x, int y); +extern int vnc_pause(void); -extern void vnc_kbinput(int, int); +extern void vnc_kbinput(int, int); -extern void vnc_take_screenshot(wchar_t *fn); +extern void vnc_take_screenshot(wchar_t *fn); #ifdef __cplusplus } #endif - -#endif /*EMU_VNC_H*/ +#endif /*EMU_VNC_H*/ diff --git a/src/include/86box/win.h b/src/include/86box/win.h index 4fb6a7d00..35f6688ad 100644 --- a/src/include/86box/win.h +++ b/src/include/86box/win.h @@ -1,72 +1,75 @@ /* - * 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. + * 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. + * This file is part of the 86Box distribution. * - * Platform support defintions for Win32. + * Platform support defintions for Win32. * * * - * Authors: Sarah Walker, - * Miran Grca, - * Fred N. van Kempen, + * Authors: Sarah Walker, + * Miran Grca, + * Fred N. van Kempen, * - * Copyright 2008-2019 Sarah Walker. - * Copyright 2016-2019 Miran Grca. - * Copyright 2017-2019 Fred N. van Kempen. - * Copyright 2021 Laci bá' + * Copyright 2008-2019 Sarah Walker. + * Copyright 2016-2019 Miran Grca. + * Copyright 2017-2019 Fred N. van Kempen. + * Copyright 2021 Laci bá' */ -#ifndef PLAT_WIN_H -# define PLAT_WIN_H -# define UNICODE -# define BITMAP WINDOWS_BITMAP -# if 0 -# ifdef _WIN32_WINNT -# undef _WIN32_WINNT -# define _WIN32_WINNT 0x0501 -# endif -# endif -# include -# include "resource.h" -# undef BITMAP +#ifndef PLAT_WIN_H +#define PLAT_WIN_H + +#ifndef UNICODE +# define UNICODE +#endif +#define BITMAP WINDOWS_BITMAP +#if 0 +# ifdef _WIN32_WINNT +# undef _WIN32_WINNT +# define _WIN32_WINNT 0x0501 +# endif +#endif +#include "resource.h" +#include +#undef BITMAP /* DPI Awareness Context, copied from MinGW-w64 windef.h */ #ifndef _DPI_AWARENESS_CONTEXTS_ DECLARE_HANDLE(DPI_AWARENESS_CONTEXT); -#define DPI_AWARENESS_CONTEXT_UNAWARE ((DPI_AWARENESS_CONTEXT)-1) -#define DPI_AWARENESS_CONTEXT_SYSTEM_AWARE ((DPI_AWARENESS_CONTEXT)-2) -#define DPI_AWARENESS_CONTEXT_PER_MONITOR_AWARE ((DPI_AWARENESS_CONTEXT)-3) -#define DPI_AWARENESS_CONTEXT_PER_MONITOR_AWARE_V2 ((DPI_AWARENESS_CONTEXT)-4) -#define DPI_AWARENESS_CONTEXT_UNAWARE_GDISCALED ((DPI_AWARENESS_CONTEXT)-5) +# define DPI_AWARENESS_CONTEXT_UNAWARE ((DPI_AWARENESS_CONTEXT) -1) +# define DPI_AWARENESS_CONTEXT_SYSTEM_AWARE ((DPI_AWARENESS_CONTEXT) -2) +# define DPI_AWARENESS_CONTEXT_PER_MONITOR_AWARE ((DPI_AWARENESS_CONTEXT) -3) +# define DPI_AWARENESS_CONTEXT_PER_MONITOR_AWARE_V2 ((DPI_AWARENESS_CONTEXT) -4) +# define DPI_AWARENESS_CONTEXT_UNAWARE_GDISCALED ((DPI_AWARENESS_CONTEXT) -5) #endif #ifndef WM_DPICHANGED_AFTERPARENT -#define WM_DPICHANGED_AFTERPARENT 0x02E3 +# define WM_DPICHANGED_AFTERPARENT 0x02E3 #endif /* Class names and such. */ -#define CLASS_NAME L"86BoxMainWnd" -#define MENU_NAME L"MainMenu" -#define ACCEL_NAME L"MainAccel" -#define SUB_CLASS_NAME L"86BoxSubWnd" -#define SB_CLASS_NAME L"86BoxStatusBar" -#define SB_MENU_NAME L"StatusBarMenu" -#define FS_CLASS_NAME L"86BoxFullScreen" -#define SDL_CLASS_NAME L"86BoxSDLWnd" -#define SDL_SUB_CLASS_NAME L"86BoxSDLSubWnd" +#define CLASS_NAME L"86BoxMainWnd" +#define MENU_NAME L"MainMenu" +#define ACCEL_NAME L"MainAccel" +#define SUB_CLASS_NAME L"86BoxSubWnd" +#define SB_CLASS_NAME L"86BoxStatusBar" +#define SB_MENU_NAME L"StatusBarMenu" +#define FS_CLASS_NAME L"86BoxFullScreen" +#define SDL_CLASS_NAME L"86BoxSDLWnd" +#define SDL_SUB_CLASS_NAME L"86BoxSDLSubWnd" -#define CASSETTE_SUBMENU_NAME L"CassetteSubmenu" -#define CARTRIDGE_SUBMENU_NAME L"CartridgeSubmenu" -#define FLOPPY_SUBMENU_NAME L"FloppySubmenu" -#define CDROM_SUBMENU_NAME L"CdromSubmenu" -#define ZIP_SUBMENU_NAME L"ZIPSubmenu" -#define MO_SUBMENU_NAME L"MOSubmenu" +#define CASSETTE_SUBMENU_NAME L"CassetteSubmenu" +#define CARTRIDGE_SUBMENU_NAME L"CartridgeSubmenu" +#define FLOPPY_SUBMENU_NAME L"FloppySubmenu" +#define CDROM_SUBMENU_NAME L"CdromSubmenu" +#define ZIP_SUBMENU_NAME L"ZIPSubmenu" +#define MO_SUBMENU_NAME L"MOSubmenu" -#define VID_GL_SUBMENU L"VidGLSubMenu" +#define VID_GL_SUBMENU L"VidGLSubMenu" /* Application-specific window messages. @@ -74,187 +77,178 @@ DECLARE_HANDLE(DPI_AWARENESS_CONTEXT); and 0x8895 with WPARAM = followed by 0x8896 with WPARAM = 0. All shutdowns will send an 0x8897. */ -#define WM_LEAVEFULLSCREEN WM_USER -#define WM_SAVESETTINGS 0x8888 -#define WM_SHOWSETTINGS 0x8889 -#define WM_PAUSE 0x8890 -#define WM_SENDHWND 0x8891 -#define WM_HARDRESET 0x8892 -#define WM_SHUTDOWN 0x8893 -#define WM_CTRLALTDEL 0x8894 +#define WM_LEAVEFULLSCREEN WM_USER +#define WM_SAVESETTINGS 0x8888 +#define WM_SHOWSETTINGS 0x8889 +#define WM_PAUSE 0x8890 +#define WM_SENDHWND 0x8891 +#define WM_HARDRESET 0x8892 +#define WM_SHUTDOWN 0x8893 +#define WM_CTRLALTDEL 0x8894 /* Pause/resume status: WPARAM = 1 for paused, 0 for resumed. */ -#define WM_SENDSTATUS 0x8895 +#define WM_SENDSTATUS 0x8895 /* Dialog (Settings or message box) status: WPARAM = 1 for open, 0 for closed. */ -#define WM_SENDDLGSTATUS 0x8896 +#define WM_SENDDLGSTATUS 0x8896 /* The emulator has shut down. */ -#define WM_HAS_SHUTDOWN 0x8897 +#define WM_HAS_SHUTDOWN 0x8897 #ifdef USE_VNC -#define RENDERERS_NUM 5 +# define RENDERERS_NUM 5 #else -#define RENDERERS_NUM 4 +# define RENDERERS_NUM 4 #endif - #ifdef __cplusplus extern "C" { #endif -extern HINSTANCE hinstance; -extern HWND hwndMain, - hwndRender; -extern HANDLE ghMutex; -extern HICON hIcon[256]; -extern int dpi; -extern RECT oldclip; -extern int sbar_height, tbar_height, user_resize; -extern int acp_utf8; +extern HINSTANCE hinstance; +extern HWND hwndMain; +extern HWND hwndRender; +extern HWND hwndRender2; +extern HANDLE ghMutex; +extern HICON hIcon[256]; +extern int dpi; +extern RECT oldclip; +extern int sbar_height; +extern int tbar_height; +extern int user_resize; +extern int acp_utf8; -// extern int status_is_open; +#if 0 +extern int status_is_open; +#endif -extern char openfilestring[512]; -extern WCHAR wopenfilestring[512]; +extern char openfilestring[512]; +extern WCHAR wopenfilestring[512]; -extern uint8_t filterindex; +extern uint8_t filterindex; - -extern void ResizeWindowByClientArea(HWND hwnd, int width, int height); -extern void InitCrashDump(void); +extern void ResizeWindowByClientArea(HWND hwnd, int width, int height); /* Emulator start/stop support functions. */ -extern void do_start(void); -extern void do_stop(void); +extern void do_start(void); +extern void do_stop(void); /* Internal platform support functions. */ -extern int has_language_changed(uint32_t id); -extern void set_language(uint32_t id); -extern int get_vidpause(void); -extern void show_cursor(int); +extern int has_language_changed(uint32_t id); +extern void set_language(uint32_t id); +extern int get_vidpause(void); +extern void show_cursor(int); -extern void keyboard_getkeymap(void); -extern void keyboard_handle(PRAWINPUT raw); +extern void keyboard_getkeymap(void); +extern void keyboard_handle(PRAWINPUT raw); -extern void win_mouse_init(void); -extern void win_mouse_close(void); -extern void win_mouse_handle(PRAWINPUT raw); +extern void win_mouse_init(void); +extern void win_mouse_close(void); +extern void win_mouse_handle(PRAWINPUT raw); -extern void win_joystick_handle(PRAWINPUT raw); +extern void win_joystick_handle(PRAWINPUT raw); -extern void win_notify_dlg_open(void); -extern void win_notify_dlg_closed(void); -extern int win_get_dpi(HWND hwnd); -extern int win_get_system_metrics(int i, int dpi); +extern void win_notify_dlg_open(void); +extern void win_notify_dlg_closed(void); +extern int win_get_dpi(HWND hwnd); +extern int win_get_system_metrics(int i, int dpi); -extern LPARAM win_get_string(int id); +extern LPARAM win_get_string(int id); -extern void win_clear_icon_set(); -extern void win_system_icon_set(); -extern void win_load_icon_set(); -extern void win_get_icons_path(char* path_root); +extern void win_clear_icon_set(void); +extern void win_system_icon_set(void); +extern void win_load_icon_set(void); +extern void win_get_icons_path(char *path_root); -extern intptr_t fdd_type_to_icon(int type); +extern intptr_t fdd_type_to_icon(int type); #ifdef EMU_DEVICE_H -extern uint8_t deviceconfig_open(HWND hwnd, const device_t *device); -extern uint8_t deviceconfig_inst_open(HWND hwnd, const device_t *device, int inst); +extern uint8_t deviceconfig_open(HWND hwnd, const device_t *device); +extern uint8_t deviceconfig_inst_open(HWND hwnd, const device_t *device, int inst); #endif -extern uint8_t joystickconfig_open(HWND hwnd, int joy_nr, int type); +extern uint8_t joystickconfig_open(HWND hwnd, int joy_nr, int type); -extern int getfile(HWND hwnd, char *f, char *fn); -extern int getsfile(HWND hwnd, char *f, char *fn); - -extern void hard_disk_add_open(HWND hwnd, int is_existing); -extern int hard_disk_was_added(void); +extern int getfile(HWND hwnd, char *f, char *fn); +extern int getsfile(HWND hwnd, char *f, char *fn); +extern void hard_disk_add_open(HWND hwnd, int is_existing); +extern int hard_disk_was_added(void); /* Platform UI support functions. */ -extern int ui_init(int nCmdShow); - +extern int ui_init(int nCmdShow); /* Functions in win_about.c: */ -extern void AboutDialogCreate(HWND hwnd); - +extern void AboutDialogCreate(HWND hwnd); /* Functions in win_snd_gain.c: */ -extern void SoundGainDialogCreate(HWND hwnd); - +extern void SoundGainDialogCreate(HWND hwnd); /* Functions in win_new_floppy.c: */ -extern void NewFloppyDialogCreate(HWND hwnd, int id, int part); - +extern void NewFloppyDialogCreate(HWND hwnd, int id, int part); /* Functions in win_specify_dim.c: */ -extern void SpecifyDimensionsDialogCreate(HWND hwnd); +extern void SpecifyDimensionsDialogCreate(HWND hwnd); /* Functions in win_preferences.c: */ -extern void PreferencesDlgCreate(HWND hwnd); - +extern void PreferencesDlgCreate(HWND hwnd); /* Functions in win_settings.c: */ -#define SETTINGS_PAGE_MACHINE 0 -#define SETTINGS_PAGE_VIDEO 1 -#define SETTINGS_PAGE_INPUT 2 -#define SETTINGS_PAGE_SOUND 3 -#define SETTINGS_PAGE_NETWORK 4 -#define SETTINGS_PAGE_PORTS 5 -#define SETTINGS_PAGE_STORAGE 6 -#define SETTINGS_PAGE_HARD_DISKS 7 -#define SETTINGS_PAGE_FLOPPY_AND_CDROM_DRIVES 8 -#define SETTINGS_PAGE_OTHER_REMOVABLE_DEVICES 9 -#define SETTINGS_PAGE_PERIPHERALS 10 - -extern void win_settings_open(HWND hwnd); -extern void win_settings_open_ex(HWND hwnd, int category); +#define SETTINGS_PAGE_MACHINE 0 +#define SETTINGS_PAGE_VIDEO 1 +#define SETTINGS_PAGE_INPUT 2 +#define SETTINGS_PAGE_SOUND 3 +#define SETTINGS_PAGE_NETWORK 4 +#define SETTINGS_PAGE_PORTS 5 +#define SETTINGS_PAGE_STORAGE 6 +#define SETTINGS_PAGE_HARD_DISKS 7 +#define SETTINGS_PAGE_FLOPPY_AND_CDROM_DRIVES 8 +#define SETTINGS_PAGE_OTHER_REMOVABLE_DEVICES 9 +#define SETTINGS_PAGE_PERIPHERALS 10 +extern void win_settings_open(HWND hwnd); +extern void win_settings_open_ex(HWND hwnd, int category); /* Functions in win_stbar.c: */ -extern HWND hwndSBAR; -extern void StatusBarCreate(HWND hwndParent, uintptr_t idStatus, HINSTANCE hInst); -extern int MediaMenuHandler(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam); - +extern HWND hwndSBAR; +extern void StatusBarCreate(HWND hwndParent, uintptr_t idStatus, HINSTANCE hInst); +extern int MediaMenuHandler(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam); /* Functions in win_toolbar.c */ -extern HWND hwndRebar; -extern void ToolBarCreate(HWND hwndParent, HINSTANCE hInst); -extern void ToolBarLoadIcons(); -extern void ToolBarUpdatePause(int paused); - +extern HWND hwndRebar; +extern void ToolBarCreate(HWND hwndParent, HINSTANCE hInst); +extern void ToolBarLoadIcons(void); +extern void ToolBarUpdatePause(int paused); /* Functions in win_dialog.c: */ /* Pass NULL in the title param to use the default title. */ -extern int file_dlg_w(HWND hwnd, WCHAR *f, WCHAR *fn, WCHAR *title, int save); -extern int file_dlg(HWND hwnd, WCHAR *f, char *fn, char *title, int save); -extern int file_dlg_mb(HWND hwnd, char *f, char *fn, char *title, int save); -extern int file_dlg_w_st(HWND hwnd, int i, WCHAR *fn, char *title, int save); -extern int file_dlg_st(HWND hwnd, int i, char *fn, char *title, int save); - -extern wchar_t *BrowseFolder(wchar_t *saved_path, wchar_t *title); +extern int file_dlg_w(HWND hwnd, WCHAR *f, WCHAR *fn, WCHAR *title, int save); +extern int file_dlg(HWND hwnd, WCHAR *f, char *fn, char *title, int save); +extern int file_dlg_mb(HWND hwnd, char *f, char *fn, char *title, int save); +extern int file_dlg_w_st(HWND hwnd, int i, WCHAR *fn, char *title, int save); +extern int file_dlg_st(HWND hwnd, int i, char *fn, char *title, int save); +extern wchar_t *BrowseFolder(wchar_t *saved_path, wchar_t *title); /* Functions in win_media_menu.c */ -extern void media_menu_init(); -extern void media_menu_reset(); -extern int media_menu_proc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam); -extern HMENU media_menu_get_cassette(void); -extern HMENU media_menu_get_cartridge(int id); -extern HMENU media_menu_get_floppy(int id); -extern HMENU media_menu_get_cdrom(int id); -extern HMENU media_menu_get_zip(int id); -extern HMENU media_menu_get_mo(int id); -extern void media_menu_update_cassette(void); -extern void media_menu_update_cartridge(int id); -extern void media_menu_update_floppy(int id); -extern void media_menu_update_cdrom(int id); -extern void media_menu_update_zip(int id); -extern void media_menu_update_mo(int id); +extern void media_menu_init(void); +extern void media_menu_reset(void); +extern int media_menu_proc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam); +extern HMENU media_menu_get_cassette(void); +extern HMENU media_menu_get_cartridge(int id); +extern HMENU media_menu_get_floppy(int id); +extern HMENU media_menu_get_cdrom(int id); +extern HMENU media_menu_get_zip(int id); +extern HMENU media_menu_get_mo(int id); +extern void media_menu_update_cassette(void); +extern void media_menu_update_cartridge(int id); +extern void media_menu_update_floppy(int id); +extern void media_menu_update_cdrom(int id); +extern void media_menu_update_zip(int id); +extern void media_menu_update_mo(int id); /* Functions in win_ui.c */ -extern HMENU menuMain; -extern void ResetAllMenus(); +extern HMENU menuMain; +extern void ResetAllMenus(void); #ifdef __cplusplus } #endif - -#endif /*PLAT_WIN_H*/ +#endif /*PLAT_WIN_H*/ diff --git a/src/include/86box/win_opengl.h b/src/include/86box/win_opengl.h index 9e78c0aed..d354131ef 100644 --- a/src/include/86box/win_opengl.h +++ b/src/include/86box/win_opengl.h @@ -1,28 +1,29 @@ /* - * 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. + * 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. + * This file is part of the 86Box distribution. * - * Header file for OpenGL rendering module + * Header file for OpenGL rendering module * - * Authors: Teemu Korhonen + * Authors: Teemu Korhonen * - * Copyright 2021 Teemu Korhonen + * Copyright 2021 Teemu Korhonen */ + #ifndef WIN_OPENGL_H #define WIN_OPENGL_H #define UNICODE -#include +#include -extern int opengl_init(HWND hwnd); -extern int opengl_pause(void); +extern int opengl_init(HWND hwnd); +extern int opengl_pause(void); extern void opengl_close(void); extern void opengl_set_fs(int fs); extern void opengl_resize(int w, int h); extern void opengl_reload(void); -#endif /*!WIN_OPENGL_H*/ \ No newline at end of file +#endif /*!WIN_OPENGL_H*/ diff --git a/src/include/86box/win_opengl_glslp.h b/src/include/86box/win_opengl_glslp.h index dcc098635..6586cd526 100644 --- a/src/include/86box/win_opengl_glslp.h +++ b/src/include/86box/win_opengl_glslp.h @@ -1,23 +1,24 @@ /* - * 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. + * 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. + * This file is part of the 86Box distribution. * - * Header file for shader file parser. + * Header file for shader file parser. * - * Authors: Teemu Korhonen + * Authors: Teemu Korhonen * - * Copyright 2021 Teemu Korhonen + * Copyright 2021 Teemu Korhonen */ + #ifndef WIN_OPENGL_GLSLP_H #define WIN_OPENGL_GLSLP_H #include -GLuint load_custom_shaders(const char* path); -GLuint load_default_shaders(); +GLuint load_custom_shaders(const char *path); +GLuint load_default_shaders(void); -#endif /*!WIN_OPENGL_GLSLP_H*/ \ No newline at end of file +#endif /*!WIN_OPENGL_GLSLP_H*/ diff --git a/src/include/86box/win_sdl.h b/src/include/86box/win_sdl.h index aa082fe6c..69340e8b6 100644 --- a/src/include/86box/win_sdl.h +++ b/src/include/86box/win_sdl.h @@ -1,38 +1,38 @@ /* - * 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. + * 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. + * This file is part of the 86Box distribution. * - * Definitions for the libSDL2 rendering module. + * Definitions for the libSDL2 rendering module. * * * - * Authors: Fred N. van Kempen, - * Michael Drüing, + * Authors: Fred N. van Kempen, + * Michael Drüing, * - * Copyright 2018,2019 Fred N. van Kempen. - * Copyright 2018,2019 Michael Drüing. + * Copyright 2018-2019 Fred N. van Kempen. + * Copyright 2018-2019 Michael Drüing. * - * Redistribution and use in source and binary forms, with - * or without modification, are permitted provided that the - * following conditions are met: + * Redistribution and use in source and binary forms, with + * or without modification, are permitted provided that the + * following conditions are met: * - * 1. Redistributions of source code must retain the entire - * above notice, this list of conditions and the following - * disclaimer. + * 1. Redistributions of source code must retain the entire + * above notice, this list of conditions and the following + * disclaimer. * - * 2. Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the - * following disclaimer in the documentation and/or other - * materials provided with the distribution. + * 2. Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the + * following disclaimer in the documentation and/or other + * materials provided with the distribution. * - * 3. Neither the name of the copyright holder nor the names - * of its contributors may be used to endorse or promote - * products derived from this software without specific - * prior written permission. + * 3. Neither the name of the copyright holder nor the names + * of its contributors may be used to endorse or promote + * products derived from this software without specific + * prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT @@ -46,18 +46,18 @@ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ + #ifndef WIN_SDL_H -# define WIN_SDL_H +#define WIN_SDL_H +extern void sdl_close(void); +extern int sdl_inits(HWND h); +extern int sdl_inith(HWND h); +extern int sdl_initho(HWND h); +extern int sdl_pause(void); +extern void sdl_resize(int x, int y); +extern void sdl_enable(int enable); +extern void sdl_set_fs(int fs); +extern void sdl_reload(void); -extern void sdl_close(void); -extern int sdl_inits(HWND h); -extern int sdl_inith(HWND h); -extern int sdl_initho(HWND h); -extern int sdl_pause(void); -extern void sdl_resize(int x, int y); -extern void sdl_enable(int enable); -extern void sdl_set_fs(int fs); -extern void sdl_reload(void); - -#endif /*WIN_SDL_H*/ +#endif /*WIN_SDL_H*/ diff --git a/src/include/86box/zip.h b/src/include/86box/zip.h index 4a7c05cbd..a4a4c341f 100644 --- a/src/include/86box/zip.h +++ b/src/include/86box/zip.h @@ -1,127 +1,152 @@ /* - * 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. + * 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. + * This file is part of the 86Box distribution. * - * Implementation of the Iomega ZIP drive with SCSI(-like) - * commands, for both ATAPI and SCSI usage. + * Implementation of the Iomega ZIP drive with SCSI(-like) + * commands, for both ATAPI and SCSI usage. * * * - * Author: Miran Grca, + * Authors: Miran Grca, * - * Copyright 2018,2019 Miran Grca. + * Copyright 2018-2019 Miran Grca. */ + #ifndef EMU_ZIP_H #define EMU_ZIP_H +#define ZIP_NUM 4 -#define ZIP_NUM 4 +#define BUF_SIZE 32768 -#define BUF_SIZE 32768 +#define ZIP_TIME 10.0 -#define ZIP_TIME 10.0 - -#define ZIP_SECTORS (96*2048) +#define ZIP_SECTORS (96 * 2048) #define ZIP_250_SECTORS (489532) +#define ZIP_IMAGE_HISTORY 4 enum { ZIP_BUS_DISABLED = 0, - ZIP_BUS_ATAPI = 5, - ZIP_BUS_SCSI, - ZIP_BUS_USB + ZIP_BUS_ATAPI = 5, + ZIP_BUS_SCSI = 6, + ZIP_BUS_USB = 7 }; - -typedef struct { +typedef struct zip_drive_t { uint8_t id; union { - uint8_t res, res0, /* Reserved for other ID's. */ - res1, - ide_channel, scsi_device_id; + uint8_t res; + uint8_t res0; /* Reserved for other ID's. */ + uint8_t res1; + uint8_t ide_channel; + uint8_t scsi_device_id; }; - uint8_t bus_type, /* 0 = ATAPI, 1 = SCSI */ - bus_mode, /* Bit 0 = PIO suported; - Bit 1 = DMA supportd. */ - read_only, /* Struct variable reserved for - media status. */ - pad, pad0; + uint8_t bus_type; /* 0 = ATAPI, 1 = SCSI */ + uint8_t bus_mode; /* Bit 0 = PIO suported; + Bit 1 = DMA supportd. */ + uint8_t read_only; /* Struct variable reserved for + media status. */ + uint8_t pad; + uint8_t pad0; - FILE *f; + FILE *fp; void *priv; - char image_path[1024], - prev_image_path[1024]; + char image_path[1024]; + char prev_image_path[1024]; - uint32_t is_250, medium_size, - base; + char *image_history[ZIP_IMAGE_HISTORY]; + + uint32_t is_250; + uint32_t medium_size; + uint32_t base; } zip_drive_t; -typedef struct { +typedef struct zip_t { mode_sense_pages_t ms_pages_saved; zip_drive_t *drv; +#ifdef EMU_IDE_H + ide_tf_t * tf; +#else + void * tf; +#endif - uint8_t *buffer, - atapi_cdb[16], - current_cdb[16], - sense[256]; + uint8_t *buffer; + uint8_t atapi_cdb[16]; + uint8_t current_cdb[16]; + uint8_t sense[256]; - uint8_t status, phase, - error, id, - features, cur_lun, - pad0, pad1; +#ifdef ANCIENT_CODE + /* Task file. */ + uint8_t features; + uint8_t phase; + uint16_t request_length; + uint8_t status; + uint8_t error; + uint16_t pad; + uint32_t pos; +#endif - uint16_t request_length, max_transfer_len; + uint8_t id; + uint8_t cur_lun; + uint8_t pad0; + uint8_t pad1; - int requested_blocks, packet_status, - total_length, do_page_save, - unit_attention, request_pos, - old_len, pad3; + uint16_t max_transfer_len; + uint16_t pad2; - uint32_t sector_pos, sector_len, - packet_len, pos; + int requested_blocks; + int packet_status; + int total_length; + int do_page_save; + int unit_attention; + int request_pos; + int old_len; + int pad3; + + uint32_t sector_pos; + uint32_t sector_len; + uint32_t packet_len; double callback; } zip_t; - -extern zip_t *zip[ZIP_NUM]; -extern zip_drive_t zip_drives[ZIP_NUM]; -extern uint8_t atapi_zip_drives[8]; -extern uint8_t scsi_zip_drives[16]; +extern zip_t *zip[ZIP_NUM]; +extern zip_drive_t zip_drives[ZIP_NUM]; +extern uint8_t atapi_zip_drives[8]; +extern uint8_t scsi_zip_drives[16]; #define zip_sense_error dev->sense[0] -#define zip_sense_key dev->sense[2] -#define zip_asc dev->sense[12] -#define zip_ascq dev->sense[13] - +#define zip_sense_key dev->sense[2] +#define zip_asc dev->sense[12] +#define zip_ascq dev->sense[13] #ifdef __cplusplus extern "C" { #endif -extern void zip_disk_close(zip_t *dev); -extern void zip_disk_reload(zip_t *dev); -extern void zip_insert(zip_t *dev); +extern void zip_disk_close(zip_t *dev); +extern void zip_disk_reload(zip_t *dev); +extern void zip_insert(zip_t *dev); -extern void zip_global_init(void); -extern void zip_hard_reset(void); +extern void zip_global_init(void); +extern void zip_hard_reset(void); -extern void zip_reset(scsi_common_t *sc); -extern int zip_load(zip_t *dev, char *fn); -extern void zip_close(); +extern void zip_reset(scsi_common_t *sc); +extern int zip_load(zip_t *dev, char *fn); +extern void zip_close(void); #ifdef __cplusplus } #endif - -#endif /*EMU_ZIP_H*/ +#endif /*EMU_ZIP_H*/ diff --git a/src/include/AL/al.h b/src/include/AL/al.h deleted file mode 100644 index 413b38331..000000000 --- a/src/include/AL/al.h +++ /dev/null @@ -1,656 +0,0 @@ -#ifndef AL_AL_H -#define AL_AL_H - -#if defined(__cplusplus) -extern "C" { -#endif - -#ifndef AL_API - #if defined(AL_LIBTYPE_STATIC) - #define AL_API - #elif defined(_WIN32) - #define AL_API __declspec(dllimport) - #else - #define AL_API extern - #endif -#endif - -#if defined(_WIN32) - #define AL_APIENTRY __cdecl -#else - #define AL_APIENTRY -#endif - - -/** Deprecated macro. */ -#define OPENAL -#define ALAPI AL_API -#define ALAPIENTRY AL_APIENTRY -#define AL_INVALID (-1) -#define AL_ILLEGAL_ENUM AL_INVALID_ENUM -#define AL_ILLEGAL_COMMAND AL_INVALID_OPERATION - -/** Supported AL version. */ -#define AL_VERSION_1_0 -#define AL_VERSION_1_1 - -/** 8-bit boolean */ -typedef char ALboolean; - -/** character */ -typedef char ALchar; - -/** signed 8-bit 2's complement integer */ -typedef signed char ALbyte; - -/** unsigned 8-bit integer */ -typedef unsigned char ALubyte; - -/** signed 16-bit 2's complement integer */ -typedef short ALshort; - -/** unsigned 16-bit integer */ -typedef unsigned short ALushort; - -/** signed 32-bit 2's complement integer */ -typedef int ALint; - -/** unsigned 32-bit integer */ -typedef unsigned int ALuint; - -/** non-negative 32-bit binary integer size */ -typedef int ALsizei; - -/** enumerated 32-bit value */ -typedef int ALenum; - -/** 32-bit IEEE754 floating-point */ -typedef float ALfloat; - -/** 64-bit IEEE754 floating-point */ -typedef double ALdouble; - -/** void type (for opaque pointers only) */ -typedef void ALvoid; - - -/* Enumerant values begin at column 50. No tabs. */ - -/** "no distance model" or "no buffer" */ -#define AL_NONE 0 - -/** Boolean False. */ -#define AL_FALSE 0 - -/** Boolean True. */ -#define AL_TRUE 1 - - -/** - * Relative source. - * Type: ALboolean - * Range: [AL_TRUE, AL_FALSE] - * Default: AL_FALSE - * - * Specifies if the Source has relative coordinates. - */ -#define AL_SOURCE_RELATIVE 0x202 - - -/** - * Inner cone angle, in degrees. - * Type: ALint, ALfloat - * Range: [0 - 360] - * Default: 360 - * - * The angle covered by the inner cone, where the source will not attenuate. - */ -#define AL_CONE_INNER_ANGLE 0x1001 - -/** - * Outer cone angle, in degrees. - * Range: [0 - 360] - * Default: 360 - * - * The angle covered by the outer cone, where the source will be fully - * attenuated. - */ -#define AL_CONE_OUTER_ANGLE 0x1002 - -/** - * Source pitch. - * Type: ALfloat - * Range: [0.5 - 2.0] - * Default: 1.0 - * - * A multiplier for the frequency (sample rate) of the source's buffer. - */ -#define AL_PITCH 0x1003 - -/** - * Source or listener position. - * Type: ALfloat[3], ALint[3] - * Default: {0, 0, 0} - * - * The source or listener location in three dimensional space. - * - * OpenAL, like OpenGL, uses a right handed coordinate system, where in a - * frontal default view X (thumb) points right, Y points up (index finger), and - * Z points towards the viewer/camera (middle finger). - * - * To switch from a left handed coordinate system, flip the sign on the Z - * coordinate. - */ -#define AL_POSITION 0x1004 - -/** - * Source direction. - * Type: ALfloat[3], ALint[3] - * Default: {0, 0, 0} - * - * Specifies the current direction in local space. - * A zero-length vector specifies an omni-directional source (cone is ignored). - */ -#define AL_DIRECTION 0x1005 - -/** - * Source or listener velocity. - * Type: ALfloat[3], ALint[3] - * Default: {0, 0, 0} - * - * Specifies the current velocity in local space. - */ -#define AL_VELOCITY 0x1006 - -/** - * Source looping. - * Type: ALboolean - * Range: [AL_TRUE, AL_FALSE] - * Default: AL_FALSE - * - * Specifies whether source is looping. - */ -#define AL_LOOPING 0x1007 - -/** - * Source buffer. - * Type: ALuint - * Range: any valid Buffer. - * - * Specifies the buffer to provide sound samples. - */ -#define AL_BUFFER 0x1009 - -/** - * Source or listener gain. - * Type: ALfloat - * Range: [0.0 - ] - * - * A value of 1.0 means unattenuated. Each division by 2 equals an attenuation - * of about -6dB. Each multiplicaton by 2 equals an amplification of about - * +6dB. - * - * A value of 0.0 is meaningless with respect to a logarithmic scale; it is - * silent. - */ -#define AL_GAIN 0x100A - -/** - * Minimum source gain. - * Type: ALfloat - * Range: [0.0 - 1.0] - * - * The minimum gain allowed for a source, after distance and cone attenation is - * applied (if applicable). - */ -#define AL_MIN_GAIN 0x100D - -/** - * Maximum source gain. - * Type: ALfloat - * Range: [0.0 - 1.0] - * - * The maximum gain allowed for a source, after distance and cone attenation is - * applied (if applicable). - */ -#define AL_MAX_GAIN 0x100E - -/** - * Listener orientation. - * Type: ALfloat[6] - * Default: {0.0, 0.0, -1.0, 0.0, 1.0, 0.0} - * - * Effectively two three dimensional vectors. The first vector is the front (or - * "at") and the second is the top (or "up"). - * - * Both vectors are in local space. - */ -#define AL_ORIENTATION 0x100F - -/** - * Source state (query only). - * Type: ALint - * Range: [AL_INITIAL, AL_PLAYING, AL_PAUSED, AL_STOPPED] - */ -#define AL_SOURCE_STATE 0x1010 - -/** Source state value. */ -#define AL_INITIAL 0x1011 -#define AL_PLAYING 0x1012 -#define AL_PAUSED 0x1013 -#define AL_STOPPED 0x1014 - -/** - * Source Buffer Queue size (query only). - * Type: ALint - * - * The number of buffers queued using alSourceQueueBuffers, minus the buffers - * removed with alSourceUnqueueBuffers. - */ -#define AL_BUFFERS_QUEUED 0x1015 - -/** - * Source Buffer Queue processed count (query only). - * Type: ALint - * - * The number of queued buffers that have been fully processed, and can be - * removed with alSourceUnqueueBuffers. - * - * Looping sources will never fully process buffers because they will be set to - * play again for when the source loops. - */ -#define AL_BUFFERS_PROCESSED 0x1016 - -/** - * Source reference distance. - * Type: ALfloat - * Range: [0.0 - ] - * Default: 1.0 - * - * The distance in units that no attenuation occurs. - * - * At 0.0, no distance attenuation ever occurs on non-linear attenuation models. - */ -#define AL_REFERENCE_DISTANCE 0x1020 - -/** - * Source rolloff factor. - * Type: ALfloat - * Range: [0.0 - ] - * Default: 1.0 - * - * Multiplier to exaggerate or diminish distance attenuation. - * - * At 0.0, no distance attenuation ever occurs. - */ -#define AL_ROLLOFF_FACTOR 0x1021 - -/** - * Outer cone gain. - * Type: ALfloat - * Range: [0.0 - 1.0] - * Default: 0.0 - * - * The gain attenuation applied when the listener is outside of the source's - * outer cone. - */ -#define AL_CONE_OUTER_GAIN 0x1022 - -/** - * Source maximum distance. - * Type: ALfloat - * Range: [0.0 - ] - * Default: +inf - * - * The distance above which the source is not attenuated any further with a - * clamped distance model, or where attenuation reaches 0.0 gain for linear - * distance models with a default rolloff factor. - */ -#define AL_MAX_DISTANCE 0x1023 - -/** Source buffer position, in seconds */ -#define AL_SEC_OFFSET 0x1024 -/** Source buffer position, in sample frames */ -#define AL_SAMPLE_OFFSET 0x1025 -/** Source buffer position, in bytes */ -#define AL_BYTE_OFFSET 0x1026 - -/** - * Source type (query only). - * Type: ALint - * Range: [AL_STATIC, AL_STREAMING, AL_UNDETERMINED] - * - * A Source is Static if a Buffer has been attached using AL_BUFFER. - * - * A Source is Streaming if one or more Buffers have been attached using - * alSourceQueueBuffers. - * - * A Source is Undetermined when it has the NULL buffer attached using - * AL_BUFFER. - */ -#define AL_SOURCE_TYPE 0x1027 - -/** Source type value. */ -#define AL_STATIC 0x1028 -#define AL_STREAMING 0x1029 -#define AL_UNDETERMINED 0x1030 - -/** Buffer format specifier. */ -#define AL_FORMAT_MONO8 0x1100 -#define AL_FORMAT_MONO16 0x1101 -#define AL_FORMAT_STEREO8 0x1102 -#define AL_FORMAT_STEREO16 0x1103 - -/** Buffer frequency (query only). */ -#define AL_FREQUENCY 0x2001 -/** Buffer bits per sample (query only). */ -#define AL_BITS 0x2002 -/** Buffer channel count (query only). */ -#define AL_CHANNELS 0x2003 -/** Buffer data size (query only). */ -#define AL_SIZE 0x2004 - -/** - * Buffer state. - * - * Not for public use. - */ -#define AL_UNUSED 0x2010 -#define AL_PENDING 0x2011 -#define AL_PROCESSED 0x2012 - - -/** No error. */ -#define AL_NO_ERROR 0 - -/** Invalid name paramater passed to AL call. */ -#define AL_INVALID_NAME 0xA001 - -/** Invalid enum parameter passed to AL call. */ -#define AL_INVALID_ENUM 0xA002 - -/** Invalid value parameter passed to AL call. */ -#define AL_INVALID_VALUE 0xA003 - -/** Illegal AL call. */ -#define AL_INVALID_OPERATION 0xA004 - -/** Not enough memory. */ -#define AL_OUT_OF_MEMORY 0xA005 - - -/** Context string: Vendor ID. */ -#define AL_VENDOR 0xB001 -/** Context string: Version. */ -#define AL_VERSION 0xB002 -/** Context string: Renderer ID. */ -#define AL_RENDERER 0xB003 -/** Context string: Space-separated extension list. */ -#define AL_EXTENSIONS 0xB004 - - -/** - * Doppler scale. - * Type: ALfloat - * Range: [0.0 - ] - * Default: 1.0 - * - * Scale for source and listener velocities. - */ -#define AL_DOPPLER_FACTOR 0xC000 -AL_API void AL_APIENTRY alDopplerFactor(ALfloat value); - -/** - * Doppler velocity (deprecated). - * - * A multiplier applied to the Speed of Sound. - */ -#define AL_DOPPLER_VELOCITY 0xC001 -AL_API void AL_APIENTRY alDopplerVelocity(ALfloat value); - -/** - * Speed of Sound, in units per second. - * Type: ALfloat - * Range: [0.0001 - ] - * Default: 343.3 - * - * The speed at which sound waves are assumed to travel, when calculating the - * doppler effect. - */ -#define AL_SPEED_OF_SOUND 0xC003 -AL_API void AL_APIENTRY alSpeedOfSound(ALfloat value); - -/** - * Distance attenuation model. - * Type: ALint - * Range: [AL_NONE, AL_INVERSE_DISTANCE, AL_INVERSE_DISTANCE_CLAMPED, - * AL_LINEAR_DISTANCE, AL_LINEAR_DISTANCE_CLAMPED, - * AL_EXPONENT_DISTANCE, AL_EXPONENT_DISTANCE_CLAMPED] - * Default: AL_INVERSE_DISTANCE_CLAMPED - * - * The model by which sources attenuate with distance. - * - * None - No distance attenuation. - * Inverse - Doubling the distance halves the source gain. - * Linear - Linear gain scaling between the reference and max distances. - * Exponent - Exponential gain dropoff. - * - * Clamped variations work like the non-clamped counterparts, except the - * distance calculated is clamped between the reference and max distances. - */ -#define AL_DISTANCE_MODEL 0xD000 -AL_API void AL_APIENTRY alDistanceModel(ALenum distanceModel); - -/** Distance model value. */ -#define AL_INVERSE_DISTANCE 0xD001 -#define AL_INVERSE_DISTANCE_CLAMPED 0xD002 -#define AL_LINEAR_DISTANCE 0xD003 -#define AL_LINEAR_DISTANCE_CLAMPED 0xD004 -#define AL_EXPONENT_DISTANCE 0xD005 -#define AL_EXPONENT_DISTANCE_CLAMPED 0xD006 - -/** Renderer State management. */ -AL_API void AL_APIENTRY alEnable(ALenum capability); -AL_API void AL_APIENTRY alDisable(ALenum capability); -AL_API ALboolean AL_APIENTRY alIsEnabled(ALenum capability); - -/** State retrieval. */ -AL_API const ALchar* AL_APIENTRY alGetString(ALenum param); -AL_API void AL_APIENTRY alGetBooleanv(ALenum param, ALboolean *values); -AL_API void AL_APIENTRY alGetIntegerv(ALenum param, ALint *values); -AL_API void AL_APIENTRY alGetFloatv(ALenum param, ALfloat *values); -AL_API void AL_APIENTRY alGetDoublev(ALenum param, ALdouble *values); -AL_API ALboolean AL_APIENTRY alGetBoolean(ALenum param); -AL_API ALint AL_APIENTRY alGetInteger(ALenum param); -AL_API ALfloat AL_APIENTRY alGetFloat(ALenum param); -AL_API ALdouble AL_APIENTRY alGetDouble(ALenum param); - -/** - * Error retrieval. - * - * Obtain the first error generated in the AL context since the last check. - */ -AL_API ALenum AL_APIENTRY alGetError(void); - -/** - * Extension support. - * - * Query for the presence of an extension, and obtain any appropriate function - * pointers and enum values. - */ -AL_API ALboolean AL_APIENTRY alIsExtensionPresent(const ALchar *extname); -AL_API void* AL_APIENTRY alGetProcAddress(const ALchar *fname); -AL_API ALenum AL_APIENTRY alGetEnumValue(const ALchar *ename); - - -/** Set Listener parameters */ -AL_API void AL_APIENTRY alListenerf(ALenum param, ALfloat value); -AL_API void AL_APIENTRY alListener3f(ALenum param, ALfloat value1, ALfloat value2, ALfloat value3); -AL_API void AL_APIENTRY alListenerfv(ALenum param, const ALfloat *values); -AL_API void AL_APIENTRY alListeneri(ALenum param, ALint value); -AL_API void AL_APIENTRY alListener3i(ALenum param, ALint value1, ALint value2, ALint value3); -AL_API void AL_APIENTRY alListeneriv(ALenum param, const ALint *values); - -/** Get Listener parameters */ -AL_API void AL_APIENTRY alGetListenerf(ALenum param, ALfloat *value); -AL_API void AL_APIENTRY alGetListener3f(ALenum param, ALfloat *value1, ALfloat *value2, ALfloat *value3); -AL_API void AL_APIENTRY alGetListenerfv(ALenum param, ALfloat *values); -AL_API void AL_APIENTRY alGetListeneri(ALenum param, ALint *value); -AL_API void AL_APIENTRY alGetListener3i(ALenum param, ALint *value1, ALint *value2, ALint *value3); -AL_API void AL_APIENTRY alGetListeneriv(ALenum param, ALint *values); - - -/** Create Source objects. */ -AL_API void AL_APIENTRY alGenSources(ALsizei n, ALuint *sources); -/** Delete Source objects. */ -AL_API void AL_APIENTRY alDeleteSources(ALsizei n, const ALuint *sources); -/** Verify a handle is a valid Source. */ -AL_API ALboolean AL_APIENTRY alIsSource(ALuint source); - -/** Set Source parameters. */ -AL_API void AL_APIENTRY alSourcef(ALuint source, ALenum param, ALfloat value); -AL_API void AL_APIENTRY alSource3f(ALuint source, ALenum param, ALfloat value1, ALfloat value2, ALfloat value3); -AL_API void AL_APIENTRY alSourcefv(ALuint source, ALenum param, const ALfloat *values); -AL_API void AL_APIENTRY alSourcei(ALuint source, ALenum param, ALint value); -AL_API void AL_APIENTRY alSource3i(ALuint source, ALenum param, ALint value1, ALint value2, ALint value3); -AL_API void AL_APIENTRY alSourceiv(ALuint source, ALenum param, const ALint *values); - -/** Get Source parameters. */ -AL_API void AL_APIENTRY alGetSourcef(ALuint source, ALenum param, ALfloat *value); -AL_API void AL_APIENTRY alGetSource3f(ALuint source, ALenum param, ALfloat *value1, ALfloat *value2, ALfloat *value3); -AL_API void AL_APIENTRY alGetSourcefv(ALuint source, ALenum param, ALfloat *values); -AL_API void AL_APIENTRY alGetSourcei(ALuint source, ALenum param, ALint *value); -AL_API void AL_APIENTRY alGetSource3i(ALuint source, ALenum param, ALint *value1, ALint *value2, ALint *value3); -AL_API void AL_APIENTRY alGetSourceiv(ALuint source, ALenum param, ALint *values); - - -/** Play, replay, or resume (if paused) a list of Sources */ -AL_API void AL_APIENTRY alSourcePlayv(ALsizei n, const ALuint *sources); -/** Stop a list of Sources */ -AL_API void AL_APIENTRY alSourceStopv(ALsizei n, const ALuint *sources); -/** Rewind a list of Sources */ -AL_API void AL_APIENTRY alSourceRewindv(ALsizei n, const ALuint *sources); -/** Pause a list of Sources */ -AL_API void AL_APIENTRY alSourcePausev(ALsizei n, const ALuint *sources); - -/** Play, replay, or resume a Source */ -AL_API void AL_APIENTRY alSourcePlay(ALuint source); -/** Stop a Source */ -AL_API void AL_APIENTRY alSourceStop(ALuint source); -/** Rewind a Source (set playback postiton to beginning) */ -AL_API void AL_APIENTRY alSourceRewind(ALuint source); -/** Pause a Source */ -AL_API void AL_APIENTRY alSourcePause(ALuint source); - -/** Queue buffers onto a source */ -AL_API void AL_APIENTRY alSourceQueueBuffers(ALuint source, ALsizei nb, const ALuint *buffers); -/** Unqueue processed buffers from a source */ -AL_API void AL_APIENTRY alSourceUnqueueBuffers(ALuint source, ALsizei nb, ALuint *buffers); - - -/** Create Buffer objects */ -AL_API void AL_APIENTRY alGenBuffers(ALsizei n, ALuint *buffers); -/** Delete Buffer objects */ -AL_API void AL_APIENTRY alDeleteBuffers(ALsizei n, const ALuint *buffers); -/** Verify a handle is a valid Buffer */ -AL_API ALboolean AL_APIENTRY alIsBuffer(ALuint buffer); - -/** Specifies the data to be copied into a buffer */ -AL_API void AL_APIENTRY alBufferData(ALuint buffer, ALenum format, const ALvoid *data, ALsizei size, ALsizei freq); - -/** Set Buffer parameters, */ -AL_API void AL_APIENTRY alBufferf(ALuint buffer, ALenum param, ALfloat value); -AL_API void AL_APIENTRY alBuffer3f(ALuint buffer, ALenum param, ALfloat value1, ALfloat value2, ALfloat value3); -AL_API void AL_APIENTRY alBufferfv(ALuint buffer, ALenum param, const ALfloat *values); -AL_API void AL_APIENTRY alBufferi(ALuint buffer, ALenum param, ALint value); -AL_API void AL_APIENTRY alBuffer3i(ALuint buffer, ALenum param, ALint value1, ALint value2, ALint value3); -AL_API void AL_APIENTRY alBufferiv(ALuint buffer, ALenum param, const ALint *values); - -/** Get Buffer parameters. */ -AL_API void AL_APIENTRY alGetBufferf(ALuint buffer, ALenum param, ALfloat *value); -AL_API void AL_APIENTRY alGetBuffer3f(ALuint buffer, ALenum param, ALfloat *value1, ALfloat *value2, ALfloat *value3); -AL_API void AL_APIENTRY alGetBufferfv(ALuint buffer, ALenum param, ALfloat *values); -AL_API void AL_APIENTRY alGetBufferi(ALuint buffer, ALenum param, ALint *value); -AL_API void AL_APIENTRY alGetBuffer3i(ALuint buffer, ALenum param, ALint *value1, ALint *value2, ALint *value3); -AL_API void AL_APIENTRY alGetBufferiv(ALuint buffer, ALenum param, ALint *values); - -/** Pointer-to-function type, useful for dynamically getting AL entry points. */ -typedef void (AL_APIENTRY *LPALENABLE)(ALenum capability); -typedef void (AL_APIENTRY *LPALDISABLE)(ALenum capability); -typedef ALboolean (AL_APIENTRY *LPALISENABLED)(ALenum capability); -typedef const ALchar* (AL_APIENTRY *LPALGETSTRING)(ALenum param); -typedef void (AL_APIENTRY *LPALGETBOOLEANV)(ALenum param, ALboolean *values); -typedef void (AL_APIENTRY *LPALGETINTEGERV)(ALenum param, ALint *values); -typedef void (AL_APIENTRY *LPALGETFLOATV)(ALenum param, ALfloat *values); -typedef void (AL_APIENTRY *LPALGETDOUBLEV)(ALenum param, ALdouble *values); -typedef ALboolean (AL_APIENTRY *LPALGETBOOLEAN)(ALenum param); -typedef ALint (AL_APIENTRY *LPALGETINTEGER)(ALenum param); -typedef ALfloat (AL_APIENTRY *LPALGETFLOAT)(ALenum param); -typedef ALdouble (AL_APIENTRY *LPALGETDOUBLE)(ALenum param); -typedef ALenum (AL_APIENTRY *LPALGETERROR)(void); -typedef ALboolean (AL_APIENTRY *LPALISEXTENSIONPRESENT)(const ALchar *extname); -typedef void* (AL_APIENTRY *LPALGETPROCADDRESS)(const ALchar *fname); -typedef ALenum (AL_APIENTRY *LPALGETENUMVALUE)(const ALchar *ename); -typedef void (AL_APIENTRY *LPALLISTENERF)(ALenum param, ALfloat value); -typedef void (AL_APIENTRY *LPALLISTENER3F)(ALenum param, ALfloat value1, ALfloat value2, ALfloat value3); -typedef void (AL_APIENTRY *LPALLISTENERFV)(ALenum param, const ALfloat *values); -typedef void (AL_APIENTRY *LPALLISTENERI)(ALenum param, ALint value); -typedef void (AL_APIENTRY *LPALLISTENER3I)(ALenum param, ALint value1, ALint value2, ALint value3); -typedef void (AL_APIENTRY *LPALLISTENERIV)(ALenum param, const ALint *values); -typedef void (AL_APIENTRY *LPALGETLISTENERF)(ALenum param, ALfloat *value); -typedef void (AL_APIENTRY *LPALGETLISTENER3F)(ALenum param, ALfloat *value1, ALfloat *value2, ALfloat *value3); -typedef void (AL_APIENTRY *LPALGETLISTENERFV)(ALenum param, ALfloat *values); -typedef void (AL_APIENTRY *LPALGETLISTENERI)(ALenum param, ALint *value); -typedef void (AL_APIENTRY *LPALGETLISTENER3I)(ALenum param, ALint *value1, ALint *value2, ALint *value3); -typedef void (AL_APIENTRY *LPALGETLISTENERIV)(ALenum param, ALint *values); -typedef void (AL_APIENTRY *LPALGENSOURCES)(ALsizei n, ALuint *sources); -typedef void (AL_APIENTRY *LPALDELETESOURCES)(ALsizei n, const ALuint *sources); -typedef ALboolean (AL_APIENTRY *LPALISSOURCE)(ALuint source); -typedef void (AL_APIENTRY *LPALSOURCEF)(ALuint source, ALenum param, ALfloat value); -typedef void (AL_APIENTRY *LPALSOURCE3F)(ALuint source, ALenum param, ALfloat value1, ALfloat value2, ALfloat value3); -typedef void (AL_APIENTRY *LPALSOURCEFV)(ALuint source, ALenum param, const ALfloat *values); -typedef void (AL_APIENTRY *LPALSOURCEI)(ALuint source, ALenum param, ALint value); -typedef void (AL_APIENTRY *LPALSOURCE3I)(ALuint source, ALenum param, ALint value1, ALint value2, ALint value3); -typedef void (AL_APIENTRY *LPALSOURCEIV)(ALuint source, ALenum param, const ALint *values); -typedef void (AL_APIENTRY *LPALGETSOURCEF)(ALuint source, ALenum param, ALfloat *value); -typedef void (AL_APIENTRY *LPALGETSOURCE3F)(ALuint source, ALenum param, ALfloat *value1, ALfloat *value2, ALfloat *value3); -typedef void (AL_APIENTRY *LPALGETSOURCEFV)(ALuint source, ALenum param, ALfloat *values); -typedef void (AL_APIENTRY *LPALGETSOURCEI)(ALuint source, ALenum param, ALint *value); -typedef void (AL_APIENTRY *LPALGETSOURCE3I)(ALuint source, ALenum param, ALint *value1, ALint *value2, ALint *value3); -typedef void (AL_APIENTRY *LPALGETSOURCEIV)(ALuint source, ALenum param, ALint *values); -typedef void (AL_APIENTRY *LPALSOURCEPLAYV)(ALsizei n, const ALuint *sources); -typedef void (AL_APIENTRY *LPALSOURCESTOPV)(ALsizei n, const ALuint *sources); -typedef void (AL_APIENTRY *LPALSOURCEREWINDV)(ALsizei n, const ALuint *sources); -typedef void (AL_APIENTRY *LPALSOURCEPAUSEV)(ALsizei n, const ALuint *sources); -typedef void (AL_APIENTRY *LPALSOURCEPLAY)(ALuint source); -typedef void (AL_APIENTRY *LPALSOURCESTOP)(ALuint source); -typedef void (AL_APIENTRY *LPALSOURCEREWIND)(ALuint source); -typedef void (AL_APIENTRY *LPALSOURCEPAUSE)(ALuint source); -typedef void (AL_APIENTRY *LPALSOURCEQUEUEBUFFERS)(ALuint source, ALsizei nb, const ALuint *buffers); -typedef void (AL_APIENTRY *LPALSOURCEUNQUEUEBUFFERS)(ALuint source, ALsizei nb, ALuint *buffers); -typedef void (AL_APIENTRY *LPALGENBUFFERS)(ALsizei n, ALuint *buffers); -typedef void (AL_APIENTRY *LPALDELETEBUFFERS)(ALsizei n, const ALuint *buffers); -typedef ALboolean (AL_APIENTRY *LPALISBUFFER)(ALuint buffer); -typedef void (AL_APIENTRY *LPALBUFFERDATA)(ALuint buffer, ALenum format, const ALvoid *data, ALsizei size, ALsizei freq); -typedef void (AL_APIENTRY *LPALBUFFERF)(ALuint buffer, ALenum param, ALfloat value); -typedef void (AL_APIENTRY *LPALBUFFER3F)(ALuint buffer, ALenum param, ALfloat value1, ALfloat value2, ALfloat value3); -typedef void (AL_APIENTRY *LPALBUFFERFV)(ALuint buffer, ALenum param, const ALfloat *values); -typedef void (AL_APIENTRY *LPALBUFFERI)(ALuint buffer, ALenum param, ALint value); -typedef void (AL_APIENTRY *LPALBUFFER3I)(ALuint buffer, ALenum param, ALint value1, ALint value2, ALint value3); -typedef void (AL_APIENTRY *LPALBUFFERIV)(ALuint buffer, ALenum param, const ALint *values); -typedef void (AL_APIENTRY *LPALGETBUFFERF)(ALuint buffer, ALenum param, ALfloat *value); -typedef void (AL_APIENTRY *LPALGETBUFFER3F)(ALuint buffer, ALenum param, ALfloat *value1, ALfloat *value2, ALfloat *value3); -typedef void (AL_APIENTRY *LPALGETBUFFERFV)(ALuint buffer, ALenum param, ALfloat *values); -typedef void (AL_APIENTRY *LPALGETBUFFERI)(ALuint buffer, ALenum param, ALint *value); -typedef void (AL_APIENTRY *LPALGETBUFFER3I)(ALuint buffer, ALenum param, ALint *value1, ALint *value2, ALint *value3); -typedef void (AL_APIENTRY *LPALGETBUFFERIV)(ALuint buffer, ALenum param, ALint *values); -typedef void (AL_APIENTRY *LPALDOPPLERFACTOR)(ALfloat value); -typedef void (AL_APIENTRY *LPALDOPPLERVELOCITY)(ALfloat value); -typedef void (AL_APIENTRY *LPALSPEEDOFSOUND)(ALfloat value); -typedef void (AL_APIENTRY *LPALDISTANCEMODEL)(ALenum distanceModel); - -#if defined(__cplusplus) -} /* extern "C" */ -#endif - -#endif /* AL_AL_H */ diff --git a/src/include/AL/alc.h b/src/include/AL/alc.h deleted file mode 100644 index 294e8b33c..000000000 --- a/src/include/AL/alc.h +++ /dev/null @@ -1,237 +0,0 @@ -#ifndef AL_ALC_H -#define AL_ALC_H - -#if defined(__cplusplus) -extern "C" { -#endif - -#ifndef ALC_API - #if defined(AL_LIBTYPE_STATIC) - #define ALC_API - #elif defined(_WIN32) - #define ALC_API __declspec(dllimport) - #else - #define ALC_API extern - #endif -#endif - -#if defined(_WIN32) - #define ALC_APIENTRY __cdecl -#else - #define ALC_APIENTRY -#endif - - -/** Deprecated macro. */ -#define ALCAPI ALC_API -#define ALCAPIENTRY ALC_APIENTRY -#define ALC_INVALID 0 - -/** Supported ALC version? */ -#define ALC_VERSION_0_1 1 - -/** Opaque device handle */ -typedef struct ALCdevice_struct ALCdevice; -/** Opaque context handle */ -typedef struct ALCcontext_struct ALCcontext; - -/** 8-bit boolean */ -typedef char ALCboolean; - -/** character */ -typedef char ALCchar; - -/** signed 8-bit 2's complement integer */ -typedef signed char ALCbyte; - -/** unsigned 8-bit integer */ -typedef unsigned char ALCubyte; - -/** signed 16-bit 2's complement integer */ -typedef short ALCshort; - -/** unsigned 16-bit integer */ -typedef unsigned short ALCushort; - -/** signed 32-bit 2's complement integer */ -typedef int ALCint; - -/** unsigned 32-bit integer */ -typedef unsigned int ALCuint; - -/** non-negative 32-bit binary integer size */ -typedef int ALCsizei; - -/** enumerated 32-bit value */ -typedef int ALCenum; - -/** 32-bit IEEE754 floating-point */ -typedef float ALCfloat; - -/** 64-bit IEEE754 floating-point */ -typedef double ALCdouble; - -/** void type (for opaque pointers only) */ -typedef void ALCvoid; - - -/* Enumerant values begin at column 50. No tabs. */ - -/** Boolean False. */ -#define ALC_FALSE 0 - -/** Boolean True. */ -#define ALC_TRUE 1 - -/** Context attribute: Hz. */ -#define ALC_FREQUENCY 0x1007 - -/** Context attribute: Hz. */ -#define ALC_REFRESH 0x1008 - -/** Context attribute: AL_TRUE or AL_FALSE. */ -#define ALC_SYNC 0x1009 - -/** Context attribute: requested Mono (3D) Sources. */ -#define ALC_MONO_SOURCES 0x1010 - -/** Context attribute: requested Stereo Sources. */ -#define ALC_STEREO_SOURCES 0x1011 - -/** No error. */ -#define ALC_NO_ERROR 0 - -/** Invalid device handle. */ -#define ALC_INVALID_DEVICE 0xA001 - -/** Invalid context handle. */ -#define ALC_INVALID_CONTEXT 0xA002 - -/** Invalid enum parameter passed to an ALC call. */ -#define ALC_INVALID_ENUM 0xA003 - -/** Invalid value parameter passed to an ALC call. */ -#define ALC_INVALID_VALUE 0xA004 - -/** Out of memory. */ -#define ALC_OUT_OF_MEMORY 0xA005 - - -/** Runtime ALC version. */ -#define ALC_MAJOR_VERSION 0x1000 -#define ALC_MINOR_VERSION 0x1001 - -/** Context attribute list properties. */ -#define ALC_ATTRIBUTES_SIZE 0x1002 -#define ALC_ALL_ATTRIBUTES 0x1003 - -/** String for the default device specifier. */ -#define ALC_DEFAULT_DEVICE_SPECIFIER 0x1004 -/** - * String for the given device's specifier. - * - * If device handle is NULL, it is instead a null-char separated list of - * strings of known device specifiers (list ends with an empty string). - */ -#define ALC_DEVICE_SPECIFIER 0x1005 -/** String for space-separated list of ALC extensions. */ -#define ALC_EXTENSIONS 0x1006 - - -/** Capture extension */ -#define ALC_EXT_CAPTURE 1 -/** - * String for the given capture device's specifier. - * - * If device handle is NULL, it is instead a null-char separated list of - * strings of known capture device specifiers (list ends with an empty string). - */ -#define ALC_CAPTURE_DEVICE_SPECIFIER 0x310 -/** String for the default capture device specifier. */ -#define ALC_CAPTURE_DEFAULT_DEVICE_SPECIFIER 0x311 -/** Number of sample frames available for capture. */ -#define ALC_CAPTURE_SAMPLES 0x312 - - -/** Enumerate All extension */ -#define ALC_ENUMERATE_ALL_EXT 1 -/** String for the default extended device specifier. */ -#define ALC_DEFAULT_ALL_DEVICES_SPECIFIER 0x1012 -/** - * String for the given extended device's specifier. - * - * If device handle is NULL, it is instead a null-char separated list of - * strings of known extended device specifiers (list ends with an empty string). - */ -#define ALC_ALL_DEVICES_SPECIFIER 0x1013 - - -/** Context management. */ -ALC_API ALCcontext* ALC_APIENTRY alcCreateContext(ALCdevice *device, const ALCint* attrlist); -ALC_API ALCboolean ALC_APIENTRY alcMakeContextCurrent(ALCcontext *context); -ALC_API void ALC_APIENTRY alcProcessContext(ALCcontext *context); -ALC_API void ALC_APIENTRY alcSuspendContext(ALCcontext *context); -ALC_API void ALC_APIENTRY alcDestroyContext(ALCcontext *context); -ALC_API ALCcontext* ALC_APIENTRY alcGetCurrentContext(void); -ALC_API ALCdevice* ALC_APIENTRY alcGetContextsDevice(ALCcontext *context); - -/** Device management. */ -ALC_API ALCdevice* ALC_APIENTRY alcOpenDevice(const ALCchar *devicename); -ALC_API ALCboolean ALC_APIENTRY alcCloseDevice(ALCdevice *device); - - -/** - * Error support. - * - * Obtain the most recent Device error. - */ -ALC_API ALCenum ALC_APIENTRY alcGetError(ALCdevice *device); - -/** - * Extension support. - * - * Query for the presence of an extension, and obtain any appropriate - * function pointers and enum values. - */ -ALC_API ALCboolean ALC_APIENTRY alcIsExtensionPresent(ALCdevice *device, const ALCchar *extname); -ALC_API void* ALC_APIENTRY alcGetProcAddress(ALCdevice *device, const ALCchar *funcname); -ALC_API ALCenum ALC_APIENTRY alcGetEnumValue(ALCdevice *device, const ALCchar *enumname); - -/** Query function. */ -ALC_API const ALCchar* ALC_APIENTRY alcGetString(ALCdevice *device, ALCenum param); -ALC_API void ALC_APIENTRY alcGetIntegerv(ALCdevice *device, ALCenum param, ALCsizei size, ALCint *values); - -/** Capture function. */ -ALC_API ALCdevice* ALC_APIENTRY alcCaptureOpenDevice(const ALCchar *devicename, ALCuint frequency, ALCenum format, ALCsizei buffersize); -ALC_API ALCboolean ALC_APIENTRY alcCaptureCloseDevice(ALCdevice *device); -ALC_API void ALC_APIENTRY alcCaptureStart(ALCdevice *device); -ALC_API void ALC_APIENTRY alcCaptureStop(ALCdevice *device); -ALC_API void ALC_APIENTRY alcCaptureSamples(ALCdevice *device, ALCvoid *buffer, ALCsizei samples); - -/** Pointer-to-function type, useful for dynamically getting ALC entry points. */ -typedef ALCcontext* (ALC_APIENTRY *LPALCCREATECONTEXT)(ALCdevice *device, const ALCint *attrlist); -typedef ALCboolean (ALC_APIENTRY *LPALCMAKECONTEXTCURRENT)(ALCcontext *context); -typedef void (ALC_APIENTRY *LPALCPROCESSCONTEXT)(ALCcontext *context); -typedef void (ALC_APIENTRY *LPALCSUSPENDCONTEXT)(ALCcontext *context); -typedef void (ALC_APIENTRY *LPALCDESTROYCONTEXT)(ALCcontext *context); -typedef ALCcontext* (ALC_APIENTRY *LPALCGETCURRENTCONTEXT)(void); -typedef ALCdevice* (ALC_APIENTRY *LPALCGETCONTEXTSDEVICE)(ALCcontext *context); -typedef ALCdevice* (ALC_APIENTRY *LPALCOPENDEVICE)(const ALCchar *devicename); -typedef ALCboolean (ALC_APIENTRY *LPALCCLOSEDEVICE)(ALCdevice *device); -typedef ALCenum (ALC_APIENTRY *LPALCGETERROR)(ALCdevice *device); -typedef ALCboolean (ALC_APIENTRY *LPALCISEXTENSIONPRESENT)(ALCdevice *device, const ALCchar *extname); -typedef void* (ALC_APIENTRY *LPALCGETPROCADDRESS)(ALCdevice *device, const ALCchar *funcname); -typedef ALCenum (ALC_APIENTRY *LPALCGETENUMVALUE)(ALCdevice *device, const ALCchar *enumname); -typedef const ALCchar* (ALC_APIENTRY *LPALCGETSTRING)(ALCdevice *device, ALCenum param); -typedef void (ALC_APIENTRY *LPALCGETINTEGERV)(ALCdevice *device, ALCenum param, ALCsizei size, ALCint *values); -typedef ALCdevice* (ALC_APIENTRY *LPALCCAPTUREOPENDEVICE)(const ALCchar *devicename, ALCuint frequency, ALCenum format, ALCsizei buffersize); -typedef ALCboolean (ALC_APIENTRY *LPALCCAPTURECLOSEDEVICE)(ALCdevice *device); -typedef void (ALC_APIENTRY *LPALCCAPTURESTART)(ALCdevice *device); -typedef void (ALC_APIENTRY *LPALCCAPTURESTOP)(ALCdevice *device); -typedef void (ALC_APIENTRY *LPALCCAPTURESAMPLES)(ALCdevice *device, ALCvoid *buffer, ALCsizei samples); - -#if defined(__cplusplus) -} -#endif - -#endif /* AL_ALC_H */ diff --git a/src/include/AL/alext.h b/src/include/AL/alext.h deleted file mode 100644 index cd7f2750d..000000000 --- a/src/include/AL/alext.h +++ /dev/null @@ -1,516 +0,0 @@ -/** - * OpenAL cross platform audio library - * Copyright (C) 2008 by authors. - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Library General Public - * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Library General Public License for more details. - * - * You should have received a copy of the GNU Library General Public - * License along with this library; if not, write to the - * Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. - * Or go to http://www.gnu.org/copyleft/lgpl.html - */ - -#ifndef AL_ALEXT_H -#define AL_ALEXT_H - -#include -/* Define int64_t and uint64_t types */ -#if defined(__STDC_VERSION__) && __STDC_VERSION__ >= 199901L -#include -#elif defined(_WIN32) && defined(__GNUC__) -#include -#elif defined(_WIN32) -typedef __int64 int64_t; -typedef unsigned __int64 uint64_t; -#else -/* Fallback if nothing above works */ -#include -#endif - -#include "alc.h" -#include "al.h" - -#ifdef __cplusplus -extern "C" { -#endif - -#ifndef AL_LOKI_IMA_ADPCM_format -#define AL_LOKI_IMA_ADPCM_format 1 -#define AL_FORMAT_IMA_ADPCM_MONO16_EXT 0x10000 -#define AL_FORMAT_IMA_ADPCM_STEREO16_EXT 0x10001 -#endif - -#ifndef AL_LOKI_WAVE_format -#define AL_LOKI_WAVE_format 1 -#define AL_FORMAT_WAVE_EXT 0x10002 -#endif - -#ifndef AL_EXT_vorbis -#define AL_EXT_vorbis 1 -#define AL_FORMAT_VORBIS_EXT 0x10003 -#endif - -#ifndef AL_LOKI_quadriphonic -#define AL_LOKI_quadriphonic 1 -#define AL_FORMAT_QUAD8_LOKI 0x10004 -#define AL_FORMAT_QUAD16_LOKI 0x10005 -#endif - -#ifndef AL_EXT_float32 -#define AL_EXT_float32 1 -#define AL_FORMAT_MONO_FLOAT32 0x10010 -#define AL_FORMAT_STEREO_FLOAT32 0x10011 -#endif - -#ifndef AL_EXT_double -#define AL_EXT_double 1 -#define AL_FORMAT_MONO_DOUBLE_EXT 0x10012 -#define AL_FORMAT_STEREO_DOUBLE_EXT 0x10013 -#endif - -#ifndef AL_EXT_MULAW -#define AL_EXT_MULAW 1 -#define AL_FORMAT_MONO_MULAW_EXT 0x10014 -#define AL_FORMAT_STEREO_MULAW_EXT 0x10015 -#endif - -#ifndef AL_EXT_ALAW -#define AL_EXT_ALAW 1 -#define AL_FORMAT_MONO_ALAW_EXT 0x10016 -#define AL_FORMAT_STEREO_ALAW_EXT 0x10017 -#endif - -#ifndef ALC_LOKI_audio_channel -#define ALC_LOKI_audio_channel 1 -#define ALC_CHAN_MAIN_LOKI 0x500001 -#define ALC_CHAN_PCM_LOKI 0x500002 -#define ALC_CHAN_CD_LOKI 0x500003 -#endif - -#ifndef AL_EXT_MCFORMATS -#define AL_EXT_MCFORMATS 1 -/* Provides support for surround sound buffer formats with 8, 16, and 32-bit - * samples. - * - * QUAD8: Unsigned 8-bit, Quadraphonic (Front Left, Front Right, Rear Left, - * Rear Right). - * QUAD16: Signed 16-bit, Quadraphonic. - * QUAD32: 32-bit float, Quadraphonic. - * REAR8: Unsigned 8-bit, Rear Stereo (Rear Left, Rear Right). - * REAR16: Signed 16-bit, Rear Stereo. - * REAR32: 32-bit float, Rear Stereo. - * 51CHN8: Unsigned 8-bit, 5.1 Surround (Front Left, Front Right, Front Center, - * LFE, Side Left, Side Right). Note that some audio systems may label - * 5.1's Side channels as Rear or Surround; they are equivalent for the - * purposes of this extension. - * 51CHN16: Signed 16-bit, 5.1 Surround. - * 51CHN32: 32-bit float, 5.1 Surround. - * 61CHN8: Unsigned 8-bit, 6.1 Surround (Front Left, Front Right, Front Center, - * LFE, Rear Center, Side Left, Side Right). - * 61CHN16: Signed 16-bit, 6.1 Surround. - * 61CHN32: 32-bit float, 6.1 Surround. - * 71CHN8: Unsigned 8-bit, 7.1 Surround (Front Left, Front Right, Front Center, - * LFE, Rear Left, Rear Right, Side Left, Side Right). - * 71CHN16: Signed 16-bit, 7.1 Surround. - * 71CHN32: 32-bit float, 7.1 Surround. - */ -#define AL_FORMAT_QUAD8 0x1204 -#define AL_FORMAT_QUAD16 0x1205 -#define AL_FORMAT_QUAD32 0x1206 -#define AL_FORMAT_REAR8 0x1207 -#define AL_FORMAT_REAR16 0x1208 -#define AL_FORMAT_REAR32 0x1209 -#define AL_FORMAT_51CHN8 0x120A -#define AL_FORMAT_51CHN16 0x120B -#define AL_FORMAT_51CHN32 0x120C -#define AL_FORMAT_61CHN8 0x120D -#define AL_FORMAT_61CHN16 0x120E -#define AL_FORMAT_61CHN32 0x120F -#define AL_FORMAT_71CHN8 0x1210 -#define AL_FORMAT_71CHN16 0x1211 -#define AL_FORMAT_71CHN32 0x1212 -#endif - -#ifndef AL_EXT_MULAW_MCFORMATS -#define AL_EXT_MULAW_MCFORMATS 1 -#define AL_FORMAT_MONO_MULAW 0x10014 -#define AL_FORMAT_STEREO_MULAW 0x10015 -#define AL_FORMAT_QUAD_MULAW 0x10021 -#define AL_FORMAT_REAR_MULAW 0x10022 -#define AL_FORMAT_51CHN_MULAW 0x10023 -#define AL_FORMAT_61CHN_MULAW 0x10024 -#define AL_FORMAT_71CHN_MULAW 0x10025 -#endif - -#ifndef AL_EXT_IMA4 -#define AL_EXT_IMA4 1 -#define AL_FORMAT_MONO_IMA4 0x1300 -#define AL_FORMAT_STEREO_IMA4 0x1301 -#endif - -#ifndef AL_EXT_STATIC_BUFFER -#define AL_EXT_STATIC_BUFFER 1 -typedef ALvoid (AL_APIENTRY*PFNALBUFFERDATASTATICPROC)(const ALint,ALenum,ALvoid*,ALsizei,ALsizei); -#ifdef AL_ALEXT_PROTOTYPES -AL_API ALvoid AL_APIENTRY alBufferDataStatic(const ALint buffer, ALenum format, ALvoid *data, ALsizei len, ALsizei freq); -#endif -#endif - -#ifndef ALC_EXT_EFX -#define ALC_EXT_EFX 1 -#include "efx.h" -#endif - -#ifndef ALC_EXT_disconnect -#define ALC_EXT_disconnect 1 -#define ALC_CONNECTED 0x313 -#endif - -#ifndef ALC_EXT_thread_local_context -#define ALC_EXT_thread_local_context 1 -typedef ALCboolean (ALC_APIENTRY*PFNALCSETTHREADCONTEXTPROC)(ALCcontext *context); -typedef ALCcontext* (ALC_APIENTRY*PFNALCGETTHREADCONTEXTPROC)(void); -#ifdef AL_ALEXT_PROTOTYPES -ALC_API ALCboolean ALC_APIENTRY alcSetThreadContext(ALCcontext *context); -ALC_API ALCcontext* ALC_APIENTRY alcGetThreadContext(void); -#endif -#endif - -#ifndef AL_EXT_source_distance_model -#define AL_EXT_source_distance_model 1 -#define AL_SOURCE_DISTANCE_MODEL 0x200 -#endif - -#ifndef AL_SOFT_buffer_sub_data -#define AL_SOFT_buffer_sub_data 1 -#define AL_BYTE_RW_OFFSETS_SOFT 0x1031 -#define AL_SAMPLE_RW_OFFSETS_SOFT 0x1032 -typedef ALvoid (AL_APIENTRY*PFNALBUFFERSUBDATASOFTPROC)(ALuint,ALenum,const ALvoid*,ALsizei,ALsizei); -#ifdef AL_ALEXT_PROTOTYPES -AL_API ALvoid AL_APIENTRY alBufferSubDataSOFT(ALuint buffer,ALenum format,const ALvoid *data,ALsizei offset,ALsizei length); -#endif -#endif - -#ifndef AL_SOFT_loop_points -#define AL_SOFT_loop_points 1 -#define AL_LOOP_POINTS_SOFT 0x2015 -#endif - -#ifndef AL_EXT_FOLDBACK -#define AL_EXT_FOLDBACK 1 -#define AL_EXT_FOLDBACK_NAME "AL_EXT_FOLDBACK" -#define AL_FOLDBACK_EVENT_BLOCK 0x4112 -#define AL_FOLDBACK_EVENT_START 0x4111 -#define AL_FOLDBACK_EVENT_STOP 0x4113 -#define AL_FOLDBACK_MODE_MONO 0x4101 -#define AL_FOLDBACK_MODE_STEREO 0x4102 -typedef void (AL_APIENTRY*LPALFOLDBACKCALLBACK)(ALenum,ALsizei); -typedef void (AL_APIENTRY*LPALREQUESTFOLDBACKSTART)(ALenum,ALsizei,ALsizei,ALfloat*,LPALFOLDBACKCALLBACK); -typedef void (AL_APIENTRY*LPALREQUESTFOLDBACKSTOP)(void); -#ifdef AL_ALEXT_PROTOTYPES -AL_API void AL_APIENTRY alRequestFoldbackStart(ALenum mode,ALsizei count,ALsizei length,ALfloat *mem,LPALFOLDBACKCALLBACK callback); -AL_API void AL_APIENTRY alRequestFoldbackStop(void); -#endif -#endif - -#ifndef ALC_EXT_DEDICATED -#define ALC_EXT_DEDICATED 1 -#define AL_DEDICATED_GAIN 0x0001 -#define AL_EFFECT_DEDICATED_DIALOGUE 0x9001 -#define AL_EFFECT_DEDICATED_LOW_FREQUENCY_EFFECT 0x9000 -#endif - -#ifndef AL_SOFT_buffer_samples -#define AL_SOFT_buffer_samples 1 -/* Channel configurations */ -#define AL_MONO_SOFT 0x1500 -#define AL_STEREO_SOFT 0x1501 -#define AL_REAR_SOFT 0x1502 -#define AL_QUAD_SOFT 0x1503 -#define AL_5POINT1_SOFT 0x1504 -#define AL_6POINT1_SOFT 0x1505 -#define AL_7POINT1_SOFT 0x1506 - -/* Sample types */ -#define AL_BYTE_SOFT 0x1400 -#define AL_UNSIGNED_BYTE_SOFT 0x1401 -#define AL_SHORT_SOFT 0x1402 -#define AL_UNSIGNED_SHORT_SOFT 0x1403 -#define AL_INT_SOFT 0x1404 -#define AL_UNSIGNED_INT_SOFT 0x1405 -#define AL_FLOAT_SOFT 0x1406 -#define AL_DOUBLE_SOFT 0x1407 -#define AL_BYTE3_SOFT 0x1408 -#define AL_UNSIGNED_BYTE3_SOFT 0x1409 - -/* Storage formats */ -#define AL_MONO8_SOFT 0x1100 -#define AL_MONO16_SOFT 0x1101 -#define AL_MONO32F_SOFT 0x10010 -#define AL_STEREO8_SOFT 0x1102 -#define AL_STEREO16_SOFT 0x1103 -#define AL_STEREO32F_SOFT 0x10011 -#define AL_QUAD8_SOFT 0x1204 -#define AL_QUAD16_SOFT 0x1205 -#define AL_QUAD32F_SOFT 0x1206 -#define AL_REAR8_SOFT 0x1207 -#define AL_REAR16_SOFT 0x1208 -#define AL_REAR32F_SOFT 0x1209 -#define AL_5POINT1_8_SOFT 0x120A -#define AL_5POINT1_16_SOFT 0x120B -#define AL_5POINT1_32F_SOFT 0x120C -#define AL_6POINT1_8_SOFT 0x120D -#define AL_6POINT1_16_SOFT 0x120E -#define AL_6POINT1_32F_SOFT 0x120F -#define AL_7POINT1_8_SOFT 0x1210 -#define AL_7POINT1_16_SOFT 0x1211 -#define AL_7POINT1_32F_SOFT 0x1212 - -/* Buffer attributes */ -#define AL_INTERNAL_FORMAT_SOFT 0x2008 -#define AL_BYTE_LENGTH_SOFT 0x2009 -#define AL_SAMPLE_LENGTH_SOFT 0x200A -#define AL_SEC_LENGTH_SOFT 0x200B - -typedef void (AL_APIENTRY*LPALBUFFERSAMPLESSOFT)(ALuint,ALuint,ALenum,ALsizei,ALenum,ALenum,const ALvoid*); -typedef void (AL_APIENTRY*LPALBUFFERSUBSAMPLESSOFT)(ALuint,ALsizei,ALsizei,ALenum,ALenum,const ALvoid*); -typedef void (AL_APIENTRY*LPALGETBUFFERSAMPLESSOFT)(ALuint,ALsizei,ALsizei,ALenum,ALenum,ALvoid*); -typedef ALboolean (AL_APIENTRY*LPALISBUFFERFORMATSUPPORTEDSOFT)(ALenum); -#ifdef AL_ALEXT_PROTOTYPES -AL_API void AL_APIENTRY alBufferSamplesSOFT(ALuint buffer, ALuint samplerate, ALenum internalformat, ALsizei samples, ALenum channels, ALenum type, const ALvoid *data); -AL_API void AL_APIENTRY alBufferSubSamplesSOFT(ALuint buffer, ALsizei offset, ALsizei samples, ALenum channels, ALenum type, const ALvoid *data); -AL_API void AL_APIENTRY alGetBufferSamplesSOFT(ALuint buffer, ALsizei offset, ALsizei samples, ALenum channels, ALenum type, ALvoid *data); -AL_API ALboolean AL_APIENTRY alIsBufferFormatSupportedSOFT(ALenum format); -#endif -#endif - -#ifndef AL_SOFT_direct_channels -#define AL_SOFT_direct_channels 1 -#define AL_DIRECT_CHANNELS_SOFT 0x1033 -#endif - -#ifndef ALC_SOFT_loopback -#define ALC_SOFT_loopback 1 -#define ALC_FORMAT_CHANNELS_SOFT 0x1990 -#define ALC_FORMAT_TYPE_SOFT 0x1991 - -/* Sample types */ -#define ALC_BYTE_SOFT 0x1400 -#define ALC_UNSIGNED_BYTE_SOFT 0x1401 -#define ALC_SHORT_SOFT 0x1402 -#define ALC_UNSIGNED_SHORT_SOFT 0x1403 -#define ALC_INT_SOFT 0x1404 -#define ALC_UNSIGNED_INT_SOFT 0x1405 -#define ALC_FLOAT_SOFT 0x1406 - -/* Channel configurations */ -#define ALC_MONO_SOFT 0x1500 -#define ALC_STEREO_SOFT 0x1501 -#define ALC_QUAD_SOFT 0x1503 -#define ALC_5POINT1_SOFT 0x1504 -#define ALC_6POINT1_SOFT 0x1505 -#define ALC_7POINT1_SOFT 0x1506 - -typedef ALCdevice* (ALC_APIENTRY*LPALCLOOPBACKOPENDEVICESOFT)(const ALCchar*); -typedef ALCboolean (ALC_APIENTRY*LPALCISRENDERFORMATSUPPORTEDSOFT)(ALCdevice*,ALCsizei,ALCenum,ALCenum); -typedef void (ALC_APIENTRY*LPALCRENDERSAMPLESSOFT)(ALCdevice*,ALCvoid*,ALCsizei); -#ifdef AL_ALEXT_PROTOTYPES -ALC_API ALCdevice* ALC_APIENTRY alcLoopbackOpenDeviceSOFT(const ALCchar *deviceName); -ALC_API ALCboolean ALC_APIENTRY alcIsRenderFormatSupportedSOFT(ALCdevice *device, ALCsizei freq, ALCenum channels, ALCenum type); -ALC_API void ALC_APIENTRY alcRenderSamplesSOFT(ALCdevice *device, ALCvoid *buffer, ALCsizei samples); -#endif -#endif - -#ifndef AL_EXT_STEREO_ANGLES -#define AL_EXT_STEREO_ANGLES 1 -#define AL_STEREO_ANGLES 0x1030 -#endif - -#ifndef AL_EXT_SOURCE_RADIUS -#define AL_EXT_SOURCE_RADIUS 1 -#define AL_SOURCE_RADIUS 0x1031 -#endif - -#ifndef AL_SOFT_source_latency -#define AL_SOFT_source_latency 1 -#define AL_SAMPLE_OFFSET_LATENCY_SOFT 0x1200 -#define AL_SEC_OFFSET_LATENCY_SOFT 0x1201 -typedef int64_t ALint64SOFT; -typedef uint64_t ALuint64SOFT; -typedef void (AL_APIENTRY*LPALSOURCEDSOFT)(ALuint,ALenum,ALdouble); -typedef void (AL_APIENTRY*LPALSOURCE3DSOFT)(ALuint,ALenum,ALdouble,ALdouble,ALdouble); -typedef void (AL_APIENTRY*LPALSOURCEDVSOFT)(ALuint,ALenum,const ALdouble*); -typedef void (AL_APIENTRY*LPALGETSOURCEDSOFT)(ALuint,ALenum,ALdouble*); -typedef void (AL_APIENTRY*LPALGETSOURCE3DSOFT)(ALuint,ALenum,ALdouble*,ALdouble*,ALdouble*); -typedef void (AL_APIENTRY*LPALGETSOURCEDVSOFT)(ALuint,ALenum,ALdouble*); -typedef void (AL_APIENTRY*LPALSOURCEI64SOFT)(ALuint,ALenum,ALint64SOFT); -typedef void (AL_APIENTRY*LPALSOURCE3I64SOFT)(ALuint,ALenum,ALint64SOFT,ALint64SOFT,ALint64SOFT); -typedef void (AL_APIENTRY*LPALSOURCEI64VSOFT)(ALuint,ALenum,const ALint64SOFT*); -typedef void (AL_APIENTRY*LPALGETSOURCEI64SOFT)(ALuint,ALenum,ALint64SOFT*); -typedef void (AL_APIENTRY*LPALGETSOURCE3I64SOFT)(ALuint,ALenum,ALint64SOFT*,ALint64SOFT*,ALint64SOFT*); -typedef void (AL_APIENTRY*LPALGETSOURCEI64VSOFT)(ALuint,ALenum,ALint64SOFT*); -#ifdef AL_ALEXT_PROTOTYPES -AL_API void AL_APIENTRY alSourcedSOFT(ALuint source, ALenum param, ALdouble value); -AL_API void AL_APIENTRY alSource3dSOFT(ALuint source, ALenum param, ALdouble value1, ALdouble value2, ALdouble value3); -AL_API void AL_APIENTRY alSourcedvSOFT(ALuint source, ALenum param, const ALdouble *values); -AL_API void AL_APIENTRY alGetSourcedSOFT(ALuint source, ALenum param, ALdouble *value); -AL_API void AL_APIENTRY alGetSource3dSOFT(ALuint source, ALenum param, ALdouble *value1, ALdouble *value2, ALdouble *value3); -AL_API void AL_APIENTRY alGetSourcedvSOFT(ALuint source, ALenum param, ALdouble *values); -AL_API void AL_APIENTRY alSourcei64SOFT(ALuint source, ALenum param, ALint64SOFT value); -AL_API void AL_APIENTRY alSource3i64SOFT(ALuint source, ALenum param, ALint64SOFT value1, ALint64SOFT value2, ALint64SOFT value3); -AL_API void AL_APIENTRY alSourcei64vSOFT(ALuint source, ALenum param, const ALint64SOFT *values); -AL_API void AL_APIENTRY alGetSourcei64SOFT(ALuint source, ALenum param, ALint64SOFT *value); -AL_API void AL_APIENTRY alGetSource3i64SOFT(ALuint source, ALenum param, ALint64SOFT *value1, ALint64SOFT *value2, ALint64SOFT *value3); -AL_API void AL_APIENTRY alGetSourcei64vSOFT(ALuint source, ALenum param, ALint64SOFT *values); -#endif -#endif - -#ifndef ALC_EXT_DEFAULT_FILTER_ORDER -#define ALC_EXT_DEFAULT_FILTER_ORDER 1 -#define ALC_DEFAULT_FILTER_ORDER 0x1100 -#endif - -#ifndef AL_SOFT_deferred_updates -#define AL_SOFT_deferred_updates 1 -#define AL_DEFERRED_UPDATES_SOFT 0xC002 -typedef ALvoid (AL_APIENTRY*LPALDEFERUPDATESSOFT)(void); -typedef ALvoid (AL_APIENTRY*LPALPROCESSUPDATESSOFT)(void); -#ifdef AL_ALEXT_PROTOTYPES -AL_API ALvoid AL_APIENTRY alDeferUpdatesSOFT(void); -AL_API ALvoid AL_APIENTRY alProcessUpdatesSOFT(void); -#endif -#endif - -#ifndef AL_SOFT_block_alignment -#define AL_SOFT_block_alignment 1 -#define AL_UNPACK_BLOCK_ALIGNMENT_SOFT 0x200C -#define AL_PACK_BLOCK_ALIGNMENT_SOFT 0x200D -#endif - -#ifndef AL_SOFT_MSADPCM -#define AL_SOFT_MSADPCM 1 -#define AL_FORMAT_MONO_MSADPCM_SOFT 0x1302 -#define AL_FORMAT_STEREO_MSADPCM_SOFT 0x1303 -#endif - -#ifndef AL_SOFT_source_length -#define AL_SOFT_source_length 1 -/*#define AL_BYTE_LENGTH_SOFT 0x2009*/ -/*#define AL_SAMPLE_LENGTH_SOFT 0x200A*/ -/*#define AL_SEC_LENGTH_SOFT 0x200B*/ -#endif - -#ifndef ALC_SOFT_pause_device -#define ALC_SOFT_pause_device 1 -typedef void (ALC_APIENTRY*LPALCDEVICEPAUSESOFT)(ALCdevice *device); -typedef void (ALC_APIENTRY*LPALCDEVICERESUMESOFT)(ALCdevice *device); -#ifdef AL_ALEXT_PROTOTYPES -ALC_API void ALC_APIENTRY alcDevicePauseSOFT(ALCdevice *device); -ALC_API void ALC_APIENTRY alcDeviceResumeSOFT(ALCdevice *device); -#endif -#endif - -#ifndef AL_EXT_BFORMAT -#define AL_EXT_BFORMAT 1 -/* Provides support for B-Format ambisonic buffers (first-order, FuMa scaling - * and layout). - * - * BFORMAT2D_8: Unsigned 8-bit, 3-channel non-periphonic (WXY). - * BFORMAT2D_16: Signed 16-bit, 3-channel non-periphonic (WXY). - * BFORMAT2D_FLOAT32: 32-bit float, 3-channel non-periphonic (WXY). - * BFORMAT3D_8: Unsigned 8-bit, 4-channel periphonic (WXYZ). - * BFORMAT3D_16: Signed 16-bit, 4-channel periphonic (WXYZ). - * BFORMAT3D_FLOAT32: 32-bit float, 4-channel periphonic (WXYZ). - */ -#define AL_FORMAT_BFORMAT2D_8 0x20021 -#define AL_FORMAT_BFORMAT2D_16 0x20022 -#define AL_FORMAT_BFORMAT2D_FLOAT32 0x20023 -#define AL_FORMAT_BFORMAT3D_8 0x20031 -#define AL_FORMAT_BFORMAT3D_16 0x20032 -#define AL_FORMAT_BFORMAT3D_FLOAT32 0x20033 -#endif - -#ifndef AL_EXT_MULAW_BFORMAT -#define AL_EXT_MULAW_BFORMAT 1 -#define AL_FORMAT_BFORMAT2D_MULAW 0x10031 -#define AL_FORMAT_BFORMAT3D_MULAW 0x10032 -#endif - -#ifndef ALC_SOFT_HRTF -#define ALC_SOFT_HRTF 1 -#define ALC_HRTF_SOFT 0x1992 -#define ALC_DONT_CARE_SOFT 0x0002 -#define ALC_HRTF_STATUS_SOFT 0x1993 -#define ALC_HRTF_DISABLED_SOFT 0x0000 -#define ALC_HRTF_ENABLED_SOFT 0x0001 -#define ALC_HRTF_DENIED_SOFT 0x0002 -#define ALC_HRTF_REQUIRED_SOFT 0x0003 -#define ALC_HRTF_HEADPHONES_DETECTED_SOFT 0x0004 -#define ALC_HRTF_UNSUPPORTED_FORMAT_SOFT 0x0005 -#define ALC_NUM_HRTF_SPECIFIERS_SOFT 0x1994 -#define ALC_HRTF_SPECIFIER_SOFT 0x1995 -#define ALC_HRTF_ID_SOFT 0x1996 -typedef const ALCchar* (ALC_APIENTRY*LPALCGETSTRINGISOFT)(ALCdevice *device, ALCenum paramName, ALCsizei index); -typedef ALCboolean (ALC_APIENTRY*LPALCRESETDEVICESOFT)(ALCdevice *device, const ALCint *attribs); -#ifdef AL_ALEXT_PROTOTYPES -ALC_API const ALCchar* ALC_APIENTRY alcGetStringiSOFT(ALCdevice *device, ALCenum paramName, ALCsizei index); -ALC_API ALCboolean ALC_APIENTRY alcResetDeviceSOFT(ALCdevice *device, const ALCint *attribs); -#endif -#endif - -#ifndef AL_SOFT_gain_clamp_ex -#define AL_SOFT_gain_clamp_ex 1 -#define AL_GAIN_LIMIT_SOFT 0x200E -#endif - -#ifndef AL_SOFT_source_resampler -#define AL_SOFT_source_resampler -#define AL_NUM_RESAMPLERS_SOFT 0x1210 -#define AL_DEFAULT_RESAMPLER_SOFT 0x1211 -#define AL_SOURCE_RESAMPLER_SOFT 0x1212 -#define AL_RESAMPLER_NAME_SOFT 0x1213 -typedef const ALchar* (AL_APIENTRY*LPALGETSTRINGISOFT)(ALenum pname, ALsizei index); -#ifdef AL_ALEXT_PROTOTYPES -AL_API const ALchar* AL_APIENTRY alGetStringiSOFT(ALenum pname, ALsizei index); -#endif -#endif - -#ifndef AL_SOFT_source_spatialize -#define AL_SOFT_source_spatialize -#define AL_SOURCE_SPATIALIZE_SOFT 0x1214 -#define AL_AUTO_SOFT 0x0002 -#endif - -#ifndef ALC_SOFT_output_limiter -#define ALC_SOFT_output_limiter -#define ALC_OUTPUT_LIMITER_SOFT 0x199A -#endif - -#ifndef ALC_SOFT_device_clock -#define ALC_SOFT_device_clock 1 -typedef int64_t ALCint64SOFT; -typedef uint64_t ALCuint64SOFT; -#define ALC_DEVICE_CLOCK_SOFT 0x1600 -#define ALC_DEVICE_LATENCY_SOFT 0x1601 -#define ALC_DEVICE_CLOCK_LATENCY_SOFT 0x1602 -#define AL_SAMPLE_OFFSET_CLOCK_SOFT 0x1202 -#define AL_SEC_OFFSET_CLOCK_SOFT 0x1203 -typedef void (ALC_APIENTRY*LPALCGETINTEGER64VSOFT)(ALCdevice *device, ALCenum pname, ALsizei size, ALCint64SOFT *values); -#ifdef AL_ALEXT_PROTOTYPES -ALC_API void ALC_APIENTRY alcGetInteger64vSOFT(ALCdevice *device, ALCenum pname, ALsizei size, ALCint64SOFT *values); -#endif -#endif - -#ifdef __cplusplus -} -#endif - -#endif diff --git a/src/include/AL/efx-creative.h b/src/include/AL/efx-creative.h deleted file mode 100644 index 0a04c982e..000000000 --- a/src/include/AL/efx-creative.h +++ /dev/null @@ -1,3 +0,0 @@ -/* The tokens that would be defined here are already defined in efx.h. This - * empty file is here to provide compatibility with Windows-based projects - * that would include it. */ diff --git a/src/include/AL/efx-presets.h b/src/include/AL/efx-presets.h deleted file mode 100644 index 8539fd517..000000000 --- a/src/include/AL/efx-presets.h +++ /dev/null @@ -1,402 +0,0 @@ -/* Reverb presets for EFX */ - -#ifndef EFX_PRESETS_H -#define EFX_PRESETS_H - -#ifndef EFXEAXREVERBPROPERTIES_DEFINED -#define EFXEAXREVERBPROPERTIES_DEFINED -typedef struct { - float flDensity; - float flDiffusion; - float flGain; - float flGainHF; - float flGainLF; - float flDecayTime; - float flDecayHFRatio; - float flDecayLFRatio; - float flReflectionsGain; - float flReflectionsDelay; - float flReflectionsPan[3]; - float flLateReverbGain; - float flLateReverbDelay; - float flLateReverbPan[3]; - float flEchoTime; - float flEchoDepth; - float flModulationTime; - float flModulationDepth; - float flAirAbsorptionGainHF; - float flHFReference; - float flLFReference; - float flRoomRolloffFactor; - int iDecayHFLimit; -} EFXEAXREVERBPROPERTIES, *LPEFXEAXREVERBPROPERTIES; -#endif - -/* Default Presets */ - -#define EFX_REVERB_PRESET_GENERIC \ - { 1.0000f, 1.0000f, 0.3162f, 0.8913f, 1.0000f, 1.4900f, 0.8300f, 1.0000f, 0.0500f, 0.0070f, { 0.0000f, 0.0000f, 0.0000f }, 1.2589f, 0.0110f, { 0.0000f, 0.0000f, 0.0000f }, 0.2500f, 0.0000f, 0.2500f, 0.0000f, 0.9943f, 5000.0000f, 250.0000f, 0.0000f, 0x1 } - -#define EFX_REVERB_PRESET_PADDEDCELL \ - { 0.1715f, 1.0000f, 0.3162f, 0.0010f, 1.0000f, 0.1700f, 0.1000f, 1.0000f, 0.2500f, 0.0010f, { 0.0000f, 0.0000f, 0.0000f }, 1.2691f, 0.0020f, { 0.0000f, 0.0000f, 0.0000f }, 0.2500f, 0.0000f, 0.2500f, 0.0000f, 0.9943f, 5000.0000f, 250.0000f, 0.0000f, 0x1 } - -#define EFX_REVERB_PRESET_ROOM \ - { 0.4287f, 1.0000f, 0.3162f, 0.5929f, 1.0000f, 0.4000f, 0.8300f, 1.0000f, 0.1503f, 0.0020f, { 0.0000f, 0.0000f, 0.0000f }, 1.0629f, 0.0030f, { 0.0000f, 0.0000f, 0.0000f }, 0.2500f, 0.0000f, 0.2500f, 0.0000f, 0.9943f, 5000.0000f, 250.0000f, 0.0000f, 0x1 } - -#define EFX_REVERB_PRESET_BATHROOM \ - { 0.1715f, 1.0000f, 0.3162f, 0.2512f, 1.0000f, 1.4900f, 0.5400f, 1.0000f, 0.6531f, 0.0070f, { 0.0000f, 0.0000f, 0.0000f }, 3.2734f, 0.0110f, { 0.0000f, 0.0000f, 0.0000f }, 0.2500f, 0.0000f, 0.2500f, 0.0000f, 0.9943f, 5000.0000f, 250.0000f, 0.0000f, 0x1 } - -#define EFX_REVERB_PRESET_LIVINGROOM \ - { 0.9766f, 1.0000f, 0.3162f, 0.0010f, 1.0000f, 0.5000f, 0.1000f, 1.0000f, 0.2051f, 0.0030f, { 0.0000f, 0.0000f, 0.0000f }, 0.2805f, 0.0040f, { 0.0000f, 0.0000f, 0.0000f }, 0.2500f, 0.0000f, 0.2500f, 0.0000f, 0.9943f, 5000.0000f, 250.0000f, 0.0000f, 0x1 } - -#define EFX_REVERB_PRESET_STONEROOM \ - { 1.0000f, 1.0000f, 0.3162f, 0.7079f, 1.0000f, 2.3100f, 0.6400f, 1.0000f, 0.4411f, 0.0120f, { 0.0000f, 0.0000f, 0.0000f }, 1.1003f, 0.0170f, { 0.0000f, 0.0000f, 0.0000f }, 0.2500f, 0.0000f, 0.2500f, 0.0000f, 0.9943f, 5000.0000f, 250.0000f, 0.0000f, 0x1 } - -#define EFX_REVERB_PRESET_AUDITORIUM \ - { 1.0000f, 1.0000f, 0.3162f, 0.5781f, 1.0000f, 4.3200f, 0.5900f, 1.0000f, 0.4032f, 0.0200f, { 0.0000f, 0.0000f, 0.0000f }, 0.7170f, 0.0300f, { 0.0000f, 0.0000f, 0.0000f }, 0.2500f, 0.0000f, 0.2500f, 0.0000f, 0.9943f, 5000.0000f, 250.0000f, 0.0000f, 0x1 } - -#define EFX_REVERB_PRESET_CONCERTHALL \ - { 1.0000f, 1.0000f, 0.3162f, 0.5623f, 1.0000f, 3.9200f, 0.7000f, 1.0000f, 0.2427f, 0.0200f, { 0.0000f, 0.0000f, 0.0000f }, 0.9977f, 0.0290f, { 0.0000f, 0.0000f, 0.0000f }, 0.2500f, 0.0000f, 0.2500f, 0.0000f, 0.9943f, 5000.0000f, 250.0000f, 0.0000f, 0x1 } - -#define EFX_REVERB_PRESET_CAVE \ - { 1.0000f, 1.0000f, 0.3162f, 1.0000f, 1.0000f, 2.9100f, 1.3000f, 1.0000f, 0.5000f, 0.0150f, { 0.0000f, 0.0000f, 0.0000f }, 0.7063f, 0.0220f, { 0.0000f, 0.0000f, 0.0000f }, 0.2500f, 0.0000f, 0.2500f, 0.0000f, 0.9943f, 5000.0000f, 250.0000f, 0.0000f, 0x0 } - -#define EFX_REVERB_PRESET_ARENA \ - { 1.0000f, 1.0000f, 0.3162f, 0.4477f, 1.0000f, 7.2400f, 0.3300f, 1.0000f, 0.2612f, 0.0200f, { 0.0000f, 0.0000f, 0.0000f }, 1.0186f, 0.0300f, { 0.0000f, 0.0000f, 0.0000f }, 0.2500f, 0.0000f, 0.2500f, 0.0000f, 0.9943f, 5000.0000f, 250.0000f, 0.0000f, 0x1 } - -#define EFX_REVERB_PRESET_HANGAR \ - { 1.0000f, 1.0000f, 0.3162f, 0.3162f, 1.0000f, 10.0500f, 0.2300f, 1.0000f, 0.5000f, 0.0200f, { 0.0000f, 0.0000f, 0.0000f }, 1.2560f, 0.0300f, { 0.0000f, 0.0000f, 0.0000f }, 0.2500f, 0.0000f, 0.2500f, 0.0000f, 0.9943f, 5000.0000f, 250.0000f, 0.0000f, 0x1 } - -#define EFX_REVERB_PRESET_CARPETEDHALLWAY \ - { 0.4287f, 1.0000f, 0.3162f, 0.0100f, 1.0000f, 0.3000f, 0.1000f, 1.0000f, 0.1215f, 0.0020f, { 0.0000f, 0.0000f, 0.0000f }, 0.1531f, 0.0300f, { 0.0000f, 0.0000f, 0.0000f }, 0.2500f, 0.0000f, 0.2500f, 0.0000f, 0.9943f, 5000.0000f, 250.0000f, 0.0000f, 0x1 } - -#define EFX_REVERB_PRESET_HALLWAY \ - { 0.3645f, 1.0000f, 0.3162f, 0.7079f, 1.0000f, 1.4900f, 0.5900f, 1.0000f, 0.2458f, 0.0070f, { 0.0000f, 0.0000f, 0.0000f }, 1.6615f, 0.0110f, { 0.0000f, 0.0000f, 0.0000f }, 0.2500f, 0.0000f, 0.2500f, 0.0000f, 0.9943f, 5000.0000f, 250.0000f, 0.0000f, 0x1 } - -#define EFX_REVERB_PRESET_STONECORRIDOR \ - { 1.0000f, 1.0000f, 0.3162f, 0.7612f, 1.0000f, 2.7000f, 0.7900f, 1.0000f, 0.2472f, 0.0130f, { 0.0000f, 0.0000f, 0.0000f }, 1.5758f, 0.0200f, { 0.0000f, 0.0000f, 0.0000f }, 0.2500f, 0.0000f, 0.2500f, 0.0000f, 0.9943f, 5000.0000f, 250.0000f, 0.0000f, 0x1 } - -#define EFX_REVERB_PRESET_ALLEY \ - { 1.0000f, 0.3000f, 0.3162f, 0.7328f, 1.0000f, 1.4900f, 0.8600f, 1.0000f, 0.2500f, 0.0070f, { 0.0000f, 0.0000f, 0.0000f }, 0.9954f, 0.0110f, { 0.0000f, 0.0000f, 0.0000f }, 0.1250f, 0.9500f, 0.2500f, 0.0000f, 0.9943f, 5000.0000f, 250.0000f, 0.0000f, 0x1 } - -#define EFX_REVERB_PRESET_FOREST \ - { 1.0000f, 0.3000f, 0.3162f, 0.0224f, 1.0000f, 1.4900f, 0.5400f, 1.0000f, 0.0525f, 0.1620f, { 0.0000f, 0.0000f, 0.0000f }, 0.7682f, 0.0880f, { 0.0000f, 0.0000f, 0.0000f }, 0.1250f, 1.0000f, 0.2500f, 0.0000f, 0.9943f, 5000.0000f, 250.0000f, 0.0000f, 0x1 } - -#define EFX_REVERB_PRESET_CITY \ - { 1.0000f, 0.5000f, 0.3162f, 0.3981f, 1.0000f, 1.4900f, 0.6700f, 1.0000f, 0.0730f, 0.0070f, { 0.0000f, 0.0000f, 0.0000f }, 0.1427f, 0.0110f, { 0.0000f, 0.0000f, 0.0000f }, 0.2500f, 0.0000f, 0.2500f, 0.0000f, 0.9943f, 5000.0000f, 250.0000f, 0.0000f, 0x1 } - -#define EFX_REVERB_PRESET_MOUNTAINS \ - { 1.0000f, 0.2700f, 0.3162f, 0.0562f, 1.0000f, 1.4900f, 0.2100f, 1.0000f, 0.0407f, 0.3000f, { 0.0000f, 0.0000f, 0.0000f }, 0.1919f, 0.1000f, { 0.0000f, 0.0000f, 0.0000f }, 0.2500f, 1.0000f, 0.2500f, 0.0000f, 0.9943f, 5000.0000f, 250.0000f, 0.0000f, 0x0 } - -#define EFX_REVERB_PRESET_QUARRY \ - { 1.0000f, 1.0000f, 0.3162f, 0.3162f, 1.0000f, 1.4900f, 0.8300f, 1.0000f, 0.0000f, 0.0610f, { 0.0000f, 0.0000f, 0.0000f }, 1.7783f, 0.0250f, { 0.0000f, 0.0000f, 0.0000f }, 0.1250f, 0.7000f, 0.2500f, 0.0000f, 0.9943f, 5000.0000f, 250.0000f, 0.0000f, 0x1 } - -#define EFX_REVERB_PRESET_PLAIN \ - { 1.0000f, 0.2100f, 0.3162f, 0.1000f, 1.0000f, 1.4900f, 0.5000f, 1.0000f, 0.0585f, 0.1790f, { 0.0000f, 0.0000f, 0.0000f }, 0.1089f, 0.1000f, { 0.0000f, 0.0000f, 0.0000f }, 0.2500f, 1.0000f, 0.2500f, 0.0000f, 0.9943f, 5000.0000f, 250.0000f, 0.0000f, 0x1 } - -#define EFX_REVERB_PRESET_PARKINGLOT \ - { 1.0000f, 1.0000f, 0.3162f, 1.0000f, 1.0000f, 1.6500f, 1.5000f, 1.0000f, 0.2082f, 0.0080f, { 0.0000f, 0.0000f, 0.0000f }, 0.2652f, 0.0120f, { 0.0000f, 0.0000f, 0.0000f }, 0.2500f, 0.0000f, 0.2500f, 0.0000f, 0.9943f, 5000.0000f, 250.0000f, 0.0000f, 0x0 } - -#define EFX_REVERB_PRESET_SEWERPIPE \ - { 0.3071f, 0.8000f, 0.3162f, 0.3162f, 1.0000f, 2.8100f, 0.1400f, 1.0000f, 1.6387f, 0.0140f, { 0.0000f, 0.0000f, 0.0000f }, 3.2471f, 0.0210f, { 0.0000f, 0.0000f, 0.0000f }, 0.2500f, 0.0000f, 0.2500f, 0.0000f, 0.9943f, 5000.0000f, 250.0000f, 0.0000f, 0x1 } - -#define EFX_REVERB_PRESET_UNDERWATER \ - { 0.3645f, 1.0000f, 0.3162f, 0.0100f, 1.0000f, 1.4900f, 0.1000f, 1.0000f, 0.5963f, 0.0070f, { 0.0000f, 0.0000f, 0.0000f }, 7.0795f, 0.0110f, { 0.0000f, 0.0000f, 0.0000f }, 0.2500f, 0.0000f, 1.1800f, 0.3480f, 0.9943f, 5000.0000f, 250.0000f, 0.0000f, 0x1 } - -#define EFX_REVERB_PRESET_DRUGGED \ - { 0.4287f, 0.5000f, 0.3162f, 1.0000f, 1.0000f, 8.3900f, 1.3900f, 1.0000f, 0.8760f, 0.0020f, { 0.0000f, 0.0000f, 0.0000f }, 3.1081f, 0.0300f, { 0.0000f, 0.0000f, 0.0000f }, 0.2500f, 0.0000f, 0.2500f, 1.0000f, 0.9943f, 5000.0000f, 250.0000f, 0.0000f, 0x0 } - -#define EFX_REVERB_PRESET_DIZZY \ - { 0.3645f, 0.6000f, 0.3162f, 0.6310f, 1.0000f, 17.2300f, 0.5600f, 1.0000f, 0.1392f, 0.0200f, { 0.0000f, 0.0000f, 0.0000f }, 0.4937f, 0.0300f, { 0.0000f, 0.0000f, 0.0000f }, 0.2500f, 1.0000f, 0.8100f, 0.3100f, 0.9943f, 5000.0000f, 250.0000f, 0.0000f, 0x0 } - -#define EFX_REVERB_PRESET_PSYCHOTIC \ - { 0.0625f, 0.5000f, 0.3162f, 0.8404f, 1.0000f, 7.5600f, 0.9100f, 1.0000f, 0.4864f, 0.0200f, { 0.0000f, 0.0000f, 0.0000f }, 2.4378f, 0.0300f, { 0.0000f, 0.0000f, 0.0000f }, 0.2500f, 0.0000f, 4.0000f, 1.0000f, 0.9943f, 5000.0000f, 250.0000f, 0.0000f, 0x0 } - -/* Castle Presets */ - -#define EFX_REVERB_PRESET_CASTLE_SMALLROOM \ - { 1.0000f, 0.8900f, 0.3162f, 0.3981f, 0.1000f, 1.2200f, 0.8300f, 0.3100f, 0.8913f, 0.0220f, { 0.0000f, 0.0000f, 0.0000f }, 1.9953f, 0.0110f, { 0.0000f, 0.0000f, 0.0000f }, 0.1380f, 0.0800f, 0.2500f, 0.0000f, 0.9943f, 5168.6001f, 139.5000f, 0.0000f, 0x1 } - -#define EFX_REVERB_PRESET_CASTLE_SHORTPASSAGE \ - { 1.0000f, 0.8900f, 0.3162f, 0.3162f, 0.1000f, 2.3200f, 0.8300f, 0.3100f, 0.8913f, 0.0070f, { 0.0000f, 0.0000f, 0.0000f }, 1.2589f, 0.0230f, { 0.0000f, 0.0000f, 0.0000f }, 0.1380f, 0.0800f, 0.2500f, 0.0000f, 0.9943f, 5168.6001f, 139.5000f, 0.0000f, 0x1 } - -#define EFX_REVERB_PRESET_CASTLE_MEDIUMROOM \ - { 1.0000f, 0.9300f, 0.3162f, 0.2818f, 0.1000f, 2.0400f, 0.8300f, 0.4600f, 0.6310f, 0.0220f, { 0.0000f, 0.0000f, 0.0000f }, 1.5849f, 0.0110f, { 0.0000f, 0.0000f, 0.0000f }, 0.1550f, 0.0300f, 0.2500f, 0.0000f, 0.9943f, 5168.6001f, 139.5000f, 0.0000f, 0x1 } - -#define EFX_REVERB_PRESET_CASTLE_LARGEROOM \ - { 1.0000f, 0.8200f, 0.3162f, 0.2818f, 0.1259f, 2.5300f, 0.8300f, 0.5000f, 0.4467f, 0.0340f, { 0.0000f, 0.0000f, 0.0000f }, 1.2589f, 0.0160f, { 0.0000f, 0.0000f, 0.0000f }, 0.1850f, 0.0700f, 0.2500f, 0.0000f, 0.9943f, 5168.6001f, 139.5000f, 0.0000f, 0x1 } - -#define EFX_REVERB_PRESET_CASTLE_LONGPASSAGE \ - { 1.0000f, 0.8900f, 0.3162f, 0.3981f, 0.1000f, 3.4200f, 0.8300f, 0.3100f, 0.8913f, 0.0070f, { 0.0000f, 0.0000f, 0.0000f }, 1.4125f, 0.0230f, { 0.0000f, 0.0000f, 0.0000f }, 0.1380f, 0.0800f, 0.2500f, 0.0000f, 0.9943f, 5168.6001f, 139.5000f, 0.0000f, 0x1 } - -#define EFX_REVERB_PRESET_CASTLE_HALL \ - { 1.0000f, 0.8100f, 0.3162f, 0.2818f, 0.1778f, 3.1400f, 0.7900f, 0.6200f, 0.1778f, 0.0560f, { 0.0000f, 0.0000f, 0.0000f }, 1.1220f, 0.0240f, { 0.0000f, 0.0000f, 0.0000f }, 0.2500f, 0.0000f, 0.2500f, 0.0000f, 0.9943f, 5168.6001f, 139.5000f, 0.0000f, 0x1 } - -#define EFX_REVERB_PRESET_CASTLE_CUPBOARD \ - { 1.0000f, 0.8900f, 0.3162f, 0.2818f, 0.1000f, 0.6700f, 0.8700f, 0.3100f, 1.4125f, 0.0100f, { 0.0000f, 0.0000f, 0.0000f }, 3.5481f, 0.0070f, { 0.0000f, 0.0000f, 0.0000f }, 0.1380f, 0.0800f, 0.2500f, 0.0000f, 0.9943f, 5168.6001f, 139.5000f, 0.0000f, 0x1 } - -#define EFX_REVERB_PRESET_CASTLE_COURTYARD \ - { 1.0000f, 0.4200f, 0.3162f, 0.4467f, 0.1995f, 2.1300f, 0.6100f, 0.2300f, 0.2239f, 0.1600f, { 0.0000f, 0.0000f, 0.0000f }, 0.7079f, 0.0360f, { 0.0000f, 0.0000f, 0.0000f }, 0.2500f, 0.3700f, 0.2500f, 0.0000f, 0.9943f, 5000.0000f, 250.0000f, 0.0000f, 0x0 } - -#define EFX_REVERB_PRESET_CASTLE_ALCOVE \ - { 1.0000f, 0.8900f, 0.3162f, 0.5012f, 0.1000f, 1.6400f, 0.8700f, 0.3100f, 1.0000f, 0.0070f, { 0.0000f, 0.0000f, 0.0000f }, 1.4125f, 0.0340f, { 0.0000f, 0.0000f, 0.0000f }, 0.1380f, 0.0800f, 0.2500f, 0.0000f, 0.9943f, 5168.6001f, 139.5000f, 0.0000f, 0x1 } - -/* Factory Presets */ - -#define EFX_REVERB_PRESET_FACTORY_SMALLROOM \ - { 0.3645f, 0.8200f, 0.3162f, 0.7943f, 0.5012f, 1.7200f, 0.6500f, 1.3100f, 0.7079f, 0.0100f, { 0.0000f, 0.0000f, 0.0000f }, 1.7783f, 0.0240f, { 0.0000f, 0.0000f, 0.0000f }, 0.1190f, 0.0700f, 0.2500f, 0.0000f, 0.9943f, 3762.6001f, 362.5000f, 0.0000f, 0x1 } - -#define EFX_REVERB_PRESET_FACTORY_SHORTPASSAGE \ - { 0.3645f, 0.6400f, 0.2512f, 0.7943f, 0.5012f, 2.5300f, 0.6500f, 1.3100f, 1.0000f, 0.0100f, { 0.0000f, 0.0000f, 0.0000f }, 1.2589f, 0.0380f, { 0.0000f, 0.0000f, 0.0000f }, 0.1350f, 0.2300f, 0.2500f, 0.0000f, 0.9943f, 3762.6001f, 362.5000f, 0.0000f, 0x1 } - -#define EFX_REVERB_PRESET_FACTORY_MEDIUMROOM \ - { 0.4287f, 0.8200f, 0.2512f, 0.7943f, 0.5012f, 2.7600f, 0.6500f, 1.3100f, 0.2818f, 0.0220f, { 0.0000f, 0.0000f, 0.0000f }, 1.4125f, 0.0230f, { 0.0000f, 0.0000f, 0.0000f }, 0.1740f, 0.0700f, 0.2500f, 0.0000f, 0.9943f, 3762.6001f, 362.5000f, 0.0000f, 0x1 } - -#define EFX_REVERB_PRESET_FACTORY_LARGEROOM \ - { 0.4287f, 0.7500f, 0.2512f, 0.7079f, 0.6310f, 4.2400f, 0.5100f, 1.3100f, 0.1778f, 0.0390f, { 0.0000f, 0.0000f, 0.0000f }, 1.1220f, 0.0230f, { 0.0000f, 0.0000f, 0.0000f }, 0.2310f, 0.0700f, 0.2500f, 0.0000f, 0.9943f, 3762.6001f, 362.5000f, 0.0000f, 0x1 } - -#define EFX_REVERB_PRESET_FACTORY_LONGPASSAGE \ - { 0.3645f, 0.6400f, 0.2512f, 0.7943f, 0.5012f, 4.0600f, 0.6500f, 1.3100f, 1.0000f, 0.0200f, { 0.0000f, 0.0000f, 0.0000f }, 1.2589f, 0.0370f, { 0.0000f, 0.0000f, 0.0000f }, 0.1350f, 0.2300f, 0.2500f, 0.0000f, 0.9943f, 3762.6001f, 362.5000f, 0.0000f, 0x1 } - -#define EFX_REVERB_PRESET_FACTORY_HALL \ - { 0.4287f, 0.7500f, 0.3162f, 0.7079f, 0.6310f, 7.4300f, 0.5100f, 1.3100f, 0.0631f, 0.0730f, { 0.0000f, 0.0000f, 0.0000f }, 0.8913f, 0.0270f, { 0.0000f, 0.0000f, 0.0000f }, 0.2500f, 0.0700f, 0.2500f, 0.0000f, 0.9943f, 3762.6001f, 362.5000f, 0.0000f, 0x1 } - -#define EFX_REVERB_PRESET_FACTORY_CUPBOARD \ - { 0.3071f, 0.6300f, 0.2512f, 0.7943f, 0.5012f, 0.4900f, 0.6500f, 1.3100f, 1.2589f, 0.0100f, { 0.0000f, 0.0000f, 0.0000f }, 1.9953f, 0.0320f, { 0.0000f, 0.0000f, 0.0000f }, 0.1070f, 0.0700f, 0.2500f, 0.0000f, 0.9943f, 3762.6001f, 362.5000f, 0.0000f, 0x1 } - -#define EFX_REVERB_PRESET_FACTORY_COURTYARD \ - { 0.3071f, 0.5700f, 0.3162f, 0.3162f, 0.6310f, 2.3200f, 0.2900f, 0.5600f, 0.2239f, 0.1400f, { 0.0000f, 0.0000f, 0.0000f }, 0.3981f, 0.0390f, { 0.0000f, 0.0000f, 0.0000f }, 0.2500f, 0.2900f, 0.2500f, 0.0000f, 0.9943f, 3762.6001f, 362.5000f, 0.0000f, 0x1 } - -#define EFX_REVERB_PRESET_FACTORY_ALCOVE \ - { 0.3645f, 0.5900f, 0.2512f, 0.7943f, 0.5012f, 3.1400f, 0.6500f, 1.3100f, 1.4125f, 0.0100f, { 0.0000f, 0.0000f, 0.0000f }, 1.0000f, 0.0380f, { 0.0000f, 0.0000f, 0.0000f }, 0.1140f, 0.1000f, 0.2500f, 0.0000f, 0.9943f, 3762.6001f, 362.5000f, 0.0000f, 0x1 } - -/* Ice Palace Presets */ - -#define EFX_REVERB_PRESET_ICEPALACE_SMALLROOM \ - { 1.0000f, 0.8400f, 0.3162f, 0.5623f, 0.2818f, 1.5100f, 1.5300f, 0.2700f, 0.8913f, 0.0100f, { 0.0000f, 0.0000f, 0.0000f }, 1.4125f, 0.0110f, { 0.0000f, 0.0000f, 0.0000f }, 0.1640f, 0.1400f, 0.2500f, 0.0000f, 0.9943f, 12428.5000f, 99.6000f, 0.0000f, 0x1 } - -#define EFX_REVERB_PRESET_ICEPALACE_SHORTPASSAGE \ - { 1.0000f, 0.7500f, 0.3162f, 0.5623f, 0.2818f, 1.7900f, 1.4600f, 0.2800f, 0.5012f, 0.0100f, { 0.0000f, 0.0000f, 0.0000f }, 1.1220f, 0.0190f, { 0.0000f, 0.0000f, 0.0000f }, 0.1770f, 0.0900f, 0.2500f, 0.0000f, 0.9943f, 12428.5000f, 99.6000f, 0.0000f, 0x1 } - -#define EFX_REVERB_PRESET_ICEPALACE_MEDIUMROOM \ - { 1.0000f, 0.8700f, 0.3162f, 0.5623f, 0.4467f, 2.2200f, 1.5300f, 0.3200f, 0.3981f, 0.0390f, { 0.0000f, 0.0000f, 0.0000f }, 1.1220f, 0.0270f, { 0.0000f, 0.0000f, 0.0000f }, 0.1860f, 0.1200f, 0.2500f, 0.0000f, 0.9943f, 12428.5000f, 99.6000f, 0.0000f, 0x1 } - -#define EFX_REVERB_PRESET_ICEPALACE_LARGEROOM \ - { 1.0000f, 0.8100f, 0.3162f, 0.5623f, 0.4467f, 3.1400f, 1.5300f, 0.3200f, 0.2512f, 0.0390f, { 0.0000f, 0.0000f, 0.0000f }, 1.0000f, 0.0270f, { 0.0000f, 0.0000f, 0.0000f }, 0.2140f, 0.1100f, 0.2500f, 0.0000f, 0.9943f, 12428.5000f, 99.6000f, 0.0000f, 0x1 } - -#define EFX_REVERB_PRESET_ICEPALACE_LONGPASSAGE \ - { 1.0000f, 0.7700f, 0.3162f, 0.5623f, 0.3981f, 3.0100f, 1.4600f, 0.2800f, 0.7943f, 0.0120f, { 0.0000f, 0.0000f, 0.0000f }, 1.2589f, 0.0250f, { 0.0000f, 0.0000f, 0.0000f }, 0.1860f, 0.0400f, 0.2500f, 0.0000f, 0.9943f, 12428.5000f, 99.6000f, 0.0000f, 0x1 } - -#define EFX_REVERB_PRESET_ICEPALACE_HALL \ - { 1.0000f, 0.7600f, 0.3162f, 0.4467f, 0.5623f, 5.4900f, 1.5300f, 0.3800f, 0.1122f, 0.0540f, { 0.0000f, 0.0000f, 0.0000f }, 0.6310f, 0.0520f, { 0.0000f, 0.0000f, 0.0000f }, 0.2260f, 0.1100f, 0.2500f, 0.0000f, 0.9943f, 12428.5000f, 99.6000f, 0.0000f, 0x1 } - -#define EFX_REVERB_PRESET_ICEPALACE_CUPBOARD \ - { 1.0000f, 0.8300f, 0.3162f, 0.5012f, 0.2239f, 0.7600f, 1.5300f, 0.2600f, 1.1220f, 0.0120f, { 0.0000f, 0.0000f, 0.0000f }, 1.9953f, 0.0160f, { 0.0000f, 0.0000f, 0.0000f }, 0.1430f, 0.0800f, 0.2500f, 0.0000f, 0.9943f, 12428.5000f, 99.6000f, 0.0000f, 0x1 } - -#define EFX_REVERB_PRESET_ICEPALACE_COURTYARD \ - { 1.0000f, 0.5900f, 0.3162f, 0.2818f, 0.3162f, 2.0400f, 1.2000f, 0.3800f, 0.3162f, 0.1730f, { 0.0000f, 0.0000f, 0.0000f }, 0.3162f, 0.0430f, { 0.0000f, 0.0000f, 0.0000f }, 0.2350f, 0.4800f, 0.2500f, 0.0000f, 0.9943f, 12428.5000f, 99.6000f, 0.0000f, 0x1 } - -#define EFX_REVERB_PRESET_ICEPALACE_ALCOVE \ - { 1.0000f, 0.8400f, 0.3162f, 0.5623f, 0.2818f, 2.7600f, 1.4600f, 0.2800f, 1.1220f, 0.0100f, { 0.0000f, 0.0000f, 0.0000f }, 0.8913f, 0.0300f, { 0.0000f, 0.0000f, 0.0000f }, 0.1610f, 0.0900f, 0.2500f, 0.0000f, 0.9943f, 12428.5000f, 99.6000f, 0.0000f, 0x1 } - -/* Space Station Presets */ - -#define EFX_REVERB_PRESET_SPACESTATION_SMALLROOM \ - { 0.2109f, 0.7000f, 0.3162f, 0.7079f, 0.8913f, 1.7200f, 0.8200f, 0.5500f, 0.7943f, 0.0070f, { 0.0000f, 0.0000f, 0.0000f }, 1.4125f, 0.0130f, { 0.0000f, 0.0000f, 0.0000f }, 0.1880f, 0.2600f, 0.2500f, 0.0000f, 0.9943f, 3316.1001f, 458.2000f, 0.0000f, 0x1 } - -#define EFX_REVERB_PRESET_SPACESTATION_SHORTPASSAGE \ - { 0.2109f, 0.8700f, 0.3162f, 0.6310f, 0.8913f, 3.5700f, 0.5000f, 0.5500f, 1.0000f, 0.0120f, { 0.0000f, 0.0000f, 0.0000f }, 1.1220f, 0.0160f, { 0.0000f, 0.0000f, 0.0000f }, 0.1720f, 0.2000f, 0.2500f, 0.0000f, 0.9943f, 3316.1001f, 458.2000f, 0.0000f, 0x1 } - -#define EFX_REVERB_PRESET_SPACESTATION_MEDIUMROOM \ - { 0.2109f, 0.7500f, 0.3162f, 0.6310f, 0.8913f, 3.0100f, 0.5000f, 0.5500f, 0.3981f, 0.0340f, { 0.0000f, 0.0000f, 0.0000f }, 1.1220f, 0.0350f, { 0.0000f, 0.0000f, 0.0000f }, 0.2090f, 0.3100f, 0.2500f, 0.0000f, 0.9943f, 3316.1001f, 458.2000f, 0.0000f, 0x1 } - -#define EFX_REVERB_PRESET_SPACESTATION_LARGEROOM \ - { 0.3645f, 0.8100f, 0.3162f, 0.6310f, 0.8913f, 3.8900f, 0.3800f, 0.6100f, 0.3162f, 0.0560f, { 0.0000f, 0.0000f, 0.0000f }, 0.8913f, 0.0350f, { 0.0000f, 0.0000f, 0.0000f }, 0.2330f, 0.2800f, 0.2500f, 0.0000f, 0.9943f, 3316.1001f, 458.2000f, 0.0000f, 0x1 } - -#define EFX_REVERB_PRESET_SPACESTATION_LONGPASSAGE \ - { 0.4287f, 0.8200f, 0.3162f, 0.6310f, 0.8913f, 4.6200f, 0.6200f, 0.5500f, 1.0000f, 0.0120f, { 0.0000f, 0.0000f, 0.0000f }, 1.2589f, 0.0310f, { 0.0000f, 0.0000f, 0.0000f }, 0.2500f, 0.2300f, 0.2500f, 0.0000f, 0.9943f, 3316.1001f, 458.2000f, 0.0000f, 0x1 } - -#define EFX_REVERB_PRESET_SPACESTATION_HALL \ - { 0.4287f, 0.8700f, 0.3162f, 0.6310f, 0.8913f, 7.1100f, 0.3800f, 0.6100f, 0.1778f, 0.1000f, { 0.0000f, 0.0000f, 0.0000f }, 0.6310f, 0.0470f, { 0.0000f, 0.0000f, 0.0000f }, 0.2500f, 0.2500f, 0.2500f, 0.0000f, 0.9943f, 3316.1001f, 458.2000f, 0.0000f, 0x1 } - -#define EFX_REVERB_PRESET_SPACESTATION_CUPBOARD \ - { 0.1715f, 0.5600f, 0.3162f, 0.7079f, 0.8913f, 0.7900f, 0.8100f, 0.5500f, 1.4125f, 0.0070f, { 0.0000f, 0.0000f, 0.0000f }, 1.7783f, 0.0180f, { 0.0000f, 0.0000f, 0.0000f }, 0.1810f, 0.3100f, 0.2500f, 0.0000f, 0.9943f, 3316.1001f, 458.2000f, 0.0000f, 0x1 } - -#define EFX_REVERB_PRESET_SPACESTATION_ALCOVE \ - { 0.2109f, 0.7800f, 0.3162f, 0.7079f, 0.8913f, 1.1600f, 0.8100f, 0.5500f, 1.4125f, 0.0070f, { 0.0000f, 0.0000f, 0.0000f }, 1.0000f, 0.0180f, { 0.0000f, 0.0000f, 0.0000f }, 0.1920f, 0.2100f, 0.2500f, 0.0000f, 0.9943f, 3316.1001f, 458.2000f, 0.0000f, 0x1 } - -/* Wooden Galleon Presets */ - -#define EFX_REVERB_PRESET_WOODEN_SMALLROOM \ - { 1.0000f, 1.0000f, 0.3162f, 0.1122f, 0.3162f, 0.7900f, 0.3200f, 0.8700f, 1.0000f, 0.0320f, { 0.0000f, 0.0000f, 0.0000f }, 0.8913f, 0.0290f, { 0.0000f, 0.0000f, 0.0000f }, 0.2500f, 0.0000f, 0.2500f, 0.0000f, 0.9943f, 4705.0000f, 99.6000f, 0.0000f, 0x1 } - -#define EFX_REVERB_PRESET_WOODEN_SHORTPASSAGE \ - { 1.0000f, 1.0000f, 0.3162f, 0.1259f, 0.3162f, 1.7500f, 0.5000f, 0.8700f, 0.8913f, 0.0120f, { 0.0000f, 0.0000f, 0.0000f }, 0.6310f, 0.0240f, { 0.0000f, 0.0000f, 0.0000f }, 0.2500f, 0.0000f, 0.2500f, 0.0000f, 0.9943f, 4705.0000f, 99.6000f, 0.0000f, 0x1 } - -#define EFX_REVERB_PRESET_WOODEN_MEDIUMROOM \ - { 1.0000f, 1.0000f, 0.3162f, 0.1000f, 0.2818f, 1.4700f, 0.4200f, 0.8200f, 0.8913f, 0.0490f, { 0.0000f, 0.0000f, 0.0000f }, 0.8913f, 0.0290f, { 0.0000f, 0.0000f, 0.0000f }, 0.2500f, 0.0000f, 0.2500f, 0.0000f, 0.9943f, 4705.0000f, 99.6000f, 0.0000f, 0x1 } - -#define EFX_REVERB_PRESET_WOODEN_LARGEROOM \ - { 1.0000f, 1.0000f, 0.3162f, 0.0891f, 0.2818f, 2.6500f, 0.3300f, 0.8200f, 0.8913f, 0.0660f, { 0.0000f, 0.0000f, 0.0000f }, 0.7943f, 0.0490f, { 0.0000f, 0.0000f, 0.0000f }, 0.2500f, 0.0000f, 0.2500f, 0.0000f, 0.9943f, 4705.0000f, 99.6000f, 0.0000f, 0x1 } - -#define EFX_REVERB_PRESET_WOODEN_LONGPASSAGE \ - { 1.0000f, 1.0000f, 0.3162f, 0.1000f, 0.3162f, 1.9900f, 0.4000f, 0.7900f, 1.0000f, 0.0200f, { 0.0000f, 0.0000f, 0.0000f }, 0.4467f, 0.0360f, { 0.0000f, 0.0000f, 0.0000f }, 0.2500f, 0.0000f, 0.2500f, 0.0000f, 0.9943f, 4705.0000f, 99.6000f, 0.0000f, 0x1 } - -#define EFX_REVERB_PRESET_WOODEN_HALL \ - { 1.0000f, 1.0000f, 0.3162f, 0.0794f, 0.2818f, 3.4500f, 0.3000f, 0.8200f, 0.8913f, 0.0880f, { 0.0000f, 0.0000f, 0.0000f }, 0.7943f, 0.0630f, { 0.0000f, 0.0000f, 0.0000f }, 0.2500f, 0.0000f, 0.2500f, 0.0000f, 0.9943f, 4705.0000f, 99.6000f, 0.0000f, 0x1 } - -#define EFX_REVERB_PRESET_WOODEN_CUPBOARD \ - { 1.0000f, 1.0000f, 0.3162f, 0.1413f, 0.3162f, 0.5600f, 0.4600f, 0.9100f, 1.1220f, 0.0120f, { 0.0000f, 0.0000f, 0.0000f }, 1.1220f, 0.0280f, { 0.0000f, 0.0000f, 0.0000f }, 0.2500f, 0.0000f, 0.2500f, 0.0000f, 0.9943f, 4705.0000f, 99.6000f, 0.0000f, 0x1 } - -#define EFX_REVERB_PRESET_WOODEN_COURTYARD \ - { 1.0000f, 0.6500f, 0.3162f, 0.0794f, 0.3162f, 1.7900f, 0.3500f, 0.7900f, 0.5623f, 0.1230f, { 0.0000f, 0.0000f, 0.0000f }, 0.1000f, 0.0320f, { 0.0000f, 0.0000f, 0.0000f }, 0.2500f, 0.0000f, 0.2500f, 0.0000f, 0.9943f, 4705.0000f, 99.6000f, 0.0000f, 0x1 } - -#define EFX_REVERB_PRESET_WOODEN_ALCOVE \ - { 1.0000f, 1.0000f, 0.3162f, 0.1259f, 0.3162f, 1.2200f, 0.6200f, 0.9100f, 1.1220f, 0.0120f, { 0.0000f, 0.0000f, 0.0000f }, 0.7079f, 0.0240f, { 0.0000f, 0.0000f, 0.0000f }, 0.2500f, 0.0000f, 0.2500f, 0.0000f, 0.9943f, 4705.0000f, 99.6000f, 0.0000f, 0x1 } - -/* Sports Presets */ - -#define EFX_REVERB_PRESET_SPORT_EMPTYSTADIUM \ - { 1.0000f, 1.0000f, 0.3162f, 0.4467f, 0.7943f, 6.2600f, 0.5100f, 1.1000f, 0.0631f, 0.1830f, { 0.0000f, 0.0000f, 0.0000f }, 0.3981f, 0.0380f, { 0.0000f, 0.0000f, 0.0000f }, 0.2500f, 0.0000f, 0.2500f, 0.0000f, 0.9943f, 5000.0000f, 250.0000f, 0.0000f, 0x1 } - -#define EFX_REVERB_PRESET_SPORT_SQUASHCOURT \ - { 1.0000f, 0.7500f, 0.3162f, 0.3162f, 0.7943f, 2.2200f, 0.9100f, 1.1600f, 0.4467f, 0.0070f, { 0.0000f, 0.0000f, 0.0000f }, 0.7943f, 0.0110f, { 0.0000f, 0.0000f, 0.0000f }, 0.1260f, 0.1900f, 0.2500f, 0.0000f, 0.9943f, 7176.8999f, 211.2000f, 0.0000f, 0x1 } - -#define EFX_REVERB_PRESET_SPORT_SMALLSWIMMINGPOOL \ - { 1.0000f, 0.7000f, 0.3162f, 0.7943f, 0.8913f, 2.7600f, 1.2500f, 1.1400f, 0.6310f, 0.0200f, { 0.0000f, 0.0000f, 0.0000f }, 0.7943f, 0.0300f, { 0.0000f, 0.0000f, 0.0000f }, 0.1790f, 0.1500f, 0.8950f, 0.1900f, 0.9943f, 5000.0000f, 250.0000f, 0.0000f, 0x0 } - -#define EFX_REVERB_PRESET_SPORT_LARGESWIMMINGPOOL \ - { 1.0000f, 0.8200f, 0.3162f, 0.7943f, 1.0000f, 5.4900f, 1.3100f, 1.1400f, 0.4467f, 0.0390f, { 0.0000f, 0.0000f, 0.0000f }, 0.5012f, 0.0490f, { 0.0000f, 0.0000f, 0.0000f }, 0.2220f, 0.5500f, 1.1590f, 0.2100f, 0.9943f, 5000.0000f, 250.0000f, 0.0000f, 0x0 } - -#define EFX_REVERB_PRESET_SPORT_GYMNASIUM \ - { 1.0000f, 0.8100f, 0.3162f, 0.4467f, 0.8913f, 3.1400f, 1.0600f, 1.3500f, 0.3981f, 0.0290f, { 0.0000f, 0.0000f, 0.0000f }, 0.5623f, 0.0450f, { 0.0000f, 0.0000f, 0.0000f }, 0.1460f, 0.1400f, 0.2500f, 0.0000f, 0.9943f, 7176.8999f, 211.2000f, 0.0000f, 0x1 } - -#define EFX_REVERB_PRESET_SPORT_FULLSTADIUM \ - { 1.0000f, 1.0000f, 0.3162f, 0.0708f, 0.7943f, 5.2500f, 0.1700f, 0.8000f, 0.1000f, 0.1880f, { 0.0000f, 0.0000f, 0.0000f }, 0.2818f, 0.0380f, { 0.0000f, 0.0000f, 0.0000f }, 0.2500f, 0.0000f, 0.2500f, 0.0000f, 0.9943f, 5000.0000f, 250.0000f, 0.0000f, 0x1 } - -#define EFX_REVERB_PRESET_SPORT_STADIUMTANNOY \ - { 1.0000f, 0.7800f, 0.3162f, 0.5623f, 0.5012f, 2.5300f, 0.8800f, 0.6800f, 0.2818f, 0.2300f, { 0.0000f, 0.0000f, 0.0000f }, 0.5012f, 0.0630f, { 0.0000f, 0.0000f, 0.0000f }, 0.2500f, 0.2000f, 0.2500f, 0.0000f, 0.9943f, 5000.0000f, 250.0000f, 0.0000f, 0x1 } - -/* Prefab Presets */ - -#define EFX_REVERB_PRESET_PREFAB_WORKSHOP \ - { 0.4287f, 1.0000f, 0.3162f, 0.1413f, 0.3981f, 0.7600f, 1.0000f, 1.0000f, 1.0000f, 0.0120f, { 0.0000f, 0.0000f, 0.0000f }, 1.1220f, 0.0120f, { 0.0000f, 0.0000f, 0.0000f }, 0.2500f, 0.0000f, 0.2500f, 0.0000f, 0.9943f, 5000.0000f, 250.0000f, 0.0000f, 0x0 } - -#define EFX_REVERB_PRESET_PREFAB_SCHOOLROOM \ - { 0.4022f, 0.6900f, 0.3162f, 0.6310f, 0.5012f, 0.9800f, 0.4500f, 0.1800f, 1.4125f, 0.0170f, { 0.0000f, 0.0000f, 0.0000f }, 1.4125f, 0.0150f, { 0.0000f, 0.0000f, 0.0000f }, 0.0950f, 0.1400f, 0.2500f, 0.0000f, 0.9943f, 7176.8999f, 211.2000f, 0.0000f, 0x1 } - -#define EFX_REVERB_PRESET_PREFAB_PRACTISEROOM \ - { 0.4022f, 0.8700f, 0.3162f, 0.3981f, 0.5012f, 1.1200f, 0.5600f, 0.1800f, 1.2589f, 0.0100f, { 0.0000f, 0.0000f, 0.0000f }, 1.4125f, 0.0110f, { 0.0000f, 0.0000f, 0.0000f }, 0.0950f, 0.1400f, 0.2500f, 0.0000f, 0.9943f, 7176.8999f, 211.2000f, 0.0000f, 0x1 } - -#define EFX_REVERB_PRESET_PREFAB_OUTHOUSE \ - { 1.0000f, 0.8200f, 0.3162f, 0.1122f, 0.1585f, 1.3800f, 0.3800f, 0.3500f, 0.8913f, 0.0240f, { 0.0000f, 0.0000f, -0.0000f }, 0.6310f, 0.0440f, { 0.0000f, 0.0000f, 0.0000f }, 0.1210f, 0.1700f, 0.2500f, 0.0000f, 0.9943f, 2854.3999f, 107.5000f, 0.0000f, 0x0 } - -#define EFX_REVERB_PRESET_PREFAB_CARAVAN \ - { 1.0000f, 1.0000f, 0.3162f, 0.0891f, 0.1259f, 0.4300f, 1.5000f, 1.0000f, 1.0000f, 0.0120f, { 0.0000f, 0.0000f, 0.0000f }, 1.9953f, 0.0120f, { 0.0000f, 0.0000f, 0.0000f }, 0.2500f, 0.0000f, 0.2500f, 0.0000f, 0.9943f, 5000.0000f, 250.0000f, 0.0000f, 0x0 } - -/* Dome and Pipe Presets */ - -#define EFX_REVERB_PRESET_DOME_TOMB \ - { 1.0000f, 0.7900f, 0.3162f, 0.3548f, 0.2239f, 4.1800f, 0.2100f, 0.1000f, 0.3868f, 0.0300f, { 0.0000f, 0.0000f, 0.0000f }, 1.6788f, 0.0220f, { 0.0000f, 0.0000f, 0.0000f }, 0.1770f, 0.1900f, 0.2500f, 0.0000f, 0.9943f, 2854.3999f, 20.0000f, 0.0000f, 0x0 } - -#define EFX_REVERB_PRESET_PIPE_SMALL \ - { 1.0000f, 1.0000f, 0.3162f, 0.3548f, 0.2239f, 5.0400f, 0.1000f, 0.1000f, 0.5012f, 0.0320f, { 0.0000f, 0.0000f, 0.0000f }, 2.5119f, 0.0150f, { 0.0000f, 0.0000f, 0.0000f }, 0.2500f, 0.0000f, 0.2500f, 0.0000f, 0.9943f, 2854.3999f, 20.0000f, 0.0000f, 0x1 } - -#define EFX_REVERB_PRESET_DOME_SAINTPAULS \ - { 1.0000f, 0.8700f, 0.3162f, 0.3548f, 0.2239f, 10.4800f, 0.1900f, 0.1000f, 0.1778f, 0.0900f, { 0.0000f, 0.0000f, 0.0000f }, 1.2589f, 0.0420f, { 0.0000f, 0.0000f, 0.0000f }, 0.2500f, 0.1200f, 0.2500f, 0.0000f, 0.9943f, 2854.3999f, 20.0000f, 0.0000f, 0x1 } - -#define EFX_REVERB_PRESET_PIPE_LONGTHIN \ - { 0.2560f, 0.9100f, 0.3162f, 0.4467f, 0.2818f, 9.2100f, 0.1800f, 0.1000f, 0.7079f, 0.0100f, { 0.0000f, 0.0000f, 0.0000f }, 0.7079f, 0.0220f, { 0.0000f, 0.0000f, 0.0000f }, 0.2500f, 0.0000f, 0.2500f, 0.0000f, 0.9943f, 2854.3999f, 20.0000f, 0.0000f, 0x0 } - -#define EFX_REVERB_PRESET_PIPE_LARGE \ - { 1.0000f, 1.0000f, 0.3162f, 0.3548f, 0.2239f, 8.4500f, 0.1000f, 0.1000f, 0.3981f, 0.0460f, { 0.0000f, 0.0000f, 0.0000f }, 1.5849f, 0.0320f, { 0.0000f, 0.0000f, 0.0000f }, 0.2500f, 0.0000f, 0.2500f, 0.0000f, 0.9943f, 2854.3999f, 20.0000f, 0.0000f, 0x1 } - -#define EFX_REVERB_PRESET_PIPE_RESONANT \ - { 0.1373f, 0.9100f, 0.3162f, 0.4467f, 0.2818f, 6.8100f, 0.1800f, 0.1000f, 0.7079f, 0.0100f, { 0.0000f, 0.0000f, 0.0000f }, 1.0000f, 0.0220f, { 0.0000f, 0.0000f, 0.0000f }, 0.2500f, 0.0000f, 0.2500f, 0.0000f, 0.9943f, 2854.3999f, 20.0000f, 0.0000f, 0x0 } - -/* Outdoors Presets */ - -#define EFX_REVERB_PRESET_OUTDOORS_BACKYARD \ - { 1.0000f, 0.4500f, 0.3162f, 0.2512f, 0.5012f, 1.1200f, 0.3400f, 0.4600f, 0.4467f, 0.0690f, { 0.0000f, 0.0000f, -0.0000f }, 0.7079f, 0.0230f, { 0.0000f, 0.0000f, 0.0000f }, 0.2180f, 0.3400f, 0.2500f, 0.0000f, 0.9943f, 4399.1001f, 242.9000f, 0.0000f, 0x0 } - -#define EFX_REVERB_PRESET_OUTDOORS_ROLLINGPLAINS \ - { 1.0000f, 0.0000f, 0.3162f, 0.0112f, 0.6310f, 2.1300f, 0.2100f, 0.4600f, 0.1778f, 0.3000f, { 0.0000f, 0.0000f, -0.0000f }, 0.4467f, 0.0190f, { 0.0000f, 0.0000f, 0.0000f }, 0.2500f, 1.0000f, 0.2500f, 0.0000f, 0.9943f, 4399.1001f, 242.9000f, 0.0000f, 0x0 } - -#define EFX_REVERB_PRESET_OUTDOORS_DEEPCANYON \ - { 1.0000f, 0.7400f, 0.3162f, 0.1778f, 0.6310f, 3.8900f, 0.2100f, 0.4600f, 0.3162f, 0.2230f, { 0.0000f, 0.0000f, -0.0000f }, 0.3548f, 0.0190f, { 0.0000f, 0.0000f, 0.0000f }, 0.2500f, 1.0000f, 0.2500f, 0.0000f, 0.9943f, 4399.1001f, 242.9000f, 0.0000f, 0x0 } - -#define EFX_REVERB_PRESET_OUTDOORS_CREEK \ - { 1.0000f, 0.3500f, 0.3162f, 0.1778f, 0.5012f, 2.1300f, 0.2100f, 0.4600f, 0.3981f, 0.1150f, { 0.0000f, 0.0000f, -0.0000f }, 0.1995f, 0.0310f, { 0.0000f, 0.0000f, 0.0000f }, 0.2180f, 0.3400f, 0.2500f, 0.0000f, 0.9943f, 4399.1001f, 242.9000f, 0.0000f, 0x0 } - -#define EFX_REVERB_PRESET_OUTDOORS_VALLEY \ - { 1.0000f, 0.2800f, 0.3162f, 0.0282f, 0.1585f, 2.8800f, 0.2600f, 0.3500f, 0.1413f, 0.2630f, { 0.0000f, 0.0000f, -0.0000f }, 0.3981f, 0.1000f, { 0.0000f, 0.0000f, 0.0000f }, 0.2500f, 0.3400f, 0.2500f, 0.0000f, 0.9943f, 2854.3999f, 107.5000f, 0.0000f, 0x0 } - -/* Mood Presets */ - -#define EFX_REVERB_PRESET_MOOD_HEAVEN \ - { 1.0000f, 0.9400f, 0.3162f, 0.7943f, 0.4467f, 5.0400f, 1.1200f, 0.5600f, 0.2427f, 0.0200f, { 0.0000f, 0.0000f, 0.0000f }, 1.2589f, 0.0290f, { 0.0000f, 0.0000f, 0.0000f }, 0.2500f, 0.0800f, 2.7420f, 0.0500f, 0.9977f, 5000.0000f, 250.0000f, 0.0000f, 0x1 } - -#define EFX_REVERB_PRESET_MOOD_HELL \ - { 1.0000f, 0.5700f, 0.3162f, 0.3548f, 0.4467f, 3.5700f, 0.4900f, 2.0000f, 0.0000f, 0.0200f, { 0.0000f, 0.0000f, 0.0000f }, 1.4125f, 0.0300f, { 0.0000f, 0.0000f, 0.0000f }, 0.1100f, 0.0400f, 2.1090f, 0.5200f, 0.9943f, 5000.0000f, 139.5000f, 0.0000f, 0x0 } - -#define EFX_REVERB_PRESET_MOOD_MEMORY \ - { 1.0000f, 0.8500f, 0.3162f, 0.6310f, 0.3548f, 4.0600f, 0.8200f, 0.5600f, 0.0398f, 0.0000f, { 0.0000f, 0.0000f, 0.0000f }, 1.1220f, 0.0000f, { 0.0000f, 0.0000f, 0.0000f }, 0.2500f, 0.0000f, 0.4740f, 0.4500f, 0.9886f, 5000.0000f, 250.0000f, 0.0000f, 0x0 } - -/* Driving Presets */ - -#define EFX_REVERB_PRESET_DRIVING_COMMENTATOR \ - { 1.0000f, 0.0000f, 0.3162f, 0.5623f, 0.5012f, 2.4200f, 0.8800f, 0.6800f, 0.1995f, 0.0930f, { 0.0000f, 0.0000f, 0.0000f }, 0.2512f, 0.0170f, { 0.0000f, 0.0000f, 0.0000f }, 0.2500f, 1.0000f, 0.2500f, 0.0000f, 0.9886f, 5000.0000f, 250.0000f, 0.0000f, 0x1 } - -#define EFX_REVERB_PRESET_DRIVING_PITGARAGE \ - { 0.4287f, 0.5900f, 0.3162f, 0.7079f, 0.5623f, 1.7200f, 0.9300f, 0.8700f, 0.5623f, 0.0000f, { 0.0000f, 0.0000f, 0.0000f }, 1.2589f, 0.0160f, { 0.0000f, 0.0000f, 0.0000f }, 0.2500f, 0.1100f, 0.2500f, 0.0000f, 0.9943f, 5000.0000f, 250.0000f, 0.0000f, 0x0 } - -#define EFX_REVERB_PRESET_DRIVING_INCAR_RACER \ - { 0.0832f, 0.8000f, 0.3162f, 1.0000f, 0.7943f, 0.1700f, 2.0000f, 0.4100f, 1.7783f, 0.0070f, { 0.0000f, 0.0000f, 0.0000f }, 0.7079f, 0.0150f, { 0.0000f, 0.0000f, 0.0000f }, 0.2500f, 0.0000f, 0.2500f, 0.0000f, 0.9943f, 10268.2002f, 251.0000f, 0.0000f, 0x1 } - -#define EFX_REVERB_PRESET_DRIVING_INCAR_SPORTS \ - { 0.0832f, 0.8000f, 0.3162f, 0.6310f, 1.0000f, 0.1700f, 0.7500f, 0.4100f, 1.0000f, 0.0100f, { 0.0000f, 0.0000f, 0.0000f }, 0.5623f, 0.0000f, { 0.0000f, 0.0000f, 0.0000f }, 0.2500f, 0.0000f, 0.2500f, 0.0000f, 0.9943f, 10268.2002f, 251.0000f, 0.0000f, 0x1 } - -#define EFX_REVERB_PRESET_DRIVING_INCAR_LUXURY \ - { 0.2560f, 1.0000f, 0.3162f, 0.1000f, 0.5012f, 0.1300f, 0.4100f, 0.4600f, 0.7943f, 0.0100f, { 0.0000f, 0.0000f, 0.0000f }, 1.5849f, 0.0100f, { 0.0000f, 0.0000f, 0.0000f }, 0.2500f, 0.0000f, 0.2500f, 0.0000f, 0.9943f, 10268.2002f, 251.0000f, 0.0000f, 0x1 } - -#define EFX_REVERB_PRESET_DRIVING_FULLGRANDSTAND \ - { 1.0000f, 1.0000f, 0.3162f, 0.2818f, 0.6310f, 3.0100f, 1.3700f, 1.2800f, 0.3548f, 0.0900f, { 0.0000f, 0.0000f, 0.0000f }, 0.1778f, 0.0490f, { 0.0000f, 0.0000f, 0.0000f }, 0.2500f, 0.0000f, 0.2500f, 0.0000f, 0.9943f, 10420.2002f, 250.0000f, 0.0000f, 0x0 } - -#define EFX_REVERB_PRESET_DRIVING_EMPTYGRANDSTAND \ - { 1.0000f, 1.0000f, 0.3162f, 1.0000f, 0.7943f, 4.6200f, 1.7500f, 1.4000f, 0.2082f, 0.0900f, { 0.0000f, 0.0000f, 0.0000f }, 0.2512f, 0.0490f, { 0.0000f, 0.0000f, 0.0000f }, 0.2500f, 0.0000f, 0.2500f, 0.0000f, 0.9943f, 10420.2002f, 250.0000f, 0.0000f, 0x0 } - -#define EFX_REVERB_PRESET_DRIVING_TUNNEL \ - { 1.0000f, 0.8100f, 0.3162f, 0.3981f, 0.8913f, 3.4200f, 0.9400f, 1.3100f, 0.7079f, 0.0510f, { 0.0000f, 0.0000f, 0.0000f }, 0.7079f, 0.0470f, { 0.0000f, 0.0000f, 0.0000f }, 0.2140f, 0.0500f, 0.2500f, 0.0000f, 0.9943f, 5000.0000f, 155.3000f, 0.0000f, 0x1 } - -/* City Presets */ - -#define EFX_REVERB_PRESET_CITY_STREETS \ - { 1.0000f, 0.7800f, 0.3162f, 0.7079f, 0.8913f, 1.7900f, 1.1200f, 0.9100f, 0.2818f, 0.0460f, { 0.0000f, 0.0000f, 0.0000f }, 0.1995f, 0.0280f, { 0.0000f, 0.0000f, 0.0000f }, 0.2500f, 0.2000f, 0.2500f, 0.0000f, 0.9943f, 5000.0000f, 250.0000f, 0.0000f, 0x1 } - -#define EFX_REVERB_PRESET_CITY_SUBWAY \ - { 1.0000f, 0.7400f, 0.3162f, 0.7079f, 0.8913f, 3.0100f, 1.2300f, 0.9100f, 0.7079f, 0.0460f, { 0.0000f, 0.0000f, 0.0000f }, 1.2589f, 0.0280f, { 0.0000f, 0.0000f, 0.0000f }, 0.1250f, 0.2100f, 0.2500f, 0.0000f, 0.9943f, 5000.0000f, 250.0000f, 0.0000f, 0x1 } - -#define EFX_REVERB_PRESET_CITY_MUSEUM \ - { 1.0000f, 0.8200f, 0.3162f, 0.1778f, 0.1778f, 3.2800f, 1.4000f, 0.5700f, 0.2512f, 0.0390f, { 0.0000f, 0.0000f, -0.0000f }, 0.8913f, 0.0340f, { 0.0000f, 0.0000f, 0.0000f }, 0.1300f, 0.1700f, 0.2500f, 0.0000f, 0.9943f, 2854.3999f, 107.5000f, 0.0000f, 0x0 } - -#define EFX_REVERB_PRESET_CITY_LIBRARY \ - { 1.0000f, 0.8200f, 0.3162f, 0.2818f, 0.0891f, 2.7600f, 0.8900f, 0.4100f, 0.3548f, 0.0290f, { 0.0000f, 0.0000f, -0.0000f }, 0.8913f, 0.0200f, { 0.0000f, 0.0000f, 0.0000f }, 0.1300f, 0.1700f, 0.2500f, 0.0000f, 0.9943f, 2854.3999f, 107.5000f, 0.0000f, 0x0 } - -#define EFX_REVERB_PRESET_CITY_UNDERPASS \ - { 1.0000f, 0.8200f, 0.3162f, 0.4467f, 0.8913f, 3.5700f, 1.1200f, 0.9100f, 0.3981f, 0.0590f, { 0.0000f, 0.0000f, 0.0000f }, 0.8913f, 0.0370f, { 0.0000f, 0.0000f, 0.0000f }, 0.2500f, 0.1400f, 0.2500f, 0.0000f, 0.9920f, 5000.0000f, 250.0000f, 0.0000f, 0x1 } - -#define EFX_REVERB_PRESET_CITY_ABANDONED \ - { 1.0000f, 0.6900f, 0.3162f, 0.7943f, 0.8913f, 3.2800f, 1.1700f, 0.9100f, 0.4467f, 0.0440f, { 0.0000f, 0.0000f, 0.0000f }, 0.2818f, 0.0240f, { 0.0000f, 0.0000f, 0.0000f }, 0.2500f, 0.2000f, 0.2500f, 0.0000f, 0.9966f, 5000.0000f, 250.0000f, 0.0000f, 0x1 } - -/* Misc. Presets */ - -#define EFX_REVERB_PRESET_DUSTYROOM \ - { 0.3645f, 0.5600f, 0.3162f, 0.7943f, 0.7079f, 1.7900f, 0.3800f, 0.2100f, 0.5012f, 0.0020f, { 0.0000f, 0.0000f, 0.0000f }, 1.2589f, 0.0060f, { 0.0000f, 0.0000f, 0.0000f }, 0.2020f, 0.0500f, 0.2500f, 0.0000f, 0.9886f, 13046.0000f, 163.3000f, 0.0000f, 0x1 } - -#define EFX_REVERB_PRESET_CHAPEL \ - { 1.0000f, 0.8400f, 0.3162f, 0.5623f, 1.0000f, 4.6200f, 0.6400f, 1.2300f, 0.4467f, 0.0320f, { 0.0000f, 0.0000f, 0.0000f }, 0.7943f, 0.0490f, { 0.0000f, 0.0000f, 0.0000f }, 0.2500f, 0.0000f, 0.2500f, 0.1100f, 0.9943f, 5000.0000f, 250.0000f, 0.0000f, 0x1 } - -#define EFX_REVERB_PRESET_SMALLWATERROOM \ - { 1.0000f, 0.7000f, 0.3162f, 0.4477f, 1.0000f, 1.5100f, 1.2500f, 1.1400f, 0.8913f, 0.0200f, { 0.0000f, 0.0000f, 0.0000f }, 1.4125f, 0.0300f, { 0.0000f, 0.0000f, 0.0000f }, 0.1790f, 0.1500f, 0.8950f, 0.1900f, 0.9920f, 5000.0000f, 250.0000f, 0.0000f, 0x0 } - -#endif /* EFX_PRESETS_H */ diff --git a/src/include/AL/efx.h b/src/include/AL/efx.h deleted file mode 100644 index 57766983f..000000000 --- a/src/include/AL/efx.h +++ /dev/null @@ -1,761 +0,0 @@ -#ifndef AL_EFX_H -#define AL_EFX_H - - -#include "alc.h" -#include "al.h" - -#ifdef __cplusplus -extern "C" { -#endif - -#define ALC_EXT_EFX_NAME "ALC_EXT_EFX" - -#define ALC_EFX_MAJOR_VERSION 0x20001 -#define ALC_EFX_MINOR_VERSION 0x20002 -#define ALC_MAX_AUXILIARY_SENDS 0x20003 - - -/* Listener properties. */ -#define AL_METERS_PER_UNIT 0x20004 - -/* Source properties. */ -#define AL_DIRECT_FILTER 0x20005 -#define AL_AUXILIARY_SEND_FILTER 0x20006 -#define AL_AIR_ABSORPTION_FACTOR 0x20007 -#define AL_ROOM_ROLLOFF_FACTOR 0x20008 -#define AL_CONE_OUTER_GAINHF 0x20009 -#define AL_DIRECT_FILTER_GAINHF_AUTO 0x2000A -#define AL_AUXILIARY_SEND_FILTER_GAIN_AUTO 0x2000B -#define AL_AUXILIARY_SEND_FILTER_GAINHF_AUTO 0x2000C - - -/* Effect properties. */ - -/* Reverb effect parameters */ -#define AL_REVERB_DENSITY 0x0001 -#define AL_REVERB_DIFFUSION 0x0002 -#define AL_REVERB_GAIN 0x0003 -#define AL_REVERB_GAINHF 0x0004 -#define AL_REVERB_DECAY_TIME 0x0005 -#define AL_REVERB_DECAY_HFRATIO 0x0006 -#define AL_REVERB_REFLECTIONS_GAIN 0x0007 -#define AL_REVERB_REFLECTIONS_DELAY 0x0008 -#define AL_REVERB_LATE_REVERB_GAIN 0x0009 -#define AL_REVERB_LATE_REVERB_DELAY 0x000A -#define AL_REVERB_AIR_ABSORPTION_GAINHF 0x000B -#define AL_REVERB_ROOM_ROLLOFF_FACTOR 0x000C -#define AL_REVERB_DECAY_HFLIMIT 0x000D - -/* EAX Reverb effect parameters */ -#define AL_EAXREVERB_DENSITY 0x0001 -#define AL_EAXREVERB_DIFFUSION 0x0002 -#define AL_EAXREVERB_GAIN 0x0003 -#define AL_EAXREVERB_GAINHF 0x0004 -#define AL_EAXREVERB_GAINLF 0x0005 -#define AL_EAXREVERB_DECAY_TIME 0x0006 -#define AL_EAXREVERB_DECAY_HFRATIO 0x0007 -#define AL_EAXREVERB_DECAY_LFRATIO 0x0008 -#define AL_EAXREVERB_REFLECTIONS_GAIN 0x0009 -#define AL_EAXREVERB_REFLECTIONS_DELAY 0x000A -#define AL_EAXREVERB_REFLECTIONS_PAN 0x000B -#define AL_EAXREVERB_LATE_REVERB_GAIN 0x000C -#define AL_EAXREVERB_LATE_REVERB_DELAY 0x000D -#define AL_EAXREVERB_LATE_REVERB_PAN 0x000E -#define AL_EAXREVERB_ECHO_TIME 0x000F -#define AL_EAXREVERB_ECHO_DEPTH 0x0010 -#define AL_EAXREVERB_MODULATION_TIME 0x0011 -#define AL_EAXREVERB_MODULATION_DEPTH 0x0012 -#define AL_EAXREVERB_AIR_ABSORPTION_GAINHF 0x0013 -#define AL_EAXREVERB_HFREFERENCE 0x0014 -#define AL_EAXREVERB_LFREFERENCE 0x0015 -#define AL_EAXREVERB_ROOM_ROLLOFF_FACTOR 0x0016 -#define AL_EAXREVERB_DECAY_HFLIMIT 0x0017 - -/* Chorus effect parameters */ -#define AL_CHORUS_WAVEFORM 0x0001 -#define AL_CHORUS_PHASE 0x0002 -#define AL_CHORUS_RATE 0x0003 -#define AL_CHORUS_DEPTH 0x0004 -#define AL_CHORUS_FEEDBACK 0x0005 -#define AL_CHORUS_DELAY 0x0006 - -/* Distortion effect parameters */ -#define AL_DISTORTION_EDGE 0x0001 -#define AL_DISTORTION_GAIN 0x0002 -#define AL_DISTORTION_LOWPASS_CUTOFF 0x0003 -#define AL_DISTORTION_EQCENTER 0x0004 -#define AL_DISTORTION_EQBANDWIDTH 0x0005 - -/* Echo effect parameters */ -#define AL_ECHO_DELAY 0x0001 -#define AL_ECHO_LRDELAY 0x0002 -#define AL_ECHO_DAMPING 0x0003 -#define AL_ECHO_FEEDBACK 0x0004 -#define AL_ECHO_SPREAD 0x0005 - -/* Flanger effect parameters */ -#define AL_FLANGER_WAVEFORM 0x0001 -#define AL_FLANGER_PHASE 0x0002 -#define AL_FLANGER_RATE 0x0003 -#define AL_FLANGER_DEPTH 0x0004 -#define AL_FLANGER_FEEDBACK 0x0005 -#define AL_FLANGER_DELAY 0x0006 - -/* Frequency shifter effect parameters */ -#define AL_FREQUENCY_SHIFTER_FREQUENCY 0x0001 -#define AL_FREQUENCY_SHIFTER_LEFT_DIRECTION 0x0002 -#define AL_FREQUENCY_SHIFTER_RIGHT_DIRECTION 0x0003 - -/* Vocal morpher effect parameters */ -#define AL_VOCAL_MORPHER_PHONEMEA 0x0001 -#define AL_VOCAL_MORPHER_PHONEMEA_COARSE_TUNING 0x0002 -#define AL_VOCAL_MORPHER_PHONEMEB 0x0003 -#define AL_VOCAL_MORPHER_PHONEMEB_COARSE_TUNING 0x0004 -#define AL_VOCAL_MORPHER_WAVEFORM 0x0005 -#define AL_VOCAL_MORPHER_RATE 0x0006 - -/* Pitchshifter effect parameters */ -#define AL_PITCH_SHIFTER_COARSE_TUNE 0x0001 -#define AL_PITCH_SHIFTER_FINE_TUNE 0x0002 - -/* Ringmodulator effect parameters */ -#define AL_RING_MODULATOR_FREQUENCY 0x0001 -#define AL_RING_MODULATOR_HIGHPASS_CUTOFF 0x0002 -#define AL_RING_MODULATOR_WAVEFORM 0x0003 - -/* Autowah effect parameters */ -#define AL_AUTOWAH_ATTACK_TIME 0x0001 -#define AL_AUTOWAH_RELEASE_TIME 0x0002 -#define AL_AUTOWAH_RESONANCE 0x0003 -#define AL_AUTOWAH_PEAK_GAIN 0x0004 - -/* Compressor effect parameters */ -#define AL_COMPRESSOR_ONOFF 0x0001 - -/* Equalizer effect parameters */ -#define AL_EQUALIZER_LOW_GAIN 0x0001 -#define AL_EQUALIZER_LOW_CUTOFF 0x0002 -#define AL_EQUALIZER_MID1_GAIN 0x0003 -#define AL_EQUALIZER_MID1_CENTER 0x0004 -#define AL_EQUALIZER_MID1_WIDTH 0x0005 -#define AL_EQUALIZER_MID2_GAIN 0x0006 -#define AL_EQUALIZER_MID2_CENTER 0x0007 -#define AL_EQUALIZER_MID2_WIDTH 0x0008 -#define AL_EQUALIZER_HIGH_GAIN 0x0009 -#define AL_EQUALIZER_HIGH_CUTOFF 0x000A - -/* Effect type */ -#define AL_EFFECT_FIRST_PARAMETER 0x0000 -#define AL_EFFECT_LAST_PARAMETER 0x8000 -#define AL_EFFECT_TYPE 0x8001 - -/* Effect types, used with the AL_EFFECT_TYPE property */ -#define AL_EFFECT_NULL 0x0000 -#define AL_EFFECT_REVERB 0x0001 -#define AL_EFFECT_CHORUS 0x0002 -#define AL_EFFECT_DISTORTION 0x0003 -#define AL_EFFECT_ECHO 0x0004 -#define AL_EFFECT_FLANGER 0x0005 -#define AL_EFFECT_FREQUENCY_SHIFTER 0x0006 -#define AL_EFFECT_VOCAL_MORPHER 0x0007 -#define AL_EFFECT_PITCH_SHIFTER 0x0008 -#define AL_EFFECT_RING_MODULATOR 0x0009 -#define AL_EFFECT_AUTOWAH 0x000A -#define AL_EFFECT_COMPRESSOR 0x000B -#define AL_EFFECT_EQUALIZER 0x000C -#define AL_EFFECT_EAXREVERB 0x8000 - -/* Auxiliary Effect Slot properties. */ -#define AL_EFFECTSLOT_EFFECT 0x0001 -#define AL_EFFECTSLOT_GAIN 0x0002 -#define AL_EFFECTSLOT_AUXILIARY_SEND_AUTO 0x0003 - -/* NULL Auxiliary Slot ID to disable a source send. */ -#define AL_EFFECTSLOT_NULL 0x0000 - - -/* Filter properties. */ - -/* Lowpass filter parameters */ -#define AL_LOWPASS_GAIN 0x0001 -#define AL_LOWPASS_GAINHF 0x0002 - -/* Highpass filter parameters */ -#define AL_HIGHPASS_GAIN 0x0001 -#define AL_HIGHPASS_GAINLF 0x0002 - -/* Bandpass filter parameters */ -#define AL_BANDPASS_GAIN 0x0001 -#define AL_BANDPASS_GAINLF 0x0002 -#define AL_BANDPASS_GAINHF 0x0003 - -/* Filter type */ -#define AL_FILTER_FIRST_PARAMETER 0x0000 -#define AL_FILTER_LAST_PARAMETER 0x8000 -#define AL_FILTER_TYPE 0x8001 - -/* Filter types, used with the AL_FILTER_TYPE property */ -#define AL_FILTER_NULL 0x0000 -#define AL_FILTER_LOWPASS 0x0001 -#define AL_FILTER_HIGHPASS 0x0002 -#define AL_FILTER_BANDPASS 0x0003 - - -/* Effect object function types. */ -typedef void (AL_APIENTRY *LPALGENEFFECTS)(ALsizei, ALuint*); -typedef void (AL_APIENTRY *LPALDELETEEFFECTS)(ALsizei, const ALuint*); -typedef ALboolean (AL_APIENTRY *LPALISEFFECT)(ALuint); -typedef void (AL_APIENTRY *LPALEFFECTI)(ALuint, ALenum, ALint); -typedef void (AL_APIENTRY *LPALEFFECTIV)(ALuint, ALenum, const ALint*); -typedef void (AL_APIENTRY *LPALEFFECTF)(ALuint, ALenum, ALfloat); -typedef void (AL_APIENTRY *LPALEFFECTFV)(ALuint, ALenum, const ALfloat*); -typedef void (AL_APIENTRY *LPALGETEFFECTI)(ALuint, ALenum, ALint*); -typedef void (AL_APIENTRY *LPALGETEFFECTIV)(ALuint, ALenum, ALint*); -typedef void (AL_APIENTRY *LPALGETEFFECTF)(ALuint, ALenum, ALfloat*); -typedef void (AL_APIENTRY *LPALGETEFFECTFV)(ALuint, ALenum, ALfloat*); - -/* Filter object function types. */ -typedef void (AL_APIENTRY *LPALGENFILTERS)(ALsizei, ALuint*); -typedef void (AL_APIENTRY *LPALDELETEFILTERS)(ALsizei, const ALuint*); -typedef ALboolean (AL_APIENTRY *LPALISFILTER)(ALuint); -typedef void (AL_APIENTRY *LPALFILTERI)(ALuint, ALenum, ALint); -typedef void (AL_APIENTRY *LPALFILTERIV)(ALuint, ALenum, const ALint*); -typedef void (AL_APIENTRY *LPALFILTERF)(ALuint, ALenum, ALfloat); -typedef void (AL_APIENTRY *LPALFILTERFV)(ALuint, ALenum, const ALfloat*); -typedef void (AL_APIENTRY *LPALGETFILTERI)(ALuint, ALenum, ALint*); -typedef void (AL_APIENTRY *LPALGETFILTERIV)(ALuint, ALenum, ALint*); -typedef void (AL_APIENTRY *LPALGETFILTERF)(ALuint, ALenum, ALfloat*); -typedef void (AL_APIENTRY *LPALGETFILTERFV)(ALuint, ALenum, ALfloat*); - -/* Auxiliary Effect Slot object function types. */ -typedef void (AL_APIENTRY *LPALGENAUXILIARYEFFECTSLOTS)(ALsizei, ALuint*); -typedef void (AL_APIENTRY *LPALDELETEAUXILIARYEFFECTSLOTS)(ALsizei, const ALuint*); -typedef ALboolean (AL_APIENTRY *LPALISAUXILIARYEFFECTSLOT)(ALuint); -typedef void (AL_APIENTRY *LPALAUXILIARYEFFECTSLOTI)(ALuint, ALenum, ALint); -typedef void (AL_APIENTRY *LPALAUXILIARYEFFECTSLOTIV)(ALuint, ALenum, const ALint*); -typedef void (AL_APIENTRY *LPALAUXILIARYEFFECTSLOTF)(ALuint, ALenum, ALfloat); -typedef void (AL_APIENTRY *LPALAUXILIARYEFFECTSLOTFV)(ALuint, ALenum, const ALfloat*); -typedef void (AL_APIENTRY *LPALGETAUXILIARYEFFECTSLOTI)(ALuint, ALenum, ALint*); -typedef void (AL_APIENTRY *LPALGETAUXILIARYEFFECTSLOTIV)(ALuint, ALenum, ALint*); -typedef void (AL_APIENTRY *LPALGETAUXILIARYEFFECTSLOTF)(ALuint, ALenum, ALfloat*); -typedef void (AL_APIENTRY *LPALGETAUXILIARYEFFECTSLOTFV)(ALuint, ALenum, ALfloat*); - -#ifdef AL_ALEXT_PROTOTYPES -AL_API ALvoid AL_APIENTRY alGenEffects(ALsizei n, ALuint *effects); -AL_API ALvoid AL_APIENTRY alDeleteEffects(ALsizei n, const ALuint *effects); -AL_API ALboolean AL_APIENTRY alIsEffect(ALuint effect); -AL_API ALvoid AL_APIENTRY alEffecti(ALuint effect, ALenum param, ALint iValue); -AL_API ALvoid AL_APIENTRY alEffectiv(ALuint effect, ALenum param, const ALint *piValues); -AL_API ALvoid AL_APIENTRY alEffectf(ALuint effect, ALenum param, ALfloat flValue); -AL_API ALvoid AL_APIENTRY alEffectfv(ALuint effect, ALenum param, const ALfloat *pflValues); -AL_API ALvoid AL_APIENTRY alGetEffecti(ALuint effect, ALenum param, ALint *piValue); -AL_API ALvoid AL_APIENTRY alGetEffectiv(ALuint effect, ALenum param, ALint *piValues); -AL_API ALvoid AL_APIENTRY alGetEffectf(ALuint effect, ALenum param, ALfloat *pflValue); -AL_API ALvoid AL_APIENTRY alGetEffectfv(ALuint effect, ALenum param, ALfloat *pflValues); - -AL_API ALvoid AL_APIENTRY alGenFilters(ALsizei n, ALuint *filters); -AL_API ALvoid AL_APIENTRY alDeleteFilters(ALsizei n, const ALuint *filters); -AL_API ALboolean AL_APIENTRY alIsFilter(ALuint filter); -AL_API ALvoid AL_APIENTRY alFilteri(ALuint filter, ALenum param, ALint iValue); -AL_API ALvoid AL_APIENTRY alFilteriv(ALuint filter, ALenum param, const ALint *piValues); -AL_API ALvoid AL_APIENTRY alFilterf(ALuint filter, ALenum param, ALfloat flValue); -AL_API ALvoid AL_APIENTRY alFilterfv(ALuint filter, ALenum param, const ALfloat *pflValues); -AL_API ALvoid AL_APIENTRY alGetFilteri(ALuint filter, ALenum param, ALint *piValue); -AL_API ALvoid AL_APIENTRY alGetFilteriv(ALuint filter, ALenum param, ALint *piValues); -AL_API ALvoid AL_APIENTRY alGetFilterf(ALuint filter, ALenum param, ALfloat *pflValue); -AL_API ALvoid AL_APIENTRY alGetFilterfv(ALuint filter, ALenum param, ALfloat *pflValues); - -AL_API ALvoid AL_APIENTRY alGenAuxiliaryEffectSlots(ALsizei n, ALuint *effectslots); -AL_API ALvoid AL_APIENTRY alDeleteAuxiliaryEffectSlots(ALsizei n, const ALuint *effectslots); -AL_API ALboolean AL_APIENTRY alIsAuxiliaryEffectSlot(ALuint effectslot); -AL_API ALvoid AL_APIENTRY alAuxiliaryEffectSloti(ALuint effectslot, ALenum param, ALint iValue); -AL_API ALvoid AL_APIENTRY alAuxiliaryEffectSlotiv(ALuint effectslot, ALenum param, const ALint *piValues); -AL_API ALvoid AL_APIENTRY alAuxiliaryEffectSlotf(ALuint effectslot, ALenum param, ALfloat flValue); -AL_API ALvoid AL_APIENTRY alAuxiliaryEffectSlotfv(ALuint effectslot, ALenum param, const ALfloat *pflValues); -AL_API ALvoid AL_APIENTRY alGetAuxiliaryEffectSloti(ALuint effectslot, ALenum param, ALint *piValue); -AL_API ALvoid AL_APIENTRY alGetAuxiliaryEffectSlotiv(ALuint effectslot, ALenum param, ALint *piValues); -AL_API ALvoid AL_APIENTRY alGetAuxiliaryEffectSlotf(ALuint effectslot, ALenum param, ALfloat *pflValue); -AL_API ALvoid AL_APIENTRY alGetAuxiliaryEffectSlotfv(ALuint effectslot, ALenum param, ALfloat *pflValues); -#endif - -/* Filter ranges and defaults. */ - -/* Lowpass filter */ -#define AL_LOWPASS_MIN_GAIN (0.0f) -#define AL_LOWPASS_MAX_GAIN (1.0f) -#define AL_LOWPASS_DEFAULT_GAIN (1.0f) - -#define AL_LOWPASS_MIN_GAINHF (0.0f) -#define AL_LOWPASS_MAX_GAINHF (1.0f) -#define AL_LOWPASS_DEFAULT_GAINHF (1.0f) - -/* Highpass filter */ -#define AL_HIGHPASS_MIN_GAIN (0.0f) -#define AL_HIGHPASS_MAX_GAIN (1.0f) -#define AL_HIGHPASS_DEFAULT_GAIN (1.0f) - -#define AL_HIGHPASS_MIN_GAINLF (0.0f) -#define AL_HIGHPASS_MAX_GAINLF (1.0f) -#define AL_HIGHPASS_DEFAULT_GAINLF (1.0f) - -/* Bandpass filter */ -#define AL_BANDPASS_MIN_GAIN (0.0f) -#define AL_BANDPASS_MAX_GAIN (1.0f) -#define AL_BANDPASS_DEFAULT_GAIN (1.0f) - -#define AL_BANDPASS_MIN_GAINHF (0.0f) -#define AL_BANDPASS_MAX_GAINHF (1.0f) -#define AL_BANDPASS_DEFAULT_GAINHF (1.0f) - -#define AL_BANDPASS_MIN_GAINLF (0.0f) -#define AL_BANDPASS_MAX_GAINLF (1.0f) -#define AL_BANDPASS_DEFAULT_GAINLF (1.0f) - - -/* Effect parameter ranges and defaults. */ - -/* Standard reverb effect */ -#define AL_REVERB_MIN_DENSITY (0.0f) -#define AL_REVERB_MAX_DENSITY (1.0f) -#define AL_REVERB_DEFAULT_DENSITY (1.0f) - -#define AL_REVERB_MIN_DIFFUSION (0.0f) -#define AL_REVERB_MAX_DIFFUSION (1.0f) -#define AL_REVERB_DEFAULT_DIFFUSION (1.0f) - -#define AL_REVERB_MIN_GAIN (0.0f) -#define AL_REVERB_MAX_GAIN (1.0f) -#define AL_REVERB_DEFAULT_GAIN (0.32f) - -#define AL_REVERB_MIN_GAINHF (0.0f) -#define AL_REVERB_MAX_GAINHF (1.0f) -#define AL_REVERB_DEFAULT_GAINHF (0.89f) - -#define AL_REVERB_MIN_DECAY_TIME (0.1f) -#define AL_REVERB_MAX_DECAY_TIME (20.0f) -#define AL_REVERB_DEFAULT_DECAY_TIME (1.49f) - -#define AL_REVERB_MIN_DECAY_HFRATIO (0.1f) -#define AL_REVERB_MAX_DECAY_HFRATIO (2.0f) -#define AL_REVERB_DEFAULT_DECAY_HFRATIO (0.83f) - -#define AL_REVERB_MIN_REFLECTIONS_GAIN (0.0f) -#define AL_REVERB_MAX_REFLECTIONS_GAIN (3.16f) -#define AL_REVERB_DEFAULT_REFLECTIONS_GAIN (0.05f) - -#define AL_REVERB_MIN_REFLECTIONS_DELAY (0.0f) -#define AL_REVERB_MAX_REFLECTIONS_DELAY (0.3f) -#define AL_REVERB_DEFAULT_REFLECTIONS_DELAY (0.007f) - -#define AL_REVERB_MIN_LATE_REVERB_GAIN (0.0f) -#define AL_REVERB_MAX_LATE_REVERB_GAIN (10.0f) -#define AL_REVERB_DEFAULT_LATE_REVERB_GAIN (1.26f) - -#define AL_REVERB_MIN_LATE_REVERB_DELAY (0.0f) -#define AL_REVERB_MAX_LATE_REVERB_DELAY (0.1f) -#define AL_REVERB_DEFAULT_LATE_REVERB_DELAY (0.011f) - -#define AL_REVERB_MIN_AIR_ABSORPTION_GAINHF (0.892f) -#define AL_REVERB_MAX_AIR_ABSORPTION_GAINHF (1.0f) -#define AL_REVERB_DEFAULT_AIR_ABSORPTION_GAINHF (0.994f) - -#define AL_REVERB_MIN_ROOM_ROLLOFF_FACTOR (0.0f) -#define AL_REVERB_MAX_ROOM_ROLLOFF_FACTOR (10.0f) -#define AL_REVERB_DEFAULT_ROOM_ROLLOFF_FACTOR (0.0f) - -#define AL_REVERB_MIN_DECAY_HFLIMIT AL_FALSE -#define AL_REVERB_MAX_DECAY_HFLIMIT AL_TRUE -#define AL_REVERB_DEFAULT_DECAY_HFLIMIT AL_TRUE - -/* EAX reverb effect */ -#define AL_EAXREVERB_MIN_DENSITY (0.0f) -#define AL_EAXREVERB_MAX_DENSITY (1.0f) -#define AL_EAXREVERB_DEFAULT_DENSITY (1.0f) - -#define AL_EAXREVERB_MIN_DIFFUSION (0.0f) -#define AL_EAXREVERB_MAX_DIFFUSION (1.0f) -#define AL_EAXREVERB_DEFAULT_DIFFUSION (1.0f) - -#define AL_EAXREVERB_MIN_GAIN (0.0f) -#define AL_EAXREVERB_MAX_GAIN (1.0f) -#define AL_EAXREVERB_DEFAULT_GAIN (0.32f) - -#define AL_EAXREVERB_MIN_GAINHF (0.0f) -#define AL_EAXREVERB_MAX_GAINHF (1.0f) -#define AL_EAXREVERB_DEFAULT_GAINHF (0.89f) - -#define AL_EAXREVERB_MIN_GAINLF (0.0f) -#define AL_EAXREVERB_MAX_GAINLF (1.0f) -#define AL_EAXREVERB_DEFAULT_GAINLF (1.0f) - -#define AL_EAXREVERB_MIN_DECAY_TIME (0.1f) -#define AL_EAXREVERB_MAX_DECAY_TIME (20.0f) -#define AL_EAXREVERB_DEFAULT_DECAY_TIME (1.49f) - -#define AL_EAXREVERB_MIN_DECAY_HFRATIO (0.1f) -#define AL_EAXREVERB_MAX_DECAY_HFRATIO (2.0f) -#define AL_EAXREVERB_DEFAULT_DECAY_HFRATIO (0.83f) - -#define AL_EAXREVERB_MIN_DECAY_LFRATIO (0.1f) -#define AL_EAXREVERB_MAX_DECAY_LFRATIO (2.0f) -#define AL_EAXREVERB_DEFAULT_DECAY_LFRATIO (1.0f) - -#define AL_EAXREVERB_MIN_REFLECTIONS_GAIN (0.0f) -#define AL_EAXREVERB_MAX_REFLECTIONS_GAIN (3.16f) -#define AL_EAXREVERB_DEFAULT_REFLECTIONS_GAIN (0.05f) - -#define AL_EAXREVERB_MIN_REFLECTIONS_DELAY (0.0f) -#define AL_EAXREVERB_MAX_REFLECTIONS_DELAY (0.3f) -#define AL_EAXREVERB_DEFAULT_REFLECTIONS_DELAY (0.007f) - -#define AL_EAXREVERB_DEFAULT_REFLECTIONS_PAN_XYZ (0.0f) - -#define AL_EAXREVERB_MIN_LATE_REVERB_GAIN (0.0f) -#define AL_EAXREVERB_MAX_LATE_REVERB_GAIN (10.0f) -#define AL_EAXREVERB_DEFAULT_LATE_REVERB_GAIN (1.26f) - -#define AL_EAXREVERB_MIN_LATE_REVERB_DELAY (0.0f) -#define AL_EAXREVERB_MAX_LATE_REVERB_DELAY (0.1f) -#define AL_EAXREVERB_DEFAULT_LATE_REVERB_DELAY (0.011f) - -#define AL_EAXREVERB_DEFAULT_LATE_REVERB_PAN_XYZ (0.0f) - -#define AL_EAXREVERB_MIN_ECHO_TIME (0.075f) -#define AL_EAXREVERB_MAX_ECHO_TIME (0.25f) -#define AL_EAXREVERB_DEFAULT_ECHO_TIME (0.25f) - -#define AL_EAXREVERB_MIN_ECHO_DEPTH (0.0f) -#define AL_EAXREVERB_MAX_ECHO_DEPTH (1.0f) -#define AL_EAXREVERB_DEFAULT_ECHO_DEPTH (0.0f) - -#define AL_EAXREVERB_MIN_MODULATION_TIME (0.04f) -#define AL_EAXREVERB_MAX_MODULATION_TIME (4.0f) -#define AL_EAXREVERB_DEFAULT_MODULATION_TIME (0.25f) - -#define AL_EAXREVERB_MIN_MODULATION_DEPTH (0.0f) -#define AL_EAXREVERB_MAX_MODULATION_DEPTH (1.0f) -#define AL_EAXREVERB_DEFAULT_MODULATION_DEPTH (0.0f) - -#define AL_EAXREVERB_MIN_AIR_ABSORPTION_GAINHF (0.892f) -#define AL_EAXREVERB_MAX_AIR_ABSORPTION_GAINHF (1.0f) -#define AL_EAXREVERB_DEFAULT_AIR_ABSORPTION_GAINHF (0.994f) - -#define AL_EAXREVERB_MIN_HFREFERENCE (1000.0f) -#define AL_EAXREVERB_MAX_HFREFERENCE (20000.0f) -#define AL_EAXREVERB_DEFAULT_HFREFERENCE (5000.0f) - -#define AL_EAXREVERB_MIN_LFREFERENCE (20.0f) -#define AL_EAXREVERB_MAX_LFREFERENCE (1000.0f) -#define AL_EAXREVERB_DEFAULT_LFREFERENCE (250.0f) - -#define AL_EAXREVERB_MIN_ROOM_ROLLOFF_FACTOR (0.0f) -#define AL_EAXREVERB_MAX_ROOM_ROLLOFF_FACTOR (10.0f) -#define AL_EAXREVERB_DEFAULT_ROOM_ROLLOFF_FACTOR (0.0f) - -#define AL_EAXREVERB_MIN_DECAY_HFLIMIT AL_FALSE -#define AL_EAXREVERB_MAX_DECAY_HFLIMIT AL_TRUE -#define AL_EAXREVERB_DEFAULT_DECAY_HFLIMIT AL_TRUE - -/* Chorus effect */ -#define AL_CHORUS_WAVEFORM_SINUSOID (0) -#define AL_CHORUS_WAVEFORM_TRIANGLE (1) - -#define AL_CHORUS_MIN_WAVEFORM (0) -#define AL_CHORUS_MAX_WAVEFORM (1) -#define AL_CHORUS_DEFAULT_WAVEFORM (1) - -#define AL_CHORUS_MIN_PHASE (-180) -#define AL_CHORUS_MAX_PHASE (180) -#define AL_CHORUS_DEFAULT_PHASE (90) - -#define AL_CHORUS_MIN_RATE (0.0f) -#define AL_CHORUS_MAX_RATE (10.0f) -#define AL_CHORUS_DEFAULT_RATE (1.1f) - -#define AL_CHORUS_MIN_DEPTH (0.0f) -#define AL_CHORUS_MAX_DEPTH (1.0f) -#define AL_CHORUS_DEFAULT_DEPTH (0.1f) - -#define AL_CHORUS_MIN_FEEDBACK (-1.0f) -#define AL_CHORUS_MAX_FEEDBACK (1.0f) -#define AL_CHORUS_DEFAULT_FEEDBACK (0.25f) - -#define AL_CHORUS_MIN_DELAY (0.0f) -#define AL_CHORUS_MAX_DELAY (0.016f) -#define AL_CHORUS_DEFAULT_DELAY (0.016f) - -/* Distortion effect */ -#define AL_DISTORTION_MIN_EDGE (0.0f) -#define AL_DISTORTION_MAX_EDGE (1.0f) -#define AL_DISTORTION_DEFAULT_EDGE (0.2f) - -#define AL_DISTORTION_MIN_GAIN (0.01f) -#define AL_DISTORTION_MAX_GAIN (1.0f) -#define AL_DISTORTION_DEFAULT_GAIN (0.05f) - -#define AL_DISTORTION_MIN_LOWPASS_CUTOFF (80.0f) -#define AL_DISTORTION_MAX_LOWPASS_CUTOFF (24000.0f) -#define AL_DISTORTION_DEFAULT_LOWPASS_CUTOFF (8000.0f) - -#define AL_DISTORTION_MIN_EQCENTER (80.0f) -#define AL_DISTORTION_MAX_EQCENTER (24000.0f) -#define AL_DISTORTION_DEFAULT_EQCENTER (3600.0f) - -#define AL_DISTORTION_MIN_EQBANDWIDTH (80.0f) -#define AL_DISTORTION_MAX_EQBANDWIDTH (24000.0f) -#define AL_DISTORTION_DEFAULT_EQBANDWIDTH (3600.0f) - -/* Echo effect */ -#define AL_ECHO_MIN_DELAY (0.0f) -#define AL_ECHO_MAX_DELAY (0.207f) -#define AL_ECHO_DEFAULT_DELAY (0.1f) - -#define AL_ECHO_MIN_LRDELAY (0.0f) -#define AL_ECHO_MAX_LRDELAY (0.404f) -#define AL_ECHO_DEFAULT_LRDELAY (0.1f) - -#define AL_ECHO_MIN_DAMPING (0.0f) -#define AL_ECHO_MAX_DAMPING (0.99f) -#define AL_ECHO_DEFAULT_DAMPING (0.5f) - -#define AL_ECHO_MIN_FEEDBACK (0.0f) -#define AL_ECHO_MAX_FEEDBACK (1.0f) -#define AL_ECHO_DEFAULT_FEEDBACK (0.5f) - -#define AL_ECHO_MIN_SPREAD (-1.0f) -#define AL_ECHO_MAX_SPREAD (1.0f) -#define AL_ECHO_DEFAULT_SPREAD (-1.0f) - -/* Flanger effect */ -#define AL_FLANGER_WAVEFORM_SINUSOID (0) -#define AL_FLANGER_WAVEFORM_TRIANGLE (1) - -#define AL_FLANGER_MIN_WAVEFORM (0) -#define AL_FLANGER_MAX_WAVEFORM (1) -#define AL_FLANGER_DEFAULT_WAVEFORM (1) - -#define AL_FLANGER_MIN_PHASE (-180) -#define AL_FLANGER_MAX_PHASE (180) -#define AL_FLANGER_DEFAULT_PHASE (0) - -#define AL_FLANGER_MIN_RATE (0.0f) -#define AL_FLANGER_MAX_RATE (10.0f) -#define AL_FLANGER_DEFAULT_RATE (0.27f) - -#define AL_FLANGER_MIN_DEPTH (0.0f) -#define AL_FLANGER_MAX_DEPTH (1.0f) -#define AL_FLANGER_DEFAULT_DEPTH (1.0f) - -#define AL_FLANGER_MIN_FEEDBACK (-1.0f) -#define AL_FLANGER_MAX_FEEDBACK (1.0f) -#define AL_FLANGER_DEFAULT_FEEDBACK (-0.5f) - -#define AL_FLANGER_MIN_DELAY (0.0f) -#define AL_FLANGER_MAX_DELAY (0.004f) -#define AL_FLANGER_DEFAULT_DELAY (0.002f) - -/* Frequency shifter effect */ -#define AL_FREQUENCY_SHIFTER_MIN_FREQUENCY (0.0f) -#define AL_FREQUENCY_SHIFTER_MAX_FREQUENCY (24000.0f) -#define AL_FREQUENCY_SHIFTER_DEFAULT_FREQUENCY (0.0f) - -#define AL_FREQUENCY_SHIFTER_MIN_LEFT_DIRECTION (0) -#define AL_FREQUENCY_SHIFTER_MAX_LEFT_DIRECTION (2) -#define AL_FREQUENCY_SHIFTER_DEFAULT_LEFT_DIRECTION (0) - -#define AL_FREQUENCY_SHIFTER_DIRECTION_DOWN (0) -#define AL_FREQUENCY_SHIFTER_DIRECTION_UP (1) -#define AL_FREQUENCY_SHIFTER_DIRECTION_OFF (2) - -#define AL_FREQUENCY_SHIFTER_MIN_RIGHT_DIRECTION (0) -#define AL_FREQUENCY_SHIFTER_MAX_RIGHT_DIRECTION (2) -#define AL_FREQUENCY_SHIFTER_DEFAULT_RIGHT_DIRECTION (0) - -/* Vocal morpher effect */ -#define AL_VOCAL_MORPHER_MIN_PHONEMEA (0) -#define AL_VOCAL_MORPHER_MAX_PHONEMEA (29) -#define AL_VOCAL_MORPHER_DEFAULT_PHONEMEA (0) - -#define AL_VOCAL_MORPHER_MIN_PHONEMEA_COARSE_TUNING (-24) -#define AL_VOCAL_MORPHER_MAX_PHONEMEA_COARSE_TUNING (24) -#define AL_VOCAL_MORPHER_DEFAULT_PHONEMEA_COARSE_TUNING (0) - -#define AL_VOCAL_MORPHER_MIN_PHONEMEB (0) -#define AL_VOCAL_MORPHER_MAX_PHONEMEB (29) -#define AL_VOCAL_MORPHER_DEFAULT_PHONEMEB (10) - -#define AL_VOCAL_MORPHER_MIN_PHONEMEB_COARSE_TUNING (-24) -#define AL_VOCAL_MORPHER_MAX_PHONEMEB_COARSE_TUNING (24) -#define AL_VOCAL_MORPHER_DEFAULT_PHONEMEB_COARSE_TUNING (0) - -#define AL_VOCAL_MORPHER_PHONEME_A (0) -#define AL_VOCAL_MORPHER_PHONEME_E (1) -#define AL_VOCAL_MORPHER_PHONEME_I (2) -#define AL_VOCAL_MORPHER_PHONEME_O (3) -#define AL_VOCAL_MORPHER_PHONEME_U (4) -#define AL_VOCAL_MORPHER_PHONEME_AA (5) -#define AL_VOCAL_MORPHER_PHONEME_AE (6) -#define AL_VOCAL_MORPHER_PHONEME_AH (7) -#define AL_VOCAL_MORPHER_PHONEME_AO (8) -#define AL_VOCAL_MORPHER_PHONEME_EH (9) -#define AL_VOCAL_MORPHER_PHONEME_ER (10) -#define AL_VOCAL_MORPHER_PHONEME_IH (11) -#define AL_VOCAL_MORPHER_PHONEME_IY (12) -#define AL_VOCAL_MORPHER_PHONEME_UH (13) -#define AL_VOCAL_MORPHER_PHONEME_UW (14) -#define AL_VOCAL_MORPHER_PHONEME_B (15) -#define AL_VOCAL_MORPHER_PHONEME_D (16) -#define AL_VOCAL_MORPHER_PHONEME_F (17) -#define AL_VOCAL_MORPHER_PHONEME_G (18) -#define AL_VOCAL_MORPHER_PHONEME_J (19) -#define AL_VOCAL_MORPHER_PHONEME_K (20) -#define AL_VOCAL_MORPHER_PHONEME_L (21) -#define AL_VOCAL_MORPHER_PHONEME_M (22) -#define AL_VOCAL_MORPHER_PHONEME_N (23) -#define AL_VOCAL_MORPHER_PHONEME_P (24) -#define AL_VOCAL_MORPHER_PHONEME_R (25) -#define AL_VOCAL_MORPHER_PHONEME_S (26) -#define AL_VOCAL_MORPHER_PHONEME_T (27) -#define AL_VOCAL_MORPHER_PHONEME_V (28) -#define AL_VOCAL_MORPHER_PHONEME_Z (29) - -#define AL_VOCAL_MORPHER_WAVEFORM_SINUSOID (0) -#define AL_VOCAL_MORPHER_WAVEFORM_TRIANGLE (1) -#define AL_VOCAL_MORPHER_WAVEFORM_SAWTOOTH (2) - -#define AL_VOCAL_MORPHER_MIN_WAVEFORM (0) -#define AL_VOCAL_MORPHER_MAX_WAVEFORM (2) -#define AL_VOCAL_MORPHER_DEFAULT_WAVEFORM (0) - -#define AL_VOCAL_MORPHER_MIN_RATE (0.0f) -#define AL_VOCAL_MORPHER_MAX_RATE (10.0f) -#define AL_VOCAL_MORPHER_DEFAULT_RATE (1.41f) - -/* Pitch shifter effect */ -#define AL_PITCH_SHIFTER_MIN_COARSE_TUNE (-12) -#define AL_PITCH_SHIFTER_MAX_COARSE_TUNE (12) -#define AL_PITCH_SHIFTER_DEFAULT_COARSE_TUNE (12) - -#define AL_PITCH_SHIFTER_MIN_FINE_TUNE (-50) -#define AL_PITCH_SHIFTER_MAX_FINE_TUNE (50) -#define AL_PITCH_SHIFTER_DEFAULT_FINE_TUNE (0) - -/* Ring modulator effect */ -#define AL_RING_MODULATOR_MIN_FREQUENCY (0.0f) -#define AL_RING_MODULATOR_MAX_FREQUENCY (8000.0f) -#define AL_RING_MODULATOR_DEFAULT_FREQUENCY (440.0f) - -#define AL_RING_MODULATOR_MIN_HIGHPASS_CUTOFF (0.0f) -#define AL_RING_MODULATOR_MAX_HIGHPASS_CUTOFF (24000.0f) -#define AL_RING_MODULATOR_DEFAULT_HIGHPASS_CUTOFF (800.0f) - -#define AL_RING_MODULATOR_SINUSOID (0) -#define AL_RING_MODULATOR_SAWTOOTH (1) -#define AL_RING_MODULATOR_SQUARE (2) - -#define AL_RING_MODULATOR_MIN_WAVEFORM (0) -#define AL_RING_MODULATOR_MAX_WAVEFORM (2) -#define AL_RING_MODULATOR_DEFAULT_WAVEFORM (0) - -/* Autowah effect */ -#define AL_AUTOWAH_MIN_ATTACK_TIME (0.0001f) -#define AL_AUTOWAH_MAX_ATTACK_TIME (1.0f) -#define AL_AUTOWAH_DEFAULT_ATTACK_TIME (0.06f) - -#define AL_AUTOWAH_MIN_RELEASE_TIME (0.0001f) -#define AL_AUTOWAH_MAX_RELEASE_TIME (1.0f) -#define AL_AUTOWAH_DEFAULT_RELEASE_TIME (0.06f) - -#define AL_AUTOWAH_MIN_RESONANCE (2.0f) -#define AL_AUTOWAH_MAX_RESONANCE (1000.0f) -#define AL_AUTOWAH_DEFAULT_RESONANCE (1000.0f) - -#define AL_AUTOWAH_MIN_PEAK_GAIN (0.00003f) -#define AL_AUTOWAH_MAX_PEAK_GAIN (31621.0f) -#define AL_AUTOWAH_DEFAULT_PEAK_GAIN (11.22f) - -/* Compressor effect */ -#define AL_COMPRESSOR_MIN_ONOFF (0) -#define AL_COMPRESSOR_MAX_ONOFF (1) -#define AL_COMPRESSOR_DEFAULT_ONOFF (1) - -/* Equalizer effect */ -#define AL_EQUALIZER_MIN_LOW_GAIN (0.126f) -#define AL_EQUALIZER_MAX_LOW_GAIN (7.943f) -#define AL_EQUALIZER_DEFAULT_LOW_GAIN (1.0f) - -#define AL_EQUALIZER_MIN_LOW_CUTOFF (50.0f) -#define AL_EQUALIZER_MAX_LOW_CUTOFF (800.0f) -#define AL_EQUALIZER_DEFAULT_LOW_CUTOFF (200.0f) - -#define AL_EQUALIZER_MIN_MID1_GAIN (0.126f) -#define AL_EQUALIZER_MAX_MID1_GAIN (7.943f) -#define AL_EQUALIZER_DEFAULT_MID1_GAIN (1.0f) - -#define AL_EQUALIZER_MIN_MID1_CENTER (200.0f) -#define AL_EQUALIZER_MAX_MID1_CENTER (3000.0f) -#define AL_EQUALIZER_DEFAULT_MID1_CENTER (500.0f) - -#define AL_EQUALIZER_MIN_MID1_WIDTH (0.01f) -#define AL_EQUALIZER_MAX_MID1_WIDTH (1.0f) -#define AL_EQUALIZER_DEFAULT_MID1_WIDTH (1.0f) - -#define AL_EQUALIZER_MIN_MID2_GAIN (0.126f) -#define AL_EQUALIZER_MAX_MID2_GAIN (7.943f) -#define AL_EQUALIZER_DEFAULT_MID2_GAIN (1.0f) - -#define AL_EQUALIZER_MIN_MID2_CENTER (1000.0f) -#define AL_EQUALIZER_MAX_MID2_CENTER (8000.0f) -#define AL_EQUALIZER_DEFAULT_MID2_CENTER (3000.0f) - -#define AL_EQUALIZER_MIN_MID2_WIDTH (0.01f) -#define AL_EQUALIZER_MAX_MID2_WIDTH (1.0f) -#define AL_EQUALIZER_DEFAULT_MID2_WIDTH (1.0f) - -#define AL_EQUALIZER_MIN_HIGH_GAIN (0.126f) -#define AL_EQUALIZER_MAX_HIGH_GAIN (7.943f) -#define AL_EQUALIZER_DEFAULT_HIGH_GAIN (1.0f) - -#define AL_EQUALIZER_MIN_HIGH_CUTOFF (4000.0f) -#define AL_EQUALIZER_MAX_HIGH_CUTOFF (16000.0f) -#define AL_EQUALIZER_DEFAULT_HIGH_CUTOFF (6000.0f) - - -/* Source parameter value ranges and defaults. */ -#define AL_MIN_AIR_ABSORPTION_FACTOR (0.0f) -#define AL_MAX_AIR_ABSORPTION_FACTOR (10.0f) -#define AL_DEFAULT_AIR_ABSORPTION_FACTOR (0.0f) - -#define AL_MIN_ROOM_ROLLOFF_FACTOR (0.0f) -#define AL_MAX_ROOM_ROLLOFF_FACTOR (10.0f) -#define AL_DEFAULT_ROOM_ROLLOFF_FACTOR (0.0f) - -#define AL_MIN_CONE_OUTER_GAINHF (0.0f) -#define AL_MAX_CONE_OUTER_GAINHF (1.0f) -#define AL_DEFAULT_CONE_OUTER_GAINHF (1.0f) - -#define AL_MIN_DIRECT_FILTER_GAINHF_AUTO AL_FALSE -#define AL_MAX_DIRECT_FILTER_GAINHF_AUTO AL_TRUE -#define AL_DEFAULT_DIRECT_FILTER_GAINHF_AUTO AL_TRUE - -#define AL_MIN_AUXILIARY_SEND_FILTER_GAIN_AUTO AL_FALSE -#define AL_MAX_AUXILIARY_SEND_FILTER_GAIN_AUTO AL_TRUE -#define AL_DEFAULT_AUXILIARY_SEND_FILTER_GAIN_AUTO AL_TRUE - -#define AL_MIN_AUXILIARY_SEND_FILTER_GAINHF_AUTO AL_FALSE -#define AL_MAX_AUXILIARY_SEND_FILTER_GAINHF_AUTO AL_TRUE -#define AL_DEFAULT_AUXILIARY_SEND_FILTER_GAINHF_AUTO AL_TRUE - - -/* Listener parameter value ranges and defaults. */ -#define AL_MIN_METERS_PER_UNIT FLT_MIN -#define AL_MAX_METERS_PER_UNIT FLT_MAX -#define AL_DEFAULT_METERS_PER_UNIT (1.0f) - - -#ifdef __cplusplus -} /* extern "C" */ -#endif - -#endif /* AL_EFX_H */ diff --git a/src/include/FAudio_compat.h b/src/include/FAudio_compat.h new file mode 100644 index 000000000..dd76dea3d --- /dev/null +++ b/src/include/FAudio_compat.h @@ -0,0 +1,106 @@ +/* map xaudio2 API to faudio API */ +typedef uint32_t HRESULT; +typedef uint32_t UINT32; +typedef uint32_t DWORD; +typedef uint8_t BOOL; + +#define WINAPI FAUDIOCALL + +#define TRUE 1 +#define FALSE 0 + +#define S_OK 0 +#define XAUDIO2_E_INVALID_CALL FAUDIO_E_INVALID_CALL + +#define XAUDIO2_DEFAULT_PROCESSOR FAUDIO_DEFAULT_PROCESSOR +#define XAUDIO2_COMMIT_NOW FAUDIO_COMMIT_NOW +#define XAUDIO2_END_OF_STREAM FAUDIO_END_OF_STREAM + +#define WAVE_FORMAT_PCM FAUDIO_FORMAT_PCM +#define WAVE_FORMAT_IEEE_FLOAT FAUDIO_FORMAT_IEEE_FLOAT + +#define AudioCategory_GameEffects FAudioStreamCategory_GameEffects + +#define GlobalDefaultDevice FAudioGlobalDefaultDevice +#define NotDefaultDevice FAudioNotDefaultDevice + +#define XAudio2Create FAudioCreate + +typedef FAudioBuffer XAUDIO2_BUFFER; +typedef FAudioDeviceDetails XAUDIO2_DEVICE_DETAILS; +typedef FAudioEffectChain XAUDIO2_EFFECT_CHAIN; +typedef FAudioEffectDescriptor XAUDIO2_EFFECT_DESCRIPTOR; +typedef FAudioVoiceDetails XAUDIO2_VOICE_DETAILS; +typedef FAudioVoiceDetails XAUDIO27_VOICE_DETAILS; +typedef FAudioVoiceState XAUDIO2_VOICE_STATE; +typedef FAudioWaveFormatEx WAVEFORMATEX; +typedef FAudioPerformanceData XAUDIO2_PERFORMANCE_DATA; + +typedef FAudioEngineCallback IXAudio2EngineCallback; +typedef FAudioVoiceCallback IXAudio2VoiceCallback; + +typedef FAPO IXAPO; + +typedef FAudio IXAudio27; +#define IXAudio27_CreateMasteringVoice FAudio_CreateMasteringVoice +#define IXAudio27_CreateSourceVoice FAudio_CreateSourceVoice +#define IXAudio27_CreateSubmixVoice FAudio_CreateSubmixVoice +#define IXAudio27_GetDeviceCount FAudio_GetDeviceCount +#define IXAudio27_GetDeviceDetails FAudio_GetDeviceDetails +#define IXAudio27_GetPerformanceData FAudio_GetPerformanceData +#define IXAudio27_Initialize FAudio_Initialize +#define IXAudio27_RegisterForCallbacks FAudio_RegisterForCallbacks +#define IXAudio27_Release FAudio_Release +#define IXAudio27_StartEngine FAudio_StartEngine +#define IXAudio27_StopEngine FAudio_StopEngine +#define IXAudio27_UnregisterForCallbacks FAudio_UnregisterForCallbacks + +typedef FAudio IXAudio2; +#define IXAudio2_CreateMasteringVoice FAudio_CreateMasteringVoice8 +#define IXAudio2_CreateSourceVoice FAudio_CreateSourceVoice +#define IXAudio2_CreateSubmixVoice FAudio_CreateSubmixVoice +#define IXAudio2_GetPerformanceData FAudio_GetPerformanceData +#define IXAudio2_RegisterForCallbacks FAudio_RegisterForCallbacks +#define IXAudio2_Release FAudio_Release +#define IXAudio2_StartEngine FAudio_StartEngine +#define IXAudio2_StopEngine FAudio_StopEngine +#define IXAudio2_UnregisterForCallbacks FAudio_UnregisterForCallbacks + +typedef FAudioMasteringVoice IXAudio2MasteringVoice; +#define IXAudio2MasteringVoice_DestroyVoice FAudioVoice_DestroyVoice +#define IXAudio2MasteringVoice_GetChannelMask FAudioMasteringVoice_GetChannelMask +#define IXAudio2MasteringVoice_SetEffectChain FAudioVoice_SetEffectChain +#define IXAudio2MasteringVoice_SetVolume FAudioVoice_SetVolume + +typedef FAudioSourceVoice IXAudio27SourceVoice; +#define IXAudio27SourceVoice_DestroyVoice FAudioVoice_DestroyVoice +#define IXAudio27SourceVoice_ExitLoop FAudioSourceVoice_ExitLoop +#define IXAudio27SourceVoice_FlushSourceBuffers FAudioSourceVoice_FlushSourceBuffers +#define IXAudio27SourceVoice_GetState(a,b) FAudioSourceVoice_GetState(a,b,0) +#define IXAudio27SourceVoice_GetVoiceDetails FAudioVoice_GetVoiceDetails +#define IXAudio27SourceVoice_SetChannelVolumes FAudioVoice_SetChannelVolumes +#define IXAudio27SourceVoice_SetSourceSampleRate FAudioSourceVoice_SetSourceSampleRate +#define IXAudio27SourceVoice_Start FAudioSourceVoice_Start +#define IXAudio27SourceVoice_Stop FAudioSourceVoice_Stop +#define IXAudio27SourceVoice_SubmitSourceBuffer FAudioSourceVoice_SubmitSourceBuffer + +typedef FAudioSourceVoice IXAudio2SourceVoice; +#define IXAudio2SourceVoice_DestroyVoice FAudioVoice_DestroyVoice +#define IXAudio2SourceVoice_ExitLoop FAudioSourceVoice_ExitLoop +#define IXAudio2SourceVoice_FlushSourceBuffers FAudioSourceVoice_FlushSourceBuffers +#define IXAudio2SourceVoice_GetState FAudioSourceVoice_GetState +#define IXAudio2SourceVoice_GetVoiceDetails FAudioVoice_GetVoiceDetails +#define IXAudio2SourceVoice_SetChannelVolumes FAudioVoice_SetChannelVolumes +#define IXAudio2SourceVoice_SetSourceSampleRate FAudioSourceVoice_SetSourceSampleRate +#define IXAudio2SourceVoice_SetVolume FAudioVoice_SetVolume +#define IXAudio2SourceVoice_Start FAudioSourceVoice_Start +#define IXAudio2SourceVoice_Stop FAudioSourceVoice_Stop +#define IXAudio2SourceVoice_SubmitSourceBuffer FAudioSourceVoice_SubmitSourceBuffer + +typedef FAudioSubmixVoice IXAudio27SubmixVoice; +#define IXAudio27SubmixVoice_GetVoiceDetails FAudioVoice_GetVoiceDetails +#define IXAudio27SubmixVoice_DestroyVoice FAudioVoice_DestroyVoice + +typedef FAudioSubmixVoice IXAudio2SubmixVoice; +#define IXAudio2SubmixVoice_GetVoiceDetails FAudioVoice_GetVoiceDetails +#define IXAudio2SubmixVoice_DestroyVoice FAudioVoice_DestroyVoice diff --git a/src/include/KHR/khrplatform.h b/src/include/KHR/khrplatform.h index dd22d9270..01646449c 100644 --- a/src/include/KHR/khrplatform.h +++ b/src/include/KHR/khrplatform.h @@ -153,6 +153,20 @@ typedef int64_t khronos_int64_t; typedef uint64_t khronos_uint64_t; #define KHRONOS_SUPPORT_INT64 1 #define KHRONOS_SUPPORT_FLOAT 1 +/* + * To support platform where unsigned long cannot be used interchangeably with + * inptr_t (e.g. CHERI-extended ISAs), we can use the stdint.h intptr_t. + * Ideally, we could just use (u)intptr_t everywhere, but this could result in + * ABI breakage if khronos_uintptr_t is changed from unsigned long to + * unsigned long long or similar (this results in different C++ name mangling). + * To avoid changes for existing platforms, we restrict usage of intptr_t to + * platforms where the size of a pointer is larger than the size of long. + */ +#if defined(__SIZEOF_LONG__) && defined(__SIZEOF_POINTER__) +#if __SIZEOF_POINTER__ > __SIZEOF_LONG__ +#define KHRONOS_USE_INTPTR_T +#endif +#endif #elif defined(__VMS ) || defined(__sgi) @@ -235,14 +249,21 @@ typedef unsigned short int khronos_uint16_t; * pointers are 64 bits, but 'long' is still 32 bits. Win64 appears * to be the only LLP64 architecture in current use. */ -#ifdef _WIN64 +#ifdef KHRONOS_USE_INTPTR_T +typedef intptr_t khronos_intptr_t; +typedef uintptr_t khronos_uintptr_t; +#elif defined(_WIN64) typedef signed long long int khronos_intptr_t; typedef unsigned long long int khronos_uintptr_t; -typedef signed long long int khronos_ssize_t; -typedef unsigned long long int khronos_usize_t; #else typedef signed long int khronos_intptr_t; typedef unsigned long int khronos_uintptr_t; +#endif + +#if defined(_WIN64) +typedef signed long long int khronos_ssize_t; +typedef unsigned long long int khronos_usize_t; +#else typedef signed long int khronos_ssize_t; typedef unsigned long int khronos_usize_t; #endif diff --git a/src/include/discord_game_sdk.h b/src/include/discord_game_sdk.h index 50aa13736..0d3da6dea 100644 --- a/src/include/discord_game_sdk.h +++ b/src/include/discord_game_sdk.h @@ -1,4 +1,4 @@ -/* +/* * This file is distributed as a part of the Discord Game SDK. * Downloading, accessing, or using the API or SDK is bound by * the Discord Developer Terms of Service: @@ -8,6 +8,23 @@ #ifndef _DISCORD_GAME_SDK_H_ #define _DISCORD_GAME_SDK_H_ +#ifdef _WIN32 +#include +#include +#endif + +#ifdef _WIN32 +# ifdef _WIN64 +# define DISCORD_API +# else +# define DISCORD_API __stdcall +# endif +#else +# define DISCORD_API +#endif + +#define DISCORD_CALLBACK DISCORD_API + #ifdef __cplusplus extern "C" { #endif @@ -18,7 +35,7 @@ extern "C" { #include #endif -#define DISCORD_VERSION 2 +#define DISCORD_VERSION 3 #define DISCORD_APPLICATION_MANAGER_VERSION 1 #define DISCORD_USER_MANAGER_VERSION 1 #define DISCORD_IMAGE_MANAGER_VERSION 1 @@ -26,7 +43,7 @@ extern "C" { #define DISCORD_RELATIONSHIP_MANAGER_VERSION 1 #define DISCORD_LOBBY_MANAGER_VERSION 1 #define DISCORD_NETWORK_MANAGER_VERSION 1 -#define DISCORD_OVERLAY_MANAGER_VERSION 1 +#define DISCORD_OVERLAY_MANAGER_VERSION 2 #define DISCORD_STORAGE_MANAGER_VERSION 1 #define DISCORD_STORE_MANAGER_VERSION 1 #define DISCORD_VOICE_MANAGER_VERSION 1 @@ -77,6 +94,7 @@ enum EDiscordResult { DiscordResult_InvalidGiftCode = 41, DiscordResult_PurchaseError = 42, DiscordResult_TransactionAborted = 43, + DiscordResult_DrawingInitFailed = 44, }; enum EDiscordCreateFlags { @@ -109,6 +127,11 @@ enum EDiscordImageType { DiscordImageType_User, }; +enum EDiscordActivityPartyPrivacy { + DiscordActivityPartyPrivacy_Private = 0, + DiscordActivityPartyPrivacy_Public = 1, +}; + enum EDiscordActivityType { DiscordActivityType_Playing, DiscordActivityType_Streaming, @@ -121,6 +144,12 @@ enum EDiscordActivityActionType { DiscordActivityActionType_Spectate, }; +enum EDiscordActivitySupportedPlatformFlags { + DiscordActivitySupportedPlatformFlags_Desktop = 1, + DiscordActivitySupportedPlatformFlags_Android = 2, + DiscordActivitySupportedPlatformFlags_iOS = 4, +}; + enum EDiscordActivityJoinRequestReply { DiscordActivityJoinRequestReply_No, DiscordActivityJoinRequestReply_Yes, @@ -169,6 +198,18 @@ enum EDiscordLobbySearchDistance { DiscordLobbySearchDistance_Global, }; +enum EDiscordKeyVariant { + DiscordKeyVariant_Normal, + DiscordKeyVariant_Right, + DiscordKeyVariant_Left, +}; + +enum EDiscordMouseButton { + DiscordMouseButton_Left, + DiscordMouseButton_Middle, + DiscordMouseButton_Right, +}; + enum EDiscordEntitlementType { DiscordEntitlementType_Purchase = 1, DiscordEntitlementType_PremiumSubscription, @@ -204,6 +245,18 @@ typedef char DiscordMetadataKey[256]; typedef char DiscordMetadataValue[4096]; typedef uint64_t DiscordNetworkPeerId; typedef uint8_t DiscordNetworkChannelId; +#ifdef __APPLE__ +typedef void IDXGISwapChain; +#endif +#ifdef __linux__ +typedef void IDXGISwapChain; +#endif +#ifdef __APPLE__ +typedef void MSG; +#endif +#ifdef __linux__ +typedef void MSG; +#endif typedef char DiscordPath[4096]; typedef char DiscordDateTime[64]; @@ -252,6 +305,7 @@ struct DiscordPartySize { struct DiscordActivityParty { char id[128]; struct DiscordPartySize size; + enum EDiscordActivityPartyPrivacy privacy; }; struct DiscordActivitySecrets { @@ -271,6 +325,7 @@ struct DiscordActivity { struct DiscordActivityParty party; struct DiscordActivitySecrets secrets; bool instance; + uint32_t supported_platforms; }; struct DiscordPresence { @@ -293,6 +348,21 @@ struct DiscordLobby { bool locked; }; +struct DiscordImeUnderline { + int32_t from; + int32_t to; + uint32_t color; + uint32_t background_color; + bool thick; +}; + +struct DiscordRect { + int32_t left; + int32_t top; + int32_t right; + int32_t bottom; +}; + struct DiscordFileStat { char filename[260]; uint64_t size; @@ -330,265 +400,278 @@ struct DiscordUserAchievement { }; struct IDiscordLobbyTransaction { - enum EDiscordResult (*set_type)(struct IDiscordLobbyTransaction* lobby_transaction, enum EDiscordLobbyType type); - enum EDiscordResult (*set_owner)(struct IDiscordLobbyTransaction* lobby_transaction, DiscordUserId owner_id); - enum EDiscordResult (*set_capacity)(struct IDiscordLobbyTransaction* lobby_transaction, uint32_t capacity); - enum EDiscordResult (*set_metadata)(struct IDiscordLobbyTransaction* lobby_transaction, DiscordMetadataKey key, DiscordMetadataValue value); - enum EDiscordResult (*delete_metadata)(struct IDiscordLobbyTransaction* lobby_transaction, DiscordMetadataKey key); - enum EDiscordResult (*set_locked)(struct IDiscordLobbyTransaction* lobby_transaction, bool locked); + enum EDiscordResult (DISCORD_API *set_type)(struct IDiscordLobbyTransaction* lobby_transaction, enum EDiscordLobbyType type); + enum EDiscordResult (DISCORD_API *set_owner)(struct IDiscordLobbyTransaction* lobby_transaction, DiscordUserId owner_id); + enum EDiscordResult (DISCORD_API *set_capacity)(struct IDiscordLobbyTransaction* lobby_transaction, uint32_t capacity); + enum EDiscordResult (DISCORD_API *set_metadata)(struct IDiscordLobbyTransaction* lobby_transaction, DiscordMetadataKey key, DiscordMetadataValue value); + enum EDiscordResult (DISCORD_API *delete_metadata)(struct IDiscordLobbyTransaction* lobby_transaction, DiscordMetadataKey key); + enum EDiscordResult (DISCORD_API *set_locked)(struct IDiscordLobbyTransaction* lobby_transaction, bool locked); }; struct IDiscordLobbyMemberTransaction { - enum EDiscordResult (*set_metadata)(struct IDiscordLobbyMemberTransaction* lobby_member_transaction, DiscordMetadataKey key, DiscordMetadataValue value); - enum EDiscordResult (*delete_metadata)(struct IDiscordLobbyMemberTransaction* lobby_member_transaction, DiscordMetadataKey key); + enum EDiscordResult (DISCORD_API *set_metadata)(struct IDiscordLobbyMemberTransaction* lobby_member_transaction, DiscordMetadataKey key, DiscordMetadataValue value); + enum EDiscordResult (DISCORD_API *delete_metadata)(struct IDiscordLobbyMemberTransaction* lobby_member_transaction, DiscordMetadataKey key); }; struct IDiscordLobbySearchQuery { - enum EDiscordResult (*filter)(struct IDiscordLobbySearchQuery* lobby_search_query, DiscordMetadataKey key, enum EDiscordLobbySearchComparison comparison, enum EDiscordLobbySearchCast cast, DiscordMetadataValue value); - enum EDiscordResult (*sort)(struct IDiscordLobbySearchQuery* lobby_search_query, DiscordMetadataKey key, enum EDiscordLobbySearchCast cast, DiscordMetadataValue value); - enum EDiscordResult (*limit)(struct IDiscordLobbySearchQuery* lobby_search_query, uint32_t limit); - enum EDiscordResult (*distance)(struct IDiscordLobbySearchQuery* lobby_search_query, enum EDiscordLobbySearchDistance distance); + enum EDiscordResult (DISCORD_API *filter)(struct IDiscordLobbySearchQuery* lobby_search_query, DiscordMetadataKey key, enum EDiscordLobbySearchComparison comparison, enum EDiscordLobbySearchCast cast, DiscordMetadataValue value); + enum EDiscordResult (DISCORD_API *sort)(struct IDiscordLobbySearchQuery* lobby_search_query, DiscordMetadataKey key, enum EDiscordLobbySearchCast cast, DiscordMetadataValue value); + enum EDiscordResult (DISCORD_API *limit)(struct IDiscordLobbySearchQuery* lobby_search_query, uint32_t limit); + enum EDiscordResult (DISCORD_API *distance)(struct IDiscordLobbySearchQuery* lobby_search_query, enum EDiscordLobbySearchDistance distance); }; typedef void* IDiscordApplicationEvents; struct IDiscordApplicationManager { - void (*validate_or_exit)(struct IDiscordApplicationManager* manager, void* callback_data, void (*callback)(void* callback_data, enum EDiscordResult result)); - void (*get_current_locale)(struct IDiscordApplicationManager* manager, DiscordLocale* locale); - void (*get_current_branch)(struct IDiscordApplicationManager* manager, DiscordBranch* branch); - void (*get_oauth2_token)(struct IDiscordApplicationManager* manager, void* callback_data, void (*callback)(void* callback_data, enum EDiscordResult result, struct DiscordOAuth2Token* oauth2_token)); - void (*get_ticket)(struct IDiscordApplicationManager* manager, void* callback_data, void (*callback)(void* callback_data, enum EDiscordResult result, const char* data)); + void (DISCORD_API *validate_or_exit)(struct IDiscordApplicationManager* manager, void* callback_data, void (DISCORD_API *callback)(void* callback_data, enum EDiscordResult result)); + void (DISCORD_API *get_current_locale)(struct IDiscordApplicationManager* manager, DiscordLocale* locale); + void (DISCORD_API *get_current_branch)(struct IDiscordApplicationManager* manager, DiscordBranch* branch); + void (DISCORD_API *get_oauth2_token)(struct IDiscordApplicationManager* manager, void* callback_data, void (DISCORD_API *callback)(void* callback_data, enum EDiscordResult result, struct DiscordOAuth2Token* oauth2_token)); + void (DISCORD_API *get_ticket)(struct IDiscordApplicationManager* manager, void* callback_data, void (DISCORD_API *callback)(void* callback_data, enum EDiscordResult result, const char* data)); }; struct IDiscordUserEvents { - void (*on_current_user_update)(void* event_data); + void (DISCORD_API *on_current_user_update)(void* event_data); }; struct IDiscordUserManager { - enum EDiscordResult (*get_current_user)(struct IDiscordUserManager* manager, struct DiscordUser* current_user); - void (*get_user)(struct IDiscordUserManager* manager, DiscordUserId user_id, void* callback_data, void (*callback)(void* callback_data, enum EDiscordResult result, struct DiscordUser* user)); - enum EDiscordResult (*get_current_user_premium_type)(struct IDiscordUserManager* manager, enum EDiscordPremiumType* premium_type); - enum EDiscordResult (*current_user_has_flag)(struct IDiscordUserManager* manager, enum EDiscordUserFlag flag, bool* has_flag); + enum EDiscordResult (DISCORD_API *get_current_user)(struct IDiscordUserManager* manager, struct DiscordUser* current_user); + void (DISCORD_API *get_user)(struct IDiscordUserManager* manager, DiscordUserId user_id, void* callback_data, void (DISCORD_API *callback)(void* callback_data, enum EDiscordResult result, struct DiscordUser* user)); + enum EDiscordResult (DISCORD_API *get_current_user_premium_type)(struct IDiscordUserManager* manager, enum EDiscordPremiumType* premium_type); + enum EDiscordResult (DISCORD_API *current_user_has_flag)(struct IDiscordUserManager* manager, enum EDiscordUserFlag flag, bool* has_flag); }; typedef void* IDiscordImageEvents; struct IDiscordImageManager { - void (*fetch)(struct IDiscordImageManager* manager, struct DiscordImageHandle handle, bool refresh, void* callback_data, void (*callback)(void* callback_data, enum EDiscordResult result, struct DiscordImageHandle handle_result)); - enum EDiscordResult (*get_dimensions)(struct IDiscordImageManager* manager, struct DiscordImageHandle handle, struct DiscordImageDimensions* dimensions); - enum EDiscordResult (*get_data)(struct IDiscordImageManager* manager, struct DiscordImageHandle handle, uint8_t* data, uint32_t data_length); + void (DISCORD_API *fetch)(struct IDiscordImageManager* manager, struct DiscordImageHandle handle, bool refresh, void* callback_data, void (DISCORD_API *callback)(void* callback_data, enum EDiscordResult result, struct DiscordImageHandle handle_result)); + enum EDiscordResult (DISCORD_API *get_dimensions)(struct IDiscordImageManager* manager, struct DiscordImageHandle handle, struct DiscordImageDimensions* dimensions); + enum EDiscordResult (DISCORD_API *get_data)(struct IDiscordImageManager* manager, struct DiscordImageHandle handle, uint8_t* data, uint32_t data_length); }; struct IDiscordActivityEvents { - void (*on_activity_join)(void* event_data, const char* secret); - void (*on_activity_spectate)(void* event_data, const char* secret); - void (*on_activity_join_request)(void* event_data, struct DiscordUser* user); - void (*on_activity_invite)(void* event_data, enum EDiscordActivityActionType type, struct DiscordUser* user, struct DiscordActivity* activity); + void (DISCORD_API *on_activity_join)(void* event_data, const char* secret); + void (DISCORD_API *on_activity_spectate)(void* event_data, const char* secret); + void (DISCORD_API *on_activity_join_request)(void* event_data, struct DiscordUser* user); + void (DISCORD_API *on_activity_invite)(void* event_data, enum EDiscordActivityActionType type, struct DiscordUser* user, struct DiscordActivity* activity); }; struct IDiscordActivityManager { - enum EDiscordResult (*register_command)(struct IDiscordActivityManager* manager, const char* command); - enum EDiscordResult (*register_steam)(struct IDiscordActivityManager* manager, uint32_t steam_id); - void (*update_activity)(struct IDiscordActivityManager* manager, struct DiscordActivity* activity, void* callback_data, void (*callback)(void* callback_data, enum EDiscordResult result)); - void (*clear_activity)(struct IDiscordActivityManager* manager, void* callback_data, void (*callback)(void* callback_data, enum EDiscordResult result)); - void (*send_request_reply)(struct IDiscordActivityManager* manager, DiscordUserId user_id, enum EDiscordActivityJoinRequestReply reply, void* callback_data, void (*callback)(void* callback_data, enum EDiscordResult result)); - void (*send_invite)(struct IDiscordActivityManager* manager, DiscordUserId user_id, enum EDiscordActivityActionType type, const char* content, void* callback_data, void (*callback)(void* callback_data, enum EDiscordResult result)); - void (*accept_invite)(struct IDiscordActivityManager* manager, DiscordUserId user_id, void* callback_data, void (*callback)(void* callback_data, enum EDiscordResult result)); + enum EDiscordResult (DISCORD_API *register_command)(struct IDiscordActivityManager* manager, const char* command); + enum EDiscordResult (DISCORD_API *register_steam)(struct IDiscordActivityManager* manager, uint32_t steam_id); + void (DISCORD_API *update_activity)(struct IDiscordActivityManager* manager, struct DiscordActivity* activity, void* callback_data, void (DISCORD_API *callback)(void* callback_data, enum EDiscordResult result)); + void (DISCORD_API *clear_activity)(struct IDiscordActivityManager* manager, void* callback_data, void (DISCORD_API *callback)(void* callback_data, enum EDiscordResult result)); + void (DISCORD_API *send_request_reply)(struct IDiscordActivityManager* manager, DiscordUserId user_id, enum EDiscordActivityJoinRequestReply reply, void* callback_data, void (DISCORD_API *callback)(void* callback_data, enum EDiscordResult result)); + void (DISCORD_API *send_invite)(struct IDiscordActivityManager* manager, DiscordUserId user_id, enum EDiscordActivityActionType type, const char* content, void* callback_data, void (DISCORD_API *callback)(void* callback_data, enum EDiscordResult result)); + void (DISCORD_API *accept_invite)(struct IDiscordActivityManager* manager, DiscordUserId user_id, void* callback_data, void (DISCORD_API *callback)(void* callback_data, enum EDiscordResult result)); }; struct IDiscordRelationshipEvents { - void (*on_refresh)(void* event_data); - void (*on_relationship_update)(void* event_data, struct DiscordRelationship* relationship); + void (DISCORD_API *on_refresh)(void* event_data); + void (DISCORD_API *on_relationship_update)(void* event_data, struct DiscordRelationship* relationship); }; struct IDiscordRelationshipManager { - void (*filter)(struct IDiscordRelationshipManager* manager, void* filter_data, bool (*filter)(void* filter_data, struct DiscordRelationship* relationship)); - enum EDiscordResult (*count)(struct IDiscordRelationshipManager* manager, int32_t* count); - enum EDiscordResult (*get)(struct IDiscordRelationshipManager* manager, DiscordUserId user_id, struct DiscordRelationship* relationship); - enum EDiscordResult (*get_at)(struct IDiscordRelationshipManager* manager, uint32_t index, struct DiscordRelationship* relationship); + void (DISCORD_API *filter)(struct IDiscordRelationshipManager* manager, void* filter_data, bool (DISCORD_API *filter)(void* filter_data, struct DiscordRelationship* relationship)); + enum EDiscordResult (DISCORD_API *count)(struct IDiscordRelationshipManager* manager, int32_t* count); + enum EDiscordResult (DISCORD_API *get)(struct IDiscordRelationshipManager* manager, DiscordUserId user_id, struct DiscordRelationship* relationship); + enum EDiscordResult (DISCORD_API *get_at)(struct IDiscordRelationshipManager* manager, uint32_t index, struct DiscordRelationship* relationship); }; struct IDiscordLobbyEvents { - void (*on_lobby_update)(void* event_data, int64_t lobby_id); - void (*on_lobby_delete)(void* event_data, int64_t lobby_id, uint32_t reason); - void (*on_member_connect)(void* event_data, int64_t lobby_id, int64_t user_id); - void (*on_member_update)(void* event_data, int64_t lobby_id, int64_t user_id); - void (*on_member_disconnect)(void* event_data, int64_t lobby_id, int64_t user_id); - void (*on_lobby_message)(void* event_data, int64_t lobby_id, int64_t user_id, uint8_t* data, uint32_t data_length); - void (*on_speaking)(void* event_data, int64_t lobby_id, int64_t user_id, bool speaking); - void (*on_network_message)(void* event_data, int64_t lobby_id, int64_t user_id, uint8_t channel_id, uint8_t* data, uint32_t data_length); + void (DISCORD_API *on_lobby_update)(void* event_data, int64_t lobby_id); + void (DISCORD_API *on_lobby_delete)(void* event_data, int64_t lobby_id, uint32_t reason); + void (DISCORD_API *on_member_connect)(void* event_data, int64_t lobby_id, int64_t user_id); + void (DISCORD_API *on_member_update)(void* event_data, int64_t lobby_id, int64_t user_id); + void (DISCORD_API *on_member_disconnect)(void* event_data, int64_t lobby_id, int64_t user_id); + void (DISCORD_API *on_lobby_message)(void* event_data, int64_t lobby_id, int64_t user_id, uint8_t* data, uint32_t data_length); + void (DISCORD_API *on_speaking)(void* event_data, int64_t lobby_id, int64_t user_id, bool speaking); + void (DISCORD_API *on_network_message)(void* event_data, int64_t lobby_id, int64_t user_id, uint8_t channel_id, uint8_t* data, uint32_t data_length); }; struct IDiscordLobbyManager { - enum EDiscordResult (*get_lobby_create_transaction)(struct IDiscordLobbyManager* manager, struct IDiscordLobbyTransaction** transaction); - enum EDiscordResult (*get_lobby_update_transaction)(struct IDiscordLobbyManager* manager, DiscordLobbyId lobby_id, struct IDiscordLobbyTransaction** transaction); - enum EDiscordResult (*get_member_update_transaction)(struct IDiscordLobbyManager* manager, DiscordLobbyId lobby_id, DiscordUserId user_id, struct IDiscordLobbyMemberTransaction** transaction); - void (*create_lobby)(struct IDiscordLobbyManager* manager, struct IDiscordLobbyTransaction* transaction, void* callback_data, void (*callback)(void* callback_data, enum EDiscordResult result, struct DiscordLobby* lobby)); - void (*update_lobby)(struct IDiscordLobbyManager* manager, DiscordLobbyId lobby_id, struct IDiscordLobbyTransaction* transaction, void* callback_data, void (*callback)(void* callback_data, enum EDiscordResult result)); - void (*delete_lobby)(struct IDiscordLobbyManager* manager, DiscordLobbyId lobby_id, void* callback_data, void (*callback)(void* callback_data, enum EDiscordResult result)); - void (*connect_lobby)(struct IDiscordLobbyManager* manager, DiscordLobbyId lobby_id, DiscordLobbySecret secret, void* callback_data, void (*callback)(void* callback_data, enum EDiscordResult result, struct DiscordLobby* lobby)); - void (*connect_lobby_with_activity_secret)(struct IDiscordLobbyManager* manager, DiscordLobbySecret activity_secret, void* callback_data, void (*callback)(void* callback_data, enum EDiscordResult result, struct DiscordLobby* lobby)); - void (*disconnect_lobby)(struct IDiscordLobbyManager* manager, DiscordLobbyId lobby_id, void* callback_data, void (*callback)(void* callback_data, enum EDiscordResult result)); - enum EDiscordResult (*get_lobby)(struct IDiscordLobbyManager* manager, DiscordLobbyId lobby_id, struct DiscordLobby* lobby); - enum EDiscordResult (*get_lobby_activity_secret)(struct IDiscordLobbyManager* manager, DiscordLobbyId lobby_id, DiscordLobbySecret* secret); - enum EDiscordResult (*get_lobby_metadata_value)(struct IDiscordLobbyManager* manager, DiscordLobbyId lobby_id, DiscordMetadataKey key, DiscordMetadataValue* value); - enum EDiscordResult (*get_lobby_metadata_key)(struct IDiscordLobbyManager* manager, DiscordLobbyId lobby_id, int32_t index, DiscordMetadataKey* key); - enum EDiscordResult (*lobby_metadata_count)(struct IDiscordLobbyManager* manager, DiscordLobbyId lobby_id, int32_t* count); - enum EDiscordResult (*member_count)(struct IDiscordLobbyManager* manager, DiscordLobbyId lobby_id, int32_t* count); - enum EDiscordResult (*get_member_user_id)(struct IDiscordLobbyManager* manager, DiscordLobbyId lobby_id, int32_t index, DiscordUserId* user_id); - enum EDiscordResult (*get_member_user)(struct IDiscordLobbyManager* manager, DiscordLobbyId lobby_id, DiscordUserId user_id, struct DiscordUser* user); - enum EDiscordResult (*get_member_metadata_value)(struct IDiscordLobbyManager* manager, DiscordLobbyId lobby_id, DiscordUserId user_id, DiscordMetadataKey key, DiscordMetadataValue* value); - enum EDiscordResult (*get_member_metadata_key)(struct IDiscordLobbyManager* manager, DiscordLobbyId lobby_id, DiscordUserId user_id, int32_t index, DiscordMetadataKey* key); - enum EDiscordResult (*member_metadata_count)(struct IDiscordLobbyManager* manager, DiscordLobbyId lobby_id, DiscordUserId user_id, int32_t* count); - void (*update_member)(struct IDiscordLobbyManager* manager, DiscordLobbyId lobby_id, DiscordUserId user_id, struct IDiscordLobbyMemberTransaction* transaction, void* callback_data, void (*callback)(void* callback_data, enum EDiscordResult result)); - void (*send_lobby_message)(struct IDiscordLobbyManager* manager, DiscordLobbyId lobby_id, uint8_t* data, uint32_t data_length, void* callback_data, void (*callback)(void* callback_data, enum EDiscordResult result)); - enum EDiscordResult (*get_search_query)(struct IDiscordLobbyManager* manager, struct IDiscordLobbySearchQuery** query); - void (*search)(struct IDiscordLobbyManager* manager, struct IDiscordLobbySearchQuery* query, void* callback_data, void (*callback)(void* callback_data, enum EDiscordResult result)); - void (*lobby_count)(struct IDiscordLobbyManager* manager, int32_t* count); - enum EDiscordResult (*get_lobby_id)(struct IDiscordLobbyManager* manager, int32_t index, DiscordLobbyId* lobby_id); - void (*connect_voice)(struct IDiscordLobbyManager* manager, DiscordLobbyId lobby_id, void* callback_data, void (*callback)(void* callback_data, enum EDiscordResult result)); - void (*disconnect_voice)(struct IDiscordLobbyManager* manager, DiscordLobbyId lobby_id, void* callback_data, void (*callback)(void* callback_data, enum EDiscordResult result)); - enum EDiscordResult (*connect_network)(struct IDiscordLobbyManager* manager, DiscordLobbyId lobby_id); - enum EDiscordResult (*disconnect_network)(struct IDiscordLobbyManager* manager, DiscordLobbyId lobby_id); - enum EDiscordResult (*flush_network)(struct IDiscordLobbyManager* manager); - enum EDiscordResult (*open_network_channel)(struct IDiscordLobbyManager* manager, DiscordLobbyId lobby_id, uint8_t channel_id, bool reliable); - enum EDiscordResult (*send_network_message)(struct IDiscordLobbyManager* manager, DiscordLobbyId lobby_id, DiscordUserId user_id, uint8_t channel_id, uint8_t* data, uint32_t data_length); + enum EDiscordResult (DISCORD_API *get_lobby_create_transaction)(struct IDiscordLobbyManager* manager, struct IDiscordLobbyTransaction** transaction); + enum EDiscordResult (DISCORD_API *get_lobby_update_transaction)(struct IDiscordLobbyManager* manager, DiscordLobbyId lobby_id, struct IDiscordLobbyTransaction** transaction); + enum EDiscordResult (DISCORD_API *get_member_update_transaction)(struct IDiscordLobbyManager* manager, DiscordLobbyId lobby_id, DiscordUserId user_id, struct IDiscordLobbyMemberTransaction** transaction); + void (DISCORD_API *create_lobby)(struct IDiscordLobbyManager* manager, struct IDiscordLobbyTransaction* transaction, void* callback_data, void (DISCORD_API *callback)(void* callback_data, enum EDiscordResult result, struct DiscordLobby* lobby)); + void (DISCORD_API *update_lobby)(struct IDiscordLobbyManager* manager, DiscordLobbyId lobby_id, struct IDiscordLobbyTransaction* transaction, void* callback_data, void (DISCORD_API *callback)(void* callback_data, enum EDiscordResult result)); + void (DISCORD_API *delete_lobby)(struct IDiscordLobbyManager* manager, DiscordLobbyId lobby_id, void* callback_data, void (DISCORD_API *callback)(void* callback_data, enum EDiscordResult result)); + void (DISCORD_API *connect_lobby)(struct IDiscordLobbyManager* manager, DiscordLobbyId lobby_id, DiscordLobbySecret secret, void* callback_data, void (DISCORD_API *callback)(void* callback_data, enum EDiscordResult result, struct DiscordLobby* lobby)); + void (DISCORD_API *connect_lobby_with_activity_secret)(struct IDiscordLobbyManager* manager, DiscordLobbySecret activity_secret, void* callback_data, void (DISCORD_API *callback)(void* callback_data, enum EDiscordResult result, struct DiscordLobby* lobby)); + void (DISCORD_API *disconnect_lobby)(struct IDiscordLobbyManager* manager, DiscordLobbyId lobby_id, void* callback_data, void (DISCORD_API *callback)(void* callback_data, enum EDiscordResult result)); + enum EDiscordResult (DISCORD_API *get_lobby)(struct IDiscordLobbyManager* manager, DiscordLobbyId lobby_id, struct DiscordLobby* lobby); + enum EDiscordResult (DISCORD_API *get_lobby_activity_secret)(struct IDiscordLobbyManager* manager, DiscordLobbyId lobby_id, DiscordLobbySecret* secret); + enum EDiscordResult (DISCORD_API *get_lobby_metadata_value)(struct IDiscordLobbyManager* manager, DiscordLobbyId lobby_id, DiscordMetadataKey key, DiscordMetadataValue* value); + enum EDiscordResult (DISCORD_API *get_lobby_metadata_key)(struct IDiscordLobbyManager* manager, DiscordLobbyId lobby_id, int32_t index, DiscordMetadataKey* key); + enum EDiscordResult (DISCORD_API *lobby_metadata_count)(struct IDiscordLobbyManager* manager, DiscordLobbyId lobby_id, int32_t* count); + enum EDiscordResult (DISCORD_API *member_count)(struct IDiscordLobbyManager* manager, DiscordLobbyId lobby_id, int32_t* count); + enum EDiscordResult (DISCORD_API *get_member_user_id)(struct IDiscordLobbyManager* manager, DiscordLobbyId lobby_id, int32_t index, DiscordUserId* user_id); + enum EDiscordResult (DISCORD_API *get_member_user)(struct IDiscordLobbyManager* manager, DiscordLobbyId lobby_id, DiscordUserId user_id, struct DiscordUser* user); + enum EDiscordResult (DISCORD_API *get_member_metadata_value)(struct IDiscordLobbyManager* manager, DiscordLobbyId lobby_id, DiscordUserId user_id, DiscordMetadataKey key, DiscordMetadataValue* value); + enum EDiscordResult (DISCORD_API *get_member_metadata_key)(struct IDiscordLobbyManager* manager, DiscordLobbyId lobby_id, DiscordUserId user_id, int32_t index, DiscordMetadataKey* key); + enum EDiscordResult (DISCORD_API *member_metadata_count)(struct IDiscordLobbyManager* manager, DiscordLobbyId lobby_id, DiscordUserId user_id, int32_t* count); + void (DISCORD_API *update_member)(struct IDiscordLobbyManager* manager, DiscordLobbyId lobby_id, DiscordUserId user_id, struct IDiscordLobbyMemberTransaction* transaction, void* callback_data, void (DISCORD_API *callback)(void* callback_data, enum EDiscordResult result)); + void (DISCORD_API *send_lobby_message)(struct IDiscordLobbyManager* manager, DiscordLobbyId lobby_id, uint8_t* data, uint32_t data_length, void* callback_data, void (DISCORD_API *callback)(void* callback_data, enum EDiscordResult result)); + enum EDiscordResult (DISCORD_API *get_search_query)(struct IDiscordLobbyManager* manager, struct IDiscordLobbySearchQuery** query); + void (DISCORD_API *search)(struct IDiscordLobbyManager* manager, struct IDiscordLobbySearchQuery* query, void* callback_data, void (DISCORD_API *callback)(void* callback_data, enum EDiscordResult result)); + void (DISCORD_API *lobby_count)(struct IDiscordLobbyManager* manager, int32_t* count); + enum EDiscordResult (DISCORD_API *get_lobby_id)(struct IDiscordLobbyManager* manager, int32_t index, DiscordLobbyId* lobby_id); + void (DISCORD_API *connect_voice)(struct IDiscordLobbyManager* manager, DiscordLobbyId lobby_id, void* callback_data, void (DISCORD_API *callback)(void* callback_data, enum EDiscordResult result)); + void (DISCORD_API *disconnect_voice)(struct IDiscordLobbyManager* manager, DiscordLobbyId lobby_id, void* callback_data, void (DISCORD_API *callback)(void* callback_data, enum EDiscordResult result)); + enum EDiscordResult (DISCORD_API *connect_network)(struct IDiscordLobbyManager* manager, DiscordLobbyId lobby_id); + enum EDiscordResult (DISCORD_API *disconnect_network)(struct IDiscordLobbyManager* manager, DiscordLobbyId lobby_id); + enum EDiscordResult (DISCORD_API *flush_network)(struct IDiscordLobbyManager* manager); + enum EDiscordResult (DISCORD_API *open_network_channel)(struct IDiscordLobbyManager* manager, DiscordLobbyId lobby_id, uint8_t channel_id, bool reliable); + enum EDiscordResult (DISCORD_API *send_network_message)(struct IDiscordLobbyManager* manager, DiscordLobbyId lobby_id, DiscordUserId user_id, uint8_t channel_id, uint8_t* data, uint32_t data_length); }; struct IDiscordNetworkEvents { - void (*on_message)(void* event_data, DiscordNetworkPeerId peer_id, DiscordNetworkChannelId channel_id, uint8_t* data, uint32_t data_length); - void (*on_route_update)(void* event_data, const char* route_data); + void (DISCORD_API *on_message)(void* event_data, DiscordNetworkPeerId peer_id, DiscordNetworkChannelId channel_id, uint8_t* data, uint32_t data_length); + void (DISCORD_API *on_route_update)(void* event_data, const char* route_data); }; struct IDiscordNetworkManager { /** * Get the local peer ID for this process. */ - void (*get_peer_id)(struct IDiscordNetworkManager* manager, DiscordNetworkPeerId* peer_id); + void (DISCORD_API *get_peer_id)(struct IDiscordNetworkManager* manager, DiscordNetworkPeerId* peer_id); /** * Send pending network messages. */ - enum EDiscordResult (*flush)(struct IDiscordNetworkManager* manager); + enum EDiscordResult (DISCORD_API *flush)(struct IDiscordNetworkManager* manager); /** * Open a connection to a remote peer. */ - enum EDiscordResult (*open_peer)(struct IDiscordNetworkManager* manager, DiscordNetworkPeerId peer_id, const char* route_data); + enum EDiscordResult (DISCORD_API *open_peer)(struct IDiscordNetworkManager* manager, DiscordNetworkPeerId peer_id, const char* route_data); /** * Update the route data for a connected peer. */ - enum EDiscordResult (*update_peer)(struct IDiscordNetworkManager* manager, DiscordNetworkPeerId peer_id, const char* route_data); + enum EDiscordResult (DISCORD_API *update_peer)(struct IDiscordNetworkManager* manager, DiscordNetworkPeerId peer_id, const char* route_data); /** * Close the connection to a remote peer. */ - enum EDiscordResult (*close_peer)(struct IDiscordNetworkManager* manager, DiscordNetworkPeerId peer_id); + enum EDiscordResult (DISCORD_API *close_peer)(struct IDiscordNetworkManager* manager, DiscordNetworkPeerId peer_id); /** * Open a message channel to a connected peer. */ - enum EDiscordResult (*open_channel)(struct IDiscordNetworkManager* manager, DiscordNetworkPeerId peer_id, DiscordNetworkChannelId channel_id, bool reliable); + enum EDiscordResult (DISCORD_API *open_channel)(struct IDiscordNetworkManager* manager, DiscordNetworkPeerId peer_id, DiscordNetworkChannelId channel_id, bool reliable); /** * Close a message channel to a connected peer. */ - enum EDiscordResult (*close_channel)(struct IDiscordNetworkManager* manager, DiscordNetworkPeerId peer_id, DiscordNetworkChannelId channel_id); + enum EDiscordResult (DISCORD_API *close_channel)(struct IDiscordNetworkManager* manager, DiscordNetworkPeerId peer_id, DiscordNetworkChannelId channel_id); /** * Send a message to a connected peer over an opened message channel. */ - enum EDiscordResult (*send_message)(struct IDiscordNetworkManager* manager, DiscordNetworkPeerId peer_id, DiscordNetworkChannelId channel_id, uint8_t* data, uint32_t data_length); + enum EDiscordResult (DISCORD_API *send_message)(struct IDiscordNetworkManager* manager, DiscordNetworkPeerId peer_id, DiscordNetworkChannelId channel_id, uint8_t* data, uint32_t data_length); }; struct IDiscordOverlayEvents { - void (*on_toggle)(void* event_data, bool locked); + void (DISCORD_API *on_toggle)(void* event_data, bool locked); }; struct IDiscordOverlayManager { - void (*is_enabled)(struct IDiscordOverlayManager* manager, bool* enabled); - void (*is_locked)(struct IDiscordOverlayManager* manager, bool* locked); - void (*set_locked)(struct IDiscordOverlayManager* manager, bool locked, void* callback_data, void (*callback)(void* callback_data, enum EDiscordResult result)); - void (*open_activity_invite)(struct IDiscordOverlayManager* manager, enum EDiscordActivityActionType type, void* callback_data, void (*callback)(void* callback_data, enum EDiscordResult result)); - void (*open_guild_invite)(struct IDiscordOverlayManager* manager, const char* code, void* callback_data, void (*callback)(void* callback_data, enum EDiscordResult result)); - void (*open_voice_settings)(struct IDiscordOverlayManager* manager, void* callback_data, void (*callback)(void* callback_data, enum EDiscordResult result)); + void (DISCORD_API *is_enabled)(struct IDiscordOverlayManager* manager, bool* enabled); + void (DISCORD_API *is_locked)(struct IDiscordOverlayManager* manager, bool* locked); + void (DISCORD_API *set_locked)(struct IDiscordOverlayManager* manager, bool locked, void* callback_data, void (DISCORD_API *callback)(void* callback_data, enum EDiscordResult result)); + void (DISCORD_API *open_activity_invite)(struct IDiscordOverlayManager* manager, enum EDiscordActivityActionType type, void* callback_data, void (DISCORD_API *callback)(void* callback_data, enum EDiscordResult result)); + void (DISCORD_API *open_guild_invite)(struct IDiscordOverlayManager* manager, const char* code, void* callback_data, void (DISCORD_API *callback)(void* callback_data, enum EDiscordResult result)); + void (DISCORD_API *open_voice_settings)(struct IDiscordOverlayManager* manager, void* callback_data, void (DISCORD_API *callback)(void* callback_data, enum EDiscordResult result)); + enum EDiscordResult (DISCORD_API *init_drawing_dxgi)(struct IDiscordOverlayManager* manager, IDXGISwapChain* swapchain, bool use_message_forwarding); + void (DISCORD_API *on_present)(struct IDiscordOverlayManager* manager); + void (DISCORD_API *forward_message)(struct IDiscordOverlayManager* manager, MSG* message); + void (DISCORD_API *key_event)(struct IDiscordOverlayManager* manager, bool down, const char* key_code, enum EDiscordKeyVariant variant); + void (DISCORD_API *char_event)(struct IDiscordOverlayManager* manager, const char* character); + void (DISCORD_API *mouse_button_event)(struct IDiscordOverlayManager* manager, uint8_t down, int32_t click_count, enum EDiscordMouseButton which, int32_t x, int32_t y); + void (DISCORD_API *mouse_motion_event)(struct IDiscordOverlayManager* manager, int32_t x, int32_t y); + void (DISCORD_API *ime_commit_text)(struct IDiscordOverlayManager* manager, const char* text); + void (DISCORD_API *ime_set_composition)(struct IDiscordOverlayManager* manager, const char* text, struct DiscordImeUnderline* underlines, uint32_t underlines_length, int32_t from, int32_t to); + void (DISCORD_API *ime_cancel_composition)(struct IDiscordOverlayManager* manager); + void (DISCORD_API *set_ime_composition_range_callback)(struct IDiscordOverlayManager* manager, void* on_ime_composition_range_changed_data, void (DISCORD_API *on_ime_composition_range_changed)(void* on_ime_composition_range_changed_data, int32_t from, int32_t to, struct DiscordRect* bounds, uint32_t bounds_length)); + void (DISCORD_API *set_ime_selection_bounds_callback)(struct IDiscordOverlayManager* manager, void* on_ime_selection_bounds_changed_data, void (DISCORD_API *on_ime_selection_bounds_changed)(void* on_ime_selection_bounds_changed_data, struct DiscordRect anchor, struct DiscordRect focus, bool is_anchor_first)); + bool (DISCORD_API *is_point_inside_click_zone)(struct IDiscordOverlayManager* manager, int32_t x, int32_t y); }; typedef void* IDiscordStorageEvents; struct IDiscordStorageManager { - enum EDiscordResult (*read)(struct IDiscordStorageManager* manager, const char* name, uint8_t* data, uint32_t data_length, uint32_t* read); - void (*read_async)(struct IDiscordStorageManager* manager, const char* name, void* callback_data, void (*callback)(void* callback_data, enum EDiscordResult result, uint8_t* data, uint32_t data_length)); - void (*read_async_partial)(struct IDiscordStorageManager* manager, const char* name, uint64_t offset, uint64_t length, void* callback_data, void (*callback)(void* callback_data, enum EDiscordResult result, uint8_t* data, uint32_t data_length)); - enum EDiscordResult (*write)(struct IDiscordStorageManager* manager, const char* name, uint8_t* data, uint32_t data_length); - void (*write_async)(struct IDiscordStorageManager* manager, const char* name, uint8_t* data, uint32_t data_length, void* callback_data, void (*callback)(void* callback_data, enum EDiscordResult result)); - enum EDiscordResult (*delete_)(struct IDiscordStorageManager* manager, const char* name); - enum EDiscordResult (*exists)(struct IDiscordStorageManager* manager, const char* name, bool* exists); - void (*count)(struct IDiscordStorageManager* manager, int32_t* count); - enum EDiscordResult (*stat)(struct IDiscordStorageManager* manager, const char* name, struct DiscordFileStat* stat); - enum EDiscordResult (*stat_at)(struct IDiscordStorageManager* manager, int32_t index, struct DiscordFileStat* stat); - enum EDiscordResult (*get_path)(struct IDiscordStorageManager* manager, DiscordPath* path); + enum EDiscordResult (DISCORD_API *read)(struct IDiscordStorageManager* manager, const char* name, uint8_t* data, uint32_t data_length, uint32_t* read); + void (DISCORD_API *read_async)(struct IDiscordStorageManager* manager, const char* name, void* callback_data, void (DISCORD_API *callback)(void* callback_data, enum EDiscordResult result, uint8_t* data, uint32_t data_length)); + void (DISCORD_API *read_async_partial)(struct IDiscordStorageManager* manager, const char* name, uint64_t offset, uint64_t length, void* callback_data, void (DISCORD_API *callback)(void* callback_data, enum EDiscordResult result, uint8_t* data, uint32_t data_length)); + enum EDiscordResult (DISCORD_API *write)(struct IDiscordStorageManager* manager, const char* name, uint8_t* data, uint32_t data_length); + void (DISCORD_API *write_async)(struct IDiscordStorageManager* manager, const char* name, uint8_t* data, uint32_t data_length, void* callback_data, void (DISCORD_API *callback)(void* callback_data, enum EDiscordResult result)); + enum EDiscordResult (DISCORD_API *delete_)(struct IDiscordStorageManager* manager, const char* name); + enum EDiscordResult (DISCORD_API *exists)(struct IDiscordStorageManager* manager, const char* name, bool* exists); + void (DISCORD_API *count)(struct IDiscordStorageManager* manager, int32_t* count); + enum EDiscordResult (DISCORD_API *stat)(struct IDiscordStorageManager* manager, const char* name, struct DiscordFileStat* stat); + enum EDiscordResult (DISCORD_API *stat_at)(struct IDiscordStorageManager* manager, int32_t index, struct DiscordFileStat* stat); + enum EDiscordResult (DISCORD_API *get_path)(struct IDiscordStorageManager* manager, DiscordPath* path); }; struct IDiscordStoreEvents { - void (*on_entitlement_create)(void* event_data, struct DiscordEntitlement* entitlement); - void (*on_entitlement_delete)(void* event_data, struct DiscordEntitlement* entitlement); + void (DISCORD_API *on_entitlement_create)(void* event_data, struct DiscordEntitlement* entitlement); + void (DISCORD_API *on_entitlement_delete)(void* event_data, struct DiscordEntitlement* entitlement); }; struct IDiscordStoreManager { - void (*fetch_skus)(struct IDiscordStoreManager* manager, void* callback_data, void (*callback)(void* callback_data, enum EDiscordResult result)); - void (*count_skus)(struct IDiscordStoreManager* manager, int32_t* count); - enum EDiscordResult (*get_sku)(struct IDiscordStoreManager* manager, DiscordSnowflake sku_id, struct DiscordSku* sku); - enum EDiscordResult (*get_sku_at)(struct IDiscordStoreManager* manager, int32_t index, struct DiscordSku* sku); - void (*fetch_entitlements)(struct IDiscordStoreManager* manager, void* callback_data, void (*callback)(void* callback_data, enum EDiscordResult result)); - void (*count_entitlements)(struct IDiscordStoreManager* manager, int32_t* count); - enum EDiscordResult (*get_entitlement)(struct IDiscordStoreManager* manager, DiscordSnowflake entitlement_id, struct DiscordEntitlement* entitlement); - enum EDiscordResult (*get_entitlement_at)(struct IDiscordStoreManager* manager, int32_t index, struct DiscordEntitlement* entitlement); - enum EDiscordResult (*has_sku_entitlement)(struct IDiscordStoreManager* manager, DiscordSnowflake sku_id, bool* has_entitlement); - void (*start_purchase)(struct IDiscordStoreManager* manager, DiscordSnowflake sku_id, void* callback_data, void (*callback)(void* callback_data, enum EDiscordResult result)); + void (DISCORD_API *fetch_skus)(struct IDiscordStoreManager* manager, void* callback_data, void (DISCORD_API *callback)(void* callback_data, enum EDiscordResult result)); + void (DISCORD_API *count_skus)(struct IDiscordStoreManager* manager, int32_t* count); + enum EDiscordResult (DISCORD_API *get_sku)(struct IDiscordStoreManager* manager, DiscordSnowflake sku_id, struct DiscordSku* sku); + enum EDiscordResult (DISCORD_API *get_sku_at)(struct IDiscordStoreManager* manager, int32_t index, struct DiscordSku* sku); + void (DISCORD_API *fetch_entitlements)(struct IDiscordStoreManager* manager, void* callback_data, void (DISCORD_API *callback)(void* callback_data, enum EDiscordResult result)); + void (DISCORD_API *count_entitlements)(struct IDiscordStoreManager* manager, int32_t* count); + enum EDiscordResult (DISCORD_API *get_entitlement)(struct IDiscordStoreManager* manager, DiscordSnowflake entitlement_id, struct DiscordEntitlement* entitlement); + enum EDiscordResult (DISCORD_API *get_entitlement_at)(struct IDiscordStoreManager* manager, int32_t index, struct DiscordEntitlement* entitlement); + enum EDiscordResult (DISCORD_API *has_sku_entitlement)(struct IDiscordStoreManager* manager, DiscordSnowflake sku_id, bool* has_entitlement); + void (DISCORD_API *start_purchase)(struct IDiscordStoreManager* manager, DiscordSnowflake sku_id, void* callback_data, void (DISCORD_API *callback)(void* callback_data, enum EDiscordResult result)); }; struct IDiscordVoiceEvents { - void (*on_settings_update)(void* event_data); + void (DISCORD_API *on_settings_update)(void* event_data); }; struct IDiscordVoiceManager { - enum EDiscordResult (*get_input_mode)(struct IDiscordVoiceManager* manager, struct DiscordInputMode* input_mode); - void (*set_input_mode)(struct IDiscordVoiceManager* manager, struct DiscordInputMode input_mode, void* callback_data, void (*callback)(void* callback_data, enum EDiscordResult result)); - enum EDiscordResult (*is_self_mute)(struct IDiscordVoiceManager* manager, bool* mute); - enum EDiscordResult (*set_self_mute)(struct IDiscordVoiceManager* manager, bool mute); - enum EDiscordResult (*is_self_deaf)(struct IDiscordVoiceManager* manager, bool* deaf); - enum EDiscordResult (*set_self_deaf)(struct IDiscordVoiceManager* manager, bool deaf); - enum EDiscordResult (*is_local_mute)(struct IDiscordVoiceManager* manager, DiscordSnowflake user_id, bool* mute); - enum EDiscordResult (*set_local_mute)(struct IDiscordVoiceManager* manager, DiscordSnowflake user_id, bool mute); - enum EDiscordResult (*get_local_volume)(struct IDiscordVoiceManager* manager, DiscordSnowflake user_id, uint8_t* volume); - enum EDiscordResult (*set_local_volume)(struct IDiscordVoiceManager* manager, DiscordSnowflake user_id, uint8_t volume); + enum EDiscordResult (DISCORD_API *get_input_mode)(struct IDiscordVoiceManager* manager, struct DiscordInputMode* input_mode); + void (DISCORD_API *set_input_mode)(struct IDiscordVoiceManager* manager, struct DiscordInputMode input_mode, void* callback_data, void (DISCORD_API *callback)(void* callback_data, enum EDiscordResult result)); + enum EDiscordResult (DISCORD_API *is_self_mute)(struct IDiscordVoiceManager* manager, bool* mute); + enum EDiscordResult (DISCORD_API *set_self_mute)(struct IDiscordVoiceManager* manager, bool mute); + enum EDiscordResult (DISCORD_API *is_self_deaf)(struct IDiscordVoiceManager* manager, bool* deaf); + enum EDiscordResult (DISCORD_API *set_self_deaf)(struct IDiscordVoiceManager* manager, bool deaf); + enum EDiscordResult (DISCORD_API *is_local_mute)(struct IDiscordVoiceManager* manager, DiscordSnowflake user_id, bool* mute); + enum EDiscordResult (DISCORD_API *set_local_mute)(struct IDiscordVoiceManager* manager, DiscordSnowflake user_id, bool mute); + enum EDiscordResult (DISCORD_API *get_local_volume)(struct IDiscordVoiceManager* manager, DiscordSnowflake user_id, uint8_t* volume); + enum EDiscordResult (DISCORD_API *set_local_volume)(struct IDiscordVoiceManager* manager, DiscordSnowflake user_id, uint8_t volume); }; struct IDiscordAchievementEvents { - void (*on_user_achievement_update)(void* event_data, struct DiscordUserAchievement* user_achievement); + void (DISCORD_API *on_user_achievement_update)(void* event_data, struct DiscordUserAchievement* user_achievement); }; struct IDiscordAchievementManager { - void (*set_user_achievement)(struct IDiscordAchievementManager* manager, DiscordSnowflake achievement_id, uint8_t percent_complete, void* callback_data, void (*callback)(void* callback_data, enum EDiscordResult result)); - void (*fetch_user_achievements)(struct IDiscordAchievementManager* manager, void* callback_data, void (*callback)(void* callback_data, enum EDiscordResult result)); - void (*count_user_achievements)(struct IDiscordAchievementManager* manager, int32_t* count); - enum EDiscordResult (*get_user_achievement)(struct IDiscordAchievementManager* manager, DiscordSnowflake user_achievement_id, struct DiscordUserAchievement* user_achievement); - enum EDiscordResult (*get_user_achievement_at)(struct IDiscordAchievementManager* manager, int32_t index, struct DiscordUserAchievement* user_achievement); + void (DISCORD_API *set_user_achievement)(struct IDiscordAchievementManager* manager, DiscordSnowflake achievement_id, uint8_t percent_complete, void* callback_data, void (DISCORD_API *callback)(void* callback_data, enum EDiscordResult result)); + void (DISCORD_API *fetch_user_achievements)(struct IDiscordAchievementManager* manager, void* callback_data, void (DISCORD_API *callback)(void* callback_data, enum EDiscordResult result)); + void (DISCORD_API *count_user_achievements)(struct IDiscordAchievementManager* manager, int32_t* count); + enum EDiscordResult (DISCORD_API *get_user_achievement)(struct IDiscordAchievementManager* manager, DiscordSnowflake user_achievement_id, struct DiscordUserAchievement* user_achievement); + enum EDiscordResult (DISCORD_API *get_user_achievement_at)(struct IDiscordAchievementManager* manager, int32_t index, struct DiscordUserAchievement* user_achievement); }; typedef void* IDiscordCoreEvents; struct IDiscordCore { - void (*destroy)(struct IDiscordCore* core); - enum EDiscordResult (*run_callbacks)(struct IDiscordCore* core); - void (*set_log_hook)(struct IDiscordCore* core, enum EDiscordLogLevel min_level, void* hook_data, void (*hook)(void* hook_data, enum EDiscordLogLevel level, const char* message)); - struct IDiscordApplicationManager* (*get_application_manager)(struct IDiscordCore* core); - struct IDiscordUserManager* (*get_user_manager)(struct IDiscordCore* core); - struct IDiscordImageManager* (*get_image_manager)(struct IDiscordCore* core); - struct IDiscordActivityManager* (*get_activity_manager)(struct IDiscordCore* core); - struct IDiscordRelationshipManager* (*get_relationship_manager)(struct IDiscordCore* core); - struct IDiscordLobbyManager* (*get_lobby_manager)(struct IDiscordCore* core); - struct IDiscordNetworkManager* (*get_network_manager)(struct IDiscordCore* core); - struct IDiscordOverlayManager* (*get_overlay_manager)(struct IDiscordCore* core); - struct IDiscordStorageManager* (*get_storage_manager)(struct IDiscordCore* core); - struct IDiscordStoreManager* (*get_store_manager)(struct IDiscordCore* core); - struct IDiscordVoiceManager* (*get_voice_manager)(struct IDiscordCore* core); - struct IDiscordAchievementManager* (*get_achievement_manager)(struct IDiscordCore* core); + void (DISCORD_API *destroy)(struct IDiscordCore* core); + enum EDiscordResult (DISCORD_API *run_callbacks)(struct IDiscordCore* core); + void (DISCORD_API *set_log_hook)(struct IDiscordCore* core, enum EDiscordLogLevel min_level, void* hook_data, void (DISCORD_API *hook)(void* hook_data, enum EDiscordLogLevel level, const char* message)); + struct IDiscordApplicationManager* (DISCORD_API *get_application_manager)(struct IDiscordCore* core); + struct IDiscordUserManager* (DISCORD_API *get_user_manager)(struct IDiscordCore* core); + struct IDiscordImageManager* (DISCORD_API *get_image_manager)(struct IDiscordCore* core); + struct IDiscordActivityManager* (DISCORD_API *get_activity_manager)(struct IDiscordCore* core); + struct IDiscordRelationshipManager* (DISCORD_API *get_relationship_manager)(struct IDiscordCore* core); + struct IDiscordLobbyManager* (DISCORD_API *get_lobby_manager)(struct IDiscordCore* core); + struct IDiscordNetworkManager* (DISCORD_API *get_network_manager)(struct IDiscordCore* core); + struct IDiscordOverlayManager* (DISCORD_API *get_overlay_manager)(struct IDiscordCore* core); + struct IDiscordStorageManager* (DISCORD_API *get_storage_manager)(struct IDiscordCore* core); + struct IDiscordStoreManager* (DISCORD_API *get_store_manager)(struct IDiscordCore* core); + struct IDiscordVoiceManager* (DISCORD_API *get_voice_manager)(struct IDiscordCore* core); + struct IDiscordAchievementManager* (DISCORD_API *get_achievement_manager)(struct IDiscordCore* core); }; struct DiscordCreateParams { @@ -644,10 +727,10 @@ void DiscordCreateParamsSetDefault(struct DiscordCreateParams* params) params->achievement_version = DISCORD_ACHIEVEMENT_MANAGER_VERSION; } -enum EDiscordResult DiscordCreate(DiscordVersion version, struct DiscordCreateParams* params, struct IDiscordCore** result); +enum EDiscordResult DISCORD_API DiscordCreate(DiscordVersion version, struct DiscordCreateParams* params, struct IDiscordCore** result); #ifdef __cplusplus } #endif -#endif \ No newline at end of file +#endif diff --git a/src/include/fdi2raw.h b/src/include/fdi2raw.h index 8f71679a8..b848b26f2 100644 --- a/src/include/fdi2raw.h +++ b/src/include/fdi2raw.h @@ -1,51 +1,81 @@ /* - * 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. + * 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. + * This file is part of the 86Box distribution. * - * Definitions for the FDI floppy file format. + * Definitions for the FDI floppy file format. * * * - * Authors: Toni Wilen, - * and Vincent Joguin, - * Thomas Harte, + * Authors: Toni Wilen, + * and Vincent Joguin, + * Thomas Harte, * - * Copyright 2001-2004 Toni Wilen. - * Copyright 2001-2004 Vincent Joguin. - * Copyright 2001 Thomas Harte. + * Copyright 2001-2004 Toni Wilen. + * Copyright 2001-2004 Vincent Joguin. + * Copyright 2001-2016 Thomas Harte. */ #ifndef __FDI2RAW_H #define __FDI2RAW_H -#define uae_u8 uint8_t -#define uae_u16 uint16_t -#define uae_u32 uint32_t - +#include +#include #include + typedef struct fdi FDI; #ifdef __cplusplus extern "C" { #endif -extern int fdi2raw_loadtrack (FDI*, uae_u16 *mfmbuf, uae_u16 *tracktiming, int track, int *tracklength, int *indexoffset, int *multirev, int mfm); +/*! + Attempts to parse and return an FDI header from the file @c file. -extern int fdi2raw_loadrevolution (FDI*, uae_u16 *mfmbuf, uae_u16 *tracktiming, int track, int *tracklength, int mfm); + @parameter file the file from which to attempt to read the FDI. + @returns a newly-allocated `FDI` if parsing succeeded; @c NULL otherwise. +*/ +extern FDI *fdi2raw_header(FILE *file); -extern FDI *fdi2raw_header(FILE *f); -extern void fdi2raw_header_free (FDI *); -extern int fdi2raw_get_last_track(FDI *); -extern int fdi2raw_get_num_sector (FDI *); -extern int fdi2raw_get_last_head(FDI *); -extern int fdi2raw_get_type (FDI *); -extern int fdi2raw_get_bit_rate (FDI *); -extern int fdi2raw_get_rotation (FDI *); -extern int fdi2raw_get_write_protect (FDI *); -extern int fdi2raw_get_tpi (FDI *); +/*! + Release all memory associated with @c file. +*/ +extern void fdi2raw_header_free(FDI *file); + +extern int fdi2raw_loadtrack(FDI *, uint16_t *mfmbuf, uint16_t *tracktiming, int track, int *tracklength, int *indexoffset, int *multirev, int mfm); +extern int fdi2raw_loadrevolution(FDI *, uint16_t *mfmbuf, uint16_t *tracktiming, int track, int *tracklength, int mfm); + +typedef enum { + FDI2RawDiskType8Inch = 0, + FDI2RawDiskType5_25Inch = 1, + FDI2RawDiskType3_5Inch = 2, + FDI2RawDiskType3Inch = 3, +} FDI2RawDiskType; + +/// @returns the disk type described by @c fdi. +extern FDI2RawDiskType fdi2raw_get_type(FDI *fdi); + +/// @returns the bit rate at which @c fdi is sampled if spinning at the intended rate, in Kbit/s. +extern int fdi2raw_get_bit_rate(FDI *fdi); + +/// @returns the intended rotation speed of @c fdi, in rotations per minute. +extern int fdi2raw_get_rotation(FDI *fdi); + +/// @returns whether the imaged disk was write protected. +extern bool fdi2raw_get_write_protect(FDI *fdi); + +/// @returns the final enumerated track represented in @c fdi. +extern int fdi2raw_get_last_track(FDI *fdi); + +/// @returns the final enumerated head represented in @c fdi. +extern int fdi2raw_get_last_head(FDI *fdi); + +/// @returns @c 22 if track 0 is a standard Amiga high-density; @c 11 otherwise. +extern int fdi2raw_get_num_sector(FDI *fdi); + +extern int fdi2raw_get_tpi(FDI *fdi); #ifdef __cplusplus } diff --git a/src/include/glad/glad.h b/src/include/glad/glad.h index 0b4d36656..5b2fd13f4 100644 --- a/src/include/glad/glad.h +++ b/src/include/glad/glad.h @@ -1,6 +1,6 @@ /* - OpenGL loader generated by glad 0.1.34 on Sat Dec 4 18:46:02 2021. + OpenGL loader generated by glad 0.1.36 on Sat Jan 7 18:24:33 2023. Language/Generator: C/C++ Specification: gl diff --git a/src/include/lzf.h b/src/include/lzf.h index 919b6e6be..98e038f31 100644 --- a/src/include/lzf.h +++ b/src/include/lzf.h @@ -1,16 +1,16 @@ /* * Copyright (c) 2000-2008 Marc Alexander Lehmann - * + * * Redistribution and use in source and binary forms, with or without modifica- * tion, are permitted provided that the following conditions are met: - * + * * 1. Redistributions of source code must retain the above copyright notice, * this list of conditions and the following disclaimer. - * + * * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. - * + * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MER- * CHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO @@ -73,7 +73,7 @@ * and lzf_c.c. * */ -unsigned int +unsigned int lzf_compress (const void *const in_data, unsigned int in_len, void *out_data, unsigned int out_len); @@ -92,7 +92,7 @@ lzf_compress (const void *const in_data, unsigned int in_len, * * This function is very fast, about as fast as a copying loop. */ -unsigned int +unsigned int lzf_decompress (const void *const in_data, unsigned int in_len, void *out_data, unsigned int out_len); diff --git a/src/include/minitrace/minitrace.h b/src/include/minitrace/minitrace.h index 2047eedb7..0335c9ac3 100644 --- a/src/include/minitrace/minitrace.h +++ b/src/include/minitrace/minitrace.h @@ -1,7 +1,7 @@ // Minitrace // // Copyright 2014 by Henrik RydgÃ¥rd -// http://www.github.com/hrydgard/minitrace +// https://www.github.com/hrydgard/minitrace // Released under the MIT license. // // Ultra-light dependency free library for performance tracing C/C++ applications. @@ -71,13 +71,13 @@ const char *mtr_pool_string(const char *str); // Commented-out types will be supported in the future. typedef enum { - MTR_ARG_TYPE_NONE = 0, - MTR_ARG_TYPE_INT = 1, // I - // MTR_ARG_TYPE_FLOAT = 2, // TODO - // MTR_ARG_TYPE_DOUBLE = 3, // TODO - MTR_ARG_TYPE_STRING_CONST = 8, // C - MTR_ARG_TYPE_STRING_COPY = 9, - // MTR_ARG_TYPE_JSON_COPY = 10, + MTR_ARG_TYPE_NONE = 0, + MTR_ARG_TYPE_INT = 1, // I + // MTR_ARG_TYPE_FLOAT = 2, // TODO + // MTR_ARG_TYPE_DOUBLE = 3, // TODO + MTR_ARG_TYPE_STRING_CONST = 8, // C + MTR_ARG_TYPE_STRING_COPY = 9, + // MTR_ARG_TYPE_JSON_COPY = 10, } mtr_arg_type; // TODO: Add support for more than one argument (metadata) per event @@ -213,55 +213,55 @@ void internal_mtr_raw_event_arg(const char *category, const char *name, char ph, // These are optimized to use X events (combined B and E). Much easier to do in C++ than in C. class MTRScopedTrace { public: - MTRScopedTrace(const char *category, const char *name) - : category_(category), name_(name) { - start_time_ = mtr_time_s(); - } - ~MTRScopedTrace() { - internal_mtr_raw_event(category_, name_, 'X', &start_time_); - } + MTRScopedTrace(const char *category, const char *name) + : category_(category), name_(name) { + start_time_ = mtr_time_s(); + } + ~MTRScopedTrace() { + internal_mtr_raw_event(category_, name_, 'X', &start_time_); + } private: - const char *category_; - const char *name_; - double start_time_; + const char *category_; + const char *name_; + double start_time_; }; // Only outputs a block if execution time exceeded the limit. // TODO: This will effectively call mtr_time_s twice at the end, which is bad. class MTRScopedTraceLimit { public: - MTRScopedTraceLimit(const char *category, const char *name, double limit_s) - : category_(category), name_(name), limit_(limit_s) { - start_time_ = mtr_time_s(); - } - ~MTRScopedTraceLimit() { - double end_time = mtr_time_s(); - if (end_time - start_time_ >= limit_) { - internal_mtr_raw_event(category_, name_, 'X', &start_time_); - } - } + MTRScopedTraceLimit(const char *category, const char *name, double limit_s) + : category_(category), name_(name), limit_(limit_s) { + start_time_ = mtr_time_s(); + } + ~MTRScopedTraceLimit() { + double end_time = mtr_time_s(); + if (end_time - start_time_ >= limit_) { + internal_mtr_raw_event(category_, name_, 'X', &start_time_); + } + } private: - const char *category_; - const char *name_; - double start_time_; - double limit_; + const char *category_; + const char *name_; + double start_time_; + double limit_; }; class MTRScopedTraceArg { public: - MTRScopedTraceArg(const char *category, const char *name, mtr_arg_type arg_type, const char *arg_name, void *arg_value) - : category_(category), name_(name) { - internal_mtr_raw_event_arg(category, name, 'B', 0, arg_type, arg_name, arg_value); - } - ~MTRScopedTraceArg() { - internal_mtr_raw_event(category_, name_, 'E', 0); - } + MTRScopedTraceArg(const char *category, const char *name, mtr_arg_type arg_type, const char *arg_name, void *arg_value) + : category_(category), name_(name) { + internal_mtr_raw_event_arg(category, name, 'B', 0, arg_type, arg_name, arg_value); + } + ~MTRScopedTraceArg() { + internal_mtr_raw_event(category_, name_, 'E', 0); + } private: - const char *category_; - const char *name_; + const char *category_; + const char *name_; }; #endif diff --git a/src/include/mt32emu/Enumerations.h b/src/include/mt32emu/Enumerations.h index bb580ca5b..3cbfdd4c8 100644 --- a/src/include/mt32emu/Enumerations.h +++ b/src/include/mt32emu/Enumerations.h @@ -1,5 +1,5 @@ /* Copyright (C) 2003, 2004, 2005, 2006, 2008, 2009 Dean Beeler, Jerome Fisher - * Copyright (C) 2011-2017 Dean Beeler, Jerome Fisher, Sergey V. Mikayev + * Copyright (C) 2011-2022 Dean Beeler, Jerome Fisher, Sergey V. Mikayev * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by diff --git a/src/include/mt32emu/Types.h b/src/include/mt32emu/Types.h index f70e4795c..12e454750 100644 --- a/src/include/mt32emu/Types.h +++ b/src/include/mt32emu/Types.h @@ -1,5 +1,5 @@ /* Copyright (C) 2003, 2004, 2005, 2006, 2008, 2009 Dean Beeler, Jerome Fisher - * Copyright (C) 2011-2017 Dean Beeler, Jerome Fisher, Sergey V. Mikayev + * Copyright (C) 2011-2022 Dean Beeler, Jerome Fisher, Sergey V. Mikayev * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by diff --git a/src/include/mt32emu/c_interface/c_interface.h b/src/include/mt32emu/c_interface/c_interface.h index 2ca3a3b04..5653c9051 100644 --- a/src/include/mt32emu/c_interface/c_interface.h +++ b/src/include/mt32emu/c_interface/c_interface.h @@ -1,5 +1,5 @@ /* Copyright (C) 2003, 2004, 2005, 2006, 2008, 2009 Dean Beeler, Jerome Fisher - * Copyright (C) 2011-2017 Dean Beeler, Jerome Fisher, Sergey V. Mikayev + * Copyright (C) 2011-2022 Dean Beeler, Jerome Fisher, Sergey V. Mikayev * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by @@ -24,7 +24,9 @@ #include "c_types.h" #undef MT32EMU_EXPORT +#undef MT32EMU_EXPORT_V #define MT32EMU_EXPORT MT32EMU_EXPORT_ATTRIBUTE +#define MT32EMU_EXPORT_V(symbol_version_tag) MT32EMU_EXPORT #ifdef __cplusplus extern "C" { @@ -35,24 +37,28 @@ extern "C" { /* === Interface handling === */ /** Returns mt32emu_service_i interface. */ -MT32EMU_EXPORT mt32emu_service_i mt32emu_get_service_i(); +MT32EMU_EXPORT mt32emu_service_i MT32EMU_C_CALL mt32emu_get_service_i(void); #if MT32EMU_EXPORTS_TYPE == 2 #undef MT32EMU_EXPORT +#undef MT32EMU_EXPORT_V #define MT32EMU_EXPORT +#define MT32EMU_EXPORT_V(symbol_version_tag) MT32EMU_EXPORT #endif /** * Returns the version ID of mt32emu_report_handler_i interface the library has been compiled with. * This allows a client to fall-back gracefully instead of silently not receiving expected event reports. */ -MT32EMU_EXPORT mt32emu_report_handler_version mt32emu_get_supported_report_handler_version(); +MT32EMU_EXPORT mt32emu_report_handler_version MT32EMU_C_CALL mt32emu_get_supported_report_handler_version(void); /** * Returns the version ID of mt32emu_midi_receiver_version_i interface the library has been compiled with. * This allows a client to fall-back gracefully instead of silently not receiving expected MIDI messages. */ -MT32EMU_EXPORT mt32emu_midi_receiver_version mt32emu_get_supported_midi_receiver_version(); +MT32EMU_EXPORT mt32emu_midi_receiver_version MT32EMU_C_CALL mt32emu_get_supported_midi_receiver_version(void); + +/* === Utility === */ /** * Returns library version as an integer in format: 0x00MMmmpp, where: @@ -60,67 +66,149 @@ MT32EMU_EXPORT mt32emu_midi_receiver_version mt32emu_get_supported_midi_receiver * mm - minor version number * pp - patch number */ -MT32EMU_EXPORT mt32emu_bit32u mt32emu_get_library_version_int(); +MT32EMU_EXPORT mt32emu_bit32u MT32EMU_C_CALL mt32emu_get_library_version_int(void); /** * Returns library version as a C-string in format: "MAJOR.MINOR.PATCH". */ -MT32EMU_EXPORT const char *mt32emu_get_library_version_string(); +MT32EMU_EXPORT const char * MT32EMU_C_CALL mt32emu_get_library_version_string(void); /** * Returns output sample rate used in emulation of stereo analog circuitry of hardware units for particular analog_output_mode. * See comment for mt32emu_analog_output_mode. */ -MT32EMU_EXPORT mt32emu_bit32u mt32emu_get_stereo_output_samplerate(const mt32emu_analog_output_mode analog_output_mode); +MT32EMU_EXPORT mt32emu_bit32u MT32EMU_C_CALL mt32emu_get_stereo_output_samplerate(const mt32emu_analog_output_mode analog_output_mode); /** * Returns the value of analog_output_mode for which the output signal may retain its full frequency spectrum * at the sample rate specified by the target_samplerate argument. * See comment for mt32emu_analog_output_mode. */ -MT32EMU_EXPORT mt32emu_analog_output_mode mt32emu_get_best_analog_output_mode(const double target_samplerate); +MT32EMU_EXPORT mt32emu_analog_output_mode MT32EMU_C_CALL mt32emu_get_best_analog_output_mode(const double target_samplerate); + +/* === ROM handling === */ + +/** + * Retrieves a list of identifiers (as C-strings) of supported machines. Argument machine_ids points to the array of size + * machine_ids_size to be filled. + * Returns the number of identifiers available for retrieval. The size of the target array to be allocated can be found + * by passing NULL in argument machine_ids; argument machine_ids_size is ignored in this case. + */ +MT32EMU_EXPORT_V(2.5) size_t MT32EMU_C_CALL mt32emu_get_machine_ids(const char **machine_ids, size_t machine_ids_size); +/** + * Retrieves a list of identifiers (as C-strings) of supported ROM images. Argument rom_ids points to the array of size + * rom_ids_size to be filled. Optional argument machine_id can be used to indicate a specific machine to retrieve ROM identifiers + * for; if NULL, identifiers of all the ROM images supported by the emulation engine are retrieved. + * Returns the number of ROM identifiers available for retrieval. The size of the target array to be allocated can be found + * by passing NULL in argument rom_ids; argument rom_ids_size is ignored in this case. If argument machine_id contains + * an unrecognised value, 0 is returned. + */ +MT32EMU_EXPORT_V(2.5) size_t MT32EMU_C_CALL mt32emu_get_rom_ids(const char **rom_ids, size_t rom_ids_size, const char *machine_id); + +/** + * Identifies a ROM image the provided data array contains by its SHA1 digest. Optional argument machine_id can be used to indicate + * a specific machine to identify the ROM image for; if NULL, the ROM image is identified for any supported machine. + * A mt32emu_rom_info structure supplied in argument rom_info is filled in accordance with the provided ROM image; unused fields + * are filled with NULLs. If the content of the ROM image is not identified successfully (e.g. when the ROM image is incompatible + * with the specified machine), all fields of rom_info are filled with NULLs. + * Returns MT32EMU_RC_OK upon success or a negative error code otherwise. + */ +MT32EMU_EXPORT_V(2.5) mt32emu_return_code MT32EMU_C_CALL mt32emu_identify_rom_data(mt32emu_rom_info *rom_info, const mt32emu_bit8u *data, size_t data_size, const char *machine_id); +/** + * Loads the content of the file specified by argument filename and identifies a ROM image the file contains by its SHA1 digest. + * Optional argument machine_id can be used to indicate a specific machine to identify the ROM image for; if NULL, the ROM image + * is identified for any supported machine. + * A mt32emu_rom_info structure supplied in argument rom_info is filled in accordance with the provided ROM image; unused fields + * are filled with NULLs. If the content of the file is not identified successfully (e.g. when the ROM image is incompatible + * with the specified machine), all fields of rom_info are filled with NULLs. + * Returns MT32EMU_RC_OK upon success or a negative error code otherwise. + */ +MT32EMU_EXPORT_V(2.5) mt32emu_return_code MT32EMU_C_CALL mt32emu_identify_rom_file(mt32emu_rom_info *rom_info, const char *filename, const char *machine_id); /* == Context-dependent functions == */ /** Initialises a new emulation context and installs custom report handler if non-NULL. */ -MT32EMU_EXPORT mt32emu_context mt32emu_create_context(mt32emu_report_handler_i report_handler, void *instance_data); +MT32EMU_EXPORT mt32emu_context MT32EMU_C_CALL mt32emu_create_context(mt32emu_report_handler_i report_handler, void *instance_data); /** Closes and destroys emulation context. */ -MT32EMU_EXPORT void mt32emu_free_context(mt32emu_context context); +MT32EMU_EXPORT void MT32EMU_C_CALL mt32emu_free_context(mt32emu_context context); /** - * Adds new ROM identified by its SHA1 digest to the emulation context replacing previously added ROM of the same type if any. - * Argument sha1_digest can be NULL, in this case the digest will be computed using the actual ROM data. + * Adds a new full ROM data image identified by its SHA1 digest to the emulation context replacing previously added ROM of the same + * type if any. Argument sha1_digest can be NULL, in this case the digest will be computed using the actual ROM data. * If sha1_digest is set to non-NULL, it is assumed being correct and will not be recomputed. - * This function doesn't immediately change the state of already opened synth. Newly added ROM will take effect upon next call of mt32emu_open_synth(). + * The provided data array is NOT copied and used directly for efficiency. The caller should not deallocate it while the emulation + * context is referring to the ROM data. + * This function doesn't immediately change the state of already opened synth. Newly added ROM will take effect upon next call of + * mt32emu_open_synth(). * Returns positive value upon success. */ -MT32EMU_EXPORT mt32emu_return_code mt32emu_add_rom_data(mt32emu_context context, const mt32emu_bit8u *data, size_t data_size, const mt32emu_sha1_digest *sha1_digest); +MT32EMU_EXPORT mt32emu_return_code MT32EMU_C_CALL mt32emu_add_rom_data(mt32emu_context context, const mt32emu_bit8u *data, size_t data_size, const mt32emu_sha1_digest *sha1_digest); /** - * Loads a ROM file, identify it by SHA1 digest, and adds it to the emulation context replacing previously added ROM of the same type if any. - * This function doesn't immediately change the state of already opened synth. Newly added ROM will take effect upon next call of mt32emu_open_synth(). + * Loads a ROM file that contains a full ROM data image, identifies it by the SHA1 digest, and adds it to the emulation context + * replacing previously added ROM of the same type if any. + * This function doesn't immediately change the state of already opened synth. Newly added ROM will take effect upon next call of + * mt32emu_open_synth(). * Returns positive value upon success. */ -MT32EMU_EXPORT mt32emu_return_code mt32emu_add_rom_file(mt32emu_context context, const char *filename); +MT32EMU_EXPORT mt32emu_return_code MT32EMU_C_CALL mt32emu_add_rom_file(mt32emu_context context, const char *filename); + +/** + * Merges a pair of compatible ROM data image parts into a full image and adds it to the emulation context replacing previously + * added ROM of the same type if any. Each partial image is identified by its SHA1 digest. Arguments partN_sha1_digest can be NULL, + * in this case the digest will be computed using the actual ROM data. If a non-NULL SHA1 value is provided, it is assumed being + * correct and will not be recomputed. The provided data arrays may be deallocated as soon as the function completes. + * This function doesn't immediately change the state of already opened synth. Newly added ROM will take effect upon next call of + * mt32emu_open_synth(). + * Returns positive value upon success. + */ +MT32EMU_EXPORT_V(2.5) mt32emu_return_code MT32EMU_C_CALL mt32emu_merge_and_add_rom_data(mt32emu_context context, const mt32emu_bit8u *part1_data, size_t part1_data_size, const mt32emu_sha1_digest *part1_sha1_digest, const mt32emu_bit8u *part2_data, size_t part2_data_size, const mt32emu_sha1_digest *part2_sha1_digest); + +/** + * Loads a pair of files that contains compatible parts of a full ROM image, identifies them by the SHA1 digest, merges these + * parts into a full ROM image and adds it to the emulation context replacing previously added ROM of the same type if any. + * This function doesn't immediately change the state of already opened synth. Newly added ROM will take effect upon next call of + * mt32emu_open_synth(). + * Returns positive value upon success. + */ +MT32EMU_EXPORT_V(2.5) mt32emu_return_code MT32EMU_C_CALL mt32emu_merge_and_add_rom_files(mt32emu_context context, const char *part1_filename, const char *part2_filename); + +/** + * Loads a file that contains a ROM image of a specific machine, identifies it by the SHA1 digest, and adds it to the emulation + * context. The ROM image can only be identified successfully if it is compatible with the specified machine. + * Full and partial ROM images are supported and handled according to the following rules: + * - a file with any compatible ROM image is added if none (of the same type) exists in the emulation context; + * - a file with any compatible ROM image replaces any image of the same type that is incompatible with the specified machine; + * - a file with a full ROM image replaces the previously added partial ROM of the same type; + * - a file with a partial ROM image is merged with the previously added ROM image if pairable; + * - otherwise, the file is ignored. + * The described behaviour allows the caller application to traverse a directory with ROM files attempting to add each one in turn. + * As soon as both the full control and the full PCM ROM images are added and / or merged, the iteration can be stopped. + * This function doesn't immediately change the state of already opened synth. Newly added ROMs will take effect upon next call of + * mt32emu_open_synth(). + * Returns a positive value in case changes have been made, MT32EMU_RC_OK if the file has been ignored or a negative error code + * upon failure. + */ +MT32EMU_EXPORT_V(2.5) mt32emu_return_code MT32EMU_C_CALL mt32emu_add_machine_rom_file(mt32emu_context context, const char *machine_id, const char *filename); /** * Fills in mt32emu_rom_info structure with identifiers and descriptions of control and PCM ROM files identified and added to the synth context. * If one of the ROM files is not loaded and identified yet, NULL is returned in the corresponding fields of the mt32emu_rom_info structure. */ -MT32EMU_EXPORT void mt32emu_get_rom_info(mt32emu_const_context context, mt32emu_rom_info *rom_info); +MT32EMU_EXPORT void MT32EMU_C_CALL mt32emu_get_rom_info(mt32emu_const_context context, mt32emu_rom_info *rom_info); /** * Allows to override the default maximum number of partials playing simultaneously within the emulation session. * This function doesn't immediately change the state of already opened synth. Newly set value will take effect upon next call of mt32emu_open_synth(). */ -MT32EMU_EXPORT void mt32emu_set_partial_count(mt32emu_context context, const mt32emu_bit32u partial_count); +MT32EMU_EXPORT void MT32EMU_C_CALL mt32emu_set_partial_count(mt32emu_context context, const mt32emu_bit32u partial_count); /** * Allows to override the default mode for emulation of analogue circuitry of the hardware units within the emulation session. * This function doesn't immediately change the state of already opened synth. Newly set value will take effect upon next call of mt32emu_open_synth(). */ -MT32EMU_EXPORT void mt32emu_set_analog_output_mode(mt32emu_context context, const mt32emu_analog_output_mode analog_output_mode); +MT32EMU_EXPORT void MT32EMU_C_CALL mt32emu_set_analog_output_mode(mt32emu_context context, const mt32emu_analog_output_mode analog_output_mode); /** * Allows to convert the synthesiser output to any desired sample rate. The samplerate conversion @@ -131,7 +219,7 @@ MT32EMU_EXPORT void mt32emu_set_analog_output_mode(mt32emu_context context, cons * This function doesn't immediately change the state of already opened synth. * Newly set value will take effect upon next call of mt32emu_open_synth(). */ -MT32EMU_EXPORT void mt32emu_set_stereo_output_samplerate(mt32emu_context context, const double samplerate); +MT32EMU_EXPORT void MT32EMU_C_CALL mt32emu_set_stereo_output_samplerate(mt32emu_context context, const double samplerate); /** * Several samplerate conversion quality options are provided which allow to trade-off the conversion speed vs. @@ -140,66 +228,79 @@ MT32EMU_EXPORT void mt32emu_set_stereo_output_samplerate(mt32emu_context context * This function doesn't immediately change the state of already opened synth. * Newly set value will take effect upon next call of mt32emu_open_synth(). */ -MT32EMU_EXPORT void mt32emu_set_samplerate_conversion_quality(mt32emu_context context, const mt32emu_samplerate_conversion_quality quality); +MT32EMU_EXPORT void MT32EMU_C_CALL mt32emu_set_samplerate_conversion_quality(mt32emu_context context, const mt32emu_samplerate_conversion_quality quality); /** * Selects new type of the wave generator and renderer to be used during subsequent calls to mt32emu_open_synth(). * By default, MT32EMU_RT_BIT16S is selected. * See mt32emu_renderer_type for details. */ -MT32EMU_EXPORT void mt32emu_select_renderer_type(mt32emu_context context, const mt32emu_renderer_type renderer_type); +MT32EMU_EXPORT void MT32EMU_C_CALL mt32emu_select_renderer_type(mt32emu_context context, const mt32emu_renderer_type renderer_type); /** * Returns previously selected type of the wave generator and renderer. * See mt32emu_renderer_type for details. */ -MT32EMU_EXPORT mt32emu_renderer_type mt32emu_get_selected_renderer_type(mt32emu_context context); +MT32EMU_EXPORT mt32emu_renderer_type MT32EMU_C_CALL mt32emu_get_selected_renderer_type(mt32emu_context context); /** * Prepares the emulation context to receive MIDI messages and produce output audio data using aforehand added set of ROMs, * and optionally set the maximum partial count and the analog output mode. * Returns MT32EMU_RC_OK upon success. */ -MT32EMU_EXPORT mt32emu_return_code mt32emu_open_synth(mt32emu_const_context context); +MT32EMU_EXPORT mt32emu_return_code MT32EMU_C_CALL mt32emu_open_synth(mt32emu_const_context context); /** Closes the emulation context freeing allocated resources. Added ROMs remain unaffected and ready for reuse. */ -MT32EMU_EXPORT void mt32emu_close_synth(mt32emu_const_context context); +MT32EMU_EXPORT void MT32EMU_C_CALL mt32emu_close_synth(mt32emu_const_context context); /** Returns true if the synth is in completely initialized state, otherwise returns false. */ -MT32EMU_EXPORT mt32emu_boolean mt32emu_is_open(mt32emu_const_context context); +MT32EMU_EXPORT mt32emu_boolean MT32EMU_C_CALL mt32emu_is_open(mt32emu_const_context context); /** * Returns actual sample rate of the fully processed output stereo signal. * If samplerate conversion is used (i.e. when mt32emu_set_stereo_output_samplerate() has been invoked with a non-zero value), * the returned value is the desired output samplerate rounded down to the closest integer. - * Otherwise, the output samplerate is choosen depending on the emulation mode of stereo analog circuitry of hardware units. + * Otherwise, the output samplerate is chosen depending on the emulation mode of stereo analog circuitry of hardware units. * See comment for mt32emu_analog_output_mode for more info. */ -MT32EMU_EXPORT mt32emu_bit32u mt32emu_get_actual_stereo_output_samplerate(mt32emu_const_context context); +MT32EMU_EXPORT mt32emu_bit32u MT32EMU_C_CALL mt32emu_get_actual_stereo_output_samplerate(mt32emu_const_context context); /** * Returns the number of samples produced at the internal synth sample rate (32000 Hz) * that correspond to the given number of samples at the output sample rate. * Intended to facilitate audio time synchronisation. */ -MT32EMU_EXPORT mt32emu_bit32u mt32emu_convert_output_to_synth_timestamp(mt32emu_const_context context, mt32emu_bit32u output_timestamp); +MT32EMU_EXPORT mt32emu_bit32u MT32EMU_C_CALL mt32emu_convert_output_to_synth_timestamp(mt32emu_const_context context, mt32emu_bit32u output_timestamp); /** * Returns the number of samples produced at the output sample rate * that correspond to the given number of samples at the internal synth sample rate (32000 Hz). * Intended to facilitate audio time synchronisation. */ -MT32EMU_EXPORT mt32emu_bit32u mt32emu_convert_synth_to_output_timestamp(mt32emu_const_context context, mt32emu_bit32u synth_timestamp); +MT32EMU_EXPORT mt32emu_bit32u MT32EMU_C_CALL mt32emu_convert_synth_to_output_timestamp(mt32emu_const_context context, mt32emu_bit32u synth_timestamp); /** All the enqueued events are processed by the synth immediately. */ -MT32EMU_EXPORT void mt32emu_flush_midi_queue(mt32emu_const_context context); +MT32EMU_EXPORT void MT32EMU_C_CALL mt32emu_flush_midi_queue(mt32emu_const_context context); /** * Sets size of the internal MIDI event queue. The queue size is set to the minimum power of 2 that is greater or equal to the size specified. * The queue is flushed before reallocation. * Returns the actual queue size being used. */ -MT32EMU_EXPORT mt32emu_bit32u mt32emu_set_midi_event_queue_size(mt32emu_const_context context, const mt32emu_bit32u queue_size); +MT32EMU_EXPORT mt32emu_bit32u MT32EMU_C_CALL mt32emu_set_midi_event_queue_size(mt32emu_const_context context, const mt32emu_bit32u queue_size); + +/** + * Configures the SysEx storage of the internal MIDI event queue. + * Supplying 0 in the storage_buffer_size argument makes the SysEx data stored + * in multiple dynamically allocated buffers per MIDI event. These buffers are only disposed + * when a new MIDI event replaces the SysEx event in the queue, thus never on the rendering thread. + * This is the default behaviour. + * In contrast, when a positive value is specified, SysEx data will be stored in a single preallocated buffer, + * which makes this kind of storage safe for use in a realtime thread. Additionally, the space retained + * by a SysEx event, that has been processed and thus is no longer necessary, is disposed instantly. + * Note, the queue is flushed and recreated in the process so that its size remains intact. + */ +MT32EMU_EXPORT void MT32EMU_C_CALL mt32emu_configure_midi_event_queue_sysex_storage(mt32emu_const_context context, const mt32emu_bit32u storage_buffer_size); /** * Installs custom MIDI receiver object intended for receiving MIDI messages generated by MIDI stream parser. @@ -207,13 +308,13 @@ MT32EMU_EXPORT mt32emu_bit32u mt32emu_set_midi_event_queue_size(mt32emu_const_co * By default, parsed short MIDI messages and System Exclusive messages are sent to the synth input MIDI queue. * This function allows to override default behaviour. If midi_receiver argument is set to NULL, the default behaviour is restored. */ -MT32EMU_EXPORT void mt32emu_set_midi_receiver(mt32emu_context context, mt32emu_midi_receiver_i midi_receiver, void *instance_data); +MT32EMU_EXPORT void MT32EMU_C_CALL mt32emu_set_midi_receiver(mt32emu_context context, mt32emu_midi_receiver_i midi_receiver, void *instance_data); /** * Returns current value of the global counter of samples rendered since the synth was created (at the native sample rate 32000 Hz). * This method helps to compute accurate timestamp of a MIDI message to use with the methods below. */ -MT32EMU_EXPORT mt32emu_bit32u mt32emu_get_internal_rendered_sample_count(mt32emu_const_context context); +MT32EMU_EXPORT mt32emu_bit32u MT32EMU_C_CALL mt32emu_get_internal_rendered_sample_count(mt32emu_const_context context); /* Enqueues a MIDI event for subsequent playback. * The MIDI event will be processed not before the specified timestamp. @@ -230,7 +331,7 @@ MT32EMU_EXPORT mt32emu_bit32u mt32emu_get_internal_rendered_sample_count(mt32emu * When a System Realtime MIDI message is parsed, onMIDISystemRealtime callback is invoked. * NOTE: the total length of a SysEx message being fragmented shall not exceed MT32EMU_MAX_STREAM_BUFFER_SIZE (32768 bytes). */ -MT32EMU_EXPORT void mt32emu_parse_stream(mt32emu_const_context context, const mt32emu_bit8u *stream, mt32emu_bit32u length); +MT32EMU_EXPORT void MT32EMU_C_CALL mt32emu_parse_stream(mt32emu_const_context context, const mt32emu_bit8u *stream, mt32emu_bit32u length); /** * Parses a block of raw MIDI bytes and enqueues parsed MIDI messages to play at specified time. @@ -238,31 +339,31 @@ MT32EMU_EXPORT void mt32emu_parse_stream(mt32emu_const_context context, const mt * When a System Realtime MIDI message is parsed, onMIDISystemRealtime callback is invoked. * NOTE: the total length of a SysEx message being fragmented shall not exceed MT32EMU_MAX_STREAM_BUFFER_SIZE (32768 bytes). */ -MT32EMU_EXPORT void mt32emu_parse_stream_at(mt32emu_const_context context, const mt32emu_bit8u *stream, mt32emu_bit32u length, mt32emu_bit32u timestamp); +MT32EMU_EXPORT void MT32EMU_C_CALL mt32emu_parse_stream_at(mt32emu_const_context context, const mt32emu_bit8u *stream, mt32emu_bit32u length, mt32emu_bit32u timestamp); /** * Enqueues a single mt32emu_bit32u-encoded short MIDI message with full processing ASAP. * The short MIDI message may contain no status byte, the running status is used in this case. * When the argument is a System Realtime MIDI message, onMIDISystemRealtime callback is invoked. */ -MT32EMU_EXPORT void mt32emu_play_short_message(mt32emu_const_context context, mt32emu_bit32u message); +MT32EMU_EXPORT void MT32EMU_C_CALL mt32emu_play_short_message(mt32emu_const_context context, mt32emu_bit32u message); /** * Enqueues a single mt32emu_bit32u-encoded short MIDI message to play at specified time with full processing. * The short MIDI message may contain no status byte, the running status is used in this case. * When the argument is a System Realtime MIDI message, onMIDISystemRealtime callback is invoked. */ -MT32EMU_EXPORT void mt32emu_play_short_message_at(mt32emu_const_context context, mt32emu_bit32u message, mt32emu_bit32u timestamp); +MT32EMU_EXPORT void MT32EMU_C_CALL mt32emu_play_short_message_at(mt32emu_const_context context, mt32emu_bit32u message, mt32emu_bit32u timestamp); /** Enqueues a single short MIDI message to be processed ASAP. The message must contain a status byte. */ -MT32EMU_EXPORT mt32emu_return_code mt32emu_play_msg(mt32emu_const_context context, mt32emu_bit32u msg); +MT32EMU_EXPORT mt32emu_return_code MT32EMU_C_CALL mt32emu_play_msg(mt32emu_const_context context, mt32emu_bit32u msg); /** Enqueues a single well formed System Exclusive MIDI message to be processed ASAP. */ -MT32EMU_EXPORT mt32emu_return_code mt32emu_play_sysex(mt32emu_const_context context, const mt32emu_bit8u *sysex, mt32emu_bit32u len); +MT32EMU_EXPORT mt32emu_return_code MT32EMU_C_CALL mt32emu_play_sysex(mt32emu_const_context context, const mt32emu_bit8u *sysex, mt32emu_bit32u len); /** Enqueues a single short MIDI message to play at specified time. The message must contain a status byte. */ -MT32EMU_EXPORT mt32emu_return_code mt32emu_play_msg_at(mt32emu_const_context context, mt32emu_bit32u msg, mt32emu_bit32u timestamp); +MT32EMU_EXPORT mt32emu_return_code MT32EMU_C_CALL mt32emu_play_msg_at(mt32emu_const_context context, mt32emu_bit32u msg, mt32emu_bit32u timestamp); /** Enqueues a single well formed System Exclusive MIDI message to play at specified time. */ -MT32EMU_EXPORT mt32emu_return_code mt32emu_play_sysex_at(mt32emu_const_context context, const mt32emu_bit8u *sysex, mt32emu_bit32u len, mt32emu_bit32u timestamp); +MT32EMU_EXPORT mt32emu_return_code MT32EMU_C_CALL mt32emu_play_sysex_at(mt32emu_const_context context, const mt32emu_bit8u *sysex, mt32emu_bit32u len, mt32emu_bit32u timestamp); /* WARNING: * The methods below don't ensure minimum 1-sample delay between sequential MIDI events, @@ -274,66 +375,73 @@ MT32EMU_EXPORT mt32emu_return_code mt32emu_play_sysex_at(mt32emu_const_context c * Sends a short MIDI message to the synth for immediate playback. The message must contain a status byte. * See the WARNING above. */ -MT32EMU_EXPORT void mt32emu_play_msg_now(mt32emu_const_context context, mt32emu_bit32u msg); +MT32EMU_EXPORT void MT32EMU_C_CALL mt32emu_play_msg_now(mt32emu_const_context context, mt32emu_bit32u msg); /** * Sends unpacked short MIDI message to the synth for immediate playback. The message must contain a status byte. * See the WARNING above. */ -MT32EMU_EXPORT void mt32emu_play_msg_on_part(mt32emu_const_context context, mt32emu_bit8u part, mt32emu_bit8u code, mt32emu_bit8u note, mt32emu_bit8u velocity); +MT32EMU_EXPORT void MT32EMU_C_CALL mt32emu_play_msg_on_part(mt32emu_const_context context, mt32emu_bit8u part, mt32emu_bit8u code, mt32emu_bit8u note, mt32emu_bit8u velocity); /** * Sends a single well formed System Exclusive MIDI message for immediate processing. The length is in bytes. * See the WARNING above. */ -MT32EMU_EXPORT void mt32emu_play_sysex_now(mt32emu_const_context context, const mt32emu_bit8u *sysex, mt32emu_bit32u len); +MT32EMU_EXPORT void MT32EMU_C_CALL mt32emu_play_sysex_now(mt32emu_const_context context, const mt32emu_bit8u *sysex, mt32emu_bit32u len); /** * Sends inner body of a System Exclusive MIDI message for direct processing. The length is in bytes. * See the WARNING above. */ -MT32EMU_EXPORT void mt32emu_write_sysex(mt32emu_const_context context, mt32emu_bit8u channel, const mt32emu_bit8u *sysex, mt32emu_bit32u len); +MT32EMU_EXPORT void MT32EMU_C_CALL mt32emu_write_sysex(mt32emu_const_context context, mt32emu_bit8u channel, const mt32emu_bit8u *sysex, mt32emu_bit32u len); /** Allows to disable wet reverb output altogether. */ -MT32EMU_EXPORT void mt32emu_set_reverb_enabled(mt32emu_const_context context, const mt32emu_boolean reverb_enabled); +MT32EMU_EXPORT void MT32EMU_C_CALL mt32emu_set_reverb_enabled(mt32emu_const_context context, const mt32emu_boolean reverb_enabled); /** Returns whether wet reverb output is enabled. */ -MT32EMU_EXPORT mt32emu_boolean mt32emu_is_reverb_enabled(mt32emu_const_context context); +MT32EMU_EXPORT mt32emu_boolean MT32EMU_C_CALL mt32emu_is_reverb_enabled(mt32emu_const_context context); /** * Sets override reverb mode. In this mode, emulation ignores sysexes (or the related part of them) which control the reverb parameters. * This mode is in effect until it is turned off. When the synth is re-opened, the override mode is unchanged but the state * of the reverb model is reset to default. */ -MT32EMU_EXPORT void mt32emu_set_reverb_overridden(mt32emu_const_context context, const mt32emu_boolean reverb_overridden); +MT32EMU_EXPORT void MT32EMU_C_CALL mt32emu_set_reverb_overridden(mt32emu_const_context context, const mt32emu_boolean reverb_overridden); /** Returns whether reverb settings are overridden. */ -MT32EMU_EXPORT mt32emu_boolean mt32emu_is_reverb_overridden(mt32emu_const_context context); +MT32EMU_EXPORT mt32emu_boolean MT32EMU_C_CALL mt32emu_is_reverb_overridden(mt32emu_const_context context); /** * Forces reverb model compatibility mode. By default, the compatibility mode corresponds to the used control ROM version. * Invoking this method with the argument set to true forces emulation of old MT-32 reverb circuit. * When the argument is false, emulation of the reverb circuit used in new generation of MT-32 compatible modules is enforced * (these include CM-32L and LAPC-I). */ -MT32EMU_EXPORT void mt32emu_set_reverb_compatibility_mode(mt32emu_const_context context, const mt32emu_boolean mt32_compatible_mode); +MT32EMU_EXPORT void MT32EMU_C_CALL mt32emu_set_reverb_compatibility_mode(mt32emu_const_context context, const mt32emu_boolean mt32_compatible_mode); /** Returns whether reverb is in old MT-32 compatibility mode. */ -MT32EMU_EXPORT mt32emu_boolean mt32emu_is_mt32_reverb_compatibility_mode(mt32emu_const_context context); +MT32EMU_EXPORT mt32emu_boolean MT32EMU_C_CALL mt32emu_is_mt32_reverb_compatibility_mode(mt32emu_const_context context); /** Returns whether default reverb compatibility mode is the old MT-32 compatibility mode. */ -MT32EMU_EXPORT mt32emu_boolean mt32emu_is_default_reverb_mt32_compatible(mt32emu_const_context context); +MT32EMU_EXPORT mt32emu_boolean MT32EMU_C_CALL mt32emu_is_default_reverb_mt32_compatible(mt32emu_const_context context); + +/** + * If enabled, reverb buffers for all modes are kept around allocated all the time to avoid memory + * allocating/freeing in the rendering thread, which may be required for realtime operation. + * Otherwise, reverb buffers that are not in use are deleted to save memory (the default behaviour). + */ +MT32EMU_EXPORT void MT32EMU_C_CALL mt32emu_preallocate_reverb_memory(mt32emu_const_context context, const mt32emu_boolean enabled); /** Sets new DAC input mode. See mt32emu_dac_input_mode for details. */ -MT32EMU_EXPORT void mt32emu_set_dac_input_mode(mt32emu_const_context context, const mt32emu_dac_input_mode mode); +MT32EMU_EXPORT void MT32EMU_C_CALL mt32emu_set_dac_input_mode(mt32emu_const_context context, const mt32emu_dac_input_mode mode); /** Returns current DAC input mode. See mt32emu_dac_input_mode for details. */ -MT32EMU_EXPORT mt32emu_dac_input_mode mt32emu_get_dac_input_mode(mt32emu_const_context context); +MT32EMU_EXPORT mt32emu_dac_input_mode MT32EMU_C_CALL mt32emu_get_dac_input_mode(mt32emu_const_context context); /** Sets new MIDI delay mode. See mt32emu_midi_delay_mode for details. */ -MT32EMU_EXPORT void mt32emu_set_midi_delay_mode(mt32emu_const_context context, const mt32emu_midi_delay_mode mode); +MT32EMU_EXPORT void MT32EMU_C_CALL mt32emu_set_midi_delay_mode(mt32emu_const_context context, const mt32emu_midi_delay_mode mode); /** Returns current MIDI delay mode. See mt32emu_midi_delay_mode for details. */ -MT32EMU_EXPORT mt32emu_midi_delay_mode mt32emu_get_midi_delay_mode(mt32emu_const_context context); +MT32EMU_EXPORT mt32emu_midi_delay_mode MT32EMU_C_CALL mt32emu_get_midi_delay_mode(mt32emu_const_context context); /** * Sets output gain factor for synth output channels. Applied to all output samples and unrelated with the synth's Master volume, * it rather corresponds to the gain of the output analog circuitry of the hardware units. However, together with mt32emu_set_reverb_output_gain() * it offers to the user a capability to control the gain of reverb and non-reverb output channels independently. */ -MT32EMU_EXPORT void mt32emu_set_output_gain(mt32emu_const_context context, float gain); +MT32EMU_EXPORT void MT32EMU_C_CALL mt32emu_set_output_gain(mt32emu_const_context context, float gain); /** Returns current output gain factor for synth output channels. */ -MT32EMU_EXPORT float mt32emu_get_output_gain(mt32emu_const_context context); +MT32EMU_EXPORT float MT32EMU_C_CALL mt32emu_get_output_gain(mt32emu_const_context context); /** * Sets output gain factor for the reverb wet output channels. It rather corresponds to the gain of the output @@ -345,14 +453,34 @@ MT32EMU_EXPORT float mt32emu_get_output_gain(mt32emu_const_context context); * there is a difference in the reverb analogue circuit, and the resulting output gain is 0.68 * of that for LA32 analogue output. This factor is applied to the reverb output gain. */ -MT32EMU_EXPORT void mt32emu_set_reverb_output_gain(mt32emu_const_context context, float gain); +MT32EMU_EXPORT void MT32EMU_C_CALL mt32emu_set_reverb_output_gain(mt32emu_const_context context, float gain); /** Returns current output gain factor for reverb wet output channels. */ -MT32EMU_EXPORT float mt32emu_get_reverb_output_gain(mt32emu_const_context context); +MT32EMU_EXPORT float MT32EMU_C_CALL mt32emu_get_reverb_output_gain(mt32emu_const_context context); + +/** + * Sets (or removes) an override for the current volume (output level) on a specific part. + * When the part volume is overridden, the MIDI controller Volume (7) on the MIDI channel this part is assigned to + * has no effect on the output level of this part. Similarly, the output level value set on this part via a SysEx that + * modifies the Patch temp structure is disregarded. + * To enable the override mode, argument volumeOverride should be in range 0..100, setting a value outside this range + * disables the previously set override, if any. + * Note: Setting volumeOverride to 0 mutes the part completely, meaning no sound is generated at all. + * This is unlike the behaviour of real devices - setting 0 volume on a part may leave it still producing + * sound at a very low level. + * Argument partNumber should be 0..7 for Part 1..8, or 8 for Rhythm. + */ +MT32EMU_EXPORT_V(2.6) void MT32EMU_C_CALL mt32emu_set_part_volume_override(mt32emu_const_context context, mt32emu_bit8u part_number, mt32emu_bit8u volume_override); +/** + * Returns the overridden volume previously set on a specific part; a value outside the range 0..100 means no override + * is currently in effect. + * Argument partNumber should be 0..7 for Part 1..8, or 8 for Rhythm. + */ +MT32EMU_EXPORT_V(2.6) mt32emu_bit8u MT32EMU_C_CALL mt32emu_get_part_volume_override(mt32emu_const_context context, mt32emu_bit8u part_number); /** Swaps left and right output channels. */ -MT32EMU_EXPORT void mt32emu_set_reversed_stereo_enabled(mt32emu_const_context context, const mt32emu_boolean enabled); +MT32EMU_EXPORT void MT32EMU_C_CALL mt32emu_set_reversed_stereo_enabled(mt32emu_const_context context, const mt32emu_boolean enabled); /** Returns whether left and right output channels are swapped. */ -MT32EMU_EXPORT mt32emu_boolean mt32emu_is_reversed_stereo_enabled(mt32emu_const_context context); +MT32EMU_EXPORT mt32emu_boolean MT32EMU_C_CALL mt32emu_is_reversed_stereo_enabled(mt32emu_const_context context); /** * Allows to toggle the NiceAmpRamp mode. @@ -362,9 +490,36 @@ MT32EMU_EXPORT mt32emu_boolean mt32emu_is_reversed_stereo_enabled(mt32emu_const_ * We also prefer the quality improvement over the emulation accuracy, * so this mode is enabled by default. */ -MT32EMU_EXPORT void mt32emu_set_nice_amp_ramp_enabled(mt32emu_const_context context, const mt32emu_boolean enabled); +MT32EMU_EXPORT void MT32EMU_C_CALL mt32emu_set_nice_amp_ramp_enabled(mt32emu_const_context context, const mt32emu_boolean enabled); /** Returns whether NiceAmpRamp mode is enabled. */ -MT32EMU_EXPORT mt32emu_boolean mt32emu_is_nice_amp_ramp_enabled(mt32emu_const_context context); +MT32EMU_EXPORT mt32emu_boolean MT32EMU_C_CALL mt32emu_is_nice_amp_ramp_enabled(mt32emu_const_context context); + +/** + * Allows to toggle the NicePanning mode. + * Despite the Roland's manual specifies allowed panpot values in range 0-14, + * the LA-32 only receives 3-bit pan setting in fact. In particular, this + * makes it impossible to set the "middle" panning for a single partial. + * In the NicePanning mode, we enlarge the pan setting accuracy to 4 bits + * making it smoother thus sacrificing the emulation accuracy. + * This mode is disabled by default. + */ +MT32EMU_EXPORT void MT32EMU_C_CALL mt32emu_set_nice_panning_enabled(mt32emu_const_context context, const mt32emu_boolean enabled); +/** Returns whether NicePanning mode is enabled. */ +MT32EMU_EXPORT mt32emu_boolean MT32EMU_C_CALL mt32emu_is_nice_panning_enabled(mt32emu_const_context context); + +/** + * Allows to toggle the NicePartialMixing mode. + * LA-32 is known to mix partials either in-phase (so that they are added) + * or in counter-phase (so that they are subtracted instead). + * In some cases, this quirk isn't highly desired because a pair of closely + * sounding partials may occasionally cancel out. + * In the NicePartialMixing mode, the mixing is always performed in-phase, + * thus making the behaviour more predictable. + * This mode is disabled by default. + */ +MT32EMU_EXPORT void MT32EMU_C_CALL mt32emu_set_nice_partial_mixing_enabled(mt32emu_const_context context, const mt32emu_boolean enabled); +/** Returns whether NicePartialMixing mode is enabled. */ +MT32EMU_EXPORT mt32emu_boolean MT32EMU_C_CALL mt32emu_is_nice_partial_mixing_enabled(mt32emu_const_context context); /** * Renders samples to the specified output stream as if they were sampled at the analog stereo output at the desired sample rate. @@ -372,9 +527,9 @@ MT32EMU_EXPORT mt32emu_boolean mt32emu_is_nice_amp_ramp_enabled(mt32emu_const_co * mode of analog circuitry emulation. See mt32emu_analog_output_mode. * The length is in frames, not bytes (in 16-bit stereo, one frame is 4 bytes). Uses NATIVE byte ordering. */ -MT32EMU_EXPORT void mt32emu_render_bit16s(mt32emu_const_context context, mt32emu_bit16s *stream, mt32emu_bit32u len); +MT32EMU_EXPORT void MT32EMU_C_CALL mt32emu_render_bit16s(mt32emu_const_context context, mt32emu_bit16s *stream, mt32emu_bit32u len); /** Same as above but outputs to a float stereo stream. */ -MT32EMU_EXPORT void mt32emu_render_float(mt32emu_const_context context, float *stream, mt32emu_bit32u len); +MT32EMU_EXPORT void MT32EMU_C_CALL mt32emu_render_float(mt32emu_const_context context, float *stream, mt32emu_bit32u len); /** * Renders samples to the specified output streams as if they appeared at the DAC entrance. @@ -382,25 +537,25 @@ MT32EMU_EXPORT void mt32emu_render_float(mt32emu_const_context context, float *s * NULL may be specified in place of any or all of the stream buffers to skip it. * The length is in samples, not bytes. Uses NATIVE byte ordering. */ -MT32EMU_EXPORT void mt32emu_render_bit16s_streams(mt32emu_const_context context, const mt32emu_dac_output_bit16s_streams *streams, mt32emu_bit32u len); +MT32EMU_EXPORT void MT32EMU_C_CALL mt32emu_render_bit16s_streams(mt32emu_const_context context, const mt32emu_dac_output_bit16s_streams *streams, mt32emu_bit32u len); /** Same as above but outputs to float streams. */ -MT32EMU_EXPORT void mt32emu_render_float_streams(mt32emu_const_context context, const mt32emu_dac_output_float_streams *streams, mt32emu_bit32u len); +MT32EMU_EXPORT void MT32EMU_C_CALL mt32emu_render_float_streams(mt32emu_const_context context, const mt32emu_dac_output_float_streams *streams, mt32emu_bit32u len); /** Returns true when there is at least one active partial, otherwise false. */ -MT32EMU_EXPORT mt32emu_boolean mt32emu_has_active_partials(mt32emu_const_context context); +MT32EMU_EXPORT mt32emu_boolean MT32EMU_C_CALL mt32emu_has_active_partials(mt32emu_const_context context); /** Returns true if mt32emu_has_active_partials() returns true, or reverb is (somewhat unreliably) detected as being active. */ -MT32EMU_EXPORT mt32emu_boolean mt32emu_is_active(mt32emu_const_context context); +MT32EMU_EXPORT mt32emu_boolean MT32EMU_C_CALL mt32emu_is_active(mt32emu_const_context context); /** Returns the maximum number of partials playing simultaneously. */ -MT32EMU_EXPORT mt32emu_bit32u mt32emu_get_partial_count(mt32emu_const_context context); +MT32EMU_EXPORT mt32emu_bit32u MT32EMU_C_CALL mt32emu_get_partial_count(mt32emu_const_context context); /** * Returns current states of all the parts as a bit set. The least significant bit corresponds to the state of part 1, * total of 9 bits hold the states of all the parts. If the returned bit for a part is set, there is at least one active * non-releasing partial playing on this part. This info is useful in emulating behaviour of LCD display of the hardware units. */ -MT32EMU_EXPORT mt32emu_bit32u mt32emu_get_part_states(mt32emu_const_context context); +MT32EMU_EXPORT mt32emu_bit32u MT32EMU_C_CALL mt32emu_get_part_states(mt32emu_const_context context); /** * Fills in current states of all the partials into the array provided. Each byte in the array holds states of 4 partials @@ -408,7 +563,7 @@ MT32EMU_EXPORT mt32emu_bit32u mt32emu_get_part_states(mt32emu_const_context cont * The array must be large enough to accommodate states of all the partials. * @see getPartialCount() */ -MT32EMU_EXPORT void mt32emu_get_partial_states(mt32emu_const_context context, mt32emu_bit8u *partial_states); +MT32EMU_EXPORT void MT32EMU_C_CALL mt32emu_get_partial_states(mt32emu_const_context context, mt32emu_bit8u *partial_states); /** * Fills in information about currently playing notes on the specified part into the arrays provided. The arrays must be large enough @@ -416,16 +571,71 @@ MT32EMU_EXPORT void mt32emu_get_partial_states(mt32emu_const_context context, mt * Argument partNumber should be 0..7 for Part 1..8, or 8 for Rhythm. * Returns the number of currently playing notes on the specified part. */ -MT32EMU_EXPORT mt32emu_bit32u mt32emu_get_playing_notes(mt32emu_const_context context, mt32emu_bit8u part_number, mt32emu_bit8u *keys, mt32emu_bit8u *velocities); +MT32EMU_EXPORT mt32emu_bit32u MT32EMU_C_CALL mt32emu_get_playing_notes(mt32emu_const_context context, mt32emu_bit8u part_number, mt32emu_bit8u *keys, mt32emu_bit8u *velocities); /** * Returns name of the patch set on the specified part. * Argument partNumber should be 0..7 for Part 1..8, or 8 for Rhythm. + * The returned value is a null-terminated string which is guaranteed to remain valid until the next call to one of functions + * that perform sample rendering or immediate SysEx processing (e.g. mt32emu_play_sysex_now). */ -MT32EMU_EXPORT const char *mt32emu_get_patch_name(mt32emu_const_context context, mt32emu_bit8u part_number); +MT32EMU_EXPORT const char * MT32EMU_C_CALL mt32emu_get_patch_name(mt32emu_const_context context, mt32emu_bit8u part_number); + +/** + * Retrieves the name of the sound group the timbre identified by arguments timbre_group and timbre_number is associated with. + * Values 0-3 of timbre_group correspond to the timbre banks GROUP A, GROUP B, MEMORY and RHYTHM. + * For all but the RHYTHM timbre bank, allowed values of timbre_number are in range 0-63. The number of timbres + * contained in the RHYTHM bank depends on the used control ROM version. + * The argument sound_group_name must point to an array of at least 8 characters. The result is a null-terminated string. + * Returns whether the specified timbre has been found and the result written in sound_group_name. + */ +MT32EMU_EXPORT_V(2.7) mt32emu_boolean MT32EMU_C_CALL mt32emu_get_sound_group_name(mt32emu_const_context context, char *sound_group_name, mt32emu_bit8u timbre_group, mt32emu_bit8u timbre_number); +/** + * Retrieves the name of the timbre identified by arguments timbre_group and timbre_number. + * Values 0-3 of timbre_group correspond to the timbre banks GROUP A, GROUP B, MEMORY and RHYTHM. + * For all but the RHYTHM timbre bank, allowed values of timbre_number are in range 0-63. The number of timbres + * contained in the RHYTHM bank depends on the used control ROM version. + * The argument sound_name must point to an array of at least 11 characters. The result is a null-terminated string. + * Returns whether the specified timbre has been found and the result written in sound_name. + */ +MT32EMU_EXPORT_V(2.7) mt32emu_boolean MT32EMU_C_CALL mt32emu_get_sound_name(mt32emu_const_context context, char *sound_name, mt32emu_bit8u timbreGroup, mt32emu_bit8u timbreNumber); /** Stores internal state of emulated synth into an array provided (as it would be acquired from hardware). */ -MT32EMU_EXPORT void mt32emu_read_memory(mt32emu_const_context context, mt32emu_bit32u addr, mt32emu_bit32u len, mt32emu_bit8u *data); +MT32EMU_EXPORT void MT32EMU_C_CALL mt32emu_read_memory(mt32emu_const_context context, mt32emu_bit32u addr, mt32emu_bit32u len, mt32emu_bit8u *data); + +/** + * Retrieves the current state of the emulated MT-32 display facilities. + * Typically, the state is updated during the rendering. When that happens, a related callback from mt32emu_report_handler_i_v1 + * is invoked. However, there might be no need to invoke this method after each update, e.g. when the render buffer is just + * a few milliseconds long. + * The argument target_buffer must point to an array of at least 21 characters. The result is a null-terminated string. + * The argument narrow_lcd enables a condensed representation of the displayed information in some cases. This is mainly intended + * to route the result to a hardware LCD that is only 16 characters wide. Automatic scrolling of longer strings is not supported. + * Returns whether the MIDI MESSAGE LED is ON and fills the target_buffer parameter. + */ +MT32EMU_EXPORT_V(2.6) mt32emu_boolean MT32EMU_C_CALL mt32emu_get_display_state(mt32emu_const_context context, char *target_buffer, const mt32emu_boolean narrow_lcd); + +/** + * Resets the emulated LCD to the main mode (Master Volume). This has the same effect as pressing the Master Volume button + * while the display shows some other message. Useful for the new-gen devices as those require a special Display Reset SysEx + * to return to the main mode e.g. from showing a custom display message or a checksum error. + */ +MT32EMU_EXPORT_V(2.6) void MT32EMU_C_CALL mt32emu_set_main_display_mode(mt32emu_const_context context); + +/** + * Permits to select an arbitrary display emulation model that does not necessarily match the actual behaviour implemented + * in the control ROM version being used. + * Invoking this method with the argument set to true forces emulation of the old-gen MT-32 display features. + * Otherwise, emulation of the new-gen devices is enforced (these include CM-32L and LAPC-I as if these were connected to an LCD). + */ +MT32EMU_EXPORT_V(2.6) void MT32EMU_C_CALL mt32emu_set_display_compatibility(mt32emu_const_context context, mt32emu_boolean old_mt32_compatibility_enabled); +/** Returns whether the currently configured features of the emulated display are compatible with the old-gen MT-32 devices. */ +MT32EMU_EXPORT_V(2.6) mt32emu_boolean MT32EMU_C_CALL mt32emu_is_display_old_mt32_compatible(mt32emu_const_context context); +/** + * Returns whether the emulated display features configured by default depending on the actual control ROM version + * are compatible with the old-gen MT-32 devices. + */ +MT32EMU_EXPORT_V(2.6) mt32emu_boolean MT32EMU_C_CALL mt32emu_is_default_display_old_mt32_compatible(mt32emu_const_context context); #ifdef __cplusplus } // extern "C" diff --git a/src/include/mt32emu/c_interface/c_types.h b/src/include/mt32emu/c_interface/c_types.h index db612e282..8928bfeae 100644 --- a/src/include/mt32emu/c_interface/c_types.h +++ b/src/include/mt32emu/c_interface/c_types.h @@ -1,5 +1,5 @@ /* Copyright (C) 2003, 2004, 2005, 2006, 2008, 2009 Dean Beeler, Jerome Fisher - * Copyright (C) 2011-2017 Dean Beeler, Jerome Fisher, Sergey V. Mikayev + * Copyright (C) 2011-2022 Dean Beeler, Jerome Fisher, Sergey V. Mikayev * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by @@ -27,6 +27,12 @@ #include "../Enumerations.h" #undef MT32EMU_C_ENUMERATIONS +#ifdef _WIN32 +# define MT32EMU_C_CALL __cdecl +#else +# define MT32EMU_C_CALL +#endif + typedef unsigned int mt32emu_bit32u; typedef signed int mt32emu_bit32s; typedef unsigned short int mt32emu_bit16u; @@ -45,6 +51,8 @@ typedef enum { MT32EMU_RC_OK = 0, MT32EMU_RC_ADDED_CONTROL_ROM = 1, MT32EMU_RC_ADDED_PCM_ROM = 2, + MT32EMU_RC_ADDED_PARTIAL_CONTROL_ROM = 3, + MT32EMU_RC_ADDED_PARTIAL_PCM_ROM = 4, /* Definite error occurred. */ MT32EMU_RC_ROM_NOT_IDENTIFIED = -1, @@ -53,6 +61,8 @@ typedef enum { MT32EMU_RC_MISSING_ROMS = -4, MT32EMU_RC_NOT_OPENED = -5, MT32EMU_RC_QUEUE_FULL = -6, + MT32EMU_RC_ROMS_NOT_PAIRABLE = -7, + MT32EMU_RC_MACHINE_NOT_IDENTIFIED = -8, /* Undefined error occurred. */ MT32EMU_RC_FAILED = -100 @@ -107,7 +117,8 @@ typedef struct { /** Report handler interface versions */ typedef enum { MT32EMU_REPORT_HANDLER_VERSION_0 = 0, - MT32EMU_REPORT_HANDLER_VERSION_CURRENT = MT32EMU_REPORT_HANDLER_VERSION_0 + MT32EMU_REPORT_HANDLER_VERSION_1 = 1, + MT32EMU_REPORT_HANDLER_VERSION_CURRENT = MT32EMU_REPORT_HANDLER_VERSION_1 } mt32emu_report_handler_version; /** MIDI receiver interface versions */ @@ -121,7 +132,11 @@ typedef enum { MT32EMU_SERVICE_VERSION_0 = 0, MT32EMU_SERVICE_VERSION_1 = 1, MT32EMU_SERVICE_VERSION_2 = 2, - MT32EMU_SERVICE_VERSION_CURRENT = MT32EMU_SERVICE_VERSION_2 + MT32EMU_SERVICE_VERSION_3 = 3, + MT32EMU_SERVICE_VERSION_4 = 4, + MT32EMU_SERVICE_VERSION_5 = 5, + MT32EMU_SERVICE_VERSION_6 = 6, + MT32EMU_SERVICE_VERSION_CURRENT = MT32EMU_SERVICE_VERSION_6 } mt32emu_service_version; /* === Report Handler Interface === */ @@ -129,42 +144,59 @@ typedef enum { typedef union mt32emu_report_handler_i mt32emu_report_handler_i; /** Interface for handling reported events (initial version) */ -typedef struct { - /** Returns the actual interface version ID */ - mt32emu_report_handler_version (*getVersionID)(mt32emu_report_handler_i i); - - /** Callback for debug messages, in vprintf() format */ - void (*printDebug)(void *instance_data, const char *fmt, va_list list); - /** Callbacks for reporting errors */ - void (*onErrorControlROM)(void *instance_data); - void (*onErrorPCMROM)(void *instance_data); - /** Callback for reporting about displaying a new custom message on LCD */ - void (*showLCDMessage)(void *instance_data, const char *message); - /** Callback for reporting actual processing of a MIDI message */ - void (*onMIDIMessagePlayed)(void *instance_data); +#define MT32EMU_REPORT_HANDLER_I_V0 \ + /** Returns the actual interface version ID */ \ + mt32emu_report_handler_version (MT32EMU_C_CALL *getVersionID)(mt32emu_report_handler_i i); \ +\ + /** Callback for debug messages, in vprintf() format */ \ + void (MT32EMU_C_CALL *printDebug)(void *instance_data, const char *fmt, va_list list); \ + /** Callbacks for reporting errors */ \ + void (MT32EMU_C_CALL *onErrorControlROM)(void *instance_data); \ + void (MT32EMU_C_CALL *onErrorPCMROM)(void *instance_data); \ + /** Callback for reporting about displaying a new custom message on LCD */ \ + void (MT32EMU_C_CALL *showLCDMessage)(void *instance_data, const char *message); \ + /** Callback for reporting actual processing of a MIDI message */ \ + void (MT32EMU_C_CALL *onMIDIMessagePlayed)(void *instance_data); \ /** * Callback for reporting an overflow of the input MIDI queue. * Returns MT32EMU_BOOL_TRUE if a recovery action was taken * and yet another attempt to enqueue the MIDI event is desired. - */ - mt32emu_boolean (*onMIDIQueueOverflow)(void *instance_data); + */ \ + mt32emu_boolean (MT32EMU_C_CALL *onMIDIQueueOverflow)(void *instance_data); \ /** * Callback invoked when a System Realtime MIDI message is detected in functions * mt32emu_parse_stream and mt32emu_play_short_message and the likes. - */ - void (*onMIDISystemRealtime)(void *instance_data, mt32emu_bit8u system_realtime); - /** Callbacks for reporting system events */ - void (*onDeviceReset)(void *instance_data); - void (*onDeviceReconfig)(void *instance_data); - /** Callbacks for reporting changes of reverb settings */ - void (*onNewReverbMode)(void *instance_data, mt32emu_bit8u mode); - void (*onNewReverbTime)(void *instance_data, mt32emu_bit8u time); - void (*onNewReverbLevel)(void *instance_data, mt32emu_bit8u level); - /** Callbacks for reporting various information */ - void (*onPolyStateChanged)(void *instance_data, mt32emu_bit8u part_num); - void (*onProgramChanged)(void *instance_data, mt32emu_bit8u part_num, const char *sound_group_name, const char *patch_name); + */ \ + void (MT32EMU_C_CALL *onMIDISystemRealtime)(void *instance_data, mt32emu_bit8u system_realtime); \ + /** Callbacks for reporting system events */ \ + void (MT32EMU_C_CALL *onDeviceReset)(void *instance_data); \ + void (MT32EMU_C_CALL *onDeviceReconfig)(void *instance_data); \ + /** Callbacks for reporting changes of reverb settings */ \ + void (MT32EMU_C_CALL *onNewReverbMode)(void *instance_data, mt32emu_bit8u mode); \ + void (MT32EMU_C_CALL *onNewReverbTime)(void *instance_data, mt32emu_bit8u time); \ + void (MT32EMU_C_CALL *onNewReverbLevel)(void *instance_data, mt32emu_bit8u level); \ + /** Callbacks for reporting various information */ \ + void (MT32EMU_C_CALL *onPolyStateChanged)(void *instance_data, mt32emu_bit8u part_num); \ + void (MT32EMU_C_CALL *onProgramChanged)(void *instance_data, mt32emu_bit8u part_num, const char *sound_group_name, const char *patch_name); + +#define MT32EMU_REPORT_HANDLER_I_V1 \ + /** + * Invoked to signal about a change of the emulated LCD state. Use mt32emu_get_display_state to retrieve the actual data. + * This callback will not be invoked on further changes, until the client retrieves the LCD state. + */ \ + void (MT32EMU_C_CALL *onLCDStateUpdated)(void *instance_data); \ + /** Invoked when the emulated MIDI MESSAGE LED changes state. The led_state parameter represents whether the LED is ON. */ \ + void (MT32EMU_C_CALL *onMidiMessageLEDStateUpdated)(void *instance_data, mt32emu_boolean led_state); + +typedef struct { + MT32EMU_REPORT_HANDLER_I_V0 } mt32emu_report_handler_i_v0; +typedef struct { + MT32EMU_REPORT_HANDLER_I_V0 + MT32EMU_REPORT_HANDLER_I_V1 +} mt32emu_report_handler_i_v1; + /** * Extensible interface for handling reported events. * Union intended to view an interface of any subsequent version as any parent interface not requiring a cast. @@ -172,8 +204,12 @@ typedef struct { */ union mt32emu_report_handler_i { const mt32emu_report_handler_i_v0 *v0; + const mt32emu_report_handler_i_v1 *v1; }; +#undef MT32EMU_REPORT_HANDLER_I_V0 +#undef MT32EMU_REPORT_HANDLER_I_V1 + /* === MIDI Receiver Interface === */ typedef union mt32emu_midi_receiver_i mt32emu_midi_receiver_i; @@ -181,16 +217,16 @@ typedef union mt32emu_midi_receiver_i mt32emu_midi_receiver_i; /** Interface for receiving MIDI messages generated by MIDI stream parser (initial version) */ typedef struct { /** Returns the actual interface version ID */ - mt32emu_midi_receiver_version (*getVersionID)(mt32emu_midi_receiver_i i); + mt32emu_midi_receiver_version (MT32EMU_C_CALL *getVersionID)(mt32emu_midi_receiver_i i); /** Invoked when a complete short MIDI message is parsed in the input MIDI stream. */ - void (*handleShortMessage)(void *instance_data, const mt32emu_bit32u message); + void (MT32EMU_C_CALL *handleShortMessage)(void *instance_data, const mt32emu_bit32u message); /** Invoked when a complete well-formed System Exclusive MIDI message is parsed in the input MIDI stream. */ - void (*handleSysex)(void *instance_data, const mt32emu_bit8u stream[], const mt32emu_bit32u length); + void (MT32EMU_C_CALL *handleSysex)(void *instance_data, const mt32emu_bit8u stream[], const mt32emu_bit32u length); /** Invoked when a System Realtime MIDI message is parsed in the input MIDI stream. */ - void (*handleSystemRealtimeMessage)(void *instance_data, const mt32emu_bit8u realtime); + void (MT32EMU_C_CALL *handleSystemRealtimeMessage)(void *instance_data, const mt32emu_bit8u realtime); } mt32emu_midi_receiver_i_v0; /** @@ -215,93 +251,124 @@ typedef union mt32emu_service_i mt32emu_service_i; */ #define MT32EMU_SERVICE_I_V0 \ /** Returns the actual interface version ID */ \ - mt32emu_service_version (*getVersionID)(mt32emu_service_i i); \ - mt32emu_report_handler_version (*getSupportedReportHandlerVersionID)(); \ - mt32emu_midi_receiver_version (*getSupportedMIDIReceiverVersionID)(); \ + mt32emu_service_version (MT32EMU_C_CALL *getVersionID)(mt32emu_service_i i); \ + mt32emu_report_handler_version (MT32EMU_C_CALL *getSupportedReportHandlerVersionID)(void); \ + mt32emu_midi_receiver_version (MT32EMU_C_CALL *getSupportedMIDIReceiverVersionID)(void); \ \ - mt32emu_bit32u (*getLibraryVersionInt)(); \ - const char *(*getLibraryVersionString)(); \ + mt32emu_bit32u (MT32EMU_C_CALL *getLibraryVersionInt)(void); \ + const char *(MT32EMU_C_CALL *getLibraryVersionString)(void); \ \ - mt32emu_bit32u (*getStereoOutputSamplerate)(const mt32emu_analog_output_mode analog_output_mode); \ + mt32emu_bit32u (MT32EMU_C_CALL *getStereoOutputSamplerate)(const mt32emu_analog_output_mode analog_output_mode); \ \ - mt32emu_context (*createContext)(mt32emu_report_handler_i report_handler, void *instance_data); \ - void (*freeContext)(mt32emu_context context); \ - mt32emu_return_code (*addROMData)(mt32emu_context context, const mt32emu_bit8u *data, size_t data_size, const mt32emu_sha1_digest *sha1_digest); \ - mt32emu_return_code (*addROMFile)(mt32emu_context context, const char *filename); \ - void (*getROMInfo)(mt32emu_const_context context, mt32emu_rom_info *rom_info); \ - void (*setPartialCount)(mt32emu_context context, const mt32emu_bit32u partial_count); \ - void (*setAnalogOutputMode)(mt32emu_context context, const mt32emu_analog_output_mode analog_output_mode); \ - mt32emu_return_code (*openSynth)(mt32emu_const_context context); \ - void (*closeSynth)(mt32emu_const_context context); \ - mt32emu_boolean (*isOpen)(mt32emu_const_context context); \ - mt32emu_bit32u (*getActualStereoOutputSamplerate)(mt32emu_const_context context); \ - void (*flushMIDIQueue)(mt32emu_const_context context); \ - mt32emu_bit32u (*setMIDIEventQueueSize)(mt32emu_const_context context, const mt32emu_bit32u queue_size); \ - void (*setMIDIReceiver)(mt32emu_context context, mt32emu_midi_receiver_i midi_receiver, void *instance_data); \ + mt32emu_context (MT32EMU_C_CALL *createContext)(mt32emu_report_handler_i report_handler, void *instance_data); \ + void (MT32EMU_C_CALL *freeContext)(mt32emu_context context); \ + mt32emu_return_code (MT32EMU_C_CALL *addROMData)(mt32emu_context context, const mt32emu_bit8u *data, size_t data_size, const mt32emu_sha1_digest *sha1_digest); \ + mt32emu_return_code (MT32EMU_C_CALL *addROMFile)(mt32emu_context context, const char *filename); \ + void (MT32EMU_C_CALL *getROMInfo)(mt32emu_const_context context, mt32emu_rom_info *rom_info); \ + void (MT32EMU_C_CALL *setPartialCount)(mt32emu_context context, const mt32emu_bit32u partial_count); \ + void (MT32EMU_C_CALL *setAnalogOutputMode)(mt32emu_context context, const mt32emu_analog_output_mode analog_output_mode); \ + mt32emu_return_code (MT32EMU_C_CALL *openSynth)(mt32emu_const_context context); \ + void (MT32EMU_C_CALL *closeSynth)(mt32emu_const_context context); \ + mt32emu_boolean (MT32EMU_C_CALL *isOpen)(mt32emu_const_context context); \ + mt32emu_bit32u (MT32EMU_C_CALL *getActualStereoOutputSamplerate)(mt32emu_const_context context); \ + void (MT32EMU_C_CALL *flushMIDIQueue)(mt32emu_const_context context); \ + mt32emu_bit32u (MT32EMU_C_CALL *setMIDIEventQueueSize)(mt32emu_const_context context, const mt32emu_bit32u queue_size); \ + void (MT32EMU_C_CALL *setMIDIReceiver)(mt32emu_context context, mt32emu_midi_receiver_i midi_receiver, void *instance_data); \ \ - void (*parseStream)(mt32emu_const_context context, const mt32emu_bit8u *stream, mt32emu_bit32u length); \ - void (*parseStream_At)(mt32emu_const_context context, const mt32emu_bit8u *stream, mt32emu_bit32u length, mt32emu_bit32u timestamp); \ - void (*playShortMessage)(mt32emu_const_context context, mt32emu_bit32u message); \ - void (*playShortMessageAt)(mt32emu_const_context context, mt32emu_bit32u message, mt32emu_bit32u timestamp); \ - mt32emu_return_code (*playMsg)(mt32emu_const_context context, mt32emu_bit32u msg); \ - mt32emu_return_code (*playSysex)(mt32emu_const_context context, const mt32emu_bit8u *sysex, mt32emu_bit32u len); \ - mt32emu_return_code (*playMsgAt)(mt32emu_const_context context, mt32emu_bit32u msg, mt32emu_bit32u timestamp); \ - mt32emu_return_code (*playSysexAt)(mt32emu_const_context context, const mt32emu_bit8u *sysex, mt32emu_bit32u len, mt32emu_bit32u timestamp); \ + void (MT32EMU_C_CALL *parseStream)(mt32emu_const_context context, const mt32emu_bit8u *stream, mt32emu_bit32u length); \ + void (MT32EMU_C_CALL *parseStream_At)(mt32emu_const_context context, const mt32emu_bit8u *stream, mt32emu_bit32u length, mt32emu_bit32u timestamp); \ + void (MT32EMU_C_CALL *playShortMessage)(mt32emu_const_context context, mt32emu_bit32u message); \ + void (MT32EMU_C_CALL *playShortMessageAt)(mt32emu_const_context context, mt32emu_bit32u message, mt32emu_bit32u timestamp); \ + mt32emu_return_code (MT32EMU_C_CALL *playMsg)(mt32emu_const_context context, mt32emu_bit32u msg); \ + mt32emu_return_code (MT32EMU_C_CALL *playSysex)(mt32emu_const_context context, const mt32emu_bit8u *sysex, mt32emu_bit32u len); \ + mt32emu_return_code (MT32EMU_C_CALL *playMsgAt)(mt32emu_const_context context, mt32emu_bit32u msg, mt32emu_bit32u timestamp); \ + mt32emu_return_code (MT32EMU_C_CALL *playSysexAt)(mt32emu_const_context context, const mt32emu_bit8u *sysex, mt32emu_bit32u len, mt32emu_bit32u timestamp); \ \ - void (*playMsgNow)(mt32emu_const_context context, mt32emu_bit32u msg); \ - void (*playMsgOnPart)(mt32emu_const_context context, mt32emu_bit8u part, mt32emu_bit8u code, mt32emu_bit8u note, mt32emu_bit8u velocity); \ - void (*playSysexNow)(mt32emu_const_context context, const mt32emu_bit8u *sysex, mt32emu_bit32u len); \ - void (*writeSysex)(mt32emu_const_context context, mt32emu_bit8u channel, const mt32emu_bit8u *sysex, mt32emu_bit32u len); \ + void (MT32EMU_C_CALL *playMsgNow)(mt32emu_const_context context, mt32emu_bit32u msg); \ + void (MT32EMU_C_CALL *playMsgOnPart)(mt32emu_const_context context, mt32emu_bit8u part, mt32emu_bit8u code, mt32emu_bit8u note, mt32emu_bit8u velocity); \ + void (MT32EMU_C_CALL *playSysexNow)(mt32emu_const_context context, const mt32emu_bit8u *sysex, mt32emu_bit32u len); \ + void (MT32EMU_C_CALL *writeSysex)(mt32emu_const_context context, mt32emu_bit8u channel, const mt32emu_bit8u *sysex, mt32emu_bit32u len); \ \ - void (*setReverbEnabled)(mt32emu_const_context context, const mt32emu_boolean reverb_enabled); \ - mt32emu_boolean (*isReverbEnabled)(mt32emu_const_context context); \ - void (*setReverbOverridden)(mt32emu_const_context context, const mt32emu_boolean reverb_overridden); \ - mt32emu_boolean (*isReverbOverridden)(mt32emu_const_context context); \ - void (*setReverbCompatibilityMode)(mt32emu_const_context context, const mt32emu_boolean mt32_compatible_mode); \ - mt32emu_boolean (*isMT32ReverbCompatibilityMode)(mt32emu_const_context context); \ - mt32emu_boolean (*isDefaultReverbMT32Compatible)(mt32emu_const_context context); \ + void (MT32EMU_C_CALL *setReverbEnabled)(mt32emu_const_context context, const mt32emu_boolean reverb_enabled); \ + mt32emu_boolean (MT32EMU_C_CALL *isReverbEnabled)(mt32emu_const_context context); \ + void (MT32EMU_C_CALL *setReverbOverridden)(mt32emu_const_context context, const mt32emu_boolean reverb_overridden); \ + mt32emu_boolean (MT32EMU_C_CALL *isReverbOverridden)(mt32emu_const_context context); \ + void (MT32EMU_C_CALL *setReverbCompatibilityMode)(mt32emu_const_context context, const mt32emu_boolean mt32_compatible_mode); \ + mt32emu_boolean (MT32EMU_C_CALL *isMT32ReverbCompatibilityMode)(mt32emu_const_context context); \ + mt32emu_boolean (MT32EMU_C_CALL *isDefaultReverbMT32Compatible)(mt32emu_const_context context); \ \ - void (*setDACInputMode)(mt32emu_const_context context, const mt32emu_dac_input_mode mode); \ - mt32emu_dac_input_mode (*getDACInputMode)(mt32emu_const_context context); \ + void (MT32EMU_C_CALL *setDACInputMode)(mt32emu_const_context context, const mt32emu_dac_input_mode mode); \ + mt32emu_dac_input_mode (MT32EMU_C_CALL *getDACInputMode)(mt32emu_const_context context); \ \ - void (*setMIDIDelayMode)(mt32emu_const_context context, const mt32emu_midi_delay_mode mode); \ - mt32emu_midi_delay_mode (*getMIDIDelayMode)(mt32emu_const_context context); \ + void (MT32EMU_C_CALL *setMIDIDelayMode)(mt32emu_const_context context, const mt32emu_midi_delay_mode mode); \ + mt32emu_midi_delay_mode (MT32EMU_C_CALL *getMIDIDelayMode)(mt32emu_const_context context); \ \ - void (*setOutputGain)(mt32emu_const_context context, float gain); \ - float (*getOutputGain)(mt32emu_const_context context); \ - void (*setReverbOutputGain)(mt32emu_const_context context, float gain); \ - float (*getReverbOutputGain)(mt32emu_const_context context); \ + void (MT32EMU_C_CALL *setOutputGain)(mt32emu_const_context context, float gain); \ + float (MT32EMU_C_CALL *getOutputGain)(mt32emu_const_context context); \ + void (MT32EMU_C_CALL *setReverbOutputGain)(mt32emu_const_context context, float gain); \ + float (MT32EMU_C_CALL *getReverbOutputGain)(mt32emu_const_context context); \ \ - void (*setReversedStereoEnabled)(mt32emu_const_context context, const mt32emu_boolean enabled); \ - mt32emu_boolean (*isReversedStereoEnabled)(mt32emu_const_context context); \ + void (MT32EMU_C_CALL *setReversedStereoEnabled)(mt32emu_const_context context, const mt32emu_boolean enabled); \ + mt32emu_boolean (MT32EMU_C_CALL *isReversedStereoEnabled)(mt32emu_const_context context); \ \ - void (*renderBit16s)(mt32emu_const_context context, mt32emu_bit16s *stream, mt32emu_bit32u len); \ - void (*renderFloat)(mt32emu_const_context context, float *stream, mt32emu_bit32u len); \ - void (*renderBit16sStreams)(mt32emu_const_context context, const mt32emu_dac_output_bit16s_streams *streams, mt32emu_bit32u len); \ - void (*renderFloatStreams)(mt32emu_const_context context, const mt32emu_dac_output_float_streams *streams, mt32emu_bit32u len); \ + void (MT32EMU_C_CALL *renderBit16s)(mt32emu_const_context context, mt32emu_bit16s *stream, mt32emu_bit32u len); \ + void (MT32EMU_C_CALL *renderFloat)(mt32emu_const_context context, float *stream, mt32emu_bit32u len); \ + void (MT32EMU_C_CALL *renderBit16sStreams)(mt32emu_const_context context, const mt32emu_dac_output_bit16s_streams *streams, mt32emu_bit32u len); \ + void (MT32EMU_C_CALL *renderFloatStreams)(mt32emu_const_context context, const mt32emu_dac_output_float_streams *streams, mt32emu_bit32u len); \ \ - mt32emu_boolean (*hasActivePartials)(mt32emu_const_context context); \ - mt32emu_boolean (*isActive)(mt32emu_const_context context); \ - mt32emu_bit32u (*getPartialCount)(mt32emu_const_context context); \ - mt32emu_bit32u (*getPartStates)(mt32emu_const_context context); \ - void (*getPartialStates)(mt32emu_const_context context, mt32emu_bit8u *partial_states); \ - mt32emu_bit32u (*getPlayingNotes)(mt32emu_const_context context, mt32emu_bit8u part_number, mt32emu_bit8u *keys, mt32emu_bit8u *velocities); \ - const char *(*getPatchName)(mt32emu_const_context context, mt32emu_bit8u part_number); \ - void (*readMemory)(mt32emu_const_context context, mt32emu_bit32u addr, mt32emu_bit32u len, mt32emu_bit8u *data); + mt32emu_boolean (MT32EMU_C_CALL *hasActivePartials)(mt32emu_const_context context); \ + mt32emu_boolean (MT32EMU_C_CALL *isActive)(mt32emu_const_context context); \ + mt32emu_bit32u (MT32EMU_C_CALL *getPartialCount)(mt32emu_const_context context); \ + mt32emu_bit32u (MT32EMU_C_CALL *getPartStates)(mt32emu_const_context context); \ + void (MT32EMU_C_CALL *getPartialStates)(mt32emu_const_context context, mt32emu_bit8u *partial_states); \ + mt32emu_bit32u (MT32EMU_C_CALL *getPlayingNotes)(mt32emu_const_context context, mt32emu_bit8u part_number, mt32emu_bit8u *keys, mt32emu_bit8u *velocities); \ + const char *(MT32EMU_C_CALL *getPatchName)(mt32emu_const_context context, mt32emu_bit8u part_number); \ + void (MT32EMU_C_CALL *readMemory)(mt32emu_const_context context, mt32emu_bit32u addr, mt32emu_bit32u len, mt32emu_bit8u *data); #define MT32EMU_SERVICE_I_V1 \ - mt32emu_analog_output_mode (*getBestAnalogOutputMode)(const double target_samplerate); \ - void (*setStereoOutputSampleRate)(mt32emu_context context, const double samplerate); \ - void (*setSamplerateConversionQuality)(mt32emu_context context, const mt32emu_samplerate_conversion_quality quality); \ - void (*selectRendererType)(mt32emu_context context, mt32emu_renderer_type renderer_type); \ - mt32emu_renderer_type (*getSelectedRendererType)(mt32emu_context context); \ - mt32emu_bit32u (*convertOutputToSynthTimestamp)(mt32emu_const_context context, mt32emu_bit32u output_timestamp); \ - mt32emu_bit32u (*convertSynthToOutputTimestamp)(mt32emu_const_context context, mt32emu_bit32u synth_timestamp); + mt32emu_analog_output_mode (MT32EMU_C_CALL *getBestAnalogOutputMode)(const double target_samplerate); \ + void (MT32EMU_C_CALL *setStereoOutputSampleRate)(mt32emu_context context, const double samplerate); \ + void (MT32EMU_C_CALL *setSamplerateConversionQuality)(mt32emu_context context, const mt32emu_samplerate_conversion_quality quality); \ + void (MT32EMU_C_CALL *selectRendererType)(mt32emu_context context, mt32emu_renderer_type renderer_type); \ + mt32emu_renderer_type (MT32EMU_C_CALL *getSelectedRendererType)(mt32emu_context context); \ + mt32emu_bit32u (MT32EMU_C_CALL *convertOutputToSynthTimestamp)(mt32emu_const_context context, mt32emu_bit32u output_timestamp); \ + mt32emu_bit32u (MT32EMU_C_CALL *convertSynthToOutputTimestamp)(mt32emu_const_context context, mt32emu_bit32u synth_timestamp); #define MT32EMU_SERVICE_I_V2 \ - mt32emu_bit32u (*getInternalRenderedSampleCount)(mt32emu_const_context context); \ - void (*setNiceAmpRampEnabled)(mt32emu_const_context context, const mt32emu_boolean enabled); \ - mt32emu_boolean (*isNiceAmpRampEnabled)(mt32emu_const_context context); + mt32emu_bit32u (MT32EMU_C_CALL *getInternalRenderedSampleCount)(mt32emu_const_context context); \ + void (MT32EMU_C_CALL *setNiceAmpRampEnabled)(mt32emu_const_context context, const mt32emu_boolean enabled); \ + mt32emu_boolean (MT32EMU_C_CALL *isNiceAmpRampEnabled)(mt32emu_const_context context); + +#define MT32EMU_SERVICE_I_V3 \ + void (MT32EMU_C_CALL *setNicePanningEnabled)(mt32emu_const_context context, const mt32emu_boolean enabled); \ + mt32emu_boolean (MT32EMU_C_CALL *isNicePanningEnabled)(mt32emu_const_context context); \ + void (MT32EMU_C_CALL *setNicePartialMixingEnabled)(mt32emu_const_context context, const mt32emu_boolean enabled); \ + mt32emu_boolean (MT32EMU_C_CALL *isNicePartialMixingEnabled)(mt32emu_const_context context); \ + void (MT32EMU_C_CALL *preallocateReverbMemory)(mt32emu_const_context context, const mt32emu_boolean enabled); \ + void (MT32EMU_C_CALL *configureMIDIEventQueueSysexStorage)(mt32emu_const_context context, const mt32emu_bit32u storage_buffer_size); + +#define MT32EMU_SERVICE_I_V4 \ + size_t (MT32EMU_C_CALL *getMachineIDs)(const char **machine_ids, size_t machine_ids_size); \ + size_t (MT32EMU_C_CALL *getROMIDs)(const char **rom_ids, size_t rom_ids_size, const char *machine_id); \ + mt32emu_return_code (MT32EMU_C_CALL *identifyROMData)(mt32emu_rom_info *rom_info, const mt32emu_bit8u *data, size_t data_size, const char *machine_id); \ + mt32emu_return_code (MT32EMU_C_CALL *identifyROMFile)(mt32emu_rom_info *rom_info, const char *filename, const char *machine_id); \ +\ + mt32emu_return_code (MT32EMU_C_CALL *mergeAndAddROMData)(mt32emu_context context, const mt32emu_bit8u *part1_data, size_t part1_data_size, const mt32emu_sha1_digest *part1_sha1_digest, const mt32emu_bit8u *part2_data, size_t part2_data_size, const mt32emu_sha1_digest *part2_sha1_digest); \ + mt32emu_return_code (MT32EMU_C_CALL *mergeAndAddROMFiles)(mt32emu_context context, const char *part1_filename, const char *part2_filename); \ + mt32emu_return_code (MT32EMU_C_CALL *addMachineROMFile)(mt32emu_context context, const char *machine_id, const char *filename); + +#define MT32EMU_SERVICE_I_V5 \ + mt32emu_boolean (MT32EMU_C_CALL *getDisplayState)(mt32emu_const_context context, char *target_buffer, const mt32emu_boolean narrow_lcd); \ + void (MT32EMU_C_CALL *setMainDisplayMode)(mt32emu_const_context context); \ + void (MT32EMU_C_CALL *setDisplayCompatibility)(mt32emu_const_context context, mt32emu_boolean old_mt32_compatibility_enabled); \ + mt32emu_boolean (MT32EMU_C_CALL *isDisplayOldMT32Compatible)(mt32emu_const_context context); \ + mt32emu_boolean (MT32EMU_C_CALL *isDefaultDisplayOldMT32Compatible)(mt32emu_const_context context); \ + void (MT32EMU_C_CALL *setPartVolumeOverride)(mt32emu_const_context context, mt32emu_bit8u part_number, mt32emu_bit8u volume_override); \ + mt32emu_bit8u (MT32EMU_C_CALL *getPartVolumeOverride)(mt32emu_const_context context, mt32emu_bit8u part_number); + +#define MT32EMU_SERVICE_I_V6 \ + mt32emu_boolean (MT32EMU_C_CALL *getSoundGroupName)(mt32emu_const_context context, char *sound_group_name, mt32emu_bit8u timbre_group, mt32emu_bit8u timbre_number); \ + mt32emu_boolean (MT32EMU_C_CALL *getSoundName)(mt32emu_const_context context, char *sound_name, mt32emu_bit8u timbre_group, mt32emu_bit8u timbre_number); typedef struct { MT32EMU_SERVICE_I_V0 @@ -318,6 +385,40 @@ typedef struct { MT32EMU_SERVICE_I_V2 } mt32emu_service_i_v2; +typedef struct { + MT32EMU_SERVICE_I_V0 + MT32EMU_SERVICE_I_V1 + MT32EMU_SERVICE_I_V2 + MT32EMU_SERVICE_I_V3 +} mt32emu_service_i_v3; + +typedef struct { + MT32EMU_SERVICE_I_V0 + MT32EMU_SERVICE_I_V1 + MT32EMU_SERVICE_I_V2 + MT32EMU_SERVICE_I_V3 + MT32EMU_SERVICE_I_V4 +} mt32emu_service_i_v4; + +typedef struct { + MT32EMU_SERVICE_I_V0 + MT32EMU_SERVICE_I_V1 + MT32EMU_SERVICE_I_V2 + MT32EMU_SERVICE_I_V3 + MT32EMU_SERVICE_I_V4 + MT32EMU_SERVICE_I_V5 +} mt32emu_service_i_v5; + +typedef struct { + MT32EMU_SERVICE_I_V0 + MT32EMU_SERVICE_I_V1 + MT32EMU_SERVICE_I_V2 + MT32EMU_SERVICE_I_V3 + MT32EMU_SERVICE_I_V4 + MT32EMU_SERVICE_I_V5 + MT32EMU_SERVICE_I_V6 +} mt32emu_service_i_v6; + /** * Extensible interface for all the library services. * Union intended to view an interface of any subsequent version as any parent interface not requiring a cast. @@ -327,10 +428,18 @@ union mt32emu_service_i { const mt32emu_service_i_v0 *v0; const mt32emu_service_i_v1 *v1; const mt32emu_service_i_v2 *v2; + const mt32emu_service_i_v3 *v3; + const mt32emu_service_i_v4 *v4; + const mt32emu_service_i_v5 *v5; + const mt32emu_service_i_v6 *v6; }; #undef MT32EMU_SERVICE_I_V0 #undef MT32EMU_SERVICE_I_V1 #undef MT32EMU_SERVICE_I_V2 +#undef MT32EMU_SERVICE_I_V3 +#undef MT32EMU_SERVICE_I_V4 +#undef MT32EMU_SERVICE_I_V5 +#undef MT32EMU_SERVICE_I_V6 #endif /* #ifndef MT32EMU_C_TYPES_H */ diff --git a/src/include/mt32emu/c_interface/cpp_interface.h b/src/include/mt32emu/c_interface/cpp_interface.h index 3b02c0325..d22897b74 100644 --- a/src/include/mt32emu/c_interface/cpp_interface.h +++ b/src/include/mt32emu/c_interface/cpp_interface.h @@ -1,5 +1,5 @@ /* Copyright (C) 2003, 2004, 2005, 2006, 2008, 2009 Dean Beeler, Jerome Fisher - * Copyright (C) 2011-2017 Dean Beeler, Jerome Fisher, Sergey V. Mikayev + * Copyright (C) 2011-2022 Dean Beeler, Jerome Fisher, Sergey V. Mikayev * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by @@ -41,10 +41,17 @@ mt32emu_service_i mt32emu_get_service_i(); #define mt32emu_get_library_version_string i.v0->getLibraryVersionString #define mt32emu_get_stereo_output_samplerate i.v0->getStereoOutputSamplerate #define mt32emu_get_best_analog_output_mode iV1()->getBestAnalogOutputMode +#define mt32emu_get_machine_ids iV4()->getMachineIDs +#define mt32emu_get_rom_ids iV4()->getROMIDs +#define mt32emu_identify_rom_data iV4()->identifyROMData +#define mt32emu_identify_rom_file iV4()->identifyROMFile #define mt32emu_create_context i.v0->createContext #define mt32emu_free_context i.v0->freeContext #define mt32emu_add_rom_data i.v0->addROMData #define mt32emu_add_rom_file i.v0->addROMFile +#define mt32emu_merge_and_add_rom_data iV4()->mergeAndAddROMData +#define mt32emu_merge_and_add_rom_files iV4()->mergeAndAddROMFiles +#define mt32emu_add_machine_rom_file iV4()->addMachineROMFile #define mt32emu_get_rom_info i.v0->getROMInfo #define mt32emu_set_partial_count i.v0->setPartialCount #define mt32emu_set_analog_output_mode i.v0->setAnalogOutputMode @@ -60,6 +67,7 @@ mt32emu_service_i mt32emu_get_service_i(); #define mt32emu_convert_synth_to_output_timestamp iV1()->convertSynthToOutputTimestamp #define mt32emu_flush_midi_queue i.v0->flushMIDIQueue #define mt32emu_set_midi_event_queue_size i.v0->setMIDIEventQueueSize +#define mt32emu_configure_midi_event_queue_sysex_storage iV3()->configureMIDIEventQueueSysexStorage #define mt32emu_set_midi_receiver i.v0->setMIDIReceiver #define mt32emu_get_internal_rendered_sample_count iV2()->getInternalRenderedSampleCount #define mt32emu_parse_stream i.v0->parseStream @@ -81,6 +89,7 @@ mt32emu_service_i mt32emu_get_service_i(); #define mt32emu_set_reverb_compatibility_mode i.v0->setReverbCompatibilityMode #define mt32emu_is_mt32_reverb_compatibility_mode i.v0->isMT32ReverbCompatibilityMode #define mt32emu_is_default_reverb_mt32_compatible i.v0->isDefaultReverbMT32Compatible +#define mt32emu_preallocate_reverb_memory iV3()->preallocateReverbMemory #define mt32emu_set_dac_input_mode i.v0->setDACInputMode #define mt32emu_get_dac_input_mode i.v0->getDACInputMode #define mt32emu_set_midi_delay_mode i.v0->setMIDIDelayMode @@ -89,10 +98,16 @@ mt32emu_service_i mt32emu_get_service_i(); #define mt32emu_get_output_gain i.v0->getOutputGain #define mt32emu_set_reverb_output_gain i.v0->setReverbOutputGain #define mt32emu_get_reverb_output_gain i.v0->getReverbOutputGain +#define mt32emu_set_part_volume_override iV5()->setPartVolumeOverride +#define mt32emu_get_part_volume_override iV5()->getPartVolumeOverride #define mt32emu_set_reversed_stereo_enabled i.v0->setReversedStereoEnabled #define mt32emu_is_reversed_stereo_enabled i.v0->isReversedStereoEnabled #define mt32emu_set_nice_amp_ramp_enabled iV2()->setNiceAmpRampEnabled #define mt32emu_is_nice_amp_ramp_enabled iV2()->isNiceAmpRampEnabled +#define mt32emu_set_nice_panning_enabled iV3()->setNicePanningEnabled +#define mt32emu_is_nice_panning_enabled iV3()->isNicePanningEnabled +#define mt32emu_set_nice_partial_mixing_enabled iV3()->setNicePartialMixingEnabled +#define mt32emu_is_nice_partial_mixing_enabled iV3()->isNicePartialMixingEnabled #define mt32emu_render_bit16s i.v0->renderBit16s #define mt32emu_render_float i.v0->renderFloat #define mt32emu_render_bit16s_streams i.v0->renderBit16sStreams @@ -104,7 +119,14 @@ mt32emu_service_i mt32emu_get_service_i(); #define mt32emu_get_partial_states i.v0->getPartialStates #define mt32emu_get_playing_notes i.v0->getPlayingNotes #define mt32emu_get_patch_name i.v0->getPatchName +#define mt32emu_get_sound_group_name iV6()->getSoundGroupName +#define mt32emu_get_sound_name iV6()->getSoundName #define mt32emu_read_memory i.v0->readMemory +#define mt32emu_get_display_state iV5()->getDisplayState +#define mt32emu_set_main_display_mode iV5()->setMainDisplayMode +#define mt32emu_set_display_compatibility iV5()->setDisplayCompatibility +#define mt32emu_is_display_old_mt32_compatible iV5()->isDisplayOldMT32Compatible +#define mt32emu_is_default_display_old_mt32_compatible iV5()->isDefaultDisplayOldMT32Compatible #else // #if MT32EMU_API_TYPE == 2 @@ -117,7 +139,7 @@ namespace MT32Emu { namespace CppInterfaceImpl { static const mt32emu_report_handler_i NULL_REPORT_HANDLER = { NULL }; -static mt32emu_report_handler_i getReportHandlerThunk(); +static mt32emu_report_handler_i getReportHandlerThunk(mt32emu_report_handler_version); static mt32emu_midi_receiver_i getMidiReceiverThunk(); } @@ -130,8 +152,8 @@ static mt32emu_midi_receiver_i getMidiReceiverThunk(); * See c_types.h and c_interface.h for description of the corresponding interface methods. */ -// Defines the interface for handling reported events. -// Corresponds to the current version of mt32emu_report_handler_i interface. +// Defines the interface for handling reported events (initial version). +// Corresponds to the mt32emu_report_handler_i_v0 interface. class IReportHandler { public: virtual void printDebug(const char *fmt, va_list list) = 0; @@ -153,6 +175,17 @@ protected: ~IReportHandler() {} }; +// Extends IReportHandler, so that the client may supply callbacks for reporting signals about updated display state. +// Corresponds to the mt32emu_report_handler_i_v1 interface. +class IReportHandlerV1 : public IReportHandler { +public: + virtual void onLCDStateUpdated() = 0; + virtual void onMidiMessageLEDStateUpdated(bool ledState) = 0; + +protected: + ~IReportHandlerV1() {} +}; + // Defines the interface for receiving MIDI messages generated by MIDI stream parser. // Corresponds to the current version of mt32emu_midi_receiver_i interface. class IMidiReceiver { @@ -190,14 +223,24 @@ public: Bit32u getStereoOutputSamplerate(const AnalogOutputMode analog_output_mode) { return mt32emu_get_stereo_output_samplerate(static_cast(analog_output_mode)); } AnalogOutputMode getBestAnalogOutputMode(const double target_samplerate) { return static_cast(mt32emu_get_best_analog_output_mode(target_samplerate)); } + size_t getMachineIDs(const char **machine_ids, size_t machine_ids_size) { return mt32emu_get_machine_ids(machine_ids, machine_ids_size); } + size_t getROMIDs(const char **rom_ids, size_t rom_ids_size, const char *machine_id) { return mt32emu_get_rom_ids(rom_ids, rom_ids_size, machine_id); } + mt32emu_return_code identifyROMData(mt32emu_rom_info *rom_info, const Bit8u *data, size_t data_size, const char *machine_id) { return mt32emu_identify_rom_data(rom_info, data, data_size, machine_id); } + mt32emu_return_code identifyROMFile(mt32emu_rom_info *rom_info, const char *filename, const char *machine_id) { return mt32emu_identify_rom_file(rom_info, filename, machine_id); } + // Context-dependent methods mt32emu_context getContext() { return c; } void createContext(mt32emu_report_handler_i report_handler = CppInterfaceImpl::NULL_REPORT_HANDLER, void *instance_data = NULL) { freeContext(); c = mt32emu_create_context(report_handler, instance_data); } - void createContext(IReportHandler &report_handler) { createContext(CppInterfaceImpl::getReportHandlerThunk(), &report_handler); } + void createContext(IReportHandler &report_handler) { createContext(CppInterfaceImpl::getReportHandlerThunk(MT32EMU_REPORT_HANDLER_VERSION_0), &report_handler); } + void createContext(IReportHandlerV1 &report_handler) { createContext(CppInterfaceImpl::getReportHandlerThunk(MT32EMU_REPORT_HANDLER_VERSION_1), &report_handler); } void freeContext() { if (c != NULL) { mt32emu_free_context(c); c = NULL; } } mt32emu_return_code addROMData(const Bit8u *data, size_t data_size, const mt32emu_sha1_digest *sha1_digest = NULL) { return mt32emu_add_rom_data(c, data, data_size, sha1_digest); } mt32emu_return_code addROMFile(const char *filename) { return mt32emu_add_rom_file(c, filename); } + mt32emu_return_code mergeAndAddROMData(const Bit8u *part1_data, size_t part1_data_size, const Bit8u *part2_data, size_t part2_data_size) { return mt32emu_merge_and_add_rom_data(c, part1_data, part1_data_size, NULL, part2_data, part2_data_size, NULL); } + mt32emu_return_code mergeAndAddROMData(const Bit8u *part1_data, size_t part1_data_size, const mt32emu_sha1_digest *part1_sha1_digest, const Bit8u *part2_data, size_t part2_data_size, const mt32emu_sha1_digest *part2_sha1_digest) { return mt32emu_merge_and_add_rom_data(c, part1_data, part1_data_size, part1_sha1_digest, part2_data, part2_data_size, part2_sha1_digest); } + mt32emu_return_code mergeAndAddROMFiles(const char *part1_filename, const char *part2_filename) { return mt32emu_merge_and_add_rom_files(c, part1_filename, part2_filename); } + mt32emu_return_code addMachineROMFile(const char *machine_id, const char *filename) { return mt32emu_add_machine_rom_file(c, machine_id, filename); } void getROMInfo(mt32emu_rom_info *rom_info) { mt32emu_get_rom_info(c, rom_info); } void setPartialCount(const Bit32u partial_count) { mt32emu_set_partial_count(c, partial_count); } void setAnalogOutputMode(const AnalogOutputMode analog_output_mode) { mt32emu_set_analog_output_mode(c, static_cast(analog_output_mode)); } @@ -213,6 +256,7 @@ public: Bit32u convertSynthToOutputTimestamp(Bit32u synth_timestamp) { return mt32emu_convert_synth_to_output_timestamp(c, synth_timestamp); } void flushMIDIQueue() { mt32emu_flush_midi_queue(c); } Bit32u setMIDIEventQueueSize(const Bit32u queue_size) { return mt32emu_set_midi_event_queue_size(c, queue_size); } + void configureMIDIEventQueueSysexStorage(const Bit32u storage_buffer_size) { mt32emu_configure_midi_event_queue_sysex_storage(c, storage_buffer_size); } void setMIDIReceiver(mt32emu_midi_receiver_i midi_receiver, void *instance_data) { mt32emu_set_midi_receiver(c, midi_receiver, instance_data); } void setMIDIReceiver(IMidiReceiver &midi_receiver) { setMIDIReceiver(CppInterfaceImpl::getMidiReceiverThunk(), &midi_receiver); } @@ -238,6 +282,7 @@ public: void setReverbCompatibilityMode(const bool mt32_compatible_mode) { mt32emu_set_reverb_compatibility_mode(c, mt32_compatible_mode ? MT32EMU_BOOL_TRUE : MT32EMU_BOOL_FALSE); } bool isMT32ReverbCompatibilityMode() { return mt32emu_is_mt32_reverb_compatibility_mode(c) != MT32EMU_BOOL_FALSE; } bool isDefaultReverbMT32Compatible() { return mt32emu_is_default_reverb_mt32_compatible(c) != MT32EMU_BOOL_FALSE; } + void preallocateReverbMemory(const bool enabled) { mt32emu_preallocate_reverb_memory(c, enabled ? MT32EMU_BOOL_TRUE : MT32EMU_BOOL_FALSE); } void setDACInputMode(const DACInputMode mode) { mt32emu_set_dac_input_mode(c, static_cast(mode)); } DACInputMode getDACInputMode() { return static_cast(mt32emu_get_dac_input_mode(c)); } @@ -250,12 +295,21 @@ public: void setReverbOutputGain(float gain) { mt32emu_set_reverb_output_gain(c, gain); } float getReverbOutputGain() { return mt32emu_get_reverb_output_gain(c); } + void setPartVolumeOverride(Bit8u part_number, Bit8u volume_override) { mt32emu_set_part_volume_override(c, part_number, volume_override); } + Bit8u getPartVolumeOverride(Bit8u part_number) { return mt32emu_get_part_volume_override(c, part_number); } + void setReversedStereoEnabled(const bool enabled) { mt32emu_set_reversed_stereo_enabled(c, enabled ? MT32EMU_BOOL_TRUE : MT32EMU_BOOL_FALSE); } bool isReversedStereoEnabled() { return mt32emu_is_reversed_stereo_enabled(c) != MT32EMU_BOOL_FALSE; } void setNiceAmpRampEnabled(const bool enabled) { mt32emu_set_nice_amp_ramp_enabled(c, enabled ? MT32EMU_BOOL_TRUE : MT32EMU_BOOL_FALSE); } bool isNiceAmpRampEnabled() { return mt32emu_is_nice_amp_ramp_enabled(c) != MT32EMU_BOOL_FALSE; } + void setNicePanningEnabled(const bool enabled) { mt32emu_set_nice_panning_enabled(c, enabled ? MT32EMU_BOOL_TRUE : MT32EMU_BOOL_FALSE); } + bool isNicePanningEnabled() { return mt32emu_is_nice_panning_enabled(c) != MT32EMU_BOOL_FALSE; } + + void setNicePartialMixingEnabled(const bool enabled) { mt32emu_set_nice_partial_mixing_enabled(c, enabled ? MT32EMU_BOOL_TRUE : MT32EMU_BOOL_FALSE); } + bool isNicePartialMixingEnabled() { return mt32emu_is_nice_partial_mixing_enabled(c) != MT32EMU_BOOL_FALSE; } + void renderBit16s(Bit16s *stream, Bit32u len) { mt32emu_render_bit16s(c, stream, len); } void renderFloat(float *stream, Bit32u len) { mt32emu_render_float(c, stream, len); } void renderBit16sStreams(const mt32emu_dac_output_bit16s_streams *streams, Bit32u len) { mt32emu_render_bit16s_streams(c, streams, len); } @@ -268,8 +322,17 @@ public: void getPartialStates(Bit8u *partial_states) { mt32emu_get_partial_states(c, partial_states); } Bit32u getPlayingNotes(Bit8u part_number, Bit8u *keys, Bit8u *velocities) { return mt32emu_get_playing_notes(c, part_number, keys, velocities); } const char *getPatchName(Bit8u part_number) { return mt32emu_get_patch_name(c, part_number); } + bool getSoundGroupName(char *soundGroupName, Bit8u timbreGroup, Bit8u timbreNumber) { return mt32emu_get_sound_group_name(c, soundGroupName, timbreGroup, timbreNumber) != MT32EMU_BOOL_FALSE; } + bool getSoundName(char *soundName, Bit8u timbreGroup, Bit8u timbreNumber) { return mt32emu_get_sound_name(c, soundName, timbreGroup, timbreNumber) != MT32EMU_BOOL_FALSE; } void readMemory(Bit32u addr, Bit32u len, Bit8u *data) { mt32emu_read_memory(c, addr, len, data); } + bool getDisplayState(char *target_buffer, const bool narrow_lcd) { return mt32emu_get_display_state(c, target_buffer, narrow_lcd ? MT32EMU_BOOL_TRUE : MT32EMU_BOOL_FALSE) != MT32EMU_BOOL_FALSE; } + void setMainDisplayMode() { mt32emu_set_main_display_mode(c); } + + void setDisplayCompatibility(const bool oldMT32CompatibilityEnabled) { mt32emu_set_display_compatibility(c, oldMT32CompatibilityEnabled ? MT32EMU_BOOL_TRUE : MT32EMU_BOOL_FALSE); } + bool isDisplayOldMT32Compatible() { return mt32emu_is_display_old_mt32_compatible(c) != MT32EMU_BOOL_FALSE; } + bool isDefaultDisplayOldMT32Compatible() { return mt32emu_is_default_display_old_mt32_compatible(c) != MT32EMU_BOOL_FALSE; } + private: #if MT32EMU_API_TYPE == 2 const mt32emu_service_i i; @@ -279,108 +342,138 @@ private: #if MT32EMU_API_TYPE == 2 const mt32emu_service_i_v1 *iV1() { return (getVersionID() < MT32EMU_SERVICE_VERSION_1) ? NULL : i.v1; } const mt32emu_service_i_v2 *iV2() { return (getVersionID() < MT32EMU_SERVICE_VERSION_2) ? NULL : i.v2; } + const mt32emu_service_i_v3 *iV3() { return (getVersionID() < MT32EMU_SERVICE_VERSION_3) ? NULL : i.v3; } + const mt32emu_service_i_v4 *iV4() { return (getVersionID() < MT32EMU_SERVICE_VERSION_4) ? NULL : i.v4; } + const mt32emu_service_i_v5 *iV5() { return (getVersionID() < MT32EMU_SERVICE_VERSION_5) ? NULL : i.v5; } + const mt32emu_service_i_v6 *iV6() { return (getVersionID() < MT32EMU_SERVICE_VERSION_6) ? NULL : i.v6; } #endif + + Service(const Service &); // prevent copy-construction + Service& operator=(const Service &); // prevent assignment }; namespace CppInterfaceImpl { -static mt32emu_report_handler_version getReportHandlerVersionID(mt32emu_report_handler_i) { - return MT32EMU_REPORT_HANDLER_VERSION_CURRENT; -} +static mt32emu_report_handler_version MT32EMU_C_CALL getReportHandlerVersionID(mt32emu_report_handler_i); -static void printDebug(void *instance_data, const char *fmt, va_list list) { +static void MT32EMU_C_CALL printDebug(void *instance_data, const char *fmt, va_list list) { static_cast(instance_data)->printDebug(fmt, list); } -static void onErrorControlROM(void *instance_data) { +static void MT32EMU_C_CALL onErrorControlROM(void *instance_data) { static_cast(instance_data)->onErrorControlROM(); } -static void onErrorPCMROM(void *instance_data) { +static void MT32EMU_C_CALL onErrorPCMROM(void *instance_data) { static_cast(instance_data)->onErrorPCMROM(); } -static void showLCDMessage(void *instance_data, const char *message) { +static void MT32EMU_C_CALL showLCDMessage(void *instance_data, const char *message) { static_cast(instance_data)->showLCDMessage(message); } -static void onMIDIMessagePlayed(void *instance_data) { +static void MT32EMU_C_CALL onMIDIMessagePlayed(void *instance_data) { static_cast(instance_data)->onMIDIMessagePlayed(); } -static mt32emu_boolean onMIDIQueueOverflow(void *instance_data) { +static mt32emu_boolean MT32EMU_C_CALL onMIDIQueueOverflow(void *instance_data) { return static_cast(instance_data)->onMIDIQueueOverflow() ? MT32EMU_BOOL_TRUE : MT32EMU_BOOL_FALSE; } -static void onMIDISystemRealtime(void *instance_data, mt32emu_bit8u system_realtime) { +static void MT32EMU_C_CALL onMIDISystemRealtime(void *instance_data, mt32emu_bit8u system_realtime) { static_cast(instance_data)->onMIDISystemRealtime(system_realtime); } -static void onDeviceReset(void *instance_data) { +static void MT32EMU_C_CALL onDeviceReset(void *instance_data) { static_cast(instance_data)->onDeviceReset(); } -static void onDeviceReconfig(void *instance_data) { +static void MT32EMU_C_CALL onDeviceReconfig(void *instance_data) { static_cast(instance_data)->onDeviceReconfig(); } -static void onNewReverbMode(void *instance_data, mt32emu_bit8u mode) { +static void MT32EMU_C_CALL onNewReverbMode(void *instance_data, mt32emu_bit8u mode) { static_cast(instance_data)->onNewReverbMode(mode); } -static void onNewReverbTime(void *instance_data, mt32emu_bit8u time) { +static void MT32EMU_C_CALL onNewReverbTime(void *instance_data, mt32emu_bit8u time) { static_cast(instance_data)->onNewReverbTime(time); } -static void onNewReverbLevel(void *instance_data, mt32emu_bit8u level) { +static void MT32EMU_C_CALL onNewReverbLevel(void *instance_data, mt32emu_bit8u level) { static_cast(instance_data)->onNewReverbLevel(level); } -static void onPolyStateChanged(void *instance_data, mt32emu_bit8u part_num) { +static void MT32EMU_C_CALL onPolyStateChanged(void *instance_data, mt32emu_bit8u part_num) { static_cast(instance_data)->onPolyStateChanged(part_num); } -static void onProgramChanged(void *instance_data, mt32emu_bit8u part_num, const char *sound_group_name, const char *patch_name) { +static void MT32EMU_C_CALL onProgramChanged(void *instance_data, mt32emu_bit8u part_num, const char *sound_group_name, const char *patch_name) { static_cast(instance_data)->onProgramChanged(part_num, sound_group_name, patch_name); } -static mt32emu_report_handler_i getReportHandlerThunk() { - static const mt32emu_report_handler_i_v0 REPORT_HANDLER_V0_THUNK = { - getReportHandlerVersionID, - printDebug, - onErrorControlROM, - onErrorPCMROM, - showLCDMessage, - onMIDIMessagePlayed, - onMIDIQueueOverflow, - onMIDISystemRealtime, - onDeviceReset, - onDeviceReconfig, - onNewReverbMode, - onNewReverbTime, - onNewReverbLevel, - onPolyStateChanged, - onProgramChanged - }; - - static const mt32emu_report_handler_i REPORT_HANDLER_THUNK = { &REPORT_HANDLER_V0_THUNK }; - - return REPORT_HANDLER_THUNK; +static void MT32EMU_C_CALL onLCDStateUpdated(void *instance_data) { + static_cast(instance_data)->onLCDStateUpdated(); } -static mt32emu_midi_receiver_version getMidiReceiverVersionID(mt32emu_midi_receiver_i) { +static void MT32EMU_C_CALL onMidiMessageLEDStateUpdated(void *instance_data, mt32emu_boolean led_state) { + static_cast(instance_data)->onMidiMessageLEDStateUpdated(led_state != MT32EMU_BOOL_FALSE); +} + +#define MT32EMU_REPORT_HANDLER_V0_THUNK \ + getReportHandlerVersionID, \ + printDebug, \ + onErrorControlROM, \ + onErrorPCMROM, \ + showLCDMessage, \ + onMIDIMessagePlayed, \ + onMIDIQueueOverflow, \ + onMIDISystemRealtime, \ + onDeviceReset, \ + onDeviceReconfig, \ + onNewReverbMode, \ + onNewReverbTime, \ + onNewReverbLevel, \ + onPolyStateChanged, \ + onProgramChanged + +static const mt32emu_report_handler_i_v0 REPORT_HANDLER_V0_THUNK = { + MT32EMU_REPORT_HANDLER_V0_THUNK +}; + +static const mt32emu_report_handler_i_v1 REPORT_HANDLER_V1_THUNK = { + MT32EMU_REPORT_HANDLER_V0_THUNK, + onLCDStateUpdated, + onMidiMessageLEDStateUpdated +}; + +#undef MT32EMU_REPORT_HANDLER_THUNK_V0 + +static mt32emu_report_handler_version MT32EMU_C_CALL getReportHandlerVersionID(mt32emu_report_handler_i thunk) { + if (thunk.v0 == &REPORT_HANDLER_V0_THUNK) return MT32EMU_REPORT_HANDLER_VERSION_0; + return MT32EMU_REPORT_HANDLER_VERSION_CURRENT; +} + +static mt32emu_report_handler_i getReportHandlerThunk(mt32emu_report_handler_version versionID) { + mt32emu_report_handler_i thunk; + if (versionID == MT32EMU_REPORT_HANDLER_VERSION_0) thunk.v0 = &REPORT_HANDLER_V0_THUNK; + else thunk.v1 = &REPORT_HANDLER_V1_THUNK; + return thunk; +} + +static mt32emu_midi_receiver_version MT32EMU_C_CALL getMidiReceiverVersionID(mt32emu_midi_receiver_i) { return MT32EMU_MIDI_RECEIVER_VERSION_CURRENT; } -static void handleShortMessage(void *instance_data, const mt32emu_bit32u message) { +static void MT32EMU_C_CALL handleShortMessage(void *instance_data, const mt32emu_bit32u message) { static_cast(instance_data)->handleShortMessage(message); } -static void handleSysex(void *instance_data, const mt32emu_bit8u stream[], const mt32emu_bit32u length) { +static void MT32EMU_C_CALL handleSysex(void *instance_data, const mt32emu_bit8u stream[], const mt32emu_bit32u length) { static_cast(instance_data)->handleSysex(stream, length); } -static void handleSystemRealtimeMessage(void *instance_data, const mt32emu_bit8u realtime) { +static void MT32EMU_C_CALL handleSystemRealtimeMessage(void *instance_data, const mt32emu_bit8u realtime) { static_cast(instance_data)->handleSystemRealtimeMessage(realtime); } @@ -409,10 +502,17 @@ static mt32emu_midi_receiver_i getMidiReceiverThunk() { #undef mt32emu_get_library_version_string #undef mt32emu_get_stereo_output_samplerate #undef mt32emu_get_best_analog_output_mode +#undef mt32emu_get_machine_ids +#undef mt32emu_get_rom_ids +#undef mt32emu_identify_rom_data +#undef mt32emu_identify_rom_file #undef mt32emu_create_context #undef mt32emu_free_context #undef mt32emu_add_rom_data #undef mt32emu_add_rom_file +#undef mt32emu_merge_and_add_rom_data +#undef mt32emu_merge_and_add_rom_files +#undef mt32emu_add_machine_rom_file #undef mt32emu_get_rom_info #undef mt32emu_set_partial_count #undef mt32emu_set_analog_output_mode @@ -428,6 +528,7 @@ static mt32emu_midi_receiver_i getMidiReceiverThunk() { #undef mt32emu_convert_synth_to_output_timestamp #undef mt32emu_flush_midi_queue #undef mt32emu_set_midi_event_queue_size +#undef mt32emu_configure_midi_event_queue_sysex_storage #undef mt32emu_set_midi_receiver #undef mt32emu_get_internal_rendered_sample_count #undef mt32emu_parse_stream @@ -449,6 +550,7 @@ static mt32emu_midi_receiver_i getMidiReceiverThunk() { #undef mt32emu_set_reverb_compatibility_mode #undef mt32emu_is_mt32_reverb_compatibility_mode #undef mt32emu_is_default_reverb_mt32_compatible +#undef mt32emu_preallocate_reverb_memory #undef mt32emu_set_dac_input_mode #undef mt32emu_get_dac_input_mode #undef mt32emu_set_midi_delay_mode @@ -461,6 +563,10 @@ static mt32emu_midi_receiver_i getMidiReceiverThunk() { #undef mt32emu_is_reversed_stereo_enabled #undef mt32emu_set_nice_amp_ramp_enabled #undef mt32emu_is_nice_amp_ramp_enabled +#undef mt32emu_set_nice_panning_enabled +#undef mt32emu_is_nice_panning_enabled +#undef mt32emu_set_nice_partial_mixing_enabled +#undef mt32emu_is_nice_partial_mixing_enabled #undef mt32emu_render_bit16s #undef mt32emu_render_float #undef mt32emu_render_bit16s_streams @@ -472,7 +578,14 @@ static mt32emu_midi_receiver_i getMidiReceiverThunk() { #undef mt32emu_get_partial_states #undef mt32emu_get_playing_notes #undef mt32emu_get_patch_name +#undef mt32emu_get_sound_group_name +#undef mt32emu_get_sound_name #undef mt32emu_read_memory +#undef mt32emu_get_display_state +#undef mt32emu_set_main_display_mode +#undef mt32emu_set_display_compatibility +#undef mt32emu_is_display_old_mt32_compatible +#undef mt32emu_is_default_display_old_mt32_compatible #endif // #if MT32EMU_API_TYPE == 2 diff --git a/src/include/mt32emu/config.h b/src/include/mt32emu/config.h index 5f5b6c9fb..a7e31bd8d 100644 --- a/src/include/mt32emu/config.h +++ b/src/include/mt32emu/config.h @@ -1,5 +1,5 @@ /* Copyright (C) 2003, 2004, 2005, 2006, 2008, 2009 Dean Beeler, Jerome Fisher - * Copyright (C) 2011-2017 Dean Beeler, Jerome Fisher, Sergey V. Mikayev + * Copyright (C) 2011-2022 Dean Beeler, Jerome Fisher, Sergey V. Mikayev * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by @@ -18,9 +18,9 @@ #ifndef MT32EMU_CONFIG_H #define MT32EMU_CONFIG_H -#define MT32EMU_VERSION "2.2.0" +#define MT32EMU_VERSION "2.7.0" #define MT32EMU_VERSION_MAJOR 2 -#define MT32EMU_VERSION_MINOR 2 +#define MT32EMU_VERSION_MINOR 7 #define MT32EMU_VERSION_PATCH 0 /* Library Exports Configuration @@ -37,4 +37,9 @@ #define MT32EMU_API_TYPE 0 -#endif +#define MT32EMU_WITH_LIBSOXR_RESAMPLER 0 +#define MT32EMU_WITH_LIBSAMPLERATE_RESAMPLER 0 +#define MT32EMU_WITH_INTERNAL_RESAMPLER 1 + + +#endif /* #ifndef MT32EMU_CONFIG_H */ diff --git a/src/include/mt32emu/globals.h b/src/include/mt32emu/globals.h index 2d984c82b..86ac1ca5b 100644 --- a/src/include/mt32emu/globals.h +++ b/src/include/mt32emu/globals.h @@ -1,5 +1,5 @@ /* Copyright (C) 2003, 2004, 2005, 2006, 2008, 2009 Dean Beeler, Jerome Fisher - * Copyright (C) 2011-2017 Dean Beeler, Jerome Fisher, Sergey V. Mikayev + * Copyright (C) 2011-2022 Dean Beeler, Jerome Fisher, Sergey V. Mikayev * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by @@ -20,27 +20,35 @@ #include "config.h" -/* Support for compiling shared library. */ +/* Support for compiling shared library. + * MT32EMU_SHARED and mt32emu_EXPORTS are defined when building a shared library. + * MT32EMU_SHARED should also be defined for Windows platforms that provides for a small performance benefit, + * and it _must_ be defined along with MT32EMU_RUNTIME_VERSION_CHECK when using MSVC. + */ #ifdef MT32EMU_SHARED -#if defined _WIN32 || defined __CYGWIN__ -#ifdef _MSC_VER -#ifdef mt32emu_EXPORTS -#define MT32EMU_EXPORT_ATTRIBUTE _declspec(dllexport) -#else /* #ifdef mt32emu_EXPORTS */ -#define MT32EMU_EXPORT_ATTRIBUTE _declspec(dllimport) -#endif /* #ifdef mt32emu_EXPORTS */ -#else /* #ifdef _MSC_VER */ -#ifdef mt32emu_EXPORTS -#define MT32EMU_EXPORT_ATTRIBUTE __attribute__ ((dllexport)) -#else /* #ifdef mt32emu_EXPORTS */ -#define MT32EMU_EXPORT_ATTRIBUTE __attribute__ ((dllimport)) -#endif /* #ifdef mt32emu_EXPORTS */ -#endif /* #ifdef _MSC_VER */ -#else /* #if defined _WIN32 || defined __CYGWIN__ */ -#define MT32EMU_EXPORT_ATTRIBUTE __attribute__ ((visibility("default"))) -#endif /* #if defined _WIN32 || defined __CYGWIN__ */ +# if defined _WIN32 || defined __CYGWIN__ || defined __OS2__ +# ifdef _MSC_VER +# ifdef mt32emu_EXPORTS +# define MT32EMU_EXPORT_ATTRIBUTE _declspec(dllexport) +# else /* #ifdef mt32emu_EXPORTS */ +# define MT32EMU_EXPORT_ATTRIBUTE _declspec(dllimport) +# endif /* #ifdef mt32emu_EXPORTS */ +# else /* #ifdef _MSC_VER */ +# ifdef mt32emu_EXPORTS +# define MT32EMU_EXPORT_ATTRIBUTE __attribute__ ((dllexport)) +# else /* #ifdef mt32emu_EXPORTS */ +# define MT32EMU_EXPORT_ATTRIBUTE __attribute__ ((dllimport)) +# endif /* #ifdef mt32emu_EXPORTS */ +# endif /* #ifdef _MSC_VER */ +# else /* #if defined _WIN32 || defined __CYGWIN__ || defined __OS2__ */ +# ifdef mt32emu_EXPORTS +# define MT32EMU_EXPORT_ATTRIBUTE __attribute__ ((visibility("default"))) +# else /* #ifdef mt32emu_EXPORTS */ +# define MT32EMU_EXPORT_ATTRIBUTE +# endif /* #ifdef mt32emu_EXPORTS */ +# endif /* #if defined _WIN32 || defined __CYGWIN__ || defined __OS2__ */ #else /* #ifdef MT32EMU_SHARED */ -#define MT32EMU_EXPORT_ATTRIBUTE +# define MT32EMU_EXPORT_ATTRIBUTE #endif /* #ifdef MT32EMU_SHARED */ #if MT32EMU_EXPORTS_TYPE == 1 || MT32EMU_EXPORTS_TYPE == 2 @@ -49,6 +57,33 @@ #define MT32EMU_EXPORT MT32EMU_EXPORT_ATTRIBUTE #endif +/* Facilitates easier tracking of the library version when an external symbol was introduced. + * Particularly useful for shared library builds on POSIX systems that support symbol versioning, + * so that the version map file can be generated automatically. + */ +#define MT32EMU_EXPORT_V(symbol_version_tag) MT32EMU_EXPORT + +/* Helpers for compile-time version checks */ + +/* Encodes the given version components to a single integer value to simplify further checks. */ +#define MT32EMU_VERSION_INT(major, minor, patch) ((major << 16) | (minor << 8) | patch) + +/* The version of this library build, as an integer. */ +#define MT32EMU_CURRENT_VERSION_INT MT32EMU_VERSION_INT(MT32EMU_VERSION_MAJOR, MT32EMU_VERSION_MINOR, MT32EMU_VERSION_PATCH) + +/* Compares the current library version with the given version components. Intended for feature checks. */ +#define MT32EMU_VERSION_ATLEAST(major, minor, patch) (MT32EMU_CURRENT_VERSION_INT >= MT32EMU_VERSION_INT(major, minor, patch)) + +/* Implements a simple version check that ensures full API compatibility of this library build + * with the application requirements. The latter can be derived from the versions of used public symbols. + * + * Note: This macro is intended for a quick compile-time check. To ensure compatibility of an application + * linked with a shared library, an automatic version check can be engaged with help of the build option + * libmt32emu_WITH_VERSION_TAGGING. For a fine-grained feature checking in run-time, see functions + * mt32emu_get_library_version_int and Synth::getLibraryVersionInt. + */ +#define MT32EMU_IS_COMPATIBLE(major, minor) (MT32EMU_VERSION_MAJOR == major && MT32EMU_VERSION_MINOR >= minor) + /* Useful constants */ /* Sample rate to use in mixing. With the progress of development, we've found way too many thing dependent. diff --git a/src/include/mt32emu/mt32emu.h b/src/include/mt32emu/mt32emu.h index 6b93121be..571b25571 100644 --- a/src/include/mt32emu/mt32emu.h +++ b/src/include/mt32emu/mt32emu.h @@ -1,5 +1,5 @@ /* Copyright (C) 2003, 2004, 2005, 2006, 2008, 2009 Dean Beeler, Jerome Fisher - * Copyright (C) 2011-2017 Dean Beeler, Jerome Fisher, Sergey V. Mikayev + * Copyright (C) 2011-2022 Dean Beeler, Jerome Fisher, Sergey V. Mikayev * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by @@ -37,28 +37,23 @@ */ #ifdef MT32EMU_API_TYPE -#if MT32EMU_API_TYPE == 0 && (MT32EMU_EXPORTS_TYPE == 1 || MT32EMU_EXPORTS_TYPE == 2) -#error Incompatible setting MT32EMU_API_TYPE=0 -#elif MT32EMU_API_TYPE == 1 && (MT32EMU_EXPORTS_TYPE == 0 || MT32EMU_EXPORTS_TYPE == 2) -#error Incompatible setting MT32EMU_API_TYPE=1 -#elif MT32EMU_API_TYPE == 2 && (MT32EMU_EXPORTS_TYPE == 0) -#error Incompatible setting MT32EMU_API_TYPE=2 -#elif MT32EMU_API_TYPE == 3 && (MT32EMU_EXPORTS_TYPE == 0 || MT32EMU_EXPORTS_TYPE == 2) -#error Incompatible setting MT32EMU_API_TYPE=3 -#endif +# if MT32EMU_API_TYPE == 0 && (MT32EMU_EXPORTS_TYPE == 1 || MT32EMU_EXPORTS_TYPE == 2) +# error Incompatible setting MT32EMU_API_TYPE=0 +# elif MT32EMU_API_TYPE == 1 && (MT32EMU_EXPORTS_TYPE == 0 || MT32EMU_EXPORTS_TYPE == 2) +# error Incompatible setting MT32EMU_API_TYPE=1 +# elif MT32EMU_API_TYPE == 2 && (MT32EMU_EXPORTS_TYPE == 0) +# error Incompatible setting MT32EMU_API_TYPE=2 +# elif MT32EMU_API_TYPE == 3 && (MT32EMU_EXPORTS_TYPE == 0 || MT32EMU_EXPORTS_TYPE == 2) +# error Incompatible setting MT32EMU_API_TYPE=3 +# endif #else /* #ifdef MT32EMU_API_TYPE */ -#if 0 < MT32EMU_EXPORTS_TYPE && MT32EMU_EXPORTS_TYPE < 3 -#define MT32EMU_API_TYPE MT32EMU_EXPORTS_TYPE -#else -#define MT32EMU_API_TYPE 0 -#endif +# if 0 < MT32EMU_EXPORTS_TYPE && MT32EMU_EXPORTS_TYPE < 3 +# define MT32EMU_API_TYPE MT32EMU_EXPORTS_TYPE +# else +# define MT32EMU_API_TYPE 0 +# endif #endif /* #ifdef MT32EMU_API_TYPE */ -/* MT32EMU_SHARED should be defined when building shared library, especially for Windows platforms. */ -/* -#define MT32EMU_SHARED -*/ - #include "globals.h" #if !defined(__cplusplus) || MT32EMU_API_TYPE == 1 @@ -79,6 +74,14 @@ #include "MidiStreamParser.h" #include "SampleRateConverter.h" +#if MT32EMU_RUNTIME_VERSION_CHECK == 1 +#include "VersionTagging.h" +#endif + #endif /* #if !defined(__cplusplus) || MT32EMU_API_TYPE == 1 */ +#if MT32EMU_RUNTIME_VERSION_CHECK == 2 +#include "VersionTagging.h" +#endif + #endif /* #ifndef MT32EMU_MT32EMU_H */ diff --git a/src/include/slirp/libslirp-version.h b/src/include/slirp/libslirp-version.h index 1599206a5..b68906957 100644 --- a/src/include/slirp/libslirp-version.h +++ b/src/include/slirp/libslirp-version.h @@ -7,9 +7,9 @@ extern "C" { #endif #define SLIRP_MAJOR_VERSION 4 -#define SLIRP_MINOR_VERSION 3 -#define SLIRP_MICRO_VERSION 1 -#define SLIRP_VERSION_STRING "4.3.1-git-86Box" +#define SLIRP_MINOR_VERSION 7 +#define SLIRP_MICRO_VERSION 0 +#define SLIRP_VERSION_STRING "4.7.0-86Box" #define SLIRP_CHECK_VERSION(major,minor,micro) \ (SLIRP_MAJOR_VERSION > (major) || \ diff --git a/src/include/slirp/libslirp.h b/src/include/slirp/libslirp.h index 7c4340390..7a6c9a4da 100644 --- a/src/include/slirp/libslirp.h +++ b/src/include/slirp/libslirp.h @@ -8,6 +8,7 @@ #ifdef _WIN32 #include +#include #include #else #include @@ -31,8 +32,10 @@ extern "C" { #endif +/* Opaque structure containing the slirp state */ typedef struct Slirp Slirp; +/* Flags passed to SlirpAddPollCb and to be returned by SlirpGetREventsCb. */ enum { SLIRP_POLL_IN = 1 << 0, SLIRP_POLL_OUT = 1 << 1, @@ -47,38 +50,58 @@ typedef void (*SlirpTimerCb)(void *opaque); typedef int (*SlirpAddPollCb)(int fd, int events, void *opaque); typedef int (*SlirpGetREventsCb)(int idx, void *opaque); +typedef enum SlirpTimerId { + SLIRP_TIMER_RA, + SLIRP_TIMER_NUM, +} SlirpTimerId; + /* - * Callbacks from slirp + * Callbacks from slirp, to be set by the application. + * + * The opaque parameter is set to the opaque pointer given in the slirp_new / + * slirp_init call. */ typedef struct SlirpCb { /* - * Send an ethernet frame to the guest network. The opaque - * parameter is the one given to slirp_init(). The function - * doesn't need to send all the data and may return - * - * Copyright 2020 RichardG. - */ -#ifndef TINYGLIB_H -# define TINYGLIB_H - -/* Define this to bypass TinyGLib and use full GLib instead. */ -#ifdef TINYGLIB_USE_GLIB -#include -#else - -#include -#include -#include -#include -#define HAVE_STDARG_H -#include <86box/86box.h> - - -/* Definitions */ - -#define G_LITTLE_ENDIAN 1234 -#define G_BIG_ENDIAN 4321 -#define G_PDP_ENDIAN 3412 -#ifdef __BYTE_ORDER__ -# if __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__ -# define G_BYTE_ORDER G_LITTLE_ENDIAN -# elif __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__ -# define G_BYTE_ORDER G_BIG_ENDIAN -# elif __BYTE_ORDER__ == __ORDER_PDP_ENDIAN__ -# define G_BYTE_ORDER G_PDP_ENDIAN -# endif -#endif -#ifndef G_BYTE_ORDER -/* Safe to assume LE for MSVC, as Windows is LE on all architectures. */ -# define G_BYTE_ORDER G_LITTLE_ENDIAN -#endif - -#ifdef _WIN32 -# define G_OS_WIN32 1 -#else -# define G_OS_UNIX 1 -#endif - -#define G_SPAWN_SEARCH_PATH 0 - -#if defined(__LP64__) || defined(__LLP64__) || defined(_WIN64) -# define GLIB_SIZEOF_VOID_P 8 -# if defined(__LLP64__) || defined(_WIN64) -# define GLIB_SIZEOF_LONG 4 -# else -# define GLIB_SIZEOF_LONG 8 -# endif -# define GLIB_SIZEOF_SIZE_T 8 -# define GLIB_SIZEOF_SSIZE_T 8 -#else -# define GLIB_SIZEOF_VOID_P 4 -# define GLIB_SIZEOF_LONG 4 -# define GLIB_SIZEOF_SIZE_T 4 -# define GLIB_SIZEOF_SSIZE_T 4 -#endif - - -/* Types */ - -/* Windows does not define ssize_t, so we need to define it here. */ -#ifndef _SSIZE_T_DEFINED -# define _SSIZE_T_DEFINED -# undef ssize_t -# ifdef _WIN64 -# define ssize_t int64_t -# else -# define ssize_t int32_t -# endif -#endif - -#define gboolean int -#define gchar char -#define gint int -#define gint16 int16_t -#define gint32 int32_t -#define gint64 int64_t -#define glong long -#define GPid void * -#define gpointer void * -#define gsize size_t -#define GSpawnFlags void * -#define GSpawnChildSetupFunc void * -#define gssize ssize_t -#define GString char -#define GStrv char ** -#define guint unsigned int -#define guint16 uint16_t -#define guint32 uint32_t -#define guint64 uint64_t - -typedef struct _GDebugKey { - char key[32]; - int val; -} GDebugKey; - -typedef struct _GError { - char message[1]; -} GError; - -typedef struct _GRand { - uint8_t dummy; -} GRand; - - -/* Functions */ -extern gboolean g_spawn_async_with_fds(const gchar *working_directory, gchar **argv, - gchar **envp, GSpawnFlags flags, - GSpawnChildSetupFunc child_setup, - gpointer user_data, GPid *child_pid, gint stdin_fd, - gint stdout_fd, gint stderr_fd, GError **error); -extern GString *g_string_new(gchar *base); -extern gchar *g_string_free(GString *string, gboolean free_segment); -extern gchar *g_strstr_len(const gchar *haystack, gssize haystack_len, const gchar *needle); -extern guint g_strv_length(gchar **str_array); - - -/* Macros */ -#define tinyglib_pclog(f, s, ...) pclog("TinyGLib " f "(): " s "\n", ##__VA_ARGS__) - -#define GLIB_CHECK_VERSION(a, b, c) 1 -#ifdef __GNUC__ -# define G_GNUC_PRINTF(format_idx, arg_idx) __attribute__((__format__ (__printf__, format_idx, arg_idx))) -#else -# define G_GNUC_PRINTF(format_idx, arg_idx) -#endif -#define G_N_ELEMENTS(arr) (sizeof(arr) / sizeof((arr)[0])) -#define G_STATIC_ASSERT(e) /* this should probably do something */ -#define G_UNLIKELY(e) (e) - -#define g_assert(e) do { if (!(e)) fatal("TinyGLib g_assert(" #e ")\n"); } while (0) -#ifdef __GNUC__ -# define g_assert_not_reached __builtin_unreachable -#else -# ifdef _MSC_VER -# define g_assert_not_reached() __assume(0) -# else -# define g_assert_not_reached() -# endif -#endif -#define g_critical(s, ...) fatal("TinyGLib g_critical(): " s "\n", ##__VA_ARGS__) -#ifdef TINYGLIB_DEBUG -# define g_debug(s, ...) tinyglib_pclog("g_debug", s, ##__VA_ARGS__) -#else -# define g_debug(s, ...) -#endif -#define g_error(s, ...) tinyglib_pclog("g_error", s, ##__VA_ARGS__) -#define g_error_free(err) -#define g_malloc0(s) calloc(1, s) -#define g_new(t, n) (t *) malloc(sizeof(t) * n) -#define g_new0(t, n) (t *) calloc(n, sizeof(t)) -#ifdef TINYGLIB_DEBUG -# define g_parse_debug_string(s, k, n) ((!!sizeof(k)) * -1) /* unimplemented; always enables all debug flags */ -#else -# define g_parse_debug_string(s, k, n) (!sizeof(k)) -#endif -#define g_rand_int_range(r, min, max) (rand() % (max + 1 - min) + min) -#define g_rand_new() calloc(1, sizeof(GRand)) -#define g_return_val_if_fail(e, v) if (!(e)) return (v) -#define g_shell_parse_argv(a, b, c, d) !!(sizeof(b)) /* unimplemented */ -#define g_strdup(str) ((str) ? strdup(str) : NULL) -#define g_warn_if_fail(e) do { if (!(e)) pclog("TinyGLib g_warn_if_fail(" #e ")\n"); } while (0) -#define g_warn_if_reached() pclog("TinyGLib g_warn_if_reached()\n") -#define g_warning(s, ...) tinyglib_pclog("g_warning", s, ##__VA_ARGS__) - - -/* Remapped functions */ -#define g_free free -#define g_getenv getenv -#define g_malloc malloc -#define g_rand_free free -#define g_realloc realloc -#define g_snprintf snprintf -#define g_strerror strerror -#define g_strfreev free -#define g_string_append_printf sprintf /* unimplemented */ -#define g_vsnprintf vsnprintf - - -#endif - -#endif diff --git a/src/include_make/86box/version.h b/src/include_make/86box/version.h index d2a0b2791..4b6a8d5d0 100644 --- a/src/include_make/86box/version.h +++ b/src/include_make/86box/version.h @@ -1,47 +1,49 @@ /* - * 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. + * 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. + * This file is part of the 86Box distribution. * - * Definitions for project version, branding, and external links. + * Definitions for project version, branding, and external links. * - * Authors: Miran Grca, * - * Copyright 2020 Miran Grca. + * + * Authors: Miran Grca, + * + * Copyright 2020 Miran Grca. */ #define _LSTR(s) L ## s #define LSTR(s) _LSTR(s) /* Version info. */ -#define EMU_NAME "86Box" -#define EMU_NAME_W LSTR(EMU_NAME) +#define EMU_NAME "86Box" +#define EMU_NAME_W LSTR(EMU_NAME) -#define EMU_VERSION "3.2" -#define EMU_VERSION_W LSTR(EMU_VERSION) -#define EMU_VERSION_EX "3.02" -#define EMU_VERSION_MAJ 3 -#define EMU_VERSION_MIN 0 -#define EMU_VERSION_PATCH 0 +#define EMU_VERSION "4.0.2" +#define EMU_VERSION_W LSTR(EMU_VERSION) +#define EMU_VERSION_EX "3.50" /* frozen due to IDE re-detection behavior on Windows */ +#define EMU_VERSION_MAJ 4 +#define EMU_VERSION_MIN 0 +#define EMU_VERSION_PATCH 2 -#define EMU_BUILD_NUM 0 +#define EMU_BUILD_NUM 0 -#define EMU_VERSION_FULL EMU_VERSION -#define EMU_VERSION_FULL_W EMU_VERSION_W +#define EMU_VERSION_FULL EMU_VERSION +#define EMU_VERSION_FULL_W EMU_VERSION_W -#define COPYRIGHT_YEAR "2022" +#define COPYRIGHT_YEAR "2022" /* Web URL info. */ -#define EMU_SITE "86box.net" -#define EMU_SITE_W LSTR(EMU_SITE) -#define EMU_ROMS_URL "https://github.com/86Box/roms/releases/latest" -#define EMU_ROMS_URL_W LSTR(EMU_ROMS_URL) +#define EMU_SITE "86box.net" +#define EMU_SITE_W LSTR(EMU_SITE) +#define EMU_ROMS_URL "https://github.com/86Box/roms/releases/latest" +#define EMU_ROMS_URL_W LSTR(EMU_ROMS_URL) #ifdef RELEASE_BUILD -# define EMU_DOCS_URL "https://86box.readthedocs.io/en/v3.2/" +# define EMU_DOCS_URL "https://86box.readthedocs.io/en/v4.0/" #else -# define EMU_DOCS_URL "https://86box.readthedocs.io" +# define EMU_DOCS_URL "https://86box.readthedocs.io" #endif -#define EMU_DOCS_URL_W LSTR(EMU_DOCS_URL) +#define EMU_DOCS_URL_W LSTR(EMU_DOCS_URL) diff --git a/src/ini.c b/src/ini.c new file mode 100644 index 000000000..a792d356b --- /dev/null +++ b/src/ini.c @@ -0,0 +1,878 @@ +/* + * 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. + * + * Configuration file handler. + * + * + * + * Authors: Sarah Walker, + * Miran Grca, + * Fred N. van Kempen, + * Overdoze, + * David HrdliÄka, + * + * Copyright 2008-2019 Sarah Walker. + * Copyright 2016-2019 Miran Grca. + * Copyright 2017-2019 Fred N. van Kempen. + * Copyright 2018-2019 David HrdliÄka. + * + * NOTE: Forcing config files to be in Unicode encoding breaks + * it on Windows XP, and possibly also Vista. Use the + * -DANSI_CFG for use on these systems. + */ + +#include +#include +#include +#include +#include +#include +#include +#define HAVE_STDARG_H +#include <86box/86box.h> +#include <86box/ini.h> +#include <86box/plat.h> + +typedef struct _list_ { + struct _list_ *next; +} list_t; + +typedef struct section_t { + list_t list; + + char name[128]; + + list_t entry_head; +} section_t; + +typedef struct entry_t { + list_t list; + + char name[128]; + char data[512]; + wchar_t wdata[512]; +} entry_t; + +#define list_add(new, head) \ + { \ + list_t *next = head; \ + \ + while (next->next != NULL) \ + next = next->next; \ + \ + (next)->next = new; \ + (new)->next = NULL; \ + } + +#define list_delete(old, head) \ + { \ + list_t *next = head; \ + \ + while ((next)->next != old) { \ + next = (next)->next; \ + } \ + \ + (next)->next = (old)->next; \ + if ((next) == (head)) \ + (head)->next = (old)->next; \ + } + +#ifdef ENABLE_INI_LOG +int ini_do_log = ENABLE_INI_LOG; + +static void +ini_log(const char *fmt, ...) +{ + va_list ap; + + if (ini_do_log) { + va_start(ap, fmt); + pclog_ex(fmt, ap); + va_end(ap); + } +} +#else +# define ini_log(fmt, ...) +#endif + +static section_t * +find_section(list_t *head, const char *name) +{ + section_t *sec = (section_t *) head->next; + const char blank[] = ""; + + if (name == NULL) + name = blank; + + while (sec != NULL) { + if (!strncmp(sec->name, name, sizeof(sec->name))) + return sec; + + sec = (section_t *) sec->list.next; + } + + return NULL; +} + +ini_section_t +ini_find_section(ini_t ini, const char *name) +{ + if (ini == NULL) + return NULL; + + return (ini_section_t) find_section((list_t *) ini, name); +} + +void +ini_rename_section(ini_section_t section, const char *name) +{ + section_t *sec = (section_t *) section; + + if (sec == NULL) + return; + + memset(sec->name, 0x00, sizeof(sec->name)); + memcpy(sec->name, name, MIN(128, strlen(name) + 1)); +} + +static entry_t * +find_entry(section_t *section, const char *name) +{ + entry_t *ent; + + ent = (entry_t *) section->entry_head.next; + + while (ent != NULL) { + if (!strncmp(ent->name, name, sizeof(ent->name))) + return ent; + + ent = (entry_t *) ent->list.next; + } + + return (NULL); +} + +static int +entries_num(section_t *section) +{ + entry_t *ent; + int i = 0; + + ent = (entry_t *) section->entry_head.next; + + while (ent != NULL) { + if (strlen(ent->name) > 0) + i++; + + ent = (entry_t *) ent->list.next; + } + + return i; +} + +static void +delete_section_if_empty(list_t *head, section_t *section) +{ + if (section == NULL) + return; + + if (entries_num(section) == 0) { + list_delete(§ion->list, head); + free(section); + } +} + +void +ini_delete_section_if_empty(ini_t ini, ini_section_t section) +{ + if (ini == NULL || section == NULL) + return; + + delete_section_if_empty((list_t *) ini, (section_t *) section); +} + +static section_t * +create_section(list_t *head, const char *name) +{ + section_t *ns = malloc(sizeof(section_t)); + + memset(ns, 0x00, sizeof(section_t)); + memcpy(ns->name, name, strlen(name) + 1); + list_add(&ns->list, head); + + return ns; +} + +ini_section_t +ini_find_or_create_section(ini_t ini, const char *name) +{ + if (ini == NULL) + return NULL; + + section_t *section = find_section((list_t *) ini, name); + if (section == NULL) + section = create_section((list_t *) ini, name); + + return (ini_section_t) section; +} + +static entry_t * +create_entry(section_t *section, const char *name) +{ + entry_t *ne = malloc(sizeof(entry_t)); + + memset(ne, 0x00, sizeof(entry_t)); + memcpy(ne->name, name, strlen(name) + 1); + list_add(&ne->list, §ion->entry_head); + + return ne; +} + +void +ini_close(ini_t ini) +{ + section_t *sec; + section_t *ns; + entry_t *ent; + list_t *list = (list_t *) ini; + + if (list == NULL) + return; + + sec = (section_t *) list->next; + while (sec != NULL) { + ns = (section_t *) sec->list.next; + ent = (entry_t *) sec->entry_head.next; + + while (ent != NULL) { + entry_t *nent = (entry_t *) ent->list.next; + + free(ent); + ent = nent; + } + + free(sec); + sec = ns; + } + + free(list); +} + +static int +ini_detect_bom(const char *fn) +{ + FILE *fp; + unsigned char bom[4] = { 0, 0, 0, 0 }; + +#if defined(ANSI_CFG) || !defined(_WIN32) + fp = plat_fopen(fn, "rt"); +#else + fp = plat_fopen(fn, "rt, ccs=UTF-8"); +#endif + if (fp == NULL) + return 0; + (void) !fread(bom, 1, 3, fp); + if (bom[0] == 0xEF && bom[1] == 0xBB && bom[2] == 0xBF) { + fclose(fp); + return 1; + } + fclose(fp); + return 0; +} + +#ifdef __HAIKU__ +/* Local version of fgetws to avoid a crash */ +static wchar_t * +ini_fgetws(wchar_t *str, int count, FILE *stream) +{ + int i = 0; + if (feof(stream)) + return NULL; + for (i = 0; i < count; i++) { + wint_t curChar = fgetwc(stream); + if (curChar == WEOF) { + if (i + 1 < count) + str[i + 1] = 0; + return feof(stream) ? str : NULL; + } + str[i] = curChar; + if (curChar == '\n') + break; + } + if (i + 1 < count) + str[i + 1] = 0; + return str; +} +#endif + +/* Read and parse the configuration file into memory. */ +ini_t +ini_read(const char *fn) +{ + char sname[128]; + char ename[128]; + wchar_t buff[1024]; + section_t *sec; + section_t *ns; + entry_t *ne; + int c; + int d; + int bom; + FILE *fp; + list_t *head; + + bom = ini_detect_bom(fn); +#if defined(ANSI_CFG) || !defined(_WIN32) + fp = plat_fopen(fn, "rt"); +#else + fp = plat_fopen(fn, "rt, ccs=UTF-8"); +#endif + if (fp == NULL) + return NULL; + + head = malloc(sizeof(list_t)); + memset(head, 0x00, sizeof(list_t)); + + sec = malloc(sizeof(section_t)); + memset(sec, 0x00, sizeof(section_t)); + + list_add(&sec->list, head); + if (bom) + fseek(fp, 3, SEEK_SET); + + while (1) { + memset(buff, 0x00, sizeof(buff)); +#ifdef __HAIKU__ + ini_fgetws(buff, sizeof_w(buff), fp); +#else + (void) !fgetws(buff, sizeof_w(buff), fp); +#endif + if (feof(fp)) + break; + + /* Make sure there are no stray newlines or hard-returns in there. */ + if (wcslen(buff) > 0) + if (buff[wcslen(buff) - 1] == L'\n') + buff[wcslen(buff) - 1] = L'\0'; + if (wcslen(buff) > 0) + if (buff[wcslen(buff) - 1] == L'\r') + buff[wcslen(buff) - 1] = L'\0'; + + /* Skip any leading whitespace. */ + c = 0; + while ((buff[c] == L' ') || (buff[c] == L'\t')) + c++; + + /* Skip empty lines. */ + if (buff[c] == L'\0') + continue; + + /* Skip lines that (only) have a comment. */ + if ((buff[c] == L'#') || (buff[c] == L';')) + continue; + + if (buff[c] == L'[') { /*Section*/ + c++; + d = 0; + while (buff[c] != L']' && buff[c]) + (void) !wctomb(&(sname[d++]), buff[c++]); + sname[d] = L'\0'; + + /* Is the section name properly terminated? */ + if (buff[c] != L']') + continue; + + /* Create a new section and insert it. */ + ns = malloc(sizeof(section_t)); + memset(ns, 0x00, sizeof(section_t)); + memcpy(ns->name, sname, 128); + list_add(&ns->list, head); + + /* New section is now the current one. */ + sec = ns; + continue; + } + + /* Get the variable name. */ + d = 0; + while ((buff[c] != L'=') && (buff[c] != L' ') && buff[c]) + (void) !wctomb(&(ename[d++]), buff[c++]); + ename[d] = L'\0'; + + /* Skip incomplete lines. */ + if (buff[c] == L'\0') + continue; + + /* Look for =, skip whitespace. */ + while ((buff[c] == L'=' || buff[c] == L' ') && buff[c]) + c++; + + /* Skip incomplete lines. */ + if (buff[c] == L'\0') + continue; + + /* This is where the value part starts. */ + d = c; + + /* Allocate a new variable entry.. */ + ne = malloc(sizeof(entry_t)); + memset(ne, 0x00, sizeof(entry_t)); + memcpy(ne->name, ename, 128); + wcsncpy(ne->wdata, &buff[d], sizeof_w(ne->wdata) - 1); + ne->wdata[sizeof_w(ne->wdata) - 1] = L'\0'; +#ifdef _WIN32 /* Make sure the string is converted to UTF-8 rather than a legacy codepage */ + c16stombs(ne->data, ne->wdata, sizeof(ne->data)); +#else + wcstombs(ne->data, ne->wdata, sizeof(ne->data)); +#endif + ne->data[sizeof(ne->data) - 1] = '\0'; + + /* .. and insert it. */ + list_add(&ne->list, &sec->entry_head); + } + + (void) fclose(fp); + + return (ini_t) head; +} + +/* Write the in-memory configuration to disk. */ +void +ini_write(ini_t ini, const char *fn) +{ + wchar_t wtemp[512]; + list_t *list = (list_t *) ini; + section_t *sec; + FILE *fp; + int fl = 0; + + if (list == NULL) + return; + + sec = (section_t *) list->next; + +#if defined(ANSI_CFG) || !defined(_WIN32) + fp = plat_fopen(fn, "wt"); +#else + fp = plat_fopen(fn, "wt, ccs=UTF-8"); +#endif + if (fp == NULL) + return; + + while (sec != NULL) { + entry_t *ent; + + if (sec->name[0]) { + mbstowcs(wtemp, sec->name, strlen(sec->name) + 1); + if (fl) + fwprintf(fp, L"\n[%ls]\n", wtemp); + else + fwprintf(fp, L"[%ls]\n", wtemp); + fl++; + } + + ent = (entry_t *) sec->entry_head.next; + while (ent != NULL) { + if (ent->name[0] != '\0') { + mbstowcs(wtemp, ent->name, 128); + if (ent->wdata[0] == L'\0') + fwprintf(fp, L"%ls = \n", wtemp); + else + fwprintf(fp, L"%ls = %ls\n", wtemp, ent->wdata); + fl++; + } + + ent = (entry_t *) ent->list.next; + } + + sec = (section_t *) sec->list.next; + } + + (void) fclose(fp); +} + +ini_t +ini_new(void) +{ + ini_t ini = malloc(sizeof(list_t)); + memset(ini, 0, sizeof(list_t)); + return ini; +} + +void +ini_dump(ini_t ini) +{ + section_t *sec = (section_t *) ini; + while (sec != NULL) { + entry_t *ent; + + if (sec->name[0]) + ini_log("[%s]\n", sec->name); + + ent = (entry_t *) sec->entry_head.next; + while (ent != NULL) { + ini_log("%s = %s\n", ent->name, ent->data); + + ent = (entry_t *) ent->list.next; + } + + sec = (section_t *) sec->list.next; + } +} + +void +ini_section_delete_var(ini_section_t self, const char *name) +{ + section_t *section = (section_t *) self; + entry_t *entry; + + if (section == NULL) + return; + + entry = find_entry(section, name); + if (entry != NULL) { + list_delete(&entry->list, §ion->entry_head); + free(entry); + } +} + +int +ini_section_get_int(ini_section_t self, const char *name, int def) +{ + section_t *section = (section_t *) self; + const entry_t *entry; + int value; + + if (section == NULL) + return def; + + entry = find_entry(section, name); + if (entry == NULL) + return def; + + sscanf(entry->data, "%i", &value); + + return value; +} + +uint32_t +ini_section_get_uint(ini_section_t self, const char *name, uint32_t def) +{ + section_t *section = (section_t *) self; + const entry_t *entry; + uint32_t value; + + if (section == NULL) + return def; + + entry = find_entry(section, name); + if (entry == NULL) + return def; + + sscanf(entry->data, "%u", &value); + + return value; +} + +#if 0 +float +ini_section_get_float(ini_section_t self, const char *name, float def) +{ + section_t *section = (section_t *) self; + const entry_t *entry; + float value; + + if (section == NULL) + return def; + + entry = find_entry(section, name); + if (entry == NULL) + return def; + + sscanf(entry->data, "%g", &value); + + return value; +} +#endif + +double +ini_section_get_double(ini_section_t self, const char *name, double def) +{ + section_t *section = (section_t *) self; + const entry_t *entry; + double value; + + if (section == NULL) + return def; + + entry = find_entry(section, name); + if (entry == NULL) + return def; + + sscanf(entry->data, "%lg", &value); + + return value; +} + +int +ini_section_get_hex16(ini_section_t self, const char *name, int def) +{ + section_t *section = (section_t *) self; + const entry_t *entry; + unsigned int value; + + if (section == NULL) + return def; + + entry = find_entry(section, name); + if (entry == NULL) + return def; + + sscanf(entry->data, "%04X", &value); + + return value; +} + +int +ini_section_get_hex20(ini_section_t self, const char *name, int def) +{ + section_t *section = (section_t *) self; + const entry_t *entry; + unsigned int value; + + if (section == NULL) + return def; + + entry = find_entry(section, name); + if (entry == NULL) + return def; + + sscanf(entry->data, "%05X", &value); + + return value; +} + +int +ini_section_get_mac(ini_section_t self, const char *name, int def) +{ + section_t *section = (section_t *) self; + const entry_t *entry; + unsigned int val0 = 0; + unsigned int val1 = 0; + unsigned int val2 = 0; + + if (section == NULL) + return def; + + entry = find_entry(section, name); + if (entry == NULL) + return def; + + sscanf(entry->data, "%02x:%02x:%02x", &val0, &val1, &val2); + + return ((val0 << 16) + (val1 << 8) + val2); +} + +char * +ini_section_get_string(ini_section_t self, const char *name, char *def) +{ + section_t *section = (section_t *) self; + entry_t *entry; + + if (section == NULL) + return def; + + entry = find_entry(section, name); + if (entry == NULL) + return def; + + return (entry->data); +} + +wchar_t * +ini_section_get_wstring(ini_section_t self, const char *name, wchar_t *def) +{ + section_t *section = (section_t *) self; + entry_t *entry; + + if (section == NULL) + return def; + + entry = find_entry(section, name); + if (entry == NULL) + return def; + + return (entry->wdata); +} + +void +ini_section_set_int(ini_section_t self, const char *name, int val) +{ + section_t *section = (section_t *) self; + entry_t *ent; + + if (section == NULL) + return; + + ent = find_entry(section, name); + if (ent == NULL) + ent = create_entry(section, name); + + sprintf(ent->data, "%i", val); + mbstowcs(ent->wdata, ent->data, 512); +} + +void +ini_section_set_uint(ini_section_t self, const char *name, uint32_t val) +{ + section_t *section = (section_t *) self; + entry_t *ent; + + if (section == NULL) + return; + + ent = find_entry(section, name); + if (ent == NULL) + ent = create_entry(section, name); + + sprintf(ent->data, "%i", val); + mbstowcs(ent->wdata, ent->data, 512); +} + +#if 0 +void +ini_section_set_float(ini_section_t self, const char *name, float val) +{ + section_t *section = (section_t *) self; + entry_t *ent; + + if (section == NULL) + return; + + ent = find_entry(section, name); + if (ent == NULL) + ent = create_entry(section, name); + + sprintf(ent->data, "%g", val); + mbstowcs(ent->wdata, ent->data, 512); +} +#endif + +void +ini_section_set_double(ini_section_t self, const char *name, double val) +{ + section_t *section = (section_t *) self; + entry_t *ent; + + if (section == NULL) + return; + + ent = find_entry(section, name); + if (ent == NULL) + ent = create_entry(section, name); + + sprintf(ent->data, "%lg", val); + mbstowcs(ent->wdata, ent->data, 512); +} + +void +ini_section_set_hex16(ini_section_t self, const char *name, int val) +{ + section_t *section = (section_t *) self; + entry_t *ent; + + if (section == NULL) + return; + + ent = find_entry(section, name); + if (ent == NULL) + ent = create_entry(section, name); + + sprintf(ent->data, "%04X", val); + mbstowcs(ent->wdata, ent->data, sizeof_w(ent->wdata)); +} + +void +ini_section_set_hex20(ini_section_t self, const char *name, int val) +{ + section_t *section = (section_t *) self; + entry_t *ent; + + if (section == NULL) + return; + + ent = find_entry(section, name); + if (ent == NULL) + ent = create_entry(section, name); + + sprintf(ent->data, "%05X", val); + mbstowcs(ent->wdata, ent->data, sizeof_w(ent->wdata)); +} + +void +ini_section_set_mac(ini_section_t self, const char *name, int val) +{ + section_t *section = (section_t *) self; + entry_t *ent; + + if (section == NULL) + return; + + ent = find_entry(section, name); + if (ent == NULL) + ent = create_entry(section, name); + + sprintf(ent->data, "%02x:%02x:%02x", + (val >> 16) & 0xff, (val >> 8) & 0xff, val & 0xff); + mbstowcs(ent->wdata, ent->data, 512); +} + +void +ini_section_set_string(ini_section_t self, const char *name, const char *val) +{ + section_t *section = (section_t *) self; + entry_t *ent; + + if (section == NULL) + return; + + ent = find_entry(section, name); + if (ent == NULL) + ent = create_entry(section, name); + + if ((strlen(val) + 1) <= sizeof(ent->data)) + memcpy(ent->data, val, strlen(val) + 1); + else + memcpy(ent->data, val, sizeof(ent->data)); +#ifdef _WIN32 /* Make sure the string is converted from UTF-8 rather than a legacy codepage */ + mbstoc16s(ent->wdata, ent->data, sizeof_w(ent->wdata)); +#else + mbstowcs(ent->wdata, ent->data, sizeof_w(ent->wdata)); +#endif +} + +void +ini_section_set_wstring(ini_section_t self, const char *name, wchar_t *val) +{ + section_t *section = (section_t *) self; + entry_t *ent; + + if (section == NULL) + return; + + ent = find_entry(section, name); + if (ent == NULL) + ent = create_entry(section, name); + + memcpy(ent->wdata, val, sizeof_w(ent->wdata)); +#ifdef _WIN32 /* Make sure the string is converted to UTF-8 rather than a legacy codepage */ + c16stombs(ent->data, ent->wdata, sizeof(ent->data)); +#else + wcstombs(ent->data, ent->wdata, sizeof(ent->data)); +#endif +} diff --git a/src/io.c b/src/io.c index 92b6b591c..0e68049c3 100644 --- a/src/io.c +++ b/src/io.c @@ -1,21 +1,21 @@ /* - * 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. + * 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. + * This file is part of the 86Box distribution. * - * Implement I/O ports and their operations. + * Implement I/O ports and their operations. * * * - * Authors: Sarah Walker, - * Miran Grca, - * Fred N. van Kempen, + * Authors: Sarah Walker, + * Miran Grca, + * Fred N. van Kempen, * - * Copyright 2008-2019 Sarah Walker. - * Copyright 2016-2019 Miran Grca. + * Copyright 2008-2019 Sarah Walker. + * Copyright 2016-2019 Miran Grca. */ #include #include @@ -29,332 +29,359 @@ #include <86box/timer.h> #include "cpu.h" #include <86box/m_amstrad.h> +#include <86box/pci.h> - -#define NPORTS 65536 /* PC/AT supports 64K ports */ - +#define NPORTS 65536 /* PC/AT supports 64K ports */ typedef struct _io_ { - uint8_t (*inb)(uint16_t addr, void *priv); + uint8_t (*inb)(uint16_t addr, void *priv); uint16_t (*inw)(uint16_t addr, void *priv); uint32_t (*inl)(uint16_t addr, void *priv); - void (*outb)(uint16_t addr, uint8_t val, void *priv); - void (*outw)(uint16_t addr, uint16_t val, void *priv); - void (*outl)(uint16_t addr, uint32_t val, void *priv); + void (*outb)(uint16_t addr, uint8_t val, void *priv); + void (*outw)(uint16_t addr, uint16_t val, void *priv); + void (*outl)(uint16_t addr, uint32_t val, void *priv); - void *priv; + void *priv; struct _io_ *prev, *next; } io_t; typedef struct { - uint8_t enable; - uint16_t base, size; - void (*func)(int size, uint16_t addr, uint8_t write, uint8_t val, void *priv), - *priv; + uint8_t enable; + uint16_t base; + uint16_t size; + void (*func)(int size, uint16_t addr, uint8_t write, uint8_t val, void *priv); + void *priv; } io_trap_t; -int initialized = 0; -io_t *io[NPORTS], *io_last[NPORTS]; - +int initialized = 0; +io_t *io[NPORTS]; +io_t *io_last[NPORTS]; #ifdef ENABLE_IO_LOG int io_do_log = ENABLE_IO_LOG; - static void io_log(const char *fmt, ...) { va_list ap; if (io_do_log) { - va_start(ap, fmt); - pclog_ex(fmt, ap); - va_end(ap); + va_start(ap, fmt); + pclog_ex(fmt, ap); + va_end(ap); } } #else -#define io_log(fmt, ...) +# define io_log(fmt, ...) #endif - void io_init(void) { - int c; - io_t *p, *q; + int c; + io_t *p; + io_t *q; if (!initialized) { - for (c=0; cprev; - free(p); - p = q; - } - p = NULL; - } + /* Port c has at least one handler. */ + p = io_last[c]; + /* After this loop, p will have the pointer to the first handler. */ + while (p) { + q = p->prev; + free(p); + p = q; + } + p = NULL; + } - /* io[c] should be NULL. */ - io[c] = io_last[c] = NULL; + /* io[c] should be NULL. */ + io[c] = io_last[c] = NULL; } } - void io_sethandler_common(uint16_t base, int size, - uint8_t (*inb)(uint16_t addr, void *priv), - uint16_t (*inw)(uint16_t addr, void *priv), - uint32_t (*inl)(uint16_t addr, void *priv), - void (*outb)(uint16_t addr, uint8_t val, void *priv), - void (*outw)(uint16_t addr, uint16_t val, void *priv), - void (*outl)(uint16_t addr, uint32_t val, void *priv), - void *priv, int step) + uint8_t (*inb)(uint16_t addr, void *priv), + uint16_t (*inw)(uint16_t addr, void *priv), + uint32_t (*inl)(uint16_t addr, void *priv), + void (*outb)(uint16_t addr, uint8_t val, void *priv), + void (*outw)(uint16_t addr, uint16_t val, void *priv), + void (*outl)(uint16_t addr, uint32_t val, void *priv), + void *priv, int step) { - int c; - io_t *p, *q = NULL; + io_t *p; + io_t *q = NULL; - for (c = 0; c < size; c += step) { - p = io_last[base + c]; - q = (io_t *) malloc(sizeof(io_t)); - memset(q, 0, sizeof(io_t)); - if (p) { - p->next = q; - q->prev = p; - } else { - io[base + c] = q; - q->prev = NULL; - } + for (int c = 0; c < size; c += step) { + p = io_last[base + c]; + q = (io_t *) malloc(sizeof(io_t)); + memset(q, 0, sizeof(io_t)); + if (p) { + p->next = q; + q->prev = p; + } else { + io[base + c] = q; + q->prev = NULL; + } - q->inb = inb; - q->inw = inw; - q->inl = inl; + q->inb = inb; + q->inw = inw; + q->inl = inl; - q->outb = outb; - q->outw = outw; - q->outl = outl; + q->outb = outb; + q->outw = outw; + q->outl = outl; - q->priv = priv; - q->next = NULL; + q->priv = priv; + q->next = NULL; - io_last[base + c] = q; + io_last[base + c] = q; } } - void io_removehandler_common(uint16_t base, int size, - uint8_t (*inb)(uint16_t addr, void *priv), - uint16_t (*inw)(uint16_t addr, void *priv), - uint32_t (*inl)(uint16_t addr, void *priv), - void (*outb)(uint16_t addr, uint8_t val, void *priv), - void (*outw)(uint16_t addr, uint16_t val, void *priv), - void (*outl)(uint16_t addr, uint32_t val, void *priv), - void *priv, int step) + uint8_t (*inb)(uint16_t addr, void *priv), + uint16_t (*inw)(uint16_t addr, void *priv), + uint32_t (*inl)(uint16_t addr, void *priv), + void (*outb)(uint16_t addr, uint8_t val, void *priv), + void (*outw)(uint16_t addr, uint16_t val, void *priv), + void (*outl)(uint16_t addr, uint32_t val, void *priv), + void *priv, int step) { - int c; - io_t *p, *q; + io_t *p; + io_t *q; - for (c = 0; c < size; c += step) { - p = io[base + c]; - if (!p) - continue; - while(p) { - q = p->next; - if ((p->inb == inb) && (p->inw == inw) && - (p->inl == inl) && (p->outb == outb) && - (p->outw == outw) && (p->outl == outl) && - (p->priv == priv)) { - if (p->prev) - p->prev->next = p->next; - else - io[base + c] = p->next; - if (p->next) - p->next->prev = p->prev; - else - io_last[base + c] = p->prev; - free(p); - p = NULL; - break; - } - p = q; - } + for (int c = 0; c < size; c += step) { + p = io[base + c]; + if (!p) + continue; + while (p) { + q = p->next; + if ((p->inb == inb) && (p->inw == inw) && (p->inl == inl) && (p->outb == outb) && (p->outw == outw) && (p->outl == outl) && (p->priv == priv)) { + if (p->prev) + p->prev->next = p->next; + else + io[base + c] = p->next; + if (p->next) + p->next->prev = p->prev; + else + io_last[base + c] = p->prev; + free(p); + p = NULL; + break; + } + p = q; + } } } - void -io_handler_common(int set, uint16_t base, int size, - uint8_t (*inb)(uint16_t addr, void *priv), - uint16_t (*inw)(uint16_t addr, void *priv), - uint32_t (*inl)(uint16_t addr, void *priv), - void (*outb)(uint16_t addr, uint8_t val, void *priv), - void (*outw)(uint16_t addr, uint16_t val, void *priv), - void (*outl)(uint16_t addr, uint32_t val, void *priv), - void *priv, int step) +io_handler_common(int set, uint16_t base, int size, + uint8_t (*inb)(uint16_t addr, void *priv), + uint16_t (*inw)(uint16_t addr, void *priv), + uint32_t (*inl)(uint16_t addr, void *priv), + void (*outb)(uint16_t addr, uint8_t val, void *priv), + void (*outw)(uint16_t addr, uint16_t val, void *priv), + void (*outl)(uint16_t addr, uint32_t val, void *priv), + void *priv, int step) { if (set) - io_sethandler_common(base, size, inb, inw, inl, outb, outw, outl, priv, step); + io_sethandler_common(base, size, inb, inw, inl, outb, outw, outl, priv, step); else - io_removehandler_common(base, size, inb, inw, inl, outb, outw, outl, priv, step); + io_removehandler_common(base, size, inb, inw, inl, outb, outw, outl, priv, step); } - void -io_sethandler(uint16_t base, int size, - uint8_t (*inb)(uint16_t addr, void *priv), - uint16_t (*inw)(uint16_t addr, void *priv), - uint32_t (*inl)(uint16_t addr, void *priv), - void (*outb)(uint16_t addr, uint8_t val, void *priv), - void (*outw)(uint16_t addr, uint16_t val, void *priv), - void (*outl)(uint16_t addr, uint32_t val, void *priv), - void *priv) +io_sethandler(uint16_t base, int size, + uint8_t (*inb)(uint16_t addr, void *priv), + uint16_t (*inw)(uint16_t addr, void *priv), + uint32_t (*inl)(uint16_t addr, void *priv), + void (*outb)(uint16_t addr, uint8_t val, void *priv), + void (*outw)(uint16_t addr, uint16_t val, void *priv), + void (*outl)(uint16_t addr, uint32_t val, void *priv), + void *priv) { io_sethandler_common(base, size, inb, inw, inl, outb, outw, outl, priv, 1); } - void io_removehandler(uint16_t base, int size, - uint8_t (*inb)(uint16_t addr, void *priv), - uint16_t (*inw)(uint16_t addr, void *priv), - uint32_t (*inl)(uint16_t addr, void *priv), - void (*outb)(uint16_t addr, uint8_t val, void *priv), - void (*outw)(uint16_t addr, uint16_t val, void *priv), - void (*outl)(uint16_t addr, uint32_t val, void *priv), - void *priv) + uint8_t (*inb)(uint16_t addr, void *priv), + uint16_t (*inw)(uint16_t addr, void *priv), + uint32_t (*inl)(uint16_t addr, void *priv), + void (*outb)(uint16_t addr, uint8_t val, void *priv), + void (*outw)(uint16_t addr, uint16_t val, void *priv), + void (*outl)(uint16_t addr, uint32_t val, void *priv), + void *priv) { io_removehandler_common(base, size, inb, inw, inl, outb, outw, outl, priv, 1); } - void -io_handler(int set, uint16_t base, int size, - uint8_t (*inb)(uint16_t addr, void *priv), - uint16_t (*inw)(uint16_t addr, void *priv), - uint32_t (*inl)(uint16_t addr, void *priv), - void (*outb)(uint16_t addr, uint8_t val, void *priv), - void (*outw)(uint16_t addr, uint16_t val, void *priv), - void (*outl)(uint16_t addr, uint32_t val, void *priv), - void *priv) +io_handler(int set, uint16_t base, int size, + uint8_t (*inb)(uint16_t addr, void *priv), + uint16_t (*inw)(uint16_t addr, void *priv), + uint32_t (*inl)(uint16_t addr, void *priv), + void (*outb)(uint16_t addr, uint8_t val, void *priv), + void (*outw)(uint16_t addr, uint16_t val, void *priv), + void (*outl)(uint16_t addr, uint32_t val, void *priv), + void *priv) { io_handler_common(set, base, size, inb, inw, inl, outb, outw, outl, priv, 1); } - void -io_sethandler_interleaved(uint16_t base, int size, - uint8_t (*inb)(uint16_t addr, void *priv), - uint16_t (*inw)(uint16_t addr, void *priv), - uint32_t (*inl)(uint16_t addr, void *priv), - void (*outb)(uint16_t addr, uint8_t val, void *priv), - void (*outw)(uint16_t addr, uint16_t val, void *priv), - void (*outl)(uint16_t addr, uint32_t val, void *priv), - void *priv) +io_sethandler_interleaved(uint16_t base, int size, + uint8_t (*inb)(uint16_t addr, void *priv), + uint16_t (*inw)(uint16_t addr, void *priv), + uint32_t (*inl)(uint16_t addr, void *priv), + void (*outb)(uint16_t addr, uint8_t val, void *priv), + void (*outw)(uint16_t addr, uint16_t val, void *priv), + void (*outl)(uint16_t addr, uint32_t val, void *priv), + void *priv) { io_sethandler_common(base, size, inb, inw, inl, outb, outw, outl, priv, 2); } - void io_removehandler_interleaved(uint16_t base, int size, - uint8_t (*inb)(uint16_t addr, void *priv), - uint16_t (*inw)(uint16_t addr, void *priv), - uint32_t (*inl)(uint16_t addr, void *priv), - void (*outb)(uint16_t addr, uint8_t val, void *priv), - void (*outw)(uint16_t addr, uint16_t val, void *priv), - void (*outl)(uint16_t addr, uint32_t val, void *priv), - void *priv) + uint8_t (*inb)(uint16_t addr, void *priv), + uint16_t (*inw)(uint16_t addr, void *priv), + uint32_t (*inl)(uint16_t addr, void *priv), + void (*outb)(uint16_t addr, uint8_t val, void *priv), + void (*outw)(uint16_t addr, uint16_t val, void *priv), + void (*outl)(uint16_t addr, uint32_t val, void *priv), + void *priv) { io_removehandler_common(base, size, inb, inw, inl, outb, outw, outl, priv, 2); } - void -io_handler_interleaved(int set, uint16_t base, int size, - uint8_t (*inb)(uint16_t addr, void *priv), - uint16_t (*inw)(uint16_t addr, void *priv), - uint32_t (*inl)(uint16_t addr, void *priv), - void (*outb)(uint16_t addr, uint8_t val, void *priv), - void (*outw)(uint16_t addr, uint16_t val, void *priv), - void (*outl)(uint16_t addr, uint32_t val, void *priv), - void *priv) +io_handler_interleaved(int set, uint16_t base, int size, + uint8_t (*inb)(uint16_t addr, void *priv), + uint16_t (*inw)(uint16_t addr, void *priv), + uint32_t (*inl)(uint16_t addr, void *priv), + void (*outb)(uint16_t addr, uint8_t val, void *priv), + void (*outw)(uint16_t addr, uint16_t val, void *priv), + void (*outl)(uint16_t addr, uint32_t val, void *priv), + void *priv) { io_handler_common(set, base, size, inb, inw, inl, outb, outw, outl, priv, 2); } - uint8_t inb(uint16_t port) { uint8_t ret = 0xff; - io_t *p, *q; - int found = 0; - int qfound = 0; + io_t *p; + io_t *q; + int found = 0; +#ifdef ENABLE_IO_LOG + int qfound = 0; +#endif - p = io[port]; - while(p) { - q = p->next; - if (p->inb) { - ret &= p->inb(port, p->priv); - found |= 1; - qfound++; - } - p = q; + if ((pci_flags & FLAG_CONFIG_IO_ON) && (port >= pci_base) && (port < (pci_base + pci_size))) { + ret = pci_read(port, NULL); + found = 1; +#ifdef ENABLE_IO_LOG + qfound = 1; +#endif + } else if ((pci_flags & FLAG_CONFIG_DEV0_IO_ON) && (port >= 0xc000) && (port < 0xc100)) { + ret = pci_read(port, NULL); + found = 1; +#ifdef ENABLE_IO_LOG + qfound = 1; +#endif + } else { + p = io[port]; + while (p) { + q = p->next; + if (p->inb) { + ret &= p->inb(port, p->priv); + found |= 1; +#ifdef ENABLE_IO_LOG + qfound++; +#endif + } + p = q; + } } - if (port & 0x80) - amstrad_latch = AMSTRAD_NOLATCH; - else if (port & 0x4000) - amstrad_latch = AMSTRAD_SW10; - else - amstrad_latch = AMSTRAD_SW9; + if (amstrad_latch & 0x80000000) { + if (port & 0x80) + amstrad_latch = AMSTRAD_NOLATCH | 0x80000000; + else if (port & 0x4000) + amstrad_latch = AMSTRAD_SW10 | 0x80000000; + else + amstrad_latch = AMSTRAD_SW9 | 0x80000000; + } if (!found) - cycles -= io_delay; + cycles -= io_delay; /* TriGem 486-BIOS MHz output. */ +#if 0 if (port == 0x1ed) - ret = 0xfe; + ret = 0xfe; +#endif io_log("[%04X:%08X] (%i, %i, %04i) in b(%04X) = %02X\n", CS, cpu_state.pc, in_smm, found, qfound, port, ret); - return(ret); + return ret; } - void outb(uint16_t port, uint8_t val) { - io_t *p, *q; - int found = 0; - int qfound = 0; + io_t *p; + io_t *q; + int found = 0; +#ifdef ENABLE_IO_LOG + int qfound = 0; +#endif - p = io[port]; - while(p) { - q = p->next; - if (p->outb) { - p->outb(port, val, p->priv); - found |= 1; - qfound++; - } - p = q; + if ((pci_flags & FLAG_CONFIG_IO_ON) && (port >= pci_base) && (port < (pci_base + pci_size))) { + pci_write(port, val, NULL); + found = 1; +#ifdef ENABLE_IO_LOG + qfound = 1; +#endif + } else if ((pci_flags & FLAG_CONFIG_DEV0_IO_ON) && (port >= 0xc000) && (port < 0xc100)) { + pci_write(port, val, NULL); + found = 1; +#ifdef ENABLE_IO_LOG + qfound = 1; +#endif + } else { + p = io[port]; + while (p) { + q = p->next; + if (p->outb) { + p->outb(port, val, p->priv); + found |= 1; +#ifdef ENABLE_IO_LOG + qfound++; +#endif + } + p = q; + } } if (!found) { - cycles -= io_delay; + cycles -= io_delay; #ifdef USE_DYNAREC - if (cpu_use_dynarec && ((port == 0xeb) || (port == 0xed))) - update_tsc(); + if (cpu_use_dynarec && ((port == 0xeb) || (port == 0xed))) + update_tsc(); #endif } @@ -363,97 +390,137 @@ outb(uint16_t port, uint8_t val) return; } - uint16_t inw(uint16_t port) { - io_t *p, *q; - uint16_t ret = 0xffff; - int found = 0; - int qfound = 0; - uint8_t ret8[2]; - int i = 0; + io_t *p; + io_t *q; + uint16_t ret = 0xffff; + int found = 0; +#ifdef ENABLE_IO_LOG + int qfound = 0; +#endif + uint8_t ret8[2]; - p = io[port]; - while(p) { - q = p->next; - if (p->inw) { - ret &= p->inw(port, p->priv); - found |= 2; - qfound++; - } - p = q; + if ((pci_flags & FLAG_CONFIG_IO_ON) && (port >= pci_base) && (port < (pci_base + pci_size))) { + ret = pci_readw(port, NULL); + found = 2; +#ifdef ENABLE_IO_LOG + qfound = 1; +#endif + } else if ((pci_flags & FLAG_CONFIG_DEV0_IO_ON) && (port >= 0xc000) && (port < 0xc100)) { + ret = pci_readw(port, NULL); + found = 2; +#ifdef ENABLE_IO_LOG + qfound = 1; +#endif + } else { + p = io[port]; + while (p) { + q = p->next; + if (p->inw) { + ret &= p->inw(port, p->priv); + found |= 2; +#ifdef ENABLE_IO_LOG + qfound++; +#endif + } + p = q; + } + + ret8[0] = ret & 0xff; + ret8[1] = (ret >> 8) & 0xff; + for (uint8_t i = 0; i < 2; i++) { + p = io[(port + i) & 0xffff]; + while (p) { + q = p->next; + if (p->inb && !p->inw) { + ret8[i] &= p->inb(port + i, p->priv); + found |= 1; +#ifdef ENABLE_IO_LOG + qfound++; +#endif + } + p = q; + } + } + ret = (ret8[1] << 8) | ret8[0]; } - ret8[0] = ret & 0xff; - ret8[1] = (ret >> 8) & 0xff; - for (i = 0; i < 2; i++) { - p = io[(port + i) & 0xffff]; - while(p) { - q = p->next; - if (p->inb && !p->inw) { - ret8[i] &= p->inb(port + i, p->priv); - found |= 1; - qfound++; - } - p = q; - } + if (amstrad_latch & 0x80000000) { + if (port & 0x80) + amstrad_latch = AMSTRAD_NOLATCH | 0x80000000; + else if (port & 0x4000) + amstrad_latch = AMSTRAD_SW10 | 0x80000000; + else + amstrad_latch = AMSTRAD_SW9 | 0x80000000; } - ret = (ret8[1] << 8) | ret8[0]; - - if (port & 0x80) - amstrad_latch = AMSTRAD_NOLATCH; - else if (port & 0x4000) - amstrad_latch = AMSTRAD_SW10; - else - amstrad_latch = AMSTRAD_SW9; if (!found) - cycles -= io_delay; + cycles -= io_delay; io_log("[%04X:%08X] (%i, %i, %04i) in w(%04X) = %04X\n", CS, cpu_state.pc, in_smm, found, qfound, port, ret); return ret; } - void outw(uint16_t port, uint16_t val) { - io_t *p, *q; - int found = 0; - int qfound = 0; - int i = 0; + io_t *p; + io_t *q; + int found = 0; +#ifdef ENABLE_IO_LOG + int qfound = 0; +#endif - p = io[port]; - while(p) { - q = p->next; - if (p->outw) { - p->outw(port, val, p->priv); - found |= 2; - qfound++; - } - p = q; - } + if ((pci_flags & FLAG_CONFIG_IO_ON) && (port >= pci_base) && (port < (pci_base + pci_size))) { + pci_writew(port, val, NULL); + found = 2; +#ifdef ENABLE_IO_LOG + qfound = 1; +#endif + } else if ((pci_flags & FLAG_CONFIG_DEV0_IO_ON) && (port >= 0xc000) && (port < 0xc100)) { + pci_writew(port, val, NULL); + found = 2; +#ifdef ENABLE_IO_LOG + qfound = 1; +#endif + } else { + p = io[port]; + while (p) { + q = p->next; + if (p->outw) { + p->outw(port, val, p->priv); + found |= 2; +#ifdef ENABLE_IO_LOG + qfound++; +#endif + } + p = q; + } - for (i = 0; i < 2; i++) { - p = io[(port + i) & 0xffff]; - while(p) { - q = p->next; - if (p->outb && !p->outw) { - p->outb(port + i, val >> (i << 3), p->priv); - found |= 1; - qfound++; - } - p = q; - } + for (uint8_t i = 0; i < 2; i++) { + p = io[(port + i) & 0xffff]; + while (p) { + q = p->next; + if (p->outb && !p->outw) { + p->outb(port + i, val >> (i << 3), p->priv); + found |= 1; +#ifdef ENABLE_IO_LOG + qfound++; +#endif + } + p = q; + } + } } if (!found) { - cycles -= io_delay; + cycles -= io_delay; #ifdef USE_DYNAREC - if (cpu_use_dynarec && ((port == 0xeb) || (port == 0xed))) - update_tsc(); + if (cpu_use_dynarec && ((port == 0xeb) || (port == 0xed))) + update_tsc(); #endif } @@ -462,131 +529,187 @@ outw(uint16_t port, uint16_t val) return; } - uint32_t inl(uint16_t port) { - io_t *p, *q; + io_t *p; + io_t *q; uint32_t ret = 0xffffffff; uint16_t ret16[2]; - uint8_t ret8[4]; - int found = 0; - int qfound = 0; - int i = 0; + uint8_t ret8[4]; + int found = 0; +#ifdef ENABLE_IO_LOG + int qfound = 0; +#endif - p = io[port]; - while(p) { - q = p->next; - if (p->inl) { - ret &= p->inl(port, p->priv); - found |= 4; - qfound++; - } - p = q; + if ((pci_flags & FLAG_CONFIG_IO_ON) && (port >= pci_base) && (port < (pci_base + pci_size))) { + ret = pci_readl(port, NULL); + found = 4; +#ifdef ENABLE_IO_LOG + qfound = 1; +#endif + } else if ((pci_flags & FLAG_CONFIG_DEV0_IO_ON) && (port >= 0xc000) && (port < 0xc100)) { + ret = pci_readl(port, NULL); + found = 4; +#ifdef ENABLE_IO_LOG + qfound = 1; +#endif + } else { + p = io[port]; + while (p) { + q = p->next; + if (p->inl) { + ret &= p->inl(port, p->priv); + found |= 4; +#ifdef ENABLE_IO_LOG + qfound++; +#endif + } + p = q; + } + + ret16[0] = ret & 0xffff; + ret16[1] = (ret >> 16) & 0xffff; + p = io[port & 0xffff]; + while (p) { + q = p->next; + if (p->inw && !p->inl) { + ret16[0] &= p->inw(port, p->priv); + found |= 2; +#ifdef ENABLE_IO_LOG + qfound++; +#endif + } + p = q; + } + + p = io[(port + 2) & 0xffff]; + while (p) { + q = p->next; + if (p->inw && !p->inl) { + ret16[1] &= p->inw(port + 2, p->priv); + found |= 2; +#ifdef ENABLE_IO_LOG + qfound++; +#endif + } + p = q; + } + ret = (ret16[1] << 16) | ret16[0]; + + ret8[0] = ret & 0xff; + ret8[1] = (ret >> 8) & 0xff; + ret8[2] = (ret >> 16) & 0xff; + ret8[3] = (ret >> 24) & 0xff; + for (uint8_t i = 0; i < 4; i++) { + p = io[(port + i) & 0xffff]; + while (p) { + q = p->next; + if (p->inb && !p->inw && !p->inl) { + ret8[i] &= p->inb(port + i, p->priv); + found |= 1; +#ifdef ENABLE_IO_LOG + qfound++; +#endif + } + p = q; + } + } + ret = (ret8[3] << 24) | (ret8[2] << 16) | (ret8[1] << 8) | ret8[0]; } - ret16[0] = ret & 0xffff; - ret16[1] = (ret >> 16) & 0xffff; - for (i = 0; i < 4; i += 2) { - p = io[(port + i) & 0xffff]; - while(p) { - q = p->next; - if (p->inw && !p->inl) { - ret16[i >> 1] &= p->inw(port + i, p->priv); - found |= 2; - qfound++; - } - p = q; - } + if (amstrad_latch & 0x80000000) { + if (port & 0x80) + amstrad_latch = AMSTRAD_NOLATCH | 0x80000000; + else if (port & 0x4000) + amstrad_latch = AMSTRAD_SW10 | 0x80000000; + else + amstrad_latch = AMSTRAD_SW9 | 0x80000000; } - ret = (ret16[1] << 16) | ret16[0]; - - ret8[0] = ret & 0xff; - ret8[1] = (ret >> 8) & 0xff; - ret8[2] = (ret >> 16) & 0xff; - ret8[3] = (ret >> 24) & 0xff; - for (i = 0; i < 4; i++) { - p = io[(port + i) & 0xffff]; - while(p) { - q = p->next; - if (p->inb && !p->inw && !p->inl) { - ret8[i] &= p->inb(port + i, p->priv); - found |= 1; - qfound++; - } - p = q; - } - } - ret = (ret8[3] << 24) | (ret8[2] << 16) | (ret8[1] << 8) | ret8[0]; - - if (port & 0x80) - amstrad_latch = AMSTRAD_NOLATCH; - else if (port & 0x4000) - amstrad_latch = AMSTRAD_SW10; - else - amstrad_latch = AMSTRAD_SW9; if (!found) - cycles -= io_delay; + cycles -= io_delay; io_log("[%04X:%08X] (%i, %i, %04i) in l(%04X) = %08X\n", CS, cpu_state.pc, in_smm, found, qfound, port, ret); return ret; } - void outl(uint16_t port, uint32_t val) { - io_t *p, *q; - int found = 0; - int qfound = 0; - int i = 0; + io_t *p; + io_t *q; + int found = 0; +#ifdef ENABLE_IO_LOG + int qfound = 0; +#endif + int i = 0; - p = io[port]; - if (p) { - while(p) { - q = p->next; - if (p->outl) { - p->outl(port, val, p->priv); - found |= 4; - qfound++; - } - p = q; - } - } + if ((pci_flags & FLAG_CONFIG_IO_ON) && (port >= pci_base) && (port < (pci_base + pci_size))) { + pci_writel(port, val, NULL); + found = 4; +#ifdef ENABLE_IO_LOG + qfound = 1; +#endif + } else if ((pci_flags & FLAG_CONFIG_DEV0_IO_ON) && (port >= 0xc000) && (port < 0xc100)) { + pci_writel(port, val, NULL); + found = 4; +#ifdef ENABLE_IO_LOG + qfound = 1; +#endif + } else { + p = io[port]; + if (p) { + while (p) { + q = p->next; + if (p->outl) { + p->outl(port, val, p->priv); + found |= 4; +#ifdef ENABLE_IO_LOG + qfound++; +#endif + } + p = q; + } + } - for (i = 0; i < 4; i += 2) { - p = io[(port + i) & 0xffff]; - while(p) { - q = p->next; - if (p->outw && !p->outl) { - p->outw(port + i, val >> (i << 3), p->priv); - found |= 2; - qfound++; - } - p = q; - } - } + for (i = 0; i < 4; i += 2) { + p = io[(port + i) & 0xffff]; + while (p) { + q = p->next; + if (p->outw && !p->outl) { + p->outw(port + i, val >> (i << 3), p->priv); + found |= 2; +#ifdef ENABLE_IO_LOG + qfound++; +#endif + } + p = q; + } + } - for (i = 0; i < 4; i++) { - p = io[(port + i) & 0xffff]; - while(p) { - q = p->next; - if (p->outb && !p->outw && !p->outl) { - p->outb(port + i, val >> (i << 3), p->priv); - found |= 1; - qfound++; - } - p = q; - } + for (i = 0; i < 4; i++) { + p = io[(port + i) & 0xffff]; + while (p) { + q = p->next; + if (p->outb && !p->outw && !p->outl) { + p->outb(port + i, val >> (i << 3), p->priv); + found |= 1; +#ifdef ENABLE_IO_LOG + qfound++; +#endif + } + p = q; + } + } } if (!found) { - cycles -= io_delay; + cycles -= io_delay; #ifdef USE_DYNAREC - if (cpu_use_dynarec && ((port == 0xeb) || (port == 0xed))) - update_tsc(); + if (cpu_use_dynarec && ((port == 0xeb) || (port == 0xed))) + update_tsc(); #endif } @@ -595,7 +718,6 @@ outl(uint16_t port, uint32_t val) return; } - static uint8_t io_trap_readb(uint16_t addr, void *priv) { @@ -604,7 +726,6 @@ io_trap_readb(uint16_t addr, void *priv) return 0xff; } - static uint16_t io_trap_readw(uint16_t addr, void *priv) { @@ -613,7 +734,6 @@ io_trap_readw(uint16_t addr, void *priv) return 0xffff; } - static uint32_t io_trap_readl(uint16_t addr, void *priv) { @@ -622,7 +742,6 @@ io_trap_readl(uint16_t addr, void *priv) return 0xffffffff; } - static void io_trap_writeb(uint16_t addr, uint8_t val, void *priv) { @@ -630,7 +749,6 @@ io_trap_writeb(uint16_t addr, uint8_t val, void *priv) trap->func(1, addr, 1, val, trap->priv); } - static void io_trap_writew(uint16_t addr, uint16_t val, void *priv) { @@ -638,7 +756,6 @@ io_trap_writew(uint16_t addr, uint16_t val, void *priv) trap->func(2, addr, 1, val, trap->priv); } - static void io_trap_writel(uint16_t addr, uint32_t val, void *priv) { @@ -646,61 +763,58 @@ io_trap_writel(uint16_t addr, uint32_t val, void *priv) trap->func(4, addr, 1, val, trap->priv); } - void * io_trap_add(void (*func)(int size, uint16_t addr, uint8_t write, uint8_t val, void *priv), - void *priv) + void *priv) { /* Instantiate new I/O trap. */ io_trap_t *trap = (io_trap_t *) malloc(sizeof(io_trap_t)); - trap->enable = 0; + trap->enable = 0; trap->base = trap->size = 0; - trap->func = func; - trap->priv = priv; + trap->func = func; + trap->priv = priv; return trap; } - void io_trap_remap(void *handle, int enable, uint16_t addr, uint16_t size) { io_trap_t *trap = (io_trap_t *) handle; if (!trap) - return; + return; io_log("I/O: Remapping trap from %04X-%04X (enable %d) to %04X-%04X (enable %d)\n", - trap->base, trap->base + trap->size - 1, trap->enable, addr, addr + size - 1, enable); + trap->base, trap->base + trap->size - 1, trap->enable, addr, addr + size - 1, enable); /* Remove old I/O mapping. */ - if (trap->enable && trap->base && trap->size) { - io_removehandler(trap->base, trap->size, - io_trap_readb, io_trap_readw, io_trap_readl, - io_trap_writeb, io_trap_writew, io_trap_writel, - trap); + if (trap->enable && trap->size) { + io_removehandler(trap->base, trap->size, + io_trap_readb, io_trap_readw, io_trap_readl, + io_trap_writeb, io_trap_writew, io_trap_writel, + trap); } /* Set trap enable flag, base address and size. */ trap->enable = !!enable; - trap->base = addr; - trap->size = size; + trap->base = addr; + trap->size = size; /* Add new I/O mapping. */ - if (trap->enable && trap->base && trap->size) { - io_sethandler(trap->base, trap->size, - io_trap_readb, io_trap_readw, io_trap_readl, - io_trap_writeb, io_trap_writew, io_trap_writel, - trap); + if (trap->enable && trap->size) { + io_sethandler(trap->base, trap->size, + io_trap_readb, io_trap_readw, io_trap_readl, + io_trap_writeb, io_trap_writew, io_trap_writel, + trap); } } - void io_trap_remove(void *handle) { io_trap_t *trap = (io_trap_t *) handle; if (!trap) - return; + return; /* Unmap I/O trap before freeing it. */ io_trap_remap(trap, 0, 0, 0); diff --git a/src/ioapic.c b/src/ioapic.c index b899beec0..c3939f249 100644 --- a/src/ioapic.c +++ b/src/ioapic.c @@ -1,19 +1,19 @@ /* - * 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. + * 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. + * This file is part of the 86Box distribution. * - * Skeleton I/O APIC implementation, currently housing the MPS - * table patcher for machines that require it. + * Skeleton I/O APIC implementation, currently housing the MPS + * table patcher for machines that require it. * * * - * Author: RichardG, + * Authors: RichardG, * - * Copyright 2020 RichardG. + * Copyright 2020 RichardG. */ #include #include @@ -27,86 +27,81 @@ #include <86box/machine.h> #include <86box/mem.h> #include <86box/chipset.h> +#include <86box/plat_unused.h> - -typedef struct { +typedef struct ioapic_t { uint8_t dummy; } ioapic_t; - #ifdef ENABLE_IOAPIC_LOG int ioapic_do_log = ENABLE_IOAPIC_LOG; - static void ioapic_log(const char *fmt, ...) { va_list ap; if (ioapic_do_log) { - va_start(ap, fmt); - pclog_ex(fmt, ap); - va_end(ap); + va_start(ap, fmt); + pclog_ex(fmt, ap); + va_end(ap); } } #else -#define ioapic_log(fmt, ...) +# define ioapic_log(fmt, ...) #endif - static void -ioapic_write(uint16_t port, uint8_t val, void *priv) +ioapic_write(UNUSED(uint16_t port), uint8_t val, UNUSED(void *priv)) { - uint32_t addr, pcmp; + uint32_t pcmp; /* target POST FF, issued by Award before jumping to the bootloader */ if (val != 0xff) - return; + return; ioapic_log("IOAPIC: Caught POST %02X\n", val); /* The _MP_ table must be located in the BIOS area, the EBDA, or the last 1k of conventional memory; at a 16-byte boundary in all cases. Award writes both tables to the BIOS area. */ - for (addr = 0xf0000; addr <= 0xfffff; addr += 16) { - /* check signature for the _MP_ table (Floating Point Structure) */ - if (mem_readl_phys(addr) != 0x5f504d5f) /* ASCII "_MP_" */ - continue; + for (uint32_t addr = 0xf0000; addr <= 0xfffff; addr += 16) { + /* check signature for the _MP_ table (Floating Point Structure) */ + if (mem_readl_phys(addr) != 0x5f504d5f) /* ASCII "_MP_" */ + continue; - /* read and check pointer to the PCMP table (Configuration Table) */ - pcmp = mem_readl_phys(addr + 4); - if ((pcmp < 0xf0000) || (pcmp > 0xfffff) || (mem_readl_phys(pcmp) != 0x504d4350)) /* ASCII "PCMP" */ - continue; + /* read and check pointer to the PCMP table (Configuration Table) */ + pcmp = mem_readl_phys(addr + 4); + if ((pcmp < 0xf0000) || (pcmp > 0xfffff) || (mem_readl_phys(pcmp) != 0x504d4350)) /* ASCII "PCMP" */ + continue; - /* patch over the signature on both tables */ - ioapic_log("IOAPIC: Patching _MP_ [%08x] and PCMP [%08x] tables\n", addr, pcmp); - ram[addr] = ram[addr + 1] = ram[addr + 2] = ram[addr + 3] = 0xff; - ram[pcmp] = ram[pcmp + 1] = ram[pcmp + 2] = ram[pcmp + 3] = 0xff; + /* patch over the signature on both tables */ + ioapic_log("IOAPIC: Patching _MP_ [%08x] and PCMP [%08x] tables\n", addr, pcmp); + ram[addr] = ram[addr + 1] = ram[addr + 2] = ram[addr + 3] = 0xff; + ram[pcmp] = ram[pcmp + 1] = ram[pcmp + 2] = ram[pcmp + 3] = 0xff; - break; + break; } } - static void -ioapic_reset(ioapic_t *dev) +ioapic_reset(UNUSED(ioapic_t *dev)) { + // } - static void ioapic_close(void *priv) { ioapic_t *dev = (ioapic_t *) priv; io_removehandler(0x80, 1, - NULL, NULL, NULL, ioapic_write, NULL, NULL, NULL); + NULL, NULL, NULL, ioapic_write, NULL, NULL, NULL); free(dev); } - static void * -ioapic_init(const device_t *info) +ioapic_init(UNUSED(const device_t *info)) { ioapic_t *dev = (ioapic_t *) malloc(sizeof(ioapic_t)); memset(dev, 0, sizeof(ioapic_t)); @@ -114,18 +109,21 @@ ioapic_init(const device_t *info) ioapic_reset(dev); io_sethandler(0x80, 1, - NULL, NULL, NULL, ioapic_write, NULL, NULL, NULL); + NULL, NULL, NULL, ioapic_write, NULL, NULL, NULL); return dev; } - const device_t ioapic_device = { - "I/O Advanced Programmable Interrupt Controller", - "ioapic", - DEVICE_AT, - 0, - ioapic_init, ioapic_close, NULL, - { NULL }, NULL, NULL, - NULL + .name = "I/O Advanced Programmable Interrupt Controller", + .internal_name = "ioapic", + .flags = DEVICE_AT, + .local = 0, + .init = ioapic_init, + .close = ioapic_close, + .reset = NULL, + { .available = NULL }, + .speed_changed = NULL, + .force_redraw = NULL, + .config = NULL }; diff --git a/src/log.c b/src/log.c index 99bab97a5..b5267d70b 100644 --- a/src/log.c +++ b/src/log.c @@ -1,20 +1,20 @@ /* - * 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. + * 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. + * This file is part of the 86Box distribution. * - * The handler of the new logging system. + * The handler of the new logging system. * * * - * Authors: Miran Grca, - * Fred N. van Kempen, + * Authors: Miran Grca, + * Fred N. van Kempen, * - * Copyright 2021 Miran Grca. - * Copyright 2021 Fred N. van Kempen. + * Copyright 2021 Miran Grca. + * Copyright 2021 Fred N. van Kempen. */ #include #include @@ -34,17 +34,15 @@ #include <86box/version.h> #include <86box/log.h> - #ifndef RELEASE_BUILD -typedef struct -{ - char buff[1024], *dev_name; - int seen, suppr_seen; +typedef struct log_t { + char buff[1024]; + char *dev_name; + int seen; + int suppr_seen; } log_t; - -extern FILE *stdlog; /* file to log output to */ - +extern FILE *stdlog; /* file to log output to */ void log_set_suppr_seen(void *priv, int suppr_seen) @@ -54,7 +52,6 @@ log_set_suppr_seen(void *priv, int suppr_seen) log->suppr_seen = suppr_seen; } - void log_set_dev_name(void *priv, char *dev_name) { @@ -63,19 +60,17 @@ log_set_dev_name(void *priv, char *dev_name) log->dev_name = dev_name; } - static void log_copy(log_t *log, char *dest, const char *src, size_t dest_size) { memset(dest, 0x00, dest_size * sizeof(char)); if (log && log->dev_name && strcmp(log->dev_name, "")) { - strcat(dest, log->dev_name); - strcat(dest, ": "); + strcat(dest, log->dev_name); + strcat(dest, ": "); } strcat(dest, src); } - /* * Log something to the logfile or stdout. * @@ -87,50 +82,51 @@ void log_out(void *priv, const char *fmt, va_list ap) { log_t *log = (log_t *) priv; - char temp[1024], fmt2[1024]; + char temp[1024]; + char fmt2[1024]; if (log == NULL) - return; + return; if (strcmp(fmt, "") == 0) - return; + return; if (stdlog == NULL) { - if (log_path[0] != '\0') { - stdlog = plat_fopen(log_path, "w"); - if (stdlog == NULL) - stdlog = stdout; - } else - stdlog = stdout; + if (log_path[0] != '\0') { + stdlog = plat_fopen(log_path, "w"); + if (stdlog == NULL) + stdlog = stdout; + } else + stdlog = stdout; } vsprintf(temp, fmt, ap); - if (log->suppr_seen && ! strcmp(log->buff, temp)) - log->seen++; + if (log->suppr_seen && !strcmp(log->buff, temp)) + log->seen++; else { - if (log->suppr_seen && log->seen) { - log_copy(log, fmt2, "*** %d repeats ***\n", 1024); - fprintf(stdlog, fmt2, log->seen); - } - log->seen = 0; - strcpy(log->buff, temp); - log_copy(log, fmt2, temp, 1024); - fprintf(stdlog, fmt2, ap); + if (log->suppr_seen && log->seen) { + log_copy(log, fmt2, "*** %d repeats ***\n", 1024); + fprintf(stdlog, fmt2, log->seen); + } + log->seen = 0; + strcpy(log->buff, temp); + log_copy(log, fmt2, temp, 1024); + fprintf(stdlog, fmt2, ap); } fflush(stdlog); } - void log_fatal(void *priv, const char *fmt, ...) { - log_t *log = (log_t *) priv; - char temp[1024], fmt2[1024]; + log_t *log = (log_t *) priv; + char temp[1024]; + char fmt2[1024]; va_list ap; if (log == NULL) - return; + return; va_start(ap, fmt); log_copy(log, fmt2, fmt, 1024); @@ -140,7 +136,6 @@ log_fatal(void *priv, const char *fmt, ...) exit(-1); } - void * log_open(char *dev_name) { @@ -148,13 +143,12 @@ log_open(char *dev_name) memset(log, 0, sizeof(log_t)); - log->dev_name = dev_name; + log->dev_name = dev_name; log->suppr_seen = 1; return (void *) log; } - void log_close(void *priv) { diff --git a/src/lpt.c b/src/lpt.c index e2cb6ad5e..5bbf79875 100644 --- a/src/lpt.c +++ b/src/lpt.c @@ -13,222 +13,237 @@ #include <86box/prt_devs.h> #include <86box/net_plip.h> +lpt_port_t lpt_ports[PARALLEL_MAX]; -lpt_port_t lpt_ports[PARALLEL_MAX]; - - -static const struct { - const char *internal_name; - const lpt_device_t *device; -} lpt_devices[] = { - {"none", NULL}, - {"dss", &dss_device}, - {"lpt_dac", &lpt_dac_device}, - {"lpt_dac_stereo", &lpt_dac_stereo_device}, - {"text_prt", &lpt_prt_text_device}, - {"dot_matrix", &lpt_prt_escp_device}, - {"postscript", &lpt_prt_ps_device}, - {"plip", &lpt_plip_device}, - {"dongle_savquest", &lpt_hasp_savquest_device}, - {"", NULL} +const lpt_device_t lpt_none_device = { + .name = "None", + .internal_name = "none", + .init = NULL, + .close = NULL, + .write_data = NULL, + .write_ctrl = NULL, + .read_data = NULL, + .read_status = NULL, + .read_ctrl = NULL }; +static const struct { + const char *internal_name; + const lpt_device_t *device; +} lpt_devices[] = { + // clang-format off + {"none", &lpt_none_device }, + {"dss", &dss_device }, + {"lpt_dac", &lpt_dac_device }, + {"lpt_dac_stereo", &lpt_dac_stereo_device }, + {"text_prt", &lpt_prt_text_device }, + {"dot_matrix", &lpt_prt_escp_device }, + {"postscript", &lpt_prt_ps_device }, + {"plip", &lpt_plip_device }, + {"dongle_savquest", &lpt_hasp_savquest_device }, + {"", NULL } + // clang-format on +}; -char * +const char * lpt_device_get_name(int id) { - if (strlen((char *) lpt_devices[id].internal_name) == 0) - return NULL; + if (strlen(lpt_devices[id].internal_name) == 0) + return NULL; if (!lpt_devices[id].device) - return "None"; - return (char *) lpt_devices[id].device->name; + return "None"; + return lpt_devices[id].device->name; } - -char * +const char * lpt_device_get_internal_name(int id) { - if (strlen((char *) lpt_devices[id].internal_name) == 0) - return NULL; - return (char *) lpt_devices[id].internal_name; + if (strlen(lpt_devices[id].internal_name) == 0) + return NULL; + return lpt_devices[id].internal_name; } - int lpt_device_get_from_internal_name(char *s) { int c = 0; - while (strlen((char *) lpt_devices[c].internal_name) != 0) { - if (strcmp(lpt_devices[c].internal_name, s) == 0) - return c; - c++; + while (strlen(lpt_devices[c].internal_name) != 0) { + if (strcmp(lpt_devices[c].internal_name, s) == 0) + return c; + c++; } return 0; } - void lpt_devices_init(void) { - int i = 0; + for (uint8_t i = 0; i < PARALLEL_MAX; i++) { + lpt_ports[i].dt = (lpt_device_t *) lpt_devices[lpt_ports[i].device].device; - for (i = 0; i < PARALLEL_MAX; i++) { - lpt_ports[i].dt = (lpt_device_t *) lpt_devices[lpt_ports[i].device].device; - - if (lpt_ports[i].dt) - lpt_ports[i].priv = lpt_ports[i].dt->init(&lpt_ports[i]); + if (lpt_ports[i].dt && lpt_ports[i].dt->init) + lpt_ports[i].priv = lpt_ports[i].dt->init(&lpt_ports[i]); } } - void lpt_devices_close(void) { - int i = 0; lpt_port_t *dev; - for (i = 0; i < PARALLEL_MAX; i++) { - dev = &lpt_ports[i]; + for (uint8_t i = 0; i < PARALLEL_MAX; i++) { + dev = &lpt_ports[i]; - if (dev->dt) - dev->dt->close(dev->priv); + if (lpt_ports[i].dt && lpt_ports[i].dt->close) + dev->dt->close(dev->priv); dev->dt = NULL; } } - void lpt_write(uint16_t port, uint8_t val, void *priv) { lpt_port_t *dev = (lpt_port_t *) priv; switch (port & 3) { - case 0: - if (dev->dt && dev->dt->write_data && dev->priv) - dev->dt->write_data(val, dev->priv); - dev->dat = val; - break; + case 0: + if (dev->dt && dev->dt->write_data && dev->priv) + dev->dt->write_data(val, dev->priv); + dev->dat = val; + break; - case 1: - break; + case 1: + break; - case 2: - if (dev->dt && dev->dt->write_ctrl && dev->priv) - dev->dt->write_ctrl(val, dev->priv); - dev->ctrl = val; - dev->enable_irq = val & 0x10; - break; + case 2: + if (dev->dt && dev->dt->write_ctrl && dev->priv) + dev->dt->write_ctrl(val, dev->priv); + dev->ctrl = val; + dev->enable_irq = val & 0x10; + break; + + default: + break; } } - uint8_t lpt_read(uint16_t port, void *priv) { - uint8_t ret = 0xff; + uint8_t ret = 0xff; lpt_port_t *dev = (lpt_port_t *) priv; switch (port & 3) { - case 0: - if (dev->dt && dev->dt->read_data && dev->priv) - ret = dev->dt->read_data(dev->priv); - else - ret = dev->dat; - break; + case 0: + if (dev->dt && dev->dt->read_data && dev->priv) + ret = dev->dt->read_data(dev->priv); + else + ret = dev->dat; + break; - case 1: - if (dev->dt && dev->dt->read_status && dev->priv) - ret = dev->dt->read_status(dev->priv) | 0x07; - else - ret = 0xdf; - break; + case 1: + if (dev->dt && dev->dt->read_status && dev->priv) + ret = dev->dt->read_status(dev->priv) | 0x07; + else + ret = 0xdf; + break; - case 2: - if (dev->dt && dev->dt->read_ctrl && dev->priv) - ret = (dev->dt->read_ctrl(dev->priv) & 0xef) | dev->enable_irq; - else - ret = 0xe0 | dev->ctrl | dev->enable_irq; - break; + case 2: + if (dev->dt && dev->dt->read_ctrl && dev->priv) + ret = (dev->dt->read_ctrl(dev->priv) & 0xef) | dev->enable_irq; + else + ret = 0xe0 | dev->ctrl | dev->enable_irq; + break; + + default: + break; } return ret; } +uint8_t +lpt_read_status(int port) +{ + lpt_port_t *dev = &(lpt_ports[port]); + uint8_t ret = 0xff; + + if (dev->dt && dev->dt->read_status && dev->priv) + ret = dev->dt->read_status(dev->priv) | 0x07; + else + ret = 0xdf; + + return ret; +} void lpt_irq(void *priv, int raise) { - lpt_port_t *dev = (lpt_port_t *) priv; + const lpt_port_t *dev = (lpt_port_t *) priv; if (dev->enable_irq && (dev->irq != 0xff)) { - if (raise) - picint(1 << dev->irq); - else - picintc(1 << dev->irq); + if (raise) + picint(1 << dev->irq); + else + picintc(1 << dev->irq); } } - void lpt_init(void) { - int i; - uint16_t default_ports[PARALLEL_MAX] = { 0x378, 0x278, 0x3bc, 0x268 }; /*, 0x27c, 0x26c }; */ - uint8_t default_irqs[PARALLEL_MAX] = { 7, 5, 7, 5 }; /* , 7, 5 }; */ + uint16_t default_ports[PARALLEL_MAX] = { LPT1_ADDR, LPT2_ADDR, LPT_MDA_ADDR, LPT4_ADDR }; + uint8_t default_irqs[PARALLEL_MAX] = { LPT1_IRQ, LPT2_IRQ, LPT_MDA_IRQ, LPT4_IRQ }; - for (i = 0; i < PARALLEL_MAX; i++) { - lpt_ports[i].addr = 0xffff; - lpt_ports[i].irq = 0xff; - lpt_ports[i].enable_irq = 0x10; + for (uint8_t i = 0; i < PARALLEL_MAX; i++) { + lpt_ports[i].addr = 0xffff; + lpt_ports[i].irq = 0xff; + lpt_ports[i].enable_irq = 0x10; - if (lpt_ports[i].enabled) { - lpt_port_init(i, default_ports[i]); - lpt_port_irq(i, default_irqs[i]); - } + if (lpt_ports[i].enabled) { + lpt_port_init(i, default_ports[i]); + lpt_port_irq(i, default_irqs[i]); + } } } - void lpt_port_init(int i, uint16_t port) { if (lpt_ports[i].enabled) { - if (lpt_ports[i].addr != 0xffff) - io_removehandler(lpt_ports[i].addr, 0x0003, lpt_read, NULL, NULL, lpt_write, NULL, NULL, &lpt_ports[i]); - if (port != 0xffff) - io_sethandler(port, 0x0003, lpt_read, NULL, NULL, lpt_write, NULL, NULL, &lpt_ports[i]); - lpt_ports[i].addr = port; + if (lpt_ports[i].addr != 0xffff) + io_removehandler(lpt_ports[i].addr, 0x0003, lpt_read, NULL, NULL, lpt_write, NULL, NULL, &lpt_ports[i]); + if (port != 0xffff) + io_sethandler(port, 0x0003, lpt_read, NULL, NULL, lpt_write, NULL, NULL, &lpt_ports[i]); + lpt_ports[i].addr = port; } else - lpt_ports[i].addr = 0xffff; + lpt_ports[i].addr = 0xffff; } - void lpt_port_irq(int i, uint8_t irq) { if (lpt_ports[i].enabled) - lpt_ports[i].irq = irq; + lpt_ports[i].irq = irq; else - lpt_ports[i].irq = 0xff; + lpt_ports[i].irq = 0xff; } - void lpt_port_remove(int i) { if (lpt_ports[i].enabled && (lpt_ports[i].addr != 0xffff)) { - io_removehandler(lpt_ports[i].addr, 0x0003, lpt_read, NULL, NULL, lpt_write, NULL, NULL, &lpt_ports[i]); - lpt_ports[i].addr = 0xffff; + io_removehandler(lpt_ports[i].addr, 0x0003, lpt_read, NULL, NULL, lpt_write, NULL, NULL, &lpt_ports[i]); + lpt_ports[i].addr = 0xffff; } } - void lpt1_remove_ams(void) { if (lpt_ports[0].enabled) - io_removehandler(lpt_ports[0].addr + 1, 0x0002, lpt_read, NULL, NULL, lpt_write, NULL, NULL, &lpt_ports[0]); + io_removehandler(lpt_ports[0].addr + 1, 0x0002, lpt_read, NULL, NULL, lpt_write, NULL, NULL, &lpt_ports[0]); } diff --git a/src/mac/CMakeLists.txt b/src/mac/CMakeLists.txt index 6682d5bcd..bbdf1d5d5 100644 --- a/src/mac/CMakeLists.txt +++ b/src/mac/CMakeLists.txt @@ -1,20 +1,20 @@ # -# 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. +# 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. +# This file is part of the 86Box distribution. # -# CMake build script. +# CMake build script. # -# Authors: dob205, -# Jerome Vernet -# David HrdliÄka, +# Authors: dob205, +# Jerome Vernet +# David HrdliÄka, # -# Copyright 2021 dob205. -# Copyright 2021 Jerome Vernet. -# Copyright 2021 David HrdliÄka. +# Copyright 2021 dob205. +# Copyright 2021 Jerome Vernet. +# Copyright 2021 David HrdliÄka. # # Pick the bundle icon depending on the release channel @@ -29,7 +29,7 @@ else() endif() target_link_libraries(86Box "-framework AppKit") -target_sources(86Box PRIVATE macOSXGlue.m ${APP_ICON_MACOSX}) +target_sources(86Box PRIVATE ${APP_ICON_MACOSX}) # Make sure the icon is copied to the bundle set_source_files_properties(${APP_ICON_MACOSX} @@ -38,9 +38,9 @@ set_source_files_properties(${APP_ICON_MACOSX} # Prepare long version string if(EMU_BUILD) - set(LONG_VER_STRING "${CMAKE_PROJECT_VERSION} [${EMU_BUILD}]") + set(LONG_VER_STRING "${CMAKE_PROJECT_VERSION} [${EMU_BUILD}]") else() - set(LONG_VER_STRING "${CMAKE_PROJECT_VERSION}") + set(LONG_VER_STRING "${CMAKE_PROJECT_VERSION}") endif() # Generate Info.plist @@ -48,7 +48,6 @@ configure_file(Info.plist.in Info.plist @ONLY) set_target_properties(86Box PROPERTIES MACOSX_BUNDLE_INFO_PLIST ${CMAKE_CURRENT_BINARY_DIR}/Info.plist) -set(CMAKE_XCODE_ATTRIBUTE_OTHER_CODE_SIGN_FLAGS "-o linker-signed") -set(XCODE_ATTRIBUTE_CODE_SIGNING_REQUIRED "YES") -set(XCODE_ATTRIBUTE_CODE_SIGN_IDENTITY "-") -#set(XCODE_ATTRIBUTE_CODE_SIGN_ENTITLEMENTS ${CMAKE_CURRENT_SOURCE_DIR}/mac/codesign/dev/app.entitlements) \ No newline at end of file +#set(XCODE_ATTRIBUTE_CODE_SIGNING_REQUIRED "YES") +#set(XCODE_ATTRIBUTE_CODE_SIGN_IDENTITY "-") +#set(XCODE_ATTRIBUTE_CODE_SIGN_ENTITLEMENTS ${CMAKE_CURRENT_SOURCE_DIR}/mac/codesign/dev/app.entitlements) diff --git a/src/mac/icons/beta/86Box.icns b/src/mac/icons/beta/86Box.icns index 0068beeda..e1e78daa7 100644 Binary files a/src/mac/icons/beta/86Box.icns and b/src/mac/icons/beta/86Box.icns differ diff --git a/src/mac/icons/branch/86Box.icns b/src/mac/icons/branch/86Box.icns index a2631c66e..f466bfe3f 100644 Binary files a/src/mac/icons/branch/86Box.icns and b/src/mac/icons/branch/86Box.icns differ diff --git a/src/mac/icons/dev/86Box.icns b/src/mac/icons/dev/86Box.icns index 5ff137b55..9663821d5 100644 Binary files a/src/mac/icons/dev/86Box.icns and b/src/mac/icons/dev/86Box.icns differ diff --git a/src/mac/icons/release/86Box.icns b/src/mac/icons/release/86Box.icns index 4f15661ed..8d375d4bf 100644 Binary files a/src/mac/icons/release/86Box.icns and b/src/mac/icons/release/86Box.icns differ diff --git a/src/mac/macOSXGlue.m b/src/mac/macOSXGlue.m deleted file mode 100644 index 07b8c3552..000000000 --- a/src/mac/macOSXGlue.m +++ /dev/null @@ -1,45 +0,0 @@ -// -// macOSXGlue.m -// 86BOx MacoSx Glue.... -// Todo: so much -// Created by Jerome Vernet on 18/11/2021. -// Copyright © 2021 Jerome Vernet. All rights reserved. -// - -#import - -void getDefaultROMPath(char* Path) -{ - NSFileManager* sharedFM = [NSFileManager defaultManager]; - NSArray* possibleURLs = [sharedFM URLsForDirectory:NSApplicationSupportDirectory - inDomains:NSUserDomainMask]; - NSURL* appSupportDir = nil; - NSURL* appDirectory = nil; - - if ([possibleURLs count] >= 1) { - // Use the first directory (if multiple are returned) - appSupportDir = [possibleURLs objectAtIndex:0]; - } - - // If a valid app support directory exists, add the - // app's bundle ID to it to specify the final directory. - if (appSupportDir) { - NSString* appBundleID = [[NSBundle mainBundle] bundleIdentifier]; - appDirectory = [appSupportDir URLByAppendingPathComponent:appBundleID]; - appDirectory=[appDirectory URLByAppendingPathComponent:@"roms"]; - } - // create ~/Library/Application Support/... stuff - - NSError* theError = nil; - if (![sharedFM createDirectoryAtURL:appDirectory withIntermediateDirectories:YES - attributes:nil error:&theError]) - { - // Handle the error. - NSLog(@"Error creating user library rom path"); - } else NSLog(@"Create user rom path sucessfull"); - - strcpy(Path,[appDirectory fileSystemRepresentation]); - // return appDirectory; -} - - diff --git a/src/machine/CMakeLists.txt b/src/machine/CMakeLists.txt index a20c105fe..e88631044 100644 --- a/src/machine/CMakeLists.txt +++ b/src/machine/CMakeLists.txt @@ -1,22 +1,22 @@ # -# 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. +# 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. +# This file is part of the 86Box distribution. # -# CMake build script. +# CMake build script. # -# Authors: David HrdliÄka, +# Authors: David HrdliÄka, # -# Copyright 2020,2021 David HrdliÄka. +# Copyright 2020-2021 David HrdliÄka. # add_library(mch OBJECT machine.c machine_table.c m_xt.c m_xt_compaq.c m_xt_philips.c m_xt_t1000.c m_xt_t1000_vid.c m_xt_xi8088.c m_xt_zenith.c m_pcjr.c - m_amstrad.c m_europc.c m_xt_olivetti.c m_tandy.c m_v86p.c + m_amstrad.c m_europc.c m_elt.c m_xt_olivetti.c m_tandy.c m_v86p.c m_at.c m_at_commodore.c m_at_t3100e.c m_at_t3100e_vid.c m_ps1.c m_ps1_hdc.c m_ps2_isa.c m_ps2_mca.c m_at_compaq.c m_at_286_386sx.c m_at_386dx_486.c @@ -24,15 +24,19 @@ add_library(mch OBJECT machine.c machine_table.c m_xt.c m_xt_compaq.c m_at_sockets7.c m_at_socket8.c m_at_slot1.c m_at_slot2.c m_at_socket370.c m_at_misc.c) +if(AN430TX) + target_compile_definitions(mch PRIVATE USE_AN430TX) +endif() + +if(DESKPRO386) + target_compile_definitions(mch PRIVATE USE_DESKPRO386) +endif() + if(LASERXT) target_sources(mch PRIVATE m_xt_laserxt.c) target_compile_definitions(mch PRIVATE USE_LASERXT) endif() -if(NO_SIO) - target_compile_definitions(mch PRIVATE NO_SIO) -endif() - if(OPEN_AT) target_compile_definitions(mch PRIVATE USE_OPEN_AT) -endif() \ No newline at end of file +endif() diff --git a/src/machine/m_amstrad.c b/src/machine/m_amstrad.c index 704933d0f..4bc53c9b4 100644 --- a/src/machine/m_amstrad.c +++ b/src/machine/m_amstrad.c @@ -1,45 +1,45 @@ /* - * 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. + * 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. + * This file is part of the 86Box distribution. * - * Emulation of the Amstrad series of PC's: PC1512, PC1640 and - * PC200, including their keyboard, mouse and video devices, as - * well as the PC2086 and PC3086 systems. + * Emulation of the Amstrad series of PC's: PC1512, PC1640 and + * PC200, including their keyboard, mouse and video devices, as + * well as the PC2086 and PC3086 systems. * - * PC1512: The PC1512 extends CGA with a bit-planar 640x200x16 mode. - * Most CRTC registers are fixed. + * PC1512: The PC1512 extends CGA with a bit-planar 640x200x16 mode. + * Most CRTC registers are fixed. * - * The Technical Reference Manual lists the video waitstate - * time as between 12 and 46 cycles. We currently always use - * the lower number. + * The Technical Reference Manual lists the video waitstate + * time as between 12 and 46 cycles. We currently always use + * the lower number. * - * PC1640: Mostly standard EGA, but with CGA & Hercules emulation. + * PC1640: Mostly standard EGA, but with CGA & Hercules emulation. * - * PC200: CGA with some NMI stuff. But we don't need that as it's only - * used for TV and LCD displays, and we're emulating a CRT. + * PC200: CGA with some NMI stuff. But we don't need that as it's only + * used for TV and LCD displays, and we're emulating a CRT. * - * PPC512/640: Portable with both CGA-compatible and MDA-compatible monitors. + * PPC512/640: Portable with both CGA-compatible and MDA-compatible monitors. * - * TODO: This module is not complete yet: + * TODO: This module is not complete yet: * - * All models: The internal mouse controller does not work correctly with - * version 7.04 of the mouse driver. + * All models: The internal mouse controller does not work correctly with + * version 7.04 of the mouse driver. * * * - * Authors: Sarah Walker, - * Miran Grca, - * Fred N. van Kempen, - * John Elliott, + * Authors: Sarah Walker, + * Miran Grca, + * Fred N. van Kempen, + * John Elliott, * - * Copyright 2008-2019 Sarah Walker. - * Copyright 2016-2019 Miran Grca. - * Copyright 2017-2019 Fred N. van Kempen. - * Copyright 2019 John Elliott. + * Copyright 2008-2019 Sarah Walker. + * Copyright 2016-2019 Miran Grca. + * Copyright 2017-2019 Fred N. van Kempen. + * Copyright 2019 John Elliott. */ #include #include @@ -74,110 +74,108 @@ #include <86box/vid_mda.h> #include <86box/machine.h> #include <86box/m_amstrad.h> +#include <86box/plat_unused.h> +#define STAT_PARITY 0x80 +#define STAT_RTIMEOUT 0x40 +#define STAT_TTIMEOUT 0x20 +#define STAT_LOCK 0x10 +#define STAT_CD 0x08 +#define STAT_SYSFLAG 0x04 +#define STAT_IFULL 0x02 +#define STAT_OFULL 0x01 -#define STAT_PARITY 0x80 -#define STAT_RTIMEOUT 0x40 -#define STAT_TTIMEOUT 0x20 -#define STAT_LOCK 0x10 -#define STAT_CD 0x08 -#define STAT_SYSFLAG 0x04 -#define STAT_IFULL 0x02 -#define STAT_OFULL 0x01 - - -typedef struct { - rom_t bios_rom; /* 1640 */ - cga_t cga; /* 1640/200 */ - mda_t mda; /* 1512/200/PPC512/640*/ - ega_t ega; /* 1640 */ - uint8_t emulation; /* Which display are we emulating? */ - uint8_t dipswitches; /* DIP switches 1-3 */ - uint8_t crtc_index; /* CRTC index readback - * Bit 7: CGA control port written - * Bit 6: Operation control port written - * Bit 5: CRTC register written - * Bits 0-4: Last CRTC register selected */ - uint8_t operation_ctrl; - uint8_t reg_3df, type; - uint8_t crtc[32]; - int crtcreg; - int cga_enabled; /* 1640 */ - uint8_t cgacol, - cgamode, - stat; - uint8_t plane_write, /* 1512/200 */ - plane_read, /* 1512/200 */ - border, /* 1512/200 */ - invert; /* 512/640 */ - int fontbase; /* 1512/200 */ - int linepos, - displine; - int sc, vc; - int cgadispon; - int con, coff, - cursoron, - cgablink; - int vsynctime; - int vadj; - uint16_t ma, maback; - int dispon; - int blink; - uint64_t dispontime, /* 1512/1640 */ - dispofftime; /* 1512/1640 */ - pc_timer_t timer; /* 1512/1640 */ - int firstline, - lastline; - uint8_t *vram; - void *ams; +typedef struct amsvid_t { + rom_t bios_rom; /* 1640 */ + cga_t cga; /* 1640/200 */ + mda_t mda; /* 1512/200/PPC512/640*/ + ega_t ega; /* 1640 */ + uint8_t emulation; /* Which display are we emulating? */ + uint8_t dipswitches; /* DIP switches 1-3 */ + uint8_t crtc_index; /* CRTC index readback + * Bit 7: CGA control port written + * Bit 6: Operation control port written + * Bit 5: CRTC register written + * Bits 0-4: Last CRTC register selected */ + uint8_t operation_ctrl; + uint8_t reg_3df; + uint8_t type; + uint8_t crtc[32]; + int crtcreg; + int cga_enabled; /* 1640 */ + uint8_t cgacol; + uint8_t cgamode; + uint8_t stat; + uint8_t plane_write; /* 1512/200 */ + uint8_t plane_read; /* 1512/200 */ + uint8_t border; /* 1512/200 */ + uint8_t invert; /* 512/640 */ + int fontbase; /* 1512/200 */ + int linepos; + int displine; + int sc; + int vc; + int cgadispon; + int con; + int coff; + int cursoron; + int cgablink; + int vsynctime; + int fullchange; + int vadj; + uint16_t ma; + uint16_t maback; + int dispon; + int blink; + uint64_t dispontime; /* 1512/1640 */ + uint64_t dispofftime; /* 1512/1640 */ + pc_timer_t timer; /* 1512/1640 */ + int firstline; + int lastline; + uint8_t *vram; + void *ams; } amsvid_t; -typedef struct { +typedef struct amstrad_t { /* Machine stuff. */ - uint8_t dead; - uint8_t stat1, - stat2; - uint8_t type, - language; + uint8_t dead; + uint8_t stat1; + uint8_t stat2; + uint8_t type; + uint8_t language; /* Keyboard stuff. */ - int8_t wantirq; - uint8_t key_waiting; - uint8_t pa; - uint8_t pb; - pc_timer_t send_delay_timer; + int8_t wantirq; + uint8_t key_waiting; + uint8_t pa; + uint8_t pb; + pc_timer_t send_delay_timer; /* Mouse stuff. */ - uint8_t mousex, - mousey; - int oldb; + int oldb; /* Video stuff. */ - amsvid_t *vid; - fdc_t *fdc; + amsvid_t *vid; + fdc_t *fdc; } amstrad_t; +uint32_t amstrad_latch; -int amstrad_latch; - - -static uint8_t key_queue[16]; -static int key_queue_start = 0, - key_queue_end = 0; -static uint8_t crtc_mask[32] = { +static uint8_t key_queue[16]; +static int key_queue_start = 0; +static int key_queue_end = 0; +static uint8_t crtc_mask[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 video_timings_t timing_pc1512 = {VIDEO_BUS, 0,0,0, 0,0,0}; /*PC1512 video code handles waitstates itself*/ -static video_timings_t timing_pc1640 = {VIDEO_ISA, 8,16,32, 8,16,32}; -static video_timings_t timing_pc200 = {VIDEO_ISA, 8,16,32, 8,16,32}; +static video_timings_t timing_pc1512 = { VIDEO_BUS, 0, 0, 0, 0, 0, 0 }; /*PC1512 video code handles waitstates itself*/ +static video_timings_t timing_pc1640 = { VIDEO_ISA, 8, 16, 32, 8, 16, 32 }; +static video_timings_t timing_pc200 = { VIDEO_ISA, 8, 16, 32, 8, 16, 32 }; - -enum -{ +enum { AMS_PC1512, AMS_PC1640, AMS_PC200, @@ -186,458 +184,456 @@ enum AMS_PC3086 }; - #ifdef ENABLE_AMSTRAD_LOG int amstrad_do_log = ENABLE_AMSTRAD_LOG; - static void amstrad_log(const char *fmt, ...) { - va_list ap; + va_list ap; - if (amstrad_do_log) - { - va_start(ap, fmt); - pclog_ex(fmt, ap); - va_end(ap); - } + if (amstrad_do_log) { + va_start(ap, fmt); + pclog_ex(fmt, ap); + va_end(ap); + } } #else -#define amstrad_log(fmt, ...) +# define amstrad_log(fmt, ...) #endif - static void recalc_timings_1512(amsvid_t *vid) { - double _dispontime, _dispofftime, disptime; + double _dispontime; + double _dispofftime; + double disptime; - disptime = /*128*/ 114; /*Fixed on PC1512*/ - _dispontime = 80; + disptime = /*128*/ 114; /*Fixed on PC1512*/ + _dispontime = 80; _dispofftime = disptime - _dispontime; - _dispontime *= CGACONST; + _dispontime *= CGACONST; _dispofftime *= CGACONST; - vid->dispontime = (uint64_t)_dispontime; - vid->dispofftime = (uint64_t)_dispofftime; + vid->dispontime = (uint64_t) _dispontime; + vid->dispofftime = (uint64_t) _dispofftime; } - static void vid_out_1512(uint16_t addr, uint8_t val, void *priv) { - amsvid_t *vid = (amsvid_t *)priv; - uint8_t old; + amsvid_t *vid = (amsvid_t *) priv; + uint8_t old; if ((addr >= 0x3d0) && (addr <= 0x3d7)) - addr = (addr & 0xff9) | 0x004; + addr = (addr & 0xff9) | 0x004; switch (addr) { - case 0x03d4: - vid->crtcreg = val & 31; - return; + case 0x03d4: + vid->crtcreg = val & 31; + return; - case 0x03d5: - old = vid->crtc[vid->crtcreg]; - vid->crtc[vid->crtcreg] = val & crtc_mask[vid->crtcreg]; - if (old != val) { - if (vid->crtcreg < 0xe || vid->crtcreg > 0x10) { - fullchange = changeframecount; - recalc_timings_1512(vid); - } - } - return; + case 0x03d5: + old = vid->crtc[vid->crtcreg]; + vid->crtc[vid->crtcreg] = val & crtc_mask[vid->crtcreg]; + if (old != val) { + if (vid->crtcreg < 0xe || vid->crtcreg > 0x10) { + vid->fullchange = changeframecount; + recalc_timings_1512(vid); + } + } + return; - case 0x03d8: - if ((val & 0x12) == 0x12 && (vid->cgamode & 0x12) != 0x12) { - vid->plane_write = 0xf; - vid->plane_read = 0; - } - vid->cgamode = val; - return; + case 0x03d8: + if ((val & 0x12) == 0x12 && (vid->cgamode & 0x12) != 0x12) { + vid->plane_write = 0xf; + vid->plane_read = 0; + } + vid->cgamode = val; + return; - case 0x03d9: - vid->cgacol = val; - return; + case 0x03d9: + vid->cgacol = val; + return; - case 0x03dd: - vid->plane_write = val; - return; + case 0x03dd: + vid->plane_write = val; + return; - case 0x03de: - vid->plane_read = val & 3; - return; + case 0x03de: + vid->plane_read = val & 3; + return; - case 0x03df: - vid->border = val; - return; + case 0x03df: + vid->border = val; + return; + + default: + return; } } - static uint8_t vid_in_1512(uint16_t addr, void *priv) { - amsvid_t *vid = (amsvid_t *)priv; - uint8_t ret = 0xff; + const amsvid_t *vid = (amsvid_t *) priv; + uint8_t ret = 0xff; if ((addr >= 0x3d0) && (addr <= 0x3d7)) - addr = (addr & 0xff9) | 0x004; + addr = (addr & 0xff9) | 0x004; switch (addr) { - case 0x03d4: - ret = vid->crtcreg; - break; + case 0x03d4: + ret = vid->crtcreg; + break; - case 0x03d5: - ret = vid->crtc[vid->crtcreg]; - break; + case 0x03d5: + ret = vid->crtc[vid->crtcreg]; + break; - case 0x03da: - ret = vid->stat; - break; + case 0x03da: + ret = vid->stat; + break; + + default: + break; } - return(ret); + return ret; } - static void vid_write_1512(uint32_t addr, uint8_t val, void *priv) { - amsvid_t *vid = (amsvid_t *)priv; + amsvid_t *vid = (amsvid_t *) priv; cycles -= 12; addr &= 0x3fff; if ((vid->cgamode & 0x12) == 0x12) { - if (vid->plane_write & 1) vid->vram[addr] = val; - if (vid->plane_write & 2) vid->vram[addr | 0x4000] = val; - if (vid->plane_write & 4) vid->vram[addr | 0x8000] = val; - if (vid->plane_write & 8) vid->vram[addr | 0xc000] = val; + if (vid->plane_write & 1) + vid->vram[addr] = val; + if (vid->plane_write & 2) + vid->vram[addr | 0x4000] = val; + if (vid->plane_write & 4) + vid->vram[addr | 0x8000] = val; + if (vid->plane_write & 8) + vid->vram[addr | 0xc000] = val; } else - vid->vram[addr] = val; + vid->vram[addr] = val; } - static uint8_t vid_read_1512(uint32_t addr, void *priv) { - amsvid_t *vid = (amsvid_t *)priv; + const amsvid_t *vid = (amsvid_t *) priv; cycles -= 12; addr &= 0x3fff; if ((vid->cgamode & 0x12) == 0x12) - return(vid->vram[addr | (vid->plane_read << 14)]); + return (vid->vram[addr | (vid->plane_read << 14)]); - return(vid->vram[addr]); + return (vid->vram[addr]); } - static void vid_poll_1512(void *priv) { - amsvid_t *vid = (amsvid_t *)priv; - uint16_t ca = (vid->crtc[15] | (vid->crtc[14] << 8)) & 0x3fff; - int drawcursor; - int x, c, xs_temp, ys_temp; - uint8_t chr, attr; - uint16_t dat, dat2, dat3, dat4; - int cols[4]; - int col; - int oldsc; + amsvid_t *vid = (amsvid_t *) priv; + uint16_t ca = (vid->crtc[15] | (vid->crtc[14] << 8)) & 0x3fff; + int drawcursor; + int x; + int c; + int xs_temp; + int ys_temp; + uint8_t chr; + uint8_t attr; + uint16_t dat; + uint16_t dat2; + uint16_t dat3; + uint16_t dat4; + int cols[4]; + int col; + int oldsc; - if (! vid->linepos) { - timer_advance_u64(&vid->timer, vid->dispofftime); - vid->stat |= 1; - vid->linepos = 1; - oldsc = vid->sc; - if (vid->dispon) { - if (vid->displine < vid->firstline) { - vid->firstline = vid->displine; - video_wait_for_buffer(); - } - vid->lastline = vid->displine; - for (c = 0; c < 8; c++) { - if ((vid->cgamode & 0x12) == 0x12) { - buffer32->line[(vid->displine << 1)][c] = buffer32->line[(vid->displine << 1) + 1][c] = (vid->border & 15) + 16; - if (vid->cgamode & 1) { - buffer32->line[(vid->displine << 1)][c + (vid->crtc[1] << 3) + 8] = - buffer32->line[(vid->displine << 1) + 1][c + (vid->crtc[1] << 3) + 8] = 0; - } else { - buffer32->line[(vid->displine << 1)][c + (vid->crtc[1] << 4) + 8] = - buffer32->line[(vid->displine << 1)+ 1][c + (vid->crtc[1] << 4) + 8] = 0; - } - } else { - buffer32->line[(vid->displine << 1)][c] = buffer32->line[(vid->displine << 1) + 1][c] = (vid->cgacol & 15) + 16; - if (vid->cgamode & 1) { - buffer32->line[(vid->displine << 1)][c + (vid->crtc[1] << 3) + 8] = - buffer32->line[(vid->displine << 1) + 1][c + (vid->crtc[1] << 3) + 8] = (vid->cgacol & 15) + 16; - } else { - buffer32->line[(vid->displine << 1)][c + (vid->crtc[1] << 4) + 8] = - buffer32->line[(vid->displine << 1) + 1][c + (vid->crtc[1] << 4) + 8] = (vid->cgacol & 15) + 16; - } - } - } - if (vid->cgamode & 1) { - for (x = 0; x < 80; x++) { - chr = vid->vram[ ((vid->ma << 1) & 0x3fff)]; - attr = vid->vram[(((vid->ma << 1) + 1) & 0x3fff)]; - drawcursor = ((vid->ma == ca) && vid->con && vid->cursoron); - if (vid->cgamode & 0x20) { - cols[1] = (attr & 15) + 16; - cols[0] = ((attr >> 4) & 7) + 16; - if ((vid->blink & 16) && (attr & 0x80) && !drawcursor) - cols[1] = cols[0]; - } else { - cols[1] = (attr & 15) + 16; - cols[0] = (attr >> 4) + 16; - } - if (drawcursor) { - for (c = 0; c < 8; c++) { - buffer32->line[(vid->displine << 1)][(x << 3) + c + 8] = - buffer32->line[(vid->displine << 1) + 1][(x << 3) + c + 8] = - cols[(fontdat[vid->fontbase + chr][vid->sc & 7] & (1 << (c ^ 7))) ? 1 : 0] ^ 15; - } - } else { - for (c = 0; c < 8; c++) { - buffer32->line[(vid->displine << 1)][(x << 3) + c + 8] = - buffer32->line[(vid->displine << 1) + 1][(x << 3) + c + 8] = - cols[(fontdat[vid->fontbase + chr][vid->sc & 7] & (1 << (c ^ 7))) ? 1 : 0]; - } - } - vid->ma++; - } - } else if (! (vid->cgamode & 2)) { - for (x = 0; x < 40; x++) { - chr = vid->vram[((vid->ma << 1) & 0x3fff)]; - attr = vid->vram[(((vid->ma << 1) + 1) & 0x3fff)]; - drawcursor = ((vid->ma == ca) && vid->con && vid->cursoron); - if (vid->cgamode & 0x20) { - cols[1] = (attr & 15) + 16; - cols[0] = ((attr >> 4) & 7) + 16; - if ((vid->blink & 16) && (attr & 0x80)) - cols[1] = cols[0]; - } else { - cols[1] = (attr & 15) + 16; - cols[0] = (attr >> 4) + 16; - } - vid->ma++; - if (drawcursor) { - for (c = 0; c < 8; c++) { - buffer32->line[(vid->displine << 1)][(x << 4) + (c << 1) + 8] = - buffer32->line[(vid->displine << 1)][(x << 4) + (c << 1) + 1 + 8] = - buffer32->line[(vid->displine << 1) + 1][(x << 4) + (c << 1) + 8] = - buffer32->line[(vid->displine << 1) + 1][(x << 4) + (c << 1) + 1 + 8] = - cols[(fontdat[vid->fontbase + chr][vid->sc & 7] & (1 << (c ^ 7))) ? 1 : 0] ^ 15; - } - } else { - for (c = 0; c < 8; c++) { - buffer32->line[(vid->displine << 1)][(x << 4) + (c << 1) + 8] = - buffer32->line[(vid->displine << 1)][(x << 4) + (c << 1) + 1 + 8] = - buffer32->line[(vid->displine << 1) + 1][(x << 4) + (c << 1) + 8] = - buffer32->line[(vid->displine << 1) + 1][(x << 4) + (c << 1) + 1 + 8] = - cols[(fontdat[vid->fontbase + chr][vid->sc & 7] & (1 << (c ^ 7))) ? 1 : 0]; - } - } - } - } else if (! (vid->cgamode & 16)) { - cols[0] = (vid->cgacol & 15) | 16; - col = (vid->cgacol & 16) ? 24 : 16; - if (vid->cgamode & 4) { - cols[1] = col | 3; - cols[2] = col | 4; - cols[3] = col | 7; - } else if (vid->cgacol & 32) { - cols[1] = col | 3; - cols[2] = col | 5; - cols[3] = col | 7; - } else { - cols[1] = col | 2; - cols[2] = col | 4; - cols[3] = col | 6; - } - for (x = 0; x < 40; x++) { - dat = (vid->vram[((vid->ma << 1) & 0x1fff) + ((vid->sc & 1) * 0x2000)] << 8) | vid->vram[((vid->ma << 1) & 0x1fff) + ((vid->sc & 1) * 0x2000) + 1]; - vid->ma++; - for (c = 0; c < 8; c++) { - buffer32->line[(vid->displine << 1)][(x << 4) + (c << 1) + 8] = - buffer32->line[(vid->displine << 1)][(x << 4) + (c << 1) + 1 + 8] = - buffer32->line[(vid->displine << 1) + 1][(x << 4) + (c << 1) + 8] = - buffer32->line[(vid->displine << 1) + 1][(x << 4) + (c << 1) + 1 + 8] = - cols[dat >> 14]; - dat <<= 2; - } - } - } else { - for (x = 0; x < 40; x++) { - ca = ((vid->ma << 1) & 0x1fff) + ((vid->sc & 1) * 0x2000); - dat = (vid->vram[ca] << 8) | vid->vram[ca + 1]; - dat2 = (vid->vram[ca + 0x4000] << 8) | vid->vram[ca + 0x4001]; - dat3 = (vid->vram[ca + 0x8000] << 8) | vid->vram[ca + 0x8001]; - dat4 = (vid->vram[ca + 0xc000] << 8) | vid->vram[ca + 0xc001]; + if (!vid->linepos) { + timer_advance_u64(&vid->timer, vid->dispofftime); + vid->stat |= 1; + vid->linepos = 1; + oldsc = vid->sc; + if (vid->dispon) { + if (vid->displine < vid->firstline) { + vid->firstline = vid->displine; + video_wait_for_buffer(); + } + vid->lastline = vid->displine; + for (c = 0; c < 8; c++) { + if ((vid->cgamode & 0x12) == 0x12) { + buffer32->line[vid->displine << 1][c] = buffer32->line[(vid->displine << 1) + 1][c] = (vid->border & 15) + 16; + if (vid->cgamode & 1) { + buffer32->line[vid->displine << 1][c + (vid->crtc[1] << 3) + 8] = buffer32->line[(vid->displine << 1) + 1][c + (vid->crtc[1] << 3) + 8] = 0; + } else { + buffer32->line[vid->displine << 1][c + (vid->crtc[1] << 4) + 8] = buffer32->line[(vid->displine << 1) + 1][c + (vid->crtc[1] << 4) + 8] = 0; + } + } else { + buffer32->line[vid->displine << 1][c] = buffer32->line[(vid->displine << 1) + 1][c] = (vid->cgacol & 15) + 16; + if (vid->cgamode & 1) { + buffer32->line[vid->displine << 1][c + (vid->crtc[1] << 3) + 8] = buffer32->line[(vid->displine << 1) + 1][c + (vid->crtc[1] << 3) + 8] = (vid->cgacol & 15) + 16; + } else { + buffer32->line[vid->displine << 1][c + (vid->crtc[1] << 4) + 8] = buffer32->line[(vid->displine << 1) + 1][c + (vid->crtc[1] << 4) + 8] = (vid->cgacol & 15) + 16; + } + } + } + if (vid->cgamode & 1) { + for (x = 0; x < 80; x++) { + chr = vid->vram[(vid->ma << 1) & 0x3fff]; + attr = vid->vram[((vid->ma << 1) + 1) & 0x3fff]; + drawcursor = ((vid->ma == ca) && vid->con && vid->cursoron); + if (vid->cgamode & 0x20) { + cols[1] = (attr & 15) + 16; + cols[0] = ((attr >> 4) & 7) + 16; + if ((vid->blink & 16) && (attr & 0x80) && !drawcursor) + cols[1] = cols[0]; + } else { + cols[1] = (attr & 15) + 16; + cols[0] = (attr >> 4) + 16; + } + if (drawcursor) { + for (c = 0; c < 8; c++) { + buffer32->line[vid->displine << 1][(x << 3) + c + 8] = buffer32->line[(vid->displine << 1) + 1][(x << 3) + c + 8] = cols[(fontdat[vid->fontbase + chr][vid->sc & 7] & (1 << (c ^ 7))) ? 1 : 0] ^ 15; + } + } else { + for (c = 0; c < 8; c++) { + buffer32->line[vid->displine << 1][(x << 3) + c + 8] = buffer32->line[(vid->displine << 1) + 1][(x << 3) + c + 8] = cols[(fontdat[vid->fontbase + chr][vid->sc & 7] & (1 << (c ^ 7))) ? 1 : 0]; + } + } + vid->ma++; + } + } else if (!(vid->cgamode & 2)) { + for (x = 0; x < 40; x++) { + chr = vid->vram[(vid->ma << 1) & 0x3fff]; + attr = vid->vram[((vid->ma << 1) + 1) & 0x3fff]; + drawcursor = ((vid->ma == ca) && vid->con && vid->cursoron); + if (vid->cgamode & 0x20) { + cols[1] = (attr & 15) + 16; + cols[0] = ((attr >> 4) & 7) + 16; + if ((vid->blink & 16) && (attr & 0x80)) + cols[1] = cols[0]; + } else { + cols[1] = (attr & 15) + 16; + cols[0] = (attr >> 4) + 16; + } + vid->ma++; + if (drawcursor) { + for (c = 0; c < 8; c++) { + buffer32->line[vid->displine << 1][(x << 4) + (c << 1) + 8] = buffer32->line[vid->displine << 1][(x << 4) + (c << 1) + 1 + 8] = buffer32->line[(vid->displine << 1) + 1][(x << 4) + (c << 1) + 8] = buffer32->line[(vid->displine << 1) + 1][(x << 4) + (c << 1) + 1 + 8] = cols[(fontdat[vid->fontbase + chr][vid->sc & 7] & (1 << (c ^ 7))) ? 1 : 0] ^ 15; + } + } else { + for (c = 0; c < 8; c++) { + buffer32->line[vid->displine << 1][(x << 4) + (c << 1) + 8] = buffer32->line[vid->displine << 1][(x << 4) + (c << 1) + 1 + 8] = buffer32->line[(vid->displine << 1) + 1][(x << 4) + (c << 1) + 8] = buffer32->line[(vid->displine << 1) + 1][(x << 4) + (c << 1) + 1 + 8] = cols[(fontdat[vid->fontbase + chr][vid->sc & 7] & (1 << (c ^ 7))) ? 1 : 0]; + } + } + } + } else if (!(vid->cgamode & 16)) { + cols[0] = (vid->cgacol & 15) | 16; + col = (vid->cgacol & 16) ? 24 : 16; + if (vid->cgamode & 4) { + cols[1] = col | 3; + cols[2] = col | 4; + cols[3] = col | 7; + } else if (vid->cgacol & 32) { + cols[1] = col | 3; + cols[2] = col | 5; + cols[3] = col | 7; + } else { + cols[1] = col | 2; + cols[2] = col | 4; + cols[3] = col | 6; + } + for (x = 0; x < 40; x++) { + dat = (vid->vram[((vid->ma << 1) & 0x1fff) + ((vid->sc & 1) * 0x2000)] << 8) | vid->vram[((vid->ma << 1) & 0x1fff) + ((vid->sc & 1) * 0x2000) + 1]; + vid->ma++; + for (c = 0; c < 8; c++) { + buffer32->line[vid->displine << 1][(x << 4) + (c << 1) + 8] = buffer32->line[vid->displine << 1][(x << 4) + (c << 1) + 1 + 8] = buffer32->line[(vid->displine << 1) + 1][(x << 4) + (c << 1) + 8] = buffer32->line[(vid->displine << 1) + 1][(x << 4) + (c << 1) + 1 + 8] = cols[dat >> 14]; + dat <<= 2; + } + } + } else { + for (x = 0; x < 40; x++) { + ca = ((vid->ma << 1) & 0x1fff) + ((vid->sc & 1) * 0x2000); + dat = (vid->vram[ca] << 8) | vid->vram[ca + 1]; + dat2 = (vid->vram[ca + 0x4000] << 8) | vid->vram[ca + 0x4001]; + dat3 = (vid->vram[ca + 0x8000] << 8) | vid->vram[ca + 0x8001]; + dat4 = (vid->vram[ca + 0xc000] << 8) | vid->vram[ca + 0xc001]; - vid->ma++; - for (c = 0; c < 16; c++) { - buffer32->line[(vid->displine << 1)][(x << 4) + c + 8] = buffer32->line[(vid->displine << 1) + 1][(x << 4) + c + 8] = - (((dat >> 15) | ((dat2 >> 15) << 1) | ((dat3 >> 15) << 2) | ((dat4 >> 15) << 3)) & (vid->cgacol & 15)) + 16; - dat <<= 1; - dat2 <<= 1; - dat3 <<= 1; - dat4 <<= 1; - } - } - } - } else { - cols[0] = ((vid->cgamode & 0x12) == 0x12) ? 0 : (vid->cgacol & 15) + 16; - if (vid->cgamode & 1) { - hline(buffer32, 0, (vid->displine << 1), (vid->crtc[1] << 3) + 16, cols[0]); - hline(buffer32, 0, (vid->displine << 1) + 1, (vid->crtc[1] << 3) + 16, cols[0]); - } else { - hline(buffer32, 0, (vid->displine << 1), (vid->crtc[1] << 4) + 16, cols[0]); - hline(buffer32, 0, (vid->displine << 1), (vid->crtc[1] << 4) + 16, cols[0]); - } - } + vid->ma++; + for (c = 0; c < 16; c++) { + buffer32->line[vid->displine << 1][(x << 4) + c + 8] = buffer32->line[(vid->displine << 1) + 1][(x << 4) + c + 8] = (((dat >> 15) | ((dat2 >> 15) << 1) | ((dat3 >> 15) << 2) | ((dat4 >> 15) << 3)) & (vid->cgacol & 15)) + 16; + dat <<= 1; + dat2 <<= 1; + dat3 <<= 1; + dat4 <<= 1; + } + } + } + } else { + cols[0] = ((vid->cgamode & 0x12) == 0x12) ? 0 : (vid->cgacol & 15) + 16; + if (vid->cgamode & 1) { + hline(buffer32, 0, (vid->displine << 1), (vid->crtc[1] << 3) + 16, cols[0]); + hline(buffer32, 0, (vid->displine << 1) + 1, (vid->crtc[1] << 3) + 16, cols[0]); + } else { + hline(buffer32, 0, (vid->displine << 1), (vid->crtc[1] << 4) + 16, cols[0]); + hline(buffer32, 0, (vid->displine << 1), (vid->crtc[1] << 4) + 16, cols[0]); + } + } - vid->sc = oldsc; - if (vid->vsynctime) - vid->stat |= 8; - vid->displine++; - if (vid->displine >= 360) - vid->displine = 0; + if (vid->cgamode & 1) + x = (vid->crtc[1] << 3) + 16; + else + x = (vid->crtc[1] << 4) + 16; + + video_process_8(x, vid->displine << 1); + video_process_8(x, (vid->displine << 1) + 1); + + vid->sc = oldsc; + if (vid->vsynctime) + vid->stat |= 8; + vid->displine++; + if (vid->displine >= 360) + vid->displine = 0; } else { - timer_advance_u64(&vid->timer, vid->dispontime); - if ((vid->lastline - vid->firstline) == 199) - vid->dispon = 0; /*Amstrad PC1512 always displays 200 lines, regardless of CRTC settings*/ - if (vid->dispon) - vid->stat &= ~1; - vid->linepos = 0; - if (vid->vsynctime) { - vid->vsynctime--; - if (! vid->vsynctime) - vid->stat &= ~8; - } - if (vid->sc == (vid->crtc[11] & 31)) { - vid->con = 0; - vid->coff = 1; - } - if (vid->vadj) { - vid->sc++; - vid->sc &= 31; - vid->ma = vid->maback; - vid->vadj--; - if (! vid->vadj) { - vid->dispon = 1; - vid->ma = vid->maback = (vid->crtc[13] | (vid->crtc[12] << 8)) & 0x3fff; - vid->sc = 0; - } - } else if (vid->sc == vid->crtc[9]) { - vid->maback = vid->ma; - vid->sc = 0; - vid->vc++; - vid->vc &= 127; + timer_advance_u64(&vid->timer, vid->dispontime); + if ((vid->lastline - vid->firstline) == 199) + vid->dispon = 0; /*Amstrad PC1512 always displays 200 lines, regardless of CRTC settings*/ + if (vid->dispon) + vid->stat &= ~1; + vid->linepos = 0; + if (vid->vsynctime) { + vid->vsynctime--; + if (!vid->vsynctime) + vid->stat &= ~8; + } + if (vid->sc == (vid->crtc[11] & 31)) { + vid->con = 0; + vid->coff = 1; + } + if (vid->vadj) { + vid->sc++; + vid->sc &= 31; + vid->ma = vid->maback; + vid->vadj--; + if (!vid->vadj) { + vid->dispon = 1; + vid->ma = vid->maback = (vid->crtc[13] | (vid->crtc[12] << 8)) & 0x3fff; + vid->sc = 0; + } + } else if (vid->sc == vid->crtc[9]) { + vid->maback = vid->ma; + vid->sc = 0; + vid->vc++; + vid->vc &= 127; - if (vid->displine == 32) { - vid->vc = 0; - vid->vadj = 6; - if ((vid->crtc[10] & 0x60) == 0x20) - vid->cursoron = 0; - else - vid->cursoron = vid->blink & 16; - } + if (vid->displine == 32) { + vid->vc = 0; + vid->vadj = 6; + if ((vid->crtc[10] & 0x60) == 0x20) + vid->cursoron = 0; + else + vid->cursoron = vid->blink & 16; + } - if (vid->displine >= 262) { - vid->dispon = 0; - vid->displine = 0; - vid->vsynctime = 46; + if (vid->displine >= 262) { + vid->dispon = 0; + vid->displine = 0; + vid->vsynctime = 46; - if (vid->cgamode&1) - x = (vid->crtc[1] << 3) + 16; - else - x = (vid->crtc[1] << 4) + 16; - vid->lastline++; + if (vid->cgamode & 1) + x = (vid->crtc[1] << 3) + 16; + else + x = (vid->crtc[1] << 4) + 16; + vid->lastline++; - xs_temp = x; - ys_temp = (vid->lastline - vid->firstline) << 1; + xs_temp = x; + ys_temp = (vid->lastline - vid->firstline) << 1; - if ((xs_temp > 0) && (ys_temp > 0)) { - if (xs_temp < 64) xs_temp = 656; - if (ys_temp < 32) ys_temp = 400; - if (!enable_overscan) - xs_temp -= 16; + if ((xs_temp > 0) && (ys_temp > 0)) { + if (xs_temp < 64) + xs_temp = 656; + if (ys_temp < 32) + ys_temp = 400; + if (!enable_overscan) + xs_temp -= 16; - if ((xs_temp != xsize) || (ys_temp != ysize) || video_force_resize_get()) { - xsize = xs_temp; - ysize = ys_temp; - set_screen_size(xsize, ysize + (enable_overscan ? 16 : 0)); + if ((xs_temp != xsize) || (ys_temp != ysize) || video_force_resize_get()) { + xsize = xs_temp; + ysize = ys_temp; + set_screen_size(xsize, ysize + (enable_overscan ? 16 : 0)); - if (video_force_resize_get()) - video_force_resize_set(0); - } + if (video_force_resize_get()) + video_force_resize_set(0); + } - if (enable_overscan) { - video_blit_memtoscreen_8(0, (vid->firstline - 4) << 1, - xsize, ((vid->lastline - vid->firstline) + 8) << 1); - } else { - video_blit_memtoscreen_8(8, vid->firstline << 1, - xsize, (vid->lastline - vid->firstline) << 1); - } - } + if (enable_overscan) { + video_blit_memtoscreen(0, (vid->firstline - 4) << 1, + xsize, ((vid->lastline - vid->firstline) + 8) << 1); + } else { + video_blit_memtoscreen(8, vid->firstline << 1, + xsize, (vid->lastline - vid->firstline) << 1); + } + } - video_res_x = xsize; - video_res_y = ysize; - if (vid->cgamode & 1) { - video_res_x /= 8; - video_res_y /= vid->crtc[9] + 1; - video_bpp = 0; - } else if (! (vid->cgamode & 2)) { - video_res_x /= 16; - video_res_y /= vid->crtc[9] + 1; - video_bpp = 0; - } else if (! (vid->cgamode & 16)) { - video_res_x /= 2; - video_bpp = 2; - } else { - video_bpp = 4; - } + video_res_x = xsize; + video_res_y = ysize; + if (vid->cgamode & 1) { + video_res_x /= 8; + video_res_y /= vid->crtc[9] + 1; + video_bpp = 0; + } else if (!(vid->cgamode & 2)) { + video_res_x /= 16; + video_res_y /= vid->crtc[9] + 1; + video_bpp = 0; + } else if (!(vid->cgamode & 16)) { + video_res_x /= 2; + video_bpp = 2; + } else { + video_bpp = 4; + } - vid->firstline = 1000; - vid->lastline = 0; - vid->blink++; - } - } else { - vid->sc++; - vid->sc &= 31; - vid->ma = vid->maback; - } - if (vid->sc == (vid->crtc[10] & 31)) - vid->con = 1; + vid->firstline = 1000; + vid->lastline = 0; + vid->blink++; + } + } else { + vid->sc++; + vid->sc &= 31; + vid->ma = vid->maback; + } + if (vid->sc == (vid->crtc[10] & 31)) + vid->con = 1; } } - static void vid_init_1512(amstrad_t *ams) { amsvid_t *vid; /* Allocate a video controller block. */ - vid = (amsvid_t *)malloc(sizeof(amsvid_t)); + vid = (amsvid_t *) malloc(sizeof(amsvid_t)); memset(vid, 0x00, sizeof(amsvid_t)); video_inform(VIDEO_FLAG_TYPE_CGA, &timing_pc1512); - vid->vram = malloc(0x10000); - vid->cgacol = 7; + vid->vram = malloc(0x10000); + vid->cgacol = 7; vid->cgamode = 0x12; timer_add(&vid->timer, vid_poll_1512, vid, 1); mem_mapping_add(&vid->cga.mapping, 0xb8000, 0x08000, - vid_read_1512, NULL, NULL, vid_write_1512, NULL, NULL, - NULL, 0, vid); + vid_read_1512, NULL, NULL, vid_write_1512, NULL, NULL, + NULL, 0, vid); io_sethandler(0x03d0, 16, - vid_in_1512, NULL, NULL, vid_out_1512, NULL, NULL, vid); + vid_in_1512, NULL, NULL, vid_out_1512, NULL, NULL, vid); overscan_x = overscan_y = 16; @@ -649,117 +645,93 @@ vid_init_1512(amstrad_t *ams) ams->vid = vid; } - static void vid_close_1512(void *priv) { - amsvid_t *vid = (amsvid_t *)priv; + amsvid_t *vid = (amsvid_t *) priv; free(vid->vram); free(vid); } - static void vid_speed_change_1512(void *priv) { - amsvid_t *vid = (amsvid_t *)priv; + amsvid_t *vid = (amsvid_t *) priv; recalc_timings_1512(vid); } - -device_config_t vid_1512_config[] = -{ - { - "display_type", "Display type", CONFIG_SELECTION, "", 0, "", { 0 }, - { - { - "PC-CM (Colour)", 0 - }, - { - "PC-MM (Monochrome)", 3 - }, - { - "" - } - } - }, - { - "codepage", "Hardware font", CONFIG_SELECTION, "", 3, "", { 0 }, - { - { - "US English", 3 - }, - { - "Danish", 1 - }, - { - "Greek", 0 - }, - { - "" - } - } - }, - { - "language", "BIOS language", CONFIG_SELECTION, "", 7, "", { 0 }, - { - { - "English", 7 - }, - { - "German", 6 - }, - { - "French", 5 - }, - { - "Spanish", 4 - }, - { - "Danish", 3 - }, - { - "Swedish", 2 - }, - { - "Italian", 1 - }, - { - "Diagnostic mode", 0 - }, - { - "" - } - } - }, - { - "", "", -1 - } +const device_config_t vid_1512_config[] = { + // clang-format off + { + .name = "display_type", + .description = "Display type", + .type = CONFIG_SELECTION, + .default_string = "", + .default_int = 0, + .file_filter = "", + .spinner = { 0 }, + .selection = { + { .description = "PC-CM (Colour)", .value = 0 }, + { .description = "PC-MM (Monochrome)", .value = 3 }, + { .description = "" } + } + }, + { + .name = "codepage", + .description = "Hardware font", + .type = CONFIG_SELECTION, + .default_string = "", + .default_int = 3, + .file_filter = "", + .spinner = { 0 }, + .selection = { + { .description = "US English", .value = 3 }, + { .description = "Danish", .value = 1 }, + { .description = "Greek", .value = 0 }, + { .description = "" } + } + }, + { + .name = "language", + .description = "BIOS language", + .type = CONFIG_SELECTION, + .default_string = "", + .default_int = 7, + .file_filter = "", + .spinner = { 0 }, + .selection = { + { .description = "English", .value = 7 }, + { .description = "German", .value = 6 }, + { .description = "French", .value = 5 }, + { .description = "Spanish", .value = 4 }, + { .description = "Danish", .value = 3 }, + { .description = "Swedish", .value = 2 }, + { .description = "Italian", .value = 1 }, + { .description = "Diagnostic mode", .value = 0 }, + { .description = "" } + } + }, + { .name = "", .description = "", .type = CONFIG_END } + // clang-format on }; - -static const device_t vid_1512_device = { - "Amstrad PC1512 (video)", - "vid_1512", - 0, 0, - NULL, vid_close_1512, NULL, - { NULL }, - vid_speed_change_1512, - NULL, - vid_1512_config +const device_t vid_1512_device = { + .name = "Amstrad PC1512 (video)", + .internal_name = "vid_1512", + .flags = 0, + .local = 0, + .init = NULL, + .close = vid_close_1512, + .reset = NULL, + { .available = NULL }, + .speed_changed = vid_speed_change_1512, + .force_redraw = NULL, + .config = vid_1512_config }; - -const device_t * -pc1512_get_device(void) -{ - return(&vid_1512_device); -} - - static void recalc_timings_1640(amsvid_t *vid) { @@ -767,94 +739,98 @@ recalc_timings_1640(amsvid_t *vid) ega_recalctimings(&vid->ega); if (vid->cga_enabled) { - overscan_x = overscan_y = 16; + overscan_x = overscan_y = 16; - vid->dispontime = vid->cga.dispontime; - vid->dispofftime = vid->cga.dispofftime; + vid->dispontime = vid->cga.dispontime; + vid->dispofftime = vid->cga.dispofftime; } else { - overscan_x = 16; overscan_y = 28; + overscan_x = 16; + overscan_y = 28; - vid->dispontime = vid->ega.dispontime; - vid->dispofftime = vid->ega.dispofftime; + vid->dispontime = vid->ega.dispontime; + vid->dispofftime = vid->ega.dispofftime; } } - static void vid_out_1640(uint16_t addr, uint8_t val, void *priv) { - amsvid_t *vid = (amsvid_t *)priv; + amsvid_t *vid = (amsvid_t *) priv; switch (addr) { - case 0x03db: - vid->cga_enabled = val & 0x40; - if (vid->cga_enabled) { - timer_disable(&vid->ega.timer); - timer_set_delay_u64(&vid->cga.timer, 0); - mem_mapping_enable(&vid->cga.mapping); - mem_mapping_disable(&vid->ega.mapping); - } else { - timer_disable(&vid->cga.timer); - timer_set_delay_u64(&vid->ega.timer, 0); - mem_mapping_disable(&vid->cga.mapping); - switch (vid->ega.gdcreg[6] & 0xc) { - case 0x0: /*128k at A0000*/ - mem_mapping_set_addr(&vid->ega.mapping, - 0xa0000, 0x20000); - break; + case 0x03db: + vid->cga_enabled = val & 0x40; + if (vid->cga_enabled) { + timer_disable(&vid->ega.timer); + timer_set_delay_u64(&vid->cga.timer, 0); + mem_mapping_enable(&vid->cga.mapping); + mem_mapping_disable(&vid->ega.mapping); + } else { + timer_disable(&vid->cga.timer); + timer_set_delay_u64(&vid->ega.timer, 0); + mem_mapping_disable(&vid->cga.mapping); + switch (vid->ega.gdcreg[6] & 0xc) { + case 0x0: /*128k at A0000*/ + mem_mapping_set_addr(&vid->ega.mapping, + 0xa0000, 0x20000); + break; - case 0x4: /*64k at A0000*/ - mem_mapping_set_addr(&vid->ega.mapping, - 0xa0000, 0x10000); - break; + case 0x4: /*64k at A0000*/ + mem_mapping_set_addr(&vid->ega.mapping, + 0xa0000, 0x10000); + break; - case 0x8: /*32k at B0000*/ - mem_mapping_set_addr(&vid->ega.mapping, - 0xb0000, 0x08000); - break; + case 0x8: /*32k at B0000*/ + mem_mapping_set_addr(&vid->ega.mapping, + 0xb0000, 0x08000); + break; - case 0xC: /*32k at B8000*/ - mem_mapping_set_addr(&vid->ega.mapping, - 0xb8000, 0x08000); - break; - } - } - return; + case 0xC: /*32k at B8000*/ + mem_mapping_set_addr(&vid->ega.mapping, + 0xb8000, 0x08000); + break; + + default: + break; + } + } + return; + + default: + break; } if (vid->cga_enabled) - cga_out(addr, val, &vid->cga); - else - ega_out(addr, val, &vid->ega); + cga_out(addr, val, &vid->cga); + else + ega_out(addr, val, &vid->ega); } - static uint8_t vid_in_1640(uint16_t addr, void *priv) { - amsvid_t *vid = (amsvid_t *)priv; + amsvid_t *vid = (amsvid_t *) priv; if (vid->cga_enabled) - return(cga_in(addr, &vid->cga)); - else - return(ega_in(addr, &vid->ega)); + return (cga_in(addr, &vid->cga)); + else + return (ega_in(addr, &vid->ega)); } - static void vid_init_1640(amstrad_t *ams) { amsvid_t *vid; /* Allocate a video controller block. */ - vid = (amsvid_t *)malloc(sizeof(amsvid_t)); + vid = (amsvid_t *) malloc(sizeof(amsvid_t)); memset(vid, 0x00, sizeof(amsvid_t)); rom_init(&vid->bios_rom, "roms/machines/pc1640/40100", - 0xc0000, 0x8000, 0x7fff, 0, 0); + 0xc0000, 0x8000, 0x7fff, 0, 0); ega_init(&vid->ega, 9, 0); - vid->cga.vram = vid->ega.vram; + vid->cga.vram = vid->ega.vram; vid->cga_enabled = 1; cga_init(&vid->cga); timer_disable(&vid->ega.timer); @@ -862,11 +838,11 @@ vid_init_1640(amstrad_t *ams) video_inform(VIDEO_FLAG_TYPE_SPECIAL, &timing_pc1640); mem_mapping_add(&vid->cga.mapping, 0xb8000, 0x08000, - cga_read, NULL, NULL, cga_write, NULL, NULL, NULL, 0, &vid->cga); - mem_mapping_add(&vid->ega.mapping, 0, 0, - ega_read, NULL, NULL, ega_write, NULL, NULL, NULL, 0, &vid->ega); + cga_read, NULL, NULL, cga_write, NULL, NULL, NULL, 0, &vid->cga); + mem_mapping_add(&vid->ega.mapping, 0, 0, + ega_read, NULL, NULL, ega_write, NULL, NULL, NULL, 0, &vid->ega); io_sethandler(0x03a0, 64, - vid_in_1640, NULL, NULL, vid_out_1640, NULL, NULL, vid); + vid_in_1640, NULL, NULL, vid_out_1640, NULL, NULL, vid); overscan_x = overscan_y = 16; @@ -878,801 +854,827 @@ vid_init_1640(amstrad_t *ams) ams->vid = vid; } - static void vid_close_1640(void *priv) { - amsvid_t *vid = (amsvid_t *)priv; + amsvid_t *vid = (amsvid_t *) priv; free(vid->ega.vram); free(vid); } - static void vid_speed_changed_1640(void *priv) { - amsvid_t *vid = (amsvid_t *)priv; + amsvid_t *vid = (amsvid_t *) priv; recalc_timings_1640(vid); } - -device_config_t vid_1640_config[] = -{ - { - "language", "BIOS language", CONFIG_SELECTION, "", 7, "", { 0 }, - { - { - "English", 7 - }, - { - "German", 6 - }, - { - "French", 5 - }, - { - "Spanish", 4 - }, - { - "Danish", 3 - }, - { - "Swedish", 2 - }, - { - "Italian", 1 - }, - { - "Diagnostic mode", 0 - }, - { - "" - } - } - }, - { - "", "", -1 +const device_config_t vid_1640_config[] = { + // clang-format off + { + .name = "language", + .description = "BIOS language", + .type = CONFIG_SELECTION, + .default_string = "", + .default_int = 7, + .file_filter = "", + .spinner = { 0 }, + .selection = { + { .description = "English", .value = 7 }, + { .description = "German", .value = 6 }, + { .description = "French", .value = 5 }, + { .description = "Spanish", .value = 4 }, + { .description = "Danish", .value = 3 }, + { .description = "Swedish", .value = 2 }, + { .description = "Italian", .value = 1 }, + { .description = "Diagnostic mode", .value = 0 }, + { .description = "" } } + }, + { .name = "", .description = "", .type = CONFIG_END } + // clang-format on }; -static const device_t vid_1640_device = { - "Amstrad PC1640 (video)", - "vid_1640", - 0, 0, - NULL, vid_close_1640, NULL, - { NULL }, - vid_speed_changed_1640, - NULL, - vid_1640_config +const device_t vid_1640_device = { + .name = "Amstrad PC1640 (video)", + .internal_name = "vid_1640", + .flags = 0, + .local = 0, + .init = NULL, + .close = vid_close_1640, + .reset = NULL, + { .available = NULL }, + .speed_changed = vid_speed_changed_1640, + .force_redraw = NULL, + .config = vid_1640_config }; -const device_t * -pc1640_get_device(void) -{ - return(&vid_1640_device); -} - /* Display type */ -#define PC200_CGA 0 /* CGA monitor */ -#define PC200_MDA 1 /* MDA monitor */ -#define PC200_TV 2 /* Television */ -#define PC200_LCDC 3 /* PPC512 LCD as CGA*/ -#define PC200_LCDM 4 /* PPC512 LCD as MDA*/ +#define PC200_CGA 0 /* CGA monitor */ +#define PC200_MDA 1 /* MDA monitor */ +#define PC200_TV 2 /* Television */ +#define PC200_LCDC 3 /* PPC512 LCD as CGA*/ +#define PC200_LCDM 4 /* PPC512 LCD as MDA*/ extern int nmi_mask; -static uint32_t blue, green; +static uint32_t blue; +static uint32_t green; static uint32_t lcdcols[256][2][2]; - static void ams_inform(amsvid_t *vid) { switch (vid->emulation) { - case PC200_CGA: - case PC200_TV: - case PC200_LCDC: - video_inform(VIDEO_FLAG_TYPE_CGA, &timing_pc200); - break; - case PC200_MDA: - case PC200_LCDM: - video_inform(VIDEO_FLAG_TYPE_MDA, &timing_pc200); - break; + case PC200_CGA: + case PC200_TV: + case PC200_LCDC: + video_inform(VIDEO_FLAG_TYPE_CGA, &timing_pc200); + break; + case PC200_MDA: + case PC200_LCDM: + video_inform(VIDEO_FLAG_TYPE_MDA, &timing_pc200); + break; + + default: + break; } } - static void vid_speed_changed_200(void *priv) { - amsvid_t *vid = (amsvid_t *)priv; + amsvid_t *vid = (amsvid_t *) priv; cga_recalctimings(&vid->cga); mda_recalctimings(&vid->mda); } - /* LCD colour mappings - * + * * 0 => solid green * 1 => blue on green * 2 => green on blue * 3 => solid blue */ -static unsigned char mapping1[256] = -{ -/* 0 1 2 3 4 5 6 7 8 9 A B C D E F */ -/*00*/ 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, -/*10*/ 2, 0, 1, 1, 1, 1, 1, 1, 2, 1, 1, 1, 1, 1, 1, 1, -/*20*/ 2, 2, 0, 1, 2, 2, 1, 1, 2, 2, 1, 1, 2, 2, 1, 1, -/*30*/ 2, 2, 2, 0, 2, 2, 1, 1, 2, 2, 2, 1, 2, 2, 1, 1, -/*40*/ 2, 2, 1, 1, 0, 1, 1, 1, 2, 2, 1, 1, 1, 1, 1, 1, -/*50*/ 2, 2, 1, 1, 2, 0, 1, 1, 2, 2, 1, 1, 2, 1, 1, 1, -/*60*/ 2, 2, 2, 2, 2, 2, 0, 1, 2, 2, 2, 2, 2, 2, 1, 1, -/*70*/ 2, 2, 2, 2, 2, 2, 2, 0, 2, 2, 2, 2, 2, 2, 2, 1, -/*80*/ 2, 1, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1, 1, -/*90*/ 2, 2, 1, 1, 1, 1, 1, 1, 2, 0, 1, 1, 1, 1, 1, 1, -/*A0*/ 2, 2, 2, 1, 2, 2, 1, 1, 2, 2, 0, 1, 2, 2, 1, 1, -/*B0*/ 2, 2, 2, 2, 2, 2, 1, 1, 2, 2, 2, 0, 2, 2, 1, 1, -/*C0*/ 2, 2, 1, 1, 2, 1, 1, 1, 2, 2, 1, 1, 0, 1, 1, 1, -/*D0*/ 2, 2, 1, 1, 2, 2, 1, 1, 2, 2, 1, 1, 2, 0, 1, 1, -/*E0*/ 2, 2, 2, 2, 2, 2, 2, 1, 2, 2, 2, 2, 2, 2, 0, 1, -/*F0*/ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 0, +static unsigned char mapping1[256] = { + // clang-format off +/* 0 1 2 3 4 5 6 7 8 9 A B C D E F */ +/*00*/ 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, +/*10*/ 2, 0, 1, 1, 1, 1, 1, 1, 2, 1, 1, 1, 1, 1, 1, 1, +/*20*/ 2, 2, 0, 1, 2, 2, 1, 1, 2, 2, 1, 1, 2, 2, 1, 1, +/*30*/ 2, 2, 2, 0, 2, 2, 1, 1, 2, 2, 2, 1, 2, 2, 1, 1, +/*40*/ 2, 2, 1, 1, 0, 1, 1, 1, 2, 2, 1, 1, 1, 1, 1, 1, +/*50*/ 2, 2, 1, 1, 2, 0, 1, 1, 2, 2, 1, 1, 2, 1, 1, 1, +/*60*/ 2, 2, 2, 2, 2, 2, 0, 1, 2, 2, 2, 2, 2, 2, 1, 1, +/*70*/ 2, 2, 2, 2, 2, 2, 2, 0, 2, 2, 2, 2, 2, 2, 2, 1, +/*80*/ 2, 1, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1, 1, +/*90*/ 2, 2, 1, 1, 1, 1, 1, 1, 2, 0, 1, 1, 1, 1, 1, 1, +/*A0*/ 2, 2, 2, 1, 2, 2, 1, 1, 2, 2, 0, 1, 2, 2, 1, 1, +/*B0*/ 2, 2, 2, 2, 2, 2, 1, 1, 2, 2, 2, 0, 2, 2, 1, 1, +/*C0*/ 2, 2, 1, 1, 2, 1, 1, 1, 2, 2, 1, 1, 0, 1, 1, 1, +/*D0*/ 2, 2, 1, 1, 2, 2, 1, 1, 2, 2, 1, 1, 2, 0, 1, 1, +/*E0*/ 2, 2, 2, 2, 2, 2, 2, 1, 2, 2, 2, 2, 2, 2, 0, 1, +/*F0*/ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 0, + // clang-format on }; -static unsigned char mapping2[256] = -{ -/* 0 1 2 3 4 5 6 7 8 9 A B C D E F */ -/*00*/ 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, -/*10*/ 1, 3, 2, 2, 2, 2, 2, 2, 1, 2, 2, 2, 2, 2, 2, 2, -/*20*/ 1, 1, 3, 2, 1, 1, 2, 2, 1, 1, 2, 2, 1, 1, 2, 2, -/*30*/ 1, 1, 1, 3, 1, 1, 2, 2, 1, 1, 1, 2, 1, 1, 2, 2, -/*40*/ 1, 1, 2, 2, 3, 2, 2, 2, 1, 1, 2, 2, 2, 2, 2, 2, -/*50*/ 1, 1, 2, 2, 1, 3, 2, 2, 1, 1, 2, 2, 1, 2, 2, 2, -/*60*/ 1, 1, 1, 1, 1, 1, 3, 2, 1, 1, 1, 1, 1, 1, 2, 2, -/*70*/ 1, 1, 1, 1, 1, 1, 1, 3, 1, 1, 1, 1, 1, 1, 1, 2, -/*80*/ 2, 1, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1, 1, -/*90*/ 1, 1, 2, 2, 2, 2, 2, 2, 1, 3, 2, 2, 2, 2, 2, 2, -/*A0*/ 1, 1, 1, 2, 1, 1, 2, 2, 1, 1, 3, 2, 1, 1, 2, 2, -/*B0*/ 1, 1, 1, 1, 1, 1, 2, 2, 1, 1, 1, 3, 1, 1, 2, 2, -/*C0*/ 1, 1, 2, 2, 1, 2, 2, 2, 1, 1, 2, 2, 3, 2, 2, 2, -/*D0*/ 1, 1, 2, 2, 1, 1, 2, 2, 1, 1, 2, 2, 1, 3, 2, 2, -/*E0*/ 1, 1, 1, 1, 1, 1, 1, 2, 1, 1, 1, 1, 1, 1, 3, 2, -/*F0*/ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 3, +static unsigned char mapping2[256] = { + // clang-format off +/* 0 1 2 3 4 5 6 7 8 9 A B C D E F */ +/*00*/ 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, +/*10*/ 1, 3, 2, 2, 2, 2, 2, 2, 1, 2, 2, 2, 2, 2, 2, 2, +/*20*/ 1, 1, 3, 2, 1, 1, 2, 2, 1, 1, 2, 2, 1, 1, 2, 2, +/*30*/ 1, 1, 1, 3, 1, 1, 2, 2, 1, 1, 1, 2, 1, 1, 2, 2, +/*40*/ 1, 1, 2, 2, 3, 2, 2, 2, 1, 1, 2, 2, 2, 2, 2, 2, +/*50*/ 1, 1, 2, 2, 1, 3, 2, 2, 1, 1, 2, 2, 1, 2, 2, 2, +/*60*/ 1, 1, 1, 1, 1, 1, 3, 2, 1, 1, 1, 1, 1, 1, 2, 2, +/*70*/ 1, 1, 1, 1, 1, 1, 1, 3, 1, 1, 1, 1, 1, 1, 1, 2, +/*80*/ 2, 1, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1, 1, +/*90*/ 1, 1, 2, 2, 2, 2, 2, 2, 1, 3, 2, 2, 2, 2, 2, 2, +/*A0*/ 1, 1, 1, 2, 1, 1, 2, 2, 1, 1, 3, 2, 1, 1, 2, 2, +/*B0*/ 1, 1, 1, 1, 1, 1, 2, 2, 1, 1, 1, 3, 1, 1, 2, 2, +/*C0*/ 1, 1, 2, 2, 1, 2, 2, 2, 1, 1, 2, 2, 3, 2, 2, 2, +/*D0*/ 1, 1, 2, 2, 1, 1, 2, 2, 1, 1, 2, 2, 1, 3, 2, 2, +/*E0*/ 1, 1, 1, 1, 1, 1, 1, 2, 1, 1, 1, 1, 1, 1, 3, 2, +/*F0*/ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 3, + // clang-format on }; - -static void set_lcd_cols(uint8_t mode_reg) +static void +set_lcd_cols(uint8_t mode_reg) { - unsigned char *mapping = (mode_reg & 0x80) ? mapping2 : mapping1; - int c; + const unsigned char *mapping = (mode_reg & 0x80) ? mapping2 : mapping1; - for (c = 0; c < 256; c++) { - switch (mapping[c]) { - case 0: - lcdcols[c][0][0] = lcdcols[c][1][0] = green; - lcdcols[c][0][1] = lcdcols[c][1][1] = green; - break; + for (uint16_t c = 0; c < 256; c++) { + switch (mapping[c]) { + case 0: + lcdcols[c][0][0] = lcdcols[c][1][0] = green; + lcdcols[c][0][1] = lcdcols[c][1][1] = green; + break; - case 1: - lcdcols[c][0][0] = lcdcols[c][1][0] = - lcdcols[c][1][1] = green; - lcdcols[c][0][1] = blue; - break; + case 1: + lcdcols[c][0][0] = lcdcols[c][1][0] = lcdcols[c][1][1] = green; + lcdcols[c][0][1] = blue; + break; - case 2: - lcdcols[c][0][0] = lcdcols[c][1][0] = - lcdcols[c][1][1] = blue; - lcdcols[c][0][1] = green; - break; + case 2: + lcdcols[c][0][0] = lcdcols[c][1][0] = lcdcols[c][1][1] = blue; + lcdcols[c][0][1] = green; + break; - case 3: - lcdcols[c][0][0] = lcdcols[c][1][0] = blue; - lcdcols[c][0][1] = lcdcols[c][1][1] = blue; - break; - } + case 3: + lcdcols[c][0][0] = lcdcols[c][1][0] = blue; + lcdcols[c][0][1] = lcdcols[c][1][1] = blue; + break; + + default: + break; + } } } - static uint8_t vid_in_200(uint16_t addr, void *priv) { - amsvid_t *vid = (amsvid_t *)priv; - cga_t *cga = &vid->cga; - mda_t *mda = &vid->mda; - uint8_t ret; + amsvid_t *vid = (amsvid_t *) priv; + cga_t *cga = &vid->cga; + mda_t *mda = &vid->mda; + uint8_t ret; switch (addr) { - case 0x03b8: - return(mda->ctrl); - - case 0x03d8: - return(cga->cgamode); + case 0x03b8: + return (mda->ctrl); - case 0x03dd: - ret = vid->crtc_index; /* Read NMI reason */ - vid->crtc_index &= 0x1f; /* Reset NMI reason */ - nmi = 0; /* And reset NMI flag */ - return(ret); + case 0x03d8: + return (cga->cgamode); - case 0x03de: - return((vid->operation_ctrl & 0xc7) | vid->dipswitches); /*External CGA*/ + case 0x03dd: + ret = vid->crtc_index; /* Read NMI reason */ + vid->crtc_index &= 0x1f; /* Reset NMI reason */ + nmi = 0; /* And reset NMI flag */ + return ret; - case 0x03df: - return(vid->reg_3df); + case 0x03de: + return ((vid->operation_ctrl & 0xc7) | vid->dipswitches); /*External CGA*/ + + case 0x03df: + return (vid->reg_3df); + + default: + break; } if (addr >= 0x3D0 && addr <= 0x3DF) - return cga_in(addr, cga); + return cga_in(addr, cga); if (addr >= 0x3B0 && addr <= 0x3BB) - return mda_in(addr, mda); + return mda_in(addr, mda); return 0xFF; } - static void vid_out_200(uint16_t addr, uint8_t val, void *priv) { - amsvid_t *vid = (amsvid_t *)priv; - cga_t *cga = &vid->cga; - mda_t *mda = &vid->mda; - uint8_t old; + amsvid_t *vid = (amsvid_t *) priv; + cga_t *cga = &vid->cga; + mda_t *mda = &vid->mda; + uint8_t old; switch (addr) { -/* MDA writes ============================================================== */ - case 0x3b1: - case 0x3b3: - case 0x3b5: - case 0x3b7: - /* Writes banned to CRTC registers 0-11? */ - if (!(vid->operation_ctrl & 0x40) && mda->crtcreg <= 11) { - vid->crtc_index = 0x20 | (mda->crtcreg & 0x1f); - if (vid->operation_ctrl & 0x80) - nmi = 1; - vid->reg_3df = val; - return; - } - old = mda->crtc[mda->crtcreg]; - mda->crtc[mda->crtcreg] = val & crtc_mask[mda->crtcreg]; - if (old != val) { - if (mda->crtcreg < 0xe || mda->crtcreg > 0x10) { - fullchange = changeframecount; - mda_recalctimings(mda); - } - } - return; - case 0x3b8: - old = mda->ctrl; - mda->ctrl = val; - if ((mda->ctrl ^ old) & 3) - mda_recalctimings(mda); - vid->crtc_index &= 0x1F; - vid->crtc_index |= 0x80; - if (vid->operation_ctrl & 0x80) - nmi = 1; - return; + /* MDA writes ============================================================== */ + case 0x3b1: + case 0x3b3: + case 0x3b5: + case 0x3b7: + /* Writes banned to CRTC registers 0-11? */ + if (!(vid->operation_ctrl & 0x40) && mda->crtcreg <= 11) { + vid->crtc_index = 0x20 | (mda->crtcreg & 0x1f); + if (vid->operation_ctrl & 0x80) + nmi_raise(); + vid->reg_3df = val; + return; + } + old = mda->crtc[mda->crtcreg]; + mda->crtc[mda->crtcreg] = val & crtc_mask[mda->crtcreg]; + if (old != val) { + if (mda->crtcreg < 0xe || mda->crtcreg > 0x10) { + vid->fullchange = changeframecount; + mda_recalctimings(mda); + } + } + return; + case 0x3b8: + old = mda->ctrl; + mda->ctrl = val; + if ((mda->ctrl ^ old) & 3) + mda_recalctimings(mda); + vid->crtc_index &= 0x1F; + vid->crtc_index |= 0x80; + if (vid->operation_ctrl & 0x80) + nmi_raise(); + return; -/* CGA writes ============================================================== */ - case 0x03d1: - case 0x03d3: - case 0x03d5: - case 0x03d7: - if (!(vid->operation_ctrl & 0x40) && cga->crtcreg <= 11) { - vid->crtc_index = 0x20 | (cga->crtcreg & 0x1f); - if (vid->operation_ctrl & 0x80) - nmi = 1; - vid->reg_3df = val; - return; - } - old = cga->crtc[cga->crtcreg]; - cga->crtc[cga->crtcreg] = val & crtc_mask[cga->crtcreg]; - if (old != val) { - if (cga->crtcreg < 0xe || cga->crtcreg > 0x10) { - fullchange = changeframecount; - cga_recalctimings(cga); - } - } - return; + /* CGA writes ============================================================== */ + case 0x03d1: + case 0x03d3: + case 0x03d5: + case 0x03d7: + if (!(vid->operation_ctrl & 0x40) && cga->crtcreg <= 11) { + vid->crtc_index = 0x20 | (cga->crtcreg & 0x1f); + if (vid->operation_ctrl & 0x80) + nmi_raise(); + vid->reg_3df = val; + return; + } + old = cga->crtc[cga->crtcreg]; + cga->crtc[cga->crtcreg] = val & crtc_mask[cga->crtcreg]; + if (old != val) { + if (cga->crtcreg < 0xe || cga->crtcreg > 0x10) { + vid->fullchange = changeframecount; + cga_recalctimings(cga); + } + } + return; - case 0x03d8: - old = cga->cgamode; - cga->cgamode = val; - if ((cga->cgamode ^ old) & 3) - cga_recalctimings(cga); - vid->crtc_index &= 0x1f; - vid->crtc_index |= 0x80; - if (vid->operation_ctrl & 0x80) - nmi = 1; - else - set_lcd_cols(val); - return; + case 0x03d8: + old = cga->cgamode; + cga->cgamode = val; + if ((cga->cgamode ^ old) & 3) + cga_recalctimings(cga); + vid->crtc_index &= 0x1f; + vid->crtc_index |= 0x80; + if (vid->operation_ctrl & 0x80) + nmi_raise(); + else + set_lcd_cols(val); + return; -/* PC200 control port writes ============================================== */ - case 0x03de: - vid->crtc_index = 0x1f; - /* NMI only seems to be triggered if the value being written has the high - * bit set (enable NMI). So it only protects writes to this port if you - * let it? */ - if (val & 0x80) { - vid->operation_ctrl = val; - vid->crtc_index |= 0x40; - nmi = 1; - return; - } - timer_disable(&vid->cga.timer); - timer_disable(&vid->mda.timer); - timer_disable(&vid->timer); - vid->operation_ctrl = val; - /* Bits 0 and 1 control emulation and output mode */ - amstrad_log("emulation and mode = %02X\n", val & 0x03); - if (val & 1) /* Monitor */ - vid->emulation = (val & 2) ? PC200_MDA : PC200_CGA; - else if (vid->type == AMS_PPC512) - vid->emulation = (val & 2) ? PC200_LCDM : PC200_LCDC; - else - vid->emulation = PC200_TV; - if (vid->emulation == PC200_CGA || vid->emulation == PC200_TV) - timer_advance_u64(&vid->cga.timer, 1); - else if (vid->emulation == PC200_MDA) - timer_advance_u64(&vid->mda.timer, 1); - else - timer_advance_u64(&vid->timer, 1); + /* PC200 control port writes ============================================== */ + case 0x03de: + vid->crtc_index = 0x1f; + /* NMI only seems to be triggered if the value being written has the high + * bit set (enable NMI). So it only protects writes to this port if you + * let it? */ + if (val & 0x80) { + vid->operation_ctrl = val; + vid->crtc_index |= 0x40; + nmi_raise(); + return; + } + timer_disable(&vid->cga.timer); + timer_disable(&vid->mda.timer); + timer_disable(&vid->timer); + vid->operation_ctrl = val; + /* Bits 0 and 1 control emulation and output mode */ + amstrad_log("emulation and mode = %02X\n", val & 0x03); + if (val & 1) /* Monitor */ + vid->emulation = (val & 2) ? PC200_MDA : PC200_CGA; + else if (vid->type == AMS_PPC512) + vid->emulation = (val & 2) ? PC200_LCDM : PC200_LCDC; + else + vid->emulation = PC200_TV; + if (vid->emulation == PC200_CGA || vid->emulation == PC200_TV) + timer_advance_u64(&vid->cga.timer, 1); + else if (vid->emulation == PC200_MDA) + timer_advance_u64(&vid->mda.timer, 1); + else + timer_advance_u64(&vid->timer, 1); - /* Bit 2 disables the IDA. We don't support dynamic enabling - * and disabling of the IDA (instead, PCEM disconnects the - * IDA from the bus altogether) so don't implement this */ + /* Bit 2 disables the IDA. We don't support dynamic enabling + * and disabling of the IDA (instead, PCEM disconnects the + * IDA from the bus altogether) so don't implement this */ - /* Enable the appropriate memory ranges depending whether - * the IDA is configured as MDA or CGA */ - if (vid->emulation == PC200_MDA || - vid->emulation == PC200_LCDM) { - mem_mapping_disable(&vid->cga.mapping); - mem_mapping_enable(&vid->mda.mapping); - } - else { - mem_mapping_disable(&vid->mda.mapping); - mem_mapping_enable(&vid->cga.mapping); - } - return; + /* Enable the appropriate memory ranges depending whether + * the IDA is configured as MDA or CGA */ + if (vid->emulation == PC200_MDA || vid->emulation == PC200_LCDM) { + mem_mapping_disable(&vid->cga.mapping); + mem_mapping_enable(&vid->mda.mapping); + } else { + mem_mapping_disable(&vid->mda.mapping); + mem_mapping_enable(&vid->cga.mapping); + } + return; + + default: + break; } if (addr >= 0x3D0 && addr <= 0x3DF) - cga_out(addr, val, cga); + cga_out(addr, val, cga); if (addr >= 0x3B0 && addr <= 0x3BB) - mda_out(addr, val, mda); + mda_out(addr, val, mda); } - -static void -lcd_draw_char_80(amsvid_t *vid, uint32_t *buffer, uint8_t chr, - uint8_t attr, int drawcursor, int blink, int sc, - int mode160, uint8_t control) +static void +lcd_draw_char_80(amsvid_t *vid, uint32_t *buffer, uint8_t chr, + uint8_t attr, int drawcursor, int blink, int sc, + int mode160, uint8_t control) { - int c; - uint8_t bits = fontdat[chr + vid->cga.fontbase][sc]; - uint8_t bright = 0; + int c; + uint8_t bits = fontdat[chr + vid->cga.fontbase][sc]; + uint8_t bright = 0; uint16_t mask; - if (attr & 8) { /* bright */ - /* The brightness algorithm appears to be: replace any bit sequence 011 - * with 001 (assuming an extra 0 to the left of the byte). - */ - bright = bits; - for (c = 0, mask = 0x100; c < 7; c++, mask >>= 1) { - if (((bits & mask) == 0) && ((bits & (mask >> 1)) != 0) && - ((bits & (mask >> 2)) != 0)) - bright &= ~(mask >> 1); - } - bits = bright; + if (attr & 8) { /* bright */ + /* The brightness algorithm appears to be: replace any bit sequence 011 + * with 001 (assuming an extra 0 to the left of the byte). + */ + bright = bits; + for (c = 0, mask = 0x100; c < 7; c++, mask >>= 1) { + if (((bits & mask) == 0) && ((bits & (mask >> 1)) != 0) && ((bits & (mask >> 2)) != 0)) + bright &= ~(mask >> 1); + } + bits = bright; } - if (drawcursor) bits ^= 0xFF; + if (drawcursor) + bits ^= 0xFF; for (c = 0, mask = 0x80; c < 8; c++, mask >>= 1) { - if (mode160) buffer[c] = (attr & mask) ? blue : green; - else if (control & 0x20) /* blinking */ - buffer[c] = lcdcols[attr & 0x7F][blink][(bits & mask) ? 1 : 0]; - else buffer[c] = lcdcols[attr][blink][(bits & mask) ? 1 : 0]; + if (mode160) + buffer[c] = (attr & mask) ? blue : green; + else if (control & 0x20) /* blinking */ + buffer[c] = lcdcols[attr & 0x7F][blink][(bits & mask) ? 1 : 0]; + else + buffer[c] = lcdcols[attr][blink][(bits & mask) ? 1 : 0]; } } - -static void -lcd_draw_char_40(amsvid_t *vid, uint32_t *buffer, uint8_t chr, - uint8_t attr, int drawcursor, int blink, int sc, - uint8_t control) +static void +lcd_draw_char_40(amsvid_t *vid, uint32_t *buffer, uint8_t chr, + uint8_t attr, int drawcursor, int blink, int sc, + uint8_t control) { - int c; uint8_t bits = fontdat[chr + vid->cga.fontbase][sc]; uint8_t mask = 0x80; - if (attr & 8) /* bright */ - bits = bits & (bits >> 1); - if (drawcursor) bits ^= 0xFF; + if (attr & 8) /* bright */ + bits = bits & (bits >> 1); + if (drawcursor) + bits ^= 0xFF; - for (c = 0; c < 8; c++, mask >>= 1) { - if (control & 0x20) { - buffer[c*2] = buffer[c*2+1] = - lcdcols[attr & 0x7F][blink][(bits & mask) ? 1 : 0]; - } else { - buffer[c*2] = buffer[c*2+1] = - lcdcols[attr][blink][(bits & mask) ? 1 : 0]; - } + for (uint8_t c = 0; c < 8; c++, mask >>= 1) { + if (control & 0x20) { + buffer[c * 2] = buffer[c * 2 + 1] = lcdcols[attr & 0x7F][blink][(bits & mask) ? 1 : 0]; + } else { + buffer[c * 2] = buffer[c * 2 + 1] = lcdcols[attr][blink][(bits & mask) ? 1 : 0]; + } } } - -static void +static void lcdm_poll(amsvid_t *vid) { - mda_t *mda = &vid->mda; - uint16_t ca = (mda->crtc[15] | (mda->crtc[14] << 8)) & 0x3fff; - int drawcursor; - int x; - int oldvc; - uint8_t chr, attr; - int oldsc; - int blink; + mda_t *mda = &vid->mda; + uint16_t ca = (mda->crtc[15] | (mda->crtc[14] << 8)) & 0x3fff; + int drawcursor; + int x; + int oldvc; + uint8_t chr; + uint8_t attr; + int oldsc; + int blink; if (!mda->linepos) { - timer_advance_u64(&vid->timer, mda->dispofftime); - mda->stat |= 1; - mda->linepos = 1; - oldsc = mda->sc; - if ((mda->crtc[8] & 3) == 3) - mda->sc = (mda->sc << 1) & 7; - if (mda->dispon) { - if (mda->displine < mda->firstline) - mda->firstline = mda->displine; - mda->lastline = mda->displine; - for (x = 0; x < mda->crtc[1]; x++) { - chr = mda->vram[(mda->ma << 1) & 0xfff]; - attr = mda->vram[((mda->ma << 1) + 1) & 0xfff]; - drawcursor = ((mda->ma == ca) && mda->con && mda->cursoron); - blink = ((mda->blink & 16) && (mda->ctrl & 0x20) && (attr & 0x80) && !drawcursor); + timer_advance_u64(&vid->timer, mda->dispofftime); + mda->stat |= 1; + mda->linepos = 1; + oldsc = mda->sc; + if ((mda->crtc[8] & 3) == 3) + mda->sc = (mda->sc << 1) & 7; + if (mda->dispon) { + if (mda->displine < mda->firstline) + mda->firstline = mda->displine; + mda->lastline = mda->displine; + for (x = 0; x < mda->crtc[1]; x++) { + chr = mda->vram[(mda->ma << 1) & 0xfff]; + attr = mda->vram[((mda->ma << 1) + 1) & 0xfff]; + drawcursor = ((mda->ma == ca) && mda->con && mda->cursoron); + blink = ((mda->blink & 16) && (mda->ctrl & 0x20) && (attr & 0x80) && !drawcursor); - lcd_draw_char_80(vid, &((uint32_t *)(buffer32->line[mda->displine]))[x * 8], chr, attr, drawcursor, blink, mda->sc, 0, mda->ctrl); - mda->ma++; - } - } - mda->sc = oldsc; - if (mda->vc == mda->crtc[7] && !mda->sc) - mda->stat |= 8; - mda->displine++; - if (mda->displine >= 500) - mda->displine=0; + lcd_draw_char_80(vid, &(buffer32->line[mda->displine])[x * 8], chr, attr, drawcursor, blink, mda->sc, 0, mda->ctrl); + mda->ma++; + } + } + mda->sc = oldsc; + if (mda->vc == mda->crtc[7] && !mda->sc) + mda->stat |= 8; + mda->displine++; + if (mda->displine >= 500) + mda->displine = 0; } else { - timer_advance_u64(&vid->timer, mda->dispontime); - if (mda->dispon) mda->stat&=~1; - mda->linepos=0; - if (mda->vsynctime) { - mda->vsynctime--; - if (!mda->vsynctime) - mda->stat&=~8; - } - if (mda->sc == (mda->crtc[11] & 31) || ((mda->crtc[8] & 3) == 3 && mda->sc == ((mda->crtc[11] & 31) >> 1))) { - mda->con = 0; - mda->coff = 1; - } - if (mda->vadj) { - mda->sc++; - mda->sc &= 31; - mda->ma = mda->maback; - mda->vadj--; - if (!mda->vadj) { - mda->dispon = 1; - mda->ma = mda->maback = (mda->crtc[13] | (mda->crtc[12] << 8)) & 0x3fff; - mda->sc = 0; - } - } else if (mda->sc == mda->crtc[9] || ((mda->crtc[8] & 3) == 3 && mda->sc == (mda->crtc[9] >> 1))) { - mda->maback = mda->ma; - mda->sc = 0; - oldvc = mda->vc; - mda->vc++; - mda->vc &= 127; - if (mda->vc == mda->crtc[6]) - mda->dispon=0; - if (oldvc == mda->crtc[4]) { - mda->vc = 0; - mda->vadj = mda->crtc[5]; - if (!mda->vadj) mda->dispon = 1; - if (!mda->vadj) mda->ma = mda->maback = (mda->crtc[13] | (mda->crtc[12] << 8)) & 0x3fff; - if ((mda->crtc[10] & 0x60) == 0x20) mda->cursoron = 0; - else mda->cursoron = mda->blink & 16; - } - if (mda->vc == mda->crtc[7]) { - mda->dispon = 0; - mda->displine = 0; - mda->vsynctime = 16; - if (mda->crtc[7]) { - x = mda->crtc[1] * 8; - mda->lastline++; - if ((x != xsize) || ((mda->lastline - mda->firstline) != ysize) || video_force_resize_get()) { - xsize = x; - ysize = mda->lastline - mda->firstline; - if (xsize < 64) xsize = 656; - if (ysize < 32) ysize = 200; - set_screen_size(xsize, ysize); + timer_advance_u64(&vid->timer, mda->dispontime); + if (mda->dispon) + mda->stat &= ~1; + mda->linepos = 0; + if (mda->vsynctime) { + mda->vsynctime--; + if (!mda->vsynctime) + mda->stat &= ~8; + } + if (mda->sc == (mda->crtc[11] & 31) || ((mda->crtc[8] & 3) == 3 && mda->sc == ((mda->crtc[11] & 31) >> 1))) { + mda->con = 0; + mda->coff = 1; + } + if (mda->vadj) { + mda->sc++; + mda->sc &= 31; + mda->ma = mda->maback; + mda->vadj--; + if (!mda->vadj) { + mda->dispon = 1; + mda->ma = mda->maback = (mda->crtc[13] | (mda->crtc[12] << 8)) & 0x3fff; + mda->sc = 0; + } + } else if (mda->sc == mda->crtc[9] || ((mda->crtc[8] & 3) == 3 && mda->sc == (mda->crtc[9] >> 1))) { + mda->maback = mda->ma; + mda->sc = 0; + oldvc = mda->vc; + mda->vc++; + mda->vc &= 127; + if (mda->vc == mda->crtc[6]) + mda->dispon = 0; + if (oldvc == mda->crtc[4]) { + mda->vc = 0; + mda->vadj = mda->crtc[5]; + if (!mda->vadj) + mda->dispon = 1; + if (!mda->vadj) + mda->ma = mda->maback = (mda->crtc[13] | (mda->crtc[12] << 8)) & 0x3fff; + if ((mda->crtc[10] & 0x60) == 0x20) + mda->cursoron = 0; + else + mda->cursoron = mda->blink & 16; + } + if (mda->vc == mda->crtc[7]) { + mda->dispon = 0; + mda->displine = 0; + mda->vsynctime = 16; + if (mda->crtc[7]) { + x = mda->crtc[1] * 8; + mda->lastline++; + if ((x != xsize) || ((mda->lastline - mda->firstline) != ysize) || video_force_resize_get()) { + xsize = x; + ysize = mda->lastline - mda->firstline; + if (xsize < 64) + xsize = 656; + if (ysize < 32) + ysize = 200; + set_screen_size(xsize, ysize); - if (video_force_resize_get()) - video_force_resize_set(0); - } - video_blit_memtoscreen(0, mda->firstline, xsize, ysize); - frames++; - video_res_x = mda->crtc[1]; - video_res_y = mda->crtc[6]; - video_bpp = 0; - } - mda->firstline = 1000; - mda->lastline = 0; - mda->blink++; - } - } else { - mda->sc++; - mda->sc &= 31; - mda->ma = mda->maback; - } - if ((mda->sc == (mda->crtc[10] & 31) || ((mda->crtc[8] & 3) == 3 && mda->sc == ((mda->crtc[10] & 31) >> 1)))) - mda->con = 1; + if (video_force_resize_get()) + video_force_resize_set(0); + } + video_blit_memtoscreen(0, mda->firstline, xsize, ysize); + frames++; + video_res_x = mda->crtc[1]; + video_res_y = mda->crtc[6]; + video_bpp = 0; + } + mda->firstline = 1000; + mda->lastline = 0; + mda->blink++; + } + } else { + mda->sc++; + mda->sc &= 31; + mda->ma = mda->maback; + } + if (mda->sc == (mda->crtc[10] & 31) || ((mda->crtc[8] & 3) == 3 && mda->sc == ((mda->crtc[10] & 31) >> 1))) + mda->con = 1; } } - -static void +static void lcdc_poll(amsvid_t *vid) { - cga_t *cga = &vid->cga; - int drawcursor; - int x, c, xs_temp, ys_temp; - int oldvc; - uint8_t chr, attr; + cga_t *cga = &vid->cga; + int drawcursor; + int x; + int xs_temp; + int ys_temp; + int oldvc; + uint8_t chr; + uint8_t attr; uint16_t dat; - int oldsc; + int oldsc; uint16_t ca; - int blink; + int blink; ca = (cga->crtc[15] | (cga->crtc[14] << 8)) & 0x3fff; if (!cga->linepos) { - timer_advance_u64(&vid->timer, cga->dispofftime); - cga->cgastat |= 1; - cga->linepos = 1; - oldsc = cga->sc; - if ((cga->crtc[8] & 3) == 3) - cga->sc = ((cga->sc << 1) + cga->oddeven) & 7; - if (cga->cgadispon) { - if (cga->displine < cga->firstline) { - cga->firstline = cga->displine; - video_wait_for_buffer(); - } - cga->lastline = cga->displine; + timer_advance_u64(&vid->timer, cga->dispofftime); + cga->cgastat |= 1; + cga->linepos = 1; + oldsc = cga->sc; + if ((cga->crtc[8] & 3) == 3) + cga->sc = ((cga->sc << 1) + cga->oddeven) & 7; + if (cga->cgadispon) { + if (cga->displine < cga->firstline) { + cga->firstline = cga->displine; + video_wait_for_buffer(); + } + cga->lastline = cga->displine; - if (cga->cgamode & 1) { - for (x = 0; x < cga->crtc[1]; x++) { - chr = cga->charbuffer[x << 1]; - attr = cga->charbuffer[(x << 1) + 1]; - drawcursor = ((cga->ma == ca) && cga->con && cga->cursoron); - blink = ((cga->cgablink & 16) && (cga->cgamode & 0x20) && (attr & 0x80) && !drawcursor); - lcd_draw_char_80(vid, &(buffer32->line[(cga->displine << 1)])[x * 8], chr, attr, drawcursor, blink, cga->sc, cga->cgamode & 0x40, cga->cgamode); - lcd_draw_char_80(vid, &(buffer32->line[(cga->displine << 1) + 1])[x * 8], chr, attr, drawcursor, blink, cga->sc, cga->cgamode & 0x40, cga->cgamode); - cga->ma++; - } - } else if (!(cga->cgamode & 2)) { - for (x = 0; x < cga->crtc[1]; x++) { - chr = cga->vram[((cga->ma << 1) & 0x3fff)]; - attr = cga->vram[(((cga->ma << 1) + 1) & 0x3fff)]; - drawcursor = ((cga->ma == ca) && cga->con && cga->cursoron); - blink = ((cga->cgablink & 16) && (cga->cgamode & 0x20) && (attr & 0x80) && !drawcursor); - lcd_draw_char_40(vid, &(buffer32->line[(cga->displine << 1)])[x * 16], chr, attr, drawcursor, blink, cga->sc, cga->cgamode); - lcd_draw_char_40(vid, &(buffer32->line[(cga->displine << 1) + 1])[x * 16], chr, attr, drawcursor, blink, cga->sc, cga->cgamode); - cga->ma++; - } - } else { /* Graphics mode */ - for (x = 0; x < cga->crtc[1]; x++) { - dat = (cga->vram[((cga->ma << 1) & 0x1fff) + ((cga->sc & 1) * 0x2000)] << 8) | cga->vram[((cga->ma << 1) & 0x1fff) + ((cga->sc & 1) * 0x2000) + 1]; - cga->ma++; - for (c = 0; c < 16; c++) { - buffer32->line[(cga->displine << 1)][(x << 4) + c] = buffer32->line[(cga->displine << 1) + 1][(x << 4) + c] = - (dat & 0x8000) ? blue : green; - dat <<= 1; - } - } - } - } else { - if (cga->cgamode & 1) { - hline(buffer32, 0, (cga->displine << 1), (cga->crtc[1] << 3), green); - hline(buffer32, 0, (cga->displine << 1) + 1, (cga->crtc[1] << 3), green); - } else { - hline(buffer32, 0, (cga->displine << 1), (cga->crtc[1] << 4), green); - hline(buffer32, 0, (cga->displine << 1) + 1, (cga->crtc[1] << 4), green); - } - } + if (cga->cgamode & 1) { + for (x = 0; x < cga->crtc[1]; x++) { + chr = cga->charbuffer[x << 1]; + attr = cga->charbuffer[(x << 1) + 1]; + drawcursor = ((cga->ma == ca) && cga->con && cga->cursoron); + blink = ((cga->cgablink & 16) && (cga->cgamode & 0x20) && (attr & 0x80) && !drawcursor); + lcd_draw_char_80(vid, &(buffer32->line[cga->displine << 1])[x * 8], chr, attr, drawcursor, blink, cga->sc, cga->cgamode & 0x40, cga->cgamode); + lcd_draw_char_80(vid, &(buffer32->line[(cga->displine << 1) + 1])[x * 8], chr, attr, drawcursor, blink, cga->sc, cga->cgamode & 0x40, cga->cgamode); + cga->ma++; + } + } else if (!(cga->cgamode & 2)) { + for (x = 0; x < cga->crtc[1]; x++) { + chr = cga->vram[(cga->ma << 1) & 0x3fff]; + attr = cga->vram[((cga->ma << 1) + 1) & 0x3fff]; + drawcursor = ((cga->ma == ca) && cga->con && cga->cursoron); + blink = ((cga->cgablink & 16) && (cga->cgamode & 0x20) && (attr & 0x80) && !drawcursor); + lcd_draw_char_40(vid, &(buffer32->line[cga->displine << 1])[x * 16], chr, attr, drawcursor, blink, cga->sc, cga->cgamode); + lcd_draw_char_40(vid, &(buffer32->line[(cga->displine << 1) + 1])[x * 16], chr, attr, drawcursor, blink, cga->sc, cga->cgamode); + cga->ma++; + } + } else { /* Graphics mode */ + for (x = 0; x < cga->crtc[1]; x++) { + dat = (cga->vram[((cga->ma << 1) & 0x1fff) + ((cga->sc & 1) * 0x2000)] << 8) | cga->vram[((cga->ma << 1) & 0x1fff) + ((cga->sc & 1) * 0x2000) + 1]; + cga->ma++; + for (uint8_t c = 0; c < 16; c++) { + buffer32->line[cga->displine << 1][(x << 4) + c] = buffer32->line[(cga->displine << 1) + 1][(x << 4) + c] = (dat & 0x8000) ? blue : green; + dat <<= 1; + } + } + } + } else { + if (cga->cgamode & 1) { + hline(buffer32, 0, (cga->displine << 1), (cga->crtc[1] << 3), green); + hline(buffer32, 0, (cga->displine << 1) + 1, (cga->crtc[1] << 3), green); + } else { + hline(buffer32, 0, (cga->displine << 1), (cga->crtc[1] << 4), green); + hline(buffer32, 0, (cga->displine << 1) + 1, (cga->crtc[1] << 4), green); + } + } - if (cga->cgamode & 1) x = (cga->crtc[1] << 3); - else x = (cga->crtc[1] << 4); + if (cga->cgamode & 1) + x = (cga->crtc[1] << 3); + else + x = (cga->crtc[1] << 4); - cga->sc = oldsc; - if (cga->vc == cga->crtc[7] && !cga->sc) - cga->cgastat |= 8; - cga->displine++; - if (cga->displine >= 360) - cga->displine = 0; + cga->sc = oldsc; + if (cga->vc == cga->crtc[7] && !cga->sc) + cga->cgastat |= 8; + cga->displine++; + if (cga->displine >= 360) + cga->displine = 0; } else { - timer_advance_u64(&vid->timer, cga->dispontime); - cga->linepos = 0; - if (cga->vsynctime) { - cga->vsynctime--; - if (!cga->vsynctime) - cga->cgastat &= ~8; - } - if (cga->sc == (cga->crtc[11] & 31) || ((cga->crtc[8] & 3) == 3 && cga->sc == ((cga->crtc[11] & 31) >> 1))) { - cga->con = 0; - cga->coff = 1; - } - if ((cga->crtc[8] & 3) == 3 && cga->sc == (cga->crtc[9] >> 1)) - cga->maback = cga->ma; - if (cga->vadj) { - cga->sc++; - cga->sc &= 31; - cga->ma = cga->maback; - cga->vadj--; - if (!cga->vadj) { - cga->cgadispon = 1; - cga->ma = cga->maback = (cga->crtc[13] | (cga->crtc[12] << 8)) & 0x3fff; - cga->sc = 0; - } - } else if (cga->sc == cga->crtc[9]) { - cga->maback = cga->ma; - cga->sc = 0; - oldvc = cga->vc; - cga->vc++; - cga->vc &= 127; + timer_advance_u64(&vid->timer, cga->dispontime); + cga->linepos = 0; + if (cga->vsynctime) { + cga->vsynctime--; + if (!cga->vsynctime) + cga->cgastat &= ~8; + } + if (cga->sc == (cga->crtc[11] & 31) || ((cga->crtc[8] & 3) == 3 && cga->sc == ((cga->crtc[11] & 31) >> 1))) { + cga->con = 0; + cga->coff = 1; + } + if ((cga->crtc[8] & 3) == 3 && cga->sc == (cga->crtc[9] >> 1)) + cga->maback = cga->ma; + if (cga->vadj) { + cga->sc++; + cga->sc &= 31; + cga->ma = cga->maback; + cga->vadj--; + if (!cga->vadj) { + cga->cgadispon = 1; + cga->ma = cga->maback = (cga->crtc[13] | (cga->crtc[12] << 8)) & 0x3fff; + cga->sc = 0; + } + } else if (cga->sc == cga->crtc[9]) { + cga->maback = cga->ma; + cga->sc = 0; + oldvc = cga->vc; + cga->vc++; + cga->vc &= 127; - if (cga->vc == cga->crtc[6]) - cga->cgadispon = 0; + if (cga->vc == cga->crtc[6]) + cga->cgadispon = 0; - if (oldvc == cga->crtc[4]) { - cga->vc = 0; - cga->vadj = cga->crtc[5]; - if (!cga->vadj) cga->cgadispon = 1; - if (!cga->vadj) cga->ma = cga->maback = (cga->crtc[13] | (cga->crtc[12] << 8)) & 0x3fff; - if ((cga->crtc[10] & 0x60) == 0x20) cga->cursoron = 0; - else cga->cursoron = cga->cgablink & 8; - } + if (oldvc == cga->crtc[4]) { + cga->vc = 0; + cga->vadj = cga->crtc[5]; + if (!cga->vadj) + cga->cgadispon = 1; + if (!cga->vadj) + cga->ma = cga->maback = (cga->crtc[13] | (cga->crtc[12] << 8)) & 0x3fff; + if ((cga->crtc[10] & 0x60) == 0x20) + cga->cursoron = 0; + else + cga->cursoron = cga->cgablink & 8; + } - if (cga->vc == cga->crtc[7]) { - cga->cgadispon = 0; - cga->displine = 0; - cga->vsynctime = 16; - if (cga->crtc[7]) { - if (cga->cgamode & 1) x = (cga->crtc[1] << 3); - else x = (cga->crtc[1] << 4); - cga->lastline++; + if (cga->vc == cga->crtc[7]) { + cga->cgadispon = 0; + cga->displine = 0; + cga->vsynctime = 16; + if (cga->crtc[7]) { + if (cga->cgamode & 1) + x = (cga->crtc[1] << 3); + else + x = (cga->crtc[1] << 4); + cga->lastline++; - xs_temp = x; - ys_temp = (cga->lastline - cga->firstline) << 1; + xs_temp = x; + ys_temp = (cga->lastline - cga->firstline) << 1; - if ((xs_temp > 0) && (ys_temp > 0)) { - if (xs_temp < 64) xs_temp = 640; - if (ys_temp < 32) ys_temp = 400; + if ((xs_temp > 0) && (ys_temp > 0)) { + if (xs_temp < 64) + xs_temp = 640; + if (ys_temp < 32) + ys_temp = 400; - if ((cga->cgamode & 8) && ((xs_temp != xsize) || (ys_temp != ysize) || video_force_resize_get())) { - xsize = xs_temp; - ysize = ys_temp; - set_screen_size(xsize, ysize); + if ((cga->cgamode & 8) && ((xs_temp != xsize) || (ys_temp != ysize) || video_force_resize_get())) { + xsize = xs_temp; + ysize = ys_temp; + set_screen_size(xsize, ysize); - if (video_force_resize_get()) - video_force_resize_set(0); - } + if (video_force_resize_get()) + video_force_resize_set(0); + } - video_blit_memtoscreen(0, cga->firstline << 1, - xsize, (cga->lastline - cga->firstline) << 1); - } + video_blit_memtoscreen(0, cga->firstline << 1, + xsize, (cga->lastline - cga->firstline) << 1); + } - frames++; + frames++; - video_res_x = xsize; - video_res_y = ysize; - if (cga->cgamode & 1) { - video_res_x /= 8; - video_res_y /= cga->crtc[9] + 1; - video_bpp = 0; - } else if (!(cga->cgamode & 2)) { - video_res_x /= 16; - video_res_y /= cga->crtc[9] + 1; - video_bpp = 0; - } else if (!(cga->cgamode & 16)) { - video_res_x /= 2; - video_bpp = 2; - } else - video_bpp = 1; - } - cga->firstline = 1000; - cga->lastline = 0; - cga->cgablink++; - cga->oddeven ^= 1; - } - } else { - cga->sc++; - cga->sc &= 31; - cga->ma = cga->maback; - } - if (cga->cgadispon) - cga->cgastat &= ~1; - if ((cga->sc == (cga->crtc[10] & 31) || ((cga->crtc[8] & 3) == 3 && cga->sc == ((cga->crtc[10] & 31) >> 1)))) - cga->con = 1; - if (cga->cgadispon && (cga->cgamode & 1)) { - for (x = 0; x < (cga->crtc[1] << 1); x++) - cga->charbuffer[x] = cga->vram[(((cga->ma << 1) + x) & 0x3fff)]; - } + video_res_x = xsize; + video_res_y = ysize; + if (cga->cgamode & 1) { + video_res_x /= 8; + video_res_y /= cga->crtc[9] + 1; + video_bpp = 0; + } else if (!(cga->cgamode & 2)) { + video_res_x /= 16; + video_res_y /= cga->crtc[9] + 1; + video_bpp = 0; + } else if (!(cga->cgamode & 16)) { + video_res_x /= 2; + video_bpp = 2; + } else + video_bpp = 1; + } + cga->firstline = 1000; + cga->lastline = 0; + cga->cgablink++; + cga->oddeven ^= 1; + } + } else { + cga->sc++; + cga->sc &= 31; + cga->ma = cga->maback; + } + if (cga->cgadispon) + cga->cgastat &= ~1; + if (cga->sc == (cga->crtc[10] & 31) || ((cga->crtc[8] & 3) == 3 && cga->sc == ((cga->crtc[10] & 31) >> 1))) + cga->con = 1; + if (cga->cgadispon && (cga->cgamode & 1)) { + for (x = 0; x < (cga->crtc[1] << 1); x++) + cga->charbuffer[x] = cga->vram[((cga->ma << 1) + x) & 0x3fff]; + } } } - -static void -vid_poll_200(void *p) +static void +vid_poll_200(void *priv) { - amsvid_t *vid = (amsvid_t *)p; + amsvid_t *vid = (amsvid_t *) priv; switch (vid->emulation) { - case PC200_LCDM: - lcdm_poll(vid); - return; - case PC200_LCDC: - lcdc_poll(vid); - return; + case PC200_LCDM: + lcdm_poll(vid); + return; + case PC200_LCDC: + lcdc_poll(vid); + return; + + default: + break; } } - static void vid_init_200(amstrad_t *ams) { amsvid_t *vid; - cga_t *cga; - mda_t *mda; + cga_t *cga; + mda_t *mda; /* Allocate a video controller block. */ - vid = (amsvid_t *)malloc(sizeof(amsvid_t)); + vid = (amsvid_t *) malloc(sizeof(amsvid_t)); memset(vid, 0x00, sizeof(amsvid_t)); vid->emulation = device_get_config_int("video_emulation"); /* Default to CGA */ - vid->dipswitches = 0x10; - vid->type = ams->type; + vid->dipswitches = 0x10; + vid->type = ams->type; - if (ams->type == AMS_PC200) switch (vid->emulation) { - /* DIP switches for PC200. Switches 2,3 give video emulation. - * Switch 1 is 'swap floppy drives' (not implemented) */ - case PC200_CGA: vid->dipswitches = 0x10; break; - case PC200_MDA: vid->dipswitches = 0x30; break; - case PC200_TV: vid->dipswitches = 0x00; break; - /* The other combination is 'IDA disabled' (0x20) - see - * m_amstrad.c */ - } else switch (vid->emulation) { - /* DIP switches for PPC512. Switch 1 is CRT/LCD. Switch 2 - * is MDA / CGA. Switch 3 disables IDA, not implemented. */ - /* 1 = on, 0 = off - SW1: off = crt, on = lcd; - SW2: off = mda, on = cga; - SW3: off = disable built-in card, on = enable */ - case PC200_CGA: vid->dipswitches = 0x08; break; - case PC200_MDA: vid->dipswitches = 0x18; break; - case PC200_LCDC: vid->dipswitches = 0x00; break; - case PC200_LCDM: vid->dipswitches = 0x10; break; - } + if (ams->type == AMS_PC200) + switch (vid->emulation) { + /* DIP switches for PC200. Switches 2,3 give video emulation. + * Switch 1 is 'swap floppy drives' (not implemented) */ + case PC200_CGA: + vid->dipswitches = 0x10; + break; + case PC200_MDA: + vid->dipswitches = 0x30; + break; + case PC200_TV: + vid->dipswitches = 0x00; + break; + /* The other combination is 'IDA disabled' (0x20) - see + * m_amstrad.c */ - cga = &vid->cga; - mda = &vid->mda; + default: + break; + } + else + switch (vid->emulation) { + /* DIP switches for PPC512. Switch 1 is CRT/LCD. Switch 2 + * is MDA / CGA. Switch 3 disables IDA, not implemented. */ + /* 1 = on, 0 = off + SW1: off = crt, on = lcd; + SW2: off = mda, on = cga; + SW3: off = disable built-in card, on = enable */ + case PC200_CGA: + vid->dipswitches = 0x08; + break; + case PC200_MDA: + vid->dipswitches = 0x18; + break; + case PC200_LCDC: + vid->dipswitches = 0x00; + break; + case PC200_LCDM: + vid->dipswitches = 0x10; + break; + + default: + break; + } + + cga = &vid->cga; + mda = &vid->mda; cga->vram = mda->vram = malloc(0x4000); cga_init(cga); mda_init(mda); @@ -1685,30 +1687,31 @@ vid_init_200(amstrad_t *ams) mda_setcol(0x88, 0, 1, 15); /* Attribute 64 is black on black (on a real MDA it's white on black) */ mda_setcol(0x40, 0, 1, 0); - mda_setcol(0xC0, 0, 1, 0); + mda_setcol(0xC0, 0, 1, 0); cga->fontbase = (device_get_config_int("codepage") & 3) * 256; + mda->fontbase = cga->fontbase; timer_add(&vid->timer, vid_poll_200, vid, 1); - mem_mapping_add(&vid->mda.mapping, 0xb0000, 0x08000, - mda_read, NULL, NULL, mda_write, NULL, NULL, NULL, 0, mda); + mem_mapping_add(&vid->mda.mapping, 0xb0000, 0x08000, + mda_read, NULL, NULL, mda_write, NULL, NULL, NULL, 0, mda); mem_mapping_add(&vid->cga.mapping, 0xb8000, 0x08000, - cga_read, NULL, NULL, cga_write, NULL, NULL, NULL, 0, cga); + cga_read, NULL, NULL, cga_write, NULL, NULL, NULL, 0, cga); io_sethandler(0x03d0, 16, vid_in_200, NULL, NULL, vid_out_200, NULL, NULL, vid); io_sethandler(0x03b0, 0x000c, vid_in_200, NULL, NULL, vid_out_200, NULL, NULL, vid); overscan_x = overscan_y = 16; if (ams->type == AMS_PC200) - vid->invert = 0; + vid->invert = 0; else - vid->invert = device_get_config_int("invert"); + vid->invert = device_get_config_int("invert"); if (vid->invert) { - blue = makecol(0x1C, 0x71, 0x31); - green = makecol(0x0f, 0x21, 0x3f); + blue = makecol(0x1C, 0x71, 0x31); + green = makecol(0x0f, 0x21, 0x3f); } else { - green = makecol(0x1C, 0x71, 0x31); - blue = makecol(0x0f, 0x21, 0x3f); + green = makecol(0x1C, 0x71, 0x31); + blue = makecol(0x0f, 0x21, 0x3f); } cgapal_rebuild(); set_lcd_cols(0); @@ -1717,721 +1720,787 @@ vid_init_200(amstrad_t *ams) timer_disable(&vid->mda.timer); timer_disable(&vid->timer); if (vid->emulation == PC200_CGA || vid->emulation == PC200_TV) - timer_enable(&vid->cga.timer); + timer_enable(&vid->cga.timer); else if (vid->emulation == PC200_MDA) - timer_enable(&vid->mda.timer); + timer_enable(&vid->mda.timer); else - timer_enable(&vid->timer); + timer_enable(&vid->timer); ams->vid = vid; } - static void vid_close_200(void *priv) { - amsvid_t *vid = (amsvid_t *)priv; + amsvid_t *vid = (amsvid_t *) priv; if (vid->cga.vram != vid->mda.vram) { - free(vid->cga.vram); - free(vid->mda.vram); + free(vid->cga.vram); + free(vid->mda.vram); } else - free(vid->cga.vram); + free(vid->cga.vram); vid->cga.vram = vid->mda.vram = NULL; free(vid); } +const device_config_t vid_200_config[] = { + /* TODO: Should have options here for: + * + * > Display port (TTL or RF) + */ + // clang-format off + { + .name = "video_emulation", + .description = "Display type", + .type = CONFIG_SELECTION, + .default_string = "", + .default_int = PC200_CGA, + .file_filter = "", + .spinner = { 0 }, + .selection = { + { .description = "CGA monitor", .value = PC200_CGA }, + { .description = "MDA monitor", .value = PC200_MDA }, + { .description = "Television", .value = PC200_TV }, + { .description = "" } + } + }, + { + .name = "display_type", + .description = "Monitor type", + .type = CONFIG_SELECTION, + .default_string = "", + .default_int = 0, + .file_filter = "", + .spinner = { 0 }, + .selection = { + { .description = "RGB", .value = 0 }, + { .description = "RGB (no brown)", .value = 4 }, + { .description = "Green Monochrome", .value = 1 }, + { .description = "Amber Monochrome", .value = 2 }, + { .description = "White Monochrome", .value = 3 }, + { .description = "" } + } + }, + { + .name = "codepage", + .description = "Hardware font", + .type = CONFIG_SELECTION, + .default_string = "", + .default_int = 3, + .file_filter = "", + .spinner = { 0 }, + .selection = { + { .description = "US English", .value = 3 }, + { .description = "Portugese", .value = 2 }, + { .description = "Norwegian", .value = 1 }, + { .description = "Greek", .value = 0 }, + { .description = "" } + } + }, + { + .name = "language", + .description = "BIOS language", + .type = CONFIG_SELECTION, + .default_string = "", + .default_int = 7, + .file_filter = "", + .spinner = { 0 }, + .selection = { + { .description = "English", .value = 7 }, + { .description = "German", .value = 6 }, + { .description = "French", .value = 5 }, + { .description = "Spanish", .value = 4 }, + { .description = "Danish", .value = 3 }, + { .description = "Swedish", .value = 2 }, + { .description = "Italian", .value = 1 }, + { .description = "Diagnostic mode", .value = 0 }, + { .description = "" } + } + }, + { .name = "", .description = "", .type = CONFIG_END } + // clang-format on +}; -device_config_t vid_200_config[] = -{ - /* TODO: Should have options here for: - * - * > Display port (TTL or RF) - */ - { - "video_emulation", "Display type", CONFIG_SELECTION, "", PC200_CGA, "", { 0 }, - { - { - "CGA monitor", PC200_CGA - }, - { - "MDA monitor", PC200_MDA - }, - { - "Television", PC200_TV - }, - { - "" - } - } - }, - { - "display_type", "Monitor type", CONFIG_SELECTION, "", 0, "", { 0 }, - { - { - "RGB", 0 - }, - { - "RGB (no brown)", 4 - }, - { - "Green Monochrome", 1 - }, - { - "Amber Monochrome", 2 - }, - { - "White Monochrome", 3 - }, - { - "" - } - } +const device_t vid_200_device = { + .name = "Amstrad PC200 (video)", + .internal_name = "vid_200", + .flags = 0, + .local = 0, + .init = NULL, + .close = vid_close_200, + .reset = NULL, + { .available = NULL }, + .speed_changed = vid_speed_changed_200, + .force_redraw = NULL, + .config = vid_200_config +}; + +const device_config_t vid_ppc512_config[] = { + /* TODO: Should have options here for: + * + * > Display port (TTL or RF) + */ + // clang-format off + { + .name = "video_emulation", + .description = "Display type", + .type = CONFIG_SELECTION, + .default_string = "", + .default_int = PC200_LCDC, + .file_filter = "", + .spinner = { 0 }, + .selection = { + { .description = "CGA monitor", .value = PC200_CGA }, + { .description = "MDA monitor", .value = PC200_MDA }, + { .description = "LCD (CGA mode)", .value = PC200_LCDC }, + { .description = "LCD (MDA mode)", .value = PC200_LCDM }, + { .description = "" } }, - { - "codepage", "Hardware font", CONFIG_SELECTION, "", 3, "", { 0 }, - { - { - "US English", 3 - }, - { - "Portugese", 2 - }, - { - "Norwegian", 1 - }, - { - "Greek", 0 - }, - { - "" - } - } - }, - { - "language", "BIOS language", CONFIG_SELECTION, "", 7, "", { 0 }, - { - { - "English", 7 - }, - { - "German", 6 - }, - { - "French", 5 - }, - { - "Spanish", 4 - }, - { - "Danish", 3 - }, - { - "Swedish", 2 - }, - { - "Italian", 1 - }, - { - "Diagnostic mode", 0 - }, - { - "" - } - } - }, - { - "", "", -1 - } -}; - - -static const device_t vid_200_device = { - "Amstrad PC200 (video)", - "vid_200", - 0, 0, - NULL, vid_close_200, NULL, - { NULL }, - vid_speed_changed_200, - NULL, - vid_200_config -}; - - -const device_t * -pc200_get_device(void) -{ - return(&vid_200_device); -} - - -device_config_t vid_ppc512_config[] = -{ - /* TODO: Should have options here for: - * - * > Display port (TTL or RF) - */ - { - "video_emulation", "Display type", CONFIG_SELECTION, "", PC200_LCDC, "", { 0 }, - { - { - "CGA monitor", PC200_CGA - }, - { - "MDA monitor", PC200_MDA - }, - { - "LCD (CGA mode)", PC200_LCDC - }, - { - "LCD (MDA mode)", PC200_LCDM - }, - { - "" - } - }, - }, - { - "display_type", "Monitor type", CONFIG_SELECTION, "", 0, "", { 0 }, - { - { - "RGB", 0 - }, - { - "RGB (no brown)", 4 - }, - { - "Green Monochrome", 1 - }, - { - "Amber Monochrome", 2 - }, - { - "White Monochrome", 3 - }, - { - "" - } - }, + }, + { + .name = "display_type", + .description = "Monitor type", + .type = CONFIG_SELECTION, + .default_string = "", + .default_int = 0, + .file_filter = "", + .spinner = { 0 }, + .selection = { + { .description = "RGB", .value = 0 }, + { .description = "RGB (no brown)", .value = 4 }, + { .description = "Green Monochrome", .value = 1 }, + { .description = "Amber Monochrome", .value = 2 }, + { .description = "White Monochrome", .value = 3 }, + { .description = "" } }, - { - "codepage", "Hardware font", CONFIG_SELECTION, "", 3, "", { 0 }, - { - { - "US English", 3 - }, - { - "Portugese", 2 - }, - { - "Norwegian",1 - }, - { - "Greek", 0 - }, - { - "" - } - }, + }, + { + .name = "codepage", + .description = "Hardware font", + .type = CONFIG_SELECTION, + .default_string = "", + .default_int = 3, + .file_filter = "", + .spinner = { 0 }, + .selection = { + { .description = "US English", .value = 3 }, + { .description = "Portugese", .value = 2 }, + { .description = "Norwegian", .value = 1 }, + { .description = "Greek", .value = 0 }, + { .description = "" } }, - { - "language", "BIOS language", CONFIG_SELECTION, "", 7, "", { 0 }, - { - { - "English", 7 - }, - { - "German", 6 - }, - { - "French", 5 - }, - { - "Spanish", 4 - }, - { - "Danish", 3 - }, - { - "Swedish", 2 - }, - { - "Italian", 1 - }, - { - "Diagnostic mode", 0 - }, - { - "" - } - } - }, - { - "invert", "Invert LCD colors", CONFIG_BINARY, "", 0 - }, - { - "", "", -1 + }, + { + .name = "language", + .description = "BIOS language", + .type = CONFIG_SELECTION, + .default_string = "", + .default_int = 7, + .file_filter = "", + .spinner = { 0 }, + .selection = { + { .description = "English", .value = 7 }, + { .description = "German", .value = 6 }, + { .description = "French", .value = 5 }, + { .description = "Spanish", .value = 4 }, + { .description = "Danish", .value = 3 }, + { .description = "Swedish", .value = 2 }, + { .description = "Italian", .value = 1 }, + { .description = "Diagnostic mode", .value = 0 }, + { .description = "" } } + }, + { + .name = "invert", + .description = "Invert LCD colors", + .type = CONFIG_BINARY, + .default_string = "", + .default_int = 0 + }, + { .name = "", .description = "", .type = CONFIG_END } + // clang-format on }; -static const device_t vid_ppc512_device = { - "Amstrad PPC512 (video)", - "vid_ppc512", - 0, 0, - NULL, vid_close_200, NULL, - { NULL }, - vid_speed_changed_200, - NULL, - vid_ppc512_config +const device_t vid_ppc512_device = { + .name = "Amstrad PPC512 (video)", + .internal_name = "vid_ppc512", + .flags = 0, + .local = 0, + .init = NULL, + .close = vid_close_200, + .reset = NULL, + { .available = NULL }, + .speed_changed = vid_speed_changed_200, + .force_redraw = NULL, + .config = vid_ppc512_config }; - -const device_t * -ppc512_get_device(void) -{ - return(&vid_ppc512_device); -} - - -device_config_t vid_pc2086_config[] = -{ - { - "language", "BIOS language", CONFIG_SELECTION, "", 7, "", { 0 }, - { - { - "English", 7 - }, - { - "Diagnostic mode", 0 - }, - { - "" - } - } - }, - { - "", "", -1 +const device_config_t vid_pc2086_config[] = { + // clang-format off + { + .name = "language", + .description = "BIOS language", + .type = CONFIG_SELECTION, + .default_string = "", + .default_int = 7, + .file_filter = "", + .spinner = { 0 }, + .selection = { + { .description = "English", .value = 7 }, + { .description = "Diagnostic mode", .value = 0 }, + { .description = "" } } + }, + { .name = "", .description = "", .type = CONFIG_END } + // clang-format on }; -static const device_t vid_pc2086_device = { - "Amstrad PC2086", - "vid_pc2086", - 0, 0, - NULL, NULL, NULL, - { NULL }, - NULL, - NULL, - vid_pc2086_config +const device_t vid_pc2086_device = { + .name = "Amstrad PC2086", + .internal_name = "vid_pc2086", + .flags = 0, + .local = 0, + .init = NULL, + .close = NULL, + .reset = NULL, + { .available = NULL }, + .speed_changed = NULL, + .force_redraw = NULL, + .config = vid_pc2086_config }; - -const device_t * -pc2086_get_device(void) -{ - return(&vid_pc2086_device); -} - - -device_config_t vid_pc3086_config[] = -{ - { - "language", "BIOS language", CONFIG_SELECTION, "", 7, "", { 0 }, - { - { - "English", 7 - }, - { - "Diagnostic mode", 3 - }, - { - "" - } - } - }, - { - "", "", -1 +const device_config_t vid_pc3086_config[] = { + // clang-format off + { + .name = "language", + .description = "BIOS language", + .type = CONFIG_SELECTION, + .default_string = "", + .default_int = 7, + .file_filter = "", + .spinner = { 0 }, + .selection = { + { .description = "English", .value = 7 }, + { .description = "Diagnostic mode", .value = 3 }, + { .description = "" } } + }, + { .name = "", .description = "", .type = CONFIG_END } + // clang-format on }; -static const device_t vid_pc3086_device = { - "Amstrad PC3086", - "vid_pc3086", - 0, 0, - NULL, NULL, NULL, - { NULL }, - NULL, - NULL, - vid_pc3086_config +const device_t vid_pc3086_device = { + .name = "Amstrad PC3086", + .internal_name = "vid_pc3086", + .flags = 0, + .local = 0, + .init = NULL, + .close = NULL, + .reset = NULL, + { .available = NULL }, + .speed_changed = NULL, + .force_redraw = NULL, + .config = vid_pc3086_config }; - -const device_t * -pc3086_get_device(void) -{ - return(&vid_pc3086_device); -} - - static void -ms_write(uint16_t addr, uint8_t val, void *priv) +ms_write(uint16_t addr, UNUSED(uint8_t val), UNUSED(void *priv)) { - amstrad_t *ams = (amstrad_t *)priv; - if ((addr == 0x78) || (addr == 0x79)) - ams->mousex = 0; + mouse_clear_x(); else - ams->mousey = 0; + mouse_clear_y(); } - static uint8_t -ms_read(uint16_t addr, void *priv) +ms_read(uint16_t addr, UNUSED(void *priv)) { - amstrad_t *ams = (amstrad_t *)priv; uint8_t ret; + int delta = 0; if ((addr == 0x78) || (addr == 0x79)) { - ret = ams->mousex; - ams->mousex = 0; + mouse_subtract_x(&delta, NULL, -128, 127, 0); + mouse_clear_x(); } else { - ret = ams->mousey; - ams->mousey = 0; + mouse_subtract_y(&delta, NULL, -128, 127, 1, 0); + mouse_clear_y(); } - return(ret); + ret = (uint8_t) (int8_t) delta; + + return ret; } - static int -ms_poll(int x, int y, int z, int b, void *priv) +ms_poll(void *priv) { - amstrad_t *ams = (amstrad_t *)priv; - - ams->mousex += x; - ams->mousey -= y; + amstrad_t *ams = (amstrad_t *) priv; + int b = mouse_get_buttons_ex(); if ((b & 1) && !(ams->oldb & 1)) - keyboard_send(0x7e); + keyboard_send(0x7e); if (!(b & 1) && (ams->oldb & 1)) - keyboard_send(0xfe); + keyboard_send(0xfe); if ((b & 2) && !(ams->oldb & 2)) - keyboard_send(0x7d); + keyboard_send(0x7d); if (!(b & 2) && (ams->oldb & 2)) - keyboard_send(0xfd); + keyboard_send(0xfd); ams->oldb = b; - return(0); + return 0; } - static void kbd_adddata(uint16_t val) { key_queue[key_queue_end] = val; - key_queue_end = (key_queue_end + 1) & 0xf; + key_queue_end = (key_queue_end + 1) & 0xf; } - static void kbd_adddata_ex(uint16_t val) { kbd_adddata_process(val, kbd_adddata); } - static void kbd_write(uint16_t port, uint8_t val, void *priv) { - amstrad_t *ams = (amstrad_t *)priv; + amstrad_t *ams = (amstrad_t *) priv; amstrad_log("keyboard_amstrad : write %04X %02X %02X\n", port, val, ams->pb); switch (port) { - case 0x61: - /* - * PortB - System Control. - * - * 7 Enable Status-1/Disable Keyboard Code on Port A. - * 6 Enable incoming Keyboard Clock. - * 5 Prevent external parity errors from causing NMI. - * 4 Disable parity checking of on-board system Ram. - * 3 Undefined (Not Connected). - * 2 Enable Port C LSB / Disable MSB. (See 1.8.3) - * 1 Speaker Drive. - * 0 8253 GATE 2 (Speaker Modulate). - * - * This register is controlled by BIOS and/or ROS. - */ - amstrad_log("AMSkb: write PB %02x (%02x)\n", val, ams->pb); - if (!(ams->pb & 0x40) && (val & 0x40)) { /*Reset keyboard*/ - amstrad_log("AMSkb: reset keyboard\n"); - kbd_adddata(0xaa); - } - ams->pb = val; - ppi.pb = val; + case 0x61: + /* + * PortB - System Control. + * + * 7 Enable Status-1/Disable Keyboard Code on Port A. + * 6 Enable incoming Keyboard Clock. + * 5 Prevent external parity errors from causing NMI. + * 4 Disable parity checking of on-board system Ram. + * 3 Undefined (Not Connected). + * 2 Enable Port C LSB / Disable MSB. (See 1.8.3) + * 1 Speaker Drive. + * 0 8253 GATE 2 (Speaker Modulate). + * + * This register is controlled by BIOS and/or ROS. + */ + amstrad_log("AMSkb: write PB %02x (%02x)\n", val, ams->pb); + if (!(ams->pb & 0x40) && (val & 0x40)) { /*Reset keyboard*/ + amstrad_log("AMSkb: reset keyboard\n"); + kbd_adddata(0xaa); + } + ams->pb = val; + ppi.pb = val; - speaker_update(); - speaker_gated = val & 0x01; - speaker_enable = val & 0x02; - if (speaker_enable) - was_speaker_enable = 1; - pit_ctr_set_gate(&pit->counters[2], val & 0x01); + speaker_update(); + speaker_gated = val & 0x01; + speaker_enable = val & 0x02; + if (speaker_enable) + was_speaker_enable = 1; + pit_devs[0].set_gate(pit_devs[0].data, 2, val & 0x01); - if (val & 0x80) { - /* Keyboard enabled, so enable PA reading. */ - ams->pa = 0x00; - } - break; + if (val & 0x80) { + /* Keyboard enabled, so enable PA reading. */ + ams->pa = 0x00; + } + break; - case 0x63: - break; + case 0x63: + break; - case 0x64: - ams->stat1 = val; - break; + case 0x64: + ams->stat1 = val; + break; - case 0x65: - ams->stat2 = val; - break; + case 0x65: + ams->stat2 = val; + break; - case 0x66: - softresetx86(); - cpu_set_edx(); - break; + case 0x66: + softresetx86(); + cpu_set_edx(); + break; - default: - amstrad_log("AMSkb: bad keyboard write %04X %02X\n", port, val); + default: + amstrad_log("AMSkb: bad keyboard write %04X %02X\n", port, val); } } - static uint8_t kbd_read(uint16_t port, void *priv) { - amstrad_t *ams = (amstrad_t *)priv; - uint8_t ret = 0xff; + amstrad_t *ams = (amstrad_t *) priv; + uint8_t ret = 0xff; switch (port) { - case 0x60: - if (ams->pb & 0x80) { - /* - * PortA - System Status 1 - * - * 7 Always 0 (KBD7) - * 6 Second Floppy disk drive installed (KBD6) - * 5 DDM1 - Default Display Mode bit 1 (KBD5) - * 4 DDM0 - Default Display Mode bit 0 (KBD4) - * 3 Always 1 (KBD3) - * 2 Always 1 (KBD2) - * 1 8087 NDP installed (KBD1) - * 0 Always 1 (KBD0) - * - * DDM00 - * 00 unknown, external color? - * 01 Color,alpha,40x25, bright white on black. - * 10 Color,alpha,80x25, bright white on black. - * 11 External Monochrome,80x25. - * - * Following a reset, the hardware selects VDU mode - * 2. The ROS then sets the initial VDU state based - * on the DDM value. - */ - ret = (ams->stat1 | 0x0d) & 0x7f; - } else { - ret = ams->pa; - if (key_queue_start == key_queue_end) - ams->wantirq = 0; - else { - ams->key_waiting = key_queue[key_queue_start]; - key_queue_start = (key_queue_start + 1) & 0xf; - ams->wantirq = 1; - } - } - break; + case 0x60: + if (ams->pb & 0x80) { + /* + * PortA - System Status 1 + * + * 7 Always 0 (KBD7) + * 6 Second Floppy disk drive installed (KBD6) + * 5 DDM1 - Default Display Mode bit 1 (KBD5) + * 4 DDM0 - Default Display Mode bit 0 (KBD4) + * 3 Always 1 (KBD3) + * 2 Always 1 (KBD2) + * 1 8087 NDP installed (KBD1) + * 0 Always 1 (KBD0) + * + * DDM00 + * 00 unknown, external color? + * 01 Color,alpha,40x25, bright white on black. + * 10 Color,alpha,80x25, bright white on black. + * 11 External Monochrome,80x25. + * + * Following a reset, the hardware selects VDU mode + * 2. The ROS then sets the initial VDU state based + * on the DDM value. + */ + ret = (ams->stat1 | 0x0d) & 0x7f; + } else { + ret = ams->pa; + if (key_queue_start == key_queue_end) + ams->wantirq = 0; + else { + ams->key_waiting = key_queue[key_queue_start]; + key_queue_start = (key_queue_start + 1) & 0xf; + ams->wantirq = 1; + } + } + break; - case 0x61: - ret = ams->pb; - break; + case 0x61: + ret = ams->pb; + break; - case 0x62: - /* - * PortC - System Status 2. - * - * 7 On-board system RAM parity error. - * 6 External parity error (I/OCHCK from expansion bus). - * 5 8253 PIT OUT2 output. - * 4 Undefined (Not Connected). - *------------------------------------------- - * LSB MSB (depends on PB2) - *------------------------------------------- - * 3 RAM3 Undefined - * 2 RAM2 Undefined - * 1 RAM1 Undefined - * 0 RAM0 RAM4 - * - * PC7 is forced to 0 when on-board system RAM parity - * checking is disabled by PB4. - * - * RAM4:0 - * 01110 512K bytes on-board. - * 01111 544K bytes (32K external). - * 10000 576K bytes (64K external). - * 10001 608K bytes (96K external). - * 10010 640K bytes (128K external or fitted on-board). - */ - if (ams->pb & 0x04) - ret = ams->stat2 & 0x0f; - else - ret = ams->stat2 >> 4; - ret |= (ppispeakon ? 0x20 : 0); - if (nmi) - ret |= 0x40; - break; + case 0x62: + /* + * PortC - System Status 2. + * + * 7 On-board system RAM parity error. + * 6 External parity error (I/OCHCK from expansion bus). + * 5 8253 PIT OUT2 output. + * 4 Undefined (Not Connected). + *------------------------------------------- + * LSB MSB (depends on PB2) + *------------------------------------------- + * 3 RAM3 Undefined + * 2 RAM2 Undefined + * 1 RAM1 Undefined + * 0 RAM0 RAM4 + * + * PC7 is forced to 0 when on-board system RAM parity + * checking is disabled by PB4. + * + * RAM4:0 + * 01110 512K bytes on-board. + * 01111 544K bytes (32K external). + * 10000 576K bytes (64K external). + * 10001 608K bytes (96K external). + * 10010 640K bytes (128K external or fitted on-board). + */ + if (ams->pb & 0x04) + ret = ams->stat2 & 0x0f; + else + ret = ams->stat2 >> 4; + ret |= (ppispeakon ? 0x20 : 0); + if (nmi) + ret |= 0x40; + break; - default: - amstrad_log("AMDkb: bad keyboard read %04X\n", port); + default: + amstrad_log("AMDkb: bad keyboard read %04X\n", port); } - return(ret); + return ret; } - static void kbd_poll(void *priv) { - amstrad_t *ams = (amstrad_t *)priv; + amstrad_t *ams = (amstrad_t *) priv; timer_advance_u64(&ams->send_delay_timer, 1000 * TIMER_USEC); if (ams->wantirq) { - ams->wantirq = 0; - ams->pa = ams->key_waiting; - picint(2); + ams->wantirq = 0; + ams->pa = ams->key_waiting; + picint(2); } if (key_queue_start != key_queue_end && !ams->pa) { - ams->key_waiting = key_queue[key_queue_start]; - key_queue_start = (key_queue_start + 1) & 0x0f; - ams->wantirq = 1; + ams->key_waiting = key_queue[key_queue_start]; + key_queue_start = (key_queue_start + 1) & 0x0f; + ams->wantirq = 1; } } - static void ams_write(uint16_t port, uint8_t val, void *priv) { - amstrad_t *ams = (amstrad_t *)priv; + amstrad_t *ams = (amstrad_t *) priv; switch (port) { - case 0x0378: - case 0x0379: - case 0x037a: - lpt_write(port, val, &lpt_ports[0]); - break; + case 0x0378: + case 0x0379: + case 0x037a: + lpt_write(port, val, &lpt_ports[0]); + break; - case 0xdead: - ams->dead = val; - break; + case 0xdead: + ams->dead = val; + break; + + default: + break; } } - static uint8_t ams_read(uint16_t port, void *priv) { - amstrad_t *ams = (amstrad_t *)priv; - uint8_t ret = 0xff; + amstrad_t *ams = (amstrad_t *) priv; + uint8_t ret = 0xff; switch (port) { - case 0x0378: - ret = lpt_read(port, &lpt_ports[0]); - break; + case 0x0378: + ret = lpt_read(port, &lpt_ports[0]); + break; - case 0x0379: /* printer control, also set LK1-3. - * per John Elliott's site, this is xor'ed with 0x07 - * 7 English Language. - * 6 German Language. - * 5 French Language. - * 4 Spanish Language. - * 3 Danish Language. - * 2 Swedish Language. - * 1 Italian Language. - * 0 Diagnostic Mode. - */ - ret = (lpt_read(port, &lpt_ports[0]) & 0xf8) | ams->language; - break; + case 0x0379: /* printer control, also set LK1-3. + * per John Elliott's site, this is xor'ed with 0x07 + * 7 English Language. + * 6 German Language. + * 5 French Language. + * 4 Spanish Language. + * 3 Danish Language. + * 2 Swedish Language. + * 1 Italian Language. + * 0 Diagnostic Mode. + */ + ret = (lpt_read(port, &lpt_ports[0]) & 0xf8) | ams->language; + break; - case 0x037a: /* printer status */ - ret = lpt_read(port, &lpt_ports[0]) & 0x1f; + case 0x037a: /* printer status */ + ret = lpt_read(port, &lpt_ports[0]) & 0x1f; - switch(ams->type) { - case AMS_PC1512: - ret |= 0x20; - break; + switch (ams->type) { + case AMS_PC1512: + ret |= 0x20; + break; - case AMS_PC200: - case AMS_PPC512: - if (video_is_cga()) - ret |= 0x80; - else if (video_is_mda()) - ret |= 0xc0; + case AMS_PC200: + case AMS_PPC512: + if (video_is_cga()) + ret |= 0x80; + else if (video_is_mda()) + ret |= 0xc0; - if (fdc_read(0x037f, ams->fdc) & 0x80) - ret |= 0x20; - break; + if (fdc_read(0x037f, ams->fdc) & 0x80) + ret |= 0x20; + break; - case AMS_PC1640: - if (video_is_cga()) - ret |= 0x80; - else if (video_is_mda()) - ret |= 0xc0; + case AMS_PC1640: + if (video_is_cga()) + ret |= 0x80; + else if (video_is_mda()) + ret |= 0xc0; - switch (amstrad_latch) { - case AMSTRAD_NOLATCH: - ret &= ~0x20; - break; - case AMSTRAD_SW9: - ret &= ~0x20; - break; - case AMSTRAD_SW10: - ret |= 0x20; - break; - } - break; + switch (amstrad_latch & 0x7fffffff) { + case AMSTRAD_NOLATCH: + ret &= ~0x20; + break; + case AMSTRAD_SW9: + ret &= ~0x20; + break; + case AMSTRAD_SW10: + ret |= 0x20; + break; - default: - break; - } - break; + default: + break; + } + break; - case 0x03de: - ret = 0x20; - break; + default: + break; + } + break; - case 0xdead: - ret = ams->dead; - break; + case 0x03de: + ret = 0x20; + break; + + case 0xdead: + ret = ams->dead; + break; + + default: + break; } - return(ret); + return ret; } +static const scancode scancode_pc200[512] = { + // clang-format off + { { 0},{ 0} }, { { 0x01,0},{ 0x81,0} }, { { 0x02,0},{ 0x82,0} }, { { 0x03,0},{ 0x83,0} }, /*000*/ + { { 0x04,0},{ 0x84,0} }, { { 0x05,0},{ 0x85,0} }, { { 0x06,0},{ 0x86,0} }, { { 0x07,0},{ 0x87,0} }, /*004*/ + { { 0x08,0},{ 0x88,0} }, { { 0x09,0},{ 0x89,0} }, { { 0x0a,0},{ 0x8a,0} }, { { 0x0b,0},{ 0x8b,0} }, /*008*/ + { { 0x0c,0},{ 0x8c,0} }, { { 0x0d,0},{ 0x8d,0} }, { { 0x0e,0},{ 0x8e,0} }, { { 0x0f,0},{ 0x8f,0} }, /*00c*/ + { { 0x10,0},{ 0x90,0} }, { { 0x11,0},{ 0x91,0} }, { { 0x12,0},{ 0x92,0} }, { { 0x13,0},{ 0x93,0} }, /*010*/ + { { 0x14,0},{ 0x94,0} }, { { 0x15,0},{ 0x95,0} }, { { 0x16,0},{ 0x96,0} }, { { 0x17,0},{ 0x97,0} }, /*014*/ + { { 0x18,0},{ 0x98,0} }, { { 0x19,0},{ 0x99,0} }, { { 0x1a,0},{ 0x9a,0} }, { { 0x1b,0},{ 0x9b,0} }, /*018*/ + { { 0x1c,0},{ 0x9c,0} }, { { 0x1d,0},{ 0x9d,0} }, { { 0x1e,0},{ 0x9e,0} }, { { 0x1f,0},{ 0x9f,0} }, /*01c*/ + { { 0x20,0},{ 0xa0,0} }, { { 0x21,0},{ 0xa1,0} }, { { 0x22,0},{ 0xa2,0} }, { { 0x23,0},{ 0xa3,0} }, /*020*/ + { { 0x24,0},{ 0xa4,0} }, { { 0x25,0},{ 0xa5,0} }, { { 0x26,0},{ 0xa6,0} }, { { 0x27,0},{ 0xa7,0} }, /*024*/ + { { 0x28,0},{ 0xa8,0} }, { { 0x29,0},{ 0xa9,0} }, { { 0x2a,0},{ 0xaa,0} }, { { 0x2b,0},{ 0xab,0} }, /*028*/ + { { 0x2c,0},{ 0xac,0} }, { { 0x2d,0},{ 0xad,0} }, { { 0x2e,0},{ 0xae,0} }, { { 0x2f,0},{ 0xaf,0} }, /*02c*/ + { { 0x30,0},{ 0xb0,0} }, { { 0x31,0},{ 0xb1,0} }, { { 0x32,0},{ 0xb2,0} }, { { 0x33,0},{ 0xb3,0} }, /*030*/ + { { 0x34,0},{ 0xb4,0} }, { { 0x35,0},{ 0xb5,0} }, { { 0x36,0},{ 0xb6,0} }, { { 0x37,0},{ 0xb7,0} }, /*034*/ + { { 0x38,0},{ 0xb8,0} }, { { 0x39,0},{ 0xb9,0} }, { { 0x3a,0},{ 0xba,0} }, { { 0x3b,0},{ 0xbb,0} }, /*038*/ + { { 0x3c,0},{ 0xbc,0} }, { { 0x3d,0},{ 0xbd,0} }, { { 0x3e,0},{ 0xbe,0} }, { { 0x3f,0},{ 0xbf,0} }, /*03c*/ + { { 0x40,0},{ 0xc0,0} }, { { 0x41,0},{ 0xc1,0} }, { { 0x42,0},{ 0xc2,0} }, { { 0x43,0},{ 0xc3,0} }, /*040*/ + { { 0x44,0},{ 0xc4,0} }, { { 0x45,0},{ 0xc5,0} }, { { 0x46,0},{ 0xc6,0} }, { { 0x47,0},{ 0xc7,0} }, /*044*/ + { { 0x48,0},{ 0xc8,0} }, { { 0x49,0},{ 0xc9,0} }, { { 0x4a,0},{ 0xca,0} }, { { 0x4b,0},{ 0xcb,0} }, /*048*/ + { { 0x4c,0},{ 0xcc,0} }, { { 0x4d,0},{ 0xcd,0} }, { { 0x4e,0},{ 0xce,0} }, { { 0x4f,0},{ 0xcf,0} }, /*04c*/ + { { 0x50,0},{ 0xd0,0} }, { { 0x51,0},{ 0xd1,0} }, { { 0x52,0},{ 0xd2,0} }, { { 0x53,0},{ 0xd3,0} }, /*050*/ + { { 0x54,0},{ 0xd4,0} }, { { 0x55,0},{ 0xd5,0} }, { { 0x56,0},{ 0xd6,0} }, { { 0x57,0},{ 0xd7,0} }, /*054*/ + { { 0x58,0},{ 0xd8,0} }, { { 0x59,0},{ 0xd9,0} }, { { 0x5a,0},{ 0xda,0} }, { { 0x5b,0},{ 0xdb,0} }, /*058*/ + { { 0x5c,0},{ 0xdc,0} }, { { 0x5d,0},{ 0xdd,0} }, { { 0x5e,0},{ 0xde,0} }, { { 0x5f,0},{ 0xdf,0} }, /*05c*/ + { { 0x60,0},{ 0xe0,0} }, { { 0x61,0},{ 0xe1,0} }, { { 0x62,0},{ 0xe2,0} }, { { 0x63,0},{ 0xe3,0} }, /*060*/ + { { 0x64,0},{ 0xe4,0} }, { { 0x65,0},{ 0xe5,0} }, { { 0x66,0},{ 0xe6,0} }, { { 0x67,0},{ 0xe7,0} }, /*064*/ + { { 0x68,0},{ 0xe8,0} }, { { 0x69,0},{ 0xe9,0} }, { { 0x6a,0},{ 0xea,0} }, { { 0x6b,0},{ 0xeb,0} }, /*068*/ + { { 0x6c,0},{ 0xec,0} }, { { 0x6d,0},{ 0xed,0} }, { { 0x6e,0},{ 0xee,0} }, { { 0x6f,0},{ 0xef,0} }, /*06c*/ + { { 0x70,0},{ 0xf0,0} }, { { 0x71,0},{ 0xf1,0} }, { { 0x72,0},{ 0xf2,0} }, { { 0x73,0},{ 0xf3,0} }, /*070*/ + { { 0x74,0},{ 0xf4,0} }, { { 0x75,0},{ 0xf5,0} }, { { 0x76,0},{ 0xf6,0} }, { { 0x77,0},{ 0xf7,0} }, /*074*/ + { { 0x78,0},{ 0xf8,0} }, { { 0x79,0},{ 0xf9,0} }, { { 0x7a,0},{ 0xfa,0} }, { { 0x7b,0},{ 0xfb,0} }, /*078*/ + { { 0x7c,0},{ 0xfc,0} }, { { 0x7d,0},{ 0xfd,0} }, { { 0x7e,0},{ 0xfe,0} }, { { 0x7f,0},{ 0xff,0} }, /*07c*/ + + { { 0x80,0},{ 0} }, { { 0x81,0},{ 0} }, { { 0x82,0},{ 0} }, { { 0},{ 0} }, /*080*/ + { { 0},{ 0} }, { { 0x85,0},{ 0} }, { { 0x86,0},{ 0} }, { { 0x87,0},{ 0} }, /*084*/ + { { 0x88,0},{ 0} }, { { 0x89,0},{ 0} }, { { 0x8a,0},{ 0} }, { { 0x8b,0},{ 0} }, /*088*/ + { { 0x8c,0},{ 0} }, { { 0x8d,0},{ 0} }, { { 0x8e,0},{ 0} }, { { 0x8f,0},{ 0} }, /*08c*/ + { { 0x90,0},{ 0} }, { { 0x91,0},{ 0} }, { { 0x92,0},{ 0} }, { { 0x93,0},{ 0} }, /*090*/ + { { 0x94,0},{ 0} }, { { 0x95,0},{ 0} }, { { 0x96,0},{ 0} }, { { 0x97,0},{ 0} }, /*094*/ + { { 0x98,0},{ 0} }, { { 0x99,0},{ 0} }, { { 0x9a,0},{ 0} }, { { 0x9b,0},{ 0} }, /*098*/ + { { 0x9c,0},{ 0} }, { { 0x9d,0},{ 0} }, { { 0x9e,0},{ 0} }, { { 0x9f,0},{ 0} }, /*09c*/ + { { 0xa0,0},{ 0} }, { { 0xa1,0},{ 0} }, { { 0xa2,0},{ 0} }, { { 0xa3,0},{ 0} }, /*0a0*/ + { { 0xa4,0},{ 0} }, { { 0xa5,0},{ 0} }, { { 0xa6,0},{ 0} }, { { 0xa7,0},{ 0} }, /*0a4*/ + { { 0xa8,0},{ 0} }, { { 0xa9,0},{ 0} }, { { 0xaa,0},{ 0} }, { { 0xab,0},{ 0} }, /*0a8*/ + { { 0xac,0},{ 0} }, { { 0xad,0},{ 0} }, { { 0xae,0},{ 0} }, { { 0xaf,0},{ 0} }, /*0ac*/ + { { 0xb0,0},{ 0} }, { { 0xb1,0},{ 0} }, { { 0xb2,0},{ 0} }, { { 0xb3,0},{ 0} }, /*0b0*/ + { { 0xb4,0},{ 0} }, { { 0xb5,0},{ 0} }, { { 0xb6,0},{ 0} }, { { 0xb7,0},{ 0} }, /*0b4*/ + { { 0xb8,0},{ 0} }, { { 0xb9,0},{ 0} }, { { 0xba,0},{ 0} }, { { 0xbb,0},{ 0} }, /*0b8*/ + { { 0xbc,0},{ 0} }, { { 0xbd,0},{ 0} }, { { 0xbe,0},{ 0} }, { { 0xbf,0},{ 0} }, /*0bc*/ + { { 0xc0,0},{ 0} }, { { 0xc1,0},{ 0} }, { { 0xc2,0},{ 0} }, { { 0xc3,0},{ 0} }, /*0c0*/ + { { 0xc4,0},{ 0} }, { { 0xc5,0},{ 0} }, { { 0xc6,0},{ 0} }, { { 0xc7,0},{ 0} }, /*0c4*/ + { { 0xc8,0},{ 0} }, { { 0xc9,0},{ 0} }, { { 0xca,0},{ 0} }, { { 0xcb,0},{ 0} }, /*0c8*/ + { { 0xcc,0},{ 0} }, { { 0xcd,0},{ 0} }, { { 0xce,0},{ 0} }, { { 0xcf,0},{ 0} }, /*0cc*/ + { { 0xd0,0},{ 0} }, { { 0xd1,0},{ 0} }, { { 0xd2,0},{ 0} }, { { 0xd3,0},{ 0} }, /*0d0*/ + { { 0xd4,0},{ 0} }, { { 0xd5,0},{ 0} }, { { 0xd6,0},{ 0} }, { { 0xd7,0},{ 0} }, /*0d4*/ + { { 0xd8,0},{ 0} }, { { 0xd9,0},{ 0} }, { { 0xda,0},{ 0} }, { { 0xdb,0},{ 0} }, /*0d8*/ + { { 0xdc,0},{ 0} }, { { 0xdd,0},{ 0} }, { { 0xde,0},{ 0} }, { { 0xdf,0},{ 0} }, /*0dc*/ + { { 0xe0,0},{ 0} }, { { 0xe1,0},{ 0} }, { { 0xe2,0},{ 0} }, { { 0xe3,0},{ 0} }, /*0e0*/ + { { 0xe4,0},{ 0} }, { { 0xe5,0},{ 0} }, { { 0xe6,0},{ 0} }, { { 0xe7,0},{ 0} }, /*0e4*/ + { { 0xe8,0},{ 0} }, { { 0xe9,0},{ 0} }, { { 0xea,0},{ 0} }, { { 0xeb,0},{ 0} }, /*0e8*/ + { { 0xec,0},{ 0} }, { { 0xed,0},{ 0} }, { { 0xee,0},{ 0} }, { { 0xef,0},{ 0} }, /*0ec*/ + { { 0},{ 0} }, { { 0xf1,0},{ 0} }, { { 0xf2,0},{ 0} }, { { 0xf3,0},{ 0} }, /*0f0*/ + { { 0xf4,0},{ 0} }, { { 0xf5,0},{ 0} }, { { 0xf6,0},{ 0} }, { { 0xf7,0},{ 0} }, /*0f4*/ + { { 0xf8,0},{ 0} }, { { 0xf9,0},{ 0} }, { { 0xfa,0},{ 0} }, { { 0xfb,0},{ 0} }, /*0f8*/ + { { 0xfc,0},{ 0} }, { { 0xfd,0},{ 0} }, { { 0xfe,0},{ 0} }, { { 0xff,0},{ 0} }, /*0fc*/ + + { {0xe1,0x1d,0},{0xe1, 0x9d,0} }, { {0xe0,0x01,0},{0xe0, 0x81,0} }, { {0xe0,0x02,0},{0xe0, 0x82,0} }, { {0xe0,0x03,0},{0xe0, 0x83,0} }, /*100*/ + { {0xe0,0x04,0},{0xe0, 0x84,0} }, { {0xe0,0x05,0},{0xe0, 0x85,0} }, { {0xe0,0x06,0},{0xe0, 0x86,0} }, { {0xe0,0x07,0},{0xe0, 0x87,0} }, /*104*/ + { {0xe0,0x08,0},{0xe0, 0x88,0} }, { {0xe0,0x09,0},{0xe0, 0x89,0} }, { {0xe0,0x0a,0},{0xe0, 0x8a,0} }, { {0xe0,0x0b,0},{0xe0, 0x8b,0} }, /*108*/ + { {0xe0,0x0c,0},{0xe0, 0x8c,0} }, { { 0},{ 0} }, { {0xe0,0x0e,0},{0xe0, 0x8e,0} }, { {0xe0,0x0f,0},{0xe0, 0x8f,0} }, /*10c*/ + { {0xe0,0x10,0},{0xe0, 0x90,0} }, { {0xe0,0x11,0},{0xe0, 0x91,0} }, { {0xe0,0x12,0},{0xe0, 0x92,0} }, { {0xe0,0x13,0},{0xe0, 0x93,0} }, /*110*/ + { {0xe0,0x14,0},{0xe0, 0x94,0} }, { {0xe0,0x15,0},{0xe0, 0x95,0} }, { {0xe0,0x16,0},{0xe0, 0x96,0} }, { {0xe0,0x17,0},{0xe0, 0x97,0} }, /*114*/ + { {0xe0,0x18,0},{0xe0, 0x98,0} }, { {0xe0,0x19,0},{0xe0, 0x99,0} }, { {0xe0,0x1a,0},{0xe0, 0x9a,0} }, { {0xe0,0x1b,0},{0xe0, 0x9b,0} }, /*118*/ + { {0xe0,0x1c,0},{0xe0, 0x9c,0} }, { {0xe0,0x1d,0},{0xe0, 0x9d,0} }, { {0xe0,0x1e,0},{0xe0, 0x9e,0} }, { {0xe0,0x1f,0},{0xe0, 0x9f,0} }, /*11c*/ + { {0xe0,0x20,0},{0xe0, 0xa0,0} }, { {0xe0,0x21,0},{0xe0, 0xa1,0} }, { {0xe0,0x22,0},{0xe0, 0xa2,0} }, { {0xe0,0x23,0},{0xe0, 0xa3,0} }, /*120*/ + { {0xe0,0x24,0},{0xe0, 0xa4,0} }, { {0xe0,0x25,0},{0xe0, 0xa5,0} }, { {0xe0,0x26,0},{0xe0, 0xa6,0} }, { { 0},{ 0} }, /*124*/ + { { 0},{ 0} }, { { 0},{ 0} }, { { 0},{ 0} }, { { 0},{ 0} }, /*128*/ + { {0xe0,0x2c,0},{0xe0, 0xac,0} }, { {0xe0,0x2d,0},{0xe0, 0xad,0} }, { {0xe0,0x2e,0},{0xe0, 0xae,0} }, { {0xe0,0x2f,0},{0xe0, 0xaf,0} }, /*12c*/ + { {0xe0,0x30,0},{0xe0, 0xb0,0} }, { {0xe0,0x31,0},{0xe0, 0xb1,0} }, { {0xe0,0x32,0},{0xe0, 0xb2,0} }, { { 0},{ 0} }, /*130*/ + { {0xe0,0x34,0},{0xe0, 0xb4,0} }, { {0xe0,0x35,0},{0xe0, 0xb5,0} }, { { 0},{ 0} }, { {0xe0,0x37,0},{0xe0, 0xb7,0} }, /*134*/ + { {0xe0,0x38,0},{0xe0, 0xb8,0} }, { { 0},{ 0} }, { {0xe0,0x3a,0},{0xe0, 0xba,0} }, { {0xe0,0x3b,0},{0xe0, 0xbb,0} }, /*138*/ + { {0xe0,0x3c,0},{0xe0, 0xbc,0} }, { {0xe0,0x3d,0},{0xe0, 0xbd,0} }, { {0xe0,0x3e,0},{0xe0, 0xbe,0} }, { {0xe0,0x3f,0},{0xe0, 0xbf,0} }, /*13c*/ + { {0xe0,0x40,0},{0xe0, 0xc0,0} }, { {0xe0,0x41,0},{0xe0, 0xc1,0} }, { {0xe0,0x42,0},{0xe0, 0xc2,0} }, { {0xe0,0x43,0},{0xe0, 0xc3,0} }, /*140*/ + { {0xe0,0x44,0},{0xe0, 0xc4,0} }, { { 0},{ 0} }, { {0xe0,0x46,0},{0xe0, 0xc6,0} }, { {0xe0,0x47,0},{0xe0, 0xc7,0} }, /*144*/ + { {0xe0,0x48,0},{0xe0, 0xc8,0} }, { {0xe0,0x49,0},{0xe0, 0xc9,0} }, { { 0},{ 0} }, { {0xe0,0x4b,0},{0xe0, 0xcb,0} }, /*148*/ + { {0xe0,0x4c,0},{0xe0, 0xcc,0} }, { {0xe0,0x4d,0},{0xe0, 0xcd,0} }, { {0xe0,0x4e,0},{0xe0, 0xce,0} }, { {0xe0,0x4f,0},{0xe0, 0xcf,0} }, /*14c*/ + { {0xe0,0x50,0},{0xe0, 0xd0,0} }, { {0xe0,0x51,0},{0xe0, 0xd1,0} }, { {0xe0,0x52,0},{0xe0, 0xd2,0} }, { {0xe0,0x53,0},{0xe0, 0xd3,0} }, /*150*/ + { { 0},{ 0} }, { {0xe0,0x55,0},{0xe0, 0xd5,0} }, { { 0},{ 0} }, { {0xe0,0x57,0},{0xe0, 0xd7,0} }, /*154*/ + { {0xe0,0x58,0},{0xe0, 0xd8,0} }, { {0xe0,0x59,0},{0xe0, 0xd9,0} }, { {0xe0,0x5a,0},{0xe0, 0xaa,0} }, { {0xe0,0x5b,0},{0xe0, 0xdb,0} }, /*158*/ + { {0xe0,0x5c,0},{0xe0, 0xdc,0} }, { {0xe0,0x5d,0},{0xe0, 0xdd,0} }, { {0xe0,0x5e,0},{0xe0, 0xee,0} }, { {0xe0,0x5f,0},{0xe0, 0xdf,0} }, /*15c*/ + { { 0},{ 0} }, { {0xe0,0x61,0},{0xe0, 0xe1,0} }, { {0xe0,0x62,0},{0xe0, 0xe2,0} }, { {0xe0,0x63,0},{0xe0, 0xe3,0} }, /*160*/ + { {0xe0,0x64,0},{0xe0, 0xe4,0} }, { {0xe0,0x65,0},{0xe0, 0xe5,0} }, { {0xe0,0x66,0},{0xe0, 0xe6,0} }, { {0xe0,0x67,0},{0xe0, 0xe7,0} }, /*164*/ + { {0xe0,0x68,0},{0xe0, 0xe8,0} }, { {0xe0,0x69,0},{0xe0, 0xe9,0} }, { {0xe0,0x6a,0},{0xe0, 0xea,0} }, { {0xe0,0x6b,0},{0xe0, 0xeb,0} }, /*168*/ + { {0xe0,0x6c,0},{0xe0, 0xec,0} }, { {0xe0,0x6d,0},{0xe0, 0xed,0} }, { {0xe0,0x6e,0},{0xe0, 0xee,0} }, { { 0},{ 0} }, /*16c*/ + { {0xe0,0x70,0},{0xe0, 0xf0,0} }, { {0xe0,0x71,0},{0xe0, 0xf1,0} }, { {0xe0,0x72,0},{0xe0, 0xf2,0} }, { {0xe0,0x73,0},{0xe0, 0xf3,0} }, /*170*/ + { {0xe0,0x74,0},{0xe0, 0xf4,0} }, { {0xe0,0x75,0},{0xe0, 0xf5,0} }, { { 0},{ 0} }, { {0xe0,0x77,0},{0xe0, 0xf7,0} }, /*174*/ + { {0xe0,0x78,0},{0xe0, 0xf8,0} }, { {0xe0,0x79,0},{0xe0, 0xf9,0} }, { {0xe0,0x7a,0},{0xe0, 0xfa,0} }, { {0xe0,0x7b,0},{0xe0, 0xfb,0} }, /*178*/ + { {0xe0,0x7c,0},{0xe0, 0xfc,0} }, { {0xe0,0x7d,0},{0xe0, 0xfd,0} }, { {0xe0,0x7e,0},{0xe0, 0xfe,0} }, { {0xe0,0x7f,0},{0xe0, 0xff,0} }, /*17c*/ + + { { 0},{ 0} }, { { 0},{ 0} }, { { 0},{ 0} }, { { 0},{ 0} }, /*180*/ + { { 0},{ 0} }, { { 0},{ 0} }, { { 0},{ 0} }, { { 0},{ 0} }, /*184*/ + { { 0},{ 0} }, { { 0},{ 0} }, { { 0},{ 0} }, { { 0},{ 0} }, /*188*/ + { { 0},{ 0} }, { { 0},{ 0} }, { { 0},{ 0} }, { { 0},{ 0} }, /*18c*/ + { { 0},{ 0} }, { { 0},{ 0} }, { { 0},{ 0} }, { { 0},{ 0} }, /*190*/ + { { 0},{ 0} }, { { 0},{ 0} }, { { 0},{ 0} }, { { 0},{ 0} }, /*194*/ + { { 0},{ 0} }, { { 0},{ 0} }, { { 0},{ 0} }, { { 0},{ 0} }, /*198*/ + { { 0},{ 0} }, { { 0},{ 0} }, { { 0},{ 0} }, { { 0},{ 0} }, /*19c*/ + { { 0},{ 0} }, { { 0},{ 0} }, { { 0},{ 0} }, { { 0},{ 0} }, /*1a0*/ + { { 0},{ 0} }, { { 0},{ 0} }, { { 0},{ 0} }, { { 0},{ 0} }, /*1a4*/ + { { 0},{ 0} }, { { 0},{ 0} }, { { 0},{ 0} }, { { 0},{ 0} }, /*1a8*/ + { { 0},{ 0} }, { { 0},{ 0} }, { { 0},{ 0} }, { { 0},{ 0} }, /*1ac*/ + { { 0},{ 0} }, { { 0},{ 0} }, { { 0},{ 0} }, { { 0},{ 0} }, /*1c0*/ + { { 0},{ 0} }, { { 0},{ 0} }, { { 0},{ 0} }, { { 0},{ 0} }, /*1c4*/ + { { 0},{ 0} }, { { 0},{ 0} }, { { 0},{ 0} }, { { 0},{ 0} }, /*1c8*/ + { { 0},{ 0} }, { { 0},{ 0} }, { { 0},{ 0} }, { { 0},{ 0} }, /*1cc*/ + { { 0},{ 0} }, { { 0},{ 0} }, { { 0},{ 0} }, { { 0},{ 0} }, /*1d0*/ + { { 0},{ 0} }, { { 0},{ 0} }, { { 0},{ 0} }, { { 0},{ 0} }, /*1d4*/ + { { 0},{ 0} }, { { 0},{ 0} }, { { 0},{ 0} }, { { 0},{ 0} }, /*1d8*/ + { { 0},{ 0} }, { { 0},{ 0} }, { { 0},{ 0} }, { { 0},{ 0} }, /*1dc*/ + { { 0},{ 0} }, { {0xe0,0xe1,0},{ 0} }, { { 0},{ 0} }, { { 0},{ 0} }, /*1e0*/ + { { 0},{ 0} }, { { 0},{ 0} }, { { 0},{ 0} }, { { 0},{ 0} }, /*1e4*/ + { { 0},{ 0} }, { { 0},{ 0} }, { { 0},{ 0} }, { { 0},{ 0} }, /*1e8*/ + { { 0},{ 0} }, { { 0},{ 0} }, { {0xe0,0xee,0},{ 0} }, { { 0},{ 0} }, /*1ec*/ + { { 0},{ 0} }, { {0xe0,0xf1,0},{ 0} }, { { 0},{ 0} }, { { 0},{ 0} }, /*1f0*/ + { { 0},{ 0} }, { { 0},{ 0} }, { { 0},{ 0} }, { { 0},{ 0} }, /*1f4*/ + { { 0},{ 0} }, { { 0},{ 0} }, { { 0},{ 0} }, { { 0},{ 0} }, /*1f8*/ + { { 0},{ 0} }, { { 0},{ 0} }, { {0xe0,0xfe,0},{ 0} }, { {0xe0,0xff,0},{ 0} } /*1fc*/ + // clang-format on +}; static void machine_amstrad_init(const machine_t *model, int type) { amstrad_t *ams; - ams = (amstrad_t *)malloc(sizeof(amstrad_t)); + ams = (amstrad_t *) malloc(sizeof(amstrad_t)); memset(ams, 0x00, sizeof(amstrad_t)); - ams->type = type; + ams->type = type; + amstrad_latch = 0x80000000; - device_add(&amstrad_nvr_device); + switch (type) { + case AMS_PC200: + case AMS_PPC512: + device_add(&amstrad_no_nmi_nvr_device); + break; + + default: + device_add(&amstrad_nvr_device); + break; + } machine_common_init(model); @@ -2441,213 +2510,219 @@ machine_amstrad_init(const machine_t *model, int type) lpt2_remove(); io_sethandler(0x0378, 3, - ams_read, NULL, NULL, ams_write, NULL, NULL, ams); + ams_read, NULL, NULL, ams_write, NULL, NULL, ams); io_sethandler(0xdead, 1, - ams_read, NULL, NULL, ams_write, NULL, NULL, ams); + ams_read, NULL, NULL, ams_write, NULL, NULL, ams); - switch(type) { - case AMS_PC1512: - case AMS_PC1640: - case AMS_PC200: - case AMS_PPC512: - ams->fdc = device_add(&fdc_xt_device); - break; + switch (type) { + case AMS_PC1512: + case AMS_PC1640: + case AMS_PC200: + case AMS_PPC512: + ams->fdc = device_add(&fdc_xt_device); + break; - case AMS_PC2086: - case AMS_PC3086: - ams->fdc = device_add(&fdc_at_actlow_device); - break; + case AMS_PC2086: + case AMS_PC3086: + ams->fdc = device_add(&fdc_at_actlow_device); + break; + + default: + break; } ams->language = 7; - video_reset(gfxcard); + video_reset(gfxcard[0]); - if (gfxcard == VID_INTERNAL) switch(type) { - case AMS_PC1512: - loadfont("roms/machines/pc1512/40078", 8); - device_context(&vid_1512_device); - ams->language = device_get_config_int("language"); - vid_init_1512(ams); - device_context_restore(); - device_add_ex(&vid_1512_device, ams->vid); - break; - - case AMS_PPC512: - loadfont("roms/machines/ppc512/40109", 1); - device_context(&vid_ppc512_device); - ams->language = device_get_config_int("language"); - vid_init_200(ams); - device_context_restore(); - device_add_ex(&vid_ppc512_device, ams->vid); - break; - - case AMS_PC1640: - loadfont("roms/video/mda/mda.rom", 0); - device_context(&vid_1640_device); - ams->language = device_get_config_int("language"); - vid_init_1640(ams); - device_context_restore(); - device_add_ex(&vid_1640_device, ams->vid); - break; + if (gfxcard[0] == VID_INTERNAL) + switch (type) { + case AMS_PC1512: + loadfont("roms/machines/pc1512/40078", 8); + device_context(&vid_1512_device); + ams->language = device_get_config_int("language"); + vid_init_1512(ams); + device_context_restore(); + device_add_ex(&vid_1512_device, ams->vid); + break; - case AMS_PC200: - loadfont("roms/machines/pc200/40109", 1); - device_context(&vid_200_device); - ams->language = device_get_config_int("language"); - vid_init_200(ams); - device_context_restore(); - device_add_ex(&vid_200_device, ams->vid); - break; + case AMS_PPC512: + loadfont("roms/machines/ppc512/40109", 1); + device_context(&vid_ppc512_device); + ams->language = device_get_config_int("language"); + vid_init_200(ams); + device_context_restore(); + device_add_ex(&vid_ppc512_device, ams->vid); + break; - case AMS_PC2086: - device_context(&vid_pc2086_device); - ams->language = device_get_config_int("language"); - device_context_restore(); - device_add(¶dise_pvga1a_pc2086_device); - break; + case AMS_PC1640: + loadfont("roms/video/mda/mda.rom", 0); + device_context(&vid_1640_device); + ams->language = device_get_config_int("language"); + vid_init_1640(ams); + device_context_restore(); + device_add_ex(&vid_1640_device, ams->vid); + break; - case AMS_PC3086: - device_context(&vid_pc3086_device); - ams->language = device_get_config_int("language"); - device_context_restore(); - device_add(¶dise_pvga1a_pc3086_device); - break; - } else if ((type == AMS_PC200) || (type == AMS_PPC512)) - io_sethandler(0x03de, 1, - ams_read, NULL, NULL, ams_write, NULL, NULL, ams); + case AMS_PC200: + loadfont("roms/machines/pc200/40109", 1); + device_context(&vid_200_device); + ams->language = device_get_config_int("language"); + vid_init_200(ams); + device_context_restore(); + device_add_ex(&vid_200_device, ams->vid); + break; + + case AMS_PC2086: + device_context(&vid_pc2086_device); + ams->language = device_get_config_int("language"); + device_context_restore(); + device_add(¶dise_pvga1a_pc2086_device); + break; + + case AMS_PC3086: + device_context(&vid_pc3086_device); + ams->language = device_get_config_int("language"); + device_context_restore(); + device_add(¶dise_pvga1a_pc3086_device); + break; + + default: + break; + } + else if ((type == AMS_PC200) || (type == AMS_PPC512)) + io_sethandler(0x03de, 1, + ams_read, NULL, NULL, ams_write, NULL, NULL, ams); /* Initialize the (custom) keyboard/mouse interface. */ ams->wantirq = 0; io_sethandler(0x0060, 7, - kbd_read, NULL, NULL, kbd_write, NULL, NULL, ams); + kbd_read, NULL, NULL, kbd_write, NULL, NULL, ams); timer_add(&ams->send_delay_timer, kbd_poll, ams, 1); - keyboard_set_table(scancode_xt); + if (type == AMS_PC1512) + keyboard_set_table(scancode_xt); + else + keyboard_set_table(scancode_pc200); keyboard_send = kbd_adddata_ex; keyboard_scan = 1; keyboard_set_is_amstrad(((type == AMS_PC1512) || (type == AMS_PC1640)) ? 0 : 1); io_sethandler(0x0078, 2, - ms_read, NULL, NULL, ms_write, NULL, NULL, ams); + ms_read, NULL, NULL, ms_write, NULL, NULL, ams); io_sethandler(0x007a, 2, - ms_read, NULL, NULL, ms_write, NULL, NULL, ams); + ms_read, NULL, NULL, ms_write, NULL, NULL, ams); if (mouse_type == MOUSE_TYPE_INTERNAL) { - /* Tell mouse driver about our internal mouse. */ - mouse_reset(); - mouse_set_poll(ms_poll, ams); + /* Tell mouse driver about our internal mouse. */ + mouse_reset(); + mouse_set_buttons(2); + mouse_set_poll(ms_poll, ams); } standalone_gameport_type = &gameport_device; } - int machine_pc1512_init(const machine_t *model) { int ret; ret = bios_load_interleaved("roms/machines/pc1512/40044", - "roms/machines/pc1512/40043", - 0x000fc000, 16384, 0); + "roms/machines/pc1512/40043", + 0x000fc000, 16384, 0); ret &= rom_present("roms/machines/pc1512/40078"); if (bios_only || !ret) - return ret; + return ret; machine_amstrad_init(model, AMS_PC1512); return ret; } - int machine_pc1640_init(const machine_t *model) { int ret; ret = bios_load_interleaved("roms/machines/pc1640/40044.v3", - "roms/machines/pc1640/40043.v3", - 0x000fc000, 16384, 0); + "roms/machines/pc1640/40043.v3", + 0x000fc000, 16384, 0); ret &= rom_present("roms/machines/pc1640/40100"); if (bios_only || !ret) - return ret; + return ret; machine_amstrad_init(model, AMS_PC1640); return ret; } - int machine_pc200_init(const machine_t *model) { int ret; ret = bios_load_interleaved("roms/machines/pc200/pc20v2.1", - "roms/machines/pc200/pc20v2.0", - 0x000fc000, 16384, 0); + "roms/machines/pc200/pc20v2.0", + 0x000fc000, 16384, 0); ret &= rom_present("roms/machines/pc200/40109"); if (bios_only || !ret) - return ret; + return ret; machine_amstrad_init(model, AMS_PC200); return ret; } - int machine_ppc512_init(const machine_t *model) { int ret; ret = bios_load_interleaved("roms/machines/ppc512/40107.v2", - "roms/machines/ppc512/40108.v2", - 0x000fc000, 16384, 0); + "roms/machines/ppc512/40108.v2", + 0x000fc000, 16384, 0); ret &= rom_present("roms/machines/ppc512/40109"); if (bios_only || !ret) - return ret; + return ret; machine_amstrad_init(model, AMS_PPC512); return ret; } - int machine_pc2086_init(const machine_t *model) { int ret; ret = bios_load_interleavedr("roms/machines/pc2086/40179.ic129", - "roms/machines/pc2086/40180.ic132", - 0x000fc000, 65536, 0); + "roms/machines/pc2086/40180.ic132", + 0x000fc000, 65536, 0); ret &= rom_present("roms/machines/pc2086/40186.ic171"); if (bios_only || !ret) - return ret; + return ret; machine_amstrad_init(model, AMS_PC2086); return ret; } - int machine_pc3086_init(const machine_t *model) { int ret; ret = bios_load_linearr("roms/machines/pc3086/fc00.bin", - 0x000fc000, 65536, 0); + 0x000fc000, 65536, 0); ret &= rom_present("roms/machines/pc3086/c000.bin"); if (bios_only || !ret) - return ret; + return ret; machine_amstrad_init(model, AMS_PC3086); diff --git a/src/machine/m_at.c b/src/machine/m_at.c index dc47b6207..9fc53ebcd 100644 --- a/src/machine/m_at.c +++ b/src/machine/m_at.c @@ -1,22 +1,22 @@ /* - * VARCem Virtual ARchaeological Computer EMulator. - * An emulator of (mostly) x86-based PC systems and devices, - * using the ISA,EISA,VLB,MCA and PCI system buses, roughly - * spanning the era between 1981 and 1995. + * 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 VARCem Project. + * This file is part of the 86Box distribution. * - * Standard PC/AT implementation. + * Standard PC/AT implementation. * * * - * Authors: Fred N. van Kempen, - * Miran Grca, - * Sarah Walker, + * Authors: Fred N. van Kempen, + * Miran Grca, + * Sarah Walker, * - * Copyright 2017-2020 Fred N. van Kempen. - * Copyright 2016-2020 Miran Grca. - * Copyright 2008-2020 Sarah Walker. + * Copyright 2017-2020 Fred N. van Kempen. + * Copyright 2016-2020 Miran Grca. + * Copyright 2008-2020 Sarah Walker. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -35,7 +35,8 @@ * 59 Temple Place - Suite 330 * Boston, MA 02111-1307 * USA. -*/ + */ + #include #include #include @@ -59,37 +60,34 @@ #include <86box/port_6x.h> #include <86box/machine.h> - void machine_at_common_init_ex(const machine_t *model, int type) { machine_common_init(model); refresh_at_enable = 1; - pit_ctr_set_out_func(&pit->counters[1], pit_refresh_timer_at); + pit_devs[0].set_out_func(pit_devs[0].data, 1, pit_refresh_timer_at); pic2_init(); dma16_init(); if (!(type & 4)) - device_add(&port_6x_device); + device_add(&port_6x_device); type &= 3; if (type == 1) - device_add(&ibmat_nvr_device); + device_add(&ibmat_nvr_device); else if (type == 0) - device_add(&at_nvr_device); + device_add(&at_nvr_device); standalone_gameport_type = &gameport_device; } - void machine_at_common_init(const machine_t *model) { machine_at_common_init_ex(model, 0); } - void machine_at_init(const machine_t *model) { @@ -98,7 +96,6 @@ machine_at_init(const machine_t *model) device_add(&keyboard_at_device); } - static void machine_at_ibm_common_init(const machine_t *model) { @@ -109,10 +106,9 @@ machine_at_ibm_common_init(const machine_t *model) mem_remap_top(384); if (fdc_type == FDC_INTERNAL) - device_add(&fdc_at_device); + device_add(&fdc_at_device); } - void machine_at_ps2_init(const machine_t *model) { @@ -121,7 +117,6 @@ machine_at_ps2_init(const machine_t *model) device_add(&keyboard_ps2_device); } - void machine_at_common_ide_init(const machine_t *model) { @@ -130,7 +125,6 @@ machine_at_common_ide_init(const machine_t *model) device_add(&ide_isa_device); } - void machine_at_ibm_common_ide_init(const machine_t *model) { @@ -139,7 +133,6 @@ machine_at_ibm_common_ide_init(const machine_t *model) device_add(&ide_isa_device); } - void machine_at_ide_init(const machine_t *model) { @@ -148,7 +141,6 @@ machine_at_ide_init(const machine_t *model) device_add(&ide_isa_device); } - void machine_at_ps2_ide_init(const machine_t *model) { @@ -157,25 +149,23 @@ machine_at_ps2_ide_init(const machine_t *model) device_add(&ide_isa_device); } - int machine_at_ibm_init(const machine_t *model) { int ret; ret = bios_load_interleaved("roms/machines/ibmat/62x0820.u27", - "roms/machines/ibmat/62x0821.u47", - 0x000f0000, 65536, 0); + "roms/machines/ibmat/62x0821.u47", + 0x000f0000, 65536, 0); if (bios_only || !ret) - return ret; + return ret; machine_at_ibm_common_init(model); return ret; } - /* IBM AT machines with custom BIOSes */ int machine_at_ibmatquadtel_init(const machine_t *model) @@ -183,65 +173,62 @@ machine_at_ibmatquadtel_init(const machine_t *model) int ret; ret = bios_load_interleaved("roms/machines/ibmatquadtel/BIOS_30MAR90_U27_QUADTEL_ENH_286_BIOS_3.05.01_27256.BIN", - "roms/machines/ibmatquadtel/BIOS_30MAR90_U47_QUADTEL_ENH_286_BIOS_3.05.01_27256.BIN", - 0x000f0000, 65536, 0); + "roms/machines/ibmatquadtel/BIOS_30MAR90_U47_QUADTEL_ENH_286_BIOS_3.05.01_27256.BIN", + 0x000f0000, 65536, 0); if (bios_only || !ret) - return ret; + return ret; machine_at_ibm_common_init(model); return ret; } - int machine_at_ibmatami_init(const machine_t *model) { int ret; ret = bios_load_interleaved("roms/machines/ibmatami/BIOS_5170_30APR89_U27_AMI_27256.BIN", - "roms/machines/ibmatami/BIOS_5170_30APR89_U47_AMI_27256.BIN", - 0x000f0000, 65536, 0); + "roms/machines/ibmatami/BIOS_5170_30APR89_U47_AMI_27256.BIN", + 0x000f0000, 65536, 0); if (bios_only || !ret) - return ret; + return ret; machine_at_ibm_common_init(model); return ret; } - int machine_at_ibmatpx_init(const machine_t *model) { int ret; ret = bios_load_interleaved("roms/machines/ibmatpx/BIOS ROM - PhoenixBIOS A286 - Version 1.01 - Even.bin", - "roms/machines/ibmatpx/BIOS ROM - PhoenixBIOS A286 - Version 1.01 - Odd.bin", - 0x000f0000, 65536, 0); + "roms/machines/ibmatpx/BIOS ROM - PhoenixBIOS A286 - Version 1.01 - Odd.bin", + 0x000f0000, 65536, 0); if (bios_only || !ret) - return ret; + return ret; machine_at_ibm_common_init(model); return ret; } - int machine_at_ibmxt286_init(const machine_t *model) { int ret; ret = bios_load_interleaved("roms/machines/ibmxt286/bios_5162_21apr86_u34_78x7460_27256.bin", - "roms/machines/ibmxt286/bios_5162_21apr86_u35_78x7461_27256.bin", - 0x000f0000, 65536, 0); + "roms/machines/ibmxt286/bios_5162_21apr86_u35_78x7461_27256.bin", + 0x000f0000, 65536, 0); if (bios_only || !ret) - return ret; + return ret; machine_at_ibm_common_init(model); @@ -254,17 +241,23 @@ machine_at_siemens_init(const machine_t *model) int ret; ret = bios_load_linear("roms/machines/siemens/286BIOS.BIN", - 0x000f0000, 65536, 0); + 0x000f0000, 65536, 0); if (bios_only || !ret) - return ret; + return ret; - machine_at_ibm_common_init(model); + machine_at_common_init_ex(model, 1); + + device_add(&keyboard_at_siemens_device); + + mem_remap_top(384); + + if (fdc_type == FDC_INTERNAL) + device_add(&fdc_at_device); return ret; } - #if defined(DEV_BRANCH) && defined(USE_OPEN_AT) int machine_at_openat_init(const machine_t *model) @@ -272,10 +265,10 @@ machine_at_openat_init(const machine_t *model) int ret; ret = bios_load_linear("roms/machines/openat/bios.bin", - 0x000f0000, 65536, 0); + 0x000f0000, 65536, 0); if (bios_only || !ret) - return ret; + return ret; machine_at_ibm_common_init(model); diff --git a/src/machine/m_at_286_386sx.c b/src/machine/m_at_286_386sx.c index 05c700fb8..c7b1acb0c 100644 --- a/src/machine/m_at_286_386sx.c +++ b/src/machine/m_at_286_386sx.c @@ -1,22 +1,20 @@ /* - * 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. + * 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. + * This file is part of the 86Box distribution. * - * Implementation of 286 and 386SX machines. + * Implementation of 286 and 386SX machines. * * * - * Authors: Sarah Walker, - * Miran Grca, - * EngiNerd + * Authors: Miran Grca, + * EngiNerd * - * Copyright 2010-2019 Sarah Walker. - * Copyright 2016-2019 Miran Grca. - * Copyright 2020 EngiNerd. + * Copyright 2016-2019 Miran Grca. + * Copyright 2020 EngiNerd. */ #include #include @@ -37,6 +35,7 @@ #include <86box/fdc.h> #include <86box/fdc_ext.h> #include <86box/hdc.h> +#include <86box/nvr.h> #include <86box/port_6x.h> #include <86box/sio.h> #include <86box/serial.h> @@ -51,34 +50,35 @@ machine_at_mr286_init(const machine_t *model) int ret; ret = bios_load_interleaved("roms/machines/mr286/V000B200-1", - "roms/machines/mr286/V000B200-2", - 0x000f0000, 65536, 0); + "roms/machines/mr286/V000B200-2", + 0x000f0000, 65536, 0); if (bios_only || !ret) - return ret; + return ret; machine_at_common_ide_init(model); device_add(&keyboard_at_device); if (fdc_type == FDC_INTERNAL) - device_add(&fdc_at_device); + device_add(&fdc_at_device); return ret; } - static void -machine_at_headland_common_init(int ht386) +machine_at_headland_common_init(int type) { device_add(&keyboard_at_ami_device); if (fdc_type == FDC_INTERNAL) - device_add(&fdc_at_device); + device_add(&fdc_at_device); - if (ht386) - device_add(&headland_ht18b_device); + if (type == 2) + device_add(&headland_ht18b_device); + else if (type == 1) + device_add(&headland_gc113_device); else - device_add(&headland_gc10x_device); + device_add(&headland_gc10x_device); } int @@ -87,158 +87,145 @@ machine_at_tg286m_init(const machine_t *model) int ret; ret = bios_load_linear("roms/machines/tg286m/ami.bin", - 0x000f0000, 131072, 0); + 0x000f0000, 131072, 0); if (bios_only || !ret) - return ret; + return ret; machine_at_common_ide_init(model); - machine_at_headland_common_init(0); + machine_at_headland_common_init(1); return ret; } - -const device_t * -at_ama932j_get_device(void) -{ - return &oti067_ama932j_device; -} - - int machine_at_ama932j_init(const machine_t *model) { int ret; ret = bios_load_linear("roms/machines/ama932j/ami.bin", - 0x000f0000, 131072, 0); + 0x000f0000, 131072, 0); if (bios_only || !ret) - return ret; + return ret; machine_at_common_ide_init(model); - if (gfxcard == VID_INTERNAL) - device_add(&oti067_ama932j_device); + if (gfxcard[0] == VID_INTERNAL) + device_add(&oti067_ama932j_device); - machine_at_headland_common_init(1); + machine_at_headland_common_init(2); return ret; } - int machine_at_quadt286_init(const machine_t *model) { int ret; ret = bios_load_interleaved("roms/machines/quadt286/QUADT89L.ROM", - "roms/machines/quadt286/QUADT89H.ROM", - 0x000f0000, 65536, 0); + "roms/machines/quadt286/QUADT89H.ROM", + 0x000f0000, 65536, 0); if (bios_only || !ret) - return ret; + return ret; machine_at_common_init(model); - device_add(&keyboard_at_device); + device_add(&keyboard_at_device); if (fdc_type == FDC_INTERNAL) - device_add(&fdc_at_device); + device_add(&fdc_at_device); device_add(&headland_gc10x_device); return ret; } - int machine_at_quadt386sx_init(const machine_t *model) { int ret; ret = bios_load_interleaved("roms/machines/quadt386sx/QTC-SXM-EVEN-U3-05-07.BIN", - "roms/machines/quadt386sx/QTC-SXM-ODD-U3-05-07.BIN", - 0x000f0000, 65536, 0); + "roms/machines/quadt386sx/QTC-SXM-ODD-U3-05-07.BIN", + 0x000f0000, 65536, 0); if (bios_only || !ret) - return ret; + return ret; machine_at_common_init(model); device_add(&keyboard_at_device); if (fdc_type == FDC_INTERNAL) - device_add(&fdc_at_device); + device_add(&fdc_at_device); device_add(&headland_gc10x_device); return ret; } - int machine_at_neat_init(const machine_t *model) { int ret; ret = bios_load_linear("roms/machines/dtk386/3cto001.bin", - 0x000f0000, 65536, 0); + 0x000f0000, 65536, 0); if (bios_only || !ret) - return ret; + return ret; machine_at_init(model); device_add(&neat_device); if (fdc_type == FDC_INTERNAL) - device_add(&fdc_at_device); + device_add(&fdc_at_device); return ret; } - int machine_at_neat_ami_init(const machine_t *model) { int ret; ret = bios_load_linear("roms/machines/ami286/AMIC206.BIN", - 0x000f0000, 65536, 0); + 0x000f0000, 65536, 0); if (bios_only || !ret) - return ret; + return ret; machine_at_common_init(model); device_add(&neat_device); if (fdc_type == FDC_INTERNAL) - device_add(&fdc_at_device); + device_add(&fdc_at_device); device_add(&keyboard_at_ami_device); return ret; } - int machine_at_px286_init(const machine_t *model) { int ret; - ret = bios_load_linear("roms/machines/px286/KENITEC.BIN", - 0x000f0000, 65536, 0); + ret = bios_load_linear("roms/machines/px286/KENITEC.BIN", + 0x000f0000, 65536, 0); if (bios_only || !ret) - return ret; + return ret; machine_at_common_init(model); device_add(&keyboard_at_device); if (fdc_type == FDC_INTERNAL) - device_add(&fdc_at_device); + device_add(&fdc_at_device); device_add(&neat_device); @@ -251,36 +238,43 @@ machine_at_micronics386_init(const machine_t *model) int ret; ret = bios_load_interleaved("roms/machines/micronics386/386-Micronics-09-00021-EVEN.BIN", - "roms/machines/micronics386/386-Micronics-09-00021-ODD.BIN", - 0x000f0000, 131072, 0); + "roms/machines/micronics386/386-Micronics-09-00021-ODD.BIN", + 0x000f0000, 65536, 0); if (bios_only || !ret) - return ret; + return ret; machine_at_init(model); - device_add(&neat_device); - if (fdc_type == FDC_INTERNAL) - device_add(&fdc_at_device); + device_add(&fdc_at_device); return ret; } - static void -machine_at_scat_init(const machine_t *model, int is_v4) +machine_at_scat_init(const machine_t *model, int is_v4, int is_ami) { machine_at_common_init(model); - device_add(&keyboard_at_ami_device); + + if (machines[machine].bus_flags & MACHINE_BUS_PS2) { + if (is_ami) + device_add(&keyboard_ps2_ami_device); + else + device_add(&keyboard_ps2_device); + } else { + if (is_ami) + device_add(&keyboard_at_ami_device); + else + device_add(&keyboard_at_device); + } if (is_v4) - device_add(&scat_4_device); + device_add(&scat_4_device); else - device_add(&scat_device); + device_add(&scat_device); } - static void machine_at_scatsx_init(const machine_t *model) { @@ -289,27 +283,26 @@ machine_at_scatsx_init(const machine_t *model) device_add(&keyboard_at_ami_device); if (fdc_type == FDC_INTERNAL) - device_add(&fdc_at_device); + device_add(&fdc_at_device); device_add(&scat_sx_device); } - int machine_at_award286_init(const machine_t *model) { int ret; ret = bios_load_linear("roms/machines/award286/award.bin", - 0x000f0000, 131072, 0); + 0x000f0000, 131072, 0); if (bios_only || !ret) - return ret; + return ret; - machine_at_scat_init(model, 0); + machine_at_scat_init(model, 0, 1); if (fdc_type == FDC_INTERNAL) - device_add(&fdc_at_device); + device_add(&fdc_at_device); return ret; } @@ -320,15 +313,15 @@ machine_at_gdc212m_init(const machine_t *model) int ret; ret = bios_load_linear("roms/machines/gdc212m/gdc212m_72h.bin", - 0x000f0000, 65536, 0); + 0x000f0000, 65536, 0); if (bios_only || !ret) - return ret; + return ret; - machine_at_scat_init(model, 0); + machine_at_scat_init(model, 0, 1); if (fdc_type == FDC_INTERNAL) - device_add(&fdc_at_device); + device_add(&fdc_at_device); device_add(&ide_isa_device); @@ -341,164 +334,147 @@ machine_at_gw286ct_init(const machine_t *model) int ret; ret = bios_load_linear("roms/machines/gw286ct/2ctc001.bin", - 0x000f0000, 131072, 0); + 0x000f0000, 131072, 0); if (bios_only || !ret) - return ret; + return ret; device_add(&f82c710_device); - machine_at_common_init(model); - device_add(&keyboard_at_device); - - device_add(&scat_4_device); + machine_at_scat_init(model, 1, 0); device_add(&ide_isa_device); return ret; } - int machine_at_super286tr_init(const machine_t *model) { int ret; ret = bios_load_linear("roms/machines/super286tr/hyundai_award286.bin", - 0x000f0000, 131072, 0); + 0x000f0000, 131072, 0); if (bios_only || !ret) - return ret; + return ret; - machine_at_scat_init(model, 0); + machine_at_scat_init(model, 0, 1); if (fdc_type == FDC_INTERNAL) - device_add(&fdc_at_device); + device_add(&fdc_at_device); return ret; } - int machine_at_spc4200p_init(const machine_t *model) { int ret; ret = bios_load_linear("roms/machines/spc4200p/u8.01", - 0x000f0000, 131072, 0); + 0x000f0000, 131072, 0); if (bios_only || !ret) - return ret; + return ret; - machine_at_scat_init(model, 0); + machine_at_scat_init(model, 0, 1); if (fdc_type == FDC_INTERNAL) - device_add(&fdc_at_device); + device_add(&fdc_at_device); return ret; } - int machine_at_spc4216p_init(const machine_t *model) { int ret; ret = bios_load_interleaved("roms/machines/spc4216p/7101.U8", - "roms/machines/spc4216p/AC64.U10", - 0x000f0000, 131072, 0); + "roms/machines/spc4216p/AC64.U10", + 0x000f0000, 131072, 0); if (bios_only || !ret) - return ret; + return ret; - machine_at_scat_init(model, 1); + machine_at_scat_init(model, 1, 1); if (fdc_type == FDC_INTERNAL) - device_add(&fdc_at_device); + device_add(&fdc_at_device); return ret; } - -const device_t * -at_spc4620p_get_device(void) -{ - return &ati28800k_spc4620p_device; -} - - int machine_at_spc4620p_init(const machine_t *model) { int ret; ret = bios_load_interleaved("roms/machines/spc4620p/31005h.u8", - "roms/machines/spc4620p/31005h.u10", - 0x000f0000, 131072, 0x8000); + "roms/machines/spc4620p/31005h.u10", + 0x000f0000, 131072, 0x8000); if (bios_only || !ret) - return ret; + return ret; - if (gfxcard == VID_INTERNAL) - device_add(&ati28800k_spc4620p_device); + if (gfxcard[0] == VID_INTERNAL) + device_add(&ati28800k_spc4620p_device); - machine_at_scat_init(model, 1); + machine_at_scat_init(model, 1, 1); if (fdc_type == FDC_INTERNAL) - device_add(&fdc_at_device); + device_add(&fdc_at_device); return ret; } - int machine_at_kmxc02_init(const machine_t *model) { int ret; ret = bios_load_linear("roms/machines/kmxc02/3ctm005.bin", - 0x000f0000, 131072, 0); + 0x000f0000, 131072, 0); if (bios_only || !ret) - return ret; + return ret; machine_at_scatsx_init(model); return ret; } - int machine_at_deskmaster286_init(const machine_t *model) { int ret; ret = bios_load_linear("roms/machines/deskmaster286/SAMSUNG-DESKMASTER-28612-ROM.BIN", - 0x000f0000, 131072, 0); + 0x000f0000, 131072, 0); if (bios_only || !ret) - return ret; + return ret; - machine_at_scat_init(model, 0); + machine_at_scat_init(model, 0, 1); if (fdc_type == FDC_INTERNAL) - device_add(&fdc_at_device); + device_add(&fdc_at_device); return ret; } - int machine_at_shuttle386sx_init(const machine_t *model) { int ret; ret = bios_load_interleaved("roms/machines/shuttle386sx/386-Shuttle386SX-Even.BIN", - "roms/machines/shuttle386sx/386-Shuttle386SX-Odd.BIN", - 0x000f0000, 131072, 0); + "roms/machines/shuttle386sx/386-Shuttle386SX-Odd.BIN", + 0x000f0000, 131072, 0); if (bios_only || !ret) - return ret; + return ret; machine_at_common_init(model); @@ -506,52 +482,51 @@ machine_at_shuttle386sx_init(const machine_t *model) device_add(&keyboard_at_ami_device); if (fdc_type == FDC_INTERNAL) - device_add(&fdc_at_device); + device_add(&fdc_at_device); return ret; } - int machine_at_adi386sx_init(const machine_t *model) { int ret; ret = bios_load_interleaved("roms/machines/adi386sx/3iip001l.bin", - "roms/machines/adi386sx/3iip001h.bin", - 0x000f0000, 65536, 0); + "roms/machines/adi386sx/3iip001h.bin", + 0x000f0000, 65536, 0); if (bios_only || !ret) - return ret; + return ret; - machine_at_common_init(model); + machine_at_common_init_ex(model, 2); + device_add(&amstrad_megapc_nvr_device); /* NVR that is initialized to all 0x00's. */ device_add(&intel_82335_device); device_add(&keyboard_at_ami_device); if (fdc_type == FDC_INTERNAL) - device_add(&fdc_at_device); + device_add(&fdc_at_device); return ret; } - int machine_at_wd76c10_init(const machine_t *model) { int ret; ret = bios_load_interleaved("roms/machines/megapc/41651-bios lo.u18", - "roms/machines/megapc/211253-bios hi.u19", - 0x000f0000, 65536, 0x08000); + "roms/machines/megapc/211253-bios hi.u19", + 0x000f0000, 65536, 0x08000); if (bios_only || !ret) - return ret; + return ret; machine_at_common_init(model); - if (gfxcard == VID_INTERNAL) - device_add(¶dise_wd90c11_megapc_device); + if (gfxcard[0] == VID_INTERNAL) + device_add(¶dise_wd90c11_megapc_device); device_add(&keyboard_ps2_quadtel_device); @@ -560,25 +535,24 @@ machine_at_wd76c10_init(const machine_t *model) return ret; } - int machine_at_cmdsl386sx16_init(const machine_t *model) { int ret; ret = bios_load_interleaved("roms/machines/cmdsl386sx16/cbm-sl386sx-bios-lo-v1.04-390914-04.bin", - "roms/machines/cmdsl386sx16/cbm-sl386sx-bios-hi-v1.04-390915-04.bin", - 0x000f0000, 65536, 0); + "roms/machines/cmdsl386sx16/cbm-sl386sx-bios-hi-v1.04-390915-04.bin", + 0x000f0000, 65536, 0); if (bios_only || !ret) - return ret; + return ret; machine_at_common_ide_init(model); device_add(&keyboard_at_device); if (fdc_type == FDC_INTERNAL) - device_add(&fdc_at_device); + device_add(&fdc_at_device); device_add(&neat_device); /* Two serial ports - on the real hardware SL386SX-16, they are on the single UMC UM82C452. */ @@ -588,127 +562,107 @@ machine_at_cmdsl386sx16_init(const machine_t *model) return ret; } - static void machine_at_scamp_common_init(const machine_t *model, int is_ps2) { machine_at_common_ide_init(model); if (is_ps2) - device_add(&keyboard_ps2_ami_device); + device_add(&keyboard_ps2_ami_device); else - device_add(&keyboard_at_ami_device); + device_add(&keyboard_at_ami_device); if (fdc_type == FDC_INTERNAL) - device_add(&fdc_at_device); + device_add(&fdc_at_device); device_add(&vlsi_scamp_device); } - -const device_t * -at_cmdsl386sx25_get_device(void) -{ - return &gd5402_onboard_device; -} - - int machine_at_cmdsl386sx25_init(const machine_t *model) { int ret; ret = bios_load_linear("roms/machines/cmdsl386sx25/f000.rom", - 0x000f0000, 65536, 0); + 0x000f0000, 65536, 0); if (bios_only || !ret) - return ret; + return ret; - if (gfxcard == VID_INTERNAL) - device_add(&gd5402_onboard_device); + if (gfxcard[0] == VID_INTERNAL) + device_add(&gd5402_onboard_device); machine_at_scamp_common_init(model, 1); return ret; } - int machine_at_dataexpert386sx_init(const machine_t *model) { int ret; ret = bios_load_linear("roms/machines/dataexpert386sx/5e9f20e5ef967717086346.BIN", - 0x000f0000, 65536, 0); + 0x000f0000, 65536, 0); if (bios_only || !ret) - return ret; + return ret; machine_at_scamp_common_init(model, 0); return ret; } - -const device_t * -at_spc6033p_get_device(void) -{ - return &ati28800k_spc6033p_device; -} - - int machine_at_spc6033p_init(const machine_t *model) { int ret; ret = bios_load_linear("roms/machines/spc6033p/phoenix.BIN", - 0x000f0000, 65536, 0x10000); + 0x000f0000, 65536, 0x10000); if (bios_only || !ret) - return ret; + return ret; - if (gfxcard == VID_INTERNAL) - device_add(&ati28800k_spc6033p_device); + if (gfxcard[0] == VID_INTERNAL) + device_add(&ati28800k_spc6033p_device); machine_at_scamp_common_init(model, 1); return ret; } - int machine_at_awardsx_init(const machine_t *model) { int ret; ret = bios_load_linear("roms/machines/awardsx/Unknown 386SX OPTi291 - Award (original).BIN", - 0x000f0000, 65536, 0); + 0x000f0000, 65536, 0); if (bios_only || !ret) - return ret; + return ret; machine_at_init(model); device_add(&opti291_device); if (fdc_type == FDC_INTERNAL) - device_add(&fdc_at_device); + device_add(&fdc_at_device); return ret; } - int machine_at_arb1374_init(const machine_t *model) { int ret; ret = bios_load_linear("roms/machines/arb1374/1374s.rom", - 0x000f0000, 65536, 0); + 0x000f0000, 65536, 0); if (bios_only || !ret) - return ret; + return ret; machine_at_common_init(model); @@ -719,17 +673,16 @@ machine_at_arb1374_init(const machine_t *model) return ret; } - int machine_at_sbc350a_init(const machine_t *model) { int ret; ret = bios_load_linear("roms/machines/sbc350a/350a.rom", - 0x000f0000, 65536, 0); + 0x000f0000, 65536, 0); if (bios_only || !ret) - return ret; + return ret; machine_at_common_init(model); @@ -740,71 +693,60 @@ machine_at_sbc350a_init(const machine_t *model) return ret; } - int machine_at_flytech386_init(const machine_t *model) { int ret; ret = bios_load_linear("roms/machines/flytech386/FLYTECH.BIO", - 0x000f0000, 65536, 0); + 0x000f0000, 65536, 0); if (bios_only || !ret) - return ret; + return ret; machine_at_common_init(model); device_add(&ali1217_device); device_add(&w83787f_ide_en_device); - if (gfxcard == VID_INTERNAL) - device_add(&tvga8900d_device); + if (gfxcard[0] == VID_INTERNAL) + device_add(&tvga8900d_device); device_add(&keyboard_ps2_device); return ret; } - -const device_t * -at_flytech386_get_device(void) -{ - return &tvga8900d_device; -} - - int machine_at_mr1217_init(const machine_t *model) { int ret; ret = bios_load_linear("roms/machines/mr1217/mrbios.BIN", - 0x000f0000, 65536, 0); + 0x000f0000, 65536, 0); if (bios_only || !ret) - return ret; + return ret; - machine_at_common_init(model); + machine_at_common_ide_init(model); device_add(&ali1217_device); device_add(&fdc_at_device); - device_add(&ide_isa_device); device_add(&keyboard_ps2_device); return ret; } - int machine_at_pja511m_init(const machine_t *model) { int ret; ret = bios_load_linear("roms/machines/pja511m/2006915102435734.rom", - 0x000e0000, 131072, 0); + 0x000e0000, 131072, 0); if (bios_only || !ret) - return ret; + return ret; machine_at_common_init(model); @@ -817,17 +759,16 @@ machine_at_pja511m_init(const machine_t *model) return ret; } - int machine_at_prox1332_init(const machine_t *model) { int ret; ret = bios_load_linear("roms/machines/prox1332/D30B3AC1.BIN", - 0x000e0000, 131072, 0); + 0x000e0000, 131072, 0); if (bios_only || !ret) - return ret; + return ret; machine_at_common_init(model); @@ -839,9 +780,8 @@ machine_at_prox1332_init(const machine_t *model) return ret; } - /* - * Current bugs: + * Current bugs: * - ctrl-alt-del produces an 8042 error */ int @@ -850,59 +790,53 @@ machine_at_pc8_init(const machine_t *model) int ret; ret = bios_load_interleaved("roms/machines/pc8/ncr_35117_u127_vers.4-2.bin", - "roms/machines/pc8/ncr_35116_u113_vers.4-2.bin", - 0x000f0000, 65536, 0); + "roms/machines/pc8/ncr_35116_u113_vers.4-2.bin", + 0x000f0000, 65536, 0); if (bios_only || !ret) - return ret; + return ret; machine_at_common_init(model); device_add(&keyboard_at_ncr_device); if (fdc_type == FDC_INTERNAL) - device_add(&fdc_at_device); - + device_add(&fdc_at_device); + return ret; } - -/* - * Current bugs: - * - ctrl-alt-del produces an 8042 error - */ int machine_at_3302_init(const machine_t *model) { int ret; ret = bios_load_linear("roms/machines/3302/f000-flex_drive_test.bin", - 0x000f0000, 65536, 0); + 0x000f0000, 65536, 0); if (ret) { - bios_load_aux_linear("roms/machines/3302/f800-setup_ncr3.5-013190.bin", - 0x000f8000, 32768, 0); + ret &= bios_load_aux_linear("roms/machines/3302/f800-setup_ncr3.5-013190.bin", + 0x000f8000, 32768, 0); } if (bios_only || !ret) - return ret; + return ret; machine_at_common_ide_init(model); device_add(&neat_device); if (fdc_type == FDC_INTERNAL) - device_add(&fdc_at_device); + device_add(&fdc_at_device); - if (gfxcard == VID_INTERNAL) - device_add(¶dise_pvga1a_ncr3302_device); + if (gfxcard[0] == VID_INTERNAL) + device_add(¶dise_pvga1a_ncr3302_device); device_add(&keyboard_at_ncr_device); - + return ret; } - /* - * Current bugs: + * Current bugs: * - soft-reboot after saving CMOS settings/pressing ctrl-alt-del produces an 8042 error */ int @@ -911,24 +845,23 @@ machine_at_pc916sx_init(const machine_t *model) int ret; ret = bios_load_interleaved("roms/machines/pc916sx/ncr_386sx_u46-17_7.3.bin", - "roms/machines/pc916sx/ncr_386sx_u12-19_7.3.bin", - 0x000f0000, 65536, 0); + "roms/machines/pc916sx/ncr_386sx_u12-19_7.3.bin", + 0x000f0000, 65536, 0); if (bios_only || !ret) - return ret; + return ret; machine_at_common_init(model); - + device_add(&keyboard_at_ncr_device); mem_remap_top(384); if (fdc_type == FDC_INTERNAL) - device_add(&fdc_at_device); - + device_add(&fdc_at_device); + return ret; } - #if defined(DEV_BRANCH) && defined(USE_OLIVETTI) int machine_at_m290_init(const machine_t *model) @@ -936,20 +869,20 @@ machine_at_m290_init(const machine_t *model) int ret; ret = bios_load_linear("roms/machines/m290/m290_pep3_1.25.bin", - 0x000f0000, 65536, 0); + 0x000f0000, 65536, 0); if (bios_only || !ret) - return ret; + return ret; machine_at_common_init_ex(model, 4); device_add(&keyboard_at_olivetti_device); device_add(&port_6x_olivetti_device); if (fdc_type == FDC_INTERNAL) - device_add(&fdc_at_device); - + device_add(&fdc_at_device); + device_add(&olivetti_eva_device); - + return ret; } #endif diff --git a/src/machine/m_at_386dx_486.c b/src/machine/m_at_386dx_486.c index 9bb4ff21e..10f82e4ed 100644 --- a/src/machine/m_at_386dx_486.c +++ b/src/machine/m_at_386dx_486.c @@ -1,20 +1,18 @@ /* - * 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. + * 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. + * This file is part of the 86Box distribution. * - * Implementation of 386DX and 486 machines. + * Implementation of 386DX and 486 machines. * * * - * Authors: Sarah Walker, - * Miran Grca, + * Authors: Miran Grca, * - * Copyright 2010-2020 Sarah Walker. - * Copyright 2016-2020 Miran Grca. + * Copyright 2016-2020 Miran Grca. */ #include #include @@ -48,52 +46,50 @@ #include <86box/scsi_ncr53c8xx.h> #include <86box/hwm.h> #include <86box/machine.h> - +#include <86box/plat_unused.h> int machine_at_acc386_init(const machine_t *model) { int ret; - ret = bios_load_linear("roms/machines/acc386/acc386.BIN", - 0x000f0000, 65536, 0); + ret = bios_load_linear("roms/machines/acc386/acc386.BIN", + 0x000f0000, 65536, 0); if (bios_only || !ret) - return ret; + return ret; machine_at_common_init(model); device_add(&acc2168_device); device_add(&keyboard_at_ami_device); if (fdc_type == FDC_INTERNAL) - device_add(&fdc_at_device); + device_add(&fdc_at_device); return ret; } - int machine_at_asus386_init(const machine_t *model) { int ret; - ret = bios_load_linear("roms/machines/asus386/ASUS_ISA-386C_BIOS.bin", - 0x000f0000, 65536, 0); + ret = bios_load_linear("roms/machines/asus386/ASUS_ISA-386C_BIOS.bin", + 0x000f0000, 65536, 0); if (bios_only || !ret) - return ret; + return ret; machine_at_common_init(model); device_add(&rabbit_device); device_add(&keyboard_at_ami_device); if (fdc_type == FDC_INTERNAL) - device_add(&fdc_at_device); + device_add(&fdc_at_device); return ret; } - static void machine_at_sis401_common_init(const machine_t *model) { @@ -102,156 +98,142 @@ machine_at_sis401_common_init(const machine_t *model) device_add(&keyboard_at_ami_device); if (fdc_type == FDC_INTERNAL) - device_add(&fdc_at_device); + device_add(&fdc_at_device); } - int machine_at_sis401_init(const machine_t *model) { int ret; ret = bios_load_linear("roms/machines/sis401/SIS401-2.AMI", - 0x000f0000, 65536, 0); + 0x000f0000, 65536, 0); if (bios_only || !ret) - return ret; + return ret; machine_at_sis401_common_init(model); return ret; } - int machine_at_isa486_init(const machine_t *model) { int ret; ret = bios_load_linear("roms/machines/isa486/ISA-486.BIN", - 0x000f0000, 65536, 0); + 0x000f0000, 65536, 0); if (bios_only || !ret) - return ret; + return ret; machine_at_sis401_common_init(model); return ret; } - int machine_at_av4_init(const machine_t *model) { int ret; ret = bios_load_linear("roms/machines/av4/amibios_486dx_isa_bios_aa4025963.bin", - 0x000f0000, 65536, 0); + 0x000f0000, 65536, 0); if (bios_only || !ret) - return ret; + return ret; machine_at_common_ide_init(model); device_add(&sis_85c460_device); device_add(&keyboard_at_ami_device); if (fdc_type == FDC_INTERNAL) - device_add(&fdc_at_device); + device_add(&fdc_at_device); return ret; } - int -machine_at_valuepoint433_init(const machine_t *model) // hangs without the PS/2 mouse +machine_at_valuepoint433_init(const machine_t *model) // hangs without the PS/2 mouse { int ret; ret = bios_load_linear("roms/machines/valuepoint433/$IMAGEP.FLH", - 0x000e0000, 131072, 0); + 0x000e0000, 131072, 0); if (bios_only || !ret) - return ret; + return ret; machine_at_common_ide_init(model); device_add(&sis_85c461_device); - if (gfxcard == VID_INTERNAL) - device_add(&et4000w32_onboard_device); + if (gfxcard[0] == VID_INTERNAL) + device_add(&et4000w32_onboard_device); device_add(&keyboard_ps2_device); if (fdc_type == FDC_INTERNAL) - device_add(&fdc_at_device); + device_add(&fdc_at_device); return ret; } - -const device_t * -at_valuepoint433_get_device(void) -{ - return &et4000w32_onboard_device; -} - - int machine_at_ecs386_init(const machine_t *model) { int ret; ret = bios_load_interleaved("roms/machines/ecs386/AMI BIOS for ECS-386_32 motherboard - L chip.bin", - "roms/machines/ecs386/AMI BIOS for ECS-386_32 motherboard - H chip.bin", - 0x000f0000, 65536, 0); + "roms/machines/ecs386/AMI BIOS for ECS-386_32 motherboard - H chip.bin", + 0x000f0000, 65536, 0); if (bios_only || !ret) - return ret; + return ret; machine_at_common_init(model); device_add(&cs8230_device); if (fdc_type == FDC_INTERNAL) - device_add(&fdc_at_device); + device_add(&fdc_at_device); device_add(&keyboard_at_ami_device); return ret; } - int machine_at_spc6000a_init(const machine_t *model) { int ret; ret = bios_load_interleaved("roms/machines/spc6000a/3c80.u27", - "roms/machines/spc6000a/9f80.u26", - 0x000f8000, 32768, 0); + "roms/machines/spc6000a/9f80.u26", + 0x000f8000, 32768, 0); if (bios_only || !ret) - return ret; + return ret; machine_at_common_init_ex(model, 1); device_add(&cs8230_device); if (fdc_type == FDC_INTERNAL) - device_add(&fdc_at_device); + device_add(&fdc_at_device); device_add(&keyboard_at_ami_device); return ret; } - int machine_at_rycleopardlx_init(const machine_t *model) { int ret; ret = bios_load_linear("roms/machines/rycleopardlx/486-RYC-Leopard-LX.BIN", - 0x000f0000, 65536, 0); + 0x000f0000, 65536, 0); if (bios_only || !ret) - return ret; + return ret; machine_at_common_init(model); @@ -259,22 +241,21 @@ machine_at_rycleopardlx_init(const machine_t *model) device_add(&keyboard_at_ami_device); if (fdc_type == FDC_INTERNAL) - device_add(&fdc_at_device); + device_add(&fdc_at_device); return ret; } - int machine_at_486vchd_init(const machine_t *model) { int ret; ret = bios_load_linear("roms/machines/486vchd/486-4386-VC-HD.BIN", - 0x000f0000, 65536, 0); + 0x000f0000, 65536, 0); if (bios_only || !ret) - return ret; + return ret; machine_at_common_init(model); @@ -282,44 +263,42 @@ machine_at_486vchd_init(const machine_t *model) device_add(&keyboard_at_device); if (fdc_type == FDC_INTERNAL) - device_add(&fdc_at_device); + device_add(&fdc_at_device); return ret; } - int machine_at_cs4031_init(const machine_t *model) { int ret; - ret = bios_load_linear("roms/machines/cs4031/CHIPS_1.AMI", - 0x000f0000, 65536, 0); + ret = bios_load_linear("roms/machines/cs4031/CHIPS_1.AMI", + 0x000f0000, 65536, 0); if (bios_only || !ret) - return ret; + return ret; machine_at_common_init(model); device_add(&cs4031_device); device_add(&keyboard_at_ami_device); if (fdc_type == FDC_INTERNAL) - device_add(&fdc_at_device); + device_add(&fdc_at_device); return ret; } - int machine_at_pb410a_init(const machine_t *model) { int ret; ret = bios_load_linear("roms/machines/pb410a/pb410a.080337.4abf.u25.bin", - 0x000e0000, 131072, 0); + 0x000e0000, 131072, 0); if (bios_only || !ret) - return ret; + return ret; machine_at_ibm_common_ide_init(model); @@ -330,30 +309,29 @@ machine_at_pb410a_init(const machine_t *model) device_add(&phoenix_486_jumper_device); - if (gfxcard == VID_INTERNAL) - device_add(&ht216_32_pb410a_device); + if (gfxcard[0] == VID_INTERNAL) + device_add(&ht216_32_pb410a_device); return ret; } - int -machine_at_vect486vl_init(const machine_t *model) // has HDC problems +machine_at_vect486vl_init(const machine_t *model) // has HDC problems { int ret; - ret = bios_load_linear("roms/machines/vect486vl/aa0500.ami", - 0x000e0000, 131072, 0); + ret = bios_load_linear("roms/machines/vect486vl/aa0500.ami", + 0x000e0000, 131072, 0); if (bios_only || !ret) - return ret; + return ret; machine_at_common_ide_init(model); device_add(&vl82c480_device); - if (gfxcard == VID_INTERNAL) - device_add(&gd5428_onboard_device); + if (gfxcard[0] == VID_INTERNAL) + device_add(&gd5428_onboard_device); device_add(&keyboard_ps2_ami_device); device_add(&fdc37c651_ide_device); @@ -361,30 +339,23 @@ machine_at_vect486vl_init(const machine_t *model) // has HDC problems return ret; } -const device_t * -at_vect486vl_get_device(void) -{ - return &gd5428_onboard_device; -} - - int machine_at_d824_init(const machine_t *model) { int ret; - ret = bios_load_linear("roms/machines/d824/fts-biosupdated824noflashbiosepromv320-320334-160.bin", - 0x000e0000, 131072, 0); + ret = bios_load_linear("roms/machines/d824/fts-biosupdated824noflashbiosepromv320-320334-160.bin", + 0x000e0000, 131072, 0); if (bios_only || !ret) - return ret; + return ret; machine_at_common_init(model); device_add(&vl82c480_device); - if (gfxcard == VID_INTERNAL) - device_add(&gd5428_onboard_device); + if (gfxcard[0] == VID_INTERNAL) + device_add(&gd5428_onboard_device); device_add(&keyboard_ps2_device); device_add(&fdc37c651_device); @@ -392,91 +363,77 @@ machine_at_d824_init(const machine_t *model) return ret; } - -const device_t * -at_d824_get_device(void) -{ - return &gd5428_onboard_device; -} - - int machine_at_acera1g_init(const machine_t *model) { int ret; - ret = bios_load_linear("roms/machines/acera1g/4alo001.bin", - 0x000e0000, 131072, 0); + ret = bios_load_linear("roms/machines/acera1g/4alo001.bin", + 0x000e0000, 131072, 0); if (bios_only || !ret) - return ret; + return ret; machine_at_common_init(model); device_add(&ali1429g_device); - if (gfxcard == VID_INTERNAL) - device_add(&gd5428_onboard_device); + if (gfxcard[0] == VID_INTERNAL) + device_add(&gd5428_onboard_device); device_add(&keyboard_ps2_acer_pci_device); device_add(&ide_isa_2ch_device); if (fdc_type == FDC_INTERNAL) - device_add(&fdc_at_device); + device_add(&fdc_at_device); return ret; } - -const device_t * -at_acera1g_get_device(void) -{ - return &gd5428_onboard_device; -} - - int machine_at_acerv10_init(const machine_t *model) { int ret; - ret = bios_load_linear("roms/machines/acerv10/ALL.BIN", - 0x000e0000, 131072, 0); + ret = bios_load_linear("roms/machines/acerv10/ALL.BIN", + 0x000e0000, 131072, 0); if (bios_only || !ret) - return ret; + return ret; machine_at_common_init(model); device_add(&sis_85c461_device); - device_add(&keyboard_ps2_ami_pci_device); + device_add(&keyboard_ps2_acer_pci_device); device_add(&ide_isa_2ch_device); if (fdc_type == FDC_INTERNAL) - device_add(&fdc_at_device); + device_add(&fdc_at_device); return ret; } - int machine_at_decpclpv_init(const machine_t *model) { int ret; - ret = bios_load_linear("roms/machines/decpclpv/bios.bin", - 0x000e0000, 131072, 0); + ret = bios_load_linear("roms/machines/decpclpv/bios.bin", + 0x000e0000, 131072, 0); if (bios_only || !ret) - return ret; + return ret; machine_at_common_init(model); device_add(&sis_85c461_device); + + if (gfxcard[0] == VID_INTERNAL) + device_add(&s3_86c805_onboard_vlb_device); + /* TODO: Phoenix MultiKey KBC */ device_add(&keyboard_ps2_ami_pci_device); device_add(&ide_isa_2ch_device); - device_add(&fdc37c663_device); - /* TODO: On-board S3 805 with AT&T 490 RAM DAC. */ + device_add(&fdc37c663_ide_device); return ret; } @@ -487,61 +444,58 @@ machine_at_ali1429_common_init(const machine_t *model, int is_green) machine_at_common_ide_init(model); if (is_green) - device_add(&ali1429g_device); + device_add(&ali1429g_device); else - device_add(&ali1429_device); + device_add(&ali1429_device); device_add(&keyboard_at_ami_device); if (fdc_type == FDC_INTERNAL) - device_add(&fdc_at_device); + device_add(&fdc_at_device); } - int machine_at_ali1429_init(const machine_t *model) { int ret; - ret = bios_load_linear("roms/machines/ali1429/ami486.BIN", - 0x000f0000, 65536, 0); + ret = bios_load_linear("roms/machines/ali1429/ami486.BIN", + 0x000f0000, 65536, 0); if (bios_only || !ret) - return ret; + return ret; machine_at_ali1429_common_init(model, 0); return ret; } - int machine_at_winbios1429_init(const machine_t *model) { int ret; ret = bios_load_linear("roms/machines/win486/ali1429g.amw", - 0x000f0000, 65536, 0); + 0x000f0000, 65536, 0); if (bios_only || !ret) - return ret; + return ret; machine_at_ali1429_common_init(model, 1); return ret; } - int machine_at_opti495_init(const machine_t *model) { int ret; ret = bios_load_linear("roms/machines/award495/opt495s.awa", - 0x000f0000, 65536, 0); + 0x000f0000, 65536, 0); if (bios_only || !ret) - return ret; + return ret; machine_at_common_ide_init(model); @@ -550,12 +504,11 @@ machine_at_opti495_init(const machine_t *model) device_add(&keyboard_at_device); if (fdc_type == FDC_INTERNAL) - device_add(&fdc_at_device); + device_add(&fdc_at_device); return ret; } - static void machine_at_opti495_ami_common_init(const machine_t *model) { @@ -566,151 +519,154 @@ machine_at_opti495_ami_common_init(const machine_t *model) device_add(&keyboard_at_ami_device); if (fdc_type == FDC_INTERNAL) - device_add(&fdc_at_device); + device_add(&fdc_at_device); } - int machine_at_opti495_ami_init(const machine_t *model) { int ret; ret = bios_load_linear("roms/machines/ami495/opt495sx.ami", - 0x000f0000, 65536, 0); + 0x000f0000, 65536, 0); if (bios_only || !ret) - return ret; + return ret; machine_at_opti495_ami_common_init(model); return ret; } - int machine_at_opti495_mr_init(const machine_t *model) { int ret; ret = bios_load_linear("roms/machines/mr495/opt495sx.mr", - 0x000f0000, 65536, 0); + 0x000f0000, 65536, 0); if (bios_only || !ret) - return ret; + return ret; machine_at_opti495_ami_common_init(model); return ret; } - static void machine_at_403tg_common_init(const machine_t *model, int nvr_hack) { if (nvr_hack) { - machine_at_common_init_ex(model, 2); - device_add(&ami_1994_nvr_device); + machine_at_common_init_ex(model, 2); + device_add(&ami_1994_nvr_device); } else - machine_at_common_init(model); + machine_at_common_init(model); device_add(&opti895_device); device_add(&keyboard_at_ami_device); if (fdc_type == FDC_INTERNAL) - device_add(&fdc_at_device); + device_add(&fdc_at_device); } - int machine_at_403tg_init(const machine_t *model) { int ret; ret = bios_load_linear("roms/machines/403tg/403TG.BIN", - 0x000f0000, 65536, 0); + 0x000f0000, 65536, 0); if (bios_only || !ret) - return ret; + return ret; machine_at_403tg_common_init(model, 0); return ret; } - int machine_at_403tg_d_init(const machine_t *model) { int ret; ret = bios_load_linear("roms/machines/403tg_d/J403TGRevD.BIN", - 0x000f0000, 65536, 0); + 0x000f0000, 65536, 0); if (bios_only || !ret) - return ret; + return ret; machine_at_403tg_common_init(model, 1); return ret; } - int machine_at_403tg_d_mr_init(const machine_t *model) { int ret; ret = bios_load_linear("roms/machines/403tg_d/MRBiosOPT895.bin", - 0x000f0000, 65536, 0); + 0x000f0000, 65536, 0); if (bios_only || !ret) - return ret; + return ret; machine_at_403tg_common_init(model, 0); return ret; } - int -machine_at_pc330_6573_init(const machine_t *model) /* doesn't like every CPU other than the iDX4 and the Intel OverDrive, hangs without a PS/2 mouse */ +machine_at_pc330_6573_init(const machine_t *model) /* doesn't like every CPU other than the iDX4 and the Intel OverDrive, hangs without a PS/2 mouse */ { int ret; ret = bios_load_linear("roms/machines/pc330_6573/$IMAGES.USF", - 0x000e0000, 131072, 0); + 0x000e0000, 131072, 0); if (bios_only || !ret) - return ret; + return ret; - machine_at_common_init(model); - pci_register_slot(0x10, PCI_CARD_NORTHBRIDGE, 0, 0, 0, 0); - pci_register_slot(0x11, PCI_CARD_NORMAL, 1, 2, 3, 4); - pci_register_slot(0x12, PCI_CARD_NORMAL, 2, 3, 4, 1); - pci_register_slot(0x13, PCI_CARD_NORMAL, 3, 4, 1, 2); - + machine_at_common_init_ex(model, 2); + device_add(&ide_vlb_2ch_device); + + pci_init(PCI_CONFIG_TYPE_1); + pci_register_slot(0x10, PCI_CARD_NORTHBRIDGE, 0, 0, 0, 0); + pci_register_slot(0x0B, PCI_CARD_NORMAL, 1, 2, 3, 4); + pci_register_slot(0x0C, PCI_CARD_NORMAL, 5, 6, 7, 8); + pci_register_slot(0x0D, PCI_CARD_NORMAL, 9, 10, 11, 12); + /* This is a guess because the BIOS always gives it a video BIOS + and never gives it an IRQ, so it is impossible to known for + certain until we obtain PCI readouts from the real machine. */ + pci_register_slot(0x0E, PCI_CARD_VIDEO, 13, 14, 15, 16); + + if (gfxcard[0] == VID_INTERNAL) + device_add(&gd5430_onboard_vlb_device); + + device_add(&opti602_device); device_add(&opti802g_device); device_add(&opti822_device); - device_add(&keyboard_ps2_device); - device_add(&fdc37c665_device); + device_add(&keyboard_ps2_ami_device); + device_add(&fdc37c665_ide_device); device_add(&ide_opti611_vlb_device); device_add(&intel_flash_bxt_device); return ret; } - int machine_at_mvi486_init(const machine_t *model) { int ret; ret = bios_load_linear("roms/machines/mvi486/MVI627.BIN", - 0x000f0000, 65536, 0); + 0x000f0000, 65536, 0); if (bios_only || !ret) - return ret; + return ret; machine_at_common_init(model); @@ -727,22 +683,21 @@ machine_at_sis_85c471_common_init(const machine_t *model) machine_at_common_init(model); if (fdc_type == FDC_INTERNAL) - device_add(&fdc_at_device); + device_add(&fdc_at_device); device_add(&sis_85c471_device); } - int machine_at_ami471_init(const machine_t *model) { int ret; ret = bios_load_linear("roms/machines/ami471/SIS471BE.AMI", - 0x000f0000, 65536, 0); + 0x000f0000, 65536, 0); if (bios_only || !ret) - return ret; + return ret; machine_at_sis_85c471_common_init(model); device_add(&ide_vlb_device); @@ -751,17 +706,16 @@ machine_at_ami471_init(const machine_t *model) return ret; } - int machine_at_vli486sv2g_init(const machine_t *model) { int ret; ret = bios_load_linear("roms/machines/vli486sv2g/0402.001", - 0x000f0000, 65536, 0); + 0x000f0000, 65536, 0); if (bios_only || !ret) - return ret; + return ret; machine_at_sis_85c471_common_init(model); device_add(&ide_vlb_2ch_device); @@ -770,17 +724,16 @@ machine_at_vli486sv2g_init(const machine_t *model) return ret; } - int machine_at_dtk486_init(const machine_t *model) { int ret; ret = bios_load_linear("roms/machines/dtk486/4siw005.bin", - 0x000f0000, 65536, 0); + 0x000f0000, 65536, 0); if (bios_only || !ret) - return ret; + return ret; machine_at_sis_85c471_common_init(model); device_add(&ide_vlb_device); @@ -789,17 +742,16 @@ machine_at_dtk486_init(const machine_t *model) return ret; } - int machine_at_px471_init(const machine_t *model) { int ret; ret = bios_load_linear("roms/machines/px471/SIS471A1.PHO", - 0x000f0000, 65536, 0); + 0x000f0000, 65536, 0); if (bios_only || !ret) - return ret; + return ret; machine_at_sis_85c471_common_init(model); device_add(&ide_vlb_device); @@ -808,17 +760,16 @@ machine_at_px471_init(const machine_t *model) return ret; } - int machine_at_win471_init(const machine_t *model) { int ret; ret = bios_load_linear("roms/machines/win471/486-SiS_AC0360136.BIN", - 0x000f0000, 65536, 0); + 0x000f0000, 65536, 0); if (bios_only || !ret) - return ret; + return ret; machine_at_sis_85c471_common_init(model); device_add(&ide_vlb_device); @@ -827,17 +778,16 @@ machine_at_win471_init(const machine_t *model) return ret; } - int machine_at_vi15g_init(const machine_t *model) { int ret; ret = bios_load_linear("roms/machines/vi15g/vi15gr23.rom", - 0x000f0000, 65536, 0); + 0x000f0000, 65536, 0); if (bios_only || !ret) - return ret; + return ret; machine_at_sis_85c471_common_init(model); device_add(&ide_vlb_device); @@ -846,22 +796,21 @@ machine_at_vi15g_init(const machine_t *model) return ret; } - int machine_at_greenb_init(const machine_t *model) { int ret; ret = bios_load_linear("roms/machines/greenb/4gpv31-ami-1993-8273517.bin", - 0x000f0000, 65536, 0); + 0x000f0000, 65536, 0); if (bios_only || !ret) - return ret; + return ret; machine_at_common_init(model); if (fdc_type == FDC_INTERNAL) - device_add(&fdc_at_device); + device_add(&fdc_at_device); device_add(&contaq_82c597_device); @@ -870,9 +819,8 @@ machine_at_greenb_init(const machine_t *model) return ret; } - static void -machine_at_sis_85c496_common_init(const machine_t *model) +machine_at_sis_85c496_common_init(UNUSED(const machine_t *model)) { device_add(&ide_pci_2ch_device); @@ -885,17 +833,16 @@ machine_at_sis_85c496_common_init(const machine_t *model) pci_set_irq_routing(PCI_INTD, PCI_IRQ_DISABLED); } - int machine_at_r418_init(const machine_t *model) { int ret; ret = bios_load_linear("roms/machines/r418/r418i.bin", - 0x000e0000, 131072, 0); + 0x000e0000, 131072, 0); if (bios_only || !ret) - return ret; + return ret; machine_at_common_init_ex(model, 2); @@ -912,17 +859,16 @@ machine_at_r418_init(const machine_t *model) return ret; } - int machine_at_m4li_init(const machine_t *model) { int ret; ret = bios_load_linear("roms/machines/m4li/M4LI.04S", - 0x000e0000, 131072, 0); + 0x000e0000, 131072, 0); if (bios_only || !ret) - return ret; + return ret; machine_at_common_init_ex(model, 2); @@ -939,17 +885,16 @@ machine_at_m4li_init(const machine_t *model) return ret; } - int machine_at_ls486e_init(const machine_t *model) { int ret; ret = bios_load_linear("roms/machines/ls486e/LS486E RevC.BIN", - 0x000e0000, 131072, 0); + 0x000e0000, 131072, 0); if (bios_only || !ret) - return ret; + return ret; machine_at_common_init_ex(model, 2); @@ -966,17 +911,16 @@ machine_at_ls486e_init(const machine_t *model) return ret; } - int machine_at_4dps_init(const machine_t *model) { int ret; ret = bios_load_linear("roms/machines/4dps/4DPS172G.BIN", - 0x000e0000, 131072, 0); + 0x000e0000, 131072, 0); if (bios_only || !ret) - return ret; + return ret; machine_at_common_init_ex(model, 2); @@ -995,17 +939,16 @@ machine_at_4dps_init(const machine_t *model) return ret; } - int machine_at_486sp3c_init(const machine_t *model) { int ret; ret = bios_load_linear("roms/machines/486sp3c/SI4I0306.AWD", - 0x000e0000, 131072, 0); + 0x000e0000, 131072, 0); if (bios_only || !ret) - return ret; + return ret; machine_at_common_init_ex(model, 2); @@ -1023,17 +966,16 @@ machine_at_486sp3c_init(const machine_t *model) return ret; } - int machine_at_4saw2_init(const machine_t *model) { int ret; ret = bios_load_linear("roms/machines/4saw2/4saw0911.bin", - 0x000e0000, 131072, 0); + 0x000e0000, 131072, 0); if (bios_only || !ret) - return ret; + return ret; machine_at_common_init_ex(model, 2); @@ -1052,27 +994,26 @@ machine_at_4saw2_init(const machine_t *model) return ret; } - int machine_at_alfredo_init(const machine_t *model) { int ret; ret = bios_load_linear_combined("roms/machines/alfredo/1010AQ0_.BIO", - "roms/machines/alfredo/1010AQ0_.BI1", 0x1c000, 128); + "roms/machines/alfredo/1010AQ0_.BI1", 0x1c000, 128); if (bios_only || !ret) - return ret; + return ret; machine_at_common_init(model); device_add(&ide_pci_2ch_device); pci_init(PCI_CONFIG_TYPE_2 | PCI_NO_IRQ_STEERING); pci_register_slot(0x00, PCI_CARD_NORTHBRIDGE, 0, 0, 0, 0); - pci_register_slot(0x01, PCI_CARD_IDE, 0, 0, 0, 0); - pci_register_slot(0x06, PCI_CARD_NORMAL, 3, 2, 1, 4); - pci_register_slot(0x0E, PCI_CARD_NORMAL, 2, 1, 3, 4); - pci_register_slot(0x0C, PCI_CARD_NORMAL, 1, 3, 2, 4); + pci_register_slot(0x01, PCI_CARD_IDE, 0, 0, 0, 0); + pci_register_slot(0x06, PCI_CARD_NORMAL, 3, 2, 1, 4); + pci_register_slot(0x0E, PCI_CARD_NORMAL, 2, 1, 3, 4); + pci_register_slot(0x0C, PCI_CARD_NORMAL, 1, 3, 2, 4); pci_register_slot(0x02, PCI_CARD_SOUTHBRIDGE, 0, 0, 0, 0); device_add(&keyboard_ps2_pci_device); device_add(&sio_device); @@ -1084,25 +1025,24 @@ machine_at_alfredo_init(const machine_t *model) return ret; } - int machine_at_ninja_init(const machine_t *model) { int ret; ret = bios_load_linear_combined("roms/machines/ninja/1008AY0_.BIO", - "roms/machines/ninja/1008AY0_.BI1", 0x1c000, 128); + "roms/machines/ninja/1008AY0_.BI1", 0x1c000, 128); if (bios_only || !ret) - return ret; + return ret; machine_at_common_init(model); pci_init(PCI_CONFIG_TYPE_1 | PCI_NO_IRQ_STEERING); pci_register_slot(0x05, PCI_CARD_NORTHBRIDGE, 0, 0, 0, 0); - pci_register_slot(0x11, PCI_CARD_NORMAL, 1, 2, 1, 2); - pci_register_slot(0x13, PCI_CARD_NORMAL, 2, 1, 2, 1); - pci_register_slot(0x0B, PCI_CARD_NORMAL, 2, 1, 2, 1); + pci_register_slot(0x11, PCI_CARD_NORMAL, 1, 2, 1, 2); + pci_register_slot(0x13, PCI_CARD_NORMAL, 2, 1, 2, 1); + pci_register_slot(0x0B, PCI_CARD_NORMAL, 2, 1, 2, 1); device_add(&keyboard_ps2_intel_ami_pci_device); device_add(&intel_flash_bxt_ami_device); @@ -1112,28 +1052,27 @@ machine_at_ninja_init(const machine_t *model) return ret; } - int machine_at_486sp3_init(const machine_t *model) { int ret; ret = bios_load_linear("roms/machines/486sp3/awsi2737.bin", - 0x000e0000, 131072, 0); + 0x000e0000, 131072, 0); if (bios_only || !ret) - return ret; + return ret; machine_at_common_init(model); device_add(&ide_isa_device); pci_init(PCI_CONFIG_TYPE_2 | PCI_NO_IRQ_STEERING); pci_register_slot(0x00, PCI_CARD_NORTHBRIDGE, 0, 0, 0, 0); - pci_register_slot(0x01, PCI_CARD_SCSI, 1, 2, 3, 4); /* 01 = SCSI */ - pci_register_slot(0x03, PCI_CARD_NORMAL, 1, 2, 3, 4); /* 03 = Slot 1 */ - pci_register_slot(0x04, PCI_CARD_NORMAL, 2, 3, 4, 1); /* 04 = Slot 2 */ - pci_register_slot(0x05, PCI_CARD_NORMAL, 3, 4, 1, 2); /* 05 = Slot 3 */ - pci_register_slot(0x06, PCI_CARD_NORMAL, 4, 1, 2, 3); /* 06 = Slot 4 */ + pci_register_slot(0x01, PCI_CARD_SCSI, 1, 2, 3, 4); /* 01 = SCSI */ + pci_register_slot(0x03, PCI_CARD_NORMAL, 1, 2, 3, 4); /* 03 = Slot 1 */ + pci_register_slot(0x04, PCI_CARD_NORMAL, 2, 3, 4, 1); /* 04 = Slot 2 */ + pci_register_slot(0x05, PCI_CARD_NORMAL, 3, 4, 1, 2); /* 05 = Slot 3 */ + pci_register_slot(0x06, PCI_CARD_NORMAL, 4, 1, 2, 3); /* 06 = Slot 4 */ pci_register_slot(0x02, PCI_CARD_SOUTHBRIDGE, 0, 0, 0, 0); device_add(&keyboard_ps2_ami_pci_device); /* Uses the AMIKEY KBC */ device_add(&sio_device); @@ -1146,17 +1085,16 @@ machine_at_486sp3_init(const machine_t *model) return ret; } - int machine_at_pci400cb_init(const machine_t *model) { int ret; ret = bios_load_linear("roms/machines/pci400cb/032295.ROM", - 0x000e0000, 131072, 0); + 0x000e0000, 131072, 0); if (bios_only || !ret) - return ret; + return ret; machine_at_common_init_ex(model, 2); device_add(&ami_1994_nvr_device); @@ -1164,32 +1102,31 @@ machine_at_pci400cb_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(0x0F, PCI_CARD_NORMAL, 4, 3, 2, 1); /* 0F = Slot 1 */ - pci_register_slot(0x0E, PCI_CARD_NORMAL, 3, 4, 1, 2); /* 0E = Slot 2 */ - pci_register_slot(0x0D, PCI_CARD_NORMAL, 2, 3, 4, 1); /* 0D = Slot 3 */ - pci_register_slot(0x0C, PCI_CARD_NORMAL, 1, 2, 3, 4); /* 0C = Slot 4 */ - device_add(&keyboard_ps2_ami_pci_device); /* Assume AMI Megakey 1993 standalone ('P') - because of the Tekram machine below. */ + pci_register_slot(0x0F, PCI_CARD_NORMAL, 4, 3, 2, 1); /* 0F = Slot 1 */ + pci_register_slot(0x0E, PCI_CARD_NORMAL, 3, 4, 1, 2); /* 0E = Slot 2 */ + pci_register_slot(0x0D, PCI_CARD_NORMAL, 2, 3, 4, 1); /* 0D = Slot 3 */ + pci_register_slot(0x0C, PCI_CARD_NORMAL, 1, 2, 3, 4); /* 0C = Slot 4 */ + device_add(&keyboard_ps2_ami_pci_device); /* Assume AMI Megakey 1993 standalone ('P') + because of the Tekram machine below. */ device_add(&ims8848_device); if (fdc_type == FDC_INTERNAL) - device_add(&fdc_at_device); + device_add(&fdc_at_device); return ret; } - int machine_at_g486ip_init(const machine_t *model) { int ret; ret = bios_load_linear("roms/machines/g486ip/G486IP.BIN", - 0x000e0000, 131072, 0); + 0x000e0000, 131072, 0); if (bios_only || !ret) - return ret; + return ret; machine_at_common_init_ex(model, 2); device_add(&ami_1992_nvr_device); @@ -1197,42 +1134,41 @@ machine_at_g486ip_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(0x0F, PCI_CARD_NORMAL, 3, 4, 1, 2); /* 03 = Slot 1 */ - pci_register_slot(0x0E, PCI_CARD_NORMAL, 2, 3, 4, 1); /* 04 = Slot 2 */ - pci_register_slot(0x0D, PCI_CARD_NORMAL, 1, 2, 3, 4); /* 05 = Slot 3 */ - device_add(&keyboard_ps2_ami_pci_device); /* AMI Megakey 1993 stanalone ('P') */ + pci_register_slot(0x0F, PCI_CARD_NORMAL, 3, 4, 1, 2); /* 03 = Slot 1 */ + pci_register_slot(0x0E, PCI_CARD_NORMAL, 2, 3, 4, 1); /* 04 = Slot 2 */ + pci_register_slot(0x0D, PCI_CARD_NORMAL, 1, 2, 3, 4); /* 05 = Slot 3 */ + device_add(&keyboard_ps2_ami_pci_device); /* AMI Megakey 1993 stanalone ('P') */ device_add(&ims8848_device); if (fdc_type == FDC_INTERNAL) - device_add(&fdc_at_device); + device_add(&fdc_at_device); return ret; } - int machine_at_486sp3g_init(const machine_t *model) { int ret; ret = bios_load_linear("roms/machines/486sp3g/PCI-I-486SP3G_0306.001 (Beta).bin", - 0x000e0000, 131072, 0); + 0x000e0000, 131072, 0); if (bios_only || !ret) - return ret; + return ret; machine_at_common_init(model); device_add(&ide_isa_device); pci_init(PCI_CONFIG_TYPE_2); pci_register_slot(0x00, PCI_CARD_NORTHBRIDGE, 0, 0, 0, 0); - pci_register_slot(0x01, PCI_CARD_SCSI, 1, 2, 3, 4); /* 01 = SCSI */ - pci_register_slot(0x06, PCI_CARD_NORMAL, 1, 2, 3, 4); /* 06 = Slot 1 */ - pci_register_slot(0x05, PCI_CARD_NORMAL, 2, 3, 4, 1); /* 05 = Slot 2 */ - pci_register_slot(0x04, PCI_CARD_NORMAL, 3, 4, 1, 2); /* 04 = Slot 3 */ + pci_register_slot(0x01, PCI_CARD_SCSI, 1, 2, 3, 4); /* 01 = SCSI */ + pci_register_slot(0x06, PCI_CARD_NORMAL, 1, 2, 3, 4); /* 06 = Slot 1 */ + pci_register_slot(0x05, PCI_CARD_NORMAL, 2, 3, 4, 1); /* 05 = Slot 2 */ + pci_register_slot(0x04, PCI_CARD_NORMAL, 3, 4, 1, 2); /* 04 = Slot 3 */ pci_register_slot(0x02, PCI_CARD_SOUTHBRIDGE, 0, 0, 0, 0); - device_add(&keyboard_ps2_ami_pci_device); /* Uses the AMIKEY KBC */ + device_add(&keyboard_ps2_ami_pci_device); /* Uses the AMIKEY KBC */ device_add(&sio_zb_device); device_add(&pc87332_398_ide_device); device_add(&sst_flash_29ee010_device); @@ -1243,57 +1179,55 @@ machine_at_486sp3g_init(const machine_t *model) return ret; } - int machine_at_486ap4_init(const machine_t *model) { int ret; ret = bios_load_linear("roms/machines/486ap4/0205.002", - 0x000e0000, 131072, 0); + 0x000e0000, 131072, 0); if (bios_only || !ret) - return ret; + return ret; machine_at_common_init(model); pci_init(PCI_CONFIG_TYPE_1 | PCI_NO_IRQ_STEERING); /* Excluded: 5, 6, 7, 8 */ pci_register_slot(0x05, PCI_CARD_NORTHBRIDGE, 0, 0, 0, 0); - pci_register_slot(0x09, PCI_CARD_NORMAL, 1, 2, 3, 4); /* 09 = Slot 1 */ - pci_register_slot(0x0a, PCI_CARD_NORMAL, 2, 3, 4, 1); /* 0a = Slot 2 */ - pci_register_slot(0x0b, PCI_CARD_NORMAL, 3, 4, 1, 2); /* 0b = Slot 3 */ - pci_register_slot(0x0c, PCI_CARD_NORMAL, 4, 1, 2, 3); /* 0c = Slot 4 */ - device_add(&keyboard_ps2_ami_pci_device); /* Uses the AMIKEY KBC */ + pci_register_slot(0x09, PCI_CARD_NORMAL, 1, 2, 3, 4); /* 09 = Slot 1 */ + pci_register_slot(0x0a, PCI_CARD_NORMAL, 2, 3, 4, 1); /* 0a = Slot 2 */ + pci_register_slot(0x0b, PCI_CARD_NORMAL, 3, 4, 1, 2); /* 0b = Slot 3 */ + pci_register_slot(0x0c, PCI_CARD_NORMAL, 4, 1, 2, 3); /* 0c = Slot 4 */ + device_add(&keyboard_ps2_ami_pci_device); /* Uses the AMIKEY KBC */ if (fdc_type == FDC_INTERNAL) - device_add(&fdc_at_device); + device_add(&fdc_at_device); device_add(&i420ex_device); return ret; } - int machine_at_g486vpa_init(const machine_t *model) { int ret; ret = bios_load_linear("roms/machines/g486vpa/3.BIN", - 0x000e0000, 131072, 0); + 0x000e0000, 131072, 0); if (bios_only || !ret) - return ret; + return ret; machine_at_common_init(model); pci_init(PCI_CONFIG_TYPE_1); pci_register_slot(0x00, PCI_CARD_NORTHBRIDGE, 0, 0, 0, 0); - pci_register_slot(0x08, PCI_CARD_NORMAL, 1, 2, 3, 4); - pci_register_slot(0x09, PCI_CARD_NORMAL, 2, 3, 4, 1); - pci_register_slot(0x0A, PCI_CARD_NORMAL, 3, 4, 1, 2); - pci_register_slot(0x0B, PCI_CARD_NORMAL, 4, 1, 2, 3); + pci_register_slot(0x08, PCI_CARD_NORMAL, 1, 2, 3, 4); + pci_register_slot(0x09, PCI_CARD_NORMAL, 2, 3, 4, 1); + pci_register_slot(0x0A, PCI_CARD_NORMAL, 3, 4, 1, 2); + pci_register_slot(0x0B, PCI_CARD_NORMAL, 4, 1, 2, 3); device_add(&via_vt82c49x_pci_ide_device); device_add(&via_vt82c505_device); @@ -1304,26 +1238,25 @@ machine_at_g486vpa_init(const machine_t *model) return ret; } - int machine_at_486vipio2_init(const machine_t *model) { int ret; ret = bios_load_linear("roms/machines/486vipio2/1175G701.BIN", - 0x000e0000, 131072, 0); + 0x000e0000, 131072, 0); if (bios_only || !ret) - return ret; + return ret; machine_at_common_init(model); pci_init(PCI_CONFIG_TYPE_1); pci_register_slot(0x00, PCI_CARD_NORTHBRIDGE, 0, 0, 0, 0); - pci_register_slot(0x08, PCI_CARD_NORMAL, 1, 2, 3, 4); - pci_register_slot(0x09, PCI_CARD_NORMAL, 2, 3, 4, 1); - pci_register_slot(0x0A, PCI_CARD_NORMAL, 3, 4, 1, 2); - pci_register_slot(0x0B, PCI_CARD_NORMAL, 4, 1, 2, 3); + pci_register_slot(0x08, PCI_CARD_NORMAL, 1, 2, 3, 4); + pci_register_slot(0x09, PCI_CARD_NORMAL, 2, 3, 4, 1); + pci_register_slot(0x0A, PCI_CARD_NORMAL, 3, 4, 1, 2); + pci_register_slot(0x0B, PCI_CARD_NORMAL, 4, 1, 2, 3); device_add(&via_vt82c49x_pci_ide_device); device_add(&via_vt82c505_device); @@ -1334,54 +1267,54 @@ machine_at_486vipio2_init(const machine_t *model) return ret; } - int machine_at_abpb4_init(const machine_t *model) { int ret; ret = bios_load_linear("roms/machines/abpb4/486-AB-PB4.BIN", - 0x000e0000, 131072, 0); + 0x000e0000, 131072, 0); if (bios_only || !ret) - return ret; + return ret; machine_at_common_init(model); - + pci_init(PCI_CAN_SWITCH_TYPE); pci_register_slot(0x00, PCI_CARD_NORTHBRIDGE, 0, 0, 0, 0); - pci_register_slot(0x03, PCI_CARD_NORMAL, 1, 2, 3, 4); - pci_register_slot(0x04, PCI_CARD_NORMAL, 2, 3, 4, 1); - pci_register_slot(0x05, PCI_CARD_NORMAL, 3, 4, 1, 2); + pci_register_slot(0x03, PCI_CARD_NORMAL, 1, 2, 3, 4); + pci_register_slot(0x04, PCI_CARD_NORMAL, 2, 3, 4, 1); + pci_register_slot(0x05, PCI_CARD_NORMAL, 3, 4, 1, 2); device_add(&ali1489_device); device_add(&w83787f_device); device_add(&keyboard_at_device); - // device_add(&intel_flash_bxt_device); +#if 0 + device_add(&intel_flash_bxt_device); +#endif device_add(&sst_flash_29ee010_device); return ret; } - int machine_at_win486pci_init(const machine_t *model) { int ret; ret = bios_load_linear("roms/machines/win486pci/v1hj3.BIN", - 0x000e0000, 131072, 0); + 0x000e0000, 131072, 0); if (bios_only || !ret) - return ret; + return ret; machine_at_common_init(model); - + pci_init(PCI_CONFIG_TYPE_1); pci_register_slot(0x00, PCI_CARD_NORTHBRIDGE, 0, 0, 0, 0); - pci_register_slot(0x03, PCI_CARD_NORMAL, 1, 2, 3, 4); - pci_register_slot(0x04, PCI_CARD_NORMAL, 2, 3, 4, 1); - pci_register_slot(0x05, PCI_CARD_NORMAL, 3, 4, 1, 2); + pci_register_slot(0x03, PCI_CARD_NORMAL, 1, 2, 3, 4); + pci_register_slot(0x04, PCI_CARD_NORMAL, 2, 3, 4, 1); + pci_register_slot(0x05, PCI_CARD_NORMAL, 3, 4, 1, 2); device_add(&ali1489_device); device_add(&prime3b_device); @@ -1390,26 +1323,25 @@ machine_at_win486pci_init(const machine_t *model) return ret; } - int machine_at_ms4145_init(const machine_t *model) { int ret; ret = bios_load_linear("roms/machines/ms4145/AG56S.ROM", - 0x000e0000, 131072, 0); + 0x000e0000, 131072, 0); if (bios_only || !ret) - return ret; + return ret; machine_at_common_init(model); - + pci_init(PCI_CONFIG_TYPE_1); pci_register_slot(0x00, PCI_CARD_NORTHBRIDGE, 0, 0, 0, 0); - pci_register_slot(0x03, PCI_CARD_NORMAL, 1, 2, 3, 4); - pci_register_slot(0x04, PCI_CARD_NORMAL, 2, 3, 4, 1); - pci_register_slot(0x05, PCI_CARD_NORMAL, 3, 4, 1, 2); - pci_register_slot(0x06, PCI_CARD_NORMAL, 4, 1, 2, 3); + pci_register_slot(0x03, PCI_CARD_NORMAL, 1, 2, 3, 4); + pci_register_slot(0x04, PCI_CARD_NORMAL, 2, 3, 4, 1); + pci_register_slot(0x05, PCI_CARD_NORMAL, 3, 4, 1, 2); + pci_register_slot(0x06, PCI_CARD_NORMAL, 4, 1, 2, 3); device_add(&ali1489_device); device_add(&w83787f_device); @@ -1419,33 +1351,32 @@ machine_at_ms4145_init(const machine_t *model) return ret; } - int machine_at_sbc490_init(const machine_t *model) { int ret; ret = bios_load_linear("roms/machines/sbc490/07159589.rom", - 0x000e0000, 131072, 0); + 0x000e0000, 131072, 0); if (bios_only || !ret) - return ret; + return ret; machine_at_common_init(model); - + pci_init(PCI_CONFIG_TYPE_1); pci_register_slot(0x00, PCI_CARD_NORTHBRIDGE, 0, 0, 0, 0); - pci_register_slot(0x0F, PCI_CARD_NORMAL, 2, 3, 4, 1); - pci_register_slot(0x0E, PCI_CARD_NORMAL, 3, 4, 1, 2); - pci_register_slot(0x0D, PCI_CARD_NORMAL, 4, 1, 2, 3); - pci_register_slot(0x0C, PCI_CARD_NORMAL, 1, 2, 3, 4); - pci_register_slot(0x01, PCI_CARD_VIDEO, 4, 1, 2, 3); + pci_register_slot(0x0F, PCI_CARD_NORMAL, 2, 3, 4, 1); + pci_register_slot(0x0E, PCI_CARD_NORMAL, 3, 4, 1, 2); + pci_register_slot(0x0D, PCI_CARD_NORMAL, 4, 1, 2, 3); + pci_register_slot(0x0C, PCI_CARD_NORMAL, 1, 2, 3, 4); + pci_register_slot(0x01, PCI_CARD_VIDEO, 4, 1, 2, 3); device_add(&ali1489_device); device_add(&fdc37c665_device); - if (gfxcard == VID_INTERNAL) - device_add(&tgui9440_onboard_pci_device); + if (gfxcard[0] == VID_INTERNAL) + device_add(&tgui9440_onboard_pci_device); device_add(&keyboard_ps2_ami_device); device_add(&sst_flash_29ee010_device); @@ -1453,30 +1384,22 @@ machine_at_sbc490_init(const machine_t *model) return ret; } - -const device_t * -at_sbc490_get_device(void) -{ - return &tgui9440_onboard_pci_device; -} - - int machine_at_tf486_init(const machine_t *model) { int ret; ret = bios_load_linear("roms/machines/tf486/tf486v10.BIN", - 0x000e0000, 131072, 0); + 0x000e0000, 131072, 0); if (bios_only || !ret) - return ret; + return ret; machine_at_common_init(model); - + pci_init(PCI_CONFIG_TYPE_1); pci_register_slot(0x00, PCI_CARD_NORTHBRIDGE, 0, 0, 0, 0); - pci_register_slot(0x0C, PCI_CARD_NORMAL, 1, 2, 3, 4); + pci_register_slot(0x0C, PCI_CARD_NORMAL, 1, 2, 3, 4); device_add(&ali1489_device); device_add(&w83977ef_device); @@ -1486,56 +1409,54 @@ machine_at_tf486_init(const machine_t *model) return ret; } - int machine_at_itoxstar_init(const machine_t *model) { int ret; ret = bios_load_linear("roms/machines/itoxstar/STARA.ROM", - 0x000c0000, 262144, 0); + 0x000c0000, 262144, 0); if (bios_only || !ret) - return ret; + return ret; machine_at_common_init(model); pci_init(PCI_CONFIG_TYPE_1); pci_register_slot(0x0B, PCI_CARD_NORTHBRIDGE, 0, 0, 0, 0); pci_register_slot(0x0C, PCI_CARD_SOUTHBRIDGE, 0, 0, 0, 0); - pci_register_slot(0x1F, PCI_CARD_NORMAL, 1, 2, 3, 4); + pci_register_slot(0x1F, PCI_CARD_NORMAL, 1, 2, 3, 4); device_add(&w83977f_device); device_add(&keyboard_ps2_ami_pci_device); device_add(&stpc_client_device); device_add(&sst_flash_29ee020_device); - device_add(&w83781d_device); /* fans: Chassis, CPU, unused; temperatures: Chassis, CPU, unused */ - hwm_values.fans[2] = 0; /* unused */ + device_add(&w83781d_device); /* fans: Chassis, CPU, unused; temperatures: Chassis, CPU, unused */ + hwm_values.fans[2] = 0; /* unused */ hwm_values.temperatures[2] = 0; /* unused */ - hwm_values.voltages[0] = 0; /* Vcore unused */ + hwm_values.voltages[0] = 0; /* Vcore unused */ return ret; } - int machine_at_arb1423c_init(const machine_t *model) { int ret; ret = bios_load_linear("roms/machines/arb1423c/A1423C.v12", - 0x000c0000, 262144, 0); + 0x000c0000, 262144, 0); if (bios_only || !ret) - return ret; + return ret; machine_at_common_init(model); pci_init(PCI_CONFIG_TYPE_1); pci_register_slot(0x0B, PCI_CARD_NORTHBRIDGE, 0, 0, 0, 0); pci_register_slot(0x0C, PCI_CARD_SOUTHBRIDGE, 0, 0, 0, 0); - pci_register_slot(0x1F, PCI_CARD_NORMAL, 1, 0, 0, 0); - pci_register_slot(0x1E, PCI_CARD_NORMAL, 2, 3, 4, 1); - pci_register_slot(0x1D, PCI_CARD_NORMAL, 3, 4, 1, 2); + pci_register_slot(0x1F, PCI_CARD_NORMAL, 1, 0, 0, 0); + pci_register_slot(0x1E, PCI_CARD_NORMAL, 2, 3, 4, 1); + pci_register_slot(0x1D, PCI_CARD_NORMAL, 3, 4, 1, 2); device_add(&w83977f_device); device_add(&keyboard_ps2_ami_pci_device); device_add(&stpc_consumer2_device); @@ -1544,26 +1465,25 @@ machine_at_arb1423c_init(const machine_t *model) return ret; } - int machine_at_arb1479_init(const machine_t *model) { int ret; ret = bios_load_linear("roms/machines/arb1479/1479A.rom", - 0x000c0000, 262144, 0); + 0x000c0000, 262144, 0); if (bios_only || !ret) - return ret; + return ret; machine_at_common_init(model); pci_init(PCI_CONFIG_TYPE_1); pci_register_slot(0x0B, PCI_CARD_NORTHBRIDGE, 0, 0, 0, 0); pci_register_slot(0x0C, PCI_CARD_SOUTHBRIDGE, 0, 0, 0, 0); - pci_register_slot(0x1F, PCI_CARD_NORMAL, 1, 0, 0, 0); - pci_register_slot(0x1E, PCI_CARD_NORMAL, 2, 3, 4, 1); - pci_register_slot(0x1D, PCI_CARD_NORMAL, 3, 4, 1, 2); + pci_register_slot(0x1F, PCI_CARD_NORMAL, 1, 0, 0, 0); + pci_register_slot(0x1E, PCI_CARD_NORMAL, 2, 3, 4, 1); + pci_register_slot(0x1D, PCI_CARD_NORMAL, 3, 4, 1, 2); device_add(&w83977f_device); device_add(&keyboard_ps2_ami_pci_device); device_add(&stpc_consumer2_device); @@ -1572,26 +1492,25 @@ machine_at_arb1479_init(const machine_t *model) return ret; } - int machine_at_pcm9340_init(const machine_t *model) { int ret; ret = bios_load_linear("roms/machines/pcm9340/9340v110.bin", - 0x000c0000, 262144, 0); + 0x000c0000, 262144, 0); if (bios_only || !ret) - return ret; + return ret; machine_at_common_init(model); pci_init(PCI_CONFIG_TYPE_1); pci_register_slot(0x0B, PCI_CARD_NORTHBRIDGE, 0, 0, 0, 0); pci_register_slot(0x0C, PCI_CARD_SOUTHBRIDGE, 0, 0, 0, 0); - pci_register_slot(0x1D, PCI_CARD_NORMAL, 4, 1, 2, 3); - pci_register_slot(0x1E, PCI_CARD_NORMAL, 3, 4, 1, 2); - pci_register_slot(0x1F, PCI_CARD_NORMAL, 2, 3, 4, 1); + pci_register_slot(0x1D, PCI_CARD_NORMAL, 4, 1, 2, 3); + pci_register_slot(0x1E, PCI_CARD_NORMAL, 3, 4, 1, 2); + pci_register_slot(0x1F, PCI_CARD_NORMAL, 2, 3, 4, 1); device_add_inst(&w83977f_device, 1); device_add_inst(&w83977f_device, 2); device_add(&keyboard_ps2_ami_pci_device); @@ -1601,26 +1520,25 @@ machine_at_pcm9340_init(const machine_t *model) return ret; } - int machine_at_pcm5330_init(const machine_t *model) { int ret; ret = bios_load_linear("roms/machines/pcm5330/5330_13b.bin", - 0x000c0000, 262144, 0); + 0x000c0000, 262144, 0); if (bios_only || !ret) - return ret; + return ret; machine_at_common_init(model); pci_init(PCI_CONFIG_TYPE_1); - pci_register_slot(0x0B, PCI_CARD_NORTHBRIDGE, 0, 0, 0, 0); - pci_register_slot(0x0C, PCI_CARD_SOUTHBRIDGE, 0, 0, 0, 0); - pci_register_slot(0x0D, PCI_CARD_SOUTHBRIDGE, 0, 0, 0, 0); - pci_register_slot(0x0E, PCI_CARD_SOUTHBRIDGE, 1, 2, 3, 4); - pci_register_slot(0x13, PCI_CARD_NORMAL, 1, 2, 3, 4); + pci_register_slot(0x0B, PCI_CARD_NORTHBRIDGE, 0, 0, 0, 0); + pci_register_slot(0x0C, PCI_CARD_SOUTHBRIDGE, 0, 0, 0, 0); + pci_register_slot(0x0D, PCI_CARD_SOUTHBRIDGE_IDE, 0, 0, 0, 0); + pci_register_slot(0x0E, PCI_CARD_SOUTHBRIDGE_USB, 1, 2, 3, 4); + pci_register_slot(0x13, PCI_CARD_NORMAL, 1, 2, 3, 4); device_add(&stpc_serial_device); device_add(&w83977f_370_device); device_add(&keyboard_ps2_ami_pci_device); @@ -1630,91 +1548,86 @@ machine_at_pcm5330_init(const machine_t *model) return ret; } - int machine_at_ecs486_init(const machine_t *model) { int ret; ret = bios_load_linear("roms/machines/ecs486/8810AIO.32J", - 0x000e0000, 131072, 0); + 0x000e0000, 131072, 0); if (bios_only || !ret) - return ret; + return ret; machine_at_common_init(model); - + pci_init(PCI_CONFIG_TYPE_1); pci_register_slot(0x10, PCI_CARD_NORTHBRIDGE, 0, 0, 0, 0); pci_register_slot(0x12, PCI_CARD_SOUTHBRIDGE, 1, 2, 3, 4); - pci_register_slot(0x0F, PCI_CARD_IDE, 0, 0, 0, 0); - pci_register_slot(0x0C, PCI_CARD_NORMAL, 1, 2, 3, 4); - pci_register_slot(0x0D, PCI_CARD_NORMAL, 2, 3, 4, 1); - pci_register_slot(0x0E, PCI_CARD_NORMAL, 3, 4, 1, 2); + pci_register_slot(0x0F, PCI_CARD_IDE, 0, 0, 0, 0); + pci_register_slot(0x0C, PCI_CARD_NORMAL, 1, 2, 3, 4); + pci_register_slot(0x0D, PCI_CARD_NORMAL, 2, 3, 4, 1); + pci_register_slot(0x0E, PCI_CARD_NORMAL, 3, 4, 1, 2); device_add(&umc_hb4_device); device_add(&umc_8886f_device); device_add(&ide_cmd640_pci_legacy_only_device); device_add(&fdc37c665_device); device_add(&intel_flash_bxt_device); - device_add(&keyboard_at_ami_device); + device_add(&keyboard_ps2_ami_device); return ret; } - int machine_at_hot433_init(const machine_t *model) { int ret; ret = bios_load_linear("roms/machines/hot433/433AUS33.ROM", - 0x000e0000, 131072, 0); + 0x000e0000, 131072, 0); if (bios_only || !ret) - return ret; + return ret; machine_at_common_init(model); - + pci_init(PCI_CONFIG_TYPE_1); pci_register_slot(0x10, PCI_CARD_NORTHBRIDGE, 0, 0, 0, 0); pci_register_slot(0x12, PCI_CARD_SOUTHBRIDGE, 1, 2, 3, 4); - pci_register_slot(0x0C, PCI_CARD_NORMAL, 1, 2, 3, 4); - pci_register_slot(0x0D, PCI_CARD_NORMAL, 4, 1, 2, 3); - pci_register_slot(0x0E, PCI_CARD_NORMAL, 3, 4, 1, 2); - pci_register_slot(0x0F, PCI_CARD_NORMAL, 2, 3, 4, 1); + pci_register_slot(0x0C, PCI_CARD_NORMAL, 1, 2, 3, 4); + pci_register_slot(0x0D, PCI_CARD_NORMAL, 4, 1, 2, 3); + pci_register_slot(0x0E, PCI_CARD_NORMAL, 3, 4, 1, 2); + pci_register_slot(0x0F, PCI_CARD_NORMAL, 2, 3, 4, 1); device_add(&umc_hb4_device); device_add(&umc_8886af_device); device_add(&um8669f_device); - // device_add(&intel_flash_bxt_device); - device_add(&sst_flash_29ee010_device); - // device_add(&keyboard_at_ami_device); - device_add(&keyboard_ps2_ami_device); + device_add(&winbond_flash_w29c010_device); + device_add(&keyboard_at_ami_device); return ret; } - int machine_at_atc1415_init(const machine_t *model) { int ret; ret = bios_load_linear("roms/machines/atc1415/1415V330.ROM", - 0x000e0000, 131072, 0); + 0x000e0000, 131072, 0); if (bios_only || !ret) - return ret; + return ret; machine_at_common_init(model); - + pci_init(PCI_CONFIG_TYPE_1); pci_register_slot(0x10, PCI_CARD_NORTHBRIDGE, 0, 0, 0, 0); pci_register_slot(0x12, PCI_CARD_SOUTHBRIDGE, 1, 2, 3, 4); - pci_register_slot(0x0C, PCI_CARD_NORMAL, 1, 2, 3, 4); - pci_register_slot(0x13, PCI_CARD_NORMAL, 4, 1, 2, 3); - pci_register_slot(0x14, PCI_CARD_NORMAL, 3, 4, 1, 2); + pci_register_slot(0x0C, PCI_CARD_NORMAL, 1, 2, 3, 4); + pci_register_slot(0x13, PCI_CARD_NORMAL, 4, 1, 2, 3); + pci_register_slot(0x14, PCI_CARD_NORMAL, 3, 4, 1, 2); device_add(&umc_hb4_device); device_add(&umc_8886af_device); @@ -1722,62 +1635,60 @@ machine_at_atc1415_init(const machine_t *model) device_add(&keyboard_at_ami_device); if (fdc_type == FDC_INTERNAL) - device_add(&fdc_at_device); + device_add(&fdc_at_device); return ret; } - int machine_at_actionpc2600_init(const machine_t *model) { int ret; ret = bios_load_linear("roms/machines/actionpc2600/action2600.BIN", - 0x000e0000, 131072, 0); + 0x000e0000, 131072, 0); if (bios_only || !ret) - return ret; + return ret; machine_at_common_init(model); - + pci_init(PCI_CONFIG_TYPE_1); pci_register_slot(0x10, PCI_CARD_NORTHBRIDGE, 0, 0, 0, 0); pci_register_slot(0x12, PCI_CARD_SOUTHBRIDGE, 1, 2, 3, 4); - pci_register_slot(0x0C, PCI_CARD_NORMAL, 1, 2, 3, 4); - pci_register_slot(0x0D, PCI_CARD_NORMAL, 4, 1, 2, 3); - pci_register_slot(0x0E, PCI_CARD_NORMAL, 3, 4, 1, 2); - pci_register_slot(0x0F, PCI_CARD_NORMAL, 2, 3, 4, 1); + pci_register_slot(0x0C, PCI_CARD_NORMAL, 1, 2, 3, 4); + pci_register_slot(0x0D, PCI_CARD_NORMAL, 4, 1, 2, 3); + pci_register_slot(0x0E, PCI_CARD_NORMAL, 3, 4, 1, 2); + pci_register_slot(0x0F, PCI_CARD_NORMAL, 2, 3, 4, 1); device_add(&umc_hb4_device); device_add(&umc_8886af_device); device_add(&um8669f_device); device_add(&intel_flash_bxt_device); - device_add(&keyboard_at_ami_device); + device_add(&keyboard_ps2_tg_ami_device); return ret; } - int machine_at_m919_init(const machine_t *model) { int ret; ret = bios_load_linear("roms/machines/m919/9190914s.rom", - 0x000e0000, 131072, 0); + 0x000e0000, 131072, 0); if (bios_only || !ret) - return ret; + return ret; machine_at_common_init(model); - + pci_init(PCI_CONFIG_TYPE_1); pci_register_slot(0x10, PCI_CARD_NORTHBRIDGE, 0, 0, 0, 0); pci_register_slot(0x12, PCI_CARD_SOUTHBRIDGE, 1, 2, 3, 4); - pci_register_slot(0x0C, PCI_CARD_NORMAL, 1, 2, 3, 4); - pci_register_slot(0x0D, PCI_CARD_NORMAL, 4, 1, 2, 3); - pci_register_slot(0x0E, PCI_CARD_NORMAL, 3, 4, 1, 2); + pci_register_slot(0x0C, PCI_CARD_NORMAL, 1, 2, 3, 4); + pci_register_slot(0x0D, PCI_CARD_NORMAL, 4, 1, 2, 3); + pci_register_slot(0x0E, PCI_CARD_NORMAL, 3, 4, 1, 2); device_add(&umc_hb4_device); device_add(&umc_8886af_device); @@ -1788,32 +1699,125 @@ machine_at_m919_init(const machine_t *model) return ret; } - int machine_at_spc7700plw_init(const machine_t *model) { int ret; ret = bios_load_linear("roms/machines/spc7700plw/77LW13FH.P24", - 0x000e0000, 131072, 0); + 0x000e0000, 131072, 0); if (bios_only || !ret) - return ret; + return ret; machine_at_common_init(model); - + pci_init(PCI_CONFIG_TYPE_1); pci_register_slot(0x10, PCI_CARD_NORTHBRIDGE, 0, 0, 0, 0); pci_register_slot(0x12, PCI_CARD_SOUTHBRIDGE, 1, 2, 3, 4); - pci_register_slot(0x0C, PCI_CARD_NORMAL, 2, 3, 4, 1); - pci_register_slot(0x0D, PCI_CARD_NORMAL, 1, 2, 3, 4); - pci_register_slot(0x0E, PCI_CARD_NORMAL, 3, 4, 1, 2); + pci_register_slot(0x0C, PCI_CARD_NORMAL, 2, 3, 4, 1); + pci_register_slot(0x0D, PCI_CARD_NORMAL, 1, 2, 3, 4); + pci_register_slot(0x0E, PCI_CARD_NORMAL, 3, 4, 1, 2); device_add(&umc_hb4_device); device_add(&umc_8886af_device); device_add(&fdc37c665_device); device_add(&intel_flash_bxt_device); - device_add(&keyboard_at_ami_device); + device_add(&keyboard_ps2_ami_device); + + return ret; +} + +int +machine_at_ms4134_init(const machine_t *model) +{ + int ret; + + ret = bios_load_linear("roms/machines/ms4134/4alm001.bin", + 0x000e0000, 131072, 0); + + if (bios_only || !ret) + return ret; + + machine_at_common_ide_init(model); + + device_add(&ali1429g_device); + + device_add(&fdc37c665_ide_pri_device); + + pci_init(FLAG_MECHANISM_1 | FLAG_MECHANISM_2 | PCI_ALWAYS_EXPOSE_DEV0); + pci_register_slot(0x00, PCI_CARD_NORTHBRIDGE, 0, 0, 0, 0); + + pci_register_slot(0x0B, PCI_CARD_SCSI, 4, 1, 2, 3); + pci_register_slot(0x08, PCI_CARD_NORMAL, 1, 2, 3, 4); + pci_register_slot(0x09, PCI_CARD_NORMAL, 2, 3, 4, 1); + pci_register_slot(0x0A, PCI_CARD_NORMAL, 3, 4, 1, 2); + pci_register_slot(0x10, PCI_CARD_NORMAL, 1, 2, 3, 4); + + device_add(&ali1435_device); + device_add(&sst_flash_29ee010_device); + + device_add(&keyboard_ps2_ami_device); + + return ret; +} + +int +machine_at_tg486gp_init(const machine_t *model) +{ + int ret; + + ret = bios_load_linear("roms/machines/tg486gp/tg486gp.bin", + 0x000e0000, 131072, 0); + + if (bios_only || !ret) + return ret; + + machine_at_common_ide_init(model); + + device_add(&ali1429g_device); + + device_add(&fdc37c665_ide_pri_device); + + pci_init(FLAG_MECHANISM_1 | FLAG_MECHANISM_2 | PCI_ALWAYS_EXPOSE_DEV0); + pci_register_slot(0x00, PCI_CARD_NORTHBRIDGE, 0, 0, 0, 0); + + pci_register_slot(0x0F, PCI_CARD_NORMAL, 1, 2, 3, 4); + pci_register_slot(0x0D, PCI_CARD_NORMAL, 2, 3, 4, 1); + pci_register_slot(0x0B, PCI_CARD_NORMAL, 3, 4, 1, 2); + pci_register_slot(0x10, PCI_CARD_NORMAL, 1, 2, 3, 4); + + device_add(&ali1435_device); + device_add(&sst_flash_29ee010_device); + + device_add(&keyboard_ps2_tg_ami_device); + + return ret; +} + +int +machine_at_tg486g_init(const machine_t *model) +{ + int ret; + + ret = bios_load_linear("roms/machines/tg486g/tg486g.bin", + 0x000c0000, 262144, 0); + + if (bios_only || !ret) + return ret; + + machine_at_common_init(model); + device_add(&sis_85c471_device); + device_add(&ide_isa_device); + device_add(&fdc37c651_ide_device); + device_add(&keyboard_ps2_tg_ami_pci_device); + + if (gfxcard[0] != VID_INTERNAL) { + for (uint16_t i = 0; i < 32768; i++) + rom[i] = mem_readb_phys(0x000c0000 + i); + } + mem_mapping_set_addr(&bios_mapping, 0x0c0000, 0x40000); + mem_mapping_set_exec(&bios_mapping, rom); return ret; } diff --git a/src/machine/m_at_commodore.c b/src/machine/m_at_commodore.c index 8aa75059f..a0b522371 100644 --- a/src/machine/m_at_commodore.c +++ b/src/machine/m_at_commodore.c @@ -1,22 +1,22 @@ /* - * VARCem Virtual ARchaeological Computer EMulator. - * An emulator of (mostly) x86-based PC systems and devices, - * using the ISA,EISA,VLB,MCA and PCI system buses, roughly - * spanning the era between 1981 and 1995. + * 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 VARCem Project. + * This file is part of the 86Box distribution. * - * Implementation of the Commodore PC3 system. + * Implementation of the Commodore PC3 system. * * * - * Authors: Fred N. van Kempen, - * Miran Grca, - * Sarah Walker, + * Authors: Fred N. van Kempen, + * Miran Grca, + * Sarah Walker, * - * Copyright 2017,2018 Fred N. van Kempen. - * Copyright 2016-2018 Miran Grca. - * Copyright 2008-2018 Sarah Walker. + * Copyright 2017-2018 Fred N. van Kempen. + * Copyright 2016-2018 Miran Grca. + * Copyright 2008-2018 Sarah Walker. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -35,7 +35,7 @@ * 59 Temple Place - Suite 330 * Boston, MA 02111-1307 * USA. -*/ + */ #include #include #include @@ -52,65 +52,68 @@ #include <86box/fdd.h> #include <86box/fdc.h> #include <86box/machine.h> - +#include <86box/plat_unused.h> static serial_t *cmd_uart; - static void -cbm_io_write(uint16_t port, uint8_t val, void *p) +cbm_io_write(UNUSED(uint16_t port), uint8_t val, UNUSED(void *priv)) { lpt1_remove(); lpt2_remove(); switch (val & 3) { - case 1: - lpt1_init(0x3bc); - break; - case 2: - lpt1_init(0x378); - break; - case 3: - lpt1_init(0x278); - break; + case 1: + lpt1_init(LPT_MDA_ADDR); + break; + case 2: + lpt1_init(LPT1_ADDR); + break; + case 3: + lpt1_init(LPT2_ADDR); + break; + + default: + break; } switch (val & 0xc) { - case 0x4: - serial_setup(cmd_uart, 0x2f8, 3); - break; - case 0x8: - serial_setup(cmd_uart, 0x3f8, 4); - break; + case 0x4: + serial_setup(cmd_uart, COM2_ADDR, COM2_IRQ); + break; + case 0x8: + serial_setup(cmd_uart, COM1_ADDR, COM1_IRQ); + break; + + default: + break; } } - static void -cbm_io_init() +cbm_io_init(void) { - io_sethandler(0x0230, 0x0001, NULL,NULL,NULL, cbm_io_write,NULL,NULL, NULL); + io_sethandler(0x0230, 0x0001, NULL, NULL, NULL, cbm_io_write, NULL, NULL, NULL); } - int machine_at_cmdpc_init(const machine_t *model) { int ret; ret = bios_load_interleaved("roms/machines/cmdpc30/commodore pc 30 iii even.bin", - "roms/machines/cmdpc30/commodore pc 30 iii odd.bin", - 0x000f8000, 32768, 0); + "roms/machines/cmdpc30/commodore pc 30 iii odd.bin", + 0x000f8000, 32768, 0); if (bios_only || !ret) - return ret; + return ret; machine_at_init(model); mem_remap_top(384); if (fdc_type == FDC_INTERNAL) - device_add(&fdc_at_device); + device_add(&fdc_at_device); cmd_uart = device_add(&ns8250_device); diff --git a/src/machine/m_at_compaq.c b/src/machine/m_at_compaq.c index 3c1db5ea6..86656b181 100644 --- a/src/machine/m_at_compaq.c +++ b/src/machine/m_at_compaq.c @@ -1,21 +1,21 @@ /* - * 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. + * 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. + * This file is part of the 86Box distribution. * - * Emulation of various Compaq PC's. + * Emulation of various Compaq PC's. * * * - * Authors: Sarah Walker, - * Miran Grca, - * TheCollector1995, + * Authors: Sarah Walker, + * Miran Grca, + * TheCollector1995, * - * Copyright 2008-2018 Sarah Walker. - * Copyright 2016-2018 Miran Grca. + * Copyright 2008-2018 Sarah Walker. + * Copyright 2016-2018 Miran Grca. */ #include #include @@ -31,6 +31,8 @@ #include <86box/mem.h> #include <86box/rom.h> #include <86box/device.h> +#include <86box/chipset.h> +#include <86box/keyboard.h> #include <86box/fdd.h> #include <86box/fdc.h> #include <86box/fdc_ext.h> @@ -40,741 +42,710 @@ #include <86box/video.h> #include <86box/vid_cga.h> #include <86box/vid_cga_comp.h> +#include <86box/plat_unused.h> -enum -{ +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_05_1988 }; -#define CGA_RGB 0 +#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) +#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, black; -static uint32_t blinkcols[256][2]; -static uint32_t normcols[256][2]; +static uint32_t amber; +static uint32_t black; +static uint32_t blinkcols[256][2]; +static uint32_t normcols[256][2]; /* Video options set by the motherboard; they will be picked up by the card * on the next poll. * * Bit 3: Disable built-in video (for add-on card) * Bit 2: Thin font - * Bits 0,1: Font set (not currently implemented) - */ + * Bits 0,1: Font set (not currently implemented) + */ static int8_t cpq_st_display_internal = -1; -static void +static uint8_t mdaattr[256][2][2]; + +static void compaq_plasma_display_set(uint8_t internal) { - cpq_st_display_internal = internal; + cpq_st_display_internal = internal; } -static uint8_t +static uint8_t compaq_plasma_display_get(void) { - return cpq_st_display_internal; + return cpq_st_display_internal; } - -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; +typedef struct compaq_plasma_t { + cga_t cga; + uint8_t port_23c6; + uint8_t internal_monitor; + 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; +static mem_mapping_t ram_mapping; static void compaq_plasma_recalcattrs(compaq_plasma_t *self); -static void +static void compaq_plasma_recalctimings(compaq_plasma_t *self) { - double _dispontime, _dispofftime, disptime; + double _dispontime; + double _dispofftime; + double disptime; - if (!self->internal_monitor && !(self->port_23c6 & 1)) { - cga_recalctimings(&self->cga); - return; - } + if (!self->internal_monitor && !(self->port_23c6 & 1)) { + cga_recalctimings(&self->cga); + return; + } - 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)); + disptime = 651; + _dispontime = 640; + _dispofftime = disptime - _dispontime; + 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(UNUSED(void *priv)) +{ + 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 compaq_plasma_write(uint32_t addr, uint8_t val, void *priv) { - compaq_plasma_t *self = (compaq_plasma_t *)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 compaq_plasma_read(uint32_t addr, void *priv) { - compaq_plasma_t *self = (compaq_plasma_t *)priv; - uint8_t ret; + 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 x, c; - uint8_t chr, 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 (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 x, c; - uint8_t chr, 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 (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) -{ - int x, c; - 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 (x = 0; x < 80; x++) { - dat = self->vram[(addr & 0x7FFF)]; - addr++; - - for (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) -{ - int x, c; - uint8_t dat, pattern; - uint32_t ink0 = 0, 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 (x = 0; x < 80; x++) { - dat = self->vram[(addr & 0x7FFF)]; - addr++; - - for (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; - } - } + return ret; } static void compaq_plasma_out(uint16_t addr, uint8_t val, void *priv) { - compaq_plasma_t *self = (compaq_plasma_t *)priv; - uint8_t old; + compaq_plasma_t *self = (compaq_plasma_t *) priv; + uint8_t old; - switch (addr) { - /* Emulated CRTC, register select */ - case 0x3d4: - self->cga.crtcreg = val & 31; - break; + switch (addr) { + /* Emulated CRTC, register select */ + case 0x3d4: + cga_out(addr, val, &self->cga); + break; - /* Emulated CRTC, value */ - case 0x3d5: - old = self->cga.crtc[self->cga.crtcreg]; - self->cga.crtc[self->cga.crtcreg] = val & cga_crtcmask[self->cga.crtcreg]; + /* Emulated CRTC, value */ + case 0x3d5: + old = self->cga.crtc[self->cga.crtcreg]; + self->cga.crtc[self->cga.crtcreg] = val & cga_crtcmask[self->cga.crtcreg]; - /* Register 0x12 controls the attribute mappings for the - * plasma screen. */ - if (self->cga.crtcreg == 0x12) { - self->attrmap = val; - compaq_plasma_recalcattrs(self); - break; - } - - if (old != val) { - if (self->cga.crtcreg < 0xe || self->cga.crtcreg > 0x10) { - fullchange = changeframecount; - compaq_plasma_recalctimings(self); - } - } - break; - - case 0x3d8: - self->cga.cgamode = val; - break; + /* Register 0x12 controls the attribute mappings for the + * plasma screen. */ + if (self->cga.crtcreg == 0x12) { + self->attrmap = val; + compaq_plasma_recalcattrs(self); + break; + } - case 0x3d9: - self->cga.cgacol = val; - break; + if (old != val) { + if (self->cga.crtcreg < 0xe || self->cga.crtcreg > 0x10) { + self->cga.fullchange = changeframecount; + compaq_plasma_recalctimings(self); + } + } + break; + case 0x3d8: + case 0x3d9: + cga_out(addr, val, &self->cga); + break; - case 0x13c6: - if (val & 8) - compaq_plasma_display_set(1); - else - compaq_plasma_display_set(0); - break; - - case 0x23c6: - self->port_23c6 = val; - if (val & 8) /* Disable internal CGA */ - mem_mapping_disable(&self->plasma_mapping); - else - mem_mapping_enable(&self->plasma_mapping); - break; - } + case 0x13c6: + 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->cga.mapping); + else + mem_mapping_enable(&self->cga.mapping); + break; + + default: + break; + } } - static uint8_t compaq_plasma_in(uint16_t addr, void *priv) { - compaq_plasma_t *self = (compaq_plasma_t *)priv; - uint8_t ret = 0xff; + compaq_plasma_t *self = (compaq_plasma_t *) priv; + uint8_t ret = 0xff; - switch (addr) { - case 0x3d4: - ret = self->cga.crtcreg; - break; + switch (addr) { + case 0x3d4: + case 0x3da: + ret = cga_in(addr, &self->cga); + break; - case 0x3d5: - if (self->cga.crtcreg == 0x12) { - ret = self->attrmap & 0x0F; - if (self->internal_monitor) - ret |= 0x30; /* Plasma / CRT */ - } else - ret = self->cga.crtc[self->cga.crtcreg]; - break; + case 0x3d5: + if (self->cga.crtcreg == 0x12) { + ret = self->attrmap & 0x0f; + if (self->internal_monitor) + ret |= 0x30; /* Plasma / CRT */ + } else + ret = cga_in(addr, &self->cga); + break; - case 0x3da: - ret = self->cga.cgastat; - break; - - case 0x13c6: - if (compaq_plasma_display_get()) - ret = 8; - else - ret = 0; - break; + case 0x13c6: + ret = compaq_plasma_display_get() ? 8 : 0; + ret |= 4; + break; - case 0x23c6: - ret = self->port_23c6; - 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; - return ret; + case 0x23c6: + ret = 0; + break; + + default: + break; + } + + return ret; } static void -compaq_plasma_poll(void *p) +compaq_plasma_poll(void *priv) { - compaq_plasma_t *self = (compaq_plasma_t *)p; - - /* Switch between internal plasma and external CRT display. */ - if (cpq_st_display_internal != -1 && cpq_st_display_internal != self->internal_monitor) { - self->internal_monitor = cpq_st_display_internal; - compaq_plasma_recalctimings(self); - } + compaq_plasma_t *self = (compaq_plasma_t *) priv; + uint8_t chr; + uint8_t 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 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 dat; + uint8_t pattern; + uint32_t ink0 = 0; + uint32_t ink1 = 0; - if (!self->internal_monitor && !(self->port_23c6 & 1)) { - cga_poll(&self->cga); - return; - } - - if (!self->linepos) { - timer_advance_u64(&self->cga.timer, self->dispofftime); - self->cga.cgastat |= 1; - self->linepos = 1; - if (self->dispon) { - if (self->displine == 0) - video_wait_for_buffer(); + /* Switch between internal plasma and external CRT display. */ + if ((cpq_st_display_internal != -1) && (cpq_st_display_internal != self->internal_monitor)) { + self->internal_monitor = cpq_st_display_internal; + compaq_plasma_recalctimings(self); + } - /* Graphics */ - if (self->cga.cgamode & 0x02) { - if (self->cga.cgamode & 0x10) - compaq_plasma_cgaline6(self); - else - compaq_plasma_cgaline4(self); - } - else if (self->cga.cgamode & 0x01) /* High-res text */ - compaq_plasma_text80(self); - else - compaq_plasma_text40(self); - } - self->displine++; - /* Hardcode a fixed refresh rate and VSYNC timing */ - if (self->displine == 400) { /* Start of VSYNC */ - self->cga.cgastat |= 8; - self->dispon = 0; - } - if (self->displine == 416) { /* End of VSYNC */ - self->displine = 0; - self->cga.cgastat &= ~8; - self->dispon = 1; - } - } else { - if (self->dispon) - self->cga.cgastat &= ~1; + /* graphic mode and not mode 40h */ + if (!self->internal_monitor && !(self->port_23c6 & 1)) { + cga_poll(&self->cga); + return; + } - timer_advance_u64(&self->cga.timer, self->dispontime); - self->linepos = 0; + /* mode 40h or text mode */ + if (!self->cga.linepos) { + timer_advance_u64(&self->cga.timer, self->cga.dispofftime); + self->cga.cgastat |= 1; + 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 (uint8_t x = 0; x < 80; x++) { + dat = self->cga.vram[addr & 0x7FFF]; + addr++; - if (self->displine == 400) { - /* Hardcode 640x400 window size */ - if ((640 != xsize) || (400 != ysize) || video_force_resize_get()) { - xsize = 640; - ysize = 400; - if (xsize < 64) - xsize = 656; - if (ysize < 32) - ysize = 200; - set_screen_size(xsize, ysize); - - if (video_force_resize_get()) - video_force_resize_set(0); + for (uint8_t c = 0; c < 8; c++) { + ink = (dat & 0x80) ? fg : bg; + if (!(self->cga.cgamode & 8)) + ink = black; + (buffer32->line[self->cga.displine])[x * 8 + c] = ink; + dat <<= 1; } - video_blit_memtoscreen(0, 0, xsize, ysize); - frames++; + } + } else { + addr = ((self->cga.displine >> 1) & 1) * 0x2000 + (self->cga.displine >> 2) * 80 + ((ma & ~1) << 1); + for (uint8_t x = 0; x < 80; x++) { + dat = self->cga.vram[addr & 0x7fff]; + addr++; - /* Fixed 640x400 resolution */ - video_res_x = 640; - video_res_y = 400; + for (uint8_t c = 0; c < 4; c++) { + pattern = (dat & 0xC0) >> 6; + if (!(self->cga.cgamode & 8)) + pattern = 0; - if (self->cga.cgamode & 0x02) { - if (self->cga.cgamode & 0x10) - video_bpp = 1; - else - video_bpp = 2; + 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; - } else - video_bpp = 0; - self->cga.cgablink++; + default: + break; + } + buffer32->line[self->cga.displine][x * 8 + 2 * c] = ink0; + buffer32->line[self->cga.displine][x * 8 + 2 * c + 1] = ink1; + dat <<= 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 + cursorline = ((self->cga.crtc[0x0a] & 0x0f) * 2 <= sc) && ((self->cga.crtc[0x0b] & 0x0F) * 2 >= sc); + + /* for each text column */ + for (uint8_t x = 0; x < 80; x++) { + /* video output enabled */ + chr = self->cga.vram[(addr + 2 * x) & 0x7FFF]; + attr = self->cga.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); + underline = ((self->port_23c6 & 0x40) && (attr & 0x1) && !(attr & 0x6)); + /* blink active */ + if (self->cga.cgamode & 0x20) { + cols[1] = blinkcols[attr][1]; + cols[0] = blinkcols[attr][0]; + /* attribute 7 active and not cursor */ + if (blink) { + /* set blinking */ + cols[1] = cols[0]; + } + } else { + /* Set intensity bit */ + cols[1] = normcols[attr][1]; + cols[0] = normcols[attr][0]; + } + /* character underline active and 7th row of pixels in character height being drawn */ + if (underline && (sc == 7)) { + /* for each pixel in character width */ + for (uint8_t c = 0; c < 8; c++) + buffer32->line[self->cga.displine][(x << 3) + c] = mdaattr[attr][blink][1]; + } else if (drawcursor) { + for (uint8_t c = 0; c < 8; c++) + buffer32->line[self->cga.displine][(x << 3) + c] = cols[(fontdatm2[chr + self->cga.fontbase][sc] & (1 << (c ^ 7))) ? 1 : 0] ^ (amber ^ black); + } else { + for (uint8_t c = 0; c < 8; c++) + buffer32->line[self->cga.displine][(x << 3) + c] = cols[(fontdatm2[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 (uint8_t x = 0; x < 40; x++) { + chr = self->cga.vram[(addr + 2 * x) & 0x7FFF]; + attr = self->cga.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); + underline = ((self->port_23c6 & 0x40) && (attr & 0x1) && !(attr & 0x6)); + /* blink active */ + if (self->cga.cgamode & 0x20) { + cols[1] = blinkcols[attr][1]; + cols[0] = blinkcols[attr][0]; + /* attribute 7 active and not cursor */ + if (blink) { + /* set blinking */ + cols[1] = cols[0]; + } + } else { + /* Set intensity bit */ + cols[1] = normcols[attr][1]; + cols[0] = normcols[attr][0]; + } + /* character underline active and 7th row of pixels in character height being drawn */ + if (underline && (sc == 7)) { + /* for each pixel in character width */ + for (uint8_t 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 (uint8_t 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[(fontdatm2[chr][sc] & (1 << (c ^ 7))) ? 1 : 0] ^ (amber ^ black); + } else { + for (uint8_t 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[(fontdatm2[chr][sc] & (1 << (c ^ 7))) ? 1 : 0]; + } + ++ma; + } + } } + self->cga.displine++; + /* Hardcode a fixed refresh rate and VSYNC timing */ + if (self->cga.displine == 400) { /* Start of VSYNC */ + self->cga.cgastat |= 8; + self->cga.cgadispon = 0; + } + if (self->cga.displine == 416) { /* End of VSYNC */ + self->cga.displine = 0; + self->cga.cgastat &= ~8; + self->cga.cgadispon = 1; + } + } else { + if (self->cga.cgadispon) + self->cga.cgastat &= ~1; + + timer_advance_u64(&self->cga.timer, self->cga.dispontime); + self->cga.linepos = 0; + + if (self->cga.displine == 400) { + /* Hardcode 640x400 window size */ + if ((640 != xsize) || (400 != ysize) || video_force_resize_get()) { + xsize = 640; + ysize = 400; + if (xsize < 64) + xsize = 656; + if (ysize < 32) + ysize = 200; + set_screen_size(xsize, ysize); + + if (video_force_resize_get()) + video_force_resize_set(0); + } + video_blit_memtoscreen(0, 0, xsize, ysize); + frames++; + + /* Fixed 640x400 resolution */ + video_res_x = 640; + video_res_y = 400; + + if (self->cga.cgamode & 0x02) { + if (self->cga.cgamode & 0x10) + video_bpp = 1; + else + video_bpp = 2; + } else + video_bpp = 0; + + self->cga.cgablink++; + } + } } -static void +static void +compaq_plasma_mdaattr_rebuild(void) +{ + for (uint16_t 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) { - int n; + int n; - /* val behaves as follows: - * Bit 0: Attributes 01-06, 08-0E are inverse video - * Bit 1: Attributes 01-06, 08-0E are bold - * Bit 2: Attributes 11-16, 18-1F, 21-26, 28-2F ... F1-F6, F8-FF - * are inverse video - * Bit 3: Attributes 11-16, 18-1F, 21-26, 28-2F ... F1-F6, F8-FF - * are bold */ + /* val behaves as follows: + * Bit 0: Attributes 01-06, 08-0E are inverse video + * Bit 1: Attributes 01-06, 08-0E are bold + * Bit 2: Attributes 11-16, 18-1F, 21-26, 28-2F ... F1-F6, F8-FF + * are inverse video + * Bit 3: Attributes 11-16, 18-1F, 21-26, 28-2F ... F1-F6, F8-FF + * are bold */ - /* Set up colours */ - amber = makecol(0xff, 0x7D, 0x00); - black = makecol(0x64, 0x19, 0x00); + /* Set up colours */ + amber = makecol(0xff, 0x7d, 0x00); + black = makecol(0x64, 0x0c, 0x00); - /* Initialise 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; - blinkcols[n][1] = normcols[n][1] = black; - } + /* 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; + blinkcols[n][1] = normcols[n][1] = black; + } - /* Colours 0x11-0xFF are controlled by bits 2 and 3 of the - * passed value. Exclude x0 and x8, which are always black on - * amber. */ - for (n = 0x11; n <= 0xFF; n++) { - if ((n & 7) == 0) - continue; - if (self->attrmap & 4) { /* Inverse */ - blinkcols[n][0] = normcols[n][0] = amber; - blinkcols[n][1] = normcols[n][1] = black; - } else { /* Normal */ - blinkcols[n][0] = normcols[n][0] = black; - blinkcols[n][1] = normcols[n][1] = amber; - } - } - /* Set up the 01-0E range, controlled by bits 0 and 1 of the - * passed value. When blinking is enabled this also affects 81-8E. */ - for (n = 0x01; n <= 0x0E; n++) { - if (n == 7) - continue; - if (self->attrmap & 1) { - blinkcols[n][0] = normcols[n][0] = amber; - blinkcols[n][1] = normcols[n][1] = black; - blinkcols[n+128][0] = amber; - blinkcols[n+128][1] = black; - } else { - blinkcols[n][0] = normcols[n][0] = black; - blinkcols[n][1] = normcols[n][1] = amber; - blinkcols[n+128][0] = black; - blinkcols[n+128][1] = amber; - } - } - /* Colours 07 and 0F are always amber on black. If blinking is - * enabled so are 87 and 8F. */ - for (n = 0x07; n <= 0x0F; n += 8) { - blinkcols[n][0] = normcols[n][0] = black; - blinkcols[n][1] = normcols[n][1] = amber; - blinkcols[n+128][0] = black; - blinkcols[n+128][1] = amber; - } - /* When not blinking, colours 81-8F are always amber on black. */ - for (n = 0x81; n <= 0x8F; n ++) { - normcols[n][0] = black; - normcols[n][1] = amber; - } + /* Colours 0x11-0xFF are controlled by bits 2 and 3 of the + * passed value. Exclude x0 and x8, which are always black on + * amber. */ + for (n = 0x11; n <= 0xFF; n++) { + if ((n & 7) == 0) + continue; + if (self->attrmap & 4) { /* Inverse */ + blinkcols[n][0] = normcols[n][0] = amber; + blinkcols[n][1] = normcols[n][1] = black; + } else { /* Normal */ + blinkcols[n][0] = normcols[n][0] = black; + blinkcols[n][1] = normcols[n][1] = amber; + } + } + /* Set up the 01-0E range, controlled by bits 0 and 1 of the + * passed value. When blinking is enabled this also affects 81-8E. */ + for (n = 0x01; n <= 0x0E; n++) { + if (n == 7) + continue; + if (self->attrmap & 1) { + blinkcols[n][0] = normcols[n][0] = amber; + blinkcols[n][1] = normcols[n][1] = black; + blinkcols[n + 128][0] = amber; + blinkcols[n + 128][1] = black; + } else { + blinkcols[n][0] = normcols[n][0] = black; + blinkcols[n][1] = normcols[n][1] = amber; + blinkcols[n + 128][0] = black; + blinkcols[n + 128][1] = amber; + } + } + /* Colours 07 and 0F are always amber on black. If blinking is + * enabled so are 87 and 8F. */ + for (n = 0x07; n <= 0x0F; n += 8) { + blinkcols[n][0] = normcols[n][0] = black; + blinkcols[n][1] = normcols[n][1] = amber; + blinkcols[n + 128][0] = black; + blinkcols[n + 128][1] = amber; + } + /* When not blinking, colours 81-8F are always amber on black. */ + for (n = 0x81; n <= 0x8F; n++) { + normcols[n][0] = black; + normcols[n][1] = amber; + } - /* Finally do the ones which are solid black. These differ between - * the normal and blinking mappings */ - for (n = 0; n <= 0xFF; n += 0x11) - normcols[n][0] = normcols[n][1] = black; + /* Finally do the ones which are solid black. These differ between + * the normal and blinking mappings */ + for (n = 0; n <= 0xFF; n += 0x11) + normcols[n][0] = normcols[n][1] = black; - /* In the blinking range, 00 11 22 .. 77 and 80 91 A2 .. F7 are black */ - for (n = 0; n <= 0x77; n += 0x11) { - blinkcols[n][0] = blinkcols[n][1] = black; - blinkcols[n+128][0] = blinkcols[n+128][1] = black; - } + /* In the blinking range, 00 11 22 .. 77 and 80 91 A2 .. F7 are black */ + for (n = 0; n <= 0x77; n += 0x11) { + blinkcols[n][0] = blinkcols[n][1] = black; + blinkcols[n + 128][0] = blinkcols[n + 128][1] = black; + } } static void * -compaq_plasma_init(const device_t *info) +compaq_plasma_init(UNUSED(const device_t *info)) { - int display_type; - compaq_plasma_t *self = malloc(sizeof(compaq_plasma_t)); - memset(self, 0, sizeof(compaq_plasma_t)); + 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", 11, 0x4bb2); - self->vram = malloc(0x8000); - self->internal_monitor = 1; + self->cga.composite = 0; + self->cga.revision = 0; - 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); - 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(0x23c6, 0x0001, compaq_plasma_in, NULL, NULL, compaq_plasma_out, NULL, NULL, self); + self->cga.vram = malloc(0x8000); + self->internal_monitor = 1; - /* Default attribute mapping is 4 */ - self->attrmap = 4; - compaq_plasma_recalcattrs(self); + cga_comp_init(self->cga.revision); + timer_add(&self->cga.timer, compaq_plasma_poll, self, 1); + 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); - self->cga.cgastat = 0xF4; - self->cga.vram = self->vram; + /* Default attribute mapping is 4 */ + self->attrmap = 4; + compaq_plasma_recalcattrs(self); - overscan_x = overscan_y = 16; + 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(); - - return self; + 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; } static void -compaq_plasma_close(void *p) +compaq_plasma_close(void *priv) { - compaq_plasma_t *self = (compaq_plasma_t *)p; + compaq_plasma_t *self = (compaq_plasma_t *) priv; - free(self->vram); - - free(self); + free(self->cga.vram); + free(self); } static void -compaq_plasma_speed_changed(void *p) +compaq_plasma_speed_changed(void *priv) { - compaq_plasma_t *self = (compaq_plasma_t *)p; + compaq_plasma_t *self = (compaq_plasma_t *) priv; - compaq_plasma_recalctimings(self); + compaq_plasma_recalctimings(self); } -const device_config_t compaq_plasma_config[] = -{ - { - "display_type", "Display type", CONFIG_SELECTION, "", CGA_RGB, "", { 0 }, - { - { - "RGB", CGA_RGB - }, - { - "Composite", CGA_COMPOSITE - }, - { - "" - } - } - }, - { - "composite_type", "Composite type", CONFIG_SELECTION, "", COMPOSITE_OLD, "", { 0 }, - { - { - "Old", COMPOSITE_OLD - }, - { - "New", COMPOSITE_NEW - }, - { - "" - } - } - }, - { - "rgb_type", "RGB type", CONFIG_SELECTION, "", 0, "", { 0 }, - { - { - "Color", 0 - }, - { - "Green Monochrome", 1 - }, - { - "Amber Monochrome", 2 - }, - { - "Gray Monochrome", 3 - }, - { - "Color (no brown)", 4 - }, - { - "" - } - } - }, - { - "", "", -1 +const device_config_t compaq_plasma_config[] = { + // clang-format off + { + .name = "rgb_type", + .description = "RGB type", + .type = CONFIG_SELECTION, + .default_string = "", + .default_int = 0, + .file_filter = "", + .spinner = { 0 }, + .selection = { + { .description = "Color", .value = 0 }, + { .description = "Green Monochrome", .value = 1 }, + { .description = "Amber Monochrome", .value = 2 }, + { .description = "Gray Monochrome", .value = 3 }, + { .description = "" } } + }, + { .name = "", .description = "", .type = CONFIG_END } + // clang-format on }; - -static const device_t compaq_plasma_device = -{ - "Compaq Plasma", - "compaq_plasma", - 0, 0, - compaq_plasma_init, - compaq_plasma_close, - NULL, - { NULL }, - compaq_plasma_speed_changed, - NULL, - compaq_plasma_config +const device_t compaq_plasma_device = { + .name = "Compaq Plasma", + .internal_name = "compaq_plasma", + .flags = 0, + .local = 0, + .init = compaq_plasma_init, + .close = compaq_plasma_close, + .reset = NULL, + { .available = NULL }, + .speed_changed = compaq_plasma_speed_changed, + .force_redraw = NULL, + .config = compaq_plasma_config }; static uint8_t -read_ram(uint32_t addr, void *priv) +read_ram(uint32_t addr, UNUSED(void *priv)) { addr = (addr & 0x7ffff) + 0x80000; addreadlookup(mem_logical_addr, addr); - return(ram[addr]); + return (ram[addr]); } - static uint16_t -read_ramw(uint32_t addr, void *priv) +read_ramw(uint32_t addr, UNUSED(void *priv)) { addr = (addr & 0x7ffff) + 0x80000; addreadlookup(mem_logical_addr, addr); - return(*(uint16_t *)&ram[addr]); + return (*(uint16_t *) &ram[addr]); } - static uint32_t -read_raml(uint32_t addr, void *priv) +read_raml(uint32_t addr, UNUSED(void *priv)) { addr = (addr & 0x7ffff) + 0x80000; addreadlookup(mem_logical_addr, addr); - return(*(uint32_t *)&ram[addr]); + return (*(uint32_t *) &ram[addr]); } - static void -write_ram(uint32_t addr, uint8_t val, void *priv) +write_ram(uint32_t addr, uint8_t val, UNUSED(void *priv)) { addr = (addr & 0x7ffff) + 0x80000; addwritelookup(mem_logical_addr, addr); @@ -782,9 +753,8 @@ write_ram(uint32_t addr, uint8_t val, void *priv) mem_write_ramb_page(addr, val, &pages[addr >> 12]); } - static void -write_ramw(uint32_t addr, uint16_t val, void *priv) +write_ramw(uint32_t addr, uint16_t val, UNUSED(void *priv)) { addr = (addr & 0x7ffff) + 0x80000; addwritelookup(mem_logical_addr, addr); @@ -792,9 +762,8 @@ write_ramw(uint32_t addr, uint16_t val, void *priv) mem_write_ramw_page(addr, val, &pages[addr >> 12]); } - static void -write_raml(uint32_t addr, uint32_t val, void *priv) +write_raml(uint32_t addr, uint32_t val, UNUSED(void *priv)) { addr = (addr & 0x7ffff) + 0x80000; addwritelookup(mem_logical_addr, addr); @@ -802,53 +771,56 @@ write_raml(uint32_t addr, uint32_t val, void *priv) mem_write_raml_page(addr, val, &pages[addr >> 12]); } -const device_t * -at_cpqiii_get_device(void) -{ - return &compaq_plasma_device; -} - static void machine_at_compaq_init(const machine_t *model, int type) { - if (type != COMPAQ_DESKPRO386) - mem_remap_top(384); - - if (fdc_type == FDC_INTERNAL) - device_add(&fdc_at_device); + compaq_machine_type = type; - 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 (fdc_type == FDC_INTERNAL) + device_add(&fdc_at_device); - video_reset(gfxcard); - - switch(type) { - case COMPAQ_PORTABLEII: - break; - - case COMPAQ_PORTABLEIII: - if (gfxcard == VID_INTERNAL) - device_add(&compaq_plasma_device); - break; - - case COMPAQ_PORTABLEIII386: - if (hdc_current == 1) - device_add(&ide_isa_device); - if (gfxcard == VID_INTERNAL) - device_add(&compaq_plasma_device); - break; - - case COMPAQ_DESKPRO386: - if (hdc_current == 1) - device_add(&ide_isa_device); - break; + if (type < COMPAQ_PORTABLEIII386) { + mem_remap_top(384); + 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); } - machine_at_init(model); -} + 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: + if (hdc_current == 1) + 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_05_1988: + if (hdc_current == 1) + device_add(&ide_isa_device); + device_add(&compaq_386_device); + machine_at_common_init(model); + device_add(&keyboard_at_compaq_device); + break; + + default: + break; + } +} int machine_at_portableii_init(const machine_t *model) @@ -856,49 +828,78 @@ machine_at_portableii_init(const machine_t *model) int ret; ret = bios_load_interleavedr("roms/machines/portableii/109740-001.rom", - "roms/machines/portableii/109739-001.rom", - 0x000f8000, 65536, 0); + "roms/machines/portableii/109739-001.rom", + 0x000f8000, 65536, 0); if (bios_only || !ret) - return ret; + return ret; machine_at_compaq_init(model, COMPAQ_PORTABLEII); return ret; } - int 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; + return ret; machine_at_compaq_init(model, COMPAQ_PORTABLEIII); return ret; } - int 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; + return ret; machine_at_compaq_init(model, COMPAQ_PORTABLEIII386); return ret; } + +int +machine_at_deskpro386_init(const machine_t *model) +{ + int ret; + + ret = bios_load_linearr("roms/machines/deskpro386/1986-09-04-HI.json.bin", + 0x000f8000, 65536, 0); + + if (bios_only || !ret) + return ret; + + machine_at_compaq_init(model, COMPAQ_DESKPRO386); + + return ret; +} + +int +machine_at_deskpro386_05_1988_init(const machine_t *model) +{ + int ret; + + ret = bios_load_linearr("roms/machines/deskpro386/1988-05-10.json.bin", + 0x000f8000, 65536, 0); + + if (bios_only || !ret) + return ret; + + machine_at_compaq_init(model, COMPAQ_DESKPRO386_05_1988); + + return ret; +} diff --git a/src/machine/m_at_misc.c b/src/machine/m_at_misc.c index b41735d74..d4264f07e 100644 --- a/src/machine/m_at_misc.c +++ b/src/machine/m_at_misc.c @@ -1,74 +1,74 @@ -/* - * 86Box A hypervisor and IBM PC system emulator that specializes in - * running old operating systems and software designed for IBM - * PC systems and compatibles from 1981 through fairly recent - * system designs based on the PCI bus. - * - * This file is part of the 86Box distribution. - * - * Implementation of Miscellaneous, Fake, Hypervisor machines. - * - * - * - * Authors: Miran Grca, - * - * Copyright 2016-2019 Miran Grca. - */ -#include -#include -#include -#include -#include -#include <86box/86box.h> -#include <86box/mem.h> -#include <86box/io.h> -#include <86box/rom.h> -#include <86box/pci.h> -#include <86box/device.h> -#include <86box/chipset.h> -#include <86box/hdc.h> -#include <86box/hdc_ide.h> -#include <86box/keyboard.h> -#include <86box/flash.h> -#include <86box/sio.h> -#include <86box/hwm.h> -#include <86box/spd.h> -#include <86box/video.h> -#include "cpu.h" -#include <86box/machine.h> -#include <86box/sound.h> - -int -machine_at_vpc2007_init(const machine_t *model) -{ - int ret; - - ret = bios_load_linear("roms/machines/vpc2007/13500.bin", - 0x000c0000, 262144, 0); - - if (bios_only || !ret) - return ret; - - machine_at_common_init_ex(model, 2); - is_vpc = 1; - - pci_init(PCI_CONFIG_TYPE_1); - pci_register_slot(0x00, PCI_CARD_NORTHBRIDGE, 0, 0, 0, 0); - pci_register_slot(0x07, PCI_CARD_SOUTHBRIDGE, 0, 0, 0, 4); - pci_register_slot(0x08, PCI_CARD_NORMAL, 1, 2, 3, 4); - pci_register_slot(0x09, PCI_CARD_NORMAL, 1, 2, 3, 4); - pci_register_slot(0x0A, PCI_CARD_NORMAL, 1, 2, 3, 4); - pci_register_slot(0x0B, PCI_CARD_NORMAL, 1, 2, 3, 4); - pci_register_slot(0x0C, PCI_CARD_NORMAL, 1, 2, 3, 4); - pci_register_slot(0x0D, PCI_CARD_NORMAL, 1, 2, 3, 4); - pci_register_slot(0x0E, PCI_CARD_NORMAL, 1, 2, 3, 4); - pci_register_slot(0x0F, PCI_CARD_NORMAL, 1, 2, 3, 4); - device_add(&i440bx_no_agp_device); - device_add(&piix4e_device); - device_add(&w83977f_370_device); - device_add(&keyboard_ps2_ami_pci_device); - device_add(&intel_flash_bxt_device); - spd_register(SPD_TYPE_SDRAM, 0xF, 256); /* real VPC provides invalid SPD data */ - - return ret; -} +/* + * 86Box A hypervisor and IBM PC system emulator that specializes in + * running old operating systems and software designed for IBM + * PC systems and compatibles from 1981 through fairly recent + * system designs based on the PCI bus. + * + * This file is part of the 86Box distribution. + * + * Implementation of Miscellaneous, Fake, Hypervisor machines. + * + * + * + * Authors: Miran Grca, + * + * Copyright 2016-2019 Miran Grca. + */ +#include +#include +#include +#include +#include +#include <86box/86box.h> +#include <86box/mem.h> +#include <86box/io.h> +#include <86box/rom.h> +#include <86box/pci.h> +#include <86box/device.h> +#include <86box/chipset.h> +#include <86box/hdc.h> +#include <86box/hdc_ide.h> +#include <86box/keyboard.h> +#include <86box/flash.h> +#include <86box/sio.h> +#include <86box/hwm.h> +#include <86box/spd.h> +#include <86box/video.h> +#include "cpu.h" +#include <86box/machine.h> +#include <86box/sound.h> + +int +machine_at_vpc2007_init(const machine_t *model) +{ + int ret; + + ret = bios_load_linear("roms/machines/vpc2007/13500.bin", + 0x000c0000, 262144, 0); + + if (bios_only || !ret) + return ret; + + machine_at_common_init_ex(model, 2); + is_vpc = 1; + + pci_init(PCI_CONFIG_TYPE_1); + pci_register_slot(0x00, PCI_CARD_NORTHBRIDGE, 0, 0, 0, 0); + pci_register_slot(0x07, PCI_CARD_SOUTHBRIDGE, 0, 0, 0, 4); + pci_register_slot(0x08, PCI_CARD_NORMAL, 1, 2, 3, 4); + pci_register_slot(0x09, PCI_CARD_NORMAL, 1, 2, 3, 4); + pci_register_slot(0x0A, PCI_CARD_NORMAL, 1, 2, 3, 4); + pci_register_slot(0x0B, PCI_CARD_NORMAL, 1, 2, 3, 4); + pci_register_slot(0x0C, PCI_CARD_NORMAL, 1, 2, 3, 4); + pci_register_slot(0x0D, PCI_CARD_NORMAL, 1, 2, 3, 4); + pci_register_slot(0x0E, PCI_CARD_NORMAL, 1, 2, 3, 4); + pci_register_slot(0x0F, PCI_CARD_NORMAL, 1, 2, 3, 4); + device_add(&i440bx_no_agp_device); + device_add(&piix4e_device); + device_add(&w83977f_370_device); + device_add(&keyboard_ps2_ami_pci_device); + device_add(&intel_flash_bxt_device); + spd_register(SPD_TYPE_SDRAM, 0xF, 256); /* real VPC provides invalid SPD data */ + + return ret; +} diff --git a/src/machine/m_at_slot1.c b/src/machine/m_at_slot1.c index 0f34b0244..184cfc34d 100644 --- a/src/machine/m_at_slot1.c +++ b/src/machine/m_at_slot1.c @@ -1,18 +1,18 @@ /* - * 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. + * 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. + * This file is part of the 86Box distribution. * - * Implementation of Slot 1 machines. + * Implementation of Slot 1 machines. * * * - * Authors: Miran Grca, + * Authors: Miran Grca, * - * Copyright 2016-2019 Miran Grca. + * Copyright 2016-2019 Miran Grca. */ #include #include @@ -46,27 +46,26 @@ machine_at_p65up5_cpknd_init(const machine_t *model) int ret; ret = bios_load_linear("roms/machines/p65up5/NDKN0218.AWD", - 0x000e0000, 131072, 0); + 0x000e0000, 131072, 0); if (bios_only || !ret) - return ret; + return ret; machine_at_p65up5_common_init(model, &i440fx_device); return ret; } - int machine_at_kn97_init(const machine_t *model) { int ret; ret = bios_load_linear("roms/machines/kn97/0116I.001", - 0x000e0000, 131072, 0); + 0x000e0000, 131072, 0); if (bios_only || !ret) - return ret; + return ret; machine_at_common_init(model); @@ -85,22 +84,21 @@ machine_at_kn97_init(const machine_t *model) device_add(&intel_flash_bxt_device); device_add(&lm78_device); /* fans: Chassis, CPU, Power; temperature: MB */ for (uint8_t i = 0; i < 3; i++) - hwm_values.fans[i] *= 2; /* BIOS reports fans with the wrong divisor for some reason */ - + hwm_values.fans[i] *= 2; /* BIOS reports fans with the wrong divisor for some reason */ + return ret; } - int machine_at_lx6_init(const machine_t *model) { int ret; ret = bios_load_linear("roms/machines/lx6/LX6C_PZ.B00", - 0x000e0000, 131072, 0); + 0x000e0000, 131072, 0); if (bios_only || !ret) - return ret; + return ret; machine_at_common_init_ex(model, 2); @@ -118,21 +116,20 @@ machine_at_lx6_init(const machine_t *model) device_add(&w83977tf_device); device_add(&sst_flash_29ee010_device); spd_register(SPD_TYPE_SDRAM, 0xF, 256); - + return ret; } - int machine_at_spitfire_init(const machine_t *model) { int ret; ret = bios_load_linear("roms/machines/spitfire/SPIHM.02", - 0x000c0000, 262144, 0); + 0x000c0000, 262144, 0); if (bios_only || !ret) - return ret; + return ret; machine_at_common_init_ex(model, 2); @@ -155,58 +152,56 @@ machine_at_spitfire_init(const machine_t *model) return ret; } - int machine_at_p6i440e2_init(const machine_t *model) { int ret; ret = bios_load_linear("roms/machines/p6i440e2/E2_v14sl.bin", - 0x000e0000, 131072, 0); + 0x000e0000, 131072, 0); if (bios_only || !ret) - return ret; + return ret; machine_at_common_init_ex(model, 2); pci_init(PCI_CONFIG_TYPE_1); pci_register_slot(0x00, PCI_CARD_NORTHBRIDGE, 0, 0, 0, 0); pci_register_slot(0x07, PCI_CARD_SOUTHBRIDGE, 1, 2, 3, 4); - pci_register_slot(0x09, PCI_CARD_NORMAL, 1, 2, 3, 4); - pci_register_slot(0x0A, PCI_CARD_NORMAL, 2, 3, 4, 1); - pci_register_slot(0x01, PCI_CARD_AGPBRIDGE, 1, 2, 3, 4); + pci_register_slot(0x09, PCI_CARD_NORMAL, 1, 2, 3, 4); + pci_register_slot(0x0A, PCI_CARD_NORMAL, 2, 3, 4, 1); + pci_register_slot(0x01, PCI_CARD_AGPBRIDGE, 1, 2, 3, 4); device_add(&i440ex_device); device_add(&piix4_device); device_add(&keyboard_ps2_ami_pci_device); device_add(&w83977tf_device); device_add(&sst_flash_29ee010_device); spd_register(SPD_TYPE_SDRAM, 0x03, 256); - device_add(&w83781d_device); /* fans: CPU, CHS, PS; temperatures: unused, CPU, System */ - hwm_values.temperatures[0] = 0; /* unused */ - hwm_values.voltages[1] = 1500; /* CPUVTT */ + device_add(&w83781d_device); /* fans: CPU, CHS, PS; temperatures: unused, CPU, System */ + hwm_values.temperatures[0] = 0; /* unused */ + hwm_values.voltages[1] = 1500; /* CPUVTT */ return ret; } - int machine_at_p2bls_init(const machine_t *model) { int ret; ret = bios_load_linear("roms/machines/p2bls/1014ls.003", - 0x000c0000, 262144, 0); + 0x000c0000, 262144, 0); if (bios_only || !ret) - return ret; + return ret; machine_at_common_init_ex(model, 2); pci_init(PCI_CONFIG_TYPE_1); pci_register_slot(0x00, PCI_CARD_NORTHBRIDGE, 0, 0, 0, 0); pci_register_slot(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); @@ -216,27 +211,28 @@ machine_at_p2bls_init(const machine_t *model) device_add(&piix4e_device); device_add(&keyboard_ps2_ami_pci_device); device_add(&w83977ef_device); - //device_add(ics9xxx_get(ICS9150_08)); /* setting proper speeds requires some interaction with the AS97127F ASIC */ +#if 0 + device_add(ics9xxx_get(ICS9150_08)); /* setting proper speeds requires some interaction with the AS97127F ASIC */ +#endif device_add(&sst_flash_39sf020_device); spd_register(SPD_TYPE_SDRAM, 0xF, 256); - device_add(&w83781d_device); /* fans: Chassis, CPU, Power; temperatures: MB, unused, CPU */ - hwm_values.temperatures[1] = 0; /* unused */ + device_add(&w83781d_device); /* fans: Chassis, CPU, Power; temperatures: MB, unused, CPU */ + hwm_values.temperatures[1] = 0; /* unused */ hwm_values.temperatures[2] -= 3; /* CPU offset */ return ret; } - int machine_at_p3bf_init(const machine_t *model) { int ret; ret = bios_load_linear("roms/machines/p3bf/1008f.004", - 0x000c0000, 262144, 0); + 0x000c0000, 262144, 0); if (bios_only || !ret) - return ret; + return ret; machine_at_common_init_ex(model, 2); @@ -257,23 +253,22 @@ machine_at_p3bf_init(const machine_t *model) device_add(ics9xxx_get(ICS9250_08)); device_add(&sst_flash_39sf020_device); spd_register(SPD_TYPE_SDRAM, 0xF, 256); - device_add(&as99127f_device); /* fans: Chassis, CPU, Power; temperatures: MB, JTPWR, CPU */ + device_add(&as99127f_device); /* fans: Chassis, CPU, Power; temperatures: MB, JTPWR, CPU */ hwm_values.voltages[4] = hwm_values.voltages[5]; /* +12V reading not in line with other boards; appears to be close to the -12V reading */ return ret; } - int machine_at_bf6_init(const machine_t *model) { int ret; ret = bios_load_linear("roms/machines/bf6/Beh_70.bin", - 0x000c0000, 262144, 0); + 0x000c0000, 262144, 0); if (bios_only || !ret) - return ret; + return ret; machine_at_common_init_ex(model, 2); @@ -293,22 +288,21 @@ machine_at_bf6_init(const machine_t *model) device_add(&keyboard_ps2_pci_device); device_add(&w83977ef_device); device_add(&sst_flash_39sf020_device); - spd_register(SPD_TYPE_SDRAM, 0x7, 256); + spd_register(SPD_TYPE_SDRAM, 0x7, 256); return ret; } - int machine_at_ax6bc_init(const machine_t *model) { int ret; ret = bios_load_linear("roms/machines/ax6bc/AX6BC_R2.59.bin", - 0x000c0000, 262144, 0); + 0x000c0000, 262144, 0); if (bios_only || !ret) - return ret; + return ret; machine_at_common_init_ex(model, 2); @@ -332,17 +326,16 @@ machine_at_ax6bc_init(const machine_t *model) return ret; } - int machine_at_atc6310bxii_init(const machine_t *model) { int ret; ret = bios_load_linear("roms/machines/atc6310bxii/6310s102.bin", - 0x000c0000, 262144, 0); + 0x000c0000, 262144, 0); if (bios_only || !ret) - return ret; + return ret; machine_at_common_init_ex(model, 2); @@ -362,20 +355,19 @@ machine_at_atc6310bxii_init(const machine_t *model) device_add(&sst_flash_39sf020_device); spd_register(SPD_TYPE_SDRAM, 0x7, 256); - return ret; + return ret; } - int machine_at_686bx_init(const machine_t *model) { int ret; ret = bios_load_linear("roms/machines/686bx/6BX.F2a", - 0x000c0000, 262144, 0); + 0x000c0000, 262144, 0); if (bios_only || !ret) - return ret; + return ret; machine_at_common_init_ex(model, 2); @@ -393,27 +385,26 @@ machine_at_686bx_init(const machine_t *model) device_add(&w83977tf_device); device_add(&intel_flash_bxt_device); spd_register(SPD_TYPE_SDRAM, 0xF, 256); - device_add(&w83781d_device); /* fans: CPU, unused, unused; temperatures: unused, CPU, unused */ - hwm_values.temperatures[0] = 0; /* unused */ + device_add(&w83781d_device); /* fans: CPU, unused, unused; temperatures: unused, CPU, unused */ + hwm_values.temperatures[0] = 0; /* unused */ hwm_values.temperatures[1] += 4; /* CPU offset */ - hwm_values.temperatures[2] = 0; /* unused */ - hwm_values.fans[1] = 0; /* unused */ - hwm_values.fans[2] = 0; /* unused */ + hwm_values.temperatures[2] = 0; /* unused */ + hwm_values.fans[1] = 0; /* unused */ + hwm_values.fans[2] = 0; /* unused */ return ret; } - int machine_at_p6sba_init(const machine_t *model) { int ret; ret = bios_load_linear("roms/machines/p6sba/SBAB21.ROM", - 0x000c0000, 262144, 0); + 0x000c0000, 262144, 0); if (bios_only || !ret) - return ret; + return ret; machine_at_common_init_ex(model, 2); @@ -433,8 +424,8 @@ machine_at_p6sba_init(const machine_t *model) device_add(&keyboard_ps2_ami_pci_device); device_add(&intel_flash_bxt_device); spd_register(SPD_TYPE_SDRAM, 0x7, 256); - device_add(&w83781d_device); /* fans: CPU1, CPU2, Thermal Control; temperatures: unused, CPU1, CPU2? */ - hwm_values.fans[1] = 0; /* no CPU2 fan */ + device_add(&w83781d_device); /* fans: CPU1, CPU2, Thermal Control; temperatures: unused, CPU1, CPU2? */ + hwm_values.fans[1] = 0; /* no CPU2 fan */ hwm_values.temperatures[0] = 0; /* unused */ hwm_values.temperatures[2] = 0; /* CPU2? */ /* no CPU2 voltage */ @@ -442,17 +433,16 @@ machine_at_p6sba_init(const machine_t *model) return ret; } - int machine_at_s1846_init(const machine_t *model) { int ret; ret = bios_load_linear("roms/machines/s1846/bx46200f.rom", - 0x000c0000, 262144, 0); + 0x000c0000, 262144, 0); if (bios_only || !ret) - return ret; + return ret; machine_at_common_init_ex(model, 2); @@ -473,32 +463,24 @@ machine_at_s1846_init(const machine_t *model) device_add(&intel_flash_bxt_device); spd_register(SPD_TYPE_SDRAM, 0x7, 256); - if (sound_card_current == SOUND_INTERNAL) { - device_add(&es1371_onboard_device); - device_add(&cs4297_device); /* found on other Tyan boards around the same time */ + if (sound_card_current[0] == SOUND_INTERNAL) { + device_add(&es1371_onboard_device); + device_add(&cs4297_device); /* found on other Tyan boards around the same time */ } return ret; } - -const device_t * -at_s1846_get_device(void) -{ - return &es1371_onboard_device; -} - - int machine_at_ficka6130_init(const machine_t *model) { int ret; ret = bios_load_linear("roms/machines/ficka6130/qa4163.bin", - 0x000c0000, 262144, 0); + 0x000c0000, 262144, 0); if (bios_only || !ret) - return ret; + return ret; machine_at_common_init_ex(model, 2); @@ -520,17 +502,16 @@ machine_at_ficka6130_init(const machine_t *model) return ret; } - int machine_at_p3v133_init(const machine_t *model) { int ret; ret = bios_load_linear("roms/machines/p3v133/1003.002", - 0x000c0000, 262144, 0); + 0x000c0000, 262144, 0); if (bios_only || !ret) - return ret; + return ret; machine_at_common_init_ex(model, 2); @@ -551,24 +532,23 @@ machine_at_p3v133_init(const machine_t *model) device_add(ics9xxx_get(ICS9248_39)); device_add(&sst_flash_39sf020_device); spd_register(SPD_TYPE_SDRAM, 0x7, 512); - device_add(&w83781d_device); /* fans: Chassis, CPU, Power; temperatures: MB, unused, CPU */ - hwm_values.temperatures[1] = 0; /* unused */ + device_add(&w83781d_device); /* fans: Chassis, CPU, Power; temperatures: MB, unused, CPU */ + hwm_values.temperatures[1] = 0; /* unused */ hwm_values.temperatures[2] -= 3; /* CPU offset */ return ret; } - int machine_at_p3v4x_init(const machine_t *model) { int ret; ret = bios_load_linear("roms/machines/p3v4x/1006.004", - 0x000c0000, 262144, 0); + 0x000c0000, 262144, 0); if (bios_only || !ret) - return ret; + return ret; machine_at_common_init_ex(model, 2); @@ -594,6 +574,47 @@ machine_at_p3v4x_init(const machine_t *model) return ret; } +int +machine_at_gt694va_init(const machine_t *model) +{ + int ret; + + ret = bios_load_linear("roms/machines/gt694va/21071100.bin", + 0x000c0000, 262144, 0); + + if (bios_only || !ret) + return ret; + + machine_at_common_init_ex(model, 2); + + pci_init(PCI_CONFIG_TYPE_1); + pci_register_slot(0x00, PCI_CARD_NORTHBRIDGE, 0, 0, 0, 0); + pci_register_slot(0x07, PCI_CARD_SOUTHBRIDGE, 0, 0, 3, 4); + pci_register_slot(0x0D, PCI_CARD_SOUND, 4, 1, 2, 3); /* assumed */ + pci_register_slot(0x0F, PCI_CARD_NORMAL, 3, 4, 1, 2); + pci_register_slot(0x11, PCI_CARD_NORMAL, 2, 3, 4, 1); + pci_register_slot(0x13, PCI_CARD_NORMAL, 1, 2, 3, 4); + pci_register_slot(0x01, PCI_CARD_AGPBRIDGE, 1, 2, 3, 4); + device_add(&via_apro133a_device); + device_add(&via_vt82c596b_device); + device_add(&w83977ef_device); + device_add(&keyboard_ps2_ami_pci_device); + device_add(&sst_flash_39sf020_device); + spd_register(SPD_TYPE_SDRAM, 0x7, 1024); + device_add(&w83782d_device); /* fans: CPU, unused, unused; temperatures: System, CPU1, unused */ + hwm_values.voltages[1] = 1500; /* IN1 (unknown purpose, assumed Vtt) */ + hwm_values.fans[0] = 4500; /* BIOS does not display <4411 RPM */ + hwm_values.fans[1] = 0; /* unused */ + hwm_values.fans[2] = 0; /* unused */ + hwm_values.temperatures[2] = 0; /* unused */ + + if (sound_card_current[0] == SOUND_INTERNAL) { + device_add(&es1371_onboard_device); + device_add(&cs4297_device); /* assumed */ + } + + return ret; +} int machine_at_vei8_init(const machine_t *model) @@ -601,10 +622,10 @@ machine_at_vei8_init(const machine_t *model) int ret; ret = bios_load_linear("roms/machines/vei8/QHW1001.BIN", - 0x000c0000, 262144, 0); + 0x000c0000, 262144, 0); if (bios_only || !ret) - return ret; + return ret; machine_at_common_init_ex(model, 2); @@ -627,7 +648,6 @@ machine_at_vei8_init(const machine_t *model) return ret; } - static void machine_at_ms6168_common_init(const machine_t *model) { @@ -636,8 +656,8 @@ machine_at_ms6168_common_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(0x14, PCI_CARD_SOUND, 3, 4, 1, 2); - pci_register_slot(0x0E, PCI_CARD_NORMAL, 1, 2, 3, 4); - pci_register_slot(0x10, PCI_CARD_NORMAL, 2, 3, 4, 1); + pci_register_slot(0x0E, PCI_CARD_NORMAL, 1, 2, 3, 4); + pci_register_slot(0x10, PCI_CARD_NORMAL, 2, 3, 4, 1); pci_register_slot(0x12, PCI_CARD_NORMAL, 3, 4, 1, 2); pci_register_slot(0x07, PCI_CARD_SOUTHBRIDGE, 1, 2, 3, 4); pci_register_slot(0x01, PCI_CARD_AGPBRIDGE, 1, 2, 3, 4); @@ -645,71 +665,61 @@ machine_at_ms6168_common_init(const machine_t *model) device_add(&piix4e_device); device_add(&w83977ef_device); - if (gfxcard == VID_INTERNAL) - device_add(&voodoo_3_2000_agp_onboard_8m_device); + if (gfxcard[0] == VID_INTERNAL) + device_add(&voodoo_3_2000_agp_onboard_8m_device); device_add(&keyboard_ps2_ami_pci_device); device_add(&intel_flash_bxt_device); spd_register(SPD_TYPE_SDRAM, 0x3, 256); - if (sound_card_current == SOUND_INTERNAL) { - device_add(&es1371_onboard_device); - device_add(&cs4297_device); + if (sound_card_current[0] == SOUND_INTERNAL) { + device_add(&es1371_onboard_device); + device_add(&cs4297_device); } } - -const device_t * -at_ms6168_get_device(void) -{ - return &voodoo_3_2000_agp_onboard_8m_device; -} - - int machine_at_borapro_init(const machine_t *model) { int ret; ret = bios_load_linear("roms/machines/borapro/MS6168V2.50", - 0x000c0000, 262144, 0); + 0x000c0000, 262144, 0); if (bios_only || !ret) - return ret; + return ret; machine_at_ms6168_common_init(model); return ret; } - int machine_at_ms6168_init(const machine_t *model) { int ret; ret = bios_load_linear("roms/machines/ms6168/w6168ims.130", - 0x000c0000, 262144, 0); + 0x000c0000, 262144, 0); if (bios_only || !ret) - return ret; + return ret; machine_at_ms6168_common_init(model); return ret; } - int machine_at_m729_init(const machine_t *model) { int ret; ret = bios_load_linear("roms/machines/m729/M729NEW.BIN", - 0x000e0000, 131072, 0); + 0x000e0000, 131072, 0); if (bios_only || !ret) - return ret; + return ret; machine_at_common_init_ex(model, 2); @@ -717,16 +727,15 @@ machine_at_m729_init(const machine_t *model) pci_register_slot(0x00, PCI_CARD_NORTHBRIDGE, 0, 0, 0, 0); pci_register_slot(0x01, PCI_CARD_AGPBRIDGE, 1, 2, 0, 0); pci_register_slot(0x07, PCI_CARD_SOUTHBRIDGE, 1, 2, 3, 4); - pci_register_slot(0x0F, PCI_CARD_SOUTHBRIDGE, 1, 2, 3, 4); - pci_register_slot(0x03, PCI_CARD_SOUTHBRIDGE, 1, 2, 3, 4); - pci_register_slot(0x02, PCI_CARD_SOUTHBRIDGE, 1, 2, 3, 4); + pci_register_slot(0x0F, PCI_CARD_SOUTHBRIDGE_IDE, 1, 2, 3, 4); + pci_register_slot(0x03, PCI_CARD_SOUTHBRIDGE_PMU, 1, 2, 3, 4); + pci_register_slot(0x02, PCI_CARD_SOUTHBRIDGE_USB, 1, 2, 3, 4); pci_register_slot(0x14, PCI_CARD_NORMAL, 1, 2, 3, 4); pci_register_slot(0x12, PCI_CARD_NORMAL, 2, 3, 4, 1); pci_register_slot(0x10, PCI_CARD_NORMAL, 3, 4, 1, 2); device_add(&ali1621_device); - device_add(&ali1543c_device); - device_add(&keyboard_ps2_ami_pci_device); - device_add(&sst_flash_29ee010_device); + device_add(&ali1543c_device); /* +0 */ + device_add(&winbond_flash_w29c010_device); spd_register(SPD_TYPE_SDRAM, 0x7, 512); return ret; diff --git a/src/machine/m_at_slot2.c b/src/machine/m_at_slot2.c index 4a1babf74..da160c138 100644 --- a/src/machine/m_at_slot2.c +++ b/src/machine/m_at_slot2.c @@ -1,153 +1,153 @@ -/* - * 86Box A hypervisor and IBM PC system emulator that specializes in - * running old operating systems and software designed for IBM - * PC systems and compatibles from 1981 through fairly recent - * system designs based on the PCI bus. - * - * This file is part of the 86Box distribution. - * - * Implementation of Slot 2 machines. - * - * Slot 2 is quite a rare type of Slot. Used mostly by Pentium II & III Xeons - * - * - * - * Authors: Miran Grca, - * - * Copyright 2016-2019 Miran Grca. - */ -#include -#include -#include -#include -#include -#include <86box/86box.h> -#include <86box/mem.h> -#include <86box/io.h> -#include <86box/rom.h> -#include <86box/pci.h> -#include <86box/device.h> -#include <86box/chipset.h> -#include <86box/hdc.h> -#include <86box/hdc_ide.h> -#include <86box/keyboard.h> -#include <86box/flash.h> -#include <86box/sio.h> -#include <86box/hwm.h> -#include <86box/spd.h> -#include <86box/video.h> -#include <86box/clock.h> -#include "cpu.h" -#include <86box/machine.h> - -int -machine_at_6gxu_init(const machine_t *model) -{ - int ret; - - ret = bios_load_linear("roms/machines/6gxu/6gxu.f1c", - 0x000c0000, 262144, 0); - - if (bios_only || !ret) - return ret; - - machine_at_common_init_ex(model, 2); - - pci_init(PCI_CONFIG_TYPE_1); - pci_register_slot(0x00, PCI_CARD_NORTHBRIDGE, 0, 0, 0, 0); - pci_register_slot(0x07, PCI_CARD_SOUTHBRIDGE, 1, 2, 3, 4); - pci_register_slot(0x08, PCI_CARD_NORMAL, 1, 2, 3, 4); - pci_register_slot(0x09, PCI_CARD_NORMAL, 2, 3, 4, 1); - pci_register_slot(0x0A, PCI_CARD_NORMAL, 3, 4, 1, 2); - pci_register_slot(0x0B, PCI_CARD_NORMAL, 4, 1, 2, 3); - pci_register_slot(0x0C, PCI_CARD_NORMAL, 1, 2, 3, 4); /* On-Board SCSI. Not emulated at the moment */ - pci_register_slot(0x01, PCI_CARD_AGPBRIDGE, 1, 2, 3, 4); - - device_add(&i440gx_device); - device_add(&piix4e_device); - device_add(&keyboard_ps2_pci_device); - device_add(&w83977ef_device); - device_add(&sst_flash_39sf020_device); - spd_register(SPD_TYPE_SDRAM, 0xF, 512); - device_add(&w83782d_device); /* fans: CPU, Power, System; temperatures: System, CPU, unused */ - hwm_values.temperatures[2] = 0; /* unused */ - hwm_values.voltages[1] = 1500; /* VGTL */ - - return ret; -} - -int -machine_at_s2dge_init(const machine_t *model) -{ - int ret; - - ret = bios_load_linear("roms/machines/s2dge/2gu7301.rom", - 0x000c0000, 262144, 0); - - if (bios_only || !ret) - return ret; - - machine_at_common_init_ex(model, 2); - - pci_init(PCI_CONFIG_TYPE_1); - pci_register_slot(0x00, PCI_CARD_NORTHBRIDGE, 0, 0, 0, 0); - pci_register_slot(0x07, PCI_CARD_SOUTHBRIDGE, 1, 2, 0, 0); - pci_register_slot(0x0F, PCI_CARD_NORMAL, 1, 2, 3, 4); - pci_register_slot(0x10, PCI_CARD_NORMAL, 2, 3, 4, 1); - pci_register_slot(0x12, PCI_CARD_NORMAL, 3, 4, 1, 2); - pci_register_slot(0x14, PCI_CARD_NORMAL, 4, 1, 2, 3); - pci_register_slot(0x0D, PCI_CARD_NORMAL, 2, 3, 4, 1); - pci_register_slot(0x0E, PCI_CARD_NORMAL, 1, 2, 3, 4); - pci_register_slot(0x01, PCI_CARD_AGPBRIDGE, 1, 2, 0, 0); - - device_add(&i440gx_device); - device_add(&piix4e_device); - device_add(&keyboard_ps2_ami_pci_device); - device_add(&w83977tf_device); - device_add(&intel_flash_bxt_device); - spd_register(SPD_TYPE_SDRAM, 0xF, 512); - device_add(&w83781d_device); /* fans: CPU1, CPU2, Thermal Control; temperatures: unused, CPU1, CPU2? */ - hwm_values.fans[1] = 0; /* no CPU2 fan */ - hwm_values.temperatures[0] = 0; /* unused */ - hwm_values.temperatures[2] = 0; /* CPU2? */ - - return ret; -} - -int -machine_at_fw6400gx_init(const machine_t *model) -{ - int ret; - - ret = bios_load_linear("roms/machines/fw6400gx/FWGX1211.ROM", - 0x000c0000, 262144, 0); - - if (bios_only || !ret) - return ret; - - machine_at_common_init_ex(model, 2); - - pci_init(PCI_CONFIG_TYPE_1); - pci_register_slot(0x00, PCI_CARD_NORTHBRIDGE, 0, 0, 0, 0); - pci_register_slot(0x07, PCI_CARD_SOUTHBRIDGE, 0, 0, 0, 4); - pci_register_slot(0x0A, PCI_CARD_NORMAL, 1, 2, 3, 4); - pci_register_slot(0x0B, PCI_CARD_NORMAL, 2, 3, 4, 1); - pci_register_slot(0x0C, PCI_CARD_NORMAL, 3, 4, 1, 2); - pci_register_slot(0x0D, PCI_CARD_NORMAL, 4, 1, 2, 3); - pci_register_slot(0x0E, PCI_CARD_NORMAL, 4, 1, 2, 3); - pci_register_slot(0x0F, PCI_CARD_NORMAL, 4, 1, 2, 3); - pci_register_slot(0x01, PCI_CARD_AGPBRIDGE, 1, 2, 0, 0); - - device_add(&i440gx_device); - device_add(&piix4e_device); - device_add(&keyboard_ps2_ami_pci_device); - device_add(&pc87309_15c_device); - device_add(ics9xxx_get(ICS9250_08)); - device_add(&sst_flash_29ee020_device); - spd_register(SPD_TYPE_SDRAM, 0xF, 512); - device_add(&w83781d_device); /* fans: Chassis, Power, CPU; temperatures: System, CPU, unused */ - hwm_values.temperatures[3] = 0; /* unused */ - hwm_values.voltages[1] = 1500; /* Vtt */ - - return ret; -} +/* + * 86Box A hypervisor and IBM PC system emulator that specializes in + * running old operating systems and software designed for IBM + * PC systems and compatibles from 1981 through fairly recent + * system designs based on the PCI bus. + * + * This file is part of the 86Box distribution. + * + * Implementation of Slot 2 machines. + * + * Slot 2 is quite a rare type of Slot. Used mostly by Pentium II & III Xeons + * + * + * + * Authors: Miran Grca, + * + * Copyright 2016-2019 Miran Grca. + */ +#include +#include +#include +#include +#include +#include <86box/86box.h> +#include <86box/mem.h> +#include <86box/io.h> +#include <86box/rom.h> +#include <86box/pci.h> +#include <86box/device.h> +#include <86box/chipset.h> +#include <86box/hdc.h> +#include <86box/hdc_ide.h> +#include <86box/keyboard.h> +#include <86box/flash.h> +#include <86box/sio.h> +#include <86box/hwm.h> +#include <86box/spd.h> +#include <86box/video.h> +#include <86box/clock.h> +#include "cpu.h" +#include <86box/machine.h> + +int +machine_at_6gxu_init(const machine_t *model) +{ + int ret; + + ret = bios_load_linear("roms/machines/6gxu/6gxu.f1c", + 0x000c0000, 262144, 0); + + if (bios_only || !ret) + return ret; + + machine_at_common_init_ex(model, 2); + + pci_init(PCI_CONFIG_TYPE_1); + pci_register_slot(0x00, PCI_CARD_NORTHBRIDGE, 0, 0, 0, 0); + pci_register_slot(0x07, PCI_CARD_SOUTHBRIDGE, 1, 2, 3, 4); + pci_register_slot(0x08, PCI_CARD_NORMAL, 1, 2, 3, 4); + pci_register_slot(0x09, PCI_CARD_NORMAL, 2, 3, 4, 1); + pci_register_slot(0x0A, PCI_CARD_NORMAL, 3, 4, 1, 2); + pci_register_slot(0x0B, PCI_CARD_NORMAL, 4, 1, 2, 3); + pci_register_slot(0x0C, PCI_CARD_NORMAL, 1, 2, 3, 4); /* On-Board SCSI. Not emulated at the moment */ + pci_register_slot(0x01, PCI_CARD_AGPBRIDGE, 1, 2, 3, 4); + + device_add(&i440gx_device); + device_add(&piix4e_device); + device_add(&keyboard_ps2_pci_device); + device_add(&w83977ef_device); + device_add(&sst_flash_39sf020_device); + spd_register(SPD_TYPE_SDRAM, 0xF, 512); + device_add(&w83782d_device); /* fans: CPU, Power, System; temperatures: System, CPU, unused */ + hwm_values.temperatures[2] = 0; /* unused */ + hwm_values.voltages[1] = 1500; /* VGTL */ + + return ret; +} + +int +machine_at_s2dge_init(const machine_t *model) +{ + int ret; + + ret = bios_load_linear("roms/machines/s2dge/2gu7301.rom", + 0x000c0000, 262144, 0); + + if (bios_only || !ret) + return ret; + + machine_at_common_init_ex(model, 2); + + pci_init(PCI_CONFIG_TYPE_1); + pci_register_slot(0x00, PCI_CARD_NORTHBRIDGE, 0, 0, 0, 0); + pci_register_slot(0x07, PCI_CARD_SOUTHBRIDGE, 1, 2, 0, 0); + pci_register_slot(0x0F, PCI_CARD_NORMAL, 1, 2, 3, 4); + pci_register_slot(0x10, PCI_CARD_NORMAL, 2, 3, 4, 1); + pci_register_slot(0x12, PCI_CARD_NORMAL, 3, 4, 1, 2); + pci_register_slot(0x14, PCI_CARD_NORMAL, 4, 1, 2, 3); + pci_register_slot(0x0D, PCI_CARD_NORMAL, 2, 3, 4, 1); + pci_register_slot(0x0E, PCI_CARD_NORMAL, 1, 2, 3, 4); + pci_register_slot(0x01, PCI_CARD_AGPBRIDGE, 1, 2, 0, 0); + + device_add(&i440gx_device); + device_add(&piix4e_device); + device_add(&keyboard_ps2_ami_pci_device); + device_add(&w83977tf_device); + device_add(&intel_flash_bxt_device); + spd_register(SPD_TYPE_SDRAM, 0xF, 512); + device_add(&w83781d_device); /* fans: CPU1, CPU2, Thermal Control; temperatures: unused, CPU1, CPU2? */ + hwm_values.fans[1] = 0; /* no CPU2 fan */ + hwm_values.temperatures[0] = 0; /* unused */ + hwm_values.temperatures[2] = 0; /* CPU2? */ + + return ret; +} + +int +machine_at_fw6400gx_init(const machine_t *model) +{ + int ret; + + ret = bios_load_linear("roms/machines/fw6400gx/FWGX1211.ROM", + 0x000c0000, 262144, 0); + + if (bios_only || !ret) + return ret; + + machine_at_common_init_ex(model, 2); + + pci_init(PCI_CONFIG_TYPE_1); + pci_register_slot(0x00, PCI_CARD_NORTHBRIDGE, 0, 0, 0, 0); + pci_register_slot(0x07, PCI_CARD_SOUTHBRIDGE, 0, 0, 0, 4); + pci_register_slot(0x0A, PCI_CARD_NORMAL, 1, 2, 3, 4); + pci_register_slot(0x0B, PCI_CARD_NORMAL, 2, 3, 4, 1); + pci_register_slot(0x0C, PCI_CARD_NORMAL, 3, 4, 1, 2); + pci_register_slot(0x0D, PCI_CARD_NORMAL, 4, 1, 2, 3); + pci_register_slot(0x0E, PCI_CARD_NORMAL, 4, 1, 2, 3); + pci_register_slot(0x0F, PCI_CARD_NORMAL, 4, 1, 2, 3); + pci_register_slot(0x01, PCI_CARD_AGPBRIDGE, 1, 2, 0, 0); + + device_add(&i440gx_device); + device_add(&piix4e_device); + device_add(&keyboard_ps2_ami_pci_device); + device_add(&pc87309_15c_device); + device_add(ics9xxx_get(ICS9250_08)); + device_add(&sst_flash_29ee020_device); + spd_register(SPD_TYPE_SDRAM, 0xF, 512); + device_add(&w83781d_device); /* fans: Chassis, Power, CPU; temperatures: System, CPU, unused */ + hwm_values.temperatures[3] = 0; /* unused */ + hwm_values.voltages[1] = 1500; /* Vtt */ + + return ret; +} diff --git a/src/machine/m_at_socket370.c b/src/machine/m_at_socket370.c index c0a0224fb..07432bfd7 100644 --- a/src/machine/m_at_socket370.c +++ b/src/machine/m_at_socket370.c @@ -1,473 +1,457 @@ -/* - * 86Box A hypervisor and IBM PC system emulator that specializes in - * running old operating systems and software designed for IBM - * PC systems and compatibles from 1981 through fairly recent - * system designs based on the PCI bus. - * - * This file is part of the 86Box distribution. - * - * Implementation of Socket 370(PGA370) machines. - * - * - * - * Authors: Miran Grca, - * - * Copyright 2016-2019 Miran Grca. - */ -#include -#include -#include -#include -#include -#include <86box/86box.h> -#include <86box/mem.h> -#include <86box/io.h> -#include <86box/rom.h> -#include <86box/pci.h> -#include <86box/device.h> -#include <86box/chipset.h> -#include <86box/hdc.h> -#include <86box/hdc_ide.h> -#include <86box/keyboard.h> -#include <86box/flash.h> -#include <86box/sio.h> -#include <86box/hwm.h> -#include <86box/spd.h> -#include <86box/video.h> -#include "cpu.h" -#include <86box/machine.h> -#include <86box/clock.h> -#include <86box/sound.h> -#include <86box/snd_ac97.h> - - -int -machine_at_s370slm_init(const machine_t *model) -{ - int ret; - - ret = bios_load_linear("roms/machines/s370slm/3LM1202.rom", - 0x000c0000, 262144, 0); - - if (bios_only || !ret) - return ret; - - machine_at_common_init_ex(model, 2); - - pci_init(PCI_CONFIG_TYPE_1); - pci_register_slot(0x00, PCI_CARD_NORTHBRIDGE, 0, 0, 0, 0); - pci_register_slot(0x07, PCI_CARD_SOUTHBRIDGE, 1, 2, 3, 4); - pci_register_slot(0x0F, PCI_CARD_NORMAL, 1, 2, 3, 4); - pci_register_slot(0x10, PCI_CARD_NORMAL, 2, 3, 4, 1); - pci_register_slot(0x12, PCI_CARD_NORMAL, 3, 4, 1, 2); - pci_register_slot(0x14, PCI_CARD_NORMAL, 4, 1, 2, 3); - pci_register_slot(0x01, PCI_CARD_AGPBRIDGE, 1, 2, 3, 4); - device_add(&i440lx_device); - device_add(&piix4e_device); - device_add(&w83977tf_device); - device_add(&keyboard_ps2_ami_pci_device); - device_add(&intel_flash_bxt_device); - spd_register(SPD_TYPE_SDRAM, 0x7, 256); - device_add(&w83781d_device); /* fans: CPU, Fan 2, Chassis; temperatures: unused, CPU, unused */ - hwm_values.temperatures[0] = 0; /* unused */ - hwm_values.temperatures[2] = 0; /* unused */ - - return ret; -} - - -int -machine_at_s1857_init(const machine_t *model) -{ - int ret; - - ret = bios_load_linear("roms/machines/s1857/BX57200A.ROM", - 0x000c0000, 262144, 0); - - if (bios_only || !ret) - return ret; - - machine_at_common_init_ex(model, 2); - - pci_init(PCI_CONFIG_TYPE_1); - pci_register_slot(0x00, PCI_CARD_NORTHBRIDGE, 0, 0, 0, 0); - pci_register_slot(0x07, PCI_CARD_SOUTHBRIDGE, 1, 2, 3, 4); - pci_register_slot(0x0F, PCI_CARD_SOUND, 1, 0, 0, 0); - pci_register_slot(0x10, PCI_CARD_NORMAL, 1, 2, 3, 4); - pci_register_slot(0x11, PCI_CARD_NORMAL, 2, 3, 4, 1); - pci_register_slot(0x12, PCI_CARD_NORMAL, 3, 4, 1, 2); - pci_register_slot(0x13, PCI_CARD_NORMAL, 4, 1, 2, 3); - pci_register_slot(0x14, PCI_CARD_NORMAL, 1, 2, 3, 4); - pci_register_slot(0x01, PCI_CARD_AGPBRIDGE, 1, 2, 3, 4); - device_add(&i440bx_device); - device_add(&piix4e_device); - device_add(&keyboard_ps2_ami_pci_device); - device_add(&w83977ef_370_device); - device_add(&intel_flash_bxt_device); - spd_register(SPD_TYPE_SDRAM, 0x7, 256); - - if (sound_card_current == SOUND_INTERNAL) { - device_add(&es1371_onboard_device); - device_add(&cs4297_device); /* found on other Tyan boards around the same time */ - } - - return ret; -} - - -int -machine_at_p6bap_init(const machine_t *model) -{ - int ret; - - ret = bios_load_linear("roms/machines/p6bap/bapa14a.BIN", - 0x000c0000, 262144, 0); - - if (bios_only || !ret) - return ret; - - machine_at_common_init_ex(model, 2); - - pci_init(PCI_CONFIG_TYPE_1); - pci_register_slot(0x00, PCI_CARD_NORTHBRIDGE, 0, 0, 0, 0); - pci_register_slot(0x07, PCI_CARD_SOUTHBRIDGE, 1, 2, 0, 0); - pci_register_slot(0x14, PCI_CARD_NORMAL, 2, 3, 4, 1); - pci_register_slot(0x13, PCI_CARD_NORMAL, 3, 4, 1, 2); - pci_register_slot(0x12, PCI_CARD_NORMAL, 4, 1, 2, 3); - pci_register_slot(0x11, PCI_CARD_NORMAL, 1, 2, 3, 4); - pci_register_slot(0x10, PCI_CARD_NORMAL, 2, 3, 4, 1); - pci_register_slot(0x01, PCI_CARD_AGPBRIDGE, 1, 2, 3, 4); - device_add(&via_apro133a_device); /* Rebranded as ET82C693A */ - device_add(&via_vt82c596b_device); /* Rebranded as ET82C696B */ - device_add(&w83977ef_device); - device_add(&keyboard_ps2_ami_pci_device); - device_add(&sst_flash_39sf020_device); - spd_register(SPD_TYPE_SDRAM, 0x7, 256); - - return ret; -} - - -int -machine_at_cubx_init(const machine_t *model) -{ - int ret; - - ret = bios_load_linear("roms/machines/cubx/1008cu.004", - 0x000c0000, 262144, 0); - - if (bios_only || !ret) - return ret; - - machine_at_common_init_ex(model, 2); - - pci_init(PCI_CONFIG_TYPE_1); - pci_register_slot(0x00, PCI_CARD_NORTHBRIDGE, 0, 0, 0, 0); - pci_register_slot(0x04, PCI_CARD_SOUTHBRIDGE, 1, 2, 3, 4); - pci_register_slot(0x07, PCI_CARD_IDE, 2, 3, 4, 1); - pci_register_slot(0x09, PCI_CARD_NORMAL, 4, 1, 2, 3); - pci_register_slot(0x0A, PCI_CARD_NORMAL, 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(0x0D, PCI_CARD_NORMAL, 4, 1, 2, 3); - pci_register_slot(0x0E, PCI_CARD_NORMAL, 3, 4, 1, 2); - pci_register_slot(0x01, PCI_CARD_AGPBRIDGE, 1, 2, 3, 4); - device_add(&i440bx_device); - device_add(&piix4e_device); - device_add(&keyboard_ps2_ami_pci_device); - device_add(&w83977ef_device); - device_add(ics9xxx_get(ICS9250_08)); - device_add(&sst_flash_39sf020_device); - spd_register(SPD_TYPE_SDRAM, 0xF, 256); - device_add(&as99127f_device); /* fans: Chassis, CPU, Power; temperatures: MB, JTPWR, CPU */ - - return ret; -} - - -int -machine_at_atc7020bxii_init(const machine_t *model) -{ - int ret; - - ret = bios_load_linear("roms/machines/atc7020bxii/7020s102.bin", - 0x000c0000, 262144, 0); - - if (bios_only || !ret) - return ret; - - machine_at_common_init_ex(model, 2); - - pci_init(PCI_CONFIG_TYPE_1); - pci_register_slot(0x00, PCI_CARD_NORTHBRIDGE, 0, 0, 0, 0); - pci_register_slot(0x07, PCI_CARD_SOUTHBRIDGE, 1, 2, 3, 4); - pci_register_slot(0x0A, PCI_CARD_NORMAL, 1, 2, 3, 4); - pci_register_slot(0x0B, PCI_CARD_NORMAL, 2, 3, 4, 1); - pci_register_slot(0x0C, PCI_CARD_NORMAL, 3, 4, 1, 2); - pci_register_slot(0x0D, PCI_CARD_NORMAL, 4, 1, 2, 3); - pci_register_slot(0x0E, PCI_CARD_NORMAL, 4, 1, 2, 3); - pci_register_slot(0x01, PCI_CARD_AGPBRIDGE, 1, 2, 3, 4); - device_add(&i440bx_device); - device_add(&slc90e66_device); - device_add(&keyboard_ps2_pci_device); - device_add(&w83977ef_device); - device_add(&sst_flash_39sf020_device); - spd_register(SPD_TYPE_SDRAM, 0xF, 256); - - return ret; -} - - -int -machine_at_ambx133_init(const machine_t *model) -{ - int ret; - - ret = bios_load_linear("roms/machines/ambx133/mkbx2vg2.bin", - 0x000c0000, 262144, 0); - - if (bios_only || !ret) - return ret; - - machine_at_common_init_ex(model, 2); - - pci_init(PCI_CONFIG_TYPE_1); - pci_register_slot(0x00, PCI_CARD_NORTHBRIDGE, 0, 0, 0, 0); - pci_register_slot(0x07, PCI_CARD_SOUTHBRIDGE, 1, 2, 3, 4); - pci_register_slot(0x09, PCI_CARD_NORMAL, 1, 2, 3, 4); - pci_register_slot(0x0A, PCI_CARD_NORMAL, 2, 3, 4, 1); - pci_register_slot(0x0B, PCI_CARD_NORMAL, 3, 4, 1, 2); - pci_register_slot(0x0C, PCI_CARD_NORMAL, 4, 1, 2, 3); - pci_register_slot(0x0D, PCI_CARD_NORMAL, 4, 1, 2, 3); - pci_register_slot(0x01, PCI_CARD_AGPBRIDGE, 1, 2, 3, 4); - device_add(&i440bx_device); - device_add(&piix4e_device); - device_add(&w83977ef_device); - device_add(&keyboard_ps2_ami_pci_device); - device_add(&sst_flash_39sf020_device); - spd_register(SPD_TYPE_SDRAM, 0x7, 256); - device_add(&gl518sm_2d_device); /* fans: CPUFAN1, CPUFAN2; temperature: CPU */ - hwm_values.fans[1] += 500; - hwm_values.temperatures[0] += 4; /* CPU offset */ - hwm_values.voltages[1] = RESISTOR_DIVIDER(12000, 10, 2); /* different 12V divider in BIOS (10K/2K?) */ - - return ret; -} - - -int -machine_at_awo671r_init(const machine_t *model) -{ - int ret; - - ret = bios_load_linear("roms/machines/awo671r/a08139c.bin", - 0x000c0000, 262144, 0); - - if (bios_only || !ret) - return ret; - - machine_at_common_init_ex(model, 2); - - pci_init(PCI_CONFIG_TYPE_1); - pci_register_slot(0x00, PCI_CARD_NORTHBRIDGE, 0, 0, 0, 0); - pci_register_slot(0x07, PCI_CARD_SOUTHBRIDGE, 1, 2, 3, 4); - pci_register_slot(0x09, PCI_CARD_NORMAL, 1, 2, 3, 4); - pci_register_slot(0x0A, PCI_CARD_NORMAL, 2, 3, 4, 1); - pci_register_slot(0x0B, PCI_CARD_NORMAL, 3, 4, 1, 2); - pci_register_slot(0x0C, PCI_CARD_NORMAL, 4, 1, 2, 3); - pci_register_slot(0x0D, PCI_CARD_NORMAL, 2, 3, 4, 1); - pci_register_slot(0x01, PCI_CARD_AGPBRIDGE, 1, 2, 3, 4); - device_add(&i440bx_device); - device_add(&piix4e_device); - device_add_inst(&w83977ef_device, 1); - device_add_inst(&w83977ef_device, 2); - device_add(&keyboard_ps2_pci_device); - device_add(&sst_flash_39sf020_device); - spd_register(SPD_TYPE_SDRAM, 0x3, 256); - - return ret; -} - - -int -machine_at_63a1_init(const machine_t *model) -{ - int ret; - - ret = bios_load_linear("roms/machines/63a1/63a-q3.bin", - 0x000c0000, 262144, 0); - - if (bios_only || !ret) - return ret; - - machine_at_common_init_ex(model, 2); - - pci_init(PCI_CONFIG_TYPE_1); - pci_register_slot(0x00, PCI_CARD_NORTHBRIDGE, 0, 0, 0, 0); - pci_register_slot(0x07, PCI_CARD_SOUTHBRIDGE, 1, 2, 3, 4); - pci_register_slot(0x08, PCI_CARD_NORMAL, 1, 2, 3, 4); - pci_register_slot(0x09, PCI_CARD_NORMAL, 2, 3, 4, 1); - pci_register_slot(0x0A, PCI_CARD_NORMAL, 3, 4, 1, 2); - pci_register_slot(0x0B, PCI_CARD_NORMAL, 4, 1, 2, 3); - pci_register_slot(0x0C, PCI_CARD_NORMAL, 1, 2, 3, 4); /* Integrated Sound? */ - pci_register_slot(0x01, PCI_CARD_AGPBRIDGE, 1, 2, 3, 4); - device_add(&i440zx_device); - device_add(&piix4e_device); - device_add(&w83977tf_device); - device_add(&keyboard_ps2_ami_pci_device); - device_add(&intel_flash_bxt_device); - spd_register(SPD_TYPE_SDRAM, 0x3, 256); - - return ret; -} - - -int -machine_at_apas3_init(const machine_t *model) -{ - int ret; - - ret = bios_load_linear("roms/machines/apas3/V0218SAG.BIN", - 0x000c0000, 262144, 0); - - if (bios_only || !ret) - return ret; - - machine_at_common_init_ex(model, 2); - - pci_init(PCI_CONFIG_TYPE_1); - pci_register_slot(0x00, PCI_CARD_NORTHBRIDGE, 0, 0, 0, 0); - pci_register_slot(0x07, PCI_CARD_SOUTHBRIDGE, 1, 2, 0, 0); - pci_register_slot(0x0F, PCI_CARD_NORMAL, 1, 2, 3, 4); - pci_register_slot(0x10, PCI_CARD_NORMAL, 2, 3, 4, 1); - pci_register_slot(0x13, PCI_CARD_NORMAL, 3, 4, 1, 2); - pci_register_slot(0x14, PCI_CARD_NORMAL, 4, 1, 2, 3); - pci_register_slot(0x01, PCI_CARD_AGPBRIDGE, 1, 2, 3, 4); - device_add(&via_apro_device); - device_add(&via_vt82c586b_device); - device_add(&fdc37c669_device); - device_add(&keyboard_ps2_ami_pci_device); - device_add(&sst_flash_39sf020_device); - spd_register(SPD_TYPE_SDRAM, 0x7, 256); - - return ret; -} - - -int -machine_at_gt694va_init(const machine_t *model) -{ - int ret; - - ret = bios_load_linear("roms/machines/gt694va/21071100.bin", - 0x000c0000, 262144, 0); - - if (bios_only || !ret) - return ret; - - machine_at_common_init_ex(model, 2); - - pci_init(PCI_CONFIG_TYPE_1); - pci_register_slot(0x00, PCI_CARD_NORTHBRIDGE, 0, 0, 0, 0); - pci_register_slot(0x07, PCI_CARD_SOUTHBRIDGE, 0, 0, 3, 4); - pci_register_slot(0x0D, PCI_CARD_SOUND, 4, 1, 2, 3); /* assumed */ - pci_register_slot(0x0F, PCI_CARD_NORMAL, 3, 4, 1, 2); - pci_register_slot(0x11, PCI_CARD_NORMAL, 2, 3, 4, 1); - pci_register_slot(0x13, PCI_CARD_NORMAL, 1, 2, 3, 4); - pci_register_slot(0x01, PCI_CARD_AGPBRIDGE, 1, 2, 3, 4); - device_add(&via_apro133a_device); - device_add(&via_vt82c596b_device); - device_add(&w83977ef_device); - device_add(&keyboard_ps2_ami_pci_device); - device_add(&sst_flash_39sf020_device); - spd_register(SPD_TYPE_SDRAM, 0x7, 1024); - device_add(&w83782d_device); /* fans: CPU, unused, unused; temperatures: System, CPU1, unused */ - hwm_values.voltages[1] = 1500; /* IN1 (unknown purpose, assumed Vtt) */ - hwm_values.fans[0] = 4500; /* BIOS does not display <4411 RPM */ - hwm_values.fans[1] = 0; /* unused */ - hwm_values.fans[2] = 0; /* unused */ - hwm_values.temperatures[2] = 0; /* unused */ - - if (sound_card_current == SOUND_INTERNAL) { - device_add(&es1371_onboard_device); - device_add(&cs4297_device); /* assumed */ - } - - return ret; -} - - -int -machine_at_cuv4xls_init(const machine_t *model) -{ - int ret; - - ret = bios_load_linear("roms/machines/cuv4xls/1005LS.001", - 0x000c0000, 262144, 0); - - if (bios_only || !ret) - return ret; - - machine_at_common_init_ex(model, 2); - - pci_init(PCI_CONFIG_TYPE_1); - pci_register_slot(0x00, PCI_CARD_NORTHBRIDGE, 0, 0, 0, 0); - pci_register_slot(0x04, PCI_CARD_SOUTHBRIDGE, 4, 1, 2, 3); - pci_register_slot(0x05, PCI_CARD_SOUND, 3, 0, 0, 0); - pci_register_slot(0x06, PCI_CARD_NORMAL, 3, 4, 1, 2); - pci_register_slot(0x07, PCI_CARD_NORMAL, 2, 3, 0, 0); - pci_register_slot(0x08, PCI_CARD_NORMAL, 1, 2, 3, 4); - pci_register_slot(0x09, PCI_CARD_NORMAL, 4, 1, 2, 3); - pci_register_slot(0x0A, PCI_CARD_NORMAL, 3, 4, 1, 2); - pci_register_slot(0x0B, PCI_CARD_NORMAL, 2, 3, 4, 1); - pci_register_slot(0x14, PCI_CARD_NORMAL, 4, 0, 0, 0); - pci_register_slot(0x01, PCI_CARD_AGPBRIDGE, 1, 2, 3, 4); - device_add(&via_apro133a_device); - device_add(&via_vt82c686b_device); - device_add(&keyboard_ps2_ami_pci_device); - device_add(ics9xxx_get(ICS9250_18)); - device_add(&sst_flash_39sf020_device); - spd_register(SPD_TYPE_SDRAM, 0xF, 1024); - device_add(&as99127f_device); /* fans: Chassis, CPU, Power; temperatures: MB, JTPWR, CPU */ - - return ret; -} - - -int -machine_at_6via90ap_init(const machine_t *model) -{ - int ret; - - ret = bios_load_linear("roms/machines/6via90ap/90ap10.bin", - 0x000c0000, 262144, 0); - - if (bios_only || !ret) - return ret; - - machine_at_common_init_ex(model, 2); - - pci_init(PCI_CONFIG_TYPE_1); - pci_register_slot(0x00, PCI_CARD_NORTHBRIDGE, 0, 0, 0, 0); - pci_register_slot(0x07, PCI_CARD_SOUTHBRIDGE, 1, 2, 3, 4); - pci_register_slot(0x09, PCI_CARD_NORMAL, 1, 2, 3, 4); - pci_register_slot(0x0A, PCI_CARD_NORMAL, 2, 3, 4, 1); - pci_register_slot(0x0B, PCI_CARD_NORMAL, 3, 4, 1, 2); - pci_register_slot(0x0C, PCI_CARD_NORMAL, 4, 1, 2, 3); - pci_register_slot(0x0D, PCI_CARD_NORMAL, 1, 2, 3, 4); - pci_register_slot(0x01, PCI_CARD_AGPBRIDGE, 1, 2, 3, 4); - device_add(&via_apro133a_device); - device_add(&via_vt82c686b_device); /* fans: CPU1, CPU2; temperatures: CPU, System, unused */ - device_add(&keyboard_ps2_ami_pci_device); - device_add(ics9xxx_get(ICS9250_18)); - device_add(&sst_flash_39sf020_device); - spd_register(SPD_TYPE_SDRAM, 0x7, 1024); - hwm_values.temperatures[0] += 2; /* CPU offset */ - hwm_values.temperatures[1] += 2; /* System offset */ - hwm_values.temperatures[2] = 0; /* unused */ - - if (sound_card_current == SOUND_INTERNAL) - device_add(&alc100_device); /* ALC100P identified on similar Acorp boards (694TA, 6VIA90A1) */ - - return ret; -} +/* + * 86Box A hypervisor and IBM PC system emulator that specializes in + * running old operating systems and software designed for IBM + * PC systems and compatibles from 1981 through fairly recent + * system designs based on the PCI bus. + * + * This file is part of the 86Box distribution. + * + * Implementation of Socket 370(PGA370) machines. + * + * + * + * Authors: Miran Grca, + * + * Copyright 2016-2019 Miran Grca. + */ +#include +#include +#include +#include +#include +#include <86box/86box.h> +#include <86box/mem.h> +#include <86box/io.h> +#include <86box/rom.h> +#include <86box/pci.h> +#include <86box/device.h> +#include <86box/chipset.h> +#include <86box/hdc.h> +#include <86box/hdc_ide.h> +#include <86box/keyboard.h> +#include <86box/flash.h> +#include <86box/sio.h> +#include <86box/hwm.h> +#include <86box/spd.h> +#include <86box/video.h> +#include "cpu.h" +#include <86box/machine.h> +#include <86box/clock.h> +#include <86box/sound.h> +#include <86box/snd_ac97.h> + +int +machine_at_s370slm_init(const machine_t *model) +{ + int ret; + + ret = bios_load_linear("roms/machines/s370slm/3LM1202.rom", + 0x000c0000, 262144, 0); + + if (bios_only || !ret) + return ret; + + machine_at_common_init_ex(model, 2); + + pci_init(PCI_CONFIG_TYPE_1); + pci_register_slot(0x00, PCI_CARD_NORTHBRIDGE, 0, 0, 0, 0); + pci_register_slot(0x07, PCI_CARD_SOUTHBRIDGE, 1, 2, 3, 4); + pci_register_slot(0x0F, PCI_CARD_NORMAL, 1, 2, 3, 4); + pci_register_slot(0x10, PCI_CARD_NORMAL, 2, 3, 4, 1); + pci_register_slot(0x12, PCI_CARD_NORMAL, 3, 4, 1, 2); + pci_register_slot(0x14, PCI_CARD_NORMAL, 4, 1, 2, 3); + pci_register_slot(0x01, PCI_CARD_AGPBRIDGE, 1, 2, 3, 4); + device_add(&i440lx_device); + device_add(&piix4e_device); + device_add(&w83977tf_device); + device_add(&keyboard_ps2_ami_pci_device); + device_add(&intel_flash_bxt_device); + spd_register(SPD_TYPE_SDRAM, 0x7, 256); + device_add(&w83781d_device); /* fans: CPU, Fan 2, Chassis; temperatures: unused, CPU, unused */ + hwm_values.temperatures[0] = 0; /* unused */ + hwm_values.temperatures[2] = 0; /* unused */ + + return ret; +} + +int +machine_at_s1857_init(const machine_t *model) +{ + int ret; + + ret = bios_load_linear("roms/machines/s1857/BX57200A.ROM", + 0x000c0000, 262144, 0); + + if (bios_only || !ret) + return ret; + + machine_at_common_init_ex(model, 2); + + pci_init(PCI_CONFIG_TYPE_1); + pci_register_slot(0x00, PCI_CARD_NORTHBRIDGE, 0, 0, 0, 0); + pci_register_slot(0x07, PCI_CARD_SOUTHBRIDGE, 1, 2, 3, 4); + pci_register_slot(0x0F, PCI_CARD_SOUND, 1, 0, 0, 0); + pci_register_slot(0x10, PCI_CARD_NORMAL, 1, 2, 3, 4); + pci_register_slot(0x11, PCI_CARD_NORMAL, 2, 3, 4, 1); + pci_register_slot(0x12, PCI_CARD_NORMAL, 3, 4, 1, 2); + pci_register_slot(0x13, PCI_CARD_NORMAL, 4, 1, 2, 3); + pci_register_slot(0x14, PCI_CARD_NORMAL, 1, 2, 3, 4); + pci_register_slot(0x01, PCI_CARD_AGPBRIDGE, 1, 2, 3, 4); + device_add(&i440bx_device); + device_add(&piix4e_device); + device_add(&keyboard_ps2_ami_pci_device); + device_add(&w83977ef_370_device); + device_add(&intel_flash_bxt_device); + spd_register(SPD_TYPE_SDRAM, 0x7, 256); + + if (sound_card_current[0] == SOUND_INTERNAL) { + device_add(&es1371_onboard_device); + device_add(&cs4297_device); /* found on other Tyan boards around the same time */ + } + + return ret; +} + +int +machine_at_p6bap_init(const machine_t *model) +{ + int ret; + + ret = bios_load_linear("roms/machines/p6bap/bapa14a.BIN", + 0x000c0000, 262144, 0); + + if (bios_only || !ret) + return ret; + + machine_at_common_init_ex(model, 2); + + pci_init(PCI_CONFIG_TYPE_1); + pci_register_slot(0x00, PCI_CARD_NORTHBRIDGE, 0, 0, 0, 0); + pci_register_slot(0x07, PCI_CARD_SOUTHBRIDGE, 0, 0, 3, 5); + pci_register_slot(0x09, PCI_CARD_NORMAL, 1, 2, 3, 5); + pci_register_slot(0x0a, PCI_CARD_NORMAL, 2, 3, 5, 1); + pci_register_slot(0x0b, PCI_CARD_NORMAL, 3, 5, 1, 2); + pci_register_slot(0x0c, PCI_CARD_NORMAL, 5, 1, 2, 3); + pci_register_slot(0x0d, PCI_CARD_NORMAL, 5, 3, 2, 1); + pci_register_slot(0x01, PCI_CARD_AGPBRIDGE, 1, 2, 3, 5); + device_add(&via_apro133a_device); /* Rebranded as ET82C693A */ + device_add(&via_vt82c596b_device); /* Rebranded as ET82C696B */ + device_add(&w83977ef_device); + device_add(&keyboard_ps2_ami_pci_device); + device_add(&sst_flash_39sf020_device); + spd_register(SPD_TYPE_SDRAM, 0x7, 256); + + return ret; +} + +int +machine_at_p6bat_init(const machine_t *model) +{ + int ret; + + ret = bios_load_linear("roms/machines/p6bat/bata+56.BIN", + 0x000c0000, 262144, 0); + + if (bios_only || !ret) + return ret; + + machine_at_common_init_ex(model, 2); + + pci_init(PCI_CONFIG_TYPE_1); + pci_register_slot(0x00, PCI_CARD_NORTHBRIDGE, 0, 0, 0, 0); + pci_register_slot(0x07, PCI_CARD_SOUTHBRIDGE, 0, 0, 3, 5); + pci_register_slot(0x09, PCI_CARD_NORMAL, 1, 2, 3, 5); + pci_register_slot(0x0a, PCI_CARD_NORMAL, 2, 3, 5, 1); + pci_register_slot(0x0b, PCI_CARD_NORMAL, 3, 5, 1, 2); + pci_register_slot(0x0c, PCI_CARD_NORMAL, 5, 1, 2, 3); + pci_register_slot(0x0d, PCI_CARD_NORMAL, 5, 3, 2, 1); + pci_register_slot(0x01, PCI_CARD_AGPBRIDGE, 1, 2, 3, 5); + device_add(&via_apro133_device); + device_add(&via_vt82c596b_device); + device_add(&w83977ef_device); + device_add(&keyboard_ps2_ami_pci_device); + device_add(&sst_flash_39sf020_device); + spd_register(SPD_TYPE_SDRAM, 0x7, 256); + + if (sound_card_current[0] == SOUND_INTERNAL) + device_add(&cmi8738_onboard_device); + + return ret; +} + +int +machine_at_cubx_init(const machine_t *model) +{ + int ret; + + ret = bios_load_linear("roms/machines/cubx/1008cu.004", + 0x000c0000, 262144, 0); + + if (bios_only || !ret) + return ret; + + machine_at_common_init_ex(model, 2); + + pci_init(PCI_CONFIG_TYPE_1); + pci_register_slot(0x00, PCI_CARD_NORTHBRIDGE, 0, 0, 0, 0); + pci_register_slot(0x04, PCI_CARD_SOUTHBRIDGE, 1, 2, 3, 4); + pci_register_slot(0x07, PCI_CARD_IDE, 2, 3, 4, 1); + pci_register_slot(0x09, PCI_CARD_NORMAL, 4, 1, 2, 3); + pci_register_slot(0x0A, PCI_CARD_NORMAL, 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(0x0D, PCI_CARD_NORMAL, 4, 1, 2, 3); + pci_register_slot(0x0E, PCI_CARD_NORMAL, 3, 4, 1, 2); + pci_register_slot(0x01, PCI_CARD_AGPBRIDGE, 1, 2, 3, 4); + device_add(&i440bx_device); + device_add(&piix4e_device); + device_add(&keyboard_ps2_ami_pci_device); + device_add(&w83977ef_device); + device_add(ics9xxx_get(ICS9250_08)); + device_add(&sst_flash_39sf020_device); + spd_register(SPD_TYPE_SDRAM, 0xF, 256); + device_add(&as99127f_device); /* fans: Chassis, CPU, Power; temperatures: MB, JTPWR, CPU */ + + return ret; +} + +int +machine_at_atc7020bxii_init(const machine_t *model) +{ + int ret; + + ret = bios_load_linear("roms/machines/atc7020bxii/7020s102.bin", + 0x000c0000, 262144, 0); + + if (bios_only || !ret) + return ret; + + machine_at_common_init_ex(model, 2); + + pci_init(PCI_CONFIG_TYPE_1); + pci_register_slot(0x00, PCI_CARD_NORTHBRIDGE, 0, 0, 0, 0); + pci_register_slot(0x07, PCI_CARD_SOUTHBRIDGE, 1, 2, 3, 4); + pci_register_slot(0x0A, PCI_CARD_NORMAL, 1, 2, 3, 4); + pci_register_slot(0x0B, PCI_CARD_NORMAL, 2, 3, 4, 1); + pci_register_slot(0x0C, PCI_CARD_NORMAL, 3, 4, 1, 2); + pci_register_slot(0x0D, PCI_CARD_NORMAL, 4, 1, 2, 3); + pci_register_slot(0x0E, PCI_CARD_NORMAL, 4, 1, 2, 3); + pci_register_slot(0x01, PCI_CARD_AGPBRIDGE, 1, 2, 3, 4); + device_add(&i440bx_device); + device_add(&slc90e66_device); + device_add(&keyboard_ps2_pci_device); + device_add(&w83977ef_device); + device_add(&sst_flash_39sf020_device); + spd_register(SPD_TYPE_SDRAM, 0xF, 256); + + return ret; +} + +int +machine_at_ambx133_init(const machine_t *model) +{ + int ret; + + ret = bios_load_linear("roms/machines/ambx133/mkbx2vg2.bin", + 0x000c0000, 262144, 0); + + if (bios_only || !ret) + return ret; + + machine_at_common_init_ex(model, 2); + + pci_init(PCI_CONFIG_TYPE_1); + pci_register_slot(0x00, PCI_CARD_NORTHBRIDGE, 0, 0, 0, 0); + pci_register_slot(0x07, PCI_CARD_SOUTHBRIDGE, 1, 2, 3, 4); + pci_register_slot(0x09, PCI_CARD_NORMAL, 1, 2, 3, 4); + pci_register_slot(0x0A, PCI_CARD_NORMAL, 2, 3, 4, 1); + pci_register_slot(0x0B, PCI_CARD_NORMAL, 3, 4, 1, 2); + pci_register_slot(0x0C, PCI_CARD_NORMAL, 4, 1, 2, 3); + pci_register_slot(0x0D, PCI_CARD_NORMAL, 4, 1, 2, 3); + pci_register_slot(0x01, PCI_CARD_AGPBRIDGE, 1, 2, 3, 4); + device_add(&i440bx_device); + device_add(&piix4e_device); + device_add(&w83977ef_device); + device_add(&keyboard_ps2_ami_pci_device); + device_add(&sst_flash_39sf020_device); + spd_register(SPD_TYPE_SDRAM, 0x7, 256); + device_add(&gl518sm_2d_device); /* fans: CPUFAN1, CPUFAN2; temperature: CPU */ + hwm_values.fans[1] += 500; + hwm_values.temperatures[0] += 4; /* CPU offset */ + hwm_values.voltages[1] = RESISTOR_DIVIDER(12000, 10, 2); /* different 12V divider in BIOS (10K/2K?) */ + + return ret; +} + +int +machine_at_awo671r_init(const machine_t *model) +{ + int ret; + + ret = bios_load_linear("roms/machines/awo671r/a08139c.bin", + 0x000c0000, 262144, 0); + + if (bios_only || !ret) + return ret; + + machine_at_common_init_ex(model, 2); + + pci_init(PCI_CONFIG_TYPE_1); + pci_register_slot(0x00, PCI_CARD_NORTHBRIDGE, 0, 0, 0, 0); + pci_register_slot(0x07, PCI_CARD_SOUTHBRIDGE, 1, 2, 3, 4); + pci_register_slot(0x09, PCI_CARD_NORMAL, 1, 2, 3, 4); + pci_register_slot(0x0A, PCI_CARD_NORMAL, 2, 3, 4, 1); + pci_register_slot(0x0B, PCI_CARD_NORMAL, 3, 4, 1, 2); + pci_register_slot(0x0C, PCI_CARD_NORMAL, 4, 1, 2, 3); + pci_register_slot(0x0D, PCI_CARD_NORMAL, 2, 3, 4, 1); + pci_register_slot(0x01, PCI_CARD_AGPBRIDGE, 1, 2, 3, 4); + device_add(&i440bx_device); + device_add(&piix4e_device); + device_add_inst(&w83977ef_device, 1); + device_add_inst(&w83977ef_device, 2); + device_add(&keyboard_ps2_pci_device); + device_add(&sst_flash_39sf020_device); + spd_register(SPD_TYPE_SDRAM, 0x3, 256); + + return ret; +} + +int +machine_at_63a1_init(const machine_t *model) +{ + int ret; + + ret = bios_load_linear("roms/machines/63a1/63a-q3.bin", + 0x000c0000, 262144, 0); + + if (bios_only || !ret) + return ret; + + machine_at_common_init_ex(model, 2); + + pci_init(PCI_CONFIG_TYPE_1); + pci_register_slot(0x00, PCI_CARD_NORTHBRIDGE, 0, 0, 0, 0); + pci_register_slot(0x07, PCI_CARD_SOUTHBRIDGE, 1, 2, 3, 4); + pci_register_slot(0x08, PCI_CARD_NORMAL, 1, 2, 3, 4); + pci_register_slot(0x09, PCI_CARD_NORMAL, 2, 3, 4, 1); + pci_register_slot(0x0A, PCI_CARD_NORMAL, 3, 4, 1, 2); + pci_register_slot(0x0B, PCI_CARD_NORMAL, 4, 1, 2, 3); + pci_register_slot(0x0C, PCI_CARD_NORMAL, 1, 2, 3, 4); /* Integrated Sound? */ + pci_register_slot(0x01, PCI_CARD_AGPBRIDGE, 1, 2, 3, 4); + device_add(&i440zx_device); + device_add(&piix4e_device); + device_add(&w83977tf_device); + device_add(&keyboard_ps2_ami_pci_device); + device_add(&intel_flash_bxt_device); + spd_register(SPD_TYPE_SDRAM, 0x3, 256); + + return ret; +} + +int +machine_at_apas3_init(const machine_t *model) +{ + int ret; + + ret = bios_load_linear("roms/machines/apas3/V0218SAG.BIN", + 0x000c0000, 262144, 0); + + if (bios_only || !ret) + return ret; + + machine_at_common_init_ex(model, 2); + + pci_init(PCI_CONFIG_TYPE_1); + pci_register_slot(0x00, PCI_CARD_NORTHBRIDGE, 0, 0, 0, 0); + pci_register_slot(0x07, PCI_CARD_SOUTHBRIDGE, 1, 2, 0, 0); + pci_register_slot(0x0F, PCI_CARD_NORMAL, 1, 2, 3, 4); + pci_register_slot(0x10, PCI_CARD_NORMAL, 2, 3, 4, 1); + pci_register_slot(0x13, PCI_CARD_NORMAL, 3, 4, 1, 2); + pci_register_slot(0x14, PCI_CARD_NORMAL, 4, 1, 2, 3); + pci_register_slot(0x01, PCI_CARD_AGPBRIDGE, 1, 2, 3, 4); + device_add(&via_apro_device); + device_add(&via_vt82c586b_device); + device_add(&fdc37c669_device); + device_add(&keyboard_ps2_ami_pci_device); + device_add(&sst_flash_39sf020_device); + spd_register(SPD_TYPE_SDRAM, 0x7, 256); + + return ret; +} + +int +machine_at_cuv4xls_init(const machine_t *model) +{ + int ret; + + ret = bios_load_linear("roms/machines/cuv4xls/1005LS.001", + 0x000c0000, 262144, 0); + + if (bios_only || !ret) + return ret; + + machine_at_common_init_ex(model, 2); + + pci_init(PCI_CONFIG_TYPE_1); + pci_register_slot(0x00, PCI_CARD_NORTHBRIDGE, 0, 0, 0, 0); + pci_register_slot(0x04, PCI_CARD_SOUTHBRIDGE, 4, 1, 2, 3); + pci_register_slot(0x05, PCI_CARD_SOUND, 3, 0, 0, 0); + pci_register_slot(0x06, PCI_CARD_NORMAL, 3, 4, 1, 2); + pci_register_slot(0x07, PCI_CARD_NORMAL, 2, 3, 0, 0); + pci_register_slot(0x08, PCI_CARD_NORMAL, 1, 2, 3, 4); + pci_register_slot(0x09, PCI_CARD_NORMAL, 4, 1, 2, 3); + pci_register_slot(0x0A, PCI_CARD_NORMAL, 3, 4, 1, 2); + pci_register_slot(0x0B, PCI_CARD_NORMAL, 2, 3, 4, 1); + pci_register_slot(0x14, PCI_CARD_NORMAL, 4, 0, 0, 0); + pci_register_slot(0x01, PCI_CARD_AGPBRIDGE, 1, 2, 3, 4); + device_add(&via_apro133a_device); + device_add(&via_vt82c686b_device); + device_add(&keyboard_ps2_ami_pci_device); + device_add(ics9xxx_get(ICS9250_18)); + device_add(&sst_flash_39sf020_device); + spd_register(SPD_TYPE_SDRAM, 0xF, 1024); + device_add(&as99127f_device); /* fans: Chassis, CPU, Power; temperatures: MB, JTPWR, CPU */ + + if (sound_card_current[0] == SOUND_INTERNAL) + device_add(&cmi8738_onboard_device); + + return ret; +} + +int +machine_at_6via90ap_init(const machine_t *model) +{ + int ret; + + ret = bios_load_linear("roms/machines/6via90ap/90ap10.bin", + 0x000c0000, 262144, 0); + + if (bios_only || !ret) + return ret; + + machine_at_common_init_ex(model, 2); + + pci_init(PCI_CONFIG_TYPE_1); + pci_register_slot(0x00, PCI_CARD_NORTHBRIDGE, 0, 0, 0, 0); + pci_register_slot(0x07, PCI_CARD_SOUTHBRIDGE, 1, 2, 3, 4); + pci_register_slot(0x09, PCI_CARD_NORMAL, 1, 2, 3, 4); + pci_register_slot(0x0A, PCI_CARD_NORMAL, 2, 3, 4, 1); + pci_register_slot(0x0B, PCI_CARD_NORMAL, 3, 4, 1, 2); + pci_register_slot(0x0C, PCI_CARD_NORMAL, 4, 1, 2, 3); + pci_register_slot(0x0D, PCI_CARD_NORMAL, 1, 2, 3, 4); + pci_register_slot(0x01, PCI_CARD_AGPBRIDGE, 1, 2, 3, 4); + device_add(&via_apro133a_device); + device_add(&via_vt82c686b_device); /* fans: CPU1, CPU2; temperatures: CPU, System, unused */ + device_add(&keyboard_ps2_ami_pci_device); + device_add(ics9xxx_get(ICS9250_18)); + device_add(&sst_flash_39sf020_device); + spd_register(SPD_TYPE_SDRAM, 0x7, 1024); + hwm_values.temperatures[0] += 2; /* CPU offset */ + hwm_values.temperatures[1] += 2; /* System offset */ + hwm_values.temperatures[2] = 0; /* unused */ + + if (sound_card_current[0] == SOUND_INTERNAL) + device_add(&alc100_device); /* ALC100P identified on similar Acorp boards (694TA, 6VIA90A1) */ + + return ret; +} diff --git a/src/machine/m_at_socket4.c b/src/machine/m_at_socket4.c index 0e526b448..ad6d2c995 100644 --- a/src/machine/m_at_socket4.c +++ b/src/machine/m_at_socket4.c @@ -1,20 +1,18 @@ /* - * 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. + * 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. + * This file is part of the 86Box distribution. * - * Implementation of Socket 4 machines. + * Implementation of Socket 4 machines. * * * - * Authors: Sarah Walker, - * Miran Grca, + * Authors: Miran Grca, * - * Copyright 2010-2019 Sarah Walker. - * Copyright 2016-2019 Miran Grca. + * Copyright 2016-2019 Miran Grca. */ #include #include @@ -39,10 +37,10 @@ #include <86box/nvr.h> #include <86box/scsi_ncr53c8xx.h> #include <86box/sio.h> +#include <86box/timer.h> #include <86box/video.h> #include <86box/machine.h> - void machine_at_premiere_common_init(const machine_t *model, int pci_switch) { @@ -51,10 +49,10 @@ machine_at_premiere_common_init(const machine_t *model, int pci_switch) pci_init(PCI_CONFIG_TYPE_2 | pci_switch); pci_register_slot(0x00, PCI_CARD_NORTHBRIDGE, 0, 0, 0, 0); - pci_register_slot(0x01, PCI_CARD_IDE, 0, 0, 0, 0); - pci_register_slot(0x06, PCI_CARD_NORMAL, 3, 2, 1, 4); - pci_register_slot(0x0E, PCI_CARD_NORMAL, 2, 1, 3, 4); - pci_register_slot(0x0C, PCI_CARD_NORMAL, 1, 3, 2, 4); + pci_register_slot(0x01, PCI_CARD_IDE, 0, 0, 0, 0); + pci_register_slot(0x06, PCI_CARD_NORMAL, 3, 2, 1, 4); + pci_register_slot(0x0E, PCI_CARD_NORMAL, 2, 1, 3, 4); + pci_register_slot(0x0C, PCI_CARD_NORMAL, 1, 3, 2, 4); pci_register_slot(0x02, PCI_CARD_SOUTHBRIDGE, 0, 0, 0, 0); device_add(&keyboard_ps2_intel_ami_pci_device); device_add(&sio_zb_device); @@ -62,7 +60,6 @@ machine_at_premiere_common_init(const machine_t *model, int pci_switch) device_add(&intel_flash_bxt_ami_device); } - void machine_at_award_common_init(const machine_t *model) { @@ -71,22 +68,23 @@ machine_at_award_common_init(const machine_t *model) pci_init(PCI_CONFIG_TYPE_2 | PCI_NO_IRQ_STEERING); pci_register_slot(0x00, PCI_CARD_NORTHBRIDGE, 0, 0, 0, 0); - pci_register_slot(0x01, PCI_CARD_IDE, 0, 0, 0, 0); - pci_register_slot(0x03, PCI_CARD_NORMAL, 1, 2, 3, 4); /* 03 = Slot 1 */ - pci_register_slot(0x04, PCI_CARD_NORMAL, 2, 3, 4, 1); /* 04 = Slot 2 */ - pci_register_slot(0x05, PCI_CARD_NORMAL, 3, 4, 1, 2); /* 05 = Slot 3 */ - pci_register_slot(0x06, PCI_CARD_NORMAL, 4, 1, 2, 3); /* 06 = Slot 4 */ - pci_register_slot(0x07, PCI_CARD_SCSI, 1, 2, 3, 4); /* 07 = SCSI */ + pci_register_slot(0x01, PCI_CARD_IDE, 0, 0, 0, 0); + pci_register_slot(0x03, PCI_CARD_NORMAL, 1, 2, 3, 4); /* 03 = Slot 1 */ + pci_register_slot(0x04, PCI_CARD_NORMAL, 2, 3, 4, 1); /* 04 = Slot 2 */ + pci_register_slot(0x05, PCI_CARD_NORMAL, 3, 4, 1, 2); /* 05 = Slot 3 */ + pci_register_slot(0x06, PCI_CARD_NORMAL, 4, 1, 2, 3); /* 06 = Slot 4 */ + pci_register_slot(0x07, PCI_CARD_SCSI, 1, 2, 3, 4); /* 07 = SCSI */ pci_register_slot(0x02, PCI_CARD_SOUTHBRIDGE, 0, 0, 0, 0); if (fdc_type == FDC_INTERNAL) - device_add(&fdc_at_device); + device_add(&fdc_at_device); - // device_add(&keyboard_ps2_pci_device); +#if 0 + device_add(&keyboard_ps2_pci_device); +#endif device_add(&keyboard_ps2_ami_pci_device); } - void machine_at_sp4_common_init(const machine_t *model) { @@ -99,10 +97,10 @@ machine_at_sp4_common_init(const machine_t *model) pci_register_slot(0x0D, PCI_CARD_IDE, 1, 2, 3, 4); /* Excluded: 02, 03*, 04*, 05*, 06*, 07*, 08* */ /* Slots: 09 (04), 0A (03), 0B (02), 0C (07) */ - pci_register_slot(0x0C, PCI_CARD_NORMAL, 1, 2, 3, 4); - pci_register_slot(0x0B, PCI_CARD_NORMAL, 2, 3, 4, 1); - pci_register_slot(0x0A, PCI_CARD_NORMAL, 3, 4, 1, 2); - pci_register_slot(0x09, PCI_CARD_NORMAL, 4, 1, 2, 3); + pci_register_slot(0x0C, PCI_CARD_NORMAL, 1, 2, 3, 4); + pci_register_slot(0x0B, PCI_CARD_NORMAL, 2, 3, 4, 1); + pci_register_slot(0x0A, PCI_CARD_NORMAL, 3, 4, 1, 2); + pci_register_slot(0x09, PCI_CARD_NORMAL, 4, 1, 2, 3); device_add(&sis_85c50x_device); device_add(&ide_cmd640_pci_device); device_add(&keyboard_ps2_ami_pci_device); @@ -110,26 +108,25 @@ machine_at_sp4_common_init(const machine_t *model) device_add(&intel_flash_bxt_device); } - int machine_at_excaliburpci_init(const machine_t *model) { int ret; ret = bios_load_linear_inverted("roms/machines/excaliburpci/S701P.ROM", - 0x000e0000, 131072, 0); + 0x000e0000, 131072, 0); if (bios_only || !ret) - return ret; + return ret; machine_at_common_init(model); pci_init(PCI_CONFIG_TYPE_2); pci_register_slot(0x00, PCI_CARD_NORTHBRIDGE, 0, 0, 0, 0); - pci_register_slot(0x03, PCI_CARD_IDE, 0, 0, 0, 0); - pci_register_slot(0x0F, PCI_CARD_NORMAL, 1, 2, 3, 4); - pci_register_slot(0x0E, PCI_CARD_NORMAL, 2, 3, 4, 1); - pci_register_slot(0x0D, PCI_CARD_NORMAL, 3, 4, 1, 2); + pci_register_slot(0x03, PCI_CARD_IDE, 0, 0, 0, 0); + pci_register_slot(0x0F, PCI_CARD_NORMAL, 1, 2, 3, 4); + pci_register_slot(0x0E, PCI_CARD_NORMAL, 2, 3, 4, 1); + pci_register_slot(0x0D, PCI_CARD_NORMAL, 3, 4, 1, 2); pci_register_slot(0x02, PCI_CARD_SOUTHBRIDGE, 0, 0, 0, 0); device_add(&fdc37c665_device); device_add(&keyboard_ps2_ami_pci_device); @@ -142,26 +139,25 @@ machine_at_excaliburpci_init(const machine_t *model) return ret; } - int machine_at_p5mp3_init(const machine_t *model) { int ret; ret = bios_load_linear("roms/machines/p5mp3/0205.bin", - 0x000e0000, 131072, 0); + 0x000e0000, 131072, 0); if (bios_only || !ret) - return ret; + return ret; machine_at_common_init(model); device_add(&ide_pci_device); pci_init(PCI_CONFIG_TYPE_2 | PCI_NO_IRQ_STEERING); pci_register_slot(0x00, PCI_CARD_NORTHBRIDGE, 0, 0, 0, 0); - pci_register_slot(0x05, PCI_CARD_NORMAL, 1, 2, 3, 4); /* 05 = Slot 1 */ - pci_register_slot(0x04, PCI_CARD_NORMAL, 2, 3, 4, 1); /* 04 = Slot 2 */ - pci_register_slot(0x03, PCI_CARD_NORMAL, 3, 4, 1, 2); /* 03 = Slot 3 */ + pci_register_slot(0x05, PCI_CARD_NORMAL, 1, 2, 3, 4); /* 05 = Slot 1 */ + pci_register_slot(0x04, PCI_CARD_NORMAL, 2, 3, 4, 1); /* 04 = Slot 2 */ + pci_register_slot(0x03, PCI_CARD_NORMAL, 3, 4, 1, 2); /* 03 = Slot 3 */ pci_register_slot(0x02, PCI_CARD_SOUTHBRIDGE, 0, 0, 0, 0); device_add(&fdc_at_device); device_add(&keyboard_ps2_pci_device); @@ -173,17 +169,16 @@ machine_at_p5mp3_init(const machine_t *model) return ret; } - int machine_at_dellxp60_init(const machine_t *model) { int ret; ret = bios_load_linear_inverted("roms/machines/dellxp60/XP60-A08.ROM", - 0x000e0000, 131072, 0); - + 0x000e0000, 131072, 0); + if (bios_only || !ret) - return ret; + return ret; machine_at_common_init(model); device_add(&ide_pci_2ch_device); @@ -192,10 +187,10 @@ machine_at_dellxp60_init(const machine_t *model) pci_register_slot(0x00, PCI_CARD_NORTHBRIDGE, 0, 0, 0, 0); /* Not: 00, 02, 03, 04, 05, 06, 07, 08, 09, 0A, 0B, 0C, 0D, 0E, 0F. */ /* Yes: 01, 10, 11, 12, 13, 14. */ - pci_register_slot(0x01, PCI_CARD_NORMAL, 1, 3, 2, 4); - pci_register_slot(0x04, PCI_CARD_NORMAL, 4, 4, 3, 3); - pci_register_slot(0x05, PCI_CARD_NORMAL, 1, 4, 3, 2); - pci_register_slot(0x06, PCI_CARD_NORMAL, 2, 1, 3, 4); + pci_register_slot(0x01, PCI_CARD_NORMAL, 1, 3, 2, 4); + pci_register_slot(0x04, PCI_CARD_NORMAL, 4, 4, 3, 3); + pci_register_slot(0x05, PCI_CARD_NORMAL, 1, 4, 3, 2); + pci_register_slot(0x06, PCI_CARD_NORMAL, 2, 1, 3, 4); pci_register_slot(0x02, PCI_CARD_SOUTHBRIDGE, 0, 0, 0, 0); device_add(&i430lx_device); device_add(&keyboard_ps2_intel_ami_pci_device); @@ -206,26 +201,25 @@ machine_at_dellxp60_init(const machine_t *model) return ret; } - int machine_at_opti560l_init(const machine_t *model) { int ret; ret = bios_load_linear_inverted("roms/machines/opti560l/560L_A06.ROM", - 0x000e0000, 131072, 0); + 0x000e0000, 131072, 0); if (bios_only || !ret) - return ret; + return ret; machine_at_common_init(model); device_add(&ide_pci_2ch_device); pci_init(PCI_CONFIG_TYPE_2); pci_register_slot(0x00, PCI_CARD_NORTHBRIDGE, 0, 0, 0, 0); - pci_register_slot(0x03, PCI_CARD_NORMAL, 4, 4, 3, 3); - pci_register_slot(0x07, PCI_CARD_NORMAL, 1, 4, 3, 2); - pci_register_slot(0x08, PCI_CARD_NORMAL, 2, 1, 3, 4); + pci_register_slot(0x03, PCI_CARD_NORMAL, 4, 4, 3, 3); + pci_register_slot(0x07, PCI_CARD_NORMAL, 1, 4, 3, 2); + pci_register_slot(0x08, PCI_CARD_NORMAL, 2, 1, 3, 4); pci_register_slot(0x02, PCI_CARD_SOUTHBRIDGE, 0, 0, 0, 0); device_add(&i430lx_device); device_add(&keyboard_ps2_intel_ami_pci_device); @@ -236,17 +230,17 @@ machine_at_opti560l_init(const machine_t *model) return ret; } - int machine_at_ambradp60_init(const machine_t *model) { int ret; ret = bios_load_linear_combined("roms/machines/ambradp60/1004AF1P.BIO", - "roms/machines/ambradp60/1004AF1P.BI1", 0x1c000, 128); + "roms/machines/ambradp60/1004AF1P.BI1", + 0x1c000, 128); if (bios_only || !ret) - return ret; + return ret; machine_at_premiere_common_init(model, 0); @@ -255,27 +249,28 @@ machine_at_ambradp60_init(const machine_t *model) return ret; } - int machine_at_valuepointp60_init(const machine_t *model) { int ret; ret = bios_load_linear_combined("roms/machines/valuepointp60/1006AV0M.BIO", - "roms/machines/valuepointp60/1006AV0M.BI1", 0x1d000, 128); + "roms/machines/valuepointp60/1006AV0M.BI1", + 0x1d000, 128); if (bios_only || !ret) - return ret; + return ret; machine_at_common_init(model); device_add(&ide_pci_2ch_device); pci_init(PCI_CONFIG_TYPE_2 | PCI_NO_IRQ_STEERING); pci_register_slot(0x00, PCI_CARD_NORTHBRIDGE, 0, 0, 0, 0); - pci_register_slot(0x01, PCI_CARD_IDE, 0, 0, 0, 0); - pci_register_slot(0x06, PCI_CARD_NORMAL, 3, 2, 1, 4); - pci_register_slot(0x0E, PCI_CARD_NORMAL, 2, 1, 3, 4); - pci_register_slot(0x0C, PCI_CARD_NORMAL, 1, 3, 2, 4); + pci_register_slot(0x01, PCI_CARD_IDE, 0, 0, 0, 0); + pci_register_slot(0x03, PCI_CARD_VIDEO, 3, 3, 3, 3); + pci_register_slot(0x06, PCI_CARD_NORMAL, 3, 2, 1, 4); + pci_register_slot(0x0E, PCI_CARD_NORMAL, 2, 1, 3, 4); + pci_register_slot(0x0C, PCI_CARD_NORMAL, 1, 3, 2, 4); pci_register_slot(0x02, PCI_CARD_SOUTHBRIDGE, 0, 0, 0, 0); device_add(&keyboard_ps2_ps1_pci_device); device_add(&sio_device); @@ -284,20 +279,23 @@ machine_at_valuepointp60_init(const machine_t *model) device_add(&i430lx_device); + if (gfxcard[0] == VID_INTERNAL) + device_add(&mach32_onboard_pci_device); + return ret; } - int machine_at_revenge_init(const machine_t *model) { int ret; ret = bios_load_linear_combined("roms/machines/revenge/1009af2_.bio", - "roms/machines/revenge/1009af2_.bi1", 0x1c000, 128); + "roms/machines/revenge/1009af2_.bi1", + 0x1c000, 128); if (bios_only || !ret) - return ret; + return ret; machine_at_premiere_common_init(model, 0); @@ -306,17 +304,16 @@ machine_at_revenge_init(const machine_t *model) return ret; } - int machine_at_586mc1_init(const machine_t *model) { int ret; ret = bios_load_linear("roms/machines/586mc1/IS.34", - 0x000e0000, 131072, 0); + 0x000e0000, 131072, 0); if (bios_only || !ret) - return ret; + return ret; machine_at_award_common_init(model); @@ -327,33 +324,33 @@ machine_at_586mc1_init(const machine_t *model) return ret; } - int machine_at_pb520r_init(const machine_t *model) { int ret; ret = bios_load_linear_combined("roms/machines/pb520r/1009bc0r.bio", - "roms/machines/pb520r/1009bc0r.bi1", 0x1d000, 128); + "roms/machines/pb520r/1009bc0r.bi1", + 0x1d000, 128); if (bios_only || !ret) - return ret; + return ret; machine_at_common_init(model); pci_init(PCI_CONFIG_TYPE_2); pci_register_slot(0x00, PCI_CARD_NORTHBRIDGE, 0, 0, 0, 0); - pci_register_slot(0x01, PCI_CARD_IDE, 0, 0, 0, 0); - pci_register_slot(0x03, PCI_CARD_VIDEO, 3, 3, 3, 3); - pci_register_slot(0x06, PCI_CARD_NORMAL, 3, 2, 1, 4); - pci_register_slot(0x0E, PCI_CARD_NORMAL, 2, 1, 3, 4); - pci_register_slot(0x0C, PCI_CARD_NORMAL, 1, 3, 2, 4); + pci_register_slot(0x01, PCI_CARD_IDE, 0, 0, 0, 0); + pci_register_slot(0x03, PCI_CARD_VIDEO, 3, 3, 3, 3); + pci_register_slot(0x06, PCI_CARD_NORMAL, 3, 2, 1, 4); + pci_register_slot(0x0E, PCI_CARD_NORMAL, 2, 1, 3, 4); + pci_register_slot(0x0C, PCI_CARD_NORMAL, 1, 3, 2, 4); pci_register_slot(0x02, PCI_CARD_SOUTHBRIDGE, 0, 0, 0, 0); device_add(&i430lx_device); device_add(&ide_cmd640_pci_single_channel_device); - if (gfxcard == VID_INTERNAL) - device_add(&gd5434_onboard_pci_device); + if (gfxcard[0] == VID_INTERNAL) + device_add(&gd5434_onboard_pci_device); device_add(&keyboard_ps2_pci_device); device_add(&sio_zb_device); @@ -363,24 +360,16 @@ machine_at_pb520r_init(const machine_t *model) return ret; } - -const device_t * -at_pb520r_get_device(void) -{ - return &gd5434_onboard_pci_device; -} - - int machine_at_excalibur_init(const machine_t *model) { int ret; ret = bios_load_linear_inverted("roms/machines/excalibur/S75P.ROM", - 0x000e0000, 131072, 0); + 0x000e0000, 131072, 0); if (bios_only || !ret) - return ret; + return ret; machine_at_common_init(model); @@ -392,46 +381,48 @@ machine_at_excalibur_init(const machine_t *model) return ret; } - int machine_at_p5vl_init(const machine_t *model) { int ret; ret = bios_load_linear("roms/machines/p5vl/SM507.ROM", - 0x000e0000, 131072, 0); + 0x000e0000, 131072, 0); if (bios_only || !ret) - return ret; + return ret; machine_at_common_init(model); + pci_init(PCI_CONFIG_TYPE_1); pci_register_slot(0x10, PCI_CARD_NORTHBRIDGE, 0, 0, 0, 0); - pci_register_slot(0x11, PCI_CARD_NORMAL, 1, 2, 3, 4); - pci_register_slot(0x12, PCI_CARD_NORMAL, 2, 3, 4, 1); - pci_register_slot(0x13, PCI_CARD_NORMAL, 3, 4, 1, 2); - device_add(&opti5x7_device); + + pci_register_slot(0x11, PCI_CARD_NORMAL, 1, 2, 3, 4); + pci_register_slot(0x12, PCI_CARD_NORMAL, 5, 6, 7, 8); + pci_register_slot(0x13, PCI_CARD_NORMAL, 9, 10, 11, 12); + pci_register_slot(0x14, PCI_CARD_NORMAL, 13, 14, 15, 16); + + device_add(&opti5x7_pci_device); device_add(&opti822_device); device_add(&sst_flash_29ee010_device); device_add(&keyboard_at_ami_device); if (fdc_type == FDC_INTERNAL) - device_add(&fdc_at_device); + device_add(&fdc_at_device); return ret; } - int machine_at_excaliburpci2_init(const machine_t *model) { int ret; ret = bios_load_linear_inverted("roms/machines/excaliburpci2/S722P.ROM", - 0x000e0000, 131072, 0); + 0x000e0000, 131072, 0); if (bios_only || !ret) - return ret; + return ret; machine_at_common_init_ex(model, 2); device_add(&ami_1994_nvr_device); @@ -439,11 +430,11 @@ machine_at_excaliburpci2_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(0x01, PCI_CARD_SOUTHBRIDGE, 0, 0, 0, 0); - pci_register_slot(0x08, PCI_CARD_IDE, 0, 0, 0, 0); - pci_register_slot(0x0A, PCI_CARD_NORMAL, 1, 2, 3, 4); - pci_register_slot(0x0B, PCI_CARD_NORMAL, 2, 3, 4, 1); - pci_register_slot(0x0C, PCI_CARD_NORMAL, 3, 4, 1, 2); - pci_register_slot(0x0D, PCI_CARD_NORMAL, 4, 1, 2, 3); + pci_register_slot(0x08, PCI_CARD_IDE, 0, 0, 0, 0); + pci_register_slot(0x0A, PCI_CARD_NORMAL, 1, 2, 3, 4); + pci_register_slot(0x0B, PCI_CARD_NORMAL, 2, 3, 4, 1); + pci_register_slot(0x0C, PCI_CARD_NORMAL, 3, 4, 1, 2); + pci_register_slot(0x0D, PCI_CARD_NORMAL, 4, 1, 2, 3); device_add(&fdc37c665_device); device_add(&keyboard_ps2_ami_pci_device); device_add(&ide_cmd640_pci_legacy_only_device); @@ -454,17 +445,16 @@ machine_at_excaliburpci2_init(const machine_t *model) return ret; } - int machine_at_p5sp4_init(const machine_t *model) { int ret; ret = bios_load_linear("roms/machines/p5sp4/0106.001", - 0x000e0000, 131072, 0); + 0x000e0000, 131072, 0); if (bios_only || !ret) - return ret; + return ret; machine_at_sp4_common_init(model); diff --git a/src/machine/m_at_socket5.c b/src/machine/m_at_socket5.c index 4a1bb9802..5a336da24 100644 --- a/src/machine/m_at_socket5.c +++ b/src/machine/m_at_socket5.c @@ -1,20 +1,18 @@ /* - * 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. + * 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. + * This file is part of the 86Box distribution. * - * Implementation of Socket 5 machines. + * Implementation of Socket 5 machines. * * * - * Authors: Sarah Walker, - * Miran Grca, + * Authors: Miran Grca, * - * Copyright 2010-2019 Sarah Walker. - * Copyright 2016-2019 Miran Grca. + * Copyright 2016-2019 Miran Grca. */ #include #include @@ -42,17 +40,17 @@ #include <86box/video.h> #include <86box/machine.h> - int machine_at_plato_init(const machine_t *model) { int ret; ret = bios_load_linear_combined("roms/machines/plato/1016ax1_.bio", - "roms/machines/plato/1016ax1_.bi1", 0x1d000, 128); + "roms/machines/plato/1016ax1_.bi1", + 0x1d000, 128); if (bios_only || !ret) - return ret; + return ret; machine_at_premiere_common_init(model, PCI_CAN_SWITCH_TYPE); @@ -61,17 +59,17 @@ machine_at_plato_init(const machine_t *model) return ret; } - int machine_at_ambradp90_init(const machine_t *model) { int ret; ret = bios_load_linear_combined("roms/machines/ambradp90/1002AX1P.BIO", - "roms/machines/ambradp90/1002AX1P.BI1", 0x1d000, 128); + "roms/machines/ambradp90/1002AX1P.BI1", + 0x1d000, 128); if (bios_only || !ret) - return ret; + return ret; machine_at_premiere_common_init(model, PCI_CAN_SWITCH_TYPE); @@ -80,17 +78,16 @@ machine_at_ambradp90_init(const machine_t *model) return ret; } - int machine_at_430nx_init(const machine_t *model) { int ret; ret = bios_load_linear("roms/machines/430nx/IP.20", - 0x000e0000, 131072, 0); + 0x000e0000, 131072, 0); if (bios_only || !ret) - return ret; + return ret; machine_at_award_common_init(model); @@ -101,27 +98,26 @@ machine_at_430nx_init(const machine_t *model) return ret; } - int machine_at_acerv30_init(const machine_t *model) { int ret; ret = bios_load_linear("roms/machines/acerv30/V30R01N9.BIN", - 0x000e0000, 131072, 0); + 0x000e0000, 131072, 0); if (bios_only || !ret) - return ret; + return ret; machine_at_common_init(model); pci_init(PCI_CONFIG_TYPE_1); pci_register_slot(0x00, PCI_CARD_NORTHBRIDGE, 0, 0, 0, 0); pci_register_slot(0x07, PCI_CARD_SOUTHBRIDGE, 0, 0, 0, 0); - pci_register_slot(0x12, PCI_CARD_NORMAL, 1, 2, 3, 4); - pci_register_slot(0x11, PCI_CARD_NORMAL, 2, 3, 4, 1); - pci_register_slot(0x14, PCI_CARD_NORMAL, 3, 4, 1, 2); - pci_register_slot(0x13, PCI_CARD_NORMAL, 4, 1, 2, 3); + pci_register_slot(0x12, PCI_CARD_NORMAL, 1, 2, 3, 4); + pci_register_slot(0x11, PCI_CARD_NORMAL, 2, 3, 4, 1); + pci_register_slot(0x14, PCI_CARD_NORMAL, 3, 4, 1, 2); + pci_register_slot(0x13, PCI_CARD_NORMAL, 4, 1, 2, 3); device_add(&i430fx_device); device_add(&piix_device); device_add(&keyboard_ps2_acer_pci_device); @@ -132,27 +128,26 @@ machine_at_acerv30_init(const machine_t *model) return ret; } - int machine_at_apollo_init(const machine_t *model) { int ret; ret = bios_load_linear("roms/machines/apollo/S728P.ROM", - 0x000e0000, 131072, 0); + 0x000e0000, 131072, 0); if (bios_only || !ret) - return ret; + return ret; machine_at_common_init_ex(model, 2); device_add(&ami_1995_nvr_device); pci_init(PCI_CONFIG_TYPE_1); pci_register_slot(0x00, PCI_CARD_NORTHBRIDGE, 0, 0, 0, 0); - pci_register_slot(0x08, PCI_CARD_NORMAL, 1, 2, 3, 4); - pci_register_slot(0x09, PCI_CARD_NORMAL, 2, 3, 4, 1); - pci_register_slot(0x0A, PCI_CARD_NORMAL, 3, 4, 1, 2); - pci_register_slot(0x0B, PCI_CARD_NORMAL, 4, 1, 2, 3); + pci_register_slot(0x08, PCI_CARD_NORMAL, 1, 2, 3, 4); + pci_register_slot(0x09, PCI_CARD_NORMAL, 2, 3, 4, 1); + pci_register_slot(0x0A, PCI_CARD_NORMAL, 3, 4, 1, 2); + pci_register_slot(0x0B, PCI_CARD_NORMAL, 4, 1, 2, 3); pci_register_slot(0x07, PCI_CARD_SOUTHBRIDGE, 0, 0, 0, 0); device_add(&keyboard_ps2_ami_pci_device); device_add(&i430fx_device); @@ -163,55 +158,59 @@ machine_at_apollo_init(const machine_t *model) return ret; } - -int -machine_at_exp8551_init(const machine_t *model) +static void +machine_at_zappa_gpio_init(void) { - int ret; + uint32_t gpio = 0xffffe6ff; - ret = bios_load_linear("roms/machines/exp8551/AMI20.BIO", - 0x000e0000, 131072, 0); + /* Register 0x0079: */ + /* Bit 7: 0 = Clear password, 1 = Keep password. */ + /* Bit 6: 0 = NVRAM cleared by jumper, 1 = NVRAM normal. */ + /* Bit 5: 0 = CMOS Setup disabled, 1 = CMOS Setup enabled. */ + /* Bit 4: External CPU clock (Switch 8). */ + /* Bit 3: External CPU clock (Switch 7). */ + /* 50 MHz: Switch 7 = Off, Switch 8 = Off. */ + /* 60 MHz: Switch 7 = On, Switch 8 = Off. */ + /* 66 MHz: Switch 7 = Off, Switch 8 = On. */ + /* Bit 2: No Connect. */ + /* Bit 1: No Connect. */ + /* Bit 0: 2x multiplier, 1 = 1.5x multiplier (Switch 6). */ + /* NOTE: A bit is read as 1 if switch is off, and as 0 if switch is on. */ + if (cpu_busspeed <= 50000000) + gpio |= 0xffff00ff; + else if ((cpu_busspeed > 50000000) && (cpu_busspeed <= 60000000)) + gpio |= 0xffff08ff; + else if (cpu_busspeed > 60000000) + gpio |= 0xffff10ff; - if (bios_only || !ret) - return ret; + if (cpu_dmulti <= 1.5) + gpio |= 0xffff01ff; + else + gpio |= 0xffff00ff; - machine_at_common_init(model); - - pci_init(PCI_CONFIG_TYPE_1); - pci_register_slot(0x00, PCI_CARD_NORTHBRIDGE, 0, 0, 0, 0); - pci_register_slot(0x13, PCI_CARD_NORMAL, 2, 3, 4, 1); - pci_register_slot(0x14, PCI_CARD_NORMAL, 1, 2, 3, 4); - pci_register_slot(0x12, PCI_CARD_NORMAL, 3, 4, 1, 2); - pci_register_slot(0x11, PCI_CARD_NORMAL, 4, 1, 2, 3); - pci_register_slot(0x07, PCI_CARD_SOUTHBRIDGE, 0, 0, 0, 0); - device_add(&keyboard_ps2_ami_pci_device); - device_add(&i430fx_device); - device_add(&piix_device); - device_add(&w83787f_device); - device_add(&sst_flash_29ee010_device); - - return ret; + machine_set_gpio_default(gpio); } - int machine_at_zappa_init(const machine_t *model) { int ret; ret = bios_load_linear_combined("roms/machines/zappa/1006bs0_.bio", - "roms/machines/zappa/1006bs0_.bi1", 0x20000, 128); + "roms/machines/zappa/1006bs0_.bi1", + 0x20000, 128); if (bios_only || !ret) - return ret; + return ret; - machine_at_common_init(model); + machine_at_common_init_ex(model, 2); + machine_at_zappa_gpio_init(); pci_init(PCI_CONFIG_TYPE_1); pci_register_slot(0x00, PCI_CARD_NORTHBRIDGE, 0, 0, 0, 0); - pci_register_slot(0x0D, PCI_CARD_NORMAL, 1, 2, 3, 4); - pci_register_slot(0x0E, PCI_CARD_NORMAL, 3, 4, 1, 2); - pci_register_slot(0x0F, PCI_CARD_NORMAL, 2, 3, 4, 1); + pci_register_slot(0x0D, PCI_CARD_NORMAL, 1, 2, 3, 4); + pci_register_slot(0x0E, PCI_CARD_NORMAL, 3, 4, 1, 2); + pci_register_slot(0x0F, PCI_CARD_NORMAL, 2, 3, 4, 1); pci_register_slot(0x07, PCI_CARD_SOUTHBRIDGE, 0, 0, 0, 0); device_add(&keyboard_ps2_intel_ami_pci_device); device_add(&i430fx_device); @@ -222,26 +221,25 @@ machine_at_zappa_init(const machine_t *model) return ret; } - int machine_at_powermatev_init(const machine_t *model) { int ret; ret = bios_load_linear("roms/machines/powermatev/BIOS.ROM", - 0x000e0000, 131072, 0); + 0x000e0000, 131072, 0); if (bios_only || !ret) - return ret; + return ret; machine_at_common_init(model); pci_init(PCI_CONFIG_TYPE_1); pci_register_slot(0x00, PCI_CARD_NORTHBRIDGE, 0, 0, 0, 0); pci_register_slot(0x07, PCI_CARD_SOUTHBRIDGE, 0, 0, 0, 0); - pci_register_slot(0x08, PCI_CARD_NORMAL, 0, 0, 0, 0); - pci_register_slot(0x11, PCI_CARD_NORMAL, 1, 2, 3, 4); - pci_register_slot(0x13, PCI_CARD_NORMAL, 2, 3, 4, 1); + pci_register_slot(0x08, PCI_CARD_NORMAL, 0, 0, 0, 0); + pci_register_slot(0x11, PCI_CARD_NORMAL, 1, 2, 3, 4); + pci_register_slot(0x13, PCI_CARD_NORMAL, 2, 3, 4, 1); device_add(&keyboard_ps2_ami_pci_device); device_add(&i430fx_device); device_add(&piix_device); @@ -251,58 +249,27 @@ machine_at_powermatev_init(const machine_t *model) return ret; } - -int -machine_at_mb500n_init(const machine_t *model) -{ - int ret; - - ret = bios_load_linear("roms/machines/mb500n/031396s.bin", - 0x000e0000, 131072, 0); - - if (bios_only || !ret) - return ret; - - machine_at_common_init(model); - - pci_init(PCI_CONFIG_TYPE_1); - pci_register_slot(0x00, PCI_CARD_NORTHBRIDGE, 0, 0, 0, 0); - pci_register_slot(0x14, PCI_CARD_NORMAL, 1, 2, 3, 4); - pci_register_slot(0x13, PCI_CARD_NORMAL, 2, 3, 4, 1); - pci_register_slot(0x12, PCI_CARD_NORMAL, 3, 4, 1, 2); - pci_register_slot(0x11, PCI_CARD_NORMAL, 4, 1, 2, 3); - pci_register_slot(0x07, PCI_CARD_SOUTHBRIDGE, 0, 0, 0, 0); - device_add(&keyboard_ps2_pci_device); - device_add(&i430fx_device); - device_add(&piix_device); - device_add(&fdc37c665_device); - device_add(&intel_flash_bxt_device); - - return ret; -} - - int machine_at_hawk_init(const machine_t *model) { int ret; ret = bios_load_linear("roms/machines/hawk/HAWK.ROM", - 0x000e0000, 131072, 0); + 0x000e0000, 131072, 0); if (bios_only || !ret) - return ret; + return ret; machine_at_common_init_ex(model, 2); device_add(&ami_1994_nvr_device); pci_init(PCI_CONFIG_TYPE_1); pci_register_slot(0x00, PCI_CARD_NORTHBRIDGE, 0, 0, 0, 0); - pci_register_slot(0x14, PCI_CARD_NORMAL, 1, 2, 3, 4); - pci_register_slot(0x13, PCI_CARD_NORMAL, 2, 3, 4, 1); - pci_register_slot(0x12, PCI_CARD_NORMAL, 3, 4, 1, 2); + pci_register_slot(0x14, PCI_CARD_NORMAL, 1, 2, 3, 4); + pci_register_slot(0x13, PCI_CARD_NORMAL, 2, 3, 4, 1); + pci_register_slot(0x12, PCI_CARD_NORMAL, 3, 4, 1, 2); pci_register_slot(0x07, PCI_CARD_SOUTHBRIDGE, 0, 0, 0, 0); - device_add(&keyboard_ps2_ami_pci_device); + device_add(&keyboard_ps2_tg_ami_pci_device); device_add(&i430fx_device); device_add(&piix_device); device_add(&fdc37c665_device); @@ -311,86 +278,84 @@ machine_at_hawk_init(const machine_t *model) return ret; } - int machine_at_pat54pv_init(const machine_t *model) { int ret; ret = bios_load_linear("roms/machines/pat54pv/PAT54PV.bin", - 0x000f0000, 65536, 0); + 0x000f0000, 65536, 0); if (bios_only || !ret) - return ret; + return ret; machine_at_common_init(model); device_add(&opti5x7_device); device_add(&keyboard_ps2_intel_ami_pci_device); - + if (fdc_type == FDC_INTERNAL) - device_add(&fdc_at_device); + device_add(&fdc_at_device); return ret; } - int machine_at_hot543_init(const machine_t *model) { int ret; ret = bios_load_linear("roms/machines/hot543/543_R21.BIN", - 0x000e0000, 131072, 0); + 0x000e0000, 131072, 0); if (bios_only || !ret) - return ret; + return ret; machine_at_common_init(model); + pci_init(PCI_CONFIG_TYPE_1); pci_register_slot(0x10, PCI_CARD_NORTHBRIDGE, 0, 0, 0, 0); - pci_register_slot(0x11, PCI_CARD_NORMAL, 1, 2, 3, 4); - pci_register_slot(0x12, PCI_CARD_NORMAL, 2, 3, 4, 1); - pci_register_slot(0x13, PCI_CARD_NORMAL, 3, 4, 1, 2); - device_add(&opti5x7_device); + pci_register_slot(0x11, PCI_CARD_NORMAL, 1, 2, 3, 4); + pci_register_slot(0x12, PCI_CARD_NORMAL, 2, 3, 4, 1); + pci_register_slot(0x13, PCI_CARD_NORMAL, 3, 4, 1, 2); + + device_add(&opti5x7_pci_device); device_add(&opti822_device); device_add(&sst_flash_29ee010_device); device_add(&keyboard_at_device); if (fdc_type == FDC_INTERNAL) - device_add(&fdc_at_device); + device_add(&fdc_at_device); return ret; } - int machine_at_p54sp4_init(const machine_t *model) { int ret; ret = bios_load_linear("roms/machines/p54sp4/SI5I0204.AWD", - 0x000e0000, 131072, 0); + 0x000e0000, 131072, 0); if (bios_only || !ret) - return ret; + return ret; machine_at_sp4_common_init(model); return ret; } - int machine_at_sq588_init(const machine_t *model) { int ret; ret = bios_load_linear("roms/machines/sq588/sq588b03.rom", - 0x000e0000, 131072, 0); + 0x000e0000, 131072, 0); if (bios_only || !ret) - return ret; + return ret; machine_at_common_init(model); @@ -398,11 +363,11 @@ machine_at_sq588_init(const machine_t *model) pci_register_slot(0x00, PCI_CARD_NORTHBRIDGE, 0, 0, 0, 0); pci_register_slot(0x01, PCI_CARD_SOUTHBRIDGE, 0, 0, 0, 0); /* Correct: 0D (01), 0F (02), 11 (03), 13 (04) */ - pci_register_slot(0x02, PCI_CARD_IDE, 1, 2, 3, 4); - pci_register_slot(0x0D, PCI_CARD_NORMAL, 1, 2, 3, 4); - pci_register_slot(0x0F, PCI_CARD_NORMAL, 2, 3, 4, 1); - pci_register_slot(0x11, PCI_CARD_NORMAL, 3, 4, 1, 2); - pci_register_slot(0x13, PCI_CARD_NORMAL, 4, 1, 2, 3); + pci_register_slot(0x02, PCI_CARD_IDE, 1, 2, 3, 4); + pci_register_slot(0x0D, PCI_CARD_NORMAL, 1, 2, 3, 4); + pci_register_slot(0x0F, PCI_CARD_NORMAL, 2, 3, 4, 1); + pci_register_slot(0x11, PCI_CARD_NORMAL, 3, 4, 1, 2); + pci_register_slot(0x13, PCI_CARD_NORMAL, 4, 1, 2, 3); device_add(&sis_85c50x_device); device_add(&ide_cmd640_pci_single_channel_device); device_add(&keyboard_ps2_ami_pci_device); @@ -410,4 +375,33 @@ machine_at_sq588_init(const machine_t *model) device_add(&sst_flash_29ee010_device); return ret; -} \ No newline at end of file +} + +int +machine_at_p54sps_init(const machine_t *model) +{ + int ret; + + ret = bios_load_linear("roms/machines/p54sps/35s106.bin", + 0x000e0000, 131072, 0); + + if (bios_only || !ret) + return ret; + + machine_at_common_init(model); + + pci_init(PCI_CONFIG_TYPE_1); + pci_register_slot(0x00, PCI_CARD_NORTHBRIDGE, 0, 0, 0, 0); + pci_register_slot(0x01, PCI_CARD_SOUTHBRIDGE, 0, 0, 0, 0); + pci_register_slot(0x06, PCI_CARD_NORMAL, 1, 2, 3, 4); + pci_register_slot(0x07, PCI_CARD_NORMAL, 2, 3, 4, 1); + pci_register_slot(0x08, PCI_CARD_NORMAL, 3, 4, 1, 2); + pci_register_slot(0x09, PCI_CARD_NORMAL, 4, 1, 2, 3); + device_add(&sis_85c50x_device); + device_add(&ide_pci_2ch_device); + device_add(&keyboard_at_ami_device); + device_add(&w83787f_device); + device_add(&sst_flash_29ee010_device); + + return ret; +} diff --git a/src/machine/m_at_socket7.c b/src/machine/m_at_socket7.c index 940cb82ba..f600710af 100644 --- a/src/machine/m_at_socket7.c +++ b/src/machine/m_at_socket7.c @@ -1,21 +1,18 @@ /* - * 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. + * 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. + * This file is part of the 86Box distribution. * - * Implementation of Socket 7 (Dual Voltage) machines. + * Implementation of Socket 7 (Dual Voltage) machines. * * * - * Authors: Sarah Walker, - * Miran Grca, - * Melissa Goad, + * Authors: Miran Grca, * - * Copyright 2010-2020 Sarah Walker. - * Copyright 2016-2020 Miran Grca. + * Copyright 2016-2020 Miran Grca. * */ #include @@ -35,6 +32,7 @@ #include <86box/keyboard.h> #include <86box/flash.h> #include <86box/sio.h> +#include <86box/sound.h> #include <86box/hwm.h> #include <86box/video.h> #include <86box/spd.h> @@ -46,19 +44,22 @@ #include <86box/nvr.h> #include <86box/scsi_ncr53c8xx.h> - int machine_at_acerv35n_init(const machine_t *model) { int ret; ret = bios_load_linear("roms/machines/acerv35n/v35nd1s1.bin", - 0x000e0000, 131072, 0); + 0x000e0000, 131072, 0); if (bios_only || !ret) - return ret; + return ret; - machine_at_common_init(model); + machine_at_common_init_ex(model, 2); + /* Yes, it's called amstrad_mega_pc_nvr_device, but it's basically the + standard AT NVR, just initialized to 0x00's (perhaps that should be the + default behavior?). */ + device_add(&amstrad_megapc_nvr_device); pci_init(PCI_CONFIG_TYPE_1); pci_register_slot(0x00, PCI_CARD_NORTHBRIDGE, 0, 0, 0, 0); @@ -78,17 +79,16 @@ machine_at_acerv35n_init(const machine_t *model) return ret; } - int machine_at_ap5vm_init(const machine_t *model) { int ret; ret = bios_load_linear("roms/machines/ap5vm/AP5V270.ROM", - 0x000e0000, 131072, 0); + 0x000e0000, 131072, 0); if (bios_only || !ret) - return ret; + return ret; machine_at_common_init(model); @@ -97,11 +97,11 @@ machine_at_ap5vm_init(const machine_t *model) /* It seems there were plans for an on-board NCR 53C810 according to some clues left in the manual, but were latter scrapped. The BIOS still support that PCI device, though, so why not. */ - pci_register_slot(0x06, PCI_CARD_SCSI, 1, 2, 3, 4); - pci_register_slot(0x09, PCI_CARD_NORMAL, 1, 2, 3, 4); - pci_register_slot(0x0A, PCI_CARD_NORMAL, 2, 3, 4, 1); - pci_register_slot(0x0B, PCI_CARD_NORMAL, 3, 4, 1, 2); - pci_register_slot(0x0C, PCI_CARD_NORMAL, 4, 1, 2, 3); + pci_register_slot(0x06, PCI_CARD_SCSI, 1, 2, 3, 4); + pci_register_slot(0x09, PCI_CARD_NORMAL, 1, 2, 3, 4); + pci_register_slot(0x0A, PCI_CARD_NORMAL, 2, 3, 4, 1); + pci_register_slot(0x0B, PCI_CARD_NORMAL, 3, 4, 1, 2); + pci_register_slot(0x0C, PCI_CARD_NORMAL, 4, 1, 2, 3); pci_register_slot(0x07, PCI_CARD_SOUTHBRIDGE, 0, 0, 0, 0); device_add(&i430vx_device); device_add(&piix3_device); @@ -113,26 +113,25 @@ machine_at_ap5vm_init(const machine_t *model) return ret; } - int machine_at_p55t2p4_init(const machine_t *model) { int ret; ret = bios_load_linear("roms/machines/p55t2p4/0207_j2.bin", - 0x000e0000, 131072, 0); + 0x000e0000, 131072, 0); if (bios_only || !ret) - return ret; + return ret; machine_at_common_init(model); pci_init(PCI_CONFIG_TYPE_1); pci_register_slot(0x00, PCI_CARD_NORTHBRIDGE, 0, 0, 0, 0); - pci_register_slot(0x0C, PCI_CARD_NORMAL, 1, 2, 3, 4); - pci_register_slot(0x0B, PCI_CARD_NORMAL, 2, 3, 4, 1); - pci_register_slot(0x0A, PCI_CARD_NORMAL, 3, 4, 1, 2); - pci_register_slot(0x09, PCI_CARD_NORMAL, 4, 1, 2, 3); + pci_register_slot(0x0C, PCI_CARD_NORMAL, 1, 2, 3, 4); + pci_register_slot(0x0B, PCI_CARD_NORMAL, 2, 3, 4, 1); + pci_register_slot(0x0A, PCI_CARD_NORMAL, 3, 4, 1, 2); + pci_register_slot(0x09, PCI_CARD_NORMAL, 4, 1, 2, 3); pci_register_slot(0x07, PCI_CARD_SOUTHBRIDGE, 0, 0, 0, 0); device_add(&i430hx_device); device_add(&piix3_device); @@ -143,26 +142,25 @@ machine_at_p55t2p4_init(const machine_t *model) return ret; } - int machine_at_m7shi_init(const machine_t *model) { int ret; ret = bios_load_linear("roms/machines/m7shi/m7shi2n.rom", - 0x000c0000, 262144, 0); + 0x000c0000, 262144, 0); if (bios_only || !ret) - return ret; + return ret; machine_at_common_init(model); pci_init(PCI_CONFIG_TYPE_1); pci_register_slot(0x07, PCI_CARD_SOUTHBRIDGE, 0, 0, 0, 0); - pci_register_slot(0x12, PCI_CARD_NORMAL, 4, 1, 2, 3); - pci_register_slot(0x11, PCI_CARD_NORMAL, 3, 4, 1, 2); - pci_register_slot(0x10, PCI_CARD_NORMAL, 2, 3, 4, 1); - pci_register_slot(0x0F, PCI_CARD_NORMAL, 1, 2, 3, 4); + pci_register_slot(0x12, PCI_CARD_NORMAL, 4, 1, 2, 3); + pci_register_slot(0x11, PCI_CARD_NORMAL, 3, 4, 1, 2); + pci_register_slot(0x10, PCI_CARD_NORMAL, 2, 3, 4, 1); + pci_register_slot(0x0F, PCI_CARD_NORMAL, 1, 2, 3, 4); pci_register_slot(0x00, PCI_CARD_NORTHBRIDGE, 0, 0, 0, 0); device_add(&i430hx_device); device_add(&piix3_device); @@ -173,6 +171,41 @@ machine_at_m7shi_init(const machine_t *model) return ret; } +/* The Sony VAIO is an AG430HX, I'm assuming it has the same configuration bits + as the TC430HX, hence the #define. */ +#define machine_at_ag430hx_gpio_init machine_at_tc430hx_gpio_init + +/* The PB680 is a NV430VX, I'm assuming it has the same configuration bits as + the TC430HX, hence the #define. */ +#define machine_at_nv430vx_gpio_init machine_at_tc430hx_gpio_init + +static void +machine_at_tc430hx_gpio_init(void) +{ + uint32_t gpio = 0xffffe1ff; + + /* Register 0x0079: */ + /* Bit 7: 0 = Clear password, 1 = Keep password. */ + /* Bit 6: 0 = NVRAM cleared by jumper, 1 = NVRAM normal. */ + /* Bit 5: 0 = CMOS Setup disabled, 1 = CMOS Setup enabled. */ + /* Bit 4: External CPU clock (Switch 8). */ + /* Bit 3: External CPU clock (Switch 7). */ + /* 50 MHz: Switch 7 = Off, Switch 8 = Off. */ + /* 60 MHz: Switch 7 = On, Switch 8 = Off. */ + /* 66 MHz: Switch 7 = Off, Switch 8 = On. */ + /* Bit 2: 0 = On-board audio absent, 1 = On-board audio present. */ + /* Bit 1: 0 = Soft-off capable power supply present, 1 = Soft-off capable power supply absent. */ + /* Bit 0: 0 = Reserved. */ + /* NOTE: A bit is read as 1 if switch is off, and as 0 if switch is on. */ + if (cpu_busspeed <= 50000000) + gpio |= 0xffff10ff; + else if ((cpu_busspeed > 50000000) && (cpu_busspeed <= 60000000)) + gpio |= 0xffff18ff; + else if (cpu_busspeed > 60000000) + gpio |= 0xffff00ff; + + machine_set_gpio_default(gpio); +} int machine_at_tc430hx_init(const machine_t *model) @@ -180,16 +213,56 @@ machine_at_tc430hx_init(const machine_t *model) int ret; ret = bios_load_linear_combined2("roms/machines/tc430hx/1007DH0_.BIO", - "roms/machines/tc430hx/1007DH0_.BI1", - "roms/machines/tc430hx/1007DH0_.BI2", - "roms/machines/tc430hx/1007DH0_.BI3", - "roms/machines/tc430hx/1007DH0_.RCV", - 0x3a000, 128); + "roms/machines/tc430hx/1007DH0_.BI1", + "roms/machines/tc430hx/1007DH0_.BI2", + "roms/machines/tc430hx/1007DH0_.BI3", + "roms/machines/tc430hx/1007DH0_.RCV", + 0x3a000, 128); if (bios_only || !ret) - return ret; + return ret; - machine_at_common_init(model); + machine_at_common_init_ex(model, 2); + machine_at_tc430hx_gpio_init(); + + pci_init(PCI_CONFIG_TYPE_1); + pci_register_slot(0x00, PCI_CARD_NORTHBRIDGE, 0, 0, 0, 0); + pci_register_slot(0x08, PCI_CARD_VIDEO, 4, 0, 0, 0); + pci_register_slot(0x0D, PCI_CARD_NORMAL, 1, 2, 3, 4); + pci_register_slot(0x0E, PCI_CARD_NORMAL, 2, 3, 4, 1); + pci_register_slot(0x0F, PCI_CARD_NORMAL, 3, 4, 1, 2); + pci_register_slot(0x10, PCI_CARD_NORMAL, 4, 1, 2, 3); + pci_register_slot(0x07, PCI_CARD_SOUTHBRIDGE, 0, 0, 0, 0); + + if (gfxcard[0] == VID_INTERNAL) + device_add(machine_get_vid_device(machine)); + + device_add(&i430hx_device); + device_add(&piix3_device); + device_add(&keyboard_ps2_ami_pci_device); + device_add(&pc87306_device); + device_add(&intel_flash_bxt_ami_device); + + return ret; +} + +int +machine_at_infinia7200_init(const machine_t *model) +{ + int ret; + + ret = bios_load_linear_combined2("roms/machines/infinia7200/1008DH08.BIO", + "roms/machines/infinia7200/1008DH08.BI1", + "roms/machines/infinia7200/1008DH08.BI2", + "roms/machines/infinia7200/1008DH08.BI3", + "roms/machines/infinia7200/1008DH08.RCV", + 0x3a000, 128); + + if (bios_only || !ret) + return ret; + + machine_at_common_init_ex(model, 2); + machine_at_tc430hx_gpio_init(); pci_init(PCI_CONFIG_TYPE_1); pci_register_slot(0x00, PCI_CARD_NORTHBRIDGE, 0, 0, 0, 0); @@ -199,6 +272,10 @@ machine_at_tc430hx_init(const machine_t *model) pci_register_slot(0x0F, PCI_CARD_NORMAL, 3, 4, 1, 2); pci_register_slot(0x10, PCI_CARD_NORMAL, 4, 1, 2, 3); pci_register_slot(0x07, PCI_CARD_SOUTHBRIDGE, 0, 0, 0, 0); + + if (gfxcard[0] == VID_INTERNAL) + device_add(machine_get_vid_device(machine)); + device_add(&i430hx_device); device_add(&piix3_device); device_add(&keyboard_ps2_ami_pci_device); @@ -208,67 +285,128 @@ machine_at_tc430hx_init(const machine_t *model) return ret; } +static void +machine_at_cu430hx_gpio_init(void) +{ + uint32_t gpio = 0xffffe1ff; + + /* Register 0x0079: */ + /* Bit 7: 0 = Clear password, 1 = Keep password. */ + /* Bit 6: 0 = NVRAM cleared by jumper, 1 = NVRAM normal. */ + /* Bit 5: 0 = CMOS Setup disabled, 1 = CMOS Setup enabled. */ + /* Bit 4: External CPU clock (Switch 8). */ + /* Bit 3: External CPU clock (Switch 7). */ + /* 50 MHz: Switch 7 = Off, Switch 8 = Off. */ + /* 60 MHz: Switch 7 = On, Switch 8 = Off. */ + /* 66 MHz: Switch 7 = Off, Switch 8 = On. */ + /* Bit 2: 0 = On-board audio absent, 1 = On-board audio present. */ + /* Bit 1: 0 = Soft-off capable power supply present, 1 = Soft-off capable power supply absent. */ + /* Bit 0: 0 = Reserved. */ + /* NOTE: A bit is read as 1 if switch is off, and as 0 if switch is on. */ + if (cpu_busspeed <= 50000000) + gpio |= 0xffff10ff; + else if ((cpu_busspeed > 50000000) && (cpu_busspeed <= 60000000)) + gpio |= 0xffff18ff; + else if (cpu_busspeed > 60000000) + gpio |= 0xffff00ff; + + if ((sound_card_current[0] == SOUND_INTERNAL) && machine_get_snd_device(machine)->available()) + gpio |= 0xffff04ff; + + machine_set_gpio_default(gpio); +} + +static void +machine_at_cu430hx_common_init(const machine_t *model) +{ + machine_at_common_init_ex(model, 2); + machine_at_cu430hx_gpio_init(); + + pci_init(PCI_CONFIG_TYPE_1); + pci_register_slot(0x00, PCI_CARD_NORTHBRIDGE, 0, 0, 0, 0); + pci_register_slot(0x08, PCI_CARD_VIDEO, 4, 0, 0, 0); // ATI VGA Graphics + pci_register_slot(0x0C, PCI_CARD_NETWORK, 4, 0, 0, 0); // Intel 82557 Ethernet Network + pci_register_slot(0x11, PCI_CARD_NORMAL, 1, 2, 3, 4); + pci_register_slot(0x13, PCI_CARD_NORMAL, 2, 3, 4, 1); + pci_register_slot(0x0B, PCI_CARD_NORMAL, 3, 4, 1, 2); + pci_register_slot(0x07, PCI_CARD_SOUTHBRIDGE, 0, 0, 0, 0); + pci_register_slot(0x0A, PCI_CARD_NORMAL, 3, 0, 0, 0); // riser + + if ((sound_card_current[0] == SOUND_INTERNAL) && machine_get_snd_device(machine)->available()) + machine_snd = device_add(machine_get_snd_device(machine)); + + device_add(&i430hx_device); + device_add(&piix3_device); + device_add(&keyboard_ps2_ami_pci_device); + device_add(&pc87306_device); + device_add(&intel_flash_bxt_ami_device); +} + +int +machine_at_cu430hx_init(const machine_t *model) +{ + int ret; + + ret = bios_load_linear_combined2("roms/machines/cu430hx/1006DK0_.BIO", + "roms/machines/cu430hx/1006DK0_.BI1", + "roms/machines/cu430hx/1006DK0_.BI2", + "roms/machines/cu430hx/1006DK0_.BI3", + "roms/machines/cu430hx/1006DK0_.RCV", + 0x3a000, 128); + + if (bios_only || !ret) + return ret; + + machine_at_cu430hx_common_init(model); + + return ret; +} -/* Information about that machine on machine.h */ int machine_at_equium5200_init(const machine_t *model) { int ret; ret = bios_load_linear_combined2("roms/machines/equium5200/1003DK08.BIO", - "roms/machines/equium5200/1003DK08.BI1", - "roms/machines/equium5200/1003DK08.BI2", - "roms/machines/equium5200/1003DK08.BI3", - "roms/machines/equium5200/1003DK08.RCV", - 0x3a000, 128); + "roms/machines/equium5200/1003DK08.BI1", + "roms/machines/equium5200/1003DK08.BI2", + "roms/machines/equium5200/1003DK08.BI3", + "roms/machines/equium5200/1003DK08.RCV", + 0x3a000, 128); if (bios_only || !ret) - return ret; + return ret; - machine_at_common_init(model); - - pci_init(PCI_CONFIG_TYPE_1); - pci_register_slot(0x00, PCI_CARD_NORTHBRIDGE, 0, 0, 0, 0); - pci_register_slot(0x08, PCI_CARD_VIDEO, 4, 0, 0, 0); - pci_register_slot(0x11, PCI_CARD_NORMAL, 1, 2, 3, 4); - pci_register_slot(0x13, PCI_CARD_NORMAL, 2, 3, 4, 1); - pci_register_slot(0x0B, PCI_CARD_NORMAL, 3, 4, 1, 2); - pci_register_slot(0x07, PCI_CARD_SOUTHBRIDGE, 0, 0, 0, 0); - pci_register_slot(0x0A, PCI_CARD_NORMAL, 3, 0, 0, 0); // riser - device_add(&i430hx_device); - device_add(&piix3_device); - device_add(&keyboard_ps2_ami_pci_device); - device_add(&pc87306_device); - device_add(&intel_flash_bxt_ami_device); + machine_at_cu430hx_common_init(model); return ret; } - int machine_at_pcv90_init(const machine_t *model) { int ret; ret = bios_load_linear_combined2("roms/machines/pcv90/1010DD04.BIO", - "roms/machines/pcv90/1010DD04.BI1", - "roms/machines/pcv90/1010DD04.BI2", - "roms/machines/pcv90/1010DD04.BI3", - "roms/machines/pcv90/1010DD04.RCV", - 0x3a000, 128); + "roms/machines/pcv90/1010DD04.BI1", + "roms/machines/pcv90/1010DD04.BI2", + "roms/machines/pcv90/1010DD04.BI3", + "roms/machines/pcv90/1010DD04.RCV", + 0x3a000, 128); if (bios_only || !ret) - return ret; + return ret; - machine_at_common_init(model); + machine_at_common_init_ex(model, 2); + machine_at_ag430hx_gpio_init(); pci_init(PCI_CONFIG_TYPE_1); pci_register_slot(0x00, PCI_CARD_NORTHBRIDGE, 0, 0, 0, 0); - pci_register_slot(0x08, PCI_CARD_VIDEO, 4, 0, 0, 0); - pci_register_slot(0x0D, PCI_CARD_NORMAL, 1, 2, 3, 4); - pci_register_slot(0x0E, PCI_CARD_NORMAL, 2, 3, 4, 1); - pci_register_slot(0x0F, PCI_CARD_NORMAL, 3, 4, 1, 2); - pci_register_slot(0x10, PCI_CARD_NORMAL, 4, 1, 2, 3); + pci_register_slot(0x08, PCI_CARD_VIDEO, 4, 0, 0, 0); + pci_register_slot(0x0D, PCI_CARD_NORMAL, 1, 2, 3, 4); + pci_register_slot(0x0E, PCI_CARD_NORMAL, 2, 3, 4, 1); + pci_register_slot(0x0F, PCI_CARD_NORMAL, 3, 4, 1, 2); + pci_register_slot(0x10, PCI_CARD_NORMAL, 4, 1, 2, 3); pci_register_slot(0x07, PCI_CARD_SOUTHBRIDGE, 0, 0, 0, 0); device_add(&i430hx_device); device_add(&piix3_device); @@ -279,72 +417,69 @@ machine_at_pcv90_init(const machine_t *model) return ret; } - int machine_at_p65up5_cp55t2d_init(const machine_t *model) { int ret; ret = bios_load_linear("roms/machines/p65up5/TD5I0201.AWD", - 0x000e0000, 131072, 0); + 0x000e0000, 131072, 0); if (bios_only || !ret) - return ret; + return ret; machine_at_p65up5_common_init(model, &i430hx_device); return ret; } - int machine_at_p55tvp4_init(const machine_t *model) { int ret; ret = bios_load_linear("roms/machines/p55tvp4/0204_128.BIN", - 0x000e0000, 131072, 0); + 0x000e0000, 131072, 0); if (bios_only || !ret) - return ret; + return ret; machine_at_common_init(model); pci_init(PCI_CONFIG_TYPE_1); pci_register_slot(0x00, PCI_CARD_NORTHBRIDGE, 0, 0, 0, 0); - pci_register_slot(0x09, PCI_CARD_NORMAL, 4, 1, 2, 3); - pci_register_slot(0x0A, PCI_CARD_NORMAL, 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); + pci_register_slot(0x0A, PCI_CARD_NORMAL, 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(0x07, PCI_CARD_SOUTHBRIDGE, 0, 0, 0, 0); device_add(&i430vx_device); device_add(&piix3_device); - device_add(&keyboard_ps2_ami_pci_device); //It uses the AMIKEY KBC + device_add(&keyboard_ps2_ami_pci_device); // It uses the AMIKEY KBC device_add(&w83877f_device); device_add(&intel_flash_bxt_device); return ret; } - int machine_at_5ivg_init(const machine_t *model) { int ret; ret = bios_load_linear("roms/machines/5ivg/5IVG.BIN", - 0x000e0000, 131072, 0); + 0x000e0000, 131072, 0); if (bios_only || !ret) - return ret; + return ret; machine_at_common_init(model); pci_init(PCI_CONFIG_TYPE_1); pci_register_slot(0x00, PCI_CARD_NORTHBRIDGE, 0, 0, 0, 0); - pci_register_slot(0x11, PCI_CARD_NORMAL, 2, 3, 4, 1); - pci_register_slot(0x12, PCI_CARD_NORMAL, 1, 2, 3, 4); - pci_register_slot(0x13, PCI_CARD_NORMAL, 3, 4, 1, 2); + pci_register_slot(0x11, PCI_CARD_NORMAL, 1, 2, 3, 4); + pci_register_slot(0x12, PCI_CARD_NORMAL, 2, 3, 4, 1); + pci_register_slot(0x13, PCI_CARD_NORMAL, 3, 4, 1, 2); pci_register_slot(0x07, PCI_CARD_SOUTHBRIDGE, 0, 0, 0, 0); device_add(&i430vx_device); device_add(&piix3_device); @@ -355,27 +490,26 @@ machine_at_5ivg_init(const machine_t *model) return ret; } - int machine_at_8500tvxa_init(const machine_t *model) { int ret; ret = bios_load_linear("roms/machines/8500tvxa/tvx0619b.rom", - 0x000e0000, 131072, 0); + 0x000e0000, 131072, 0); if (bios_only || !ret) - return ret; + return ret; machine_at_common_init(model); pci_init(PCI_CONFIG_TYPE_1); pci_register_slot(0x00, PCI_CARD_NORTHBRIDGE, 0, 0, 0, 0); pci_register_slot(0x07, PCI_CARD_SOUTHBRIDGE, 0, 0, 0, 0); - pci_register_slot(0x08, PCI_CARD_NORMAL, 1, 2, 3, 4); - pci_register_slot(0x09, PCI_CARD_NORMAL, 2, 3, 4, 1); - pci_register_slot(0x0A, PCI_CARD_NORMAL, 3, 4, 2, 1); - pci_register_slot(0x0B, PCI_CARD_NORMAL, 4, 3, 2, 1); + pci_register_slot(0x08, PCI_CARD_NORMAL, 1, 2, 3, 4); + pci_register_slot(0x09, PCI_CARD_NORMAL, 2, 3, 4, 1); + pci_register_slot(0x0A, PCI_CARD_NORMAL, 3, 4, 2, 1); + pci_register_slot(0x0B, PCI_CARD_NORMAL, 4, 3, 2, 1); device_add(&i430vx_device); device_add(&piix3_device); device_add(&keyboard_ps2_ami_pci_device); @@ -385,28 +519,27 @@ machine_at_8500tvxa_init(const machine_t *model) return ret; } - int machine_at_presario2240_init(const machine_t *model) { int ret; ret = bios_load_linear("roms/machines/presario2240/B0184008.ROM", - 0x000c0000, 262144, 0); + 0x000c0000, 262144, 0); if (bios_only || !ret) - return ret; + return ret; machine_at_common_init_ex(model, 2); pci_init(PCI_CONFIG_TYPE_1); pci_register_slot(0x00, PCI_CARD_NORTHBRIDGE, 0, 0, 0, 0); pci_register_slot(0x07, PCI_CARD_SOUTHBRIDGE, 1, 2, 3, 4); - pci_register_slot(0x14, PCI_CARD_VIDEO, 3, 0, 0, 0); - pci_register_slot(0x13, PCI_CARD_NORMAL, 1, 2, 3, 4); + pci_register_slot(0x14, PCI_CARD_VIDEO, 3, 0, 0, 0); + pci_register_slot(0x13, PCI_CARD_NORMAL, 1, 2, 3, 4); - if (gfxcard == VID_INTERNAL) - device_add(&s3_trio64v2_dx_onboard_pci_device); + if (gfxcard[0] == VID_INTERNAL) + device_add(&s3_trio64v2_dx_onboard_pci_device); device_add(&i430vx_device); device_add(&piix3_device); @@ -417,35 +550,27 @@ machine_at_presario2240_init(const machine_t *model) return ret; } - -const device_t * -at_presario2240_get_device(void) -{ - return &s3_trio64v2_dx_onboard_pci_device; -} - - int machine_at_presario4500_init(const machine_t *model) { int ret; ret = bios_load_linear("roms/machines/presario4500/B013300I.ROM", - 0x000c0000, 262144, 0); + 0x000c0000, 262144, 0); if (bios_only || !ret) - return ret; + return ret; machine_at_common_init_ex(model, 2); pci_init(PCI_CONFIG_TYPE_1); pci_register_slot(0x00, PCI_CARD_NORTHBRIDGE, 0, 0, 0, 0); pci_register_slot(0x07, PCI_CARD_SOUTHBRIDGE, 1, 2, 3, 4); - pci_register_slot(0x14, PCI_CARD_VIDEO, 3, 0, 0, 0); - pci_register_slot(0x13, PCI_CARD_NORMAL, 1, 2, 3, 4); + pci_register_slot(0x14, PCI_CARD_VIDEO, 3, 0, 0, 0); + pci_register_slot(0x13, PCI_CARD_NORMAL, 1, 2, 3, 4); - if (gfxcard == VID_INTERNAL) - device_add(&s3_trio64v2_dx_onboard_pci_device); + if (gfxcard[0] == VID_INTERNAL) + device_add(&s3_trio64v2_dx_onboard_pci_device); device_add(&i430vx_device); device_add(&piix3_device); @@ -456,26 +581,25 @@ machine_at_presario4500_init(const machine_t *model) return ret; } - int machine_at_p55va_init(const machine_t *model) { int ret; ret = bios_load_linear("roms/machines/p55va/va021297.bin", - 0x000e0000, 131072, 0); + 0x000e0000, 131072, 0); if (bios_only || !ret) - return ret; + return ret; machine_at_common_init(model); pci_init(PCI_CONFIG_TYPE_1); pci_register_slot(0x00, PCI_CARD_NORTHBRIDGE, 0, 0, 0, 0); - pci_register_slot(0x08, PCI_CARD_NORMAL, 1, 2, 3, 4); - pci_register_slot(0x09, PCI_CARD_NORMAL, 2, 3, 4, 1); - pci_register_slot(0x0A, PCI_CARD_NORMAL, 3, 4, 1, 2); - pci_register_slot(0x0B, PCI_CARD_NORMAL, 4, 1, 2, 3); + pci_register_slot(0x08, PCI_CARD_NORMAL, 1, 2, 3, 4); + pci_register_slot(0x09, PCI_CARD_NORMAL, 2, 3, 4, 1); + pci_register_slot(0x0A, PCI_CARD_NORMAL, 3, 4, 1, 2); + pci_register_slot(0x0B, PCI_CARD_NORMAL, 4, 1, 2, 3); pci_register_slot(0x07, PCI_CARD_SOUTHBRIDGE, 0, 0, 0, 0); device_add(&i430vx_device); device_add(&piix3_device); @@ -486,26 +610,25 @@ machine_at_p55va_init(const machine_t *model) return ret; } - int machine_at_brio80xx_init(const machine_t *model) { int ret; ret = bios_load_linear("roms/machines/brio80xx/Hf0705.rom", - 0x000c0000, 262144, 0); + 0x000c0000, 262144, 0); if (bios_only || !ret) - return ret; + return ret; machine_at_common_init(model); pci_init(PCI_CONFIG_TYPE_1); pci_register_slot(0x07, PCI_CARD_SOUTHBRIDGE, 0, 0, 0, 0); - pci_register_slot(0x14, PCI_CARD_VIDEO, 4, 0, 0, 0); - pci_register_slot(0x13, PCI_CARD_NORMAL, 1, 2, 3, 4); - pci_register_slot(0x12, PCI_CARD_NORMAL, 2, 3, 4, 1); - pci_register_slot(0x11, PCI_CARD_NORMAL, 3, 4, 1, 2); + pci_register_slot(0x14, PCI_CARD_VIDEO, 4, 0, 0, 0); + pci_register_slot(0x13, PCI_CARD_NORMAL, 1, 2, 3, 4); + pci_register_slot(0x12, PCI_CARD_NORMAL, 2, 3, 4, 1); + pci_register_slot(0x11, PCI_CARD_NORMAL, 3, 4, 1, 2); pci_register_slot(0x00, PCI_CARD_NORTHBRIDGE, 0, 0, 0, 0); device_add(&i430vx_device); device_add(&piix3_device); @@ -516,31 +639,35 @@ machine_at_brio80xx_init(const machine_t *model) return ret; } - int machine_at_pb680_init(const machine_t *model) { int ret; ret = bios_load_linear_combined2("roms/machines/pb680/1012DN0R.BIO", - "roms/machines/pb680/1012DN0R.BI1", - "roms/machines/pb680/1012DN0R.BI2", - "roms/machines/pb680/1012DN0R.BI3", - "roms/machines/pb680/1012DN0R.RCV", - 0x3a000, 128); + "roms/machines/pb680/1012DN0R.BI1", + "roms/machines/pb680/1012DN0R.BI2", + "roms/machines/pb680/1012DN0R.BI3", + "roms/machines/pb680/1012DN0R.RCV", + 0x3a000, 128); if (bios_only || !ret) - return ret; + return ret; - machine_at_common_init(model); + machine_at_common_init_ex(model, 2); + machine_at_nv430vx_gpio_init(); pci_init(PCI_CONFIG_TYPE_1); pci_register_slot(0x00, PCI_CARD_NORTHBRIDGE, 0, 0, 0, 0); - pci_register_slot(0x08, PCI_CARD_VIDEO, 4, 0, 0, 0); - pci_register_slot(0x11, PCI_CARD_NORMAL, 1, 2, 3, 4); - pci_register_slot(0x13, PCI_CARD_NORMAL, 2, 3, 4, 1); - pci_register_slot(0x0B, PCI_CARD_NORMAL, 3, 4, 1, 2); + pci_register_slot(0x08, PCI_CARD_VIDEO, 4, 0, 0, 0); + pci_register_slot(0x11, PCI_CARD_NORMAL, 1, 2, 3, 4); + pci_register_slot(0x13, PCI_CARD_NORMAL, 2, 3, 4, 1); + pci_register_slot(0x0B, PCI_CARD_NORMAL, 3, 4, 1, 2); pci_register_slot(0x07, PCI_CARD_SOUTHBRIDGE, 0, 0, 0, 0); + + if (gfxcard[0] == VID_INTERNAL) + device_add(machine_get_vid_device(machine)); + device_add(&i430vx_device); device_add(&piix3_device); device_add(&keyboard_ps2_ami_pci_device); @@ -550,6 +677,37 @@ machine_at_pb680_init(const machine_t *model) return ret; } +int +machine_at_pb810_init(const machine_t *model) +{ + int ret; + + ret = bios_load_linear("roms/machines/pb810/G400125I.BIN", + 0x000e0000, 131072, 0); + + if (bios_only || !ret) + return ret; + + machine_at_common_init(model); + + pci_init(PCI_CONFIG_TYPE_1); + pci_register_slot(0x00, PCI_CARD_NORTHBRIDGE, 0, 0, 0, 0); + pci_register_slot(0x13, PCI_CARD_NORMAL, 2, 1, 3, 4); + pci_register_slot(0x11, PCI_CARD_NORMAL, 1, 3, 2, 4); + pci_register_slot(0x0b, PCI_CARD_NORMAL, 1, 2, 3, 4); + pci_register_slot(0x07, PCI_CARD_SOUTHBRIDGE, 0, 0, 0, 0); + + if (sound_card_current[0] == SOUND_INTERNAL) + device_add(&cs4237b_device); + + device_add(&i430vx_device); + device_add(&piix3_device); + device_add(&keyboard_ps2_device); + device_add(&fdc37c935_device); + device_add(&intel_flash_bxt_device); + + return ret; +} int machine_at_mb520n_init(const machine_t *model) @@ -557,19 +715,19 @@ machine_at_mb520n_init(const machine_t *model) int ret; ret = bios_load_linear("roms/machines/mb520n/520n503s.rom", - 0x000e0000, 131072, 0); + 0x000e0000, 131072, 0); if (bios_only || !ret) - return ret; + return ret; machine_at_common_init(model); pci_init(PCI_CONFIG_TYPE_1); pci_register_slot(0x00, PCI_CARD_NORTHBRIDGE, 0, 0, 0, 0); - pci_register_slot(0x14, PCI_CARD_NORMAL, 1, 2, 3, 4); - pci_register_slot(0x13, PCI_CARD_NORMAL, 2, 3, 4, 1); - pci_register_slot(0x12, PCI_CARD_NORMAL, 3, 4, 1, 2); - pci_register_slot(0x11, PCI_CARD_NORMAL, 4, 1, 2, 3); + pci_register_slot(0x14, PCI_CARD_NORMAL, 1, 2, 3, 4); + pci_register_slot(0x13, PCI_CARD_NORMAL, 2, 3, 4, 1); + pci_register_slot(0x12, PCI_CARD_NORMAL, 3, 4, 1, 2); + pci_register_slot(0x11, PCI_CARD_NORMAL, 4, 1, 2, 3); pci_register_slot(0x07, PCI_CARD_SOUTHBRIDGE, 0, 0, 0, 0); device_add(&i430vx_device); device_add(&piix3_device); @@ -580,26 +738,25 @@ machine_at_mb520n_init(const machine_t *model) return ret; } - int machine_at_i430vx_init(const machine_t *model) { int ret; ret = bios_load_linear("roms/machines/430vx/55XWUQ0E.BIN", - 0x000e0000, 131072, 0); + 0x000e0000, 131072, 0); if (bios_only || !ret) - return ret; + return ret; machine_at_common_init(model); pci_init(PCI_CONFIG_TYPE_1); pci_register_slot(0x00, PCI_CARD_NORTHBRIDGE, 0, 0, 0, 0); - pci_register_slot(0x11, PCI_CARD_NORMAL, 2, 3, 4, 1); - pci_register_slot(0x12, PCI_CARD_NORMAL, 1, 2, 3, 4); - pci_register_slot(0x14, PCI_CARD_NORMAL, 3, 4, 1, 2); - pci_register_slot(0x13, PCI_CARD_NORMAL, 4, 1, 2, 3); + pci_register_slot(0x11, PCI_CARD_NORMAL, 2, 3, 4, 1); + pci_register_slot(0x12, PCI_CARD_NORMAL, 1, 2, 3, 4); + pci_register_slot(0x14, PCI_CARD_NORMAL, 3, 4, 1, 2); + pci_register_slot(0x13, PCI_CARD_NORMAL, 4, 1, 2, 3); pci_register_slot(0x07, PCI_CARD_SOUTHBRIDGE, 0, 0, 0, 0); device_add(&i430vx_device); device_add(&piix3_device); @@ -610,120 +767,117 @@ machine_at_i430vx_init(const machine_t *model) return ret; } - int machine_at_nupro592_init(const machine_t *model) { int ret; ret = bios_load_linear("roms/machines/nupro592/np590b10.bin", - 0x000c0000, 262144, 0); + 0x000c0000, 262144, 0); if (bios_only || !ret) - return ret; + return ret; machine_at_common_init_ex(model, 2); pci_init(PCI_CONFIG_TYPE_1); pci_register_slot(0x00, PCI_CARD_NORTHBRIDGE, 0, 0, 0, 0); - pci_register_slot(0x11, PCI_CARD_NORMAL, 1, 2, 3, 4); - pci_register_slot(0x12, PCI_CARD_NORMAL, 4, 1, 2, 3); - pci_register_slot(0x13, PCI_CARD_NORMAL, 3, 4, 1, 2); - pci_register_slot(0x14, PCI_CARD_NORMAL, 2, 3, 4, 1); - pci_register_slot(0x0B, PCI_CARD_NORMAL, 3, 4, 1, 2); /*Strongly suspect these are on-board slots*/ - pci_register_slot(0x0C, PCI_CARD_NORMAL, 4, 1, 2, 3); - pci_register_slot(0x07, PCI_CARD_SOUTHBRIDGE, 0, 0, 0, 4); /* PIIX4 */ + pci_register_slot(0x11, PCI_CARD_NORMAL, 1, 2, 3, 4); + pci_register_slot(0x12, PCI_CARD_NORMAL, 4, 1, 2, 3); + pci_register_slot(0x13, PCI_CARD_NORMAL, 3, 4, 1, 2); + pci_register_slot(0x14, PCI_CARD_NORMAL, 2, 3, 4, 1); + pci_register_slot(0x0B, PCI_CARD_NORMAL, 3, 4, 1, 2); /*Strongly suspect these are on-board slots*/ + pci_register_slot(0x0C, PCI_CARD_NORMAL, 4, 1, 2, 3); + pci_register_slot(0x07, PCI_CARD_SOUTHBRIDGE, 0, 0, 0, 4); /* PIIX4 */ device_add(&i430tx_device); device_add(&piix4_device); device_add(&keyboard_ps2_ami_pci_device); device_add(&w83977ef_device); device_add(&intel_flash_bxt_device); spd_register(SPD_TYPE_SDRAM, 0x3, 128); - device_add(&w83781d_device); /* fans: CPU1, unused, unused; temperatures: System, CPU1, unused */ + device_add(&w83781d_device); /* fans: CPU1, unused, unused; temperatures: System, CPU1, unused */ hwm_values.temperatures[2] = 0; /* unused */ - hwm_values.fans[1] = 0; /* unused */ - hwm_values.fans[2] = 0; /* unused */ + hwm_values.fans[1] = 0; /* unused */ + hwm_values.fans[2] = 0; /* unused */ /* -5V is not reported by the BIOS, but leave it set */ - + return ret; } - int machine_at_tx97_init(const machine_t *model) { int ret; ret = bios_load_linear("roms/machines/tx97/0112.001", - 0x000e0000, 131072, 0); + 0x000e0000, 131072, 0); if (bios_only || !ret) - return ret; + return ret; machine_at_common_init_ex(model, 2); pci_init(PCI_CONFIG_TYPE_1); pci_register_slot(0x00, PCI_CARD_NORTHBRIDGE, 0, 0, 0, 0); - pci_register_slot(0x0C, PCI_CARD_NORMAL, 1, 2, 3, 4); - pci_register_slot(0x0B, PCI_CARD_NORMAL, 2, 3, 4, 1); - pci_register_slot(0x0A, PCI_CARD_NORMAL, 3, 4, 1, 2); - pci_register_slot(0x09, PCI_CARD_NORMAL, 4, 1, 2, 3); - pci_register_slot(0x01, PCI_CARD_SOUTHBRIDGE, 1, 2, 3, 4); /* PIIX4 */ - pci_register_slot(0x0D, PCI_CARD_NORMAL, 1, 2, 3, 4); - pci_register_slot(0x08, PCI_CARD_NORMAL, 1, 2, 3, 4); + pci_register_slot(0x0C, PCI_CARD_NORMAL, 1, 2, 3, 4); + pci_register_slot(0x0B, PCI_CARD_NORMAL, 2, 3, 4, 1); + pci_register_slot(0x0A, PCI_CARD_NORMAL, 3, 4, 1, 2); + pci_register_slot(0x09, PCI_CARD_NORMAL, 4, 1, 2, 3); + pci_register_slot(0x01, PCI_CARD_SOUTHBRIDGE, 1, 2, 3, 4); /* PIIX4 */ + pci_register_slot(0x0D, PCI_CARD_NORMAL, 1, 2, 3, 4); + pci_register_slot(0x08, PCI_CARD_NORMAL, 1, 2, 3, 4); device_add(&i430tx_device); device_add(&piix4_device); device_add(&keyboard_ps2_ami_pci_device); device_add(&w83877tf_acorp_device); device_add(&intel_flash_bxt_device); spd_register(SPD_TYPE_SDRAM, 0x3, 128); - device_add(&w83781d_device); /* fans: Chassis, CPU, Power; temperatures: MB, unused, CPU */ + device_add(&w83781d_device); /* fans: Chassis, CPU, Power; temperatures: MB, unused, CPU */ hwm_values.temperatures[1] = 0; /* unused */ /* CPU offset */ if (hwm_values.temperatures[2] < 32) /* prevent underflow */ - hwm_values.temperatures[2] = 0; + hwm_values.temperatures[2] = 0; else - hwm_values.temperatures[2] -= 32; + hwm_values.temperatures[2] -= 32; return ret; } - -#if defined(DEV_BRANCH) && defined(NO_SIO) +#if defined(DEV_BRANCH) && defined(USE_AN430TX) int machine_at_an430tx_init(const machine_t *model) { int ret; -#if 1 +# if 1 ret = bios_load_linear_combined2("roms/machines/an430tx/P10-0095.BIO", - "roms/machines/an430tx/P10-0095.BI1", - "roms/machines/an430tx/P10-0095.BI2", - "roms/machines/an430tx/P10-0095.BI3", - "roms/machines/an430tx/P10-0095.RCV", - 0x3a000, 160); -#else + "roms/machines/an430tx/P10-0095.BI1", + "roms/machines/an430tx/P10-0095.BI2", + "roms/machines/an430tx/P10-0095.BI3", + "roms/machines/an430tx/P10-0095.RCV", + 0x3a000, 160); +# else ret = bios_load_linear_combined2("roms/machines/an430tx/P06-0062.BIO", - "roms/machines/an430tx/P06-0062.BI1", - "roms/machines/an430tx/P06-0062.BI2", - "roms/machines/an430tx/P06-0062.BI3", - "roms/machines/an430tx/P10-0095.RCV", - 0x3a000, 160); -#endif + "roms/machines/an430tx/P06-0062.BI1", + "roms/machines/an430tx/P06-0062.BI2", + "roms/machines/an430tx/P06-0062.BI3", + "roms/machines/an430tx/P10-0095.RCV", + 0x3a000, 160); +# endif if (bios_only || !ret) - return ret; + return ret; machine_at_common_init_ex(model, 2); pci_init(PCI_CONFIG_TYPE_1); pci_register_slot(0x00, PCI_CARD_NORTHBRIDGE, 0, 0, 0, 0); - pci_register_slot(0x07, PCI_CARD_SOUTHBRIDGE, 1, 2, 3, 4); /* PIIX4 */ - // pci_register_slot(0x08, PCI_CARD_VIDEO, 4, 0, 0, 0); - pci_register_slot(0x0D, PCI_CARD_NORMAL, 1, 2, 3, 4); - pci_register_slot(0x0E, PCI_CARD_NORMAL, 2, 3, 4, 1); - pci_register_slot(0x0F, PCI_CARD_NORMAL, 3, 4, 1, 2); - pci_register_slot(0x10, PCI_CARD_NORMAL, 4, 1, 2, 3); + pci_register_slot(0x07, PCI_CARD_SOUTHBRIDGE, 1, 2, 3, 4); /* PIIX4 */ + // pci_register_slot(0x08, PCI_CARD_VIDEO, 4, 0, 0, 0); + pci_register_slot(0x0D, PCI_CARD_NORMAL, 1, 2, 3, 4); + pci_register_slot(0x0E, PCI_CARD_NORMAL, 2, 3, 4, 1); + pci_register_slot(0x0F, PCI_CARD_NORMAL, 3, 4, 1, 2); + pci_register_slot(0x10, PCI_CARD_NORMAL, 4, 1, 2, 3); device_add(&i430tx_device); device_add(&piix4_device); device_add(&keyboard_ps2_ami_pci_device); @@ -735,29 +889,28 @@ machine_at_an430tx_init(const machine_t *model) } #endif - int machine_at_ym430tx_init(const machine_t *model) { int ret; ret = bios_load_linear("roms/machines/ym430tx/YM430TX.003", - 0x000e0000, 131072, 0); + 0x000e0000, 131072, 0); if (bios_only || !ret) - return ret; + return ret; machine_at_common_init_ex(model, 2); pci_init(PCI_CONFIG_TYPE_1); pci_register_slot(0x00, PCI_CARD_NORTHBRIDGE, 0, 0, 0, 0); - pci_register_slot(0x0C, PCI_CARD_NORMAL, 1, 2, 3, 4); - pci_register_slot(0x0B, PCI_CARD_NORMAL, 2, 3, 4, 1); - pci_register_slot(0x0A, PCI_CARD_NORMAL, 3, 4, 1, 2); - pci_register_slot(0x09, PCI_CARD_NORMAL, 4, 1, 2, 3); - pci_register_slot(0x01, PCI_CARD_SOUTHBRIDGE, 1, 2, 3, 4); /* PIIX4 */ - pci_register_slot(0x0D, PCI_CARD_NORMAL, 1, 2, 3, 4); - pci_register_slot(0x08, PCI_CARD_NORMAL, 1, 2, 3, 4); + pci_register_slot(0x0C, PCI_CARD_NORMAL, 1, 2, 3, 4); + pci_register_slot(0x0B, PCI_CARD_NORMAL, 2, 3, 4, 1); + pci_register_slot(0x0A, PCI_CARD_NORMAL, 3, 4, 1, 2); + pci_register_slot(0x09, PCI_CARD_NORMAL, 4, 1, 2, 3); + pci_register_slot(0x01, PCI_CARD_SOUTHBRIDGE, 1, 2, 3, 4); /* PIIX4 */ + pci_register_slot(0x0D, PCI_CARD_NORMAL, 1, 2, 3, 4); + pci_register_slot(0x08, PCI_CARD_NORMAL, 1, 2, 3, 4); device_add(&i430tx_device); device_add(&piix4_device); device_add(&keyboard_ps2_pci_device); @@ -768,27 +921,26 @@ machine_at_ym430tx_init(const machine_t *model) return ret; } - int machine_at_mb540n_init(const machine_t *model) { int ret; ret = bios_load_linear("roms/machines/mb540n/Tx0720ug.bin", - 0x000e0000, 131072, 0); + 0x000e0000, 131072, 0); if (bios_only || !ret) - return ret; + return ret; machine_at_common_init_ex(model, 2); pci_init(PCI_CONFIG_TYPE_1); pci_register_slot(0x00, PCI_CARD_NORTHBRIDGE, 0, 0, 0, 0); - pci_register_slot(0x11, PCI_CARD_NORMAL, 4, 1, 2, 3); - pci_register_slot(0x12, PCI_CARD_NORMAL, 3, 4, 1, 2); - pci_register_slot(0x13, PCI_CARD_NORMAL, 2, 3, 4, 1); - pci_register_slot(0x14, PCI_CARD_NORMAL, 1, 2, 3, 4); - pci_register_slot(0x07, PCI_CARD_SOUTHBRIDGE, 1, 2, 3, 4); /* PIIX4 */ + pci_register_slot(0x11, PCI_CARD_NORMAL, 4, 1, 2, 3); + pci_register_slot(0x12, PCI_CARD_NORMAL, 3, 4, 1, 2); + pci_register_slot(0x13, PCI_CARD_NORMAL, 2, 3, 4, 1); + pci_register_slot(0x14, PCI_CARD_NORMAL, 1, 2, 3, 4); + pci_register_slot(0x07, PCI_CARD_SOUTHBRIDGE, 1, 2, 3, 4); /* PIIX4 */ device_add(&i430tx_device); device_add(&piix4_device); device_add(&keyboard_ps2_pci_device); @@ -799,6 +951,36 @@ machine_at_mb540n_init(const machine_t *model) return ret; } +int +machine_at_56a5_init(const machine_t *model) +{ + int ret; + + ret = bios_load_linear("roms/machines/56a5/54p5b6b.bin", + 0x000e0000, 131072, 0); + + if (bios_only || !ret) + return ret; + + machine_at_common_init_ex(model, 2); + + pci_init(PCI_CONFIG_TYPE_1); + pci_register_slot(0x00, PCI_CARD_NORTHBRIDGE, 0, 0, 0, 0); + pci_register_slot(0x11, PCI_CARD_NORMAL, 1, 2, 3, 4); + pci_register_slot(0x12, PCI_CARD_NORMAL, 2, 3, 4, 1); + pci_register_slot(0x13, PCI_CARD_NORMAL, 3, 4, 1, 2); + pci_register_slot(0x14, PCI_CARD_NORMAL, 4, 1, 2, 3); + pci_register_slot(0x07, PCI_CARD_SOUTHBRIDGE, 1, 2, 3, 4); /* PIIX4 */ + pci_register_slot(0x10, PCI_CARD_NORMAL, 1, 2, 3, 4); + device_add(&i430tx_device); + device_add(&piix4_device); + device_add(&keyboard_ps2_pci_device); + device_add(&w83877f_device); + device_add(&sst_flash_29ee010_device); + spd_register(SPD_TYPE_SDRAM, 0x3, 128); + + return ret; +} int machine_at_p5mms98_init(const machine_t *model) @@ -806,52 +988,51 @@ machine_at_p5mms98_init(const machine_t *model) int ret; ret = bios_load_linear("roms/machines/p5mms98/s981182.rom", - 0x000e0000, 131072, 0); + 0x000e0000, 131072, 0); if (bios_only || !ret) - return ret; + return ret; machine_at_common_init_ex(model, 2); pci_init(PCI_CONFIG_TYPE_1); pci_register_slot(0x00, PCI_CARD_NORTHBRIDGE, 0, 0, 0, 0); - pci_register_slot(0x07, PCI_CARD_SOUTHBRIDGE, 1, 2, 3, 4); /* PIIX4 */ - pci_register_slot(0x11, PCI_CARD_NORMAL, 1, 2, 3, 4); - pci_register_slot(0x12, PCI_CARD_NORMAL, 2, 3, 4, 1); - pci_register_slot(0x13, PCI_CARD_NORMAL, 3, 4, 1, 2); - pci_register_slot(0x14, PCI_CARD_NORMAL, 4, 1, 2, 3); + pci_register_slot(0x07, PCI_CARD_SOUTHBRIDGE, 1, 2, 3, 4); /* PIIX4 */ + pci_register_slot(0x11, PCI_CARD_NORMAL, 1, 2, 3, 4); + pci_register_slot(0x12, PCI_CARD_NORMAL, 2, 3, 4, 1); + pci_register_slot(0x13, PCI_CARD_NORMAL, 3, 4, 1, 2); + pci_register_slot(0x14, PCI_CARD_NORMAL, 4, 1, 2, 3); device_add(&i430tx_device); device_add(&piix4_device); device_add(&keyboard_ps2_ami_pci_device); device_add(&w83977tf_device); device_add(&intel_flash_bxt_device); spd_register(SPD_TYPE_SDRAM, 0x3, 128); - device_add(&lm78_device); /* fans: Thermal, CPU, Chassis; temperature: unused */ + device_add(&lm78_device); /* fans: Thermal, CPU, Chassis; temperature: unused */ device_add(&lm75_1_4a_device); /* temperature: CPU */ return ret; } - int machine_at_ficva502_init(const machine_t *model) { int ret; ret = bios_load_linear("roms/machines/ficva502/VA502bp.BIN", - 0x000e0000, 131072, 0); + 0x000e0000, 131072, 0); if (bios_only || !ret) - return ret; + return ret; machine_at_common_init_ex(model, 2); pci_init(PCI_CONFIG_TYPE_1); pci_register_slot(0x00, PCI_CARD_NORTHBRIDGE, 0, 0, 0, 0); - pci_register_slot(0x08, PCI_CARD_NORMAL, 1, 2, 3, 4); - pci_register_slot(0x09, PCI_CARD_NORMAL, 2, 3, 4, 1); - pci_register_slot(0x0A, PCI_CARD_NORMAL, 3, 4, 1, 2); - pci_register_slot(0x0B, PCI_CARD_NORMAL, 4, 1, 2, 3); + pci_register_slot(0x08, PCI_CARD_NORMAL, 1, 2, 3, 4); + pci_register_slot(0x09, PCI_CARD_NORMAL, 2, 3, 4, 1); + pci_register_slot(0x0A, PCI_CARD_NORMAL, 3, 4, 1, 2); + pci_register_slot(0x0B, PCI_CARD_NORMAL, 4, 1, 2, 3); pci_register_slot(0x07, PCI_CARD_SOUTHBRIDGE, 1, 2, 3, 4); device_add(&via_vpx_device); device_add(&via_vt82c586b_device); @@ -863,17 +1044,16 @@ machine_at_ficva502_init(const machine_t *model) return ret; } - int machine_at_ficpa2012_init(const machine_t *model) { int ret; ret = bios_load_linear("roms/machines/ficpa2012/113jb16.awd", - 0x000e0000, 131072, 0); + 0x000e0000, 131072, 0); if (bios_only || !ret) - return ret; + return ret; machine_at_common_init_ex(model, 2); @@ -896,17 +1076,16 @@ machine_at_ficpa2012_init(const machine_t *model) return ret; } - int machine_at_r534f_init(const machine_t *model) { int ret; ret = bios_load_linear("roms/machines/r534f/r534f008.bin", - 0x000e0000, 131072, 0); + 0x000e0000, 131072, 0); if (bios_only || !ret) - return ret; + return ret; machine_at_common_init(model); @@ -926,17 +1105,16 @@ machine_at_r534f_init(const machine_t *model) return ret; } - int machine_at_ms5146_init(const machine_t *model) { int ret; ret = bios_load_linear("roms/machines/ms5146/A546MS11.ROM", - 0x000e0000, 131072, 0); + 0x000e0000, 131072, 0); if (bios_only || !ret) - return ret; + return ret; machine_at_common_init(model); @@ -956,68 +1134,64 @@ machine_at_ms5146_init(const machine_t *model) return ret; } - int machine_at_m560_init(const machine_t *model) { int ret; ret = bios_load_linear("roms/machines/m560/5600410s.ami", - 0x000e0000, 131072, 0); + 0x000e0000, 131072, 0); if (bios_only || !ret) - return ret; + return ret; machine_at_common_init_ex(model, 2); pci_init(PCI_CONFIG_TYPE_1); - pci_register_slot(0x00, PCI_CARD_NORTHBRIDGE, 0, 0, 0, 0); - pci_register_slot(0x02, PCI_CARD_SOUTHBRIDGE, 1, 2, 3, 4); - pci_register_slot(0x0B, PCI_CARD_SOUTHBRIDGE, 1, 2, 3, 4); - pci_register_slot(0x0C, PCI_CARD_SOUTHBRIDGE, 1, 2, 3, 4); - pci_register_slot(0x0F, PCI_CARD_SOUTHBRIDGE, 1, 2, 3, 4); - pci_register_slot(0x03, PCI_CARD_NORMAL, 1, 2, 3, 4); - pci_register_slot(0x04, PCI_CARD_NORMAL, 2, 3, 4, 1); - pci_register_slot(0x05, PCI_CARD_NORMAL, 3, 4, 1, 2); - pci_register_slot(0x06, PCI_CARD_NORMAL, 4, 1, 2, 3); + pci_register_slot(0x00, PCI_CARD_NORTHBRIDGE, 0, 0, 0, 0); + pci_register_slot(0x02, PCI_CARD_SOUTHBRIDGE, 1, 2, 3, 4); + pci_register_slot(0x0B, PCI_CARD_SOUTHBRIDGE_IDE, 1, 2, 3, 4); + pci_register_slot(0x0C, PCI_CARD_SOUTHBRIDGE_PMU, 1, 2, 3, 4); + pci_register_slot(0x0F, PCI_CARD_SOUTHBRIDGE_USB, 1, 2, 3, 4); + pci_register_slot(0x03, PCI_CARD_NORMAL, 1, 2, 3, 4); + pci_register_slot(0x04, PCI_CARD_NORMAL, 2, 3, 4, 1); + pci_register_slot(0x05, PCI_CARD_NORMAL, 3, 4, 1, 2); + pci_register_slot(0x06, PCI_CARD_NORMAL, 4, 1, 2, 3); device_add(&ali1531_device); - device_add(&ali1543_device); - device_add(&keyboard_ps2_ami_pci_device); + device_add(&ali1543_device); /* -5 */ device_add(&sst_flash_29ee010_device); spd_register(SPD_TYPE_SDRAM, 0x3, 256); return ret; } - int machine_at_ms5164_init(const machine_t *model) { int ret; ret = bios_load_linear("roms/machines/ms5164/W564MS43.005", - 0x000e0000, 131072, 0); + 0x000e0000, 131072, 0); if (bios_only || !ret) - return ret; + return ret; machine_at_common_init_ex(model, 2); pci_init(PCI_CONFIG_TYPE_1); - pci_register_slot(0x00, PCI_CARD_NORTHBRIDGE, 0, 0, 0, 0); - pci_register_slot(0x02, PCI_CARD_SOUTHBRIDGE, 1, 2, 3, 4); - pci_register_slot(0x0B, PCI_CARD_SOUTHBRIDGE, 5, 6, 0, 0); - pci_register_slot(0x0C, PCI_CARD_SOUTHBRIDGE, 1, 2, 3, 4); - pci_register_slot(0x0F, PCI_CARD_SOUTHBRIDGE, 1, 2, 3, 4); - pci_register_slot(0x03, PCI_CARD_NORMAL, 1, 2, 3, 4); - pci_register_slot(0x04, PCI_CARD_NORMAL, 2, 3, 4, 1); - pci_register_slot(0x05, PCI_CARD_NORMAL, 3, 4, 1, 2); - pci_register_slot(0x06, PCI_CARD_NORMAL, 4, 1, 2, 3); - pci_register_slot(0x07, PCI_CARD_NORMAL, 1, 2, 3, 4); + pci_register_slot(0x00, PCI_CARD_NORTHBRIDGE, 0, 0, 0, 0); + pci_register_slot(0x02, PCI_CARD_SOUTHBRIDGE, 1, 2, 3, 4); + pci_register_slot(0x0B, PCI_CARD_SOUTHBRIDGE_IDE, 5, 6, 0, 0); + pci_register_slot(0x0C, PCI_CARD_SOUTHBRIDGE_PMU, 1, 2, 3, 4); + pci_register_slot(0x0F, PCI_CARD_SOUTHBRIDGE_USB, 1, 2, 3, 4); + pci_register_slot(0x03, PCI_CARD_NORMAL, 1, 2, 3, 4); + pci_register_slot(0x04, PCI_CARD_NORMAL, 2, 3, 4, 1); + pci_register_slot(0x05, PCI_CARD_NORMAL, 3, 4, 1, 2); + pci_register_slot(0x06, PCI_CARD_NORMAL, 4, 1, 2, 3); + pci_register_slot(0x07, PCI_CARD_NORMAL, 1, 2, 3, 4); device_add(&ali1531_device); - device_add(&ali1543_device); - device_add(&keyboard_ps2_ami_pci_device); + device_add(&ali1543_device); /* -5 */ device_add(&sst_flash_29ee010_device); spd_register(SPD_TYPE_SDRAM, 0x3, 256); diff --git a/src/machine/m_at_socket7_3v.c b/src/machine/m_at_socket7_3v.c index 19b60bdbb..de87ec90d 100644 --- a/src/machine/m_at_socket7_3v.c +++ b/src/machine/m_at_socket7_3v.c @@ -1,22 +1,18 @@ /* - * 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. + * 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. + * This file is part of the 86Box distribution. * - * Implementation of Socket 7 (Single Voltage) machines. + * Implementation of Socket 7 (Single Voltage) machines. * * * - * Authors: Sarah Walker, - * Miran Grca, - * Melissa Goad, - * - * Copyright 2010-2020 Sarah Walker. - * Copyright 2016-2020 Miran Grca. + * Authors: Miran Grca, * + * Copyright 2016-2020 Miran Grca. */ #include #include @@ -44,26 +40,72 @@ #include <86box/fdd.h> #include <86box/fdc.h> #include <86box/nvr.h> - +#include <86box/plat_unused.h> +#include <86box/sound.h> static void -machine_at_thor_common_init(const machine_t *model, int mr) +machine_at_thor_gpio_init(void) { - machine_at_common_init_ex(model, mr); + uint32_t gpio = 0xffffe1cf; + + /* Register 0x0078 (Undocumented): */ + /* Bit 5: 0 = Multiplier. */ + /* Bit 4: 0 = Multiplier. */ + /* 1.5: 0, 0. */ + /* 3.0: 0, 1. */ + /* 2.0: 1, 0. */ + /* 2.5: 1, 1. */ + /* Bit 1: 0 = Error beep, 1 = No error. */ + if (cpu_dmulti <= 1.5) + gpio |= 0xffff0000; + else if ((cpu_dmulti > 1.5) && (cpu_dmulti <= 2.0)) + gpio |= 0xffff0020; + else if ((cpu_dmulti > 2.0) && (cpu_dmulti <= 2.5)) + gpio |= 0xffff0030; + else if (cpu_dmulti > 2.5) + gpio |= 0xffff0010; + + /* Register 0x0079: */ + /* Bit 7: 0 = Clear password, 1 = Keep password. */ + /* Bit 6: 0 = NVRAM cleared by jumper, 1 = NVRAM normal. */ + /* Bit 5: 0 = CMOS Setup disabled, 1 = CMOS Setup enabled. */ + /* Bit 4: External CPU clock (Switch 8). */ + /* Bit 3: External CPU clock (Switch 7). */ + /* 50 MHz: Switch 7 = Off, Switch 8 = Off. */ + /* 60 MHz: Switch 7 = On, Switch 8 = Off. */ + /* 66 MHz: Switch 7 = Off, Switch 8 = On. */ + /* Bit 2: 0 = On-board audio absent, 1 = On-board audio present. */ + /* Bit 1: 0 = Soft-off capable power supply present, 1 = Soft-off capable power supply absent. */ + /* Bit 0: 0 = Reserved. */ + /* NOTE: A bit is read as 1 if switch is off, and as 0 if switch is on. */ + if (cpu_busspeed <= 50000000) + gpio |= 0xffff0000; + else if ((cpu_busspeed > 50000000) && (cpu_busspeed <= 60000000)) + gpio |= 0xffff0800; + else if (cpu_busspeed > 60000000) + gpio |= 0xffff1000; + + machine_set_gpio_default(gpio); +} + +static void +machine_at_thor_common_init(const machine_t *model, int has_video) +{ + machine_at_common_init_ex(model, 2); + machine_at_thor_gpio_init(); pci_init(PCI_CONFIG_TYPE_1); pci_register_slot(0x00, PCI_CARD_NORTHBRIDGE, 0, 0, 0, 0); - pci_register_slot(0x08, PCI_CARD_VIDEO, 4, 0, 0, 0); - pci_register_slot(0x0D, PCI_CARD_NORMAL, 1, 2, 3, 4); - pci_register_slot(0x0E, PCI_CARD_NORMAL, 2, 3, 4, 1); - pci_register_slot(0x0F, PCI_CARD_NORMAL, 3, 4, 2, 1); - pci_register_slot(0x10, PCI_CARD_NORMAL, 4, 3, 2, 1); + pci_register_slot(0x08, PCI_CARD_VIDEO, 4, 0, 0, 0); + pci_register_slot(0x0D, PCI_CARD_NORMAL, 1, 2, 3, 4); + pci_register_slot(0x0E, PCI_CARD_NORMAL, 2, 3, 4, 1); + pci_register_slot(0x0F, PCI_CARD_NORMAL, 3, 4, 2, 1); + pci_register_slot(0x10, PCI_CARD_NORMAL, 4, 3, 2, 1); pci_register_slot(0x07, PCI_CARD_SOUTHBRIDGE, 0, 0, 0, 0); - if (gfxcard == VID_INTERNAL) - device_add(&s3_phoenix_trio64vplus_onboard_pci_device); + if (has_video && (gfxcard[0] == VID_INTERNAL)) + device_add(machine_get_vid_device(machine)); - // device_add(&keyboard_ps2_ami_pci_device); device_add(&keyboard_ps2_intel_ami_pci_device); device_add(&i430fx_device); device_add(&piix_device); @@ -71,7 +113,6 @@ machine_at_thor_common_init(const machine_t *model, int mr) device_add(&intel_flash_bxt_ami_device); } - static void machine_at_p54tp4xe_common_init(const machine_t *model) { @@ -79,52 +120,78 @@ machine_at_p54tp4xe_common_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(0x0C, PCI_CARD_NORMAL, 1, 2, 3, 4); - pci_register_slot(0x0B, PCI_CARD_NORMAL, 2, 3, 4, 1); - pci_register_slot(0x0A, PCI_CARD_NORMAL, 3, 4, 1, 2); - pci_register_slot(0x09, PCI_CARD_NORMAL, 4, 1, 2, 3); + pci_register_slot(0x0C, PCI_CARD_NORMAL, 1, 2, 3, 4); + pci_register_slot(0x0B, PCI_CARD_NORMAL, 2, 3, 4, 1); + pci_register_slot(0x0A, PCI_CARD_NORMAL, 3, 4, 1, 2); + pci_register_slot(0x09, PCI_CARD_NORMAL, 4, 1, 2, 3); pci_register_slot(0x07, PCI_CARD_SOUTHBRIDGE, 0, 0, 0, 0); - device_add(&keyboard_ps2_pci_device); + device_add(&keyboard_ps2_ami_pci_device); device_add(&i430fx_device); device_add(&piix_device); device_add(&fdc37c665_device); device_add(&intel_flash_bxt_device); } - int machine_at_p54tp4xe_init(const machine_t *model) { int ret; ret = bios_load_linear("roms/machines/p54tp4xe/t15i0302.awd", - 0x000e0000, 131072, 0); + 0x000e0000, 131072, 0); if (bios_only || !ret) - return ret; + return ret; machine_at_p54tp4xe_common_init(model); return ret; } - int machine_at_p54tp4xe_mr_init(const machine_t *model) { int ret; ret = bios_load_linear("roms/machines/p54tp4xe/TRITON.BIO", - 0x000e0000, 131072, 0); + 0x000e0000, 131072, 0); if (bios_only || !ret) - return ret; + return ret; machine_at_p54tp4xe_common_init(model); return ret; } +int +machine_at_exp8551_init(const machine_t *model) +{ + int ret; + + ret = bios_load_linear("roms/machines/exp8551/AMI20.BIO", + 0x000e0000, 131072, 0); + + if (bios_only || !ret) + return ret; + + machine_at_common_init(model); + + pci_init(PCI_CONFIG_TYPE_1); + pci_register_slot(0x00, PCI_CARD_NORTHBRIDGE, 0, 0, 0, 0); + pci_register_slot(0x13, PCI_CARD_NORMAL, 2, 3, 4, 1); + pci_register_slot(0x14, PCI_CARD_NORMAL, 1, 2, 3, 4); + pci_register_slot(0x12, PCI_CARD_NORMAL, 3, 4, 1, 2); + pci_register_slot(0x11, PCI_CARD_NORMAL, 4, 1, 2, 3); + pci_register_slot(0x07, PCI_CARD_SOUTHBRIDGE, 0, 0, 0, 0); + device_add(&keyboard_ps2_ami_pci_device); + device_add(&i430fx_device); + device_add(&piix_device); + device_add(&w83787f_device); + device_add(&sst_flash_29ee010_device); + + return ret; +} int machine_at_gw2katx_init(const machine_t *model) @@ -132,57 +199,135 @@ machine_at_gw2katx_init(const machine_t *model) int ret; ret = bios_load_linear_combined("roms/machines/gw2katx/1003CN0T.BIO", - "roms/machines/gw2katx/1003CN0T.BI1", 0x20000, 128); + "roms/machines/gw2katx/1003CN0T.BI1", + 0x20000, 128); if (bios_only || !ret) - return ret; + return ret; machine_at_thor_common_init(model, 0); return ret; } - int machine_at_thor_init(const machine_t *model) { int ret; ret = bios_load_linear_combined("roms/machines/thor/1006cn0_.bio", - "roms/machines/thor/1006cn0_.bi1", 0x20000, 128); + "roms/machines/thor/1006cn0_.bi1", + 0x20000, 128); if (bios_only || !ret) - return ret; + return ret; - machine_at_thor_common_init(model, 0); + machine_at_thor_common_init(model, 1); return ret; } - -const device_t * -at_thor_get_device(void) -{ - return &s3_phoenix_trio64vplus_onboard_pci_device; -} - - int machine_at_mrthor_init(const machine_t *model) { int ret; ret = bios_load_linear("roms/machines/mrthor/mr_atx.bio", - 0x000e0000, 131072, 0); + 0x000e0000, 131072, 0); if (bios_only || !ret) - return ret; + return ret; - machine_at_thor_common_init(model, 1); + machine_at_thor_common_init(model, 0); return ret; } +static void +machine_at_endeavor_gpio_init(void) +{ + uint32_t gpio = 0xffffe0cf; + uint16_t addr; + + /* Register 0x0078 (Undocumented): */ + /* Bit 5,4: Vibra 16S base address: 0 = 220h, 1 = 260h, 2 = 240h, 3 = 280h. */ + device_context(machine_get_snd_device(machine)); + addr = device_get_config_hex16("base"); + switch (addr) { + case 0x0220: + gpio |= 0xffff00cf; + break; + case 0x0240: + gpio |= 0xffff00ef; + break; + case 0x0260: + gpio |= 0xffff00df; + break; + case 0x0280: + gpio |= 0xffff00ff; + break; + } + device_context_restore(); + + /* Register 0x0079: */ + /* Bit 7: 0 = Clear password, 1 = Keep password. */ + /* Bit 6: 0 = NVRAM cleared by jumper, 1 = NVRAM normal. */ + /* Bit 5: 0 = CMOS Setup disabled, 1 = CMOS Setup enabled. */ + /* Bit 4: External CPU clock (Switch 8). */ + /* Bit 3: External CPU clock (Switch 7). */ + /* 50 MHz: Switch 7 = Off, Switch 8 = Off. */ + /* 60 MHz: Switch 7 = On, Switch 8 = Off. */ + /* 66 MHz: Switch 7 = Off, Switch 8 = On. */ + /* Bit 2: 0 = On-board audio absent, 1 = On-board audio present. */ + /* Bit 1: 0 = Soft-off capable power supply present, 1 = Soft-off capable power supply absent. */ + /* Bit 0: 0 = 2x multiplier, 1 = 1.5x multiplier (Switch 6). */ + /* NOTE: A bit is read as 1 if switch is off, and as 0 if switch is on. */ + if (cpu_busspeed <= 50000000) + gpio |= 0xffff0000; + else if ((cpu_busspeed > 50000000) && (cpu_busspeed <= 60000000)) + gpio |= 0xffff0800; + else if (cpu_busspeed > 60000000) + gpio |= 0xffff1000; + + if (sound_card_current[0] == SOUND_INTERNAL) + gpio |= 0xffff0400; + + if (cpu_dmulti <= 1.5) + gpio |= 0xffff0100; + else + gpio |= 0xffff0000; + + machine_set_gpio_default(gpio); +} + +uint32_t +machine_at_endeavor_gpio_handler(uint8_t write, uint32_t val) +{ + uint32_t ret = machine_get_gpio_default(); + + if (write) { + ret &= ((val & 0xffffffcf) | 0xffff0000); + ret |= (val & 0x00000030); + if (machine_snd != NULL) switch ((val >> 4) & 0x03) { + case 0x00: + sb_vibra16s_onboard_relocate_base(0x0220, machine_snd); + break; + case 0x01: + sb_vibra16s_onboard_relocate_base(0x0260, machine_snd); + break; + case 0x02: + sb_vibra16s_onboard_relocate_base(0x0240, machine_snd); + break; + case 0x03: + sb_vibra16s_onboard_relocate_base(0x0280, machine_snd); + break; + } + machine_set_gpio(ret); + } else + ret = machine_get_gpio(); + + return ret; +} int machine_at_endeavor_init(const machine_t *model) @@ -190,24 +335,29 @@ machine_at_endeavor_init(const machine_t *model) int ret; ret = bios_load_linear_combined("roms/machines/endeavor/1006cb0_.bio", - "roms/machines/endeavor/1006cb0_.bi1", 0x1d000, 128); + "roms/machines/endeavor/1006cb0_.bi1", + 0x1d000, 128); if (bios_only || !ret) - return ret; + return ret; - machine_at_common_init(model); + machine_at_common_init_ex(model, 2); + machine_at_endeavor_gpio_init(); pci_init(PCI_CONFIG_TYPE_1); pci_register_slot(0x00, PCI_CARD_NORTHBRIDGE, 0, 0, 0, 0); - pci_register_slot(0x08, PCI_CARD_VIDEO, 4, 0, 0, 0); - pci_register_slot(0x0D, PCI_CARD_NORMAL, 1, 2, 3, 4); - pci_register_slot(0x0E, PCI_CARD_NORMAL, 2, 3, 4, 1); - pci_register_slot(0x0F, PCI_CARD_NORMAL, 3, 4, 1, 2); - pci_register_slot(0x10, PCI_CARD_NORMAL, 4, 1, 2, 3); + pci_register_slot(0x08, PCI_CARD_VIDEO, 4, 0, 0, 0); + pci_register_slot(0x0D, PCI_CARD_NORMAL, 1, 2, 3, 4); + pci_register_slot(0x0E, PCI_CARD_NORMAL, 2, 3, 4, 1); + pci_register_slot(0x0F, PCI_CARD_NORMAL, 3, 4, 1, 2); + pci_register_slot(0x10, PCI_CARD_NORMAL, 4, 1, 2, 3); pci_register_slot(0x07, PCI_CARD_SOUTHBRIDGE, 0, 0, 0, 0); - if (gfxcard == VID_INTERNAL) - device_add(&s3_phoenix_trio64_onboard_pci_device); + if (gfxcard[0] == VID_INTERNAL) + device_add(machine_get_vid_device(machine)); + + if (sound_card_current[0] == SOUND_INTERNAL) + machine_snd = device_add(machine_get_snd_device(machine)); device_add(&keyboard_ps2_intel_ami_pci_device); device_add(&i430fx_device); @@ -218,34 +368,26 @@ machine_at_endeavor_init(const machine_t *model) return ret; } - -const device_t * -at_endeavor_get_device(void) -{ - return &s3_phoenix_trio64_onboard_pci_device; -} - - int machine_at_ms5119_init(const machine_t *model) { int ret; - ret = bios_load_linear("roms/machines/ms5119/A37E.ROM", - 0x000e0000, 131072, 0); + ret = bios_load_linear("roms/machines/ms5119/A37EB.ROM", + 0x000e0000, 131072, 0); if (bios_only || !ret) - return ret; + return ret; machine_at_common_init(model); pci_init(PCI_CONFIG_TYPE_1); pci_register_slot(0x00, PCI_CARD_NORTHBRIDGE, 0, 0, 0, 0); pci_register_slot(0x07, PCI_CARD_SOUTHBRIDGE, 0, 0, 0, 0); - pci_register_slot(0x0d, PCI_CARD_NORMAL, 1, 2, 3, 4); - pci_register_slot(0x0e, PCI_CARD_NORMAL, 2, 3, 4, 1); - pci_register_slot(0x0f, PCI_CARD_NORMAL, 3, 4, 1, 2); - + pci_register_slot(0x0d, PCI_CARD_NORMAL, 1, 2, 3, 4); + pci_register_slot(0x0e, PCI_CARD_NORMAL, 2, 3, 4, 1); + pci_register_slot(0x0f, PCI_CARD_NORMAL, 3, 4, 1, 2); + device_add(&i430fx_device); device_add(&piix_device); device_add(&keyboard_ps2_ami_pci_device); @@ -255,6 +397,38 @@ machine_at_ms5119_init(const machine_t *model) return ret; } +static void +machine_at_pb640_gpio_init(void) +{ + uint32_t gpio = 0xffffe6ff; + + /* Register 0x0079: */ + /* Bit 7: 0 = Clear password, 1 = Keep password. */ + /* Bit 6: 0 = NVRAM cleared by jumper, 1 = NVRAM normal. */ + /* Bit 5: 0 = CMOS Setup disabled, 1 = CMOS Setup enabled. */ + /* Bit 4: External CPU clock (Switch 8). */ + /* Bit 3: External CPU clock (Switch 7). */ + /* 50 MHz: Switch 7 = Off, Switch 8 = Off. */ + /* 60 MHz: Switch 7 = On, Switch 8 = Off. */ + /* 66 MHz: Switch 7 = Off, Switch 8 = On. */ + /* Bit 2: No Connect. */ + /* Bit 1: No Connect. */ + /* Bit 0: 2x multiplier, 1 = 1.5x multiplier (Switch 6). */ + /* NOTE: A bit is read as 1 if switch is off, and as 0 if switch is on. */ + if (cpu_busspeed <= 50000000) + gpio |= 0xffff00ff; + else if ((cpu_busspeed > 50000000) && (cpu_busspeed <= 60000000)) + gpio |= 0xffff08ff; + else if (cpu_busspeed > 60000000) + gpio |= 0xffff10ff; + + if (cpu_dmulti <= 1.5) + gpio |= 0xffff01ff; + else + gpio |= 0xffff00ff; + + machine_set_gpio_default(gpio); +} int machine_at_pb640_init(const machine_t *model) @@ -262,25 +436,26 @@ machine_at_pb640_init(const machine_t *model) int ret; ret = bios_load_linear_combined("roms/machines/pb640/1007CP0R.BIO", - "roms/machines/pb640/1007CP0R.BI1", 0x1d000, 128); + "roms/machines/pb640/1007CP0R.BI1", 0x1d000, 128); if (bios_only || !ret) - return ret; + return ret; - machine_at_common_init(model); + machine_at_common_init_ex(model, 2); + machine_at_pb640_gpio_init(); pci_init(PCI_CONFIG_TYPE_1); pci_register_slot(0x00, PCI_CARD_NORTHBRIDGE, 0, 0, 0, 0); - pci_register_slot(0x08, PCI_CARD_VIDEO, 4, 0, 0, 0); - pci_register_slot(0x11, PCI_CARD_NORMAL, 1, 2, 3, 4); - pci_register_slot(0x13, PCI_CARD_NORMAL, 2, 1, 3, 4); - pci_register_slot(0x0B, PCI_CARD_NORMAL, 3, 2, 1, 4); + pci_register_slot(0x08, PCI_CARD_VIDEO, 4, 0, 0, 0); + pci_register_slot(0x11, PCI_CARD_NORMAL, 1, 2, 3, 4); + pci_register_slot(0x13, PCI_CARD_NORMAL, 2, 1, 3, 4); + pci_register_slot(0x0B, PCI_CARD_NORMAL, 3, 2, 1, 4); pci_register_slot(0x07, PCI_CARD_SOUTHBRIDGE, 0, 0, 0, 0); device_add(&i430fx_rev02_device); device_add(&piix_rev02_device); - if (gfxcard == VID_INTERNAL) - device_add(&gd5440_onboard_pci_device); + if (gfxcard[0] == VID_INTERNAL) + device_add(&gd5440_onboard_pci_device); device_add(&keyboard_ps2_intel_ami_pci_device); device_add(&pc87306_device); @@ -289,13 +464,34 @@ machine_at_pb640_init(const machine_t *model) return ret; } - -const device_t * -at_pb640_get_device(void) +int +machine_at_mb500n_init(const machine_t *model) { - return &gd5440_onboard_pci_device; -} + int ret; + ret = bios_load_linear("roms/machines/mb500n/031396s.bin", + 0x000e0000, 131072, 0); + + if (bios_only || !ret) + return ret; + + machine_at_common_init(model); + + pci_init(PCI_CONFIG_TYPE_1); + pci_register_slot(0x00, PCI_CARD_NORTHBRIDGE, 0, 0, 0, 0); + pci_register_slot(0x14, PCI_CARD_NORMAL, 1, 2, 3, 4); + pci_register_slot(0x13, PCI_CARD_NORMAL, 2, 3, 4, 1); + pci_register_slot(0x12, PCI_CARD_NORMAL, 3, 4, 1, 2); + pci_register_slot(0x11, PCI_CARD_NORMAL, 4, 1, 2, 3); + pci_register_slot(0x07, PCI_CARD_SOUTHBRIDGE, 0, 0, 0, 0); + device_add(&keyboard_ps2_pci_device); + device_add(&i430fx_device); + device_add(&piix_no_mirq_device); + device_add(&fdc37c665_device); + device_add(&intel_flash_bxt_device); + + return ret; +} int machine_at_fmb_init(const machine_t *model) @@ -303,52 +499,51 @@ machine_at_fmb_init(const machine_t *model) int ret; ret = bios_load_linear("roms/machines/fmb/P5IV183.ROM", - 0x000e0000, 131072, 0); + 0x000e0000, 131072, 0); if (bios_only || !ret) - return ret; + return ret; machine_at_common_init(model); pci_init(PCI_CONFIG_TYPE_1); pci_register_slot(0x00, PCI_CARD_NORTHBRIDGE, 0, 0, 0, 0); pci_register_slot(0x07, PCI_CARD_SOUTHBRIDGE, 0, 0, 0, 0); - pci_register_slot(0x14, PCI_CARD_NORMAL, 1, 2, 3, 4); - pci_register_slot(0x13, PCI_CARD_NORMAL, 2, 3, 4, 1); - pci_register_slot(0x12, PCI_CARD_NORMAL, 3, 4, 2, 1); - pci_register_slot(0x11, PCI_CARD_NORMAL, 4, 3, 2, 1); - + pci_register_slot(0x14, PCI_CARD_NORMAL, 1, 2, 3, 4); + pci_register_slot(0x13, PCI_CARD_NORMAL, 2, 3, 4, 1); + pci_register_slot(0x12, PCI_CARD_NORMAL, 3, 4, 2, 1); + pci_register_slot(0x11, PCI_CARD_NORMAL, 4, 3, 2, 1); + device_add(&i430fx_device); - device_add(&piix_device); - device_add(&keyboard_ps2_ami_pci_device); + device_add(&piix_no_mirq_device); + device_add(&keyboard_at_ami_device); device_add(&w83787f_device); device_add(&intel_flash_bxt_device); return ret; } - int machine_at_acerm3a_init(const machine_t *model) { int ret; ret = bios_load_linear("roms/machines/acerm3a/r01-b3.bin", - 0x000e0000, 131072, 0); + 0x000e0000, 131072, 0); if (bios_only || !ret) - return ret; + return ret; machine_at_common_init(model); pci_init(PCI_CONFIG_TYPE_1); pci_register_slot(0x00, PCI_CARD_NORTHBRIDGE, 0, 0, 0, 0); pci_register_slot(0x07, PCI_CARD_SOUTHBRIDGE, 0, 0, 0, 0); - pci_register_slot(0x0C, PCI_CARD_NORMAL, 1, 2, 3, 4); - pci_register_slot(0x0D, PCI_CARD_NORMAL, 2, 3, 4, 1); - pci_register_slot(0x0E, PCI_CARD_NORMAL, 3, 4, 1, 2); - pci_register_slot(0x0F, PCI_CARD_NORMAL, 4, 1, 2, 3); - pci_register_slot(0x10, PCI_CARD_VIDEO, 4, 0, 0, 0); + pci_register_slot(0x0C, PCI_CARD_NORMAL, 1, 2, 3, 4); + pci_register_slot(0x0D, PCI_CARD_NORMAL, 2, 3, 4, 1); + pci_register_slot(0x0E, PCI_CARD_NORMAL, 3, 4, 1, 2); + pci_register_slot(0x0F, PCI_CARD_NORMAL, 4, 1, 2, 3); + pci_register_slot(0x10, PCI_CARD_VIDEO, 4, 0, 0, 0); device_add(&i430hx_device); device_add(&piix3_device); device_add(&keyboard_ps2_pci_device); @@ -359,28 +554,27 @@ machine_at_acerm3a_init(const machine_t *model) return ret; } - int machine_at_ap53_init(const machine_t *model) { int ret; ret = bios_load_linear("roms/machines/ap53/ap53r2c0.rom", - 0x000e0000, 131072, 0); + 0x000e0000, 131072, 0); if (bios_only || !ret) - return ret; + return ret; machine_at_common_init(model); pci_init(PCI_CONFIG_TYPE_1); pci_register_slot(0x00, PCI_CARD_NORTHBRIDGE, 0, 0, 0, 0); - pci_register_slot(0x11, PCI_CARD_NORMAL, 1, 2, 3, 4); - pci_register_slot(0x12, PCI_CARD_NORMAL, 2, 3, 4, 1); - pci_register_slot(0x13, PCI_CARD_NORMAL, 3, 4, 1, 2); - pci_register_slot(0x14, PCI_CARD_NORMAL, 4, 1, 2, 3); + pci_register_slot(0x11, PCI_CARD_NORMAL, 1, 2, 3, 4); + pci_register_slot(0x12, PCI_CARD_NORMAL, 2, 3, 4, 1); + pci_register_slot(0x13, PCI_CARD_NORMAL, 3, 4, 1, 2); + pci_register_slot(0x14, PCI_CARD_NORMAL, 4, 1, 2, 3); pci_register_slot(0x07, PCI_CARD_SOUTHBRIDGE, 0, 0, 0, 0); - pci_register_slot(0x06, PCI_CARD_VIDEO, 1, 2, 3, 4); + pci_register_slot(0x06, PCI_CARD_VIDEO, 1, 2, 3, 4); device_add(&i430hx_device); device_add(&piix3_device); device_add(&keyboard_ps2_ami_pci_device); @@ -390,26 +584,25 @@ machine_at_ap53_init(const machine_t *model) return ret; } - int machine_at_8500tuc_init(const machine_t *model) { int ret; ret = bios_load_linear("roms/machines/8500tuc/Tuc0221b.rom", - 0x000e0000, 131072, 0); + 0x000e0000, 131072, 0); if (bios_only || !ret) - return ret; + return ret; machine_at_common_init(model); pci_init(PCI_CONFIG_TYPE_1); pci_register_slot(0x00, PCI_CARD_NORTHBRIDGE, 0, 0, 0, 0); - pci_register_slot(0x08, PCI_CARD_NORMAL, 1, 2, 3, 4); - pci_register_slot(0x09, PCI_CARD_NORMAL, 2, 3, 4, 1); - pci_register_slot(0x0A, PCI_CARD_NORMAL, 3, 4, 1, 2); - pci_register_slot(0x0B, PCI_CARD_NORMAL, 4, 1, 2, 3); + pci_register_slot(0x08, PCI_CARD_NORMAL, 1, 2, 3, 4); + pci_register_slot(0x09, PCI_CARD_NORMAL, 2, 3, 4, 1); + pci_register_slot(0x0A, PCI_CARD_NORMAL, 3, 4, 1, 2); + pci_register_slot(0x0B, PCI_CARD_NORMAL, 4, 1, 2, 3); pci_register_slot(0x07, PCI_CARD_SOUTHBRIDGE, 1, 2, 3, 4); device_add(&i430hx_device); device_add(&piix3_device); @@ -420,26 +613,25 @@ machine_at_8500tuc_init(const machine_t *model) return ret; } - int machine_at_p55t2s_init(const machine_t *model) { int ret; ret = bios_load_linear("roms/machines/p55t2s/s6y08t.rom", - 0x000e0000, 131072, 0); + 0x000e0000, 131072, 0); if (bios_only || !ret) - return ret; + return ret; - machine_at_common_init(model); + machine_at_common_init_ex(model, 2); pci_init(PCI_CONFIG_TYPE_1); pci_register_slot(0x00, PCI_CARD_NORTHBRIDGE, 0, 0, 0, 0); - pci_register_slot(0x12, PCI_CARD_NORMAL, 1, 2, 3, 4); - pci_register_slot(0x13, PCI_CARD_NORMAL, 4, 1, 2, 3); - pci_register_slot(0x14, PCI_CARD_NORMAL, 3, 4, 1, 2); - pci_register_slot(0x11, PCI_CARD_NORMAL, 2, 3, 4, 1); + pci_register_slot(0x12, PCI_CARD_NORMAL, 1, 2, 3, 4); + pci_register_slot(0x13, PCI_CARD_NORMAL, 4, 1, 2, 3); + pci_register_slot(0x14, PCI_CARD_NORMAL, 3, 4, 1, 2); + pci_register_slot(0x11, PCI_CARD_NORMAL, 2, 3, 4, 1); pci_register_slot(0x07, PCI_CARD_SOUTHBRIDGE, 0, 0, 0, 0); device_add(&i430hx_device); device_add(&piix3_device); @@ -450,26 +642,25 @@ machine_at_p55t2s_init(const machine_t *model) return ret; } - int machine_at_p5vxb_init(const machine_t *model) { int ret; ret = bios_load_linear("roms/machines/p5vxb/P5VXB10.BIN", - 0x000e0000, 131072, 0); + 0x000e0000, 131072, 0); if (bios_only || !ret) - return ret; + return ret; machine_at_common_init(model); pci_init(PCI_CONFIG_TYPE_1); pci_register_slot(0x00, PCI_CARD_NORTHBRIDGE, 0, 0, 0, 0); - pci_register_slot(0x05, PCI_CARD_NORMAL, 1, 2, 3, 4); - pci_register_slot(0x06, PCI_CARD_NORMAL, 2, 3, 4, 1); - pci_register_slot(0x08, PCI_CARD_NORMAL, 3, 4, 1, 2); - pci_register_slot(0x09, PCI_CARD_NORMAL, 4, 1, 2, 3); + pci_register_slot(0x05, PCI_CARD_NORMAL, 1, 2, 3, 4); + pci_register_slot(0x06, PCI_CARD_NORMAL, 2, 3, 4, 1); + pci_register_slot(0x08, PCI_CARD_NORMAL, 3, 4, 1, 2); + pci_register_slot(0x09, PCI_CARD_NORMAL, 4, 1, 2, 3); pci_register_slot(0x07, PCI_CARD_SOUTHBRIDGE, 0, 0, 0, 4); device_add(&i430vx_device); device_add(&piix3_device); @@ -480,31 +671,30 @@ machine_at_p5vxb_init(const machine_t *model) return ret; } - int machine_at_gw2kte_init(const machine_t *model) { int ret; ret = bios_load_linear_combined2("roms/machines/gw2kte/1008CY1T.BIO", - "roms/machines/gw2kte/1008CY1T.BI1", - "roms/machines/gw2kte/1008CY1T.BI2", - "roms/machines/gw2kte/1008CY1T.BI3", - "roms/machines/gw2kte/1008CY1T.RCV", - 0x3a000, 128); + "roms/machines/gw2kte/1008CY1T.BI1", + "roms/machines/gw2kte/1008CY1T.BI2", + "roms/machines/gw2kte/1008CY1T.BI3", + "roms/machines/gw2kte/1008CY1T.RCV", + 0x3a000, 128); if (bios_only || !ret) - return ret; + return ret; machine_at_common_init(model); pci_init(PCI_CONFIG_TYPE_1); pci_register_slot(0x00, PCI_CARD_NORTHBRIDGE, 0, 0, 0, 0); - pci_register_slot(0x08, PCI_CARD_VIDEO, 4, 0, 0, 0); - pci_register_slot(0x0D, PCI_CARD_NORMAL, 1, 2, 3, 4); - pci_register_slot(0x0E, PCI_CARD_NORMAL, 2, 3, 4, 1); - pci_register_slot(0x0F, PCI_CARD_NORMAL, 3, 4, 1, 2); - pci_register_slot(0x10, PCI_CARD_NORMAL, 3, 4, 1, 2); + pci_register_slot(0x08, PCI_CARD_VIDEO, 4, 0, 0, 0); + pci_register_slot(0x0D, PCI_CARD_NORMAL, 1, 2, 3, 4); + pci_register_slot(0x0E, PCI_CARD_NORMAL, 2, 3, 4, 1); + pci_register_slot(0x0F, PCI_CARD_NORMAL, 3, 4, 1, 2); + pci_register_slot(0x10, PCI_CARD_NORMAL, 3, 4, 1, 2); pci_register_slot(0x07, PCI_CARD_SOUTHBRIDGE, 0, 0, 0, 4); device_add(&i430vx_device); device_add(&piix3_device); @@ -515,36 +705,63 @@ machine_at_gw2kte_init(const machine_t *model) return ret; } - int machine_at_ap5s_init(const machine_t *model) { int ret; ret = bios_load_linear("roms/machines/ap5s/AP5S150.BIN", - 0x000e0000, 131072, 0); + 0x000e0000, 131072, 0); if (bios_only || !ret) - return ret; + return ret; - machine_at_common_init(model); + machine_at_common_init_ex(model, 2); pci_init(PCI_CONFIG_TYPE_1); pci_register_slot(0x00, PCI_CARD_NORTHBRIDGE, 0, 0, 0, 0); pci_register_slot(0x01, PCI_CARD_SOUTHBRIDGE, 0, 0, 0, 0); - pci_register_slot(0x0D, PCI_CARD_NORMAL, 1, 2, 3, 4); - pci_register_slot(0x0F, PCI_CARD_NORMAL, 2, 3, 4, 1); - pci_register_slot(0x11, PCI_CARD_NORMAL, 3, 4, 2, 1); - pci_register_slot(0x13, PCI_CARD_NORMAL, 4, 3, 2, 1); - + pci_register_slot(0x0D, PCI_CARD_NORMAL, 1, 2, 3, 4); + pci_register_slot(0x0F, PCI_CARD_NORMAL, 2, 3, 4, 1); + pci_register_slot(0x11, PCI_CARD_NORMAL, 3, 4, 1, 2); + pci_register_slot(0x13, PCI_CARD_NORMAL, 4, 1, 2, 3); + device_add(&sis_5511_device); - device_add(&keyboard_ps2_ami_pci_device); + device_add(&keyboard_ps2_ami_device); device_add(&fdc37c665_device); device_add(&sst_flash_29ee010_device); return ret; } +int +machine_at_ms5124_init(const machine_t *model) +{ + int ret; + + ret = bios_load_linear("roms/machines/ms5124/AG77.ROM", + 0x000e0000, 131072, 0); + + if (bios_only || !ret) + return ret; + + machine_at_common_init_ex(model, 2); + + pci_init(PCI_CONFIG_TYPE_1); + pci_register_slot(0x00, PCI_CARD_NORTHBRIDGE, 0, 0, 0, 0); + pci_register_slot(0x01, PCI_CARD_SOUTHBRIDGE, 0xFE, 0xFF, 0, 0); + pci_register_slot(0x10, PCI_CARD_NORMAL, 1, 2, 3, 4); + pci_register_slot(0x11, PCI_CARD_NORMAL, 4, 1, 2, 3); + pci_register_slot(0x12, PCI_CARD_NORMAL, 3, 4, 1, 2); + pci_register_slot(0x0F, PCI_CARD_NORMAL, 2, 3, 4, 1); + + device_add(&sis_5511_device); + device_add(&keyboard_ps2_ami_device); + device_add(&w83787f_88h_device); + device_add(&sst_flash_29ee010_device); + + return ret; +} int machine_at_vectra54_init(const machine_t *model) @@ -552,23 +769,23 @@ machine_at_vectra54_init(const machine_t *model) int ret; ret = bios_load_linear("roms/machines/vectra54/GT0724.22", - 0x000e0000, 131072, 0); + 0x000e0000, 131072, 0); if (bios_only || !ret) - return ret; + return ret; machine_at_common_init_ex(model, 2); pci_init(PCI_CONFIG_TYPE_1); pci_register_slot(0x00, PCI_CARD_NORTHBRIDGE, 0, 0, 0, 0); pci_register_slot(0x0F, PCI_CARD_SOUTHBRIDGE, 0, 0, 0, 0); - pci_register_slot(0x0D, PCI_CARD_VIDEO, 0, 0, 0, 0); - pci_register_slot(0x06, PCI_CARD_NORMAL, 1, 2, 3, 4); - pci_register_slot(0x07, PCI_CARD_NORMAL, 2, 3, 4, 1); - pci_register_slot(0x08, PCI_CARD_NORMAL, 3, 4, 1, 2); + pci_register_slot(0x0D, PCI_CARD_VIDEO, 0, 0, 0, 0); + pci_register_slot(0x06, PCI_CARD_NORMAL, 1, 2, 3, 4); + pci_register_slot(0x07, PCI_CARD_NORMAL, 2, 3, 4, 1); + pci_register_slot(0x08, PCI_CARD_NORMAL, 3, 4, 1, 2); - if (gfxcard == VID_INTERNAL) - device_add(&s3_phoenix_trio64_onboard_pci_device); + if (gfxcard[0] == VID_INTERNAL) + device_add(&s3_phoenix_trio64_onboard_pci_device); device_add(&keyboard_ps2_ami_pci_device); device_add(&i430fx_device); diff --git a/src/machine/m_at_socket8.c b/src/machine/m_at_socket8.c index 00545eff9..c8e507335 100644 --- a/src/machine/m_at_socket8.c +++ b/src/machine/m_at_socket8.c @@ -1,18 +1,18 @@ /* - * 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. + * 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. + * This file is part of the 86Box distribution. * - * Implementation of Socket 8 machines. + * Implementation of Socket 8 machines. * * * - * Authors: Miran Grca, + * Authors: Miran Grca, * - * Copyright 2016-2019 Miran Grca. + * Copyright 2016-2019 Miran Grca. */ #include #include @@ -39,30 +39,29 @@ #include "cpu.h" #include <86box/machine.h> - int machine_at_p6rp4_init(const machine_t *model) { int ret; ret = bios_load_linear("roms/machines/p6rp4/OR6I0106.SMC", - 0x000e0000, 131072, 0); + 0x000e0000, 131072, 0); if (bios_only || !ret) - return ret; + return ret; machine_at_common_init_ex(model, 2); device_add(&p6rp4_nvr_device); pci_init(PCI_CONFIG_TYPE_1); - pci_register_slot(0x19, PCI_CARD_NORTHBRIDGE, 0, 0, 0, 0); - pci_register_slot(0x14, PCI_CARD_AGPBRIDGE, 0, 0, 0, 0); - pci_register_slot(0x02, PCI_CARD_SOUTHBRIDGE, 0, 0, 0, 0); - pci_register_slot(0x08, PCI_CARD_IDE, 0, 0, 0, 0); - pci_register_slot(0x07, PCI_CARD_NORMAL, 1, 2, 3, 4); - pci_register_slot(0x06, PCI_CARD_NORMAL, 2, 3, 4, 1); - pci_register_slot(0x05, PCI_CARD_NORMAL, 3, 4, 1, 2); - pci_register_slot(0x04, PCI_CARD_NORMAL, 4, 1, 2, 3); + pci_register_slot(0x19, PCI_CARD_NORTHBRIDGE, 0, 0, 0, 0); + pci_register_slot(0x14, PCI_CARD_NORTHBRIDGE_SEC, 0, 0, 0, 0); + pci_register_slot(0x02, PCI_CARD_SOUTHBRIDGE, 0, 0, 0, 0); + pci_register_slot(0x08, PCI_CARD_IDE, 0, 0, 0, 0); + pci_register_slot(0x07, PCI_CARD_NORMAL, 1, 2, 3, 4); + pci_register_slot(0x06, PCI_CARD_NORMAL, 2, 3, 4, 1); + pci_register_slot(0x05, PCI_CARD_NORMAL, 3, 4, 1, 2); + pci_register_slot(0x04, PCI_CARD_NORMAL, 4, 1, 2, 3); device_add(&i450kx_device); device_add(&sio_zb_device); device_add(&ide_cmd646_device); @@ -74,57 +73,55 @@ machine_at_p6rp4_init(const machine_t *model) return ret; } - int machine_at_686nx_init(const machine_t *model) { int ret; ret = bios_load_linear("roms/machines/686nx/6nx.140", - 0x000e0000, 131072, 0); + 0x000e0000, 131072, 0); if (bios_only || !ret) - return ret; + return ret; machine_at_common_init(model); pci_init(PCI_CONFIG_TYPE_1); pci_register_slot(0x00, PCI_CARD_NORTHBRIDGE, 0, 0, 0, 0); pci_register_slot(0x07, PCI_CARD_SOUTHBRIDGE, 0, 0, 0, 0); - pci_register_slot(0x08, PCI_CARD_NORMAL, 1, 2, 3, 4); - pci_register_slot(0x09, PCI_CARD_NORMAL, 2, 3, 4, 1); - pci_register_slot(0x0A, PCI_CARD_NORMAL, 3, 4, 1, 2); - pci_register_slot(0x0B, PCI_CARD_NORMAL, 4, 1, 2, 3); + pci_register_slot(0x08, PCI_CARD_NORMAL, 1, 2, 3, 4); + pci_register_slot(0x09, PCI_CARD_NORMAL, 2, 3, 4, 1); + pci_register_slot(0x0A, PCI_CARD_NORMAL, 3, 4, 1, 2); + pci_register_slot(0x0B, PCI_CARD_NORMAL, 4, 1, 2, 3); device_add(&i440fx_device); device_add(&piix3_device); - device_add(&keyboard_ps2_ami_pci_device); //Uses the AMIKEY keyboard controller + device_add(&keyboard_ps2_ami_pci_device); // Uses the AMIKEY keyboard controller device_add(&um8669f_device); device_add(&intel_flash_bxt_device); return ret; } - int machine_at_mb600n_init(const machine_t *model) { int ret; ret = bios_load_linear("roms/machines/mb600n/60915cs.rom", - 0x000e0000, 131072, 0); + 0x000e0000, 131072, 0); if (bios_only || !ret) - return ret; + return ret; machine_at_common_init(model); pci_init(PCI_CONFIG_TYPE_1); pci_register_slot(0x00, PCI_CARD_NORTHBRIDGE, 0, 0, 0, 0); pci_register_slot(0x07, PCI_CARD_SOUTHBRIDGE, 0, 0, 0, 0); - pci_register_slot(0x11, PCI_CARD_NORMAL, 1, 2, 3, 4); - pci_register_slot(0x12, PCI_CARD_NORMAL, 2, 3, 4, 1); - pci_register_slot(0x13, PCI_CARD_NORMAL, 3, 4, 1, 2); - pci_register_slot(0x14, PCI_CARD_NORMAL, 4, 1, 2, 3); + pci_register_slot(0x11, PCI_CARD_NORMAL, 1, 2, 3, 4); + pci_register_slot(0x12, PCI_CARD_NORMAL, 2, 3, 4, 1); + pci_register_slot(0x13, PCI_CARD_NORMAL, 3, 4, 1, 2); + pci_register_slot(0x14, PCI_CARD_NORMAL, 4, 1, 2, 3); device_add(&i440fx_device); device_add(&piix3_device); device_add(&keyboard_ps2_ami_pci_device); @@ -140,21 +137,21 @@ machine_at_acerv60n_init(const machine_t *model) int ret; ret = bios_load_linear("roms/machines/acerv60n/V60NE5.BIN", - 0x000e0000, 131072, 0); + 0x000e0000, 131072, 0); if (bios_only || !ret) - return ret; + return ret; machine_at_common_init(model); pci_init(PCI_CONFIG_TYPE_1); pci_register_slot(0x00, PCI_CARD_NORTHBRIDGE, 0, 0, 0, 0); pci_register_slot(0x07, PCI_CARD_SOUTHBRIDGE, 0, 0, 0, 0); - pci_register_slot(0x0D, PCI_CARD_NORMAL, 1, 2, 3, 4); - pci_register_slot(0x0F, PCI_CARD_NORMAL, 2, 3, 4, 1); - pci_register_slot(0x10, PCI_CARD_NORMAL, 3, 4, 1, 2); - pci_register_slot(0x12, PCI_CARD_NORMAL, 4, 1, 2, 3); - pci_register_slot(0x0C, PCI_CARD_NORMAL, 2, 3, 4, 1); + pci_register_slot(0x0D, PCI_CARD_NORMAL, 1, 2, 3, 4); + pci_register_slot(0x0F, PCI_CARD_NORMAL, 2, 3, 4, 1); + pci_register_slot(0x10, PCI_CARD_NORMAL, 3, 4, 1, 2); + pci_register_slot(0x12, PCI_CARD_NORMAL, 4, 1, 2, 3); + pci_register_slot(0x0C, PCI_CARD_NORMAL, 2, 3, 4, 1); device_add(&i440fx_device); device_add(&piix3_device); device_add(&keyboard_ps2_pci_device); @@ -170,23 +167,23 @@ machine_at_vs440fx_init(const machine_t *model) int ret; ret = bios_load_linear_combined2("roms/machines/vs440fx/1018CS1_.BIO", - "roms/machines/vs440fx/1018CS1_.BI1", - "roms/machines/vs440fx/1018CS1_.BI2", - "roms/machines/vs440fx/1018CS1_.BI3", - "roms/machines/vs440fx/1018CS1_.RCV", - 0x3a000, 128); + "roms/machines/vs440fx/1018CS1_.BI1", + "roms/machines/vs440fx/1018CS1_.BI2", + "roms/machines/vs440fx/1018CS1_.BI3", + "roms/machines/vs440fx/1018CS1_.RCV", + 0x3a000, 128); if (bios_only || !ret) - return ret; + return ret; machine_at_common_init(model); pci_init(PCI_CONFIG_TYPE_1); pci_register_slot(0x00, PCI_CARD_NORTHBRIDGE, 0, 0, 0, 0); - pci_register_slot(0x0B, PCI_CARD_NORMAL, 1, 2, 3, 4); - pci_register_slot(0x0F, PCI_CARD_NORMAL, 4, 1, 2, 3); - pci_register_slot(0x11, PCI_CARD_NORMAL, 3, 4, 1, 2); - pci_register_slot(0x13, PCI_CARD_NORMAL, 2, 3, 4, 1); + pci_register_slot(0x0B, PCI_CARD_NORMAL, 1, 2, 3, 4); + pci_register_slot(0x0F, PCI_CARD_NORMAL, 4, 1, 2, 3); + pci_register_slot(0x11, PCI_CARD_NORMAL, 3, 4, 1, 2); + pci_register_slot(0x13, PCI_CARD_NORMAL, 2, 3, 4, 1); pci_register_slot(0x07, PCI_CARD_SOUTHBRIDGE, 0, 0, 0, 0); device_add(&i440fx_device); device_add(&piix3_device); @@ -204,23 +201,23 @@ machine_at_ap440fx_init(const machine_t *model) int ret; ret = bios_load_linear_combined2("roms/machines/ap440fx/1011CT1_.BIO", - "roms/machines/ap440fx/1011CT1_.BI1", - "roms/machines/ap440fx/1011CT1_.BI2", - "roms/machines/ap440fx/1011CT1_.BI3", - "roms/machines/ap440fx/1011CT1_.RCV", - 0x3a000, 128); + "roms/machines/ap440fx/1011CT1_.BI1", + "roms/machines/ap440fx/1011CT1_.BI2", + "roms/machines/ap440fx/1011CT1_.BI3", + "roms/machines/ap440fx/1011CT1_.RCV", + 0x3a000, 128); if (bios_only || !ret) - return ret; + return ret; machine_at_common_init(model); pci_init(PCI_CONFIG_TYPE_1); pci_register_slot(0x00, PCI_CARD_NORTHBRIDGE, 0, 0, 0, 0); - pci_register_slot(0x08, PCI_CARD_VIDEO, 3, 0, 0, 0); - pci_register_slot(0x11, PCI_CARD_NORMAL, 1, 3, 2, 4); - pci_register_slot(0x13, PCI_CARD_NORMAL, 2, 1, 3, 4); - pci_register_slot(0x0B, PCI_CARD_NORMAL, 3, 2, 1, 4); + pci_register_slot(0x08, PCI_CARD_VIDEO, 3, 0, 0, 0); + pci_register_slot(0x11, PCI_CARD_NORMAL, 1, 3, 2, 4); + pci_register_slot(0x13, PCI_CARD_NORMAL, 2, 1, 3, 4); + pci_register_slot(0x0B, PCI_CARD_NORMAL, 3, 2, 1, 4); pci_register_slot(0x07, PCI_CARD_SOUTHBRIDGE, 0, 0, 0, 4); device_add(&i440fx_device); device_add(&piix3_device); @@ -237,20 +234,20 @@ machine_at_8600ttc_init(const machine_t *model) int ret; ret = bios_load_linear("roms/machines/8600ttc/TTC0715B.ROM", - 0x000e0000, 131072, 0); + 0x000e0000, 131072, 0); if (bios_only || !ret) - return ret; + return ret; machine_at_common_init(model); pci_init(PCI_CONFIG_TYPE_1); pci_register_slot(0x00, PCI_CARD_NORTHBRIDGE, 0, 0, 0, 0); pci_register_slot(0x07, PCI_CARD_SOUTHBRIDGE, 0, 0, 0, 0); - pci_register_slot(0x08, PCI_CARD_NORMAL, 1, 2, 3, 4); - pci_register_slot(0x09, PCI_CARD_NORMAL, 2, 3, 4, 1); - pci_register_slot(0x0A, PCI_CARD_NORMAL, 3, 4, 1, 2); - pci_register_slot(0x0B, PCI_CARD_NORMAL, 4, 1, 2, 3); + pci_register_slot(0x08, PCI_CARD_NORMAL, 1, 2, 3, 4); + pci_register_slot(0x09, PCI_CARD_NORMAL, 2, 3, 4, 1); + pci_register_slot(0x0A, PCI_CARD_NORMAL, 3, 4, 1, 2); + pci_register_slot(0x0B, PCI_CARD_NORMAL, 4, 1, 2, 3); device_add(&i440fx_device); device_add(&piix3_device); device_add(&keyboard_ps2_ami_pci_device); @@ -266,20 +263,20 @@ machine_at_m6mi_init(const machine_t *model) int ret; ret = bios_load_linear("roms/machines/m6mi/M6MI05.ROM", - 0x000e0000, 131072, 0); + 0x000e0000, 131072, 0); if (bios_only || !ret) - return ret; + return ret; machine_at_common_init(model); pci_init(PCI_CONFIG_TYPE_1); pci_register_slot(0x00, PCI_CARD_NORTHBRIDGE, 0, 0, 0, 0); pci_register_slot(0x07, PCI_CARD_SOUTHBRIDGE, 0, 0, 0, 0); - pci_register_slot(0x12, PCI_CARD_NORMAL, 1, 2, 3, 4); - pci_register_slot(0x11, PCI_CARD_NORMAL, 2, 3, 4, 1); - pci_register_slot(0x10, PCI_CARD_NORMAL, 3, 4, 1, 2); - pci_register_slot(0x0F, PCI_CARD_NORMAL, 4, 1, 2, 3); + pci_register_slot(0x12, PCI_CARD_NORMAL, 1, 2, 3, 4); + pci_register_slot(0x11, PCI_CARD_NORMAL, 2, 3, 4, 1); + pci_register_slot(0x10, PCI_CARD_NORMAL, 3, 4, 1, 2); + pci_register_slot(0x0F, PCI_CARD_NORMAL, 4, 1, 2, 3); device_add(&i440fx_device); device_add(&piix3_device); device_add(&keyboard_ps2_ami_pci_device); @@ -297,11 +294,11 @@ machine_at_p65up5_common_init(const machine_t *model, const device_t *northbridg pci_init(PCI_CONFIG_TYPE_1); pci_register_slot(0x00, PCI_CARD_NORTHBRIDGE, 0, 0, 0, 0); pci_register_slot(0x01, PCI_CARD_SOUTHBRIDGE, 0, 0, 0, 0); - pci_register_slot(0x09, PCI_CARD_NORMAL, 4, 1, 2, 3); - pci_register_slot(0x0A, PCI_CARD_NORMAL, 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(0x0D, PCI_CARD_NORMAL, 4, 1, 2, 3); + pci_register_slot(0x09, PCI_CARD_NORMAL, 4, 1, 2, 3); + pci_register_slot(0x0A, PCI_CARD_NORMAL, 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(0x0D, PCI_CARD_NORMAL, 4, 1, 2, 3); device_add(northbridge); device_add(&piix3_ioapic_device); device_add(&keyboard_ps2_ami_pci_device); @@ -316,10 +313,10 @@ machine_at_p65up5_cp6nd_init(const machine_t *model) int ret; ret = bios_load_linear("roms/machines/p65up5/ND6I0218.AWD", - 0x000e0000, 131072, 0); + 0x000e0000, 131072, 0); if (bios_only || !ret) - return ret; + return ret; machine_at_p65up5_common_init(model, &i440fx_device); diff --git a/src/machine/m_at_sockets7.c b/src/machine/m_at_sockets7.c index dae4e5396..382a4f327 100644 --- a/src/machine/m_at_sockets7.c +++ b/src/machine/m_at_sockets7.c @@ -1,22 +1,18 @@ /* - * 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. + * 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. + * This file is part of the 86Box distribution. * - * Implementation of Super Socket 7 machines. + * Implementation of Super Socket 7 machines. * * * - * Authors: Sarah Walker, - * Miran Grca, - * Melissa Goad, + * Authors: Miran Grca, * - * Copyright 2010-2020 Sarah Walker. - * Copyright 2016-2020 Miran Grca. - * Copyright 2020 Melissa Goad. + * Copyright 2016-2020 Miran Grca. */ #include #include @@ -44,17 +40,16 @@ #include <86box/snd_ac97.h> #include <86box/clock.h> - int machine_at_p5a_init(const machine_t *model) { int ret; ret = bios_load_linear("roms/machines/p5a/1011.005", - 0x000c0000, 262144, 0); + 0x000c0000, 262144, 0); if (bios_only || !ret) - return ret; + return ret; machine_at_common_init_ex(model, 2); @@ -62,9 +57,9 @@ machine_at_p5a_init(const machine_t *model) pci_register_slot(0x00, PCI_CARD_NORTHBRIDGE, 0, 0, 0, 0); pci_register_slot(0x01, PCI_CARD_AGPBRIDGE, 1, 2, 0, 0); pci_register_slot(0x07, PCI_CARD_SOUTHBRIDGE, 1, 2, 3, 4); - pci_register_slot(0x0F, PCI_CARD_SOUTHBRIDGE, 1, 2, 3, 4); - pci_register_slot(0x03, PCI_CARD_SOUTHBRIDGE, 1, 2, 3, 4); - pci_register_slot(0x02, PCI_CARD_SOUTHBRIDGE, 1, 2, 3, 4); + pci_register_slot(0x0F, PCI_CARD_SOUTHBRIDGE_IDE, 1, 2, 3, 4); + pci_register_slot(0x03, PCI_CARD_SOUTHBRIDGE_PMU, 1, 2, 3, 4); + pci_register_slot(0x02, PCI_CARD_SOUTHBRIDGE_USB, 1, 2, 3, 4); pci_register_slot(0x0C, PCI_CARD_NORMAL, 1, 2, 3, 4); pci_register_slot(0x0B, PCI_CARD_NORMAL, 2, 3, 4, 1); pci_register_slot(0x0A, PCI_CARD_NORMAL, 3, 4, 1, 2); @@ -72,8 +67,7 @@ machine_at_p5a_init(const machine_t *model) pci_register_slot(0x0D, PCI_CARD_NORMAL, 4, 1, 2, 3); pci_register_slot(0x06, PCI_CARD_NORMAL, 3, 4, 1, 2); device_add(&ali1541_device); - device_add(&ali1543c_device); - device_add(&keyboard_ps2_ami_pci_device); + device_add(&ali1543c_device); /* +0 */ device_add(&sst_flash_39sf020_device); spd_register(SPD_TYPE_SDRAM, 0x7, 512); device_add(&w83781d_p5a_device); /* fans: Chassis, CPU, Power; temperatures: MB, unused, CPU */ @@ -81,17 +75,16 @@ machine_at_p5a_init(const machine_t *model) return ret; } - int machine_at_m579_init(const machine_t *model) { int ret; ret = bios_load_linear("roms/machines/m579/MS6260S_Socket7_ALi_M1542_AMI.BIN", - 0x000e0000, 131072, 0); + 0x000e0000, 131072, 0); if (bios_only || !ret) - return ret; + return ret; machine_at_common_init_ex(model, 2); @@ -99,32 +92,30 @@ machine_at_m579_init(const machine_t *model) pci_register_slot(0x00, PCI_CARD_NORTHBRIDGE, 0, 0, 0, 0); pci_register_slot(0x01, PCI_CARD_AGPBRIDGE, 1, 2, 0, 0); pci_register_slot(0x07, PCI_CARD_SOUTHBRIDGE, 1, 2, 3, 4); - pci_register_slot(0x0F, PCI_CARD_SOUTHBRIDGE, 1, 2, 3, 4); - pci_register_slot(0x03, PCI_CARD_SOUTHBRIDGE, 1, 2, 3, 4); - pci_register_slot(0x02, PCI_CARD_SOUTHBRIDGE, 1, 2, 3, 4); + pci_register_slot(0x0F, PCI_CARD_SOUTHBRIDGE_IDE, 1, 2, 3, 4); + pci_register_slot(0x03, PCI_CARD_SOUTHBRIDGE_PMU, 1, 2, 3, 4); + pci_register_slot(0x02, PCI_CARD_SOUTHBRIDGE_USB, 1, 2, 3, 4); pci_register_slot(0x10, PCI_CARD_NORMAL, 3, 4, 1, 2); pci_register_slot(0x12, PCI_CARD_NORMAL, 2, 3, 4, 1); pci_register_slot(0x14, PCI_CARD_NORMAL, 1, 2, 3, 4); device_add(&ali1541_device); - device_add(&ali1543c_device); - device_add(&keyboard_ps2_ami_pci_device); + device_add(&ali1543c_device); /* +0 */ device_add(&sst_flash_29ee010_device); spd_register(SPD_TYPE_SDRAM, 0x7, 512); return ret; } - int machine_at_5aa_init(const machine_t *model) { int ret; ret = bios_load_linear("roms/machines/5aa/GA-5AA.F7b", - 0x000e0000, 131072, 0); + 0x000e0000, 131072, 0); if (bios_only || !ret) - return ret; + return ret; machine_at_common_init_ex(model, 2); @@ -132,32 +123,30 @@ machine_at_5aa_init(const machine_t *model) pci_register_slot(0x00, PCI_CARD_NORTHBRIDGE, 0, 0, 0, 0); pci_register_slot(0x01, PCI_CARD_AGPBRIDGE, 1, 2, 0, 0); pci_register_slot(0x07, PCI_CARD_SOUTHBRIDGE, 1, 2, 3, 4); - pci_register_slot(0x0F, PCI_CARD_SOUTHBRIDGE, 1, 2, 3, 4); - pci_register_slot(0x03, PCI_CARD_SOUTHBRIDGE, 1, 2, 3, 4); - pci_register_slot(0x02, PCI_CARD_SOUTHBRIDGE, 1, 2, 3, 4); + pci_register_slot(0x0F, PCI_CARD_SOUTHBRIDGE_IDE, 1, 2, 3, 4); + pci_register_slot(0x03, PCI_CARD_SOUTHBRIDGE_PMU, 1, 2, 3, 4); + pci_register_slot(0x02, PCI_CARD_SOUTHBRIDGE_USB, 1, 2, 3, 4); pci_register_slot(0x08, PCI_CARD_NORMAL, 1, 2, 3, 4); pci_register_slot(0x09, PCI_CARD_NORMAL, 2, 3, 4, 1); pci_register_slot(0x0A, PCI_CARD_NORMAL, 3, 4, 1, 2); device_add(&ali1541_device); - device_add(&ali1543c_device); - device_add(&keyboard_ps2_ami_pci_device); + device_add(&ali1543c_device); /* +0 */ device_add(&sst_flash_29ee010_device); spd_register(SPD_TYPE_SDRAM, 0x7, 512); return ret; } - int machine_at_5ax_init(const machine_t *model) { int ret; ret = bios_load_linear("roms/machines/5ax/5AX.F4", - 0x000e0000, 131072, 0); + 0x000e0000, 131072, 0); if (bios_only || !ret) - return ret; + return ret; machine_at_common_init_ex(model, 2); @@ -165,34 +154,32 @@ machine_at_5ax_init(const machine_t *model) pci_register_slot(0x00, PCI_CARD_NORTHBRIDGE, 0, 0, 0, 0); pci_register_slot(0x01, PCI_CARD_AGPBRIDGE, 1, 2, 0, 0); pci_register_slot(0x07, PCI_CARD_SOUTHBRIDGE, 1, 2, 3, 4); - pci_register_slot(0x0F, PCI_CARD_SOUTHBRIDGE, 1, 2, 3, 4); - pci_register_slot(0x03, PCI_CARD_SOUTHBRIDGE, 1, 2, 3, 4); - pci_register_slot(0x02, PCI_CARD_SOUTHBRIDGE, 1, 2, 3, 4); + pci_register_slot(0x0F, PCI_CARD_SOUTHBRIDGE_IDE, 1, 2, 3, 4); + pci_register_slot(0x03, PCI_CARD_SOUTHBRIDGE_PMU, 1, 2, 3, 4); + pci_register_slot(0x02, PCI_CARD_SOUTHBRIDGE_USB, 1, 2, 3, 4); pci_register_slot(0x08, PCI_CARD_NORMAL, 1, 2, 3, 4); pci_register_slot(0x09, PCI_CARD_NORMAL, 2, 3, 4, 1); pci_register_slot(0x0A, PCI_CARD_NORMAL, 3, 4, 1, 2); pci_register_slot(0x0B, PCI_CARD_NORMAL, 4, 1, 2, 3); pci_register_slot(0x0C, PCI_CARD_NORMAL, 1, 2, 3, 4); device_add(&ali1541_device); - device_add(&ali1543c_device); - device_add(&keyboard_ps2_ami_pci_device); + device_add(&ali1543c_device); /* +0 */ device_add(&sst_flash_29ee010_device); spd_register(SPD_TYPE_SDRAM, 0x7, 512); return ret; } - int machine_at_ax59pro_init(const machine_t *model) { int ret; ret = bios_load_linear("roms/machines/ax59pro/AX59P236.BIN", - 0x000c0000, 262144, 0); + 0x000c0000, 262144, 0); if (bios_only || !ret) - return ret; + return ret; machine_at_common_init_ex(model, 2); @@ -215,17 +202,16 @@ machine_at_ax59pro_init(const machine_t *model) return ret; } - int machine_at_mvp3_init(const machine_t *model) { int ret; ret = bios_load_linear("roms/machines/ficva503p/je4333.bin", - 0x000e0000, 131072, 0); + 0x000e0000, 131072, 0); if (bios_only || !ret) - return ret; + return ret; machine_at_common_init_ex(model, 2); @@ -247,17 +233,16 @@ machine_at_mvp3_init(const machine_t *model) return ret; } - int machine_at_ficva503a_init(const machine_t *model) { int ret; ret = bios_load_linear("roms/machines/ficva503a/jn4116.bin", - 0x000c0000, 262144, 0); + 0x000c0000, 262144, 0); if (bios_only || !ret) - return ret; + return ret; machine_at_common_init_ex(model, 2); @@ -277,25 +262,24 @@ machine_at_ficva503a_init(const machine_t *model) spd_register(SPD_TYPE_SDRAM, 0x7, 256); hwm_values.temperatures[0] += 2; /* CPU offset */ hwm_values.temperatures[1] += 2; /* System offset */ - hwm_values.temperatures[2] = 0; /* unused */ + hwm_values.temperatures[2] = 0; /* unused */ - if (sound_card_current == SOUND_INTERNAL) - device_add(&wm9701a_device); /* on daughtercard */ + if (sound_card_current[0] == SOUND_INTERNAL) + device_add(&wm9701a_device); /* on daughtercard */ return ret; } - int machine_at_5emapro_init(const machine_t *model) { int ret; ret = bios_load_linear("roms/machines/5emapro/5emo1aa2.bin", - 0x000e0000, 131072, 0); + 0x000e0000, 131072, 0); if (bios_only || !ret) - return ret; + return ret; machine_at_common_init_ex(model, 2); @@ -315,9 +299,9 @@ machine_at_5emapro_init(const machine_t *model) device_add(&sst_flash_39sf010_device); spd_register(SPD_TYPE_SDRAM, 0x7, 256); device_add(&via_vt82c686_hwm_device); /* fans: CPU1, Chassis; temperatures: CPU, System, unused */ - hwm_values.temperatures[0] += 2; /* CPU offset */ - hwm_values.temperatures[1] += 2; /* System offset */ - hwm_values.temperatures[2] = 0; /* unused */ + hwm_values.temperatures[0] += 2; /* CPU offset */ + hwm_values.temperatures[1] += 2; /* System offset */ + hwm_values.temperatures[2] = 0; /* unused */ return ret; } diff --git a/src/machine/m_at_t3100e.c b/src/machine/m_at_t3100e.c index 6e84a5832..e3e24cf2c 100644 --- a/src/machine/m_at_t3100e.c +++ b/src/machine/m_at_t3100e.c @@ -1,131 +1,131 @@ /* - * VARCem Virtual ARchaeological Computer EMulator. - * An emulator of (mostly) x86-based PC systems and devices, - * using the ISA,EISA,VLB,MCA and PCI system buses, roughly - * spanning the era between 1981 and 1995. + * 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 VARCem Project. + * This file is part of the 86Box distribution. * - * Implementation of the Toshiba T3100e. + * Implementation of the Toshiba T3100e. * - * The Toshiba 3100e is a 286-based portable. + * The Toshiba 3100e is a 286-based portable. * - * To bring up the BIOS setup screen hold down the 'Fn' key - * on booting. + * To bring up the BIOS setup screen hold down the 'Fn' key + * on booting. * - * Memory management - * ~~~~~~~~~~~~~~~~~ - * - * Motherboard memory is divided into: - * - Conventional memory: Either 512k or 640k - * - Upper memory: Either 512k or 384k, depending on - * amount of conventional memory. - * Upper memory can be used as EMS or XMS. - * - High memory: 0-4Mb, depending on RAM installed. - * The BIOS setup screen allows some or - * all of this to be used as EMS; the - * remainder is XMS. - * - * Additional memory (either EMS or XMS) can also be provided - * by ISA expansion cards. + * Memory management + * ~~~~~~~~~~~~~~~~~ * - * Under test in PCem, the BIOS will boot with up to 65368Kb - * of memory in total (16Mb less 16k). However it will give - * an error with RAM sizes above 8Mb, if any of the high - * memory is allocated as EMS, because the builtin EMS page - * registers can only access up to 8Mb. + * Motherboard memory is divided into: + * - Conventional memory: Either 512k or 640k + * - Upper memory: Either 512k or 384k, depending on + * amount of conventional memory. + * Upper memory can be used as EMS or XMS. + * - High memory: 0-4Mb, depending on RAM installed. + * The BIOS setup screen allows some or + * all of this to be used as EMS; the + * remainder is XMS. * - * Memory is controlled by writes to I/O port 8084h: - * Bit 7: Always 0 } - * Bit 6: Always 1 } These bits select which motherboard - * Bit 5: Always 0 } function to access. - * Bit 4: Set to treat upper RAM as XMS - * Bit 3: Enable external RAM boards? - * Bit 2: Set for 640k conventional memory, clear for 512k - * Bit 1: Enable RAM beyond 1Mb. - * Bit 0: Enable EMS. + * Additional memory (either EMS or XMS) can also be provided + * by ISA expansion cards. * - * The last value written to this port is saved at 0040:0093h, - * and in CMOS memory at offset 0x37. If the top bit of the - * CMOS byte is set, then high memory is being provided by - * an add-on card rather than the mainboard; accordingly, - * the BIOS will not allow high memory to be used as EMS. + * Under test in PCem, the BIOS will boot with up to 65368Kb + * of memory in total (16Mb less 16k). However it will give + * an error with RAM sizes above 8Mb, if any of the high + * memory is allocated as EMS, because the builtin EMS page + * registers can only access up to 8Mb. * - * EMS is controlled by 16 page registers: + * Memory is controlled by writes to I/O port 8084h: + * Bit 7: Always 0 } + * Bit 6: Always 1 } These bits select which motherboard + * Bit 5: Always 0 } function to access. + * Bit 4: Set to treat upper RAM as XMS + * Bit 3: Enable external RAM boards? + * Bit 2: Set for 640k conventional memory, clear for 512k + * Bit 1: Enable RAM beyond 1Mb. + * Bit 0: Enable EMS. * - * Page mapped at 0xD000 0xD400 0xD800 0xDC00 - * ------------------------------------------------------ - * Pages 0x00-0x7F 0x208 0x4208 0x8208 0xc208 - * Pages 0x80-0xFF 0x218 0x4218 0x8218 0xc218 - * Pages 0x100-0x17F 0x258 0x4258 0x8258 0xc258 - * Pages 0x180-0x1FF 0x268 0x4268 0x8268 0xc268 + * The last value written to this port is saved at 0040:0093h, + * and in CMOS memory at offset 0x37. If the top bit of the + * CMOS byte is set, then high memory is being provided by + * an add-on card rather than the mainboard; accordingly, + * the BIOS will not allow high memory to be used as EMS. * - * The value written has bit 7 set to enable EMS, reset to - * disable it. + * EMS is controlled by 16 page registers: * - * So: - * OUT 0x208, 0x80 will page in the first 16k page at 0xD0000. - * OUT 0x208, 0x00 will page out EMS, leaving nothing at 0xD0000. - * OUT 0x4208, 0x80 will page in the first 16k page at 0xD4000. - * OUT 0x218, 0x80 will page in the 129th 16k page at 0xD0000. - * etc. - * - * To use EMS from DOS, you will need the Toshiba EMS driver - * (TOSHEMM.ZIP). This supports the above system, plus further - * ranges of ports at 0x_2A8, 0x_2B8, 0x_2C8. + * Page mapped at 0xD000 0xD400 0xD800 0xDC00 + * ------------------------------------------------------ + * Pages 0x00-0x7F 0x208 0x4208 0x8208 0xc208 + * Pages 0x80-0xFF 0x218 0x4218 0x8218 0xc218 + * Pages 0x100-0x17F 0x258 0x4258 0x8258 0xc258 + * Pages 0x180-0x1FF 0x268 0x4268 0x8268 0xc268 * - * Features not implemented: - * > Four video fonts. - * > BIOS-controlled mapping of serial ports to IRQs. - * > Custom keyboard controller. This has a number of extra - * commands in the 0xB0-0xBC range, for such things as turbo - * on/off, and switching the keyboard between AT and PS/2 - * modes. Currently I have only implemented command 0xBB, - * so that self-test completes successfully. Commands include: + * The value written has bit 7 set to enable EMS, reset to + * disable it. * - * 0xB0: Turbo on - * 0xB1: Turbo off - * 0xB2: Internal display on? - * 0xB3: Internal display off? - * 0xB5: Get settings byte (bottom bit is color/mono setting) - * 0xB6: Set settings byte - * 0xB7: Behave as 101-key PS/2 keyboard - * 0xB8: Behave as 84-key AT keyboard - * 0xBB: Return a byte, bit 2 is Fn key state, other bits unknown. + * So: + * OUT 0x208, 0x80 will page in the first 16k page at 0xD0000. + * OUT 0x208, 0x00 will page out EMS, leaving nothing at 0xD0000. + * OUT 0x4208, 0x80 will page in the first 16k page at 0xD4000. + * OUT 0x218, 0x80 will page in the 129th 16k page at 0xD0000. + * etc. * - * The other main I/O port needed to POST is: - * 0x8084: System control. - * Top 3 bits give command, bottom 5 bits give parameters. - * 000 => set serial port IRQ / addresses - * bit 4: IRQ5 serial port base: 1 => 0x338, 0 => 0x3E8 - * bits 3, 2, 0 specify serial IRQs for COM1, COM2, COM3: - * 00 0 => 4, 3, 5 + * To use EMS from DOS, you will need the Toshiba EMS driver + * (TOSHEMM.ZIP). This supports the above system, plus further + * ranges of ports at 0x_2A8, 0x_2B8, 0x_2C8. + * + * Features not implemented: + * > Four video fonts. + * > BIOS-controlled mapping of serial ports to IRQs. + * > Custom keyboard controller. This has a number of extra + * commands in the 0xB0-0xBC range, for such things as turbo + * on/off, and switching the keyboard between AT and PS/2 + * modes. Currently I have only implemented command 0xBB, + * so that self-test completes successfully. Commands include: + * + * 0xB0: Turbo on + * 0xB1: Turbo off + * 0xB2: Internal display on? + * 0xB3: Internal display off? + * 0xB5: Get settings byte (bottom bit is color/mono setting) + * 0xB6: Set settings byte + * 0xB7: Behave as 101-key PS/2 keyboard + * 0xB8: Behave as 84-key AT keyboard + * 0xBB: Return a byte, bit 2 is Fn key state, other bits unknown. + * + * The other main I/O port needed to POST is: + * 0x8084: System control. + * Top 3 bits give command, bottom 5 bits give parameters. + * 000 => set serial port IRQ / addresses + * bit 4: IRQ5 serial port base: 1 => 0x338, 0 => 0x3E8 + * bits 3, 2, 0 specify serial IRQs for COM1, COM2, COM3: + * 00 0 => 4, 3, 5 * 00 1 => 4, 5, 3 * 01 0 => 3, 4, 5 * 01 1 => 3, 5, 4 * 10 0 => 4, -, 3 - * 10 1 => 3, -, 4 - * 010 => set memory mappings - * bit 4 set if upper RAM is XMS - * bit 3 enable add-on memory boards beyond 5Mb? - * bit 2 set for 640k sysram, clear for 512k sysram - * bit 1 enable mainboard XMS - * bit 0 enable mainboard EMS - * 100 => set parallel mode / LCD settings - * bit 4 set for bidirectional parallel port - * bit 3 set to disable internal CGA - * bit 2 set for single-pixel LCD font - * bits 0,1 for display font + * 10 1 => 3, -, 4 + * 010 => set memory mappings + * bit 4 set if upper RAM is XMS + * bit 3 enable add-on memory boards beyond 5Mb? + * bit 2 set for 640k sysram, clear for 512k sysram + * bit 1 enable mainboard XMS + * bit 0 enable mainboard EMS + * 100 => set parallel mode / LCD settings + * bit 4 set for bidirectional parallel port + * bit 3 set to disable internal CGA + * bit 2 set for single-pixel LCD font + * bits 0,1 for display font * * * - * Authors: Fred N. van Kempen, - * Miran Grca, - * Sarah Walker, + * Authors: Fred N. van Kempen, + * Miran Grca, + * John Elliott, * - * Copyright 2017,2018 Fred N. van Kempen. - * Copyright 2016-2018 Miran Grca. - * Copyright 2008-2018 Sarah Walker. + * Copyright 2017-2018 Fred N. van Kempen. + * Copyright 2016-2018 Miran Grca. + * Copyright 2008-2018 John Elliott. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -166,12 +166,11 @@ #include <86box/fdc_ext.h> #include <86box/machine.h> #include <86box/m_at_t3100e.h> +#include <86box/plat_unused.h> +extern uint8_t *ram; /* Physical RAM */ -extern uint8_t *ram; /* Physical RAM */ - -void at_init(); - +void at_init(void); /* The T3100e motherboard can (and does) dynamically reassign RAM between * conventional, XMS and EMS. This translates to monkeying with the mappings. @@ -179,631 +178,679 @@ void at_init(); extern mem_mapping_t base_mapping; -extern mem_mapping_t ram_low_mapping; /* This is to switch conventional RAM - * between 512k and 640k */ +extern mem_mapping_t ram_low_mapping; /* This is to switch conventional RAM + * between 512k and 640k */ -extern mem_mapping_t ram_mid_mapping; /* This will not be used */ +extern mem_mapping_t ram_mid_mapping; /* This will not be used */ -extern mem_mapping_t ram_high_mapping; /* This is RAM beyond 1Mb if any */ +extern mem_mapping_t ram_high_mapping; /* This is RAM beyond 1Mb if any */ extern uint8_t *ram; -static unsigned t3100e_ems_page_reg[] = -{ - 0x208, 0x4208, 0x8208, 0xc208, /* The first four map the first 2Mb */ - /* of RAM into the page frame */ - 0x218, 0x4218, 0x8218, 0xc218, /* The next four map the next 2Mb */ - /* of RAM */ - 0x258, 0x4258, 0x8258, 0xc258, /* and so on. */ - 0x268, 0x4268, 0x8268, 0xc268, +static unsigned t3100e_ems_page_reg[] = { + 0x208, + 0x4208, + 0x8208, + 0xc208, /* The first four map the first 2Mb */ + /* of RAM into the page frame */ + 0x218, + 0x4218, + 0x8218, + 0xc218, /* The next four map the next 2Mb */ + /* of RAM */ + 0x258, + 0x4258, + 0x8258, + 0xc258, /* and so on. */ + 0x268, + 0x4268, + 0x8268, + 0xc268, }; -struct t3100e_ems_regs -{ - uint8_t page[16]; - mem_mapping_t mapping[4]; - uint32_t page_exec[4]; /* Physical location of memory pages */ - uint32_t upper_base; /* Start of upper RAM */ - uint8_t upper_pages; /* Pages of EMS available from upper RAM */ - uint8_t upper_is_ems; /* Upper RAM is EMS? */ - mem_mapping_t upper_mapping; - uint8_t notify; /* Notification from keyboard controller */ - uint8_t turbo; /* 0 for 6MHz, else full speed */ - uint8_t mono; /* Emulates PC/AT 'mono' motherboard switch */ - /* Bit 0 is 0 for colour, 1 for mono */ +struct t3100e_ems_regs { + uint8_t page[16]; + mem_mapping_t mapping[4]; + uint32_t page_exec[4]; /* Physical location of memory pages */ + uint32_t upper_base; /* Start of upper RAM */ + uint8_t upper_pages; /* Pages of EMS available from upper RAM */ + uint8_t upper_is_ems; /* Upper RAM is EMS? */ + mem_mapping_t upper_mapping; + uint8_t notify; /* Notification from keyboard controller */ + uint8_t turbo; /* 0 for 6MHz, else full speed */ + uint8_t mono; /* Emulates PC/AT 'mono' motherboard switch */ + /* Bit 0 is 0 for colour, 1 for mono */ } t3100e_ems; -void t3100e_ems_out(uint16_t addr, uint8_t val, void *p); - +void t3100e_ems_out(uint16_t addr, uint8_t val, void *priv); #ifdef ENABLE_T3100E_LOG int t3100e_do_log = ENABLE_T3100E_LOG; - static void t3100e_log(const char *fmt, ...) { - va_list ap; + va_list ap; - if (t3100e_do_log) - { - va_start(ap, fmt); - pclog_ex(fmt, ap); - va_end(ap); - } + if (t3100e_do_log) { + va_start(ap, fmt); + pclog_ex(fmt, ap); + va_end(ap); + } } #else -#define t3100e_log(fmt, ...) +# define t3100e_log(fmt, ...) #endif - -/* Given a memory address (which ought to be in the page frame at 0xD0000), +/* Given a memory address (which ought to be in the page frame at 0xD0000), * which page does it relate to? */ -static int addr_to_page(uint32_t addr) +static int +addr_to_page(uint32_t addr) { - if ((addr & 0xF0000) == 0xD0000) - { - return ((addr >> 14) & 3); - } - return -1; + if ((addr & 0xF0000) == 0xD0000) { + return ((addr >> 14) & 3); + } + return -1; } -/* And vice versa: Given a page slot, which memory address does it +/* And vice versa: Given a page slot, which memory address does it * correspond to? */ -static uint32_t page_to_addr(int pg) +static uint32_t +page_to_addr(int pg) { - return 0xD0000 + ((pg & 3) * 16384); + return 0xD0000 + ((pg & 3) * 16384); } /* Given an EMS page ID, return its physical address in RAM. */ -uint32_t t3100e_ems_execaddr(struct t3100e_ems_regs *regs, - int pg, uint16_t val) +uint32_t +t3100e_ems_execaddr(struct t3100e_ems_regs *regs, + int pg, uint16_t val) { - uint32_t addr; + uint32_t addr; - if (!(val & 0x80)) return 0; /* Bit 7 reset => not mapped */ + if (!(val & 0x80)) + return 0; /* Bit 7 reset => not mapped */ - val &= 0x7F; - val += (0x80 * (pg >> 2)); /* The high bits of the register bank */ - /* are used to extend val to allow up */ - /* to 8Mb of EMS to be accessed */ + val &= 0x7F; + val += (0x80 * (pg >> 2)); /* The high bits of the register bank */ + /* are used to extend val to allow up */ + /* to 8Mb of EMS to be accessed */ - /* Is it in the upper memory range? */ - if (regs->upper_is_ems) - { - if (val < regs->upper_pages) - { - addr = regs->upper_base + 0x4000 * val; - return addr; - } - val -= regs->upper_pages; - } - /* Otherwise work down from the top of high RAM (so, the more EMS, - * the less XMS) */ - if ((val * 0x4000) + 0x100000 >= (mem_size * 1024)) - { - return 0; /* Not enough high RAM for this page */ - } - /* High RAM found */ - addr = (mem_size * 1024) - 0x4000 * (val + 1); + /* Is it in the upper memory range? */ + if (regs->upper_is_ems) { + if (val < regs->upper_pages) { + addr = regs->upper_base + 0x4000 * val; + return addr; + } + val -= regs->upper_pages; + } + /* Otherwise work down from the top of high RAM (so, the more EMS, + * the less XMS) */ + if ((val * 0x4000) + 0x100000 >= (mem_size * 1024)) { + return 0; /* Not enough high RAM for this page */ + } + /* High RAM found */ + addr = (mem_size * 1024) - 0x4000 * (val + 1); - return addr; + return addr; } - /* The registers governing the EMS ports are in rather a nonintuitive order */ -static int port_to_page(uint16_t addr) +static int +port_to_page(uint16_t addr) { - switch (addr) - { - case 0x208: return 0; - case 0x4208: return 1; - case 0x8208: return 2; - case 0xC208: return 3; - case 0x218: return 4; - case 0x4218: return 5; - case 0x8218: return 6; - case 0xC218: return 7; - case 0x258: return 8; - case 0x4258: return 9; - case 0x8258: return 10; - case 0xC258: return 11; - case 0x268: return 12; - case 0x4268: return 13; - case 0x8268: return 14; - case 0xC268: return 15; - } - return -1; + switch (addr) { + case 0x208: + return 0; + case 0x4208: + return 1; + case 0x8208: + return 2; + case 0xC208: + return 3; + case 0x218: + return 4; + case 0x4218: + return 5; + case 0x8218: + return 6; + case 0xC218: + return 7; + case 0x258: + return 8; + case 0x4258: + return 9; + case 0x8258: + return 10; + case 0xC258: + return 11; + case 0x268: + return 12; + case 0x4268: + return 13; + case 0x8268: + return 14; + case 0xC268: + return 15; + + default: + break; + } + return -1; } -/* Used to dump the memory mapping table, for debugging -void dump_mappings() +/* Used to dump the memory mapping table, for debugging */ +#if 0 +void dump_mappings(void) { - mem_mapping_t *mm = base_mapping.next; + mem_mapping_t *mm = base_mapping.next; - if (!t3100e_log) return; - while (mm) - { - const char *name = ""; - uint32_t offset = (uint32_t)(mm->exec - ram); + if (!t3100e_log) return; + while (mm) + { + const char *name = ""; + uint32_t offset = (uint32_t)(mm->exec - ram); - if (mm == &ram_low_mapping ) name = "LOW "; - if (mm == &ram_mid_mapping ) name = "MID "; - if (mm == &ram_high_mapping) name = "HIGH"; - if (mm == &t3100e_ems.upper_mapping) name = "UPPR"; - if (mm == &t3100e_ems.mapping[0]) - { - name = "EMS0"; - offset = t3100e_ems.page_exec[0]; - } - if (mm == &t3100e_ems.mapping[1]) - { - name = "EMS1"; - offset = t3100e_ems.page_exec[1]; - } - if (mm == &t3100e_ems.mapping[2]) - { - name = "EMS2"; - offset = t3100e_ems.page_exec[2]; - } - if (mm == &t3100e_ems.mapping[3]) - { - name = "EMS3"; - offset = t3100e_ems.page_exec[3]; - } + if (mm == &ram_low_mapping ) name = "LOW "; + if (mm == &ram_mid_mapping ) name = "MID "; + if (mm == &ram_high_mapping) name = "HIGH"; + if (mm == &t3100e_ems.upper_mapping) name = "UPPR"; + if (mm == &t3100e_ems.mapping[0]) + { + name = "EMS0"; + offset = t3100e_ems.page_exec[0]; + } + if (mm == &t3100e_ems.mapping[1]) + { + name = "EMS1"; + offset = t3100e_ems.page_exec[1]; + } + if (mm == &t3100e_ems.mapping[2]) + { + name = "EMS2"; + offset = t3100e_ems.page_exec[2]; + } + if (mm == &t3100e_ems.mapping[3]) + { + name = "EMS3"; + offset = t3100e_ems.page_exec[3]; + } - t3100e_log(" %p | base=%05x size=%05x %c @ %06x %s\n", mm, - mm->base, mm->size, mm->enable ? 'Y' : 'N', - offset, name); + t3100e_log(" %p | base=%05x size=%05x %c @ %06x %s\n", mm, + mm->base, mm->size, mm->enable ? 'Y' : 'N', + offset, name); - mm = mm->next; - } -}*/ - -void t3100e_map_ram(uint8_t val) -{ - int n; - int32_t upper_len; - -#ifdef ENABLE_T3100E_LOG - t3100e_log("OUT 0x8084, %02x [ set memory mapping :", val | 0x40); - if (val & 1) t3100e_log("ENABLE_EMS "); - if (val & 2) t3100e_log("ENABLE_XMS "); - if (val & 4) t3100e_log("640K "); - if (val & 8) t3100e_log("X8X "); - if (val & 16) t3100e_log("UPPER_IS_XMS "); - t3100e_log("\n"); + mm = mm->next; + } +} #endif - /* Bit 2 controls size of conventional memory */ - if (val & 4) - { - t3100e_ems.upper_base = 0xA0000; - t3100e_ems.upper_pages = 24; - } - else - { - t3100e_ems.upper_base = 0x80000; - t3100e_ems.upper_pages = 32; - } - upper_len = t3100e_ems.upper_pages * 16384; - - mem_mapping_set_addr(&ram_low_mapping, 0, t3100e_ems.upper_base); - /* Bit 0 set if upper RAM is EMS */ - t3100e_ems.upper_is_ems = (val & 1); - - /* Bit 1 set if high RAM is enabled */ - if (val & 2) - { - mem_mapping_enable(&ram_high_mapping); - } - else - { - mem_mapping_disable(&ram_high_mapping); - } - - /* Bit 4 set if upper RAM is mapped to high memory - * (and bit 1 set if XMS enabled) */ - if ((val & 0x12) == 0x12) - { - mem_mapping_set_addr(&t3100e_ems.upper_mapping, - mem_size * 1024, - upper_len); - mem_mapping_enable(&t3100e_ems.upper_mapping); - mem_mapping_set_exec(&t3100e_ems.upper_mapping, ram + t3100e_ems.upper_base); - } - else - { - mem_mapping_disable(&t3100e_ems.upper_mapping); - } - /* Recalculate EMS mappings */ - for (n = 0; n < 4; n++) - { - t3100e_ems_out(t3100e_ems_page_reg[n], t3100e_ems.page[n], - &t3100e_ems); - } - - //dump_mappings(); -} - - -void t3100e_notify_set(uint8_t value) +void +t3100e_map_ram(uint8_t val) { - t3100e_ems.notify = value; + int32_t upper_len; + +#ifdef ENABLE_T3100E_LOG + t3100e_log("OUT 0x8084, %02x [ set memory mapping :", val | 0x40); + if (val & 1) + t3100e_log("ENABLE_EMS "); + if (val & 2) + t3100e_log("ENABLE_XMS "); + if (val & 4) + t3100e_log("640K "); + if (val & 8) + t3100e_log("X8X "); + if (val & 16) + t3100e_log("UPPER_IS_XMS "); + t3100e_log("\n"); +#endif + + /* Bit 2 controls size of conventional memory */ + if (val & 4) { + t3100e_ems.upper_base = 0xA0000; + t3100e_ems.upper_pages = 24; + } else { + t3100e_ems.upper_base = 0x80000; + t3100e_ems.upper_pages = 32; + } + upper_len = t3100e_ems.upper_pages * 16384; + + mem_mapping_set_addr(&ram_low_mapping, 0, t3100e_ems.upper_base); + /* Bit 0 set if upper RAM is EMS */ + t3100e_ems.upper_is_ems = (val & 1); + + /* Bit 1 set if high RAM is enabled */ + if (val & 2) { + mem_mapping_enable(&ram_high_mapping); + } else { + mem_mapping_disable(&ram_high_mapping); + } + + /* Bit 4 set if upper RAM is mapped to high memory + * (and bit 1 set if XMS enabled) */ + if ((val & 0x12) == 0x12) { + mem_mapping_set_addr(&t3100e_ems.upper_mapping, + mem_size * 1024, + upper_len); + mem_mapping_enable(&t3100e_ems.upper_mapping); + mem_mapping_set_exec(&t3100e_ems.upper_mapping, ram + t3100e_ems.upper_base); + } else { + mem_mapping_disable(&t3100e_ems.upper_mapping); + } + /* Recalculate EMS mappings */ + for (uint8_t n = 0; n < 4; n++) { + t3100e_ems_out(t3100e_ems_page_reg[n], t3100e_ems.page[n], + &t3100e_ems); + } + +#if 0 + dump_mappings(); +#endif } -void t3100e_mono_set(uint8_t value) +void +t3100e_notify_set(uint8_t value) { - t3100e_ems.mono = value; + t3100e_ems.notify = value; } -uint8_t t3100e_mono_get(void) +void +t3100e_mono_set(uint8_t value) { - return t3100e_ems.mono; + t3100e_ems.mono = value; } -void t3100e_turbo_set(uint8_t value) +uint8_t +t3100e_mono_get(void) { - t3100e_ems.turbo = value; - if (!value) - { - cpu_dynamic_switch(0); /* 286/6 */ - } - else - { - cpu_dynamic_switch(cpu); - } + return t3100e_ems.mono; } - - -uint8_t t3100e_sys_in(uint16_t addr, void *p) +void +t3100e_turbo_set(uint8_t value) { - struct t3100e_ems_regs *regs = (struct t3100e_ems_regs *)p; - - /* The low 4 bits always seem to be 0x0C. The high 4 are a - * notification sent by the keyboard controller when it detects - * an [Fn] key combination */ - t3100e_log("IN 0x8084\n"); - return 0x0C | (regs->notify << 4); + t3100e_ems.turbo = value; + if (!value) { + cpu_dynamic_switch(0); /* 286/6 */ + } else { + cpu_dynamic_switch(cpu); + } } +uint8_t +t3100e_sys_in(UNUSED(uint16_t addr), void *priv) +{ + const struct t3100e_ems_regs *regs = (struct t3100e_ems_regs *) priv; + /* The low 4 bits always seem to be 0x0C. The high 4 are a + * notification sent by the keyboard controller when it detects + * an [Fn] key combination */ + t3100e_log("IN 0x8084\n"); + return 0x0C | (regs->notify << 4); +} /* Handle writes to the T3100e system control port at 0x8084 */ -void t3100e_sys_out(uint16_t addr, uint8_t val, void *p) +void +t3100e_sys_out(UNUSED(uint16_t addr), uint8_t val, UNUSED(void *priv)) { -// struct t3100e_ems_regs *regs = (struct t3100e_ems_regs *)p; +#if 0 + struct t3100e_ems_regs *regs = (struct t3100e_ems_regs *) priv; +#endif - switch (val & 0xE0) - { - case 0x00: /* Set serial port IRQs. Not implemented */ - t3100e_log("OUT 0x8084, %02x [ set serial port IRQs]\n", val); - break; - case 0x40: /* Set RAM mappings. */ - t3100e_map_ram(val & 0x1F); - break; + switch (val & 0xE0) { + case 0x00: /* Set serial port IRQs. Not implemented */ + t3100e_log("OUT 0x8084, %02x [ set serial port IRQs]\n", val); + break; + case 0x40: /* Set RAM mappings. */ + t3100e_map_ram(val & 0x1F); + break; - case 0x80: /* Set video options. */ - t3100e_video_options_set(val & 0x1F); break; + case 0x80: /* Set video options. */ + t3100e_video_options_set(val & 0x1F); + break; - /* Other options not implemented. */ - default: t3100e_log("OUT 0x8084, %02x\n", val); break; - } + /* Other options not implemented. */ + default: + t3100e_log("OUT 0x8084, %02x\n", val); + break; + } } - -uint8_t t3100e_config_get(void) +uint8_t +t3100e_config_get(void) { -/* The byte returned: - Bit 7: Set if internal plasma display enabled - Bit 6: Set if running at 6MHz, clear at full speed - Bit 5: Always 1? - Bit 4: Set if the FD2MB jumper is present (internal floppy is ?tri-mode) - Bit 3: Clear if the FD2 jumper is present (two internal floppies) - Bit 2: Set if the internal drive is A:, clear if B: - Bit 1: Set if the parallel port is configured as a floppy connector - for the second drive. - Bit 0: Set if the F2HD jumper is present (internal floppy is 720k) - */ - uint8_t value = 0x28; /* Start with bits 5 and 3 set. */ + /* The byte returned: + Bit 7: Set if internal plasma display enabled + Bit 6: Set if running at 6MHz, clear at full speed + Bit 5: Always 1? + Bit 4: Set if the FD2MB jumper is present (internal floppy is ?tri-mode) + Bit 3: Clear if the FD2 jumper is present (two internal floppies) + Bit 2: Set if the internal drive is A:, clear if B: + Bit 1: Set if the parallel port is configured as a floppy connector + for the second drive. + Bit 0: Set if the F2HD jumper is present (internal floppy is 720k) + */ + uint8_t value = 0x28; /* Start with bits 5 and 3 set. */ - int type_a = fdd_get_type(0); - int type_b = fdd_get_type(1); - int prt_switch; /* External drive type: 0=> none, 1=>A, 2=>B */ + int type_a = fdd_get_type(0); + int type_b = fdd_get_type(1); + int prt_switch; /* External drive type: 0=> none, 1=>A, 2=>B */ -/* Get display setting */ - if (t3100e_display_get()) value |= 0x80; - if (!t3100e_ems.turbo) value |= 0x40; + /* Get display setting */ + if (t3100e_display_get()) + value |= 0x80; + if (!t3100e_ems.turbo) + value |= 0x40; -/* Try to determine the floppy types.*/ + /* Try to determine the floppy types.*/ - prt_switch = (type_b ? 2 : 0); - switch(type_a) - { -/* Since a T3100e cannot have an internal 5.25" drive, mark 5.25" A: drive as - * being external, and set the internal type based on type_b. */ - case 1: /* 360k */ - case 2: /* 1.2Mb */ - case 3: /* 1.2Mb RPMx2*/ - prt_switch = 1; /* External drive is A: */ - switch (type_b) - { - case 1: /* 360k */ - case 4: value |= 1; break; /* 720k */ - case 6: value |= 0x10; break; /* Tri-mode */ - /* All others will be treated as 1.4M */ - } - break; - case 4: value |= 0x01; /* 720k */ - if (type_a == type_b) - { - value &= (~8); /* Two internal drives */ - prt_switch = 0; /* No external drive */ - } - break; - case 5: /* 1.4M */ - case 7: /* 2.8M */ - if (type_a == type_b) - { - value &= (~8); /* Two internal drives */ - prt_switch = 0; /* No external drive */ - } - break; - case 6: /* 3-mode */ - value |= 0x10; - if (type_a == type_b) - { - value &= (~8); /* Two internal drives */ - prt_switch = 0; /* No external drive */ - } - break; - } /* End switch */ - switch (prt_switch) - { - case 0: value |= 4; break; /* No external floppy */ - case 1: value |= 2; break; /* External floppy is A: */ - case 2: value |= 6; break; /* External floppy is B: */ - } - return value; + prt_switch = (type_b ? 2 : 0); + switch (type_a) { + /* Since a T3100e cannot have an internal 5.25" drive, mark 5.25" A: drive as + * being external, and set the internal type based on type_b. */ + case 1: /* 360k */ + case 2: /* 1.2Mb */ + case 3: /* 1.2Mb RPMx2*/ + prt_switch = 1; /* External drive is A: */ + switch (type_b) { + case 1: /* 360k */ + case 4: + value |= 1; + break; /* 720k */ + case 6: + value |= 0x10; + break; /* Tri-mode */ + /* All others will be treated as 1.4M */ + + default: + break; + } + break; + case 4: + value |= 0x01; /* 720k */ + if (type_a == type_b) { + value &= (~8); /* Two internal drives */ + prt_switch = 0; /* No external drive */ + } + break; + case 5: /* 1.4M */ + case 7: /* 2.8M */ + if (type_a == type_b) { + value &= (~8); /* Two internal drives */ + prt_switch = 0; /* No external drive */ + } + break; + case 6: /* 3-mode */ + value |= 0x10; + if (type_a == type_b) { + value &= (~8); /* Two internal drives */ + prt_switch = 0; /* No external drive */ + } + break; + + default: + break; + } /* End switch */ + + switch (prt_switch) { + case 0: + value |= 4; + break; /* No external floppy */ + case 1: + value |= 2; + break; /* External floppy is A: */ + case 2: + value |= 6; + break; /* External floppy is B: */ + + default: + break; + } + return value; } - /* Read EMS page register */ -uint8_t t3100e_ems_in(uint16_t addr, void *p) +uint8_t +t3100e_ems_in(uint16_t addr, void *priv) { - struct t3100e_ems_regs *regs = (struct t3100e_ems_regs *)p; - - int page = port_to_page(addr); - if (page >= 0) - return regs->page[page]; - else { - fatal("t3100e_ems_in(): invalid address"); - return 0xff; - } + const struct t3100e_ems_regs *regs = (struct t3100e_ems_regs *) priv; + + int page = port_to_page(addr); + if (page >= 0) + return regs->page[page]; + else { + fatal("t3100e_ems_in(): invalid address"); + return 0xff; + } } /* Write EMS page register */ -void t3100e_ems_out(uint16_t addr, uint8_t val, void *p) +void +t3100e_ems_out(uint16_t addr, uint8_t val, void *priv) { - struct t3100e_ems_regs *regs = (struct t3100e_ems_regs *)p; - int pg = port_to_page(addr); + struct t3100e_ems_regs *regs = (struct t3100e_ems_regs *) priv; + int pg = port_to_page(addr); - if (pg == -1) - return; + if (pg == -1) + return; - regs->page_exec[pg & 3] = t3100e_ems_execaddr(regs, pg, val); - t3100e_log("EMS: page %d %02x -> %02x [%06x]\n", - pg, regs->page[pg], val, regs->page_exec[pg & 3]); - regs->page[pg] = val; + regs->page_exec[pg & 3] = t3100e_ems_execaddr(regs, pg, val); + t3100e_log("EMS: page %d %02x -> %02x [%06x]\n", + pg, regs->page[pg], val, regs->page_exec[pg & 3]); + regs->page[pg] = val; - pg &= 3; -/* Bit 7 set if page is enabled, reset if page is disabled */ - if (regs->page_exec[pg]) - { - t3100e_log("Enabling EMS RAM at %05x\n", - page_to_addr(pg)); - mem_mapping_enable(®s->mapping[pg]); - mem_mapping_set_exec(®s->mapping[pg], ram + regs->page_exec[pg]); - } - else - { - t3100e_log("Disabling EMS RAM at %05x\n", - page_to_addr(pg)); - mem_mapping_disable(®s->mapping[pg]); - } + pg &= 3; + /* Bit 7 set if page is enabled, reset if page is disabled */ + if (regs->page_exec[pg]) { + t3100e_log("Enabling EMS RAM at %05x\n", + page_to_addr(pg)); + mem_mapping_enable(®s->mapping[pg]); + mem_mapping_set_exec(®s->mapping[pg], ram + regs->page_exec[pg]); + } else { + t3100e_log("Disabling EMS RAM at %05x\n", + page_to_addr(pg)); + mem_mapping_disable(®s->mapping[pg]); + } } - /* Read RAM in the EMS page frame */ -static uint8_t ems_read_ram(uint32_t addr, void *priv) +static uint8_t +ems_read_ram(uint32_t addr, void *priv) { - struct t3100e_ems_regs *regs = (struct t3100e_ems_regs *)priv; - int pg = addr_to_page(addr); + const struct t3100e_ems_regs *regs = (struct t3100e_ems_regs *) priv; + int pg = addr_to_page(addr); - if (pg < 0) return 0xFF; - addr = regs->page_exec[pg] + (addr & 0x3FFF); - return ram[addr]; + if (pg < 0) + return 0xFF; + addr = regs->page_exec[pg] + (addr & 0x3FFF); + return ram[addr]; } - - - -static uint16_t ems_read_ramw(uint32_t addr, void *priv) +static uint16_t +ems_read_ramw(uint32_t addr, void *priv) { - struct t3100e_ems_regs *regs = (struct t3100e_ems_regs *)priv; - int pg = addr_to_page(addr); + const struct t3100e_ems_regs *regs = (struct t3100e_ems_regs *) priv; + int pg = addr_to_page(addr); - if (pg < 0) return 0xFFFF; - //t3100e_log("ems_read_ramw addr=%05x ", addr); - addr = regs->page_exec[pg] + (addr & 0x3FFF); - //t3100e_log("-> %06x val=%04x\n", addr, *(uint16_t *)&ram[addr]); - return *(uint16_t *)&ram[addr]; + if (pg < 0) + return 0xFFFF; +#if 0 + t3100e_log("ems_read_ramw addr=%05x ", addr); +#endif + addr = regs->page_exec[pg] + (addr & 0x3FFF); +#if 0 + // t3100e_log("-> %06x val=%04x\n", addr, *(uint16_t *) &ram[addr]); +#endif + return *(uint16_t *) &ram[addr]; } - -static uint32_t ems_read_raml(uint32_t addr, void *priv) +static uint32_t +ems_read_raml(uint32_t addr, void *priv) { - struct t3100e_ems_regs *regs = (struct t3100e_ems_regs *)priv; - int pg = addr_to_page(addr); + const struct t3100e_ems_regs *regs = (struct t3100e_ems_regs *) priv; + int pg = addr_to_page(addr); - if (pg < 0) return 0xFFFFFFFF; - addr = regs->page_exec[pg] + (addr & 0x3FFF); - return *(uint32_t *)&ram[addr]; + if (pg < 0) + return 0xFFFFFFFF; + addr = regs->page_exec[pg] + (addr & 0x3FFF); + return *(uint32_t *) &ram[addr]; } /* Write RAM in the EMS page frame */ -static void ems_write_ram(uint32_t addr, uint8_t val, void *priv) +static void +ems_write_ram(uint32_t addr, uint8_t val, void *priv) { - struct t3100e_ems_regs *regs = (struct t3100e_ems_regs *)priv; - int pg = addr_to_page(addr); + const struct t3100e_ems_regs *regs = (struct t3100e_ems_regs *) priv; + int pg = addr_to_page(addr); - if (pg < 0) return; - addr = regs->page_exec[pg] + (addr & 0x3FFF); - ram[addr] = val; + if (pg < 0) + return; + addr = regs->page_exec[pg] + (addr & 0x3FFF); + ram[addr] = val; } - -static void ems_write_ramw(uint32_t addr, uint16_t val, void *priv) +static void +ems_write_ramw(uint32_t addr, uint16_t val, void *priv) { - struct t3100e_ems_regs *regs = (struct t3100e_ems_regs *)priv; - int pg = addr_to_page(addr); + const struct t3100e_ems_regs *regs = (struct t3100e_ems_regs *) priv; + int pg = addr_to_page(addr); - if (pg < 0) return; - //t3100e_log("ems_write_ramw addr=%05x ", addr); - addr = regs->page_exec[pg] + (addr & 0x3FFF); - //t3100e_log("-> %06x val=%04x\n", addr, val); + if (pg < 0) + return; +#if 0 + t3100e_log("ems_write_ramw addr=%05x ", addr); +#endif + addr = regs->page_exec[pg] + (addr & 0x3FFF); +#if 0 + t3100e_log("-> %06x val=%04x\n", addr, val); +#endif - *(uint16_t *)&ram[addr] = val; + *(uint16_t *) &ram[addr] = val; } - -static void ems_write_raml(uint32_t addr, uint32_t val, void *priv) +static void +ems_write_raml(uint32_t addr, uint32_t val, void *priv) { - struct t3100e_ems_regs *regs = (struct t3100e_ems_regs *)priv; - int pg = addr_to_page(addr); + const struct t3100e_ems_regs *regs = (struct t3100e_ems_regs *) priv; + int pg = addr_to_page(addr); - if (pg < 0) return; - addr = regs->page_exec[pg] + (addr & 0x3FFF); - *(uint32_t *)&ram[addr] = val; + if (pg < 0) + return; + addr = regs->page_exec[pg] + (addr & 0x3FFF); + *(uint32_t *) &ram[addr] = val; } - - -/* Read RAM in the upper area. This is basically what the 'remapped' +/* Read RAM in the upper area. This is basically what the 'remapped' * mapping in mem.c does, except that the upper area can move around */ -static uint8_t upper_read_ram(uint32_t addr, void *priv) +static uint8_t +upper_read_ram(uint32_t addr, void *priv) { - struct t3100e_ems_regs *regs = (struct t3100e_ems_regs *)priv; + const struct t3100e_ems_regs *regs = (struct t3100e_ems_regs *) priv; - addr = (addr - (1024 * mem_size)) + regs->upper_base; - return ram[addr]; + addr = (addr - (1024 * mem_size)) + regs->upper_base; + return ram[addr]; } -static uint16_t upper_read_ramw(uint32_t addr, void *priv) +static uint16_t +upper_read_ramw(uint32_t addr, void *priv) { - struct t3100e_ems_regs *regs = (struct t3100e_ems_regs *)priv; + const struct t3100e_ems_regs *regs = (struct t3100e_ems_regs *) priv; - addr = (addr - (1024 * mem_size)) + regs->upper_base; - return *(uint16_t *)&ram[addr]; + addr = (addr - (1024 * mem_size)) + regs->upper_base; + return *(uint16_t *) &ram[addr]; } -static uint32_t upper_read_raml(uint32_t addr, void *priv) +static uint32_t +upper_read_raml(uint32_t addr, void *priv) { - struct t3100e_ems_regs *regs = (struct t3100e_ems_regs *)priv; + const struct t3100e_ems_regs *regs = (struct t3100e_ems_regs *) priv; - addr = (addr - (1024 * mem_size)) + regs->upper_base; - return *(uint32_t *)&ram[addr]; + addr = (addr - (1024 * mem_size)) + regs->upper_base; + return *(uint32_t *) &ram[addr]; } - -static void upper_write_ram(uint32_t addr, uint8_t val, void *priv) +static void +upper_write_ram(uint32_t addr, uint8_t val, void *priv) { - struct t3100e_ems_regs *regs = (struct t3100e_ems_regs *)priv; + const struct t3100e_ems_regs *regs = (struct t3100e_ems_regs *) priv; - addr = (addr - (1024 * mem_size)) + regs->upper_base; - ram[addr] = val; + addr = (addr - (1024 * mem_size)) + regs->upper_base; + ram[addr] = val; } - -static void upper_write_ramw(uint32_t addr, uint16_t val, void *priv) +static void +upper_write_ramw(uint32_t addr, uint16_t val, void *priv) { - struct t3100e_ems_regs *regs = (struct t3100e_ems_regs *)priv; + const struct t3100e_ems_regs *regs = (struct t3100e_ems_regs *) priv; - addr = (addr - (1024 * mem_size)) + regs->upper_base; - *(uint16_t *)&ram[addr] = val; + addr = (addr - (1024 * mem_size)) + regs->upper_base; + *(uint16_t *) &ram[addr] = val; } - - -static void upper_write_raml(uint32_t addr, uint32_t val, void *priv) +static void +upper_write_raml(uint32_t addr, uint32_t val, void *priv) { - struct t3100e_ems_regs *regs = (struct t3100e_ems_regs *)priv; + const struct t3100e_ems_regs *regs = (struct t3100e_ems_regs *) priv; - addr = (addr - (1024 * mem_size)) + regs->upper_base; - *(uint32_t *)&ram[addr] = val; + addr = (addr - (1024 * mem_size)) + regs->upper_base; + *(uint32_t *) &ram[addr] = val; } - - - -int machine_at_t3100e_init(const machine_t *model) +int +machine_at_t3100e_init(const machine_t *model) { - int ret; + int ret; - ret = bios_load_linear("roms/machines/t3100e/t3100e.rom", - 0x000f0000, 65536, 0); + ret = bios_load_linear("roms/machines/t3100e/t3100e.rom", + 0x000f0000, 65536, 0); - if (bios_only || !ret) - return ret; + if (bios_only || !ret) + return ret; - int pg; + int pg; - memset(&t3100e_ems, 0, sizeof(t3100e_ems)); - - machine_at_common_ide_init(model); + memset(&t3100e_ems, 0, sizeof(t3100e_ems)); - device_add(&keyboard_at_toshiba_device); + machine_at_common_ide_init(model); - if (fdc_type == FDC_INTERNAL) - { - device_add(&fdc_at_device); - } - - /* Hook up system control port */ - io_sethandler(0x8084, 0x0001, - t3100e_sys_in, NULL, NULL, - t3100e_sys_out, NULL, NULL, &t3100e_ems); + device_add(&keyboard_at_toshiba_device); - /* Start monitoring all 16 EMS registers */ - for (pg = 0; pg < 16; pg++) - { - io_sethandler(t3100e_ems_page_reg[pg], 0x0001, - t3100e_ems_in, NULL, NULL, - t3100e_ems_out, NULL, NULL, &t3100e_ems); - } + if (fdc_type == FDC_INTERNAL) { + device_add(&fdc_at_device); + } - /* Map the EMS page frame */ - for (pg = 0; pg < 4; pg++) - { - t3100e_log("Adding memory map at %x for page %d\n", page_to_addr(pg), pg); - mem_mapping_add(&t3100e_ems.mapping[pg], - page_to_addr(pg), 16384, - ems_read_ram, ems_read_ramw, ems_read_raml, - ems_write_ram, ems_write_ramw, ems_write_raml, - NULL, MEM_MAPPING_EXTERNAL, - &t3100e_ems); - /* Start them all off disabled */ - mem_mapping_disable(&t3100e_ems.mapping[pg]); - } - /* Mapping for upper RAM when in use as XMS*/ - mem_mapping_add(&t3100e_ems.upper_mapping, mem_size * 1024, 384 * 1024, - upper_read_ram, upper_read_ramw, upper_read_raml, - upper_write_ram, upper_write_ramw, upper_write_raml, - NULL, MEM_MAPPING_INTERNAL, &t3100e_ems); - mem_mapping_disable(&t3100e_ems.upper_mapping); + /* Hook up system control port */ + io_sethandler(0x8084, 0x0001, + t3100e_sys_in, NULL, NULL, + t3100e_sys_out, NULL, NULL, &t3100e_ems); - device_add(&t3100e_device); + /* Start monitoring all 16 EMS registers */ + for (pg = 0; pg < 16; pg++) { + io_sethandler(t3100e_ems_page_reg[pg], 0x0001, + t3100e_ems_in, NULL, NULL, + t3100e_ems_out, NULL, NULL, &t3100e_ems); + } - return ret; + /* Map the EMS page frame */ + for (pg = 0; pg < 4; pg++) { + t3100e_log("Adding memory map at %x for page %d\n", page_to_addr(pg), pg); + mem_mapping_add(&t3100e_ems.mapping[pg], + page_to_addr(pg), 16384, + ems_read_ram, ems_read_ramw, ems_read_raml, + ems_write_ram, ems_write_ramw, ems_write_raml, + NULL, MEM_MAPPING_EXTERNAL, + &t3100e_ems); + /* Start them all off disabled */ + mem_mapping_disable(&t3100e_ems.mapping[pg]); + } + /* Mapping for upper RAM when in use as XMS*/ + mem_mapping_add(&t3100e_ems.upper_mapping, mem_size * 1024, 384 * 1024, + upper_read_ram, upper_read_ramw, upper_read_raml, + upper_write_ram, upper_write_ramw, upper_write_raml, + NULL, MEM_MAPPING_INTERNAL, &t3100e_ems); + mem_mapping_disable(&t3100e_ems.upper_mapping); + + device_add(&t3100e_device); + + return ret; } diff --git a/src/machine/m_at_t3100e_vid.c b/src/machine/m_at_t3100e_vid.c index 0367b28f2..50c9ec05a 100644 --- a/src/machine/m_at_t3100e_vid.c +++ b/src/machine/m_at_t3100e_vid.c @@ -1,36 +1,36 @@ /* - * VARCem Virtual ARchaeological Computer EMulator. - * An emulator of (mostly) x86-based PC systems and devices, - * using the ISA,EISA,VLB,MCA and PCI system buses, roughly - * spanning the era between 1981 and 1995. + * 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 VARCem Project. + * This file is part of the 86Box distribution. * - * Implementation of the Toshiba 3100e plasma display. - * This display has a fixed 640x400 resolution. + * Implementation of the Toshiba 3100e plasma display. + * This display has a fixed 640x400 resolution. * - * T3100e CRTC regs (from the ROM): + * T3100e CRTC regs (from the ROM): * - * Selecting a character height of 3 seems to be sufficient to - * convert the 640x200 graphics mode to 640x400 (and, by - * analogy, 320x200 to 320x400). - * - * Horiz-----> Vert------> I ch - * 38 28 2D 0A 1F 06 19 1C 02 07 06 07 CO40 - * 71 50 5A 0A 1F 06 19 1C 02 07 06 07 CO80 - * 38 28 2D 0A 7F 06 64 70 02 01 06 07 Graphics - * 61 50 52 0F 19 06 19 19 02 0D 0B 0C MONO - * 2D 28 22 0A 67 00 64 67 02 03 06 07 640x400 + * Selecting a character height of 3 seems to be sufficient to + * convert the 640x200 graphics mode to 640x400 (and, by + * analogy, 320x200 to 320x400). + * + * Horiz-----> Vert------> I ch + * 38 28 2D 0A 1F 06 19 1C 02 07 06 07 CO40 + * 71 50 5A 0A 1F 06 19 1C 02 07 06 07 CO80 + * 38 28 2D 0A 7F 06 64 70 02 01 06 07 Graphics + * 61 50 52 0F 19 06 19 19 02 0D 0B 0C MONO + * 2D 28 22 0A 67 00 64 67 02 03 06 07 640x400 * * * - * Authors: Fred N. van Kempen, - * Miran Grca, - * Sarah Walker, + * Authors: Fred N. van Kempen, + * Miran Grca, + * John Elliott, * - * Copyright 2017-2019 Fred N. van Kempen. - * Copyright 2016-2019 Miran Grca. - * Copyright 2008-2019 Sarah Walker. + * Copyright 2017-2019 Fred N. van Kempen. + * Copyright 2016-2019 Miran Grca. + * Copyright 2008-2019 John Elliott. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -66,18 +66,18 @@ #include <86box/video.h> #include <86box/vid_cga.h> #include <86box/m_at_t3100e.h> - +#include <86box/plat_unused.h> #define T3100E_XSIZE 640 #define T3100E_YSIZE 400 /*Very rough estimate*/ -#define VID_CLOCK (double)(651 * 416 * 60) - +#define VID_CLOCK (double) (651 * 416 * 60) /* Mapping of attributes to colours */ -static uint32_t amber, black; -static uint8_t boldcols[256]; /* Which attributes use the bold font */ +static uint32_t amber; +static uint32_t black; +static uint8_t boldcols[256]; /* Which attributes use the bold font */ static uint32_t blinkcols[256][2]; static uint32_t normcols[256][2]; @@ -86,687 +86,633 @@ static uint32_t normcols[256][2]; * * Bit 3: Disable built-in video (for add-on card) * Bit 2: Thin font - * Bits 0,1: Font set (not currently implemented) + * Bits 0,1: Font set (not currently implemented) */ static uint8_t st_video_options; -static int8_t st_display_internal = -1; +static int8_t st_display_internal = -1; -void t3100e_video_options_set(uint8_t options) +void +t3100e_video_options_set(uint8_t options) { - st_video_options = options; + st_video_options = options; } -void t3100e_display_set(uint8_t internal) +void +t3100e_display_set(uint8_t internal) { - st_display_internal = internal; + st_display_internal = internal; } -uint8_t t3100e_display_get() +uint8_t +t3100e_display_get(void) { - return st_display_internal; + return st_display_internal; } +typedef struct t3100e_t { + mem_mapping_t mapping; -typedef struct t3100e_t -{ - mem_mapping_t mapping; + cga_t cga; /* The CGA is used for the external + * display; most of its registers are + * ignored by the plasma display. */ - cga_t cga; /* The CGA is used for the external - * display; most of its registers are - * ignored by the plasma display. */ + int font; /* Current font, 0-3 */ + int enabled; /* Hardware enabled, 0 or 1 */ + int internal; /* Using internal display? */ + uint8_t attrmap; /* Attribute mapping register */ - int font; /* Current font, 0-3 */ - int enabled; /* Hardware enabled, 0 or 1 */ - int internal; /* Using internal display? */ - uint8_t attrmap; /* Attribute mapping register */ + uint64_t dispontime, dispofftime; - uint64_t dispontime, dispofftime; - - int linepos, displine; - int vc; - int dispon; - int vsynctime; - uint8_t video_options; + int linepos, displine; + int vc; + int dispon; + int vsynctime; + uint8_t video_options; - uint8_t *vram; + uint8_t *vram; } t3100e_t; -static video_timings_t timing_t3100e = {VIDEO_ISA, 8,16,32, 8,16,32}; +static video_timings_t timing_t3100e = { VIDEO_ISA, 8, 16, 32, 8, 16, 32 }; +void t3100e_recalctimings(t3100e_t *t3100e); +void t3100e_write(uint32_t addr, uint8_t val, void *priv); +uint8_t t3100e_read(uint32_t addr, void *priv); +void t3100e_recalcattrs(t3100e_t *t3100e); -void t3100e_recalctimings(t3100e_t *t3100e); -void t3100e_write(uint32_t addr, uint8_t val, void *p); -uint8_t t3100e_read(uint32_t addr, void *p); -void t3100e_recalcattrs(t3100e_t *t3100e); - - -void t3100e_out(uint16_t addr, uint8_t val, void *p) +void +t3100e_out(uint16_t addr, uint8_t val, void *priv) { - t3100e_t *t3100e = (t3100e_t *)p; - switch (addr) - { - /* Emulated CRTC, register select */ - case 0x3d0: case 0x3d2: case 0x3d4: case 0x3d6: - cga_out(addr, val, &t3100e->cga); - break; + t3100e_t *t3100e = (t3100e_t *) priv; + switch (addr) { + /* Emulated CRTC, register select */ + case 0x3d0: + case 0x3d2: + case 0x3d4: + case 0x3d6: + cga_out(addr, val, &t3100e->cga); + break; - /* Emulated CRTC, value */ - case 0x3d1: case 0x3d3: case 0x3d5: case 0x3d7: - /* Register 0x12 controls the attribute mappings for the - * plasma screen. */ - if (t3100e->cga.crtcreg == 0x12) - { - t3100e->attrmap = val; - t3100e_recalcattrs(t3100e); - return; - } - cga_out(addr, val, &t3100e->cga); + /* Emulated CRTC, value */ + case 0x3d1: + case 0x3d3: + case 0x3d5: + case 0x3d7: + /* Register 0x12 controls the attribute mappings for the + * plasma screen. */ + if (t3100e->cga.crtcreg == 0x12) { + t3100e->attrmap = val; + t3100e_recalcattrs(t3100e); + return; + } + cga_out(addr, val, &t3100e->cga); - t3100e_recalctimings(t3100e); - return; + t3100e_recalctimings(t3100e); + return; - /* CGA control register */ - case 0x3D8: - cga_out(addr, val, &t3100e->cga); - return; - /* CGA colour register */ - case 0x3D9: - cga_out(addr, val, &t3100e->cga); - return; - } + case 0x3D8: /* CGA control register */ + case 0x3D9: /* CGA colour register */ + cga_out(addr, val, &t3100e->cga); + return; + + default: + break; + } } -uint8_t t3100e_in(uint16_t addr, void *p) +uint8_t +t3100e_in(uint16_t addr, void *priv) { - t3100e_t *t3100e = (t3100e_t *)p; - uint8_t val; + t3100e_t *t3100e = (t3100e_t *) priv; + uint8_t val; - switch (addr) - { - case 0x3d1: case 0x3d3: case 0x3d5: case 0x3d7: - if (t3100e->cga.crtcreg == 0x12) - { - val = t3100e->attrmap & 0x0F; - if (t3100e->internal) val |= 0x30; /* Plasma / CRT */ - return val; - } - } - - return cga_in(addr, &t3100e->cga); + switch (addr) { + case 0x3d1: + case 0x3d3: + case 0x3d5: + case 0x3d7: + if (t3100e->cga.crtcreg == 0x12) { + val = t3100e->attrmap & 0x0F; + if (t3100e->internal) + val |= 0x30; /* Plasma / CRT */ + return val; + } + break; + + default: + break; + } + + return cga_in(addr, &t3100e->cga); } - - - -void t3100e_write(uint32_t addr, uint8_t val, void *p) +void +t3100e_write(uint32_t addr, uint8_t val, void *priv) { - t3100e_t *t3100e = (t3100e_t *)p; + t3100e_t *t3100e = (t3100e_t *) priv; - t3100e->vram[addr & 0x7fff] = val; - cycles -= 4; -} - - - -uint8_t t3100e_read(uint32_t addr, void *p) -{ - t3100e_t *t3100e = (t3100e_t *)p; - cycles -= 4; - - return t3100e->vram[addr & 0x7fff]; + t3100e->vram[addr & 0x7fff] = val; + cycles -= 4; } - - -void t3100e_recalctimings(t3100e_t *t3100e) +uint8_t +t3100e_read(uint32_t addr, void *priv) { - double disptime; - double _dispontime, _dispofftime; + const t3100e_t *t3100e = (t3100e_t *) priv; - if (!t3100e->internal) - { - cga_recalctimings(&t3100e->cga); - return; - } - disptime = 651; - _dispontime = 640; - _dispofftime = disptime - _dispontime; - t3100e->dispontime = (uint64_t)(_dispontime * (cpuclock / VID_CLOCK) * (double)(1ull << 32)); - t3100e->dispofftime = (uint64_t)(_dispofftime * (cpuclock / VID_CLOCK) * (double)(1ull << 32)); + cycles -= 4; + + return t3100e->vram[addr & 0x7fff]; } +void +t3100e_recalctimings(t3100e_t *t3100e) +{ + double disptime; + double _dispontime; + double _dispofftime; + + if (!t3100e->internal) { + cga_recalctimings(&t3100e->cga); + return; + } + disptime = 651; + _dispontime = 640; + _dispofftime = disptime - _dispontime; + t3100e->dispontime = (uint64_t) (_dispontime * (cpuclock / VID_CLOCK) * (double) (1ULL << 32)); + t3100e->dispofftime = (uint64_t) (_dispofftime * (cpuclock / VID_CLOCK) * (double) (1ULL << 32)); +} /* Draw a row of text in 80-column mode */ -void t3100e_text_row80(t3100e_t *t3100e) +void +t3100e_text_row80(t3100e_t *t3100e) { - uint32_t cols[2]; - int x, c; - uint8_t chr, attr; - int drawcursor; - int cursorline; - int bold; - int blink; - uint16_t addr; - uint8_t sc; - uint16_t ma = (t3100e->cga.crtc[13] | (t3100e->cga.crtc[12] << 8)) & 0x7fff; - uint16_t ca = (t3100e->cga.crtc[15] | (t3100e->cga.crtc[14] << 8)) & 0x7fff; + uint32_t cols[2]; + uint8_t chr; + uint8_t attr; + int drawcursor; + int cursorline; + int bold; + int blink; + uint16_t addr; + uint8_t sc; + uint16_t ma = (t3100e->cga.crtc[13] | (t3100e->cga.crtc[12] << 8)) & 0x7fff; + uint16_t ca = (t3100e->cga.crtc[15] | (t3100e->cga.crtc[14] << 8)) & 0x7fff; - sc = (t3100e->displine) & 15; - addr = ((ma & ~1) + (t3100e->displine >> 4) * 80) * 2; - ma += (t3100e->displine >> 4) * 80; + sc = (t3100e->displine) & 15; + addr = ((ma & ~1) + (t3100e->displine >> 4) * 80) * 2; + ma += (t3100e->displine >> 4) * 80; - if ((t3100e->cga.crtc[10] & 0x60) == 0x20) - { - cursorline = 0; - } - else - { - cursorline = ((t3100e->cga.crtc[10] & 0x0F)*2 <= sc) && - ((t3100e->cga.crtc[11] & 0x0F)*2 >= sc); - } - for (x = 0; x < 80; x++) + if ((t3100e->cga.crtc[10] & 0x60) == 0x20) { + cursorline = 0; + } else { + cursorline = ((t3100e->cga.crtc[10] & 0x0F) * 2 <= sc) && ((t3100e->cga.crtc[11] & 0x0F) * 2 >= sc); + } + for (uint8_t x = 0; x < 80; x++) { + chr = t3100e->vram[(addr + 2 * x) & 0x7FFF]; + attr = t3100e->vram[(addr + 2 * x + 1) & 0x7FFF]; + drawcursor = ((ma == ca) && cursorline && (t3100e->cga.cgamode & 8) && (t3100e->cga.cgablink & 16)); + + blink = ((t3100e->cga.cgablink & 16) && (t3100e->cga.cgamode & 0x20) && (attr & 0x80) && !drawcursor); + + if (t3100e->video_options & 4) + bold = boldcols[attr] ? chr + 256 : chr; + else + bold = boldcols[attr] ? chr : chr + 256; + bold += 512 * (t3100e->video_options & 3); + + if (t3100e->cga.cgamode & 0x20) /* Blink */ { - chr = t3100e->vram[(addr + 2 * x) & 0x7FFF]; - attr = t3100e->vram[(addr + 2 * x + 1) & 0x7FFF]; - drawcursor = ((ma == ca) && cursorline && - (t3100e->cga.cgamode & 8) && (t3100e->cga.cgablink & 16)); - - blink = ((t3100e->cga.cgablink & 16) && (t3100e->cga.cgamode & 0x20) && - (attr & 0x80) && !drawcursor); - - if (t3100e->video_options & 4) - bold = boldcols[attr] ? chr + 256 : chr; - else - bold = boldcols[attr] ? chr : chr + 256; - bold += 512 * (t3100e->video_options & 3); - - if (t3100e->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[t3100e->displine])[(x << 3) + c] = cols[(fontdatm[bold][sc] & (1 << (c ^ 7))) ? 1 : 0] ^ (amber ^ black); - } - } - else - { - for (c = 0; c < 8; c++) - ((uint32_t *)buffer32->line[t3100e->displine])[(x << 3) + c] = cols[(fontdatm[bold][sc] & (1 << (c ^ 7))) ? 1 : 0]; - } - ++ma; - } + 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 (uint8_t c = 0; c < 8; c++) { + (buffer32->line[t3100e->displine])[(x << 3) + c] = cols[(fontdatm[bold][sc] & (1 << (c ^ 7))) ? 1 : 0] ^ (amber ^ black); + } + } else { + for (uint8_t c = 0; c < 8; c++) + (buffer32->line[t3100e->displine])[(x << 3) + c] = cols[(fontdatm[bold][sc] & (1 << (c ^ 7))) ? 1 : 0]; + } + ++ma; + } } /* Draw a row of text in 40-column mode */ -void t3100e_text_row40(t3100e_t *t3100e) +void +t3100e_text_row40(t3100e_t *t3100e) { - uint32_t cols[2]; - int x, c; - uint8_t chr, attr; - int drawcursor; - int cursorline; - int bold; - int blink; - uint16_t addr; - uint8_t sc; - uint16_t ma = (t3100e->cga.crtc[13] | (t3100e->cga.crtc[12] << 8)) & 0x7fff; - uint16_t ca = (t3100e->cga.crtc[15] | (t3100e->cga.crtc[14] << 8)) & 0x7fff; + uint32_t cols[2]; + int c; + uint8_t chr; + uint8_t attr; + int drawcursor; + int cursorline; + int bold; + int blink; + uint16_t addr; + uint8_t sc; + uint16_t ma = (t3100e->cga.crtc[13] | (t3100e->cga.crtc[12] << 8)) & 0x7fff; + uint16_t ca = (t3100e->cga.crtc[15] | (t3100e->cga.crtc[14] << 8)) & 0x7fff; - sc = (t3100e->displine) & 15; - addr = ((ma & ~1) + (t3100e->displine >> 4) * 40) * 2; - ma += (t3100e->displine >> 4) * 40; + sc = (t3100e->displine) & 15; + addr = ((ma & ~1) + (t3100e->displine >> 4) * 40) * 2; + ma += (t3100e->displine >> 4) * 40; - if ((t3100e->cga.crtc[10] & 0x60) == 0x20) - { - cursorline = 0; - } - else - { - cursorline = ((t3100e->cga.crtc[10] & 0x0F)*2 <= sc) && - ((t3100e->cga.crtc[11] & 0x0F)*2 >= sc); - } - for (x = 0; x < 40; x++) + if ((t3100e->cga.crtc[10] & 0x60) == 0x20) { + cursorline = 0; + } else { + cursorline = ((t3100e->cga.crtc[10] & 0x0F) * 2 <= sc) && ((t3100e->cga.crtc[11] & 0x0F) * 2 >= sc); + } + for (uint8_t x = 0; x < 40; x++) { + chr = t3100e->vram[(addr + 2 * x) & 0x7FFF]; + attr = t3100e->vram[(addr + 2 * x + 1) & 0x7FFF]; + drawcursor = ((ma == ca) && cursorline && (t3100e->cga.cgamode & 8) && (t3100e->cga.cgablink & 16)); + + blink = ((t3100e->cga.cgablink & 16) && (t3100e->cga.cgamode & 0x20) && (attr & 0x80) && !drawcursor); + + if (t3100e->video_options & 4) + bold = boldcols[attr] ? chr + 256 : chr; + else + bold = boldcols[attr] ? chr : chr + 256; + bold += 512 * (t3100e->video_options & 3); + + if (t3100e->cga.cgamode & 0x20) /* Blink */ { - chr = t3100e->vram[(addr + 2 * x) & 0x7FFF]; - attr = t3100e->vram[(addr + 2 * x + 1) & 0x7FFF]; - drawcursor = ((ma == ca) && cursorline && - (t3100e->cga.cgamode & 8) && (t3100e->cga.cgablink & 16)); - - blink = ((t3100e->cga.cgablink & 16) && (t3100e->cga.cgamode & 0x20) && - (attr & 0x80) && !drawcursor); - - if (t3100e->video_options & 4) - bold = boldcols[attr] ? chr + 256 : chr; - else bold = boldcols[attr] ? chr : chr + 256; - bold += 512 * (t3100e->video_options & 3); - - if (t3100e->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[t3100e->displine])[(x << 4) + c*2] = - ((uint32_t *)buffer32->line[t3100e->displine])[(x << 4) + c*2 + 1] = cols[(fontdatm[bold][sc] & (1 << (c ^ 7))) ? 1 : 0] ^ (amber ^ black); - } - } - else - { - for (c = 0; c < 8; c++) - { - ((uint32_t *)buffer32->line[t3100e->displine])[(x << 4) + c*2] = - ((uint32_t *)buffer32->line[t3100e->displine])[(x << 4) + c*2+1] = cols[(fontdatm[bold][sc] & (1 << (c ^ 7))) ? 1 : 0]; - } - } - ++ma; - } + 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++) { + (buffer32->line[t3100e->displine])[(x << 4) + c * 2] = (buffer32->line[t3100e->displine])[(x << 4) + c * 2 + 1] = cols[(fontdatm[bold][sc] & (1 << (c ^ 7))) ? 1 : 0] ^ (amber ^ black); + } + } else { + for (c = 0; c < 8; c++) { + (buffer32->line[t3100e->displine])[(x << 4) + c * 2] = (buffer32->line[t3100e->displine])[(x << 4) + c * 2 + 1] = cols[(fontdatm[bold][sc] & (1 << (c ^ 7))) ? 1 : 0]; + } + } + ++ma; + } } - - - /* Draw a line in CGA 640x200 or T3100e 640x400 mode */ -void t3100e_cgaline6(t3100e_t *t3100e) +void +t3100e_cgaline6(t3100e_t *t3100e) { - int x, c; - uint8_t dat; - uint32_t ink = 0; - uint16_t addr; - uint32_t fg = (t3100e->cga.cgacol & 0x0F) ? amber : black; - uint32_t bg = black; + uint8_t dat; + uint32_t ink = 0; + uint16_t addr; + uint32_t fg = (t3100e->cga.cgacol & 0x0F) ? amber : black; + uint32_t bg = black; - uint16_t ma = (t3100e->cga.crtc[13] | (t3100e->cga.crtc[12] << 8)) & 0x7fff; + uint16_t ma = (t3100e->cga.crtc[13] | (t3100e->cga.crtc[12] << 8)) & 0x7fff; - if (t3100e->cga.crtc[9] == 3) /* 640*400 */ - { - addr = ((t3100e->displine) & 1) * 0x2000 + - ((t3100e->displine >> 1) & 1) * 0x4000 + - (t3100e->displine >> 2) * 80 + - ((ma & ~1) << 1); - } - else - { - addr = ((t3100e->displine >> 1) & 1) * 0x2000 + - (t3100e->displine >> 2) * 80 + - ((ma & ~1) << 1); - } - for (x = 0; x < 80; x++) - { - dat = t3100e->vram[addr & 0x7FFF]; - addr++; + if (t3100e->cga.crtc[9] == 3) /* 640*400 */ + { + addr = ((t3100e->displine) & 1) * 0x2000 + ((t3100e->displine >> 1) & 1) * 0x4000 + (t3100e->displine >> 2) * 80 + ((ma & ~1) << 1); + } else { + addr = ((t3100e->displine >> 1) & 1) * 0x2000 + (t3100e->displine >> 2) * 80 + ((ma & ~1) << 1); + } + for (uint8_t x = 0; x < 80; x++) { + dat = t3100e->vram[addr & 0x7FFF]; + addr++; - for (c = 0; c < 8; c++) - { - ink = (dat & 0x80) ? fg : bg; - if (!(t3100e->cga.cgamode & 8)) ink = black; - ((uint32_t *)buffer32->line[t3100e->displine])[x*8+c] = ink; - dat = dat << 1; - } - } + for (uint8_t c = 0; c < 8; c++) { + ink = (dat & 0x80) ? fg : bg; + if (!(t3100e->cga.cgamode & 8)) + ink = black; + (buffer32->line[t3100e->displine])[x * 8 + c] = ink; + dat = 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 */ -void t3100e_cgaline4(t3100e_t *t3100e) +void +t3100e_cgaline4(t3100e_t *t3100e) { - int x, c; - uint8_t dat, pattern; - uint32_t ink0 = 0, ink1 = 0; - uint16_t addr; + uint8_t dat; + uint8_t pattern; + uint32_t ink0 = 0; + uint32_t ink1 = 0; + uint16_t addr; - uint16_t ma = (t3100e->cga.crtc[13] | (t3100e->cga.crtc[12] << 8)) & 0x7fff; - if (t3100e->cga.crtc[9] == 3) /* 320*400 undocumented */ - { - addr = ((t3100e->displine) & 1) * 0x2000 + - ((t3100e->displine >> 1) & 1) * 0x4000 + - (t3100e->displine >> 2) * 80 + - ((ma & ~1) << 1); - } - else /* 320*200 */ - { - addr = ((t3100e->displine >> 1) & 1) * 0x2000 + - (t3100e->displine >> 2) * 80 + - ((ma & ~1) << 1); - } - for (x = 0; x < 80; x++) - { - dat = t3100e->vram[addr & 0x7FFF]; - addr++; + uint16_t ma = (t3100e->cga.crtc[13] | (t3100e->cga.crtc[12] << 8)) & 0x7fff; + if (t3100e->cga.crtc[9] == 3) /* 320*400 undocumented */ + { + addr = ((t3100e->displine) & 1) * 0x2000 + ((t3100e->displine >> 1) & 1) * 0x4000 + (t3100e->displine >> 2) * 80 + ((ma & ~1) << 1); + } else /* 320*200 */ + { + addr = ((t3100e->displine >> 1) & 1) * 0x2000 + (t3100e->displine >> 2) * 80 + ((ma & ~1) << 1); + } + for (uint8_t x = 0; x < 80; x++) { + dat = t3100e->vram[addr & 0x7FFF]; + addr++; - for (c = 0; c < 4; c++) - { - pattern = (dat & 0xC0) >> 6; - if (!(t3100e->cga.cgamode & 8)) pattern = 0; + for (uint8_t c = 0; c < 4; c++) { + pattern = (dat & 0xC0) >> 6; + if (!(t3100e->cga.cgamode & 8)) + pattern = 0; - switch (pattern & 3) - { - case 0: ink0 = ink1 = black; break; - case 1: if (t3100e->displine & 1) - { - ink0 = black; ink1 = black; - } - else - { - ink0 = amber; ink1 = black; - } - break; - case 2: if (t3100e->displine & 1) - { - ink0 = black; ink1 = amber; - } - else - { - ink0 = amber; ink1 = black; - } - break; - case 3: ink0 = ink1 = amber; break; + switch (pattern & 3) { + case 0: + ink0 = ink1 = black; + break; + case 1: + if (t3100e->displine & 1) { + ink0 = black; + ink1 = black; + } else { + ink0 = amber; + ink1 = black; + } + break; + case 2: + if (t3100e->displine & 1) { + ink0 = black; + ink1 = amber; + } else { + ink0 = amber; + ink1 = black; + } + break; + case 3: + ink0 = ink1 = amber; + break; - } - ((uint32_t *)buffer32->line[t3100e->displine])[x*8+2*c] = ink0; - ((uint32_t *)buffer32->line[t3100e->displine])[x*8+2*c+1] = ink1; - dat = dat << 2; - } - } + default: + break; + } + (buffer32->line[t3100e->displine])[x * 8 + 2 * c] = ink0; + (buffer32->line[t3100e->displine])[x * 8 + 2 * c + 1] = ink1; + dat = dat << 2; + } + } } - - - - - -void t3100e_poll(void *p) +void +t3100e_poll(void *priv) { - t3100e_t *t3100e = (t3100e_t *)p; + t3100e_t *t3100e = (t3100e_t *) priv; - if (t3100e->video_options != st_video_options) - { - t3100e->video_options = st_video_options; + if (t3100e->video_options != st_video_options) { + t3100e->video_options = st_video_options; - if (t3100e->video_options & 8) /* Disable internal CGA */ - mem_mapping_disable(&t3100e->mapping); - else mem_mapping_enable(&t3100e->mapping); - - /* Set the font used for the external display */ - t3100e->cga.fontbase = (512 * (t3100e->video_options & 3)) - + ((t3100e->video_options & 4) ? 256 : 0); - - } - /* Switch between internal plasma and external CRT display. */ - if (st_display_internal != -1 && st_display_internal != t3100e->internal) - { - t3100e->internal = st_display_internal; - t3100e_recalctimings(t3100e); - } - if (!t3100e->internal) - { - cga_poll(&t3100e->cga); - return; - } - - - if (!t3100e->linepos) - { - timer_advance_u64(&t3100e->cga.timer, t3100e->dispofftime); - t3100e->cga.cgastat |= 1; - t3100e->linepos = 1; - if (t3100e->dispon) - { - if (t3100e->displine == 0) - { - video_wait_for_buffer(); - } - - /* Graphics */ - if (t3100e->cga.cgamode & 0x02) - { - if (t3100e->cga.cgamode & 0x10) - t3100e_cgaline6(t3100e); - else t3100e_cgaline4(t3100e); - } - else - if (t3100e->cga.cgamode & 0x01) /* High-res text */ - { - t3100e_text_row80(t3100e); - } - else - { - t3100e_text_row40(t3100e); - } - } - t3100e->displine++; - /* Hardcode a fixed refresh rate and VSYNC timing */ - if (t3100e->displine == 400) /* Start of VSYNC */ - { - t3100e->cga.cgastat |= 8; - t3100e->dispon = 0; - } - if (t3100e->displine == 416) /* End of VSYNC */ - { - t3100e->displine = 0; - t3100e->cga.cgastat &= ~8; - t3100e->dispon = 1; - } - } + if (t3100e->video_options & 8) /* Disable internal CGA */ + mem_mapping_disable(&t3100e->mapping); else - { - if (t3100e->dispon) - { - t3100e->cga.cgastat &= ~1; - } - timer_advance_u64(&t3100e->cga.timer, t3100e->dispontime); - t3100e->linepos = 0; + mem_mapping_enable(&t3100e->mapping); - if (t3100e->displine == 400) - { -/* Hardcode 640x400 window size */ - if ((T3100E_XSIZE != xsize) || (T3100E_YSIZE != ysize) || video_force_resize_get()) - { - xsize = T3100E_XSIZE; - ysize = T3100E_YSIZE; - if (xsize < 64) xsize = 656; - if (ysize < 32) ysize = 200; - set_screen_size(xsize, ysize); - - if (video_force_resize_get()) - video_force_resize_set(0); - } - video_blit_memtoscreen(0, 0, xsize, ysize); - - frames++; - /* Fixed 640x400 resolution */ - video_res_x = T3100E_XSIZE; - video_res_y = T3100E_YSIZE; - - if (t3100e->cga.cgamode & 0x02) - { - if (t3100e->cga.cgamode & 0x10) - video_bpp = 1; - else video_bpp = 2; - - } - else video_bpp = 0; - t3100e->cga.cgablink++; - } - } -} - - - -void t3100e_recalcattrs(t3100e_t *t3100e) -{ - int n; - - /* val behaves as follows: - * Bit 0: Attributes 01-06, 08-0E are inverse video - * Bit 1: Attributes 01-06, 08-0E are bold - * Bit 2: Attributes 11-16, 18-1F, 21-26, 28-2F ... F1-F6, F8-FF - * are inverse video - * Bit 3: Attributes 11-16, 18-1F, 21-26, 28-2F ... F1-F6, F8-FF - * are bold */ - - /* Set up colours */ - amber = makecol(0xf7, 0x7C, 0x34); - black = makecol(0x17, 0x0C, 0x00); - - /* Initialise the attribute mapping. Start by defaulting everything - * to black on amber, and with bold set by bit 3 */ - for (n = 0; n < 256; n++) - { - boldcols[n] = (n & 8) != 0; - blinkcols[n][0] = normcols[n][0] = amber; - blinkcols[n][1] = normcols[n][1] = black; - } - - /* Colours 0x11-0xFF are controlled by bits 2 and 3 of the - * passed value. Exclude x0 and x8, which are always black on - * amber. */ - for (n = 0x11; n <= 0xFF; n++) - { - if ((n & 7) == 0) continue; - if (t3100e->attrmap & 4) /* Inverse */ - { - blinkcols[n][0] = normcols[n][0] = amber; - blinkcols[n][1] = normcols[n][1] = black; - } - else /* Normal */ - { - blinkcols[n][0] = normcols[n][0] = black; - blinkcols[n][1] = normcols[n][1] = amber; - } - if (t3100e->attrmap & 8) boldcols[n] = 1; /* Bold */ - } - /* Set up the 01-0E range, controlled by bits 0 and 1 of the - * passed value. When blinking is enabled this also affects 81-8E. */ - for (n = 0x01; n <= 0x0E; n++) - { - if (n == 7) continue; - if (t3100e->attrmap & 1) - { - blinkcols[n][0] = normcols[n][0] = amber; - blinkcols[n][1] = normcols[n][1] = black; - blinkcols[n+128][0] = amber; - blinkcols[n+128][1] = black; - } - else - { - blinkcols[n][0] = normcols[n][0] = black; - blinkcols[n][1] = normcols[n][1] = amber; - blinkcols[n+128][0] = black; - blinkcols[n+128][1] = amber; - } - if (t3100e->attrmap & 2) boldcols[n] = 1; - } - /* Colours 07 and 0F are always amber on black. If blinking is - * enabled so are 87 and 8F. */ - for (n = 0x07; n <= 0x0F; n += 8) - { - blinkcols[n][0] = normcols[n][0] = black; - blinkcols[n][1] = normcols[n][1] = amber; - blinkcols[n+128][0] = black; - blinkcols[n+128][1] = amber; - } - /* When not blinking, colours 81-8F are always amber on black. */ - for (n = 0x81; n <= 0x8F; n ++) - { - normcols[n][0] = black; - normcols[n][1] = amber; - boldcols[n] = (n & 0x08) != 0; - } - - - /* Finally do the ones which are solid black. These differ between - * the normal and blinking mappings */ - for (n = 0; n <= 0xFF; n += 0x11) - { - normcols[n][0] = normcols[n][1] = black; - } - /* In the blinking range, 00 11 22 .. 77 and 80 91 A2 .. F7 are black */ - for (n = 0; n <= 0x77; n += 0x11) - { - blinkcols[n][0] = blinkcols[n][1] = black; - blinkcols[n+128][0] = blinkcols[n+128][1] = black; - } -} - - -void *t3100e_init(const device_t *info) -{ - t3100e_t *t3100e = malloc(sizeof(t3100e_t)); - memset(t3100e, 0, sizeof(t3100e_t)); - loadfont("roms/machines/t3100e/t3100e_font.bin", 5); - cga_init(&t3100e->cga); - video_inform(VIDEO_FLAG_TYPE_CGA, &timing_t3100e); - - t3100e->internal = 1; - - /* 32k video RAM */ - t3100e->vram = malloc(0x8000); - - timer_set_callback(&t3100e->cga.timer, t3100e_poll); - timer_set_p(&t3100e->cga.timer, t3100e); - - /* Occupy memory between 0xB8000 and 0xBFFFF */ - mem_mapping_add(&t3100e->mapping, 0xb8000, 0x8000, t3100e_read, NULL, NULL, t3100e_write, NULL, NULL, NULL, 0, t3100e); - /* Respond to CGA I/O ports */ - io_sethandler(0x03d0, 0x000c, t3100e_in, NULL, NULL, t3100e_out, NULL, NULL, t3100e); - - /* Default attribute mapping is 4 */ - t3100e->attrmap = 4; - t3100e_recalcattrs(t3100e); - -/* Start off in 80x25 text mode */ - t3100e->cga.cgastat = 0xF4; - t3100e->cga.vram = t3100e->vram; - t3100e->enabled = 1; - t3100e->video_options = 0xFF; - return t3100e; -} - -void t3100e_close(void *p) -{ - t3100e_t *t3100e = (t3100e_t *)p; - - free(t3100e->vram); - free(t3100e); -} - -void t3100e_speed_changed(void *p) -{ - t3100e_t *t3100e = (t3100e_t *)p; - + /* Set the font used for the external display */ + t3100e->cga.fontbase = (512 * (t3100e->video_options & 3)) + + ((t3100e->video_options & 4) ? 256 : 0); + } + /* Switch between internal plasma and external CRT display. */ + if (st_display_internal != -1 && st_display_internal != t3100e->internal) { + t3100e->internal = st_display_internal; t3100e_recalctimings(t3100e); + } + if (!t3100e->internal) { + cga_poll(&t3100e->cga); + return; + } + + if (!t3100e->linepos) { + timer_advance_u64(&t3100e->cga.timer, t3100e->dispofftime); + t3100e->cga.cgastat |= 1; + t3100e->linepos = 1; + if (t3100e->dispon) { + if (t3100e->displine == 0) { + video_wait_for_buffer(); + } + + /* Graphics */ + if (t3100e->cga.cgamode & 0x02) { + if (t3100e->cga.cgamode & 0x10) + t3100e_cgaline6(t3100e); + else + t3100e_cgaline4(t3100e); + } else if (t3100e->cga.cgamode & 0x01) /* High-res text */ + { + t3100e_text_row80(t3100e); + } else { + t3100e_text_row40(t3100e); + } + } + t3100e->displine++; + /* Hardcode a fixed refresh rate and VSYNC timing */ + if (t3100e->displine == 400) /* Start of VSYNC */ + { + t3100e->cga.cgastat |= 8; + t3100e->dispon = 0; + } + if (t3100e->displine == 416) /* End of VSYNC */ + { + t3100e->displine = 0; + t3100e->cga.cgastat &= ~8; + t3100e->dispon = 1; + } + } else { + if (t3100e->dispon) { + t3100e->cga.cgastat &= ~1; + } + timer_advance_u64(&t3100e->cga.timer, t3100e->dispontime); + t3100e->linepos = 0; + + if (t3100e->displine == 400) { + /* Hardcode 640x400 window size */ + if ((T3100E_XSIZE != xsize) || (T3100E_YSIZE != ysize) || video_force_resize_get()) { + xsize = T3100E_XSIZE; + ysize = T3100E_YSIZE; + if (xsize < 64) + xsize = 656; + if (ysize < 32) + ysize = 200; + set_screen_size(xsize, ysize); + + if (video_force_resize_get()) + video_force_resize_set(0); + } + video_blit_memtoscreen(0, 0, xsize, ysize); + + frames++; + /* Fixed 640x400 resolution */ + video_res_x = T3100E_XSIZE; + video_res_y = T3100E_YSIZE; + + if (t3100e->cga.cgamode & 0x02) { + if (t3100e->cga.cgamode & 0x10) + video_bpp = 1; + else + video_bpp = 2; + + } else + video_bpp = 0; + t3100e->cga.cgablink++; + } + } } -const device_t t3100e_device = +void +t3100e_recalcattrs(t3100e_t *t3100e) { - "Toshiba T3100e", - "t3100e", - 0, - 0, - t3100e_init, - t3100e_close, - NULL, - { NULL }, - t3100e_speed_changed, - NULL + int n; + + /* val behaves as follows: + * Bit 0: Attributes 01-06, 08-0E are inverse video + * Bit 1: Attributes 01-06, 08-0E are bold + * Bit 2: Attributes 11-16, 18-1F, 21-26, 28-2F ... F1-F6, F8-FF + * are inverse video + * Bit 3: Attributes 11-16, 18-1F, 21-26, 28-2F ... F1-F6, F8-FF + * are bold */ + + /* Set up colours */ + amber = makecol(0xf7, 0x7C, 0x34); + black = makecol(0x17, 0x0C, 0x00); + + /* Initialise the attribute mapping. Start by defaulting everything + * to black on amber, and with bold set by bit 3 */ + for (n = 0; n < 256; n++) { + boldcols[n] = (n & 8) != 0; + blinkcols[n][0] = normcols[n][0] = amber; + blinkcols[n][1] = normcols[n][1] = black; + } + + /* Colours 0x11-0xFF are controlled by bits 2 and 3 of the + * passed value. Exclude x0 and x8, which are always black on + * amber. */ + for (n = 0x11; n <= 0xFF; n++) { + if ((n & 7) == 0) + continue; + if (t3100e->attrmap & 4) /* Inverse */ + { + blinkcols[n][0] = normcols[n][0] = amber; + blinkcols[n][1] = normcols[n][1] = black; + } else /* Normal */ + { + blinkcols[n][0] = normcols[n][0] = black; + blinkcols[n][1] = normcols[n][1] = amber; + } + if (t3100e->attrmap & 8) + boldcols[n] = 1; /* Bold */ + } + /* Set up the 01-0E range, controlled by bits 0 and 1 of the + * passed value. When blinking is enabled this also affects 81-8E. */ + for (n = 0x01; n <= 0x0E; n++) { + if (n == 7) + continue; + if (t3100e->attrmap & 1) { + blinkcols[n][0] = normcols[n][0] = amber; + blinkcols[n][1] = normcols[n][1] = black; + blinkcols[n + 128][0] = amber; + blinkcols[n + 128][1] = black; + } else { + blinkcols[n][0] = normcols[n][0] = black; + blinkcols[n][1] = normcols[n][1] = amber; + blinkcols[n + 128][0] = black; + blinkcols[n + 128][1] = amber; + } + if (t3100e->attrmap & 2) + boldcols[n] = 1; + } + /* Colours 07 and 0F are always amber on black. If blinking is + * enabled so are 87 and 8F. */ + for (n = 0x07; n <= 0x0F; n += 8) { + blinkcols[n][0] = normcols[n][0] = black; + blinkcols[n][1] = normcols[n][1] = amber; + blinkcols[n + 128][0] = black; + blinkcols[n + 128][1] = amber; + } + /* When not blinking, colours 81-8F are always amber on black. */ + for (n = 0x81; n <= 0x8F; n++) { + normcols[n][0] = black; + normcols[n][1] = amber; + boldcols[n] = (n & 0x08) != 0; + } + + /* Finally do the ones which are solid black. These differ between + * the normal and blinking mappings */ + for (n = 0; n <= 0xFF; n += 0x11) { + normcols[n][0] = normcols[n][1] = black; + } + /* In the blinking range, 00 11 22 .. 77 and 80 91 A2 .. F7 are black */ + for (n = 0; n <= 0x77; n += 0x11) { + blinkcols[n][0] = blinkcols[n][1] = black; + blinkcols[n + 128][0] = blinkcols[n + 128][1] = black; + } +} + +void * +t3100e_init(UNUSED(const device_t *info)) +{ + t3100e_t *t3100e = malloc(sizeof(t3100e_t)); + memset(t3100e, 0, sizeof(t3100e_t)); + loadfont("roms/machines/t3100e/t3100e_font.bin", 5); + cga_init(&t3100e->cga); + video_inform(VIDEO_FLAG_TYPE_CGA, &timing_t3100e); + + t3100e->internal = 1; + + /* 32k video RAM */ + t3100e->vram = malloc(0x8000); + + timer_set_callback(&t3100e->cga.timer, t3100e_poll); + timer_set_p(&t3100e->cga.timer, t3100e); + + /* Occupy memory between 0xB8000 and 0xBFFFF */ + mem_mapping_add(&t3100e->mapping, 0xb8000, 0x8000, t3100e_read, NULL, NULL, t3100e_write, NULL, NULL, NULL, 0, t3100e); + /* Respond to CGA I/O ports */ + io_sethandler(0x03d0, 0x000c, t3100e_in, NULL, NULL, t3100e_out, NULL, NULL, t3100e); + + /* Default attribute mapping is 4 */ + t3100e->attrmap = 4; + t3100e_recalcattrs(t3100e); + + /* Start off in 80x25 text mode */ + t3100e->cga.cgastat = 0xF4; + t3100e->cga.vram = t3100e->vram; + t3100e->enabled = 1; + t3100e->video_options = 0xFF; + return t3100e; +} + +void +t3100e_close(void *priv) +{ + t3100e_t *t3100e = (t3100e_t *) priv; + + free(t3100e->vram); + free(t3100e); +} + +void +t3100e_speed_changed(void *priv) +{ + t3100e_t *t3100e = (t3100e_t *) priv; + + t3100e_recalctimings(t3100e); +} + +const device_t t3100e_device = { + .name = "Toshiba T3100e", + .internal_name = "t3100e", + .flags = 0, + .local = 0, + .init = t3100e_init, + .close = t3100e_close, + .reset = NULL, + { .available = NULL }, + .speed_changed = t3100e_speed_changed, + .force_redraw = NULL, + .config = NULL }; diff --git a/src/machine/m_elt.c b/src/machine/m_elt.c new file mode 100644 index 000000000..95ca52a3e --- /dev/null +++ b/src/machine/m_elt.c @@ -0,0 +1,199 @@ +/* + * 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. + * + * Epson Equity LT portable computer emulation. + * + * Authors: Lubomir Rintel, + * + * Copyright 2022 Lubomir Rintel. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the: + * + * Free Software Foundation, Inc. + * 59 Temple Place - Suite 330 + * Boston, MA 02111-1307 + * USA. + */ + +#include +#include +#include +#include <86box/timer.h> +#include <86box/fdd.h> +#include <86box/86box.h> +#include <86box/device.h> +#include <86box/fdc.h> +#include <86box/fdc_ext.h> +#include <86box/io.h> +#include <86box/keyboard.h> +#include <86box/machine.h> +#include <86box/mem.h> +#include <86box/nmi.h> +#include <86box/nvr.h> +#include <86box/pit.h> +#include <86box/rom.h> +#include <86box/video.h> +#include <86box/vid_cga.h> +#include <86box/plat_fallthrough.h> +#include <86box/plat_unused.h> + +static void +elt_vid_off_poll(void *priv) +{ + cga_t *cga = priv; + uint8_t hdisp = cga->crtc[1]; + + /* Don't display anything. + * TODO: Do something less stupid to emulate backlight off. */ + cga->crtc[1] = 0; + cga_poll(cga); + cga->crtc[1] = hdisp; +} + +static void +sysstat_out(UNUSED(uint16_t port), uint8_t val, void *priv) +{ + cga_t *cga = priv; + + switch (val) { + case 0: + break; + case 1: + /* Backlight off. */ + if (cga) + timer_set_callback(&cga->timer, elt_vid_off_poll); + break; + case 2: + /* Backlight on. */ + if (cga) + timer_set_callback(&cga->timer, cga_poll); + break; + default: + pclog("Unknown sysstat command: 0x%02x\n", val); + } +} + +static uint8_t +sysstat_in(UNUSED(uint16_t port), void *priv) +{ + const cga_t *cga = priv; + uint8_t ret = 0x0a; /* No idea what these bits are */ + + /* External CRT. We don't emulate the LCD/CRT switching, let's just + * frivolously use this bit to indicate we're using the LCD if the + * user didn't override the video card for now. */ + if (cga == NULL) + ret |= 0x40; + + return ret; +} + +static void +elt_vid_out(uint16_t addr, uint8_t val, void *priv) +{ + cga_t *cga = priv; + + /* The Equity LT chipset's CRTC contains more registers than the + * regular CGA. The BIOS writes one of them, register 36 (0x24). + * Nothing is known about the number or function of those registers, + * let's just ignore them so that we don't clobber the CGA register. + * Also, the BIOS writes that register via the 3D0h/3D1h alias + * instead of the usual 3D4h/3D5h, possibly to keep the wraparound + * behavior on the usual addresses (just an assumption, not + * verified). */ + switch (addr) { + case 0x3d0: + cga->crtcreg = val; + return; + case 0x3d1: + if (cga->crtcreg >= 32) + return; + fallthrough; + + default: + cga->crtcreg &= 31; + cga_out(addr, val, priv); + } +} + +static uint8_t +elt_vid_in(uint16_t addr, void *priv) +{ + cga_t *cga = priv; + + /* Just make sure we don't ever let regular CGA code run with crtcreg + * pointing out of crtcregs[] bounds. */ + cga->crtcreg &= 31; + return cga_in(addr, priv); +} + +static void +load_font_rom(uint32_t font_data) +{ + for (uint16_t c = 0; c < 256; c++) + for (uint8_t d = 0; d < 8; d++) + fontdat[c][d] = mem_readb_phys(font_data++); +} + +int +machine_elt_init(const machine_t *model) +{ + cga_t *cga = NULL; + int ret; + + ret = bios_load_interleavedr("roms/machines/elt/HLO-B2.rom", + "roms/machines/elt/HLO-A2.rom", + 0x000fc000, 65536, 0); + + if (bios_only || !ret) + return ret; + + /* The machine doesn't have any separate font ROM chip. The text mode + * font is likely a mask ROM in the chipset. video_reset() will try + * to load a MDA font, but let's have a reasonable fall back if it's + * not available. Read in the graphical mode font from the BIOS ROM + * image. */ + load_font_rom(0xffa6e); + + machine_common_init(model); + + nmi_init(); + + pit_devs[0].set_out_func(pit_devs[0].data, 1, pit_refresh_timer_xt); + + if (fdc_type == FDC_INTERNAL) + device_add(&fdc_xt_device); + + if (gfxcard[0] == VID_INTERNAL) { + cga = device_add(&cga_device); + io_removehandler(0x03d0, 0x0010, cga_in, NULL, NULL, cga_out, NULL, NULL, cga); + io_sethandler(0x03d0, 0x0010, elt_vid_in, NULL, NULL, elt_vid_out, NULL, NULL, cga); + } + + /* Keyboard goes after the video, because on XT compatibles it's dealt + * with by the same PPI as the config switches and we need them to + * indicate the correct display type */ + device_add(&keyboard_xt_device); + + device_add(&elt_nvr_device); + + io_sethandler(0x11b8, 1, sysstat_in, NULL, NULL, sysstat_out, NULL, NULL, cga); + + return ret; +} diff --git a/src/machine/m_europc.c b/src/machine/m_europc.c index 29405024b..e541cf718 100644 --- a/src/machine/m_europc.c +++ b/src/machine/m_europc.c @@ -1,83 +1,83 @@ /* - * 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. + * 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. + * This file is part of the 86Box distribution. * - * Implementation of the Schneider EuroPC system. + * Implementation of the Schneider EuroPC system. * - * NOTES: BIOS info (taken from MAME, thanks guys!!) + * NOTES: BIOS info (taken from MAME, thanks guys!!) * - * f000:e107 bios checksum test - * memory test - * f000:e145 irq vector init - * f000:e156 - * f000:e169-d774 test of special registers 254/354 - * f000:e16c-e817 - * f000:e16f - * f000:ec08 test of special registers 800a rtc time - * or date error, rtc corrected - * f000:ef66 0xf - * f000:db3e 0x8..0xc - * f000:d7f8 - * f000:db5f - * f000:e172 - * f000:ecc5 801a video setup error - * f000:d6c9 copyright output - * f000:e1b7 - * f000:e1be DI bits set mean output text!!! (801a) - * f000: 0x8000 output - * 1 rtc error - * 2 rtc time or date error - * 4 checksum error in setup - * 8 rtc status corrected - * 10 video setup error - * 20 video ram bad - * 40 monitor type not recogniced - * 80 mouse port enabled - * 100 joystick port enabled - * f000:e1e2-dc0c CPU speed is 4.77 mhz - * f000:e1e5-f9c0 keyboard processor error - * f000:e1eb-c617 external lpt1 at 0x3bc - * f000:e1ee-e8ee external coms at + * f000:e107 bios checksum test + * memory test + * f000:e145 irq vector init + * f000:e156 + * f000:e169-d774 test of special registers 254/354 + * f000:e16c-e817 + * f000:e16f + * f000:ec08 test of special registers 800a rtc time + * or date error, rtc corrected + * f000:ef66 0xf + * f000:db3e 0x8..0xc + * f000:d7f8 + * f000:db5f + * f000:e172 + * f000:ecc5 801a video setup error + * f000:d6c9 copyright output + * f000:e1b7 + * f000:e1be DI bits set mean output text!!! (801a) + * f000: 0x8000 output + * 1 rtc error + * 2 rtc time or date error + * 4 checksum error in setup + * 8 rtc status corrected + * 10 video setup error + * 20 video ram bad + * 40 monitor type not recogniced + * 80 mouse port enabled + * 100 joystick port enabled + * f000:e1e2-dc0c CPU speed is 4.77 mhz + * f000:e1e5-f9c0 keyboard processor error + * f000:e1eb-c617 external lpt1 at 0x3bc + * f000:e1ee-e8ee external coms at * - * Routines: - * f000:c92d output text at bp - * f000:db3e RTC read reg cl - * f000:e8ee piep - * f000:e95e RTC write reg cl - * polls until JIM 0xa is zero, - * output cl at jim 0xa - * write ah hinibble as lownibble into jim 0xa - * write ah lownibble into jim 0xa - * f000:ef66 RTC read reg cl - * polls until jim 0xa is zero, - * output cl at jim 0xa - * read low 4 nibble at jim 0xa - * read low 4 nibble at jim 0xa - * return first nibble<<4|second nibble in ah - * f000:f046 seldom compares ret - * f000:fe87 0 -> ds + * Routines: + * f000:c92d output text at bp + * f000:db3e RTC read reg cl + * f000:e8ee piep + * f000:e95e RTC write reg cl + * polls until JIM 0xa is zero, + * output cl at jim 0xa + * write ah hinibble as lownibble into jim 0xa + * write ah lownibble into jim 0xa + * f000:ef66 RTC read reg cl + * polls until jim 0xa is zero, + * output cl at jim 0xa + * read low 4 nibble at jim 0xa + * read low 4 nibble at jim 0xa + * return first nibble<<4|second nibble in ah + * f000:f046 seldom compares ret + * f000:fe87 0 -> ds * - * Memory: - * 0000:0469 bit 0: b0000 memory available - * bit 1: b8000 memory available - * 0000:046a: 00 jim 250 01 jim 350 + * Memory: + * 0000:0469 bit 0: b0000 memory available + * bit 1: b8000 memory available + * 0000:046a: 00 jim 250 01 jim 350 * - * WARNING THIS IS A WORK-IN-PROGRESS MODULE. USE AT OWN RISK. - * + * WARNING THIS IS A WORK-IN-PROGRESS MODULE. USE AT OWN RISK. * * - * Author: Fred N. van Kempen, * - * Inspired by the "jim.c" file originally present, but a - * fully re-written module, based on the information from - * Schneider's schematics and technical manuals, and the - * input from people with real EuroPC hardware. + * Authors: Fred N. van Kempen, * - * Copyright 2017-2019 Fred N. van Kempen. + * Inspired by the "jim.c" file originally present, but a + * fully re-written module, based on the information from + * Schneider's schematics and technical manuals, and the + * input from people with real EuroPC hardware. + * + * Copyright 2017-2019 Fred N. van Kempen. */ #include #include @@ -104,66 +104,60 @@ #include <86box/hdc.h> #include <86box/video.h> #include <86box/machine.h> +#include <86box/plat_unused.h> - -#define EUROPC_DEBUG 0 /* current debugging level */ - +#define EUROPC_DEBUG 0 /* current debugging level */ /* M3002 RTC chip registers. */ -#define MRTC_SECONDS 0x00 /* BCD, 00-59 */ -#define MRTC_MINUTES 0x01 /* BCD, 00-59 */ -#define MRTC_HOURS 0x02 /* BCD, 00-23 */ -#define MRTC_DAYS 0x03 /* BCD, 01-31 */ -#define MRTC_MONTHS 0x04 /* BCD, 01-12 */ -#define MRTC_YEARS 0x05 /* BCD, 00-99 (year only) */ -#define MRTC_WEEKDAY 0x06 /* BCD, 01-07 */ -#define MRTC_WEEKNO 0x07 /* BCD, 01-52 */ -#define MRTC_CONF_A 0x08 /* EuroPC config, binary */ -#define MRTC_CONF_B 0x09 /* EuroPC config, binary */ -#define MRTC_CONF_C 0x0a /* EuroPC config, binary */ -#define MRTC_CONF_D 0x0b /* EuroPC config, binary */ -#define MRTC_CONF_E 0x0c /* EuroPC config, binary */ -#define MRTC_CHECK_LO 0x0d /* Checksum, low byte */ -#define MRTC_CHECK_HI 0x0e /* Checksum, high byte */ -#define MRTC_CTRLSTAT 0x0f /* RTC control/status, binary */ +#define MRTC_SECONDS 0x00 /* BCD, 00-59 */ +#define MRTC_MINUTES 0x01 /* BCD, 00-59 */ +#define MRTC_HOURS 0x02 /* BCD, 00-23 */ +#define MRTC_DAYS 0x03 /* BCD, 01-31 */ +#define MRTC_MONTHS 0x04 /* BCD, 01-12 */ +#define MRTC_YEARS 0x05 /* BCD, 00-99 (year only) */ +#define MRTC_WEEKDAY 0x06 /* BCD, 01-07 */ +#define MRTC_WEEKNO 0x07 /* BCD, 01-52 */ +#define MRTC_CONF_A 0x08 /* EuroPC config, binary */ +#define MRTC_CONF_B 0x09 /* EuroPC config, binary */ +#define MRTC_CONF_C 0x0a /* EuroPC config, binary */ +#define MRTC_CONF_D 0x0b /* EuroPC config, binary */ +#define MRTC_CONF_E 0x0c /* EuroPC config, binary */ +#define MRTC_CHECK_LO 0x0d /* Checksum, low byte */ +#define MRTC_CHECK_HI 0x0e /* Checksum, high byte */ +#define MRTC_CTRLSTAT 0x0f /* RTC control/status, binary */ -typedef struct { - uint16_t jim; /* JIM base address */ +typedef struct europc_t { + uint16_t jim; /* JIM base address */ - uint8_t regs[16]; /* JIM internal regs (8) */ + uint8_t regs[16]; /* JIM internal regs (8) */ - nvr_t nvr; /* NVR */ - uint8_t nvr_stat; - uint8_t nvr_addr; + nvr_t nvr; /* NVR */ + uint8_t nvr_stat; + uint8_t nvr_addr; - void * mouse; + void *mouse; } europc_t; - static europc_t europc; - #ifdef ENABLE_EUROPC_LOG int europc_do_log = ENABLE_EUROPC_LOG; - static void europc_log(const char *fmt, ...) { - va_list ap; + va_list ap; - if (europc_do_log) - { - va_start(ap, fmt); - pclog_ex(fmt, ap); - va_end(ap); - } + if (europc_do_log) { + va_start(ap, fmt); + pclog_ex(fmt, ap); + va_end(ap); + } } #else -#define europc_log(fmt, ...) +# define europc_log(fmt, ...) #endif - /* * This is called every second through the NVR/RTC hook. * @@ -180,56 +174,56 @@ static void europc_rtc_tick(nvr_t *nvr) { uint8_t *regs; - int mon, yr; + int mon; + int yr; /* Only if RTC is running.. */ regs = nvr->regs; - if (! (regs[MRTC_CTRLSTAT] & 0x01)) return; + if (!(regs[MRTC_CTRLSTAT] & 0x01)) + return; regs[MRTC_SECONDS] = RTC_BCDINC(nvr->regs[MRTC_SECONDS], 1); if (regs[MRTC_SECONDS] >= RTC_BCD(60)) { - regs[MRTC_SECONDS] = RTC_BCD(0); - regs[MRTC_MINUTES] = RTC_BCDINC(regs[MRTC_MINUTES], 1); - if (regs[MRTC_MINUTES] >= RTC_BCD(60)) { - regs[MRTC_MINUTES] = RTC_BCD(0); - regs[MRTC_HOURS] = RTC_BCDINC(regs[MRTC_HOURS], 1); - if (regs[MRTC_HOURS] >= RTC_BCD(24)) { - regs[MRTC_HOURS] = RTC_BCD(0); - regs[MRTC_DAYS] = RTC_BCDINC(regs[MRTC_DAYS], 1); - mon = RTC_DCB(regs[MRTC_MONTHS]); - yr = RTC_DCB(regs[MRTC_YEARS]) + 1900; - if (RTC_DCB(regs[MRTC_DAYS]) > nvr_get_days(mon, yr)) { - regs[MRTC_DAYS] = RTC_BCD(1); - regs[MRTC_MONTHS] = RTC_BCDINC(regs[MRTC_MONTHS], 1); - if (regs[MRTC_MONTHS] > RTC_BCD(12)) { - regs[MRTC_MONTHS] = RTC_BCD(1); - regs[MRTC_YEARS] = RTC_BCDINC(regs[MRTC_YEARS], 1) & 0xff; - } - } - } - } + regs[MRTC_SECONDS] = RTC_BCD(0); + regs[MRTC_MINUTES] = RTC_BCDINC(regs[MRTC_MINUTES], 1); + if (regs[MRTC_MINUTES] >= RTC_BCD(60)) { + regs[MRTC_MINUTES] = RTC_BCD(0); + regs[MRTC_HOURS] = RTC_BCDINC(regs[MRTC_HOURS], 1); + if (regs[MRTC_HOURS] >= RTC_BCD(24)) { + regs[MRTC_HOURS] = RTC_BCD(0); + regs[MRTC_DAYS] = RTC_BCDINC(regs[MRTC_DAYS], 1); + mon = RTC_DCB(regs[MRTC_MONTHS]); + yr = RTC_DCB(regs[MRTC_YEARS]) + 1900; + if (RTC_DCB(regs[MRTC_DAYS]) > nvr_get_days(mon, yr)) { + regs[MRTC_DAYS] = RTC_BCD(1); + regs[MRTC_MONTHS] = RTC_BCDINC(regs[MRTC_MONTHS], 1); + if (regs[MRTC_MONTHS] > RTC_BCD(12)) { + regs[MRTC_MONTHS] = RTC_BCD(1); + regs[MRTC_YEARS] = RTC_BCDINC(regs[MRTC_YEARS], 1) & 0xff; + } + } + } + } } } - /* Get the current NVR time. */ static void rtc_time_get(uint8_t *regs, struct tm *tm) { /* NVR is in BCD data mode. */ - tm->tm_sec = RTC_DCB(regs[MRTC_SECONDS]); - tm->tm_min = RTC_DCB(regs[MRTC_MINUTES]); + tm->tm_sec = RTC_DCB(regs[MRTC_SECONDS]); + tm->tm_min = RTC_DCB(regs[MRTC_MINUTES]); tm->tm_hour = RTC_DCB(regs[MRTC_HOURS]); tm->tm_wday = (RTC_DCB(regs[MRTC_WEEKDAY]) - 1); tm->tm_mday = RTC_DCB(regs[MRTC_DAYS]); - tm->tm_mon = (RTC_DCB(regs[MRTC_MONTHS]) - 1); + tm->tm_mon = (RTC_DCB(regs[MRTC_MONTHS]) - 1); tm->tm_year = RTC_DCB(regs[MRTC_YEARS]); #if USE_Y2K tm->tm_year += (RTC_DCB(regs[MRTC_CENTURY]) * 100) - 1900; #endif } - /* Set the current NVR time. */ static void rtc_time_set(uint8_t *regs, struct tm *tm) @@ -237,17 +231,16 @@ rtc_time_set(uint8_t *regs, struct tm *tm) /* NVR is in BCD data mode. */ regs[MRTC_SECONDS] = RTC_BCD(tm->tm_sec); regs[MRTC_MINUTES] = RTC_BCD(tm->tm_min); - regs[MRTC_HOURS] = RTC_BCD(tm->tm_hour); + regs[MRTC_HOURS] = RTC_BCD(tm->tm_hour); regs[MRTC_WEEKDAY] = RTC_BCD(tm->tm_wday + 1); - regs[MRTC_DAYS] = RTC_BCD(tm->tm_mday); - regs[MRTC_MONTHS] = RTC_BCD(tm->tm_mon + 1); - regs[MRTC_YEARS] = RTC_BCD(tm->tm_year % 100); + regs[MRTC_DAYS] = RTC_BCD(tm->tm_mday); + regs[MRTC_MONTHS] = RTC_BCD(tm->tm_mon + 1); + regs[MRTC_YEARS] = RTC_BCD(tm->tm_year % 100); #if USE_Y2K - regs[MRTC_CENTURY] = RTC_BCD((tm->tm_year+1900) / 100); + regs[MRTC_CENTURY] = RTC_BCD((tm->tm_year + 1900) / 100); #endif } - static void rtc_start(nvr_t *nvr) { @@ -255,13 +248,13 @@ rtc_start(nvr_t *nvr) /* Initialize the internal and chip times. */ if (time_sync & TIME_SYNC_ENABLED) { - /* Use the internal clock's time. */ - nvr_time_get(&tm); - rtc_time_set(nvr->regs, &tm); + /* Use the internal clock's time. */ + nvr_time_get(&tm); + rtc_time_set(nvr->regs, &tm); } else { - /* Set the internal clock from the chip time. */ - rtc_time_get(nvr->regs, &tm); - nvr_time_set(&tm); + /* Set the internal clock from the chip time. */ + rtc_time_get(nvr->regs, &tm); + nvr_time_set(&tm); } #if 0 @@ -270,293 +263,304 @@ rtc_start(nvr_t *nvr) #endif } - /* Create a valid checksum for the current NVR data. */ static uint8_t rtc_checksum(uint8_t *ptr) { uint8_t sum; - int i; /* Calculate all bytes with XOR. */ sum = 0x00; - for (i=MRTC_CONF_A; i<=MRTC_CONF_E; i++) - sum += ptr[i]; + for (uint8_t i = MRTC_CONF_A; i <= MRTC_CONF_E; i++) + sum += ptr[i]; - return(sum); + return sum; } - /* Reset the machine's NVR to a sane state. */ static void rtc_reset(nvr_t *nvr) { /* Initialize the RTC to a known state. */ - nvr->regs[MRTC_SECONDS] = RTC_BCD(0); /* seconds */ - nvr->regs[MRTC_MINUTES] = RTC_BCD(0); /* minutes */ - nvr->regs[MRTC_HOURS] = RTC_BCD(0); /* hours */ - nvr->regs[MRTC_DAYS] = RTC_BCD(1); /* days */ - nvr->regs[MRTC_MONTHS] = RTC_BCD(1); /* months */ - nvr->regs[MRTC_YEARS] = RTC_BCD(80); /* years */ - nvr->regs[MRTC_WEEKDAY] = RTC_BCD(1); /* weekday */ - nvr->regs[MRTC_WEEKNO] = RTC_BCD(1); /* weekno */ + nvr->regs[MRTC_SECONDS] = RTC_BCD(0); /* seconds */ + nvr->regs[MRTC_MINUTES] = RTC_BCD(0); /* minutes */ + nvr->regs[MRTC_HOURS] = RTC_BCD(0); /* hours */ + nvr->regs[MRTC_DAYS] = RTC_BCD(1); /* days */ + nvr->regs[MRTC_MONTHS] = RTC_BCD(1); /* months */ + nvr->regs[MRTC_YEARS] = RTC_BCD(80); /* years */ + nvr->regs[MRTC_WEEKDAY] = RTC_BCD(1); /* weekday */ + nvr->regs[MRTC_WEEKNO] = RTC_BCD(1); /* weekno */ /* * EuroPC System Configuration: * - * [A] unknown + * [A] unknown * - * [B] 7 1 bootdrive extern - * 0 bootdribe intern - * 6:5 11 invalid hard disk type - * 10 hard disk installed, type 2 - * 01 hard disk installed, type 1 - * 00 hard disk not installed - * 4:3 11 invalid external drive type - * 10 external drive 720K - * 01 external drive 360K - * 00 external drive disabled - * 2 unknown - * 1:0 11 invalid internal drive type - * 10 internal drive 360K - * 01 internal drive 720K - * 00 internal drive disabled + * [B] 7 1 bootdrive extern + * 0 bootdrive intern + * 6:5 11 invalid hard disk type + * 10 hard disk installed, type 2 + * 01 hard disk installed, type 1 + * 00 hard disk not installed + * 4:3 11 invalid external drive type + * 10 external drive 720K + * 01 external drive 360K + * 00 external drive disabled + * 2 unknown + * 1:0 11 invalid internal drive type + * 10 internal drive 360K + * 01 internal drive 720K + * 00 internal drive disabled * - * [C] 7:6 unknown - * 5 monitor detection OFF - * 4 unknown - * 3:2 11 illegal memory size - * 10 512K - * 01 256K - * 00 640K - * 1:0 11 illegal game port - * 10 gameport as mouse port - * 01 gameport as joysticks - * 00 gameport disabled + * [C] 7:6 unknown + * 5 monitor detection OFF + * 4 unknown + * 3:2 11 illegal memory size + * 10 512K + * 01 256K + * 00 640K + * 1:0 11 illegal game port + * 10 gameport as mouse port + * 01 gameport as joysticks + * 00 gameport disabled * - * [D] 7:6 10 9MHz CPU speed - * 01 7MHz CPU speed - * 00 4.77 MHz CPU - * 5 unknown - * 4 external: color, internal: mono - * 3 unknown - * 2 internal video ON - * 1:0 11 mono - * 10 color80 - * 01 color40 - * 00 special (EGA,VGA etc) + * [D] 7:6 10 9MHz CPU speed + * 01 7MHz CPU speed + * 00 4.77 MHz CPU + * 5 unknown + * 4 external: color, internal: mono + * 3 unknown + * 2 internal video ON + * 1:0 11 mono + * 10 color80 + * 01 color40 + * 00 special (EGA,VGA etc) * - * [E] 7:4 unknown - * 3:0 country (00=Deutschland, 0A=ASCII) + * [E] 7:4 unknown + * 3:0 country (00=Deutschland, 0A=ASCII) */ - nvr->regs[MRTC_CONF_A] = 0x00; /* CONFIG A */ - nvr->regs[MRTC_CONF_B] = 0x0A; /* CONFIG B */ - nvr->regs[MRTC_CONF_C] = 0x28; /* CONFIG C */ - nvr->regs[MRTC_CONF_D] = 0x12; /* CONFIG D */ - nvr->regs[MRTC_CONF_E] = 0x0A; /* CONFIG E */ + nvr->regs[MRTC_CONF_A] = 0x00; /* CONFIG A */ + nvr->regs[MRTC_CONF_B] = 0x0A; /* CONFIG B */ + nvr->regs[MRTC_CONF_C] = 0x28; /* CONFIG C */ + nvr->regs[MRTC_CONF_D] = 0x12; /* CONFIG D */ + nvr->regs[MRTC_CONF_E] = 0x0A; /* CONFIG E */ - nvr->regs[MRTC_CHECK_LO] = 0x00; /* checksum (LO) */ - nvr->regs[MRTC_CHECK_HI] = 0x00; /* checksum (HI) */ + nvr->regs[MRTC_CHECK_LO] = 0x00; /* checksum (LO) */ + nvr->regs[MRTC_CHECK_HI] = 0x00; /* checksum (HI) */ - nvr->regs[MRTC_CTRLSTAT] = 0x01; /* status/control */ + nvr->regs[MRTC_CTRLSTAT] = 0x01; /* status/control */ /* Generate a valid checksum. */ nvr->regs[MRTC_CHECK_LO] = rtc_checksum(nvr->regs); } - /* Execute a JIM control command. */ static void jim_set(europc_t *sys, uint8_t reg, uint8_t val) { - switch(reg) { - case 0: /* MISC control (WO) */ - // bit0: enable MOUSE - // bit1: enable joystick - break; + switch (reg) { + case 0: /* MISC control (WO) */ + // bit0: enable MOUSE + // bit1: enable joystick + break; - case 2: /* AGA control */ - if (! (val & 0x80)) { - /* Reset AGA. */ - break; - } + case 2: /* AGA control */ + if (!(val & 0x80)) { + /* Reset AGA. */ + break; + } - switch (val) { - case 0x1f: /* 0001 1111 */ - case 0x0b: /* 0000 1011 */ - //europc_jim.mode=AGA_MONO; - europc_log("EuroPC: AGA Monochrome mode!\n"); - break; + switch (val) { + case 0x1f: /* 0001 1111 */ + case 0x0b: /* 0000 1011 */ +#if 0 + europc_jim.mode=AGA_MONO; +#endif + europc_log("EuroPC: AGA Monochrome mode!\n"); + break; - case 0x18: /* 0001 1000 */ - case 0x1a: /* 0001 1010 */ - //europc_jim.mode=AGA_COLOR; - break; + case 0x18: /* 0001 1000 */ + case 0x1a: /* 0001 1010 */ +#if 0 + europc_jim.mode=AGA_COLOR; +#endif + break; - case 0x0e: /* 0000 1100 */ - /*80 columns? */ - europc_log("EuroPC: AGA 80-column mode!\n"); - break; + case 0x0e: /* 0000 1100 */ + /*80 columns? */ + europc_log("EuroPC: AGA 80-column mode!\n"); + break; - case 0x0d: /* 0000 1011 */ - /*40 columns? */ - europc_log("EuroPC: AGA 40-column mode!\n"); - break; + case 0x0d: /* 0000 1011 */ + /*40 columns? */ + europc_log("EuroPC: AGA 40-column mode!\n"); + break; - default: - //europc_jim.mode=AGA_OFF; - break; - } - break; + default: +#if 0 + europc_jim.mode=AGA_OFF; +#endif + break; + } + break; - case 4: /* CPU Speed control */ - switch(val & 0xc0) { - case 0x00: /* 4.77 MHz */ -// cpu_set_clockscale(0, 1.0/2); - break; + case 4: /* CPU Speed control */ + switch (val & 0xc0) { + case 0x00: /* 4.77 MHz */ +#if 0 + cpu_set_clockscale(0, 1.0/2); +#endif + break; - case 0x40: /* 7.16 MHz */ -// cpu_set_clockscale(0, 3.0/4); - break; + case 0x40: /* 7.16 MHz */ +#if 0 + cpu_set_clockscale(0, 3.0/4); +#endif + break; - default: /* 9.54 MHz */ -// cpu_set_clockscale(0, 1);break; - break; - } - break; + default: /* 9.54 MHz */ +#if 0 + cpu_set_clockscale(0, 1);break; +#endif + break; + } + break; - default: - break; + default: + break; } sys->regs[reg] = val; } - /* Write to one of the JIM registers. */ static void jim_write(uint16_t addr, uint8_t val, void *priv) { - europc_t *sys = (europc_t *)priv; - uint8_t b; + europc_t *sys = (europc_t *) priv; + uint8_t b; #if EUROPC_DEBUG > 1 europc_log("EuroPC: jim_wr(%04x, %02x)\n", addr, val); #endif switch (addr & 0x000f) { - case 0x00: /* JIM internal registers (WRONLY) */ - case 0x01: - case 0x02: - case 0x03: - case 0x04: /* JIM internal registers (R/W) */ - case 0x05: - case 0x06: - case 0x07: - jim_set(sys, (addr & 0x07), val); - break; + case 0x00: /* JIM internal registers (WRONLY) */ + case 0x01: + case 0x02: + case 0x03: + case 0x04: /* JIM internal registers (R/W) */ + case 0x05: + case 0x06: + case 0x07: + jim_set(sys, (addr & 0x07), val); + break; - case 0x0a: /* M3002 RTC INDEX/DATA register */ - switch(sys->nvr_stat) { - case 0: /* save index */ - sys->nvr_addr = val & 0x0f; - sys->nvr_stat++; - break; + case 0x0a: /* M3002 RTC INDEX/DATA register */ + switch (sys->nvr_stat) { + case 0: /* save index */ + sys->nvr_addr = val & 0x0f; + sys->nvr_stat++; + break; - case 1: /* save data HI nibble */ - b = sys->nvr.regs[sys->nvr_addr] & 0x0f; - b |= (val << 4); - sys->nvr.regs[sys->nvr_addr] = b; - sys->nvr_stat++; - nvr_dosave++; - break; + case 1: /* save data HI nibble */ + b = sys->nvr.regs[sys->nvr_addr] & 0x0f; + b |= (val << 4); + sys->nvr.regs[sys->nvr_addr] = b; + sys->nvr_stat++; + nvr_dosave++; + break; - case 2: /* save data LO nibble */ - b = sys->nvr.regs[sys->nvr_addr] & 0xf0; - b |= (val & 0x0f); - sys->nvr.regs[sys->nvr_addr] = b; - sys->nvr_stat = 0; - nvr_dosave++; - break; - } - break; + case 2: /* save data LO nibble */ + b = sys->nvr.regs[sys->nvr_addr] & 0xf0; + b |= (val & 0x0f); + sys->nvr.regs[sys->nvr_addr] = b; + sys->nvr_stat = 0; + nvr_dosave++; + break; - default: - europc_log("EuroPC: invalid JIM write %02x, val %02x\n", addr, val); - break; + default: + break; + } + break; + + default: + europc_log("EuroPC: invalid JIM write %02x, val %02x\n", addr, val); + break; } } - /* Read from one of the JIM registers. */ static uint8_t jim_read(uint16_t addr, void *priv) { - europc_t *sys = (europc_t *)priv; - uint8_t r = 0xff; + europc_t *sys = (europc_t *) priv; + uint8_t r = 0xff; switch (addr & 0x000f) { - case 0x00: /* JIM internal registers (WRONLY) */ - case 0x01: - case 0x02: - case 0x03: - r = 0x00; - break; + case 0x00: /* JIM internal registers (WRONLY) */ + case 0x01: + case 0x02: + case 0x03: + r = 0x00; + break; - case 0x04: /* JIM internal registers (R/W) */ - case 0x05: - case 0x06: - case 0x07: - r = sys->regs[addr & 0x07]; - break; + case 0x04: /* JIM internal registers (R/W) */ + case 0x05: + case 0x06: + case 0x07: + r = sys->regs[addr & 0x07]; + break; - case 0x0a: /* M3002 RTC INDEX/DATA register */ - switch(sys->nvr_stat) { - case 0: - r = 0x00; - break; + case 0x0a: /* M3002 RTC INDEX/DATA register */ + switch (sys->nvr_stat) { + case 0: + r = 0x00; + break; - case 1: /* read data HI nibble */ - r = (sys->nvr.regs[sys->nvr_addr] >> 4); - sys->nvr_stat++; - break; + case 1: /* read data HI nibble */ + r = (sys->nvr.regs[sys->nvr_addr] >> 4); + sys->nvr_stat++; + break; - case 2: /* read data LO nibble */ - r = (sys->nvr.regs[sys->nvr_addr] & 0x0f); - sys->nvr_stat = 0; - break; - } - break; + case 2: /* read data LO nibble */ + r = (sys->nvr.regs[sys->nvr_addr] & 0x0f); + sys->nvr_stat = 0; + break; - default: - europc_log("EuroPC: invalid JIM read %02x\n", addr); - break; + default: + break; + } + break; + + default: + europc_log("EuroPC: invalid JIM read %02x\n", addr); + break; } #if EUROPC_DEBUG > 1 europc_log("EuroPC: jim_rd(%04x): %02x\n", addr, r); #endif - return(r); + return r; } - /* Initialize the mainboard 'device' of the machine. */ static void * -europc_boot(const device_t *info) +europc_boot(UNUSED(const device_t *info)) { europc_t *sys = &europc; - uint8_t b; + uint8_t b; #if EUROPC_DEBUG europc_log("EuroPC: booting mainboard..\n"); #endif europc_log("EuroPC: NVR=[ %02x %02x %02x %02x %02x ] %sVALID\n", - sys->nvr.regs[MRTC_CONF_A], sys->nvr.regs[MRTC_CONF_B], - sys->nvr.regs[MRTC_CONF_C], sys->nvr.regs[MRTC_CONF_D], - sys->nvr.regs[MRTC_CONF_E], - (sys->nvr.regs[MRTC_CHECK_LO]!=rtc_checksum(sys->nvr.regs))?"IN":""); + sys->nvr.regs[MRTC_CONF_A], sys->nvr.regs[MRTC_CONF_B], + sys->nvr.regs[MRTC_CONF_C], sys->nvr.regs[MRTC_CONF_D], + sys->nvr.regs[MRTC_CONF_E], + (sys->nvr.regs[MRTC_CHECK_LO] != rtc_checksum(sys->nvr.regs)) ? "IN" : ""); /* * Now that we have initialized the NVR (either from file, @@ -564,59 +568,65 @@ europc_boot(const device_t *info) * with values set by the user. */ b = (sys->nvr.regs[MRTC_CONF_D] & ~0x17); - video_reset(gfxcard); + video_reset(gfxcard[0]); if (video_is_cga()) - b |= 0x12; /* external video, CGA80 */ + b |= 0x12; /* external video, CGA80 */ else if (video_is_mda()) - b |= 0x03; /* external video, mono */ + b |= 0x03; /* external video, mono */ else - b |= 0x10; /* external video, special */ + b |= 0x10; /* external video, special */ sys->nvr.regs[MRTC_CONF_D] = b; /* Update the memory size. */ b = (sys->nvr.regs[MRTC_CONF_C] & 0xf3); - switch(mem_size) { - case 256: - b |= 0x04; - break; + switch (mem_size) { + case 256: + b |= 0x04; + break; - case 512: - b |= 0x08; - break; + case 512: + b |= 0x08; + break; - case 640: - b |= 0x00; - break; + case 640: + b |= 0x00; + break; + + default: + break; } sys->nvr.regs[MRTC_CONF_C] = b; /* Update CPU speed. */ b = (sys->nvr.regs[MRTC_CONF_D] & 0x3f); - switch(cpu) { - case 0: /* 8088, 4.77 MHz */ - b |= 0x00; - break; + switch (cpu) { + case 0: /* 8088, 4.77 MHz */ + b |= 0x00; + break; - case 1: /* 8088, 7.15 MHz */ - b |= 0x40; - break; + case 1: /* 8088, 7.15 MHz */ + b |= 0x40; + break; - case 2: /* 8088, 9.56 MHz */ - b |= 0x80; - break; + case 2: /* 8088, 9.56 MHz */ + b |= 0x80; + break; + + default: + break; } sys->nvr.regs[MRTC_CONF_D] = b; /* Set up game port. */ b = (sys->nvr.regs[MRTC_CONF_C] & 0xfc); if (mouse_type == MOUSE_TYPE_INTERNAL) { - sys->mouse = device_add(&mouse_logibus_onboard_device); - mouse_bus_set_irq(sys->mouse, 2); - /* Configure the port for (Bus Mouse Compatible) Mouse. */ - b |= 0x01; + sys->mouse = device_add(&mouse_logibus_onboard_device); + mouse_bus_set_irq(sys->mouse, 2); + /* Configure the port for (Bus Mouse Compatible) Mouse. */ + b |= 0x01; } else if (joystick_type) - b |= 0x02; /* enable port as joysticks */ + b |= 0x02; /* enable port as joysticks */ sys->nvr.regs[MRTC_CONF_C] = b; #if 0 @@ -637,67 +647,68 @@ europc_boot(const device_t *info) * the way of other cards that need this range. */ io_sethandler(sys->jim, 16, - jim_read,NULL,NULL, jim_write,NULL,NULL, sys); + jim_read, NULL, NULL, jim_write, NULL, NULL, sys); /* Only after JIM has been initialized. */ - (void)device_add(&keyboard_xt_device); + (void) device_add(&keyboard_xt_device); /* Enable and set up the FDC. */ - (void)device_add(&fdc_xt_device); + (void) device_add(&fdc_xt_device); - /* + /* * Set up and enable the HD20 disk controller. * * We only do this if we have not configured another one. */ if (hdc_current == 1) - (void)device_add(&xta_hd20_device); + (void) device_add(&xta_hd20_device); - return(sys); + return sys; } - static void -europc_close(void *priv) +europc_close(UNUSED(void *priv)) { nvr_t *nvr = &europc.nvr; if (nvr->fn != NULL) - free(nvr->fn); + free(nvr->fn); } - static const device_config_t europc_config[] = { + // clang-format off { - "js9", "JS9 Jumper (JIM)", CONFIG_INT, "", 0, "", { 0 }, - { - { - "Disabled (250h)", 0 - }, - { - "Enabled (350h)", 1 - }, - { - "" - } - }, + .name = "js9", + .description = "JS9 Jumper (JIM)", + .type = CONFIG_INT, + .default_string = "", + .default_int = 0, + .file_filter = "", + .spinner = { 0 }, + .selection = { + { .description = "Disabled (250h)", .value = 0 }, + { .description = "Enabled (350h)", .value = 1 }, + { .description = "" } + }, }, - { - "", "", -1 - } + { .name = "", .description = "", .type = CONFIG_END } + // clang-format on }; - const device_t europc_device = { - "EuroPC System Board", - "europc", - 0, 0, - europc_boot, europc_close, NULL, - { NULL }, NULL, NULL, - europc_config + .name = "EuroPC System Board", + .internal_name = "europc", + .flags = 0, + .local = 0, + .init = europc_boot, + .close = europc_close, + .reset = NULL, + { .available = NULL }, + .speed_changed = NULL, + .force_redraw = NULL, + .config = europc_config }; - /* * This function sets up the Scheider EuroPC machine. * @@ -712,13 +723,13 @@ machine_europc_init(const machine_t *model) int ret; ret = bios_load_linear("roms/machines/europc/50145", - 0x000f8000, 32768, 0); + 0x000f8000, 32768, 0); if (bios_only || !ret) - return ret; + return ret; machine_common_init(model); - pit_ctr_set_out_func(&pit->counters[1], pit_refresh_timer_xt); + pit_devs[0].set_out_func(pit_devs[0].data, 1, pit_refresh_timer_xt); nmi_init(); @@ -728,12 +739,12 @@ machine_europc_init(const machine_t *model) /* This is machine specific. */ europc.nvr.size = model->nvrmask + 1; - europc.nvr.irq = -1; + europc.nvr.irq = -1; /* Set up any local handlers here. */ europc.nvr.reset = rtc_reset; europc.nvr.start = rtc_start; - europc.nvr.tick = europc_rtc_tick; + europc.nvr.tick = europc_rtc_tick; /* Initialize the actual NVR. */ nvr_init(&europc.nvr); diff --git a/src/machine/m_pcjr.c b/src/machine/m_pcjr.c index e6cafb1ac..80a0ffbc1 100644 --- a/src/machine/m_pcjr.c +++ b/src/machine/m_pcjr.c @@ -1,22 +1,22 @@ /* - * 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. + * 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. + * This file is part of the 86Box distribution. * - * Emulation of the IBM PCjr. + * Emulation of the IBM PCjr. * * * - * Authors: Sarah Walker, - * Miran Grca, - * Fred N. van Kempen, + * Authors: Sarah Walker, + * Miran Grca, + * Fred N. van Kempen, * - * Copyright 2008-2019 Sarah Walker. - * Copyright 2016-2019 Miran Grca. - * Copyright 2017-2019 Fred N. van Kempen. + * Copyright 2008-2019 Sarah Walker. + * Copyright 2016-2019 Miran Grca. + * Copyright 2017-2019 Fred N. van Kempen. */ #include #include @@ -37,6 +37,7 @@ #include <86box/pit.h> #include <86box/mem.h> #include <86box/device.h> +#include <86box/gameport.h> #include <86box/serial.h> #include <86box/keyboard.h> #include <86box/rom.h> @@ -48,58 +49,65 @@ #include <86box/video.h> #include <86box/vid_cga_comp.h> #include <86box/machine.h> +#include <86box/plat_unused.h> +#define PCJR_RGB 0 +#define PCJR_COMPOSITE 1 -#define PCJR_RGB 0 -#define PCJR_COMPOSITE 1 +#define STAT_PARITY 0x80 +#define STAT_RTIMEOUT 0x40 +#define STAT_TTIMEOUT 0x20 +#define STAT_LOCK 0x10 +#define STAT_CD 0x08 +#define STAT_SYSFLAG 0x04 +#define STAT_IFULL 0x02 +#define STAT_OFULL 0x01 -#define STAT_PARITY 0x80 -#define STAT_RTIMEOUT 0x40 -#define STAT_TTIMEOUT 0x20 -#define STAT_LOCK 0x10 -#define STAT_CD 0x08 -#define STAT_SYSFLAG 0x04 -#define STAT_IFULL 0x02 -#define STAT_OFULL 0x01 - - -typedef struct { +typedef struct pcjr_t { /* Video Controller stuff. */ mem_mapping_t mapping; - uint8_t crtc[32]; - int crtcreg; - int array_index; - uint8_t array[32]; - int array_ff; - int memctrl; - uint8_t stat; - int addr_mode; - uint8_t *vram, - *b8000; - int linepos, displine; - int sc, vc; - int dispon; - int con, coff, cursoron, blink; - int vsynctime; - int vadj; - uint16_t ma, maback; - uint64_t dispontime, dispofftime; - pc_timer_t timer; - int firstline, lastline; - int composite; + uint8_t crtc[32]; + int crtcreg; + int array_index; + uint8_t array[32]; + int array_ff; + int memctrl; + uint8_t stat; + int addr_mode; + uint8_t *vram; + uint8_t *b8000; + int linepos; + int displine; + int sc; + int vc; + int dispon; + int con; + int coff; + int cursoron; + int blink; + int vsynctime; + int fullchange; + int vadj; + uint16_t ma; + uint16_t maback; + uint64_t dispontime; + uint64_t dispofftime; + pc_timer_t timer; + int firstline; + int lastline; + int composite; /* Keyboard Controller stuff. */ - int latched; - int data; - int serial_data[44]; - int serial_pos; - uint8_t pa; - uint8_t pb; - pc_timer_t send_delay_timer; + int latched; + int data; + int serial_data[44]; + int serial_pos; + uint8_t pa; + uint8_t pb; + pc_timer_t send_delay_timer; } pcjr_t; -static video_timings_t timing_dram = {VIDEO_BUS, 0,0,0, 0,0,0}; /*No additional waitstates*/ - +static video_timings_t timing_dram = { VIDEO_BUS, 0, 0, 0, 0, 0, 0 }; /*No additional waitstates*/ static uint8_t crtcmask[32] = { 0xff, 0xff, 0xff, 0xff, 0x7f, 0x1f, 0x7f, 0x7f, @@ -107,727 +115,728 @@ static uint8_t crtcmask[32] = { 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }; -static uint8_t key_queue[16]; -static int key_queue_start = 0, - key_queue_end = 0; - +static uint8_t key_queue[16]; +static int key_queue_start = 0; +static int key_queue_end = 0; static void recalc_address(pcjr_t *pcjr) { + uint8_t masked_memctrl = pcjr->memctrl; + + /* According to the Technical Reference, bits 2 and 5 are + ignored if there is only 64k of RAM and there are only + 4 pages. */ + if (mem_size < 128) + masked_memctrl &= ~0x24; + if ((pcjr->memctrl & 0xc0) == 0xc0) { - pcjr->vram = &ram[(pcjr->memctrl & 0x06) << 14]; - pcjr->b8000 = &ram[(pcjr->memctrl & 0x30) << 11]; + pcjr->vram = &ram[(masked_memctrl & 0x06) << 14]; + pcjr->b8000 = &ram[(masked_memctrl & 0x30) << 11]; } else { - pcjr->vram = &ram[(pcjr->memctrl & 0x07) << 14]; - pcjr->b8000 = &ram[(pcjr->memctrl & 0x38) << 11]; + pcjr->vram = &ram[(masked_memctrl & 0x07) << 14]; + pcjr->b8000 = &ram[(masked_memctrl & 0x38) << 11]; } } - static void recalc_timings(pcjr_t *pcjr) { - double _dispontime, _dispofftime, disptime; + double _dispontime; + double _dispofftime; + double disptime; if (pcjr->array[0] & 1) { - disptime = pcjr->crtc[0] + 1; - _dispontime = pcjr->crtc[1]; + disptime = pcjr->crtc[0] + 1; + _dispontime = pcjr->crtc[1]; } else { - disptime = (pcjr->crtc[0] + 1) << 1; - _dispontime = pcjr->crtc[1] << 1; + disptime = (pcjr->crtc[0] + 1) << 1; + _dispontime = pcjr->crtc[1] << 1; } _dispofftime = disptime - _dispontime; - _dispontime *= CGACONST; + _dispontime *= CGACONST; _dispofftime *= CGACONST; - pcjr->dispontime = (uint64_t)(_dispontime); - pcjr->dispofftime = (uint64_t)(_dispofftime); + pcjr->dispontime = (uint64_t) (_dispontime); + pcjr->dispofftime = (uint64_t) (_dispofftime); } - static void -vid_out(uint16_t addr, uint8_t val, void *p) +vid_out(uint16_t addr, uint8_t val, void *priv) { - pcjr_t *pcjr = (pcjr_t *)p; + pcjr_t *pcjr = (pcjr_t *) priv; uint8_t old; switch (addr) { - case 0x3d4: - pcjr->crtcreg = val & 0x1f; - return; + case 0x3d0: + case 0x3d2: + case 0x3d4: + case 0x3d6: + pcjr->crtcreg = val & 0x1f; + return; - case 0x3d5: - old = pcjr->crtc[pcjr->crtcreg]; - pcjr->crtc[pcjr->crtcreg] = val & crtcmask[pcjr->crtcreg]; - if (old != val) { - if (pcjr->crtcreg < 0xe || pcjr->crtcreg > 0x10) { - fullchange = changeframecount; - recalc_timings(pcjr); - } - } - return; + case 0x3d1: + case 0x3d3: + case 0x3d5: + case 0x3d7: + old = pcjr->crtc[pcjr->crtcreg]; + pcjr->crtc[pcjr->crtcreg] = val & crtcmask[pcjr->crtcreg]; + if (old != val) { + if (pcjr->crtcreg < 0xe || pcjr->crtcreg > 0x10) { + pcjr->fullchange = changeframecount; + recalc_timings(pcjr); + } + } + return; - case 0x3da: - if (!pcjr->array_ff) - pcjr->array_index = val & 0x1f; - else { - if (pcjr->array_index & 0x10) - val &= 0x0f; - pcjr->array[pcjr->array_index & 0x1f] = val; - if (!(pcjr->array_index & 0x1f)) - update_cga16_color(val); - } - pcjr->array_ff = !pcjr->array_ff; - break; + case 0x3da: + if (!pcjr->array_ff) + pcjr->array_index = val & 0x1f; + else { + if (pcjr->array_index & 0x10) + val &= 0x0f; + pcjr->array[pcjr->array_index & 0x1f] = val; + if (!(pcjr->array_index & 0x1f)) + update_cga16_color(val); + } + pcjr->array_ff = !pcjr->array_ff; + break; - case 0x3df: - pcjr->memctrl = val; - pcjr->addr_mode = val >> 6; - recalc_address(pcjr); - break; + case 0x3df: + pcjr->memctrl = val; + pcjr->pa = val; /* The PCjr BIOS expects the value written to 3DF to + then be readable from port 60, others it errors out + with only 64k RAM set (but somehow, still works with + 128k or more RAM). */ + pcjr->addr_mode = val >> 6; + recalc_address(pcjr); + break; + + default: + break; } } - static uint8_t -vid_in(uint16_t addr, void *p) +vid_in(uint16_t addr, void *priv) { - pcjr_t *pcjr = (pcjr_t *)p; - uint8_t ret = 0xff; + pcjr_t *pcjr = (pcjr_t *) priv; + uint8_t ret = 0xff; switch (addr) { - case 0x3d4: - ret = pcjr->crtcreg; - break; + case 0x3d0: + case 0x3d2: + case 0x3d4: + case 0x3d6: + ret = pcjr->crtcreg; + break; - case 0x3d5: - ret = pcjr->crtc[pcjr->crtcreg]; - break; + case 0x3d1: + case 0x3d3: + case 0x3d5: + case 0x3d7: + ret = pcjr->crtc[pcjr->crtcreg]; + break; - case 0x3da: - pcjr->array_ff = 0; - pcjr->stat ^= 0x10; - ret = pcjr->stat; - break; + case 0x3da: + pcjr->array_ff = 0; + pcjr->stat ^= 0x10; + ret = pcjr->stat; + break; + + default: + break; } - return(ret); + return ret; } - static void -vid_write(uint32_t addr, uint8_t val, void *p) +vid_write(uint32_t addr, uint8_t val, void *priv) { - pcjr_t *pcjr = (pcjr_t *)p; + pcjr_t *pcjr = (pcjr_t *) priv; - if (pcjr->memctrl == -1) return; + if (pcjr->memctrl == -1) + return; pcjr->b8000[addr & 0x3fff] = val; } - static uint8_t -vid_read(uint32_t addr, void *p) +vid_read(uint32_t addr, void *priv) { - pcjr_t *pcjr = (pcjr_t *)p; + const pcjr_t *pcjr = (pcjr_t *) priv; - if (pcjr->memctrl == -1) return(0xff); - - return(pcjr->b8000[addr & 0x3fff]); + if (pcjr->memctrl == -1) + return 0xff; + + return (pcjr->b8000[addr & 0x3fff]); } - static void -vid_poll(void *p) +vid_poll(void *priv) { - pcjr_t *pcjr = (pcjr_t *)p; - uint16_t ca = (pcjr->crtc[15] | (pcjr->crtc[14] << 8)) & 0x3fff; - int drawcursor; - int x, c, xs_temp, ys_temp; - int oldvc; - uint8_t chr, attr; + pcjr_t *pcjr = (pcjr_t *) priv; + uint16_t ca = (pcjr->crtc[15] | (pcjr->crtc[14] << 8)) & 0x3fff; + int drawcursor; + int x; + int xs_temp; + int ys_temp; + int oldvc; + uint8_t chr; + uint8_t attr; uint16_t dat; - int cols[4]; - int oldsc; + int cols[4]; + int oldsc; - if (! pcjr->linepos) { - timer_advance_u64(&pcjr->timer, pcjr->dispofftime); - pcjr->stat &= ~1; - pcjr->linepos = 1; - oldsc = pcjr->sc; - if ((pcjr->crtc[8] & 3) == 3) - pcjr->sc = (pcjr->sc << 1) & 7; - if (pcjr->dispon) { - uint16_t offset = 0; - uint16_t mask = 0x1fff; + if (!pcjr->linepos) { + timer_advance_u64(&pcjr->timer, pcjr->dispofftime); + pcjr->stat &= ~1; + pcjr->linepos = 1; + oldsc = pcjr->sc; + if ((pcjr->crtc[8] & 3) == 3) + pcjr->sc = (pcjr->sc << 1) & 7; + if (pcjr->dispon) { + uint16_t offset = 0; + uint16_t mask = 0x1fff; - if (pcjr->displine < pcjr->firstline) { - pcjr->firstline = pcjr->displine; - video_wait_for_buffer(); - } - pcjr->lastline = pcjr->displine; - cols[0] = (pcjr->array[2] & 0xf) + 16; - for (c = 0; c < 8; c++) { - ((uint32_t *)buffer32->line[pcjr->displine])[c] = cols[0]; - if (pcjr->array[0] & 1) { - buffer32->line[(pcjr->displine << 1)][c + (pcjr->crtc[1] << 3) + 8] = - buffer32->line[(pcjr->displine << 1) + 1][c + (pcjr->crtc[1] << 3) + 8] = cols[0]; - } else { - buffer32->line[(pcjr->displine << 1)][c + (pcjr->crtc[1] << 4) + 8] = - buffer32->line[(pcjr->displine << 1) + 1][c + (pcjr->crtc[1] << 4) + 8] = cols[0]; - } - } + if (pcjr->displine < pcjr->firstline) { + pcjr->firstline = pcjr->displine; + video_wait_for_buffer(); + } + pcjr->lastline = pcjr->displine; + cols[0] = (pcjr->array[2] & 0xf) + 16; + for (uint8_t c = 0; c < 8; c++) { + (buffer32->line[pcjr->displine])[c] = cols[0]; + if (pcjr->array[0] & 1) { + buffer32->line[pcjr->displine << 1][c + (pcjr->crtc[1] << 3) + 8] = buffer32->line[(pcjr->displine << 1) + 1][c + (pcjr->crtc[1] << 3) + 8] = cols[0]; + } else { + buffer32->line[pcjr->displine << 1][c + (pcjr->crtc[1] << 4) + 8] = buffer32->line[(pcjr->displine << 1) + 1][c + (pcjr->crtc[1] << 4) + 8] = cols[0]; + } + } - switch (pcjr->addr_mode) { - case 0: /*Alpha*/ - offset = 0; - mask = 0x3fff; - break; - case 1: /*Low resolution graphics*/ - offset = (pcjr->sc & 1) * 0x2000; - break; - case 3: /*High resolution graphics*/ - offset = (pcjr->sc & 3) * 0x2000; - break; - } - switch ((pcjr->array[0] & 0x13) | ((pcjr->array[3] & 0x08) << 5)) { - case 0x13: /*320x200x16*/ - for (x = 0; x < pcjr->crtc[1]; x++) { - dat = (pcjr->vram[((pcjr->ma << 1) & mask) + offset] << 8) | - pcjr->vram[((pcjr->ma << 1) & mask) + offset + 1]; - pcjr->ma++; - buffer32->line[(pcjr->displine << 1)][(x << 3) + 8] = buffer32->line[(pcjr->displine << 1)][(x << 3) + 9] = - buffer32->line[(pcjr->displine << 1) + 1][(x << 3) + 8] = buffer32->line[(pcjr->displine << 1) + 1][(x << 3) + 9] = - pcjr->array[((dat >> 12) & pcjr->array[1]) + 16] + 16; - buffer32->line[(pcjr->displine << 1)][(x << 3) + 10] = buffer32->line[(pcjr->displine << 1)][(x << 3) + 11] = - buffer32->line[(pcjr->displine << 1) + 1][(x << 3) + 10] = buffer32->line[(pcjr->displine << 1) + 1][(x << 3) + 11] = - pcjr->array[((dat >> 8) & pcjr->array[1]) + 16] + 16; - buffer32->line[(pcjr->displine << 1)][(x << 3) + 12] = buffer32->line[(pcjr->displine << 1)][(x << 3) + 13] = - buffer32->line[(pcjr->displine << 1) + 1][(x << 3) + 12] = buffer32->line[(pcjr->displine << 1) + 1][(x << 3) + 13] = - pcjr->array[((dat >> 4) & pcjr->array[1]) + 16] + 16; - buffer32->line[(pcjr->displine << 1)][(x << 3) + 14] = buffer32->line[(pcjr->displine << 1)][(x << 3) + 15] = - buffer32->line[(pcjr->displine << 1) + 1][(x << 3) + 14] = buffer32->line[(pcjr->displine << 1) + 1][(x << 3) + 15] = - pcjr->array[(dat & pcjr->array[1]) + 16] + 16; - } - break; - case 0x12: /*160x200x16*/ - for (x = 0; x < pcjr->crtc[1]; x++) { - dat = (pcjr->vram[((pcjr->ma << 1) & mask) + offset] << 8) | - pcjr->vram[((pcjr->ma << 1) & mask) + offset + 1]; - pcjr->ma++; - buffer32->line[(pcjr->displine << 1)][(x << 4) + 8] = buffer32->line[(pcjr->displine << 1)][(x << 4) + 9] = - buffer32->line[(pcjr->displine << 1)][(x << 4) + 10] = buffer32->line[(pcjr->displine << 1)][(x << 4) + 11] = - buffer32->line[(pcjr->displine << 1) + 1][(x << 4) + 8] = buffer32->line[(pcjr->displine << 1) + 1][(x << 4) + 9] = - buffer32->line[(pcjr->displine << 1) + 1][(x << 4) + 10] = buffer32->line[(pcjr->displine << 1) + 1][(x << 4) + 11] = - pcjr->array[((dat >> 12) & pcjr->array[1]) + 16] + 16; - buffer32->line[(pcjr->displine << 1)][(x << 4) + 12] = buffer32->line[(pcjr->displine << 1)][(x << 4) + 13] = - buffer32->line[(pcjr->displine << 1)][(x << 4) + 14] = buffer32->line[(pcjr->displine << 1)][(x << 4) + 15] = - buffer32->line[(pcjr->displine << 1) + 1][(x << 4) + 12] = buffer32->line[(pcjr->displine << 1) + 1][(x << 4) + 13] = - buffer32->line[(pcjr->displine << 1) + 1][(x << 4) + 14] = buffer32->line[(pcjr->displine << 1) + 1][(x << 4) + 15] = - pcjr->array[((dat >> 8) & pcjr->array[1]) + 16] + 16; - buffer32->line[(pcjr->displine << 1)][(x << 4) + 16] = buffer32->line[(pcjr->displine << 1)][(x << 4) + 17] = - buffer32->line[(pcjr->displine << 1)][(x << 4) + 18] = buffer32->line[(pcjr->displine << 1)][(x << 4) + 19] = - buffer32->line[(pcjr->displine << 1) + 1][(x << 4) + 16] = buffer32->line[(pcjr->displine << 1) + 1][(x << 4) + 17] = - buffer32->line[(pcjr->displine << 1) + 1][(x << 4) + 18] = buffer32->line[(pcjr->displine << 1) + 1][(x << 4) + 19] = - pcjr->array[((dat >> 4) & pcjr->array[1]) + 16] + 16; - buffer32->line[(pcjr->displine << 1)][(x << 4) + 20] = buffer32->line[(pcjr->displine << 1)][(x << 4) + 21] = - buffer32->line[(pcjr->displine << 1)][(x << 4) + 22] = buffer32->line[(pcjr->displine << 1)][(x << 4) + 23] = - buffer32->line[(pcjr->displine << 1) + 1][(x << 4) + 20] = buffer32->line[(pcjr->displine << 1) + 1][(x << 4) + 21] = - buffer32->line[(pcjr->displine << 1) + 1][(x << 4) + 22] = buffer32->line[(pcjr->displine << 1) + 1][(x << 4) + 23] = - pcjr->array[(dat & pcjr->array[1]) + 16] + 16; - } - break; - case 0x03: /*640x200x4*/ - for (x = 0; x < pcjr->crtc[1]; x++) { - dat = (pcjr->vram[((pcjr->ma << 1) & mask) + offset] << 8) | - pcjr->vram[((pcjr->ma << 1) & mask) + offset + 1]; - pcjr->ma++; - for (c = 0; c < 8; c++) { - chr = (dat >> 7) & 1; - chr |= ((dat >> 14) & 2); - buffer32->line[(pcjr->displine << 1)][(x << 3) + 8 + c] = buffer32->line[(pcjr->displine << 1) + 1][(x << 3) + 8 + c] = - pcjr->array[(chr & pcjr->array[1]) + 16] + 16; - dat <<= 1; - } - } - break; - case 0x01: /*80 column text*/ - for (x = 0; x < pcjr->crtc[1]; x++) { - chr = pcjr->vram[((pcjr->ma << 1) & mask) + offset]; - attr = pcjr->vram[((pcjr->ma << 1) & mask) + offset + 1]; - drawcursor = ((pcjr->ma == ca) && pcjr->con && pcjr->cursoron); - if (pcjr->array[3] & 4) { - cols[1] = pcjr->array[ ((attr & 15) & pcjr->array[1]) + 16] + 16; - cols[0] = pcjr->array[(((attr >> 4) & 7) & pcjr->array[1]) + 16] + 16; - if ((pcjr->blink & 16) && (attr & 0x80) && !drawcursor) - cols[1] = cols[0]; - } else { - cols[1] = pcjr->array[((attr & 15) & pcjr->array[1]) + 16] + 16; - cols[0] = pcjr->array[((attr >> 4) & pcjr->array[1]) + 16] + 16; - } - if (pcjr->sc & 8) { - for (c = 0; c < 8; c++) { - buffer32->line[(pcjr->displine << 1)][(x << 3) + c + 8] = - buffer32->line[(pcjr->displine << 1) + 1][(x << 3) + c + 8] = cols[0]; - } - } else { - for (c = 0; c < 8; c++) { - buffer32->line[(pcjr->displine << 1)][(x << 3) + c + 8] = - buffer32->line[(pcjr->displine << 1) + 1][(x << 3) + c + 8] = - cols[(fontdat[chr][pcjr->sc & 7] & (1 << (c ^ 7))) ? 1 : 0]; - } - } - if (drawcursor) { - for (c = 0; c < 8; c++) { - buffer32->line[(pcjr->displine << 1)][(x << 3) + c + 8] ^= 15; - buffer32->line[(pcjr->displine << 1) + 1][(x << 3) + c + 8] ^= 15; - } - } - pcjr->ma++; - } - break; - case 0x00: /*40 column text*/ - for (x = 0; x < pcjr->crtc[1]; x++) { - chr = pcjr->vram[((pcjr->ma << 1) & mask) + offset]; - attr = pcjr->vram[((pcjr->ma << 1) & mask) + offset + 1]; - drawcursor = ((pcjr->ma == ca) && pcjr->con && pcjr->cursoron); - if (pcjr->array[3] & 4) { - cols[1] = pcjr->array[ ((attr & 15) & pcjr->array[1]) + 16] + 16; - cols[0] = pcjr->array[(((attr >> 4) & 7) & pcjr->array[1]) + 16] + 16; - if ((pcjr->blink & 16) && (attr & 0x80) && !drawcursor) - cols[1] = cols[0]; - } else { - cols[1] = pcjr->array[((attr & 15) & pcjr->array[1]) + 16] + 16; - cols[0] = pcjr->array[((attr >> 4) & pcjr->array[1]) + 16] + 16; - } - pcjr->ma++; - if (pcjr->sc & 8) { - for (c = 0; c < 8; c++) { - buffer32->line[(pcjr->displine << 1)][(x << 4) + (c << 1) + 8] = - buffer32->line[(pcjr->displine << 1)][(x << 4) + (c << 1) + 1 + 8] = - buffer32->line[(pcjr->displine << 1) + 1][(x << 4) + (c << 1) + 8] = - buffer32->line[(pcjr->displine << 1) + 1][(x << 4) + (c << 1) + 1 + 8] = cols[0]; - } - } else { - for (c = 0; c < 8; c++) { - buffer32->line[(pcjr->displine << 1)][(x << 4) + (c << 1) + 8] = - buffer32->line[(pcjr->displine << 1)][(x << 4) + (c << 1) + 1 + 8] = - buffer32->line[(pcjr->displine << 1) + 1][(x << 4) + (c << 1) + 8] = - buffer32->line[(pcjr->displine << 1) + 1][(x << 4) + (c << 1) + 1 + 8] = - cols[(fontdat[chr][pcjr->sc & 7] & (1 << (c ^ 7))) ? 1 : 0]; - } - } - if (drawcursor) { - for (c = 0; c < 16; c++) { - buffer32->line[(pcjr->displine << 1)][(x << 4) + c + 8] ^= 15; - buffer32->line[(pcjr->displine << 1) + 1][(x << 4) + c + 8] ^= 15; - } - } - } - break; - case 0x02: /*320x200x4*/ - cols[0] = pcjr->array[0 + 16] + 16; - cols[1] = pcjr->array[1 + 16] + 16; - cols[2] = pcjr->array[2 + 16] + 16; - cols[3] = pcjr->array[3 + 16] + 16; - for (x = 0; x < pcjr->crtc[1]; x++) { - dat = (pcjr->vram[((pcjr->ma << 1) & mask) + offset] << 8) | - pcjr->vram[((pcjr->ma << 1) & mask) + offset + 1]; - pcjr->ma++; - for (c = 0; c < 8; c++) { - buffer32->line[(pcjr->displine << 1)][(x << 4) + (c << 1) + 8] = - buffer32->line[(pcjr->displine << 1)][(x << 4) + (c << 1) + 1 + 8] = - buffer32->line[(pcjr->displine << 1) + 1][(x << 4) + (c << 1) + 8] = - buffer32->line[(pcjr->displine << 1) + 1][(x << 4) + (c << 1) + 1 + 8] = cols[dat >> 14]; - dat <<= 2; - } - } - break; - case 0x102: /*640x200x2*/ - cols[0] = pcjr->array[0 + 16] + 16; - cols[1] = pcjr->array[1 + 16] + 16; - for (x = 0; x < pcjr->crtc[1]; x++) { - dat = (pcjr->vram[((pcjr->ma << 1) & mask) + offset] << 8) | - pcjr->vram[((pcjr->ma << 1) & mask) + offset + 1]; - pcjr->ma++; - for (c = 0; c < 16; c++) { - buffer32->line[(pcjr->displine << 1)][(x << 4) + c + 8] = - buffer32->line[(pcjr->displine << 1) + 1][(x << 4) + c + 8] = - cols[dat >> 15]; - dat <<= 1; - } - } - break; - } - } else { - if (pcjr->array[3] & 4) { - if (pcjr->array[0] & 1) { - hline(buffer32, 0, (pcjr->displine << 1), (pcjr->crtc[1] << 3) + 16, (pcjr->array[2] & 0xf) + 16); - hline(buffer32, 0, (pcjr->displine << 1) + 1, (pcjr->crtc[1] << 3) + 16, (pcjr->array[2] & 0xf) + 16); - } else { - hline(buffer32, 0, (pcjr->displine << 1), (pcjr->crtc[1] << 4) + 16, (pcjr->array[2] & 0xf) + 16); - hline(buffer32, 0, (pcjr->displine << 1) + 1, (pcjr->crtc[1] << 4) + 16, (pcjr->array[2] & 0xf) + 16); - } - } else { - cols[0] = pcjr->array[0 + 16] + 16; - if (pcjr->array[0] & 1) { - hline(buffer32, 0, (pcjr->displine << 1), (pcjr->crtc[1] << 3) + 16, cols[0]); - hline(buffer32, 0, (pcjr->displine << 1) + 1, (pcjr->crtc[1] << 3) + 16, cols[0]); - } else { - hline(buffer32, 0, (pcjr->displine << 1), (pcjr->crtc[1] << 4) + 16, cols[0]); - hline(buffer32, 0, (pcjr->displine << 1) + 1, (pcjr->crtc[1] << 4) + 16, cols[0]); - } - } - } - if (pcjr->array[0] & 1) x = (pcjr->crtc[1] << 3) + 16; - else x = (pcjr->crtc[1] << 4) + 16; - if (pcjr->composite) { - Composite_Process(pcjr->array[0], 0, x >> 2, buffer32->line[(pcjr->displine << 1)]); - Composite_Process(pcjr->array[0], 0, x >> 2, buffer32->line[(pcjr->displine << 1) + 1]); - } - pcjr->sc = oldsc; - if (pcjr->vc == pcjr->crtc[7] && !pcjr->sc) { - pcjr->stat |= 8; - } - pcjr->displine++; - if (pcjr->displine >= 360) - pcjr->displine = 0; + switch (pcjr->addr_mode) { + case 0: /*Alpha*/ + offset = 0; + mask = 0x3fff; + break; + case 1: /*Low resolution graphics*/ + offset = (pcjr->sc & 1) * 0x2000; + break; + case 3: /*High resolution graphics*/ + offset = (pcjr->sc & 3) * 0x2000; + break; + + default: + break; + } + switch ((pcjr->array[0] & 0x13) | ((pcjr->array[3] & 0x08) << 5)) { + case 0x13: /*320x200x16*/ + for (x = 0; x < pcjr->crtc[1]; x++) { + dat = (pcjr->vram[((pcjr->ma << 1) & mask) + offset] << 8) | pcjr->vram[((pcjr->ma << 1) & mask) + offset + 1]; + pcjr->ma++; + buffer32->line[pcjr->displine << 1][(x << 3) + 8] = buffer32->line[pcjr->displine << 1][(x << 3) + 9] = buffer32->line[(pcjr->displine << 1) + 1][(x << 3) + 8] = buffer32->line[(pcjr->displine << 1) + 1][(x << 3) + 9] = pcjr->array[((dat >> 12) & pcjr->array[1]) + 16] + 16; + buffer32->line[pcjr->displine << 1][(x << 3) + 10] = buffer32->line[pcjr->displine << 1][(x << 3) + 11] = buffer32->line[(pcjr->displine << 1) + 1][(x << 3) + 10] = buffer32->line[(pcjr->displine << 1) + 1][(x << 3) + 11] = pcjr->array[((dat >> 8) & pcjr->array[1]) + 16] + 16; + buffer32->line[pcjr->displine << 1][(x << 3) + 12] = buffer32->line[pcjr->displine << 1][(x << 3) + 13] = buffer32->line[(pcjr->displine << 1) + 1][(x << 3) + 12] = buffer32->line[(pcjr->displine << 1) + 1][(x << 3) + 13] = pcjr->array[((dat >> 4) & pcjr->array[1]) + 16] + 16; + buffer32->line[pcjr->displine << 1][(x << 3) + 14] = buffer32->line[pcjr->displine << 1][(x << 3) + 15] = buffer32->line[(pcjr->displine << 1) + 1][(x << 3) + 14] = buffer32->line[(pcjr->displine << 1) + 1][(x << 3) + 15] = pcjr->array[(dat & pcjr->array[1]) + 16] + 16; + } + break; + case 0x12: /*160x200x16*/ + for (x = 0; x < pcjr->crtc[1]; x++) { + dat = (pcjr->vram[((pcjr->ma << 1) & mask) + offset] << 8) | pcjr->vram[((pcjr->ma << 1) & mask) + offset + 1]; + pcjr->ma++; + buffer32->line[pcjr->displine << 1][(x << 4) + 8] = buffer32->line[pcjr->displine << 1][(x << 4) + 9] = buffer32->line[pcjr->displine << 1][(x << 4) + 10] = buffer32->line[pcjr->displine << 1][(x << 4) + 11] = buffer32->line[(pcjr->displine << 1) + 1][(x << 4) + 8] = buffer32->line[(pcjr->displine << 1) + 1][(x << 4) + 9] = buffer32->line[(pcjr->displine << 1) + 1][(x << 4) + 10] = buffer32->line[(pcjr->displine << 1) + 1][(x << 4) + 11] = pcjr->array[((dat >> 12) & pcjr->array[1]) + 16] + 16; + buffer32->line[pcjr->displine << 1][(x << 4) + 12] = buffer32->line[pcjr->displine << 1][(x << 4) + 13] = buffer32->line[pcjr->displine << 1][(x << 4) + 14] = buffer32->line[pcjr->displine << 1][(x << 4) + 15] = buffer32->line[(pcjr->displine << 1) + 1][(x << 4) + 12] = buffer32->line[(pcjr->displine << 1) + 1][(x << 4) + 13] = buffer32->line[(pcjr->displine << 1) + 1][(x << 4) + 14] = buffer32->line[(pcjr->displine << 1) + 1][(x << 4) + 15] = pcjr->array[((dat >> 8) & pcjr->array[1]) + 16] + 16; + buffer32->line[pcjr->displine << 1][(x << 4) + 16] = buffer32->line[pcjr->displine << 1][(x << 4) + 17] = buffer32->line[pcjr->displine << 1][(x << 4) + 18] = buffer32->line[pcjr->displine << 1][(x << 4) + 19] = buffer32->line[(pcjr->displine << 1) + 1][(x << 4) + 16] = buffer32->line[(pcjr->displine << 1) + 1][(x << 4) + 17] = buffer32->line[(pcjr->displine << 1) + 1][(x << 4) + 18] = buffer32->line[(pcjr->displine << 1) + 1][(x << 4) + 19] = pcjr->array[((dat >> 4) & pcjr->array[1]) + 16] + 16; + buffer32->line[pcjr->displine << 1][(x << 4) + 20] = buffer32->line[pcjr->displine << 1][(x << 4) + 21] = buffer32->line[pcjr->displine << 1][(x << 4) + 22] = buffer32->line[pcjr->displine << 1][(x << 4) + 23] = buffer32->line[(pcjr->displine << 1) + 1][(x << 4) + 20] = buffer32->line[(pcjr->displine << 1) + 1][(x << 4) + 21] = buffer32->line[(pcjr->displine << 1) + 1][(x << 4) + 22] = buffer32->line[(pcjr->displine << 1) + 1][(x << 4) + 23] = pcjr->array[(dat & pcjr->array[1]) + 16] + 16; + } + break; + case 0x03: /*640x200x4*/ + for (x = 0; x < pcjr->crtc[1]; x++) { + dat = (pcjr->vram[((pcjr->ma << 1) & mask) + offset] << 8) | pcjr->vram[((pcjr->ma << 1) & mask) + offset + 1]; + pcjr->ma++; + for (uint8_t c = 0; c < 8; c++) { + chr = (dat >> 7) & 1; + chr |= ((dat >> 14) & 2); + buffer32->line[pcjr->displine << 1][(x << 3) + 8 + c] = buffer32->line[(pcjr->displine << 1) + 1][(x << 3) + 8 + c] = pcjr->array[(chr & pcjr->array[1]) + 16] + 16; + dat <<= 1; + } + } + break; + case 0x01: /*80 column text*/ + for (x = 0; x < pcjr->crtc[1]; x++) { + chr = pcjr->vram[((pcjr->ma << 1) & mask) + offset]; + attr = pcjr->vram[((pcjr->ma << 1) & mask) + offset + 1]; + drawcursor = ((pcjr->ma == ca) && pcjr->con && pcjr->cursoron); + if (pcjr->array[3] & 4) { + cols[1] = pcjr->array[((attr & 15) & pcjr->array[1]) + 16] + 16; + cols[0] = pcjr->array[(((attr >> 4) & 7) & pcjr->array[1]) + 16] + 16; + if ((pcjr->blink & 16) && (attr & 0x80) && !drawcursor) + cols[1] = cols[0]; + } else { + cols[1] = pcjr->array[((attr & 15) & pcjr->array[1]) + 16] + 16; + cols[0] = pcjr->array[((attr >> 4) & pcjr->array[1]) + 16] + 16; + } + if (pcjr->sc & 8) { + for (uint8_t c = 0; c < 8; c++) { + buffer32->line[pcjr->displine << 1][(x << 3) + c + 8] = buffer32->line[(pcjr->displine << 1) + 1][(x << 3) + c + 8] = cols[0]; + } + } else { + for (uint8_t c = 0; c < 8; c++) { + buffer32->line[pcjr->displine << 1][(x << 3) + c + 8] = buffer32->line[(pcjr->displine << 1) + 1][(x << 3) + c + 8] = cols[(fontdat[chr][pcjr->sc & 7] & (1 << (c ^ 7))) ? 1 : 0]; + } + } + if (drawcursor) { + for (uint8_t c = 0; c < 8; c++) { + buffer32->line[pcjr->displine << 1][(x << 3) + c + 8] ^= 15; + buffer32->line[(pcjr->displine << 1) + 1][(x << 3) + c + 8] ^= 15; + } + } + pcjr->ma++; + } + break; + case 0x00: /*40 column text*/ + for (x = 0; x < pcjr->crtc[1]; x++) { + chr = pcjr->vram[((pcjr->ma << 1) & mask) + offset]; + attr = pcjr->vram[((pcjr->ma << 1) & mask) + offset + 1]; + drawcursor = ((pcjr->ma == ca) && pcjr->con && pcjr->cursoron); + if (pcjr->array[3] & 4) { + cols[1] = pcjr->array[((attr & 15) & pcjr->array[1]) + 16] + 16; + cols[0] = pcjr->array[(((attr >> 4) & 7) & pcjr->array[1]) + 16] + 16; + if ((pcjr->blink & 16) && (attr & 0x80) && !drawcursor) + cols[1] = cols[0]; + } else { + cols[1] = pcjr->array[((attr & 15) & pcjr->array[1]) + 16] + 16; + cols[0] = pcjr->array[((attr >> 4) & pcjr->array[1]) + 16] + 16; + } + pcjr->ma++; + if (pcjr->sc & 8) { + for (uint8_t c = 0; c < 8; c++) { + buffer32->line[pcjr->displine << 1][(x << 4) + (c << 1) + 8] = buffer32->line[pcjr->displine << 1][(x << 4) + (c << 1) + 1 + 8] = buffer32->line[(pcjr->displine << 1) + 1][(x << 4) + (c << 1) + 8] = buffer32->line[(pcjr->displine << 1) + 1][(x << 4) + (c << 1) + 1 + 8] = cols[0]; + } + } else { + for (uint8_t c = 0; c < 8; c++) { + buffer32->line[pcjr->displine << 1][(x << 4) + (c << 1) + 8] = buffer32->line[pcjr->displine << 1][(x << 4) + (c << 1) + 1 + 8] = buffer32->line[(pcjr->displine << 1) + 1][(x << 4) + (c << 1) + 8] = buffer32->line[(pcjr->displine << 1) + 1][(x << 4) + (c << 1) + 1 + 8] = cols[(fontdat[chr][pcjr->sc & 7] & (1 << (c ^ 7))) ? 1 : 0]; + } + } + if (drawcursor) { + for (uint8_t c = 0; c < 16; c++) { + buffer32->line[pcjr->displine << 1][(x << 4) + c + 8] ^= 15; + buffer32->line[(pcjr->displine << 1) + 1][(x << 4) + c + 8] ^= 15; + } + } + } + break; + case 0x02: /*320x200x4*/ + cols[0] = pcjr->array[0 + 16] + 16; + cols[1] = pcjr->array[1 + 16] + 16; + cols[2] = pcjr->array[2 + 16] + 16; + cols[3] = pcjr->array[3 + 16] + 16; + for (x = 0; x < pcjr->crtc[1]; x++) { + dat = (pcjr->vram[((pcjr->ma << 1) & mask) + offset] << 8) | pcjr->vram[((pcjr->ma << 1) & mask) + offset + 1]; + pcjr->ma++; + for (uint8_t c = 0; c < 8; c++) { + buffer32->line[pcjr->displine << 1][(x << 4) + (c << 1) + 8] = buffer32->line[pcjr->displine << 1][(x << 4) + (c << 1) + 1 + 8] = buffer32->line[(pcjr->displine << 1) + 1][(x << 4) + (c << 1) + 8] = buffer32->line[(pcjr->displine << 1) + 1][(x << 4) + (c << 1) + 1 + 8] = cols[dat >> 14]; + dat <<= 2; + } + } + break; + case 0x102: /*640x200x2*/ + cols[0] = pcjr->array[0 + 16] + 16; + cols[1] = pcjr->array[1 + 16] + 16; + for (x = 0; x < pcjr->crtc[1]; x++) { + dat = (pcjr->vram[((pcjr->ma << 1) & mask) + offset] << 8) | pcjr->vram[((pcjr->ma << 1) & mask) + offset + 1]; + pcjr->ma++; + for (uint8_t c = 0; c < 16; c++) { + buffer32->line[pcjr->displine << 1][(x << 4) + c + 8] = buffer32->line[(pcjr->displine << 1) + 1][(x << 4) + c + 8] = cols[dat >> 15]; + dat <<= 1; + } + } + break; + + default: + break; + } + } else { + if (pcjr->array[3] & 4) { + if (pcjr->array[0] & 1) { + hline(buffer32, 0, (pcjr->displine << 1), (pcjr->crtc[1] << 3) + 16, (pcjr->array[2] & 0xf) + 16); + hline(buffer32, 0, (pcjr->displine << 1) + 1, (pcjr->crtc[1] << 3) + 16, (pcjr->array[2] & 0xf) + 16); + } else { + hline(buffer32, 0, (pcjr->displine << 1), (pcjr->crtc[1] << 4) + 16, (pcjr->array[2] & 0xf) + 16); + hline(buffer32, 0, (pcjr->displine << 1) + 1, (pcjr->crtc[1] << 4) + 16, (pcjr->array[2] & 0xf) + 16); + } + } else { + cols[0] = pcjr->array[0 + 16] + 16; + if (pcjr->array[0] & 1) { + hline(buffer32, 0, (pcjr->displine << 1), (pcjr->crtc[1] << 3) + 16, cols[0]); + hline(buffer32, 0, (pcjr->displine << 1) + 1, (pcjr->crtc[1] << 3) + 16, cols[0]); + } else { + hline(buffer32, 0, (pcjr->displine << 1), (pcjr->crtc[1] << 4) + 16, cols[0]); + hline(buffer32, 0, (pcjr->displine << 1) + 1, (pcjr->crtc[1] << 4) + 16, cols[0]); + } + } + } + if (pcjr->array[0] & 1) + x = (pcjr->crtc[1] << 3) + 16; + else + x = (pcjr->crtc[1] << 4) + 16; + if (pcjr->composite) { + Composite_Process(pcjr->array[0], 0, x >> 2, buffer32->line[pcjr->displine << 1]); + Composite_Process(pcjr->array[0], 0, x >> 2, buffer32->line[(pcjr->displine << 1) + 1]); + } else { + video_process_8(x, pcjr->displine << 1); + video_process_8(x, (pcjr->displine << 1) + 1); + } + pcjr->sc = oldsc; + if (pcjr->vc == pcjr->crtc[7] && !pcjr->sc) { + pcjr->stat |= 8; + } + pcjr->displine++; + if (pcjr->displine >= 360) + pcjr->displine = 0; } else { - timer_advance_u64(&pcjr->timer, pcjr->dispontime); - if (pcjr->dispon) - pcjr->stat |= 1; - pcjr->linepos = 0; - if (pcjr->vsynctime) { - pcjr->vsynctime--; - if (!pcjr->vsynctime) { - pcjr->stat &= ~8; - } - } - if (pcjr->sc == (pcjr->crtc[11] & 31) || ((pcjr->crtc[8] & 3) == 3 && pcjr->sc == ((pcjr->crtc[11] & 31) >> 1))) { - pcjr->con = 0; - pcjr->coff = 1; - } - if (pcjr->vadj) { - pcjr->sc++; - pcjr->sc &= 31; - pcjr->ma = pcjr->maback; - pcjr->vadj--; - if (!pcjr->vadj) { - pcjr->dispon = 1; - pcjr->ma = pcjr->maback = (pcjr->crtc[13] | (pcjr->crtc[12] << 8)) & 0x3fff; - pcjr->sc = 0; - } - } else if (pcjr->sc == pcjr->crtc[9] || ((pcjr->crtc[8] & 3) == 3 && pcjr->sc == (pcjr->crtc[9] >> 1))) { - pcjr->maback = pcjr->ma; - pcjr->sc = 0; - oldvc = pcjr->vc; - pcjr->vc++; - pcjr->vc &= 127; - if (pcjr->vc == pcjr->crtc[6]) - pcjr->dispon = 0; - if (oldvc == pcjr->crtc[4]) { - pcjr->vc = 0; - pcjr->vadj = pcjr->crtc[5]; - if (!pcjr->vadj) - pcjr->dispon = 1; - if (!pcjr->vadj) - pcjr->ma = pcjr->maback = (pcjr->crtc[13] | (pcjr->crtc[12] << 8)) & 0x3fff; - if ((pcjr->crtc[10] & 0x60) == 0x20) pcjr->cursoron = 0; - else pcjr->cursoron = pcjr->blink & 16; - } - if (pcjr->vc == pcjr->crtc[7]) { - pcjr->dispon = 0; - pcjr->displine = 0; - pcjr->vsynctime = 16; - picint(1 << 5); - if (pcjr->crtc[7]) { - if (pcjr->array[0] & 1) x = (pcjr->crtc[1] << 3) + 16; - else x = (pcjr->crtc[1] << 4) + 16; - pcjr->lastline++; + timer_advance_u64(&pcjr->timer, pcjr->dispontime); + if (pcjr->dispon) + pcjr->stat |= 1; + pcjr->linepos = 0; + if (pcjr->vsynctime) { + pcjr->vsynctime--; + if (!pcjr->vsynctime) { + pcjr->stat &= ~8; + } + } + if (pcjr->sc == (pcjr->crtc[11] & 31) || ((pcjr->crtc[8] & 3) == 3 && pcjr->sc == ((pcjr->crtc[11] & 31) >> 1))) { + pcjr->con = 0; + pcjr->coff = 1; + } + if (pcjr->vadj) { + pcjr->sc++; + pcjr->sc &= 31; + pcjr->ma = pcjr->maback; + pcjr->vadj--; + if (!pcjr->vadj) { + pcjr->dispon = 1; + pcjr->ma = pcjr->maback = (pcjr->crtc[13] | (pcjr->crtc[12] << 8)) & 0x3fff; + pcjr->sc = 0; + } + } else if (pcjr->sc == pcjr->crtc[9] || ((pcjr->crtc[8] & 3) == 3 && pcjr->sc == (pcjr->crtc[9] >> 1))) { + pcjr->maback = pcjr->ma; + pcjr->sc = 0; + oldvc = pcjr->vc; + pcjr->vc++; + pcjr->vc &= 127; + if (pcjr->vc == pcjr->crtc[6]) + pcjr->dispon = 0; + if (oldvc == pcjr->crtc[4]) { + pcjr->vc = 0; + pcjr->vadj = pcjr->crtc[5]; + if (!pcjr->vadj) + pcjr->dispon = 1; + if (!pcjr->vadj) + pcjr->ma = pcjr->maback = (pcjr->crtc[13] | (pcjr->crtc[12] << 8)) & 0x3fff; + if ((pcjr->crtc[10] & 0x60) == 0x20) + pcjr->cursoron = 0; + else + pcjr->cursoron = pcjr->blink & 16; + } + if (pcjr->vc == pcjr->crtc[7]) { + pcjr->dispon = 0; + pcjr->displine = 0; + pcjr->vsynctime = 16; + picint(1 << 5); + if (pcjr->crtc[7]) { + if (pcjr->array[0] & 1) + x = (pcjr->crtc[1] << 3) + 16; + else + x = (pcjr->crtc[1] << 4) + 16; + pcjr->lastline++; - xs_temp = x; - ys_temp = (pcjr->lastline - pcjr->firstline) << 1; + xs_temp = x; + ys_temp = (pcjr->lastline - pcjr->firstline) << 1; - if ((xs_temp > 0) && (ys_temp > 0)) { - if (xs_temp < 64) xs_temp = 656; - if (ys_temp < 32) ys_temp = 400; - if (!enable_overscan) - xs_temp -= 16; + if ((xs_temp > 0) && (ys_temp > 0)) { + if (xs_temp < 64) + xs_temp = 656; + if (ys_temp < 32) + ys_temp = 400; + if (!enable_overscan) + xs_temp -= 16; - if ((xs_temp != xsize) || (ys_temp != ysize) || video_force_resize_get()) { - xsize = xs_temp; - ysize = ys_temp; - set_screen_size(xsize, ysize + (enable_overscan ? 16 : 0)); + if ((xs_temp != xsize) || (ys_temp != ysize) || video_force_resize_get()) { + xsize = xs_temp; + ysize = ys_temp; + set_screen_size(xsize, ysize + (enable_overscan ? 16 : 0)); - if (video_force_resize_get()) - video_force_resize_set(0); - } + if (video_force_resize_get()) + video_force_resize_set(0); + } - if (enable_overscan) { - if (pcjr->composite) - video_blit_memtoscreen(0, (pcjr->firstline - 4) << 1, - xsize, ((pcjr->lastline - pcjr->firstline) + 8) << 1); - else - video_blit_memtoscreen_8(0, (pcjr->firstline - 4) << 1, - xsize, ((pcjr->lastline - pcjr->firstline) + 8) << 1); - } else { - if (pcjr->composite) - video_blit_memtoscreen(8, pcjr->firstline << 1, - xsize, (pcjr->lastline - pcjr->firstline) << 1); - else - video_blit_memtoscreen_8(8, pcjr->firstline << 1, - xsize, (pcjr->lastline - pcjr->firstline) << 1); - } - } + if (enable_overscan) { + video_blit_memtoscreen(0, (pcjr->firstline - 4) << 1, + xsize, ((pcjr->lastline - pcjr->firstline) + 8) << 1); + } else { + video_blit_memtoscreen(8, pcjr->firstline << 1, + xsize, (pcjr->lastline - pcjr->firstline) << 1); + } + } - frames++; - video_res_x = xsize; - video_res_y = ysize; - } - pcjr->firstline = 1000; - pcjr->lastline = 0; - pcjr->blink++; - } - } else { - pcjr->sc++; - pcjr->sc &= 31; - pcjr->ma = pcjr->maback; - } - if ((pcjr->sc == (pcjr->crtc[10] & 31) || ((pcjr->crtc[8] & 3) == 3 && pcjr->sc == ((pcjr->crtc[10] & 31) >> 1)))) - pcjr->con = 1; + frames++; + video_res_x = xsize; + video_res_y = ysize; + } + pcjr->firstline = 1000; + pcjr->lastline = 0; + pcjr->blink++; + } + } else { + pcjr->sc++; + pcjr->sc &= 31; + pcjr->ma = pcjr->maback; + } + if (pcjr->sc == (pcjr->crtc[10] & 31) || ((pcjr->crtc[8] & 3) == 3 && pcjr->sc == ((pcjr->crtc[10] & 31) >> 1))) + pcjr->con = 1; } } - static void kbd_write(uint16_t port, uint8_t val, void *priv) { - pcjr_t *pcjr = (pcjr_t *)priv; + pcjr_t *pcjr = (pcjr_t *) priv; if ((port >= 0xa0) && (port <= 0xa7)) - port = 0xa0; + port = 0xa0; switch (port) { - case 0x60: - pcjr->pa = val; - break; + case 0x60: + pcjr->pa = val; + break; - case 0x61: - pcjr->pb = val; + case 0x61: + pcjr->pb = val; - timer_process(); + if (cassette != NULL) + pc_cas_set_motor(cassette, (pcjr->pb & 0x08) == 0); - if (cassette != NULL) - pc_cas_set_motor(cassette, (pcjr->pb & 0x08) == 0); + speaker_update(); + speaker_gated = val & 1; + speaker_enable = val & 2; + if (speaker_enable) + was_speaker_enable = 1; + pit_devs[0].set_gate(pit_devs[0].data, 2, val & 1); + sn76489_mute = speaker_mute = 1; + switch (val & 0x60) { + case 0x00: + speaker_mute = 0; + break; - speaker_update(); - speaker_gated = val & 1; - speaker_enable = val & 2; - if (speaker_enable) - was_speaker_enable = 1; - pit_ctr_set_gate(&pit->counters[2], val & 1); - sn76489_mute = speaker_mute = 1; - switch (val & 0x60) { - case 0x00: - speaker_mute = 0; - break; + case 0x60: + sn76489_mute = 0; + break; - case 0x60: - sn76489_mute = 0; - break; - } - break; + default: + break; + } + break; - case 0xa0: - nmi_mask = val & 0x80; - pit_ctr_set_using_timer(&pit->counters[1], !(val & 0x20)); - break; + case 0xa0: + nmi_mask = val & 0x80; + pit_devs[0].set_using_timer(pit_devs[0].data, 1, !(val & 0x20)); + break; + + default: + break; } } - static uint8_t kbd_read(uint16_t port, void *priv) { - pcjr_t *pcjr = (pcjr_t *)priv; - uint8_t ret = 0xff; + pcjr_t *pcjr = (pcjr_t *) priv; + uint8_t ret = 0xff; if ((port >= 0xa0) && (port <= 0xa7)) - port = 0xa0; + port = 0xa0; switch (port) { - case 0x60: - ret = pcjr->pa; - break; - - case 0x61: - ret = pcjr->pb; - break; + case 0x60: + ret = pcjr->pa; + break; - case 0x62: - ret = (pcjr->latched ? 1 : 0); - ret |= 0x02; /*Modem card not installed*/ - if ((pcjr->pb & 0x08) || (cassette == NULL)) - ret |= (ppispeakon ? 0x10 : 0); - else - ret |= (pc_cas_get_inp(cassette) ? 0x10 : 0); - ret |= (ppispeakon ? 0x10 : 0); - ret |= (ppispeakon ? 0x20 : 0); - ret |= (pcjr->data ? 0x40: 0); - if (pcjr->data) - ret |= 0x40; - break; - - case 0xa0: - pcjr->latched = 0; - ret = 0; - break; + case 0x61: + ret = pcjr->pb; + break; + + case 0x62: + ret = (pcjr->latched ? 1 : 0); + ret |= 0x02; /* Modem card not installed */ + if (mem_size < 128) + ret |= 0x08; /* 64k expansion card not installed */ + if ((pcjr->pb & 0x08) || (cassette == NULL)) + ret |= (ppispeakon ? 0x10 : 0); + else + ret |= (pc_cas_get_inp(cassette) ? 0x10 : 0); + ret |= (ppispeakon ? 0x10 : 0); + ret |= (ppispeakon ? 0x20 : 0); + ret |= (pcjr->data ? 0x40 : 0); + if (pcjr->data) + ret |= 0x40; + break; + + case 0xa0: + pcjr->latched = 0; + ret = 0; + break; + + default: + break; } - return(ret); + return ret; } - static void kbd_poll(void *priv) { - pcjr_t *pcjr = (pcjr_t *)priv; - int c, p = 0, key; + pcjr_t *pcjr = (pcjr_t *) priv; + int c; + int p = 0; + int key; timer_advance_u64(&pcjr->send_delay_timer, 220 * TIMER_USEC); - if (key_queue_start != key_queue_end && - !pcjr->serial_pos && !pcjr->latched) { - key = key_queue[key_queue_start]; + if (key_queue_start != key_queue_end && !pcjr->serial_pos && !pcjr->latched) { + key = key_queue[key_queue_start]; - key_queue_start = (key_queue_start + 1) & 0xf; + key_queue_start = (key_queue_start + 1) & 0xf; - pcjr->latched = 1; - pcjr->serial_data[0] = 1; /*Start bit*/ - pcjr->serial_data[1] = 0; + pcjr->latched = 1; + pcjr->serial_data[0] = 1; /*Start bit*/ + pcjr->serial_data[1] = 0; - for (c = 0; c < 8; c++) { - if (key & (1 << c)) { - pcjr->serial_data[(c + 1) * 2] = 1; - pcjr->serial_data[(c + 1) * 2 + 1] = 0; - p++; - } else { - pcjr->serial_data[(c + 1) * 2] = 0; - pcjr->serial_data[(c + 1) * 2 + 1] = 1; - } - } + for (c = 0; c < 8; c++) { + if (key & (1 << c)) { + pcjr->serial_data[(c + 1) * 2] = 1; + pcjr->serial_data[(c + 1) * 2 + 1] = 0; + p++; + } else { + pcjr->serial_data[(c + 1) * 2] = 0; + pcjr->serial_data[(c + 1) * 2 + 1] = 1; + } + } - if (p & 1) { /*Parity*/ - pcjr->serial_data[9 * 2] = 1; - pcjr->serial_data[9 * 2 + 1] = 0; - } else { - pcjr->serial_data[9 * 2] = 0; - pcjr->serial_data[9 * 2 + 1] = 1; - } + if (p & 1) { /*Parity*/ + pcjr->serial_data[9 * 2] = 1; + pcjr->serial_data[9 * 2 + 1] = 0; + } else { + pcjr->serial_data[9 * 2] = 0; + pcjr->serial_data[9 * 2 + 1] = 1; + } - for (c = 0; c < 11; c++) { /*11 stop bits*/ - pcjr->serial_data[(c + 10) * 2] = 0; - pcjr->serial_data[(c + 10) * 2 + 1] = 0; - } + for (c = 0; c < 11; c++) { /*11 stop bits*/ + pcjr->serial_data[(c + 10) * 2] = 0; + pcjr->serial_data[(c + 10) * 2 + 1] = 0; + } - pcjr->serial_pos++; + pcjr->serial_pos++; } if (pcjr->serial_pos) { - pcjr->data = pcjr->serial_data[pcjr->serial_pos - 1]; - nmi = pcjr->data; - pcjr->serial_pos++; - if (pcjr->serial_pos == 42+1) - pcjr->serial_pos = 0; + pcjr->data = pcjr->serial_data[pcjr->serial_pos - 1]; + nmi = pcjr->data; + pcjr->serial_pos++; + if (pcjr->serial_pos == 42 + 1) + pcjr->serial_pos = 0; } } - static void kbd_adddata(uint16_t val) { key_queue[key_queue_end] = val; - key_queue_end = (key_queue_end + 1) & 0xf; + key_queue_end = (key_queue_end + 1) & 0xf; } - - - static void kbd_adddata_ex(uint16_t val) { - kbd_adddata_process(val, kbd_adddata); + kbd_adddata_process(val, kbd_adddata); } - static void speed_changed(void *priv) { - pcjr_t *pcjr = (pcjr_t *)priv; + pcjr_t *pcjr = (pcjr_t *) priv; recalc_timings(pcjr); } - -static const device_config_t pcjr_config[] = { - { - "display_type", "Display type", CONFIG_SELECTION, "", PCJR_RGB, "", { 0 }, - { - { - "RGB", PCJR_RGB - }, - { - "Composite", PCJR_COMPOSITE - }, - { - "" - } - } - }, - { - "", "", -1 - } -}; - - -static const device_t pcjr_device = { - "IBM PCjr", - "pcjr", - 0, 0, - NULL, NULL, NULL, - { NULL }, - speed_changed, - NULL, - pcjr_config -}; - - -const device_t * -pcjr_get_device(void) +void +pit_irq0_timer_pcjr(int new_out, int old_out) { - return &pcjr_device; + if (new_out && !old_out) { + picint(1); + pit_devs[0].ctr_clock(pit_devs[0].data, 1); + } + + if (!new_out) + picintc(1); } +static const device_config_t pcjr_config[] = { + // clang-format off + { + .name = "display_type", + .description = "Display type", + .type = CONFIG_SELECTION, + .default_string = "", + .default_int = PCJR_RGB, + .file_filter = "", + .spinner = { 0 }, + .selection = { + { .description = "RGB", .value = PCJR_RGB }, + { .description = "Composite", .value = PCJR_COMPOSITE }, + { .description = "" } + } + }, + { .name = "", .description = "", .type = CONFIG_END } + // clang-format on +}; + +const device_t pcjr_device = { + .name = "IBM PCjr", + .internal_name = "pcjr", + .flags = 0, + .local = 0, + .init = NULL, + .close = NULL, + .reset = NULL, + { .available = NULL }, + .speed_changed = speed_changed, + .force_redraw = NULL, + .config = pcjr_config +}; int -machine_pcjr_init(const machine_t *model) +machine_pcjr_init(UNUSED(const machine_t *model)) { - int display_type; + int display_type; pcjr_t *pcjr; int ret; ret = bios_load_linear("roms/machines/ibmpcjr/bios.rom", - 0x000f0000, 65536, 0); + 0x000f0000, 65536, 0); if (bios_only || !ret) - return ret; + return ret; pcjr = malloc(sizeof(pcjr_t)); memset(pcjr, 0x00, sizeof(pcjr_t)); - pcjr->memctrl = -1; - display_type = machine_get_config_int("display_type"); + pcjr->memctrl = -1; + if (mem_size < 128) + pcjr->memctrl &= ~0x24; + display_type = machine_get_config_int("display_type"); pcjr->composite = (display_type != PCJR_RGB); pic_init_pcjr(); @@ -836,13 +845,13 @@ machine_pcjr_init(const machine_t *model) cpu_set(); /* Initialize the video controller. */ - video_reset(gfxcard); + video_reset(gfxcard[0]); loadfont("roms/video/mda/mda.rom", 0); mem_mapping_add(&pcjr->mapping, 0xb8000, 0x08000, - vid_read, NULL, NULL, - vid_write, NULL, NULL, NULL, 0, pcjr); + vid_read, NULL, NULL, + vid_write, NULL, NULL, NULL, 0, pcjr); io_sethandler(0x03d0, 16, - vid_in, NULL, NULL, vid_out, NULL, NULL, pcjr); + vid_in, NULL, NULL, vid_out, NULL, NULL, pcjr); timer_add(&pcjr->timer, vid_poll, pcjr, 1); video_inform(VIDEO_FLAG_TYPE_CGA, &timing_dram); device_add_ex(&pcjr_device, pcjr); @@ -850,12 +859,12 @@ machine_pcjr_init(const machine_t *model) cgapal_rebuild(); /* Initialize the keyboard. */ - keyboard_scan = 1; + keyboard_scan = 1; key_queue_start = key_queue_end = 0; io_sethandler(0x0060, 4, - kbd_read, NULL, NULL, kbd_write, NULL, NULL, pcjr); + kbd_read, NULL, NULL, kbd_write, NULL, NULL, pcjr); io_sethandler(0x00a0, 8, - kbd_read, NULL, NULL, kbd_write, NULL, NULL, pcjr); + kbd_read, NULL, NULL, kbd_write, NULL, NULL, pcjr); timer_add(&pcjr->send_delay_timer, kbd_poll, pcjr, 1); keyboard_set_table(scancode_xt); keyboard_send = kbd_adddata_ex; @@ -868,7 +877,13 @@ machine_pcjr_init(const machine_t *model) device_add(&fdc_pcjr_device); device_add(&ns8250_pcjr_device); - serial_set_next_inst(SERIAL_MAX); /* So that serial_standalone_init() won't do anything. */ + serial_set_next_inst(SERIAL_MAX); /* So that serial_standalone_init() won't do anything. */ + + /* "All the inputs are 'read' with one 'IN' from address hex 201." - PCjr Technical Reference (Nov. 83), p.2-119 + + Note by Miran Grca: Meanwhile, the same Technical Reference clearly says that + the gameport is on ports 201-207. */ + standalone_gameport_type = &gameport_201_device; return ret; } diff --git a/src/machine/m_ps1.c b/src/machine/m_ps1.c index 47b8121e0..d2c9f80ba 100644 --- a/src/machine/m_ps1.c +++ b/src/machine/m_ps1.c @@ -1,36 +1,36 @@ /* - * 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. + * 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. + * This file is part of the 86Box distribution. * - * Emulation of the IBM PS/1 models 2011, 2121. + * Emulation of the IBM PS/1 models 2011, 2121. * - * Model 2011: The initial model, using a 10MHz 80286. + * Model 2011: The initial model, using a 10MHz 80286. * - * Model 2121: This is similar to model 2011 but some of the functionality - * has moved to a chip at ports 0xe0 (index)/0xe1 (data). The - * only functions I have identified are enables for the first - * 512K and next 128K of RAM, in bits 0 of registers 0 and 1 - * respectively. + * Model 2121: This is similar to model 2011 but some of the functionality + * has moved to a chip at ports 0xe0 (index)/0xe1 (data). The + * only functions I have identified are enables for the first + * 512K and next 128K of RAM, in bits 0 of registers 0 and 1 + * respectively. * - * Port 0x105 has bit 7 forced high. Without this 128K of - * memory will be missed by the BIOS on cold boots. + * Port 0x105 has bit 7 forced high. Without this 128K of + * memory will be missed by the BIOS on cold boots. * - * The reserved 384K is remapped to the top of extended memory. - * If this is not done then you get an error on startup. + * The reserved 384K is remapped to the top of extended memory. + * If this is not done then you get an error on startup. * * * - * Authors: Sarah Walker, - * Miran Grca, - * Fred N. van Kempen, + * Authors: Sarah Walker, + * Miran Grca, + * Fred N. van Kempen, * - * Copyright 2008-2019 Sarah Walker. - * Copyright 2016-2019 Miran Grca. - * Copyright 2017-2019 Fred N. van Kempen. + * Copyright 2008-2019 Sarah Walker. + * Copyright 2016-2019 Miran Grca. + * Copyright 2017-2019 Fred N. van Kempen. */ #include #include @@ -64,255 +64,256 @@ #include <86box/machine.h> #include <86box/sound.h> - typedef struct { - int model; + int model; - rom_t high_rom; + rom_t mid_rom, high_rom; - uint8_t ps1_91, - ps1_92, - ps1_94, - ps1_102, - ps1_103, - ps1_104, - ps1_105, - ps1_190; - int ps1_e0_addr; - uint8_t ps1_e0_regs[256]; + uint8_t ps1_91, + ps1_92, + ps1_94, + ps1_102, + ps1_103, + ps1_104, + ps1_105, + ps1_190; + int ps1_e0_addr; + uint8_t ps1_e0_regs[256]; - serial_t *uart; + serial_t *uart; } ps1_t; - static void recalc_memory(ps1_t *ps) { /* Enable first 512K */ mem_set_mem_state(0x00000, 0x80000, - (ps->ps1_e0_regs[0] & 0x01) ? - (MEM_READ_INTERNAL | MEM_WRITE_INTERNAL) : - (MEM_READ_EXTANY | MEM_WRITE_EXTANY)); + (ps->ps1_e0_regs[0] & 0x01) ? (MEM_READ_INTERNAL | MEM_WRITE_INTERNAL) : (MEM_READ_EXTANY | MEM_WRITE_EXTANY)); /* Enable 512-640K */ mem_set_mem_state(0x80000, 0x20000, - (ps->ps1_e0_regs[1] & 0x01) ? - (MEM_READ_INTERNAL | MEM_WRITE_INTERNAL) : - (MEM_READ_EXTANY | MEM_WRITE_EXTANY)); + (ps->ps1_e0_regs[1] & 0x01) ? (MEM_READ_INTERNAL | MEM_WRITE_INTERNAL) : (MEM_READ_EXTANY | MEM_WRITE_EXTANY)); } - static void ps1_write(uint16_t port, uint8_t val, void *priv) { - ps1_t *ps = (ps1_t *)priv; + ps1_t *ps = (ps1_t *) priv; switch (port) { - case 0x0092: - if (ps->model != 2011) { - if (val & 1) { - softresetx86(); - cpu_set_edx(); - } - ps->ps1_92 = val & ~1; - } else { - ps->ps1_92 = val; - } - mem_a20_alt = val & 2; - mem_a20_recalc(); - break; + case 0x0092: + if (ps->model != 2011) { + if (val & 1) { + softresetx86(); + cpu_set_edx(); + } + ps->ps1_92 = val & ~1; + } else { + ps->ps1_92 = val; + } + mem_a20_alt = val & 2; + mem_a20_recalc(); + break; - case 0x0094: - ps->ps1_94 = val; - break; + case 0x0094: + ps->ps1_94 = val; + break; - case 0x00e0: - if (ps->model != 2011) { - ps->ps1_e0_addr = val; - } - break; + case 0x00e0: + if (ps->model != 2011) { + ps->ps1_e0_addr = val; + } + break; - case 0x00e1: - if (ps->model != 2011) { - ps->ps1_e0_regs[ps->ps1_e0_addr] = val; - recalc_memory(ps); - } - break; + case 0x00e1: + if (ps->model != 2011) { + ps->ps1_e0_regs[ps->ps1_e0_addr] = val; + recalc_memory(ps); + } + break; - case 0x0102: - if (!(ps->ps1_94 & 0x80)) { - lpt1_remove(); - serial_remove(ps->uart); - if (val & 0x04) { - if (val & 0x08) - serial_setup(ps->uart, SERIAL1_ADDR, SERIAL1_IRQ); - else - serial_setup(ps->uart, SERIAL2_ADDR, SERIAL2_IRQ); - } - if (val & 0x10) { - switch ((val >> 5) & 3) - { - case 0: - lpt1_init(0x3bc); - break; - case 1: - lpt1_init(0x378); - break; - case 2: - lpt1_init(0x278); - break; - } - } - ps->ps1_102 = val; - } - break; + case 0x0102: + if (!(ps->ps1_94 & 0x80)) { + lpt1_remove(); + serial_remove(ps->uart); + if (val & 0x04) { + if (val & 0x08) + serial_setup(ps->uart, COM1_ADDR, COM1_IRQ); + else + serial_setup(ps->uart, COM2_ADDR, COM2_IRQ); + } + if (val & 0x10) { + switch ((val >> 5) & 3) { + case 0: + lpt1_init(LPT_MDA_ADDR); + break; + case 1: + lpt1_init(LPT1_ADDR); + break; + case 2: + lpt1_init(LPT2_ADDR); + break; - case 0x0103: - ps->ps1_103 = val; - break; + default: + break; + } + } + ps->ps1_102 = val; + } + break; - case 0x0104: - ps->ps1_104 = val; - break; + case 0x0103: + ps->ps1_103 = val; + break; - case 0x0105: - ps->ps1_105 = val; - break; + case 0x0104: + ps->ps1_104 = val; + break; - case 0x0190: - ps->ps1_190 = val; - break; + case 0x0105: + ps->ps1_105 = val; + break; + + case 0x0190: + ps->ps1_190 = val; + break; + + default: + break; } } - static uint8_t ps1_read(uint16_t port, void *priv) { - ps1_t *ps = (ps1_t *)priv; + ps1_t *ps = (ps1_t *) priv; uint8_t ret = 0xff; switch (port) { - case 0x0091: - ret = ps->ps1_91; - ps->ps1_91 = 0; - break; + case 0x0091: + ret = ps->ps1_91; + ps->ps1_91 = 0; + break; - case 0x0092: - ret = ps->ps1_92; - break; + case 0x0092: + ret = ps->ps1_92; + break; - case 0x0094: - ret = ps->ps1_94; - break; + case 0x0094: + ret = ps->ps1_94; + break; - case 0x00e1: - if (ps->model != 2011) { - ret = ps->ps1_e0_regs[ps->ps1_e0_addr]; - } - break; + case 0x00e1: + if (ps->model != 2011) { + ret = ps->ps1_e0_regs[ps->ps1_e0_addr]; + } + break; - case 0x0102: - if (ps->model == 2011) - ret = ps->ps1_102 | 0x08; - else - ret = ps->ps1_102; - break; + case 0x0102: + if (ps->model == 2011) + ret = ps->ps1_102 | 0x08; + else + ret = ps->ps1_102; + break; - case 0x0103: - ret = ps->ps1_103; - break; + case 0x0103: + ret = ps->ps1_103; + break; - case 0x0104: - ret = ps->ps1_104; - break; + case 0x0104: + ret = ps->ps1_104; + break; - case 0x0105: - if (ps->model == 2011) - ret = ps->ps1_105; - else - ret = ps->ps1_105 | 0x80; - break; + case 0x0105: + if (ps->model == 2011) + ret = ps->ps1_105; + else + ret = ps->ps1_105 | 0x80; + break; - case 0x0190: - ret = ps->ps1_190; - break; + case 0x0190: + ret = ps->ps1_190; + break; - default: - break; + default: + break; } - return(ret); + return ret; } - static void ps1_setup(int model) { ps1_t *ps; - void *priv; + void *priv; - ps = (ps1_t *)malloc(sizeof(ps1_t)); + ps = (ps1_t *) malloc(sizeof(ps1_t)); memset(ps, 0x00, sizeof(ps1_t)); ps->model = model; io_sethandler(0x0091, 1, - ps1_read, NULL, NULL, ps1_write, NULL, NULL, ps); + ps1_read, NULL, NULL, ps1_write, NULL, NULL, ps); io_sethandler(0x0092, 1, - ps1_read, NULL, NULL, ps1_write, NULL, NULL, ps); + ps1_read, NULL, NULL, ps1_write, NULL, NULL, ps); io_sethandler(0x0094, 1, - ps1_read, NULL, NULL, ps1_write, NULL, NULL, ps); + ps1_read, NULL, NULL, ps1_write, NULL, NULL, ps); io_sethandler(0x0102, 4, - ps1_read, NULL, NULL, ps1_write, NULL, NULL, ps); + ps1_read, NULL, NULL, ps1_write, NULL, NULL, ps); io_sethandler(0x0190, 1, - ps1_read, NULL, NULL, ps1_write, NULL, NULL, ps); + ps1_read, NULL, NULL, ps1_write, NULL, NULL, ps); ps->uart = device_add_inst(&ns16450_device, 1); lpt1_remove(); - lpt1_init(0x3bc); + lpt1_init(LPT_MDA_ADDR); mem_remap_top(384); device_add(&ps_nvr_device); if (model == 2011) { - rom_init(&ps->high_rom, - "roms/machines/ibmps1es/f80000.bin", - 0xf80000, 0x80000, 0x7ffff, 0, MEM_MAPPING_EXTERNAL); + rom_init(&ps->high_rom, + "roms/machines/ibmps1es/f80000.bin", + 0xf80000, 0x80000, 0x7ffff, 0, MEM_MAPPING_EXTERNAL); - lpt2_remove(); + lpt2_remove(); - device_add(&ps1snd_device); + device_add(&ps1snd_device); - device_add(&fdc_at_ps1_device); + device_add(&fdc_at_ps1_device); - /* Enable the builtin HDC. */ - if (hdc_current == 1) { - priv = device_add(&ps1_hdc_device); + /* Enable the builtin HDC. */ + if (hdc_current == 1) { + priv = device_add(&ps1_hdc_device); - ps1_hdc_inform(priv, &ps->ps1_91); - } - - /* Enable the PS/1 VGA controller. */ - device_add(&ps1vga_device); + ps1_hdc_inform(priv, &ps->ps1_91); + } + + /* Enable the PS/1 VGA controller. */ + device_add(&ps1vga_device); } else if (model == 2121) { - io_sethandler(0x00e0, 2, - ps1_read, NULL, NULL, ps1_write, NULL, NULL, ps); + io_sethandler(0x00e0, 2, + ps1_read, NULL, NULL, ps1_write, NULL, NULL, ps); - rom_init(&ps->high_rom, - "roms/machines/ibmps1_2121/FC0000.BIN", - 0xfc0000, 0x40000, 0x3ffff, 0, MEM_MAPPING_EXTERNAL); + if (rom_present("roms/machines/ibmps1_2121/F80000.BIN")) { + rom_init(&ps->mid_rom, + "roms/machines/ibmps1_2121/F80000.BIN", + 0xf80000, 0x40000, 0x3ffff, 0, MEM_MAPPING_EXTERNAL); + } + rom_init(&ps->high_rom, + "roms/machines/ibmps1_2121/FC0000.BIN", + 0xfc0000, 0x40000, 0x3ffff, 0, MEM_MAPPING_EXTERNAL); - /* Initialize the video controller. */ - if (gfxcard == VID_INTERNAL) - device_add(&ibm_ps1_2121_device); + /* Initialize the video controller. */ + if (gfxcard[0] == VID_INTERNAL) + device_add(&ibm_ps1_2121_device); - device_add(&fdc_at_ps1_device); + device_add(&fdc_at_ps1_device); - device_add(&ide_isa_device); + device_add(&ide_isa_device); - device_add(&ps1snd_device); + device_add(&ps1snd_device); } } @@ -322,7 +323,7 @@ ps1_common_init(const machine_t *model) machine_common_init(model); refresh_at_enable = 1; - pit_ctr_set_out_func(&pit->counters[1], pit_refresh_timer_at); + pit_devs[0].set_out_func(pit_devs[0].data, 1, pit_refresh_timer_at); dma16_init(); pic2_init(); @@ -334,17 +335,16 @@ ps1_common_init(const machine_t *model) standalone_gameport_type = &gameport_201_device; } - int machine_ps1_m2011_init(const machine_t *model) { int ret; ret = bios_load_linear("roms/machines/ibmps1es/f80000.bin", - 0x000e0000, 131072, 0x60000); + 0x000e0000, 131072, 0x60000); if (bios_only || !ret) - return ret; + return ret; ps1_common_init(model); @@ -353,17 +353,16 @@ machine_ps1_m2011_init(const machine_t *model) return ret; } - int machine_ps1_m2121_init(const machine_t *model) { int ret; ret = bios_load_linear("roms/machines/ibmps1_2121/FC0000.BIN", - 0x000e0000, 131072, 0x20000); + 0x000e0000, 131072, 0x20000); if (bios_only || !ret) - return ret; + return ret; ps1_common_init(model); @@ -371,4 +370,3 @@ machine_ps1_m2121_init(const machine_t *model) return ret; } - diff --git a/src/machine/m_ps1_hdc.c b/src/machine/m_ps1_hdc.c index e7547a681..f35879458 100644 --- a/src/machine/m_ps1_hdc.c +++ b/src/machine/m_ps1_hdc.c @@ -1,74 +1,72 @@ /* - * VARCem Virtual ARchaeological Computer EMulator. - * An emulator of (mostly) x86-based PC systems and devices, - * using the ISA,EISA,VLB,MCA and PCI system buses, roughly - * spanning the era between 1981 and 1995. + * VARCem Virtual ARchaeological Computer EMulator. + * An emulator of (mostly) x86-based PC systems and devices, + * using the ISA,EISA,VLB,MCA and PCI system buses, roughly + * spanning the era between 1981 and 1995. * - * This file is part of the VARCem Project. + * Implementation of the PS/1 Model 2011 disk controller. * - * Implementation of the PS/1 Model 2011 disk controller. + * XTA is the acronym for 'XT-Attached', which was basically + * the XT-counterpart to what we know now as IDE (which is + * also named ATA - AT Attachment.) The basic ideas was to + * put the actual drive controller electronics onto the drive + * itself, and have the host machine just talk to that using + * a simpe, standardized I/O path- hence the name IDE, for + * Integrated Drive Electronics. * - * XTA is the acronym for 'XT-Attached', which was basically - * the XT-counterpart to what we know now as IDE (which is - * also named ATA - AT Attachment.) The basic ideas was to - * put the actual drive controller electronics onto the drive - * itself, and have the host machine just talk to that using - * a simpe, standardized I/O path- hence the name IDE, for - * Integrated Drive Electronics. + * In the ATA version of IDE, the programming interface of + * the IBM PC/AT (which used the Western Digitial 1002/1003 + * controllers) was kept, and, so, ATA-IDE assumes a 16bit + * data path: it reads and writes 16bit words of data. The + * disk drives for this bus commonly have an 'A' suffix to + * identify them as 'ATBUS'. * - * In the ATA version of IDE, the programming interface of - * the IBM PC/AT (which used the Western Digitial 1002/1003 - * controllers) was kept, and, so, ATA-IDE assumes a 16bit - * data path: it reads and writes 16bit words of data. The - * disk drives for this bus commonly have an 'A' suffix to - * identify them as 'ATBUS'. + * In XTA-IDE, which is slightly older, the programming + * interface of the IBM PC/XT (which used the MFM controller + * from Xebec) was kept, and, so, it uses an 8bit data path. + * Disk drives for this bus commonly have the 'X' suffix to + * mark them as being for this XTBUS variant. * - * In XTA-IDE, which is slightly older, the programming - * interface of the IBM PC/XT (which used the MFM controller - * from Xebec) was kept, and, so, it uses an 8bit data path. - * Disk drives for this bus commonly have the 'X' suffix to - * mark them as being for this XTBUS variant. + * So, XTA and ATA try to do the same thing, but they use + * different ways to achive their goal. * - * So, XTA and ATA try to do the same thing, but they use - * different ways to achive their goal. + * Also, XTA is **not** the same as XTIDE. XTIDE is a modern + * variant of ATA-IDE, but retro-fitted for use on 8bit XT + * systems: an extra register is used to deal with the extra + * data byte per transfer. XTIDE uses regular IDE drives, + * and uses the regular ATA/IDE programming interface, just + * with the extra register. * - * Also, XTA is **not** the same as XTIDE. XTIDE is a modern - * variant of ATA-IDE, but retro-fitted for use on 8bit XT - * systems: an extra register is used to deal with the extra - * data byte per transfer. XTIDE uses regular IDE drives, - * and uses the regular ATA/IDE programming interface, just - * with the extra register. - * - * NOTE: We should probably find a nicer way to integrate our Disk - * Type table with the main code, so the user can only select - * items from that list... + * NOTE: We should probably find a nicer way to integrate our Disk + * Type table with the main code, so the user can only select + * items from that list... * * * - * Author: Fred N. van Kempen, + * Authors: Fred N. van Kempen, * - * Based on my earlier HD20 driver for the EuroPC. - * Thanks to Marco Bortolin for the help and feedback !! + * Based on my earlier HD20 driver for the EuroPC. + * Thanks to Marco Bortolin for the help and feedback !! * - * Copyright 2017-2019 Fred N. van Kempen. + * Copyright 2017-2019 Fred N. van Kempen. * - * Redistribution and use in source and binary forms, with - * or without modification, are permitted provided that the - * following conditions are met: + * Redistribution and use in source and binary forms, with + * or without modification, are permitted provided that the + * following conditions are met: * - * 1. Redistributions of source code must retain the entire - * above notice, this list of conditions and the following - * disclaimer. + * 1. Redistributions of source code must retain the entire + * above notice, this list of conditions and the following + * disclaimer. * - * 2. Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the - * following disclaimer in the documentation and/or other - * materials provided with the distribution. + * 2. Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the + * following disclaimer in the documentation and/or other + * materials provided with the distribution. * - * 3. Neither the name of the copyright holder nor the names - * of its contributors may be used to endorse or promote - * products derived from this software without specific - * prior written permission. + * 3. Neither the name of the copyright holder nor the names + * of its contributors may be used to endorse or promote + * products derived from this software without specific + * prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT @@ -82,9 +80,6 @@ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -#define __USE_LARGEFILE64 -#define _LARGEFILE_SOURCE -#define _LARGEFILE64_SOURCE #include #include #include @@ -104,10 +99,8 @@ #include <86box/ui.h> #include <86box/machine.h> - -#define HDC_TIME (50*TIMER_USEC) -#define HDC_TYPE_USER 47 /* user drive type */ - +#define HDC_TIME (250 * TIMER_USEC) +#define HDC_TYPE_USER 47 /* user drive type */ enum { STATE_IDLE = 0, @@ -121,45 +114,43 @@ enum { STATE_FDONE }; - /* Command values. These deviate from the XTA ones. */ -#define CMD_READ_SECTORS 0x01 /* regular read-date */ -#define CMD_READ_VERIFY 0x02 /* read for verify, no data */ -#define CMD_READ_EXT 0x03 /* read extended (ecc) */ -#define CMD_READ_ID 0x05 /* read ID mark on cyl */ -#define CMD_RECALIBRATE 0x08 /* recalibrate to track0 */ -#define CMD_WRITE_SECTORS 0x09 /* regular write-data */ -#define CMD_WRITE_VERIFY 0x0a /* write-data with verify */ -#define CMD_WRITE_EXT 0x0b /* write extended (ecc) */ -#define CMD_FORMAT_DRIVE 0x0d /* format entire disk */ -#define CMD_SEEK 0x0e /* seek */ -#define CMD_FORMAT_TRACK 0x0f /* format one track */ +#define CMD_READ_SECTORS 0x01 /* regular read-date */ +#define CMD_READ_VERIFY 0x02 /* read for verify, no data */ +#define CMD_READ_EXT 0x03 /* read extended (ecc) */ +#define CMD_READ_ID 0x05 /* read ID mark on cyl */ +#define CMD_RECALIBRATE 0x08 /* recalibrate to track0 */ +#define CMD_WRITE_SECTORS 0x09 /* regular write-data */ +#define CMD_WRITE_VERIFY 0x0a /* write-data with verify */ +#define CMD_WRITE_EXT 0x0b /* write extended (ecc) */ +#define CMD_FORMAT_DRIVE 0x0d /* format entire disk */ +#define CMD_SEEK 0x0e /* seek */ +#define CMD_FORMAT_TRACK 0x0f /* format one track */ /* Attachment Status register (reg 2R) values (IBM PS/1 2011.) */ -#define ASR_TX_EN 0x01 /* transfer enable */ -#define ASR_INT_REQ 0x02 /* interrupt request */ -#define ASR_BUSY 0x04 /* busy */ -#define ASR_DIR 0x08 /* direction */ -#define ASR_DATA_REQ 0x10 /* data request */ +#define ASR_TX_EN 0x01 /* transfer enable */ +#define ASR_INT_REQ 0x02 /* interrupt request */ +#define ASR_BUSY 0x04 /* busy */ +#define ASR_DIR 0x08 /* direction */ +#define ASR_DATA_REQ 0x10 /* data request */ /* Attachment Control register (2W) values (IBM PS/1 2011.) */ -#define ACR_DMA_EN 0x01 /* DMA enable */ -#define ACR_INT_EN 0x02 /* interrupt enable */ -#define ACR_RESET 0x80 /* reset */ +#define ACR_DMA_EN 0x01 /* DMA enable */ +#define ACR_INT_EN 0x02 /* interrupt enable */ +#define ACR_RESET 0x80 /* reset */ /* Interrupt Status register (4R) values (IBM PS/1 2011.) */ -#define ISR_EQUIP_CHECK 0x01 /* internal hardware error */ -#define ISR_ERP_INVOKED 0x02 /* error recovery invoked */ -#define ISR_CMD_REJECT 0x20 /* command reject */ -#define ISR_INVALID_CMD 0x40 /* invalid command */ -#define ISR_TERMINATION 0x80 /* termination error */ +#define ISR_EQUIP_CHECK 0x01 /* internal hardware error */ +#define ISR_ERP_INVOKED 0x02 /* error recovery invoked */ +#define ISR_CMD_REJECT 0x20 /* command reject */ +#define ISR_INVALID_CMD 0x40 /* invalid command */ +#define ISR_TERMINATION 0x80 /* termination error */ /* Attention register (4W) values (IBM PS/1 2011.) */ -#define ATT_DATA 0x10 /* data request */ -#define ATT_SSB 0x20 /* sense summary block */ -#define ATT_CSB 0x40 /* command specify block */ -#define ATT_CCB 0x80 /* command control block */ - +#define ATT_DATA 0x10 /* data request */ +#define ATT_SSB 0x20 /* sense summary block */ +#define ATT_CSB 0x40 /* command specify block */ +#define ATT_CCB 0x80 /* command control block */ /* * Define the Sense Summary Block. @@ -169,59 +160,59 @@ enum { * each command is completed, after an error, or before the * block is transferred. */ -#pragma pack(push,1) -typedef struct { +#pragma pack(push, 1) +typedef struct ssb_t { /* Status byte 0. */ - uint8_t track_0 :1, /* T0 */ - mbz1 :1, /* 0 */ - mbz2 :1, /* 0 */ - cylinder_err :1, /* CE */ - write_fault :1, /* WF */ - mbz3 :1, /* 0 */ - seek_end :1, /* SE */ - not_ready :1; /* NR */ + uint8_t track_0 : 1; /* T0 */ + uint8_t mbz1 : 1; /* 0 */ + uint8_t mbz2 : 1; /* 0 */ + uint8_t cylinder_err : 1; /* CE */ + uint8_t write_fault : 1; /* WF */ + uint8_t mbz3 : 1; /* 0 */ + uint8_t seek_end : 1; /* SE */ + uint8_t not_ready : 1; /* NR */ /* Status byte 1. */ - uint8_t id_not_found :1, /* ID */ - mbz4 :1, /* 0 */ - mbz5 :1, /* 0 */ - wrong_cyl :1, /* WC */ - all_bit_set :1, /* BT */ - mark_not_found :1, /* AM */ - ecc_crc_err :1, /* ET */ - ecc_crc_field :1; /* EF */ + uint8_t id_not_found : 1; /* ID */ + uint8_t mbz4 : 1; /* 0 */ + uint8_t mbz5 : 1; /* 0 */ + uint8_t wrong_cyl : 1; /* WC */ + uint8_t all_bit_set : 1; /* BT */ + uint8_t mark_not_found : 1; /* AM */ + uint8_t ecc_crc_err : 1; /* ET */ + uint8_t ecc_crc_field : 1; /* EF */ /* Status byte 2. */ - uint8_t headsel_state :4, /* headsel state[4] */ - defective_sector:1, /* DS */ - retried_ok :1, /* RG */ - need_reset :1, /* RR */ + uint8_t headsel_state : 4; /* headsel state[4] */ + uint8_t defective_sector : 1; /* DS */ + uint8_t retried_ok : 1; /* RG */ + uint8_t need_reset : 1; /* RR */ #if 1 - valid :1; /* 0 (abused as VALID) */ + uint8_t valid : 1; /* 0 (abused as VALID) */ #else - mbz6 :1; /* 0 */ + uint8_t mbz6 : 1; /* 0 */ #endif /* Most recent ID field seen. */ - uint8_t last_cyl_low; /* Cyl_Low[8] */ - uint8_t last_head :4, /* HD[4] */ - mbz7 :1, /* 0 */ - last_cyl_high :2, /* Cyl_high[2] */ - last_def_sect :1; /* DS */ - uint8_t last_sect; /* Sect[8] */ + uint8_t last_cyl_low; /* Cyl_Low[8] */ + uint8_t last_head : 4; /* HD[4] */ + uint8_t mbz7 : 1; /* 0 */ + uint8_t last_cyl_high : 2; /* Cyl_high[2] */ + uint8_t last_def_sect : 1; /* DS */ + uint8_t last_sect; /* Sect[8] */ - uint8_t sect_size; /* Size[8] = 02 */ + uint8_t sect_size; /* Size[8] = 02 */ /* Current position. */ - uint8_t curr_cyl_high :2, /* Cyl_High_[2] */ - mbz8 :1, /* 0 */ - mbz9 :1, /* 0 */ - curr_head :4; /* HD_2[4] */ - uint8_t curr_cyl_low; /* Cyl_Low_2[8] */ + uint8_t curr_cyl_high : 2; /* Cyl_High_[2] */ + uint8_t mbz8 : 1; /* 0 */ + uint8_t mbz9 : 1; /* 0 */ + uint8_t curr_head : 4; /* HD_2[4] */ + uint8_t curr_cyl_low; /* Cyl_Low_2[8] */ - uint8_t sect_corr; /* sectors corrected */ + uint8_t sect_corr; /* sectors corrected */ - uint8_t retries; /* retries */ + uint8_t retries; /* retries */ /* * This byte shows the progress of the controller through the @@ -242,7 +233,7 @@ typedef struct { * transfer: * * Bit 7 A sector was transferred between the system - * and the sector buffer. + * and the sector buffer. * * Bit 6 A sector was transferred between the controller * and the sector buffer. @@ -256,11 +247,11 @@ typedef struct { * 4. When the transfer is complete, the low nibble equals hex 4 * and the high nibble is unchanged. */ - uint8_t cmd_syndrome; /* command syndrome */ + uint8_t cmd_syndrome; /* command syndrome */ - uint8_t drive_type; /* drive type */ + uint8_t drive_type; /* drive type */ - uint8_t rsvd; /* reserved byte */ + uint8_t rsvd; /* reserved byte */ } ssb_t; #pragma pack(pop) @@ -298,22 +289,22 @@ typedef struct { * being formatted, an additional byte is sent with all * bits 0. */ -#pragma pack(push,1) -typedef struct { - uint8_t cyl_high :2, /* cylinder [9:8] bits */ - defective_sector:1, /* DS */ - mbz1 :1, /* 0 */ - head :4; /* head number */ +#pragma pack(push, 1) +typedef struct fcb_t { + uint8_t cyl_high : 2; /* cylinder [9:8] bits */ + uint8_t defective_sector : 1; /* DS */ + uint8_t mbz1 : 1; /* 0 */ + uint8_t head : 4; /* head number */ - uint8_t cyl_low; /* cylinder [7:0] bits */ + uint8_t cyl_low; /* cylinder [7:0] bits */ - uint8_t sector; /* sector number */ + uint8_t sector; /* sector number */ - uint8_t mbz2 :1, /* 0 */ - mbo :1, /* 1 */ - mbz3 :6; /* 000000 */ + uint8_t mbz2 : 1; /* 0 */ + uint8_t mbo : 1; /* 1 */ + uint8_t mbz3 : 6; /* 000000 */ - uint8_t fill; /* filler byte */ + uint8_t fill; /* filler byte */ } fcb_t; #pragma pack(pop) @@ -324,97 +315,94 @@ typedef struct { * command control block to the controller. It can be sent * through a DMA or PIO operation. */ -#pragma pack(push,1) -typedef struct { - uint8_t ec_p :1, /* EC/P (ecc/park) */ - mbz1 :1, /* 0 */ - auto_seek :1, /* AS (auto-seek) */ - no_data :1, /* ND (no data) */ - cmd :4; /* command code[4] */ +#pragma pack(push, 1) +typedef struct ccb_t{ + uint8_t ec_p : 1; /* EC/P (ecc/park) */ + uint8_t mbz1 : 1; /* 0 */ + uint8_t auto_seek : 1; /* AS (auto-seek) */ + uint8_t no_data : 1; /* ND (no data) */ + uint8_t cmd : 4; /* command code[4] */ - uint8_t cyl_high :2, /* cylinder [9:8] bits */ - mbz2 :2, /* 00 */ - head :4; /* head number */ + uint8_t cyl_high : 2; /* cylinder [9:8] bits */ + uint8_t mbz2 : 2; /* 00 */ + uint8_t head : 4; /* head number */ - uint8_t cyl_low; /* cylinder [7:0] bits */ + uint8_t cyl_low; /* cylinder [7:0] bits */ - uint8_t sector; /* sector number */ + uint8_t sector; /* sector number */ - uint8_t mbz3 :1, /* 0 */ - mbo1 :1, /* 1 */ - mbz4 :6; /* 000000 */ + uint8_t mbz3 : 1; /* 0 */ + uint8_t mbo1 : 1; /* 1 */ + uint8_t mbz4 : 6; /* 000000 */ - uint8_t count; /* blk count/interleave */ + uint8_t count; /* blk count/interleave */ } ccb_t; #pragma pack(pop) /* Define the hard drive geometry table. */ -typedef struct { - uint16_t cyl; - uint8_t hpc; - uint8_t spt; - int16_t wpc; - int16_t lz; +typedef struct geom_t { + uint16_t cyl; + uint8_t hpc; + uint8_t spt; + int16_t wpc; + int16_t lz; } geom_t; /* Define an attached drive. */ -typedef struct { - int8_t id, /* drive ID on bus */ - present, /* drive is present */ - hdd_num, /* index to global disk table */ - type; /* drive type ID */ +typedef struct drive_t { + int8_t id; /* drive ID on bus */ + int8_t present; /* drive is present */ + int8_t hdd_num; /* index to global disk table */ + int8_t type; /* drive type ID */ - uint16_t cur_cyl; /* last known position of heads */ + uint16_t cur_cyl; /* last known position of heads */ - uint8_t spt, /* active drive parameters */ - hpc; - uint16_t tracks; + uint8_t spt; /* active drive parameters */ + uint8_t hpc; + uint16_t tracks; - uint8_t cfg_spt, /* configured drive parameters */ - cfg_hpc; - uint16_t cfg_tracks; + uint8_t cfg_spt; /* configured drive parameters */ + uint8_t cfg_hpc; + uint16_t cfg_tracks; } drive_t; - -typedef struct { - uint16_t base; /* controller base I/O address */ - int8_t irq; /* controller IRQ channel */ - int8_t dma; /* controller DMA channel */ +typedef struct hdc_t { + uint16_t base; /* controller base I/O address */ + int8_t irq; /* controller IRQ channel */ + int8_t dma; /* controller DMA channel */ /* Registers. */ - uint8_t attn, /* ATTENTION register */ - ctrl, /* Control register (ACR) */ - status, /* Status register (ASR) */ - intstat; /* Interrupt Status register (ISR) */ + uint8_t attn; /* ATTENTION register */ + uint8_t ctrl; /* Control register (ACR) */ + uint8_t status; /* Status register (ASR) */ + uint8_t intstat; /* Interrupt Status register (ISR) */ - uint8_t *reg_91; /* handle to system board's register 0x91 */ + uint8_t *reg_91; /* handle to system board's register 0x91 */ /* Controller state. */ - uint64_t callback; - pc_timer_t timer; - int8_t state, /* controller state */ - reset; /* reset state counter */ + pc_timer_t timer; + int8_t state; /* controller state */ + int8_t reset; /* reset state counter */ /* Data transfer. */ - int16_t buf_idx, /* buffer index and pointer */ - buf_len; - uint8_t *buf_ptr; + int16_t buf_idx; /* buffer index and pointer */ + int16_t buf_len; + uint8_t *buf_ptr; /* Current operation parameters. */ - ssb_t ssb; /* sense block */ - ccb_t ccb; /* command control block */ - uint16_t track; /* requested track# */ - uint8_t head, /* requested head# */ - sector; /* requested sector# */ - int count; /* requested sector count */ + ssb_t ssb; /* sense block */ + ccb_t ccb; /* command control block */ + uint16_t track; /* requested track# */ + uint8_t head; /* requested head# */ + uint8_t sector; /* requested sector# */ + int count; /* requested sector count */ - drive_t drives[XTA_NUM]; /* the attached drive(s) */ + drive_t drives[XTA_NUM]; /* the attached drive(s) */ - uint8_t data[512]; /* data buffer */ - uint8_t sector_buf[512]; /* sector buffer */ + uint8_t data[512]; /* data buffer */ + uint8_t sector_buf[512]; /* sector buffer */ } hdc_t; - /* * IBM hard drive types 1-44. * @@ -425,169 +413,147 @@ typedef struct { * p-comp Zone */ static const geom_t ibm_type_table[] = { - { 0, 0, 0, 0, 0 }, /* 0 (none) */ - { 306, 4, 17, 128, 305 }, /* 1 10 MB */ - { 615, 4, 17, 300, 615 }, /* 2 20 MB */ - { 615, 6, 17, 300, 615 }, /* 3 31 MB */ - { 940, 8, 17, 512, 940 }, /* 4 62 MB */ - { 940, 6, 17, 512, 940 }, /* 5 47 MB */ - { 615, 4, 17, -1, 615 }, /* 6 20 MB */ - { 462, 8, 17, 256, 511 }, /* 7 31 MB */ - { 733, 5, 17, -1, 733 }, /* 8 30 MB */ - { 900, 15, 17, -1, 901 }, /* 9 112 MB */ - { 820, 3, 17, -1, 820 }, /* 10 20 MB */ - { 855, 5, 17, -1, 855 }, /* 11 35 MB */ - { 855, 7, 17, -1, 855 }, /* 12 50 MB */ - { 306, 8, 17, 128, 319 }, /* 13 20 MB */ - { 733, 7, 17, -1, 733 }, /* 14 43 MB */ - { 0, 0, 0, 0, 0 }, /* 15 (rsvd) */ - { 612, 4, 17, 0, 663 }, /* 16 20 MB */ - { 977, 5, 17, 300, 977 }, /* 17 41 MB */ - { 977, 7, 17, -1, 977 }, /* 18 57 MB */ - { 1024, 7, 17, 512, 1023 }, /* 19 59 MB */ - { 733, 5, 17, 300, 732 }, /* 20 30 MB */ - { 733, 7, 17, 300, 732 }, /* 21 43 MB */ - { 733, 5, 17, 300, 733 }, /* 22 30 MB */ - { 306, 4, 17, 0, 336 }, /* 23 10 MB */ - { 612, 4, 17, 305, 663 }, /* 24 20 MB */ - { 306, 4, 17, -1, 340 }, /* 25 10 MB */ - { 612, 4, 17, -1, 670 }, /* 26 20 MB */ - { 698, 7, 17, 300, 732 }, /* 27 41 MB */ - { 976, 5, 17, 488, 977 }, /* 28 40 MB */ - { 306, 4, 17, 0, 340 }, /* 29 10 MB */ - { 611, 4, 17, 306, 663 }, /* 30 20 MB */ - { 732, 7, 17, 300, 732 }, /* 31 43 MB */ - { 1023, 5, 17, -1, 1023 }, /* 32 42 MB */ - { 614, 4, 25, -1, 663 }, /* 33 30 MB */ - { 775, 2, 27, -1, 900 }, /* 34 20 MB */ - { 921, 2, 33, -1, 1000 }, /* 35 30 MB * */ - { 402, 4, 26, -1, 460 }, /* 36 20 MB */ - { 580, 6, 26, -1, 640 }, /* 37 44 MB */ - { 845, 2, 36, -1, 1023 }, /* 38 30 MB * */ - { 769, 3, 36, -1, 1023 }, /* 39 41 MB * */ - { 531, 4, 39, -1, 532 }, /* 40 40 MB */ - { 577, 2, 36, -1, 1023 }, /* 41 20 MB */ - { 654, 2, 32, -1, 674 }, /* 42 20 MB */ - { 923, 5, 36, -1, 1023 }, /* 43 81 MB */ - { 531, 8, 39, -1, 532 } /* 44 81 MB */ + // clang-format off + { 0, 0, 0, 0, 0 }, /* 0 (none) */ + { 306, 4, 17, 128, 305 }, /* 1 10 MB */ + { 615, 4, 17, 300, 615 }, /* 2 20 MB */ + { 615, 6, 17, 300, 615 }, /* 3 31 MB */ + { 940, 8, 17, 512, 940 }, /* 4 62 MB */ + { 940, 6, 17, 512, 940 }, /* 5 47 MB */ + { 615, 4, 17, -1, 615 }, /* 6 20 MB */ + { 462, 8, 17, 256, 511 }, /* 7 31 MB */ + { 733, 5, 17, -1, 733 }, /* 8 30 MB */ + { 900, 15, 17, -1, 901 }, /* 9 112 MB */ + { 820, 3, 17, -1, 820 }, /* 10 20 MB */ + { 855, 5, 17, -1, 855 }, /* 11 35 MB */ + { 855, 7, 17, -1, 855 }, /* 12 50 MB */ + { 306, 8, 17, 128, 319 }, /* 13 20 MB */ + { 733, 7, 17, -1, 733 }, /* 14 43 MB */ + { 0, 0, 0, 0, 0 }, /* 15 (rsvd) */ + { 612, 4, 17, 0, 663 }, /* 16 20 MB */ + { 977, 5, 17, 300, 977 }, /* 17 41 MB */ + { 977, 7, 17, -1, 977 }, /* 18 57 MB */ + { 1024, 7, 17, 512, 1023 }, /* 19 59 MB */ + { 733, 5, 17, 300, 732 }, /* 20 30 MB */ + { 733, 7, 17, 300, 732 }, /* 21 43 MB */ + { 733, 5, 17, 300, 733 }, /* 22 30 MB */ + { 306, 4, 17, 0, 336 }, /* 23 10 MB */ + { 612, 4, 17, 305, 663 }, /* 24 20 MB */ + { 306, 4, 17, -1, 340 }, /* 25 10 MB */ + { 612, 4, 17, -1, 670 }, /* 26 20 MB */ + { 698, 7, 17, 300, 732 }, /* 27 41 MB */ + { 976, 5, 17, 488, 977 }, /* 28 40 MB */ + { 306, 4, 17, 0, 340 }, /* 29 10 MB */ + { 611, 4, 17, 306, 663 }, /* 30 20 MB */ + { 732, 7, 17, 300, 732 }, /* 31 43 MB */ + { 1023, 5, 17, -1, 1023 }, /* 32 42 MB */ + { 614, 4, 25, -1, 663 }, /* 33 30 MB */ + { 775, 2, 27, -1, 900 }, /* 34 20 MB */ + { 921, 2, 33, -1, 1000 }, /* 35 30 MB * */ + { 402, 4, 26, -1, 460 }, /* 36 20 MB */ + { 580, 6, 26, -1, 640 }, /* 37 44 MB */ + { 845, 2, 36, -1, 1023 }, /* 38 30 MB * */ + { 769, 3, 36, -1, 1023 }, /* 39 41 MB * */ + { 531, 4, 39, -1, 532 }, /* 40 40 MB */ + { 577, 2, 36, -1, 1023 }, /* 41 20 MB */ + { 654, 2, 32, -1, 674 }, /* 42 20 MB */ + { 923, 5, 36, -1, 1023 }, /* 43 81 MB */ + { 531, 8, 39, -1, 532 } /* 44 81 MB */ + // clang-format on }; - +#define ENABLE_PS1_HDC_LOG 1 #ifdef ENABLE_PS1_HDC_LOG int ps1_hdc_do_log = ENABLE_PS1_HDC_LOG; - static void ps1_hdc_log(const char *fmt, ...) { - va_list ap; + va_list ap; - if (ps1_hdc_do_log) - { - va_start(ap, fmt); - pclog_ex(fmt, ap); - va_end(ap); - } + if (ps1_hdc_do_log) { + va_start(ap, fmt); + pclog_ex(fmt, ap); + va_end(ap); + } } #else -#define ps1_hdc_log(fmt, ...) +# define ps1_hdc_log(fmt, ...) #endif -static void -hdc_set_callback(hdc_t *dev, uint64_t callback) -{ - if (!dev) { - return; - } - - if (callback) { - dev->callback = callback; - timer_set_delay_u64(&dev->timer, dev->callback); - } else { - dev->callback = 0; - timer_disable(&dev->timer); - } -} - /* FIXME: we should use the disk/hdd_table.c code with custom tables! */ static int ibm_drive_type(drive_t *drive) { const geom_t *ptr; - int i; - for (i = 0; i < (sizeof(ibm_type_table) / sizeof(geom_t)); i++) { - ptr = &ibm_type_table[i]; - if ((drive->tracks == ptr->cyl) && - (drive->hpc == ptr->hpc) && (drive->spt == ptr->spt)) return(i); + for (uint16_t i = 0; i < (sizeof(ibm_type_table) / sizeof(geom_t)); i++) { + ptr = &ibm_type_table[i]; + if ((drive->tracks == ptr->cyl) && (drive->hpc == ptr->hpc) && (drive->spt == ptr->spt)) + return i; } - return(HDC_TYPE_USER); + return HDC_TYPE_USER; } - static void set_intr(hdc_t *dev, int raise) { if (raise) { - dev->status |= ASR_INT_REQ; - if (dev->ctrl & ACR_INT_EN) - picint(1 << dev->irq); + dev->status |= ASR_INT_REQ; + if (dev->ctrl & ACR_INT_EN) + picint(1 << dev->irq); } else { - dev->status &= ~ASR_INT_REQ; - picintc(1 << dev->irq); + dev->status &= ~ASR_INT_REQ; + picintc(1 << dev->irq); } } - /* Get the logical (block) address of a CHS triplet. */ static int get_sector(hdc_t *dev, drive_t *drive, off64_t *addr) { if (drive->cur_cyl != dev->track) { - ps1_hdc_log("HDC: get_sector: wrong cylinder %d/%d\n", - drive->cur_cyl, dev->track); - dev->ssb.wrong_cyl = 1; - return(1); + ps1_hdc_log("HDC: get_sector: wrong cylinder %d/%d\n", + drive->cur_cyl, dev->track); + dev->ssb.wrong_cyl = 1; + return 1; } if (dev->head >= drive->hpc) { - ps1_hdc_log("HDC: get_sector: past end of heads\n"); - dev->ssb.cylinder_err = 1; - return(1); + ps1_hdc_log("HDC: get_sector: past end of heads\n"); + dev->ssb.cylinder_err = 1; + return 1; } if (dev->sector > drive->spt) { - ps1_hdc_log("HDC: get_sector: past end of sectors\n"); - dev->ssb.mark_not_found = 1; - return(1); + ps1_hdc_log("HDC: get_sector: past end of sectors\n"); + dev->ssb.mark_not_found = 1; + return 1; } /* Calculate logical address (block number) of desired sector. */ - *addr = ((((off64_t) dev->track*drive->hpc) + \ - dev->head)*drive->spt) + dev->sector - 1; + *addr = ((((off64_t) dev->track * drive->hpc) + dev->head) * drive->spt) + dev->sector - 1; - return(0); + return 0; } - static void next_sector(hdc_t *dev, drive_t *drive) { if (++dev->sector > drive->spt) { - dev->sector = 1; - if (++dev->head >= drive->hpc) { - dev->head = 0; - dev->track++; - if (++drive->cur_cyl >= drive->tracks) { - drive->cur_cyl = drive->tracks-1; - dev->ssb.cylinder_err = 1; - } - } + dev->sector = 1; + if (++dev->head >= drive->hpc) { + dev->head = 0; + dev->track++; + if (++drive->cur_cyl >= drive->tracks) { + drive->cur_cyl = drive->tracks - 1; + dev->ssb.cylinder_err = 1; + } + } } } - /* Finish up. Repeated all over, so a function it is now. */ static void do_finish(hdc_t *dev) @@ -601,29 +567,29 @@ do_finish(hdc_t *dev) set_intr(dev, 1); } - /* Seek to a cylinder. */ static int do_seek(hdc_t *dev, drive_t *drive, uint16_t cyl) { if (cyl >= drive->tracks) { - dev->ssb.cylinder_err = 1; - return(1); + dev->ssb.cylinder_err = 1; + return 1; } - dev->track = cyl; + dev->track = cyl; drive->cur_cyl = dev->track; - return(0); + return 0; } - /* Format a track or an entire drive. */ static void do_format(hdc_t *dev, drive_t *drive, ccb_t *ccb) { - int start_cyl, end_cyl; - int intr = 0, val; + int start_cyl; + int end_cyl; + int intr = 0; + int val; off64_t addr; #if 0 fcb_t *fcb; @@ -631,470 +597,525 @@ do_format(hdc_t *dev, drive_t *drive, ccb_t *ccb) /* Get the parameters from the CCB. */ if (ccb->cmd == CMD_FORMAT_DRIVE) { - start_cyl = 0; - end_cyl = drive->tracks; + start_cyl = 0; + end_cyl = drive->tracks; } else { - start_cyl = (ccb->cyl_low | (ccb->cyl_high << 8)); - end_cyl = start_cyl + 1; + start_cyl = (ccb->cyl_low | (ccb->cyl_high << 8)); + end_cyl = start_cyl + 1; } switch (dev->state) { - case STATE_IDLE: - /* Ready to transfer the FCB data in. */ - dev->state = STATE_RDATA; - dev->buf_idx = 0; - dev->buf_ptr = dev->data; - dev->buf_len = ccb->count * sizeof(fcb_t); - if (dev->buf_len & 1) - dev->buf_len++; /* must be even */ + case STATE_IDLE: + /* Ready to transfer the FCB data in. */ + dev->state = STATE_RDATA; + dev->buf_idx = 0; + dev->buf_ptr = dev->data; + dev->buf_len = ccb->count * sizeof(fcb_t); + if (dev->buf_len & 1) + dev->buf_len++; /* must be even */ - /* Enable for PIO or DMA, as needed. */ + /* Enable for PIO or DMA, as needed. */ #if NOT_USED - if (dev->ctrl & ACR_DMA_EN) - hdc_set_callback(dev, HDC_TIME); - else + if (dev->ctrl & ACR_DMA_EN) + timer_advance_u64(&dev->timer, HDC_TIME); + else #endif - dev->status |= ASR_DATA_REQ; - break; + dev->status |= ASR_DATA_REQ; + break; - case STATE_RDATA: - /* Perform DMA. */ - while (dev->buf_idx < dev->buf_len) { - val = dma_channel_read(dev->dma); - if (val == DMA_NODATA) { - dev->intstat |= ISR_EQUIP_CHECK; - dev->ssb.need_reset = 1; - intr = 1; - break; - } - dev->buf_ptr[dev->buf_idx] = (val & 0xff); - dev->buf_idx++; - } - dev->state = STATE_RDONE; - hdc_set_callback(dev, HDC_TIME); - break; + case STATE_RDATA: + /* Perform DMA. */ + while (dev->buf_idx < dev->buf_len) { + val = dma_channel_read(dev->dma); + if (val == DMA_NODATA) { + dev->intstat |= ISR_EQUIP_CHECK; + dev->ssb.need_reset = 1; + intr = 1; + break; + } + dev->buf_ptr[dev->buf_idx] = (val & 0xff); + dev->buf_idx++; + } + dev->state = STATE_RDONE; + timer_advance_u64(&dev->timer, HDC_TIME); + break; - case STATE_RDONE: - if (! (dev->ctrl & ACR_DMA_EN)) - dev->status &= ~ASR_DATA_REQ; + case STATE_RDONE: + if (!(dev->ctrl & ACR_DMA_EN)) + dev->status &= ~ASR_DATA_REQ; - /* Point to the FCB we got. */ + /* Point to the FCB we got. */ #if 0 - fcb = (fcb_t *)dev->data; + fcb = (fcb_t *)dev->data; #endif - dev->state = STATE_FINIT; - /*FALLTHROUGH*/ + dev->state = STATE_FINIT; + fallthrough; - case STATE_FINIT: + case STATE_FINIT: do_fmt: - /* Activate the status icon. */ - ui_sb_update_icon(SB_HDD|HDD_BUS_XTA, 1); + /* Activate the status icon. */ + ui_sb_update_icon(SB_HDD | HDD_BUS_XTA, 1); - /* Seek to cylinder. */ - if (do_seek(dev, drive, start_cyl)) { - intr = 1; - break; - } - dev->head = ccb->head; - dev->sector = 1; + /* Seek to cylinder. */ + if (do_seek(dev, drive, start_cyl)) { + intr = 1; + break; + } + dev->head = ccb->head; + dev->sector = 1; - /* Get address of sector to write. */ - if (get_sector(dev, drive, &addr)) { - intr = 1; - break; - } + /* Get address of sector to write. */ + if (get_sector(dev, drive, &addr)) { + intr = 1; + break; + } - /* - * For now, we don't use the info from - * the FCB, although we should at least - * use it's "filler byte" value... - */ + /* + * For now, we don't use the info from + * the FCB, although we should at least + * use it's "filler byte" value... + */ #if 0 - hdd_image_zero_ex(drive->hdd_num, addr, fcb->fill, drive->spt); + hdd_image_zero_ex(drive->hdd_num, addr, fcb->fill, drive->spt); #else - hdd_image_zero(drive->hdd_num, addr, drive->spt); + hdd_image_zero(drive->hdd_num, addr, drive->spt); #endif - /* Done with this track. */ - dev->state = STATE_FDONE; - /*FALLTHROUGH*/ + /* Done with this track. */ + dev->state = STATE_FDONE; + fallthrough; + case STATE_FDONE: + /* One more track done. */ + if (++start_cyl == end_cyl) { + intr = 1; + break; + } - case STATE_FDONE: - /* One more track done. */ - if (++start_cyl == end_cyl) { - intr = 1; - break; - } + /* De-activate the status icon. */ + ui_sb_update_icon(SB_HDD | HDD_BUS_XTA, 0); - /* De-activate the status icon. */ - ui_sb_update_icon(SB_HDD|HDD_BUS_XTA, 0); + /* This saves us a LOT of code. */ + dev->state = STATE_FINIT; + goto do_fmt; - /* This saves us a LOT of code. */ - dev->state = STATE_FINIT; - goto do_fmt; + default: + break; } /* If we errored out, go back idle. */ if (intr) { - /* De-activate the status icon. */ - ui_sb_update_icon(SB_HDD|HDD_BUS_XTA, 0); + /* De-activate the status icon. */ + ui_sb_update_icon(SB_HDD | HDD_BUS_XTA, 0); - do_finish(dev); + do_finish(dev); } } - /* Execute the CCB we just received. */ static void hdc_callback(void *priv) { - hdc_t *dev = (hdc_t *)priv; - ccb_t *ccb = &dev->ccb; + hdc_t *dev = (hdc_t *) priv; + ccb_t *ccb = &dev->ccb; drive_t *drive; - off64_t addr; - int no_data = 0; - int val; - - /* Cancel timer. */ - dev->callback = 0; + off64_t addr; + int no_data = 0; + int val; + uint8_t cmd = ccb->cmd & 0x0f; /* Clear the SSB error bits. */ - dev->ssb.track_0 = 0; - dev->ssb.cylinder_err = 0; - dev->ssb.write_fault = 0; - dev->ssb.seek_end = 0; - dev->ssb.not_ready = 0; - dev->ssb.id_not_found = 0; - dev->ssb.wrong_cyl = 0; - dev->ssb.all_bit_set = 0; + dev->ssb.track_0 = 0; + dev->ssb.cylinder_err = 0; + dev->ssb.write_fault = 0; + dev->ssb.seek_end = 0; + dev->ssb.not_ready = 0; + dev->ssb.id_not_found = 0; + dev->ssb.wrong_cyl = 0; + dev->ssb.all_bit_set = 0; dev->ssb.mark_not_found = 0; - dev->ssb.ecc_crc_err = 0; - dev->ssb.ecc_crc_field = 0; - dev->ssb.valid = 1; + dev->ssb.ecc_crc_err = 0; + dev->ssb.ecc_crc_field = 0; + dev->ssb.valid = 1; /* We really only support one drive, but ohwell. */ drive = &dev->drives[0]; + ps1_hdc_log("hdc_callback(): %02X\n", cmd); + switch (ccb->cmd) { - case CMD_READ_VERIFY: - no_data = 1; - /*FALLTHROUGH*/ + case CMD_READ_VERIFY: + no_data = 1; + fallthrough; - case CMD_READ_SECTORS: - if (! drive->present) { - dev->ssb.not_ready = 1; - do_finish(dev); - return; - } + case CMD_READ_SECTORS: + if (!drive->present) { + dev->ssb.not_ready = 1; + do_finish(dev); + return; + } - switch (dev->state) { - case STATE_IDLE: - /* Seek to cylinder if requested. */ - if (ccb->auto_seek) { - if (do_seek(dev, drive, - (ccb->cyl_low|(ccb->cyl_high<<8)))) { - do_finish(dev); - return; - } - } - dev->head = ccb->head; - dev->sector = ccb->sector; + switch (dev->state) { + case STATE_IDLE: + /* Seek to cylinder if requested. */ + if (ccb->auto_seek) { + if (do_seek(dev, drive, + (ccb->cyl_low | (ccb->cyl_high << 8)))) { + do_finish(dev); + return; + } + } + dev->head = ccb->head; + dev->sector = ccb->sector; - /* Get sector count and size. */ - dev->count = (int)ccb->count; - dev->buf_len = (128 << dev->ssb.sect_size); + /* Get sector count and size. */ + dev->count = (int) ccb->count; + dev->buf_len = (128 << dev->ssb.sect_size); - dev->state = STATE_SEND; - /*FALLTHROUGH*/ + dev->state = STATE_SEND; + fallthrough; - case STATE_SEND: - /* Activate the status icon. */ - ui_sb_update_icon(SB_HDD|HDD_BUS_XTA, 1); + case STATE_SEND: + /* Activate the status icon. */ + ui_sb_update_icon(SB_HDD | HDD_BUS_XTA, 1); do_send: - /* Get address of sector to load. */ - if (get_sector(dev, drive, &addr)) { - /* De-activate the status icon. */ - ui_sb_update_icon(SB_HDD|HDD_BUS_XTA, 0); - do_finish(dev); - return; - } + /* Get address of sector to load. */ + if (get_sector(dev, drive, &addr)) { + /* De-activate the status icon. */ + ui_sb_update_icon(SB_HDD | HDD_BUS_XTA, 0); + do_finish(dev); + return; + } - /* Read the block from the image. */ - hdd_image_read(drive->hdd_num, addr, 1, - (uint8_t *)dev->sector_buf); + /* Read the block from the image. */ + hdd_image_read(drive->hdd_num, addr, 1, + (uint8_t *) dev->sector_buf); - /* Ready to transfer the data out. */ - dev->state = STATE_SDATA; - dev->buf_idx = 0; - if (no_data) { - /* Delay a bit, no actual transfer. */ - hdc_set_callback(dev, HDC_TIME); - } else { - if (dev->ctrl & ACR_DMA_EN) { - /* DMA enabled. */ - dev->buf_ptr = dev->sector_buf; - hdc_set_callback(dev, HDC_TIME); - } else { - /* No DMA, do PIO. */ - dev->status |= (ASR_DATA_REQ|ASR_DIR); + /* Ready to transfer the data out. */ + dev->state = STATE_SDATA; + dev->buf_idx = 0; + if (no_data) { + /* Delay a bit, no actual transfer. */ + timer_advance_u64(&dev->timer, HDC_TIME); + } else { + if (dev->ctrl & ACR_DMA_EN) { + /* DMA enabled. */ + dev->buf_ptr = dev->sector_buf; + timer_advance_u64(&dev->timer, HDC_TIME); + } else { + /* No DMA, do PIO. */ + dev->status |= (ASR_DATA_REQ | ASR_DIR); - /* Copy from sector to data. */ - memcpy(dev->data, - dev->sector_buf, - dev->buf_len); - dev->buf_ptr = dev->data; - } - } - break; - - case STATE_SDATA: - if (! no_data) { - /* Perform DMA. */ - while (dev->buf_idx < dev->buf_len) { - val = dma_channel_write(dev->dma, - *dev->buf_ptr++); - if (val == DMA_NODATA) { - ps1_hdc_log("HDC: CMD_READ_SECTORS out of data (idx=%d, len=%d)!\n", dev->buf_idx, dev->buf_len); + /* Copy from sector to data. */ + memcpy(dev->data, + dev->sector_buf, + dev->buf_len); + dev->buf_ptr = dev->data; + } + } + break; - /* De-activate the status icon. */ - ui_sb_update_icon(SB_HDD|HDD_BUS_XTA, 0); + case STATE_SDATA: + if (!no_data) { + /* Perform DMA. */ + while (dev->buf_idx < dev->buf_len) { + val = dma_channel_write(dev->dma, + *dev->buf_ptr++); + if (val == DMA_NODATA) { + ps1_hdc_log("HDC: CMD_READ_SECTORS out of data (idx=%d, len=%d)!\n", dev->buf_idx, dev->buf_len); - dev->intstat |= ISR_EQUIP_CHECK; - dev->ssb.need_reset = 1; - do_finish(dev); - return; - } - dev->buf_idx++; - } - } - dev->state = STATE_SDONE; - hdc_set_callback(dev, HDC_TIME); - break; + /* De-activate the status icon. */ + ui_sb_update_icon(SB_HDD | HDD_BUS_XTA, 0); - case STATE_SDONE: - dev->buf_idx = 0; - if (--dev->count == 0) { - /* De-activate the status icon. */ - ui_sb_update_icon(SB_HDD|HDD_BUS_XTA, 0); + dev->intstat |= ISR_EQUIP_CHECK; + dev->ssb.need_reset = 1; + do_finish(dev); + return; + } + dev->buf_idx++; + } + } + dev->state = STATE_SDONE; + timer_advance_u64(&dev->timer, HDC_TIME); + break; - if (! (dev->ctrl & ACR_DMA_EN)) - dev->status &= ~(ASR_DATA_REQ|ASR_DIR); - dev->ssb.cmd_syndrome = 0xD4; - do_finish(dev); - return; - } + case STATE_SDONE: + dev->buf_idx = 0; + if (--dev->count == 0) { + /* De-activate the status icon. */ + ui_sb_update_icon(SB_HDD | HDD_BUS_XTA, 0); - /* Addvance to next sector. */ - next_sector(dev, drive); + if (!(dev->ctrl & ACR_DMA_EN)) + dev->status &= ~(ASR_DATA_REQ | ASR_DIR); + dev->ssb.cmd_syndrome = 0xD4; + do_finish(dev); + return; + } - /* This saves us a LOT of code. */ - dev->state = STATE_SEND; - goto do_send; - } - break; + /* Addvance to next sector. */ + next_sector(dev, drive); - case CMD_READ_EXT: /* READ_EXT */ - case CMD_READ_ID: /* READ_ID */ - if (! drive->present) { - dev->ssb.not_ready = 1; - do_finish(dev); - return; - } + /* This saves us a LOT of code. */ + dev->state = STATE_SEND; + goto do_send; - dev->intstat |= ISR_INVALID_CMD; - do_finish(dev); - break; + default: + break; + } + break; - case CMD_RECALIBRATE: /* RECALIBRATE */ - if (drive->present) { - dev->track = drive->cur_cyl = 0; - } else { - dev->ssb.not_ready = 1; - dev->intstat |= ISR_TERMINATION; - } + case CMD_READ_ID: /* READ_ID */ + if (!drive->present) { + dev->ssb.not_ready = 1; + do_finish(dev); + return; + } - do_finish(dev); - break; + switch (dev->state) { + case STATE_IDLE: + /* Seek to cylinder if requested. */ + if (ccb->auto_seek) { + if (do_seek(dev, drive, + (ccb->cyl_low | (ccb->cyl_high << 8)))) { + do_finish(dev); + return; + } + } + dev->head = ccb->head; - case CMD_WRITE_VERIFY: - no_data = 1; - /*FALLTHROUGH*/ + /* Get sector count and size. */ + dev->count = (int) ccb->count; + dev->buf_len = (128 << dev->ssb.sect_size); - case CMD_WRITE_SECTORS: - if (! drive->present) { - dev->ssb.not_ready = 1; - do_finish(dev); - return; - } + /* Activate the status icon. */ + ui_sb_update_icon(SB_HDD | HDD_BUS_XTA, 1); - switch (dev->state) { - case STATE_IDLE: - /* Seek to cylinder if requested. */ - if (ccb->auto_seek) { - if (do_seek(dev, drive, - (ccb->cyl_low|(ccb->cyl_high<<8)))) { - do_finish(dev); - return; - } - } - dev->head = ccb->head; - dev->sector = ccb->sector; + /* Ready to transfer the data out. */ + dev->state = STATE_SDONE; + dev->buf_idx = 0; + /* Delay a bit, no actual transfer. */ + timer_advance_u64(&dev->timer, HDC_TIME); + break; - /* Get sector count and size. */ - dev->count = (int)ccb->count; - dev->buf_len = (128 << dev->ssb.sect_size); + case STATE_SDONE: + dev->buf_idx = 0; - dev->state = STATE_RECV; - /*FALLTHROUGH*/ + /* De-activate the status icon. */ + ui_sb_update_icon(SB_HDD | HDD_BUS_XTA, 0); - case STATE_RECV: - /* Activate the status icon. */ - ui_sb_update_icon(SB_HDD|HDD_BUS_XTA, 1); + if (!(dev->ctrl & ACR_DMA_EN)) + dev->status &= ~(ASR_DATA_REQ | ASR_DIR); + dev->ssb.cmd_syndrome = 0x14; + do_finish(dev); + break; + + default: + break; + } + break; + + case CMD_READ_EXT: /* READ_EXT */ + if (!drive->present) { + dev->ssb.not_ready = 1; + do_finish(dev); + return; + } + + dev->intstat |= ISR_INVALID_CMD; + do_finish(dev); + break; + + case CMD_RECALIBRATE: /* RECALIBRATE */ + if (drive->present) { + dev->track = drive->cur_cyl = 0; + } else { + dev->ssb.not_ready = 1; + dev->intstat |= ISR_TERMINATION; + } + + do_finish(dev); + break; + + case CMD_WRITE_VERIFY: + no_data = 1; + fallthrough; + + case CMD_WRITE_SECTORS: + if (!drive->present) { + dev->ssb.not_ready = 1; + do_finish(dev); + return; + } + + switch (dev->state) { + case STATE_IDLE: + /* Seek to cylinder if requested. */ + if (ccb->auto_seek) { + if (do_seek(dev, drive, + (ccb->cyl_low | (ccb->cyl_high << 8)))) { + do_finish(dev); + return; + } + } + dev->head = ccb->head; + dev->sector = ccb->sector; + + /* Get sector count and size. */ + dev->count = (int) ccb->count; + dev->buf_len = (128 << dev->ssb.sect_size); + + dev->state = STATE_RECV; + fallthrough; + + case STATE_RECV: + /* Activate the status icon. */ + ui_sb_update_icon(SB_HDD | HDD_BUS_XTA, 1); do_recv: - /* Ready to transfer the data in. */ - dev->state = STATE_RDATA; - dev->buf_idx = 0; - if (no_data) { - /* Delay a bit, no actual transfer. */ - hdc_set_callback(dev, HDC_TIME); - } else { - if (dev->ctrl & ACR_DMA_EN) { - /* DMA enabled. */ - dev->buf_ptr = dev->sector_buf; - hdc_set_callback(dev, HDC_TIME); - } else { - /* No DMA, do PIO. */ - dev->buf_ptr = dev->data; - dev->status |= ASR_DATA_REQ; - } - } - break; + /* Ready to transfer the data in. */ + dev->state = STATE_RDATA; + dev->buf_idx = 0; + if (no_data) { + /* Delay a bit, no actual transfer. */ + timer_advance_u64(&dev->timer, HDC_TIME); + } else { + if (dev->ctrl & ACR_DMA_EN) { + /* DMA enabled. */ + dev->buf_ptr = dev->sector_buf; + timer_advance_u64(&dev->timer, HDC_TIME); + } else { + /* No DMA, do PIO. */ + dev->buf_ptr = dev->data; + dev->status |= ASR_DATA_REQ; + } + } + break; - case STATE_RDATA: - if (! no_data) { - /* Perform DMA. */ - while (dev->buf_idx < dev->buf_len) { - val = dma_channel_read(dev->dma); - if (val == DMA_NODATA) { - ps1_hdc_log("HDC: CMD_WRITE_SECTORS out of data (idx=%d, len=%d)!\n", dev->buf_idx, dev->buf_len); + case STATE_RDATA: + if (!no_data) { + /* Perform DMA. */ + while (dev->buf_idx < dev->buf_len) { + val = dma_channel_read(dev->dma); + if (val == DMA_NODATA) { + ps1_hdc_log("HDC: CMD_WRITE_SECTORS out of data (idx=%d, len=%d)!\n", dev->buf_idx, dev->buf_len); - /* De-activate the status icon. */ - ui_sb_update_icon(SB_HDD|HDD_BUS_XTA, 0); + /* De-activate the status icon. */ + ui_sb_update_icon(SB_HDD | HDD_BUS_XTA, 0); - dev->intstat |= ISR_EQUIP_CHECK; - dev->ssb.need_reset = 1; - do_finish(dev); - return; - } - dev->buf_ptr[dev->buf_idx] = (val & 0xff); - dev->buf_idx++; - } - } - dev->state = STATE_RDONE; - hdc_set_callback(dev, HDC_TIME); - break; + dev->intstat |= ISR_EQUIP_CHECK; + dev->ssb.need_reset = 1; + do_finish(dev); + return; + } + dev->buf_ptr[dev->buf_idx] = (val & 0xff); + dev->buf_idx++; + } + } + dev->state = STATE_RDONE; + timer_advance_u64(&dev->timer, HDC_TIME); + break; - case STATE_RDONE: - /* Copy from data to sector if PIO. */ - if (! (dev->ctrl & ACR_DMA_EN)) - memcpy(dev->sector_buf, - dev->data, - dev->buf_len); + case STATE_RDONE: + /* Copy from data to sector if PIO. */ + if (!(dev->ctrl & ACR_DMA_EN)) + memcpy(dev->sector_buf, + dev->data, + dev->buf_len); - /* Get address of sector to write. */ - if (get_sector(dev, drive, &addr)) { - /* De-activate the status icon. */ - ui_sb_update_icon(SB_HDD|HDD_BUS_XTA, 0); + /* Get address of sector to write. */ + if (get_sector(dev, drive, &addr)) { + /* De-activate the status icon. */ + ui_sb_update_icon(SB_HDD | HDD_BUS_XTA, 0); - do_finish(dev); - return; - } + do_finish(dev); + return; + } - /* Write the block to the image. */ - hdd_image_write(drive->hdd_num, addr, 1, - (uint8_t *)dev->sector_buf); + /* Write the block to the image. */ + hdd_image_write(drive->hdd_num, addr, 1, + (uint8_t *) dev->sector_buf); - dev->buf_idx = 0; - if (--dev->count == 0) { - /* De-activate the status icon. */ - ui_sb_update_icon(SB_HDD|HDD_BUS_XTA, 0); + dev->buf_idx = 0; + if (--dev->count == 0) { + /* De-activate the status icon. */ + ui_sb_update_icon(SB_HDD | HDD_BUS_XTA, 0); - if (! (dev->ctrl & ACR_DMA_EN)) - dev->status &= ~ASR_DATA_REQ; - dev->ssb.cmd_syndrome = 0xD4; - do_finish(dev); - return; - } + if (!(dev->ctrl & ACR_DMA_EN)) + dev->status &= ~ASR_DATA_REQ; + dev->ssb.cmd_syndrome = 0xD4; + do_finish(dev); + return; + } - /* Advance to next sector. */ - next_sector(dev, drive); + /* Advance to next sector. */ + next_sector(dev, drive); - /* This saves us a LOT of code. */ - dev->state = STATE_RECV; - goto do_recv; - } - break; + /* This saves us a LOT of code. */ + dev->state = STATE_RECV; + goto do_recv; - case CMD_FORMAT_DRIVE: - case CMD_FORMAT_TRACK: - do_format(dev, drive, ccb); - break; - - case CMD_SEEK: - if (! drive->present) { - dev->ssb.not_ready = 1; - do_finish(dev); - return; - } + default: + break; + } + break; - if (ccb->ec_p == 1) { - /* Park the heads. */ - val = do_seek(dev, drive, drive->tracks-1); - } else { - /* Seek to cylinder. */ - val = do_seek(dev, drive, - (ccb->cyl_low|(ccb->cyl_high<<8))); - } - if (! val) - dev->ssb.seek_end = 1; - do_finish(dev); - break; + case CMD_FORMAT_DRIVE: + case CMD_FORMAT_TRACK: + do_format(dev, drive, ccb); + break; - default: - dev->intstat |= ISR_INVALID_CMD; - do_finish(dev); + case CMD_SEEK: + if (!drive->present) { + dev->ssb.not_ready = 1; + do_finish(dev); + return; + } + + if (ccb->ec_p == 1) { + /* Park the heads. */ + val = do_seek(dev, drive, drive->tracks - 1); + } else { + /* Seek to cylinder. */ + val = do_seek(dev, drive, + (ccb->cyl_low | (ccb->cyl_high << 8))); + } + if (!val) + dev->ssb.seek_end = 1; + do_finish(dev); + break; + + default: + dev->intstat |= ISR_INVALID_CMD; + do_finish(dev); } } - /* Prepare to send the SSB block. */ static void hdc_send_ssb(hdc_t *dev) { - drive_t *drive; + const drive_t *drive; /* We only support one drive, really, but ohwell. */ drive = &dev->drives[0]; - if (! dev->ssb.valid) { - /* Create a valid SSB. */ - memset(&dev->ssb, 0x00, sizeof(dev->ssb)); - dev->ssb.sect_size = 0x02; /* 512 bytes */ - dev->ssb.drive_type = drive->type; + if (!dev->ssb.valid) { + /* Create a valid SSB. */ + memset(&dev->ssb, 0x00, sizeof(dev->ssb)); + dev->ssb.sect_size = 0x02; /* 512 bytes */ + dev->ssb.drive_type = drive->type; } /* Update position fields. */ - dev->ssb.track_0 = !!(dev->track == 0); - dev->ssb.last_cyl_low = dev->ssb.curr_cyl_low; + dev->ssb.track_0 = !!(dev->track == 0); + dev->ssb.last_cyl_low = dev->ssb.curr_cyl_low; dev->ssb.last_cyl_high = dev->ssb.curr_cyl_high; - dev->ssb.last_head = dev->ssb.curr_head; + dev->ssb.last_head = dev->ssb.curr_head; dev->ssb.curr_cyl_high = ((dev->track >> 8) & 0x03); - dev->ssb.curr_cyl_low = (dev->track & 0xff); - dev->ssb.curr_head = (dev->head & 0x0f); + dev->ssb.curr_cyl_low = (dev->track & 0xff); + dev->ssb.curr_head = (dev->head & 0x0f); dev->ssb.headsel_state = dev->ssb.curr_head; - dev->ssb.last_sect = dev->sector; + dev->ssb.last_sect = dev->sector; /* We abuse an unused MBZ bit, so clear it. */ dev->ssb.valid = 0; @@ -1102,169 +1123,177 @@ hdc_send_ssb(hdc_t *dev) /* Set up the transfer buffer for the SSB. */ dev->buf_idx = 0; dev->buf_len = sizeof(dev->ssb); - dev->buf_ptr = (uint8_t *)&dev->ssb; + dev->buf_ptr = (uint8_t *) &dev->ssb; /* Done with the SSB. */ dev->attn &= ~ATT_SSB; } - /* Read one of the controller registers. */ static uint8_t hdc_read(uint16_t port, void *priv) { - hdc_t *dev = (hdc_t *)priv; + hdc_t *dev = (hdc_t *) priv; uint8_t ret = 0xff; /* TRM: tell system board we are alive. */ *dev->reg_91 |= 0x01; switch (port & 7) { - case 0: /* DATA register */ - if (dev->state == STATE_SDATA) { - if (dev->buf_idx > dev->buf_len) { - ps1_hdc_log("HDC: read with empty buffer!\n"); - dev->state = STATE_IDLE; - dev->intstat |= ISR_INVALID_CMD; - dev->status &= (ASR_TX_EN|ASR_DATA_REQ|ASR_DIR); - set_intr(dev, 1); - break; - } + case 0: /* DATA register */ + if (dev->state == STATE_SDATA) { + if (dev->buf_idx > dev->buf_len) { + ps1_hdc_log("HDC: read with empty buffer!\n"); + dev->state = STATE_IDLE; + dev->intstat |= ISR_INVALID_CMD; + dev->status &= (ASR_TX_EN | ASR_DATA_REQ | ASR_DIR); + set_intr(dev, 1); + break; + } - ret = dev->buf_ptr[dev->buf_idx]; - if (++dev->buf_idx == dev->buf_len) { - /* Data block sent OK. */ - dev->status &= ~(ASR_TX_EN|ASR_DATA_REQ|ASR_DIR); - dev->state = STATE_IDLE; - } - } - break; + ret = dev->buf_ptr[dev->buf_idx]; + if (++dev->buf_idx == dev->buf_len) { + /* Data block sent OK. */ + dev->status &= ~(ASR_TX_EN | ASR_DATA_REQ | ASR_DIR); + dev->state = STATE_IDLE; + } + } + break; - case 2: /* ASR */ - ret = dev->status; - break; + case 2: /* ASR */ + ret = dev->status; + break; - case 4: /* ISR */ - ret = dev->intstat; - dev->intstat = 0x00; - break; + case 4: /* ISR */ + ret = dev->intstat; + dev->intstat = 0x00; + break; + + default: + break; } - return(ret); -} + ps1_hdc_log("[%04X:%08X] [R] %04X = %02X\n", CS, cpu_state.pc, port, ret); + return ret; +} static void hdc_write(uint16_t port, uint8_t val, void *priv) { - hdc_t *dev = (hdc_t *)priv; + hdc_t *dev = (hdc_t *) priv; + + ps1_hdc_log("[%04X:%08X] [W] %04X = %02X\n", CS, cpu_state.pc, port, val); /* TRM: tell system board we are alive. */ *dev->reg_91 |= 0x01; switch (port & 7) { - case 0: /* DATA register */ - if (dev->state == STATE_RDATA) { - if (dev->buf_idx >= dev->buf_len) { - ps1_hdc_log("HDC: write with full buffer!\n"); - dev->intstat |= ISR_INVALID_CMD; - dev->status &= ~ASR_DATA_REQ; - set_intr(dev, 1); - break; - } + case 0: /* DATA register */ + if (dev->state == STATE_RDATA) { + if (dev->buf_idx >= dev->buf_len) { + ps1_hdc_log("HDC: write with full buffer!\n"); + dev->intstat |= ISR_INVALID_CMD; + dev->status &= ~ASR_DATA_REQ; + set_intr(dev, 1); + break; + } - /* Store the data into the buffer. */ - dev->buf_ptr[dev->buf_idx] = val; - if (++dev->buf_idx == dev->buf_len) { - /* We got all the data we need. */ - dev->status &= ~ASR_DATA_REQ; - dev->state = STATE_IDLE; + /* Store the data into the buffer. */ + dev->buf_ptr[dev->buf_idx] = val; + ps1_hdc_log("dev->buf_ptr[%02X] = %02X\n", dev->buf_idx, val); + if (++dev->buf_idx == dev->buf_len) { + /* We got all the data we need. */ + dev->status &= ~ASR_DATA_REQ; + dev->state = STATE_IDLE; - /* If we were receiving a CCB, execute it. */ - if (dev->attn & ATT_CCB) { - /* - * If we were already busy with - * a CCB, then it must have had - * some new data using PIO. - */ - if (dev->status & ASR_BUSY) - dev->state = STATE_RDONE; - else - dev->status |= ASR_BUSY; + /* If we were receiving a CCB, execute it. */ + if (dev->attn & ATT_CCB) { + /* + * If we were already busy with + * a CCB, then it must have had + * some new data using PIO. + */ + if (dev->status & ASR_BUSY) + dev->state = STATE_RDONE; + else + dev->status |= ASR_BUSY; - /* Schedule command execution. */ - hdc_set_callback(dev, HDC_TIME); - } - } - } - break; + /* Schedule command execution. */ + timer_set_delay_u64(&dev->timer, HDC_TIME); + } + } + } + break; - case 2: /* ACR */ - dev->ctrl = val; - if (val & ACR_INT_EN) - set_intr(dev, 0); /* clear IRQ */ + case 2: /* ACR */ + dev->ctrl = val; + if (val & ACR_INT_EN) + set_intr(dev, 0); /* clear IRQ */ - if (dev->reset != 0) { - if (++dev->reset == 3) { - dev->reset = 0; + if (dev->reset != 0) { + if (++dev->reset == 3) { + dev->reset = 0; - set_intr(dev, 1); - } - break; - } + set_intr(dev, 1); + } + break; + } - if (val & ACR_RESET) - dev->reset = 1; - break; + if (val & ACR_RESET) + dev->reset = 1; + break; - case 4: /* ATTN */ - dev->status &= ~ASR_INT_REQ; - if (val & ATT_DATA) { - /* Dunno. Start PIO/DMA now? */ - } + case 4: /* ATTN */ + dev->status &= ~ASR_INT_REQ; + if (val & ATT_DATA) { + /* Dunno. Start PIO/DMA now? */ + } - if (val & ATT_SSB) { - if (dev->attn & ATT_CCB) { - /* Hey now, we're still busy for you! */ - dev->intstat |= ISR_INVALID_CMD; - set_intr(dev, 1); - break; - } + if (val & ATT_SSB) { + if (dev->attn & ATT_CCB) { + /* Hey now, we're still busy for you! */ + dev->intstat |= ISR_INVALID_CMD; + set_intr(dev, 1); + break; + } - /* OK, prepare for sending an SSB. */ - dev->attn |= ATT_SSB; + /* OK, prepare for sending an SSB. */ + dev->attn |= ATT_SSB; - /* Grab or initialize an SSB to send. */ - hdc_send_ssb(dev); + /* Grab or initialize an SSB to send. */ + hdc_send_ssb(dev); - dev->state = STATE_SDATA; - dev->status |= (ASR_TX_EN|ASR_DATA_REQ|ASR_DIR); - set_intr(dev, 1); - } + dev->state = STATE_SDATA; + dev->status |= (ASR_TX_EN | ASR_DATA_REQ | ASR_DIR); + set_intr(dev, 1); + } - if (val & ATT_CCB) { - dev->attn |= ATT_CCB; + if (val & ATT_CCB) { + dev->attn |= ATT_CCB; - /* Set up the transfer buffer for a CCB. */ - dev->buf_idx = 0; - dev->buf_len = sizeof(dev->ccb); - dev->buf_ptr = (uint8_t *)&dev->ccb; + /* Set up the transfer buffer for a CCB. */ + dev->buf_idx = 0; + dev->buf_len = sizeof(dev->ccb); + dev->buf_ptr = (uint8_t *) &dev->ccb; - dev->state = STATE_RDATA; - dev->status |= ASR_DATA_REQ; - set_intr(dev, 1); - } - break; + dev->state = STATE_RDATA; + dev->status |= ASR_DATA_REQ; + set_intr(dev, 1); + } + break; + + default: + break; } } - static void * -ps1_hdc_init(const device_t *info) +ps1_hdc_init(UNUSED(const device_t *info)) { drive_t *drive; - hdc_t *dev; - int c, i; + hdc_t *dev; + int c; /* Allocate and initialize device block. */ dev = malloc(sizeof(hdc_t)); @@ -1272,44 +1301,45 @@ ps1_hdc_init(const device_t *info) /* Set up controller parameters for PS/1 2011. */ dev->base = 0x0320; - dev->irq = 14; - dev->dma = 3; + dev->irq = 14; + dev->dma = 3; ps1_hdc_log("HDC: initializing (I/O=%04X, IRQ=%d, DMA=%d)\n", - dev->base, dev->irq, dev->dma); + dev->base, dev->irq, dev->dma); /* Load any disks for this device class. */ c = 0; - for (i = 0; i < HDD_NUM; i++) { - if ((hdd[i].bus == HDD_BUS_XTA) && (hdd[i].xta_channel < 1)) { - drive = &dev->drives[hdd[i].xta_channel]; + for (uint8_t i = 0; i < HDD_NUM; i++) { + if ((hdd[i].bus == HDD_BUS_XTA) && (hdd[i].xta_channel < 1)) { + drive = &dev->drives[hdd[i].xta_channel]; - if (! hdd_image_load(i)) { - drive->present = 0; - continue; - } - drive->id = c; + if (!hdd_image_load(i)) { + drive->present = 0; + continue; + } + drive->id = c; - /* These are the "hardware" parameters (from the image.) */ - drive->cfg_spt = (uint8_t)(hdd[i].spt & 0xff); - drive->cfg_hpc = (uint8_t)(hdd[i].hpc & 0xff); - drive->cfg_tracks = (uint16_t)hdd[i].tracks; + /* These are the "hardware" parameters (from the image.) */ + drive->cfg_spt = (uint8_t) (hdd[i].spt & 0xff); + drive->cfg_hpc = (uint8_t) (hdd[i].hpc & 0xff); + drive->cfg_tracks = (uint16_t) hdd[i].tracks; - /* Use them as "active" parameters until overwritten. */ - drive->spt = drive->cfg_spt; - drive->hpc = drive->cfg_hpc; - drive->tracks = drive->cfg_tracks; + /* Use them as "active" parameters until overwritten. */ + drive->spt = drive->cfg_spt; + drive->hpc = drive->cfg_hpc; + drive->tracks = drive->cfg_tracks; - drive->type = ibm_drive_type(drive); - drive->hdd_num = i; - drive->present = 1; + drive->type = ibm_drive_type(drive); + drive->hdd_num = i; + drive->present = 1; - ps1_hdc_log("HDC: drive%d (type %d: cyl=%d,hd=%d,spt=%d), disk %d\n", - hdd[i].xta_channel, drive->type, - drive->tracks, drive->hpc, drive->spt, i); + ps1_hdc_log("HDC: drive%d (type %d: cyl=%d,hd=%d,spt=%d), disk %d\n", + hdd[i].xta_channel, drive->type, + drive->tracks, drive->hpc, drive->spt, i); - if (++c > 1) break; - } + if (++c > 1) + break; + } } /* Sectors are 1-based. */ @@ -1317,50 +1347,50 @@ ps1_hdc_init(const device_t *info) /* Enable the I/O block. */ io_sethandler(dev->base, 5, - hdc_read,NULL,NULL, hdc_write,NULL,NULL, dev); + hdc_read, NULL, NULL, hdc_write, NULL, NULL, dev); /* Create a timer for command delays. */ - timer_add(&dev->timer, hdc_callback, dev, 0); + timer_add(&dev->timer, hdc_callback, dev, 0); - return(dev); + return dev; } - static void ps1_hdc_close(void *priv) { - hdc_t *dev = (hdc_t *)priv; - drive_t *drive; - int d; + hdc_t *dev = (hdc_t *) priv; + const drive_t *drive; /* Remove the I/O handler. */ io_removehandler(dev->base, 5, - hdc_read,NULL,NULL, hdc_write,NULL,NULL, dev); + hdc_read, NULL, NULL, hdc_write, NULL, NULL, dev); /* Close all disks and their images. */ - for (d = 0; d < XTA_NUM; d++) { - drive = &dev->drives[d]; + for (uint8_t d = 0; d < XTA_NUM; d++) { + drive = &dev->drives[d]; - if (drive->present) - hdd_image_close(drive->hdd_num); + if (drive->present) + hdd_image_close(drive->hdd_num); } /* Release the device. */ free(dev); } - const device_t ps1_hdc_device = { - "PS/1 2011 Fixed Disk Controller", - "ps1_hdc", - DEVICE_ISA | DEVICE_PS2, - 0, - ps1_hdc_init, ps1_hdc_close, NULL, - { NULL }, NULL, NULL, - NULL + .name = "PS/1 2011 Fixed Disk Controller", + .internal_name = "ps1_hdc", + .flags = DEVICE_ISA | DEVICE_PS2, + .local = 0, + .init = ps1_hdc_init, + .close = ps1_hdc_close, + .reset = NULL, + { .available = NULL }, + .speed_changed = NULL, + .force_redraw = NULL, + .config = NULL }; - /* * Very nasty. * @@ -1376,7 +1406,7 @@ const device_t ps1_hdc_device = { void ps1_hdc_inform(void *priv, uint8_t *reg_91) { - hdc_t *dev = (hdc_t *)priv; + hdc_t *dev = (hdc_t *) priv; dev->reg_91 = reg_91; } diff --git a/src/machine/m_ps2_isa.c b/src/machine/m_ps2_isa.c index 987b29f2e..fa9c5acc2 100644 --- a/src/machine/m_ps2_isa.c +++ b/src/machine/m_ps2_isa.c @@ -1,5 +1,6 @@ #include #include +#include #include #include #include <86box/86box.h> @@ -24,182 +25,197 @@ #include <86box/video.h> #include <86box/machine.h> +typedef struct { + int model; + int cpu_type; -static uint8_t ps2_91, ps2_94, ps2_102, ps2_103, ps2_104, ps2_105, ps2_190; -static serial_t *ps2_uart; + uint8_t ps2_91, + ps2_92, + ps2_94, + ps2_102, + ps2_103, + ps2_104, + ps2_105, + ps2_190; + serial_t *uart; +} ps2_isa_t; -static struct +static void +ps2_write(uint16_t port, uint8_t val, void *priv) { - uint8_t status, int_status; - uint8_t attention, ctrl; -} ps2_hd; + ps2_isa_t *ps2 = (ps2_isa_t *) priv; + switch (port) { + case 0x0094: + ps2->ps2_94 = val; + break; -static uint8_t ps2_read(uint16_t port, void *p) -{ - uint8_t temp; + case 0x0102: + if (!(ps2->ps2_94 & 0x80)) { + lpt1_remove(); + serial_remove(ps2->uart); + if (val & 0x04) { + if (val & 0x08) + serial_setup(ps2->uart, COM1_ADDR, COM1_IRQ); + else + serial_setup(ps2->uart, COM2_ADDR, COM2_IRQ); + } + if (val & 0x10) { + switch ((val >> 5) & 3) { + case 0: + lpt1_init(LPT_MDA_ADDR); + break; + case 1: + lpt1_init(LPT1_ADDR); + break; + case 2: + lpt1_init(LPT2_ADDR); + break; - switch (port) - { - case 0x91: - temp = ps2_91; - ps2_91 = 0; - return temp; - case 0x94: - return ps2_94; - case 0x102: - return ps2_102 | 8; - case 0x103: - return ps2_103; - case 0x104: - return ps2_104; - case 0x105: - return ps2_105; - case 0x190: - return ps2_190; + default: + break; + } + } + ps2->ps2_102 = val; + } + break; -#ifdef FIXME - case 0x322: - temp = ps2_hd.status; - break; - case 0x324: - temp = ps2_hd.int_status; - ps2_hd.int_status &= ~0x02; - break; -#endif + case 0x0103: + ps2->ps2_103 = val; + break; - default: - temp = 0xff; - break; - } - - return temp; + case 0x0104: + ps2->ps2_104 = val; + break; + + case 0x0105: + ps2->ps2_105 = val; + break; + + case 0x0190: + ps2->ps2_190 = val; + break; + + default: + break; + } } -static void ps2_write(uint16_t port, uint8_t val, void *p) +static uint8_t +ps2_read(uint16_t port, void *priv) { - switch (port) - { - case 0x94: - ps2_94 = val; - break; - case 0x102: - if (!(ps2_94 & 0x80)) { - lpt1_remove(); - serial_remove(ps2_uart); - if (val & 0x04) { - if (val & 0x08) - serial_setup(ps2_uart, SERIAL1_ADDR, SERIAL1_IRQ); - else - serial_setup(ps2_uart, SERIAL2_ADDR, SERIAL2_IRQ); - } - if (val & 0x10) { - switch ((val >> 5) & 3) - { - case 0: - lpt1_init(0x3bc); - break; - case 1: - lpt1_init(0x378); - break; - case 2: - lpt1_init(0x278); - break; - } - } - ps2_102 = val; - } - break; + ps2_isa_t *ps2 = (ps2_isa_t *) priv; + uint8_t temp = 0xff; - case 0x103: - ps2_103 = val; - break; - case 0x104: - ps2_104 = val; - break; - case 0x105: - ps2_105 = val; - break; - case 0x190: - ps2_190 = val; - break; + switch (port) { + case 0x0091: + temp = ps2->ps2_91; + ps2->ps2_91 = 0; + break; -#ifdef FIXME - case 0x322: - ps2_hd.ctrl = val; - if (val & 0x80) - ps2_hd.status |= 0x02; - break; - case 0x324: - ps2_hd.attention = val & 0xf0; - if (ps2_hd.attention) - ps2_hd.status = 0x14; - break; -#endif - } + case 0x0094: + temp = ps2->ps2_94; + break; + + case 0x0102: + temp = ps2->ps2_102 | 0x08; + break; + + case 0x0103: + temp = ps2->ps2_103; + break; + + case 0x0104: + temp = ps2->ps2_104; + break; + + case 0x0105: + temp = ps2->ps2_105; + break; + + case 0x0190: + temp = ps2->ps2_190; + break; + + default: + break; + } + + return temp; } - -static void ps2board_init(void) +static void +ps2_isa_setup(int model, int cpu_type) { - io_sethandler(0x0091, 0x0001, ps2_read, NULL, NULL, ps2_write, NULL, NULL, NULL); - io_sethandler(0x0094, 0x0001, ps2_read, NULL, NULL, ps2_write, NULL, NULL, NULL); - io_sethandler(0x0102, 0x0004, ps2_read, NULL, NULL, ps2_write, NULL, NULL, NULL); - io_sethandler(0x0190, 0x0001, ps2_read, NULL, NULL, ps2_write, NULL, NULL, NULL); -#ifdef FIXME - io_sethandler(0x0320, 0x0001, ps2_read, NULL, NULL, ps2_write, NULL, NULL, NULL); - io_sethandler(0x0322, 0x0001, ps2_read, NULL, NULL, ps2_write, NULL, NULL, NULL); - io_sethandler(0x0324, 0x0001, ps2_read, NULL, NULL, ps2_write, NULL, NULL, NULL); -#endif + ps2_isa_t *ps2; + void *priv; - device_add(&port_92_device); + ps2 = (ps2_isa_t *) malloc(sizeof(ps2_isa_t)); + memset(ps2, 0x00, sizeof(ps2_isa_t)); + ps2->model = model; + ps2->cpu_type = cpu_type; - ps2_190 = 0; + io_sethandler(0x0091, 1, + ps2_read, NULL, NULL, ps2_write, NULL, NULL, ps2); + io_sethandler(0x0094, 1, + ps2_read, NULL, NULL, ps2_write, NULL, NULL, ps2); + io_sethandler(0x0102, 4, + ps2_read, NULL, NULL, ps2_write, NULL, NULL, ps2); + io_sethandler(0x0190, 1, + ps2_read, NULL, NULL, ps2_write, NULL, NULL, ps2); - ps2_uart = device_add_inst(&ns16450_device, 1); + ps2->uart = device_add_inst(&ns16450_device, 1); - lpt1_init(0x3bc); - - memset(&ps2_hd, 0, sizeof(ps2_hd)); + lpt1_remove(); + lpt1_init(LPT_MDA_ADDR); + + device_add(&port_92_device); + + mem_remap_top(384); + + device_add(&ps_nvr_device); + + device_add(&fdc_at_ps1_device); + + /* Enable the builtin HDC. */ + if (hdc_current == 1) { + priv = device_add(&ps1_hdc_device); + ps1_hdc_inform(priv, &ps2->ps2_91); + } + + device_add(&ps1vga_device); } +static void +ps2_isa_common_init(const machine_t *model) +{ + machine_common_init(model); + + refresh_at_enable = 1; + pit_devs[0].set_out_func(pit_devs[0].data, 1, pit_refresh_timer_at); + + dma16_init(); + pic2_init(); + + device_add(&keyboard_ps2_device); + device_add(&port_6x_ps2_device); +} int machine_ps2_m30_286_init(const machine_t *model) { - void *priv; + int ret; - int ret; + ret = bios_load_linear("roms/machines/ibmps2_m30_286/33f5381a.bin", + 0x000e0000, 131072, 0); - ret = bios_load_linear("roms/machines/ibmps2_m30_286/33f5381a.bin", - 0x000e0000, 131072, 0); + if (bios_only || !ret) + return ret; - if (bios_only || !ret) - return ret; + ps2_isa_common_init(model); - machine_common_init(model); + ps2_isa_setup(30, 286); - mem_remap_top(384); - - device_add(&fdc_at_ps1_device); - - refresh_at_enable = 1; - pit_ctr_set_out_func(&pit->counters[1], pit_refresh_timer_at); - dma16_init(); - device_add(&keyboard_ps2_device); - device_add(&port_6x_ps2_device); - device_add(&ps_nvr_device); - pic2_init(); - ps2board_init(); - device_add(&ps1vga_device); - - /* Enable the builtin HDC. */ - if (hdc_current == 1) { - priv = device_add(&ps1_hdc_device); - - ps1_hdc_inform(priv, &ps2_91); - } - - return ret; + return ret; } diff --git a/src/machine/m_ps2_mca.c b/src/machine/m_ps2_mca.c index 549168ffb..a6fc30e1c 100644 --- a/src/machine/m_ps2_mca.c +++ b/src/machine/m_ps2_mca.c @@ -1,22 +1,22 @@ /* - * VARCem Virtual ARchaeological Computer EMulator. - * An emulator of (mostly) x86-based PC systems and devices, - * using the ISA,EISA,VLB,MCA and PCI system buses, roughly - * spanning the era between 1981 and 1995. + * 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 VARCem Project. + * This file is part of the 86Box distribution. * - * Implementation of MCA-based PS/2 machines. + * Implementation of MCA-based PS/2 machines. * * * - * Authors: Fred N. van Kempen, - * Miran Grca, - * Sarah Walker, + * Authors: Fred N. van Kempen, + * Miran Grca, + * Sarah Walker, * - * Copyright 2017-2019 Fred N. van Kempen. - * Copyright 2016-2019 Miran Grca. - * Copyright 2008-2019 Sarah Walker. + * Copyright 2017-2019 Fred N. van Kempen. + * Copyright 2016-2019 Miran Grca. + * Copyright 2008-2019 Sarah Walker. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -35,7 +35,7 @@ * 59 Temple Place - Suite 330 * Boston, MA 02111-1307 * USA. -*/ + */ #include #include #include @@ -68,45 +68,46 @@ #include <86box/serial.h> #include <86box/video.h> #include <86box/machine.h> +#include <86box/plat_unused.h> +static struct ps2_t { + uint8_t adapter_setup; + uint8_t option[4]; + uint8_t pos_vga; + uint8_t setup; + uint8_t sys_ctrl_port_a; + uint8_t subaddr_lo; + uint8_t subaddr_hi; -static struct -{ - uint8_t adapter_setup; - uint8_t option[4]; - uint8_t pos_vga; - uint8_t setup; - uint8_t sys_ctrl_port_a; - uint8_t subaddr_lo, subaddr_hi; - - uint8_t memory_bank[8]; - - uint8_t io_id; - uint16_t planar_id; + uint8_t memory_bank[8]; - mem_mapping_t split_mapping; - mem_mapping_t expansion_mapping; - mem_mapping_t cache_mapping; - - uint8_t (*planar_read)(uint16_t port); - void (*planar_write)(uint16_t port, uint8_t val); - - uint8_t mem_regs[3]; - - uint32_t split_addr, split_size; - uint32_t split_phys; - - uint8_t mem_pos_regs[8]; - uint8_t mem_2mb_pos_regs[8]; - - int pending_cache_miss; + uint8_t io_id; + uint16_t planar_id; - serial_t *uart; + mem_mapping_t split_mapping; + mem_mapping_t expansion_mapping; + mem_mapping_t cache_mapping; + + uint8_t (*planar_read)(uint16_t port); + void (*planar_write)(uint16_t port, uint8_t val); + + uint8_t mem_regs[3]; + + uint32_t split_addr; + uint32_t split_size; + uint32_t split_phys; + + uint8_t mem_pos_regs[8]; + uint8_t mem_2mb_pos_regs[8]; + + int pending_cache_miss; + + serial_t *uart; } ps2; /*The model 70 type 3/4 BIOS performs cache testing. Since 86Box doesn't have any proper cache emulation, it's faked a bit here. - + Port E2 is used for cache diagnostics. Bit 7 seems to be set on a cache miss, toggling bit 2 seems to clear this. The BIOS performs at least the following tests : @@ -124,7 +125,7 @@ static struct This behaviour is required to pass the timer interrupt test on the 486 version - the BIOS uses a fixed length loop that will terminate too early on a 486/25 if it executes from internal cache. - + To handle this, 86Box uses some basic heuristics : - If cache is enabled but RAM is disabled, accesses to low memory go directly to cache memory. @@ -138,1077 +139,1132 @@ static struct */ static uint8_t ps2_cache[65536]; -static int ps2_cache_valid[65536/8]; - +static int ps2_cache_valid[65536 / 8]; #ifdef ENABLE_PS2_MCA_LOG int ps2_mca_do_log = ENABLE_PS2_MCA_LOG; - static void ps2_mca_log(const char *fmt, ...) { va_list ap; if (ps2_mca_do_log) { - va_start(ap, fmt); - pclog_ex(fmt, ap); - va_end(ap); + va_start(ap, fmt); + pclog_ex(fmt, ap); + va_end(ap); } } #else -#define ps2_mca_log(fmt, ...) +# define ps2_mca_log(fmt, ...) #endif - -static uint8_t ps2_read_cache_ram(uint32_t addr, void *priv) +static uint8_t +ps2_read_cache_ram(uint32_t addr, UNUSED(void *priv)) { - ps2_mca_log("ps2_read_cache_ram: addr=%08x %i %04x:%04x\n", addr, ps2_cache_valid[addr >> 3], CS,cpu_state.pc); - if (!ps2_cache_valid[addr >> 3]) - { - ps2_cache_valid[addr >> 3] = 1; - ps2.mem_regs[2] |= 0x80; - } - else - ps2.pending_cache_miss = 0; + ps2_mca_log("ps2_read_cache_ram: addr=%08x %i %04x:%04x\n", addr, ps2_cache_valid[addr >> 3], CS, cpu_state.pc); + if (!ps2_cache_valid[addr >> 3]) { + ps2_cache_valid[addr >> 3] = 1; + ps2.mem_regs[2] |= 0x80; + } else + ps2.pending_cache_miss = 0; - return ps2_cache[addr]; + return ps2_cache[addr]; } -static uint16_t ps2_read_cache_ramw(uint32_t addr, void *priv) +static uint16_t +ps2_read_cache_ramw(uint32_t addr, UNUSED(void *priv)) { - ps2_mca_log("ps2_read_cache_ramw: addr=%08x %i %04x:%04x\n", addr, ps2_cache_valid[addr >> 3], CS,cpu_state.pc); - if (!ps2_cache_valid[addr >> 3]) - { - ps2_cache_valid[addr >> 3] = 1; - ps2.mem_regs[2] |= 0x80; - } - else - ps2.pending_cache_miss = 0; + ps2_mca_log("ps2_read_cache_ramw: addr=%08x %i %04x:%04x\n", addr, ps2_cache_valid[addr >> 3], CS, cpu_state.pc); + if (!ps2_cache_valid[addr >> 3]) { + ps2_cache_valid[addr >> 3] = 1; + ps2.mem_regs[2] |= 0x80; + } else + ps2.pending_cache_miss = 0; - return *(uint16_t *)&ps2_cache[addr]; + return *(uint16_t *) &ps2_cache[addr]; } -static uint32_t ps2_read_cache_raml(uint32_t addr, void *priv) +static uint32_t +ps2_read_cache_raml(uint32_t addr, UNUSED(void *priv)) { - ps2_mca_log("ps2_read_cache_raml: addr=%08x %i %04x:%04x\n", addr, ps2_cache_valid[addr >> 3], CS,cpu_state.pc); - if (!ps2_cache_valid[addr >> 3]) - { - ps2_cache_valid[addr >> 3] = 1; - ps2.mem_regs[2] |= 0x80; - } - else - ps2.pending_cache_miss = 0; + ps2_mca_log("ps2_read_cache_raml: addr=%08x %i %04x:%04x\n", addr, ps2_cache_valid[addr >> 3], CS, cpu_state.pc); + if (!ps2_cache_valid[addr >> 3]) { + ps2_cache_valid[addr >> 3] = 1; + ps2.mem_regs[2] |= 0x80; + } else + ps2.pending_cache_miss = 0; - return *(uint32_t *)&ps2_cache[addr]; + return *(uint32_t *) &ps2_cache[addr]; } -static void ps2_write_cache_ram(uint32_t addr, uint8_t val, void *priv) +static void +ps2_write_cache_ram(uint32_t addr, uint8_t val, UNUSED(void *priv)) { - ps2_mca_log("ps2_write_cache_ram: addr=%08x val=%02x %04x:%04x %i\n", addr, val, CS,cpu_state.pc); - ps2_cache[addr] = val; + ps2_mca_log("ps2_write_cache_ram: addr=%08x val=%02x %04x:%04x %i\n", addr, val, CS, cpu_state.pc); + ps2_cache[addr] = val; } -void ps2_cache_clean(void) +void +ps2_cache_clean(void) { - memset(ps2_cache_valid, 0, sizeof(ps2_cache_valid)); + memset(ps2_cache_valid, 0, sizeof(ps2_cache_valid)); } -static uint8_t ps2_read_split_ram(uint32_t addr, void *priv) +static uint8_t +ps2_read_split_ram(uint32_t addr, void *priv) { - addr = (addr % (ps2.split_size << 10)) + ps2.split_phys; - return mem_read_ram(addr, priv); + addr = (addr % (ps2.split_size << 10)) + ps2.split_phys; + return mem_read_ram(addr, priv); } -static uint16_t ps2_read_split_ramw(uint32_t addr, void *priv) +static uint16_t +ps2_read_split_ramw(uint32_t addr, void *priv) { - addr = (addr % (ps2.split_size << 10)) + ps2.split_phys; - return mem_read_ramw(addr, priv); + addr = (addr % (ps2.split_size << 10)) + ps2.split_phys; + return mem_read_ramw(addr, priv); } -static uint32_t ps2_read_split_raml(uint32_t addr, void *priv) +static uint32_t +ps2_read_split_raml(uint32_t addr, void *priv) { - addr = (addr % (ps2.split_size << 10)) + ps2.split_phys; - return mem_read_raml(addr, priv); + addr = (addr % (ps2.split_size << 10)) + ps2.split_phys; + return mem_read_raml(addr, priv); } -static void ps2_write_split_ram(uint32_t addr, uint8_t val, void *priv) +static void +ps2_write_split_ram(uint32_t addr, uint8_t val, void *priv) { - addr = (addr % (ps2.split_size << 10)) + ps2.split_phys; - mem_write_ram(addr, val, priv); + addr = (addr % (ps2.split_size << 10)) + ps2.split_phys; + mem_write_ram(addr, val, priv); } -static void ps2_write_split_ramw(uint32_t addr, uint16_t val, void *priv) +static void +ps2_write_split_ramw(uint32_t addr, uint16_t val, void *priv) { - addr = (addr % (ps2.split_size << 10)) + ps2.split_phys; - mem_write_ramw(addr, val, priv); + addr = (addr % (ps2.split_size << 10)) + ps2.split_phys; + mem_write_ramw(addr, val, priv); } -static void ps2_write_split_raml(uint32_t addr, uint32_t val, void *priv) +static void +ps2_write_split_raml(uint32_t addr, uint32_t val, void *priv) { - addr = (addr % (ps2.split_size << 10)) + ps2.split_phys; - mem_write_raml(addr, val, priv); + addr = (addr % (ps2.split_size << 10)) + ps2.split_phys; + mem_write_raml(addr, val, priv); } - -#define PS2_SETUP_IO 0x80 -#define PS2_SETUP_VGA 0x20 +#define PS2_SETUP_IO 0x80 +#define PS2_SETUP_VGA 0x20 #define PS2_ADAPTER_SETUP 0x08 -static uint8_t model_50_read(uint16_t port) +static uint8_t +model_50_read(uint16_t port) { - switch (port) - { - case 0x100: - return 0xff; - case 0x101: - return 0xfb; - case 0x102: - return ps2.option[0]; - case 0x103: - return ps2.option[1]; - case 0x104: - return ps2.option[2]; - case 0x105: - return ps2.option[3]; - case 0x106: - return ps2.subaddr_lo; - case 0x107: - return ps2.subaddr_hi; - } - return 0xff; + switch (port) { + case 0x100: + return ps2.planar_id & 0xff; + case 0x101: + return ps2.planar_id >> 8; + case 0x102: + return ps2.option[0]; + case 0x103: + return ps2.option[1]; + case 0x104: + return ps2.option[2]; + case 0x105: + return ps2.option[3]; + case 0x106: + return ps2.subaddr_lo; + case 0x107: + return ps2.subaddr_hi; + + default: + break; + } + return 0xff; } -static uint8_t model_55sx_read(uint16_t port) +static uint8_t +model_55sx_read(uint16_t port) { - switch (port) - { - case 0x100: - return 0xff; - case 0x101: - return 0xfb; - case 0x102: - return ps2.option[0]; - case 0x103: - return ps2.option[1]; - case 0x104: - return ps2.memory_bank[ps2.option[3] & 7]; - case 0x105: - return ps2.option[3]; - case 0x106: - return ps2.subaddr_lo; - case 0x107: - return ps2.subaddr_hi; - } - return 0xff; + switch (port) { + case 0x100: + return ps2.planar_id & 0xff; + case 0x101: + return ps2.planar_id >> 8; + case 0x102: + return ps2.option[0]; + case 0x103: + return ps2.option[1]; + case 0x104: + return ps2.memory_bank[ps2.option[3] & 7]; + case 0x105: + return ps2.option[3]; + case 0x106: + return ps2.subaddr_lo; + case 0x107: + return ps2.subaddr_hi; + + default: + break; + } + return 0xff; } -static uint8_t model_70_type3_read(uint16_t port) +static uint8_t +model_70_type3_read(uint16_t port) { - switch (port) - { - case 0x100: - return ps2.planar_id & 0xff; - case 0x101: - return ps2.planar_id >> 8; - case 0x102: - return ps2.option[0]; - case 0x103: - return ps2.option[1]; - case 0x104: - return ps2.option[2]; - case 0x105: - return ps2.option[3]; - case 0x106: - return ps2.subaddr_lo; - case 0x107: - return ps2.subaddr_hi; - } - return 0xff; + switch (port) { + case 0x100: + return ps2.planar_id & 0xff; + case 0x101: + return ps2.planar_id >> 8; + case 0x102: + return ps2.option[0]; + case 0x103: + return ps2.option[1]; + case 0x104: + return ps2.option[2]; + case 0x105: + return ps2.option[3]; + case 0x106: + return ps2.subaddr_lo; + case 0x107: + return ps2.subaddr_hi; + + default: + break; + } + return 0xff; } -static uint8_t model_80_read(uint16_t port) +static uint8_t +model_80_read(uint16_t port) { - switch (port) - { - case 0x100: - return 0xff; - case 0x101: - return 0xfd; - case 0x102: - return ps2.option[0]; - case 0x103: - return ps2.option[1]; - case 0x104: - return ps2.option[2]; - case 0x105: - return ps2.option[3]; - case 0x106: - return ps2.subaddr_lo; - case 0x107: - return ps2.subaddr_hi; - } - return 0xff; + switch (port) { + case 0x100: + return ps2.planar_id & 0xff; + case 0x101: + return ps2.planar_id >> 8; + case 0x102: + return ps2.option[0]; + case 0x103: + return ps2.option[1]; + case 0x104: + return ps2.option[2]; + case 0x105: + return ps2.option[3]; + case 0x106: + return ps2.subaddr_lo; + case 0x107: + return ps2.subaddr_hi; + + default: + break; + } + return 0xff; } -static void model_50_write(uint16_t port, uint8_t val) +static void +model_50_write(uint16_t port, uint8_t val) { - switch (port) - { - case 0x100: - ps2.io_id = val; - break; - case 0x101: - break; - case 0x102: - lpt1_remove(); - serial_remove(ps2.uart); - if (val & 0x04) - { - if (val & 0x08) - serial_setup(ps2.uart, SERIAL1_ADDR, SERIAL1_IRQ); - else - serial_setup(ps2.uart, SERIAL2_ADDR, SERIAL2_IRQ); + switch (port) { + case 0x102: + lpt1_remove(); + serial_remove(ps2.uart); + if (val & 0x04) { + if (val & 0x08) + serial_setup(ps2.uart, COM1_ADDR, COM1_IRQ); + else + serial_setup(ps2.uart, COM2_ADDR, COM2_IRQ); + } + if (val & 0x10) { + switch ((val >> 5) & 3) { + case 0: + lpt1_init(LPT_MDA_ADDR); + break; + case 1: + lpt1_init(LPT1_ADDR); + break; + case 2: + lpt1_init(LPT2_ADDR); + break; + + default: + break; } - if (val & 0x10) - { - switch ((val >> 5) & 3) - { - case 0: - lpt1_init(0x3bc); - break; - case 1: - lpt1_init(0x378); - break; - case 2: - lpt1_init(0x278); - break; - } - } - ps2.option[0] = val; - break; - case 0x103: - ps2.option[1] = val; - break; - case 0x104: - ps2.option[2] = val; - break; - case 0x105: - ps2.option[3] = val; - break; - case 0x106: - ps2.subaddr_lo = val; - break; - case 0x107: - ps2.subaddr_hi = val; - break; - } + } + ps2.option[0] = val; + break; + case 0x103: + ps2.option[1] = val; + break; + case 0x104: + ps2.option[2] = val; + break; + case 0x105: + ps2.option[3] = val; + break; + case 0x106: + ps2.subaddr_lo = val; + break; + case 0x107: + ps2.subaddr_hi = val; + break; + + default: + break; + } } - -static void model_55sx_mem_recalc(void) +static void +model_55sx_mem_recalc(void) { - int i, j, state, enabled_mem = 0; - int base = 0, remap_size = (ps2.option[3] & 0x10) ? 384 : 256; - int bit_mask = 0x00, max_rows = 4; - int bank_to_rows[16] = { 4, 2, 1, 0, 0, 2, 1, 0, 0, 0, 0, 0, 0, 2, 1, 0 }; - - ps2_mca_log("%02X %02X\n", ps2.option[1], ps2.option[3]); - - mem_remap_top(remap_size); - mem_set_mem_state(0x00000000, (mem_size + 384) * 1024, MEM_READ_EXTERNAL | MEM_WRITE_EXTERNAL); - mem_set_mem_state(0x000e0000, 0x00020000, MEM_READ_EXTANY | MEM_WRITE_DISABLED); - - for (i = 0; i < 2; i++) - { - max_rows = bank_to_rows[(ps2.memory_bank[i] >> 4) & 0x0f]; - - if (max_rows == 0) - continue; - - for (j = 0; j < max_rows; j++) - { - if (ps2.memory_bank[i] & (1 << j)) { - ps2_mca_log("Set memory at %06X-%06X to internal\n", (base * 1024), (base * 1024) + (((base > 0) ? 1024 : 640) * 1024) - 1); - mem_set_mem_state(base * 1024, ((base > 0) ? 1024 : 640) * 1024, MEM_READ_INTERNAL | MEM_WRITE_INTERNAL); - enabled_mem += 1024; - bit_mask |= (1 << (j + (i << 2))); - } - base += 1024; - } - } - - ps2_mca_log("Enabled memory: %i kB (%02X)\n", enabled_mem, bit_mask); - - if (ps2.option[3] & 0x10) - { - /* Enable ROM. */ - ps2_mca_log("Enable ROM\n"); - state = MEM_READ_EXTANY; - } - else - { - /* Disable ROM. */ - if ((ps2.option[1] & 1) && !(ps2.option[3] & 0x20) && (bit_mask & 0x01)) - { - /* Disable RAM between 640 kB and 1 MB. */ - ps2_mca_log("Disable ROM, enable RAM\n"); - state = MEM_READ_INTERNAL; - } - else - { - ps2_mca_log("Disable ROM, disable RAM\n"); - state = MEM_READ_DISABLED; - } - } - - /* Write always disabled. */ - state |= MEM_WRITE_DISABLED; - - mem_set_mem_state(0xe0000, 0x20000, state); - - /* if (!(ps2.option[3] & 0x08)) - { - ps2_mca_log("Memory not yet configured\n"); - return; - } */ - - ps2_mca_log("Enable shadow mapping at %06X-%06X\n", (mem_size * 1024), (mem_size * 1024) + (remap_size * 1024) - 1); - - if ((ps2.option[1] & 1) && !(ps2.option[3] & 0x20) && (bit_mask & 0x01)) { - ps2_mca_log("Set memory at %06X-%06X to internal\n", (mem_size * 1024), (mem_size * 1024) + (remap_size * 1024) - 1); - mem_set_mem_state(mem_size * 1024, remap_size * 1024, MEM_READ_INTERNAL | MEM_WRITE_INTERNAL); - } - - flushmmucache_nopc(); -} - - -static void model_55sx_write(uint16_t port, uint8_t val) -{ - switch (port) - { - case 0x100: - ps2.io_id = val; - break; - case 0x101: - break; - case 0x102: - lpt1_remove(); - serial_remove(ps2.uart); - if (val & 0x04) - { - if (val & 0x08) - serial_setup(ps2.uart, SERIAL1_ADDR, SERIAL1_IRQ); - else - serial_setup(ps2.uart, SERIAL2_ADDR, SERIAL2_IRQ); - } - if (val & 0x10) - { - switch ((val >> 5) & 3) - { - case 0: - lpt1_init(0x3bc); - break; - case 1: - lpt1_init(0x378); - break; - case 2: - lpt1_init(0x278); - break; - } - } - ps2.option[0] = val; - break; - case 0x103: - ps2_mca_log("Write POS1: %02X\n", val); - ps2.option[1] = val; - model_55sx_mem_recalc(); - break; - case 0x104: - ps2.memory_bank[ps2.option[3] & 7] &= ~0xf; - ps2.memory_bank[ps2.option[3] & 7] |= (val & 0xf); - ps2_mca_log("Write memory bank %i: %02X\n", ps2.option[3] & 7, val); - model_55sx_mem_recalc(); - break; - case 0x105: - ps2_mca_log("Write POS3: %02X\n", val); - ps2.option[3] = val; - model_55sx_mem_recalc(); - break; - case 0x106: - ps2.subaddr_lo = val; - break; - case 0x107: - ps2.subaddr_hi = val; - break; - } -} - -static void model_70_type3_write(uint16_t port, uint8_t val) -{ - switch (port) - { - case 0x100: - break; - case 0x101: - break; - case 0x102: - lpt1_remove(); - serial_remove(ps2.uart); - if (val & 0x04) - { - if (val & 0x08) - serial_setup(ps2.uart, SERIAL1_ADDR, SERIAL1_IRQ); - else - serial_setup(ps2.uart, SERIAL2_ADDR, SERIAL2_IRQ); - } - if (val & 0x10) - { - switch ((val >> 5) & 3) - { - case 0: - lpt1_init(0x3bc); - break; - case 1: - lpt1_init(0x378); - break; - case 2: - lpt1_init(0x278); - break; - } - } - ps2.option[0] = val; - break; - case 0x103: - if (ps2.planar_id == 0xfff9) - ps2.option[1] = (ps2.option[1] & 0x0f) | (val & 0xf0); - break; - case 0x104: - if (ps2.planar_id == 0xfff9) - ps2.option[2] = val; - break; - case 0x105: - ps2.option[3] = val; - break; - case 0x106: - ps2.subaddr_lo = val; - break; - case 0x107: - ps2.subaddr_hi = val; - break; - } -} - - -static void model_80_write(uint16_t port, uint8_t val) -{ - switch (port) - { - case 0x100: - break; - case 0x101: - break; - case 0x102: - lpt1_remove(); - serial_remove(ps2.uart); - if (val & 0x04) - { - if (val & 0x08) - serial_setup(ps2.uart, SERIAL1_ADDR, SERIAL1_IRQ); - else - serial_setup(ps2.uart, SERIAL2_ADDR, SERIAL2_IRQ); - } - if (val & 0x10) - { - switch ((val >> 5) & 3) - { - case 0: - lpt1_init(0x3bc); - break; - case 1: - lpt1_init(0x378); - break; - case 2: - lpt1_init(0x278); - break; - } - } - ps2.option[0] = val; - break; - case 0x103: - ps2.option[1] = (ps2.option[1] & 0x0f) | (val & 0xf0); - break; - case 0x104: - ps2.option[2] = val; - break; - case 0x105: - ps2.option[3] = val; - break; - case 0x106: - ps2.subaddr_lo = val; - break; - case 0x107: - ps2.subaddr_hi = val; - break; - } -} - -uint8_t ps2_mca_read(uint16_t port, void *p) -{ - uint8_t temp; - - switch (port) - { - case 0x91: - // fatal("Read 91 setup=%02x adapter=%02x\n", ps2.setup, ps2.adapter_setup); - if (!(ps2.setup & PS2_SETUP_IO)) - temp = 0x00; - else if (!(ps2.setup & PS2_SETUP_VGA)) - temp = 0x00; - else if (ps2.adapter_setup & PS2_ADAPTER_SETUP) - temp = 0x00; - else - temp = !mca_feedb(); - temp |= 0xfe; - break; - case 0x94: - temp = ps2.setup; - break; - case 0x96: - temp = ps2.adapter_setup | 0x70; - break; - case 0x100: - if (!(ps2.setup & PS2_SETUP_IO)) - temp = ps2.planar_read(port); - else if (!(ps2.setup & PS2_SETUP_VGA)) - temp = 0xfd; - else if (ps2.adapter_setup & PS2_ADAPTER_SETUP) - temp = mca_read(port); - else - temp = 0xff; - break; - case 0x101: - if (!(ps2.setup & PS2_SETUP_IO)) - temp = ps2.planar_read(port); - else if (!(ps2.setup & PS2_SETUP_VGA)) - temp = 0xef; - else if (ps2.adapter_setup & PS2_ADAPTER_SETUP) - temp = mca_read(port); - else - temp = 0xff; - break; - case 0x102: - if (!(ps2.setup & PS2_SETUP_IO)) - temp = ps2.planar_read(port); - else if (!(ps2.setup & PS2_SETUP_VGA)) - temp = ps2.pos_vga; - else if (ps2.adapter_setup & PS2_ADAPTER_SETUP) - temp = mca_read(port); - else - temp = 0xff; - break; - case 0x103: - if (!(ps2.setup & PS2_SETUP_IO)) - temp = ps2.planar_read(port); - else if ((ps2.setup & PS2_SETUP_VGA) && (ps2.adapter_setup & PS2_ADAPTER_SETUP)) - temp = mca_read(port); - else - temp = 0xff; - break; - case 0x104: - if (!(ps2.setup & PS2_SETUP_IO)) - temp = ps2.planar_read(port); - else if ((ps2.setup & PS2_SETUP_VGA) && (ps2.adapter_setup & PS2_ADAPTER_SETUP)) - temp = mca_read(port); - else - temp = 0xff; - break; - case 0x105: - if (!(ps2.setup & PS2_SETUP_IO)) - temp = ps2.planar_read(port); - else if ((ps2.setup & PS2_SETUP_VGA) && (ps2.adapter_setup & PS2_ADAPTER_SETUP)) - temp = mca_read(port); - else - temp = 0xff; - break; - case 0x106: - if (!(ps2.setup & PS2_SETUP_IO)) - temp = ps2.planar_read(port); - else if ((ps2.setup & PS2_SETUP_VGA) && (ps2.adapter_setup & PS2_ADAPTER_SETUP)) - temp = mca_read(port); - else - temp = 0xff; - break; - case 0x107: - if (!(ps2.setup & PS2_SETUP_IO)) - temp = ps2.planar_read(port); - else if ((ps2.setup & PS2_SETUP_VGA) && (ps2.adapter_setup & PS2_ADAPTER_SETUP)) - temp = mca_read(port); - else - temp = 0xff; - break; - - default: - temp = 0xff; - break; - } - - ps2_mca_log("ps2_read: port=%04x temp=%02x\n", port, temp); - - return temp; -} - -static void ps2_mca_write(uint16_t port, uint8_t val, void *p) -{ - ps2_mca_log("ps2_write: port=%04x val=%02x %04x:%04x\n", port, val, CS,cpu_state.pc); - - switch (port) - { - case 0x94: - ps2.setup = val; - break; - case 0x96: - if ((val & 0x80) && !(ps2.adapter_setup & 0x80)) - mca_reset(); - ps2.adapter_setup = val; - mca_set_index(val & 7); - break; - case 0x100: - if (!(ps2.setup & PS2_SETUP_IO)) - ps2.planar_write(port, val); - else if ((ps2.setup & PS2_SETUP_VGA) && (ps2.adapter_setup & PS2_ADAPTER_SETUP)) - mca_write(port, val); - break; - case 0x101: - if (!(ps2.setup & PS2_SETUP_IO)) - ps2.planar_write(port, val); - else if ((ps2.setup & PS2_SETUP_VGA) && (ps2.setup & PS2_SETUP_VGA) && (ps2.adapter_setup & PS2_ADAPTER_SETUP)) - mca_write(port, val); - break; - case 0x102: - if (!(ps2.setup & PS2_SETUP_IO)) - ps2.planar_write(port, val); - else if (!(ps2.setup & PS2_SETUP_VGA)) - ps2.pos_vga = val; - else if (ps2.adapter_setup & PS2_ADAPTER_SETUP) - mca_write(port, val); - break; - case 0x103: - if (!(ps2.setup & PS2_SETUP_IO)) - ps2.planar_write(port, val); - else if (ps2.adapter_setup & PS2_ADAPTER_SETUP) - mca_write(port, val); - break; - case 0x104: - if (!(ps2.setup & PS2_SETUP_IO)) - ps2.planar_write(port, val); - else if (ps2.adapter_setup & PS2_ADAPTER_SETUP) - mca_write(port, val); - break; - case 0x105: - if (!(ps2.setup & PS2_SETUP_IO)) - ps2.planar_write(port, val); - else if (ps2.adapter_setup & PS2_ADAPTER_SETUP) - mca_write(port, val); - break; - case 0x106: - if (!(ps2.setup & PS2_SETUP_IO)) - ps2.planar_write(port, val); - else if (ps2.adapter_setup & PS2_ADAPTER_SETUP) - mca_write(port, val); - break; - case 0x107: - if (!(ps2.setup & PS2_SETUP_IO)) - ps2.planar_write(port, val); - else if (ps2.adapter_setup & PS2_ADAPTER_SETUP) - mca_write(port, val); - break; - } -} - -static void ps2_mca_board_common_init() -{ - io_sethandler(0x0091, 0x0001, ps2_mca_read, NULL, NULL, ps2_mca_write, NULL, NULL, NULL); - io_sethandler(0x0094, 0x0001, ps2_mca_read, NULL, NULL, ps2_mca_write, NULL, NULL, NULL); - io_sethandler(0x0096, 0x0001, ps2_mca_read, NULL, NULL, ps2_mca_write, NULL, NULL, NULL); - io_sethandler(0x0100, 0x0008, ps2_mca_read, NULL, NULL, ps2_mca_write, NULL, NULL, NULL); - - device_add(&port_6x_ps2_device); - device_add(&port_92_device); - - ps2.setup = 0xff; - - lpt1_init(0x3bc); -} - -static uint8_t ps2_mem_expansion_read(int port, void *p) -{ - return ps2.mem_pos_regs[port & 7]; -} - -static void ps2_mem_expansion_write(int port, uint8_t val, void *p) -{ - if (port < 0x102 || port == 0x104) - return; - - ps2.mem_pos_regs[port & 7] = val; - - if (ps2.mem_pos_regs[2] & 1) - mem_mapping_enable(&ps2.expansion_mapping); - else - mem_mapping_disable(&ps2.expansion_mapping); -} - -static uint8_t ps2_mem_expansion_feedb(void *p) -{ - return (ps2.mem_pos_regs[2] & 1); -} - -static void ps2_mca_mem_fffc_init(int start_mb) -{ - uint32_t planar_size, expansion_start; - - planar_size = (start_mb - 1) << 20; - expansion_start = start_mb << 20; - - mem_mapping_set_addr(&ram_high_mapping, 0x100000, planar_size); - - ps2.mem_pos_regs[0] = 0xff; - ps2.mem_pos_regs[1] = 0xfc; - - switch ((mem_size / 1024) - start_mb) - { - case 1: - ps2.mem_pos_regs[4] = 0xfc; /* 11 11 11 00 = 0 0 0 1 */ - break; - case 2: - ps2.mem_pos_regs[4] = 0xfe; /* 11 11 11 10 = 0 0 0 2 */ - break; - case 3: - ps2.mem_pos_regs[4] = 0xf2; /* 11 11 00 10 = 0 0 1 2 */ - break; - case 4: - ps2.mem_pos_regs[4] = 0xfa; /* 11 11 10 10 = 0 0 2 2 */ - break; - case 5: - ps2.mem_pos_regs[4] = 0xca; /* 11 00 10 10 = 0 1 2 2 */ - break; - case 6: - ps2.mem_pos_regs[4] = 0xea; /* 11 10 10 10 = 0 2 2 2 */ - break; - case 7: - ps2.mem_pos_regs[4] = 0x2a; /* 00 10 10 10 = 1 2 2 2 */ - break; - case 8: - ps2.mem_pos_regs[4] = 0xaa; /* 10 10 10 10 = 2 2 2 2 */ - break; - } - - mca_add(ps2_mem_expansion_read, ps2_mem_expansion_write, ps2_mem_expansion_feedb, NULL, NULL); - mem_mapping_add(&ps2.expansion_mapping, - expansion_start, - (mem_size - (start_mb << 10)) << 10, - mem_read_ram, - mem_read_ramw, - mem_read_raml, - mem_write_ram, - mem_write_ramw, - mem_write_raml, - &ram[expansion_start], - MEM_MAPPING_INTERNAL, - NULL); - mem_mapping_disable(&ps2.expansion_mapping); -} - -static void ps2_mca_mem_d071_init(int start_mb) -{ - uint32_t planar_size, expansion_start; - - planar_size = (start_mb - 1) << 20; - expansion_start = start_mb << 20; - - mem_mapping_set_addr(&ram_high_mapping, 0x100000, planar_size); - - ps2.mem_pos_regs[0] = 0xd0; - ps2.mem_pos_regs[1] = 0x71; - ps2.mem_pos_regs[4] = (mem_size / 1024) - start_mb; - - mca_add(ps2_mem_expansion_read, ps2_mem_expansion_write, ps2_mem_expansion_feedb, NULL, NULL); - mem_mapping_add(&ps2.expansion_mapping, - expansion_start, - (mem_size - (start_mb << 10)) << 10, - mem_read_ram, - mem_read_ramw, - mem_read_raml, - mem_write_ram, - mem_write_ramw, - mem_write_raml, - &ram[expansion_start], - MEM_MAPPING_INTERNAL, - NULL); - mem_mapping_disable(&ps2.expansion_mapping); -} - - -static void ps2_mca_board_model_50_init() -{ - ps2_mca_board_common_init(); - - mem_remap_top(384); - mca_init(4); - device_add(&keyboard_ps2_mca_2_device); - - ps2.planar_read = model_50_read; - ps2.planar_write = model_50_write; - - if (mem_size > 2048) - { - /* Only 2 MB supported on planar, create a memory expansion card for the rest */ - ps2_mca_mem_fffc_init(2); - } - - if (gfxcard == VID_INTERNAL) - device_add(&ps1vga_mca_device); -} - -static void ps2_mca_board_model_55sx_init() -{ - ps2_mca_board_common_init(); - - ps2.option[1] = 0x00; - ps2.option[2] = 0x00; - ps2.option[3] = 0x10; - - memset(ps2.memory_bank, 0xf0, 8); - switch (mem_size/1024) - { - case 1: - ps2.memory_bank[0] = 0x61; - break; - case 2: - ps2.memory_bank[0] = 0x51; - break; - case 3: - ps2.memory_bank[0] = 0x51; - ps2.memory_bank[1] = 0x61; - break; - case 4: - ps2.memory_bank[0] = 0x51; - ps2.memory_bank[1] = 0x51; - break; - case 5: - ps2.memory_bank[0] = 0x01; - ps2.memory_bank[1] = 0x61; - break; - case 6: - ps2.memory_bank[0] = 0x01; - ps2.memory_bank[1] = 0x51; - break; - case 7: /*Not supported*/ - ps2.memory_bank[0] = 0x01; - ps2.memory_bank[1] = 0x51; - break; - case 8: - ps2.memory_bank[0] = 0x01; - ps2.memory_bank[1] = 0x01; - break; - } - - mca_init(4); - device_add(&keyboard_ps2_mca_device); - - ps2.planar_read = model_55sx_read; - ps2.planar_write = model_55sx_write; - - if (gfxcard == VID_INTERNAL) - device_add(&ps1vga_mca_device); - - model_55sx_mem_recalc(); -} - -static void mem_encoding_update(void) -{ - mem_mapping_disable(&ps2.split_mapping); - - if (ps2.split_size > 0) - mem_set_mem_state(ps2.split_addr, ps2.split_size << 10, MEM_READ_EXTANY | MEM_WRITE_EXTANY); - if (((mem_size << 10) - (1 << 20)) > 0) - mem_set_mem_state(1 << 20, (mem_size << 10) - (1 << 20), MEM_READ_INTERNAL | MEM_WRITE_INTERNAL); - - ps2.split_addr = ((uint32_t) (ps2.mem_regs[0] & 0xf)) << 20; - if (!ps2.split_addr) - ps2.split_addr = 1 << 20; - - if (ps2.mem_regs[1] & 2) { - mem_set_mem_state(0xe0000, 0x20000, MEM_READ_EXTANY | MEM_WRITE_INTERNAL); - ps2_mca_log("PS/2 Model 80-111: ROM space enabled\n"); - } else { - mem_set_mem_state(0xe0000, 0x20000, MEM_READ_INTERNAL | MEM_WRITE_DISABLED); - ps2_mca_log("PS/2 Model 80-111: ROM space disabled\n"); - } - - if (ps2.mem_regs[1] & 4) { - mem_mapping_set_addr(&ram_low_mapping, 0x00000, 0x80000); - ps2_mca_log("PS/2 Model 80-111: 00080000- 0009FFFF disabled\n"); - } else { - mem_mapping_set_addr(&ram_low_mapping, 0x00000, 0xa0000); - ps2_mca_log("PS/2 Model 80-111: 00080000- 0009FFFF enabled\n"); - } - - if (!(ps2.mem_regs[1] & 8)) - { - if (ps2.mem_regs[1] & 4) { - ps2.split_size = 384; - ps2.split_phys = 0x80000; - } else { - ps2.split_size = 256; - ps2.split_phys = 0xa0000; - } - - mem_set_mem_state(ps2.split_addr, ps2.split_size << 10, MEM_READ_INTERNAL | MEM_WRITE_INTERNAL); - mem_mapping_set_exec(&ps2.split_mapping, &ram[ps2.split_phys]); - mem_mapping_set_addr(&ps2.split_mapping, ps2.split_addr, ps2.split_size << 10); - - ps2_mca_log("PS/2 Model 80-111: Split memory block enabled at %08X\n", ps2.split_addr); - } else { - ps2.split_size = 0; - ps2_mca_log("PS/2 Model 80-111: Split memory block disabled\n"); - } - - flushmmucache_nopc(); -} - -static uint8_t mem_encoding_read(uint16_t addr, void *p) -{ - switch (addr) - { - case 0xe0: - return ps2.mem_regs[0]; - case 0xe1: - return ps2.mem_regs[1]; - } - return 0xff; -} -static void mem_encoding_write(uint16_t addr, uint8_t val, void *p) -{ - switch (addr) - { - case 0xe0: - ps2.mem_regs[0] = val; - break; - case 0xe1: - ps2.mem_regs[1] = val; - break; - } - mem_encoding_update(); -} - -static uint8_t mem_encoding_read_cached(uint16_t addr, void *p) -{ - switch (addr) - { - case 0xe0: - return ps2.mem_regs[0]; - case 0xe1: - return ps2.mem_regs[1]; - case 0xe2: - return ps2.mem_regs[2]; - } - return 0xff; -} - -static void mem_encoding_write_cached(uint16_t addr, uint8_t val, void *p) -{ - uint8_t old; - - switch (addr) - { - case 0xe0: - ps2.mem_regs[0] = val; - break; - case 0xe1: - ps2.mem_regs[1] = val; - break; - case 0xe2: - old = ps2.mem_regs[2]; - ps2.mem_regs[2] = (ps2.mem_regs[2] & 0x80) | (val & ~0x88); - if (val & 2) - { - ps2_mca_log("Clear latch - %i\n", ps2.pending_cache_miss); - if (ps2.pending_cache_miss) - ps2.mem_regs[2] |= 0x80; - else - ps2.mem_regs[2] &= ~0x80; - ps2.pending_cache_miss = 0; - } - - if ((val & 0x21) == 0x20 && (old & 0x21) != 0x20) - ps2.pending_cache_miss = 1; - if ((val & 0x21) == 0x01 && (old & 0x21) != 0x01) - ps2_cache_clean(); -#if 1 - // FIXME: Look into this!!! - if (val & 0x01) - ram_mid_mapping.flags |= MEM_MAPPING_ROM_WS; - else - ram_mid_mapping.flags &= ~MEM_MAPPING_ROM_WS; + int state; +#ifdef ENABLE_PS2_MCA_LOG + int enabled_mem = 0; #endif - break; + int base = 0; + int remap_size = (ps2.option[3] & 0x10) ? 384 : 256; + int bit_mask = 0x00; + int max_rows = 4; + int bank_to_rows[16] = { 4, 2, 1, 0, 0, 2, 1, 0, 0, 0, 0, 0, 0, 2, 1, 0 }; + + ps2_mca_log("%02X %02X\n", ps2.option[1], ps2.option[3]); + + mem_remap_top(remap_size); + mem_set_mem_state(0x00000000, (mem_size + 384) * 1024, MEM_READ_EXTERNAL | MEM_WRITE_EXTERNAL); + mem_set_mem_state(0x000e0000, 0x00020000, MEM_READ_EXTANY | MEM_WRITE_DISABLED); + + for (uint8_t i = 0; i < 2; i++) { + max_rows = bank_to_rows[(ps2.memory_bank[i] >> 4) & 0x0f]; + + if (max_rows == 0) + continue; + + for (int j = 0; j < max_rows; j++) { + if (ps2.memory_bank[i] & (1 << j)) { + ps2_mca_log("Set memory at %06X-%06X to internal\n", (base * 1024), (base * 1024) + (((base > 0) ? 1024 : 640) * 1024) - 1); + mem_set_mem_state(base * 1024, ((base > 0) ? 1024 : 640) * 1024, MEM_READ_INTERNAL | MEM_WRITE_INTERNAL); +#ifdef ENABLE_PS2_MCA_LOG + enabled_mem += 1024; +#endif + bit_mask |= (1 << (j + (i << 2))); + } + base += 1024; } - ps2_mca_log("mem_encoding_write: addr=%02x val=%02x %04x:%04x %02x %02x\n", addr, val, CS,cpu_state.pc, ps2.mem_regs[1],ps2.mem_regs[2]); - mem_encoding_update(); - if ((ps2.mem_regs[1] & 0x10) && (ps2.mem_regs[2] & 0x21) == 0x20) - { - mem_mapping_disable(&ram_low_mapping); - mem_mapping_enable(&ps2.cache_mapping); - flushmmucache(); - } - else - { - mem_mapping_disable(&ps2.cache_mapping); - mem_mapping_enable(&ram_low_mapping); - flushmmucache(); + } + +#ifdef ENABLE_PS2_MCA_LOG + ps2_mca_log("Enabled memory: %i kB (%02X)\n", enabled_mem, bit_mask); +#endif + + if (ps2.option[3] & 0x10) { + /* Enable ROM. */ + ps2_mca_log("Enable ROM\n"); + state = MEM_READ_EXTANY; + } else { + /* Disable ROM. */ + if ((ps2.option[1] & 1) && !(ps2.option[3] & 0x20) && (bit_mask & 0x01)) { + /* Disable RAM between 640 kB and 1 MB. */ + ps2_mca_log("Disable ROM, enable RAM\n"); + state = MEM_READ_INTERNAL; + } else { + ps2_mca_log("Disable ROM, disable RAM\n"); + state = MEM_READ_DISABLED; } + } + + /* Write always disabled. */ + state |= MEM_WRITE_DISABLED; + + mem_set_mem_state(0xe0000, 0x20000, state); + +#if 0 + if (!(ps2.option[3] & 0x08)) { + ps2_mca_log("Memory not yet configured\n"); + return; + } +#endif + + ps2_mca_log("Enable shadow mapping at %06X-%06X\n", (mem_size * 1024), (mem_size * 1024) + (remap_size * 1024) - 1); + + if ((ps2.option[1] & 1) && !(ps2.option[3] & 0x20) && (bit_mask & 0x01)) { + ps2_mca_log("Set memory at %06X-%06X to internal\n", (mem_size * 1024), (mem_size * 1024) + (remap_size * 1024) - 1); + mem_set_mem_state(mem_size * 1024, remap_size * 1024, MEM_READ_INTERNAL | MEM_WRITE_INTERNAL); + } + + flushmmucache_nopc(); } -static void ps2_mca_board_model_70_type34_init(int is_type4, int slots) -{ - ps2_mca_board_common_init(); +static void +model_55sx_write(uint16_t port, uint8_t val) +{ + switch (port) { + case 0x102: + lpt1_remove(); + serial_remove(ps2.uart); + if (val & 0x04) { + if (val & 0x08) + serial_setup(ps2.uart, COM1_ADDR, COM1_IRQ); + else + serial_setup(ps2.uart, COM2_ADDR, COM2_IRQ); + } + if (val & 0x10) { + switch ((val >> 5) & 3) { + case 0: + lpt1_init(LPT_MDA_ADDR); + break; + case 1: + lpt1_init(LPT1_ADDR); + break; + case 2: + lpt1_init(LPT2_ADDR); + break; - ps2.split_addr = mem_size * 1024; - mca_init(slots); - device_add(&keyboard_ps2_mca_device); + default: + break; + } + } + ps2.option[0] = val; + break; + case 0x103: + ps2_mca_log("Write POS1: %02X\n", val); + ps2.option[1] = val; + model_55sx_mem_recalc(); + break; + case 0x104: + ps2.memory_bank[ps2.option[3] & 7] &= ~0xf; + ps2.memory_bank[ps2.option[3] & 7] |= (val & 0xf); + ps2_mca_log("Write memory bank %i: %02X\n", ps2.option[3] & 7, val); + model_55sx_mem_recalc(); + break; + case 0x105: + ps2_mca_log("Write POS3: %02X\n", val); + ps2.option[3] = val; + model_55sx_mem_recalc(); + break; + case 0x106: + ps2.subaddr_lo = val; + break; + case 0x107: + ps2.subaddr_hi = val; + break; - ps2.planar_read = model_70_type3_read; - ps2.planar_write = model_70_type3_write; - - device_add(&ps2_nvr_device); - - io_sethandler(0x00e0, 0x0003, mem_encoding_read_cached, NULL, NULL, mem_encoding_write_cached, NULL, NULL, NULL); + default: + break; + } +} - ps2.mem_regs[1] = 2; +static void +model_70_type3_write(uint16_t port, uint8_t val) +{ + switch (port) { + case 0x102: + lpt1_remove(); + serial_remove(ps2.uart); + if (val & 0x04) { + if (val & 0x08) + serial_setup(ps2.uart, COM1_ADDR, COM1_IRQ); + else + serial_setup(ps2.uart, COM2_ADDR, COM2_IRQ); + } + if (val & 0x10) { + switch ((val >> 5) & 3) { + case 0: + lpt1_init(LPT_MDA_ADDR); + break; + case 1: + lpt1_init(LPT1_ADDR); + break; + case 2: + lpt1_init(LPT2_ADDR); + break; - switch (mem_size/1024) - { - case 2: - ps2.option[1] = 0xa6; - ps2.option[2] = 0x01; - break; - case 4: - ps2.option[1] = 0xaa; - ps2.option[2] = 0x01; - break; - case 6: - ps2.option[1] = 0xca; - ps2.option[2] = 0x01; - break; - case 8: - default: - ps2.option[1] = 0xca; - ps2.option[2] = 0x02; - break; + default: + break; + } + } + ps2.option[0] = val; + break; + case 0x103: + if (ps2.planar_id == 0xfff9) + ps2.option[1] = (ps2.option[1] & 0x0f) | (val & 0xf0); + break; + case 0x104: + if (ps2.planar_id == 0xfff9) + ps2.option[2] = val; + break; + case 0x105: + ps2.option[3] = val; + break; + case 0x106: + ps2.subaddr_lo = val; + break; + case 0x107: + ps2.subaddr_hi = val; + break; + + default: + break; + } +} + +static void +model_80_write(uint16_t port, uint8_t val) +{ + switch (port) { + case 0x102: + lpt1_remove(); + serial_remove(ps2.uart); + if (val & 0x04) { + if (val & 0x08) + serial_setup(ps2.uart, COM1_ADDR, COM1_IRQ); + else + serial_setup(ps2.uart, COM2_ADDR, COM2_IRQ); + } + if (val & 0x10) { + switch ((val >> 5) & 3) { + case 0: + lpt1_init(LPT_MDA_ADDR); + break; + case 1: + lpt1_init(LPT1_ADDR); + break; + case 2: + lpt1_init(LPT2_ADDR); + break; + + default: + break; + } + } + ps2.option[0] = val; + break; + case 0x103: + ps2.option[1] = (ps2.option[1] & 0x0f) | (val & 0xf0); + break; + case 0x104: + ps2.option[2] = val; + break; + case 0x105: + ps2.option[3] = val; + break; + case 0x106: + ps2.subaddr_lo = val; + break; + case 0x107: + ps2.subaddr_hi = val; + break; + + default: + break; + } +} + +uint8_t +ps2_mca_read(uint16_t port, UNUSED(void *priv)) +{ + uint8_t temp; + + switch (port) { + case 0x91: +#if 0 + fatal("Read 91 setup=%02x adapter=%02x\n", ps2.setup, ps2.adapter_setup); +#endif + if (!(ps2.setup & PS2_SETUP_IO)) + temp = 0x00; + else if (!(ps2.setup & PS2_SETUP_VGA)) + temp = 0x00; + else if (ps2.adapter_setup & PS2_ADAPTER_SETUP) + temp = 0x00; + else + temp = !mca_feedb(); + temp |= 0xfe; + break; + case 0x94: + temp = ps2.setup; + break; + case 0x96: + temp = ps2.adapter_setup | 0x70; + break; + case 0x100: + if (!(ps2.setup & PS2_SETUP_IO)) + temp = ps2.planar_read(port); + else if (!(ps2.setup & PS2_SETUP_VGA)) + temp = 0xfd; + else if (ps2.adapter_setup & PS2_ADAPTER_SETUP) + temp = mca_read(port); + else + temp = 0xff; + break; + case 0x101: + if (!(ps2.setup & PS2_SETUP_IO)) + temp = ps2.planar_read(port); + else if (!(ps2.setup & PS2_SETUP_VGA)) + temp = 0xef; + else if (ps2.adapter_setup & PS2_ADAPTER_SETUP) + temp = mca_read(port); + else + temp = 0xff; + break; + case 0x102: + if (!(ps2.setup & PS2_SETUP_IO)) + temp = ps2.planar_read(port); + else if (!(ps2.setup & PS2_SETUP_VGA)) + temp = ps2.pos_vga; + else if (ps2.adapter_setup & PS2_ADAPTER_SETUP) + temp = mca_read(port); + else + temp = 0xff; + break; + case 0x103: + if (!(ps2.setup & PS2_SETUP_IO)) + temp = ps2.planar_read(port); + else if ((ps2.setup & PS2_SETUP_VGA) && (ps2.adapter_setup & PS2_ADAPTER_SETUP)) + temp = mca_read(port); + else + temp = 0xff; + break; + case 0x104: + if (!(ps2.setup & PS2_SETUP_IO)) + temp = ps2.planar_read(port); + else if ((ps2.setup & PS2_SETUP_VGA) && (ps2.adapter_setup & PS2_ADAPTER_SETUP)) + temp = mca_read(port); + else + temp = 0xff; + break; + case 0x105: + if (!(ps2.setup & PS2_SETUP_IO)) + temp = ps2.planar_read(port); + else if ((ps2.setup & PS2_SETUP_VGA) && (ps2.adapter_setup & PS2_ADAPTER_SETUP)) + temp = mca_read(port); + else + temp = 0xff; + break; + case 0x106: + if (!(ps2.setup & PS2_SETUP_IO)) + temp = ps2.planar_read(port); + else if ((ps2.setup & PS2_SETUP_VGA) && (ps2.adapter_setup & PS2_ADAPTER_SETUP)) + temp = mca_read(port); + else + temp = 0xff; + break; + case 0x107: + if (!(ps2.setup & PS2_SETUP_IO)) + temp = ps2.planar_read(port); + else if ((ps2.setup & PS2_SETUP_VGA) && (ps2.adapter_setup & PS2_ADAPTER_SETUP)) + temp = mca_read(port); + else + temp = 0xff; + break; + + default: + temp = 0xff; + break; + } + + ps2_mca_log("ps2_read: port=%04x temp=%02x\n", port, temp); + + return temp; +} + +static void +ps2_mca_write(uint16_t port, uint8_t val, UNUSED(void *priv)) +{ + ps2_mca_log("ps2_write: port=%04x val=%02x %04x:%04x\n", port, val, CS, cpu_state.pc); + + switch (port) { + case 0x94: + ps2.setup = val; + break; + case 0x96: + if ((val & 0x80) && !(ps2.adapter_setup & 0x80)) + mca_reset(); + ps2.adapter_setup = val; + mca_set_index(val & 7); + break; + case 0x100: + if (!(ps2.setup & PS2_SETUP_IO)) + ps2.planar_write(port, val); + else if ((ps2.setup & PS2_SETUP_VGA) && (ps2.adapter_setup & PS2_ADAPTER_SETUP)) + mca_write(port, val); + break; + case 0x101: + if (!(ps2.setup & PS2_SETUP_IO)) + ps2.planar_write(port, val); + else if ((ps2.setup & PS2_SETUP_VGA) && (ps2.adapter_setup & PS2_ADAPTER_SETUP)) + mca_write(port, val); + break; + case 0x102: + if (!(ps2.setup & PS2_SETUP_IO)) + ps2.planar_write(port, val); + else if (!(ps2.setup & PS2_SETUP_VGA)) + ps2.pos_vga = val; + else if (ps2.adapter_setup & PS2_ADAPTER_SETUP) + mca_write(port, val); + break; + case 0x103: + if (!(ps2.setup & PS2_SETUP_IO)) + ps2.planar_write(port, val); + else if (ps2.adapter_setup & PS2_ADAPTER_SETUP) + mca_write(port, val); + break; + case 0x104: + if (!(ps2.setup & PS2_SETUP_IO)) + ps2.planar_write(port, val); + else if (ps2.adapter_setup & PS2_ADAPTER_SETUP) + mca_write(port, val); + break; + case 0x105: + if (!(ps2.setup & PS2_SETUP_IO)) + ps2.planar_write(port, val); + else if (ps2.adapter_setup & PS2_ADAPTER_SETUP) + mca_write(port, val); + break; + case 0x106: + if (!(ps2.setup & PS2_SETUP_IO)) + ps2.planar_write(port, val); + else if (ps2.adapter_setup & PS2_ADAPTER_SETUP) + mca_write(port, val); + break; + case 0x107: + if (!(ps2.setup & PS2_SETUP_IO)) + ps2.planar_write(port, val); + else if (ps2.adapter_setup & PS2_ADAPTER_SETUP) + mca_write(port, val); + break; + + default: + break; + } +} + +static void +ps2_mca_board_common_init(void) +{ + io_sethandler(0x0091, 0x0001, ps2_mca_read, NULL, NULL, ps2_mca_write, NULL, NULL, NULL); + io_sethandler(0x0094, 0x0001, ps2_mca_read, NULL, NULL, ps2_mca_write, NULL, NULL, NULL); + io_sethandler(0x0096, 0x0001, ps2_mca_read, NULL, NULL, ps2_mca_write, NULL, NULL, NULL); + io_sethandler(0x0100, 0x0008, ps2_mca_read, NULL, NULL, ps2_mca_write, NULL, NULL, NULL); + + device_add(&port_6x_ps2_device); + device_add(&port_92_device); + + ps2.setup = 0xff; + + lpt1_init(LPT_MDA_ADDR); +} + +static uint8_t +ps2_mem_expansion_read(int port, UNUSED(void *priv)) +{ + return ps2.mem_pos_regs[port & 7]; +} + +static void +ps2_mem_expansion_write(int port, uint8_t val, UNUSED(void *priv)) +{ + if (port < 0x102 || port == 0x104) + return; + + ps2.mem_pos_regs[port & 7] = val; + + if (ps2.mem_pos_regs[2] & 1) + mem_mapping_enable(&ps2.expansion_mapping); + else + mem_mapping_disable(&ps2.expansion_mapping); +} + +static uint8_t +ps2_mem_expansion_feedb(UNUSED(void *priv)) +{ + return (ps2.mem_pos_regs[2] & 1); +} + +static void +ps2_mca_mem_fffc_init(int start_mb) +{ + uint32_t planar_size; + uint32_t expansion_start; + + planar_size = (start_mb - 1) << 20; + expansion_start = start_mb << 20; + + mem_mapping_set_addr(&ram_high_mapping, 0x100000, planar_size); + + ps2.mem_pos_regs[0] = 0xff; + ps2.mem_pos_regs[1] = 0xfc; + + switch ((mem_size / 1024) - start_mb) { + case 1: + ps2.mem_pos_regs[4] = 0xfc; /* 11 11 11 00 = 0 0 0 1 */ + break; + case 2: + ps2.mem_pos_regs[4] = 0xfe; /* 11 11 11 10 = 0 0 0 2 */ + break; + case 3: + ps2.mem_pos_regs[4] = 0xf2; /* 11 11 00 10 = 0 0 1 2 */ + break; + case 4: + ps2.mem_pos_regs[4] = 0xfa; /* 11 11 10 10 = 0 0 2 2 */ + break; + case 5: + ps2.mem_pos_regs[4] = 0xca; /* 11 00 10 10 = 0 1 2 2 */ + break; + case 6: + ps2.mem_pos_regs[4] = 0xea; /* 11 10 10 10 = 0 2 2 2 */ + break; + case 7: + ps2.mem_pos_regs[4] = 0x2a; /* 00 10 10 10 = 1 2 2 2 */ + break; + case 8: + ps2.mem_pos_regs[4] = 0xaa; /* 10 10 10 10 = 2 2 2 2 */ + break; + + default: + break; + } + + mca_add(ps2_mem_expansion_read, ps2_mem_expansion_write, ps2_mem_expansion_feedb, NULL, NULL); + mem_mapping_add(&ps2.expansion_mapping, + expansion_start, + (mem_size - (start_mb << 10)) << 10, + mem_read_ram, + mem_read_ramw, + mem_read_raml, + mem_write_ram, + mem_write_ramw, + mem_write_raml, + &ram[expansion_start], + MEM_MAPPING_INTERNAL, + NULL); + mem_mapping_disable(&ps2.expansion_mapping); +} + +static void +ps2_mca_mem_d071_init(int start_mb) +{ + uint32_t planar_size; + uint32_t expansion_start; + + planar_size = (start_mb - 1) << 20; + expansion_start = start_mb << 20; + + mem_mapping_set_addr(&ram_high_mapping, 0x100000, planar_size); + + ps2.mem_pos_regs[0] = 0xd0; + ps2.mem_pos_regs[1] = 0x71; + ps2.mem_pos_regs[4] = (mem_size / 1024) - start_mb; + + mca_add(ps2_mem_expansion_read, ps2_mem_expansion_write, ps2_mem_expansion_feedb, NULL, NULL); + mem_mapping_add(&ps2.expansion_mapping, + expansion_start, + (mem_size - (start_mb << 10)) << 10, + mem_read_ram, + mem_read_ramw, + mem_read_raml, + mem_write_ram, + mem_write_ramw, + mem_write_raml, + &ram[expansion_start], + MEM_MAPPING_INTERNAL, + NULL); + mem_mapping_disable(&ps2.expansion_mapping); +} + +static void +ps2_mca_board_model_50_init(void) +{ + ps2_mca_board_common_init(); + + mem_remap_top(384); + mca_init(4); + device_add(&keyboard_ps2_mca_2_device); + + ps2.planar_read = model_50_read; + ps2.planar_write = model_50_write; + + if (mem_size > 2048) { + /* Only 2 MB supported on planar, create a memory expansion card for the rest */ + ps2_mca_mem_fffc_init(2); + } + + if (gfxcard[0] == VID_INTERNAL) + device_add(&ps1vga_mca_device); +} + +static void +ps2_mca_board_model_60_init(void) +{ + ps2_mca_board_common_init(); + + mem_remap_top(384); + mca_init(8); + device_add(&keyboard_ps2_mca_2_device); + + ps2.planar_read = model_50_read; + ps2.planar_write = model_50_write; + + if (mem_size > 2048) { + /* Only 2 MB supported on planar, create a memory expansion card for the rest */ + ps2_mca_mem_fffc_init(2); + } + + device_add(&ps2_nvr_55ls_device); + + if (gfxcard[0] == VID_INTERNAL) + device_add(&ps1vga_mca_device); +} + +static void +ps2_mca_board_model_55sx_init(int has_sec_nvram, int slots) +{ + ps2_mca_board_common_init(); + + ps2.option[1] = 0x00; + ps2.option[2] = 0x00; + ps2.option[3] = 0x10; + + memset(ps2.memory_bank, 0xf0, 8); + switch (mem_size / 1024) { + case 1: + ps2.memory_bank[0] = 0x61; + break; + case 2: + ps2.memory_bank[0] = 0x51; + break; + case 3: + ps2.memory_bank[0] = 0x51; + ps2.memory_bank[1] = 0x61; + break; + case 4: + ps2.memory_bank[0] = 0x51; + ps2.memory_bank[1] = 0x51; + break; + case 5: + ps2.memory_bank[0] = 0x01; + ps2.memory_bank[1] = 0x61; + break; + case 6: + case 7: /*Not supported*/ + ps2.memory_bank[0] = 0x01; + ps2.memory_bank[1] = 0x51; + break; + case 8: + ps2.memory_bank[0] = 0x01; + ps2.memory_bank[1] = 0x01; + break; + + default: + break; + } + + mca_init(slots); + device_add(&keyboard_ps2_device); + + if (has_sec_nvram) + device_add(&ps2_nvr_55ls_device); + + ps2.planar_read = model_55sx_read; + ps2.planar_write = model_55sx_write; + + if (gfxcard[0] == VID_INTERNAL) + device_add(&ps1vga_mca_device); + + model_55sx_mem_recalc(); +} + +static void +mem_encoding_update(void) +{ + mem_mapping_disable(&ps2.split_mapping); + + if (ps2.split_size > 0) + mem_set_mem_state(ps2.split_addr, ps2.split_size << 10, MEM_READ_EXTANY | MEM_WRITE_EXTANY); + if (((mem_size << 10) - (1 << 20)) > 0) + mem_set_mem_state(1 << 20, (mem_size << 10) - (1 << 20), MEM_READ_INTERNAL | MEM_WRITE_INTERNAL); + + ps2.split_addr = ((uint32_t) (ps2.mem_regs[0] & 0xf)) << 20; + if (!ps2.split_addr) + ps2.split_addr = 1 << 20; + + if (ps2.mem_regs[1] & 2) { + mem_set_mem_state(0xe0000, 0x20000, MEM_READ_EXTANY | MEM_WRITE_INTERNAL); + ps2_mca_log("PS/2 Model 80-111: ROM space enabled\n"); + } else { + mem_set_mem_state(0xe0000, 0x20000, MEM_READ_INTERNAL | MEM_WRITE_DISABLED); + ps2_mca_log("PS/2 Model 80-111: ROM space disabled\n"); + } + + if (ps2.mem_regs[1] & 4) { + mem_mapping_set_addr(&ram_low_mapping, 0x00000, 0x80000); + ps2_mca_log("PS/2 Model 80-111: 00080000- 0009FFFF disabled\n"); + } else { + mem_mapping_set_addr(&ram_low_mapping, 0x00000, 0xa0000); + ps2_mca_log("PS/2 Model 80-111: 00080000- 0009FFFF enabled\n"); + } + + if (!(ps2.mem_regs[1] & 8)) { + if (ps2.mem_regs[1] & 4) { + ps2.split_size = 384; + ps2.split_phys = 0x80000; + } else { + ps2.split_size = 256; + ps2.split_phys = 0xa0000; } - - if (is_type4) - ps2.option[2] |= 0x04; /*486 CPU*/ - mem_mapping_add(&ps2.split_mapping, - (mem_size+256) * 1024, - 256*1024, + mem_set_mem_state(ps2.split_addr, ps2.split_size << 10, MEM_READ_INTERNAL | MEM_WRITE_INTERNAL); + mem_mapping_set_exec(&ps2.split_mapping, &ram[ps2.split_phys]); + mem_mapping_set_addr(&ps2.split_mapping, ps2.split_addr, ps2.split_size << 10); + + ps2_mca_log("PS/2 Model 80-111: Split memory block enabled at %08X\n", ps2.split_addr); + } else { + ps2.split_size = 0; + ps2_mca_log("PS/2 Model 80-111: Split memory block disabled\n"); + } + + flushmmucache_nopc(); +} + +static uint8_t +mem_encoding_read(uint16_t addr, UNUSED(void *priv)) +{ + switch (addr) { + case 0xe0: + return ps2.mem_regs[0]; + case 0xe1: + return ps2.mem_regs[1]; + + default: + break; + } + return 0xff; +} +static void +mem_encoding_write(uint16_t addr, uint8_t val, UNUSED(void *priv)) +{ + switch (addr) { + case 0xe0: + ps2.mem_regs[0] = val; + break; + case 0xe1: + ps2.mem_regs[1] = val; + break; + + default: + break; + } + mem_encoding_update(); +} + +static uint8_t +mem_encoding_read_cached(uint16_t addr, UNUSED(void *priv)) +{ + switch (addr) { + case 0xe0: + return ps2.mem_regs[0]; + case 0xe1: + return ps2.mem_regs[1]; + case 0xe2: + return ps2.mem_regs[2]; + + default: + break; + } + return 0xff; +} + +static void +mem_encoding_write_cached(uint16_t addr, uint8_t val, UNUSED(void *priv)) +{ + uint8_t old; + + switch (addr) { + case 0xe0: + ps2.mem_regs[0] = val; + break; + case 0xe1: + ps2.mem_regs[1] = val; + break; + case 0xe2: + old = ps2.mem_regs[2]; + ps2.mem_regs[2] = (ps2.mem_regs[2] & 0x80) | (val & ~0x88); + if (val & 2) { + ps2_mca_log("Clear latch - %i\n", ps2.pending_cache_miss); + if (ps2.pending_cache_miss) + ps2.mem_regs[2] |= 0x80; + else + ps2.mem_regs[2] &= ~0x80; + ps2.pending_cache_miss = 0; + } + + if ((val & 0x21) == 0x20 && (old & 0x21) != 0x20) + ps2.pending_cache_miss = 1; + if ((val & 0x21) == 0x01 && (old & 0x21) != 0x01) + ps2_cache_clean(); +#if 1 + // FIXME: Look into this!!! + if (val & 0x01) + ram_mid_mapping.flags |= MEM_MAPPING_ROM_WS; + else + ram_mid_mapping.flags &= ~MEM_MAPPING_ROM_WS; +#endif + break; + + default: + break; + } + ps2_mca_log("mem_encoding_write: addr=%02x val=%02x %04x:%04x %02x %02x\n", addr, val, CS, cpu_state.pc, ps2.mem_regs[1], ps2.mem_regs[2]); + mem_encoding_update(); + if ((ps2.mem_regs[1] & 0x10) && (ps2.mem_regs[2] & 0x21) == 0x20) { + mem_mapping_disable(&ram_low_mapping); + mem_mapping_enable(&ps2.cache_mapping); + flushmmucache(); + } else { + mem_mapping_disable(&ps2.cache_mapping); + mem_mapping_enable(&ram_low_mapping); + flushmmucache(); + } +} + +static void +ps2_mca_board_model_70_type34_init(int is_type4, int slots) +{ + ps2_mca_board_common_init(); + + ps2.split_addr = mem_size * 1024; + mca_init(slots); + device_add(&keyboard_ps2_device); + + ps2.planar_read = model_70_type3_read; + ps2.planar_write = model_70_type3_write; + + device_add(&ps2_nvr_device); + + io_sethandler(0x00e0, 0x0003, mem_encoding_read_cached, NULL, NULL, mem_encoding_write_cached, NULL, NULL, NULL); + + ps2.mem_regs[1] = 2; + + switch (mem_size / 1024) { + case 2: + ps2.option[1] = 0xa6; + ps2.option[2] = 0x01; + break; + case 4: + ps2.option[1] = 0xaa; + ps2.option[2] = 0x01; + break; + case 6: + ps2.option[1] = 0xca; + ps2.option[2] = 0x01; + break; + case 8: + default: + ps2.option[1] = 0xca; + ps2.option[2] = 0x02; + break; + } + + if (is_type4) + ps2.option[2] |= 0x04; /*486 CPU*/ + + mem_mapping_add(&ps2.split_mapping, + (mem_size + 256) * 1024, + 256 * 1024, ps2_read_split_ram, ps2_read_split_ramw, ps2_read_split_raml, @@ -1218,11 +1274,11 @@ static void ps2_mca_board_model_70_type34_init(int is_type4, int slots) &ram[0xa0000], MEM_MAPPING_INTERNAL, NULL); - mem_mapping_disable(&ps2.split_mapping); + mem_mapping_disable(&ps2.split_mapping); - mem_mapping_add(&ps2.cache_mapping, - 0, - (is_type4) ? (8 * 1024) : (64 * 1024), + mem_mapping_add(&ps2.cache_mapping, + 0, + is_type4 ? (8 * 1024) : (64 * 1024), ps2_read_cache_ram, ps2_read_cache_ramw, ps2_read_cache_raml, @@ -1232,84 +1288,82 @@ static void ps2_mca_board_model_70_type34_init(int is_type4, int slots) ps2_cache, MEM_MAPPING_INTERNAL, NULL); - mem_mapping_disable(&ps2.cache_mapping); - - if (ps2.planar_id == 0xfff9) { - if (mem_size > 4096) - { - /* Only 4 MB supported on planar, create a memory expansion card for the rest */ - if (mem_size > 12288) { - ps2_mca_mem_d071_init(4); - } else { - ps2_mca_mem_fffc_init(4); - } - } - } else { - if (mem_size > 8192) - { - /* Only 8 MB supported on planar, create a memory expansion card for the rest */ - if (mem_size > 16384) - ps2_mca_mem_d071_init(8); - else { - ps2_mca_mem_fffc_init(8); - } - } - } + mem_mapping_disable(&ps2.cache_mapping); - if (gfxcard == VID_INTERNAL) - device_add(&ps1vga_mca_device); + if (ps2.planar_id == 0xfff9) { + if (mem_size > 4096) { + /* Only 4 MB supported on planar, create a memory expansion card for the rest */ + if (mem_size > 12288) { + ps2_mca_mem_d071_init(4); + } else { + ps2_mca_mem_fffc_init(4); + } + } + } else { + if (mem_size > 8192) { + /* Only 8 MB supported on planar, create a memory expansion card for the rest */ + if (mem_size > 16384) + ps2_mca_mem_d071_init(8); + else { + ps2_mca_mem_fffc_init(8); + } + } + } + + if (gfxcard[0] == VID_INTERNAL) + device_add(&ps1vga_mca_device); } -static void ps2_mca_board_model_80_type2_init(int is486) -{ - ps2_mca_board_common_init(); +static void +ps2_mca_board_model_80_type2_init(void) +{ + ps2_mca_board_common_init(); - ps2.split_addr = mem_size * 1024; - mca_init(8); - device_add(&keyboard_ps2_mca_device); - - ps2.planar_read = model_80_read; - ps2.planar_write = model_80_write; - - device_add(&ps2_nvr_device); - - io_sethandler(0x00e0, 0x0002, mem_encoding_read, NULL, NULL, mem_encoding_write, NULL, NULL, NULL); - - ps2.mem_regs[1] = 2; + ps2.split_addr = mem_size * 1024; + mca_init(8); + device_add(&keyboard_ps2_device); - /* Note by Kotori: I rewrote this because the original code was using - Model 80 Type 1-style 1 MB memory card settings, which are *NOT* - supported by Model 80 Type 2. */ - switch (mem_size/1024) - { - case 1: - ps2.option[1] = 0x0e; /* 11 10 = 0 2 */ - ps2.mem_regs[1] = 0xd2; /* 01 = 1 (first) */ - ps2.mem_regs[0] = 0xf0; /* 11 = invalid */ - break; - case 2: - ps2.option[1] = 0x0e; /* 11 10 = 0 2 */ - ps2.mem_regs[1] = 0xc2; /* 00 = 2 */ - ps2.mem_regs[0] = 0xf0; /* 11 = invalid */ - break; - case 3: - ps2.option[1] = 0x0a; /* 10 10 = 2 2 */ - ps2.mem_regs[1] = 0xc2; /* 00 = 2 */ - ps2.mem_regs[0] = 0xd0; /* 01 = 1 (first) */ - break; - case 4: - default: - ps2.option[1] = 0x0a; /* 10 10 = 2 2 */ - ps2.mem_regs[1] = 0xc2; /* 00 = 2 */ - ps2.mem_regs[0] = 0xc0; /* 00 = 2 */ - break; - } + ps2.planar_read = model_80_read; + ps2.planar_write = model_80_write; - ps2.mem_regs[0] |= ((mem_size/1024) & 0x0f); + device_add(&ps2_nvr_device); - mem_mapping_add(&ps2.split_mapping, - (mem_size+256) * 1024, - 256*1024, + io_sethandler(0x00e0, 0x0002, mem_encoding_read, NULL, NULL, mem_encoding_write, NULL, NULL, NULL); + + ps2.mem_regs[1] = 2; + + /* Note by Kotori: I rewrote this because the original code was using + Model 80 Type 1-style 1 MB memory card settings, which are *NOT* + supported by Model 80 Type 2. */ + switch (mem_size / 1024) { + case 1: + ps2.option[1] = 0x0e; /* 11 10 = 0 2 */ + ps2.mem_regs[1] = 0xd2; /* 01 = 1 (first) */ + ps2.mem_regs[0] = 0xf0; /* 11 = invalid */ + break; + case 2: + ps2.option[1] = 0x0e; /* 11 10 = 0 2 */ + ps2.mem_regs[1] = 0xc2; /* 00 = 2 */ + ps2.mem_regs[0] = 0xf0; /* 11 = invalid */ + break; + case 3: + ps2.option[1] = 0x0a; /* 10 10 = 2 2 */ + ps2.mem_regs[1] = 0xc2; /* 00 = 2 */ + ps2.mem_regs[0] = 0xd0; /* 01 = 1 (first) */ + break; + case 4: + default: + ps2.option[1] = 0x0a; /* 10 10 = 2 2 */ + ps2.mem_regs[1] = 0xc2; /* 00 = 2 */ + ps2.mem_regs[0] = 0xc0; /* 00 = 2 */ + break; + } + + ps2.mem_regs[0] |= ((mem_size / 1024) & 0x0f); + + mem_mapping_add(&ps2.split_mapping, + (mem_size + 256) * 1024, + 256 * 1024, ps2_read_split_ram, ps2_read_split_ramw, ps2_read_split_raml, @@ -1319,147 +1373,206 @@ static void ps2_mca_board_model_80_type2_init(int is486) &ram[0xa0000], MEM_MAPPING_INTERNAL, NULL); - mem_mapping_disable(&ps2.split_mapping); - - if ((mem_size > 4096) && !is486) - { - /* Only 4 MB supported on planar, create a memory expansion card for the rest */ - if (mem_size > 12288) - ps2_mca_mem_d071_init(4); - else { - ps2_mca_mem_fffc_init(4); - } + mem_mapping_disable(&ps2.split_mapping); + + if (mem_size > 4096) { + /* Only 4 MB supported on planar, create a memory expansion card for the rest */ + if (mem_size > 12288) + ps2_mca_mem_d071_init(4); + else { + ps2_mca_mem_fffc_init(4); } + } - if (gfxcard == VID_INTERNAL) - device_add(&ps1vga_mca_device); + if (gfxcard[0] == VID_INTERNAL) + device_add(&ps1vga_mca_device); - ps2.split_size = 0; + ps2.split_size = 0; } - static void machine_ps2_common_init(const machine_t *model) { - machine_common_init(model); + machine_common_init(model); - if (fdc_type == FDC_INTERNAL) - device_add(&fdc_at_device); + if (fdc_type == FDC_INTERNAL) + device_add(&fdc_at_device); - dma16_init(); - ps2_dma_init(); - device_add(&ps_nvr_device); - pic2_init(); + dma16_init(); + ps2_dma_init(); + device_add(&ps_no_nmi_nvr_device); + pic2_init(); - pit_ps2_init(); + int pit_type = ((pit_mode == -1 && is486) || pit_mode == 1) ? PIT_8254_FAST : PIT_8254; + pit_ps2_init(pit_type); - nmi_mask = 0x80; + nmi_mask = 0x80; - ps2.uart = device_add_inst(&ns16550_device, 1); + ps2.uart = device_add_inst(&ns16550_device, 1); } - int machine_ps2_model_50_init(const machine_t *model) { - int ret; + int ret; - ret = bios_load_interleaved("roms/machines/ibmps2_m50/90x7420.zm13", - "roms/machines/ibmps2_m50/90x7429.zm18", - 0x000f0000, 131072, 0); - ret &= bios_load_aux_interleaved("roms/machines/ibmps2_m50/90x7423.zm14", - "roms/machines/ibmps2_m50/90x7426.zm16", - 0x000e0000, 65536, 0); + ret = bios_load_interleaved("roms/machines/ibmps2_m50/90x7420.zm13", + "roms/machines/ibmps2_m50/90x7429.zm18", + 0x000f0000, 131072, 0); + ret &= bios_load_aux_interleaved("roms/machines/ibmps2_m50/90x7423.zm14", + "roms/machines/ibmps2_m50/90x7426.zm16", + 0x000e0000, 65536, 0); - if (bios_only || !ret) - return ret; + if (bios_only || !ret) + return ret; - machine_ps2_common_init(model); + machine_ps2_common_init(model); - ps2_mca_board_model_50_init(); + ps2.planar_id = 0xfbff; + ps2_mca_board_model_50_init(); - return ret; + return ret; } +int +machine_ps2_model_60_init(const machine_t *model) +{ + int ret; + + ret = bios_load_interleaved("roms/machines/ibmps2_m50/90x7420.zm13", + "roms/machines/ibmps2_m50/90x7429.zm18", + 0x000f0000, 131072, 0); + ret &= bios_load_aux_interleaved("roms/machines/ibmps2_m50/90x7423.zm14", + "roms/machines/ibmps2_m50/90x7426.zm16", + 0x000e0000, 65536, 0); + + if (bios_only || !ret) + return ret; + + machine_ps2_common_init(model); + + ps2.planar_id = 0xf7ff; + ps2_mca_board_model_60_init(); + + return ret; +} int machine_ps2_model_55sx_init(const machine_t *model) { - int ret; + int ret; - ret = bios_load_interleaved("roms/machines/ibmps2_m55sx/33f8146.zm41", - "roms/machines/ibmps2_m55sx/33f8145.zm40", - 0x000e0000, 131072, 0); + ret = bios_load_interleaved("roms/machines/ibmps2_m55sx/33f8146.zm41", + "roms/machines/ibmps2_m55sx/33f8145.zm40", + 0x000e0000, 131072, 0); - if (bios_only || !ret) - return ret; + if (bios_only || !ret) + return ret; - machine_ps2_common_init(model); + machine_ps2_common_init(model); - ps2_mca_board_model_55sx_init(); + ps2.planar_id = 0xfbff; + ps2_mca_board_model_55sx_init(0, 4); - return ret; + return ret; } +int +machine_ps2_model_65sx_init(const machine_t *model) +{ + int ret; + + ret = bios_load_interleaved("roms/machines/ibmps2_m65sx/64F3608.BIN", + "roms/machines/ibmps2_m65sx/64F3611.BIN", + 0x000e0000, 131072, 0); + + if (bios_only || !ret) + return ret; + + machine_ps2_common_init(model); + + ps2.planar_id = 0xe3ff; + ps2_mca_board_model_55sx_init(1, 8); + + return ret; +} int machine_ps2_model_70_type3_init(const machine_t *model) { - int ret; + int ret; - ret = bios_load_interleaved("roms/machines/ibmps2_m70_type3/70-a_even.bin", - "roms/machines/ibmps2_m70_type3/70-a_odd.bin", - 0x000e0000, 131072, 0); + ret = bios_load_interleaved("roms/machines/ibmps2_m70_type3/70-a_even.bin", + "roms/machines/ibmps2_m70_type3/70-a_odd.bin", + 0x000e0000, 131072, 0); - if (bios_only || !ret) - return ret; + if (bios_only || !ret) + return ret; - machine_ps2_common_init(model); - - ps2.planar_id = 0xf9ff; + machine_ps2_common_init(model); - ps2_mca_board_model_70_type34_init(0, 4); + ps2.planar_id = 0xf9ff; + ps2_mca_board_model_70_type34_init(0, 4); - return ret; + return ret; } - int machine_ps2_model_80_init(const machine_t *model) { - int ret; + int ret; - ret = bios_load_interleaved("roms/machines/ibmps2_m80/15f6637.bin", - "roms/machines/ibmps2_m80/15f6639.bin", - 0x000e0000, 131072, 0); + ret = bios_load_interleaved("roms/machines/ibmps2_m80/15f6637.bin", + "roms/machines/ibmps2_m80/15f6639.bin", + 0x000e0000, 131072, 0); - if (bios_only || !ret) - return ret; + if (bios_only || !ret) + return ret; - machine_ps2_common_init(model); + machine_ps2_common_init(model); - ps2_mca_board_model_80_type2_init(0); + ps2.planar_id = 0xfdff; + ps2_mca_board_model_80_type2_init(); - return ret; + return ret; } int machine_ps2_model_80_axx_init(const machine_t *model) { - int ret; + int ret; - ret = bios_load_interleaved("roms/machines/ibmps2_m80/64f4356.bin", - "roms/machines/ibmps2_m80/64f4355.bin", - 0x000e0000, 131072, 0); + ret = bios_load_interleaved("roms/machines/ibmps2_m80/64f4356.bin", + "roms/machines/ibmps2_m80/64f4355.bin", + 0x000e0000, 131072, 0); - if (bios_only || !ret) - return ret; + if (bios_only || !ret) + return ret; - machine_ps2_common_init(model); + machine_ps2_common_init(model); - ps2.planar_id = 0xfff9; + ps2.planar_id = 0xfff9; + ps2_mca_board_model_70_type34_init(0, 8); - ps2_mca_board_model_70_type34_init(0, 8); + return ret; +} - return ret; -} \ No newline at end of file +int +machine_ps2_model_70_type4_init(const machine_t *model) +{ + int ret; + + ret = bios_load_interleaved("roms/machines/ibmps2_m70_type4/64F3126.BIN", + "roms/machines/ibmps2_m70_type4/64F3125.BIN", + 0x000e0000, 131072, 0); + + if (bios_only || !ret) + return ret; + + machine_ps2_common_init(model); + + ps2.planar_id = 0xf9ff; + ps2_mca_board_model_70_type34_init(1, 4); + + return ret; +} diff --git a/src/machine/m_tandy.c b/src/machine/m_tandy.c index 1eaf93163..1d4c3303f 100644 --- a/src/machine/m_tandy.c +++ b/src/machine/m_tandy.c @@ -1,20 +1,20 @@ /* - * 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. + * 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. + * This file is part of the 86Box distribution. * - * Emulation of Tandy models 1000, 1000HX and 1000SL2. + * Emulation of Tandy models 1000, 1000HX and 1000SL2. * * * - * Authors: Sarah Walker, - * Miran Grca, + * Authors: Sarah Walker, + * Miran Grca, * - * Copyright 2008-2019 Sarah Walker. - * Copyright 2016-2019 Miran Grca. + * Copyright 2008-2019 Sarah Walker. + * Copyright 2016-2019 Miran Grca. */ #include #include @@ -43,21 +43,19 @@ #include <86box/video.h> #include <86box/vid_cga_comp.h> #include <86box/machine.h> - +#include <86box/plat_unused.h> enum { TANDY_RGB = 0, TANDY_COMPOSITE }; - enum { TYPE_TANDY = 0, TYPE_TANDY1000HX, TYPE_TANDY1000SL2 }; - enum { EEPROM_IDLE = 0, EEPROM_GET_OPERATION, @@ -65,75 +63,81 @@ enum { EEPROM_WRITE }; +typedef struct t1kvid_t { + mem_mapping_t mapping; + mem_mapping_t vram_mapping; -typedef struct { - mem_mapping_t mapping; - mem_mapping_t vram_mapping; + uint8_t crtc[32]; + int crtcreg; - uint8_t crtc[32]; - int crtcreg; + int array_index; + uint8_t array[256]; + int memctrl; + uint8_t mode; + uint8_t col; + uint8_t stat; - int array_index; - uint8_t array[256]; - int memctrl; - uint8_t mode, col; - uint8_t stat; + uint8_t *vram; + uint8_t *b8000; + uint32_t b8000_mask; + uint32_t b8000_limit; + uint8_t planar_ctrl; - uint8_t *vram, *b8000; - uint32_t b8000_mask; - uint32_t b8000_limit; - uint8_t planar_ctrl; + int linepos; + int displine; + int sc; + int vc; + int dispon; + int con; + int coff; + int cursoron; + int blink; + int fullchange; + int vsynctime; + int vadj; + uint16_t ma; + uint16_t maback; - int linepos, - displine; - int sc, vc; - int dispon; - int con, coff, - cursoron, - blink; - int vsynctime; - int vadj; - uint16_t ma, maback; + uint64_t dispontime; + uint64_t dispofftime; + pc_timer_t timer; + int firstline; + int lastline; - uint64_t dispontime, - dispofftime; - pc_timer_t timer; - int firstline, - lastline; - - int composite; + int composite; } t1kvid_t; -typedef struct { - char *path; +typedef struct t1keep_t { + char *path; - int state; - int count; - int addr; - int clk; - uint16_t data; - uint16_t store[64]; + int state; + int count; + int addr; + int clk; + uint16_t data; + uint16_t store[64]; } t1keep_t; -typedef struct { - mem_mapping_t ram_mapping; - mem_mapping_t rom_mapping; /* SL2 */ +typedef struct tandy_t { + mem_mapping_t ram_mapping; + mem_mapping_t rom_mapping; /* SL2 */ - uint8_t *rom; /* SL2 */ - uint8_t ram_bank; - uint8_t rom_bank; /* SL2 */ - int rom_offset; /* SL2 */ + uint8_t *rom; /* SL2 */ + uint8_t ram_bank; + uint8_t rom_bank; /* SL2 */ + int rom_offset; /* SL2 */ - uint32_t base; - int is_sl2; + uint32_t base; + uint32_t mask; + int is_sl2; - t1kvid_t *vid; + t1kvid_t *vid; } tandy_t; -static video_timings_t timing_dram = {VIDEO_BUS, 0,0,0, 0,0,0}; /*No additional waitstates*/ - +static video_timings_t timing_dram = { VIDEO_BUS, 0, 0, 0, 0, 0, 0 }; /*No additional waitstates*/ static const scancode scancode_tandy[512] = { + // clang-format off { {0}, {0} }, { {0x01, 0}, {0x81, 0} }, { {0x02, 0}, {0x82, 0} }, { {0x03, 0}, {0x83, 0} }, { {0x04, 0}, {0x84, 0} }, { {0x05, 0}, {0x85, 0} }, @@ -177,219 +181,220 @@ static const scancode scancode_tandy[512] = { { {0x50, 0}, {0xd0, 0} }, { {0x51, 0}, {0xd1, 0} }, { {0x52, 0}, {0xd2, 0} }, { {0x56, 0}, {0xd6, 0} }, { {0}, {0} }, { {0}, {0} }, - { {0}, {0} }, { {0}, {0} }, /*054*/ + { {0}, {0} }, { {0}, {0} }, /*054*/ { {0}, {0} }, { {0}, {0} }, - { {0}, {0} }, { {0}, {0} }, /*058*/ + { {0}, {0} }, { {0}, {0} }, /*058*/ { {0}, {0} }, { {0}, {0} }, - { {0}, {0} }, { {0}, {0} }, /*05c*/ + { {0}, {0} }, { {0}, {0} }, /*05c*/ { {0}, {0} }, { {0}, {0} }, - { {0}, {0} }, { {0}, {0} }, /*060*/ + { {0}, {0} }, { {0}, {0} }, /*060*/ { {0}, {0} }, { {0}, {0} }, - { {0}, {0} }, { {0}, {0} }, /*064*/ + { {0}, {0} }, { {0}, {0} }, /*064*/ { {0}, {0} }, { {0}, {0} }, - { {0}, {0} }, { {0}, {0} }, /*068*/ + { {0}, {0} }, { {0}, {0} }, /*068*/ { {0}, {0} }, { {0}, {0} }, - { {0}, {0} }, { {0}, {0} }, /*06c*/ + { {0}, {0} }, { {0}, {0} }, /*06c*/ { {0}, {0} }, { {0}, {0} }, - { {0}, {0} }, { {0}, {0} }, /*070*/ + { {0}, {0} }, { {0}, {0} }, /*070*/ { {0}, {0} }, { {0}, {0} }, - { {0}, {0} }, { {0}, {0} }, /*074*/ + { {0}, {0} }, { {0}, {0} }, /*074*/ { {0}, {0} }, { {0}, {0} }, - { {0}, {0} }, { {0}, {0} }, /*078*/ + { {0}, {0} }, { {0}, {0} }, /*078*/ { {0}, {0} }, { {0}, {0} }, - { {0}, {0} }, { {0}, {0} }, /*07c*/ + { {0}, {0} }, { {0}, {0} }, /*07c*/ { {0}, {0} }, { {0}, {0} }, - { {0}, {0} }, { {0}, {0} }, /*080*/ + { {0}, {0} }, { {0}, {0} }, /*080*/ { {0}, {0} }, { {0}, {0} }, - { {0}, {0} }, { {0}, {0} }, /*084*/ + { {0}, {0} }, { {0}, {0} }, /*084*/ { {0}, {0} }, { {0}, {0} }, - { {0}, {0} }, { {0}, {0} }, /*088*/ + { {0}, {0} }, { {0}, {0} }, /*088*/ { {0}, {0} }, { {0}, {0} }, - { {0}, {0} }, { {0}, {0} }, /*08c*/ + { {0}, {0} }, { {0}, {0} }, /*08c*/ { {0}, {0} }, { {0}, {0} }, - { {0}, {0} }, { {0}, {0} }, /*090*/ + { {0}, {0} }, { {0}, {0} }, /*090*/ { {0}, {0} }, { {0}, {0} }, - { {0}, {0} }, { {0}, {0} }, /*094*/ + { {0}, {0} }, { {0}, {0} }, /*094*/ { {0}, {0} }, { {0}, {0} }, - { {0}, {0} }, { {0}, {0} }, /*098*/ + { {0}, {0} }, { {0}, {0} }, /*098*/ { {0}, {0} }, { {0}, {0} }, - { {0}, {0} }, { {0}, {0} }, /*09c*/ + { {0}, {0} }, { {0}, {0} }, /*09c*/ { {0}, {0} }, { {0}, {0} }, - { {0}, {0} }, { {0}, {0} }, /*0a0*/ + { {0}, {0} }, { {0}, {0} }, /*0a0*/ { {0}, {0} }, { {0}, {0} }, - { {0}, {0} }, { {0}, {0} }, /*0a4*/ + { {0}, {0} }, { {0}, {0} }, /*0a4*/ { {0}, {0} }, { {0}, {0} }, - { {0}, {0} }, { {0}, {0} }, /*0a8*/ + { {0}, {0} }, { {0}, {0} }, /*0a8*/ { {0}, {0} }, { {0}, {0} }, - { {0}, {0} }, { {0}, {0} }, /*0ac*/ + { {0}, {0} }, { {0}, {0} }, /*0ac*/ { {0}, {0} }, { {0}, {0} }, - { {0}, {0} }, { {0}, {0} }, /*0b0*/ + { {0}, {0} }, { {0}, {0} }, /*0b0*/ { {0}, {0} }, { {0}, {0} }, - { {0}, {0} }, { {0}, {0} }, /*0b4*/ + { {0}, {0} }, { {0}, {0} }, /*0b4*/ { {0}, {0} }, { {0}, {0} }, - { {0}, {0} }, { {0}, {0} }, /*0b8*/ + { {0}, {0} }, { {0}, {0} }, /*0b8*/ { {0}, {0} }, { {0}, {0} }, - { {0}, {0} }, { {0}, {0} }, /*0bc*/ + { {0}, {0} }, { {0}, {0} }, /*0bc*/ { {0}, {0} }, { {0}, {0} }, - { {0}, {0} }, { {0}, {0} }, /*0c0*/ + { {0}, {0} }, { {0}, {0} }, /*0c0*/ { {0}, {0} }, { {0}, {0} }, - { {0}, {0} }, { {0}, {0} }, /*0c4*/ + { {0}, {0} }, { {0}, {0} }, /*0c4*/ { {0}, {0} }, { {0}, {0} }, - { {0}, {0} }, { {0}, {0} }, /*0c8*/ + { {0}, {0} }, { {0}, {0} }, /*0c8*/ { {0}, {0} }, { {0}, {0} }, - { {0}, {0} }, { {0}, {0} }, /*0cc*/ + { {0}, {0} }, { {0}, {0} }, /*0cc*/ { {0}, {0} }, { {0}, {0} }, - { {0}, {0} }, { {0}, {0} }, /*0d0*/ + { {0}, {0} }, { {0}, {0} }, /*0d0*/ { {0}, {0} }, { {0}, {0} }, - { {0}, {0} }, { {0}, {0} }, /*0d4*/ + { {0}, {0} }, { {0}, {0} }, /*0d4*/ { {0}, {0} }, { {0}, {0} }, - { {0}, {0} }, { {0}, {0} }, /*0d8*/ + { {0}, {0} }, { {0}, {0} }, /*0d8*/ { {0}, {0} }, { {0}, {0} }, - { {0}, {0} }, { {0}, {0} }, /*0dc*/ + { {0}, {0} }, { {0}, {0} }, /*0dc*/ { {0}, {0} }, { {0}, {0} }, - { {0}, {0} }, { {0}, {0} }, /*0e0*/ + { {0}, {0} }, { {0}, {0} }, /*0e0*/ { {0}, {0} }, { {0}, {0} }, - { {0}, {0} }, { {0}, {0} }, /*0e4*/ + { {0}, {0} }, { {0}, {0} }, /*0e4*/ { {0}, {0} }, { {0}, {0} }, - { {0}, {0} }, { {0}, {0} }, /*0e8*/ + { {0}, {0} }, { {0}, {0} }, /*0e8*/ { {0}, {0} }, { {0}, {0} }, - { {0}, {0} }, { {0}, {0} }, /*0ec*/ + { {0}, {0} }, { {0}, {0} }, /*0ec*/ { {0}, {0} }, { {0}, {0} }, - { {0}, {0} }, { {0}, {0} }, /*0f0*/ + { {0}, {0} }, { {0}, {0} }, /*0f0*/ { {0}, {0} }, { {0}, {0} }, - { {0}, {0} }, { {0}, {0} }, /*0f4*/ + { {0}, {0} }, { {0}, {0} }, /*0f4*/ { {0}, {0} }, { {0}, {0} }, - { {0}, {0} }, { {0}, {0} }, /*0f8*/ + { {0}, {0} }, { {0}, {0} }, /*0f8*/ { {0}, {0} }, { {0}, {0} }, - { {0}, {0} }, { {0}, {0} }, /*0fc*/ + { {0}, {0} }, { {0}, {0} }, /*0fc*/ { {0}, {0} }, { {0}, {0} }, - { {0}, {0} }, { {0}, {0} }, /*100*/ + { {0}, {0} }, { {0}, {0} }, /*100*/ { {0}, {0} }, { {0}, {0} }, - { {0}, {0} }, { {0}, {0} }, /*104*/ + { {0}, {0} }, { {0}, {0} }, /*104*/ { {0}, {0} }, { {0}, {0} }, - { {0}, {0} }, { {0}, {0} }, /*108*/ + { {0}, {0} }, { {0}, {0} }, /*108*/ { {0}, {0} }, { {0}, {0} }, - { {0}, {0} }, { {0}, {0} }, /*10c*/ + { {0}, {0} }, { {0}, {0} }, /*10c*/ { {0}, {0} }, { {0}, {0} }, - { {0}, {0} }, { {0}, {0} }, /*110*/ + { {0}, {0} }, { {0}, {0} }, /*110*/ { {0}, {0} }, { {0}, {0} }, - { {0}, {0} }, { {0}, {0} }, /*114*/ + { {0}, {0} }, { {0}, {0} }, /*114*/ { {0}, {0} }, { {0}, {0} }, - { {0}, {0} }, { {0}, {0} }, /*118*/ + { {0}, {0} }, { {0}, {0} }, /*118*/ { {0x57, 0}, {0xd7, 0} }, { {0}, {0} }, - { {0}, {0} }, { {0}, {0} }, /*11c*/ + { {0}, {0} }, { {0}, {0} }, /*11c*/ { {0}, {0} }, { {0}, {0} }, - { {0}, {0} }, { {0}, {0} }, /*120*/ + { {0}, {0} }, { {0}, {0} }, /*120*/ { {0}, {0} }, { {0}, {0} }, - { {0}, {0} }, { {0}, {0} }, /*124*/ + { {0}, {0} }, { {0}, {0} }, /*124*/ { {0}, {0} }, { {0}, {0} }, - { {0}, {0} }, { {0}, {0} }, /*128*/ + { {0}, {0} }, { {0}, {0} }, /*128*/ { {0}, {0} }, { {0}, {0} }, - { {0}, {0} }, { {0}, {0} }, /*12c*/ + { {0}, {0} }, { {0}, {0} }, /*12c*/ { {0}, {0} }, { {0}, {0} }, - { {0}, {0} }, { {0}, {0} }, /*130*/ + { {0}, {0} }, { {0}, {0} }, /*130*/ { {0}, {0} }, { {0x35, 0}, {0xb5, 0} }, - { {0}, {0} }, { {0x37, 0}, {0xb7, 0} }, /*134*/ + { {0}, {0} }, { {0x37, 0}, {0xb7, 0} }, /*134*/ { {0x38, 0}, {0xb8, 0} }, { {0}, {0} }, - { {0}, {0} }, { {0}, {0} }, /*138*/ + { {0}, {0} }, { {0}, {0} }, /*138*/ { {0}, {0} }, { {0}, {0} }, - { {0}, {0} }, { {0}, {0} }, /*13c*/ + { {0}, {0} }, { {0}, {0} }, /*13c*/ { {0}, {0} }, { {0}, {0} }, - { {0}, {0} }, { {0}, {0} }, /*140*/ + { {0}, {0} }, { {0}, {0} }, /*140*/ { {0}, {0} }, { {0}, {0} }, - { {0x46, 0}, {0xc6, 0} }, { {0x47, 0}, {0xc7, 0} }, /*144*/ + { {0x46, 0}, {0xc6, 0} }, { {0x47, 0}, {0xc7, 0} }, /*144*/ { {0x29, 0}, {0xa9, 0} }, { {0x49, 0}, {0xc9, 0} }, - { {0}, {0} }, { {0x2b, 0}, {0xab, 0} }, /*148*/ + { {0}, {0} }, { {0x2b, 0}, {0xab, 0} }, /*148*/ { {0}, {0} }, { {0x4e, 0}, {0xce, 0} }, - { {0}, {0} }, { {0x4f, 0}, {0xcf, 0} }, /*14c*/ + { {0}, {0} }, { {0x4f, 0}, {0xcf, 0} }, /*14c*/ { {0x4a, 0}, {0xca, 0} }, { {0x51, 0}, {0xd1, 0} }, - { {0x52, 0}, {0xd2, 0} }, { {0x53, 0}, {0xd3, 0} }, /*150*/ + { {0x52, 0}, {0xd2, 0} }, { {0x53, 0}, {0xd3, 0} }, /*150*/ { {0}, {0} }, { {0}, {0} }, - { {0}, {0} }, { {0}, {0} }, /*154*/ + { {0}, {0} }, { {0}, {0} }, /*154*/ { {0}, {0} }, { {0}, {0} }, - { {0}, {0} }, { {0}, {0} }, /*158*/ + { {0}, {0} }, { {0}, {0} }, /*158*/ { {0}, {0} }, { {0}, {0} }, - { {0}, {0} }, { {0}, {0} }, /*15c*/ + { {0}, {0} }, { {0}, {0} }, /*15c*/ { {0}, {0} }, { {0}, {0} }, - { {0}, {0} }, { {0}, {0} }, /*160*/ + { {0}, {0} }, { {0}, {0} }, /*160*/ { {0}, {0} }, { {0}, {0} }, - { {0}, {0} }, { {0}, {0} }, /*164*/ + { {0}, {0} }, { {0}, {0} }, /*164*/ { {0}, {0} }, { {0}, {0} }, - { {0}, {0} }, { {0}, {0} }, /*168*/ + { {0}, {0} }, { {0}, {0} }, /*168*/ { {0}, {0} }, { {0}, {0} }, - { {0}, {0} }, { {0}, {0} }, /*16c*/ + { {0}, {0} }, { {0}, {0} }, /*16c*/ { {0}, {0} }, { {0}, {0} }, - { {0}, {0} }, { {0}, {0} }, /*170*/ + { {0}, {0} }, { {0}, {0} }, /*170*/ { {0}, {0} }, { {0}, {0} }, - { {0}, {0} }, { {0}, {0} }, /*174*/ + { {0}, {0} }, { {0}, {0} }, /*174*/ { {0}, {0} }, { {0}, {0} }, - { {0}, {0} }, { {0}, {0} }, /*148*/ + { {0}, {0} }, { {0}, {0} }, /*148*/ { {0}, {0} }, { {0}, {0} }, - { {0}, {0} }, { {0}, {0} }, /*17c*/ + { {0}, {0} }, { {0}, {0} }, /*17c*/ { {0}, {0} }, { {0}, {0} }, - { {0}, {0} }, { {0}, {0} }, /*180*/ + { {0}, {0} }, { {0}, {0} }, /*180*/ { {0}, {0} }, { {0}, {0} }, - { {0}, {0} }, { {0}, {0} }, /*184*/ + { {0}, {0} }, { {0}, {0} }, /*184*/ { {0}, {0} }, { {0}, {0} }, - { {0}, {0} }, { {0}, {0} }, /*88*/ + { {0}, {0} }, { {0}, {0} }, /*188*/ { {0}, {0} }, { {0}, {0} }, - { {0}, {0} }, { {0}, {0} }, /*18c*/ + { {0}, {0} }, { {0}, {0} }, /*18c*/ { {0}, {0} }, { {0}, {0} }, - { {0}, {0} }, { {0}, {0} }, /*190*/ + { {0}, {0} }, { {0}, {0} }, /*190*/ { {0}, {0} }, { {0}, {0} }, - { {0}, {0} }, { {0}, {0} }, /*194*/ + { {0}, {0} }, { {0}, {0} }, /*194*/ { {0}, {0} }, { {0}, {0} }, - { {0}, {0} }, { {0}, {0} }, /*198*/ + { {0}, {0} }, { {0}, {0} }, /*198*/ { {0}, {0} }, { {0}, {0} }, - { {0}, {0} }, { {0}, {0} }, /*19c*/ + { {0}, {0} }, { {0}, {0} }, /*19c*/ { {0}, {0} }, { {0}, {0} }, - { {0}, {0} }, { {0}, {0} }, /*1a0*/ + { {0}, {0} }, { {0}, {0} }, /*1a0*/ { {0}, {0} }, { {0}, {0} }, - { {0}, {0} }, { {0}, {0} }, /*1a4*/ + { {0}, {0} }, { {0}, {0} }, /*1a4*/ { {0}, {0} }, { {0}, {0} }, - { {0}, {0} }, { {0}, {0} }, /*1a8*/ + { {0}, {0} }, { {0}, {0} }, /*1a8*/ { {0}, {0} }, { {0}, {0} }, - { {0}, {0} }, { {0}, {0} }, /*1ac*/ + { {0}, {0} }, { {0}, {0} }, /*1ac*/ { {0}, {0} }, { {0}, {0} }, - { {0}, {0} }, { {0}, {0} }, /*1b0*/ + { {0}, {0} }, { {0}, {0} }, /*1b0*/ { {0}, {0} }, { {0}, {0} }, - { {0}, {0} }, { {0}, {0} }, /*1b4*/ + { {0}, {0} }, { {0}, {0} }, /*1b4*/ { {0}, {0} }, { {0}, {0} }, - { {0}, {0} }, { {0}, {0} }, /*1b8*/ + { {0}, {0} }, { {0}, {0} }, /*1b8*/ { {0}, {0} }, { {0}, {0} }, - { {0}, {0} }, { {0}, {0} }, /*1bc*/ + { {0}, {0} }, { {0}, {0} }, /*1bc*/ { {0}, {0} }, { {0}, {0} }, - { {0}, {0} }, { {0}, {0} }, /*1c0*/ + { {0}, {0} }, { {0}, {0} }, /*1c0*/ { {0}, {0} }, { {0}, {0} }, - { {0}, {0} }, { {0}, {0} }, /*1c4*/ + { {0}, {0} }, { {0}, {0} }, /*1c4*/ { {0}, {0} }, { {0}, {0} }, - { {0}, {0} }, { {0}, {0} }, /*1c8*/ + { {0}, {0} }, { {0}, {0} }, /*1c8*/ { {0}, {0} }, { {0}, {0} }, - { {0}, {0} }, { {0}, {0} }, /*1cc*/ + { {0}, {0} }, { {0}, {0} }, /*1cc*/ { {0}, {0} }, { {0}, {0} }, - { {0}, {0} }, { {0}, {0} }, /*1d0*/ + { {0}, {0} }, { {0}, {0} }, /*1d0*/ { {0}, {0} }, { {0}, {0} }, - { {0}, {0} }, { {0}, {0} }, /*1d4*/ + { {0}, {0} }, { {0}, {0} }, /*1d4*/ { {0}, {0} }, { {0}, {0} }, - { {0}, {0} }, { {0}, {0} }, /*1d8*/ + { {0}, {0} }, { {0}, {0} }, /*1d8*/ { {0}, {0} }, { {0}, {0} }, - { {0}, {0} }, { {0}, {0} }, /*1dc*/ + { {0}, {0} }, { {0}, {0} }, /*1dc*/ { {0}, {0} }, { {0}, {0} }, - { {0}, {0} }, { {0}, {0} }, /*1e0*/ + { {0}, {0} }, { {0}, {0} }, /*1e0*/ { {0}, {0} }, { {0}, {0} }, - { {0}, {0} }, { {0}, {0} }, /*1e4*/ + { {0}, {0} }, { {0}, {0} }, /*1e4*/ { {0}, {0} }, { {0}, {0} }, - { {0}, {0} }, { {0}, {0} }, /*1e8*/ + { {0}, {0} }, { {0}, {0} }, /*1e8*/ { {0}, {0} }, { {0}, {0} }, - { {0}, {0} }, { {0}, {0} }, /*1ec*/ + { {0}, {0} }, { {0}, {0} }, /*1ec*/ { {0}, {0} }, { {0}, {0} }, - { {0}, {0} }, { {0}, {0} }, /*1f0*/ + { {0}, {0} }, { {0}, {0} }, /*1f0*/ { {0}, {0} }, { {0}, {0} }, - { {0}, {0} }, { {0}, {0} }, /*1f4*/ + { {0}, {0} }, { {0}, {0} }, /*1f4*/ { {0}, {0} }, { {0}, {0} }, - { {0}, {0} }, { {0}, {0} }, /*1f8*/ + { {0}, {0} }, { {0}, {0} }, /*1f8*/ { {0}, {0} }, { {0}, {0} }, - { {0}, {0} }, { {0}, {0} } /*1fc*/ + { {0}, {0} }, { {0}, {0} } /*1fc*/ + // clang-format on }; static uint8_t crtcmask[32] = { 0xff, 0xff, 0xff, 0xff, 0x7f, 0x1f, 0x7f, 0x7f, @@ -405,32 +410,27 @@ static uint8_t crtcmask_sl[32] = { }; static int eep_data_out; - -static uint8_t vid_in(uint16_t addr, void *priv); -static void vid_out(uint16_t addr, uint8_t val, void *priv); - +static uint8_t vid_in(uint16_t addr, void *priv); +static void vid_out(uint16_t addr, uint8_t val, void *priv); #ifdef ENABLE_TANDY_LOG int tandy_do_log = ENABLE_TANDY_LOG; - static void tandy_log(const char *fmt, ...) { - va_list ap; + va_list ap; - if (tandy_do_log) - { - va_start(ap, fmt); - pclog_ex(fmt, ap); - va_end(ap); - } + if (tandy_do_log) { + va_start(ap, fmt); + pclog_ex(fmt, ap); + va_end(ap); + } } #else -#define tandy_log(fmt, ...) +# define tandy_log(fmt, ...) #endif - static void recalc_mapping(tandy_t *dev) { @@ -438,59 +438,58 @@ recalc_mapping(tandy_t *dev) mem_mapping_disable(&vid->mapping); io_removehandler(0x03d0, 16, - vid_in, NULL, NULL, vid_out, NULL, NULL, dev); + vid_in, NULL, NULL, vid_out, NULL, NULL, dev); if (vid->planar_ctrl & 4) { - mem_mapping_enable(&vid->mapping); - if (vid->array[5] & 1) - mem_mapping_set_addr(&vid->mapping, 0xa0000, 0x10000); - else - mem_mapping_set_addr(&vid->mapping, 0xb8000, 0x8000); - io_sethandler(0x03d0, 16, vid_in,NULL,NULL, vid_out,NULL,NULL, dev); + mem_mapping_enable(&vid->mapping); + if (vid->array[5] & 1) + mem_mapping_set_addr(&vid->mapping, 0xa0000, 0x10000); + else + mem_mapping_set_addr(&vid->mapping, 0xb8000, 0x8000); + io_sethandler(0x03d0, 16, vid_in, NULL, NULL, vid_out, NULL, NULL, dev); } } - static void recalc_timings(tandy_t *dev) { t1kvid_t *vid = dev->vid; - double _dispontime, _dispofftime, disptime; + double _dispontime; + double _dispofftime; + double disptime; if (vid->mode & 1) { - disptime = vid->crtc[0] + 1; - _dispontime = vid->crtc[1]; + disptime = vid->crtc[0] + 1; + _dispontime = vid->crtc[1]; } else { - disptime = (vid->crtc[0] + 1) << 1; - _dispontime = vid->crtc[1] << 1; + disptime = (vid->crtc[0] + 1) << 1; + _dispontime = vid->crtc[1] << 1; } _dispofftime = disptime - _dispontime; - _dispontime *= CGACONST; + _dispontime *= CGACONST; _dispofftime *= CGACONST; - vid->dispontime = (uint64_t)(_dispontime); - vid->dispofftime = (uint64_t)(_dispofftime); + vid->dispontime = (uint64_t) (_dispontime); + vid->dispofftime = (uint64_t) (_dispofftime); } - static void recalc_address(tandy_t *dev) { t1kvid_t *vid = dev->vid; if ((vid->memctrl & 0xc0) == 0xc0) { - vid->vram = &ram[((vid->memctrl & 0x06) << 14) + dev->base]; - vid->b8000 = &ram[((vid->memctrl & 0x30) << 11) + dev->base]; - vid->b8000_mask = 0x7fff; + vid->vram = &ram[((vid->memctrl & 0x06) << 14) + dev->base]; + vid->b8000 = &ram[((vid->memctrl & 0x30) << 11) + dev->base]; + vid->b8000_mask = 0x7fff; } else { - vid->vram = &ram[((vid->memctrl & 0x07) << 14) + dev->base]; - vid->b8000 = &ram[((vid->memctrl & 0x38) << 11) + dev->base]; - vid->b8000_mask = 0x3fff; + vid->vram = &ram[((vid->memctrl & 0x07) << 14) + dev->base]; + vid->b8000 = &ram[((vid->memctrl & 0x38) << 11) + dev->base]; + vid->b8000_mask = 0x3fff; } } - static void recalc_address_sl(tandy_t *dev) { @@ -499,1006 +498,965 @@ recalc_address_sl(tandy_t *dev) vid->b8000_limit = 0x8000; if (vid->array[5] & 1) { - vid->vram = &ram[((vid->memctrl & 0x04) << 14) + dev->base]; - vid->b8000 = &ram[((vid->memctrl & 0x20) << 11) + dev->base]; + vid->vram = &ram[((vid->memctrl & 0x04) << 14) + dev->base]; + vid->b8000 = &ram[((vid->memctrl & 0x20) << 11) + dev->base]; } else if ((vid->memctrl & 0xc0) == 0xc0) { - vid->vram = &ram[((vid->memctrl & 0x06) << 14) + dev->base]; - vid->b8000 = &ram[((vid->memctrl & 0x30) << 11) + dev->base]; + vid->vram = &ram[((vid->memctrl & 0x06) << 14) + dev->base]; + vid->b8000 = &ram[((vid->memctrl & 0x30) << 11) + dev->base]; } else { - vid->vram = &ram[((vid->memctrl & 0x07) << 14) + dev->base]; - vid->b8000 = &ram[((vid->memctrl & 0x38) << 11) + dev->base]; - if ((vid->memctrl & 0x38) == 0x38) - vid->b8000_limit = 0x4000; + vid->vram = &ram[((vid->memctrl & 0x07) << 14) + dev->base]; + vid->b8000 = &ram[((vid->memctrl & 0x38) << 11) + dev->base]; + if ((vid->memctrl & 0x38) == 0x38) + vid->b8000_limit = 0x4000; } } - static void vid_out(uint16_t addr, uint8_t val, void *priv) { - tandy_t *dev = (tandy_t *)priv; + tandy_t *dev = (tandy_t *) priv; t1kvid_t *vid = dev->vid; - uint8_t old; + uint8_t old; if ((addr >= 0x3d0) && (addr <= 0x3d7)) - addr = (addr & 0xff9) | 0x004; + addr = (addr & 0xff9) | 0x004; switch (addr) { - case 0x03d4: - vid->crtcreg = val & 0x1f; - break; + case 0x03d4: + vid->crtcreg = val & 0x1f; + break; - case 0x03d5: - old = vid->crtc[vid->crtcreg]; - if (dev->is_sl2) - vid->crtc[vid->crtcreg] = val & crtcmask_sl[vid->crtcreg]; - else - vid->crtc[vid->crtcreg] = val & crtcmask[vid->crtcreg]; - if (old != val) { - if (vid->crtcreg < 0xe || vid->crtcreg > 0x10) { - fullchange = changeframecount; - recalc_timings(dev); - } - } - break; + case 0x03d5: + old = vid->crtc[vid->crtcreg]; + if (dev->is_sl2) + vid->crtc[vid->crtcreg] = val & crtcmask_sl[vid->crtcreg]; + else + vid->crtc[vid->crtcreg] = val & crtcmask[vid->crtcreg]; + if (old != val) { + if (vid->crtcreg < 0xe || vid->crtcreg > 0x10) { + vid->fullchange = changeframecount; + recalc_timings(dev); + } + } + break; - case 0x03d8: - vid->mode = val; - if (! dev->is_sl2) - update_cga16_color(vid->mode); - break; + case 0x03d8: + vid->mode = val; + if (!dev->is_sl2) + update_cga16_color(vid->mode); + break; - case 0x03d9: - vid->col = val; - break; + case 0x03d9: + vid->col = val; + break; - case 0x03da: - vid->array_index = val & 0x1f; - break; + case 0x03da: + vid->array_index = val & 0x1f; + break; - case 0x03de: - if (vid->array_index & 16) - val &= 0xf; - vid->array[vid->array_index & 0x1f] = val; - if (dev->is_sl2) { - if ((vid->array_index & 0x1f) == 5) { - recalc_mapping(dev); - recalc_address_sl(dev); - } - } - break; + case 0x03de: + if (vid->array_index & 16) + val &= 0xf; + vid->array[vid->array_index & 0x1f] = val; + if (dev->is_sl2) { + if ((vid->array_index & 0x1f) == 5) { + recalc_mapping(dev); + recalc_address_sl(dev); + } + } + break; - case 0x03df: - vid->memctrl = val; - if (dev->is_sl2) - recalc_address_sl(dev); - else - recalc_address(dev); - break; + case 0x03df: + vid->memctrl = val; + if (dev->is_sl2) + recalc_address_sl(dev); + else + recalc_address(dev); + break; - case 0x0065: - if (val == 8) return; /*Hack*/ - vid->planar_ctrl = val; - recalc_mapping(dev); - break; + case 0x0065: + if (val == 8) + return; /*Hack*/ + vid->planar_ctrl = val; + recalc_mapping(dev); + break; + + default: + break; } } - static uint8_t vid_in(uint16_t addr, void *priv) { - tandy_t *dev = (tandy_t *)priv; - t1kvid_t *vid = dev->vid; - uint8_t ret = 0xff; + const tandy_t *dev = (tandy_t *) priv; + const t1kvid_t *vid = dev->vid; + uint8_t ret = 0xff; if ((addr >= 0x3d0) && (addr <= 0x3d7)) - addr = (addr & 0xff9) | 0x004; + addr = (addr & 0xff9) | 0x004; switch (addr) { - case 0x03d4: - ret = vid->crtcreg; - break; + case 0x03d4: + ret = vid->crtcreg; + break; - case 0x03d5: - ret = vid->crtc[vid->crtcreg]; - break; + case 0x03d5: + ret = vid->crtc[vid->crtcreg]; + break; - case 0x03da: - ret = vid->stat; - break; + case 0x03da: + ret = vid->stat; + break; + + default: + break; } - return(ret); + return ret; } - static void vid_write(uint32_t addr, uint8_t val, void *priv) { - tandy_t *dev = (tandy_t *)priv; + tandy_t *dev = (tandy_t *) priv; t1kvid_t *vid = dev->vid; - if (vid->memctrl == -1) return; + if (vid->memctrl == -1) + return; if (dev->is_sl2) { - if (vid->array[5] & 1) - vid->b8000[addr & 0xffff] = val; - else { - if ((addr & 0x7fff) < vid->b8000_limit) - vid->b8000[addr & 0x7fff] = val; - } + if (vid->array[5] & 1) + vid->b8000[addr & 0xffff] = val; + else { + if ((addr & 0x7fff) < vid->b8000_limit) + vid->b8000[addr & 0x7fff] = val; + } } else { - vid->b8000[addr & vid->b8000_mask] = val; + vid->b8000[addr & vid->b8000_mask] = val; } } - static uint8_t vid_read(uint32_t addr, void *priv) { - tandy_t *dev = (tandy_t *)priv; - t1kvid_t *vid = dev->vid; + const tandy_t *dev = (tandy_t *) priv; + const t1kvid_t *vid = dev->vid; - if (vid->memctrl == -1) return(0xff); + if (vid->memctrl == -1) + return 0xff; if (dev->is_sl2) { - if (vid->array[5] & 1) - return(vid->b8000[addr & 0xffff]); - if ((addr & 0x7fff) < vid->b8000_limit) - return(vid->b8000[addr & 0x7fff]); - else - return(0xff); + if (vid->array[5] & 1) + return (vid->b8000[addr & 0xffff]); + if ((addr & 0x7fff) < vid->b8000_limit) + return (vid->b8000[addr & 0x7fff]); + else + return 0xff; } else { - return(vid->b8000[addr & vid->b8000_mask]); + return (vid->b8000[addr & vid->b8000_mask]); } } - static void vid_poll(void *priv) { - tandy_t *dev = (tandy_t *)priv; + tandy_t *dev = (tandy_t *) priv; t1kvid_t *vid = dev->vid; - uint16_t ca = (vid->crtc[15] | (vid->crtc[14] << 8)) & 0x3fff; - int drawcursor; - int x, c, xs_temp, ys_temp; - int oldvc; - uint8_t chr, attr; - uint16_t dat; - int cols[4]; - int col; - int oldsc; + uint16_t ca = (vid->crtc[15] | (vid->crtc[14] << 8)) & 0x3fff; + int drawcursor; + int x; + int c; + int xs_temp; + int ys_temp; + int oldvc; + uint8_t chr; + uint8_t attr; + uint16_t dat; + int cols[4]; + int col; + int oldsc; - if (! vid->linepos) { - timer_advance_u64(&vid->timer, vid->dispofftime); - vid->stat |= 1; - vid->linepos = 1; - oldsc = vid->sc; - if ((vid->crtc[8] & 3) == 3) - vid->sc = (vid->sc << 1) & 7; - if (vid->dispon) { - if (vid->displine < vid->firstline) { - vid->firstline = vid->displine; - video_wait_for_buffer(); - } - vid->lastline = vid->displine; - cols[0] = (vid->array[2] & 0xf) + 16; - for (c = 0; c < 8; c++) { - if (vid->array[3] & 4) { - buffer32->line[(vid->displine << 1)][c] = buffer32->line[(vid->displine << 1) + 1][c] = cols[0]; - if (vid->mode & 1) { - buffer32->line[(vid->displine << 1)][c + (vid->crtc[1] << 3) + 8] = - buffer32->line[(vid->displine << 1) + 1][c + (vid->crtc[1] << 3) + 8] = cols[0]; - } else { - buffer32->line[(vid->displine << 1)][c + (vid->crtc[1] << 4) + 8] = - buffer32->line[(vid->displine << 1) + 1][c + (vid->crtc[1] << 4) + 8] = cols[0]; - } - } else if ((vid->mode & 0x12) == 0x12) { - buffer32->line[(vid->displine << 1)][c] = buffer32->line[(vid->displine << 1) + 1][c] = 0; - if (vid->mode & 1) { - buffer32->line[(vid->displine << 1)][c + (vid->crtc[1] << 3) + 8] = - buffer32->line[(vid->displine << 1) + 1][c + (vid->crtc[1] << 3) + 8] = 0; - } else { - buffer32->line[(vid->displine << 1)][c + (vid->crtc[1] << 4) + 8] = - buffer32->line[(vid->displine << 1) + 1][c + (vid->crtc[1] << 4) + 8] = 0; - } - } else { - buffer32->line[(vid->displine << 1)][c] = buffer32->line[(vid->displine << 1) + 1][c] = (vid->col & 15) + 16; - if (vid->mode & 1) { - buffer32->line[(vid->displine << 1)][c + (vid->crtc[1] << 3) + 8] = - buffer32->line[(vid->displine << 1) + 1][c + (vid->crtc[1] << 3) + 8] = (vid->col & 15) + 16; - } else { - buffer32->line[(vid->displine << 1)][c + (vid->crtc[1] << 4) + 8] = - buffer32->line[(vid->displine << 1) + 1][c + (vid->crtc[1] << 4) + 8] = (vid->col & 15) + 16; - } - } - } - if (dev->is_sl2 && (vid->array[5] & 1)) { /*640x200x16*/ - for (x = 0; x < vid->crtc[1]*2; x++) { - dat = (vid->vram[(vid->ma << 1) & 0xffff] << 8) | - vid->vram[((vid->ma << 1) + 1) & 0xffff]; - vid->ma++; - buffer32->line[(vid->displine << 1)][(x << 2) + 8] = buffer32->line[(vid->displine << 1) + 1][(x << 2) + 8] = - vid->array[((dat >> 12) & 0xf) + 16] + 16; - buffer32->line[(vid->displine << 1)][(x << 2) + 9] = buffer32->line[(vid->displine << 1) + 1][(x << 2) + 9] = - vid->array[((dat >> 8) & 0xf) + 16] + 16; - buffer32->line[(vid->displine << 1)][(x << 2) + 10] = buffer32->line[(vid->displine << 1) + 1][(x << 2) + 10] = - vid->array[((dat >> 4) & 0xf) + 16] + 16; - buffer32->line[(vid->displine << 1)][(x << 2) + 11] = buffer32->line[(vid->displine << 1) + 1][(x << 2) + 11] = - vid->array[(dat & 0xf) + 16] + 16; - } - } else if ((vid->array[3] & 0x10) && (vid->mode & 1)) { /*320x200x16*/ - for (x = 0; x < vid->crtc[1]; x++) { - dat = (vid->vram[((vid->ma << 1) & 0x1fff) + ((vid->sc & 3) * 0x2000)] << 8) | - vid->vram[((vid->ma << 1) & 0x1fff) + ((vid->sc & 3) * 0x2000) + 1]; - vid->ma++; - buffer32->line[(vid->displine << 1)][(x << 3) + 8] = buffer32->line[(vid->displine << 1) + 1][(x << 3) + 8] = - buffer32->line[(vid->displine << 1)][(x << 3) + 9] = buffer32->line[(vid->displine << 1) + 1][(x << 3) + 9] = - vid->array[((dat >> 12) & vid->array[1]) + 16] + 16; - buffer32->line[(vid->displine << 1)][(x << 3) + 10] = buffer32->line[(vid->displine << 1) + 1][(x << 3) + 10] = - buffer32->line[(vid->displine << 1)][(x << 3) + 11] = buffer32->line[(vid->displine << 1) + 1][(x << 3) + 11] = - vid->array[((dat >> 8) & vid->array[1]) + 16] + 16; - buffer32->line[(vid->displine << 1)][(x << 3) + 12] = buffer32->line[(vid->displine << 1) + 1][(x << 3) + 12] = - buffer32->line[(vid->displine << 1)][(x << 3) + 13] = buffer32->line[(vid->displine << 1) + 1][(x << 3) + 13] = - vid->array[((dat >> 4) & vid->array[1]) + 16] + 16; - buffer32->line[(vid->displine << 1)][(x << 3) + 14] = buffer32->line[(vid->displine << 1) + 1][(x << 3) + 14] = - buffer32->line[(vid->displine << 1)][(x << 3) + 15] = buffer32->line[(vid->displine << 1) + 1][(x << 3) + 15] = - vid->array[(dat & vid->array[1]) + 16] + 16; - } - } else if (vid->array[3] & 0x10) { /*160x200x16*/ - for (x = 0; x < vid->crtc[1]; x++) { - if (dev->is_sl2) { - dat = (vid->vram[((vid->ma << 1) & 0x1fff) + ((vid->sc & 1) * 0x2000)] << 8) | - vid->vram[((vid->ma << 1) & 0x1fff) + ((vid->sc & 1) * 0x2000) + 1]; - } else { - dat = (vid->vram[((vid->ma << 1) & 0x1fff) + ((vid->sc & 3) * 0x2000)] << 8) | - vid->vram[((vid->ma << 1) & 0x1fff) + ((vid->sc & 3) * 0x2000) + 1]; - } - vid->ma++; - buffer32->line[(vid->displine << 1)][(x << 4) + 8] = buffer32->line[(vid->displine << 1) + 1][(x << 4) + 8] = - buffer32->line[(vid->displine << 1)][(x << 4) + 9] = buffer32->line[(vid->displine << 1) + 1][(x << 4) + 9] = - buffer32->line[(vid->displine << 1)][(x << 4) + 10] = buffer32->line[(vid->displine << 1) + 1][(x << 4) + 10] = - buffer32->line[(vid->displine << 1)][(x << 4) + 11] = buffer32->line[(vid->displine << 1) + 1][(x << 4) + 11] = - vid->array[((dat >> 12) & vid->array[1]) + 16] + 16; - buffer32->line[(vid->displine << 1)][(x << 4) + 12] = buffer32->line[(vid->displine << 1) + 1][(x << 4) + 12] = - buffer32->line[(vid->displine << 1)][(x << 4) + 13] = buffer32->line[(vid->displine << 1) + 1][(x << 4) + 13] = - buffer32->line[(vid->displine << 1)][(x << 4) + 14] = buffer32->line[(vid->displine << 1) + 1][(x << 4) + 14] = - buffer32->line[(vid->displine << 1)][(x << 4) + 15] = buffer32->line[(vid->displine << 1) + 1][(x << 4) + 15] = - vid->array[((dat >> 8) & vid->array[1]) + 16] + 16; - buffer32->line[(vid->displine << 1)][(x << 4) + 16] = buffer32->line[(vid->displine << 1) + 1][(x << 4) + 16] = - buffer32->line[(vid->displine << 1)][(x << 4) + 17] = buffer32->line[(vid->displine << 1) + 1][(x << 4) + 17] = - buffer32->line[(vid->displine << 1)][(x << 4) + 18] = buffer32->line[(vid->displine << 1) + 1][(x << 4) + 18] = - buffer32->line[(vid->displine << 1)][(x << 4) + 19] = buffer32->line[(vid->displine << 1) + 1][(x << 4) + 19] = - vid->array[((dat >> 4) & vid->array[1]) + 16] + 16; - buffer32->line[(vid->displine << 1)][(x << 4) + 20] = buffer32->line[(vid->displine << 1) + 1][(x << 4) + 20] = - buffer32->line[(vid->displine << 1)][(x << 4) + 21] = buffer32->line[(vid->displine << 1) + 1][(x << 4) + 21] = - buffer32->line[(vid->displine << 1)][(x << 4) + 22] = buffer32->line[(vid->displine << 1) + 1][(x << 4) + 22] = - buffer32->line[(vid->displine << 1)][(x << 4) + 23] = buffer32->line[(vid->displine << 1) + 1][(x << 4) + 23] = - vid->array[(dat & vid->array[1]) + 16] + 16; - } - } else if (vid->array[3] & 0x08) { /*640x200x4 - this implementation is a complete guess!*/ - for (x = 0; x < vid->crtc[1]; x++) { - dat = (vid->vram[((vid->ma << 1) & 0x1fff) + ((vid->sc & 3) * 0x2000)] << 8) | - vid->vram[((vid->ma << 1) & 0x1fff) + ((vid->sc & 3) * 0x2000) + 1]; - vid->ma++; - for (c = 0; c < 8; c++) { - chr = (dat >> 6) & 2; - chr |= ((dat >> 15) & 1); - buffer32->line[(vid->displine << 1)][(x << 3) + 8 + c] = buffer32->line[(vid->displine << 1) + 1][(x << 3) + 8 + c] = - vid->array[(chr & vid->array[1]) + 16] + 16; - dat <<= 1; - } - } - } else if (vid->mode & 1) { - for (x = 0; x < vid->crtc[1]; x++) { - chr = vid->vram[ (vid->ma << 1) & 0x3fff]; - attr = vid->vram[((vid->ma << 1) + 1) & 0x3fff]; - drawcursor = ((vid->ma == ca) && vid->con && vid->cursoron); - if (vid->mode & 0x20) { - cols[1] = vid->array[ ((attr & 15) & vid->array[1]) + 16] + 16; - cols[0] = vid->array[(((attr >> 4) & 7) & vid->array[1]) + 16] + 16; - if ((vid->blink & 16) && (attr & 0x80) && !drawcursor) - cols[1] = cols[0]; - } else { - cols[1] = vid->array[((attr & 15) & vid->array[1]) + 16] + 16; - cols[0] = vid->array[((attr >> 4) & vid->array[1]) + 16] + 16; - } - if (vid->sc & 8) { - for (c = 0; c < 8; c++) { - buffer32->line[(vid->displine << 1)][(x << 3) + c + 8] = buffer32->line[(vid->displine << 1) + 1][(x << 3) + c + 8] = - cols[0]; - } - } else { - for (c = 0; c < 8; c++) { - if (vid->sc == 8) { - buffer32->line[(vid->displine << 1)][(x << 3) + c + 8] = buffer32->line[(vid->displine << 1) + 1][(x << 3) + c + 8] = - cols[(fontdat[chr][7] & (1 << (c ^ 7))) ? 1 : 0]; - } else { - buffer32->line[(vid->displine << 1)][(x << 3) + c + 8] = buffer32->line[(vid->displine << 1) + 1][(x << 3) + c + 8] = - cols[(fontdat[chr][vid->sc & 7] & (1 << (c ^ 7))) ? 1 : 0]; - } - } - } - if (drawcursor) { - for (c = 0; c < 8; c++) { - buffer32->line[(vid->displine << 1)][(x << 3) + c + 8] ^= 15; - buffer32->line[(vid->displine << 1) + 1][(x << 3) + c + 8] ^= 15; - } - } - vid->ma++; - } - } else if (! (vid->mode & 2)) { - for (x = 0; x < vid->crtc[1]; x++) { - chr = vid->vram[ (vid->ma << 1) & 0x3fff]; - attr = vid->vram[((vid->ma << 1) + 1) & 0x3fff]; - drawcursor = ((vid->ma == ca) && vid->con && vid->cursoron); - if (vid->mode & 0x20) { - cols[1] = vid->array[ ((attr & 15) & vid->array[1]) + 16] + 16; - cols[0] = vid->array[(((attr >> 4) & 7) & vid->array[1]) + 16] + 16; - if ((vid->blink & 16) && (attr & 0x80) && !drawcursor) - cols[1] = cols[0]; - } else { - cols[1] = vid->array[((attr & 15) & vid->array[1]) + 16] + 16; - cols[0] = vid->array[((attr >> 4) & vid->array[1]) + 16] + 16; - } - vid->ma++; - if (vid->sc & 8) { - for (c = 0; c < 8; c++) - buffer32->line[(vid->displine << 1)][(x << 4) + (c << 1) + 8] = buffer32->line[(vid->displine << 1)][(x << 4) + (c << 1) + 1 + 8] = - cols[0]; - } else { - for (c = 0; c < 8; c++) { - if (vid->sc == 8) { - buffer32->line[(vid->displine << 1)][(x << 4) + (c << 1) + 8] = buffer32->line[(vid->displine << 1) + 1][(x << 4) + (c << 1) + 8] = - buffer32->line[(vid->displine << 1)][(x << 4) + (c << 1) + 1 + 8] = buffer32->line[(vid->displine << 1) + 1][(x << 4) + (c << 1) + 1 + 8] = - cols[(fontdat[chr][7] & (1 << (c ^ 7))) ? 1 : 0]; - } else { - buffer32->line[(vid->displine << 1)][(x << 4) + (c << 1) + 8] = buffer32->line[(vid->displine << 1) + 1][(x << 4) + (c << 1) + 8] = - buffer32->line[(vid->displine << 1)][(x << 4) + (c << 1) + 1 + 8] = buffer32->line[(vid->displine << 1) + 1][(x << 4) + (c << 1) + 1 + 8] = - cols[(fontdat[chr][vid->sc & 7] & (1 << (c ^ 7))) ? 1 : 0]; - } - } - } - if (drawcursor) { - for (c = 0; c < 16; c++) { - buffer32->line[(vid->displine << 1)][(x << 4) + c + 8] ^= 15; - buffer32->line[(vid->displine << 1) + 1][(x << 4) + c + 8] ^= 15; - } - } - } - } else if (! (vid->mode & 16)) { - cols[0] = (vid->col & 15); - col = (vid->col & 16) ? 8 : 0; - if (vid->mode & 4) { - cols[1] = col | 3; - cols[2] = col | 4; - cols[3] = col | 7; - } else if (vid->col & 32) { - cols[1] = col | 3; - cols[2] = col | 5; - cols[3] = col | 7; - } else { - cols[1] = col | 2; - cols[2] = col | 4; - cols[3] = col | 6; - } - cols[0] = vid->array[(cols[0] & vid->array[1]) + 16] + 16; - cols[1] = vid->array[(cols[1] & vid->array[1]) + 16] + 16; - cols[2] = vid->array[(cols[2] & vid->array[1]) + 16] + 16; - cols[3] = vid->array[(cols[3] & vid->array[1]) + 16] + 16; - for (x = 0; x < vid->crtc[1]; x++) { - dat = (vid->vram[((vid->ma << 1) & 0x1fff) + ((vid->sc & 1) * 0x2000)] << 8) | - vid->vram[((vid->ma << 1) & 0x1fff) + ((vid->sc & 1) * 0x2000) + 1]; - vid->ma++; - for (c = 0; c < 8; c++) { - buffer32->line[(vid->displine << 1)][(x << 4) + (c << 1) + 8] = buffer32->line[(vid->displine << 1) + 1][(x << 4) + (c << 1) + 8] = - buffer32->line[(vid->displine << 1)][(x << 4) + (c << 1) + 1 + 8] = buffer32->line[(vid->displine << 1) + 1][(x << 4) + (c << 1) + 1 + 8] = - cols[dat >> 14]; - dat <<= 2; - } - } - } else { - cols[0] = 0; - cols[1] = vid->array[(vid->col & vid->array[1]) + 16] + 16; - for (x = 0; x < vid->crtc[1]; x++) { - dat = (vid->vram[((vid->ma << 1) & 0x1fff) + ((vid->sc & 1) * 0x2000)] << 8) | - vid->vram[((vid->ma << 1) & 0x1fff) + ((vid->sc & 1) * 0x2000) + 1]; - vid->ma++; - for (c = 0; c < 16; c++) { - buffer32->line[(vid->displine << 1)][(x << 4) + c + 8] = buffer32->line[(vid->displine << 1) + 1][(x << 4) + c + 8] = - cols[dat >> 15]; - dat <<= 1; - } - } - } - } else { - if (vid->array[3] & 4) { - if (vid->mode & 1) { - hline(buffer32, 0, (vid->displine << 1), (vid->crtc[1] << 3) + 16, (vid->array[2] & 0xf) + 16); - hline(buffer32, 0, (vid->displine << 1) + 1, (vid->crtc[1] << 3) + 16, (vid->array[2] & 0xf) + 16); - } else { - hline(buffer32, 0, (vid->displine << 1), (vid->crtc[1] << 4) + 16, (vid->array[2] & 0xf) + 16); - hline(buffer32, 0, (vid->displine << 1) + 1, (vid->crtc[1] << 4) + 16, (vid->array[2] & 0xf) + 16); - } - } else { - cols[0] = ((vid->mode & 0x12) == 0x12) ? 0 : (vid->col & 0xf) + 16; - if (vid->mode & 1) { - hline(buffer32, 0, (vid->displine << 1), (vid->crtc[1] << 3) + 16, cols[0]); - hline(buffer32, 0, (vid->displine << 1) + 1, (vid->crtc[1] << 3) + 16, cols[0]); - } else { - hline(buffer32, 0, (vid->displine << 1), (vid->crtc[1] << 4) + 16, cols[0]); - hline(buffer32, 0, (vid->displine << 1) + 1, (vid->crtc[1] << 4) + 16, cols[0]); - } - } - } + if (!vid->linepos) { + timer_advance_u64(&vid->timer, vid->dispofftime); + vid->stat |= 1; + vid->linepos = 1; + oldsc = vid->sc; + if ((vid->crtc[8] & 3) == 3) + vid->sc = (vid->sc << 1) & 7; + if (vid->dispon) { + if (vid->displine < vid->firstline) { + vid->firstline = vid->displine; + video_wait_for_buffer(); + } + vid->lastline = vid->displine; + cols[0] = (vid->array[2] & 0xf) + 16; + for (c = 0; c < 8; c++) { + if (vid->array[3] & 4) { + buffer32->line[vid->displine << 1][c] = buffer32->line[(vid->displine << 1) + 1][c] = cols[0]; + if (vid->mode & 1) { + buffer32->line[vid->displine << 1][c + (vid->crtc[1] << 3) + 8] = buffer32->line[(vid->displine << 1) + 1][c + (vid->crtc[1] << 3) + 8] = cols[0]; + } else { + buffer32->line[vid->displine << 1][c + (vid->crtc[1] << 4) + 8] = buffer32->line[(vid->displine << 1) + 1][c + (vid->crtc[1] << 4) + 8] = cols[0]; + } + } else if ((vid->mode & 0x12) == 0x12) { + buffer32->line[vid->displine << 1][c] = buffer32->line[(vid->displine << 1) + 1][c] = 0; + if (vid->mode & 1) { + buffer32->line[vid->displine << 1][c + (vid->crtc[1] << 3) + 8] = buffer32->line[(vid->displine << 1) + 1][c + (vid->crtc[1] << 3) + 8] = 0; + } else { + buffer32->line[vid->displine << 1][c + (vid->crtc[1] << 4) + 8] = buffer32->line[(vid->displine << 1) + 1][c + (vid->crtc[1] << 4) + 8] = 0; + } + } else { + buffer32->line[vid->displine << 1][c] = buffer32->line[(vid->displine << 1) + 1][c] = (vid->col & 15) + 16; + if (vid->mode & 1) { + buffer32->line[vid->displine << 1][c + (vid->crtc[1] << 3) + 8] = buffer32->line[(vid->displine << 1) + 1][c + (vid->crtc[1] << 3) + 8] = (vid->col & 15) + 16; + } else { + buffer32->line[vid->displine << 1][c + (vid->crtc[1] << 4) + 8] = buffer32->line[(vid->displine << 1) + 1][c + (vid->crtc[1] << 4) + 8] = (vid->col & 15) + 16; + } + } + } + if (dev->is_sl2 && (vid->array[5] & 1)) { /*640x200x16*/ + for (x = 0; x < vid->crtc[1] * 2; x++) { + dat = (vid->vram[(vid->ma << 1) & 0xffff] << 8) | vid->vram[((vid->ma << 1) + 1) & 0xffff]; + vid->ma++; + buffer32->line[vid->displine << 1][(x << 2) + 8] = buffer32->line[(vid->displine << 1) + 1][(x << 2) + 8] = vid->array[((dat >> 12) & 0xf) + 16] + 16; + buffer32->line[vid->displine << 1][(x << 2) + 9] = buffer32->line[(vid->displine << 1) + 1][(x << 2) + 9] = vid->array[((dat >> 8) & 0xf) + 16] + 16; + buffer32->line[vid->displine << 1][(x << 2) + 10] = buffer32->line[(vid->displine << 1) + 1][(x << 2) + 10] = vid->array[((dat >> 4) & 0xf) + 16] + 16; + buffer32->line[vid->displine << 1][(x << 2) + 11] = buffer32->line[(vid->displine << 1) + 1][(x << 2) + 11] = vid->array[(dat & 0xf) + 16] + 16; + } + } else if ((vid->array[3] & 0x10) && (vid->mode & 1)) { /*320x200x16*/ + for (x = 0; x < vid->crtc[1]; x++) { + dat = (vid->vram[((vid->ma << 1) & 0x1fff) + ((vid->sc & 3) * 0x2000)] << 8) | vid->vram[((vid->ma << 1) & 0x1fff) + ((vid->sc & 3) * 0x2000) + 1]; + vid->ma++; + buffer32->line[vid->displine << 1][(x << 3) + 8] = buffer32->line[(vid->displine << 1) + 1][(x << 3) + 8] = buffer32->line[vid->displine << 1][(x << 3) + 9] = buffer32->line[(vid->displine << 1) + 1][(x << 3) + 9] = vid->array[((dat >> 12) & vid->array[1]) + 16] + 16; + buffer32->line[vid->displine << 1][(x << 3) + 10] = buffer32->line[(vid->displine << 1) + 1][(x << 3) + 10] = buffer32->line[vid->displine << 1][(x << 3) + 11] = buffer32->line[(vid->displine << 1) + 1][(x << 3) + 11] = vid->array[((dat >> 8) & vid->array[1]) + 16] + 16; + buffer32->line[vid->displine << 1][(x << 3) + 12] = buffer32->line[(vid->displine << 1) + 1][(x << 3) + 12] = buffer32->line[vid->displine << 1][(x << 3) + 13] = buffer32->line[(vid->displine << 1) + 1][(x << 3) + 13] = vid->array[((dat >> 4) & vid->array[1]) + 16] + 16; + buffer32->line[vid->displine << 1][(x << 3) + 14] = buffer32->line[(vid->displine << 1) + 1][(x << 3) + 14] = buffer32->line[vid->displine << 1][(x << 3) + 15] = buffer32->line[(vid->displine << 1) + 1][(x << 3) + 15] = vid->array[(dat & vid->array[1]) + 16] + 16; + } + } else if (vid->array[3] & 0x10) { /*160x200x16*/ + for (x = 0; x < vid->crtc[1]; x++) { + if (dev->is_sl2) { + dat = (vid->vram[((vid->ma << 1) & 0x1fff) + ((vid->sc & 1) * 0x2000)] << 8) | vid->vram[((vid->ma << 1) & 0x1fff) + ((vid->sc & 1) * 0x2000) + 1]; + } else { + dat = (vid->vram[((vid->ma << 1) & 0x1fff) + ((vid->sc & 3) * 0x2000)] << 8) | vid->vram[((vid->ma << 1) & 0x1fff) + ((vid->sc & 3) * 0x2000) + 1]; + } + vid->ma++; + buffer32->line[vid->displine << 1][(x << 4) + 8] = buffer32->line[(vid->displine << 1) + 1][(x << 4) + 8] = buffer32->line[vid->displine << 1][(x << 4) + 9] = buffer32->line[(vid->displine << 1) + 1][(x << 4) + 9] = buffer32->line[vid->displine << 1][(x << 4) + 10] = buffer32->line[(vid->displine << 1) + 1][(x << 4) + 10] = buffer32->line[vid->displine << 1][(x << 4) + 11] = buffer32->line[(vid->displine << 1) + 1][(x << 4) + 11] = vid->array[((dat >> 12) & vid->array[1]) + 16] + 16; + buffer32->line[vid->displine << 1][(x << 4) + 12] = buffer32->line[(vid->displine << 1) + 1][(x << 4) + 12] = buffer32->line[vid->displine << 1][(x << 4) + 13] = buffer32->line[(vid->displine << 1) + 1][(x << 4) + 13] = buffer32->line[vid->displine << 1][(x << 4) + 14] = buffer32->line[(vid->displine << 1) + 1][(x << 4) + 14] = buffer32->line[vid->displine << 1][(x << 4) + 15] = buffer32->line[(vid->displine << 1) + 1][(x << 4) + 15] = vid->array[((dat >> 8) & vid->array[1]) + 16] + 16; + buffer32->line[vid->displine << 1][(x << 4) + 16] = buffer32->line[(vid->displine << 1) + 1][(x << 4) + 16] = buffer32->line[vid->displine << 1][(x << 4) + 17] = buffer32->line[(vid->displine << 1) + 1][(x << 4) + 17] = buffer32->line[vid->displine << 1][(x << 4) + 18] = buffer32->line[(vid->displine << 1) + 1][(x << 4) + 18] = buffer32->line[vid->displine << 1][(x << 4) + 19] = buffer32->line[(vid->displine << 1) + 1][(x << 4) + 19] = vid->array[((dat >> 4) & vid->array[1]) + 16] + 16; + buffer32->line[vid->displine << 1][(x << 4) + 20] = buffer32->line[(vid->displine << 1) + 1][(x << 4) + 20] = buffer32->line[vid->displine << 1][(x << 4) + 21] = buffer32->line[(vid->displine << 1) + 1][(x << 4) + 21] = buffer32->line[vid->displine << 1][(x << 4) + 22] = buffer32->line[(vid->displine << 1) + 1][(x << 4) + 22] = buffer32->line[vid->displine << 1][(x << 4) + 23] = buffer32->line[(vid->displine << 1) + 1][(x << 4) + 23] = vid->array[(dat & vid->array[1]) + 16] + 16; + } + } else if (vid->array[3] & 0x08) { /*640x200x4 - this implementation is a complete guess!*/ + for (x = 0; x < vid->crtc[1]; x++) { + dat = (vid->vram[((vid->ma << 1) & 0x1fff) + ((vid->sc & 3) * 0x2000)] << 8) | vid->vram[((vid->ma << 1) & 0x1fff) + ((vid->sc & 3) * 0x2000) + 1]; + vid->ma++; + for (c = 0; c < 8; c++) { + chr = (dat >> 6) & 2; + chr |= ((dat >> 15) & 1); + buffer32->line[vid->displine << 1][(x << 3) + 8 + c] = buffer32->line[(vid->displine << 1) + 1][(x << 3) + 8 + c] = vid->array[(chr & vid->array[1]) + 16] + 16; + dat <<= 1; + } + } + } else if (vid->mode & 1) { + for (x = 0; x < vid->crtc[1]; x++) { + chr = vid->vram[(vid->ma << 1) & 0x3fff]; + attr = vid->vram[((vid->ma << 1) + 1) & 0x3fff]; + drawcursor = ((vid->ma == ca) && vid->con && vid->cursoron); + if (vid->mode & 0x20) { + cols[1] = vid->array[((attr & 15) & vid->array[1]) + 16] + 16; + cols[0] = vid->array[(((attr >> 4) & 7) & vid->array[1]) + 16] + 16; + if ((vid->blink & 16) && (attr & 0x80) && !drawcursor) + cols[1] = cols[0]; + } else { + cols[1] = vid->array[((attr & 15) & vid->array[1]) + 16] + 16; + cols[0] = vid->array[((attr >> 4) & vid->array[1]) + 16] + 16; + } + if (vid->sc & 8) { + for (c = 0; c < 8; c++) { + buffer32->line[vid->displine << 1][(x << 3) + c + 8] = buffer32->line[(vid->displine << 1) + 1][(x << 3) + c + 8] = cols[0]; + } + } else { + for (c = 0; c < 8; c++) { + if (vid->sc == 8) { + buffer32->line[vid->displine << 1][(x << 3) + c + 8] = buffer32->line[(vid->displine << 1) + 1][(x << 3) + c + 8] = cols[(fontdat[chr][7] & (1 << (c ^ 7))) ? 1 : 0]; + } else { + buffer32->line[vid->displine << 1][(x << 3) + c + 8] = buffer32->line[(vid->displine << 1) + 1][(x << 3) + c + 8] = cols[(fontdat[chr][vid->sc & 7] & (1 << (c ^ 7))) ? 1 : 0]; + } + } + } + if (drawcursor) { + for (c = 0; c < 8; c++) { + buffer32->line[vid->displine << 1][(x << 3) + c + 8] ^= 15; + buffer32->line[(vid->displine << 1) + 1][(x << 3) + c + 8] ^= 15; + } + } + vid->ma++; + } + } else if (!(vid->mode & 2)) { + for (x = 0; x < vid->crtc[1]; x++) { + chr = vid->vram[(vid->ma << 1) & 0x3fff]; + attr = vid->vram[((vid->ma << 1) + 1) & 0x3fff]; + drawcursor = ((vid->ma == ca) && vid->con && vid->cursoron); + if (vid->mode & 0x20) { + cols[1] = vid->array[((attr & 15) & vid->array[1]) + 16] + 16; + cols[0] = vid->array[(((attr >> 4) & 7) & vid->array[1]) + 16] + 16; + if ((vid->blink & 16) && (attr & 0x80) && !drawcursor) + cols[1] = cols[0]; + } else { + cols[1] = vid->array[((attr & 15) & vid->array[1]) + 16] + 16; + cols[0] = vid->array[((attr >> 4) & vid->array[1]) + 16] + 16; + } + vid->ma++; + if (vid->sc & 8) { + for (c = 0; c < 8; c++) + buffer32->line[vid->displine << 1][(x << 4) + (c << 1) + 8] = buffer32->line[vid->displine << 1][(x << 4) + (c << 1) + 1 + 8] = cols[0]; + } else { + for (c = 0; c < 8; c++) { + if (vid->sc == 8) { + buffer32->line[vid->displine << 1][(x << 4) + (c << 1) + 8] = buffer32->line[(vid->displine << 1) + 1][(x << 4) + (c << 1) + 8] = buffer32->line[vid->displine << 1][(x << 4) + (c << 1) + 1 + 8] = buffer32->line[(vid->displine << 1) + 1][(x << 4) + (c << 1) + 1 + 8] = cols[(fontdat[chr][7] & (1 << (c ^ 7))) ? 1 : 0]; + } else { + buffer32->line[vid->displine << 1][(x << 4) + (c << 1) + 8] = buffer32->line[(vid->displine << 1) + 1][(x << 4) + (c << 1) + 8] = buffer32->line[vid->displine << 1][(x << 4) + (c << 1) + 1 + 8] = buffer32->line[(vid->displine << 1) + 1][(x << 4) + (c << 1) + 1 + 8] = cols[(fontdat[chr][vid->sc & 7] & (1 << (c ^ 7))) ? 1 : 0]; + } + } + } + if (drawcursor) { + for (c = 0; c < 16; c++) { + buffer32->line[vid->displine << 1][(x << 4) + c + 8] ^= 15; + buffer32->line[(vid->displine << 1) + 1][(x << 4) + c + 8] ^= 15; + } + } + } + } else if (!(vid->mode & 16)) { + cols[0] = (vid->col & 15); + col = (vid->col & 16) ? 8 : 0; + if (vid->mode & 4) { + cols[1] = col | 3; + cols[2] = col | 4; + cols[3] = col | 7; + } else if (vid->col & 32) { + cols[1] = col | 3; + cols[2] = col | 5; + cols[3] = col | 7; + } else { + cols[1] = col | 2; + cols[2] = col | 4; + cols[3] = col | 6; + } + cols[0] = vid->array[(cols[0] & vid->array[1]) + 16] + 16; + cols[1] = vid->array[(cols[1] & vid->array[1]) + 16] + 16; + cols[2] = vid->array[(cols[2] & vid->array[1]) + 16] + 16; + cols[3] = vid->array[(cols[3] & vid->array[1]) + 16] + 16; + for (x = 0; x < vid->crtc[1]; x++) { + dat = (vid->vram[((vid->ma << 1) & 0x1fff) + ((vid->sc & 1) * 0x2000)] << 8) | vid->vram[((vid->ma << 1) & 0x1fff) + ((vid->sc & 1) * 0x2000) + 1]; + vid->ma++; + for (c = 0; c < 8; c++) { + buffer32->line[vid->displine << 1][(x << 4) + (c << 1) + 8] = buffer32->line[(vid->displine << 1) + 1][(x << 4) + (c << 1) + 8] = buffer32->line[vid->displine << 1][(x << 4) + (c << 1) + 1 + 8] = buffer32->line[(vid->displine << 1) + 1][(x << 4) + (c << 1) + 1 + 8] = cols[dat >> 14]; + dat <<= 2; + } + } + } else { + cols[0] = 0; + cols[1] = vid->array[(vid->col & vid->array[1]) + 16] + 16; + for (x = 0; x < vid->crtc[1]; x++) { + dat = (vid->vram[((vid->ma << 1) & 0x1fff) + ((vid->sc & 1) * 0x2000)] << 8) | vid->vram[((vid->ma << 1) & 0x1fff) + ((vid->sc & 1) * 0x2000) + 1]; + vid->ma++; + for (c = 0; c < 16; c++) { + buffer32->line[vid->displine << 1][(x << 4) + c + 8] = buffer32->line[(vid->displine << 1) + 1][(x << 4) + c + 8] = cols[dat >> 15]; + dat <<= 1; + } + } + } + } else { + if (vid->array[3] & 4) { + if (vid->mode & 1) { + hline(buffer32, 0, (vid->displine << 1), (vid->crtc[1] << 3) + 16, (vid->array[2] & 0xf) + 16); + hline(buffer32, 0, (vid->displine << 1) + 1, (vid->crtc[1] << 3) + 16, (vid->array[2] & 0xf) + 16); + } else { + hline(buffer32, 0, (vid->displine << 1), (vid->crtc[1] << 4) + 16, (vid->array[2] & 0xf) + 16); + hline(buffer32, 0, (vid->displine << 1) + 1, (vid->crtc[1] << 4) + 16, (vid->array[2] & 0xf) + 16); + } + } else { + cols[0] = ((vid->mode & 0x12) == 0x12) ? 0 : (vid->col & 0xf) + 16; + if (vid->mode & 1) { + hline(buffer32, 0, (vid->displine << 1), (vid->crtc[1] << 3) + 16, cols[0]); + hline(buffer32, 0, (vid->displine << 1) + 1, (vid->crtc[1] << 3) + 16, cols[0]); + } else { + hline(buffer32, 0, (vid->displine << 1), (vid->crtc[1] << 4) + 16, cols[0]); + hline(buffer32, 0, (vid->displine << 1) + 1, (vid->crtc[1] << 4) + 16, cols[0]); + } + } + } - if (vid->mode & 1) - x = (vid->crtc[1] << 3) + 16; - else - x = (vid->crtc[1] << 4) + 16; - if (!dev->is_sl2 && vid->composite) { - Composite_Process(vid->mode, 0, x >> 2, buffer32->line[(vid->displine << 1)]); - Composite_Process(vid->mode, 0, x >> 2, buffer32->line[(vid->displine << 1) + 1]); - } - vid->sc = oldsc; - if (vid->vc == vid->crtc[7] && !vid->sc) - vid->stat |= 8; - vid->displine++; - if (vid->displine >= 360) - vid->displine = 0; + if (vid->mode & 1) + x = (vid->crtc[1] << 3) + 16; + else + x = (vid->crtc[1] << 4) + 16; + if (!dev->is_sl2 && vid->composite) { + Composite_Process(vid->mode, 0, x >> 2, buffer32->line[vid->displine << 1]); + Composite_Process(vid->mode, 0, x >> 2, buffer32->line[(vid->displine << 1) + 1]); + } else { + video_process_8(x, vid->displine << 1); + video_process_8(x, (vid->displine << 1) + 1); + } + vid->sc = oldsc; + if (vid->vc == vid->crtc[7] && !vid->sc) + vid->stat |= 8; + vid->displine++; + if (vid->displine >= 360) + vid->displine = 0; } else { - timer_advance_u64(&vid->timer, vid->dispontime); - if (vid->dispon) - vid->stat &= ~1; - vid->linepos = 0; - if (vid->vsynctime) { - vid->vsynctime--; - if (! vid->vsynctime) - vid->stat &= ~8; - } - if (vid->sc == (vid->crtc[11] & 31) || ((vid->crtc[8] & 3) == 3 && vid->sc == ((vid->crtc[11] & 31) >> 1))) { - vid->con = 0; - vid->coff = 1; - } - if (vid->vadj) { - vid->sc++; - vid->sc &= 31; - vid->ma = vid->maback; - vid->vadj--; - if (! vid->vadj) { - vid->dispon = 1; - if (dev->is_sl2 && (vid->array[5] & 1)) - vid->ma = vid->maback = vid->crtc[13] | (vid->crtc[12] << 8); - else - vid->ma = vid->maback = (vid->crtc[13] | (vid->crtc[12] << 8)) & 0x3fff; - vid->sc = 0; - } - } else if (vid->sc == vid->crtc[9] || ((vid->crtc[8] & 3) == 3 && vid->sc == (vid->crtc[9] >> 1))) { - vid->maback = vid->ma; - vid->sc = 0; - oldvc = vid->vc; - vid->vc++; - if (dev->is_sl2) - vid->vc &= 255; - else - vid->vc &= 127; - if (vid->vc == vid->crtc[6]) - vid->dispon = 0; - if (oldvc == vid->crtc[4]) { - vid->vc = 0; - vid->vadj = vid->crtc[5]; - if (! vid->vadj) - vid->dispon = 1; - if (! vid->vadj) { - if (dev->is_sl2 && (vid->array[5] & 1)) - vid->ma = vid->maback = vid->crtc[13] | (vid->crtc[12] << 8); - else - vid->ma = vid->maback = (vid->crtc[13] | (vid->crtc[12] << 8)) & 0x3fff; - } - if ((vid->crtc[10] & 0x60) == 0x20) - vid->cursoron = 0; - else - vid->cursoron = vid->blink & 16; - } - if (vid->vc == vid->crtc[7]) { - vid->dispon = 0; - vid->displine = 0; - vid->vsynctime = 16; - if (vid->crtc[7]) { - if (vid->mode & 1) - x = (vid->crtc[1] << 3) + 16; - else - x = (vid->crtc[1] << 4) + 16; - vid->lastline++; + timer_advance_u64(&vid->timer, vid->dispontime); + if (vid->dispon) + vid->stat &= ~1; + vid->linepos = 0; + if (vid->vsynctime) { + vid->vsynctime--; + if (!vid->vsynctime) + vid->stat &= ~8; + } + if (vid->sc == (vid->crtc[11] & 31) || ((vid->crtc[8] & 3) == 3 && vid->sc == ((vid->crtc[11] & 31) >> 1))) { + vid->con = 0; + vid->coff = 1; + } + if (vid->vadj) { + vid->sc++; + vid->sc &= 31; + vid->ma = vid->maback; + vid->vadj--; + if (!vid->vadj) { + vid->dispon = 1; + if (dev->is_sl2 && (vid->array[5] & 1)) + vid->ma = vid->maback = vid->crtc[13] | (vid->crtc[12] << 8); + else + vid->ma = vid->maback = (vid->crtc[13] | (vid->crtc[12] << 8)) & 0x3fff; + vid->sc = 0; + } + } else if (vid->sc == vid->crtc[9] || ((vid->crtc[8] & 3) == 3 && vid->sc == (vid->crtc[9] >> 1))) { + vid->maback = vid->ma; + vid->sc = 0; + oldvc = vid->vc; + vid->vc++; + if (dev->is_sl2) + vid->vc &= 255; + else + vid->vc &= 127; + if (vid->vc == vid->crtc[6]) + vid->dispon = 0; + if (oldvc == vid->crtc[4]) { + vid->vc = 0; + vid->vadj = vid->crtc[5]; + if (!vid->vadj) + vid->dispon = 1; + if (!vid->vadj) { + if (dev->is_sl2 && (vid->array[5] & 1)) + vid->ma = vid->maback = vid->crtc[13] | (vid->crtc[12] << 8); + else + vid->ma = vid->maback = (vid->crtc[13] | (vid->crtc[12] << 8)) & 0x3fff; + } + if ((vid->crtc[10] & 0x60) == 0x20) + vid->cursoron = 0; + else + vid->cursoron = vid->blink & 16; + } + if (vid->vc == vid->crtc[7]) { + vid->dispon = 0; + vid->displine = 0; + vid->vsynctime = 16; + if (vid->crtc[7]) { + if (vid->mode & 1) + x = (vid->crtc[1] << 3) + 16; + else + x = (vid->crtc[1] << 4) + 16; + vid->lastline++; - xs_temp = x; - ys_temp = (vid->lastline - vid->firstline) << 1; + xs_temp = x; + ys_temp = (vid->lastline - vid->firstline) << 1; - if ((xs_temp > 0) && (ys_temp > 0)) { - if (xs_temp < 64) xs_temp = 656; - if (ys_temp < 32) ys_temp = 400; - if (!enable_overscan) - xs_temp -= 16; + if ((xs_temp > 0) && (ys_temp > 0)) { + if (xs_temp < 64) + xs_temp = 656; + if (ys_temp < 32) + ys_temp = 400; + if (!enable_overscan) + xs_temp -= 16; - if (((xs_temp != xsize) || (ys_temp != ysize) || video_force_resize_get())) { - xsize = xs_temp; - ysize = ys_temp; - set_screen_size(xsize, ysize + (enable_overscan ? 16 : 0)); + if ((xs_temp != xsize) || (ys_temp != ysize) || video_force_resize_get()) { + xsize = xs_temp; + ysize = ys_temp; + set_screen_size(xsize, ysize + (enable_overscan ? 16 : 0)); - if (video_force_resize_get()) - video_force_resize_set(0); - } + if (video_force_resize_get()) + video_force_resize_set(0); + } - if (enable_overscan) { - if (!dev->is_sl2 && vid->composite) - video_blit_memtoscreen(0, (vid->firstline - 4) << 1, - xsize, ((vid->lastline - vid->firstline) + 8) << 1); - else - video_blit_memtoscreen_8(0, (vid->firstline - 4) << 1, - xsize, ((vid->lastline - vid->firstline) + 8) << 1); - } else { - if (!dev->is_sl2 && vid->composite) - video_blit_memtoscreen(8, vid->firstline << 1, - xsize, (vid->lastline - vid->firstline) << 1); - else - video_blit_memtoscreen_8(8, vid->firstline << 1, - xsize, (vid->lastline - vid->firstline) << 1); - } - } + if (enable_overscan) { + video_blit_memtoscreen(0, (vid->firstline - 4) << 1, + xsize, ((vid->lastline - vid->firstline) + 8) << 1); + } else { + video_blit_memtoscreen(8, vid->firstline << 1, + xsize, (vid->lastline - vid->firstline) << 1); + } + } - frames++; + frames++; - video_res_x = xsize; - video_res_y = ysize; - if ((vid->array[3] & 0x10) && (vid->mode & 1)) { /*320x200x16*/ - video_res_x /= 2; - video_bpp = 4; - } else if (vid->array[3] & 0x10) { /*160x200x16*/ - video_res_x /= 4; - video_bpp = 4; - } else if (vid->array[3] & 0x08) { /*640x200x4 - this implementation is a complete guess!*/ - video_bpp = 2; - } else if (vid->mode & 1) { - video_res_x /= 8; - video_res_y /= vid->crtc[9] + 1; - video_bpp = 0; - } else if (! (vid->mode & 2)) { - video_res_x /= 16; - video_res_y /= vid->crtc[9] + 1; - video_bpp = 0; - } else if (! (vid->mode & 16)) { - video_res_x /= 2; - video_bpp = 2; - } else { - video_bpp = 1; - } - } - vid->firstline = 1000; - vid->lastline = 0; - vid->blink++; - } - } else { - vid->sc++; - vid->sc &= 31; - vid->ma = vid->maback; - } - if ((vid->sc == (vid->crtc[10] & 31) || ((vid->crtc[8] & 3) == 3 && vid->sc == ((vid->crtc[10] & 31) >> 1)))) - vid->con = 1; + video_res_x = xsize; + video_res_y = ysize; + if ((vid->array[3] & 0x10) && (vid->mode & 1)) { /*320x200x16*/ + video_res_x /= 2; + video_bpp = 4; + } else if (vid->array[3] & 0x10) { /*160x200x16*/ + video_res_x /= 4; + video_bpp = 4; + } else if (vid->array[3] & 0x08) { /*640x200x4 - this implementation is a complete guess!*/ + video_bpp = 2; + } else if (vid->mode & 1) { + video_res_x /= 8; + video_res_y /= vid->crtc[9] + 1; + video_bpp = 0; + } else if (!(vid->mode & 2)) { + video_res_x /= 16; + video_res_y /= vid->crtc[9] + 1; + video_bpp = 0; + } else if (!(vid->mode & 16)) { + video_res_x /= 2; + video_bpp = 2; + } else { + video_bpp = 1; + } + } + vid->firstline = 1000; + vid->lastline = 0; + vid->blink++; + } + } else { + vid->sc++; + vid->sc &= 31; + vid->ma = vid->maback; + } + if (vid->sc == (vid->crtc[10] & 31) || ((vid->crtc[8] & 3) == 3 && vid->sc == ((vid->crtc[10] & 31) >> 1))) + vid->con = 1; } } - static void vid_speed_changed(void *priv) { - tandy_t *dev = (tandy_t *)priv; + tandy_t *dev = (tandy_t *) priv; recalc_timings(dev); } - static void vid_close(void *priv) { - tandy_t *dev = (tandy_t *)priv; + tandy_t *dev = (tandy_t *) priv; free(dev->vid); dev->vid = NULL; } - static void vid_init(tandy_t *dev) { - int display_type; + int display_type; t1kvid_t *vid; vid = malloc(sizeof(t1kvid_t)); memset(vid, 0x00, sizeof(t1kvid_t)); vid->memctrl = -1; - dev->vid = vid; + dev->vid = vid; video_inform(VIDEO_FLAG_TYPE_CGA, &timing_dram); - display_type = machine_get_config_int("display_type"); + display_type = machine_get_config_int("display_type"); vid->composite = (display_type != TANDY_RGB); cga_comp_init(1); if (dev->is_sl2) { - vid->b8000_limit = 0x8000; - vid->planar_ctrl = 4; - overscan_x = overscan_y = 16; + vid->b8000_limit = 0x8000; + vid->planar_ctrl = 4; + overscan_x = overscan_y = 16; - io_sethandler(0x0065, 1, vid_in,NULL,NULL, vid_out,NULL,NULL, dev); + io_sethandler(0x0065, 1, vid_in, NULL, NULL, vid_out, NULL, NULL, dev); } else - vid->b8000_mask = 0x3fff; + vid->b8000_mask = 0x3fff; timer_add(&vid->timer, vid_poll, dev, 1); mem_mapping_add(&vid->mapping, 0xb8000, 0x08000, - vid_read,NULL,NULL, vid_write,NULL,NULL, NULL, 0, dev); + vid_read, NULL, NULL, vid_write, NULL, NULL, NULL, 0, dev); io_sethandler(0x03d0, 16, - vid_in,NULL,NULL, vid_out,NULL,NULL, dev); + vid_in, NULL, NULL, vid_out, NULL, NULL, dev); } - -static const device_config_t vid_config[] = { +const device_config_t vid_config[] = { + // clang-format off { - "display_type", "Display type", CONFIG_SELECTION, "", TANDY_RGB, "", { 0 }, - { - { - "RGB", TANDY_RGB - }, - { - "Composite", TANDY_COMPOSITE - }, - { - "" - } - } + .name = "display_type", + .description = "Display type", + .type = CONFIG_SELECTION, + .default_string = "", + .default_int = TANDY_RGB, + .file_filter = "", + .spinner = { 0 }, + .selection = { + { .description = "RGB", .value = TANDY_RGB }, + { .description = "Composite", .value = TANDY_COMPOSITE }, + { .description = "" } + } }, - { - "", "", -1 - } + { .name = "", .description = "", .type = CONFIG_END } + // clang-format on }; - -static const device_t vid_device = { - "Tandy 1000", - "tandy1000_video", - 0, 0, - NULL, vid_close, NULL, - { NULL }, - vid_speed_changed, - NULL, - vid_config +const device_t vid_device = { + .name = "Tandy 1000", + .internal_name = "tandy1000_video", + .flags = 0, + .local = 0, + .init = NULL, + .close = vid_close, + .reset = NULL, + { .available = NULL }, + .speed_changed = vid_speed_changed, + .force_redraw = NULL, + .config = vid_config }; -static const device_t vid_device_hx = { - "Tandy 1000 HX", - "tandy1000_hx_video", - 0, 0, - NULL, vid_close, NULL, - { NULL }, - vid_speed_changed, - NULL, - vid_config +const device_t vid_device_hx = { + .name = "Tandy 1000 HX", + .internal_name = "tandy1000_hx_video", + .flags = 0, + .local = 0, + .init = NULL, + .close = vid_close, + .reset = NULL, + { .available = NULL }, + .speed_changed = vid_speed_changed, + .force_redraw = NULL, + .config = vid_config }; -static const device_t vid_device_sl = { - "Tandy 1000SL2", - "tandy1000_sl_video", - 0, 1, - NULL, vid_close, NULL, - { NULL }, - vid_speed_changed, - NULL, - NULL +const device_t vid_device_sl = { + .name = "Tandy 1000SL2", + .internal_name = "tandy1000_sl_video", + .flags = 0, + .local = 1, + .init = NULL, + .close = vid_close, + .reset = NULL, + { .available = NULL }, + .speed_changed = vid_speed_changed, + .force_redraw = NULL, + .config = NULL }; - -const device_t * -tandy1k_get_device(void) -{ - return &vid_device; -} - - -const device_t * -tandy1k_hx_get_device(void) -{ - return &vid_device_hx; -} - -const device_t * -tandy1k_sl_get_device(void) -{ - return &vid_device_sl; -} - - static void -eep_write(uint16_t addr, uint8_t val, void *priv) +eep_write(UNUSED(uint16_t addr), uint8_t val, void *priv) { - t1keep_t *eep = (t1keep_t *)priv; + t1keep_t *eep = (t1keep_t *) priv; - if ((val & 4) && !eep->clk) switch (eep->state) { - case EEPROM_IDLE: - switch (eep->count) { - case 0: - if (! (val & 3)) - eep->count = 1; - else - eep->count = 0; - break; + if ((val & 4) && !eep->clk) + switch (eep->state) { + case EEPROM_IDLE: + switch (eep->count) { + case 0: + if (!(val & 3)) + eep->count = 1; + else + eep->count = 0; + break; - case 1: - if ((val & 3) == 2) - eep->count = 2; - else - eep->count = 0; - break; + case 1: + if ((val & 3) == 2) + eep->count = 2; + else + eep->count = 0; + break; - case 2: - if ((val & 3) == 3) - eep->state = EEPROM_GET_OPERATION; - eep->count = 0; - break; - } - break; + case 2: + if ((val & 3) == 3) + eep->state = EEPROM_GET_OPERATION; + eep->count = 0; + break; - case EEPROM_GET_OPERATION: - eep->data = (eep->data << 1) | (val & 1); - eep->count++; - if (eep->count == 8) { - eep->count = 0; - eep->addr = eep->data & 0x3f; - switch (eep->data & 0xc0) { - case 0x40: - eep->state = EEPROM_WRITE; - break; + default: + break; + } + break; - case 0x80: - eep->state = EEPROM_READ; - eep->data = eep->store[eep->addr]; - break; + case EEPROM_GET_OPERATION: + eep->data = (eep->data << 1) | (val & 1); + eep->count++; + if (eep->count == 8) { + eep->count = 0; + eep->addr = eep->data & 0x3f; + switch (eep->data & 0xc0) { + case 0x40: + eep->state = EEPROM_WRITE; + break; - default: - eep->state = EEPROM_IDLE; - break; - } - } - break; + case 0x80: + eep->state = EEPROM_READ; + eep->data = eep->store[eep->addr]; + break; - case EEPROM_READ: - eep_data_out = eep->data & 0x8000; - eep->data <<= 1; - eep->count++; - if (eep->count == 16) { - eep->count = 0; - eep->state = EEPROM_IDLE; - } - break; + default: + eep->state = EEPROM_IDLE; + break; + } + } + break; - case EEPROM_WRITE: - eep->data = (eep->data << 1) | (val & 1); - eep->count++; - if (eep->count == 16) { - eep->count = 0; - eep->state = EEPROM_IDLE; - eep->store[eep->addr] = eep->data; - } - break; - } + case EEPROM_READ: + eep_data_out = eep->data & 0x8000; + eep->data <<= 1; + eep->count++; + if (eep->count == 16) { + eep->count = 0; + eep->state = EEPROM_IDLE; + } + break; + + case EEPROM_WRITE: + eep->data = (eep->data << 1) | (val & 1); + eep->count++; + if (eep->count == 16) { + eep->count = 0; + eep->state = EEPROM_IDLE; + eep->store[eep->addr] = eep->data; + } + break; + + default: + break; + } eep->clk = val & 4; } - static void * eep_init(const device_t *info) { t1keep_t *eep; - FILE *f = NULL; + FILE *fp = NULL; - eep = (t1keep_t *)malloc(sizeof(t1keep_t)); + eep = (t1keep_t *) malloc(sizeof(t1keep_t)); memset(eep, 0x00, sizeof(t1keep_t)); switch (info->local) { - case TYPE_TANDY1000HX: - eep->path = "tandy1000hx.bin"; - break; + case TYPE_TANDY1000HX: + eep->path = "tandy1000hx.bin"; + break; - case TYPE_TANDY1000SL2: - eep->path = "tandy1000sl2.bin"; - break; + case TYPE_TANDY1000SL2: + eep->path = "tandy1000sl2.bin"; + break; + default: + break; } - f = nvr_fopen(eep->path, "rb"); - if (f != NULL) { - if (fread(eep->store, 1, 128, f) != 128) - fatal("eep_init(): Error reading Tandy EEPROM\n"); - (void)fclose(f); + fp = nvr_fopen(eep->path, "rb"); + if (fp != NULL) { + if (fread(eep->store, 1, 128, fp) != 128) + fatal("eep_init(): Error reading Tandy EEPROM\n"); + (void) fclose(fp); } else - memset(eep->store, 0x00, 128); + memset(eep->store, 0x00, 128); - io_sethandler(0x037c, 1, NULL,NULL,NULL, eep_write,NULL,NULL, eep); + io_sethandler(0x037c, 1, NULL, NULL, NULL, eep_write, NULL, NULL, eep); - return(eep); + return eep; } - static void eep_close(void *priv) { - t1keep_t *eep = (t1keep_t *)priv; - FILE *f = NULL; + t1keep_t *eep = (t1keep_t *) priv; + FILE *fp = NULL; - f = nvr_fopen(eep->path, "wb"); - if (f != NULL) { - (void)fwrite(eep->store, 128, 1, f); - (void)fclose(f); + fp = nvr_fopen(eep->path, "wb"); + if (fp != NULL) { + (void) fwrite(eep->store, 128, 1, fp); + (void) fclose(fp); } free(eep); } - static const device_t eep_1000hx_device = { - "Tandy 1000HX EEPROM", - "eep_1000hx", - 0, TYPE_TANDY1000HX, - eep_init, eep_close, NULL, - { NULL }, NULL, NULL, - NULL + .name = "Tandy 1000HX EEPROM", + .internal_name = "eep_1000hx", + .flags = 0, + .local = TYPE_TANDY1000HX, + .init = eep_init, + .close = eep_close, + .reset = NULL, + { .available = NULL }, + .speed_changed = NULL, + .force_redraw = NULL, + .config = NULL }; - static const device_t eep_1000sl2_device = { - "Tandy 1000SL2 EEPROM", - "eep_1000sl2", - 0, TYPE_TANDY1000SL2, - eep_init, eep_close, NULL, - { NULL }, NULL, NULL, - NULL + .name = "Tandy 1000SL2 EEPROM", + .internal_name = "eep_1000sl2", + .flags = 0, + .local = TYPE_TANDY1000SL2, + .init = eep_init, + .close = eep_close, + .reset = NULL, + { .available = NULL }, + .speed_changed = NULL, + .force_redraw = NULL, + .config = NULL }; - static void tandy_write(uint16_t addr, uint8_t val, void *priv) { - tandy_t *dev = (tandy_t *)priv; + tandy_t *dev = (tandy_t *) priv; switch (addr) { - case 0x00a0: - mem_mapping_set_addr(&dev->ram_mapping, - ((val >> 1) & 7) * 128 * 1024, 0x20000); - dev->ram_bank = val; - break; + case 0x00a0: + if (val & 0x10) { + dev->base = (mem_size - 256) * 1024; + dev->mask = 0x3ffff; + mem_mapping_set_addr(&ram_low_mapping, 0, dev->base); + mem_mapping_set_addr(&dev->ram_mapping, + ((val >> 1) & 7) * 128 * 1024, 0x40000); + } else { + dev->base = (mem_size - 128) * 1024; + dev->mask = 0x1ffff; + mem_mapping_set_addr(&ram_low_mapping, 0, dev->base); + mem_mapping_set_addr(&dev->ram_mapping, + ((val >> 1) & 7) * 128 * 1024, 0x20000); + } + dev->ram_bank = val; + break; - case 0xffe8: - if ((val & 0xe) == 0xe) - mem_mapping_disable(&dev->ram_mapping); - else - mem_mapping_set_addr(&dev->ram_mapping, - ((val >> 1) & 7) * 128 * 1024, - 0x20000); - recalc_address_sl(dev); - dev->ram_bank = val; - break; + case 0xffe8: + if ((val & 0xe) == 0xe) + mem_mapping_disable(&dev->ram_mapping); + else + mem_mapping_set_addr(&dev->ram_mapping, + ((val >> 1) & 7) * 128 * 1024, + 0x20000); + recalc_address_sl(dev); + dev->ram_bank = val; + break; - case 0xffea: - dev->rom_bank = val; - dev->rom_offset = ((val ^ 4) & 7) * 0x10000; - mem_mapping_set_exec(&dev->rom_mapping, - &dev->rom[dev->rom_offset]); + case 0xffea: + dev->rom_bank = val; + dev->rom_offset = ((val ^ 4) & 7) * 0x10000; + mem_mapping_set_exec(&dev->rom_mapping, + &dev->rom[dev->rom_offset]); + break; + + default: + break; } } - static uint8_t tandy_read(uint16_t addr, void *priv) { - tandy_t *dev = (tandy_t *)priv; - uint8_t ret = 0xff; + const tandy_t *dev = (tandy_t *) priv; + uint8_t ret = 0xff; switch (addr) { - case 0x00a0: - ret = dev->ram_bank; - break; + case 0x00a0: + ret = dev->ram_bank; + break; - case 0xffe8: - ret = dev->ram_bank; - break; + case 0xffe8: + ret = dev->ram_bank; + break; - case 0xffea: - ret = (dev->rom_bank ^ 0x10); - break; + case 0xffea: + ret = (dev->rom_bank ^ 0x10); + break; + + default: + break; } - return(ret); + return ret; } - static void write_ram(uint32_t addr, uint8_t val, void *priv) { - tandy_t *dev = (tandy_t *)priv; + const tandy_t *dev = (tandy_t *) priv; - ram[dev->base + (addr & 0x1ffff)] = val; + ram[dev->base + (addr & dev->mask)] = val; } - static uint8_t read_ram(uint32_t addr, void *priv) { - tandy_t *dev = (tandy_t *)priv; + const tandy_t *dev = (tandy_t *) priv; - return(ram[dev->base + (addr & 0x1ffff)]); + return (ram[dev->base + (addr & dev->mask)]); } - static uint8_t read_rom(uint32_t addr, void *priv) { - tandy_t *dev = (tandy_t *)priv; - uint32_t addr2 = (addr & 0xffff) + dev->rom_offset; + const tandy_t *dev = (tandy_t *) priv; + uint32_t addr2 = (addr & 0xffff) + dev->rom_offset; - return(dev->rom[addr2]); + return (dev->rom[addr2]); } - static uint16_t read_romw(uint32_t addr, void *priv) { - tandy_t *dev = (tandy_t *)priv; + tandy_t *dev = (tandy_t *) priv; uint32_t addr2 = (addr & 0xffff) + dev->rom_offset; - return(*(uint16_t *)&dev->rom[addr2]); + return (*(uint16_t *) &dev->rom[addr2]); } - static uint32_t read_roml(uint32_t addr, void *priv) { - tandy_t *dev = (tandy_t *)priv; + tandy_t *dev = (tandy_t *) priv; - return(*(uint32_t *)&dev->rom[addr]); + return (*(uint32_t *) &dev->rom[addr]); } - static void init_rom(tandy_t *dev) { - dev->rom = (uint8_t *)malloc(0x80000); + dev->rom = (uint8_t *) malloc(0x80000); #if 1 - if (! rom_load_interleaved("roms/machines/tandy1000sl2/8079047.hu1", - "roms/machines/tandy1000sl2/8079048.hu2", - 0x000000, 0x80000, 0, dev->rom)) { - tandy_log("TANDY: unable to load BIOS for 1000/SL2 !\n"); - free(dev->rom); - dev->rom = NULL; - return; + if (!rom_load_interleaved("roms/machines/tandy1000sl2/8079047.hu1", + "roms/machines/tandy1000sl2/8079048.hu2", + 0x000000, 0x80000, 0, dev->rom)) { + tandy_log("TANDY: unable to load BIOS for 1000/SL2 !\n"); + free(dev->rom); + dev->rom = NULL; + return; } #else f = rom_fopen("roms/machines/tandy1000sl2/8079047.hu1", "rb"); ff = rom_fopen("roms/machines/tandy1000sl2/8079048.hu2", "rb"); for (c = 0x0000; c < 0x80000; c += 2) { - dev->rom[c] = getc(f); - dev->rom[c + 1] = getc(ff); + dev->rom[c] = getc(f); + dev->rom[c + 1] = getc(ff); } fclose(ff); fclose(f); #endif mem_mapping_add(&dev->rom_mapping, 0xe0000, 0x10000, - read_rom, read_romw, read_roml, NULL, NULL, NULL, - dev->rom, MEM_MAPPING_EXTERNAL, dev); + read_rom, read_romw, read_roml, NULL, NULL, NULL, + dev->rom, MEM_MAPPING_EXTERNAL, dev); } - static void machine_tandy1k_init(const machine_t *model, int type) { @@ -1516,47 +1474,52 @@ machine_tandy1k_init(const machine_t *model, int type) * 0xFFE8 (SL2), so we remove it from the main mapping. */ dev->base = (mem_size - 128) * 1024; - mem_mapping_add(&dev->ram_mapping, 0x80000, 0x20000, - read_ram,NULL,NULL, write_ram,NULL,NULL, NULL, 0, dev); + dev->mask = 0x1ffff; + mem_mapping_add(&dev->ram_mapping, 0x60000, 0x20000, + read_ram, NULL, NULL, write_ram, NULL, NULL, NULL, + MEM_MAPPING_INTERNAL, dev); mem_mapping_set_addr(&ram_low_mapping, 0, dev->base); device_add(&keyboard_tandy_device); - if (fdc_type == FDC_INTERNAL) - device_add(&fdc_xt_tandy_device); + if (fdc_type == FDC_INTERNAL) + device_add(&fdc_xt_tandy_device); - video_reset(gfxcard); + video_reset(gfxcard[0]); - switch(type) { - case TYPE_TANDY: - keyboard_set_table(scancode_tandy); - io_sethandler(0x00a0, 1, - tandy_read,NULL,NULL,tandy_write,NULL,NULL,dev); - vid_init(dev); - device_add_ex(&vid_device, dev); - device_add(&sn76489_device); - break; + switch (type) { + case TYPE_TANDY: + keyboard_set_table(scancode_tandy); + io_sethandler(0x00a0, 1, + tandy_read, NULL, NULL, tandy_write, NULL, NULL, dev); + vid_init(dev); + device_add_ex(&vid_device, dev); + device_add(&sn76489_device); + break; - case TYPE_TANDY1000HX: - keyboard_set_table(scancode_tandy); - io_sethandler(0x00a0, 1, - tandy_read,NULL,NULL,tandy_write,NULL,NULL,dev); - vid_init(dev); - device_add_ex(&vid_device, dev); - device_add(&ncr8496_device); - device_add(&eep_1000hx_device); - break; + case TYPE_TANDY1000HX: + keyboard_set_table(scancode_tandy); + io_sethandler(0x00a0, 1, + tandy_read, NULL, NULL, tandy_write, NULL, NULL, dev); + vid_init(dev); + device_add_ex(&vid_device, dev); + device_add(&ncr8496_device); + device_add(&eep_1000hx_device); + break; - case TYPE_TANDY1000SL2: - dev->is_sl2 = 1; - init_rom(dev); - io_sethandler(0xffe8, 8, - tandy_read,NULL,NULL,tandy_write,NULL,NULL,dev); - vid_init(dev); - device_add_ex(&vid_device_sl, dev); - device_add(&pssj_device); - device_add(&eep_1000sl2_device); - break; + case TYPE_TANDY1000SL2: + dev->is_sl2 = 1; + init_rom(dev); + io_sethandler(0xffe8, 8, + tandy_read, NULL, NULL, tandy_write, NULL, NULL, dev); + vid_init(dev); + device_add_ex(&vid_device_sl, dev); + device_add(&pssj_device); + device_add(&eep_1000sl2_device); + break; + + default: + break; } standalone_gameport_type = &gameport_device; @@ -1564,59 +1527,55 @@ machine_tandy1k_init(const machine_t *model, int type) eep_data_out = 0x0000; } - int tandy1k_eeprom_read(void) { - return(eep_data_out); + return eep_data_out; } - int machine_tandy_init(const machine_t *model) { int ret; ret = bios_load_linearr("roms/machines/tandy/tandy1t1.020", - 0x000f0000, 131072, 0); + 0x000f0000, 131072, 0); if (bios_only || !ret) - return ret; + return ret; machine_tandy1k_init(model, TYPE_TANDY); return ret; } - int machine_tandy1000hx_init(const machine_t *model) { int ret; ret = bios_load_linear("roms/machines/tandy1000hx/v020000.u12", - 0x000e0000, 131072, 0); + 0x000e0000, 131072, 0); if (bios_only || !ret) - return ret; + return ret; machine_tandy1k_init(model, TYPE_TANDY1000HX); return ret; } - int machine_tandy1000sl2_init(const machine_t *model) { int ret; ret = bios_load_interleaved("roms/machines/tandy1000sl2/8079047.hu1", - "roms/machines/tandy1000sl2/8079048.hu2", - 0x000f0000, 65536, 0x18000); + "roms/machines/tandy1000sl2/8079048.hu2", + 0x000f0000, 65536, 0x18000); if (bios_only || !ret) - return ret; + return ret; machine_tandy1k_init(model, TYPE_TANDY1000SL2); diff --git a/src/machine/m_v86p.c b/src/machine/m_v86p.c index 022c9baec..54af9b053 100644 --- a/src/machine/m_v86p.c +++ b/src/machine/m_v86p.c @@ -1,16 +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. + * 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. + * This file is part of the 86Box distribution. * - * Victor V86P portable computer emulation. + * Victor V86P portable computer emulation. * - * Author: Lubomir Rintel, + * Authors: Lubomir Rintel, * - * Copyright 2021 Lubomir Rintel. + * Copyright 2021 Lubomir Rintel. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -19,7 +19,7 @@ * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * General Public License for more details. * * You should have received a copy of the GNU General Public License @@ -42,6 +42,7 @@ #include <86box/fdd.h> #include <86box/fdc.h> #include <86box/fdc_ext.h> +#include <86box/hdc.h> #include <86box/keyboard.h> #include <86box/chipset.h> #include <86box/sio.h> @@ -50,47 +51,51 @@ int machine_v86p_init(const machine_t *model) { - int ret, rom = 0; + int ret; + int rom_id = 0; - ret = bios_load_interleavedr("roms/machines/v86p/INTEL8086AWD_BIOS_S3.1_V86P_122089_Even.rom", - "roms/machines/v86p/INTEL8086AWD_BIOS_S3.1_V86P_122089_Odd.rom", - 0x000f8000, 65536, 0); + ret = bios_load_interleavedr("roms/machines/v86p/INTEL8086AWD_BIOS_S3.1_V86P_122089_Even.rom", + "roms/machines/v86p/INTEL8086AWD_BIOS_S3.1_V86P_122089_Odd.rom", + 0x000f8000, 65536, 0); - if (!ret) { - /* Try an older version of the BIOS. */ - rom = 1; - ret = bios_load_interleavedr("roms/machines/v86p/INTEL8086AWD_BIOS_S3.1_V86P_090489_Even.rom", - "roms/machines/v86p/INTEL8086AWD_BIOS_S3.1_V86P_090489_Odd.rom", - 0x000f8000, 65536, 0); - } + if (!ret) { + /* Try an older version of the BIOS. */ + rom_id = 1; + ret = bios_load_interleavedr("roms/machines/v86p/INTEL8086AWD_BIOS_S3.1_V86P_090489_Even.rom", + "roms/machines/v86p/INTEL8086AWD_BIOS_S3.1_V86P_090489_Odd.rom", + 0x000f8000, 65536, 0); + } - if (!ret) { - /* Try JVERNET's BIOS. */ - rom = 2; - ret = bios_load_linear("roms/machines/v86p/V86P.ROM", - 0x000f0000, 65536, 0); - } + if (!ret) { + /* Try JVERNET's BIOS. */ + rom_id = 2; + ret = bios_load_linear("roms/machines/v86p/V86P.ROM", + 0x000f0000, 65536, 0); + } - if (bios_only || !ret) - return ret; + if (bios_only || !ret) + return ret; - if (rom == 2) - loadfont("roms/machines/v86p/V86P.FON", 8); - else - loadfont("roms/machines/v86p/v86pfont.rom", 8); + if (rom_id == 2) + loadfont("roms/machines/v86p/V86P.FON", 8); + else + loadfont("roms/machines/v86p/v86pfont.rom", 8); - machine_common_init(model); + machine_common_init(model); - device_add(&ct_82c100_device); - device_add(&f82c606_device); + device_add(&ct_82c100_device); + device_add(&f82c606_device); - device_add(&keyboard_xt_device); + device_add(&keyboard_xt_device); - if (fdc_type == FDC_INTERNAL) - device_add(&fdc_xt_device); + if (fdc_type == FDC_INTERNAL) + device_add(&fdc_xt_device); - if (gfxcard == VID_INTERNAL) - device_add(&f82c425_video_device); + if (gfxcard[0] == VID_INTERNAL) + device_add(&f82c425_video_device); - return ret; + if (hdc_current <= 1) + device_add(&st506_xt_victor_v86p_device); + + return ret; } diff --git a/src/machine/m_xt.c b/src/machine/m_xt.c index 1e4e7bd39..a374b58f3 100644 --- a/src/machine/m_xt.c +++ b/src/machine/m_xt.c @@ -18,42 +18,44 @@ #include <86box/rom.h> #include <86box/machine.h> #include <86box/chipset.h> +#include <86box/port_6x.h> + +extern const device_t vendex_xt_rtc_onboard_device; static void machine_xt_common_init(const machine_t *model) { machine_common_init(model); - pit_ctr_set_out_func(&pit->counters[1], pit_refresh_timer_xt); + pit_devs[0].set_out_func(pit_devs[0].data, 1, pit_refresh_timer_xt); + + if (fdc_type == FDC_INTERNAL) + device_add(&fdc_xt_device); - if (fdc_type == FDC_INTERNAL) - device_add(&fdc_xt_device); - nmi_init(); standalone_gameport_type = &gameport_device; } - int machine_pc_init(const machine_t *model) { int ret; ret = bios_load_linear("roms/machines/ibmpc/BIOS_5150_24APR81_U33.BIN", - 0x000fe000, 40960, 0); + 0x000fe000, 40960, 0); if (ret) { - bios_load_aux_linear("roms/machines/ibmpc/IBM 5150 - Cassette BASIC version C1.00 - U29 - 5700019.bin", - 0x000f6000, 8192, 0); - bios_load_aux_linear("roms/machines/ibmpc/IBM 5150 - Cassette BASIC version C1.00 - U30 - 5700027.bin", - 0x000f8000, 8192, 0); - bios_load_aux_linear("roms/machines/ibmpc/IBM 5150 - Cassette BASIC version C1.00 - U31 - 5700035.bin", - 0x000fa000, 8192, 0); - bios_load_aux_linear("roms/machines/ibmpc/IBM 5150 - Cassette BASIC version C1.00 - U32 - 5700043.bin", - 0x000fc000, 8192, 0); + bios_load_aux_linear("roms/machines/ibmpc/IBM 5150 - Cassette BASIC version C1.00 - U29 - 5700019.bin", + 0x000f6000, 8192, 0); + bios_load_aux_linear("roms/machines/ibmpc/IBM 5150 - Cassette BASIC version C1.00 - U30 - 5700027.bin", + 0x000f8000, 8192, 0); + bios_load_aux_linear("roms/machines/ibmpc/IBM 5150 - Cassette BASIC version C1.00 - U31 - 5700035.bin", + 0x000fa000, 8192, 0); + bios_load_aux_linear("roms/machines/ibmpc/IBM 5150 - Cassette BASIC version C1.00 - U32 - 5700043.bin", + 0x000fc000, 8192, 0); } if (bios_only || !ret) - return ret; + return ret; device_add(&keyboard_pc_device); @@ -62,31 +64,31 @@ machine_pc_init(const machine_t *model) return ret; } - int machine_pc82_init(const machine_t *model) { - int ret, ret2; + int ret; + int ret2; ret = bios_load_linear("roms/machines/ibmpc82/pc102782.bin", - 0x000fe000, 40960, 0); + 0x000fe000, 40960, 0); if (ret) { - ret2 = bios_load_aux_linear("roms/machines/ibmpc82/ibm-basic-1.10.rom", - 0x000f6000, 32768, 0); - if (!ret2) { - bios_load_aux_linear("roms/machines/ibmpc82/basicc11.f6", - 0x000f6000, 8192, 0); - bios_load_aux_linear("roms/machines/ibmpc82/basicc11.f8", - 0x000f8000, 8192, 0); - bios_load_aux_linear("roms/machines/ibmpc82/basicc11.fa", - 0x000fa000, 8192, 0); - bios_load_aux_linear("roms/machines/ibmpc82/basicc11.fc", - 0x000fc000, 8192, 0); - } + ret2 = bios_load_aux_linear("roms/machines/ibmpc82/ibm-basic-1.10.rom", + 0x000f6000, 32768, 0); + if (!ret2) { + bios_load_aux_linear("roms/machines/ibmpc82/basicc11.f6", + 0x000f6000, 8192, 0); + bios_load_aux_linear("roms/machines/ibmpc82/basicc11.f8", + 0x000f8000, 8192, 0); + bios_load_aux_linear("roms/machines/ibmpc82/basicc11.fa", + 0x000fa000, 8192, 0); + bios_load_aux_linear("roms/machines/ibmpc82/basicc11.fc", + 0x000fc000, 8192, 0); + } } if (bios_only || !ret) - return ret; + return ret; device_add(&keyboard_pc82_device); device_add(&ibm_5161_device); @@ -96,7 +98,6 @@ machine_pc82_init(const machine_t *model) return ret; } - static void machine_xt_init_ex(const machine_t *model) { @@ -105,27 +106,26 @@ machine_xt_init_ex(const machine_t *model) machine_xt_common_init(model); } - int machine_xt_init(const machine_t *model) { int ret; ret = bios_load_linear("roms/machines/ibmxt/xt.rom", - 0x000f0000, 65536, 0); + 0x000f0000, 65536, 0); if (!ret) { - ret = bios_load_linear("roms/machines/ibmxt/1501512.u18", - 0x000fe000, 65536, 0x6000); - if (ret) { - bios_load_aux_linear("roms/machines/ibmxt/1501512.u18", - 0x000f8000, 24576, 0); - bios_load_aux_linear("roms/machines/ibmxt/5000027.u19", - 0x000f0000, 32768, 0); - } + ret = bios_load_linear("roms/machines/ibmxt/1501512.u18", + 0x000fe000, 65536, 0x6000); + if (ret) { + bios_load_aux_linear("roms/machines/ibmxt/1501512.u18", + 0x000f8000, 24576, 0); + bios_load_aux_linear("roms/machines/ibmxt/5000027.u19", + 0x000f0000, 32768, 0); + } } if (bios_only || !ret) - return ret; + return ret; machine_xt_init_ex(model); @@ -134,17 +134,16 @@ machine_xt_init(const machine_t *model) return ret; } - int machine_genxt_init(const machine_t *model) { int ret; ret = bios_load_linear("roms/machines/genxt/pcxt.rom", - 0x000fe000, 8192, 0); + 0x000fe000, 8192, 0); if (bios_only || !ret) - return ret; + return ret; machine_xt_init_ex(model); @@ -157,16 +156,16 @@ machine_xt86_init(const machine_t *model) int ret; ret = bios_load_linear("roms/machines/ibmxt86/BIOS_5160_09MAY86_U18_59X7268_62X0890_27256_F800.BIN", - 0x000fe000, 65536, 0x6000); + 0x000fe000, 65536, 0x6000); if (ret) { - (void) bios_load_aux_linear("roms/machines/ibmxt86/BIOS_5160_09MAY86_U18_59X7268_62X0890_27256_F800.BIN", - 0x000f8000, 24576, 0); - (void) bios_load_aux_linear("roms/machines/ibmxt86/BIOS_5160_09MAY86_U19_62X0819_68X4370_27256_F000.BIN", - 0x000f0000, 32768, 0); + (void) bios_load_aux_linear("roms/machines/ibmxt86/BIOS_5160_09MAY86_U18_59X7268_62X0890_27256_F800.BIN", + 0x000f8000, 24576, 0); + (void) bios_load_aux_linear("roms/machines/ibmxt86/BIOS_5160_09MAY86_U19_62X0819_68X4370_27256_F000.BIN", + 0x000f0000, 32768, 0); } if (bios_only || !ret) - return ret; + return ret; device_add(&keyboard_xt86_device); device_add(&ibm_5161_device); @@ -176,11 +175,10 @@ machine_xt86_init(const machine_t *model) return ret; } - static void machine_xt_clone_init(const machine_t *model) { - device_add(&keyboard_xt86_device); + device_add(&keyboard_xtclone_device); machine_xt_common_init(model); } @@ -191,10 +189,10 @@ machine_xt_americxt_init(const machine_t *model) int ret; ret = bios_load_linear("roms/machines/americxt/AMERICXT.ROM", - 0x000fe000, 8192, 0); + 0x000fe000, 8192, 0); if (bios_only || !ret) - return ret; + return ret; machine_xt_clone_init(model); @@ -207,16 +205,31 @@ machine_xt_amixt_init(const machine_t *model) int ret; ret = bios_load_linear("roms/machines/amixt/ami_8088_bios_31jan89.bin", - 0x000fe000, 8192, 0); + 0x000fe000, 8192, 0); if (bios_only || !ret) - return ret; + return ret; machine_xt_clone_init(model); return ret; } +int +machine_xt_znic_init(const machine_t *model) +{ + int ret; + + ret = bios_load_linear("roms/machines/znic/ibmzen.rom", + 0x000fe000, 8192, 0); + + if (bios_only || !ret) + return ret; + + machine_xt_clone_init(model); + + return ret; +} int machine_xt_dtk_init(const machine_t *model) @@ -224,106 +237,151 @@ machine_xt_dtk_init(const machine_t *model) int ret; ret = bios_load_linear("roms/machines/dtk/dtk_erso_2.42_2764.bin", - 0x000fe000, 8192, 0); + 0x000fe000, 8192, 0); if (bios_only || !ret) - return ret; + return ret; machine_xt_clone_init(model); return ret; } - int machine_xt_jukopc_init(const machine_t *model) { int ret; ret = bios_load_linear("roms/machines/jukopc/000o001.bin", - 0x000fe000, 8192, 0); + 0x000fe000, 8192, 0); if (bios_only || !ret) - return ret; + return ret; machine_xt_clone_init(model); return ret; } - int machine_xt_openxt_init(const machine_t *model) { int ret; ret = bios_load_linear("roms/machines/openxt/pcxt31.bin", - 0x000fe000, 8192, 0); + 0x000fe000, 8192, 0); if (bios_only || !ret) - return ret; + return ret; machine_xt_clone_init(model); return ret; } - int machine_xt_pcxt_init(const machine_t *model) { int ret; ret = bios_load_linear("roms/machines/pcxt/u18.rom", - 0x000f8000, 65536, 0); + 0x000f8000, 65536, 0); if (ret) { - bios_load_aux_linear("roms/machines/pcxt/u19.rom", - 0x000f0000, 32768, 0); + bios_load_aux_linear("roms/machines/pcxt/u19.rom", + 0x000f0000, 32768, 0); } if (bios_only || !ret) - return ret; + return ret; machine_xt_clone_init(model); return ret; } - int machine_xt_pxxt_init(const machine_t *model) { int ret; ret = bios_load_linear("roms/machines/pxxt/000p001.bin", - 0x000fe000, 8192, 0); + 0x000fe000, 8192, 0); if (bios_only || !ret) - return ret; + return ret; - machine_xt_clone_init(model); + device_add(&keyboard_xt_device); + + machine_xt_common_init(model); return ret; } - int machine_xt_iskra3104_init(const machine_t *model) { int ret; ret = bios_load_interleaved("roms/machines/iskra3104/198.bin", - "roms/machines/iskra3104/199.bin", - 0x000fc000, 16384, 0); + "roms/machines/iskra3104/199.bin", + 0x000fc000, 16384, 0); if (bios_only || !ret) - return ret; + return ret; machine_xt_clone_init(model); return ret; } +int +machine_xt_pravetz16_imko4_init(const machine_t *model) +{ + int ret; + + ret = bios_load_linear("roms/machines/pravetz16/BIOS_IMKO4_FE00.BIN", + 0x000fe000, 65536, 0); + if (ret) { + bios_load_aux_linear("roms/machines/pravetz16/BIOS_IMKO4_F400.BIN", + 0x000f4000, 8192, 0); + + bios_load_aux_linear("roms/machines/pravetz16/BIOS_IMKO4_F600.BIN", + 0x000f6000, 8192, 0); + + bios_load_aux_linear("roms/machines/pravetz16/BIOS_IMKO4_FA00.BIN", + 0x000fa000, 8192, 0); + + bios_load_aux_linear("roms/machines/pravetz16/BIOS_IMKO4_F800.BIN", + 0x000f8000, 8192, 0); + + bios_load_aux_linear("roms/machines/pravetz16/BIOS_IMKO4_FC00.BIN", + 0x000fc000, 8192, 0); + } + + if (bios_only || !ret) + return ret; + + device_add(&keyboard_pravetz_device); + + machine_xt_common_init(model); + + return ret; +} + +int +machine_xt_micoms_xl7turbo_init(const machine_t *model) +{ + int ret; + + ret = bios_load_linear("roms/machines/mxl7t/XL7_TURBO.BIN", + 0x000fe000, 8192, 0); + + if (bios_only || !ret) + return ret; + + machine_xt_init_ex(model); + return ret; +} int machine_xt_pc4i_init(const machine_t *model) @@ -331,27 +389,26 @@ machine_xt_pc4i_init(const machine_t *model) int ret; ret = bios_load_linear("roms/machines/pc4i/NCR_PC4i_BIOSROM_1985.BIN", - 0x000fc000, 16384, 0); + 0x000fc000, 16384, 0); if (bios_only || !ret) - return ret; + return ret; machine_xt_clone_init(model); return ret; } - int machine_xt_mpc1600_init(const machine_t *model) { int ret; ret = bios_load_linear("roms/machines/mpc1600/mpc4.34_merged.bin", - 0x000fc000, 16384, 0); - + 0x000fc000, 16384, 0); + if (bios_only || !ret) - return ret; + return ret; device_add(&keyboard_pc82_device); @@ -360,22 +417,21 @@ machine_xt_mpc1600_init(const machine_t *model) return ret; } - int machine_xt_pcspirit_init(const machine_t *model) { int ret; ret = bios_load_linear("roms/machines/pcspirit/u1101.bin", - 0x000fe000, 16384, 0); - + 0x000fe000, 16384, 0); + if (ret) { - bios_load_aux_linear("roms/machines/pcspirit/u1103.bin", - 0x000fc000, 8192, 0); + bios_load_aux_linear("roms/machines/pcspirit/u1103.bin", + 0x000fc000, 8192, 0); } if (bios_only || !ret) - return ret; + return ret; device_add(&keyboard_pc82_device); @@ -384,17 +440,16 @@ machine_xt_pcspirit_init(const machine_t *model) return ret; } - int machine_xt_pc700_init(const machine_t *model) { int ret; ret = bios_load_linear("roms/machines/pc700/multitech pc-700 3.1.bin", - 0x000fe000, 8192, 0); + 0x000fe000, 8192, 0); if (bios_only || !ret) - return ret; + return ret; device_add(&keyboard_pc_device); @@ -403,17 +458,16 @@ machine_xt_pc700_init(const machine_t *model) return ret; } - int -machine_xt_pc500_init(const machine_t* model) +machine_xt_pc500_init(const machine_t *model) { int ret; ret = bios_load_linear("roms/machines/pc500/rom404.bin", - 0x000f8000, 32768, 0); + 0x000f8000, 32768, 0); if (bios_only || !ret) - return ret; + return ret; device_add(&keyboard_pc_device); @@ -421,3 +475,168 @@ machine_xt_pc500_init(const machine_t* model) return ret; } + +int +machine_xt_vendex_init(const machine_t *model) +{ + int ret; + + ret = bios_load_linear("roms/machines/vendex/Vendex Turbo 888 XT - ROM BIOS - VER 2.03C.bin", + 0x000fc000, 16384, 0); + + if (bios_only || !ret) + return ret; + + machine_xt_clone_init(model); + device_add(&vendex_xt_rtc_onboard_device); + + return ret; +} + +static void +machine_xt_hyundai_common_init(const machine_t *model) +{ + device_add(&keyboard_xt_hyundai_device); + + machine_xt_common_init(model); +} + +int +machine_xt_super16t_init(const machine_t *model) +{ + int ret; + + ret = bios_load_linear("roms/machines/super16t/Hyundai SUPER-16T - System BIOS HEA v1.12Ta (16k)(MBM27128)(1986).BIN", + 0x000fc000, 16384, 0); + + if (bios_only || !ret) + return ret; + + machine_xt_hyundai_common_init(model); + + /* On-board FDC cannot be disabled */ + device_add(&fdc_xt_device); + + return ret; +} + +int +machine_xt_super16te_init(const machine_t *model) +{ + int ret; + + ret = bios_load_linear("roms/machines/super16te/Hyundai SUPER-16TE - System BIOS v2.00Id (16k)(D27128A)(1989).BIN", + 0x000fc000, 16384, 0); + + if (bios_only || !ret) + return ret; + + machine_xt_hyundai_common_init(model); + + /* On-board FDC cannot be disabled */ + device_add(&fdc_xt_device); + + return ret; +} + +int +machine_xt_top88_init(const machine_t *model) +{ + int ret; + + ret = bios_load_linear("roms/machines/top88/Hyosung Topstar 88T - BIOS version 3.0.bin", + 0x000fc000, 16384, 0); + + if (bios_only || !ret) + return ret; + + machine_xt_clone_init(model); + + /* On-board FDC cannot be disabled */ + device_add(&fdc_xt_device); + + return ret; +} + +int +machine_xt_kaypropc_init(const machine_t *model) +{ + int ret; + + ret = bios_load_linear("roms/machines/kaypropc/Kaypro_v2.03K.bin", + 0x000fe000, 8192, 0); + + if (bios_only || !ret) + return ret; + + machine_xt_clone_init(model); + + return ret; +} + +int +machine_xt_sansx16_init(const machine_t *model) +{ + int ret; + + ret = bios_load_linear("roms/machines/sansx16/tmm27128ad.bin.bin", + 0x000fc000, 16384, 0); + + if (bios_only || !ret) + return ret; + + machine_xt_clone_init(model); + + /* On-board FDC cannot be disabled */ + device_add(&fdc_xt_device); + + return ret; +} + +int +machine_xt_bw230_init(const machine_t *model) +{ + int ret; + + ret = bios_load_linear("roms/machines/bw230/bondwell.bin", + 0x000fe000, 8192, 0); + + if (bios_only || !ret) + return ret; + + machine_xt_clone_init(model); + + return ret; +} + +int +machine_xt_v20xt_init(const machine_t *model) +{ + int ret; + + ret = bios_load_linear("roms/machines/v20xt/V20XTBios.bin", + 0x000fe000, 8192, 0); + + if (bios_only || !ret) + return ret; + + machine_xt_clone_init(model); + + return ret; +} + +int +machine_xt_pb8810_init(const machine_t *model) +{ + int ret; + + ret = bios_load_linear("roms/machines/pb8810/pb8088-8810-633acc631aba0345517682.bin", + 0x000fc000, 16384, 0); + + if (bios_only || !ret) + return ret; + + machine_xt_clone_init(model); + + return ret; +} diff --git a/src/machine/m_xt_compaq.c b/src/machine/m_xt_compaq.c index 5950ec3f9..f5dca48a7 100644 --- a/src/machine/m_xt_compaq.c +++ b/src/machine/m_xt_compaq.c @@ -1,21 +1,21 @@ /* - * 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. + * 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. + * This file is part of the 86Box distribution. * - * Emulation of various Compaq XT-class PC's. + * Emulation of various Compaq XT-class PC's. * * * - * Authors: Sarah Walker, - * Miran Grca, - * TheCollector1995, + * Authors: Sarah Walker, + * Miran Grca, + * TheCollector1995, * - * Copyright 2008-2019 Sarah Walker. - * Copyright 2016-2019 Miran Grca. + * Copyright 2008-2019 Sarah Walker. + * Copyright 2016-2019 Miran Grca. */ #include #include @@ -43,52 +43,51 @@ machine_xt_compaq_deskpro_init(const machine_t *model) int ret; ret = bios_load_linear("roms/machines/deskpro/Compaq - BIOS - Revision J - 106265-002.bin", - 0x000fe000, 8192, 0); + 0x000fe000, 8192, 0); if (bios_only || !ret) - return ret; + return ret; machine_common_init(model); - pit_ctr_set_out_func(&pit->counters[1], pit_refresh_timer_xt); + pit_devs[0].set_out_func(pit_devs[0].data, 1, pit_refresh_timer_xt); device_add(&keyboard_xt_compaq_device); if (fdc_type == FDC_INTERNAL) - device_add(&fdc_xt_device); + device_add(&fdc_xt_device); nmi_init(); standalone_gameport_type = &gameport_device; lpt1_remove(); - lpt1_init(0x03bc); + lpt1_init(LPT_MDA_ADDR); return ret; } - int machine_xt_compaq_portable_init(const machine_t *model) { int ret; ret = bios_load_linear("roms/machines/portable/compaq portable plus 100666-001 rev c u47.bin", - 0x000fe000, 8192, 0); + 0x000fe000, 8192, 0); if (bios_only || !ret) - return ret; + return ret; machine_common_init(model); - pit_ctr_set_out_func(&pit->counters[1], pit_refresh_timer_xt); + pit_devs[0].set_out_func(pit_devs[0].data, 1, pit_refresh_timer_xt); device_add(&keyboard_xt_compaq_device); if (fdc_type == FDC_INTERNAL) - device_add(&fdc_xt_device); + device_add(&fdc_xt_device); nmi_init(); if (joystick_type) - device_add(&gameport_device); + device_add(&gameport_device); lpt1_remove(); - lpt1_init(0x03bc); + lpt1_init(LPT_MDA_ADDR); return ret; } diff --git a/src/machine/m_xt_laserxt.c b/src/machine/m_xt_laserxt.c index 58b7d3774..87c2fe362 100644 --- a/src/machine/m_xt_laserxt.c +++ b/src/machine/m_xt_laserxt.c @@ -19,164 +19,175 @@ #include <86box/fdc_ext.h> #include <86box/gameport.h> #include <86box/keyboard.h> +#include <86box/plat_unused.h> - -static int laserxt_emspage[4]; -static int laserxt_emscontrol[4]; +static int laserxt_emspage[4]; +static int laserxt_emscontrol[4]; static mem_mapping_t laserxt_ems_mapping[4]; -static int laserxt_ems_baseaddr_index = 0; -static int laserxt_is_lxt3 = 0; +static int laserxt_ems_baseaddr_index = 0; +static int laserxt_is_lxt3 = 0; - -static uint32_t get_laserxt_ems_addr(uint32_t addr) +static uint32_t +get_laserxt_ems_addr(uint32_t addr) { - if(laserxt_emspage[(addr >> 14) & 3] & 0x80) - { - addr = (!laserxt_is_lxt3 ? 0x70000 + (((mem_size + 64) & 255) << 10) : 0x30000 + (((mem_size + 320) & 511) << 10)) + ((laserxt_emspage[(addr >> 14) & 3] & 0x0F) << 14) + ((laserxt_emspage[(addr >> 14) & 3] & 0x40) << 12) + (addr & 0x3FFF); - } + if (laserxt_emspage[(addr >> 14) & 3] & 0x80) { + addr = (!laserxt_is_lxt3 ? 0x70000 + (((mem_size + 64) & 255) << 10) : 0x30000 + (((mem_size + 320) & 511) << 10)) + ((laserxt_emspage[(addr >> 14) & 3] & 0x0F) << 14) + ((laserxt_emspage[(addr >> 14) & 3] & 0x40) << 12) + (addr & 0x3FFF); + } - return addr; + return addr; } - -static void laserxt_write(uint16_t port, uint8_t val, void *priv) +static void +laserxt_write(uint16_t port, uint8_t val, UNUSED(void *priv)) { - int i; - uint32_t paddr, vaddr; - switch (port) - { - case 0x0208: case 0x4208: case 0x8208: case 0xC208: - laserxt_emspage[port >> 14] = val; - paddr = 0xC0000 + (port & 0xC000) + (((laserxt_ems_baseaddr_index + (4 - (port >> 14))) & 0x0C) << 14); - if(val & 0x80) - { - mem_mapping_enable(&laserxt_ems_mapping[port >> 14]); - vaddr = get_laserxt_ems_addr(paddr); - mem_mapping_set_exec(&laserxt_ems_mapping[port >> 14], ram + vaddr); - } - else - { - mem_mapping_disable(&laserxt_ems_mapping[port >> 14]); - } - flushmmucache(); - break; - case 0x0209: case 0x4209: case 0x8209: case 0xC209: - laserxt_emscontrol[port >> 14] = val; - laserxt_ems_baseaddr_index = 0; - for(i=0; i<4; i++) - { - laserxt_ems_baseaddr_index |= (laserxt_emscontrol[i] & 0x80) >> (7 - i); - } + uint32_t paddr; + uint32_t vaddr; + switch (port) { + case 0x0208: + case 0x4208: + case 0x8208: + case 0xC208: + laserxt_emspage[port >> 14] = val; + paddr = 0xC0000 + (port & 0xC000) + (((laserxt_ems_baseaddr_index + (4 - (port >> 14))) & 0x0C) << 14); + if (val & 0x80) { + mem_mapping_enable(&laserxt_ems_mapping[port >> 14]); + vaddr = get_laserxt_ems_addr(paddr); + mem_mapping_set_exec(&laserxt_ems_mapping[port >> 14], ram + vaddr); + } else { + mem_mapping_disable(&laserxt_ems_mapping[port >> 14]); + } + flushmmucache(); + break; + case 0x0209: + case 0x4209: + case 0x8209: + case 0xC209: + laserxt_emscontrol[port >> 14] = val; + laserxt_ems_baseaddr_index = 0; + for (uint8_t i = 0; i < 4; i++) { + laserxt_ems_baseaddr_index |= (laserxt_emscontrol[i] & 0x80) >> (7 - i); + } - mem_mapping_set_addr(&laserxt_ems_mapping[0], 0xC0000 + (((laserxt_ems_baseaddr_index + 4) & 0x0C) << 14), 0x4000); - mem_mapping_set_addr(&laserxt_ems_mapping[1], 0xC4000 + (((laserxt_ems_baseaddr_index + 3) & 0x0C) << 14), 0x4000); - mem_mapping_set_addr(&laserxt_ems_mapping[2], 0xC8000 + (((laserxt_ems_baseaddr_index + 2) & 0x0C) << 14), 0x4000); - mem_mapping_set_addr(&laserxt_ems_mapping[3], 0xCC000 + (((laserxt_ems_baseaddr_index + 1) & 0x0C) << 14), 0x4000); - flushmmucache(); - break; - } + mem_mapping_set_addr(&laserxt_ems_mapping[0], 0xC0000 + (((laserxt_ems_baseaddr_index + 4) & 0x0C) << 14), 0x4000); + mem_mapping_set_addr(&laserxt_ems_mapping[1], 0xC4000 + (((laserxt_ems_baseaddr_index + 3) & 0x0C) << 14), 0x4000); + mem_mapping_set_addr(&laserxt_ems_mapping[2], 0xC8000 + (((laserxt_ems_baseaddr_index + 2) & 0x0C) << 14), 0x4000); + mem_mapping_set_addr(&laserxt_ems_mapping[3], 0xCC000 + (((laserxt_ems_baseaddr_index + 1) & 0x0C) << 14), 0x4000); + flushmmucache(); + break; + + default: + break; + } } - -static uint8_t laserxt_read(uint16_t port, void *priv) +static uint8_t +laserxt_read(uint16_t port, UNUSED(void *priv)) { - switch (port) - { - case 0x0208: case 0x4208: case 0x8208: case 0xC208: - return laserxt_emspage[port >> 14]; - case 0x0209: case 0x4209: case 0x8209: case 0xC209: - return laserxt_emscontrol[port >> 14]; - break; - } - return 0xff; + switch (port) { + case 0x0208: + case 0x4208: + case 0x8208: + case 0xC208: + return laserxt_emspage[port >> 14]; + case 0x0209: + case 0x4209: + case 0x8209: + case 0xC209: + return laserxt_emscontrol[port >> 14]; + + default: + break; + } + return 0xff; } - -static void mem_write_laserxtems(uint32_t addr, uint8_t val, void *priv) +static void +mem_write_laserxtems(uint32_t addr, uint8_t val, UNUSED(void *priv)) { - addr = get_laserxt_ems_addr(addr); - if (addr < (mem_size << 10)) - ram[addr] = val; + addr = get_laserxt_ems_addr(addr); + if (addr < (mem_size << 10)) + ram[addr] = val; } - -static uint8_t mem_read_laserxtems(uint32_t addr, void *priv) +static uint8_t +mem_read_laserxtems(uint32_t addr, UNUSED(void *priv)) { - uint8_t val = 0xFF; - addr = get_laserxt_ems_addr(addr); - if (addr < (mem_size << 10)) - val = ram[addr]; - return val; + uint8_t val = 0xFF; + addr = get_laserxt_ems_addr(addr); + if (addr < (mem_size << 10)) + val = ram[addr]; + return val; } - -static void laserxt_init(int is_lxt3) +static void +laserxt_init(int is_lxt3) { - int i; + if (mem_size > 640) { + io_sethandler(0x0208, 0x0002, laserxt_read, NULL, NULL, laserxt_write, NULL, NULL, NULL); + io_sethandler(0x4208, 0x0002, laserxt_read, NULL, NULL, laserxt_write, NULL, NULL, NULL); + io_sethandler(0x8208, 0x0002, laserxt_read, NULL, NULL, laserxt_write, NULL, NULL, NULL); + io_sethandler(0xc208, 0x0002, laserxt_read, NULL, NULL, laserxt_write, NULL, NULL, NULL); + mem_mapping_set_addr(&ram_low_mapping, 0, !is_lxt3 ? 0x70000 + (((mem_size + 64) & 255) << 10) : 0x30000 + (((mem_size + 320) & 511) << 10)); + } - if(mem_size > 640) - { - io_sethandler(0x0208, 0x0002, laserxt_read, NULL, NULL, laserxt_write, NULL, NULL, NULL); - io_sethandler(0x4208, 0x0002, laserxt_read, NULL, NULL, laserxt_write, NULL, NULL, NULL); - io_sethandler(0x8208, 0x0002, laserxt_read, NULL, NULL, laserxt_write, NULL, NULL, NULL); - io_sethandler(0xc208, 0x0002, laserxt_read, NULL, NULL, laserxt_write, NULL, NULL, NULL); - mem_mapping_set_addr(&ram_low_mapping, 0, !is_lxt3 ? 0x70000 + (((mem_size + 64) & 255) << 10) : 0x30000 + (((mem_size + 320) & 511) << 10)); - } - - for (i = 0; i < 4; i++) - { - laserxt_emspage[i] = 0x7F; - laserxt_emscontrol[i] = (i == 3) ? 0x00 : 0x80; - mem_mapping_add(&laserxt_ems_mapping[i], 0xE0000 + (i << 14), 0x4000, mem_read_laserxtems, NULL, NULL, mem_write_laserxtems, NULL, NULL, ram + 0xA0000 + (i << 14), 0, NULL); - mem_mapping_disable(&laserxt_ems_mapping[i]); - } - mem_set_mem_state(0x0c0000, 0x40000, MEM_READ_EXTANY | MEM_WRITE_EXTANY); - laserxt_is_lxt3 = is_lxt3; + for (uint8_t i = 0; i < 4; i++) { + laserxt_emspage[i] = 0x7F; + laserxt_emscontrol[i] = (i == 3) ? 0x00 : 0x80; + mem_mapping_add(&laserxt_ems_mapping[i], 0xE0000 + (i << 14), 0x4000, mem_read_laserxtems, NULL, NULL, mem_write_laserxtems, NULL, NULL, ram + 0xA0000 + (i << 14), 0, NULL); + mem_mapping_disable(&laserxt_ems_mapping[i]); + } + mem_set_mem_state(0x0c0000, 0x40000, MEM_READ_EXTANY | MEM_WRITE_EXTANY); + laserxt_is_lxt3 = is_lxt3; } +static void +machine_xt_laserxt_common_init(const machine_t *model,int is_lxt3) +{ + machine_common_init(model); + + pit_devs[0].set_out_func(pit_devs[0].data, 1, pit_refresh_timer_xt); + + if (fdc_type == FDC_INTERNAL) + device_add(&fdc_xt_device); + + nmi_init(); + standalone_gameport_type = &gameport_device; + + laserxt_init(is_lxt3); +} int machine_xt_laserxt_init(const machine_t *model) { - int ret; + int ret; - ret = bios_load_linear("roms/machines/ltxt/27c64.bin", - 0x000fe000, 8192, 0); + ret = bios_load_linear("roms/machines/ltxt/27c64.bin", + 0x000fe000, 8192, 0); - if (bios_only || !ret) - return ret; + if (bios_only || !ret) + return ret; - machine_xt_init(model); + device_add(&keyboard_xt_device); - laserxt_init(0); + machine_xt_laserxt_common_init(model, 0); - return ret; + return ret; } - int machine_xt_lxt3_init(const machine_t *model) { int ret; ret = bios_load_linear("roms/machines/lxt3/27c64d.bin", - 0x000fe000, 8192, 0); + 0x000fe000, 8192, 0); if (bios_only || !ret) - return ret; - - machine_common_init(model); - - pit_ctr_set_out_func(&pit->counters[1], pit_refresh_timer_xt); + return ret; device_add(&keyboard_xt_lxt3_device); - if (fdc_type == FDC_INTERNAL) - device_add(&fdc_xt_device); - nmi_init(); - standalone_gameport_type = &gameport_device; - - laserxt_init(1); + machine_xt_laserxt_common_init(model, 1); return ret; } diff --git a/src/machine/m_xt_olivetti.c b/src/machine/m_xt_olivetti.c index 9100bbe3b..0b5a3eab0 100644 --- a/src/machine/m_xt_olivetti.c +++ b/src/machine/m_xt_olivetti.c @@ -1,32 +1,34 @@ /* - * 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. + * 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. + * This file is part of the 86Box distribution. * - * Emulation of the Olivetti XT-compatible machines. + * Emulation of the Olivetti XT-compatible machines. * + * - Supports MM58174 real-time clock emulation (M24) + * - Supports MM58274 real-time clock emulation (M240) * + * Authors: Sarah Walker, + * Miran Grca, + * Fred N. van Kempen, + * EngiNerd * - * Authors: Sarah Walker, - * Miran Grca, - * Fred N. van Kempen, - * EngiNerd - * - * Copyright 2008-2019 Sarah Walker. - * Copyright 2016-2019 Miran Grca. - * Copyright 2017-2019 Fred N. van Kempen. - * Copyright 2020 EngiNerd. + * Copyright 2008-2019 Sarah Walker. + * Copyright 2016-2019 Miran Grca. + * Copyright 2017-2019 Fred N. van Kempen. + * Copyright 2020 EngiNerd. */ - #include #include #include #include +#include #include #include +#define HAVE_STDARG_H #include <86box/86box.h> #include <86box/timer.h> #include <86box/io.h> @@ -44,7 +46,9 @@ #include <86box/fdc.h> #include <86box/fdc_ext.h> #include <86box/gameport.h> +#include <86box/hdc.h> #include <86box/port_6x.h> +#include <86box/serial.h> #include <86box/sound.h> #include <86box/snd_speaker.h> #include <86box/video.h> @@ -53,532 +57,1495 @@ #include <86box/vid_ogc.h> #include <86box/vid_colorplus.h> #include <86box/vid_cga_comp.h> +#include <86box/plat_unused.h> -#define STAT_PARITY 0x80 -#define STAT_RTIMEOUT 0x40 -#define STAT_TTIMEOUT 0x20 -#define STAT_LOCK 0x10 -#define STAT_CD 0x08 -#define STAT_SYSFLAG 0x04 -#define STAT_IFULL 0x02 -#define STAT_OFULL 0x01 +#define STAT_PARITY 0x80 +#define STAT_RTIMEOUT 0x40 +#define STAT_TTIMEOUT 0x20 +#define STAT_LOCK 0x10 +#define STAT_CD 0x08 +#define STAT_SYSFLAG 0x04 +#define STAT_IFULL 0x02 +#define STAT_OFULL 0x01 -#define PLANTRONICS_MODE 1 +#define PLANTRONICS_MODE 1 #define OLIVETTI_OGC_MODE 0 -#define CGA_RGB 0 -#define CGA_COMPOSITE 1 +#define CGA_RGB 0 +#define CGA_COMPOSITE 1 -typedef struct { +enum MM58174_ADDR { + /* Registers */ + MM58174_TEST, /* TEST register, write only */ + MM58174_TENTHS, /* Tenths of second, read only */ + MM58174_SECOND1, /* Units of seconds, read only */ + MM58174_SECOND10, /* Tens of seconds, read only */ + MM58174_MINUTE1, + MM58174_MINUTE10, + MM58174_HOUR1, + MM58174_HOUR10, + MM58174_DAY1, + MM58174_DAY10, + MM58174_WEEKDAY, + MM58174_MONTH1, + MM58174_MONTH10, + MM58174_LEAPYEAR, /* Leap year status, write only */ + MM58174_RESET, /* RESET register, write only */ + MM58174_IRQ /* Interrupt register, read / write */ +}; + +enum MM58274_ADDR { + /* Registers */ + MM58274_CONTROL, /* Control register */ + MM58274_TENTHS, /* Tenths of second, read only */ + MM58274_SECOND1, + MM58274_SECOND10, + MM58274_MINUTE1, + MM58274_MINUTE10, + MM58274_HOUR1, + MM58274_HOUR10, + MM58274_DAY1, + MM58274_DAY10, + MM58274_MONTH1, + MM58274_MONTH10, + MM58274_YEAR1, + MM58274_YEAR10, + MM58274_WEEKDAY, + MM58274_SETTINGS /* Settings register */ +}; + +static struct tm intclk; + +typedef struct m24_kbd_t { /* Keyboard stuff. */ - int wantirq; - uint8_t command; - uint8_t status; - uint8_t out; - uint8_t output_port; - int param, - param_total; - uint8_t params[16]; - uint8_t scan[7]; + int wantirq; + uint8_t command; + uint8_t status; + uint8_t out; + uint8_t output_port; + uint8_t id; + int param; + int param_total; + uint8_t params[16]; + uint8_t scan[7]; /* Mouse stuff. */ - int mouse_mode; - int x, y, b; - pc_timer_t send_delay_timer; + int mouse_input_mode; + int b; + + pc_timer_t send_delay_timer; } m24_kbd_t; -typedef struct { - ogc_t ogc; - colorplus_t colorplus; - int mode; +typedef struct m19_vid_t { + ogc_t ogc; + colorplus_t colorplus; + int mode; } m19_vid_t; -static uint8_t key_queue[16]; -static int key_queue_start = 0, - key_queue_end = 0; +static uint8_t key_queue[16]; +static int key_queue_start = 0; +static int key_queue_end = 0; -video_timings_t timing_m19_vid = {VIDEO_ISA, 8, 16, 32, 8, 16, 32}; +video_timings_t timing_m19_vid = { VIDEO_ISA, 8, 16, 32, 8, 16, 32 }; -const device_t m19_vid_device; - - -#ifdef ENABLE_M24VID_LOG -int m24vid_do_log = ENABLE_M24VID_LOG; +const device_t m19_vid_device; +#ifdef ENABLE_XT_OLIVETTI_LOG +int xt_olivetti_do_log = ENABLE_XT_OLIVETTI_LOG; static void -m24_log(const char *fmt, ...) +xt_olivetti_log(const char *fmt, ...) { va_list ap; - if (m24vid_do_log) { - va_start(ap, fmt); - vfprintf(stdlog, fmt, ap); - va_end(ap); - fflush(stdlog); + if (xt_olivetti_do_log) { + va_start(ap, fmt); + pclog_ex(fmt, ap); + va_end(ap); } } #else -#define m24_log(fmt, ...) +# define xt_olivetti_log(fmt, ...) #endif +/* Set the chip time. */ +static void +mm58174_time_set(uint8_t *regs, struct tm *tm) +{ + regs[MM58174_SECOND1] = (tm->tm_sec % 10); + regs[MM58174_SECOND10] = (tm->tm_sec / 10); + regs[MM58174_MINUTE1] = (tm->tm_min % 10); + regs[MM58174_MINUTE10] = (tm->tm_min / 10); + regs[MM58174_HOUR1] = (tm->tm_hour % 10); + regs[MM58174_HOUR10] = (tm->tm_hour / 10); + regs[MM58174_WEEKDAY] = (tm->tm_wday + 1); + regs[MM58174_DAY1] = (tm->tm_mday % 10); + regs[MM58174_DAY10] = (tm->tm_mday / 10); + regs[MM58174_MONTH1] = ((tm->tm_mon + 1) % 10); + regs[MM58174_MONTH10] = ((tm->tm_mon + 1) / 10); + /* MM58174 does not store the year, M24 uses the IRQ register to count 8 years from leap year */ + regs[MM58174_IRQ] = ((tm->tm_year + 1900) % 8); + regs[MM58174_LEAPYEAR] = 8 >> ((regs[MM58174_IRQ] & 0x07) & 0x03); +} + +/* Get the chip time. */ +#define nibbles(a) (regs[(a##1)] + 10 * regs[(a##10)]) +static void +mm58174_time_get(uint8_t *regs, struct tm *tm) +{ + tm->tm_sec = nibbles(MM58174_SECOND); + tm->tm_min = nibbles(MM58174_MINUTE); + tm->tm_hour = nibbles(MM58174_HOUR); + tm->tm_wday = (regs[MM58174_WEEKDAY] - 1); + tm->tm_mday = nibbles(MM58174_DAY); + tm->tm_mon = (nibbles(MM58174_MONTH) - 1); + /* MM58174 does not store the year */ + tm->tm_year = (1984 + (regs[MM58174_IRQ] & 0x07) - 1900); +} + +/* One more second has passed, update the internal clock. */ +static void +mm58x74_recalc(void) +{ + /* Ping the internal clock. */ + if (++intclk.tm_sec == 60) { + intclk.tm_sec = 0; + if (++intclk.tm_min == 60) { + intclk.tm_min = 0; + if (++intclk.tm_hour == 24) { + intclk.tm_hour = 0; + if (++intclk.tm_mday == (nvr_get_days(intclk.tm_mon, intclk.tm_year) + 1)) { + intclk.tm_mday = 1; + if (++intclk.tm_mon == 13) { + intclk.tm_mon = 1; + intclk.tm_year++; + } + } + } + } + } +} + +/* This is called every second through the NVR/RTC hook. */ +static void +mm58174_tick(nvr_t *nvr) +{ + mm58x74_recalc(); + mm58174_time_set(nvr->regs, &intclk); +} + +static void +mm58174_start(nvr_t *nvr) +{ + struct tm tm; + + /* Initialize the internal and chip times. */ + if (time_sync & TIME_SYNC_ENABLED) { + /* Use the internal clock's time. */ + nvr_time_get(&tm); + mm58174_time_set(nvr->regs, &tm); + } else { + /* Set the internal clock from the chip time. */ + mm58174_time_get(nvr->regs, &tm); + nvr_time_set(&tm); + } + mm58174_time_get(nvr->regs, &intclk); +} + +/* Write to one of the chip registers. */ +static void +mm58174_write(uint16_t addr, uint8_t val, void *priv) +{ + nvr_t *nvr = (nvr_t *) priv; + + addr &= 0x0f; + val &= 0x0f; + + /* Update non-read-only changed values if not synchronizing time to host */ + if ((addr != MM58174_TENTHS) && (addr != MM58174_SECOND1) && (addr != MM58174_SECOND10)) + if ((nvr->regs[addr] != val) && !(time_sync & TIME_SYNC_ENABLED)) + nvr_dosave = 1; + + if ((addr == MM58174_RESET) && (val & 0x01)) { + /* When timer starts, MM58174 sets seconds and tenths of second to 0 */ + nvr->regs[MM58174_TENTHS] = 0; + if (!(time_sync & TIME_SYNC_ENABLED)) { + /* Only set seconds to 0 if not synchronizing time to host clock */ + nvr->regs[MM58174_SECOND1] = 0; + nvr->regs[MM58174_SECOND10] = 0; + } + } + + /* Store the new value */ + nvr->regs[addr] = val; + + /* Update internal clock with MM58174 time */ + mm58174_time_get(nvr->regs, &intclk); +} + +/* Read from one of the chip registers. */ +static uint8_t +mm58174_read(uint16_t addr, void *priv) +{ + nvr_t *nvr = (nvr_t *) priv; + + addr &= 0x0f; + + /* Set IRQ control bit to 0 upon read */ + if (addr == 0x0f) + nvr->regs[addr] &= 0x07; + + /* Grab and return the desired value */ + return (nvr->regs[addr]); +} + +/* Reset the MM58174 to a default state. */ +static void +mm58174_reset(nvr_t *nvr) +{ + /* Clear the NVRAM. */ + memset(nvr->regs, 0xff, nvr->size); + + /* Reset the RTC registers. */ + memset(nvr->regs, 0x00, 16); + nvr->regs[MM58174_WEEKDAY] = 0x01; + nvr->regs[MM58174_DAY1] = 0x01; + nvr->regs[MM58174_MONTH1] = 0x01; +} + +static void +mm58174_init(nvr_t *nvr, int size) +{ + /* This is machine specific. */ + nvr->size = size; + nvr->irq = -1; + + /* Set up any local handlers here. */ + nvr->reset = mm58174_reset; + nvr->start = mm58174_start; + nvr->tick = mm58174_tick; + + /* Initialize the actual NVR. */ + nvr_init(nvr); + + io_sethandler(0x0070, 16, + mm58174_read, NULL, NULL, mm58174_write, NULL, NULL, nvr); +} + +/* Set the chip time. */ +static void +mm58274_time_set(uint8_t *regs, struct tm *tm) +{ + regs[MM58274_SECOND1] = (tm->tm_sec % 10); + regs[MM58274_SECOND10] = (tm->tm_sec / 10); + regs[MM58274_MINUTE1] = (tm->tm_min % 10); + regs[MM58274_MINUTE10] = (tm->tm_min / 10); + regs[MM58274_HOUR1] = (tm->tm_hour % 10); + regs[MM58274_HOUR10] = (tm->tm_hour / 10); + /* Store hour in 24-hour or 12-hour mode */ + if (regs[MM58274_SETTINGS] & 0x01) { + regs[MM58274_HOUR1] = (tm->tm_hour % 10); + regs[MM58274_HOUR10] = (tm->tm_hour / 10); + } else { + regs[MM58274_HOUR1] = ((tm->tm_hour % 12) % 10); + regs[MM58274_HOUR10] = ((tm->tm_hour % 12) / 10); + if (tm->tm_hour >= 12) + regs[MM58274_SETTINGS] |= 0x04; + else + regs[MM58274_SETTINGS] &= 0x0B; + } + regs[MM58274_WEEKDAY] = (tm->tm_wday + 1); + regs[MM58274_DAY1] = (tm->tm_mday % 10); + regs[MM58274_DAY10] = (tm->tm_mday / 10); + regs[MM58274_MONTH1] = ((tm->tm_mon + 1) % 10); + regs[MM58274_MONTH10] = ((tm->tm_mon + 1) / 10); + /* MM58274 can store 00 to 99 years but M240 uses the YEAR1 register to count 8 years from leap year */ + regs[MM58274_YEAR1] = ((tm->tm_year + 1900) % 8); + /* Keep bit 0 and 1 12-hour / 24-hour and AM / PM */ + regs[MM58274_SETTINGS] &= 0x03; + /* Set leap counter bits 2 and 3 */ + regs[MM58274_SETTINGS] += (4 * (regs[MM58274_YEAR1] & 0x03)); +} + +/* Get the chip time. */ +static void +mm58274_time_get(uint8_t *regs, struct tm *tm) +{ + tm->tm_sec = nibbles(MM58274_SECOND); + tm->tm_min = nibbles(MM58274_MINUTE); + /* Read hour in 24-hour or 12-hour mode */ + if (regs[MM58274_SETTINGS] & 0x01) + tm->tm_hour = nibbles(MM58274_HOUR); + else + tm->tm_hour = ((nibbles(MM58274_HOUR) % 12) + (regs[MM58274_SETTINGS] & 0x04) ? 12 : 0); + tm->tm_wday = (regs[MM58274_WEEKDAY] - 1); + tm->tm_mday = nibbles(MM58274_DAY); + tm->tm_mon = (nibbles(MM58274_MONTH) - 1); + /* MM58274 can store 00 to 99 years but M240 uses the YEAR1 register to count 8 years from leap year */ + tm->tm_year = (1984 + regs[MM58274_YEAR1] - 1900); +} + +/* This is called every second through the NVR/RTC hook. */ +static void +mm58274_tick(nvr_t *nvr) +{ + mm58x74_recalc(); + mm58274_time_set(nvr->regs, &intclk); +} + +static void +mm58274_start(nvr_t *nvr) +{ + struct tm tm; + + /* Initialize the internal and chip times. */ + if (time_sync & TIME_SYNC_ENABLED) { + /* Use the internal clock's time. */ + nvr_time_get(&tm); + mm58274_time_set(nvr->regs, &tm); + } else { + /* Set the internal clock from the chip time. */ + mm58274_time_get(nvr->regs, &tm); + nvr_time_set(&tm); + } + mm58274_time_get(nvr->regs, &intclk); +} + +/* Write to one of the chip registers. */ +static void +mm58274_write(uint16_t addr, uint8_t val, void *priv) +{ + nvr_t *nvr = (nvr_t *) priv; + + addr &= 0x0f; + val &= 0x0f; + + /* Update non-read-only changed values if not synchronizing time to host */ + if (addr != MM58274_TENTHS) + if ((nvr->regs[addr] != val) && !(time_sync & TIME_SYNC_ENABLED)) + nvr_dosave = 1; + + if ((addr == MM58274_CONTROL) && (val & 0x04)) { + /* When timer starts, MM58274 sets tenths of second to 0 */ + nvr->regs[MM58274_TENTHS] = 0; + } + + /* Store the new value */ + nvr->regs[addr] = val; + + /* Update internal clock with MM58274 time */ + mm58274_time_get(nvr->regs, &intclk); +} + +/* Read from one of the chip registers. */ +static uint8_t +mm58274_read(uint16_t addr, void *priv) +{ + const nvr_t *nvr = (nvr_t *) priv; + + addr &= 0x0f; + + /* Grab and return the desired value */ + return (nvr->regs[addr]); +} + +/* Reset the MM58274 to a default state. */ +static void +mm58274_reset(nvr_t *nvr) +{ + /* Clear the NVRAM. */ + memset(nvr->regs, 0xff, nvr->size); + + /* Reset the RTC registers. */ + memset(nvr->regs, 0x00, 16); + nvr->regs[MM58274_WEEKDAY] = 0x01; + nvr->regs[MM58274_DAY1] = 0x01; + nvr->regs[MM58274_MONTH1] = 0x01; + nvr->regs[MM58274_SETTINGS] = 0x01; +} + +static void +mm58274_init(nvr_t *nvr, int size) +{ + /* This is machine specific. */ + nvr->size = size; + nvr->irq = -1; + + /* Set up any local handlers here. */ + nvr->reset = mm58274_reset; + nvr->start = mm58274_start; + nvr->tick = mm58274_tick; + + /* Initialize the actual NVR. */ + nvr_init(nvr); + + io_sethandler(0x0070, 16, + mm58274_read, NULL, NULL, mm58274_write, NULL, NULL, nvr); +} static void m24_kbd_poll(void *priv) { - m24_kbd_t *m24_kbd = (m24_kbd_t *)priv; + m24_kbd_t *m24_kbd = (m24_kbd_t *) priv; timer_advance_u64(&m24_kbd->send_delay_timer, 1000 * TIMER_USEC); if (m24_kbd->wantirq) { - m24_kbd->wantirq = 0; - picint(2); -#if ENABLE_KEYBOARD_LOG - m24_log("M24: take IRQ\n"); -#endif + m24_kbd->wantirq = 0; + picint(2); + xt_olivetti_log("M24: take IRQ\n"); } if (!(m24_kbd->status & STAT_OFULL) && key_queue_start != key_queue_end) { -#if ENABLE_KEYBOARD_LOG - m24_log("Reading %02X from the key queue at %i\n", - m24_kbd->out, key_queue_start); -#endif - m24_kbd->out = key_queue[key_queue_start]; - key_queue_start = (key_queue_start + 1) & 0xf; - m24_kbd->status |= STAT_OFULL; - m24_kbd->status &= ~STAT_IFULL; - m24_kbd->wantirq = 1; + xt_olivetti_log("Reading %02X from the key queue at %i\n", + m24_kbd->out, key_queue_start); + m24_kbd->out = key_queue[key_queue_start]; + key_queue_start = (key_queue_start + 1) & 0xf; + m24_kbd->status |= STAT_OFULL; + m24_kbd->status &= ~STAT_IFULL; + m24_kbd->wantirq = 1; } } - static void m24_kbd_adddata(uint16_t val) { key_queue[key_queue_end] = val; - key_queue_end = (key_queue_end + 1) & 0xf; + key_queue_end = (key_queue_end + 1) & 0xf; } - static void m24_kbd_adddata_ex(uint16_t val) { kbd_adddata_process(val, m24_kbd_adddata); } +/* + From the Olivetti M21/M24 Theory of Operation: + Port Function + ---- -------- + 60h Keyboard 8041 Data Transfer Read/Write + 61h Control Port A Read/Write + 62h Control Port B Read + 63h Not Used + 64h Keyboard 8041 Command/Status + 65h Communications Port Read + 66h System Configuration Read + 67h System Configuration Read + */ static void m24_kbd_write(uint16_t port, uint8_t val, void *priv) { - m24_kbd_t *m24_kbd = (m24_kbd_t *)priv; + m24_kbd_t *m24_kbd = (m24_kbd_t *) priv; + uint8_t ret; -#if ENABLE_KEYBOARD_LOG - m24_log("M24: write %04X %02X\n", port, val); -#endif + xt_olivetti_log("M24: write %04X %02X\n", port, val); -#if 0 - if (ram[8] == 0xc3) - output = 3; -#endif switch (port) { - case 0x60: - if (m24_kbd->param != m24_kbd->param_total) { - m24_kbd->params[m24_kbd->param++] = val; - if (m24_kbd->param == m24_kbd->param_total) { - switch (m24_kbd->command) { - case 0x11: - m24_kbd->mouse_mode = 0; - m24_kbd->scan[0] = m24_kbd->params[0]; - m24_kbd->scan[1] = m24_kbd->params[1]; - m24_kbd->scan[2] = m24_kbd->params[2]; - m24_kbd->scan[3] = m24_kbd->params[3]; - m24_kbd->scan[4] = m24_kbd->params[4]; - m24_kbd->scan[5] = m24_kbd->params[5]; - m24_kbd->scan[6] = m24_kbd->params[6]; - break; + case 0x60: + m24_kbd->status &= ~STAT_CD; - case 0x12: - m24_kbd->mouse_mode = 1; - m24_kbd->scan[0] = m24_kbd->params[0]; - m24_kbd->scan[1] = m24_kbd->params[1]; - m24_kbd->scan[2] = m24_kbd->params[2]; - break; - - default: - m24_log("M24: bad keyboard command complete %02X\n", m24_kbd->command); - } - } - } else { - m24_kbd->command = val; - switch (val) { - case 0x01: /*Self-test*/ - break; + if (m24_kbd->param != m24_kbd->param_total) { + m24_kbd->params[m24_kbd->param++] = val; + if (m24_kbd->param == m24_kbd->param_total) { + switch (m24_kbd->command) { + case 0x11: + m24_kbd->mouse_input_mode = 0; + m24_kbd->scan[0] = m24_kbd->params[0]; + m24_kbd->scan[1] = m24_kbd->params[1]; + m24_kbd->scan[2] = m24_kbd->params[2]; + m24_kbd->scan[3] = m24_kbd->params[3]; + m24_kbd->scan[4] = m24_kbd->params[4]; + m24_kbd->scan[5] = m24_kbd->params[5]; + m24_kbd->scan[6] = m24_kbd->params[6]; + break; - case 0x05: /*Read ID*/ - m24_kbd_adddata(0x00); - break; + case 0x12: + m24_kbd->mouse_input_mode = 1; + m24_kbd->scan[0] = m24_kbd->params[0]; + m24_kbd->scan[1] = m24_kbd->params[1]; + m24_kbd->scan[2] = m24_kbd->params[2]; + break; - case 0x11: - m24_kbd->param = 0; - m24_kbd->param_total = 9; - break; + default: + xt_olivetti_log("M24: bad keyboard command complete %02X\n", m24_kbd->command); + } + } + } else { + m24_kbd->command = val; + switch (val) { + /* 01: FD, 05: ANY ---> Customer test reports no keyboard. + 01: AA, 05: 01 ---> Customer test reports 102 Deluxe keyboard. + 01: AA, 05: 02 ---> Customer test reports 83-key keyboard. + 01: AA, 05: 10 ---> Customer test reports M240 keyboard. + 01: AA, 05: 20 ---> Customer test reports 101/102/key keyboard. + 01: AA, 05: 40 or anything else ---> Customer test reports 101/102/key keyboard. - case 0x12: - m24_kbd->param = 0; - m24_kbd->param_total = 4; - break; + AA is the correct return for command 01, as confirmed by the M24 Customer Test. */ + case 0x01: /*Self-test*/ + m24_kbd_adddata(0xaa); + break; - default: - m24_log("M24: bad keyboard command %02X\n", val); - } - } - break; + case 0x02: /*Olivetti M240: Read SWB*/ + /* SWB on mainboard (off=1) + * bit 7 - use BIOS HD on mainboard (on) / on controller (off) + * bit 6 - use OCG/CGA display adapter (on) / other display adapter (off) + */ + ret = (hdc_current == HDC_INTERNAL) ? 0x00 : 0x80; + ret |= video_is_cga() ? 0x40 : 0x00; - case 0x61: - ppi.pb = val; + m24_kbd_adddata(ret); + break; - speaker_update(); - speaker_gated = val & 1; - speaker_enable = val & 2; - if (speaker_enable) - was_speaker_enable = 1; - pit_ctr_set_gate(&pit->counters[2], val & 1); - break; + case 0x05: /*Read ID*/ + ret = m24_kbd->id; + m24_kbd_adddata(ret); + break; + + case 0x11: + m24_kbd->param = 0; + m24_kbd->param_total = 9; + break; + + case 0x12: + m24_kbd->param = 0; + m24_kbd->param_total = 4; + break; + + case 0x13: /*Sent by Olivetti M240 Customer Diagnostics*/ + break; + + default: + xt_olivetti_log("M24: bad keyboard command %02X\n", val); + } + } + break; + + case 0x61: + ppi.pb = val; + + speaker_update(); + speaker_gated = val & 1; + speaker_enable = val & 2; + if (speaker_enable) + was_speaker_enable = 1; + pit_devs[0].set_gate(pit_devs[0].data, 2, val & 1); + break; + + case 0x64: + m24_kbd->status |= STAT_CD; + + if (val == 0x02) + m24_kbd_adddata(0x00); + break; + + default: + break; } } +extern uint8_t random_generate(void); static uint8_t m24_kbd_read(uint16_t port, void *priv) { - m24_kbd_t *m24_kbd = (m24_kbd_t *)priv; - uint8_t ret = 0xff; + m24_kbd_t *m24_kbd = (m24_kbd_t *) priv; + uint8_t ret = 0xff; switch (port) { - case 0x60: - ret = m24_kbd->out; - if (key_queue_start == key_queue_end) { - m24_kbd->status &= ~STAT_OFULL; - m24_kbd->wantirq = 0; - } else { - m24_kbd->out = key_queue[key_queue_start]; - key_queue_start = (key_queue_start + 1) & 0xf; - m24_kbd->status |= STAT_OFULL; - m24_kbd->status &= ~STAT_IFULL; - m24_kbd->wantirq = 1; - } - break; + case 0x60: + ret = m24_kbd->out; + if (key_queue_start == key_queue_end) { + m24_kbd->status &= ~STAT_OFULL; + m24_kbd->wantirq = 0; + } else { + m24_kbd->out = key_queue[key_queue_start]; + key_queue_start = (key_queue_start + 1) & 0xf; + m24_kbd->status |= STAT_OFULL; + m24_kbd->status &= ~STAT_IFULL; + m24_kbd->wantirq = 1; + } + break; - case 0x61: - ret = ppi.pb; - break; + case 0x61: + /* MS-DOS 5.00 and higher's KEYB.COM freezes due to port 61h not having the + AT refresh toggle, because for some reson it thinks the M24 is an AT. - case 0x64: - ret = m24_kbd->status; - m24_kbd->status &= ~(STAT_RTIMEOUT | STAT_TTIMEOUT); - break; + A German-language site confirms this also happens on real hardware. - default: - m24_log("\nBad M24 keyboard read %04X\n", port); + The M240 is not affected. */ + ret = ppi.pb; + break; + + case 0x64: + ret = m24_kbd->status & 0x0f; + m24_kbd->status &= ~(STAT_RTIMEOUT | STAT_TTIMEOUT); + break; + + default: + xt_olivetti_log("\nBad M24 keyboard read %04X\n", port); } - return(ret); + return ret; } - static void m24_kbd_close(void *priv) { - m24_kbd_t *kbd = (m24_kbd_t *)priv; + m24_kbd_t *kbd = (m24_kbd_t *) priv; /* Stop the timer. */ timer_disable(&kbd->send_delay_timer); - + /* Disable scanning. */ keyboard_scan = 0; keyboard_send = NULL; io_removehandler(0x0060, 2, - m24_kbd_read, NULL, NULL, m24_kbd_write, NULL, NULL, kbd); + m24_kbd_read, NULL, NULL, m24_kbd_write, NULL, NULL, kbd); io_removehandler(0x0064, 1, - m24_kbd_read, NULL, NULL, m24_kbd_write, NULL, NULL, kbd); + m24_kbd_read, NULL, NULL, m24_kbd_write, NULL, NULL, kbd); free(kbd); } - static void m24_kbd_reset(void *priv) { - m24_kbd_t *m24_kbd = (m24_kbd_t *)priv; - - /* Initialize the keyboard. */ - m24_kbd->status = STAT_LOCK | STAT_CD; - m24_kbd->wantirq = 0; - keyboard_scan = 1; - m24_kbd->param = m24_kbd->param_total = 0; - m24_kbd->mouse_mode = 0; - m24_kbd->scan[0] = 0x1c; - m24_kbd->scan[1] = 0x53; - m24_kbd->scan[2] = 0x01; - m24_kbd->scan[3] = 0x4b; - m24_kbd->scan[4] = 0x4d; - m24_kbd->scan[5] = 0x48; - m24_kbd->scan[6] = 0x50; -} + m24_kbd_t *m24_kbd = (m24_kbd_t *) priv; + /* Initialize the keyboard. */ + m24_kbd->status = STAT_LOCK | STAT_CD; + m24_kbd->wantirq = 0; + keyboard_scan = 1; + m24_kbd->param = m24_kbd->param_total = 0; + m24_kbd->mouse_input_mode = 0; + m24_kbd->scan[0] = 0x1c; + m24_kbd->scan[1] = 0x53; + m24_kbd->scan[2] = 0x01; + m24_kbd->scan[3] = 0x4b; + m24_kbd->scan[4] = 0x4d; + m24_kbd->scan[5] = 0x48; + m24_kbd->scan[6] = 0x50; +} static int -ms_poll(int x, int y, int z, int b, void *priv) +ms_poll(void *priv) { - m24_kbd_t *m24_kbd = (m24_kbd_t *)priv; + m24_kbd_t *m24_kbd = (m24_kbd_t *) priv; + int delta_x; + int delta_y; + int o_x; + int o_y; + int b = mouse_get_buttons_ex(); - m24_kbd->x += x; - m24_kbd->y += y; - - if (((key_queue_end - key_queue_start) & 0xf) > 14) return(0xff); + if (((key_queue_end - key_queue_start) & 0xf) > 14) + return 0xff; if ((b & 1) && !(m24_kbd->b & 1)) - m24_kbd_adddata(m24_kbd->scan[0]); + m24_kbd_adddata(m24_kbd->scan[0]); if (!(b & 1) && (m24_kbd->b & 1)) - m24_kbd_adddata(m24_kbd->scan[0] | 0x80); + m24_kbd_adddata(m24_kbd->scan[0] | 0x80); m24_kbd->b = (m24_kbd->b & ~1) | (b & 1); - if (((key_queue_end - key_queue_start) & 0xf) > 14) return(0xff); + if (((key_queue_end - key_queue_start) & 0xf) > 14) + return 0xff; if ((b & 2) && !(m24_kbd->b & 2)) - m24_kbd_adddata(m24_kbd->scan[2]); + m24_kbd_adddata(m24_kbd->scan[2]); if (!(b & 2) && (m24_kbd->b & 2)) - m24_kbd_adddata(m24_kbd->scan[2] | 0x80); + m24_kbd_adddata(m24_kbd->scan[2] | 0x80); m24_kbd->b = (m24_kbd->b & ~2) | (b & 2); - if (((key_queue_end - key_queue_start) & 0xf) > 14) return(0xff); + if (((key_queue_end - key_queue_start) & 0xf) > 14) + return 0xff; if ((b & 4) && !(m24_kbd->b & 4)) - m24_kbd_adddata(m24_kbd->scan[1]); + m24_kbd_adddata(m24_kbd->scan[1]); if (!(b & 4) && (m24_kbd->b & 4)) - m24_kbd_adddata(m24_kbd->scan[1] | 0x80); + m24_kbd_adddata(m24_kbd->scan[1] | 0x80); m24_kbd->b = (m24_kbd->b & ~4) | (b & 4); - if (m24_kbd->mouse_mode) { - if (((key_queue_end - key_queue_start) & 0xf) > 12) return(0xff); + if (m24_kbd->mouse_input_mode) { + if (((key_queue_end - key_queue_start) & 0xf) > 12) + return 0xff; - if (!m24_kbd->x && !m24_kbd->y) return(0xff); - - m24_kbd->y = -m24_kbd->y; + if (!mouse_moved()) + return 0xff; - if (m24_kbd->x < -127) m24_kbd->x = -127; - if (m24_kbd->x > 127) m24_kbd->x = 127; - if (m24_kbd->x < -127) m24_kbd->x = 0x80 | ((-m24_kbd->x) & 0x7f); + mouse_subtract_coords(&delta_x, &delta_y, &o_x, &o_y, -127, 127, 1, 0); - if (m24_kbd->y < -127) m24_kbd->y = -127; - if (m24_kbd->y > 127) m24_kbd->y = 127; - if (m24_kbd->y < -127) m24_kbd->y = 0x80 | ((-m24_kbd->y) & 0x7f); + if ((delta_x == -127) && o_x) + delta_x = 0x80 | ((-delta_x) & 0x7f); - m24_kbd_adddata(0xfe); - m24_kbd_adddata(m24_kbd->x); - m24_kbd_adddata(m24_kbd->y); + if ((delta_y == -127) && o_y) + delta_y = 0x80 | ((-delta_y) & 0x7f); - m24_kbd->x = m24_kbd->y = 0; + m24_kbd_adddata(0xfe); + m24_kbd_adddata(delta_x); + m24_kbd_adddata(delta_y); } else { - while (m24_kbd->x < -4) { - if (((key_queue_end - key_queue_start) & 0xf) > 14) - return(0xff); - m24_kbd->x += 4; - m24_kbd_adddata(m24_kbd->scan[3]); - } - while (m24_kbd->x > 4) { - if (((key_queue_end - key_queue_start) & 0xf) > 14) - return(0xff); - m24_kbd->x -= 4; - m24_kbd_adddata(m24_kbd->scan[4]); - } - while (m24_kbd->y < -4) { - if (((key_queue_end - key_queue_start) & 0xf) > 14) - return(0xff); - m24_kbd->y += 4; - m24_kbd_adddata(m24_kbd->scan[5]); - } - while (m24_kbd->y > 4) { - if (((key_queue_end - key_queue_start) & 0xf) > 14) - return(0xff); - m24_kbd->y -= 4; - m24_kbd_adddata(m24_kbd->scan[6]); - } + mouse_subtract_coords(&delta_x, &delta_y, &o_x, &o_y, -127, 127, 1, 0); + + while (delta_x < -4) { + if (((key_queue_end - key_queue_start) & 0xf) > 14) + return 0xff; + delta_x += 4; + m24_kbd_adddata(m24_kbd->scan[3]); + } + while (delta_x > 4) { + if (((key_queue_end - key_queue_start) & 0xf) > 14) + return 0xff; + delta_x -= 4; + m24_kbd_adddata(m24_kbd->scan[4]); + } + while (delta_y < -4) { + if (((key_queue_end - key_queue_start) & 0xf) > 14) + return 0xff; + delta_y += 4; + m24_kbd_adddata(m24_kbd->scan[5]); + } + while (delta_y > 4) { + if (((key_queue_end - key_queue_start) & 0xf) > 14) + return 0xff; + delta_y -= 4; + m24_kbd_adddata(m24_kbd->scan[6]); + } } - return(0); + return 0; } +/* Remapping as follows: + + - Left Windows (E0 5B) -> NUMPAD 00 (54); + - Print Screen (E0 37) -> SCR PRT (55); + - Menu (E0 5D) -> HELP (56); + - NumPad Enter (E0 1C) -> NUMPAD ENTER (57). + - Left (E0 4B) -> LEFT (58); + - Down (E0 50) -> DOWN (59); + - Right (E0 4D) -> RIGHT (5A); + - Up (E0 48) -> UP (5B); + - Page Up (E0 49) -> CLEAR (5C); + - Page Down (E0 51) -> BREAK (5D); + - CE Key (56) -> CE KEY (5E); + WARNING: The Olivetti CE Key is undocumented, but can be inferred from the fact + its position is missing in the shown layout, it being used by the Italian + keyboard layout, the keyboard is called 103-key, but only 102 keys are + shown. + - NumPad / (E0 35) -> NUMPAD / (5F); + - F11 (57) -> F11 (60); + - F12 (58) -> F12 (61); + - Insert (E0 52) -> F13 (62); + - Home (E0 47) -> F14 (63); + - Delete (E0 53) -> F15 (64); + - End (E0 4F) -> F16 (65); + - Right Alt (Gr)(E0 38) -> F16 (66); + - Right Windows (E0 5C) -> F18 (67). + */ +const scancode scancode_olivetti_m24_deluxe[512] = { + // clang-format off + { {0}, {0} }, { {0x01, 0}, {0x81, 0} }, + { {0x02, 0}, {0x82, 0} }, { {0x03, 0}, {0x83, 0} }, + { {0x04, 0}, {0x84, 0} }, { {0x05, 0}, {0x85, 0} }, + { {0x06, 0}, {0x86, 0} }, { {0x07, 0}, {0x87, 0} }, + { {0x08, 0}, {0x88, 0} }, { {0x09, 0}, {0x89, 0} }, + { {0x0a, 0}, {0x8a, 0} }, { {0x0b, 0}, {0x8b, 0} }, + { {0x0c, 0}, {0x8c, 0} }, { {0x0d, 0}, {0x8d, 0} }, + { {0x0e, 0}, {0x8e, 0} }, { {0x0f, 0}, {0x8f, 0} }, + { {0x10, 0}, {0x90, 0} }, { {0x11, 0}, {0x91, 0} }, + { {0x12, 0}, {0x92, 0} }, { {0x13, 0}, {0x93, 0} }, + { {0x14, 0}, {0x94, 0} }, { {0x15, 0}, {0x95, 0} }, + { {0x16, 0}, {0x96, 0} }, { {0x17, 0}, {0x97, 0} }, + { {0x18, 0}, {0x98, 0} }, { {0x19, 0}, {0x99, 0} }, + { {0x1a, 0}, {0x9a, 0} }, { {0x1b, 0}, {0x9b, 0} }, + { {0x1c, 0}, {0x9c, 0} }, { {0x1d, 0}, {0x9d, 0} }, + { {0x1e, 0}, {0x9e, 0} }, { {0x1f, 0}, {0x9f, 0} }, + { {0x20, 0}, {0xa0, 0} }, { {0x21, 0}, {0xa1, 0} }, + { {0x22, 0}, {0xa2, 0} }, { {0x23, 0}, {0xa3, 0} }, + { {0x24, 0}, {0xa4, 0} }, { {0x25, 0}, {0xa5, 0} }, + { {0x26, 0}, {0xa6, 0} }, { {0x27, 0}, {0xa7, 0} }, + { {0x28, 0}, {0xa8, 0} }, { {0x29, 0}, {0xa9, 0} }, + { {0x2a, 0}, {0xaa, 0} }, { {0x2b, 0}, {0xab, 0} }, + { {0x2c, 0}, {0xac, 0} }, { {0x2d, 0}, {0xad, 0} }, + { {0x2e, 0}, {0xae, 0} }, { {0x2f, 0}, {0xaf, 0} }, + { {0x30, 0}, {0xb0, 0} }, { {0x31, 0}, {0xb1, 0} }, + { {0x32, 0}, {0xb2, 0} }, { {0x33, 0}, {0xb3, 0} }, + { {0x34, 0}, {0xb4, 0} }, { {0x35, 0}, {0xb5, 0} }, + { {0x36, 0}, {0xb6, 0} }, { {0x37, 0}, {0xb7, 0} }, + { {0x38, 0}, {0xb8, 0} }, { {0x39, 0}, {0xb9, 0} }, + { {0x3a, 0}, {0xba, 0} }, { {0x3b, 0}, {0xbb, 0} }, + { {0x3c, 0}, {0xbc, 0} }, { {0x3d, 0}, {0xbd, 0} }, + { {0x3e, 0}, {0xbe, 0} }, { {0x3f, 0}, {0xbf, 0} }, + { {0x40, 0}, {0xc0, 0} }, { {0x41, 0}, {0xc1, 0} }, + { {0x42, 0}, {0xc2, 0} }, { {0x43, 0}, {0xc3, 0} }, + { {0x44, 0}, {0xc4, 0} }, { {0x45, 0}, {0xc5, 0} }, + { {0x46, 0}, {0xc6, 0} }, { {0x47, 0}, {0xc7, 0} }, + { {0x48, 0}, {0xc8, 0} }, { {0x49, 0}, {0xc9, 0} }, + { {0x4a, 0}, {0xca, 0} }, { {0x4b, 0}, {0xcb, 0} }, + { {0x4c, 0}, {0xcc, 0} }, { {0x4d, 0}, {0xcd, 0} }, + { {0x4e, 0}, {0xce, 0} }, { {0x4f, 0}, {0xcf, 0} }, + { {0x50, 0}, {0xd0, 0} }, { {0x51, 0}, {0xd1, 0} }, + { {0x52, 0}, {0xd2, 0} }, { {0x53, 0}, {0xd3, 0} }, + { {0}, {0} }, { {0}, {0} }, + { {0x5e, 0}, {0xde, 0} }, { {0x60, 0}, {0xe0, 0} }, /*054*/ + { {0x61, 0}, {0xe1, 0} }, { {0}, {0} }, + { {0}, {0} }, { {0}, {0} }, /*058*/ + { {0}, {0} }, { {0}, {0} }, + { {0}, {0} }, { {0}, {0} }, /*05c*/ + { {0}, {0} }, { {0}, {0} }, + { {0}, {0} }, { {0}, {0} }, /*060*/ + { {0}, {0} }, { {0}, {0} }, + { {0}, {0} }, { {0}, {0} }, /*064*/ + { {0}, {0} }, { {0}, {0} }, + { {0}, {0} }, { {0}, {0} }, /*068*/ + { {0}, {0} }, { {0}, {0} }, + { {0}, {0} }, { {0}, {0} }, /*06c*/ + { {0}, {0} }, { {0}, {0} }, + { {0}, {0} }, { {0}, {0} }, /*070*/ + { {0}, {0} }, { {0}, {0} }, + { {0}, {0} }, { {0}, {0} }, /*074*/ + { {0}, {0} }, { {0}, {0} }, + { {0}, {0} }, { {0}, {0} }, /*078*/ + { {0}, {0} }, { {0}, {0} }, + { {0}, {0} }, { {0}, {0} }, /*07c*/ + { {0}, {0} }, { {0}, {0} }, + { {0}, {0} }, { {0}, {0} }, /*080*/ + { {0}, {0} }, { {0}, {0} }, + { {0}, {0} }, { {0}, {0} }, /*084*/ + { {0}, {0} }, { {0}, {0} }, + { {0}, {0} }, { {0}, {0} }, /*088*/ + { {0}, {0} }, { {0}, {0} }, + { {0}, {0} }, { {0}, {0} }, /*08c*/ + { {0}, {0} }, { {0}, {0} }, + { {0}, {0} }, { {0}, {0} }, /*090*/ + { {0}, {0} }, { {0}, {0} }, + { {0}, {0} }, { {0}, {0} }, /*094*/ + { {0}, {0} }, { {0}, {0} }, + { {0}, {0} }, { {0}, {0} }, /*098*/ + { {0}, {0} }, { {0}, {0} }, + { {0}, {0} }, { {0}, {0} }, /*09c*/ + { {0}, {0} }, { {0}, {0} }, + { {0}, {0} }, { {0}, {0} }, /*0a0*/ + { {0}, {0} }, { {0}, {0} }, + { {0}, {0} }, { {0}, {0} }, /*0a4*/ + { {0}, {0} }, { {0}, {0} }, + { {0}, {0} }, { {0}, {0} }, /*0a8*/ + { {0}, {0} }, { {0}, {0} }, + { {0}, {0} }, { {0}, {0} }, /*0ac*/ + { {0}, {0} }, { {0}, {0} }, + { {0}, {0} }, { {0}, {0} }, /*0b0*/ + { {0}, {0} }, { {0}, {0} }, + { {0}, {0} }, { {0}, {0} }, /*0b4*/ + { {0}, {0} }, { {0}, {0} }, + { {0}, {0} }, { {0}, {0} }, /*0b8*/ + { {0}, {0} }, { {0}, {0} }, + { {0}, {0} }, { {0}, {0} }, /*0bc*/ + { {0}, {0} }, { {0}, {0} }, + { {0}, {0} }, { {0}, {0} }, /*0c0*/ + { {0}, {0} }, { {0}, {0} }, + { {0}, {0} }, { {0}, {0} }, /*0c4*/ + { {0}, {0} }, { {0}, {0} }, + { {0}, {0} }, { {0}, {0} }, /*0c8*/ + { {0}, {0} }, { {0}, {0} }, + { {0}, {0} }, { {0}, {0} }, /*0cc*/ + { {0}, {0} }, { {0}, {0} }, + { {0}, {0} }, { {0}, {0} }, /*0d0*/ + { {0}, {0} }, { {0}, {0} }, + { {0}, {0} }, { {0}, {0} }, /*0d4*/ + { {0}, {0} }, { {0}, {0} }, + { {0}, {0} }, { {0}, {0} }, /*0d8*/ + { {0}, {0} }, { {0}, {0} }, + { {0}, {0} }, { {0}, {0} }, /*0dc*/ + { {0}, {0} }, { {0}, {0} }, + { {0}, {0} }, { {0}, {0} }, /*0e0*/ + { {0}, {0} }, { {0}, {0} }, + { {0}, {0} }, { {0}, {0} }, /*0e4*/ + { {0}, {0} }, { {0}, {0} }, + { {0}, {0} }, { {0}, {0} }, /*0e8*/ + { {0}, {0} }, { {0}, {0} }, + { {0}, {0} }, { {0}, {0} }, /*0ec*/ + { {0}, {0} }, { {0}, {0} }, + { {0}, {0} }, { {0}, {0} }, /*0f0*/ + { {0}, {0} }, { {0}, {0} }, + { {0}, {0} }, { {0}, {0} }, /*0f4*/ + { {0}, {0} }, { {0}, {0} }, + { {0}, {0} }, { {0}, {0} }, /*0f8*/ + { {0}, {0} }, { {0}, {0} }, + { {0}, {0} }, { {0}, {0} }, /*0fc*/ + { {0}, {0} }, { {0}, {0} }, + { {0}, {0} }, { {0}, {0} }, /*100*/ + { {0}, {0} }, { {0}, {0} }, + { {0}, {0} }, { {0}, {0} }, /*104*/ + { {0}, {0} }, { {0}, {0} }, + { {0}, {0} }, { {0}, {0} }, /*108*/ + { {0}, {0} }, { {0}, {0} }, + { {0}, {0} }, { {0}, {0} }, /*10c*/ + { {0}, {0} }, { {0}, {0} }, + { {0}, {0} }, { {0}, {0} }, /*110*/ + { {0}, {0} }, { {0}, {0} }, + { {0}, {0} }, { {0}, {0} }, /*114*/ + { {0}, {0} }, { {0}, {0} }, + { {0}, {0} }, { {0}, {0} }, /*118*/ + { {0x57, 0}, {0xd7, 0} }, { {0}, {0} }, + { {0}, {0} }, { {0}, {0} }, /*11c*/ + { {0}, {0} }, { {0}, {0} }, + { {0}, {0} }, { {0}, {0} }, /*120*/ + { {0}, {0} }, { {0}, {0} }, + { {0}, {0} }, { {0}, {0} }, /*124*/ + { {0}, {0} }, { {0}, {0} }, + { {0}, {0} }, { {0}, {0} }, /*128*/ + { {0}, {0} }, { {0}, {0} }, + { {0}, {0} }, { {0}, {0} }, /*12c*/ + { {0}, {0} }, { {0}, {0} }, + { {0}, {0} }, { {0}, {0} }, /*130*/ + { {0}, {0} }, { {0x5f, 0}, {0xdf, 0} }, + { {0}, {0} }, { {0x37, 0}, {0xb7, 0} }, /*134*/ + { {0x66, 0}, {0xe6, 0} }, { {0x55, 0}, {0xd5, 0} }, + { {0}, {0} }, { {0}, {0} }, /*138*/ + { {0}, {0} }, { {0}, {0} }, + { {0}, {0} }, { {0}, {0} }, /*13c*/ + { {0}, {0} }, { {0}, {0} }, + { {0}, {0} }, { {0}, {0} }, /*140*/ + { {0}, {0} }, { {0}, {0} }, + { {0x46, 0}, {0xc6, 0} }, { {0x63, 0}, {0xe3, 0} }, /*144*/ + { {0x5b, 0}, {0xdb, 0} }, { {0x5c, 0}, {0xdc, 0} }, + { {0}, {0} }, { {0x58, 0}, {0xd8, 0} }, /*148*/ + { {0}, {0} }, { {0x5a, 0}, {0xda, 0} }, + { {0}, {0} }, { {0x65, 0}, {0xe5, 0} }, /*14c*/ + { {0x59, 0}, {0xd9, 0} }, { {0x5d, 0}, {0xdd, 0} }, + { {0x62, 0}, {0xe2, 0} }, { {0x64, 0}, {0xe4, 0} }, /*150*/ + { {0}, {0} }, { {0}, {0} }, + { {0}, {0} }, { {0}, {0} }, /*154*/ + { {0}, {0} }, { {0}, {0} }, + { {0}, {0} }, { {0x54, 0}, {0xd4, 0} }, /*158*/ + { {0x67, 0}, {0xe7, 0} }, { {0x56, 0}, {0xd6, 0} }, + { {0}, {0} }, { {0}, {0} }, /*15c*/ + { {0}, {0} }, { {0}, {0} }, + { {0}, {0} }, { {0}, {0} }, /*160*/ + { {0}, {0} }, { {0}, {0} }, + { {0}, {0} }, { {0}, {0} }, /*164*/ + { {0}, {0} }, { {0}, {0} }, + { {0}, {0} }, { {0}, {0} }, /*168*/ + { {0}, {0} }, { {0}, {0} }, + { {0}, {0} }, { {0}, {0} }, /*16c*/ + { {0}, {0} }, { {0}, {0} }, + { {0}, {0} }, { {0}, {0} }, /*170*/ + { {0}, {0} }, { {0}, {0} }, + { {0}, {0} }, { {0}, {0} }, /*174*/ + { {0}, {0} }, { {0}, {0} }, + { {0}, {0} }, { {0}, {0} }, /*148*/ + { {0}, {0} }, { {0}, {0} }, + { {0}, {0} }, { {0}, {0} }, /*17c*/ + { {0}, {0} }, { {0}, {0} }, + { {0}, {0} }, { {0}, {0} }, /*180*/ + { {0}, {0} }, { {0}, {0} }, + { {0}, {0} }, { {0}, {0} }, /*184*/ + { {0}, {0} }, { {0}, {0} }, + { {0}, {0} }, { {0}, {0} }, /*188*/ + { {0}, {0} }, { {0}, {0} }, + { {0}, {0} }, { {0}, {0} }, /*18c*/ + { {0}, {0} }, { {0}, {0} }, + { {0}, {0} }, { {0}, {0} }, /*190*/ + { {0}, {0} }, { {0}, {0} }, + { {0}, {0} }, { {0}, {0} }, /*194*/ + { {0}, {0} }, { {0}, {0} }, + { {0}, {0} }, { {0}, {0} }, /*198*/ + { {0}, {0} }, { {0}, {0} }, + { {0}, {0} }, { {0}, {0} }, /*19c*/ + { {0}, {0} }, { {0}, {0} }, + { {0}, {0} }, { {0}, {0} }, /*1a0*/ + { {0}, {0} }, { {0}, {0} }, + { {0}, {0} }, { {0}, {0} }, /*1a4*/ + { {0}, {0} }, { {0}, {0} }, + { {0}, {0} }, { {0}, {0} }, /*1a8*/ + { {0}, {0} }, { {0}, {0} }, + { {0}, {0} }, { {0}, {0} }, /*1ac*/ + { {0}, {0} }, { {0}, {0} }, + { {0}, {0} }, { {0}, {0} }, /*1b0*/ + { {0}, {0} }, { {0}, {0} }, + { {0}, {0} }, { {0}, {0} }, /*1b4*/ + { {0}, {0} }, { {0}, {0} }, + { {0}, {0} }, { {0}, {0} }, /*1b8*/ + { {0}, {0} }, { {0}, {0} }, + { {0}, {0} }, { {0}, {0} }, /*1bc*/ + { {0}, {0} }, { {0}, {0} }, + { {0}, {0} }, { {0}, {0} }, /*1c0*/ + { {0}, {0} }, { {0}, {0} }, + { {0}, {0} }, { {0}, {0} }, /*1c4*/ + { {0}, {0} }, { {0}, {0} }, + { {0}, {0} }, { {0}, {0} }, /*1c8*/ + { {0}, {0} }, { {0}, {0} }, + { {0}, {0} }, { {0}, {0} }, /*1cc*/ + { {0}, {0} }, { {0}, {0} }, + { {0}, {0} }, { {0}, {0} }, /*1d0*/ + { {0}, {0} }, { {0}, {0} }, + { {0}, {0} }, { {0}, {0} }, /*1d4*/ + { {0}, {0} }, { {0}, {0} }, + { {0}, {0} }, { {0}, {0} }, /*1d8*/ + { {0}, {0} }, { {0}, {0} }, + { {0}, {0} }, { {0}, {0} }, /*1dc*/ + { {0}, {0} }, { {0}, {0} }, + { {0}, {0} }, { {0}, {0} }, /*1e0*/ + { {0}, {0} }, { {0}, {0} }, + { {0}, {0} }, { {0}, {0} }, /*1e4*/ + { {0}, {0} }, { {0}, {0} }, + { {0}, {0} }, { {0}, {0} }, /*1e8*/ + { {0}, {0} }, { {0}, {0} }, + { {0}, {0} }, { {0}, {0} }, /*1ec*/ + { {0}, {0} }, { {0}, {0} }, + { {0}, {0} }, { {0}, {0} }, /*1f0*/ + { {0}, {0} }, { {0}, {0} }, + { {0}, {0} }, { {0}, {0} }, /*1f4*/ + { {0}, {0} }, { {0}, {0} }, + { {0}, {0} }, { {0}, {0} }, /*1f8*/ + { {0}, {0} }, { {0}, {0} }, + { {0}, {0} }, { {0}, {0} } /*1fc*/ + // clang-format on +}; + +/* Remapping as follows: + + - Left Windows (E0 5B) -> 54; + - Right Windows (E0 5C) -> 56; + - Menu (E0 5D) -> 5C. + */ +const scancode scancode_olivetti_m240[512] = { + // clang-format off + { {0}, {0} }, { {0x01, 0}, {0x81, 0} }, + { {0x02, 0}, {0x82, 0} }, { {0x03, 0}, {0x83, 0} }, + { {0x04, 0}, {0x84, 0} }, { {0x05, 0}, {0x85, 0} }, + { {0x06, 0}, {0x86, 0} }, { {0x07, 0}, {0x87, 0} }, + { {0x08, 0}, {0x88, 0} }, { {0x09, 0}, {0x89, 0} }, + { {0x0a, 0}, {0x8a, 0} }, { {0x0b, 0}, {0x8b, 0} }, + { {0x0c, 0}, {0x8c, 0} }, { {0x0d, 0}, {0x8d, 0} }, + { {0x0e, 0}, {0x8e, 0} }, { {0x0f, 0}, {0x8f, 0} }, + { {0x10, 0}, {0x90, 0} }, { {0x11, 0}, {0x91, 0} }, + { {0x12, 0}, {0x92, 0} }, { {0x13, 0}, {0x93, 0} }, + { {0x14, 0}, {0x94, 0} }, { {0x15, 0}, {0x95, 0} }, + { {0x16, 0}, {0x96, 0} }, { {0x17, 0}, {0x97, 0} }, + { {0x18, 0}, {0x98, 0} }, { {0x19, 0}, {0x99, 0} }, + { {0x1a, 0}, {0x9a, 0} }, { {0x1b, 0}, {0x9b, 0} }, + { {0x1c, 0}, {0x9c, 0} }, { {0x1d, 0}, {0x9d, 0} }, + { {0x1e, 0}, {0x9e, 0} }, { {0x1f, 0}, {0x9f, 0} }, + { {0x20, 0}, {0xa0, 0} }, { {0x21, 0}, {0xa1, 0} }, + { {0x22, 0}, {0xa2, 0} }, { {0x23, 0}, {0xa3, 0} }, + { {0x24, 0}, {0xa4, 0} }, { {0x25, 0}, {0xa5, 0} }, + { {0x26, 0}, {0xa6, 0} }, { {0x27, 0}, {0xa7, 0} }, + { {0x28, 0}, {0xa8, 0} }, { {0x29, 0}, {0xa9, 0} }, + { {0x2a, 0}, {0xaa, 0} }, { {0x2b, 0}, {0xab, 0} }, + { {0x2c, 0}, {0xac, 0} }, { {0x2d, 0}, {0xad, 0} }, + { {0x2e, 0}, {0xae, 0} }, { {0x2f, 0}, {0xaf, 0} }, + { {0x30, 0}, {0xb0, 0} }, { {0x31, 0}, {0xb1, 0} }, + { {0x32, 0}, {0xb2, 0} }, { {0x33, 0}, {0xb3, 0} }, + { {0x34, 0}, {0xb4, 0} }, { {0x35, 0}, {0xb5, 0} }, + { {0x36, 0}, {0xb6, 0} }, { {0x37, 0}, {0xb7, 0} }, + { {0x38, 0}, {0xb8, 0} }, { {0x39, 0}, {0xb9, 0} }, + { {0x3a, 0}, {0xba, 0} }, { {0x3b, 0}, {0xbb, 0} }, + { {0x3c, 0}, {0xbc, 0} }, { {0x3d, 0}, {0xbd, 0} }, + { {0x3e, 0}, {0xbe, 0} }, { {0x3f, 0}, {0xbf, 0} }, + { {0x40, 0}, {0xc0, 0} }, { {0x41, 0}, {0xc1, 0} }, + { {0x42, 0}, {0xc2, 0} }, { {0x43, 0}, {0xc3, 0} }, + { {0x44, 0}, {0xc4, 0} }, { {0x45, 0}, {0xc5, 0} }, + { {0x46, 0}, {0xc6, 0} }, { {0x47, 0}, {0xc7, 0} }, + { {0x48, 0}, {0xc8, 0} }, { {0x49, 0}, {0xc9, 0} }, + { {0x4a, 0}, {0xca, 0} }, { {0x4b, 0}, {0xcb, 0} }, + { {0x4c, 0}, {0xcc, 0} }, { {0x4d, 0}, {0xcd, 0} }, + { {0x4e, 0}, {0xce, 0} }, { {0x4f, 0}, {0xcf, 0} }, + { {0x50, 0}, {0xd0, 0} }, { {0x51, 0}, {0xd1, 0} }, + { {0x52, 0}, {0xd2, 0} }, { {0x53, 0}, {0xd3, 0} }, + { {0}, {0} }, { {0}, {0} }, + { {0}, {0} }, { {0}, {0} }, /*054*/ + { {0}, {0} }, { {0}, {0} }, + { {0}, {0} }, { {0}, {0} }, /*058*/ + { {0}, {0} }, { {0}, {0} }, + { {0}, {0} }, { {0}, {0} }, /*05c*/ + { {0}, {0} }, { {0}, {0} }, + { {0}, {0} }, { {0}, {0} }, /*060*/ + { {0}, {0} }, { {0}, {0} }, + { {0}, {0} }, { {0}, {0} }, /*064*/ + { {0}, {0} }, { {0}, {0} }, + { {0}, {0} }, { {0}, {0} }, /*068*/ + { {0}, {0} }, { {0}, {0} }, + { {0}, {0} }, { {0}, {0} }, /*06c*/ + { {0}, {0} }, { {0}, {0} }, + { {0}, {0} }, { {0}, {0} }, /*070*/ + { {0}, {0} }, { {0}, {0} }, + { {0}, {0} }, { {0}, {0} }, /*074*/ + { {0}, {0} }, { {0}, {0} }, + { {0}, {0} }, { {0}, {0} }, /*078*/ + { {0}, {0} }, { {0}, {0} }, + { {0}, {0} }, { {0}, {0} }, /*07c*/ + { {0}, {0} }, { {0}, {0} }, + { {0}, {0} }, { {0}, {0} }, /*080*/ + { {0}, {0} }, { {0}, {0} }, + { {0}, {0} }, { {0}, {0} }, /*084*/ + { {0}, {0} }, { {0}, {0} }, + { {0}, {0} }, { {0}, {0} }, /*088*/ + { {0}, {0} }, { {0}, {0} }, + { {0}, {0} }, { {0}, {0} }, /*08c*/ + { {0}, {0} }, { {0}, {0} }, + { {0}, {0} }, { {0}, {0} }, /*090*/ + { {0}, {0} }, { {0}, {0} }, + { {0}, {0} }, { {0}, {0} }, /*094*/ + { {0}, {0} }, { {0}, {0} }, + { {0}, {0} }, { {0}, {0} }, /*098*/ + { {0}, {0} }, { {0}, {0} }, + { {0}, {0} }, { {0}, {0} }, /*09c*/ + { {0}, {0} }, { {0}, {0} }, + { {0}, {0} }, { {0}, {0} }, /*0a0*/ + { {0}, {0} }, { {0}, {0} }, + { {0}, {0} }, { {0}, {0} }, /*0a4*/ + { {0}, {0} }, { {0}, {0} }, + { {0}, {0} }, { {0}, {0} }, /*0a8*/ + { {0}, {0} }, { {0}, {0} }, + { {0}, {0} }, { {0}, {0} }, /*0ac*/ + { {0}, {0} }, { {0}, {0} }, + { {0}, {0} }, { {0}, {0} }, /*0b0*/ + { {0}, {0} }, { {0}, {0} }, + { {0}, {0} }, { {0}, {0} }, /*0b4*/ + { {0}, {0} }, { {0}, {0} }, + { {0}, {0} }, { {0}, {0} }, /*0b8*/ + { {0}, {0} }, { {0}, {0} }, + { {0}, {0} }, { {0}, {0} }, /*0bc*/ + { {0}, {0} }, { {0}, {0} }, + { {0}, {0} }, { {0}, {0} }, /*0c0*/ + { {0}, {0} }, { {0}, {0} }, + { {0}, {0} }, { {0}, {0} }, /*0c4*/ + { {0}, {0} }, { {0}, {0} }, + { {0}, {0} }, { {0}, {0} }, /*0c8*/ + { {0}, {0} }, { {0}, {0} }, + { {0}, {0} }, { {0}, {0} }, /*0cc*/ + { {0}, {0} }, { {0}, {0} }, + { {0}, {0} }, { {0}, {0} }, /*0d0*/ + { {0}, {0} }, { {0}, {0} }, + { {0}, {0} }, { {0}, {0} }, /*0d4*/ + { {0}, {0} }, { {0}, {0} }, + { {0}, {0} }, { {0}, {0} }, /*0d8*/ + { {0}, {0} }, { {0}, {0} }, + { {0}, {0} }, { {0}, {0} }, /*0dc*/ + { {0}, {0} }, { {0}, {0} }, + { {0}, {0} }, { {0}, {0} }, /*0e0*/ + { {0}, {0} }, { {0}, {0} }, + { {0}, {0} }, { {0}, {0} }, /*0e4*/ + { {0}, {0} }, { {0}, {0} }, + { {0}, {0} }, { {0}, {0} }, /*0e8*/ + { {0}, {0} }, { {0}, {0} }, + { {0}, {0} }, { {0}, {0} }, /*0ec*/ + { {0}, {0} }, { {0}, {0} }, + { {0}, {0} }, { {0}, {0} }, /*0f0*/ + { {0}, {0} }, { {0}, {0} }, + { {0}, {0} }, { {0}, {0} }, /*0f4*/ + { {0}, {0} }, { {0}, {0} }, + { {0}, {0} }, { {0}, {0} }, /*0f8*/ + { {0}, {0} }, { {0}, {0} }, + { {0}, {0} }, { {0}, {0} }, /*0fc*/ + { {0}, {0} }, { {0}, {0} }, + { {0}, {0} }, { {0}, {0} }, /*100*/ + { {0}, {0} }, { {0}, {0} }, + { {0}, {0} }, { {0}, {0} }, /*104*/ + { {0}, {0} }, { {0}, {0} }, + { {0}, {0} }, { {0}, {0} }, /*108*/ + { {0}, {0} }, { {0}, {0} }, + { {0}, {0} }, { {0}, {0} }, /*10c*/ + { {0}, {0} }, { {0}, {0} }, + { {0}, {0} }, { {0}, {0} }, /*110*/ + { {0}, {0} }, { {0}, {0} }, + { {0}, {0} }, { {0}, {0} }, /*114*/ + { {0}, {0} }, { {0}, {0} }, + { {0}, {0} }, { {0}, {0} }, /*118*/ + { {0x1c, 0}, {0x9c, 0} }, { {0x1d, 0}, {0x9d, 0} }, + { {0}, {0} }, { {0}, {0} }, /*11c*/ + { {0}, {0} }, { {0}, {0} }, + { {0}, {0} }, { {0}, {0} }, /*120*/ + { {0}, {0} }, { {0}, {0} }, + { {0}, {0} }, { {0}, {0} }, /*124*/ + { {0}, {0} }, { {0}, {0} }, + { {0}, {0} }, { {0}, {0} }, /*128*/ + { {0}, {0} }, { {0}, {0} }, + { {0}, {0} }, { {0}, {0} }, /*12c*/ + { {0}, {0} }, { {0}, {0} }, + { {0}, {0} }, { {0}, {0} }, /*130*/ + { {0}, {0} }, { {0x35, 0}, {0xb5, 0} }, + { {0}, {0} }, { {0x37, 0}, {0xb7, 0} }, /*134*/ + { {0x38, 0}, {0xb8, 0} }, { {0}, {0} }, + { {0}, {0} }, { {0}, {0} }, /*138*/ + { {0}, {0} }, { {0}, {0} }, + { {0}, {0} }, { {0}, {0} }, /*13c*/ + { {0}, {0} }, { {0}, {0} }, + { {0}, {0} }, { {0}, {0} }, /*140*/ + { {0}, {0} }, { {0}, {0} }, + { {0x46, 0}, {0xc6, 0} }, { {0x47, 0}, {0xc7, 0} }, /*144*/ + { {0x48, 0}, {0xc8, 0} }, { {0x49, 0}, {0xc9, 0} }, + { {0}, {0} }, { {0x4b, 0}, {0xcb, 0} }, /*148*/ + { {0}, {0} }, { {0x4d, 0}, {0xcd, 0} }, + { {0}, {0} }, { {0x4f, 0}, {0xcf, 0} }, /*14c*/ + { {0x50, 0}, {0xd0, 0} }, { {0x51, 0}, {0xd1, 0} }, + { {0x52, 0}, {0xd2, 0} }, { {0x53, 0}, {0xd3, 0} }, /*150*/ + { {0}, {0} }, { {0}, {0} }, + { {0}, {0} }, { {0}, {0} }, /*154*/ + { {0}, {0} }, { {0}, {0} }, + { {0}, {0} }, { {0}, {0} }, /*158*/ + { {0}, {0} }, { {0x54, 0}, {0xd4, 0} }, + { {0x56, 0}, {0xd6, 0} }, { {0x5c, 0}, {0xdc, 0} }, /*15c*/ + { {0}, {0} }, { {0}, {0} }, + { {0}, {0} }, { {0}, {0} }, /*160*/ + { {0}, {0} }, { {0}, {0} }, + { {0}, {0} }, { {0}, {0} }, /*164*/ + { {0}, {0} }, { {0}, {0} }, + { {0}, {0} }, { {0}, {0} }, /*168*/ + { {0}, {0} }, { {0}, {0} }, + { {0}, {0} }, { {0}, {0} }, /*16c*/ + { {0}, {0} }, { {0}, {0} }, + { {0}, {0} }, { {0}, {0} }, /*170*/ + { {0}, {0} }, { {0}, {0} }, + { {0}, {0} }, { {0}, {0} }, /*174*/ + { {0}, {0} }, { {0}, {0} }, + { {0}, {0} }, { {0}, {0} }, /*148*/ + { {0}, {0} }, { {0}, {0} }, + { {0}, {0} }, { {0}, {0} }, /*17c*/ + { {0}, {0} }, { {0}, {0} }, + { {0}, {0} }, { {0}, {0} }, /*180*/ + { {0}, {0} }, { {0}, {0} }, + { {0}, {0} }, { {0}, {0} }, /*184*/ + { {0}, {0} }, { {0}, {0} }, + { {0}, {0} }, { {0}, {0} }, /*188*/ + { {0}, {0} }, { {0}, {0} }, + { {0}, {0} }, { {0}, {0} }, /*18c*/ + { {0}, {0} }, { {0}, {0} }, + { {0}, {0} }, { {0}, {0} }, /*190*/ + { {0}, {0} }, { {0}, {0} }, + { {0}, {0} }, { {0}, {0} }, /*194*/ + { {0}, {0} }, { {0}, {0} }, + { {0}, {0} }, { {0}, {0} }, /*198*/ + { {0}, {0} }, { {0}, {0} }, + { {0}, {0} }, { {0}, {0} }, /*19c*/ + { {0}, {0} }, { {0}, {0} }, + { {0}, {0} }, { {0}, {0} }, /*1a0*/ + { {0}, {0} }, { {0}, {0} }, + { {0}, {0} }, { {0}, {0} }, /*1a4*/ + { {0}, {0} }, { {0}, {0} }, + { {0}, {0} }, { {0}, {0} }, /*1a8*/ + { {0}, {0} }, { {0}, {0} }, + { {0}, {0} }, { {0}, {0} }, /*1ac*/ + { {0}, {0} }, { {0}, {0} }, + { {0}, {0} }, { {0}, {0} }, /*1b0*/ + { {0}, {0} }, { {0}, {0} }, + { {0}, {0} }, { {0}, {0} }, /*1b4*/ + { {0}, {0} }, { {0}, {0} }, + { {0}, {0} }, { {0}, {0} }, /*1b8*/ + { {0}, {0} }, { {0}, {0} }, + { {0}, {0} }, { {0}, {0} }, /*1bc*/ + { {0}, {0} }, { {0}, {0} }, + { {0}, {0} }, { {0}, {0} }, /*1c0*/ + { {0}, {0} }, { {0}, {0} }, + { {0}, {0} }, { {0}, {0} }, /*1c4*/ + { {0}, {0} }, { {0}, {0} }, + { {0}, {0} }, { {0}, {0} }, /*1c8*/ + { {0}, {0} }, { {0}, {0} }, + { {0}, {0} }, { {0}, {0} }, /*1cc*/ + { {0}, {0} }, { {0}, {0} }, + { {0}, {0} }, { {0}, {0} }, /*1d0*/ + { {0}, {0} }, { {0}, {0} }, + { {0}, {0} }, { {0}, {0} }, /*1d4*/ + { {0}, {0} }, { {0}, {0} }, + { {0}, {0} }, { {0}, {0} }, /*1d8*/ + { {0}, {0} }, { {0}, {0} }, + { {0}, {0} }, { {0}, {0} }, /*1dc*/ + { {0}, {0} }, { {0}, {0} }, + { {0}, {0} }, { {0}, {0} }, /*1e0*/ + { {0}, {0} }, { {0}, {0} }, + { {0}, {0} }, { {0}, {0} }, /*1e4*/ + { {0}, {0} }, { {0}, {0} }, + { {0}, {0} }, { {0}, {0} }, /*1e8*/ + { {0}, {0} }, { {0}, {0} }, + { {0}, {0} }, { {0}, {0} }, /*1ec*/ + { {0}, {0} }, { {0}, {0} }, + { {0}, {0} }, { {0}, {0} }, /*1f0*/ + { {0}, {0} }, { {0}, {0} }, + { {0}, {0} }, { {0}, {0} }, /*1f4*/ + { {0}, {0} }, { {0}, {0} }, + { {0}, {0} }, { {0}, {0} }, /*1f8*/ + { {0}, {0} }, { {0}, {0} }, + { {0}, {0} }, { {0}, {0} } /*1fc*/ + // clang-format on +}; static void m24_kbd_init(m24_kbd_t *kbd) { - + /* Initialize the keyboard. */ io_sethandler(0x0060, 2, - m24_kbd_read, NULL, NULL, m24_kbd_write, NULL, NULL, kbd); + m24_kbd_read, NULL, NULL, m24_kbd_write, NULL, NULL, kbd); io_sethandler(0x0064, 1, - m24_kbd_read, NULL, NULL, m24_kbd_write, NULL, NULL, kbd); + m24_kbd_read, NULL, NULL, m24_kbd_write, NULL, NULL, kbd); keyboard_send = m24_kbd_adddata_ex; m24_kbd_reset(kbd); timer_add(&kbd->send_delay_timer, m24_kbd_poll, kbd, 1); - /* Tell mouse driver about our internal mouse. */ - mouse_reset(); - mouse_set_poll(ms_poll, kbd); + if (mouse_type == MOUSE_TYPE_INTERNAL) { + /* Tell mouse driver about our internal mouse. */ + mouse_reset(); + mouse_set_buttons(2); + mouse_set_poll(ms_poll, kbd); + } - keyboard_set_table(scancode_xt); + keyboard_set_table((kbd->id == 0x01) ? scancode_olivetti_m24_deluxe : scancode_olivetti_m240); keyboard_set_is_amstrad(0); } - static void m19_vid_out(uint16_t addr, uint8_t val, void *priv) { - m19_vid_t *vid = (m19_vid_t *)priv; - int oldmode = vid->mode; + m19_vid_t *vid = (m19_vid_t *) priv; + int oldmode = vid->mode; /* activating plantronics mode */ if (addr == 0x3dd) { - /* already in graphics mode */ - if ((val & 0x30) && (vid->ogc.cga.cgamode & 0x2)) - vid->mode = PLANTRONICS_MODE; - else - vid->mode = OLIVETTI_OGC_MODE; - /* setting graphics mode */ + /* already in graphics mode */ + if ((val & 0x30) && (vid->ogc.cga.cgamode & 0x2)) + vid->mode = PLANTRONICS_MODE; + else + vid->mode = OLIVETTI_OGC_MODE; + /* setting graphics mode */ } else if (addr == 0x3d8) { - if ((val & 0x2) && (vid->colorplus.control & 0x30)) - vid->mode = PLANTRONICS_MODE; - else - vid->mode = OLIVETTI_OGC_MODE; + if ((val & 0x2) && (vid->colorplus.control & 0x30)) + vid->mode = PLANTRONICS_MODE; + else + vid->mode = OLIVETTI_OGC_MODE; } /* video mode changed */ if (oldmode != vid->mode) { - /* activate Plantronics emulation */ - if (vid->mode == PLANTRONICS_MODE){ - timer_disable(&vid->ogc.cga.timer); - timer_set_delay_u64(&vid->colorplus.cga.timer, 0); - /* return to OGC mode */ - } else { - timer_disable(&vid->colorplus.cga.timer); - timer_set_delay_u64(&vid->ogc.cga.timer, 0); - } + /* activate Plantronics emulation */ + if (vid->mode == PLANTRONICS_MODE) { + timer_disable(&vid->ogc.cga.timer); + timer_set_delay_u64(&vid->colorplus.cga.timer, 0); + /* return to OGC mode */ + } else { + timer_disable(&vid->colorplus.cga.timer); + timer_set_delay_u64(&vid->ogc.cga.timer, 0); + } - colorplus_recalctimings(&vid->colorplus); - ogc_recalctimings(&vid->ogc); + colorplus_recalctimings(&vid->colorplus); + ogc_recalctimings(&vid->ogc); } colorplus_out(addr, val, &vid->colorplus); ogc_out(addr, val, &vid->ogc); } - static uint8_t m19_vid_in(uint16_t addr, void *priv) { - m19_vid_t *vid = (m19_vid_t *)priv; + m19_vid_t *vid = (m19_vid_t *) priv; if (vid->mode == PLANTRONICS_MODE) - return colorplus_in(addr, &vid->colorplus); + return colorplus_in(addr, &vid->colorplus); else - return ogc_in(addr, &vid->ogc); + return ogc_in(addr, &vid->ogc); } - static uint8_t m19_vid_read(uint32_t addr, void *priv) { - m19_vid_t *vid = (m19_vid_t *)priv; + m19_vid_t *vid = (m19_vid_t *) priv; vid->colorplus.cga.mapping = vid->ogc.cga.mapping; if (vid->mode == PLANTRONICS_MODE) - return colorplus_read(addr, &vid->colorplus); + return colorplus_read(addr, &vid->colorplus); else - return ogc_read(addr, &vid->ogc); + return ogc_read(addr, &vid->ogc); } - static void m19_vid_write(uint32_t addr, uint8_t val, void *priv) { - m19_vid_t *vid = (m19_vid_t *)priv; + m19_vid_t *vid = (m19_vid_t *) priv; colorplus_write(addr, val, &vid->colorplus); ogc_write(addr, val, &vid->ogc); } - static void m19_vid_close(void *priv) { - m19_vid_t *vid = (m19_vid_t *)priv; + m19_vid_t *vid = (m19_vid_t *) priv; free(vid->ogc.cga.vram); free(vid->colorplus.cga.vram); free(vid); } - static void m19_vid_speed_changed(void *priv) { - m19_vid_t *vid = (m19_vid_t *)priv; + m19_vid_t *vid = (m19_vid_t *) priv; colorplus_recalctimings(&vid->colorplus); ogc_recalctimings(&vid->ogc); } - static void m19_vid_init(m19_vid_t *vid) { device_context(&m19_vid_device); - /* int display_type; */ +#if 0 + int display_type; +#endif vid->mode = OLIVETTI_OGC_MODE; video_inform(VIDEO_FLAG_TYPE_CGA, &timing_m19_vid); - /* display_type = device_get_config_int("display_type"); */ +#if 0 + display_type = device_get_config_int("display_type"); +#endif /* OGC emulation part begin */ - loadfont_ex("roms/machines/m19/BIOS.BIN", 1, 90); + loadfont("roms/machines/m19/MBM2764-30 8514 107 AB PCF3.BIN", 7); /* composite is not working yet */ - vid->ogc.cga.composite = 0; // (display_type != CGA_RGB); - vid->ogc.cga.revision = device_get_config_int("composite_type"); + vid->ogc.cga.composite = 0; // (display_type != CGA_RGB); + vid->ogc.cga.revision = device_get_config_int("composite_type"); vid->ogc.cga.snow_enabled = device_get_config_int("snow_enabled"); vid->ogc.cga.vram = malloc(0x8000); - /* cga_comp_init(vid->ogc.cga.revision); */ +#if 0 + cga_comp_init(vid->ogc.cga.revision); +#endif vid->ogc.cga.rgb_type = device_get_config_int("rgb_type"); - cga_palette = (vid->ogc.cga.rgb_type << 1); + cga_palette = (vid->ogc.cga.rgb_type << 1); cgapal_rebuild(); ogc_mdaattr_rebuild(); /* color display */ - if (device_get_config_int("rgb_type")==0 || device_get_config_int("rgb_type") == 4) - vid->ogc.mono_display = 0; + if (device_get_config_int("rgb_type") == 0 || device_get_config_int("rgb_type") == 4) + vid->ogc.mono_display = 0; else - vid->ogc.mono_display = 1; + vid->ogc.mono_display = 1; /* OGC emulation part end */ /* Plantronics emulation part begin*/ /* composite is not working yet */ vid->colorplus.cga.composite = 0; //(display_type != CGA_RGB); - /* vid->colorplus.cga.snow_enabled = device_get_config_int("snow_enabled"); */ +#if 0 + vid->colorplus.cga.snow_enabled = device_get_config_int("snow_enabled"); +#endif vid->colorplus.cga.vram = malloc(0x8000); - /* vid->colorplus.cga.cgamode = 0x1; */ +#if 0 + vid->colorplus.cga.cgamode = 0x1; +#endif /* Plantronics emulation part end*/ timer_add(&vid->ogc.cga.timer, ogc_poll, &vid->ogc, 1); timer_add(&vid->colorplus.cga.timer, colorplus_poll, &vid->colorplus, 1); timer_disable(&vid->colorplus.cga.timer); - mem_mapping_add(&vid->ogc.cga.mapping, 0xb8000, 0x08000, m19_vid_read, NULL, NULL, m19_vid_write, NULL, NULL, NULL, MEM_MAPPING_EXTERNAL, vid); + mem_mapping_add(&vid->ogc.cga.mapping, 0xb8000, 0x08000, m19_vid_read, NULL, NULL, m19_vid_write, NULL, NULL, NULL, MEM_MAPPING_EXTERNAL, vid); io_sethandler(0x03d0, 0x0010, m19_vid_in, NULL, NULL, m19_vid_out, NULL, NULL, vid); vid->mode = OLIVETTI_OGC_MODE; @@ -586,176 +1553,251 @@ m19_vid_init(m19_vid_t *vid) device_context_restore(); } - const device_t m24_kbd_device = { - "Olivetti M24 keyboard and mouse", - "m24_kbd", - 0, - 0, - NULL, - m24_kbd_close, - m24_kbd_reset, - { NULL }, NULL, NULL + .name = "Olivetti M24 keyboard and mouse", + .internal_name = "m24_kbd", + .flags = 0, + .local = 0, + .init = NULL, + .close = m24_kbd_close, + .reset = m24_kbd_reset, + { .available = NULL }, + .speed_changed = NULL, + .force_redraw = NULL, + .config = NULL }; -const device_config_t m19_vid_config[] = -{ - { - /* Olivetti / ATT compatible displays */ - "rgb_type", "RGB type", CONFIG_SELECTION, "", CGA_RGB, "", { 0 }, - { - { - "Color", 0 - }, - { - "Green Monochrome", 1 - }, - { - "Amber Monochrome", 2 - }, - { - "Gray Monochrome", 3 - }, - { - "" - } - } - }, - { - "snow_enabled", "Snow emulation", CONFIG_BINARY, "", 1, - }, - { - "", "", -1 +const device_config_t m19_vid_config[] = { + // clang-format off + { + /* Olivetti / ATT compatible displays */ + .name = "rgb_type", + .description = "RGB type", + .type = CONFIG_SELECTION, + .default_string = "", + .default_int = CGA_RGB, + .file_filter = "", + .spinner = { 0 }, + .selection = { + { .description = "Color", .value = 0 }, + { .description = "Green Monochrome", .value = 1 }, + { .description = "Amber Monochrome", .value = 2 }, + { .description = "Gray Monochrome", .value = 3 }, + { .description = "" } } + }, + { + .name = "snow_enabled", + .description = "Snow emulation", + .type = CONFIG_BINARY, + .default_string = "", + .default_int = 1, + }, + { .name = "", .description = "", .type = CONFIG_END } + // clang-format on }; const device_t m19_vid_device = { - "Olivetti M19 graphics card", - "m19_vid", - 0, 0, - NULL, m19_vid_close, NULL, - { NULL }, - m19_vid_speed_changed, - NULL, - m19_vid_config + .name = "Olivetti M19 graphics card", + .internal_name = "m19_vid", + .flags = 0, + .local = 0, + .init = NULL, + .close = m19_vid_close, + .reset = NULL, + { .available = NULL }, + .speed_changed = m19_vid_speed_changed, + .force_redraw = NULL, + .config = m19_vid_config }; -const device_t * -m19_get_device(void) -{ - return &m19_vid_device; -} - - static uint8_t -m24_read(uint16_t port, void *priv) +m24_read(uint16_t port, UNUSED(void *priv)) { - uint8_t ret = 0x00; - int i, fdd_count = 0; + uint8_t ret = 0x00; + int fdd_count = 0; switch (port) { - /* - * port 66: - * DIPSW-0 on mainboard (off=present=1) - * bit 7 - 2764 (off) / 2732 (on) ROM (BIOS < 1.36) - * bit 7 - Use (off) / do not use (on) memory bank 1 (BIOS >= 1.36) - * bit 6 - n/a - * bit 5 - 8530 (off) / 8250 (on) SCC - * bit 4 - 8087 present - * bits 3-0 - installed memory - */ - case 0x66: - /* Switch 5 - 8087 present */ - if (hasfpu) - ret |= 0x10; - /* - * Switches 1, 2, 3, 4 - installed memory - * Switch 8 - Use memory bank 1 - */ - switch (mem_size) { - case 128: - ret |= 0x1; - break; - case 256: - ret |= 0x2|0x80; - break; - case 384: - ret |= 0x1|0x2|0x80; - break; - case 512: - ret |= 0x8; - break; - case 640: - default: - ret |= 0x1|0x8|0x80; - break; - } - /* - * port 67: - * DIPSW-1 on mainboard (off=present=1) - * bits 7-6 - number of drives - * bits 5-4 - display adapter - * bit 3 - video scroll CPU (on) / slow scroll (off) - * bit 2 - BIOS HD on mainboard (on) / on controller (off) - * bit 1 - FDD fast (off) / slow (on) start drive - * bit 0 - 96 TPI (720 KB 3.5") (off) / 48 TPI (360 KB 5.25") FDD drive - * - * Display adapter: - * off off 80x25 mono - * off on 40x25 color - * on off 80x25 color - * on on EGA/VGA (works only for BIOS ROM 1.43) - */ - case 0x67: - for (i = 0; i < FDD_NUM; i++) { - if (fdd_get_flags(i)) - fdd_count++; - } + case 0x62: + /* Control Port B Read */ + ret = 0xff; + break; - /* Switches 7, 8 - floppy drives. */ - if (!fdd_count) - ret |= 0x00; - else - ret |= ((fdd_count - 1) << 6); - - /* Switches 5, 6 - monitor type */ - if (video_is_mda()) - ret |= 0x30; - else if (video_is_cga()) - ret |= 0x20; /* 0x10 would be 40x25 */ - else - ret |= 0x0; - - /* Switch 3 - Disable internal BIOS HD */ - ret |= 0x4; - - /* Switch 2 - Set fast startup */ - ret |= 0x2; + case 0x65: + /* Communications Port Read */ + ret = 0xff; + break; + + /* + * port 66: + * DIPSW-0 on mainboard (off=present=1) + * bit 7 - 2764 (off) / 2732 (on) ROM (BIOS < 1.36) + * bit 7 - Use (off) / do not use (on) memory bank 1 (BIOS >= 1.36) + * bit 6 - n/a + * bit 5 - 8530 (off) / 8250 (on) SCC + * bit 4 - 8087 present + * bits 3-0 - installed memory + */ + case 0x66: + /* Switch 5 - 8087 present */ + if (hasfpu) + ret |= 0x10; + /* + * Switches 1, 2, 3, 4 - installed memory + * Switch 8 - Use memory bank 1 + */ + switch (mem_size) { + case 128: + ret |= 0x1; + break; + case 256: + ret |= 0x2; + break; + case 384: + ret |= 0x1 | 0x2 | 0x80; + break; + case 512: + ret |= 0x8; + break; + case 640: + ret |= 0x1 | 0x8 | 0x80; + break; + default: + break; + } + break; + + /* + * port 67: + * DIPSW-1 on mainboard (off=present=1) + * bits 7-6 - number of drives + * bits 5-4 - display adapter + * bit 3 - video scroll CPU (on) / slow scroll (off) + * bit 2 - BIOS HD on mainboard (on) / on controller (off) + * bit 1 - FDD fast (off) / slow (on) start drive + * bit 0 - 96 TPI (720 KB 3.5") (off) / 48 TPI (360 KB 5.25") FDD drive + * + * Display adapter: + * off off 80x25 mono + * off on 40x25 color + * on off 80x25 color + * on on EGA/VGA (works only for BIOS ROM 1.43) + */ + case 0x67: + for (uint8_t i = 0; i < FDD_NUM; i++) { + if (fdd_get_flags(i)) + fdd_count++; + } + + /* Switches 7, 8 - floppy drives. */ + if (!fdd_count) + ret |= 0x00; + else + ret |= ((fdd_count - 1) << 6); + + /* Switches 5, 6 - monitor type */ + if (video_is_mda()) + ret |= 0x30; + else if (video_is_cga()) + ret |= 0x20; /* 0x10 would be 40x25 */ + else + ret |= 0x0; + + /* Switch 4 - The M21/M24 Theory of Operation says + "Reserved for HDU", same as for Switch 3 */ + + /* Switch 3 - Disable internal BIOS HD */ + if (hdc_current != HDC_INTERNAL) + ret |= 0x4; + + /* Switch 2 - Set fast startup */ + ret |= 0x2; + + /* 1 = 720 kB (3.5"), 0 = 360 kB (5.25") */ + ret |= (fdd_doublestep_40(0) || fdd_doublestep_40(1)) ? 0x1 : 0x0; + break; + + default: + break; } - return(ret); + return ret; } - -const device_t * -m24_get_device(void) +static uint8_t +m240_read(uint16_t port, UNUSED(void *priv)) { - return &ogc_m24_device; + uint8_t ret = 0x00; + int fdd_count = 0; + + switch (port) { + case 0x62: + /* SWA on Olivetti M240 mainboard (off=1) */ + ret = 0x00; + if (ppi.pb & 0x8) { + /* Switches 4, 5 - floppy drives (number) */ + for (uint8_t i = 0; i < FDD_NUM; i++) { + if (fdd_get_flags(i)) + fdd_count++; + } + if (!fdd_count) + ret |= 0x00; + else + ret |= ((fdd_count - 1) << 2); + /* Switches 6, 7 - monitor type */ + if (video_is_mda()) + ret |= 0x3; + else if (video_is_cga()) + ret |= 0x2; /* 0x10 would be 40x25 */ + else + ret |= 0x0; + } else { + /* bit 2 always on */ + ret |= 0x4; + /* Switch 8 - 8087 FPU. */ + if (hasfpu) + ret |= 0x02; + } + break; + + case 0x63: + /* Olivetti M240 SWB: + - Bit 7: 1 = MFDD (= high-density) unit present (Customer Test will then always think Drive 2 is absent), + 0 = MFD unit absent; + - Bit 6: 1 = Second drive is 3.5" (for low density drive, this means 80-track), + 0 = Second drive is 5.25" (for low density drive, this means 40-track). + - Bit 5: 1 = First drive is 3.5" (for low density drive, this means 80-track), + 0 = First drive is 5.25" (for low density drive, this means 40-track). + */ + + ret = (fdd_is_hd(0) || fdd_is_hd(1)) ? 0x80 : 0x00; + ret |= fdd_doublestep_40(1) ? 0x40 : 0x00; + ret |= fdd_doublestep_40(0) ? 0x20 : 0x00; + break; + + default: + break; + } + + return ret; } - +/* + * Uses M21/M24/M240 keyboard controller and M24 102/103-key Deluxe keyboard. + */ int machine_xt_m24_init(const machine_t *model) { - int ret; + int ret; m24_kbd_t *m24_kbd; + nvr_t *nvr; - ret = bios_load_interleaved("roms/machines/m24/olivetti_m24_version_1.43_low.bin", - "roms/machines/m24/olivetti_m24_version_1.43_high.bin", - 0x000fc000, 16384, 0); + ret = bios_load_interleaved("roms/machines/m24/olivetti_m24_bios_version_1.44_low_even.bin", + "roms/machines/m24/olivetti_m24_bios_version_1.44_high_odd.bin", + 0x000fc000, 16384, 0); if (bios_only || !ret) - return ret; + return ret; m24_kbd = (m24_kbd_t *) malloc(sizeof(m24_kbd_t)); memset(m24_kbd, 0x00, sizeof(m24_kbd_t)); @@ -764,78 +1806,105 @@ machine_xt_m24_init(const machine_t *model) /* On-board FDC can be disabled only on M24SP */ if (fdc_type == FDC_INTERNAL) - device_add(&fdc_xt_device); + device_add(&fdc_xt_device); /* Address 66-67 = mainboard dip-switch settings */ - io_sethandler(0x0066, 2, m24_read, NULL, NULL, NULL, NULL, NULL, NULL); - - /* FIXME: make sure this is correct?? */ - device_add(&at_nvr_device); + io_sethandler(0x0065, 3, m24_read, NULL, NULL, NULL, NULL, NULL, NULL); standalone_gameport_type = &gameport_device; nmi_init(); - video_reset(gfxcard); + /* Allocate an NVR for this machine. */ + nvr = (nvr_t *) malloc(sizeof(nvr_t)); + if (nvr == NULL) + return 0; + memset(nvr, 0x00, sizeof(nvr_t)); - if (gfxcard == VID_INTERNAL) - device_add(&ogc_m24_device); + mm58174_init(nvr, model->nvrmask + 1); + + video_reset(gfxcard[0]); + + if (gfxcard[0] == VID_INTERNAL) + device_add(&ogc_m24_device); + + pit_devs[0].set_out_func(pit_devs[0].data, 1, pit_refresh_timer_xt); + + io_sethandler(0x0062, 1, m24_read, NULL, NULL, NULL, NULL, NULL, NULL); + + m24_kbd->id = 0x01; m24_kbd_init(m24_kbd); device_add_ex(&m24_kbd_device, m24_kbd); + if (hdc_current == HDC_INTERNAL) + device_add(&st506_xt_wd1002a_wx1_nobios_device); + return ret; } /* - * Current bugs: - * - handles only 360kb floppy drives (drive type and capacity selectable with jumpers mapped to unknown memory locations) + * Uses M21/M24/M240 keyboard controller and M240 keyboard. */ int machine_xt_m240_init(const machine_t *model) { - int ret; + int ret; + m24_kbd_t *m24_kbd; + nvr_t *nvr; ret = bios_load_interleaved("roms/machines/m240/olivetti_m240_pch6_2.04_low.bin", - "roms/machines/m240/olivetti_m240_pch5_2.04_high.bin", - 0x000f8000, 32768, 0); + "roms/machines/m240/olivetti_m240_pch5_2.04_high.bin", + 0x000f8000, 32768, 0); if (bios_only || !ret) - return ret; + return ret; + + m24_kbd = (m24_kbd_t *) malloc(sizeof(m24_kbd_t)); + memset(m24_kbd, 0x00, sizeof(m24_kbd_t)); machine_common_init(model); - pit_ctr_set_out_func(&pit->counters[1], pit_refresh_timer_xt); + pit_devs[0].set_out_func(pit_devs[0].data, 1, pit_refresh_timer_xt); /* Address 66-67 = mainboard dip-switch settings */ - io_sethandler(0x0066, 2, m24_read, NULL, NULL, NULL, NULL, NULL, NULL); + io_sethandler(0x0062, 2, m240_read, NULL, NULL, NULL, NULL, NULL, NULL); - /* + /* * port 60: should return jumper settings only under unknown conditions * SWB on mainboard (off=1) * bit 7 - use BIOS HD on mainboard (on) / on controller (off) * bit 6 - use OCG/CGA display adapter (on) / other display adapter (off) */ - device_add(&keyboard_at_olivetti_device); - device_add(&port_6x_olivetti_device); + m24_kbd->id = 0x10; - /* FIXME: make sure this is correct?? */ - device_add(&at_nvr_device); + m24_kbd_init(m24_kbd); + device_add_ex(&m24_kbd_device, m24_kbd); if (fdc_type == FDC_INTERNAL) - device_add(&fdc_xt_device); + device_add(&fdc_at_device); /* io.c logs clearly show it using port 3F7 */ if (joystick_type) - device_add(&gameport_device); + device_add(&gameport_device); nmi_init(); + /* Allocate an NVR for this machine. */ + nvr = (nvr_t *) malloc(sizeof(nvr_t)); + if (nvr == NULL) + return 0; + memset(nvr, 0x00, sizeof(nvr_t)); + + mm58274_init(nvr, model->nvrmask + 1); + + if (hdc_current == HDC_INTERNAL) + device_add(&st506_xt_wd1002a_wx1_nobios_device); + return ret; } - /* - * Current bugs: + * Current bugs: * - 640x400x2 graphics mode not supported (bit 0 of register 0x3de cannot be set) * - optional mouse emulation missing * - setting CPU speed at 4.77MHz sometimes throws a timer error. If the machine is hard-resetted, the error disappears. @@ -846,10 +1915,11 @@ machine_xt_m19_init(const machine_t *model) int ret; ret = bios_load_linear("roms/machines/m19/BIOS.BIN", - 0x000fc000, 16384, 0); + 0x000fc000, 16384, 0); + ret &= rom_present("roms/machines/m19/MBM2764-30 8514 107 AB PCF3.BIN"); if (bios_only || !ret) - return ret; + return ret; m19_vid_t *vid; @@ -859,21 +1929,21 @@ machine_xt_m19_init(const machine_t *model) machine_common_init(model); - pit_ctr_set_out_func(&pit->counters[1], pit_refresh_timer_xt); + pit_devs[0].set_out_func(pit_devs[0].data, 1, pit_refresh_timer_xt); /* On-board FDC cannot be disabled */ device_add(&fdc_xt_device); nmi_init(); - video_reset(gfxcard); + video_reset(gfxcard[0]); m19_vid_init(vid); device_add_ex(&m19_vid_device, vid); device_add(&keyboard_xt_olivetti_device); - pit_set_clock(14318184.0); + pit_set_clock((uint32_t) 14318184.0); return ret; } diff --git a/src/machine/m_xt_philips.c b/src/machine/m_xt_philips.c index 753d1300b..1fc284a46 100644 --- a/src/machine/m_xt_philips.c +++ b/src/machine/m_xt_philips.c @@ -1,20 +1,19 @@ /* - * 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. + * 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. + * This file is part of the 86Box distribution. * - * Emulation of the Philips XT-compatible machines. + * Emulation of the Philips XT-compatible machines. * * * - * Authors: EngiNerd + * Authors: EngiNerd * - * Copyright 2020-2021 EngiNerd. + * Copyright 2020-2021 EngiNerd. */ - #include #include #include @@ -40,14 +39,12 @@ #include <86box/chipset.h> #include <86box/io.h> #include <86box/video.h> +#include <86box/plat_unused.h> - -typedef struct -{ - uint8_t reg; +typedef struct philips_t { + uint8_t reg; } philips_t; - #ifdef ENABLE_PHILIPS_LOG int philips_do_log = ENABLE_PHILIPS_LOG; static void @@ -58,11 +55,11 @@ philips_log(const char *fmt, ...) if (philips_do_log) { va_start(ap, fmt); pclog_ex(fmt, ap); - va_end(ap); + va_end(ap); } } #else -#define philips_log(fmt, ...) +# define philips_log(fmt, ...) #endif static void @@ -71,39 +68,44 @@ philips_write(uint16_t port, uint8_t val, void *priv) philips_t *dev = (philips_t *) priv; switch (port) { - /* port 0xc0 - * bit 7: turbo - * bits 4-5: rtc read/set (I2C Bus SDA/SCL?) - * bit 2: parity disabled - */ - case 0xc0: - dev->reg = val; - if (val & 0x80) - cpu_dynamic_switch(cpu); - else - cpu_dynamic_switch(0); - break; + /* port 0xc0 + * bit 7: turbo + * bits 4-5: rtc read/set (I2C Bus SDA/SCL?) + * bit 2: parity disabled + */ + case 0xc0: + dev->reg = val; + if (val & 0x80) + cpu_dynamic_switch(cpu); + else + cpu_dynamic_switch(0); + break; + + default: + break; } - + philips_log("Philips XT Mainboard: Write %02x at %02x\n", val, port); - } static uint8_t philips_read(uint16_t port, void *priv) { - philips_t *dev = (philips_t *) priv; - uint8_t ret = 0xff; + const philips_t *dev = (philips_t *) priv; + uint8_t ret = 0xff; switch (port) { - /* port 0xc0 - * bit 7: turbo - * bits 4-5: rtc read/set - * bit 2: parity disabled - */ - case 0xc0: - ret = dev->reg; - break; + /* port 0xc0 + * bit 7: turbo + * bits 4-5: rtc read/set + * bit 2: parity disabled + */ + case 0xc0: + ret = dev->reg; + break; + + default: + break; } philips_log("Philips XT Mainboard: Read %02x at %02x\n", ret, port); @@ -111,7 +113,6 @@ philips_read(uint16_t port, void *priv) return ret; } - static void philips_close(void *priv) { @@ -121,7 +122,7 @@ philips_close(void *priv) } static void * -philips_init(const device_t *info) +philips_init(UNUSED(const device_t *info)) { philips_t *dev = (philips_t *) malloc(sizeof(philips_t)); memset(dev, 0, sizeof(philips_t)); @@ -134,22 +135,25 @@ philips_init(const device_t *info) } const device_t philips_device = { - "Philips XT Mainboard", - "philips", - 0, - 0, - philips_init, philips_close, NULL, - { NULL }, NULL, NULL, - NULL + .name = "Philips XT Mainboard", + .internal_name = "philips", + .flags = 0, + .local = 0, + .init = philips_init, + .close = philips_close, + .reset = NULL, + { .available = NULL }, + .speed_changed = NULL, + .force_redraw = NULL, + .config = NULL }; - void machine_xt_philips_common_init(const machine_t *model) { machine_common_init(model); - pit_ctr_set_out_func(&pit->counters[1], pit_refresh_timer_xt); + pit_devs[0].set_out_func(pit_devs[0].data, 1, pit_refresh_timer_xt); nmi_init(); @@ -160,7 +164,6 @@ machine_xt_philips_common_init(const machine_t *model) device_add(&philips_device); device_add(&xta_hd20_device); - } int @@ -169,15 +172,15 @@ machine_xt_p3105_init(const machine_t *model) int ret; ret = bios_load_linear("roms/machines/p3105/philipsnms9100.bin", - 0x000fc000, 16384, 0); - + 0x000fc000, 16384, 0); + if (bios_only || !ret) - return ret; + return ret; machine_xt_philips_common_init(model); /* On-board FDC cannot be disabled */ - device_add(&fdc_xt_device); + device_add(&fdc_xt_device); return ret; } @@ -188,17 +191,16 @@ machine_xt_p3120_init(const machine_t *model) int ret; ret = bios_load_linear("roms/machines/p3120/philips_p3120.bin", - 0x000f8000, 32768, 0); - + 0x000f8000, 32768, 0); + if (bios_only || !ret) - return ret; + return ret; machine_xt_philips_common_init(model); - + device_add(&gc100a_device); device_add(&fdc_at_device); - + return ret; } - diff --git a/src/machine/m_xt_t1000.c b/src/machine/m_xt_t1000.c index ef4a09c42..a12fa4e96 100644 --- a/src/machine/m_xt_t1000.c +++ b/src/machine/m_xt_t1000.c @@ -1,65 +1,65 @@ /* - * VARCem Virtual ARchaeological Computer EMulator. - * An emulator of (mostly) x86-based PC systems and devices, - * using the ISA,EISA,VLB,MCA and PCI system buses, roughly - * spanning the era between 1981 and 1995. + * 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 VARCem Project. + * This file is part of the 86Box distribution. * - * Implementation of the Toshiba T1000 and T1200 portables. + * Implementation of the Toshiba T1000 and T1200 portables. * - * The T1000 is the T3100e's little brother -- a real laptop - * with a rechargeable battery. + * The T1000 is the T3100e's little brother -- a real laptop + * with a rechargeable battery. * - * Features: 80C88 at 4.77MHz - * - 512k system RAM - * - 640x200 monochrome LCD - * - 82-key keyboard - * - Real-time clock. Not the normal 146818, but a TC8521, - * which is a 4-bit chip. - * - A ROM drive (128k, 256k or 512k) which acts as a mini - * hard drive and contains a copy of DOS 2.11. - * - 160 bytes of non-volatile RAM for the CONFIG.SYS used - * when booting from the ROM drive. Possibly physically - * located in the keyboard controller RAM. + * Features: 80C88 at 4.77MHz + * - 512k system RAM + * - 640x200 monochrome LCD + * - 82-key keyboard + * - Real-time clock. Not the normal 146818, but a TC8521, + * which is a 4-bit chip. + * - A ROM drive (128k, 256k or 512k) which acts as a mini + * hard drive and contains a copy of DOS 2.11. + * - 160 bytes of non-volatile RAM for the CONFIG.SYS used + * when booting from the ROM drive. Possibly physically + * located in the keyboard controller RAM. * - * An optional memory expansion board can be fitted. This adds - * 768k of RAM, which can be used for up to three purposes: - * > Conventional memory -- 128k between 512k and 640k - * > HardRAM -- a battery-backed RAM drive. - * > EMS + * An optional memory expansion board can be fitted. This adds + * 768k of RAM, which can be used for up to three purposes: + * > Conventional memory -- 128k between 512k and 640k + * > HardRAM -- a battery-backed RAM drive. + * > EMS * - * This means that there are up to three different - * implementations of non-volatile RAM in the same computer - * (52 nibbles in the TC8521, 160 bytes of CONFIG.SYS, and - * up to 768k of HardRAM). + * This means that there are up to three different + * implementations of non-volatile RAM in the same computer + * (52 nibbles in the TC8521, 160 bytes of CONFIG.SYS, and + * up to 768k of HardRAM). * - * The T1200 is a slightly upgraded version with a turbo mode - * (double CPU clock, 9.54MHz) and an optional hard drive. - * The interface for this is proprietary both at the physical - * and programming level. + * The T1200 is a slightly upgraded version with a turbo mode + * (double CPU clock, 9.54MHz) and an optional hard drive. + * The interface for this is proprietary both at the physical + * and programming level. * - * 01F2h: If hard drive is present, low 4 bits are 0Ch [20Mb] - * or 0Dh [10Mb]. + * 01F2h: If hard drive is present, low 4 bits are 0Ch [20Mb] + * or 0Dh [10Mb]. * - * The hard drive is a 20MB (615/2/26) RLL 3.5" drive. + * The hard drive is a 20MB (615/2/26) RLL 3.5" drive. * - * The TC8521 is a 4-bit RTC, so each memory location can only - * hold a single BCD digit. Hence everything has 'ones' and - * 'tens' digits. + * The TC8521 is a 4-bit RTC, so each memory location can only + * hold a single BCD digit. Hence everything has 'ones' and + * 'tens' digits. * - * NOTE: Still need to figure out a way to load/save ConfigSys and - * HardRAM stuff. Needs to be linked in to the NVR code. + * NOTE: Still need to figure out a way to load/save ConfigSys and + * HardRAM stuff. Needs to be linked in to the NVR code. * * * - * Authors: Fred N. van Kempen, - * Miran Grca, - * Sarah Walker, + * Authors: Fred N. van Kempen, + * Miran Grca, + * John Elliott, * - * Copyright 2018,2019 Fred N. van Kempen. - * Copyright 2018,2019 Miran Grca. - * Copyright 2018,2019 Sarah Walker. + * Copyright 2018-2019 Fred N. van Kempen. + * Copyright 2018-2019 Miran Grca. + * Copyright 2018-2019 John Elliott. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -103,14 +103,13 @@ #include <86box/fdd.h> #include <86box/fdc.h> #include <86box/gameport.h> +#include <86box/hdc.h> #include <86box/video.h> #include <86box/plat.h> #include <86box/machine.h> #include <86box/m_xt_t1000.h> - -#define T1000_ROMSIZE (512*1024UL) /* Maximum ROM drive size is 512k */ - +#define T1000_ROMSIZE (512 * 1024UL) /* Maximum ROM drive size is 512k */ enum TC8521_ADDR { /* Page 0 registers */ @@ -127,133 +126,122 @@ enum TC8521_ADDR { TC8521_MONTH10, TC8521_YEAR1, TC8521_YEAR10, - TC8521_PAGE, /* PAGE register */ - TC8521_TEST, /* TEST register */ - TC8521_RESET, /* RESET register */ + TC8521_PAGE, /* PAGE register */ + TC8521_TEST, /* TEST register */ + TC8521_RESET, /* RESET register */ /* Page 1 registers */ - TC8521_24HR = 0x1A, + TC8521_24HR = 0x1A, TC8521_LEAPYEAR = 0x1B }; - -typedef struct { +typedef struct t1000_t { /* ROM drive */ - uint8_t *romdrive; - uint8_t rom_ctl; - uint32_t rom_offset; + uint8_t *romdrive; + uint8_t rom_ctl; + uint32_t rom_offset; mem_mapping_t rom_mapping; /* CONFIG.SYS drive. */ - uint8_t t1000_nvram[160]; - uint8_t t1200_nvram[2048]; + uint8_t t1000_nvram[160]; + uint8_t t1200_nvram[2048]; /* System control registers */ - uint8_t sys_ctl[16]; - uint8_t syskeys; - uint8_t turbo; + uint8_t sys_ctl[16]; + uint8_t syskeys; + uint8_t turbo; /* NVRAM control */ - uint8_t nvr_c0; - uint8_t nvr_tick; - int nvr_addr; - uint8_t nvr_active; - mem_mapping_t nvr_mapping; /* T1200 NVRAM mapping */ + uint8_t nvr_c0; + uint8_t nvr_tick; + int nvr_addr; + uint8_t nvr_active; + mem_mapping_t nvr_mapping; /* T1200 NVRAM mapping */ /* EMS data */ - uint8_t ems_reg[4]; + uint8_t ems_reg[4]; mem_mapping_t mapping[4]; - uint32_t page_exec[4]; - uint8_t ems_port_index; - uint16_t ems_port; - uint8_t is_640k; - uint32_t ems_base; - int32_t ems_pages; + uint32_t page_exec[4]; + uint8_t ems_port_index; + uint16_t ems_port; + uint8_t is_640k; + uint32_t ems_base; + int32_t ems_pages; - fdc_t *fdc; + fdc_t *fdc; - nvr_t nvr; - int is_t1200; + nvr_t nvr; + int is_t1200; } t1000_t; - -static t1000_t t1000; - +static t1000_t t1000; #ifdef ENABLE_T1000_LOG int t1000_do_log = ENABLE_T1000_LOG; - static void t1000_log(const char *fmt, ...) { - va_list ap; + va_list ap; - if (t1000_do_log) - { - va_start(ap, fmt); - pclog_ex(fmt, ap); - va_end(ap); - } + if (t1000_do_log) { + va_start(ap, fmt); + pclog_ex(fmt, ap); + va_end(ap); + } } #else -#define t1000_log(fmt, ...) +# define t1000_log(fmt, ...) #endif - /* Set the chip time. */ static void tc8521_time_set(uint8_t *regs, struct tm *tm) { - regs[TC8521_SECOND1] = (tm->tm_sec % 10); + regs[TC8521_SECOND1] = (tm->tm_sec % 10); regs[TC8521_SECOND10] = (tm->tm_sec / 10); - regs[TC8521_MINUTE1] = (tm->tm_min % 10); + regs[TC8521_MINUTE1] = (tm->tm_min % 10); regs[TC8521_MINUTE10] = (tm->tm_min / 10); if (regs[TC8521_24HR] & 0x01) { - regs[TC8521_HOUR1] = (tm->tm_hour % 10); - regs[TC8521_HOUR10] = (tm->tm_hour / 10); + regs[TC8521_HOUR1] = (tm->tm_hour % 10); + regs[TC8521_HOUR10] = (tm->tm_hour / 10); } else { - regs[TC8521_HOUR1] = ((tm->tm_hour % 12) % 10); - regs[TC8521_HOUR10] = (((tm->tm_hour % 12) / 10) | - ((tm->tm_hour >= 12) ? 2 : 0)); + regs[TC8521_HOUR1] = ((tm->tm_hour % 12) % 10); + regs[TC8521_HOUR10] = (((tm->tm_hour % 12) / 10) | ((tm->tm_hour >= 12) ? 2 : 0)); } regs[TC8521_WEEKDAY] = tm->tm_wday; - regs[TC8521_DAY1] = (tm->tm_mday % 10); - regs[TC8521_DAY10] = (tm->tm_mday / 10); - regs[TC8521_MONTH1] = ((tm->tm_mon + 1) % 10); + regs[TC8521_DAY1] = (tm->tm_mday % 10); + regs[TC8521_DAY10] = (tm->tm_mday / 10); + regs[TC8521_MONTH1] = ((tm->tm_mon + 1) % 10); regs[TC8521_MONTH10] = ((tm->tm_mon + 1) / 10); - regs[TC8521_YEAR1] = ((tm->tm_year - 80) % 10); - regs[TC8521_YEAR10] = (((tm->tm_year - 80) % 100) / 10); + regs[TC8521_YEAR1] = ((tm->tm_year - 80) % 10); + regs[TC8521_YEAR10] = (((tm->tm_year - 80) % 100) / 10); } - /* Get the chip time. */ -#define nibbles(a) (regs[(a##1)] + 10 * regs[(a##10)]) +#define nibbles(a) (regs[(a##1)] + 10 * regs[(a##10)]) static void tc8521_time_get(uint8_t *regs, struct tm *tm) { tm->tm_sec = nibbles(TC8521_SECOND); tm->tm_min = nibbles(TC8521_MINUTE); if (regs[TC8521_24HR] & 0x01) - tm->tm_hour = nibbles(TC8521_HOUR); - else - tm->tm_hour = ((nibbles(TC8521_HOUR) % 12) + - (regs[TC8521_HOUR10] & 0x02) ? 12 : 0); + tm->tm_hour = nibbles(TC8521_HOUR); + else + tm->tm_hour = ((nibbles(TC8521_HOUR) % 12) + (regs[TC8521_HOUR10] & 0x02) ? 12 : 0); tm->tm_wday = regs[TC8521_WEEKDAY]; tm->tm_mday = nibbles(TC8521_DAY); - tm->tm_mon = (nibbles(TC8521_MONTH) - 1); + tm->tm_mon = (nibbles(TC8521_MONTH) - 1); tm->tm_year = (nibbles(TC8521_YEAR) + 1980); } - /* This is called every second through the NVR/RTC hook. */ static void -tc8521_tick(nvr_t *nvr) +tc8521_tick(UNUSED(nvr_t *nvr)) { t1000_log("TC8521: ping\n"); } - static void tc8521_start(nvr_t *nvr) { @@ -261,13 +249,13 @@ tc8521_start(nvr_t *nvr) /* Initialize the internal and chip times. */ if (time_sync & TIME_SYNC_ENABLED) { - /* Use the internal clock's time. */ - nvr_time_get(&tm); - tc8521_time_set(nvr->regs, &tm); + /* Use the internal clock's time. */ + nvr_time_get(&tm); + tc8521_time_set(nvr->regs, &tm); } else { - /* Set the internal clock from the chip time. */ - tc8521_time_get(nvr->regs, &tm); - nvr_time_set(&tm); + /* Set the internal clock from the chip time. */ + tc8521_time_get(nvr->regs, &tm); + nvr_time_set(&tm); } #if 0 @@ -276,46 +264,43 @@ tc8521_start(nvr_t *nvr) #endif } - /* Write to one of the chip registers. */ static void tc8521_write(uint16_t addr, uint8_t val, void *priv) { - nvr_t *nvr = (nvr_t *)priv; + nvr_t *nvr = (nvr_t *) priv; uint8_t page; /* Get to the correct register page. */ addr &= 0x0f; page = nvr->regs[0x0d] & 0x03; if (addr < 0x0d) - addr += (16 * page); + addr += (16 * page); if (addr >= 0x10 && nvr->regs[addr] != val) - nvr_dosave = 1; + nvr_dosave = 1; /* Store the new value. */ nvr->regs[addr] = val; } - /* Read from one of the chip registers. */ static uint8_t tc8521_read(uint16_t addr, void *priv) { - nvr_t *nvr = (nvr_t *)priv; - uint8_t page; + const nvr_t *nvr = (nvr_t *) priv; + uint8_t page; /* Get to the correct register page. */ addr &= 0x0f; page = nvr->regs[0x0d] & 0x03; if (addr < 0x0d) - addr += (16 * page); + addr += (16 * page); /* Grab and return the desired value. */ - return(nvr->regs[addr]); + return (nvr->regs[addr]); } - /* Reset the 8521 to a default state. */ static void tc8521_reset(nvr_t *nvr) @@ -326,124 +311,117 @@ tc8521_reset(nvr_t *nvr) /* Reset the RTC registers. */ memset(nvr->regs, 0x00, 16); nvr->regs[TC8521_WEEKDAY] = 0x01; - nvr->regs[TC8521_DAY1] = 0x01; - nvr->regs[TC8521_MONTH1] = 0x01; + nvr->regs[TC8521_DAY1] = 0x01; + nvr->regs[TC8521_MONTH1] = 0x01; } - static void tc8521_init(nvr_t *nvr, int size) { /* This is machine specific. */ nvr->size = size; - nvr->irq = -1; + nvr->irq = -1; /* Set up any local handlers here. */ nvr->reset = tc8521_reset; nvr->start = tc8521_start; - nvr->tick = tc8521_tick; + nvr->tick = tc8521_tick; /* Initialize the actual NVR. */ nvr_init(nvr); io_sethandler(0x02c0, 16, - tc8521_read,NULL,NULL, tc8521_write,NULL,NULL, nvr); - + tc8521_read, NULL, NULL, tc8521_write, NULL, NULL, nvr); } - /* Given an EMS page ID, return its physical address in RAM. */ static uint32_t -ems_execaddr(t1000_t *sys, int pg, uint16_t val) +ems_execaddr(t1000_t *sys, UNUSED(int pg), uint16_t val) { - if (!(val & 0x80)) return(0); /* Bit 7 reset => not mapped */ - if (!sys->ems_pages) return(0); /* No EMS available: all used by - * HardRAM or conventional RAM */ + if (!(val & 0x80)) + return 0; /* Bit 7 reset => not mapped */ + if (!sys->ems_pages) + return 0; /* No EMS available: all used by + * HardRAM or conventional RAM */ val &= 0x7f; #if 0 t1000_log("Select EMS page: %d of %d\n", val, sys->ems_pages); #endif if (val < sys->ems_pages) { - /* EMS is any memory above 512k, - with ems_base giving the start address */ - return((512 * 1024) + (sys->ems_base * 0x10000) + (0x4000 * val)); + /* EMS is any memory above 512k, + with ems_base giving the start address */ + return ((512 * 1024) + (sys->ems_base * 0x10000) + (0x4000 * val)); } - return(0); + return 0; } - static uint8_t ems_in(uint16_t addr, void *priv) { - t1000_t *sys = (t1000_t *)priv; + const t1000_t *sys = (t1000_t *) priv; #if 0 t1000_log("ems_in(%04x)=%02x\n", addr, sys->ems_reg[(addr >> 14) & 3]); #endif - return(sys->ems_reg[(addr >> 14) & 3]); + return (sys->ems_reg[(addr >> 14) & 3]); } - static void ems_out(uint16_t addr, uint8_t val, void *priv) { - t1000_t *sys = (t1000_t *)priv; - int pg = (addr >> 14) & 3; + t1000_t *sys = (t1000_t *) priv; + int pg = (addr >> 14) & 3; #if 0 t1000_log("ems_out(%04x, %02x) pg=%d\n", addr, val, pg); #endif - sys->ems_reg[pg] = val; + sys->ems_reg[pg] = val; sys->page_exec[pg] = ems_execaddr(sys, pg, val); if (sys->page_exec[pg]) { - /* Page present */ - mem_mapping_enable(&sys->mapping[pg]); - mem_mapping_set_exec(&sys->mapping[pg], ram + sys->page_exec[pg]); + /* Page present */ + mem_mapping_enable(&sys->mapping[pg]); + mem_mapping_set_exec(&sys->mapping[pg], ram + sys->page_exec[pg]); } else { - mem_mapping_disable(&sys->mapping[pg]); + mem_mapping_disable(&sys->mapping[pg]); } } - /* Hardram size is in 64k units */ static void ems_set_hardram(t1000_t *sys, uint8_t val) { - int n; - - val &= 0x1f; /* Mask off pageframe address */ + val &= 0x1f; /* Mask off pageframe address */ if (val && mem_size > 512) - sys->ems_base = val; - else - sys->ems_base = 0; + sys->ems_base = val; + else + sys->ems_base = 0; #if 0 t1000_log("EMS base set to %02x\n", val); #endif sys->ems_pages = ((mem_size - 512) / 16) - 4 * sys->ems_base; - if (sys->ems_pages < 0) sys->ems_pages = 0; + if (sys->ems_pages < 0) + sys->ems_pages = 0; /* Recalculate EMS mappings */ - for (n = 0; n < 4; n++) - ems_out(n << 14, sys->ems_reg[n], sys); + for (uint8_t n = 0; n < 4; n++) + ems_out(n << 14, sys->ems_reg[n], sys); } - static void ems_set_640k(t1000_t *sys, uint8_t val) { if (val && mem_size >= 640) { - mem_mapping_set_addr(&ram_low_mapping, 0, 640 * 1024); - sys->is_640k = 1; + mem_mapping_set_addr(&ram_low_mapping, 0, 640 * 1024); + sys->is_640k = 1; } else { - mem_mapping_set_addr(&ram_low_mapping, 0, 512 * 1024); - sys->is_640k = 0; + mem_mapping_set_addr(&ram_low_mapping, 0, 512 * 1024); + sys->is_640k = 0; } } - static void ems_set_port(t1000_t *sys, uint8_t val) { @@ -453,25 +431,25 @@ ems_set_port(t1000_t *sys, uint8_t val) t1000_log("ems_set_port(%d)", val & 0x0f); #endif if (sys->ems_port) { - for (n = 0; n <= 0xc000; n += 0x4000) { - io_removehandler(sys->ems_port+n, 1, - ems_in,NULL,NULL, ems_out,NULL,NULL, sys); - } - sys->ems_port = 0; + for (n = 0; n <= 0xc000; n += 0x4000) { + io_removehandler(sys->ems_port + n, 1, + ems_in, NULL, NULL, ems_out, NULL, NULL, sys); + } + sys->ems_port = 0; } val &= 0x0f; sys->ems_port_index = val; if (val == 7) { - /* No EMS */ - sys->ems_port = 0; + /* No EMS */ + sys->ems_port = 0; } else { - sys->ems_port = 0x208 | (val << 4); - for (n = 0; n <= 0xc000; n += 0x4000) { - io_sethandler(sys->ems_port+n, 1, - ems_in,NULL,NULL, ems_out,NULL,NULL, sys); - } - sys->ems_port = 0; + sys->ems_port = 0x208 | (val << 4); + for (n = 0; n <= 0xc000; n += 0x4000) { + io_sethandler(sys->ems_port + n, 1, + ems_in, NULL, NULL, ems_out, NULL, NULL, sys); + } + sys->ems_port = 0; } #if 0 @@ -479,35 +457,34 @@ ems_set_port(t1000_t *sys, uint8_t val) #endif } - static int addr_to_page(uint32_t addr) { - return((addr - 0xd0000) / 0x4000); + return ((addr - 0xd0000) / 0x4000); } - /* Read RAM in the EMS page frame. */ static uint8_t ems_read_ram(uint32_t addr, void *priv) { - t1000_t *sys = (t1000_t *)priv; - int pg = addr_to_page(addr); + const t1000_t *sys = (t1000_t *) priv; + int pg = addr_to_page(addr); - if (pg < 0) return(0xff); + if (pg < 0) + return 0xff; addr = sys->page_exec[pg] + (addr & 0x3fff); - return(ram[addr]); + return (ram[addr]); } - static uint16_t ems_read_ramw(uint32_t addr, void *priv) { - t1000_t *sys = (t1000_t *)priv; - int pg = addr_to_page(addr); + const t1000_t *sys = (t1000_t *) priv; + int pg = addr_to_page(addr); - if (pg < 0) return(0xff); + if (pg < 0) + return 0xff; #if 0 t1000_log("ems_read_ramw addr=%05x ", addr); @@ -518,46 +495,47 @@ ems_read_ramw(uint32_t addr, void *priv) t1000_log("-> %06x val=%04x\n", addr, *(uint16_t *)&ram[addr]); #endif - return(*(uint16_t *)&ram[addr]); + return (*(uint16_t *) &ram[addr]); } - static uint32_t ems_read_raml(uint32_t addr, void *priv) { - t1000_t *sys = (t1000_t *)priv; - int pg = addr_to_page(addr); + const t1000_t *sys = (t1000_t *) priv; + int pg = addr_to_page(addr); - if (pg < 0) return(0xff); + if (pg < 0) + return 0xff; addr = sys->page_exec[pg] + (addr & 0x3fff); - return(*(uint32_t *)&ram[addr]); + return (*(uint32_t *) &ram[addr]); } - /* Write RAM in the EMS page frame. */ static void ems_write_ram(uint32_t addr, uint8_t val, void *priv) { - t1000_t *sys = (t1000_t *)priv; - int pg = addr_to_page(addr); + const t1000_t *sys = (t1000_t *) priv; + int pg = addr_to_page(addr); - if (pg < 0) return; + if (pg < 0) + return; addr = sys->page_exec[pg] + (addr & 0x3fff); - if (ram[addr] != val) nvr_dosave = 1; + if (ram[addr] != val) + nvr_dosave = 1; ram[addr] = val; } - static void ems_write_ramw(uint32_t addr, uint16_t val, void *priv) { - t1000_t *sys = (t1000_t *)priv; - int pg = addr_to_page(addr); + const t1000_t *sys = (t1000_t *) priv; + int pg = addr_to_page(addr); - if (pg < 0) return; + if (pg < 0) + return; #if 0 t1000_log("ems_write_ramw addr=%05x ", addr); @@ -568,122 +546,130 @@ ems_write_ramw(uint32_t addr, uint16_t val, void *priv) t1000_log("-> %06x val=%04x\n", addr, val); #endif - if (*(uint16_t *)&ram[addr] != val) nvr_dosave = 1; + if (*(uint16_t *) &ram[addr] != val) + nvr_dosave = 1; - *(uint16_t *)&ram[addr] = val; + *(uint16_t *) &ram[addr] = val; } - static void ems_write_raml(uint32_t addr, uint32_t val, void *priv) { - t1000_t *sys = (t1000_t *)priv; - int pg = addr_to_page(addr); + const t1000_t *sys = (t1000_t *) priv; + int pg = addr_to_page(addr); - if (pg < 0) return; + if (pg < 0) + return; addr = sys->page_exec[pg] + (addr & 0x3fff); - if (*(uint32_t *)&ram[addr] != val) nvr_dosave = 1; + if (*(uint32_t *) &ram[addr] != val) + nvr_dosave = 1; - *(uint32_t *)&ram[addr] = val; + *(uint32_t *) &ram[addr] = val; } - static uint8_t read_ctl(uint16_t addr, void *priv) { - t1000_t *sys = (t1000_t *)priv; - uint8_t ret = 0xff; + const t1000_t *sys = (t1000_t *) priv; + uint8_t ret = 0xff; switch (addr & 0x0f) { - case 1: - ret = sys->syskeys; - break; + case 1: + ret = sys->syskeys; + break; - case 0x0f: /* Detect EMS board */ - switch (sys->sys_ctl[0x0e]) { - case 0x50: - if (mem_size > 512) - ret = (0x90 | sys->ems_port_index); - break; + case 0x0f: /* Detect EMS board */ + switch (sys->sys_ctl[0x0e]) { + case 0x50: + if (mem_size > 512) + ret = (0x90 | sys->ems_port_index); + break; - case 0x51: - /* 0x60 is the page frame address: - (0xd000 - 0xc400) / 0x20 */ - ret = (sys->ems_base | 0x60); - break; + case 0x51: + /* 0x60 is the page frame address: + (0xd000 - 0xc400) / 0x20 */ + ret = (sys->ems_base | 0x60); + break; - case 0x52: - ret = (sys->is_640k ? 0x80 : 0); - break; - } - break; + case 0x52: + ret = (sys->is_640k ? 0x80 : 0); + break; - default: - ret = (sys->sys_ctl[addr & 0x0f]); + default: + break; + } + break; + + default: + ret = (sys->sys_ctl[addr & 0x0f]); } - return(ret); + return ret; } - static void t1200_turbo_set(uint8_t value) { - if (value == t1000.turbo) return; + if (value == t1000.turbo) + return; t1000.turbo = value; - if (! value) - cpu_dynamic_switch(0); - else - cpu_dynamic_switch(cpu); + if (!value) + cpu_dynamic_switch(0); + else + cpu_dynamic_switch(cpu); } - static void write_ctl(uint16_t addr, uint8_t val, void *priv) { - t1000_t *sys = (t1000_t *)priv; + t1000_t *sys = (t1000_t *) priv; sys->sys_ctl[addr & 0x0f] = val; switch (addr & 0x0f) { - case 4: /* Video control */ - if (sys->sys_ctl[3] == 0x5A) { - t1000_video_options_set((val & 0x20) ? 1 : 0); - t1000_display_set((val & 0x40) ? 0 : 1); - if (sys->is_t1200) - t1200_turbo_set((val & 0x80) ? 1 : 0); - } - break; + case 4: /* Video control */ + if (sys->sys_ctl[3] == 0x5A) { + t1000_video_options_set((val & 0x20) ? 1 : 0); + t1000_display_set((val & 0x40) ? 0 : 1); + if (sys->is_t1200) + t1200_turbo_set((val & 0x80) ? 1 : 0); + } + break; - /* It looks as if the T1200, like the T3100, can disable - * its builtin video chipset if it detects the presence of - * another video card. */ - case 6: if (sys->is_t1200) - { - t1000_video_enable(val & 0x01 ? 0 : 1); - } - break; - - case 0x0f: /* EMS control */ - switch (sys->sys_ctl[0x0e]) { - case 0x50: - ems_set_port(sys, val); - break; + /* It looks as if the T1200, like the T3100, can disable + * its builtin video chipset if it detects the presence of + * another video card. */ + case 6: + if (sys->is_t1200) { + t1000_video_enable(val & 0x01 ? 0 : 1); + } + break; - case 0x51: - ems_set_hardram(sys, val); - break; + case 0x0f: /* EMS control */ + switch (sys->sys_ctl[0x0e]) { + case 0x50: + ems_set_port(sys, val); + break; - case 0x52: - ems_set_640k(sys, val); - break; - } - break; + case 0x51: + ems_set_hardram(sys, val); + break; + + case 0x52: + ems_set_640k(sys, val); + break; + + default: + break; + } + break; + + default: + break; } } - /* Ports 0xC0 to 0xC3 appear to have two purposes: * * > Access to the 160 bytes of non-volatile RAM containing CONFIG.SYS @@ -694,179 +680,172 @@ write_ctl(uint16_t addr, uint8_t val, void *priv) static uint8_t t1000_read_nvram(uint16_t addr, void *priv) { - t1000_t *sys = (t1000_t *)priv; - uint8_t tmp = 0xff; + t1000_t *sys = (t1000_t *) priv; + uint8_t tmp = 0xff; switch (addr) { - case 0xc2: /* Read next byte from NVRAM */ - if (sys->nvr_addr >= 0 && sys->nvr_addr < 160) - tmp = sys->t1000_nvram[sys->nvr_addr]; - sys->nvr_addr++; - break; + case 0xc2: /* Read next byte from NVRAM */ + if (sys->nvr_addr >= 0 && sys->nvr_addr < 160) + tmp = sys->t1000_nvram[sys->nvr_addr]; + sys->nvr_addr++; + break; - case 0xc3: /* Read floppy changeline and NVRAM ready state */ - tmp = fdc_read(0x03f7, t1000.fdc); + case 0xc3: /* Read floppy changeline and NVRAM ready state */ + tmp = fdc_read(0x03f7, t1000.fdc); - tmp = (tmp & 0x80) >> 3; /* Bit 4 is changeline */ - tmp |= (sys->nvr_active & 0xc0);/* Bits 6,7 are r/w mode */ - tmp |= 0x2e; /* Bits 5,3,2,1 always 1 */ - tmp |= (sys->nvr_active & 0x40) >> 6; /* Ready state */ - break; + tmp = (tmp & 0x80) >> 3; /* Bit 4 is changeline */ + tmp |= (sys->nvr_active & 0xc0); /* Bits 6, 7 are r/w mode */ + tmp |= 0x2e; /* Bits 5, 3, 2, 1 always 1 */ + tmp |= (sys->nvr_active & 0x40) >> 6; /* Ready state */ + break; + + default: + break; } - return(tmp); + return tmp; } - static void t1000_write_nvram(uint16_t addr, uint8_t val, void *priv) { - t1000_t *sys = (t1000_t *)priv; + t1000_t *sys = (t1000_t *) priv; /* * On the real T1000, port 0xC1 is only usable as the high byte * of a 16-bit write to port 0xC0, with 0x5A in the low byte. */ switch (addr) { - case 0xc0: - sys->nvr_c0 = val; - break; + case 0xc0: + sys->nvr_c0 = val; + break; - case 0xc1: /* Write next byte to NVRAM */ - if (sys->nvr_addr >= 0 && sys->nvr_addr < 160) { - if (sys->t1000_nvram[sys->nvr_addr] != val) - nvr_dosave = 1; - sys->t1000_nvram[sys->nvr_addr] = val; - } - sys->nvr_addr++; - break; + case 0xc1: /* Write next byte to NVRAM */ + if (sys->nvr_addr >= 0 && sys->nvr_addr < 160) { + if (sys->t1000_nvram[sys->nvr_addr] != val) + nvr_dosave = 1; + sys->t1000_nvram[sys->nvr_addr] = val; + } + sys->nvr_addr++; + break; - case 0xc2: - break; + case 0xc2: + break; - case 0xc3: - /* - * At start of NVRAM read / write, 0x80 is written to - * port 0xC3. This seems to reset the NVRAM address - * counter. A single byte is then written (0xff for - * write, 0x00 for read) which appears to be ignored. - * Simulate that by starting the address counter off - * at -1. - */ - sys->nvr_active = val; - if (val == 0x80) sys->nvr_addr = -1; - break; + case 0xc3: + /* + * At start of NVRAM read / write, 0x80 is written to + * port 0xC3. This seems to reset the NVRAM address + * counter. A single byte is then written (0xff for + * write, 0x00 for read) which appears to be ignored. + * Simulate that by starting the address counter off + * at -1. + */ + sys->nvr_active = val; + if (val == 0x80) + sys->nvr_addr = -1; + break; + + default: + break; } } - -static -uint8_t read_t1200_nvram(uint32_t addr, void *priv) +static uint8_t +read_t1200_nvram(uint32_t addr, void *priv) { - t1000_t *sys = (t1000_t *)priv; + const t1000_t *sys = (t1000_t *) priv; return sys->t1200_nvram[addr & 0x7FF]; } - -static void write_t1200_nvram(uint32_t addr, uint8_t value, void *priv) +static void +write_t1200_nvram(uint32_t addr, uint8_t value, void *priv) { - t1000_t *sys = (t1000_t *)priv; + t1000_t *sys = (t1000_t *) priv; - if (sys->t1200_nvram[addr & 0x7FF] != value) - nvr_dosave = 1; + if (sys->t1200_nvram[addr & 0x7FF] != value) + nvr_dosave = 1; sys->t1200_nvram[addr & 0x7FF] = value; } - /* Port 0xC8 controls the ROM drive */ static uint8_t -t1000_read_rom_ctl(uint16_t addr, void *priv) +t1000_read_rom_ctl(UNUSED(uint16_t addr), void *priv) { - t1000_t *sys = (t1000_t *)priv; + const t1000_t *sys = (t1000_t *) priv; - return(sys->rom_ctl); + return (sys->rom_ctl); } - static void -t1000_write_rom_ctl(uint16_t addr, uint8_t val, void *priv) +t1000_write_rom_ctl(UNUSED(uint16_t addr), uint8_t val, void *priv) { - t1000_t *sys = (t1000_t *)priv; + t1000_t *sys = (t1000_t *) priv; sys->rom_ctl = val; if (sys->romdrive && (val & 0x80)) { - /* Enable */ - sys->rom_offset = ((val & 0x7f) * 0x10000) % T1000_ROMSIZE; - mem_mapping_set_addr(&sys->rom_mapping, 0xa0000, 0x10000); - mem_mapping_set_exec(&sys->rom_mapping, sys->romdrive + sys->rom_offset); - mem_mapping_enable(&sys->rom_mapping); + /* Enable */ + sys->rom_offset = ((val & 0x7f) * 0x10000) % T1000_ROMSIZE; + mem_mapping_set_addr(&sys->rom_mapping, 0xa0000, 0x10000); + mem_mapping_set_exec(&sys->rom_mapping, sys->romdrive + sys->rom_offset); + mem_mapping_enable(&sys->rom_mapping); } else { - mem_mapping_disable(&sys->rom_mapping); + mem_mapping_disable(&sys->rom_mapping); } } - /* Read the ROM drive */ static uint8_t t1000_read_rom(uint32_t addr, void *priv) { - t1000_t *sys = (t1000_t *)priv; + const t1000_t *sys = (t1000_t *) priv; - if (! sys->romdrive) return(0xff); + if (!sys->romdrive) + return 0xff; - return(sys->romdrive[sys->rom_offset + (addr & 0xffff)]); + return (sys->romdrive[sys->rom_offset + (addr & 0xffff)]); } - static uint16_t t1000_read_romw(uint32_t addr, void *priv) { - t1000_t *sys = (t1000_t *)priv; + t1000_t *sys = (t1000_t *) priv; - if (! sys->romdrive) return(0xffff); + if (!sys->romdrive) + return 0xffff; - return(*(uint16_t *)(&sys->romdrive[sys->rom_offset + (addr & 0xffff)])); + return (*(uint16_t *) (&sys->romdrive[sys->rom_offset + (addr & 0xffff)])); } - static uint32_t t1000_read_roml(uint32_t addr, void *priv) { - t1000_t *sys = (t1000_t *)priv; + t1000_t *sys = (t1000_t *) priv; - if (! sys->romdrive) return(0xffffffff); + if (!sys->romdrive) + return 0xffffffff; - return(*(uint32_t *)(&sys->romdrive[sys->rom_offset + (addr & 0xffff)])); + return (*(uint32_t *) (&sys->romdrive[sys->rom_offset + (addr & 0xffff)])); } - -const device_t * -t1000_get_device(void) -{ - return(&t1000_video_device); -} - - int machine_xt_t1000_init(const machine_t *model) { - FILE *f; - int pg; - + FILE *fp; int ret; ret = bios_load_linear("roms/machines/t1000/t1000.rom", - 0x000f8000, 32768, 0); + 0x000f8000, 32768, 0); if (bios_only || !ret) - return ret; + return ret; memset(&t1000, 0x00, sizeof(t1000)); - t1000.is_t1200 = 0; - t1000.turbo = 0xff; - t1000.ems_port_index = 7; /* EMS disabled */ + t1000.is_t1200 = 0; + t1000.turbo = 0xff; + t1000.ems_port_index = 7; /* EMS disabled */ /* Load the T1000 CGA Font ROM. */ loadfont("roms/machines/t1000/t1000font.bin", 2); @@ -877,50 +856,50 @@ machine_xt_t1000_init(const machine_t *model) * If the file is missing, continue to boot; the BIOS will * complain 'No ROM drive' but boot normally from floppy. */ - f = rom_fopen("roms/machines/t1000/t1000dos.rom", "rb"); - if (f != NULL) { - t1000.romdrive = malloc(T1000_ROMSIZE); - if (t1000.romdrive) { - memset(t1000.romdrive, 0xff, T1000_ROMSIZE); - if (fread(t1000.romdrive, 1, T1000_ROMSIZE, f) != T1000_ROMSIZE) - fatal("machine_xt_t1000_init(): Error reading DOS ROM data\n"); - } - fclose(f); + fp = rom_fopen("roms/machines/t1000/t1000dos.rom", "rb"); + if (fp != NULL) { + t1000.romdrive = malloc(T1000_ROMSIZE); + if (t1000.romdrive) { + memset(t1000.romdrive, 0xff, T1000_ROMSIZE); + if (fread(t1000.romdrive, 1, T1000_ROMSIZE, fp) != T1000_ROMSIZE) + fatal("machine_xt_t1000_init(): Error reading DOS ROM data\n"); + } + fclose(fp); } mem_mapping_add(&t1000.rom_mapping, 0xa0000, 0x10000, - t1000_read_rom,t1000_read_romw,t1000_read_roml, - NULL,NULL,NULL, NULL, MEM_MAPPING_EXTERNAL, &t1000); + t1000_read_rom, t1000_read_romw, t1000_read_roml, + NULL, NULL, NULL, NULL, MEM_MAPPING_EXTERNAL, &t1000); mem_mapping_disable(&t1000.rom_mapping); /* Map the EMS page frame */ - for (pg = 0; pg < 4; pg++) { - mem_mapping_add(&t1000.mapping[pg], 0xd0000 + (0x4000 * pg), 16384, - ems_read_ram,ems_read_ramw,ems_read_raml, - ems_write_ram,ems_write_ramw,ems_write_raml, - NULL, MEM_MAPPING_EXTERNAL, &t1000); + for (uint8_t pg = 0; pg < 4; pg++) { + mem_mapping_add(&t1000.mapping[pg], 0xd0000 + (0x4000 * pg), 16384, + ems_read_ram, ems_read_ramw, ems_read_raml, + ems_write_ram, ems_write_ramw, ems_write_raml, + NULL, MEM_MAPPING_EXTERNAL, &t1000); - /* Start them all off disabled */ - mem_mapping_disable(&t1000.mapping[pg]); + /* Start them all off disabled */ + mem_mapping_disable(&t1000.mapping[pg]); } /* Non-volatile RAM for CONFIG.SYS */ io_sethandler(0xc0, 4, - t1000_read_nvram,NULL,NULL, - t1000_write_nvram,NULL,NULL, &t1000); + t1000_read_nvram, NULL, NULL, + t1000_write_nvram, NULL, NULL, &t1000); /* ROM drive */ io_sethandler(0xc8, 1, - t1000_read_rom_ctl,NULL,NULL, - t1000_write_rom_ctl,NULL,NULL, &t1000); + t1000_read_rom_ctl, NULL, NULL, + t1000_write_rom_ctl, NULL, NULL, &t1000); /* System control functions, and add-on memory board */ io_sethandler(0xe0, 16, - read_ctl,NULL,NULL, write_ctl,NULL,NULL, &t1000); + read_ctl, NULL, NULL, write_ctl, NULL, NULL, &t1000); machine_common_init(model); - pit_ctr_set_out_func(&pit->counters[1], pit_refresh_timer_xt); - device_add(&keyboard_xt_device); + pit_devs[0].set_out_func(pit_devs[0].data, 1, pit_refresh_timer_xt); + device_add(&keyboard_xt_t1x00_device); t1000.fdc = device_add(&fdc_xt_device); nmi_init(); @@ -929,66 +908,56 @@ machine_xt_t1000_init(const machine_t *model) t1000_nvr_load(); nvr_set_ven_save(t1000_nvr_save); - if (gfxcard == VID_INTERNAL) - device_add(&t1000_video_device); + if (gfxcard[0] == VID_INTERNAL) + device_add(&t1000_video_device); return ret; } - -const device_t * -t1200_get_device(void) -{ - return(&t1200_video_device); -} - - int machine_xt_t1200_init(const machine_t *model) { - int pg; - int ret; ret = bios_load_linear("roms/machines/t1200/t1200_019e.ic15.bin", - 0x000f8000, 32768, 0); + 0x000f8000, 32768, 0); if (bios_only || !ret) - return ret; + return ret; memset(&t1000, 0x00, sizeof(t1000)); - t1000.is_t1200 = 1; - t1000.ems_port_index = 7; /* EMS disabled */ + t1000.is_t1200 = 1; + t1000.ems_port_index = 7; /* EMS disabled */ /* Load the T1000 CGA Font ROM. */ loadfont("roms/machines/t1000/t1000font.bin", 2); /* Map the EMS page frame */ - for (pg = 0; pg < 4; pg++) { - mem_mapping_add(&t1000.mapping[pg], - 0xd0000 + (0x4000 * pg), 16384, - ems_read_ram,ems_read_ramw,ems_read_raml, - ems_write_ram,ems_write_ramw,ems_write_raml, - NULL, MEM_MAPPING_EXTERNAL, &t1000); + for (uint8_t pg = 0; pg < 4; pg++) { + mem_mapping_add(&t1000.mapping[pg], + 0xd0000 + (0x4000 * pg), 16384, + ems_read_ram, ems_read_ramw, ems_read_raml, + ems_write_ram, ems_write_ramw, ems_write_raml, + NULL, MEM_MAPPING_EXTERNAL, &t1000); - /* Start them all off disabled */ - mem_mapping_disable(&t1000.mapping[pg]); + /* Start them all off disabled */ + mem_mapping_disable(&t1000.mapping[pg]); } /* System control functions, and add-on memory board */ io_sethandler(0xe0, 16, - read_ctl,NULL,NULL, write_ctl,NULL,NULL, &t1000); + read_ctl, NULL, NULL, write_ctl, NULL, NULL, &t1000); machine_common_init(model); mem_mapping_add(&t1000.nvr_mapping, - 0x000f0000, 2048, - read_t1200_nvram, NULL, NULL, - write_t1200_nvram, NULL, NULL, - NULL, MEM_MAPPING_EXTERNAL, &t1000); + 0x000f0000, 2048, + read_t1200_nvram, NULL, NULL, + write_t1200_nvram, NULL, NULL, + NULL, MEM_MAPPING_EXTERNAL, &t1000); - pit_ctr_set_out_func(&pit->counters[1], pit_refresh_timer_xt); - device_add(&keyboard_xt_device); + pit_devs[0].set_out_func(pit_devs[0].data, 1, pit_refresh_timer_xt); + device_add(&keyboard_xt_t1x00_device); t1000.fdc = device_add(&fdc_xt_t1x00_device); nmi_init(); @@ -997,13 +966,15 @@ machine_xt_t1200_init(const machine_t *model) t1200_nvr_load(); nvr_set_ven_save(t1200_nvr_save); - if (gfxcard == VID_INTERNAL) - device_add(&t1200_video_device); + if (gfxcard[0] == VID_INTERNAL) + device_add(&t1200_video_device); + + if (hdc_current <= 1) + device_add(&st506_xt_toshiba_t1200_device); return ret; } - void t1000_syskey(uint8_t andmask, uint8_t ormask, uint8_t xormask) { @@ -1012,104 +983,97 @@ t1000_syskey(uint8_t andmask, uint8_t ormask, uint8_t xormask) t1000.syskeys ^= xormask; } - static void t1000_configsys_load(void) { - FILE *f; - int size; + FILE *fp; + int size; memset(t1000.t1000_nvram, 0x1a, sizeof(t1000.t1000_nvram)); - f = plat_fopen(nvr_path("t1000_config.nvr"), "rb"); - if (f != NULL) { - size = sizeof(t1000.t1000_nvram); - if (fread(t1000.t1000_nvram, 1, size, f) != size) - fatal("t1000_configsys_load(): Error reading data\n"); - fclose(f); + fp = plat_fopen(nvr_path("t1000_config.nvr"), "rb"); + if (fp != NULL) { + size = sizeof(t1000.t1000_nvram); + if (fread(t1000.t1000_nvram, 1, size, fp) != size) + fatal("t1000_configsys_load(): Error reading data\n"); + fclose(fp); } } - static void t1000_configsys_save(void) { - FILE *f; - int size; + FILE *fp; + int size; - f = plat_fopen(nvr_path("t1000_config.nvr"), "wb"); - if (f != NULL) { - size = sizeof(t1000.t1000_nvram); - if (fwrite(t1000.t1000_nvram, 1, size, f) != size) - fatal("t1000_configsys_save(): Error writing data\n"); - fclose(f); + fp = plat_fopen(nvr_path("t1000_config.nvr"), "wb"); + if (fp != NULL) { + size = sizeof(t1000.t1000_nvram); + if (fwrite(t1000.t1000_nvram, 1, size, fp) != size) + fatal("t1000_configsys_save(): Error writing data\n"); + fclose(fp); } } - static void t1200_state_load(void) { - FILE *f; - int size; + FILE *fp; + int size; memset(t1000.t1200_nvram, 0, sizeof(t1000.t1200_nvram)); - f = plat_fopen(nvr_path("t1200_state.nvr"), "rb"); - if (f != NULL) { - size = sizeof(t1000.t1200_nvram); - if (fread(t1000.t1200_nvram, 1, size, f) != size) - fatal("t1200_state_load(): Error reading data\n"); - fclose(f); + fp = plat_fopen(nvr_path("t1200_state.nvr"), "rb"); + if (fp != NULL) { + size = sizeof(t1000.t1200_nvram); + if (fread(t1000.t1200_nvram, 1, size, fp) != size) + fatal("t1200_state_load(): Error reading data\n"); + fclose(fp); } } - static void t1200_state_save(void) { - FILE *f; - int size; + FILE *fp; + int size; - f = plat_fopen(nvr_path("t1200_state.nvr"), "wb"); - if (f != NULL) { - size = sizeof(t1000.t1200_nvram); - if (fwrite(t1000.t1200_nvram, 1, size, f) != size) - fatal("t1200_state_save(): Error writing data\n"); - fclose(f); + fp = plat_fopen(nvr_path("t1200_state.nvr"), "wb"); + if (fp != NULL) { + size = sizeof(t1000.t1200_nvram); + if (fwrite(t1000.t1200_nvram, 1, size, fp) != size) + fatal("t1200_state_save(): Error writing data\n"); + fclose(fp); } } - /* All RAM beyond 512k is non-volatile */ static void t1000_emsboard_load(void) { - FILE *f; + FILE *fp; if (mem_size > 512) { - f = plat_fopen(nvr_path("t1000_ems.nvr"), "rb"); - if (f != NULL) { - fread(&ram[512 * 1024], 1024, (mem_size - 512), f); - fclose(f); - } + fp = plat_fopen(nvr_path("t1000_ems.nvr"), "rb"); + if (fp != NULL) { + (void) !fread(&ram[512 * 1024], 1024, (mem_size - 512), fp); + fclose(fp); + } } } - static void t1000_emsboard_save(void) { - FILE *f; + FILE *fp; if (mem_size > 512) { - f = plat_fopen(nvr_path("t1000_ems.nvr"), "wb"); - if (f != NULL) { - fwrite(&ram[512 * 1024], 1024, (mem_size - 512), f); - fclose(f); - } + fp = plat_fopen(nvr_path("t1000_ems.nvr"), "wb"); + if (fp != NULL) { + fwrite(&ram[512 * 1024], 1024, (mem_size - 512), fp); + fclose(fp); + } } } - void t1000_nvr_load(void) { @@ -1117,7 +1081,6 @@ t1000_nvr_load(void) t1000_configsys_load(); } - void t1000_nvr_save(void) { @@ -1125,7 +1088,6 @@ t1000_nvr_save(void) t1000_configsys_save(); } - void t1200_nvr_load(void) { @@ -1133,7 +1095,6 @@ t1200_nvr_load(void) t1200_state_load(); } - void t1200_nvr_save(void) { diff --git a/src/machine/m_xt_t1000_vid.c b/src/machine/m_xt_t1000_vid.c index d5cd7b21e..4ec13b5c4 100644 --- a/src/machine/m_xt_t1000_vid.c +++ b/src/machine/m_xt_t1000_vid.c @@ -1,23 +1,23 @@ /* - * VARCem Virtual ARchaeological Computer EMulator. - * An emulator of (mostly) x86-based PC systems and devices, - * using the ISA,EISA,VLB,MCA and PCI system buses, roughly - * spanning the era between 1981 and 1995. + * 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 VARCem Project. + * This file is part of the 86Box distribution. * - * Implementation of the Toshiba T1000 plasma display, which - * has a fixed resolution of 640x200 pixels. + * Implementation of the Toshiba T1000 plasma display, which + * has a fixed resolution of 640x200 pixels. * * * - * Authors: Fred N. van Kempen, - * Miran Grca, - * Sarah Walker, + * Authors: Fred N. van Kempen, + * Miran Grca, + * John Elliott, * - * Copyright 2018,2019 Fred N. van Kempen. - * Copyright 2018,2019 Miran Grca. - * Copyright 2018,2019 Sarah Walker. + * Copyright 2018-2019 Fred N. van Kempen. + * Copyright 2018-2019 Miran Grca. + * Copyright 2018-2019 John Elliott. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -51,21 +51,20 @@ #include <86box/video.h> #include <86box/vid_cga.h> #include <86box/m_xt_t1000.h> - +#include <86box/plat_unused.h> #define T1000_XSIZE 640 #define T1000_YSIZE 200 - /* Mapping of attributes to colours */ -static uint32_t blue, grey; -static uint8_t boldcols[256]; /* Which attributes use the bold font */ +static uint32_t blue; +static uint32_t grey; +static uint8_t boldcols[256]; /* Which attributes use the bold font */ static uint32_t blinkcols[256][2]; static uint32_t normcols[256][2]; static uint8_t language; -static video_timings_t timing_t1000 = {VIDEO_ISA, 8,16,32, 8,16,32}; - +static video_timings_t timing_t1000 = { VIDEO_ISA, 8, 16, 32, 8, 16, 32 }; /* Video options set by the motherboard; they will be picked up by the card * on the next poll. @@ -74,722 +73,690 @@ static video_timings_t timing_t1000 = {VIDEO_ISA, 8,16,32, 8,16,32}; * Bit 0: Thin font */ static uint8_t st_video_options; -static uint8_t st_enabled = 1; -static int8_t st_display_internal = -1; +static uint8_t st_enabled = 1; +static int8_t st_display_internal = -1; -void t1000_video_options_set(uint8_t options) +void +t1000_video_options_set(uint8_t options) { - st_video_options = options & 1; - st_video_options |= language; + st_video_options = options & 1; + st_video_options |= language; } -void t1000_video_enable(uint8_t enabled) +void +t1000_video_enable(uint8_t enabled) { - st_enabled = enabled; + st_enabled = enabled; } -void t1000_display_set(uint8_t internal) +void +t1000_display_set(uint8_t internal) { - st_display_internal = (int8_t)internal; + st_display_internal = (int8_t) internal; } -uint8_t t1000_display_get() +uint8_t +t1000_display_get(void) { - return (uint8_t)st_display_internal; + return (uint8_t) st_display_internal; } +typedef struct t1000_t { + mem_mapping_t mapping; -typedef struct t1000_t -{ - mem_mapping_t mapping; + cga_t cga; /* The CGA is used for the external + * display; most of its registers are + * ignored by the plasma display. */ - cga_t cga; /* The CGA is used for the external - * display; most of its registers are - * ignored by the plasma display. */ + int font; /* Current font, 0-3 */ + int enabled; /* Hardware enabled, 0 or 1 */ + int internal; /* Using internal display? */ + uint8_t attrmap; /* Attribute mapping register */ - int font; /* Current font, 0-3 */ - int enabled; /* Hardware enabled, 0 or 1 */ - int internal; /* Using internal display? */ - uint8_t attrmap; /* Attribute mapping register */ + uint64_t dispontime, dispofftime; - uint64_t dispontime, dispofftime; - - int linepos, displine; - int vc; - int dispon; - int vsynctime; - uint8_t video_options; - uint8_t backlight, invert; + int linepos, displine; + int vc; + int dispon; + int vsynctime; + uint8_t video_options; + uint8_t backlight, invert; - uint8_t *vram; + uint8_t *vram; } t1000_t; +static void t1000_recalctimings(t1000_t *t1000); +static void t1000_write(uint32_t addr, uint8_t val, void *priv); +static uint8_t t1000_read(uint32_t addr, void *priv); +static void t1000_recalcattrs(t1000_t *t1000); -static void t1000_recalctimings(t1000_t *t1000); -static void t1000_write(uint32_t addr, uint8_t val, void *p); -static uint8_t t1000_read(uint32_t addr, void *p); -static void t1000_recalcattrs(t1000_t *t1000); - - -static void t1000_out(uint16_t addr, uint8_t val, void *p) +static void +t1000_out(uint16_t addr, uint8_t val, void *priv) { - t1000_t *t1000 = (t1000_t *)p; - switch (addr) - { - /* Emulated CRTC, register select */ - case 0x3d0: case 0x3d2: case 0x3d4: case 0x3d6: - cga_out(addr, val, &t1000->cga); - break; + t1000_t *t1000 = (t1000_t *) priv; + switch (addr) { + /* Emulated CRTC, register select */ + case 0x3d0: + case 0x3d2: + case 0x3d4: + case 0x3d6: + cga_out(addr, val, &t1000->cga); + break; - /* Emulated CRTC, value */ - case 0x3d1: case 0x3d3: case 0x3d5: case 0x3d7: - /* Register 0x12 controls the attribute mappings for the - * LCD screen. */ - if (t1000->cga.crtcreg == 0x12) - { - t1000->attrmap = val; - t1000_recalcattrs(t1000); - return; - } - cga_out(addr, val, &t1000->cga); + /* Emulated CRTC, value */ + case 0x3d1: + case 0x3d3: + case 0x3d5: + case 0x3d7: + /* Register 0x12 controls the attribute mappings for the + * LCD screen. */ + if (t1000->cga.crtcreg == 0x12) { + t1000->attrmap = val; + t1000_recalcattrs(t1000); + return; + } + cga_out(addr, val, &t1000->cga); - t1000_recalctimings(t1000); - return; + t1000_recalctimings(t1000); + return; - /* CGA control register */ - case 0x3D8: - cga_out(addr, val, &t1000->cga); - return; - /* CGA colour register */ - case 0x3D9: - cga_out(addr, val, &t1000->cga); - return; - } + case 0x3D8: /* CGA control register */ + case 0x3D9: /* CGA colour register */ + cga_out(addr, val, &t1000->cga); + return; + + default: + break; + } } -static uint8_t t1000_in(uint16_t addr, void *p) +static uint8_t +t1000_in(uint16_t addr, void *priv) { - t1000_t *t1000 = (t1000_t *)p; - uint8_t val; + t1000_t *t1000 = (t1000_t *) priv; + uint8_t val; - switch (addr) - { - case 0x3d1: case 0x3d3: case 0x3d5: case 0x3d7: - if (t1000->cga.crtcreg == 0x12) - { - val = t1000->attrmap & 0x0F; - if (t1000->internal) val |= 0x20; /* LCD / CRT */ - return val; - } - } - - return cga_in(addr, &t1000->cga); + switch (addr) { + case 0x3d1: + case 0x3d3: + case 0x3d5: + case 0x3d7: + if (t1000->cga.crtcreg == 0x12) { + val = t1000->attrmap & 0x0F; + if (t1000->internal) + val |= 0x20; /* LCD / CRT */ + return val; + } + break; + + default: + break; + } + + return cga_in(addr, &t1000->cga); } - - - -static void t1000_write(uint32_t addr, uint8_t val, void *p) +static void +t1000_write(uint32_t addr, uint8_t val, void *priv) { - t1000_t *t1000 = (t1000_t *)p; + t1000_t *t1000 = (t1000_t *) priv; - t1000->vram[addr & 0x3fff] = val; - cycles -= 4; -} - -static uint8_t t1000_read(uint32_t addr, void *p) -{ - t1000_t *t1000 = (t1000_t *)p; - cycles -= 4; - - return t1000->vram[addr & 0x3fff]; + t1000->vram[addr & 0x3fff] = val; + cycles -= 4; } - - -static void t1000_recalctimings(t1000_t *t1000) +static uint8_t +t1000_read(uint32_t addr, void *priv) { - double disptime; - double _dispontime, _dispofftime; + const t1000_t *t1000 = (t1000_t *) priv; - if (!t1000->internal) - { - cga_recalctimings(&t1000->cga); - return; - } - disptime = 651; - _dispontime = 640; - _dispofftime = disptime - _dispontime; - t1000->dispontime = (uint64_t)(_dispontime * xt_cpu_multi); - t1000->dispofftime = (uint64_t)(_dispofftime * xt_cpu_multi); + cycles -= 4; + + return t1000->vram[addr & 0x3fff]; +} + +static void +t1000_recalctimings(t1000_t *t1000) +{ + double disptime; + double _dispontime; + double _dispofftime; + + if (!t1000->internal) { + cga_recalctimings(&t1000->cga); + return; + } + disptime = 651; + _dispontime = 640; + _dispofftime = disptime - _dispontime; + t1000->dispontime = (uint64_t) (_dispontime * xt_cpu_multi); + t1000->dispofftime = (uint64_t) (_dispofftime * xt_cpu_multi); } /* Draw a row of text in 80-column mode */ -static void t1000_text_row80(t1000_t *t1000) +static void +t1000_text_row80(t1000_t *t1000) { - uint32_t cols[2]; - int x, c; - uint8_t chr, attr; - int drawcursor; - int cursorline; - int bold; - int blink; - uint16_t addr; - uint8_t sc; - uint16_t ma = (t1000->cga.crtc[13] | (t1000->cga.crtc[12] << 8)) & 0x3fff; - uint16_t ca = (t1000->cga.crtc[15] | (t1000->cga.crtc[14] << 8)) & 0x3fff; + uint32_t cols[2]; + uint8_t chr; + uint8_t attr; + int drawcursor; + int cursorline; + int bold; + int blink; + uint16_t addr; + uint8_t sc; + uint16_t ma = (t1000->cga.crtc[13] | (t1000->cga.crtc[12] << 8)) & 0x3fff; + uint16_t ca = (t1000->cga.crtc[15] | (t1000->cga.crtc[14] << 8)) & 0x3fff; - sc = (t1000->displine) & 7; - addr = ((ma & ~1) + (t1000->displine >> 3) * 80) * 2; - ma += (t1000->displine >> 3) * 80; + sc = (t1000->displine) & 7; + addr = ((ma & ~1) + (t1000->displine >> 3) * 80) * 2; + ma += (t1000->displine >> 3) * 80; - if ((t1000->cga.crtc[10] & 0x60) == 0x20) - { - cursorline = 0; - } - else - { - cursorline = ((t1000->cga.crtc[10] & 0x0F) <= sc) && - ((t1000->cga.crtc[11] & 0x0F) >= sc); - } - for (x = 0; x < 80; x++) + if ((t1000->cga.crtc[10] & 0x60) == 0x20) { + cursorline = 0; + } else { + cursorline = ((t1000->cga.crtc[10] & 0x0F) <= sc) && ((t1000->cga.crtc[11] & 0x0F) >= sc); + } + for (uint8_t x = 0; x < 80; x++) { + chr = t1000->vram[(addr + 2 * x) & 0x3FFF]; + attr = t1000->vram[(addr + 2 * x + 1) & 0x3FFF]; + drawcursor = ((ma == ca) && cursorline && (t1000->cga.cgamode & 8) && (t1000->cga.cgablink & 16)); + + blink = ((t1000->cga.cgablink & 16) && (t1000->cga.cgamode & 0x20) && (attr & 0x80) && !drawcursor); + + if (t1000->video_options & 1) + bold = boldcols[attr] ? chr : chr + 256; + else + bold = boldcols[attr] ? chr + 256 : chr; + if (t1000->video_options & 2) + bold += 512; + + if (t1000->cga.cgamode & 0x20) /* Blink */ { - chr = t1000->vram[(addr + 2 * x) & 0x3FFF]; - attr = t1000->vram[(addr + 2 * x + 1) & 0x3FFF]; - drawcursor = ((ma == ca) && cursorline && - (t1000->cga.cgamode & 8) && (t1000->cga.cgablink & 16)); - - blink = ((t1000->cga.cgablink & 16) && (t1000->cga.cgamode & 0x20) && - (attr & 0x80) && !drawcursor); - - if (t1000->video_options & 1) - bold = boldcols[attr] ? chr : chr + 256; - else - bold = boldcols[attr] ? chr + 256 : chr; - if (t1000->video_options & 2) - bold += 512; - - if (t1000->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[t1000->displine])[(x << 3) + c] = cols[(fontdat[bold][sc] & (1 << (c ^ 7))) ? 1 : 0] ^ (blue ^ grey); - } - } - else - { - for (c = 0; c < 8; c++) - ((uint32_t *)buffer32->line[t1000->displine])[(x << 3) + c] = cols[(fontdat[bold][sc] & (1 << (c ^ 7))) ? 1 : 0]; - } - ++ma; - } + 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 (uint8_t c = 0; c < 8; c++) { + (buffer32->line[t1000->displine])[(x << 3) + c] = cols[(fontdat[bold][sc] & (1 << (c ^ 7))) ? 1 : 0] ^ (blue ^ grey); + } + } else { + for (uint8_t c = 0; c < 8; c++) + (buffer32->line[t1000->displine])[(x << 3) + c] = cols[(fontdat[bold][sc] & (1 << (c ^ 7))) ? 1 : 0]; + } + ++ma; + } } /* Draw a row of text in 40-column mode */ -static void t1000_text_row40(t1000_t *t1000) +static void +t1000_text_row40(t1000_t *t1000) { - uint32_t cols[2]; - int x, c; - uint8_t chr, attr; - int drawcursor; - int cursorline; - int bold; - int blink; - uint16_t addr; - uint8_t sc; - uint16_t ma = (t1000->cga.crtc[13] | (t1000->cga.crtc[12] << 8)) & 0x3fff; - uint16_t ca = (t1000->cga.crtc[15] | (t1000->cga.crtc[14] << 8)) & 0x3fff; + uint32_t cols[2]; + uint8_t chr; + uint8_t attr; + int drawcursor; + int cursorline; + int bold; + int blink; + uint16_t addr; + uint8_t sc; + uint16_t ma = (t1000->cga.crtc[13] | (t1000->cga.crtc[12] << 8)) & 0x3fff; + uint16_t ca = (t1000->cga.crtc[15] | (t1000->cga.crtc[14] << 8)) & 0x3fff; - sc = (t1000->displine) & 7; - addr = ((ma & ~1) + (t1000->displine >> 3) * 40) * 2; - ma += (t1000->displine >> 3) * 40; + sc = (t1000->displine) & 7; + addr = ((ma & ~1) + (t1000->displine >> 3) * 40) * 2; + ma += (t1000->displine >> 3) * 40; - if ((t1000->cga.crtc[10] & 0x60) == 0x20) - { - cursorline = 0; - } - else - { - cursorline = ((t1000->cga.crtc[10] & 0x0F) <= sc) && - ((t1000->cga.crtc[11] & 0x0F) >= sc); - } - for (x = 0; x < 40; x++) + if ((t1000->cga.crtc[10] & 0x60) == 0x20) { + cursorline = 0; + } else { + cursorline = ((t1000->cga.crtc[10] & 0x0F) <= sc) && ((t1000->cga.crtc[11] & 0x0F) >= sc); + } + for (uint8_t x = 0; x < 40; x++) { + chr = t1000->vram[(addr + 2 * x) & 0x3FFF]; + attr = t1000->vram[(addr + 2 * x + 1) & 0x3FFF]; + drawcursor = ((ma == ca) && cursorline && (t1000->cga.cgamode & 8) && (t1000->cga.cgablink & 16)); + + blink = ((t1000->cga.cgablink & 16) && (t1000->cga.cgamode & 0x20) && (attr & 0x80) && !drawcursor); + + if (t1000->video_options & 1) + bold = boldcols[attr] ? chr : chr + 256; + else + bold = boldcols[attr] ? chr + 256 : chr; + if (t1000->video_options & 2) + bold += 512; + + if (t1000->cga.cgamode & 0x20) /* Blink */ { - chr = t1000->vram[(addr + 2 * x) & 0x3FFF]; - attr = t1000->vram[(addr + 2 * x + 1) & 0x3FFF]; - drawcursor = ((ma == ca) && cursorline && - (t1000->cga.cgamode & 8) && (t1000->cga.cgablink & 16)); - - blink = ((t1000->cga.cgablink & 16) && (t1000->cga.cgamode & 0x20) && - (attr & 0x80) && !drawcursor); - - if (t1000->video_options & 1) - bold = boldcols[attr] ? chr : chr + 256; - else - bold = boldcols[attr] ? chr + 256 : chr; - if (t1000->video_options & 2) - bold += 512; - - if (t1000->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[t1000->displine])[(x << 4) + c*2] = - ((uint32_t *)buffer32->line[t1000->displine])[(x << 4) + c*2 + 1] = cols[(fontdat[bold][sc] & (1 << (c ^ 7))) ? 1 : 0] ^ (blue ^ grey); - } - } - else - { - for (c = 0; c < 8; c++) - { - ((uint32_t *)buffer32->line[t1000->displine])[(x << 4) + c*2] = - ((uint32_t *)buffer32->line[t1000->displine])[(x << 4) + c*2+1] = cols[(fontdat[bold][sc] & (1 << (c ^ 7))) ? 1 : 0]; - } - } - ++ma; - } + 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 (uint8_t c = 0; c < 8; c++) { + (buffer32->line[t1000->displine])[(x << 4) + c * 2] = (buffer32->line[t1000->displine])[(x << 4) + c * 2 + 1] = cols[(fontdat[bold][sc] & (1 << (c ^ 7))) ? 1 : 0] ^ (blue ^ grey); + } + } else { + for (uint8_t c = 0; c < 8; c++) { + (buffer32->line[t1000->displine])[(x << 4) + c * 2] = (buffer32->line[t1000->displine])[(x << 4) + c * 2 + 1] = cols[(fontdat[bold][sc] & (1 << (c ^ 7))) ? 1 : 0]; + } + } + ++ma; + } } /* Draw a line in CGA 640x200 mode */ -static void t1000_cgaline6(t1000_t *t1000) +static void +t1000_cgaline6(t1000_t *t1000) { - int x, c; - uint8_t dat; - uint32_t ink = 0; - uint16_t addr; - uint32_t fg = (t1000->cga.cgacol & 0x0F) ? blue : grey; - uint32_t bg = grey; + uint8_t dat; + uint32_t ink = 0; + uint16_t addr; + uint32_t fg = (t1000->cga.cgacol & 0x0F) ? blue : grey; + uint32_t bg = grey; - uint16_t ma = (t1000->cga.crtc[13] | (t1000->cga.crtc[12] << 8)) & 0x3fff; + uint16_t ma = (t1000->cga.crtc[13] | (t1000->cga.crtc[12] << 8)) & 0x3fff; - addr = ((t1000->displine) & 1) * 0x2000 + - (t1000->displine >> 1) * 80 + - ((ma & ~1) << 1); + addr = ((t1000->displine) & 1) * 0x2000 + (t1000->displine >> 1) * 80 + ((ma & ~1) << 1); - for (x = 0; x < 80; x++) - { - dat = t1000->vram[addr & 0x3FFF]; - addr++; + for (uint8_t x = 0; x < 80; x++) { + dat = t1000->vram[addr & 0x3FFF]; + addr++; - for (c = 0; c < 8; c++) - { - ink = (dat & 0x80) ? fg : bg; - if (!(t1000->cga.cgamode & 8)) - ink = grey; - ((uint32_t *)buffer32->line[t1000->displine])[x*8+c] = ink; - dat = dat << 1; - } - } + for (uint8_t c = 0; c < 8; c++) { + ink = (dat & 0x80) ? fg : bg; + if (!(t1000->cga.cgamode & 8)) + ink = grey; + (buffer32->line[t1000->displine])[x * 8 + c] = ink; + dat = 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 t1000_cgaline4(t1000_t *t1000) +static void +t1000_cgaline4(t1000_t *t1000) { - int x, c; - uint8_t dat, pattern; - uint32_t ink0, ink1; - uint16_t addr; + uint8_t dat; + uint8_t pattern; + uint32_t ink0; + uint32_t ink1; + uint16_t addr; - uint16_t ma = (t1000->cga.crtc[13] | (t1000->cga.crtc[12] << 8)) & 0x3fff; - addr = ((t1000->displine) & 1) * 0x2000 + - (t1000->displine >> 1) * 80 + - ((ma & ~1) << 1); + uint16_t ma = (t1000->cga.crtc[13] | (t1000->cga.crtc[12] << 8)) & 0x3fff; + addr = ((t1000->displine) & 1) * 0x2000 + (t1000->displine >> 1) * 80 + ((ma & ~1) << 1); - for (x = 0; x < 80; x++) - { - dat = t1000->vram[addr & 0x3FFF]; - addr++; + for (uint8_t x = 0; x < 80; x++) { + dat = t1000->vram[addr & 0x3FFF]; + addr++; - for (c = 0; c < 4; c++) - { - pattern = (dat & 0xC0) >> 6; - if (!(t1000->cga.cgamode & 8)) pattern = 0; + for (uint8_t c = 0; c < 4; c++) { + pattern = (dat & 0xC0) >> 6; + if (!(t1000->cga.cgamode & 8)) + pattern = 0; - switch (pattern & 3) - { - default: - case 0: ink0 = ink1 = grey; break; - case 1: if (t1000->displine & 1) - { - ink0 = grey; ink1 = grey; - } - else - { - ink0 = blue; ink1 = grey; - } - break; - case 2: if (t1000->displine & 1) - { - ink0 = grey; ink1 = blue; - } - else - { - ink0 = blue; ink1 = grey; - } - break; - case 3: ink0 = ink1 = blue; break; - - } - ((uint32_t *)buffer32->line[t1000->displine])[x*8+2*c] = ink0; - ((uint32_t *)buffer32->line[t1000->displine])[x*8+2*c+1] = ink1; - dat = dat << 2; - } - } + switch (pattern & 3) { + default: + case 0: + ink0 = ink1 = grey; + break; + case 1: + if (t1000->displine & 1) { + ink0 = grey; + ink1 = grey; + } else { + ink0 = blue; + ink1 = grey; + } + break; + case 2: + if (t1000->displine & 1) { + ink0 = grey; + ink1 = blue; + } else { + ink0 = blue; + ink1 = grey; + } + break; + case 3: + ink0 = ink1 = blue; + break; + } + (buffer32->line[t1000->displine])[x * 8 + 2 * c] = ink0; + (buffer32->line[t1000->displine])[x * 8 + 2 * c + 1] = ink1; + dat = dat << 2; + } + } } -static void t1000_poll(void *p) +static void +t1000_poll(void *priv) { - t1000_t *t1000 = (t1000_t *)p; + t1000_t *t1000 = (t1000_t *) priv; - if (t1000->video_options != st_video_options || - t1000->enabled != st_enabled) - { - t1000->video_options = st_video_options; - t1000->enabled = st_enabled; + if (t1000->video_options != st_video_options || t1000->enabled != st_enabled) { + t1000->video_options = st_video_options; + t1000->enabled = st_enabled; - /* Set the font used for the external display */ - t1000->cga.fontbase = ((t1000->video_options & 3) * 256); - - if (t1000->enabled) /* Disable internal chipset */ - mem_mapping_enable(&t1000->mapping); - else - mem_mapping_disable(&t1000->mapping); - } - /* Switch between internal plasma and external CRT display. */ - if (st_display_internal != -1 && st_display_internal != t1000->internal) - { - t1000->internal = st_display_internal; - t1000_recalctimings(t1000); - } - if (!t1000->internal) - { - cga_poll(&t1000->cga); - return; - } + /* Set the font used for the external display */ + t1000->cga.fontbase = ((t1000->video_options & 3) * 256); - if (!t1000->linepos) - { - timer_advance_u64(&t1000->cga.timer, t1000->dispofftime); - t1000->cga.cgastat |= 1; - t1000->linepos = 1; - if (t1000->dispon) - { - if (t1000->displine == 0) - { - video_wait_for_buffer(); - } - - /* Graphics */ - if (t1000->cga.cgamode & 0x02) - { - if (t1000->cga.cgamode & 0x10) - t1000_cgaline6(t1000); - else t1000_cgaline4(t1000); - } - else - if (t1000->cga.cgamode & 0x01) /* High-res text */ - { - t1000_text_row80(t1000); - } - else - { - t1000_text_row40(t1000); - } - } - t1000->displine++; - /* Hardcode a fixed refresh rate and VSYNC timing */ - if (t1000->displine == 200) /* Start of VSYNC */ - { - t1000->cga.cgastat |= 8; - t1000->dispon = 0; - } - if (t1000->displine == 216) /* End of VSYNC */ - { - t1000->displine = 0; - t1000->cga.cgastat &= ~8; - t1000->dispon = 1; - } - } + if (t1000->enabled) /* Disable internal chipset */ + mem_mapping_enable(&t1000->mapping); else - { - if (t1000->dispon) - { - t1000->cga.cgastat &= ~1; - } - timer_advance_u64(&t1000->cga.timer, t1000->dispontime); - t1000->linepos = 0; - - if (t1000->displine == 200) - { - /* Hardcode 640x200 window size */ - if ((T1000_XSIZE != xsize) || (T1000_YSIZE != ysize) || video_force_resize_get()) - { - xsize = T1000_XSIZE; - ysize = T1000_YSIZE; - if (xsize < 64) xsize = 656; - if (ysize < 32) ysize = 200; - set_screen_size(xsize, ysize); - - if (video_force_resize_get()) - video_force_resize_set(0); - } - video_blit_memtoscreen(0, 0, xsize, ysize); - - frames++; - /* Fixed 640x200 resolution */ - video_res_x = T1000_XSIZE; - video_res_y = T1000_YSIZE; - - if (t1000->cga.cgamode & 0x02) - { - if (t1000->cga.cgamode & 0x10) - video_bpp = 1; - else video_bpp = 2; - - } - else video_bpp = 0; - t1000->cga.cgablink++; - } - } -} - -static void t1000_recalcattrs(t1000_t *t1000) -{ - int n; - - /* val behaves as follows: - * Bit 0: Attributes 01-06, 08-0E are inverse video - * Bit 1: Attributes 01-06, 08-0E are bold - * Bit 2: Attributes 11-16, 18-1F, 21-26, 28-2F ... F1-F6, F8-FF - * are inverse video - * Bit 3: Attributes 11-16, 18-1F, 21-26, 28-2F ... F1-F6, F8-FF - * are bold */ - - /* Set up colours */ - if (t1000->invert) { - if (t1000->backlight) { - grey = makecol(0x2D, 0x39, 0x5A); - blue = makecol(0x85, 0xa0, 0xD6); - } else { - grey = makecol(0x0f, 0x21, 0x3f); - blue = makecol(0x1C, 0x71, 0x31); - } - } else { - if (t1000->backlight) { - blue = makecol(0x2D, 0x39, 0x5A); - grey = makecol(0x85, 0xa0, 0xD6); - } else { - blue = makecol(0x0f, 0x21, 0x3f); - grey = makecol(0x1C, 0x71, 0x31); - } - } - - /* Initialise the attribute mapping. Start by defaulting everything - * to grey on blue, and with bold set by bit 3 */ - for (n = 0; n < 256; n++) - { - boldcols[n] = (n & 8) != 0; - blinkcols[n][0] = normcols[n][0] = blue; - blinkcols[n][1] = normcols[n][1] = grey; - } - - /* Colours 0x11-0xFF are controlled by bits 2 and 3 of the - * passed value. Exclude x0 and x8, which are always grey on - * blue. */ - for (n = 0x11; n <= 0xFF; n++) - { - if ((n & 7) == 0) continue; - if (t1000->attrmap & 4) /* Inverse */ - { - blinkcols[n][0] = normcols[n][0] = blue; - blinkcols[n][1] = normcols[n][1] = grey; - } - else /* Normal */ - { - blinkcols[n][0] = normcols[n][0] = grey; - blinkcols[n][1] = normcols[n][1] = blue; - } - if (t1000->attrmap & 8) boldcols[n] = 1; /* Bold */ - } - /* Set up the 01-0E range, controlled by bits 0 and 1 of the - * passed value. When blinking is enabled this also affects 81-8E. */ - for (n = 0x01; n <= 0x0E; n++) - { - if (n == 7) continue; - if (t1000->attrmap & 1) - { - blinkcols[n][0] = normcols[n][0] = blue; - blinkcols[n][1] = normcols[n][1] = grey; - blinkcols[n+128][0] = blue; - blinkcols[n+128][1] = grey; - } - else - { - blinkcols[n][0] = normcols[n][0] = grey; - blinkcols[n][1] = normcols[n][1] = blue; - blinkcols[n+128][0] = grey; - blinkcols[n+128][1] = blue; - } - if (t1000->attrmap & 2) boldcols[n] = 1; - } - /* Colours 07 and 0F are always blue on grey. If blinking is - * enabled so are 87 and 8F. */ - for (n = 0x07; n <= 0x0F; n += 8) - { - blinkcols[n][0] = normcols[n][0] = grey; - blinkcols[n][1] = normcols[n][1] = blue; - blinkcols[n+128][0] = grey; - blinkcols[n+128][1] = blue; - } - /* When not blinking, colours 81-8F are always blue on grey. */ - for (n = 0x81; n <= 0x8F; n ++) - { - normcols[n][0] = grey; - normcols[n][1] = blue; - boldcols[n] = (n & 0x08) != 0; - } - - - /* Finally do the ones which are solid grey. These differ between - * the normal and blinking mappings */ - for (n = 0; n <= 0xFF; n += 0x11) - { - normcols[n][0] = normcols[n][1] = grey; - } - /* In the blinking range, 00 11 22 .. 77 and 80 91 A2 .. F7 are grey */ - for (n = 0; n <= 0x77; n += 0x11) - { - blinkcols[n][0] = blinkcols[n][1] = grey; - blinkcols[n+128][0] = blinkcols[n+128][1] = grey; - } -} - - -static void *t1000_init(const device_t *info) -{ - t1000_t *t1000 = malloc(sizeof(t1000_t)); - memset(t1000, 0, sizeof(t1000_t)); - loadfont("roms/machines/t1000/t1000font.bin", 8); - cga_init(&t1000->cga); - video_inform(VIDEO_FLAG_TYPE_CGA, &timing_t1000); - - t1000->internal = 1; - - t1000->backlight = device_get_config_int("backlight"); - t1000->invert = device_get_config_int("invert"); - - /* 16k video RAM */ - t1000->vram = malloc(0x4000); - - timer_set_callback(&t1000->cga.timer, t1000_poll); - timer_set_p(&t1000->cga.timer, t1000); - - /* Occupy memory between 0xB8000 and 0xBFFFF */ - mem_mapping_add(&t1000->mapping, 0xb8000, 0x8000, t1000_read, NULL, NULL, t1000_write, NULL, NULL, NULL, 0, t1000); - /* Respond to CGA I/O ports */ - io_sethandler(0x03d0, 0x000c, t1000_in, NULL, NULL, t1000_out, NULL, NULL, t1000); - - /* Default attribute mapping is 4 */ - t1000->attrmap = 4; - t1000_recalcattrs(t1000); - - /* Start off in 80x25 text mode */ - t1000->cga.cgastat = 0xF4; - t1000->cga.vram = t1000->vram; - t1000->enabled = 1; - t1000->video_options = 0x01; - language = device_get_config_int("display_language") ? 2 : 0; - return t1000; -} - -static void t1000_close(void *p) -{ - t1000_t *t1000 = (t1000_t *)p; - - free(t1000->vram); - free(t1000); -} - -static void t1000_speed_changed(void *p) -{ - t1000_t *t1000 = (t1000_t *)p; - + mem_mapping_disable(&t1000->mapping); + } + /* Switch between internal plasma and external CRT display. */ + if (st_display_internal != -1 && st_display_internal != t1000->internal) { + t1000->internal = st_display_internal; t1000_recalctimings(t1000); + } + if (!t1000->internal) { + cga_poll(&t1000->cga); + return; + } + + if (!t1000->linepos) { + timer_advance_u64(&t1000->cga.timer, t1000->dispofftime); + t1000->cga.cgastat |= 1; + t1000->linepos = 1; + if (t1000->dispon) { + if (t1000->displine == 0) { + video_wait_for_buffer(); + } + + /* Graphics */ + if (t1000->cga.cgamode & 0x02) { + if (t1000->cga.cgamode & 0x10) + t1000_cgaline6(t1000); + else + t1000_cgaline4(t1000); + } else if (t1000->cga.cgamode & 0x01) /* High-res text */ + { + t1000_text_row80(t1000); + } else { + t1000_text_row40(t1000); + } + } + t1000->displine++; + /* Hardcode a fixed refresh rate and VSYNC timing */ + if (t1000->displine == 200) /* Start of VSYNC */ + { + t1000->cga.cgastat |= 8; + t1000->dispon = 0; + } + if (t1000->displine == 216) /* End of VSYNC */ + { + t1000->displine = 0; + t1000->cga.cgastat &= ~8; + t1000->dispon = 1; + } + } else { + if (t1000->dispon) { + t1000->cga.cgastat &= ~1; + } + timer_advance_u64(&t1000->cga.timer, t1000->dispontime); + t1000->linepos = 0; + + if (t1000->displine == 200) { + /* Hardcode 640x200 window size */ + if ((T1000_XSIZE != xsize) || (T1000_YSIZE != ysize) || video_force_resize_get()) { + xsize = T1000_XSIZE; + ysize = T1000_YSIZE; + if (xsize < 64) + xsize = 656; + if (ysize < 32) + ysize = 200; + set_screen_size(xsize, ysize); + + if (video_force_resize_get()) + video_force_resize_set(0); + } + video_blit_memtoscreen(0, 0, xsize, ysize); + + frames++; + /* Fixed 640x200 resolution */ + video_res_x = T1000_XSIZE; + video_res_y = T1000_YSIZE; + + if (t1000->cga.cgamode & 0x02) { + if (t1000->cga.cgamode & 0x10) + video_bpp = 1; + else + video_bpp = 2; + + } else + video_bpp = 0; + t1000->cga.cgablink++; + } + } } -static const device_config_t t1000_config[] = +static void +t1000_recalcattrs(t1000_t *t1000) { - { - .name = "display_language", - .description = "Language", - .type = CONFIG_SELECTION, - .selection = - { - { - .description = "USA", - .value = 0 - }, - { - .description = "Danish", - .value = 1 - } - }, - .default_int = 0 - }, - { - "backlight", "Enable backlight", CONFIG_BINARY, "", 1 - }, - { - "invert", "Invert colors", CONFIG_BINARY, "", 0 - }, - { - .type = -1 - } -}; + int n; + /* val behaves as follows: + * Bit 0: Attributes 01-06, 08-0E are inverse video + * Bit 1: Attributes 01-06, 08-0E are bold + * Bit 2: Attributes 11-16, 18-1F, 21-26, 28-2F ... F1-F6, F8-FF + * are inverse video + * Bit 3: Attributes 11-16, 18-1F, 21-26, 28-2F ... F1-F6, F8-FF + * are bold */ + + /* Set up colours */ + if (t1000->invert) { + if (t1000->backlight) { + grey = makecol(0x2D, 0x39, 0x5A); + blue = makecol(0x85, 0xa0, 0xD6); + } else { + grey = makecol(0x0f, 0x21, 0x3f); + blue = makecol(0x1C, 0x71, 0x31); + } + } else { + if (t1000->backlight) { + blue = makecol(0x2D, 0x39, 0x5A); + grey = makecol(0x85, 0xa0, 0xD6); + } else { + blue = makecol(0x0f, 0x21, 0x3f); + grey = makecol(0x1C, 0x71, 0x31); + } + } + + /* Initialise the attribute mapping. Start by defaulting everything + * to grey on blue, and with bold set by bit 3 */ + for (n = 0; n < 256; n++) { + boldcols[n] = (n & 8) != 0; + blinkcols[n][0] = normcols[n][0] = blue; + blinkcols[n][1] = normcols[n][1] = grey; + } + + /* Colours 0x11-0xFF are controlled by bits 2 and 3 of the + * passed value. Exclude x0 and x8, which are always grey on + * blue. */ + for (n = 0x11; n <= 0xFF; n++) { + if ((n & 7) == 0) + continue; + if (t1000->attrmap & 4) /* Inverse */ + { + blinkcols[n][0] = normcols[n][0] = blue; + blinkcols[n][1] = normcols[n][1] = grey; + } else /* Normal */ + { + blinkcols[n][0] = normcols[n][0] = grey; + blinkcols[n][1] = normcols[n][1] = blue; + } + if (t1000->attrmap & 8) + boldcols[n] = 1; /* Bold */ + } + /* Set up the 01-0E range, controlled by bits 0 and 1 of the + * passed value. When blinking is enabled this also affects 81-8E. */ + for (n = 0x01; n <= 0x0E; n++) { + if (n == 7) + continue; + if (t1000->attrmap & 1) { + blinkcols[n][0] = normcols[n][0] = blue; + blinkcols[n][1] = normcols[n][1] = grey; + blinkcols[n + 128][0] = blue; + blinkcols[n + 128][1] = grey; + } else { + blinkcols[n][0] = normcols[n][0] = grey; + blinkcols[n][1] = normcols[n][1] = blue; + blinkcols[n + 128][0] = grey; + blinkcols[n + 128][1] = blue; + } + if (t1000->attrmap & 2) + boldcols[n] = 1; + } + /* Colours 07 and 0F are always blue on grey. If blinking is + * enabled so are 87 and 8F. */ + for (n = 0x07; n <= 0x0F; n += 8) { + blinkcols[n][0] = normcols[n][0] = grey; + blinkcols[n][1] = normcols[n][1] = blue; + blinkcols[n + 128][0] = grey; + blinkcols[n + 128][1] = blue; + } + /* When not blinking, colours 81-8F are always blue on grey. */ + for (n = 0x81; n <= 0x8F; n++) { + normcols[n][0] = grey; + normcols[n][1] = blue; + boldcols[n] = (n & 0x08) != 0; + } + + /* Finally do the ones which are solid grey. These differ between + * the normal and blinking mappings */ + for (n = 0; n <= 0xFF; n += 0x11) { + normcols[n][0] = normcols[n][1] = grey; + } + /* In the blinking range, 00 11 22 .. 77 and 80 91 A2 .. F7 are grey */ + for (n = 0; n <= 0x77; n += 0x11) { + blinkcols[n][0] = blinkcols[n][1] = grey; + blinkcols[n + 128][0] = blinkcols[n + 128][1] = grey; + } +} + +static void * +t1000_init(UNUSED(const device_t *info)) +{ + t1000_t *t1000 = malloc(sizeof(t1000_t)); + memset(t1000, 0, sizeof(t1000_t)); + loadfont("roms/machines/t1000/t1000font.bin", 8); + cga_init(&t1000->cga); + video_inform(VIDEO_FLAG_TYPE_CGA, &timing_t1000); + + t1000->internal = 1; + + t1000->backlight = device_get_config_int("backlight"); + t1000->invert = device_get_config_int("invert"); + + /* 16k video RAM */ + t1000->vram = malloc(0x4000); + + timer_set_callback(&t1000->cga.timer, t1000_poll); + timer_set_p(&t1000->cga.timer, t1000); + + /* Occupy memory between 0xB8000 and 0xBFFFF */ + mem_mapping_add(&t1000->mapping, 0xb8000, 0x8000, t1000_read, NULL, NULL, t1000_write, NULL, NULL, NULL, 0, t1000); + /* Respond to CGA I/O ports */ + io_sethandler(0x03d0, 0x000c, t1000_in, NULL, NULL, t1000_out, NULL, NULL, t1000); + + /* Default attribute mapping is 4 */ + t1000->attrmap = 4; + t1000_recalcattrs(t1000); + + /* Start off in 80x25 text mode */ + t1000->cga.cgastat = 0xF4; + t1000->cga.vram = t1000->vram; + t1000->enabled = 1; + t1000->video_options = 0x01; + language = device_get_config_int("display_language") ? 2 : 0; + return t1000; +} + +static void +t1000_close(void *priv) +{ + t1000_t *t1000 = (t1000_t *) priv; + + free(t1000->vram); + free(t1000); +} + +static void +t1000_speed_changed(void *priv) +{ + t1000_t *t1000 = (t1000_t *) priv; + + t1000_recalctimings(t1000); +} + +static const device_config_t t1000_config[] = { + // clang-format off + { + .name = "display_language", + .description = "Language", + .type = CONFIG_SELECTION, + .selection = { + { .description = "USA", .value = 0 }, + { .description = "Danish", .value = 1 } + }, + .default_int = 0 + }, + { + .name = "backlight", + .description = "Enable backlight", + .type = CONFIG_BINARY, + .default_string = "", + .default_int = 1 + }, + { + .name = "invert", + .description = "Invert colors", + .type = CONFIG_BINARY, + .default_string = "", + .default_int = 0 + }, + { .name = "", .description = "", .type = CONFIG_END } + // clang-format on +}; const device_t t1000_video_device = { - "Toshiba T1000 Video", - "t1000_video", - 0, 0, - t1000_init, t1000_close, NULL, - { NULL }, - t1000_speed_changed, - NULL, - t1000_config + .name = "Toshiba T1000 Video", + .internal_name = "t1000_video", + .flags = 0, + .local = 0, + .init = t1000_init, + .close = t1000_close, + .reset = NULL, + { .available = NULL }, + .speed_changed = t1000_speed_changed, + .force_redraw = NULL, + .config = t1000_config }; - const device_t t1200_video_device = { - "Toshiba T1200 Video", - "t1200_video", - 0, 0, - t1000_init, t1000_close, NULL, - { NULL }, - t1000_speed_changed, - NULL, - t1000_config + .name = "Toshiba T1200 Video", + .internal_name = "t1200_video", + .flags = 0, + .local = 0, + .init = t1000_init, + .close = t1000_close, + .reset = NULL, + { .available = NULL }, + .speed_changed = t1000_speed_changed, + .force_redraw = NULL, + .config = t1000_config }; diff --git a/src/machine/m_xt_xi8088.c b/src/machine/m_xt_xi8088.c index bb56b3486..3f07e6a4e 100644 --- a/src/machine/m_xt_xi8088.c +++ b/src/machine/m_xt_xi8088.c @@ -24,204 +24,185 @@ #include <86box/video.h> #include <86box/machine.h> #include "cpu.h" +#include <86box/plat_unused.h> #include <86box/m_xt_xi8088.h> -typedef struct xi8088_t -{ - uint8_t turbo; +typedef struct xi8088_t { + uint8_t turbo; - int turbo_setting; - int bios_128kb; + int turbo_setting; + int bios_128kb; } xi8088_t; - -static xi8088_t xi8088; - +static xi8088_t xi8088; uint8_t -xi8088_turbo_get() +xi8088_turbo_get(void) { return xi8088.turbo; } - void xi8088_turbo_set(uint8_t value) { int c; if (!xi8088.turbo_setting) - return; + return; xi8088.turbo = value; if (!value) { - c = cpu; - cpu = 0; /* 8088/4.77 */ - cpu_set(); - cpu = c; + c = cpu; + cpu = 0; /* 8088/4.77 */ + cpu_set(); + cpu = c; } else - cpu_set(); + cpu_set(); } - int xi8088_bios_128kb(void) { return xi8088.bios_128kb; } - static void * -xi8088_init(const device_t *info) +xi8088_init(UNUSED(const device_t *info)) { - xi8088.turbo = 1; + xi8088.turbo = 1; xi8088.turbo_setting = device_get_config_int("turbo_setting"); - xi8088.bios_128kb = device_get_config_int("bios_128kb"); + xi8088.bios_128kb = device_get_config_int("bios_128kb"); - mem_set_mem_state(0x0a0000, 0x20000, MEM_READ_EXTANY | MEM_WRITE_EXTANY); - mem_set_mem_state(0x0c0000, 0x08000, device_get_config_int("umb_c0000h_c7fff") ? (MEM_READ_INTERNAL | MEM_WRITE_INTERNAL) : (MEM_READ_EXTANY | MEM_WRITE_EXTANY)); - mem_set_mem_state(0x0c8000, 0x08000, device_get_config_int("umb_c8000h_cffff") ? (MEM_READ_INTERNAL | MEM_WRITE_INTERNAL) : (MEM_READ_EXTANY | MEM_WRITE_EXTANY)); - mem_set_mem_state(0x0d0000, 0x08000, device_get_config_int("umb_d0000h_d7fff") ? (MEM_READ_INTERNAL | MEM_WRITE_INTERNAL) : (MEM_READ_EXTANY | MEM_WRITE_EXTANY)); - mem_set_mem_state(0x0d8000, 0x08000, device_get_config_int("umb_d8000h_dffff") ? (MEM_READ_INTERNAL | MEM_WRITE_INTERNAL) : (MEM_READ_EXTANY | MEM_WRITE_EXTANY)); - mem_set_mem_state(0x0e0000, 0x08000, device_get_config_int("umb_e0000h_e7fff") ? (MEM_READ_INTERNAL | MEM_WRITE_INTERNAL) : (MEM_READ_EXTANY | MEM_WRITE_EXTANY)); - mem_set_mem_state(0x0e8000, 0x08000, device_get_config_int("umb_e8000h_effff") ? (MEM_READ_INTERNAL | MEM_WRITE_INTERNAL) : (MEM_READ_EXTANY | MEM_WRITE_EXTANY)); - mem_set_mem_state(0x0f0000, 0x10000, MEM_READ_EXTANY | MEM_WRITE_EXTANY); + mem_set_mem_state(0x0a0000, 0x20000, MEM_READ_EXTANY | MEM_WRITE_EXTANY); + mem_set_mem_state(0x0c0000, 0x08000, device_get_config_int("umb_c0000h_c7fff") ? (MEM_READ_INTERNAL | MEM_WRITE_INTERNAL) : (MEM_READ_EXTANY | MEM_WRITE_EXTANY)); + mem_set_mem_state(0x0c8000, 0x08000, device_get_config_int("umb_c8000h_cffff") ? (MEM_READ_INTERNAL | MEM_WRITE_INTERNAL) : (MEM_READ_EXTANY | MEM_WRITE_EXTANY)); + mem_set_mem_state(0x0d0000, 0x08000, device_get_config_int("umb_d0000h_d7fff") ? (MEM_READ_INTERNAL | MEM_WRITE_INTERNAL) : (MEM_READ_EXTANY | MEM_WRITE_EXTANY)); + mem_set_mem_state(0x0d8000, 0x08000, device_get_config_int("umb_d8000h_dffff") ? (MEM_READ_INTERNAL | MEM_WRITE_INTERNAL) : (MEM_READ_EXTANY | MEM_WRITE_EXTANY)); + mem_set_mem_state(0x0e0000, 0x08000, device_get_config_int("umb_e0000h_e7fff") ? (MEM_READ_INTERNAL | MEM_WRITE_INTERNAL) : (MEM_READ_EXTANY | MEM_WRITE_EXTANY)); + mem_set_mem_state(0x0e8000, 0x08000, device_get_config_int("umb_e8000h_effff") ? (MEM_READ_INTERNAL | MEM_WRITE_INTERNAL) : (MEM_READ_EXTANY | MEM_WRITE_EXTANY)); + mem_set_mem_state(0x0f0000, 0x10000, MEM_READ_EXTANY | MEM_WRITE_EXTANY); return &xi8088; } - -static const device_config_t xi8088_config[] = -{ - { - .name = "turbo_setting", - .description = "Turbo", - .type = CONFIG_SELECTION, - .selection = - { - { - .description = "Always at selected speed", - .value = 0 - }, - { - .description = "BIOS setting + Hotkeys (off during POST)", - .value = 1 - } - }, - .default_int = 0 +static const device_config_t xi8088_config[] = { + // clang-format off + { + .name = "turbo_setting", + .description = "Turbo", + .type = CONFIG_SELECTION, + .selection = { + { + .description = "Always at selected speed", + .value = 0 + }, + { + .description = "BIOS setting + Hotkeys (off during POST)", + .value = 1 + } }, - { - .name = "bios_128kb", - .description = "BIOS size", - .type = CONFIG_SELECTION, - .selection = - { - { - .description = "64KB starting from 0xF0000", - .value = 0 - }, - { - .description = "128KB starting from 0xE0000 (address MSB inverted, last 64KB first)", - .value = 1 - } - }, - .default_int = 1 + .default_int = 0 + }, + { + .name = "bios_128kb", + .description = "BIOS size", + .type = CONFIG_SELECTION, + .selection = { + { + .description = "64KB starting from 0xF0000", + .value = 0 + }, + { + .description = "128KB starting from 0xE0000 (address MSB inverted, last 64KB first)", + .value = 1 + } }, - { - .name = "umb_c0000h_c7fff", - .description = "Map 0xc0000-0xc7fff as UMB", - .type = CONFIG_BINARY, - .default_int = 0 - }, - { - .name = "umb_c8000h_cffff", - .description = "Map 0xc8000-0xcffff as UMB", - .type = CONFIG_BINARY, - .default_int = 0 - }, - { - .name = "umb_d0000h_d7fff", - .description = "Map 0xd0000-0xd7fff as UMB", - .type = CONFIG_BINARY, - .default_int = 0 - }, - { - .name = "umb_d8000h_dffff", - .description = "Map 0xd8000-0xdffff as UMB", - .type = CONFIG_BINARY, - .default_int = 0 - }, - { - .name = "umb_e0000h_e7fff", - .description = "Map 0xe0000-0xe7fff as UMB", - .type = CONFIG_BINARY, - .default_int = 0 - }, - { - .name = "umb_e8000h_effff", - .description = "Map 0xe8000-0xeffff as UMB", - .type = CONFIG_BINARY, - .default_int = 0 - }, - { - .type = -1 - } + .default_int = 1 + }, + { + .name = "umb_c0000h_c7fff", + .description = "Map 0xc0000-0xc7fff as UMB", + .type = CONFIG_BINARY, + .default_int = 0 + }, + { + .name = "umb_c8000h_cffff", + .description = "Map 0xc8000-0xcffff as UMB", + .type = CONFIG_BINARY, + .default_int = 0 + }, + { + .name = "umb_d0000h_d7fff", + .description = "Map 0xd0000-0xd7fff as UMB", + .type = CONFIG_BINARY, + .default_int = 0 + }, + { + .name = "umb_d8000h_dffff", + .description = "Map 0xd8000-0xdffff as UMB", + .type = CONFIG_BINARY, + .default_int = 0 + }, + { + .name = "umb_e0000h_e7fff", + .description = "Map 0xe0000-0xe7fff as UMB", + .type = CONFIG_BINARY, + .default_int = 0 + }, + { + .name = "umb_e8000h_effff", + .description = "Map 0xe8000-0xeffff as UMB", + .type = CONFIG_BINARY, + .default_int = 0 + }, + { .name = "", .description = "", .type = CONFIG_END } + // clang-format on }; - -const device_t xi8088_device = -{ - "Xi8088", - "xi8088", - 0, - 0, - xi8088_init, - NULL, - NULL, - { NULL }, - NULL, - NULL, - xi8088_config +const device_t xi8088_device = { + .name = "Xi8088", + .internal_name = "xi8088", + .flags = 0, + .local = 0, + .init = xi8088_init, + .close = NULL, + .reset = NULL, + { .available = NULL }, + .speed_changed = NULL, + .force_redraw = NULL, + .config = xi8088_config }; - -const device_t * -xi8088_get_device(void) -{ - return &xi8088_device; -} - - int machine_xt_xi8088_init(const machine_t *model) { int ret; if (bios_only) { - ret = bios_load_linear_inverted("roms/machines/xi8088/bios-xi8088-128k.bin", - 0x000e0000, 131072, 0); - ret |= bios_load_linear("roms/machines/xi8088/bios-xi8088.bin", - 0x000f0000, 65536, 0); + ret = bios_load_linear_inverted("roms/machines/xi8088/bios-xi8088-128k.bin", + 0x000e0000, 131072, 0); + ret |= bios_load_linear("roms/machines/xi8088/bios-xi8088.bin", + 0x000f0000, 65536, 0); } else { - device_add(&xi8088_device); + device_add(&xi8088_device); - if (xi8088_bios_128kb()) { - ret = bios_load_linear_inverted("roms/machines/xi8088/bios-xi8088-128k.bin", - 0x000e0000, 131072, 0); - } else { - ret = bios_load_linear("roms/machines/xi8088/bios-xi8088.bin", - 0x000f0000, 65536, 0); - } + if (xi8088_bios_128kb()) { + ret = bios_load_linear_inverted("roms/machines/xi8088/bios-xi8088-128k.bin", + 0x000e0000, 131072, 0); + } else { + ret = bios_load_linear("roms/machines/xi8088/bios-xi8088.bin", + 0x000f0000, 65536, 0); + } } if (bios_only || !ret) - return ret; + return ret; machine_common_init(model); if (fdc_type == FDC_INTERNAL) - device_add(&fdc_at_device); + device_add(&fdc_at_device); device_add(&keyboard_ps2_xi8088_device); device_add(&port_6x_xi8088_device); @@ -229,7 +210,7 @@ machine_xt_xi8088_init(const machine_t *model) device_add(&ibmat_nvr_device); pic2_init(); standalone_gameport_type = &gameport_device; - device_add(&sst_flash_39sf010_device); + device_add(&sst_flash_39sf010_device); return ret; } diff --git a/src/machine/m_xt_zenith.c b/src/machine/m_xt_zenith.c index 19f2bc748..0da091917 100644 --- a/src/machine/m_xt_zenith.c +++ b/src/machine/m_xt_zenith.c @@ -1,24 +1,24 @@ /* - * 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. + * 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. + * This file is part of the 86Box distribution. * - * Emulation of various Zenith PC compatible machines. - * Currently only the Zenith Data Systems Supersport is emulated. + * Emulation of various Zenith PC compatible machines. + * Currently only the Zenith Data Systems Supersport is emulated. * * * - * Authors: Sarah Walker, - * Miran Grca, - * TheCollector1995, - * EngiNerd + * Authors: Tux, + * Miran Grca, + * TheCollector1995, + * EngiNerd * - * Copyright 2008-2019 Sarah Walker. - * Copyright 2016-2019 Miran Grca. - * Copyright 2020 EngiNerd. + * Copyright 2016-2019 Tux. + * Copyright 2016-2019 Miran Grca. + * Copyright 2020 EngiNerd. */ #include #include @@ -46,92 +46,81 @@ #include <86box/machine.h> #include <86box/io.h> #include <86box/vid_cga.h> - +#include <86box/plat_unused.h> typedef struct { mem_mapping_t scratchpad_mapping; - uint8_t *scratchpad_ram; + uint8_t *scratchpad_ram; } zenith_t; - static uint8_t -zenith_scratchpad_read(uint32_t addr, void *p) +zenith_scratchpad_read(uint32_t addr, void *priv) { - zenith_t *dev = (zenith_t *)p; + const zenith_t *dev = (zenith_t *) priv; + return dev->scratchpad_ram[addr & 0x3fff]; } - static void -zenith_scratchpad_write(uint32_t addr, uint8_t val, void *p) +zenith_scratchpad_write(uint32_t addr, uint8_t val, void *priv) { - zenith_t *dev = (zenith_t *)p; + zenith_t *dev = (zenith_t *) priv; dev->scratchpad_ram[addr & 0x3fff] = val; } - static void * -zenith_scratchpad_init(const device_t *info) +zenith_scratchpad_init(UNUSED(const device_t *info)) { zenith_t *dev; - dev = (zenith_t *)malloc(sizeof(zenith_t)); - memset(dev, 0x00, sizeof(zenith_t)); - + dev = (zenith_t *) malloc(sizeof(zenith_t)); + memset(dev, 0x00, sizeof(zenith_t)); + dev->scratchpad_ram = malloc(0x4000); - + mem_mapping_add(&dev->scratchpad_mapping, 0xf0000, 0x4000, - zenith_scratchpad_read, NULL, NULL, - zenith_scratchpad_write, NULL, NULL, - dev->scratchpad_ram, MEM_MAPPING_EXTERNAL, dev); - + zenith_scratchpad_read, NULL, NULL, + zenith_scratchpad_write, NULL, NULL, + dev->scratchpad_ram, MEM_MAPPING_EXTERNAL, dev); + return dev; } - -static void -zenith_scratchpad_close(void *p) +static void +zenith_scratchpad_close(void *priv) { - zenith_t *dev = (zenith_t *)p; + zenith_t *dev = (zenith_t *) priv; free(dev->scratchpad_ram); free(dev); } - static const device_t zenith_scratchpad_device = { - "Zenith scratchpad RAM", - "zenith_scratchpad", - 0, 0, - zenith_scratchpad_init, zenith_scratchpad_close, NULL, - { NULL }, - NULL, - NULL + .name = "Zenith scratchpad RAM", + .internal_name = "zenith_scratchpad", + .flags = 0, + .local = 0, + .init = zenith_scratchpad_init, + .close = zenith_scratchpad_close, + .reset = NULL, + { .available = NULL }, + .speed_changed = NULL, + .force_redraw = NULL, + .config = NULL }; - void -machine_zenith_init(const machine_t *model){ - +machine_zenith_init(const machine_t *model) +{ machine_common_init(model); - - if (fdc_type == FDC_INTERNAL) - device_add(&fdc_xt_device); device_add(&zenith_scratchpad_device); - - pit_ctr_set_out_func(&pit->counters[1], pit_refresh_timer_xt); - + + pit_devs[0].set_out_func(pit_devs[0].data, 1, pit_refresh_timer_xt); + device_add(&keyboard_xt_zenith_device); nmi_init(); - -} - -const device_t * -z184_get_device(void) -{ - return &cga_device; } /* @@ -140,25 +129,28 @@ z184_get_device(void) */ int machine_xt_z184_init(const machine_t *model) -{ +{ int ret; ret = bios_load_linear("roms/machines/zdsupers/z184m v3.1d.10d", - 0x000f8000, 32768, 0); + 0x000f8000, 32768, 0); if (bios_only || !ret) - return ret; + return ret; machine_zenith_init(model); - - lpt1_remove(); /* only one parallel port */ + + if (fdc_type == FDC_INTERNAL) + device_add(&fdc_xt_device); + + lpt1_remove(); /* only one parallel port */ lpt2_remove(); lpt1_init(0x278); device_add(&ns8250_device); - serial_set_next_inst(SERIAL_MAX); /* So that serial_standalone_init() won't do anything. */ - + serial_set_next_inst(SERIAL_MAX); /* So that serial_standalone_init() won't do anything. */ + device_add(&cga_device); - + return ret; } @@ -167,17 +159,20 @@ machine_xt_z151_init(const machine_t *model) { int ret; ret = bios_load_linear("roms/machines/zdsz151/444-229-18.bin", - 0x000fc000, 32768, 0); + 0x000fc000, 32768, 0); if (ret) { bios_load_aux_linear("roms/machines/zdsz151/444-260-18.bin", - 0x000f8000, 16384, 0); + 0x000f8000, 16384, 0); } if (bios_only || !ret) - return ret; + return ret; machine_zenith_init(model); - + + if (fdc_type == FDC_INTERNAL) + device_add(&fdc_xt_tandy_device); + return ret; } @@ -191,17 +186,20 @@ machine_xt_z159_init(const machine_t *model) int ret; ret = bios_load_linear("roms/machines/zdsz159/z159m v2.9e.10d", - 0x000f8000, 32768, 0); + 0x000f8000, 32768, 0); if (bios_only || !ret) - return ret; + return ret; machine_zenith_init(model); - + + if (fdc_type == FDC_INTERNAL) + device_add(&fdc_xt_tandy_device); + /* parallel port is on the memory board */ - lpt1_remove(); /* only one parallel port */ + lpt1_remove(); /* only one parallel port */ lpt2_remove(); lpt1_init(0x278); return ret; -} \ No newline at end of file +} diff --git a/src/machine/machine.c b/src/machine/machine.c index 5813c1d1a..c4ace6b4f 100644 --- a/src/machine/machine.c +++ b/src/machine/machine.c @@ -1,22 +1,20 @@ /* - * 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. + * 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. + * This file is part of the 86Box distribution. * - * Handling of the emulated machines. + * Handling of the emulated machines. * * * - * Authors: Sarah Walker, - * Miran Grca, - * Fred N. van Kempen, + * Authors: Miran Grca, + * Fred N. van Kempen, * - * Copyright 2008-2020 Sarah Walker. - * Copyright 2016-2020 Miran Grca. - * Copyright 2017-2020 Fred N. van Kempen. + * Copyright 2016-2020 Miran Grca. + * Copyright 2017-2020 Fred N. van Kempen. */ #include #include @@ -41,87 +39,96 @@ #include <86box/video.h> #include <86box/machine.h> #include <86box/isamem.h> - +#include <86box/pci.h> +#include <86box/plat_unused.h> int bios_only = 0; int machine; // int AT, PCI; - #ifdef ENABLE_MACHINE_LOG int machine_do_log = ENABLE_MACHINE_LOG; - static void machine_log(const char *fmt, ...) { - va_list ap; + va_list ap; - if (machine_do_log) - { - va_start(ap, fmt); - pclog_ex(fmt, ap); - va_end(ap); - } + if (machine_do_log) { + va_start(ap, fmt); + pclog_ex(fmt, ap); + va_end(ap); + } } #else -#define machine_log(fmt, ...) +# define machine_log(fmt, ...) #endif - static int machine_init_ex(int m) { int ret = 0; if (!bios_only) { - machine_log("Initializing as \"%s\"\n", machine_getname()); + machine_log("Initializing as \"%s\"\n", machine_getname()); - is_vpc = 0; - standalone_gameport_type = NULL; - gameport_instance_id = 0; + machine_init_p1(); - /* Set up the architecture flags. */ - // AT = IS_AT(machine); - // PCI = IS_ARCH(machine, MACHINE_BUS_PCI); + machine_init_gpio(); + machine_init_gpio_acpi(); - cpu_set(); - pc_speed_changed(); + machine_snd = NULL; - /* Reset the memory state. */ - mem_reset(); - smbase = is_am486dxl ? 0x00060000 : 0x00030000; + is_vpc = 0; - lpt_init(); + standalone_gameport_type = NULL; + gameport_instance_id = 0; - if (cassette_enable) - device_add(&cassette_device); + /* Set up the architecture flags. */ +#if 0 + AT = IS_AT(machine); + PCI = IS_ARCH(machine, MACHINE_BUS_PCI); +#endif - cart_reset(); + cpu_set(); + pc_speed_changed(); - /* Prepare some video-related things if we're using internal - or no video. */ - video_pre_reset(gfxcard); + /* Reset the memory state. */ + mem_reset(); + smbase = is_am486dxl ? 0x00060000 : 0x00030000; - /* Reset any ISA memory cards. */ - isamem_reset(); + lpt_init(); + + if (cassette_enable) + device_add(&cassette_device); + + cart_reset(); + + /* Prepare some video-related things if we're using internal + or no video. */ + video_pre_reset(gfxcard[0]); + + /* Reset any ISA memory cards. */ + isamem_reset(); + + /* Reset the fast off stuff. */ + cpu_fast_off_reset(); + + pci_flags = 0x00000000; } /* All good, boot the machine! */ if (machines[m].init) - ret = machines[m].init(&machines[m]); + ret = machines[m].init(&machines[m]); if (bios_only || !ret) - return ret; + return ret; - /* Reset the graphics card (or do nothing if it was already done - by the machine's init function). */ - video_reset(gfxcard); + video_post_reset(); return ret; } - void machine_init(void) { @@ -129,26 +136,48 @@ machine_init(void) (void) machine_init_ex(machine); } - int machine_available(int m) { - int ret; + int ret; + const device_t *dev = machine_get_device(m); bios_only = 1; - ret = machine_init_ex(m); + + ret = device_available(dev); + /* Do not check via machine_init_ex() if the device is not NULL and + it has a CONFIG_BIOS field. */ + if ((dev == NULL) || (ret != -1)) + ret = machine_init_ex(m); bios_only = 0; - return ret; + + return !!ret; } +void +pit_irq0_timer(int new_out, int old_out) +{ + if (new_out && !old_out) + picint(1); + + if (!new_out) + picintc(1); +} void -machine_common_init(const machine_t *model) +machine_common_init(UNUSED(const machine_t *model)) { + uint8_t cpu_requires_fast_pit = is486 || (is8086 && (cpu_s->rspeed >= 8000000)); + /* System devices first. */ pic_init(); dma_init(); - pit_common_init(!!IS_AT(machine), pit_irq0_timer, NULL); + int pit_type = IS_AT(machine) ? PIT_8254 : PIT_8253; + /* Select fast PIT if needed */ + if (((pit_mode == -1) && cpu_requires_fast_pit) || (pit_mode == 1)) + pit_type += 2; + + pit_common_init(pit_type, pit_irq0_timer, NULL); } diff --git a/src/machine/machine_table.c b/src/machine/machine_table.c index b8322fff9..3a9bfa72a 100644 --- a/src/machine/machine_table.c +++ b/src/machine/machine_table.c @@ -1,25 +1,23 @@ /* - * 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. + * 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. + * This file is part of the 86Box distribution. * - * Handling of the emulated machines. + * Handling of the emulated machines. * - * NOTES: OpenAT wip for 286-class machine with open BIOS. - * PS2_M80-486 wip, pending receipt of TRM's for machine. + * NOTES: OpenAT wip for 286-class machine with open BIOS. + * PS2_M80-486 wip, pending receipt of TRM's for machine. * * * - * Authors: Sarah Walker, - * Miran Grca, - * Fred N. van Kempen, + * Authors: Miran Grca, + * Fred N. van Kempen, * - * Copyright 2008-2020 Sarah Walker. - * Copyright 2016-2020 Miran Grca. - * Copyright 2017-2020 Fred N. van Kempen. + * Copyright 2016-2020 Miran Grca. + * Copyright 2017-2020 Fred N. van Kempen. */ #include #include @@ -31,298 +29,5203 @@ #include <86box/rom.h> #include <86box/device.h> #include <86box/machine.h> +#include <86box/keyboard.h> +#include <86box/sound.h> +#include <86box/video.h> +#include <86box/plat_unused.h> +// Temporarily here till we move everything out into the right files +extern const device_t pcjr_device; +extern const device_t m19_vid_device; +extern const device_t vid_device; +extern const device_t vid_device_hx; +extern const device_t t1000_video_device; +extern const device_t xi8088_device; +extern const device_t cga_device; +extern const device_t vid_1512_device; +extern const device_t vid_1640_device; +extern const device_t vid_pc2086_device; +extern const device_t vid_pc3086_device; +extern const device_t vid_200_device; +extern const device_t vid_ppc512_device; +extern const device_t vid_device_sl; +extern const device_t t1200_video_device; +extern const device_t compaq_plasma_device; -const machine_type_t machine_types[] = { - { "None", MACHINE_TYPE_NONE }, - { "8088", MACHINE_TYPE_8088 }, - { "8086", MACHINE_TYPE_8086 }, - { "80286", MACHINE_TYPE_286 }, - { "i386SX", MACHINE_TYPE_386SX }, - { "486SLC", MACHINE_TYPE_486SLC }, - { "i386DX", MACHINE_TYPE_386DX }, - { "i386DX/i486", MACHINE_TYPE_386DX_486 }, - { "i486 (Socket 168 and 1)", MACHINE_TYPE_486 }, - { "i486 (Socket 2)", MACHINE_TYPE_486_S2 }, - { "i486 (Socket 3)", MACHINE_TYPE_486_S3 }, - { "i486 (Miscellaneous)", MACHINE_TYPE_486_MISC }, - { "Socket 4", MACHINE_TYPE_SOCKET4 }, - { "Socket 5", MACHINE_TYPE_SOCKET5 }, - { "Socket 7 (Single Voltage)", MACHINE_TYPE_SOCKET7_3V }, - { "Socket 7 (Dual Voltage)", MACHINE_TYPE_SOCKET7 }, - { "Super Socket 7", MACHINE_TYPE_SOCKETS7 }, - { "Socket 8", MACHINE_TYPE_SOCKET8 }, - { "Slot 1", MACHINE_TYPE_SLOT1 }, - { "Slot 1/2", MACHINE_TYPE_SLOT1_2 }, - { "Slot 1/Socket 370", MACHINE_TYPE_SLOT1_370 }, - { "Slot 2", MACHINE_TYPE_SLOT2 }, - { "Socket 370", MACHINE_TYPE_SOCKET370 }, - { "Miscellaneous", MACHINE_TYPE_MISC } +const machine_filter_t machine_types[] = { + { "None", MACHINE_TYPE_NONE }, + { "8088", MACHINE_TYPE_8088 }, + { "8086", MACHINE_TYPE_8086 }, + { "80286", MACHINE_TYPE_286 }, + { "i386SX", MACHINE_TYPE_386SX }, + { "486SLC", MACHINE_TYPE_486SLC }, + { "i386DX", MACHINE_TYPE_386DX }, + { "i386DX/i486", MACHINE_TYPE_386DX_486 }, + { "i486 (Socket 168 and 1)", MACHINE_TYPE_486 }, + { "i486 (Socket 2)", MACHINE_TYPE_486_S2 }, + { "i486 (Socket 3)", MACHINE_TYPE_486_S3 }, + { "i486 (Miscellaneous)", MACHINE_TYPE_486_MISC }, + { "Socket 4", MACHINE_TYPE_SOCKET4 }, + { "Socket 5", MACHINE_TYPE_SOCKET5 }, + { "Socket 7 (Single Voltage)", MACHINE_TYPE_SOCKET7_3V }, + { "Socket 7 (Dual Voltage)", MACHINE_TYPE_SOCKET7 }, + { "Super Socket 7", MACHINE_TYPE_SOCKETS7 }, + { "Socket 8", MACHINE_TYPE_SOCKET8 }, + { "Slot 1", MACHINE_TYPE_SLOT1 }, + { "Slot 1/2", MACHINE_TYPE_SLOT1_2 }, + { "Slot 1/Socket 370", MACHINE_TYPE_SLOT1_370 }, + { "Slot 2", MACHINE_TYPE_SLOT2 }, + { "Socket 370", MACHINE_TYPE_SOCKET370 }, + { "Miscellaneous", MACHINE_TYPE_MISC } }; +const machine_filter_t machine_chipsets[] = { + { "None", MACHINE_CHIPSET_NONE }, + { "Discrete", MACHINE_CHIPSET_DISCRETE }, + { "Proprietary", MACHINE_CHIPSET_PROPRIETARY }, + { "Headland GC100A", MACHINE_CHIPSET_GC100A }, + { "Headland GC103", MACHINE_CHIPSET_GC103 }, + { "Headland HT18", MACHINE_CHIPSET_HT18 }, + { "ACC 2168", MACHINE_CHIPSET_ACC_2168 }, + { "ALi M1217", MACHINE_CHIPSET_ALI_M1217 }, + { "ALi M6117", MACHINE_CHIPSET_ALI_M6117 }, + { "ALi M1409", MACHINE_CHIPSET_ALI_M1409 }, + { "ALi M1429", MACHINE_CHIPSET_ALI_M1429 }, + { "ALi M1429G", MACHINE_CHIPSET_ALI_M1429G }, + { "ALi M1489", MACHINE_CHIPSET_ALI_M1489 }, + { "ALi ALADDiN IV+", MACHINE_CHIPSET_ALI_ALADDIN_IV_PLUS }, + { "ALi ALADDiN V", MACHINE_CHIPSET_ALI_ALADDIN_V }, + { "ALi ALADDiN-PRO II", MACHINE_CHIPSET_ALI_ALADDIN_PRO_II }, + { "C&T 82C235 SCAT", MACHINE_CHIPSET_SCAT }, + { "C&T CS8121 NEAT", MACHINE_CHIPSET_NEAT }, + { "C&T 386", MACHINE_CHIPSET_CT_386 }, + { "C&T CS4031", MACHINE_CHIPSET_CT_CS4031 }, + { "Contaq 82C596", MACHINE_CHIPSET_CONTAQ_82C596 }, + { "Contaq 82C597", MACHINE_CHIPSET_CONTAQ_82C597 }, + { "IMS 8848", MACHINE_CHIPSET_IMS_8848 }, + { "Intel 82335", MACHINE_CHIPSET_INTEL_82335 }, + { "Intel 420TX", MACHINE_CHIPSET_INTEL_420TX }, + { "Intel 420ZX", MACHINE_CHIPSET_INTEL_420ZX }, + { "Intel 420EX", MACHINE_CHIPSET_INTEL_420EX }, + { "Intel 430LX", MACHINE_CHIPSET_INTEL_430LX }, + { "Intel 430NX", MACHINE_CHIPSET_INTEL_430NX }, + { "Intel 430FX", MACHINE_CHIPSET_INTEL_430FX }, + { "Intel 430HX", MACHINE_CHIPSET_INTEL_430HX }, + { "Intel 430VX", MACHINE_CHIPSET_INTEL_430VX }, + { "Intel 430TX", MACHINE_CHIPSET_INTEL_430TX }, + { "Intel 450KX", MACHINE_CHIPSET_INTEL_450KX }, + { "Intel 440FX", MACHINE_CHIPSET_INTEL_440FX }, + { "Intel 440LX", MACHINE_CHIPSET_INTEL_440LX }, + { "Intel 440EX", MACHINE_CHIPSET_INTEL_440EX }, + { "Intel 440BX", MACHINE_CHIPSET_INTEL_440BX }, + { "Intel 440ZX", MACHINE_CHIPSET_INTEL_440ZX }, + { "Intel 440GX", MACHINE_CHIPSET_INTEL_440GX }, + { "OPTi 283", MACHINE_CHIPSET_OPTI_283 }, + { "OPTi 291", MACHINE_CHIPSET_OPTI_291 }, + { "OPTi 493", MACHINE_CHIPSET_OPTI_493 }, + { "OPTi 495", MACHINE_CHIPSET_OPTI_495 }, + { "OPTi 499", MACHINE_CHIPSET_OPTI_499 }, + { "OPTi 895/802G", MACHINE_CHIPSET_OPTI_895_802G }, + { "OPTi 547/597", MACHINE_CHIPSET_OPTI_547_597 }, + { "SARC RC2016A", MACHINE_CHIPSET_SARC_RC2016A }, + { "SiS 310", MACHINE_CHIPSET_SIS_310 }, + { "SiS 401", MACHINE_CHIPSET_SIS_401 }, + { "SiS 460", MACHINE_CHIPSET_SIS_460 }, + { "SiS 461", MACHINE_CHIPSET_SIS_461 }, + { "SiS 471", MACHINE_CHIPSET_SIS_471 }, + { "SiS 496", MACHINE_CHIPSET_SIS_496 }, + { "SiS 501", MACHINE_CHIPSET_SIS_501 }, + { "SiS 5511", MACHINE_CHIPSET_SIS_5511 }, + { "SiS 5571", MACHINE_CHIPSET_SIS_5571 }, + { "SMSC VictoryBX-66", MACHINE_CHIPSET_SMSC_VICTORYBX_66 }, + { "STPC Client", MACHINE_CHIPSET_STPC_CLIENT }, + { "STPC Consumer-II", MACHINE_CHIPSET_STPC_CONSUMER_II }, + { "STPC Elite", MACHINE_CHIPSET_STPC_ELITE }, + { "STPC Atlas", MACHINE_CHIPSET_STPC_ATLAS }, + { "Symphony SL82C460 Haydn II", MACHINE_CHIPSET_SYMPHONY_SL82C460 }, + { "UMC UM82C480", MACHINE_CHIPSET_UMC_UM82C480 }, + { "UMC UM82C491", MACHINE_CHIPSET_UMC_UM82C491 }, + { "UMC UM8881", MACHINE_CHIPSET_UMC_UM8881 }, + { "UMC UM8890BF", MACHINE_CHIPSET_UMC_UM8890BF }, + { "VIA VT82C495", MACHINE_CHIPSET_VIA_VT82C495 }, + { "VIA VT82C496G", MACHINE_CHIPSET_VIA_VT82C496G }, + { "VIA Apollo VPX", MACHINE_CHIPSET_VIA_APOLLO_VPX }, + { "VIA Apollo VP3", MACHINE_CHIPSET_VIA_APOLLO_VP3 }, + { "VIA Apollo MVP3", MACHINE_CHIPSET_VIA_APOLLO_MVP3 }, + { "VIA Apollo Pro", MACHINE_CHIPSET_VIA_APOLLO_PRO }, + { "VIA Apollo Pro 133", MACHINE_CHIPSET_VIA_APOLLO_PRO_133 }, + { "VIA Apollo Pro 133A", MACHINE_CHIPSET_VIA_APOLLO_PRO_133A }, + { "VLSI SCAMP", MACHINE_CHIPSET_VLSI_SCAMP }, + { "VLSI VL82C480", MACHINE_CHIPSET_VLSI_VL82C480 }, + { "VLSI VL82C481", MACHINE_CHIPSET_VLSI_VL82C481 }, + { "VLSI VL82C486", MACHINE_CHIPSET_VLSI_VL82C486 }, + { "WD76C10", MACHINE_CHIPSET_WD76C10 } +}; /* Machines to add before machine freeze: - PCChips M773 (440BX + SMSC with AMI BIOS); - - Rise R418 (was removed on my end, has to be re-added); - TMC Mycomp PCI54ST; - Zeos Quadtel 486. NOTE: The AMI MegaKey tests were done on a real Intel Advanced/ATX - (thanks, MrKsoft for running my AMIKEY.COM on it), but the - technical specifications of the other Intel machines confirm - that the other boards also have the MegaKey. + (thanks, MrKsoft for running my AMIKEY.COM on it), but the + technical specifications of the other Intel machines confirm + that the other boards also have the MegaKey. NOTE: The later (ie. not AMI Color) Intel AMI BIOS'es execute a - sequence of commands (B8, BA, BB) during one of the very first - phases of POST, in a way that is only valid on the AMIKey-3 - KBC firmware, that includes the Classic PCI/ED (Ninja) BIOS - which otherwise does not execute any AMI KBC commands, which - indicates that the sequence is a leftover of whatever AMI - BIOS (likely a laptop one since the AMIKey-3 is a laptop KBC - firmware!) Intel forked. + sequence of commands (B8, BA, BB) during one of the very first + phases of POST, in a way that is only valid on the AMIKey-3 + KBC firmware, that includes the Classic PCI/ED (Ninja) BIOS + which otherwise does not execute any AMI KBC commands, which + indicates that the sequence is a leftover of whatever AMI + BIOS (likely a laptop one since the AMIKey-3 is a laptop KBC + firmware!) Intel forked. NOTE: The VIA VT82C42N returns 0x46 ('F') in command 0xA1 (so it - emulates the AMI KF/AMIKey KBC firmware), and 0x42 ('B') in - command 0xAF. - The version on the VIA VT82C686B southbridge also returns - 'F' in command 0xA1, but 0x45 ('E') in command 0xAF. - The version on the VIA VT82C586B southbridge also returns - 'F' in command 0xA1, but 0x44 ('D') in command 0xAF. - The version on the VIA VT82C586A southbridge also returns - 'F' in command 0xA1, but 0x43 ('C') in command 0xAF. + emulates the AMI KF/AMIKey KBC firmware), and 0x42 ('B') in + command 0xAF. + The version on the VIA VT82C686B southbridge also returns + 'F' in command 0xA1, but 0x45 ('E') in command 0xAF. + The version on the VIA VT82C586B southbridge also returns + 'F' in command 0xA1, but 0x44 ('D') in command 0xAF. + The version on the VIA VT82C586A southbridge also returns + 'F' in command 0xA1, but 0x43 ('C') in command 0xAF. NOTE: The AMI MegaKey commands blanked in the technical reference - are CC and and C4, which are Set P14 High and Set P14 Low, - respectively. Also, AMI KBC command C1, mysteriously missing - from the technical references of AMI MegaKey and earlier, is - Write Input Port, same as on AMIKey-3. - - Machines to remove: - - Hedaka HED-919. + are CC and and C4, which are Set P14 High and Set P14 Low, + respectively. Also, AMI KBC command C1, mysteriously missing + from the technical references of AMI MegaKey and earlier, is + Write Input Port, same as on AMIKey-3. */ - const machine_t machines[] = { + // clang-format off /* 8088 Machines */ - { "[8088] IBM PC (1981)", "ibmpc", MACHINE_TYPE_8088, CPU_PKG_8088, 0, 0, 0, 0, 0, 0, 0, MACHINE_PC, 16, 64, 16, 0, machine_pc_init, NULL }, - { "[8088] IBM PC (1982)", "ibmpc82", MACHINE_TYPE_8088, CPU_PKG_8088, 0, 0, 0, 0, 0, 0, 0, MACHINE_PC, 64, 256, 64, 0, machine_pc82_init, NULL }, - { "[8088] IBM PCjr", "ibmpcjr", MACHINE_TYPE_8088, CPU_PKG_8088, 0, 4772728, 4772728, 0, 0, 0, 0, MACHINE_PC | MACHINE_VIDEO_FIXED | MACHINE_CARTRIDGE, 128, 640, 128, 0, machine_pcjr_init, pcjr_get_device }, - { "[8088] IBM XT (1982)", "ibmxt", MACHINE_TYPE_8088, CPU_PKG_8088, 0, 0, 0, 0, 0, 0, 0, MACHINE_PC, 64, 256, 64, 0, machine_xt_init, NULL }, - { "[8088] IBM XT (1986)", "ibmxt86", MACHINE_TYPE_8088, CPU_PKG_8088, 0, 0, 0, 0, 0, 0, 0, MACHINE_PC, 256, 640, 64, 0, machine_xt86_init, NULL }, - { "[8088] American XT Computer", "americxt", MACHINE_TYPE_8088, CPU_PKG_8088, 0, 0, 0, 0, 0, 0, 0, MACHINE_PC, 64, 640, 64, 0, machine_xt_americxt_init, NULL }, - { "[8088] AMI XT clone", "amixt", MACHINE_TYPE_8088, CPU_PKG_8088, 0, 0, 0, 0, 0, 0, 0, MACHINE_PC, 64, 640, 64, 0, machine_xt_amixt_init, NULL }, - { "[8088] Columbia Data Products MPC-1600", "mpc1600", MACHINE_TYPE_8088, CPU_PKG_8088, 0, 0, 0, 0, 0, 0, 0, MACHINE_PC, 128, 512, 64, 0, machine_xt_mpc1600_init, NULL }, - { "[8088] Compaq Portable", "portable", MACHINE_TYPE_8088, CPU_PKG_8088, 0, 0, 0, 0, 0, 0, 0, MACHINE_PC, 128, 640, 128, 0, machine_xt_compaq_portable_init, NULL }, - { "[8088] DTK PIM-TB10-Z", "dtk", MACHINE_TYPE_8088, CPU_PKG_8088, 0, 0, 0, 0, 0, 0, 0, MACHINE_PC, 64, 640, 64, 0, machine_xt_dtk_init, NULL }, - { "[8088] Eagle PC Spirit", "pcspirit", MACHINE_TYPE_8088, CPU_PKG_8088, 0, 0, 0, 0, 0, 0, 0, MACHINE_PC, 128, 640, 64, 0, machine_xt_pcspirit_init, NULL }, - { "[8088] Generic XT clone", "genxt", MACHINE_TYPE_8088, CPU_PKG_8088, 0, 0, 0, 0, 0, 0, 0, MACHINE_PC, 64, 640, 64, 0, machine_genxt_init, NULL }, - { "[8088] Juko ST", "jukopc", MACHINE_TYPE_8088, CPU_PKG_8088, 0, 0, 0, 0, 0, 0, 0, MACHINE_PC, 64, 640, 64, 0, machine_xt_jukopc_init, NULL }, - { "[8088] Multitech PC-500", "pc500", MACHINE_TYPE_8088, CPU_PKG_8088, 0, 0, 0, 0, 0, 0, 0, MACHINE_PC, 128, 640, 64, 0, machine_xt_pc500_init, NULL }, - { "[8088] Multitech PC-700", "pc700", MACHINE_TYPE_8088, CPU_PKG_8088, 0, 0, 0, 0, 0, 0, 0, MACHINE_PC, 128, 640, 64, 0, machine_xt_pc700_init, NULL }, - { "[8088] NCR PC4i", "pc4i", MACHINE_TYPE_8088, CPU_PKG_8088, 0, 0, 0, 0, 0, 0, 0, MACHINE_PC, 256, 640, 256, 0, machine_xt_pc4i_init, NULL }, - { "[8088] Olivetti M19", "m19", MACHINE_TYPE_8088, CPU_PKG_8088, 0, 4772728, 7159092, 0, 0, 0, 0, MACHINE_PC | MACHINE_VIDEO_FIXED, 256, 640, 256, 0, machine_xt_m19_init, m19_get_device }, - { "[8088] OpenXT", "openxt", MACHINE_TYPE_8088, CPU_PKG_8088, 0, 0, 0, 0, 0, 0, 0, MACHINE_PC, 64, 640, 64, 0, machine_xt_openxt_init, NULL }, - { "[8088] Philips P3105/NMS9100", "p3105", MACHINE_TYPE_8088, CPU_PKG_8088, 0, 0, 0, 0, 0, 0, 0, MACHINE_PC | MACHINE_XTA, 256, 768, 256, 0, machine_xt_p3105_init, NULL }, - { "[8088] Phoenix XT clone", "pxxt", MACHINE_TYPE_8088, CPU_PKG_8088, 0, 0, 0, 0, 0, 0, 0, MACHINE_PC, 64, 640, 64, 0, machine_xt_pxxt_init, NULL }, - { "[8088] Schneider EuroPC", "europc", MACHINE_TYPE_8088, CPU_PKG_8088_EUROPC, 0, 0, 0, 0, 0, 0, 0, MACHINE_PC | MACHINE_XTA | MACHINE_MOUSE, 512, 640, 128, 15, machine_europc_init, NULL }, - { "[8088] Super PC/Turbo XT", "pcxt", MACHINE_TYPE_8088, CPU_PKG_8088, 0, 0, 0, 0, 0, 0, 0, MACHINE_PC, 64, 640, 64, 0, machine_xt_pcxt_init, NULL }, - { "[8088] Tandy 1000", "tandy", MACHINE_TYPE_8088, CPU_PKG_8088_EUROPC, 0, 0, 0, 0, 0, 0, 0, MACHINE_PC | MACHINE_VIDEO_FIXED, 128, 640, 128, 0, machine_tandy_init, tandy1k_get_device }, - { "[8088] Tandy 1000 HX", "tandy1000hx", MACHINE_TYPE_8088, CPU_PKG_8088_EUROPC, 0, 0, 0, 0, 0, 0, 0, MACHINE_PC | MACHINE_VIDEO_FIXED, 256, 640, 128, 0, machine_tandy1000hx_init, tandy1k_hx_get_device }, - { "[8088] Toshiba T1000", "t1000", MACHINE_TYPE_8088, CPU_PKG_8088, 0, 0, 0, 0, 0, 0, 0, MACHINE_PC | MACHINE_VIDEO, 512, 1280, 768, 63, machine_xt_t1000_init, t1000_get_device }, + { + .name = "[8088] IBM PC (1981)", + .internal_name = "ibmpc", + .type = MACHINE_TYPE_8088, + .chipset = MACHINE_CHIPSET_DISCRETE, + .init = machine_pc_init, + .p1_handler = NULL, + .gpio_handler = NULL, + .available_flag = MACHINE_AVAILABLE, + .gpio_acpi_handler = NULL, + .cpu = { + .package = CPU_PKG_8088, + .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_PC5150, + .flags = MACHINE_FLAGS_NONE, + .ram = { + .min = 16, + .max = 64, + .step = 16 + }, + .nvrmask = 0, + .kbc_device = &keyboard_pc_device, + .kbc_p1 = 0xff, + .gpio = 0xffffffff, + .gpio_acpi = 0xffffffff, + .device = NULL, + .fdc_device = NULL, + .sio_device = NULL, + .vid_device = NULL, + .snd_device = NULL, + .net_device = NULL + }, + { + .name = "[8088] IBM PC (1982)", + .internal_name = "ibmpc82", + .type = MACHINE_TYPE_8088, + .chipset = MACHINE_CHIPSET_DISCRETE, + .init = machine_pc82_init, + .p1_handler = NULL, + .gpio_handler = NULL, + .available_flag = MACHINE_AVAILABLE, + .gpio_acpi_handler = NULL, + .cpu = { + .package = CPU_PKG_8088, + .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_PC5150, + .flags = MACHINE_FLAGS_NONE, + .ram = { + .min = 64, + .max = 256, + .step = 64 + }, + .nvrmask = 0, + .kbc_device = &keyboard_pc82_device, + .kbc_p1 = 0xff, + .gpio = 0xffffffff, + .gpio_acpi = 0xffffffff, + .device = NULL, + .fdc_device = NULL, + .sio_device = NULL, + .vid_device = NULL, + .snd_device = NULL, + .net_device = NULL + }, + { + .name = "[8088] IBM PCjr", + .internal_name = "ibmpcjr", + .type = MACHINE_TYPE_8088, + .chipset = MACHINE_CHIPSET_DISCRETE, + .init = machine_pcjr_init, + .p1_handler = NULL, + .gpio_handler = NULL, + .available_flag = MACHINE_AVAILABLE, + .gpio_acpi_handler = NULL, + .cpu = { + .package = CPU_PKG_8088, + .block = CPU_BLOCK_NONE, + .min_bus = 4772728, + .max_bus = 4772728, + .min_voltage = 0, + .max_voltage = 0, + .min_multi = 0, + .max_multi = 0 + }, + .bus_flags = MACHINE_PCJR, + .flags = MACHINE_VIDEO_FIXED, + .ram = { + .min = 64, + .max = 640, + .step = 64 + }, + .nvrmask = 0, + .kbc_device = NULL, /* TODO: No specific kbd_device yet */ + .kbc_p1 = 0xff, + .gpio = 0xffffffff, + .gpio_acpi = 0xffffffff, + .device = NULL, + .fdc_device = NULL, + .sio_device = NULL, + .vid_device = &pcjr_device, + .snd_device = NULL, + .net_device = NULL + }, + { + .name = "[8088] IBM XT (1982)", + .internal_name = "ibmxt", + .type = MACHINE_TYPE_8088, + .chipset = MACHINE_CHIPSET_DISCRETE, + .init = machine_xt_init, + .p1_handler = NULL, + .gpio_handler = NULL, + .available_flag = MACHINE_AVAILABLE, + .gpio_acpi_handler = NULL, + .cpu = { + .package = CPU_PKG_8088, + .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_PC, + .flags = MACHINE_FLAGS_NONE, + .ram = { + .min = 64, + .max = 256, + .step = 64 + }, + .nvrmask = 0, + .kbc_device = &keyboard_xt_device, + .kbc_p1 = 0xff, + .gpio = 0xffffffff, + .gpio_acpi = 0xffffffff, + .device = NULL, + .fdc_device = NULL, + .sio_device = NULL, + .vid_device = NULL, + .snd_device = NULL, + .net_device = NULL + }, + { + .name = "[8088] IBM XT (1986)", + .internal_name = "ibmxt86", + .type = MACHINE_TYPE_8088, + .chipset = MACHINE_CHIPSET_DISCRETE, + .init = machine_xt86_init, + .p1_handler = NULL, + .gpio_handler = NULL, + .available_flag = MACHINE_AVAILABLE, + .gpio_acpi_handler = NULL, + .cpu = { + .package = CPU_PKG_8088, + .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_PC, + .flags = MACHINE_FLAGS_NONE, + .ram = { + .min = 256, + .max = 640, + .step = 64 + }, + .nvrmask = 0, + .kbc_device = &keyboard_xt86_device, + .kbc_p1 = 0xff, + .gpio = 0xffffffff, + .gpio_acpi = 0xffffffff, + .device = NULL, + .fdc_device = NULL, + .sio_device = NULL, + .vid_device = NULL, + .snd_device = NULL, + .net_device = NULL + }, + { + .name = "[8088] American XT Computer", + .internal_name = "americxt", + .type = MACHINE_TYPE_8088, + .chipset = MACHINE_CHIPSET_DISCRETE, + .init = machine_xt_americxt_init, + .p1_handler = NULL, + .gpio_handler = NULL, + .available_flag = MACHINE_AVAILABLE, + .gpio_acpi_handler = NULL, + .cpu = { + .package = CPU_PKG_8088, + .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_PC, + .flags = MACHINE_FLAGS_NONE, + .ram = { + .min = 64, + .max = 640, + .step = 64 + }, + .nvrmask = 0, + .kbc_device = &keyboard_xtclone_device, + .kbc_p1 = 0xff, + .gpio = 0xffffffff, + .gpio_acpi = 0xffffffff, + .device = NULL, + .fdc_device = NULL, + .sio_device = NULL, + .vid_device = NULL, + .snd_device = NULL, + .net_device = NULL + }, + { + .name = "[8088] AMI XT clone", + .internal_name = "amixt", + .type = MACHINE_TYPE_8088, + .chipset = MACHINE_CHIPSET_DISCRETE, + .init = machine_xt_amixt_init, + .p1_handler = NULL, + .gpio_handler = NULL, + .available_flag = MACHINE_AVAILABLE, + .gpio_acpi_handler = NULL, + .cpu = { + .package = CPU_PKG_8088, + .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_PC, + .flags = MACHINE_FLAGS_NONE, + .ram = { + .min = 64, + .max = 640, + .step = 64 + }, + .nvrmask = 0, + .kbc_device = &keyboard_xtclone_device, + .kbc_p1 = 0xff, + .gpio = 0xffffffff, + .gpio_acpi = 0xffffffff, + .device = NULL, + .fdc_device = NULL, + .sio_device = NULL, + .vid_device = NULL, + .snd_device = NULL, + .net_device = NULL + }, + { + .name = "[8088] Bondwell BW230", + .internal_name = "bw230", + .type = MACHINE_TYPE_8088, + .chipset = MACHINE_CHIPSET_DISCRETE, + .init = machine_xt_bw230_init, + .p1_handler = NULL, + .gpio_handler = NULL, + .available_flag = MACHINE_AVAILABLE, + .gpio_acpi_handler = NULL, + .cpu = { + .package = CPU_PKG_8088, + .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_PC, + .flags = MACHINE_FLAGS_NONE, + .ram = { + .min = 64, + .max = 640, + .step = 64 + }, + .nvrmask = 0, + .kbc_device = &keyboard_xtclone_device, + .kbc_p1 = 0xff, + .gpio = 0xffffffff, + .gpio_acpi = 0xffffffff, + .device = NULL, + .fdc_device = NULL, + .sio_device = NULL, + .vid_device = NULL, + .snd_device = NULL, + .net_device = NULL + }, + { + .name = "[8088] Columbia Data Products MPC-1600", + .internal_name = "mpc1600", + .type = MACHINE_TYPE_8088, + .chipset = MACHINE_CHIPSET_DISCRETE, + .init = machine_xt_mpc1600_init, + .p1_handler = NULL, + .gpio_handler = NULL, + .available_flag = MACHINE_AVAILABLE, + .gpio_acpi_handler = NULL, + .cpu = { + .package = CPU_PKG_8088, + .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_PC, + .flags = MACHINE_FLAGS_NONE, + .ram = { + .min = 128, + .max = 512, + .step = 64 + }, + .nvrmask = 0, + .kbc_device = &keyboard_pc82_device, + .kbc_p1 = 0xff, + .gpio = 0xffffffff, + .gpio_acpi = 0xffffffff, + .device = NULL, + .fdc_device = NULL, + .sio_device = NULL, + .vid_device = NULL, + .snd_device = NULL, + .net_device = NULL + }, + { + .name = "[8088] Compaq Portable", + .internal_name = "portable", + .type = MACHINE_TYPE_8088, + .chipset = MACHINE_CHIPSET_DISCRETE, + .init = machine_xt_compaq_portable_init, + .p1_handler = NULL, + .gpio_handler = NULL, + .available_flag = MACHINE_AVAILABLE, + .gpio_acpi_handler = NULL, + .cpu = { + .package = CPU_PKG_8088, + .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_PC, + .flags = MACHINE_FLAGS_NONE, + .ram = { + .min = 128, + .max = 640, + .step = 128 + }, + .nvrmask = 0, + .kbc_device = &keyboard_xt_compaq_device, + .kbc_p1 = 0xff, + .gpio = 0xffffffff, + .gpio_acpi = 0xffffffff, + .device = NULL, + .fdc_device = NULL, + .sio_device = NULL, + .vid_device = NULL, + .snd_device = NULL, + .net_device = NULL + }, + { + .name = "[8088] DTK PIM-TB10-Z", + .internal_name = "dtk", + .type = MACHINE_TYPE_8088, + .chipset = MACHINE_CHIPSET_DISCRETE, + .init = machine_xt_dtk_init, + .p1_handler = NULL, + .gpio_handler = NULL, + .available_flag = MACHINE_AVAILABLE, + .gpio_acpi_handler = NULL, + .cpu = { + .package = CPU_PKG_8088, + .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_PC, + .flags = MACHINE_FLAGS_NONE, + .ram = { + .min = 64, + .max = 640, + .step = 64 + }, + .nvrmask = 0, + .kbc_device = &keyboard_xtclone_device, + .kbc_p1 = 0xff, + .gpio = 0xffffffff, + .gpio_acpi = 0xffffffff, + .device = NULL, + .fdc_device = NULL, + .sio_device = NULL, + .vid_device = NULL, + .snd_device = NULL, + .net_device = NULL + }, + { + .name = "[8088] Eagle PC Spirit", + .internal_name = "pcspirit", + .type = MACHINE_TYPE_8088, + .chipset = MACHINE_CHIPSET_DISCRETE, + .init = machine_xt_pcspirit_init, + .p1_handler = NULL, + .gpio_handler = NULL, + .available_flag = MACHINE_AVAILABLE, + .gpio_acpi_handler = NULL, + .cpu = { + .package = CPU_PKG_8088, + .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_PC, + .flags = MACHINE_FLAGS_NONE, + .ram = { + .min = 128, + .max = 640, + .step = 64 + }, + .nvrmask = 0, + .kbc_device = &keyboard_pc82_device, + .kbc_p1 = 0xff, + .gpio = 0xffffffff, + .gpio_acpi = 0xffffffff, + .device = NULL, + .fdc_device = NULL, + .sio_device = NULL, + .vid_device = NULL, + .snd_device = NULL, + .net_device = NULL + }, + { + .name = "[8088] Generic XT clone", + .internal_name = "genxt", + .type = MACHINE_TYPE_8088, + .chipset = MACHINE_CHIPSET_DISCRETE, + .init = machine_genxt_init, + .p1_handler = NULL, + .gpio_handler = NULL, + .available_flag = MACHINE_AVAILABLE, + .gpio_acpi_handler = NULL, + .cpu = { + .package = CPU_PKG_8088, + .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_PC, + .flags = MACHINE_FLAGS_NONE, + .ram = { + .min = 64, + .max = 640, + .step = 64 + }, + .nvrmask = 0, + .kbc_device = &keyboard_xt_device, + .kbc_p1 = 0xff, + .gpio = 0xffffffff, + .gpio_acpi = 0xffffffff, + .device = NULL, + .fdc_device = NULL, + .sio_device = NULL, + .vid_device = NULL, + .snd_device = NULL, + .net_device = NULL + }, + { + .name = "[8088] Hyosung Topstar 88T", + .internal_name = "top88", + .type = MACHINE_TYPE_8088, + .chipset = MACHINE_CHIPSET_DISCRETE, + .init = machine_xt_top88_init, + .p1_handler = NULL, + .gpio_handler = NULL, + .available_flag = MACHINE_AVAILABLE, + .gpio_acpi_handler = NULL, + .cpu = { + .package = CPU_PKG_8088, + .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_PC, + .flags = MACHINE_FLAGS_NONE, + .ram = { + .min = 128, + .max = 640, + .step = 64 + }, + .nvrmask = 0, + .kbc_device = &keyboard_xtclone_device, + .kbc_p1 = 0xff, + .gpio = 0xffffffff, + .gpio_acpi = 0xffffffff, + .device = NULL, + .fdc_device = NULL, + .sio_device = NULL, + .vid_device = NULL, + .snd_device = NULL, + .net_device = NULL + }, + { + .name = "[8088] Hyundai SUPER-16T", + .internal_name = "super16t", + .type = MACHINE_TYPE_8088, + .chipset = MACHINE_CHIPSET_DISCRETE, + .init = machine_xt_super16t_init, + .p1_handler = NULL, + .gpio_handler = NULL, + .available_flag = MACHINE_AVAILABLE, + .gpio_acpi_handler = NULL, + .cpu = { + .package = CPU_PKG_8088, + .block = CPU_BLOCK_NONE, + .min_bus = 4772728, + .max_bus = 7159092, + .min_voltage = 0, + .max_voltage = 0, + .min_multi = 0, + .max_multi = 0 + }, + .bus_flags = MACHINE_PC, + .flags = MACHINE_FLAGS_NONE, + .ram = { + .min = 128, + .max = 640, + .step = 64 + }, + .nvrmask = 0, + .kbc_device = &keyboard_xtclone_device, + .kbc_p1 = 0xff, + .gpio = 0xffffffff, + .gpio_acpi = 0xffffffff, + .device = NULL, + .fdc_device = NULL, + .sio_device = NULL, + .vid_device = NULL, + .snd_device = NULL, + .net_device = NULL + }, + { + .name = "[8088] Hyundai SUPER-16TE", + .internal_name = "super16te", + .type = MACHINE_TYPE_8088, + .chipset = MACHINE_CHIPSET_DISCRETE, + .init = machine_xt_super16te_init, + .p1_handler = NULL, + .gpio_handler = NULL, + .available_flag = MACHINE_AVAILABLE, + .gpio_acpi_handler = NULL, + .cpu = { + .package = CPU_PKG_8088, + .block = CPU_BLOCK_NONE, + .min_bus = 0, + .max_bus = 10000000, + .min_voltage = 0, + .max_voltage = 0, + .min_multi = 0, + .max_multi = 0 + }, + .bus_flags = MACHINE_PC, + .flags = MACHINE_FLAGS_NONE, + .ram = { + .min = 128, + .max = 640, + .step = 64 + }, + .nvrmask = 0, + .kbc_device = &keyboard_xtclone_device, + .kbc_p1 = 0xff, + .gpio = 0xffffffff, + .gpio_acpi = 0xffffffff, + .device = NULL, + .fdc_device = NULL, + .sio_device = NULL, + .vid_device = NULL, + .snd_device = NULL, + .net_device = NULL + }, + { + .name = "[8088] Juko ST", + .internal_name = "jukopc", + .type = MACHINE_TYPE_8088, + .chipset = MACHINE_CHIPSET_DISCRETE, + .init = machine_xt_jukopc_init, + .p1_handler = NULL, + .gpio_handler = NULL, + .available_flag = MACHINE_AVAILABLE, + .gpio_acpi_handler = NULL, + .cpu = { + .package = CPU_PKG_8088, + .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_PC, + .flags = MACHINE_FLAGS_NONE, + .ram = { + .min = 64, + .max = 640, + .step = 64 + }, + .nvrmask = 0, + .kbc_device = &keyboard_xtclone_device, + .kbc_p1 = 0xff, + .gpio = 0xffffffff, + .gpio_acpi = 0xffffffff, + .device = NULL, + .fdc_device = NULL, + .sio_device = NULL, + .vid_device = NULL, + .snd_device = NULL, + .net_device = NULL + }, + { + .name = "[8088] Kaypro PC", + .internal_name = "kaypropc", + .type = MACHINE_TYPE_8088, + .chipset = MACHINE_CHIPSET_DISCRETE, + .init = machine_xt_kaypropc_init, + .p1_handler = NULL, + .gpio_handler = NULL, + .available_flag = MACHINE_AVAILABLE, + .gpio_acpi_handler = NULL, + .cpu = { + .package = CPU_PKG_8088, + .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_PC, + .flags = MACHINE_FLAGS_NONE, + .ram = { + .min = 128, + .max = 640, + .step = 64 + }, + .nvrmask = 0, + .kbc_device = &keyboard_xtclone_device, + .kbc_p1 = 0xff, + .gpio = 0xffffffff, + .gpio_acpi = 0xffffffff, + .device = NULL, + .fdc_device = NULL, + .sio_device = NULL, + .vid_device = NULL, + .snd_device = NULL, + .net_device = NULL + }, + { + .name = "[8088] Micoms XL-7 Turbo", + .internal_name = "mxl7t", + .type = MACHINE_TYPE_8088, + .chipset = MACHINE_CHIPSET_DISCRETE, + .init = machine_xt_micoms_xl7turbo_init, + .p1_handler = NULL, + .gpio_handler = NULL, + .available_flag = MACHINE_AVAILABLE, + .gpio_acpi_handler = NULL, + .cpu = { + .package = CPU_PKG_8088, + .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_PC, + .flags = MACHINE_FLAGS_NONE, + .ram = { + .min = 64, + .max = 640, + .step = 64 + }, + .nvrmask = 0, + .kbc_device = &keyboard_xt_device, + .kbc_p1 = 0xff, + .gpio = 0xffffffff, + .gpio_acpi = 0xffffffff, + .device = NULL, + .fdc_device = NULL, + .sio_device = NULL, + .vid_device = NULL, + .snd_device = NULL, + .net_device = NULL + }, + { + .name = "[8088] Multitech PC-500", + .internal_name = "pc500", + .type = MACHINE_TYPE_8088, + .chipset = MACHINE_CHIPSET_DISCRETE, + .init = machine_xt_pc500_init, + .p1_handler = NULL, + .gpio_handler = NULL, + .available_flag = MACHINE_AVAILABLE, + .gpio_acpi_handler = NULL, + .cpu = { + .package = CPU_PKG_8088, + .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_PC, + .flags = MACHINE_FLAGS_NONE, + .ram = { + .min = 128, + .max = 640, + .step = 64 + }, + .nvrmask = 0, + .kbc_device = &keyboard_pc_device, + .kbc_p1 = 0xff, + .gpio = 0xffffffff, + .gpio_acpi = 0xffffffff, + .device = NULL, + .fdc_device = NULL, + .sio_device = NULL, + .vid_device = NULL, + .snd_device = NULL, + .net_device = NULL + }, + { + .name = "[8088] Multitech PC-700", + .internal_name = "pc700", + .type = MACHINE_TYPE_8088, + .chipset = MACHINE_CHIPSET_DISCRETE, + .init = machine_xt_pc700_init, + .p1_handler = NULL, + .gpio_handler = NULL, + .available_flag = MACHINE_AVAILABLE, + .gpio_acpi_handler = NULL, + .cpu = { + .package = CPU_PKG_8088, + .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_PC, + .flags = MACHINE_FLAGS_NONE, + .ram = { + .min = 128, + .max = 640, + .step = 64 + }, + .nvrmask = 0, + .kbc_device = &keyboard_pc_device, + .kbc_p1 = 0xff, + .gpio = 0xffffffff, + .gpio_acpi = 0xffffffff, + .device = NULL, + .fdc_device = NULL, + .sio_device = NULL, + .vid_device = NULL, + .snd_device = NULL, + .net_device = NULL + }, + { + .name = "[8088] NCR PC4i", + .internal_name = "pc4i", + .type = MACHINE_TYPE_8088, + .chipset = MACHINE_CHIPSET_DISCRETE, + .init = machine_xt_pc4i_init, + .p1_handler = NULL, + .gpio_handler = NULL, + .available_flag = MACHINE_AVAILABLE, + .gpio_acpi_handler = NULL, + .cpu = { + .package = CPU_PKG_8088, + .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_PC, + .flags = MACHINE_FLAGS_NONE, + .ram = { + .min = 256, + .max = 640, + .step = 128 + }, + .nvrmask = 0, + .kbc_device = &keyboard_xtclone_device, + .kbc_p1 = 0xff, + .gpio = 0xffffffff, + .gpio_acpi = 0xffffffff, + .device = NULL, + .fdc_device = NULL, + .sio_device = NULL, + .vid_device = NULL, + .snd_device = NULL, + .net_device = NULL + }, + { + .name = "[8088] Olivetti M19", + .internal_name = "m19", + .type = MACHINE_TYPE_8088, + .chipset = MACHINE_CHIPSET_PROPRIETARY, + .init = machine_xt_m19_init, + .p1_handler = NULL, + .gpio_handler = NULL, + .available_flag = MACHINE_AVAILABLE, + .gpio_acpi_handler = NULL, + .cpu = { + .package = CPU_PKG_8088, + .block = CPU_BLOCK_NONE, + .min_bus = 4772728, + .max_bus = 7159092, + .min_voltage = 0, + .max_voltage = 0, + .min_multi = 0, + .max_multi = 0 + }, + .bus_flags = MACHINE_PC, + .flags = MACHINE_VIDEO_FIXED, + .ram = { + .min = 256, + .max = 640, + .step = 128 + }, + .nvrmask = 0, + .kbc_device = &keyboard_xt_olivetti_device, + .kbc_p1 = 0xff, + .gpio = 0xffffffff, + .gpio_acpi = 0xffffffff, + .device = NULL, + .fdc_device = NULL, + .sio_device = NULL, + .vid_device = &m19_vid_device, + .snd_device = NULL, + .net_device = NULL + }, + { + .name = "[8088] OpenXT", + .internal_name = "openxt", + .type = MACHINE_TYPE_8088, + .chipset = MACHINE_CHIPSET_DISCRETE, + .init = machine_xt_openxt_init, + .p1_handler = NULL, + .gpio_handler = NULL, + .available_flag = MACHINE_AVAILABLE, + .gpio_acpi_handler = NULL, + .cpu = { + .package = CPU_PKG_8088, + .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_PC, + .flags = MACHINE_FLAGS_NONE, + .ram = { + .min = 64, + .max = 640, + .step = 64 + }, + .nvrmask = 0, + .kbc_device = &keyboard_xtclone_device, + .kbc_p1 = 0xff, + .gpio = 0xffffffff, + .gpio_acpi = 0xffffffff, + .device = NULL, + .fdc_device = NULL, + .sio_device = NULL, + .vid_device = NULL, + .snd_device = NULL, + .net_device = NULL + }, + { + .name = "[8088] Packard Bell PB8810", + .internal_name = "pb8810", + .type = MACHINE_TYPE_8088, + .chipset = MACHINE_CHIPSET_DISCRETE, + .init = machine_xt_pb8810_init, + .p1_handler = NULL, + .gpio_handler = NULL, + .available_flag = MACHINE_AVAILABLE, + .gpio_acpi_handler = NULL, + .cpu = { + .package = CPU_PKG_8088, + .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_PC, + .flags = MACHINE_FLAGS_NONE, + .ram = { + .min = 256, + .max = 640, + .step = 128 + }, + .nvrmask = 0, + .kbc_device = &keyboard_xtclone_device, + .kbc_p1 = 0xff, + .gpio = 0xffffffff, + .gpio_acpi = 0xffffffff, + .device = NULL, + .fdc_device = NULL, + .sio_device = NULL, + .vid_device = NULL, + .snd_device = NULL, + .net_device = NULL + }, + { + .name = "[8088] Philips P3105/NMS9100", + .internal_name = "p3105", + .type = MACHINE_TYPE_8088, + .chipset = MACHINE_CHIPSET_DISCRETE, + .init = machine_xt_p3105_init, + .p1_handler = NULL, + .gpio_handler = NULL, + .available_flag = MACHINE_AVAILABLE, + .gpio_acpi_handler = NULL, + .cpu = { + .package = CPU_PKG_8088, + .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_PC, + .flags = MACHINE_XTA, + .ram = { + .min = 256, + .max = 768, + .step = 256 + }, + .nvrmask = 0, + .kbc_device = &keyboard_pc_device, + .kbc_p1 = 0xff, + .gpio = 0xffffffff, + .gpio_acpi = 0xffffffff, + .device = NULL, + .fdc_device = NULL, + .sio_device = NULL, + .vid_device = NULL, + .snd_device = NULL, + .net_device = NULL + }, + { + .name = "[8088] Phoenix XT clone", + .internal_name = "pxxt", + .type = MACHINE_TYPE_8088, + .chipset = MACHINE_CHIPSET_DISCRETE, + .init = machine_xt_pxxt_init, + .p1_handler = NULL, + .gpio_handler = NULL, + .available_flag = MACHINE_AVAILABLE, + .gpio_acpi_handler = NULL, + .cpu = { + .package = CPU_PKG_8088, + .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_PC, + .flags = MACHINE_FLAGS_NONE, + .ram = { + .min = 64, + .max = 640, + .step = 64 + }, + .nvrmask = 0, + .kbc_device = &keyboard_xtclone_device, + .kbc_p1 = 0xff, + .gpio = 0xffffffff, + .gpio_acpi = 0xffffffff, + .device = NULL, + .fdc_device = NULL, + .sio_device = NULL, + .vid_device = NULL, + .snd_device = NULL, + .net_device = NULL + }, + { + .name = "[8088] Pravetz 16 / IMKO-4", + .internal_name = "pravetz16", + .type = MACHINE_TYPE_8088, + .chipset = MACHINE_CHIPSET_DISCRETE, + .init = machine_xt_pravetz16_imko4_init, + .p1_handler = NULL, + .gpio_handler = NULL, + .available_flag = MACHINE_AVAILABLE, + .gpio_acpi_handler = NULL, + .cpu = { + .package = CPU_PKG_8088, + .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_PC, + .flags = MACHINE_FLAGS_NONE, + .ram = { + .min = 64, + .max = 640, + .step = 64 + }, + .nvrmask = 0, + .kbc_device = &keyboard_pravetz_device, + .kbc_p1 = 0xff, + .gpio = 0xffffffff, + .gpio_acpi = 0xffffffff, + .device = NULL, + .fdc_device = NULL, + .sio_device = NULL, + .vid_device = NULL, + .snd_device = NULL, + .net_device = NULL + }, + { + .name = "[8088] Sanyo SX-16", + .internal_name = "sansx16", + .type = MACHINE_TYPE_8088, + .chipset = MACHINE_CHIPSET_DISCRETE, + .init = machine_xt_sansx16_init, + .p1_handler = NULL, + .gpio_handler = NULL, + .available_flag = MACHINE_AVAILABLE, + .gpio_acpi_handler = NULL, + .cpu = { + .package = CPU_PKG_8088, + .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_PC, + .flags = MACHINE_FLAGS_NONE, + .ram = { + .min = 256, + .max = 640, + .step = 128 + }, + .nvrmask = 0, + .kbc_device = &keyboard_xtclone_device, + .kbc_p1 = 0xff, + .gpio = 0xffffffff, + .gpio_acpi = 0xffffffff, + .device = NULL, + .fdc_device = NULL, + .sio_device = NULL, + .vid_device = NULL, + .snd_device = NULL, + .net_device = NULL + }, + { + .name = "[8088] Schneider EuroPC", + .internal_name = "europc", + .type = MACHINE_TYPE_8088, + .chipset = MACHINE_CHIPSET_PROPRIETARY, + .init = machine_europc_init, + .p1_handler = NULL, + .gpio_handler = NULL, + .available_flag = MACHINE_AVAILABLE, + .gpio_acpi_handler = NULL, + .cpu = { + .package = CPU_PKG_8088_EUROPC, + .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_PC, + .flags = MACHINE_XTA | MACHINE_MOUSE, + .ram = { + .min = 512, + .max = 640, + .step = 128 + }, + .nvrmask = 15, + .kbc_device = &keyboard_xt_device, + .kbc_p1 = 0xff, + .gpio = 0xffffffff, + .gpio_acpi = 0xffffffff, + .device = NULL, + .fdc_device = NULL, + .sio_device = NULL, + .vid_device = NULL, + .snd_device = NULL, + .net_device = NULL + }, + { + .name = "[8088] Super PC/Turbo XT", + .internal_name = "pcxt", + .type = MACHINE_TYPE_8088, + .chipset = MACHINE_CHIPSET_DISCRETE, + .init = machine_xt_pcxt_init, + .p1_handler = NULL, + .gpio_handler = NULL, + .available_flag = MACHINE_AVAILABLE, + .gpio_acpi_handler = NULL, + .cpu = { + .package = CPU_PKG_8088, + .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_PC, + .flags = MACHINE_FLAGS_NONE, + .ram = { + .min = 64, + .max = 640, + .step = 64 + }, + .nvrmask = 0, + .kbc_device = &keyboard_xtclone_device, + .kbc_p1 = 0xff, + .gpio = 0xffffffff, + .gpio_acpi = 0xffffffff, + .device = NULL, + .fdc_device = NULL, + .sio_device = NULL, + .vid_device = NULL, + .snd_device = NULL, + .net_device = NULL + }, + { + .name = "[8088] Tandy 1000", + .internal_name = "tandy", + .type = MACHINE_TYPE_8088, + .chipset = MACHINE_CHIPSET_PROPRIETARY, + .init = machine_tandy_init, + .p1_handler = NULL, + .gpio_handler = NULL, + .available_flag = MACHINE_AVAILABLE, + .gpio_acpi_handler = NULL, + .cpu = { + .package = CPU_PKG_8088_EUROPC, + .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_PC, + .flags = MACHINE_VIDEO_FIXED, + .ram = { + .min = 128, + .max = 640, + .step = 128 + }, + .nvrmask = 0, + .kbc_device = &keyboard_tandy_device, + .kbc_p1 = 0xff, + .gpio = 0xffffffff, + .gpio_acpi = 0xffffffff, + .device = NULL, + .fdc_device = NULL, + .sio_device = NULL, + .vid_device = &vid_device, + .snd_device = NULL, + .net_device = NULL + }, + { + .name = "[8088] Tandy 1000 HX", + .internal_name = "tandy1000hx", + .type = MACHINE_TYPE_8088, + .chipset = MACHINE_CHIPSET_PROPRIETARY, + .init = machine_tandy1000hx_init, + .p1_handler = NULL, + .gpio_handler = NULL, + .available_flag = MACHINE_AVAILABLE, + .gpio_acpi_handler = NULL, + .cpu = { + .package = CPU_PKG_8088_EUROPC, + .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_PC, + .flags = MACHINE_VIDEO_FIXED, + .ram = { + .min = 384, + .max = 640, + .step = 128 + }, + .nvrmask = 0, + .kbc_device = &keyboard_tandy_device, + .kbc_p1 = 0xff, + .gpio = 0xffffffff, + .gpio_acpi = 0xffffffff, + .device = NULL, + .fdc_device = NULL, + .sio_device = NULL, + .vid_device = &vid_device_hx, + .snd_device = NULL, + .net_device = NULL + }, + { + .name = "[8088] Toshiba T1000", + .internal_name = "t1000", + .type = MACHINE_TYPE_8088, + .chipset = MACHINE_CHIPSET_PROPRIETARY, + .init = machine_xt_t1000_init, + .p1_handler = NULL, + .gpio_handler = NULL, + .available_flag = MACHINE_AVAILABLE, + .gpio_acpi_handler = NULL, + .cpu = { + .package = CPU_PKG_8088, + .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_PC, + .flags = MACHINE_VIDEO, + .ram = { + .min = 512, + .max = 1280, + .step = 768 + }, + .nvrmask = 63, + .kbc_device = &keyboard_xt_t1x00_device, + .kbc_p1 = 0xff, + .gpio = 0xffffffff, + .gpio_acpi = 0xffffffff, + .device = NULL, + .fdc_device = NULL, + .sio_device = NULL, + .vid_device = &t1000_video_device, + .snd_device = NULL, + .net_device = NULL + }, + { + .name = "[8088] Vendex HeadStart Turbo 888-XT", + .internal_name = "vendex", + .type = MACHINE_TYPE_8088, + .chipset = MACHINE_CHIPSET_PROPRIETARY, + .init = machine_xt_vendex_init, + .p1_handler = NULL, + .gpio_handler = NULL, + .available_flag = MACHINE_AVAILABLE, + .gpio_acpi_handler = NULL, + .cpu = { + .package = CPU_PKG_8088, + .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_PC, + .flags = MACHINE_FLAGS_NONE, + .ram = { + .min = 256, + .max = 768, + .step = 256 + }, + .nvrmask = 0, + .kbc_device = &keyboard_xtclone_device, + .kbc_p1 = 0xff, + .gpio = 0xffffffff, + .gpio_acpi = 0xffffffff, + .device = NULL, + .fdc_device = NULL, + .sio_device = NULL, + .vid_device = NULL, + .snd_device = NULL, + .net_device = NULL + }, #if defined(DEV_BRANCH) && defined(USE_LASERXT) - { "[8088] VTech Laser Turbo XT", "ltxt", MACHINE_TYPE_8088, CPU_PKG_8088, 0, 0, 0, 0, 0, 0, 0, MACHINE_PC, 256, 640, 256, 0, machine_xt_laserxt_init, NULL }, -#endif + { + .name = "[8088] VTech Laser Turbo XT", + .internal_name = "ltxt", + .type = MACHINE_TYPE_8088, + .chipset = MACHINE_CHIPSET_DISCRETE, + .init = machine_xt_laserxt_init, + .p1_handler = NULL, + .gpio_handler = NULL, + .available_flag = MACHINE_AVAILABLE, + .gpio_acpi_handler = NULL, + .cpu = { + .package = CPU_PKG_8088, + .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_PC, + .flags = MACHINE_FLAGS_NONE, + .ram = { + .min = 256, + .max = 640, + .step = 256 + }, + .nvrmask = 0, + .kbc_device = &keyboard_xt_device, + .kbc_p1 = 0xff, + .gpio = 0xffffffff, + .gpio_acpi = 0xffffffff, + .device = NULL, + .fdc_device = NULL, + .sio_device = NULL, + .vid_device = NULL, + .snd_device = NULL, + .net_device = NULL + }, +#endif /* defined(DEV_BRANCH) && defined(USE_LASERXT) */ /* Has a standard PS/2 KBC (so, use IBM PS/2 Type 1). */ - { "[8088] Xi8088", "xi8088", MACHINE_TYPE_8088, CPU_PKG_8088, 0, 0, 0, 0, 0, 0, 0, MACHINE_AT | MACHINE_BUS_PS2, 64, 1024, 128, 127, machine_xt_xi8088_init, xi8088_get_device }, - { "[8088] Zenith Data Systems Z-151/152/161","zdsz151", MACHINE_TYPE_8088, CPU_PKG_8088, 0, 0, 0, 0, 0, 0, 0, MACHINE_PC, 128, 640, 64, 0, machine_xt_z151_init, NULL }, - { "[8088] Zenith Data Systems Z-159", "zdsz159", MACHINE_TYPE_8088, CPU_PKG_8088, 0, 0, 0, 0, 0, 0, 0, MACHINE_PC, 128, 640, 64, 0, machine_xt_z159_init, NULL }, - { "[8088] Zenith Data Systems SupersPort (Z-184)","zdsupers", MACHINE_TYPE_8088, CPU_PKG_8088, 0, 0, 0, 0, 0, 0, 0, MACHINE_PC | MACHINE_VIDEO_FIXED, 128, 640, 128, 0, machine_xt_z184_init, z184_get_device }, - { "[GC100A] Philips P3120", "p3120", MACHINE_TYPE_8088, CPU_PKG_8088, 0, 0, 0, 0, 0, 0, 0, MACHINE_PC | MACHINE_XTA, 256, 768, 256, 0, machine_xt_p3120_init, NULL }, - + { + .name = "[8088] Xi8088", + .internal_name = "xi8088", + .type = MACHINE_TYPE_8088, + .chipset = MACHINE_CHIPSET_DISCRETE, + .init = machine_xt_xi8088_init, + .p1_handler = NULL, + .gpio_handler = NULL, + .available_flag = MACHINE_AVAILABLE, + .gpio_acpi_handler = NULL, + .cpu = { + .package = CPU_PKG_8088, + .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_PS2, + .flags = MACHINE_FLAGS_NONE, + .ram = { + .min = 64, + .max = 1024, + .step = 128 + }, + .nvrmask = 127, + .kbc_device = &keyboard_ps2_xi8088_device, + .kbc_p1 = 0xff, + .gpio = 0xffffffff, + .gpio_acpi = 0xffffffff, + .device = &xi8088_device, + .fdc_device = NULL, + .sio_device = NULL, + .vid_device = NULL, + .snd_device = NULL, + .net_device = NULL + }, + { + .name = "[8088] Z-NIX PC-1600", + .internal_name = "znic", + .type = MACHINE_TYPE_8088, + .chipset = MACHINE_CHIPSET_DISCRETE, + .init = machine_xt_znic_init, + .p1_handler = NULL, + .gpio_handler = NULL, + .available_flag = MACHINE_AVAILABLE, + .gpio_acpi_handler = NULL, + .cpu = { + .package = CPU_PKG_8088, + .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_PC, + .flags = MACHINE_FLAGS_NONE, + .ram = { + .min = 64, + .max = 640, + .step = 64 + }, + .nvrmask = 0, + .kbc_device = &keyboard_xtclone_device, + .kbc_p1 = 0xff, + .gpio = 0xffffffff, + .gpio_acpi = 0xffffffff, + .device = NULL, + .fdc_device = NULL, + .sio_device = NULL, + .vid_device = NULL, + .snd_device = NULL, + .net_device = NULL + }, + { + .name = "[8088] Zenith Data Systems Z-151/152/161", + .internal_name = "zdsz151", + .type = MACHINE_TYPE_8088, + .chipset = MACHINE_CHIPSET_DISCRETE, + .init = machine_xt_z151_init, + .p1_handler = NULL, + .gpio_handler = NULL, + .available_flag = MACHINE_AVAILABLE, + .gpio_acpi_handler = NULL, + .cpu = { + .package = CPU_PKG_8088, + .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_PC, + .flags = MACHINE_FLAGS_NONE, + .ram = { + .min = 128, + .max = 640, + .step = 64 + }, + .nvrmask = 0, + .kbc_device = &keyboard_xt_zenith_device, + .kbc_p1 = 0xff, + .gpio = 0xffffffff, + .gpio_acpi = 0xffffffff, + .device = NULL, + .fdc_device = NULL, + .sio_device = NULL, + .vid_device = NULL, + .snd_device = NULL, + .net_device = NULL + }, + { + .name = "[8088] Zenith Data Systems Z-159", + .internal_name = "zdsz159", + .type = MACHINE_TYPE_8088, + .chipset = MACHINE_CHIPSET_DISCRETE, + .init = machine_xt_z159_init, + .p1_handler = NULL, + .gpio_handler = NULL, + .available_flag = MACHINE_AVAILABLE, + .gpio_acpi_handler = NULL, + .cpu = { + .package = CPU_PKG_8088, + .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_PC, + .flags = MACHINE_FLAGS_NONE, + .ram = { + .min = 128, + .max = 640, + .step = 64 + }, + .nvrmask = 0, + .kbc_device = &keyboard_xt_zenith_device, + .kbc_p1 = 0xff, + .gpio = 0xffffffff, + .gpio_acpi = 0xffffffff, + .device = NULL, + .fdc_device = NULL, + .sio_device = NULL, + .vid_device = NULL, + .snd_device = NULL, + .net_device = NULL + }, + { + .name = "[8088] Zenith Data Systems SupersPort (Z-184)", + .internal_name = "zdsupers", + .type = MACHINE_TYPE_8088, + .chipset = MACHINE_CHIPSET_DISCRETE, + .init = machine_xt_z184_init, + .p1_handler = NULL, + .gpio_handler = NULL, + .available_flag = MACHINE_AVAILABLE, + .gpio_acpi_handler = NULL, + .cpu = { + .package = CPU_PKG_8088, + .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_PC, + .flags = MACHINE_VIDEO_FIXED, + .ram = { + .min = 128, + .max = 640, + .step = 128 + }, + .nvrmask = 0, + .kbc_device = &keyboard_xt_zenith_device, + .kbc_p1 = 0xff, + .gpio = 0xffffffff, + .gpio_acpi = 0xffffffff, + .device = NULL, + .fdc_device = NULL, + .sio_device = NULL, + .vid_device = &cga_device, + .snd_device = NULL, + .net_device = NULL + }, + { + .name = "[GC100A] Philips P3120", + .internal_name = "p3120", + .type = MACHINE_TYPE_8088, + .chipset = MACHINE_CHIPSET_GC100A, + .init = machine_xt_p3120_init, + .p1_handler = NULL, + .gpio_handler = NULL, + .available_flag = MACHINE_AVAILABLE, + .gpio_acpi_handler = NULL, + .cpu = { + .package = CPU_PKG_8088, + .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_PC, + .flags = MACHINE_XTA, + .ram = { + .min = 256, + .max = 768, + .step = 256 + }, + .nvrmask = 0, + .kbc_device = &keyboard_pc_device, + .kbc_p1 = 0xff, + .gpio = 0xffffffff, + .gpio_acpi = 0xffffffff, + .device = NULL, + .fdc_device = NULL, + .sio_device = NULL, + .vid_device = NULL, + .snd_device = NULL, + .net_device = NULL + }, + { + .name = "[V20] PC-XT", + .internal_name = "v20xt", + .type = MACHINE_TYPE_8088, + .chipset = MACHINE_CHIPSET_DISCRETE, + .init = machine_xt_v20xt_init, + .p1_handler = NULL, + .gpio_handler = NULL, + .available_flag = MACHINE_AVAILABLE, + .gpio_acpi_handler = NULL, + .cpu = { + .package = CPU_PKG_8088, + .block = CPU_BLOCK(CPU_8088), + .min_bus = 0, + .max_bus = 0, + .min_voltage = 0, + .max_voltage = 0, + .min_multi = 0, + .max_multi = 0 + }, + .bus_flags = MACHINE_PC, + .flags = MACHINE_FLAGS_NONE, + .ram = { + .min = 64, + .max = 640, + .step = 64 + }, + .nvrmask = 0, + .kbc_device = &keyboard_xtclone_device, + .kbc_p1 = 0xff, + .gpio = 0xffffffff, + .gpio_acpi = 0xffffffff, + .device = NULL, + .fdc_device = NULL, + .sio_device = NULL, + .vid_device = NULL, + .snd_device = NULL, + .net_device = NULL + }, + /* 8086 Machines */ - { "[8086] Amstrad PC1512", "pc1512", MACHINE_TYPE_8086, CPU_PKG_8086, 0, 8000000, 8000000, 0, 0, 0, 0, MACHINE_PC | MACHINE_VIDEO_FIXED | MACHINE_MOUSE, 512, 640, 128, 63, machine_pc1512_init, pc1512_get_device }, - { "[8086] Amstrad PC1640", "pc1640", MACHINE_TYPE_8086, CPU_PKG_8086, 0, 0, 0, 0, 0, 0, 0, MACHINE_PC | MACHINE_VIDEO | MACHINE_MOUSE, 640, 640, 640, 63, machine_pc1640_init, pc1640_get_device }, - { "[8086] Amstrad PC2086", "pc2086", MACHINE_TYPE_8086, CPU_PKG_8086, 0, 0, 0, 0, 0, 0, 0, MACHINE_PC | MACHINE_VIDEO_FIXED | MACHINE_MOUSE, 640, 640, 640, 63, machine_pc2086_init, pc2086_get_device }, - { "[8086] Amstrad PC3086", "pc3086", MACHINE_TYPE_8086, CPU_PKG_8086, 0, 0, 0, 0, 0, 0, 0, MACHINE_PC | MACHINE_VIDEO_FIXED | MACHINE_MOUSE, 640, 640, 640, 63, machine_pc3086_init, pc3086_get_device }, - { "[8086] Amstrad PC20(0)", "pc200", MACHINE_TYPE_8086, CPU_PKG_8086, 0, 0, 0, 0, 0, 0, 0, MACHINE_PC | MACHINE_VIDEO | MACHINE_MOUSE | MACHINE_NONMI, 512, 640, 128, 63, machine_pc200_init, pc200_get_device }, - { "[8086] Amstrad PPC512/640", "ppc512", MACHINE_TYPE_8086, CPU_PKG_8086, 0, 0, 0, 0, 0, 0, 0, MACHINE_PC | MACHINE_VIDEO | MACHINE_MOUSE | MACHINE_NONMI, 512, 640, 128, 63, machine_ppc512_init, ppc512_get_device }, - { "[8086] Compaq Deskpro", "deskpro", MACHINE_TYPE_8086, CPU_PKG_8086, 0, 0, 0, 0, 0, 0, 0, MACHINE_PC, 128, 640, 128, 0, machine_xt_compaq_deskpro_init, NULL }, - { "[8086] Olivetti M21/24/24SP", "m24", MACHINE_TYPE_8086, CPU_PKG_8086, 0, 0, 0, 0, 0, 0, 0, MACHINE_PC | MACHINE_VIDEO | MACHINE_MOUSE, 128, 640, 128, 0, machine_xt_m24_init, m24_get_device }, + { + .name = "[8086] Amstrad PC1512", + .internal_name = "pc1512", + .type = MACHINE_TYPE_8086, + .chipset = MACHINE_CHIPSET_PROPRIETARY, + .init = machine_pc1512_init, + .p1_handler = NULL, + .gpio_handler = NULL, + .available_flag = MACHINE_AVAILABLE, + .gpio_acpi_handler = NULL, + .cpu = { + .package = CPU_PKG_8086, + .block = CPU_BLOCK_NONE, + .min_bus = 8000000, + .max_bus = 8000000, + .min_voltage = 0, + .max_voltage = 0, + .min_multi = 0, + .max_multi = 0 + }, + .bus_flags = MACHINE_PC, + .flags = MACHINE_VIDEO_FIXED | MACHINE_MOUSE, + .ram = { + .min = 512, + .max = 640, + .step = 128 + }, + .nvrmask = 63, + .kbc_device = NULL /* TODO: No specific kbd_device yet */, + .kbc_p1 = 0xff, + .gpio = 0xffffffff, + .gpio_acpi = 0xffffffff, + .device = NULL, + .fdc_device = NULL, + .sio_device = NULL, + .vid_device = &vid_1512_device, + .snd_device = NULL, + .net_device = NULL + }, + { + .name = "[8086] Amstrad PC1640", + .internal_name = "pc1640", + .type = MACHINE_TYPE_8086, + .chipset = MACHINE_CHIPSET_PROPRIETARY, + .init = machine_pc1640_init, + .p1_handler = NULL, + .gpio_handler = NULL, + .available_flag = MACHINE_AVAILABLE, + .gpio_acpi_handler = NULL, + .cpu = { + .package = CPU_PKG_8086, + .block = CPU_BLOCK_NONE, + .min_bus = 0, + .max_bus = 10000000, + .min_voltage = 0, + .max_voltage = 0, + .min_multi = 0, + .max_multi = 0 + }, + .bus_flags = MACHINE_PC, + .flags = MACHINE_VIDEO | MACHINE_MOUSE, + .ram = { + .min = 640, + .max = 640, + .step = 640 + }, + .nvrmask = 63, + .kbc_device = NULL /* TODO: No specific kbd_device yet */, + .kbc_p1 = 0xff, + .gpio = 0xffffffff, + .gpio_acpi = 0xffffffff, + .device = NULL, + .fdc_device = NULL, + .sio_device = NULL, + .vid_device = &vid_1640_device, + .snd_device = NULL, + .net_device = NULL + }, + { + .name = "[8086] Amstrad PC2086", + .internal_name = "pc2086", + .type = MACHINE_TYPE_8086, + .chipset = MACHINE_CHIPSET_PROPRIETARY, + .init = machine_pc2086_init, + .p1_handler = NULL, + .gpio_handler = NULL, + .available_flag = MACHINE_AVAILABLE, + .gpio_acpi_handler = NULL, + .cpu = { + .package = CPU_PKG_8086, + .block = CPU_BLOCK_NONE, + .min_bus = 0, + .max_bus = 10000000, + .min_voltage = 0, + .max_voltage = 0, + .min_multi = 0, + .max_multi = 0 + }, + .bus_flags = MACHINE_PC, + .flags = MACHINE_VIDEO_FIXED | MACHINE_MOUSE, + .ram = { + .min = 640, + .max = 640, + .step = 640 + }, + .nvrmask = 63, + .kbc_device = NULL /* TODO: No specific kbd_device yet */, + .kbc_p1 = 0xff, + .gpio = 0xffffffff, + .gpio_acpi = 0xffffffff, + .device = NULL, + .fdc_device = NULL, + .sio_device = NULL, + .vid_device = &vid_pc2086_device, + .snd_device = NULL, + .net_device = NULL + }, + { + .name = "[8086] Amstrad PC3086", + .internal_name = "pc3086", + .type = MACHINE_TYPE_8086, + .chipset = MACHINE_CHIPSET_PROPRIETARY, + .init = machine_pc3086_init, + .p1_handler = NULL, + .gpio_handler = NULL, + .available_flag = MACHINE_AVAILABLE, + .gpio_acpi_handler = NULL, + .cpu = { + .package = CPU_PKG_8086, + .block = CPU_BLOCK_NONE, + .min_bus = 0, + .max_bus = 10000000, + .min_voltage = 0, + .max_voltage = 0, + .min_multi = 0, + .max_multi = 0 + }, + .bus_flags = MACHINE_PC, + .flags = MACHINE_VIDEO_FIXED | MACHINE_MOUSE, + .ram = { + .min = 640, + .max = 640, + .step = 640 + }, + .nvrmask = 63, + .kbc_device = NULL /* TODO: No specific kbd_device yet */, + .kbc_p1 = 0xff, + .gpio = 0xffffffff, + .gpio_acpi = 0xffffffff, + .device = NULL, + .fdc_device = NULL, + .sio_device = NULL, + .vid_device = &vid_pc3086_device, + .snd_device = NULL, + .net_device = NULL + }, + { + .name = "[8086] Amstrad PC20(0)", + .internal_name = "pc200", + .type = MACHINE_TYPE_8086, + .chipset = MACHINE_CHIPSET_PROPRIETARY, + .init = machine_pc200_init, + .p1_handler = NULL, + .gpio_handler = NULL, + .available_flag = MACHINE_AVAILABLE, + .gpio_acpi_handler = NULL, + .cpu = { + .package = CPU_PKG_8086, + .block = CPU_BLOCK_NONE, + .min_bus = 0, + .max_bus = 10000000, + .min_voltage = 0, + .max_voltage = 0, + .min_multi = 0, + .max_multi = 0 + }, + .bus_flags = MACHINE_PC, + .flags = MACHINE_VIDEO | MACHINE_MOUSE, + .ram = { + .min = 512, + .max = 640, + .step = 128 + }, + .nvrmask = 63, + .kbc_device = NULL /* TODO: No specific kbd_device yet */, + .kbc_p1 = 0xff, + .gpio = 0xffffffff, + .gpio_acpi = 0xffffffff, + .device = NULL, + .fdc_device = NULL, + .sio_device = NULL, + .vid_device = &vid_200_device, + .snd_device = NULL, + .net_device = NULL + }, + { + .name = "[8086] Amstrad PPC512/640", + .internal_name = "ppc512", + .type = MACHINE_TYPE_8086, + .chipset = MACHINE_CHIPSET_PROPRIETARY, + .init = machine_ppc512_init, + .p1_handler = NULL, + .gpio_handler = NULL, + .available_flag = MACHINE_AVAILABLE, + .gpio_acpi_handler = NULL, + .cpu = { + .package = CPU_PKG_8086, + .block = CPU_BLOCK_NONE, + .min_bus = 0, + .max_bus = 10000000, + .min_voltage = 0, + .max_voltage = 0, + .min_multi = 0, + .max_multi = 0 + }, + .bus_flags = MACHINE_PC, + .flags = MACHINE_VIDEO | MACHINE_MOUSE, + .ram = { + .min = 512, + .max = 640, + .step = 128 + }, + .nvrmask = 63, + .kbc_device = NULL /* TODO: No specific kbd_device yet */, + .kbc_p1 = 0xff, + .gpio = 0xffffffff, + .gpio_acpi = 0xffffffff, + .device = NULL, + .fdc_device = NULL, + .sio_device = NULL, + .vid_device = &vid_ppc512_device, + .snd_device = NULL, + .net_device = NULL + }, + { + .name = "[8086] Compaq Deskpro", + .internal_name = "deskpro", + .type = MACHINE_TYPE_8086, + .chipset = MACHINE_CHIPSET_PROPRIETARY, + .init = machine_xt_compaq_deskpro_init, + .p1_handler = NULL, + .gpio_handler = NULL, + .available_flag = MACHINE_AVAILABLE, + .gpio_acpi_handler = NULL, + .cpu = { + .package = CPU_PKG_8086, + .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_PC, + .flags = MACHINE_FLAGS_NONE, + .ram = { + .min = 128, + .max = 640, + .step = 128 + }, + .nvrmask = 0, + .kbc_device = &keyboard_xt_compaq_device, + .kbc_p1 = 0xff, + .gpio = 0xffffffff, + .gpio_acpi = 0xffffffff, + .device = NULL, + .fdc_device = NULL, + .sio_device = NULL, + .vid_device = NULL, + .snd_device = NULL, + .net_device = NULL + }, + { + .name = "[8086] Epson Equity LT", + .internal_name = "elt", + .type = MACHINE_TYPE_8086, + .chipset = MACHINE_CHIPSET_PROPRIETARY, + .init = machine_elt_init, + .p1_handler = NULL, + .gpio_handler = NULL, + .available_flag = MACHINE_AVAILABLE, + .gpio_acpi_handler = NULL, + .cpu = { + .package = CPU_PKG_8086, + .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_PC, + .flags = MACHINE_VIDEO, + .ram = { + .min = 640, + .max = 640, + .step = 640 + }, + .nvrmask = 0x3f, + .kbc_device = &keyboard_xt_device, + .kbc_p1 = 0xff, + .gpio = 0xffffffff, + .gpio_acpi = 0xffffffff, + .device = NULL, + .fdc_device = NULL, + .sio_device = NULL, + .vid_device = NULL, + .snd_device = NULL, + .net_device = NULL + }, + { + .name = "[8086] Olivetti M21/24/24SP", + .internal_name = "m24", + .type = MACHINE_TYPE_8086, + .chipset = MACHINE_CHIPSET_PROPRIETARY, + .init = machine_xt_m24_init, + .p1_handler = NULL, + .gpio_handler = NULL, + .available_flag = MACHINE_AVAILABLE, + .gpio_acpi_handler = NULL, + .cpu = { + .package = CPU_PKG_8086, + .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_PC, + .flags = MACHINE_VIDEO | MACHINE_MOUSE | MACHINE_MFM, + .ram = { + .min = 128, + .max = 640, + .step = 128 + }, + .nvrmask = 15, + .kbc_device = NULL /* TODO: No specific kbd_device yet */, + .kbc_p1 = 0xff, + .gpio = 0xffffffff, + .gpio_acpi = 0xffffffff, + .device = NULL, + .fdc_device = NULL, + .sio_device = NULL, + .vid_device = &ogc_m24_device, + .snd_device = NULL, + .net_device = NULL + }, /* Has Olivetti KBC firmware. */ - { "[8086] Olivetti M240", "m240", MACHINE_TYPE_8086, CPU_PKG_8086, 0, 0, 0, 0, 0, 0, 0, MACHINE_PC, 128, 640, 128, 0, machine_xt_m240_init, NULL }, - { "[8086] Schetmash Iskra-3104", "iskra3104", MACHINE_TYPE_8086, CPU_PKG_8086, 0, 0, 0, 0, 0, 0, 0, MACHINE_PC, 128, 640, 128, 0, machine_xt_iskra3104_init, NULL }, - { "[8086] Tandy 1000 SL/2", "tandy1000sl2", MACHINE_TYPE_8086, CPU_PKG_8086, 0, 0, 0, 0, 0, 0, 0, MACHINE_PC | MACHINE_VIDEO_FIXED, 512, 768, 128, 0, machine_tandy1000sl2_init, tandy1k_sl_get_device }, - { "[8086] Victor V86P", "v86p", MACHINE_TYPE_8086, CPU_PKG_8086, 0, 0, 0, 0, 0, 0, 0, MACHINE_PC | MACHINE_VIDEO, 512, 1024, 128, 127, machine_v86p_init, NULL }, - { "[8086] Toshiba T1200", "t1200", MACHINE_TYPE_8086, CPU_PKG_8086, 0, 0, 0, 0, 0, 0, 0, MACHINE_PC | MACHINE_VIDEO, 1024, 2048,1024, 63, machine_xt_t1200_init, t1200_get_device }, - + { + .name = "[8086] Olivetti M240", + .internal_name = "m240", + .type = MACHINE_TYPE_8086, + .chipset = MACHINE_CHIPSET_PROPRIETARY, + .init = machine_xt_m240_init, + .p1_handler = NULL, + .gpio_handler = NULL, + .available_flag = MACHINE_AVAILABLE, + .gpio_acpi_handler = NULL, + .cpu = { + .package = CPU_PKG_8086, + .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_PC, + .flags = MACHINE_MFM, + .ram = { + .min = 128, + .max = 640, + .step = 128 + }, + .nvrmask = 15, + .kbc_device = NULL /* TODO: No specific kbd_device yet */, + .kbc_p1 = 0xff, + .gpio = 0xffffffff, + .gpio_acpi = 0xffffffff, + .device = NULL, + .fdc_device = NULL, + .sio_device = NULL, + .vid_device = NULL, + .snd_device = NULL, + .net_device = NULL + }, + { + .name = "[8086] Schetmash Iskra-3104", + .internal_name = "iskra3104", + .type = MACHINE_TYPE_8086, + .chipset = MACHINE_CHIPSET_DISCRETE, + .init = machine_xt_iskra3104_init, + .p1_handler = NULL, + .gpio_handler = NULL, + .available_flag = MACHINE_AVAILABLE, + .gpio_acpi_handler = NULL, + .cpu = { + .package = CPU_PKG_8086, + .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_PC, + .flags = MACHINE_FLAGS_NONE, + .ram = { + .min = 128, + .max = 640, + .step = 128 + }, + .nvrmask = 0, + .kbc_device = &keyboard_xtclone_device, + .kbc_p1 = 0xff, + .gpio = 0xffffffff, + .gpio_acpi = 0xffffffff, + .device = NULL, + .fdc_device = NULL, + .sio_device = NULL, + .vid_device = NULL, + .snd_device = NULL, + .net_device = NULL + }, + { + .name = "[8086] Tandy 1000 SL/2", + .internal_name = "tandy1000sl2", + .type = MACHINE_TYPE_8086, + .chipset = MACHINE_CHIPSET_PROPRIETARY, + .init = machine_tandy1000sl2_init, + .p1_handler = NULL, + .gpio_handler = NULL, + .available_flag = MACHINE_AVAILABLE, + .gpio_acpi_handler = NULL, + .cpu = { + .package = CPU_PKG_8086, + .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_PC, + .flags = MACHINE_VIDEO_FIXED, + .ram = { + .min = 512, + .max = 768, + .step = 128 + }, + .nvrmask = 0, + .kbc_device = NULL /* TODO: No specific kbd_device yet */, + .kbc_p1 = 0xff, + .gpio = 0xffffffff, + .gpio_acpi = 0xffffffff, + .device = NULL, + .fdc_device = NULL, + .sio_device = NULL, + .vid_device = &vid_device_sl, + .snd_device = NULL, + .net_device = NULL + }, + { + .name = "[8086] Toshiba T1200", + .internal_name = "t1200", + .type = MACHINE_TYPE_8086, + .chipset = MACHINE_CHIPSET_PROPRIETARY, + .init = machine_xt_t1200_init, + .p1_handler = NULL, + .gpio_handler = NULL, + .available_flag = MACHINE_AVAILABLE, + .gpio_acpi_handler = NULL, + .cpu = { + .package = CPU_PKG_8086, + .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_PC, + .flags = MACHINE_VIDEO | MACHINE_MFM, + .ram = { + .min = 1024, + .max = 2048, + .step = 1024 + }, + .nvrmask = 63, + .kbc_device = &keyboard_xt_t1x00_device, + .kbc_p1 = 0xff, + .gpio = 0xffffffff, + .gpio_acpi = 0xffffffff, + .device = NULL, + .fdc_device = NULL, + .sio_device = NULL, + .vid_device = &t1200_video_device, + .snd_device = NULL, + .net_device = NULL + }, + { + .name = "[8086] Victor V86P", + .internal_name = "v86p", + .type = MACHINE_TYPE_8086, + .chipset = MACHINE_CHIPSET_PROPRIETARY, + .init = machine_v86p_init, + .p1_handler = NULL, + .gpio_handler = NULL, + .available_flag = MACHINE_AVAILABLE, + .gpio_acpi_handler = NULL, + .cpu = { + .package = CPU_PKG_8086, + .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_PC, + .flags = MACHINE_VIDEO | MACHINE_MFM, + .ram = { + .min = 512, + .max = 1024, + .step = 128 + }, + .nvrmask = 127, + .kbc_device = &keyboard_xt_device, + .kbc_p1 = 0xff, + .gpio = 0xffffffff, + .gpio_acpi = 0xffffffff, + .device = NULL, + .fdc_device = NULL, + .sio_device = NULL, + .vid_device = NULL, + .snd_device = NULL, + .net_device = NULL + }, + #if defined(DEV_BRANCH) && defined(USE_LASERXT) - { "[8086] VTech Laser XT3", "lxt3", MACHINE_TYPE_8086, CPU_PKG_8086, 0, 0, 0, 0, 0, 0, 0, MACHINE_PC, 256, 640, 256, 0, machine_xt_lxt3_init, NULL }, -#endif + { + .name = "[8086] VTech Laser XT3", + .internal_name = "lxt3", + .type = MACHINE_TYPE_8086, + .chipset = MACHINE_CHIPSET_DISCRETE, + .init = machine_xt_lxt3_init, + .p1_handler = NULL, + .gpio_handler = NULL, + .available_flag = MACHINE_AVAILABLE, + .gpio_acpi_handler = NULL, + .cpu = { + .package = CPU_PKG_8086, + .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_PC, + .flags = MACHINE_FLAGS_NONE, + .ram = { + .min = 256, + .max = 640, + .step = 256 + }, + .nvrmask = 0, + .kbc_device = &keyboard_xt_lxt3_device, + .kbc_p1 = 0xff, + .gpio = 0xffffffff, + .gpio_acpi = 0xffffffff, + .device = NULL, + .fdc_device = NULL, + .sio_device = NULL, + .vid_device = NULL, + .snd_device = NULL, + .net_device = NULL + }, +#endif /* defined(DEV_BRANCH) && defined(USE_LASERXT) */ /* 286 AT machines */ /* Has IBM AT KBC firmware. */ - { "[ISA] IBM AT", "ibmat", MACHINE_TYPE_286, CPU_PKG_286, 0, 6000000, 8000000, 0, 0, 0, 0, MACHINE_AT, 256, 15872, 128, 63, machine_at_ibm_init, NULL }, + { + .name = "[ISA] IBM AT", + .internal_name = "ibmat", + .type = MACHINE_TYPE_286, + .chipset = MACHINE_CHIPSET_DISCRETE, + .init = machine_at_ibm_init, + .p1_handler = NULL, + .gpio_handler = NULL, + .available_flag = MACHINE_AVAILABLE, + .gpio_acpi_handler = NULL, + .cpu = { + .package = CPU_PKG_286, + .block = CPU_BLOCK_NONE, + .min_bus = 6000000, + .max_bus = 8000000, + .min_voltage = 0, + .max_voltage = 0, + .min_multi = 0, + .max_multi = 0 + }, + .bus_flags = MACHINE_AT, + .flags = MACHINE_FLAGS_NONE, + .ram = { + .min = 256, + .max = 15872, + .step = 128 + }, + .nvrmask = 63, + .kbc_device = NULL, + .kbc_p1 = 0xff, + .gpio = 0xffffffff, + .gpio_acpi = 0xffffffff, + .device = NULL, + .fdc_device = NULL, + .sio_device = NULL, + .vid_device = NULL, + .snd_device = NULL, + .net_device = NULL + }, /* Has IBM PS/2 Type 1 KBC firmware. */ - { "[ISA] IBM PS/1 model 2011", "ibmps1es", MACHINE_TYPE_286, CPU_PKG_286, 0, 10000000, 10000000, 0, 0, 0, 0, MACHINE_AT | MACHINE_BUS_PS2 | MACHINE_XTA | MACHINE_VIDEO_FIXED, 512, 16384, 512, 63, machine_ps1_m2011_init, NULL }, + { + .name = "[ISA] IBM PS/1 model 2011", + .internal_name = "ibmps1es", + .type = MACHINE_TYPE_286, + .chipset = MACHINE_CHIPSET_PROPRIETARY, + .init = machine_ps1_m2011_init, + .p1_handler = NULL, + .gpio_handler = NULL, + .available_flag = MACHINE_AVAILABLE, + .gpio_acpi_handler = NULL, + .cpu = { + .package = CPU_PKG_286, + .block = CPU_BLOCK_NONE, + .min_bus = 10000000, + .max_bus = 10000000, + .min_voltage = 0, + .max_voltage = 0, + .min_multi = 0, + .max_multi = 0 + }, + .bus_flags = MACHINE_PS2, + .flags = MACHINE_XTA | MACHINE_VIDEO_FIXED, + .ram = { + .min = 512, + .max = 16384, + .step = 512 + }, + .nvrmask = 63, + .kbc_device = NULL, + .kbc_p1 = 0xff, + .gpio = 0xffffffff, + .gpio_acpi = 0xffffffff, + .device = NULL, + .fdc_device = NULL, + .sio_device = NULL, + .vid_device = NULL, + .snd_device = NULL, + .net_device = NULL + }, /* Has IBM PS/2 Type 1 KBC firmware. */ - { "[ISA] IBM PS/2 model 30-286", "ibmps2_m30_286", MACHINE_TYPE_286, CPU_PKG_286 | CPU_PKG_486SLC_IBM, 0, 10000000, 0, 0, 0, 0, 0, MACHINE_AT | MACHINE_BUS_PS2 | MACHINE_XTA | MACHINE_VIDEO_FIXED, 1024, 16384,1024, 127, machine_ps2_m30_286_init, NULL }, + { + .name = "[ISA] IBM PS/2 model 30-286", + .internal_name = "ibmps2_m30_286", + .type = MACHINE_TYPE_286, + .chipset = MACHINE_CHIPSET_PROPRIETARY, + .init = machine_ps2_m30_286_init, + .p1_handler = NULL, + .gpio_handler = NULL, + .available_flag = MACHINE_AVAILABLE, + .gpio_acpi_handler = NULL, + .cpu = { + .package = CPU_PKG_286 | CPU_PKG_486SLC_IBM, + .block = CPU_BLOCK_NONE, + .min_bus = 10000000, + .max_bus = 0, + .min_voltage = 0, + .max_voltage = 0, + .min_multi = 0, + .max_multi = 0 + }, + .bus_flags = MACHINE_PS2, + .flags = MACHINE_XTA | MACHINE_VIDEO_FIXED, + .ram = { + .min = 1024, + .max = 16384, + .step = 1024 + }, + .nvrmask = 127, + .kbc_device = NULL, + .kbc_p1 = 0xff, + .gpio = 0xffffffff, + .gpio_acpi = 0xffffffff, + .device = NULL, + .fdc_device = NULL, + .sio_device = NULL, + .vid_device = NULL, + .snd_device = NULL, + .net_device = NULL + }, /* Has IBM AT KBC firmware. */ - { "[ISA] IBM XT Model 286", "ibmxt286", MACHINE_TYPE_286, CPU_PKG_286, 0, 6000000, 6000000, 0, 0, 0, 0, MACHINE_AT, 256, 15872, 128, 127, machine_at_ibmxt286_init, NULL }, + { + .name = "[ISA] IBM XT Model 286", + .internal_name = "ibmxt286", + .type = MACHINE_TYPE_286, + .chipset = MACHINE_CHIPSET_DISCRETE, + .init = machine_at_ibmxt286_init, + .p1_handler = NULL, + .gpio_handler = NULL, + .available_flag = MACHINE_AVAILABLE, + .gpio_acpi_handler = NULL, + .cpu = { + .package = CPU_PKG_286, + .block = CPU_BLOCK_NONE, + .min_bus = 6000000, + .max_bus = 6000000, + .min_voltage = 0, + .max_voltage = 0, + .min_multi = 0, + .max_multi = 0 + }, + .bus_flags = MACHINE_AT, + .flags = MACHINE_FLAGS_NONE, + .ram = { + .min = 256, + .max = 15872, + .step = 128 + }, + .nvrmask = 127, + .kbc_device = NULL, + .kbc_p1 = 0xff, + .gpio = 0xffffffff, + .gpio_acpi = 0xffffffff, + .device = NULL, + .fdc_device = NULL, + .sio_device = NULL, + .vid_device = NULL, + .snd_device = NULL, + .net_device = NULL + }, /* AMI BIOS for a chipset-less machine, most likely has AMI 'F' KBC firmware. */ - { "[ISA] AMI IBM AT", "ibmatami", MACHINE_TYPE_286, CPU_PKG_286, 0, 6000000, 8000000, 0, 0, 0, 0, MACHINE_AT, 256, 15872, 128, 63, machine_at_ibmatami_init, NULL }, + { + .name = "[ISA] AMI IBM AT", + .internal_name = "ibmatami", + .type = MACHINE_TYPE_286, + .chipset = MACHINE_CHIPSET_DISCRETE, + .init = machine_at_ibmatami_init, + .p1_handler = NULL, + .gpio_handler = NULL, + .available_flag = MACHINE_AVAILABLE, + .gpio_acpi_handler = NULL, + .cpu = { + .package = CPU_PKG_286, + .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_FLAGS_NONE, + .ram = { + .min = 256, + .max = 15872, + .step = 128 + }, + .nvrmask = 63, + .kbc_device = NULL, + .kbc_p1 = 0xff, + .gpio = 0xffffffff, + .gpio_acpi = 0xffffffff, + .device = NULL, + .fdc_device = NULL, + .sio_device = NULL, + .vid_device = NULL, + .snd_device = NULL, + .net_device = NULL + }, /* Uses Commodore (CBM) KBC firmware, to be implemented as identical to the IBM AT KBC firmware unless evidence emerges of any proprietary commands. */ - { "[ISA] Commodore PC 30 III", "cmdpc30", MACHINE_TYPE_286, CPU_PKG_286, 0, 0, 0, 0, 0, 0, 0, MACHINE_AT, 640, 16384, 128, 127, machine_at_cmdpc_init, NULL }, + { + .name = "[ISA] Commodore PC 30 III", + .internal_name = "cmdpc30", + .type = MACHINE_TYPE_286, + .chipset = MACHINE_CHIPSET_PROPRIETARY, + .init = machine_at_cmdpc_init, + .p1_handler = NULL, + .gpio_handler = NULL, + .available_flag = MACHINE_AVAILABLE, + .gpio_acpi_handler = NULL, + .cpu = { + .package = CPU_PKG_286, + .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_FLAGS_NONE, + .ram = { + .min = 640, + .max = 16384, + .step = 128 + }, + .nvrmask = 127, + .kbc_device = NULL, + .kbc_p1 = 0xff, + .gpio = 0xffffffff, + .gpio_acpi = 0xffffffff, + .device = NULL, + .fdc_device = NULL, + .sio_device = NULL, + .vid_device = NULL, + .snd_device = NULL, + .net_device = NULL + }, /* Uses Compaq KBC firmware. */ - { "[ISA] Compaq Portable II", "portableii", MACHINE_TYPE_286, CPU_PKG_286, 0, 0, 0, 0, 0, 0, 0, MACHINE_AT, 640, 16384, 128, 127, machine_at_portableii_init, NULL }, + { + .name = "[ISA] Compaq Portable II", + .internal_name = "portableii", + .type = MACHINE_TYPE_286, + .chipset = MACHINE_CHIPSET_PROPRIETARY, + .init = machine_at_portableii_init, + .p1_handler = NULL, + .gpio_handler = NULL, + .available_flag = MACHINE_AVAILABLE, + .gpio_acpi_handler = NULL, + .cpu = { + .package = CPU_PKG_286, + .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_FLAGS_NONE, + .ram = { + .min = 640, + .max = 16384, + .step = 128 + }, + .nvrmask = 127, + .kbc_device = NULL, + .kbc_p1 = 0xff, + .gpio = 0xffffffff, + .gpio_acpi = 0xffffffff, + .device = NULL, + .fdc_device = NULL, + .sio_device = NULL, + .vid_device = NULL, + .snd_device = NULL, + .net_device = NULL + }, /* Uses Compaq KBC firmware. */ - { "[ISA] Compaq Portable III", "portableiii", MACHINE_TYPE_286, CPU_PKG_286, 0, 0, 0, 0, 0, 0, 0, MACHINE_AT | MACHINE_VIDEO, 640, 16384, 128, 127, machine_at_portableiii_init, at_cpqiii_get_device }, + { + .name = "[ISA] Compaq Portable III", + .internal_name = "portableiii", + .type = MACHINE_TYPE_286, + .chipset = MACHINE_CHIPSET_PROPRIETARY, + .init = machine_at_portableiii_init, + .p1_handler = NULL, + .gpio_handler = NULL, + .available_flag = MACHINE_AVAILABLE, + .gpio_acpi_handler = NULL, + .cpu = { + .package = CPU_PKG_286, + .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_VIDEO, + .ram = { + .min = 640, + .max = 16384, + .step = 128 + }, + .nvrmask = 127, + .kbc_device = NULL, + .kbc_p1 = 0xff, + .gpio = 0xffffffff, + .gpio_acpi = 0xffffffff, + .device = NULL, + .fdc_device = NULL, + .sio_device = NULL, + .vid_device = &compaq_plasma_device, + .snd_device = NULL, + .net_device = NULL + }, /* Has IBM AT KBC firmware. */ - { "[ISA] MR BIOS 286 clone", "mr286", MACHINE_TYPE_286, CPU_PKG_286, 0, 0, 0, 0, 0, 0, 0, MACHINE_AT | MACHINE_IDE, 512, 16384, 128, 127, machine_at_mr286_init, NULL }, + { + .name = "[ISA] MR BIOS 286 clone", + .internal_name = "mr286", + .type = MACHINE_TYPE_286, + .chipset = MACHINE_CHIPSET_DISCRETE, + .init = machine_at_mr286_init, + .p1_handler = NULL, + .gpio_handler = NULL, + .available_flag = MACHINE_AVAILABLE, + .gpio_acpi_handler = NULL, + .cpu = { + .package = CPU_PKG_286, + .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 = 512, + .max = 16384, + .step = 128 + }, + .nvrmask = 127, + .kbc_device = NULL, + .kbc_p1 = 0xff, + .gpio = 0xffffffff, + .gpio_acpi = 0xffffffff, + .device = NULL, + .fdc_device = NULL, + .sio_device = NULL, + .vid_device = NULL, + .snd_device = NULL, + .net_device = NULL + }, /* Has IBM AT KBC firmware. */ - { "[ISA] NCR PC8/810/710/3390/3392", "pc8", MACHINE_TYPE_286, CPU_PKG_286, 0, 0, 0, 0, 0, 0, 0, MACHINE_AT, 512, 16384, 128, 127, machine_at_pc8_init, NULL }, + { + .name = "[ISA] NCR PC8/810/710/3390/3392", + .internal_name = "pc8", + .type = MACHINE_TYPE_286, + .chipset = MACHINE_CHIPSET_DISCRETE, + .init = machine_at_pc8_init, + .p1_handler = NULL, + .gpio_handler = NULL, + .available_flag = MACHINE_AVAILABLE, + .gpio_acpi_handler = NULL, + .cpu = { + .package = CPU_PKG_286, + .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_FLAGS_NONE, + .ram = { + .min = 512, + .max = 16384, + .step = 128 + }, + .nvrmask = 127, + .kbc_device = NULL, + .kbc_p1 = 0xff, + .gpio = 0xffffffff, + .gpio_acpi = 0xffffffff, + .device = NULL, + .fdc_device = NULL, + .sio_device = NULL, + .vid_device = NULL, + .snd_device = NULL, + .net_device = NULL + }, #if defined(DEV_BRANCH) && defined(USE_OLIVETTI) /* Has Olivetti KBC firmware. */ - { "[ISA] Olivetti M290", "m290", MACHINE_TYPE_286, CPU_PKG_286, 0, 0, 0, 0, 0, 0, 0, MACHINE_AT, 640, 16384, 128, 127, machine_at_m290_init, NULL }, -#endif + { + .name = "[ISA] Olivetti M290", + .internal_name = "m290", + .type = MACHINE_TYPE_286, + .chipset = MACHINE_CHIPSET_PROPRIETARY, + .init = machine_at_m290_init, + .p1_handler = NULL, + .gpio_handler = NULL, + .available_flag = MACHINE_AVAILABLE, + .gpio_acpi_handler = NULL, + .cpu = { + .package = CPU_PKG_286, + .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_FLAGS_NONE, + .ram = { + .min = 640, + .max = 16384, + .step = 128 + }, + .nvrmask = 127, + .kbc_device = NULL, + .kbc_p1 = 0xff, + .gpio = 0xffffffff, + .gpio_acpi = 0xffffffff, + .device = NULL, + .fdc_device = NULL, + .sio_device = NULL, + .vid_device = NULL, + .snd_device = NULL, + .net_device = NULL + }, +#endif /* defined(DEV_BRANCH) && defined(USE_OLIVETTI) */ #if defined(DEV_BRANCH) && defined(USE_OPEN_AT) /* Has IBM AT KBC firmware. */ - { "[ISA] OpenAT", "openat", MACHINE_TYPE_286, CPU_PKG_286, 0, 0, 0, 0, 0, 0, 0, MACHINE_AT, 256, 15872, 128, 63, machine_at_openat_init, NULL }, -#endif + { + .name = "[ISA] OpenAT", + .internal_name = "openat", + .type = MACHINE_TYPE_286, + .chipset = MACHINE_CHIPSET_DISCRETE, + .init = machine_at_openat_init, + .p1_handler = NULL, + .gpio_handler = NULL, + .available_flag = MACHINE_AVAILABLE, + .gpio_acpi_handler = NULL, + .cpu = { + .package = CPU_PKG_286, + .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_FLAGS_NONE, + .ram = { + .min = 256, + .max = 15872, + .step = 128 + }, + .nvrmask = 63, + .kbc_device = NULL, + .kbc_p1 = 0xff, + .gpio = 0xffffffff, + .gpio_acpi = 0xffffffff, + .device = NULL, + .fdc_device = NULL, + .sio_device = NULL, + .vid_device = NULL, + .snd_device = NULL, + .net_device = NULL + }, +#endif /* defined(DEV_BRANCH) && defined(USE_OPEN_AT) */ /* Has IBM AT KBC firmware. */ - { "[ISA] Phoenix IBM AT", "ibmatpx", MACHINE_TYPE_286, CPU_PKG_286, 0, 6000000, 8000000, 0, 0, 0, 0, MACHINE_AT, 256, 15872, 128, 63, machine_at_ibmatpx_init, NULL }, + { + .name = "[ISA] Phoenix IBM AT", + .internal_name = "ibmatpx", + .type = MACHINE_TYPE_286, + .chipset = MACHINE_CHIPSET_DISCRETE, + .init = machine_at_ibmatpx_init, + .p1_handler = NULL, + .gpio_handler = NULL, + .available_flag = MACHINE_AVAILABLE, + .gpio_acpi_handler = NULL, + .cpu = { + .package = CPU_PKG_286, + .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_FLAGS_NONE, + .ram = { + .min = 256, + .max = 15872, + .step = 128 + }, + .nvrmask = 63, + .kbc_device = NULL, + .kbc_p1 = 0xff, + .gpio = 0xffffffff, + .gpio_acpi = 0xffffffff, + .device = NULL, + .fdc_device = NULL, + .sio_device = NULL, + .vid_device = NULL, + .snd_device = NULL, + .net_device = NULL + }, /* Has Quadtel KBC firmware. */ - { "[ISA] Quadtel IBM AT", "ibmatquadtel", MACHINE_TYPE_286, CPU_PKG_286, 0, 6000000, 8000000, 0, 0, 0, 0, MACHINE_AT, 256, 15872, 128, 63, machine_at_ibmatquadtel_init, NULL }, + { + .name = "[ISA] Quadtel IBM AT", + .internal_name = "ibmatquadtel", + .type = MACHINE_TYPE_286, + .chipset = MACHINE_CHIPSET_DISCRETE, + .init = machine_at_ibmatquadtel_init, + .p1_handler = NULL, + .gpio_handler = NULL, + .available_flag = MACHINE_AVAILABLE, + .gpio_acpi_handler = NULL, + .cpu = { + .package = CPU_PKG_286, + .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_FLAGS_NONE, + .ram = { + .min = 256, + .max = 15872, + .step = 128 + }, + .nvrmask = 63, + .kbc_device = NULL, + .kbc_p1 = 0xff, + .gpio = 0xffffffff, + .gpio_acpi = 0xffffffff, + .device = NULL, + .fdc_device = NULL, + .sio_device = NULL, + .vid_device = NULL, + .snd_device = NULL, + .net_device = NULL + }, /* This has a Siemens proprietary KBC which is completely undocumented. */ - { "[ISA] Siemens PCD-2L", "siemens", MACHINE_TYPE_286, CPU_PKG_286, 0, 0, 0, 0, 0, 0, 0, MACHINE_AT, 256, 15872, 128, 63, machine_at_siemens_init, NULL }, + { + .name = "[ISA] Siemens PCD-2L", + .internal_name = "siemens", + .type = MACHINE_TYPE_286, + .chipset = MACHINE_CHIPSET_DISCRETE, + .init = machine_at_siemens_init, + .p1_handler = NULL, + .gpio_handler = NULL, + .available_flag = MACHINE_AVAILABLE, + .gpio_acpi_handler = NULL, + .cpu = { + .package = CPU_PKG_286, + .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_FLAGS_NONE, + .ram = { + .min = 256, + .max = 15872, + .step = 128 + }, + .nvrmask = 63, + .kbc_device = NULL, + .kbc_p1 = 0xff, + .gpio = 0xffffffff, + .gpio_acpi = 0xffffffff, + .device = NULL, + .fdc_device = NULL, + .sio_device = NULL, + .vid_device = NULL, + .snd_device = NULL, + .net_device = NULL + }, /* This has Toshiba's proprietary KBC, which is already implemented. */ - { "[ISA] Toshiba T3100e", "t3100e", MACHINE_TYPE_286, CPU_PKG_286, 0, 0, 0, 0, 0, 0, 0, MACHINE_AT | MACHINE_IDE | MACHINE_VIDEO_FIXED, 1024, 5120, 256, 63, machine_at_t3100e_init, NULL }, + { + .name = "[ISA] Toshiba T3100e", + .internal_name = "t3100e", + .type = MACHINE_TYPE_286, + .chipset = MACHINE_CHIPSET_PROPRIETARY, + .init = machine_at_t3100e_init, + .p1_handler = NULL, + .gpio_handler = NULL, + .available_flag = MACHINE_AVAILABLE, + .gpio_acpi_handler = NULL, + .cpu = { + .package = CPU_PKG_286, + .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 | MACHINE_VIDEO_FIXED, + .ram = { + .min = 1024, + .max = 5120, + .step = 256 + }, + .nvrmask = 63, + .kbc_device = NULL, + .kbc_p1 = 0xff, + .gpio = 0xffffffff, + .gpio_acpi = 0xffffffff, + .device = NULL, + .fdc_device = NULL, + .sio_device = NULL, + .vid_device = NULL, + .snd_device = NULL, + .net_device = NULL + }, /* Has Quadtel KBC firmware. */ - { "[GC103] Quadtel 286 clone", "quadt286", MACHINE_TYPE_286, CPU_PKG_286, 0, 0, 0, 0, 0, 0, 0, MACHINE_AT, 512, 16384, 128, 127, machine_at_quadt286_init, NULL }, + { + .name = "[GC103] Quadtel 286 clone", + .internal_name = "quadt286", + .type = MACHINE_TYPE_286, + .chipset = MACHINE_CHIPSET_GC103, + .init = machine_at_quadt286_init, + .p1_handler = NULL, + .gpio_handler = NULL, + .available_flag = MACHINE_AVAILABLE, + .gpio_acpi_handler = NULL, + .cpu = { + .package = CPU_PKG_286, + .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_SOFTFLOAT_ONLY, + .ram = { + .min = 512, + .max = 16384, + .step = 128 + }, + .nvrmask = 127, + .kbc_device = NULL, + .kbc_p1 = 0xff, + .gpio = 0xffffffff, + .gpio_acpi = 0xffffffff, + .device = NULL, + .fdc_device = NULL, + .sio_device = NULL, + .vid_device = NULL, + .snd_device = NULL, + .net_device = NULL + }, /* Most likely has AMI 'F' KBC firmware. */ - { "[GC103] TriGem 286M", "tg286m", MACHINE_TYPE_286, CPU_PKG_286, 0, 0, 0, 0, 0, 0, 0, MACHINE_AT | MACHINE_IDE, 512, 8192, 128, 127, machine_at_tg286m_init, NULL }, + { + .name = "[GC103] TriGem 286M", + .internal_name = "tg286m", + .type = MACHINE_TYPE_286, + .chipset = MACHINE_CHIPSET_GC103, + .init = machine_at_tg286m_init, + .p1_handler = NULL, + .gpio_handler = NULL, + .available_flag = MACHINE_AVAILABLE, + .gpio_acpi_handler = NULL, + .cpu = { + .package = CPU_PKG_286, + .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 = 512, + .max = 8192, + .step = 128 + }, + .nvrmask = 127, + .kbc_device = NULL, + .kbc_p1 = 0xff, + .gpio = 0xffffffff, + .gpio_acpi = 0xffffffff, + .device = NULL, + .fdc_device = NULL, + .sio_device = NULL, + .vid_device = NULL, + .snd_device = NULL, + .net_device = NULL + }, /* This has "AMI KEYBOARD BIOS", most likely 'F'. */ - { "[NEAT] DataExpert 286", "ami286", MACHINE_TYPE_286, CPU_PKG_286, 0, 0, 0, 0, 0, 0, 0, MACHINE_AT, 512, 8192, 128, 127, machine_at_neat_ami_init, NULL }, + { + .name = "[NEAT] DataExpert 286", + .internal_name = "ami286", + .type = MACHINE_TYPE_286, + .chipset = MACHINE_CHIPSET_NEAT, + .init = machine_at_neat_ami_init, + .p1_handler = NULL, + .gpio_handler = NULL, + .available_flag = MACHINE_AVAILABLE, + .gpio_acpi_handler = NULL, + .cpu = { + .package = CPU_PKG_286, + .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_FLAGS_NONE, + .ram = { + .min = 512, + .max = 8192, + .step = 128 + }, + .nvrmask = 127, + .kbc_device = NULL, + .kbc_p1 = 0xff, + .gpio = 0xffffffff, + .gpio_acpi = 0xffffffff, + .device = NULL, + .fdc_device = NULL, + .sio_device = NULL, + .vid_device = NULL, + .snd_device = NULL, + .net_device = NULL + }, /* Has IBM AT KBC firmware. */ - { "[NEAT] NCR 3302", "3302", MACHINE_TYPE_286, CPU_PKG_286, 0, 0, 0, 0, 0, 0, 0, MACHINE_AT | MACHINE_VIDEO, 512, 16384, 128, 127, machine_at_3302_init, NULL }, + { + .name = "[NEAT] NCR 3302", + .internal_name = "3302", + .type = MACHINE_TYPE_286, + .chipset = MACHINE_CHIPSET_NEAT, + .init = machine_at_3302_init, + .p1_handler = NULL, + .gpio_handler = NULL, + .available_flag = MACHINE_AVAILABLE, + .gpio_acpi_handler = NULL, + .cpu = { + .package = CPU_PKG_286, + .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_VIDEO, + .ram = { + .min = 512, + .max = 16384, + .step = 128 + }, + .nvrmask = 127, + .kbc_device = NULL, + .kbc_p1 = 0xff, + .gpio = 0xffffffff, + .gpio_acpi = 0xffffffff, + .device = NULL, + .fdc_device = NULL, + .sio_device = NULL, + .vid_device = NULL, + .snd_device = NULL, + .net_device = NULL + }, /* Has IBM AT KBC firmware. */ - { "[NEAT] Phoenix 286 clone", "px286", MACHINE_TYPE_286, CPU_PKG_286, 0, 0, 0, 0, 0, 0, 0, MACHINE_AT, 512, 16384, 128, 127, machine_at_px286_init, NULL }, + { + .name = "[NEAT] Phoenix 286 clone", + .internal_name = "px286", + .type = MACHINE_TYPE_286, + .chipset = MACHINE_CHIPSET_NEAT, + .init = machine_at_px286_init, + .p1_handler = NULL, + .gpio_handler = NULL, + .available_flag = MACHINE_AVAILABLE, + .gpio_acpi_handler = NULL, + .cpu = { + .package = CPU_PKG_286, + .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_FLAGS_NONE, + .ram = { + .min = 512, + .max = 16384, + .step = 128 + }, + .nvrmask = 127, + .kbc_device = NULL, + .kbc_p1 = 0xff, + .gpio = 0xffffffff, + .gpio_acpi = 0xffffffff, + .device = NULL, + .fdc_device = NULL, + .sio_device = NULL, + .vid_device = NULL, + .snd_device = NULL, + .net_device = NULL + }, /* Has Chips & Technologies KBC firmware. */ - { "[SCAT] GW-286CT GEAR", "gw286ct", MACHINE_TYPE_286, CPU_PKG_286, 0, 0, 0, 0, 0, 0, 0, MACHINE_AT | MACHINE_IDE, 512, 16384, 128, 127, machine_at_gw286ct_init, NULL }, + { + .name = "[SCAT] GW-286CT GEAR", + .internal_name = "gw286ct", + .type = MACHINE_TYPE_286, + .chipset = MACHINE_CHIPSET_SCAT, + .init = machine_at_gw286ct_init, + .p1_handler = NULL, + .gpio_handler = NULL, + .available_flag = MACHINE_AVAILABLE, + .gpio_acpi_handler = NULL, + .cpu = { + .package = CPU_PKG_286, + .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 = 512, + .max = 16384, + .step = 128 + }, + .nvrmask = 127, + .kbc_device = NULL, + .kbc_p1 = 0xff, + .gpio = 0xffffffff, + .gpio_acpi = 0xffffffff, + .device = NULL, + .fdc_device = NULL, + .sio_device = NULL, + .vid_device = NULL, + .snd_device = NULL, + .net_device = NULL + }, /* Has IBM PS/2 Type 1 KBC firmware. */ - { "[SCAT] Goldstar GDC-212M", "gdc212m", MACHINE_TYPE_286, CPU_PKG_286, 0, 0, 0, 0, 0, 0, 0, MACHINE_AT | MACHINE_IDE | MACHINE_BUS_PS2, 512, 4096, 512, 127, machine_at_gdc212m_init, NULL }, + { + .name = "[SCAT] Goldstar GDC-212M", + .internal_name = "gdc212m", + .type = MACHINE_TYPE_286, + .chipset = MACHINE_CHIPSET_SCAT, + .init = machine_at_gdc212m_init, + .p1_handler = NULL, + .gpio_handler = NULL, + .available_flag = MACHINE_AVAILABLE, + .gpio_acpi_handler = NULL, + .cpu = { + .package = CPU_PKG_286, + .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_PS2, + .flags = MACHINE_IDE, + .ram = { + .min = 512, + .max = 4096, + .step = 512 + }, + .nvrmask = 127, + .kbc_device = NULL, + .kbc_p1 = 0xff, + .gpio = 0xffffffff, + .gpio_acpi = 0xffffffff, + .device = NULL, + .fdc_device = NULL, + .sio_device = NULL, + .vid_device = NULL, + .snd_device = NULL, + .net_device = NULL + }, /* Has a VIA VT82C42N KBC. */ - { "[SCAT] Hyundai Solomon 286KP", "award286", MACHINE_TYPE_286, CPU_PKG_286, 0, 0, 0, 0, 0, 0, 0, MACHINE_AT, 512, 16384, 128, 127, machine_at_award286_init, NULL }, + { + .name = "[SCAT] Hyundai Solomon 286KP", + .internal_name = "award286", + .type = MACHINE_TYPE_286, + .chipset = MACHINE_CHIPSET_SCAT, + .init = machine_at_award286_init, + .p1_handler = NULL, + .gpio_handler = NULL, + .available_flag = MACHINE_AVAILABLE, + .gpio_acpi_handler = NULL, + .cpu = { + .package = CPU_PKG_286, + .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_FLAGS_NONE, + .ram = { + .min = 512, + .max = 16384, + .step = 128 + }, + .nvrmask = 127, + .kbc_device = NULL, + .kbc_p1 = 0xff, + .gpio = 0xffffffff, + .gpio_acpi = 0xffffffff, + .device = NULL, + .fdc_device = NULL, + .sio_device = NULL, + .vid_device = NULL, + .snd_device = NULL, + .net_device = NULL + }, /* Has a VIA VT82C42N KBC. */ - { "[SCAT] Hyundai Super-286TR", "super286tr", MACHINE_TYPE_286, CPU_PKG_286, 0, 0, 0, 0, 0, 0, 0, MACHINE_AT, 512, 16384, 128, 127, machine_at_super286tr_init, NULL }, + { + .name = "[SCAT] Hyundai Super-286TR", + .internal_name = "super286tr", + .type = MACHINE_TYPE_286, + .chipset = MACHINE_CHIPSET_SCAT, + .init = machine_at_super286tr_init, + .p1_handler = NULL, + .gpio_handler = NULL, + .available_flag = MACHINE_AVAILABLE, + .gpio_acpi_handler = NULL, + .cpu = { + .package = CPU_PKG_286, + .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_FLAGS_NONE, + .ram = { + .min = 512, + .max = 16384, + .step = 128 + }, + .nvrmask = 127, + .kbc_device = NULL, + .kbc_p1 = 0xff, + .gpio = 0xffffffff, + .gpio_acpi = 0xffffffff, + .device = NULL, + .fdc_device = NULL, + .sio_device = NULL, + .vid_device = NULL, + .snd_device = NULL, + .net_device = NULL + }, /* Has IBM PS/2 Type 1 KBC firmware. */ - { "[SCAT] Samsung SPC-4200P", "spc4200p", MACHINE_TYPE_286, CPU_PKG_286, 0, 0, 0, 0, 0, 0, 0, MACHINE_AT | MACHINE_BUS_PS2, 512, 2048, 128, 127, machine_at_spc4200p_init, NULL }, + { + .name = "[SCAT] Samsung SPC-4200P", + .internal_name = "spc4200p", + .type = MACHINE_TYPE_286, + .chipset = MACHINE_CHIPSET_SCAT, + .init = machine_at_spc4200p_init, + .p1_handler = NULL, + .gpio_handler = NULL, + .available_flag = MACHINE_AVAILABLE, + .gpio_acpi_handler = NULL, + .cpu = { + .package = CPU_PKG_286, + .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_PS2, + .flags = MACHINE_FLAGS_NONE, + .ram = { + .min = 512, + .max = 2048, + .step = 128 + }, + .nvrmask = 127, + .kbc_device = NULL, + .kbc_p1 = 0xff, + .gpio = 0xffffffff, + .gpio_acpi = 0xffffffff, + .device = NULL, + .fdc_device = NULL, + .sio_device = NULL, + .vid_device = NULL, + .snd_device = NULL, + .net_device = NULL + }, /* Has IBM PS/2 Type 1 KBC firmware. */ - { "[SCAT] Samsung SPC-4216P", "spc4216p", MACHINE_TYPE_286, CPU_PKG_286, 0, 0, 0, 0, 0, 0, 0, MACHINE_AT | MACHINE_BUS_PS2, 1024, 5120,1024, 127, machine_at_spc4216p_init, NULL }, + { + .name = "[SCAT] Samsung SPC-4216P", + .internal_name = "spc4216p", + .type = MACHINE_TYPE_286, + .chipset = MACHINE_CHIPSET_SCAT, + .init = machine_at_spc4216p_init, + .p1_handler = NULL, + .gpio_handler = NULL, + .available_flag = MACHINE_AVAILABLE, + .gpio_acpi_handler = NULL, + .cpu = { + .package = CPU_PKG_286, + .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_PS2, + .flags = MACHINE_FLAGS_NONE, + .ram = { + .min = 1024, + .max = 5120, + .step = 1024 + }, + .nvrmask = 127, + .kbc_device = NULL, + .kbc_p1 = 0xff, + .gpio = 0xffffffff, + .gpio_acpi = 0xffffffff, + .device = NULL, + .fdc_device = NULL, + .sio_device = NULL, + .vid_device = NULL, + .snd_device = NULL, + .net_device = NULL + }, /* Has IBM PS/2 Type 1 KBC firmware. */ - { "[SCAT] Samsung SPC-4620P", "spc4620p", MACHINE_TYPE_286, CPU_PKG_286, 0, 0, 0, 0, 0, 0, 0, MACHINE_AT | MACHINE_BUS_PS2 | MACHINE_VIDEO, 1024, 5120,1024, 127, machine_at_spc4620p_init, NULL }, + { + .name = "[SCAT] Samsung SPC-4620P", + .internal_name = "spc4620p", + .type = MACHINE_TYPE_286, + .chipset = MACHINE_CHIPSET_SCAT, + .init = machine_at_spc4620p_init, + .p1_handler = NULL, + .gpio_handler = NULL, + .available_flag = MACHINE_AVAILABLE, + .gpio_acpi_handler = NULL, + .cpu = { + .package = CPU_PKG_286, + .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_PS2, + .flags = MACHINE_VIDEO, + .ram = { + .min = 1024, + .max = 5120, + .step = 1024 + }, + .nvrmask = 127, + .kbc_device = NULL, + .kbc_p1 = 0xff, + .gpio = 0xffffffff, + .gpio_acpi = 0xffffffff, + .device = NULL, + .fdc_device = NULL, + .sio_device = NULL, + .vid_device = NULL, + .snd_device = NULL, + .net_device = NULL + }, /* Has IBM AT KBC firmware. */ - { "[SCAT] Samsung Deskmaster 286", "deskmaster286", MACHINE_TYPE_286, CPU_PKG_286, 0, 0, 0, 0, 0, 0, 0, MACHINE_AT, 512, 16384, 128, 127, machine_at_deskmaster286_init, NULL }, - + { + .name = "[SCAT] Samsung Deskmaster 286", + .internal_name = "deskmaster286", + .type = MACHINE_TYPE_286, + .chipset = MACHINE_CHIPSET_SCAT, + .init = machine_at_deskmaster286_init, + .p1_handler = NULL, + .gpio_handler = NULL, + .available_flag = MACHINE_AVAILABLE, + .gpio_acpi_handler = NULL, + .cpu = { + .package = CPU_PKG_286, + .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_FLAGS_NONE, + .ram = { + .min = 512, + .max = 16384, + .step = 128 + }, + .nvrmask = 127, + .kbc_device = NULL, + .kbc_p1 = 0xff, + .gpio = 0xffffffff, + .gpio_acpi = 0xffffffff, + .device = NULL, + .fdc_device = NULL, + .sio_device = NULL, + .vid_device = NULL, + .snd_device = NULL, + .net_device = NULL + }, + /* 286 machines that utilize the MCA bus */ /* Has IBM PS/2 Type 2 KBC firmware. */ - { "[MCA] IBM PS/2 model 50", "ibmps2_m50", MACHINE_TYPE_286, CPU_PKG_286 | CPU_PKG_486SLC_IBM, 0, 10000000, 0, 0, 0, 0, 0, MACHINE_MCA | MACHINE_BUS_PS2 | MACHINE_VIDEO, 1024, 10240,1024, 63, machine_ps2_model_50_init, NULL }, + { + .name = "[MCA] IBM PS/2 model 50", + .internal_name = "ibmps2_m50", + .type = MACHINE_TYPE_286, + .chipset = MACHINE_CHIPSET_PROPRIETARY, + .init = machine_ps2_model_50_init, + .p1_handler = NULL, + .gpio_handler = NULL, + .available_flag = MACHINE_AVAILABLE, + .gpio_acpi_handler = NULL, + .cpu = { + .package = CPU_PKG_286 | CPU_PKG_486SLC_IBM, + .block = CPU_BLOCK_NONE, + .min_bus = 10000000, + .max_bus = 0, + .min_voltage = 0, + .max_voltage = 0, + .min_multi = 0, + .max_multi = 0 + }, + .bus_flags = MACHINE_PS2_MCA, + .flags = MACHINE_VIDEO, + .ram = { + .min = 1024, + .max = 10240, + .step = 1024 + }, + .nvrmask = 63, + .kbc_device = NULL, + .kbc_p1 = 0xff, + .gpio = 0xffffffff, + .gpio_acpi = 0xffffffff, + .device = NULL, + .fdc_device = NULL, + .sio_device = NULL, + .vid_device = NULL, + .snd_device = NULL, + .net_device = NULL + }, + /* Has IBM PS/2 Type 2 KBC firmware. */ + { + .name = "[MCA] IBM PS/2 model 60", + .internal_name = "ibmps2_m60", + .type = MACHINE_TYPE_286, + .chipset = MACHINE_CHIPSET_PROPRIETARY, + .init = machine_ps2_model_60_init, + .p1_handler = NULL, + .gpio_handler = NULL, + .available_flag = MACHINE_AVAILABLE, + .gpio_acpi_handler = NULL, + .cpu = { + .package = CPU_PKG_286 | CPU_PKG_486SLC_IBM, + .block = CPU_BLOCK_NONE, + .min_bus = 10000000, + .max_bus = 0, + .min_voltage = 0, + .max_voltage = 0, + .min_multi = 0, + .max_multi = 0 + }, + .bus_flags = MACHINE_PS2_MCA, + .flags = MACHINE_VIDEO, + .ram = { + .min = 1024, + .max = 10240, + .step = 1024 + }, + .nvrmask = 63, + .kbc_device = NULL, + .kbc_p1 = 0xff, + .gpio = 0xffffffff, + .gpio_acpi = 0xffffffff, + .device = NULL, + .fdc_device = NULL, + .sio_device = NULL, + .vid_device = NULL, + .snd_device = NULL, + .net_device = NULL + }, /* 386SX machines */ /* ISA slots available because an official IBM expansion for that existed. */ /* Has IBM PS/2 Type 1 KBC firmware. */ - { "[ISA] IBM PS/1 model 2121", "ibmps1_2121", MACHINE_TYPE_386SX, CPU_PKG_386SX, 0, 0, 0, 0, 0, 0, 0, MACHINE_AT | MACHINE_BUS_PS2 | MACHINE_IDE | MACHINE_VIDEO, 2048, 6144,1024, 63, machine_ps1_m2121_init, NULL }, + { + .name = "[ISA] IBM PS/1 model 2121", + .internal_name = "ibmps1_2121", + .type = MACHINE_TYPE_386SX, + .chipset = MACHINE_CHIPSET_PROPRIETARY, + .init = machine_ps1_m2121_init, + .p1_handler = NULL, + .gpio_handler = NULL, + .available_flag = MACHINE_AVAILABLE, + .gpio_acpi_handler = NULL, + .cpu = { + .package = CPU_PKG_386SX, + .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_PS2, + .flags = MACHINE_IDE | MACHINE_VIDEO, + .ram = { + .min = 2048, + .max = 6144, + .step = 1024 + }, + .nvrmask = 63, + .kbc_device = NULL, + .kbc_p1 = 0xff, + .gpio = 0xffffffff, + .gpio_acpi = 0xffffffff, + .device = NULL, + .fdc_device = NULL, + .sio_device = NULL, + .vid_device = NULL, + .snd_device = NULL, + .net_device = NULL + }, /* Has IBM AT KBC firmware. */ - { "[ISA] NCR PC916SX", "pc916sx", MACHINE_TYPE_386SX, CPU_PKG_386SX, 0, 0, 0, 0, 0, 0, 0, MACHINE_AT, 1024, 16384, 128, 127, machine_at_pc916sx_init, NULL }, + { + .name = "[ISA] NCR PC916SX", + .internal_name = "pc916sx", + .type = MACHINE_TYPE_386SX, + .chipset = MACHINE_CHIPSET_DISCRETE, + .init = machine_at_pc916sx_init, + .p1_handler = NULL, + .gpio_handler = NULL, + .available_flag = MACHINE_AVAILABLE, + .gpio_acpi_handler = NULL, + .cpu = { + .package = CPU_PKG_386SX, + .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_FLAGS_NONE, + .ram = { + .min = 1024, + .max = 16384, + .step = 128 + }, + .nvrmask = 127, + .kbc_device = NULL, + .kbc_p1 = 0xff, + .gpio = 0xffffffff, + .gpio_acpi = 0xffffffff, + .device = NULL, + .fdc_device = NULL, + .sio_device = NULL, + .vid_device = NULL, + .snd_device = NULL, + .net_device = NULL + }, /* Has Quadtel KBC firmware. */ - { "[ISA] QTC-SXM KT X20T02/HI", "quadt386sx", MACHINE_TYPE_386SX, CPU_PKG_386SX, 0, 0, 0, 0, 0, 0, 0, MACHINE_AT, 1024, 16384, 128, 127, machine_at_quadt386sx_init, NULL }, + { + .name = "[ISA] QTC-SXM KT X20T02/HI", + .internal_name = "quadt386sx", + .type = MACHINE_TYPE_386SX, + .chipset = MACHINE_CHIPSET_DISCRETE, + .init = machine_at_quadt386sx_init, + .p1_handler = NULL, + .gpio_handler = NULL, + .available_flag = MACHINE_AVAILABLE, + .gpio_acpi_handler = NULL, + .cpu = { + .package = CPU_PKG_386SX, + .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_FLAGS_NONE, + .ram = { + .min = 1024, + .max = 16384, + .step = 128 + }, + .nvrmask = 127, + .kbc_device = NULL, + .kbc_p1 = 0xff, + .gpio = 0xffffffff, + .gpio_acpi = 0xffffffff, + .device = NULL, + .fdc_device = NULL, + .sio_device = NULL, + .vid_device = NULL, + .snd_device = NULL, + .net_device = NULL + }, /* This has an AMIKey-2, which is an updated version of type 'H'. */ - { "[ALi M1217] Acrosser AR-B1374", "arb1374", MACHINE_TYPE_386SX, CPU_PKG_386SX, 0, 0, 0, 0, 0, 0, 0, MACHINE_AT | MACHINE_BUS_PS2 | MACHINE_IDE, 1024, 32768,1024, 127, machine_at_arb1374_init, NULL }, + { + .name = "[ALi M1217] Acrosser AR-B1374", + .internal_name = "arb1374", + .type = MACHINE_TYPE_386SX, + .chipset = MACHINE_CHIPSET_ALI_M1217, + .init = machine_at_arb1374_init, + .p1_handler = NULL, + .gpio_handler = NULL, + .available_flag = MACHINE_AVAILABLE, + .gpio_acpi_handler = NULL, + .cpu = { + .package = CPU_PKG_386SX, + .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 = 1024, + .max = 32768, + .step = 1024 + }, + .nvrmask = 127, + .kbc_device = NULL, + .kbc_p1 = 0xff, + .gpio = 0xffffffff, + .gpio_acpi = 0xffffffff, + .device = NULL, + .fdc_device = NULL, + .sio_device = NULL, + .vid_device = NULL, + .snd_device = NULL, + .net_device = NULL + }, /* Has the AMIKey KBC firmware, which is an updated 'F' type. */ - { "[ALi M1217] AAEON SBC-350A", "sbc350a", MACHINE_TYPE_386SX, CPU_PKG_386SX, 0, 0, 0, 0, 0, 0, 0, MACHINE_AT | MACHINE_BUS_PS2 | MACHINE_IDE, 1024, 16384, 1024, 127, machine_at_sbc350a_init, NULL }, + { + .name = "[ALi M1217] AAEON SBC-350A", + .internal_name = "sbc350a", + .type = MACHINE_TYPE_386SX, + .chipset = MACHINE_CHIPSET_ALI_M1217, + .init = machine_at_sbc350a_init, + .p1_handler = NULL, + .gpio_handler = NULL, + .available_flag = MACHINE_AVAILABLE, + .gpio_acpi_handler = NULL, + .cpu = { + .package = CPU_PKG_386SX, + .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 = 1024, + .max = 16384, + .step = 1024 + }, + .nvrmask = 127, + .kbc_device = NULL, + .kbc_p1 = 0xff, + .gpio = 0xffffffff, + .gpio_acpi = 0xffffffff, + .device = NULL, + .fdc_device = NULL, + .sio_device = NULL, + .vid_device = NULL, + .snd_device = NULL, + .net_device = NULL + }, /* Has an AMI KBC firmware, the only photo of this is too low resolution for me to read what's on the KBC chip, so I'm going to assume AMI 'F' based on the other known HT18 AMI BIOS strings. */ - { "[ALi M1217] Flytech 386", "flytech386", MACHINE_TYPE_386SX, CPU_PKG_386SX, 0, 0, 0, 0, 0, 0, 0, MACHINE_AT | MACHINE_BUS_PS2 | MACHINE_IDE | MACHINE_VIDEO, 1024, 16384, 1024, 127, machine_at_flytech386_init, at_flytech386_get_device }, + { + .name = "[ALi M1217] Flytech 386", + .internal_name = "flytech386", + .type = MACHINE_TYPE_386SX, + .chipset = MACHINE_CHIPSET_ALI_M1217, + .init = machine_at_flytech386_init, + .p1_handler = NULL, + .gpio_handler = NULL, + .available_flag = MACHINE_AVAILABLE, + .gpio_acpi_handler = NULL, + .cpu = { + .package = CPU_PKG_386SX, + .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_PS2, + .flags = MACHINE_IDE | MACHINE_VIDEO, + .ram = { + .min = 1024, + .max = 16384, + .step = 1024 + }, + .nvrmask = 127, + .kbc_device = NULL, + .kbc_p1 = 0xff, + .gpio = 0xffffffff, + .gpio_acpi = 0xffffffff, + .device = NULL, + .fdc_device = NULL, + .sio_device = NULL, + .vid_device = &tvga8900d_device, + .snd_device = NULL, + .net_device = NULL + }, /* I'm going to assume this has a standard/generic IBM-compatible AT KBC firmware until the board is identified. */ - { "[ALi M1217] MR BIOS 386SX clone", "mr1217", MACHINE_TYPE_386SX, CPU_PKG_386SX, 0, 0, 0, 0, 0, 0, 0, MACHINE_AT | MACHINE_BUS_PS2 | MACHINE_IDE | MACHINE_VIDEO, 1024, 16384, 1024, 127, machine_at_mr1217_init, NULL }, + { + .name = "[ALi M1217] MR BIOS 386SX clone", + .internal_name = "mr1217", + .type = MACHINE_TYPE_386SX, + .chipset = MACHINE_CHIPSET_ALI_M1217, + .init = machine_at_mr1217_init, + .p1_handler = NULL, + .gpio_handler = NULL, + .available_flag = MACHINE_AVAILABLE, + .gpio_acpi_handler = NULL, + .cpu = { + .package = CPU_PKG_386SX, + .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 = 1024, + .max = 16384, + .step = 1024 + }, + .nvrmask = 127, + .kbc_device = NULL, + .kbc_p1 = 0xff, + .gpio = 0xffffffff, + .gpio_acpi = 0xffffffff, + .device = NULL, + .fdc_device = NULL, + .sio_device = NULL, + .vid_device = NULL, + .snd_device = NULL, + .net_device = NULL + }, /* Has IBM PS/2 Type 1 KBC firmware. */ - { "[ALi M6117] Acrosser PJ-A511M", "pja511m", MACHINE_TYPE_386SX, CPU_PKG_M6117, 0, 0, 0, 0, 0, 0, 0, MACHINE_AT | MACHINE_BUS_PS2 | MACHINE_IDE, 1024, 32768, 1024, 127, machine_at_pja511m_init, NULL }, + { + .name = "[ALi M6117] Acrosser PJ-A511M", + .internal_name = "pja511m", + .type = MACHINE_TYPE_386SX, + .chipset = MACHINE_CHIPSET_ALI_M6117, + .init = machine_at_pja511m_init, + .p1_handler = NULL, + .gpio_handler = NULL, + .available_flag = MACHINE_AVAILABLE, + .gpio_acpi_handler = NULL, + .cpu = { + .package = CPU_PKG_M6117, + .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_PS2, + .flags = MACHINE_IDE, + .ram = { + .min = 1024, + .max = 32768, + .step = 1024 + }, + .nvrmask = 127, + .kbc_device = NULL, + .kbc_p1 = 0xff, + .gpio = 0xffffffff, + .gpio_acpi = 0xffffffff, + .device = NULL, + .fdc_device = NULL, + .sio_device = NULL, + .vid_device = NULL, + .snd_device = NULL, + .net_device = NULL + }, /* Has IBM PS/2 Type 1 KBC firmware. */ - { "[ALi M6117] Protech ProX-1332", "prox1332", MACHINE_TYPE_386SX, CPU_PKG_M6117, 0, 0, 0, 0, 0, 0, 0, MACHINE_AT | MACHINE_BUS_PS2 | MACHINE_IDE, 1024, 32768, 1024, 127, machine_at_prox1332_init, NULL }, + { + .name = "[ALi M6117] Protech ProX-1332", + .internal_name = "prox1332", + .type = MACHINE_TYPE_386SX, + .chipset = MACHINE_CHIPSET_ALI_M6117, + .init = machine_at_prox1332_init, + .p1_handler = NULL, + .gpio_handler = NULL, + .available_flag = MACHINE_AVAILABLE, + .gpio_acpi_handler = NULL, + .cpu = { + .package = CPU_PKG_M6117, + .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_PS2, + .flags = MACHINE_IDE, + .ram = { + .min = 1024, + .max = 32768, + .step = 1024 + }, + .nvrmask = 127, + .kbc_device = NULL, + .kbc_p1 = 0xff, + .gpio = 0xffffffff, + .gpio_acpi = 0xffffffff, + .device = NULL, + .fdc_device = NULL, + .sio_device = NULL, + .vid_device = NULL, + .snd_device = NULL, + .net_device = NULL + }, /* Has an AMI KBC firmware, the only photo of this is too low resolution for me to read what's on the KBC chip, so I'm going to assume AMI 'F' based on the other known HT18 AMI BIOS strings. */ - { "[HT18] AMA-932J", "ama932j", MACHINE_TYPE_386SX, CPU_PKG_386SX, 0, 0, 0, 0, 0, 0, 0, MACHINE_AT | MACHINE_IDE | MACHINE_VIDEO, 512, 8192, 128, 127, machine_at_ama932j_init, at_ama932j_get_device }, + { + .name = "[HT18] AMA-932J", + .internal_name = "ama932j", + .type = MACHINE_TYPE_386SX, + .chipset = MACHINE_CHIPSET_HT18, + .init = machine_at_ama932j_init, + .p1_handler = NULL, + .gpio_handler = NULL, + .available_flag = MACHINE_AVAILABLE, + .gpio_acpi_handler = NULL, + .cpu = { + .package = CPU_PKG_386SX, + .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 | MACHINE_VIDEO, + .ram = { + .min = 512, + .max = 8192, + .step = 128 + }, + .nvrmask = 127, + .kbc_device = NULL, + .kbc_p1 = 0xff, + .gpio = 0xffffffff, + .gpio_acpi = 0xffffffff, + .device = NULL, + .fdc_device = NULL, + .sio_device = NULL, + .vid_device = &oti067_ama932j_device, + .snd_device = NULL, + .net_device = NULL + }, /* Has an unknown KBC firmware with commands B8 and BB in the style of Phoenix MultiKey and AMIKey-3(!), but also commands E1 and EA with unknown functions. */ - { "[Intel 82335] ADI 386SX", "adi386sx", MACHINE_TYPE_386SX, CPU_PKG_386SX, 0, 0, 0, 0, 0, 0, 0, MACHINE_AT, 512, 8192, 128, 127, machine_at_adi386sx_init, NULL }, + { + .name = "[Intel 82335] ADI 386SX", + .internal_name = "adi386sx", + .type = MACHINE_TYPE_386SX, + .chipset = MACHINE_CHIPSET_INTEL_82335, + .init = machine_at_adi386sx_init, + .p1_handler = NULL, + .gpio_handler = NULL, + .available_flag = MACHINE_AVAILABLE, + .gpio_acpi_handler = NULL, + .cpu = { + .package = CPU_PKG_386SX, + .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_FLAGS_NONE, + .ram = { + .min = 512, + .max = 8192, + .step = 128 + }, + .nvrmask = 127, + .kbc_device = NULL, + .kbc_p1 = 0xff, + .gpio = 0xffffffff, + .gpio_acpi = 0xffffffff, + .device = NULL, + .fdc_device = NULL, + .sio_device = NULL, + .vid_device = NULL, + .snd_device = NULL, + .net_device = NULL + }, /* Has an AMI Keyboard BIOS PLUS KBC firmware ('8'). */ - { "[Intel 82335] Shuttle 386SX", "shuttle386sx", MACHINE_TYPE_386SX, CPU_PKG_386SX, 0, 0, 0, 0, 0, 0, 0, MACHINE_AT, 512, 8192, 128, 127, machine_at_shuttle386sx_init, NULL }, + { .name = "[Intel 82335] Shuttle 386SX", + .internal_name = "shuttle386sx", + .type = MACHINE_TYPE_386SX, + .chipset = MACHINE_CHIPSET_INTEL_82335, + .init = machine_at_shuttle386sx_init, + .p1_handler = NULL, + .gpio_handler = NULL, + .available_flag = MACHINE_AVAILABLE, + .gpio_acpi_handler = NULL, + .cpu = { + .package = CPU_PKG_386SX, + .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_FLAGS_NONE, + .ram = { + .min = 512, + .max = 8192, + .step = 128 + }, + .nvrmask = 127, + .kbc_device = NULL, + .kbc_p1 = 0xff, + .gpio = 0xffffffff, + .gpio_acpi = 0xffffffff, + .device = NULL, + .fdc_device = NULL, + .sio_device = NULL, + .vid_device = NULL, + .snd_device = NULL, + .net_device = NULL + }, /* Uses Commodore (CBM) KBC firmware, to be implemented as identical to the IBM PS/2 Type 1 KBC firmware unless evidence emerges of any proprietary commands. */ - { "[NEAT] Commodore SL386SX-16", "cmdsl386sx16", MACHINE_TYPE_386SX, CPU_PKG_386SX, 0, 0, 0, 0, 0, 0, 0, MACHINE_AT | MACHINE_BUS_PS2 | MACHINE_IDE, 1024, 8192, 512, 127, machine_at_cmdsl386sx16_init, NULL }, + { + .name = "[NEAT] Commodore SL386SX-16", + .internal_name = "cmdsl386sx16", + .type = MACHINE_TYPE_386SX, + .chipset = MACHINE_CHIPSET_NEAT, + .init = machine_at_cmdsl386sx16_init, + .p1_handler = NULL, + .gpio_handler = NULL, + .available_flag = MACHINE_AVAILABLE, + .gpio_acpi_handler = NULL, + .cpu = { + .package = CPU_PKG_386SX, + .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_PS2, + .flags = MACHINE_IDE, + .ram = { + .min = 1024, + .max = 8192, + .step = 512 + }, + .nvrmask = 127, + .kbc_device = NULL, + .kbc_p1 = 0xff, + .gpio = 0xffffffff, + .gpio_acpi = 0xffffffff, + .device = NULL, + .fdc_device = NULL, + .sio_device = NULL, + .vid_device = NULL, + .snd_device = NULL, + .net_device = NULL + }, /* Has IBM AT KBC firmware. */ - { "[NEAT] DTK 386SX clone", "dtk386", MACHINE_TYPE_386SX, CPU_PKG_386SX, 0, 0, 0, 0, 0, 0, 0, MACHINE_AT, 512, 8192, 128, 127, machine_at_neat_init, NULL }, + { + .name = "[NEAT] DTK 386SX clone", + .internal_name = "dtk386", + .type = MACHINE_TYPE_386SX, + .chipset = MACHINE_CHIPSET_NEAT, + .init = machine_at_neat_init, + .p1_handler = NULL, + .gpio_handler = NULL, + .available_flag = MACHINE_AVAILABLE, + .gpio_acpi_handler = NULL, + .cpu = { + .package = CPU_PKG_386SX, + .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_FLAGS_NONE, + .ram = { + .min = 512, + .max = 8192, + .step = 128 + }, + .nvrmask = 127, + .kbc_device = NULL, + .kbc_p1 = 0xff, + .gpio = 0xffffffff, + .gpio_acpi = 0xffffffff, + .device = NULL, + .fdc_device = NULL, + .sio_device = NULL, + .vid_device = NULL, + .snd_device = NULL, + .net_device = NULL + }, /* Has IBM AT KBC firmware. */ - { "[OPTi 291] DTK PPM-3333P", "awardsx", MACHINE_TYPE_386SX, CPU_PKG_386SX, 0, 0, 0, 0, 0, 0, 0, MACHINE_AT, 1024, 16384, 1024, 127, machine_at_awardsx_init, NULL }, + { + .name = "[OPTi 291] DTK PPM-3333P", + .internal_name = "awardsx", + .type = MACHINE_TYPE_386SX, + .chipset = MACHINE_CHIPSET_OPTI_291, + .init = machine_at_awardsx_init, + .p1_handler = NULL, + .gpio_handler = NULL, + .available_flag = MACHINE_AVAILABLE, + .gpio_acpi_handler = NULL, + .cpu = { + .package = CPU_PKG_386SX, + .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_FLAGS_NONE, + .ram = { + .min = 1024, + .max = 16384, + .step = 1024 + }, + .nvrmask = 127, + .kbc_device = NULL, + .kbc_p1 = 0xff, + .gpio = 0xffffffff, + .gpio_acpi = 0xffffffff, + .device = NULL, + .fdc_device = NULL, + .sio_device = NULL, + .vid_device = NULL, + .snd_device = NULL, + .net_device = NULL + }, /* Uses Commodore (CBM) KBC firmware, to be implemented as identical to the IBM PS/2 Type 1 KBC firmware unless evidence emerges of any proprietary commands. */ - { "[SCAMP] Commodore SL386SX-25", "cmdsl386sx25", MACHINE_TYPE_386SX, CPU_PKG_386SX, 0, 0, 0, 0, 0, 0, 0, MACHINE_AT | MACHINE_BUS_PS2 | MACHINE_IDE | MACHINE_VIDEO, 1024, 8192, 512, 127, machine_at_cmdsl386sx25_init, at_cmdsl386sx25_get_device }, + { + .name = "[SCAMP] Commodore SL386SX-25", + .internal_name = "cmdsl386sx25", + .type = MACHINE_TYPE_386SX, + .chipset = MACHINE_CHIPSET_VLSI_SCAMP, + .init = machine_at_cmdsl386sx25_init, + .p1_handler = NULL, + .gpio_handler = NULL, + .available_flag = MACHINE_AVAILABLE, + .gpio_acpi_handler = NULL, + .cpu = { + .package = CPU_PKG_386SX, + .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_PS2, + .flags = MACHINE_IDE | MACHINE_VIDEO, + .ram = { + .min = 1024, + .max = 8192, + .step = 512 + }, + .nvrmask = 127, + .kbc_device = NULL, + .kbc_p1 = 0xff, + .gpio = 0xffffffff, + .gpio_acpi = 0xffffffff, + .device = NULL, + .fdc_device = NULL, + .sio_device = NULL, + .vid_device = &gd5402_onboard_device, + .snd_device = NULL, + .net_device = NULL + }, /* The closest BIOS string I find to this one's, differs only in one part, and ends in -8, so I'm going to assume that this, too, has an AMI '8' (AMI Keyboard BIOS Plus) KBC firmware. */ - { "[SCAMP] DataExpert 386SX", "dataexpert386sx", MACHINE_TYPE_386SX, CPU_PKG_386SX, 0, 10000000, 25000000, 0, 0, 0, 0, MACHINE_AT, 1024, 16384, 1024, 127, machine_at_dataexpert386sx_init, NULL }, + { + .name = "[SCAMP] DataExpert 386SX", + .internal_name = "dataexpert386sx", + .type = MACHINE_TYPE_386SX, + .chipset = MACHINE_CHIPSET_VLSI_SCAMP, + .init = machine_at_dataexpert386sx_init, + .p1_handler = NULL, + .gpio_handler = NULL, + .available_flag = MACHINE_AVAILABLE, + .gpio_acpi_handler = NULL, + .cpu = { + .package = CPU_PKG_386SX, + .block = CPU_BLOCK_NONE, + .min_bus = 10000000, + .max_bus = 25000000, + .min_voltage = 0, + .max_voltage = 0, + .min_multi = 0, + .max_multi = 0 + }, + .bus_flags = MACHINE_AT, + .flags = MACHINE_FLAGS_NONE, + .ram = { + .min = 1024, + .max = 16384, + .step = 1024 + }, + .nvrmask = 127, + .kbc_device = NULL, + .kbc_p1 = 0xff, + .gpio = 0xffffffff, + .gpio_acpi = 0xffffffff, + .device = NULL, + .fdc_device = NULL, + .sio_device = NULL, + .vid_device = NULL, + .snd_device = NULL, + .net_device = NULL + }, /* Has IBM PS/2 Type 1 KBC firmware. */ - { "[SCAMP] Samsung SPC-6033P", "spc6033p", MACHINE_TYPE_386SX, CPU_PKG_386SX, 0, 0, 0, 0, 0, 0, 0, MACHINE_AT | MACHINE_BUS_PS2 | MACHINE_IDE | MACHINE_VIDEO, 2048, 12288, 2048, 127, machine_at_spc6033p_init, at_spc6033p_get_device }, + { + .name = "[SCAMP] Samsung SPC-6033P", + .internal_name = "spc6033p", + .type = MACHINE_TYPE_386SX, + .chipset = MACHINE_CHIPSET_VLSI_SCAMP, + .init = machine_at_spc6033p_init, + .p1_handler = NULL, + .gpio_handler = NULL, + .available_flag = MACHINE_AVAILABLE, + .gpio_acpi_handler = NULL, + .cpu = { + .package = CPU_PKG_386SX, + .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_PS2, + .flags = MACHINE_IDE | MACHINE_VIDEO, + .ram = { + .min = 2048, + .max = 12288, + .step = 2048 + }, + .nvrmask = 127, + .kbc_device = NULL, + .kbc_p1 = 0xff, + .gpio = 0xffffffff, + .gpio_acpi = 0xffffffff, + .device = NULL, + .fdc_device = NULL, + .sio_device = NULL, + .vid_device = &ati28800k_spc6033p_device, + .snd_device = NULL, + .net_device = NULL + }, /* Has an unknown AMI KBC firmware, I'm going to assume 'F' until a photo or real hardware BIOS string is found. */ - { "[SCAT] KMX-C-02", "kmxc02", MACHINE_TYPE_386SX, CPU_PKG_386SX, 0, 0, 0, 0, 0, 0, 0, MACHINE_AT, 512, 16384, 512, 127, machine_at_kmxc02_init, NULL }, + { + .name = "[SCAT] KMX-C-02", + .internal_name = "kmxc02", + .type = MACHINE_TYPE_386SX, + .chipset = MACHINE_CHIPSET_SCAT, + .init = machine_at_kmxc02_init, + .p1_handler = NULL, + .gpio_handler = NULL, + .available_flag = MACHINE_AVAILABLE, + .gpio_acpi_handler = NULL, + .cpu = { + .package = CPU_PKG_386SX, + .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_FLAGS_NONE, + .ram = { + .min = 512, + .max = 16384, + .step = 512 + }, + .nvrmask = 127, + .kbc_device = NULL, + .kbc_p1 = 0xff, + .gpio = 0xffffffff, + .gpio_acpi = 0xffffffff, + .device = NULL, + .fdc_device = NULL, + .sio_device = NULL, + .vid_device = NULL, + .snd_device = NULL, + .net_device = NULL + }, /* Has Quadtel KBC firmware. */ - { "[WD76C10] Amstrad MegaPC", "megapc", MACHINE_TYPE_386SX, CPU_PKG_386SX, 0, 0, 0, 0, 0, 0, 0, MACHINE_AT | MACHINE_BUS_PS2 | MACHINE_IDE | MACHINE_VIDEO, 1024, 32768, 1024, 127, machine_at_wd76c10_init, NULL }, + { + .name = "[WD76C10] Amstrad MegaPC", + .internal_name = "megapc", + .type = MACHINE_TYPE_386SX, + .chipset = MACHINE_CHIPSET_WD76C10, + .init = machine_at_wd76c10_init, + .p1_handler = NULL, + .gpio_handler = NULL, + .available_flag = MACHINE_AVAILABLE, + .gpio_acpi_handler = NULL, + .cpu = { + .package = CPU_PKG_386SX, + .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_PS2, + .flags = MACHINE_IDE | MACHINE_VIDEO, + .ram = { + .min = 1024, + .max = 32768, + .step = 1024 + }, + .nvrmask = 127, + .kbc_device = NULL, + .kbc_p1 = 0xff, + .gpio = 0xffffffff, + .gpio_acpi = 0xffffffff, + .device = NULL, + .fdc_device = NULL, + .sio_device = NULL, + .vid_device = NULL, + .snd_device = NULL, + .net_device = NULL + }, /* 386SX machines which utilize the MCA bus */ /* Has IBM PS/2 Type 1 KBC firmware. */ - { "[MCA] IBM PS/2 model 55SX", "ibmps2_m55sx", MACHINE_TYPE_386SX, CPU_PKG_386SX, 0, 0, 0, 0, 0, 0, 0, MACHINE_MCA | MACHINE_BUS_PS2 | MACHINE_VIDEO, 1024, 8192, 1024, 63, machine_ps2_model_55sx_init, NULL }, + { + .name = "[MCA] IBM PS/2 model 55SX", + .internal_name = "ibmps2_m55sx", + .type = MACHINE_TYPE_386SX, + .chipset = MACHINE_CHIPSET_PROPRIETARY, + .init = machine_ps2_model_55sx_init, + .p1_handler = NULL, + .gpio_handler = NULL, + .available_flag = MACHINE_AVAILABLE, + .gpio_acpi_handler = NULL, + .cpu = { + .package = CPU_PKG_386SX, + .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_PS2_MCA, + .flags = MACHINE_VIDEO, + .ram = { + .min = 1024, + .max = 8192, + .step = 1024 + }, + .nvrmask = 63, + .kbc_device = NULL, + .kbc_p1 = 0xff, + .gpio = 0xffffffff, + .gpio_acpi = 0xffffffff, + .device = NULL, + .fdc_device = NULL, + .sio_device = NULL, + .vid_device = NULL, + .snd_device = NULL, + .net_device = NULL + }, + /* Has IBM PS/2 Type 1 KBC firmware. */ + { + .name = "[MCA] IBM PS/2 model 65SX", + .internal_name = "ibmps2_m65sx", + .type = MACHINE_TYPE_386SX, + .chipset = MACHINE_CHIPSET_PROPRIETARY, + .init = machine_ps2_model_65sx_init, + .p1_handler = NULL, + .gpio_handler = NULL, + .available_flag = MACHINE_AVAILABLE, + .gpio_acpi_handler = NULL, + .cpu = { + .package = CPU_PKG_386SX, + .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_PS2_MCA, + .flags = MACHINE_VIDEO, + .ram = { + .min = 1024, + .max = 8192, + .step = 1024 + }, + .nvrmask = 63, + .kbc_device = NULL, + .kbc_p1 = 0xff, + .gpio = 0xffffffff, + .gpio_acpi = 0xffffffff, + .device = NULL, + .fdc_device = NULL, + .sio_device = NULL, + .vid_device = NULL, + .snd_device = NULL, + .net_device = NULL + }, /* 486SLC machines */ /* 486SLC machines with just the ISA slot */ /* Has AMIKey H KBC firmware. */ - { "[OPTi 283] RYC Leopard LX", "rycleopardlx", MACHINE_TYPE_486SLC, CPU_PKG_486SLC_IBM, 0, 0, 0, 0, 0, 0, 0, MACHINE_AT, 1024, 16384, 1024, 127, machine_at_rycleopardlx_init, NULL }, + { + .name = "[OPTi 283] RYC Leopard LX", + .internal_name = "rycleopardlx", + .type = MACHINE_TYPE_486SLC, + .chipset = MACHINE_CHIPSET_OPTI_283, + .init = machine_at_rycleopardlx_init, + .p1_handler = NULL, + .gpio_handler = NULL, + .available_flag = MACHINE_AVAILABLE, + .gpio_acpi_handler = NULL, + .cpu = { + .package = CPU_PKG_486SLC_IBM, + .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_APM, + .ram = { + .min = 1024, + .max = 16384, + .step = 1024 + }, + .nvrmask = 127, + .kbc_device = NULL, + .kbc_p1 = 0xff, + .gpio = 0xffffffff, + .gpio_acpi = 0xffffffff, + .device = NULL, + .fdc_device = NULL, + .sio_device = NULL, + .vid_device = NULL, + .snd_device = NULL, + .net_device = NULL + }, /* 386DX machines */ - { "[ACC 2168] AMI 386DX clone", "acc386", MACHINE_TYPE_386DX, CPU_PKG_386DX, 0, 0, 0, 0, 0, 0, 0, MACHINE_AT, 1024, 16384, 1024, 127, machine_at_acc386_init, NULL }, + { + .name = "[ACC 2168] AMI 386DX clone", + .internal_name = "acc386", + .type = MACHINE_TYPE_386DX, + .chipset = MACHINE_CHIPSET_ACC_2168, + .init = machine_at_acc386_init, + .p1_handler = NULL, + .gpio_handler = NULL, + .available_flag = MACHINE_AVAILABLE, + .gpio_acpi_handler = NULL, + .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_APM, + .ram = { + .min = 1024, + .max = 16384, + .step = 1024 + }, + .nvrmask = 127, + .kbc_device = NULL, + .kbc_p1 = 0xff, + .gpio = 0xffffffff, + .gpio_acpi = 0xffffffff, + .device = NULL, + .fdc_device = NULL, + .sio_device = NULL, + .vid_device = NULL, + .snd_device = NULL, + .net_device = NULL + }, /* Has an AMI Keyboard BIOS PLUS KBC firmware ('8'). */ - { "[C&T 386] ECS 386/32", "ecs386", MACHINE_TYPE_386DX, CPU_PKG_386DX, 0, 0, 0, 0, 0, 0, 0, MACHINE_AT, 1024, 16384, 1024, 127, machine_at_ecs386_init, NULL }, + { + .name = "[C&T 386] ECS 386/32", + .internal_name = "ecs386", + .type = MACHINE_TYPE_386DX, + .chipset = MACHINE_CHIPSET_CT_386, + .init = machine_at_ecs386_init, + .p1_handler = NULL, + .gpio_handler = NULL, + .available_flag = MACHINE_AVAILABLE, + .gpio_acpi_handler = NULL, + .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_APM, + .ram = { + .min = 1024, + .max = 16384, + .step = 1024 + }, + .nvrmask = 127, + .kbc_device = NULL, + .kbc_p1 = 0xff, + .gpio = 0xffffffff, + .gpio_acpi = 0xffffffff, + .device = NULL, + .fdc_device = NULL, + .sio_device = NULL, + .vid_device = NULL, + .snd_device = NULL, + .net_device = NULL + }, /* Has IBM AT KBC firmware. */ - { "[C&T 386] Samsung SPC-6000A", "spc6000a", MACHINE_TYPE_386DX, CPU_PKG_386DX, 0, 0, 0, 0, 0, 0, 0, MACHINE_AT | MACHINE_IDE, 1024, 32768, 1024, 127, machine_at_spc6000a_init, NULL }, + { + .name = "[C&T 386] Samsung SPC-6000A", + .internal_name = "spc6000a", + .type = MACHINE_TYPE_386DX, + .chipset = MACHINE_CHIPSET_CT_386, + .init = machine_at_spc6000a_init, + .p1_handler = NULL, + .gpio_handler = NULL, + .available_flag = MACHINE_AVAILABLE, + .gpio_acpi_handler = NULL, + .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_APM, + .ram = { + .min = 1024, + .max = 32768, + .step = 1024 + }, + .nvrmask = 127, + .kbc_device = NULL, + .kbc_p1 = 0xff, + .gpio = 0xffffffff, + .gpio_acpi = 0xffffffff, + .device = NULL, + .fdc_device = NULL, + .sio_device = NULL, + .vid_device = NULL, + .snd_device = NULL, + .net_device = NULL + }, /* Uses Compaq KBC firmware. */ - { "[ISA] Compaq Portable III (386)", "portableiii386", MACHINE_TYPE_386DX, CPU_PKG_386DX, 0, 0, 0, 0, 0, 0, 0, MACHINE_AT | MACHINE_IDE | MACHINE_VIDEO, 1024, 14336, 1024, 127, machine_at_portableiii386_init, at_cpqiii_get_device }, + { + .name = "[ISA] Compaq Deskpro 386 (September 1986)", + .internal_name = "deskpro386", + .type = MACHINE_TYPE_386DX, + .chipset = MACHINE_CHIPSET_DISCRETE, + .init = machine_at_deskpro386_init, + .p1_handler = NULL, + .gpio_handler = NULL, + .available_flag = MACHINE_AVAILABLE, + .gpio_acpi_handler = NULL, + .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 = 1024, + .max = 16384, + .step = 1024 + }, + .nvrmask = 63, + .kbc_device = NULL, + .kbc_p1 = 0xff, + .gpio = 0xffffffff, + .gpio_acpi = 0xffffffff, + .device = NULL, + .fdc_device = NULL, + .sio_device = NULL, + .vid_device = NULL, + .snd_device = NULL, + .net_device = NULL + }, + { + .name = "[ISA] Compaq Deskpro 386 (May 1988)", + .internal_name = "deskpro386_05_1988", + .type = MACHINE_TYPE_386DX, + .chipset = MACHINE_CHIPSET_DISCRETE, + .init = machine_at_deskpro386_05_1988_init, + .p1_handler = NULL, + .gpio_handler = NULL, + .available_flag = MACHINE_AVAILABLE, + .gpio_acpi_handler = NULL, + .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 = 1024, + .max = 16384, + .step = 1024 + }, + .nvrmask = 63, + .kbc_device = NULL, + .kbc_p1 = 0xff, + .gpio = 0xffffffff, + .gpio_acpi = 0xffffffff, + .device = NULL, + .fdc_device = NULL, + .sio_device = NULL, + .vid_device = NULL, + .snd_device = NULL, + .net_device = NULL + }, + { + .name = "[ISA] Compaq Portable III (386)", + .internal_name = "portableiii386", + .type = MACHINE_TYPE_386DX, + .chipset = MACHINE_CHIPSET_DISCRETE, + .init = machine_at_portableiii386_init, + .p1_handler = NULL, + .gpio_handler = NULL, + .available_flag = MACHINE_AVAILABLE, + .gpio_acpi_handler = NULL, + .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 | MACHINE_VIDEO, + .ram = { + .min = 1024, + .max = 14336, + .step = 1024 + }, + .nvrmask = 127, + .kbc_device = NULL, + .kbc_p1 = 0xff, + .gpio = 0xffffffff, + .gpio_acpi = 0xffffffff, + .device = NULL, + .fdc_device = NULL, + .sio_device = NULL, + .vid_device = &compaq_plasma_device, + .snd_device = NULL, + .net_device = NULL + }, /* Has IBM AT KBC firmware. */ - { "[ISA] Micronics 09-00021", "micronics386", MACHINE_TYPE_386DX, CPU_PKG_386DX, 0, 0, 0, 0, 0, 0, 0, MACHINE_AT, 512, 8192, 128, 127, machine_at_micronics386_init, NULL }, + { + .name = "[ISA] Micronics 09-00021", + .internal_name = "micronics386", + .type = MACHINE_TYPE_386DX, + .chipset = MACHINE_CHIPSET_DISCRETE, + .init = machine_at_micronics386_init, + .p1_handler = NULL, + .gpio_handler = NULL, + .available_flag = MACHINE_AVAILABLE, + .gpio_acpi_handler = NULL, + .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_APM, + .ram = { + .min = 512, + .max = 8192, + .step = 128 + }, + .nvrmask = 127, + .kbc_device = NULL, + .kbc_p1 = 0xff, + .gpio = 0xffffffff, + .gpio_acpi = 0xffffffff, + .device = NULL, + .fdc_device = NULL, + .sio_device = NULL, + .vid_device = NULL, + .snd_device = NULL, + .net_device = NULL + }, /* Has AMIKey F KBC firmware. */ - { "[SiS 310] ASUS ISA-386C", "asus386", MACHINE_TYPE_386DX, CPU_PKG_386DX, 0, 0, 0, 0, 0, 0, 0, MACHINE_AT, 1024, 65536, 1024, 127, machine_at_asus386_init, NULL }, + { + .name = "[SiS 310] ASUS ISA-386C", + .internal_name = "asus386", + .type = MACHINE_TYPE_386DX, + .chipset = MACHINE_CHIPSET_SIS_310, + .init = machine_at_asus386_init, + .p1_handler = NULL, + .gpio_handler = NULL, + .available_flag = MACHINE_AVAILABLE, + .gpio_acpi_handler = NULL, + .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_APM, + .ram = { + .min = 1024, + .max = 65536, + .step = 1024 + }, + .nvrmask = 127, + .kbc_device = NULL, + .kbc_p1 = 0xff, + .gpio = 0xffffffff, + .gpio_acpi = 0xffffffff, + .device = NULL, + .fdc_device = NULL, + .sio_device = NULL, + .vid_device = NULL, + .snd_device = NULL, + .net_device = NULL + }, /* 386DX machines which utilize the MCA bus */ /* Has IBM PS/2 Type 1 KBC firmware. */ - { "[MCA] IBM PS/2 model 70 (type 3)", "ibmps2_m70_type3", MACHINE_TYPE_386DX, CPU_PKG_386DX | CPU_PKG_486BL, 0, 0, 0, 0, 0, 0, 0, MACHINE_MCA | MACHINE_BUS_PS2 | MACHINE_VIDEO, 2048, 65536, 2048, 63, machine_ps2_model_70_type3_init, NULL }, - /* Has IBM PS/2 Type 1 KBC firmware. */ - { "[MCA] IBM PS/2 model 80 (type 2)", "ibmps2_m80", MACHINE_TYPE_386DX, CPU_PKG_386DX | CPU_PKG_486BL | CPU_PKG_SOCKET1, 0, 0, 0, 0, 0, 0, 0, MACHINE_MCA | MACHINE_BUS_PS2 | MACHINE_VIDEO, 1024, 65536, 1024, 63, machine_ps2_model_80_init, NULL }, - /* Has IBM PS/2 Type 1 KBC firmware. */ - { "[MCA] IBM PS/2 model 80 (type 3)", "ibmps2_m80_type3", MACHINE_TYPE_386DX, CPU_PKG_386DX | CPU_PKG_486BL | CPU_PKG_SOCKET1, 0, 0, 0, 0, 0, 0, 0, MACHINE_MCA | MACHINE_BUS_PS2 | MACHINE_VIDEO, 2048, 65536, 2048, 63, machine_ps2_model_80_axx_init, NULL }, + { + .name = "[MCA] IBM PS/2 model 80 (type 2)", + .internal_name = "ibmps2_m80", + .type = MACHINE_TYPE_386DX, + .chipset = MACHINE_CHIPSET_PROPRIETARY, + .init = machine_ps2_model_80_init, + .p1_handler = NULL, + .gpio_handler = NULL, + .available_flag = MACHINE_AVAILABLE, + .gpio_acpi_handler = NULL, + .cpu = { + .package = CPU_PKG_386DX | CPU_PKG_486BL, + .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_PS2_MCA, + .flags = MACHINE_VIDEO | MACHINE_APM, + .ram = { + .min = 1024, + .max = 65536, + .step = 1024 + }, + .nvrmask = 63, + .kbc_device = NULL, + .kbc_p1 = 0xff, + .gpio = 0xffffffff, + .gpio_acpi = 0xffffffff, + .device = NULL, + .fdc_device = NULL, + .sio_device = NULL, + .vid_device = NULL, + .snd_device = NULL, + .net_device = NULL + }, /* 386DX/486 machines */ /* The BIOS sends commands C9 without a parameter and D5, both of which are Phoenix MultiKey commands. */ - { "[OPTi 495] Award 486 clone", "award495", MACHINE_TYPE_386DX_486, CPU_PKG_386DX | CPU_PKG_SOCKET1, 0, 0, 0, 0, 0, 0, 0, MACHINE_VLB | MACHINE_IDE, 1024, 32768, 1024, 127, machine_at_opti495_init, NULL }, + { + .name = "[OPTi 495] Award 486 clone", + .internal_name = "award495", + .type = MACHINE_TYPE_386DX_486, + .chipset = MACHINE_CHIPSET_OPTI_495, + .init = machine_at_opti495_init, + .p1_handler = NULL, + .gpio_handler = NULL, + .available_flag = MACHINE_AVAILABLE, + .gpio_acpi_handler = NULL, + .cpu = { + .package = CPU_PKG_386DX | CPU_PKG_SOCKET1, + .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_VLB, + .flags = MACHINE_IDE | MACHINE_APM, + .ram = { + .min = 1024, + .max = 32768, + .step = 1024 + }, + .nvrmask = 127, + .kbc_device = NULL, + .kbc_p1 = 0xff, + .gpio = 0xffffffff, + .gpio_acpi = 0xffffffff, + .device = NULL, + .fdc_device = NULL, + .sio_device = NULL, + .vid_device = NULL, + .snd_device = NULL, + .net_device = NULL + }, /* Has AMIKey F KBC firmware. */ - { "[OPTi 495] DataExpert SX495", "ami495", MACHINE_TYPE_386DX_486, CPU_PKG_386DX | CPU_PKG_SOCKET1, 0, 0, 0, 0, 0, 0, 0, MACHINE_VLB | MACHINE_IDE, 1024, 32768, 1024, 127, machine_at_opti495_ami_init, NULL }, + { + .name = "[OPTi 495] DataExpert SX495", + .internal_name = "ami495", + .type = MACHINE_TYPE_386DX_486, + .chipset = MACHINE_CHIPSET_OPTI_495, + .init = machine_at_opti495_ami_init, + .p1_handler = NULL, + .gpio_handler = NULL, + .available_flag = MACHINE_AVAILABLE, + .gpio_acpi_handler = NULL, + .cpu = { + .package = CPU_PKG_386DX | CPU_PKG_SOCKET1, + .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_VLB, + .flags = MACHINE_IDE | MACHINE_APM, + .ram = { + .min = 1024, + .max = 32768, + .step = 1024 + }, + .nvrmask = 127, + .kbc_device = NULL, + .kbc_p1 = 0xff, + .gpio = 0xffffffff, + .gpio_acpi = 0xffffffff, + .device = NULL, + .fdc_device = NULL, + .sio_device = NULL, + .vid_device = NULL, + .snd_device = NULL, + .net_device = NULL + }, /* Has AMIKey F KBC firmware (it's just the MR BIOS for the above machine). */ - { "[OPTi 495] DataExpert SX495 (MR BIOS)", "mr495", MACHINE_TYPE_386DX_486, CPU_PKG_386DX | CPU_PKG_SOCKET3, 0, 0, 0, 0, 0, 0, 0, MACHINE_VLB | MACHINE_IDE, 1024, 32768, 1024, 127, machine_at_opti495_mr_init, NULL }, + { + .name = "[OPTi 495] DataExpert SX495 (MR BIOS)", + .internal_name = "mr495", + .type = MACHINE_TYPE_386DX_486, + .chipset = MACHINE_CHIPSET_OPTI_495, + .init = machine_at_opti495_mr_init, + .p1_handler = NULL, + .gpio_handler = NULL, + .available_flag = MACHINE_AVAILABLE, + .gpio_acpi_handler = NULL, + .cpu = { + .package = CPU_PKG_386DX | CPU_PKG_SOCKET1, + .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_VLB, + .flags = MACHINE_IDE | MACHINE_APM, + .ram = { + .min = 1024, + .max = 32768, + .step = 1024 + }, + .nvrmask = 127, + .kbc_device = NULL, + .kbc_p1 = 0xff, + .gpio = 0xffffffff, + .gpio_acpi = 0xffffffff, + .device = NULL, + .fdc_device = NULL, + .sio_device = NULL, + .vid_device = NULL, + .snd_device = NULL, + .net_device = NULL + }, + /* Has IBM PS/2 Type 1 KBC firmware. */ + { + .name = "[MCA] IBM PS/2 model 70 (type 3)", + .internal_name = "ibmps2_m70_type3", + .type = MACHINE_TYPE_386DX_486, + .chipset = MACHINE_CHIPSET_PROPRIETARY, + .init = machine_ps2_model_70_type3_init, + .p1_handler = NULL, + .gpio_handler = NULL, + .available_flag = MACHINE_AVAILABLE, + .gpio_acpi_handler = NULL, + .cpu = { + .package = CPU_PKG_386DX | CPU_PKG_486BL | CPU_PKG_SOCKET1, + .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_PS2_MCA, + .flags = MACHINE_VIDEO | MACHINE_APM, + .ram = { + .min = 2048, + .max = 65536, + .step = 2048 + }, + .nvrmask = 63, + .kbc_device = NULL, + .kbc_p1 = 0xff, + .gpio = 0xffffffff, + .gpio_acpi = 0xffffffff, + .device = NULL, + .fdc_device = NULL, + .sio_device = NULL, + .vid_device = NULL, + .snd_device = NULL, + .net_device = NULL + }, + /* Has IBM PS/2 Type 1 KBC firmware. */ + { + .name = "[MCA] IBM PS/2 model 80 (type 3)", + .internal_name = "ibmps2_m80_type3", + .type = MACHINE_TYPE_386DX_486, + .chipset = MACHINE_CHIPSET_PROPRIETARY, + .init = machine_ps2_model_80_axx_init, + .p1_handler = NULL, + .gpio_handler = NULL, + .available_flag = MACHINE_AVAILABLE, + .gpio_acpi_handler = NULL, + .cpu = { + .package = CPU_PKG_386DX | CPU_PKG_486BL | CPU_PKG_SOCKET1, + .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_PS2_MCA, + .flags = MACHINE_VIDEO | MACHINE_APM, + .ram = { + .min = 2048, + .max = 65536, + .step = 2048 + }, + .nvrmask = 63, + .kbc_device = NULL, + .kbc_p1 = 0xff, + .gpio = 0xffffffff, + .gpio_acpi = 0xffffffff, + .device = NULL, + .fdc_device = NULL, + .sio_device = NULL, + .vid_device = NULL, + .snd_device = NULL, + .net_device = NULL + }, /* 486 machines - Socket 1 */ /* Has JetKey 5 KBC Firmware which looks like it is a clone of AMIKey type F. @@ -330,161 +5233,2486 @@ const machine_t machines[] = { supposedly sends command EF. The board was also seen in 2003 with a -H string - perhaps someone swapped the KBC? */ - { "[ALi M1429] Olystar LIL1429", "ali1429", MACHINE_TYPE_486, CPU_PKG_SOCKET1, 0, 0, 0, 0, 0, 0, 0, MACHINE_VLB | MACHINE_IDE, 1024, 32768, 1024, 127, machine_at_ali1429_init, NULL }, + { + .name = "[ALi M1429] Olystar LIL1429", + .internal_name = "ali1429", + .type = MACHINE_TYPE_486, + .chipset = MACHINE_CHIPSET_ALI_M1429, + .init = machine_at_ali1429_init, + .p1_handler = NULL, + .gpio_handler = NULL, + .available_flag = MACHINE_AVAILABLE, + .gpio_acpi_handler = NULL, + .cpu = { + .package = CPU_PKG_SOCKET1, + .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_VLB, + .flags = MACHINE_IDE | MACHINE_APM, + .ram = { + .min = 1024, + .max = 32768, + .step = 1024 + }, + .nvrmask = 127, + .kbc_device = NULL, + .kbc_p1 = 0xff, + .gpio = 0xffffffff, + .gpio_acpi = 0xffffffff, + .device = NULL, + .fdc_device = NULL, + .sio_device = NULL, + .vid_device = NULL, + .snd_device = NULL, + .net_device = NULL + }, /* Has JetKey 5 KBC Firmware - but the BIOS string ends in a hardcoded -F, and the BIOS also explicitly expects command A1 to return a 'F', so it looks like the JetKey 5 is a clone of AMIKey type F. */ - { "[CS4031] AMI 486 CS4031", "cs4031", MACHINE_TYPE_486, CPU_PKG_SOCKET1, 0, 0, 0, 0, 0, 0, 0, MACHINE_VLB, 1024, 65536, 1024, 127, machine_at_cs4031_init, NULL }, + { + .name = "[CS4031] AMI 486 CS4031", + .internal_name = "cs4031", + .type = MACHINE_TYPE_486, + .chipset = MACHINE_CHIPSET_CT_CS4031, + .init = machine_at_cs4031_init, + .p1_handler = NULL, + .gpio_handler = NULL, + .available_flag = MACHINE_AVAILABLE, + .gpio_acpi_handler = NULL, + .cpu = { + .package = CPU_PKG_SOCKET1, + .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_VLB, + .flags = MACHINE_APM, + .ram = { + .min = 1024, + .max = 65536, + .step = 1024 + }, + .nvrmask = 127, + .kbc_device = NULL, + .kbc_p1 = 0xff, + .gpio = 0xffffffff, + .gpio_acpi = 0xffffffff, + .device = NULL, + .fdc_device = NULL, + .sio_device = NULL, + .vid_device = NULL, + .snd_device = NULL, + .net_device = NULL + }, /* Uses some variant of Phoenix MultiKey/42 as the Intel 8242 chip has a Phoenix copyright. */ - { "[OPTi 895] Mylex MVI486", "mvi486", MACHINE_TYPE_486, CPU_PKG_SOCKET1, 0, 0, 0, 0, 0, 0, 0, MACHINE_VLB | MACHINE_IDE_DUAL, 1024, 65536, 1024, 127, machine_at_mvi486_init, NULL }, + { + .name = "[OPTi 895] Mylex MVI486", + .internal_name = "mvi486", + .type = MACHINE_TYPE_486, + .chipset = MACHINE_CHIPSET_OPTI_895_802G, + .init = machine_at_mvi486_init, + .p1_handler = NULL, + .gpio_handler = NULL, + .available_flag = MACHINE_AVAILABLE, + .gpio_acpi_handler = NULL, + .cpu = { + .package = CPU_PKG_SOCKET1, + .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_VLB, + .flags = MACHINE_IDE_DUAL | MACHINE_APM, + .ram = { + .min = 1024, + .max = 65536, + .step = 1024 + }, + .nvrmask = 127, + .kbc_device = NULL, + .kbc_p1 = 0xff, + .gpio = 0xffffffff, + .gpio_acpi = 0xffffffff, + .device = NULL, + .fdc_device = NULL, + .sio_device = NULL, + .vid_device = NULL, + .snd_device = NULL, + .net_device = NULL + }, /* Has AMI KF KBC firmware. */ - { "[SiS 401] ASUS ISA-486", "isa486", MACHINE_TYPE_486, CPU_PKG_SOCKET1, 0, 0, 0, 0, 0, 0, 0, MACHINE_AT | MACHINE_IDE, 1024, 65536, 1024, 127, machine_at_isa486_init, NULL }, + { + .name = "[SiS 401] ASUS ISA-486", + .internal_name = "isa486", + .type = MACHINE_TYPE_486, + .chipset = MACHINE_CHIPSET_SIS_401, + .init = machine_at_isa486_init, + .p1_handler = NULL, + .gpio_handler = NULL, + .available_flag = MACHINE_AVAILABLE, + .gpio_acpi_handler = NULL, + .cpu = { + .package = CPU_PKG_SOCKET1, + .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 | MACHINE_APM, + .ram = { + .min = 1024, + .max = 65536, + .step = 1024 + }, + .nvrmask = 127, + .kbc_device = NULL, + .kbc_p1 = 0xff, + .gpio = 0xffffffff, + .gpio_acpi = 0xffffffff, + .device = NULL, + .fdc_device = NULL, + .sio_device = NULL, + .vid_device = NULL, + .snd_device = NULL, + .net_device = NULL + }, /* Has AMIKey H KBC firmware, per the screenshot in "How computers & MS-DOS work". */ - { "[SiS 401] Chaintech 433SC", "sis401", MACHINE_TYPE_486, CPU_PKG_SOCKET1, 0, 0, 0, 0, 0, 0, 0, MACHINE_AT | MACHINE_IDE, 1024, 65536, 1024, 127, machine_at_sis401_init, NULL }, + { + .name = "[SiS 401] Chaintech 433SC", + .internal_name = "sis401", + .type = MACHINE_TYPE_486, + .chipset = MACHINE_CHIPSET_SIS_401, + .init = machine_at_sis401_init, + .p1_handler = NULL, + .gpio_handler = NULL, + .available_flag = MACHINE_AVAILABLE, + .gpio_acpi_handler = NULL, + .cpu = { + .package = CPU_PKG_SOCKET1, + .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 | MACHINE_APM, + .ram = { + .min = 1024, + .max = 65536, + .step = 1024 + }, + .nvrmask = 127, + .kbc_device = NULL, + .kbc_p1 = 0xff, + .gpio = 0xffffffff, + .gpio_acpi = 0xffffffff, + .device = NULL, + .fdc_device = NULL, + .sio_device = NULL, + .vid_device = NULL, + .snd_device = NULL, + .net_device = NULL + }, /* Has AMIKey F KBC firmware, per a photo of a monitor with the BIOS screen on eBay. */ - { "[SiS 460] ABIT AV4", "av4", MACHINE_TYPE_486, CPU_PKG_SOCKET1, 0, 0, 0, 0, 0, 0, 0, MACHINE_VLB | MACHINE_IDE, 1024, 65536, 1024, 127, machine_at_av4_init, NULL }, + { + .name = "[SiS 460] ABIT AV4", + .internal_name = "av4", + .type = MACHINE_TYPE_486, + .chipset = MACHINE_CHIPSET_SIS_460, + .init = machine_at_av4_init, + .p1_handler = NULL, + .gpio_handler = NULL, + .available_flag = MACHINE_AVAILABLE, + .gpio_acpi_handler = NULL, + .cpu = { + .package = CPU_PKG_SOCKET1, + .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_VLB, + .flags = MACHINE_IDE | MACHINE_APM, + .ram = { + .min = 1024, + .max = 65536, + .step = 1024 + }, + .nvrmask = 127, + .kbc_device = NULL, + .kbc_p1 = 0xff, + .gpio = 0xffffffff, + .gpio_acpi = 0xffffffff, + .device = NULL, + .fdc_device = NULL, + .sio_device = NULL, + .vid_device = NULL, + .snd_device = NULL, + .net_device = NULL + }, /* Has a MR (!) KBC firmware, which is a clone of the standard IBM PS/2 KBC firmware. */ - { "[SiS 471] SiS VL-BUS 471 REV. A1", "px471", MACHINE_TYPE_486, CPU_PKG_SOCKET1, 0, 0, 0, 0, 0, 0, 0, MACHINE_VLB | MACHINE_IDE, 1024,131072, 1024, 127, machine_at_px471_init, NULL }, + { + .name = "[SiS 471] SiS VL-BUS 471 REV. A1", + .internal_name = "px471", + .type = MACHINE_TYPE_486, + .chipset = MACHINE_CHIPSET_SIS_471, + .init = machine_at_px471_init, + .p1_handler = NULL, + .gpio_handler = NULL, + .available_flag = MACHINE_AVAILABLE, + .gpio_acpi_handler = NULL, + .cpu = { + .package = CPU_PKG_SOCKET1, + .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_VLB, + .flags = MACHINE_IDE | MACHINE_APM, + .ram = { + .min = 1024, + .max = 131072, + .step = 1024 + }, + .nvrmask = 127, + .kbc_device = NULL, + .kbc_p1 = 0xff, + .gpio = 0xffffffff, + .gpio_acpi = 0xffffffff, + .device = NULL, + .fdc_device = NULL, + .sio_device = NULL, + .vid_device = NULL, + .snd_device = NULL, + .net_device = NULL + }, /* The chip is a Lance LT38C41, a clone of the Intel 8041, and the BIOS sends commands BC, BD, and C9 which exist on both AMIKey and Phoenix MultiKey/42, but it does not write a byte after C9, which is consistent with AMIKey, so this must have some form of AMIKey. */ - { "[VIA VT82C495] FIC 486-VC-HD", "486vchd", MACHINE_TYPE_486, CPU_PKG_SOCKET1, 0, 0, 0, 0, 0, 0, 0, MACHINE_AT, 1024, 64512, 1024, 127, machine_at_486vchd_init, NULL }, + { + .name = "[VIA VT82C495] FIC 486-VC-HD", + .internal_name = "486vchd", + .type = MACHINE_TYPE_486, + .chipset = MACHINE_CHIPSET_VIA_VT82C495, + .init = machine_at_486vchd_init, + .p1_handler = NULL, + .gpio_handler = NULL, + .available_flag = MACHINE_AVAILABLE, + .gpio_acpi_handler = NULL, + .cpu = { + .package = CPU_PKG_SOCKET1, + .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_APM, + .ram = { + .min = 1024, + .max = 64512, + .step = 1024 + }, + .nvrmask = 127, + .kbc_device = NULL, + .kbc_p1 = 0xff, + .gpio = 0xffffffff, + .gpio_acpi = 0xffffffff, + .device = NULL, + .fdc_device = NULL, + .sio_device = NULL, + .vid_device = NULL, + .snd_device = NULL, + .net_device = NULL + }, /* According to Deksor on the Win3x.org forum, the BIOS string ends in a -0, indicating an unknown KBC firmware. But it does send the AMIKey get version command, so it must expect an AMIKey. */ - { "[VLSI 82C480] HP Vectra 486VL", "vect486vl", MACHINE_TYPE_486, CPU_PKG_SOCKET1, 0, 0, 0, 0, 0, 0, 0, MACHINE_AT | MACHINE_BUS_PS2 | MACHINE_IDE | MACHINE_VIDEO, 2048, 32768, 2048, 127, machine_at_vect486vl_init, at_vect486vl_get_device }, + { + .name = "[VLSI 82C480] HP Vectra 486VL", + .internal_name = "vect486vl", + .type = MACHINE_TYPE_486, + .chipset = MACHINE_CHIPSET_VLSI_VL82C480, + .init = machine_at_vect486vl_init, + .p1_handler = NULL, + .gpio_handler = NULL, + .available_flag = MACHINE_AVAILABLE, + .gpio_acpi_handler = NULL, + .cpu = { + .package = CPU_PKG_SOCKET1, + .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_PS2, + .flags = MACHINE_IDE | MACHINE_VIDEO | MACHINE_APM, + .ram = { + .min = 2048, + .max = 32768, + .step = 2048 + }, + .nvrmask = 127, + .kbc_device = NULL, + .kbc_p1 = 0xff, + .gpio = 0xffffffff, + .gpio_acpi = 0xffffffff, + .device = NULL, + .fdc_device = NULL, + .sio_device = NULL, + .vid_device = &gd5428_onboard_device, + .snd_device = NULL, + .net_device = NULL + }, /* Has a standard IBM PS/2 KBC firmware or a clone thereof. */ - { "[VLSI 82C481] Siemens Nixdorf D824", "d824", MACHINE_TYPE_486, CPU_PKG_SOCKET1, 0, 0, 0, 0, 0, 0, 0, MACHINE_AT | MACHINE_BUS_PS2 | MACHINE_IDE | MACHINE_VIDEO, 2048, 32768, 2048, 127, machine_at_d824_init, at_d824_get_device }, - + { + .name = "[VLSI 82C481] Siemens Nixdorf D824", + .internal_name = "d824", + .type = MACHINE_TYPE_486, + .chipset = MACHINE_CHIPSET_VLSI_VL82C481, + .init = machine_at_d824_init, + .p1_handler = NULL, + .gpio_handler = NULL, + .available_flag = MACHINE_AVAILABLE, + .gpio_acpi_handler = NULL, + .cpu = { + .package = CPU_PKG_SOCKET1, + .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_PS2, + .flags = MACHINE_IDE | MACHINE_VIDEO | MACHINE_APM, + .ram = { + .min = 2048, + .max = 32768, + .step = 2048 + }, + .nvrmask = 127, + .kbc_device = NULL, + .kbc_p1 = 0xff, + .gpio = 0xffffffff, + .gpio_acpi = 0xffffffff, + .device = NULL, + .fdc_device = NULL, + .sio_device = NULL, + .vid_device = &gd5428_onboard_device, + .snd_device = NULL, + .net_device = NULL + }, + /* Has IBM PS/2 Type 1 KBC firmware. */ + { + .name = "[MCA] IBM PS/2 model 70 (type 4)", + .internal_name = "ibmps2_m70_type4", + .type = MACHINE_TYPE_486, + .chipset = MACHINE_CHIPSET_PROPRIETARY, + .init = machine_ps2_model_70_type4_init, + .p1_handler = NULL, + .gpio_handler = NULL, + .available_flag = MACHINE_AVAILABLE, + .gpio_acpi_handler = NULL, + .cpu = { + .package = CPU_PKG_SOCKET1, + .block = CPU_BLOCK(CPU_i486SX, CPU_i486SX_SLENH, CPU_Am486SX, CPU_Cx486S), + .min_bus = 0, + .max_bus = 0, + .min_voltage = 0, + .max_voltage = 0, + .min_multi = 0, + .max_multi = 0 + }, + .bus_flags = MACHINE_PS2_MCA, + .flags = MACHINE_VIDEO | MACHINE_SOFTFLOAT_ONLY, + .ram = { + .min = 2048, + .max = 65536, + .step = 2048 + }, + .nvrmask = 63, + .kbc_device = NULL, + .kbc_p1 = 0xff, + .gpio = 0xffffffff, + .gpio_acpi = 0xffffffff, + .device = NULL, + .fdc_device = NULL, + .sio_device = NULL, + .vid_device = NULL, + .snd_device = NULL, + .net_device = NULL + }, /* 486 machines - Socket 2 */ /* 486 machines with just the ISA slot */ /* Uses some variant of Phoenix MultiKey/42 as the BIOS sends keyboard controller command C7 (OR input byte with received data byte). */ - { "[ACC 2168] Packard Bell PB410A", "pb410a", MACHINE_TYPE_486_S2, CPU_PKG_SOCKET3, 0, 0, 0, 0, 0, 0, 0, MACHINE_AT | MACHINE_BUS_PS2 | MACHINE_IDE | MACHINE_VIDEO, 4096, 36864, 1024, 127, machine_at_pb410a_init, NULL }, + { + .name = "[ACC 2168] Packard Bell PB410A", + .internal_name = "pb410a", + .type = MACHINE_TYPE_486_S2, + .chipset = MACHINE_CHIPSET_ACC_2168, + .init = machine_at_pb410a_init, + .p1_handler = NULL, + .gpio_handler = NULL, + .available_flag = MACHINE_AVAILABLE, + .gpio_acpi_handler = NULL, + .cpu = { + .package = CPU_PKG_SOCKET3, + .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_PS2, + .flags = MACHINE_IDE | MACHINE_VIDEO | MACHINE_APM, + .ram = { + .min = 4096, + .max = 36864, + .step = 1024 + }, + .nvrmask = 127, + .kbc_device = NULL, + .kbc_p1 = 0xff, + .gpio = 0xffffffff, + .gpio_acpi = 0xffffffff, + .device = NULL, + .fdc_device = NULL, + .sio_device = NULL, + .vid_device = NULL, + .snd_device = NULL, + .net_device = NULL + }, /* Uses an ACER/NEC 90M002A (UPD82C42C, 8042 clone) with unknown firmware (V4.01H). */ - { "[ALi M1429G] Acer A1G", "acera1g", MACHINE_TYPE_486_S2, CPU_PKG_SOCKET3, 0, 0, 0, 0, 0, 0, 0, MACHINE_AT | MACHINE_BUS_PS2 | MACHINE_IDE_DUAL | MACHINE_VIDEO, 4096, 36864, 1024, 127, machine_at_acera1g_init, at_acera1g_get_device }, + { + .name = "[ALi M1429G] Acer A1G", + .internal_name = "acera1g", + .type = MACHINE_TYPE_486_S2, + .chipset = MACHINE_CHIPSET_ALI_M1429G, + .init = machine_at_acera1g_init, + .p1_handler = NULL, + .gpio_handler = NULL, + .available_flag = MACHINE_AVAILABLE, + .gpio_acpi_handler = NULL, + .cpu = { + .package = CPU_PKG_SOCKET3, + .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_PS2, + .flags = MACHINE_IDE_DUAL | MACHINE_VIDEO | MACHINE_APM, + .ram = { + .min = 4096, + .max = 36864, + .step = 1024 + }, + .nvrmask = 127, + .kbc_device = NULL, + .kbc_p1 = 0xff, + .gpio = 0xffffffff, + .gpio_acpi = 0xffffffff, + .device = NULL, + .fdc_device = NULL, + .sio_device = NULL, + .vid_device = &gd5428_onboard_device, + .snd_device = NULL, + .net_device = NULL + }, /* This has an AMIKey-2, which is an updated version of type 'H'. */ - { "[ALi M1429G] Kaimei SA-486 VL-BUS M.B.", "win486", MACHINE_TYPE_486_S2, CPU_PKG_SOCKET3, 0, 0, 0, 0, 0, 0, 0, MACHINE_VLB | MACHINE_IDE, 1024, 32768, 1024, 127, machine_at_winbios1429_init, NULL }, + { + .name = "[ALi M1429G] Kaimei SA-486 VL-BUS M.B.", + .internal_name = "win486", + .type = MACHINE_TYPE_486_S2, + .chipset = MACHINE_CHIPSET_ALI_M1429G, + .init = machine_at_winbios1429_init, + .p1_handler = NULL, + .gpio_handler = NULL, + .available_flag = MACHINE_AVAILABLE, + .gpio_acpi_handler = NULL, + .cpu = { + .package = CPU_PKG_SOCKET3, + .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_VLB, + .flags = MACHINE_IDE | MACHINE_APM, + .ram = { + .min = 1024, + .max = 32768, + .step = 1024 + }, + .nvrmask = 127, + .kbc_device = NULL, + .kbc_p1 = 0xff, + .gpio = 0xffffffff, + .gpio_acpi = 0xffffffff, + .device = NULL, + .fdc_device = NULL, + .sio_device = NULL, + .vid_device = NULL, + .snd_device = NULL, + .net_device = NULL + }, /* Uses an Intel KBC with Phoenix MultiKey KBC firmware. */ - { "[SiS 461] DEC DECpc LPV", "decpclpv", MACHINE_TYPE_486_S2, CPU_PKG_SOCKET3, 0, 0, 0, 0, 0, 0, 0, MACHINE_AT | MACHINE_BUS_PS2 | MACHINE_IDE_DUAL | MACHINE_VIDEO, 1024, 32768, 1024, 127, machine_at_decpclpv_init, NULL }, + { + .name = "[SiS 461] DEC DECpc LPV", + .internal_name = "decpclpv", + .type = MACHINE_TYPE_486_S2, + .chipset = MACHINE_CHIPSET_SIS_461, + .init = machine_at_decpclpv_init, + .p1_handler = NULL, + .gpio_handler = NULL, + .available_flag = MACHINE_AVAILABLE, + .gpio_acpi_handler = NULL, + .cpu = { + .package = CPU_PKG_SOCKET3, + .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_PS2, + .flags = MACHINE_IDE_DUAL | MACHINE_VIDEO | MACHINE_APM, + .ram = { + .min = 1024, + .max = 32768, + .step = 1024 + }, + .nvrmask = 127, + .kbc_device = NULL, + .kbc_p1 = 0xff, + .gpio = 0xffffffff, + .gpio_acpi = 0xffffffff, + .device = NULL, + .fdc_device = NULL, + .sio_device = NULL, + .vid_device = &s3_86c805_onboard_vlb_device, + .snd_device = NULL, + .net_device = NULL + }, /* Uses an NEC 90M002A (UPD82C42C, 8042 clone) with unknown firmware. */ - { "[SiS 461] Acer V10", "acerv10", MACHINE_TYPE_486_S2, CPU_PKG_SOCKET3, 0, 0, 0, 0, 0, 0, 0, MACHINE_AT | MACHINE_BUS_PS2 | MACHINE_IDE_DUAL | MACHINE_VIDEO, 1024, 32768, 1024, 127, machine_at_acerv10_init, NULL }, + { + .name = "[SiS 461] Acer V10", + .internal_name = "acerv10", + .type = MACHINE_TYPE_486_S2, + .chipset = MACHINE_CHIPSET_SIS_461, + .init = machine_at_acerv10_init, + .p1_handler = NULL, + .gpio_handler = NULL, + .available_flag = MACHINE_AVAILABLE, + .gpio_acpi_handler = NULL, + .cpu = { + .package = CPU_PKG_SOCKET3, + .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_PS2, + .flags = MACHINE_IDE_DUAL | MACHINE_APM, + .ram = { + .min = 1024, + .max = 32768, + .step = 1024 + }, + .nvrmask = 127, + .kbc_device = NULL, + .kbc_p1 = 0xff, + .gpio = 0xffffffff, + .gpio_acpi = 0xffffffff, + .device = NULL, + .fdc_device = NULL, + .sio_device = NULL, + .vid_device = NULL, + .snd_device = NULL, + .net_device = NULL + }, /* The BIOS does not send any non-standard keyboard controller commands and wants a PS/2 mouse, so it's an IBM PS/2 KBC (Type 1) firmware. */ - { "[SiS 461] IBM PS/ValuePoint 433DX/Si", "valuepoint433", MACHINE_TYPE_486_S2, CPU_PKG_SOCKET3, 0, 0, 0, 0, 0, 0, 0, MACHINE_AT | MACHINE_BUS_PS2 | MACHINE_IDE | MACHINE_VIDEO, 1024, 65536, 1024, 127, machine_at_valuepoint433_init, NULL }, + { + .name = "[SiS 461] IBM PS/ValuePoint 433DX/Si", + .internal_name = "valuepoint433", + .type = MACHINE_TYPE_486_S2, + .chipset = MACHINE_CHIPSET_SIS_461, + .init = machine_at_valuepoint433_init, + .p1_handler = NULL, + .gpio_handler = NULL, + .available_flag = MACHINE_AVAILABLE, + .gpio_acpi_handler = NULL, + .cpu = { + .package = CPU_PKG_SOCKET3, + .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_PS2, + .flags = MACHINE_IDE | MACHINE_VIDEO | MACHINE_APM, + .ram = { + .min = 1024, + .max = 65536, + .step = 1024 + }, + .nvrmask = 127, + .kbc_device = NULL, + .kbc_p1 = 0xff, + .gpio = 0xffffffff, + .gpio_acpi = 0xffffffff, + .device = NULL, + .fdc_device = NULL, + .sio_device = NULL, + .vid_device = NULL, + .snd_device = NULL, + .net_device = NULL + }, /* The BIOS string ends in -U, unless command 0xA1 (AMIKey get version) returns an 'F', in which case, it ends in -F, so it has an AMIKey F KBC firmware. The photo of the board shows an AMIKey KBC which is indeed F. */ - { "[SiS 471] ABit AB-AH4", "win471", MACHINE_TYPE_486_S2, CPU_PKG_SOCKET3, 0, 0, 0, 0, 0, 0, 0, MACHINE_VLB | MACHINE_IDE, 1024, 65536, 1024, 127, machine_at_win471_init, NULL }, + { + .name = "[SiS 471] ABit AB-AH4", + .internal_name = "win471", + .type = MACHINE_TYPE_486_S2, + .chipset = MACHINE_CHIPSET_SIS_471, + .init = machine_at_win471_init, + .p1_handler = NULL, + .gpio_handler = NULL, + .available_flag = MACHINE_AVAILABLE, + .gpio_acpi_handler = NULL, + .cpu = { + .package = CPU_PKG_SOCKET3, + .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_VLB, + .flags = MACHINE_IDE | MACHINE_APM, + .ram = { + .min = 1024, + .max = 65536, + .step = 1024 + }, + .nvrmask = 127, + .kbc_device = NULL, + .kbc_p1 = 0xff, + .gpio = 0xffffffff, + .gpio_acpi = 0xffffffff, + .device = NULL, + .fdc_device = NULL, + .sio_device = NULL, + .vid_device = NULL, + .snd_device = NULL, + .net_device = NULL + }, /* 486 machines - Socket 3 */ /* 486 machines with just the ISA slot */ /* Has AMI MegaKey KBC firmware. */ - { "[Contaq 82C597] Green-B", "greenb", MACHINE_TYPE_486_S3, CPU_PKG_SOCKET3, 0, 0, 0, 0, 0, 0, 0, MACHINE_VLB, 1024, 65536, 1024, 127, machine_at_greenb_init, NULL }, + { + .name = "[Contaq 82C597] Green-B", + .internal_name = "greenb", + .type = MACHINE_TYPE_486_S3, + .chipset = MACHINE_CHIPSET_CONTAQ_82C597, + .init = machine_at_greenb_init, + .p1_handler = NULL, + .gpio_handler = NULL, + .available_flag = MACHINE_AVAILABLE, + .gpio_acpi_handler = NULL, + .cpu = { + .package = CPU_PKG_SOCKET3, + .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_VLB, + .flags = MACHINE_APM, + .ram = { + .min = 1024, + .max = 65536, + .step = 1024 + }, + .nvrmask = 127, + .kbc_device = NULL, + .kbc_p1 = 0xff, + .gpio = 0xffffffff, + .gpio_acpi = 0xffffffff, + .device = NULL, + .fdc_device = NULL, + .sio_device = NULL, + .vid_device = NULL, + .snd_device = NULL, + .net_device = NULL + }, /* Has a VIA VT82C42N KBC. */ - { "[OPTi 895] Jetway J-403TG", "403tg", MACHINE_TYPE_486_S3, CPU_PKG_SOCKET3, 0, 0, 0, 0, 0, 0, 0, MACHINE_VLB, 1024, 65536, 1024, 127, machine_at_403tg_init, NULL }, + { + .name = "[OPTi 895] Jetway J-403TG", + .internal_name = "403tg", + .type = MACHINE_TYPE_486_S3, + .chipset = MACHINE_CHIPSET_OPTI_895_802G, + .init = machine_at_403tg_init, + .p1_handler = NULL, + .gpio_handler = NULL, + .available_flag = MACHINE_AVAILABLE, + .gpio_acpi_handler = NULL, + .cpu = { + .package = CPU_PKG_SOCKET3, + .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_VLB, + .flags = MACHINE_APM, + .ram = { + .min = 1024, + .max = 65536, + .step = 1024 + }, + .nvrmask = 127, + .kbc_device = NULL, + .kbc_p1 = 0xff, + .gpio = 0xffffffff, + .gpio_acpi = 0xffffffff, + .device = NULL, + .fdc_device = NULL, + .sio_device = NULL, + .vid_device = NULL, + .snd_device = NULL, + .net_device = NULL + }, /* Has JetKey 5 KBC Firmware which looks like it is a clone of AMIKey type F. */ - { "[OPTi 895] Jetway J-403TG Rev D", "403tg_d", MACHINE_TYPE_486_S3, CPU_PKG_SOCKET3, 0, 0, 0, 0, 0, 0, 0, MACHINE_VLB, 1024, 65536, 1024, 127, machine_at_403tg_d_init, NULL }, + { + .name = "[OPTi 895] Jetway J-403TG Rev D", + .internal_name = "403tg_d", + .type = MACHINE_TYPE_486_S3, + .chipset = MACHINE_CHIPSET_OPTI_895_802G, + .init = machine_at_403tg_d_init, + .p1_handler = NULL, + .gpio_handler = NULL, + .available_flag = MACHINE_AVAILABLE, + .gpio_acpi_handler = NULL, + .cpu = { + .package = CPU_PKG_SOCKET3, + .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_VLB, + .flags = MACHINE_APM, + .ram = { + .min = 1024, + .max = 65536, + .step = 1024 + }, + .nvrmask = 127, + .kbc_device = NULL, + .kbc_p1 = 0xff, + .gpio = 0xffffffff, + .gpio_acpi = 0xffffffff, + .device = NULL, + .fdc_device = NULL, + .sio_device = NULL, + .vid_device = NULL, + .snd_device = NULL, + .net_device = NULL + }, /* Has JetKey 5 KBC Firmware which looks like it is a clone of AMIKey type F. */ - { "[OPTi 895] Jetway J-403TG Rev D (MR BIOS)","403tg_d_mr", MACHINE_TYPE_486_S3, CPU_PKG_SOCKET3, 0, 0, 0, 0, 0, 0, 0, MACHINE_VLB, 1024, 65536, 1024, 127, machine_at_403tg_d_mr_init, NULL }, + { + .name = "[OPTi 895] Jetway J-403TG Rev D (MR BIOS)", + .internal_name = "403tg_d_mr", + .type = MACHINE_TYPE_486_S3, + .chipset = MACHINE_CHIPSET_OPTI_895_802G, + .init = machine_at_403tg_d_mr_init, + .p1_handler = NULL, + .gpio_handler = NULL, + .available_flag = MACHINE_AVAILABLE, + .gpio_acpi_handler = NULL, + .cpu = { + .package = CPU_PKG_SOCKET3, + .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_VLB, + .flags = MACHINE_APM, + .ram = { + .min = 1024, + .max = 65536, + .step = 1024 + }, + .nvrmask = 127, + .kbc_device = NULL, + .kbc_p1 = 0xff, + .gpio = 0xffffffff, + .gpio_acpi = 0xffffffff, + .device = NULL, + .fdc_device = NULL, + .sio_device = NULL, + .vid_device = NULL, + .snd_device = NULL, + .net_device = NULL + }, /* Has AMIKey H keyboard BIOS. */ - { "[SiS 471] AOpen Vi15G", "vi15g", MACHINE_TYPE_486_S3, CPU_PKG_SOCKET3, 0, 0, 0, 0, 0, 0, 0, MACHINE_VLB | MACHINE_IDE, 1024, 65536, 1024, 127, machine_at_vi15g_init, NULL }, + { + .name = "[SiS 471] AOpen Vi15G", + .internal_name = "vi15g", + .type = MACHINE_TYPE_486_S3, + .chipset = MACHINE_CHIPSET_SIS_471, + .init = machine_at_vi15g_init, + .p1_handler = NULL, + .gpio_handler = NULL, + .available_flag = MACHINE_AVAILABLE, + .gpio_acpi_handler = NULL, + .cpu = { + .package = CPU_PKG_SOCKET3, + .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_VLB, + .flags = MACHINE_IDE | MACHINE_APM, + .ram = { + .min = 1024, + .max = 65536, + .step = 1024 + }, + .nvrmask = 127, + .kbc_device = NULL, + .kbc_p1 = 0xff, + .gpio = 0xffffffff, + .gpio_acpi = 0xffffffff, + .device = NULL, + .fdc_device = NULL, + .sio_device = NULL, + .vid_device = NULL, + .snd_device = NULL, + .net_device = NULL + }, /* This has an AMIKey-2, which is an updated version of type 'H'. */ - { "[SiS 471] ASUS VL/I-486SV2G (GX4)", "vli486sv2g", MACHINE_TYPE_486_S3, CPU_PKG_SOCKET3, 0, 0, 0, 0, 0, 0, 0, MACHINE_VLB | MACHINE_BUS_PS2 | MACHINE_IDE_DUAL, 1024, 65536, 1024, 127, machine_at_vli486sv2g_init, NULL }, + { + .name = "[SiS 471] ASUS VL/I-486SV2G (GX4)", + .internal_name = "vli486sv2g", + .type = MACHINE_TYPE_486_S3, + .chipset = MACHINE_CHIPSET_SIS_471, + .init = machine_at_vli486sv2g_init, + .p1_handler = NULL, + .gpio_handler = NULL, + .available_flag = MACHINE_AVAILABLE, + .gpio_acpi_handler = NULL, + .cpu = { + .package = CPU_PKG_SOCKET3, + .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_PS2_VLB, + .flags = MACHINE_IDE_DUAL | MACHINE_APM, + .ram = { + .min = 1024, + .max = 65536, + .step = 1024 + }, + .nvrmask = 127, + .kbc_device = NULL, + .kbc_p1 = 0xff, + .gpio = 0xffffffff, + .gpio_acpi = 0xffffffff, + .device = NULL, + .fdc_device = NULL, + .sio_device = NULL, + .vid_device = NULL, + .snd_device = NULL, + .net_device = NULL + }, /* Has JetKey 5 KBC Firmware which looks like it is a clone of AMIKey type F. */ - { "[SiS 471] DTK PKM-0038S E-2", "dtk486", MACHINE_TYPE_486_S3, CPU_PKG_SOCKET3, 0, 0, 0, 0, 0, 0, 0, MACHINE_VLB | MACHINE_IDE, 1024, 65536, 1024, 127, machine_at_dtk486_init, NULL }, + { + .name = "[SiS 471] DTK PKM-0038S E-2", + .internal_name = "dtk486", + .type = MACHINE_TYPE_486_S3, + .chipset = MACHINE_CHIPSET_SIS_471, + .init = machine_at_dtk486_init, + .p1_handler = NULL, + .gpio_handler = NULL, + .available_flag = MACHINE_AVAILABLE, + .gpio_acpi_handler = NULL, + .cpu = { + .package = CPU_PKG_SOCKET3, + .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_VLB, + .flags = MACHINE_IDE | MACHINE_APM, + .ram = { + .min = 1024, + .max = 65536, + .step = 1024 + }, + .nvrmask = 127, + .kbc_device = NULL, + .kbc_p1 = 0xff, + .gpio = 0xffffffff, + .gpio_acpi = 0xffffffff, + .device = NULL, + .fdc_device = NULL, + .sio_device = NULL, + .vid_device = NULL, + .snd_device = NULL, + .net_device = NULL + }, /* Unknown Epox VLB Socket 3 board, has AMIKey F keyboard BIOS. */ - { "[SiS 471] Epox 486SX/DX Green", "ami471", MACHINE_TYPE_486_S3, CPU_PKG_SOCKET3, 0, 0, 0, 0, 0, 0, 0, MACHINE_VLB | MACHINE_IDE, 1024, 65536, 1024, 127, machine_at_ami471_init, NULL }, + { + .name = "[SiS 471] Epox 486SX/DX Green", + .internal_name = "ami471", + .type = MACHINE_TYPE_486_S3, + .chipset = MACHINE_CHIPSET_SIS_471, + .init = machine_at_ami471_init, + .p1_handler = NULL, + .gpio_handler = NULL, + .available_flag = MACHINE_AVAILABLE, + .gpio_acpi_handler = NULL, + .cpu = { + .package = CPU_PKG_SOCKET3, + .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_VLB, + .flags = MACHINE_IDE | MACHINE_APM, + .ram = { + .min = 1024, + .max = 65536, + .step = 1024 + }, + .nvrmask = 127, + .kbc_device = NULL, + .kbc_p1 = 0xff, + .gpio = 0xffffffff, + .gpio_acpi = 0xffffffff, + .device = NULL, + .fdc_device = NULL, + .sio_device = NULL, + .vid_device = NULL, + .snd_device = NULL, + .net_device = NULL + }, + /* TriGem AMIBIOS Pre-Color with TriGem AMI 'Z' keyboard controller */ + { + .name = "[SiS 471] TriGem 486G", + .internal_name = "tg486g", + .type = MACHINE_TYPE_486_S3, + .chipset = MACHINE_CHIPSET_SIS_471, + .init = machine_at_tg486g_init, + .p1_handler = NULL, + .gpio_handler = NULL, + .available_flag = MACHINE_AVAILABLE, + .gpio_acpi_handler = NULL, + .cpu = { + .package = CPU_PKG_SOCKET3, + .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_PS2_VLB, + .flags = MACHINE_IDE | MACHINE_APM, + .ram = { + .min = 1024, + .max = 65536, + .step = 1024 + }, + .nvrmask = 127, + .kbc_device = NULL, + .kbc_p1 = 0xff, + .gpio = 0xffffffff, + .gpio_acpi = 0xffffffff, + .device = NULL, + .fdc_device = NULL, + .sio_device = NULL, + .vid_device = NULL, + .snd_device = NULL, + .net_device = NULL + }, /* 486 machines which utilize the PCI bus */ + /* Machine with ALi M1429G chipset and M1435 southbridge */ + { + .name = "[ALi M1429G] MSI MS-4134", + .internal_name = "ms4134", + .type = MACHINE_TYPE_486_S3, + .chipset = MACHINE_CHIPSET_ALI_M1429G, + .init = machine_at_ms4134_init, + .p1_handler = NULL, + .gpio_handler = NULL, + .available_flag = MACHINE_AVAILABLE, + .gpio_acpi_handler = NULL, + .cpu = { + .package = CPU_PKG_SOCKET3, + .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_PS2_PCIV, + .flags = MACHINE_IDE_DUAL | MACHINE_APM, + .ram = { + .min = 1024, + .max = 131072, + .step = 1024 + }, + .nvrmask = 255, + .kbc_device = NULL, + .kbc_p1 = 0xff, + .gpio = 0xffffffff, + .gpio_acpi = 0xffffffff, + .device = NULL, + .fdc_device = NULL, + .sio_device = NULL, + .vid_device = NULL, + .snd_device = NULL, + .net_device = NULL + }, + /* TriGem machine with M1429G and PhoenixBIOS */ + { + .name = "[ALi M1429G] TriGem 486GP", + .internal_name = "tg486gp", + .type = MACHINE_TYPE_486_S3, + .chipset = MACHINE_CHIPSET_ALI_M1429G, + .init = machine_at_tg486gp_init, + .p1_handler = NULL, + .gpio_handler = NULL, + .available_flag = MACHINE_AVAILABLE, + .gpio_acpi_handler = NULL, + .cpu = { + .package = CPU_PKG_SOCKET3, + .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_PS2_PCIV, + .flags = MACHINE_IDE_DUAL | MACHINE_APM, + .ram = { + .min = 1024, + .max = 131072, + .step = 1024 + }, + .nvrmask = 255, + .kbc_device = NULL, + .kbc_p1 = 0xff, + .gpio = 0xffffffff, + .gpio_acpi = 0xffffffff, + .device = NULL, + .fdc_device = NULL, + .sio_device = NULL, + .vid_device = NULL, + .snd_device = NULL, + .net_device = NULL + }, /* This has an AMIKey-2, which is an updated version of type 'H'. */ - { "[ALi M1489] AAEON SBC-490", "sbc490", MACHINE_TYPE_486_S3, CPU_PKG_SOCKET3, 0, 0, 0, 0, 0, 0, 0, MACHINE_PCI | MACHINE_BUS_PS2 | MACHINE_IDE_DUAL | MACHINE_VIDEO, 1024, 65536, 1024, 255, machine_at_sbc490_init, at_sbc490_get_device }, + { + .name = "[ALi M1489] AAEON SBC-490", + .internal_name = "sbc490", + .type = MACHINE_TYPE_486_S3, + .chipset = MACHINE_CHIPSET_ALI_M1489, + .init = machine_at_sbc490_init, + .p1_handler = NULL, + .gpio_handler = NULL, + .available_flag = MACHINE_AVAILABLE, + .gpio_acpi_handler = NULL, + .cpu = { + .package = CPU_PKG_SOCKET3, + .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_PS2_PCI, + .flags = MACHINE_IDE_DUAL | MACHINE_VIDEO | MACHINE_APM, + .ram = { + .min = 1024, + .max = 65536, + .step = 1024 + }, + .nvrmask = 255, + .kbc_device = NULL, + .kbc_p1 = 0xff, + .gpio = 0xffffffff, + .gpio_acpi = 0xffffffff, + .device = NULL, + .fdc_device = NULL, + .sio_device = NULL, + .vid_device = &tgui9440_onboard_pci_device, + .snd_device = NULL, + .net_device = NULL + }, /* Has the ALi M1487/9's on-chip keyboard controller which clones a standard AT KBC. */ - { "[ALi M1489] ABIT AB-PB4", "abpb4", MACHINE_TYPE_486_S3, CPU_PKG_SOCKET3, 0, 0, 0, 0, 0, 0, 0, MACHINE_PCI | MACHINE_IDE_DUAL, 1024, 65536, 1024, 255, machine_at_abpb4_init, NULL }, + { + .name = "[ALi M1489] ABIT AB-PB4", + .internal_name = "abpb4", + .type = MACHINE_TYPE_486_S3, + .chipset = MACHINE_CHIPSET_ALI_M1489, + .init = machine_at_abpb4_init, + .p1_handler = NULL, + .gpio_handler = NULL, + .available_flag = MACHINE_AVAILABLE, + .gpio_acpi_handler = NULL, + .cpu = { + .package = CPU_PKG_SOCKET3, + .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_PCI, + .flags = MACHINE_IDE_DUAL | MACHINE_APM, + .ram = { + .min = 1024, + .max = 65536, + .step = 1024 + }, + .nvrmask = 255, + .kbc_device = NULL, + .kbc_p1 = 0xff, + .gpio = 0xffffffff, + .gpio_acpi = 0xffffffff, + .device = NULL, + .fdc_device = NULL, + .sio_device = NULL, + .vid_device = NULL, + .snd_device = NULL, + .net_device = NULL + }, /* Has the ALi M1487/9's on-chip keyboard controller which clones a standard AT KBC. The BIOS string always ends in -U, but the BIOS will send AMIKey commands 0xCA and 0xCB if command 0xA1 returns a letter in the 0x5x or 0x7x ranges, so I'm going to give it an AMI 'U' KBC. */ - { "[ALi M1489] AMI WinBIOS 486 PCI", "win486pci", MACHINE_TYPE_486_S3, CPU_PKG_SOCKET3, 0, 0, 0, 0, 0, 0, 0, MACHINE_PCI | MACHINE_IDE_DUAL, 1024, 65536, 1024, 255, machine_at_win486pci_init, NULL }, + { + .name = "[ALi M1489] AMI WinBIOS 486 PCI", + .internal_name = "win486pci", + .type = MACHINE_TYPE_486_S3, + .chipset = MACHINE_CHIPSET_ALI_M1489, + .init = machine_at_win486pci_init, + .p1_handler = NULL, + .gpio_handler = NULL, + .available_flag = MACHINE_AVAILABLE, + .gpio_acpi_handler = NULL, + .cpu = { + .package = CPU_PKG_SOCKET3, + .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_PCI, + .flags = MACHINE_IDE_DUAL | MACHINE_APM, + .ram = { + .min = 1024, + .max = 65536, + .step = 1024 + }, + .nvrmask = 255, + .kbc_device = NULL, + .kbc_p1 = 0xff, + .gpio = 0xffffffff, + .gpio_acpi = 0xffffffff, + .device = NULL, + .fdc_device = NULL, + .sio_device = NULL, + .vid_device = NULL, + .snd_device = NULL, + .net_device = NULL + }, /* Has the ALi M1487/9's on-chip keyboard controller which clones a standard AT KBC. The known BIOS string ends in -E, and the BIOS returns whatever command 0xA1 returns (but only if command 0xA1 is instant response), so said ALi keyboard controller likely returns 'E'. */ - { "[ALi M1489] MSI MS-4145", "ms4145", MACHINE_TYPE_486_S3, CPU_PKG_SOCKET3, 0, 0, 0, 0, 0, 0, 0, MACHINE_PCI | MACHINE_IDE_DUAL, 1024, 65536, 1024, 255, machine_at_ms4145_init, NULL }, + { + .name = "[ALi M1489] MSI MS-4145", + .internal_name = "ms4145", + .type = MACHINE_TYPE_486_S3, + .chipset = MACHINE_CHIPSET_ALI_M1489, + .init = machine_at_ms4145_init, + .p1_handler = NULL, + .gpio_handler = NULL, + .available_flag = MACHINE_AVAILABLE, + .gpio_acpi_handler = NULL, + .cpu = { + .package = CPU_PKG_SOCKET3, + .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_PCI, + .flags = MACHINE_IDE_DUAL | MACHINE_APM, + .ram = { + .min = 1024, + .max = 65536, + .step = 1024 + }, + .nvrmask = 255, + .kbc_device = NULL, + .kbc_p1 = 0xff, + .gpio = 0xffffffff, + .gpio_acpi = 0xffffffff, + .device = NULL, + .fdc_device = NULL, + .sio_device = NULL, + .vid_device = NULL, + .snd_device = NULL, + .net_device = NULL + }, /* Has an ALi M5042 keyboard controller with Phoenix MultiKey/42 v1.40 firmware. */ - { "[ALi M1489] ESA TF-486", "tf486", MACHINE_TYPE_486_S3, CPU_PKG_SOCKET3, 0, 0, 0, 0, 0, 0, 0, MACHINE_PCI | MACHINE_BUS_PS2 | MACHINE_IDE_DUAL, 1024, 65536, 1024, 255, machine_at_tf486_init, NULL }, + { + .name = "[ALi M1489] ESA TF-486", + .internal_name = "tf486", + .type = MACHINE_TYPE_486_S3, + .chipset = MACHINE_CHIPSET_ALI_M1489, + .init = machine_at_tf486_init, + .p1_handler = NULL, + .gpio_handler = NULL, + .available_flag = MACHINE_AVAILABLE, + .gpio_acpi_handler = NULL, + .cpu = { + .package = CPU_PKG_SOCKET3, + .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_PS2_PCI, + .flags = MACHINE_IDE_DUAL | MACHINE_APM, + .ram = { + .min = 1024, + .max = 65536, + .step = 1024 + }, + .nvrmask = 255, + .kbc_device = NULL, + .kbc_p1 = 0xff, + .gpio = 0xffffffff, + .gpio_acpi = 0xffffffff, + .device = NULL, + .fdc_device = NULL, + .sio_device = NULL, + .vid_device = NULL, + .snd_device = NULL, + .net_device = NULL + }, /* Has IBM PS/2 Type 1 KBC firmware. */ - { "[OPTi 802G] IBM PC 330 (type 6573)", "pc330_6573", MACHINE_TYPE_486_S3, CPU_PKG_SOCKET3_PC330, 0, 25000000, 33333333, 0, 0, 2.0, 3.0, MACHINE_PCI | MACHINE_BUS_PS2 | MACHINE_IDE, 1024, 65536, 1024, 127, machine_at_pc330_6573_init, NULL }, + { + .name = "[OPTi 802G] IBM PC 330 (type 6573)", + .internal_name = "pc330_6573", + .type = MACHINE_TYPE_486_S3, + .chipset = MACHINE_CHIPSET_OPTI_895_802G, + .init = machine_at_pc330_6573_init, + .p1_handler = NULL, + .gpio_handler = NULL, + .available_flag = MACHINE_AVAILABLE, + .gpio_acpi_handler = NULL, + .cpu = { + .package = CPU_PKG_SOCKET3_PC330, + .block = CPU_BLOCK_NONE, + .min_bus = 25000000, + .max_bus = 33333333, + .min_voltage = 0, + .max_voltage = 0, + .min_multi = 2.0, + .max_multi = 3.0 + }, + .bus_flags = MACHINE_PS2_PCI, + .flags = MACHINE_IDE | MACHINE_VIDEO | MACHINE_APM, + .ram = { + .min = 1024, + .max = 65536, + .step = 1024 + }, + .nvrmask = 255, + .kbc_device = NULL, + .kbc_p1 = 0xff, + .gpio = 0xffffffff, + .gpio_acpi = 0xffffffff, + .device = NULL, + .fdc_device = NULL, + .sio_device = NULL, + .vid_device = &gd5430_onboard_pci_device, + .snd_device = NULL, + .net_device = NULL + }, /* This has an AMIKey-2, which is an updated version of type 'H'. */ - { "[i420EX] ASUS PVI-486AP4", "486ap4", MACHINE_TYPE_486_S3, CPU_PKG_SOCKET3, 0, 0, 0, 0, 0, 0, 0, MACHINE_PCIV | MACHINE_BUS_PS2 | MACHINE_IDE_DUAL, 1024, 131072, 1024, 127, machine_at_486ap4_init, NULL }, + { + .name = "[i420EX] ASUS PVI-486AP4", + .internal_name = "486ap4", + .type = MACHINE_TYPE_486_S3, + .chipset = MACHINE_CHIPSET_INTEL_420EX, + .init = machine_at_486ap4_init, + .p1_handler = NULL, + .gpio_handler = NULL, + .available_flag = MACHINE_AVAILABLE, + .gpio_acpi_handler = NULL, + .cpu = { + .package = CPU_PKG_SOCKET3, + .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_PS2_PCIV, + .flags = MACHINE_IDE_DUAL | MACHINE_APM, + .ram = { + .min = 1024, + .max = 131072, + .step = 1024 + }, + .nvrmask = 127, + .kbc_device = NULL, + .kbc_p1 = 0xff, + .gpio = 0xffffffff, + .gpio_acpi = 0xffffffff, + .device = NULL, + .fdc_device = NULL, + .sio_device = NULL, + .vid_device = NULL, + .snd_device = NULL, + .net_device = NULL + }, /* This has the Phoenix MultiKey KBC firmware. */ - { "[i420EX] Intel Classic/PCI ED", "ninja", MACHINE_TYPE_486_S3, CPU_PKG_SOCKET3, 0, 0, 0, 0, 0, 0, 0, MACHINE_PCI | MACHINE_BUS_PS2 | MACHINE_IDE_DUAL, 1024, 131072, 1024, 127, machine_at_ninja_init, NULL }, + { + .name = "[i420EX] Intel Classic/PCI ED", + .internal_name = "ninja", + .type = MACHINE_TYPE_486_S3, + .chipset = MACHINE_CHIPSET_INTEL_420EX, + .init = machine_at_ninja_init, + .p1_handler = NULL, + .gpio_handler = NULL, + .available_flag = MACHINE_AVAILABLE, + .gpio_acpi_handler = NULL, + .cpu = { + .package = CPU_PKG_SOCKET3, + .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_PS2_PCI, + .flags = MACHINE_IDE_DUAL | MACHINE_APM, + .ram = { + .min = 1024, + .max = 131072, + .step = 1024 + }, + .nvrmask = 127, + .kbc_device = NULL, + .kbc_p1 = 0xff, + .gpio = 0xffffffff, + .gpio_acpi = 0xffffffff, + .device = NULL, + .fdc_device = NULL, + .sio_device = NULL, + .vid_device = NULL, + .snd_device = NULL, + .net_device = NULL + }, + /* I'm going to assume this as an AMIKey-2 like the other two 486SP3's. */ + { + .name = "[i420TX] ASUS PCI/I-486SP3", + .internal_name = "486sp3", + .type = MACHINE_TYPE_486_S3, + .chipset = MACHINE_CHIPSET_INTEL_420TX, + .init = machine_at_486sp3_init, + .p1_handler = NULL, + .gpio_handler = NULL, + .available_flag = MACHINE_AVAILABLE, + .gpio_acpi_handler = NULL, + .cpu = { + .package = CPU_PKG_SOCKET3, + .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_PCI, + .flags = MACHINE_IDE_DUAL | MACHINE_SCSI | MACHINE_APM, + .ram = { + .min = 1024, + .max = 131072, + .step = 1024 + }, + .nvrmask = 127, + .kbc_device = NULL, + .kbc_p1 = 0xff, + .gpio = 0xffffffff, + .gpio_acpi = 0xffffffff, + .device = NULL, + .fdc_device = NULL, + .sio_device = NULL, + .vid_device = NULL, + .snd_device = NULL, + .net_device = NULL + }, + /* This has the Phoenix MultiKey KBC firmware. */ + { + .name = "[i420TX] Intel Classic/PCI", + .internal_name = "alfredo", + .type = MACHINE_TYPE_486_S3, + .chipset = MACHINE_CHIPSET_INTEL_420TX, + .init = machine_at_alfredo_init, + .p1_handler = NULL, + .gpio_handler = NULL, + .available_flag = MACHINE_AVAILABLE, + .gpio_acpi_handler = NULL, + .cpu = { + .package = CPU_PKG_SOCKET3, + .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_PS2_PCI, + .flags = MACHINE_IDE_DUAL | MACHINE_APM, + .ram = { + .min = 2048, + .max = 131072, + .step = 2048 + }, + .nvrmask = 127, + .kbc_device = NULL, + .kbc_p1 = 0xff, + .gpio = 0xffffffff, + .gpio_acpi = 0xffffffff, + .device = NULL, + .fdc_device = NULL, + .sio_device = NULL, + .vid_device = NULL, + .snd_device = NULL, + .net_device = NULL + }, /* This has an AMIKey-2, which is an updated version of type 'H'. Also has a SST 29EE010 Flash chip. */ - { "[i420ZX] ASUS PCI/I-486SP3G", "486sp3g", MACHINE_TYPE_486_S3, CPU_PKG_SOCKET3, 0, 0, 0, 0, 0, 0, 0, MACHINE_PCI | MACHINE_BUS_PS2 | MACHINE_IDE_DUAL | MACHINE_SCSI, 1024, 131072, 1024, 127, machine_at_486sp3g_init, NULL }, - /* I'm going to assume this as an AMIKey-2 like the other two 486SP3's. */ - { "[i420TX] ASUS PCI/I-486SP3", "486sp3", MACHINE_TYPE_486_S3, CPU_PKG_SOCKET3, 0, 0, 0, 0, 0, 0, 0, MACHINE_PCI | MACHINE_IDE_DUAL | MACHINE_SCSI, 1024, 131072, 1024, 127, machine_at_486sp3_init, NULL }, - /* This has the Phoenix MultiKey KBC firmware. */ - { "[i420TX] Intel Classic/PCI", "alfredo", MACHINE_TYPE_486_S3, CPU_PKG_SOCKET3, 0, 0, 0, 0, 0, 0, 0, MACHINE_PCI | MACHINE_BUS_PS2 | MACHINE_IDE_DUAL, 2048, 131072, 2048, 127, machine_at_alfredo_init, NULL }, + { + .name = "[i420ZX] ASUS PCI/I-486SP3G", + .internal_name = "486sp3g", + .type = MACHINE_TYPE_486_S3, + .chipset = MACHINE_CHIPSET_INTEL_420ZX, + .init = machine_at_486sp3g_init, + .p1_handler = NULL, + .gpio_handler = NULL, + .available_flag = MACHINE_AVAILABLE, + .gpio_acpi_handler = NULL, + .cpu = { + .package = CPU_PKG_SOCKET3, + .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_PS2_PCI, + .flags = MACHINE_IDE_DUAL | MACHINE_SCSI | MACHINE_APM, + .ram = { + .min = 1024, + .max = 131072, + .step = 1024 + }, + .nvrmask = 127, + .kbc_device = NULL, + .kbc_p1 = 0xff, + .gpio = 0xffffffff, + .gpio_acpi = 0xffffffff, + .device = NULL, + .fdc_device = NULL, + .sio_device = NULL, + .vid_device = NULL, + .snd_device = NULL, + .net_device = NULL + }, /* This most likely has a standalone AMI Megakey 1993, which is type 'P', like the below Tekram board. */ - { "[IMS 8848] J-Bond PCI400C-B", "pci400cb", MACHINE_TYPE_486_S3, CPU_PKG_SOCKET3, 0, 0, 0, 0, 0, 0, 0, MACHINE_PCI | MACHINE_BUS_PS2 | MACHINE_IDE_DUAL, 2048, 131072, 2048, 127, machine_at_pci400cb_init, NULL }, + { + .name = "[IMS 8848] J-Bond PCI400C-B", + .internal_name = "pci400cb", + .type = MACHINE_TYPE_486_S3, + .chipset = MACHINE_CHIPSET_IMS_8848, + .init = machine_at_pci400cb_init, + .p1_handler = NULL, + .gpio_handler = NULL, + .available_flag = MACHINE_AVAILABLE, + .gpio_acpi_handler = NULL, + .cpu = { + .package = CPU_PKG_SOCKET3, + .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_PS2_PCI, + .flags = MACHINE_IDE_DUAL | MACHINE_APM, + .ram = { + .min = 2048, + .max = 131072, + .step = 2048 + }, + .nvrmask = 127, + .kbc_device = NULL, + .kbc_p1 = 0xff, + .gpio = 0xffffffff, + .gpio_acpi = 0xffffffff, + .device = NULL, + .fdc_device = NULL, + .sio_device = NULL, + .vid_device = NULL, + .snd_device = NULL, + .net_device = NULL + }, /* This has a standalone AMI Megakey 1993, which is type 'P'. */ - { "[IMS 8848] Tekram G486IP", "g486ip", MACHINE_TYPE_486_S3, CPU_PKG_SOCKET3, 0, 0, 0, 0, 0, 0, 0, MACHINE_PCI | MACHINE_BUS_PS2 | MACHINE_IDE_DUAL, 2048, 131072, 2048, 127, machine_at_g486ip_init, NULL }, + { + .name = "[IMS 8848] Tekram G486IP", + .internal_name = "g486ip", + .type = MACHINE_TYPE_486_S3, + .chipset = MACHINE_CHIPSET_IMS_8848, + .init = machine_at_g486ip_init, + .p1_handler = NULL, + .gpio_handler = NULL, + .available_flag = MACHINE_AVAILABLE, + .gpio_acpi_handler = NULL, + .cpu = { + .package = CPU_PKG_SOCKET3, + .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_PS2_PCI, + .flags = MACHINE_IDE_DUAL | MACHINE_APM, + .ram = { + .min = 2048, + .max = 131072, + .step = 2048 + }, + .nvrmask = 127, + .kbc_device = NULL, + .kbc_p1 = 0xff, + .gpio = 0xffffffff, + .gpio_acpi = 0xffffffff, + .device = NULL, + .fdc_device = NULL, + .sio_device = NULL, + .vid_device = NULL, + .snd_device = NULL, + .net_device = NULL + }, /* This has an AMIKey-2, which is an updated version of type 'H'. */ - { "[SiS 496] ASUS PVI-486SP3C", "486sp3c", MACHINE_TYPE_486_S3, CPU_PKG_SOCKET3, 0, 0, 0, 0, 0, 0, 0, MACHINE_PCIV | MACHINE_BUS_PS2 | MACHINE_IDE_DUAL, 1024, 261120, 1024, 255, machine_at_486sp3c_init, NULL }, + { + .name = "[SiS 496] ASUS PVI-486SP3C", + .internal_name = "486sp3c", + .type = MACHINE_TYPE_486_S3, + .chipset = MACHINE_CHIPSET_SIS_496, + .init = machine_at_486sp3c_init, + .p1_handler = NULL, + .gpio_handler = NULL, + .available_flag = MACHINE_AVAILABLE, + .gpio_acpi_handler = NULL, + .cpu = { + .package = CPU_PKG_SOCKET3, + .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_PS2_PCIV, + .flags = MACHINE_IDE_DUAL | MACHINE_APM, + .ram = { + .min = 1024, + .max = 261120, + .step = 1024 + }, + .nvrmask = 255, + .kbc_device = NULL, + .kbc_p1 = 0xff, + .gpio = 0xffffffff, + .gpio_acpi = 0xffffffff, + .device = NULL, + .fdc_device = NULL, + .sio_device = NULL, + .vid_device = NULL, + .snd_device = NULL, + .net_device = NULL + }, /* This has an AMIKey-2, which is an updated version of type 'H'. */ - { "[SiS 496] Lucky Star LS-486E", "ls486e", MACHINE_TYPE_486_S3, CPU_PKG_SOCKET3, 0, 0, 0, 0, 0, 0, 0, MACHINE_PCI | MACHINE_IDE_DUAL, 1024, 131072, 1024, 255, machine_at_ls486e_init, NULL }, + { + .name = "[SiS 496] Lucky Star LS-486E", + .internal_name = "ls486e", + .type = MACHINE_TYPE_486_S3, + .chipset = MACHINE_CHIPSET_SIS_496, + .init = machine_at_ls486e_init, + .p1_handler = NULL, + .gpio_handler = NULL, + .available_flag = MACHINE_AVAILABLE, + .gpio_acpi_handler = NULL, + .cpu = { + .package = CPU_PKG_SOCKET3, + .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_BUS_PS2_LATCH | MACHINE_PCI, + .flags = MACHINE_IDE_DUAL | MACHINE_APM, + .ram = { + .min = 1024, + .max = 131072, + .step = 1024 + }, + .nvrmask = 255, + .kbc_device = NULL, + .kbc_p1 = 0xff, + .gpio = 0xffffffff, + .gpio_acpi = 0xffffffff, + .device = NULL, + .fdc_device = NULL, + .sio_device = NULL, + .vid_device = NULL, + .snd_device = NULL, + .net_device = NULL + }, /* The BIOS does not send a single non-standard KBC command, so it has a standard PS/2 KBC. */ - { "[SiS 496] Micronics M4Li", "m4li", MACHINE_TYPE_486_S3, CPU_PKG_SOCKET3, 0, 0, 0, 0, 0, 0, 0, MACHINE_PCI | MACHINE_BUS_PS2 | MACHINE_IDE_DUAL, 1024, 131072, 1024, 127, machine_at_m4li_init, NULL }, + { + .name = "[SiS 496] Micronics M4Li", + .internal_name = "m4li", + .type = MACHINE_TYPE_486_S3, + .chipset = MACHINE_CHIPSET_SIS_496, + .init = machine_at_m4li_init, + .p1_handler = NULL, + .gpio_handler = NULL, + .available_flag = MACHINE_AVAILABLE, + .gpio_acpi_handler = NULL, + .cpu = { + .package = CPU_PKG_SOCKET3, + .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_PS2_PCI, + .flags = MACHINE_IDE_DUAL | MACHINE_APM, + .ram = { + .min = 1024, + .max = 131072, + .step = 1024 + }, + .nvrmask = 127, + .kbc_device = NULL, + .kbc_p1 = 0xff, + .gpio = 0xffffffff, + .gpio_acpi = 0xffffffff, + .device = NULL, + .fdc_device = NULL, + .sio_device = NULL, + .vid_device = NULL, + .snd_device = NULL, + .net_device = NULL + }, /* Has a BestKey KBC which clones AMI type 'H'. */ - { "[SiS 496] Rise Computer R418", "r418", MACHINE_TYPE_486_S3, CPU_PKG_SOCKET3, 0, 0, 0, 0, 0, 0, 0, MACHINE_PCI | MACHINE_IDE_DUAL, 1024, 261120, 1024, 255, machine_at_r418_init, NULL }, + { + .name = "[SiS 496] Rise Computer R418", + .internal_name = "r418", + .type = MACHINE_TYPE_486_S3, + .chipset = MACHINE_CHIPSET_SIS_496, + .init = machine_at_r418_init, + .p1_handler = NULL, + .gpio_handler = NULL, + .available_flag = MACHINE_AVAILABLE, + .gpio_acpi_handler = NULL, + .cpu = { + .package = CPU_PKG_SOCKET3, + .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_BUS_PS2_LATCH | MACHINE_PCI, + .flags = MACHINE_IDE_DUAL | MACHINE_APM, + .ram = { + .min = 1024, + .max = 261120, + .step = 1024 + }, + .nvrmask = 255, + .kbc_device = NULL, + .kbc_p1 = 0xff, + .gpio = 0xffffffff, + .gpio_acpi = 0xffffffff, + .device = NULL, + .fdc_device = NULL, + .sio_device = NULL, + .vid_device = NULL, + .snd_device = NULL, + .net_device = NULL + }, /* This has a Holtek KBC and the BIOS does not send a single non-standard KBC command, so it must be an ASIC that clones the standard IBM PS/2 KBC. */ - { "[SiS 496] Soyo 4SAW2", "4saw2", MACHINE_TYPE_486_S3, CPU_PKG_SOCKET3, CPU_BLOCK(CPU_i486SX, CPU_i486DX, CPU_Am486SX, CPU_Am486DX), 0, 0, 0, 0, 0, 0, MACHINE_PCIV | MACHINE_BUS_PS2 | MACHINE_IDE_DUAL, 1024, 261120, 1024, 255, machine_at_4saw2_init, NULL }, + { + .name = "[SiS 496] Soyo 4SAW2", + .internal_name = "4saw2", + .type = MACHINE_TYPE_486_S3, + .chipset = MACHINE_CHIPSET_SIS_496, + .init = machine_at_4saw2_init, + .p1_handler = NULL, + .gpio_handler = NULL, + .available_flag = MACHINE_AVAILABLE, + .gpio_acpi_handler = NULL, + .cpu = { + .package = CPU_PKG_SOCKET3, + .block = CPU_BLOCK(CPU_i486SX, CPU_i486DX, CPU_Am486SX, CPU_Am486DX), + .min_bus = 0, + .max_bus = 0, + .min_voltage = 0, + .max_voltage = 0, + .min_multi = 0, + .max_multi = 0 + }, + .bus_flags = MACHINE_PS2_PCIV, + .flags = MACHINE_IDE_DUAL | MACHINE_APM, + .ram = { + .min = 2048, + .max = 261120, + .step = 1024 + }, + .nvrmask = 255, + .kbc_device = NULL, + .kbc_p1 = 0xff, + .gpio = 0xffffffff, + .gpio_acpi = 0xffffffff, + .device = NULL, + .fdc_device = NULL, + .sio_device = NULL, + .vid_device = NULL, + .snd_device = NULL, + .net_device = NULL + }, /* According to MrKsoft, his real 4DPS has an AMIKey-2, which is an updated version of type 'H'. */ - { "[SiS 496] Zida Tomato 4DP", "4dps", MACHINE_TYPE_486_S3, CPU_PKG_SOCKET3, 0, 0, 0, 0, 0, 0, 0, MACHINE_PCI | MACHINE_BUS_PS2 | MACHINE_IDE_DUAL, 1024, 261120, 1024, 255, machine_at_4dps_init, NULL }, + { + .name = "[SiS 496] Zida Tomato 4DP", + .internal_name = "4dps", + .type = MACHINE_TYPE_486_S3, + .chipset = MACHINE_CHIPSET_SIS_496, + .init = machine_at_4dps_init, + .p1_handler = NULL, + .gpio_handler = NULL, + .available_flag = MACHINE_AVAILABLE, + .gpio_acpi_handler = NULL, + .cpu = { + .package = CPU_PKG_SOCKET3, + .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_PS2_PCI, + .flags = MACHINE_IDE_DUAL | MACHINE_APM, + .ram = { + .min = 2048, + .max = 261120, + .step = 1024 + }, + .nvrmask = 255, + .kbc_device = NULL, + .kbc_p1 = 0xff, + .gpio = 0xffffffff, + .gpio_acpi = 0xffffffff, + .device = NULL, + .fdc_device = NULL, + .sio_device = NULL, + .vid_device = NULL, + .snd_device = NULL, + .net_device = NULL + }, /* This has the UMC 88xx on-chip KBC. */ - { "[UMC 8881] A-Trend ATC-1415", "atc1415", MACHINE_TYPE_486_S3, CPU_PKG_SOCKET3, 0, 0, 0, 0, 0, 0, 0, MACHINE_PCI | MACHINE_IDE_DUAL, 1024, 65536, 1024, 255, machine_at_atc1415_init, NULL }, + { + .name = "[UMC 8881] A-Trend ATC-1415", + .internal_name = "atc1415", + .type = MACHINE_TYPE_486_S3, + .chipset = MACHINE_CHIPSET_UMC_UM8881, + .init = machine_at_atc1415_init, + .p1_handler = NULL, + .gpio_handler = NULL, + .available_flag = MACHINE_AVAILABLE, + .gpio_acpi_handler = NULL, + .cpu = { + .package = CPU_PKG_SOCKET3, + .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_PCI, + .flags = MACHINE_IDE_DUAL | MACHINE_APM, + .ram = { + .min = 1024, + .max = 65536, + .step = 1024 + }, + .nvrmask = 255, + .kbc_device = NULL, + .kbc_p1 = 0xff, + .gpio = 0xffffffff, + .gpio_acpi = 0xffffffff, + .device = NULL, + .fdc_device = NULL, + .sio_device = NULL, + .vid_device = NULL, + .snd_device = NULL, + .net_device = NULL + }, /* This has an AMIKey-2, which is an updated version of type 'H'. */ - { "[UMC 8881] ECS Elite UM8810PAIO", "ecs486", MACHINE_TYPE_486_S3, CPU_PKG_SOCKET3, 0, 0, 0, 0, 0, 0, 0, MACHINE_PCI | MACHINE_IDE_DUAL, 1024, 131072, 1024, 255, machine_at_ecs486_init, NULL }, + { + .name = "[UMC 8881] ECS Elite UM8810PAIO", + .internal_name = "ecs486", + .type = MACHINE_TYPE_486_S3, + .chipset = MACHINE_CHIPSET_UMC_UM8881, + .init = machine_at_ecs486_init, + .p1_handler = NULL, + .gpio_handler = NULL, + .available_flag = MACHINE_AVAILABLE, + .gpio_acpi_handler = NULL, + .cpu = { + .package = CPU_PKG_SOCKET3, + .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_PCI | MACHINE_BUS_PS2_LATCH, + .flags = MACHINE_IDE_DUAL | MACHINE_APM, + .ram = { + .min = 1024, + .max = 131072, + .step = 1024 + }, + .nvrmask = 255, + .kbc_device = NULL, + .kbc_p1 = 0xff, + .gpio = 0xffffffff, + .gpio_acpi = 0xffffffff, + .device = NULL, + .fdc_device = NULL, + .sio_device = NULL, + .vid_device = NULL, + .snd_device = NULL, + .net_device = NULL + }, /* Has AMIKey Z(!) KBC firmware. */ - { "[UMC 8881] Epson Action PC 2600", "actionpc2600", MACHINE_TYPE_486_S3, CPU_PKG_SOCKET3, 0, 0, 0, 0, 0, 0, 0, MACHINE_PCI | MACHINE_IDE_DUAL, 1024, 262144, 1024, 255, machine_at_actionpc2600_init, NULL }, + { + .name = "[UMC 8881] Epson Action PC 2600", + .internal_name = "actionpc2600", + .type = MACHINE_TYPE_486_S3, + .chipset = MACHINE_CHIPSET_UMC_UM8881, + .init = machine_at_actionpc2600_init, + .p1_handler = NULL, + .gpio_handler = NULL, + .available_flag = MACHINE_AVAILABLE, + .gpio_acpi_handler = NULL, + .cpu = { + .package = CPU_PKG_SOCKET3, + .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_PS2_PCI, + .flags = MACHINE_IDE_DUAL | MACHINE_APM, + .ram = { + .min = 1024, + .max = 262144, + .step = 1024 + }, + .nvrmask = 255, + .kbc_device = NULL, + .kbc_p1 = 0xff, + .gpio = 0xffffffff, + .gpio_acpi = 0xffffffff, + .device = NULL, + .fdc_device = NULL, + .sio_device = NULL, + .vid_device = NULL, + .snd_device = NULL, + .net_device = NULL + }, /* This has the UMC 88xx on-chip KBC. All the copies of the BIOS string I can find, end in in -H, so the UMC on-chip KBC likely emulates the AMI 'H' KBC firmware. */ - { "[UMC 8881] PC Chips M919", "m919", MACHINE_TYPE_486_S3, CPU_PKG_SOCKET3, 0, 0, 0, 0, 0, 0, 0, MACHINE_PCI | MACHINE_VLB | MACHINE_IDE_DUAL, 1024, 131072, 1024, 255, machine_at_m919_init, NULL }, + { + .name = "[UMC 8881] PC Chips M919", + .internal_name = "m919", + .type = MACHINE_TYPE_486_S3, + .chipset = MACHINE_CHIPSET_UMC_UM8881, + .init = machine_at_m919_init, + .p1_handler = NULL, + .gpio_handler = NULL, + .available_flag = MACHINE_AVAILABLE, + .gpio_acpi_handler = NULL, + .cpu = { + .package = CPU_PKG_SOCKET3, + .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_PCIV, + .flags = MACHINE_IDE_DUAL | MACHINE_APM, + .ram = { + .min = 1024, + .max = 131072, + .step = 1024 + }, + .nvrmask = 255, + .kbc_device = NULL, + .kbc_p1 = 0xff, + .gpio = 0xffffffff, + .gpio_acpi = 0xffffffff, + .device = NULL, + .fdc_device = NULL, + .sio_device = NULL, + .vid_device = NULL, + .snd_device = NULL, + .net_device = NULL + }, /* Has IBM PS/2 Type 1 KBC firmware. Uses a mysterious I/O port C05. */ - { "[UMC 8881] Samsung SPC7700P-LW", "spc7700plw", MACHINE_TYPE_486_S3, CPU_PKG_SOCKET3, 0, 0, 0, 0, 0, 0, 0, MACHINE_PCI | MACHINE_BUS_PS2 | MACHINE_IDE_DUAL, 1024, 131072, 1024, 255, machine_at_spc7700plw_init, NULL }, + { + .name = "[UMC 8881] Samsung SPC7700P-LW", + .internal_name = "spc7700plw", + .type = MACHINE_TYPE_486_S3, + .chipset = MACHINE_CHIPSET_UMC_UM8881, + .init = machine_at_spc7700plw_init, + .p1_handler = NULL, + .gpio_handler = NULL, + .available_flag = MACHINE_AVAILABLE, + .gpio_acpi_handler = NULL, + .cpu = { + .package = CPU_PKG_SOCKET3, + .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_PS2_PCI, + .flags = MACHINE_IDE_DUAL | MACHINE_APM, + .ram = { + .min = 1024, + .max = 131072, + .step = 1024 + }, + .nvrmask = 255, + .kbc_device = NULL, + .kbc_p1 = 0xff, + .gpio = 0xffffffff, + .gpio_acpi = 0xffffffff, + .device = NULL, + .fdc_device = NULL, + .sio_device = NULL, + .vid_device = NULL, + .snd_device = NULL, + .net_device = NULL + }, /* This has a Holtek KBC. */ - { "[UMC 8881] Shuttle HOT-433A", "hot433", MACHINE_TYPE_486_S3, CPU_PKG_SOCKET3, 0, 0, 0, 0, 0, 0, 0, MACHINE_PCI | MACHINE_IDE_DUAL, 1024, 262144, 1024, 255, machine_at_hot433_init, NULL }, + { + .name = "[UMC 8881] Shuttle HOT-433A", + .internal_name = "hot433", + .type = MACHINE_TYPE_486_S3, + .chipset = MACHINE_CHIPSET_UMC_UM8881, + .init = machine_at_hot433_init, + .p1_handler = NULL, + .gpio_handler = NULL, + .available_flag = MACHINE_AVAILABLE, + .gpio_acpi_handler = NULL, + .cpu = { + .package = CPU_PKG_SOCKET3, + .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_PCI, + .flags = MACHINE_IDE_DUAL | MACHINE_APM, + .ram = { + .min = 1024, + .max = 262144, + .step = 1024 + }, + .nvrmask = 255, + .kbc_device = NULL, + .kbc_p1 = 0xff, + .gpio = 0xffffffff, + .gpio_acpi = 0xffffffff, + .device = NULL, + .fdc_device = NULL, + .sio_device = NULL, + .vid_device = NULL, + .snd_device = NULL, + .net_device = NULL + }, /* Has a VIA VT82C406 KBC+RTC that likely has identical commands to the VT82C42N. */ - { "[VIA VT82C496G] DFI G486VPA", "g486vpa", MACHINE_TYPE_486_S3, CPU_PKG_SOCKET3, 0, 0, 0, 0, 0, 0, 0, MACHINE_PCIV | MACHINE_IDE_DUAL, 1024, 131072, 1024, 255, machine_at_g486vpa_init, NULL }, + { + .name = "[VIA VT82C496G] DFI G486VPA", + .internal_name = "g486vpa", + .type = MACHINE_TYPE_486_S3, + .chipset = MACHINE_CHIPSET_VIA_VT82C496G, + .init = machine_at_g486vpa_init, + .p1_handler = NULL, + .gpio_handler = NULL, + .available_flag = MACHINE_AVAILABLE, + .gpio_acpi_handler = NULL, + .cpu = { + .package = CPU_PKG_SOCKET3, + .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_PCIV, + .flags = MACHINE_IDE_DUAL | MACHINE_APM, + .ram = { + .min = 1024, + .max = 131072, + .step = 1024 + }, + .nvrmask = 255, + .kbc_device = NULL, + .kbc_p1 = 0xff, + .gpio = 0xffffffff, + .gpio_acpi = 0xffffffff, + .device = NULL, + .fdc_device = NULL, + .sio_device = NULL, + .vid_device = NULL, + .snd_device = NULL, + .net_device = NULL + }, /* Has a VIA VT82C42N KBC. */ - { "[VIA VT82C496G] FIC VIP-IO2", "486vipio2", MACHINE_TYPE_486_S3, CPU_PKG_SOCKET3, 0, 0, 0, 0, 0, 0, 0, MACHINE_PCIV | MACHINE_BUS_PS2 | MACHINE_IDE_DUAL, 1024, 131072, 1024, 255, machine_at_486vipio2_init, NULL }, + { + .name = "[VIA VT82C496G] FIC VIP-IO2", + .internal_name = "486vipio2", + .type = MACHINE_TYPE_486_S3, + .chipset = MACHINE_CHIPSET_VIA_VT82C496G, + .init = machine_at_486vipio2_init, + .p1_handler = NULL, + .gpio_handler = NULL, + .available_flag = MACHINE_AVAILABLE, + .gpio_acpi_handler = NULL, + .cpu = { + .package = CPU_PKG_SOCKET3, + .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_PS2_PCIV, + .flags = MACHINE_IDE_DUAL | MACHINE_APM, + .ram = { + .min = 1024, + .max = 131072, + .step = 1024 + }, + .nvrmask = 255, + .kbc_device = NULL, + .kbc_p1 = 0xff, + .gpio = 0xffffffff, + .gpio_acpi = 0xffffffff, + .device = NULL, + .fdc_device = NULL, + .sio_device = NULL, + .vid_device = NULL, + .snd_device = NULL, + .net_device = NULL + }, /* 486 machines - Miscellaneous */ /* 486 machines which utilize the PCI bus */ /* Has a Winbond W83977F Super I/O chip with on-chip KBC with AMIKey-2 KBC firmware. */ - { "[STPC Client] ITOX STAR", "itoxstar", MACHINE_TYPE_486_MISC, CPU_PKG_STPC, 0, 66666667, 75000000, 0, 0, 1.0, 1.0, MACHINE_PCI | MACHINE_BUS_PS2 | MACHINE_IDE_DUAL, 8192, 131072, 8192, 255, machine_at_itoxstar_init, NULL }, + { + .name = "[STPC Client] ITOX STAR", + .internal_name = "itoxstar", + .type = MACHINE_TYPE_486_MISC, + .chipset = MACHINE_CHIPSET_STPC_CLIENT, + .init = machine_at_itoxstar_init, + .p1_handler = NULL, + .gpio_handler = NULL, + .available_flag = MACHINE_AVAILABLE, + .gpio_acpi_handler = NULL, + .cpu = { + .package = CPU_PKG_STPC, + .block = CPU_BLOCK_NONE, + .min_bus = 66666667, + .max_bus = 75000000, + .min_voltage = 0, + .max_voltage = 0, + .min_multi = 1.0, + .max_multi = 1.0 + }, + .bus_flags = MACHINE_PS2_PCI, + .flags = MACHINE_IDE_DUAL | MACHINE_APM, + .ram = { + .min = 8192, + .max = 131072, + .step = 8192 + }, + .nvrmask = 255, + .kbc_device = NULL, + .kbc_p1 = 0xff, + .gpio = 0xffffffff, + .gpio_acpi = 0xffffffff, + .device = NULL, + .fdc_device = NULL, + .sio_device = NULL, + .vid_device = NULL, + .snd_device = NULL, + .net_device = NULL + }, /* Has a Winbond W83977F Super I/O chip with on-chip KBC with AMIKey-2 KBC firmware. */ - { "[STPC Consumer-II] Acrosser AR-B1423C", "arb1423c", MACHINE_TYPE_486_MISC, CPU_PKG_STPC, 0, 66666667, 66666667, 0, 0, 2.0, 2.0, MACHINE_PCI | MACHINE_BUS_PS2 | MACHINE_IDE_DUAL, 32768, 163840, 8192, 255, machine_at_arb1423c_init, NULL }, + { + .name = "[STPC Consumer-II] Acrosser AR-B1423C", + .internal_name = "arb1423c", + .type = MACHINE_TYPE_486_MISC, + .chipset = MACHINE_CHIPSET_STPC_CONSUMER_II, + .init = machine_at_arb1423c_init, + .p1_handler = NULL, + .gpio_handler = NULL, + .available_flag = MACHINE_AVAILABLE, + .gpio_acpi_handler = NULL, + .cpu = { + .package = CPU_PKG_STPC, + .block = CPU_BLOCK_NONE, + .min_bus = 66666667, + .max_bus = 66666667, + .min_voltage = 0, + .max_voltage = 0, + .min_multi = 2.0, + .max_multi = 2.0 + }, + .bus_flags = MACHINE_PS2_PCI, + .flags = MACHINE_IDE_DUAL | MACHINE_APM, + .ram = { + .min = 32768, + .max = 163840, + .step = 8192 + }, + .nvrmask = 255, + .kbc_device = NULL, + .kbc_p1 = 0xff, + .gpio = 0xffffffff, + .gpio_acpi = 0xffffffff, + .device = NULL, + .fdc_device = NULL, + .sio_device = NULL, + .vid_device = NULL, + .snd_device = NULL, + .net_device = NULL + }, /* Has a Winbond W83977F Super I/O chip with on-chip KBC with AMIKey-2 KBC firmware. */ - { "[STPC Consumer-II] Acrosser AR-B1479", "arb1479", MACHINE_TYPE_486_MISC, CPU_PKG_STPC, 0, 66666667, 66666667, 0, 0, 2.0, 2.0, MACHINE_PCI | MACHINE_BUS_PS2 | MACHINE_IDE_DUAL, 32768, 163840, 8192, 255, machine_at_arb1479_init, NULL }, + { + .name = "[STPC Consumer-II] Acrosser AR-B1479", + .internal_name = "arb1479", + .type = MACHINE_TYPE_486_MISC, + .chipset = MACHINE_CHIPSET_STPC_CONSUMER_II, + .init = machine_at_arb1479_init, + .p1_handler = NULL, + .gpio_handler = NULL, + .available_flag = MACHINE_AVAILABLE, + .gpio_acpi_handler = NULL, + .cpu = { + .package = CPU_PKG_STPC, + .block = CPU_BLOCK_NONE, + .min_bus = 66666667, + .max_bus = 66666667, + .min_voltage = 0, + .max_voltage = 0, + .min_multi = 2.0, + .max_multi = 2.0 + }, + .bus_flags = MACHINE_PS2_PCI, + .flags = MACHINE_IDE_DUAL | MACHINE_APM, + .ram = { + .min = 32768, + .max = 163840, + .step = 8192 + }, + .nvrmask = 255, + .kbc_device = NULL, + .kbc_p1 = 0xff, + .gpio = 0xffffffff, + .gpio_acpi = 0xffffffff, + .device = NULL, + .fdc_device = NULL, + .sio_device = NULL, + .vid_device = NULL, + .snd_device = NULL, + .net_device = NULL + }, /* Has a Winbond W83977F Super I/O chip with on-chip KBC with AMIKey-2 KBC firmware. */ - { "[STPC Elite] Advantech PCM-9340", "pcm9340", MACHINE_TYPE_486_MISC, CPU_PKG_STPC, 0, 66666667, 66666667, 0, 0, 2.0, 2.0, MACHINE_PCI | MACHINE_BUS_PS2 | MACHINE_IDE_DUAL, 32768, 98304, 8192, 255, machine_at_pcm9340_init, NULL }, + { + .name = "[STPC Elite] Advantech PCM-9340", + .internal_name = "pcm9340", + .type = MACHINE_TYPE_486_MISC, + .chipset = MACHINE_CHIPSET_STPC_ELITE, + .init = machine_at_pcm9340_init, + .p1_handler = NULL, + .gpio_handler = NULL, + .available_flag = MACHINE_AVAILABLE, + .gpio_acpi_handler = NULL, + .cpu = { + .package = CPU_PKG_STPC, + .block = CPU_BLOCK_NONE, + .min_bus = 66666667, + .max_bus = 66666667, + .min_voltage = 0, + .max_voltage = 0, + .min_multi = 2.0, + .max_multi = 2.0 + }, + .bus_flags = MACHINE_PS2_PCI, + .flags = MACHINE_IDE_DUAL | MACHINE_APM, + .ram = { + .min = 32768, + .max = 98304, + .step = 8192 + }, + .nvrmask = 255, + .kbc_device = NULL, + .kbc_p1 = 0xff, + .gpio = 0xffffffff, + .gpio_acpi = 0xffffffff, + .device = NULL, + .fdc_device = NULL, + .sio_device = NULL, + .vid_device = NULL, + .snd_device = NULL, + .net_device = NULL + }, /* Has a Winbond W83977F Super I/O chip with on-chip KBC with AMIKey-2 KBC firmware. */ - { "[STPC Atlas] AAEON PCM-5330", "pcm5330", MACHINE_TYPE_486_MISC, CPU_PKG_STPC, 0, 66666667, 66666667, 0, 0, 2.0, 2.0, MACHINE_PCI | MACHINE_BUS_PS2 | MACHINE_IDE_DUAL, 32768, 131072,32768, 255, machine_at_pcm5330_init, NULL }, + { + .name = "[STPC Atlas] AAEON PCM-5330", + .internal_name = "pcm5330", + .type = MACHINE_TYPE_486_MISC, + .chipset = MACHINE_CHIPSET_STPC_ATLAS, + .init = machine_at_pcm5330_init, + .p1_handler = NULL, + .gpio_handler = NULL, + .available_flag = MACHINE_AVAILABLE, + .gpio_acpi_handler = NULL, + .cpu = { + .package = CPU_PKG_STPC, + .block = CPU_BLOCK_NONE, + .min_bus = 66666667, + .max_bus = 66666667, + .min_voltage = 0, + .max_voltage = 0, + .min_multi = 2.0, + .max_multi = 2.0 + }, + .bus_flags = MACHINE_PS2_PCI, + .flags = MACHINE_IDE_DUAL | MACHINE_APM, + .ram = { + .min = 32768, + .max = 131072, + .step = 32768 + }, + .nvrmask = 255, + .kbc_device = NULL, + .kbc_p1 = 0xff, + .gpio = 0xffffffff, + .gpio_acpi = 0xffffffff, + .device = NULL, + .fdc_device = NULL, + .sio_device = NULL, + .vid_device = NULL, + .snd_device = NULL, + .net_device = NULL + }, /* Socket 4 machines */ /* 430LX */ @@ -493,554 +7721,5922 @@ const machine_t machines[] = { connector. The boot block for BIOS recovery requires an unknown bit on port 805h to be clear. */ - { "[i430LX] AMI Excalibur PCI Pentium", "excaliburpci", MACHINE_TYPE_SOCKET4, CPU_PKG_SOCKET4, 0, 60000000, 66666667, 5000, 5000, MACHINE_MULTIPLIER_FIXED, MACHINE_PCI | MACHINE_BUS_PS2 | MACHINE_IDE_DUAL, 2048, 131072, 2048, 127, machine_at_excaliburpci_init, NULL }, + { + .name = "[i430LX] AMI Excalibur PCI Pentium", + .internal_name = "excaliburpci", + .type = MACHINE_TYPE_SOCKET4, + .chipset = MACHINE_CHIPSET_INTEL_430LX, + .init = machine_at_excaliburpci_init, + .p1_handler = NULL, + .gpio_handler = NULL, + .available_flag = MACHINE_AVAILABLE, + .gpio_acpi_handler = NULL, + .cpu = { + .package = CPU_PKG_SOCKET4, + .block = CPU_BLOCK_NONE, + .min_bus = 60000000, + .max_bus = 66666667, + .min_voltage = 5000, + .max_voltage = 5000, + .min_multi = MACHINE_MULTIPLIER_FIXED, + .max_multi = MACHINE_MULTIPLIER_FIXED + }, + .bus_flags = MACHINE_PS2_PCI, + .flags = MACHINE_IDE_DUAL | MACHINE_APM | MACHINE_ACPI, + .ram = { + .min = 2048, + .max = 131072, + .step = 2048 + }, + .nvrmask = 127, + .kbc_device = NULL, + .kbc_p1 = 0xff, + .gpio = 0xffffffff, + .gpio_acpi = 0xffffffff, + .device = NULL, + .fdc_device = NULL, + .sio_device = NULL, + .vid_device = NULL, + .snd_device = NULL, + .net_device = NULL + }, /* Has AMIKey F KBC firmware (AMIKey). */ - { "[i430LX] ASUS P/I-P5MP3", "p5mp3", MACHINE_TYPE_SOCKET4, CPU_PKG_SOCKET4, 0, 60000000, 66666667, 5000, 5000, MACHINE_MULTIPLIER_FIXED, MACHINE_PCI | MACHINE_BUS_PS2 | MACHINE_IDE, 2048, 196608, 2048, 127, machine_at_p5mp3_init, NULL }, + { + .name = "[i430LX] ASUS P/I-P5MP3", + .internal_name = "p5mp3", + .type = MACHINE_TYPE_SOCKET4, + .chipset = MACHINE_CHIPSET_INTEL_430LX, + .init = machine_at_p5mp3_init, + .p1_handler = NULL, + .gpio_handler = NULL, + .available_flag = MACHINE_AVAILABLE, + .gpio_acpi_handler = NULL, + .cpu = { + .package = CPU_PKG_SOCKET4, + .block = CPU_BLOCK_NONE, + .min_bus = 60000000, + .max_bus = 66666667, + .min_voltage = 5000, + .max_voltage = 5000, + .min_multi = MACHINE_MULTIPLIER_FIXED, + .max_multi = MACHINE_MULTIPLIER_FIXED + }, + .bus_flags = MACHINE_PS2_PCI, + .flags = MACHINE_IDE | MACHINE_APM | MACHINE_ACPI, + .ram = { + .min = 2048, + .max = 196608, + .step = 2048 + }, + .nvrmask = 127, + .kbc_device = NULL, + .kbc_p1 = 0xff, + .gpio = 0xffffffff, + .gpio_acpi = 0xffffffff, + .device = NULL, + .fdc_device = NULL, + .sio_device = NULL, + .vid_device = NULL, + .snd_device = NULL, + .net_device = NULL + }, /* Has IBM PS/2 Type 1 KBC firmware. */ - { "[i430LX] Dell Dimension XPS P60", "dellxp60", MACHINE_TYPE_SOCKET4, CPU_PKG_SOCKET4, 0, 60000000, 66666667, 5000, 5000, MACHINE_MULTIPLIER_FIXED, MACHINE_PCI | MACHINE_BUS_PS2 | MACHINE_IDE, 2048, 131072, 2048, 127, machine_at_dellxp60_init, NULL }, + { + .name = "[i430LX] Dell Dimension XPS P60", + .internal_name = "dellxp60", + .type = MACHINE_TYPE_SOCKET4, + .chipset = MACHINE_CHIPSET_INTEL_430LX, + .init = machine_at_dellxp60_init, + .p1_handler = NULL, + .gpio_handler = NULL, + .available_flag = MACHINE_AVAILABLE, + .gpio_acpi_handler = NULL, + .cpu = { + .package = CPU_PKG_SOCKET4, + .block = CPU_BLOCK_NONE, + .min_bus = 60000000, + .max_bus = 66666667, + .min_voltage = 5000, + .max_voltage = 5000, + .min_multi = MACHINE_MULTIPLIER_FIXED, + .max_multi = MACHINE_MULTIPLIER_FIXED + }, + .bus_flags = MACHINE_PS2_PCI, + .flags = MACHINE_IDE | MACHINE_APM | MACHINE_ACPI, + .ram = { + .min = 2048, + .max = 131072, + .step = 2048 + }, + .nvrmask = 127, + .kbc_device = NULL, + .kbc_p1 = 0xff, + .gpio = 0xffffffff, + .gpio_acpi = 0xffffffff, + .device = NULL, + .fdc_device = NULL, + .sio_device = NULL, + .vid_device = NULL, + .snd_device = NULL, + .net_device = NULL + }, /* Has IBM PS/2 Type 1 KBC firmware. */ - { "[i430LX] Dell OptiPlex 560/L", "opti560l", MACHINE_TYPE_SOCKET4, CPU_PKG_SOCKET4, 0, 60000000, 66666667, 5000, 5000, MACHINE_MULTIPLIER_FIXED, MACHINE_PCI | MACHINE_BUS_PS2 | MACHINE_IDE_DUAL, 2048, 131072, 2048, 127, machine_at_opti560l_init, NULL }, + { + .name = "[i430LX] Dell OptiPlex 560/L", + .internal_name = "opti560l", + .type = MACHINE_TYPE_SOCKET4, + .chipset = MACHINE_CHIPSET_INTEL_430LX, + .init = machine_at_opti560l_init, + .p1_handler = NULL, + .gpio_handler = NULL, + .available_flag = MACHINE_AVAILABLE, + .gpio_acpi_handler = NULL, + .cpu = { + .package = CPU_PKG_SOCKET4, + .block = CPU_BLOCK_NONE, + .min_bus = 60000000, + .max_bus = 66666667, + .min_voltage = 5000, + .max_voltage = 5000, + .min_multi = MACHINE_MULTIPLIER_FIXED, + .max_multi = MACHINE_MULTIPLIER_FIXED + }, + .bus_flags = MACHINE_PS2_PCI, + .flags = MACHINE_IDE_DUAL | MACHINE_APM | MACHINE_ACPI, + .ram = { + .min = 2048, + .max = 131072, + .step = 2048 + }, + .nvrmask = 127, + .kbc_device = NULL, + .kbc_p1 = 0xff, + .gpio = 0xffffffff, + .gpio_acpi = 0xffffffff, + .device = NULL, + .fdc_device = NULL, + .sio_device = NULL, + .vid_device = NULL, + .snd_device = NULL, + .net_device = NULL + }, /* This has the Phoenix MultiKey KBC firmware. This is basically an Intel Batman (*NOT* Batman's Revenge) with a fancier POST screen */ - { "[i430LX] AMBRA DP60 PCI", "ambradp60", MACHINE_TYPE_SOCKET4, CPU_PKG_SOCKET4, 0, 60000000, 66666667, 5000, 5000, MACHINE_MULTIPLIER_FIXED, MACHINE_PCI | MACHINE_BUS_PS2 | MACHINE_IDE_DUAL, 2048, 131072, 2048, 127, machine_at_ambradp60_init, NULL }, + { + .name = "[i430LX] AMBRA DP60 PCI", + .internal_name = "ambradp60", + .type = MACHINE_TYPE_SOCKET4, + .chipset = MACHINE_CHIPSET_INTEL_430LX, + .init = machine_at_ambradp60_init, + .p1_handler = NULL, + .gpio_handler = NULL, + .available_flag = MACHINE_AVAILABLE, + .gpio_acpi_handler = NULL, + .cpu = { + .package = CPU_PKG_SOCKET4, + .block = CPU_BLOCK_NONE, + .min_bus = 60000000, + .max_bus = 66666667, + .min_voltage = 5000, + .max_voltage = 5000, + .min_multi = MACHINE_MULTIPLIER_FIXED, + .max_multi = MACHINE_MULTIPLIER_FIXED + }, + .bus_flags = MACHINE_PS2_PCI, + .flags = MACHINE_IDE_DUAL | MACHINE_APM | MACHINE_ACPI, + .ram = { + .min = 2048, + .max = 131072, + .step = 2048 + }, + .nvrmask = 127, + .kbc_device = NULL, + .kbc_p1 = 0xff, + .gpio = 0xffffffff, + .gpio_acpi = 0xffffffff, + .device = NULL, + .fdc_device = NULL, + .sio_device = NULL, + .vid_device = NULL, + .snd_device = NULL, + .net_device = NULL + }, /* Has IBM PS/2 Type 1 KBC firmware. */ - { "[i430LX] IBM PS/ValuePoint P60", "valuepointp60", MACHINE_TYPE_SOCKET4, CPU_PKG_SOCKET4, 0, 60000000, 66666667, 5000, 5000, MACHINE_MULTIPLIER_FIXED, MACHINE_PCI | MACHINE_BUS_PS2 | MACHINE_IDE_DUAL, 2048, 131072, 2048, 127, machine_at_valuepointp60_init, NULL }, + { + .name = "[i430LX] IBM PS/ValuePoint P60", + .internal_name = "valuepointp60", + .type = MACHINE_TYPE_SOCKET4, + .chipset = MACHINE_CHIPSET_INTEL_430LX, + .init = machine_at_valuepointp60_init, + .p1_handler = NULL, + .gpio_handler = NULL, + .available_flag = MACHINE_AVAILABLE, + .gpio_acpi_handler = NULL, + .cpu = { + .package = CPU_PKG_SOCKET4, + .block = CPU_BLOCK_NONE, + .min_bus = 60000000, + .max_bus = 66666667, + .min_voltage = 5000, + .max_voltage = 5000, + .min_multi = MACHINE_MULTIPLIER_FIXED, + .max_multi = MACHINE_MULTIPLIER_FIXED + }, + .bus_flags = MACHINE_PS2_PCI, + .flags = MACHINE_IDE_DUAL | MACHINE_VIDEO | MACHINE_VIDEO_8514A | MACHINE_APM | MACHINE_ACPI, + .ram = { + .min = 2048, + .max = 131072, + .step = 2048 + }, + .nvrmask = 127, + .kbc_device = NULL, + .kbc_p1 = 0xff, + .gpio = 0xffffffff, + .gpio_acpi = 0xffffffff, + .device = NULL, + .fdc_device = NULL, + .sio_device = NULL, + .vid_device = &mach32_onboard_pci_device, + .snd_device = NULL, + .net_device = NULL + }, /* This has the Phoenix MultiKey KBC firmware. */ - { "[i430LX] Intel Premiere/PCI", "revenge", MACHINE_TYPE_SOCKET4, CPU_PKG_SOCKET4, 0, 60000000, 66666667, 5000, 5000, MACHINE_MULTIPLIER_FIXED, MACHINE_PCI | MACHINE_BUS_PS2 | MACHINE_IDE_DUAL, 2048, 131072, 2048, 127, machine_at_revenge_init, NULL }, + { + .name = "[i430LX] Intel Premiere/PCI", + .internal_name = "revenge", + .type = MACHINE_TYPE_SOCKET4, + .chipset = MACHINE_CHIPSET_INTEL_430LX, + .init = machine_at_revenge_init, + .p1_handler = NULL, + .gpio_handler = NULL, + .available_flag = MACHINE_AVAILABLE, + .gpio_acpi_handler = NULL, + .cpu = { + .package = CPU_PKG_SOCKET4, + .block = CPU_BLOCK_NONE, + .min_bus = 60000000, + .max_bus = 66666667, + .min_voltage = 5000, + .max_voltage = 5000, + .min_multi = MACHINE_MULTIPLIER_FIXED, + .max_multi = MACHINE_MULTIPLIER_FIXED + }, + .bus_flags = MACHINE_PS2_PCI, + .flags = MACHINE_IDE_DUAL | MACHINE_APM | MACHINE_ACPI, + .ram = { + .min = 2048, + .max = 131072, + .step = 2048 + }, + .nvrmask = 127, + .kbc_device = NULL, + .kbc_p1 = 0xff, + .gpio = 0xffffffff, + .gpio_acpi = 0xffffffff, + .device = NULL, + .fdc_device = NULL, + .sio_device = NULL, + .vid_device = NULL, + .snd_device = NULL, + .net_device = NULL + }, /* Has AMI MegaKey KBC firmware. */ - { "[i430LX] Micro Star 586MC1", "586mc1", MACHINE_TYPE_SOCKET4, CPU_PKG_SOCKET4, 0, 60000000, 66666667, 5000, 5000, MACHINE_MULTIPLIER_FIXED, MACHINE_PCI | MACHINE_BUS_PS2 | MACHINE_IDE_DUAL, 2048, 131072, 2048, 127, machine_at_586mc1_init, NULL }, + { + .name = "[i430LX] Micro Star 586MC1", + .internal_name = "586mc1", + .type = MACHINE_TYPE_SOCKET4, + .chipset = MACHINE_CHIPSET_INTEL_430LX, + .init = machine_at_586mc1_init, + .p1_handler = NULL, + .gpio_handler = NULL, + .available_flag = MACHINE_AVAILABLE, + .gpio_acpi_handler = NULL, + .cpu = { + .package = CPU_PKG_SOCKET4, + .block = CPU_BLOCK_NONE, + .min_bus = 60000000, + .max_bus = 66666667, + .min_voltage = 5000, + .max_voltage = 5000, + .min_multi = MACHINE_MULTIPLIER_FIXED, + .max_multi = MACHINE_MULTIPLIER_FIXED + }, + .bus_flags = MACHINE_PS2_PCI, + .flags = MACHINE_IDE_DUAL | MACHINE_APM | MACHINE_ACPI, + .ram = { + .min = 2048, + .max = 131072, + .step = 2048 + }, + .nvrmask = 127, + .kbc_device = NULL, + .kbc_p1 = 0xff, + .gpio = 0xffffffff, + .gpio_acpi = 0xffffffff, + .device = NULL, + .fdc_device = NULL, + .sio_device = NULL, + .vid_device = NULL, + .snd_device = NULL, + .net_device = NULL + }, /* This has the Phoenix MultiKey KBC firmware. */ - { "[i430LX] Packard Bell PB520R", "pb520r", MACHINE_TYPE_SOCKET4, CPU_PKG_SOCKET4, 0, 60000000, 66666667, 5000, 5000, MACHINE_MULTIPLIER_FIXED, MACHINE_PCI | MACHINE_BUS_PS2 | MACHINE_IDE_DUAL | MACHINE_VIDEO, 8192, 139264, 2048, 127, machine_at_pb520r_init, at_pb520r_get_device }, + { + .name = "[i430LX] Packard Bell PB520R", + .internal_name = "pb520r", + .type = MACHINE_TYPE_SOCKET4, + .chipset = MACHINE_CHIPSET_INTEL_430LX, + .init = machine_at_pb520r_init, + .p1_handler = NULL, + .gpio_handler = NULL, + .available_flag = MACHINE_AVAILABLE, + .gpio_acpi_handler = NULL, + .cpu = { + .package = CPU_PKG_SOCKET4, + .block = CPU_BLOCK_NONE, + .min_bus = 60000000, + .max_bus = 66666667, + .min_voltage = 5000, + .max_voltage = 5000, + .min_multi = MACHINE_MULTIPLIER_FIXED, + .max_multi = MACHINE_MULTIPLIER_FIXED + }, + .bus_flags = MACHINE_PS2_PCI, + .flags = MACHINE_IDE_DUAL | MACHINE_VIDEO | MACHINE_APM | MACHINE_ACPI, + .ram = { + .min = 8192, + .max = 139264, + .step = 2048 + }, + .nvrmask = 127, + .kbc_device = NULL, + .kbc_p1 = 0xff, + .gpio = 0xffffffff, + .gpio_acpi = 0xffffffff, + .device = NULL, + .fdc_device = NULL, + .sio_device = NULL, + .vid_device = &gd5434_onboard_pci_device, + .snd_device = NULL, + .net_device = NULL + }, /* OPTi 596/597 */ /* This uses an AMI KBC firmware in PS/2 mode (it sends command A5 with the PS/2 "Load Security" meaning), most likely MegaKey as it sends command AF (Set Extended Controller RAM) just like the later Intel AMI BIOS'es. */ - { "[OPTi 597] AMI Excalibur VLB", "excalibur", MACHINE_TYPE_SOCKET4, CPU_PKG_SOCKET4, 0, 60000000, 60000000, 5000, 5000, MACHINE_MULTIPLIER_FIXED, MACHINE_VLB | MACHINE_BUS_PS2 | MACHINE_IDE, 2048, 65536, 2048, 127, machine_at_excalibur_init, NULL }, + { + .name = "[OPTi 597] AMI Excalibur VLB", + .internal_name = "excalibur", + .type = MACHINE_TYPE_SOCKET4, + .chipset = MACHINE_CHIPSET_OPTI_547_597, + .init = machine_at_excalibur_init, + .p1_handler = NULL, + .gpio_handler = NULL, + .available_flag = MACHINE_AVAILABLE, + .gpio_acpi_handler = NULL, + .cpu = { + .package = CPU_PKG_SOCKET4, + .block = CPU_BLOCK_NONE, + .min_bus = 60000000, + .max_bus = 60000000, + .min_voltage = 5000, + .max_voltage = 5000, + .min_multi = MACHINE_MULTIPLIER_FIXED, + .max_multi = MACHINE_MULTIPLIER_FIXED + }, + .bus_flags = MACHINE_PS2_VLB, + .flags = MACHINE_IDE | MACHINE_APM | MACHINE_ACPI, + .ram = { + .min = 2048, + .max = 65536, + .step = 2048 + }, + .nvrmask = 127, + .kbc_device = NULL, + .kbc_p1 = 0xff, + .gpio = 0xffffffff, + .gpio_acpi = 0xffffffff, + .device = NULL, + .fdc_device = NULL, + .sio_device = NULL, + .vid_device = NULL, + .snd_device = NULL, + .net_device = NULL + }, /* OPTi 596/597/822 */ /* This has AMIKey 'F' KBC firmware. */ - { "[OPTi 597] Supermicro P5VL-PCI", "p5vl", MACHINE_TYPE_SOCKET4, CPU_PKG_SOCKET4, 0, 60000000, 66666667, 5000, 5000, MACHINE_MULTIPLIER_FIXED, MACHINE_PCI | MACHINE_VLB, 8192, 131072, 8192, 127, machine_at_p5vl_init, NULL }, + { + .name = "[OPTi 597] Supermicro P5VL-PCI", + .internal_name = "p5vl", + .type = MACHINE_TYPE_SOCKET4, + .chipset = MACHINE_CHIPSET_OPTI_547_597, + .init = machine_at_p5vl_init, + .p1_handler = NULL, + .gpio_handler = NULL, + .available_flag = MACHINE_AVAILABLE, + .gpio_acpi_handler = NULL, + .cpu = { + .package = CPU_PKG_SOCKET4, + .block = CPU_BLOCK_NONE, + .min_bus = 60000000, + .max_bus = 66666667, + .min_voltage = 5000, + .max_voltage = 5000, + .min_multi = MACHINE_MULTIPLIER_FIXED, + .max_multi = MACHINE_MULTIPLIER_FIXED + }, + .bus_flags = MACHINE_PCIV, + .flags = MACHINE_APM | MACHINE_ACPI, + .ram = { + .min = 8192, + .max = 131072, + .step = 8192 + }, + .nvrmask = 127, + .kbc_device = NULL, + .kbc_p1 = 0xff, + .gpio = 0xffffffff, + .gpio_acpi = 0xffffffff, + .device = NULL, + .fdc_device = NULL, + .sio_device = NULL, + .vid_device = NULL, + .snd_device = NULL, + .net_device = NULL + }, /* SiS 50x */ /* This has some form of AMI MegaKey as it uses keyboard controller command 0xCC. */ - { "[SiS 501] AMI Excalibur PCI-II Pentium ISA","excaliburpci2", MACHINE_TYPE_SOCKET4, CPU_PKG_SOCKET4, 0, 60000000, 66666667, 5000, 5000, MACHINE_MULTIPLIER_FIXED, MACHINE_PCI | MACHINE_BUS_PS2 | MACHINE_IDE_DUAL, 8192, 131072, 8192, 127, machine_at_excaliburpci2_init, NULL }, + { + .name = "[SiS 501] AMI Excalibur PCI-II Pentium ISA", + .internal_name = "excaliburpci2", + .type = MACHINE_TYPE_SOCKET4, + .chipset = MACHINE_CHIPSET_SIS_501, + .init = machine_at_excaliburpci2_init, + .p1_handler = NULL, + .gpio_handler = NULL, + .available_flag = MACHINE_AVAILABLE, + .gpio_acpi_handler = NULL, + .cpu = { + .package = CPU_PKG_SOCKET4, + .block = CPU_BLOCK_NONE, + .min_bus = 60000000, + .max_bus = 66666667, + .min_voltage = 5000, + .max_voltage = 5000, + .min_multi = MACHINE_MULTIPLIER_FIXED, + .max_multi = MACHINE_MULTIPLIER_FIXED + }, + .bus_flags = MACHINE_PS2_PCI, + .flags = MACHINE_IDE_DUAL | MACHINE_APM | MACHINE_ACPI, + .ram = { + .min = 8192, + .max = 131072, + .step = 8192 + }, + .nvrmask = 127, + .kbc_device = NULL, + .kbc_p1 = 0xff, + .gpio = 0xffffffff, + .gpio_acpi = 0xffffffff, + .device = NULL, + .fdc_device = NULL, + .sio_device = NULL, + .vid_device = NULL, + .snd_device = NULL, + .net_device = NULL + }, /* This has an AMIKey-2, which is an updated version of type 'H'. */ - { "[SiS 501] ASUS PCI/I-P5SP4", "p5sp4", MACHINE_TYPE_SOCKET4, CPU_PKG_SOCKET4, 0, 60000000, 66666667, 5000, 5000, MACHINE_MULTIPLIER_FIXED, MACHINE_PCI | MACHINE_BUS_PS2 | MACHINE_IDE_DUAL, 8192, 131072, 8192, 127, machine_at_p5sp4_init, NULL }, + { + .name = "[SiS 501] ASUS PCI/I-P5SP4", + .internal_name = "p5sp4", + .type = MACHINE_TYPE_SOCKET4, + .chipset = MACHINE_CHIPSET_SIS_501, + .init = machine_at_p5sp4_init, + .p1_handler = NULL, + .gpio_handler = NULL, + .available_flag = MACHINE_AVAILABLE, + .gpio_acpi_handler = NULL, + .cpu = { + .package = CPU_PKG_SOCKET4, + .block = CPU_BLOCK_NONE, + .min_bus = 60000000, + .max_bus = 66666667, + .min_voltage = 5000, + .max_voltage = 5000, + .min_multi = MACHINE_MULTIPLIER_FIXED, + .max_multi = MACHINE_MULTIPLIER_FIXED + }, + .bus_flags = MACHINE_PS2_PCI, + .flags = MACHINE_IDE_DUAL | MACHINE_APM | MACHINE_ACPI, + .ram = { + .min = 8192, + .max = 131072, + .step = 8192 + }, + .nvrmask = 127, + .kbc_device = NULL, + .kbc_p1 = 0xff, + .gpio = 0xffffffff, + .gpio_acpi = 0xffffffff, + .device = NULL, + .fdc_device = NULL, + .sio_device = NULL, + .vid_device = NULL, + .snd_device = NULL, + .net_device = NULL + }, /* Socket 5 machines */ /* 430NX */ /* This has the Phoenix MultiKey KBC firmware. */ - { "[i430NX] Intel Premiere/PCI II", "plato", MACHINE_TYPE_SOCKET5, CPU_PKG_SOCKET5_7, 0, 50000000, 66666667, 3520, 3520, 1.5, 1.5, MACHINE_PCI | MACHINE_BUS_PS2 | MACHINE_IDE_DUAL, 2048, 131072, 2048, 127, machine_at_plato_init, NULL }, + { + .name = "[i430NX] Intel Premiere/PCI II", + .internal_name = "plato", + .type = MACHINE_TYPE_SOCKET5, + .chipset = MACHINE_CHIPSET_INTEL_430NX, + .init = machine_at_plato_init, + .p1_handler = NULL, + .gpio_handler = NULL, + .available_flag = MACHINE_AVAILABLE, + .gpio_acpi_handler = NULL, + .cpu = { + .package = CPU_PKG_SOCKET5_7, + .block = CPU_BLOCK_NONE, + .min_bus = 50000000, + .max_bus = 66666667, + .min_voltage = 3520, + .max_voltage = 3520, + .min_multi = 1.5, + .max_multi = 1.5 + }, + .bus_flags = MACHINE_PS2_PCI, + .flags = MACHINE_IDE_DUAL | MACHINE_APM | MACHINE_ACPI, + .ram = { + .min = 2048, + .max = 131072, + .step = 2048 + }, + .nvrmask = 127, + .kbc_device = NULL, + .kbc_p1 = 0xff, + .gpio = 0xffffffff, + .gpio_acpi = 0xffffffff, + .device = NULL, + .fdc_device = NULL, + .sio_device = NULL, + .vid_device = NULL, + .snd_device = NULL, + .net_device = NULL + }, /* This has the Phoenix MultiKey KBC firmware. This is basically an Intel Premiere/PCI II with a fancier POST screen. */ - { "[i430NX] AMBRA DP90 PCI", "ambradp90", MACHINE_TYPE_SOCKET5, CPU_PKG_SOCKET5_7, 0, 50000000, 66666667, 3380, 3520, 1.5, 1.5, MACHINE_PCI | MACHINE_BUS_PS2 | MACHINE_IDE_DUAL, 2048, 131072, 2048, 127, machine_at_ambradp90_init, NULL }, + { + .name = "[i430NX] AMBRA DP90 PCI", + .internal_name = "ambradp90", + .type = MACHINE_TYPE_SOCKET5, + .chipset = MACHINE_CHIPSET_INTEL_430NX, + .init = machine_at_ambradp90_init, + .p1_handler = NULL, + .gpio_handler = NULL, + .available_flag = MACHINE_AVAILABLE, + .gpio_acpi_handler = NULL, + .cpu = { + .package = CPU_PKG_SOCKET5_7, + .block = CPU_BLOCK_NONE, + .min_bus = 50000000, + .max_bus = 66666667, + .min_voltage = 3380, + .max_voltage = 3520, + .min_multi = 1.5, + .max_multi = 1.5 + }, + .bus_flags = MACHINE_PS2_PCI, + .flags = MACHINE_IDE_DUAL | MACHINE_APM | MACHINE_ACPI, + .ram = { + .min = 2048, + .max = 131072, + .step = 2048 + }, + .nvrmask = 127, + .kbc_device = NULL, + .kbc_p1 = 0xff, + .gpio = 0xffffffff, + .gpio_acpi = 0xffffffff, + .device = NULL, + .fdc_device = NULL, + .sio_device = NULL, + .vid_device = NULL, + .snd_device = NULL, + .net_device = NULL + }, /* Has AMI MegaKey KBC firmware. */ - { "[i430NX] Gigabyte GA-586IP", "430nx", MACHINE_TYPE_SOCKET5, CPU_PKG_SOCKET5_7, 0, 60000000, 66666667, 3520, 3520, 1.5, 1.5, MACHINE_PCI | MACHINE_BUS_PS2 | MACHINE_IDE_DUAL, 2048, 131072, 2048, 127, machine_at_430nx_init, NULL }, + { + .name = "[i430NX] Gigabyte GA-586IP", + .internal_name = "430nx", + .type = MACHINE_TYPE_SOCKET5, + .chipset = MACHINE_CHIPSET_INTEL_430NX, + .init = machine_at_430nx_init, + .p1_handler = NULL, + .gpio_handler = NULL, + .available_flag = MACHINE_AVAILABLE, + .gpio_acpi_handler = NULL, + .cpu = { + .package = CPU_PKG_SOCKET5_7, + .block = CPU_BLOCK_NONE, + .min_bus = 60000000, + .max_bus = 66666667, + .min_voltage = 3520, + .max_voltage = 3520, + .min_multi = 1.5, + .max_multi = 1.5 + }, + .bus_flags = MACHINE_PCI, + .flags = MACHINE_IDE_DUAL | MACHINE_APM | MACHINE_ACPI, + .ram = { + .min = 2048, + .max = 262144, + .step = 2048 + }, + .nvrmask = 127, + .kbc_device = NULL, + .kbc_p1 = 0xff, + .gpio = 0xffffffff, + .gpio_acpi = 0xffffffff, + .device = NULL, + .fdc_device = NULL, + .sio_device = NULL, + .vid_device = NULL, + .snd_device = NULL, + .net_device = NULL + }, /* 430FX */ /* Uses an ACER/NEC 90M002A (UPD82C42C, 8042 clone) with unknown firmware (V5.0). */ - { "[i430FX] Acer V30", "acerv30", MACHINE_TYPE_SOCKET5, CPU_PKG_SOCKET5_7, 0, 50000000, 66666667, 3380, 3520, 1.5, 2.0, MACHINE_PCI | MACHINE_BUS_PS2 | MACHINE_IDE_DUAL, 8192, 131072, 8192, 127, machine_at_acerv30_init, NULL }, + { + .name = "[i430FX] Acer V30", + .internal_name = "acerv30", + .type = MACHINE_TYPE_SOCKET5, + .chipset = MACHINE_CHIPSET_INTEL_430FX, + .init = machine_at_acerv30_init, + .p1_handler = NULL, + .gpio_handler = NULL, + .available_flag = MACHINE_AVAILABLE, + .gpio_acpi_handler = NULL, + .cpu = { + .package = CPU_PKG_SOCKET5_7, + .block = CPU_BLOCK_NONE, + .min_bus = 50000000, + .max_bus = 66666667, + .min_voltage = 3380, + .max_voltage = 3520, + .min_multi = 1.5, + .max_multi = 2.0 + }, + .bus_flags = MACHINE_PS2_PCI, + .flags = MACHINE_IDE_DUAL | MACHINE_APM | MACHINE_ACPI, + .ram = { + .min = 8192, + .max = 131072, + .step = 8192 + }, + .nvrmask = 127, + .kbc_device = NULL, + .kbc_p1 = 0xff, + .gpio = 0xffffffff, + .gpio_acpi = 0xffffffff, + .device = NULL, + .fdc_device = NULL, + .sio_device = NULL, + .vid_device = NULL, + .snd_device = NULL, + .net_device = NULL + }, /* Has AMIKey F KBC firmware. */ - { "[i430FX] AMI Apollo", "apollo", MACHINE_TYPE_SOCKET5, CPU_PKG_SOCKET5_7, 0, 50000000, 66666667, 3380, 3520, 1.5, 2.0, MACHINE_PCI | MACHINE_BUS_PS2 | MACHINE_IDE_DUAL, 8192, 131072, 8192, 127, machine_at_apollo_init, NULL }, - /* Has AMIKey H KBC firmware. */ - { "[i430FX] DataExpert EXP8551", "exp8551", MACHINE_TYPE_SOCKET5, CPU_PKG_SOCKET5_7, 0, 50000000, 66666667, 3380, 3520, 1.5, 3.0, MACHINE_PCI | MACHINE_BUS_PS2 | MACHINE_IDE_DUAL, 8192, 131072, 8192, 127, machine_at_exp8551_init, NULL }, + { + .name = "[i430FX] AMI Apollo", + .internal_name = "apollo", + .type = MACHINE_TYPE_SOCKET5, + .chipset = MACHINE_CHIPSET_INTEL_430FX, + .init = machine_at_apollo_init, + .p1_handler = NULL, + .gpio_handler = NULL, + .available_flag = MACHINE_AVAILABLE, + .gpio_acpi_handler = NULL, + .cpu = { + .package = CPU_PKG_SOCKET5_7, + .block = CPU_BLOCK_NONE, + .min_bus = 50000000, + .max_bus = 66666667, + .min_voltage = 3380, + .max_voltage = 3520, + .min_multi = 1.5, + .max_multi = 2.0 + }, + .bus_flags = MACHINE_PS2_PCI, + .flags = MACHINE_IDE_DUAL | MACHINE_APM | MACHINE_ACPI, + .ram = { + .min = 8192, + .max = 131072, + .step = 8192 + }, + .nvrmask = 127, + .kbc_device = NULL, + .kbc_p1 = 0xff, + .gpio = 0xffffffff, + .gpio_acpi = 0xffffffff, + .device = NULL, + .fdc_device = NULL, + .sio_device = NULL, + .vid_device = NULL, + .snd_device = NULL, + .net_device = NULL + }, /* According to tests from real hardware: This has AMI MegaKey KBC firmware on the PC87306 Super I/O chip, command 0xA1 returns '5'. Command 0xA0 copyright string: (C)1994 AMI . */ - { "[i430FX] Intel Advanced/ZP", "zappa", MACHINE_TYPE_SOCKET5, CPU_PKG_SOCKET5_7, 0, 50000000, 66666667, 3380, 3520, 1.5, 2.0, MACHINE_PCI | MACHINE_BUS_PS2 | MACHINE_IDE_DUAL, 8192, 131072, 8192, 127, machine_at_zappa_init, NULL }, + { + .name = "[i430FX] Intel Advanced/ZP", + .internal_name = "zappa", + .type = MACHINE_TYPE_SOCKET5, + .chipset = MACHINE_CHIPSET_INTEL_430FX, + .init = machine_at_zappa_init, + .p1_handler = NULL, + .gpio_handler = NULL, + .available_flag = MACHINE_AVAILABLE, + .gpio_acpi_handler = NULL, + .cpu = { + .package = CPU_PKG_SOCKET5_7, + .block = CPU_BLOCK_NONE, + .min_bus = 50000000, + .max_bus = 66666667, + .min_voltage = 3380, + .max_voltage = 3520, + .min_multi = 1.5, + .max_multi = 2.0 + }, + .bus_flags = MACHINE_PS2_PCI, + .flags = MACHINE_IDE_DUAL | MACHINE_APM | MACHINE_ACPI, + .ram = { + .min = 8192, + .max = 131072, + .step = 8192 + }, + .nvrmask = 255, + .kbc_device = NULL, + .kbc_p1 = 0xff, + .gpio = 0xffffffff, + .gpio_acpi = 0xffffffff, + .device = NULL, + .fdc_device = NULL, + .sio_device = NULL, + .vid_device = NULL, + .snd_device = NULL, + .net_device = NULL + }, /* The BIOS sends KBC command B3 which indicates an AMI (or VIA VT82C42N) KBC. */ - { "[i430FX] NEC PowerMate V", "powermatev", MACHINE_TYPE_SOCKET5, CPU_PKG_SOCKET5_7, 0, 50000000, 66666667, 3380, 3520, 1.5, 2.0, MACHINE_PCI | MACHINE_BUS_PS2 | MACHINE_IDE_DUAL, 8192, 131072, 8192, 127, machine_at_powermatev_init, NULL }, - /* Has a VIA VT82C42N KBC. */ - { "[i430FX] PC Partner MB500N", "mb500n", MACHINE_TYPE_SOCKET5, CPU_PKG_SOCKET5_7, 0, 50000000, 66666667, 3380, 3520, 1.5, 3.0, MACHINE_PCI | MACHINE_IDE_DUAL, 8192, 131072, 8192, 127, machine_at_mb500n_init, NULL }, + { + .name = "[i430FX] NEC PowerMate V", + .internal_name = "powermatev", + .type = MACHINE_TYPE_SOCKET5, + .chipset = MACHINE_CHIPSET_INTEL_430FX, + .init = machine_at_powermatev_init, + .p1_handler = NULL, + .gpio_handler = NULL, + .available_flag = MACHINE_AVAILABLE, + .gpio_acpi_handler = NULL, + .cpu = { + .package = CPU_PKG_SOCKET5_7, + .block = CPU_BLOCK_NONE, + .min_bus = 50000000, + .max_bus = 66666667, + .min_voltage = 3380, + .max_voltage = 3520, + .min_multi = 1.5, + .max_multi = 2.0 + }, + .bus_flags = MACHINE_PS2_PCI, + .flags = MACHINE_IDE_DUAL | MACHINE_APM | MACHINE_ACPI, + .ram = { + .min = 8192, + .max = 131072, + .step = 8192 + }, + .nvrmask = 127, + .kbc_device = NULL, + .kbc_p1 = 0xff, + .gpio = 0xffffffff, + .gpio_acpi = 0xffffffff, + .device = NULL, + .fdc_device = NULL, + .sio_device = NULL, + .vid_device = NULL, + .snd_device = NULL, + .net_device = NULL + }, /* Has AMIKey Z(!) KBC firmware. */ - { "[i430FX] TriGem Hawk", "hawk", MACHINE_TYPE_SOCKET5, CPU_PKG_SOCKET5_7, 0, 50000000, 66666667, 3380, 3520, 1.5, 2.0, MACHINE_PCI | MACHINE_BUS_PS2 | MACHINE_IDE_DUAL, 8192, 131072, 8192, 127, machine_at_hawk_init, NULL }, + { + .name = "[i430FX] TriGem Hawk", + .internal_name = "hawk", + .type = MACHINE_TYPE_SOCKET5, + .chipset = MACHINE_CHIPSET_INTEL_430FX, + .init = machine_at_hawk_init, + .p1_handler = NULL, + .gpio_handler = NULL, + .available_flag = MACHINE_AVAILABLE, + .gpio_acpi_handler = NULL, + .cpu = { + .package = CPU_PKG_SOCKET5_7, + .block = CPU_BLOCK_NONE, + .min_bus = 50000000, + .max_bus = 66666667, + .min_voltage = 3380, + .max_voltage = 3520, + .min_multi = 1.5, + .max_multi = 2.0 + }, + .bus_flags = MACHINE_PS2_PCI, + .flags = MACHINE_IDE_DUAL | MACHINE_APM | MACHINE_ACPI, + .ram = { + .min = 8192, + .max = 131072, + .step = 8192 + }, + .nvrmask = 127, + .kbc_device = NULL, + .kbc_p1 = 0xff, + .gpio = 0xffffffff, + .gpio_acpi = 0xffffffff, + .device = NULL, + .fdc_device = NULL, + .sio_device = NULL, + .vid_device = NULL, + .snd_device = NULL, + .net_device = NULL + }, /* OPTi 596/597 */ /* This uses an AMI KBC firmware in PS/2 mode (it sends command A5 with the PS/2 "Load Security" meaning), most likely MegaKey as it sends command AF (Set Extended Controller RAM) just like the later Intel AMI BIOS'es. */ - { "[OPTi 597] TMC PAT54PV", "pat54pv", MACHINE_TYPE_SOCKET5, CPU_PKG_SOCKET5_7, CPU_BLOCK(CPU_K5, CPU_5K86), 50000000, 66666667, 3520, 3520, 1.5, 1.5, MACHINE_VLB, 2048, 65536, 2048, 127, machine_at_pat54pv_init, NULL }, - + { + .name = "[OPTi 597] TMC PAT54PV", + .internal_name = "pat54pv", + .type = MACHINE_TYPE_SOCKET5, + .chipset = MACHINE_CHIPSET_OPTI_547_597, + .init = machine_at_pat54pv_init, + .p1_handler = NULL, + .gpio_handler = NULL, + .available_flag = MACHINE_AVAILABLE, + .gpio_acpi_handler = NULL, + .cpu = { + .package = CPU_PKG_SOCKET5_7, + .block = CPU_BLOCK(CPU_K5, CPU_5K86), + .min_bus = 50000000, + .max_bus = 66666667, + .min_voltage = 3520, + .max_voltage = 3520, + .min_multi = 1.5, + .max_multi = 1.5 + }, + .bus_flags = MACHINE_VLB, + .flags = MACHINE_APM | MACHINE_ACPI, + .ram = { + .min = 2048, + .max = 65536, + .step = 2048 + }, + .nvrmask = 127, + .kbc_device = NULL, + .kbc_p1 = 0xff, + .gpio = 0xffffffff, + .gpio_acpi = 0xffffffff, + .device = NULL, + .fdc_device = NULL, + .sio_device = NULL, + .vid_device = NULL, + .snd_device = NULL, + .net_device = NULL + }, + /* OPTi 596/597/822 */ - { "[OPTi 597] Shuttle HOT-543", "hot543", MACHINE_TYPE_SOCKET5, CPU_PKG_SOCKET5_7, 0, 50000000, 66666667, 3520, 3520, 1.5, 2.0, MACHINE_PCI | MACHINE_VLB, 8192, 131072, 8192, 127, machine_at_hot543_init, NULL }, + { + .name = "[OPTi 597] Shuttle HOT-543", + .internal_name = "hot543", + .type = MACHINE_TYPE_SOCKET5, + .chipset = MACHINE_CHIPSET_OPTI_547_597, + .init = machine_at_hot543_init, + .p1_handler = NULL, + .gpio_handler = NULL, + .available_flag = MACHINE_AVAILABLE, + .gpio_acpi_handler = NULL, + .cpu = { + .package = CPU_PKG_SOCKET5_7, + .block = CPU_BLOCK_NONE, + .min_bus = 50000000, + .max_bus = 66666667, + .min_voltage = 3520, + .max_voltage = 3520, + .min_multi = 1.5, + .max_multi = 2.0 + }, + .bus_flags = MACHINE_PCIV, + .flags = MACHINE_APM | MACHINE_ACPI, + .ram = { + .min = 8192, + .max = 131072, + .step = 8192 + }, + .nvrmask = 127, + .kbc_device = NULL, + .kbc_p1 = 0xff, + .gpio = 0xffffffff, + .gpio_acpi = 0xffffffff, + .device = NULL, + .fdc_device = NULL, + .sio_device = NULL, + .vid_device = NULL, + .snd_device = NULL, + .net_device = NULL + }, /* SiS 85C50x */ /* This has an AMIKey-2, which is an updated version of type 'H'. */ - { "[SiS 501] ASUS PCI/I-P54SP4", "p54sp4", MACHINE_TYPE_SOCKET5, CPU_PKG_SOCKET5_7, CPU_BLOCK(CPU_K5, CPU_5K86), 40000000, 66666667, 3380, 3520, 1.5, 1.5, MACHINE_PCI | MACHINE_BUS_PS2 | MACHINE_IDE_DUAL, 8192, 131072, 8192, 127, machine_at_p54sp4_init, NULL }, + { + .name = "[SiS 501] ASUS PCI/I-P54SP4", + .internal_name = "p54sp4", + .type = MACHINE_TYPE_SOCKET5, + .chipset = MACHINE_CHIPSET_SIS_501, + .init = machine_at_p54sp4_init, + .p1_handler = NULL, + .gpio_handler = NULL, + .available_flag = MACHINE_AVAILABLE, + .gpio_acpi_handler = NULL, + .cpu = { + .package = CPU_PKG_SOCKET5_7, + .block = CPU_BLOCK(CPU_K5, CPU_5K86), + .min_bus = 40000000, + .max_bus = 66666667, + .min_voltage = 3380, + .max_voltage = 3520, + .min_multi = 1.5, + .max_multi = 1.5 + }, + .bus_flags = MACHINE_PS2_PCI, + .flags = MACHINE_IDE_DUAL | MACHINE_APM | MACHINE_ACPI, + .ram = { + .min = 8192, + .max = 131072, + .step = 8192 + }, + .nvrmask = 127, + .kbc_device = NULL, + .kbc_p1 = 0xff, + .gpio = 0xffffffff, + .gpio_acpi = 0xffffffff, + .device = NULL, + .fdc_device = NULL, + .sio_device = NULL, + .vid_device = NULL, + .snd_device = NULL, + .net_device = NULL + }, /* This has an AMIKey-2, which is an updated version of type 'H'. */ - { "[SiS 501] BCM SQ-588", "sq588", MACHINE_TYPE_SOCKET5, CPU_PKG_SOCKET5_7, CPU_BLOCK(CPU_PENTIUMMMX), 50000000, 66666667, 3520, 3520, 1.5, 1.5, MACHINE_PCI | MACHINE_BUS_PS2 | MACHINE_IDE_DUAL, 8192, 131072, 8192, 127, machine_at_sq588_init, NULL }, + { + .name = "[SiS 501] BCM SQ-588", + .internal_name = "sq588", + .type = MACHINE_TYPE_SOCKET5, + .chipset = MACHINE_CHIPSET_SIS_501, + .init = machine_at_sq588_init, + .p1_handler = NULL, + .gpio_handler = NULL, + .available_flag = MACHINE_AVAILABLE, + .gpio_acpi_handler = NULL, + .cpu = { + .package = CPU_PKG_SOCKET5_7, + .block = CPU_BLOCK(CPU_PENTIUMMMX), + .min_bus = 50000000, + .max_bus = 66666667, + .min_voltage = 3520, + .max_voltage = 3520, + .min_multi = 1.5, + .max_multi = 1.5 + }, + .bus_flags = MACHINE_PS2_PCI, + .flags = MACHINE_IDE_DUAL | MACHINE_APM | MACHINE_ACPI, + .ram = { + .min = 8192, + .max = 131072, + .step = 8192 + }, + .nvrmask = 127, + .kbc_device = NULL, + .kbc_p1 = 0xff, + .gpio = 0xffffffff, + .gpio_acpi = 0xffffffff, + .device = NULL, + .fdc_device = NULL, + .sio_device = NULL, + .vid_device = NULL, + .snd_device = NULL, + .net_device = NULL + }, + /* This machine has a Winbond W83C842 KBC */ + { + .name = "[SiS 501] Gemlight GMB-P54SPS", + .internal_name = "p54sps", + .type = MACHINE_TYPE_SOCKET5, + .chipset = MACHINE_CHIPSET_SIS_501, + .init = machine_at_p54sps_init, + .p1_handler = NULL, + .gpio_handler = NULL, + .available_flag = MACHINE_AVAILABLE, + .gpio_acpi_handler = NULL, + .cpu = { + .package = CPU_PKG_SOCKET5_7, + CPU_BLOCK(CPU_PENTIUMMMX), + .min_bus = 50000000, + .max_bus = 66666667, + .min_voltage = 3520, + .max_voltage = 3520, + .min_multi = 1.5, + .max_multi = 1.5 + }, + .bus_flags = MACHINE_PCI, + .flags = MACHINE_IDE_DUAL | MACHINE_APM | MACHINE_ACPI, + .ram = { + .min = 8192, + .max = 131072, + .step = 8192 + }, + .nvrmask = 127, + .kbc_device = &keyboard_at_ami_device, + .kbc_p1 = 0xff, + .gpio = 0xffffffff, + .gpio_acpi = 0xffffffff, + .device = NULL, + .fdc_device = NULL, + .sio_device = NULL, + .vid_device = NULL, + .snd_device = NULL, + .net_device = NULL + }, /* Socket 7 (Single Voltage) machines */ /* 430FX */ /* This has an AMIKey-2, which is an updated version of type 'H'. */ - { "[i430FX] ASUS P/I-P54TP4XE", "p54tp4xe", MACHINE_TYPE_SOCKET7_3V, CPU_PKG_SOCKET5_7, 0, 50000000, 66666667, 3380, 3600, 1.5, 3.0, MACHINE_PCI | MACHINE_BUS_PS2 | MACHINE_IDE_DUAL, 8192, 131072, 8192, 127, machine_at_p54tp4xe_init, NULL }, + { + .name = "[i430FX] ASUS P/I-P54TP4XE", + .internal_name = "p54tp4xe", + .type = MACHINE_TYPE_SOCKET7_3V, + .chipset = MACHINE_CHIPSET_INTEL_430FX, + .init = machine_at_p54tp4xe_init, + .p1_handler = NULL, + .gpio_handler = NULL, + .available_flag = MACHINE_AVAILABLE, + .gpio_acpi_handler = NULL, + .cpu = { + .package = CPU_PKG_SOCKET5_7, + .block = CPU_BLOCK_NONE, + .min_bus = 50000000, + .max_bus = 66666667, + .min_voltage = 3380, + .max_voltage = 3600, + .min_multi = 1.5, + .max_multi = 3.0 + }, + .bus_flags = MACHINE_PS2_PCI, + .flags = MACHINE_IDE_DUAL | MACHINE_APM | MACHINE_ACPI, + .ram = { + .min = 8192, + .max = 131072, + .step = 8192 + }, + .nvrmask = 127, + .kbc_device = NULL, + .kbc_p1 = 0xff, + .gpio = 0xffffffff, + .gpio_acpi = 0xffffffff, + .device = NULL, + .fdc_device = NULL, + .sio_device = NULL, + .vid_device = NULL, + .snd_device = NULL, + .net_device = NULL + }, /* This has an AMIKey-2, which is an updated version of type 'H'. */ - { "[i430FX] ASUS P/I-P54TP4XE (MR BIOS)", "p54tp4xe_mr", MACHINE_TYPE_SOCKET7_3V, CPU_PKG_SOCKET5_7, 0, 50000000, 66666667, 3380, 3600, 1.5, 3.0, MACHINE_PCI | MACHINE_BUS_PS2 | MACHINE_IDE_DUAL, 8192, 131072, 8192, 127, machine_at_p54tp4xe_mr_init, NULL }, + { + .name = "[i430FX] ASUS P/I-P54TP4XE (MR BIOS)", + .internal_name = "p54tp4xe_mr", + .type = MACHINE_TYPE_SOCKET7_3V, + .chipset = MACHINE_CHIPSET_INTEL_430FX, + .init = machine_at_p54tp4xe_mr_init, + .p1_handler = NULL, + .gpio_handler = NULL, + .available_flag = MACHINE_AVAILABLE, + .gpio_acpi_handler = NULL, + .cpu = { + .package = CPU_PKG_SOCKET5_7, + .block = CPU_BLOCK_NONE, + .min_bus = 50000000, + .max_bus = 66666667, + .min_voltage = 3380, + .max_voltage = 3600, + .min_multi = 1.5, + .max_multi = 3.0 + }, + .bus_flags = MACHINE_PS2_PCI, + .flags = MACHINE_IDE_DUAL | MACHINE_APM | MACHINE_ACPI, + .ram = { + .min = 8192, + .max = 131072, + .step = 8192 + }, + .nvrmask = 127, + .kbc_device = NULL, + .kbc_p1 = 0xff, + .gpio = 0xffffffff, + .gpio_acpi = 0xffffffff, + .device = NULL, + .fdc_device = NULL, + .sio_device = NULL, + .vid_device = NULL, + .snd_device = NULL, + .net_device = NULL + }, + /* Has AMIKey H KBC firmware. */ + { + .name = "[i430FX] DataExpert EXP8551", + .internal_name = "exp8551", + .type = MACHINE_TYPE_SOCKET7_3V, + .chipset = MACHINE_CHIPSET_INTEL_430FX, + .init = machine_at_exp8551_init, + .p1_handler = NULL, + .gpio_handler = NULL, + .available_flag = MACHINE_AVAILABLE, + .gpio_acpi_handler = NULL, + .cpu = { + .package = CPU_PKG_SOCKET5_7, + .block = CPU_BLOCK_NONE, + .min_bus = 50000000, + .max_bus = 66666667, + .min_voltage = 3380, + .max_voltage = 3520, + .min_multi = 1.5, + .max_multi = 3.0 + }, + .bus_flags = MACHINE_PS2_PCI, + .flags = MACHINE_IDE_DUAL | MACHINE_GAMEPORT | MACHINE_APM | MACHINE_ACPI, + .ram = { + .min = 8192, + .max = 131072, + .step = 8192 + }, + .nvrmask = 127, + .kbc_device = NULL, + .kbc_p1 = 0xff, + .gpio = 0xffffffff, + .gpio_acpi = 0xffffffff, + .device = NULL, + .fdc_device = NULL, + .sio_device = NULL, + .vid_device = NULL, + .snd_device = NULL, + .net_device = NULL + }, /* According to tests from real hardware: This has AMI MegaKey KBC firmware on the PC87306 Super I/O chip, command 0xA1 returns '5'. Command 0xA0 copyright string: (C)1994 AMI . */ - { "[i430FX] Gateway 2000 Thor", "gw2katx", MACHINE_TYPE_SOCKET7_3V, CPU_PKG_SOCKET5_7, 0, 50000000, 66666667, 3380, 3520, 1.5, 3.0, MACHINE_PCI | MACHINE_BUS_PS2 | MACHINE_IDE_DUAL, 8192, 131072, 8192, 127, machine_at_gw2katx_init, NULL }, + { + .name = "[i430FX] Gateway 2000 Thor", + .internal_name = "gw2katx", + .type = MACHINE_TYPE_SOCKET7_3V, + .chipset = MACHINE_CHIPSET_INTEL_430FX, + .init = machine_at_gw2katx_init, + .p1_handler = NULL, + .gpio_handler = NULL, + .available_flag = MACHINE_AVAILABLE, + .gpio_acpi_handler = NULL, + .cpu = { + .package = CPU_PKG_SOCKET5_7, + .block = CPU_BLOCK_NONE, + .min_bus = 50000000, + .max_bus = 66666667, + .min_voltage = 3380, + .max_voltage = 3520, + .min_multi = 1.5, + .max_multi = 3.0 + }, + .bus_flags = MACHINE_PS2_PCI, + .flags = MACHINE_IDE_DUAL | MACHINE_APM | MACHINE_ACPI, + .ram = { + .min = 8192, + .max = 131072, + .step = 8192 + }, + .nvrmask = 255, + .kbc_device = NULL, + .kbc_p1 = 0xff, + .gpio = 0xffffffff, + .gpio_acpi = 0xffffffff, + .device = NULL, + .fdc_device = NULL, + .sio_device = NULL, + .vid_device = NULL, + .snd_device = NULL, + .net_device = NULL + }, /* The BIOS does not send a single non-standard KBC command, but the board has a SMC Super I/O chip with on-chip KBC and AMI MegaKey KBC firmware. */ - { "[i430FX] HP Vectra VL 5 Series 4", "vectra54", MACHINE_TYPE_SOCKET7_3V, CPU_PKG_SOCKET5_7, 0, 50000000, 66666667, 3380, 3520, 1.5, 2.0, MACHINE_PCI | MACHINE_BUS_PS2 | MACHINE_IDE_DUAL | MACHINE_VIDEO, 8192, 131072, 8192, 511, machine_at_vectra54_init, at_vectra54_get_device }, + { + .name = "[i430FX] HP Vectra VL 5 Series 4", + .internal_name = "vectra54", + .type = MACHINE_TYPE_SOCKET7_3V, + .chipset = MACHINE_CHIPSET_INTEL_430FX, + .init = machine_at_vectra54_init, + .p1_handler = NULL, + .gpio_handler = NULL, + .available_flag = MACHINE_AVAILABLE, + .gpio_acpi_handler = NULL, + .cpu = { + .package = CPU_PKG_SOCKET5_7, + .block = CPU_BLOCK_NONE, + .min_bus = 50000000, + .max_bus = 66666667, + .min_voltage = 3380, + .max_voltage = 3520, + .min_multi = 1.5, + .max_multi = 2.0 + }, + .bus_flags = MACHINE_PS2_PCI, + .flags = MACHINE_IDE_DUAL | MACHINE_VIDEO | MACHINE_APM | MACHINE_ACPI, + .ram = { + .min = 8192, + .max = 131072, + .step = 8192 + }, + .nvrmask = 511, + .kbc_device = NULL, + .kbc_p1 = 0xff, + .gpio = 0xffffffff, + .gpio_acpi = 0xffffffff, + .device = NULL, + .fdc_device = NULL, + .sio_device = NULL, + .vid_device = &s3_phoenix_trio64_onboard_pci_device, + .snd_device = NULL, + .net_device = NULL + }, /* According to tests from real hardware: This has AMI MegaKey KBC firmware on the PC87306 Super I/O chip, command 0xA1 returns '5'. Command 0xA0 copyright string: (C)1994 AMI . */ - { "[i430FX] Intel Advanced/ATX", "thor", MACHINE_TYPE_SOCKET7_3V, CPU_PKG_SOCKET5_7, 0, 50000000, 66666667, 3380, 3520, 1.5, 3.0, MACHINE_PCI | MACHINE_BUS_PS2 | MACHINE_IDE_DUAL | MACHINE_VIDEO, 8192, 131072, 8192, 127, machine_at_thor_init, at_thor_get_device }, + { + .name = "[i430FX] Intel Advanced/ATX", + .internal_name = "thor", + .type = MACHINE_TYPE_SOCKET7_3V, + .chipset = MACHINE_CHIPSET_INTEL_430FX, + .init = machine_at_thor_init, + .p1_handler = NULL, + .gpio_handler = NULL, + .available_flag = MACHINE_AVAILABLE, + .gpio_acpi_handler = NULL, + .cpu = { + .package = CPU_PKG_SOCKET5_7, + .block = CPU_BLOCK_NONE, + .min_bus = 50000000, + .max_bus = 66666667, + .min_voltage = 3380, + .max_voltage = 3520, + .min_multi = 1.5, + .max_multi = 3.0 + }, + .bus_flags = MACHINE_PS2_PCI, + .flags = MACHINE_IDE_DUAL | MACHINE_VIDEO | MACHINE_APM | MACHINE_ACPI, + .ram = { + .min = 8192, + .max = 131072, + .step = 8192 + }, + .nvrmask = 255, + .kbc_device = NULL, + .kbc_p1 = 0xff, + .gpio = 0xffffffff, + .gpio_acpi = 0xffffffff, + .device = NULL, + .fdc_device = NULL, + .sio_device = NULL, + .vid_device = &s3_phoenix_trio64vplus_onboard_pci_device, + .snd_device = NULL, + .net_device = NULL + }, /* According to tests from real hardware: This has AMI MegaKey KBC firmware on the PC87306 Super I/O chip, command 0xA1 returns '5'. Command 0xA0 copyright string: (C)1994 AMI . */ - { "[i430FX] Intel Advanced/ATX (MR BIOS)", "mrthor", MACHINE_TYPE_SOCKET7_3V, CPU_PKG_SOCKET5_7, 0, 50000000, 66666667, 3380, 3520, 1.5, 3.0, MACHINE_PCI | MACHINE_BUS_PS2 | MACHINE_IDE_DUAL, 8192, 131072, 8192, 127, machine_at_mrthor_init, at_mrthor_get_device }, + { + .name = "[i430FX] Intel Advanced/ATX (MR BIOS)", + .internal_name = "mrthor", + .type = MACHINE_TYPE_SOCKET7_3V, + .chipset = MACHINE_CHIPSET_INTEL_430FX, + .init = machine_at_mrthor_init, + .p1_handler = NULL, + .gpio_handler = NULL, + .available_flag = MACHINE_AVAILABLE, + .gpio_acpi_handler = NULL, + .cpu = { + .package = CPU_PKG_SOCKET5_7, + .block = CPU_BLOCK_NONE, + .min_bus = 50000000, + .max_bus = 66666667, + .min_voltage = 3380, + .max_voltage = 3520, + .min_multi = 1.5, + .max_multi = 3.0 + }, + .bus_flags = MACHINE_PS2_PCI, + .flags = MACHINE_IDE_DUAL | MACHINE_APM | MACHINE_ACPI, + .ram = { + .min = 8192, + .max = 131072, + .step = 8192 + }, + .nvrmask = 255, + .kbc_device = NULL, + .kbc_p1 = 0xff, + .gpio = 0xffffffff, + .gpio_acpi = 0xffffffff, + .device = NULL, + .fdc_device = NULL, + .sio_device = NULL, + .vid_device = NULL, + .snd_device = NULL, + .net_device = NULL + }, /* According to tests from real hardware: This has AMI MegaKey KBC firmware on the PC87306 Super I/O chip, command 0xA1 returns '5'. Command 0xA0 copyright string: (C)1994 AMI . */ - { "[i430FX] Intel Advanced/EV", "endeavor", MACHINE_TYPE_SOCKET7_3V, CPU_PKG_SOCKET5_7, 0, 50000000, 66666667, 3380, 3520, 1.5, 3.0, MACHINE_PCI | MACHINE_BUS_PS2 | MACHINE_IDE_DUAL | MACHINE_VIDEO, 8192, 131072, 8192, 127, machine_at_endeavor_init, at_endeavor_get_device }, + { + .name = "[i430FX] Intel Advanced/EV", + .internal_name = "endeavor", + .type = MACHINE_TYPE_SOCKET7_3V, + .chipset = MACHINE_CHIPSET_INTEL_430FX, + .init = machine_at_endeavor_init, + .p1_handler = NULL, + .gpio_handler = machine_at_endeavor_gpio_handler, + .available_flag = MACHINE_AVAILABLE, + .gpio_acpi_handler = NULL, + .cpu = { + .package = CPU_PKG_SOCKET5_7, + .block = CPU_BLOCK_NONE, + .min_bus = 50000000, + .max_bus = 66666667, + .min_voltage = 3380, + .max_voltage = 3520, + .min_multi = 1.5, + .max_multi = 3.0 + }, + .bus_flags = MACHINE_PS2_PCI, + .flags = MACHINE_IDE_DUAL | MACHINE_VIDEO | MACHINE_SOUND | MACHINE_APM | MACHINE_ACPI, + .ram = { + .min = 8192, + .max = 131072, + .step = 8192 + }, + .nvrmask = 255, + .kbc_device = NULL, + .kbc_p1 = 0xff, + .gpio = 0xffffffff, + .gpio_acpi = 0xffffffff, + .device = NULL, + .fdc_device = NULL, + .sio_device = NULL, + .vid_device = &s3_phoenix_trio64_onboard_pci_device, + .snd_device = &sb_vibra16s_onboard_device, + .net_device = NULL + }, /* This has an AMIKey-2, which is an updated version of type 'H'. */ - { "[i430FX] MSI MS-5119", "ms5119", MACHINE_TYPE_SOCKET7_3V, CPU_PKG_SOCKET5_7, 0, 50000000, 66666667, 2500, 3520, 1.5, 3.0, MACHINE_PCI | MACHINE_BUS_PS2 | MACHINE_IDE_DUAL, 8192, 131072, 8192, 127, machine_at_ms5119_init, NULL }, + { + .name = "[i430FX] MSI MS-5119", + .internal_name = "ms5119", + .type = MACHINE_TYPE_SOCKET7_3V, + .chipset = MACHINE_CHIPSET_INTEL_430FX, + .init = machine_at_ms5119_init, + .p1_handler = NULL, + .gpio_handler = NULL, + .available_flag = MACHINE_AVAILABLE, + .gpio_acpi_handler = NULL, + .cpu = { + .package = CPU_PKG_SOCKET5_7, + .block = CPU_BLOCK_NONE, + .min_bus = 50000000, + .max_bus = 66666667, + .min_voltage = 2500, + .max_voltage = 3520, + .min_multi = 1.5, + .max_multi = 3.0 + }, + .bus_flags = MACHINE_PS2_PCI, + .flags = MACHINE_IDE_DUAL | MACHINE_APM | MACHINE_ACPI, + .ram = { + .min = 8192, + .max = 131072, + .step = 8192 + }, + .nvrmask = 127, + .kbc_device = NULL, + .kbc_p1 = 0xff, + .gpio = 0xffffffff, + .gpio_acpi = 0xffffffff, + .device = NULL, + .fdc_device = NULL, + .sio_device = NULL, + .vid_device = NULL, + .snd_device = NULL, + .net_device = NULL + }, /* This most likely uses AMI MegaKey KBC firmware as well due to having the same Super I/O chip (that has the KBC firmware on it) as eg. the Advanced/EV. */ - { "[i430FX] Packard Bell PB640", "pb640", MACHINE_TYPE_SOCKET7_3V, CPU_PKG_SOCKET5_7, 0, 50000000, 66666667, 3380, 3520, 1.5, 3.0, MACHINE_PCI | MACHINE_BUS_PS2 | MACHINE_IDE_DUAL | MACHINE_VIDEO, 8192, 131072, 8192, 127, machine_at_pb640_init, at_pb640_get_device }, + { + .name = "[i430FX] Packard Bell PB640", + .internal_name = "pb640", + .type = MACHINE_TYPE_SOCKET7_3V, + .chipset = MACHINE_CHIPSET_INTEL_430FX, + .init = machine_at_pb640_init, + .p1_handler = NULL, + .gpio_handler = NULL, + .available_flag = MACHINE_AVAILABLE, + .gpio_acpi_handler = NULL, + .cpu = { + .package = CPU_PKG_SOCKET5_7, + .block = CPU_BLOCK_NONE, + .min_bus = 50000000, + .max_bus = 66666667, + .min_voltage = 3380, + .max_voltage = 3520, + .min_multi = 1.5, + .max_multi = 3.0 + }, + .bus_flags = MACHINE_PS2_PCI, + .flags = MACHINE_IDE_DUAL | MACHINE_VIDEO | MACHINE_APM | MACHINE_ACPI, + .ram = { + .min = 8192, + .max = 131072, + .step = 8192 + }, + .nvrmask = 255, + .kbc_device = NULL, + .kbc_p1 = 0xff, + .gpio = 0xffffffff, + .gpio_acpi = 0xffffffff, + .device = NULL, + .fdc_device = NULL, + .sio_device = NULL, + .vid_device = &gd5440_onboard_pci_device, + .snd_device = NULL, + .net_device = NULL + }, + /* Has a VIA VT82C42N KBC. */ + { + .name = "[i430FX] PC Partner MB500N", + .internal_name = "mb500n", + .type = MACHINE_TYPE_SOCKET7_3V, + .chipset = MACHINE_CHIPSET_INTEL_430FX, + .init = machine_at_mb500n_init, + .p1_handler = NULL, + .gpio_handler = NULL, + .available_flag = MACHINE_AVAILABLE, + .gpio_acpi_handler = NULL, + .cpu = { + .package = CPU_PKG_SOCKET5_7, + .block = CPU_BLOCK_NONE, + .min_bus = 50000000, + .max_bus = 66666667, + .min_voltage = 3380, + .max_voltage = 3520, + .min_multi = 1.5, + .max_multi = 3.0 + }, + .bus_flags = MACHINE_PCI, + .flags = MACHINE_IDE_DUAL | MACHINE_APM | MACHINE_ACPI, + .ram = { + .min = 8192, + .max = 131072, + .step = 8192 + }, + .nvrmask = 127, + .kbc_device = NULL, + .kbc_p1 = 0xff, + .gpio = 0xffffffff, + .gpio_acpi = 0xffffffff, + .device = NULL, + .fdc_device = NULL, + .sio_device = NULL, + .vid_device = NULL, + .snd_device = NULL, + .net_device = NULL + }, /* Has an AMI 'H' KBC firmware (1992). */ - { "[i430FX] QDI FMB", "fmb", MACHINE_TYPE_SOCKET7_3V, CPU_PKG_SOCKET5_7, CPU_BLOCK(CPU_WINCHIP, CPU_WINCHIP2, CPU_Cx6x86, CPU_Cx6x86L, CPU_Cx6x86MX), 50000000, 66666667, 3380, 3520, 1.5, 3.0, MACHINE_PCI | MACHINE_BUS_PS2 | MACHINE_IDE_DUAL, 8192, 131072, 8192, 127, machine_at_fmb_init, NULL }, + { + .name = "[i430FX] QDI FMB", + .internal_name = "fmb", + .type = MACHINE_TYPE_SOCKET7_3V, + .chipset = MACHINE_CHIPSET_INTEL_430FX, + .init = machine_at_fmb_init, + .p1_handler = NULL, + .gpio_handler = NULL, + .available_flag = MACHINE_AVAILABLE, + .gpio_acpi_handler = NULL, + .cpu = { + .package = CPU_PKG_SOCKET5_7, + .block = CPU_BLOCK(CPU_WINCHIP, CPU_WINCHIP2, CPU_Cx6x86, CPU_Cx6x86L, CPU_Cx6x86MX), + .min_bus = 50000000, + .max_bus = 66666667, + .min_voltage = 3380, + .max_voltage = 3520, + .min_multi = 1.5, + .max_multi = 3.0 + }, + .bus_flags = MACHINE_PCI, + .flags = MACHINE_IDE_DUAL | MACHINE_APM | MACHINE_ACPI, + .ram = { + .min = 8192, + .max = 131072, + .step = 8192 + }, + .nvrmask = 127, + .kbc_device = NULL, + .kbc_p1 = 0xff, + .gpio = 0xffffffff, + .gpio_acpi = 0xffffffff, + .device = NULL, + .fdc_device = NULL, + .sio_device = NULL, + .vid_device = NULL, + .snd_device = NULL, + .net_device = NULL + }, /* 430HX */ /* I can't determine what KBC firmware this has, but given that the Acer V35N and V60 have Phoenix MultiKey KBC firmware on the chip, I'm going to assume so does the M3A. */ - { "[i430HX] Acer M3A", "acerm3a", MACHINE_TYPE_SOCKET7_3V, CPU_PKG_SOCKET5_7, 0, 50000000, 66666667, 3300, 3520, 1.5, 3.0, MACHINE_PCI | MACHINE_BUS_PS2 | MACHINE_IDE_DUAL, 8192, 196608, 8192, 127, machine_at_acerm3a_init, NULL }, + { + .name = "[i430HX] Acer M3A", + .internal_name = "acerm3a", + .type = MACHINE_TYPE_SOCKET7_3V, + .chipset = MACHINE_CHIPSET_INTEL_430HX, + .init = machine_at_acerm3a_init, + .p1_handler = NULL, + .gpio_handler = NULL, + .available_flag = MACHINE_AVAILABLE, + .gpio_acpi_handler = NULL, + .cpu = { + .package = CPU_PKG_SOCKET5_7, + .block = CPU_BLOCK_NONE, + .min_bus = 50000000, + .max_bus = 66666667, + .min_voltage = 3300, + .max_voltage = 3520, + .min_multi = 1.5, + .max_multi = 3.0 + }, + .bus_flags = MACHINE_PS2_PCI, + .flags = MACHINE_IDE_DUAL | MACHINE_APM | MACHINE_ACPI, + .ram = { + .min = 8192, + .max = 196608, + .step = 8192 + }, + .nvrmask = 127, + .kbc_device = NULL, + .kbc_p1 = 0xff, + .gpio = 0xffffffff, + .gpio_acpi = 0xffffffff, + .device = NULL, + .fdc_device = NULL, + .sio_device = NULL, + .vid_device = NULL, + .snd_device = NULL, + .net_device = NULL + }, /* Has AMIKey F KBC firmware. */ - { "[i430HX] AOpen AP53", "ap53", MACHINE_TYPE_SOCKET7_3V, CPU_PKG_SOCKET5_7, 0, 50000000, 66666667, 3450, 3520, 1.5, 3.0, MACHINE_PCI | MACHINE_BUS_PS2 | MACHINE_IDE_DUAL, 8192, 524288, 8192, 127, machine_at_ap53_init, NULL }, + { + .name = "[i430HX] AOpen AP53", + .internal_name = "ap53", + .type = MACHINE_TYPE_SOCKET7_3V, + .chipset = MACHINE_CHIPSET_INTEL_430HX, + .init = machine_at_ap53_init, + .p1_handler = NULL, + .gpio_handler = NULL, + .available_flag = MACHINE_AVAILABLE, + .gpio_acpi_handler = NULL, + .cpu = { + .package = CPU_PKG_SOCKET5_7, + .block = CPU_BLOCK_NONE, + .min_bus = 50000000, + .max_bus = 66666667, + .min_voltage = 3450, + .max_voltage = 3520, + .min_multi = 1.5, + .max_multi = 3.0 + }, + .bus_flags = MACHINE_PS2_PCI, + .flags = MACHINE_IDE_DUAL | MACHINE_APM | MACHINE_ACPI, + .ram = { + .min = 8192, + .max = 524288, + .step = 8192 + }, + .nvrmask = 127, + .kbc_device = NULL, + .kbc_p1 = 0xff, + .gpio = 0xffffffff, + .gpio_acpi = 0xffffffff, + .device = NULL, + .fdc_device = NULL, + .sio_device = NULL, + .vid_device = NULL, + .snd_device = NULL, + .net_device = NULL + }, /* [TEST] Has a VIA 82C42N KBC, with AMIKey F KBC firmware. */ - { "[i430HX] Biostar MB-8500TUC", "8500tuc", MACHINE_TYPE_SOCKET7_3V, CPU_PKG_SOCKET5_7, 0, 50000000, 66666667, 3380, 3520, 1.5, 3.0, MACHINE_PCI | MACHINE_BUS_PS2 | MACHINE_IDE_DUAL, 8192, 524288, 8192, 127, machine_at_8500tuc_init, NULL }, + { + .name = "[i430HX] Biostar MB-8500TUC", + .internal_name = "8500tuc", + .type = MACHINE_TYPE_SOCKET7_3V, + .chipset = MACHINE_CHIPSET_INTEL_430HX, + .init = machine_at_8500tuc_init, + .p1_handler = NULL, + .gpio_handler = NULL, + .available_flag = MACHINE_AVAILABLE, + .gpio_acpi_handler = NULL, + .cpu = { + .package = CPU_PKG_SOCKET5_7, + .block = CPU_BLOCK_NONE, + .min_bus = 50000000, + .max_bus = 66666667, + .min_voltage = 3380, + .max_voltage = 3520, + .min_multi = 1.5, + .max_multi = 3.0 + }, + .bus_flags = MACHINE_PS2_PCI, + .flags = MACHINE_IDE_DUAL | MACHINE_APM | MACHINE_ACPI, + .ram = { + .min = 8192, + .max = 524288, + .step = 8192 + }, + .nvrmask = 127, + .kbc_device = NULL, + .kbc_p1 = 0xff, + .gpio = 0xffffffff, + .gpio_acpi = 0xffffffff, + .device = NULL, + .fdc_device = NULL, + .sio_device = NULL, + .vid_device = NULL, + .snd_device = NULL, + .net_device = NULL + }, /* [TEST] Unable to determine what KBC this has. A list on a Danish site shows the BIOS as having a -0 string, indicating non-AMI KBC firmware. */ - { "[i430HX] Supermicro P55T2S", "p55t2s", MACHINE_TYPE_SOCKET7_3V, CPU_PKG_SOCKET5_7, 0, 50000000, 66666667, 3300, 3520, 1.5, 3.0, MACHINE_PCI | MACHINE_BUS_PS2 | MACHINE_IDE_DUAL, 8192, 786432, 8192, 127, machine_at_p55t2s_init, NULL }, + { + .name = "[i430HX] Supermicro P55T2S", + .internal_name = "p55t2s", + .type = MACHINE_TYPE_SOCKET7_3V, + .chipset = MACHINE_CHIPSET_INTEL_430HX, + .init = machine_at_p55t2s_init, + .p1_handler = NULL, + .gpio_handler = NULL, + .available_flag = MACHINE_AVAILABLE, + .gpio_acpi_handler = NULL, + .cpu = { + .package = CPU_PKG_SOCKET5_7, + .block = CPU_BLOCK_NONE, + .min_bus = 50000000, + .max_bus = 66666667, + .min_voltage = 3300, + .max_voltage = 3520, + .min_multi = 1.5, + .max_multi = 3.0 + }, + .bus_flags = MACHINE_PS2_PCI, + .flags = MACHINE_IDE_DUAL | MACHINE_APM | MACHINE_ACPI, + .ram = { + .min = 8192, + .max = 786432, + .step = 8192 + }, + .nvrmask = 255, + .kbc_device = NULL, + .kbc_p1 = 0xff, + .gpio = 0xffffffff, + .gpio_acpi = 0xffffffff, + .device = NULL, + .fdc_device = NULL, + .sio_device = NULL, + .vid_device = NULL, + .snd_device = NULL, + .net_device = NULL + }, /* 430VX */ /* Has AMIKey H KBC firmware (AMIKey-2). */ - { "[i430VX] ECS P5VX-B", "p5vxb", MACHINE_TYPE_SOCKET7_3V, CPU_PKG_SOCKET5_7, 0, 50000000, 66666667, 3380, 3520, 1.5, 3.0, MACHINE_PCI | MACHINE_BUS_PS2 | MACHINE_IDE_DUAL, 8192, 131072, 8192, 127, machine_at_p5vxb_init, NULL }, + { + .name = "[i430VX] ECS P5VX-B", + .internal_name = "p5vxb", + .type = MACHINE_TYPE_SOCKET7_3V, + .chipset = MACHINE_CHIPSET_INTEL_430VX, + .init = machine_at_p5vxb_init, + .p1_handler = NULL, + .gpio_handler = NULL, + .available_flag = MACHINE_AVAILABLE, + .gpio_acpi_handler = NULL, + .cpu = { + .package = CPU_PKG_SOCKET5_7, + .block = CPU_BLOCK_NONE, + .min_bus = 50000000, + .max_bus = 66666667, + .min_voltage = 3380, + .max_voltage = 3520, + .min_multi = 1.5, + .max_multi = 3.0 + }, + .bus_flags = MACHINE_PS2_PCI, + .flags = MACHINE_IDE_DUAL | MACHINE_APM | MACHINE_ACPI, + .ram = { + .min = 8192, + .max = 131072, + .step = 8192 + }, + .nvrmask = 127, + .kbc_device = NULL, + .kbc_p1 = 0xff, + .gpio = 0xffffffff, + .gpio_acpi = 0xffffffff, + .device = NULL, + .fdc_device = NULL, + .sio_device = NULL, + .vid_device = NULL, + .snd_device = NULL, + .net_device = NULL + }, /* According to tests from real hardware: This has AMI MegaKey KBC firmware on the PC87306 Super I/O chip, command 0xA1 returns '5'. Command 0xA0 copyright string: (C)1994 AMI . */ - { "[i430VX] Gateway 2000 Tigereye", "gw2kte", MACHINE_TYPE_SOCKET7_3V, CPU_PKG_SOCKET5_7, 0, 50000000, 66666667, 3380, 3520, 1.5, 3.0, MACHINE_PCI | MACHINE_BUS_PS2 | MACHINE_IDE_DUAL, 8192, 131072, 8192, 127, machine_at_gw2kte_init, NULL }, + { + .name = "[i430VX] Gateway 2000 Tigereye", + .internal_name = "gw2kte", + .type = MACHINE_TYPE_SOCKET7_3V, + .chipset = MACHINE_CHIPSET_INTEL_430VX, + .init = machine_at_gw2kte_init, + .p1_handler = NULL, + .gpio_handler = NULL, + .available_flag = MACHINE_AVAILABLE, + .gpio_acpi_handler = NULL, + .cpu = { + .package = CPU_PKG_SOCKET5_7, + .block = CPU_BLOCK_NONE, + .min_bus = 50000000, + .max_bus = 66666667, + .min_voltage = 3380, + .max_voltage = 3520, + .min_multi = 1.5, + .max_multi = 3.0 + }, + .bus_flags = MACHINE_PS2_PCI, + .flags = MACHINE_IDE_DUAL | MACHINE_APM | MACHINE_ACPI, + .ram = { + .min = 8192, + .max = 131072, + .step = 8192 + }, + .nvrmask = 127, + .kbc_device = NULL, + .kbc_p1 = 0xff, + .gpio = 0xffffffff, + .gpio_acpi = 0xffffffff, + .device = NULL, + .fdc_device = NULL, + .sio_device = NULL, + .vid_device = NULL, + .snd_device = NULL, + .net_device = NULL + }, /* SiS 5511 */ /* Has AMIKey H KBC firmware (AMIKey-2). */ - { "[SiS 5511] AOpen AP5S", "ap5s", MACHINE_TYPE_SOCKET7_3V, CPU_PKG_SOCKET5_7, 0, 50000000, 66666667, 3380, 3520, 1.5, 3.0, MACHINE_PCI | MACHINE_BUS_PS2 | MACHINE_IDE_DUAL, 8192, 524288, 8192, 127, machine_at_ap5s_init, NULL }, + { + .name = "[SiS 5511] AOpen AP5S", + .internal_name = "ap5s", + .type = MACHINE_TYPE_SOCKET7_3V, + .chipset = MACHINE_CHIPSET_SIS_5511, + .init = machine_at_ap5s_init, + .p1_handler = NULL, + .gpio_handler = NULL, + .available_flag = MACHINE_AVAILABLE, + .gpio_acpi_handler = NULL, + .cpu = { + .package = CPU_PKG_SOCKET5_7, + .block = CPU_BLOCK_NONE, + .min_bus = 50000000, + .max_bus = 66666667, + .min_voltage = 3380, + .max_voltage = 3520, + .min_multi = 1.5, + .max_multi = 3.0 + }, + .bus_flags = MACHINE_PS2_PCI, + .flags = MACHINE_IDE_DUAL | MACHINE_APM | MACHINE_ACPI, + .ram = { + .min = 8192, + .max = 524288, + .step = 8192 + }, + .nvrmask = 127, + .kbc_device = NULL, + .kbc_p1 = 0xff, + .gpio = 0xffffffff, + .gpio_acpi = 0xffffffff, + .device = NULL, + .fdc_device = NULL, + .sio_device = NULL, + .vid_device = NULL, + .snd_device = NULL, + .net_device = NULL + }, + /* Has AMIKey H KBC firmware (AMIKey-2). */ + { + .name = "[SiS 5511] MSI MS-5124", + .internal_name = "ms5124", + .type = MACHINE_TYPE_SOCKET7_3V, + .chipset = MACHINE_CHIPSET_SIS_5511, + .init = machine_at_ms5124_init, + .p1_handler = NULL, + .gpio_handler = NULL, + .available_flag = MACHINE_AVAILABLE, + .gpio_acpi_handler = NULL, + .cpu = { + .package = CPU_PKG_SOCKET5_7, + .block = CPU_BLOCK_NONE, + .min_bus = 50000000, + .max_bus = 66666667, + .min_voltage = 3380, + .max_voltage = 3520, + .min_multi = 1.5, + .max_multi = 3.0 + }, + .bus_flags = MACHINE_PS2_PCI, + .flags = MACHINE_IDE_DUAL | MACHINE_APM | MACHINE_ACPI, + .ram = { + .min = 8192, + .max = 524288, + .step = 8192 + }, + .nvrmask = 127, + .kbc_device = NULL, + .kbc_p1 = 0xff, + .gpio = 0xffffffff, + .gpio_acpi = 0xffffffff, + .device = NULL, + .fdc_device = NULL, + .sio_device = NULL, + .vid_device = NULL, + .snd_device = NULL, + .net_device = NULL + }, /* Socket 7 (Dual Voltage) machines */ /* 430HX */ /* Has SST flash and the SMC FDC73C935's on-chip KBC with Phoenix MultiKey firmware. */ - { "[i430HX] Acer V35N", "acerv35n", MACHINE_TYPE_SOCKET7, CPU_PKG_SOCKET5_7, CPU_BLOCK(CPU_Cx6x86MX), 50000000, 66666667, 2800, 3520, 1.5, 3.0, MACHINE_PCI | MACHINE_BUS_PS2 | MACHINE_IDE_DUAL, 8192, 196608, 8192, 127, machine_at_acerv35n_init, NULL }, + { + .name = "[i430HX] Acer V35N", + .internal_name = "acerv35n", + .type = MACHINE_TYPE_SOCKET7, + .chipset = MACHINE_CHIPSET_INTEL_430HX, + .init = machine_at_acerv35n_init, + .p1_handler = NULL, + .gpio_handler = NULL, + .available_flag = MACHINE_AVAILABLE, + .gpio_acpi_handler = NULL, + .cpu = { + .package = CPU_PKG_SOCKET5_7, + .block = CPU_BLOCK(CPU_Cx6x86MX), + .min_bus = 50000000, + .max_bus = 66666667, + .min_voltage = 2800, + .max_voltage = 3520, + .min_multi = 1.5, + .max_multi = 3.0 + }, + .bus_flags = MACHINE_PS2_PCI, + .flags = MACHINE_IDE_DUAL | MACHINE_APM | MACHINE_ACPI, + .ram = { + .min = 8192, + .max = 196608, + .step = 8192 + }, + .nvrmask = 127, + .kbc_device = NULL, + .kbc_p1 = 0xff, + .gpio = 0xffffffff, + .gpio_acpi = 0xffffffff, + .device = NULL, + .fdc_device = NULL, + .sio_device = NULL, + .vid_device = NULL, + .snd_device = NULL, + .net_device = NULL + }, /* Has AMIKey H KBC firmware (AMIKey-2). */ - { "[i430HX] ASUS P/I-P55T2P4", "p55t2p4", MACHINE_TYPE_SOCKET7, CPU_PKG_SOCKET5_7, 0, 50000000, 83333333, 2500, 3520, 1.5, 3.0, MACHINE_PCI | MACHINE_BUS_PS2 | MACHINE_IDE_DUAL, 8192, 262144, 8192, 127, machine_at_p55t2p4_init, NULL }, + { + .name = "[i430HX] ASUS P/I-P55T2P4", + .internal_name = "p55t2p4", + .type = MACHINE_TYPE_SOCKET7, + .chipset = MACHINE_CHIPSET_INTEL_430HX, + .init = machine_at_p55t2p4_init, + .p1_handler = NULL, + .gpio_handler = NULL, + .available_flag = MACHINE_AVAILABLE, + .gpio_acpi_handler = NULL, + .cpu = { + .package = CPU_PKG_SOCKET5_7, + .block = CPU_BLOCK_NONE, + .min_bus = 50000000, + .max_bus = 83333333, + .min_voltage = 2500, + .max_voltage = 3520, + .min_multi = 1.5, + .max_multi = 3.0 + }, + .bus_flags = MACHINE_PS2_PCI, + .flags = MACHINE_IDE_DUAL | MACHINE_APM | MACHINE_ACPI, + .ram = { + .min = 8192, + .max = 262144, + .step = 8192 + }, + .nvrmask = 127, + .kbc_device = NULL, + .kbc_p1 = 0xff, + .gpio = 0xffffffff, + .gpio_acpi = 0xffffffff, + .device = NULL, + .fdc_device = NULL, + .sio_device = NULL, + .vid_device = NULL, + .snd_device = NULL, + .net_device = NULL + }, /* Has the SMC FDC73C935's on-chip KBC with Phoenix MultiKey firmware. */ - { "[i430HX] Micronics M7S-Hi", "m7shi", MACHINE_TYPE_SOCKET7, CPU_PKG_SOCKET5_7, 0, 50000000, 66666667, 2800, 3520, 1.5, 3.0, MACHINE_PCI | MACHINE_BUS_PS2 | MACHINE_IDE_DUAL, 8192, 131072, 8192, 511, machine_at_m7shi_init, NULL }, + { + .name = "[i430HX] Micronics M7S-Hi", + .internal_name = "m7shi", + .type = MACHINE_TYPE_SOCKET7, + .chipset = MACHINE_CHIPSET_INTEL_430HX, + .init = machine_at_m7shi_init, + .p1_handler = NULL, + .gpio_handler = NULL, + .available_flag = MACHINE_AVAILABLE, + .gpio_acpi_handler = NULL, + .cpu = { + .package = CPU_PKG_SOCKET5_7, + .block = CPU_BLOCK_NONE, + .min_bus = 50000000, + .max_bus = 66666667, + .min_voltage = 2800, + .max_voltage = 3520, + .min_multi = 1.5, + .max_multi = 3.0 + }, + .bus_flags = MACHINE_PS2_PCI, + .flags = MACHINE_IDE_DUAL | MACHINE_APM | MACHINE_ACPI, + .ram = { + .min = 8192, + .max = 131072, + .step = 8192 + }, + .nvrmask = 511, + .kbc_device = NULL, + .kbc_p1 = 0xff, + .gpio = 0xffffffff, + .gpio_acpi = 0xffffffff, + .device = NULL, + .fdc_device = NULL, + .sio_device = NULL, + .vid_device = NULL, + .snd_device = NULL, + .net_device = NULL + }, /* According to tests from real hardware: This has AMI MegaKey KBC firmware on the PC87306 Super I/O chip, command 0xA1 returns '5'. Command 0xA0 copyright string: (C)1994 AMI . */ - { "[i430HX] Intel TC430HX", "tc430hx", MACHINE_TYPE_SOCKET7, CPU_PKG_SOCKET5_7, 0, 50000000, 66666667, 2800, 3520, 1.5, 3.0, MACHINE_PCI | MACHINE_BUS_PS2 | MACHINE_IDE_DUAL, 8192, 131072, 8192, 255, machine_at_tc430hx_init, NULL }, - /* According to tests from real hardware: This has AMI MegaKey KBC firmware on the - PC87306 Super I/O chip, command 0xA1 returns '5'. - Command 0xA0 copyright string: (C)1994 AMI . */ - { "[i430HX] Toshiba Equium 5200D", "equium5200", MACHINE_TYPE_SOCKET7, CPU_PKG_SOCKET5_7, 0, 50000000, 66666667, 2800, 3520, 1.5, 3.0, MACHINE_PCI | MACHINE_BUS_PS2 | MACHINE_IDE_DUAL, 8192, 196608, 8192, 127, machine_at_equium5200_init, NULL }, + { + .name = "[i430HX] Intel TC430HX", + .internal_name = "tc430hx", + .type = MACHINE_TYPE_SOCKET7, + .chipset = MACHINE_CHIPSET_INTEL_430HX, + .init = machine_at_tc430hx_init, + .p1_handler = NULL, + .gpio_handler = NULL, + .available_flag = MACHINE_AVAILABLE, + .gpio_acpi_handler = NULL, + .cpu = { + .package = CPU_PKG_SOCKET5_7, + .block = CPU_BLOCK_NONE, + .min_bus = 50000000, + .max_bus = 66666667, + .min_voltage = 2800, + .max_voltage = 3520, + .min_multi = 1.5, + .max_multi = 3.0 + }, + .bus_flags = MACHINE_PS2_PCI, + .flags = MACHINE_VIDEO | MACHINE_IDE_DUAL | MACHINE_APM | MACHINE_ACPI, + .ram = { + .min = 8192, + .max = 131072, + .step = 8192 + }, + .nvrmask = 255, + .kbc_device = NULL, + .kbc_p1 = 0xff, + .gpio = 0xffffffff, + .gpio_acpi = 0xffffffff, + .device = NULL, + .fdc_device = NULL, + .sio_device = NULL, + .vid_device = &s3_virge_375_pci_device, + .snd_device = NULL, + .net_device = NULL + }, + /* OEM version of Intel TC430HX, has AMI MegaKey KBC firmware on the PC87306 Super I/O chip. */ + { + .name = "[i430HX] Toshiba Infinia 7200", + .internal_name = "infinia7200", + .type = MACHINE_TYPE_SOCKET7, + .chipset = MACHINE_CHIPSET_INTEL_430HX, + .init = machine_at_infinia7200_init, + .p1_handler = NULL, + .gpio_handler = NULL, + .available_flag = MACHINE_AVAILABLE, + .gpio_acpi_handler = NULL, + .cpu = { + .package = CPU_PKG_SOCKET5_7, + .block = CPU_BLOCK_NONE, + .min_bus = 50000000, + .max_bus = 66666667, + .min_voltage = 2800, + .max_voltage = 3520, + .min_multi = 1.5, + .max_multi = 3.0 + }, + .bus_flags = MACHINE_PS2_PCI, + .flags = MACHINE_VIDEO | MACHINE_IDE_DUAL | MACHINE_APM | MACHINE_ACPI, + .ram = { + .min = 8192, + .max = 131072, + .step = 8192 + }, + .nvrmask = 255, + .kbc_device = NULL, + .kbc_p1 = 0xff, + .gpio = 0xffffffff, + .gpio_acpi = 0xffffffff, + .device = NULL, + .fdc_device = NULL, + .sio_device = NULL, + .vid_device = &s3_virge_375_pci_device, + .snd_device = NULL, + .net_device = NULL + }, + /* OEM-only Intel CU430HX, has AMI MegaKey KBC firmware on the PC87306 Super I/O chip. */ + { + .name = "[i430HX] Intel CU430HX", + .internal_name = "cu430hx", + .type = MACHINE_TYPE_SOCKET7, + .chipset = MACHINE_CHIPSET_INTEL_430HX, + .init = machine_at_cu430hx_init, + .p1_handler = NULL, + .gpio_handler = NULL, + .available_flag = MACHINE_AVAILABLE, + .gpio_acpi_handler = NULL, + .cpu = { + .package = CPU_PKG_SOCKET5_7, + .block = CPU_BLOCK_NONE, + .min_bus = 50000000, + .max_bus = 66666667, + .min_voltage = 2800, + .max_voltage = 3520, + .min_multi = 1.5, + .max_multi = 3.0 + }, + .bus_flags = MACHINE_PS2_PCI, + .flags = MACHINE_IDE_DUAL | MACHINE_SOUND | MACHINE_APM | MACHINE_ACPI, + .ram = { + .min = 8192, + .max = 196608, + .step = 8192 + }, + .nvrmask = 255, + .kbc_device = NULL, + .kbc_p1 = 0xff, + .gpio = 0xffffffff, + .gpio_acpi = 0xffffffff, + .device = NULL, + .fdc_device = NULL, + .sio_device = NULL, + .vid_device = NULL, + .snd_device = &sb_vibra16c_onboard_device, + .net_device = NULL + }, + /* OEM-only Intel CU430HX, has AMI MegaKey KBC firmware on the PC87306 Super I/O chip. */ + { + .name = "[i430HX] Toshiba Equium 5200D", + .internal_name = "equium5200", + .type = MACHINE_TYPE_SOCKET7, + .chipset = MACHINE_CHIPSET_INTEL_430HX, + .init = machine_at_equium5200_init, + .p1_handler = NULL, + .gpio_handler = NULL, + .available_flag = MACHINE_AVAILABLE, + .gpio_acpi_handler = NULL, + .cpu = { + .package = CPU_PKG_SOCKET5_7, + .block = CPU_BLOCK_NONE, + .min_bus = 50000000, + .max_bus = 66666667, + .min_voltage = 2800, + .max_voltage = 3520, + .min_multi = 1.5, + .max_multi = 3.0 + }, + .bus_flags = MACHINE_PS2_PCI, + .flags = MACHINE_IDE_DUAL | MACHINE_SOUND | MACHINE_APM | MACHINE_ACPI, + .ram = { + .min = 8192, + .max = 196608, + .step = 8192 + }, + .nvrmask = 255, + .kbc_device = NULL, + .kbc_p1 = 0xff, + .gpio = 0xffffffff, + .gpio_acpi = 0xffffffff, + .device = NULL, + .fdc_device = NULL, + .sio_device = NULL, + .vid_device = NULL, + .snd_device = &sb_vibra16c_onboard_device, + .net_device = NULL + }, /* According to tests from real hardware: This has AMI MegaKey KBC firmware on the PC87306 Super I/O chip, command 0xA1 returns '5'. Command 0xA0 copyright string: (C)1994 AMI . Yes, this is an Intel AMI BIOS with a fancy splash screen. */ - { "[i430HX] Sony Vaio PCV-90", "pcv90", MACHINE_TYPE_SOCKET7, CPU_PKG_SOCKET5_7, 0, 50000000, 66666667, 2800, 3520, 1.5, 3.0, MACHINE_PCI | MACHINE_BUS_PS2 | MACHINE_IDE_DUAL, 8192, 196608, 8192, 127, machine_at_pcv90_init, NULL }, + { + .name = "[i430HX] Sony Vaio PCV-90", + .internal_name = "pcv90", + .type = MACHINE_TYPE_SOCKET7, + .chipset = MACHINE_CHIPSET_INTEL_430HX, + .init = machine_at_pcv90_init, + .p1_handler = NULL, + .gpio_handler = NULL, + .available_flag = MACHINE_AVAILABLE, + .gpio_acpi_handler = NULL, + .cpu = { + .package = CPU_PKG_SOCKET5_7, + .block = CPU_BLOCK_NONE, + .min_bus = 50000000, + .max_bus = 66666667, + .min_voltage = 2800, + .max_voltage = 3520, + .min_multi = 1.5, + .max_multi = 3.0 + }, + .bus_flags = MACHINE_PS2_PCI, + .flags = MACHINE_IDE_DUAL | MACHINE_APM | MACHINE_ACPI, + .ram = { + .min = 8192, + .max = 196608, + .step = 8192 + }, + .nvrmask = 255, + .kbc_device = NULL, + .kbc_p1 = 0xff, + .gpio = 0xffffffff, + .gpio_acpi = 0xffffffff, + .device = NULL, + .fdc_device = NULL, + .sio_device = NULL, + .vid_device = NULL, + .snd_device = NULL, + .net_device = NULL + }, /* The base board has AMIKey-2 (updated 'H') KBC firmware. */ - { "[i430HX] ASUS P/I-P65UP5 (C-P55T2D)", "p65up5_cp55t2d", MACHINE_TYPE_SOCKET7, CPU_PKG_SOCKET5_7, 0, 50000000, 66666667, 2500, 3520, 1.5, 3.0, MACHINE_PCI | MACHINE_BUS_PS2 | MACHINE_IDE_DUAL, 8192, 524288, 8192, 127, machine_at_p65up5_cp55t2d_init, NULL }, + { + .name = "[i430HX] ASUS P/I-P65UP5 (C-P55T2D)", + .internal_name = "p65up5_cp55t2d", + .type = MACHINE_TYPE_SOCKET7, + .chipset = MACHINE_CHIPSET_INTEL_430HX, + .init = machine_at_p65up5_cp55t2d_init, + .p1_handler = NULL, + .gpio_handler = NULL, + .available_flag = MACHINE_AVAILABLE, + .gpio_acpi_handler = NULL, + .cpu = { + .package = CPU_PKG_SOCKET5_7, + .block = CPU_BLOCK_NONE, + .min_bus = 50000000, + .max_bus = 66666667, + .min_voltage = 2500, + .max_voltage = 3520, + .min_multi = 1.5, + .max_multi = 3.0 + }, + .bus_flags = MACHINE_PS2_PCI, + .flags = MACHINE_IDE_DUAL | MACHINE_APM | MACHINE_ACPI, + .ram = { + .min = 8192, + .max = 524288, + .step = 8192 + }, + .nvrmask = 127, + .kbc_device = NULL, + .kbc_p1 = 0xff, + .gpio = 0xffffffff, + .gpio_acpi = 0xffffffff, + .device = NULL, + .fdc_device = NULL, + .sio_device = NULL, + .vid_device = NULL, + .snd_device = NULL, + .net_device = NULL + }, /* 430VX */ /* This has the VIA VT82C42N KBC. */ - { "[i430VX] AOpen AP5VM", "ap5vm", MACHINE_TYPE_SOCKET7, CPU_PKG_SOCKET5_7, 0, 50000000, 66666667, 2600, 3520, 1.5, 3.0, MACHINE_PCI | MACHINE_BUS_PS2 | MACHINE_IDE_DUAL | MACHINE_SCSI, 8192, 131072, 8192, 127, machine_at_ap5vm_init, NULL }, + { + .name = "[i430VX] AOpen AP5VM", + .internal_name = "ap5vm", + .type = MACHINE_TYPE_SOCKET7, + .chipset = MACHINE_CHIPSET_INTEL_430VX, + .init = machine_at_ap5vm_init, + .p1_handler = NULL, + .gpio_handler = NULL, + .available_flag = MACHINE_AVAILABLE, + .gpio_acpi_handler = NULL, + .cpu = { + .package = CPU_PKG_SOCKET5_7, + .block = CPU_BLOCK_NONE, + .min_bus = 50000000, + .max_bus = 66666667, + .min_voltage = 2600, + .max_voltage = 3520, + .min_multi = 1.5, + .max_multi = 3.0 + }, + .bus_flags = MACHINE_PS2_PCI, + .flags = MACHINE_IDE_DUAL | MACHINE_SCSI | MACHINE_APM | MACHINE_ACPI, + .ram = { + .min = 8192, + .max = 131072, + .step = 8192 + }, + .nvrmask = 127, + .kbc_device = NULL, + .kbc_p1 = 0xff, + .gpio = 0xffffffff, + .gpio_acpi = 0xffffffff, + .device = NULL, + .fdc_device = NULL, + .sio_device = NULL, + .vid_device = NULL, + .snd_device = NULL, + .net_device = NULL + }, /* Has AMIKey H KBC firmware (AMIKey-2). */ - { "[i430VX] ASUS P/I-P55TVP4", "p55tvp4", MACHINE_TYPE_SOCKET7, CPU_PKG_SOCKET5_7, 0, 50000000, 66666667, 2500, 3520, 1.5, 3.0, MACHINE_PCI | MACHINE_BUS_PS2 | MACHINE_IDE_DUAL, 8192, 131072, 8192, 127, machine_at_p55tvp4_init, NULL }, + { + .name = "[i430VX] ASUS P/I-P55TVP4", + .internal_name = "p55tvp4", + .type = MACHINE_TYPE_SOCKET7, + .chipset = MACHINE_CHIPSET_INTEL_430VX, + .init = machine_at_p55tvp4_init, + .p1_handler = NULL, + .gpio_handler = NULL, + .available_flag = MACHINE_AVAILABLE, + .gpio_acpi_handler = NULL, + .cpu = { + .package = CPU_PKG_SOCKET5_7, + .block = CPU_BLOCK_NONE, + .min_bus = 50000000, + .max_bus = 66666667, + .min_voltage = 2500, + .max_voltage = 3520, + .min_multi = 1.5, + .max_multi = 3.0 + }, + .bus_flags = MACHINE_PS2_PCI, + .flags = MACHINE_IDE_DUAL | MACHINE_APM | MACHINE_ACPI, + .ram = { + .min = 8192, + .max = 131072, + .step = 8192 + }, + .nvrmask = 127, + .kbc_device = NULL, + .kbc_p1 = 0xff, + .gpio = 0xffffffff, + .gpio_acpi = 0xffffffff, + .device = NULL, + .fdc_device = NULL, + .sio_device = NULL, + .vid_device = NULL, + .snd_device = NULL, + .net_device = NULL + }, /* The BIOS does not send a single non-standard KBC command, so it must have a standard IBM PS/2 KBC firmware or a clone thereof. */ - { "[i430VX] Azza PT-5IV", "5ivg", MACHINE_TYPE_SOCKET7, CPU_PKG_SOCKET5_7, 0, 50000000, 66666667, 2500, 3520, 1.5, 3.0, MACHINE_PCI | MACHINE_BUS_PS2 | MACHINE_IDE_DUAL, 8192, 131072, 8192, 127, machine_at_5ivg_init, NULL }, + { + .name = "[i430VX] Azza PT-5IV", + .internal_name = "5ivg", + .type = MACHINE_TYPE_SOCKET7, + .chipset = MACHINE_CHIPSET_INTEL_430VX, + .init = machine_at_5ivg_init, + .p1_handler = NULL, + .gpio_handler = NULL, + .available_flag = MACHINE_AVAILABLE, + .gpio_acpi_handler = NULL, + .cpu = { + .package = CPU_PKG_SOCKET5_7, + .block = CPU_BLOCK_NONE, + .min_bus = 50000000, + .max_bus = 66666667, + .min_voltage = 2500, + .max_voltage = 3520, + .min_multi = 1.5, + .max_multi = 3.0 + }, + .bus_flags = MACHINE_PS2_PCI, + .flags = MACHINE_IDE_DUAL | MACHINE_APM | MACHINE_ACPI, + .ram = { + .min = 8192, + .max = 131072, + .step = 8192 + }, + .nvrmask = 127, + .kbc_device = NULL, + .kbc_p1 = 0xff, + .gpio = 0xffffffff, + .gpio_acpi = 0xffffffff, + .device = NULL, + .fdc_device = NULL, + .sio_device = NULL, + .vid_device = NULL, + .snd_device = NULL, + .net_device = NULL + }, /* [TEST] Has AMIKey 'F' KBC firmware. */ - { "[i430VX] Biostar MB-8500TVX-A", "8500tvxa", MACHINE_TYPE_SOCKET7, CPU_PKG_SOCKET5_7, 0, 50000000, 66666667, 2600, 3520, 1.5, 3.0, MACHINE_PCI | MACHINE_BUS_PS2 | MACHINE_IDE_DUAL, 8192, 131072, 8192, 127, machine_at_8500tvxa_init, NULL }, + { + .name = "[i430VX] Biostar MB-8500TVX-A", + .internal_name = "8500tvxa", + .type = MACHINE_TYPE_SOCKET7, + .chipset = MACHINE_CHIPSET_INTEL_430VX, + .init = machine_at_8500tvxa_init, + .p1_handler = NULL, + .gpio_handler = NULL, + .available_flag = MACHINE_AVAILABLE, + .gpio_acpi_handler = NULL, + .cpu = { + .package = CPU_PKG_SOCKET5_7, + .block = CPU_BLOCK_NONE, + .min_bus = 50000000, + .max_bus = 66666667, + .min_voltage = 2600, + .max_voltage = 3520, + .min_multi = 1.5, + .max_multi = 3.0 + }, + .bus_flags = MACHINE_PS2_PCI, + .flags = MACHINE_IDE_DUAL | MACHINE_APM | MACHINE_ACPI, + .ram = { + .min = 8192, + .max = 131072, + .step = 8192 + }, + .nvrmask = 127, + .kbc_device = NULL, + .kbc_p1 = 0xff, + .gpio = 0xffffffff, + .gpio_acpi = 0xffffffff, + .device = NULL, + .fdc_device = NULL, + .sio_device = NULL, + .vid_device = NULL, + .snd_device = NULL, + .net_device = NULL + }, /* The BIOS does not send a single non-standard KBC command, but the board has a SMC Super I/O chip with on-chip KBC and AMI MegaKey KBC firmware. */ - { "[i430VX] Compaq Presario 2240", "presario2240", MACHINE_TYPE_SOCKET7, CPU_PKG_SOCKET5_7, 0, 50000000, 66666667, 2800, 3520, 1.5, 3.0, MACHINE_PCI | MACHINE_BUS_PS2 | MACHINE_IDE_DUAL | MACHINE_VIDEO, 8192, 131072, 8192, 127, machine_at_presario2240_init, at_presario2240_get_device }, + { + .name = "[i430VX] Compaq Presario 2240", + .internal_name = "presario2240", + .type = MACHINE_TYPE_SOCKET7, + .chipset = MACHINE_CHIPSET_INTEL_430VX, + .init = machine_at_presario2240_init, + .p1_handler = NULL, + .gpio_handler = NULL, + .available_flag = MACHINE_AVAILABLE, + .gpio_acpi_handler = NULL, + .cpu = { + .package = CPU_PKG_SOCKET5_7, + .block = CPU_BLOCK_NONE, + .min_bus = 50000000, + .max_bus = 66666667, + .min_voltage = 2800, + .max_voltage = 3520, + .min_multi = 1.5, + .max_multi = 3.0 + }, + .bus_flags = MACHINE_PS2_PCI, + .flags = MACHINE_IDE_DUAL | MACHINE_VIDEO | MACHINE_APM | MACHINE_ACPI, + .ram = { + .min = 8192, + .max = 131072, + .step = 8192 + }, + .nvrmask = 127, + .kbc_device = NULL, + .kbc_p1 = 0xff, + .gpio = 0xffffffff, + .gpio_acpi = 0xffffffff, + .device = NULL, + .fdc_device = NULL, + .sio_device = NULL, + .vid_device = &s3_trio64v2_dx_onboard_pci_device, + .snd_device = NULL, + .net_device = NULL + }, /* This most likely has AMI MegaKey as above. */ - { "[i430VX] Compaq Presario 4500", "presario4500", MACHINE_TYPE_SOCKET7, CPU_PKG_SOCKET5_7, 0, 50000000, 66666667, 2800, 3520, 1.5, 3.0, MACHINE_PCI | MACHINE_BUS_PS2 | MACHINE_IDE_DUAL | MACHINE_VIDEO, 8192, 131072, 8192, 127, machine_at_presario4500_init, at_presario4500_get_device }, + { + .name = "[i430VX] Compaq Presario 4500", + .internal_name = "presario4500", + .type = MACHINE_TYPE_SOCKET7, + .chipset = MACHINE_CHIPSET_INTEL_430VX, + .init = machine_at_presario4500_init, + .p1_handler = NULL, + .gpio_handler = NULL, + .available_flag = MACHINE_AVAILABLE, + .gpio_acpi_handler = NULL, + .cpu = { + .package = CPU_PKG_SOCKET5_7, + .block = CPU_BLOCK_NONE, + .min_bus = 50000000, + .max_bus = 66666667, + .min_voltage = 2800, + .max_voltage = 3520, + .min_multi = 1.5, + .max_multi = 3.0 + }, + .bus_flags = MACHINE_PS2_PCI, + .flags = MACHINE_IDE_DUAL | MACHINE_VIDEO | MACHINE_APM | MACHINE_ACPI, + .ram = { + .min = 8192, + .max = 131072, + .step = 8192 + }, + .nvrmask = 127, + .kbc_device = NULL, + .kbc_p1 = 0xff, + .gpio = 0xffffffff, + .gpio_acpi = 0xffffffff, + .device = NULL, + .fdc_device = NULL, + .sio_device = NULL, + .vid_device = &s3_trio64v2_dx_onboard_pci_device, + .snd_device = NULL, + .net_device = NULL + }, /* The BIOS sends KBC command CB which is an AMI KBC command, so it has an AMI KBC firmware. */ - { "[i430VX] Epox P55-VA", "p55va", MACHINE_TYPE_SOCKET7, CPU_PKG_SOCKET5_7, 0, 50000000, 66666667, 2500, 3520, 1.5, 3.0, MACHINE_PCI | MACHINE_BUS_PS2 | MACHINE_IDE_DUAL, 8192, 131072, 8192, 127, machine_at_p55va_init, NULL }, + { + .name = "[i430VX] Epox P55-VA", + .internal_name = "p55va", + .type = MACHINE_TYPE_SOCKET7, + .chipset = MACHINE_CHIPSET_INTEL_430VX, + .init = machine_at_p55va_init, + .p1_handler = NULL, + .gpio_handler = NULL, + .available_flag = MACHINE_AVAILABLE, + .gpio_acpi_handler = NULL, + .cpu = { + .package = CPU_PKG_SOCKET5_7, + .block = CPU_BLOCK_NONE, + .min_bus = 50000000, + .max_bus = 66666667, + .min_voltage = 2500, + .max_voltage = 3520, + .min_multi = 1.5, + .max_multi = 3.0 + }, + .bus_flags = MACHINE_PS2_PCI, + .flags = MACHINE_IDE_DUAL | MACHINE_APM | MACHINE_ACPI, + .ram = { + .min = 8192, + .max = 131072, + .step = 8192 + }, + .nvrmask = 127, + .kbc_device = NULL, + .kbc_p1 = 0xff, + .gpio = 0xffffffff, + .gpio_acpi = 0xffffffff, + .device = NULL, + .fdc_device = NULL, + .sio_device = NULL, + .vid_device = NULL, + .snd_device = NULL, + .net_device = NULL + }, /* The BIOS does not send a single non-standard KBC command. */ - { "[i430VX] HP Brio 80xx", "brio80xx", MACHINE_TYPE_SOCKET7, CPU_PKG_SOCKET5_7, 0, 66666667, 66666667, 2200, 3520, 1.5, 3.0, MACHINE_PCI | MACHINE_BUS_PS2 | MACHINE_IDE_DUAL, 8192, 131072, 8192, 127, machine_at_brio80xx_init, NULL }, + { + .name = "[i430VX] HP Brio 80xx", + .internal_name = "brio80xx", + .type = MACHINE_TYPE_SOCKET7, + .chipset = MACHINE_CHIPSET_INTEL_430VX, + .init = machine_at_brio80xx_init, + .p1_handler = NULL, + .gpio_handler = NULL, + .available_flag = MACHINE_AVAILABLE, + .gpio_acpi_handler = NULL, + .cpu = { + .package = CPU_PKG_SOCKET5_7, + .block = CPU_BLOCK_NONE, + .min_bus = 66666667, + .max_bus = 66666667, + .min_voltage = 2200, + .max_voltage = 3520, + .min_multi = 1.5, + .max_multi = 3.0 + }, + .bus_flags = MACHINE_PS2_PCI, + .flags = MACHINE_IDE_DUAL | MACHINE_APM | MACHINE_ACPI, + .ram = { + .min = 8192, + .max = 131072, + .step = 8192 + }, + .nvrmask = 127, + .kbc_device = NULL, + .kbc_p1 = 0xff, + .gpio = 0xffffffff, + .gpio_acpi = 0xffffffff, + .device = NULL, + .fdc_device = NULL, + .sio_device = NULL, + .vid_device = NULL, + .snd_device = NULL, + .net_device = NULL + }, /* According to tests from real hardware: This has AMI MegaKey KBC firmware on the PC87306 Super I/O chip, command 0xA1 returns '5'. Command 0xA0 copyright string: (C)1994 AMI . */ - { "[i430VX] Packard Bell PB680", "pb680", MACHINE_TYPE_SOCKET7, CPU_PKG_SOCKET5_7, 0, 50000000, 66666667, 2800, 3520, 1.5, 3.0, MACHINE_PCI | MACHINE_BUS_PS2 | MACHINE_IDE_DUAL, 8192, 131072, 8192, 127, machine_at_pb680_init, NULL }, + { + .name = "[i430VX] Packard Bell PB680", + .internal_name = "pb680", + .type = MACHINE_TYPE_SOCKET7, + .chipset = MACHINE_CHIPSET_INTEL_430VX, + .init = machine_at_pb680_init, + .p1_handler = NULL, + .gpio_handler = NULL, + .available_flag = MACHINE_AVAILABLE, + .gpio_acpi_handler = NULL, + .cpu = { + .package = CPU_PKG_SOCKET5_7, + .block = CPU_BLOCK_NONE, + .min_bus = 50000000, + .max_bus = 66666667, + .min_voltage = 2800, + .max_voltage = 3520, + .min_multi = 1.5, + .max_multi = 3.0 + }, + .bus_flags = MACHINE_PS2_PCI, + .flags = MACHINE_VIDEO | MACHINE_IDE_DUAL | MACHINE_APM | MACHINE_ACPI, + .ram = { + .min = 8192, + .max = 131072, + .step = 8192 + }, + .nvrmask = 255, + .kbc_device = NULL, + .kbc_p1 = 0xff, + .gpio = 0xffffffff, + .gpio_acpi = 0xffffffff, + .device = NULL, + .fdc_device = NULL, + .sio_device = NULL, + .vid_device = &s3_phoenix_trio64vplus_onboard_pci_device, + .snd_device = NULL, + .net_device = NULL + }, + /* This machine has Phoenix MultiKey/42i KBC */ + { + .name = "[i430VX] Packard Bell PB810", + .internal_name = "pb810", + .type = MACHINE_TYPE_SOCKET7, + .chipset = MACHINE_CHIPSET_INTEL_430VX, + .init = machine_at_pb810_init, + .p1_handler = NULL, + .gpio_handler = NULL, + .available_flag = MACHINE_AVAILABLE, + .gpio_acpi_handler = NULL, + .cpu = { + .package = CPU_PKG_SOCKET5_7, + .block = CPU_BLOCK_NONE, + .min_bus = 50000000, + .max_bus = 66666667, + .min_voltage = 2500, + .max_voltage = 3520, + .min_multi = 1.5, + .max_multi = 3.0 + }, + .bus_flags = MACHINE_PS2_PCI, + .flags = MACHINE_IDE_DUAL | MACHINE_SOUND | MACHINE_APM | MACHINE_ACPI, + .ram = { + .min = 8192, + .max = 131072, + .step = 8192 + }, + .nvrmask = 127, + .kbc_device = NULL, + .kbc_p1 = 0xff, + .gpio = 0xffffffff, + .gpio_acpi = 0xffffffff, + .device = NULL, + .fdc_device = NULL, + .sio_device = NULL, + .vid_device = NULL, + .snd_device = NULL, + .net_device = NULL + }, /* This has the AMIKey 'H' firmware, possibly AMIKey-2. Photos show it with a BestKey, so it likely clones the behavior of AMIKey 'H'. */ - { "[i430VX] PC Partner MB520N", "mb520n", MACHINE_TYPE_SOCKET7, CPU_PKG_SOCKET5_7, 0, 50000000, 66666667, 2600, 3520, 1.5, 3.0, MACHINE_PCI | MACHINE_BUS_PS2 | MACHINE_IDE_DUAL, 8192, 131072, 8192, 127, machine_at_mb520n_init, NULL }, + { + .name = "[i430VX] PC Partner MB520N", + .internal_name = "mb520n", + .type = MACHINE_TYPE_SOCKET7, + .chipset = MACHINE_CHIPSET_INTEL_430VX, + .init = machine_at_mb520n_init, + .p1_handler = NULL, + .gpio_handler = NULL, + .available_flag = MACHINE_AVAILABLE, + .gpio_acpi_handler = NULL, + .cpu = { + .package = CPU_PKG_SOCKET5_7, + .block = CPU_BLOCK_NONE, + .min_bus = 50000000, + .max_bus = 66666667, + .min_voltage = 2600, + .max_voltage = 3520, + .min_multi = 1.5, + .max_multi = 3.0 + }, + .bus_flags = MACHINE_PS2_PCI, + .flags = MACHINE_IDE_DUAL | MACHINE_APM | MACHINE_ACPI, + .ram = { + .min = 8192, + .max = 131072, + .step = 8192 + }, + .nvrmask = 127, + .kbc_device = NULL, + .kbc_p1 = 0xff, + .gpio = 0xffffffff, + .gpio_acpi = 0xffffffff, + .device = NULL, + .fdc_device = NULL, + .sio_device = NULL, + .vid_device = NULL, + .snd_device = NULL, + .net_device = NULL + }, /* This has a Holtek KBC and the BIOS does not send a single non-standard KBC command, so it must be an ASIC that clones the standard IBM PS/2 KBC. */ - { "[i430VX] Shuttle HOT-557", "430vx", MACHINE_TYPE_SOCKET7, CPU_PKG_SOCKET5_7, 0, 50000000, 66666667, 2500, 3520, 1.5, 3.0, MACHINE_PCI | MACHINE_BUS_PS2 | MACHINE_IDE_DUAL | MACHINE_GAMEPORT, 8192, 131072, 8192, 127, machine_at_i430vx_init, NULL }, + { + .name = "[i430VX] Shuttle HOT-557", + .internal_name = "430vx", + .type = MACHINE_TYPE_SOCKET7, + .chipset = MACHINE_CHIPSET_INTEL_430VX, + .init = machine_at_i430vx_init, + .p1_handler = NULL, + .gpio_handler = NULL, + .available_flag = MACHINE_AVAILABLE, + .gpio_acpi_handler = NULL, + .cpu = { + .package = CPU_PKG_SOCKET5_7, + .block = CPU_BLOCK_NONE, + .min_bus = 50000000, + .max_bus = 66666667, + .min_voltage = 2500, + .max_voltage = 3520, + .min_multi = 1.5, + .max_multi = 3.0 + }, + .bus_flags = MACHINE_PS2_PCI, + .flags = MACHINE_IDE_DUAL | MACHINE_GAMEPORT | MACHINE_APM | MACHINE_ACPI, + .ram = { + .min = 8192, + .max = 131072, + .step = 8192 + }, + .nvrmask = 127, + .kbc_device = NULL, + .kbc_p1 = 0xff, + .gpio = 0xffffffff, + .gpio_acpi = 0xffffffff, + .device = NULL, + .fdc_device = NULL, + .sio_device = NULL, + .vid_device = NULL, + .snd_device = NULL, + .net_device = NULL + }, /* 430TX */ /* The BIOS sends KBC command B8, CA, and CB, so it has an AMI KBC firmware. */ - { "[i430TX] ADLink NuPRO-592", "nupro592", MACHINE_TYPE_SOCKET7, CPU_PKG_SOCKET5_7, 0, 66666667, 66666667, 1900, 2800, 1.5, 5.5, MACHINE_PCI | MACHINE_BUS_PS2 | MACHINE_IDE_DUAL, 8192, 262144, 8192, 255, machine_at_nupro592_init, NULL }, + { + .name = "[i430TX] ADLink NuPRO-592", + .internal_name = "nupro592", + .type = MACHINE_TYPE_SOCKET7, + .chipset = MACHINE_CHIPSET_INTEL_430TX, + .init = machine_at_nupro592_init, + .p1_handler = NULL, + .gpio_handler = NULL, + .available_flag = MACHINE_AVAILABLE, + .gpio_acpi_handler = NULL, + .cpu = { + .package = CPU_PKG_SOCKET5_7, + .block = CPU_BLOCK_NONE, + .min_bus = 66666667, + .max_bus = 66666667, + .min_voltage = 1900, + .max_voltage = 2800, + .min_multi = 1.5, + .max_multi = 5.5 + }, + .bus_flags = MACHINE_PS2_PCI, + .flags = MACHINE_IDE_DUAL | MACHINE_APM | MACHINE_ACPI, + .ram = { + .min = 8192, + .max = 262144, + .step = 8192 + }, + .nvrmask = 255, + .kbc_device = NULL, + .kbc_p1 = 0xff, + .gpio = 0xffffffff, + .gpio_acpi = 0xffffffff, + .device = NULL, + .fdc_device = NULL, + .sio_device = NULL, + .vid_device = NULL, + .snd_device = NULL, + .net_device = NULL + }, /* This has the AMIKey KBC firmware, which is an updated 'F' type (YM430TX is based on the TX97). */ - { "[i430TX] ASUS TX97", "tx97", MACHINE_TYPE_SOCKET7, CPU_PKG_SOCKET5_7, 0, 50000000, 75000000, 2500, 3520, 1.5, 3.0, MACHINE_PCI | MACHINE_BUS_PS2 | MACHINE_IDE_DUAL, 8192, 262144, 8192, 255, machine_at_tx97_init, NULL }, -#if defined(DEV_BRANCH) && defined(NO_SIO) + { + .name = "[i430TX] ASUS TX97", + .internal_name = "tx97", + .type = MACHINE_TYPE_SOCKET7, + .chipset = MACHINE_CHIPSET_INTEL_430TX, + .init = machine_at_tx97_init, + .p1_handler = NULL, + .gpio_handler = NULL, + .available_flag = MACHINE_AVAILABLE, + .gpio_acpi_handler = NULL, + .cpu = { + .package = CPU_PKG_SOCKET5_7, + .block = CPU_BLOCK_NONE, + .min_bus = 50000000, + .max_bus = 75000000, + .min_voltage = 2500, + .max_voltage = 3520, + .min_multi = 1.5, + .max_multi = 3.0 + }, + .bus_flags = MACHINE_PS2_PCI, + .flags = MACHINE_IDE_DUAL | MACHINE_APM | MACHINE_ACPI, + .ram = { + .min = 8192, + .max = 262144, + .step = 8192 + }, + .nvrmask = 255, + .kbc_device = NULL, + .kbc_p1 = 0xff, + .gpio = 0xffffffff, + .gpio_acpi = 0xffffffff, + .device = NULL, + .fdc_device = NULL, + .sio_device = NULL, + .vid_device = NULL, + .snd_device = NULL, + .net_device = NULL + }, +#if defined(DEV_BRANCH) && defined(USE_AN430TX) /* This has the Phoenix MultiKey KBC firmware. */ - { "[i430TX] Intel AN430TX", "an430tx", MACHINE_TYPE_SOCKET7, CPU_PKG_SOCKET5_7, 0, 60000000, 66666667, 2800, 3520, 1.5, 3.0, MACHINE_PCI | MACHINE_BUS_PS2 | MACHINE_IDE_DUAL, 8192, 262144, 8192, 255, machine_at_an430tx_init, NULL }, -#endif + { + .name = "[i430TX] Intel AN430TX", + .internal_name = "an430tx", + .type = MACHINE_TYPE_SOCKET7, + .chipset = MACHINE_CHIPSET_INTEL_430TX, + .init = machine_at_an430tx_init, + .p1_handler = NULL, + .gpio_handler = NULL, + .available_flag = MACHINE_AVAILABLE, + .gpio_acpi_handler = NULL, + .cpu = { + .package = CPU_PKG_SOCKET5_7, + .block = CPU_BLOCK_NONE, + .min_bus = 60000000, + .max_bus = 66666667, + .min_voltage = 2800, + .max_voltage = 3520, + .min_multi = 1.5, + .max_multi = 3.0 + }, + .bus_flags = MACHINE_PS2_PCI, + .flags = MACHINE_IDE_DUAL | MACHINE_APM | MACHINE_ACPI, + .ram = { + .min = 8192, + .max = 262144, + .step = 8192 + }, + .nvrmask = 255, + .kbc_device = NULL, + .kbc_p1 = 0xff, + .gpio = 0xffffffff, + .gpio_acpi = 0xffffffff, + .device = NULL, + .fdc_device = NULL, + .sio_device = NULL, + .vid_device = NULL, + .snd_device = NULL, + .net_device = NULL + }, +#endif /* defined(DEV_BRANCH) && defined(USE_AN430TX) */ /* This has the AMIKey KBC firmware, which is an updated 'F' type. */ - { "[i430TX] Intel YM430TX", "ym430tx", MACHINE_TYPE_SOCKET7, CPU_PKG_SOCKET5_7, 0, 60000000, 66666667, 2800, 3520, 1.5, 3.0, MACHINE_PCI | MACHINE_BUS_PS2 | MACHINE_IDE_DUAL, 8192, 262144, 8192, 255, machine_at_ym430tx_init, NULL }, + { + .name = "[i430TX] Intel YM430TX", + .internal_name = "ym430tx", + .type = MACHINE_TYPE_SOCKET7, + .chipset = MACHINE_CHIPSET_INTEL_430TX, + .init = machine_at_ym430tx_init, + .p1_handler = NULL, + .gpio_handler = NULL, + .available_flag = MACHINE_AVAILABLE, + .gpio_acpi_handler = NULL, + .cpu = { + .package = CPU_PKG_SOCKET5_7, + .block = CPU_BLOCK_NONE, + .min_bus = 60000000, + .max_bus = 66666667, + .min_voltage = 2800, + .max_voltage = 3520, + .min_multi = 1.5, + .max_multi = 3.0 + }, + .bus_flags = MACHINE_PS2_PCI, + .flags = MACHINE_IDE_DUAL | MACHINE_APM | MACHINE_ACPI, + .ram = { + .min = 8192, + .max = 262144, + .step = 8192 + }, + .nvrmask = 255, + .kbc_device = NULL, + .kbc_p1 = 0xff, + .gpio = 0xffffffff, + .gpio_acpi = 0xffffffff, + .device = NULL, + .fdc_device = NULL, + .sio_device = NULL, + .vid_device = NULL, + .snd_device = NULL, + .net_device = NULL + }, /* The BIOS sends KBC command BB and expects it to output a byte, which is AMI KBC behavior. */ - { "[i430TX] PC Partner MB540N", "mb540n", MACHINE_TYPE_SOCKET7, CPU_PKG_SOCKET5_7, 0, 60000000, 66666667, 2700, 3520, 1.5, 3.0, MACHINE_PCI | MACHINE_BUS_PS2 | MACHINE_IDE_DUAL, 8192, 262144, 8192, 255, machine_at_mb540n_init, NULL }, + { + .name = "[i430TX] PC Partner MB540N", + .internal_name = "mb540n", + .type = MACHINE_TYPE_SOCKET7, + .chipset = MACHINE_CHIPSET_INTEL_430TX, + .init = machine_at_mb540n_init, + .p1_handler = NULL, + .gpio_handler = NULL, + .available_flag = MACHINE_AVAILABLE, + .gpio_acpi_handler = NULL, + .cpu = { + .package = CPU_PKG_SOCKET5_7, + .block = CPU_BLOCK_NONE, + .min_bus = 60000000, + .max_bus = 66666667, + .min_voltage = 2700, + .max_voltage = 3520, + .min_multi = 1.5, + .max_multi = 3.0 + }, + .bus_flags = MACHINE_PS2_PCI, + .flags = MACHINE_IDE_DUAL | MACHINE_APM | MACHINE_ACPI, + .ram = { + .min = 8192, + .max = 262144, + .step = 8192 + }, + .nvrmask = 255, + .kbc_device = NULL, + .kbc_p1 = 0xff, + .gpio = 0xffffffff, + .gpio_acpi = 0xffffffff, + .device = NULL, + .fdc_device = NULL, + .sio_device = NULL, + .vid_device = NULL, + .snd_device = NULL, + .net_device = NULL + }, + /* Award BIOS, PS2, EDO, SDRAM, 4 PCI, 4 ISA, VIA VT82C42N KBC */ + { + .name = "[i430TX] Soltek SL-56A5", + .internal_name = "56a5", + .type = MACHINE_TYPE_SOCKET7, + .chipset = MACHINE_CHIPSET_INTEL_430TX, + .init = machine_at_56a5_init, + .p1_handler = NULL, + .gpio_handler = NULL, + .available_flag = MACHINE_AVAILABLE, + .gpio_acpi_handler = NULL, + .cpu = { + .package = CPU_PKG_SOCKET5_7, + .block = CPU_BLOCK_NONE, + .min_bus = 55000000, + .max_bus = 75000000, + .min_voltage = 2800, + .max_voltage = 3520, + .min_multi = 1.5, + .max_multi = 5.5 + }, + .bus_flags = MACHINE_PS2_PCI, + .flags = MACHINE_IDE_DUAL | MACHINE_APM | MACHINE_ACPI, + .ram = { + .min = 8192, + .max = 262144, + .step = 8192 + }, + .nvrmask = 255, + .kbc_device = NULL, + .kbc_p1 = 0xff, + .gpio = 0xffffffff, + .gpio_acpi = 0xffffffff, + .device = NULL, + .fdc_device = NULL, + .sio_device = NULL, + .vid_device = NULL, + .snd_device = NULL, + .net_device = NULL + }, /* [TEST] Has AMIKey 'H' KBC firmware. */ - { "[i430TX] Supermicro P5MMS98", "p5mms98", MACHINE_TYPE_SOCKET7, CPU_PKG_SOCKET5_7, 0, 50000000, 66666667, 2100, 3520, 1.5, 3.0, MACHINE_PCI | MACHINE_BUS_PS2 | MACHINE_IDE_DUAL, 8192, 262144, 8192, 255, machine_at_p5mms98_init, NULL }, + { + .name = "[i430TX] Supermicro P5MMS98", + .internal_name = "p5mms98", + .type = MACHINE_TYPE_SOCKET7, + .chipset = MACHINE_CHIPSET_INTEL_430TX, + .init = machine_at_p5mms98_init, + .p1_handler = NULL, + .gpio_handler = NULL, + .available_flag = MACHINE_AVAILABLE, + .gpio_acpi_handler = NULL, + .cpu = { + .package = CPU_PKG_SOCKET5_7, + .block = CPU_BLOCK_NONE, + .min_bus = 50000000, + .max_bus = 66666667, + .min_voltage = 2100, + .max_voltage = 3520, + .min_multi = 1.5, + .max_multi = 3.0 + }, + .bus_flags = MACHINE_PS2_PCI, + .flags = MACHINE_IDE_DUAL | MACHINE_APM | MACHINE_ACPI, + .ram = { + .min = 8192, + .max = 262144, + .step = 8192 + }, + .nvrmask = 255, + .kbc_device = NULL, + .kbc_p1 = 0xff, + .gpio = 0xffffffff, + .gpio_acpi = 0xffffffff, + .device = NULL, + .fdc_device = NULL, + .sio_device = NULL, + .vid_device = NULL, + .snd_device = NULL, + .net_device = NULL + }, /* Apollo VPX */ /* Has the VIA VT82C586B southbridge with on-chip KBC identical to the VIA VT82C42N. */ - { "[VIA VPX] FIC VA-502", "ficva502", MACHINE_TYPE_SOCKET7, CPU_PKG_SOCKET5_7, 0, 50000000, 75000000, 2800, 3520, 1.5, 3.0, MACHINE_PCI | MACHINE_BUS_PS2 | MACHINE_IDE_DUAL, 8192, 524288, 8192, 127, machine_at_ficva502_init, NULL }, + { + .name = "[VIA VPX] FIC VA-502", + .internal_name = "ficva502", + .type = MACHINE_TYPE_SOCKET7, + .chipset = MACHINE_CHIPSET_VIA_APOLLO_VPX, + .init = machine_at_ficva502_init, + .p1_handler = NULL, + .gpio_handler = NULL, + .available_flag = MACHINE_AVAILABLE, + .gpio_acpi_handler = NULL, + .cpu = { + .package = CPU_PKG_SOCKET5_7, + .block = CPU_BLOCK_NONE, + .min_bus = 50000000, + .max_bus = 75000000, + .min_voltage = 2800, + .max_voltage = 3520, + .min_multi = 1.5, + .max_multi = 3.0 + }, + .bus_flags = MACHINE_PS2_PCI, + .flags = MACHINE_IDE_DUAL | MACHINE_APM | MACHINE_ACPI, + .ram = { + .min = 8192, + .max = 524288, + .step = 8192 + }, + .nvrmask = 127, + .kbc_device = NULL, + .kbc_p1 = 0xff, + .gpio = 0xffffffff, + .gpio_acpi = 0xffffffff, + .device = NULL, + .fdc_device = NULL, + .sio_device = NULL, + .vid_device = NULL, + .snd_device = NULL, + .net_device = NULL + }, /* Apollo VP3 */ /* Has the VIA VT82C586B southbridge with on-chip KBC identical to the VIA VT82C42N. */ - { "[VIA VP3] FIC PA-2012", "ficpa2012", MACHINE_TYPE_SOCKET7, CPU_PKG_SOCKET5_7, 0, 55000000, 75000000, 2100, 3520, 1.5, 5.5, MACHINE_AGP | MACHINE_BUS_PS2 | MACHINE_IDE_DUAL, 8192,1048576, 8192, 127, machine_at_ficpa2012_init, NULL }, + { + .name = "[VIA VP3] FIC PA-2012", + .internal_name = "ficpa2012", + .type = MACHINE_TYPE_SOCKET7, + .chipset = MACHINE_CHIPSET_VIA_APOLLO_VP3, + .init = machine_at_ficpa2012_init, + .p1_handler = NULL, + .gpio_handler = NULL, + .available_flag = MACHINE_AVAILABLE, + .gpio_acpi_handler = NULL, + .cpu = { + .package = CPU_PKG_SOCKET5_7, + .block = CPU_BLOCK_NONE, + .min_bus = 55000000, + .max_bus = 75000000, + .min_voltage = 2100, + .max_voltage = 3520, + .min_multi = 1.5, + .max_multi = 5.5 + }, + .bus_flags = MACHINE_PS2_AGP, + .flags = MACHINE_IDE_DUAL | MACHINE_APM | MACHINE_ACPI, + .ram = { + .min = 8192, + .max = 1048576, + .step = 8192 + }, + .nvrmask = 127, + .kbc_device = NULL, + .kbc_p1 = 0xff, + .gpio = 0xffffffff, + .gpio_acpi = 0xffffffff, + .device = NULL, + .fdc_device = NULL, + .sio_device = NULL, + .vid_device = NULL, + .snd_device = NULL, + .net_device = NULL + }, /* SiS 5571 */ /* Has the SiS 5571 chipset with on-chip KBC. */ - { "[SiS 5571] Rise R534F", "r534f", MACHINE_TYPE_SOCKET7, CPU_PKG_SOCKET5_7, 0, 55000000, 83333333, 2500, 3520, 1.5, 3.0, MACHINE_PCI | MACHINE_BUS_PS2 | MACHINE_IDE_DUAL, 8192, 393216, 8192, 127, machine_at_r534f_init, NULL }, + { + .name = "[SiS 5571] Rise R534F", + .internal_name = "r534f", + .type = MACHINE_TYPE_SOCKET7, + .chipset = MACHINE_CHIPSET_SIS_5571, + .init = machine_at_r534f_init, + .p1_handler = NULL, + .gpio_handler = NULL, + .available_flag = MACHINE_AVAILABLE, + .gpio_acpi_handler = NULL, + .cpu = { + .package = CPU_PKG_SOCKET5_7, + .block = CPU_BLOCK_NONE, + .min_bus = 55000000, + .max_bus = 83333333, + .min_voltage = 2500, + .max_voltage = 3520, + .min_multi = 1.5, + .max_multi = 3.0 + }, + .bus_flags = MACHINE_PS2_PCI, + .flags = MACHINE_IDE_DUAL | MACHINE_APM | MACHINE_ACPI, + .ram = { + .min = 8192, + .max = 393216, + .step = 8192 + }, + .nvrmask = 127, + .kbc_device = NULL, + .kbc_p1 = 0xff, + .gpio = 0xffffffff, + .gpio_acpi = 0xffffffff, + .device = NULL, + .fdc_device = NULL, + .sio_device = NULL, + .vid_device = NULL, + .snd_device = NULL, + .net_device = NULL + }, /* Has the SiS 5571 chipset with on-chip KBC. */ - { "[SiS 5571] MSI MS-5146", "ms5146", MACHINE_TYPE_SOCKET7, CPU_PKG_SOCKET5_7, 0, 50000000, 75000000, 2800, 3520, 1.5, 3.0, MACHINE_PCI | MACHINE_BUS_PS2 | MACHINE_IDE_DUAL, 8192, 262144, 8192, 127, machine_at_ms5146_init, NULL }, + { + .name = "[SiS 5571] MSI MS-5146", + .internal_name = "ms5146", + .type = MACHINE_TYPE_SOCKET7, + .chipset = MACHINE_CHIPSET_SIS_5571, + .init = machine_at_ms5146_init, + .p1_handler = NULL, + .gpio_handler = NULL, + .available_flag = MACHINE_AVAILABLE, + .gpio_acpi_handler = NULL, + .cpu = { + .package = CPU_PKG_SOCKET5_7, + .block = CPU_BLOCK_NONE, + .min_bus = 50000000, + .max_bus = 75000000, + .min_voltage = 2800, + .max_voltage = 3520, + .min_multi = 1.5, + .max_multi = 3.0 + }, + .bus_flags = MACHINE_PS2_PCI, + .flags = MACHINE_IDE_DUAL | MACHINE_APM | MACHINE_ACPI, + .ram = { + .min = 8192, + .max = 262144, + .step = 8192 + }, + .nvrmask = 127, + .kbc_device = NULL, + .kbc_p1 = 0xff, + .gpio = 0xffffffff, + .gpio_acpi = 0xffffffff, + .device = NULL, + .fdc_device = NULL, + .sio_device = NULL, + .vid_device = NULL, + .snd_device = NULL, + .net_device = NULL + }, /* ALi ALADDiN IV+ */ /* Has the ALi M1543 southbridge with on-chip KBC. */ - { "[ALi ALADDiN IV+] PC Chips M560", "m560", MACHINE_TYPE_SOCKET7, CPU_PKG_SOCKET5_7, 0, 50000000, 83333333, 2500, 3520, 1.5, 3.0, MACHINE_PCI | MACHINE_BUS_PS2 | MACHINE_IDE_DUAL, 8192, 786432, 8192, 255, machine_at_m560_init, NULL }, + { + .name = "[ALi ALADDiN IV+] PC Chips M560", + .internal_name = "m560", + .type = MACHINE_TYPE_SOCKET7, + .chipset = MACHINE_CHIPSET_ALI_ALADDIN_IV_PLUS, + .init = machine_at_m560_init, + .p1_handler = NULL, + .gpio_handler = NULL, + .available_flag = MACHINE_AVAILABLE, + .gpio_acpi_handler = NULL, + .cpu = { + .package = CPU_PKG_SOCKET5_7, + .block = CPU_BLOCK_NONE, + .min_bus = 50000000, + .max_bus = 83333333, + .min_voltage = 2500, + .max_voltage = 3520, + .min_multi = 1.5, + .max_multi = 3.0 + }, + .bus_flags = MACHINE_PS2_PCI, + .flags = MACHINE_IDE_DUAL | MACHINE_APM | MACHINE_ACPI, + .ram = { + .min = 8192, + .max = 786432, + .step = 8192 + }, + .nvrmask = 255, + .kbc_device = NULL, + .kbc_p1 = 0xff, + .gpio = 0xffffffff, + .gpio_acpi = 0xffffffff, + .device = NULL, + .fdc_device = NULL, + .sio_device = NULL, + .vid_device = NULL, + .snd_device = NULL, + .net_device = NULL + }, /* Has the ALi M1543 southbridge with on-chip KBC. */ - { "[ALi ALADDiN IV+] MSI MS-5164", "ms5164", MACHINE_TYPE_SOCKET7, CPU_PKG_SOCKET5_7, 0, 60000000, 83333333, 2100, 3520, 1.5, 3.0, MACHINE_PCI | MACHINE_BUS_PS2 | MACHINE_IDE_DUAL, 8192,1048576, 8192, 255, machine_at_ms5164_init, NULL }, + { + .name = "[ALi ALADDiN IV+] MSI MS-5164", + .internal_name = "ms5164", + .type = MACHINE_TYPE_SOCKET7, + .chipset = MACHINE_CHIPSET_ALI_ALADDIN_IV_PLUS, + .init = machine_at_ms5164_init, + .p1_handler = NULL, + .gpio_handler = NULL, + .available_flag = MACHINE_AVAILABLE, + .gpio_acpi_handler = NULL, + .cpu = { + .package = CPU_PKG_SOCKET5_7, + .block = CPU_BLOCK_NONE, + .min_bus = 60000000, + .max_bus = 83333333, + .min_voltage = 2100, + .max_voltage = 3520, + .min_multi = 1.5, + .max_multi = 3.0 + }, + .bus_flags = MACHINE_PS2_PCI, + .flags = MACHINE_IDE_DUAL | MACHINE_APM | MACHINE_ACPI, + .ram = { + .min = 8192, + .max = 1048576, + .step = 8192 + }, + .nvrmask = 255, + .kbc_device = NULL, + .kbc_p1 = 0xff, + .gpio = 0xffffffff, + .gpio_acpi = 0xffffffff, + .device = NULL, + .fdc_device = NULL, + .sio_device = NULL, + .vid_device = NULL, + .snd_device = NULL, + .net_device = NULL + }, /* Super Socket 7 machines */ /* ALi ALADDiN V */ /* Has the ALi M1543C southbridge with on-chip KBC. */ - { "[ALi ALADDiN V] ASUS P5A", "p5a", MACHINE_TYPE_SOCKETS7, CPU_PKG_SOCKET5_7, 0, 60000000, 120000000, 2000, 3520, 1.5, 5.5, MACHINE_AGP | MACHINE_BUS_PS2 | MACHINE_IDE_DUAL, 1024,1572864, 8192, 255, machine_at_p5a_init, NULL }, + { + .name = "[ALi ALADDiN V] ASUS P5A", + .internal_name = "p5a", + .type = MACHINE_TYPE_SOCKETS7, + .chipset = MACHINE_CHIPSET_ALI_ALADDIN_V, + .init = machine_at_p5a_init, + .p1_handler = NULL, + .gpio_handler = NULL, + .available_flag = MACHINE_AVAILABLE, + .gpio_acpi_handler = NULL, + .cpu = { + .package = CPU_PKG_SOCKET5_7, + .block = CPU_BLOCK_NONE, + .min_bus = 60000000, + .max_bus = 120000000, + .min_voltage = 2000, + .max_voltage = 3520, + .min_multi = 1.5, + .max_multi = 5.5 + }, + .bus_flags = MACHINE_PS2_AGP, + .flags = MACHINE_IDE_DUAL | MACHINE_APM | MACHINE_ACPI, + .ram = { + .min = 1024, + .max = 1572864, + .step = 8192 + }, + .nvrmask = 255, + .kbc_device = NULL, + .kbc_p1 = 0xff, + .gpio = 0xffffffff, + .gpio_acpi = 0xffffffff, + .device = NULL, + .fdc_device = NULL, + .sio_device = NULL, + .vid_device = NULL, + .snd_device = NULL, + .net_device = NULL + }, /* Is the exact same as the Matsonic MS6260S. Has the ALi M1543C southbridge with on-chip KBC. */ - { "[ALi ALADDiN V] PC Chips M579", "m579", MACHINE_TYPE_SOCKETS7, CPU_PKG_SOCKET5_7, 0, 66666667, 100000000, 2000, 3520, 1.5, 5.5, MACHINE_AGP | MACHINE_BUS_PS2 | MACHINE_IDE_DUAL, 1024,1572864, 8192, 255, machine_at_m579_init, NULL }, + { + .name = "[ALi ALADDiN V] PC Chips M579", + .internal_name = "m579", + .type = MACHINE_TYPE_SOCKETS7, + .chipset = MACHINE_CHIPSET_ALI_ALADDIN_V, + .init = machine_at_m579_init, + .p1_handler = NULL, + .gpio_handler = NULL, + .available_flag = MACHINE_AVAILABLE, + .gpio_acpi_handler = NULL, + .cpu = { + .package = CPU_PKG_SOCKET5_7, + .block = CPU_BLOCK_NONE, + .min_bus = 66666667, + .max_bus = 100000000, + .min_voltage = 2000, + .max_voltage = 3520, + .min_multi = 1.5, + .max_multi = 5.5 + }, + .bus_flags = MACHINE_PS2_AGP, + .flags = MACHINE_IDE_DUAL | MACHINE_APM | MACHINE_ACPI, + .ram = { + .min = 1024, + .max = 1572864, + .step = 8192 + }, + .nvrmask = 255, + .kbc_device = NULL, + .kbc_p1 = 0xff, + .gpio = 0xffffffff, + .gpio_acpi = 0xffffffff, + .device = NULL, + .fdc_device = NULL, + .sio_device = NULL, + .vid_device = NULL, + .snd_device = NULL, + .net_device = NULL + }, /* Has the ALi M1543C southbridge with on-chip KBC. */ - { "[ALi ALADDiN V] Gigabyte GA-5AA", "5aa", MACHINE_TYPE_SOCKETS7, CPU_PKG_SOCKET5_7, 0, 66666667, 140000000, 1300, 3520, 1.5, 5.5, MACHINE_AGP | MACHINE_BUS_PS2 | MACHINE_IDE_DUAL, 1024,1572864, 8192, 255, machine_at_5aa_init, NULL }, + { + .name = "[ALi ALADDiN V] Gigabyte GA-5AA", + .internal_name = "5aa", + .type = MACHINE_TYPE_SOCKETS7, + .chipset = MACHINE_CHIPSET_ALI_ALADDIN_V, + .init = machine_at_5aa_init, + .p1_handler = NULL, + .gpio_handler = NULL, + .available_flag = MACHINE_AVAILABLE, + .gpio_acpi_handler = NULL, + .cpu = { + .package = CPU_PKG_SOCKET5_7, + .block = CPU_BLOCK_NONE, + .min_bus = 66666667, + .max_bus = 140000000, + .min_voltage = 1300, + .max_voltage = 3520, + .min_multi = 1.5, + .max_multi = 5.5 + }, + .bus_flags = MACHINE_PS2_AGP, + .flags = MACHINE_IDE_DUAL | MACHINE_APM | MACHINE_ACPI, + .ram = { + .min = 1024, + .max = 1572864, + .step = 8192 + }, + .nvrmask = 255, + .kbc_device = NULL, + .kbc_p1 = 0xff, + .gpio = 0xffffffff, + .gpio_acpi = 0xffffffff, + .device = NULL, + .fdc_device = NULL, + .sio_device = NULL, + .vid_device = NULL, + .snd_device = NULL, + .net_device = NULL + }, /* Has the ALi M1543C southbridge with on-chip KBC. */ - { "[ALi ALADDiN V] Gigabyte GA-5AX", "5ax", MACHINE_TYPE_SOCKETS7, CPU_PKG_SOCKET5_7, 0, 66666667, 140000000, 1300, 3520, 1.5, 5.5, MACHINE_AGP | MACHINE_BUS_PS2 | MACHINE_IDE_DUAL, 1024,1572864, 8192, 255, machine_at_5ax_init, NULL }, + { + .name = "[ALi ALADDiN V] Gigabyte GA-5AX", + .internal_name = "5ax", + .type = MACHINE_TYPE_SOCKETS7, + .chipset = MACHINE_CHIPSET_ALI_ALADDIN_V, + .init = machine_at_5ax_init, + .p1_handler = NULL, + .gpio_handler = NULL, + .available_flag = MACHINE_AVAILABLE, + .gpio_acpi_handler = NULL, + .cpu = { + .package = CPU_PKG_SOCKET5_7, + .block = CPU_BLOCK_NONE, + .min_bus = 66666667, + .max_bus = 140000000, + .min_voltage = 1300, + .max_voltage = 3520, + .min_multi = 1.5, + .max_multi = 5.5 + }, + .bus_flags = MACHINE_PS2_AGP, + .flags = MACHINE_IDE_DUAL | MACHINE_APM | MACHINE_ACPI, + .ram = { + .min = 1024, + .max = 1572864, + .step = 8192 + }, + .nvrmask = 255, + .kbc_device = NULL, + .kbc_p1 = 0xff, + .gpio = 0xffffffff, + .gpio_acpi = 0xffffffff, + .device = NULL, + .fdc_device = NULL, + .sio_device = NULL, + .vid_device = NULL, + .snd_device = NULL, + .net_device = NULL + }, /* Apollo MVP3 */ /* Has the VIA VT82C586B southbridge with on-chip KBC identical to the VIA VT82C42N. */ - { "[VIA MVP3] AOpen AX59 Pro", "ax59pro", MACHINE_TYPE_SOCKETS7, CPU_PKG_SOCKET5_7, 0, 66666667, 124242424, 1300, 3520, 1.5, 5.5, MACHINE_AGP | MACHINE_BUS_PS2 | MACHINE_IDE_DUAL, 8192,1048576, 8192, 255, machine_at_ax59pro_init, NULL }, + { + .name = "[VIA MVP3] AOpen AX59 Pro", + .internal_name = "ax59pro", + .type = MACHINE_TYPE_SOCKETS7, + .chipset = MACHINE_CHIPSET_VIA_APOLLO_MVP3, + .init = machine_at_ax59pro_init, + .p1_handler = NULL, + .gpio_handler = NULL, + .available_flag = MACHINE_AVAILABLE, + .gpio_acpi_handler = NULL, + .cpu = { + .package = CPU_PKG_SOCKET5_7, + .block = CPU_BLOCK_NONE, + .min_bus = 66666667, + .max_bus = 124242424, + .min_voltage = 1300, + .max_voltage = 3520, + .min_multi = 1.5, + .max_multi = 5.5 + }, + .bus_flags = MACHINE_PS2_AGP, + .flags = MACHINE_IDE_DUAL | MACHINE_APM | MACHINE_ACPI, + .ram = { + .min = 8192, + .max = 1048576, + .step = 8192 + }, + .nvrmask = 255, + .kbc_device = NULL, + .kbc_p1 = 0xff, + .gpio = 0xffffffff, + .gpio_acpi = 0xffffffff, + .device = NULL, + .fdc_device = NULL, + .sio_device = NULL, + .vid_device = NULL, + .snd_device = NULL, + .net_device = NULL + }, /* Has the VIA VT82C586B southbridge with on-chip KBC identical to the VIA VT82C42N. */ - { "[VIA MVP3] FIC VA-503+", "ficva503p", MACHINE_TYPE_SOCKETS7, CPU_PKG_SOCKET5_7, 0, 66666667, 124242424, 2000, 3200, 1.5, 5.5, MACHINE_AGP | MACHINE_BUS_PS2 | MACHINE_IDE_DUAL, 8192,1048576, 8192, 255, machine_at_mvp3_init, NULL }, + { + .name = "[VIA MVP3] FIC VA-503+", + .internal_name = "ficva503p", + .type = MACHINE_TYPE_SOCKETS7, + .chipset = MACHINE_CHIPSET_VIA_APOLLO_MVP3, + .init = machine_at_mvp3_init, + .p1_handler = NULL, + .gpio_handler = NULL, + .available_flag = MACHINE_AVAILABLE, + .gpio_acpi_handler = NULL, + .cpu = { + .package = CPU_PKG_SOCKET5_7, + .block = CPU_BLOCK_NONE, + .min_bus = 66666667, + .max_bus = 124242424, + .min_voltage = 2000, + .max_voltage = 3200, + .min_multi = 1.5, + .max_multi = 5.5 + }, + .bus_flags = MACHINE_PS2_AGP, + .flags = MACHINE_IDE_DUAL | MACHINE_APM | MACHINE_ACPI, + .ram = { + .min = 8192, + .max = 1048576, + .step = 8192 + }, + .nvrmask = 255, + .kbc_device = NULL, + .kbc_p1 = 0xff, + .gpio = 0xffffffff, + .gpio_acpi = 0xffffffff, + .device = NULL, + .fdc_device = NULL, + .sio_device = NULL, + .vid_device = NULL, + .snd_device = NULL, + .net_device = NULL + }, /* Has the VIA VT82C686A southbridge with on-chip KBC identical to the VIA VT82C42N. */ - { "[VIA MVP3] FIC VA-503A", "ficva503a", MACHINE_TYPE_SOCKETS7, CPU_PKG_SOCKET5_7, 0, 66666667, 124242424, 1800, 3100, 1.5, 5.5, MACHINE_AGP | MACHINE_BUS_PS2 | MACHINE_BUS_AC97 | MACHINE_IDE_DUAL | MACHINE_SOUND, 8192, 786432, 8192, 255, machine_at_ficva503a_init, NULL }, + { + .name = "[VIA MVP3] FIC VA-503A", + .internal_name = "ficva503a", + .type = MACHINE_TYPE_SOCKETS7, + .chipset = MACHINE_CHIPSET_VIA_APOLLO_MVP3, + .init = machine_at_ficva503a_init, + .p1_handler = NULL, + .gpio_handler = NULL, + .available_flag = MACHINE_AVAILABLE, + .gpio_acpi_handler = NULL, + .cpu = { + .package = CPU_PKG_SOCKET5_7, + .block = CPU_BLOCK_NONE, + .min_bus = 66666667, + .max_bus = 124242424, + .min_voltage = 1800, + .max_voltage = 3100, + .min_multi = 1.5, + .max_multi = 5.5 + }, + .bus_flags = MACHINE_PS2_A97, + .flags = MACHINE_IDE_DUAL | MACHINE_SOUND | MACHINE_APM | MACHINE_ACPI, + .ram = { + .min = 8192, + .max = 786432, + .step = 8192 + }, + .nvrmask = 255, + .kbc_device = NULL, + .kbc_p1 = 0xff, + .gpio = 0xffffffff, + .gpio_acpi = 0xffffffff, + .device = NULL, + .fdc_device = NULL, + .sio_device = NULL, + .vid_device = NULL, + .snd_device = NULL, + .net_device = NULL + }, /* Has the VIA VT82C686A southbridge with on-chip KBC identical to the VIA VT82C42N. */ - { "[VIA MVP3] Soyo 5EMA PRO", "5emapro", MACHINE_TYPE_SOCKETS7, CPU_PKG_SOCKET5_7, 0, 66666667, 124242424, 2000, 3520, 1.5, 5.5, MACHINE_AGP | MACHINE_BUS_PS2 | MACHINE_IDE_DUAL, 8192, 786432, 8192, 255, machine_at_5emapro_init, NULL }, + { + .name = "[VIA MVP3] Soyo 5EMA PRO", + .internal_name = "5emapro", + .type = MACHINE_TYPE_SOCKETS7, + .chipset = MACHINE_CHIPSET_VIA_APOLLO_MVP3, + .init = machine_at_5emapro_init, + .p1_handler = NULL, + .gpio_handler = NULL, + .available_flag = MACHINE_AVAILABLE, + .gpio_acpi_handler = NULL, + .cpu = { + .package = CPU_PKG_SOCKET5_7, + .block = CPU_BLOCK_NONE, + .min_bus = 66666667, + .max_bus = 124242424, + .min_voltage = 2000, + .max_voltage = 3520, + .min_multi = 1.5, + .max_multi = 5.5 + }, + .bus_flags = MACHINE_PS2_AGP, + .flags = MACHINE_IDE_DUAL | MACHINE_APM | MACHINE_ACPI, + .ram = { + .min = 8192, + .max = 786432, + .step = 8192 + }, + .nvrmask = 255, + .kbc_device = NULL, + .kbc_p1 = 0xff, + .gpio = 0xffffffff, + .gpio_acpi = 0xffffffff, + .device = NULL, + .fdc_device = NULL, + .sio_device = NULL, + .vid_device = NULL, + .snd_device = NULL, + .net_device = NULL + }, /* Socket 8 machines */ /* 450KX */ /* This has an AMIKey-2, which is an updated version of type 'H'. */ - { "[i450KX] ASUS P/I-P6RP4", "p6rp4", MACHINE_TYPE_SOCKET8, CPU_PKG_SOCKET8, 0, 60000000, 66666667, 2100, 3500, 1.5, 8.0, MACHINE_PCI | MACHINE_BUS_PS2 | MACHINE_IDE_DUAL, 8192, 524288, 8192, 127, machine_at_p6rp4_init, NULL }, + { + .name = "[i450KX] ASUS P/I-P6RP4", + .internal_name = "p6rp4", + .type = MACHINE_TYPE_SOCKET8, + .chipset = MACHINE_CHIPSET_INTEL_450KX, + .init = machine_at_p6rp4_init, + .p1_handler = NULL, + .gpio_handler = NULL, + .available_flag = MACHINE_AVAILABLE, + .gpio_acpi_handler = NULL, + .cpu = { + .package = CPU_PKG_SOCKET8, + .block = CPU_BLOCK_NONE, + .min_bus = 60000000, + .max_bus = 66666667, + .min_voltage = 2100, + .max_voltage = 3500, + .min_multi = 1.5, + .max_multi = 8.0 + }, + .bus_flags = MACHINE_PS2_PCI, + .flags = MACHINE_IDE_DUAL | MACHINE_APM | MACHINE_ACPI, + .ram = { + .min = 8192, + .max = 524288, + .step = 8192 + }, + .nvrmask = 127, + .kbc_device = NULL, + .kbc_p1 = 0xff, + .gpio = 0xffffffff, + .gpio_acpi = 0xffffffff, + .device = NULL, + .fdc_device = NULL, + .sio_device = NULL, + .vid_device = NULL, + .snd_device = NULL, + .net_device = NULL + }, /* 440FX */ /* Has the SMC FDC73C935's on-chip KBC with Phoenix MultiKey firmware. */ - { "[i440FX] Acer V60N", "acerv60n", MACHINE_TYPE_SOCKET8, CPU_PKG_SOCKET8, 0, 60000000, 66666667, 2500, 3500, 1.5, 8.0, MACHINE_PCI | MACHINE_BUS_PS2 | MACHINE_IDE_DUAL, 8192, 524288, 8192, 127, machine_at_acerv60n_init, NULL }, + { + .name = "[i440FX] Acer V60N", + .internal_name = "acerv60n", + .type = MACHINE_TYPE_SOCKET8, + .chipset = MACHINE_CHIPSET_INTEL_440FX, + .init = machine_at_acerv60n_init, + .p1_handler = NULL, + .gpio_handler = NULL, + .available_flag = MACHINE_AVAILABLE, + .gpio_acpi_handler = NULL, + .cpu = { + .package = CPU_PKG_SOCKET8, + .block = CPU_BLOCK_NONE, + .min_bus = 60000000, + .max_bus = 66666667, + .min_voltage = 2500, + .max_voltage = 3500, + .min_multi = 1.5, + .max_multi = 8.0 + }, + .bus_flags = MACHINE_PS2_PCI, + .flags = MACHINE_IDE_DUAL | MACHINE_APM | MACHINE_ACPI, + .ram = { + .min = 8192, + .max = 524288, + .step = 8192 + }, + .nvrmask = 127, + .kbc_device = NULL, + .kbc_p1 = 0xff, + .gpio = 0xffffffff, + .gpio_acpi = 0xffffffff, + .device = NULL, + .fdc_device = NULL, + .sio_device = NULL, + .vid_device = NULL, + .snd_device = NULL, + .net_device = NULL + }, /* The base board has AMIKey-2 (updated 'H') KBC firmware. */ - { "[i440FX] ASUS P/I-P65UP5 (C-P6ND)", "p65up5_cp6nd", MACHINE_TYPE_SOCKET8, CPU_PKG_SOCKET8, 0, 60000000, 66666667, 2100, 3500, 1.5, 8.0, MACHINE_PCI | MACHINE_BUS_PS2 | MACHINE_IDE_DUAL, 8192,1048576, 8192, 127, machine_at_p65up5_cp6nd_init, NULL }, + { + .name = "[i440FX] ASUS P/I-P65UP5 (C-P6ND)", + .internal_name = "p65up5_cp6nd", + .type = MACHINE_TYPE_SOCKET8, + .chipset = MACHINE_CHIPSET_INTEL_440FX, + .init = machine_at_p65up5_cp6nd_init, + .p1_handler = NULL, + .gpio_handler = NULL, + .available_flag = MACHINE_AVAILABLE, + .gpio_acpi_handler = NULL, + .cpu = { + .package = CPU_PKG_SOCKET8, + .block = CPU_BLOCK_NONE, + .min_bus = 60000000, + .max_bus = 66666667, + .min_voltage = 2100, + .max_voltage = 3500, + .min_multi = 1.5, + .max_multi = 8.0 + }, + .bus_flags = MACHINE_PS2_PCI, + .flags = MACHINE_IDE_DUAL | MACHINE_APM | MACHINE_ACPI, + .ram = { + .min = 8192, + .max = 1048576, + .step = 8192 + }, + .nvrmask = 127, + .kbc_device = NULL, + .kbc_p1 = 0xff, + .gpio = 0xffffffff, + .gpio_acpi = 0xffffffff, + .device = NULL, + .fdc_device = NULL, + .sio_device = NULL, + .vid_device = NULL, + .snd_device = NULL, + .net_device = NULL + }, /* The MB-8600TTX has an AMIKey 'F' KBC firmware, so I'm going to assume so does the MB-8600TTC until someone can actually identify it. */ - { "[i440FX] Biostar MB-8600TTC", "8600ttc", MACHINE_TYPE_SOCKET8, CPU_PKG_SOCKET8, 0, 50000000, 66666667, 2900, 3300, 2.0, 5.5, MACHINE_PCI | MACHINE_BUS_PS2 | MACHINE_IDE_DUAL, 8192,1048576, 8192, 127, machine_at_8600ttc_init, NULL }, - { "[i440FX] Gigabyte GA-686NX", "686nx", MACHINE_TYPE_SOCKET8, CPU_PKG_SOCKET8, 0, 60000000, 66666667, 2100, 3500, 2.0, 5.5, MACHINE_PCI | MACHINE_BUS_PS2 | MACHINE_IDE_DUAL, 8192, 524288, 8192, 127, machine_at_686nx_init, NULL }, + { + .name = "[i440FX] Biostar MB-8600TTC", + .internal_name = "8600ttc", + .type = MACHINE_TYPE_SOCKET8, + .chipset = MACHINE_CHIPSET_INTEL_440FX, + .init = machine_at_8600ttc_init, + .p1_handler = NULL, + .gpio_handler = NULL, + .available_flag = MACHINE_AVAILABLE, + .gpio_acpi_handler = NULL, + .cpu = { + .package = CPU_PKG_SOCKET8, + .block = CPU_BLOCK_NONE, + .min_bus = 50000000, + .max_bus = 66666667, + .min_voltage = 2900, + .max_voltage = 3300, + .min_multi = 2.0, + .max_multi = 5.5 + }, + .bus_flags = MACHINE_PS2_PCI, + .flags = MACHINE_IDE_DUAL | MACHINE_APM | MACHINE_ACPI, + .ram = { + .min = 8192, + .max = 1048576, + .step = 8192 + }, + .nvrmask = 127, + .kbc_device = NULL, + .kbc_p1 = 0xff, + .gpio = 0xffffffff, + .gpio_acpi = 0xffffffff, + .device = NULL, + .fdc_device = NULL, + .sio_device = NULL, + .vid_device = NULL, + .snd_device = NULL, + .net_device = NULL + }, + { + .name = "[i440FX] Gigabyte GA-686NX", + .internal_name = "686nx", + .type = MACHINE_TYPE_SOCKET8, + .chipset = MACHINE_CHIPSET_INTEL_440FX, + .init = machine_at_686nx_init, + .p1_handler = NULL, + .gpio_handler = NULL, + .available_flag = MACHINE_AVAILABLE, + .gpio_acpi_handler = NULL, + .cpu = { + .package = CPU_PKG_SOCKET8, + .block = CPU_BLOCK_NONE, + .min_bus = 60000000, + .max_bus = 66666667, + .min_voltage = 2100, + .max_voltage = 3500, + .min_multi = 2.0, + .max_multi = 5.5 + }, + .bus_flags = MACHINE_PS2_PCI, + .flags = MACHINE_IDE_DUAL | MACHINE_APM | MACHINE_ACPI, + .ram = { + .min = 8192, + .max = 524288, + .step = 8192 + }, + .nvrmask = 127, + .kbc_device = NULL, + .kbc_p1 = 0xff, + .gpio = 0xffffffff, + .gpio_acpi = 0xffffffff, + .device = NULL, + .fdc_device = NULL, + .sio_device = NULL, + .vid_device = NULL, + .snd_device = NULL, + .net_device = NULL + }, /* According to tests from real hardware: This has AMI MegaKey KBC firmware on the PC87306 Super I/O chip, command 0xA1 returns '5'. Command 0xA0 copyright string: (C)1994 AMI . */ - { "[i440FX] Intel AP440FX", "ap440fx", MACHINE_TYPE_SOCKET8, CPU_PKG_SOCKET8, 0, 60000000, 66666667, 2100, 3500, 2.0, 3.5, MACHINE_PCI | MACHINE_BUS_PS2 | MACHINE_IDE_DUAL, 8192, 131072, 8192, 127, machine_at_ap440fx_init, NULL }, + { + .name = "[i440FX] Intel AP440FX", + .internal_name = "ap440fx", + .type = MACHINE_TYPE_SOCKET8, + .chipset = MACHINE_CHIPSET_INTEL_440FX, + .init = machine_at_ap440fx_init, + .p1_handler = NULL, + .gpio_handler = NULL, + .available_flag = MACHINE_AVAILABLE, + .gpio_acpi_handler = NULL, + .cpu = { + .package = CPU_PKG_SOCKET8, + .block = CPU_BLOCK_NONE, + .min_bus = 60000000, + .max_bus = 66666667, + .min_voltage = 2100, + .max_voltage = 3500, + .min_multi = 2.0, + .max_multi = 3.5 + }, + .bus_flags = MACHINE_PS2_PCI, + .flags = MACHINE_IDE_DUAL | MACHINE_APM | MACHINE_ACPI, + .ram = { + .min = 8192, + .max = 131072, + .step = 8192 + }, + .nvrmask = 127, + .kbc_device = NULL, + .kbc_p1 = 0xff, + .gpio = 0xffffffff, + .gpio_acpi = 0xffffffff, + .device = NULL, + .fdc_device = NULL, + .sio_device = NULL, + .vid_device = NULL, + .snd_device = NULL, + .net_device = NULL + }, /* According to tests from real hardware: This has AMI MegaKey KBC firmware on the PC87306 Super I/O chip, command 0xA1 returns '5'. Command 0xA0 copyright string: (C)1994 AMI . */ - { "[i440FX] Intel VS440FX", "vs440fx", MACHINE_TYPE_SOCKET8, CPU_PKG_SOCKET8, 0, 60000000, 66666667, 2100, 3500, 2.0, 3.5, MACHINE_PCI | MACHINE_BUS_PS2 | MACHINE_IDE_DUAL, 8192, 524288, 8192, 127, machine_at_vs440fx_init, NULL }, + { + .name = "[i440FX] Intel VS440FX", + .internal_name = "vs440fx", + .type = MACHINE_TYPE_SOCKET8, + .chipset = MACHINE_CHIPSET_INTEL_440FX, + .init = machine_at_vs440fx_init, + .p1_handler = NULL, + .gpio_handler = NULL, + .available_flag = MACHINE_AVAILABLE, + .gpio_acpi_handler = NULL, + .cpu = { + .package = CPU_PKG_SOCKET8, + .block = CPU_BLOCK_NONE, + .min_bus = 60000000, + .max_bus = 66666667, + .min_voltage = 2100, + .max_voltage = 3500, + .min_multi = 2.0, + .max_multi = 3.5 + }, + .bus_flags = MACHINE_PS2_PCI, + .flags = MACHINE_IDE_DUAL | MACHINE_APM | MACHINE_ACPI, + .ram = { + .min = 8192, + .max = 524288, + .step = 8192 + }, + .nvrmask = 127, + .kbc_device = NULL, + .kbc_p1 = 0xff, + .gpio = 0xffffffff, + .gpio_acpi = 0xffffffff, + .device = NULL, + .fdc_device = NULL, + .sio_device = NULL, + .vid_device = NULL, + .snd_device = NULL, + .net_device = NULL + }, /* Has the SMC FDC73C935's on-chip KBC with Phoenix MultiKey firmware. */ - { "[i440FX] Micronics M6Mi", "m6mi", MACHINE_TYPE_SOCKET8, CPU_PKG_SOCKET8, 0, 60000000, 66666667, 2900, 3300, 1.5, 8.0, MACHINE_PCI | MACHINE_BUS_PS2 | MACHINE_IDE_DUAL, 8192, 786432, 8192, 127, machine_at_m6mi_init, NULL }, + { + .name = "[i440FX] Micronics M6Mi", + .internal_name = "m6mi", + .type = MACHINE_TYPE_SOCKET8, + .chipset = MACHINE_CHIPSET_INTEL_440FX, + .init = machine_at_m6mi_init, + .p1_handler = NULL, + .gpio_handler = NULL, + .available_flag = MACHINE_AVAILABLE, + .gpio_acpi_handler = NULL, + .cpu = { + .package = CPU_PKG_SOCKET8, + .block = CPU_BLOCK_NONE, + .min_bus = 60000000, + .max_bus = 66666667, + .min_voltage = 2900, + .max_voltage = 3300, + .min_multi = 1.5, + .max_multi = 8.0 + }, + .bus_flags = MACHINE_PS2_PCI, + .flags = MACHINE_IDE_DUAL | MACHINE_APM | MACHINE_ACPI, + .ram = { + .min = 8192, + .max = 786432, + .step = 8192 + }, + .nvrmask = 127, + .kbc_device = NULL, + .kbc_p1 = 0xff, + .gpio = 0xffffffff, + .gpio_acpi = 0xffffffff, + .device = NULL, + .fdc_device = NULL, + .sio_device = NULL, + .vid_device = NULL, + .snd_device = NULL, + .net_device = NULL + }, /* I found a BIOS string of it that ends in -S, but it could be a typo for -5 (there's quite a few AMI BIOS strings around with typo'd KBC codes), so I'm going to give it an AMI MegaKey. */ - { "[i440FX] PC Partner MB600N", "mb600n", MACHINE_TYPE_SOCKET8, CPU_PKG_SOCKET8, 0, 60000000, 66666667, 2100, 3500, 1.5, 8.0, MACHINE_PCI | MACHINE_BUS_PS2 | MACHINE_IDE_DUAL, 8192, 524288, 8192, 127, machine_at_mb600n_init, NULL }, + { + .name = "[i440FX] PC Partner MB600N", + .internal_name = "mb600n", + .type = MACHINE_TYPE_SOCKET8, + .chipset = MACHINE_CHIPSET_INTEL_440FX, + .init = machine_at_mb600n_init, + .p1_handler = NULL, + .gpio_handler = NULL, + .available_flag = MACHINE_AVAILABLE, + .gpio_acpi_handler = NULL, + .cpu = { + .package = CPU_PKG_SOCKET8, + .block = CPU_BLOCK_NONE, + .min_bus = 60000000, + .max_bus = 66666667, + .min_voltage = 2100, + .max_voltage = 3500, + .min_multi = 1.5, + .max_multi = 8.0 + }, + .bus_flags = MACHINE_PS2_PCI, + .flags = MACHINE_IDE_DUAL | MACHINE_APM | MACHINE_ACPI, + .ram = { + .min = 8192, + .max = 524288, + .step = 8192 + }, + .nvrmask = 127, + .kbc_device = NULL, + .kbc_p1 = 0xff, + .gpio = 0xffffffff, + .gpio_acpi = 0xffffffff, + .device = NULL, + .fdc_device = NULL, + .sio_device = NULL, + .vid_device = NULL, + .snd_device = NULL, + .net_device = NULL + }, /* Slot 1 machines */ /* ALi ALADDiN V */ /* Has the ALi M1543C southbridge with on-chip KBC. */ - { "[ALi ALADDiN-PRO II] PC Chips M729", "m729", MACHINE_TYPE_SLOT1, CPU_PKG_SLOT1, 0, 66666667, 100000000, 1800, 3500, 1.5, 8.0, MACHINE_AGP | MACHINE_BUS_PS2 | MACHINE_IDE_DUAL, 1024,1572864, 8192, 255, machine_at_m729_init, NULL }, + { + .name = "[ALi ALADDiN-PRO II] PC Chips M729", + .internal_name = "m729", + .type = MACHINE_TYPE_SLOT1, + .chipset = MACHINE_CHIPSET_ALI_ALADDIN_PRO_II, + .init = machine_at_m729_init, + .p1_handler = NULL, + .gpio_handler = NULL, + .available_flag = MACHINE_AVAILABLE, + .gpio_acpi_handler = NULL, + .cpu = { + .package = CPU_PKG_SLOT1, + .block = CPU_BLOCK_NONE, + .min_bus = 66666667, + .max_bus = 100000000, + .min_voltage = 1800, + .max_voltage = 3500, + .min_multi = 1.5, + .max_multi = 8.0 + }, + .bus_flags = MACHINE_PS2_AGP, + .flags = MACHINE_IDE_DUAL | MACHINE_APM | MACHINE_ACPI, + .ram = { + .min = 1024, + .max = 1572864, + .step = 8192 + }, + .nvrmask = 255, + .kbc_device = NULL, + .kbc_p1 = 0xff, + .gpio = 0xffffffff, + .gpio_acpi = 0xffffffff, + .device = NULL, + .fdc_device = NULL, + .sio_device = NULL, + .vid_device = NULL, + .snd_device = NULL, + .net_device = NULL + }, /* 440FX */ /* The base board has AMIKey-2 (updated 'H') KBC firmware. */ - { "[i440FX] ASUS P/I-P65UP5 (C-PKND)", "p65up5_cpknd", MACHINE_TYPE_SLOT1, CPU_PKG_SLOT1, 0, 50000000, 66666667, 1800, 3500, 1.5, 8.0, MACHINE_PCI | MACHINE_BUS_PS2 | MACHINE_IDE_DUAL, 8192,1048576, 8192, 127, machine_at_p65up5_cpknd_init, NULL }, + { + .name = "[i440FX] ASUS P/I-P65UP5 (C-PKND)", + .internal_name = "p65up5_cpknd", + .type = MACHINE_TYPE_SLOT1, + .chipset = MACHINE_CHIPSET_INTEL_440FX, + .init = machine_at_p65up5_cpknd_init, + .p1_handler = NULL, + .gpio_handler = NULL, + .available_flag = MACHINE_AVAILABLE, + .gpio_acpi_handler = NULL, + .cpu = { + .package = CPU_PKG_SLOT1, + .block = CPU_BLOCK_NONE, + .min_bus = 50000000, + .max_bus = 66666667, + .min_voltage = 1800, + .max_voltage = 3500, + .min_multi = 1.5, + .max_multi = 8.0 + }, + .bus_flags = MACHINE_PS2_PCI, + .flags = MACHINE_IDE_DUAL | MACHINE_APM | MACHINE_ACPI, + .ram = { + .min = 8192, + .max = 1048576, + .step = 8192 + }, + .nvrmask = 127, + .kbc_device = NULL, + .kbc_p1 = 0xff, + .gpio = 0xffffffff, + .gpio_acpi = 0xffffffff, + .device = NULL, + .fdc_device = NULL, + .sio_device = NULL, + .vid_device = NULL, + .snd_device = NULL, + .net_device = NULL + }, /* This has a Holtek KBC and the BIOS does not send a single non-standard KBC command, so it must be an ASIC that clones the standard IBM PS/2 KBC. */ - { "[i440FX] ASUS KN97", "kn97", MACHINE_TYPE_SLOT1, CPU_PKG_SLOT1, 0, 60000000, 83333333, 1800, 3500, 1.5, 8.0, MACHINE_PCI | MACHINE_BUS_PS2 | MACHINE_IDE_DUAL, 8192, 786432, 8192, 127, machine_at_kn97_init, NULL }, + { + .name = "[i440FX] ASUS KN97", + .internal_name = "kn97", + .type = MACHINE_TYPE_SLOT1, + .chipset = MACHINE_CHIPSET_INTEL_440FX, + .init = machine_at_kn97_init, + .p1_handler = NULL, + .gpio_handler = NULL, + .available_flag = MACHINE_AVAILABLE, + .gpio_acpi_handler = NULL, + .cpu = { + .package = CPU_PKG_SLOT1, + .block = CPU_BLOCK_NONE, + .min_bus = 60000000, + .max_bus = 83333333, + .min_voltage = 1800, + .max_voltage = 3500, + .min_multi = 1.5, + .max_multi = 8.0 + }, + .bus_flags = MACHINE_PS2_PCI, + .flags = MACHINE_IDE_DUAL | MACHINE_APM | MACHINE_ACPI, + .ram = { + .min = 8192, + .max = 786432, + .step = 8192 + }, + .nvrmask = 127, + .kbc_device = NULL, + .kbc_p1 = 0xff, + .gpio = 0xffffffff, + .gpio_acpi = 0xffffffff, + .device = NULL, + .fdc_device = NULL, + .sio_device = NULL, + .vid_device = NULL, + .snd_device = NULL, + .net_device = NULL + }, /* 440LX */ /* Has a Winbond W83977TF Super I/O chip with on-chip KBC with AMIKey-2 KBC firmware. */ - { "[i440LX] ABIT LX6", "lx6", MACHINE_TYPE_SLOT1, CPU_PKG_SLOT1, 0, 60000000, 100000000, 1500, 3500, 2.0, 5.5, MACHINE_AGP | MACHINE_BUS_PS2 | MACHINE_IDE_DUAL, 8192,1048576, 8192, 255, machine_at_lx6_init, NULL }, + { + .name = "[i440LX] ABIT LX6", + .internal_name = "lx6", + .type = MACHINE_TYPE_SLOT1, + .chipset = MACHINE_CHIPSET_INTEL_440LX, + .init = machine_at_lx6_init, + .p1_handler = NULL, + .gpio_handler = NULL, + .available_flag = MACHINE_AVAILABLE, + .gpio_acpi_handler = NULL, + .cpu = { + .package = CPU_PKG_SLOT1, + .block = CPU_BLOCK_NONE, + .min_bus = 60000000, + .max_bus = 100000000, + .min_voltage = 1500, + .max_voltage = 3500, + .min_multi = 2.0, + .max_multi = 5.5 + }, + .bus_flags = MACHINE_PS2_AGP, + .flags = MACHINE_IDE_DUAL | MACHINE_APM | MACHINE_ACPI, + .ram = { + .min = 8192, + .max = 1048576, + .step = 8192 + }, + .nvrmask = 255, + .kbc_device = NULL, + .kbc_p1 = 0xff, + .gpio = 0xffffffff, + .gpio_acpi = 0xffffffff, + .device = NULL, + .fdc_device = NULL, + .sio_device = NULL, + .vid_device = NULL, + .snd_device = NULL, + .net_device = NULL + }, /* Has a SM(S)C FDC37C935 Super I/O chip with on-chip KBC with Phoenix MultiKey KBC firmware. */ - { "[i440LX] Micronics Spitfire", "spitfire", MACHINE_TYPE_SLOT1, CPU_PKG_SLOT1, 0, 66666667, 66666667, 1800, 3500, 1.5, 8.0, MACHINE_AGP | MACHINE_BUS_PS2 | MACHINE_IDE_DUAL, 8192,1048576, 8192, 255, machine_at_spitfire_init, NULL }, + { + .name = "[i440LX] Micronics Spitfire", + .internal_name = "spitfire", + .type = MACHINE_TYPE_SLOT1, + .chipset = MACHINE_CHIPSET_INTEL_440LX, + .init = machine_at_spitfire_init, + .p1_handler = NULL, + .gpio_handler = NULL, + .available_flag = MACHINE_AVAILABLE, + .gpio_acpi_handler = NULL, + .cpu = { + .package = CPU_PKG_SLOT1, + .block = CPU_BLOCK_NONE, + .min_bus = 66666667, + .max_bus = 66666667, + .min_voltage = 1800, + .max_voltage = 3500, + .min_multi = 1.5, + .max_multi = 8.0 + }, + .bus_flags = MACHINE_PS2_AGP, + .flags = MACHINE_IDE_DUAL | MACHINE_APM | MACHINE_ACPI, + .ram = { + .min = 8192, + .max = 1048576, + .step = 8192 + }, + .nvrmask = 255, + .kbc_device = NULL, + .kbc_p1 = 0xff, + .gpio = 0xffffffff, + .gpio_acpi = 0xffffffff, + .device = NULL, + .fdc_device = NULL, + .sio_device = NULL, + .vid_device = NULL, + .snd_device = NULL, + .net_device = NULL + }, /* 440EX */ /* Has a Winbond W83977TF Super I/O chip with on-chip KBC with AMIKey-2 KBC firmware. */ - { "[i440EX] QDI EXCELLENT II", "p6i440e2", MACHINE_TYPE_SLOT1, CPU_PKG_SLOT1, 0, 66666667, 83333333, 1800, 3500, 3.0, 8.0, MACHINE_PCI | MACHINE_BUS_PS2 | MACHINE_IDE_DUAL, 8192, 524288, 8192, 255, machine_at_p6i440e2_init, NULL }, + { + .name = "[i440EX] QDI EXCELLENT II", + .internal_name = "p6i440e2", + .type = MACHINE_TYPE_SLOT1, + .chipset = MACHINE_CHIPSET_INTEL_440EX, + .init = machine_at_p6i440e2_init, + .p1_handler = NULL, + .gpio_handler = NULL, + .available_flag = MACHINE_AVAILABLE, + .gpio_acpi_handler = NULL, + .cpu = { + .package = CPU_PKG_SLOT1, + .block = CPU_BLOCK_NONE, + .min_bus = 66666667, + .max_bus = 83333333, + .min_voltage = 1800, + .max_voltage = 3500, + .min_multi = 3.0, + .max_multi = 8.0 + }, + .bus_flags = MACHINE_PS2_AGP, + .flags = MACHINE_IDE_DUAL | MACHINE_APM | MACHINE_ACPI, + .ram = { + .min = 8192, + .max = 524288, + .step = 8192 + }, + .nvrmask = 255, + .kbc_device = NULL, + .kbc_p1 = 0xff, + .gpio = 0xffffffff, + .gpio_acpi = 0xffffffff, + .device = NULL, + .fdc_device = NULL, + .sio_device = NULL, + .vid_device = NULL, + .snd_device = NULL, + .net_device = NULL + }, /* 440BX */ /* Has a Winbond W83977EF Super I/O chip with on-chip KBC with AMIKey-2 KBC firmware. */ - { "[i440BX] ASUS P2B-LS", "p2bls", MACHINE_TYPE_SLOT1, CPU_PKG_SLOT1, 0, 50000000, 112121212, 1300, 3500, 1.5, 8.0, MACHINE_AGP | MACHINE_BUS_PS2 | MACHINE_IDE_DUAL, 8192,1048576, 8192, 255, machine_at_p2bls_init, NULL }, + { + .name = "[i440BX] ASUS P2B-LS", + .internal_name = "p2bls", + .type = MACHINE_TYPE_SLOT1, + .chipset = MACHINE_CHIPSET_INTEL_440BX, + .init = machine_at_p2bls_init, + .p1_handler = NULL, + .gpio_handler = NULL, + .available_flag = MACHINE_AVAILABLE, + .gpio_acpi_handler = NULL, + .cpu = { + .package = CPU_PKG_SLOT1, + .block = CPU_BLOCK_NONE, + .min_bus = 50000000, + .max_bus = 112121212, + .min_voltage = 1300, + .max_voltage = 3500, + .min_multi = 1.5, + .max_multi = 8.0 + }, + .bus_flags = MACHINE_PS2_AGP, + .flags = MACHINE_IDE_DUAL | MACHINE_APM | MACHINE_ACPI, + .ram = { + .min = 8192, + .max = 1048576, + .step = 8192 + }, + .nvrmask = 255, + .kbc_device = NULL, + .kbc_p1 = 0xff, + .gpio = 0xffffffff, + .gpio_acpi = 0xffffffff, + .device = NULL, + .fdc_device = NULL, + .sio_device = NULL, + .vid_device = NULL, + .snd_device = NULL, + .net_device = NULL + }, /* Has a Winbond W83977EF Super I/O chip with on-chip KBC with AMIKey-2 KBC firmware. */ - { "[i440BX] ASUS P3B-F", "p3bf", MACHINE_TYPE_SLOT1, CPU_PKG_SLOT1, 0, 66666667, 150000000, 1300, 3500, 1.5, 8.0, MACHINE_AGP | MACHINE_BUS_PS2 | MACHINE_IDE_DUAL, 8192,1048576, 8192, 255, machine_at_p3bf_init, NULL }, + { + .name = "[i440BX] ASUS P3B-F", + .internal_name = "p3bf", + .type = MACHINE_TYPE_SLOT1, + .chipset = MACHINE_CHIPSET_INTEL_440BX, + .init = machine_at_p3bf_init, + .p1_handler = NULL, + .gpio_handler = NULL, + .available_flag = MACHINE_AVAILABLE, + .gpio_acpi_handler = NULL, + .cpu = { + .package = CPU_PKG_SLOT1, + .block = CPU_BLOCK_NONE, + .min_bus = 66666667, + .max_bus = 150000000, + .min_voltage = 1300, + .max_voltage = 3500, + .min_multi = 1.5, + .max_multi = 8.0 + }, + .bus_flags = MACHINE_PS2_AGP, + .flags = MACHINE_IDE_DUAL | MACHINE_APM | MACHINE_ACPI, + .ram = { + .min = 8192, + .max = 1048576, + .step = 8192 + }, + .nvrmask = 255, + .kbc_device = NULL, + .kbc_p1 = 0xff, + .gpio = 0xffffffff, + .gpio_acpi = 0xffffffff, + .device = NULL, + .fdc_device = NULL, + .sio_device = NULL, + .vid_device = NULL, + .snd_device = NULL, + .net_device = NULL + }, /* Has a Winbond W83977EF Super I/O chip with on-chip KBC with AMIKey-2 KBC firmware. */ - { "[i440BX] ABIT BF6", "bf6", MACHINE_TYPE_SLOT1, CPU_PKG_SLOT1, 0, 66666667, 133333333, 1800, 3500, 1.5, 8.0, MACHINE_AGP | MACHINE_BUS_PS2 | MACHINE_IDE_DUAL, 8192, 786432, 8192, 255, machine_at_bf6_init, NULL }, + { + .name = "[i440BX] ABIT BF6", + .internal_name = "bf6", + .type = MACHINE_TYPE_SLOT1, + .chipset = MACHINE_CHIPSET_INTEL_440BX, + .init = machine_at_bf6_init, + .p1_handler = NULL, + .gpio_handler = NULL, + .available_flag = MACHINE_AVAILABLE, + .gpio_acpi_handler = NULL, + .cpu = { + .package = CPU_PKG_SLOT1, + .block = CPU_BLOCK_NONE, + .min_bus = 66666667, + .max_bus = 133333333, + .min_voltage = 1800, + .max_voltage = 3500, + .min_multi = 1.5, + .max_multi = 8.0 + }, + .bus_flags = MACHINE_PS2_AGP, + .flags = MACHINE_IDE_DUAL | MACHINE_APM | MACHINE_ACPI, + .ram = { + .min = 8192, + .max = 786432, + .step = 8192 + }, + .nvrmask = 255, + .kbc_device = NULL, + .kbc_p1 = 0xff, + .gpio = 0xffffffff, + .gpio_acpi = 0xffffffff, + .device = NULL, + .fdc_device = NULL, + .sio_device = NULL, + .vid_device = NULL, + .snd_device = NULL, + .net_device = NULL + }, /* Has a Winbond W83977TF Super I/O chip with on-chip KBC with AMIKey-2 KBC firmware. */ - { "[i440BX] AOpen AX6BC", "ax6bc", MACHINE_TYPE_SLOT1, CPU_PKG_SLOT1, 0, 66666667, 112121212, 1800, 3500, 1.5, 8.0, MACHINE_AGP | MACHINE_BUS_PS2 | MACHINE_IDE_DUAL, 8192, 786432, 8192, 255, machine_at_ax6bc_init, NULL }, + { + .name = "[i440BX] AOpen AX6BC", + .internal_name = "ax6bc", + .type = MACHINE_TYPE_SLOT1, + .chipset = MACHINE_CHIPSET_INTEL_440BX, + .init = machine_at_ax6bc_init, + .p1_handler = NULL, + .gpio_handler = NULL, + .available_flag = MACHINE_AVAILABLE, + .gpio_acpi_handler = NULL, + .cpu = { + .package = CPU_PKG_SLOT1, + .block = CPU_BLOCK_NONE, + .min_bus = 66666667, + .max_bus = 112121212, + .min_voltage = 1800, + .max_voltage = 3500, + .min_multi = 1.5, + .max_multi = 8.0 + }, + .bus_flags = MACHINE_PS2_AGP, + .flags = MACHINE_IDE_DUAL | MACHINE_APM | MACHINE_ACPI, + .ram = { + .min = 8192, + .max = 786432, + .step = 8192 + }, + .nvrmask = 255, + .kbc_device = NULL, + .kbc_p1 = 0xff, + .gpio = 0xffffffff, + .gpio_acpi = 0xffffffff, + .device = NULL, + .fdc_device = NULL, + .sio_device = NULL, + .vid_device = NULL, + .snd_device = NULL, + .net_device = NULL + }, /* Has a Winbond W83977TF Super I/O chip with on-chip KBC with AMIKey-2 KBC firmware. */ - { "[i440BX] Gigabyte GA-686BX", "686bx", MACHINE_TYPE_SLOT1, CPU_PKG_SLOT1, 0, 66666667, 100000000, 1800, 3500, 1.5, 8.0, MACHINE_AGP | MACHINE_BUS_PS2 | MACHINE_IDE_DUAL, 8192,1048576, 8192, 255, machine_at_686bx_init, NULL }, + { + .name = "[i440BX] Gigabyte GA-686BX", + .internal_name = "686bx", + .type = MACHINE_TYPE_SLOT1, + .chipset = MACHINE_CHIPSET_INTEL_440BX, + .init = machine_at_686bx_init, + .p1_handler = NULL, + .gpio_handler = NULL, + .available_flag = MACHINE_AVAILABLE, + .gpio_acpi_handler = NULL, + .cpu = { + .package = CPU_PKG_SLOT1, + .block = CPU_BLOCK_NONE, + .min_bus = 66666667, + .max_bus = 100000000, + .min_voltage = 1800, + .max_voltage = 3500, + .min_multi = 1.5, + .max_multi = 8.0 + }, + .bus_flags = MACHINE_PS2_AGP, + .flags = MACHINE_IDE_DUAL | MACHINE_APM | MACHINE_ACPI, + .ram = { + .min = 8192, + .max = 1048576, + .step = 8192 + }, + .nvrmask = 255, + .kbc_device = NULL, + .kbc_p1 = 0xff, + .gpio = 0xffffffff, + .gpio_acpi = 0xffffffff, + .device = NULL, + .fdc_device = NULL, + .sio_device = NULL, + .vid_device = NULL, + .snd_device = NULL, + .net_device = NULL + }, /* Has a SM(S)C FDC37M60x Super I/O chip with on-chip KBC with most likely AMIKey-2 KBC firmware. */ - { "[i440BX] HP Vectra VEi 8", "vei8", MACHINE_TYPE_SLOT1, CPU_PKG_SLOT1, 0, 66666667, 100000000, 1800, 3500, 1.5, 8.0, MACHINE_AGP | MACHINE_BUS_PS2 | MACHINE_IDE_DUAL, 8192,1048576, 8192, 255, machine_at_vei8_init, NULL }, + { + .name = "[i440BX] HP Vectra VEi 8", + .internal_name = "vei8", + .type = MACHINE_TYPE_SLOT1, + .chipset = MACHINE_CHIPSET_INTEL_440BX, + .init = machine_at_vei8_init, + .p1_handler = NULL, + .gpio_handler = NULL, + .available_flag = MACHINE_AVAILABLE, + .gpio_acpi_handler = NULL, + .cpu = { + .package = CPU_PKG_SLOT1, + .block = CPU_BLOCK_NONE, + .min_bus = 66666667, + .max_bus = 100000000, + .min_voltage = 1800, + .max_voltage = 3500, + .min_multi = 1.5, + .max_multi = 8.0 + }, + .bus_flags = MACHINE_PS2_AGP, + .flags = MACHINE_IDE_DUAL | MACHINE_APM | MACHINE_ACPI, + .ram = { + .min = 8192, + .max = 1048576, + .step = 8192 + }, + .nvrmask = 255, + .kbc_device = NULL, + .kbc_p1 = 0xff, + .gpio = 0xffffffff, + .gpio_acpi = 0xffffffff, + .device = NULL, + .fdc_device = NULL, + .sio_device = NULL, + .vid_device = NULL, + .snd_device = NULL, + .net_device = NULL + }, /* Has a National Semiconductors PC87309 Super I/O chip with on-chip KBC with most likely AMIKey-2 KBC firmware. */ - { "[i440BX] Tyan Tsunami ATX", "s1846", MACHINE_TYPE_SLOT1, CPU_PKG_SLOT1, 0, 66666667, 112121212, 1800, 3500, 1.5, 8.0, MACHINE_AGP | MACHINE_BUS_PS2 | MACHINE_IDE_DUAL | MACHINE_SOUND, 8192,1048576, 8192, 255, machine_at_s1846_init, at_s1846_get_device }, + { + .name = "[i440BX] Tyan Tsunami ATX", + .internal_name = "s1846", + .type = MACHINE_TYPE_SLOT1, + .chipset = MACHINE_CHIPSET_INTEL_440BX, + .init = machine_at_s1846_init, + .p1_handler = NULL, + .gpio_handler = NULL, + .available_flag = MACHINE_AVAILABLE, + .gpio_acpi_handler = NULL, + .cpu = { + .package = CPU_PKG_SLOT1, + .block = CPU_BLOCK_NONE, + .min_bus = 66666667, + .max_bus = 112121212, + .min_voltage = 1800, + .max_voltage = 3500, + .min_multi = 1.5, + .max_multi = 8.0 + }, + .bus_flags = MACHINE_PS2_AGP, + .flags = MACHINE_IDE_DUAL | MACHINE_SOUND | MACHINE_APM | MACHINE_ACPI, + .ram = { + .min = 8192, + .max = 1048576, + .step = 8192 + }, + .nvrmask = 255, + .kbc_device = NULL, + .kbc_p1 = 0xff, + .gpio = 0xffffffff, + .gpio_acpi = 0xffffffff, + .device = NULL, + .fdc_device = NULL, + .sio_device = NULL, + .vid_device = NULL, + .snd_device = &es1371_onboard_device, + .net_device = NULL + }, /* Has a Winbond W83977TF Super I/O chip with on-chip KBC with AMIKey-2 KBC firmware. */ - { "[i440BX] Supermicro P6SBA", "p6sba", MACHINE_TYPE_SLOT1, CPU_PKG_SLOT1, 0, 66666667, 100000000, 1800, 3500, 1.5, 8.0, MACHINE_AGP | MACHINE_BUS_PS2 | MACHINE_IDE_DUAL, 8192, 786432, 8192, 255, machine_at_p6sba_init, NULL }, - + { + .name = "[i440BX] Supermicro P6SBA", + .internal_name = "p6sba", + .type = MACHINE_TYPE_SLOT1, + .chipset = MACHINE_CHIPSET_INTEL_440BX, + .init = machine_at_p6sba_init, + .p1_handler = NULL, + .gpio_handler = NULL, + .available_flag = MACHINE_AVAILABLE, + .gpio_acpi_handler = NULL, + .cpu = { + .package = CPU_PKG_SLOT1, + .block = CPU_BLOCK_NONE, + .min_bus = 66666667, + .max_bus = 100000000, + .min_voltage = 1800, + .max_voltage = 3500, + .min_multi = 1.5, + .max_multi = 8.0 + }, + .bus_flags = MACHINE_PS2_AGP, + .flags = MACHINE_IDE_DUAL | MACHINE_APM | MACHINE_ACPI, + .ram = { + .min = 8192, + .max = 786432, + .step = 8192 + }, + .nvrmask = 255, + .kbc_device = NULL, + .kbc_p1 = 0xff, + .gpio = 0xffffffff, + .gpio_acpi = 0xffffffff, + .device = NULL, + .fdc_device = NULL, + .sio_device = NULL, + .vid_device = NULL, + .snd_device = NULL, + .net_device = NULL + }, + /* 440ZX */ /* Has a Winbond W83977EF Super I/O chip with on-chip KBC with AMIKey-2 KBC firmware. */ - { "[i440ZX] MSI MS-6168", "ms6168", MACHINE_TYPE_SLOT1, CPU_PKG_SLOT1, 0, 66666667, 100000000, 1800, 3500, 1.5, 8.0, MACHINE_AGP | MACHINE_BUS_PS2 | MACHINE_IDE_DUAL | MACHINE_VIDEO | MACHINE_SOUND,8192, 524288, 8192, 255, machine_at_ms6168_init, at_ms6168_get_device }, + { + .name = "[i440ZX] MSI MS-6168", + .internal_name = "ms6168", + .type = MACHINE_TYPE_SLOT1, + .chipset = MACHINE_CHIPSET_INTEL_440ZX, + .init = machine_at_ms6168_init, + .p1_handler = NULL, + .gpio_handler = NULL, + .available_flag = MACHINE_AVAILABLE, + .gpio_acpi_handler = NULL, + .cpu = { + .package = CPU_PKG_SLOT1, + .block = CPU_BLOCK_NONE, + .min_bus = 66666667, + .max_bus = 100000000, + .min_voltage = 1800, + .max_voltage = 3500, + .min_multi = 1.5, + .max_multi = 8.0 + }, + .bus_flags = MACHINE_PS2_AGP, + .flags = MACHINE_IDE_DUAL | MACHINE_AV | MACHINE_APM | MACHINE_ACPI, + .ram = { + .min = 8192, + .max = 524288, + .step = 8192 + }, + .nvrmask = 255, + .kbc_device = NULL, + .kbc_p1 = 0xff, + .gpio = 0xffffffff, + .gpio_acpi = 0xffffffff, + .device = NULL, + .fdc_device = NULL, + .sio_device = NULL, + .vid_device = &voodoo_3_2000_agp_onboard_8m_device, + .snd_device = NULL, + .net_device = NULL + }, /* Has a Winbond W83977EF Super I/O chip with on-chip KBC with AMIKey-2 KBC firmware. */ - { "[i440ZX] Packard Bell Bora Pro", "borapro", MACHINE_TYPE_SLOT1, CPU_PKG_SLOT1, 0, 66666667, 66666667, 1800, 3500, 1.5, 8.0, MACHINE_AGP | MACHINE_BUS_PS2 | MACHINE_IDE_DUAL | MACHINE_VIDEO | MACHINE_SOUND,8192, 524288, 8192, 255, machine_at_borapro_init, at_borapro_get_device }, + { + .name = "[i440ZX] Packard Bell Bora Pro", + .internal_name = "borapro", + .type = MACHINE_TYPE_SLOT1, + .chipset = MACHINE_CHIPSET_INTEL_440ZX, + .init = machine_at_borapro_init, + .p1_handler = NULL, + .gpio_handler = NULL, + .available_flag = MACHINE_AVAILABLE, + .gpio_acpi_handler = NULL, + .cpu = { + .package = CPU_PKG_SLOT1, + .block = CPU_BLOCK_NONE, + .min_bus = 66666667, + .max_bus = 66666667, + .min_voltage = 1800, + .max_voltage = 3500, + .min_multi = 1.5, + .max_multi = 8.0 + }, + .bus_flags = MACHINE_PS2_AGP, + .flags = MACHINE_IDE_DUAL | MACHINE_AV | MACHINE_APM | MACHINE_ACPI, + .ram = { + .min = 8192, + .max = 524288, + .step = 8192 + }, + .nvrmask = 255, + .kbc_device = NULL, + .kbc_p1 = 0xff, + .gpio = 0xffffffff, + .gpio_acpi = 0xffffffff, + .device = NULL, + .fdc_device = NULL, + .sio_device = NULL, + .vid_device = &voodoo_3_2000_agp_onboard_8m_device, + .snd_device = NULL, + .net_device = NULL + }, /* SMSC VictoryBX-66 */ /* Has a Winbond W83977EF Super I/O chip with on-chip KBC with AMIKey-2 KBC firmware. */ - { "[SMSC VictoryBX-66] A-Trend ATC6310BXII","atc6310bxii", MACHINE_TYPE_SLOT1, CPU_PKG_SLOT1, 0, 66666667, 133333333, 1300, 3500, 1.5, 8.0, MACHINE_AGP | MACHINE_BUS_PS2 | MACHINE_IDE_DUAL, 8192, 786432, 8192, 255, machine_at_atc6310bxii_init, NULL }, + { + .name = "[SMSC VictoryBX-66] A-Trend ATC6310BXII", + .internal_name = "atc6310bxii", + .type = MACHINE_TYPE_SLOT1, + .chipset = MACHINE_CHIPSET_SMSC_VICTORYBX_66, + .init = machine_at_atc6310bxii_init, + .p1_handler = NULL, + .gpio_handler = NULL, + .available_flag = MACHINE_AVAILABLE, + .gpio_acpi_handler = NULL, + .cpu = { + .package = CPU_PKG_SLOT1, + .block = CPU_BLOCK_NONE, + .min_bus = 66666667, + .max_bus = 133333333, + .min_voltage = 1300, + .max_voltage = 3500, + .min_multi = 1.5, + .max_multi = 8.0 + }, + .bus_flags = MACHINE_PS2_AGP, + .flags = MACHINE_IDE_DUAL | MACHINE_APM | MACHINE_ACPI, + .ram = { + .min = 8192, + .max = 786432, + .step = 8192 + }, + .nvrmask = 255, + .kbc_device = NULL, + .kbc_p1 = 0xff, + .gpio = 0xffffffff, + .gpio_acpi = 0xffffffff, + .device = NULL, + .fdc_device = NULL, + .sio_device = NULL, + .vid_device = NULL, + .snd_device = NULL, + .net_device = NULL + }, /* VIA Apollo Pro */ /* Has the VIA VT82C596B southbridge with on-chip KBC identical to the VIA VT82C42N. */ - { "[VIA Apollo Pro] FIC KA-6130", "ficka6130", MACHINE_TYPE_SLOT1, CPU_PKG_SLOT1, 0, 66666667, 100000000, 1800, 3500, 1.5, 8.0, MACHINE_AGP | MACHINE_BUS_PS2 | MACHINE_IDE_DUAL, 8192, 524288, 8192, 255, machine_at_ficka6130_init, NULL }, + { + .name = "[VIA Apollo Pro] FIC KA-6130", + .internal_name = "ficka6130", + .type = MACHINE_TYPE_SLOT1, + .chipset = MACHINE_CHIPSET_VIA_APOLLO_PRO, + .init = machine_at_ficka6130_init, + .p1_handler = NULL, + .gpio_handler = NULL, + .available_flag = MACHINE_AVAILABLE, + .gpio_acpi_handler = NULL, + .cpu = { + .package = CPU_PKG_SLOT1, + .block = CPU_BLOCK_NONE, + .min_bus = 66666667, + .max_bus = 100000000, + .min_voltage = 1800, + .max_voltage = 3500, + .min_multi = 1.5, + .max_multi = 8.0 + }, + .bus_flags = MACHINE_PS2_AGP, + .flags = MACHINE_IDE_DUAL | MACHINE_APM | MACHINE_ACPI, + .ram = { + .min = 8192, + .max = 524288, + .step = 8192 + }, + .nvrmask = 255, + .kbc_device = NULL, + .kbc_p1 = 0xff, + .gpio = 0xffffffff, + .gpio_acpi = 0xffffffff, + .device = NULL, + .fdc_device = NULL, + .sio_device = NULL, + .vid_device = NULL, + .snd_device = NULL, + .net_device = NULL + }, /* Has a Winbond W83977EF Super I/O chip with on-chip KBC with AMIKey-2 KBC firmware. */ - { "[VIA Apollo Pro 133] ASUS P3V133", "p3v133", MACHINE_TYPE_SLOT1, CPU_PKG_SLOT1, 0, 66666667, 150000000, 1300, 3500, 1.5, 8.0, MACHINE_AGP | MACHINE_BUS_PS2 | MACHINE_IDE_DUAL, 8192,1572864, 8192, 255, machine_at_p3v133_init, NULL }, + { + .name = "[VIA Apollo Pro 133] ASUS P3V133", + .internal_name = "p3v133", + .type = MACHINE_TYPE_SLOT1, + .chipset = MACHINE_CHIPSET_VIA_APOLLO_PRO_133, + .init = machine_at_p3v133_init, + .p1_handler = NULL, + .gpio_handler = NULL, + .available_flag = MACHINE_AVAILABLE, + .gpio_acpi_handler = NULL, + .cpu = { + .package = CPU_PKG_SLOT1, + .block = CPU_BLOCK_NONE, + .min_bus = 66666667, + .max_bus = 150000000, + .min_voltage = 1300, + .max_voltage = 3500, + .min_multi = 1.5, + .max_multi = 8.0 + }, + .bus_flags = MACHINE_PS2_AGP, + .flags = MACHINE_IDE_DUAL | MACHINE_APM | MACHINE_ACPI, + .ram = { + .min = 8192, + .max = 1572864, + .step = 8192 + }, + .nvrmask = 255, + .kbc_device = NULL, + .kbc_p1 = 0xff, + .gpio = 0xffffffff, + .gpio_acpi = 0xffffffff, + .device = NULL, + .fdc_device = NULL, + .sio_device = NULL, + .vid_device = NULL, + .snd_device = NULL, + .net_device = NULL + }, /* Has a Winbond W83977EF Super I/O chip with on-chip KBC with AMIKey-2 KBC firmware. */ - { "[VIA Apollo Pro 133A] ASUS P3V4X", "p3v4x", MACHINE_TYPE_SLOT1, CPU_PKG_SLOT1, 0, 66666667, 150000000, 1300, 3500, 1.5, 8.0, MACHINE_AGP | MACHINE_BUS_PS2 | MACHINE_IDE_DUAL, 8192,2097152, 8192, 255, machine_at_p3v4x_init, NULL }, + { + .name = "[VIA Apollo Pro 133A] ASUS P3V4X", + .internal_name = "p3v4x", + .type = MACHINE_TYPE_SLOT1, + .chipset = MACHINE_CHIPSET_VIA_APOLLO_PRO_133A, + .init = machine_at_p3v4x_init, + .p1_handler = NULL, + .gpio_handler = NULL, + .available_flag = MACHINE_AVAILABLE, + .gpio_acpi_handler = NULL, + .cpu = { + .package = CPU_PKG_SLOT1, + .block = CPU_BLOCK_NONE, + .min_bus = 66666667, + .max_bus = 150000000, + .min_voltage = 1300, + .max_voltage = 3500, + .min_multi = 1.5, + .max_multi = 8.0 + }, + .bus_flags = MACHINE_PS2_AGP, + .flags = MACHINE_IDE_DUAL | MACHINE_APM | MACHINE_ACPI, + .ram = { + .min = 8192, + .max = 2097152, + .step = 8192 + }, + .nvrmask = 255, + .kbc_device = NULL, + .kbc_p1 = 0xff, + .gpio = 0xffffffff, + .gpio_acpi = 0xffffffff, + .device = NULL, + .fdc_device = NULL, + .sio_device = NULL, + .vid_device = NULL, + .snd_device = NULL, + .net_device = NULL + }, + /* Has a Winbond W83977EF Super I/O chip with on-chip KBC with AMIKey-2 KBC + firmware. */ + { + .name = "[VIA Apollo Pro 133A] BCM GT694VA", + .internal_name = "gt694va", + .type = MACHINE_TYPE_SLOT1, + .chipset = MACHINE_CHIPSET_VIA_APOLLO_PRO_133A, + .init = machine_at_gt694va_init, + .p1_handler = NULL, + .gpio_handler = NULL, + .available_flag = MACHINE_AVAILABLE, + .gpio_acpi_handler = NULL, + .cpu = { + .package = CPU_PKG_SLOT1, + .block = CPU_BLOCK_NONE, + .min_bus = 66666667, + .max_bus = 133333333, + .min_voltage = 1300, + .max_voltage = 3500, + .min_multi = 1.5, + .max_multi = 8.0 + }, + .bus_flags = MACHINE_PS2_AGP, + .flags = MACHINE_IDE_DUAL | MACHINE_SOUND | MACHINE_APM | MACHINE_ACPI, + .ram = { + .min = 8192, + .max = 3145728, + .step = 8192 + }, + .nvrmask = 255, + .kbc_device = NULL, + .kbc_p1 = 0xff, + .gpio = 0xffffffff, + .gpio_acpi = 0xffffffff, + .device = NULL, + .fdc_device = NULL, + .sio_device = NULL, + .vid_device = NULL, + .snd_device = &es1371_onboard_device, + .net_device = NULL + }, /* Slot 1/2 machines */ /* 440GX */ /* Has a National Semiconductors PC87309 Super I/O chip with on-chip KBC with most likely AMIKey-2 KBC firmware. */ - { "[i440GX] Freeway FW-6400GX", "fw6400gx", MACHINE_TYPE_SLOT1_2, CPU_PKG_SLOT1 | CPU_PKG_SLOT2, 0, 100000000, 150000000, 1800, 3500, 3.0, 8.0, (MACHINE_AGP & ~MACHINE_AT) | MACHINE_BUS_PS2 | MACHINE_IDE_DUAL, 16384,2080768,16384, 511, machine_at_fw6400gx_init, NULL }, + { + .name = "[i440GX] Freeway FW-6400GX", + .internal_name = "fw6400gx", + .type = MACHINE_TYPE_SLOT1_2, + .chipset = MACHINE_CHIPSET_INTEL_440GX, + .init = machine_at_fw6400gx_init, + .p1_handler = NULL, + .gpio_handler = NULL, + .available_flag = MACHINE_AVAILABLE, + .gpio_acpi_handler = NULL, + .cpu = { + .package = CPU_PKG_SLOT1 | CPU_PKG_SLOT2, + .block = CPU_BLOCK_NONE, + .min_bus = 100000000, + .max_bus = 150000000, + .min_voltage = 1800, + .max_voltage = 3500, + .min_multi = 3.0, + .max_multi = 8.0 + }, + .bus_flags = MACHINE_PS2_NOISA, + .flags = MACHINE_IDE_DUAL | MACHINE_APM | MACHINE_ACPI, + .ram = { + .min = 16384, + .max = 2097152, + .step = 16384 + }, + .nvrmask = 511, + .kbc_device = NULL, + .kbc_p1 = 0xff, + .gpio = 0xffffffff, + .gpio_acpi = 0xffffffff, + .device = NULL, + .fdc_device = NULL, + .sio_device = NULL, + .vid_device = NULL, + .snd_device = NULL, + .net_device = NULL + }, /* Slot 1/Socket 370 machines */ /* 440BX */ /* Has a Winbond W83977EF Super I/O chip with on-chip KBC with AMIKey-2 KBC firmware. */ - { "[i440BX] Tyan Trinity 371", "s1857", MACHINE_TYPE_SLOT1_370, CPU_PKG_SLOT1 | CPU_PKG_SOCKET370, 0, 66666667, 133333333, 1300, 3500, 1.5, 8.0, MACHINE_AGP | MACHINE_BUS_PS2 | MACHINE_IDE_DUAL, 8192, 786432, 8192, 255, machine_at_s1857_init, at_s1857_get_device }, + { + .name = "[i440BX] Tyan Trinity 371", + .internal_name = "s1857", + .type = MACHINE_TYPE_SLOT1_370, + .chipset = MACHINE_CHIPSET_INTEL_440BX, + .init = machine_at_s1857_init, + .p1_handler = NULL, + .gpio_handler = NULL, + .available_flag = MACHINE_AVAILABLE, + .gpio_acpi_handler = NULL, + .cpu = { + .package = CPU_PKG_SLOT1 | CPU_PKG_SOCKET370, + .block = CPU_BLOCK_NONE, + .min_bus = 66666667, + .max_bus = 133333333, + .min_voltage = 1300, + .max_voltage = 3500, + .min_multi = 1.5, + .max_multi = 8.0 + }, + .bus_flags = MACHINE_PS2_AGP, + .flags = MACHINE_IDE_DUAL | MACHINE_APM | MACHINE_ACPI, + .ram = { + .min = 8192, + .max = 786432, + .step = 8192 + }, + .nvrmask = 255, + .kbc_device = NULL, + .kbc_p1 = 0xff, + .gpio = 0xffffffff, + .gpio_acpi = 0xffffffff, + .device = NULL, + .fdc_device = NULL, + .sio_device = NULL, + .vid_device = NULL, + .snd_device = &es1371_onboard_device, + .net_device = NULL + }, + /* VIA Apollo Pro */ + /* Has a Winbond W83977EF Super I/O chip with on-chip KBC with AMIKey-2 KBC + firmware. */ + { + .name = "[VIA Apollo Pro 133] ECS P6BAT-A+", + .internal_name = "p6bat", + .type = MACHINE_TYPE_SLOT1_370, + .chipset = MACHINE_CHIPSET_VIA_APOLLO_PRO_133, + .init = machine_at_p6bat_init, + .p1_handler = NULL, + .gpio_handler = NULL, + .available_flag = MACHINE_AVAILABLE, + .gpio_acpi_handler = NULL, + .cpu = { + .package = CPU_PKG_SLOT1 | CPU_PKG_SOCKET370, + .block = CPU_BLOCK_NONE, + .min_bus = 66666667, + .max_bus = 133333333, + .min_voltage = 1300, + .max_voltage = 3500, + .min_multi = 1.5, + .max_multi = 8.0 + }, + .bus_flags = MACHINE_PS2_AGP, + .flags = MACHINE_IDE_DUAL | MACHINE_SOUND | MACHINE_APM | MACHINE_ACPI, + .ram = { + .min = 8192, + .max = 786432, + .step = 8192 + }, + .nvrmask = 255, + .kbc_device = NULL, + .kbc_p1 = 0xff, + .gpio = 0xffffffff, + .gpio_acpi = 0xffffffff, + .device = NULL, + .fdc_device = NULL, + .sio_device = NULL, + .vid_device = NULL, + .snd_device = &cmi8738_onboard_device, + .net_device = NULL + }, /* Slot 2 machines */ /* 440GX */ /* Has a Winbond W83977EF Super I/O chip with on-chip KBC with AMIKey-2 KBC firmware. */ - { "[i440GX] Gigabyte GA-6GXU", "6gxu", MACHINE_TYPE_SLOT2, CPU_PKG_SLOT2, 0, 100000000, 133333333, 1800, 3500, 1.5, 8.0, MACHINE_AGP | MACHINE_BUS_PS2 | MACHINE_IDE_DUAL, 16384,2097152,16384, 511, machine_at_6gxu_init, NULL }, + { + .name = "[i440GX] Gigabyte GA-6GXU", + .internal_name = "6gxu", + .type = MACHINE_TYPE_SLOT2, + .chipset = MACHINE_CHIPSET_INTEL_440GX, + .init = machine_at_6gxu_init, + .p1_handler = NULL, + .gpio_handler = NULL, + .available_flag = MACHINE_AVAILABLE, + .gpio_acpi_handler = NULL, + .cpu = { + .package = CPU_PKG_SLOT2, + .block = CPU_BLOCK_NONE, + .min_bus = 100000000, + .max_bus = 133333333, + .min_voltage = 1800, + .max_voltage = 3500, + .min_multi = 1.5, + .max_multi = 8.0 + }, + .bus_flags = MACHINE_PS2_AGP, + .flags = MACHINE_IDE_DUAL | MACHINE_APM | MACHINE_ACPI, + .ram = { + .min = 16384, + .max = 2097152, + .step = 16384 + }, + .nvrmask = 511, + .kbc_device = NULL, + .kbc_p1 = 0xff, + .gpio = 0xffffffff, + .gpio_acpi = 0xffffffff, + .device = NULL, + .fdc_device = NULL, + .sio_device = NULL, + .vid_device = NULL, + .snd_device = NULL, + .net_device = NULL + }, /* Has a Winbond W83977TF Super I/O chip with on-chip KBC with AMIKey-2 KBC firmware. */ - { "[i440GX] Supermicro S2DGE", "s2dge", MACHINE_TYPE_SLOT2, CPU_PKG_SLOT2, 0, 66666667, 100000000, 1800, 3500, 1.5, 8.0, MACHINE_AGP | MACHINE_BUS_PS2 | MACHINE_IDE_DUAL, 16384,2097152,16384, 511, machine_at_s2dge_init, NULL }, + { + .name = "[i440GX] Supermicro S2DGE", + .internal_name = "s2dge", + .type = MACHINE_TYPE_SLOT2, + .chipset = MACHINE_CHIPSET_INTEL_440GX, + .init = machine_at_s2dge_init, + .p1_handler = NULL, + .gpio_handler = NULL, + .available_flag = MACHINE_AVAILABLE, + .gpio_acpi_handler = NULL, + .cpu = { + .package = CPU_PKG_SLOT2, + .block = CPU_BLOCK_NONE, + .min_bus = 66666667, + .max_bus = 100000000, + .min_voltage = 1800, + .max_voltage = 3500, + .min_multi = 1.5, + .max_multi = 8.0 + }, + .bus_flags = MACHINE_PS2_AGP, + .flags = MACHINE_IDE_DUAL | MACHINE_APM | MACHINE_ACPI, + .ram = { + .min = 16384, + .max = 2097152, + .step = 16384 + }, + .nvrmask = 511, + .kbc_device = NULL, + .kbc_p1 = 0xff, + .gpio = 0xffffffff, + .gpio_acpi = 0xffffffff, + .device = NULL, + .fdc_device = NULL, + .sio_device = NULL, + .vid_device = NULL, + .snd_device = NULL, + .net_device = NULL + }, /* PGA370 machines */ /* 440LX */ /* Has a Winbond W83977TF Super I/O chip with on-chip KBC with AMIKey-2 KBC firmware. */ - { "[i440LX] Supermicro 370SLM", "s370slm", MACHINE_TYPE_SOCKET370, CPU_PKG_SOCKET370, 0, 66666667, 100000000, 1800, 3500, MACHINE_MULTIPLIER_FIXED, MACHINE_AGP | MACHINE_BUS_PS2 | MACHINE_IDE_DUAL, 8192, 786432, 8192, 255, machine_at_s370slm_init, NULL }, + { + .name = "[i440LX] Supermicro 370SLM", + .internal_name = "s370slm", + .type = MACHINE_TYPE_SOCKET370, + .chipset = MACHINE_CHIPSET_INTEL_440LX, + .init = machine_at_s370slm_init, + .p1_handler = NULL, + .gpio_handler = NULL, + .available_flag = MACHINE_AVAILABLE, + .gpio_acpi_handler = NULL, + .cpu = { + .package = CPU_PKG_SOCKET370, + .block = CPU_BLOCK_NONE, + .min_bus = 66666667, + .max_bus = 100000000, + .min_voltage = 1800, + .max_voltage = 3500, + .min_multi = MACHINE_MULTIPLIER_FIXED, + .max_multi = MACHINE_MULTIPLIER_FIXED, + }, + .bus_flags = MACHINE_PS2_AGP, + .flags = MACHINE_IDE_DUAL | MACHINE_APM | MACHINE_ACPI, + .ram = { + .min = 8192, + .max = 786432, + .step = 8192 + }, + .nvrmask = 255, + .kbc_device = NULL, + .kbc_p1 = 0xff, + .gpio = 0xffffffff, + .gpio_acpi = 0xffffffff, + .device = NULL, + .fdc_device = NULL, + .sio_device = NULL, + .vid_device = NULL, + .snd_device = NULL, + .net_device = NULL + }, /* 440BX */ /* Has a Winbond W83977EF Super I/O chip with on-chip KBC with AMIKey-2 KBC firmware. */ - { "[i440BX] AEWIN AW-O671R", "awo671r", MACHINE_TYPE_SOCKET370, CPU_PKG_SOCKET370, 0, 66666667, 133333333, 1300, 3500, 1.5, 8.0, /* limits assumed */ MACHINE_AGP | MACHINE_BUS_PS2 | MACHINE_IDE_DUAL, 8192, 524288, 8192, 255, machine_at_awo671r_init, NULL }, + { + .name = "[i440BX] AEWIN AW-O671R", + .internal_name = "awo671r", + .type = MACHINE_TYPE_SOCKET370, + .chipset = MACHINE_CHIPSET_INTEL_440BX, + .init = machine_at_awo671r_init, + .p1_handler = NULL, + .gpio_handler = NULL, + .available_flag = MACHINE_AVAILABLE, + .gpio_acpi_handler = NULL, + .cpu = { + .package = CPU_PKG_SOCKET370, + .block = CPU_BLOCK_NONE, + .min_bus = 66666667, + .max_bus = 133333333, + .min_voltage = 1300, + .max_voltage = 3500, + .min_multi = 1.5, + .max_multi = 8.0 /* limits assumed */ + }, + .bus_flags = MACHINE_PS2_AGP, + .flags = MACHINE_IDE_DUAL | MACHINE_APM | MACHINE_ACPI, + .ram = { + .min = 8192, + .max = 524288, + .step = 8192 + }, + .nvrmask = 255, + .kbc_device = NULL, + .kbc_p1 = 0xff, + .gpio = 0xffffffff, + .gpio_acpi = 0xffffffff, + .device = NULL, + .fdc_device = NULL, + .sio_device = NULL, + .vid_device = NULL, + .snd_device = NULL, + .net_device = NULL + }, /* Has a Winbond W83977EF Super I/O chip with on-chip KBC with AMIKey-2 KBC firmware. */ - { "[i440BX] ASUS CUBX", "cubx", MACHINE_TYPE_SOCKET370, CPU_PKG_SOCKET370, 0, 66666667, 150000000, 1300, 3500, 1.5, 8.0, MACHINE_AGP | MACHINE_BUS_PS2 | MACHINE_IDE_DUAL, 8192,1048576, 8192, 255, machine_at_cubx_init, NULL }, + { + .name = "[i440BX] ASUS CUBX", + .internal_name = "cubx", + .type = MACHINE_TYPE_SOCKET370, + .chipset = MACHINE_CHIPSET_INTEL_440BX, + .init = machine_at_cubx_init, + .p1_handler = NULL, + .gpio_handler = NULL, + .available_flag = MACHINE_AVAILABLE, + .gpio_acpi_handler = NULL, + .cpu = { + .package = CPU_PKG_SOCKET370, + .block = CPU_BLOCK_NONE, + .min_bus = 66666667, + .max_bus = 150000000, + .min_voltage = 1300, + .max_voltage = 3500, + .min_multi = 1.5, + .max_multi = 8.0 + }, + .bus_flags = MACHINE_PS2_AGP, + .flags = MACHINE_IDE_DUAL | MACHINE_APM | MACHINE_ACPI, + .ram = { + .min = 8192, + .max = 1048576, + .step = 8192 + }, + .nvrmask = 255, + .kbc_device = NULL, + .kbc_p1 = 0xff, + .gpio = 0xffffffff, + .gpio_acpi = 0xffffffff, + .device = NULL, + .fdc_device = NULL, + .sio_device = NULL, + .vid_device = NULL, + .snd_device = NULL, + .net_device = NULL + }, /* Has a Winbond W83977EF Super I/O chip with on-chip KBC with AMIKey-2 KBC firmware. */ - { "[i440BX] AmazePC AM-BX133", "ambx133", MACHINE_TYPE_SOCKET370, CPU_PKG_SOCKET370, 0, 66666667, 133333333, 1300, 3500, 1.5, 8.0, /* limits assumed */ MACHINE_AGP | MACHINE_BUS_PS2 | MACHINE_IDE_DUAL, 8192, 786432, 8192, 255, machine_at_ambx133_init, NULL }, + { + .name = "[i440BX] AmazePC AM-BX133", + .internal_name = "ambx133", + .type = MACHINE_TYPE_SOCKET370, + .chipset = MACHINE_CHIPSET_INTEL_440BX, + .init = machine_at_ambx133_init, + .p1_handler = NULL, + .gpio_handler = NULL, + .available_flag = MACHINE_AVAILABLE, + .gpio_acpi_handler = NULL, + .cpu = { + .package = CPU_PKG_SOCKET370, + .block = CPU_BLOCK_NONE, + .min_bus = 66666667, + .max_bus = 133333333, + .min_voltage = 1300, + .max_voltage = 3500, + .min_multi = 1.5, + .max_multi = 8.0 /* limits assumed */ + }, + .bus_flags = MACHINE_PS2_AGP, + .flags = MACHINE_IDE_DUAL | MACHINE_APM | MACHINE_ACPI, + .ram = { + .min = 8192, + .max = 786432, + .step = 8192 + }, + .nvrmask = 255, + .kbc_device = NULL, + .kbc_p1 = 0xff, + .gpio = 0xffffffff, + .gpio_acpi = 0xffffffff, + .device = NULL, + .fdc_device = NULL, + .sio_device = NULL, + .vid_device = NULL, + .snd_device = NULL, + .net_device = NULL + }, /* 440ZX */ /* Has a Winbond W83977TF Super I/O chip with on-chip KBC with AMIKey-2 KBC firmware. */ - { "[i440ZX] Soltek SL-63A1", "63a1", MACHINE_TYPE_SOCKET370, CPU_PKG_SOCKET370, 0, 66666667, 100000000, 1800, 3500, 1.5, 8.0, MACHINE_AGP | MACHINE_BUS_PS2 | MACHINE_IDE_DUAL, 8192, 524288, 8192, 255, machine_at_63a1_init, NULL }, + { + .name = "[i440ZX] Soltek SL-63A1", + .internal_name = "63a1", + .type = MACHINE_TYPE_SOCKET370, + .chipset = MACHINE_CHIPSET_INTEL_440ZX, + .init = machine_at_63a1_init, + .p1_handler = NULL, + .gpio_handler = NULL, + .available_flag = MACHINE_AVAILABLE, + .gpio_acpi_handler = NULL, + .cpu = { + .package = CPU_PKG_SOCKET370, + .block = CPU_BLOCK_NONE, + .min_bus = 66666667, + .max_bus = 100000000, + .min_voltage = 1800, + .max_voltage = 3500, + .min_multi = 1.5, + .max_multi = 8.0 + }, + .bus_flags = MACHINE_PS2_AGP, + .flags = MACHINE_IDE_DUAL | MACHINE_APM | MACHINE_ACPI, + .ram = { + .min = 8192, + .max = 524288, + .step = 8192 + }, + .nvrmask = 255, + .kbc_device = NULL, + .kbc_p1 = 0xff, + .gpio = 0xffffffff, + .gpio_acpi = 0xffffffff, + .device = NULL, + .fdc_device = NULL, + .sio_device = NULL, + .vid_device = NULL, + .snd_device = NULL, + .net_device = NULL + }, /* SMSC VictoryBX-66 */ /* Has a Winbond W83977EF Super I/O chip with on-chip KBC with AMIKey-2 KBC firmware. */ - { "[SMSC VictoryBX-66] A-Trend ATC7020BXII","atc7020bxii", MACHINE_TYPE_SOCKET370, CPU_PKG_SOCKET370, 0, 66666667, 133333333, 1300, 3500, 1.5, 8.0, MACHINE_AGP | MACHINE_BUS_PS2 | MACHINE_IDE_DUAL, 8192,1048576, 8192, 255, machine_at_atc7020bxii_init, NULL }, + { + .name = "[SMSC VictoryBX-66] A-Trend ATC7020BXII", + .internal_name = "atc7020bxii", + .type = MACHINE_TYPE_SOCKET370, + .chipset = MACHINE_CHIPSET_SMSC_VICTORYBX_66, + .init = machine_at_atc7020bxii_init, + .p1_handler = NULL, + .gpio_handler = NULL, + .available_flag = MACHINE_AVAILABLE, + .gpio_acpi_handler = NULL, + .cpu = { + .package = CPU_PKG_SOCKET370, + .block = CPU_BLOCK_NONE, + .min_bus = 66666667, + .max_bus = 133333333, + .min_voltage = 1300, + .max_voltage = 3500, + .min_multi = 1.5, + .max_multi = 8.0 + }, + .bus_flags = MACHINE_PS2_AGP, + .flags = MACHINE_IDE_DUAL | MACHINE_APM | MACHINE_ACPI, + .ram = { + .min = 8192, + .max = 1048576, + .step = 8192 + }, + .nvrmask = 255, + .kbc_device = NULL, + .kbc_p1 = 0xff, + .gpio = 0xffffffff, + .gpio_acpi = 0xffffffff, + .device = NULL, + .fdc_device = NULL, + .sio_device = NULL, + .vid_device = NULL, + .snd_device = NULL, + .net_device = NULL + }, /* VIA Apollo Pro */ /* Has the VIA VT82C586B southbridge with on-chip KBC identical to the VIA VT82C42N. */ - { "[VIA Apollo Pro] PC Partner APAS3", "apas3", MACHINE_TYPE_SOCKET370, CPU_PKG_SOCKET370, 0, 66666667, 100000000, 1800, 3500, 1.5, 8.0, MACHINE_AGP | MACHINE_BUS_PS2 | MACHINE_IDE_DUAL, 8192, 786432, 8192, 255, machine_at_apas3_init, NULL }, + { + .name = "[VIA Apollo Pro] PC Partner APAS3", + .internal_name = "apas3", + .type = MACHINE_TYPE_SOCKET370, + .chipset = MACHINE_CHIPSET_VIA_APOLLO_PRO, + .init = machine_at_apas3_init, + .p1_handler = NULL, + .gpio_handler = NULL, + .available_flag = MACHINE_AVAILABLE, + .gpio_acpi_handler = NULL, + .cpu = { + .package = CPU_PKG_SOCKET370, + .block = CPU_BLOCK_NONE, + .min_bus = 66666667, + .max_bus = 100000000, + .min_voltage = 1800, + .max_voltage = 3500, + .min_multi = 1.5, + .max_multi = 8.0 + }, + .bus_flags = MACHINE_PS2_AGP, + .flags = MACHINE_IDE_DUAL | MACHINE_APM | MACHINE_ACPI, + .ram = { + .min = 8192, + .max = 786432, + .step = 8192 + }, + .nvrmask = 255, + .kbc_device = NULL, + .kbc_p1 = 0xff, + .gpio = 0xffffffff, + .gpio_acpi = 0xffffffff, + .device = NULL, + .fdc_device = NULL, + .sio_device = NULL, + .vid_device = NULL, + .snd_device = NULL, + .net_device = NULL + }, /* Has a Winbond W83977EF Super I/O chip with on-chip KBC with AMIKey-2 KBC firmware. */ - { "[VIA Apollo Pro 133] ECS P6BAP", "p6bap", MACHINE_TYPE_SOCKET370, CPU_PKG_SOCKET370, 0, 66666667, 150000000, 1300, 3500, 1.5, 8.0, MACHINE_AGP | MACHINE_BUS_PS2 | MACHINE_IDE_DUAL, 8192,1572864, 8192, 255, machine_at_p6bap_init, NULL }, + { + .name = "[VIA Apollo Pro 133] ECS P6BAP-A+", + .internal_name = "p6bap", + .type = MACHINE_TYPE_SOCKET370, + .chipset = MACHINE_CHIPSET_VIA_APOLLO_PRO_133, + .init = machine_at_p6bap_init, + .p1_handler = NULL, + .gpio_handler = NULL, + .available_flag = MACHINE_AVAILABLE, + .gpio_acpi_handler = NULL, + .cpu = { + .package = CPU_PKG_SOCKET370, + .block = CPU_BLOCK_NONE, + .min_bus = 66666667, + .max_bus = 150000000, + .min_voltage = 1300, + .max_voltage = 3500, + .min_multi = 1.5, + .max_multi = 8.0 + }, + .bus_flags = MACHINE_PS2_AGP, + .flags = MACHINE_IDE_DUAL | MACHINE_APM | MACHINE_ACPI, + .ram = { + .min = 8192, + .max = 1572864, + .step = 8192 + }, + .nvrmask = 255, + .kbc_device = NULL, + .kbc_p1 = 0xff, + .gpio = 0xffffffff, + .gpio_acpi = 0xffffffff, + .device = NULL, + .fdc_device = NULL, + .sio_device = NULL, + .vid_device = NULL, + .snd_device = NULL, + .net_device = NULL + }, /* Has the VIA VT82C686B southbridge with on-chip KBC identical to the VIA VT82C42N. */ - { "[VIA Apollo Pro 133A] Acorp 6VIA90AP", "6via90ap", MACHINE_TYPE_SOCKET370, CPU_PKG_SOCKET370, 0, 66666667, 150000000, 1300, 3500, MACHINE_MULTIPLIER_FIXED, MACHINE_AGP | MACHINE_BUS_PS2 | MACHINE_BUS_AC97 | MACHINE_IDE_DUAL | MACHINE_SOUND | MACHINE_GAMEPORT, 16384,3145728, 8192, 255, machine_at_6via90ap_init, NULL }, + { + .name = "[VIA Apollo Pro 133A] Acorp 6VIA90AP", + .internal_name = "6via90ap", + .type = MACHINE_TYPE_SOCKET370, + .chipset = MACHINE_CHIPSET_VIA_APOLLO_PRO_133A, + .init = machine_at_6via90ap_init, + .p1_handler = NULL, + .gpio_handler = NULL, + .available_flag = MACHINE_AVAILABLE, + .gpio_acpi_handler = NULL, + .cpu = { + .package = CPU_PKG_SOCKET370, + .block = CPU_BLOCK_NONE, + .min_bus = 66666667, + .max_bus = 150000000, + .min_voltage = 1300, + .max_voltage = 3500, + .min_multi = MACHINE_MULTIPLIER_FIXED, + .max_multi = MACHINE_MULTIPLIER_FIXED + }, + .bus_flags = MACHINE_PS2_A97, + .flags = MACHINE_IDE_DUAL | MACHINE_AG | MACHINE_APM | MACHINE_ACPI, + .ram = { + .min = 16384, + .max = 3145728, + .step = 8192 + }, + .nvrmask = 255, + .kbc_device = NULL, + .kbc_p1 = 0xff, + .gpio = 0xffffffff, + .gpio_acpi = 0xffffffff, + .device = NULL, + .fdc_device = NULL, + .sio_device = NULL, + .vid_device = NULL, + .snd_device = NULL, + .net_device = NULL + }, /* Has the VIA VT82C686B southbridge with on-chip KBC identical to the VIA VT82C42N. */ - { "[VIA Apollo Pro 133A] ASUS CUV4X-LS", "cuv4xls", MACHINE_TYPE_SOCKET370, CPU_PKG_SOCKET370, 0, 66666667, 150000000, 1300, 3500, 1.5, 8.0, (MACHINE_AGP & ~MACHINE_AT) | MACHINE_BUS_PS2 | MACHINE_BUS_AC97 | MACHINE_IDE_DUAL,16384,4194304, 8192, 255, machine_at_cuv4xls_init, NULL }, - /* Has a Winbond W83977EF Super I/O chip with on-chip KBC with AMIKey-2 KBC - firmware. */ - { "[VIA Apollo Pro 133A] BCM GT694VA", "gt694va", MACHINE_TYPE_SOCKET370, CPU_PKG_SOCKET370, 0, 66666667, 133333333, 1300, 3500, 1.5, 8.0, MACHINE_AGP | MACHINE_BUS_PS2 | MACHINE_IDE_DUAL | MACHINE_SOUND, 16384,3145728, 8192, 255, machine_at_gt694va_init, at_gt694va_get_device }, + { + .name = "[VIA Apollo Pro 133A] ASUS CUV4X-LS", + .internal_name = "cuv4xls", + .type = MACHINE_TYPE_SOCKET370, + .chipset = MACHINE_CHIPSET_VIA_APOLLO_PRO_133A, + .init = machine_at_cuv4xls_init, + .p1_handler = NULL, + .gpio_handler = NULL, + .available_flag = MACHINE_AVAILABLE, + .gpio_acpi_handler = NULL, + .cpu = { + .package = CPU_PKG_SOCKET370, + .block = CPU_BLOCK_NONE, + .min_bus = 66666667, + .max_bus = 150000000, + .min_voltage = 1300, + .max_voltage = 3500, + .min_multi = 1.5, + .max_multi = 8.0 + }, + .bus_flags = MACHINE_PS2_NOI97, + .flags = MACHINE_IDE_DUAL | MACHINE_SOUND | MACHINE_APM | MACHINE_ACPI, + .ram = { + .min = 16384, + .max = 4194304, + .step = 8192 + }, + .nvrmask = 255, + .kbc_device = NULL, + .kbc_p1 = 0xff, + .gpio = 0xffffffff, + .gpio_acpi = 0xffffffff, + .device = NULL, + .fdc_device = NULL, + .sio_device = NULL, + .vid_device = NULL, + .snd_device = &cmi8738_onboard_device, + .net_device = NULL + }, /* Miscellaneous/Fake/Hypervisor machines */ /* Has a Winbond W83977F Super I/O chip with on-chip KBC with AMIKey-2 KBC firmware. */ - { "[i440BX] Microsoft Virtual PC 2007", "vpc2007", MACHINE_TYPE_MISC, CPU_PKG_SLOT1, CPU_BLOCK(CPU_PENTIUM2, CPU_CYRIX3S), 0, 66666667, 0, 0, 0, 0, MACHINE_PCI | MACHINE_BUS_PS2 | MACHINE_IDE_DUAL, 8192,1048576, 8192, 255, machine_at_vpc2007_init, NULL }, + { + .name = "[i440BX] Microsoft Virtual PC 2007", + .internal_name = "vpc2007", + .type = MACHINE_TYPE_MISC, + .chipset = MACHINE_CHIPSET_INTEL_440BX, + .init = machine_at_vpc2007_init, + .p1_handler = NULL, + .gpio_handler = NULL, + .available_flag = MACHINE_AVAILABLE, + .gpio_acpi_handler = NULL, + .cpu = { + .package = CPU_PKG_SLOT1, + .block = CPU_BLOCK(CPU_PENTIUM2, CPU_CYRIX3S), + .min_bus = 0, + .max_bus = 66666667, + .min_voltage = 0, + .max_voltage = 0, + .min_multi = 0, + .max_multi = 0 + }, + .bus_flags = MACHINE_PS2_PCI, + .flags = MACHINE_IDE_DUAL | MACHINE_APM | MACHINE_ACPI, + .ram = { + .min = 8192, + .max = 1048576, + .step = 8192 + }, + .nvrmask = 255, + .kbc_device = NULL, + .kbc_p1 = 0xff, + .gpio = 0xffffffff, + .gpio_acpi = 0xffffffff, + .device = NULL, + .fdc_device = NULL, + .sio_device = NULL, + .vid_device = NULL, + .snd_device = NULL, + .net_device = NULL + }, - { NULL, NULL, MACHINE_TYPE_NONE, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL, NULL } + { + .name = NULL, + .internal_name = NULL, + .type = MACHINE_TYPE_NONE, + .chipset = MACHINE_CHIPSET_NONE, + .init = NULL, + .p1_handler = NULL, + .gpio_handler = NULL, + .available_flag = MACHINE_AVAILABLE, + .gpio_acpi_handler = NULL, + .cpu = { + .package = 0, + .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_BUS_NONE, + .flags = MACHINE_FLAGS_NONE, + .ram = { + .min = 0, + .max = 0, + .step = 0 + }, + .nvrmask = 0, + .kbc_device = NULL, + .kbc_p1 = 0xff, + .gpio = 0xffffffff, + .gpio_acpi = 0xffffffff, + .device = NULL, + .fdc_device = NULL, + .sio_device = NULL, + .vid_device = NULL, + .snd_device = NULL, + .net_device = NULL + } + // clang-format on }; +/* Saved copies - jumpers get applied to these. + We use also machine_gpio to store IBM PC/XT jumpers as they need more than one byte. */ +static uint8_t machine_p1_default; +static uint8_t machine_p1; + +static uint32_t machine_gpio_default; +static uint32_t machine_gpio; + +static uint32_t machine_gpio_acpi_default; +static uint32_t machine_gpio_acpi; + +void *machine_snd = NULL; + +uint8_t +machine_get_p1_default(void) +{ + return machine_p1_default; +} + +uint8_t +machine_get_p1(void) +{ + return machine_p1; +} + +void +machine_set_p1_default(uint8_t val) +{ + machine_p1 = machine_p1_default = val; +} + +void +machine_set_p1(uint8_t val) +{ + machine_p1 = val; +} + +void +machine_and_p1(uint8_t val) +{ + machine_p1 = machine_p1_default & val; +} + +uint8_t +machine_handle_p1(uint8_t write, uint8_t val) +{ + uint8_t ret = 0xff; + + if (machines[machine].p1_handler) + ret = machines[machine].p1_handler(write, val); + else { + if (write) + machine_p1 = machine_p1_default & val; + else + ret = machine_p1; + } + + return ret; +} + +void +machine_init_p1(void) +{ + machine_p1 = machine_p1_default = machines[machine].kbc_p1; +} + +uint32_t +machine_get_gpio_default(void) +{ + return machine_gpio_default; +} + +uint32_t +machine_get_gpio(void) +{ + return machine_gpio; +} + +void +machine_set_gpio_default(uint32_t val) +{ + machine_gpio = machine_gpio_default = val; +} + +void +machine_set_gpio(uint32_t val) +{ + machine_gpio = val; +} + +void +machine_and_gpio(uint32_t val) +{ + machine_gpio = machine_gpio_default & val; +} + +uint32_t +machine_handle_gpio(uint8_t write, uint32_t val) +{ + uint32_t ret = 0xffffffff; + + if (machines[machine].gpio_handler) + ret = machines[machine].gpio_handler(write, val); + else { + if (write) + machine_gpio = machine_gpio_default & val; + else + ret = machine_gpio; + } + + return ret; +} + +void +machine_init_gpio(void) +{ + machine_gpio = machine_gpio_default = machines[machine].gpio; +} + +uint32_t +machine_get_gpio_acpi_default(void) +{ + return machine_gpio_acpi_default; +} + +uint32_t +machine_get_gpio_acpi(void) +{ + return machine_gpio_acpi; +} + +void +machine_set_gpio_acpi_default(uint32_t val) +{ + machine_gpio_acpi = machine_gpio_acpi_default = val; +} + +void +machine_set_gpio_acpi(uint32_t val) +{ + machine_gpio_acpi = val; +} + +void +machine_and_gpio_acpi(uint32_t val) +{ + machine_gpio_acpi = machine_gpio_acpi_default & val; +} + +uint32_t +machine_handle_gpio_acpi(uint8_t write, uint32_t val) +{ + uint32_t ret = 0xffffffff; + + if (machines[machine].gpio_acpi_handler) + ret = machines[machine].gpio_acpi_handler(write, val); + else { + if (write) + machine_gpio_acpi = machine_gpio_acpi_default & val; + else + ret = machine_gpio_acpi; + } + + return ret; +} + +void +machine_init_gpio_acpi(void) +{ + machine_gpio_acpi = machine_gpio_acpi_default = machines[machine].gpio_acpi; +} int machine_count(void) { - return((sizeof(machines) / sizeof(machine_t)) - 1); + return ((sizeof(machines) / sizeof(machine_t)) - 1); } - -char * +const char * machine_getname(void) { - return((char *)machines[machine].name); + return (machines[machine].name); } - -char * +const char * machine_getname_ex(int m) { - return((char *)machines[m].name); + return (machines[m].name); } - const device_t * -machine_getdevice(int m) +machine_get_kbc_device(int m) { - if (machines[m].get_device) - return(machines[m].get_device()); + if (machines[m].kbc_device) + return (machines[m].kbc_device); - return(NULL); + return (NULL); } +const device_t * +machine_get_device(int m) +{ + if (machines[m].device) + return (machines[m].device); -char * + return (NULL); +} + +const device_t * +machine_get_fdc_device(int m) +{ + if (machines[m].fdc_device) + return (machines[m].fdc_device); + + return (NULL); +} + +const device_t * +machine_get_sio_device(int m) +{ + if (machines[m].sio_device) + return (machines[m].sio_device); + + return (NULL); +} + +const device_t * +machine_get_vid_device(int m) +{ + if (machines[m].vid_device) + return (machines[m].vid_device); + + return (NULL); +} + +const device_t * +machine_get_snd_device(int m) +{ + if (machines[m].snd_device) + return (machines[m].snd_device); + + return (NULL); +} + +const device_t * +machine_get_net_device(int m) +{ + if (machines[m].net_device) + return (machines[m].net_device); + + return (NULL); +} + +const char * machine_get_internal_name(void) { - return((char *)machines[machine].internal_name); + return (machines[machine].internal_name); } - -char * +const char * machine_get_internal_name_ex(int m) { - return((char *)machines[m].internal_name); + return (machines[m].internal_name); } - int machine_get_nvrmask(int m) { - return(machines[m].nvrmask); + return (machines[m].nvrmask); } - int machine_has_flags(int m, int flags) { - return(machines[m].flags & flags); + return (machines[m].flags & flags); } - int machine_has_bus(int m, int bus_flags) { - return(machines[m].flags & bus_flags); + return (machines[m].bus_flags & bus_flags); } - int machine_has_cartridge(int m) { - return(machine_has_flags(m, MACHINE_CARTRIDGE) ? 1 : 0); + return (machine_has_bus(m, MACHINE_CARTRIDGE) ? 1 : 0); } - int machine_get_min_ram(int m) { - return(machines[m].min_ram); + return (machines[m].ram.min); } - int machine_get_max_ram(int m) { #if (!(defined __amd64__ || defined _M_X64 || defined __aarch64__ || defined _M_ARM64)) - return MIN(((int) machines[m].max_ram), 2097152); + return MIN(((int) machines[m].ram.max), 2097152); #else - return MIN(((int) machines[m].max_ram), 3145728); + return MIN(((int) machines[m].ram.max), 3145728); #endif } - int machine_get_ram_granularity(int m) { - return(machines[m].ram_granularity); + return (machines[m].ram.step); } - int machine_get_type(int m) { - return(machines[m].type); + return (machines[m].type); } - int -machine_get_machine_from_internal_name(char *s) +machine_get_machine_from_internal_name(const char *s) { int c = 0; while (machines[c].init != NULL) { - if (!strcmp(machines[c].internal_name, (const char *)s)) - return(c); - c++; + if (!strcmp(machines[c].internal_name, s)) + return c; + c++; } - return(0); + return 0; +} + +int +machine_has_mouse(void) +{ + return (machines[machine].flags & MACHINE_MOUSE); +} + +int +machine_is_sony(void) +{ + return (!strcmp(machines[machine].internal_name, "pcv90")); } diff --git a/src/machine_status.c b/src/machine_status.c new file mode 100644 index 000000000..65f4704b4 --- /dev/null +++ b/src/machine_status.c @@ -0,0 +1,58 @@ +#include +#include +#include +#include +#include + +#include <86box/86box.h> +#include <86box/plat.h> +#include <86box/ui.h> +#include <86box/timer.h> +#include <86box/device.h> +#include <86box/fdd.h> +#include <86box/hdc.h> +#include <86box/scsi.h> +#include <86box/scsi_device.h> +#include <86box/cartridge.h> +#include <86box/cassette.h> +#include <86box/cdrom.h> +#include <86box/zip.h> +#include <86box/mo.h> +#include <86box/hdd.h> +#include <86box/thread.h> +#include <86box/network.h> +#include <86box/machine_status.h> + +machine_status_t machine_status; + +void +machine_status_init(void) +{ + for (size_t i = 0; i < FDD_NUM; ++i) { + machine_status.fdd[i].empty = (strlen(floppyfns[i]) == 0); + machine_status.fdd[i].active = false; + } + for (size_t i = 0; i < CDROM_NUM; ++i) { + machine_status.cdrom[i].empty = cdrom[i].host_drive != 200 || (strlen(cdrom[i].image_path) == 0); + machine_status.cdrom[i].active = false; + } + for (size_t i = 0; i < ZIP_NUM; i++) { + machine_status.zip[i].empty = (strlen(zip_drives[i].image_path) == 0); + machine_status.zip[i].active = false; + } + for (size_t i = 0; i < MO_NUM; i++) { + machine_status.mo[i].empty = (strlen(mo_drives[i].image_path) == 0); + machine_status.mo[i].active = false; + } + + machine_status.cassette.empty = (strlen(cassette_fname) == 0); + + for (size_t i = 0; i < HDD_BUS_USB; i++) { + machine_status.hdd[i].active = false; + } + + for (size_t i = 0; i < NET_CARD_MAX; i++) { + machine_status.net[i].active = false; + machine_status.net[i].empty = !network_is_connected(i); + } +} \ No newline at end of file diff --git a/src/mca.c b/src/mca.c index f067d7cdc..871060bb4 100644 --- a/src/mca.c +++ b/src/mca.c @@ -5,85 +5,99 @@ #include <86box/io.h> #include <86box/mca.h> - -void (*mca_card_write[8])(int addr, uint8_t val, void *priv); -uint8_t (*mca_card_read[8])(int addr, void *priv); +void (*mca_card_write[8])(int addr, uint8_t val, void *priv); +uint8_t (*mca_card_read[8])(int addr, void *priv); uint8_t (*mca_card_feedb[8])(void *priv); -void (*mca_card_reset[8])(void *priv); -void *mca_priv[8]; +void (*mca_card_reset[8])(void *priv); +void *mca_priv[8]; static int mca_index; static int mca_nr_cards; - -void mca_init(int nr_cards) +void +mca_init(int nr_cards) { - int c; + for (uint8_t c = 0; c < 8; c++) { + mca_card_read[c] = NULL; + mca_card_write[c] = NULL; + mca_card_reset[c] = NULL; + mca_priv[c] = NULL; + } - for (c = 0; c < 8; c++) { - mca_card_read[c] = NULL; - mca_card_write[c] = NULL; - mca_card_reset[c] = NULL; - mca_priv[c] = NULL; - } - - mca_index = 0; - mca_nr_cards = nr_cards; + mca_index = 0; + mca_nr_cards = nr_cards; } -void mca_set_index(int index) +void +mca_set_index(int index) { - mca_index = index; + mca_index = index; } -uint8_t mca_read(uint16_t port) +uint8_t +mca_read(uint16_t port) { - if (mca_index >= mca_nr_cards) - return 0xff; - if (!mca_card_read[mca_index]) - return 0xff; - return mca_card_read[mca_index](port, mca_priv[mca_index]); + if (mca_index >= mca_nr_cards) + return 0xff; + if (!mca_card_read[mca_index]) + return 0xff; + return mca_card_read[mca_index](port, mca_priv[mca_index]); } -void mca_write(uint16_t port, uint8_t val) +uint8_t +mca_read_index(uint16_t port, int index) { - if (mca_index >= mca_nr_cards) - return; - if (mca_card_write[mca_index]) - mca_card_write[mca_index](port, val, mca_priv[mca_index]); + if (mca_index >= mca_nr_cards) + return 0xff; + if (!mca_card_read[index]) + return 0xff; + return mca_card_read[index](port, mca_priv[index]); } -uint8_t mca_feedb(void) +int +mca_get_nr_cards(void) { - if (mca_card_feedb[mca_index]) - return !!(mca_card_feedb[mca_index](mca_priv[mca_index])); - else - return 0; + return mca_nr_cards; } -void mca_reset(void) +void +mca_write(uint16_t port, uint8_t val) { - int c; - - for (c = 0; c < 8; c++) { - if (mca_card_reset[c]) - mca_card_reset[c](mca_priv[c]); - } + if (mca_index >= mca_nr_cards) + return; + if (mca_card_write[mca_index]) + mca_card_write[mca_index](port, val, mca_priv[mca_index]); } - -void mca_add(uint8_t (*read)(int addr, void *priv), void (*write)(int addr, uint8_t val, void *priv), uint8_t (*feedb)(void *priv), void (*reset)(void *priv), void *priv) +uint8_t +mca_feedb(void) { - int c; - - for (c = 0; c < mca_nr_cards; c++) { - if (!mca_card_read[c] && !mca_card_write[c]) { - mca_card_read[c] = read; - mca_card_write[c] = write; - mca_card_feedb[c] = feedb; - mca_card_reset[c] = reset; - mca_priv[c] = priv; - return; - } - } + if (mca_card_feedb[mca_index]) + return !!(mca_card_feedb[mca_index](mca_priv[mca_index])); + else + return 0; +} + +void +mca_reset(void) +{ + for (uint8_t c = 0; c < 8; c++) { + if (mca_card_reset[c]) + mca_card_reset[c](mca_priv[c]); + } +} + +void +mca_add(uint8_t (*read)(int addr, void *priv), void (*write)(int addr, uint8_t val, void *priv), uint8_t (*feedb)(void *priv), void (*reset)(void *priv), void *priv) +{ + for (int c = 0; c < mca_nr_cards; c++) { + if (!mca_card_read[c] && !mca_card_write[c]) { + mca_card_read[c] = read; + mca_card_write[c] = write; + mca_card_feedb[c] = feedb; + mca_card_reset[c] = reset; + mca_priv[c] = priv; + return; + } + } } diff --git a/src/mem/CMakeLists.txt b/src/mem/CMakeLists.txt index 4e9e7917d..d3d5d1ce7 100644 --- a/src/mem/CMakeLists.txt +++ b/src/mem/CMakeLists.txt @@ -1,17 +1,17 @@ # -# 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. +# 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. +# This file is part of the 86Box distribution. # -# CMake build script. +# CMake build script. # -# Authors: David HrdliÄka, +# Authors: David HrdliÄka, # -# Copyright 2020,2021 David HrdliÄka. +# Copyright 2020-2021 David HrdliÄka. # -add_library(mem OBJECT catalyst_flash.c i2c_eeprom.c intel_flash.c mem.c rom.c - smram.c spd.c sst_flash.c) \ No newline at end of file +add_library(mem OBJECT catalyst_flash.c i2c_eeprom.c intel_flash.c mem.c mmu_2386.c + rom.c row.c smram.c spd.c sst_flash.c) diff --git a/src/mem/catalyst_flash.c b/src/mem/catalyst_flash.c index 246063276..7cd40e9d7 100644 --- a/src/mem/catalyst_flash.c +++ b/src/mem/catalyst_flash.c @@ -1,21 +1,21 @@ /* - * 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. + * 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. + * This file is part of the 86Box distribution. * - * Implementation of the Intel 1 Mbit and 2 Mbit, 8-bit and - * 16-bit flash devices. + * Implementation of the Intel 1 Mbit and 2 Mbit, 8-bit and + * 16-bit flash devices. * * * - * Authors: Sarah Walker, - * Miran Grca, + * Authors: Sarah Walker, + * Miran Grca, * - * Copyright 2008-2019 Sarah Walker. - * Copyright 2016-2019 Miran Grca. + * Copyright 2008-2019 Sarah Walker. + * Copyright 2016-2019 Miran Grca. */ #include #include @@ -30,14 +30,11 @@ #include <86box/nvr.h> #include <86box/plat.h> +#define FLAG_WORD 4 +#define FLAG_BXB 2 +#define FLAG_INV_A16 1 -#define FLAG_WORD 4 -#define FLAG_BXB 2 -#define FLAG_INV_A16 1 - - -enum -{ +enum { BLOCK_MAIN1, BLOCK_MAIN2, BLOCK_DATA1, @@ -46,145 +43,141 @@ enum BLOCKS_NUM }; -enum -{ - CMD_SET_READ = 0x00, +enum { + CMD_SET_READ = 0x00, CMD_READ_SIGNATURE = 0x90, - CMD_ERASE = 0x20, - CMD_ERASE_CONFIRM = 0x20, - CMD_ERASE_VERIFY = 0xA0, - CMD_PROGRAM = 0x40, + CMD_ERASE = 0x20, + CMD_ERASE_CONFIRM = 0x20, + CMD_ERASE_VERIFY = 0xA0, + CMD_PROGRAM = 0x40, CMD_PROGRAM_VERIFY = 0xC0, - CMD_RESET = 0xFF + CMD_RESET = 0xFF }; +typedef struct flash_t { + uint8_t command; + uint8_t pad; + uint8_t pad0; + uint8_t pad1; + uint8_t *array; -typedef struct flash_t -{ - uint8_t command, pad, - pad0, pad1, - *array; - - mem_mapping_t mapping, mapping_h[2]; + mem_mapping_t mapping; + mem_mapping_t mapping_h[2]; } flash_t; - -static char flash_path[1024]; - +static char flash_path[1024]; static uint8_t -flash_read(uint32_t addr, void *p) +flash_read(uint32_t addr, void *priv) { - flash_t *dev = (flash_t *) p; - uint8_t ret = 0xff; + const flash_t *dev = (flash_t *) priv; + uint8_t ret = 0xff; addr &= biosmask; switch (dev->command) { - case CMD_ERASE_VERIFY: - case CMD_PROGRAM_VERIFY: - case CMD_RESET: - case CMD_SET_READ: - ret = dev->array[addr]; - break; + case CMD_ERASE_VERIFY: + case CMD_PROGRAM_VERIFY: + case CMD_RESET: + case CMD_SET_READ: + ret = dev->array[addr]; + break; - case CMD_READ_SIGNATURE: - if (addr == 0x00000) - ret = 0x31; /* CATALYST */ - else if (addr == 0x00001) - ret = 0xB4; /* 28F010 */ - break; + case CMD_READ_SIGNATURE: + if (addr == 0x00000) + ret = 0x31; /* CATALYST */ + else if (addr == 0x00001) + ret = 0xB4; /* 28F010 */ + break; + + default: + break; } return ret; } - static uint16_t -flash_readw(uint32_t addr, void *p) +flash_readw(uint32_t addr, void *priv) { - flash_t *dev = (flash_t *)p; - uint16_t *q; + flash_t *dev = (flash_t *) priv; + const uint16_t *q; addr &= biosmask; - q = (uint16_t *)&(dev->array[addr]); + q = (uint16_t *) &(dev->array[addr]); return *q; } - static uint32_t -flash_readl(uint32_t addr, void *p) +flash_readl(uint32_t addr, void *priv) { - flash_t *dev = (flash_t *)p; - uint32_t *q; + flash_t *dev = (flash_t *) priv; + const uint32_t *q; addr &= biosmask; - q = (uint32_t *)&(dev->array[addr]); + q = (uint32_t *) &(dev->array[addr]); return *q; } - static void -flash_write(uint32_t addr, uint8_t val, void *p) +flash_write(uint32_t addr, uint8_t val, void *priv) { - flash_t *dev = (flash_t *) p; + flash_t *dev = (flash_t *) priv; addr &= biosmask; switch (dev->command) { - case CMD_ERASE: - if (val == CMD_ERASE_CONFIRM) - memset(dev->array, 0xff, biosmask + 1); - break; + case CMD_ERASE: + if (val == CMD_ERASE_CONFIRM) + memset(dev->array, 0xff, biosmask + 1); + break; - case CMD_PROGRAM: - dev->array[addr] = val; - break; + case CMD_PROGRAM: + dev->array[addr] = val; + break; - default: - dev->command = val; - break; + default: + dev->command = val; + break; } } - static void -flash_writew(uint32_t addr, uint16_t val, void *p) +flash_writew(UNUSED(uint32_t addr), UNUSED(uint16_t val), UNUSED(void *priv)) { + // } - static void -flash_writel(uint32_t addr, uint32_t val, void *p) +flash_writel(UNUSED(uint32_t addr), UNUSED(uint32_t val), UNUSED(void *priv)) { + // } - static void catalyst_flash_add_mappings(flash_t *dev) { memcpy(dev->array, rom, biosmask + 1); mem_mapping_add(&dev->mapping, 0xe0000, 0x20000, - flash_read, flash_readw, flash_readl, - flash_write, flash_writew, flash_writel, - dev->array, MEM_MAPPING_EXTERNAL|MEM_MAPPING_ROM|MEM_MAPPING_ROMCS, (void *) dev); + flash_read, flash_readw, flash_readl, + flash_write, flash_writew, flash_writel, + dev->array, MEM_MAPPING_EXTERNAL | MEM_MAPPING_ROM | MEM_MAPPING_ROMCS, (void *) dev); mem_mapping_add(&(dev->mapping_h[0]), 0xfffc0000, 0x20000, - flash_read, flash_readw, flash_readl, - flash_write, flash_writew, flash_writel, - dev->array, MEM_MAPPING_EXTERNAL|MEM_MAPPING_ROM|MEM_MAPPING_ROMCS, (void *) dev); + flash_read, flash_readw, flash_readl, + flash_write, flash_writew, flash_writel, + dev->array, MEM_MAPPING_EXTERNAL | MEM_MAPPING_ROM | MEM_MAPPING_ROMCS, (void *) dev); mem_mapping_add(&(dev->mapping_h[1]), 0xfffe0000, 0x20000, - flash_read, flash_readw, flash_readl, - flash_write, flash_writew, flash_writel, - dev->array, MEM_MAPPING_EXTERNAL|MEM_MAPPING_ROM|MEM_MAPPING_ROMCS, (void *) dev); + flash_read, flash_readw, flash_readl, + flash_write, flash_writew, flash_writel, + dev->array, MEM_MAPPING_EXTERNAL | MEM_MAPPING_ROM | MEM_MAPPING_ROMCS, (void *) dev); } - static void catalyst_flash_reset(void *priv) { @@ -193,11 +186,10 @@ catalyst_flash_reset(void *priv) dev->command = CMD_RESET; } - static void * -catalyst_flash_init(const device_t *info) +catalyst_flash_init(UNUSED(const device_t *info)) { - FILE *f; + FILE *fp; flash_t *dev; dev = malloc(sizeof(flash_t)); @@ -215,25 +207,24 @@ catalyst_flash_init(const device_t *info) dev->command = CMD_RESET; - f = nvr_fopen(flash_path, "rb"); - if (f) { - fread(dev->array, 0x20000, 1, f); - fclose(f); + fp = nvr_fopen(flash_path, "rb"); + if (fp) { + (void) !fread(dev->array, 0x20000, 1, fp); + fclose(fp); } return dev; } - static void -catalyst_flash_close(void *p) +catalyst_flash_close(void *priv) { - FILE *f; - flash_t *dev = (flash_t *)p; + FILE *fp; + flash_t *dev = (flash_t *) priv; - f = nvr_fopen(flash_path, "wb"); - fwrite(dev->array, 0x20000, 1, f); - fclose(f); + fp = nvr_fopen(flash_path, "wb"); + fwrite(dev->array, 0x20000, 1, fp); + fclose(fp); free(dev->array); dev->array = NULL; @@ -241,15 +232,16 @@ catalyst_flash_close(void *p) free(dev); } - -const device_t catalyst_flash_device = -{ - "Catalyst 28F010-D Flash BIOS", - "catalyst_flash", - DEVICE_PCI, - 0, - catalyst_flash_init, - catalyst_flash_close, - catalyst_flash_reset, - { NULL }, NULL, NULL, NULL +const device_t catalyst_flash_device = { + .name = "Catalyst 28F010-D Flash BIOS", + .internal_name = "catalyst_flash", + .flags = DEVICE_PCI, + .local = 0, + .init = catalyst_flash_init, + .close = catalyst_flash_close, + .reset = catalyst_flash_reset, + { .available = NULL }, + .speed_changed = NULL, + .force_redraw = NULL, + .config = NULL }; diff --git a/src/mem/i2c_eeprom.c b/src/mem/i2c_eeprom.c index dceac93a5..7d83bbe88 100644 --- a/src/mem/i2c_eeprom.c +++ b/src/mem/i2c_eeprom.c @@ -1,18 +1,18 @@ /* - * 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. + * 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. + * This file is part of the 86Box distribution. * - * Emulation of the 24Cxx series of I2C EEPROMs. + * Emulation of the 24Cxx series of I2C EEPROMs. * * * - * Authors: RichardG, + * Authors: RichardG, * - * Copyright 2020 RichardG. + * Copyright 2020 RichardG. */ #include #include @@ -23,58 +23,58 @@ #include #include <86box/86box.h> #include <86box/i2c.h> +#include <86box/plat_unused.h> +typedef struct i2c_eeprom_t { + void *i2c; + uint8_t addr; + uint8_t *data; + uint8_t writable; -typedef struct { - void *i2c; - uint8_t addr, *data, writable; - - uint32_t addr_mask, addr_register; - uint8_t addr_len, addr_pos; + uint32_t addr_mask; + uint32_t addr_register; + uint8_t addr_len; + uint8_t addr_pos; } i2c_eeprom_t; - #ifdef ENABLE_I2C_EEPROM_LOG int i2c_eeprom_do_log = ENABLE_I2C_EEPROM_LOG; - static void i2c_eeprom_log(const char *fmt, ...) { va_list ap; if (i2c_eeprom_do_log) { - va_start(ap, fmt); - pclog_ex(fmt, ap); - va_end(ap); + va_start(ap, fmt); + pclog_ex(fmt, ap); + va_end(ap); } } #else -#define i2c_eeprom_log(fmt, ...) +# define i2c_eeprom_log(fmt, ...) #endif - static uint8_t -i2c_eeprom_start(void *bus, uint8_t addr, uint8_t read, void *priv) +i2c_eeprom_start(UNUSED(void *bus), uint8_t addr, uint8_t read, void *priv) { i2c_eeprom_t *dev = (i2c_eeprom_t *) priv; i2c_eeprom_log("I2C EEPROM %s %02X: start()\n", i2c_getbusname(dev->i2c), dev->addr); if (!read) { - dev->addr_pos = 0; - dev->addr_register = (addr << dev->addr_len) & dev->addr_mask; + dev->addr_pos = 0; + dev->addr_register = (addr << dev->addr_len) & dev->addr_mask; } return 1; } - static uint8_t -i2c_eeprom_read(void *bus, uint8_t addr, void *priv) +i2c_eeprom_read(UNUSED(void *bus), UNUSED(uint8_t addr), void *priv) { i2c_eeprom_t *dev = (i2c_eeprom_t *) priv; - uint8_t ret = dev->data[dev->addr_register]; + uint8_t ret = dev->data[dev->addr_register]; i2c_eeprom_log("I2C EEPROM %s %02X: read(%06X) = %02X\n", i2c_getbusname(dev->i2c), dev->addr, dev->addr_register, ret); dev->addr_register++; @@ -83,35 +83,33 @@ i2c_eeprom_read(void *bus, uint8_t addr, void *priv) return ret; } - static uint8_t -i2c_eeprom_write(void *bus, uint8_t addr, uint8_t data, void *priv) +i2c_eeprom_write(UNUSED(void *bus), uint8_t addr, uint8_t data, void *priv) { i2c_eeprom_t *dev = (i2c_eeprom_t *) priv; if (dev->addr_pos < dev->addr_len) { - dev->addr_register <<= 8; - dev->addr_register |= data; - dev->addr_register &= (1 << dev->addr_len) - 1; - dev->addr_register |= addr << dev->addr_len; - dev->addr_register &= dev->addr_mask; - i2c_eeprom_log("I2C EEPROM %s %02X: write(address, %06X)\n", i2c_getbusname(dev->i2c), dev->addr, dev->addr_register); - dev->addr_pos += 8; + dev->addr_register <<= 8; + dev->addr_register |= data; + dev->addr_register &= (1 << dev->addr_len) - 1; + dev->addr_register |= addr << dev->addr_len; + dev->addr_register &= dev->addr_mask; + i2c_eeprom_log("I2C EEPROM %s %02X: write(address, %06X)\n", i2c_getbusname(dev->i2c), dev->addr, dev->addr_register); + dev->addr_pos += 8; } else { - i2c_eeprom_log("I2C EEPROM %s %02X: write(%06X, %02X) = %d\n", i2c_getbusname(dev->i2c), dev->addr, dev->addr_register, data, !!dev->writable); - if (dev->writable) - dev->data[dev->addr_register] = data; - dev->addr_register++; - dev->addr_register &= dev->addr_mask; /* roll-over */ - return dev->writable; + i2c_eeprom_log("I2C EEPROM %s %02X: write(%06X, %02X) = %d\n", i2c_getbusname(dev->i2c), dev->addr, dev->addr_register, data, !!dev->writable); + if (dev->writable) + dev->data[dev->addr_register] = data; + dev->addr_register++; + dev->addr_register &= dev->addr_mask; /* roll-over */ + return dev->writable; } return 1; } - static void -i2c_eeprom_stop(void *bus, uint8_t addr, void *priv) +i2c_eeprom_stop(UNUSED(void *bus), UNUSED(uint8_t addr), void *priv) { i2c_eeprom_t *dev = (i2c_eeprom_t *) priv; @@ -120,17 +118,15 @@ i2c_eeprom_stop(void *bus, uint8_t addr, void *priv) dev->addr_pos = 0; } - uint8_t log2i(uint32_t i) { uint8_t ret = 0; - while ((i >>= 1)) - ret++; + while (i >>= 1) + ret++; return ret; } - void * i2c_eeprom_init(void *i2c, uint8_t addr, uint8_t *data, uint32_t size, uint8_t writable) { @@ -140,17 +136,17 @@ i2c_eeprom_init(void *i2c, uint8_t addr, uint8_t *data, uint32_t size, uint8_t w /* Round size up to the next power of 2. */ uint32_t pow_size = 1 << log2i(size); if (pow_size < size) - size = pow_size << 1; + size = pow_size << 1; size &= 0x7fffff; /* address space limit of 8 MB = 7 bits from I2C address + 16 bits */ i2c_eeprom_log("I2C EEPROM %s %02X: init(%d, %d)\n", i2c_getbusname(i2c), addr, size, writable); - dev->i2c = i2c; - dev->addr = addr; - dev->data = data; + dev->i2c = i2c; + dev->addr = addr; + dev->data = data; dev->writable = writable; - dev->addr_len = (size >= 4096) ? 16 : 8; /* use 16-bit addresses on 24C32 and above */ + dev->addr_len = (size >= 4096) ? 16 : 8; /* use 16-bit addresses on 24C32 and above */ dev->addr_mask = size - 1; i2c_sethandler(dev->i2c, dev->addr & ~(dev->addr_mask >> dev->addr_len), (dev->addr_mask >> dev->addr_len) + 1, i2c_eeprom_start, i2c_eeprom_read, i2c_eeprom_write, i2c_eeprom_stop, dev); @@ -158,7 +154,6 @@ i2c_eeprom_init(void *i2c, uint8_t addr, uint8_t *data, uint32_t size, uint8_t w return dev; } - void i2c_eeprom_close(void *dev_handle) { diff --git a/src/mem/intel_flash.c b/src/mem/intel_flash.c index bc896631a..7949f302a 100644 --- a/src/mem/intel_flash.c +++ b/src/mem/intel_flash.c @@ -1,21 +1,21 @@ /* - * 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. + * 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. + * This file is part of the 86Box distribution. * - * Implementation of the Intel 1 Mbit and 2 Mbit, 8-bit and - * 16-bit flash devices. + * Implementation of the Intel 1 Mbit and 2 Mbit, 8-bit and + * 16-bit flash devices. * * * - * Authors: Sarah Walker, - * Miran Grca, + * Authors: Sarah Walker, + * Miran Grca, * - * Copyright 2008-2020 Sarah Walker. - * Copyright 2016-2020 Miran Grca. + * Copyright 2008-2020 Sarah Walker. + * Copyright 2016-2020 Miran Grca. */ #include #include @@ -30,14 +30,11 @@ #include <86box/nvr.h> #include <86box/plat.h> +#define FLAG_WORD 4 +#define FLAG_BXB 2 +#define FLAG_INV_A16 1 -#define FLAG_WORD 4 -#define FLAG_BXB 2 -#define FLAG_INV_A16 1 - - -enum -{ +enum { BLOCK_MAIN1, BLOCK_MAIN2, BLOCK_MAIN3, @@ -48,312 +45,311 @@ enum BLOCKS_NUM }; -enum -{ - CMD_READ_ARRAY = 0xff, - CMD_IID = 0x90, - CMD_READ_STATUS = 0x70, - CMD_CLEAR_STATUS = 0x50, - CMD_ERASE_SETUP = 0x20, - CMD_ERASE_CONFIRM = 0xd0, - CMD_ERASE_SUSPEND = 0xb0, - CMD_PROGRAM_SETUP = 0x40, +enum { + CMD_READ_ARRAY = 0xff, + CMD_IID = 0x90, + CMD_READ_STATUS = 0x70, + CMD_CLEAR_STATUS = 0x50, + CMD_ERASE_SETUP = 0x20, + CMD_ERASE_CONFIRM = 0xd0, + CMD_ERASE_SUSPEND = 0xb0, + CMD_PROGRAM_SETUP = 0x40, CMD_PROGRAM_SETUP_ALT = 0x10 }; +typedef struct flash_t { + uint8_t command; + uint8_t status; + uint8_t pad; + uint8_t flags; + uint8_t *array; -typedef struct flash_t -{ - uint8_t command, status, - pad, flags, - *array; + uint16_t flash_id; + uint16_t pad16; - uint16_t flash_id, pad16; + uint32_t program_addr; + uint32_t block_start[BLOCKS_NUM]; + uint32_t block_end[BLOCKS_NUM]; + uint32_t block_len[BLOCKS_NUM]; - uint32_t program_addr, - block_start[BLOCKS_NUM], block_end[BLOCKS_NUM], - block_len[BLOCKS_NUM]; - - mem_mapping_t mapping[4], mapping_h[16]; + mem_mapping_t mapping[4]; + mem_mapping_t mapping_h[16]; } flash_t; - -static char flash_path[1024]; - +static char flash_path[1024]; static uint8_t -flash_read(uint32_t addr, void *p) +flash_read(uint32_t addr, void *priv) { - flash_t *dev = (flash_t *) p; - uint8_t ret = 0xff; + const flash_t *dev = (flash_t *) priv; + uint8_t ret = 0xff; if (dev->flags & FLAG_INV_A16) - addr ^= 0x10000; + addr ^= 0x10000; addr &= biosmask; switch (dev->command) { - case CMD_READ_ARRAY: - default: - ret = dev->array[addr]; - break; + default: + case CMD_READ_ARRAY: + ret = dev->array[addr]; + break; - case CMD_IID: - if (addr & 1) - ret = dev->flash_id & 0xff; - else - ret = 0x89; - break; + case CMD_IID: + if (addr & 1) + ret = dev->flash_id & 0xff; + else + ret = 0x89; + break; - case CMD_READ_STATUS: - ret = dev->status; - break; + case CMD_READ_STATUS: + ret = dev->status; + break; } return ret; } - static uint16_t -flash_readw(uint32_t addr, void *p) +flash_readw(uint32_t addr, void *priv) { - flash_t *dev = (flash_t *) p; - uint16_t *q; - uint16_t ret = 0xffff; + flash_t *dev = (flash_t *) priv; + const uint16_t *q; + uint16_t ret = 0xffff; if (dev->flags & FLAG_INV_A16) - addr ^= 0x10000; + addr ^= 0x10000; addr &= biosmask; if (dev->flags & FLAG_WORD) - addr &= 0xfffffffe; + addr &= 0xfffffffe; - q = (uint16_t *)&(dev->array[addr]); + q = (uint16_t *) &(dev->array[addr]); ret = *q; - if (dev->flags & FLAG_WORD) switch (dev->command) { - case CMD_READ_ARRAY: - default: - break; + if (dev->flags & FLAG_WORD) + switch (dev->command) { + default: + case CMD_READ_ARRAY: + break; - case CMD_IID: - if (addr & 2) - ret = dev->flash_id; - else - ret = 0x0089; - break; + case CMD_IID: + if (addr & 2) + ret = dev->flash_id; + else + ret = 0x0089; + break; - case CMD_READ_STATUS: - ret = dev->status; - break; - } + case CMD_READ_STATUS: + ret = dev->status; + break; + } return ret; } - static uint32_t -flash_readl(uint32_t addr, void *p) +flash_readl(uint32_t addr, void *priv) { - flash_t *dev = (flash_t *)p; - uint32_t *q; + flash_t *dev = (flash_t *) priv; + const uint32_t *q; if (dev->flags & FLAG_INV_A16) - addr ^= 0x10000; + addr ^= 0x10000; addr &= biosmask; - q = (uint32_t *)&(dev->array[addr]); + q = (uint32_t *) &(dev->array[addr]); return *q; } - static void -flash_write(uint32_t addr, uint8_t val, void *p) +flash_write(uint32_t addr, uint8_t val, void *priv) { - flash_t *dev = (flash_t *) p; - int i; + flash_t *dev = (flash_t *) priv; uint32_t bb_mask = biosmask & 0xffffe000; if (biosmask == 0x7ffff) - bb_mask &= 0xffff8000; + bb_mask &= 0xffff8000; else if (biosmask == 0x3ffff) - bb_mask &= 0xffffc000; + bb_mask &= 0xffffc000; if (dev->flags & FLAG_INV_A16) - addr ^= 0x10000; + addr ^= 0x10000; addr &= biosmask; switch (dev->command) { - case CMD_ERASE_SETUP: - if (val == CMD_ERASE_CONFIRM) { - for (i = 0; i < 6; i++) { - if ((i == dev->program_addr) && (addr >= dev->block_start[i]) && (addr <= dev->block_end[i])) - memset(&(dev->array[dev->block_start[i]]), 0xff, dev->block_len[i]); - } + case CMD_ERASE_SETUP: + if (val == CMD_ERASE_CONFIRM) { + for (uint8_t i = 0; i < 6; i++) { + if ((i == dev->program_addr) && (addr >= dev->block_start[i]) && (addr <= dev->block_end[i])) + memset(&(dev->array[dev->block_start[i]]), 0xff, dev->block_len[i]); + } - dev->status = 0x80; - } - dev->command = CMD_READ_STATUS; - break; + dev->status = 0x80; + } + dev->command = CMD_READ_STATUS; + break; - case CMD_PROGRAM_SETUP: - case CMD_PROGRAM_SETUP_ALT: - if (((addr & bb_mask) != (dev->block_start[6] & bb_mask)) && (addr == dev->program_addr)) - dev->array[addr] = val; - dev->command = CMD_READ_STATUS; - dev->status = 0x80; - break; + case CMD_PROGRAM_SETUP: + case CMD_PROGRAM_SETUP_ALT: + if (((addr & bb_mask) != (dev->block_start[6] & bb_mask)) && (addr == dev->program_addr)) + dev->array[addr] = val; + dev->command = CMD_READ_STATUS; + dev->status = 0x80; + break; - default: - dev->command = val; - switch (val) { - case CMD_CLEAR_STATUS: - dev->status = 0; - break; - case CMD_ERASE_SETUP: - for (i = 0; i < 7; i++) { - if ((addr >= dev->block_start[i]) && (addr <= dev->block_end[i])) - dev->program_addr = i; - } - break; - case CMD_PROGRAM_SETUP: - case CMD_PROGRAM_SETUP_ALT: - dev->program_addr = addr; - break; - } + default: + dev->command = val; + switch (val) { + case CMD_CLEAR_STATUS: + dev->status = 0; + break; + case CMD_ERASE_SETUP: + for (uint8_t i = 0; i < 7; i++) { + if ((addr >= dev->block_start[i]) && (addr <= dev->block_end[i])) + dev->program_addr = i; + } + break; + case CMD_PROGRAM_SETUP: + case CMD_PROGRAM_SETUP_ALT: + dev->program_addr = addr; + break; + + default: + break; + } } } - static void -flash_writew(uint32_t addr, uint16_t val, void *p) +flash_writew(uint32_t addr, uint16_t val, void *priv) { - flash_t *dev = (flash_t *) p; - int i; + flash_t *dev = (flash_t *) priv; uint32_t bb_mask = biosmask & 0xffffe000; if (biosmask == 0x7ffff) - bb_mask &= 0xffff8000; + bb_mask &= 0xffff8000; else if (biosmask == 0x3ffff) - bb_mask &= 0xffffc000; + bb_mask &= 0xffffc000; if (dev->flags & FLAG_INV_A16) - addr ^= 0x10000; + addr ^= 0x10000; addr &= biosmask; - if (dev->flags & FLAG_WORD) switch (dev->command) { - case CMD_ERASE_SETUP: - if (val == CMD_ERASE_CONFIRM) { - for (i = 0; i < 6; i++) { - if ((i == dev->program_addr) && (addr >= dev->block_start[i]) && (addr <= dev->block_end[i])) - memset(&(dev->array[dev->block_start[i]]), 0xff, dev->block_len[i]); - } + if (dev->flags & FLAG_WORD) + switch (dev->command) { + case CMD_ERASE_SETUP: + if (val == CMD_ERASE_CONFIRM) { + for (uint8_t i = 0; i < 6; i++) { + if ((i == dev->program_addr) && (addr >= dev->block_start[i]) && (addr <= dev->block_end[i])) + memset(&(dev->array[dev->block_start[i]]), 0xff, dev->block_len[i]); + } - dev->status = 0x80; - } - dev->command = CMD_READ_STATUS; - break; + dev->status = 0x80; + } + dev->command = CMD_READ_STATUS; + break; - case CMD_PROGRAM_SETUP: - case CMD_PROGRAM_SETUP_ALT: - if (((addr & bb_mask) != (dev->block_start[6] & bb_mask)) && (addr == dev->program_addr)) - *(uint16_t *) (&dev->array[addr]) = val; - dev->command = CMD_READ_STATUS; - dev->status = 0x80; - break; + case CMD_PROGRAM_SETUP: + case CMD_PROGRAM_SETUP_ALT: + if (((addr & bb_mask) != (dev->block_start[6] & bb_mask)) && (addr == dev->program_addr)) + *(uint16_t *) (&dev->array[addr]) = val; + dev->command = CMD_READ_STATUS; + dev->status = 0x80; + break; - default: - dev->command = val & 0xff; - switch (val) { - case CMD_CLEAR_STATUS: - dev->status = 0; - break; - case CMD_ERASE_SETUP: - for (i = 0; i < 7; i++) { - if ((addr >= dev->block_start[i]) && (addr <= dev->block_end[i])) - dev->program_addr = i; - } - break; - case CMD_PROGRAM_SETUP: - case CMD_PROGRAM_SETUP_ALT: - dev->program_addr = addr; - break; - } - } + default: + dev->command = val & 0xff; + switch (val) { + case CMD_CLEAR_STATUS: + dev->status = 0; + break; + case CMD_ERASE_SETUP: + for (uint8_t i = 0; i < 7; i++) { + if ((addr >= dev->block_start[i]) && (addr <= dev->block_end[i])) + dev->program_addr = i; + } + break; + case CMD_PROGRAM_SETUP: + case CMD_PROGRAM_SETUP_ALT: + dev->program_addr = addr; + break; + + default: + break; + } + } } - static void -flash_writel(uint32_t addr, uint32_t val, void *p) +flash_writel(UNUSED(uint32_t addr), UNUSED(uint32_t val), UNUSED(void *priv)) { #if 0 - flash_writew(addr, val & 0xffff, p); - flash_writew(addr + 2, (val >> 16) & 0xffff, p); + flash_writew(addr, val & 0xffff, priv); + flash_writew(addr + 2, (val >> 16) & 0xffff, priv); #endif } - static void intel_flash_add_mappings(flash_t *dev) { - int max = 2, i = 0; - uint32_t base, fbase; + uint8_t max = 2; + uint32_t base; + uint32_t fbase; uint32_t sub = 0x20000; if (biosmask == 0x7ffff) { - sub = 0x80000; - max = 8; + sub = 0x80000; + max = 8; } else if (biosmask == 0x3ffff) { - sub = 0x40000; - max = 4; + sub = 0x40000; + max = 4; } - for (i = 0; i < max; i++) { - if (biosmask == 0x7ffff) - base = 0x80000 + (i << 16); - else if (biosmask == 0x3ffff) - base = 0xc0000 + (i << 16); - else - base = 0xe0000 + (i << 16); + for (uint8_t i = 0; i < max; i++) { + if (biosmask == 0x7ffff) + base = 0x80000 + (i << 16); + else if (biosmask == 0x3ffff) + base = 0xc0000 + (i << 16); + else + base = 0xe0000 + (i << 16); - fbase = base & biosmask; - if (dev->flags & FLAG_INV_A16) - fbase ^= 0x10000; + fbase = base & biosmask; + if (dev->flags & FLAG_INV_A16) + fbase ^= 0x10000; - memcpy(&dev->array[fbase], &rom[base & biosmask], 0x10000); + memcpy(&dev->array[fbase], &rom[base & biosmask], 0x10000); - if ((max == 2) || (i >= 2)) { - mem_mapping_add(&(dev->mapping[i]), base, 0x10000, - flash_read, flash_readw, flash_readl, - flash_write, flash_writew, flash_writel, - dev->array + fbase, MEM_MAPPING_EXTERNAL|MEM_MAPPING_ROM|MEM_MAPPING_ROMCS, (void *) dev); - } - mem_mapping_add(&(dev->mapping_h[i]), (base | 0xfff00000) - sub, 0x10000, - flash_read, flash_readw, flash_readl, - flash_write, flash_writew, flash_writel, - dev->array + fbase, MEM_MAPPING_EXTERNAL|MEM_MAPPING_ROM|MEM_MAPPING_ROMCS, (void *) dev); - mem_mapping_add(&(dev->mapping_h[i + max]), (base | 0xfff00000), 0x10000, - flash_read, flash_readw, flash_readl, - flash_write, flash_writew, flash_writel, - dev->array + fbase, MEM_MAPPING_EXTERNAL|MEM_MAPPING_ROM|MEM_MAPPING_ROMCS, (void *) dev); + if ((max == 2) || (i >= 2)) { + mem_mapping_add(&(dev->mapping[i]), base, 0x10000, + flash_read, flash_readw, flash_readl, + flash_write, flash_writew, flash_writel, + dev->array + fbase, MEM_MAPPING_EXTERNAL | MEM_MAPPING_ROM | MEM_MAPPING_ROMCS, (void *) dev); + } + mem_mapping_add(&(dev->mapping_h[i]), (base | 0xfff00000) - sub, 0x10000, + flash_read, flash_readw, flash_readl, + flash_write, flash_writew, flash_writel, + dev->array + fbase, MEM_MAPPING_EXTERNAL | MEM_MAPPING_ROM | MEM_MAPPING_ROMCS, (void *) dev); + mem_mapping_add(&(dev->mapping_h[i + max]), (base | 0xfff00000), 0x10000, + flash_read, flash_readw, flash_readl, + flash_write, flash_writew, flash_writel, + dev->array + fbase, MEM_MAPPING_EXTERNAL | MEM_MAPPING_ROM | MEM_MAPPING_ROMCS, (void *) dev); } } - static void intel_flash_reset(void *priv) { flash_t *dev = (flash_t *) priv; dev->command = CMD_READ_ARRAY; - dev->status = 0; + dev->status = 0; } - static void * intel_flash_init(const device_t *info) { - FILE *f; + FILE *fp; flash_t *dev; - uint8_t type = info->local & 0xff; + uint8_t type = info->local & 0xff; dev = malloc(sizeof(flash_t)); memset(dev, 0, sizeof(flash_t)); @@ -369,190 +365,189 @@ intel_flash_init(const device_t *info) memset(dev->array, 0xff, biosmask + 1); switch (biosmask) { - case 0x7ffff: - if (dev->flags & FLAG_WORD) - dev->flash_id = (dev->flags & FLAG_BXB) ? 0x4471 : 0x4470; - else - dev->flash_id =(dev->flags & FLAG_BXB) ? 0x8A : 0x89; + case 0x7ffff: + if (dev->flags & FLAG_WORD) + dev->flash_id = (dev->flags & FLAG_BXB) ? 0x4471 : 0x4470; + else + dev->flash_id = (dev->flags & FLAG_BXB) ? 0x8A : 0x89; - /* The block lengths are the same both flash types. */ - dev->block_len[BLOCK_MAIN1] = 0x20000; - dev->block_len[BLOCK_MAIN2] = 0x20000; - dev->block_len[BLOCK_MAIN3] = 0x20000; - dev->block_len[BLOCK_MAIN4] = 0x18000; - dev->block_len[BLOCK_DATA1] = 0x02000; - dev->block_len[BLOCK_DATA2] = 0x02000; - dev->block_len[BLOCK_BOOT] = 0x04000; + /* The block lengths are the same both flash types. */ + dev->block_len[BLOCK_MAIN1] = 0x20000; + dev->block_len[BLOCK_MAIN2] = 0x20000; + dev->block_len[BLOCK_MAIN3] = 0x20000; + dev->block_len[BLOCK_MAIN4] = 0x18000; + dev->block_len[BLOCK_DATA1] = 0x02000; + dev->block_len[BLOCK_DATA2] = 0x02000; + dev->block_len[BLOCK_BOOT] = 0x04000; - if (dev->flags & FLAG_BXB) { /* 28F004BX-T/28F400BX-B */ - dev->block_start[BLOCK_BOOT] = 0x00000; /* MAIN BLOCK 1 */ - dev->block_end[BLOCK_BOOT] = 0x1ffff; - dev->block_start[BLOCK_DATA2] = 0x20000; /* MAIN BLOCK 2 */ - dev->block_end[BLOCK_DATA2] = 0x3ffff; - dev->block_start[BLOCK_DATA1] = 0x40000; /* MAIN BLOCK 3 */ - dev->block_end[BLOCK_DATA1] = 0x5ffff; - dev->block_start[BLOCK_MAIN4] = 0x60000; /* MAIN BLOCK 4 */ - dev->block_end[BLOCK_MAIN4] = 0x77fff; - dev->block_start[BLOCK_MAIN3] = 0x78000; /* DATA AREA 1 BLOCK */ - dev->block_end[BLOCK_MAIN3] = 0x79fff; - dev->block_start[BLOCK_MAIN2] = 0x7a000; /* DATA AREA 2 BLOCK */ - dev->block_end[BLOCK_MAIN2] = 0x7bfff; - dev->block_start[BLOCK_MAIN1] = 0x7c000; /* BOOT BLOCK */ - dev->block_end[BLOCK_MAIN1] = 0x7ffff; - } else { - dev->block_start[BLOCK_MAIN1] = 0x00000; /* MAIN BLOCK 1 */ - dev->block_end[BLOCK_MAIN1] = 0x1ffff; - dev->block_start[BLOCK_MAIN2] = 0x20000; /* MAIN BLOCK 2 */ - dev->block_end[BLOCK_MAIN2] = 0x3ffff; - dev->block_start[BLOCK_MAIN3] = 0x40000; /* MAIN BLOCK 3 */ - dev->block_end[BLOCK_MAIN3] = 0x5ffff; - dev->block_start[BLOCK_MAIN4] = 0x60000; /* MAIN BLOCK 4 */ - dev->block_end[BLOCK_MAIN4] = 0x77fff; - dev->block_start[BLOCK_DATA1] = 0x78000; /* DATA AREA 1 BLOCK */ - dev->block_end[BLOCK_DATA1] = 0x79fff; - dev->block_start[BLOCK_DATA2] = 0x7a000; /* DATA AREA 2 BLOCK */ - dev->block_end[BLOCK_DATA2] = 0x7bfff; - dev->block_start[BLOCK_BOOT] = 0x7c000; /* BOOT BLOCK */ - dev->block_end[BLOCK_BOOT] = 0x7ffff; - } - break; + if (dev->flags & FLAG_BXB) { /* 28F004BX-T/28F400BX-B */ + dev->block_start[BLOCK_BOOT] = 0x00000; /* MAIN BLOCK 1 */ + dev->block_end[BLOCK_BOOT] = 0x1ffff; + dev->block_start[BLOCK_DATA2] = 0x20000; /* MAIN BLOCK 2 */ + dev->block_end[BLOCK_DATA2] = 0x3ffff; + dev->block_start[BLOCK_DATA1] = 0x40000; /* MAIN BLOCK 3 */ + dev->block_end[BLOCK_DATA1] = 0x5ffff; + dev->block_start[BLOCK_MAIN4] = 0x60000; /* MAIN BLOCK 4 */ + dev->block_end[BLOCK_MAIN4] = 0x77fff; + dev->block_start[BLOCK_MAIN3] = 0x78000; /* DATA AREA 1 BLOCK */ + dev->block_end[BLOCK_MAIN3] = 0x79fff; + dev->block_start[BLOCK_MAIN2] = 0x7a000; /* DATA AREA 2 BLOCK */ + dev->block_end[BLOCK_MAIN2] = 0x7bfff; + dev->block_start[BLOCK_MAIN1] = 0x7c000; /* BOOT BLOCK */ + dev->block_end[BLOCK_MAIN1] = 0x7ffff; + } else { + dev->block_start[BLOCK_MAIN1] = 0x00000; /* MAIN BLOCK 1 */ + dev->block_end[BLOCK_MAIN1] = 0x1ffff; + dev->block_start[BLOCK_MAIN2] = 0x20000; /* MAIN BLOCK 2 */ + dev->block_end[BLOCK_MAIN2] = 0x3ffff; + dev->block_start[BLOCK_MAIN3] = 0x40000; /* MAIN BLOCK 3 */ + dev->block_end[BLOCK_MAIN3] = 0x5ffff; + dev->block_start[BLOCK_MAIN4] = 0x60000; /* MAIN BLOCK 4 */ + dev->block_end[BLOCK_MAIN4] = 0x77fff; + dev->block_start[BLOCK_DATA1] = 0x78000; /* DATA AREA 1 BLOCK */ + dev->block_end[BLOCK_DATA1] = 0x79fff; + dev->block_start[BLOCK_DATA2] = 0x7a000; /* DATA AREA 2 BLOCK */ + dev->block_end[BLOCK_DATA2] = 0x7bfff; + dev->block_start[BLOCK_BOOT] = 0x7c000; /* BOOT BLOCK */ + dev->block_end[BLOCK_BOOT] = 0x7ffff; + } + break; - case 0x3ffff: - if (dev->flags & FLAG_WORD) - dev->flash_id = (dev->flags & FLAG_BXB) ? 0x2275 : 0x2274; - else - dev->flash_id = (dev->flags & FLAG_BXB) ? 0x7D : 0x7C; + case 0x3ffff: + if (dev->flags & FLAG_WORD) + dev->flash_id = (dev->flags & FLAG_BXB) ? 0x2275 : 0x2274; + else + dev->flash_id = (dev->flags & FLAG_BXB) ? 0x7D : 0x7C; - /* The block lengths are the same both flash types. */ - dev->block_len[BLOCK_MAIN1] = 0x20000; - dev->block_len[BLOCK_MAIN2] = 0x18000; - dev->block_len[BLOCK_MAIN3] = 0x00000; - dev->block_len[BLOCK_MAIN4] = 0x00000; - dev->block_len[BLOCK_DATA1] = 0x02000; - dev->block_len[BLOCK_DATA2] = 0x02000; - dev->block_len[BLOCK_BOOT] = 0x04000; + /* The block lengths are the same both flash types. */ + dev->block_len[BLOCK_MAIN1] = 0x20000; + dev->block_len[BLOCK_MAIN2] = 0x18000; + dev->block_len[BLOCK_MAIN3] = 0x00000; + dev->block_len[BLOCK_MAIN4] = 0x00000; + dev->block_len[BLOCK_DATA1] = 0x02000; + dev->block_len[BLOCK_DATA2] = 0x02000; + dev->block_len[BLOCK_BOOT] = 0x04000; - if (dev->flags & FLAG_BXB) { /* 28F002BX-B/28F200BX-B */ - dev->block_start[BLOCK_MAIN1] = 0x20000; /* MAIN BLOCK 1 */ - dev->block_end[BLOCK_MAIN1] = 0x3ffff; - dev->block_start[BLOCK_MAIN2] = 0x08000; /* MAIN BLOCK 2 */ - dev->block_end[BLOCK_MAIN2] = 0x1ffff; - dev->block_start[BLOCK_MAIN3] = 0xfffff; /* MAIN BLOCK 3 */ - dev->block_end[BLOCK_MAIN3] = 0xfffff; - dev->block_start[BLOCK_MAIN4] = 0xfffff; /* MAIN BLOCK 4 */ - dev->block_end[BLOCK_MAIN4] = 0xfffff; - dev->block_start[BLOCK_DATA1] = 0x06000; /* DATA AREA 1 BLOCK */ - dev->block_end[BLOCK_DATA1] = 0x07fff; - dev->block_start[BLOCK_DATA2] = 0x04000; /* DATA AREA 2 BLOCK */ - dev->block_end[BLOCK_DATA2] = 0x05fff; - dev->block_start[BLOCK_BOOT] = 0x00000; /* BOOT BLOCK */ - dev->block_end[BLOCK_BOOT] = 0x03fff; - } else { /* 28F002BX-T/28F200BX-T */ - dev->block_start[BLOCK_MAIN1] = 0x00000; /* MAIN BLOCK 1 */ - dev->block_end[BLOCK_MAIN1] = 0x1ffff; - dev->block_start[BLOCK_MAIN2] = 0x20000; /* MAIN BLOCK 2 */ - dev->block_end[BLOCK_MAIN2] = 0x37fff; - dev->block_start[BLOCK_MAIN3] = 0xfffff; /* MAIN BLOCK 3 */ - dev->block_end[BLOCK_MAIN3] = 0xfffff; - dev->block_start[BLOCK_MAIN4] = 0xfffff; /* MAIN BLOCK 4 */ - dev->block_end[BLOCK_MAIN4] = 0xfffff; - dev->block_start[BLOCK_DATA1] = 0x38000; /* DATA AREA 1 BLOCK */ - dev->block_end[BLOCK_DATA1] = 0x39fff; - dev->block_start[BLOCK_DATA2] = 0x3a000; /* DATA AREA 2 BLOCK */ - dev->block_end[BLOCK_DATA2] = 0x3bfff; - dev->block_start[BLOCK_BOOT] = 0x3c000; /* BOOT BLOCK */ - dev->block_end[BLOCK_BOOT] = 0x3ffff; - } - break; + if (dev->flags & FLAG_BXB) { /* 28F002BX-B/28F200BX-B */ + dev->block_start[BLOCK_MAIN1] = 0x20000; /* MAIN BLOCK 1 */ + dev->block_end[BLOCK_MAIN1] = 0x3ffff; + dev->block_start[BLOCK_MAIN2] = 0x08000; /* MAIN BLOCK 2 */ + dev->block_end[BLOCK_MAIN2] = 0x1ffff; + dev->block_start[BLOCK_MAIN3] = 0xfffff; /* MAIN BLOCK 3 */ + dev->block_end[BLOCK_MAIN3] = 0xfffff; + dev->block_start[BLOCK_MAIN4] = 0xfffff; /* MAIN BLOCK 4 */ + dev->block_end[BLOCK_MAIN4] = 0xfffff; + dev->block_start[BLOCK_DATA1] = 0x06000; /* DATA AREA 1 BLOCK */ + dev->block_end[BLOCK_DATA1] = 0x07fff; + dev->block_start[BLOCK_DATA2] = 0x04000; /* DATA AREA 2 BLOCK */ + dev->block_end[BLOCK_DATA2] = 0x05fff; + dev->block_start[BLOCK_BOOT] = 0x00000; /* BOOT BLOCK */ + dev->block_end[BLOCK_BOOT] = 0x03fff; + } else { /* 28F002BX-T/28F200BX-T */ + dev->block_start[BLOCK_MAIN1] = 0x00000; /* MAIN BLOCK 1 */ + dev->block_end[BLOCK_MAIN1] = 0x1ffff; + dev->block_start[BLOCK_MAIN2] = 0x20000; /* MAIN BLOCK 2 */ + dev->block_end[BLOCK_MAIN2] = 0x37fff; + dev->block_start[BLOCK_MAIN3] = 0xfffff; /* MAIN BLOCK 3 */ + dev->block_end[BLOCK_MAIN3] = 0xfffff; + dev->block_start[BLOCK_MAIN4] = 0xfffff; /* MAIN BLOCK 4 */ + dev->block_end[BLOCK_MAIN4] = 0xfffff; + dev->block_start[BLOCK_DATA1] = 0x38000; /* DATA AREA 1 BLOCK */ + dev->block_end[BLOCK_DATA1] = 0x39fff; + dev->block_start[BLOCK_DATA2] = 0x3a000; /* DATA AREA 2 BLOCK */ + dev->block_end[BLOCK_DATA2] = 0x3bfff; + dev->block_start[BLOCK_BOOT] = 0x3c000; /* BOOT BLOCK */ + dev->block_end[BLOCK_BOOT] = 0x3ffff; + } + break; - default: - dev->flash_id = (type & FLAG_BXB) ? 0x95 : 0x94; + default: + dev->flash_id = (type & FLAG_BXB) ? 0x95 : 0x94; - /* The block lengths are the same both flash types. */ - dev->block_len[BLOCK_MAIN1] = 0x1c000; - dev->block_len[BLOCK_MAIN2] = 0x00000; - dev->block_len[BLOCK_MAIN3] = 0x00000; - dev->block_len[BLOCK_MAIN4] = 0x00000; - dev->block_len[BLOCK_DATA1] = 0x01000; - dev->block_len[BLOCK_DATA2] = 0x01000; - dev->block_len[BLOCK_BOOT] = 0x02000; + /* The block lengths are the same both flash types. */ + dev->block_len[BLOCK_MAIN1] = 0x1c000; + dev->block_len[BLOCK_MAIN2] = 0x00000; + dev->block_len[BLOCK_MAIN3] = 0x00000; + dev->block_len[BLOCK_MAIN4] = 0x00000; + dev->block_len[BLOCK_DATA1] = 0x01000; + dev->block_len[BLOCK_DATA2] = 0x01000; + dev->block_len[BLOCK_BOOT] = 0x02000; - if (dev->flags & FLAG_BXB) { /* 28F001BX-B/28F100BX-B */ - dev->block_start[BLOCK_MAIN1] = 0x04000; /* MAIN BLOCK 1 */ - dev->block_end[BLOCK_MAIN1] = 0x1ffff; - dev->block_start[BLOCK_MAIN2] = 0xfffff; /* MAIN BLOCK 2 */ - dev->block_end[BLOCK_MAIN2] = 0xfffff; - dev->block_start[BLOCK_MAIN3] = 0xfffff; /* MAIN BLOCK 3 */ - dev->block_end[BLOCK_MAIN3] = 0xfffff; - dev->block_start[BLOCK_MAIN4] = 0xfffff; /* MAIN BLOCK 4 */ - dev->block_end[BLOCK_MAIN4] = 0xfffff; - dev->block_start[BLOCK_DATA1] = 0x02000; /* DATA AREA 1 BLOCK */ - dev->block_end[BLOCK_DATA1] = 0x02fff; - dev->block_start[BLOCK_DATA2] = 0x03000; /* DATA AREA 2 BLOCK */ - dev->block_end[BLOCK_DATA2] = 0x03fff; - dev->block_start[BLOCK_BOOT] = 0x00000; /* BOOT BLOCK */ - dev->block_end[BLOCK_BOOT] = 0x01fff; - } else { /* 28F001BX-T/28F100BX-T */ - dev->block_start[BLOCK_MAIN1] = 0x00000; /* MAIN BLOCK 1 */ - dev->block_end[BLOCK_MAIN1] = 0x1bfff; - dev->block_start[BLOCK_MAIN2] = 0xfffff; /* MAIN BLOCK 2 */ - dev->block_end[BLOCK_MAIN2] = 0xfffff; - dev->block_start[BLOCK_MAIN3] = 0xfffff; /* MAIN BLOCK 3 */ - dev->block_end[BLOCK_MAIN3] = 0xfffff; - dev->block_start[BLOCK_MAIN4] = 0xfffff; /* MAIN BLOCK 4 */ - dev->block_end[BLOCK_MAIN4] = 0xfffff; - dev->block_start[BLOCK_DATA1] = 0x1c000; /* DATA AREA 1 BLOCK */ - dev->block_end[BLOCK_DATA1] = 0x1cfff; - dev->block_start[BLOCK_DATA2] = 0x1d000; /* DATA AREA 2 BLOCK */ - dev->block_end[BLOCK_DATA2] = 0x1dfff; - dev->block_start[BLOCK_BOOT] = 0x1e000; /* BOOT BLOCK */ - dev->block_end[BLOCK_BOOT] = 0x1ffff; - } - break; + if (dev->flags & FLAG_BXB) { /* 28F001BX-B/28F100BX-B */ + dev->block_start[BLOCK_MAIN1] = 0x04000; /* MAIN BLOCK 1 */ + dev->block_end[BLOCK_MAIN1] = 0x1ffff; + dev->block_start[BLOCK_MAIN2] = 0xfffff; /* MAIN BLOCK 2 */ + dev->block_end[BLOCK_MAIN2] = 0xfffff; + dev->block_start[BLOCK_MAIN3] = 0xfffff; /* MAIN BLOCK 3 */ + dev->block_end[BLOCK_MAIN3] = 0xfffff; + dev->block_start[BLOCK_MAIN4] = 0xfffff; /* MAIN BLOCK 4 */ + dev->block_end[BLOCK_MAIN4] = 0xfffff; + dev->block_start[BLOCK_DATA1] = 0x02000; /* DATA AREA 1 BLOCK */ + dev->block_end[BLOCK_DATA1] = 0x02fff; + dev->block_start[BLOCK_DATA2] = 0x03000; /* DATA AREA 2 BLOCK */ + dev->block_end[BLOCK_DATA2] = 0x03fff; + dev->block_start[BLOCK_BOOT] = 0x00000; /* BOOT BLOCK */ + dev->block_end[BLOCK_BOOT] = 0x01fff; + } else { /* 28F001BX-T/28F100BX-T */ + dev->block_start[BLOCK_MAIN1] = 0x00000; /* MAIN BLOCK 1 */ + dev->block_end[BLOCK_MAIN1] = 0x1bfff; + dev->block_start[BLOCK_MAIN2] = 0xfffff; /* MAIN BLOCK 2 */ + dev->block_end[BLOCK_MAIN2] = 0xfffff; + dev->block_start[BLOCK_MAIN3] = 0xfffff; /* MAIN BLOCK 3 */ + dev->block_end[BLOCK_MAIN3] = 0xfffff; + dev->block_start[BLOCK_MAIN4] = 0xfffff; /* MAIN BLOCK 4 */ + dev->block_end[BLOCK_MAIN4] = 0xfffff; + dev->block_start[BLOCK_DATA1] = 0x1c000; /* DATA AREA 1 BLOCK */ + dev->block_end[BLOCK_DATA1] = 0x1cfff; + dev->block_start[BLOCK_DATA2] = 0x1d000; /* DATA AREA 2 BLOCK */ + dev->block_end[BLOCK_DATA2] = 0x1dfff; + dev->block_start[BLOCK_BOOT] = 0x1e000; /* BOOT BLOCK */ + dev->block_end[BLOCK_BOOT] = 0x1ffff; + } + break; } intel_flash_add_mappings(dev); dev->command = CMD_READ_ARRAY; - dev->status = 0; + dev->status = 0; - f = nvr_fopen(flash_path, "rb"); - if (f) { - fread(&(dev->array[dev->block_start[BLOCK_MAIN1]]), dev->block_len[BLOCK_MAIN1], 1, f); - if (dev->block_len[BLOCK_MAIN2]) - fread(&(dev->array[dev->block_start[BLOCK_MAIN2]]), dev->block_len[BLOCK_MAIN2], 1, f); - if (dev->block_len[BLOCK_MAIN3]) - fread(&(dev->array[dev->block_start[BLOCK_MAIN3]]), dev->block_len[BLOCK_MAIN3], 1, f); - if (dev->block_len[BLOCK_MAIN4]) - fread(&(dev->array[dev->block_start[BLOCK_MAIN4]]), dev->block_len[BLOCK_MAIN4], 1, f); + fp = nvr_fopen(flash_path, "rb"); + if (fp) { + (void) !fread(&(dev->array[dev->block_start[BLOCK_MAIN1]]), dev->block_len[BLOCK_MAIN1], 1, fp); + if (dev->block_len[BLOCK_MAIN2]) + (void) !fread(&(dev->array[dev->block_start[BLOCK_MAIN2]]), dev->block_len[BLOCK_MAIN2], 1, fp); + if (dev->block_len[BLOCK_MAIN3]) + (void) !fread(&(dev->array[dev->block_start[BLOCK_MAIN3]]), dev->block_len[BLOCK_MAIN3], 1, fp); + if (dev->block_len[BLOCK_MAIN4]) + (void) !fread(&(dev->array[dev->block_start[BLOCK_MAIN4]]), dev->block_len[BLOCK_MAIN4], 1, fp); - fread(&(dev->array[dev->block_start[BLOCK_DATA1]]), dev->block_len[BLOCK_DATA1], 1, f); - fread(&(dev->array[dev->block_start[BLOCK_DATA2]]), dev->block_len[BLOCK_DATA2], 1, f); - fclose(f); + (void) !fread(&(dev->array[dev->block_start[BLOCK_DATA1]]), dev->block_len[BLOCK_DATA1], 1, fp); + (void) !fread(&(dev->array[dev->block_start[BLOCK_DATA2]]), dev->block_len[BLOCK_DATA2], 1, fp); + fclose(fp); } return dev; } - static void -intel_flash_close(void *p) +intel_flash_close(void *priv) { - FILE *f; - flash_t *dev = (flash_t *)p; + FILE *fp; + flash_t *dev = (flash_t *) priv; - f = nvr_fopen(flash_path, "wb"); - fwrite(&(dev->array[dev->block_start[BLOCK_MAIN1]]), dev->block_len[BLOCK_MAIN1], 1, f); + fp = nvr_fopen(flash_path, "wb"); + fwrite(&(dev->array[dev->block_start[BLOCK_MAIN1]]), dev->block_len[BLOCK_MAIN1], 1, fp); if (dev->block_len[BLOCK_MAIN2]) - fwrite(&(dev->array[dev->block_start[BLOCK_MAIN2]]), dev->block_len[BLOCK_MAIN2], 1, f); + fwrite(&(dev->array[dev->block_start[BLOCK_MAIN2]]), dev->block_len[BLOCK_MAIN2], 1, fp); if (dev->block_len[BLOCK_MAIN3]) - fwrite(&(dev->array[dev->block_start[BLOCK_MAIN3]]), dev->block_len[BLOCK_MAIN3], 1, f); + fwrite(&(dev->array[dev->block_start[BLOCK_MAIN3]]), dev->block_len[BLOCK_MAIN3], 1, fp); if (dev->block_len[BLOCK_MAIN4]) - fwrite(&(dev->array[dev->block_start[BLOCK_MAIN4]]), dev->block_len[BLOCK_MAIN4], 1, f); + fwrite(&(dev->array[dev->block_start[BLOCK_MAIN4]]), dev->block_len[BLOCK_MAIN4], 1, fp); - fwrite(&(dev->array[dev->block_start[BLOCK_DATA1]]), dev->block_len[BLOCK_DATA1], 1, f); - fwrite(&(dev->array[dev->block_start[BLOCK_DATA2]]), dev->block_len[BLOCK_DATA2], 1, f); - fclose(f); + fwrite(&(dev->array[dev->block_start[BLOCK_DATA1]]), dev->block_len[BLOCK_DATA1], 1, fp); + fwrite(&(dev->array[dev->block_start[BLOCK_DATA2]]), dev->block_len[BLOCK_DATA2], 1, fp); + fclose(fp); free(dev->array); dev->array = NULL; @@ -560,40 +555,45 @@ intel_flash_close(void *p) free(dev); } - /* For AMI BIOS'es - Intel 28F001BXT with A16 pin inverted. */ -const device_t intel_flash_bxt_ami_device = -{ - "Intel 28F001BXT/28F002BXT/28F004BXT Flash BIOS", - "intel_flash_bxt_ami", - DEVICE_PCI, - FLAG_INV_A16, - intel_flash_init, - intel_flash_close, - intel_flash_reset, - { NULL }, NULL, NULL, NULL +const device_t intel_flash_bxt_ami_device = { + .name = "Intel 28F001BXT/28F002BXT/28F004BXT Flash BIOS", + .internal_name = "intel_flash_bxt_ami", + .flags = DEVICE_PCI, + .local = FLAG_INV_A16, + .init = intel_flash_init, + .close = intel_flash_close, + .reset = intel_flash_reset, + { .available = NULL }, + .speed_changed = NULL, + .force_redraw = NULL, + .config = NULL }; - -const device_t intel_flash_bxt_device = -{ - "Intel 28F001BXT/28F002BXT/28F004BXT Flash BIOS", - "intel_flash_bxt", - DEVICE_PCI, 0, - intel_flash_init, - intel_flash_close, - intel_flash_reset, - { NULL }, NULL, NULL, NULL +const device_t intel_flash_bxt_device = { + .name = "Intel 28F001BXT/28F002BXT/28F004BXT Flash BIOS", + .internal_name = "intel_flash_bxt", + .flags = DEVICE_PCI, + .local = 0, + .init = intel_flash_init, + .close = intel_flash_close, + .reset = intel_flash_reset, + { .available = NULL }, + .speed_changed = NULL, + .force_redraw = NULL, + .config = NULL }; - -const device_t intel_flash_bxb_device = -{ - "Intel 28F001BXB/28F002BXB/28F004BXB Flash BIOS", - "intel_flash_bxb", - DEVICE_PCI, FLAG_BXB, - intel_flash_init, - intel_flash_close, - intel_flash_reset, - { NULL }, NULL, NULL, NULL +const device_t intel_flash_bxb_device = { + .name = "Intel 28F001BXB/28F002BXB/28F004BXB Flash BIOS", + .internal_name = "intel_flash_bxb", + .flags = DEVICE_PCI, + .local = FLAG_BXB, + .init = intel_flash_init, + .close = intel_flash_close, + .reset = intel_flash_reset, + { .available = NULL }, + .speed_changed = NULL, + .force_redraw = NULL, + .config = NULL }; diff --git a/src/mem/mem.c b/src/mem/mem.c index ae6c9a0fc..0b002b302 100644 --- a/src/mem/mem.c +++ b/src/mem/mem.c @@ -1,20 +1,20 @@ /* - * 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. + * 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. + * This file is part of the 86Box distribution. * - * Memory handling and MMU. + * Memory handling and MMU. * - * Authors: Sarah Walker, - * Miran Grca, - * Fred N. van Kempen, + * Authors: Sarah Walker, + * Miran Grca, + * Fred N. van Kempen, * - * Copyright 2008-2020 Sarah Walker. - * Copyright 2016-2020 Miran Grca. - * Copyright 2017-2020 Fred N. van Kempen. + * Copyright 2008-2020 Sarah Walker. + * Copyright 2016-2020 Miran Grca. + * Copyright 2017-2020 Fred N. van Kempen. */ #include #include @@ -29,6 +29,7 @@ #include "cpu.h" #include "x86_ops.h" #include "x86.h" +#include "x86seg_common.h" #include <86box/machine.h> #include <86box/m_xt_xi8088.h> #include <86box/config.h> @@ -36,308 +37,304 @@ #include <86box/mem.h> #include <86box/plat.h> #include <86box/rom.h> +#include <86box/gdbstub.h> #ifdef USE_DYNAREC -# include "codegen_public.h" +# include "codegen_public.h" #else -#ifdef USE_NEW_DYNAREC -# define PAGE_MASK_SHIFT 6 -#else -# define PAGE_MASK_INDEX_MASK 3 -# define PAGE_MASK_INDEX_SHIFT 10 -# define PAGE_MASK_SHIFT 4 -#endif -# define PAGE_MASK_MASK 63 +# ifdef USE_NEW_DYNAREC +# define PAGE_MASK_SHIFT 6 +# else +# define PAGE_MASK_INDEX_MASK 3 +# define PAGE_MASK_INDEX_SHIFT 10 +# define PAGE_MASK_SHIFT 4 +# endif +# define PAGE_MASK_MASK 63 #endif #if (!defined(USE_DYNAREC) && defined(USE_NEW_DYNAREC)) -#define BLOCK_PC_INVALID 0xffffffff -#define BLOCK_INVALID 0 +# define BLOCK_PC_INVALID 0xffffffff +# define BLOCK_INVALID 0 #endif +mem_mapping_t ram_low_mapping; /* 0..640K mapping */ +mem_mapping_t ram_mid_mapping; /* 640..1024K mapping */ +mem_mapping_t ram_mid_mapping2; /* 640..1024K mapping, second part, for SiS 471 in relocate mode */ +mem_mapping_t ram_remapped_mapping; /* 640..1024K mapping */ +mem_mapping_t ram_remapped_mapping2; /* 640..1024K second mapping, for SiS 471 mode */ +mem_mapping_t ram_high_mapping; /* 1024K+ mapping */ +mem_mapping_t ram_2gb_mapping; /* 1024M+ mapping */ +mem_mapping_t ram_split_mapping; +mem_mapping_t bios_mapping; +mem_mapping_t bios_high_mapping; -mem_mapping_t ram_low_mapping, /* 0..640K mapping */ - ram_mid_mapping, - ram_remapped_mapping, /* 640..1024K mapping */ - ram_high_mapping, /* 1024K+ mapping */ - ram_2gb_mapping, /* 1024M+ mapping */ - ram_remapped_mapping, - ram_split_mapping, - bios_mapping, - bios_high_mapping; +page_t *pages; /* RAM page table */ +page_t **page_lookup; /* pagetable lookup */ +uint32_t pages_sz; /* #pages in table */ -page_t *pages, /* RAM page table */ - **page_lookup; /* pagetable lookup */ -uint32_t pages_sz; /* #pages in table */ +uint8_t *ram; /* the virtual RAM */ +uint8_t *ram2; /* the virtual RAM */ +uint8_t page_ff[4096]; +uint32_t rammask; +uint32_t addr_space_size; -uint8_t *ram, *ram2; /* the virtual RAM */ -uint8_t page_ff[4096]; -uint32_t rammask; +uint8_t *rom; /* the virtual ROM */ +uint32_t biosmask; +uint32_t biosaddr; -uint8_t *rom; /* the virtual ROM */ -uint32_t biosmask, biosaddr; +uint32_t pccache; +uint8_t *pccache2; -uint32_t pccache; -uint8_t *pccache2; +int readlnext; +int readlookup[256]; +uintptr_t *readlookup2; +uintptr_t old_rl2; +uint8_t uncached = 0; +int writelnext; +int writelookup[256]; +uintptr_t *writelookup2; -int readlnext; -int readlookup[256]; -uintptr_t *readlookup2; -uintptr_t old_rl2; -uint8_t uncached = 0; -int writelnext; -int writelookup[256]; -uintptr_t *writelookup2; +uint32_t mem_logical_addr; -uint32_t mem_logical_addr; +int shadowbios = 0; +int shadowbios_write; +int readlnum = 0; +int writelnum = 0; +int cachesize = 256; -int shadowbios = 0, - shadowbios_write; -int readlnum = 0, - writelnum = 0; -int cachesize = 256; +uint32_t get_phys_virt; +uint32_t get_phys_phys; -uint32_t get_phys_virt, - get_phys_phys; +int mem_a20_key = 0; +int mem_a20_alt = 0; +int mem_a20_state = 0; -int mem_a20_key = 0, - mem_a20_alt = 0, - mem_a20_state = 0; - -int mmuflush = 0; -int mmu_perm = 4; +int mmuflush = 0; +int mmu_perm = 4; #ifdef USE_NEW_DYNAREC -uint64_t *byte_dirty_mask; -uint64_t *byte_code_present_mask; +uint64_t *byte_dirty_mask; +uint64_t *byte_code_present_mask; -uint32_t purgable_page_list_head = 0; -int purgeable_page_count = 0; +uint32_t purgable_page_list_head = 0; +int purgeable_page_count = 0; #endif -uint8_t high_page = 0; /* if a high (> 4 gb) page was detected */ +uint8_t high_page = 0; /* if a high (> 4 gb) page was detected */ +mem_mapping_t *read_mapping[MEM_MAPPINGS_NO]; +mem_mapping_t *write_mapping[MEM_MAPPINGS_NO]; /* FIXME: re-do this with a 'mem_ops' struct. */ -static uint8_t *page_lookupp; /* pagetable mmu_perm lookup */ -static uint8_t *readlookupp; -static uint8_t *writelookupp; -static mem_mapping_t *base_mapping, *last_mapping; -static mem_mapping_t *read_mapping[MEM_MAPPINGS_NO]; -static mem_mapping_t *write_mapping[MEM_MAPPINGS_NO]; -static mem_mapping_t *read_mapping_bus[MEM_MAPPINGS_NO]; -static mem_mapping_t *write_mapping_bus[MEM_MAPPINGS_NO]; -static uint8_t *_mem_exec[MEM_MAPPINGS_NO]; -static uint8_t ff_pccache[4] = { 0xff, 0xff, 0xff, 0xff }; -static mem_state_t _mem_state[MEM_MAPPINGS_NO]; -static uint32_t remap_start_addr; +static uint8_t *page_lookupp; /* pagetable mmu_perm lookup */ +static uint8_t *readlookupp; +static uint8_t *writelookupp; +static mem_mapping_t *base_mapping; +static mem_mapping_t *last_mapping; +static mem_mapping_t *read_mapping_bus[MEM_MAPPINGS_NO]; +static mem_mapping_t *write_mapping_bus[MEM_MAPPINGS_NO]; +static uint8_t *_mem_exec[MEM_MAPPINGS_NO]; +static uint8_t ff_pccache[4] = { 0xff, 0xff, 0xff, 0xff }; +static mem_state_t _mem_state[MEM_MAPPINGS_NO]; +static uint32_t remap_start_addr; +static uint32_t remap_start_addr2; #if (!(defined __amd64__ || defined _M_X64 || defined __aarch64__ || defined _M_ARM64)) -static size_t ram_size = 0, ram2_size = 0; +static size_t ram_size = 0; +static size_t ram2_size = 0; #else -static size_t ram_size = 0; +static size_t ram_size = 0; #endif - #ifdef ENABLE_MEM_LOG int mem_do_log = ENABLE_MEM_LOG; - static void mem_log(const char *fmt, ...) { va_list ap; if (mem_do_log) { - va_start(ap, fmt); - pclog_ex(fmt, ap); - va_end(ap); + va_start(ap, fmt); + pclog_ex(fmt, ap); + va_end(ap); } } #else -#define mem_log(fmt, ...) +# define mem_log(fmt, ...) #endif - int mem_addr_is_ram(uint32_t addr) { - mem_mapping_t *mapping = read_mapping[addr >> MEM_GRANULARITY_BITS]; + const mem_mapping_t *mapping = read_mapping[addr >> MEM_GRANULARITY_BITS]; - return (mapping == &ram_low_mapping) || (mapping == &ram_high_mapping) || (mapping == &ram_mid_mapping) || (mapping == &ram_remapped_mapping); + return (mapping == &ram_low_mapping) || (mapping == &ram_high_mapping) || (mapping == &ram_mid_mapping) || + (mapping == &ram_mid_mapping2) || (mapping == &ram_remapped_mapping); } - void resetreadlookup(void) { - int c; - /* Initialize the page lookup table. */ - memset(page_lookup, 0x00, (1<<20)*sizeof(page_t *)); + memset(page_lookup, 0x00, (1 << 20) * sizeof(page_t *)); /* Initialize the tables for lower (<= 1024K) RAM. */ - for (c = 0; c < 256; c++) { - readlookup[c] = 0xffffffff; - writelookup[c] = 0xffffffff; + for (uint16_t c = 0; c < 256; c++) { + readlookup[c] = 0xffffffff; + writelookup[c] = 0xffffffff; } /* Initialize the tables for high (> 1024K) RAM. */ - memset(readlookup2, 0xff, (1<<20)*sizeof(uintptr_t)); - memset(readlookupp, 0x04, (1<<20)*sizeof(uint8_t)); + memset(readlookup2, 0xff, (1 << 20) * sizeof(uintptr_t)); + memset(readlookupp, 0x04, (1 << 20) * sizeof(uint8_t)); - memset(writelookup2, 0xff, (1<<20)*sizeof(uintptr_t)); - memset(writelookupp, 0x04, (1<<20)*sizeof(uint8_t)); + memset(writelookup2, 0xff, (1 << 20) * sizeof(uintptr_t)); + memset(writelookupp, 0x04, (1 << 20) * sizeof(uint8_t)); - readlnext = 0; + readlnext = 0; writelnext = 0; - pccache = 0xffffffff; - high_page = 0; + pccache = 0xffffffff; + high_page = 0; } - void flushmmucache(void) { - int c; - - for (c = 0; c < 256; c++) { - if (readlookup[c] != (int) 0xffffffff) { - readlookup2[readlookup[c]] = LOOKUP_INV; - readlookupp[readlookup[c]] = 4; - readlookup[c] = 0xffffffff; - } - if (writelookup[c] != (int) 0xffffffff) { - page_lookup[writelookup[c]] = NULL; - page_lookupp[writelookup[c]] = 4; - writelookup2[writelookup[c]] = LOOKUP_INV; - writelookupp[writelookup[c]] = 4; - writelookup[c] = 0xffffffff; - } + for (uint16_t c = 0; c < 256; c++) { + if (readlookup[c] != (int) 0xffffffff) { + readlookup2[readlookup[c]] = LOOKUP_INV; + readlookupp[readlookup[c]] = 4; + readlookup[c] = 0xffffffff; + } + if (writelookup[c] != (int) 0xffffffff) { + page_lookup[writelookup[c]] = NULL; + page_lookupp[writelookup[c]] = 4; + writelookup2[writelookup[c]] = LOOKUP_INV; + writelookupp[writelookup[c]] = 4; + writelookup[c] = 0xffffffff; + } } mmuflush++; - pccache = (uint32_t)0xffffffff; - pccache2 = (uint8_t *)0xffffffff; + pccache = (uint32_t) 0xffffffff; + pccache2 = (uint8_t *) 0xffffffff; #ifdef USE_DYNAREC codegen_flush(); #endif } - void flushmmucache_nopc(void) { - int c; - - for (c = 0; c < 256; c++) { - if (readlookup[c] != (int) 0xffffffff) { - readlookup2[readlookup[c]] = LOOKUP_INV; - readlookupp[readlookup[c]] = 4; - readlookup[c] = 0xffffffff; - } - if (writelookup[c] != (int) 0xffffffff) { - page_lookup[writelookup[c]] = NULL; - page_lookupp[writelookup[c]] = 4; - writelookup2[writelookup[c]] = LOOKUP_INV; - writelookupp[writelookup[c]] = 4; - writelookup[c] = 0xffffffff; - } + for (uint16_t c = 0; c < 256; c++) { + if (readlookup[c] != (int) 0xffffffff) { + readlookup2[readlookup[c]] = LOOKUP_INV; + readlookupp[readlookup[c]] = 4; + readlookup[c] = 0xffffffff; + } + if (writelookup[c] != (int) 0xffffffff) { + page_lookup[writelookup[c]] = NULL; + page_lookupp[writelookup[c]] = 4; + writelookup2[writelookup[c]] = LOOKUP_INV; + writelookupp[writelookup[c]] = 4; + writelookup[c] = 0xffffffff; + } } } - void mem_flush_write_page(uint32_t addr, uint32_t virt) { - page_t *page_target = &pages[addr >> 12]; - int c; + const page_t *page_target = &pages[addr >> 12]; #if (!(defined __amd64__ || defined _M_X64 || defined __aarch64__ || defined _M_ARM64)) uint32_t a; #endif - for (c = 0; c < 256; c++) { - if (writelookup[c] != (int) 0xffffffff) { + for (uint16_t c = 0; c < 256; c++) { + if (writelookup[c] != (int) 0xffffffff) { #if (defined __amd64__ || defined _M_X64 || defined __aarch64__ || defined _M_ARM64) - uintptr_t target = (uintptr_t)&ram[(uintptr_t)(addr & ~0xfff) - (virt & ~0xfff)]; + uintptr_t target = (uintptr_t) &ram[(uintptr_t) (addr & ~0xfff) - (virt & ~0xfff)]; #else - a = (uintptr_t)(addr & ~0xfff) - (virt & ~0xfff); - uintptr_t target; + a = (uintptr_t) (addr & ~0xfff) - (virt & ~0xfff); + uintptr_t target; - if ((addr & ~0xfff) >= (1 << 30)) - target = (uintptr_t)&ram2[a - (1 << 30)]; - else - target = (uintptr_t)&ram[a]; + if ((addr & ~0xfff) >= (1 << 30)) + target = (uintptr_t) &ram2[a - (1 << 30)]; + else + target = (uintptr_t) &ram[a]; #endif - if (writelookup2[writelookup[c]] == target || page_lookup[writelookup[c]] == page_target) { - writelookup2[writelookup[c]] = LOOKUP_INV; - page_lookup[writelookup[c]] = NULL; - writelookup[c] = 0xffffffff; - } - } + if (writelookup2[writelookup[c]] == target || page_lookup[writelookup[c]] == page_target) { + writelookup2[writelookup[c]] = LOOKUP_INV; + page_lookup[writelookup[c]] = NULL; + writelookup[c] = 0xffffffff; + } + } } } - -#define mmutranslate_read(addr) mmutranslatereal(addr,0) -#define mmutranslate_write(addr) mmutranslatereal(addr,1) -#define rammap(x) ((uint32_t *)(_mem_exec[(x) >> MEM_GRANULARITY_BITS]))[((x) >> 2) & MEM_GRANULARITY_QMASK] -#define rammap64(x) ((uint64_t *)(_mem_exec[(x) >> MEM_GRANULARITY_BITS]))[((x) >> 3) & MEM_GRANULARITY_PMASK] - +#define mmutranslate_read(addr) mmutranslatereal(addr, 0) +#define mmutranslate_write(addr) mmutranslatereal(addr, 1) +#define rammap(x) ((uint32_t *) (_mem_exec[(x) >> MEM_GRANULARITY_BITS]))[((x) >> 2) & MEM_GRANULARITY_QMASK] +#define rammap64(x) ((uint64_t *) (_mem_exec[(x) >> MEM_GRANULARITY_BITS]))[((x) >> 3) & MEM_GRANULARITY_PMASK] static __inline uint64_t mmutranslatereal_normal(uint32_t addr, int rw) { - uint32_t temp, temp2, temp3; + uint32_t temp; + uint32_t temp2; + uint32_t temp3; uint32_t addr2; if (cpu_state.abrt) - return 0xffffffffffffffffULL; + return 0xffffffffffffffffULL; addr2 = ((cr3 & ~0xfff) + ((addr >> 20) & 0xffc)); temp = temp2 = rammap(addr2); if (!(temp & 1)) { - cr2 = addr; - temp &= 1; - if (CPL == 3) temp |= 4; - if (rw) temp |= 2; - cpu_state.abrt = ABRT_PF; - abrt_error = temp; - return 0xffffffffffffffffULL; + cr2 = addr; + temp &= 1; + if (CPL == 3) + temp |= 4; + if (rw) + temp |= 2; + cpu_state.abrt = ABRT_PF; + abrt_error = temp; + return 0xffffffffffffffffULL; } if ((temp & 0x80) && (cr4 & CR4_PSE)) { - /*4MB page*/ - if (((CPL == 3) && !(temp & 4) && !cpl_override) || (rw && !(temp & 2) && (((CPL == 3) && !cpl_override) || (is486 && (cr0 & WP_FLAG))))) { - cr2 = addr; - temp &= 1; - if (CPL == 3) - temp |= 4; - if (rw) - temp |= 2; - cpu_state.abrt = ABRT_PF; - abrt_error = temp; + /*4MB page*/ + if (((CPL == 3) && !(temp & 4) && !cpl_override) || (rw && !(temp & 2) && (((CPL == 3) && !cpl_override) || ((is486 || isibm486) && (cr0 & WP_FLAG))))) { + cr2 = addr; + temp &= 1; + if (CPL == 3) + temp |= 4; + if (rw) + temp |= 2; + cpu_state.abrt = ABRT_PF; + abrt_error = temp; - return 0xffffffffffffffffULL; - } + return 0xffffffffffffffffULL; + } - mmu_perm = temp & 4; - rammap(addr2) |= (rw ? 0x60 : 0x20); + mmu_perm = temp & 4; + rammap(addr2) |= (rw ? 0x60 : 0x20); - return (temp & ~0x3fffff) + (addr & 0x3fffff); + return (temp & ~0x3fffff) + (addr & 0x3fffff); } - temp = rammap((temp & ~0xfff) + ((addr >> 10) & 0xffc)); + temp = rammap((temp & ~0xfff) + ((addr >> 10) & 0xffc)); temp3 = temp & temp2; - if (!(temp & 1) || ((CPL == 3) && !(temp3 & 4) && !cpl_override) || (rw && !(temp3 & 2) && (((CPL == 3) && !cpl_override) || (is486 && (cr0 & WP_FLAG))))) { - cr2 = addr; - temp &= 1; - if (CPL == 3) - temp |= 4; - if (rw) - temp |= 2; - cpu_state.abrt = ABRT_PF; - abrt_error = temp; - return 0xffffffffffffffffULL; + if (!(temp & 1) || ((CPL == 3) && !(temp3 & 4) && !cpl_override) || (rw && !(temp3 & 2) && (((CPL == 3) && !cpl_override) || ((is486 || isibm486) && (cr0 & WP_FLAG))))) { + cr2 = addr; + temp &= 1; + if (CPL == 3) + temp |= 4; + if (rw) + temp |= 2; + cpu_state.abrt = ABRT_PF; + abrt_error = temp; + return 0xffffffffffffffffULL; } mmu_perm = temp & 4; @@ -347,72 +344,82 @@ mmutranslatereal_normal(uint32_t addr, int rw) return (uint64_t) ((temp & ~0xfff) + (addr & 0xfff)); } - static __inline uint64_t mmutranslatereal_pae(uint32_t addr, int rw) { - uint64_t temp, temp2, temp3, temp4; - uint64_t addr2, addr3, addr4; + uint64_t temp; + uint64_t temp2; + uint64_t temp3; + uint64_t temp4; + uint64_t addr2; + uint64_t addr3; + uint64_t addr4; if (cpu_state.abrt) - return 0xffffffffffffffffULL; + return 0xffffffffffffffffULL; addr2 = (cr3 & ~0x1f) + ((addr >> 27) & 0x18); temp = temp2 = rammap64(addr2) & 0x000000ffffffffffULL; if (!(temp & 1)) { - cr2 = addr; - temp &= 1; - if (CPL == 3) temp |= 4; - if (rw) temp |= 2; - cpu_state.abrt = ABRT_PF; - abrt_error = temp; - return 0xffffffffffffffffULL; + cr2 = addr; + temp &= 1; + if (CPL == 3) + temp |= 4; + if (rw) + temp |= 2; + cpu_state.abrt = ABRT_PF; + abrt_error = temp; + return 0xffffffffffffffffULL; } addr3 = (temp & ~0xfffULL) + ((addr >> 18) & 0xff8); temp = temp4 = rammap64(addr3) & 0x000000ffffffffffULL; - temp3 = temp & temp2; + temp3 = temp & temp2; if (!(temp & 1)) { - cr2 = addr; - temp &= 1; - if (CPL == 3) temp |= 4; - if (rw) temp |= 2; - cpu_state.abrt = ABRT_PF; - abrt_error = temp; - return 0xffffffffffffffffULL; + cr2 = addr; + temp &= 1; + if (CPL == 3) + temp |= 4; + if (rw) + temp |= 2; + cpu_state.abrt = ABRT_PF; + abrt_error = temp; + return 0xffffffffffffffffULL; } if (temp & 0x80) { - /*2MB page*/ - if (((CPL == 3) && !(temp & 4) && !cpl_override) || (rw && !(temp & 2) && (((CPL == 3) && !cpl_override) || (cr0 & WP_FLAG)))) { - cr2 = addr; - temp &= 1; - if (CPL == 3) - temp |= 4; - if (rw) - temp |= 2; - cpu_state.abrt = ABRT_PF; - abrt_error = temp; + /*2MB page*/ + if (((CPL == 3) && !(temp & 4) && !cpl_override) || (rw && !(temp & 2) && (((CPL == 3) && !cpl_override) || (cr0 & WP_FLAG)))) { + cr2 = addr; + temp &= 1; + if (CPL == 3) + temp |= 4; + if (rw) + temp |= 2; + cpu_state.abrt = ABRT_PF; + abrt_error = temp; - return 0xffffffffffffffffULL; - } - mmu_perm = temp & 4; - rammap64(addr3) |= (rw ? 0x60 : 0x20); + return 0xffffffffffffffffULL; + } + mmu_perm = temp & 4; + rammap64(addr3) |= (rw ? 0x60 : 0x20); - return ((temp & ~0x1fffffULL) + (addr & 0x1fffffULL)) & 0x000000ffffffffffULL; + return ((temp & ~0x1fffffULL) + (addr & 0x1fffffULL)) & 0x000000ffffffffffULL; } addr4 = (temp & ~0xfffULL) + ((addr >> 9) & 0xff8); - temp = rammap64(addr4) & 0x000000ffffffffffULL; + temp = rammap64(addr4) & 0x000000ffffffffffULL; temp3 = temp & temp4; if (!(temp & 1) || ((CPL == 3) && !(temp3 & 4) && !cpl_override) || (rw && !(temp3 & 2) && (((CPL == 3) && !cpl_override) || (cr0 & WP_FLAG)))) { - cr2 = addr; - temp &= 1; - if (CPL == 3) temp |= 4; - if (rw) temp |= 2; - cpu_state.abrt = ABRT_PF; - abrt_error = temp; - return 0xffffffffffffffffULL; + cr2 = addr; + temp &= 1; + if (CPL == 3) + temp |= 4; + if (rw) + temp |= 2; + cpu_state.abrt = ABRT_PF; + abrt_error = temp; + return 0xffffffffffffffffULL; } mmu_perm = temp & 4; @@ -422,140 +429,134 @@ mmutranslatereal_pae(uint32_t addr, int rw) return ((temp & ~0xfffULL) + ((uint64_t) (addr & 0xfff))) & 0x000000ffffffffffULL; } - uint64_t mmutranslatereal(uint32_t addr, int rw) { /* Fast path to return invalid without any call if an exception has occurred beforehand. */ - if (cpu_state.abrt) - return 0xffffffffffffffffULL; + if (cpu_state.abrt) + return 0xffffffffffffffffULL; if (cr4 & CR4_PAE) - return mmutranslatereal_pae(addr, rw); + return mmutranslatereal_pae(addr, rw); else - return mmutranslatereal_normal(addr, rw); + return mmutranslatereal_normal(addr, rw); } - /* This is needed because the old recompiler calls this to check for page fault. */ uint32_t mmutranslatereal32(uint32_t addr, int rw) { /* Fast path to return invalid without any call if an exception has occurred beforehand. */ - if (cpu_state.abrt) - return (uint32_t) 0xffffffffffffffffULL; + if (cpu_state.abrt) + return (uint32_t) 0xffffffffffffffffULL; return (uint32_t) mmutranslatereal(addr, rw); } - static __inline uint64_t mmutranslate_noabrt_normal(uint32_t addr, int rw) { - uint32_t temp,temp2,temp3; + uint32_t temp; + uint32_t temp2; + uint32_t temp3; uint32_t addr2; - if (cpu_state.abrt) - return 0xffffffffffffffffULL; + if (cpu_state.abrt) + return 0xffffffffffffffffULL; addr2 = ((cr3 & ~0xfff) + ((addr >> 20) & 0xffc)); temp = temp2 = rammap(addr2); - if (! (temp & 1)) - return 0xffffffffffffffffULL; + if (!(temp & 1)) + return 0xffffffffffffffffULL; if ((temp & 0x80) && (cr4 & CR4_PSE)) { - /*4MB page*/ - if (((CPL == 3) && !(temp & 4) && !cpl_override) || (rw && !(temp & 2) && ((CPL == 3) || (cr0 & WP_FLAG)))) - return 0xffffffffffffffffULL; + /*4MB page*/ + if (((CPL == 3) && !(temp & 4) && !cpl_override) || (rw && !(temp & 2) && ((CPL == 3) || (cr0 & WP_FLAG)))) + return 0xffffffffffffffffULL; - return (temp & ~0x3fffff) + (addr & 0x3fffff); + return (temp & ~0x3fffff) + (addr & 0x3fffff); } - temp = rammap((temp & ~0xfff) + ((addr >> 10) & 0xffc)); + temp = rammap((temp & ~0xfff) + ((addr >> 10) & 0xffc)); temp3 = temp & temp2; if (!(temp & 1) || ((CPL == 3) && !(temp3 & 4) && !cpl_override) || (rw && !(temp3 & 2) && ((CPL == 3) || (cr0 & WP_FLAG)))) - return 0xffffffffffffffffULL; + return 0xffffffffffffffffULL; return (uint64_t) ((temp & ~0xfff) + (addr & 0xfff)); } - static __inline uint64_t mmutranslate_noabrt_pae(uint32_t addr, int rw) { - uint64_t temp,temp2,temp3,temp4; - uint64_t addr2,addr3,addr4; + uint64_t temp; + uint64_t temp2; + uint64_t temp3; + uint64_t temp4; + uint64_t addr2; + uint64_t addr3; + uint64_t addr4; - if (cpu_state.abrt) - return 0xffffffffffffffffULL; + if (cpu_state.abrt) + return 0xffffffffffffffffULL; addr2 = (cr3 & ~0x1f) + ((addr >> 27) & 0x18); temp = temp2 = rammap64(addr2) & 0x000000ffffffffffULL; - if (! (temp & 1)) - return 0xffffffffffffffffULL; + if (!(temp & 1)) + return 0xffffffffffffffffULL; addr3 = (temp & ~0xfffULL) + ((addr >> 18) & 0xff8); temp = temp4 = rammap64(addr3) & 0x000000ffffffffffULL; - temp3 = temp & temp2; + temp3 = temp & temp2; - if (! (temp & 1)) - return 0xffffffffffffffffULL; + if (!(temp & 1)) + return 0xffffffffffffffffULL; if (temp & 0x80) { - /*2MB page*/ - if (((CPL == 3) && !(temp & 4) && !cpl_override) || (rw && !(temp & 2) && ((CPL == 3) || (cr0 & WP_FLAG)))) - return 0xffffffffffffffffULL; + /*2MB page*/ + if (((CPL == 3) && !(temp & 4) && !cpl_override) || (rw && !(temp & 2) && ((CPL == 3) || (cr0 & WP_FLAG)))) + return 0xffffffffffffffffULL; - return ((temp & ~0x1fffffULL) + (addr & 0x1fffff)) & 0x000000ffffffffffULL; + return ((temp & ~0x1fffffULL) + (addr & 0x1fffff)) & 0x000000ffffffffffULL; } addr4 = (temp & ~0xfffULL) + ((addr >> 9) & 0xff8); - temp = rammap64(addr4) & 0x000000ffffffffffULL;; + temp = rammap64(addr4) & 0x000000ffffffffffULL; + temp3 = temp & temp4; - if (!(temp&1) || ((CPL == 3) && !(temp3 & 4) && !cpl_override) || (rw && !(temp3 & 2) && ((CPL == 3) || (cr0 & WP_FLAG)))) - return 0xffffffffffffffffULL; + if (!(temp & 1) || ((CPL == 3) && !(temp3 & 4) && !cpl_override) || (rw && !(temp3 & 2) && ((CPL == 3) || (cr0 & WP_FLAG)))) + return 0xffffffffffffffffULL; return ((temp & ~0xfffULL) + ((uint64_t) (addr & 0xfff))) & 0x000000ffffffffffULL; } - uint64_t mmutranslate_noabrt(uint32_t addr, int rw) { /* Fast path to return invalid without any call if an exception has occurred beforehand. */ - if (cpu_state.abrt) - return 0xffffffffffffffffULL; + if (cpu_state.abrt) + return 0xffffffffffffffffULL; if (cr4 & CR4_PAE) - return mmutranslate_noabrt_pae(addr, rw); + return mmutranslate_noabrt_pae(addr, rw); else - return mmutranslate_noabrt_normal(addr, rw); + return mmutranslate_noabrt_normal(addr, rw); } - -void -mmu_invalidate(uint32_t addr) -{ - flushmmucache_cr3(); -} - - uint8_t mem_addr_range_match(uint32_t addr, uint32_t start, uint32_t len) { if (addr < start) - return 0; - else if (addr >= (start + len)) - return 0; - else - return 1; + return 0; + else if (addr >= (start + len)) + return 0; + else + return 1; } - uint32_t mem_addr_translate(uint32_t addr, uint32_t chunk_start, uint32_t len) { @@ -564,7 +565,6 @@ mem_addr_translate(uint32_t addr, uint32_t chunk_start, uint32_t len) return chunk_start + (addr & mask); } - void addreadlookup(uint32_t virt, uint32_t phys) { @@ -572,35 +572,36 @@ addreadlookup(uint32_t virt, uint32_t phys) uint32_t a; #endif - if (virt == 0xffffffff) return; + if (virt == 0xffffffff) + return; - if (readlookup2[virt>>12] != (uintptr_t) LOOKUP_INV) return; + if (readlookup2[virt >> 12] != (uintptr_t) LOOKUP_INV) + return; if (readlookup[readlnext] != (int) 0xffffffff) { - if ((readlookup[readlnext] == ((es + DI) >> 12)) || (readlookup[readlnext] == ((es + EDI) >> 12))) - uncached = 1; - readlookup2[readlookup[readlnext]] = LOOKUP_INV; + if ((readlookup[readlnext] == ((es + DI) >> 12)) || (readlookup[readlnext] == ((es + EDI) >> 12))) + uncached = 1; + readlookup2[readlookup[readlnext]] = LOOKUP_INV; } #if (defined __amd64__ || defined _M_X64 || defined __aarch64__ || defined _M_ARM64) - readlookup2[virt>>12] = (uintptr_t)&ram[(uintptr_t)(phys & ~0xFFF) - (uintptr_t)(virt & ~0xfff)]; + readlookup2[virt >> 12] = (uintptr_t) &ram[(uintptr_t) (phys & ~0xFFF) - (uintptr_t) (virt & ~0xfff)]; #else - a = ((uint32_t)(phys & ~0xfff) - (uint32_t)(virt & ~0xfff)); + a = ((uint32_t) (phys & ~0xfff) - (uint32_t) (virt & ~0xfff)); if ((phys & ~0xfff) >= (1 << 30)) - readlookup2[virt>>12] = (uintptr_t)&ram2[a - (1 << 30)]; + readlookup2[virt >> 12] = (uintptr_t) &ram2[a - (1 << 30)]; else - readlookup2[virt>>12] = (uintptr_t)&ram[a]; + readlookup2[virt >> 12] = (uintptr_t) &ram[a]; #endif - readlookupp[virt>>12] = mmu_perm; + readlookupp[virt >> 12] = mmu_perm; readlookup[readlnext++] = virt >> 12; - readlnext &= (cachesize-1); + readlnext &= (cachesize - 1); cycles -= 9; } - void addwritelookup(uint32_t virt, uint32_t phys) { @@ -608,43 +609,45 @@ addwritelookup(uint32_t virt, uint32_t phys) uint32_t a; #endif - if (virt == 0xffffffff) return; + if (virt == 0xffffffff) + return; - if (page_lookup[virt >> 12]) return; + if (page_lookup[virt >> 12]) + return; if (writelookup[writelnext] != -1) { - page_lookup[writelookup[writelnext]] = NULL; - writelookup2[writelookup[writelnext]] = LOOKUP_INV; + page_lookup[writelookup[writelnext]] = NULL; + writelookup2[writelookup[writelnext]] = LOOKUP_INV; } #ifdef USE_NEW_DYNAREC -#ifdef USE_DYNAREC +# ifdef USE_DYNAREC if (pages[phys >> 12].block || (phys & ~0xfff) == recomp_page) { -#else +# else if (pages[phys >> 12].block) { -#endif +# endif #else -#ifdef USE_DYNAREC +# ifdef USE_DYNAREC if (pages[phys >> 12].block[0] || pages[phys >> 12].block[1] || pages[phys >> 12].block[2] || pages[phys >> 12].block[3] || (phys & ~0xfff) == recomp_page) { -#else +# else if (pages[phys >> 12].block[0] || pages[phys >> 12].block[1] || pages[phys >> 12].block[2] || pages[phys >> 12].block[3]) { +# endif #endif -#endif - page_lookup[virt >> 12] = &pages[phys >> 12]; - page_lookupp[virt >> 12] = mmu_perm; + page_lookup[virt >> 12] = &pages[phys >> 12]; + page_lookupp[virt >> 12] = mmu_perm; } else { #if (defined __amd64__ || defined _M_X64 || defined __aarch64__ || defined _M_ARM64) - writelookup2[virt>>12] = (uintptr_t)&ram[(uintptr_t)(phys & ~0xFFF) - (uintptr_t)(virt & ~0xfff)]; + writelookup2[virt >> 12] = (uintptr_t) &ram[(uintptr_t) (phys & ~0xFFF) - (uintptr_t) (virt & ~0xfff)]; #else - a = ((uint32_t)(phys & ~0xfff) - (uint32_t)(virt & ~0xfff)); + a = ((uint32_t) (phys & ~0xfff) - (uint32_t) (virt & ~0xfff)); - if ((phys & ~0xfff) >= (1 << 30)) - writelookup2[virt>>12] = (uintptr_t)&ram2[a - (1 << 30)]; - else - writelookup2[virt>>12] = (uintptr_t)&ram[a]; + if ((phys & ~0xfff) >= (1 << 30)) + writelookup2[virt >> 12] = (uintptr_t) &ram2[a - (1 << 30)]; + else + writelookup2[virt >> 12] = (uintptr_t) &ram[a]; #endif } - writelookupp[virt>>12] = mmu_perm; + writelookupp[virt >> 12] = mmu_perm; writelookup[writelnext++] = virt >> 12; writelnext &= (cachesize - 1); @@ -652,78 +655,84 @@ addwritelookup(uint32_t virt, uint32_t phys) cycles -= 9; } - uint8_t * getpccache(uint32_t a) { uint64_t a64 = (uint64_t) a; +#if (defined __amd64__ || defined _M_X64 || defined __aarch64__ || defined _M_ARM64) + uint8_t *p; +#endif uint32_t a2; a2 = a; if (cr0 >> 31) { - a64 = mmutranslate_read(a64); + a64 = mmutranslate_read(a64); - if (a64 == 0xffffffffffffffffULL) return ram; + if (a64 == 0xffffffffffffffffULL) + return ram; } a64 &= rammask; if (_mem_exec[a64 >> MEM_GRANULARITY_BITS]) { - if (is286) { - if (read_mapping[a64 >> MEM_GRANULARITY_BITS] && (read_mapping[a64 >> MEM_GRANULARITY_BITS]->flags & MEM_MAPPING_ROM_WS)) - cpu_prefetch_cycles = cpu_rom_prefetch_cycles; - else - cpu_prefetch_cycles = cpu_mem_prefetch_cycles; - } - - return &_mem_exec[a64 >> MEM_GRANULARITY_BITS][(uintptr_t)(a64 & MEM_GRANULARITY_PAGE) - (uintptr_t)(a2 & ~0xfff)]; + if (is286) { + if (read_mapping[a64 >> MEM_GRANULARITY_BITS] && (read_mapping[a64 >> MEM_GRANULARITY_BITS]->flags & MEM_MAPPING_ROM_WS)) + cpu_prefetch_cycles = cpu_rom_prefetch_cycles; + else + cpu_prefetch_cycles = cpu_mem_prefetch_cycles; + } + +#if (defined __amd64__ || defined _M_X64 || defined __aarch64__ || defined _M_ARM64) + p = &_mem_exec[a64 >> MEM_GRANULARITY_BITS][(uintptr_t) (a64 & MEM_GRANULARITY_PAGE) - (uintptr_t) (a2 & ~0xfff)]; + return (uint8_t *) (((uintptr_t) p & 0x00000000ffffffffULL) | ((uintptr_t) &_mem_exec[a64 >> MEM_GRANULARITY_BITS][0] & 0xffffffff00000000ULL)); +#else + return &_mem_exec[a64 >> MEM_GRANULARITY_BITS][(uintptr_t) (a64 & MEM_GRANULARITY_PAGE) - (uintptr_t) (a2 & ~0xfff)]; +#endif } mem_log("Bad getpccache %08X%08X\n", (uint32_t) (a64 >> 32), (uint32_t) (a64 & 0xffffffffULL)); - return (uint8_t *)&ff_pccache; + return (uint8_t *) &ff_pccache; } - uint8_t read_mem_b(uint32_t addr) { mem_mapping_t *map; - uint8_t ret = 0xff; - int old_cycles = cycles; + uint8_t ret = 0xff; + int old_cycles = cycles; mem_logical_addr = addr; addr &= rammask; map = read_mapping[addr >> MEM_GRANULARITY_BITS]; if (map && map->read_b) - ret = map->read_b(addr, map->p); + ret = map->read_b(addr, map->priv); resub_cycles(old_cycles); return ret; } - uint16_t read_mem_w(uint32_t addr) { mem_mapping_t *map; - uint16_t ret = 0xffff; - int old_cycles = cycles; + uint16_t ret = 0xffff; + int old_cycles = cycles; mem_logical_addr = addr; addr &= rammask; if (addr & 1) - ret = read_mem_b(addr) | (read_mem_b(addr + 1) << 8); + ret = read_mem_b(addr) | (read_mem_b(addr + 1) << 8); else { - map = read_mapping[addr >> MEM_GRANULARITY_BITS]; + map = read_mapping[addr >> MEM_GRANULARITY_BITS]; - if (map && map->read_w) - ret = map->read_w(addr, map->p); - else if (map && map->read_b) - ret = map->read_b(addr, map->p) | (map->read_b(addr + 1, map->p) << 8); + if (map && map->read_w) + ret = map->read_w(addr, map->priv); + else if (map && map->read_b) + ret = map->read_b(addr, map->priv) | (map->read_b(addr + 1, map->priv) << 8); } resub_cycles(old_cycles); @@ -731,279 +740,277 @@ read_mem_w(uint32_t addr) return ret; } - void write_mem_b(uint32_t addr, uint8_t val) { mem_mapping_t *map; - int old_cycles = cycles; + int old_cycles = cycles; mem_logical_addr = addr; addr &= rammask; map = write_mapping[addr >> MEM_GRANULARITY_BITS]; if (map && map->write_b) - map->write_b(addr, val, map->p); + map->write_b(addr, val, map->priv); resub_cycles(old_cycles); } - void write_mem_w(uint32_t addr, uint16_t val) { mem_mapping_t *map; - int old_cycles = cycles; + int old_cycles = cycles; mem_logical_addr = addr; addr &= rammask; if (addr & 1) { - write_mem_b(addr, val); - write_mem_b(addr + 1, val >> 8); + write_mem_b(addr, val); + write_mem_b(addr + 1, val >> 8); } else { - map = write_mapping[addr >> MEM_GRANULARITY_BITS]; - if (map) { - if (map->write_w) - map->write_w(addr, val, map->p); - else if (map->write_b) { - map->write_b(addr, val, map->p); - map->write_b(addr + 1, val >> 8, map->p); - } - } + map = write_mapping[addr >> MEM_GRANULARITY_BITS]; + if (map) { + if (map->write_w) + map->write_w(addr, val, map->priv); + else if (map->write_b) { + map->write_b(addr, val, map->priv); + map->write_b(addr + 1, val >> 8, map->priv); + } + } } resub_cycles(old_cycles); } - uint8_t readmembl(uint32_t addr) { mem_mapping_t *map; - uint64_t a; + uint64_t a; - addr64 = (uint64_t) addr; + GDBSTUB_MEM_ACCESS(addr, GDBSTUB_MEM_READ, 1); + + addr64 = (uint64_t) addr; mem_logical_addr = addr; high_page = 0; if (cr0 >> 31) { - a = mmutranslate_read(addr); - addr64 = (uint32_t) a; + a = mmutranslate_read(addr); + addr64 = (uint32_t) a; - if (a > 0xffffffffULL) - return 0xff; + if (a > 0xffffffffULL) + return 0xff; } addr = (uint32_t) (addr64 & rammask); map = read_mapping[addr >> MEM_GRANULARITY_BITS]; if (map && map->read_b) - return map->read_b(addr, map->p); + return map->read_b(addr, map->priv); return 0xff; } - void writemembl(uint32_t addr, uint8_t val) { mem_mapping_t *map; - uint64_t a; + uint64_t a; - addr64 = (uint64_t) addr; + GDBSTUB_MEM_ACCESS(addr, GDBSTUB_MEM_WRITE, 1); + + addr64 = (uint64_t) addr; mem_logical_addr = addr; high_page = 0; - if (page_lookup[addr>>12] && page_lookup[addr>>12]->write_b) { - page_lookup[addr>>12]->write_b(addr, val, page_lookup[addr>>12]); - return; + if (page_lookup[addr >> 12] && page_lookup[addr >> 12]->write_b) { + page_lookup[addr >> 12]->write_b(addr, val, page_lookup[addr >> 12]); + return; } if (cr0 >> 31) { - a = mmutranslate_write(addr); - addr64 = (uint32_t) a; + a = mmutranslate_write(addr); + addr64 = (uint32_t) a; - if (a > 0xffffffffULL) - return; + if (a > 0xffffffffULL) + return; } addr = (uint32_t) (addr64 & rammask); map = write_mapping[addr >> MEM_GRANULARITY_BITS]; if (map && map->write_b) - map->write_b(addr, val, map->p); + map->write_b(addr, val, map->priv); } - /* Read a byte from memory without MMU translation - result of previous MMU translation passed as value. */ uint8_t readmembl_no_mmut(uint32_t addr, uint32_t a64) { mem_mapping_t *map; + GDBSTUB_MEM_ACCESS(addr, GDBSTUB_MEM_READ, 1); + mem_logical_addr = addr; if (cr0 >> 31) { - if (cpu_state.abrt || high_page) - return 0xff; + if (cpu_state.abrt || high_page) + return 0xff; - addr = a64 & rammask; + addr = a64 & rammask; } else - addr &= rammask; + addr &= rammask; map = read_mapping[addr >> MEM_GRANULARITY_BITS]; if (map && map->read_b) - return map->read_b(addr, map->p); + return map->read_b(addr, map->priv); return 0xff; } - /* Write a byte to memory without MMU translation - result of previous MMU translation passed as value. */ void writemembl_no_mmut(uint32_t addr, uint32_t a64, uint8_t val) { mem_mapping_t *map; + GDBSTUB_MEM_ACCESS(addr, GDBSTUB_MEM_WRITE, 1); + mem_logical_addr = addr; if (page_lookup[addr >> 12] && page_lookup[addr >> 12]->write_b) { - page_lookup[addr >> 12]->write_b(addr, val, page_lookup[addr >> 12]); - return; + page_lookup[addr >> 12]->write_b(addr, val, page_lookup[addr >> 12]); + return; } if (cr0 >> 31) { - if (cpu_state.abrt || high_page) - return; + if (cpu_state.abrt || high_page) + return; - addr = a64 & rammask; + addr = a64 & rammask; } else - addr &= rammask; + addr &= rammask; map = write_mapping[addr >> MEM_GRANULARITY_BITS]; if (map && map->write_b) - map->write_b(addr, val, map->p); + map->write_b(addr, val, map->priv); } - uint16_t readmemwl(uint32_t addr) { mem_mapping_t *map; - int i; - uint64_t a; + uint64_t a; addr64a[0] = addr; addr64a[1] = addr + 1; + GDBSTUB_MEM_ACCESS_FAST(addr64a, GDBSTUB_MEM_READ, 2); mem_logical_addr = addr; high_page = 0; if (addr & 1) { - if (!cpu_cyrix_alignment || (addr & 7) == 7) - cycles -= timing_misaligned; - if ((addr & 0xfff) > 0xffe) { - if (cr0 >> 31) { - for (i = 0; i < 2; i++) { - a = mmutranslate_read(addr + i); - addr64a[i] = (uint32_t) a; + if (!cpu_cyrix_alignment || (addr & 7) == 7) + cycles -= timing_misaligned; + if ((addr & 0xfff) > 0xffe) { + if (cr0 >> 31) { + for (uint8_t i = 0; i < 2; i++) { + a = mmutranslate_read(addr + i); + addr64a[i] = (uint32_t) a; - if (a > 0xffffffffULL) - return 0xffff; - } - } + if (a > 0xffffffffULL) + return 0xffff; + } + } - return readmembl_no_mmut(addr, addr64a[0]) | - (((uint16_t) readmembl_no_mmut(addr + 1, addr64a[1])) << 8); - } else if (readlookup2[addr >> 12] != (uintptr_t) LOOKUP_INV) { - mmu_perm = readlookupp[addr >> 12]; - return *(uint16_t *)(readlookup2[addr >> 12] + addr); - } + return readmembl_no_mmut(addr, addr64a[0]) | (((uint16_t) readmembl_no_mmut(addr + 1, addr64a[1])) << 8); + } else if (readlookup2[addr >> 12] != (uintptr_t) LOOKUP_INV) { + mmu_perm = readlookupp[addr >> 12]; + return *(uint16_t *) (readlookup2[addr >> 12] + addr); + } } if (cr0 >> 31) { - a = mmutranslate_read(addr); - addr64a[0] = (uint32_t) a; + a = mmutranslate_read(addr); + addr64a[0] = (uint32_t) a; - if (a > 0xffffffffULL) - return 0xffff; + if (a > 0xffffffffULL) + return 0xffff; } else - addr64a[0] = (uint64_t) addr; + addr64a[0] = (uint64_t) addr; addr = addr64a[0] & rammask; map = read_mapping[addr >> MEM_GRANULARITY_BITS]; if (map && map->read_w) - return map->read_w(addr, map->p); + return map->read_w(addr, map->priv); if (map && map->read_b) { - return map->read_b(addr, map->p) | - ((uint16_t) (map->read_b(addr + 1, map->p)) << 8); + return map->read_b(addr, map->priv) | ((uint16_t) (map->read_b(addr + 1, map->priv)) << 8); } return 0xffff; } - void writememwl(uint32_t addr, uint16_t val) { mem_mapping_t *map; - int i; - uint64_t a; + uint64_t a; addr64a[0] = addr; addr64a[1] = addr + 1; + GDBSTUB_MEM_ACCESS_FAST(addr64a, GDBSTUB_MEM_WRITE, 2); mem_logical_addr = addr; high_page = 0; if (addr & 1) { - if (!cpu_cyrix_alignment || (addr & 7) == 7) - cycles -= timing_misaligned; - if ((addr & 0xfff) > 0xffe) { - if (cr0 >> 31) { - for (i = 0; i < 2; i++) { - /* Do not translate a page that has a valid lookup, as that is by definition valid - and the whole purpose of the lookup is to avoid repeat identical translations. */ - if (!page_lookup[(addr + i) >> 12] || !page_lookup[(addr + i) >> 12]->write_b) { - a = mmutranslate_write(addr + i); - addr64a[i] = (uint32_t) a; + if (!cpu_cyrix_alignment || (addr & 7) == 7) + cycles -= timing_misaligned; + if ((addr & 0xfff) > 0xffe) { + if (cr0 >> 31) { + for (uint8_t i = 0; i < 2; i++) { + /* Do not translate a page that has a valid lookup, as that is by definition valid + and the whole purpose of the lookup is to avoid repeat identical translations. */ + if (!page_lookup[(addr + i) >> 12] || !page_lookup[(addr + i) >> 12]->write_b) { + a = mmutranslate_write(addr + i); + addr64a[i] = (uint32_t) a; - if (a > 0xffffffffULL) - return; - } - } - } + if (a > 0xffffffffULL) + return; + } + } + } - /* No need to waste precious CPU host cycles on mmutranslate's that were already done, just pass - their result as a parameter to be used if needed. */ - writemembl_no_mmut(addr, addr64a[0], val); - writemembl_no_mmut(addr + 1, addr64a[1], val >> 8); - return; - } else if (writelookup2[addr >> 12] != (uintptr_t) LOOKUP_INV) { - mmu_perm = writelookupp[addr >> 12]; - *(uint16_t *)(writelookup2[addr >> 12] + addr) = val; - return; - } + /* No need to waste precious CPU host cycles on mmutranslate's that were already done, just pass + their result as a parameter to be used if needed. */ + writemembl_no_mmut(addr, addr64a[0], val); + writemembl_no_mmut(addr + 1, addr64a[1], val >> 8); + return; + } else if (writelookup2[addr >> 12] != (uintptr_t) LOOKUP_INV) { + mmu_perm = writelookupp[addr >> 12]; + *(uint16_t *) (writelookup2[addr >> 12] + addr) = val; + return; + } } if (page_lookup[addr >> 12] && page_lookup[addr >> 12]->write_w) { - page_lookup[addr >> 12]->write_w(addr, val, page_lookup[addr >> 12]); - mmu_perm = page_lookupp[addr >> 12]; - return; + page_lookup[addr >> 12]->write_w(addr, val, page_lookup[addr >> 12]); + mmu_perm = page_lookupp[addr >> 12]; + return; } if (cr0 >> 31) { - a = mmutranslate_write(addr); - addr64a[0] = (uint32_t) a; + a = mmutranslate_write(addr); + addr64a[0] = (uint32_t) a; - if (a > 0xffffffffULL) - return; + if (a > 0xffffffffULL) + return; } addr = addr64a[0] & rammask; @@ -1011,177 +1018,176 @@ writememwl(uint32_t addr, uint16_t val) map = write_mapping[addr >> MEM_GRANULARITY_BITS]; if (map && map->write_w) { - map->write_w(addr, val, map->p); - return; + map->write_w(addr, val, map->priv); + return; } if (map && map->write_b) { - map->write_b(addr, val, map->p); - map->write_b(addr + 1, val >> 8, map->p); - return; + map->write_b(addr, val, map->priv); + map->write_b(addr + 1, val >> 8, map->priv); + return; } } - /* Read a word from memory without MMU translation - results of previous MMU translation passed as array. */ uint16_t readmemwl_no_mmut(uint32_t addr, uint32_t *a64) { mem_mapping_t *map; + GDBSTUB_MEM_ACCESS(addr, GDBSTUB_MEM_READ, 2); + mem_logical_addr = addr; if (addr & 1) { - if (!cpu_cyrix_alignment || (addr & 7) == 7) - cycles -= timing_misaligned; - if ((addr & 0xfff) > 0xffe) { - if (cr0 >> 31) { - if (cpu_state.abrt || high_page) - return 0xffff; - } + if (!cpu_cyrix_alignment || (addr & 7) == 7) + cycles -= timing_misaligned; + if ((addr & 0xfff) > 0xffe) { + if (cr0 >> 31) { + if (cpu_state.abrt || high_page) + return 0xffff; + } - return readmembl_no_mmut(addr, a64[0]) | - (((uint16_t) readmembl_no_mmut(addr + 1, a64[1])) << 8); - } else if (readlookup2[addr >> 12] != (uintptr_t) LOOKUP_INV) { - mmu_perm = readlookupp[addr >> 12]; - return *(uint16_t *)(readlookup2[addr >> 12] + addr); - } + return readmembl_no_mmut(addr, a64[0]) | (((uint16_t) readmembl_no_mmut(addr + 1, a64[1])) << 8); + } else if (readlookup2[addr >> 12] != (uintptr_t) LOOKUP_INV) { + mmu_perm = readlookupp[addr >> 12]; + return *(uint16_t *) (readlookup2[addr >> 12] + addr); + } } if (cr0 >> 31) { - if (cpu_state.abrt || high_page) - return 0xffff; + if (cpu_state.abrt || high_page) + return 0xffff; - addr = (uint32_t) (a64[0] & rammask); + addr = (uint32_t) (a64[0] & rammask); } else - addr &= rammask; + addr &= rammask; map = read_mapping[addr >> MEM_GRANULARITY_BITS]; if (map && map->read_w) - return map->read_w(addr, map->p); + return map->read_w(addr, map->priv); if (map && map->read_b) { - return map->read_b(addr, map->p) | - ((uint16_t) (map->read_b(addr + 1, map->p)) << 8); + return map->read_b(addr, map->priv) | ((uint16_t) (map->read_b(addr + 1, map->priv)) << 8); } return 0xffff; } - /* Write a word to memory without MMU translation - results of previous MMU translation passed as array. */ void writememwl_no_mmut(uint32_t addr, uint32_t *a64, uint16_t val) { mem_mapping_t *map; + GDBSTUB_MEM_ACCESS(addr, GDBSTUB_MEM_WRITE, 2); + mem_logical_addr = addr; if (addr & 1) { - if (!cpu_cyrix_alignment || (addr & 7) == 7) - cycles -= timing_misaligned; - if ((addr & 0xfff) > 0xffe) { - if (cr0 >> 31) { - if (cpu_state.abrt || high_page) - return; - } + if (!cpu_cyrix_alignment || (addr & 7) == 7) + cycles -= timing_misaligned; + if ((addr & 0xfff) > 0xffe) { + if (cr0 >> 31) { + if (cpu_state.abrt || high_page) + return; + } - writemembl_no_mmut(addr, a64[0], val); - writemembl_no_mmut(addr + 1, a64[1], val >> 8); - return; - } else if (writelookup2[addr >> 12] != (uintptr_t) LOOKUP_INV) { - mmu_perm = writelookupp[addr >> 12]; - *(uint16_t *)(writelookup2[addr >> 12] + addr) = val; - return; - } + writemembl_no_mmut(addr, a64[0], val); + writemembl_no_mmut(addr + 1, a64[1], val >> 8); + return; + } else if (writelookup2[addr >> 12] != (uintptr_t) LOOKUP_INV) { + mmu_perm = writelookupp[addr >> 12]; + *(uint16_t *) (writelookup2[addr >> 12] + addr) = val; + return; + } } if (page_lookup[addr >> 12] && page_lookup[addr >> 12]->write_w) { - mmu_perm = page_lookupp[addr >> 12]; - page_lookup[addr >> 12]->write_w(addr, val, page_lookup[addr >> 12]); - return; + mmu_perm = page_lookupp[addr >> 12]; + page_lookup[addr >> 12]->write_w(addr, val, page_lookup[addr >> 12]); + return; } if (cr0 >> 31) { - if (cpu_state.abrt || high_page) - return; + if (cpu_state.abrt || high_page) + return; - addr = (uint32_t) (a64[0] & rammask); + addr = (uint32_t) (a64[0] & rammask); } else - addr &= rammask; + addr &= rammask; map = write_mapping[addr >> MEM_GRANULARITY_BITS]; if (map && map->write_w) { - map->write_w(addr, val, map->p); - return; + map->write_w(addr, val, map->priv); + return; } if (map && map->write_b) { - map->write_b(addr, val, map->p); - map->write_b(addr + 1, val >> 8, map->p); - return; + map->write_b(addr, val, map->priv); + map->write_b(addr + 1, val >> 8, map->priv); + return; } } - uint32_t readmemll(uint32_t addr) { mem_mapping_t *map; - int i; - uint64_t a = 0x0000000000000000ULL; + int i; + uint64_t a = 0x0000000000000000ULL; for (i = 0; i < 4; i++) - addr64a[i] = (uint64_t) (addr + i); + addr64a[i] = (uint64_t) (addr + i); + GDBSTUB_MEM_ACCESS_FAST(addr64a, GDBSTUB_MEM_READ, 4); mem_logical_addr = addr; high_page = 0; if (addr & 3) { - if (!cpu_cyrix_alignment || (addr & 7) > 4) - cycles -= timing_misaligned; - if ((addr & 0xfff) > 0xffc) { - if (cr0 >> 31) { - for (i = 0; i < 4; i++) { - if (i == 0) { - a = mmutranslate_read(addr + i); - addr64a[i] = (uint32_t) a; - } else if (!((addr + i) & 0xfff)) { - a = mmutranslate_read(addr + 3); - addr64a[i] = (uint32_t) a; - if (!cpu_state.abrt) { - a = (a & ~0xfffLL) | ((uint64_t) ((addr + i) & 0xfff)); - addr64a[i] = (uint32_t) a; - } - } else { - a = (a & ~0xfffLL) | ((uint64_t) ((addr + i) & 0xfff)); - addr64a[i] = (uint32_t) a; - } + if (!cpu_cyrix_alignment || (addr & 7) > 4) + cycles -= timing_misaligned; + if ((addr & 0xfff) > 0xffc) { + if (cr0 >> 31) { + for (i = 0; i < 4; i++) { + if (i == 0) { + a = mmutranslate_read(addr + i); + addr64a[i] = (uint32_t) a; + } else if (!((addr + i) & 0xfff)) { + a = mmutranslate_read(addr + 3); + addr64a[i] = (uint32_t) a; + if (!cpu_state.abrt) { + a = (a & ~0xfffLL) | ((uint64_t) ((addr + i) & 0xfff)); + addr64a[i] = (uint32_t) a; + } + } else { + a = (a & ~0xfffLL) | ((uint64_t) ((addr + i) & 0xfff)); + addr64a[i] = (uint32_t) a; + } - if (a > 0xffffffffULL) - return 0xffff; - } - } + if (a > 0xffffffffULL) + return 0xffff; + } + } - /* No need to waste precious CPU host cycles on mmutranslate's that were already done, just pass - their result as a parameter to be used if needed. */ - return readmemwl_no_mmut(addr, addr64a) | - (((uint32_t) readmemwl_no_mmut(addr + 2, &(addr64a[2]))) << 16); - } else if (readlookup2[addr >> 12] != (uintptr_t) LOOKUP_INV) { - mmu_perm = readlookupp[addr >> 12]; - return *(uint32_t *)(readlookup2[addr >> 12] + addr); - } + /* No need to waste precious CPU host cycles on mmutranslate's that were already done, just pass + their result as a parameter to be used if needed. */ + return readmemwl_no_mmut(addr, addr64a) | (((uint32_t) readmemwl_no_mmut(addr + 2, &(addr64a[2]))) << 16); + } else if (readlookup2[addr >> 12] != (uintptr_t) LOOKUP_INV) { + mmu_perm = readlookupp[addr >> 12]; + return *(uint32_t *) (readlookup2[addr >> 12] + addr); + } } if (cr0 >> 31) { - a = mmutranslate_read(addr); - addr64a[0] = (uint32_t) a; + a = mmutranslate_read(addr); + addr64a[0] = (uint32_t) a; - if (a > 0xffffffffULL) - return 0xffffffff; + if (a > 0xffffffffULL) + return 0xffffffff; } addr = addr64a[0] & rammask; @@ -1189,90 +1195,86 @@ readmemll(uint32_t addr) map = read_mapping[addr >> MEM_GRANULARITY_BITS]; if (map && map->read_l) - return map->read_l(addr, map->p); + return map->read_l(addr, map->priv); if (map && map->read_w) - return map->read_w(addr, map->p) | - ((uint32_t) (map->read_w(addr + 2, map->p)) << 16); + return map->read_w(addr, map->priv) | ((uint32_t) (map->read_w(addr + 2, map->priv)) << 16); if (map && map->read_b) - return map->read_b(addr, map->p) | - ((uint32_t) (map->read_b(addr + 1, map->p)) << 8) | - ((uint32_t) (map->read_b(addr + 2, map->p)) << 16) | - ((uint32_t) (map->read_b(addr + 3, map->p)) << 24); + return map->read_b(addr, map->priv) | ((uint32_t) (map->read_b(addr + 1, map->priv)) << 8) | ((uint32_t) (map->read_b(addr + 2, map->priv)) << 16) | ((uint32_t) (map->read_b(addr + 3, map->priv)) << 24); return 0xffffffff; } - void writememll(uint32_t addr, uint32_t val) { mem_mapping_t *map; - int i; - uint64_t a = 0x0000000000000000ULL; + int i; + uint64_t a = 0x0000000000000000ULL; for (i = 0; i < 4; i++) - addr64a[i] = (uint64_t) (addr + i); + addr64a[i] = (uint64_t) (addr + i); + GDBSTUB_MEM_ACCESS_FAST(addr64a, GDBSTUB_MEM_WRITE, 4); mem_logical_addr = addr; high_page = 0; if (addr & 3) { - if (!cpu_cyrix_alignment || (addr & 7) > 4) - cycles -= timing_misaligned; - if ((addr & 0xfff) > 0xffc) { - if (cr0 >> 31) { - for (i = 0; i < 4; i++) { - /* Do not translate a page that has a valid lookup, as that is by definition valid - and the whole purpose of the lookup is to avoid repeat identical translations. */ - if (!page_lookup[(addr + i) >> 12] || !page_lookup[(addr + i) >> 12]->write_b) { - if (i == 0) { - a = mmutranslate_write(addr + i); - addr64a[i] = (uint32_t) a; - } else if (!((addr + i) & 0xfff)) { - a = mmutranslate_write(addr + 3); - addr64a[i] = (uint32_t) a; - if (!cpu_state.abrt) { - a = (a & ~0xfffLL) | ((uint64_t) ((addr + i) & 0xfff)); - addr64a[i] = (uint32_t) a; - } - } else { - a = (a & ~0xfffLL) | ((uint64_t) ((addr + i) & 0xfff)); - addr64a[i] = (uint32_t) a; - } + if (!cpu_cyrix_alignment || (addr & 7) > 4) + cycles -= timing_misaligned; + if ((addr & 0xfff) > 0xffc) { + if (cr0 >> 31) { + for (i = 0; i < 4; i++) { + /* Do not translate a page that has a valid lookup, as that is by definition valid + and the whole purpose of the lookup is to avoid repeat identical translations. */ + if (!page_lookup[(addr + i) >> 12] || !page_lookup[(addr + i) >> 12]->write_b) { + if (i == 0) { + a = mmutranslate_write(addr + i); + addr64a[i] = (uint32_t) a; + } else if (!((addr + i) & 0xfff)) { + a = mmutranslate_write(addr + 3); + addr64a[i] = (uint32_t) a; + if (!cpu_state.abrt) { + a = (a & ~0xfffLL) | ((uint64_t) ((addr + i) & 0xfff)); + addr64a[i] = (uint32_t) a; + } + } else { + a = (a & ~0xfffLL) | ((uint64_t) ((addr + i) & 0xfff)); + addr64a[i] = (uint32_t) a; + } - if (a > 0xffffffffULL) - return; - } - } - } + if (a > 0xffffffffULL) + return; + } + } + } - /* No need to waste precious CPU host cycles on mmutranslate's that were already done, just pass - their result as a parameter to be used if needed. */ - writememwl_no_mmut(addr, &(addr64a[0]), val); - writememwl_no_mmut(addr + 2, &(addr64a[2]), val >> 16); - return; - } else if (writelookup2[addr >> 12] != (uintptr_t) LOOKUP_INV) { - mmu_perm = writelookupp[addr >> 12]; - *(uint32_t *)(writelookup2[addr >> 12] + addr) = val; - return; - } + /* No need to waste precious CPU host cycles on mmutranslate's that were already done, just pass + their result as a parameter to be used if needed. */ + writememwl_no_mmut(addr, &(addr64a[0]), val); + writememwl_no_mmut(addr + 2, &(addr64a[2]), val >> 16); + return; + } else if (writelookup2[addr >> 12] != (uintptr_t) LOOKUP_INV) { + mmu_perm = writelookupp[addr >> 12]; + *(uint32_t *) (writelookup2[addr >> 12] + addr) = val; + return; + } } if (page_lookup[addr >> 12] && page_lookup[addr >> 12]->write_l) { - mmu_perm = page_lookupp[addr >> 12]; - page_lookup[addr >> 12]->write_l(addr, val, page_lookup[addr >> 12]); - return; + mmu_perm = page_lookupp[addr >> 12]; + page_lookup[addr >> 12]->write_l(addr, val, page_lookup[addr >> 12]); + return; } if (cr0 >> 31) { - a = mmutranslate_write(addr); - addr64a[0] = (uint32_t) a; + a = mmutranslate_write(addr); + addr64a[0] = (uint32_t) a; - if (a > 0xffffffffULL) - return; + if (a > 0xffffffffULL) + return; } addr = addr64a[0] & rammask; @@ -1280,279 +1282,267 @@ writememll(uint32_t addr, uint32_t val) map = write_mapping[addr >> MEM_GRANULARITY_BITS]; if (map && map->write_l) { - map->write_l(addr, val, map->p); - return; + map->write_l(addr, val, map->priv); + return; } if (map && map->write_w) { - map->write_w(addr, val, map->p); - map->write_w(addr + 2, val >> 16, map->p); - return; + map->write_w(addr, val, map->priv); + map->write_w(addr + 2, val >> 16, map->priv); + return; } if (map && map->write_b) { - map->write_b(addr, val, map->p); - map->write_b(addr + 1, val >> 8, map->p); - map->write_b(addr + 2, val >> 16, map->p); - map->write_b(addr + 3, val >> 24, map->p); - return; + map->write_b(addr, val, map->priv); + map->write_b(addr + 1, val >> 8, map->priv); + map->write_b(addr + 2, val >> 16, map->priv); + map->write_b(addr + 3, val >> 24, map->priv); + return; } } - /* Read a long from memory without MMU translation - results of previous MMU translation passed as array. */ uint32_t readmemll_no_mmut(uint32_t addr, uint32_t *a64) { -#ifndef NO_MMUT mem_mapping_t *map; + GDBSTUB_MEM_ACCESS(addr, GDBSTUB_MEM_READ, 4); + mem_logical_addr = addr; if (addr & 3) { - if (!cpu_cyrix_alignment || (addr & 7) > 4) - cycles -= timing_misaligned; - if ((addr & 0xfff) > 0xffc) { - if (cr0 >> 31) { - if (cpu_state.abrt || high_page) - return 0xffffffff; - } + if (!cpu_cyrix_alignment || (addr & 7) > 4) + cycles -= timing_misaligned; + if ((addr & 0xfff) > 0xffc) { + if (cr0 >> 31) { + if (cpu_state.abrt || high_page) + return 0xffffffff; + } - return readmemwl_no_mmut(addr, a64) | - ((uint32_t) (readmemwl_no_mmut(addr + 2, &(a64[2]))) << 16); - } else if (readlookup2[addr >> 12] != (uintptr_t) LOOKUP_INV) { - mmu_perm = readlookupp[addr >> 12]; - return *(uint32_t *)(readlookup2[addr >> 12] + addr); - } + return readmemwl_no_mmut(addr, a64) | ((uint32_t) (readmemwl_no_mmut(addr + 2, &(a64[2]))) << 16); + } else if (readlookup2[addr >> 12] != (uintptr_t) LOOKUP_INV) { + mmu_perm = readlookupp[addr >> 12]; + return *(uint32_t *) (readlookup2[addr >> 12] + addr); + } } if (cr0 >> 31) { - if (cpu_state.abrt || high_page) - return 0xffffffff; + if (cpu_state.abrt || high_page) + return 0xffffffff; - addr = (uint32_t) (a64[0] & rammask); + addr = (uint32_t) (a64[0] & rammask); } else - addr &= rammask; + addr &= rammask; map = read_mapping[addr >> MEM_GRANULARITY_BITS]; if (map && map->read_l) - return map->read_l(addr, map->p); + return map->read_l(addr, map->priv); if (map && map->read_w) - return map->read_w(addr, map->p) | - ((uint32_t) (map->read_w(addr + 2, map->p)) << 16); + return map->read_w(addr, map->priv) | ((uint32_t) (map->read_w(addr + 2, map->priv)) << 16); if (map && map->read_b) - return map->read_b(addr, map->p) | - ((uint32_t) (map->read_b(addr + 1, map->p)) << 8) | - ((uint32_t) (map->read_b(addr + 2, map->p)) << 16) | - ((uint32_t) (map->read_b(addr + 3, map->p)) << 24); + return map->read_b(addr, map->priv) | ((uint32_t) (map->read_b(addr + 1, map->priv)) << 8) | ((uint32_t) (map->read_b(addr + 2, map->priv)) << 16) | ((uint32_t) (map->read_b(addr + 3, map->priv)) << 24); return 0xffffffff; -#else - return readmemll(addr); -#endif } - /* Write a long to memory without MMU translation - results of previous MMU translation passed as array. */ void writememll_no_mmut(uint32_t addr, uint32_t *a64, uint32_t val) { -#ifndef NO_MMUT mem_mapping_t *map; + GDBSTUB_MEM_ACCESS(addr, GDBSTUB_MEM_WRITE, 4); + mem_logical_addr = addr; if (addr & 3) { - if (!cpu_cyrix_alignment || (addr & 7) > 4) - cycles -= timing_misaligned; - if ((addr & 0xfff) > 0xffc) { - if (cr0 >> 31) { - if (cpu_state.abrt || high_page) - return; - } + if (!cpu_cyrix_alignment || (addr & 7) > 4) + cycles -= timing_misaligned; + if ((addr & 0xfff) > 0xffc) { + if (cr0 >> 31) { + if (cpu_state.abrt || high_page) + return; + } - writememwl_no_mmut(addr, &(a64[0]), val); - writememwl_no_mmut(addr + 2, &(a64[2]), val >> 16); - return; - } else if (writelookup2[addr >> 12] != (uintptr_t) LOOKUP_INV) { - mmu_perm = writelookupp[addr >> 12]; - *(uint32_t *)(writelookup2[addr >> 12] + addr) = val; - return; - } + writememwl_no_mmut(addr, &(a64[0]), val); + writememwl_no_mmut(addr + 2, &(a64[2]), val >> 16); + return; + } else if (writelookup2[addr >> 12] != (uintptr_t) LOOKUP_INV) { + mmu_perm = writelookupp[addr >> 12]; + *(uint32_t *) (writelookup2[addr >> 12] + addr) = val; + return; + } } if (page_lookup[addr >> 12] && page_lookup[addr >> 12]->write_l) { - mmu_perm = page_lookupp[addr >> 12]; - page_lookup[addr >> 12]->write_l(addr, val, page_lookup[addr >> 12]); - return; + mmu_perm = page_lookupp[addr >> 12]; + page_lookup[addr >> 12]->write_l(addr, val, page_lookup[addr >> 12]); + return; } if (cr0 >> 31) { - if (cpu_state.abrt || high_page) - return; + if (cpu_state.abrt || high_page) + return; - addr = (uint32_t) (a64[0] & rammask); + addr = (uint32_t) (a64[0] & rammask); } else - addr &= rammask; + addr &= rammask; map = write_mapping[addr >> MEM_GRANULARITY_BITS]; if (map && map->write_l) { - map->write_l(addr, val, map->p); - return; + map->write_l(addr, val, map->priv); + return; } if (map && map->write_w) { - map->write_w(addr, val, map->p); - map->write_w(addr + 2, val >> 16, map->p); - return; + map->write_w(addr, val, map->priv); + map->write_w(addr + 2, val >> 16, map->priv); + return; } if (map && map->write_b) { - map->write_b(addr, val, map->p); - map->write_b(addr + 1, val >> 8, map->p); - map->write_b(addr + 2, val >> 16, map->p); - map->write_b(addr + 3, val >> 24, map->p); - return; + map->write_b(addr, val, map->priv); + map->write_b(addr + 1, val >> 8, map->priv); + map->write_b(addr + 2, val >> 16, map->priv); + map->write_b(addr + 3, val >> 24, map->priv); + return; } -#else - writememll(addr, val); -#endif } - uint64_t readmemql(uint32_t addr) { mem_mapping_t *map; - int i; - uint64_t a = 0x0000000000000000ULL; + int i; + uint64_t a = 0x0000000000000000ULL; for (i = 0; i < 8; i++) - addr64a[i] = (uint64_t) (addr + i); + addr64a[i] = (uint64_t) (addr + i); + GDBSTUB_MEM_ACCESS_FAST(addr64a, GDBSTUB_MEM_READ, 8); mem_logical_addr = addr; high_page = 0; if (addr & 7) { - cycles -= timing_misaligned; - if ((addr & 0xfff) > 0xff8) { - if (cr0 >> 31) { - for (i = 0; i < 8; i++) { - if (i == 0) { - a = mmutranslate_read(addr + i); - addr64a[i] = (uint32_t) a; - } else if (!((addr + i) & 0xfff)) { - a = mmutranslate_read(addr + 7); - addr64a[i] = (uint32_t) a; - if (!cpu_state.abrt) { - a = (a & ~0xfffLL) | ((uint64_t) ((addr + i) & 0xfff)); - addr64a[i] = (uint32_t) a; - } - } else { - a = (a & ~0xfffLL) | ((uint64_t) ((addr + i) & 0xfff)); - addr64a[i] = (uint32_t) a; - } + cycles -= timing_misaligned; + if ((addr & 0xfff) > 0xff8) { + if (cr0 >> 31) { + for (i = 0; i < 8; i++) { + if (i == 0) { + a = mmutranslate_read(addr + i); + addr64a[i] = (uint32_t) a; + } else if (!((addr + i) & 0xfff)) { + a = mmutranslate_read(addr + 7); + addr64a[i] = (uint32_t) a; + if (!cpu_state.abrt) { + a = (a & ~0xfffLL) | ((uint64_t) ((addr + i) & 0xfff)); + addr64a[i] = (uint32_t) a; + } + } else { + a = (a & ~0xfffLL) | ((uint64_t) ((addr + i) & 0xfff)); + addr64a[i] = (uint32_t) a; + } - if (a > 0xffffffffULL) - return 0xffff; - } - } + if (a > 0xffffffffULL) + return 0xffff; + } + } - /* No need to waste precious CPU host cycles on mmutranslate's that were already done, just pass - their result as a parameter to be used if needed. */ - return readmemll_no_mmut(addr, addr64a) | - (((uint64_t) readmemll_no_mmut(addr + 4, &(addr64a[4]))) << 32); - } else if (readlookup2[addr >> 12] != (uintptr_t) LOOKUP_INV) { - mmu_perm = readlookupp[addr >> 12]; - return *(uint64_t *)(readlookup2[addr >> 12] + addr); - } + /* No need to waste precious CPU host cycles on mmutranslate's that were already done, just pass + their result as a parameter to be used if needed. */ + return readmemll_no_mmut(addr, addr64a) | (((uint64_t) readmemll_no_mmut(addr + 4, &(addr64a[4]))) << 32); + } else if (readlookup2[addr >> 12] != (uintptr_t) LOOKUP_INV) { + mmu_perm = readlookupp[addr >> 12]; + return *(uint64_t *) (readlookup2[addr >> 12] + addr); + } } if (cr0 >> 31) { - a = mmutranslate_read(addr); + a = mmutranslate_read(addr); addr64a[0] = (uint32_t) a; - if (a > 0xffffffffULL) - return 0xffffffffffffffffULL; + if (a > 0xffffffffULL) + return 0xffffffffffffffffULL; } addr = addr64a[0] & rammask; map = read_mapping[addr >> MEM_GRANULARITY_BITS]; if (map && map->read_l) - return map->read_l(addr, map->p) | ((uint64_t)map->read_l(addr + 4, map->p) << 32); + return map->read_l(addr, map->priv) | ((uint64_t) map->read_l(addr + 4, map->priv) << 32); return readmemll(addr) | ((uint64_t) readmemll(addr + 4) << 32); } - void writememql(uint32_t addr, uint64_t val) { mem_mapping_t *map; - int i; - uint64_t a = 0x0000000000000000ULL; + int i; + uint64_t a = 0x0000000000000000ULL; for (i = 0; i < 8; i++) - addr64a[i] = (uint64_t) (addr + i); + addr64a[i] = (uint64_t) (addr + i); + GDBSTUB_MEM_ACCESS_FAST(addr64a, GDBSTUB_MEM_WRITE, 8); mem_logical_addr = addr; high_page = 0; if (addr & 7) { - cycles -= timing_misaligned; - if ((addr & 0xfff) > 0xff8) { - if (cr0 >> 31) { - for (i = 0; i < 8; i++) { - /* Do not translate a page that has a valid lookup, as that is by definition valid - and the whole purpose of the lookup is to avoid repeat identical translations. */ - if (!page_lookup[(addr + i) >> 12] || !page_lookup[(addr + i) >> 12]->write_b) { - if (i == 0) { - a = mmutranslate_write(addr + i); - addr64a[i] = (uint32_t) a; - } else if (!((addr + i) & 0xfff)) { - a = mmutranslate_write(addr + 7); - addr64a[i] = (uint32_t) a; - if (!cpu_state.abrt) { - a = (a & ~0xfffLL) | ((uint64_t) ((addr + i) & 0xfff)); - addr64a[i] = (uint32_t) a; - } - } else { - a = (a & ~0xfffLL) | ((uint64_t) ((addr + i) & 0xfff)); - addr64a[i] = (uint32_t) a; - } + cycles -= timing_misaligned; + if ((addr & 0xfff) > 0xff8) { + if (cr0 >> 31) { + for (i = 0; i < 8; i++) { + /* Do not translate a page that has a valid lookup, as that is by definition valid + and the whole purpose of the lookup is to avoid repeat identical translations. */ + if (!page_lookup[(addr + i) >> 12] || !page_lookup[(addr + i) >> 12]->write_b) { + if (i == 0) { + a = mmutranslate_write(addr + i); + addr64a[i] = (uint32_t) a; + } else if (!((addr + i) & 0xfff)) { + a = mmutranslate_write(addr + 7); + addr64a[i] = (uint32_t) a; + if (!cpu_state.abrt) { + a = (a & ~0xfffLL) | ((uint64_t) ((addr + i) & 0xfff)); + addr64a[i] = (uint32_t) a; + } + } else { + a = (a & ~0xfffLL) | ((uint64_t) ((addr + i) & 0xfff)); + addr64a[i] = (uint32_t) a; + } - if (addr64a[i] > 0xffffffffULL) - return; - } - } - } + if (addr64a[i] > 0xffffffffULL) + return; + } + } + } - /* No need to waste precious CPU host cycles on mmutranslate's that were already done, just pass - their result as a parameter to be used if needed. */ - writememll_no_mmut(addr, addr64a, val); - writememll_no_mmut(addr + 4, &(addr64a[4]), val >> 32); - return; - } else if (writelookup2[addr >> 12] != (uintptr_t) LOOKUP_INV) { - mmu_perm = writelookupp[addr >> 12]; - *(uint64_t *)(writelookup2[addr >> 12] + addr) = val; - return; - } + /* No need to waste precious CPU host cycles on mmutranslate's that were already done, just pass + their result as a parameter to be used if needed. */ + writememll_no_mmut(addr, addr64a, val); + writememll_no_mmut(addr + 4, &(addr64a[4]), val >> 32); + return; + } else if (writelookup2[addr >> 12] != (uintptr_t) LOOKUP_INV) { + mmu_perm = writelookupp[addr >> 12]; + *(uint64_t *) (writelookup2[addr >> 12] + addr) = val; + return; + } } if (page_lookup[addr >> 12] && page_lookup[addr >> 12]->write_l) { - mmu_perm = page_lookupp[addr >> 12]; - page_lookup[addr >> 12]->write_l(addr, val, page_lookup[addr >> 12]); - page_lookup[addr >> 12]->write_l(addr + 4, val >> 32, page_lookup[addr >> 12]); - return; + mmu_perm = page_lookupp[addr >> 12]; + page_lookup[addr >> 12]->write_l(addr, val, page_lookup[addr >> 12]); + page_lookup[addr >> 12]->write_l(addr + 4, val >> 32, page_lookup[addr >> 12]); + return; } if (cr0 >> 31) { - addr64a[0] = mmutranslate_write(addr); - if (addr64a[0] > 0xffffffffULL) - return; + addr64a[0] = mmutranslate_write(addr); + if (addr64a[0] > 0xffffffffULL) + return; } addr = addr64a[0] & rammask; @@ -1560,164 +1550,161 @@ writememql(uint32_t addr, uint64_t val) map = write_mapping[addr >> MEM_GRANULARITY_BITS]; if (map && map->write_l) { - map->write_l(addr, val, map->p); - map->write_l(addr + 4, val >> 32, map->p); - return; + map->write_l(addr, val, map->priv); + map->write_l(addr + 4, val >> 32, map->priv); + return; } if (map && map->write_w) { - map->write_w(addr, val, map->p); - map->write_w(addr + 2, val >> 16, map->p); - map->write_w(addr + 4, val >> 32, map->p); - map->write_w(addr + 6, val >> 48, map->p); - return; + map->write_w(addr, val, map->priv); + map->write_w(addr + 2, val >> 16, map->priv); + map->write_w(addr + 4, val >> 32, map->priv); + map->write_w(addr + 6, val >> 48, map->priv); + return; } if (map && map->write_b) { - map->write_b(addr, val, map->p); - map->write_b(addr + 1, val >> 8, map->p); - map->write_b(addr + 2, val >> 16, map->p); - map->write_b(addr + 3, val >> 24, map->p); - map->write_b(addr + 4, val >> 32, map->p); - map->write_b(addr + 5, val >> 40, map->p); - map->write_b(addr + 6, val >> 48, map->p); - map->write_b(addr + 7, val >> 56, map->p); - return; + map->write_b(addr, val, map->priv); + map->write_b(addr + 1, val >> 8, map->priv); + map->write_b(addr + 2, val >> 16, map->priv); + map->write_b(addr + 3, val >> 24, map->priv); + map->write_b(addr + 4, val >> 32, map->priv); + map->write_b(addr + 5, val >> 40, map->priv); + map->write_b(addr + 6, val >> 48, map->priv); + map->write_b(addr + 7, val >> 56, map->priv); + return; } } - void do_mmutranslate(uint32_t addr, uint32_t *a64, int num, int write) { - int i, cond = 1; + int i; + int cond = 1; uint32_t last_addr = addr + (num - 1); - uint64_t a = 0x0000000000000000ULL; + uint64_t a = 0x0000000000000000ULL; for (i = 0; i < num; i++) - a64[i] = (uint64_t) addr; + a64[i] = (uint64_t) addr; for (i = 0; i < num; i++) { - if (cr0 >> 31) { - if (write && ((i == 0) || !(addr & 0xfff))) - cond = (!page_lookup[addr >> 12] || !page_lookup[addr >> 12]->write_b); + if (cr0 >> 31) { + if (write && ((i == 0) || !(addr & 0xfff))) + cond = (!page_lookup[addr >> 12] || !page_lookup[addr >> 12]->write_b); - if (cond) { - /* If we have encountered at least one page fault, mark all subsequent addresses as - having page faulted, prevents false negatives in readmem*l_no_mmut. */ - if ((i > 0) && cpu_state.abrt && !high_page) - a64[i] = a64[i - 1]; - /* If we are on the same page, there is no need to translate again, as we can just - reuse the previous result. */ - else if (i == 0) { - a = mmutranslatereal(addr, write); - a64[i] = (uint32_t) a; + if (cond) { + /* If we have encountered at least one page fault, mark all subsequent addresses as + having page faulted, prevents false negatives in readmem*l_no_mmut. */ + if ((i > 0) && cpu_state.abrt && !high_page) + a64[i] = a64[i - 1]; + /* If we are on the same page, there is no need to translate again, as we can just + reuse the previous result. */ + else if (i == 0) { + a = mmutranslatereal(addr, write); + a64[i] = (uint32_t) a; - high_page = high_page || (!cpu_state.abrt && (a > 0xffffffffULL)); - } else if (!(addr & 0xfff)) { - a = mmutranslatereal(last_addr, write); - a64[i] = (uint32_t) a; + high_page = high_page || (!cpu_state.abrt && (a > 0xffffffffULL)); + } else if (!(addr & 0xfff)) { + a = mmutranslatereal(last_addr, write); + a64[i] = (uint32_t) a; - high_page = high_page || (!cpu_state.abrt && (a64[i] > 0xffffffffULL)); + high_page = high_page || (!cpu_state.abrt && (a64[i] > 0xffffffffULL)); - if (!cpu_state.abrt) { - a = (a & 0xfffffffffffff000ULL) | ((uint64_t) (addr & 0xfff)); - a64[i] = (uint32_t) a; - } - } else { - a = (a & 0xfffffffffffff000ULL) | ((uint64_t) (addr & 0xfff)); - a64[i] = (uint32_t) a; - } - } else - mmu_perm = page_lookupp[addr >> 12]; - } + if (!cpu_state.abrt) { + a = (a & 0xfffffffffffff000ULL) | ((uint64_t) (addr & 0xfff)); + a64[i] = (uint32_t) a; + } + } else { + a = (a & 0xfffffffffffff000ULL) | ((uint64_t) (addr & 0xfff)); + a64[i] = (uint32_t) a; + } + } else + mmu_perm = page_lookupp[addr >> 12]; + } - addr++; + addr++; } } - uint8_t mem_readb_phys(uint32_t addr) { mem_mapping_t *map = read_mapping_bus[addr >> MEM_GRANULARITY_BITS]; - uint8_t ret = 0xff; + uint8_t ret = 0xff; mem_logical_addr = 0xffffffff; if (map) { - if (map->exec) - ret = map->exec[addr - map->base]; - else if (map->read_b) - ret = map->read_b(addr, map->p); + if (map->exec) + ret = map->exec[(addr - map->base) & map->mask]; + else if (map->read_b) + ret = map->read_b(addr, map->priv); } return ret; } - uint16_t mem_readw_phys(uint32_t addr) { - mem_mapping_t *map = read_mapping_bus[addr >> MEM_GRANULARITY_BITS]; - uint16_t ret, *p; + mem_mapping_t *map = read_mapping_bus[addr >> MEM_GRANULARITY_BITS]; + uint16_t ret; + const uint16_t *p; mem_logical_addr = 0xffffffff; if (((addr & MEM_GRANULARITY_MASK) <= MEM_GRANULARITY_HBOUND) && (map && map->exec)) { - p = (uint16_t *) &(map->exec[addr - map->base]); - ret = *p; + p = (uint16_t *) &(map->exec[(addr - map->base) & map->mask]); + ret = *p; } else if (((addr & MEM_GRANULARITY_MASK) <= MEM_GRANULARITY_HBOUND) && (map && map->read_w)) - ret = map->read_w(addr, map->p); + ret = map->read_w(addr, map->priv); else { - ret = mem_readb_phys(addr + 1) << 8; - ret |= mem_readb_phys(addr); + ret = mem_readb_phys(addr + 1) << 8; + ret |= mem_readb_phys(addr); } return ret; } - uint32_t mem_readl_phys(uint32_t addr) { - mem_mapping_t *map = read_mapping_bus[addr >> MEM_GRANULARITY_BITS]; - uint32_t ret, *p; + mem_mapping_t *map = read_mapping_bus[addr >> MEM_GRANULARITY_BITS]; + uint32_t ret; + const uint32_t *p; mem_logical_addr = 0xffffffff; if (((addr & MEM_GRANULARITY_MASK) <= MEM_GRANULARITY_QBOUND) && (map && map->exec)) { - p = (uint32_t *) &(map->exec[addr - map->base]); - ret = *p; + p = (uint32_t *) &(map->exec[(addr - map->base) & map->mask]); + ret = *p; } else if (((addr & MEM_GRANULARITY_MASK) <= MEM_GRANULARITY_QBOUND) && (map && map->read_l)) - ret = map->read_l(addr, map->p); + ret = map->read_l(addr, map->priv); else { - ret = mem_readw_phys(addr + 2) << 16; - ret |= mem_readw_phys(addr); + ret = mem_readw_phys(addr + 2) << 16; + ret |= mem_readw_phys(addr); } return ret; } - void mem_read_phys(void *dest, uint32_t addr, int transfer_size) { - uint8_t *pb; + uint8_t *pb; uint16_t *pw; uint32_t *pl; if (transfer_size == 4) { - pl = (uint32_t *) dest; - *pl = mem_readl_phys(addr); + pl = (uint32_t *) dest; + *pl = mem_readl_phys(addr); } else if (transfer_size == 2) { - pw = (uint16_t *) dest; - *pw = mem_readw_phys(addr); + pw = (uint16_t *) dest; + *pw = mem_readw_phys(addr); } else if (transfer_size == 1) { - pb = (uint8_t *) dest; - *pb = mem_readb_phys(addr); + pb = (uint8_t *) dest; + *pb = mem_readb_phys(addr); } } - void mem_writeb_phys(uint32_t addr, uint8_t val) { @@ -1726,125 +1713,118 @@ mem_writeb_phys(uint32_t addr, uint8_t val) mem_logical_addr = 0xffffffff; if (map) { - if (map->exec) - map->exec[addr - map->base] = val; - else if (map->write_b) - map->write_b(addr, val, map->p); - } + if (map->exec) + map->exec[(addr - map->base) & map->mask] = val; + else if (map->write_b) + map->write_b(addr, val, map->priv); + } } - void mem_writew_phys(uint32_t addr, uint16_t val) { mem_mapping_t *map = write_mapping_bus[addr >> MEM_GRANULARITY_BITS]; - uint16_t *p; + uint16_t *p; mem_logical_addr = 0xffffffff; if (((addr & MEM_GRANULARITY_MASK) <= MEM_GRANULARITY_HBOUND) && (map && map->exec)) { - p = (uint16_t *) &(map->exec[addr - map->base]); - *p = val; + p = (uint16_t *) &(map->exec[(addr - map->base) & map->mask]); + *p = val; } else if (((addr & MEM_GRANULARITY_MASK) <= MEM_GRANULARITY_HBOUND) && (map && map->write_w)) - map->write_w(addr, val, map->p); + map->write_w(addr, val, map->priv); else { - mem_writeb_phys(addr, val & 0xff); - mem_writeb_phys(addr + 1, (val >> 8) & 0xff); + mem_writeb_phys(addr, val & 0xff); + mem_writeb_phys(addr + 1, (val >> 8) & 0xff); } } - void mem_writel_phys(uint32_t addr, uint32_t val) { mem_mapping_t *map = write_mapping_bus[addr >> MEM_GRANULARITY_BITS]; - uint32_t *p; + uint32_t *p; mem_logical_addr = 0xffffffff; if (((addr & MEM_GRANULARITY_MASK) <= MEM_GRANULARITY_QBOUND) && (map && map->exec)) { - p = (uint32_t *) &(map->exec[addr - map->base]); - *p = val; + p = (uint32_t *) &(map->exec[(addr - map->base) & map->mask]); + *p = val; } else if (((addr & MEM_GRANULARITY_MASK) <= MEM_GRANULARITY_QBOUND) && (map && map->write_l)) - map->write_l(addr, val, map->p); + map->write_l(addr, val, map->priv); else { - mem_writew_phys(addr, val & 0xffff); - mem_writew_phys(addr + 2, (val >> 16) & 0xffff); + mem_writew_phys(addr, val & 0xffff); + mem_writew_phys(addr + 2, (val >> 16) & 0xffff); } } - void mem_write_phys(void *src, uint32_t addr, int transfer_size) { - uint8_t *pb; - uint16_t *pw; - uint32_t *pl; + const uint8_t *pb; + const uint16_t *pw; + const uint32_t *pl; if (transfer_size == 4) { - pl = (uint32_t *) src; - mem_writel_phys(addr, *pl); + pl = (uint32_t *) src; + mem_writel_phys(addr, *pl); } else if (transfer_size == 2) { - pw = (uint16_t *) src; - mem_writew_phys(addr, *pw); + pw = (uint16_t *) src; + mem_writew_phys(addr, *pw); } else if (transfer_size == 1) { - pb = (uint8_t *) src; - mem_writeb_phys(addr, *pb); + pb = (uint8_t *) src; + mem_writeb_phys(addr, *pb); } } - uint8_t -mem_read_ram(uint32_t addr, void *priv) +mem_read_ram(uint32_t addr, UNUSED(void *priv)) { #ifdef ENABLE_MEM_LOG if ((addr >= 0xa0000) && (addr <= 0xbffff)) - mem_log("Read B %02X from %08X\n", ram[addr], addr); + mem_log("Read B %02X from %08X\n", ram[addr], addr); #endif if (is286) - addreadlookup(mem_logical_addr, addr); + addreadlookup(mem_logical_addr, addr); return ram[addr]; } - uint16_t -mem_read_ramw(uint32_t addr, void *priv) +mem_read_ramw(uint32_t addr, UNUSED(void *priv)) { #ifdef ENABLE_MEM_LOG if ((addr >= 0xa0000) && (addr <= 0xbffff)) - mem_log("Read W %04X from %08X\n", *(uint16_t *)&ram[addr], addr); + mem_log("Read W %04X from %08X\n", *(uint16_t *) &ram[addr], addr); #endif if (is286) - addreadlookup(mem_logical_addr, addr); + addreadlookup(mem_logical_addr, addr); - return *(uint16_t *)&ram[addr]; + return *(uint16_t *) &ram[addr]; } - uint32_t -mem_read_raml(uint32_t addr, void *priv) +mem_read_raml(uint32_t addr, UNUSED(void *priv)) { #ifdef ENABLE_MEM_LOG if ((addr >= 0xa0000) && (addr <= 0xbffff)) - mem_log("Read L %08X from %08X\n", *(uint32_t *)&ram[addr], addr); + mem_log("Read L %08X from %08X\n", *(uint32_t *) &ram[addr], addr); #endif if (is286) - addreadlookup(mem_logical_addr, addr); + addreadlookup(mem_logical_addr, addr); - return *(uint32_t *)&ram[addr]; + return *(uint32_t *) &ram[addr]; } - uint8_t -mem_read_ram_2gb(uint32_t addr, void *priv) +mem_read_ram_2gb(uint32_t addr, UNUSED(void *priv)) { #ifdef ENABLE_MEM_LOG if ((addr >= 0xa0000) && (addr <= 0xbffff)) - mem_log("Read B %02X from %08X\n", ram[addr], addr); + mem_log("Read B %02X from %08X\n", ram[addr], addr); #endif addreadlookup(mem_logical_addr, addr); @@ -1852,495 +1832,577 @@ mem_read_ram_2gb(uint32_t addr, void *priv) return ram2[addr - (1 << 30)]; } - uint16_t -mem_read_ram_2gbw(uint32_t addr, void *priv) +mem_read_ram_2gbw(uint32_t addr, UNUSED(void *priv)) { #ifdef ENABLE_MEM_LOG if ((addr >= 0xa0000) && (addr <= 0xbffff)) - mem_log("Read W %04X from %08X\n", *(uint16_t *)&ram[addr], addr); + mem_log("Read W %04X from %08X\n", *(uint16_t *) &ram[addr], addr); #endif addreadlookup(mem_logical_addr, addr); - return *(uint16_t *)&ram2[addr - (1 << 30)]; + return *(uint16_t *) &ram2[addr - (1 << 30)]; } - uint32_t -mem_read_ram_2gbl(uint32_t addr, void *priv) +mem_read_ram_2gbl(uint32_t addr, UNUSED(void *priv)) { #ifdef ENABLE_MEM_LOG if ((addr >= 0xa0000) && (addr <= 0xbffff)) - mem_log("Read L %08X from %08X\n", *(uint32_t *)&ram[addr], addr); + mem_log("Read L %08X from %08X\n", *(uint32_t *) &ram[addr], addr); #endif addreadlookup(mem_logical_addr, addr); - return *(uint32_t *)&ram2[addr - (1 << 30)]; + return *(uint32_t *) &ram2[addr - (1 << 30)]; } - #ifdef USE_NEW_DYNAREC static inline int -page_index(page_t *p) +page_index(page_t *page) { - return ((uintptr_t)p - (uintptr_t)pages) / sizeof(page_t); + return ((uintptr_t) page - (uintptr_t) pages) / sizeof(page_t); } - void -page_add_to_evict_list(page_t *p) +page_add_to_evict_list(page_t *page) { - pages[purgable_page_list_head].evict_prev = page_index(p); - p->evict_next = purgable_page_list_head; - p->evict_prev = 0; - purgable_page_list_head = pages[purgable_page_list_head].evict_prev; + pages[purgable_page_list_head].evict_prev = page_index(page); + page->evict_next = purgable_page_list_head; + page->evict_prev = 0; + purgable_page_list_head = pages[purgable_page_list_head].evict_prev; purgeable_page_count++; } - void -page_remove_from_evict_list(page_t *p) +page_remove_from_evict_list(page_t *page) { - if (!page_in_evict_list(p)) - fatal("page_remove_from_evict_list: not in evict list!\n"); - if (p->evict_prev) - pages[p->evict_prev].evict_next = p->evict_next; + if (!page_in_evict_list(page)) + fatal("page_remove_from_evict_list: not in evict list!\n"); + if (page->evict_prev) + pages[page->evict_prev].evict_next = page->evict_next; else - purgable_page_list_head = p->evict_next; - if (p->evict_next) - pages[p->evict_next].evict_prev = p->evict_prev; - p->evict_prev = EVICT_NOT_IN_LIST; - purgeable_page_count--; + purgable_page_list_head = page->evict_next; + if (page->evict_next) + pages[page->evict_next].evict_prev = page->evict_prev; + page->evict_prev = EVICT_NOT_IN_LIST; + purgeable_page_count--; } - void -mem_write_ramb_page(uint32_t addr, uint8_t val, page_t *p) +mem_write_ramb_page(uint32_t addr, uint8_t val, page_t *page) { - if (p == NULL) - return; + if (page == NULL) + return; -#ifdef USE_DYNAREC - if ((p->mem == NULL) || (p->mem == page_ff) || (val != p->mem[addr & 0xfff]) || codegen_in_recompile) { -#else - if ((p->mem == NULL) || (p->mem == page_ff) || (val != p->mem[addr & 0xfff])) { -#endif - uint64_t mask = (uint64_t)1 << ((addr >> PAGE_MASK_SHIFT) & PAGE_MASK_MASK); - int byte_offset = (addr >> PAGE_BYTE_MASK_SHIFT) & PAGE_BYTE_MASK_OFFSET_MASK; - uint64_t byte_mask = (uint64_t)1 << (addr & PAGE_BYTE_MASK_MASK); +# ifdef USE_DYNAREC + if ((page->mem == NULL) || (page->mem == page_ff) || (val != page->mem[addr & 0xfff]) || codegen_in_recompile) { +# else + if ((page->mem == NULL) || (page->mem == page_ff) || (val != page->mem[addr & 0xfff])) { +# endif + uint64_t mask = (uint64_t) 1 << ((addr >> PAGE_MASK_SHIFT) & PAGE_MASK_MASK); + int byte_offset = (addr >> PAGE_BYTE_MASK_SHIFT) & PAGE_BYTE_MASK_OFFSET_MASK; + uint64_t byte_mask = (uint64_t) 1 << (addr & PAGE_BYTE_MASK_MASK); - p->mem[addr & 0xfff] = val; - p->dirty_mask |= mask; - if ((p->code_present_mask & mask) && !page_in_evict_list(p)) - page_add_to_evict_list(p); - p->byte_dirty_mask[byte_offset] |= byte_mask; - if ((p->byte_code_present_mask[byte_offset] & byte_mask) && !page_in_evict_list(p)) - page_add_to_evict_list(p); + page->mem[addr & 0xfff] = val; + page->dirty_mask |= mask; + if ((page->code_present_mask & mask) && !page_in_evict_list(page)) + page_add_to_evict_list(page); + page->byte_dirty_mask[byte_offset] |= byte_mask; + if ((page->byte_code_present_mask[byte_offset] & byte_mask) && !page_in_evict_list(page)) + page_add_to_evict_list(page); } } - void -mem_write_ramw_page(uint32_t addr, uint16_t val, page_t *p) +mem_write_ramw_page(uint32_t addr, uint16_t val, page_t *page) { - if (p == NULL) - return; + if (page == NULL) + return; -#ifdef USE_DYNAREC - if ((p->mem == NULL) || (p->mem == page_ff) || (val != *(uint16_t *)&p->mem[addr & 0xfff]) || codegen_in_recompile) { -#else - if ((p->mem == NULL) || (p->mem == page_ff) || (val != *(uint16_t *)&p->mem[addr & 0xfff])) { -#endif - uint64_t mask = (uint64_t)1 << ((addr >> PAGE_MASK_SHIFT) & PAGE_MASK_MASK); - int byte_offset = (addr >> PAGE_BYTE_MASK_SHIFT) & PAGE_BYTE_MASK_OFFSET_MASK; - uint64_t byte_mask = (uint64_t)1 << (addr & PAGE_BYTE_MASK_MASK); +# ifdef USE_DYNAREC + if ((page->mem == NULL) || (page->mem == page_ff) || (val != *(uint16_t *) &page->mem[addr & 0xfff]) || codegen_in_recompile) { +# else + if ((page->mem == NULL) || (page->mem == page_ff) || (val != *(uint16_t *) &page->mem[addr & 0xfff])) { +# endif + uint64_t mask = (uint64_t) 1 << ((addr >> PAGE_MASK_SHIFT) & PAGE_MASK_MASK); + int byte_offset = (addr >> PAGE_BYTE_MASK_SHIFT) & PAGE_BYTE_MASK_OFFSET_MASK; + uint64_t byte_mask = (uint64_t) 1 << (addr & PAGE_BYTE_MASK_MASK); - if ((addr & 0xf) == 0xf) - mask |= (mask << 1); - *(uint16_t *)&p->mem[addr & 0xfff] = val; - p->dirty_mask |= mask; - if ((p->code_present_mask & mask) && !page_in_evict_list(p)) - page_add_to_evict_list(p); - if ((addr & PAGE_BYTE_MASK_MASK) == PAGE_BYTE_MASK_MASK) { - p->byte_dirty_mask[byte_offset+1] |= 1; - if ((p->byte_code_present_mask[byte_offset+1] & 1) && !page_in_evict_list(p)) - page_add_to_evict_list(p); - } else - byte_mask |= (byte_mask << 1); + if ((addr & 0xf) == 0xf) + mask |= (mask << 1); + *(uint16_t *) &page->mem[addr & 0xfff] = val; + page->dirty_mask |= mask; + if ((page->code_present_mask & mask) && !page_in_evict_list(page)) + page_add_to_evict_list(page); + if ((addr & PAGE_BYTE_MASK_MASK) == PAGE_BYTE_MASK_MASK) { + page->byte_dirty_mask[byte_offset + 1] |= 1; + if ((page->byte_code_present_mask[byte_offset + 1] & 1) && !page_in_evict_list(page)) + page_add_to_evict_list(page); + } else + byte_mask |= (byte_mask << 1); - p->byte_dirty_mask[byte_offset] |= byte_mask; + page->byte_dirty_mask[byte_offset] |= byte_mask; - if ((p->byte_code_present_mask[byte_offset] & byte_mask) && !page_in_evict_list(p)) - page_add_to_evict_list(p); + if ((page->byte_code_present_mask[byte_offset] & byte_mask) && !page_in_evict_list(page)) + page_add_to_evict_list(page); } } - void -mem_write_raml_page(uint32_t addr, uint32_t val, page_t *p) +mem_write_raml_page(uint32_t addr, uint32_t val, page_t *page) { - if (p == NULL) - return; + if (page == NULL) + return; -#ifdef USE_DYNAREC - if ((p->mem == NULL) || (p->mem == page_ff) || (val != *(uint32_t *)&p->mem[addr & 0xfff]) || codegen_in_recompile) { -#else - if ((p->mem == NULL) || (p->mem == page_ff) || (val != *(uint32_t *)&p->mem[addr & 0xfff])) { -#endif - uint64_t mask = (uint64_t)1 << ((addr >> PAGE_MASK_SHIFT) & PAGE_MASK_MASK); - int byte_offset = (addr >> PAGE_BYTE_MASK_SHIFT) & PAGE_BYTE_MASK_OFFSET_MASK; - uint64_t byte_mask = (uint64_t)0xf << (addr & PAGE_BYTE_MASK_MASK); +# ifdef USE_DYNAREC + if ((page->mem == NULL) || (page->mem == page_ff) || (val != *(uint32_t *) &page->mem[addr & 0xfff]) || codegen_in_recompile) { +# else + if ((page->mem == NULL) || (page->mem == page_ff) || (val != *(uint32_t *) &page->mem[addr & 0xfff])) { +# endif + uint64_t mask = (uint64_t) 1 << ((addr >> PAGE_MASK_SHIFT) & PAGE_MASK_MASK); + int byte_offset = (addr >> PAGE_BYTE_MASK_SHIFT) & PAGE_BYTE_MASK_OFFSET_MASK; + uint64_t byte_mask = (uint64_t) 0xf << (addr & PAGE_BYTE_MASK_MASK); - if ((addr & 0xf) >= 0xd) - mask |= (mask << 1); - *(uint32_t *)&p->mem[addr & 0xfff] = val; - p->dirty_mask |= mask; - p->byte_dirty_mask[byte_offset] |= byte_mask; - if (!page_in_evict_list(p) && ((p->code_present_mask & mask) || (p->byte_code_present_mask[byte_offset] & byte_mask))) - page_add_to_evict_list(p); - if ((addr & PAGE_BYTE_MASK_MASK) > (PAGE_BYTE_MASK_MASK-3)) { - uint32_t byte_mask_2 = 0xf >> (4 - (addr & 3)); + if ((addr & 0xf) >= 0xd) + mask |= (mask << 1); + *(uint32_t *) &page->mem[addr & 0xfff] = val; + page->dirty_mask |= mask; + page->byte_dirty_mask[byte_offset] |= byte_mask; + if (!page_in_evict_list(page) && ((page->code_present_mask & mask) || (page->byte_code_present_mask[byte_offset] & byte_mask))) + page_add_to_evict_list(page); + if ((addr & PAGE_BYTE_MASK_MASK) > (PAGE_BYTE_MASK_MASK - 3)) { + uint32_t byte_mask_2 = 0xf >> (4 - (addr & 3)); - p->byte_dirty_mask[byte_offset+1] |= byte_mask_2; - if ((p->byte_code_present_mask[byte_offset+1] & byte_mask_2) && !page_in_evict_list(p)) - page_add_to_evict_list(p); - } + page->byte_dirty_mask[byte_offset + 1] |= byte_mask_2; + if ((page->byte_code_present_mask[byte_offset + 1] & byte_mask_2) && !page_in_evict_list(page)) + page_add_to_evict_list(page); + } } } #else void -mem_write_ramb_page(uint32_t addr, uint8_t val, page_t *p) +mem_write_ramb_page(uint32_t addr, uint8_t val, page_t *page) { - if (p == NULL) - return; + if (page == NULL) + return; -#ifdef USE_DYNAREC - if ((p->mem == NULL) || (p->mem == page_ff) || (val != p->mem[addr & 0xfff]) || codegen_in_recompile) { -#else - if ((p->mem == NULL) || (p->mem == page_ff) || (val != p->mem[addr & 0xfff])) { -#endif - uint64_t mask = (uint64_t)1 << ((addr >> PAGE_MASK_SHIFT) & PAGE_MASK_MASK); - p->dirty_mask[(addr >> PAGE_MASK_INDEX_SHIFT) & PAGE_MASK_INDEX_MASK] |= mask; - p->mem[addr & 0xfff] = val; +# ifdef USE_DYNAREC + if ((page->mem == NULL) || (page->mem == page_ff) || (val != page->mem[addr & 0xfff]) || codegen_in_recompile) { +# else + if ((page->mem == NULL) || (page->mem == page_ff) || (val != page->mem[addr & 0xfff])) { +# endif + uint64_t mask = (uint64_t) 1 << ((addr >> PAGE_MASK_SHIFT) & PAGE_MASK_MASK); + page->dirty_mask[(addr >> PAGE_MASK_INDEX_SHIFT) & PAGE_MASK_INDEX_MASK] |= mask; + page->mem[addr & 0xfff] = val; } } - void -mem_write_ramw_page(uint32_t addr, uint16_t val, page_t *p) +mem_write_ramw_page(uint32_t addr, uint16_t val, page_t *page) { - if (p == NULL) - return; + if (page == NULL) + return; -#ifdef USE_DYNAREC - if ((p->mem == NULL) || (p->mem == page_ff) || (val != *(uint16_t *)&p->mem[addr & 0xfff]) || codegen_in_recompile) { -#else - if ((p->mem == NULL) || (p->mem == page_ff) || (val != *(uint16_t *)&p->mem[addr & 0xfff])) { -#endif - uint64_t mask = (uint64_t)1 << ((addr >> PAGE_MASK_SHIFT) & PAGE_MASK_MASK); - if ((addr & 0xf) == 0xf) - mask |= (mask << 1); - p->dirty_mask[(addr >> PAGE_MASK_INDEX_SHIFT) & PAGE_MASK_INDEX_MASK] |= mask; - *(uint16_t *)&p->mem[addr & 0xfff] = val; +# ifdef USE_DYNAREC + if ((page->mem == NULL) || (page->mem == page_ff) || (val != *(uint16_t *) &page->mem[addr & 0xfff]) || codegen_in_recompile) { +# else + if ((page->mem == NULL) || (page->mem == page_ff) || (val != *(uint16_t *) &page->mem[addr & 0xfff])) { +# endif + uint64_t mask = (uint64_t) 1 << ((addr >> PAGE_MASK_SHIFT) & PAGE_MASK_MASK); + if ((addr & 0xf) == 0xf) + mask |= (mask << 1); + page->dirty_mask[(addr >> PAGE_MASK_INDEX_SHIFT) & PAGE_MASK_INDEX_MASK] |= mask; + *(uint16_t *) &page->mem[addr & 0xfff] = val; } } - void -mem_write_raml_page(uint32_t addr, uint32_t val, page_t *p) +mem_write_raml_page(uint32_t addr, uint32_t val, page_t *page) { - if (p == NULL) - return; + if (page == NULL) + return; -#ifdef USE_DYNAREC - if ((p->mem == NULL) || (p->mem == page_ff) || (val != *(uint32_t *)&p->mem[addr & 0xfff]) || codegen_in_recompile) { -#else - if ((p->mem == NULL) || (p->mem == page_ff) || (val != *(uint32_t *)&p->mem[addr & 0xfff])) { -#endif - uint64_t mask = (uint64_t)1 << ((addr >> PAGE_MASK_SHIFT) & PAGE_MASK_MASK); - if ((addr & 0xf) >= 0xd) - mask |= (mask << 1); - p->dirty_mask[(addr >> PAGE_MASK_INDEX_SHIFT) & PAGE_MASK_INDEX_MASK] |= mask; - *(uint32_t *)&p->mem[addr & 0xfff] = val; +# ifdef USE_DYNAREC + if ((page->mem == NULL) || (page->mem == page_ff) || (val != *(uint32_t *) &page->mem[addr & 0xfff]) || codegen_in_recompile) { +# else + if ((page->mem == NULL) || (page->mem == page_ff) || (val != *(uint32_t *) &page->mem[addr & 0xfff])) { +# endif + uint64_t mask = (uint64_t) 1 << ((addr >> PAGE_MASK_SHIFT) & PAGE_MASK_MASK); + if ((addr & 0xf) >= 0xd) + mask |= (mask << 1); + page->dirty_mask[(addr >> PAGE_MASK_INDEX_SHIFT) & PAGE_MASK_INDEX_MASK] |= mask; + *(uint32_t *) &page->mem[addr & 0xfff] = val; } } #endif - void -mem_write_ram(uint32_t addr, uint8_t val, void *priv) +mem_write_ram(uint32_t addr, uint8_t val, UNUSED(void *priv)) { #ifdef ENABLE_MEM_LOG if ((addr >= 0xa0000) && (addr <= 0xbffff)) - mem_log("Write B %02X to %08X\n", val, addr); -#endif - if (is286) { - addwritelookup(mem_logical_addr, addr); - mem_write_ramb_page(addr, val, &pages[addr >> 12]); - } else - ram[addr] = val; -} - - -void -mem_write_ramw(uint32_t addr, uint16_t val, void *priv) -{ -#ifdef ENABLE_MEM_LOG - if ((addr >= 0xa0000) && (addr <= 0xbffff)) - mem_log("Write W %04X to %08X\n", val, addr); + mem_log("Write B %02X to %08X\n", val, addr); #endif if (is286) { - addwritelookup(mem_logical_addr, addr); - mem_write_ramw_page(addr, val, &pages[addr >> 12]); + addwritelookup(mem_logical_addr, addr); + mem_write_ramb_page(addr, val, &pages[addr >> 12]); } else - *(uint16_t *)&ram[addr] = val; + ram[addr] = val; } - void -mem_write_raml(uint32_t addr, uint32_t val, void *priv) +mem_write_ramw(uint32_t addr, uint16_t val, UNUSED(void *priv)) { #ifdef ENABLE_MEM_LOG if ((addr >= 0xa0000) && (addr <= 0xbffff)) - mem_log("Write L %08X to %08X\n", val, addr); + mem_log("Write W %04X to %08X\n", val, addr); #endif if (is286) { - addwritelookup(mem_logical_addr, addr); - mem_write_raml_page(addr, val, &pages[addr >> 12]); + addwritelookup(mem_logical_addr, addr); + mem_write_ramw_page(addr, val, &pages[addr >> 12]); } else - *(uint32_t *)&ram[addr] = val; + *(uint16_t *) &ram[addr] = val; } +void +mem_write_raml(uint32_t addr, uint32_t val, UNUSED(void *priv)) +{ +#ifdef ENABLE_MEM_LOG + if ((addr >= 0xa0000) && (addr <= 0xbffff)) + mem_log("Write L %08X to %08X\n", val, addr); +#endif + if (is286) { + addwritelookup(mem_logical_addr, addr); + mem_write_raml_page(addr, val, &pages[addr >> 12]); + } else + *(uint32_t *) &ram[addr] = val; +} static uint8_t -mem_read_remapped(uint32_t addr, void *priv) +mem_read_remapped(uint32_t addr, UNUSED(void *priv)) { addr = 0xA0000 + (addr - remap_start_addr); if (is286) - addreadlookup(mem_logical_addr, addr); + addreadlookup(mem_logical_addr, addr); return ram[addr]; } - static uint16_t -mem_read_remappedw(uint32_t addr, void *priv) +mem_read_remappedw(uint32_t addr, UNUSED(void *priv)) { addr = 0xA0000 + (addr - remap_start_addr); if (is286) - addreadlookup(mem_logical_addr, addr); - return *(uint16_t *)&ram[addr]; + addreadlookup(mem_logical_addr, addr); + return *(uint16_t *) &ram[addr]; } - static uint32_t -mem_read_remappedl(uint32_t addr, void *priv) +mem_read_remappedl(uint32_t addr, UNUSED(void *priv)) { addr = 0xA0000 + (addr - remap_start_addr); if (is286) - addreadlookup(mem_logical_addr, addr); - return *(uint32_t *)&ram[addr]; + addreadlookup(mem_logical_addr, addr); + return *(uint32_t *) &ram[addr]; } +static uint8_t +mem_read_remapped2(uint32_t addr, UNUSED(void *priv)) +{ + addr = 0xD0000 + (addr - remap_start_addr2); + if (is286) + addreadlookup(mem_logical_addr, addr); + return ram[addr]; +} + +static uint16_t +mem_read_remappedw2(uint32_t addr, UNUSED(void *priv)) +{ + addr = 0xD0000 + (addr - remap_start_addr2); + if (is286) + addreadlookup(mem_logical_addr, addr); + return *(uint16_t *) &ram[addr]; +} + +static uint32_t +mem_read_remappedl2(uint32_t addr, UNUSED(void *priv)) +{ + addr = 0xD0000 + (addr - remap_start_addr2); + if (is286) + addreadlookup(mem_logical_addr, addr); + return *(uint32_t *) &ram[addr]; +} static void -mem_write_remapped(uint32_t addr, uint8_t val, void *priv) +mem_write_remapped(uint32_t addr, uint8_t val, UNUSED(void *priv)) { uint32_t oldaddr = addr; - addr = 0xA0000 + (addr - remap_start_addr); + addr = 0xA0000 + (addr - remap_start_addr); if (is286) { - addwritelookup(mem_logical_addr, addr); - mem_write_ramb_page(addr, val, &pages[oldaddr >> 12]); + addwritelookup(mem_logical_addr, addr); + mem_write_ramb_page(addr, val, &pages[oldaddr >> 12]); } else - ram[addr] = val; + ram[addr] = val; } - static void -mem_write_remappedw(uint32_t addr, uint16_t val, void *priv) +mem_write_remappedw(uint32_t addr, uint16_t val, UNUSED(void *priv)) { uint32_t oldaddr = addr; - addr = 0xA0000 + (addr - remap_start_addr); + addr = 0xA0000 + (addr - remap_start_addr); if (is286) { - addwritelookup(mem_logical_addr, addr); - mem_write_ramw_page(addr, val, &pages[oldaddr >> 12]); + addwritelookup(mem_logical_addr, addr); + mem_write_ramw_page(addr, val, &pages[oldaddr >> 12]); } else - *(uint16_t *)&ram[addr] = val; + *(uint16_t *) &ram[addr] = val; } - static void -mem_write_remappedl(uint32_t addr, uint32_t val, void *priv) +mem_write_remappedl(uint32_t addr, uint32_t val, UNUSED(void *priv)) { uint32_t oldaddr = addr; - addr = 0xA0000 + (addr - remap_start_addr); + addr = 0xA0000 + (addr - remap_start_addr); if (is286) { - addwritelookup(mem_logical_addr, addr); - mem_write_raml_page(addr, val, &pages[oldaddr >> 12]); + addwritelookup(mem_logical_addr, addr); + mem_write_raml_page(addr, val, &pages[oldaddr >> 12]); } else - *(uint32_t *)&ram[addr] = val; + *(uint32_t *) &ram[addr] = val; } +static void +mem_write_remapped2(uint32_t addr, uint8_t val, UNUSED(void *priv)) +{ + uint32_t oldaddr = addr; + addr = 0xD0000 + (addr - remap_start_addr2); + if (is286) { + addwritelookup(mem_logical_addr, addr); + mem_write_ramb_page(addr, val, &pages[oldaddr >> 12]); + } else + ram[addr] = val; +} + +static void +mem_write_remappedw2(uint32_t addr, uint16_t val, UNUSED(void *priv)) +{ + uint32_t oldaddr = addr; + addr = 0xD0000 + (addr - remap_start_addr2); + if (is286) { + addwritelookup(mem_logical_addr, addr); + mem_write_ramw_page(addr, val, &pages[oldaddr >> 12]); + } else + *(uint16_t *) &ram[addr] = val; +} + +static void +mem_write_remappedl2(uint32_t addr, uint32_t val, UNUSED(void *priv)) +{ + uint32_t oldaddr = addr; + addr = 0xD0000 + (addr - remap_start_addr2); + if (is286) { + addwritelookup(mem_logical_addr, addr); + mem_write_raml_page(addr, val, &pages[oldaddr >> 12]); + } else + *(uint32_t *) &ram[addr] = val; +} void mem_invalidate_range(uint32_t start_addr, uint32_t end_addr) { #ifdef USE_NEW_DYNAREC - int byte_offset; - uint64_t byte_mask; - page_t *p; + page_t *page; start_addr &= ~PAGE_MASK_MASK; - end_addr = (end_addr + PAGE_MASK_MASK) & ~PAGE_MASK_MASK; + end_addr = (end_addr + PAGE_MASK_MASK) & ~PAGE_MASK_MASK; for (; start_addr <= end_addr; start_addr += 0x1000) { - if ((start_addr >> 12) >= pages_sz) - continue; + if ((start_addr >> 12) >= pages_sz) + continue; - p = &pages[start_addr >> 12]; - if (p) { - p->dirty_mask = 0xffffffffffffffffULL; + page = &pages[start_addr >> 12]; + if (page) { + page->dirty_mask = 0xffffffffffffffffULL; - if (p->byte_dirty_mask) - memset(p->byte_dirty_mask, 0xff, 64 * sizeof(uint64_t)); + if ((page->mem != page_ff) && page->byte_dirty_mask) + memset(page->byte_dirty_mask, 0xff, 64 * sizeof(uint64_t)); - if (!page_in_evict_list(p)) - page_add_to_evict_list(p); - } + if (!page_in_evict_list(page)) + page_add_to_evict_list(page); + } } #else uint32_t cur_addr; start_addr &= ~PAGE_MASK_MASK; - end_addr = (end_addr + PAGE_MASK_MASK) & ~PAGE_MASK_MASK; + end_addr = (end_addr + PAGE_MASK_MASK) & ~PAGE_MASK_MASK; for (; start_addr <= end_addr; start_addr += 0x1000) { - /* Do nothing if the pages array is empty or DMA reads/writes to/from PCI device memory addresses - may crash the emulator. */ - cur_addr = (start_addr >> 12); - if (cur_addr < pages_sz) - memset(pages[cur_addr].dirty_mask, 0xff, sizeof(pages[cur_addr].dirty_mask)); + /* Do nothing if the pages array is empty or DMA reads/writes to/from PCI device memory addresses + may crash the emulator. */ + cur_addr = (start_addr >> 12); + if (cur_addr < pages_sz) + memset(pages[cur_addr].dirty_mask, 0xff, sizeof(pages[cur_addr].dirty_mask)); } #endif } - static __inline int mem_mapping_access_allowed(uint32_t flags, uint16_t access) { int ret = 0; if (!(access & ACCESS_DISABLED)) { - if (access & ACCESS_CACHE) - ret = (flags & MEM_MAPPING_CACHE); - else if (access & ACCESS_SMRAM) - ret = (flags & MEM_MAPPING_SMRAM); - else if (!(access & ACCESS_INTERNAL)) { - if (flags & MEM_MAPPING_IS_ROM) { - if (access & ACCESS_ROMCS) - ret = (flags & MEM_MAPPING_ROMCS); - else - ret = !(flags & MEM_MAPPING_ROMCS); - } else - ret = 1; + if (access & ACCESS_CACHE) + ret = (flags & MEM_MAPPING_CACHE); + else if (access & ACCESS_SMRAM) + ret = (flags & MEM_MAPPING_SMRAM); + else if (!(access & ACCESS_INTERNAL)) { + if (flags & MEM_MAPPING_IS_ROM) { + if (access & ACCESS_ROMCS) + ret = (flags & MEM_MAPPING_ROMCS); + else + ret = !(flags & MEM_MAPPING_ROMCS); + } else + ret = 1; - ret = ret && !(flags & MEM_MAPPING_INTERNAL) && !(flags & MEM_MAPPING_SMRAM); - } else - ret = !(flags & MEM_MAPPING_EXTERNAL) && !(flags & MEM_MAPPING_SMRAM); + ret = ret && !(flags & MEM_MAPPING_INTERNAL) && !(flags & MEM_MAPPING_SMRAM); + } else + ret = !(flags & MEM_MAPPING_EXTERNAL) && !(flags & MEM_MAPPING_SMRAM); } else { - /* Still allow SMRAM if access is DISABLED but also has CACHE and/or SMRAM flags set. */ - if (access & ACCESS_CACHE) - ret = (flags & MEM_MAPPING_CACHE); - else if (access & ACCESS_SMRAM) - ret = (flags & MEM_MAPPING_SMRAM); + /* Still allow SMRAM if access is DISABLED but also has CACHE and/or SMRAM flags set. */ + if (access & ACCESS_CACHE) + ret = (flags & MEM_MAPPING_CACHE); + else if (access & ACCESS_SMRAM) + ret = (flags & MEM_MAPPING_SMRAM); } return ret; } - void mem_mapping_recalc(uint64_t base, uint64_t size) { mem_mapping_t *map; - int n; - uint64_t c; + int n; + uint64_t c; if (!size || (base_mapping == NULL)) - return; + return; map = base_mapping; /* Clear out old mappings. */ for (c = base; c < base + size; c += MEM_GRANULARITY_SIZE) { - _mem_exec[c >> MEM_GRANULARITY_BITS] = NULL; - write_mapping[c >> MEM_GRANULARITY_BITS] = NULL; - read_mapping[c >> MEM_GRANULARITY_BITS] = NULL; - write_mapping_bus[c >> MEM_GRANULARITY_BITS] = NULL; - read_mapping_bus[c >> MEM_GRANULARITY_BITS] = NULL; + _mem_exec[c >> MEM_GRANULARITY_BITS] = NULL; + write_mapping[c >> MEM_GRANULARITY_BITS] = NULL; + read_mapping[c >> MEM_GRANULARITY_BITS] = NULL; + write_mapping_bus[c >> MEM_GRANULARITY_BITS] = NULL; + read_mapping_bus[c >> MEM_GRANULARITY_BITS] = NULL; } /* Walk mapping list. */ while (map != NULL) { - /* In range? */ - if (map->enable && (uint64_t)map->base < ((uint64_t)base + (uint64_t)size) && - ((uint64_t)map->base + (uint64_t)map->size) > (uint64_t)base) { - uint64_t start = (map->base < base) ? map->base : base; - uint64_t end = (((uint64_t)map->base + (uint64_t)map->size) < (base + size)) ? - ((uint64_t)map->base + (uint64_t)map->size) : (base + size); - if (start < map->base) - start = map->base; + /* In range? */ + if (map->enable && (uint64_t) map->base < ((uint64_t) base + (uint64_t) size) && ((uint64_t) map->base + (uint64_t) map->size) > (uint64_t) base) { + uint64_t start = (map->base < base) ? map->base : base; + uint64_t end = (((uint64_t) map->base + (uint64_t) map->size) < (base + size)) ? ((uint64_t) map->base + (uint64_t) map->size) : (base + size); + if (start < map->base) + start = map->base; - for (c = start; c < end; c += MEM_GRANULARITY_SIZE) { - /* CPU */ - n = !!in_smm; - if (map->exec && - mem_mapping_access_allowed(map->flags, _mem_state[c >> MEM_GRANULARITY_BITS].states[n].x)) - _mem_exec[c >> MEM_GRANULARITY_BITS] = map->exec + (c - map->base); - if ((map->write_b || map->write_w || map->write_l) && - mem_mapping_access_allowed(map->flags, _mem_state[c >> MEM_GRANULARITY_BITS].states[n].w)) - write_mapping[c >> MEM_GRANULARITY_BITS] = map; - if ((map->read_b || map->read_w || map->read_l) && - mem_mapping_access_allowed(map->flags, _mem_state[c >> MEM_GRANULARITY_BITS].states[n].r)) - read_mapping[c >> MEM_GRANULARITY_BITS] = map; + for (c = start; c < end; c += MEM_GRANULARITY_SIZE) { + /* CPU */ + n = !!in_smm; + if (map->exec && mem_mapping_access_allowed(map->flags, _mem_state[c >> MEM_GRANULARITY_BITS].states[n].x)) + _mem_exec[c >> MEM_GRANULARITY_BITS] = map->exec + (c - map->base); + if ((map->write_b || map->write_w || map->write_l) && mem_mapping_access_allowed(map->flags, _mem_state[c >> MEM_GRANULARITY_BITS].states[n].w)) + write_mapping[c >> MEM_GRANULARITY_BITS] = map; + if ((map->read_b || map->read_w || map->read_l) && mem_mapping_access_allowed(map->flags, _mem_state[c >> MEM_GRANULARITY_BITS].states[n].r)) + read_mapping[c >> MEM_GRANULARITY_BITS] = map; - /* Bus */ - n |= STATE_BUS; - if ((map->write_b || map->write_w || map->write_l) && - mem_mapping_access_allowed(map->flags, _mem_state[c >> MEM_GRANULARITY_BITS].states[n].w)) - write_mapping_bus[c >> MEM_GRANULARITY_BITS] = map; - if ((map->read_b || map->read_w || map->read_l) && - mem_mapping_access_allowed(map->flags, _mem_state[c >> MEM_GRANULARITY_BITS].states[n].r)) - read_mapping_bus[c >> MEM_GRANULARITY_BITS] = map; - } - } - map = map->next; + /* Bus */ + n |= STATE_BUS; + if ((map->write_b || map->write_w || map->write_l) && mem_mapping_access_allowed(map->flags, _mem_state[c >> MEM_GRANULARITY_BITS].states[n].w)) + write_mapping_bus[c >> MEM_GRANULARITY_BITS] = map; + if ((map->read_b || map->read_w || map->read_l) && mem_mapping_access_allowed(map->flags, _mem_state[c >> MEM_GRANULARITY_BITS].states[n].r)) + read_mapping_bus[c >> MEM_GRANULARITY_BITS] = map; + } + } + map = map->next; } - flushmmucache_cr3(); -} + flushmmucache_nopc(); +#ifdef ENABLE_MEM_LOG + pclog("\nMemory map:\n"); + mem_mapping_t *write = (mem_mapping_t *) -1, *read = (mem_mapping_t *) -1, *write_bus = (mem_mapping_t *) -1, *read_bus = (mem_mapping_t *) -1; + for (c = 0; c < (sizeof(write_mapping) / sizeof(write_mapping[0])); c++) { + if ((write_mapping[c] == write) && (read_mapping[c] == read) && (write_mapping_bus[c] == write_bus) && (read_mapping_bus[c] == read_bus)) + continue; + write = write_mapping[c]; + read = read_mapping[c]; + write_bus = write_mapping_bus[c]; + read_bus = read_mapping_bus[c]; + + pclog("%08X | ", c << MEM_GRANULARITY_BITS); + if (read) { + pclog("R%c%c%c %08X+% 8X", + read->read_b ? 'b' : ' ', read->read_w ? 'w' : ' ', read->read_l ? 'l' : ' ', + read->base, read->size); + } else { + pclog(" "); + } + if (write) { + pclog(" | W%c%c%c %08X+% 8X", + write->write_b ? 'b' : ' ', write->write_w ? 'w' : ' ', write->write_l ? 'l' : ' ', + write->base, write->size); + } else { + pclog(" | "); + } + pclog(" | %c\n", _mem_exec[c] ? 'X' : ' '); + + if ((write != write_bus) || (read != read_bus)) { + pclog(" ^ bus | "); + if (read_bus) { + pclog("R%c%c%c %08X+% 8X", + read_bus->read_b ? 'b' : ' ', read_bus->read_w ? 'w' : ' ', read_bus->read_l ? 'l' : ' ', + read_bus->base, read_bus->size); + } else { + pclog(" "); + } + if (write_bus) { + pclog(" | W%c%c%c %08X+% 8X", + write_bus->write_b ? 'b' : ' ', write_bus->write_w ? 'w' : ' ', write_bus->write_l ? 'l' : ' ', + write_bus->base, write_bus->size); + } else { + pclog(" | "); + } + pclog(" |\n"); + } + } + pclog("\n"); +#endif +} void mem_mapping_set(mem_mapping_t *map, - uint32_t base, - uint32_t size, - uint8_t (*read_b)(uint32_t addr, void *p), - uint16_t (*read_w)(uint32_t addr, void *p), - uint32_t (*read_l)(uint32_t addr, void *p), - void (*write_b)(uint32_t addr, uint8_t val, void *p), - void (*write_w)(uint32_t addr, uint16_t val, void *p), - void (*write_l)(uint32_t addr, uint32_t val, void *p), - uint8_t *exec, - uint32_t fl, - void *p) + uint32_t base, + uint32_t size, + uint8_t (*read_b)(uint32_t addr, void *priv), + uint16_t (*read_w)(uint32_t addr, void *priv), + uint32_t (*read_l)(uint32_t addr, void *priv), + void (*write_b)(uint32_t addr, uint8_t val, void *priv), + void (*write_w)(uint32_t addr, uint16_t val, void *priv), + void (*write_l)(uint32_t addr, uint32_t val, void *priv), + uint8_t *exec, + uint32_t fl, + void *priv) { if (size != 0x00000000) - map->enable = 1; + map->enable = 1; else - map->enable = 0; + map->enable = 0; map->base = base; map->size = size; + map->mask = (map->size ? 0xffffffff : 0x00000000); map->read_b = read_b; map->read_w = read_w; map->read_l = read_l; @@ -2349,78 +2411,75 @@ mem_mapping_set(mem_mapping_t *map, map->write_l = write_l; map->exec = exec; map->flags = fl; - map->p = p; + map->priv = priv; map->next = NULL; mem_log("mem_mapping_add(): Linked list structure: %08X -> %08X -> %08X\n", map->prev, map, map->next); /* If the mapping is disabled, there is no need to recalc anything. */ if (size != 0x00000000) - mem_mapping_recalc(map->base, map->size); + mem_mapping_recalc(map->base, map->size); } - void mem_mapping_add(mem_mapping_t *map, - uint32_t base, - uint32_t size, - uint8_t (*read_b)(uint32_t addr, void *p), - uint16_t (*read_w)(uint32_t addr, void *p), - uint32_t (*read_l)(uint32_t addr, void *p), - void (*write_b)(uint32_t addr, uint8_t val, void *p), - void (*write_w)(uint32_t addr, uint16_t val, void *p), - void (*write_l)(uint32_t addr, uint32_t val, void *p), - uint8_t *exec, - uint32_t fl, - void *p) + uint32_t base, + uint32_t size, + uint8_t (*read_b)(uint32_t addr, void *priv), + uint16_t (*read_w)(uint32_t addr, void *priv), + uint32_t (*read_l)(uint32_t addr, void *priv), + void (*write_b)(uint32_t addr, uint8_t val, void *priv), + void (*write_w)(uint32_t addr, uint16_t val, void *priv), + void (*write_l)(uint32_t addr, uint32_t val, void *priv), + uint8_t *exec, + uint32_t fl, + void *priv) { /* Do a sanity check */ if ((base_mapping == NULL) && (last_mapping != NULL)) { - fatal("mem_mapping_add(): NULL base mapping with non-NULL last mapping\n"); - return; + fatal("mem_mapping_add(): NULL base mapping with non-NULL last mapping\n"); + return; } else if ((base_mapping != NULL) && (last_mapping == NULL)) { - fatal("mem_mapping_add(): Non-NULL base mapping with NULL last mapping\n"); - return; + fatal("mem_mapping_add(): Non-NULL base mapping with NULL last mapping\n"); + return; } else if ((base_mapping != NULL) && (base_mapping->prev != NULL)) { - fatal("mem_mapping_add(): Base mapping with a preceding mapping\n"); - return; + fatal("mem_mapping_add(): Base mapping with a preceding mapping\n"); + return; } else if ((last_mapping != NULL) && (last_mapping->next != NULL)) { - fatal("mem_mapping_add(): Last mapping with a following mapping\n"); - return; + fatal("mem_mapping_add(): Last mapping with a following mapping\n"); + return; } /* Add mapping to the beginning of the list if necessary.*/ if (base_mapping == NULL) - base_mapping = map; + base_mapping = map; /* Add mapping to the end of the list.*/ if (last_mapping == NULL) - map->prev = NULL; - else { - map->prev = last_mapping; - last_mapping->next = map; + map->prev = NULL; + else { + map->prev = last_mapping; + last_mapping->next = map; } last_mapping = map; mem_mapping_set(map, base, size, read_b, read_w, read_l, - write_b, write_w, write_l, exec, fl, p); + write_b, write_w, write_l, exec, fl, priv); } - void mem_mapping_do_recalc(mem_mapping_t *map) { mem_mapping_recalc(map->base, map->size); } - void mem_mapping_set_handler(mem_mapping_t *map, - uint8_t (*read_b)(uint32_t addr, void *p), - uint16_t (*read_w)(uint32_t addr, void *p), - uint32_t (*read_l)(uint32_t addr, void *p), - void (*write_b)(uint32_t addr, uint8_t val, void *p), - void (*write_w)(uint32_t addr, uint16_t val, void *p), - void (*write_l)(uint32_t addr, uint32_t val, void *p)) + uint8_t (*read_b)(uint32_t addr, void *priv), + uint16_t (*read_w)(uint32_t addr, void *priv), + uint32_t (*read_l)(uint32_t addr, void *priv), + void (*write_b)(uint32_t addr, uint8_t val, void *priv), + void (*write_w)(uint32_t addr, uint16_t val, void *priv), + void (*write_l)(uint32_t addr, uint32_t val, void *priv)) { map->read_b = read_b; map->read_w = read_w; @@ -2432,7 +2491,6 @@ mem_mapping_set_handler(mem_mapping_t *map, mem_mapping_recalc(map->base, map->size); } - void mem_mapping_set_addr(mem_mapping_t *map, uint32_t base, uint32_t size) { @@ -2442,13 +2500,12 @@ mem_mapping_set_addr(mem_mapping_t *map, uint32_t base, uint32_t size) /* Set new mapping. */ map->enable = 1; - map->base = base; - map->size = size; + map->base = base; + map->size = size; mem_mapping_recalc(map->base, map->size); } - void mem_mapping_set_exec(mem_mapping_t *map, uint8_t *exec) { @@ -2457,13 +2514,19 @@ mem_mapping_set_exec(mem_mapping_t *map, uint8_t *exec) mem_mapping_recalc(map->base, map->size); } - void -mem_mapping_set_p(mem_mapping_t *map, void *p) +mem_mapping_set_mask(mem_mapping_t *map, uint32_t mask) { - map->p = p; + map->mask = mask; + + mem_mapping_recalc(map->base, map->size); } +void +mem_mapping_set_p(mem_mapping_t *map, void *priv) +{ + map->priv = priv; +} void mem_mapping_disable(mem_mapping_t *map) @@ -2473,7 +2536,6 @@ mem_mapping_disable(mem_mapping_t *map) mem_mapping_recalc(map->base, map->size); } - void mem_mapping_enable(mem_mapping_t *map) { @@ -2482,99 +2544,97 @@ mem_mapping_enable(mem_mapping_t *map) mem_mapping_recalc(map->base, map->size); } - void mem_set_access(uint8_t bitmap, int mode, uint32_t base, uint32_t size, uint16_t access) { - uint32_t c; - uint16_t mask, smstate = 0x0000; - const uint16_t smstates[4] = { 0x0000, (MEM_READ_SMRAM | MEM_WRITE_SMRAM), - MEM_READ_SMRAM_EX, (MEM_READ_DISABLED_EX | MEM_WRITE_DISABLED_EX) }; - - int i; + uint16_t mask; + uint16_t smstate = 0x0000; + const uint16_t smstates[4] = { 0x0000, (MEM_READ_SMRAM | MEM_WRITE_SMRAM), + MEM_READ_SMRAM_EX, (MEM_READ_DISABLED_EX | MEM_WRITE_DISABLED_EX) }; if (mode) - mask = 0x2d6b; + mask = 0x2d6b; else - mask = 0x1084; + mask = 0x1084; if (mode) { - if (mode == 1) - access = !!access; + if (mode == 1) + access = !!access; - if (mode == 3) { - if (access & ACCESS_SMRAM_X) - smstate |= MEM_EXEC_SMRAM; - if (access & ACCESS_SMRAM_R) - smstate |= MEM_READ_SMRAM_2; - if (access & ACCESS_SMRAM_W) - smstate |= MEM_WRITE_SMRAM; - } else - smstate = smstates[access & 0x07]; + if (mode == 3) { + if (access & ACCESS_SMRAM_X) + smstate |= MEM_EXEC_SMRAM; + if (access & ACCESS_SMRAM_R) + smstate |= MEM_READ_SMRAM_2; + if (access & ACCESS_SMRAM_W) + smstate |= MEM_WRITE_SMRAM; + } else + smstate = smstates[access & 0x07]; } else - smstate = access & 0x6f7b; + smstate = access & 0x6f7b; - for (c = 0; c < size; c += MEM_GRANULARITY_SIZE) { - for (i = 0; i < 4; i++) { - if (bitmap & (1 << i)) { - _mem_state[(c + base) >> MEM_GRANULARITY_BITS].vals[i] = - (_mem_state[(c + base) >> MEM_GRANULARITY_BITS].vals[i] & mask) | smstate; - } - } + for (uint32_t c = 0; c < size; c += MEM_GRANULARITY_SIZE) { + for (uint8_t i = 0; i < 4; i++) { + if (bitmap & (1 << i)) { + _mem_state[(c + base) >> MEM_GRANULARITY_BITS].vals[i] = (_mem_state[(c + base) >> MEM_GRANULARITY_BITS].vals[i] & mask) | smstate; + } + } #ifdef ENABLE_MEM_LOG - if (((c + base) >= 0xa0000) && ((c + base) <= 0xbffff)) { - mem_log("Set mem state for block at %08X to %04X with bitmap %02X\n", - c + base, smstate, bitmap); - } + if (((c + base) >= 0xa0000) && ((c + base) <= 0xbffff)) { + mem_log("Set mem state for block at %08X to %04X with bitmap %02X\n", + c + base, smstate, bitmap); + } #endif } mem_mapping_recalc(base, size); } - void mem_a20_init(void) { if (is286) { - rammask = cpu_16bitbus ? 0xefffff : 0xffefffff; - flushmmucache(); - mem_a20_state = mem_a20_key | mem_a20_alt; + mem_a20_key = mem_a20_alt = mem_a20_state = 0; + rammask = cpu_16bitbus ? 0xffffff : 0xffffffff; + if (is6117) + rammask |= 0x03000000; + flushmmucache(); +#if 0 + mem_a20_state = mem_a20_key | mem_a20_alt; +#endif } else { - rammask = 0xfffff; - flushmmucache(); - mem_a20_key = mem_a20_alt = mem_a20_state = 0; + rammask = 0xfffff; + flushmmucache(); + mem_a20_key = mem_a20_alt = mem_a20_state = 0; } } - /* Close all the memory mappings. */ void mem_close(void) { - mem_mapping_t *map = base_mapping, *next; + mem_mapping_t *map = base_mapping; + mem_mapping_t *next; while (map != NULL) { - next = map->next; - map->prev = map->next = NULL; - map = next; + next = map->next; + map->prev = map->next = NULL; + map = next; } base_mapping = last_mapping = 0; } - static void mem_add_ram_mapping(mem_mapping_t *mapping, uint32_t base, uint32_t size) { mem_mapping_add(mapping, base, size, - mem_read_ram,mem_read_ramw,mem_read_raml, - mem_write_ram,mem_write_ramw,mem_write_raml, - ram + base, MEM_MAPPING_INTERNAL, NULL); + mem_read_ram, mem_read_ramw, mem_read_raml, + mem_write_ram, mem_write_ramw, mem_write_raml, + ram + base, MEM_MAPPING_INTERNAL, NULL); } - static void mem_init_ram_mapping(mem_mapping_t *mapping, uint32_t base, uint32_t size) { @@ -2582,82 +2642,83 @@ mem_init_ram_mapping(mem_mapping_t *mapping, uint32_t base, uint32_t size) mem_add_ram_mapping(mapping, base, size); } - /* Reset the memory state. */ void mem_reset(void) { - uint32_t c, m; + size_t m; memset(page_ff, 0xff, sizeof(page_ff)); #ifdef USE_NEW_DYNAREC if (byte_dirty_mask) { - free(byte_dirty_mask); - byte_dirty_mask = NULL; + free(byte_dirty_mask); + byte_dirty_mask = NULL; } if (byte_code_present_mask) { - free(byte_code_present_mask); - byte_code_present_mask = NULL; + free(byte_code_present_mask); + byte_code_present_mask = NULL; } #endif /* Free the old pages array, if necessary. */ if (pages) { - free(pages); - pages = NULL; + free(pages); + pages = NULL; } if (ram != NULL) { - plat_munmap(ram, ram_size); - ram = NULL; - ram_size = 0; + plat_munmap(ram, ram_size); + ram = NULL; + ram_size = 0; } #if (!(defined __amd64__ || defined _M_X64 || defined __aarch64__ || defined _M_ARM64)) if (ram2 != NULL) { - plat_munmap(ram2, ram2_size); - ram2 = NULL; - ram2_size = 0; + plat_munmap(ram2, ram2_size); + ram2 = NULL; + ram2_size = 0; } if (mem_size > 2097152) - mem_size = 2097152; + mem_size = 2097152; #endif - m = 1024UL * mem_size; + m = 1024UL * (size_t) mem_size; #if (!(defined __amd64__ || defined _M_X64 || defined __aarch64__ || defined _M_ARM64)) if (mem_size > 1048576) { - ram_size = 1 << 30; - ram = (uint8_t *) plat_mmap(ram_size, 0); /* allocate and clear the RAM block of the first 1 GB */ - if (ram == NULL) { - fatal("Failed to allocate primary RAM block. Make sure you have enough RAM available.\n"); - return; - } - memset(ram, 0x00, ram_size); - ram2_size = m - (1 << 30); - ram2 = (uint8_t *) plat_mmap(ram2_size, 0); /* allocate and clear the RAM block above 1 GB */ - if (ram2 == NULL) { - if (config_changed == 2) - fatal(EMU_NAME " must be restarted for the memory amount change to be applied.\n"); - else - fatal("Failed to allocate secondary RAM block. Make sure you have enough RAM available.\n"); - return; - } - memset(ram2, 0x00, ram2_size); + ram_size = 1 << 30; + ram = (uint8_t *) plat_mmap(ram_size, 0); /* allocate and clear the RAM block of the first 1 GB */ + if (ram == NULL) { + fatal("Failed to allocate primary RAM block. Make sure you have enough RAM available.\n"); + return; + } + memset(ram, 0x00, ram_size); + ram2_size = m - (1 << 30); + /* Allocate 16 extra bytes of RAM to mitigate some dynarec recompiler memory access quirks. */ + ram2 = (uint8_t *) plat_mmap(ram2_size + 16, 0); /* allocate and clear the RAM block above 1 GB */ + if (ram2 == NULL) { + if (config_changed == 2) + fatal(EMU_NAME " must be restarted for the memory amount change to be applied.\n"); + else + fatal("Failed to allocate secondary RAM block. Make sure you have enough RAM available.\n"); + return; + } + memset(ram2, 0x00, ram2_size + 16); } else #endif { - ram_size = m; - ram = (uint8_t *) plat_mmap(ram_size, 0); /* allocate and clear the RAM block */ - if (ram == NULL) { - fatal("Failed to allocate RAM block. Make sure you have enough RAM available.\n"); - return; - } - memset(ram, 0x00, ram_size); - if (mem_size > 1048576) - ram2 = &(ram[1 << 30]); + ram_size = m; + /* Allocate 16 extra bytes of RAM to mitigate some dynarec recompiler memory access quirks. */ + ram = (uint8_t *) plat_mmap(ram_size + 16, 0); /* allocate and clear the RAM block */ + if (ram == NULL) { + fatal("Failed to allocate RAM block. Make sure you have enough RAM available.\n"); + return; + } + memset(ram, 0x00, ram_size + 16); + if (mem_size > 1048576) + ram2 = &(ram[1 << 30]); } /* @@ -2666,28 +2727,33 @@ mem_reset(void) * memory amount could have changed. */ if (is286) { - if (cpu_16bitbus) { - /* 80286/386SX; maximum address space is 16MB. */ - m = 4096; - } else { - /* 80386DX+; maximum address space is 4GB. */ - m = 1048576; - } + if (cpu_16bitbus) { + /* 80286/386SX; maximum address space is 16MB. */ + m = 4096; + /* ALi M6117; maximum address space is 64MB. */ + if (is6117) + m <<= 2; + } else { + /* 80386DX+; maximum address space is 4GB. */ + m = 1048576; + } } else { - /* 8088/86; maximum address space is 1MB. */ - m = 256; + /* 8088/86; maximum address space is 1MB. */ + m = 256; } + addr_space_size = m; + /* * Allocate and initialize the (new) page table. */ pages_sz = m; - pages = (page_t *)malloc(m*sizeof(page_t)); + pages = (page_t *) malloc(m * sizeof(page_t)); memset(page_lookup, 0x00, (1 << 20) * sizeof(page_t *)); memset(page_lookupp, 0x04, (1 << 20) * sizeof(uint8_t)); - memset(pages, 0x00, pages_sz*sizeof(page_t)); + memset(pages, 0x00, pages_sz * sizeof(page_t)); #ifdef USE_NEW_DYNAREC byte_dirty_mask = malloc((mem_size * 1024) / 8); @@ -2697,39 +2763,39 @@ mem_reset(void) memset(byte_code_present_mask, 0, (mem_size * 1024) / 8); #endif - for (c = 0; c < pages_sz; c++) { - if ((c << 12) >= (mem_size << 10)) - pages[c].mem = page_ff; - else { + for (uint32_t c = 0; c < pages_sz; c++) { + if ((c << 12) >= (mem_size << 10)) + pages[c].mem = page_ff; + else { #if (!(defined __amd64__ || defined _M_X64 || defined __aarch64__ || defined _M_ARM64)) - if (mem_size > 1048576) { - if ((c << 12) < (1 << 30)) - pages[c].mem = &ram[c << 12]; - else - pages[c].mem = &ram2[(c << 12) - (1 << 30)]; - } else - pages[c].mem = &ram[c << 12]; + if (mem_size > 1048576) { + if ((c << 12) < (1 << 30)) + pages[c].mem = &ram[c << 12]; + else + pages[c].mem = &ram2[(c << 12) - (1 << 30)]; + } else + pages[c].mem = &ram[c << 12]; #else - pages[c].mem = &ram[c << 12]; + pages[c].mem = &ram[c << 12]; #endif - } - if (c < m) { - pages[c].write_b = mem_write_ramb_page; - pages[c].write_w = mem_write_ramw_page; - pages[c].write_l = mem_write_raml_page; - } + } + if (c < m) { + pages[c].write_b = mem_write_ramb_page; + pages[c].write_w = mem_write_ramw_page; + pages[c].write_l = mem_write_raml_page; + } #ifdef USE_NEW_DYNAREC - pages[c].evict_prev = EVICT_NOT_IN_LIST; - pages[c].byte_dirty_mask = &byte_dirty_mask[c * 64]; - pages[c].byte_code_present_mask = &byte_code_present_mask[c * 64]; + pages[c].evict_prev = EVICT_NOT_IN_LIST; + pages[c].byte_dirty_mask = &byte_dirty_mask[c * 64]; + pages[c].byte_code_present_mask = &byte_code_present_mask[c * 64]; #endif } - memset(_mem_exec, 0x00, sizeof(_mem_exec)); - memset(write_mapping, 0x00, sizeof(write_mapping)); - memset(read_mapping, 0x00, sizeof(read_mapping)); + memset(_mem_exec, 0x00, sizeof(_mem_exec)); + memset(write_mapping, 0x00, sizeof(write_mapping)); + memset(read_mapping, 0x00, sizeof(read_mapping)); memset(write_mapping_bus, 0x00, sizeof(write_mapping_bus)); - memset(read_mapping_bus, 0x00, sizeof(read_mapping_bus)); + memset(read_mapping_bus, 0x00, sizeof(read_mapping_bus)); base_mapping = last_mapping = NULL; @@ -2740,153 +2806,247 @@ mem_reset(void) mem_init_ram_mapping(&ram_low_mapping, 0x000000, (mem_size > 640) ? 0xa0000 : mem_size * 1024); if (mem_size > 1024) { - if (cpu_16bitbus && mem_size > 16256) - mem_init_ram_mapping(&ram_high_mapping, 0x100000, (16256 - 1024) * 1024); - else { - if (mem_size > 1048576) { - mem_init_ram_mapping(&ram_high_mapping, 0x100000, (1048576 - 1024) * 1024); + if (cpu_16bitbus && !is6117 && mem_size > 16256) + mem_init_ram_mapping(&ram_high_mapping, 0x100000, (16256 - 1024) * 1024); + else if (cpu_16bitbus && is6117 && mem_size > 65408) + mem_init_ram_mapping(&ram_high_mapping, 0x100000, (65408 - 1024) * 1024); + else { + if (mem_size > 1048576) { + mem_init_ram_mapping(&ram_high_mapping, 0x100000, (1048576 - 1024) * 1024); - mem_set_mem_state_both((1 << 30), (mem_size - 1048576) * 1024, - MEM_READ_INTERNAL | MEM_WRITE_INTERNAL); - mem_mapping_add(&ram_2gb_mapping, (1 << 30), - ((mem_size - 1048576) * 1024), - mem_read_ram_2gb,mem_read_ram_2gbw,mem_read_ram_2gbl, - mem_write_ram,mem_write_ramw,mem_write_raml, - ram2, MEM_MAPPING_INTERNAL, NULL); - } else - mem_init_ram_mapping(&ram_high_mapping, 0x100000, (mem_size - 1024) * 1024); - } + mem_set_mem_state_both((1 << 30), (mem_size - 1048576) * 1024, + MEM_READ_INTERNAL | MEM_WRITE_INTERNAL); + mem_mapping_add(&ram_2gb_mapping, (1 << 30), + ((mem_size - 1048576) * 1024), + mem_read_ram_2gb, mem_read_ram_2gbw, mem_read_ram_2gbl, + mem_write_ram, mem_write_ramw, mem_write_raml, + ram2, MEM_MAPPING_INTERNAL, NULL); + } else + mem_init_ram_mapping(&ram_high_mapping, 0x100000, (mem_size - 1024) * 1024); + } } - if (mem_size > 768) - mem_add_ram_mapping(&ram_mid_mapping, 0xa0000, 0x60000); + if (mem_size > 768) { + mem_add_ram_mapping(&ram_mid_mapping, 0xa0000, 0x60000); + + mem_add_ram_mapping(&ram_mid_mapping2, 0xa0000, 0x60000); + mem_mapping_disable(&ram_mid_mapping2); + } mem_mapping_add(&ram_remapped_mapping, mem_size * 1024, 256 * 1024, - mem_read_remapped,mem_read_remappedw,mem_read_remappedl, - mem_write_remapped,mem_write_remappedw,mem_write_remappedl, - ram + 0xa0000, MEM_MAPPING_INTERNAL, NULL); + mem_read_remapped, mem_read_remappedw, mem_read_remappedl, + mem_write_remapped, mem_write_remappedw, mem_write_remappedl, + ram + 0xa0000, MEM_MAPPING_INTERNAL, NULL); mem_mapping_disable(&ram_remapped_mapping); + /* Mapping for SiS 471 relocation which relocates A0000-BFFFF, D0000-EFFFF, which is non-contiguous. */ + mem_mapping_add(&ram_remapped_mapping2, mem_size * 1024, 256 * 1024, + mem_read_remapped2, mem_read_remappedw2, mem_read_remappedl2, + mem_write_remapped2, mem_write_remappedw2, mem_write_remappedl2, + ram + 0xd0000, MEM_MAPPING_INTERNAL, NULL); + mem_mapping_disable(&ram_remapped_mapping2); + mem_a20_init(); #ifdef USE_NEW_DYNAREC purgable_page_list_head = 0; - purgeable_page_count = 0; + purgeable_page_count = 0; #endif } - void mem_init(void) { /* Perform a one-time init. */ ram = rom = NULL; - ram2 = NULL; - pages = NULL; + ram2 = NULL; + pages = NULL; /* Allocate the lookup tables. */ - page_lookup = (page_t **)malloc((1<<20)*sizeof(page_t *)); - page_lookupp = (uint8_t *)malloc((1<<20)*sizeof(uint8_t)); - readlookup2 = malloc((1<<20)*sizeof(uintptr_t)); - readlookupp = malloc((1<<20)*sizeof(uint8_t)); - writelookup2 = malloc((1<<20)*sizeof(uintptr_t)); - writelookupp = malloc((1<<20)*sizeof(uint8_t)); + page_lookup = (page_t **) malloc((1 << 20) * sizeof(page_t *)); + page_lookupp = (uint8_t *) malloc((1 << 20) * sizeof(uint8_t)); + readlookup2 = malloc((1 << 20) * sizeof(uintptr_t)); + readlookupp = malloc((1 << 20) * sizeof(uint8_t)); + writelookup2 = malloc((1 << 20) * sizeof(uintptr_t)); + writelookupp = malloc((1 << 20) * sizeof(uint8_t)); } - void mem_remap_top(int kb) { - uint32_t c; - uint32_t start = (mem_size >= 1024) ? mem_size : 1024; - int offset, size = mem_size - 640; - int set = 1; - static int old_kb = 0; + uint32_t c; + uint32_t start = (mem_size >= 1024) ? mem_size : 1024; + int offset; + int size = mem_size - 640; + int set = 1; + static int old_kb = 0; + int sis_mode = 0; + uint32_t start_addr = 0; + uint32_t addr = 0; mem_log("MEM: remapping top %iKB (mem=%i)\n", kb, mem_size); - if (mem_size <= 640) return; + if (mem_size <= 640) + return; + + /* SiS 471 special mode. */ + if (kb == -256) { + kb = 256; + sis_mode = 1; + } + + /* Do not remap if we're have more than (16 MB - RAM) memory. */ + if ((kb != 0) && (mem_size >= (16384 - kb))) + return; if (kb == 0) { - kb = old_kb; - set = 0; + kb = old_kb; + set = 0; } else - old_kb = kb; - - if (size > kb) - size = kb; + old_kb = kb; - remap_start_addr = start << 10; + if (size > kb) + size = kb; + + remap_start_addr = start << 10; + remap_start_addr2 = (start << 10) + 0x00020000; for (c = ((start * 1024) >> 12); c < (((start + size) * 1024) >> 12); c++) { - offset = c - ((start * 1024) >> 12); - pages[c].mem = set ? &ram[0xa0000 + (offset << 12)] : page_ff; - pages[c].write_b = set ? mem_write_ramb_page : NULL; - pages[c].write_w = set ? mem_write_ramw_page : NULL; - pages[c].write_l = set ? mem_write_raml_page : NULL; + offset = c - ((start * 1024) >> 12); + /* Use A0000-BFFFF, D0000-EFFFF instead of C0000-DFFFF, E0000-FFFFF. */ + addr = 0xa0000 + (offset << 12); + if (sis_mode) { + /* A0000-DFFFF -> A0000-BFFFF, D0000-EFFFF */ + if (addr >= 0x000c0000) + addr += 0x00010000; + } + if (start_addr == 0) + start_addr = addr; + pages[c].mem = set ? &ram[addr] : page_ff; + pages[c].write_b = set ? mem_write_ramb_page : NULL; + pages[c].write_w = set ? mem_write_ramw_page : NULL; + pages[c].write_l = set ? mem_write_raml_page : NULL; #ifdef USE_NEW_DYNAREC - pages[c].evict_prev = EVICT_NOT_IN_LIST; - pages[c].byte_dirty_mask = &byte_dirty_mask[offset * 64]; - pages[c].byte_code_present_mask = &byte_code_present_mask[offset * 64]; + pages[c].evict_prev = EVICT_NOT_IN_LIST; + pages[c].byte_dirty_mask = &byte_dirty_mask[(addr >> 12) * 64]; + pages[c].byte_code_present_mask = &byte_code_present_mask[(addr >> 12) * 64]; #endif } - mem_set_mem_state_both(start * 1024, size * 1024, set ? (MEM_READ_INTERNAL | MEM_WRITE_INTERNAL) : - (MEM_READ_EXTERNAL | MEM_WRITE_EXTERNAL)); + mem_set_mem_state_both(start * 1024, size * 1024, set ? (MEM_READ_INTERNAL | MEM_WRITE_INTERNAL) : (MEM_READ_EXTERNAL | MEM_WRITE_EXTERNAL)); + + for (c = 0xa0; c < 0xf0; c++) { + if ((c >= 0xc0) && (c <= 0xcf)) + continue; + + if (sis_mode || ((c << 12) >= (mem_size << 10))) + pages[c].mem = page_ff; + else { +#if (!(defined __amd64__ || defined _M_X64 || defined __aarch64__ || defined _M_ARM64)) + if (mem_size > 1048576) { + if ((c << 12) < (1 << 30)) + pages[c].mem = &ram[c << 12]; + else + pages[c].mem = &ram2[(c << 12) - (1 << 30)]; + } else + pages[c].mem = &ram[c << 12]; +#else + pages[c].mem = &ram[c << 12]; +#endif + } + if (!sis_mode && (c < addr_space_size)) { + pages[c].write_b = mem_write_ramb_page; + pages[c].write_w = mem_write_ramw_page; + pages[c].write_l = mem_write_raml_page; + } else { + pages[c].write_b = NULL; + pages[c].write_w = NULL; + pages[c].write_l = NULL; + } +#ifdef USE_NEW_DYNAREC + pages[c].evict_prev = EVICT_NOT_IN_LIST; + pages[c].byte_dirty_mask = &byte_dirty_mask[c * 64]; + pages[c].byte_code_present_mask = &byte_code_present_mask[c * 64]; +#endif + } if (set) { - mem_mapping_set_addr(&ram_remapped_mapping, start * 1024, size * 1024); - mem_mapping_set_exec(&ram_remapped_mapping, ram + 0xa0000); - } else - mem_mapping_disable(&ram_remapped_mapping); + if (sis_mode) { + mem_mapping_set_addr(&ram_remapped_mapping, start * 1024, 0x00020000); + mem_mapping_set_exec(&ram_remapped_mapping, ram + 0x000a0000); + mem_mapping_set_addr(&ram_remapped_mapping2, (start * 1024) + 0x00020000, 0x00020000); + mem_mapping_set_exec(&ram_remapped_mapping2, ram + 0x000d0000); + + mem_mapping_set_addr(&ram_mid_mapping, 0x000c0000, 0x00010000); + mem_mapping_set_exec(&ram_mid_mapping, ram + 0x000c0000); + mem_mapping_set_addr(&ram_mid_mapping2, 0x000f0000, 0x00010000); + mem_mapping_set_exec(&ram_mid_mapping2, ram + 0x000f0000); + } else { + mem_mapping_set_addr(&ram_remapped_mapping, start * 1024, size * 1024); + mem_mapping_set_exec(&ram_remapped_mapping, ram + start_addr); + mem_mapping_disable(&ram_remapped_mapping2); + + mem_mapping_set_addr(&ram_mid_mapping, 0x000a0000, 0x00060000); + mem_mapping_set_exec(&ram_mid_mapping, ram + 0x000a0000); + mem_mapping_disable(&ram_mid_mapping2); + } + } else { + mem_mapping_disable(&ram_remapped_mapping); + mem_mapping_disable(&ram_remapped_mapping2); + + mem_mapping_set_addr(&ram_mid_mapping, 0x000a0000, 0x00060000); + mem_mapping_set_exec(&ram_mid_mapping, ram + 0x000a0000); + mem_mapping_disable(&ram_mid_mapping2); + } flushmmucache(); } - void mem_reset_page_blocks(void) { - uint32_t c; + if (pages == NULL) + return; - if (pages == NULL) return; - - for (c = 0; c < pages_sz; c++) { - pages[c].write_b = mem_write_ramb_page; - pages[c].write_w = mem_write_ramw_page; - pages[c].write_l = mem_write_raml_page; + for (uint32_t c = 0; c < pages_sz; c++) { + pages[c].write_b = mem_write_ramb_page; + pages[c].write_w = mem_write_ramw_page; + pages[c].write_l = mem_write_raml_page; #ifdef USE_NEW_DYNAREC - pages[c].block = BLOCK_INVALID; - pages[c].block_2 = BLOCK_INVALID; - pages[c].head = BLOCK_INVALID; + pages[c].block = BLOCK_INVALID; + pages[c].block_2 = BLOCK_INVALID; + pages[c].head = BLOCK_INVALID; #else - pages[c].block[0] = pages[c].block[1] = pages[c].block[2] = pages[c].block[3] = NULL; - pages[c].block_2[0] = pages[c].block_2[1] = pages[c].block_2[2] = pages[c].block_2[3] = NULL; - pages[c].head = NULL; + pages[c].block[0] = pages[c].block[1] = pages[c].block[2] = pages[c].block[3] = NULL; + pages[c].block_2[0] = pages[c].block_2[1] = pages[c].block_2[2] = pages[c].block_2[3] = NULL; + pages[c].head = NULL; #endif } } - void mem_a20_recalc(void) { int state; - if (! is286) { - rammask = 0xfffff; - flushmmucache(); - mem_a20_key = mem_a20_alt = mem_a20_state = 0; + if (!is286) { + rammask = 0xfffff; + flushmmucache(); + mem_a20_key = mem_a20_alt = mem_a20_state = 0; - return; + return; } state = mem_a20_key | mem_a20_alt; if (state && !mem_a20_state) { - rammask = (cpu_16bitbus) ? 0xffffff : 0xffffffff; - flushmmucache(); + rammask = cpu_16bitbus ? 0xffffff : 0xffffffff; + if (is6117) + rammask |= 0x03000000; + flushmmucache(); } else if (!state && mem_a20_state) { - rammask = (cpu_16bitbus) ? 0xefffff : 0xffefffff; - flushmmucache(); + rammask = cpu_16bitbus ? 0xefffff : 0xffefffff; + if (is6117) + rammask |= 0x03000000; + flushmmucache(); } mem_a20_state = state; diff --git a/src/mem/mmu_2386.c b/src/mem/mmu_2386.c new file mode 100644 index 000000000..21c62b833 --- /dev/null +++ b/src/mem/mmu_2386.c @@ -0,0 +1,990 @@ +/* + * 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. + * + * Memory handling and MMU. + * + * Authors: Sarah Walker, + * Miran Grca, + * Fred N. van Kempen, + * + * Copyright 2008-2020 Sarah Walker. + * Copyright 2016-2020 Miran Grca. + * Copyright 2017-2020 Fred N. van Kempen. + */ +#include +#include +#include +#include +#include +#include +#include +#define HAVE_STDARG_H +#include <86box/86box.h> +#include <86box/version.h> +#include "cpu.h" +#include "x86_ops.h" +#include "x86.h" +#include "x86seg_common.h" +#include <86box/machine.h> +#include <86box/m_xt_xi8088.h> +#include <86box/config.h> +#include <86box/io.h> +#include <86box/mem.h> +#include <86box/plat.h> +#include <86box/rom.h> +#include <86box/gdbstub.h> + +uint8_t +mem_readb_map(uint32_t addr) +{ + mem_mapping_t *map = read_mapping[addr >> MEM_GRANULARITY_BITS]; + uint8_t ret = 0xff; + + mem_logical_addr = 0xffffffff; + + if (map && map->read_b) + ret = map->read_b(addr, map->priv); + + return ret; +} + +uint16_t +mem_readw_map(uint32_t addr) +{ + mem_mapping_t *map = read_mapping[addr >> MEM_GRANULARITY_BITS]; + uint16_t ret; + + mem_logical_addr = 0xffffffff; + + if (((addr & MEM_GRANULARITY_MASK) <= MEM_GRANULARITY_HBOUND) && (map && map->read_w)) + ret = map->read_w(addr, map->priv); + else { + ret = mem_readb_phys(addr + 1) << 8; + ret |= mem_readb_phys(addr); + } + + return ret; +} + +uint32_t +mem_readl_map(uint32_t addr) +{ + mem_mapping_t *map = read_mapping[addr >> MEM_GRANULARITY_BITS]; + uint32_t ret; + + mem_logical_addr = 0xffffffff; + + if (!cpu_16bitbus && ((addr & MEM_GRANULARITY_MASK) <= MEM_GRANULARITY_QBOUND) && (map && map->read_l)) + ret = map->read_l(addr, map->priv); + else { + ret = mem_readw_phys(addr + 2) << 16; + ret |= mem_readw_phys(addr); + } + + return ret; +} + +void +mem_writeb_map(uint32_t addr, uint8_t val) +{ + mem_mapping_t *map = read_mapping[addr >> MEM_GRANULARITY_BITS]; + + mem_logical_addr = 0xffffffff; + + if (map && map->write_b) + map->write_b(addr, val, map->priv); +} + +void +mem_writew_map(uint32_t addr, uint16_t val) +{ + mem_mapping_t *map = read_mapping[addr >> MEM_GRANULARITY_BITS]; + + mem_logical_addr = 0xffffffff; + + if (((addr & MEM_GRANULARITY_MASK) <= MEM_GRANULARITY_HBOUND) && (map && map->write_w)) + map->write_w(addr, val, map->priv); + else { + mem_writeb_phys(addr, val & 0xff); + mem_writeb_phys(addr + 1, val >> 8); + } +} + +void +mem_writel_map(uint32_t addr, uint32_t val) +{ + mem_mapping_t *map = read_mapping[addr >> MEM_GRANULARITY_BITS]; + + mem_logical_addr = 0xffffffff; + + if (!cpu_16bitbus && ((addr & MEM_GRANULARITY_MASK) <= MEM_GRANULARITY_QBOUND) && (map && map->write_l)) + map->write_l(addr, val, map->priv); + else { + mem_writew_phys(addr, val & 0xffff); + mem_writew_phys(addr + 2, val >> 16); + } +} + +#define mmutranslate_read_2386(addr) mmutranslatereal_2386(addr,0) +#define mmutranslate_write_2386(addr) mmutranslatereal_2386(addr,1) + +uint64_t +mmutranslatereal_2386(uint32_t addr, int rw) +{ + uint32_t temp; + uint32_t temp2; + uint32_t temp3; + uint32_t addr2; + + if (cpu_state.abrt) + return 0xffffffffffffffffULL; + + addr2 = ((cr3 & ~0xfff) + ((addr >> 20) & 0xffc)); + temp = temp2 = mem_readl_map(addr2); + if (!(temp & 1)) { + cr2 = addr; + temp &= 1; + if (CPL == 3) + temp |= 4; + if (rw) + temp |= 2; + cpu_state.abrt = ABRT_PF; + abrt_error = temp; + return 0xffffffffffffffffULL; + } + + if ((temp & 0x80) && (cr4 & CR4_PSE)) { + /*4MB page*/ + if (((CPL == 3) && !(temp & 4) && !cpl_override) || (rw && !(temp & 2) && (((CPL == 3) && !cpl_override) || ((is486 || isibm486) && (cr0 & WP_FLAG))))) { + cr2 = addr; + temp &= 1; + if (CPL == 3) + temp |= 4; + if (rw) + temp |= 2; + cpu_state.abrt = ABRT_PF; + abrt_error = temp; + + return 0xffffffffffffffffULL; + } + + mmu_perm = temp & 4; + mem_writel_map(addr2, mem_readl_map(addr2) | (rw ? 0x60 : 0x20)); + + return (temp & ~0x3fffff) + (addr & 0x3fffff); + } + + temp = mem_readl_map((temp & ~0xfff) + ((addr >> 10) & 0xffc)); + temp3 = temp & temp2; + if (!(temp & 1) || ((CPL == 3) && !(temp3 & 4) && !cpl_override) || (rw && !(temp3 & 2) && (((CPL == 3) && !cpl_override) || ((is486 || isibm486) && (cr0 & WP_FLAG))))) { + cr2 = addr; + temp &= 1; + if (CPL == 3) + temp |= 4; + if (rw) + temp |= 2; + cpu_state.abrt = ABRT_PF; + abrt_error = temp; + return 0xffffffffffffffffULL; + } + + mmu_perm = temp & 4; + mem_writel_map(addr2, mem_readl_map(addr2) | 0x20); + mem_writel_map((temp2 & ~0xfff) + ((addr >> 10) & 0xffc), + mem_readl_map((temp2 & ~0xfff) + ((addr >> 10) & 0xffc)) | (rw ? 0x60 : 0x20)); + + return (uint64_t) ((temp & ~0xfff) + (addr & 0xfff)); +} + +uint64_t +mmutranslate_noabrt_2386(uint32_t addr, int rw) +{ + uint32_t temp; + uint32_t temp2; + uint32_t temp3; + uint32_t addr2; + + if (cpu_state.abrt) + return 0xffffffffffffffffULL; + + addr2 = ((cr3 & ~0xfff) + ((addr >> 20) & 0xffc)); + temp = temp2 = mem_readl_map(addr2); + + if (!(temp & 1)) + return 0xffffffffffffffffULL; + + if ((temp & 0x80) && (cr4 & CR4_PSE)) { + /*4MB page*/ + if (((CPL == 3) && !(temp & 4) && !cpl_override) || (rw && !(temp & 2) && ((CPL == 3) || (cr0 & WP_FLAG)))) + return 0xffffffffffffffffULL; + + return (temp & ~0x3fffff) + (addr & 0x3fffff); + } + + temp = mem_readl_map((temp & ~0xfff) + ((addr >> 10) & 0xffc)); + temp3 = temp & temp2; + + if (!(temp & 1) || ((CPL == 3) && !(temp3 & 4) && !cpl_override) || (rw && !(temp3 & 2) && ((CPL == 3) || (cr0 & WP_FLAG)))) + return 0xffffffffffffffffULL; + + return (uint64_t) ((temp & ~0xfff) + (addr & 0xfff)); +} + +uint8_t +readmembl_2386(uint32_t addr) +{ + mem_mapping_t *map; + uint64_t a; + + GDBSTUB_MEM_ACCESS(addr, GDBSTUB_MEM_READ, 1); + + addr64 = (uint64_t) addr; + mem_logical_addr = addr; + + high_page = 0; + + if (cr0 >> 31) { + a = mmutranslate_read_2386(addr); + addr64 = (uint32_t) a; + + if (a > 0xffffffffULL) + return 0xff; + } + addr = (uint32_t) (addr64 & rammask); + + map = read_mapping[addr >> MEM_GRANULARITY_BITS]; + if (map && map->read_b) + return map->read_b(addr, map->priv); + + return 0xff; +} + +void +writemembl_2386(uint32_t addr, uint8_t val) +{ + mem_mapping_t *map; + uint64_t a; + + GDBSTUB_MEM_ACCESS(addr, GDBSTUB_MEM_WRITE, 1); + + addr64 = (uint64_t) addr; + mem_logical_addr = addr; + + high_page = 0; + + if (cr0 >> 31) { + a = mmutranslate_write_2386(addr); + addr64 = (uint32_t) a; + + if (a > 0xffffffffULL) + return; + } + addr = (uint32_t) (addr64 & rammask); + + map = write_mapping[addr >> MEM_GRANULARITY_BITS]; + if (map && map->write_b) + map->write_b(addr, val, map->priv); +} + +/* Read a byte from memory without MMU translation - result of previous MMU translation passed as value. */ +uint8_t +readmembl_no_mmut_2386(uint32_t addr, uint32_t a64) +{ + mem_mapping_t *map; + + GDBSTUB_MEM_ACCESS(addr, GDBSTUB_MEM_READ, 1); + + mem_logical_addr = addr; + + if (cr0 >> 31) { + if (cpu_state.abrt || high_page) + return 0xff; + + addr = a64 & rammask; + } else + addr &= rammask; + + map = read_mapping[addr >> MEM_GRANULARITY_BITS]; + if (map && map->read_b) + return map->read_b(addr, map->priv); + + return 0xff; +} + +/* Write a byte to memory without MMU translation - result of previous MMU translation passed as value. */ +void +writemembl_no_mmut_2386(uint32_t addr, uint32_t a64, uint8_t val) +{ + mem_mapping_t *map; + + GDBSTUB_MEM_ACCESS(addr, GDBSTUB_MEM_WRITE, 1); + + mem_logical_addr = addr; + + if (cr0 >> 31) { + if (cpu_state.abrt || high_page) + return; + + addr = a64 & rammask; + } else + addr &= rammask; + + map = write_mapping[addr >> MEM_GRANULARITY_BITS]; + if (map && map->write_b) + map->write_b(addr, val, map->priv); +} + +uint16_t +readmemwl_2386(uint32_t addr) +{ + mem_mapping_t *map; + uint64_t a; + + addr64a[0] = addr; + addr64a[1] = addr + 1; + GDBSTUB_MEM_ACCESS_FAST(addr64a, GDBSTUB_MEM_READ, 2); + + mem_logical_addr = addr; + + high_page = 0; + + if (addr & 1) { + if (!cpu_cyrix_alignment || (addr & 7) == 7) + cycles -= timing_misaligned; + if ((addr & 0xfff) > 0xffe) { + if (cr0 >> 31) { + for (uint8_t i = 0; i < 2; i++) { + a = mmutranslate_read_2386(addr + i); + addr64a[i] = (uint32_t) a; + + if (a > 0xffffffffULL) + return 0xffff; + } + } + + return readmembl_no_mmut(addr, addr64a[0]) | (((uint16_t) readmembl_no_mmut(addr + 1, addr64a[1])) << 8); + } + } + + if (cr0 >> 31) { + a = mmutranslate_read_2386(addr); + addr64a[0] = (uint32_t) a; + + if (a > 0xffffffffULL) + return 0xffff; + } else + addr64a[0] = (uint64_t) addr; + + addr = addr64a[0] & rammask; + + map = read_mapping[addr >> MEM_GRANULARITY_BITS]; + + if (map && map->read_w) + return map->read_w(addr, map->priv); + + if (map && map->read_b) { + return map->read_b(addr, map->priv) | ((uint16_t) (map->read_b(addr + 1, map->priv)) << 8); + } + + return 0xffff; +} + +void +writememwl_2386(uint32_t addr, uint16_t val) +{ + mem_mapping_t *map; + uint64_t a; + + addr64a[0] = addr; + addr64a[1] = addr + 1; + GDBSTUB_MEM_ACCESS_FAST(addr64a, GDBSTUB_MEM_WRITE, 2); + + mem_logical_addr = addr; + + high_page = 0; + + if (addr & 1) { + if (!cpu_cyrix_alignment || (addr & 7) == 7) + cycles -= timing_misaligned; + if ((addr & 0xfff) > 0xffe) { + if (cr0 >> 31) { + for (uint8_t i = 0; i < 2; i++) { + /* Do not translate a page that has a valid lookup, as that is by definition valid + and the whole purpose of the lookup is to avoid repeat identical translations. */ + if (!page_lookup[(addr + i) >> 12] || !page_lookup[(addr + i) >> 12]->write_b) { + a = mmutranslate_write_2386(addr + i); + addr64a[i] = (uint32_t) a; + + if (a > 0xffffffffULL) + return; + } + } + } + + /* No need to waste precious CPU host cycles on mmutranslate's that were already done, just pass + their result as a parameter to be used if needed. */ + writemembl_no_mmut(addr, addr64a[0], val); + writemembl_no_mmut(addr + 1, addr64a[1], val >> 8); + return; + } + } + + if (cr0 >> 31) { + a = mmutranslate_write_2386(addr); + addr64a[0] = (uint32_t) a; + + if (a > 0xffffffffULL) + return; + } + + addr = addr64a[0] & rammask; + + map = write_mapping[addr >> MEM_GRANULARITY_BITS]; + + if (map && map->write_w) { + map->write_w(addr, val, map->priv); + return; + } + + if (map && map->write_b) { + map->write_b(addr, val, map->priv); + map->write_b(addr + 1, val >> 8, map->priv); + return; + } +} + +/* Read a word from memory without MMU translation - results of previous MMU translation passed as array. */ +uint16_t +readmemwl_no_mmut_2386(uint32_t addr, uint32_t *a64) +{ + mem_mapping_t *map; + + GDBSTUB_MEM_ACCESS(addr, GDBSTUB_MEM_READ, 2); + + mem_logical_addr = addr; + + if (addr & 1) { + if (!cpu_cyrix_alignment || (addr & 7) == 7) + cycles -= timing_misaligned; + if ((addr & 0xfff) > 0xffe) { + if (cr0 >> 31) { + if (cpu_state.abrt || high_page) + return 0xffff; + } + + return readmembl_no_mmut(addr, a64[0]) | (((uint16_t) readmembl_no_mmut(addr + 1, a64[1])) << 8); + } + } + + if (cr0 >> 31) { + if (cpu_state.abrt || high_page) + return 0xffff; + + addr = (uint32_t) (a64[0] & rammask); + } else + addr &= rammask; + + map = read_mapping[addr >> MEM_GRANULARITY_BITS]; + + if (map && map->read_w) + return map->read_w(addr, map->priv); + + if (map && map->read_b) { + return map->read_b(addr, map->priv) | ((uint16_t) (map->read_b(addr + 1, map->priv)) << 8); + } + + return 0xffff; +} + +/* Write a word to memory without MMU translation - results of previous MMU translation passed as array. */ +void +writememwl_no_mmut_2386(uint32_t addr, uint32_t *a64, uint16_t val) +{ + mem_mapping_t *map; + + GDBSTUB_MEM_ACCESS(addr, GDBSTUB_MEM_WRITE, 2); + + mem_logical_addr = addr; + + if (addr & 1) { + if (!cpu_cyrix_alignment || (addr & 7) == 7) + cycles -= timing_misaligned; + if ((addr & 0xfff) > 0xffe) { + if (cr0 >> 31) { + if (cpu_state.abrt || high_page) + return; + } + + writemembl_no_mmut(addr, a64[0], val); + writemembl_no_mmut(addr + 1, a64[1], val >> 8); + return; + } + } + + if (cr0 >> 31) { + if (cpu_state.abrt || high_page) + return; + + addr = (uint32_t) (a64[0] & rammask); + } else + addr &= rammask; + + map = write_mapping[addr >> MEM_GRANULARITY_BITS]; + + if (map && map->write_w) { + map->write_w(addr, val, map->priv); + return; + } + + if (map && map->write_b) { + map->write_b(addr, val, map->priv); + map->write_b(addr + 1, val >> 8, map->priv); + return; + } +} + +uint32_t +readmemll_2386(uint32_t addr) +{ + mem_mapping_t *map; + int i; + uint64_t a = 0x0000000000000000ULL; + + for (i = 0; i < 4; i++) + addr64a[i] = (uint64_t) (addr + i); + GDBSTUB_MEM_ACCESS_FAST(addr64a, GDBSTUB_MEM_READ, 4); + + mem_logical_addr = addr; + + high_page = 0; + + if (addr & 3) { + if (!cpu_cyrix_alignment || (addr & 7) > 4) + cycles -= timing_misaligned; + if ((addr & 0xfff) > 0xffc) { + if (cr0 >> 31) { + for (i = 0; i < 4; i++) { + if (i == 0) { + a = mmutranslate_read_2386(addr + i); + addr64a[i] = (uint32_t) a; + } else if (!((addr + i) & 0xfff)) { + a = mmutranslate_read_2386(addr + 3); + addr64a[i] = (uint32_t) a; + if (!cpu_state.abrt) { + a = (a & ~0xfffLL) | ((uint64_t) ((addr + i) & 0xfff)); + addr64a[i] = (uint32_t) a; + } + } else { + a = (a & ~0xfffLL) | ((uint64_t) ((addr + i) & 0xfff)); + addr64a[i] = (uint32_t) a; + } + + if (a > 0xffffffffULL) + return 0xffff; + } + } + + /* No need to waste precious CPU host cycles on mmutranslate's that were already done, just pass + their result as a parameter to be used if needed. */ + return readmemwl_no_mmut(addr, addr64a) | (((uint32_t) readmemwl_no_mmut(addr + 2, &(addr64a[2]))) << 16); + } + } + + if (cr0 >> 31) { + a = mmutranslate_read_2386(addr); + addr64a[0] = (uint32_t) a; + + if (a > 0xffffffffULL) + return 0xffffffff; + } + + addr = addr64a[0] & rammask; + + map = read_mapping[addr >> MEM_GRANULARITY_BITS]; + + if (map && map->read_l) + return map->read_l(addr, map->priv); + + if (map && map->read_w) + return map->read_w(addr, map->priv) | ((uint32_t) (map->read_w(addr + 2, map->priv)) << 16); + + if (map && map->read_b) + return map->read_b(addr, map->priv) | ((uint32_t) (map->read_b(addr + 1, map->priv)) << 8) | ((uint32_t) (map->read_b(addr + 2, map->priv)) << 16) | ((uint32_t) (map->read_b(addr + 3, map->priv)) << 24); + + return 0xffffffff; +} + +void +writememll_2386(uint32_t addr, uint32_t val) +{ + mem_mapping_t *map; + int i; + uint64_t a = 0x0000000000000000ULL; + + for (i = 0; i < 4; i++) + addr64a[i] = (uint64_t) (addr + i); + GDBSTUB_MEM_ACCESS_FAST(addr64a, GDBSTUB_MEM_WRITE, 4); + + mem_logical_addr = addr; + + high_page = 0; + + if (addr & 3) { + if (!cpu_cyrix_alignment || (addr & 7) > 4) + cycles -= timing_misaligned; + if ((addr & 0xfff) > 0xffc) { + if (cr0 >> 31) { + for (i = 0; i < 4; i++) { + /* Do not translate a page that has a valid lookup, as that is by definition valid + and the whole purpose of the lookup is to avoid repeat identical translations. */ + if (!page_lookup[(addr + i) >> 12] || !page_lookup[(addr + i) >> 12]->write_b) { + if (i == 0) { + a = mmutranslate_write_2386(addr + i); + addr64a[i] = (uint32_t) a; + } else if (!((addr + i) & 0xfff)) { + a = mmutranslate_write_2386(addr + 3); + addr64a[i] = (uint32_t) a; + if (!cpu_state.abrt) { + a = (a & ~0xfffLL) | ((uint64_t) ((addr + i) & 0xfff)); + addr64a[i] = (uint32_t) a; + } + } else { + a = (a & ~0xfffLL) | ((uint64_t) ((addr + i) & 0xfff)); + addr64a[i] = (uint32_t) a; + } + + if (a > 0xffffffffULL) + return; + } + } + } + + /* No need to waste precious CPU host cycles on mmutranslate's that were already done, just pass + their result as a parameter to be used if needed. */ + writememwl_no_mmut(addr, &(addr64a[0]), val); + writememwl_no_mmut(addr + 2, &(addr64a[2]), val >> 16); + return; + } + } + + if (cr0 >> 31) { + a = mmutranslate_write_2386(addr); + addr64a[0] = (uint32_t) a; + + if (a > 0xffffffffULL) + return; + } + + addr = addr64a[0] & rammask; + + map = write_mapping[addr >> MEM_GRANULARITY_BITS]; + + if (map && map->write_l) { + map->write_l(addr, val, map->priv); + return; + } + if (map && map->write_w) { + map->write_w(addr, val, map->priv); + map->write_w(addr + 2, val >> 16, map->priv); + return; + } + if (map && map->write_b) { + map->write_b(addr, val, map->priv); + map->write_b(addr + 1, val >> 8, map->priv); + map->write_b(addr + 2, val >> 16, map->priv); + map->write_b(addr + 3, val >> 24, map->priv); + return; + } +} + +/* Read a long from memory without MMU translation - results of previous MMU translation passed as array. */ +uint32_t +readmemll_no_mmut_2386(uint32_t addr, uint32_t *a64) +{ + mem_mapping_t *map; + + GDBSTUB_MEM_ACCESS(addr, GDBSTUB_MEM_READ, 4); + + mem_logical_addr = addr; + + if (addr & 3) { + if (!cpu_cyrix_alignment || (addr & 7) > 4) + cycles -= timing_misaligned; + if ((addr & 0xfff) > 0xffc) { + if (cr0 >> 31) { + if (cpu_state.abrt || high_page) + return 0xffffffff; + } + + return readmemwl_no_mmut(addr, a64) | ((uint32_t) (readmemwl_no_mmut(addr + 2, &(a64[2]))) << 16); + } + } + + if (cr0 >> 31) { + if (cpu_state.abrt || high_page) + return 0xffffffff; + + addr = (uint32_t) (a64[0] & rammask); + } else + addr &= rammask; + + map = read_mapping[addr >> MEM_GRANULARITY_BITS]; + + if (map && map->read_l) + return map->read_l(addr, map->priv); + + if (map && map->read_w) + return map->read_w(addr, map->priv) | ((uint32_t) (map->read_w(addr + 2, map->priv)) << 16); + + if (map && map->read_b) + return map->read_b(addr, map->priv) | ((uint32_t) (map->read_b(addr + 1, map->priv)) << 8) | ((uint32_t) (map->read_b(addr + 2, map->priv)) << 16) | ((uint32_t) (map->read_b(addr + 3, map->priv)) << 24); + + return 0xffffffff; +} + +/* Write a long to memory without MMU translation - results of previous MMU translation passed as array. */ +void +writememll_no_mmut_2386(uint32_t addr, uint32_t *a64, uint32_t val) +{ + mem_mapping_t *map; + + GDBSTUB_MEM_ACCESS(addr, GDBSTUB_MEM_WRITE, 4); + + mem_logical_addr = addr; + + if (addr & 3) { + if (!cpu_cyrix_alignment || (addr & 7) > 4) + cycles -= timing_misaligned; + if ((addr & 0xfff) > 0xffc) { + if (cr0 >> 31) { + if (cpu_state.abrt || high_page) + return; + } + + writememwl_no_mmut(addr, &(a64[0]), val); + writememwl_no_mmut(addr + 2, &(a64[2]), val >> 16); + return; + } + } + + if (cr0 >> 31) { + if (cpu_state.abrt || high_page) + return; + + addr = (uint32_t) (a64[0] & rammask); + } else + addr &= rammask; + + map = write_mapping[addr >> MEM_GRANULARITY_BITS]; + + if (map && map->write_l) { + map->write_l(addr, val, map->priv); + return; + } + if (map && map->write_w) { + map->write_w(addr, val, map->priv); + map->write_w(addr + 2, val >> 16, map->priv); + return; + } + if (map && map->write_b) { + map->write_b(addr, val, map->priv); + map->write_b(addr + 1, val >> 8, map->priv); + map->write_b(addr + 2, val >> 16, map->priv); + map->write_b(addr + 3, val >> 24, map->priv); + return; + } +} + +uint64_t +readmemql_2386(uint32_t addr) +{ + mem_mapping_t *map; + int i; + uint64_t a = 0x0000000000000000ULL; + + for (i = 0; i < 8; i++) + addr64a[i] = (uint64_t) (addr + i); + GDBSTUB_MEM_ACCESS_FAST(addr64a, GDBSTUB_MEM_READ, 8); + + mem_logical_addr = addr; + + high_page = 0; + + if (addr & 7) { + cycles -= timing_misaligned; + if ((addr & 0xfff) > 0xff8) { + if (cr0 >> 31) { + for (i = 0; i < 8; i++) { + if (i == 0) { + a = mmutranslate_read_2386(addr + i); + addr64a[i] = (uint32_t) a; + } else if (!((addr + i) & 0xfff)) { + a = mmutranslate_read_2386(addr + 7); + addr64a[i] = (uint32_t) a; + if (!cpu_state.abrt) { + a = (a & ~0xfffLL) | ((uint64_t) ((addr + i) & 0xfff)); + addr64a[i] = (uint32_t) a; + } + } else { + a = (a & ~0xfffLL) | ((uint64_t) ((addr + i) & 0xfff)); + addr64a[i] = (uint32_t) a; + } + + if (a > 0xffffffffULL) + return 0xffff; + } + } + + /* No need to waste precious CPU host cycles on mmutranslate's that were already done, just pass + their result as a parameter to be used if needed. */ + return readmemll_no_mmut(addr, addr64a) | (((uint64_t) readmemll_no_mmut(addr + 4, &(addr64a[4]))) << 32); + } + } + + if (cr0 >> 31) { + a = mmutranslate_read_2386(addr); + addr64a[0] = (uint32_t) a; + + if (a > 0xffffffffULL) + return 0xffffffffffffffffULL; + } + + addr = addr64a[0] & rammask; + + map = read_mapping[addr >> MEM_GRANULARITY_BITS]; + if (map && map->read_l) + return map->read_l(addr, map->priv) | ((uint64_t) map->read_l(addr + 4, map->priv) << 32); + + return readmemll(addr) | ((uint64_t) readmemll(addr + 4) << 32); +} + +void +writememql_2386(uint32_t addr, uint64_t val) +{ + mem_mapping_t *map; + int i; + uint64_t a = 0x0000000000000000ULL; + + for (i = 0; i < 8; i++) + addr64a[i] = (uint64_t) (addr + i); + GDBSTUB_MEM_ACCESS_FAST(addr64a, GDBSTUB_MEM_WRITE, 8); + + mem_logical_addr = addr; + + high_page = 0; + + if (addr & 7) { + cycles -= timing_misaligned; + if ((addr & 0xfff) > 0xff8) { + if (cr0 >> 31) { + for (i = 0; i < 8; i++) { + /* Do not translate a page that has a valid lookup, as that is by definition valid + and the whole purpose of the lookup is to avoid repeat identical translations. */ + if (!page_lookup[(addr + i) >> 12] || !page_lookup[(addr + i) >> 12]->write_b) { + if (i == 0) { + a = mmutranslate_write_2386(addr + i); + addr64a[i] = (uint32_t) a; + } else if (!((addr + i) & 0xfff)) { + a = mmutranslate_write_2386(addr + 7); + addr64a[i] = (uint32_t) a; + if (!cpu_state.abrt) { + a = (a & ~0xfffLL) | ((uint64_t) ((addr + i) & 0xfff)); + addr64a[i] = (uint32_t) a; + } + } else { + a = (a & ~0xfffLL) | ((uint64_t) ((addr + i) & 0xfff)); + addr64a[i] = (uint32_t) a; + } + + if (addr64a[i] > 0xffffffffULL) + return; + } + } + } + + /* No need to waste precious CPU host cycles on mmutranslate's that were already done, just pass + their result as a parameter to be used if needed. */ + writememll_no_mmut(addr, addr64a, val); + writememll_no_mmut(addr + 4, &(addr64a[4]), val >> 32); + return; + } + } + + if (cr0 >> 31) { + addr64a[0] = mmutranslate_write_2386(addr); + if (addr64a[0] > 0xffffffffULL) + return; + } + + addr = addr64a[0] & rammask; + + map = write_mapping[addr >> MEM_GRANULARITY_BITS]; + + if (map && map->write_l) { + map->write_l(addr, val, map->priv); + map->write_l(addr + 4, val >> 32, map->priv); + return; + } + if (map && map->write_w) { + map->write_w(addr, val, map->priv); + map->write_w(addr + 2, val >> 16, map->priv); + map->write_w(addr + 4, val >> 32, map->priv); + map->write_w(addr + 6, val >> 48, map->priv); + return; + } + if (map && map->write_b) { + map->write_b(addr, val, map->priv); + map->write_b(addr + 1, val >> 8, map->priv); + map->write_b(addr + 2, val >> 16, map->priv); + map->write_b(addr + 3, val >> 24, map->priv); + map->write_b(addr + 4, val >> 32, map->priv); + map->write_b(addr + 5, val >> 40, map->priv); + map->write_b(addr + 6, val >> 48, map->priv); + map->write_b(addr + 7, val >> 56, map->priv); + return; + } +} + +void +do_mmutranslate_2386(uint32_t addr, uint32_t *a64, int num, int write) +{ + int i; + uint32_t last_addr = addr + (num - 1); + uint64_t a = 0x0000000000000000ULL; + + for (i = 0; i < num; i++) + a64[i] = (uint64_t) addr; + + for (i = 0; i < num; i++) { + if (cr0 >> 31) { + /* If we have encountered at least one page fault, mark all subsequent addresses as + having page faulted, prevents false negatives in readmem*l_no_mmut. */ + if ((i > 0) && cpu_state.abrt && !high_page) + a64[i] = a64[i - 1]; + /* If we are on the same page, there is no need to translate again, as we can just + reuse the previous result. */ + else if (i == 0) { + a = mmutranslatereal_2386(addr, write); + a64[i] = (uint32_t) a; + } else if (!(addr & 0xfff)) { + a = mmutranslatereal_2386(last_addr, write); + a64[i] = (uint32_t) a; + + if (!cpu_state.abrt) { + a = (a & 0xfffffffffffff000ULL) | ((uint64_t) (addr & 0xfff)); + a64[i] = (uint32_t) a; + } + } else { + a = (a & 0xfffffffffffff000ULL) | ((uint64_t) (addr & 0xfff)); + a64[i] = (uint32_t) a; + } + } + + addr++; + } +} diff --git a/src/mem/rom.c b/src/mem/rom.c index 8fbd7ff97..4a20e8ebc 100644 --- a/src/mem/rom.c +++ b/src/mem/rom.c @@ -1,26 +1,26 @@ /* - * 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. + * 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. + * This file is part of the 86Box distribution. * - * Handling of ROM image files. + * Handling of ROM image files. * - * NOTES: - pc2386 BIOS is corrupt (JMP at F000:FFF0 points to RAM) - * - pc2386 video BIOS is underdumped (16k instead of 24k) - * - c386sx16 BIOS fails checksum + * NOTES: - pc2386 BIOS is corrupt (JMP at F000:FFF0 points to RAM) + * - pc2386 video BIOS is underdumped (16k instead of 24k) + * - c386sx16 BIOS fails checksum * * * - * Authors: Sarah Walker, - * Miran Grca, - * Fred N. van Kempen, + * Authors: Sarah Walker, + * Miran Grca, + * Fred N. van Kempen, * - * Copyright 2008-2019 Sarah Walker. - * Copyright 2016-2019 Miran Grca. - * Copyright 2018,2019 Fred N. van Kempen. + * Copyright 2008-2019 Sarah Walker. + * Copyright 2016-2019 Miran Grca. + * Copyright 2018-2019 Fred N. van Kempen. */ #include #include @@ -33,304 +33,318 @@ #include "cpu.h" #include <86box/mem.h> #include <86box/rom.h> +#include <86box/path.h> #include <86box/plat.h> #include <86box/machine.h> #include <86box/m_xt_xi8088.h> - #ifdef ENABLE_ROM_LOG int rom_do_log = ENABLE_ROM_LOG; - static void rom_log(const char *fmt, ...) { va_list ap; if (rom_do_log) { - va_start(ap, fmt); - pclog_ex(fmt, ap); - va_end(ap); + va_start(ap, fmt); + pclog_ex(fmt, ap); + va_end(ap); } } #else -#define rom_log(fmt, ...) +# define rom_log(fmt, ...) #endif - -FILE * -rom_fopen(char *fn, char *mode) +void +rom_add_path(const char *path) { - char temp[1024]; - char *fn2; + char cwd[1024] = { 0 }; - if ((strstr(fn, "roms/") == fn) || (strstr(fn, "roms\\") == fn)) { - /* Relative path */ - fn2 = (char *) malloc(strlen(fn) + 1); - memcpy(fn2, fn, strlen(fn) + 1); + rom_path_t *rom_path = &rom_paths; - if (rom_path[0] != '\0') { - memset(fn2, 0x00, strlen(fn) + 1); - memcpy(fn2, &(fn[5]), strlen(fn) - 4); + if (rom_paths.path[0] != '\0') { + // Iterate to the end of the list. + while (rom_path->next != NULL) { + rom_path = rom_path->next; + } - plat_append_filename(temp, rom_path, fn2); - } else { - /* Make sure to make it a backslash, just in case there's malformed - code calling us that assumes Windows. */ - if (fn2[4] == '\\') - fn2[4] = '/'; - - plat_append_filename(temp, exe_path, fn2); - } - - free(fn2); - fn2 = NULL; - - return(plat_fopen(temp, mode)); - } else { - /* Absolute path */ - return(plat_fopen(fn, mode)); + // Allocate the new entry. + rom_path = rom_path->next = calloc(1, sizeof(rom_path_t)); } + + // Save the path, turning it into absolute if needed. + if (!path_abs((char *) path)) { + plat_getcwd(cwd, sizeof(cwd)); + path_slash(cwd); + snprintf(rom_path->path, sizeof(rom_path->path), "%s%s", cwd, path); + } else { + snprintf(rom_path->path, sizeof(rom_path->path), "%s", path); + } + + // Ensure the path ends with a separator. + path_slash(rom_path->path); } +FILE * +rom_fopen(const char *fn, char *mode) +{ + char temp[1024]; + FILE *fp = NULL; + + if (strstr(fn, "roms/") == fn) { + /* Relative path */ + for (rom_path_t *rom_path = &rom_paths; rom_path != NULL; rom_path = rom_path->next) { + path_append_filename(temp, rom_path->path, fn + 5); + + if ((fp = plat_fopen(temp, mode)) != NULL) { + return fp; + } + } + + return fp; + } else { + /* Absolute path */ + return plat_fopen(fn, mode); + } +} int rom_getfile(char *fn, char *s, int size) { - FILE *f; + char temp[1024]; - plat_append_filename(s, exe_path, fn); + if (strstr(fn, "roms/") == fn) { + /* Relative path */ + for (rom_path_t *rom_path = &rom_paths; rom_path != NULL; rom_path = rom_path->next) { + path_append_filename(temp, rom_path->path, fn + 5); - f = plat_fopen(s, "rb"); - if (f != NULL) { - (void)fclose(f); - return(1); + if (rom_present(temp)) { + strncpy(s, temp, size); + return 1; + } + } + + return 0; + } else { + /* Absolute path */ + if (rom_present(fn)) { + strncpy(s, fn, size); + return 1; + } + + return 0; } - - return(0); } - int -rom_present(char *fn) +rom_present(const char *fn) { - FILE *f; + FILE *fp; - f = rom_fopen(fn, "rb"); - if (f != NULL) { - (void)fclose(f); - return(1); + fp = rom_fopen(fn, "rb"); + if (fp != NULL) { + (void) fclose(fp); + return 1; } - return(0); + return 0; } - uint8_t rom_read(uint32_t addr, void *priv) { - rom_t *rom = (rom_t *)priv; + const rom_t *rom = (rom_t *) priv; #ifdef ROM_TRACE - if (rom->mapping.base==ROM_TRACE) - rom_log("ROM: read byte from BIOS at %06lX\n", addr); + if (rom->mapping.base == ROM_TRACE) + rom_log("ROM: read byte from BIOS at %06lX\n", addr); #endif if (addr < rom->mapping.base) - return 0xff; + return 0xff; if (addr >= (rom->mapping.base + rom->sz)) - return 0xff; - return(rom->rom[(addr - rom->mapping.base) & rom->mask]); + return 0xff; + return (rom->rom[(addr - rom->mapping.base) & rom->mask]); } - uint16_t rom_readw(uint32_t addr, void *priv) { - rom_t *rom = (rom_t *)priv; + rom_t *rom = (rom_t *) priv; #ifdef ROM_TRACE - if (rom->mapping.base==ROM_TRACE) - rom_log("ROM: read word from BIOS at %06lX\n", addr); + if (rom->mapping.base == ROM_TRACE) + rom_log("ROM: read word from BIOS at %06lX\n", addr); #endif if (addr < (rom->mapping.base - 1)) - return 0xffff; + return 0xffff; if (addr >= (rom->mapping.base + rom->sz)) - return 0xffff; - return(*(uint16_t *)&rom->rom[(addr - rom->mapping.base) & rom->mask]); + return 0xffff; + return (*(uint16_t *) &rom->rom[(addr - rom->mapping.base) & rom->mask]); } - uint32_t rom_readl(uint32_t addr, void *priv) { - rom_t *rom = (rom_t *)priv; + rom_t *rom = (rom_t *) priv; #ifdef ROM_TRACE - if (rom->mapping.base==ROM_TRACE) - rom_log("ROM: read long from BIOS at %06lX\n", addr); + if (rom->mapping.base == ROM_TRACE) + rom_log("ROM: read long from BIOS at %06lX\n", addr); #endif if (addr < (rom->mapping.base - 3)) - return 0xffffffff; + return 0xffffffff; if (addr >= (rom->mapping.base + rom->sz)) - return 0xffffffff; - return(*(uint32_t *)&rom->rom[(addr - rom->mapping.base) & rom->mask]); + return 0xffffffff; + return (*(uint32_t *) &rom->rom[(addr - rom->mapping.base) & rom->mask]); } - int -rom_load_linear_oddeven(char *fn, uint32_t addr, int sz, int off, uint8_t *ptr) +rom_load_linear_oddeven(const char *fn, uint32_t addr, int sz, int off, uint8_t *ptr) { - FILE *f = rom_fopen(fn, "rb"); - int i; - - if (f == NULL) { - rom_log("ROM: image '%s' not found\n", fn); - return(0); + FILE *fp = rom_fopen(fn, "rb"); + + if (fp == NULL) { + rom_log("ROM: image '%s' not found\n", fn); + return 0; } /* Make sure we only look at the base-256K offset. */ if (addr >= 0x40000) - addr = 0; + addr = 0; else - addr &= 0x03ffff; + addr &= 0x03ffff; if (ptr != NULL) { - if (fseek(f, off, SEEK_SET) == -1) - fatal("rom_load_linear(): Error seeking to the beginning of the file\n"); - for (i = 0; i < (sz >> 1); i++) { - if (fread(ptr + (addr + (i << 1)), 1, 1, f) != 1) - fatal("rom_load_linear(): Error reading even data\n"); - } - for (i = 0; i < (sz >> 1); i++) { - if (fread(ptr + (addr + (i << 1) + 1), 1, 1, f) != 1) - fatal("rom_load_linear(): Error reading od data\n"); - } + if (fseek(fp, off, SEEK_SET) == -1) + fatal("rom_load_linear(): Error seeking to the beginning of the file\n"); + for (int i = 0; i < (sz >> 1); i++) { + if (fread(ptr + (addr + (i << 1)), 1, 1, fp) != 1) + fatal("rom_load_linear(): Error reading even data\n"); + } + for (int i = 0; i < (sz >> 1); i++) { + if (fread(ptr + (addr + (i << 1) + 1), 1, 1, fp) != 1) + fatal("rom_load_linear(): Error reading od data\n"); + } } - (void)fclose(f); + (void) fclose(fp); - return(1); + return 1; } - /* Load a ROM BIOS from its chips, interleaved mode. */ int -rom_load_linear(char *fn, uint32_t addr, int sz, int off, uint8_t *ptr) +rom_load_linear(const char *fn, uint32_t addr, int sz, int off, uint8_t *ptr) { - FILE *f = rom_fopen(fn, "rb"); - - if (f == NULL) { - rom_log("ROM: image '%s' not found\n", fn); - return(0); + FILE *fp = rom_fopen(fn, "rb"); + + if (fp == NULL) { + rom_log("ROM: image '%s' not found\n", fn); + return 0; } /* Make sure we only look at the base-256K offset. */ if (addr >= 0x40000) - addr = 0; + addr = 0; else - addr &= 0x03ffff; + addr &= 0x03ffff; if (ptr != NULL) { - if (fseek(f, off, SEEK_SET) == -1) - fatal("rom_load_linear(): Error seeking to the beginning of the file\n"); - if (fread(ptr+addr, 1, sz, f) > sz) - fatal("rom_load_linear(): Error reading data\n"); + if (fseek(fp, off, SEEK_SET) == -1) + fatal("rom_load_linear(): Error seeking to the beginning of the file\n"); + if (fread(ptr + addr, 1, sz, fp) > sz) + fatal("rom_load_linear(): Error reading data\n"); } - (void)fclose(f); + (void) fclose(fp); - return(1); + return 1; } - /* Load a ROM BIOS from its chips, linear mode with high bit flipped. */ int -rom_load_linear_inverted(char *fn, uint32_t addr, int sz, int off, uint8_t *ptr) +rom_load_linear_inverted(const char *fn, uint32_t addr, int sz, int off, uint8_t *ptr) { - FILE *f = rom_fopen(fn, "rb"); - - if (f == NULL) { - rom_log("ROM: image '%s' not found\n", fn); - return(0); + FILE *fp = rom_fopen(fn, "rb"); + + if (fp == NULL) { + rom_log("ROM: image '%s' not found\n", fn); + return 0; } /* Make sure we only look at the base-256K offset. */ - if (addr >= 0x40000) - { - addr = 0; - } - else - { - addr &= 0x03ffff; + if (addr >= 0x40000) { + addr = 0; + } else { + addr &= 0x03ffff; } - (void)fseek(f, 0, SEEK_END); - if (ftell(f) < sz) { - (void)fclose(f); - return(0); + (void) fseek(fp, 0, SEEK_END); + if (ftell(fp) < sz) { + (void) fclose(fp); + return 0; } if (ptr != NULL) { - if (fseek(f, off, SEEK_SET) == -1) - fatal("rom_load_linear_inverted(): Error seeking to the beginning of the file\n"); - if (fread(ptr+addr+0x10000, 1, sz >> 1, f) > (sz >> 1)) - fatal("rom_load_linear_inverted(): Error reading the upper half of the data\n"); - if (fread(ptr+addr, sz >> 1, 1, f) > (sz >> 1)) - fatal("rom_load_linear_inverted(): Error reading the lower half of the data\n"); + if (fseek(fp, off, SEEK_SET) == -1) + fatal("rom_load_linear_inverted(): Error seeking to the beginning of the file\n"); + if (fread(ptr + addr + 0x10000, 1, sz >> 1, fp) > (sz >> 1)) + fatal("rom_load_linear_inverted(): Error reading the upper half of the data\n"); + if (fread(ptr + addr, sz >> 1, 1, fp) > (sz >> 1)) + fatal("rom_load_linear_inverted(): Error reading the lower half of the data\n"); } - (void)fclose(f); + (void) fclose(fp); - return(1); + return 1; } - /* Load a ROM BIOS from its chips, interleaved mode. */ int -rom_load_interleaved(char *fnl, char *fnh, uint32_t addr, int sz, int off, uint8_t *ptr) +rom_load_interleaved(const char *fnl, const char *fnh, uint32_t addr, int sz, int off, uint8_t *ptr) { - FILE *fl = rom_fopen(fnl, "rb"); - FILE *fh = rom_fopen(fnh, "rb"); - int c; + FILE *fpl = rom_fopen(fnl, "rb"); + FILE *fph = rom_fopen(fnh, "rb"); - if (fl == NULL || fh == NULL) { - if (fl == NULL) rom_log("ROM: image '%s' not found\n", fnl); - else (void)fclose(fl); - if (fh == NULL) rom_log("ROM: image '%s' not found\n", fnh); - else (void)fclose(fh); + if (fpl == NULL || fph == NULL) { + if (fpl == NULL) + rom_log("ROM: image '%s' not found\n", fnl); + else + (void) fclose(fpl); + if (fph == NULL) + rom_log("ROM: image '%s' not found\n", fnh); + else + (void) fclose(fph); - return(0); + return 0; } /* Make sure we only look at the base-256K offset. */ - if (addr >= 0x40000) - { - addr = 0; - } - else - { - addr &= 0x03ffff; + if (addr >= 0x40000) { + addr = 0; + } else { + addr &= 0x03ffff; } if (ptr != NULL) { - (void)fseek(fl, off, SEEK_SET); - (void)fseek(fh, off, SEEK_SET); - for (c=0; c 0x4000; 0x4000 -> 0x4000; 0x6000 -> 0x8000 */ if (up && (n % MEM_GRANULARITY_SIZE)) - temp_n += MEM_GRANULARITY_SIZE; + temp_n += MEM_GRANULARITY_SIZE; return temp_n; } - - static uint8_t * rom_reset(uint32_t addr, int sz) { biosaddr = bios_normalize(addr, 0); biosmask = bios_normalize(sz, 1) - 1; if ((biosaddr + biosmask) > 0x000fffff) - biosaddr = 0x000fffff - biosmask; + biosaddr = 0x000fffff - biosmask; rom_log("Load BIOS: %i bytes at %08X-%08X\n", biosmask + 1, biosaddr, biosaddr + biosmask); /* If not done yet, allocate a 128KB buffer for the BIOS ROM. */ if (rom != NULL) { - rom_log("ROM allocated, freeing...\n"); - free(rom); - rom = NULL; + rom_log("ROM allocated, freeing...\n"); + free(rom); + rom = NULL; } rom_log("Allocating ROM...\n"); - rom = (uint8_t *)malloc(biosmask + 1); + rom = (uint8_t *) malloc(biosmask + 1); rom_log("Filling ROM with FF's...\n"); memset(rom, 0xff, biosmask + 1); return rom; } - uint8_t -bios_read(uint32_t addr, void *priv) +bios_read(uint32_t addr, UNUSED(void *priv)) { uint8_t ret = 0xff; addr &= 0x000fffff; if ((addr >= biosaddr) && (addr <= (biosaddr + biosmask))) - ret = rom[addr - biosaddr]; + ret = rom[addr - biosaddr]; return ret; } - uint16_t -bios_readw(uint32_t addr, void *priv) +bios_readw(uint32_t addr, UNUSED(void *priv)) { uint16_t ret = 0xffff; addr &= 0x000fffff; if ((addr >= biosaddr) && (addr <= (biosaddr + biosmask))) - ret = *(uint16_t *)&rom[addr - biosaddr]; + ret = *(uint16_t *) &rom[addr - biosaddr]; return ret; } - uint32_t -bios_readl(uint32_t addr, void *priv) +bios_readl(uint32_t addr, UNUSED(void *priv)) { uint32_t ret = 0xffffffff; addr &= 0x000fffff; if ((addr >= biosaddr) && (addr <= (biosaddr + biosmask))) - ret = *(uint32_t *)&rom[addr - biosaddr]; + ret = *(uint32_t *) &rom[addr - biosaddr]; return ret; } - static void bios_add(void) { - int temp_cpu_type, temp_cpu_16bitbus = 1; + int temp_cpu_type; + int temp_cpu_16bitbus = 1; int temp_is286 = 0; + int temp_is6117 = 0; - if (/*AT && */cpu_s) { - temp_cpu_type = cpu_s->cpu_type; - temp_cpu_16bitbus = (temp_cpu_type == CPU_286 || temp_cpu_type == CPU_386SX || temp_cpu_type == CPU_486SLC || temp_cpu_type == CPU_IBM386SLC || temp_cpu_type == CPU_IBM486SLC ); - temp_is286 = (temp_cpu_type >= CPU_286); + if (/*AT && */ cpu_s) { + temp_cpu_type = cpu_s->cpu_type; + temp_cpu_16bitbus = (temp_cpu_type == CPU_286 || temp_cpu_type == CPU_386SX || temp_cpu_type == CPU_486SLC || temp_cpu_type == CPU_IBM386SLC || temp_cpu_type == CPU_IBM486SLC); + temp_is286 = (temp_cpu_type >= CPU_286); + temp_is6117 = !strcmp(cpu_f->manufacturer, "ALi"); } if (biosmask > 0x1ffff) { - /* 256k+ BIOS'es only have low mappings at E0000-FFFFF. */ - mem_mapping_add(&bios_mapping, 0xe0000, 0x20000, - bios_read,bios_readw,bios_readl, - NULL,NULL,NULL, - &rom[0x20000], MEM_MAPPING_EXTERNAL|MEM_MAPPING_ROM|MEM_MAPPING_ROMCS, 0); + /* 256k+ BIOS'es only have low mappings at E0000-FFFFF. */ + mem_mapping_add(&bios_mapping, 0xe0000, 0x20000, + bios_read, bios_readw, bios_readl, + NULL, NULL, NULL, + &rom[biosmask + 1 - 0x20000], MEM_MAPPING_EXTERNAL | MEM_MAPPING_ROM | MEM_MAPPING_ROMCS, 0); - mem_set_mem_state_both(0x0e0000, 0x20000, - MEM_READ_ROMCS | MEM_WRITE_ROMCS); + mem_set_mem_state_both(0x0e0000, 0x20000, + MEM_READ_ROMCS | MEM_WRITE_ROMCS); } else { - mem_mapping_add(&bios_mapping, biosaddr, biosmask + 1, - bios_read,bios_readw,bios_readl, - NULL,NULL,NULL, - rom, MEM_MAPPING_EXTERNAL|MEM_MAPPING_ROM|MEM_MAPPING_ROMCS, 0); + mem_mapping_add(&bios_mapping, biosaddr, biosmask + 1, + bios_read, bios_readw, bios_readl, + NULL, NULL, NULL, + rom, MEM_MAPPING_EXTERNAL | MEM_MAPPING_ROM | MEM_MAPPING_ROMCS, 0); - mem_set_mem_state_both(biosaddr, biosmask + 1, - MEM_READ_ROMCS | MEM_WRITE_ROMCS); + mem_set_mem_state_both(biosaddr, biosmask + 1, + MEM_READ_ROMCS | MEM_WRITE_ROMCS); } - if (temp_is286) { - mem_mapping_add(&bios_high_mapping, biosaddr | (temp_cpu_16bitbus ? 0x00f00000 : 0xfff00000), biosmask + 1, - bios_read,bios_readw,bios_readl, - NULL,NULL,NULL, - rom, MEM_MAPPING_EXTERNAL|MEM_MAPPING_ROM|MEM_MAPPING_ROMCS, 0); + if (temp_is6117) { + mem_mapping_add(&bios_high_mapping, biosaddr | 0x03f00000, biosmask + 1, + bios_read, bios_readw, bios_readl, + NULL, NULL, NULL, + rom, MEM_MAPPING_EXTERNAL | MEM_MAPPING_ROM | MEM_MAPPING_ROMCS, 0); - mem_set_mem_state_both(biosaddr | (temp_cpu_16bitbus ? 0x00f00000 : 0xfff00000), biosmask + 1, - MEM_READ_ROMCS | MEM_WRITE_ROMCS); + mem_set_mem_state_both(biosaddr | 0x03f00000, biosmask + 1, + MEM_READ_ROMCS | MEM_WRITE_ROMCS); + } else if (temp_is286) { + mem_mapping_add(&bios_high_mapping, biosaddr | (temp_cpu_16bitbus ? 0x00f00000 : 0xfff00000), biosmask + 1, + bios_read, bios_readw, bios_readl, + NULL, NULL, NULL, + rom, MEM_MAPPING_EXTERNAL | MEM_MAPPING_ROM | MEM_MAPPING_ROMCS, 0); + + mem_set_mem_state_both(biosaddr | (temp_cpu_16bitbus ? 0x00f00000 : 0xfff00000), biosmask + 1, + MEM_READ_ROMCS | MEM_WRITE_ROMCS); } } - /* These four are for loading the BIOS. */ int -bios_load(char *fn1, char *fn2, uint32_t addr, int sz, int off, int flags) +bios_load(const char *fn1, const char *fn2, uint32_t addr, int sz, int off, int flags) { - uint8_t ret = 0; + uint8_t ret = 0; uint8_t *ptr = NULL; - int i, old_sz = sz; + int old_sz = sz; /* - f0000, 65536 = prepare 64k rom starting at f0000, load 64k bios at 0000 - fe000, 65536 = prepare 64k rom starting at f0000, load 8k bios at e000 - fe000, 49152 = prepare 48k rom starting at f4000, load 8k bios at a000 - fe000, 8192 = prepare 16k rom starting at fc000, load 8k bios at 2000 + f0000, 65536 = prepare 64k rom starting at f0000, load 64k bios at 0000 + fe000, 65536 = prepare 64k rom starting at f0000, load 8k bios at e000 + fe000, 49152 = prepare 48k rom starting at f4000, load 8k bios at a000 + fe000, 8192 = prepare 16k rom starting at fc000, load 8k bios at 2000 */ if (!bios_only) - ptr = (flags & FLAG_AUX) ? rom : rom_reset(addr, sz); + ptr = (flags & FLAG_AUX) ? rom : rom_reset(addr, sz); if (!(flags & FLAG_AUX) && ((addr + sz) > 0x00100000)) - sz = 0x00100000 - addr; + sz = 0x00100000 - addr; #ifdef ENABLE_ROM_LOG if (!bios_only) - rom_log("%sing %i bytes of %sBIOS starting with ptr[%08X] (ptr = %08X)\n", (bios_only) ? "Check" : "Load", sz, (flags & FLAG_AUX) ? "auxiliary " : "", addr - biosaddr, ptr); + rom_log("%sing %i bytes of %sBIOS starting with ptr[%08X] (ptr = %08X)\n", (bios_only) ? "Check" : "Load", sz, (flags & FLAG_AUX) ? "auxiliary " : "", addr - biosaddr, ptr); #endif if (flags & FLAG_INT) - ret = rom_load_interleaved(fn1, fn2, addr - biosaddr, sz, off, ptr); + ret = rom_load_interleaved(fn1, fn2, addr - biosaddr, sz, off, ptr); else { - if (flags & FLAG_INV) - ret = rom_load_linear_inverted(fn1, addr - biosaddr, sz, off, ptr); - else - ret = rom_load_linear(fn1, addr - biosaddr, sz, off, ptr); + if (flags & FLAG_INV) + ret = rom_load_linear_inverted(fn1, addr - biosaddr, sz, off, ptr); + else + ret = rom_load_linear(fn1, addr - biosaddr, sz, off, ptr); } if (!bios_only && (flags & FLAG_REP) && (old_sz >= 65536) && (sz < old_sz)) { - old_sz /= sz; - for (i = 0; i < (old_sz - 1); i++) { - rom_log("Copying ptr[%08X] to ptr[%08X]\n", addr - biosaddr, i * sz); - memcpy(&(ptr[i * sz]), &(ptr[addr - biosaddr]), sz); - } + old_sz /= sz; + for (int i = 0; i < (old_sz - 1); i++) { + rom_log("Copying ptr[%08X] to ptr[%08X]\n", addr - biosaddr, i * sz); + memcpy(&(ptr[i * sz]), &(ptr[addr - biosaddr]), sz); + } } if (!bios_only && ret && !(flags & FLAG_AUX)) - bios_add(); + bios_add(); return ret; } - int -bios_load_linear_combined(char *fn1, char *fn2, int sz, int off) +bios_load_linear_combined(const char *fn1, const char *fn2, int sz, UNUSED(int off)) { uint8_t ret = 0; @@ -516,9 +533,8 @@ bios_load_linear_combined(char *fn1, char *fn2, int sz, int off) return ret; } - int -bios_load_linear_combined2(char *fn1, char *fn2, char *fn3, char *fn4, char *fn5, int sz, int off) +bios_load_linear_combined2(const char *fn1, const char *fn2, const char *fn3, const char *fn4, const char *fn5, int sz, int off) { uint8_t ret = 0; @@ -527,14 +543,13 @@ bios_load_linear_combined2(char *fn1, char *fn2, char *fn3, char *fn4, char *fn5 ret &= bios_load_aux_linear(fn2, 0x000c0000, 65536, off); ret &= bios_load_aux_linear(fn4, 0x000e0000, sz - 196608, off); if (fn5 != NULL) - ret &= bios_load_aux_linear(fn5, 0x000ec000, 16384, 0); + ret &= bios_load_aux_linear(fn5, 0x000ec000, 16384, 0); return ret; } - int -bios_load_linear_combined2_ex(char *fn1, char *fn2, char *fn3, char *fn4, char *fn5, int sz, int off) +bios_load_linear_combined2_ex(const char *fn1, const char *fn2, const char *fn3, const char *fn4, const char *fn5, int sz, int off) { uint8_t ret = 0; @@ -543,14 +558,42 @@ bios_load_linear_combined2_ex(char *fn1, char *fn2, char *fn3, char *fn4, char * ret &= bios_load_aux_linear(fn2, 0x000d0000, 65536, off); ret &= bios_load_aux_linear(fn4, 0x000f0000, sz - 196608, off); if (fn5 != NULL) - ret &= bios_load_aux_linear(fn5, 0x000fc000, 16384, 0); + ret &= bios_load_aux_linear(fn5, 0x000fc000, 16384, 0); return ret; } +int +rom_init(rom_t *rom, const char *fn, uint32_t addr, int sz, int mask, int off, uint32_t flags) +{ + rom_log("rom_init(%08X, %s, %08X, %08X, %08X, %08X, %08X)\n", rom, fn, addr, sz, mask, off, flags); + + /* Allocate a buffer for the image. */ + rom->rom = malloc(sz); + memset(rom->rom, 0xff, sz); + + /* Load the image file into the buffer. */ + if (!rom_load_linear(fn, addr, sz, off, rom->rom)) { + /* Nope.. clean up. */ + free(rom->rom); + rom->rom = NULL; + return (-1); + } + + rom->sz = sz; + rom->mask = mask; + + mem_mapping_add(&rom->mapping, + addr, sz, + rom_read, rom_readw, rom_readl, + NULL, NULL, NULL, + rom->rom, flags | MEM_MAPPING_ROM_WS, rom); + + return 0; +} int -rom_init(rom_t *rom, char *fn, uint32_t addr, int sz, int mask, int off, uint32_t flags) +rom_init_oddeven(rom_t *rom, const char *fn, uint32_t addr, int sz, int mask, int off, uint32_t flags) { rom_log("rom_init(%08X, %08X, %08X, %08X, %08X, %08X, %08X)\n", rom, fn, addr, sz, mask, off, flags); @@ -559,79 +602,48 @@ rom_init(rom_t *rom, char *fn, uint32_t addr, int sz, int mask, int off, uint32_ memset(rom->rom, 0xff, sz); /* Load the image file into the buffer. */ - if (! rom_load_linear(fn, addr, sz, off, rom->rom)) { - /* Nope.. clean up. */ - free(rom->rom); - rom->rom = NULL; - return(-1); + if (!rom_load_linear_oddeven(fn, addr, sz, off, rom->rom)) { + /* Nope.. clean up. */ + free(rom->rom); + rom->rom = NULL; + return (-1); } - rom->sz = sz; + rom->sz = sz; rom->mask = mask; mem_mapping_add(&rom->mapping, - addr, sz, - rom_read, rom_readw, rom_readl, - NULL, NULL, NULL, - rom->rom, flags | MEM_MAPPING_ROM_WS, rom); + addr, sz, + rom_read, rom_readw, rom_readl, + NULL, NULL, NULL, + rom->rom, flags | MEM_MAPPING_ROM_WS, rom); - return(0); + return 0; } - int -rom_init_oddeven(rom_t *rom, char *fn, uint32_t addr, int sz, int mask, int off, uint32_t flags) -{ - rom_log("rom_init(%08X, %08X, %08X, %08X, %08X, %08X, %08X)\n", rom, fn, addr, sz, mask, off, flags); - - /* Allocate a buffer for the image. */ - rom->rom = malloc(sz); - memset(rom->rom, 0xff, sz); - - /* Load the image file into the buffer. */ - if (! rom_load_linear_oddeven(fn, addr, sz, off, rom->rom)) { - /* Nope.. clean up. */ - free(rom->rom); - rom->rom = NULL; - return(-1); - } - - rom->sz = sz; - rom->mask = mask; - - mem_mapping_add(&rom->mapping, - addr, sz, - rom_read, rom_readw, rom_readl, - NULL, NULL, NULL, - rom->rom, flags | MEM_MAPPING_ROM, rom); - - return(0); -} - - -int -rom_init_interleaved(rom_t *rom, char *fnl, char *fnh, uint32_t addr, int sz, int mask, int off, uint32_t flags) +rom_init_interleaved(rom_t *rom, const char *fnl, const char *fnh, uint32_t addr, int sz, int mask, int off, uint32_t flags) { /* Allocate a buffer for the image. */ rom->rom = malloc(sz); memset(rom->rom, 0xff, sz); /* Load the image file into the buffer. */ - if (! rom_load_interleaved(fnl, fnh, addr, sz, off, rom->rom)) { - /* Nope.. clean up. */ - free(rom->rom); - rom->rom = NULL; - return(-1); + if (!rom_load_interleaved(fnl, fnh, addr, sz, off, rom->rom)) { + /* Nope.. clean up. */ + free(rom->rom); + rom->rom = NULL; + return (-1); } - rom->sz = sz; + rom->sz = sz; rom->mask = mask; mem_mapping_add(&rom->mapping, - addr, sz, - rom_read, rom_readw, rom_readl, - NULL, NULL, NULL, - rom->rom, flags | MEM_MAPPING_ROM, rom); + addr, sz, + rom_read, rom_readw, rom_readl, + NULL, NULL, NULL, + rom->rom, flags | MEM_MAPPING_ROM_WS, rom); - return(0); + return 0; } diff --git a/src/mem/row.c b/src/mem/row.c new file mode 100644 index 000000000..ccd0325a4 --- /dev/null +++ b/src/mem/row.c @@ -0,0 +1,348 @@ +/* + * 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. + * + * DRAM row handling. + * + * Authors: Miran Grca, + * + * Copyright 2016-2020 Miran Grca. + */ +#include +#include +#include +#include +#include +#include +#include +#define HAVE_STDARG_H +#include <86box/86box.h> +#include "cpu.h" +#include "x86_ops.h" +#include "x86.h" +#include <86box/config.h> +#include <86box/device.h> +#include <86box/io.h> +#include <86box/mem.h> +#include <86box/spd.h> +#include <86box/row.h> +#include <86box/plat_unused.h> + +/* 0 1 2 3 4 5 6 7 */ +static uint8_t rows_num; +static uint8_t rows_default; +static uint8_t rows_bits; +static uint32_t row_unit; +static uint8_t drb_defaults[16]; +static row_t *rows; + + +static uint8_t +row_read(uint32_t addr, void *priv) +{ + const row_t *dev = (row_t *) priv; + uint32_t new_addr = ((addr - dev->host_base) & dev->ram_mask) + dev->ram_base; + + addreadlookup(mem_logical_addr, new_addr); + + return dev->buf[new_addr]; +} + + +static uint16_t +row_readw(uint32_t addr, void *priv) +{ + row_t *dev = (row_t *) priv; + uint32_t new_addr = ((addr - dev->host_base) & dev->ram_mask) + dev->ram_base; + + addreadlookup(mem_logical_addr, new_addr); + + return *(uint16_t *) &(dev->buf[new_addr]); +} + + +static uint32_t +row_readl(uint32_t addr, void *priv) +{ + row_t *dev = (row_t *) priv; + uint32_t new_addr = ((addr - dev->host_base) & dev->ram_mask) + dev->ram_base; + + addreadlookup(mem_logical_addr, new_addr); + + return *(uint32_t *) &(dev->buf[new_addr]); +} + + +static void +row_write(uint32_t addr, uint8_t val, void *priv) +{ + const row_t *dev = (row_t *) priv; + uint32_t new_addr = ((addr - dev->host_base) & dev->ram_mask) + dev->ram_base; + + addwritelookup(mem_logical_addr, new_addr); + mem_write_ramb_page(new_addr, val, &pages[addr >> 12]); +} + + +static void +row_writew(uint32_t addr, uint16_t val, void *priv) +{ + const row_t *dev = (row_t *) priv; + uint32_t new_addr = ((addr - dev->host_base) & dev->ram_mask) + dev->ram_base; + + addwritelookup(mem_logical_addr, new_addr); + mem_write_ramw_page(new_addr, val, &pages[addr >> 12]); +} + + +static void +row_writel(uint32_t addr, uint32_t val, void *priv) +{ + const row_t *dev = (row_t *) priv; + uint32_t new_addr = ((addr - dev->host_base) & dev->ram_mask) + dev->ram_base; + + addwritelookup(mem_logical_addr, new_addr); + mem_write_raml_page(new_addr, val, &pages[addr >> 12]); +} + + +void +row_allocate(uint8_t row_id, uint8_t set) +{ + uint32_t offset; + + /* Do nothing if size is either zero or invalid. */ + if ((rows[row_id].host_size == 0x00000000) || (rows[row_id].host_size == 0xffffffff)) + return; + + if (rows[row_id].ram_size == 0x00000000) + return; + + for (uint32_t c = (rows[row_id].host_base >> 12); c < ((rows[row_id].host_base + rows[row_id].host_size) >> 12); c++) { + offset = c - (rows[row_id].host_base >> 12); + + pages[c].mem = set ? (rows[row_id].buf + rows[row_id].ram_base + ((offset << 12) & rows[row_id].ram_mask)) : page_ff; + pages[c].write_b = set ? mem_write_ramb_page : NULL; + pages[c].write_w = set ? mem_write_ramw_page : NULL; + pages[c].write_l = set ? mem_write_raml_page : NULL; +#ifdef USE_NEW_DYNAREC + pages[c].evict_prev = EVICT_NOT_IN_LIST; + pages[c].byte_dirty_mask = &byte_dirty_mask[offset * 64]; + pages[c].byte_code_present_mask = &byte_code_present_mask[offset * 64]; +#endif + } + + if (rows[row_id].host_base >= 0x00100000) { + mem_set_mem_state_both(rows[row_id].host_base, rows[row_id].host_base + rows[row_id].host_size, + set ? (MEM_READ_INTERNAL | MEM_WRITE_INTERNAL) : (MEM_READ_EXTERNAL | MEM_WRITE_EXTERNAL)); + } else { + if (0x000a0000 > rows[row_id].host_base) { + mem_set_mem_state_both(rows[row_id].host_base, 0x000a0000 - rows[row_id].host_base, + set ? (MEM_READ_INTERNAL | MEM_WRITE_INTERNAL) : (MEM_READ_EXTERNAL | MEM_WRITE_EXTERNAL)); + } + if ((rows[row_id].host_base + rows[row_id].host_size) > 0x00100000) { + mem_set_mem_state_both(0x00100000, (rows[row_id].host_base + rows[row_id].host_size) - 0x00100000, + set ? (MEM_READ_INTERNAL | MEM_WRITE_INTERNAL) : (MEM_READ_EXTERNAL | MEM_WRITE_EXTERNAL)); + } + } + + if (set) { + mem_mapping_set_addr(&rows[row_id].mapping, rows[row_id].host_base, rows[row_id].host_size); + mem_mapping_set_exec(&rows[row_id].mapping, rows[row_id].buf + rows[row_id].ram_base); + mem_mapping_set_mask(&rows[row_id].mapping, rows[row_id].ram_mask); + if ((rows[row_id].host_base == rows[row_id].ram_base) && (rows[row_id].host_size == rows[row_id].ram_size)) { +#if (defined __amd64__ || defined _M_X64 || defined __aarch64__ || defined _M_ARM64) + mem_mapping_set_handler(&rows[row_id].mapping, mem_read_ram,mem_read_ramw,mem_read_raml, + mem_write_ram,mem_write_ramw,mem_write_raml); +#else + if (rows[row_id].buf == ram2) { + mem_mapping_set_handler(&rows[row_id].mapping, mem_read_ram_2gb,mem_read_ram_2gbw,mem_read_ram_2gbl, + mem_write_ram,mem_write_ramw,mem_write_raml); + } else { + mem_mapping_set_handler(&rows[row_id].mapping, mem_read_ram,mem_read_ramw,mem_read_raml, + mem_write_ram,mem_write_ramw,mem_write_raml); + } +#endif + } else { + mem_mapping_set_handler(&rows[row_id].mapping, row_read, row_readw, row_readl, + row_write, row_writew, row_writel); + } + } else + mem_mapping_disable(&rows[row_id].mapping); +} + + +void +row_disable(uint8_t row_id) +{ + row_allocate(row_id, 0); +} + + +void +row_set_boundary(uint8_t row_id, uint32_t boundary) +{ + if (row_id >= rows_num) + return; + + boundary &= ((1 << rows_bits) - 1); + + rows[row_id].host_size = boundary * row_unit; + if (row_id == 0) + rows[row_id].host_base = 0x00000000; + else { + rows[row_id].host_base = rows[row_id - 1].boundary * row_unit; + if (rows[row_id - 1].boundary > boundary) + rows[row_id].host_size = 0x00000000; + else + rows[row_id].host_size -= rows[row_id].host_base; + } + + rows[row_id].boundary = boundary; + + row_allocate(row_id, 1); +} + + +void +row_reset(UNUSED(void *priv)) +{ + uint32_t boundary; + uint32_t shift; + + for (int8_t i = (rows_num - 1); i >= 0; i--) + row_disable(i); + + for (uint8_t i = 0; i < rows_num; i++) { + shift = (i & 1) << 2; + boundary = ((uint32_t) drb_defaults[i]) + (((((uint32_t) drb_defaults[(i >> 1) + 8]) >> shift) & 0xf) << 8); + row_set_boundary(i, boundary); + } +} + + +void +row_close(UNUSED(void *priv)) +{ + free(rows); + rows = NULL; +} + + +void * +row_init(const device_t *info) +{ + uint32_t cur_drb = 0; + uint32_t cur_drbe = 0; + uint32_t last_drb = 0; + uint32_t last_drbe = 0; + uint8_t phys_drbs[16]; + int i; + int max = info->local & 0xff; + uint32_t shift; + uint32_t drb; + uint32_t boundary; + uint32_t mask; + row_t *new_rows = NULL; + + rows_bits = ((info->local >> 24) & 0xff); + mask = (1 << rows_bits) - 1; + row_unit = ((info->local >> 8) & 0xff); + memset(phys_drbs, 0x00, 16); + spd_write_drbs(phys_drbs, 0x00, max, row_unit); + row_unit <<= 20; + rows_default = (info->local >> 16) & 0xff; + memset(drb_defaults, 0x00, 16); + for (i = 0; i < 8; i++) + drb_defaults[i] = rows_default; + + new_rows = calloc(max + 1, sizeof(row_t)); + rows_num = max + 1; + + rows = new_rows; + + mem_mapping_disable(&ram_low_mapping); + mem_mapping_disable(&ram_mid_mapping); + mem_mapping_disable(&ram_high_mapping); +#if (!(defined __amd64__ || defined _M_X64 || defined __aarch64__ || defined _M_ARM64)) + if (mem_size > 1048576) + mem_mapping_disable(&ram_2gb_mapping); +#endif + + for (uint32_t c = 0; c < pages_sz; c++) { + pages[c].mem = page_ff; + pages[c].write_b = NULL; + pages[c].write_w = NULL; + pages[c].write_l = NULL; +#ifdef USE_NEW_DYNAREC + pages[c].evict_prev = EVICT_NOT_IN_LIST; + pages[c].byte_dirty_mask = &byte_dirty_mask[c * 64]; + pages[c].byte_code_present_mask = &byte_code_present_mask[c * 64]; +#endif + } + + /* Set all memory space above the default allocated area to external. */ + boundary = ((uint32_t) rows_default) * row_unit; + mem_set_mem_state_both(boundary, (mem_size << 10) - boundary, MEM_READ_EXTERNAL | MEM_WRITE_EXTERNAL); + + for (i = 0; i <= max; i++) { + cur_drb = phys_drbs[i]; + cur_drbe = phys_drbs[(i >> 1) + 8]; + + shift = (i & 1) << 2; + drb = (cur_drb & mask) + (((cur_drbe >> shift) & 0x03) << 8); + rows[i].ram_size = drb * row_unit; + + shift = ((i - 1) & 1) << 2; + drb = (last_drb & mask) + (((last_drbe >> shift) & 0x03) << 8); + rows[i].ram_base = drb * row_unit; + rows[i].ram_size -= rows[i].ram_base; + + rows[i].buf = ram; +#if (!(defined __amd64__ || defined _M_X64 || defined __aarch64__ || defined _M_ARM64)) + if (rows[i].ram_base >= (1 << 30)) { + rows[i].ram_base -= (1 << 30); + rows[i].buf = ram2; + } +#endif + + rows[i].ram_mask = rows[i].ram_size - 1; + + mem_mapping_add(&rows[i].mapping, rows[i].ram_base, rows[i].ram_size, + row_read, row_readw, row_readl, + row_write, row_writew, row_writel, + rows[i].buf + rows[i].ram_base, MEM_MAPPING_INTERNAL, &(rows[i])); + mem_mapping_disable(&rows[i].mapping); + + shift = (i & 1) << 2; + boundary = ((uint32_t) drb_defaults[i]) + ((((uint32_t) drb_defaults[(i >> 1) + 8]) >> shift) << 8); + row_set_boundary(i, boundary); + + last_drb = cur_drb; + last_drbe = cur_drbe; + } + + flushmmucache(); + + return new_rows; +} + + +/* NOTE: NOT const, so that we can patch it at init. */ +device_t row_device = { + .name = "DRAM Rows", + .internal_name = "dram_rows", + .flags = DEVICE_AT, + .local = 0x0000, + .init = row_init, + .close = row_close, + .reset = row_reset, + { .available = NULL }, + .speed_changed = NULL, + .force_redraw = NULL, + .config = NULL +}; diff --git a/src/mem/smram.c b/src/mem/smram.c index 8b1f9fd40..0532e2dd5 100644 --- a/src/mem/smram.c +++ b/src/mem/smram.c @@ -1,16 +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. + * 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. + * This file is part of the 86Box distribution. * - * SMRAM handling. + * SMRAM handling. * - * Authors: Miran Grca, + * Authors: Miran Grca, * - * Copyright 2016-2020 Miran Grca. + * Copyright 2016-2020 Miran Grca. */ #include #include @@ -29,190 +29,181 @@ #include <86box/mem.h> #include <86box/smram.h> +static smram_t *base_smram; +static smram_t *last_smram; -static smram_t *base_smram, *last_smram; - -static uint8_t use_separate_smram = 0; -static uint8_t smram[0x40000]; - +static uint8_t use_separate_smram = 0; +static uint8_t smram[0x40000]; #ifdef ENABLE_SMRAM_LOG int smram_do_log = ENABLE_SMRAM_LOG; - static void smram_log(const char *fmt, ...) { va_list ap; if (smram_do_log) { - va_start(ap, fmt); - pclog_ex(fmt, ap); - va_end(ap); + va_start(ap, fmt); + pclog_ex(fmt, ap); + va_end(ap); } } #else -#define smram_log(fmt, ...) +# define smram_log(fmt, ...) #endif - static uint8_t smram_read(uint32_t addr, void *priv) { - smram_t *dev = (smram_t *) priv; - uint32_t new_addr = addr - dev->host_base + dev->ram_base; + const smram_t *dev = (smram_t *) priv; + uint32_t new_addr = addr - dev->host_base + dev->ram_base; if (new_addr >= (1 << 30)) - return mem_read_ram_2gb(new_addr, priv); + return mem_read_ram_2gb(new_addr, priv); else if (!use_separate_smram || (new_addr >= 0xa0000)) - return mem_read_ram(new_addr, priv); + return mem_read_ram(new_addr, priv); else - return dev->mapping.exec[addr - dev->host_base]; + return dev->mapping.exec[addr - dev->host_base]; } - static uint16_t smram_readw(uint32_t addr, void *priv) { - smram_t *dev = (smram_t *) priv; + smram_t *dev = (smram_t *) priv; uint32_t new_addr = addr - dev->host_base + dev->ram_base; if (new_addr >= (1 << 30)) - return mem_read_ram_2gbw(new_addr, priv); + return mem_read_ram_2gbw(new_addr, priv); else if (!use_separate_smram || (new_addr >= 0xa0000)) - return mem_read_ramw(new_addr, priv); + return mem_read_ramw(new_addr, priv); else - return *(uint16_t *) &(dev->mapping.exec[addr - dev->host_base]); + return *(uint16_t *) &(dev->mapping.exec[addr - dev->host_base]); } - static uint32_t smram_readl(uint32_t addr, void *priv) { - smram_t *dev = (smram_t *) priv; + smram_t *dev = (smram_t *) priv; uint32_t new_addr = addr - dev->host_base + dev->ram_base; if (new_addr >= (1 << 30)) - return mem_read_ram_2gbl(new_addr, priv); + return mem_read_ram_2gbl(new_addr, priv); else if (!use_separate_smram || (new_addr >= 0xa0000)) - return mem_read_raml(new_addr, priv); + return mem_read_raml(new_addr, priv); else - return *(uint32_t *) &(dev->mapping.exec[addr - dev->host_base]); + return *(uint32_t *) &(dev->mapping.exec[addr - dev->host_base]); } - static void smram_write(uint32_t addr, uint8_t val, void *priv) { - smram_t *dev = (smram_t *) priv; + smram_t *dev = (smram_t *) priv; uint32_t new_addr = addr - dev->host_base + dev->ram_base; if (!use_separate_smram || (new_addr >= 0xa0000)) - mem_write_ram(new_addr, val, priv); + mem_write_ram(new_addr, val, priv); else - dev->mapping.exec[addr - dev->host_base] = val; + dev->mapping.exec[addr - dev->host_base] = val; } - static void smram_writew(uint32_t addr, uint16_t val, void *priv) { - smram_t *dev = (smram_t *) priv; + smram_t *dev = (smram_t *) priv; uint32_t new_addr = addr - dev->host_base + dev->ram_base; if (!use_separate_smram || (new_addr >= 0xa0000)) - mem_write_ramw(new_addr, val, priv); + mem_write_ramw(new_addr, val, priv); else - *(uint16_t *) &(dev->mapping.exec[addr - dev->host_base]) = val; + *(uint16_t *) &(dev->mapping.exec[addr - dev->host_base]) = val; } - static void smram_writel(uint32_t addr, uint32_t val, void *priv) { - smram_t *dev = (smram_t *) priv; + smram_t *dev = (smram_t *) priv; uint32_t new_addr = addr - dev->host_base + dev->ram_base; if (!use_separate_smram || (new_addr >= 0xa0000)) - mem_write_raml(new_addr, val, priv); + mem_write_raml(new_addr, val, priv); else - *(uint32_t *) &(dev->mapping.exec[addr - dev->host_base]) = val; + *(uint32_t *) &(dev->mapping.exec[addr - dev->host_base]) = val; } - /* Make a backup copy of host_base and size of all the SMRAM structs, needed so that if the SMRAM mappings change while in SMM, they will be recalculated on return. */ void smram_backup_all(void) { - smram_t *temp_smram = base_smram, *next; + smram_t *temp_smram = base_smram; + smram_t *next; while (temp_smram != NULL) { - temp_smram->old_host_base = temp_smram->host_base; - temp_smram->old_size = temp_smram->size; + temp_smram->old_host_base = temp_smram->host_base; + temp_smram->old_size = temp_smram->size; - next = temp_smram->next; - temp_smram = next; + next = temp_smram->next; + temp_smram = next; } } - /* Recalculate any mappings, including the backup if returning from SMM. */ void smram_recalc_all(int ret) { - smram_t *temp_smram = base_smram, *next; + smram_t *temp_smram = base_smram; + smram_t *next; if (base_smram == NULL) - return; + return; if (ret) { - while (temp_smram != NULL) { - if (temp_smram->old_size != 0x00000000) - mem_mapping_recalc(temp_smram->old_host_base, temp_smram->old_size); - temp_smram->old_host_base = temp_smram->old_size = 0x00000000; + while (temp_smram != NULL) { + if (temp_smram->old_size != 0x00000000) + mem_mapping_recalc(temp_smram->old_host_base, temp_smram->old_size); + temp_smram->old_host_base = temp_smram->old_size = 0x00000000; - next = temp_smram->next; - temp_smram = next; - } + next = temp_smram->next; + temp_smram = next; + } } temp_smram = base_smram; while (temp_smram != NULL) { - if (temp_smram->size != 0x00000000) - mem_mapping_recalc(temp_smram->host_base, temp_smram->size); + if (temp_smram->size != 0x00000000) + mem_mapping_recalc(temp_smram->host_base, temp_smram->size); - next = temp_smram->next; - temp_smram = next; + next = temp_smram->next; + temp_smram = next; } flushmmucache(); } - /* Delete a SMRAM mapping. */ void smram_del(smram_t *smr) { /* Do a sanity check */ if ((base_smram == NULL) && (last_smram != NULL)) { - fatal("smram_del(): NULL base SMRAM with non-NULL last SMRAM\n"); - return; + fatal("smram_del(): NULL base SMRAM with non-NULL last SMRAM\n"); + return; } else if ((base_smram != NULL) && (last_smram == NULL)) { - fatal("smram_del(): Non-NULL base SMRAM with NULL last SMRAM\n"); - return; + fatal("smram_del(): Non-NULL base SMRAM with NULL last SMRAM\n"); + return; } else if ((base_smram != NULL) && (base_smram->prev != NULL)) { - fatal("smram_del(): Base SMRAM with a preceding SMRAM\n"); - return; + fatal("smram_del(): Base SMRAM with a preceding SMRAM\n"); + return; } else if ((last_smram != NULL) && (last_smram->next != NULL)) { - fatal("smram_del(): Last SMRAM with a following SMRAM\n"); - return; + fatal("smram_del(): Last SMRAM with a following SMRAM\n"); + return; } if (smr == NULL) { - fatal("smram_del(): Invalid SMRAM mapping\n"); - return; + fatal("smram_del(): Invalid SMRAM mapping\n"); + return; } /* Disable the entry. */ @@ -220,20 +211,19 @@ smram_del(smram_t *smr) /* Zap it from the list. */ if (smr->prev != NULL) - smr->prev->next = smr->next; + smr->prev->next = smr->next; if (smr->next != NULL) - smr->next->prev = smr->prev; + smr->next->prev = smr->prev; /* Check if it's the first or the last mapping. */ if (base_smram == smr) - base_smram = smr->next; + base_smram = smr->next; if (last_smram == smr) - last_smram = smr->prev; + last_smram = smr->prev; free(smr); } - /* Add a SMRAM mapping. */ smram_t * smram_add(void) @@ -242,63 +232,61 @@ smram_add(void) /* Do a sanity check */ if ((base_smram == NULL) && (last_smram != NULL)) { - fatal("smram_add(): NULL base SMRAM with non-NULL last SMRAM\n"); - return NULL; + fatal("smram_add(): NULL base SMRAM with non-NULL last SMRAM\n"); + return NULL; } else if ((base_smram != NULL) && (last_smram == NULL)) { - fatal("smram_add(): Non-NULL base SMRAM with NULL last SMRAM\n"); - return NULL; + fatal("smram_add(): Non-NULL base SMRAM with NULL last SMRAM\n"); + return NULL; } else if ((base_smram != NULL) && (base_smram->prev != NULL)) { - fatal("smram_add(): Base SMRAM with a preceding SMRAM\n"); - return NULL; + fatal("smram_add(): Base SMRAM with a preceding SMRAM\n"); + return NULL; } else if ((last_smram != NULL) && (last_smram->next != NULL)) { - fatal("smram_add(): Last SMRAM with a following SMRAM\n"); - return NULL; + fatal("smram_add(): Last SMRAM with a following SMRAM\n"); + return NULL; } temp_smram = (smram_t *) malloc(sizeof(smram_t)); if (temp_smram == NULL) { - fatal("smram_add(): temp_smram malloc failed\n"); - return NULL; - } + fatal("smram_add(): temp_smram malloc failed\n"); + return NULL; + } memset(temp_smram, 0x00, sizeof(smram_t)); memset(&(temp_smram->mapping), 0x00, sizeof(mem_mapping_t)); /* Add struct to the beginning of the list if necessary.*/ if (base_smram == NULL) - base_smram = temp_smram; + base_smram = temp_smram; /* Add struct to the end of the list.*/ if (last_smram == NULL) - temp_smram->prev = NULL; - else { - temp_smram->prev = last_smram; - last_smram->next = temp_smram; + temp_smram->prev = NULL; + else { + temp_smram->prev = last_smram; + last_smram->next = temp_smram; } last_smram = temp_smram; mem_mapping_add(&(temp_smram->mapping), 0x00000000, 0x00000000, - smram_read,smram_readw,smram_readl, - smram_write,smram_writew,smram_writel, - ram, MEM_MAPPING_SMRAM, temp_smram); + smram_read, smram_readw, smram_readl, + smram_write, smram_writew, smram_writel, + ram, MEM_MAPPING_SMRAM, temp_smram); smram_set_separate_smram(0); return temp_smram; } - /* Set memory state in the specified model (normal or SMM) according to the specified flags, separately for bus and CPU. */ void smram_map_ex(int bus, int smm, uint32_t addr, uint32_t size, int is_smram) { if (bus) - mem_set_access_smram_bus(smm, addr, size, is_smram); + mem_set_access_smram_bus(smm, addr, size, is_smram); else - mem_set_access_smram_cpu(smm, addr, size, is_smram); + mem_set_access_smram_cpu(smm, addr, size, is_smram); } - /* Set memory state in the specified model (normal or SMM) according to the specified flags. */ void smram_map(int smm, uint32_t addr, uint32_t size, int is_smram) @@ -307,85 +295,82 @@ smram_map(int smm, uint32_t addr, uint32_t size, int is_smram) smram_map_ex(1, smm, addr, size, is_smram); } - /* Disable a specific SMRAM mapping. */ void smram_disable(smram_t *smr) { if (smr == NULL) { - fatal("smram_disable(): Invalid SMRAM mapping\n"); - return; + fatal("smram_disable(): Invalid SMRAM mapping\n"); + return; } if (smr->size != 0x00000000) { - smram_map(0, smr->host_base, smr->size, 0); - smram_map(1, smr->host_base, smr->size, 0); + smram_map(0, smr->host_base, smr->size, 0); + smram_map(1, smr->host_base, smr->size, 0); - smr->host_base = smr->ram_base = 0x00000000; - smr->size = 0x00000000; + smr->host_base = smr->ram_base = 0x00000000; + smr->size = 0x00000000; - mem_mapping_disable(&(smr->mapping)); + mem_mapping_disable(&(smr->mapping)); } } - /* Disable all SMRAM mappings. */ void smram_disable_all(void) { - smram_t *temp_smram = base_smram, *next; + smram_t *temp_smram = base_smram; + smram_t *next; while (temp_smram != NULL) { - smram_disable(temp_smram); + smram_disable(temp_smram); - next = temp_smram->next; - temp_smram = next; + next = temp_smram->next; + temp_smram = next; } } - /* Enable SMRAM mappings according to flags for both normal and SMM modes, separately for bus and CPU. */ void smram_enable_ex(smram_t *smr, uint32_t host_base, uint32_t ram_base, uint32_t size, - int flags_normal, int flags_normal_bus, int flags_smm, int flags_smm_bus) + int flags_normal, int flags_normal_bus, int flags_smm, int flags_smm_bus) { if (smr == NULL) { - fatal("smram_add(): Invalid SMRAM mapping\n"); - return; + fatal("smram_add(): Invalid SMRAM mapping\n"); + return; } if ((size != 0x00000000) && (flags_normal || flags_smm)) { - smr->host_base = host_base; - smr->ram_base = ram_base, - smr->size = size; + smr->host_base = host_base; + smr->ram_base = ram_base; + smr->size = size; - mem_mapping_set_addr(&(smr->mapping), smr->host_base, smr->size); - if (!use_separate_smram || (smr->ram_base >= 0x000a0000)) { - if (smr->ram_base < (1 << 30)) - mem_mapping_set_exec(&(smr->mapping), ram + smr->ram_base); - else - mem_mapping_set_exec(&(smr->mapping), ram2 + smr->ram_base - (1 << 30)); - } else { - if (smr->ram_base == 0x00030000) - mem_mapping_set_exec(&(smr->mapping), smram); - else if (smr->ram_base == 0x00040000) - mem_mapping_set_exec(&(smr->mapping), smram + 0x10000); - else if (smr->ram_base == 0x00060000) - mem_mapping_set_exec(&(smr->mapping), smram + 0x20000); - else if (smr->ram_base == 0x00070000) - mem_mapping_set_exec(&(smr->mapping), smram + 0x30000); - } + mem_mapping_set_addr(&(smr->mapping), smr->host_base, smr->size); + if (!use_separate_smram || (smr->ram_base >= 0x000a0000)) { + if (smr->ram_base < (1 << 30)) + mem_mapping_set_exec(&(smr->mapping), ram + smr->ram_base); + else + mem_mapping_set_exec(&(smr->mapping), ram2 + smr->ram_base - (1 << 30)); + } else { + if (smr->ram_base == 0x00030000) + mem_mapping_set_exec(&(smr->mapping), smram); + else if (smr->ram_base == 0x00040000) + mem_mapping_set_exec(&(smr->mapping), smram + 0x10000); + else if (smr->ram_base == 0x00060000) + mem_mapping_set_exec(&(smr->mapping), smram + 0x20000); + else if (smr->ram_base == 0x00070000) + mem_mapping_set_exec(&(smr->mapping), smram + 0x30000); + } - smram_map_ex(0, 0, host_base, size, flags_normal); - smram_map_ex(1, 0, host_base, size, flags_normal_bus); - smram_map_ex(0, 1, host_base, size, flags_smm); - smram_map_ex(1, 1, host_base, size, flags_smm_bus); + smram_map_ex(0, 0, host_base, size, flags_normal); + smram_map_ex(1, 0, host_base, size, flags_normal_bus); + smram_map_ex(0, 1, host_base, size, flags_smm); + smram_map_ex(1, 1, host_base, size, flags_smm_bus); } else - smram_disable(smr); + smram_disable(smr); } - /* Enable SMRAM mappings according to flags for both normal and SMM modes. */ void smram_enable(smram_t *smr, uint32_t host_base, uint32_t ram_base, uint32_t size, int flags_normal, int flags_smm) @@ -393,7 +378,6 @@ smram_enable(smram_t *smr, uint32_t host_base, uint32_t ram_base, uint32_t size, smram_enable_ex(smr, host_base, ram_base, size, flags_normal, flags_normal, flags_smm, flags_smm); } - /* Checks if a SMRAM mapping is enabled or not. */ int smram_enabled(smram_t *smr) @@ -401,27 +385,25 @@ smram_enabled(smram_t *smr) int ret = 0; if (smr == NULL) - ret = 0; + ret = 0; else - ret = (smr->size != 0x00000000); + ret = (smr->size != 0x00000000); return ret; } - /* Changes the SMRAM state. */ void smram_state_change(smram_t *smr, int smm, int flags) { if (smr == NULL) { - fatal("smram_tate_change(): Invalid SMRAM mapping\n"); - return; + fatal("smram_tate_change(): Invalid SMRAM mapping\n"); + return; } smram_map(smm, smr->host_base, smr->size, flags); } - void smram_set_separate_smram(uint8_t set) { diff --git a/src/mem/spd.c b/src/mem/spd.c index 7c033fe8c..a3bcba46d 100644 --- a/src/mem/spd.c +++ b/src/mem/spd.c @@ -1,18 +1,18 @@ /* - * 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. + * 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. + * This file is part of the 86Box distribution. * - * Emulation of SPD (Serial Presence Detect) devices. + * Emulation of SPD (Serial Presence Detect) devices. * * * - * Authors: RichardG, + * Authors: RichardG, * - * Copyright 2020 RichardG. + * Copyright 2020 RichardG. */ #include #include @@ -27,59 +27,54 @@ #include <86box/spd.h> #include <86box/version.h> #include <86box/machine.h> +#include <86box/plat_unused.h> +#define SPD_ROLLUP(x) ((x) >= 16 ? ((x) -15) : (x)) -#define SPD_ROLLUP(x) ((x) >= 16 ? ((x) - 15) : (x)) - - -int spd_present = 0; -spd_t *spd_modules[SPD_MAX_SLOTS]; +uint8_t spd_present = 0; +spd_t *spd_modules[SPD_MAX_SLOTS]; static const device_t spd_device; - #ifdef ENABLE_SPD_LOG int spd_do_log = ENABLE_SPD_LOG; - static void spd_log(const char *fmt, ...) { va_list ap; if (spd_do_log) { - va_start(ap, fmt); - pclog_ex(fmt, ap); - va_end(ap); + va_start(ap, fmt); + pclog_ex(fmt, ap); + va_end(ap); } } #else -#define spd_log(fmt, ...) +# define spd_log(fmt, ...) #endif - static void -spd_close(void *priv) +spd_close(UNUSED(void *priv)) { spd_log("SPD: close()\n"); for (uint8_t i = 0; i < SPD_MAX_SLOTS; i++) { - if (spd_modules[i]) - i2c_eeprom_close(spd_modules[i]->eeprom); + if (spd_modules[i]) + i2c_eeprom_close(spd_modules[i]->eeprom); } spd_present = 0; } - static void * -spd_init(const device_t *info) +spd_init(UNUSED(const device_t *info)) { spd_log("SPD: init()\n"); for (uint8_t i = 0; i < SPD_MAX_SLOTS; i++) { - if (spd_modules[i]) - spd_modules[i]->eeprom = i2c_eeprom_init(i2c_smbus, SPD_BASE_ADDR + i, spd_modules[i]->data, sizeof(spd_modules[i]->data), 0); + if (spd_modules[i]) + spd_modules[i]->eeprom = i2c_eeprom_init(i2c_smbus, SPD_BASE_ADDR + i, spd_modules[i]->data, sizeof(spd_modules[i]->data), 0); } spd_present = 1; @@ -87,133 +82,135 @@ spd_init(const device_t *info) return &spd_modules; } - int comp_ui16_rev(const void *elem1, const void *elem2) { - uint16_t a = *((uint16_t *) elem1); - uint16_t b = *((uint16_t *) elem2); + const uint16_t a = *((const uint16_t *) elem1); + const uint16_t b = *((const uint16_t *) elem2); return ((a > b) ? -1 : ((a < b) ? 1 : 0)); } - void spd_populate(uint16_t *rows, uint8_t slot_count, uint16_t total_size, uint16_t min_module_size, uint16_t max_module_size, uint8_t enable_asym) { - uint8_t row, next_empty_row, split, i; + uint8_t row; + uint8_t next_empty_row; + uint8_t split; uint16_t asym; /* Populate rows with modules in power-of-2 capacities. */ memset(rows, 0, SPD_MAX_SLOTS << 1); for (row = 0; row < slot_count && total_size; row++) { - /* populate slot */ - rows[row] = 1 << log2i(MIN(total_size, max_module_size)); - if (total_size >= rows[row]) { - spd_log("SPD: Initial row %d = %d MB\n", row, rows[row]); - total_size -= rows[row]; - } else { - rows[row] = 0; - break; - } + /* populate slot */ + rows[row] = 1 << log2i(MIN(total_size, max_module_size)); + if (total_size >= rows[row]) { + spd_log("SPD: Initial row %d = %d MB\n", row, rows[row]); + total_size -= rows[row]; + } else { + rows[row] = 0; + break; + } } /* Did we populate all the RAM? */ if (total_size) { - /* Work backwards to add the missing RAM as asymmetric modules if possible. */ - if (enable_asym) { - row = slot_count - 1; - do { - asym = (1 << log2i(MIN(total_size, rows[row]))); - if (rows[row] + asym <= max_module_size) { - rows[row] += asym; - total_size -= asym; - } - } while ((row-- > 0) && total_size); - } + /* Work backwards to add the missing RAM as asymmetric modules if possible. */ + if (enable_asym) { + row = slot_count - 1; + do { + asym = (1 << log2i(MIN(total_size, rows[row]))); + if (rows[row] + asym <= max_module_size) { + rows[row] += asym; + total_size -= asym; + } + } while ((row-- > 0) && total_size); + } - if (total_size) /* still not enough */ - spd_log("SPD: Not enough RAM slots (%d) to cover memory (%d MB short)\n", slot_count, total_size); + if (total_size) /* still not enough */ + spd_log("SPD: Not enough RAM slots (%d) to cover memory (%d MB short)\n", slot_count, total_size); } /* Populate empty rows by splitting modules... */ split = (total_size == 0); /* ...if possible. */ while (split) { - /* Look for a module to split. */ - split = 0; - for (row = 0; row < slot_count; row++) { - if ((rows[row] < (min_module_size << 1)) || (rows[row] != (1 << log2i(rows[row])))) - continue; /* no module here, module is too small to be split, or asymmetric module */ + /* Look for a module to split. */ + split = 0; + for (row = 0; row < slot_count; row++) { + if ((rows[row] < (min_module_size << 1)) || (rows[row] != (1 << log2i(rows[row])))) + continue; /* no module here, module is too small to be split, or asymmetric module */ - /* Find next empty row. */ - next_empty_row = 0; - for (i = row + 1; i < slot_count && !next_empty_row; i++) { - if (!rows[i]) - next_empty_row = i; - } - if (!next_empty_row) - break; /* no empty rows left */ + /* Find next empty row. */ + next_empty_row = 0; + for (uint8_t i = row + 1; i < slot_count && !next_empty_row; i++) { + if (!rows[i]) + next_empty_row = i; + } + if (!next_empty_row) + break; /* no empty rows left */ - /* Split the module into its own row and the next empty row. */ - spd_log("SPD: splitting row %d (%d MB) into %d and %d (%d MB each)\n", row, rows[row], row, next_empty_row, rows[row] >> 1); - rows[row] = rows[next_empty_row] = rows[row] >> 1; - split = 1; - break; - } + /* Split the module into its own row and the next empty row. */ + spd_log("SPD: splitting row %d (%d MB) into %d and %d (%d MB each)\n", row, rows[row], row, next_empty_row, rows[row] >> 1); + rows[row] = rows[next_empty_row] = rows[row] >> 1; + split = 1; + break; + } - /* Sort rows by descending capacity if any were split. */ - if (split) - qsort(rows, slot_count, sizeof(uint16_t), comp_ui16_rev); + /* Sort rows by descending capacity if any were split. */ + if (split) + qsort(rows, slot_count, sizeof(uint16_t), comp_ui16_rev); } } - static int spd_write_part_no(char *part_no, char *type, uint16_t size) { char size_unit; if (size >= 1024) { - size_unit = 'G'; - size >>= 10; + size_unit = 'G'; + size >>= 10; } else { - size_unit = 'M'; + size_unit = 'M'; } return sprintf(part_no, EMU_NAME "-%s-%03d%c", type, size, size_unit); } - void spd_register(uint8_t ram_type, uint8_t slot_mask, uint16_t max_module_size) { - uint8_t slot, slot_count, row, i; - uint16_t min_module_size, rows[SPD_MAX_SLOTS], asym; - spd_edo_t *edo_data; + uint8_t slot; + uint8_t slot_count; + uint8_t row; + uint16_t min_module_size; + uint16_t rows[SPD_MAX_SLOTS]; + uint16_t asym; + spd_edo_t *edo_data; spd_sdram_t *sdram_data; /* Determine the minimum module size for this RAM type. */ switch (ram_type) { - case SPD_TYPE_FPM: - case SPD_TYPE_EDO: - min_module_size = SPD_MIN_SIZE_EDO; - break; + case SPD_TYPE_FPM: + case SPD_TYPE_EDO: + min_module_size = SPD_MIN_SIZE_EDO; + break; - case SPD_TYPE_SDRAM: - min_module_size = SPD_MIN_SIZE_SDRAM; - break; + case SPD_TYPE_SDRAM: + min_module_size = SPD_MIN_SIZE_SDRAM; + break; - default: - spd_log("SPD: unknown RAM type %02X\n", ram_type); - return; + default: + spd_log("SPD: unknown RAM type %02X\n", ram_type); + return; } /* Count how many slots are enabled. */ slot_count = 0; for (slot = 0; slot < SPD_MAX_SLOTS; slot++) { - rows[slot] = 0; - if (slot_mask & (1 << slot)) - slot_count++; - } + rows[slot] = 0; + if (slot_mask & (1 << slot)) + slot_count++; + } /* Populate rows. */ spd_populate(rows, slot_count, (mem_size >> 10), min_module_size, max_module_size, 1); @@ -221,368 +218,385 @@ spd_register(uint8_t ram_type, uint8_t slot_mask, uint16_t max_module_size) /* Register SPD devices and populate their data according to the rows. */ row = 0; for (slot = 0; (slot < SPD_MAX_SLOTS) && rows[row]; slot++) { - if (!(slot_mask & (1 << slot))) - continue; /* slot disabled */ + if (!(slot_mask & (1 << slot))) + continue; /* slot disabled */ - spd_modules[slot] = (spd_t *) malloc(sizeof(spd_t)); - memset(spd_modules[slot], 0, sizeof(spd_t)); - spd_modules[slot]->slot = slot; - spd_modules[slot]->size = rows[row]; + spd_modules[slot] = (spd_t *) malloc(sizeof(spd_t)); + memset(spd_modules[slot], 0, sizeof(spd_t)); + spd_modules[slot]->slot = slot; + spd_modules[slot]->size = rows[row]; - /* Determine the second row size, from which the first row size can be obtained. */ - asym = rows[row] - (1 << log2i(rows[row])); /* separate the powers of 2 */ - if (!asym) /* is the module asymmetric? */ - asym = rows[row] >> 1; /* symmetric, therefore divide by 2 */ + /* Determine the second row size, from which the first row size can be obtained. */ + asym = rows[row] - (1 << log2i(rows[row])); /* separate the powers of 2 */ + if (!asym) /* is the module asymmetric? */ + asym = rows[row] >> 1; /* symmetric, therefore divide by 2 */ - spd_modules[slot]->row1 = rows[row] - asym; - spd_modules[slot]->row2 = asym; + spd_modules[slot]->row1 = rows[row] - asym; + spd_modules[slot]->row2 = asym; - spd_log("SPD: Registering slot %d = row %d = %d MB (%d/%d)\n", slot, row, rows[row], spd_modules[slot]->row1, spd_modules[slot]->row2); + spd_log("SPD: Registering slot %d = row %d = %d MB (%d/%d)\n", slot, row, rows[row], spd_modules[slot]->row1, spd_modules[slot]->row2); - switch (ram_type) { - case SPD_TYPE_FPM: - case SPD_TYPE_EDO: - edo_data = &spd_modules[slot]->edo_data; + switch (ram_type) { + case SPD_TYPE_FPM: + case SPD_TYPE_EDO: + edo_data = &spd_modules[slot]->edo_data; - /* EDO SPD is specified by JEDEC and present in some modules, but - most utilities cannot interpret it correctly. SIV32 at least gets - the module capacities right, so it was used as a reference here. */ - edo_data->bytes_used = 0x80; - edo_data->spd_size = 0x08; - edo_data->mem_type = ram_type; - edo_data->row_bits = SPD_ROLLUP(7 + log2i(spd_modules[slot]->row1)); /* first row */ - edo_data->col_bits = 9; - if (spd_modules[slot]->row1 != spd_modules[slot]->row2) { /* the upper 4 bits of row_bits/col_bits should be 0 on a symmetric module */ - edo_data->row_bits |= SPD_ROLLUP(7 + log2i(spd_modules[slot]->row2)) << 4; /* second row, if different from first */ - edo_data->col_bits |= 9 << 4; /* same as first row, but just in case */ - } - edo_data->banks = 2; - edo_data->data_width_lsb = 64; - edo_data->signal_level = SPD_SIGNAL_LVTTL; - edo_data->trac = 50; - edo_data->tcac = 13; - edo_data->refresh_rate = SPD_REFRESH_NORMAL; - edo_data->dram_width = 8; + /* EDO SPD is specified by JEDEC and present in some modules, but + most utilities cannot interpret it correctly. SIV32 at least gets + the module capacities right, so it was used as a reference here. */ + edo_data->bytes_used = 0x80; + edo_data->spd_size = 0x08; + edo_data->mem_type = ram_type; + edo_data->row_bits = SPD_ROLLUP(7 + log2i(spd_modules[slot]->row1)); /* first row */ + edo_data->col_bits = 9; + if (spd_modules[slot]->row1 != spd_modules[slot]->row2) { /* the upper 4 bits of row_bits/col_bits should be 0 on a symmetric module */ + edo_data->row_bits |= SPD_ROLLUP(7 + log2i(spd_modules[slot]->row2)) << 4; /* second row, if different from first */ + edo_data->col_bits |= 9 << 4; /* same as first row, but just in case */ + } + edo_data->banks = 2; + edo_data->data_width_lsb = 64; + edo_data->signal_level = SPD_SIGNAL_LVTTL; + edo_data->trac = 50; + edo_data->tcac = 13; + edo_data->refresh_rate = SPD_REFRESH_NORMAL; + edo_data->dram_width = 8; - edo_data->spd_rev = 0x12; - for (i = spd_write_part_no(edo_data->part_no, (ram_type == SPD_TYPE_FPM) ? "FPM" : "EDO", rows[row]); - i < sizeof(edo_data->part_no); i++) - edo_data->part_no[i] = ' '; /* part number should be space-padded */ - edo_data->rev_code[0] = BCD8(EMU_VERSION_MAJ); - edo_data->rev_code[1] = BCD8(EMU_VERSION_MIN); - edo_data->mfg_year = 20; - edo_data->mfg_week = 17; + edo_data->spd_rev = 0x12; + for (int i = spd_write_part_no(edo_data->part_no, (ram_type == SPD_TYPE_FPM) ? "FPM" : "EDO", rows[row]); + i < sizeof(edo_data->part_no); i++) + edo_data->part_no[i] = ' '; /* part number should be space-padded */ + edo_data->rev_code[0] = BCD8(EMU_VERSION_MAJ); + edo_data->rev_code[1] = BCD8(EMU_VERSION_MIN); + edo_data->mfg_year = 20; + edo_data->mfg_week = 17; - for (i = 0; i < 63; i++) - edo_data->checksum += spd_modules[slot]->data[i]; - for (i = 0; i < 129; i++) - edo_data->checksum2 += spd_modules[slot]->data[i]; - break; + for (uint8_t i = 0; i < 63; i++) + edo_data->checksum += spd_modules[slot]->data[i]; + for (uint8_t i = 0; i < 129; i++) + edo_data->checksum2 += spd_modules[slot]->data[i]; + break; - case SPD_TYPE_SDRAM: - sdram_data = &spd_modules[slot]->sdram_data; + case SPD_TYPE_SDRAM: + sdram_data = &spd_modules[slot]->sdram_data; - sdram_data->bytes_used = 0x80; - sdram_data->spd_size = 0x08; - sdram_data->mem_type = ram_type; - sdram_data->row_bits = SPD_ROLLUP(6 + log2i(spd_modules[slot]->row1)); /* first row */ - sdram_data->col_bits = 9; - if (spd_modules[slot]->row1 != spd_modules[slot]->row2) { /* the upper 4 bits of row_bits/col_bits should be 0 on a symmetric module */ - sdram_data->row_bits |= SPD_ROLLUP(6 + log2i(spd_modules[slot]->row2)) << 4; /* second row, if different from first */ - sdram_data->col_bits |= 9 << 4; /* same as first row, but just in case */ - } - sdram_data->rows = 2; - sdram_data->data_width_lsb = 64; - sdram_data->signal_level = SPD_SIGNAL_LVTTL; - sdram_data->tclk = 0x75; /* 7.5 ns = 133.3 MHz */ - sdram_data->tac = 0x10; - sdram_data->refresh_rate = SPD_SDR_REFRESH_SELF | SPD_REFRESH_NORMAL; - sdram_data->sdram_width = 8; - sdram_data->tccd = 1; - sdram_data->burst = SPD_SDR_BURST_PAGE | 1 | 2 | 4 | 8; - sdram_data->banks = 4; - sdram_data->cas = 0x1c; /* CAS 5/4/3 supported */ - sdram_data->cslat = sdram_data->we = 0x7f; - sdram_data->dev_attr = SPD_SDR_ATTR_EARLY_RAS | SPD_SDR_ATTR_AUTO_PC | SPD_SDR_ATTR_PC_ALL | SPD_SDR_ATTR_W1R_BURST; - sdram_data->tclk2 = 0xA0; /* 10 ns = 100 MHz */ - sdram_data->tclk3 = 0xF0; /* 15 ns = 66.7 MHz */ - sdram_data->tac2 = sdram_data->tac3 = 0x10; - sdram_data->trp = sdram_data->trrd = sdram_data->trcd = sdram_data->tras = 1; - if (spd_modules[slot]->row1 != spd_modules[slot]->row2) { - /* Utilities interpret bank_density a bit differently on asymmetric modules. */ - sdram_data->bank_density = 1 << (log2i(spd_modules[slot]->row1 >> 1) - 2); /* first row */ - sdram_data->bank_density |= 1 << (log2i(spd_modules[slot]->row2 >> 1) - 2); /* second row */ - } else { - sdram_data->bank_density = 1 << (log2i(spd_modules[slot]->row1 >> 1) - 1); /* symmetric module = only one bit is set */ - } - sdram_data->ca_setup = sdram_data->data_setup = 0x15; - sdram_data->ca_hold = sdram_data->data_hold = 0x08; + sdram_data->bytes_used = 0x80; + sdram_data->spd_size = 0x08; + sdram_data->mem_type = ram_type; + sdram_data->row_bits = SPD_ROLLUP(6 + log2i(spd_modules[slot]->row1)); /* first row */ + sdram_data->col_bits = 9; + if (spd_modules[slot]->row1 != spd_modules[slot]->row2) { /* the upper 4 bits of row_bits/col_bits should be 0 on a symmetric module */ + sdram_data->row_bits |= SPD_ROLLUP(6 + log2i(spd_modules[slot]->row2)) << 4; /* second row, if different from first */ + sdram_data->col_bits |= 9 << 4; /* same as first row, but just in case */ + } + sdram_data->rows = 2; + sdram_data->data_width_lsb = 64; + sdram_data->signal_level = SPD_SIGNAL_LVTTL; + sdram_data->tclk = 0x75; /* 7.5 ns = 133.3 MHz */ + sdram_data->tac = 0x10; + sdram_data->refresh_rate = SPD_SDR_REFRESH_SELF | SPD_REFRESH_NORMAL; + sdram_data->sdram_width = 8; + sdram_data->tccd = 1; + sdram_data->burst = SPD_SDR_BURST_PAGE | 1 | 2 | 4 | 8; + sdram_data->banks = 4; + sdram_data->cas = 0x1c; /* CAS 5/4/3 supported */ + sdram_data->cslat = sdram_data->we = 0x7f; + sdram_data->dev_attr = SPD_SDR_ATTR_EARLY_RAS | SPD_SDR_ATTR_AUTO_PC | SPD_SDR_ATTR_PC_ALL | SPD_SDR_ATTR_W1R_BURST; + sdram_data->tclk2 = 0xA0; /* 10 ns = 100 MHz */ + sdram_data->tclk3 = 0xF0; /* 15 ns = 66.7 MHz */ + sdram_data->tac2 = sdram_data->tac3 = 0x10; + sdram_data->trp = sdram_data->trrd = sdram_data->trcd = sdram_data->tras = 1; + if (spd_modules[slot]->row1 != spd_modules[slot]->row2) { + /* Utilities interpret bank_density a bit differently on asymmetric modules. */ + sdram_data->bank_density = 1 << (log2i(spd_modules[slot]->row1 >> 1) - 2); /* first row */ + sdram_data->bank_density |= 1 << (log2i(spd_modules[slot]->row2 >> 1) - 2); /* second row */ + } else { + sdram_data->bank_density = 1 << (log2i(spd_modules[slot]->row1 >> 1) - 1); /* symmetric module = only one bit is set */ + } + sdram_data->ca_setup = sdram_data->data_setup = 0x15; + sdram_data->ca_hold = sdram_data->data_hold = 0x08; - sdram_data->spd_rev = 0x12; - for (i = spd_write_part_no(sdram_data->part_no, "SDR", rows[row]); - i < sizeof(sdram_data->part_no); i++) - sdram_data->part_no[i] = ' '; /* part number should be space-padded */ - sdram_data->rev_code[0] = BCD8(EMU_VERSION_MAJ); - sdram_data->rev_code[1] = BCD8(EMU_VERSION_MIN); - sdram_data->mfg_year = 20; - sdram_data->mfg_week = 13; + sdram_data->spd_rev = 0x12; + for (int i = spd_write_part_no(sdram_data->part_no, "SDR", rows[row]); + i < sizeof(sdram_data->part_no); i++) + sdram_data->part_no[i] = ' '; /* part number should be space-padded */ + sdram_data->rev_code[0] = BCD8(EMU_VERSION_MAJ); + sdram_data->rev_code[1] = BCD8(EMU_VERSION_MIN); + sdram_data->mfg_year = 20; + sdram_data->mfg_week = 13; - sdram_data->freq = 100; - sdram_data->features = 0xFF; + sdram_data->freq = 100; + sdram_data->features = 0xFF; - for (i = 0; i < 63; i++) - sdram_data->checksum += spd_modules[slot]->data[i]; - for (i = 0; i < 129; i++) - sdram_data->checksum2 += spd_modules[slot]->data[i]; - break; - } + for (uint8_t i = 0; i < 63; i++) + sdram_data->checksum += spd_modules[slot]->data[i]; + for (uint8_t i = 0; i < 129; i++) + sdram_data->checksum2 += spd_modules[slot]->data[i]; + break; - row++; + default: + break; + } + + row++; } device_add(&spd_device); } - void spd_write_drbs(uint8_t *regs, uint8_t reg_min, uint8_t reg_max, uint8_t drb_unit) { - uint8_t row, dimm, drb, apollo = 0; - uint16_t size, rows[SPD_MAX_SLOTS]; + uint8_t dimm; + uint8_t drb; + uint8_t apollo = 0; + uint8_t two_step = !!(drb_unit & 0x80); + uint16_t size; + uint16_t rows[SPD_MAX_SLOTS]; + + drb_unit &= 0x7f; /* Special case for VIA Apollo Pro family, which jumps from 5F to 56. */ if (reg_max < reg_min) { - apollo = reg_max; - reg_max = reg_min + 7; + apollo = reg_max; + reg_max = reg_min + 7; } /* No SPD: split SIMMs into pairs as if they were "DIMM"s. */ if (!spd_present) { - dimm = ((reg_max - reg_min) + 1) >> 1; /* amount of "DIMM"s, also used to determine the maximum "DIMM" size */ - spd_populate(rows, dimm, mem_size >> 10, drb_unit, 1 << (log2i((machines[machine].max_ram >> 10) / dimm)), 0); + dimm = ((reg_max - reg_min) + 1) >> 1; /* amount of "DIMM"s, also used to determine the maximum "DIMM" size */ + spd_populate(rows, dimm, mem_size >> 10, drb_unit, 1 << (log2i((machines[machine].ram.max >> 10) / dimm)), 0); } /* Write DRBs for each row. */ spd_log("SPD: Writing DRBs... regs=[%02X:%02X] unit=%d\n", reg_min, reg_max, drb_unit); - for (row = 0; row <= (reg_max - reg_min); row++) { - dimm = (row >> 1); - size = 0; + for (uint8_t row = 0; row <= (reg_max - reg_min); row++) { + dimm = (row >> 1); + size = 0; - if (spd_present) { - /* SPD enabled: use SPD info for this slot, if present. */ - if (spd_modules[dimm]) { - if (spd_modules[dimm]->row1 < drb_unit) /* hack within a hack: turn a double-sided DIMM that is too small into a single-sided one */ - size = (row & 1) ? 0 : drb_unit; - else - size = (row & 1) ? spd_modules[dimm]->row2 : spd_modules[dimm]->row1; - } - } else { - /* No SPD: use the values calculated above. */ - size = (rows[dimm] >> 1); - } + if (spd_present) { + /* SPD enabled: use SPD info for this slot, if present. */ + if (spd_modules[dimm]) { + if (spd_modules[dimm]->row1 < drb_unit) /* hack within a hack: turn a double-sided DIMM that is too small into a single-sided one */ + size = (row & 1) ? 0 : drb_unit; + else + size = (row & 1) ? spd_modules[dimm]->row2 : spd_modules[dimm]->row1; + } + } else { + /* No SPD: use the values calculated above. */ + size = (rows[dimm] >> 1); + } - /* Determine the DRB register to write. */ - drb = reg_min + row; - if (apollo && ((drb & 0xf) < 0xa)) - drb = apollo + (drb & 0xf); + /* Determine the DRB register to write. */ + if (two_step) + drb = reg_min + (row << 1); + else + drb = reg_min + row; + if (apollo && ((drb & 0xf) < 0xa)) + drb = apollo + (drb & 0xf); - /* Write DRB register, adding the previous DRB's value. */ - if (row == 0) - regs[drb] = 0; - else if ((apollo) && (drb == apollo)) - regs[drb] = regs[drb | 0xf]; /* 5F comes before 56 */ - else - regs[drb] = regs[drb - 1]; - if (size) - regs[drb] += size / drb_unit; /* this will intentionally overflow on 440GX with 2 GB */ - spd_log("SPD: DRB[%d] = %d MB (%02Xh raw)\n", row, size, regs[drb]); + /* Write DRB register, adding the previous DRB's value. */ + if (row == 0) + regs[drb] = 0; + else if (apollo && (drb == apollo)) + regs[drb] = regs[drb | 0xf]; /* 5F comes before 56 */ + else + regs[drb] = regs[drb - 1]; + if (size) + regs[drb] += size / drb_unit; /* this will intentionally overflow on 440GX with 2 GB */ + spd_log("SPD: DRB[%d] = %d MB (%02Xh raw)\n", row, size, regs[drb]); } } - -/* Needed for 430LX. */ +/* Needed for 430NX. */ void spd_write_drbs_with_ext(uint8_t *regs, uint8_t reg_min, uint8_t reg_max, uint8_t drb_unit) { - uint8_t row, dimm, drb; - uint16_t size, row_val, rows[SPD_MAX_SLOTS]; - int shift; + uint8_t dimm; + uint8_t drb; + uint16_t size; + uint16_t row_val = 0; + uint16_t rows[SPD_MAX_SLOTS]; + int shift; /* No SPD: split SIMMs into pairs as if they were "DIMM"s. */ if (!spd_present) { - dimm = ((reg_max - reg_min) + 1) >> 1; /* amount of "DIMM"s, also used to determine the maximum "DIMM" size */ - spd_populate(rows, dimm, mem_size >> 10, drb_unit, 1 << (log2i((machines[machine].max_ram >> 10) / dimm)), 0); + dimm = ((reg_max - reg_min) + 1) >> 1; /* amount of "DIMM"s, also used to determine the maximum "DIMM" size */ + spd_populate(rows, dimm, mem_size >> 10, drb_unit, 1 << (log2i((machines[machine].ram.max >> 10) / dimm)), 0); } /* Write DRBs for each row. */ spd_log("SPD: Writing DRBs... regs=[%02X:%02X] unit=%d\n", reg_min, reg_max, drb_unit); - for (row = 0; row <= (reg_max - reg_min); row++) { - dimm = (row >> 1); - size = 0; + for (uint8_t row = 0; row <= (reg_max - reg_min); row++) { + dimm = (row >> 1); + size = 0; - if (spd_present) { - /* SPD enabled: use SPD info for this slot, if present. */ - if (spd_modules[dimm]) { - if (spd_modules[dimm]->row1 < drb_unit) /* hack within a hack: turn a double-sided DIMM that is too small into a single-sided one */ - size = (row & 1) ? 0 : drb_unit; - else - size = (row & 1) ? spd_modules[dimm]->row2 : spd_modules[dimm]->row1; - } - } else { - /* No SPD: use the values calculated above. */ - size = (rows[dimm] >> 1); - } + if (spd_present) { + /* SPD enabled: use SPD info for this slot, if present. */ + if (spd_modules[dimm]) { + if (spd_modules[dimm]->row1 < drb_unit) /* hack within a hack: turn a double-sided DIMM that is too small into a single-sided one */ + size = (row & 1) ? 0 : drb_unit; + else + size = (row & 1) ? spd_modules[dimm]->row2 : spd_modules[dimm]->row1; + } + } else { + /* No SPD: use the values calculated above. */ + size = (rows[dimm] >> 1); + } - /* Determine the DRB register to write. */ - drb = reg_min + row; + /* Determine the DRB register to write. */ + drb = reg_min + row; - /* Write DRB register, adding the previous DRB's value. */ - if (row == 0) - row_val = 0; - if (size) - row_val += size / drb_unit; /* this will intentionally overflow on 440GX with 2 GB */ - regs[drb] = row_val & 0xff; - drb = reg_min + 8 + (row >> 1); - shift = (row & 0x01) << 3; - regs[drb] = (((row_val & 0xfff) >> 8) << shift); - spd_log("SPD: DRB[%d] = %d MB (%02Xh raw)\n", row, size, regs[drb]); + /* Write DRB register, adding the previous DRB's value. */ + if (row == 0) + row_val = 0; + if (size) + row_val += size / drb_unit; /* this will intentionally overflow on 440GX with 2 GB */ + regs[drb] = row_val & 0xff; + drb = reg_min + 8 + (row >> 1); + shift = (row & 0x01) << 2; + /* Limit to 1 GB space, per the 430NX datasheet. */ + regs[drb] = (regs[drb] & ~(0xf << shift)) | (((row_val >> 8) & 3) << shift); + spd_log("SPD: DRB[%d] = %d MB (%02Xh raw)\n", row, size, regs[drb]); } } - /* Used by ALi M1531 and M1541/2. */ void spd_write_drbs_interleaved(uint8_t *regs, uint8_t reg_min, uint8_t reg_max, uint8_t drb_unit) { - uint8_t row, dimm; - uint8_t drb; - uint16_t size, size_acc = 0; + uint8_t dimm; + uint8_t drb; + uint16_t size; + uint16_t size_acc = 0; uint16_t rows[SPD_MAX_SLOTS]; /* No SPD: split SIMMs into pairs as if they were "DIMM"s. */ if (!spd_present) { - dimm = ((reg_max - reg_min) + 1) >> 2; /* amount of "DIMM"s, also used to determine the maximum "DIMM" size */ - spd_populate(rows, dimm, mem_size >> 10, drb_unit, 1 << (log2i((machines[machine].max_ram >> 10) / dimm)), 0); + dimm = ((reg_max - reg_min) + 1) >> 2; /* amount of "DIMM"s, also used to determine the maximum "DIMM" size */ + spd_populate(rows, dimm, mem_size >> 10, drb_unit, 1 << (log2i((machines[machine].ram.max >> 10) / dimm)), 0); } /* Write DRBs for each row. */ spd_log("SPD: Writing DRBs... regs=[%02X:%02X] unit=%d\n", reg_min, reg_max, drb_unit); - for (row = 0; row <= (reg_max - reg_min); row += 2) { - dimm = (row >> 2); - size = 0; + for (uint8_t row = 0; row <= (reg_max - reg_min); row += 2) { + dimm = (row >> 2); + size = 0; - if (spd_present) { - /* SPD enabled: use SPD info for this slot, if present. */ - if (spd_modules[dimm]) { - if (spd_modules[dimm]->row1 < drb_unit) /* hack within a hack: turn a double-sided DIMM that is too small into a single-sided one */ - size = ((row >> 1) & 1) ? 0 : drb_unit; - else - size = ((row >> 1) & 1) ? spd_modules[dimm]->row2 : spd_modules[dimm]->row1; - } - } else { - /* No SPD: use the values calculated above. */ - size = (rows[dimm] >> 1); - } + if (spd_present) { + /* SPD enabled: use SPD info for this slot, if present. */ + if (spd_modules[dimm]) { + if (spd_modules[dimm]->row1 < drb_unit) /* hack within a hack: turn a double-sided DIMM that is too small into a single-sided one */ + size = ((row >> 1) & 1) ? 0 : drb_unit; + else + size = ((row >> 1) & 1) ? spd_modules[dimm]->row2 : spd_modules[dimm]->row1; + } + } else { + /* No SPD: use the values calculated above. */ + size = (rows[dimm] >> 1); + } - /* Determine the DRB register to write. */ - drb = reg_min + row; + /* Determine the DRB register to write. */ + drb = reg_min + row; - /* Calculate previous and new size. */ - if (row == 0) - size_acc = 0; - else - size_acc += (size / drb_unit); + /* Calculate previous and new size. */ + if (row == 0) + size_acc = 0; + else + size_acc += (size / drb_unit); - /* Write DRB register, adding the previous DRB's value. */ - regs[drb] = size_acc & 0xff; - regs[drb + 1] = (regs[drb + 1] & 0xf0) | ((size_acc >> 8) & 0x0f); + /* Write DRB register, adding the previous DRB's value. */ + regs[drb] = size_acc & 0xff; + regs[drb + 1] = (regs[drb + 1] & 0xf0) | ((size_acc >> 8) & 0x0f); - spd_log("SPD: DRB[%d] = %d MB (%02Xh raw)\n", row >> 1, size, regs[drb]); + spd_log("SPD: DRB[%d] = %d MB (%02Xh raw)\n", row >> 1, size, regs[drb]); } } - /* This is needed because the ALi M1621 does this stuff completely differently, as it has DRAM bank registers instead of DRAM row boundary registers. */ void spd_write_drbs_ali1621(uint8_t *regs, uint8_t reg_min, uint8_t reg_max) { - uint8_t dimm, drb; + uint8_t dimm; + uint8_t drb; uint16_t size; uint16_t rows[SPD_MAX_SLOTS]; /* No SPD: split SIMMs into pairs as if they were "DIMM"s. */ if (!spd_present) { - dimm = ((reg_max - reg_min) + 1) >> 2; /* amount of "DIMM"s, also used to determine the maximum "DIMM" size */ - spd_populate(rows, dimm, mem_size >> 10, 4, 1 << (log2i((machines[machine].max_ram >> 10) / dimm)), 0); + dimm = ((reg_max - reg_min) + 1) >> 2; /* amount of "DIMM"s, also used to determine the maximum "DIMM" size */ + spd_populate(rows, dimm, mem_size >> 10, 4, 1 << (log2i((machines[machine].ram.max >> 10) / dimm)), 0); } /* Write DRBs for each row. */ spd_log("SPD: Writing DRBs... regs=[%02X:%02X] unit=%d\n", reg_min, reg_max, drb_unit); for (dimm = 0; dimm <= ((reg_max - reg_min) >> 2); dimm++) { - size = 0; - drb = reg_min + (dimm << 2); + size = 0; + drb = reg_min + (dimm << 2); - regs[drb] = 0xff; - regs[drb + 1] = 0xff; - regs[drb + 2] = 0x00; - regs[drb + 3] = 0xf0; + regs[drb] = 0xff; + regs[drb + 1] = 0xff; + regs[drb + 2] = 0x00; + regs[drb + 3] = 0xf0; - if (spd_modules[dimm] == NULL) - continue; + if (spd_modules[dimm] == NULL) + continue; - if (spd_present) { - /* SPD enabled: use SPD info for this slot, if present. */ - size = (spd_modules[dimm]->row1 + spd_modules[dimm]->row2) >> 1; - } else { - /* No SPD: use the values calculated above. */ - size = (rows[dimm] >> 1); - } + if (spd_present) { + /* SPD enabled: use SPD info for this slot, if present. */ + size = (spd_modules[dimm]->row1 + spd_modules[dimm]->row2) >> 1; + } else { + /* No SPD: use the values calculated above. */ + size = (rows[dimm] >> 1); + } - if (spd_modules[dimm]->row1) - regs[drb + 3] |= 0x06; + if (spd_modules[dimm]->row1) + regs[drb + 3] |= 0x06; - switch (size) { - case 4: - default: - regs[drb + 2] = 0x00; - break; - case 8: - regs[drb + 2] = 0x10; - break; - case 16: - regs[drb + 2] = 0x20; - break; - case 32: - regs[drb + 2] = 0x30; - break; - case 64: - regs[drb + 2] = 0x40; - break; - case 128: - regs[drb + 2] = 0x50; - break; - case 256: - regs[drb + 2] = 0x60; - break; - } + switch (size) { + default: + case 4: + regs[drb + 2] = 0x00; + break; + case 8: + regs[drb + 2] = 0x10; + break; + case 16: + regs[drb + 2] = 0x20; + break; + case 32: + regs[drb + 2] = 0x30; + break; + case 64: + regs[drb + 2] = 0x40; + break; + case 128: + regs[drb + 2] = 0x50; + break; + case 256: + regs[drb + 2] = 0x60; + break; + } - if (spd_modules[dimm]->row2) { - regs[drb + 3] |= 0x01; - regs[drb + 2] |= 0x80; - } + if (spd_modules[dimm]->row2) { + regs[drb + 3] |= 0x01; + regs[drb + 2] |= 0x80; + } - spd_log("SPD: DIMM %i: %02X %02X %02X %02X\n", regs[drb], regs[drb + 1], regs[drb + 2], regs[drb + 3]); + spd_log("SPD: DIMM %i: %02X %02X %02X %02X\n", regs[drb], regs[drb + 1], regs[drb + 2], regs[drb + 3]); } } - static const device_t spd_device = { - "Serial Presence Detect ROMs", - "spd", - DEVICE_ISA, - 0, - spd_init, spd_close, NULL, - { NULL }, NULL, NULL, - NULL + .name = "Serial Presence Detect ROMs", + .internal_name = "spd", + .flags = DEVICE_ISA, + .local = 0, + .init = spd_init, + .close = spd_close, + .reset = NULL, + { .available = NULL }, + .speed_changed = NULL, + .force_redraw = NULL, + .config = NULL }; diff --git a/src/mem/sst_flash.c b/src/mem/sst_flash.c index 1de5e6e32..472a042d1 100644 --- a/src/mem/sst_flash.c +++ b/src/mem/sst_flash.c @@ -1,22 +1,20 @@ /* - * 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. + * 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. + * This file is part of the 86Box distribution. * - * Implementation of an SST flash chip. + * Implementation of an SST flash chip. * * * - * Authors: Sarah Walker, - * Miran Grca, - * Melissa Goad, + * Authors: Miran Grca, + * Jasmine Iwanek, * - * Copyright 2008-2020 Sarah Walker. - * Copyright 2016-2020 Miran Grca. - * Copyright 2020 Melissa Goad. + * Copyright 2016-2020 Miran Grca. + * Copyright 2022-2023 Jasmine Iwanek. */ #include #include @@ -32,62 +30,114 @@ #include <86box/plat.h> #include <86box/m_xt_xi8088.h> +typedef struct sst_t { + uint8_t manufacturer; + uint8_t id; + uint8_t has_bbp; + uint8_t is_39; + uint8_t page_bytes; + uint8_t sdp; + uint8_t bbp_first_8k; + uint8_t bbp_last_8k; -typedef struct sst_t -{ - uint8_t manufacturer, id, has_bbp, is_39, - page_bytes, sdp, bbp_first_8k, bbp_last_8k; + int command_state; + int id_mode; + int dirty; - int command_state, id_mode, - dirty; + uint32_t size; + uint32_t mask; + uint32_t page_mask; + uint32_t page_base; + uint32_t last_addr; - uint32_t size, mask, - page_mask, page_base, - last_addr; - - uint8_t page_buffer[128], - page_dirty[128]; - uint8_t *array; + uint8_t page_buffer[128]; + uint8_t page_dirty[128]; + uint8_t *array; - mem_mapping_t mapping[8], mapping_h[8]; + mem_mapping_t mapping[8]; + mem_mapping_t mapping_h[8]; - pc_timer_t page_write_timer; + pc_timer_t page_write_timer; } sst_t; +static char flash_path[1024]; -static char flash_path[1024]; +#define SST_CHIP_ERASE 0x10 /* Both 29 and 39, 6th cycle */ +#define SST_SDP_DISABLE 0x20 /* Only 29, Software data protect disable and write - treat as write */ +#define SST_SECTOR_ERASE 0x30 /* Only 39, 6th cycle */ +#define W_BOOT_BLOCK_PROT 0x40 /* Only W29C020 */ +#define SST_SET_ID_MODE_ALT 0x60 /* Only 29, 6th cycle */ +#define SST_ERASE 0x80 /* Both 29 and 39 */ + /* With data 60h on 6th cycle, it's alt. ID */ +#define SST_SET_ID_MODE 0x90 /* Both 29 and 39 */ +#define SST_BYTE_PROGRAM 0xa0 /* Both 29 and 39 */ +#define SST_CLEAR_ID_MODE 0xf0 /* Both 29 and 39 */ + /* 1st cycle variant only on 39 */ +#define SST 0xbf /* SST Manufacturer's ID */ -#define SST_CHIP_ERASE 0x10 /* Both 29 and 39, 6th cycle */ -#define SST_SDP_DISABLE 0x20 /* Only 29, Software data protect disable and write - treat as write */ -#define SST_SECTOR_ERASE 0x30 /* Only 39, 6th cycle */ -#define W_BOOT_BLOCK_PROT 0x40 /* Only W29C020 */ -#define SST_SET_ID_MODE_ALT 0x60 /* Only 29, 6th cycle */ -#define SST_ERASE 0x80 /* Both 29 and 39 */ - /* With data 60h on 6th cycle, it's alt. ID */ -#define SST_SET_ID_MODE 0x90 /* Both 29 and 39 */ -#define SST_BYTE_PROGRAM 0xa0 /* Both 29 and 39 */ -#define SST_CLEAR_ID_MODE 0xf0 /* Both 29 and 39 */ - /* 1st cycle variant only on 39 */ +#define SST29EE512 0x5d00 +#define SST29LE_VE512 0x3d00 +#define SST29EE010 0x0700 +#define SST29LE_VE010 0x0800 +#define SST29EE020 0x1000 +#define SST29LE_VE020 0x1200 -#define SST 0xbf /* SST Manufacturer's ID */ -#define SST29EE010 0x0700 -#define SST29LE_VE010 0x0800 -#define SST29EE020 0x1000 -#define SST29LE_VE020 0x1200 -#define SST39SF512 0xb400 -#define SST39SF010 0xb500 -#define SST39SF020 0xb600 -#define SST39SF040 0xb700 +#define SST39SF512 0xb400 +#define SST39SF010 0xb500 +#define SST39SF020 0xb600 +#define SST39SF040 0xb700 -#define WINBOND 0xda /* Winbond Manufacturer's ID */ -#define W29C020 0x4500 +#define SST39LF512 0xd400 +#define SST39LF010 0xd500 +#define SST39LF020 0xd600 +#define SST39LF040 0xd700 +#define SST39LF080 0xd800 +#define SST39LF016 0xd900 -#define SIZE_512K 0x010000 -#define SIZE_1M 0x020000 -#define SIZE_2M 0x040000 -#define SIZE_4M 0x080000 +#if 0 +// 16 wide +#define SST39WF400 0x272f +#define SST39WF400B 0x272e +#define SST39WF800 0x273f +#define SST39WF800B 0x273e +#define SST39WF1601 0xbf274b +#define SST39WF1602 0xbf274a +#define SST39LF100 0x2788 +#define SST39LF200 0x2789 +#define SST39LF400 0x2780 +#define SST39LF800 0x2781 +#define SST39LF160 0x2782 +#endif + +#define SST49LF002 0x5700 +#define SST49LF020 0x6100 +#define SST49LF020A 0x5200 +#define SST49LF003 0x1b00 +#define SST49LF004 0x6000 +#define SST49LF004C 0x5400 +#define SST49LF040 0x5100 +#define SST49LF008 0x5a00 +#define SST49LF008C 0x5900 +#define SST49LF080 0x5b00 +#define SST49LF030 0x1c00 +#define SST49LF160 0x4c00 +#define SST49LF016 0x5c00 + +#define WINBOND 0xda /* Winbond Manufacturer's ID */ +#define W29C512 0xc800 +#define W29C010 0xc100 +#define W29C020 0x4500 +#define W29C040 0x4600 + +#define SIZE_512K 0x010000 +#define SIZE_1M 0x020000 +#define SIZE_2M 0x040000 +#define SIZE_3M 0x060000 +#define SIZE_4M 0x080000 +#define SIZE_8M 0x100000 +#define SIZE_16M 0x200000 static void sst_sector_erase(sst_t *dev, uint32_t addr) @@ -95,323 +145,327 @@ sst_sector_erase(sst_t *dev, uint32_t addr) uint32_t base = addr & (dev->mask & ~0xfff); if ((base < 0x2000) && (dev->bbp_first_8k & 0x01)) - return; + return; else if ((base >= (dev->size - 0x2000)) && (dev->bbp_last_8k & 0x01)) - return; + return; memset(&dev->array[base], 0xff, 4096); dev->dirty = 1; } - static void sst_new_command(sst_t *dev, uint32_t addr, uint8_t val) { - uint32_t base = 0x00000, size = dev->size; + uint32_t base = 0x00000; + uint32_t size = dev->size; - if (dev->command_state == 5) switch (val) { - case SST_CHIP_ERASE: - if (dev->bbp_first_8k & 0x01) { - base += 0x2000; - size -= 0x2000; - } + if (dev->command_state == 5) + switch (val) { + case SST_CHIP_ERASE: + if (dev->bbp_first_8k & 0x01) { + base += 0x2000; + size -= 0x2000; + } - if (dev->bbp_last_8k & 0x01) - size -= 0x2000; + if (dev->bbp_last_8k & 0x01) + size -= 0x2000; - memset(&(dev->array[base]), 0xff, size); - dev->command_state = 0; - break; + memset(&(dev->array[base]), 0xff, size); + dev->command_state = 0; + break; - case SST_SDP_DISABLE: - if (!dev->is_39) - dev->sdp = 0; - dev->command_state = 0; - break; + case SST_SDP_DISABLE: + if (!dev->is_39) + dev->sdp = 0; + dev->command_state = 0; + break; - case SST_SECTOR_ERASE: - if (dev->is_39) - sst_sector_erase(dev, addr); - dev->command_state = 0; - break; + case SST_SECTOR_ERASE: + if (dev->is_39) + sst_sector_erase(dev, addr); + dev->command_state = 0; + break; - case SST_SET_ID_MODE_ALT: - dev->id_mode = 1; - dev->command_state = 0; - break; + case SST_SET_ID_MODE_ALT: + dev->id_mode = 1; + dev->command_state = 0; + break; - default: - dev->command_state = 0; - break; - } else switch (val) { - case SST_ERASE: - dev->command_state = 3; - break; + default: + dev->command_state = 0; + break; + } + else + switch (val) { + case SST_ERASE: + dev->command_state = 3; + break; - case SST_SET_ID_MODE: - dev->id_mode = 1; - dev->command_state = 0; - break; + case SST_SET_ID_MODE: + dev->id_mode = 1; + dev->command_state = 0; + break; - case SST_BYTE_PROGRAM: - if (!dev->is_39) { - dev->sdp = 1; - memset(dev->page_buffer, 0xff, 128); - memset(dev->page_dirty, 0x00, 128); - dev->page_bytes = 0; - dev->last_addr = 0xffffffff; - timer_on_auto(&dev->page_write_timer, 210.0); - } - dev->command_state = 6; - break; + case SST_BYTE_PROGRAM: + if (!dev->is_39) { + dev->sdp = 1; + memset(dev->page_buffer, 0xff, 128); + memset(dev->page_dirty, 0x00, 128); + dev->page_bytes = 0; + dev->last_addr = 0xffffffff; + timer_on_auto(&dev->page_write_timer, 210.0); + } + dev->command_state = 6; + break; - case W_BOOT_BLOCK_PROT: - dev->command_state = dev->has_bbp ? 8 : 0; - break; + case W_BOOT_BLOCK_PROT: + dev->command_state = dev->has_bbp ? 8 : 0; + break; - case SST_CLEAR_ID_MODE: - dev->id_mode = 0; - dev->command_state = 0; - break; + case SST_CLEAR_ID_MODE: + dev->id_mode = 0; + dev->command_state = 0; + break; - default: - dev->command_state = 0; - break; - } + default: + dev->command_state = 0; + break; + } } - static void sst_page_write(void *priv) { sst_t *dev = (sst_t *) priv; - int i; if (dev->last_addr != 0xffffffff) { - dev->page_base = dev->last_addr & dev->page_mask; - for (i = 0; i < 128; i++) { - if (dev->page_dirty[i]) { - if (((dev->page_base + i) < 0x2000) && (dev->bbp_first_8k & 0x01)) - continue; - else if (((dev->page_base + i) >= (dev->size - 0x2000)) && (dev->bbp_last_8k & 0x01)) - continue; + dev->page_base = dev->last_addr & dev->page_mask; + for (uint8_t i = 0; i < 128; i++) { + if (dev->page_dirty[i]) { + if (((dev->page_base + i) < 0x2000) && (dev->bbp_first_8k & 0x01)) + continue; + else if (((dev->page_base + i) >= (dev->size - 0x2000)) && (dev->bbp_last_8k & 0x01)) + continue; - dev->array[dev->page_base + i] = dev->page_buffer[i]; - dev->dirty |= 1; - } - } + dev->array[dev->page_base + i] = dev->page_buffer[i]; + dev->dirty |= 1; + } + } } - dev->page_bytes = 0; + dev->page_bytes = 0; dev->command_state = 0; timer_disable(&dev->page_write_timer); } - static uint8_t -sst_read_id(uint32_t addr, void *p) +sst_read_id(uint32_t addr, void *priv) { - sst_t *dev = (sst_t *) p; - uint8_t ret = 0x00; + const sst_t *dev = (sst_t *) priv; + uint8_t ret = 0x00; if ((addr & 0xffff) == 0) - ret = dev->manufacturer; + ret = dev->manufacturer; else if ((addr & 0xffff) == 1) - ret = dev->id; + ret = dev->id; #ifdef UNKNOWN_FLASH else if ((addr & 0xffff) == 0x100) - ret = 0x1c; + ret = 0x1c; else if ((addr & 0xffff) == 0x101) - ret = 0x92; + ret = 0x92; #endif else if (dev->has_bbp) { - if (addr == 0x00002) - ret = dev->bbp_first_8k; - else if (addr == 0x3fff2) - ret = dev->bbp_last_8k; + if (addr == 0x00002) + ret = dev->bbp_first_8k; + else if (addr == 0x3fff2) + ret = dev->bbp_last_8k; } return ret; } - static void sst_buf_write(sst_t *dev, uint32_t addr, uint8_t val) { dev->page_buffer[addr & 0x0000007f] = val; - dev->page_dirty[addr & 0x0000007f] = 1; + dev->page_dirty[addr & 0x0000007f] = 1; dev->page_bytes++; dev->last_addr = addr; if (dev->page_bytes >= 128) { - sst_page_write(dev); + sst_page_write(dev); } else - timer_on_auto(&dev->page_write_timer, 210.0); + timer_on_auto(&dev->page_write_timer, 210.0); } - static void -sst_write(uint32_t addr, uint8_t val, void *p) +sst_write(uint32_t addr, uint8_t val, void *priv) { - sst_t *dev = (sst_t *) p; + sst_t *dev = (sst_t *) priv; switch (dev->command_state) { - case 0: - case 3: - /* 1st and 4th Bus Write Cycle */ - if ((val == 0xf0) && dev->is_39 && (dev->command_state == 0)) { - if (dev->id_mode) - dev->id_mode = 0; - dev->command_state = 0; - } else if (((addr & 0x7fff) == 0x5555) && (val == 0xaa)) - dev->command_state++; - else { - if (!dev->is_39 && !dev->sdp && (dev->command_state == 0)) { - /* 29 series, software data protection off, start loading the page. */ - memset(dev->page_buffer, 0xff, 128); - memset(dev->page_dirty, 0x00, 128); - dev->page_bytes = 0; - dev->command_state = 7; - sst_buf_write(dev, addr, val); - } else - dev->command_state = 0; - } - break; - case 1: - case 4: - /* 2nd and 5th Bus Write Cycle */ - if (((addr & 0x7fff) == 0x2aaa) && (val == 0x55)) - dev->command_state++; - else - dev->command_state = 0; - break; - case 2: - case 5: - /* 3rd and 6th Bus Write Cycle */ - if ((dev->command_state == 5) && (val == SST_SECTOR_ERASE)) { - /* Sector erase - can be on any address. */ - sst_new_command(dev, addr, val); - } else if ((addr & 0x7fff) == 0x5555) - sst_new_command(dev, addr, val); - else - dev->command_state = 0; - break; - case 6: - /* Page Load Cycle (29) / Data Write Cycle (39SF) */ - if (dev->is_39) { - dev->command_state = 0; + case 0: + case 3: + /* 1st and 4th Bus Write Cycle */ + if ((val == 0xf0) && dev->is_39 && (dev->command_state == 0)) { + if (dev->id_mode) + dev->id_mode = 0; + dev->command_state = 0; + } else if (((addr & 0x7fff) == 0x5555) && (val == 0xaa)) + dev->command_state++; + else { + if (!dev->is_39 && !dev->sdp && (dev->command_state == 0)) { + /* 29 series, software data protection off, start loading the page. */ + memset(dev->page_buffer, 0xff, 128); + memset(dev->page_dirty, 0x00, 128); + dev->page_bytes = 0; + dev->command_state = 7; + sst_buf_write(dev, addr, val); + } else + dev->command_state = 0; + } + break; + case 1: + case 4: + /* 2nd and 5th Bus Write Cycle */ + if (((addr & 0x7fff) == 0x2aaa) && (val == 0x55)) + dev->command_state++; + else + dev->command_state = 0; + break; + case 2: + case 5: + /* 3rd and 6th Bus Write Cycle */ + if ((dev->command_state == 5) && (val == SST_SECTOR_ERASE)) { + /* Sector erase - can be on any address. */ + sst_new_command(dev, addr, val); + } else if ((addr & 0x7fff) == 0x5555) + sst_new_command(dev, addr, val); + else + dev->command_state = 0; + break; + case 6: + /* Page Load Cycle (29) / Data Write Cycle (39SF) */ + if (dev->is_39) { + dev->command_state = 0; - dev->array[addr & dev->mask] = val; - dev->dirty = 1; - } else { - dev->command_state++; - sst_buf_write(dev, addr, val); - } - break; - case 7: - if (!dev->is_39) - sst_buf_write(dev, addr, val); - break; - case 8: - if ((addr == 0x00000) && (val == 0x00)) - dev->bbp_first_8k = 0xff; - else if ((addr == 0x3ffff) && (val == 0xff)) - dev->bbp_last_8k = 0xff; - dev->command_state = 0; - break; + dev->array[addr & dev->mask] = val; + dev->dirty = 1; + } else { + dev->command_state++; + sst_buf_write(dev, addr, val); + } + break; + case 7: + if (!dev->is_39) + sst_buf_write(dev, addr, val); + break; + case 8: + if ((addr == 0x00000) && (val == 0x00)) + dev->bbp_first_8k = 0xff; + else if ((addr == 0x3ffff) && (val == 0xff)) + dev->bbp_last_8k = 0xff; + dev->command_state = 0; + break; + + default: + break; } } - static uint8_t -sst_read(uint32_t addr, void *p) +sst_read(uint32_t addr, void *priv) { - sst_t *dev = (sst_t *) p; - uint8_t ret = 0xff; + const sst_t *dev = (sst_t *) priv; + uint8_t ret = 0xff; addr &= 0x000fffff; if (dev->id_mode) - ret = sst_read_id(addr, p); + ret = sst_read_id(addr, priv); else { - if ((addr >= biosaddr) && (addr <= (biosaddr + biosmask))) - ret = dev->array[addr - biosaddr]; + if ((addr >= biosaddr) && (addr <= (biosaddr + biosmask))) + ret = dev->array[addr - biosaddr]; } return ret; } - static uint16_t -sst_readw(uint32_t addr, void *p) +sst_readw(uint32_t addr, void *priv) { - sst_t *dev = (sst_t *) p; + sst_t *dev = (sst_t *) priv; uint16_t ret = 0xffff; addr &= 0x000fffff; if (dev->id_mode) - ret = sst_read(addr, p) | (sst_read(addr + 1, p) << 8); + ret = sst_read(addr, priv) | (sst_read(addr + 1, priv) << 8); else { - if ((addr >= biosaddr) && (addr <= (biosaddr + biosmask))) - ret = *(uint16_t *)&dev->array[addr - biosaddr]; + if ((addr >= biosaddr) && (addr <= (biosaddr + biosmask))) + ret = *(uint16_t *) &dev->array[addr - biosaddr]; } return ret; } - static uint32_t -sst_readl(uint32_t addr, void *p) +sst_readl(uint32_t addr, void *priv) { - sst_t *dev = (sst_t *) p; + sst_t *dev = (sst_t *) priv; uint32_t ret = 0xffffffff; addr &= 0x000fffff; if (dev->id_mode) - ret = sst_readw(addr, p) | (sst_readw(addr + 2, p) << 16); + ret = sst_readw(addr, priv) | (sst_readw(addr + 2, priv) << 16); else { - if ((addr >= biosaddr) && (addr <= (biosaddr + biosmask))) - ret = *(uint32_t *)&dev->array[addr - biosaddr]; + if ((addr >= biosaddr) && (addr <= (biosaddr + biosmask))) + ret = *(uint32_t *) &dev->array[addr - biosaddr]; } return ret; } - static void sst_add_mappings(sst_t *dev) { - int i = 0, count; - uint32_t base, fbase; + int count; + uint32_t base; + uint32_t fbase; uint32_t root_base; - count = dev->size >> 16; + count = dev->size >> 16; root_base = 0x100000 - dev->size; - for (i = 0; i < count; i++) { - base = root_base + (i << 16); - fbase = base & biosmask; + for (int i = 0; i < count; i++) { + base = root_base + (i << 16); + fbase = base & biosmask; - memcpy(&dev->array[fbase], &rom[base & biosmask], 0x10000); + memcpy(&dev->array[fbase], &rom[base & biosmask], 0x10000); - if (base >= 0xe0000) { - mem_mapping_add(&(dev->mapping[i]), base, 0x10000, - sst_read, sst_readw, sst_readl, - sst_write, NULL, NULL, - dev->array + fbase, MEM_MAPPING_EXTERNAL|MEM_MAPPING_ROM|MEM_MAPPING_ROMCS, (void *) dev); - } - mem_mapping_add(&(dev->mapping_h[i]), (base | (cpu_16bitbus ? 0xf00000 : 0xfff00000)), 0x10000, - sst_read, sst_readw, sst_readl, - sst_write, NULL, NULL, - dev->array + fbase, MEM_MAPPING_EXTERNAL|MEM_MAPPING_ROM|MEM_MAPPING_ROMCS, (void *) dev); + if (base >= 0xe0000) { + mem_mapping_add(&(dev->mapping[i]), base, 0x10000, + sst_read, sst_readw, sst_readl, + sst_write, NULL, NULL, + dev->array + fbase, MEM_MAPPING_EXTERNAL | MEM_MAPPING_ROM | MEM_MAPPING_ROMCS, (void *) dev); + } + if (is6117) { + mem_mapping_add(&(dev->mapping_h[i]), (base | 0x3f00000), 0x10000, + sst_read, sst_readw, sst_readl, + sst_write, NULL, NULL, + dev->array + fbase, MEM_MAPPING_EXTERNAL | MEM_MAPPING_ROM | MEM_MAPPING_ROMCS, (void *) dev); + } else { + mem_mapping_add(&(dev->mapping_h[i]), (base | (cpu_16bitbus ? 0xf00000 : 0xfff00000)), 0x10000, + sst_read, sst_readw, sst_readl, + sst_write, NULL, NULL, + dev->array + fbase, MEM_MAPPING_EXTERNAL | MEM_MAPPING_ROM | MEM_MAPPING_ROMCS, (void *) dev); + } } } - static void * sst_init(const device_t *info) { - FILE *f; + FILE *fp; sst_t *dev = malloc(sizeof(sst_t)); memset(dev, 0, sizeof(sst_t)); @@ -424,48 +478,47 @@ sst_init(const device_t *info) memset(dev->array, 0xff, biosmask + 1); dev->manufacturer = info->local & 0xff; - dev->id = (info->local >> 8) & 0xff; - dev->has_bbp = (dev->manufacturer == WINBOND) && ((info->local & 0xff00) >= W29C020); - dev->is_39 = (dev->manufacturer == SST) && ((info->local & 0xff00) >= SST39SF512); + dev->id = (info->local >> 8) & 0xff; + dev->has_bbp = (dev->manufacturer == WINBOND) && ((info->local & 0xff00) >= W29C020); + dev->is_39 = (dev->manufacturer == SST) && ((info->local & 0xff00) >= SST39SF512); dev->size = info->local & 0xffff0000; if ((dev->size == 0x20000) && (strstr(machine_get_internal_name_ex(machine), "xi8088")) && !xi8088_bios_128kb()) - dev->size = 0x10000; + dev->size = 0x10000; - dev->mask = dev->size - 1; - dev->page_mask = dev->mask & 0xffffff80; /* Filter out A0-A6. */ - dev->sdp = 1; + dev->mask = dev->size - 1; + dev->page_mask = dev->mask & 0xffffff80; /* Filter out A0-A6. */ + dev->sdp = 1; dev->bbp_first_8k = dev->bbp_last_8k = 0xfe; sst_add_mappings(dev); - f = nvr_fopen(flash_path, "rb"); - if (f) { - if (fread(&(dev->array[0x00000]), 1, dev->size, f) != dev->size) - fatal("Less than %i bytes read from the SST Flash ROM file\n", dev->size); - fclose(f); + fp = nvr_fopen(flash_path, "rb"); + if (fp) { + if (fread(&(dev->array[0x00000]), 1, dev->size, fp) != dev->size) + pclog("Less than %i bytes read from the SST Flash ROM file\n", dev->size); + fclose(fp); } else - dev->dirty = 1; /* It is by definition dirty on creation. */ + dev->dirty = 1; /* It is by definition dirty on creation. */ if (!dev->is_39) - timer_add(&dev->page_write_timer, sst_page_write, dev, 0); + timer_add(&dev->page_write_timer, sst_page_write, dev, 0); return dev; } - static void -sst_close(void *p) +sst_close(void *priv) { - FILE *f; - sst_t *dev = (sst_t *)p; + FILE *fp; + sst_t *dev = (sst_t *) priv; if (dev->dirty) { - f = nvr_fopen(flash_path, "wb"); - if (f != NULL) { - fwrite(&(dev->array[0x00000]), dev->size, 1, f); - fclose(f); - } + fp = nvr_fopen(flash_path, "wb"); + if (fp != NULL) { + fwrite(&(dev->array[0x00000]), dev->size, 1, fp); + fclose(fp); + } } free(dev->array); @@ -474,79 +527,417 @@ sst_close(void *p) free(dev); } - -const device_t sst_flash_29ee010_device = -{ - "SST 29EE010 Flash BIOS", - "sst_flash_29ee010", - 0, - SST | SST29EE010 | SIZE_1M, - sst_init, - sst_close, - NULL, - { NULL }, NULL, NULL, NULL +const device_t sst_flash_29ee010_device = { + .name = "SST 29EE010 Flash BIOS", + .internal_name = "sst_flash_29ee010", + .flags = 0, + .local = SST | SST29EE010 | SIZE_1M, + .init = sst_init, + .close = sst_close, + .reset = NULL, + { .available = NULL }, + .speed_changed = NULL, + .force_redraw = NULL, + .config = NULL }; - -const device_t sst_flash_29ee020_device = -{ - "SST 29EE020 Flash BIOS", - "sst_flash_29ee020", - 0, - SST | SST29EE020 | SIZE_2M, - sst_init, - sst_close, - NULL, - { NULL }, NULL, NULL, NULL +const device_t sst_flash_29ee020_device = { + .name = "SST 29EE020 Flash BIOS", + .internal_name = "sst_flash_29ee020", + .flags = 0, + .local = SST | SST29EE020 | SIZE_2M, + .init = sst_init, + .close = sst_close, + .reset = NULL, + { .available = NULL }, + .speed_changed = NULL, + .force_redraw = NULL, + .config = NULL }; - -const device_t winbond_flash_w29c020_device = -{ - "Winbond W29C020 Flash BIOS", - "winbond_flash_w29c020", - 0, - WINBOND | W29C020 | SIZE_2M, - sst_init, - sst_close, - NULL, - { NULL }, NULL, NULL, NULL +const device_t winbond_flash_w29c512_device = { + .name = "Winbond W29C512 Flash BIOS", + .internal_name = "winbond_flash_w29c512", + .flags = 0, + .local = WINBOND | W29C010 | SIZE_512K, + .init = sst_init, + .close = sst_close, + .reset = NULL, + { .available = NULL }, + .speed_changed = NULL, + .force_redraw = NULL, + .config = NULL }; - -const device_t sst_flash_39sf010_device = -{ - "SST 39SF010 Flash BIOS", - "sst_flash_39sf010", - 0, - SST | SST39SF010 | SIZE_1M, - sst_init, - sst_close, - NULL, - { NULL }, NULL, NULL, NULL +const device_t winbond_flash_w29c010_device = { + .name = "Winbond W29C010 Flash BIOS", + .internal_name = "winbond_flash_w29c010", + .flags = 0, + .local = WINBOND | W29C010 | SIZE_1M, + .init = sst_init, + .close = sst_close, + .reset = NULL, + { .available = NULL }, + .speed_changed = NULL, + .force_redraw = NULL, + .config = NULL }; - -const device_t sst_flash_39sf020_device = -{ - "SST 39SF020 Flash BIOS", - "sst_flash_39sf020", - 0, - SST | SST39SF020 | SIZE_2M, - sst_init, - sst_close, - NULL, - { NULL }, NULL, NULL, NULL +const device_t winbond_flash_w29c020_device = { + .name = "Winbond W29C020 Flash BIOS", + .internal_name = "winbond_flash_w29c020", + .flags = 0, + .local = WINBOND | W29C020 | SIZE_2M, + .init = sst_init, + .close = sst_close, + .reset = NULL, + { .available = NULL }, + .speed_changed = NULL, + .force_redraw = NULL, + .config = NULL }; -const device_t sst_flash_39sf040_device = -{ - "SST 39SF040 Flash BIOS", - "sst_flash_39sf040", - 0, - SST | SST39SF040 | SIZE_4M, - sst_init, - sst_close, - NULL, - { NULL }, NULL, NULL, NULL +const device_t winbond_flash_w29c040_device = { + .name = "Winbond W29C040 Flash BIOS", + .internal_name = "winbond_flash_w29c040", + .flags = 0, + .local = WINBOND | W29C040 | SIZE_4M, + .init = sst_init, + .close = sst_close, + .reset = NULL, + { .available = NULL }, + .speed_changed = NULL, + .force_redraw = NULL, + .config = NULL +}; + +const device_t sst_flash_39sf512_device = { + .name = "SST 39SF512 Flash BIOS", + .internal_name = "sst_flash_39sf512", + .flags = 0, + .local = SST | SST39SF512 | SIZE_512K, + .init = sst_init, + .close = sst_close, + .reset = NULL, + { .available = NULL }, + .speed_changed = NULL, + .force_redraw = NULL, + .config = NULL +}; + +const device_t sst_flash_39sf010_device = { + .name = "SST 39SF010 Flash BIOS", + .internal_name = "sst_flash_39sf010", + .flags = 0, + .local = SST | SST39SF010 | SIZE_1M, + .init = sst_init, + .close = sst_close, + .reset = NULL, + { .available = NULL }, + .speed_changed = NULL, + .force_redraw = NULL, + .config = NULL +}; + +const device_t sst_flash_39sf020_device = { + .name = "SST 39SF020 Flash BIOS", + .internal_name = "sst_flash_39sf020", + .flags = 0, + .local = SST | SST39SF020 | SIZE_2M, + .init = sst_init, + .close = sst_close, + .reset = NULL, + { .available = NULL }, + .speed_changed = NULL, + .force_redraw = NULL, + .config = NULL +}; + +const device_t sst_flash_39sf040_device = { + .name = "SST 39SF040 Flash BIOS", + .internal_name = "sst_flash_39sf040", + .flags = 0, + .local = SST | SST39SF040 | SIZE_4M, + .init = sst_init, + .close = sst_close, + .reset = NULL, + { .available = NULL }, + .speed_changed = NULL, + .force_redraw = NULL, + .config = NULL +}; + +const device_t sst_flash_39lf512_device = { + .name = "SST 39LF512 Flash BIOS", + .internal_name = "sst_flash_39lf512", + .flags = 0, + .local = SST | SST39LF512 | SIZE_512K, + .init = sst_init, + .close = sst_close, + .reset = NULL, + { .available = NULL }, + .speed_changed = NULL, + .force_redraw = NULL, + .config = NULL +}; + +const device_t sst_flash_39lf010_device = { + .name = "SST 39LF010 Flash BIOS", + .internal_name = "sst_flash_39lf010", + .flags = 0, + .local = SST | SST39LF010 | SIZE_1M, + .init = sst_init, + .close = sst_close, + .reset = NULL, + { .available = NULL }, + .speed_changed = NULL, + .force_redraw = NULL, + .config = NULL +}; + +const device_t sst_flash_39lf020_device = { + .name = "SST 39LF020 Flash BIOS", + .internal_name = "sst_flash_39lf020", + .flags = 0, + .local = SST | SST39LF020 | SIZE_2M, + .init = sst_init, + .close = sst_close, + .reset = NULL, + { .available = NULL }, + .speed_changed = NULL, + .force_redraw = NULL, + .config = NULL +}; + +const device_t sst_flash_39lf040_device = { + .name = "SST 39LF040 Flash BIOS", + .internal_name = "sst_flash_39lf040", + .flags = 0, + .local = SST | SST39LF040 | SIZE_4M, + .init = sst_init, + .close = sst_close, + .reset = NULL, + { .available = NULL }, + .speed_changed = NULL, + .force_redraw = NULL, + .config = NULL +}; + +const device_t sst_flash_39lf080_device = { + .name = "SST 39LF080 Flash BIOS", + .internal_name = "sst_flash_39lf080", + .flags = 0, + .local = SST | SST39LF080 | SIZE_8M, + .init = sst_init, + .close = sst_close, + .reset = NULL, + { .available = NULL }, + .speed_changed = NULL, + .force_redraw = NULL, + .config = NULL +}; + +const device_t sst_flash_39lf016_device = { + .name = "SST 39LF016 Flash BIOS", + .internal_name = "sst_flash_39lf016", + .flags = 0, + .local = SST | SST39LF016 | SIZE_16M, + .init = sst_init, + .close = sst_close, + .reset = NULL, + { .available = NULL }, + .speed_changed = NULL, + .force_redraw = NULL, + .config = NULL +}; + +/* + * Firmware Hubs. The FWH signals are not implemented yet. Firmware Hubs do write cycles + * to read/write on the flash. SST Flashes still do traditional flashing via PP Mode. Our + * BIOS firmwares don't seem to utilize FWH R/W thus the FWH ports remain unknown for an + * implementation. We just contain the ID's so the BIOS can do ESCD & DMI writes with no + * worries. + */ + +const device_t sst_flash_49lf002_device = { + .name = "SST 49LF002 Firmware Hub", + .internal_name = "sst_flash_49lf002", + .flags = 0, + .local = SST | SST49LF002 | SIZE_2M, + .init = sst_init, + .close = sst_close, + .reset = NULL, + { .available = NULL }, + .speed_changed = NULL, + .force_redraw = NULL, + .config = NULL +}; + +const device_t sst_flash_49lf020_device = { + .name = "SST 49LF020 Firmware Hub", + .internal_name = "sst_flash_49lf0020", + .flags = 0, + .local = SST | SST49LF020 | SIZE_2M, + .init = sst_init, + .close = sst_close, + .reset = NULL, + { .available = NULL }, + .speed_changed = NULL, + .force_redraw = NULL, + .config = NULL +}; + +const device_t sst_flash_49lf020a_device = { + .name = "SST 49LF020A Firmware Hub", + .internal_name = "sst_flash_49lf0020a", + .flags = 0, + .local = SST | SST49LF020A | SIZE_2M, + .init = sst_init, + .close = sst_close, + .reset = NULL, + { .available = NULL }, + .speed_changed = NULL, + .force_redraw = NULL, + .config = NULL +}; + +const device_t sst_flash_49lf003_device = { + .name = "SST 49LF003 Firmware Hub", + .internal_name = "sst_flash_49lf003", + .flags = 0, + .local = SST | SST49LF003 | SIZE_3M, + .init = sst_init, + .close = sst_close, + .reset = NULL, + { .available = NULL }, + .speed_changed = NULL, + .force_redraw = NULL, + .config = NULL +}; + +const device_t sst_flash_49lf030_device = { + .name = "SST 49LF030 Firmware Hub", + .internal_name = "sst_flash_49lf030", + .flags = 0, + .local = SST | SST49LF030 | SIZE_3M, + .init = sst_init, + .close = sst_close, + .reset = NULL, + { .available = NULL }, + .speed_changed = NULL, + .force_redraw = NULL, + .config = NULL +}; + +const device_t sst_flash_49lf004_device = { + .name = "SST 49LF004 Firmware Hub", + .internal_name = "sst_flash_49lf004", + .flags = 0, + .local = SST | SST49LF004 | SIZE_4M, + .init = sst_init, + .close = sst_close, + .reset = NULL, + { .available = NULL }, + .speed_changed = NULL, + .force_redraw = NULL, + .config = NULL +}; + +const device_t sst_flash_49lf004c_device = { + .name = "SST 49LF004C Firmware Hub", + .internal_name = "sst_flash_49lf004c", + .flags = 0, + .local = SST | SST49LF004C | SIZE_4M, + .init = sst_init, + .close = sst_close, + .reset = NULL, + { .available = NULL }, + .speed_changed = NULL, + .force_redraw = NULL, + .config = NULL +}; + +const device_t sst_flash_49lf040_device = { + .name = "SST 49LF040 Firmware Hub", + .internal_name = "sst_flash_49lf040", + .flags = 0, + .local = SST | SST49LF040 | SIZE_4M, + .init = sst_init, + .close = sst_close, + .reset = NULL, + { .available = NULL }, + .speed_changed = NULL, + .force_redraw = NULL, + .config = NULL +}; + +const device_t sst_flash_49lf008_device = { + .name = "SST 49LF008 Firmware Hub", + .internal_name = "sst_flash_49lf008", + .flags = 0, + .local = SST | SST49LF008 | SIZE_8M, + .init = sst_init, + .close = sst_close, + .reset = NULL, + { .available = NULL }, + .speed_changed = NULL, + .force_redraw = NULL, + .config = NULL +}; + +const device_t sst_flash_49lf008c_device = { + .name = "SST 49LF008C Firmware Hub", + .internal_name = "sst_flash_49lf008c", + .flags = 0, + .local = SST | SST49LF008C | SIZE_8M, + .init = sst_init, + .close = sst_close, + .reset = NULL, + { .available = NULL }, + .speed_changed = NULL, + .force_redraw = NULL, + .config = NULL +}; + +const device_t sst_flash_49lf080_device = { + .name = "SST 49LF080 Firmware Hub", + .internal_name = "sst_flash_49lf080", + .flags = 0, + .local = SST | SST49LF080 | SIZE_8M, + .init = sst_init, + .close = sst_close, + .reset = NULL, + { .available = NULL }, + .speed_changed = NULL, + .force_redraw = NULL, + .config = NULL +}; + +const device_t sst_flash_49lf016_device = { + .name = "SST 49LF016 Firmware Hub", + .internal_name = "sst_flash_49lf016", + .flags = 0, + .local = SST | SST49LF016 | SIZE_16M, + .init = sst_init, + .close = sst_close, + .reset = NULL, + { .available = NULL }, + .speed_changed = NULL, + .force_redraw = NULL, + .config = NULL +}; + +const device_t sst_flash_49lf160_device = { + + .name = "SST 49LF160 Firmware Hub", + .internal_name = "sst_flash_49lf160", + .flags = 0, + .local = SST | SST49LF160 | SIZE_16M, + .init = sst_init, + .close = sst_close, + .reset = NULL, + { .available = NULL }, + .speed_changed = NULL, + .force_redraw = NULL, + .config = NULL }; diff --git a/src/minitrace/minitrace.c b/src/minitrace/minitrace.c index 32d2ebcae..290486ec5 100644 --- a/src/minitrace/minitrace.c +++ b/src/minitrace/minitrace.c @@ -1,6 +1,6 @@ // minitrace // Copyright 2014 by Henrik RydgÃ¥rd -// http://www.github.com/hrydgard/minitrace +// https://www.github.com/hrydgard/minitrace // Released under the MIT license. // See minitrace.h for basic documentation. @@ -30,9 +30,9 @@ #include #include #include -#include #endif +#include #include #ifdef __GNUC__ @@ -48,20 +48,20 @@ // Ugh, this struct is already pretty heavy. // Will probably need to move arguments to a second buffer to support more than one. typedef struct raw_event { - const char *name; - const char *cat; - void *id; - int64_t ts; - uint32_t pid; - uint32_t tid; - char ph; - mtr_arg_type arg_type; - const char *arg_name; - union { - const char *a_str; - int a_int; - double a_double; - }; + const char *name; + const char *cat; + void *id; + int64_t ts; + uint32_t pid; + uint32_t tid; + char ph; + mtr_arg_type arg_type; + const char *arg_name; + union { + const char *a_str; + int a_int; + double a_double; + }; } raw_event_t; static raw_event_t *event_buffer; @@ -73,8 +73,8 @@ static int is_flushing = FALSE; static int events_in_progress = 0; static int64_t time_offset; static int first_line = 1; -static FILE *f; -static __thread int cur_thread_id; // Thread local storage +static FILE *fp; +static __thread int cur_thread_id; // Thread local storage static int cur_process_id; static pthread_mutex_t mutex; static pthread_mutex_t event_mutex; @@ -89,44 +89,44 @@ void mtr_flush_with_state(int); // Tiny portability layer. // Exposes: -// get_cur_thread_id() -// get_cur_process_id() -// mtr_time_s() -// pthread basics +// get_cur_thread_id() +// get_cur_process_id() +// mtr_time_s() +// pthread basics #ifdef _WIN32 -static int get_cur_thread_id() { - return (int)GetCurrentThreadId(); +static int get_cur_thread_id(void) { + return (int)GetCurrentThreadId(); } -static int get_cur_process_id() { - return (int)GetCurrentProcessId(); +static int get_cur_process_id(void) { + return (int)GetCurrentProcessId(); } static uint64_t _frequency = 0; static uint64_t _starttime = 0; -double mtr_time_s() { - if (_frequency == 0) { - QueryPerformanceFrequency((LARGE_INTEGER*)&_frequency); - QueryPerformanceCounter((LARGE_INTEGER*)&_starttime); - } - __int64 time; - QueryPerformanceCounter((LARGE_INTEGER*)&time); - return ((double) (time - _starttime) / (double) _frequency); +double mtr_time_s(void) { + if (_frequency == 0) { + QueryPerformanceFrequency((LARGE_INTEGER*)&_frequency); + QueryPerformanceCounter((LARGE_INTEGER*)&_starttime); + } + __int64 time; + QueryPerformanceCounter((LARGE_INTEGER*)&time); + return ((double) (time - _starttime) / (double) _frequency); } // Ctrl+C handling for Windows console apps static BOOL WINAPI CtrlHandler(DWORD fdwCtrlType) { - if (atomic_load(&is_tracing) && fdwCtrlType == CTRL_C_EVENT) { - printf("Ctrl-C detected! Flushing trace and shutting down.\n\n"); - mtr_flush(); - mtr_shutdown(); - } - ExitProcess(1); + if (atomic_load(&is_tracing) && fdwCtrlType == CTRL_C_EVENT) { + printf("Ctrl-C detected! Flushing trace and shutting down.\n\n"); + mtr_flush(); + mtr_shutdown(); + } + ExitProcess(1); } -void mtr_register_sigint_handler() { - // For console apps: - SetConsoleCtrlHandler(&CtrlHandler, TRUE); +void mtr_register_sigint_handler(void) { + // For console apps: + SetConsoleCtrlHandler(&CtrlHandler, TRUE); } HANDLE thread_handle; @@ -154,11 +154,11 @@ static void join_flushing_thread(void) { #else -static inline int get_cur_thread_id() { - return (int)(intptr_t)pthread_self(); +static inline int get_cur_thread_id(void) { + return (int)(intptr_t)pthread_self(); } -static inline int get_cur_process_id() { - return (int)getpid(); +static inline int get_cur_process_id(void) { + return (int)getpid(); } static pthread_t thread_handle = 0; @@ -188,378 +188,384 @@ static void join_flushing_thread(void) { #if defined(BLACKBERRY) double mtr_time_s() { - struct timespec time; - clock_gettime(CLOCK_MONOTONIC, &time); // Linux must use CLOCK_MONOTONIC_RAW due to time warps - return time.tv_sec + time.tv_nsec / 1.0e9; + struct timespec time; + clock_gettime(CLOCK_MONOTONIC, &time); // Linux must use CLOCK_MONOTONIC_RAW due to time warps + return time.tv_sec + time.tv_nsec / 1.0e9; } #else -double mtr_time_s() { - static time_t start; - struct timeval tv; - gettimeofday(&tv, NULL); - if (start == 0) { - start = tv.tv_sec; - } - tv.tv_sec -= start; - return (double)tv.tv_sec + (double)tv.tv_usec / 1000000.0; +double mtr_time_s(void) { + static time_t start; + struct timeval tv; + gettimeofday(&tv, NULL); + if (start == 0) { + start = tv.tv_sec; + } + tv.tv_sec -= start; + return (double)tv.tv_sec + (double)tv.tv_usec / 1000000.0; } -#endif // !BLACKBERRY +#endif // !BLACKBERRY static void termination_handler(int signum) ATTR_NORETURN; static void termination_handler(int signum) { - (void) signum; - if (is_tracing) { - printf("Ctrl-C detected! Flushing trace and shutting down.\n\n"); - mtr_flush(); - fwrite("\n]}\n", 1, 4, f); - fclose(f); - } - exit(1); + (void) signum; + if (is_tracing) { + printf("Ctrl-C detected! Flushing trace and shutting down.\n\n"); + mtr_flush(); + fwrite("\n]}\n", 1, 4, f); + fclose(f); + } + exit(1); } -void mtr_register_sigint_handler() { +void mtr_register_sigint_handler(void) { #ifndef MTR_ENABLED - return; + return; #endif - // Avoid altering set-to-be-ignored handlers while registering. - if (signal(SIGINT, &termination_handler) == SIG_IGN) - signal(SIGINT, SIG_IGN); + // Avoid altering set-to-be-ignored handlers while registering. + if (signal(SIGINT, &termination_handler) == SIG_IGN) + signal(SIGINT, SIG_IGN); } #endif void mtr_init_from_stream(void *stream) { #ifndef MTR_ENABLED - return; + return; #endif - event_buffer = (raw_event_t *)malloc(INTERNAL_MINITRACE_BUFFER_SIZE * sizeof(raw_event_t)); - flush_buffer = (raw_event_t *)malloc(INTERNAL_MINITRACE_BUFFER_SIZE * sizeof(raw_event_t)); - event_count = 0; - f = (FILE *)stream; - const char *header = "{\"traceEvents\":[\n"; - fwrite(header, 1, strlen(header), f); - time_offset = (uint64_t)(mtr_time_s() * 1000000); - first_line = 1; - pthread_mutex_init(&mutex, 0); - pthread_mutex_init(&event_mutex, 0); + event_buffer = (raw_event_t *)malloc(INTERNAL_MINITRACE_BUFFER_SIZE * sizeof(raw_event_t)); + flush_buffer = (raw_event_t *)malloc(INTERNAL_MINITRACE_BUFFER_SIZE * sizeof(raw_event_t)); + event_count = 0; + fp = (FILE *) stream; + const char *header = "{\"traceEvents\":[\n"; + fwrite(header, 1, strlen(header), fp); + time_offset = (uint64_t)(mtr_time_s() * 1000000); + first_line = 1; + pthread_mutex_init(&mutex, 0); + pthread_mutex_init(&event_mutex, 0); } void mtr_init(const char *json_file) { #ifndef MTR_ENABLED - return; + return; #endif - mtr_init_from_stream(fopen(json_file, "wb")); + mtr_init_from_stream(fopen(json_file, "wb")); } -void mtr_shutdown() { - int i; +void mtr_shutdown(void) { #ifndef MTR_ENABLED - return; + return; #endif - mtr_flush_with_state(TRUE); + mtr_flush_with_state(TRUE); - fwrite("\n]}\n", 1, 4, f); - fclose(f); - pthread_mutex_destroy(&mutex); - pthread_mutex_destroy(&event_mutex); - f = 0; - free(event_buffer); - event_buffer = 0; - for (i = 0; i < STRING_POOL_SIZE; i++) { - if (str_pool[i]) { - free(str_pool[i]); - str_pool[i] = 0; - } - } + fwrite("\n]}\n", 1, 4, fp); + fclose(fp); + pthread_mutex_destroy(&mutex); + pthread_mutex_destroy(&event_mutex); + fp = 0; + free(event_buffer); + event_buffer = 0; + for (uint8_t i = 0; i < STRING_POOL_SIZE; i++) { + if (str_pool[i]) { + free(str_pool[i]); + str_pool[i] = 0; + } + } } const char *mtr_pool_string(const char *str) { - int i; - for (i = 0; i < STRING_POOL_SIZE; i++) { - if (!str_pool[i]) { - str_pool[i] = (char*)malloc(strlen(str) + 1); - strcpy(str_pool[i], str); - return str_pool[i]; - } else { - if (!strcmp(str, str_pool[i])) - return str_pool[i]; - } - } - return "string pool full"; + for (uint8_t i = 0; i < STRING_POOL_SIZE; i++) { + if (!str_pool[i]) { + str_pool[i] = (char*)malloc(strlen(str) + 1); + strcpy(str_pool[i], str); + return str_pool[i]; + } else { + if (!strcmp(str, str_pool[i])) + return str_pool[i]; + } + } + return "string pool full"; } -void mtr_start() { +void mtr_start(void) { #ifndef MTR_ENABLED - return; + return; #endif +#ifdef _WIN32 + pthread_cond_init(&buffer_not_full_cond); + pthread_cond_init(&buffer_full_cond); +#else pthread_cond_init(&buffer_not_full_cond, NULL); pthread_cond_init(&buffer_full_cond, NULL); +#endif atomic_store(&is_tracing, TRUE); - init_flushing_thread(); + init_flushing_thread(); } -void mtr_stop() { +void mtr_stop(void) { #ifndef MTR_ENABLED - return; + return; #endif - atomic_store(&is_tracing, FALSE); - atomic_store(&stop_flushing_requested, TRUE); - pthread_cond_signal(&buffer_not_full_cond); - pthread_cond_signal(&buffer_full_cond); - join_flushing_thread(); - atomic_store(&stop_flushing_requested, FALSE); + atomic_store(&is_tracing, FALSE); + atomic_store(&stop_flushing_requested, TRUE); + pthread_cond_signal(&buffer_not_full_cond); + pthread_cond_signal(&buffer_full_cond); + join_flushing_thread(); + atomic_store(&stop_flushing_requested, FALSE); } // TODO: fwrite more than one line at a time. // Flushing is thread safe and process async // using double-buffering mechanism. -// Aware: only one flushing process may be +// Aware: only one flushing process may be // running at any point of time void mtr_flush_with_state(int is_last) { #ifndef MTR_ENABLED - return; + return; #endif - int i = 0; - char linebuf[1024]; - char arg_buf[1024]; - char id_buf[256]; - int event_count_copy = 0; - int events_in_progress_copy = 1; - raw_event_t *event_buffer_tmp = NULL; + int i = 0; + char linebuf[1024]; + char arg_buf[1024]; + char id_buf[256]; + int event_count_copy = 0; + int events_in_progress_copy = 1; + raw_event_t *event_buffer_tmp = NULL; - // small critical section to swap buffers - // - no any new events can be spawn while - // swapping since they tied to the same mutex - // - checks for any flushing in process - pthread_mutex_lock(&mutex); - // if not flushing already - if (is_flushing) { - pthread_mutex_unlock(&mutex); - return; - } - is_flushing = TRUE; - if(!is_last) { - while(event_count < INTERNAL_MINITRACE_BUFFER_SIZE && atomic_load(&is_tracing)) { - pthread_cond_wait(&buffer_full_cond, &mutex); - } - } - event_count_copy = event_count; - event_buffer_tmp = flush_buffer; - flush_buffer = event_buffer; - event_buffer = event_buffer_tmp; - event_count = 0; - // waiting for any unfinished events before swap - while (events_in_progress_copy != 0) { - pthread_mutex_lock(&event_mutex); - events_in_progress_copy = events_in_progress; - pthread_mutex_unlock(&event_mutex); - } - pthread_mutex_unlock(&mutex); - pthread_cond_signal(&buffer_not_full_cond); + // small critical section to swap buffers + // - no any new events can be spawn while + // swapping since they tied to the same mutex + // - checks for any flushing in process + pthread_mutex_lock(&mutex); + // if not flushing already + if (is_flushing) { + pthread_mutex_unlock(&mutex); + return; + } + is_flushing = TRUE; + if(!is_last) { + while(event_count < INTERNAL_MINITRACE_BUFFER_SIZE && atomic_load(&is_tracing)) { + pthread_cond_wait(&buffer_full_cond, &mutex); + } + } + event_count_copy = event_count; + event_buffer_tmp = flush_buffer; + flush_buffer = event_buffer; + event_buffer = event_buffer_tmp; + event_count = 0; + // waiting for any unfinished events before swap + while (events_in_progress_copy != 0) { + pthread_mutex_lock(&event_mutex); + events_in_progress_copy = events_in_progress; + pthread_mutex_unlock(&event_mutex); + } + pthread_mutex_unlock(&mutex); + pthread_cond_signal(&buffer_not_full_cond); - for (i = 0; i < event_count_copy; i++) { - raw_event_t *raw = &flush_buffer[i]; - int len; - switch (raw->arg_type) { - case MTR_ARG_TYPE_INT: - snprintf(arg_buf, ARRAY_SIZE(arg_buf), "\"%s\":%i", raw->arg_name, raw->a_int); - break; - case MTR_ARG_TYPE_STRING_CONST: - snprintf(arg_buf, ARRAY_SIZE(arg_buf), "\"%s\":\"%s\"", raw->arg_name, raw->a_str); - break; - case MTR_ARG_TYPE_STRING_COPY: - if (strlen(raw->a_str) > 700) { - snprintf(arg_buf, ARRAY_SIZE(arg_buf), "\"%s\":\"%.*s\"", raw->arg_name, 700, raw->a_str); - } else { - snprintf(arg_buf, ARRAY_SIZE(arg_buf), "\"%s\":\"%s\"", raw->arg_name, raw->a_str); - } - break; - case MTR_ARG_TYPE_NONE: - arg_buf[0] = '\0'; - break; - } - if (raw->id) { - switch (raw->ph) { - case 'S': - case 'T': - case 'F': - // TODO: Support full 64-bit pointers - snprintf(id_buf, ARRAY_SIZE(id_buf), ",\"id\":\"0x%08x\"", (uint32_t)(uintptr_t)raw->id); - break; - case 'X': - snprintf(id_buf, ARRAY_SIZE(id_buf), ",\"dur\":%i", (int)raw->a_double); - break; - } - } else { - id_buf[0] = 0; - } - const char *cat = raw->cat; + for (i = 0; i < event_count_copy; i++) { + raw_event_t *raw = &flush_buffer[i]; + int len; + switch (raw->arg_type) { + case MTR_ARG_TYPE_INT: + snprintf(arg_buf, ARRAY_SIZE(arg_buf), "\"%s\":%i", raw->arg_name, raw->a_int); + break; + case MTR_ARG_TYPE_STRING_CONST: + snprintf(arg_buf, ARRAY_SIZE(arg_buf), "\"%s\":\"%s\"", raw->arg_name, raw->a_str); + break; + case MTR_ARG_TYPE_STRING_COPY: + if (strlen(raw->a_str) > 700) { + snprintf(arg_buf, ARRAY_SIZE(arg_buf), "\"%s\":\"%.*s\"", raw->arg_name, 700, raw->a_str); + } else { + snprintf(arg_buf, ARRAY_SIZE(arg_buf), "\"%s\":\"%s\"", raw->arg_name, raw->a_str); + } + break; + case MTR_ARG_TYPE_NONE: + arg_buf[0] = '\0'; + break; + } + if (raw->id) { + switch (raw->ph) { + case 'S': + case 'T': + case 'F': + // TODO: Support full 64-bit pointers + snprintf(id_buf, ARRAY_SIZE(id_buf), ",\"id\":\"0x%08x\"", (uint32_t)(uintptr_t)raw->id); + break; + case 'X': + snprintf(id_buf, ARRAY_SIZE(id_buf), ",\"dur\":%i", (int)raw->a_double); + break; + + default: + break; + } + } else { + id_buf[0] = 0; + } + const char *cat = raw->cat; #ifdef _WIN32 - // On Windows, we often end up with backslashes in category. - char temp[256]; - { - int len = (int)strlen(cat); - int i; - if (len > 255) len = 255; - for (i = 0; i < len; i++) { - temp[i] = cat[i] == '\\' ? '/' : cat[i]; - } - temp[len] = 0; - cat = temp; - } + // On Windows, we often end up with backslashes in category. + char temp[256]; + { + int len = (int)strlen(cat); + int i; + if (len > 255) len = 255; + for (i = 0; i < len; i++) { + temp[i] = cat[i] == '\\' ? '/' : cat[i]; + } + temp[len] = 0; + cat = temp; + } #endif - len = snprintf(linebuf, ARRAY_SIZE(linebuf), "%s{\"cat\":\"%s\",\"pid\":%i,\"tid\":%i,\"ts\":%" PRId64 ",\"ph\":\"%c\",\"name\":\"%s\",\"args\":{%s}%s}", - first_line ? "" : ",\n", - cat, raw->pid, raw->tid, raw->ts - time_offset, raw->ph, raw->name, arg_buf, id_buf); - fwrite(linebuf, 1, len, f); - first_line = 0; + len = snprintf(linebuf, ARRAY_SIZE(linebuf), "%s{\"cat\":\"%s\",\"pid\":%i,\"tid\":%i,\"ts\":%" PRId64 ",\"ph\":\"%c\",\"name\":\"%s\",\"args\":{%s}%s}", + first_line ? "" : ",\n", + cat, raw->pid, raw->tid, raw->ts - time_offset, raw->ph, raw->name, arg_buf, id_buf); + fwrite(linebuf, 1, len, f); + first_line = 0; - if (raw->arg_type == MTR_ARG_TYPE_STRING_COPY) { - free((void*)raw->a_str); - } - #ifdef MTR_COPY_EVENT_CATEGORY_AND_NAME - free(raw->name); - free(raw->cat); - #endif - } + if (raw->arg_type == MTR_ARG_TYPE_STRING_COPY) { + free((void*)raw->a_str); + } + #ifdef MTR_COPY_EVENT_CATEGORY_AND_NAME + free(raw->name); + free(raw->cat); + #endif + } - pthread_mutex_lock(&mutex); - is_flushing = is_last; - pthread_mutex_unlock(&mutex); + pthread_mutex_lock(&mutex); + is_flushing = is_last; + pthread_mutex_unlock(&mutex); } -void mtr_flush() { - mtr_flush_with_state(FALSE); +void mtr_flush(void) { + mtr_flush_with_state(FALSE); } void internal_mtr_raw_event(const char *category, const char *name, char ph, void *id) { #ifndef MTR_ENABLED - return; + return; #endif - if (!atomic_load(&is_tracing)) { - return; - } - pthread_mutex_lock(&mutex); - while(event_count >= INTERNAL_MINITRACE_BUFFER_SIZE && atomic_load(&is_tracing)) { - pthread_cond_wait(&buffer_not_full_cond, &mutex); - } - raw_event_t *ev = &event_buffer[event_count]; - ++event_count; - pthread_mutex_lock(&event_mutex); - ++events_in_progress; - pthread_mutex_unlock(&event_mutex); - int local_event_count = event_count; - pthread_mutex_unlock(&mutex); - if(local_event_count >= INTERNAL_MINITRACE_BUFFER_SIZE) { - pthread_cond_signal(&buffer_full_cond); - } + if (!atomic_load(&is_tracing)) { + return; + } + pthread_mutex_lock(&mutex); + while(event_count >= INTERNAL_MINITRACE_BUFFER_SIZE && atomic_load(&is_tracing)) { + pthread_cond_wait(&buffer_not_full_cond, &mutex); - double ts = mtr_time_s(); + } + raw_event_t *ev = &event_buffer[event_count]; + ++event_count; + pthread_mutex_lock(&event_mutex); + ++events_in_progress; + pthread_mutex_unlock(&event_mutex); + int local_event_count = event_count; + pthread_mutex_unlock(&mutex); + if(local_event_count >= INTERNAL_MINITRACE_BUFFER_SIZE) { + pthread_cond_signal(&buffer_full_cond); + } - if (!cur_thread_id) { - cur_thread_id = get_cur_thread_id(); - } - if (!cur_process_id) { - cur_process_id = get_cur_process_id(); - } + double ts = mtr_time_s(); + + if (!cur_thread_id) { + cur_thread_id = get_cur_thread_id(); + } + if (!cur_process_id) { + cur_process_id = get_cur_process_id(); + } #ifdef MTR_COPY_EVENT_CATEGORY_AND_NAME - const size_t category_len = strlen(category); - ev->cat = malloc(category_len + 1); - strcpy(ev->cat, category); + const size_t category_len = strlen(category); + ev->cat = malloc(category_len + 1); + strcpy(ev->cat, category); - const size_t name_len = strlen(name); - ev->name = malloc(name_len + 1); - strcpy(ev->name, name); + const size_t name_len = strlen(name); + ev->name = malloc(name_len + 1); + strcpy(ev->name, name); #else - ev->cat = category; - ev->name = name; + ev->cat = category; + ev->name = name; #endif - ev->id = id; - ev->ph = ph; - if (ev->ph == 'X') { - double x; - memcpy(&x, id, sizeof(double)); - ev->ts = (int64_t)(x * 1000000); - ev->a_double = (ts - x) * 1000000; - } else { - ev->ts = (int64_t)(ts * 1000000); - } - ev->tid = cur_thread_id; - ev->pid = cur_process_id; - ev->arg_type = MTR_ARG_TYPE_NONE; + ev->id = id; + ev->ph = ph; + if (ev->ph == 'X') { + double x; + memcpy(&x, id, sizeof(double)); + ev->ts = (int64_t)(x * 1000000); + ev->a_double = (ts - x) * 1000000; + } else { + ev->ts = (int64_t)(ts * 1000000); + } + ev->tid = cur_thread_id; + ev->pid = cur_process_id; + ev->arg_type = MTR_ARG_TYPE_NONE; - pthread_mutex_lock(&event_mutex); - --events_in_progress; - pthread_mutex_unlock(&event_mutex); + pthread_mutex_lock(&event_mutex); + --events_in_progress; + pthread_mutex_unlock(&event_mutex); } void internal_mtr_raw_event_arg(const char *category, const char *name, char ph, void *id, mtr_arg_type arg_type, const char *arg_name, void *arg_value) { #ifndef MTR_ENABLED - return; + return; #endif - if (!atomic_load(&is_tracing)) { - return; - } - pthread_mutex_lock(&mutex); - while(event_count >= INTERNAL_MINITRACE_BUFFER_SIZE && atomic_load(&is_tracing)) { - pthread_cond_wait(&buffer_not_full_cond, &mutex); - } - raw_event_t *ev = &event_buffer[event_count]; - ++event_count; - pthread_mutex_lock(&event_mutex); - ++events_in_progress; - pthread_mutex_unlock(&event_mutex); - int local_event_count = event_count; - pthread_mutex_unlock(&mutex); - if(local_event_count >= INTERNAL_MINITRACE_BUFFER_SIZE) { - pthread_cond_signal(&buffer_full_cond); - } + if (!atomic_load(&is_tracing)) { + return; + } + pthread_mutex_lock(&mutex); + while(event_count >= INTERNAL_MINITRACE_BUFFER_SIZE && atomic_load(&is_tracing)) { + pthread_cond_wait(&buffer_not_full_cond, &mutex); + } + raw_event_t *ev = &event_buffer[event_count]; + ++event_count; + pthread_mutex_lock(&event_mutex); + ++events_in_progress; + pthread_mutex_unlock(&event_mutex); + int local_event_count = event_count; + pthread_mutex_unlock(&mutex); + if(local_event_count >= INTERNAL_MINITRACE_BUFFER_SIZE) { + pthread_cond_signal(&buffer_full_cond); + } - if (!cur_thread_id) { - cur_thread_id = get_cur_thread_id(); - } - if (!cur_process_id) { - cur_process_id = get_cur_process_id(); - } - double ts = mtr_time_s(); + if (!cur_thread_id) { + cur_thread_id = get_cur_thread_id(); + } + if (!cur_process_id) { + cur_process_id = get_cur_process_id(); + } + double ts = mtr_time_s(); #ifdef MTR_COPY_EVENT_CATEGORY_AND_NAME - const size_t category_len = strlen(category); - ev->cat = malloc(category_len + 1); - strcpy(ev->cat, category); + const size_t category_len = strlen(category); + ev->cat = malloc(category_len + 1); + strcpy(ev->cat, category); - const size_t name_len = strlen(name); - ev->name = malloc(name_len + 1); - strcpy(ev->name, name); + const size_t name_len = strlen(name); + ev->name = malloc(name_len + 1); + strcpy(ev->name, name); #else - ev->cat = category; - ev->name = name; + ev->cat = category; + ev->name = name; #endif - ev->id = id; - ev->ts = (int64_t)(ts * 1000000); - ev->ph = ph; - ev->tid = cur_thread_id; - ev->pid = cur_process_id; - ev->arg_type = arg_type; - ev->arg_name = arg_name; - switch (arg_type) { - case MTR_ARG_TYPE_INT: ev->a_int = (int)(uintptr_t)arg_value; break; - case MTR_ARG_TYPE_STRING_CONST: ev->a_str = (const char*)arg_value; break; - case MTR_ARG_TYPE_STRING_COPY: ev->a_str = strdup((const char*)arg_value); break; - case MTR_ARG_TYPE_NONE: break; - } + ev->id = id; + ev->ts = (int64_t)(ts * 1000000); + ev->ph = ph; + ev->tid = cur_thread_id; + ev->pid = cur_process_id; + ev->arg_type = arg_type; + ev->arg_name = arg_name; + switch (arg_type) { + case MTR_ARG_TYPE_INT: ev->a_int = (int)(uintptr_t)arg_value; break; + case MTR_ARG_TYPE_STRING_CONST: ev->a_str = (const char*)arg_value; break; + case MTR_ARG_TYPE_STRING_COPY: ev->a_str = strdup((const char*)arg_value); break; + case MTR_ARG_TYPE_NONE: break; + } - pthread_mutex_lock(&event_mutex); - --events_in_progress; - pthread_mutex_unlock(&event_mutex); + pthread_mutex_lock(&event_mutex); + --events_in_progress; + pthread_mutex_unlock(&event_mutex); } - diff --git a/src/network/CMakeLists.txt b/src/network/CMakeLists.txt index 5cfa87d91..ce1bba325 100644 --- a/src/network/CMakeLists.txt +++ b/src/network/CMakeLists.txt @@ -1,29 +1,48 @@ # -# 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. +# 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. +# This file is part of the 86Box distribution. # -# CMake build script. +# CMake build script. # -# Authors: David HrdliÄka, +# Authors: David HrdliÄka, # -# Copyright 2020,2021 David HrdliÄka. +# Copyright 2020-2021 David HrdliÄka. # +set(net_sources) +list(APPEND net_sources network.c net_pcap.c net_slirp.c net_dp8390.c net_3c501.c + net_3c503.c net_ne2000.c net_pcnet.c net_wd8003.c net_plip.c net_event.c net_null.c) -add_library(net OBJECT network.c net_pcap.c net_slirp.c net_dp8390.c net_3c503.c - net_ne2000.c net_pcnet.c net_wd8003.c net_plip.c) +find_package(PkgConfig REQUIRED) +pkg_check_modules(SLIRP REQUIRED IMPORTED_TARGET slirp) +target_link_libraries(86Box PkgConfig::SLIRP) -option(SLIRP_EXTERNAL "Link against the system-provided libslirp library" OFF) -mark_as_advanced(SLIRP_EXTERNAL) +if(WIN32) + target_link_libraries(PkgConfig::SLIRP INTERFACE wsock32 ws2_32 iphlpapi iconv) +endif() -if(SLIRP_EXTERNAL) - find_package(PkgConfig REQUIRED) - pkg_check_modules(SLIRP REQUIRED IMPORTED_TARGET slirp) - target_link_libraries(86Box PkgConfig::SLIRP) -else() - add_subdirectory(slirp) - target_link_libraries(86Box slirp) -endif() \ No newline at end of file +if (HAIKU) + target_link_libraries(86Box network) +endif() + +if(WIN32) + target_link_libraries(86Box ws2_32) +endif() + +if (UNIX) + find_path(HAS_VDE "libvdeplug.h" PATHS ${VDE_INCLUDE_DIR} "/usr/include /usr/local/include" "/opt/homebrew/include" ) + if(HAS_VDE) + find_library(VDE_LIB vdeplug) + if (NOT VDE_LIB) + message(WARNING "Could not find VDE. The library will not be bundled and any related features will be disabled.") + else() + add_compile_definitions(HAS_VDE) + list(APPEND net_sources net_vde.c) + endif() + endif() +endif() + +add_library(net OBJECT ${net_sources}) diff --git a/src/network/net_3c501.c b/src/network/net_3c501.c new file mode 100644 index 000000000..5b9fc0cac --- /dev/null +++ b/src/network/net_3c501.c @@ -0,0 +1,1230 @@ +/* + * 86Box A hypervisor and IBM PC system emulator that specializes in + * running old operating systems and software designed for IBM + * PC systems and compatibles from 1981 through fairly recent + * system designs based on the PCI bus. + * + * This file is part of the 86Box distribution. + * + * Implementation of the following network controller: + * - 3Com Etherlink 3c500/3c501 (ISA 8-bit). + * + * + * + * Based on @(#)Dev3C501.cpp Oracle (VirtualBox) + * + * Authors: TheCollector1995, + * Oracle + * + * Copyright 2022 TheCollector1995. + * Portions Copyright (C) 2022 Oracle and/or its affilitates. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the: + * + * Free Software Foundation, Inc. + * 59 Temple Place - Suite 330 + * Boston, MA 02111-1307 + * USA. + */ +#include +#include +#include +#include +#include +#include +#include +#include +#define HAVE_STDARG_H +#include <86box/86box.h> +#include <86box/io.h> +#include <86box/dma.h> +#include <86box/pic.h> +#include <86box/mem.h> +#include <86box/random.h> +#include <86box/device.h> +#include <86box/thread.h> +#include <86box/timer.h> +#include <86box/network.h> +#include <86box/net_3c501.h> +#include <86box/bswap.h> +#include <86box/plat_unused.h> + +/* Maximum number of times we report a link down to the guest (failure to send frame) */ +#define ELNK_MAX_LINKDOWN_REPORTED 3 + +/* Maximum number of times we postpone restoring a link that is temporarily down. */ +#define ELNK_MAX_LINKRST_POSTPONED 3 + +/* Maximum frame size we handle */ +#define MAX_FRAME 1536 + +/* Size of the packet buffer. */ +#define ELNK_BUF_SIZE 2048 + +/* The packet buffer address mask. */ +#define ELNK_BUF_ADR_MASK (ELNK_BUF_SIZE - 1) + +/* The GP buffer pointer address within the buffer. */ +#define ELNK_GP(dev) (dev->uGPBufPtr & ELNK_BUF_ADR_MASK) + +/* The GP buffer pointer mask. + * NB: The GP buffer pointer is internally a 12-bit counter. When addressing into the + * packet buffer, bit 11 is ignored. Required to pass 3C501 diagnostics. + */ +#define ELNK_GP_MASK 0xfff + +/********************************************************************************************************************************* + * Structures and Typedefs * + *********************************************************************************************************************************/ + +/** + * EtherLink Transmit Command Register. + */ +typedef struct ELNK_XMIT_CMD { + uint8_t det_ufl : 1; /* Detect underflow. */ + uint8_t det_coll : 1; /* Detect collision. */ + uint8_t det_16col : 1; /* Detect collision 16. */ + uint8_t det_succ : 1; /* Detect successful xmit. */ + uint8_t unused : 4; +} EL_XMT_CMD; + +/** + * EtherLink Transmit Status Register. + * + * We will never see any real collisions, although collisions (including 16 + * successive collisions) may be useful to report when the link is down + * (something the 3C501 does not have a concept of). + */ +typedef struct ELNK_XMIT_STAT { + uint8_t uflow : 1; /* Underflow on transmit. */ + uint8_t coll : 1; /* Collision on transmit. */ + uint8_t coll16 : 1; /* 16 collisions on transmit. */ + uint8_t ready : 1; /* Ready for a new frame. */ + uint8_t undef : 4; +} EL_XMT_STAT; + +/** Address match (adr_match) modes. */ +typedef enum { + EL_ADRM_DISABLED = 0, /* Receiver disabled. */ + EL_ADRM_PROMISC = 1, /* Receive all addresses. */ + EL_ADRM_BCAST = 2, /* Receive station + broadcast. */ + EL_ADRM_MCAST = 3 /* Receive station + multicast. */ +} EL_ADDR_MATCH; + +/** + * EtherLink Receive Command Register. + */ +typedef struct ELNK_RECV_CMD { + uint8_t det_ofl : 1; /* Detect overflow errors. */ + uint8_t det_fcs : 1; /* Detect FCS errors. */ + uint8_t det_drbl : 1; /* Detect dribble error. */ + uint8_t det_runt : 1; /* Detect short frames. */ + uint8_t det_eof : 1; /* Detect EOF (frames without overflow). */ + uint8_t acpt_good : 1; /* Accept good frames. */ + uint8_t adr_match : 2; /* Address match mode. */ +} EL_RCV_CMD; + +/** + * EtherLink Receive Status Register. + */ +typedef struct ELNK_RECV_STAT { + uint8_t oflow : 1; /* Overflow on receive. */ + uint8_t fcs : 1; /* FCS error. */ + uint8_t dribble : 1; /* Dribble error. */ + uint8_t runt : 1; /* Short frame. */ + uint8_t no_ovf : 1; /* Received packet w/o overflow. */ + uint8_t good : 1; /* Received good packet. */ + uint8_t undef : 1; + uint8_t stale : 1; /* Stale receive status. */ +} EL_RCV_STAT; + +/** Buffer control (buf_ctl) modes. */ +typedef enum { + EL_BCTL_SYSTEM = 0, /* Host has buffer access. */ + EL_BCTL_XMT_RCV = 1, /* Transmit, then receive. */ + EL_BCTL_RECEIVE = 2, /* Receive. */ + EL_BCTL_LOOPBACK = 3 /* Loopback. */ +} EL_BUFFER_CONTROL; + +/** + * EtherLink Auxiliary Status Register. + */ +typedef struct ELNK_AUX_CMD { + uint8_t ire : 1; /* Interrupt Request Enable. */ + uint8_t xmit_bf : 1; /* Xmit packets with bad FCS. */ + uint8_t buf_ctl : 2; /* Packet buffer control. */ + uint8_t unused : 1; + uint8_t dma_req : 1; /* DMA request. */ + uint8_t ride : 1; /* Request Interrupt and DMA Enable. */ + uint8_t reset : 1; /* Card in reset while set. */ +} EL_AUX_CMD; + +/** + * EtherLink Auxiliary Status Register. + */ +typedef struct ELNK_AUX_STAT { + uint8_t recv_bsy : 1; /* Receive busy. */ + uint8_t xmit_bf : 1; /* Xmit packets with bad FCS. */ + uint8_t buf_ctl : 2; /* Packet buffer control. */ + uint8_t dma_done : 1; /* DMA done. */ + uint8_t dma_req : 1; /* DMA request. */ + uint8_t ride : 1; /* Request Interrupt and DMA Enable. */ + uint8_t xmit_bsy : 1; /* Transmit busy. */ +} EL_AUX_STAT; + +/** + * Internal interrupt status. + */ +typedef struct ELNK_INTR_STAT { + uint8_t recv_intr : 1; /* Receive interrupt status. */ + uint8_t xmit_intr : 1; /* Transmit interrupt status. */ + uint8_t dma_intr : 1; /* DMA interrupt status. */ + uint8_t unused : 5; +} EL_INTR_STAT; + +typedef struct threec501_t { + uint32_t base_address; + int base_irq; + uint32_t bios_addr; + uint8_t maclocal[6]; /* configured MAC (local) address. */ + bool fISR; /* Internal interrupt flag. */ + int fDMA; /* Internal DMA active flag. */ + int fInReset; /* Internal in-reset flag. */ + uint8_t aPROM[8]; /* The PROM contents. Only 8 bytes addressable, R/O. */ + uint8_t aStationAddr[6]; /* The station address programmed by the guest, W/O. */ + uint16_t uGPBufPtr; /* General Purpose (GP) Buffer Pointer, R/W. */ + uint16_t uRCVBufPtr; /* Receive (RCV) Buffer Pointer, R/W. */ + /** Transmit Command Register, W/O. */ + union { + uint8_t XmitCmdReg; + EL_XMT_CMD XmitCmd; + }; + /** Transmit Status Register, R/O. */ + union { + uint8_t XmitStatReg; + EL_XMT_STAT XmitStat; + }; + /** Receive Command Register, W/O. */ + union { + uint8_t RcvCmdReg; + EL_RCV_CMD RcvCmd; + }; + /** Receive Status Register, R/O. */ + union { + uint8_t RcvStatReg; + EL_RCV_STAT RcvStat; + }; + /** Auxiliary Command Register, W/O. */ + union { + uint8_t AuxCmdReg; + EL_AUX_CMD AuxCmd; + }; + /** Auxiliary Status Register, R/O. */ + union { + uint8_t AuxStatReg; + EL_AUX_STAT AuxStat; + }; + int fLinkUp; /* If set the link is currently up. */ + int fLinkTempDown; /* If set the link is temporarily down because of a saved state load. */ + uint16_t cLinkDownReported; /* Number of times we've reported the link down. */ + uint16_t cLinkRestorePostponed; /* Number of times we've postponed the link restore. */ + /* Internal interrupt state. */ + union { + uint8_t IntrStateReg; + EL_INTR_STAT IntrState; + }; + uint32_t cMsLinkUpDelay; /* MS to wait before we enable the link. */ + int dma_channel; + uint8_t abLoopBuf[ELNK_BUF_SIZE]; /* The loopback transmit buffer (avoid stack allocations). */ + uint8_t abRuntBuf[64]; /* The runt pad buffer (only really needs 60 bytes). */ + uint8_t abPacketBuf[ELNK_BUF_SIZE]; /* The packet buffer. */ + int dma_pos; + pc_timer_t timer_restore; + netcard_t *netcard; +} threec501_t; + +#ifdef ENABLE_3COM501_LOG +int threec501_do_log = ENABLE_3COM501_LOG; + +static void +threec501_log(const char *fmt, ...) +{ + va_list ap; + + if (threec501_do_log) { + va_start(ap, fmt); + pclog_ex(fmt, ap); + va_end(ap); + } +} +#else +# define threec501_log(fmt, ...) +#endif + +static void elnkSoftReset(threec501_t *dev); +static void elnkR3HardReset(threec501_t *dev); + +#ifndef ETHER_IS_MULTICAST /* Net/Open BSD macro it seems */ +# define ETHER_IS_MULTICAST(a) ((*(uint8_t *) (a)) & 1) +#endif + +#define ETHER_ADDR_LEN ETH_ALEN +#define ETH_ALEN 6 +#pragma pack(1) +struct ether_header /** @todo Use RTNETETHERHDR? */ +{ + uint8_t ether_dhost[ETH_ALEN]; /**< destination ethernet address */ + uint8_t ether_shost[ETH_ALEN]; /**< source ethernet address */ + uint16_t ether_type; /**< packet type ID field */ +}; +#pragma pack() + +static void +elnk_do_irq(threec501_t *dev, int set) +{ + if (set) + picint(1 << dev->base_irq); + else + picintc(1 << dev->base_irq); +} + +/** + * Checks if the link is up. + * @returns true if the link is up. + * @returns false if the link is down. + */ +static __inline int +elnkIsLinkUp(threec501_t *dev) +{ + return !dev->fLinkTempDown && dev->fLinkUp; +} + +/** + * Takes down the link temporarily if it's current status is up. + * + * This is used during restore and when replumbing the network link. + * + * The temporary link outage is supposed to indicate to the OS that all network + * connections have been lost and that it for instance is appropriate to + * renegotiate any DHCP lease. + * + * @param pThis The shared instance data. + */ +static void +elnkTempLinkDown(threec501_t *dev) +{ + if (dev->fLinkUp) { + dev->fLinkTempDown = 1; + dev->cLinkDownReported = 0; + dev->cLinkRestorePostponed = 0; + timer_set_delay_u64(&dev->timer_restore, (dev->cMsLinkUpDelay * 1000) * TIMER_USEC); + } +} + +/** + * @interface_method_impl{PDMDEVREG,pfnReset} + */ +static void +elnkR3Reset(void *priv) +{ + threec501_t *dev = (threec501_t *) priv; + + if (dev->fLinkTempDown) { + dev->cLinkDownReported = 0x1000; + dev->cLinkRestorePostponed = 0x1000; + timer_disable(&dev->timer_restore); + } + + /** @todo How to flush the queues? */ + elnkR3HardReset(dev); +} + +static void +elnkR3HardReset(threec501_t *dev) +{ + dev->fISR = false; + elnk_do_irq(dev, 0); + + /* Clear the packet buffer and station address. */ + memset(dev->abPacketBuf, 0, sizeof(dev->abPacketBuf)); + memset(dev->aStationAddr, 0, sizeof(dev->aStationAddr)); + + /* Reset the buffer pointers. */ + dev->uGPBufPtr = 0; + dev->uRCVBufPtr = 0; + + elnkSoftReset(dev); +} + +/** + * Check if incoming frame matches the station address. + */ +static __inline int +padr_match(threec501_t *dev, const uint8_t *buf) +{ + const struct ether_header *hdr = (const struct ether_header *) buf; + int result; + + /* Checks own + broadcast as well as own + multicast. */ + result = (dev->RcvCmd.adr_match >= EL_ADRM_BCAST) && !memcmp(hdr->ether_dhost, dev->aStationAddr, 6); + + return result; +} + +/** + * Check if incoming frame is an accepted broadcast frame. + */ +static __inline int +padr_bcast(threec501_t *dev, const uint8_t *buf) +{ + static uint8_t aBCAST[6] = { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff }; + const struct ether_header *hdr = (const struct ether_header *) buf; + int result = (dev->RcvCmd.adr_match == EL_ADRM_BCAST) && !memcmp(hdr->ether_dhost, aBCAST, 6); + + return result; +} + +/** + * Check if incoming frame is an accepted multicast frame. + */ +static __inline int +padr_mcast(threec501_t *dev, const uint8_t *buf) +{ + const struct ether_header *hdr = (const struct ether_header *) buf; + int result = (dev->RcvCmd.adr_match == EL_ADRM_MCAST) && ETHER_IS_MULTICAST(hdr->ether_dhost); + + return result; +} + +/** + * Update the device IRQ line based on internal state. + */ +static void +elnkUpdateIrq(threec501_t *dev) +{ + bool fISR = false; + + /* IRQ is active if any interrupt source is active and interrupts + * are enabled via RIDE or IRE. + */ + if (dev->IntrStateReg && (dev->AuxCmd.ride || dev->AuxCmd.ire)) + fISR = true; + +#ifdef ENABLE_3COM501_LOG + threec501_log("3Com501: elnkUpdateIrq: fISR=%d\n", fISR); +#endif + + if (fISR != dev->fISR) { + elnk_do_irq(dev, fISR); + dev->fISR = fISR; + } +} + +/** + * Perform a software reset of the NIC. + */ +static void +elnkSoftReset(threec501_t *dev) +{ +#ifdef ENABLE_3COM501_LOG + threec501_log("3Com501: elnkSoftReset\n"); +#endif + + /* Clear some of the user-visible register state. */ + dev->XmitCmdReg = 0; + dev->XmitStatReg = 0; + dev->RcvCmdReg = 0; + dev->RcvStatReg = 0; + dev->AuxCmdReg = 0; + dev->AuxStatReg = 0; + + /* The "stale receive status" is cleared by receiving an "interesting" packet. */ + dev->RcvStat.stale = 1; + + /* By virtue of setting the buffer control to system, transmit is set to busy. */ + dev->AuxStat.xmit_bsy = 1; + + /* Clear internal interrupt state. */ + dev->IntrStateReg = 0; + elnkUpdateIrq(dev); + + /* Note that a soft reset does not clear the packet buffer; software often + * assumes that it survives soft reset. The programmed station address is + * likewise not reset, and the buffer pointers are not reset either. + * Verified on a real 3C501. + */ + + /* No longer in reset state. */ + dev->fInReset = 0; +} + +/** + * Write incoming data into the packet buffer. + */ +static int +elnkReceiveLocked(void *priv, uint8_t *src, int size) +{ + threec501_t *dev = (threec501_t *) priv; + int is_padr = 0; + int is_bcast = 0; + int is_mcast = 0; + bool fLoopback = dev->RcvCmd.adr_match == EL_BCTL_LOOPBACK; + + union { + uint8_t RcvStatNewReg; + EL_RCV_STAT RcvStatNew; + } rcvstatnew; + + /* Drop everything if address matching is disabled. */ + if (dev->RcvCmd.adr_match == EL_ADRM_DISABLED) + return 0; + + /* Drop zero-length packets (how does that even happen?). */ + if (!size) + return 0; + + /* + * Drop all packets if the cable is not connected (and not in loopback). + */ + if (!elnkIsLinkUp(dev) && !fLoopback) + return 0; + + /* + * Do not receive further packets until receive status was read. + */ + if (dev->RcvStat.stale == 0) + return 0; + +#ifdef ENABLE_3COM501_LOG + threec501_log("3Com501: size on wire=%d, RCV ptr=%u\n", size, dev->uRCVBufPtr); +#endif + + /* + * Perform address matching. Packets which do not pass the address + * filter are always ignored. + */ + /// @todo cbToRecv must be 6 or more (complete address) + if ((dev->RcvCmd.adr_match == EL_ADRM_PROMISC) /* promiscuous enabled */ + || (is_padr = padr_match(dev, src)) + || (is_bcast = padr_bcast(dev, src)) + || (is_mcast = padr_mcast(dev, src))) { + uint8_t *dst = dev->abPacketBuf + dev->uRCVBufPtr; + +#ifdef ENABLE_3COM501_LOG + threec501_log("3Com501 Packet passed address filter (is_padr=%d, is_bcast=%d, is_mcast=%d), size=%d\n", is_padr, is_bcast, is_mcast, size); +#endif + + /* Receive status is evaluated from scratch. The stale bit must remain set until we know better. */ + rcvstatnew.RcvStatNewReg = 0; + rcvstatnew.RcvStatNew.stale = 1; + dev->RcvStatReg = 0x80; + + /* Detect errors: Runts, overflow, and FCS errors. + * NB: Dribble errors can not happen because we can only receive an + * integral number of bytes. FCS errors are only possible in loopback + * mode in case the FCS is deliberately corrupted. + */ + + /* See if we need to pad, and how much. Have to be careful because the + * Receive Buffer Pointer might be near the end of the buffer. + */ + if (size < 60) { + /* In loopback mode only, short packets are flagged as errors because + * diagnostic tools want to see the errors. Otherwise they're padded to + * minimum length (if packet came over the wire, it should have been + * properly padded). + */ + /// @todo This really is kind of wrong. We shouldn't be doing any + /// padding here, it should be done by the sending side! + if (!fLoopback) { + memset(dev->abRuntBuf, 0, sizeof(dev->abRuntBuf)); + memcpy(dev->abRuntBuf, src, size); + size = 60; + src = dev->abRuntBuf; + } else { +#ifdef ENABLE_3COM501_LOG + threec501_log("3Com501 runt, size=%d\n", size); +#endif + rcvstatnew.RcvStatNew.runt = 1; + } + } + + /* We don't care how big the frame is; if it fits into the buffer, all is + * good. But conversely if the Receive Buffer Pointer is initially near the + * end of the buffer, a small frame can trigger an overflow. + */ + if ((dev->uRCVBufPtr + size) <= ELNK_BUF_SIZE) + rcvstatnew.RcvStatNew.no_ovf = 1; + else { +#ifdef ENABLE_3COM501_LOG + threec501_log("3Com501 overflow, size=%d\n", size); +#endif + rcvstatnew.RcvStatNew.oflow = 1; + } + + if (fLoopback && dev->AuxCmd.xmit_bf) { +#ifdef ENABLE_3COM501_LOG + threec501_log("3Com501 bad FCS\n"); +#endif + rcvstatnew.RcvStatNew.fcs = 1; + } + + /* Error-free packets are considered good. */ + if (rcvstatnew.RcvStatNew.no_ovf && !rcvstatnew.RcvStatNew.fcs && !rcvstatnew.RcvStatNew.runt) + rcvstatnew.RcvStatNew.good = 1; + + uint16_t cbCopy = (uint16_t) MIN(ELNK_BUF_SIZE - dev->uRCVBufPtr, size); + + /* All packets that passed the address filter are copied to the buffer. */ + + /* Copy incoming data to the packet buffer. NB: Starts at the current + * Receive Buffer Pointer position. + */ + memcpy(dst, src, cbCopy); + + /* Packet length is indicated via the receive buffer pointer. */ + dev->uRCVBufPtr = (dev->uRCVBufPtr + cbCopy) & ELNK_GP_MASK; + +#ifdef ENABLE_3COM501_LOG + threec501_log("3Com501 Received packet, size=%d, RP=%u\n", cbCopy, dev->uRCVBufPtr); +#endif + + /* + * If one of the "interesting" conditions was hit, stop receiving until + * the status register is read (mark it not stale). + * NB: The precise receive logic is not very well described in the EtherLink + * documentation. It was refined using the 3C501.EXE diagnostic utility. + */ + if ((rcvstatnew.RcvStatNew.good && dev->RcvCmd.acpt_good) + || (rcvstatnew.RcvStatNew.no_ovf && dev->RcvCmd.det_eof) + || (rcvstatnew.RcvStatNew.runt && dev->RcvCmd.det_runt) + || (rcvstatnew.RcvStatNew.dribble && dev->RcvCmd.det_drbl) + || (rcvstatnew.RcvStatNew.fcs && dev->RcvCmd.det_fcs) + || (rcvstatnew.RcvStatNew.oflow && dev->RcvCmd.det_ofl)) { + dev->AuxStat.recv_bsy = 0; + dev->IntrState.recv_intr = 1; + rcvstatnew.RcvStatNew.stale = 0; /* Prevents further receive until set again. */ + } + + /* Finally update the receive status. */ + dev->RcvStat = rcvstatnew.RcvStatNew; + +#ifdef ENABLE_3COM501_LOG + threec501_log("3Com501: RcvCmd=%02X, RcvStat=%02X, RCVBufPtr=%u\n", dev->RcvCmdReg, dev->RcvStatReg, dev->uRCVBufPtr); +#endif + + elnkUpdateIrq(dev); + } + + return 1; +} + +/** + * Actually try transmit frames. + * + * @threads TX or EMT. + */ +static void +elnkAsyncTransmit(threec501_t *dev) +{ + /* + * Just drop it if not transmitting. Can happen with delayed transmits + * if transmit was disabled in the meantime. + */ + if (!dev->AuxStat.xmit_bsy) { +#ifdef ENABLE_3COM501_LOG + threec501_log("3Com501: Nope, xmit disabled\n"); +#endif + return; + } + + if ((dev->AuxCmd.buf_ctl != EL_BCTL_XMT_RCV) && (dev->AuxCmd.buf_ctl != EL_BCTL_LOOPBACK)) { +#ifdef ENABLE_3COM501_LOG + threec501_log("3Com501: Nope, not in xmit-then-receive or loopback state\n"); +#endif + return; + } + + /* + * Blast out data from the packet buffer. + */ + do { + /* Don't send anything when the link is down. */ + if (!elnkIsLinkUp(dev) + && dev->cLinkDownReported > ELNK_MAX_LINKDOWN_REPORTED) + break; + + bool const fLoopback = dev->AuxCmd.buf_ctl == EL_BCTL_LOOPBACK; + + /* + * Sending is easy peasy, there is by definition always + * a complete packet on hand. + */ + const unsigned cb = ELNK_BUF_SIZE - ELNK_GP(dev); /* Packet size. */ +#ifdef ENABLE_3COM501_LOG + threec501_log("3Com501: cb=%d, loopback=%d.\n", cb, fLoopback); +#endif + + dev->XmitStatReg = 0; /* Clear transmit status before filling it out. */ + + if (elnkIsLinkUp(dev) || fLoopback) { + if (cb <= MAX_FRAME) { + if (fLoopback) { + elnkReceiveLocked(dev, &dev->abPacketBuf[ELNK_GP(dev)], cb); + } else { +#ifdef ENABLE_3COM501_LOG + threec501_log("3Com501: elnkAsyncTransmit: transmit loopbuf xmit pos = %d\n", cb); +#endif + network_tx(dev->netcard, &dev->abPacketBuf[ELNK_GP(dev)], cb); + } + dev->XmitStat.ready = 1; + } else { + /* Signal error, as this violates the Ethernet specs. */ + /** @todo check if the correct error is generated. */ +#ifdef ENABLE_3COM501_LOG + threec501_log("3Com501: illegal giant frame (%u bytes) -> signalling error\n", cb); +#endif + } + } else { + /* Signal a transmit error pretending there was a collision. */ + dev->cLinkDownReported++; + dev->XmitStat.coll = 1; + } + + /* Transmit officially done, update register state. */ + dev->AuxStat.xmit_bsy = 0; + dev->IntrState.xmit_intr = !!(dev->XmitCmdReg & dev->XmitStatReg); +#ifdef ENABLE_3COM501_LOG + threec501_log("3Com501: XmitCmd=%02X, XmitStat=%02X\n", dev->XmitCmdReg, dev->XmitStatReg); +#endif + + /* NB: After a transmit, the GP Buffer Pointer points just past + * the end of the packet buffer (3C501 diagnostics). + */ + dev->uGPBufPtr = ELNK_BUF_SIZE; + + /* NB: The buffer control does *not* change to Receive and stays the way it was. */ + if (!fLoopback) { + dev->AuxStat.recv_bsy = 1; /* Receive Busy now set until a packet is received. */ + } + } while (0); /* No loop, because there isn't ever more than one packet to transmit. */ + + elnkUpdateIrq(dev); +} + +static void +elnkCsrWrite(threec501_t *dev, uint8_t data) +{ + bool fTransmit = false; + bool fReceive = false; + bool fDMAR; + int mode; + + union { + uint8_t reg; + EL_AUX_CMD val; + } auxcmd; + + auxcmd.reg = data; + + /* Handle reset first. */ + if (dev->AuxCmd.reset != auxcmd.val.reset) { + if (auxcmd.val.reset) { + /* Card is placed into reset. Just set the flag. NB: When in reset + * state, we permit writes to other registers, but those have no + * effect and will be overwritten when the card is taken out of reset. + */ +#ifdef ENABLE_3COM501_LOG + threec501_log("3Com501: Card going into reset\n"); +#endif + dev->fInReset = true; + + /* Many EtherLink drivers like to reset the card a lot. That can lead to + * packet loss if a packet was already received before the card was reset. + */ + } else { + /* Card is being taken out of reset. */ +#ifdef ENABLE_3COM501_LOG + threec501_log("3Com501: Card going out of reset\n"); +#endif + elnkSoftReset(dev); + } + dev->AuxCmd.reset = auxcmd.val.reset; /* Update the reset bit, if nothing else. */ + } + + /* If the card is in reset, stop right here. */ + if (dev->fInReset) { +#ifdef ENABLE_3COM501_LOG + threec501_log("3Com501: Reset\n"); +#endif + return; + } + + /* Evaluate DMA state. If it changed, we'll have to go back to R3. */ + fDMAR = auxcmd.val.dma_req && auxcmd.val.ride; + if (fDMAR != dev->fDMA) { + /* Start/stop DMA as requested. */ + dev->fDMA = fDMAR; + if (fDMAR) { + dma_set_drq(dev->dma_channel, fDMAR); + mode = dma_mode(dev->dma_channel); +#ifdef ENABLE_3COM501_LOG + threec501_log("3Com501: DMA Mode = %02x.\n", mode & 0x0c); +#endif + if ((mode & 0x0c) == 0x04) { + while (dev->dma_pos < (ELNK_BUF_SIZE - ELNK_GP(dev))) { + dma_channel_write(dev->dma_channel, dev->abPacketBuf[ELNK_GP(dev) + dev->dma_pos]); + dev->dma_pos++; + } + } else { + while (dev->dma_pos < (ELNK_BUF_SIZE - ELNK_GP(dev))) { + int dma_data = dma_channel_read(dev->dma_channel); + dev->abPacketBuf[ELNK_GP(dev) + dev->dma_pos] = dma_data & 0xff; + dev->dma_pos++; + } + } + dev->uGPBufPtr = (dev->uGPBufPtr + dev->dma_pos) & ELNK_GP_MASK; + dma_set_drq(dev->dma_channel, 0); + dev->dma_pos = 0; + dev->IntrState.dma_intr = 1; + dev->AuxStat.dma_done = 1; + elnkUpdateIrq(dev); + } +#ifdef ENABLE_3COM501_LOG + threec501_log("3Com501: DMARQ for channel %u set to %u\n", dev->dma_channel, fDMAR); +#endif + } + + /* Interrupt enable changes. */ + if ((dev->AuxCmd.ire != auxcmd.val.ire) || (dev->AuxCmd.ride != auxcmd.val.ride)) { + dev->AuxStat.ride = dev->AuxCmd.ride = auxcmd.val.ride; + dev->AuxCmd.ire = auxcmd.val.ire; /* NB: IRE is not visible in the aux status register. */ + } + + /* DMA Request changes. */ + if (dev->AuxCmd.dma_req != auxcmd.val.dma_req) { + dev->AuxStat.dma_req = dev->AuxCmd.dma_req = auxcmd.val.dma_req; + if (!auxcmd.val.dma_req) { + /* Clearing the DMA Request bit also clears the DMA Done status bit and any DMA interrupt. */ + dev->IntrState.dma_intr = 0; + dev->AuxStat.dma_done = 0; + } + } + + /* Packet buffer control changes. */ + if (dev->AuxCmd.buf_ctl != auxcmd.val.buf_ctl) { +#ifdef ENABLE_3COM501_LOG + static const char *apszBuffCntrl[4] = { "System", "Xmit then Recv", "Receive", "Loopback" }; + threec501_log("3Com501: Packet buffer control `%s' -> `%s'\n", apszBuffCntrl[dev->AuxCmd.buf_ctl], apszBuffCntrl[auxcmd.val.buf_ctl]); +#endif + if (auxcmd.val.buf_ctl == EL_BCTL_XMT_RCV) { + /* Transmit, then receive. */ + fTransmit = true; + dev->AuxStat.recv_bsy = 0; + } else if (auxcmd.val.buf_ctl == EL_BCTL_SYSTEM) { + dev->AuxStat.xmit_bsy = 1; /* Transmit Busy is set here and cleared once actual transmit completes. */ + dev->AuxStat.recv_bsy = 0; + } else if (auxcmd.val.buf_ctl == EL_BCTL_RECEIVE) { + /* Special case: If going from xmit-then-receive mode to receive mode, and we received + * a packet already (right after the receive), don't restart receive and lose the already + * received packet. + */ + if (!dev->uRCVBufPtr) + fReceive = true; + } else { + /* For loopback, we go through the regular transmit and receive path. That may be an + * overkill but the receive path is too complex for a special loopback-only case. + */ + fTransmit = true; + dev->AuxStat.recv_bsy = 1; /* Receive Busy now set until a packet is received. */ + } + dev->AuxStat.buf_ctl = dev->AuxCmd.buf_ctl = auxcmd.val.buf_ctl; + } + + /* NB: Bit 1 (xmit_bf, transmit packets with bad FCS) is a simple control + * bit which does not require special handling here. Just copy it over. + */ + dev->AuxStat.xmit_bf = dev->AuxCmd.xmit_bf = auxcmd.val.xmit_bf; + + /* There are multiple bits that affect interrupt state. Handle them now. */ + elnkUpdateIrq(dev); + + /* After fully updating register state, do a transmit (including loopback) or receive. */ + if (fTransmit) + elnkAsyncTransmit(dev); + else if (fReceive) { + dev->AuxStat.recv_bsy = 1; /* Receive Busy now set until a packet is received. */ + } +} + +static uint8_t +threec501_read(uint16_t addr, void *priv) +{ + threec501_t *dev = (threec501_t *) priv; + uint8_t retval = 0xff; + + switch (addr & 0x0f) { + case 0x00: /* Receive status register aliases. The SEEQ 8001 */ + case 0x02: /* EDLC clearly only decodes one bit for reads. */ + case 0x04: + case 0x06: /* Receive status register. */ + retval = dev->RcvStatReg; + dev->RcvStat.stale = 1; /* Allows further reception. */ + dev->IntrState.recv_intr = 0; /* Reading clears receive interrupt. */ + elnkUpdateIrq(dev); + break; + + case 0x01: /* Transmit status register aliases. */ + case 0x03: + case 0x05: + case 0x07: /* Transmit status register. */ + retval = dev->XmitStatReg; + dev->IntrState.xmit_intr = 0; /* Reading clears transmit interrupt. */ + elnkUpdateIrq(dev); + break; + + case 0x08: /* GP Buffer pointer LSB. */ + retval = (dev->uGPBufPtr & 0xff); + break; + case 0x09: /* GP Buffer pointer MSB. */ + retval = (dev->uGPBufPtr >> 8); + break; + + case 0x0a: /* RCV Buffer pointer LSB. */ + retval = (dev->uRCVBufPtr & 0xff); + break; + case 0x0b: /* RCV Buffer pointer MSB. */ + retval = (dev->uRCVBufPtr >> 8); + break; + + case 0x0c: /* Ethernet address PROM window. */ + case 0x0d: /* Alias. */ + /* Reads use low 3 bits of GP buffer pointer, no auto-increment. */ + retval = dev->aPROM[dev->uGPBufPtr & 7]; + break; + + case 0x0e: /* Auxiliary status register. */ + retval = dev->AuxStatReg; + break; + + case 0x0f: /* Buffer window. */ + /* Reads use low 11 bits of GP buffer pointer, auto-increment. */ + retval = dev->abPacketBuf[ELNK_GP(dev)]; + dev->uGPBufPtr = (dev->uGPBufPtr + 1) & ELNK_GP_MASK; + break; + + default: + break; + } + + elnkUpdateIrq(dev); +#ifdef ENABLE_3COM501_LOG + threec501_log("3Com501: read addr %x, value %x\n", addr & 0x0f, retval); +#endif + return retval; +} + +static uint8_t +threec501_nic_readb(uint16_t addr, void *priv) +{ + return threec501_read(addr, priv); +} + +static uint16_t +threec501_nic_readw(uint16_t addr, void *priv) +{ + return threec501_read(addr, priv) | (threec501_read(addr + 1, priv) << 8); +} + +static void +threec501_write(uint16_t addr, uint8_t value, void *priv) +{ + threec501_t *dev = (threec501_t *) priv; + int reg = (addr & 0x0f); + + switch (reg) { + case 0x00: /* Six bytes of station address. */ + case 0x01: + case 0x02: + case 0x03: + case 0x04: + case 0x05: + dev->aStationAddr[reg] = value; + break; + + case 0x06: /* Receive command. */ + dev->RcvCmdReg = value; +#ifdef ENABLE_3COM501_LOG + threec501_log("3Com501: Receive Command register set to %02X\n", dev->RcvCmdReg); +#endif + break; + + case 0x07: /* Transmit command. */ + dev->XmitCmdReg = value; +#ifdef ENABLE_3COM501_LOG + threec501_log("3Com501: Transmit Command register set to %02X\n", dev->XmitCmdReg); +#endif + break; + + case 0x08: /* GP Buffer pointer LSB. */ + dev->uGPBufPtr = (dev->uGPBufPtr & 0xff00) | value; + break; + case 0x09: /* GP Buffer pointer MSB. */ + dev->uGPBufPtr = (dev->uGPBufPtr & 0x00ff) | (value << 8); + break; + + case 0x0a: /* RCV Buffer pointer clear. */ + dev->uRCVBufPtr = 0; +#ifdef ENABLE_3COM501_LOG + threec501_log("3Com501: RCV Buffer Pointer cleared (%02X)\n", value); +#endif + break; + + case 0x0b: /* RCV buffer pointer MSB. */ + case 0x0c: /* Ethernet address PROM window. */ + case 0x0d: /* Undocumented. */ +#ifdef ENABLE_3COM501_LOG + threec501_log("3Com501: Writing read-only register %02X!\n", reg); +#endif + break; + + case 0x0e: /* Auxiliary Command (CSR). */ + elnkCsrWrite(dev, value); + break; + + case 0x0f: /* Buffer window. */ + /* Writes use low 11 bits of GP buffer pointer, auto-increment. */ + if (dev->AuxCmd.buf_ctl != EL_BCTL_SYSTEM) { + /// @todo Does this still increment GPBufPtr? + break; + } + dev->abPacketBuf[ELNK_GP(dev)] = value; + dev->uGPBufPtr = (dev->uGPBufPtr + 1) & ELNK_GP_MASK; + break; + + default: + break; + } + +#ifdef ENABLE_3COM501_LOG + threec501_log("3Com501: write addr %x, value %x\n", reg, value); +#endif +} + +static void +threec501_nic_writeb(uint16_t addr, uint8_t value, void *priv) +{ + threec501_write(addr, value, priv); +} + +static void +threec501_nic_writew(uint16_t addr, uint16_t value, void *priv) +{ + threec501_write(addr, value & 0xff, priv); + threec501_write(addr + 1, value >> 8, priv); +} + +static int +elnkSetLinkState(void *priv, uint32_t link_state) +{ + threec501_t *dev = (threec501_t *) priv; + + if (link_state & NET_LINK_TEMP_DOWN) { + elnkTempLinkDown(dev); + return 1; + } + + bool link_up = !(link_state & NET_LINK_DOWN); + if (dev->fLinkUp != link_up) { + dev->fLinkUp = link_up; + if (link_up) { + dev->fLinkTempDown = 1; + dev->cLinkDownReported = 0; + dev->cLinkRestorePostponed = 0; + timer_set_delay_u64(&dev->timer_restore, (dev->cMsLinkUpDelay * 1000) * TIMER_USEC); + } else { + dev->cLinkDownReported = 0; + dev->cLinkRestorePostponed = 0; + } + } + + return 0; +} + +static void +elnkR3TimerRestore(void *priv) +{ + threec501_t *dev = (threec501_t *) priv; + + if ((dev->cLinkDownReported <= ELNK_MAX_LINKDOWN_REPORTED) && (dev->cLinkRestorePostponed <= ELNK_MAX_LINKRST_POSTPONED)) { + timer_advance_u64(&dev->timer_restore, 1500000 * TIMER_USEC); + dev->cLinkRestorePostponed++; + } else { + dev->fLinkTempDown = 0; + } +} + +static void * +threec501_nic_init(UNUSED(const device_t *info)) +{ + uint32_t mac; + threec501_t *dev; + + dev = malloc(sizeof(threec501_t)); + memset(dev, 0x00, sizeof(threec501_t)); + dev->maclocal[0] = 0x02; /* 02:60:8C (3Com OID) */ + dev->maclocal[1] = 0x60; + dev->maclocal[2] = 0x8C; + + dev->base_address = device_get_config_hex16("base"); + dev->base_irq = device_get_config_int("irq"); + dev->dma_channel = device_get_config_int("dma"); + + dev->fLinkUp = 1; + dev->cMsLinkUpDelay = 5000; + + /* See if we have a local MAC address configured. */ + mac = device_get_config_mac("mac", -1); + + /* + * Make this device known to the I/O system. + * PnP and PCI devices start with address spaces inactive. + */ + io_sethandler(dev->base_address, 0x10, + threec501_nic_readb, threec501_nic_readw, NULL, + threec501_nic_writeb, threec501_nic_writew, NULL, dev); + + /* Set up our BIA. */ + if (mac & 0xff000000) { + /* Generate new local MAC. */ + dev->maclocal[3] = random_generate(); + dev->maclocal[4] = random_generate(); + dev->maclocal[5] = random_generate(); + mac = (((int) dev->maclocal[3]) << 16); + mac |= (((int) dev->maclocal[4]) << 8); + mac |= ((int) dev->maclocal[5]); + device_set_config_mac("mac", mac); + } else { + dev->maclocal[3] = (mac >> 16) & 0xff; + dev->maclocal[4] = (mac >> 8) & 0xff; + dev->maclocal[5] = (mac & 0xff); + } + + /* Initialize the PROM */ + memcpy(dev->aPROM, dev->maclocal, sizeof(dev->maclocal)); + dev->aPROM[6] = dev->aPROM[7] = 0; /* The two padding bytes. */ + +#ifdef ENABLE_3COM501_LOG + threec501_log("I/O=%04x, IRQ=%d, DMA=%d, MAC=%02x:%02x:%02x:%02x:%02x:%02x\n", + dev->base_address, dev->base_irq, dev->dma_channel, + dev->aPROM[0], dev->aPROM[1], dev->aPROM[2], + dev->aPROM[3], dev->aPROM[4], dev->aPROM[5]); +#endif + + /* Reset the board. */ + elnkR3HardReset(dev); + + /* Attach ourselves to the network module. */ + dev->netcard = network_attach(dev, dev->aPROM, elnkReceiveLocked, elnkSetLinkState); + + timer_add(&dev->timer_restore, elnkR3TimerRestore, dev, 0); + + return dev; +} + +static void +threec501_nic_close(void *priv) +{ + threec501_t *dev = (threec501_t *) priv; + +#ifdef ENABLE_3COM501_LOG + threec501_log("3Com501: closed\n"); +#endif + + free(dev); +} + +static const device_config_t threec501_config[] = { + { + .name = "base", + .description = "Address", + .type = CONFIG_HEX16, + .default_string = "", + .default_int = 0x300, + .file_filter = "", + .spinner = { 0 }, + .selection = { + { .description = "0x280", .value = 0x280 }, + { .description = "0x300", .value = 0x300 }, + { .description = "0x310", .value = 0x310 }, + { .description = "0x320", .value = 0x320 }, + { .description = "" } + }, + }, + { + .name = "irq", + .description = "IRQ", + .type = CONFIG_SELECTION, + .default_string = "", + .default_int = 3, + .file_filter = "", + .spinner = { 0 }, + .selection = { + { .description = "IRQ 2/9", .value = 9 }, + { .description = "IRQ 3", .value = 3 }, + { .description = "IRQ 4", .value = 4 }, + { .description = "IRQ 5", .value = 5 }, + { .description = "IRQ 6", .value = 6 }, + { .description = "IRQ 7", .value = 7 }, + { .description = "" } + }, + }, + { + .name = "dma", + .description = "DMA channel", + .type = CONFIG_SELECTION, + .default_string = "", + .default_int = 3, + .file_filter = "", + .spinner = { 0 }, + .selection = { + { .description = "DMA 1", .value = 1 }, + { .description = "DMA 2", .value = 2 }, + { .description = "DMA 3", .value = 3 }, + { .description = "" } + }, + }, + { + .name = "mac", + .description = "MAC Address", + .type = CONFIG_MAC, + .default_string = "", + .default_int = -1 + }, + { .name = "", .description = "", .type = CONFIG_END } +}; + +const device_t threec501_device = { + .name = "3Com EtherLink (3c500/3c501)", + .internal_name = "3c501", + .flags = DEVICE_ISA, + .local = 0, + .init = threec501_nic_init, + .close = threec501_nic_close, + .reset = elnkR3Reset, + { .available = NULL }, + .speed_changed = NULL, + .force_redraw = NULL, + .config = threec501_config +}; diff --git a/src/network/net_3c503.c b/src/network/net_3c503.c index a79699b31..d01b423ae 100644 --- a/src/network/net_3c503.c +++ b/src/network/net_3c503.c @@ -1,26 +1,27 @@ /* - * 86Box An emulator of (mostly) x86-based PC systems and devices, - * using the ISA, EISA, VLB, MCA, and PCI system buses, - * roughly spanning the era between 1981 and 1995. + * 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 Project. + * This file is part of the 86Box distribution. * - * Implementation of the following network controllers: - * - 3Com Etherlink II 3c503 (ISA 8-bit). + * Implementation of the following network controllers: + * - 3Com Etherlink II 3c503 (ISA 8-bit). * * * - * Based on @(#)3c503.cpp Carl (MAME) + * Based on @(#)3c503.cpp Carl (MAME) * - * Authors: TheCollector1995, - * Miran Grca, - * Fred N. van Kempen, - * Carl, + * Authors: TheCollector1995, + * Miran Grca, + * Fred N. van Kempen, + * Carl, * - * Copyright 2018 TheCollector1995. - * Copyright 2018 Miran Grca. - * Copyright 2017,2018 Fred N. van Kempen. - * Portions Copyright (C) 2018 MAME Project + * Copyright 2018 TheCollector1995. + * Copyright 2018 Miran Grca. + * Copyright 2017-2018 Fred N. van Kempen. + * Portions Copyright (C) 2018 MAME Project * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -55,137 +56,139 @@ #include <86box/mem.h> #include <86box/random.h> #include <86box/device.h> +#include <86box/thread.h> +#include <86box/timer.h> #include <86box/network.h> #include <86box/net_dp8390.h> #include <86box/net_3c503.h> #include <86box/bswap.h> +#include <86box/plat_unused.h> -typedef struct { - dp8390_t *dp8390; - mem_mapping_t ram_mapping; - uint32_t base_address; - int base_irq; - uint32_t bios_addr; - uint8_t maclocal[6]; /* configured MAC (local) address */ +typedef struct threec503_t { + dp8390_t *dp8390; + mem_mapping_t ram_mapping; + uint32_t base_address; + int base_irq; + uint32_t bios_addr; + uint8_t maclocal[6]; /* configured MAC (local) address */ struct { - uint8_t pstr; - uint8_t pspr; - uint8_t dqtr; - uint8_t bcfr; - uint8_t pcfr; - uint8_t gacfr; - uint8_t ctrl; - uint8_t streg; - uint8_t idcfr; - uint16_t da; - uint32_t vptr; - uint8_t rfmsb; - uint8_t rflsb; + uint8_t pstr; + uint8_t pspr; + uint8_t dqtr; + uint8_t bcfr; + uint8_t pcfr; + uint8_t gacfr; + uint8_t ctrl; + uint8_t streg; + uint8_t idcfr; + uint16_t da; + uint32_t vptr; + uint8_t rfmsb; + uint8_t rflsb; } regs; int dma_channel; } threec503_t; - #ifdef ENABLE_3COM503_LOG int threec503_do_log = ENABLE_3COM503_LOG; - static void threec503_log(const char *fmt, ...) { va_list ap; if (threec503_do_log) { - va_start(ap, fmt); - pclog_ex(fmt, ap); - va_end(ap); + va_start(ap, fmt); + pclog_ex(fmt, ap); + va_end(ap); } } #else -#define threec503_log(fmt, ...) +# define threec503_log(fmt, ...) #endif - static void threec503_interrupt(void *priv, int set) { threec503_t *dev = (threec503_t *) priv; switch (dev->base_irq) { - case 2: - dev->regs.idcfr = 0x10; - break; + case 2: + dev->regs.idcfr = 0x10; + break; - case 3: - dev->regs.idcfr = 0x20; - break; + case 3: + dev->regs.idcfr = 0x20; + break; - case 4: - dev->regs.idcfr = 0x40; - break; + case 4: + dev->regs.idcfr = 0x40; + break; - case 5: - dev->regs.idcfr = 0x80; - break; - } + case 5: + dev->regs.idcfr = 0x80; + break; + + default: + break; + } if (set) - picint(1 << dev->base_irq); + picint(1 << dev->base_irq); else - picintc(1 << dev->base_irq); + picintc(1 << dev->base_irq); } - static void threec503_ram_write(uint32_t addr, uint8_t val, void *priv) { - threec503_t *dev = (threec503_t *)priv; + threec503_t *dev = (threec503_t *) priv; if ((addr & 0x3fff) >= 0x2000) - return; + return; dev->dp8390->mem[addr & 0x1fff] = val; } - static uint8_t threec503_ram_read(uint32_t addr, void *priv) { - threec503_t *dev = (threec503_t *)priv; + const threec503_t *dev = (threec503_t *) priv; if ((addr & 0x3fff) >= 0x2000) - return 0xff; + return 0xff; return dev->dp8390->mem[addr & 0x1fff]; } - static void threec503_set_drq(threec503_t *dev) { switch (dev->dma_channel) { - case 1: - dev->regs.idcfr = 1; - break; + case 1: + dev->regs.idcfr = 1; + break; - case 2: - dev->regs.idcfr = 2; - break; + case 2: + dev->regs.idcfr = 2; + break; - case 3: - dev->regs.idcfr = 4; - break; - } + case 3: + dev->regs.idcfr = 4; + break; + + default: + break; + } } - /* reset - restore state to power-up, cancelling all i/o */ static void threec503_reset(void *priv) { - threec503_t *dev = (threec503_t *)priv; + threec503_t *dev = (threec503_t *) priv; #ifdef ENABLE_3COM503_LOG threec503_log("3Com503: reset\n"); @@ -195,377 +198,392 @@ threec503_reset(void *priv) memset(&dev->regs, 0, sizeof(dev->regs)); - dev->regs.ctrl = 0x0a; + dev->regs.ctrl = 0x0a; } - static uint8_t threec503_nic_lo_read(uint16_t addr, void *priv) { - threec503_t *dev = (threec503_t *)priv; - uint8_t retval = 0; - int off = addr - dev->base_address; + threec503_t *dev = (threec503_t *) priv; + uint8_t retval = 0; + int off = addr - dev->base_address; switch ((dev->regs.ctrl >> 2) & 3) { - case 0x00: - threec503_log("Read offset=%04x\n", off); - if (off == 0x00) - retval = dp8390_read_cr(dev->dp8390); - else switch(dev->dp8390->CR.pgsel) { - case 0x00: - retval = dp8390_page0_read(dev->dp8390, off, 1); - break; + case 0x00: + threec503_log("Read offset=%04x\n", off); + if (off == 0x00) + retval = dp8390_read_cr(dev->dp8390); + else + switch (dev->dp8390->CR.pgsel) { + case 0x00: + retval = dp8390_page0_read(dev->dp8390, off, 1); + break; - case 0x01: - retval = dp8390_page1_read(dev->dp8390, off, 1); - break; + case 0x01: + retval = dp8390_page1_read(dev->dp8390, off, 1); + break; - case 0x02: - retval = dp8390_page2_read(dev->dp8390, off, 1); - break; + case 0x02: + retval = dp8390_page2_read(dev->dp8390, off, 1); + break; - case 0x03: - retval = 0xff; - break; - } - break; + case 0x03: + retval = 0xff; + break; - case 0x01: - retval = dev->dp8390->macaddr[off]; - break; + default: + break; + } + break; - case 0x02: - retval = dev->dp8390->macaddr[off + 0x10]; - break; + case 0x01: + retval = dev->dp8390->macaddr[off]; + break; - case 0x03: - retval = 0xff; - break; + case 0x02: + retval = dev->dp8390->macaddr[off + 0x10]; + break; + + case 0x03: + retval = 0xff; + break; + + default: + break; } - return(retval); + return retval; } - static void threec503_nic_lo_write(uint16_t addr, uint8_t val, void *priv) { - threec503_t *dev = (threec503_t *)priv; - int off = addr - dev->base_address; + threec503_t *dev = (threec503_t *) priv; + int off = addr - dev->base_address; switch ((dev->regs.ctrl >> 2) & 3) { - case 0x00: - /* The high 16 bytes of i/o space are for the ne2000 asic - - the low 16 bytes are for the DS8390, with the current - page being selected by the PS0,PS1 registers in the - command register */ - if (off == 0x00) - dp8390_write_cr(dev->dp8390, val); - else switch(dev->dp8390->CR.pgsel) { - case 0x00: - dp8390_page0_write(dev->dp8390, off, val, 1); - break; + case 0x00: + /* The high 16 bytes of i/o space are for the ne2000 asic - + the low 16 bytes are for the DS8390, with the current + page being selected by the PS0,PS1 registers in the + command register */ + if (off == 0x00) + dp8390_write_cr(dev->dp8390, val); + else + switch (dev->dp8390->CR.pgsel) { + case 0x00: + dp8390_page0_write(dev->dp8390, off, val, 1); + break; - case 0x01: - dp8390_page1_write(dev->dp8390, off, val, 1); - break; + case 0x01: + dp8390_page1_write(dev->dp8390, off, val, 1); + break; - case 0x02: - dp8390_page2_write(dev->dp8390, off, val, 1); - break; + case 0x02: + dp8390_page2_write(dev->dp8390, off, val, 1); + break; - case 0x03: - break; - } - break; + case 0x03: + break; - case 0x01: - case 0x02: - case 0x03: - break; + default: + break; + } + break; + + case 0x01: + case 0x02: + case 0x03: + break; + + default: + break; } threec503_log("3Com503: write addr %x, value %x\n", addr, val); } - static uint8_t threec503_nic_hi_read(uint16_t addr, void *priv) { - threec503_t *dev = (threec503_t *)priv; + threec503_t *dev = (threec503_t *) priv; threec503_log("3Com503: Read GA address=%04x\n", addr); switch (addr & 0x0f) { - case 0x00: - return dev->regs.pstr; + case 0x00: + return dev->regs.pstr; - case 0x01: - return dev->regs.pspr; + case 0x01: + return dev->regs.pspr; - case 0x02: - return dev->regs.dqtr; + case 0x02: + return dev->regs.dqtr; - case 0x03: - switch (dev->base_address) { - default: - case 0x300: - dev->regs.bcfr = 0x80; - break; + case 0x03: + switch (dev->base_address) { + default: + case 0x300: + dev->regs.bcfr = 0x80; + break; - case 0x310: - dev->regs.bcfr = 0x40; - break; + case 0x310: + dev->regs.bcfr = 0x40; + break; - case 0x330: - dev->regs.bcfr = 0x20; - break; + case 0x330: + dev->regs.bcfr = 0x20; + break; - case 0x350: - dev->regs.bcfr = 0x10; - break; + case 0x350: + dev->regs.bcfr = 0x10; + break; - case 0x250: - dev->regs.bcfr = 0x08; - break; + case 0x250: + dev->regs.bcfr = 0x08; + break; - case 0x280: - dev->regs.bcfr = 0x04; - break; + case 0x280: + dev->regs.bcfr = 0x04; + break; - case 0x2a0: - dev->regs.bcfr = 0x02; - break; + case 0x2a0: + dev->regs.bcfr = 0x02; + break; - case 0x2e0: - dev->regs.bcfr = 0x01; - break; - } + case 0x2e0: + dev->regs.bcfr = 0x01; + break; + } - return dev->regs.bcfr; - break; + return dev->regs.bcfr; - case 0x04: - switch (dev->bios_addr) { - case 0xdc000: - dev->regs.pcfr = 0x80; - break; + case 0x04: + switch (dev->bios_addr) { + case 0xdc000: + dev->regs.pcfr = 0x80; + break; - case 0xd8000: - dev->regs.pcfr = 0x40; - break; + case 0xd8000: + dev->regs.pcfr = 0x40; + break; - case 0xcc000: - dev->regs.pcfr = 0x20; - break; + case 0xcc000: + dev->regs.pcfr = 0x20; + break; - case 0xc8000: - dev->regs.pcfr = 0x10; - break; - } + case 0xc8000: + dev->regs.pcfr = 0x10; + break; - return dev->regs.pcfr; - break; + default: + break; + } - case 0x05: - return dev->regs.gacfr; + return dev->regs.pcfr; - case 0x06: - return dev->regs.ctrl; + case 0x05: + return dev->regs.gacfr; - case 0x07: - return dev->regs.streg; + case 0x06: + return dev->regs.ctrl; - case 0x08: - return dev->regs.idcfr; + case 0x07: + return dev->regs.streg; - case 0x09: - return (dev->regs.da >> 8); + case 0x08: + return dev->regs.idcfr; - case 0x0a: - return (dev->regs.da & 0xff); + case 0x09: + return (dev->regs.da >> 8); - case 0x0b: - return (dev->regs.vptr >> 12) & 0xff; + case 0x0a: + return (dev->regs.da & 0xff); - case 0x0c: - return (dev->regs.vptr >> 4) & 0xff; + case 0x0b: + return (dev->regs.vptr >> 12) & 0xff; - case 0x0d: - return (dev->regs.vptr & 0x0f) << 4; + case 0x0c: + return (dev->regs.vptr >> 4) & 0xff; - case 0x0e: - case 0x0f: - if (!(dev->regs.ctrl & 0x80)) - return 0xff; + case 0x0d: + return (dev->regs.vptr & 0x0f) << 4; - threec503_set_drq(dev); + case 0x0e: + case 0x0f: + if (!(dev->regs.ctrl & 0x80)) + return 0xff; - return dp8390_chipmem_read(dev->dp8390, dev->regs.da++, 1); + threec503_set_drq(dev); + + return dp8390_chipmem_read(dev->dp8390, dev->regs.da++, 1); + + default: + break; } return 0; } - static void threec503_nic_hi_write(uint16_t addr, uint8_t val, void *priv) { - threec503_t *dev = (threec503_t *)priv; + threec503_t *dev = (threec503_t *) priv; threec503_log("3Com503: Write GA address=%04x, val=%04x\n", addr, val); switch (addr & 0x0f) { - case 0x00: - dev->regs.pstr = val; - break; + case 0x00: + dev->regs.pstr = val; + break; - case 0x01: - dev->regs.pspr = val; - break; + case 0x01: + dev->regs.pspr = val; + break; - case 0x02: - dev->regs.dqtr = val; - break; + case 0x02: + dev->regs.dqtr = val; + break; - case 0x05: - if ((dev->regs.gacfr & 0x0f) != (val & 0x0f)) { - switch (val & 0x0f) { - case 0: /*ROM mapping*/ - /* FIXME: Implement this when a BIOS is found/generated. */ - mem_mapping_disable(&dev->ram_mapping); - break; + case 0x05: + if ((dev->regs.gacfr & 0x0f) != (val & 0x0f)) { + switch (val & 0x0f) { + case 0: /*ROM mapping*/ + /* FIXME: Implement this when a BIOS is found/generated. */ + mem_mapping_disable(&dev->ram_mapping); + break; - case 9: /*RAM mapping*/ - mem_mapping_enable(&dev->ram_mapping); - break; + case 9: /*RAM mapping*/ + mem_mapping_enable(&dev->ram_mapping); + break; - default: /*No ROM mapping*/ - mem_mapping_disable(&dev->ram_mapping); - break; - } - } + default: /*No ROM mapping*/ + mem_mapping_disable(&dev->ram_mapping); + break; + } + } - if (!(val & 0x80)) - threec503_interrupt(dev, 1); - else - threec503_interrupt(dev, 0); + if (!(val & 0x80)) + threec503_interrupt(dev, 1); + else + threec503_interrupt(dev, 0); - dev->regs.gacfr = val; - break; + dev->regs.gacfr = val; + break; - case 0x06: - if (val & 1) { - threec503_reset(dev); - dev->dp8390->ISR.reset = 1; - dev->regs.ctrl = 0x0b; - return; - } + case 0x06: + if (val & 1) { + threec503_reset(dev); + dev->dp8390->ISR.reset = 1; + dev->regs.ctrl = 0x0b; + return; + } - if ((val & 0x80) != (dev->regs.ctrl & 0x80)) { - if (val & 0x80) - dev->regs.streg |= 0x88; - else - dev->regs.streg &= ~0x88; - dev->regs.streg &= ~0x10; - } - dev->regs.ctrl = val; - break; + if ((val & 0x80) != (dev->regs.ctrl & 0x80)) { + if (val & 0x80) + dev->regs.streg |= 0x88; + else + dev->regs.streg &= ~0x88; + dev->regs.streg &= ~0x10; + } + dev->regs.ctrl = val; + break; - case 0x08: - switch (val & 0xf0) { - case 0x00: - case 0x10: - case 0x20: - case 0x40: - case 0x80: - dev->regs.idcfr = (dev->regs.idcfr & 0x0f) | (val & 0xf0); - break; + case 0x08: + switch (val & 0xf0) { + case 0x00: + case 0x10: + case 0x20: + case 0x40: + case 0x80: + dev->regs.idcfr = (dev->regs.idcfr & 0x0f) | (val & 0xf0); + break; - default: - threec503_log("Trying to set multiple IRQs: %02x\n", val); - break; - } + default: + threec503_log("Trying to set multiple IRQs: %02x\n", val); + break; + } - switch (val & 0x0f) { - case 0x00: - case 0x01: - case 0x02: - case 0x04: - dev->regs.idcfr = (dev->regs.idcfr & 0xf0) | (val & 0x0f); - break; + switch (val & 0x0f) { + case 0x00: + case 0x01: + case 0x02: + case 0x04: + dev->regs.idcfr = (dev->regs.idcfr & 0xf0) | (val & 0x0f); + break; - case 0x08: - break; + case 0x08: + break; - default: - threec503_log("Trying to set multiple DMA channels: %02x\n", val); - break; - } - break; + default: + threec503_log("Trying to set multiple DMA channels: %02x\n", val); + break; + } + break; - case 0x09: - dev->regs.da = (val << 8) | (dev->regs.da & 0xff); - break; + case 0x09: + dev->regs.da = (val << 8) | (dev->regs.da & 0xff); + break; - case 0x0a: - dev->regs.da = (dev->regs.da & 0xff00) | val; - break; + case 0x0a: + dev->regs.da = (dev->regs.da & 0xff00) | val; + break; - case 0x0b: - dev->regs.vptr = (val << 12) | (dev->regs.vptr & 0xfff); - break; + case 0x0b: + dev->regs.vptr = (val << 12) | (dev->regs.vptr & 0xfff); + break; - case 0x0c: - dev->regs.vptr = (val << 4) | (dev->regs.vptr & 0xff00f); - break; + case 0x0c: + dev->regs.vptr = (val << 4) | (dev->regs.vptr & 0xff00f); + break; - case 0x0d: - dev->regs.vptr = (val << 4) | (dev->regs.vptr & 0xffff0); - break; + case 0x0d: + dev->regs.vptr = (val << 4) | (dev->regs.vptr & 0xffff0); + break; - case 0x0e: - case 0x0f: - if (!(dev->regs.ctrl & 0x80)) - return; + case 0x0e: + case 0x0f: + if (!(dev->regs.ctrl & 0x80)) + return; - threec503_set_drq(dev); + threec503_set_drq(dev); - dp8390_chipmem_write(dev->dp8390, dev->regs.da++, val, 1); - break; + dp8390_chipmem_write(dev->dp8390, dev->regs.da++, val, 1); + break; + + default: + break; } } - static void threec503_nic_ioset(threec503_t *dev, uint16_t addr) { io_sethandler(addr, 0x10, - threec503_nic_lo_read, NULL, NULL, - threec503_nic_lo_write, NULL, NULL, dev); + threec503_nic_lo_read, NULL, NULL, + threec503_nic_lo_write, NULL, NULL, dev); - io_sethandler(addr+0x400, 0x10, - threec503_nic_hi_read, NULL, NULL, - threec503_nic_hi_write, NULL, NULL, dev); + io_sethandler(addr + 0x400, 0x10, + threec503_nic_hi_read, NULL, NULL, + threec503_nic_hi_write, NULL, NULL, dev); } - static void * -threec503_nic_init(const device_t *info) +threec503_nic_init(UNUSED(const device_t *info)) { - uint32_t mac; + uint32_t mac; threec503_t *dev; dev = malloc(sizeof(threec503_t)); memset(dev, 0x00, sizeof(threec503_t)); - dev->maclocal[0] = 0x02; /* 02:60:8C (3Com OID) */ + dev->maclocal[0] = 0x02; /* 02:60:8C (3Com OID) */ dev->maclocal[1] = 0x60; dev->maclocal[2] = 0x8C; dev->base_address = device_get_config_hex16("base"); - dev->base_irq = device_get_config_int("irq"); - dev->dma_channel = device_get_config_int("dma"); - dev->bios_addr = device_get_config_hex20("bios_addr"); + dev->base_irq = device_get_config_int("irq"); + dev->dma_channel = device_get_config_int("dma"); + dev->bios_addr = device_get_config_hex20("bios_addr"); /* See if we have a local MAC address configured. */ mac = device_get_config_mac("mac", -1); @@ -575,58 +593,59 @@ threec503_nic_init(const device_t *info) * PnP and PCI devices start with address spaces inactive. */ threec503_nic_ioset(dev, dev->base_address); - + /* Set up our BIA. */ if (mac & 0xff000000) { - /* Generate new local MAC. */ - dev->maclocal[3] = random_generate(); - dev->maclocal[4] = random_generate(); - dev->maclocal[5] = random_generate(); - mac = (((int) dev->maclocal[3]) << 16); - mac |= (((int) dev->maclocal[4]) << 8); - mac |= ((int) dev->maclocal[5]); - device_set_config_mac("mac", mac); + /* Generate new local MAC. */ + dev->maclocal[3] = random_generate(); + dev->maclocal[4] = random_generate(); + dev->maclocal[5] = random_generate(); + mac = (((int) dev->maclocal[3]) << 16); + mac |= (((int) dev->maclocal[4]) << 8); + mac |= ((int) dev->maclocal[5]); + device_set_config_mac("mac", mac); } else { - dev->maclocal[3] = (mac>>16) & 0xff; - dev->maclocal[4] = (mac>>8) & 0xff; - dev->maclocal[5] = (mac & 0xff); + dev->maclocal[3] = (mac >> 16) & 0xff; + dev->maclocal[4] = (mac >> 8) & 0xff; + dev->maclocal[5] = (mac & 0xff); } - dev->dp8390 = device_add(&dp8390_device); - dev->dp8390->priv = dev; + dev->dp8390 = device_add_inst(&dp8390_device, dp3890_inst++); + dev->dp8390->priv = dev; dev->dp8390->interrupt = threec503_interrupt; dp8390_set_defaults(dev->dp8390, DP8390_FLAG_CHECK_CR | DP8390_FLAG_CLEAR_IRQ); dp8390_mem_alloc(dev->dp8390, 0x2000, 0x2000); - + memcpy(dev->dp8390->physaddr, dev->maclocal, sizeof(dev->maclocal)); threec503_log("I/O=%04x, IRQ=%d, MAC=%02x:%02x:%02x:%02x:%02x:%02x\n", - dev->base_address, dev->base_irq, - dev->dp8390->physaddr[0], dev->dp8390->physaddr[1], dev->dp8390->physaddr[2], - dev->dp8390->physaddr[3], dev->dp8390->physaddr[4], dev->dp8390->physaddr[5]); + dev->base_address, dev->base_irq, + dev->dp8390->physaddr[0], dev->dp8390->physaddr[1], dev->dp8390->physaddr[2], + dev->dp8390->physaddr[3], dev->dp8390->physaddr[4], dev->dp8390->physaddr[5]); /* Reset the board. */ threec503_reset(dev); /* Map this system into the memory map. */ mem_mapping_add(&dev->ram_mapping, dev->bios_addr, 0x4000, - threec503_ram_read, NULL, NULL, - threec503_ram_write, NULL, NULL, - NULL, MEM_MAPPING_EXTERNAL, dev); - // mem_mapping_disable(&dev->ram_mapping); - dev->regs.gacfr = 0x09; /* Start with RAM mapping enabled. */ + threec503_ram_read, NULL, NULL, + threec503_ram_write, NULL, NULL, + NULL, MEM_MAPPING_EXTERNAL, dev); +#if 0 + mem_mapping_disable(&dev->ram_mapping); +#endif + dev->regs.gacfr = 0x09; /* Start with RAM mapping enabled. */ /* Attach ourselves to the network module. */ - network_attach(dev->dp8390, dev->dp8390->physaddr, dp8390_rx, NULL, NULL); + dev->dp8390->card = network_attach(dev->dp8390, dev->dp8390->physaddr, dp8390_rx, NULL); - return(dev); + return dev; } - static void threec503_nic_close(void *priv) { - threec503_t *dev = (threec503_t *)priv; + threec503_t *dev = (threec503_t *) priv; #ifdef ENABLE_3COM503_LOG threec503_log("3Com503: closed\n"); @@ -635,118 +654,101 @@ threec503_nic_close(void *priv) free(dev); } - -static const device_config_t threec503_config[] = -{ +static const device_config_t threec503_config[] = { + // clang-format off { - "base", "Address", CONFIG_HEX16, "", 0x300, "", { 0 }, - { - { - "0x250", 0x250 - }, - { - "0x280", 0x280 - }, - { - "0x2a0", 0x2a0 - }, - { - "0x2e0", 0x2e0 - }, - { - "0x300", 0x300 - }, - { - "0x310", 0x310 - }, - { - "0x330", 0x330 - }, - { - "0x350", 0x350 - }, - { - "", 0 - } - }, + .name = "base", + .description = "Address", + .type = CONFIG_HEX16, + .default_string = "", + .default_int = 0x300, + .file_filter = "", + .spinner = { 0 }, + .selection = { + { .description = "0x250", .value = 0x250 }, + { .description = "0x280", .value = 0x280 }, + { .description = "0x2a0", .value = 0x2a0 }, + { .description = "0x2e0", .value = 0x2e0 }, + { .description = "0x300", .value = 0x300 }, + { .description = "0x310", .value = 0x310 }, + { .description = "0x330", .value = 0x330 }, + { .description = "0x350", .value = 0x350 }, + { .description = "", .value = 0 } + }, }, { - "irq", "IRQ", CONFIG_SELECTION, "", 3, "", { 0 }, - { - { - "IRQ 2", 2 - }, - { - "IRQ 3", 3 - }, - { - "IRQ 4", 4 - }, - { - "IRQ 5", 5 - }, - { - "", 0 - } - }, + .name = "irq", + .description = "IRQ", + .type = CONFIG_SELECTION, + .default_string = "", + .default_int = 3, + .file_filter = "", + .spinner = { 0 }, + .selection = { + { .description = "IRQ 2", .value = 2 }, + { .description = "IRQ 3", .value = 3 }, + { .description = "IRQ 4", .value = 4 }, + { .description = "IRQ 5", .value = 5 }, + { .description = "", .value = 0 } + }, }, { - "dma", "DMA", CONFIG_SELECTION, "", 3, "", { 0 }, - { - { - "DMA 1", 1 - }, - { - "DMA 2", 2 - }, - { - "DMA 3", 3 - }, - { - "", 0 - } - }, + .name = "dma", + .description = "DMA", + .type = CONFIG_SELECTION, + .default_string = "", + .default_int = 3, + .file_filter = "", + .spinner = { 0 }, + .selection = { + { .description = "DMA 1", .value = 1 }, + { .description = "DMA 2", .value = 2 }, + { .description = "DMA 3", .value = 3 }, + { .description = "", .value = 0 } + }, }, { - "mac", "MAC Address", CONFIG_MAC, "", -1, "", { 0 }, - { - { - "", 0 - } - }, + .name = "mac", + .description = "MAC Address", + .type = CONFIG_MAC, + .default_string = "", + .default_int = -1, + .file_filter = "", + .spinner = { 0 }, + .selection = { + { .description = "", .value = 0 } + }, }, { - "bios_addr", "BIOS address", CONFIG_HEX20, "", 0xCC000, "", { 0 }, - { - { - "DC00", 0xDC000 - }, - { - "D800", 0xD8000 - }, - { - "C800", 0xC8000 - }, - { - "CC00", 0xCC000 - }, - { - "", 0 - } - }, + .name = "bios_addr", + .description = "BIOS address", + .type = CONFIG_HEX20, + .default_string = "", + .default_int = 0xCC000, + .file_filter = "", + .spinner = { 0 }, + .selection = { + { .description = "DC00", .value = 0xDC000 }, + { .description = "D800", .value = 0xD8000 }, + { .description = "C800", .value = 0xC8000 }, + { .description = "CC00", .value = 0xCC000 }, + { .description = "", .value = 0 } + }, }, - { - "", "", -1 - } + { .name = "", .description = "", .type = CONFIG_END } +// clang-format off }; - const device_t threec503_device = { - "3Com EtherLink II", - "3c503", - DEVICE_ISA, - 0, - threec503_nic_init, threec503_nic_close, NULL, - { NULL }, NULL, NULL, - threec503_config + .name = "3Com EtherLink II", + .internal_name = "3c503", + .flags = DEVICE_ISA, + .local = 0, + .init = threec503_nic_init, + .close = threec503_nic_close, + .reset = NULL, + { .available = NULL }, + .speed_changed = NULL, + .force_redraw = NULL, + .config = threec503_config }; diff --git a/src/network/net_dp8390.c b/src/network/net_dp8390.c index d3d4aa46c..1c308e913 100644 --- a/src/network/net_dp8390.c +++ b/src/network/net_dp8390.c @@ -1,19 +1,19 @@ /* - * 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. + * 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. * - * Emulation of the DP8390 Network Interface Controller used by - * the WD family, NE1000/NE2000 family, and 3Com 3C503 NIC's. + * Emulation of the DP8390 Network Interface Controller used by + * the WD family, NE1000/NE2000 family, and 3Com 3C503 NIC's. * * * - * Authors: Miran Grca, - * Bochs project, + * Authors: Miran Grca, + * Bochs project, * - * Copyright 2016-2018 Miran Grca. - * Copyright 2008-2018 Bochs project. + * Copyright 2016-2018 Miran Grca. + * Copyright 2008-2018 Bochs project. */ #include #include @@ -25,14 +25,17 @@ #define HAVE_STDARG_H #include <86box/86box.h> #include <86box/device.h> +#include <86box/thread.h> +#include <86box/timer.h> #include <86box/network.h> #include <86box/net_dp8390.h> +#include <86box/plat_unused.h> +static void dp8390_tx(dp8390_t *dev, uint32_t val); +static int dp8390_rx_common(void *priv, uint8_t *buf, int io_len); +int dp8390_rx(void *priv, uint8_t *buf, int io_len); -static void dp8390_tx(dp8390_t *dev, uint32_t val); -static int dp8390_rx_common(void *priv, uint8_t *buf, int io_len); -int dp8390_rx(void *priv, uint8_t *buf, int io_len); - +int dp3890_inst = 0; #ifdef ENABLE_DP8390_LOG int dp8390_do_log = ENABLE_DP8390_LOG; @@ -42,17 +45,16 @@ dp8390_log(const char *fmt, ...) { va_list ap; - if (dp8390_do_log >= lvl) { - va_start(ap, fmt); - pclog_ex(fmt, ap); - va_end(ap); - } +// if (dp8390_do_log >= lvl) { + va_start(ap, fmt); + pclog_ex(fmt, ap); + va_end(ap); +// } } #else -#define dp8390_log(lvl, fmt, ...) +# define dp8390_log(lvl, fmt, ...) #endif - /* * Return the 6-bit index into the multicast * table. Stolen unashamedly from FreeBSD's if_ed.c @@ -61,26 +63,25 @@ static int mcast_index(const void *dst) { #define POLYNOMIAL 0x04c11db6 - uint32_t crc = 0xffffffffL; - int carry, i, j; - uint8_t b; - uint8_t *ep = (uint8_t *)dst; + uint32_t crc = 0xffffffffL; + int carry; + uint8_t b; + const uint8_t *ep = (const uint8_t *) dst; - for (i=6; --i>=0;) { - b = *ep++; - for (j = 8; --j >= 0;) { - carry = ((crc & 0x80000000L) ? 1 : 0) ^ (b & 0x01); - crc <<= 1; - b >>= 1; - if (carry) - crc = ((crc ^ POLYNOMIAL) | carry); - } + for (int8_t i = 6; --i >= 0;) { + b = *ep++; + for (int8_t j = 8; --j >= 0;) { + carry = ((crc & 0x80000000L) ? 1 : 0) ^ (b & 0x01); + crc <<= 1; + b >>= 1; + if (carry) + crc = ((crc ^ POLYNOMIAL) | carry); + } } - return(crc >> 26); + return (crc >> 26); #undef POLYNOMIAL } - /* * Access the 32K private RAM. * @@ -93,75 +94,65 @@ mcast_index(const void *dst) uint32_t dp8390_chipmem_read(dp8390_t *dev, uint32_t addr, unsigned int len) { - int i; uint32_t retval = 0; #ifdef ENABLE_DP8390_LOG - if ((len > 1) && (addr & (len - 1)) - dp3890_log("DP8390: unaligned chipmem word read\n"); + if ((len > 1) && (addr & (len - 1))) + dp8390_log("DP8390: unaligned chipmem word read\n"); #endif dp8390_log("DP8390: Chipmem Read Address=%04x\n", addr); /* ROM'd MAC address */ - for (i = 0; i < len; i++) { - if ((addr >= dev->mem_start) && (addr < dev->mem_end)) - retval |= (uint32_t) (dev->mem[addr - dev->mem_start]) << (i << 3); - else if (addr < dev->macaddr_size) - retval |= ((uint32_t) dev->macaddr[addr & (dev->macaddr_size - 1)]) << (i << 3); - else { - dp8390_log("DP8390: out-of-bounds chipmem read, %04X\n", addr); - retval |= 0xff << (i << 3); - } - addr++; + for (unsigned int i = 0; i < len; i++) { + if ((addr >= dev->mem_start) && (addr < dev->mem_end)) + retval |= (uint32_t) (dev->mem[addr - dev->mem_start]) << (i << 3); + else if (addr < dev->macaddr_size) + retval |= ((uint32_t) dev->macaddr[addr & (dev->macaddr_size - 1)]) << (i << 3); + else { + dp8390_log("DP8390: out-of-bounds chipmem read, %04X\n", addr); + retval |= 0xff << (i << 3); + } + addr++; } - return(retval); + return retval; } - void dp8390_chipmem_write(dp8390_t *dev, uint32_t addr, uint32_t val, unsigned len) { - int i; - #ifdef ENABLE_DP8390_LOG - if ((len > 1) && (addr & (len - 1)) - dp8390_log("DP8390: unaligned chipmem word write\n"); + if ((len > 1) && (addr & (len - 1))) + dp8390_log("DP8390: unaligned chipmem word write\n"); #endif dp8390_log("DP8390: Chipmem Write Address=%04x\n", addr); - for (i = 0; i < len; i++) { - if ((addr < dev->mem_start) || (addr >= dev->mem_end)) { - dp8390_log("DP8390: out-of-bounds chipmem write, %04X\n", addr); - return; - } + for (unsigned int i = 0; i < len; i++) { + if ((addr < dev->mem_start) || (addr >= dev->mem_end)) { + dp8390_log("DP8390: out-of-bounds chipmem write, %04X\n", addr); + return; + } - dev->mem[addr - dev->mem_start] = val & 0xff; - val >>= 8; - addr++; + dev->mem[addr - dev->mem_start] = val & 0xff; + val >>= 8; + addr++; } } - /* Routines for handling reads/writes to the Command Register. */ uint32_t dp8390_read_cr(dp8390_t *dev) { uint32_t retval; - retval = (((dev->CR.pgsel & 0x03) << 6) | - ((dev->CR.rdma_cmd & 0x07) << 3) | - (dev->CR.tx_packet << 2) | - (dev->CR.start << 1) | - (dev->CR.stop)); + retval = (((dev->CR.pgsel & 0x03) << 6) | ((dev->CR.rdma_cmd & 0x07) << 3) | (dev->CR.tx_packet << 2) | (dev->CR.start << 1) | (dev->CR.stop)); dp8390_log("DP8390: read CR returns 0x%02x\n", retval); - return(retval); + return retval; } - void dp8390_write_cr(dp8390_t *dev, uint32_t val) { @@ -170,17 +161,17 @@ dp8390_write_cr(dp8390_t *dev, uint32_t val) /* Validate remote-DMA */ if ((val & 0x38) == 0x00) { #ifdef ENABLE_DP8390_LOG - dp8390_log("DP8390: CR write - invalid rDMA value 0\n"); + dp8390_log("DP8390: CR write - invalid rDMA value 0\n"); #endif - val |= 0x20; /* dma_cmd == 4 is a safe default */ + val |= 0x20; /* dma_cmd == 4 is a safe default */ } /* Check for s/w reset */ if (val & 0x01) { - dev->ISR.reset = 1; - dev->CR.stop = 1; + dev->ISR.reset = 1; + dev->CR.stop = 1; } else { - dev->CR.stop = 0; + dev->CR.stop = 0; } dev->CR.rdma_cmd = (val & 0x38) >> 3; @@ -188,83 +179,82 @@ dp8390_write_cr(dp8390_t *dev, uint32_t val) /* If start command issued, the RST bit in the ISR */ /* must be cleared */ if ((val & 0x02) && !dev->CR.start) - dev->ISR.reset = 0; + dev->ISR.reset = 0; dev->CR.start = ((val & 0x02) == 0x02); dev->CR.pgsel = (val & 0xc0) >> 6; /* Check for send-packet command */ if (dev->CR.rdma_cmd == 3) { - /* Set up DMA read from receive ring */ - dev->remote_start = dev->remote_dma = dev->bound_ptr * 256; - dev->remote_bytes = (uint16_t) dp8390_chipmem_read(dev, dev->bound_ptr * 256 + 2, 2); - dp8390_log("DP8390: sending buffer #x%x length %d\n", - dev->dp8390.remote_start, dev->dp8390.remote_bytes); + /* Set up DMA read from receive ring */ + dev->remote_start = dev->remote_dma = dev->bound_ptr * 256; + dev->remote_bytes = (uint16_t) dp8390_chipmem_read(dev, dev->bound_ptr * 256 + 2, 2); + dp8390_log("DP8390: sending buffer #x%x length %d\n", + dev->remote_start, dev->remote_bytes); } /* Check for start-tx */ if ((val & 0x04) && dev->TCR.loop_cntl) { - if (dev->TCR.loop_cntl) { - dp8390_rx_common(dev, &dev->mem[(dev->tx_page_start * 256) - dev->mem_start], - dev->tx_bytes); - } + if (dev->TCR.loop_cntl) { + dp8390_rx_common(dev, &dev->mem[((dev->tx_page_start * 256) - dev->mem_start) & dev->mem_wrap], + dev->tx_bytes); + } } else if (val & 0x04) { - if (dev->CR.stop || (!dev->CR.start && (dev->flags & DP8390_FLAG_CHECK_CR))) { - if (dev->tx_bytes == 0) /* njh@bandsman.co.uk */ - return; /* Solaris9 probe */ + if (dev->CR.stop || (!dev->CR.start && (dev->flags & DP8390_FLAG_CHECK_CR))) { + if (dev->tx_bytes == 0) /* njh@bandsman.co.uk */ + return; /* Solaris9 probe */ #ifdef ENABLE_DP8390_LOG - dp8390_log("DP8390: CR write - tx start, dev in reset\n"); + dp8390_log("DP8390: CR write - tx start, dev in reset\n"); #endif - } + } #ifdef ENABLE_DP8390_LOG - if (dev->tx_bytes == 0) - dp8390_log("DP8390: CR write - tx start, tx bytes == 0\n"); + if (dev->tx_bytes == 0) + dp8390_log("DP8390: CR write - tx start, tx bytes == 0\n"); #endif - /* Send the packet to the system driver */ - dev->CR.tx_packet = 1; - - network_tx(&dev->mem[(dev->tx_page_start * 256) - dev->mem_start], dev->tx_bytes); + /* Send the packet to the system driver */ + dev->CR.tx_packet = 1; - /* some more debug */ + /* TODO: report TX error to the driver ? */ + if (!(dev->card->link_state & NET_LINK_DOWN)) + network_tx(dev->card, &dev->mem[((dev->tx_page_start * 256) - dev->mem_start) & dev->mem_wrap], dev->tx_bytes); + + /* some more debug */ #ifdef ENABLE_DP8390_LOG - if (dev->tx_timer_active) - dp8390_log("DP8390: CR write, tx timer still active\n"); + if (dev->tx_timer_active) + dp8390_log("DP8390: CR write, tx timer still active\n"); #endif - dp8390_tx(dev, val); + dp8390_tx(dev, val); } /* Linux probes for an interrupt by setting up a remote-DMA read * of 0 bytes with remote-DMA completion interrupts enabled. * Detect this here */ - if ((dev->CR.rdma_cmd == 0x01) && dev->CR.start && - (dev->remote_bytes == 0)) { - dev->ISR.rdma_done = 1; - if (dev->IMR.rdma_inte && dev->interrupt) { - dev->interrupt(dev->priv, 1); - if (dev->flags & DP8390_FLAG_CLEAR_IRQ) - dev->interrupt(dev->priv, 0); - } + if ((dev->CR.rdma_cmd == 0x01) && dev->CR.start && (dev->remote_bytes == 0)) { + dev->ISR.rdma_done = 1; + if (dev->IMR.rdma_inte && dev->interrupt) { + dev->interrupt(dev->priv, 1); + if (dev->flags & DP8390_FLAG_CLEAR_IRQ) + dev->interrupt(dev->priv, 0); + } } } - static void -dp8390_tx(dp8390_t *dev, uint32_t val) +dp8390_tx(dp8390_t *dev, UNUSED(uint32_t val)) { dev->CR.tx_packet = 0; - dev->TSR.tx_ok = 1; - dev->ISR.pkt_tx = 1; + dev->TSR.tx_ok = 1; + dev->ISR.pkt_tx = 1; /* Generate an interrupt if not masked */ if (dev->IMR.tx_inte && dev->interrupt) - dev->interrupt(dev->priv, 1); + dev->interrupt(dev->priv, 1); dev->tx_timer_active = 0; } - /* * Called by the platform-specific code when an Ethernet frame * has been received. The destination address is tested to see @@ -274,30 +264,33 @@ dp8390_tx(dp8390_t *dev, uint32_t val) static int dp8390_rx_common(void *priv, uint8_t *buf, int io_len) { - dp8390_t *dev = (dp8390_t *)priv; - static uint8_t bcast_addr[6] = {0xff,0xff,0xff,0xff,0xff,0xff}; - uint8_t pkthdr[4]; - uint8_t *startptr; - int pages, avail; - int idx, nextpage; - int endbytes; + dp8390_t *dev = (dp8390_t *) priv; + static uint8_t bcast_addr[6] = { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff }; + uint8_t pkthdr[4]; + uint8_t *startptr; + int pages; + int avail; + int idx; + int nextpage; + int endbytes; if (io_len != 60) - dp8390_log("%s: rx_frame with length %d\n", dev->name, io_len); + dp8390_log("rx_frame with length %d\n", io_len); if ((dev->CR.stop != 0) || (dev->page_start == 0)) - return 0; + return 0; + if (dev->card->link_state & NET_LINK_DOWN) + return 0; /* * Add the pkt header + CRC to the length, and work * out how many 256-byte pages the frame would occupy. */ - pages = (io_len + sizeof(pkthdr) + sizeof(uint32_t) + 255)/256; + pages = (io_len + sizeof(pkthdr) + sizeof(uint32_t) + 255) / 256; if (dev->curr_page < dev->bound_ptr) { - avail = dev->bound_ptr - dev->curr_page; + avail = dev->bound_ptr - dev->curr_page; } else { - avail = (dev->page_stop - dev->page_start) - - (dev->curr_page - dev->bound_ptr); + avail = (dev->page_stop - dev->page_start) - (dev->curr_page - dev->bound_ptr); } /* @@ -305,128 +298,125 @@ dp8390_rx_common(void *priv, uint8_t *buf, int io_len) * not attempting to do partial receives. The emulation * to handle this condition seems particularly painful. */ - if ((avail < pages) + if ((avail < pages) #if DP8390_NEVER_FULL_RING - || (avail == pages) + || (avail == pages) #endif - ) { + ) { #ifdef ENABLE_DP8390_LOG - dp8390_log("DP8390: no space\n"); + dp8390_log("DP8390: no space\n"); #endif - return 0; + return 0; } - if ((io_len < 40/*60*/) && !dev->RCR.runts_ok) { + if ((io_len < 40 /*60*/) && !dev->RCR.runts_ok) { #ifdef ENABLE_DP8390_LOG - dp8390_log("DP8390: rejected small packet, length %d\n", io_len); + dp8390_log("DP8390: rejected small packet, length %d\n", io_len); #endif - return 1; + return 1; } /* Some computers don't care... */ if (io_len < 60) - io_len = 60; + io_len = 60; dp8390_log("DP8390: RX %x:%x:%x:%x:%x:%x > %x:%x:%x:%x:%x:%x len %d\n", - buf[6], buf[7], buf[8], buf[9], buf[10], buf[11], - buf[0], buf[1], buf[2], buf[3], buf[4], buf[5], - io_len); + buf[6], buf[7], buf[8], buf[9], buf[10], buf[11], + buf[0], buf[1], buf[2], buf[3], buf[4], buf[5], + io_len); /* Do address filtering if not in promiscuous mode. */ - if (! dev->RCR.promisc) { - /* If this is a broadcast frame.. */ - if (! memcmp(buf, bcast_addr, 6)) { - /* Broadcast not enabled, we're done. */ - if (! dev->RCR.broadcast) { + if (!dev->RCR.promisc) { + /* If this is a broadcast frame.. */ + if (!memcmp(buf, bcast_addr, 6)) { + /* Broadcast not enabled, we're done. */ + if (!dev->RCR.broadcast) { #ifdef ENABLE_DP8390_LOG - dp8390_log("DP8390: RX BC disabled\n"); + dp8390_log("DP8390: RX BC disabled\n"); #endif - return 1; - } - } + return 1; + } + } - /* If this is a multicast frame.. */ - else if (buf[0] & 0x01) { - /* Multicast not enabled, we're done. */ - if (! dev->RCR.multicast) { + /* If this is a multicast frame.. */ + else if (buf[0] & 0x01) { + /* Multicast not enabled, we're done. */ + if (!dev->RCR.multicast) { #ifdef ENABLE_DP8390_LOG - dp8390_log("DP8390: RX MC disabled\n"); + dp8390_log("DP8390: RX MC disabled\n"); #endif - return 1; - } + return 1; + } - /* Are we listening to this multicast address? */ - idx = mcast_index(buf); - if (! (dev->mchash[idx>>3] & (1<<(idx&0x7)))) { + /* Are we listening to this multicast address? */ + idx = mcast_index(buf); + if (!(dev->mchash[idx >> 3] & (1 << (idx & 0x7)))) { #ifdef ENABLE_DP8390_LOG - dp8390_log("DP8390: RX MC not listed\n"); + dp8390_log("DP8390: RX MC not listed\n"); #endif - return 1; - } - } + return 1; + } + } - /* Unicast, must be for us.. */ - else if (memcmp(buf, dev->physaddr, 6)) - return 1; + /* Unicast, must be for us.. */ + else if (memcmp(buf, dev->physaddr, 6)) + return 1; } else { #ifdef ENABLE_DP8390_LOG - dp8390_log("DP8390: RX promiscuous receive\n"); + dp8390_log("DP8390: RX promiscuous receive\n"); #endif } nextpage = dev->curr_page + pages; if (nextpage >= dev->page_stop) - nextpage -= (dev->page_stop - dev->page_start); + nextpage -= (dev->page_stop - dev->page_start); /* Set up packet header. */ - pkthdr[0] = 0x01; /* RXOK - packet is OK */ + pkthdr[0] = 0x01; /* RXOK - packet is OK */ if (buf[0] & 0x01) - pkthdr[0] |= 0x20; /* MULTICAST packet */ - pkthdr[1] = nextpage; /* ptr to next packet */ - pkthdr[2] = (io_len + sizeof(pkthdr))&0xff; /* length-low */ - pkthdr[3] = (io_len + sizeof(pkthdr))>>8; /* length-hi */ + pkthdr[0] |= 0x20; /* MULTICAST packet */ + pkthdr[1] = nextpage; /* ptr to next packet */ + pkthdr[2] = (io_len + sizeof(pkthdr)) & 0xff; /* length-low */ + pkthdr[3] = (io_len + sizeof(pkthdr)) >> 8; /* length-hi */ dp8390_log("DP8390: RX pkthdr [%02x %02x %02x %02x]\n", - pkthdr[0], pkthdr[1], pkthdr[2], pkthdr[3]); + pkthdr[0], pkthdr[1], pkthdr[2], pkthdr[3]); /* Copy into buffer, update curpage, and signal interrupt if config'd */ startptr = &dev->mem[(dev->curr_page * 256) - dev->mem_start]; memcpy(startptr, pkthdr, sizeof(pkthdr)); - if ((nextpage > dev->curr_page) || - ((dev->curr_page + pages) == dev->page_stop)) { - memcpy(startptr+sizeof(pkthdr), buf, io_len); + if ((nextpage > dev->curr_page) || ((dev->curr_page + pages) == dev->page_stop)) { + memcpy(startptr + sizeof(pkthdr), buf, io_len); } else { - endbytes = (dev->page_stop - dev->curr_page) * 256; - memcpy(startptr+sizeof(pkthdr), buf, endbytes-sizeof(pkthdr)); - startptr = &dev->mem[(dev->page_start * 256) - dev->mem_start]; - memcpy(startptr, buf+endbytes-sizeof(pkthdr), io_len-endbytes+8); + endbytes = (dev->page_stop - dev->curr_page) * 256; + memcpy(startptr + sizeof(pkthdr), buf, endbytes - sizeof(pkthdr)); + startptr = &dev->mem[((dev->tx_page_start * 256) - dev->mem_start) & dev->mem_wrap]; + memcpy(startptr, buf + endbytes - sizeof(pkthdr), io_len - endbytes + 8); } dev->curr_page = nextpage; - dev->RSR.rx_ok = 1; + dev->RSR.rx_ok = 1; dev->RSR.rx_mbit = (buf[0] & 0x01) ? 1 : 0; - dev->ISR.pkt_rx = 1; + dev->ISR.pkt_rx = 1; if (dev->IMR.rx_inte && dev->interrupt) - dev->interrupt(dev->priv, 1); + dev->interrupt(dev->priv, 1); return 1; } - int dp8390_rx(void *priv, uint8_t *buf, int io_len) { - dp8390_t *dev = (dp8390_t *)priv; + const dp8390_t *dev = (dp8390_t *) priv; if ((dev->DCR.loop == 0) || (dev->TCR.loop_cntl != 0)) - return 0; + return 0; - return dp8390_rx_common(priv, buf, io_len); + return dp8390_rx_common(priv, buf, io_len); } - /* Handle reads/writes to the 'zeroth' page of the DS8390 register file. */ uint32_t dp8390_page0_read(dp8390_t *dev, uint32_t off, unsigned int len) @@ -434,547 +424,484 @@ dp8390_page0_read(dp8390_t *dev, uint32_t off, unsigned int len) uint8_t retval = 0; if (len > 1) { - /* encountered with win98 hardware probe */ - dp8390_log("DP8390: bad length! Page0 read from register 0x%02x, len=%u\n", - off, len); - return(retval); + /* encountered with win98 hardware probe */ + dp8390_log("DP8390: bad length! Page0 read from register 0x%02x, len=%u\n", + off, len); + return retval; } - switch(off) { - case 0x01: /* CLDA0 */ - retval = (dev->local_dma & 0xff); - break; + switch (off) { + case 0x01: /* CLDA0 */ + retval = (dev->local_dma & 0xff); + break; - case 0x02: /* CLDA1 */ - retval = (dev->local_dma >> 8); - break; + case 0x02: /* CLDA1 */ + retval = (dev->local_dma >> 8); + break; - case 0x03: /* BNRY */ - retval = dev->bound_ptr; - break; + case 0x03: /* BNRY */ + retval = dev->bound_ptr; + break; - case 0x04: /* TSR */ - retval = ((dev->TSR.ow_coll << 7) | - (dev->TSR.cd_hbeat << 6) | - (dev->TSR.fifo_ur << 5) | - (dev->TSR.no_carrier << 4) | - (dev->TSR.aborted << 3) | - (dev->TSR.collided << 2) | - (dev->TSR.tx_ok)); - break; + case 0x04: /* TSR */ + retval = ((dev->TSR.ow_coll << 7) | (dev->TSR.cd_hbeat << 6) | (dev->TSR.fifo_ur << 5) | (dev->TSR.no_carrier << 4) | (dev->TSR.aborted << 3) | (dev->TSR.collided << 2) | (dev->TSR.tx_ok)); + break; - case 0x05: /* NCR */ - retval = dev->num_coll; - break; + case 0x05: /* NCR */ + retval = dev->num_coll; + break; - case 0x06: /* FIFO */ - /* reading FIFO is only valid in loopback mode */ + case 0x06: /* FIFO */ + /* reading FIFO is only valid in loopback mode */ #ifdef ENABLE_DP8390_LOG - dp8390_log("DP8390: reading FIFO not supported yet\n"); + dp8390_log("DP8390: reading FIFO not supported yet\n"); #endif - retval = dev->fifo; - break; + retval = dev->fifo; + break; - case 0x07: /* ISR */ - retval = ((dev->ISR.reset << 7) | - (dev->ISR.rdma_done << 6) | - (dev->ISR.cnt_oflow << 5) | - (dev->ISR.overwrite << 4) | - (dev->ISR.tx_err << 3) | - (dev->ISR.rx_err << 2) | - (dev->ISR.pkt_tx << 1) | - (dev->ISR.pkt_rx)); - break; + case 0x07: /* ISR */ + retval = ((dev->ISR.reset << 7) | (dev->ISR.rdma_done << 6) | (dev->ISR.cnt_oflow << 5) | (dev->ISR.overwrite << 4) | (dev->ISR.tx_err << 3) | (dev->ISR.rx_err << 2) | (dev->ISR.pkt_tx << 1) | (dev->ISR.pkt_rx)); + break; - case 0x08: /* CRDA0 */ - retval = (dev->remote_dma & 0xff); - break; + case 0x08: /* CRDA0 */ + retval = (dev->remote_dma & 0xff); + break; - case 0x09: /* CRDA1 */ - retval = (dev->remote_dma >> 8); - break; + case 0x09: /* CRDA1 */ + retval = (dev->remote_dma >> 8); + break; - case 0x0a: /* reserved / RTL8029ID0 */ - retval = dev->id0; - break; + case 0x0a: /* reserved / RTL8029ID0 */ + retval = dev->id0; + break; - case 0x0b: /* reserved / RTL8029ID1 */ - retval = dev->id1; - break; + case 0x0b: /* reserved / RTL8029ID1 */ + retval = dev->id1; + break; - case 0x0c: /* RSR */ - retval = ((dev->RSR.deferred << 7) | - (dev->RSR.rx_disabled << 6) | - (dev->RSR.rx_mbit << 5) | - (dev->RSR.rx_missed << 4) | - (dev->RSR.fifo_or << 3) | - (dev->RSR.bad_falign << 2) | - (dev->RSR.bad_crc << 1) | - (dev->RSR.rx_ok)); - break; + case 0x0c: /* RSR */ + retval = ((dev->RSR.deferred << 7) | (dev->RSR.rx_disabled << 6) | (dev->RSR.rx_mbit << 5) | (dev->RSR.rx_missed << 4) | (dev->RSR.fifo_or << 3) | (dev->RSR.bad_falign << 2) | (dev->RSR.bad_crc << 1) | (dev->RSR.rx_ok)); + break; - case 0x0d: /* CNTR0 */ - retval = dev->tallycnt_0; - break; + case 0x0d: /* CNTR0 */ + retval = dev->tallycnt_0; + break; - case 0x0e: /* CNTR1 */ - retval = dev->tallycnt_1; - break; + case 0x0e: /* CNTR1 */ + retval = dev->tallycnt_1; + break; - case 0x0f: /* CNTR2 */ - retval = dev->tallycnt_2; - break; + case 0x0f: /* CNTR2 */ + retval = dev->tallycnt_2; + break; - default: - dp8390_log("DP8390: Page0 register 0x%02x out of range\n", off); - break; + default: + dp8390_log("DP8390: Page0 register 0x%02x out of range\n", off); + break; } dp8390_log("DP8390: Page0 read from register 0x%02x, value=0x%02x\n", off, - retval); + retval); - return(retval); + return retval; } - void -dp8390_page0_write(dp8390_t *dev, uint32_t off, uint32_t val, unsigned len) +dp8390_page0_write(dp8390_t *dev, uint32_t off, uint32_t val, UNUSED(unsigned len)) { uint8_t val2; dp8390_log("DP839: Page0 write to register 0x%02x, value=0x%02x\n", - off, val); + off, val); - switch(off) { - case 0x01: /* PSTART */ - dev->page_start = val; - dp8390_log("DP8390: Starting RAM address: %04X\n", val << 8); - break; + switch (off) { + case 0x01: /* PSTART */ + dev->page_start = val; + dp8390_log("DP8390: Starting RAM address: %04X\n", val << 8); + break; - case 0x02: /* PSTOP */ - dev->page_stop = val; - dp8390_log("DP8390: Stopping RAM address: %04X\n", val << 8); - break; + case 0x02: /* PSTOP */ + dev->page_stop = val; + dp8390_log("DP8390: Stopping RAM address: %04X\n", val << 8); + break; - case 0x03: /* BNRY */ - dev->bound_ptr = val; - break; + case 0x03: /* BNRY */ + dev->bound_ptr = val; + break; - case 0x04: /* TPSR */ - dev->tx_page_start = val; - break; + case 0x04: /* TPSR */ + dev->tx_page_start = val; + break; - case 0x05: /* TBCR0 */ - /* Clear out low byte and re-insert */ - dev->tx_bytes &= 0xff00; - dev->tx_bytes |= (val & 0xff); - break; + case 0x05: /* TBCR0 */ + /* Clear out low byte and re-insert */ + dev->tx_bytes &= 0xff00; + dev->tx_bytes |= (val & 0xff); + break; - case 0x06: /* TBCR1 */ - /* Clear out high byte and re-insert */ - dev->tx_bytes &= 0x00ff; - dev->tx_bytes |= ((val & 0xff) << 8); - break; + case 0x06: /* TBCR1 */ + /* Clear out high byte and re-insert */ + dev->tx_bytes &= 0x00ff; + dev->tx_bytes |= ((val & 0xff) << 8); + break; - case 0x07: /* ISR */ - val &= 0x7f; /* clear RST bit - status-only bit */ - /* All other values are cleared iff the ISR bit is 1 */ - dev->ISR.pkt_rx &= !((int)((val & 0x01) == 0x01)); - dev->ISR.pkt_tx &= !((int)((val & 0x02) == 0x02)); - dev->ISR.rx_err &= !((int)((val & 0x04) == 0x04)); - dev->ISR.tx_err &= !((int)((val & 0x08) == 0x08)); - dev->ISR.overwrite &= !((int)((val & 0x10) == 0x10)); - dev->ISR.cnt_oflow &= !((int)((val & 0x20) == 0x20)); - dev->ISR.rdma_done &= !((int)((val & 0x40) == 0x40)); - val = ((dev->ISR.rdma_done << 6) | - (dev->ISR.cnt_oflow << 5) | - (dev->ISR.overwrite << 4) | - (dev->ISR.tx_err << 3) | - (dev->ISR.rx_err << 2) | - (dev->ISR.pkt_tx << 1) | - (dev->ISR.pkt_rx)); - val &= ((dev->IMR.rdma_inte << 6) | - (dev->IMR.cofl_inte << 5) | - (dev->IMR.overw_inte << 4) | - (dev->IMR.txerr_inte << 3) | - (dev->IMR.rxerr_inte << 2) | - (dev->IMR.tx_inte << 1) | - (dev->IMR.rx_inte)); - if ((val == 0x00) && dev->interrupt) - dev->interrupt(dev->priv, 0); - break; + case 0x07: /* ISR */ + val &= 0x7f; /* clear RST bit - status-only bit */ + /* All other values are cleared iff the ISR bit is 1 */ + dev->ISR.pkt_rx &= !((int) ((val & 0x01) == 0x01)); + dev->ISR.pkt_tx &= !((int) ((val & 0x02) == 0x02)); + dev->ISR.rx_err &= !((int) ((val & 0x04) == 0x04)); + dev->ISR.tx_err &= !((int) ((val & 0x08) == 0x08)); + dev->ISR.overwrite &= !((int) ((val & 0x10) == 0x10)); + dev->ISR.cnt_oflow &= !((int) ((val & 0x20) == 0x20)); + dev->ISR.rdma_done &= !((int) ((val & 0x40) == 0x40)); + val = ((dev->ISR.rdma_done << 6) | (dev->ISR.cnt_oflow << 5) | (dev->ISR.overwrite << 4) | (dev->ISR.tx_err << 3) | (dev->ISR.rx_err << 2) | (dev->ISR.pkt_tx << 1) | (dev->ISR.pkt_rx)); + val &= ((dev->IMR.rdma_inte << 6) | (dev->IMR.cofl_inte << 5) | (dev->IMR.overw_inte << 4) | (dev->IMR.txerr_inte << 3) | (dev->IMR.rxerr_inte << 2) | (dev->IMR.tx_inte << 1) | (dev->IMR.rx_inte)); + if ((val == 0x00) && dev->interrupt) + dev->interrupt(dev->priv, 0); + break; - case 0x08: /* RSAR0 */ - /* Clear out low byte and re-insert */ - dev->remote_start &= 0xff00; - dev->remote_start |= (val & 0xff); - dev->remote_dma = dev->remote_start; - break; + case 0x08: /* RSAR0 */ + /* Clear out low byte and re-insert */ + dev->remote_start &= 0xff00; + dev->remote_start |= (val & 0xff); + dev->remote_dma = dev->remote_start; + break; - case 0x09: /* RSAR1 */ - /* Clear out high byte and re-insert */ - dev->remote_start &= 0x00ff; - dev->remote_start |= ((val & 0xff) << 8); - dev->remote_dma = dev->remote_start; - break; + case 0x09: /* RSAR1 */ + /* Clear out high byte and re-insert */ + dev->remote_start &= 0x00ff; + dev->remote_start |= ((val & 0xff) << 8); + dev->remote_dma = dev->remote_start; + break; - case 0x0a: /* RBCR0 */ - /* Clear out low byte and re-insert */ - dev->remote_bytes &= 0xff00; - dev->remote_bytes |= (val & 0xff); - break; + case 0x0a: /* RBCR0 */ + /* Clear out low byte and re-insert */ + dev->remote_bytes &= 0xff00; + dev->remote_bytes |= (val & 0xff); + break; - case 0x0b: /* RBCR1 */ - /* Clear out high byte and re-insert */ - dev->remote_bytes &= 0x00ff; - dev->remote_bytes |= ((val & 0xff) << 8); - break; + case 0x0b: /* RBCR1 */ + /* Clear out high byte and re-insert */ + dev->remote_bytes &= 0x00ff; + dev->remote_bytes |= ((val & 0xff) << 8); + break; - case 0x0c: /* RCR */ - /* Check if the reserved bits are set */ + case 0x0c: /* RCR */ + /* Check if the reserved bits are set */ #ifdef ENABLE_DP8390_LOG - if (val & 0xc0) - dp8390_log("DP8390: RCR write, reserved bits set\n"); + if (val & 0xc0) + dp8390_log("DP8390: RCR write, reserved bits set\n"); #endif - /* Set all other bit-fields */ - dev->RCR.errors_ok = ((val & 0x01) == 0x01); - dev->RCR.runts_ok = ((val & 0x02) == 0x02); - dev->RCR.broadcast = ((val & 0x04) == 0x04); - dev->RCR.multicast = ((val & 0x08) == 0x08); - dev->RCR.promisc = ((val & 0x10) == 0x10); - dev->RCR.monitor = ((val & 0x20) == 0x20); + /* Set all other bit-fields */ + dev->RCR.errors_ok = ((val & 0x01) == 0x01); + dev->RCR.runts_ok = ((val & 0x02) == 0x02); + dev->RCR.broadcast = ((val & 0x04) == 0x04); + dev->RCR.multicast = ((val & 0x08) == 0x08); + dev->RCR.promisc = ((val & 0x10) == 0x10); + dev->RCR.monitor = ((val & 0x20) == 0x20); - /* Monitor bit is a little suspicious... */ + /* Monitor bit is a little suspicious... */ #ifdef ENABLE_DP8390_LOG - if (val & 0x20) - dp8390_log("DP8390: RCR write, monitor bit set!\n"); + if (val & 0x20) + dp8390_log("DP8390: RCR write, monitor bit set!\n"); #endif - break; + break; - case 0x0d: /* TCR */ - /* Check reserved bits */ + case 0x0d: /* TCR */ + /* Check reserved bits */ #ifdef ENABLE_DP8390_LOG - if (val & 0xe0) - dp8390_log("DP8390: TCR write, reserved bits set\n"); + if (val & 0xe0) + dp8390_log("DP8390: TCR write, reserved bits set\n"); #endif - /* Test loop mode (not supported) */ - if (val & 0x06) { - dev->TCR.loop_cntl = (val & 0x6) >> 1; - dp8390_log("DP8390: TCR write, loop mode %d not supported\n", - dev->TCR.loop_cntl); - } else - dev->TCR.loop_cntl = 0; + /* Test loop mode (not supported) */ + if (val & 0x06) { + dev->TCR.loop_cntl = (val & 0x6) >> 1; + dp8390_log("DP8390: TCR write, loop mode %d not supported\n", + dev->TCR.loop_cntl); + } else + dev->TCR.loop_cntl = 0; - /* Inhibit-CRC not supported. */ + /* Inhibit-CRC not supported. */ #ifdef ENABLE_DP8390_LOG - if (val & 0x01) - dp8390_log("DP8390: TCR write, inhibit-CRC not supported\n"); + if (val & 0x01) + dp8390_log("DP8390: TCR write, inhibit-CRC not supported\n"); #endif - /* Auto-transmit disable very suspicious */ + /* Auto-transmit disable very suspicious */ #ifdef ENABLE_DP8390_LOG - if (val & 0x08) - dp8390_log("DP8390: TCR write, auto transmit disable not supported\n"); + if (val & 0x08) + dp8390_log("DP8390: TCR write, auto transmit disable not supported\n"); #endif - /* Allow collision-offset to be set, although not used */ - dev->TCR.coll_prio = ((val & 0x08) == 0x08); - break; + /* Allow collision-offset to be set, although not used */ + dev->TCR.coll_prio = ((val & 0x08) == 0x08); + break; - case 0x0e: /* DCR */ - /* the loopback mode is not suppported yet */ + case 0x0e: /* DCR */ + /* the loopback mode is not suppported yet */ #ifdef ENABLE_DP8390_LOG - if (! (val & 0x08)) - dp8390_log("DP8390: DCR write, loopback mode selected\n"); + if (!(val & 0x08)) + dp8390_log("DP8390: DCR write, loopback mode selected\n"); #endif - /* It is questionable to set longaddr and auto_rx, since - * they are not supported on the NE2000. Print a warning - * and continue. */ + /* It is questionable to set longaddr and auto_rx, since + * they are not supported on the NE2000. Print a warning + * and continue. */ #ifdef ENABLE_DP8390_LOG - if (val & 0x04) - dp8390_log("DP8390: DCR write - LAS set ???\n"); - if (val & 0x10) - dp8390_log("DP8390: DCR write - AR set ???\n"); + if (val & 0x04) + dp8390_log("DP8390: DCR write - LAS set ???\n"); + if (val & 0x10) + dp8390_log("DP8390: DCR write - AR set ???\n"); #endif - /* Set other values. */ - dev->DCR.wdsize = ((val & 0x01) == 0x01); - dev->DCR.endian = ((val & 0x02) == 0x02); - dev->DCR.longaddr = ((val & 0x04) == 0x04); /* illegal ? */ - dev->DCR.loop = ((val & 0x08) == 0x08); - dev->DCR.auto_rx = ((val & 0x10) == 0x10); /* also illegal ? */ - dev->DCR.fifo_size = (val & 0x50) >> 5; - break; + /* Set other values. */ + dev->DCR.wdsize = ((val & 0x01) == 0x01); + dev->DCR.endian = ((val & 0x02) == 0x02); + dev->DCR.longaddr = ((val & 0x04) == 0x04); /* illegal ? */ + dev->DCR.loop = ((val & 0x08) == 0x08); + dev->DCR.auto_rx = ((val & 0x10) == 0x10); /* also illegal ? */ + dev->DCR.fifo_size = (val & 0x60) >> 5; + break; - case 0x0f: /* IMR */ - /* Check for reserved bit */ + case 0x0f: /* IMR */ + /* Check for reserved bit */ #ifdef ENABLE_DP8390_LOG - if (val & 0x80) - dp8390_log("DP8390: IMR write, reserved bit set\n"); + if (val & 0x80) + dp8390_log("DP8390: IMR write, reserved bit set\n"); #endif - /* Set other values */ - dev->IMR.rx_inte = ((val & 0x01) == 0x01); - dev->IMR.tx_inte = ((val & 0x02) == 0x02); - dev->IMR.rxerr_inte = ((val & 0x04) == 0x04); - dev->IMR.txerr_inte = ((val & 0x08) == 0x08); - dev->IMR.overw_inte = ((val & 0x10) == 0x10); - dev->IMR.cofl_inte = ((val & 0x20) == 0x20); - dev->IMR.rdma_inte = ((val & 0x40) == 0x40); - val2 = ((dev->ISR.rdma_done << 6) | - (dev->ISR.cnt_oflow << 5) | - (dev->ISR.overwrite << 4) | - (dev->ISR.tx_err << 3) | - (dev->ISR.rx_err << 2) | - (dev->ISR.pkt_tx << 1) | - (dev->ISR.pkt_rx)); - if (dev->interrupt) { - if (((val & val2) & 0x7f) == 0) - dev->interrupt(dev->priv, 0); - else - dev->interrupt(dev->priv, 1); - } - break; + /* Set other values */ + dev->IMR.rx_inte = ((val & 0x01) == 0x01); + dev->IMR.tx_inte = ((val & 0x02) == 0x02); + dev->IMR.rxerr_inte = ((val & 0x04) == 0x04); + dev->IMR.txerr_inte = ((val & 0x08) == 0x08); + dev->IMR.overw_inte = ((val & 0x10) == 0x10); + dev->IMR.cofl_inte = ((val & 0x20) == 0x20); + dev->IMR.rdma_inte = ((val & 0x40) == 0x40); + val2 = ((dev->ISR.rdma_done << 6) | (dev->ISR.cnt_oflow << 5) | (dev->ISR.overwrite << 4) | (dev->ISR.tx_err << 3) | (dev->ISR.rx_err << 2) | (dev->ISR.pkt_tx << 1) | (dev->ISR.pkt_rx)); + if (dev->interrupt) { + if (((val & val2) & 0x7f) == 0) + dev->interrupt(dev->priv, 0); + else + dev->interrupt(dev->priv, 1); + } + break; - default: - dp8390_log("DP8390: Page0 write, bad register 0x%02x\n", off); - break; + default: + dp8390_log("DP8390: Page0 write, bad register 0x%02x\n", off); + break; } } - /* Handle reads/writes to the first page of the DS8390 register file. */ uint32_t -dp8390_page1_read(dp8390_t *dev, uint32_t off, unsigned int len) +dp8390_page1_read(dp8390_t *dev, uint32_t off, UNUSED(unsigned int len)) { dp8390_log("DP8390: Page1 read from register 0x%02x, len=%u\n", - off, len); + off, len); - switch(off) { - case 0x01: /* PAR0-5 */ - case 0x02: - case 0x03: - case 0x04: - case 0x05: - case 0x06: - return(dev->physaddr[off - 1]); + switch (off) { + case 0x01: /* PAR0-5 */ + case 0x02: + case 0x03: + case 0x04: + case 0x05: + case 0x06: + return (dev->physaddr[off - 1]); - case 0x07: /* CURR */ - dp8390_log("DP8390: returning current page: 0x%02x\n", - (dev->curr_page)); - return(dev->curr_page); + case 0x07: /* CURR */ + dp8390_log("DP8390: returning current page: 0x%02x\n", + (dev->curr_page)); + return (dev->curr_page); - case 0x08: /* MAR0-7 */ - case 0x09: - case 0x0a: - case 0x0b: - case 0x0c: - case 0x0d: - case 0x0e: - case 0x0f: - return(dev->mchash[off - 8]); + case 0x08: /* MAR0-7 */ + case 0x09: + case 0x0a: + case 0x0b: + case 0x0c: + case 0x0d: + case 0x0e: + case 0x0f: + return (dev->mchash[off - 8]); - default: - dp8390_log("DP8390: Page1 read register 0x%02x out of range\n", - off); - return(0); + default: + dp8390_log("DP8390: Page1 read register 0x%02x out of range\n", + off); + return 0; } } - void -dp8390_page1_write(dp8390_t *dev, uint32_t off, uint32_t val, unsigned len) +dp8390_page1_write(dp8390_t *dev, uint32_t off, uint32_t val, UNUSED(unsigned len)) { dp8390_log("DP8390: Page1 write to register 0x%02x, len=%u, value=0x%04x\n", - off, len, val); + off, len, val); - switch(off) { - case 0x01: /* PAR0-5 */ - case 0x02: - case 0x03: - case 0x04: - case 0x05: - case 0x06: - dev->physaddr[off - 1] = val; - if (off == 6) - dp8390_log("DP8390: Physical address set to %02x:%02x:%02x:%02x:%02x:%02x\n", - dev->dp8390->physaddr[0], dev->dp8390.physaddr[1], - dev->dp8390->physaddr[2], dev->dp8390.physaddr[3], - dev->dp8390->physaddr[4], dev->dp8390.physaddr[5]); - break; + switch (off) { + case 0x01: /* PAR0-5 */ + case 0x02: + case 0x03: + case 0x04: + case 0x05: + case 0x06: + dev->physaddr[off - 1] = val; + if (off == 6) + dp8390_log("DP8390: Physical address set to %02x:%02x:%02x:%02x:%02x:%02x\n", + dev->physaddr[0], dev->physaddr[1], + dev->physaddr[2], dev->physaddr[3], + dev->physaddr[4], dev->physaddr[5]); + break; - case 0x07: /* CURR */ - dev->curr_page = val; - break; + case 0x07: /* CURR */ + dev->curr_page = val; + break; - case 0x08: /* MAR0-7 */ - case 0x09: - case 0x0a: - case 0x0b: - case 0x0c: - case 0x0d: - case 0x0e: - case 0x0f: - dev->mchash[off - 8] = val; - break; + case 0x08: /* MAR0-7 */ + case 0x09: + case 0x0a: + case 0x0b: + case 0x0c: + case 0x0d: + case 0x0e: + case 0x0f: + dev->mchash[off - 8] = val; + break; - default: - dp8390_log("DP8390: Page1 write register 0x%02x out of range\n", - off); - break; + default: + dp8390_log("DP8390: Page1 write register 0x%02x out of range\n", + off); + break; } } - /* Handle reads/writes to the second page of the DS8390 register file. */ uint32_t -dp8390_page2_read(dp8390_t *dev, uint32_t off, unsigned int len) +dp8390_page2_read(dp8390_t *dev, uint32_t off, UNUSED(unsigned int len)) { dp8390_log("DP8390: Page2 read from register 0x%02x, len=%u\n", - off, len); - - switch(off) { - case 0x01: /* PSTART */ - return(dev->page_start); + off, len); - case 0x02: /* PSTOP */ - return(dev->page_stop); + switch (off) { + case 0x01: /* PSTART */ + return (dev->page_start); - case 0x03: /* Remote Next-packet pointer */ - return(dev->rempkt_ptr); + case 0x02: /* PSTOP */ + return (dev->page_stop); - case 0x04: /* TPSR */ - return(dev->tx_page_start); + case 0x03: /* Remote Next-packet pointer */ + return (dev->rempkt_ptr); - case 0x05: /* Local Next-packet pointer */ - return(dev->localpkt_ptr); + case 0x04: /* TPSR */ + return (dev->tx_page_start); - case 0x06: /* Address counter (upper) */ - return(dev->address_cnt >> 8); + case 0x05: /* Local Next-packet pointer */ + return (dev->localpkt_ptr); - case 0x07: /* Address counter (lower) */ - return(dev->address_cnt & 0xff); + case 0x06: /* Address counter (upper) */ + return (dev->address_cnt >> 8); - case 0x08: /* Reserved */ - case 0x09: - case 0x0a: - case 0x0b: - dp8390_log("DP8390: reserved Page2 read - register 0x%02x\n", - off); - return(0xff); + case 0x07: /* Address counter (lower) */ + return (dev->address_cnt & 0xff); - case 0x0c: /* RCR */ - return ((dev->RCR.monitor << 5) | - (dev->RCR.promisc << 4) | - (dev->RCR.multicast << 3) | - (dev->RCR.broadcast << 2) | - (dev->RCR.runts_ok << 1) | - (dev->RCR.errors_ok)); + case 0x08: /* Reserved */ + case 0x09: + case 0x0a: + case 0x0b: + dp8390_log("DP8390: reserved Page2 read - register 0x%02x\n", + off); + return 0xff; - case 0x0d: /* TCR */ - return ((dev->TCR.coll_prio << 4) | - (dev->TCR.ext_stoptx << 3) | - ((dev->TCR.loop_cntl & 0x3) << 1) | - (dev->TCR.crc_disable)); + case 0x0c: /* RCR */ + return ((dev->RCR.monitor << 5) | (dev->RCR.promisc << 4) | (dev->RCR.multicast << 3) | (dev->RCR.broadcast << 2) | (dev->RCR.runts_ok << 1) | (dev->RCR.errors_ok)); - case 0x0e: /* DCR */ - return (((dev->DCR.fifo_size & 0x3) << 5) | - (dev->DCR.auto_rx << 4) | - (dev->DCR.loop << 3) | - (dev->DCR.longaddr << 2) | - (dev->DCR.endian << 1) | - (dev->DCR.wdsize)); + case 0x0d: /* TCR */ + return ((dev->TCR.coll_prio << 4) | (dev->TCR.ext_stoptx << 3) | ((dev->TCR.loop_cntl & 0x3) << 1) | (dev->TCR.crc_disable)); - case 0x0f: /* IMR */ - return ((dev->IMR.rdma_inte << 6) | - (dev->IMR.cofl_inte << 5) | - (dev->IMR.overw_inte << 4) | - (dev->IMR.txerr_inte << 3) | - (dev->IMR.rxerr_inte << 2) | - (dev->IMR.tx_inte << 1) | - (dev->IMR.rx_inte)); + case 0x0e: /* DCR */ + return (((dev->DCR.fifo_size & 0x3) << 5) | (dev->DCR.auto_rx << 4) | (dev->DCR.loop << 3) | (dev->DCR.longaddr << 2) | (dev->DCR.endian << 1) | (dev->DCR.wdsize)); - default: - dp8390_log("DP8390: Page2 register 0x%02x out of range\n", - off); - break; + case 0x0f: /* IMR */ + return ((dev->IMR.rdma_inte << 6) | (dev->IMR.cofl_inte << 5) | (dev->IMR.overw_inte << 4) | (dev->IMR.txerr_inte << 3) | (dev->IMR.rxerr_inte << 2) | (dev->IMR.tx_inte << 1) | (dev->IMR.rx_inte)); + + default: + dp8390_log("DP8390: Page2 register 0x%02x out of range\n", + off); + break; } - return(0); + return 0; } - void -dp8390_page2_write(dp8390_t *dev, uint32_t off, uint32_t val, unsigned len) +dp8390_page2_write(dp8390_t *dev, uint32_t off, uint32_t val, UNUSED(unsigned len)) { -/* Maybe all writes here should be BX_PANIC()'d, since they - affect internal operation, but let them through for now - and print a warning. */ + /* Maybe all writes here should be BX_PANIC()'d, since they + affect internal operation, but let them through for now + and print a warning. */ dp8390_log("DP8390: Page2 write to register 0x%02x, len=%u, value=0x%04x\n", - off, len, val); + off, len, val); - switch(off) { - case 0x01: /* CLDA0 */ - /* Clear out low byte and re-insert */ - dev->local_dma &= 0xff00; - dev->local_dma |= (val & 0xff); - break; + switch (off) { + case 0x01: /* CLDA0 */ + /* Clear out low byte and re-insert */ + dev->local_dma &= 0xff00; + dev->local_dma |= (val & 0xff); + break; - case 0x02: /* CLDA1 */ - /* Clear out high byte and re-insert */ - dev->local_dma &= 0x00ff; - dev->local_dma |= ((val & 0xff) << 8); - break; + case 0x02: /* CLDA1 */ + /* Clear out high byte and re-insert */ + dev->local_dma &= 0x00ff; + dev->local_dma |= ((val & 0xff) << 8); + break; - case 0x03: /* Remote Next-pkt pointer */ - dev->rempkt_ptr = val; - break; + case 0x03: /* Remote Next-pkt pointer */ + dev->rempkt_ptr = val; + break; - case 0x04: + case 0x04: #ifdef ENABLE_DP8390_LOG - dp8390_log("DP8390: Page 2 write to reserved register 0x04\n"); + dp8390_log("DP8390: Page 2 write to reserved register 0x04\n"); #endif - break; + break; - case 0x05: /* Local Next-packet pointer */ - dev->localpkt_ptr = val; - break; + case 0x05: /* Local Next-packet pointer */ + dev->localpkt_ptr = val; + break; - case 0x06: /* Address counter (upper) */ - /* Clear out high byte and re-insert */ - dev->address_cnt &= 0x00ff; - dev->address_cnt |= ((val & 0xff) << 8); - break; + case 0x06: /* Address counter (upper) */ + /* Clear out high byte and re-insert */ + dev->address_cnt &= 0x00ff; + dev->address_cnt |= ((val & 0xff) << 8); + break; - case 0x07: /* Address counter (lower) */ - /* Clear out low byte and re-insert */ - dev->address_cnt &= 0xff00; - dev->address_cnt |= (val & 0xff); - break; + case 0x07: /* Address counter (lower) */ + /* Clear out low byte and re-insert */ + dev->address_cnt &= 0xff00; + dev->address_cnt |= (val & 0xff); + break; - case 0x08: - case 0x09: - case 0x0a: - case 0x0b: - case 0x0c: - case 0x0d: - case 0x0e: - case 0x0f: - dp8390_log("DP8390: Page2 write to reserved register 0x%02x\n", - off); - break; + case 0x08: + case 0x09: + case 0x0a: + case 0x0b: + case 0x0c: + case 0x0d: + case 0x0e: + case 0x0f: + dp8390_log("DP8390: Page2 write to reserved register 0x%02x\n", + off); + break; - default: - dp8390_log("DP8390: Page2 write, illegal register 0x%02x\n", - off); - break; + default: + dp8390_log("DP8390: Page2 write, illegal register 0x%02x\n", + off); + break; } } - void dp8390_set_defaults(dp8390_t *dev, uint8_t flags) { @@ -983,19 +910,18 @@ dp8390_set_defaults(dp8390_t *dev, uint8_t flags) dev->flags = flags; } - void dp8390_mem_alloc(dp8390_t *dev, uint32_t start, uint32_t size) { dev->mem = (uint8_t *) malloc(size * sizeof(uint8_t)); memset(dev->mem, 0, size * sizeof(uint8_t)); dev->mem_start = start; - dev->mem_end = start + size; - dev->mem_size = size; + dev->mem_end = start + size; + dev->mem_size = size; + dev->mem_wrap = size - 1; dp8390_log("DP8390: Mapped %i bytes of memory at address %04X in the address space\n", size, start); } - void dp8390_set_id(dp8390_t *dev, uint8_t id0, uint8_t id1) { @@ -1003,27 +929,27 @@ dp8390_set_id(dp8390_t *dev, uint8_t id0, uint8_t id1) dev->id1 = id1; } - void dp8390_reset(dp8390_t *dev) { - int i, max, shift = 0; + int max; + int shift = 0; if (dev->flags & DP8390_FLAG_EVEN_MAC) - shift = 1; + shift = 1; max = 16 << shift; /* Initialize the MAC address area by doubling the physical address */ - for (i = 0; i < max; i++) { - if (i < (6 << shift)) - dev->macaddr[i] = dev->physaddr[i >> shift]; - else /* Signature */ - dev->macaddr[i] = 0x57; + for (int i = 0; i < max; i++) { + if (i < (6 << shift)) + dev->macaddr[i] = dev->physaddr[i >> shift]; + else /* Signature */ + dev->macaddr[i] = 0x57; } /* Zero out registers and memory */ - memset(&dev->CR, 0x00, sizeof(dev->CR) ); + memset(&dev->CR, 0x00, sizeof(dev->CR)); memset(&dev->ISR, 0x00, sizeof(dev->ISR)); memset(&dev->IMR, 0x00, sizeof(dev->IMR)); memset(&dev->DCR, 0x00, sizeof(dev->DCR)); @@ -1031,16 +957,16 @@ dp8390_reset(dp8390_t *dev) memset(&dev->TSR, 0x00, sizeof(dev->TSR)); memset(&dev->RSR, 0x00, sizeof(dev->RSR)); dev->tx_timer_active = 0; - dev->local_dma = 0; - dev->page_start = 0; - dev->page_stop = 0; - dev->bound_ptr = 0; - dev->tx_page_start = 0; - dev->num_coll = 0; - dev->tx_bytes = 0; - dev->fifo = 0; - dev->remote_dma = 0; - dev->remote_start = 0; + dev->local_dma = 0; + dev->page_start = 0; + dev->page_stop = 0; + dev->bound_ptr = 0; + dev->tx_page_start = 0; + dev->num_coll = 0; + dev->tx_bytes = 0; + dev->fifo = 0; + dev->remote_dma = 0; + dev->remote_start = 0; dev->remote_bytes = 0; @@ -1063,10 +989,9 @@ dp8390_reset(dp8390_t *dev) dev->DCR.longaddr = 1; if (dev->interrupt) - dev->interrupt(dev->priv, 0); + dev->interrupt(dev->priv, 0); } - void dp8390_soft_reset(dp8390_t *dev) { @@ -1074,9 +999,8 @@ dp8390_soft_reset(dp8390_t *dev) dev->ISR.reset = 1; } - static void * -dp8390_init(const device_t *info) +dp8390_init(UNUSED(const device_t *info)) { dp8390_t *dp8390 = (dp8390_t *) malloc(sizeof(dp8390_t)); memset(dp8390, 0, sizeof(dp8390_t)); @@ -1093,29 +1017,33 @@ dp8390_init(const device_t *info) return dp8390; } - static void dp8390_close(void *priv) { dp8390_t *dp8390 = (dp8390_t *) priv; - /* Make sure the platform layer is shut down. */ - network_close(); - if (dp8390) { - if (dp8390->mem) - free(dp8390->mem); + if (dp8390->mem) + free(dp8390->mem); - free(dp8390); + if (dp8390->card) { + netcard_close(dp8390->card); + } + + free(dp8390); } } - -const device_t dp8390_device = -{ - "DP8390 Network Interface Controller", - "dp8390", - 0, 0, - dp8390_init, dp8390_close, - NULL, { NULL }, NULL, NULL +const device_t dp8390_device = { + .name = "DP8390 Network Interface Controller", + .internal_name = "dp8390", + .flags = 0, + .local = 0, + .init = dp8390_init, + .close = dp8390_close, + .reset = NULL, + { .available = NULL }, + .speed_changed = NULL, + .force_redraw = NULL, + .config = NULL }; diff --git a/src/network/net_event.c b/src/network/net_event.c new file mode 100644 index 000000000..c39c12254 --- /dev/null +++ b/src/network/net_event.c @@ -0,0 +1,77 @@ +#ifdef _WIN32 +# define WIN32_LEAN_AND_MEAN +# include +#else +# include +# include +#endif + +#include <86box/net_event.h> +#include <86box/plat_unused.h> + +#ifndef _WIN32 +static void +setup_fd(int fd) +{ + fcntl(fd, F_SETFD, FD_CLOEXEC); + fcntl(fd, F_SETFL, O_NONBLOCK); +} +#endif + +void +net_event_init(net_evt_t *event) +{ +#ifdef _WIN32 + event->handle = CreateEvent(NULL, FALSE, FALSE, NULL); +#else + (void) !pipe(event->fds); + setup_fd(event->fds[0]); + setup_fd(event->fds[1]); +#endif +} + +void +net_event_set(net_evt_t *event) +{ +#ifdef _WIN32 + SetEvent(event->handle); +#else + (void) !write(event->fds[1], "a", 1); +#endif +} + +void +net_event_clear(UNUSED(net_evt_t *event)) +{ +#ifdef _WIN32 + /* Do nothing on WIN32 since we use an auto-reset event */ +#else + char dummy[1]; + (void) !read(event->fds[0], &dummy, sizeof(dummy)); +#endif +} + +void +net_event_close(net_evt_t *event) +{ +#ifdef _WIN32 + CloseHandle(event->handle); +#else + close(event->fds[0]); + close(event->fds[1]); +#endif +} + +#ifdef _WIN32 +HANDLE +net_event_get_handle(net_evt_t *event) +{ + return event->handle; +} +#else +int +net_event_get_fd(net_evt_t *event) +{ + return event->fds[0]; +} +#endif \ No newline at end of file diff --git a/src/network/net_ne2000.c b/src/network/net_ne2000.c index 6878e4f94..c7fba404f 100644 --- a/src/network/net_ne2000.c +++ b/src/network/net_ne2000.c @@ -1,30 +1,30 @@ /* - * VARCem Virtual ARchaeological Computer EMulator. - * An emulator of (mostly) x86-based PC systems and devices, - * using the ISA,EISA,VLB,MCA and PCI system buses, roughly - * spanning the era between 1981 and 1995. + * 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 VARCem Project. + * This file is part of the 86Box distribution. * - * Implementation of the following network controllers: - * - Novell NE1000 (ISA 8-bit); - * - Novell NE2000 (ISA 16-bit); - * - Novell NE/2 compatible (NetWorth Inc. Ethernext/MC) (MCA 16-bit); - * - Realtek RTL8019AS (ISA 16-bit, PnP); - * - Realtek RTL8029AS (PCI). + * Implementation of the following network controllers: + * - Novell NE1000 (ISA 8-bit); + * - Novell NE2000 (ISA 16-bit); + * - Novell NE/2 compatible (NetWorth Inc. Ethernext/MC) (MCA 16-bit); + * - Realtek RTL8019AS (ISA 16-bit, PnP); + * - Realtek RTL8029AS (PCI). * * * - * Based on @(#)ne2k.cc v1.56.2.1 2004/02/02 22:37:22 cbothamy + * Based on @(#)ne2k.cc v1.56.2.1 2004/02/02 22:37:22 cbothamy * - * Authors: Fred N. van Kempen, - * TheCollector1995, - * Miran Grca, - * Peter Grehan, + * Authors: Fred N. van Kempen, + * TheCollector1995, + * Miran Grca, + * Peter Grehan, * - * Copyright 2017,2018 Fred N. van Kempen. - * Copyright 2016-2018 Miran Grca. - * Portions Copyright (C) 2002 MandrakeSoft S.A. + * Copyright 2017-2018 Fred N. van Kempen. + * Copyright 2016-2018 Miran Grca. + * Portions Copyright (C) 2002 MandrakeSoft S.A. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -61,68 +61,82 @@ #include <86box/pic.h> #include <86box/random.h> #include <86box/device.h> +#include <86box/thread.h> +#include <86box/timer.h> #include <86box/network.h> #include <86box/net_dp8390.h> #include <86box/net_ne2000.h> #include <86box/bswap.h> #include <86box/isapnp.h> - +#include <86box/plat_fallthrough.h> +#include <86box/plat_unused.h> /* ROM BIOS file paths. */ -#define ROM_PATH_NE1000 "roms/network/ne1000/ne1000.rom" -#define ROM_PATH_NE2000 "roms/network/ne2000/ne2000.rom" -#define ROM_PATH_RTL8019 "roms/network/rtl8019as/rtl8019as.rom" -#define ROM_PATH_RTL8029 "roms/network/rtl8029as/rtl8029as.rom" +#define ROM_PATH_NE1000 "roms/network/ne1000/ne1000.rom" +#define ROM_PATH_NE2000 "roms/network/ne2000/ne2000.rom" +#define ROM_PATH_RTL8019 "roms/network/rtl8019as/rtl8019as.rom" +#define ROM_PATH_RTL8029 "roms/network/rtl8029as/rtl8029as.rom" /* PCI info. */ -#define PCI_VENDID 0x10ec /* Realtek, Inc */ -#define PCI_DEVID 0x8029 /* RTL8029AS */ -#define PCI_REGSIZE 256 /* size of PCI space */ - +#define PCI_VENDID 0x10ec /* Realtek, Inc */ +#define PCI_DEVID 0x8029 /* RTL8029AS */ +#define PCI_REGSIZE 256 /* size of PCI space */ static uint8_t rtl8019as_pnp_rom[] = { - 0x4a, 0x8c, 0x80, 0x19, 0x00, 0x00, 0x00, 0x00, 0x00, /* RTL8019, dummy checksum (filled in by isapnp_add_card) */ - 0x0a, 0x10, 0x10, /* PnP version 1.0, vendor version 1.0 */ + 0x4a, 0x8c, 0x80, 0x19, 0x00, 0x00, 0x00, 0x00, 0x00, /* RTL8019, dummy checksum (filled in by isapnp_add_card) */ + 0x0a, 0x10, 0x10, /* PnP version 1.0, vendor version 1.0 */ 0x82, 0x22, 0x00, 'R', 'E', 'A', 'L', 'T', 'E', 'K', ' ', 'P', 'L', 'U', 'G', ' ', '&', ' ', 'P', 'L', 'A', 'Y', ' ', 'E', 'T', 'H', 'E', 'R', 'N', 'E', 'T', ' ', 'C', 'A', 'R', 'D', 0x00, /* ANSI identifier */ - - 0x16, 0x4a, 0x8c, 0x80, 0x19, 0x02, 0x00, /* logical device RTL8019 */ - 0x1c, 0x41, 0xd0, 0x80, 0xd6, /* compatible device PNP80D6 */ - 0x47, 0x00, 0x20, 0x02, 0x80, 0x03, 0x20, 0x20, /* I/O 0x220-0x380, decodes 10-bit, 32-byte alignment, 32 addresses */ - 0x23, 0x38, 0x9e, 0x01, /* IRQ 3/4/5/9/10/11/12/15, high true edge sensitive */ + + 0x16, 0x4a, 0x8c, 0x80, 0x19, 0x02, 0x00, /* logical device RTL8019 */ + 0x1c, 0x41, 0xd0, 0x80, 0xd6, /* compatible device PNP80D6 */ + 0x47, 0x00, 0x20, 0x02, 0x80, 0x03, 0x20, 0x20, /* I/O 0x220-0x380, decodes 10-bit, 32-byte alignment, 32 addresses */ + 0x23, 0x38, 0x9e, 0x01, /* IRQ 3/4/5/9/10/11/12/15, high true edge sensitive */ 0x79, 0x00 /* end tag, dummy checksum (filled in by isapnp_add_card) */ }; +typedef struct nic_t { + dp8390_t *dp8390; -typedef struct { - dp8390_t *dp8390; - const char *name; - int board; - int is_pci, is_mca, is_8bit; - uint32_t base_address; - int base_irq; - uint32_t bios_addr, - bios_size, - bios_mask; - int card; /* PCI card slot */ - int has_bios, pad; - bar_t pci_bar[2]; - uint8_t pci_regs[PCI_REGSIZE]; - uint8_t eeprom[128]; /* for RTL8029AS */ - rom_t bios_rom; - void *pnp_card; - uint8_t pnp_csnsav; - uint8_t maclocal[6]; /* configured MAC (local) address */ + const char *name; + + uint8_t pnp_csnsav; + uint8_t pci_slot; + uint8_t irq_state; + uint8_t pad; /* RTL8019AS/RTL8029AS registers */ - uint8_t config0, config2, config3; - uint8_t _9346cr; - uint32_t pad0; + uint8_t config0; + uint8_t config2; + uint8_t config3; + uint8_t _9346cr; + + uint8_t pci_regs[PCI_REGSIZE]; + uint8_t eeprom[128]; /* for RTL8029AS */ + + uint8_t maclocal[6]; /* configured MAC (local) address */ /* POS registers, MCA boards only */ - uint8_t pos_regs[8]; -} nic_t; + uint8_t pos_regs[8]; + int board; + int is_pci; + int is_mca; + int is_8bit; + int base_irq; + int has_bios; + + uint32_t base_address; + uint32_t bios_addr; + uint32_t bios_size; + uint32_t bios_mask; + + bar_t pci_bar[2]; + + rom_t bios_rom; + + void *pnp_card; +} nic_t; #ifdef ENABLE_NE2K_LOG int ne2k_do_log = ENABLE_NE2K_LOG; @@ -133,56 +147,52 @@ nelog(int lvl, const char *fmt, ...) va_list ap; if (ne2k_do_log >= lvl) { - va_start(ap, fmt); - pclog_ex(fmt, ap); - va_end(ap); + va_start(ap, fmt); + pclog_ex(fmt, ap); + va_end(ap); } } #else -#define nelog(lvl, fmt, ...) +# define nelog(lvl, fmt, ...) #endif - static void nic_interrupt(void *priv, int set) { nic_t *dev = (nic_t *) priv; if (dev->is_pci) { - if (set) - pci_set_irq(dev->card, PCI_INTA); - else - pci_clear_irq(dev->card, PCI_INTA); + if (set) + pci_set_irq(dev->pci_slot, PCI_INTA, &dev->irq_state); + else + pci_clear_irq(dev->pci_slot, PCI_INTA, &dev->irq_state); } else { - if (set) - picint(1<base_irq); - else - picintc(1<base_irq); - } + if (set) + picint(1 << dev->base_irq); + else + picintc(1 << dev->base_irq); + } } - /* reset - restore state to power-up, cancelling all i/o */ static void nic_reset(void *priv) { - nic_t *dev = (nic_t *)priv; + nic_t *dev = (nic_t *) priv; nelog(1, "%s: reset\n", dev->name); dp8390_reset(dev->dp8390); } - static void nic_soft_reset(void *priv) { - nic_t *dev = (nic_t *)priv; + nic_t *dev = (nic_t *) priv; dp8390_soft_reset(dev->dp8390); } - /* * Access the ASIC I/O space. * @@ -201,246 +211,241 @@ asic_read(nic_t *dev, uint32_t off, unsigned int len) { uint32_t retval = 0; - switch(off) { - case 0x00: /* Data register */ - /* A read remote-DMA command must have been issued, - and the source-address and length registers must - have been initialised. */ - if (len > dev->dp8390->remote_bytes) { - nelog(3, "%s: DMA read underrun iolen=%d remote_bytes=%d\n", - dev->name, len, dev->dp8390->remote_bytes); - } + switch (off) { + case 0x00: /* Data register */ + /* A read remote-DMA command must have been issued, + and the source-address and length registers must + have been initialised. */ + if (len > dev->dp8390->remote_bytes) { + nelog(3, "%s: DMA read underrun iolen=%d remote_bytes=%d\n", + dev->name, len, dev->dp8390->remote_bytes); + } - nelog(3, "%s: DMA read: addr=%4x remote_bytes=%d\n", - dev->name, dev->dp8390->remote_dma,dev->dp8390->remote_bytes); - retval = dp8390_chipmem_read(dev->dp8390, dev->dp8390->remote_dma, len); + nelog(3, "%s: DMA read: addr=%4x remote_bytes=%d\n", + dev->name, dev->dp8390->remote_dma, dev->dp8390->remote_bytes); + retval = dp8390_chipmem_read(dev->dp8390, dev->dp8390->remote_dma, len); - /* The 8390 bumps the address and decreases the byte count - by the selected word size after every access, not by - the amount of data requested by the host (io_len). */ - if (len == 4) { - dev->dp8390->remote_dma += len; - } else { - dev->dp8390->remote_dma += (dev->dp8390->DCR.wdsize + 1); - } + /* The 8390 bumps the address and decreases the byte count + by the selected word size after every access, not by + the amount of data requested by the host (io_len). */ + if (len == 4) { + dev->dp8390->remote_dma += len; + } else { + dev->dp8390->remote_dma += (dev->dp8390->DCR.wdsize + 1); + } - if (dev->dp8390->remote_dma == dev->dp8390->page_stop << 8) { - dev->dp8390->remote_dma = dev->dp8390->page_start << 8; - } + if (dev->dp8390->remote_dma == dev->dp8390->page_stop << 8) { + dev->dp8390->remote_dma = dev->dp8390->page_start << 8; + } - /* keep s.remote_bytes from underflowing */ - if (dev->dp8390->remote_bytes > dev->dp8390->DCR.wdsize) { - if (len == 4) { - dev->dp8390->remote_bytes -= len; - } else { - dev->dp8390->remote_bytes -= (dev->dp8390->DCR.wdsize + 1); - } - } else { - dev->dp8390->remote_bytes = 0; - } + /* keep s.remote_bytes from underflowing */ + if (dev->dp8390->remote_bytes > dev->dp8390->DCR.wdsize) { + if (len == 4) { + dev->dp8390->remote_bytes -= len; + } else { + dev->dp8390->remote_bytes -= (dev->dp8390->DCR.wdsize + 1); + } + } else { + dev->dp8390->remote_bytes = 0; + } - /* If all bytes have been written, signal remote-DMA complete */ - if (dev->dp8390->remote_bytes == 0) { - dev->dp8390->ISR.rdma_done = 1; - if (dev->dp8390->IMR.rdma_inte) - nic_interrupt(dev, 1); - } - break; + /* If all bytes have been written, signal remote-DMA complete */ + if (dev->dp8390->remote_bytes == 0) { + dev->dp8390->ISR.rdma_done = 1; + if (dev->dp8390->IMR.rdma_inte) + nic_interrupt(dev, 1); + } + break; - case 0x0f: /* Reset register */ - nic_soft_reset(dev); - break; + case 0x0f: /* Reset register */ + nic_soft_reset(dev); + break; - default: - nelog(3, "%s: ASIC read invalid address %04x\n", - dev->name, (unsigned)off); - break; + default: + nelog(3, "%s: ASIC read invalid address %04x\n", + dev->name, (unsigned) off); + break; } - return(retval); + return retval; } static void asic_write(nic_t *dev, uint32_t off, uint32_t val, unsigned len) { nelog(3, "%s: ASIC write addr=0x%02x, value=0x%04x\n", - dev->name, (unsigned)off, (unsigned) val); + dev->name, (unsigned) off, (unsigned) val); - switch(off) { - case 0x00: /* Data register - see asic_read for a description */ - if ((len > 1) && (dev->dp8390->DCR.wdsize == 0)) { - nelog(3, "%s: DMA write length %d on byte mode operation\n", - dev->name, len); - break; - } - if (dev->dp8390->remote_bytes == 0) - nelog(3, "%s: DMA write, byte count 0\n", dev->name); + switch (off) { + case 0x00: /* Data register - see asic_read for a description */ + if ((len > 1) && (dev->dp8390->DCR.wdsize == 0)) { + nelog(3, "%s: DMA write length %d on byte mode operation\n", + dev->name, len); + break; + } + if (dev->dp8390->remote_bytes == 0) + nelog(3, "%s: DMA write, byte count 0\n", dev->name); - dp8390_chipmem_write(dev->dp8390, dev->dp8390->remote_dma, val, len); - if (len == 4) - dev->dp8390->remote_dma += len; - else - dev->dp8390->remote_dma += (dev->dp8390->DCR.wdsize + 1); + dp8390_chipmem_write(dev->dp8390, dev->dp8390->remote_dma, val, len); + if (len == 4) + dev->dp8390->remote_dma += len; + else + dev->dp8390->remote_dma += (dev->dp8390->DCR.wdsize + 1); - if (dev->dp8390->remote_dma == dev->dp8390->page_stop << 8) - dev->dp8390->remote_dma = dev->dp8390->page_start << 8; + if (dev->dp8390->remote_dma == dev->dp8390->page_stop << 8) + dev->dp8390->remote_dma = dev->dp8390->page_start << 8; - if (len == 4) - dev->dp8390->remote_bytes -= len; - else - dev->dp8390->remote_bytes -= (dev->dp8390->DCR.wdsize + 1); + if (len == 4) + dev->dp8390->remote_bytes -= len; + else + dev->dp8390->remote_bytes -= (dev->dp8390->DCR.wdsize + 1); - if (dev->dp8390->remote_bytes > dev->dp8390->mem_size) - dev->dp8390->remote_bytes = 0; + if (dev->dp8390->remote_bytes > dev->dp8390->mem_size) + dev->dp8390->remote_bytes = 0; - /* If all bytes have been written, signal remote-DMA complete */ - if (dev->dp8390->remote_bytes == 0) { - dev->dp8390->ISR.rdma_done = 1; - if (dev->dp8390->IMR.rdma_inte) - nic_interrupt(dev, 1); - } - break; + /* If all bytes have been written, signal remote-DMA complete */ + if (dev->dp8390->remote_bytes == 0) { + dev->dp8390->ISR.rdma_done = 1; + if (dev->dp8390->IMR.rdma_inte) + nic_interrupt(dev, 1); + } + break; - case 0x0f: /* Reset register */ - /* end of reset pulse */ - break; - - default: /* this is invalid, but happens under win95 device detection */ - nelog(3, "%s: ASIC write invalid address %04x, ignoring\n", - dev->name, (unsigned)off); - break; + case 0x0f: /* Reset register */ + /* end of reset pulse */ + break; + + default: /* this is invalid, but happens under win95 device detection */ + nelog(3, "%s: ASIC write invalid address %04x, ignoring\n", + dev->name, (unsigned) off); + break; } } - /* Writes to this page are illegal. */ static uint32_t -page3_read(nic_t *dev, uint32_t off, unsigned int len) -{ - if (dev->board >= NE2K_RTL8019AS) switch(off) { - case 0x1: /* 9346CR */ - return(dev->_9346cr); +page3_read(nic_t *dev, uint32_t off, UNUSED(unsigned int len)) +{ + if (dev->board >= NE2K_RTL8019AS) + switch (off) { + case 0x1: /* 9346CR */ + return (dev->_9346cr); - case 0x3: /* CONFIG0 */ - return(0x00); /* Cable not BNC */ + case 0x3: /* CONFIG0 */ + return 0x00; /* Cable not BNC */ - case 0x5: /* CONFIG2 */ - return(dev->config2 & 0xe0); + case 0x5: /* CONFIG2 */ + return (dev->config2 & 0xe0); - case 0x6: /* CONFIG3 */ - return(dev->config3 & 0x46); + case 0x6: /* CONFIG3 */ + return (dev->config3 & 0x46); - case 0x8: /* CSNSAV */ - return((dev->board == NE2K_RTL8019AS) ? dev->pnp_csnsav : 0x00); + case 0x8: /* CSNSAV */ + return ((dev->board == NE2K_RTL8019AS) ? dev->pnp_csnsav : 0x00); - case 0xe: /* 8029ASID0 */ - if (dev->board == NE2K_RTL8029AS) - return(0x29); - break; + case 0xe: /* 8029ASID0 */ + if (dev->board == NE2K_RTL8029AS) + return 0x29; + break; - case 0xf: /* 8029ASID1 */ - if (dev->board == NE2K_RTL8029AS) - return(0x80); - break; + case 0xf: /* 8029ASID1 */ + if (dev->board == NE2K_RTL8029AS) + return 0x80; + break; - default: - break; - } + default: + break; + } nelog(3, "%s: Page3 read register 0x%02x attempted\n", dev->name, off); - return(0x00); + return 0x00; } - static void -page3_write(nic_t *dev, uint32_t off, uint32_t val, unsigned len) +page3_write(nic_t *dev, uint32_t off, uint32_t val, UNUSED(unsigned len)) { if (dev->board >= NE2K_RTL8019AS) { - nelog(3, "%s: Page2 write to register 0x%02x, len=%u, value=0x%04x\n", - dev->name, off, len, val); + nelog(3, "%s: Page2 write to register 0x%02x, len=%u, value=0x%04x\n", + dev->name, off, len, val); - switch(off) { - case 0x01: /* 9346CR */ - dev->_9346cr = (val & 0xfe); - break; + switch (off) { + case 0x01: /* 9346CR */ + dev->_9346cr = (val & 0xfe); + break; - case 0x05: /* CONFIG2 */ - dev->config2 = (val & 0xe0); - break; + case 0x05: /* CONFIG2 */ + dev->config2 = (val & 0xe0); + break; - case 0x06: /* CONFIG3 */ - dev->config3 = (val & 0x46); - break; + case 0x06: /* CONFIG3 */ + dev->config3 = (val & 0x46); + break; - case 0x09: /* HLTCLK */ - break; + case 0x09: /* HLTCLK */ + break; - default: - nelog(3, "%s: Page3 write to reserved register 0x%02x\n", - dev->name, off); - break; - } + default: + nelog(3, "%s: Page3 write to reserved register 0x%02x\n", + dev->name, off); + break; + } } else - nelog(3, "%s: Page3 write register 0x%02x attempted\n", dev->name, off); + nelog(3, "%s: Page3 write register 0x%02x attempted\n", dev->name, off); } - static uint32_t nic_read(nic_t *dev, uint32_t addr, unsigned len) { uint32_t retval = 0; - int off = addr - dev->base_address; + int off = addr - dev->base_address; nelog(3, "%s: read addr %x, len %d\n", dev->name, addr, len); if (off >= 0x10) - retval = asic_read(dev, off - 0x10, len); + retval = asic_read(dev, off - 0x10, len); else if (off == 0x00) - retval = dp8390_read_cr(dev->dp8390); - else switch(dev->dp8390->CR.pgsel) { - case 0x00: - retval = dp8390_page0_read(dev->dp8390, off, len); - break; - case 0x01: - retval = dp8390_page1_read(dev->dp8390, off, len); - break; - case 0x02: - retval = dp8390_page2_read(dev->dp8390, off, len); - break; - case 0x03: - retval = page3_read(dev, off, len); - break; - default: - nelog(3, "%s: unknown value of pgsel in read - %d\n", - dev->name, dev->dp8390->CR.pgsel); - break; - } + retval = dp8390_read_cr(dev->dp8390); + else + switch (dev->dp8390->CR.pgsel) { + case 0x00: + retval = dp8390_page0_read(dev->dp8390, off, len); + break; + case 0x01: + retval = dp8390_page1_read(dev->dp8390, off, len); + break; + case 0x02: + retval = dp8390_page2_read(dev->dp8390, off, len); + break; + case 0x03: + retval = page3_read(dev, off, len); + break; + default: + nelog(3, "%s: unknown value of pgsel in read - %d\n", + dev->name, dev->dp8390->CR.pgsel); + break; + } - return(retval); + return retval; } - static uint8_t nic_readb(uint16_t addr, void *priv) { - return(nic_read((nic_t *)priv, addr, 1)); + return (nic_read((nic_t *) priv, addr, 1)); } - static uint16_t nic_readw(uint16_t addr, void *priv) { - return(nic_read((nic_t *)priv, addr, 2)); + return (nic_read((nic_t *) priv, addr, 2)); } - static uint32_t nic_readl(uint16_t addr, void *priv) { - return(nic_read((nic_t *)priv, addr, 4)); + return (nic_read((nic_t *) priv, addr, 4)); } - static void nic_write(nic_t *dev, uint32_t addr, uint32_t val, unsigned len) { @@ -453,76 +458,71 @@ nic_write(nic_t *dev, uint32_t addr, uint32_t val, unsigned len) page being selected by the PS0,PS1 registers in the command register */ if (off >= 0x10) - asic_write(dev, off - 0x10, val, len); + asic_write(dev, off - 0x10, val, len); else if (off == 0x00) - dp8390_write_cr(dev->dp8390, val); - else switch(dev->dp8390->CR.pgsel) { - case 0x00: - dp8390_page0_write(dev->dp8390, off, val, len); - break; - case 0x01: - dp8390_page1_write(dev->dp8390, off, val, len); - break; - case 0x02: - dp8390_page2_write(dev->dp8390, off, val, len); - break; - case 0x03: - page3_write(dev, off, val, len); - break; - default: - nelog(3, "%s: unknown value of pgsel in write - %d\n", - dev->name, dev->dp8390->CR.pgsel); - break; - } + dp8390_write_cr(dev->dp8390, val); + else + switch (dev->dp8390->CR.pgsel) { + case 0x00: + dp8390_page0_write(dev->dp8390, off, val, len); + break; + case 0x01: + dp8390_page1_write(dev->dp8390, off, val, len); + break; + case 0x02: + dp8390_page2_write(dev->dp8390, off, val, len); + break; + case 0x03: + page3_write(dev, off, val, len); + break; + default: + nelog(3, "%s: unknown value of pgsel in write - %d\n", + dev->name, dev->dp8390->CR.pgsel); + break; + } } - static void nic_writeb(uint16_t addr, uint8_t val, void *priv) { - nic_write((nic_t *)priv, addr, val, 1); + nic_write((nic_t *) priv, addr, val, 1); } - static void nic_writew(uint16_t addr, uint16_t val, void *priv) { - nic_write((nic_t *)priv, addr, val, 2); + nic_write((nic_t *) priv, addr, val, 2); } - static void nic_writel(uint16_t addr, uint32_t val, void *priv) { - nic_write((nic_t *)priv, addr, val, 4); + nic_write((nic_t *) priv, addr, val, 4); } - -static void nic_ioset(nic_t *dev, uint16_t addr); -static void nic_ioremove(nic_t *dev, uint16_t addr); - +static void nic_ioset(nic_t *dev, uint16_t addr); +static void nic_ioremove(nic_t *dev, uint16_t addr); static void nic_pnp_config_changed(uint8_t ld, isapnp_device_config_t *config, void *priv) { if (ld) - return; + return; nic_t *dev = (nic_t *) priv; if (dev->base_address) { - nic_ioremove(dev, dev->base_address); - dev->base_address = 0; + nic_ioremove(dev, dev->base_address); + dev->base_address = 0; } dev->base_address = config->io[0].base; - dev->base_irq = config->irq[0].irq; + dev->base_irq = config->irq[0].irq; if (config->activate && (dev->base_address != ISAPNP_IO_DISABLED)) - nic_ioset(dev, dev->base_address); + nic_ioset(dev, dev->base_address); } - static void nic_pnp_csn_changed(uint8_t csn, void *priv) { @@ -531,357 +531,366 @@ nic_pnp_csn_changed(uint8_t csn, void *priv) dev->pnp_csnsav = csn; } - static uint8_t nic_pnp_read_vendor_reg(uint8_t ld, uint8_t reg, void *priv) { if (ld != 0) - return 0x00; + return 0x00; - nic_t *dev = (nic_t *) priv; + const nic_t *dev = (nic_t *) priv; switch (reg) { - case 0xF0: - return dev->config0; + case 0xF0: + return dev->config0; - case 0xF2: - return dev->config2; + case 0xF2: + return dev->config2; - case 0xF3: - return dev->config3; + case 0xF3: + return dev->config3; - case 0xF5: - return dev->pnp_csnsav; + case 0xF5: + return dev->pnp_csnsav; + + default: + break; } return 0x00; } - static void nic_pnp_write_vendor_reg(uint8_t ld, uint8_t reg, uint8_t val, void *priv) { nic_t *dev = (nic_t *) priv; if ((ld == 0) && (reg == 0xf6) && (val & 0x04)) { - uint8_t csn = dev->pnp_csnsav; - isapnp_set_csn(dev->pnp_card, 0); - dev->pnp_csnsav = csn; + uint8_t csn = dev->pnp_csnsav; + isapnp_set_csn(dev->pnp_card, 0); + dev->pnp_csnsav = csn; } } - static void nic_ioset(nic_t *dev, uint16_t addr) -{ +{ if (dev->is_pci) { - io_sethandler(addr, 32, - nic_readb, nic_readw, nic_readl, - nic_writeb, nic_writew, nic_writel, dev); + io_sethandler(addr, 32, + nic_readb, nic_readw, nic_readl, + nic_writeb, nic_writew, nic_writel, dev); } else { - io_sethandler(addr, 16, - nic_readb, NULL, NULL, - nic_writeb, NULL, NULL, dev); - if (dev->is_8bit) { - io_sethandler(addr+16, 16, - nic_readb, NULL, NULL, - nic_writeb, NULL, NULL, dev); - } else { - io_sethandler(addr+16, 16, - nic_readb, nic_readw, NULL, - nic_writeb, nic_writew, NULL, dev); - } + io_sethandler(addr, 16, + nic_readb, NULL, NULL, + nic_writeb, NULL, NULL, dev); + if (dev->is_8bit) { + io_sethandler(addr + 16, 16, + nic_readb, NULL, NULL, + nic_writeb, NULL, NULL, dev); + } else { + io_sethandler(addr + 16, 16, + nic_readb, nic_readw, NULL, + nic_writeb, nic_writew, NULL, dev); + } } } - static void nic_ioremove(nic_t *dev, uint16_t addr) { if (dev->is_pci) { - io_removehandler(addr, 32, - nic_readb, nic_readw, nic_readl, - nic_writeb, nic_writew, nic_writel, dev); + io_removehandler(addr, 32, + nic_readb, nic_readw, nic_readl, + nic_writeb, nic_writew, nic_writel, dev); } else { - io_removehandler(addr, 16, - nic_readb, NULL, NULL, - nic_writeb, NULL, NULL, dev); - if (dev->is_8bit) { - io_removehandler(addr+16, 16, - nic_readb, NULL, NULL, - nic_writeb, NULL, NULL, dev); - } else { - io_removehandler(addr+16, 16, - nic_readb, nic_readw, NULL, - nic_writeb, nic_writew, NULL, dev); - } + io_removehandler(addr, 16, + nic_readb, NULL, NULL, + nic_writeb, NULL, NULL, dev); + if (dev->is_8bit) { + io_removehandler(addr + 16, 16, + nic_readb, NULL, NULL, + nic_writeb, NULL, NULL, dev); + } else { + io_removehandler(addr + 16, 16, + nic_readb, nic_readw, NULL, + nic_writeb, nic_writew, NULL, dev); + } } } - static void nic_update_bios(nic_t *dev) { int reg_bios_enable; - + reg_bios_enable = 1; - if (! dev->has_bios) return; + if (!dev->has_bios) + return; if (dev->is_pci) - reg_bios_enable = dev->pci_bar[1].addr_regs[0] & 0x01; - + reg_bios_enable = dev->pci_bar[1].addr_regs[0] & 0x01; + /* PCI BIOS stuff, just enable_disable. */ if (reg_bios_enable) { - mem_mapping_set_addr(&dev->bios_rom.mapping, - dev->bios_addr, dev->bios_size); - nelog(1, "%s: BIOS now at: %06X\n", dev->name, dev->bios_addr); + mem_mapping_set_addr(&dev->bios_rom.mapping, + dev->bios_addr, dev->bios_size); + nelog(1, "%s: BIOS now at: %06X\n", dev->name, dev->bios_addr); } else { - nelog(1, "%s: BIOS disabled\n", dev->name); - mem_mapping_disable(&dev->bios_rom.mapping); + nelog(1, "%s: BIOS disabled\n", dev->name); + mem_mapping_disable(&dev->bios_rom.mapping); } } - static uint8_t -nic_pci_read(int func, int addr, void *priv) +nic_pci_read(UNUSED(int func), int addr, void *priv) { - nic_t *dev = (nic_t *)priv; - uint8_t ret = 0x00; + const nic_t *dev = (nic_t *) priv; + uint8_t ret = 0x00; - switch(addr) { - case 0x00: /* PCI_VID_LO */ - case 0x01: /* PCI_VID_HI */ - ret = dev->pci_regs[addr]; - break; + switch (addr) { + case 0x00: /* PCI_VID_LO */ + case 0x01: /* PCI_VID_HI */ + ret = dev->pci_regs[addr]; + break; - case 0x02: /* PCI_DID_LO */ - case 0x03: /* PCI_DID_HI */ - ret = dev->pci_regs[addr]; - break; + case 0x02: /* PCI_DID_LO */ + case 0x03: /* PCI_DID_HI */ + ret = dev->pci_regs[addr]; + break; - case 0x04: /* PCI_COMMAND_LO */ - case 0x05: /* PCI_COMMAND_HI */ - ret = dev->pci_regs[addr]; - break; + case 0x04: /* PCI_COMMAND_LO */ + case 0x05: /* PCI_COMMAND_HI */ + ret = dev->pci_regs[addr]; + break; - case 0x06: /* PCI_STATUS_LO */ - case 0x07: /* PCI_STATUS_HI */ - ret = dev->pci_regs[addr]; - break; + case 0x06: /* PCI_STATUS_LO */ + case 0x07: /* PCI_STATUS_HI */ + ret = dev->pci_regs[addr]; + break; - case 0x08: /* PCI_REVID */ - ret = 0x00; /* Rev. 00 */ - break; - case 0x09: /* PCI_PIFR */ - ret = 0x00; /* Rev. 00 */ - break; + case 0x08: /* PCI_REVID */ + ret = 0x00; /* Rev. 00 */ + break; + case 0x09: /* PCI_PIFR */ + ret = 0x00; /* Rev. 00 */ + break; - case 0x0A: /* PCI_SCR */ - ret = dev->pci_regs[addr]; - break; + case 0x0A: /* PCI_SCR */ + ret = dev->pci_regs[addr]; + break; - case 0x0B: /* PCI_BCR */ - ret = dev->pci_regs[addr]; - break; + case 0x0B: /* PCI_BCR */ + ret = dev->pci_regs[addr]; + break; - case 0x10: /* PCI_BAR 7:5 */ - ret = (dev->pci_bar[0].addr_regs[0] & 0xe0) | 0x01; - break; - case 0x11: /* PCI_BAR 15:8 */ - ret = dev->pci_bar[0].addr_regs[1]; - break; - case 0x12: /* PCI_BAR 23:16 */ - ret = dev->pci_bar[0].addr_regs[2]; - break; - case 0x13: /* PCI_BAR 31:24 */ - ret = dev->pci_bar[0].addr_regs[3]; - break; + case 0x10: /* PCI_BAR 7:5 */ + ret = (dev->pci_bar[0].addr_regs[0] & 0xe0) | 0x01; + break; + case 0x11: /* PCI_BAR 15:8 */ + ret = dev->pci_bar[0].addr_regs[1]; + break; + case 0x12: /* PCI_BAR 23:16 */ + ret = dev->pci_bar[0].addr_regs[2]; + break; + case 0x13: /* PCI_BAR 31:24 */ + ret = dev->pci_bar[0].addr_regs[3]; + break; - case 0x2C: /* PCI_SVID_LO */ - case 0x2D: /* PCI_SVID_HI */ - ret = dev->pci_regs[addr]; - break; + case 0x2C: /* PCI_SVID_LO */ + case 0x2D: /* PCI_SVID_HI */ + ret = dev->pci_regs[addr]; + break; - case 0x2E: /* PCI_SID_LO */ - case 0x2F: /* PCI_SID_HI */ - ret = dev->pci_regs[addr]; - break; + case 0x2E: /* PCI_SID_LO */ + case 0x2F: /* PCI_SID_HI */ + ret = dev->pci_regs[addr]; + break; - case 0x30: /* PCI_ROMBAR */ - ret = dev->pci_bar[1].addr_regs[0] & 0x01; - break; - case 0x31: /* PCI_ROMBAR 15:11 */ - ret = dev->pci_bar[1].addr_regs[1] & 0x80; - break; - case 0x32: /* PCI_ROMBAR 23:16 */ - ret = dev->pci_bar[1].addr_regs[2]; - break; - case 0x33: /* PCI_ROMBAR 31:24 */ - ret = dev->pci_bar[1].addr_regs[3]; - break; + case 0x30: /* PCI_ROMBAR */ + ret = dev->pci_bar[1].addr_regs[0] & 0x01; + break; + case 0x31: /* PCI_ROMBAR 15:11 */ + ret = dev->pci_bar[1].addr_regs[1] & 0x80; + break; + case 0x32: /* PCI_ROMBAR 23:16 */ + ret = dev->pci_bar[1].addr_regs[2]; + break; + case 0x33: /* PCI_ROMBAR 31:24 */ + ret = dev->pci_bar[1].addr_regs[3]; + break; - case 0x3C: /* PCI_ILR */ - ret = dev->pci_regs[addr]; - break; + case 0x3C: /* PCI_ILR */ + ret = dev->pci_regs[addr]; + break; - case 0x3D: /* PCI_IPR */ - ret = dev->pci_regs[addr]; - break; + case 0x3D: /* PCI_IPR */ + ret = dev->pci_regs[addr]; + break; + + default: + break; } nelog(2, "%s: PCI_Read(%d, %04x) = %02x\n", dev->name, func, addr, ret); - return(ret); + return ret; } - static void -nic_pci_write(int func, int addr, uint8_t val, void *priv) +nic_pci_write(UNUSED(int func), int addr, uint8_t val, void *priv) { - nic_t *dev = (nic_t *)priv; + nic_t *dev = (nic_t *) priv; uint8_t valxor; nelog(2, "%s: PCI_Write(%d, %04x, %02x)\n", dev->name, func, addr, val); - switch(addr) { - case 0x04: /* PCI_COMMAND_LO */ - valxor = (val & 0x03) ^ dev->pci_regs[addr]; - if (valxor & PCI_COMMAND_IO) - { - nic_ioremove(dev, dev->base_address); - if ((dev->base_address != 0) && (val & PCI_COMMAND_IO)) - { - nic_ioset(dev, dev->base_address); - } - } - dev->pci_regs[addr] = val & 0x03; - break; + switch (addr) { + case 0x04: /* PCI_COMMAND_LO */ + valxor = (val & 0x03) ^ dev->pci_regs[addr]; + if (valxor & PCI_COMMAND_IO) { + nic_ioremove(dev, dev->base_address); + if ((dev->base_address != 0) && (val & PCI_COMMAND_IO)) { + nic_ioset(dev, dev->base_address); + } + } + dev->pci_regs[addr] = val & 0x03; + break; - case 0x10: /* PCI_BAR */ - val &= 0xe0; /* 0xe0 acc to RTL DS */ - val |= 0x01; /* re-enable IOIN bit */ - /*FALLTHROUGH*/ + case 0x10: /* PCI_BAR */ + val &= 0xe0; /* 0xe0 acc to RTL DS */ + val |= 0x01; /* re-enable IOIN bit */ + fallthrough; - case 0x11: /* PCI_BAR */ - case 0x12: /* PCI_BAR */ - case 0x13: /* PCI_BAR */ - /* Remove old I/O. */ - nic_ioremove(dev, dev->base_address); + case 0x11: /* PCI_BAR */ + case 0x12: /* PCI_BAR */ + case 0x13: /* PCI_BAR */ + /* Remove old I/O. */ + nic_ioremove(dev, dev->base_address); - /* Set new I/O as per PCI request. */ - dev->pci_bar[0].addr_regs[addr & 3] = val; + /* Set new I/O as per PCI request. */ + dev->pci_bar[0].addr_regs[addr & 3] = val; - /* Then let's calculate the new I/O base. */ - dev->base_address = dev->pci_bar[0].addr & 0xffe0; + /* Then let's calculate the new I/O base. */ + dev->base_address = dev->pci_bar[0].addr & 0xffe0; - /* Log the new base. */ - nelog(1, "%s: PCI: new I/O base is %04X\n", - dev->name, dev->base_address); - /* We're done, so get out of the here. */ - if (dev->pci_regs[4] & PCI_COMMAND_IO) - { - if (dev->base_address != 0) - { - nic_ioset(dev, dev->base_address); - } - } - break; + /* Log the new base. */ + nelog(1, "%s: PCI: new I/O base is %04X\n", + dev->name, dev->base_address); + /* We're done, so get out of the here. */ + if (dev->pci_regs[4] & PCI_COMMAND_IO) { + if (dev->base_address != 0) { + nic_ioset(dev, dev->base_address); + } + } + break; - case 0x30: /* PCI_ROMBAR */ - case 0x31: /* PCI_ROMBAR */ - case 0x32: /* PCI_ROMBAR */ - case 0x33: /* PCI_ROMBAR */ - dev->pci_bar[1].addr_regs[addr & 3] = val; - /* dev->pci_bar[1].addr_regs[1] &= dev->bios_mask; */ - dev->pci_bar[1].addr &= 0xffff8001; - dev->bios_addr = dev->pci_bar[1].addr & 0xffff8000; - nic_update_bios(dev); - return; + case 0x30: /* PCI_ROMBAR */ + case 0x31: /* PCI_ROMBAR */ + case 0x32: /* PCI_ROMBAR */ + case 0x33: /* PCI_ROMBAR */ + dev->pci_bar[1].addr_regs[addr & 3] = val; +#if 0 + dev->pci_bar[1].addr_regs[1] &= dev->bios_mask; +#endif + dev->pci_bar[1].addr &= 0xffff8001; + dev->bios_addr = dev->pci_bar[1].addr & 0xffff8000; + nic_update_bios(dev); + return; - case 0x3C: /* PCI_ILR */ - nelog(1, "%s: IRQ now: %i\n", dev->name, val); - dev->base_irq = val; - dev->pci_regs[addr] = dev->base_irq; - return; + case 0x3C: /* PCI_ILR */ + nelog(1, "%s: IRQ now: %i\n", dev->name, val); + dev->base_irq = val; + dev->pci_regs[addr] = dev->base_irq; + return; + + default: + break; } } - static void nic_rom_init(nic_t *dev, char *s) { uint32_t temp; - FILE *f; + FILE *fp; - if (s == NULL) return; + if (s == NULL) + return; - if (dev->bios_addr == 0) return; + if (dev->bios_addr == 0) + return; - if ((f = rom_fopen(s, "rb")) != NULL) { - fseek(f, 0L, SEEK_END); - temp = ftell(f); - fclose(f); - dev->bios_size = 0x10000; - if (temp <= 0x8000) - dev->bios_size = 0x8000; - if (temp <= 0x4000) - dev->bios_size = 0x4000; - if (temp <= 0x2000) - dev->bios_size = 0x2000; - dev->bios_mask = (dev->bios_size >> 8) & 0xff; - dev->bios_mask = (0x100 - dev->bios_mask) & 0xff; + if ((fp = rom_fopen(s, "rb")) != NULL) { + fseek(fp, 0L, SEEK_END); + temp = ftell(fp); + fclose(fp); + dev->bios_size = 0x10000; + if (temp <= 0x8000) + dev->bios_size = 0x8000; + if (temp <= 0x4000) + dev->bios_size = 0x4000; + if (temp <= 0x2000) + dev->bios_size = 0x2000; + dev->bios_mask = (dev->bios_size >> 8) & 0xff; + dev->bios_mask = (0x100 - dev->bios_mask) & 0xff; } else { - dev->bios_addr = 0x00000; - dev->bios_size = 0; - return; + dev->bios_addr = 0x00000; + dev->bios_size = 0; + return; } /* Create a memory mapping for the space. */ rom_init(&dev->bios_rom, s, dev->bios_addr, - dev->bios_size, dev->bios_size-1, 0, MEM_MAPPING_EXTERNAL); + dev->bios_size, dev->bios_size - 1, 0, MEM_MAPPING_EXTERNAL); nelog(1, "%s: BIOS configured at %06lX (size %ld)\n", - dev->name, dev->bios_addr, dev->bios_size); + dev->name, dev->bios_addr, dev->bios_size); } static uint8_t nic_mca_read(int port, void *priv) { - nic_t *dev = (nic_t *)priv; + const nic_t *dev = (nic_t *) priv; - return(dev->pos_regs[port & 7]); + return (dev->pos_regs[port & 7]); } -#define MCA_611F_IO_PORTS { 0x300, 0x340, 0x320, 0x360, 0x1300, 0x1340, \ - 0x1320, 0x1360 } +#define MCA_611F_IO_PORTS \ + { \ + 0x300, 0x340, 0x320, 0x360, 0x1300, 0x1340, \ + 0x1320, 0x1360 \ + } -#define MCA_611F_IRQS { 2, 3, 4, 5, 10, 11, 12, 15 } +#define MCA_611F_IRQS \ + { \ + 2, 3, 4, 5, 10, 11, 12, 15 \ + } static void nic_mca_write(int port, uint8_t val, void *priv) { - nic_t *dev = (nic_t *)priv; + nic_t *dev = (nic_t *) priv; uint16_t base[] = MCA_611F_IO_PORTS; - int8_t irq[] = MCA_611F_IRQS; + int8_t irq[] = MCA_611F_IRQS; /* MCA does not write registers below 0x0100. */ - if (port < 0x0102) return; + if (port < 0x0102) + return; /* Save the MCA register value. */ dev->pos_regs[port & 7] = val; - nic_ioremove(dev, dev->base_address); + nic_ioremove(dev, dev->base_address); /* This is always necessary so that the old handler doesn't remain. */ - /* Get the new assigned I/O base address. */ - dev->base_address = base[(dev->pos_regs[2] & 0xE0) >> 4]; + /* Get the new assigned I/O base address. */ + dev->base_address = base[(dev->pos_regs[2] & 0xE0) >> 4]; - /* Save the new IRQ values. */ - dev->base_irq = irq[(dev->pos_regs[2] & 0xE) >> 1]; + /* Save the new IRQ values. */ + dev->base_irq = irq[(dev->pos_regs[2] & 0xE) >> 1]; - dev->bios_addr = 0x0000; - dev->has_bios = 0; + dev->bios_addr = 0x0000; + dev->has_bios = 0; /* * The PS/2 Model 80 BIOS always enables a card if it finds one, @@ -893,65 +902,61 @@ nic_mca_write(int port, uint8_t val, void *priv) /* Initialize the device if fully configured. */ if (dev->pos_regs[2] & 0x01) { - /* Card enabled; register (new) I/O handler. */ - - nic_ioset(dev, dev->base_address); - - nic_reset(dev); - - nelog(2, "EtherNext/MC: Port=%04x, IRQ=%d\n", dev->base_address, dev->base_irq); - + /* Card enabled; register (new) I/O handler. */ + + nic_ioset(dev, dev->base_address); + + nic_reset(dev); + + nelog(2, "EtherNext/MC: Port=%04x, IRQ=%d\n", dev->base_address, dev->base_irq); } } - static uint8_t nic_mca_feedb(void *priv) { - nic_t *dev = (nic_t *)priv; + const nic_t *dev = (nic_t *) priv; return (dev->pos_regs[2] & 0x01); } - static void * nic_init(const device_t *info) { uint32_t mac; - char *rom; - nic_t *dev; + char *rom; + nic_t *dev; dev = malloc(sizeof(nic_t)); memset(dev, 0x00, sizeof(nic_t)); - dev->name = info->name; + dev->name = info->name; dev->board = info->local; - rom = NULL; + rom = NULL; if (dev->board >= NE2K_RTL8019AS) { - dev->base_address = 0x340; - dev->base_irq = 12; - if (dev->board == NE2K_RTL8029AS) { - dev->bios_addr = 0xD0000; - dev->has_bios = device_get_config_int("bios"); - } else { - dev->bios_addr = 0x00000; - dev->has_bios = 0; - } + dev->base_address = 0x340; + dev->base_irq = 12; + if (dev->board == NE2K_RTL8029AS) { + dev->bios_addr = 0xD0000; + dev->has_bios = device_get_config_int("bios"); + } else { + dev->bios_addr = 0x00000; + dev->has_bios = 0; + } } else { - if (dev->board != NE2K_ETHERNEXT_MC) { - dev->base_address = device_get_config_hex16("base"); - dev->base_irq = device_get_config_int("irq"); - if (dev->board == NE2K_NE2000) { - dev->bios_addr = device_get_config_hex20("bios_addr"); - dev->has_bios = !!dev->bios_addr; - } else { - dev->bios_addr = 0x00000; - dev->has_bios = 0; - } - } - else { - mca_add(nic_mca_read, nic_mca_write, nic_mca_feedb, NULL, dev); - } + if (dev->board != NE2K_ETHERNEXT_MC) { + dev->base_address = device_get_config_hex16("base"); + dev->base_irq = device_get_config_int("irq"); + if (dev->board == NE2K_NE2000) { + dev->bios_addr = device_get_config_hex20("bios_addr"); + dev->has_bios = !!dev->bios_addr; + } else { + dev->bios_addr = 0x00000; + dev->has_bios = 0; + } + } else { + mca_add(nic_mca_read, nic_mca_write, nic_mca_feedb, NULL, dev); + } } /* See if we have a local MAC address configured. */ @@ -959,412 +964,397 @@ nic_init(const device_t *info) /* Set up our BIA. */ if (mac & 0xff000000) { - /* Generate new local MAC. */ - dev->maclocal[3] = random_generate(); - dev->maclocal[4] = random_generate(); - dev->maclocal[5] = random_generate(); - mac = (((int) dev->maclocal[3]) << 16); - mac |= (((int) dev->maclocal[4]) << 8); - mac |= ((int) dev->maclocal[5]); - device_set_config_mac("mac", mac); + /* Generate new local MAC. */ + dev->maclocal[3] = random_generate(); + dev->maclocal[4] = random_generate(); + dev->maclocal[5] = random_generate(); + mac = (((int) dev->maclocal[3]) << 16); + mac |= (((int) dev->maclocal[4]) << 8); + mac |= ((int) dev->maclocal[5]); + device_set_config_mac("mac", mac); } else { - dev->maclocal[3] = (mac>>16) & 0xff; - dev->maclocal[4] = (mac>>8) & 0xff; - dev->maclocal[5] = (mac & 0xff); + dev->maclocal[3] = (mac >> 16) & 0xff; + dev->maclocal[4] = (mac >> 8) & 0xff; + dev->maclocal[5] = (mac & 0xff); } - dev->dp8390 = device_add(&dp8390_device); - dev->dp8390->priv = dev; + dev->dp8390 = device_add_inst(&dp8390_device, dp3890_inst++); + dev->dp8390->priv = dev; dev->dp8390->interrupt = nic_interrupt; - switch(dev->board) { - case NE2K_NE1000: - dev->maclocal[0] = 0x00; /* 00:00:D8 (Novell OID) */ - dev->maclocal[1] = 0x00; - dev->maclocal[2] = 0xD8; - dev->is_8bit = 1; - rom = NULL; - dp8390_set_defaults(dev->dp8390, DP8390_FLAG_CHECK_CR | DP8390_FLAG_CLEAR_IRQ); - dp8390_mem_alloc(dev->dp8390, 0x2000, 0x2000); - break; + switch (dev->board) { + case NE2K_NE1000: + dev->maclocal[0] = 0x00; /* 00:00:D8 (Novell OID) */ + dev->maclocal[1] = 0x00; + dev->maclocal[2] = 0xD8; + dev->is_8bit = 1; + rom = NULL; + dp8390_set_defaults(dev->dp8390, DP8390_FLAG_CHECK_CR | DP8390_FLAG_CLEAR_IRQ); + dp8390_mem_alloc(dev->dp8390, 0x2000, 0x2000); + break; - case NE2K_NE2000: - dev->maclocal[0] = 0x00; /* 00:00:D8 (Novell OID) */ - dev->maclocal[1] = 0x00; - dev->maclocal[2] = 0xD8; - rom = ROM_PATH_NE2000; - dp8390_set_defaults(dev->dp8390, DP8390_FLAG_EVEN_MAC | DP8390_FLAG_CHECK_CR | - DP8390_FLAG_CLEAR_IRQ); - dp8390_mem_alloc(dev->dp8390, 0x4000, 0x4000); - break; - - case NE2K_ETHERNEXT_MC: - dev->maclocal[0] = 0x00; /* 00:00:D8 (Networth Inc. OID) */ - dev->maclocal[1] = 0x00; - dev->maclocal[2] = 0x79; - dev->pos_regs[0] = 0x1F; - dev->pos_regs[1] = 0x61; - rom = NULL; - dp8390_set_defaults(dev->dp8390, DP8390_FLAG_EVEN_MAC | DP8390_FLAG_CHECK_CR | - DP8390_FLAG_CLEAR_IRQ); - dp8390_mem_alloc(dev->dp8390, 0x4000, 0x4000); - break; + case NE2K_NE2000: + dev->maclocal[0] = 0x00; /* 00:00:D8 (Novell OID) */ + dev->maclocal[1] = 0x00; + dev->maclocal[2] = 0xD8; + rom = ROM_PATH_NE2000; + dp8390_set_defaults(dev->dp8390, DP8390_FLAG_EVEN_MAC | DP8390_FLAG_CHECK_CR | DP8390_FLAG_CLEAR_IRQ); + dp8390_mem_alloc(dev->dp8390, 0x4000, 0x4000); + break; - case NE2K_RTL8019AS: - case NE2K_RTL8029AS: - dev->is_pci = (dev->board == NE2K_RTL8029AS) ? 1 : 0; - dev->maclocal[0] = 0x00; /* 00:E0:4C (Realtek OID) */ - dev->maclocal[1] = 0xE0; - dev->maclocal[2] = 0x4C; - rom = (dev->board == NE2K_RTL8019AS) ? ROM_PATH_RTL8019 : ROM_PATH_RTL8029; - if (dev->is_pci) - dp8390_set_defaults(dev->dp8390, DP8390_FLAG_EVEN_MAC); - else - dp8390_set_defaults(dev->dp8390, DP8390_FLAG_EVEN_MAC | DP8390_FLAG_CLEAR_IRQ); - dp8390_set_id(dev->dp8390, 0x50, (dev->board == NE2K_RTL8019AS) ? 0x70 : 0x43); - dp8390_mem_alloc(dev->dp8390, 0x4000, 0x8000); - break; + case NE2K_ETHERNEXT_MC: + dev->maclocal[0] = 0x00; /* 00:00:D8 (Networth Inc. OID) */ + dev->maclocal[1] = 0x00; + dev->maclocal[2] = 0x79; + dev->pos_regs[0] = 0x1F; + dev->pos_regs[1] = 0x61; + rom = NULL; + dp8390_set_defaults(dev->dp8390, DP8390_FLAG_EVEN_MAC | DP8390_FLAG_CHECK_CR | DP8390_FLAG_CLEAR_IRQ); + dp8390_mem_alloc(dev->dp8390, 0x4000, 0x4000); + break; + + case NE2K_RTL8019AS: + case NE2K_RTL8029AS: + dev->is_pci = (dev->board == NE2K_RTL8029AS) ? 1 : 0; + dev->maclocal[0] = 0x00; /* 00:E0:4C (Realtek OID) */ + dev->maclocal[1] = 0xE0; + dev->maclocal[2] = 0x4C; + rom = (dev->board == NE2K_RTL8019AS) ? ROM_PATH_RTL8019 : ROM_PATH_RTL8029; + if (dev->is_pci) + dp8390_set_defaults(dev->dp8390, DP8390_FLAG_EVEN_MAC); + else + dp8390_set_defaults(dev->dp8390, DP8390_FLAG_EVEN_MAC | DP8390_FLAG_CLEAR_IRQ); + dp8390_set_id(dev->dp8390, 0x50, (dev->board == NE2K_RTL8019AS) ? 0x70 : 0x43); + dp8390_mem_alloc(dev->dp8390, 0x4000, 0x8000); + break; + + default: + break; } memcpy(dev->dp8390->physaddr, dev->maclocal, sizeof(dev->maclocal)); nelog(2, "%s: I/O=%04x, IRQ=%d, MAC=%02x:%02x:%02x:%02x:%02x:%02x\n", - dev->name, dev->base_address, dev->base_irq, - dev->dp8390->physaddr[0], dev->dp8390->physaddr[1], dev->dp8390->physaddr[2], - dev->dp8390->physaddr[3], dev->dp8390->physaddr[4], dev->dp8390->physaddr[5]); + dev->name, dev->base_address, dev->base_irq, + dev->dp8390->physaddr[0], dev->dp8390->physaddr[1], dev->dp8390->physaddr[2], + dev->dp8390->physaddr[3], dev->dp8390->physaddr[4], dev->dp8390->physaddr[5]); /* * Make this device known to the I/O system. * PnP and PCI devices start with address spaces inactive. */ if (dev->board < NE2K_RTL8019AS && dev->board != NE2K_ETHERNEXT_MC) - nic_ioset(dev, dev->base_address); + nic_ioset(dev, dev->base_address); /* Set up our BIOS ROM space, if any. */ nic_rom_init(dev, rom); if (dev->board >= NE2K_RTL8019AS) { - if (dev->is_pci) { - /* - * Configure the PCI space registers. - * - * We do this here, so the I/O routines are generic. - */ - memset(dev->pci_regs, 0, PCI_REGSIZE); + if (dev->is_pci) { + /* + * Configure the PCI space registers. + * + * We do this here, so the I/O routines are generic. + */ + memset(dev->pci_regs, 0, PCI_REGSIZE); - dev->pci_regs[0x00] = (PCI_VENDID&0xff); - dev->pci_regs[0x01] = (PCI_VENDID>>8); - dev->pci_regs[0x02] = (PCI_DEVID&0xff); - dev->pci_regs[0x03] = (PCI_DEVID>>8); + dev->pci_regs[0x00] = (PCI_VENDID & 0xff); + dev->pci_regs[0x01] = (PCI_VENDID >> 8); + dev->pci_regs[0x02] = (PCI_DEVID & 0xff); + dev->pci_regs[0x03] = (PCI_DEVID >> 8); - dev->pci_regs[0x04] = 0x03; /* IOEN */ - dev->pci_regs[0x05] = 0x00; - dev->pci_regs[0x07] = 0x02; /* DST0, medium devsel */ + dev->pci_regs[0x04] = 0x03; /* IOEN */ + dev->pci_regs[0x05] = 0x00; + dev->pci_regs[0x07] = 0x02; /* DST0, medium devsel */ - dev->pci_regs[0x09] = 0x00; /* PIFR */ + dev->pci_regs[0x09] = 0x00; /* PIFR */ - dev->pci_regs[0x0B] = 0x02; /* BCR: Network Controller */ - dev->pci_regs[0x0A] = 0x00; /* SCR: Ethernet */ + dev->pci_regs[0x0B] = 0x02; /* BCR: Network Controller */ + dev->pci_regs[0x0A] = 0x00; /* SCR: Ethernet */ - dev->pci_regs[0x2C] = (PCI_VENDID&0xff); - dev->pci_regs[0x2D] = (PCI_VENDID>>8); - dev->pci_regs[0x2E] = (PCI_DEVID&0xff); - dev->pci_regs[0x2F] = (PCI_DEVID>>8); + dev->pci_regs[0x2C] = (PCI_VENDID & 0xff); + dev->pci_regs[0x2D] = (PCI_VENDID >> 8); + dev->pci_regs[0x2E] = (PCI_DEVID & 0xff); + dev->pci_regs[0x2F] = (PCI_DEVID >> 8); - dev->pci_regs[0x3D] = PCI_INTA; /* PCI_IPR */ + dev->pci_regs[0x3D] = PCI_INTA; /* PCI_IPR */ - /* Enable our address space in PCI. */ - dev->pci_bar[0].addr_regs[0] = 0x01; + /* Enable our address space in PCI. */ + dev->pci_bar[0].addr_regs[0] = 0x01; - /* Enable our BIOS space in PCI, if needed. */ - if (dev->bios_addr > 0) { - dev->pci_bar[1].addr = 0xFFFF8000; - dev->pci_bar[1].addr_regs[1] = dev->bios_mask; - } else { - dev->pci_bar[1].addr = 0; - dev->bios_size = 0; - } + /* Enable our BIOS space in PCI, if needed. */ + if (dev->bios_addr > 0) { + dev->pci_bar[1].addr = 0xFFFF8000; + dev->pci_bar[1].addr_regs[1] = dev->bios_mask; + } else { + dev->pci_bar[1].addr = 0; + dev->bios_size = 0; + } - mem_mapping_disable(&dev->bios_rom.mapping); + mem_mapping_disable(&dev->bios_rom.mapping); - /* Add device to the PCI bus, keep its slot number. */ - dev->card = pci_add_card(PCI_ADD_NORMAL, - nic_pci_read, nic_pci_write, dev); - } + /* Add device to the PCI bus, keep its slot number. */ + pci_add_card(PCI_ADD_NORMAL, nic_pci_read, nic_pci_write, dev, &dev->pci_slot); + } - /* Initialize the RTL8029 EEPROM. */ + /* Initialize the RTL8029 EEPROM. */ memset(dev->eeprom, 0x00, sizeof(dev->eeprom)); - if (dev->board == NE2K_RTL8029AS) { - memcpy(&dev->eeprom[0x02], dev->maclocal, 6); + if (dev->board == NE2K_RTL8029AS) { + memcpy(&dev->eeprom[0x02], dev->maclocal, 6); - dev->eeprom[0x76] = - dev->eeprom[0x7A] = - dev->eeprom[0x7E] = (PCI_DEVID&0xff); - dev->eeprom[0x77] = - dev->eeprom[0x7B] = - dev->eeprom[0x7F] = (PCI_DEVID>>8); - dev->eeprom[0x78] = - dev->eeprom[0x7C] = (PCI_VENDID&0xff); - dev->eeprom[0x79] = - dev->eeprom[0x7D] = (PCI_VENDID>>8); - } else { - memcpy(&dev->eeprom[0x12], rtl8019as_pnp_rom, sizeof(rtl8019as_pnp_rom)); + dev->eeprom[0x76] = dev->eeprom[0x7A] = dev->eeprom[0x7E] = (PCI_DEVID & 0xff); + dev->eeprom[0x77] = dev->eeprom[0x7B] = dev->eeprom[0x7F] = (PCI_DEVID >> 8); + dev->eeprom[0x78] = dev->eeprom[0x7C] = (PCI_VENDID & 0xff); + dev->eeprom[0x79] = dev->eeprom[0x7D] = (PCI_VENDID >> 8); + } else { + memcpy(&dev->eeprom[0x12], rtl8019as_pnp_rom, sizeof(rtl8019as_pnp_rom)); - dev->pnp_card = isapnp_add_card(&dev->eeprom[0x12], sizeof(rtl8019as_pnp_rom), nic_pnp_config_changed, nic_pnp_csn_changed, nic_pnp_read_vendor_reg, nic_pnp_write_vendor_reg, dev); - } + dev->pnp_card = isapnp_add_card(&dev->eeprom[0x12], sizeof(rtl8019as_pnp_rom), nic_pnp_config_changed, nic_pnp_csn_changed, nic_pnp_read_vendor_reg, nic_pnp_write_vendor_reg, dev); + } } if (dev->board != NE2K_ETHERNEXT_MC) - /* Reset the board. */ - nic_reset(dev); + /* Reset the board. */ + nic_reset(dev); /* Attach ourselves to the network module. */ - network_attach(dev->dp8390, dev->dp8390->physaddr, dp8390_rx, NULL, NULL); + dev->dp8390->card = network_attach(dev->dp8390, dev->dp8390->physaddr, dp8390_rx, NULL); nelog(1, "%s: %s attached IO=0x%X IRQ=%d\n", dev->name, - dev->is_pci?"PCI":"ISA", dev->base_address, dev->base_irq); + dev->is_pci ? "PCI" : "ISA", dev->base_address, dev->base_irq); - return(dev); + return dev; } - static void nic_close(void *priv) { - nic_t *dev = (nic_t *)priv; + nic_t *dev = (nic_t *) priv; nelog(1, "%s: closed\n", dev->name); free(dev); } - -static const device_config_t ne1000_config[] = -{ - { - "base", "Address", CONFIG_HEX16, "", 0x300, "", { 0 }, - { - { - "0x280", 0x280 - }, - { - "0x300", 0x300 - }, - { - "0x320", 0x320 - }, - { - "0x340", 0x340 - }, - { - "0x360", 0x360 - }, - { - "0x380", 0x380 - }, - { - "" - } - }, - }, - { - "irq", "IRQ", CONFIG_SELECTION, "", 3, "", { 0 }, - { - { - "IRQ 2", 2 - }, - { - "IRQ 3", 3 - }, - { - "IRQ 5", 5 - }, - { - "IRQ 7", 7 - }, - { - "IRQ 10", 10 - }, - { - "IRQ 11", 11 - }, - { - "" - } - }, - }, - { - "mac", "MAC Address", CONFIG_MAC, "", -1 - }, - { - "", "", -1 - } +// clang-format off +static const device_config_t ne1000_config[] = { + { + .name = "base", + .description = "Address", + .type = CONFIG_HEX16, + .default_string = "", + .default_int = 0x300, + .file_filter = "", + .spinner = { 0 }, + .selection = { + { .description = "0x280", .value = 0x280 }, + { .description = "0x300", .value = 0x300 }, + { .description = "0x320", .value = 0x320 }, + { .description = "0x340", .value = 0x340 }, + { .description = "0x360", .value = 0x360 }, + { .description = "0x380", .value = 0x380 }, + { .description = "" } + }, + }, + { + .name = "irq", + .description = "IRQ", + .type = CONFIG_SELECTION, + .default_string = "", + .default_int = 3, + .file_filter = "", + .spinner = { 0 }, + .selection = { + { .description = "IRQ 2", .value = 2 }, + { .description = "IRQ 3", .value = 3 }, + { .description = "IRQ 5", .value = 5 }, + { .description = "IRQ 7", .value = 7 }, + { .description = "IRQ 10", .value = 10 }, + { .description = "IRQ 11", .value = 11 }, + { .description = "" } + }, + }, + { + .name = "mac", + .description = "MAC Address", + .type = CONFIG_MAC, + .default_string = "", + .default_int = -1 + }, + { .name = "", .description = "", .type = CONFIG_END } }; -static const device_config_t ne2000_config[] = -{ - { - "base", "Address", CONFIG_HEX16, "", 0x300, "", { 0 }, - { - { - "0x280", 0x280 - }, - { - "0x300", 0x300 - }, - { - "0x320", 0x320 - }, - { - "0x340", 0x340 - }, - { - "0x360", 0x360 - }, - { - "0x380", 0x380 - }, - { - "" - } - }, - }, - { - "irq", "IRQ", CONFIG_SELECTION, "", 10, "", { 0 }, - { - { - "IRQ 2", 2 - }, - { - "IRQ 3", 3 - }, - { - "IRQ 5", 5 - }, - { - "IRQ 7", 7 - }, - { - "IRQ 10", 10 - }, - { - "IRQ 11", 11 - }, - { - "" - } - }, - }, - { - "mac", "MAC Address", CONFIG_MAC, "", -1 - }, - { - "bios_addr", "BIOS address", CONFIG_HEX20, "", 0, "", { 0 }, - { - { - "Disabled", 0x00000 - }, - { - "D000", 0xD0000 - }, - { - "D800", 0xD8000 - }, - { - "C800", 0xC8000 - }, - { - "" - } - }, - }, - { - "", "", -1 - } +static const device_config_t ne2000_config[] = { + { + .name = "base", + .description = "Address", + .type = CONFIG_HEX16, + .default_string = "", + .default_int = 0x300, + .file_filter = "", + .spinner = { 0 }, + .selection = { + { .description = "0x280", .value = 0x280 }, + { .description = "0x300", .value = 0x300 }, + { .description = "0x320", .value = 0x320 }, + { .description = "0x340", .value = 0x340 }, + { .description = "0x360", .value = 0x360 }, + { .description = "0x380", .value = 0x380 }, + { .description = "" } + }, + }, + { + .name = "irq", + .description = "IRQ", + .type = CONFIG_SELECTION, + .default_string = "", + .default_int = 10, + .file_filter = "", + .spinner = { 0 }, + .selection = { + { .description = "IRQ 2", .value = 2 }, + { .description = "IRQ 3", .value = 3 }, + { .description = "IRQ 5", .value = 5 }, + { .description = "IRQ 7", .value = 7 }, + { .description = "IRQ 10", .value = 10 }, + { .description = "IRQ 11", .value = 11 }, + { .description = "" } + }, + }, + { + .name = "mac", + .description = "MAC Address", + .type = CONFIG_MAC, + .default_string = "", + .default_int = -1 + }, + { + .name = "bios_addr", + .description = "BIOS address", + .type = CONFIG_HEX20, + .default_string = "", + .default_int = 0, + .file_filter = "", + .spinner = { 0 }, + .selection = { + { .description = "Disabled", .value = 0x00000 }, + { .description = "D000", .value = 0xD0000 }, + { .description = "D800", .value = 0xD8000 }, + { .description = "C800", .value = 0xC8000 }, + { .description = "" } + }, + }, + { .name = "", .description = "", .type = CONFIG_END } }; -static const device_config_t rtl8019as_config[] = -{ - { - "mac", "MAC Address", CONFIG_MAC, "", -1 - }, - { - "", "", -1 - } +static const device_config_t rtl8019as_config[] = { + { + .name = "mac", + .description = "MAC Address", + .type = CONFIG_MAC, + .default_string = "", + .default_int = -1 + }, + { .name = "", .description = "", .type = CONFIG_END } }; -static const device_config_t rtl8029as_config[] = -{ - { - "bios", "Enable BIOS", CONFIG_BINARY, "", 0 - }, - { - "mac", "MAC Address", CONFIG_MAC, "", -1 - }, - { - "", "", -1 - } +static const device_config_t rtl8029as_config[] = { + { + .name = "bios", + .description = "Enable BIOS", + .type = CONFIG_BINARY, + .default_string = "", + .default_int = 0 + }, + { + .name = "mac", + .description = "MAC Address", + .type = CONFIG_MAC, + .default_string = "", + .default_int = -1 + }, + { .name = "", .description = "", .type = CONFIG_END } }; -static const device_config_t mca_mac_config[] = -{ - { - "mac", "MAC Address", CONFIG_MAC, "", -1 - }, - { - "", "", -1 - } +static const device_config_t mca_mac_config[] = { + { + .name = "mac", + .description = "MAC Address", + .type = CONFIG_MAC, + .default_string = "", + .default_int = -1 + }, + { .name = "", .description = "", .type = CONFIG_END } }; - - +// clang-format on const device_t ne1000_device = { - "Novell NE1000", - "ne1k", - DEVICE_ISA, - NE2K_NE1000, - nic_init, nic_close, NULL, - { NULL }, NULL, NULL, - ne1000_config + .name = "Novell NE1000", + .internal_name = "ne1k", + .flags = DEVICE_ISA, + .local = NE2K_NE1000, + .init = nic_init, + .close = nic_close, + .reset = NULL, + { .available = NULL }, + .speed_changed = NULL, + .force_redraw = NULL, + .config = ne1000_config }; const device_t ne2000_device = { - "Novell NE2000", - "ne2k", - DEVICE_ISA | DEVICE_AT, - NE2K_NE2000, - nic_init, nic_close, NULL, - { NULL }, NULL, NULL, - ne2000_config + .name = "Novell NE2000", + .internal_name = "ne2k", + .flags = DEVICE_ISA | DEVICE_AT, + .local = NE2K_NE2000, + .init = nic_init, + .close = nic_close, + .reset = NULL, + { .available = NULL }, + .speed_changed = NULL, + .force_redraw = NULL, + .config = ne2000_config }; const device_t ethernext_mc_device = { - "NetWorth EtherNext/MC", - "ethernextmc", - DEVICE_MCA, - NE2K_ETHERNEXT_MC, - nic_init, nic_close, NULL, - { NULL }, NULL, NULL, - mca_mac_config + .name = "NetWorth EtherNext/MC", + .internal_name = "ethernextmc", + .flags = DEVICE_MCA, + .local = NE2K_ETHERNEXT_MC, + .init = nic_init, + .close = nic_close, + .reset = NULL, + { .available = NULL }, + .speed_changed = NULL, + .force_redraw = NULL, + .config = mca_mac_config }; const device_t rtl8019as_device = { - "Realtek RTL8019AS", - "ne2kpnp", - DEVICE_ISA | DEVICE_AT, - NE2K_RTL8019AS, - nic_init, nic_close, NULL, - { NULL }, NULL, NULL, - rtl8019as_config + .name = "Realtek RTL8019AS", + .internal_name = "ne2kpnp", + .flags = DEVICE_ISA | DEVICE_AT, + .local = NE2K_RTL8019AS, + .init = nic_init, + .close = nic_close, + .reset = NULL, + { .available = NULL }, + .speed_changed = NULL, + .force_redraw = NULL, + .config = rtl8019as_config }; const device_t rtl8029as_device = { - "Realtek RTL8029AS", - "ne2kpci", - DEVICE_PCI, - NE2K_RTL8029AS, - nic_init, nic_close, NULL, - { NULL }, NULL, NULL, - rtl8029as_config + .name = "Realtek RTL8029AS", + .internal_name = "ne2kpci", + .flags = DEVICE_PCI, + .local = NE2K_RTL8029AS, + .init = nic_init, + .close = nic_close, + .reset = NULL, + { .available = NULL }, + .speed_changed = NULL, + .force_redraw = NULL, + .config = rtl8029as_config }; diff --git a/src/network/net_null.c b/src/network/net_null.c new file mode 100644 index 000000000..6fb3f3440 --- /dev/null +++ b/src/network/net_null.c @@ -0,0 +1,225 @@ +/* +* 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. +* +* Null network driver +* +* +* +* Authors: cold-brewed +* +* Copyright 2023 The 86Box development team +*/ + +#include +#include +#include +#include +#include +#include +#include +#ifdef _WIN32 +# define WIN32_LEAN_AND_MEAN +# include +# include +#else +# include +#endif + +#define HAVE_STDARG_H +#include <86box/86box.h> +#include <86box/device.h> +#include <86box/thread.h> +#include <86box/timer.h> +#include <86box/network.h> +#include <86box/net_event.h> +#include <86box/plat_unused.h> + +enum { + NET_EVENT_STOP = 0, + NET_EVENT_TX, + NET_EVENT_RX, + NET_EVENT_MAX +}; + +/* Special define for the windows portion. Because we are not interested + * in NET_EVENT_RX for the null driver, we only need to poll up to + * NET_EVENT_TX. NET_EVENT_RX gives us a different NET_EVENT_MAX + * excluding NET_EVENT_RX. */ +#define NET_EVENT_TX_MAX NET_EVENT_RX + +#define NULL_PKT_BATCH NET_QUEUE_LEN + +typedef struct net_null_t { + uint8_t mac_addr[6]; + netcard_t *card; + thread_t *poll_tid; + net_evt_t tx_event; + net_evt_t stop_event; + netpkt_t pkt; + netpkt_t pktv[NULL_PKT_BATCH]; +} net_null_t; + +#ifdef ENABLE_NET_NULL_LOG +int net_null_do_log = ENABLE_NET_NULL_LOG; + +static void +net_null_log(const char *fmt, ...) +{ + va_list ap; + + if (net_null_do_log) { + va_start(ap, fmt); + pclog_ex(fmt, ap); + va_end(ap); + } +} +#else +# define net_null_log(fmt, ...) +#endif + +#ifdef _WIN32 +static void +net_null_thread(void *priv) +{ + net_null_t *net_null = (net_null_t *) priv; + + net_null_log("Null Network: polling started.\n"); + + HANDLE events[NET_EVENT_TX_MAX]; + events[NET_EVENT_STOP] = net_event_get_handle(&net_null->stop_event); + events[NET_EVENT_TX] = net_event_get_handle(&net_null->tx_event); + + bool run = true; + + while (run) { + int ret = WaitForMultipleObjects(NET_EVENT_TX_MAX, events, FALSE, INFINITE); + + switch (ret - WAIT_OBJECT_0) { + case NET_EVENT_STOP: + net_event_clear(&net_null->stop_event); + run = false; + break; + + case NET_EVENT_TX: + net_event_clear(&net_null->tx_event); + int packets = network_tx_popv(net_null->card, net_null->pktv, NULL_PKT_BATCH); + for (int i = 0; i < packets; i++) { + net_null_log("Null Network: Ignoring TX packet (%d bytes)\n", net_null->pktv[i].len); + } + break; + + default: + net_null_log("Null Network: Unknown event.\n"); + break; + } + } + + net_null_log("Null Network: polling stopped.\n"); +} +#else +static void +net_null_thread(void *priv) +{ + net_null_t *net_null = (net_null_t *) priv; + + net_null_log("Null Network: polling started.\n"); + + struct pollfd pfd[NET_EVENT_MAX]; + pfd[NET_EVENT_STOP].fd = net_event_get_fd(&net_null->stop_event); + pfd[NET_EVENT_STOP].events = POLLIN | POLLPRI; + + pfd[NET_EVENT_TX].fd = net_event_get_fd(&net_null->tx_event); + pfd[NET_EVENT_TX].events = POLLIN | POLLPRI; + + while (1) { + poll(pfd, NET_EVENT_MAX, -1); + + if (pfd[NET_EVENT_STOP].revents & POLLIN) { + net_event_clear(&net_null->stop_event); + break; + } + + if (pfd[NET_EVENT_TX].revents & POLLIN) { + net_event_clear(&net_null->tx_event); + + int packets = network_tx_popv(net_null->card, net_null->pktv, NULL_PKT_BATCH); + for (int i = 0; i < packets; i++) { + net_null_log("Null Network: Ignoring TX packet (%d bytes)\n", net_null->pktv[i].len); + } + } + } + + net_null_log("Null Network: polling stopped.\n"); +} +#endif + +void * +net_null_init(const netcard_t *card, const uint8_t *mac_addr, UNUSED(void *priv), UNUSED(char *netdrv_errbuf)) +{ + net_null_log("Null Network: Init\n"); + + net_null_t *net_null = calloc(1, sizeof(net_null_t)); + net_null->card = (netcard_t *) card; + memcpy(net_null->mac_addr, mac_addr, sizeof(net_null->mac_addr)); + + for (int i = 0; i < NULL_PKT_BATCH; i++) { + net_null->pktv[i].data = calloc(1, NET_MAX_FRAME); + } + net_null->pkt.data = calloc(1, NET_MAX_FRAME); + + net_event_init(&net_null->tx_event); + net_event_init(&net_null->stop_event); + net_null->poll_tid = thread_create(net_null_thread, net_null); + + return net_null; +} + + + +void +net_null_in_available(void *priv) +{ + net_null_t *net_null = (net_null_t *) priv; + net_event_set(&net_null->tx_event); +} + +void +net_null_close(void *priv) +{ + if (!priv) + return; + + net_null_t *net_null = (net_null_t *) priv; + + net_null_log("Null Network: closing.\n"); + + /* Tell the thread to terminate. */ + net_event_set(&net_null->stop_event); + + /* Wait for the thread to finish. */ + net_null_log("Null Network: waiting for thread to end...\n"); + thread_wait(net_null->poll_tid); + net_null_log("Null Network: thread ended\n"); + + for (int i = 0; i < NULL_PKT_BATCH; i++) { + free(net_null->pktv[i].data); + } + free(net_null->pkt.data); + + net_event_close(&net_null->tx_event); + net_event_close(&net_null->stop_event); + + free(net_null); +} + +const netdrv_t net_null_drv = { + &net_null_in_available, + &net_null_init, + &net_null_close, + NULL +}; diff --git a/src/network/net_pcap.c b/src/network/net_pcap.c index 7008d1442..e1747580b 100644 --- a/src/network/net_pcap.c +++ b/src/network/net_pcap.c @@ -1,36 +1,34 @@ /* - * VARCem Virtual ARchaeological Computer EMulator. - * An emulator of (mostly) x86-based PC systems and devices, - * using the ISA,EISA,VLB,MCA and PCI system buses, roughly - * spanning the era between 1981 and 1995. + * VARCem Virtual ARchaeological Computer EMulator. + * An emulator of (mostly) x86-based PC systems and devices, + * using the ISA,EISA,VLB,MCA and PCI system buses, roughly + * spanning the era between 1981 and 1995. * - * This file is part of the VARCem Project. - * - * Handle WinPcap library processing. + * Handle WinPcap library processing. * * * - * Author: Fred N. van Kempen, + * Authors: Fred N. van Kempen, * - * Copyright 2017-2019 Fred N. van Kempen. + * Copyright 2017-2019 Fred N. van Kempen. * - * Redistribution and use in source and binary forms, with - * or without modification, are permitted provided that the - * following conditions are met: + * Redistribution and use in source and binary forms, with + * or without modification, are permitted provided that the + * following conditions are met: * - * 1. Redistributions of source code must retain the entire - * above notice, this list of conditions and the following - * disclaimer. + * 1. Redistributions of source code must retain the entire + * above notice, this list of conditions and the following + * disclaimer. * - * 2. Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the - * following disclaimer in the documentation and/or other - * materials provided with the distribution. + * 2. Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the + * following disclaimer in the documentation and/or other + * materials provided with the distribution. * - * 3. Neither the name of the copyright holder nor the names - * of its contributors may be used to endorse or promote - * products derived from this software without specific - * prior written permission. + * 3. Neither the name of the copyright holder nor the names + * of its contributors may be used to endorse or promote + * products derived from this software without specific + * prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT @@ -50,186 +48,306 @@ #include #include #include +#include +#ifdef _WIN32 +# define WIN32_LEAN_AND_MEAN +# include +# include +#else +# include +# include +# include +# include +#endif + #define HAVE_STDARG_H #include <86box/86box.h> #include <86box/device.h> #include <86box/plat.h> #include <86box/plat_dynld.h> +#include <86box/thread.h> +#include <86box/timer.h> #include <86box/network.h> +#include <86box/net_event.h> +#define PCAP_PKT_BATCH NET_QUEUE_LEN -typedef int bpf_int32; -typedef unsigned int bpf_u_int32; +enum { + NET_EVENT_STOP = 0, + NET_EVENT_TX, + NET_EVENT_RX, + NET_EVENT_MAX +}; + +#ifdef __APPLE__ +# include +#else +typedef int bpf_int32; +typedef unsigned int bpf_u_int32; /* * The instruction data structure. */ struct bpf_insn { - unsigned short code; - unsigned char jt; - unsigned char jf; - bpf_u_int32 k; + unsigned short code; + unsigned char jt; + unsigned char jf; + bpf_u_int32 k; }; /* * Structure for "pcap_compile()", "pcap_setfilter()", etc.. */ struct bpf_program { - unsigned int bf_len; - struct bpf_insn *bf_insns; + unsigned int bf_len; + struct bpf_insn *bf_insns; }; -typedef struct pcap_if pcap_if_t; +typedef struct pcap_if pcap_if_t; -typedef struct net_timeval { - long tv_sec; - long tv_usec; -} net_timeval; - -#define PCAP_ERRBUF_SIZE 256 +# define PCAP_ERRBUF_SIZE 256 struct pcap_pkthdr { - struct net_timeval ts; - bpf_u_int32 caplen; - bpf_u_int32 len; + struct timeval ts; + bpf_u_int32 caplen; + bpf_u_int32 len; }; struct pcap_if { - struct pcap_if *next; - char *name; - char *description; - void *addresses; - unsigned int flags; + struct pcap_if *next; + char *name; + char *description; + void *addresses; + bpf_u_int32 flags; }; +struct pcap_send_queue { + unsigned int maxlen; /* Maximum size of the queue, in bytes. This + variable contains the size of the buffer field. */ + unsigned int len; /* Current size of the queue, in bytes. */ + char *buffer; /* Buffer containing the packets to be sent. */ +}; -static volatile void *pcap_handle; /* handle to WinPcap DLL */ -static volatile void *pcap; /* handle to WinPcap library */ -static volatile thread_t *poll_tid; -static const netcard_t *poll_card; /* netcard linked to us */ -static event_t *poll_state; +typedef struct pcap_send_queue pcap_send_queue; +typedef void (*pcap_handler)(unsigned char *user, const struct pcap_pkthdr *h, const unsigned char *bytes); +#endif + +typedef struct { + void *pcap; /* handle to pcap lib instance */ + netcard_t *card; /* netcard linked to us */ + thread_t *poll_tid; + net_evt_t tx_event; + net_evt_t stop_event; + netpkt_t pkt; + netpkt_t pktv[PCAP_PKT_BATCH]; + uint8_t mac_addr[6]; +#ifdef _WIN32 + struct pcap_send_queue *pcap_queue; +#endif +} net_pcap_t; + +typedef struct { + char *intf_name; + uint8_t *mac_addr; +} net_pcap_params_t; + +static volatile void *libpcap_handle; /* handle to WinPcap DLL */ /* Pointers to the real functions. */ -static const char *(*f_pcap_lib_version)(void); -static int (*f_pcap_findalldevs)(pcap_if_t **,char *); -static void (*f_pcap_freealldevs)(void *); -static void *(*f_pcap_open_live)(const char *,int,int,int,char *); -static int (*f_pcap_compile)(void *,void *, - const char *,int,bpf_u_int32); -static int (*f_pcap_setfilter)(void *,void *); +static const char *(*f_pcap_lib_version)(void); +static int (*f_pcap_findalldevs)(pcap_if_t **, char *); +static void (*f_pcap_freealldevs)(void *); +static void *(*f_pcap_open_live)(const char *, int, int, int, char *); +static int (*f_pcap_compile)(void *, void *, const char *, int, bpf_u_int32); +static int (*f_pcap_setfilter)(void *, void *); static const unsigned char - *(*f_pcap_next)(void *,void *); -static int (*f_pcap_sendpacket)(void *,const unsigned char *,int); -static void (*f_pcap_close)(void *); -static dllimp_t pcap_imports[] = { - { "pcap_lib_version", &f_pcap_lib_version }, - { "pcap_findalldevs", &f_pcap_findalldevs }, - { "pcap_freealldevs", &f_pcap_freealldevs }, - { "pcap_open_live", &f_pcap_open_live }, - { "pcap_compile", &f_pcap_compile }, - { "pcap_setfilter", &f_pcap_setfilter }, - { "pcap_next", &f_pcap_next }, - { "pcap_sendpacket", &f_pcap_sendpacket }, - { "pcap_close", &f_pcap_close }, - { NULL, NULL }, -}; + *(*f_pcap_next)(void *, void *); +static int (*f_pcap_sendpacket)(void *, const unsigned char *, int); +static void (*f_pcap_close)(void *); +static int (*f_pcap_setnonblock)(void *, int, char *); +static int (*f_pcap_set_immediate_mode)(void *, int); +static int (*f_pcap_set_promisc)(void *, int); +static int (*f_pcap_set_snaplen)(void *, int); +static int (*f_pcap_dispatch)(void *, int, pcap_handler callback, unsigned char *user); +static void *(*f_pcap_create)(const char *, char *); +static int (*f_pcap_activate)(void *); +static void *(*f_pcap_geterr)(void *); +#ifdef _WIN32 +static HANDLE (*f_pcap_getevent)(void *); +static int (*f_pcap_sendqueue_queue)(void *, void *, void *); +static unsigned int (*f_pcap_sendqueue_transmit)(void *, void *, int sync); +static void *(*f_pcap_sendqueue_alloc)(unsigned int memsize); +static void (*f_pcap_sendqueue_destroy)(void *); +#else +static int (*f_pcap_get_selectable_fd)(void *); +#endif +static dllimp_t pcap_imports[] = { + {"pcap_lib_version", &f_pcap_lib_version }, + { "pcap_findalldevs", &f_pcap_findalldevs }, + { "pcap_freealldevs", &f_pcap_freealldevs }, + { "pcap_open_live", &f_pcap_open_live }, + { "pcap_compile", &f_pcap_compile }, + { "pcap_setfilter", &f_pcap_setfilter }, + { "pcap_next", &f_pcap_next }, + { "pcap_sendpacket", &f_pcap_sendpacket }, + { "pcap_close", &f_pcap_close }, + { "pcap_setnonblock", &f_pcap_setnonblock }, + { "pcap_set_immediate_mode", &f_pcap_set_immediate_mode}, + { "pcap_set_promisc", &f_pcap_set_promisc }, + { "pcap_set_snaplen", &f_pcap_set_snaplen }, + { "pcap_dispatch", &f_pcap_dispatch }, + { "pcap_create", &f_pcap_create }, + { "pcap_activate", &f_pcap_activate }, + { "pcap_geterr", &f_pcap_geterr }, +#ifdef _WIN32 + { "pcap_getevent", &f_pcap_getevent }, + { "pcap_sendqueue_queue", &f_pcap_sendqueue_queue }, + { "pcap_sendqueue_transmit", &f_pcap_sendqueue_transmit}, + { "pcap_sendqueue_alloc", &f_pcap_sendqueue_alloc }, + { "pcap_sendqueue_destroy", &f_pcap_sendqueue_destroy }, +#else + { "pcap_get_selectable_fd", &f_pcap_get_selectable_fd }, +#endif + { NULL, NULL }, +}; #ifdef ENABLE_PCAP_LOG int pcap_do_log = ENABLE_PCAP_LOG; - static void pcap_log(const char *fmt, ...) { va_list ap; if (pcap_do_log) { - va_start(ap, fmt); - pclog_ex(fmt, ap); - va_end(ap); + va_start(ap, fmt); + pclog_ex(fmt, ap); + va_end(ap); } } #else -#define pcap_log(fmt, ...) +# define pcap_log(fmt, ...) #endif - -/* Handle the receiving of frames from the channel. */ static void -poll_thread(void *arg) +net_pcap_rx_handler(uint8_t *user, const struct pcap_pkthdr *h, const uint8_t *bytes) { - uint8_t *mac = (uint8_t *)arg; - uint8_t *data = NULL; - struct pcap_pkthdr h; - uint32_t mac_cmp32[2]; - uint16_t mac_cmp16[2]; - event_t *evt; - int tx; - - pcap_log("PCAP: polling started.\n"); - thread_set_event(poll_state); - - /* Create a waitable event. */ - pcap_log("PCAP: Creating event...\n"); - evt = thread_create_event(); - - /* As long as the channel is open.. */ - while (pcap != NULL) { - /* Request ownership of the device. */ - network_wait(1); - - /* Wait for a poll request. */ - network_poll(); - - if (pcap == NULL) - break; - - if (network_get_wait() || (poll_card->set_link_state && poll_card->set_link_state(poll_card->priv)) || (poll_card->wait && poll_card->wait(poll_card->priv))) - data = NULL; - else - data = (uint8_t *)f_pcap_next((void *)pcap, &h); - if (data != NULL) { - /* Received MAC. */ - mac_cmp32[0] = *(uint32_t *)(data+6); - mac_cmp16[0] = *(uint16_t *)(data+10); - - /* Local MAC. */ - mac_cmp32[1] = *(uint32_t *)mac; - mac_cmp16[1] = *(uint16_t *)(mac+4); - if ((mac_cmp32[0] != mac_cmp32[1]) || - (mac_cmp16[0] != mac_cmp16[1])) - network_queue_put(0, poll_card->priv, data, h.caplen); - else { - /* Mark as invalid packet. */ - data = NULL; - } - } - - /* Wait for the next packet to arrive. */ - tx = network_tx_queue_check(); - - if (tx) - network_do_tx(); - - /* If we did not get anything, wait a while. */ - if (!tx) - thread_wait_event(evt, 10); - - /* Release ownership of the device. */ - network_wait(0); - } - - /* No longer needed. */ - if (evt != NULL) - thread_destroy_event(evt); - - pcap_log("PCAP: polling stopped.\n"); - if (poll_state != NULL) - thread_set_event(poll_state); + net_pcap_t *pcap = (net_pcap_t *) user; + memcpy(pcap->pkt.data, bytes, h->caplen); + pcap->pkt.len = h->caplen; + network_rx_put_pkt(pcap->card, &pcap->pkt); } +/* Send a packet to the Pcap interface. */ +void +net_pcap_in(void *pcap, uint8_t *bufp, int len) +{ + if (pcap == NULL) + return; + + f_pcap_sendpacket(pcap, bufp, len); +} + +void +net_pcap_in_available(void *priv) +{ + net_pcap_t *pcap = (net_pcap_t *) priv; + net_event_set(&pcap->tx_event); +} + +#ifdef _WIN32 +static void +net_pcap_thread(void *priv) +{ + net_pcap_t *pcap = (net_pcap_t *) priv; + + pcap_log("PCAP: polling started.\n"); + + HANDLE events[NET_EVENT_MAX]; + events[NET_EVENT_STOP] = net_event_get_handle(&pcap->stop_event); + events[NET_EVENT_TX] = net_event_get_handle(&pcap->tx_event); + events[NET_EVENT_RX] = f_pcap_getevent(pcap->pcap); + + bool run = true; + + struct pcap_pkthdr h; + while (run) { + int ret = WaitForMultipleObjects(NET_EVENT_MAX, events, FALSE, INFINITE); + + switch (ret - WAIT_OBJECT_0) { + case NET_EVENT_STOP: + net_event_clear(&pcap->stop_event); + run = false; + break; + + case NET_EVENT_TX: + net_event_clear(&pcap->tx_event); + int packets = network_tx_popv(pcap->card, pcap->pktv, PCAP_PKT_BATCH); + for (int i = 0; i < packets; i++) { + h.caplen = pcap->pktv[i].len; + f_pcap_sendqueue_queue(pcap->pcap_queue, &h, pcap->pktv[i].data); + } + f_pcap_sendqueue_transmit(pcap->pcap, pcap->pcap_queue, 0); + pcap->pcap_queue->len = 0; + break; + + case NET_EVENT_RX: + f_pcap_dispatch(pcap->pcap, PCAP_PKT_BATCH, net_pcap_rx_handler, (unsigned char *) pcap); + break; + + default: + break; + } + } + + pcap_log("PCAP: polling stopped.\n"); +} +#else +static void +net_pcap_thread(void *priv) +{ + net_pcap_t *pcap = (net_pcap_t *) priv; + + pcap_log("PCAP: polling started.\n"); + + struct pollfd pfd[NET_EVENT_MAX]; + pfd[NET_EVENT_STOP].fd = net_event_get_fd(&pcap->stop_event); + pfd[NET_EVENT_STOP].events = POLLIN | POLLPRI; + + pfd[NET_EVENT_TX].fd = net_event_get_fd(&pcap->tx_event); + pfd[NET_EVENT_TX].events = POLLIN | POLLPRI; + + pfd[NET_EVENT_RX].fd = f_pcap_get_selectable_fd((void *) pcap->pcap); + pfd[NET_EVENT_RX].events = POLLIN | POLLPRI; + + /* As long as the channel is open.. */ + while (1) { + poll(pfd, NET_EVENT_MAX, -1); + + if (pfd[NET_EVENT_STOP].revents & POLLIN) { + net_event_clear(&pcap->stop_event); + break; + } + + if (pfd[NET_EVENT_TX].revents & POLLIN) { + net_event_clear(&pcap->tx_event); + + int packets = network_tx_popv(pcap->card, pcap->pktv, PCAP_PKT_BATCH); + for (int i = 0; i < packets; i++) { + net_pcap_in(pcap->pcap, pcap->pktv[i].data, pcap->pktv[i].len); + } + } + + if (pfd[NET_EVENT_RX].revents & POLLIN) { + f_pcap_dispatch(pcap->pcap, PCAP_PKT_BATCH, net_pcap_rx_handler, (unsigned char *) pcap); + } + } + + pcap_log("PCAP: polling stopped.\n"); +} +#endif /* * Prepare the (Win)Pcap module for use. @@ -241,192 +359,215 @@ poll_thread(void *arg) int net_pcap_prepare(netdev_t *list) { - char errbuf[PCAP_ERRBUF_SIZE]; - pcap_if_t *devlist, *dev; - int i = 0; - - /* Local variables. */ - pcap = NULL; + char errbuf[PCAP_ERRBUF_SIZE]; + pcap_if_t *devlist; + int i = 0; /* Try loading the DLL. */ #ifdef _WIN32 - pcap_handle = dynld_module("wpcap.dll", pcap_imports); + libpcap_handle = dynld_module("wpcap.dll", pcap_imports); #elif defined __APPLE__ - pcap_handle = dynld_module("libpcap.dylib", pcap_imports); + libpcap_handle = dynld_module("libpcap.dylib", pcap_imports); #else - pcap_handle = dynld_module("libpcap.so", pcap_imports); + libpcap_handle = dynld_module("libpcap.so", pcap_imports); #endif - if (pcap_handle == NULL) return(-1); + if (libpcap_handle == NULL) { + pcap_log("PCAP: error loading pcap module\n"); + return (-1); + } /* Retrieve the device list from the local machine */ if (f_pcap_findalldevs(&devlist, errbuf) == -1) { - pcap_log("PCAP: error in pcap_findalldevs: %s\n", errbuf); - return(-1); + pcap_log("PCAP: error in pcap_findalldevs: %s\n", errbuf); + return (-1); } - for (dev=devlist; dev!=NULL; dev=dev->next) { - /** - * we initialize the strings to NULL first for strncpy - */ + for (pcap_if_t *dev = devlist; dev != NULL; dev = dev->next) { + if (i >= (NET_HOST_INTF_MAX - 1)) + break; - memset(list->device, '\0', sizeof(list->device)); - memset(list->description, '\0', sizeof(list->description)); + /** + * we initialize the strings to NULL first for strncpy + */ - strncpy(list->device, dev->name, sizeof(list->device) - 1); - if (dev->description) { - strncpy(list->description, dev->description, sizeof(list->description) - 1); - } else { - /* if description is NULL, set the name. This allows pcap to display *something* useful under WINE */ - strncpy(list->description, dev->name, sizeof(list->description) - 1); - } + memset(list->device, '\0', sizeof(list->device)); + memset(list->description, '\0', sizeof(list->description)); - list++; i++; + strncpy(list->device, dev->name, sizeof(list->device) - 1); + if (dev->description) { + strncpy(list->description, dev->description, sizeof(list->description) - 1); + } else { + /* if description is NULL, set the name. This allows pcap to display *something* useful under WINE */ + strncpy(list->description, dev->name, sizeof(list->description) - 1); + } + + list++; + i++; } /* Release the memory. */ f_pcap_freealldevs(devlist); - return(i); + return i; } +/* + * Copy error message to the error buffer + * and log if enabled. + */ +void net_pcap_error(char *errbuf, const char *message) { + strncpy(errbuf, message, NET_DRV_ERRBUF_SIZE); + pcap_log("PCAP: %s\n", message); +} /* * Initialize (Win)Pcap for use. * - * This is called on every 'cycle' of the emulator, - * if and as long the NetworkType is set to PCAP, - * and also as long as we have a NetCard defined. - */ -int -net_pcap_init(void) -{ - char errbuf[PCAP_ERRBUF_SIZE]; - char *str; - - /* Did we already load the library? */ - if (pcap_handle == NULL) - return(-1); - - /* Get the PCAP library name and version. */ - strcpy(errbuf, f_pcap_lib_version()); - str = strchr(errbuf, '('); - if (str != NULL) *(str-1) = '\0'; - pcap_log("PCAP: initializing, %s\n", errbuf); - - /* Get the value of our capture interface. */ - if ((network_host[0] == '\0') || !strcmp(network_host, "none")) { - pcap_log("PCAP: no interface configured!\n"); - return(-1); - } - - poll_tid = NULL; - poll_state = NULL; - poll_card = NULL; - - return(0); -} - - -/* Close up shop. */ -void -net_pcap_close(void) -{ - void *pc; - - if (pcap == NULL) return; - - pcap_log("PCAP: closing.\n"); - - /* Tell the polling thread to shut down. */ - pc = (void *)pcap; pcap = NULL; - - /* Tell the thread to terminate. */ - if (poll_tid != NULL) { - network_busy(0); - - /* Wait for the thread to finish. */ - pcap_log("PCAP: waiting for thread to end...\n"); - thread_wait_event(poll_state, -1); - pcap_log("PCAP: thread ended\n"); - thread_destroy_event(poll_state); - - poll_tid = NULL; - poll_state = NULL; - poll_card = NULL; - } - - /* OK, now shut down Pcap itself. */ - f_pcap_close(pc); - pcap = NULL; -} - - -/* - * Reset (Win)Pcap and activate it. - * - * This is called on every 'cycle' of the emulator, - * if and as long the NetworkType is set to PCAP, - * and also as long as we have a NetCard defined. - * * We already know we have PCAP available, as this * is called when the network activates itself and * tries to attach to the network module. */ -int -net_pcap_reset(const netcard_t *card, uint8_t *mac) +void * +net_pcap_init(const netcard_t *card, const uint8_t *mac_addr, void *priv, char *netdrv_errbuf) { - char errbuf[PCAP_ERRBUF_SIZE]; - char filter_exp[255]; + char errbuf[PCAP_ERRBUF_SIZE]; + char *str; + char filter_exp[255]; struct bpf_program fp; + char errbuf_prep[NET_DRV_ERRBUF_SIZE]; - /* Open a PCAP live channel. */ - if ((pcap = f_pcap_open_live(network_host, /* interface name */ - 1518, /* max packet size */ - 1, /* promiscuous mode? */ - 10, /* timeout in msec */ - errbuf)) == NULL) { /* error buffer */ - pcap_log(" Unable to open device: %s!\n", network_host); - return(-1); + char *intf_name = (char *) priv; + + /* Did we already load the library? */ + if (libpcap_handle == NULL) { + net_pcap_error(netdrv_errbuf, "net_pcap_init without handle"); + return NULL; + } + + /* Get the PCAP library name and version. */ + strcpy(errbuf, f_pcap_lib_version()); + str = strchr(errbuf, '('); + if (str != NULL) + *(str - 1) = '\0'; + pcap_log("PCAP: initializing, %s\n", errbuf); + + /* Get the value of our capture interface. */ + if ((intf_name[0] == '\0') || !strcmp(intf_name, "none")) { + net_pcap_error(netdrv_errbuf, "No interface configured"); + return NULL; + } + + pcap_log("PCAP: interface: %s\n", intf_name); + + net_pcap_t *pcap = calloc(1, sizeof(net_pcap_t)); + pcap->card = (netcard_t *) card; + memcpy(pcap->mac_addr, mac_addr, sizeof(pcap->mac_addr)); + + if ((pcap->pcap = f_pcap_create(intf_name, errbuf)) == NULL) { + snprintf(errbuf_prep, NET_DRV_ERRBUF_SIZE, " Unable to open device: %s!\n", intf_name); + net_pcap_error(netdrv_errbuf, errbuf_prep); + free(pcap); + return NULL; + } + + if (f_pcap_setnonblock(pcap->pcap, 1, errbuf) != 0) + pcap_log("PCAP: failed nonblock %s\n", errbuf); + + if (f_pcap_set_immediate_mode(pcap->pcap, 1) != 0) + pcap_log("PCAP: error setting immediate mode\n"); + + if (f_pcap_set_promisc(pcap->pcap, 1) != 0) + pcap_log("PCAP: error enabling promiscuous mode\n"); + + if (f_pcap_set_snaplen(pcap->pcap, NET_MAX_FRAME) != 0) + pcap_log("PCAP: error setting snaplen\n"); + + if (f_pcap_activate(pcap->pcap) != 0) { + snprintf(errbuf_prep, NET_DRV_ERRBUF_SIZE, "%s", (char *)f_pcap_geterr(pcap->pcap)); + net_pcap_error(netdrv_errbuf, errbuf_prep); + f_pcap_close(pcap->pcap); + free(pcap); + return NULL; } - pcap_log("PCAP: interface: %s\n", network_host); /* Create a MAC address based packet filter. */ pcap_log("PCAP: installing filter for MAC=%02x:%02x:%02x:%02x:%02x:%02x\n", - mac[0], mac[1], mac[2], mac[3], mac[4], mac[5]); + mac_addr[0], mac_addr[1], mac_addr[2], mac_addr[3], mac_addr[4], mac_addr[5]); sprintf(filter_exp, - "( ((ether dst ff:ff:ff:ff:ff:ff) or (ether dst %02x:%02x:%02x:%02x:%02x:%02x)) and not (ether src %02x:%02x:%02x:%02x:%02x:%02x) )", - mac[0], mac[1], mac[2], mac[3], mac[4], mac[5], - mac[0], mac[1], mac[2], mac[3], mac[4], mac[5]); - if (f_pcap_compile((void *)pcap, &fp, filter_exp, 0, 0xffffffff) != -1) { - if (f_pcap_setfilter((void *)pcap, &fp) != 0) { - pcap_log("PCAP: error installing filter (%s) !\n", filter_exp); - f_pcap_close((void *)pcap); - return(-1); - } + "( ((ether dst ff:ff:ff:ff:ff:ff) or (ether dst %02x:%02x:%02x:%02x:%02x:%02x)) and not (ether src %02x:%02x:%02x:%02x:%02x:%02x) )", + mac_addr[0], mac_addr[1], mac_addr[2], mac_addr[3], mac_addr[4], mac_addr[5], + mac_addr[0], mac_addr[1], mac_addr[2], mac_addr[3], mac_addr[4], mac_addr[5]); + if (f_pcap_compile(pcap->pcap, &fp, filter_exp, 0, 0xffffffff) != -1) { + if (f_pcap_setfilter(pcap->pcap, &fp) != 0) { + snprintf(errbuf_prep, NET_DRV_ERRBUF_SIZE, "Error installing filter (%s)\n", filter_exp); + net_pcap_error(netdrv_errbuf, errbuf_prep); + f_pcap_close(pcap->pcap); + free(pcap); + return NULL; + } } else { - pcap_log("PCAP: could not compile filter (%s) !\n", filter_exp); - f_pcap_close((void *)pcap); - return(-1); + snprintf(errbuf_prep, NET_DRV_ERRBUF_SIZE, "Could not compile filter (%s) : %s!\n", filter_exp, (char *)f_pcap_geterr(pcap->pcap)); + net_pcap_error(netdrv_errbuf, errbuf_prep); + f_pcap_close(pcap->pcap); + free(pcap); + return NULL; } - /* Save the callback info. */ - poll_card = card; +#ifdef _WIN32 + pcap->pcap_queue = f_pcap_sendqueue_alloc(PCAP_PKT_BATCH * NET_MAX_FRAME); +#endif - pcap_log("PCAP: starting thread..\n"); - poll_state = thread_create_event(); - poll_tid = thread_create(poll_thread, mac); - thread_wait_event(poll_state, -1); + for (int i = 0; i < PCAP_PKT_BATCH; i++) { + pcap->pktv[i].data = calloc(1, NET_MAX_FRAME); + } + pcap->pkt.data = calloc(1, NET_MAX_FRAME); - return(0); + net_event_init(&pcap->tx_event); + net_event_init(&pcap->stop_event); + pcap->poll_tid = thread_create(net_pcap_thread, pcap); + + return pcap; } - -/* Send a packet to the Pcap interface. */ +/* Close up shop. */ void -net_pcap_in(uint8_t *bufp, int len) +net_pcap_close(void *priv) { - if (pcap == NULL) - return; + if (!priv) + return; - f_pcap_sendpacket((void *)pcap, bufp, len); + net_pcap_t *pcap = (net_pcap_t *) priv; + + pcap_log("PCAP: closing.\n"); + + /* Tell the thread to terminate. */ + net_event_set(&pcap->stop_event); + + /* Wait for the thread to finish. */ + pcap_log("PCAP: waiting for thread to end...\n"); + thread_wait(pcap->poll_tid); + pcap_log("PCAP: thread ended\n"); + + for (int i = 0; i < PCAP_PKT_BATCH; i++) { + free(pcap->pktv[i].data); + } + free(pcap->pkt.data); + +#ifdef _WIN32 + f_pcap_sendqueue_destroy((void *) pcap->pcap_queue); +#endif + /* OK, now shut down Pcap itself. */ + f_pcap_close(pcap->pcap); + + net_event_close(&pcap->tx_event); + net_event_close(&pcap->stop_event); + + free(pcap); } + +const netdrv_t net_pcap_drv = { + &net_pcap_in_available, + &net_pcap_init, + &net_pcap_close, + NULL +}; diff --git a/src/network/net_pcnet.c b/src/network/net_pcnet.c index 441c50f67..ab761acf3 100644 --- a/src/network/net_pcnet.c +++ b/src/network/net_pcnet.c @@ -1,25 +1,25 @@ /* - * 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. + * 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. * - * Emulation of the AMD PCnet LANCE NIC controller for both the ISA, VLB, - * and PCI buses. + * Emulation of the AMD PCnet LANCE NIC controller for both the ISA, VLB, + * and PCI buses. * * * - * Authors: Miran Grca, - * TheCollector1995, - * Antony T Curtis + * Authors: Miran Grca, + * TheCollector1995, + * Antony T Curtis * - * Copyright 2004-2019 Antony T Curtis - * Copyright 2016-2019 Miran Grca. + * Copyright 2004-2019 Antony T Curtis + * Copyright 2016-2019 Miran Grca. */ #ifdef _WIN32 -#include +# include #else -#include +# include #endif #include #include @@ -29,6 +29,7 @@ #include #include #include +#include #define HAVE_STDARG_H #include <86box/86box.h> #include <86box/io.h> @@ -41,109 +42,112 @@ #include <86box/random.h> #include <86box/device.h> #include <86box/isapnp.h> +#include <86box/timer.h> +#include <86box/thread.h> #include <86box/network.h> #include <86box/net_pcnet.h> #include <86box/bswap.h> +#include <86box/plat_fallthrough.h> +#include <86box/plat_unused.h> /* PCI info. */ -#define PCI_VENDID 0x1022 /* AMD */ -#define PCI_DEVID 0x2000 /* PCnet-PCI II (Am79c970A) */ -#define PCI_REGSIZE 256 /* size of PCI space */ +#define PCI_VENDID 0x1022 /* AMD */ +#define PCI_DEVID 0x2000 /* PCnet-PCI II (Am79c970A) */ +#define PCI_REGSIZE 256 /* size of PCI space */ #pragma pack(1) -typedef struct RTNETETHERHDR -{ - uint8_t DstMac[6]; - uint8_t SrcMac[6]; +typedef struct RTNETETHERHDR { + uint8_t DstMac[6]; + uint8_t SrcMac[6]; /** Ethernet frame type or frame size, depending on the kind of ethernet. * This is big endian on the wire. */ - uint16_t EtherType; + uint16_t EtherType; } RTNETETHERHDR; #pragma pack() -#define BCR_MAX_RAP 50 -#define MII_MAX_REG 32 -#define CSR_MAX_REG 128 +#define BCR_MAX_RAP 50 +#define MII_MAX_REG 32 +#define CSR_MAX_REG 128 /** Maximum number of times we report a link down to the guest (failure to send frame) */ -#define PCNET_MAX_LINKDOWN_REPORTED 3 +#define PCNET_MAX_LINKDOWN_REPORTED 3 /** Maximum frame size we handle */ -#define MAX_FRAME 1536 +#define MAX_FRAME 1536 /** @name Bus configuration registers * @{ */ -#define BCR_MSRDA 0 -#define BCR_MSWRA 1 -#define BCR_MC 2 -#define BCR_RESERVED3 3 -#define BCR_LNKST 4 -#define BCR_LED1 5 -#define BCR_LED2 6 -#define BCR_LED3 7 -#define BCR_SWCONFIG 8 -#define BCR_FDC 9 +#define BCR_MSRDA 0 +#define BCR_MSWRA 1 +#define BCR_MC 2 +#define BCR_RESERVED3 3 +#define BCR_LNKST 4 +#define BCR_LED1 5 +#define BCR_LED2 6 +#define BCR_LED3 7 +#define BCR_SWCONFIG 8 +#define BCR_FDC 9 /* 10 - 15 = reserved */ -#define BCR_IOBASEL 16 /* Reserved */ -#define BCR_IOBASEU 16 /* Reserved */ -#define BCR_BSBC 18 -#define BCR_EECAS 19 -#define BCR_SWS 20 -#define BCR_INTCON 21 /* Reserved */ -#define BCR_PLAT 22 -#define BCR_PCISVID 23 -#define BCR_PCISID 24 -#define BCR_SRAMSIZ 25 -#define BCR_SRAMB 26 -#define BCR_SRAMIC 27 -#define BCR_EBADDRL 28 -#define BCR_EBADDRU 29 -#define BCR_EBD 30 -#define BCR_STVAL 31 -#define BCR_MIICAS 32 -#define BCR_MIIADDR 33 -#define BCR_MIIMDR 34 -#define BCR_PCIVID 35 -#define BCR_PMC_A 36 -#define BCR_DATA0 37 -#define BCR_DATA1 38 -#define BCR_DATA2 39 -#define BCR_DATA3 40 -#define BCR_DATA4 41 -#define BCR_DATA5 42 -#define BCR_DATA6 43 -#define BCR_DATA7 44 -#define BCR_PMR1 45 -#define BCR_PMR2 46 -#define BCR_PMR3 47 +#define BCR_IOBASEL 16 /* Reserved */ +#define BCR_IOBASEU 16 /* Reserved */ +#define BCR_BSBC 18 +#define BCR_EECAS 19 +#define BCR_SWS 20 +#define BCR_INTCON 21 /* Reserved */ +#define BCR_PLAT 22 +#define BCR_PCISVID 23 +#define BCR_PCISID 24 +#define BCR_SRAMSIZ 25 +#define BCR_SRAMB 26 +#define BCR_SRAMIC 27 +#define BCR_EBADDRL 28 +#define BCR_EBADDRU 29 +#define BCR_EBD 30 +#define BCR_STVAL 31 +#define BCR_MIICAS 32 +#define BCR_MIIADDR 33 +#define BCR_MIIMDR 34 +#define BCR_PCIVID 35 +#define BCR_PMC_A 36 +#define BCR_DATA0 37 +#define BCR_DATA1 38 +#define BCR_DATA2 39 +#define BCR_DATA3 40 +#define BCR_DATA4 41 +#define BCR_DATA5 42 +#define BCR_DATA6 43 +#define BCR_DATA7 44 +#define BCR_PMR1 45 +#define BCR_PMR2 46 +#define BCR_PMR3 47 /** @} */ /** @name Bus configuration sub register accessors. * @{ */ -#define BCR_DWIO(S) !!((S)->aBCR[BCR_BSBC] & 0x0080) -#define BCR_SSIZE32(S) !!((S)->aBCR[BCR_SWS ] & 0x0100) -#define BCR_SWSTYLE(S) ((S)->aBCR[BCR_SWS ] & 0x00FF) +#define BCR_DWIO(S) !!((S)->aBCR[BCR_BSBC] & 0x0080) +#define BCR_SSIZE32(S) !!((S)->aBCR[BCR_SWS] & 0x0100) +#define BCR_SWSTYLE(S) ((S)->aBCR[BCR_SWS] & 0x00FF) /** @} */ /** @name CSR subregister accessors. * @{ */ -#define CSR_INIT(S) !!((S)->aCSR[0] & 0x0001) /**< Init assertion */ -#define CSR_STRT(S) !!((S)->aCSR[0] & 0x0002) /**< Start assertion */ -#define CSR_STOP(S) !!((S)->aCSR[0] & 0x0004) /**< Stop assertion */ -#define CSR_TDMD(S) !!((S)->aCSR[0] & 0x0008) /**< Transmit demand. (perform xmit poll now (readable, settable, not clearable) */ -#define CSR_TXON(S) !!((S)->aCSR[0] & 0x0010) /**< Transmit on (readonly) */ -#define CSR_RXON(S) !!((S)->aCSR[0] & 0x0020) /**< Receive On */ -#define CSR_INEA(S) !!((S)->aCSR[0] & 0x0040) /**< Interrupt Enable */ -#define CSR_LAPPEN(S) !!((S)->aCSR[3] & 0x0020) /**< Look Ahead Packet Processing Enable */ -#define CSR_DXSUFLO(S) !!((S)->aCSR[3] & 0x0040) /**< Disable Transmit Stop on Underflow error */ -#define CSR_ASTRP_RCV(S) !!((S)->aCSR[4] & 0x0400) /**< Auto Strip Receive */ -#define CSR_DPOLL(S) !!((S)->aCSR[4] & 0x1000) /**< Disable Transmit Polling */ -#define CSR_SPND(S) !!((S)->aCSR[5] & 0x0001) /**< Suspend */ -#define CSR_LTINTEN(S) !!((S)->aCSR[5] & 0x4000) /**< Last Transmit Interrupt Enable */ -#define CSR_TOKINTD(S) !!((S)->aCSR[5] & 0x8000) /**< Transmit OK Interrupt Disable */ +#define CSR_INIT(S) !!((S)->aCSR[0] & 0x0001) /**< Init assertion */ +#define CSR_STRT(S) !!((S)->aCSR[0] & 0x0002) /**< Start assertion */ +#define CSR_STOP(S) !!((S)->aCSR[0] & 0x0004) /**< Stop assertion */ +#define CSR_TDMD(S) !!((S)->aCSR[0] & 0x0008) /**< Transmit demand. (perform xmit poll now (readable, settable, not clearable) */ +#define CSR_TXON(S) !!((S)->aCSR[0] & 0x0010) /**< Transmit on (readonly) */ +#define CSR_RXON(S) !!((S)->aCSR[0] & 0x0020) /**< Receive On */ +#define CSR_INEA(S) !!((S)->aCSR[0] & 0x0040) /**< Interrupt Enable */ +#define CSR_LAPPEN(S) !!((S)->aCSR[3] & 0x0020) /**< Look Ahead Packet Processing Enable */ +#define CSR_DXSUFLO(S) !!((S)->aCSR[3] & 0x0040) /**< Disable Transmit Stop on Underflow error */ +#define CSR_ASTRP_RCV(S) !!((S)->aCSR[4] & 0x0400) /**< Auto Strip Receive */ +#define CSR_DPOLL(S) !!((S)->aCSR[4] & 0x1000) /**< Disable Transmit Polling */ +#define CSR_SPND(S) !!((S)->aCSR[5] & 0x0001) /**< Suspend */ +#define CSR_LTINTEN(S) !!((S)->aCSR[5] & 0x4000) /**< Last Transmit Interrupt Enable */ +#define CSR_TOKINTD(S) !!((S)->aCSR[5] & 0x8000) /**< Transmit OK Interrupt Disable */ -#define CSR_STINT !!((S)->aCSR[7] & 0x0800) /**< Software Timer Interrupt */ -#define CSR_STINTE !!((S)->aCSR[7] & 0x0400) /**< Software Timer Interrupt Enable */ +#define CSR_STINT !!((S)->aCSR[7] & 0x0800) /**< Software Timer Interrupt */ +#define CSR_STINTE !!((S)->aCSR[7] & 0x0400) /**< Software Timer Interrupt Enable */ #define CSR_DRX(S) !!((S)->aCSR[15] & 0x0001) /**< Disable Receiver */ #define CSR_DTX(S) !!((S)->aCSR[15] & 0x0002) /**< Disable Transmit */ @@ -154,73 +158,72 @@ typedef struct RTNETETHERHDR /** @name CSR register accessors. * @{ */ -#define CSR_IADR(S) (*(uint32_t*)((S)->aCSR + 1)) /**< Initialization Block Address */ -#define CSR_CRBA(S) (*(uint32_t*)((S)->aCSR + 18)) /**< Current Receive Buffer Address */ -#define CSR_CXBA(S) (*(uint32_t*)((S)->aCSR + 20)) /**< Current Transmit Buffer Address */ -#define CSR_NRBA(S) (*(uint32_t*)((S)->aCSR + 22)) /**< Next Receive Buffer Address */ -#define CSR_BADR(S) (*(uint32_t*)((S)->aCSR + 24)) /**< Base Address of Receive Ring */ -#define CSR_NRDA(S) (*(uint32_t*)((S)->aCSR + 26)) /**< Next Receive Descriptor Address */ -#define CSR_CRDA(S) (*(uint32_t*)((S)->aCSR + 28)) /**< Current Receive Descriptor Address */ -#define CSR_BADX(S) (*(uint32_t*)((S)->aCSR + 30)) /**< Base Address of Transmit Descriptor */ -#define CSR_NXDA(S) (*(uint32_t*)((S)->aCSR + 32)) /**< Next Transmit Descriptor Address */ -#define CSR_CXDA(S) (*(uint32_t*)((S)->aCSR + 34)) /**< Current Transmit Descriptor Address */ -#define CSR_NNRD(S) (*(uint32_t*)((S)->aCSR + 36)) /**< Next Next Receive Descriptor Address */ -#define CSR_NNXD(S) (*(uint32_t*)((S)->aCSR + 38)) /**< Next Next Transmit Descriptor Address */ -#define CSR_CRBC(S) ((S)->aCSR[40]) /**< Current Receive Byte Count */ -#define CSR_CRST(S) ((S)->aCSR[41]) /**< Current Receive Status */ -#define CSR_CXBC(S) ((S)->aCSR[42]) /**< Current Transmit Byte Count */ -#define CSR_CXST(S) ((S)->aCSR[43]) /**< Current transmit status */ -#define CSR_NRBC(S) ((S)->aCSR[44]) /**< Next Receive Byte Count */ -#define CSR_NRST(S) ((S)->aCSR[45]) /**< Next Receive Status */ -#define CSR_POLL(S) ((S)->aCSR[46]) /**< Transmit Poll Time Counter */ -#define CSR_PINT(S) ((S)->aCSR[47]) /**< Transmit Polling Interval */ -#define CSR_PXDA(S) (*(uint32_t*)((S)->aCSR + 60)) /**< Previous Transmit Descriptor Address*/ -#define CSR_PXBC(S) ((S)->aCSR[62]) /**< Previous Transmit Byte Count */ -#define CSR_PXST(S) ((S)->aCSR[63]) /**< Previous Transmit Status */ -#define CSR_NXBA(S) (*(uint32_t*)((S)->aCSR + 64)) /**< Next Transmit Buffer Address */ -#define CSR_NXBC(S) ((S)->aCSR[66]) /**< Next Transmit Byte Count */ -#define CSR_NXST(S) ((S)->aCSR[67]) /**< Next Transmit Status */ -#define CSR_RCVRC(S) ((S)->aCSR[72]) /**< Receive Descriptor Ring Counter */ -#define CSR_XMTRC(S) ((S)->aCSR[74]) /**< Transmit Descriptor Ring Counter */ -#define CSR_RCVRL(S) ((S)->aCSR[76]) /**< Receive Descriptor Ring Length */ -#define CSR_XMTRL(S) ((S)->aCSR[78]) /**< Transmit Descriptor Ring Length */ -#define CSR_MISSC(S) ((S)->aCSR[112]) /**< Missed Frame Count */ +#define CSR_IADR(S) (*(uint32_t *) ((S)->aCSR + 1)) /**< Initialization Block Address */ +#define CSR_CRBA(S) (*(uint32_t *) ((S)->aCSR + 18)) /**< Current Receive Buffer Address */ +#define CSR_CXBA(S) (*(uint32_t *) ((S)->aCSR + 20)) /**< Current Transmit Buffer Address */ +#define CSR_NRBA(S) (*(uint32_t *) ((S)->aCSR + 22)) /**< Next Receive Buffer Address */ +#define CSR_BADR(S) (*(uint32_t *) ((S)->aCSR + 24)) /**< Base Address of Receive Ring */ +#define CSR_NRDA(S) (*(uint32_t *) ((S)->aCSR + 26)) /**< Next Receive Descriptor Address */ +#define CSR_CRDA(S) (*(uint32_t *) ((S)->aCSR + 28)) /**< Current Receive Descriptor Address */ +#define CSR_BADX(S) (*(uint32_t *) ((S)->aCSR + 30)) /**< Base Address of Transmit Descriptor */ +#define CSR_NXDA(S) (*(uint32_t *) ((S)->aCSR + 32)) /**< Next Transmit Descriptor Address */ +#define CSR_CXDA(S) (*(uint32_t *) ((S)->aCSR + 34)) /**< Current Transmit Descriptor Address */ +#define CSR_NNRD(S) (*(uint32_t *) ((S)->aCSR + 36)) /**< Next Next Receive Descriptor Address */ +#define CSR_NNXD(S) (*(uint32_t *) ((S)->aCSR + 38)) /**< Next Next Transmit Descriptor Address */ +#define CSR_CRBC(S) ((S)->aCSR[40]) /**< Current Receive Byte Count */ +#define CSR_CRST(S) ((S)->aCSR[41]) /**< Current Receive Status */ +#define CSR_CXBC(S) ((S)->aCSR[42]) /**< Current Transmit Byte Count */ +#define CSR_CXST(S) ((S)->aCSR[43]) /**< Current transmit status */ +#define CSR_NRBC(S) ((S)->aCSR[44]) /**< Next Receive Byte Count */ +#define CSR_NRST(S) ((S)->aCSR[45]) /**< Next Receive Status */ +#define CSR_POLL(S) ((S)->aCSR[46]) /**< Transmit Poll Time Counter */ +#define CSR_PINT(S) ((S)->aCSR[47]) /**< Transmit Polling Interval */ +#define CSR_PXDA(S) (*(uint32_t *) ((S)->aCSR + 60)) /**< Previous Transmit Descriptor Address*/ +#define CSR_PXBC(S) ((S)->aCSR[62]) /**< Previous Transmit Byte Count */ +#define CSR_PXST(S) ((S)->aCSR[63]) /**< Previous Transmit Status */ +#define CSR_NXBA(S) (*(uint32_t *) ((S)->aCSR + 64)) /**< Next Transmit Buffer Address */ +#define CSR_NXBC(S) ((S)->aCSR[66]) /**< Next Transmit Byte Count */ +#define CSR_NXST(S) ((S)->aCSR[67]) /**< Next Transmit Status */ +#define CSR_RCVRC(S) ((S)->aCSR[72]) /**< Receive Descriptor Ring Counter */ +#define CSR_XMTRC(S) ((S)->aCSR[74]) /**< Transmit Descriptor Ring Counter */ +#define CSR_RCVRL(S) ((S)->aCSR[76]) /**< Receive Descriptor Ring Length */ +#define CSR_XMTRL(S) ((S)->aCSR[78]) /**< Transmit Descriptor Ring Length */ +#define CSR_MISSC(S) ((S)->aCSR[112]) /**< Missed Frame Count */ /** Calculates the full physical address. */ -#define PHYSADDR(S,A) ((A) | (S)->GCUpperPhys) - +#define PHYSADDR(S, A) ((A) | (S)->GCUpperPhys) static const uint8_t am79c961_pnp_rom[] = { - 0x04, 0x96, 0x55, 0xaa, 0x00, 0x00, 0x00, 0x00, 0x00, /* ADV55AA, dummy checksum (filled in by isapnp_add_card) */ - 0x0a, 0x10, 0x00, /* PnP version 1.0, vendor version 0.0 */ + 0x04, 0x96, 0x55, 0xaa, 0x00, 0x00, 0x00, 0x00, 0x00, /* ADV55AA, dummy checksum (filled in by isapnp_add_card) */ + 0x0a, 0x10, 0x00, /* PnP version 1.0, vendor version 0.0 */ 0x82, 0x1c, 0x00, 'A', 'M', 'D', ' ', 'E', 't', 'h', 'e', 'r', 'n', 'e', 't', ' ', 'N', 'e', 't', 'w', 'o', 'r', 'k', ' ', 'A', 'd', 'a', 'p', 't', 'e', 'r', /* ANSI identifier */ - 0x16, 0x04, 0x96, 0x55, 0xaa, 0x00, 0xbd, /* logical device ADV55AA, supports vendor-specific registers 0x38/0x3A/0x3B/0x3C/0x3D/0x3F */ - 0x1c, 0x41, 0xd0, 0x82, 0x8c, /* compatible device PNP828C */ - 0x47, 0x00, 0x00, 0x02, 0xe0, 0x03, 0x20, 0x18, /* I/O 0x200-0x3E0, decodes 10-bit, 32-byte alignment, 24 addresses */ - 0x2a, 0xe8, 0x02, /* DMA 3/5/6/7, compatibility, no count by word, no count by byte, not bus master, 16-bit only */ - 0x23, 0x38, 0x9e, 0x09, /* IRQ 3/4/5/9/10/11/12/15, low true level sensitive, high true edge sensitive */ + 0x16, 0x04, 0x96, 0x55, 0xaa, 0x00, 0xbd, /* logical device ADV55AA, supports vendor-specific registers 0x38/0x3A/0x3B/0x3C/0x3D/0x3F */ + 0x1c, 0x41, 0xd0, 0x82, 0x8c, /* compatible device PNP828C */ + 0x47, 0x00, 0x00, 0x02, 0xe0, 0x03, 0x20, 0x18, /* I/O 0x200-0x3E0, decodes 10-bit, 32-byte alignment, 24 addresses */ + 0x2a, 0xe8, 0x02, /* DMA 3/5/6/7, compatibility, no count by word, no count by byte, not bus master, 16-bit only */ + 0x23, 0x38, 0x9e, 0x09, /* IRQ 3/4/5/9/10/11/12/15, low true level sensitive, high true edge sensitive */ 0x79, 0x00 /* end tag, dummy checksum (filled in by isapnp_add_card) */ }; - typedef struct { - mem_mapping_t mmio_mapping; - const char *name; - int board; - int is_pci, is_vlb, is_isa; - int PCIBase; - int MMIOBase; - uint32_t base_address; - int base_irq; - int dma_channel; - int card; /* PCI card slot */ - int xmit_pos; + mem_mapping_t mmio_mapping; + const char *name; + int board; + int is_pci, is_vlb, is_isa; + int PCIBase; + int MMIOBase; + uint32_t base_address; + int base_irq; + int dma_channel; + uint8_t pci_slot; /* PCI card slot */ + uint8_t irq_state; + int xmit_pos; /** Register Address Pointer */ uint32_t u32RAP; /** Internal interrupt service */ - int32_t iISR; + int32_t iISR; /** ??? */ uint32_t u32Lnkst; /** Address of the RX descriptor table (ring). Loaded at init. */ @@ -236,7 +239,7 @@ typedef struct { /** The recv buffer. */ uint8_t abRecvBuf[4096]; /** Size of a RX/TX descriptor (8 or 16 bytes according to SWSTYLE */ - int iLog2DescSize; + int iLog2DescSize; /** Bits 16..23 in 16-bit mode */ uint32_t GCUpperPhys; /** We are waiting/about to start waiting for more receive buffers. */ @@ -255,16 +258,16 @@ typedef struct { /** Number of times we've reported the link down. */ uint32_t cLinkDownReported; /** MS to wait before we enable the link. */ - uint32_t cMsLinkUpDelay; - int transfer_size; - uint8_t maclocal[6]; /* configured MAC (local) address */ - pc_timer_t timer_soft_int, timer_restore; + uint32_t cMsLinkUpDelay; + int transfer_size; + uint8_t maclocal[6]; /* configured MAC (local) address */ + pc_timer_t timer, timer_soft_int, timer_restore; + netcard_t *netcard; } nic_t; /** @todo All structs: big endian? */ -struct INITBLK16 -{ +struct INITBLK16 { uint16_t mode; /**< copied into csr15 */ uint16_t padr1; /**< MAC 0..15 */ uint16_t padr2; /**< MAC 16..32 */ @@ -273,160 +276,154 @@ struct INITBLK16 uint16_t ladrf2; /**< logical address filter 16..31 */ uint16_t ladrf3; /**< logical address filter 32..47 */ uint16_t ladrf4; /**< logical address filter 48..63 */ - uint32_t rdra:24; /**< address of receive descriptor ring */ - uint32_t res1:5; /**< reserved */ - uint32_t rlen:3; /**< number of receive descriptor ring entries */ - uint32_t tdra:24; /**< address of transmit descriptor ring */ - uint32_t res2:5; /**< reserved */ - uint32_t tlen:3; /**< number of transmit descriptor ring entries */ + uint32_t rdra : 24; /**< address of receive descriptor ring */ + uint32_t res1 : 5; /**< reserved */ + uint32_t rlen : 3; /**< number of receive descriptor ring entries */ + uint32_t tdra : 24; /**< address of transmit descriptor ring */ + uint32_t res2 : 5; /**< reserved */ + uint32_t tlen : 3; /**< number of transmit descriptor ring entries */ }; /** bird: I've changed the type for the bitfields. They should only be 16-bit all together. * frank: I've changed the bitfiled types to uint32_t to prevent compiler warnings. */ -struct INITBLK32 -{ - uint16_t mode; /**< copied into csr15 */ - uint16_t res1:4; /**< reserved */ - uint16_t rlen:4; /**< number of receive descriptor ring entries */ - uint16_t res2:4; /**< reserved */ - uint16_t tlen:4; /**< number of transmit descriptor ring entries */ - uint16_t padr1; /**< MAC 0..15 */ - uint16_t padr2; /**< MAC 16..31 */ - uint16_t padr3; /**< MAC 32..47 */ - uint16_t res3; /**< reserved */ - uint16_t ladrf1; /**< logical address filter 0..15 */ - uint16_t ladrf2; /**< logical address filter 16..31 */ - uint16_t ladrf3; /**< logical address filter 32..47 */ - uint16_t ladrf4; /**< logical address filter 48..63 */ - uint32_t rdra; /**< address of receive descriptor ring */ - uint32_t tdra; /**< address of transmit descriptor ring */ +struct INITBLK32 { + uint16_t mode; /**< copied into csr15 */ + uint16_t res1 : 4; /**< reserved */ + uint16_t rlen : 4; /**< number of receive descriptor ring entries */ + uint16_t res2 : 4; /**< reserved */ + uint16_t tlen : 4; /**< number of transmit descriptor ring entries */ + uint16_t padr1; /**< MAC 0..15 */ + uint16_t padr2; /**< MAC 16..31 */ + uint16_t padr3; /**< MAC 32..47 */ + uint16_t res3; /**< reserved */ + uint16_t ladrf1; /**< logical address filter 0..15 */ + uint16_t ladrf2; /**< logical address filter 16..31 */ + uint16_t ladrf3; /**< logical address filter 32..47 */ + uint16_t ladrf4; /**< logical address filter 48..63 */ + uint32_t rdra; /**< address of receive descriptor ring */ + uint32_t tdra; /**< address of transmit descriptor ring */ }; /** Transmit Message Descriptor */ -typedef struct TMD -{ +typedef struct TMD { struct { - uint32_t tbadr; /**< transmit buffer address */ + uint32_t tbadr; /**< transmit buffer address */ } tmd0; struct { - uint32_t bcnt:12; /**< buffer byte count (two's complement) */ - uint32_t ones:4; /**< must be 1111b */ - uint32_t res:7; /**< reserved */ - uint32_t bpe:1; /**< bus parity error */ - uint32_t enp:1; /**< end of packet */ - uint32_t stp:1; /**< start of packet */ - uint32_t def:1; /**< deferred */ - uint32_t one:1; /**< exactly one retry was needed to transmit a frame */ - uint32_t ltint:1; /**< suppress interrupts after successful transmission */ - uint32_t nofcs:1; /**< when set, the state of DXMTFCS is ignored and - transmitter FCS generation is activated. */ - uint32_t err:1; /**< error occurred */ - uint32_t own:1; /**< 0=owned by guest driver, 1=owned by controller */ + uint32_t bcnt : 12; /**< buffer byte count (two's complement) */ + uint32_t ones : 4; /**< must be 1111b */ + uint32_t res : 7; /**< reserved */ + uint32_t bpe : 1; /**< bus parity error */ + uint32_t enp : 1; /**< end of packet */ + uint32_t stp : 1; /**< start of packet */ + uint32_t def : 1; /**< deferred */ + uint32_t one : 1; /**< exactly one retry was needed to transmit a frame */ + uint32_t ltint : 1; /**< suppress interrupts after successful transmission */ + uint32_t nofcs : 1; /**< when set, the state of DXMTFCS is ignored and + transmitter FCS generation is activated. */ + uint32_t err : 1; /**< error occurred */ + uint32_t own : 1; /**< 0=owned by guest driver, 1=owned by controller */ } tmd1; struct { - uint32_t trc:4; /**< transmit retry count */ - uint32_t res:12; /**< reserved */ - uint32_t tdr:10; /**< ??? */ - uint32_t rtry:1; /**< retry error */ - uint32_t lcar:1; /**< loss of carrier */ - uint32_t lcol:1; /**< late collision */ - uint32_t exdef:1; /**< excessive deferral */ - uint32_t uflo:1; /**< underflow error */ - uint32_t buff:1; /**< out of buffers (ENP not found) */ + uint32_t trc : 4; /**< transmit retry count */ + uint32_t res : 12; /**< reserved */ + uint32_t tdr : 10; /**< ??? */ + uint32_t rtry : 1; /**< retry error */ + uint32_t lcar : 1; /**< loss of carrier */ + uint32_t lcol : 1; /**< late collision */ + uint32_t exdef : 1; /**< excessive deferral */ + uint32_t uflo : 1; /**< underflow error */ + uint32_t buff : 1; /**< out of buffers (ENP not found) */ } tmd2; struct { - uint32_t res; /**< reserved for user defined space */ + uint32_t res; /**< reserved for user defined space */ } tmd3; } TMD; /** Receive Message Descriptor */ -typedef struct RMD -{ +typedef struct RMD { struct { - uint32_t rbadr; /**< receive buffer address */ + uint32_t rbadr; /**< receive buffer address */ } rmd0; struct { - uint32_t bcnt:12; /**< buffer byte count (two's complement) */ - uint32_t ones:4; /**< must be 1111b */ - uint32_t res:4; /**< reserved */ - uint32_t bam:1; /**< broadcast address match */ - uint32_t lafm:1; /**< logical filter address match */ - uint32_t pam:1; /**< physical address match */ - uint32_t bpe:1; /**< bus parity error */ - uint32_t enp:1; /**< end of packet */ - uint32_t stp:1; /**< start of packet */ - uint32_t buff:1; /**< buffer error */ - uint32_t crc:1; /**< crc error on incoming frame */ - uint32_t oflo:1; /**< overflow error (lost all or part of incoming frame) */ - uint32_t fram:1; /**< frame error */ - uint32_t err:1; /**< error occurred */ - uint32_t own:1; /**< 0=owned by guest driver, 1=owned by controller */ + uint32_t bcnt : 12; /**< buffer byte count (two's complement) */ + uint32_t ones : 4; /**< must be 1111b */ + uint32_t res : 4; /**< reserved */ + uint32_t bam : 1; /**< broadcast address match */ + uint32_t lafm : 1; /**< logical filter address match */ + uint32_t pam : 1; /**< physical address match */ + uint32_t bpe : 1; /**< bus parity error */ + uint32_t enp : 1; /**< end of packet */ + uint32_t stp : 1; /**< start of packet */ + uint32_t buff : 1; /**< buffer error */ + uint32_t crc : 1; /**< crc error on incoming frame */ + uint32_t oflo : 1; /**< overflow error (lost all or part of incoming frame) */ + uint32_t fram : 1; /**< frame error */ + uint32_t err : 1; /**< error occurred */ + uint32_t own : 1; /**< 0=owned by guest driver, 1=owned by controller */ } rmd1; struct { - uint32_t mcnt:12; /**< message byte count */ - uint32_t zeros:4; /**< 0000b */ - uint32_t rpc:8; /**< receive frame tag */ - uint32_t rcc:8; /**< receive frame tag + reserved */ + uint32_t mcnt : 12; /**< message byte count */ + uint32_t zeros : 4; /**< 0000b */ + uint32_t rpc : 8; /**< receive frame tag */ + uint32_t rcc : 8; /**< receive frame tag + reserved */ } rmd2; struct { - uint32_t res; /**< reserved for user defined space */ + uint32_t res; /**< reserved for user defined space */ } rmd3; } RMD; -static bar_t pcnet_pci_bar[3]; -static uint8_t pcnet_pci_regs[PCI_REGSIZE]; +static bar_t pcnet_pci_bar[3]; +static uint8_t pcnet_pci_regs[PCI_REGSIZE]; static void pcnetAsyncTransmit(nic_t *dev); static void pcnetPollRxTx(nic_t *dev); -static void pcnetPollTimer(nic_t *dev); static void pcnetUpdateIrq(nic_t *dev); -static uint16_t pcnet_bcr_readw(nic_t *dev, uint16_t rap); -static void pcnet_bcr_writew(nic_t *dev, uint16_t rap, uint16_t val); -static void pcnet_csr_writew(nic_t *dev, uint16_t rap, uint16_t val); -static int pcnetCanReceive(nic_t *dev); - +static uint16_t pcnet_bcr_readw(nic_t *dev, uint16_t rap); +static void pcnet_bcr_writew(nic_t *dev, uint16_t rap, uint16_t val); +static void pcnet_csr_writew(nic_t *dev, uint16_t rap, uint16_t val); +static int pcnetCanReceive(nic_t *dev); #ifdef ENABLE_PCNET_LOG int pcnet_do_log = ENABLE_PCNET_LOG; static void -pcnetlog(int lvl, const char *fmt, ...) +pcnet_log(int lvl, const char *fmt, ...) { va_list ap; if (pcnet_do_log >= lvl) { - va_start(ap, fmt); - pclog_ex(fmt, ap); - va_end(ap); + va_start(ap, fmt); + pclog_ex(fmt, ap); + va_end(ap); } } #else -#define pcnetlog(lvl, fmt, ...) +# define pcnet_log(lvl, fmt, ...) #endif - static void pcnet_do_irq(nic_t *dev, int issue) { - if (dev->is_pci) { - if (issue) - pci_set_irq(dev->card, PCI_INTA); - else - pci_clear_irq(dev->card, PCI_INTA); - } else { - if (issue) - picint(1<base_irq); - else - picintc(1<base_irq); - } + if (dev->is_pci) { + if (issue) + pci_set_irq(dev->pci_slot, PCI_INTA, &dev->irq_state); + else + pci_clear_irq(dev->pci_slot, PCI_INTA, &dev->irq_state); + } else { + if (issue) + picint(1 << dev->base_irq); + else + picintc(1 << dev->base_irq); + } } /** @@ -440,7 +437,6 @@ pcnetIsLinkUp(nic_t *dev) return !dev->fLinkTempDown && dev->fLinkUp; } - /** * Load transmit message descriptor * Make sure we read the own flag first. @@ -453,47 +449,47 @@ pcnetIsLinkUp(nic_t *dev) static __inline int pcnetTmdLoad(nic_t *dev, TMD *tmd, uint32_t addr, int fRetIfNotOwn) { - uint8_t ownbyte, bytes[4] = { 0, 0, 0, 0 }; + uint8_t ownbyte; + uint8_t bytes[4] = { 0, 0, 0, 0 }; uint16_t xda[4]; uint32_t xda32[4]; if (BCR_SWSTYLE(dev) == 0) { - dma_bm_read(addr, (uint8_t *) bytes, 4, dev->transfer_size); - ownbyte = bytes[3]; + dma_bm_read(addr, (uint8_t *) bytes, 4, dev->transfer_size); + ownbyte = bytes[3]; if (!(ownbyte & 0x80) && fRetIfNotOwn) return 0; - dma_bm_read(addr, (uint8_t*)&xda[0], sizeof(xda), dev->transfer_size); - ((uint32_t *)tmd)[0] = (uint32_t)xda[0] | ((uint32_t)(xda[1] & 0x00ff) << 16); - ((uint32_t *)tmd)[1] = (uint32_t)xda[2] | ((uint32_t)(xda[1] & 0xff00) << 16); - ((uint32_t *)tmd)[2] = (uint32_t)xda[3] << 16; - ((uint32_t *)tmd)[3] = 0; + dma_bm_read(addr, (uint8_t *) &xda[0], sizeof(xda), dev->transfer_size); + ((uint32_t *) tmd)[0] = (uint32_t) xda[0] | ((uint32_t) (xda[1] & 0x00ff) << 16); + ((uint32_t *) tmd)[1] = (uint32_t) xda[2] | ((uint32_t) (xda[1] & 0xff00) << 16); + ((uint32_t *) tmd)[2] = (uint32_t) xda[3] << 16; + ((uint32_t *) tmd)[3] = 0; } else if (BCR_SWSTYLE(dev) != 3) { - dma_bm_read(addr + 4, (uint8_t *) bytes, 4, dev->transfer_size); - ownbyte = bytes[3]; + dma_bm_read(addr + 4, (uint8_t *) bytes, 4, dev->transfer_size); + ownbyte = bytes[3]; if (!(ownbyte & 0x80) && fRetIfNotOwn) return 0; - dma_bm_read(addr, (uint8_t*)tmd, 16, dev->transfer_size); + dma_bm_read(addr, (uint8_t *) tmd, 16, dev->transfer_size); } else { - dma_bm_read(addr + 4, (uint8_t *) bytes, 4, dev->transfer_size); - ownbyte = bytes[3]; + dma_bm_read(addr + 4, (uint8_t *) bytes, 4, dev->transfer_size); + ownbyte = bytes[3]; if (!(ownbyte & 0x80) && fRetIfNotOwn) return 0; - dma_bm_read(addr, (uint8_t*)&xda32[0], sizeof(xda32), dev->transfer_size); - ((uint32_t *)tmd)[0] = xda32[2]; - ((uint32_t *)tmd)[1] = xda32[1]; - ((uint32_t *)tmd)[2] = xda32[0]; - ((uint32_t *)tmd)[3] = xda32[3]; + dma_bm_read(addr, (uint8_t *) &xda32[0], sizeof(xda32), dev->transfer_size); + ((uint32_t *) tmd)[0] = xda32[2]; + ((uint32_t *) tmd)[1] = xda32[1]; + ((uint32_t *) tmd)[2] = xda32[0]; + ((uint32_t *) tmd)[3] = xda32[3]; } /* Double check the own bit; guest drivers might be buggy and lock prefixes in the recompiler are ignored by other threads. */ if (tmd->tmd1.own == 1 && !(ownbyte & 0x80)) - pcnetlog(3, "%s: pcnetTmdLoad: own bit flipped while reading!!\n", dev->name); + pcnet_log(3, "%s: pcnetTmdLoad: own bit flipped while reading!!\n", dev->name); if (!(ownbyte & 0x80)) tmd->tmd1.own = 0; return !!tmd->tmd1.own; } - /** * Store transmit message descriptor and hand it over to the host (the VM guest). * Make sure that all data are transmitted before we clear the own flag. @@ -505,37 +501,36 @@ pcnetTmdStorePassHost(nic_t *dev, TMD *tmd, uint32_t addr) uint32_t xda32[3]; if (BCR_SWSTYLE(dev) == 0) { - xda[0] = ((uint32_t *)tmd)[0] & 0xffff; - xda[1] = ((((uint32_t *)tmd)[0] >> 16) & 0xff) | ((((uint32_t *)tmd)[1]>>16) & 0xff00); - xda[2] = ((uint32_t *)tmd)[1] & 0xffff; - xda[3] = ((uint32_t *)tmd)[2] >> 16; + xda[0] = ((uint32_t *) tmd)[0] & 0xffff; + xda[1] = ((((uint32_t *) tmd)[0] >> 16) & 0xff) | ((((uint32_t *) tmd)[1] >> 16) & 0xff00); + xda[2] = ((uint32_t *) tmd)[1] & 0xffff; + xda[3] = ((uint32_t *) tmd)[2] >> 16; #if 0 xda[1] |= 0x8000; dma_bm_write(addr, (uint8_t*)&xda[0], sizeof(xda), dev->transfer_size); #endif xda[1] &= ~0x8000; - dma_bm_write(addr, (uint8_t*)&xda[0], sizeof(xda), dev->transfer_size); + dma_bm_write(addr, (uint8_t *) &xda[0], sizeof(xda), dev->transfer_size); } else if (BCR_SWSTYLE(dev) != 3) { #if 0 ((uint32_t*)tmd)[1] |= 0x80000000; dma_bm_write(addr, (uint8_t*)tmd, 12, dev->transfer_size); #endif - ((uint32_t*)tmd)[1] &= ~0x80000000; - dma_bm_write(addr, (uint8_t*)tmd, 12, dev->transfer_size); + ((uint32_t *) tmd)[1] &= ~0x80000000; + dma_bm_write(addr, (uint8_t *) tmd, 12, dev->transfer_size); } else { - xda32[0] = ((uint32_t *)tmd)[2]; - xda32[1] = ((uint32_t *)tmd)[1]; - xda32[2] = ((uint32_t *)tmd)[0]; + xda32[0] = ((uint32_t *) tmd)[2]; + xda32[1] = ((uint32_t *) tmd)[1]; + xda32[2] = ((uint32_t *) tmd)[0]; #if 0 xda32[1] |= 0x80000000; dma_bm_write(addr, (uint8_t*)&xda32[0], sizeof(xda32), dev->transfer_size); #endif xda32[1] &= ~0x80000000; - dma_bm_write(addr, (uint8_t*)&xda32[0], sizeof(xda32), dev->transfer_size); + dma_bm_write(addr, (uint8_t *) &xda32[0], sizeof(xda32), dev->transfer_size); } } - /** * Load receive message descriptor * Make sure we read the own flag first. @@ -548,48 +543,48 @@ pcnetTmdStorePassHost(nic_t *dev, TMD *tmd, uint32_t addr) static __inline int pcnetRmdLoad(nic_t *dev, RMD *rmd, uint32_t addr, int fRetIfNotOwn) { - uint8_t ownbyte, bytes[4] = { 0, 0, 0, 0 }; + uint8_t ownbyte; + uint8_t bytes[4] = { 0, 0, 0, 0 }; uint16_t rda[4]; uint32_t rda32[4]; if (BCR_SWSTYLE(dev) == 0) { dma_bm_read(addr, (uint8_t *) bytes, 4, dev->transfer_size); - ownbyte = bytes[3]; + ownbyte = bytes[3]; if (!(ownbyte & 0x80) && fRetIfNotOwn) return 0; - dma_bm_read(addr, (uint8_t*)&rda[0], sizeof(rda), dev->transfer_size); - ((uint32_t *)rmd)[0] = (uint32_t)rda[0] | ((rda[1] & 0x00ff) << 16); - ((uint32_t *)rmd)[1] = (uint32_t)rda[2] | ((rda[1] & 0xff00) << 16); - ((uint32_t *)rmd)[2] = (uint32_t)rda[3]; - ((uint32_t *)rmd)[3] = 0; + dma_bm_read(addr, (uint8_t *) &rda[0], sizeof(rda), dev->transfer_size); + ((uint32_t *) rmd)[0] = (uint32_t) rda[0] | ((rda[1] & 0x00ff) << 16); + ((uint32_t *) rmd)[1] = (uint32_t) rda[2] | ((rda[1] & 0xff00) << 16); + ((uint32_t *) rmd)[2] = (uint32_t) rda[3]; + ((uint32_t *) rmd)[3] = 0; } else if (BCR_SWSTYLE(dev) != 3) { dma_bm_read(addr + 4, (uint8_t *) bytes, 4, dev->transfer_size); - ownbyte = bytes[3]; + ownbyte = bytes[3]; if (!(ownbyte & 0x80) && fRetIfNotOwn) return 0; - dma_bm_read(addr, (uint8_t*)rmd, 16, dev->transfer_size); + dma_bm_read(addr, (uint8_t *) rmd, 16, dev->transfer_size); } else { dma_bm_read(addr + 4, (uint8_t *) bytes, 4, dev->transfer_size); - ownbyte = bytes[3]; + ownbyte = bytes[3]; if (!(ownbyte & 0x80) && fRetIfNotOwn) return 0; - dma_bm_read(addr, (uint8_t*)&rda32[0], sizeof(rda32), dev->transfer_size); - ((uint32_t *)rmd)[0] = rda32[2]; - ((uint32_t *)rmd)[1] = rda32[1]; - ((uint32_t *)rmd)[2] = rda32[0]; - ((uint32_t *)rmd)[3] = rda32[3]; + dma_bm_read(addr, (uint8_t *) &rda32[0], sizeof(rda32), dev->transfer_size); + ((uint32_t *) rmd)[0] = rda32[2]; + ((uint32_t *) rmd)[1] = rda32[1]; + ((uint32_t *) rmd)[2] = rda32[0]; + ((uint32_t *) rmd)[3] = rda32[3]; } /* Double check the own bit; guest drivers might be buggy and lock prefixes in the recompiler are ignored by other threads. */ if (rmd->rmd1.own == 1 && !(ownbyte & 0x80)) - pcnetlog(3, "%s: pcnetRmdLoad: own bit flipped while reading!!\n", dev->name); - + pcnet_log(3, "%s: pcnetRmdLoad: own bit flipped while reading!!\n", dev->name); + if (!(ownbyte & 0x80)) rmd->rmd1.own = 0; return !!rmd->rmd1.own; } - /** * Store receive message descriptor and hand it over to the host (the VM guest). * Make sure that all data are transmitted before we clear the own flag. @@ -601,52 +596,51 @@ pcnetRmdStorePassHost(nic_t *dev, RMD *rmd, uint32_t addr) uint32_t rda32[3]; if (BCR_SWSTYLE(dev) == 0) { - rda[0] = ((uint32_t *)rmd)[0] & 0xffff; - rda[1] = ((((uint32_t *)rmd)[0]>>16) & 0xff) | ((((uint32_t *)rmd)[1]>>16) & 0xff00); - rda[2] = ((uint32_t *)rmd)[1] & 0xffff; - rda[3] = ((uint32_t *)rmd)[2] & 0xffff; + rda[0] = ((uint32_t *) rmd)[0] & 0xffff; + rda[1] = ((((uint32_t *) rmd)[0] >> 16) & 0xff) | ((((uint32_t *) rmd)[1] >> 16) & 0xff00); + rda[2] = ((uint32_t *) rmd)[1] & 0xffff; + rda[3] = ((uint32_t *) rmd)[2] & 0xffff; #if 0 rda[1] |= 0x8000; dma_bm_write(addr, (uint8_t*)&rda[0], sizeof(rda), dev->transfer_size); #endif rda[1] &= ~0x8000; - dma_bm_write(addr, (uint8_t*)&rda[0], sizeof(rda), dev->transfer_size); + dma_bm_write(addr, (uint8_t *) &rda[0], sizeof(rda), dev->transfer_size); } else if (BCR_SWSTYLE(dev) != 3) { #if 0 ((uint32_t*)rmd)[1] |= 0x80000000; dma_bm_write(addr, (uint8_t*)rmd, 12, dev->transfer_size); #endif - ((uint32_t*)rmd)[1] &= ~0x80000000; - dma_bm_write(addr, (uint8_t*)rmd, 12, dev->transfer_size); + ((uint32_t *) rmd)[1] &= ~0x80000000; + dma_bm_write(addr, (uint8_t *) rmd, 12, dev->transfer_size); } else { - rda32[0] = ((uint32_t *)rmd)[2]; - rda32[1] = ((uint32_t *)rmd)[1]; - rda32[2] = ((uint32_t *)rmd)[0]; + rda32[0] = ((uint32_t *) rmd)[2]; + rda32[1] = ((uint32_t *) rmd)[1]; + rda32[2] = ((uint32_t *) rmd)[0]; #if 0 rda32[1] |= 0x80000000; dma_bm_write(addr, (uint8_t*)&rda32[0], sizeof(rda32), dev->transfer_size); #endif rda32[1] &= ~0x80000000; - dma_bm_write(addr, (uint8_t*)&rda32[0], sizeof(rda32), dev->transfer_size); + dma_bm_write(addr, (uint8_t *) &rda32[0], sizeof(rda32), dev->transfer_size); } } - /** Checks if it's a bad (as in invalid) RMD.*/ -#define IS_RMD_BAD(rmd) ((rmd).rmd1.ones != 15) +#define IS_RMD_BAD(rmd) ((rmd).rmd1.ones != 15) /** The network card is the owner of the RDTE/TDTE, actually it is this driver */ -#define CARD_IS_OWNER(desc) (((desc) & 0x8000)) +#define CARD_IS_OWNER(desc) (((desc) &0x8000)) /** The host is the owner of the RDTE/TDTE -- actually the VM guest. */ -#define HOST_IS_OWNER(desc) (!((desc) & 0x8000)) +#define HOST_IS_OWNER(desc) (!((desc) &0x8000)) #ifndef ETHER_IS_MULTICAST /* Net/Open BSD macro it seems */ -#define ETHER_IS_MULTICAST(a) ((*(uint8_t *)(a)) & 1) +# define ETHER_IS_MULTICAST(a) ((*(uint8_t *) (a)) & 1) #endif #define ETHER_ADDR_LEN ETH_ALEN -#define ETH_ALEN 6 +#define ETH_ALEN 6 #pragma pack(1) struct ether_header /** @todo Use RTNETETHERHDR */ { @@ -656,22 +650,20 @@ struct ether_header /** @todo Use RTNETETHERHDR */ }; #pragma pack() -#define CRC(crc, ch) (crc = (crc >> 8) ^ crctab[(crc ^ (ch)) & 0xff]) +#define CRC(crc, ch) (crc = (crc >> 8) ^ crctab[(crc ^ (ch)) & 0xff]) #define MULTICAST_FILTER_LEN 8 -static __inline uint32_t +static __inline uint32_t lnc_mchash(const uint8_t *ether_addr) { -#define LNC_POLYNOMIAL 0xEDB88320UL +#define LNC_POLYNOMIAL 0xEDB88320UL uint32_t crc = 0xFFFFFFFF; - int idx, bit; - uint8_t data; + int bit; + uint8_t data; - for (idx = 0; idx < ETHER_ADDR_LEN; idx++) - { - for (data = *ether_addr++, bit = 0; bit < MULTICAST_FILTER_LEN; bit++) - { + for (uint8_t idx = 0; idx < ETHER_ADDR_LEN; idx++) { + for (data = *ether_addr++, bit = 0; bit < MULTICAST_FILTER_LEN; bit++) { crc = (crc >> 1) ^ (((crc ^ data) & 1) ? LNC_POLYNOMIAL : 0); data >>= 1; } @@ -680,7 +672,7 @@ lnc_mchash(const uint8_t *ether_addr) #undef LNC_POLYNOMIAL } -#define CRC(crc, ch) (crc = (crc >> 8) ^ crctab[(crc ^ (ch)) & 0xff]) +#define CRC(crc, ch) (crc = (crc >> 8) ^ crctab[(crc ^ (ch)) & 0xff]) /* generated using the AUTODIN II polynomial * x^32 + x^26 + x^23 + x^22 + x^16 + @@ -754,48 +746,50 @@ static const uint32_t crctab[256] = 0xb40bbe37, 0xc30c8ea1, 0x5a05df1b, 0x2d02ef8d, }; - static __inline int -padr_match(nic_t *dev, const uint8_t *buf, int size) +padr_match(nic_t *dev, const uint8_t *buf, UNUSED(int size)) { - struct ether_header *hdr = (struct ether_header *)buf; - int result; - uint8_t padr[6]; + const struct ether_header *hdr = (const struct ether_header *) buf; + int result; + uint8_t padr[6]; + padr[0] = dev->aCSR[12] & 0xff; padr[1] = dev->aCSR[12] >> 8; padr[2] = dev->aCSR[13] & 0xff; padr[3] = dev->aCSR[13] >> 8; padr[4] = dev->aCSR[14] & 0xff; padr[5] = dev->aCSR[14] >> 8; - result = !CSR_DRCVPA(dev) && !memcmp(hdr->ether_dhost, padr, 6); + result = !CSR_DRCVPA(dev) && !memcmp(hdr->ether_dhost, padr, 6); + + pcnet_log(3, "%s: packet dhost=%02x:%02x:%02x:%02x:%02x:%02x, " + "padr=%02x:%02x:%02x:%02x:%02x:%02x => %d\n", + dev->name, + hdr->ether_dhost[0], hdr->ether_dhost[1], hdr->ether_dhost[2], + hdr->ether_dhost[3], hdr->ether_dhost[4], hdr->ether_dhost[5], + padr[0], padr[1], padr[2], padr[3], padr[4], padr[5], result); - pcnetlog(3, "%s: packet dhost=%02x:%02x:%02x:%02x:%02x:%02x, " - "padr=%02x:%02x:%02x:%02x:%02x:%02x => %d\n", dev->name, - hdr->ether_dhost[0],hdr->ether_dhost[1],hdr->ether_dhost[2], - hdr->ether_dhost[3],hdr->ether_dhost[4],hdr->ether_dhost[5], - padr[0],padr[1],padr[2],padr[3],padr[4],padr[5], result); - return result; } - static __inline int -padr_bcast(nic_t *dev, const uint8_t *buf, size_t size) +padr_bcast(nic_t *dev, const uint8_t *buf, UNUSED(size_t size)) { - static uint8_t aBCAST[6] = { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff }; - struct ether_header *hdr = (struct ether_header *)buf; - int result = !CSR_DRCVBC(dev) && !memcmp(hdr->ether_dhost, aBCAST, 6); - pcnetlog(3, "%s: padr_bcast result=%d\n", dev->name, result); - return result; + static uint8_t aBCAST[6] = { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff }; + const struct ether_header *hdr = (const struct ether_header *) buf; + int result = !CSR_DRCVBC(dev) && !memcmp(hdr->ether_dhost, aBCAST, 6); + + pcnet_log(3, "%s: padr_bcast result=%d\n", dev->name, result); + + return result; } - -static int -ladr_match(nic_t *dev, const uint8_t *buf, size_t size) +static int +ladr_match(nic_t *dev, const uint8_t *buf, UNUSED(size_t size)) { - struct ether_header *hdr = (struct ether_header *)buf; - if ((hdr->ether_dhost[0] & 0x01) && ((uint64_t *)&dev->aCSR[8])[0] != 0LL) { - int index; + const struct ether_header *hdr = (const struct ether_header *) buf; + + if ((hdr->ether_dhost[0] & 0x01) && ((uint64_t *) &dev->aCSR[8])[0] != 0LL) { + int index; uint8_t ladr[8]; ladr[0] = dev->aCSR[8] & 0xff; ladr[1] = dev->aCSR[8] >> 8; @@ -805,55 +799,52 @@ ladr_match(nic_t *dev, const uint8_t *buf, size_t size) ladr[5] = dev->aCSR[10] >> 8; ladr[6] = dev->aCSR[11] & 0xff; ladr[7] = dev->aCSR[11] >> 8; - index = lnc_mchash(hdr->ether_dhost) >> 26; + index = lnc_mchash(hdr->ether_dhost) >> 26; return (ladr[index >> 3] & (1 << (index & 7))); - } + } return 0; } - /** * Get the receive descriptor ring address with a given index. */ -static __inline uint32_t +static __inline uint32_t pcnetRdraAddr(nic_t *dev, int idx) { return dev->GCRDRA + ((CSR_RCVRL(dev) - idx) << dev->iLog2DescSize); } - /** * Get the transmit descriptor ring address with a given index. */ -static __inline uint32_t +static __inline uint32_t pcnetTdraAddr(nic_t *dev, int idx) { return dev->GCTDRA + ((CSR_XMTRL(dev) - idx) << dev->iLog2DescSize); } - -static void +static void pcnetSoftReset(nic_t *dev) { - pcnetlog(3, "%s: pcnetSoftReset\n", dev->name); - + pcnet_log(3, "%s: pcnetSoftReset\n", dev->name); + dev->u32Lnkst = 0x40; dev->GCRDRA = 0; dev->GCTDRA = 0; dev->u32RAP = 0; - - dev->aCSR[0] = 0x0004; - dev->aCSR[3] = 0x0000; - dev->aCSR[4] = 0x0115; - dev->aCSR[5] = 0x0000; - dev->aCSR[6] = 0x0000; - dev->aCSR[8] = 0; - dev->aCSR[9] = 0; - dev->aCSR[10] = 0; - dev->aCSR[11] = 0; - dev->aCSR[12] = le16_to_cpu(((uint16_t *)&dev->aPROM[0])[0]); - dev->aCSR[13] = le16_to_cpu(((uint16_t *)&dev->aPROM[0])[1]); - dev->aCSR[14] = le16_to_cpu(((uint16_t *)&dev->aPROM[0])[2]); + + dev->aCSR[0] = 0x0004; + dev->aCSR[3] = 0x0000; + dev->aCSR[4] = 0x0115; + dev->aCSR[5] = 0x0000; + dev->aCSR[6] = 0x0000; + dev->aCSR[8] = 0; + dev->aCSR[9] = 0; + dev->aCSR[10] = 0; + dev->aCSR[11] = 0; + dev->aCSR[12] = le16_to_cpu(((uint16_t *) &dev->aPROM[0])[0]); + dev->aCSR[13] = le16_to_cpu(((uint16_t *) &dev->aPROM[0])[1]); + dev->aCSR[14] = le16_to_cpu(((uint16_t *) &dev->aPROM[0])[2]); dev->aCSR[15] &= 0x21c4; CSR_RCVRC(dev) = 1; CSR_XMTRC(dev) = 1; @@ -862,21 +853,24 @@ pcnetSoftReset(nic_t *dev) dev->aCSR[80] = 0x1410; switch (dev->board) { - case DEV_AM79C970A: - dev->aCSR[88] = 0x1003; - dev->aCSR[89] = 0x0262; - break; - case DEV_AM79C973: - dev->aCSR[88] = 0x5003; - dev->aCSR[89] = 0x0262; - break; - case DEV_AM79C960: - case DEV_AM79C960_EB: - case DEV_AM79C960_VLB: - case DEV_AM79C961: - dev->aCSR[88] = 0x3003; - dev->aCSR[89] = 0x0262; - break; + case DEV_AM79C970A: + dev->aCSR[88] = 0x1003; + dev->aCSR[89] = 0x0262; + break; + case DEV_AM79C973: + dev->aCSR[88] = 0x5003; + dev->aCSR[89] = 0x0262; + break; + case DEV_AM79C960: + case DEV_AM79C960_EB: + case DEV_AM79C960_VLB: + case DEV_AM79C961: + dev->aCSR[88] = 0x3003; + dev->aCSR[89] = 0x0262; + break; + + default: + break; } dev->aCSR[94] = 0x0000; @@ -888,102 +882,98 @@ pcnetSoftReset(nic_t *dev) dev->aCSR[124] = 0x0000; } - static void pcnetUpdateIrq(nic_t *dev) { - int iISR = 0; - uint16_t csr0; + int iISR = 0; + uint16_t csr0; csr0 = dev->aCSR[0]; - + csr0 &= ~0x0080; /* clear INTR */ - if (((csr0 & ~dev->aCSR[3]) & 0x5f00) || - (((dev->aCSR[4]>>1) & ~dev->aCSR[4]) & 0x0115) || - (((dev->aCSR[5]>>1) & dev->aCSR[5]) & 0x0048)) { - iISR = !!(csr0 & 0x0040); /* CSR_INEA */ - csr0 |= 0x0080; /* set INTR */ + if (((csr0 & ~dev->aCSR[3]) & 0x5f00) || (((dev->aCSR[4] >> 1) & ~dev->aCSR[4]) & 0x0115) || (((dev->aCSR[5] >> 1) & dev->aCSR[5]) & 0x0048)) { + iISR = !!(csr0 & 0x0040); /* CSR_INEA */ + csr0 |= 0x0080; /* set INTR */ } - + if (dev->aCSR[4] & 0x0080) { /* UINTCMD */ - dev->aCSR[4] &= ~0x0080; /* clear UINTCMD */ - dev->aCSR[4] |= 0x0040; /* set UINT */ - pcnetlog(2, "%s: user int\n", dev->name); + dev->aCSR[4] &= ~0x0080; /* clear UINTCMD */ + dev->aCSR[4] |= 0x0040; /* set UINT */ + pcnet_log(2, "%s: user int\n", dev->name); } if (dev->aCSR[4] & csr0 & 0x0040 /* CSR_INEA */) { - csr0 |= 0x0080; /* set INTR */ - iISR = 1; + csr0 |= 0x0080; /* set INTR */ + iISR = 1; } - - if (((dev->aCSR[5]>>1) & dev->aCSR[5]) & 0x0500) { - iISR = 1; - csr0 |= 0x0080; /* set INTR */ + + if (((dev->aCSR[5] >> 1) & dev->aCSR[5]) & 0x0500) { + iISR = 1; + csr0 |= 0x0080; /* set INTR */ } - + if ((dev->aCSR[7] & 0x0c00) == 0x0c00) /* STINT + STINTE */ - iISR = 1; - + iISR = 1; + dev->aCSR[0] = csr0; - - pcnetlog(2, "%s: pcnetUpdateIrq: iISR=%d\n", dev->name, iISR); - + + pcnet_log(2, "%s: pcnetUpdateIrq: iISR=%d\n", dev->name, iISR); + pcnet_do_irq(dev, iISR); dev->iISR = iISR; } - -static void +static void pcnetInit(nic_t *dev) { - int i; - pcnetlog(3, "%s: pcnetInit: init_addr=%#010x\n", dev->name, PHYSADDR(dev, CSR_IADR(dev))); + pcnet_log(3, "%s: pcnetInit: init_addr=%#010x\n", dev->name, PHYSADDR(dev, CSR_IADR(dev))); /** @todo Documentation says that RCVRL and XMTRL are stored as two's complement! * Software is allowed to write these registers directly. */ -#define PCNET_INIT() do { \ - dma_bm_read(PHYSADDR(dev, CSR_IADR(dev)), \ - (uint8_t *)&initblk, sizeof(initblk), dev->transfer_size); \ - dev->aCSR[15] = le16_to_cpu(initblk.mode); \ - CSR_RCVRL(dev) = (initblk.rlen < 9) ? (1 << initblk.rlen) : 512; \ - CSR_XMTRL(dev) = (initblk.tlen < 9) ? (1 << initblk.tlen) : 512; \ - dev->aCSR[ 6] = (initblk.tlen << 12) | (initblk.rlen << 8); \ - dev->aCSR[ 8] = le16_to_cpu(initblk.ladrf1); \ - dev->aCSR[ 9] = le16_to_cpu(initblk.ladrf2); \ - dev->aCSR[10] = le16_to_cpu(initblk.ladrf3); \ - dev->aCSR[11] = le16_to_cpu(initblk.ladrf4); \ - dev->aCSR[12] = le16_to_cpu(initblk.padr1); \ - dev->aCSR[13] = le16_to_cpu(initblk.padr2); \ - dev->aCSR[14] = le16_to_cpu(initblk.padr3); \ - dev->GCRDRA = PHYSADDR(dev, initblk.rdra); \ - dev->GCTDRA = PHYSADDR(dev, initblk.tdra); \ -} while (0) +#define PCNET_INIT() \ + do { \ + dma_bm_read(PHYSADDR(dev, CSR_IADR(dev)), \ + (uint8_t *) &initblk, sizeof(initblk), dev->transfer_size); \ + dev->aCSR[15] = le16_to_cpu(initblk.mode); \ + CSR_RCVRL(dev) = (initblk.rlen < 9) ? (1 << initblk.rlen) : 512; \ + CSR_XMTRL(dev) = (initblk.tlen < 9) ? (1 << initblk.tlen) : 512; \ + dev->aCSR[6] = (initblk.tlen << 12) | (initblk.rlen << 8); \ + dev->aCSR[8] = le16_to_cpu(initblk.ladrf1); \ + dev->aCSR[9] = le16_to_cpu(initblk.ladrf2); \ + dev->aCSR[10] = le16_to_cpu(initblk.ladrf3); \ + dev->aCSR[11] = le16_to_cpu(initblk.ladrf4); \ + dev->aCSR[12] = le16_to_cpu(initblk.padr1); \ + dev->aCSR[13] = le16_to_cpu(initblk.padr2); \ + dev->aCSR[14] = le16_to_cpu(initblk.padr3); \ + dev->GCRDRA = PHYSADDR(dev, initblk.rdra); \ + dev->GCTDRA = PHYSADDR(dev, initblk.tdra); \ + } while (0) if (BCR_SSIZE32(dev)) { struct INITBLK32 initblk; dev->GCUpperPhys = 0; PCNET_INIT(); - pcnetlog(3, "%s: initblk.rlen=%#04x, initblk.tlen=%#04x\n", - dev->name, initblk.rlen, initblk.tlen); + pcnet_log(3, "%s: initblk.rlen=%#04x, initblk.tlen=%#04x\n", + dev->name, initblk.rlen, initblk.tlen); } else { struct INITBLK16 initblk; - dev->GCUpperPhys = (0xff00 & (uint32_t)dev->aCSR[2]) << 16; + dev->GCUpperPhys = (0xff00 & (uint32_t) dev->aCSR[2]) << 16; PCNET_INIT(); - pcnetlog(3, "%s: initblk.rlen=%#04x, initblk.tlen=%#04x\n", - dev->name, initblk.rlen, initblk.tlen); + pcnet_log(3, "%s: initblk.rlen=%#04x, initblk.tlen=%#04x\n", + dev->name, initblk.rlen, initblk.tlen); } #undef PCNET_INIT size_t cbRxBuffers = 0; - for (i = CSR_RCVRL(dev); i >= 1; i--) { - RMD rmd; + for (int i = CSR_RCVRL(dev); i >= 1; i--) { + RMD rmd; uint32_t rdaddr = PHYSADDR(dev, pcnetRdraAddr(dev, i)); /* At this time it is not guaranteed that the buffers are already initialized. */ if (pcnetRmdLoad(dev, &rmd, rdaddr, 0)) { - uint32_t cbBuf = 4096U-rmd.rmd1.bcnt; + uint32_t cbBuf = 4096U - rmd.rmd1.bcnt; cbRxBuffers += cbBuf; } } @@ -996,7 +986,7 @@ pcnetInit(nic_t *dev) * usually 1536 bytes and should therefore not run into condition. If they are still * short in RX buffers we notify this condition. */ - dev->fSignalRxMiss = (cbRxBuffers == 0 || cbRxBuffers >= 32*1024); + dev->fSignalRxMiss = (cbRxBuffers == 0 || cbRxBuffers >= 32 * 1024); CSR_RCVRC(dev) = CSR_RCVRL(dev); CSR_XMTRC(dev) = CSR_XMTRL(dev); @@ -1005,64 +995,61 @@ pcnetInit(nic_t *dev) CSR_CRST(dev) = CSR_CRBC(dev) = CSR_NRST(dev) = CSR_NRBC(dev) = 0; CSR_CXST(dev) = CSR_CXBC(dev) = CSR_NXST(dev) = CSR_NXBC(dev) = 0; - pcnetlog(1, "%s: Init: SWSTYLE=%d GCRDRA=%#010x[%d] GCTDRA=%#010x[%d]%s\n", - dev->name, BCR_SWSTYLE(dev), - dev->GCRDRA, CSR_RCVRL(dev), dev->GCTDRA, CSR_XMTRL(dev), - !dev->fSignalRxMiss ? " (CSR0_MISS disabled)" : ""); + pcnet_log(1, "%s: Init: SWSTYLE=%d GCRDRA=%#010x[%d] GCTDRA=%#010x[%d]%s\n", + dev->name, BCR_SWSTYLE(dev), + dev->GCRDRA, CSR_RCVRL(dev), dev->GCTDRA, CSR_XMTRL(dev), + !dev->fSignalRxMiss ? " (CSR0_MISS disabled)" : ""); if (dev->GCRDRA & (dev->iLog2DescSize - 1)) - pcnetlog(1, "%s: Warning: Misaligned RDRA\n", dev->name); + pcnet_log(1, "%s: Warning: Misaligned RDRA\n", dev->name); if (dev->GCTDRA & (dev->iLog2DescSize - 1)) - pcnetlog(1, "%s: Warning: Misaligned TDRA\n", dev->name); + pcnet_log(1, "%s: Warning: Misaligned TDRA\n", dev->name); - dev->aCSR[0] |= 0x0101; /* Initialization done */ - dev->aCSR[0] &= ~0x0004; /* clear STOP bit */ + dev->aCSR[0] |= 0x0101; /* Initialization done */ + dev->aCSR[0] &= ~0x0004; /* clear STOP bit */ } - /** * Start RX/TX operation. */ -static void +static void pcnetStart(nic_t *dev) { - pcnetlog(3, "%s: pcnetStart: Poll timer\n", dev->name); + pcnet_log(3, "%s: pcnetStart: Poll timer\n", dev->name); /* Reset any cached RX/TX descriptor state. */ CSR_CRDA(dev) = CSR_CRBA(dev) = CSR_NRDA(dev) = CSR_NRBA(dev) = 0; CSR_CRBC(dev) = CSR_NRBC(dev) = CSR_CRST(dev) = 0; if (!CSR_DTX(dev)) - dev->aCSR[0] |= 0x0010; /* set TXON */ + dev->aCSR[0] |= 0x0010; /* set TXON */ if (!CSR_DRX(dev)) - dev->aCSR[0] |= 0x0020; /* set RXON */ - dev->aCSR[0] &= ~0x0004; /* clear STOP bit */ - dev->aCSR[0] |= 0x0002; /* STRT */ - pcnetPollTimer(dev); + dev->aCSR[0] |= 0x0020; /* set RXON */ + dev->aCSR[0] &= ~0x0004; /* clear STOP bit */ + dev->aCSR[0] |= 0x0002; /* STRT */ + timer_set_delay_u64(&dev->timer, 2000 * TIMER_USEC); } - /** * Stop RX/TX operation. */ -static void +static void pcnetStop(nic_t *dev) { - pcnetlog(3, "%s: pcnetStop: Poll timer\n", dev->name); + pcnet_log(3, "%s: pcnetStop: Poll timer\n", dev->name); dev->aCSR[0] = 0x0004; dev->aCSR[4] &= ~0x02c2; dev->aCSR[5] &= ~0x0011; - pcnetPollTimer(dev); + timer_disable(&dev->timer); } - /** * Poll Receive Descriptor Table Entry and cache the results in the appropriate registers. * Note: Once a descriptor belongs to the network card (this driver), it cannot be changed * by the host (the guest driver) anymore. Well, it could but the results are undefined by * definition. */ -static void +static void pcnetRdtePoll(nic_t *dev) { /* assume lack of a next receive descriptor */ @@ -1072,57 +1059,57 @@ pcnetRdtePoll(nic_t *dev) /* * The current receive message descriptor. */ - RMD rmd; - int i = CSR_RCVRC(dev); - uint32_t addr; + RMD rmd; + int i = CSR_RCVRC(dev); + uint32_t addr; if (i < 1) i = CSR_RCVRL(dev); - addr = pcnetRdraAddr(dev, i); - CSR_CRDA(dev) = CSR_CRBA(dev) = 0; - CSR_CRBC(dev) = CSR_CRST(dev) = 0; - if (!pcnetRmdLoad(dev, &rmd, PHYSADDR(dev, addr), 1)) - return; - if (!IS_RMD_BAD(rmd)) { - CSR_CRDA(dev) = addr; /* Receive Descriptor Address */ - CSR_CRBA(dev) = rmd.rmd0.rbadr; /* Receive Buffer Address */ - CSR_CRBC(dev) = rmd.rmd1.bcnt; /* Receive Byte Count */ - CSR_CRST(dev) = ((uint32_t *)&rmd)[1] >> 16; /* Receive Status */ - } else { - /* This is not problematic since we don't own the descriptor - * We actually do own it, otherwise pcnetRmdLoad would have returned false. - * Don't flood the release log with errors. - */ - if (++dev->uCntBadRMD < 50) - pcnetlog(1, "%s: BAD RMD ENTRIES AT %#010x (i=%d)\n", - dev->name, addr, i); - return; - } - - /* - * The next descriptor. - */ - if (--i < 1) - i = CSR_RCVRL(dev); - addr = pcnetRdraAddr(dev, i); - CSR_NRDA(dev) = CSR_NRBA(dev) = 0; - CSR_NRBC(dev) = 0; + addr = pcnetRdraAddr(dev, i); + CSR_CRDA(dev) = CSR_CRBA(dev) = 0; + CSR_CRBC(dev) = CSR_CRST(dev) = 0; if (!pcnetRmdLoad(dev, &rmd, PHYSADDR(dev, addr), 1)) return; if (!IS_RMD_BAD(rmd)) { - CSR_NRDA(dev) = addr; /* Receive Descriptor Address */ - CSR_NRBA(dev) = rmd.rmd0.rbadr; /* Receive Buffer Address */ - CSR_NRBC(dev) = rmd.rmd1.bcnt; /* Receive Byte Count */ - CSR_NRST(dev) = ((uint32_t *)&rmd)[1] >> 16; /* Receive Status */ + CSR_CRDA(dev) = addr; /* Receive Descriptor Address */ + CSR_CRBA(dev) = rmd.rmd0.rbadr; /* Receive Buffer Address */ + CSR_CRBC(dev) = rmd.rmd1.bcnt; /* Receive Byte Count */ + CSR_CRST(dev) = ((uint32_t *) &rmd)[1] >> 16; /* Receive Status */ } else { /* This is not problematic since we don't own the descriptor * We actually do own it, otherwise pcnetRmdLoad would have returned false. * Don't flood the release log with errors. */ if (++dev->uCntBadRMD < 50) - pcnetlog(1, "%s: BAD RMD ENTRIES + AT %#010x (i=%d)\n", - dev->name, addr, i); + pcnet_log(1, "%s: BAD RMD ENTRIES AT %#010x (i=%d)\n", + dev->name, addr, i); + return; + } + + /* + * The next descriptor. + */ + if (--i < 1) + i = CSR_RCVRL(dev); + addr = pcnetRdraAddr(dev, i); + CSR_NRDA(dev) = CSR_NRBA(dev) = 0; + CSR_NRBC(dev) = 0; + if (!pcnetRmdLoad(dev, &rmd, PHYSADDR(dev, addr), 1)) + return; + if (!IS_RMD_BAD(rmd)) { + CSR_NRDA(dev) = addr; /* Receive Descriptor Address */ + CSR_NRBA(dev) = rmd.rmd0.rbadr; /* Receive Buffer Address */ + CSR_NRBC(dev) = rmd.rmd1.bcnt; /* Receive Byte Count */ + CSR_NRST(dev) = ((uint32_t *) &rmd)[1] >> 16; /* Receive Status */ + } else { + /* This is not problematic since we don't own the descriptor + * We actually do own it, otherwise pcnetRmdLoad would have returned false. + * Don't flood the release log with errors. + */ + if (++dev->uCntBadRMD < 50) + pcnet_log(1, "%s: BAD RMD ENTRIES + AT %#010x (i=%d)\n", + dev->name, addr, i); return; } @@ -1135,12 +1122,11 @@ pcnetRdtePoll(nic_t *dev) } } - /** * Poll Transmit Descriptor Table Entry * @return true if transmit descriptors available */ -static int +static int pcnetTdtePoll(nic_t *dev, TMD *tmd) { if (dev->GCTDRA) { @@ -1150,8 +1136,8 @@ pcnetTdtePoll(nic_t *dev, TMD *tmd) return 0; if (tmd->tmd1.ones != 15) { - pcnetlog(1, "%s: BAD TMD XDA=%#010x\n", - dev->name, PHYSADDR(dev, cxda)); + pcnet_log(1, "%s: BAD TMD XDA=%#010x\n", + dev->name, PHYSADDR(dev, cxda)); return 0; } @@ -1163,7 +1149,7 @@ pcnetTdtePoll(nic_t *dev, TMD *tmd) /* set current transmit descriptor. */ CSR_CXDA(dev) = cxda; CSR_CXBC(dev) = tmd->tmd1.bcnt; - CSR_CXST(dev) = ((uint32_t *)tmd)[1] >> 16; + CSR_CXST(dev) = ((uint32_t *) tmd)[1] >> 16; return CARD_IS_OWNER(CSR_CXST(dev)); } else { /** @todo consistency with previous receive descriptor */ @@ -1173,21 +1159,19 @@ pcnetTdtePoll(nic_t *dev, TMD *tmd) } } - /** * Poll Transmit Descriptor Table Entry * @return true if transmit descriptors available */ -static int +static int pcnetCalcPacketLen(nic_t *dev, int cb) { - TMD tmd; - int cbPacket = cb; - uint32_t iDesc = CSR_XMTRC(dev); + TMD tmd; + int cbPacket = cb; + uint32_t iDesc = CSR_XMTRC(dev); uint32_t iFirstDesc = iDesc; - do - { + do { /* Advance the ring counter */ if (iDesc < 2) iDesc = CSR_XMTRL(dev); @@ -1204,93 +1188,100 @@ pcnetCalcPacketLen(nic_t *dev, int cb) * No need to count further since this packet won't be sent anyway * due to underflow. */ - pcnetlog(3, "%s: pcnetCalcPacketLen: underflow, return %u\n", dev->name, cbPacket); + pcnet_log(3, "%s: pcnetCalcPacketLen: underflow, return %u\n", dev->name, cbPacket); return cbPacket; } if (tmd.tmd1.ones != 15) { - pcnetlog(1, "%s: BAD TMD XDA=%#010x\n", - dev->name, PHYSADDR(dev, addrDesc)); - pcnetlog(3, "%s: pcnetCalcPacketLen: bad TMD, return %u\n", dev->name, cbPacket); + pcnet_log(1, "%s: BAD TMD XDA=%#010x\n", + dev->name, PHYSADDR(dev, addrDesc)); + pcnet_log(3, "%s: pcnetCalcPacketLen: bad TMD, return %u\n", dev->name, cbPacket); return cbPacket; } - pcnetlog(3, "%s: pcnetCalcPacketLen: got valid TMD, cb=%u\n", dev->name, 4096 - tmd.tmd1.bcnt); + pcnet_log(3, "%s: pcnetCalcPacketLen: got valid TMD, cb=%u\n", dev->name, 4096 - tmd.tmd1.bcnt); cbPacket += 4096 - tmd.tmd1.bcnt; } while (!tmd.tmd1.enp); - pcnetlog(3, "#%d pcnetCalcPacketLen: return %u\n", dev->name, cbPacket); + pcnet_log(3, "#%d pcnetCalcPacketLen: return %u\n", dev->name, cbPacket); return cbPacket; } - /** * Write data into guest receive buffers. */ static int pcnetReceiveNoSync(void *priv, uint8_t *buf, int size) { - nic_t *dev = (nic_t *)priv; - int is_padr = 0, is_bcast = 0, is_ladr = 0; + nic_t *dev = (nic_t *) priv; + int is_padr = 0; + int is_bcast = 0; + int is_ladr = 0; uint32_t iRxDesc; - int cbPacket; - uint8_t buf1[60]; + int cbPacket; + uint8_t buf1[60]; + RMD rmd = { 0 }; if (CSR_DRX(dev) || CSR_STOP(dev) || CSR_SPND(dev) || !size) - return 0; + return 0; /* if too small buffer, then expand it */ if (size < 60) { memcpy(buf1, buf, size); memset(buf1 + size, 0, 60 - size); - buf = buf1; + buf = buf1; size = 60; } - + /* * Drop packets if the cable is not connected */ if (!pcnetIsLinkUp(dev)) - return 0; + return 0; - pcnetlog(1, "%s: pcnetReceiveNoSync: RX %x:%x:%x:%x:%x:%x > %x:%x:%x:%x:%x:%x len %d\n", dev->name, - buf[6], buf[7], buf[8], buf[9], buf[10], buf[11], - buf[0], buf[1], buf[2], buf[3], buf[4], buf[5], - size); + dev->fMaybeOutOfSpace = !pcnetCanReceive(dev); + if (dev->fMaybeOutOfSpace) + return 0; + + pcnet_log(1, "%s: pcnetReceiveNoSync: RX %x:%x:%x:%x:%x:%x > %x:%x:%x:%x:%x:%x len %d\n", dev->name, + buf[6], buf[7], buf[8], buf[9], buf[10], buf[11], + buf[0], buf[1], buf[2], buf[3], buf[4], buf[5], + size); /* * Perform address matching. */ if (CSR_PROM(dev) - || (is_padr = padr_match(dev, buf, size)) + || (is_padr = padr_match(dev, buf, size)) || (is_bcast = padr_bcast(dev, buf, size)) - || (is_ladr = ladr_match(dev, buf, size))) { + || (is_ladr = ladr_match(dev, buf, size))) { - if (HOST_IS_OWNER(CSR_CRST(dev))) - pcnetRdtePoll(dev); + if (HOST_IS_OWNER(CSR_CRST(dev))) + pcnetRdtePoll(dev); if (HOST_IS_OWNER(CSR_CRST(dev))) { /* Not owned by controller. This should not be possible as - * we already called pcnetCanReceive(). */ - const unsigned cb = 1 << dev->iLog2DescSize; - uint32_t GCPhys = dev->GCRDRA; - iRxDesc = CSR_RCVRL(dev); + * we already called pcnetCanReceive(). */ + const unsigned cb = 1 << dev->iLog2DescSize; + uint32_t GCPhys = dev->GCRDRA; + iRxDesc = CSR_RCVRL(dev); while (iRxDesc-- > 0) { - RMD rmd; pcnetRmdLoad(dev, &rmd, PHYSADDR(dev, GCPhys), 0); GCPhys += cb; } dev->aCSR[0] |= 0x1000; /* Set MISS flag */ - CSR_MISSC(dev)++; - pcnetlog(2, "%s: pcnetReceiveNoSync: packet missed\n", dev->name); + CSR_MISSC(dev) + ++; + pcnet_log(2, "%s: pcnetReceiveNoSync: packet missed\n", dev->name); } else { - RTNETETHERHDR *pEth = (RTNETETHERHDR *)buf; - int fStrip = 0; - size_t len_802_3; - uint8_t *src = &dev->abRecvBuf[8]; - uint32_t crda = CSR_CRDA(dev); - uint32_t next_crda; - RMD rmd, next_rmd; - + const RTNETETHERHDR *pEth = (RTNETETHERHDR *) buf; + int fStrip = 0; + size_t len_802_3; + uint8_t *src = &dev->abRecvBuf[8]; + uint32_t crda = CSR_CRDA(dev); + uint32_t next_crda; + RMD rmd; + RMD next_rmd; + /* * Ethernet framing considers these two octets to be * payload type; 802.3 framing considers them to be @@ -1300,40 +1291,40 @@ pcnetReceiveNoSync(void *priv, uint8_t *buf, int size) * * NB: CSR_ASTRP_RCV bit affects only 802.3 frames! */ - len_802_3 = cpu_to_be16(pEth->EtherType); + len_802_3 = cpu_to_be16(pEth->EtherType); if (len_802_3 < 46 && CSR_ASTRP_RCV(dev)) { - size = MIN(sizeof(RTNETETHERHDR) + len_802_3, size); + size = MIN(sizeof(RTNETETHERHDR) + len_802_3, size); fStrip = 1; - } + } - memcpy(src, buf, size); + memcpy(src, buf, size); if (!fStrip) { /* In loopback mode, Runt Packed Accept is always enabled internally; * don't do any padding because guest may be looping back very short packets. */ - if (!CSR_LOOP(dev)) - while (size < 60) - src[size++] = 0; - - uint32_t fcs = UINT32_MAX; - uint8_t *p = src; + if (!CSR_LOOP(dev)) + while (size < 60) + src[size++] = 0; - while (p != &src[size]) - CRC(fcs, *p++); + uint32_t fcs = UINT32_MAX; + const uint8_t *p = src; - /* FCS at the end of the packet */ - ((uint32_t *)&src[size])[0] = htonl(fcs); - size += 4; - } + while (p != &src[size]) + CRC(fcs, *p++); - cbPacket = (int)size; + /* FCS at the end of the packet */ + ((uint32_t *) &src[size])[0] = htonl(fcs); + size += 4; + } + + cbPacket = size; pcnetRmdLoad(dev, &rmd, PHYSADDR(dev, crda), 0); /* if (!CSR_LAPPEN(dev)) */ - rmd.rmd1.stp = 1; + rmd.rmd1.stp = 1; - size_t cbBuf = MIN(4096 - rmd.rmd1.bcnt, size); + size_t cbBuf = MIN(4096 - rmd.rmd1.bcnt, size); uint32_t rbadr = PHYSADDR(dev, rmd.rmd0.rbadr); /* save the old value to check if it was changed as long as we didn't @@ -1351,12 +1342,12 @@ pcnetReceiveNoSync(void *priv, uint8_t *buf, int size) */ dma_bm_write(rbadr, src, cbBuf, dev->transfer_size); - + /* RX disabled in the meantime? If so, abort RX. */ if (CSR_DRX(dev) || CSR_STOP(dev) || CSR_SPND(dev)) { - pcnetlog(3, "%s: RX disabled 1\n", dev->name); + pcnet_log(3, "%s: RX disabled 1\n", dev->name); return 0; - } + } /* Was the register modified in the meantime? If so, don't touch the * register but still update the RX descriptor. */ @@ -1387,7 +1378,7 @@ pcnetReceiveNoSync(void *priv, uint8_t *buf, int size) crda = next_crda; rmd = next_rmd; - cbBuf = MIN(4096 - (size_t)rmd.rmd1.bcnt, size); + cbBuf = MIN(4096 - (size_t) rmd.rmd1.bcnt, size); uint32_t rbadr2 = PHYSADDR(dev, rmd.rmd0.rbadr); /* We have to leave the critical section here or we risk deadlocking @@ -1397,9 +1388,9 @@ pcnetReceiveNoSync(void *priv, uint8_t *buf, int size) /* RX disabled in the meantime? If so, abort RX. */ if (CSR_DRX(dev) || CSR_STOP(dev) || CSR_SPND(dev)) { - pcnetlog(3, "%s: RX disabled 2\n", dev->name); + pcnet_log(3, "%s: RX disabled 2\n", dev->name); return 0; - } + } /* Was the register modified in the meantime? If so, don't touch the * register but still update the RX descriptor. */ @@ -1409,21 +1400,21 @@ pcnetReceiveNoSync(void *priv, uint8_t *buf, int size) CSR_RCVRC(dev) = iRxDesc; } else { iRxDesc = CSR_RCVRC(dev); - } + } src += cbBuf; size -= cbBuf; } if (size == 0) { - rmd.rmd1.enp = 1; - rmd.rmd1.pam = !CSR_PROM(dev) && is_padr; - rmd.rmd1.lafm = !CSR_PROM(dev) && is_ladr; - rmd.rmd1.bam = !CSR_PROM(dev) && is_bcast; - rmd.rmd2.mcnt = cbPacket; + rmd.rmd1.enp = 1; + rmd.rmd1.pam = !CSR_PROM(dev) && is_padr; + rmd.rmd1.lafm = !CSR_PROM(dev) && is_ladr; + rmd.rmd1.bam = !CSR_PROM(dev) && is_bcast; + rmd.rmd2.mcnt = cbPacket; rmd.rmd2.zeros = 0; } else { - pcnetlog(1, "%s: Overflow by %ubytes\n", dev->name, size); + pcnet_log(1, "%s: Overflow by %ubytes\n", dev->name, size); rmd.rmd1.oflo = 1; rmd.rmd1.buff = 1; rmd.rmd1.err = 1; @@ -1433,12 +1424,12 @@ pcnetReceiveNoSync(void *priv, uint8_t *buf, int size) pcnetRmdStorePassHost(dev, &rmd, PHYSADDR(dev, crda)); dev->aCSR[0] |= 0x0400; - pcnetlog(1, "%s: RINT set, RCVRC=%d CRDA=%#010x\n", dev->name, - CSR_RCVRC(dev), PHYSADDR(dev, CSR_CRDA(dev))); - + pcnet_log(1, "%s: RINT set, RCVRC=%d CRDA=%#010x\n", dev->name, + CSR_RCVRC(dev), PHYSADDR(dev, CSR_CRDA(dev))); + /* guest driver is owner: force repoll of current and next RDTEs */ CSR_CRST(dev) = 0; - } + } } pcnetUpdateIrq(dev); @@ -1474,7 +1465,7 @@ pcnetXmitFailTMDGeneric(nic_t *dev, TMD *pTmd) * * @threads TX or EMT. */ -static void +static void pcnetAsyncTransmit(nic_t *dev) { /* @@ -1489,20 +1480,19 @@ pcnetAsyncTransmit(nic_t *dev) * Iterate the transmit descriptors. */ unsigned cFlushIrq = 0; - int cMax = 32; + int cMax = 32; do { TMD tmd; if (!pcnetTdtePoll(dev, &tmd)) break; /* Don't continue sending packets when the link is down. */ - if ((!pcnetIsLinkUp(dev) - && dev->cLinkDownReported > PCNET_MAX_LINKDOWN_REPORTED) - ) + if (!pcnetIsLinkUp(dev) + && dev->cLinkDownReported > PCNET_MAX_LINKDOWN_REPORTED) break; - pcnetlog(3, "%s: TMDLOAD %#010x\n", dev->name, PHYSADDR(dev, CSR_CXDA(dev))); - + pcnet_log(3, "%s: TMDLOAD %#010x\n", dev->name, PHYSADDR(dev, CSR_CXDA(dev))); + int fLoopback = CSR_LOOP(dev); /* @@ -1510,62 +1500,62 @@ pcnetAsyncTransmit(nic_t *dev) */ if (tmd.tmd1.stp && tmd.tmd1.enp) { const int cb = 4096 - tmd.tmd1.bcnt; - pcnetlog("%s: pcnetAsyncTransmit: stp&enp: cb=%d xmtrc=%#x\n", dev->name, cb, CSR_XMTRC(dev)); + pcnet_log(3, "%s: pcnetAsyncTransmit: stp&enp: cb=%d xmtrc=%#x\n", dev->name, cb, CSR_XMTRC(dev)); - if ((pcnetIsLinkUp(dev) || fLoopback)) { - - /* From the manual: ``A zero length buffer is acceptable as - * long as it is not the last buffer in a chain (STP = 0 and - * ENP = 1).'' That means that the first buffer might have a - * zero length if it is not the last one in the chain. */ - if (cb <= MAX_FRAME) { - dev->xmit_pos = cb; - dma_bm_read(PHYSADDR(dev, tmd.tmd0.tbadr), dev->abLoopBuf, cb, dev->transfer_size); + if (pcnetIsLinkUp(dev) || fLoopback) { - if (fLoopback) { - if (HOST_IS_OWNER(CSR_CRST(dev))) - pcnetRdtePoll(dev); + /* From the manual: ``A zero length buffer is acceptable as + * long as it is not the last buffer in a chain (STP = 0 and + * ENP = 1).'' That means that the first buffer might have a + * zero length if it is not the last one in the chain. */ + if (cb <= MAX_FRAME) { + dev->xmit_pos = cb; + dma_bm_read(PHYSADDR(dev, tmd.tmd0.tbadr), dev->abLoopBuf, cb, dev->transfer_size); - pcnetReceiveNoSync(dev, dev->abLoopBuf, dev->xmit_pos); - } else { - pcnetlog(3, "%s: pcnetAsyncTransmit: transmit loopbuf stp and enp, xmit pos = %d\n", dev->name, dev->xmit_pos); - network_tx(dev->abLoopBuf, dev->xmit_pos); - } - } else if (cb == 4096) { - /* The Windows NT4 pcnet driver sometimes marks the first - * unused descriptor as owned by us. Ignore that (by - * passing it back). Do not update the ring counter in this - * case (otherwise that driver becomes even more confused, - * which causes transmit to stall for about 10 seconds). - * This is just a workaround, not a final solution. - */ - /* r=frank: IMHO this is the correct implementation. The - * manual says: ``If the OWN bit is set and the buffer - * length is 0, the OWN bit will be cleared. In the C-LANCE - * the buffer length of 0 is interpreted as a 4096-byte - * buffer.'' - */ - /* r=michaln: Perhaps not quite right. The C-LANCE (Am79C90) - * datasheet explains that the old LANCE (Am7990) ignored - * the top four bits next to BCNT and a count of 0 was - * interpreted as 4096. In the C-LANCE, that is still the - * case if the top bits are all ones. If all 16 bits are - * zero, the C-LANCE interprets it as zero-length transmit - * buffer. It's not entirely clear if the later models - * (PCnet-ISA, PCnet-PCI) behave like the C-LANCE or not. - * It is possible that the actual behavior of the C-LANCE - * and later hardware is that the buffer lengths are *16-bit* - * two's complement numbers between 0 and 4096. AMD's drivers - * in fact generally treat the length as a 16-bit quantity. */ - pcnetlog(1, "%s: pcnetAsyncTransmit: illegal 4kb frame -> ignoring\n", dev->name); - pcnetTmdStorePassHost(dev, &tmd, PHYSADDR(dev, CSR_CXDA(dev))); - break; - } else { - pcnetXmitFailTMDGeneric(dev, &tmd); - } - } else { - pcnetXmitFailTMDLinkDown(dev, &tmd); - } + if (fLoopback) { + if (HOST_IS_OWNER(CSR_CRST(dev))) + pcnetRdtePoll(dev); + + pcnetReceiveNoSync(dev, dev->abLoopBuf, dev->xmit_pos); + } else { + pcnet_log(3, "%s: pcnetAsyncTransmit: transmit loopbuf stp and enp, xmit pos = %d\n", dev->name, dev->xmit_pos); + network_tx(dev->netcard, dev->abLoopBuf, dev->xmit_pos); + } + } else if (cb == 4096) { + /* The Windows NT4 pcnet driver sometimes marks the first + * unused descriptor as owned by us. Ignore that (by + * passing it back). Do not update the ring counter in this + * case (otherwise that driver becomes even more confused, + * which causes transmit to stall for about 10 seconds). + * This is just a workaround, not a final solution. + */ + /* r=frank: IMHO this is the correct implementation. The + * manual says: ``If the OWN bit is set and the buffer + * length is 0, the OWN bit will be cleared. In the C-LANCE + * the buffer length of 0 is interpreted as a 4096-byte + * buffer.'' + */ + /* r=michaln: Perhaps not quite right. The C-LANCE (Am79C90) + * datasheet explains that the old LANCE (Am7990) ignored + * the top four bits next to BCNT and a count of 0 was + * interpreted as 4096. In the C-LANCE, that is still the + * case if the top bits are all ones. If all 16 bits are + * zero, the C-LANCE interprets it as zero-length transmit + * buffer. It's not entirely clear if the later models + * (PCnet-ISA, PCnet-PCI) behave like the C-LANCE or not. + * It is possible that the actual behavior of the C-LANCE + * and later hardware is that the buffer lengths are *16-bit* + * two's complement numbers between 0 and 4096. AMD's drivers + * in fact generally treat the length as a 16-bit quantity. */ + pcnet_log(1, "%s: pcnetAsyncTransmit: illegal 4kb frame -> ignoring\n", dev->name); + pcnetTmdStorePassHost(dev, &tmd, PHYSADDR(dev, CSR_CXDA(dev))); + break; + } else { + pcnetXmitFailTMDGeneric(dev, &tmd); + } + } else { + pcnetXmitFailTMDLinkDown(dev, &tmd); + } /* Write back the TMD and pass it to the host (clear own bit). */ pcnetTmdStorePassHost(dev, &tmd, PHYSADDR(dev, CSR_CXDA(dev))); @@ -1574,8 +1564,9 @@ pcnetAsyncTransmit(nic_t *dev) if (CSR_XMTRC(dev) < 2) { CSR_XMTRC(dev) = CSR_XMTRL(dev); } else { - CSR_XMTRC(dev)--; - } + CSR_XMTRC(dev) + --; + } } else if (tmd.tmd1.stp) { /* * Read TMDs until end-of-packet or tdte poll fails (underflow). @@ -1584,9 +1575,9 @@ pcnetAsyncTransmit(nic_t *dev) * waste time finding out how much space we actually need even if * we could reliably do that on SMP guests. */ - unsigned cb = 4096 - tmd.tmd1.bcnt; - dev->xmit_pos = pcnetCalcPacketLen(dev, cb); - dma_bm_read(PHYSADDR(dev, tmd.tmd0.tbadr), dev->abLoopBuf, cb, dev->transfer_size); + unsigned cb = 4096 - tmd.tmd1.bcnt; + dev->xmit_pos = pcnetCalcPacketLen(dev, cb); + dma_bm_read(PHYSADDR(dev, tmd.tmd0.tbadr), dev->abLoopBuf, cb, dev->transfer_size); for (;;) { /* @@ -1596,7 +1587,8 @@ pcnetAsyncTransmit(nic_t *dev) if (CSR_XMTRC(dev) < 2) CSR_XMTRC(dev) = CSR_XMTRL(dev); else - CSR_XMTRC(dev)--; + CSR_XMTRC(dev) + --; TMD dummy; if (!pcnetTdtePoll(dev, &dummy)) { @@ -1604,13 +1596,13 @@ pcnetAsyncTransmit(nic_t *dev) * Underflow! */ tmd.tmd2.buff = tmd.tmd2.uflo = tmd.tmd1.err = 1; - dev->aCSR[0] |= 0x0200; /* set TINT */ - /* Don't allow the guest to clear TINT before reading it */ - dev->u16CSR0LastSeenByGuest &= ~0x0200; - if (!CSR_DXSUFLO(dev)) /* stop on xmit underflow */ - dev->aCSR[0] &= ~0x0010; /* clear TXON */ + dev->aCSR[0] |= 0x0200; /* set TINT */ + /* Don't allow the guest to clear TINT before reading it */ + dev->u16CSR0LastSeenByGuest &= ~0x0200; + if (!CSR_DXSUFLO(dev)) /* stop on xmit underflow */ + dev->aCSR[0] &= ~0x0010; /* clear TXON */ pcnetTmdStorePassHost(dev, &tmd, GCPhysPrevTmd); - pcnetlog(3,"%s: pcnetAsyncTransmit: Underflow!!!\n", dev->name); + pcnet_log(3, "%s: pcnetAsyncTransmit: Underflow!!!\n", dev->name); break; } @@ -1623,26 +1615,26 @@ pcnetAsyncTransmit(nic_t *dev) pcnetTmdLoad(dev, &tmd, PHYSADDR(dev, CSR_CXDA(dev)), 0); cb = 4096 - tmd.tmd1.bcnt; if (dev->xmit_pos + cb <= MAX_FRAME) { /** @todo this used to be ... + cb < MAX_FRAME. */ - int off = dev->xmit_pos; - dev->xmit_pos = cb + off; - dma_bm_read(PHYSADDR(dev, tmd.tmd0.tbadr), dev->abLoopBuf + off, cb, dev->transfer_size); - } + int off = dev->xmit_pos; + dev->xmit_pos = cb + off; + dma_bm_read(PHYSADDR(dev, tmd.tmd0.tbadr), dev->abLoopBuf + off, cb, dev->transfer_size); + } /* * Done already? */ if (tmd.tmd1.enp) { - if (fLoopback) { - if (HOST_IS_OWNER(CSR_CRST(dev))) - pcnetRdtePoll(dev); + if (fLoopback) { + if (HOST_IS_OWNER(CSR_CRST(dev))) + pcnetRdtePoll(dev); + + pcnet_log(3, "%s: pcnetAsyncTransmit: receive loopback enp\n", dev->name); + pcnetReceiveNoSync(dev, dev->abLoopBuf, dev->xmit_pos); + } else { + pcnet_log(3, "%s: pcnetAsyncTransmit: transmit loopbuf enp\n", dev->name); + network_tx(dev->netcard, dev->abLoopBuf, dev->xmit_pos); + } - pcnetlog(3, "%s: pcnetAsyncTransmit: receive loopback enp\n", dev->name); - pcnetReceiveNoSync(dev, dev->abLoopBuf, dev->xmit_pos); - } else { - pcnetlog(3, "%s: pcnetAsyncTransmit: transmit loopbuf enp\n", dev->name); - network_tx(dev->abLoopBuf, dev->xmit_pos); - } - /* Write back the TMD, pass it to the host */ pcnetTmdStorePassHost(dev, &tmd, PHYSADDR(dev, CSR_CXDA(dev))); @@ -1650,40 +1642,40 @@ pcnetAsyncTransmit(nic_t *dev) if (CSR_XMTRC(dev) < 2) CSR_XMTRC(dev) = CSR_XMTRL(dev); else - CSR_XMTRC(dev)--; + CSR_XMTRC(dev) + --; break; } } /* the loop */ } /* Update TDMD, TXSTRT and TINT. */ - dev->aCSR[0] &= ~0x0008; /* clear TDMD */ - dev->aCSR[4] |= 0x0008; /* set TXSTRT */ - dev->xmit_pos = -1; - if (!CSR_TOKINTD(dev) /* Transmit OK Interrupt Disable, no infl. on errors. */ - || (CSR_LTINTEN(dev) && tmd.tmd1.ltint) + dev->aCSR[0] &= ~0x0008; /* clear TDMD */ + dev->aCSR[4] |= 0x0008; /* set TXSTRT */ + dev->xmit_pos = -1; + if (!CSR_TOKINTD(dev) /* Transmit OK Interrupt Disable, no infl. on errors. */ + || (CSR_LTINTEN(dev) && tmd.tmd1.ltint) || tmd.tmd1.err) { - cFlushIrq++; + cFlushIrq++; } if (--cMax == 0) break; - } while (CSR_TXON(dev)); /* transfer on */ - - if (cFlushIrq) { - dev->aCSR[0] |= 0x0200; /* set TINT */ - /* Don't allow the guest to clear TINT before reading it */ - dev->u16CSR0LastSeenByGuest &= ~0x0200; - pcnetUpdateIrq(dev); - } -} + } while (CSR_TXON(dev)); /* transfer on */ + if (cFlushIrq) { + dev->aCSR[0] |= 0x0200; /* set TINT */ + /* Don't allow the guest to clear TINT before reading it */ + dev->u16CSR0LastSeenByGuest &= ~0x0200; + pcnetUpdateIrq(dev); + } +} /** * Poll for changes in RX and TX descriptor rings. */ -static void +static void pcnetPollRxTx(nic_t *dev) { - if (CSR_RXON(dev)) { + if (CSR_RXON(dev)) { /* * The second case is important for pcnetWaitReceiveAvail(): If CSR_CRST(dev) was * true but pcnetCanReceive() returned false for some other reason we need to check @@ -1697,24 +1689,26 @@ pcnetPollRxTx(nic_t *dev) pcnetAsyncTransmit(dev); } - static void -pcnetPollTimer(nic_t *dev) +pcnetPollTimer(void *priv) { + nic_t *dev = (nic_t *) priv; + + timer_advance_u64(&dev->timer, 2000 * TIMER_USEC); + if (CSR_TDMD(dev)) - pcnetAsyncTransmit(dev); + pcnetAsyncTransmit(dev); pcnetUpdateIrq(dev); if (!CSR_STOP(dev) && !CSR_SPND(dev) && (!CSR_DPOLL(dev) || dev->fMaybeOutOfSpace)) - pcnetPollRxTx(dev); + pcnetPollRxTx(dev); } - static void pcnetHardReset(nic_t *dev) { - pcnetlog(2, "%s: pcnetHardReset\n", dev->name); + pcnet_log(2, "%s: pcnetHardReset\n", dev->name); dev->iISR = 0; pcnet_do_irq(dev, 0); @@ -1722,218 +1716,216 @@ pcnetHardReset(nic_t *dev) /* Many of the BCR values would normally be read from the EEPROM. */ dev->aBCR[BCR_MSRDA] = 0x0005; dev->aBCR[BCR_MSWRA] = 0x0005; - dev->aBCR[BCR_MC] = 0x0002; + dev->aBCR[BCR_MC] = 0x0002; dev->aBCR[BCR_LNKST] = 0x00c0; - dev->aBCR[BCR_LED1] = 0x0084; - dev->aBCR[BCR_LED2] = 0x0088; - dev->aBCR[BCR_LED3] = 0x0090; + dev->aBCR[BCR_LED1] = 0x0084; + dev->aBCR[BCR_LED2] = 0x0088; + dev->aBCR[BCR_LED3] = 0x0090; - dev->aBCR[BCR_FDC] = 0x0000; - dev->aBCR[BCR_BSBC] = 0x9001; + dev->aBCR[BCR_FDC] = 0x0000; + dev->aBCR[BCR_BSBC] = 0x9001; dev->aBCR[BCR_EECAS] = 0x0002; dev->aBCR[BCR_STVAL] = 0xffff; dev->aCSR[58] = dev->aBCR[BCR_SWS] = 0x0200; /* CSR58 is an alias for BCR20 */ - dev->iLog2DescSize = 3; - dev->aBCR[BCR_PLAT] = 0xff06; - dev->aBCR[BCR_MIICAS] = 0x20; /* Auto-negotiation on. */ - dev->aBCR[BCR_MIIADDR] = 0; /* Internal PHY on Am79C973 would be (0x1e << 5) */ - dev->aBCR[BCR_PCIVID] = 0x1022; - dev->aBCR[BCR_PCISID] = 0x0020; - dev->aBCR[BCR_PCISVID] = 0x1022; + dev->iLog2DescSize = 3; + dev->aBCR[BCR_PLAT] = 0xff06; + dev->aBCR[BCR_MIICAS] = 0x20; /* Auto-negotiation on. */ + dev->aBCR[BCR_MIIADDR] = 0; /* Internal PHY on Am79C973 would be (0x1e << 5) */ + dev->aBCR[BCR_PCIVID] = 0x1022; + dev->aBCR[BCR_PCISID] = 0x0020; + dev->aBCR[BCR_PCISVID] = 0x1022; /* Reset the error counter. */ - dev->uCntBadRMD = 0; + dev->uCntBadRMD = 0; pcnetSoftReset(dev); } - -static void +static void pcnet_csr_writew(nic_t *dev, uint16_t rap, uint16_t val) { - pcnetlog(1, "%s: pcnet_csr_writew: rap=%d val=%#06x\n", dev->name, rap, val); + pcnet_log(1, "%s: pcnet_csr_writew: rap=%d val=%#06x\n", dev->name, rap, val); switch (rap) { - case 0: - { - uint16_t csr0 = dev->aCSR[0]; - /* Clear any interrupt flags. - * Don't clear an interrupt flag which was not seen by the guest yet. */ - csr0 &= ~(val & 0x7f00 & dev->u16CSR0LastSeenByGuest); - csr0 = (csr0 & ~0x0040) | (val & 0x0048); - val = (val & 0x007f) | (csr0 & 0x7f00); + case 0: + { + uint16_t csr0 = dev->aCSR[0]; + /* Clear any interrupt flags. + * Don't clear an interrupt flag which was not seen by the guest yet. */ + csr0 &= ~(val & 0x7f00 & dev->u16CSR0LastSeenByGuest); + csr0 = (csr0 & ~0x0040) | (val & 0x0048); + val = (val & 0x007f) | (csr0 & 0x7f00); - /* If STOP, STRT and INIT are set, clear STRT and INIT */ - if ((val & 7) == 7) - val &= ~3; + /* If STOP, STRT and INIT are set, clear STRT and INIT */ + if ((val & 7) == 7) + val &= ~3; - pcnetlog(2, "%s: CSR0 val = %04x, val2 = %04x\n", dev->name, val, dev->aCSR[0]); + pcnet_log(2, "%s: CSR0 val = %04x, val2 = %04x\n", dev->name, val, dev->aCSR[0]); - dev->aCSR[0] = csr0; + dev->aCSR[0] = csr0; - if (!CSR_STOP(dev) && (val & 4)) { - pcnetlog(3, "%s: pcnet_csr_writew(): Stop\n", dev->name); - pcnetStop(dev); - } + if (!CSR_STOP(dev) && (val & 4)) { + pcnet_log(3, "%s: pcnet_csr_writew(): Stop\n", dev->name); + pcnetStop(dev); + } - if (!CSR_INIT(dev) && (val & 1)) { - pcnetlog(3, "%s: pcnet_csr_writew(): Init\n", dev->name); - pcnetInit(dev); - } + if (!CSR_INIT(dev) && (val & 1)) { + pcnet_log(3, "%s: pcnet_csr_writew(): Init\n", dev->name); + pcnetInit(dev); + } - if (!CSR_STRT(dev) && (val & 2)) { - pcnetlog(3, "%s: pcnet_csr_writew(): Start\n", dev->name); - pcnetStart(dev); - } + if (!CSR_STRT(dev) && (val & 2)) { + pcnet_log(3, "%s: pcnet_csr_writew(): Start\n", dev->name); + pcnetStart(dev); + } - if (CSR_TDMD(dev)) { - pcnetlog(3, "%s: pcnet_csr_writew(): Transmit\n", dev->name); - pcnetAsyncTransmit(dev); - } - } - return; + if (CSR_TDMD(dev)) { + pcnet_log(3, "%s: pcnet_csr_writew(): Transmit\n", dev->name); + pcnetAsyncTransmit(dev); + } + } + return; - case 2: /* IADRH */ - if (dev->is_isa) - val &= 0x00ff; /* Upper 8 bits ignored on ISA chips. */ - case 1: /* IADRL */ - case 8: /* LADRF 0..15 */ - case 9: /* LADRF 16..31 */ - case 10: /* LADRF 32..47 */ - case 11: /* LADRF 48..63 */ - case 12: /* PADR 0..15 */ - case 13: /* PADR 16..31 */ - case 14: /* PADR 32..47 */ - case 18: /* CRBAL */ - case 19: /* CRBAU */ - case 20: /* CXBAL */ - case 21: /* CXBAU */ - case 22: /* NRBAL */ - case 23: /* NRBAU */ - case 26: /* NRDAL */ - case 27: /* NRDAU */ - case 28: /* CRDAL */ - case 29: /* CRDAU */ - case 32: /* NXDAL */ - case 33: /* NXDAU */ - case 34: /* CXDAL */ - case 35: /* CXDAU */ - case 36: /* NNRDL */ - case 37: /* NNRDU */ - case 38: /* NNXDL */ - case 39: /* NNXDU */ - case 40: /* CRBCL */ - case 41: /* CRBCU */ - case 42: /* CXBCL */ - case 43: /* CXBCU */ - case 44: /* NRBCL */ - case 45: /* NRBCU */ - case 46: /* POLL */ - case 47: /* POLLINT */ - case 72: /* RCVRC */ - case 74: /* XMTRC */ - case 112: /* MISSC */ - if (CSR_STOP(dev) || CSR_SPND(dev)) - break; - return; - case 3: /* Interrupt Mask and Deferral Control */ - break; - case 4: /* Test and Features Control */ - dev->aCSR[4] &= ~(val & 0x026a); - val &= ~0x026a; - val |= dev->aCSR[4] & 0x026a; - break; - case 5: /* Extended Control and Interrupt 1 */ - dev->aCSR[5] &= ~(val & 0x0a90); - val &= ~0x0a90; - val |= dev->aCSR[5] & 0x0a90; - break; - case 7: /* Extended Control and Interrupt 2 */ - { - uint16_t csr7 = dev->aCSR[7]; - csr7 &= ~0x0400; - csr7 &= ~(val & 0x0800); - csr7 |= (val & 0x0400); - dev->aCSR[7] = csr7; - } - return; - case 15: /* Mode */ - break; - case 16: /* IADRL */ - pcnet_csr_writew(dev,1,val); - return; - case 17: /* IADRH */ - pcnet_csr_writew(dev,2,val); - return; - /* - * 24 and 25 are the Base Address of Receive Descriptor. - * We combine and mirror these in GCRDRA. - */ - case 24: /* BADRL */ - case 25: /* BADRU */ - if (!CSR_STOP(dev) && !CSR_SPND(dev)) { - pcnetlog(3, "%s: WRITE CSR%d, %#06x, ignoring!!\n", dev->name, rap, val); - return; - } - if (rap == 24) - dev->GCRDRA = (dev->GCRDRA & 0xffff0000) | (val & 0x0000ffff); - else - dev->GCRDRA = (dev->GCRDRA & 0x0000ffff) | ((val & 0x0000ffff) << 16); - pcnetlog(3, "%s: WRITE CSR%d, %#06x => GCRDRA=%08x (alt init)\n", dev->name, rap, val, dev->GCRDRA); - if (dev->GCRDRA & (dev->iLog2DescSize - 1)) - pcnetlog(1, "%s: Warning: Misaligned RDRA (GCRDRA=%#010x)\n", dev->name, dev->GCRDRA); - break; - /* - * 30 & 31 are the Base Address of Transmit Descriptor. - * We combine and mirrorthese in GCTDRA. - */ - case 30: /* BADXL */ - case 31: /* BADXU */ - if (!CSR_STOP(dev) && !CSR_SPND(dev)) { - pcnetlog(3, "%s: WRITE CSR%d, %#06x !!\n", dev->name, rap, val); - return; - } - if (rap == 30) - dev->GCTDRA = (dev->GCTDRA & 0xffff0000) | (val & 0x0000ffff); - else - dev->GCTDRA = (dev->GCTDRA & 0x0000ffff) | ((val & 0x0000ffff) << 16); - - pcnetlog(3, "%s: WRITE CSR%d, %#06x => GCTDRA=%08x (alt init)\n", dev->name, rap, val, dev->GCTDRA); + case 2: /* IADRH */ + if (dev->is_isa) + val &= 0x00ff; /* Upper 8 bits ignored on ISA chips. */ + case 1: /* IADRL */ + case 8: /* LADRF 0..15 */ + case 9: /* LADRF 16..31 */ + case 10: /* LADRF 32..47 */ + case 11: /* LADRF 48..63 */ + case 12: /* PADR 0..15 */ + case 13: /* PADR 16..31 */ + case 14: /* PADR 32..47 */ + case 18: /* CRBAL */ + case 19: /* CRBAU */ + case 20: /* CXBAL */ + case 21: /* CXBAU */ + case 22: /* NRBAL */ + case 23: /* NRBAU */ + case 26: /* NRDAL */ + case 27: /* NRDAU */ + case 28: /* CRDAL */ + case 29: /* CRDAU */ + case 32: /* NXDAL */ + case 33: /* NXDAU */ + case 34: /* CXDAL */ + case 35: /* CXDAU */ + case 36: /* NNRDL */ + case 37: /* NNRDU */ + case 38: /* NNXDL */ + case 39: /* NNXDU */ + case 40: /* CRBCL */ + case 41: /* CRBCU */ + case 42: /* CXBCL */ + case 43: /* CXBCU */ + case 44: /* NRBCL */ + case 45: /* NRBCU */ + case 46: /* POLL */ + case 47: /* POLLINT */ + case 72: /* RCVRC */ + case 74: /* XMTRC */ + case 112: /* MISSC */ + if (CSR_STOP(dev) || CSR_SPND(dev)) + break; + return; + case 3: /* Interrupt Mask and Deferral Control */ + break; + case 4: /* Test and Features Control */ + dev->aCSR[4] &= ~(val & 0x026a); + val &= ~0x026a; + val |= dev->aCSR[4] & 0x026a; + break; + case 5: /* Extended Control and Interrupt 1 */ + dev->aCSR[5] &= ~(val & 0x0a90); + val &= ~0x0a90; + val |= dev->aCSR[5] & 0x0a90; + break; + case 7: /* Extended Control and Interrupt 2 */ + { + uint16_t csr7 = dev->aCSR[7]; + csr7 &= ~0x0400; + csr7 &= ~(val & 0x0800); + csr7 |= (val & 0x0400); + dev->aCSR[7] = csr7; + } + return; + case 15: /* Mode */ + break; + case 16: /* IADRL */ + pcnet_csr_writew(dev, 1, val); + return; + case 17: /* IADRH */ + pcnet_csr_writew(dev, 2, val); + return; + /* + * 24 and 25 are the Base Address of Receive Descriptor. + * We combine and mirror these in GCRDRA. + */ + case 24: /* BADRL */ + case 25: /* BADRU */ + if (!CSR_STOP(dev) && !CSR_SPND(dev)) { + pcnet_log(3, "%s: WRITE CSR%d, %#06x, ignoring!!\n", dev->name, rap, val); + return; + } + if (rap == 24) + dev->GCRDRA = (dev->GCRDRA & 0xffff0000) | (val & 0x0000ffff); + else + dev->GCRDRA = (dev->GCRDRA & 0x0000ffff) | ((val & 0x0000ffff) << 16); + pcnet_log(3, "%s: WRITE CSR%d, %#06x => GCRDRA=%08x (alt init)\n", dev->name, rap, val, dev->GCRDRA); + if (dev->GCRDRA & (dev->iLog2DescSize - 1)) + pcnet_log(1, "%s: Warning: Misaligned RDRA (GCRDRA=%#010x)\n", dev->name, dev->GCRDRA); + break; + /* + * 30 & 31 are the Base Address of Transmit Descriptor. + * We combine and mirrorthese in GCTDRA. + */ + case 30: /* BADXL */ + case 31: /* BADXU */ + if (!CSR_STOP(dev) && !CSR_SPND(dev)) { + pcnet_log(3, "%s: WRITE CSR%d, %#06x !!\n", dev->name, rap, val); + return; + } + if (rap == 30) + dev->GCTDRA = (dev->GCTDRA & 0xffff0000) | (val & 0x0000ffff); + else + dev->GCTDRA = (dev->GCTDRA & 0x0000ffff) | ((val & 0x0000ffff) << 16); - if (dev->GCTDRA & (dev->iLog2DescSize - 1)) - pcnetlog(1, "%s: Warning: Misaligned TDRA (GCTDRA=%#010x)\n", dev->name, dev->GCTDRA); - break; - case 58: /* Software Style */ - pcnet_bcr_writew(dev,BCR_SWS,val); - break; - /* - * Registers 76 and 78 aren't stored correctly (see todos), but I'm don't dare - * try fix that right now. So, as a quick hack for 'alt init' I'll just correct them here. - */ - case 76: /* RCVRL */ /** @todo call pcnetUpdateRingHandlers */ - /** @todo receive ring length is stored in two's complement! */ - case 78: /* XMTRL */ /** @todo call pcnetUpdateRingHandlers */ - /** @todo transmit ring length is stored in two's complement! */ - if (!CSR_STOP(dev) && !CSR_SPND(dev)) { - pcnetlog(3, "%s: WRITE CSR%d, %#06x !!\n", dev->name, rap, val); - return; - } - pcnetlog(3, "%s: WRITE CSR%d, %#06x (hacked %#06x) (alt init)\n", dev->name, - rap, val, 1 + ~val); - val = 1 + ~val; + pcnet_log(3, "%s: WRITE CSR%d, %#06x => GCTDRA=%08x (alt init)\n", dev->name, rap, val, dev->GCTDRA); - /* - * HACK ALERT! Set the counter registers too. - */ - dev->aCSR[rap - 4] = val; - break; - default: - return; + if (dev->GCTDRA & (dev->iLog2DescSize - 1)) + pcnet_log(1, "%s: Warning: Misaligned TDRA (GCTDRA=%#010x)\n", dev->name, dev->GCTDRA); + break; + case 58: /* Software Style */ + pcnet_bcr_writew(dev, BCR_SWS, val); + break; + /* + * Registers 76 and 78 aren't stored correctly (see todos), but I'm don't dare + * try fix that right now. So, as a quick hack for 'alt init' I'll just correct them here. + */ + case 76: /* RCVRL */ /** @todo call pcnetUpdateRingHandlers */ + /** @todo receive ring length is stored in two's complement! */ + case 78: /* XMTRL */ /** @todo call pcnetUpdateRingHandlers */ + /** @todo transmit ring length is stored in two's complement! */ + if (!CSR_STOP(dev) && !CSR_SPND(dev)) { + pcnet_log(3, "%s: WRITE CSR%d, %#06x !!\n", dev->name, rap, val); + return; + } + pcnet_log(3, "%s: WRITE CSR%d, %#06x (hacked %#06x) (alt init)\n", dev->name, + rap, val, 1 + ~val); + val = 1 + ~val; + + /* + * HACK ALERT! Set the counter registers too. + */ + dev->aCSR[rap - 4] = val; + break; + default: + return; } dev->aCSR[rap] = val; } - /** * Encode a 32-bit link speed into a custom 16-bit floating-point value */ @@ -1949,294 +1941,302 @@ pcnetLinkSpd(uint32_t speed) return (exp << 13) | speed; } - static uint16_t pcnet_csr_readw(nic_t *dev, uint16_t rap) { uint16_t val; switch (rap) { - case 0: - pcnetUpdateIrq(dev); - val = dev->aCSR[0]; - val |= (val & 0x7800) ? 0x8000 : 0; - dev->u16CSR0LastSeenByGuest = val; - break; - case 16: - return pcnet_csr_readw(dev,1); - case 17: - return pcnet_csr_readw(dev,2); - case 58: - return pcnet_bcr_readw(dev,BCR_SWS); - case 68: /* Custom register to pass link speed to driver */ - return pcnetLinkSpd(dev->u32LinkSpeed); - default: - val = dev->aCSR[rap]; - break; + case 0: + pcnetUpdateIrq(dev); + val = dev->aCSR[0]; + val |= (val & 0x7800) ? 0x8000 : 0; + dev->u16CSR0LastSeenByGuest = val; + break; + case 16: + return pcnet_csr_readw(dev, 1); + case 17: + return pcnet_csr_readw(dev, 2); + case 58: + return pcnet_bcr_readw(dev, BCR_SWS); + case 68: /* Custom register to pass link speed to driver */ + return pcnetLinkSpd(dev->u32LinkSpeed); + default: + val = dev->aCSR[rap]; + break; } - pcnetlog(3, "%s: pcnet_csr_readw rap=%d val=0x%04x\n", dev->name, rap, val); + pcnet_log(3, "%s: pcnet_csr_readw rap=%d val=0x%04x\n", dev->name, rap, val); return val; } - static void pcnet_bcr_writew(nic_t *dev, uint16_t rap, uint16_t val) { rap &= 0x7f; - pcnetlog(3, "%s: pcnet_bcr_writew rap=%d val=0x%04x\n", dev->name, rap, val); + pcnet_log(3, "%s: pcnet_bcr_writew rap=%d val=0x%04x\n", dev->name, rap, val); switch (rap) { - case BCR_SWS: - if (!(CSR_STOP(dev) || CSR_SPND(dev))) - return; - val &= ~0x0300; - switch (val & 0x00ff) { - default: - case 0: - val |= 0x0200; /* 16 bit */ - dev->iLog2DescSize = 3; - dev->GCUpperPhys = (0xff00 & dev->aCSR[2]) << 16; - break; - case 1: - val |= 0x0100; /* 32 bit */ - dev->iLog2DescSize = 4; - dev->GCUpperPhys = 0; - break; - case 2: - case 3: - val |= 0x0300; /* 32 bit */ - dev->iLog2DescSize = 4; - dev->GCUpperPhys = 0; - break; - } - dev->aCSR[58] = val; - /* fall through */ - case BCR_LNKST: - case BCR_LED1: - case BCR_LED2: - case BCR_LED3: - case BCR_MC: - case BCR_FDC: - case BCR_BSBC: - case BCR_EECAS: - case BCR_PLAT: - case BCR_MIICAS: - case BCR_MIIADDR: - dev->aBCR[rap] = val; - break; + case BCR_SWS: + if (!(CSR_STOP(dev) || CSR_SPND(dev))) + return; + val &= ~0x0300; + switch (val & 0x00ff) { + default: + case 0: + val |= 0x0200; /* 16 bit */ + dev->iLog2DescSize = 3; + dev->GCUpperPhys = (0xff00 & dev->aCSR[2]) << 16; + break; + case 1: + val |= 0x0100; /* 32 bit */ + dev->iLog2DescSize = 4; + dev->GCUpperPhys = 0; + break; + case 2: + case 3: + val |= 0x0300; /* 32 bit */ + dev->iLog2DescSize = 4; + dev->GCUpperPhys = 0; + break; + } + dev->aCSR[58] = val; + fallthrough; + case BCR_LNKST: + case BCR_LED1: + case BCR_LED2: + case BCR_LED3: + case BCR_MC: + case BCR_FDC: + case BCR_BSBC: + case BCR_EECAS: + case BCR_PLAT: + case BCR_MIIADDR: + dev->aBCR[rap] = val; + break; - case BCR_STVAL: - val &= 0xffff; - dev->aBCR[BCR_STVAL] = val; - if (dev->board == DEV_AM79C973) - timer_set_delay_u64(&dev->timer_soft_int, (12.8 * val) * TIMER_USEC); - break; - - case BCR_MIIMDR: - dev->aMII[dev->aBCR[BCR_MIIADDR] & 0x1f] = val; - break; - - default: - break; + case BCR_MIICAS: + dev->netcard->byte_period = (dev->board == DEV_AM79C973 && (val & 0x28)) ? NET_PERIOD_100M : NET_PERIOD_10M; + dev->aBCR[rap] = val; + break; + + case BCR_STVAL: + val &= 0xffff; + dev->aBCR[BCR_STVAL] = val; + if (dev->board == DEV_AM79C973) + timer_set_delay_u64(&dev->timer_soft_int, (12.8 * val) * TIMER_USEC); + break; + + case BCR_MIIMDR: + dev->aMII[dev->aBCR[BCR_MIIADDR] & 0x1f] = val; + break; + + default: + break; } } -static uint16_t +static uint16_t pcnet_mii_readw(nic_t *dev, uint16_t miiaddr) { uint16_t val; - int autoneg, duplex, fast, isolate; - + int autoneg; + int duplex; + int fast; + int isolate; + /* If the DANAS (BCR32.7) bit is set, the MAC does not do any * auto-negotiation and the PHY must be set up explicitly. DANAS * effectively disables most other BCR32 bits. */ if (dev->aBCR[BCR_MIICAS] & 0x80) { - /* PHY controls auto-negotiation. */ - autoneg = duplex = fast = 1; + /* PHY controls auto-negotiation. */ + autoneg = duplex = fast = 1; } else { - /* BCR32 controls auto-negotiation. */ - autoneg = (dev->aBCR[BCR_MIICAS] & 0x20) != 0; - duplex = (dev->aBCR[BCR_MIICAS] & 0x10) != 0; - fast = (dev->aBCR[BCR_MIICAS] & 0x08) != 0; + /* BCR32 controls auto-negotiation. */ + autoneg = (dev->aBCR[BCR_MIICAS] & 0x20) != 0; + duplex = (dev->aBCR[BCR_MIICAS] & 0x10) != 0; + fast = (dev->aBCR[BCR_MIICAS] & 0x08) != 0; } - + /* Electrically isolating the PHY mostly disables it. */ isolate = (dev->aMII[0] & 0x400) != 0; - + switch (miiaddr) { - case 0: - /* MII basic mode control register. */ - val = 0; - if (autoneg) - val |= 0x1000; /* Enable auto negotiation. */ - if (fast) - val |= 0x2000; /* 100 Mbps */ - if (duplex) /* Full duplex forced */ - val |= 0x0100; /* Full duplex */ - if (isolate) /* PHY electrically isolated. */ - val |= 0x0400; /* Isolated */ - break; + case 0: + /* MII basic mode control register. */ + val = 0; + if (autoneg) + val |= 0x1000; /* Enable auto negotiation. */ + if (fast) + val |= 0x2000; /* 100 Mbps */ + if (duplex) /* Full duplex forced */ + val |= 0x0100; /* Full duplex */ + if (isolate) /* PHY electrically isolated. */ + val |= 0x0400; /* Isolated */ + break; - case 1: - /* MII basic mode status register. */ - val = 0x7800 /* Can do 100mbps FD/HD and 10mbps FD/HD. */ - | 0x0040 /* Mgmt frame preamble not required. */ - | 0x0020 /* Auto-negotiation complete. */ - | 0x0008 /* Able to do auto-negotiation. */ - | 0x0004 /* Link up. */ - | 0x0001; /* Extended Capability, i.e. registers 4+ valid. */ - if (!dev->fLinkUp || dev->fLinkTempDown || isolate) { - val &= ~(0x0020 | 0x0004); - dev->cLinkDownReported++; - } - if (!autoneg) { - /* Auto-negotiation disabled. */ - if (duplex) - val &= ~0x2800; /* Full duplex forced. */ - else - val &= ~0x5000; /* Half duplex forced. */ + case 1: + /* MII basic mode status register. */ + val = 0x7800 /* Can do 100mbps FD/HD and 10mbps FD/HD. */ + | 0x0040 /* Mgmt frame preamble not required. */ + | 0x0020 /* Auto-negotiation complete. */ + | 0x0008 /* Able to do auto-negotiation. */ + | 0x0004 /* Link up. */ + | 0x0001; /* Extended Capability, i.e. registers 4+ valid. */ + if (!pcnetIsLinkUp(dev) || isolate) { + val &= ~(0x0020 | 0x0004); + dev->cLinkDownReported++; + } + if (!autoneg) { + /* Auto-negotiation disabled. */ + val &= ~(0x0020 | 0x0008); + if (duplex) + val &= ~0x2800; /* Full duplex forced. */ + else + val &= ~0x5000; /* Half duplex forced. */ - if (fast) - val &= ~0x1800; /* 100 Mbps forced */ - else - val &= ~0x6000; /* 10 Mbps forced */ - } - break; - - case 2: - /* PHY identifier 1. */ - val = 0x22; /* Am79C874/AC101 PHY */ - break; - - case 3: - /* PHY identifier 2. */ - val = 0x561b; /* Am79C874/AC101 PHY */ - break; - - case 4: - /* Advertisement control register. */ - val = 0x01e0 /* Try 100mbps FD/HD and 10mbps FD/HD. */ - | 0x0001; /* CSMA selector. */ - break; + if (fast) + val &= ~0x1800; /* 100 Mbps forced */ + else + val &= ~0x6000; /* 10 Mbps forced */ + } + break; - case 5: - /* Link partner ability register. */ - if (dev->fLinkUp && !dev->fLinkTempDown && !isolate) { - val = 0x8000 /* Next page bit. */ - | 0x4000 /* Link partner acked us. */ - | 0x0400 /* Can do flow control. */ - | 0x01e0 /* Can do 100mbps FD/HD and 10mbps FD/HD. */ - | 0x0001; /* Use CSMA selector. */ - } else { - val = 0; - dev->cLinkDownReported++; - } - break; + case 2: + /* PHY identifier 1. */ + val = 0x22; /* Am79C874/AC101 PHY */ + break; - case 6: - /* Auto negotiation expansion register. */ - if (dev->fLinkUp && !dev->fLinkTempDown && !isolate) { - val = 0x0008 /* Link partner supports npage. */ - | 0x0004 /* Enable npage words. */ - | 0x0001; /* Can do N-way auto-negotiation. */ - } else { - val = 0; - dev->cLinkDownReported++; - } - break; - - case 18: - /* Diagnostic Register (FreeBSD pcn/ac101 driver reads this). */ - if (dev->fLinkUp && !dev->fLinkTempDown && !isolate) { - val = 0x1000 /* Receive PLL locked. */ - | 0x0200; /* Signal detected. */ - - if (autoneg) { - val |= 0x0400 /* 100Mbps rate. */ - | 0x0800; /* Full duplex. */ - } else { - if (fast) - val |= 0x0400; /* 100Mbps rate. */ - if (duplex) - val |= 0x0800; /* Full duplex. */ - } - } else { - val = 0; - dev->cLinkDownReported++; - } - break; - - default: - val = 0; - break; + case 3: + /* PHY identifier 2. */ + val = 0x561b; /* Am79C874/AC101 PHY */ + break; + + case 4: + /* Advertisement control register. */ + val = 0x01e0 /* Try 100mbps FD/HD and 10mbps FD/HD. */ + | 0x0001; /* CSMA selector. */ + break; + + case 5: + /* Link partner ability register. */ + if (pcnetIsLinkUp(dev) && !isolate) { + val = 0x8000 /* Next page bit. */ + | 0x4000 /* Link partner acked us. */ + | 0x0400 /* Can do flow control. */ + | 0x01e0 /* Can do 100mbps FD/HD and 10mbps FD/HD. */ + | 0x0001; /* Use CSMA selector. */ + } else { + val = 0; + dev->cLinkDownReported++; + } + break; + + case 6: + /* Auto negotiation expansion register. */ + if (pcnetIsLinkUp(dev) && !isolate) { + val = 0x0008 /* Link partner supports npage. */ + | 0x0004 /* Enable npage words. */ + | 0x0001; /* Can do N-way auto-negotiation. */ + } else { + val = 0; + dev->cLinkDownReported++; + } + break; + + case 18: + /* Diagnostic Register (FreeBSD pcn/ac101 driver reads this). */ + if (pcnetIsLinkUp(dev) && !isolate) { + val = 0x1000 /* Receive PLL locked. */ + | 0x0200; /* Signal detected. */ + + if (autoneg) { + val |= 0x0400 /* 100Mbps rate. */ + | 0x0800; /* Full duplex. */ + } else { + if (fast) + val |= 0x0400; /* 100Mbps rate. */ + if (duplex) + val |= 0x0800; /* Full duplex. */ + } + } else { + val = 0; + dev->cLinkDownReported++; + } + break; + + default: + val = 0; + break; } - + return val; } -static uint16_t +static uint16_t pcnet_bcr_readw(nic_t *dev, uint16_t rap) { uint16_t val; rap &= 0x7f; switch (rap) { - case BCR_LNKST: - case BCR_LED1: - case BCR_LED2: - case BCR_LED3: - val = dev->aBCR[rap] & ~0x8000; - if (dev->fLinkTempDown || !dev->fLinkUp) { - if (rap == 4) - dev->cLinkDownReported++; - val &= ~0x40; - } - val |= (val & 0x017f & dev->u32Lnkst) ? 0x8000 : 0; - break; - - case BCR_MIIMDR: - if ((dev->board == DEV_AM79C973) && (((dev->aBCR[BCR_MIIADDR] >> 5) & 0x1f) == 0)) { - uint16_t miiaddr = dev->aBCR[BCR_MIIADDR] & 0x1f; - val = pcnet_mii_readw(dev, miiaddr); - } else - val = 0xffff; - break; + case BCR_LNKST: + case BCR_LED1: + case BCR_LED2: + case BCR_LED3: + val = dev->aBCR[rap] & ~0x8000; + if (!(pcnetIsLinkUp(dev))) { + if (rap == 4) + dev->cLinkDownReported++; + val &= ~0x40; + } + val |= (val & 0x017f & dev->u32Lnkst) ? 0x8000 : 0; + break; - case BCR_SWCONFIG: - if (dev->board == DEV_AM79C961) - val = ((dev->base_irq & 0x0f) << 4) | (dev->dma_channel & 0x07); - else - val = 0xffff; - break; + case BCR_MIIMDR: + if ((dev->board == DEV_AM79C973) && (((dev->aBCR[BCR_MIIADDR] >> 5) & 0x1f) == 0)) { + uint16_t miiaddr = dev->aBCR[BCR_MIIADDR] & 0x1f; + val = pcnet_mii_readw(dev, miiaddr); + } else + val = 0xffff; + break; - default: - val = rap < BCR_MAX_RAP ? dev->aBCR[rap] : 0; - break; + case BCR_SWCONFIG: + if (dev->board == DEV_AM79C961) + val = ((dev->base_irq & 0x0f) << 4) | (dev->dma_channel & 0x07); + else + val = 0xffff; + break; + + default: + val = rap < BCR_MAX_RAP ? dev->aBCR[rap] : 0; + break; } - pcnetlog(3, "pcnet_bcr_readw rap=%d val=0x%04x\n", rap, val); + pcnet_log(3, "pcnet_bcr_readw rap=%d val=0x%04x\n", rap, val); return val; } - static void pcnet_word_write(nic_t *dev, uint32_t addr, uint16_t val) { - pcnetlog(3, "%s: pcnet_word_write: addr = %04x, val = %04x, DWIO not set = %04x\n", dev->name, addr & 0x0f, val, !BCR_DWIO(dev)); + pcnet_log(3, "%s: pcnet_word_write: addr = %04x, val = %04x, DWIO not set = %04x\n", dev->name, addr & 0x0f, val, !BCR_DWIO(dev)); if (!BCR_DWIO(dev)) { switch (addr & 0x0f) { - case 0x00: /* RDP */ - pcnetPollTimer(dev); - pcnet_csr_writew(dev, dev->u32RAP, val); - pcnetUpdateIrq(dev); - break; - case 0x02: - dev->u32RAP = val & 0x7f; - break; - case 0x06: - pcnet_bcr_writew(dev, dev->u32RAP, val); - break; - } + case 0x00: /* RDP */ + timer_set_delay_u64(&dev->timer, 2000 * TIMER_USEC); + pcnet_csr_writew(dev, dev->u32RAP, val); + pcnetUpdateIrq(dev); + break; + case 0x02: + dev->u32RAP = val & 0x7f; + break; + case 0x06: + pcnet_bcr_writew(dev, dev->u32RAP, val); + break; + + default: + break; + } } } @@ -2246,121 +2246,130 @@ pcnet_byte_read(nic_t *dev, uint32_t addr) uint8_t val = 0xff; if (!BCR_DWIO(dev)) { - switch (addr & 0x0f) { - case 0x04: - pcnetSoftReset(dev); - val = 0; - break; - } + switch (addr & 0x0f) { + case 0x04: + pcnetSoftReset(dev); + val = 0; + break; + + default: + break; + } } pcnetUpdateIrq(dev); - pcnetlog(3, "%s: pcnet_word_read: addr = %04x, val = %04x, DWIO not set = %04x\n", dev->name, addr & 0x0f, val, !BCR_DWIO(dev)); + pcnet_log(3, "%s: pcnet_word_read: addr = %04x, val = %04x, DWIO not set = %04x\n", dev->name, addr & 0x0f, val, !BCR_DWIO(dev)); - return(val); + return val; } static uint16_t pcnet_word_read(nic_t *dev, uint32_t addr) -{ +{ uint16_t val = 0xffff; if (!BCR_DWIO(dev)) { - switch (addr & 0x0f) { - case 0x00: /* RDP */ - /** @note if we're not polling, then the guest will tell us when to poll by setting TDMD in CSR0 */ - /** Polling is then useless here and possibly expensive. */ - if (!CSR_DPOLL(dev)) - pcnetPollTimer(dev); - - val = pcnet_csr_readw(dev, dev->u32RAP); - if (dev->u32RAP == 0) - goto skip_update_irq; - break; - case 0x02: - val = dev->u32RAP; - goto skip_update_irq; - case 0x04: - pcnetSoftReset(dev); - val = 0; - break; - case 0x06: - val = pcnet_bcr_readw(dev, dev->u32RAP); - break; - } + switch (addr & 0x0f) { + case 0x00: /* RDP */ + /** @note if we're not polling, then the guest will tell us when to poll by setting TDMD in CSR0 */ + /** Polling is then useless here and possibly expensive. */ + if (!CSR_DPOLL(dev)) + timer_set_delay_u64(&dev->timer, 2000 * TIMER_USEC); + + val = pcnet_csr_readw(dev, dev->u32RAP); + if (dev->u32RAP == 0) + goto skip_update_irq; + break; + case 0x02: + val = dev->u32RAP; + goto skip_update_irq; + case 0x04: + pcnetSoftReset(dev); + val = 0; + break; + case 0x06: + val = pcnet_bcr_readw(dev, dev->u32RAP); + break; + + default: + break; + } } pcnetUpdateIrq(dev); skip_update_irq: - pcnetlog(3, "%s: pcnet_word_read: addr = %04x, val = %04x, DWIO not set = %04x\n", dev->name, addr & 0x0f, val, !BCR_DWIO(dev)); + pcnet_log(3, "%s: pcnet_word_read: addr = %04x, val = %04x, DWIO not set = %04x\n", dev->name, addr & 0x0f, val, !BCR_DWIO(dev)); - return(val); + return val; } - -static void +static void pcnet_dword_write(nic_t *dev, uint32_t addr, uint32_t val) { if (BCR_DWIO(dev)) { switch (addr & 0x0f) { - case 0x00: /* RDP */ - pcnetPollTimer(dev); - pcnet_csr_writew(dev, dev->u32RAP, val & 0xffff); - pcnetUpdateIrq(dev); - break; - case 0x04: - dev->u32RAP = val & 0x7f; - break; - case 0x0c: - pcnet_bcr_writew(dev, dev->u32RAP, val & 0xffff); - break; - } + case 0x00: /* RDP */ + timer_set_delay_u64(&dev->timer, 2000 * TIMER_USEC); + pcnet_csr_writew(dev, dev->u32RAP, val & 0xffff); + pcnetUpdateIrq(dev); + break; + case 0x04: + dev->u32RAP = val & 0x7f; + break; + case 0x0c: + pcnet_bcr_writew(dev, dev->u32RAP, val & 0xffff); + break; + + default: + break; + } } else if ((addr & 0x0f) == 0) { /* switch device to dword i/o mode */ pcnet_bcr_writew(dev, BCR_BSBC, pcnet_bcr_readw(dev, BCR_BSBC) | 0x0080); - pcnetlog(3, "%s: device switched into dword i/o mode\n", dev->name); - }; + pcnet_log(3, "%s: device switched into dword i/o mode\n", dev->name); + } } - static uint32_t pcnet_dword_read(nic_t *dev, uint32_t addr) -{ +{ uint32_t val = 0xffffffff; if (BCR_DWIO(dev)) { - switch (addr & 0x0f) { - case 0x00: /* RDP */ - if (!CSR_DPOLL(dev)) - pcnetPollTimer(dev); - val = pcnet_csr_readw(dev, dev->u32RAP); - if (dev->u32RAP == 0) - goto skip_update_irq; - break; - case 0x04: - val = dev->u32RAP; - goto skip_update_irq; - case 0x08: - pcnetSoftReset(dev); - val = 0; - break; - case 0x0c: - val = pcnet_bcr_readw(dev, dev->u32RAP); - break; - } + switch (addr & 0x0f) { + case 0x00: /* RDP */ + if (!CSR_DPOLL(dev)) + timer_set_delay_u64(&dev->timer, 2000 * TIMER_USEC); + val = pcnet_csr_readw(dev, dev->u32RAP); + if (dev->u32RAP == 0) + goto skip_update_irq; + break; + case 0x04: + val = dev->u32RAP; + goto skip_update_irq; + case 0x08: + pcnetSoftReset(dev); + val = 0; + break; + case 0x0c: + val = pcnet_bcr_readw(dev, dev->u32RAP); + break; + + default: + break; + } } pcnetUpdateIrq(dev); skip_update_irq: - pcnetlog(3, "%s: Read Long mode, addr = %08x, val = %08x\n", dev->name, addr, val); - return(val); + pcnet_log(3, "%s: Read Long mode, addr = %08x, val = %08x\n", dev->name, addr, val); + return val; } - -static void +static void pcnet_aprom_writeb(nic_t *dev, uint32_t addr, uint32_t val) { /* Check APROMWE bit to enable write access */ @@ -2368,8 +2377,7 @@ pcnet_aprom_writeb(nic_t *dev, uint32_t addr, uint32_t val) dev->aPROM[addr & 0x0f] = val & 0xff; } - -static uint32_t +static uint32_t pcnet_aprom_readb(nic_t *dev, uint32_t addr) { uint32_t val = dev->aPROM[addr & 15]; @@ -2377,412 +2385,401 @@ pcnet_aprom_readb(nic_t *dev, uint32_t addr) return val; } - static void pcnet_write(nic_t *dev, uint32_t addr, uint32_t val, int len) { uint16_t off = addr & 0x1f; - pcnetlog(3, "%s: write addr %x, val %x, off %x, len %d\n", dev->name, addr, val, off, len); + pcnet_log(3, "%s: write addr %x, val %x, off %x, len %d\n", dev->name, addr, val, off, len); if (off < 0x10) { - if (!BCR_DWIO(dev) && len == 1) - pcnet_aprom_writeb(dev, addr, val); - else if (!BCR_DWIO(dev) && ((addr & 1) == 0) && len == 2) { - pcnet_aprom_writeb(dev, addr, val); - pcnet_aprom_writeb(dev, addr + 1, val >> 8); - } else if (BCR_DWIO(dev) && ((addr & 3) == 0) && len == 4) { - pcnet_aprom_writeb(dev, addr, val); - pcnet_aprom_writeb(dev, addr + 1, val >> 8); - pcnet_aprom_writeb(dev, addr + 2, val >> 16); - pcnet_aprom_writeb(dev, addr + 3, val >> 24); - } + if (!BCR_DWIO(dev) && len == 1) + pcnet_aprom_writeb(dev, addr, val); + else if (!BCR_DWIO(dev) && ((addr & 1) == 0) && len == 2) { + pcnet_aprom_writeb(dev, addr, val); + pcnet_aprom_writeb(dev, addr + 1, val >> 8); + } else if (BCR_DWIO(dev) && ((addr & 3) == 0) && len == 4) { + pcnet_aprom_writeb(dev, addr, val); + pcnet_aprom_writeb(dev, addr + 1, val >> 8); + pcnet_aprom_writeb(dev, addr + 2, val >> 16); + pcnet_aprom_writeb(dev, addr + 3, val >> 24); + } } else { - if (len == 2) - pcnet_word_write(dev, addr, val); - else if (len == 4) - pcnet_dword_write(dev, addr, val); + if (len == 2) + pcnet_word_write(dev, addr, val); + else if (len == 4) + pcnet_dword_write(dev, addr, val); } } - static void pcnet_writeb(uint16_t addr, uint8_t val, void *priv) { - pcnet_write((nic_t *)priv, addr, val, 1); + pcnet_write((nic_t *) priv, addr, val, 1); } - static void pcnet_writew(uint16_t addr, uint16_t val, void *priv) { - pcnet_write((nic_t *)priv, addr, val, 2); + pcnet_write((nic_t *) priv, addr, val, 2); } - static void pcnet_writel(uint16_t addr, uint32_t val, void *priv) { - pcnet_write((nic_t *)priv, addr, val, 4); + pcnet_write((nic_t *) priv, addr, val, 4); } - static uint32_t pcnet_read(nic_t *dev, uint32_t addr, int len) { uint32_t retval = 0xffffffff; - uint16_t off = addr & 0x1f; + uint16_t off = addr & 0x1f; - pcnetlog(3, "%s: read addr %x, off %x, len %d\n", dev->name, addr, off, len); + pcnet_log(3, "%s: read addr %x, off %x, len %d\n", dev->name, addr, off, len); if (off < 0x10) { - if (!BCR_DWIO(dev) && len == 1) - retval = pcnet_aprom_readb(dev, addr); - else if (!BCR_DWIO(dev) && ((addr & 1) == 0) && len == 2) - retval = pcnet_aprom_readb(dev, addr) | (pcnet_aprom_readb(dev, addr + 1) << 8); - else if (BCR_DWIO(dev) && ((addr & 3) == 0) && len == 4) { - retval = pcnet_aprom_readb(dev, addr) | (pcnet_aprom_readb(dev, addr + 1) << 8) | - (pcnet_aprom_readb(dev, addr + 2) << 16) | (pcnet_aprom_readb(dev, addr + 3) << 24); - } + if (!BCR_DWIO(dev) && len == 1) + retval = pcnet_aprom_readb(dev, addr); + else if (!BCR_DWIO(dev) && ((addr & 1) == 0) && len == 2) + retval = pcnet_aprom_readb(dev, addr) | (pcnet_aprom_readb(dev, addr + 1) << 8); + else if (BCR_DWIO(dev) && ((addr & 3) == 0) && len == 4) { + retval = pcnet_aprom_readb(dev, addr) | (pcnet_aprom_readb(dev, addr + 1) << 8) | (pcnet_aprom_readb(dev, addr + 2) << 16) | (pcnet_aprom_readb(dev, addr + 3) << 24); + } } else { - if (len == 1) - retval = pcnet_byte_read(dev, addr); - else if (len == 2) - retval = pcnet_word_read(dev, addr); - else if (len == 4) - retval = pcnet_dword_read(dev, addr); + if (len == 1) + retval = pcnet_byte_read(dev, addr); + else if (len == 2) + retval = pcnet_word_read(dev, addr); + else if (len == 4) + retval = pcnet_dword_read(dev, addr); } - pcnetlog(3, "%s: value in read - %08x\n", dev->name, retval); - return(retval); + pcnet_log(3, "%s: value in read - %08x\n", dev->name, retval); + return retval; } - static uint8_t pcnet_readb(uint16_t addr, void *priv) { - return(pcnet_read((nic_t *)priv, addr, 1)); + return (pcnet_read((nic_t *) priv, addr, 1)); } - static uint16_t pcnet_readw(uint16_t addr, void *priv) { - return(pcnet_read((nic_t *)priv, addr, 2)); + return (pcnet_read((nic_t *) priv, addr, 2)); } - static uint32_t pcnet_readl(uint16_t addr, void *priv) { - return(pcnet_read((nic_t *)priv, addr, 4)); + return (pcnet_read((nic_t *) priv, addr, 4)); } - static void pcnet_mmio_writeb(uint32_t addr, uint8_t val, void *priv) { - pcnet_write((nic_t *)priv, addr, val, 1); + pcnet_write((nic_t *) priv, addr, val, 1); } - static void pcnet_mmio_writew(uint32_t addr, uint16_t val, void *priv) { - pcnet_write((nic_t *)priv, addr, val, 2); + pcnet_write((nic_t *) priv, addr, val, 2); } - static void pcnet_mmio_writel(uint32_t addr, uint32_t val, void *priv) { - pcnet_write((nic_t *)priv, addr, val, 4); + pcnet_write((nic_t *) priv, addr, val, 4); } - static uint8_t pcnet_mmio_readb(uint32_t addr, void *priv) { - return(pcnet_read((nic_t *)priv, addr, 1)); + return (pcnet_read((nic_t *) priv, addr, 1)); } - static uint16_t pcnet_mmio_readw(uint32_t addr, void *priv) { - return(pcnet_read((nic_t *)priv, addr, 2)); + return (pcnet_read((nic_t *) priv, addr, 2)); } - static uint32_t pcnet_mmio_readl(uint32_t addr, void *priv) { - return(pcnet_read((nic_t *)priv, addr, 4)); + return (pcnet_read((nic_t *) priv, addr, 4)); } - static void pcnet_mem_init(nic_t *dev, uint32_t addr) { mem_mapping_add(&dev->mmio_mapping, addr, 32, - pcnet_mmio_readb, pcnet_mmio_readw, pcnet_mmio_readl, - pcnet_mmio_writeb, pcnet_mmio_writew, pcnet_mmio_writel, - NULL, MEM_MAPPING_EXTERNAL, dev); + pcnet_mmio_readb, pcnet_mmio_readw, pcnet_mmio_readl, + pcnet_mmio_writeb, pcnet_mmio_writew, pcnet_mmio_writel, + NULL, MEM_MAPPING_EXTERNAL, dev); } - static void pcnet_mem_set_addr(nic_t *dev, uint32_t base) { mem_mapping_set_addr(&dev->mmio_mapping, base, 32); } - static void pcnet_mem_disable(nic_t *dev) { mem_mapping_disable(&dev->mmio_mapping); } - static void pcnet_ioremove(nic_t *dev, uint16_t addr, int len) -{ +{ if (dev->is_pci || dev->is_vlb) { - io_removehandler(addr, len, - pcnet_readb, pcnet_readw, pcnet_readl, - pcnet_writeb, pcnet_writew, pcnet_writel, dev); + io_removehandler(addr, len, + pcnet_readb, pcnet_readw, pcnet_readl, + pcnet_writeb, pcnet_writew, pcnet_writel, dev); } else { - io_removehandler(addr, len, - pcnet_readb, pcnet_readw, NULL, - pcnet_writeb, pcnet_writew, NULL, dev); + io_removehandler(addr, len, + pcnet_readb, pcnet_readw, NULL, + pcnet_writeb, pcnet_writew, NULL, dev); } } - static void pcnet_ioset(nic_t *dev, uint16_t addr, int len) -{ +{ pcnet_ioremove(dev, addr, len); if (dev->is_pci || dev->is_vlb) { - io_sethandler(addr, len, - pcnet_readb, pcnet_readw, pcnet_readl, - pcnet_writeb, pcnet_writew, pcnet_writel, dev); + io_sethandler(addr, len, + pcnet_readb, pcnet_readw, pcnet_readl, + pcnet_writeb, pcnet_writew, pcnet_writel, dev); } else { - io_sethandler(addr, len, - pcnet_readb, pcnet_readw, NULL, - pcnet_writeb, pcnet_writew, NULL, dev); + io_sethandler(addr, len, + pcnet_readb, pcnet_readw, NULL, + pcnet_writeb, pcnet_writew, NULL, dev); } } - static void -pcnet_pci_write(int func, int addr, uint8_t val, void *p) +pcnet_pci_write(UNUSED(int func), int addr, uint8_t val, void *priv) { - nic_t *dev = (nic_t *)p; + nic_t *dev = (nic_t *) priv; uint8_t valxor; - pcnetlog(4, "%s: Write value %02X to register %02X\n", dev->name, val, addr & 0xff); + pcnet_log(4, "%s: Write value %02X to register %02X\n", dev->name, val, addr & 0xff); switch (addr) { - case 0x04: - valxor = (val & 0x57) ^ pcnet_pci_regs[addr]; - if (valxor & PCI_COMMAND_IO) { - pcnet_ioremove(dev, dev->PCIBase, 32); - if ((dev->PCIBase != 0) && (val & PCI_COMMAND_IO)) - pcnet_ioset(dev, dev->PCIBase, 32); - } - if (valxor & PCI_COMMAND_MEM) { - pcnet_mem_disable(dev); - if ((dev->MMIOBase != 0) && (val & PCI_COMMAND_MEM)) - pcnet_mem_set_addr(dev, dev->MMIOBase); - } - pcnet_pci_regs[addr] = val & 0x57; - break; + case 0x04: + valxor = (val & 0x57) ^ pcnet_pci_regs[addr]; + if (valxor & PCI_COMMAND_IO) { + pcnet_ioremove(dev, dev->PCIBase, 32); + if ((dev->PCIBase != 0) && (val & PCI_COMMAND_IO)) + pcnet_ioset(dev, dev->PCIBase, 32); + } + if (valxor & PCI_COMMAND_MEM) { + pcnet_mem_disable(dev); + if ((dev->MMIOBase != 0) && (val & PCI_COMMAND_MEM)) + pcnet_mem_set_addr(dev, dev->MMIOBase); + } + pcnet_pci_regs[addr] = val & 0x57; + break; - case 0x05: - pcnet_pci_regs[addr] = val & 0x01; - break; + case 0x05: + pcnet_pci_regs[addr] = val & 0x01; + break; - case 0x0D: - pcnet_pci_regs[addr] = val; - break; + case 0x0D: + pcnet_pci_regs[addr] = val; + break; - case 0x10: case 0x11: case 0x12: case 0x13: - /* I/O Base set. */ - /* First, remove the old I/O. */ - pcnet_ioremove(dev, dev->PCIBase, 32); - /* Then let's set the PCI regs. */ - pcnet_pci_bar[0].addr_regs[addr & 3] = val; - /* Then let's calculate the new I/O base. */ - pcnet_pci_bar[0].addr &= 0xff00; - dev->PCIBase = pcnet_pci_bar[0].addr; - /* Log the new base. */ - pcnetlog(4, "%s: New I/O base is %04X\n" , dev->name, dev->PCIBase); - /* We're done, so get out of the here. */ - if (pcnet_pci_regs[4] & PCI_COMMAND_IO) { - if (dev->PCIBase != 0) - pcnet_ioset(dev, dev->PCIBase, 32); - } - return; + case 0x10: + case 0x11: + case 0x12: + case 0x13: + /* I/O Base set. */ + /* First, remove the old I/O. */ + pcnet_ioremove(dev, dev->PCIBase, 32); + /* Then let's set the PCI regs. */ + pcnet_pci_bar[0].addr_regs[addr & 3] = val; + /* Then let's calculate the new I/O base. */ + pcnet_pci_bar[0].addr &= 0xff00; + dev->PCIBase = pcnet_pci_bar[0].addr; + /* Log the new base. */ + pcnet_log(4, "%s: New I/O base is %04X\n", dev->name, dev->PCIBase); + /* We're done, so get out of the here. */ + if (pcnet_pci_regs[4] & PCI_COMMAND_IO) { + if (dev->PCIBase != 0) + pcnet_ioset(dev, dev->PCIBase, 32); + } + return; - case 0x15: case 0x16: case 0x17: - /* MMIO Base set. */ - /* First, remove the old I/O. */ - pcnet_mem_disable(dev); - /* Then let's set the PCI regs. */ - pcnet_pci_bar[1].addr_regs[addr & 3] = val; - /* Then let's calculate the new I/O base. */ - pcnet_pci_bar[1].addr &= 0xffffc000; - dev->MMIOBase = pcnet_pci_bar[1].addr & 0xffffc000; - /* Log the new base. */ - pcnetlog(4, "%s: New MMIO base is %08X\n" , dev->name, dev->MMIOBase); - /* We're done, so get out of the here. */ - if (pcnet_pci_regs[4] & PCI_COMMAND_MEM) { - if (dev->MMIOBase != 0) - pcnet_mem_set_addr(dev, dev->MMIOBase); - } - return; + case 0x15: + case 0x16: + case 0x17: + /* MMIO Base set. */ + /* First, remove the old I/O. */ + pcnet_mem_disable(dev); + /* Then let's set the PCI regs. */ + pcnet_pci_bar[1].addr_regs[addr & 3] = val; + /* Then let's calculate the new I/O base. */ + pcnet_pci_bar[1].addr &= 0xffffc000; + dev->MMIOBase = pcnet_pci_bar[1].addr & 0xffffc000; + /* Log the new base. */ + pcnet_log(4, "%s: New MMIO base is %08X\n", dev->name, dev->MMIOBase); + /* We're done, so get out of the here. */ + if (pcnet_pci_regs[4] & PCI_COMMAND_MEM) { + if (dev->MMIOBase != 0) + pcnet_mem_set_addr(dev, dev->MMIOBase); + } + return; - case 0x3C: - dev->base_irq = val; - pcnet_pci_regs[addr] = val; - return; + case 0x3C: + dev->base_irq = val; + pcnet_pci_regs[addr] = val; + return; + + default: + break; } } - static uint8_t -pcnet_pci_read(int func, int addr, void *p) +pcnet_pci_read(UNUSED(int func), int addr, void *priv) { - nic_t *dev = (nic_t *)p; + const nic_t *dev = (nic_t *) priv; - pcnetlog(4, "%s: Read to register %02X\n", dev->name, addr & 0xff); + pcnet_log(4, "%s: Read to register %02X\n", dev->name, addr & 0xff); switch (addr) { - case 0x00: - return 0x22; - case 0x01: - return 0x10; - case 0x02: - return 0x00; - case 0x03: - return 0x20; - case 0x04: - return pcnet_pci_regs[0x04] & 0x57; /*Respond to IO and memory accesses*/ - case 0x05: - return pcnet_pci_regs[0x05] & 0x01; - case 0x06: - return 0x80; - case 0x07: - return 2; - case 0x08: - return (dev->board == DEV_AM79C973) ? 0x40 : 0x10; /*Revision ID*/ - case 0x09: - return 0; /*Programming interface*/ - case 0x0A: - return 0; /*devubclass*/ - case 0x0B: - return 2; /*Class code*/ - case 0x0D: - return pcnet_pci_regs[addr]; - case 0x0E: - return 0; /*Header type */ - case 0x10: - return 1; /*I/O space*/ - case 0x11: - return pcnet_pci_bar[0].addr_regs[1]; - case 0x12: - return pcnet_pci_bar[0].addr_regs[2]; - case 0x13: - return pcnet_pci_bar[0].addr_regs[3]; - case 0x14: - return 0; /*Memory space*/ - case 0x15: - return pcnet_pci_bar[1].addr_regs[1]; - case 0x16: - return pcnet_pci_bar[1].addr_regs[2]; - case 0x17: - return pcnet_pci_bar[1].addr_regs[3]; - case 0x2C: - return 0x22; - case 0x2D: - return 0x10; - case 0x2E: - return 0x00; - case 0x2F: - return 0x20; - case 0x3C: - return dev->base_irq; - case 0x3D: - return PCI_INTA; - case 0x3E: - return 0x06; - case 0x3F: - return 0xff; + case 0x00: + return 0x22; + case 0x01: + return 0x10; + case 0x02: + return 0x00; + case 0x03: + return 0x20; + case 0x04: + return pcnet_pci_regs[0x04] & 0x57; /*Respond to IO and memory accesses*/ + case 0x05: + return pcnet_pci_regs[0x05] & 0x01; + case 0x06: + return 0x80; + case 0x07: + return 2; + case 0x08: + return (dev->board == DEV_AM79C973) ? 0x40 : 0x10; /*Revision ID*/ + case 0x09: + return 0; /*Programming interface*/ + case 0x0A: + return 0; /*devubclass*/ + case 0x0B: + return 2; /*Class code*/ + case 0x0D: + return pcnet_pci_regs[addr]; + case 0x0E: + return 0; /*Header type */ + case 0x10: + return 1; /*I/O space*/ + case 0x11: + return pcnet_pci_bar[0].addr_regs[1]; + case 0x12: + return pcnet_pci_bar[0].addr_regs[2]; + case 0x13: + return pcnet_pci_bar[0].addr_regs[3]; + case 0x14: + return 0; /*Memory space*/ + case 0x15: + return pcnet_pci_bar[1].addr_regs[1]; + case 0x16: + return pcnet_pci_bar[1].addr_regs[2]; + case 0x17: + return pcnet_pci_bar[1].addr_regs[3]; + case 0x2C: + return 0x22; + case 0x2D: + return 0x10; + case 0x2E: + return 0x00; + case 0x2F: + return 0x20; + case 0x3C: + return dev->base_irq; + case 0x3D: + return PCI_INTA; + case 0x3E: + return 0x06; + case 0x3F: + return 0xff; + + default: + break; } - return(0); + return 0; } static void pcnet_pnp_config_changed(uint8_t ld, isapnp_device_config_t *config, void *priv) { if (ld) - return; + return; nic_t *dev = (nic_t *) priv; dev->base_address = 0; - dev->base_irq = 0; - dev->dma_channel = -1; + dev->base_irq = 0; + dev->dma_channel = -1; if (dev->base_address) { - pcnet_ioremove(dev, dev->base_address, 0x20); - dev->base_address = 0; + pcnet_ioremove(dev, dev->base_address, 0x20); + dev->base_address = 0; } if (config->activate) { - dev->base_address = config->io[0].base; - if (dev->base_address != ISAPNP_IO_DISABLED) - pcnet_ioset(dev, dev->base_address, 0x20); + dev->base_address = config->io[0].base; + if (dev->base_address != ISAPNP_IO_DISABLED) + pcnet_ioset(dev, dev->base_address, 0x20); - dev->base_irq = config->irq[0].irq; - dev->dma_channel = config->dma[0].dma; - if (dev->dma_channel == ISAPNP_DMA_DISABLED) - dev->dma_channel = -1; + dev->base_irq = config->irq[0].irq; + dev->dma_channel = config->dma[0].dma; + if (dev->dma_channel == ISAPNP_DMA_DISABLED) + dev->dma_channel = -1; - /* Update PnP register mirrors in ROM. */ - dev->aPROM[32] = dev->base_address >> 8; - dev->aPROM[33] = dev->base_address; - dev->aPROM[34] = dev->base_irq; - dev->aPROM[35] = (config->irq[0].level << 1) | config->irq[0].type; - dev->aPROM[36] = (dev->dma_channel == -1) ? ISAPNP_DMA_DISABLED : dev->dma_channel; + /* Update PnP register mirrors in ROM. */ + dev->aPROM[32] = dev->base_address >> 8; + dev->aPROM[33] = dev->base_address; + dev->aPROM[34] = dev->base_irq; + dev->aPROM[35] = (config->irq[0].level << 1) | config->irq[0].type; + dev->aPROM[36] = (dev->dma_channel == -1) ? ISAPNP_DMA_DISABLED : dev->dma_channel; } } static uint8_t pcnet_pnp_read_vendor_reg(uint8_t ld, uint8_t reg, void *priv) { - nic_t *dev = (nic_t *) priv; + const nic_t *dev = (nic_t *) priv; if (!ld && (reg == 0xf0)) - return dev->aPROM[50]; + return dev->aPROM[50]; else - return 0x00; + return 0x00; } static void pcnet_pnp_write_vendor_reg(uint8_t ld, uint8_t reg, uint8_t val, void *priv) { if (ld) - return; + return; nic_t *dev = (nic_t *) priv; if (reg == 0xf0) - dev->aPROM[50] = val & 0x1f; + dev->aPROM[50] = val & 0x1f; } /** @@ -2796,11 +2793,11 @@ pcnet_pnp_write_vendor_reg(uint8_t ld, uint8_t reg, uint8_t val, void *priv) * * @param pThis The PCnet shared instance data. */ -static void +static void pcnetTempLinkDown(nic_t *dev) { if (dev->fLinkUp) { - dev->fLinkTempDown = 1; + dev->fLinkTempDown = 1; dev->cLinkDownReported = 0; dev->aCSR[0] |= 0x8000 | 0x2000; /* ERR | CERR (this is probably wrong) */ timer_set_delay_u64(&dev->timer_restore, (dev->cMsLinkUpDelay * 1000) * TIMER_USEC); @@ -2830,48 +2827,36 @@ pcnetCanReceive(nic_t *dev) if (dev->fSignalRxMiss) dev->aCSR[0] |= 0x1000; /* Set MISS flag */ } else - rc = 1; + rc = 1; } return rc; } - static int -pcnetWaitReceiveAvail(void *priv) +pcnetSetLinkState(void *priv, uint32_t link_state) { nic_t *dev = (nic_t *) priv; - dev->fMaybeOutOfSpace = !pcnetCanReceive(dev); - - return dev->fMaybeOutOfSpace; -} - -static int -pcnetSetLinkState(void *priv) -{ - nic_t *dev = (nic_t *) priv; - int fLinkUp; - - if (dev->fLinkTempDown) { - pcnetTempLinkDown(dev); - return 1; + if (link_state & NET_LINK_TEMP_DOWN) { + pcnetTempLinkDown(dev); + return 1; } - - fLinkUp = (dev->fLinkUp && !dev->fLinkTempDown); - if (dev->fLinkUp != fLinkUp) { - dev->fLinkUp = fLinkUp; - if (fLinkUp) { - dev->fLinkTempDown = 1; - dev->cLinkDownReported = 0; - dev->aCSR[0] |= 0x8000 | 0x2000; /* ERR | CERR (this is probably wrong) */ - timer_set_delay_u64(&dev->timer_restore, (dev->cMsLinkUpDelay * 1000) * TIMER_USEC); - } else { - dev->cLinkDownReported = 0; - dev->aCSR[0] |= 0x8000 | 0x2000; /* ERR | CERR (this is probably wrong) */ - } + + bool link_up = !(link_state & NET_LINK_DOWN); + if (dev->fLinkUp != link_up) { + dev->fLinkUp = link_up; + if (link_up) { + dev->fLinkTempDown = 1; + dev->cLinkDownReported = 0; + dev->aCSR[0] |= 0x8000 | 0x2000; + timer_set_delay_u64(&dev->timer_restore, (dev->cMsLinkUpDelay * 1000) * TIMER_USEC); + } else { + dev->cLinkDownReported = 0; + dev->aCSR[0] |= 0x8000 | 0x2000; + } } - + return 0; } @@ -2889,14 +2874,14 @@ static void pcnetTimerRestore(void *priv) { nic_t *dev = (nic_t *) priv; - + if (dev->cLinkDownReported <= PCNET_MAX_LINKDOWN_REPORTED) { - timer_advance_u64(&dev->timer_restore, 1500000 * TIMER_USEC); + timer_advance_u64(&dev->timer_restore, 1500000 * TIMER_USEC); } else { - dev->fLinkTempDown = 0; - if (dev->fLinkUp) { - dev->aCSR[0] &= ~(0x8000 | 0x2000); /* ERR | CERR - probably not 100% correct either... */ - } + dev->fLinkTempDown = 0; + if (dev->fLinkUp) { + dev->aCSR[0] &= ~(0x8000 | 0x2000); /* ERR | CERR - probably not 100% correct either... */ + } } } @@ -2904,13 +2889,13 @@ static void * pcnet_init(const device_t *info) { uint32_t mac; - nic_t *dev; - int c; + nic_t *dev; + int c; uint16_t checksum; dev = malloc(sizeof(nic_t)); memset(dev, 0x00, sizeof(nic_t)); - dev->name = info->name; + dev->name = info->name; dev->board = info->local; dev->is_pci = !!(info->flags & DEVICE_PCI); @@ -2918,26 +2903,26 @@ pcnet_init(const device_t *info) dev->is_isa = !!(info->flags & (DEVICE_ISA | DEVICE_AT)); if (dev->is_pci || dev->is_vlb) - dev->transfer_size = 4; + dev->transfer_size = 4; else - dev->transfer_size = 2; + dev->transfer_size = 2; if (dev->is_pci) { - pcnet_mem_init(dev, 0x0fffff00); - pcnet_mem_disable(dev); + pcnet_mem_init(dev, 0x0fffff00); + pcnet_mem_disable(dev); } - - dev->fLinkUp = 1; + + dev->fLinkUp = 1; dev->cMsLinkUpDelay = 5000; - + if (dev->board == DEV_AM79C960_EB) { - dev->maclocal[0] = 0x02; /* 02:07:01 (Racal OID) */ - dev->maclocal[1] = 0x07; - dev->maclocal[2] = 0x01; + dev->maclocal[0] = 0x02; /* 02:07:01 (Racal OID) */ + dev->maclocal[1] = 0x07; + dev->maclocal[2] = 0x01; } else { - dev->maclocal[0] = 0x00; /* 00:0C:87 (AMD OID) */ - dev->maclocal[1] = 0x0C; - dev->maclocal[2] = 0x87; + dev->maclocal[0] = 0x00; /* 00:0C:87 (AMD OID) */ + dev->maclocal[1] = 0x0C; + dev->maclocal[2] = 0x87; } /* See if we have a local MAC address configured. */ @@ -2945,18 +2930,18 @@ pcnet_init(const device_t *info) /* Set up our BIA. */ if (mac & 0xff000000) { - /* Generate new local MAC. */ - dev->maclocal[3] = random_generate(); - dev->maclocal[4] = random_generate(); - dev->maclocal[5] = random_generate(); - mac = (((int) dev->maclocal[3]) << 16); - mac |= (((int) dev->maclocal[4]) << 8); - mac |= ((int) dev->maclocal[5]); - device_set_config_mac("mac", mac); + /* Generate new local MAC. */ + dev->maclocal[3] = random_generate(); + dev->maclocal[4] = random_generate(); + dev->maclocal[5] = random_generate(); + mac = (((int) dev->maclocal[3]) << 16); + mac |= (((int) dev->maclocal[4]) << 8); + mac |= ((int) dev->maclocal[5]); + device_set_config_mac("mac", mac); } else { - dev->maclocal[3] = (mac>>16) & 0xff; - dev->maclocal[4] = (mac>>8) & 0xff; - dev->maclocal[5] = (mac & 0xff); + dev->maclocal[3] = (mac >> 16) & 0xff; + dev->maclocal[4] = (mac >> 8) & 0xff; + dev->maclocal[5] = (mac & 0xff); } memcpy(dev->aPROM, dev->maclocal, sizeof(dev->maclocal)); @@ -2970,300 +2955,310 @@ pcnet_init(const device_t *info) /* Hardware ID: must be 11h if compatibility to AMD drivers is desired */ /* 0x00/0xFF=ISA, 0x01=PnP, 0x10=VLB, 0x11=PCI */ if (dev->is_pci) - dev->aPROM[9] = 0x11; + dev->aPROM[9] = 0x11; else if (dev->is_vlb) - dev->aPROM[9] = 0x10; + dev->aPROM[9] = 0x10; else if (dev->board == DEV_AM79C961) - dev->aPROM[9] = 0x01; + dev->aPROM[9] = 0x01; else - dev->aPROM[9] = 0x00; + dev->aPROM[9] = 0x00; /* User programmable space, init with 0 */ dev->aPROM[10] = dev->aPROM[11] = 0x00; if (dev->board == DEV_AM79C960_EB) { dev->aPROM[14] = 0x52; - dev->aPROM[15] = 0x44; /* NI6510 EtherBlaster 'RD' signature. */ + dev->aPROM[15] = 0x44; /* NI6510 EtherBlaster 'RD' signature. */ } else { - /* Must be ASCII W (57h) if compatibility to AMD - driver software is desired */ - dev->aPROM[14] = dev->aPROM[15] = 0x57; + /* Must be ASCII W (57h) if compatibility to AMD + driver software is desired */ + dev->aPROM[14] = dev->aPROM[15] = 0x57; } for (c = 0, checksum = 0; c < 16; c++) - checksum += dev->aPROM[c]; + checksum += dev->aPROM[c]; - *(uint16_t *)&dev->aPROM[12] = cpu_to_le16(checksum); + *(uint16_t *) &dev->aPROM[12] = cpu_to_le16(checksum); /* * Make this device known to the I/O system. * PCI devices start with address spaces inactive. */ if (dev->is_pci) { - /* - * Configure the PCI space registers. - * - * We do this here, so the I/O routines are generic. - */ + /* + * Configure the PCI space registers. + * + * We do this here, so the I/O routines are generic. + */ - /* Enable our address space in PCI. */ - pcnet_pci_bar[0].addr_regs[0] = 1; - pcnet_pci_bar[1].addr_regs[0] = 0; - pcnet_pci_regs[0x04] = 3; + /* Enable our address space in PCI. */ + pcnet_pci_bar[0].addr_regs[0] = 1; + pcnet_pci_bar[1].addr_regs[0] = 0; + pcnet_pci_regs[0x04] = 3; - /* Add device to the PCI bus, keep its slot number. */ - dev->card = pci_add_card(PCI_ADD_NORMAL, - pcnet_pci_read, pcnet_pci_write, dev); + /* Add device to the PCI bus, keep its slot number. */ + pci_add_card(PCI_ADD_NORMAL, pcnet_pci_read, pcnet_pci_write, dev, &dev->pci_slot); } else if (dev->board == DEV_AM79C961) { - dev->dma_channel = -1; + dev->dma_channel = -1; - /* Weird secondary checksum. The datasheet isn't clear on what - role it might play with the PnP register mirrors before it. */ - for (c = 0, checksum = 0; c < 54; c++) - checksum += dev->aPROM[c]; + /* Weird secondary checksum. The datasheet isn't clear on what + role it might play with the PnP register mirrors before it. */ + for (c = 0, checksum = 0; c < 54; c++) + checksum += dev->aPROM[c]; - dev->aPROM[51] = checksum; + dev->aPROM[51] = checksum; - memcpy(&dev->aPROM[0x40], am79c961_pnp_rom, sizeof(am79c961_pnp_rom)); - isapnp_add_card(&dev->aPROM[0x40], sizeof(am79c961_pnp_rom), pcnet_pnp_config_changed, NULL, pcnet_pnp_read_vendor_reg, pcnet_pnp_write_vendor_reg, dev); + memcpy(&dev->aPROM[0x40], am79c961_pnp_rom, sizeof(am79c961_pnp_rom)); + isapnp_add_card(&dev->aPROM[0x40], sizeof(am79c961_pnp_rom), pcnet_pnp_config_changed, NULL, pcnet_pnp_read_vendor_reg, pcnet_pnp_write_vendor_reg, dev); } else { - dev->base_address = device_get_config_hex16("base"); - dev->base_irq = device_get_config_int("irq"); - if (dev->is_vlb) - dev->dma_channel = -1; - else - dev->dma_channel = device_get_config_int("dma"); - pcnet_ioset(dev, dev->base_address, 0x20); + dev->base_address = device_get_config_hex16("base"); + dev->base_irq = device_get_config_int("irq"); + if (dev->is_vlb) + dev->dma_channel = -1; + else + dev->dma_channel = device_get_config_int("dma"); + pcnet_ioset(dev, dev->base_address, 0x20); } - pcnetlog(2, "%s: I/O=%04x, IRQ=%d, MAC=%02x:%02x:%02x:%02x:%02x:%02x\n", - dev->name, dev->base_address, dev->base_irq, - dev->aPROM[0], dev->aPROM[1], dev->aPROM[2], - dev->aPROM[3], dev->aPROM[4], dev->aPROM[5]); + pcnet_log(2, "%s: I/O=%04x, IRQ=%d, MAC=%02x:%02x:%02x:%02x:%02x:%02x\n", + dev->name, dev->base_address, dev->base_irq, + dev->aPROM[0], dev->aPROM[1], dev->aPROM[2], + dev->aPROM[3], dev->aPROM[4], dev->aPROM[5]); - pcnetlog(1, "%s: %s attached IO=0x%X IRQ=%d\n", dev->name, - dev->is_pci?"PCI":"VLB/ISA", dev->base_address, dev->base_irq); + pcnet_log(1, "%s: %s attached IO=0x%X IRQ=%d\n", dev->name, + dev->is_pci ? "PCI" : "VLB/ISA", dev->base_address, dev->base_irq); /* Reset the board. */ pcnetHardReset(dev); /* Attach ourselves to the network module. */ - network_attach(dev, dev->aPROM, pcnetReceiveNoSync, pcnetWaitReceiveAvail, pcnetSetLinkState); + dev->netcard = network_attach(dev, dev->aPROM, pcnetReceiveNoSync, pcnetSetLinkState); + dev->netcard->byte_period = (dev->board == DEV_AM79C973) ? NET_PERIOD_100M : NET_PERIOD_10M; + + timer_add(&dev->timer, pcnetPollTimer, dev, 0); if (dev->board == DEV_AM79C973) timer_add(&dev->timer_soft_int, pcnetTimerSoftInt, dev, 0); timer_add(&dev->timer_restore, pcnetTimerRestore, dev, 0); - return(dev); + return dev; } - static void pcnet_close(void *priv) { - nic_t *dev = (nic_t *)priv; + nic_t *dev = (nic_t *) priv; + + pcnet_log(1, "%s: closed\n", dev->name); + + netcard_close(dev->netcard); - pcnetlog(1, "%s: closed\n", dev->name); - - /* Make sure the platform layer is shut down. */ - network_close(); - if (dev) { - free(dev); - dev = NULL; - + free(dev); + dev = NULL; } } - -static const device_config_t pcnet_pci_config[] = -{ - { - "mac", "MAC Address", CONFIG_MAC, "", -1 - }, - { - "", "", -1 - } +// clang-format off +static const device_config_t pcnet_pci_config[] = { + { + .name = "mac", + .description = "MAC Address", + .type = CONFIG_MAC, + .default_string = "", + .default_int = -1 + }, + { .name = "", .description = "", .type = CONFIG_END } }; - -static const device_config_t pcnet_isa_config[] = -{ - { - "base", "Address", CONFIG_HEX16, "", 0x300, "", { 0 }, - { - { - "0x300", 0x300 - }, - { - "0x320", 0x320 - }, - { - "0x340", 0x340 - }, - { - "0x360", 0x360 - }, - { - "" - } - }, - }, - { - "irq", "IRQ", CONFIG_SELECTION, "", 3, "", { 0 }, - { - { - "IRQ 3", 3 - }, - { - "IRQ 4", 4 - }, - { - "IRQ 5", 5 - }, - { - "IRQ 9", 9 - }, - { - "" - } - }, - }, - { - "dma", "DMA channel", CONFIG_SELECTION, "", 5, "", { 0 }, - { - { - "DMA 3", 3 - }, - { - "DMA 5", 5 - }, - { - "DMA 6", 6 - }, - { - "DMA 7", 7 - }, - { - "" - } - }, - }, - { - "mac", "MAC Address", CONFIG_MAC, "", -1 - }, - { - "", "", -1 - } +static const device_config_t pcnet_isa_config[] = { + { + .name = "base", + .description = "Address", + .type = CONFIG_HEX16, + .default_string = "", + .default_int = 0x300, + .file_filter = "", + .spinner = { 0 }, + .selection = { + { .description = "0x300", .value = 0x300 }, + { .description = "0x320", .value = 0x320 }, + { .description = "0x340", .value = 0x340 }, + { .description = "0x360", .value = 0x360 }, + { .description = "" } + }, + }, + { + .name = "irq", + .description = "IRQ", + .type = CONFIG_SELECTION, + .default_string = "", + .default_int = 3, + .file_filter = "", + .spinner = { 0 }, + .selection = { + { .description = "IRQ 3", .value = 3 }, + { .description = "IRQ 4", .value = 4 }, + { .description = "IRQ 5", .value = 5 }, + { .description = "IRQ 9", .value = 9 }, + { .description = "IRQ 10", .value = 10 }, + { .description = "IRQ 11", .value = 11 }, + { .description = "" } + }, + }, + { + .name = "dma", + .description = "DMA channel", + .type = CONFIG_SELECTION, + .default_string = "", + .default_int = 5, + .file_filter = "", + .spinner = { 0 }, + .selection = { + { .description = "DMA 3", .value = 3 }, + { .description = "DMA 5", .value = 5 }, + { .description = "DMA 6", .value = 6 }, + { .description = "DMA 7", .value = 7 }, + { .description = "" } + }, + }, + { + .name = "mac", + .description = "MAC Address", + .type = CONFIG_MAC, + .default_string = "", + .default_int = -1 + }, + { .name = "", .description = "", .type = CONFIG_END } }; -static const device_config_t pcnet_vlb_config[] = -{ - { - "base", "Address", CONFIG_HEX16, "", 0x300, "", { 0 }, - { - { - "0x300", 0x300 - }, - { - "0x320", 0x320 - }, - { - "0x340", 0x340 - }, - { - "0x360", 0x360 - }, - { - "" - } - }, - }, - { - "irq", "IRQ", CONFIG_SELECTION, "", 3, "", { 0 }, - { - { - "IRQ 3", 3 - }, - { - "IRQ 4", 4 - }, - { - "IRQ 5", 5 - }, - { - "IRQ 9", 9 - }, - { - "" - } - }, - }, - { - "mac", "MAC Address", CONFIG_MAC, "", -1 - }, - { - "", "", -1 - } +static const device_config_t pcnet_vlb_config[] = { + { + .name = "base", + .description = "Address", + .type = CONFIG_HEX16, + .default_string = "", + .default_int = 0x300, + .file_filter = "", + .spinner = { 0 }, + .selection = { + { .description = "0x300", .value = 0x300 }, + { .description = "0x320", .value = 0x320 }, + { .description = "0x340", .value = 0x340 }, + { .description = "0x360", .value = 0x360 }, + { .description = "" } + }, + }, + { + .name = "irq", + .description = "IRQ", + .type = CONFIG_SELECTION, + .default_string = "", + .default_int = 3, + .file_filter = "", + .spinner = { 0 }, + .selection = { + { .description = "IRQ 3", .value = 3 }, + { .description = "IRQ 4", .value = 4 }, + { .description = "IRQ 5", .value = 5 }, + { .description = "IRQ 9", .value = 9 }, + { .description = "IRQ 10", .value = 10 }, + { .description = "IRQ 11", .value = 11 }, + { .description = "" } + }, + }, + { + .name = "mac", + .description = "MAC Address", + .type = CONFIG_MAC, + .default_string = "", + .default_int = -1 + }, + { .name = "", .description = "", .type = CONFIG_END } }; +// clang-format on const device_t pcnet_am79c960_device = { - "AMD PCnet-ISA", - "pcnetisa", - DEVICE_AT | DEVICE_ISA, - DEV_AM79C960, - pcnet_init, pcnet_close, NULL, - { NULL }, NULL, NULL, - pcnet_isa_config + .name = "AMD PCnet-ISA", + .internal_name = "pcnetisa", + .flags = DEVICE_AT | DEVICE_ISA, + .local = DEV_AM79C960, + .init = pcnet_init, + .close = pcnet_close, + .reset = NULL, + { .available = NULL }, + .speed_changed = NULL, + .force_redraw = NULL, + .config = pcnet_isa_config }; const device_t pcnet_am79c960_eb_device = { - "Racal Interlan EtherBlaster", - "pcnetracal", - DEVICE_AT | DEVICE_ISA, - DEV_AM79C960_EB, - pcnet_init, pcnet_close, NULL, - { NULL }, NULL, NULL, - pcnet_isa_config + .name = "Racal Interlan EtherBlaster", + .internal_name = "pcnetracal", + .flags = DEVICE_AT | DEVICE_ISA, + .local = DEV_AM79C960_EB, + .init = pcnet_init, + .close = pcnet_close, + .reset = NULL, + { .available = NULL }, + .speed_changed = NULL, + .force_redraw = NULL, + .config = pcnet_isa_config }; const device_t pcnet_am79c960_vlb_device = { - "AMD PCnet-VL", - "pcnetvlb", - DEVICE_VLB, - DEV_AM79C960_VLB, - pcnet_init, pcnet_close, NULL, - { NULL }, NULL, NULL, - pcnet_vlb_config + .name = "AMD PCnet-VL", + .internal_name = "pcnetvlb", + .flags = DEVICE_VLB, + .local = DEV_AM79C960_VLB, + .init = pcnet_init, + .close = pcnet_close, + .reset = NULL, + { .available = NULL }, + .speed_changed = NULL, + .force_redraw = NULL, + .config = pcnet_vlb_config }; const device_t pcnet_am79c961_device = { - "AMD PCnet-ISA+", - "pcnetisaplus", - DEVICE_AT | DEVICE_ISA, - DEV_AM79C961, - pcnet_init, pcnet_close, NULL, - { NULL }, NULL, NULL, - pcnet_pci_config + .name = "AMD PCnet-ISA+", + .internal_name = "pcnetisaplus", + .flags = DEVICE_AT | DEVICE_ISA, + .local = DEV_AM79C961, + .init = pcnet_init, + .close = pcnet_close, + .reset = NULL, + { .available = NULL }, + .speed_changed = NULL, + .force_redraw = NULL, + .config = pcnet_pci_config }; const device_t pcnet_am79c970a_device = { - "AMD PCnet-PCI II", - "pcnetpci", - DEVICE_PCI, - DEV_AM79C970A, - pcnet_init, pcnet_close, NULL, - { NULL }, NULL, NULL, - pcnet_pci_config + .name = "AMD PCnet-PCI II", + .internal_name = "pcnetpci", + .flags = DEVICE_PCI, + .local = DEV_AM79C970A, + .init = pcnet_init, + .close = pcnet_close, + .reset = NULL, + { .available = NULL }, + .speed_changed = NULL, + .force_redraw = NULL, + .config = pcnet_pci_config }; const device_t pcnet_am79c973_device = { - "AMD PCnet-FAST III", - "pcnetfast", - DEVICE_PCI, - DEV_AM79C973, - pcnet_init, pcnet_close, NULL, - { NULL }, NULL, NULL, - pcnet_pci_config + .name = "AMD PCnet-FAST III", + .internal_name = "pcnetfast", + .flags = DEVICE_PCI, + .local = DEV_AM79C973, + .init = pcnet_init, + .close = pcnet_close, + .reset = NULL, + { .available = NULL }, + .speed_changed = NULL, + .force_redraw = NULL, + .config = pcnet_pci_config }; diff --git a/src/network/net_plip.c b/src/network/net_plip.c index f0af9dee5..f622d455b 100644 --- a/src/network/net_plip.c +++ b/src/network/net_plip.c @@ -1,21 +1,21 @@ /* - * 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. + * 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. + * This file is part of the 86Box distribution. * - * Emulation of a PLIP parallel port network device. + * Emulation of a PLIP parallel port network device. * - * Tested against the Linux plip.c driver and the DOS plip.com - * packet driver. PLIP is not particularly fast, as it's a 4-bit - * half-duplex protocol operating over SPP. + * Tested against the Linux plip.c driver and the DOS plip.com + * packet driver. PLIP is not particularly fast, as it's a 4-bit + * half-duplex protocol operating over SPP. * * * - * Author: RichardG, - * Copyright 2020 RichardG. + * Authors: RichardG, + * Copyright 2020 RichardG. */ #include #include @@ -31,12 +31,14 @@ #include <86box/timer.h> #include <86box/pit.h> #include <86box/device.h> +#include <86box/thread.h> +#include <86box/timer.h> #include <86box/network.h> #include <86box/net_plip.h> - +#include <86box/plat_unused.h> enum { - PLIP_START = 0x00, + PLIP_START = 0x00, PLIP_TX_LEN_LSB_LOW = 0x10, PLIP_TX_LEN_LSB_HIGH, PLIP_TX_LEN_MSB_LOW, @@ -56,27 +58,34 @@ enum { PLIP_END = 0x40 }; -typedef struct -{ - uint8_t mac[6]; +typedef struct plip_t { + uint8_t mac[6]; - void *lpt; - pc_timer_t rx_timer; - pc_timer_t timeout_timer; - uint8_t status, ctrl; + void *lpt; + pc_timer_t rx_timer; + pc_timer_t timeout_timer; + uint8_t status; + uint8_t ctrl; - uint8_t state, ack, tx_checksum, tx_checksum_calc, *tx_pkt; - uint16_t tx_len, tx_ptr; + uint8_t state; + uint8_t ack; + uint8_t tx_checksum; + uint8_t tx_checksum_calc; + uint8_t *tx_pkt; + uint16_t tx_len; + uint16_t tx_ptr; - uint8_t *rx_pkt, rx_checksum, rx_return_state; - uint16_t rx_len, rx_ptr; + uint8_t *rx_pkt; + uint8_t rx_checksum; + uint8_t rx_return_state; + uint16_t rx_len; + uint16_t rx_ptr; + netcard_t *card; } plip_t; +static void plip_receive_packet(plip_t *dev); -static void plip_receive_packet(plip_t *dev); - -plip_t *instance; - +plip_t *instance; #ifdef ENABLE_PLIP_LOG int plip_do_log = ENABLE_PLIP_LOG; @@ -87,16 +96,15 @@ plip_log(uint8_t lvl, const char *fmt, ...) va_list ap; if (plip_do_log >= lvl) { - va_start(ap, fmt); - pclog_ex(fmt, ap); - va_end(ap); + va_start(ap, fmt); + pclog_ex(fmt, ap); + va_end(ap); } } #else -#define plip_log(lvl, fmt, ...) +# define plip_log(lvl, fmt, ...) #endif - static void timeout_timer(void *priv) { @@ -105,24 +113,21 @@ timeout_timer(void *priv) plip_log(1, "PLIP: timeout at state %d status %02X\n", dev->state, dev->status); /* Throw everything out the window. */ - dev->state = PLIP_START; + dev->state = PLIP_START; dev->status = 0x80; if (dev->tx_pkt) { - free(dev->tx_pkt); - dev->tx_pkt = NULL; + free(dev->tx_pkt); + dev->tx_pkt = NULL; } if (dev->rx_pkt) { - free(dev->rx_pkt); - dev->rx_pkt = NULL; + free(dev->rx_pkt); + dev->rx_pkt = NULL; } - network_rx_pause = 0; - timer_disable(&dev->timeout_timer); } - static void plip_write_data(uint8_t val, void *priv) { @@ -131,220 +136,222 @@ plip_write_data(uint8_t val, void *priv) plip_log(3, "PLIP: write_data(%02X)\n", val); switch (dev->state) { - case PLIP_START: - if (val == 0x08) { /* D3/ACK wakes us up */ - plip_log(2, "PLIP: ACK wakeup\n"); - dev->state = PLIP_TX_LEN_LSB_LOW; - dev->status = 0x08; - break; - } - return; + case PLIP_START: + if (val == 0x08) { /* D3/ACK wakes us up */ + plip_log(2, "PLIP: ACK wakeup\n"); + dev->state = PLIP_TX_LEN_LSB_LOW; + dev->status = 0x08; + break; + } + return; - case PLIP_TX_LEN_LSB_LOW: - if (!(val & 0x10)) - return; /* D4/BUSY not high yet */ - dev->tx_len = val & 0xf; - plip_log(2, "PLIP: tx_len = %04X (1/4)\n", dev->tx_len); - dev->state = PLIP_TX_LEN_LSB_HIGH; - dev->status &= ~0x88; - break; + case PLIP_TX_LEN_LSB_LOW: + if (!(val & 0x10)) + return; /* D4/BUSY not high yet */ + dev->tx_len = val & 0xf; + plip_log(2, "PLIP: tx_len = %04X (1/4)\n", dev->tx_len); + dev->state = PLIP_TX_LEN_LSB_HIGH; + dev->status &= ~0x88; + break; - case PLIP_TX_LEN_LSB_HIGH: - if (val & 0x10) - return; /* D4/BUSY not low yet */ - dev->tx_len |= (val & 0xf) << 4; - plip_log(2, "PLIP: tx_len = %04X (2/4)\n", dev->tx_len); - dev->state = PLIP_TX_LEN_MSB_LOW; - dev->status |= 0x80; - break; + case PLIP_TX_LEN_LSB_HIGH: + if (val & 0x10) + return; /* D4/BUSY not low yet */ + dev->tx_len |= (val & 0xf) << 4; + plip_log(2, "PLIP: tx_len = %04X (2/4)\n", dev->tx_len); + dev->state = PLIP_TX_LEN_MSB_LOW; + dev->status |= 0x80; + break; - case PLIP_TX_LEN_MSB_LOW: - if (!(val & 0x10)) - return; /* D4/BUSY not high yet */ - dev->tx_len |= (val & 0xf) << 8; - plip_log(2, "PLIP: tx_len = %04X (3/4)\n", dev->tx_len); - dev->state = PLIP_TX_LEN_MSB_HIGH; - dev->status &= ~0x80; - break; + case PLIP_TX_LEN_MSB_LOW: + if (!(val & 0x10)) + return; /* D4/BUSY not high yet */ + dev->tx_len |= (val & 0xf) << 8; + plip_log(2, "PLIP: tx_len = %04X (3/4)\n", dev->tx_len); + dev->state = PLIP_TX_LEN_MSB_HIGH; + dev->status &= ~0x80; + break; - case PLIP_TX_LEN_MSB_HIGH: - if (val & 0x10) - return; /* D4/BUSY not low yet */ - dev->tx_len |= (val & 0xf) << 12; - plip_log(2, "PLIP: tx_len = %04X (4/4)\n", dev->tx_len); + case PLIP_TX_LEN_MSB_HIGH: + if (val & 0x10) + return; /* D4/BUSY not low yet */ + dev->tx_len |= (val & 0xf) << 12; + plip_log(2, "PLIP: tx_len = %04X (4/4)\n", dev->tx_len); - /* We have the length, allocate a packet. */ - if (!(dev->tx_pkt = malloc(dev->tx_len))) /* unlikely */ - fatal("PLIP: unable to allocate tx_pkt\n"); - dev->tx_ptr = 0; - dev->tx_checksum_calc = 0; + /* We have the length, allocate a packet. */ + if (!(dev->tx_pkt = malloc(dev->tx_len))) /* unlikely */ + fatal("PLIP: unable to allocate tx_pkt\n"); + dev->tx_ptr = 0; + dev->tx_checksum_calc = 0; - dev->state = PLIP_TX_DATA_LOW; - dev->status |= 0x80; - break; + dev->state = PLIP_TX_DATA_LOW; + dev->status |= 0x80; + break; - case PLIP_TX_DATA_LOW: - if (!(val & 0x10)) - return; /* D4/BUSY not high yet */ - dev->tx_pkt[dev->tx_ptr] = val & 0x0f; - plip_log(2, "PLIP: tx_pkt[%d] = %02X (1/2)\n", dev->tx_ptr, dev->tx_pkt[dev->tx_ptr]); - dev->state = PLIP_TX_DATA_HIGH; - dev->status &= ~0x80; - break; + case PLIP_TX_DATA_LOW: + if (!(val & 0x10)) + return; /* D4/BUSY not high yet */ + dev->tx_pkt[dev->tx_ptr] = val & 0x0f; + plip_log(2, "PLIP: tx_pkt[%d] = %02X (1/2)\n", dev->tx_ptr, dev->tx_pkt[dev->tx_ptr]); + dev->state = PLIP_TX_DATA_HIGH; + dev->status &= ~0x80; + break; - case PLIP_TX_DATA_HIGH: - if (val & 0x10) - return; /* D4/BUSY not low yet */ - dev->tx_pkt[dev->tx_ptr] |= (val & 0x0f) << 4; - plip_log(2, "PLIP: tx_pkt[%d] = %02X (2/2)\n", dev->tx_ptr, dev->tx_pkt[dev->tx_ptr]); - dev->tx_checksum_calc += dev->tx_pkt[dev->tx_ptr++]; + case PLIP_TX_DATA_HIGH: + if (val & 0x10) + return; /* D4/BUSY not low yet */ + dev->tx_pkt[dev->tx_ptr] |= (val & 0x0f) << 4; + plip_log(2, "PLIP: tx_pkt[%d] = %02X (2/2)\n", dev->tx_ptr, dev->tx_pkt[dev->tx_ptr]); + dev->tx_checksum_calc += dev->tx_pkt[dev->tx_ptr++]; - /* Are we done yet? */ - if (dev->tx_ptr < dev->tx_len) /* no, receive another byte */ - dev->state = PLIP_TX_DATA_LOW; - else /* yes, move on to checksum */ - dev->state = PLIP_TX_CHECKSUM_LOW; - dev->status |= 0x80; - break; + /* Are we done yet? */ + if (dev->tx_ptr < dev->tx_len) /* no, receive another byte */ + dev->state = PLIP_TX_DATA_LOW; + else /* yes, move on to checksum */ + dev->state = PLIP_TX_CHECKSUM_LOW; + dev->status |= 0x80; + break; - case PLIP_TX_CHECKSUM_LOW: - if (!(val & 0x10)) - return; /* D4/BUSY not high yet */ - dev->tx_checksum = val & 0x0f; - plip_log(2, "PLIP: tx_checksum = %02X (1/2)\n", dev->tx_checksum); - dev->state = PLIP_TX_CHECKSUM_HIGH; - dev->status &= ~0x80; - break; + case PLIP_TX_CHECKSUM_LOW: + if (!(val & 0x10)) + return; /* D4/BUSY not high yet */ + dev->tx_checksum = val & 0x0f; + plip_log(2, "PLIP: tx_checksum = %02X (1/2)\n", dev->tx_checksum); + dev->state = PLIP_TX_CHECKSUM_HIGH; + dev->status &= ~0x80; + break; - case PLIP_TX_CHECKSUM_HIGH: - if (val & 0x10) - return; /* D4/BUSY not low yet */ - dev->tx_checksum |= (val & 0x0f) << 4; - plip_log(2, "PLIP: tx_checksum = %02X (2/2)\n", dev->tx_checksum); + case PLIP_TX_CHECKSUM_HIGH: + if (val & 0x10) + return; /* D4/BUSY not low yet */ + dev->tx_checksum |= (val & 0x0f) << 4; + plip_log(2, "PLIP: tx_checksum = %02X (2/2)\n", dev->tx_checksum); - /* Verify checksum. */ - if (dev->tx_checksum_calc == dev->tx_checksum) { - /* Make sure we know the other end's MAC address. */ - memcpy(dev->mac, dev->tx_pkt + 6, 6); + /* Verify checksum. */ + if (dev->tx_checksum_calc == dev->tx_checksum) { + /* Make sure we know the other end's MAC address. */ + memcpy(dev->mac, dev->tx_pkt + 6, 6); - /* Transmit packet. */ - plip_log(2, "PLIP: transmitting %d-byte packet\n", dev->tx_len); - network_tx(dev->tx_pkt, dev->tx_len); - } else { - plip_log(1, "PLIP: checksum error: expected %02X, got %02X\n", dev->tx_checksum_calc, dev->tx_checksum); - } + /* Transmit packet. */ + plip_log(2, "PLIP: transmitting %d-byte packet\n", dev->tx_len); + network_tx(dev->card, dev->tx_pkt, dev->tx_len); + } else { + plip_log(1, "PLIP: checksum error: expected %02X, got %02X\n", dev->tx_checksum_calc, dev->tx_checksum); + } - /* We're done with this packet. */ - free(dev->tx_pkt); - dev->tx_pkt = NULL; - dev->tx_len = 0; + /* We're done with this packet. */ + free(dev->tx_pkt); + dev->tx_pkt = NULL; + dev->tx_len = 0; - dev->state = PLIP_END; - dev->status |= 0x80; - break; + dev->state = PLIP_END; + dev->status |= 0x80; + break; - case PLIP_RX_LEN_LSB_LOW: - if (!(val & 0x01)) - return; /* D3/ACK not high yet */ - plip_log(2, "PLIP: rx_len = %04X (1/4)\n", dev->rx_len); - dev->status = (dev->rx_len & 0x0f) << 3; - dev->state = PLIP_RX_LEN_LSB_HIGH; - break; + case PLIP_RX_LEN_LSB_LOW: + if (!(val & 0x01)) + return; /* D3/ACK not high yet */ + plip_log(2, "PLIP: rx_len = %04X (1/4)\n", dev->rx_len); + dev->status = (dev->rx_len & 0x0f) << 3; + dev->state = PLIP_RX_LEN_LSB_HIGH; + break; - case PLIP_RX_LEN_LSB_HIGH: - if (!(val & 0x10)) - return; /* D4/BUSY not high yet */ - plip_log(2, "PLIP: rx_len = %04X (2/4)\n", dev->rx_len); - dev->status = ((dev->rx_len >> 4) & 0x0f) << 3; - dev->status |= 0x80; - dev->state = PLIP_RX_LEN_MSB_LOW; - break; + case PLIP_RX_LEN_LSB_HIGH: + if (!(val & 0x10)) + return; /* D4/BUSY not high yet */ + plip_log(2, "PLIP: rx_len = %04X (2/4)\n", dev->rx_len); + dev->status = ((dev->rx_len >> 4) & 0x0f) << 3; + dev->status |= 0x80; + dev->state = PLIP_RX_LEN_MSB_LOW; + break; - case PLIP_RX_LEN_MSB_LOW: - if (val & 0x10) - return; /* D4/BUSY not low yet */ - plip_log(2, "PLIP: rx_len = %04X (3/4)\n", dev->rx_len); - dev->status = ((dev->rx_len >> 8) & 0x0f) << 3; - dev->state = PLIP_RX_LEN_MSB_HIGH; - break; + case PLIP_RX_LEN_MSB_LOW: + if (val & 0x10) + return; /* D4/BUSY not low yet */ + plip_log(2, "PLIP: rx_len = %04X (3/4)\n", dev->rx_len); + dev->status = ((dev->rx_len >> 8) & 0x0f) << 3; + dev->state = PLIP_RX_LEN_MSB_HIGH; + break; - case PLIP_RX_LEN_MSB_HIGH: - if (!(val & 0x10)) - return; /* D4/BUSY not high yet */ - plip_log(2, "PLIP: rx_len = %04X (4/4)\n", dev->rx_len); - dev->status = ((dev->rx_len >> 12) & 0x0f) << 3; - dev->status |= 0x80; + case PLIP_RX_LEN_MSB_HIGH: + if (!(val & 0x10)) + return; /* D4/BUSY not high yet */ + plip_log(2, "PLIP: rx_len = %04X (4/4)\n", dev->rx_len); + dev->status = ((dev->rx_len >> 12) & 0x0f) << 3; + dev->status |= 0x80; - dev->rx_ptr = 0; - dev->rx_checksum = 0; - dev->state = PLIP_RX_DATA_LOW; - break; + dev->rx_ptr = 0; + dev->rx_checksum = 0; + dev->state = PLIP_RX_DATA_LOW; + break; - case PLIP_RX_DATA_LOW: - if (val & 0x10) - return; /* D4/BUSY not low yet */ - plip_log(2, "PLIP: rx_pkt[%d] = %02X (1/2)\n", dev->rx_ptr, dev->rx_pkt[dev->rx_ptr]); - dev->status = (dev->rx_pkt[dev->rx_ptr] & 0x0f) << 3; - dev->state = PLIP_RX_DATA_HIGH; - break; + case PLIP_RX_DATA_LOW: + if (val & 0x10) + return; /* D4/BUSY not low yet */ + plip_log(2, "PLIP: rx_pkt[%d] = %02X (1/2)\n", dev->rx_ptr, dev->rx_pkt[dev->rx_ptr]); + dev->status = (dev->rx_pkt[dev->rx_ptr] & 0x0f) << 3; + dev->state = PLIP_RX_DATA_HIGH; + break; - case PLIP_RX_DATA_HIGH: - if (!(val & 0x10)) - return; /* D4/BUSY not high yet */ - plip_log(2, "PLIP: rx_pkt[%d] = %02X (2/2)\n", dev->rx_ptr, dev->rx_pkt[dev->rx_ptr]); - dev->status = ((dev->rx_pkt[dev->rx_ptr] >> 4) & 0x0f) << 3; - dev->status |= 0x80; - dev->rx_checksum += dev->rx_pkt[dev->rx_ptr++]; + case PLIP_RX_DATA_HIGH: + if (!(val & 0x10)) + return; /* D4/BUSY not high yet */ + plip_log(2, "PLIP: rx_pkt[%d] = %02X (2/2)\n", dev->rx_ptr, dev->rx_pkt[dev->rx_ptr]); + dev->status = ((dev->rx_pkt[dev->rx_ptr] >> 4) & 0x0f) << 3; + dev->status |= 0x80; + dev->rx_checksum += dev->rx_pkt[dev->rx_ptr++]; - /* Are we done yet? */ - if (dev->rx_ptr < dev->rx_len) /* no, send another byte */ - dev->state = PLIP_RX_DATA_LOW; - else /* yes, move on to checksum */ - dev->state = PLIP_RX_CHECKSUM_LOW; - break; + /* Are we done yet? */ + if (dev->rx_ptr < dev->rx_len) /* no, send another byte */ + dev->state = PLIP_RX_DATA_LOW; + else /* yes, move on to checksum */ + dev->state = PLIP_RX_CHECKSUM_LOW; + break; - case PLIP_RX_CHECKSUM_LOW: - if (val & 0x10) - return; /* D4/BUSY not low yet */ - plip_log(2, "PLIP: rx_checksum = %02X (1/2)\n", dev->rx_checksum); - dev->status = (dev->rx_checksum & 0x0f) << 3; - dev->state = PLIP_RX_CHECKSUM_HIGH; - break; + case PLIP_RX_CHECKSUM_LOW: + if (val & 0x10) + return; /* D4/BUSY not low yet */ + plip_log(2, "PLIP: rx_checksum = %02X (1/2)\n", dev->rx_checksum); + dev->status = (dev->rx_checksum & 0x0f) << 3; + dev->state = PLIP_RX_CHECKSUM_HIGH; + break; - case PLIP_RX_CHECKSUM_HIGH: - if (!(val & 0x10)) - return; /* D4/BUSY not high yet */ - plip_log(2, "PLIP: rx_checksum = %02X (2/2)\n", dev->rx_checksum); - dev->status = ((dev->rx_checksum >> 4) & 0x0f) << 3; - dev->status |= 0x80; + case PLIP_RX_CHECKSUM_HIGH: + if (!(val & 0x10)) + return; /* D4/BUSY not high yet */ + plip_log(2, "PLIP: rx_checksum = %02X (2/2)\n", dev->rx_checksum); + dev->status = ((dev->rx_checksum >> 4) & 0x0f) << 3; + dev->status |= 0x80; - /* We're done with this packet. */ - free(dev->rx_pkt); - dev->rx_pkt = NULL; - dev->rx_len = 0; + /* We're done with this packet. */ + free(dev->rx_pkt); + dev->rx_pkt = NULL; + dev->rx_len = 0; - dev->state = PLIP_END; - break; + dev->state = PLIP_END; + break; - case PLIP_END: - if (val == 0x00) { /* written after TX or RX is done */ - plip_log(2, "PLIP: end\n"); - dev->status = 0x80; - dev->state = PLIP_START; + case PLIP_END: + if (val == 0x00) { /* written after TX or RX is done */ + plip_log(2, "PLIP: end\n"); + dev->status = 0x80; + dev->state = PLIP_START; - timer_set_delay_u64(&dev->rx_timer, ISACONST); /* for DOS */ - } + timer_set_delay_u64(&dev->rx_timer, ISACONST); /* for DOS */ + } - /* Disengage timeout timer. */ - timer_disable(&dev->timeout_timer); - return; + /* Disengage timeout timer. */ + timer_disable(&dev->timeout_timer); + return; + + default: + break; } /* Engage timeout timer unless otherwise specified. */ timer_set_delay_u64(&dev->timeout_timer, 1000000 * TIMER_USEC); } - static void plip_write_ctrl(uint8_t val, void *priv) { @@ -355,46 +362,43 @@ plip_write_ctrl(uint8_t val, void *priv) dev->ctrl = val; if (val & 0x10) /* for Linux */ - timer_set_delay_u64(&dev->rx_timer, ISACONST); + timer_set_delay_u64(&dev->rx_timer, ISACONST); } - static uint8_t plip_read_status(void *priv) { - plip_t *dev = (plip_t *) priv; + const plip_t *dev = (plip_t *) priv; plip_log(3, "PLIP: read_status() = %02X\n", dev->status); return dev->status; } - static void plip_receive_packet(plip_t *dev) { /* At least the Linux driver supports being interrupted in the PLIP_TX_LEN_LSB_LOW state, but let's be safe. */ if (dev->state > PLIP_START) { - plip_log(3, "PLIP: cannot receive, operation already in progress\n"); - return; + plip_log(3, "PLIP: cannot receive, operation already in progress\n"); + return; } if (!dev->rx_pkt || !dev->rx_len) { /* unpause RX queue if there's no packet to receive */ - network_rx_pause = 0; - return; + return; } if (!(dev->ctrl & 0x10)) { /* checking this is essential to avoid collisions */ - plip_log(3, "PLIP: cannot receive, interrupts are off\n"); - return; + plip_log(3, "PLIP: cannot receive, interrupts are off\n"); + return; } plip_log(2, "PLIP: receiving %d-byte packet\n", dev->rx_len); /* Set up to receive a packet. */ dev->status = 0xc7; /* DOS expects exactly 0xc7, while Linux masks the 7 off */ - dev->state = PLIP_RX_LEN_LSB_LOW; + dev->state = PLIP_RX_LEN_LSB_LOW; /* Engage timeout timer. */ timer_set_delay_u64(&dev->timeout_timer, 1000000 * TIMER_USEC); @@ -403,7 +407,6 @@ plip_receive_packet(plip_t *dev) lpt_irq(dev->lpt, 1); } - /* This timer defers a call to plip_receive_packet to the next ISA clock, in order to avoid IRQ weirdness. */ static void @@ -416,7 +419,6 @@ rx_timer(void *priv) timer_disable(&dev->rx_timer); } - static int plip_rx(void *priv, uint8_t *buf, int io_len) { @@ -425,14 +427,12 @@ plip_rx(void *priv, uint8_t *buf, int io_len) plip_log(2, "PLIP: incoming %d-byte packet\n", io_len); if (dev->rx_pkt) { /* shouldn't really happen with the RX queue paused */ - plip_log(3, "PLIP: already have a packet to receive"); - return 0; + plip_log(3, "PLIP: already have a packet to receive"); + return 0; } if (!(dev->rx_pkt = malloc(io_len))) /* unlikely */ - fatal("PLIP: unable to allocate rx_pkt\n"); - - network_rx_pause = 1; /* make sure we don't get any more packets while processing this one */ + fatal("PLIP: unable to allocate rx_pkt\n"); /* Copy this packet to our buffer. */ dev->rx_len = io_len; @@ -444,7 +444,6 @@ plip_rx(void *priv, uint8_t *buf, int io_len) return 1; } - static void * plip_lpt_init(void *lpt) { @@ -466,46 +465,53 @@ plip_lpt_init(void *lpt) return dev; } - static void * -plip_net_init(const device_t *info) +plip_net_init(UNUSED(const device_t *info)) { plip_log(1, "PLIP: net_init()"); if (!instance) { - plip_log(1, " (not attached to LPT)\n"); - return NULL; + plip_log(1, " (not attached to LPT)\n"); + return NULL; } plip_log(1, " (attached to LPT)\n"); - network_attach(instance, instance->mac, plip_rx, NULL, NULL); + instance->card = network_attach(instance, instance->mac, plip_rx, NULL); return instance; } - static void plip_close(void *priv) { + if (instance->card) { + netcard_close(instance->card); + } free(priv); } - const lpt_device_t lpt_plip_device = { - .name = "Parallel Line Internet Protocol", - .init = plip_lpt_init, - .close = plip_close, - .write_data = plip_write_data, - .write_ctrl = plip_write_ctrl, - .read_data = NULL, - .read_status = plip_read_status, - .read_ctrl = NULL + .name = "Parallel Line Internet Protocol", + .internal_name = "plip", + .init = plip_lpt_init, + .close = plip_close, + .write_data = plip_write_data, + .write_ctrl = plip_write_ctrl, + .read_data = NULL, + .read_status = plip_read_status, + .read_ctrl = NULL }; const device_t plip_device = { - "Parallel Line Internet Protocol", - "plip", - DEVICE_LPT, 0, - plip_net_init, NULL, - NULL, { NULL }, NULL, NULL + .name = "Parallel Line Internet Protocol", + .internal_name = "plip", + .flags = DEVICE_LPT, + .local = 0, + .init = plip_net_init, + .close = NULL, + .reset = NULL, + { .available = NULL }, + .speed_changed = NULL, + .force_redraw = NULL, + .config = NULL }; diff --git a/src/network/net_slirp.c b/src/network/net_slirp.c index b4b46bbe7..6aff76a90 100644 --- a/src/network/net_slirp.c +++ b/src/network/net_slirp.c @@ -1,132 +1,132 @@ /* - * 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. + * 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. + * This file is part of the 86Box distribution. * - * Handle SLiRP library processing. + * Handle SLiRP library processing. * - * Some of the code was borrowed from libvdeslirp - * + * Some of the code was borrowed from libvdeslirp + * * * * - * Authors: Fred N. van Kempen, - * RichardG, + * Authors: Fred N. van Kempen, + * RichardG, * - * Copyright 2017-2019 Fred N. van Kempen. - * Copyright 2020 RichardG. + * Copyright 2017-2019 Fred N. van Kempen. + * Copyright 2020 RichardG. */ #include #include #include #include #include +#include #include -#include #define HAVE_STDARG_H #include <86box/86box.h> #include <86box/device.h> #include <86box/plat.h> +#include <86box/thread.h> +#include <86box/timer.h> #include <86box/network.h> #include <86box/machine.h> -#include <86box/timer.h> +#include <86box/ini.h> #include <86box/config.h> +#include <86box/video.h> +#define _SSIZE_T_DEFINED +#include -/* SLiRP can use poll() or select() for socket polling. - poll() is best on *nix but slow and limited on Windows. */ -#ifndef _WIN32 -# define SLIRP_USE_POLL 1 -#endif -#ifdef SLIRP_USE_POLL -# ifdef _WIN32 -# include -# define poll WSAPoll -# else -# include -# endif -#endif - - -typedef struct { - Slirp *slirp; - void *mac; - const netcard_t *card; /* netcard attached to us */ - volatile thread_t *poll_tid; - event_t *poll_state; - uint8_t stop; -#ifdef SLIRP_USE_POLL - uint32_t pfd_len, pfd_size; - struct pollfd *pfd; +#ifdef _WIN32 +# define WIN32_LEAN_AND_MEAN +# include #else - uint32_t nfds; - fd_set rfds, wfds, xfds; +# include #endif -} slirp_t; +#include <86box/net_event.h> -static slirp_t *slirp; +#define SLIRP_PKT_BATCH NET_QUEUE_LEN +enum { + NET_EVENT_STOP = 0, + NET_EVENT_TX, + NET_EVENT_RX, + NET_EVENT_MAX +}; + +typedef struct net_slirp_t { + Slirp *slirp; + uint8_t mac_addr[6]; + netcard_t *card; /* netcard attached to us */ + thread_t *poll_tid; + net_evt_t tx_event; + net_evt_t stop_event; + netpkt_t pkt; + netpkt_t pkt_tx_v[SLIRP_PKT_BATCH]; +#ifdef _WIN32 + HANDLE sock_event; +#else + uint32_t pfd_len; + uint32_t pfd_size; + struct pollfd *pfd; +#endif +} net_slirp_t; #ifdef ENABLE_SLIRP_LOG int slirp_do_log = ENABLE_SLIRP_LOG; - static void slirp_log(const char *fmt, ...) { va_list ap; if (slirp_do_log) { - va_start(ap, fmt); - pclog_ex(fmt, ap); - va_end(ap); + va_start(ap, fmt); + pclog_ex(fmt, ap); + va_end(ap); } } #else -#define slirp_log(fmt, ...) +# define slirp_log(fmt, ...) #endif - static void -net_slirp_guest_error(const char *msg, void *opaque) +net_slirp_guest_error(UNUSED(const char *msg), UNUSED(void *opaque)) { slirp_log("SLiRP: guest_error(): %s\n", msg); } - static int64_t -net_slirp_clock_get_ns(void *opaque) +net_slirp_clock_get_ns(UNUSED(void *opaque)) { - return (TIMER_USEC ? (tsc / (TIMER_USEC / 1000)) : 0); + return (int64_t) ((double) tsc / cpuclock * 1000000000.0); } - static void * -net_slirp_timer_new(SlirpTimerCb cb, void *cb_opaque, void *opaque) +net_slirp_timer_new(SlirpTimerCb cb, void *cb_opaque, UNUSED(void *opaque)) { pc_timer_t *timer = malloc(sizeof(pc_timer_t)); timer_add(timer, cb, cb_opaque, 0); return timer; } - static void -net_slirp_timer_free(void *timer, void *opaque) +net_slirp_timer_free(void *timer, UNUSED(void *opaque)) { timer_stop(timer); + free(timer); } - static void -net_slirp_timer_mod(void *timer, int64_t expire_timer, void *opaque) +net_slirp_timer_mod(void *timer, int64_t expire_timer, UNUSED(void *opaque)) { - timer_set_delay_u64(timer, expire_timer); + timer_on_auto(timer, expire_timer * 1000); } - static void net_slirp_register_poll_fd(int fd, void *opaque) { @@ -134,7 +134,6 @@ net_slirp_register_poll_fd(int fd, void *opaque) (void) opaque; } - static void net_slirp_unregister_poll_fd(int fd, void *opaque) { @@ -142,350 +141,356 @@ net_slirp_unregister_poll_fd(int fd, void *opaque) (void) opaque; } - static void net_slirp_notify(void *opaque) { (void) opaque; } - ssize_t net_slirp_send_packet(const void *qp, size_t pkt_len, void *opaque) { - slirp_t *slirp = (slirp_t *) opaque; - uint8_t *mac = slirp->mac; - uint32_t mac_cmp32[2]; - uint16_t mac_cmp16[2]; + net_slirp_t *slirp = (net_slirp_t *) opaque; - if (!(slirp->card->set_link_state && slirp->card->set_link_state(slirp->card->priv)) && !(slirp->card->wait && slirp->card->wait(slirp->card->priv))) { - slirp_log("SLiRP: received %d-byte packet\n", pkt_len); + slirp_log("SLiRP: received %d-byte packet\n", pkt_len); - /* Received MAC. */ - mac_cmp32[0] = *(uint32_t *) (((uint8_t *) qp) + 6); - mac_cmp16[0] = *(uint16_t *) (((uint8_t *) qp) + 10); + memcpy(slirp->pkt.data, (uint8_t *) qp, pkt_len); + slirp->pkt.len = pkt_len; + network_rx_put_pkt(slirp->card, &slirp->pkt); - /* Local MAC. */ - mac_cmp32[1] = *(uint32_t *) mac; - mac_cmp16[1] = *(uint16_t *) (mac + 4); - if ((mac_cmp32[0] != mac_cmp32[1]) || - (mac_cmp16[0] != mac_cmp16[1])) { - network_queue_put(0, slirp->card->priv, (uint8_t *) qp, pkt_len); - } - - return pkt_len; - } else { - slirp_log("SLiRP: ignored %d-byte packet\n", pkt_len); - } - - return 0; + return pkt_len; } - +#ifdef _WIN32 static int net_slirp_add_poll(int fd, int events, void *opaque) { - slirp_t *slirp = (slirp_t *) opaque; -#ifdef SLIRP_USE_POLL + net_slirp_t *slirp = (net_slirp_t *) opaque; + long bitmask = 0; + if (events & SLIRP_POLL_IN) + bitmask |= FD_READ | FD_ACCEPT; + if (events & SLIRP_POLL_OUT) + bitmask |= FD_WRITE | FD_CONNECT; + if (events & SLIRP_POLL_HUP) + bitmask |= FD_CLOSE; + if (events & SLIRP_POLL_PRI) + bitmask |= FD_OOB; + + WSAEventSelect(fd, slirp->sock_event, bitmask); + return fd; +} +#else +static int +net_slirp_add_poll(int fd, int events, void *opaque) +{ + net_slirp_t *slirp = (net_slirp_t *) opaque; + if (slirp->pfd_len >= slirp->pfd_size) { - int newsize = slirp->pfd_size + 16; - struct pollfd *new = realloc(slirp->pfd, newsize * sizeof(struct pollfd)); - if (new) { - slirp->pfd = new; - slirp->pfd_size = newsize; - } + int newsize = slirp->pfd_size + 16; + struct pollfd *new = realloc(slirp->pfd, newsize * sizeof(struct pollfd)); + if (new) { + slirp->pfd = new; + slirp->pfd_size = newsize; + } } if ((slirp->pfd_len < slirp->pfd_size)) { - int idx = slirp->pfd_len++; - slirp->pfd[idx].fd = fd; - int pevents = 0; - if (events & SLIRP_POLL_IN) pevents |= POLLIN; - if (events & SLIRP_POLL_OUT) pevents |= POLLOUT; -# ifndef _WIN32 - /* Windows does not support some events. */ - if (events & SLIRP_POLL_ERR) pevents |= POLLERR; - if (events & SLIRP_POLL_PRI) pevents |= POLLPRI; - if (events & SLIRP_POLL_HUP) pevents |= POLLHUP; -# endif - slirp->pfd[idx].events = pevents; - return idx; + int idx = slirp->pfd_len++; + slirp->pfd[idx].fd = fd; + int pevents = 0; + if (events & SLIRP_POLL_IN) + pevents |= POLLIN; + if (events & SLIRP_POLL_OUT) + pevents |= POLLOUT; + if (events & SLIRP_POLL_ERR) + pevents |= POLLERR; + if (events & SLIRP_POLL_PRI) + pevents |= POLLPRI; + if (events & SLIRP_POLL_HUP) + pevents |= POLLHUP; + slirp->pfd[idx].events = pevents; + return idx; } else - return -1; -#else - if (events & SLIRP_POLL_IN) - FD_SET(fd, &slirp->rfds); - if (events & SLIRP_POLL_OUT) - FD_SET(fd, &slirp->wfds); - if (events & SLIRP_POLL_PRI) - FD_SET(fd, &slirp->xfds); - if (fd > slirp->nfds) - slirp->nfds = fd; - return fd; -#endif + return -1; } +#endif - +#ifdef _WIN32 static int net_slirp_get_revents(int idx, void *opaque) { - slirp_t *slirp = (slirp_t *) opaque; - int ret = 0; -#ifdef SLIRP_USE_POLL - int events = slirp->pfd[idx].revents; - if (events & POLLIN) ret |= SLIRP_POLL_IN; - if (events & POLLOUT) ret |= SLIRP_POLL_OUT; - if (events & POLLPRI) ret |= SLIRP_POLL_PRI; - if (events & POLLERR) ret |= SLIRP_POLL_ERR; - if (events & POLLHUP) ret |= SLIRP_POLL_HUP; -#else - if (FD_ISSET(idx, &slirp->rfds)) - ret |= SLIRP_POLL_IN; - if (FD_ISSET(idx, &slirp->wfds)) - ret |= SLIRP_POLL_OUT; - if (FD_ISSET(idx, &slirp->xfds)) - ret |= SLIRP_POLL_PRI; -#endif + net_slirp_t *slirp = (net_slirp_t *) opaque; + int ret = 0; + WSANETWORKEVENTS ev; + if (WSAEnumNetworkEvents(idx, slirp->sock_event, &ev) != 0) { + return ret; + } + +# define WSA_TO_POLL(_wsaev, _pollev) \ + do { \ + if (ev.lNetworkEvents & (_wsaev)) { \ + ret |= (_pollev); \ + if (ev.iErrorCode[_wsaev##_BIT] != 0) { \ + ret |= SLIRP_POLL_ERR; \ + } \ + } \ + } while (0) + + WSA_TO_POLL(FD_READ, SLIRP_POLL_IN); + WSA_TO_POLL(FD_ACCEPT, SLIRP_POLL_IN); + WSA_TO_POLL(FD_WRITE, SLIRP_POLL_OUT); + WSA_TO_POLL(FD_CONNECT, SLIRP_POLL_OUT); + WSA_TO_POLL(FD_OOB, SLIRP_POLL_PRI); + WSA_TO_POLL(FD_CLOSE, SLIRP_POLL_HUP); + return ret; } - - -static void -slirp_tic(slirp_t *slirp) +#else +static int +net_slirp_get_revents(int idx, void *opaque) { - int ret; - uint32_t tmo; - - /* Let SLiRP create a list of all open sockets. */ -#ifdef SLIRP_USE_POLL - tmo = -1; - slirp->pfd_len = 0; -#else - slirp->nfds = -1; - FD_ZERO(&slirp->rfds); - FD_ZERO(&slirp->wfds); - FD_ZERO(&slirp->xfds); -#endif - slirp_pollfds_fill(slirp->slirp, &tmo, net_slirp_add_poll, slirp); - - /* Now wait for something to happen, or at most 'tmo' usec. */ -#ifdef SLIRP_USE_POLL - ret = poll(slirp->pfd, slirp->pfd_len, tmo); -#else - if (tmo < 0) - tmo = 500; - - struct timeval tv; - tv.tv_sec = 0; - tv.tv_usec = tmo; - - ret = select(slirp->nfds + 1, &slirp->rfds, &slirp->wfds, &slirp->xfds, &tv); -#endif - - /* If something happened, let SLiRP handle it. */ - slirp_pollfds_poll(slirp->slirp, (ret <= 0), net_slirp_get_revents, slirp); + net_slirp_t *slirp = (net_slirp_t *) opaque; + int ret = 0; + int events = slirp->pfd[idx].revents; + if (events & POLLIN) + ret |= SLIRP_POLL_IN; + if (events & POLLOUT) + ret |= SLIRP_POLL_OUT; + if (events & POLLPRI) + ret |= SLIRP_POLL_PRI; + if (events & POLLERR) + ret |= SLIRP_POLL_ERR; + if (events & POLLHUP) + ret |= SLIRP_POLL_HUP; + return ret; } - +#endif static const SlirpCb slirp_cb = { - .send_packet = net_slirp_send_packet, - .guest_error = net_slirp_guest_error, - .clock_get_ns = net_slirp_clock_get_ns, - .timer_new = net_slirp_timer_new, - .timer_free = net_slirp_timer_free, - .timer_mod = net_slirp_timer_mod, - .register_poll_fd = net_slirp_register_poll_fd, + .send_packet = net_slirp_send_packet, + .guest_error = net_slirp_guest_error, + .clock_get_ns = net_slirp_clock_get_ns, + .timer_new = net_slirp_timer_new, + .timer_free = net_slirp_timer_free, + .timer_mod = net_slirp_timer_mod, + .register_poll_fd = net_slirp_register_poll_fd, .unregister_poll_fd = net_slirp_unregister_poll_fd, - .notify = net_slirp_notify + .notify = net_slirp_notify }; - -/* Handle the receiving of frames. */ +/* Send a packet to the SLiRP interface. */ static void -poll_thread(void *arg) -{ - slirp_t *slirp = (slirp_t *) arg; - event_t *evt; - int tx; - - slirp_log("SLiRP: initializing...\n"); - - /* Set the IP addresses to use. */ - struct in_addr net = { .s_addr = htonl(0x0a000200) }; /* 10.0.2.0 */ - struct in_addr mask = { .s_addr = htonl(0xffffff00) }; /* 255.255.255.0 */ - struct in_addr host = { .s_addr = htonl(0x0a000202) }; /* 10.0.2.2 */ - struct in_addr dhcp = { .s_addr = htonl(0x0a00020f) }; /* 10.0.2.15 */ - struct in_addr dns = { .s_addr = htonl(0x0a000203) }; /* 10.0.2.3 */ - struct in_addr bind = { .s_addr = htonl(0x00000000) }; /* 0.0.0.0 */ - struct in6_addr ipv6_dummy = { 0 }; /* contents don't matter; we're not using IPv6 */ - - /* Initialize SLiRP. */ - slirp->slirp = slirp_init(0, 1, net, mask, host, 0, ipv6_dummy, 0, ipv6_dummy, NULL, NULL, NULL, NULL, dhcp, dns, ipv6_dummy, NULL, NULL, &slirp_cb, arg); - if (!slirp->slirp) { - slirp_log("SLiRP: initialization failed\n"); - return; - } - - /* Set up port forwarding. */ - int udp, external, internal, i = 0; - char *category = "SLiRP Port Forwarding"; - char key[20]; - while (1) { - sprintf(key, "%d_protocol", i); - udp = strcmp(config_get_string(category, key, "tcp"), "udp") == 0; - sprintf(key, "%d_external", i); - external = config_get_int(category, key, 0); - sprintf(key, "%d_internal", i); - internal = config_get_int(category, key, 0); - if ((external <= 0) && (internal <= 0)) - break; - else if (internal <= 0) - internal = external; - else if (external <= 0) - external = internal; - - if (slirp_add_hostfwd(slirp->slirp, udp, bind, external, dhcp, internal) == 0) - pclog("SLiRP: Forwarded %s port external:%d to internal:%d\n", udp ? "UDP" : "TCP", external, internal); - else - pclog("SLiRP: Failed to forward %s port external:%d to internal:%d\n", udp ? "UDP" : "TCP", external, internal); - - i++; - } - - /* Start polling. */ - slirp_log("SLiRP: polling started.\n"); - thread_set_event(slirp->poll_state); - - /* Create a waitable event. */ - evt = thread_create_event(); - - while (!slirp->stop) { - /* Request ownership of the queue. */ - network_wait(1); - - /* Wait for a poll request. */ - network_poll(); - - /* Stop processing if asked to. */ - if (slirp->stop) break; - - /* See if there is any work. */ - slirp_tic(slirp); - - /* Wait for the next packet to arrive. */ - tx = network_tx_queue_check(); - - if (tx) - network_do_tx(); - - /* If we did not get anything, wait a while. */ - if (!tx) - thread_wait_event(evt, 10); - - /* Release ownership of the queue. */ - network_wait(0); - } - - /* No longer needed. */ - if (evt) - thread_destroy_event(evt); - - slirp_log("SLiRP: polling stopped.\n"); - thread_set_event(slirp->poll_state); - - /* Destroy event here to avoid a crash. */ - slirp_log("SLiRP: thread ended\n"); - thread_destroy_event(slirp->poll_state); - /* Free here instead of immediately freeing the global slirp on the main - thread to avoid a race condition. */ - slirp_cleanup(slirp->slirp); - free(slirp); -} - - -/* Initialize SLiRP for use. */ -int -net_slirp_init(void) -{ - return 0; -} - - -/* Initialize SLiRP for use. */ -int -net_slirp_reset(const netcard_t *card, uint8_t *mac) -{ - slirp_t *new_slirp = malloc(sizeof(slirp_t)); - memset(new_slirp, 0, sizeof(slirp_t)); - new_slirp->mac = mac; - new_slirp->card = card; -#ifdef SLIRP_USE_POLL - new_slirp->pfd_size = 16 * sizeof(struct pollfd); - new_slirp->pfd = malloc(new_slirp->pfd_size); - memset(new_slirp->pfd, 0, new_slirp->pfd_size); -#endif - - /* Save the callback info. */ - slirp = new_slirp; - - slirp_log("SLiRP: creating thread...\n"); - slirp->poll_state = thread_create_event(); - slirp->poll_tid = thread_create(poll_thread, new_slirp); - thread_wait_event(slirp->poll_state, -1); - - return 0; -} - - -void -net_slirp_close(void) +net_slirp_in(net_slirp_t *slirp, uint8_t *pkt, int pkt_len) { if (!slirp) - return; + return; - slirp_log("SLiRP: closing\n"); - - /* Tell the polling thread to shut down. */ - slirp->stop = 1; - - /* Tell the thread to terminate. */ - if (slirp->poll_tid) { - network_busy(0); - - /* Wait for the thread to finish. */ - slirp_log("SLiRP: waiting for thread to end...\n"); - thread_wait_event(slirp->poll_state, -1); - } - - /* Shutdown work is done by the thread on its local copy of slirp. */ - slirp = NULL; -} - - -/* Send a packet to the SLiRP interface. */ -void -net_slirp_in(uint8_t *pkt, int pkt_len) -{ - if (!slirp || !slirp->slirp) - return; - - slirp_log("SLiRP: sending %d-byte packet\n", pkt_len); + slirp_log("SLiRP: sending %d-byte packet to host network\n", pkt_len); slirp_input(slirp->slirp, (const uint8_t *) pkt, pkt_len); } +void +net_slirp_in_available(void *priv) +{ + net_slirp_t *slirp = (net_slirp_t *) priv; + net_event_set(&slirp->tx_event); +} -/* Stubs to stand in for the parts of libslirp we skip compiling. */ -void ncsi_input(void *slirp, const uint8_t *pkt, int pkt_len) {} -void ip6_init(void *slirp) {} -void ip6_cleanup(void *slirp) {} -void ip6_input(void *m) {} -int ip6_output(void *so, void *m, int fast) { return 0; } -void in6_compute_ethaddr(struct in6_addr ip, uint8_t *eth) {} -bool in6_equal(const void *a, const void *b) { return 0; } -const struct in6_addr in6addr_any = { { { 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 } } }; -const struct in6_addr in6addr_loopback = { { { 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1 } } }; -int udp6_output(void *so, void *m, void *saddr, void *daddr) { return 0; } -void icmp6_send_error(void *m, uint8_t type, uint8_t code) {} -void ndp_send_ns(void *slirp, struct in6_addr addr) {} -bool ndp_table_search(void *slirp, struct in6_addr ip_addr, uint8_t *out_ethaddr) { return 0; } -void tftp_input(void *srcsas, void *m) {} +#ifdef _WIN32 +static void +net_slirp_thread(void *priv) +{ + net_slirp_t *slirp = (net_slirp_t *) priv; + + /* Start polling. */ + slirp_log("SLiRP: polling started.\n"); + + HANDLE events[3]; + events[NET_EVENT_STOP] = net_event_get_handle(&slirp->stop_event); + events[NET_EVENT_TX] = net_event_get_handle(&slirp->tx_event); + events[NET_EVENT_RX] = slirp->sock_event; + bool run = true; + while (run) { + uint32_t timeout = -1; + slirp_pollfds_fill(slirp->slirp, &timeout, net_slirp_add_poll, slirp); + if (timeout < 0) + timeout = INFINITE; + + int ret = WaitForMultipleObjects(3, events, FALSE, (DWORD) timeout); + switch (ret - WAIT_OBJECT_0) { + case NET_EVENT_STOP: + run = false; + break; + + case NET_EVENT_TX: + { + int packets = network_tx_popv(slirp->card, slirp->pkt_tx_v, SLIRP_PKT_BATCH); + for (int i = 0; i < packets; i++) { + net_slirp_in(slirp, slirp->pkt_tx_v[i].data, slirp->pkt_tx_v[i].len); + } + } + break; + + default: + slirp_pollfds_poll(slirp->slirp, ret == WAIT_FAILED, net_slirp_get_revents, slirp); + break; + } + } + + slirp_log("SLiRP: polling stopped.\n"); +} +#else +/* Handle the receiving of frames. */ +static void +net_slirp_thread(void *priv) +{ + net_slirp_t *slirp = (net_slirp_t *) priv; + + /* Start polling. */ + slirp_log("SLiRP: polling started.\n"); + + while (1) { + uint32_t timeout = -1; + + slirp->pfd_len = 0; + net_slirp_add_poll(net_event_get_fd(&slirp->stop_event), SLIRP_POLL_IN, slirp); + net_slirp_add_poll(net_event_get_fd(&slirp->tx_event), SLIRP_POLL_IN, slirp); + + slirp_pollfds_fill(slirp->slirp, &timeout, net_slirp_add_poll, slirp); + + int ret = poll(slirp->pfd, slirp->pfd_len, timeout); + + slirp_pollfds_poll(slirp->slirp, (ret < 0), net_slirp_get_revents, slirp); + + if (slirp->pfd[NET_EVENT_STOP].revents & POLLIN) { + net_event_clear(&slirp->stop_event); + break; + } + + if (slirp->pfd[NET_EVENT_TX].revents & POLLIN) { + net_event_clear(&slirp->tx_event); + + int packets = network_tx_popv(slirp->card, slirp->pkt_tx_v, SLIRP_PKT_BATCH); + for (int i = 0; i < packets; i++) { + net_slirp_in(slirp, slirp->pkt_tx_v[i].data, slirp->pkt_tx_v[i].len); + } + } + } + + slirp_log("SLiRP: polling stopped.\n"); +} +#endif + +static int slirp_card_num = 2; + +/* Initialize SLiRP for use. */ +void * +net_slirp_init(const netcard_t *card, const uint8_t *mac_addr, UNUSED(void *priv), char *netdrv_errbuf) +{ + slirp_log("SLiRP: initializing...\n"); + net_slirp_t *slirp = calloc(1, sizeof(net_slirp_t)); + memcpy(slirp->mac_addr, mac_addr, sizeof(slirp->mac_addr)); + slirp->card = (netcard_t *) card; + +#ifndef _WIN32 + slirp->pfd_size = 16 * sizeof(struct pollfd); + slirp->pfd = malloc(slirp->pfd_size); + memset(slirp->pfd, 0, slirp->pfd_size); +#endif + + /* Set the IP addresses to use. */ + struct in_addr net = { .s_addr = htonl(0x0a000000 | (slirp_card_num << 8)) }; /* 10.0.x.0 */ + struct in_addr mask = { .s_addr = htonl(0xffffff00) }; /* 255.255.255.0 */ + struct in_addr host = { .s_addr = htonl(0x0a000002 | (slirp_card_num << 8)) }; /* 10.0.x.2 */ + struct in_addr dhcp = { .s_addr = htonl(0x0a00000f | (slirp_card_num << 8)) }; /* 10.0.x.15 */ + struct in_addr dns = { .s_addr = htonl(0x0a000003 | (slirp_card_num << 8)) }; /* 10.0.x.3 */ + struct in_addr bind = { .s_addr = htonl(0x00000000) }; /* 0.0.0.0 */ + struct in6_addr ipv6_dummy = { 0 }; /* contents don't matter; we're not using IPv6 */ + + /* Initialize SLiRP. */ + slirp->slirp = slirp_init(0, 1, net, mask, host, 0, ipv6_dummy, 0, ipv6_dummy, NULL, NULL, NULL, NULL, dhcp, dns, ipv6_dummy, NULL, NULL, &slirp_cb, slirp); + if (!slirp->slirp) { + slirp_log("SLiRP: initialization failed\n"); + snprintf(netdrv_errbuf, NET_DRV_ERRBUF_SIZE, "SLiRP initialization failed"); + free(slirp); + return NULL; + } + + /* Set up port forwarding. */ + int udp; + int i = 0; + int external; + int internal; + char category[32]; + snprintf(category, sizeof(category), "SLiRP Port Forwarding #%d", card->card_num + 1); + char key[20]; + while (1) { + sprintf(key, "%d_protocol", i); + udp = strcmp(config_get_string(category, key, "tcp"), "udp") == 0; + sprintf(key, "%d_external", i); + external = config_get_int(category, key, 0); + sprintf(key, "%d_internal", i); + internal = config_get_int(category, key, 0); + if ((external <= 0) && (internal <= 0)) + break; + else if (internal <= 0) + internal = external; + else if (external <= 0) + external = internal; + + if (slirp_add_hostfwd(slirp->slirp, udp, bind, external, dhcp, internal) == 0) + pclog("SLiRP: Forwarded %s port external:%d to internal:%d\n", udp ? "UDP" : "TCP", external, internal); + else + pclog("SLiRP: Failed to forward %s port external:%d to internal:%d\n", udp ? "UDP" : "TCP", external, internal); + + i++; + } + + for (int i = 0; i < SLIRP_PKT_BATCH; i++) { + slirp->pkt_tx_v[i].data = calloc(1, NET_MAX_FRAME); + } + slirp->pkt.data = calloc(1, NET_MAX_FRAME); + net_event_init(&slirp->tx_event); + net_event_init(&slirp->stop_event); +#ifdef _WIN32 + slirp->sock_event = CreateEvent(NULL, FALSE, FALSE, NULL); +#endif + slirp_log("SLiRP: creating thread...\n"); + slirp->poll_tid = thread_create(net_slirp_thread, slirp); + + slirp_card_num++; + return slirp; +} + +void +net_slirp_close(void *priv) +{ + if (!priv) + return; + + net_slirp_t *slirp = (net_slirp_t *) priv; + + slirp_log("SLiRP: closing\n"); + /* Tell the polling thread to shut down. */ + net_event_set(&slirp->stop_event); + + /* Wait for the thread to finish. */ + slirp_log("SLiRP: waiting for thread to end...\n"); + thread_wait(slirp->poll_tid); + + net_event_close(&slirp->tx_event); + net_event_close(&slirp->stop_event); + slirp_cleanup(slirp->slirp); + for (int i = 0; i < SLIRP_PKT_BATCH; i++) { + free(slirp->pkt_tx_v[i].data); + } + free(slirp->pkt.data); + free(slirp); + slirp_card_num--; +} + +const netdrv_t net_slirp_drv = { + &net_slirp_in_available, + &net_slirp_init, + &net_slirp_close +}; diff --git a/src/network/net_vde.c b/src/network/net_vde.c new file mode 100644 index 000000000..afeeaac9c --- /dev/null +++ b/src/network/net_vde.c @@ -0,0 +1,310 @@ + /* + * 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. + * + * VDE networking for 86box + * See https://wiki.virtualsquare.org/#!tutorials/vdebasics.md + * for basic information about VDE. You can browse the source + * code at https://github.com/virtualsquare/vde-2 + * + * VDE support is only available in Linux and MacOS. It _should_ + * be available in BSD*, and if someday there is a BSD version of + * 86box this _could_ work out of the box. + * + * Authors: jguillaumes + * Copyright 2023 jguillaumes. + * + * See the COPYING file at the top of the 86box for license details. + * TL;DR: GPL version 2. + */ +#include +#include +#include +#include +#include + +#if !defined(_WIN32) +#include +#include +#else +#error VDE is not supported under windows +#endif + +#include + +#define HAVE_STDARG_H +#include <86box/86box.h> +#include <86box/device.h> +#include <86box/plat.h> +#include <86box/plat_dynld.h> +#include <86box/thread.h> +#include <86box/timer.h> +#include <86box/network.h> +#include <86box/net_event.h> + +#define VDE_PKT_BATCH NET_QUEUE_LEN +#define VDE_DESCRIPTION "86Box virtual card" + +enum { + NET_EVENT_STOP = 0, + NET_EVENT_TX, + NET_EVENT_RX, + NET_EVENT_VDE, + NET_EVENT_MAX +}; + +static volatile void *libvde_handle = NULL; + +//+ +// VDE connection structure +//- +typedef struct net_vde_t { + void *vdeconn; // VDEPLUG Connection + netcard_t *card; // NIC linked to + thread_t *poll_tid; // Polling thread + net_evt_t tx_event; // Packets to transmit event + net_evt_t stop_event; // Stop thread event + netpkt_t pkt; // Packet read/sent + netpkt_t pktv[VDE_PKT_BATCH]; // Packet queue + uint8_t mac_addr[6]; // MAC Address +} net_vde_t; + +//+ +// VDE libvdeplug function pointers +//- +static VDECONN *(*f_vde_open)(char *, char *, int, struct vde_open_args *); // This is vde_open_real() +static void (*f_vde_close)(VDECONN *); +static int (*f_vde_datafd)(VDECONN *); // Get the data (read/write) handle +static int (*f_vde_ctlfd)(VDECONN *); // Get the control handle +static ssize_t (*f_vde_recv)(VDECONN *, void *, size_t, int); // Receive a packet +static ssize_t (*f_vde_send)(VDECONN *, const void *, size_t, int); // Send a packet + +//+ +// VDE libvdeplug function table (for import) +//- +static dllimp_t vde_imports[] = { + {"vde_open_real", &f_vde_open}, + {"vde_close", &f_vde_close}, + {"vde_datafd", &f_vde_datafd}, + {"vde_ctlfd", &f_vde_ctlfd}, + {"vde_recv", &f_vde_recv}, + {"vde_send", &f_vde_send}, + { NULL, NULL} +}; + +#ifdef ENABLE_VDE_LOG +#include +int vde_do_log = ENABLE_VDE_LOG; + +static void +vde_log(const char *fmt, ...) { + va_list ap; + + if (vde_do_log) { + va_start(ap, fmt); + pclog_ex(fmt, ap); + va_end(ap); + } +} +#else +# define vde_log(fmt, ...) +#endif + +#ifdef _WIN32 +#error VDE networking is not supported under windows +#else + +//+ +// VDE thread +//- +static void net_vde_thread(void *priv) { + net_vde_t *vde = (net_vde_t *) priv; + vde_log("VDE: Polling started.\n"); + + struct pollfd pfd[NET_EVENT_MAX]; + pfd[NET_EVENT_STOP].fd = net_event_get_fd(&vde->stop_event); + pfd[NET_EVENT_STOP].events = POLLIN | POLLPRI; + + pfd[NET_EVENT_TX].fd = net_event_get_fd(&vde->tx_event); + pfd[NET_EVENT_TX].events = POLLIN | POLLPRI; + + pfd[NET_EVENT_RX].fd = f_vde_datafd(vde->vdeconn); + pfd[NET_EVENT_RX].events = POLLIN; + + pfd[NET_EVENT_VDE].fd = f_vde_ctlfd(vde->vdeconn); + pfd[NET_EVENT_VDE].events = POLLIN; + + while(1) { + poll(pfd, NET_EVENT_MAX, -1); + + // Acvity in the control handle means the link is closed + // We send ourselves a STOP event + if (pfd[NET_EVENT_VDE].revents & POLLIN) { + net_event_set(&vde->stop_event); + } + + // There are packets queued to transmit + if (pfd[NET_EVENT_TX].revents & POLLIN) { + net_event_clear(&vde->tx_event); + int packets = network_tx_popv(vde->card, vde->pktv, VDE_PKT_BATCH); + for (int i=0; ivdeconn, vde->pktv[i].data,vde->pktv[i].len, 0 ); + if (nc == 0) { + vde_log("VDE: Problem, no bytes sent.\n"); + } + } + } + + // Packets are available for reading. Read packet and queue it + if (pfd[NET_EVENT_RX].revents & POLLIN) { + int nc = f_vde_recv(vde->vdeconn, vde->pkt.data, NET_MAX_FRAME, 0); + vde->pkt.len = nc; + network_rx_put_pkt(vde->card, &vde->pkt); + } + + // We have been told to close + if (pfd[NET_EVENT_STOP].revents & POLLIN) { + net_event_clear(&vde->stop_event); + break; + } + } + vde_log("VDE: Polling stopped.\n"); +} +#endif + + +//+ +// Prepare the VDE libvdeplug interface. +// Load the dynamic library libvdeplug. +// Returns zero if the library has been loaded, -1 in case of error. +//- +int net_vde_prepare(void) { + +#if defined(_WIN32) + #error VDE is not supported in Windows +#elif defined(__APPLE__) + libvde_handle = dynld_module("libvdeplug.dylib", vde_imports); +#else + libvde_handle = dynld_module("libvdeplug.so", vde_imports); +#endif + + if (libvde_handle == NULL) { + vde_log("VDE: error loading VDEPLUG module\n"); + return -1; + } else { + network_devmap.has_vde = 1; + } + return 0; +} + +//+ +// Close a VDE socket connection +//- +void net_vde_close(void *priv) { + int i; + + if (!priv) return; + + net_vde_t *vde = (net_vde_t *) priv; + vde_log("VDE: closing.\n"); + net_event_set(&vde->stop_event); // Tell the thread to finish + vde_log("VDE: Waiting for the thread to finish...\n"); + thread_wait(vde->poll_tid); + vde_log("VDE: Thread finished.\n"); + + // Free all the mallocs! + for(i=0;ipktv[i].data); + } + free(vde->pkt.data); + f_vde_close(vde->vdeconn); + net_event_close(&vde->tx_event); + net_event_close(&vde->stop_event); + free(vde); +} + +//+ +// Signal packets are available to be transmitted +//- +void net_vde_in_available(void *priv) { + net_vde_t *vde = (net_vde_t *) priv; + net_event_set(&vde->tx_event); +} + +//+ +// Copy error message to the error buffer +// and log if enabled. +//- +void net_vde_error(char *errbuf, const char *message) { + strncpy(errbuf, message, NET_DRV_ERRBUF_SIZE); + vde_log("VDE: %s\n", message); +} + +//+ +// Initialize VDE for use +// At this point the vdeplug library is already loaded +// card: network card we are attaching +// mac_addr: MAC address we are using +// priv: Name of the VDE contol socket directory +//- +void *net_vde_init(const netcard_t *card, const uint8_t *mac_addr, void *priv, char *netdrv_errbuf) { + struct vde_open_args vde_args; + + char *socket_name = (char *) priv; + + if (libvde_handle == NULL) { + net_vde_error(netdrv_errbuf, "net_vde_init without library handle"); + return NULL; + } + + if ((socket_name[0] == '\0') || !strcmp(socket_name, "none")) { + net_vde_error(netdrv_errbuf, "No socket name configured"); + return NULL; + } + + vde_log("VDE: Attaching to virtual switch at %s\n", socket_name); + + net_vde_t *vde = calloc(1, sizeof(net_vde_t)); + vde->card = (netcard_t *) card; + memcpy(vde->mac_addr, mac_addr, sizeof(vde->mac_addr)); + + vde_args.group = 0; + vde_args.port = 0; + vde_args.mode = 0; + + // We are calling vde_open_real(), not the vde_open() macro... + if ((vde->vdeconn = f_vde_open(socket_name, VDE_DESCRIPTION, + LIBVDEPLUG_INTERFACE_VERSION, &vde_args)) == NULL) { + char buf[NET_DRV_ERRBUF_SIZE]; + snprintf(buf, NET_DRV_ERRBUF_SIZE, "Unable to open socket %s (%s)", socket_name, strerror(errno)); + net_vde_error(netdrv_errbuf, buf); + free(vde); + return NULL; + } + vde_log("VDE: Socket opened (%s).\n", socket_name); + + for(uint8_t i = 0; i < VDE_PKT_BATCH; i++) { + vde->pktv[i].data = calloc(1, NET_MAX_FRAME); + } + vde->pkt.data = calloc(1,NET_MAX_FRAME); + net_event_init(&vde->tx_event); + net_event_init(&vde->stop_event); + vde->poll_tid = thread_create(net_vde_thread, vde); // Fire up the read-write thread! + + return vde; +} + +//+ +// VDE Driver structure +//- +const netdrv_t net_vde_drv = { + &net_vde_in_available, + &net_vde_init, + &net_vde_close, + NULL +}; + diff --git a/src/network/net_wd8003.c b/src/network/net_wd8003.c index 33aa1578c..04b922aaf 100644 --- a/src/network/net_wd8003.c +++ b/src/network/net_wd8003.c @@ -1,26 +1,26 @@ /* - * 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. + * 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. + * This file is part of the 86Box distribution. * - * Implementation of the following network controllers: - * - SMC/WD 8003E (ISA 8-bit); - * - SMC/WD 8013EBT (ISA 16-bit); - * - SMC/WD 8013EP/A (MCA). + * Implementation of the following network controllers: + * - SMC/WD 8003E (ISA 8-bit); + * - SMC/WD 8013EBT (ISA 16-bit); + * - SMC/WD 8013EP/A (MCA). * * * - * Authors: Fred N. van Kempen, - * TheCollector1995, - * Miran Grca, - * Peter Grehan, + * Authors: Fred N. van Kempen, + * TheCollector1995, + * Miran Grca, + * Peter Grehan, * - * Copyright 2017-2019 Fred N. van Kempen. - * Copyright 2016-2019 Miran Grca. - * Portions Copyright (C) 2002 MandrakeSoft S.A. + * Copyright 2017-2019 Fred N. van Kempen. + * Copyright 2016-2019 Miran Grca. + * Portions Copyright (C) 2002 MandrakeSoft S.A. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -58,67 +58,73 @@ #include <86box/pic.h> #include <86box/random.h> #include <86box/device.h> +#include <86box/timer.h> +#include <86box/thread.h> #include <86box/network.h> #include <86box/net_dp8390.h> #include <86box/net_wd8003.h> #include <86box/bswap.h> +#include <86box/plat_fallthrough.h> +#include <86box/plat_unused.h> #include "cpu.h" /* Board type codes in card ID */ -#define WE_TYPE_WD8003 0x01 -#define WE_TYPE_WD8003S 0x02 -#define WE_TYPE_WD8003E 0x03 -#define WE_TYPE_WD8013EBT 0x05 -#define WE_TYPE_TOSHIBA1 0x11 /* named PCETA1 */ -#define WE_TYPE_TOSHIBA2 0x12 /* named PCETA2 */ -#define WE_TYPE_TOSHIBA3 0x13 /* named PCETB */ -#define WE_TYPE_TOSHIBA4 0x14 /* named PCETC */ -#define WE_TYPE_WD8003W 0x24 -#define WE_TYPE_WD8003EB 0x25 -#define WE_TYPE_WD8013W 0x26 -#define WE_TYPE_WD8013EP 0x27 -#define WE_TYPE_WD8013WC 0x28 -#define WE_TYPE_WD8013EPC 0x29 -#define WE_TYPE_SMC8216T 0x2a -#define WE_TYPE_SMC8216C 0x2b -#define WE_TYPE_WD8013EBP 0x2c +#define WE_TYPE_WD8003 0x01 +#define WE_TYPE_WD8003S 0x02 +#define WE_TYPE_WD8003E 0x03 +#define WE_TYPE_WD8013EBT 0x05 +#define WE_TYPE_TOSHIBA1 0x11 /* named PCETA1 */ +#define WE_TYPE_TOSHIBA2 0x12 /* named PCETA2 */ +#define WE_TYPE_TOSHIBA3 0x13 /* named PCETB */ +#define WE_TYPE_TOSHIBA4 0x14 /* named PCETC */ +#define WE_TYPE_WD8003W 0x24 +#define WE_TYPE_WD8003EB 0x25 +#define WE_TYPE_WD8013W 0x26 +#define WE_TYPE_WD8013EP 0x27 +#define WE_TYPE_WD8013WC 0x28 +#define WE_TYPE_WD8013EPC 0x29 +#define WE_TYPE_SMC8216T 0x2a +#define WE_TYPE_SMC8216C 0x2b +#define WE_TYPE_WD8013EBP 0x2c -#define WE_ICR_16BIT_SLOT 0x01 +#define WE_ICR_16BIT_SLOT 0x01 -#define WE_MSR_ENABLE_RAM 0x40 -#define WE_MSR_SOFT_RESET 0x80 +#define WE_MSR_ENABLE_RAM 0x40 +#define WE_MSR_SOFT_RESET 0x80 -#define WE_IRR_ENABLE_IRQ 0x80 +#define WE_IRR_ENABLE_IRQ 0x80 -#define WE_ID_ETHERNET 0x01 -#define WE_ID_SOFT_CONFIG 0x20 -#define WE_ID_EXTRA_RAM 0x40 -#define WE_ID_BUS_MCA 0x80 +#define WE_ID_ETHERNET 0x01 +#define WE_ID_SOFT_CONFIG 0x20 +#define WE_ID_EXTRA_RAM 0x40 +#define WE_ID_BUS_MCA 0x80 -typedef struct { - dp8390_t *dp8390; - mem_mapping_t ram_mapping; - uint32_t ram_addr, ram_size; - uint8_t maclocal[6]; /* configured MAC (local) address */ - uint8_t bit16, pad; - int board; - const char *name; - uint32_t base_address; - int irq; +typedef struct wd_t { + dp8390_t *dp8390; + mem_mapping_t ram_mapping; + uint32_t ram_addr; + uint32_t ram_size; + uint8_t maclocal[6]; /* configured MAC (local) address */ + uint8_t bit16; + uint8_t pad; + int board; + const char *name; + uint32_t base_address; + int irq; /* POS registers, MCA boards only */ - uint8_t pos_regs[8]; + uint8_t pos_regs[8]; /* Memory for WD cards*/ - uint8_t msr, /* Memory Select Register (MSR) */ - icr, /* Interface Configuration Register (ICR) */ - irr, /* Interrupt Request Register (IRR) */ - laar, /* LA Address Register (read by Windows 98!) */ - if_chip, board_chip; + uint8_t msr; /* Memory Select Register (MSR) */ + uint8_t icr; /* Interface Configuration Register (ICR) */ + uint8_t irr; /* Interrupt Request Register (IRR) */ + uint8_t laar; /* LA Address Register (read by Windows 98!) */ + uint8_t if_chip; + uint8_t board_chip; } wd_t; - #ifdef ENABLE_WD_LOG int wd_do_log = ENABLE_WD_LOG; @@ -128,60 +134,55 @@ wdlog(const char *fmt, ...) va_list ap; if (wd_do_log) { - va_start(ap, fmt); - pclog_ex(fmt, ap); - va_end(ap); + va_start(ap, fmt); + pclog_ex(fmt, ap); + va_end(ap); } } #else -#define wdlog(fmt, ...) +# define wdlog(fmt, ...) #endif - -static const int we_int_table[4] = {2, 3, 4, 7}; - +static const int we_int_table[4] = { 2, 3, 4, 7 }; static void wd_interrupt(void *priv, int set) { - wd_t *dev = (wd_t *) priv; + const wd_t *dev = (wd_t *) priv; if (!(dev->irr & WE_IRR_ENABLE_IRQ)) - return; + return; if (set) - picint(1 << dev->irq); + picint(1 << dev->irq); else - picintc(1 << dev->irq); + picintc(1 << dev->irq); } - /* reset - restore state to power-up, cancelling all i/o */ static void wd_reset(void *priv) { - wd_t *dev = (wd_t *)priv; + wd_t *dev = (wd_t *) priv; wdlog("%s: reset\n", dev->name); dp8390_reset(dev->dp8390); } - static void wd_soft_reset(void *priv) { - wd_t *dev = (wd_t *)priv; + wd_t *dev = (wd_t *) priv; dp8390_soft_reset(dev->dp8390); } - static uint8_t wd_ram_read(uint32_t addr, void *priv) { - wd_t *dev = (wd_t *)priv; - + const wd_t *dev = (wd_t *) priv; + wdlog("WD80x3: RAM Read: addr=%06x, val=%02x\n", addr & (dev->ram_size - 1), dev->dp8390->mem[addr & (dev->ram_size - 1)]); return dev->dp8390->mem[addr & (dev->ram_size - 1)]; } @@ -189,366 +190,356 @@ wd_ram_read(uint32_t addr, void *priv) static void wd_ram_write(uint32_t addr, uint8_t val, void *priv) { - wd_t *dev = (wd_t *)priv; - + wd_t *dev = (wd_t *) priv; + dev->dp8390->mem[addr & (dev->ram_size - 1)] = val; wdlog("WD80x3: RAM Write: addr=%06x, val=%02x\n", addr & (dev->ram_size - 1), val); } - static int wd_get_irq_index(wd_t *dev) { - uint8_t i, irq = 255; + uint8_t irq = 255; - for (i = 0; i < 4; i++) { - if (we_int_table[i] == dev->irq) - irq = i; + for (uint8_t i = 0; i < 4; i++) { + if (we_int_table[i] == dev->irq) + irq = i; } if (irq != 255) - return ((irq & 0x03) << 5); + return ((irq & 0x03) << 5); else - return 0; + return 0; } - static uint32_t wd_smc_read(wd_t *dev, uint32_t off) { - uint32_t retval = 0; + uint32_t retval = 0; uint32_t checksum = 0; if (dev->board == WD8003E) - off |= 0x08; + off |= 0x08; - switch(off) { - case 0x00: - if (dev->board_chip & WE_ID_BUS_MCA) - retval = (dev->msr & 0xc0) | ((dev->ram_addr >> 13) & 0x3f); - else - retval = dev->msr; - break; + switch (off) { + case 0x00: + if (dev->board_chip & WE_ID_BUS_MCA) + retval = (dev->msr & 0xc0) | ((dev->ram_addr >> 13) & 0x3f); + else + retval = dev->msr; + break; - case 0x01: - if (dev->board_chip & WE_ID_SOFT_CONFIG) - retval = dev->icr; - else - retval = dev->icr & WE_ICR_16BIT_SLOT; - break; + case 0x01: + if (dev->board_chip & WE_ID_SOFT_CONFIG) + retval = dev->icr; + else + retval = dev->icr & WE_ICR_16BIT_SLOT; + break; - case 0x04: - if (dev->board_chip & WE_ID_SOFT_CONFIG) - retval = (dev->irr & 0x9f) | wd_get_irq_index(dev); - break; + case 0x04: + if (dev->board_chip & WE_ID_SOFT_CONFIG) + retval = (dev->irr & 0x9f) | wd_get_irq_index(dev); + break; - case 0x05: - if (dev->board_chip & WE_ID_SOFT_CONFIG) - retval = dev->laar; - break; - - case 0x07: - if (dev->board_chip & WE_ID_SOFT_CONFIG) - retval = dev->if_chip; - break; + case 0x05: + if (dev->board_chip & WE_ID_SOFT_CONFIG) + retval = dev->laar; + break; - case 0x08: - retval = dev->dp8390->physaddr[0]; - break; - - case 0x09: - retval = dev->dp8390->physaddr[1]; - break; - - case 0x0a: - retval = dev->dp8390->physaddr[2]; - break; - - case 0x0b: - retval = dev->dp8390->physaddr[3]; - break; - - case 0x0c: - retval = dev->dp8390->physaddr[4]; - break; - - case 0x0d: - retval = dev->dp8390->physaddr[5]; - break; - - case 0x0e: - retval = dev->board_chip; - break; - - case 0x0f: - /*This has to return the byte that adds up to 0xFF*/ - checksum = (dev->dp8390->physaddr[0] + dev->dp8390->physaddr[1] + dev->dp8390->physaddr[2] + - dev->dp8390->physaddr[3] + dev->dp8390->physaddr[4] + dev->dp8390->physaddr[5] + - dev->board_chip); + case 0x07: + if (dev->board_chip & WE_ID_SOFT_CONFIG) + retval = dev->if_chip; + break; - retval = 0xff - (checksum & 0xff); - break; + case 0x08: + retval = dev->dp8390->physaddr[0]; + break; + + case 0x09: + retval = dev->dp8390->physaddr[1]; + break; + + case 0x0a: + retval = dev->dp8390->physaddr[2]; + break; + + case 0x0b: + retval = dev->dp8390->physaddr[3]; + break; + + case 0x0c: + retval = dev->dp8390->physaddr[4]; + break; + + case 0x0d: + retval = dev->dp8390->physaddr[5]; + break; + + case 0x0e: + retval = dev->board_chip; + break; + + case 0x0f: + /*This has to return the byte that adds up to 0xFF*/ + checksum = (dev->dp8390->physaddr[0] + dev->dp8390->physaddr[1] + dev->dp8390->physaddr[2] + dev->dp8390->physaddr[3] + dev->dp8390->physaddr[4] + dev->dp8390->physaddr[5] + dev->board_chip); + + retval = 0xff - (checksum & 0xff); + break; + + default: + break; } wdlog("%s: ASIC read addr=0x%02x, value=0x%04x\n", - dev->name, (unsigned)off, (unsigned) retval); + dev->name, (unsigned) off, (unsigned) retval); - return(retval); + return retval; } - static void wd_set_ram(wd_t *dev) { uint32_t a13; if ((dev->board_chip & 0xa0) == 0x20) { - a13 = dev->msr & 0x3f; - a13 <<= 13; + a13 = dev->msr & 0x3f; + a13 <<= 13; - dev->ram_addr = a13 | (1 << 19); - mem_mapping_set_addr(&dev->ram_mapping, dev->ram_addr, dev->ram_size); - wdlog("%s: RAM address set to %08X\n", dev->name, dev->ram_addr); + dev->ram_addr = a13 | (1 << 19); + mem_mapping_set_addr(&dev->ram_mapping, dev->ram_addr, dev->ram_size); + wdlog("%s: RAM address set to %08X\n", dev->name, dev->ram_addr); } if (dev->msr & WE_MSR_ENABLE_RAM) - mem_mapping_enable(&dev->ram_mapping); + mem_mapping_enable(&dev->ram_mapping); else - mem_mapping_disable(&dev->ram_mapping); + mem_mapping_disable(&dev->ram_mapping); wdlog("%s: RAM now %sabled\n", dev->name, (dev->msr & WE_MSR_ENABLE_RAM) ? "en" : "dis"); } - static void wd_smc_write(wd_t *dev, uint32_t off, uint32_t val) { uint8_t old; wdlog("%s: ASIC write addr=0x%02x, value=0x%04x\n", - dev->name, (unsigned)off, (unsigned) val); + dev->name, (unsigned) off, (unsigned) val); if (off && (dev->board == WD8003E)) - return; + return; - switch(off) { - /* Bits 0-5: Bits 13-18 of memory address (writable?): - Windows 98 requires this to be preloaded with the initial - addresss to work correctly; - Bit 6: Enable memory if set; - Bit 7: Software reset if set. */ - case 0x00: /* WD Control register */ - old = dev->msr; + switch (off) { + /* Bits 0-5: Bits 13-18 of memory address (writable?): + Windows 98 requires this to be preloaded with the initial + addresss to work correctly; + Bit 6: Enable memory if set; + Bit 7: Software reset if set. */ + case 0x00: /* WD Control register */ + old = dev->msr; - if (!(old & WE_MSR_SOFT_RESET) && (val & WE_MSR_SOFT_RESET)) { - wd_soft_reset(dev); - wdlog("WD80x3: Soft reset\n"); - } + if (!(old & WE_MSR_SOFT_RESET) && (val & WE_MSR_SOFT_RESET)) { + wd_soft_reset(dev); + wdlog("WD80x3: Soft reset\n"); + } - if ((dev->board_chip & 0xa0) == 0x20) - dev->msr = val; - else - dev->msr = (dev->msr & 0x3f) | (val & 0xc0); + if ((dev->board_chip & 0xa0) == 0x20) + dev->msr = val; + else + dev->msr = (dev->msr & 0x3f) | (val & 0xc0); - if ((old &= 0x7f) != (val & 0x7f)) { - wd_set_ram(dev); - wdlog("WD80x3: Memory now %sabled (addr = %08X)\n", (val & WE_MSR_ENABLE_RAM) ? "en" : "dis", dev->ram_addr); - } - break; - - /* Bit 1: 0 = 8-bit slot, 1 = 16-bit slot; - Bit 3: 0 = 8k RAM, 1 = 32k RAM (only on revision < 2). */ - case 0x01: - if (dev->bit16 & 2) - dev->icr = (dev->icr & WE_ICR_16BIT_SLOT) | (val & WE_ICR_16BIT_SLOT); - else - dev->icr = val; - break; - - /* Bit 5: Bit 0 of encoded IRQ; - Bit 6: Bit 1 of encoded IRQ; - Bit 7: Enable interrupts. */ - case 0x04: - if (dev->board_chip & WE_ID_SOFT_CONFIG) - dev->irr = (dev->irr & 0xe0) | (val & 0x1f); - break; + if ((old &= 0x7f) != (val & 0x7f)) { + wd_set_ram(dev); + wdlog("WD80x3: Memory now %sabled (addr = %08X)\n", (val & WE_MSR_ENABLE_RAM) ? "en" : "dis", dev->ram_addr); + } + break; - /* Bits 0-4: Bits 19-23 of memory address (writable?): - Windows 98 requires this to be preloaded with the initial - addresss to work correctly; - Bit 5: Enable software interrupt; - Bit 6: Enable 16-bit RAM for LAN if set; - Bit 7: Enable 16-bit RAM for host if set. */ - case 0x05: - if (dev->board_chip & WE_ID_SOFT_CONFIG) - dev->laar = val; - break; + /* Bit 1: 0 = 8-bit slot, 1 = 16-bit slot; + Bit 3: 0 = 8k RAM, 1 = 32k RAM (only on revision < 2). */ + case 0x01: + if (dev->bit16 & 2) + dev->icr = (dev->icr & WE_ICR_16BIT_SLOT) | (val & WE_ICR_16BIT_SLOT); + else + dev->icr = val; + break; - /* Bits 0-4: Chip ID; - Bit 5: Software configuration is supported if present; - Bit 6: 0 = 16k RAM, 1 = 32k RAM. */ - case 0x07: - if (dev->board_chip & WE_ID_SOFT_CONFIG) - dev->if_chip = val; - break; - - default: - /* This is invalid, but happens under win95 device detection: - maybe some clone cards implement writing for some other - registers? */ - wdlog("%s: ASIC write invalid address %04x, ignoring\n", - dev->name, (unsigned)off); - break; + /* Bit 5: Bit 0 of encoded IRQ; + Bit 6: Bit 1 of encoded IRQ; + Bit 7: Enable interrupts. */ + case 0x04: + if (dev->board_chip & WE_ID_SOFT_CONFIG) + dev->irr = (dev->irr & 0xe0) | (val & 0x1f); + break; + + /* Bits 0-4: Bits 19-23 of memory address (writable?): + Windows 98 requires this to be preloaded with the initial + addresss to work correctly; + Bit 5: Enable software interrupt; + Bit 6: Enable 16-bit RAM for LAN if set; + Bit 7: Enable 16-bit RAM for host if set. */ + case 0x05: + if (dev->board_chip & WE_ID_SOFT_CONFIG) + dev->laar = val; + break; + + /* Bits 0-4: Chip ID; + Bit 5: Software configuration is supported if present; + Bit 6: 0 = 16k RAM, 1 = 32k RAM. */ + case 0x07: + if (dev->board_chip & WE_ID_SOFT_CONFIG) + dev->if_chip = val; + break; + + default: + /* This is invalid, but happens under win95 device detection: + maybe some clone cards implement writing for some other + registers? */ + wdlog("%s: ASIC write invalid address %04x, ignoring\n", + dev->name, (unsigned) off); + break; } } - static uint8_t wd_read(uint16_t addr, void *priv, int len) { - wd_t *dev = (wd_t *)priv; + wd_t *dev = (wd_t *) priv; uint8_t retval = 0; - int off = addr - dev->base_address; + int off = addr - dev->base_address; wdlog("%s: read addr %x\n", dev->name, addr); if (off == 0x10) - retval = dp8390_read_cr(dev->dp8390); + retval = dp8390_read_cr(dev->dp8390); else if ((off >= 0x00) && (off <= 0x0f)) - retval = wd_smc_read(dev, off); + retval = wd_smc_read(dev, off); else { - switch(dev->dp8390->CR.pgsel) { - case 0x00: - retval = dp8390_page0_read(dev->dp8390, off - 0x10, len); - break; - case 0x01: - retval = dp8390_page1_read(dev->dp8390, off - 0x10, len); - break; - case 0x02: - retval = dp8390_page2_read(dev->dp8390, off - 0x10, len); - break; - default: - wdlog("%s: unknown value of pgsel in read - %d\n", - dev->name, dev->dp8390->CR.pgsel); - break; - } + switch (dev->dp8390->CR.pgsel) { + case 0x00: + retval = dp8390_page0_read(dev->dp8390, off - 0x10, len); + break; + case 0x01: + retval = dp8390_page1_read(dev->dp8390, off - 0x10, len); + break; + case 0x02: + retval = dp8390_page2_read(dev->dp8390, off - 0x10, len); + break; + default: + wdlog("%s: unknown value of pgsel in read - %d\n", + dev->name, dev->dp8390->CR.pgsel); + break; + } } - return(retval); + return retval; } - static uint8_t wd_readb(uint16_t addr, void *priv) { wd_t *dev = (wd_t *) priv; - return(wd_read(addr, dev, 1)); + return (wd_read(addr, dev, 1)); } - static uint16_t wd_readw(uint16_t addr, void *priv) { wd_t *dev = (wd_t *) priv; - return(wd_read(addr, dev, 2)); + return (wd_read(addr, dev, 2)); } - static void wd_write(uint16_t addr, uint8_t val, void *priv, unsigned int len) { - wd_t *dev = (wd_t *)priv; - int off = addr - dev->base_address; + wd_t *dev = (wd_t *) priv; + int off = addr - dev->base_address; wdlog("%s: write addr %x, value %x\n", dev->name, addr, val); if (off == 0x10) - dp8390_write_cr(dev->dp8390, val); + dp8390_write_cr(dev->dp8390, val); else if ((off >= 0x00) && (off <= 0x0f)) - wd_smc_write(dev, off, val); + wd_smc_write(dev, off, val); else { - switch(dev->dp8390->CR.pgsel) { - case 0x00: - dp8390_page0_write(dev->dp8390, off - 0x10, val, len); - break; - case 0x01: - dp8390_page1_write(dev->dp8390, off - 0x10, val, len); - break; - default: - wdlog("%s: unknown value of pgsel in write - %d\n", - dev->name, dev->dp8390->CR.pgsel); - break; - } + switch (dev->dp8390->CR.pgsel) { + case 0x00: + dp8390_page0_write(dev->dp8390, off - 0x10, val, len); + break; + case 0x01: + dp8390_page1_write(dev->dp8390, off - 0x10, val, len); + break; + default: + wdlog("%s: unknown value of pgsel in write - %d\n", + dev->name, dev->dp8390->CR.pgsel); + break; + } } } - static void wd_writeb(uint16_t addr, uint8_t val, void *priv) { wd_write(addr, val, priv, 1); } - static void wd_writew(uint16_t addr, uint16_t val, void *priv) { wd_write(addr, val & 0xff, priv, 2); } - static void wd_io_set(wd_t *dev, uint16_t addr) -{ +{ if (dev->bit16 & 1) { - io_sethandler(addr, 0x20, - wd_readb, wd_readw, NULL, - wd_writeb, wd_writew, NULL, dev); + io_sethandler(addr, 0x20, + wd_readb, wd_readw, NULL, + wd_writeb, wd_writew, NULL, dev); } else { - io_sethandler(addr, 0x20, - wd_readb, NULL, NULL, - wd_writeb, NULL, NULL, dev); + io_sethandler(addr, 0x20, + wd_readb, NULL, NULL, + wd_writeb, NULL, NULL, dev); } } - static void wd_io_remove(wd_t *dev, uint16_t addr) -{ +{ if (dev->bit16 & 1) { - io_removehandler(addr, 0x20, - wd_readb, wd_readw, NULL, - wd_writeb, wd_writew, NULL, dev); + io_removehandler(addr, 0x20, + wd_readb, wd_readw, NULL, + wd_writeb, wd_writew, NULL, dev); } else { - io_removehandler(addr, 0x20, - wd_readb, NULL, NULL, - wd_writeb, NULL, NULL, dev); + io_removehandler(addr, 0x20, + wd_readb, NULL, NULL, + wd_writeb, NULL, NULL, dev); } } - static uint8_t wd_mca_read(int port, void *priv) { - wd_t *dev = (wd_t *)priv; + const wd_t *dev = (wd_t *) priv; - return(dev->pos_regs[port & 7]); + return (dev->pos_regs[port & 7]); } - -#define MCA_6FC0_IRQS { 3, 4, 10, 15 } - +#define MCA_6FC0_IRQS \ + { \ + 3, 4, 10, 15 \ + } static void wd_mca_write(int port, uint8_t val, void *priv) { - wd_t *dev = (wd_t *)priv; + wd_t *dev = (wd_t *) priv; int8_t irq[4] = MCA_6FC0_IRQS; /* MCA does not write registers below 0x0100. */ - if (port < 0x0102) return; + if (port < 0x0102) + return; /* Save the MCA register value. */ dev->pos_regs[port & 7] = val; @@ -561,47 +552,111 @@ wd_mca_write(int port, uint8_t val, void *priv) * So, remove current address, if any. */ if (dev->base_address) - wd_io_remove(dev, dev->base_address); + wd_io_remove(dev, dev->base_address); dev->base_address = (dev->pos_regs[2] & 0xfe) << 4; - dev->ram_addr = (dev->pos_regs[3] & 0xfc) << 12; - dev->irq = irq[dev->pos_regs[5] & 0x02]; + dev->ram_addr = (dev->pos_regs[3] & 0xfc) << 12; + dev->irq = irq[dev->pos_regs[5] & 0x03]; /* Initialize the device if fully configured. */ /* Register (new) I/O handler. */ if (dev->pos_regs[2] & 0x01) - wd_io_set(dev, dev->base_address); + wd_io_set(dev, dev->base_address); mem_mapping_set_addr(&dev->ram_mapping, dev->ram_addr, dev->ram_size); mem_mapping_disable(&dev->ram_mapping); if ((dev->msr & WE_MSR_ENABLE_RAM) && (dev->pos_regs[2] & 0x01)) - mem_mapping_enable(&dev->ram_mapping); + mem_mapping_enable(&dev->ram_mapping); wdlog("%s: attached IO=0x%X IRQ=%d, RAM addr=0x%06x\n", dev->name, - dev->base_address, dev->irq, dev->ram_addr); + dev->base_address, dev->irq, dev->ram_addr); } +static void +wd_8013epa_mca_write(int port, uint8_t val, void *priv) +{ + wd_t *dev = (wd_t *) priv; + + /* MCA does not write registers below 0x0100. */ + if (port < 0x0102) + return; + + /* Save the MCA register value. */ + dev->pos_regs[port & 7] = val; + + /* + * The PS/2 Model 80 BIOS always enables a card if it finds one, + * even if no resources were assigned yet (because we only added + * the card, but have not run AutoConfig yet...) + * + * So, remove current address, if any. + */ + if (dev->base_address) + wd_io_remove(dev, dev->base_address); + + dev->base_address = 0x800 + ((dev->pos_regs[2] & 0xf0) << 8); + + switch (dev->pos_regs[5] & 0x0c) { + case 0: + dev->irq = 3; + break; + case 4: + dev->irq = 4; + break; + case 8: + dev->irq = 10; + break; + case 0x0c: + dev->irq = 14; + break; + + default: + break; + } + + if (dev->pos_regs[3] & 0x10) + dev->ram_size = 0x4000; + else + dev->ram_size = 0x2000; + + dev->ram_addr = ((dev->pos_regs[3] & 0x0f) << 13) + 0xc0000; + if (dev->pos_regs[3] & 0x80) + dev->ram_addr += 0xf00000; + + /* Initialize the device if fully configured. */ + /* Register (new) I/O handler. */ + if (dev->pos_regs[2] & 0x01) + wd_io_set(dev, dev->base_address); + + mem_mapping_set_addr(&dev->ram_mapping, dev->ram_addr, dev->ram_size); + + mem_mapping_disable(&dev->ram_mapping); + if ((dev->msr & WE_MSR_ENABLE_RAM) && (dev->pos_regs[2] & 0x01)) + mem_mapping_enable(&dev->ram_mapping); + + wdlog("%s: attached IO=0x%X IRQ=%d, RAM addr=0x%06x\n", dev->name, + dev->base_address, dev->irq, dev->ram_addr); +} static uint8_t -wd_mca_feedb(void *priv) +wd_mca_feedb(UNUSED(void *priv)) { return 1; } - static void * wd_init(const device_t *info) { uint32_t mac; - wd_t *dev; + wd_t *dev; dev = malloc(sizeof(wd_t)); memset(dev, 0x00, sizeof(wd_t)); - dev->name = info->name; + dev->name = info->name; dev->board = info->local; - dev->maclocal[0] = 0x00; /* 00:00:C0 (WD/SMC OID) */ + dev->maclocal[0] = 0x00; /* 00:00:C0 (WD/SMC OID) */ dev->maclocal[1] = 0x00; dev->maclocal[2] = 0xC0; @@ -610,81 +665,97 @@ wd_init(const device_t *info) /* Set up our BIA. */ if (mac & 0xff000000) { - /* Generate new local MAC. */ - dev->maclocal[3] = random_generate(); - dev->maclocal[4] = random_generate(); - dev->maclocal[5] = random_generate(); - mac = (((int) dev->maclocal[3]) << 16); - mac |= (((int) dev->maclocal[4]) << 8); - mac |= ((int) dev->maclocal[5]); - device_set_config_mac("mac", mac); + /* Generate new local MAC. */ + dev->maclocal[3] = random_generate(); + dev->maclocal[4] = random_generate(); + dev->maclocal[5] = random_generate(); + mac = (((int) dev->maclocal[3]) << 16); + mac |= (((int) dev->maclocal[4]) << 8); + mac |= ((int) dev->maclocal[5]); + device_set_config_mac("mac", mac); } else { - dev->maclocal[3] = (mac>>16) & 0xff; - dev->maclocal[4] = (mac>>8) & 0xff; - dev->maclocal[5] = (mac & 0xff); + dev->maclocal[3] = (mac >> 16) & 0xff; + dev->maclocal[4] = (mac >> 8) & 0xff; + dev->maclocal[5] = (mac & 0xff); } - if ((dev->board == WD8003ETA) || (dev->board == WD8003EA)) - mca_add(wd_mca_read, wd_mca_write, wd_mca_feedb, NULL, dev); - else { - dev->base_address = device_get_config_hex16("base"); - dev->irq = device_get_config_int("irq"); - dev->ram_addr = device_get_config_hex20("ram_addr"); + if ((dev->board == WD8003ETA) || (dev->board == WD8003EA) || dev->board == WD8013EPA) { + if (dev->board == WD8013EPA) + mca_add(wd_mca_read, wd_8013epa_mca_write, wd_mca_feedb, NULL, dev); + else + mca_add(wd_mca_read, wd_mca_write, wd_mca_feedb, NULL, dev); + } else { + dev->base_address = device_get_config_hex16("base"); + dev->irq = device_get_config_int("irq"); + dev->ram_addr = device_get_config_hex20("ram_addr"); } - dev->dp8390 = device_add(&dp8390_device); - dev->dp8390->priv = dev; + dev->dp8390 = device_add_inst(&dp8390_device, dp3890_inst++); + dev->dp8390->priv = dev; dev->dp8390->interrupt = wd_interrupt; dp8390_set_defaults(dev->dp8390, DP8390_FLAG_CHECK_CR | DP8390_FLAG_CLEAR_IRQ); - switch(dev->board) { - /* Ethernet, ISA, no interface chip, RAM 8k */ - case WD8003E: - dev->board_chip = WE_TYPE_WD8003E; - dev->ram_size = 0x2000; - break; + switch (dev->board) { + /* Ethernet, ISA, no interface chip, RAM 8k */ + case WD8003E: + dev->board_chip = WE_TYPE_WD8003E; + dev->ram_size = 0x2000; + break; - /* Ethernet, ISA, 5x3 interface chip, RAM 8k or 32k */ - case WD8003EB: - dev->board_chip = WE_TYPE_WD8003EB; - dev->if_chip = 1; - dev->ram_size = device_get_config_int("ram_size"); - if (dev->ram_size == 0x8000) - dev->board_chip |= WE_ID_EXTRA_RAM; + /* Ethernet, ISA, 5x3 interface chip, RAM 8k or 32k */ + case WD8003EB: + dev->board_chip = WE_TYPE_WD8003EB; + dev->if_chip = 1; + dev->ram_size = device_get_config_int("ram_size"); + if (dev->ram_size == 0x8000) + dev->board_chip |= WE_ID_EXTRA_RAM; - /* Bit A19 is implicit 1. */ - dev->msr |= (dev->ram_addr >> 13) & 0x3f; - break; + /* Bit A19 is implicit 1. */ + dev->msr |= (dev->ram_addr >> 13) & 0x3f; + break; - /* Ethernet, ISA, no interface chip, RAM 8k or 32k (8-bit slot) / 16k or 64k (16-bit slot) */ - case WD8013EBT: - dev->board_chip = WE_TYPE_WD8013EBT; - dev->ram_size = device_get_config_int("ram_size"); - if (dev->ram_size == 0x10000) - dev->board_chip |= WE_ID_EXTRA_RAM; + /* Ethernet, ISA, no interface chip, RAM 8k or 32k (8-bit slot) / 16k or 64k (16-bit slot) */ + case WD8013EBT: + dev->board_chip = WE_TYPE_WD8013EBT; + dev->ram_size = device_get_config_int("ram_size"); + if (dev->ram_size == 0x10000) + dev->board_chip |= WE_ID_EXTRA_RAM; - dev->bit16 = 2; - if (is286) - dev->bit16 |= 1; - else { - dev->bit16 |= 0; - if (dev->irq == 9) - dev->irq = 2; - dev->ram_size >>= 1; /* Half the RAM when in 8-bit slot. */ - } - break; + dev->bit16 = 2; + if (is286) + dev->bit16 |= 1; + else { + dev->bit16 |= 0; + if (dev->irq == 9) + dev->irq = 2; + dev->ram_size >>= 1; /* Half the RAM when in 8-bit slot. */ + } + break; - /* Ethernet, MCA, 5x3 interface chip, RAM 16k */ - case WD8003EA: - dev->board_chip = WE_ID_SOFT_CONFIG; - /* Ethernet, MCA, no interface chip, RAM 16k */ - case WD8003ETA: - dev->board_chip |= 0x05 | WE_ID_BUS_MCA; - dev->ram_size = 0x4000; - dev->pos_regs[0] = 0xC0; - dev->pos_regs[1] = 0x6F; - dev->bit16 = 3; - break; + /* Ethernet, MCA, 5x3 interface chip, RAM 16k */ + case WD8003EA: + dev->board_chip = WE_ID_SOFT_CONFIG; + fallthrough; + + /* Ethernet, MCA, no interface chip, RAM 16k */ + case WD8003ETA: + dev->board_chip |= WE_TYPE_WD8013EBT | WE_ID_BUS_MCA; + dev->ram_size = 0x4000; + dev->pos_regs[0] = 0xC0; + dev->pos_regs[1] = 0x6F; + dev->bit16 = 3; + break; + + case WD8013EPA: + dev->board_chip = WE_TYPE_WD8013EP | WE_ID_BUS_MCA; + dev->ram_size = device_get_config_int("ram_size"); + dev->pos_regs[0] = 0xC8; + dev->pos_regs[1] = 0x61; + dev->bit16 = 3; + break; + + default: + break; } dev->irr |= WE_IRR_ENABLE_IRQ; @@ -693,424 +764,398 @@ wd_init(const device_t *info) dp8390_mem_alloc(dev->dp8390, 0x0000, dev->ram_size); if (dev->base_address) - wd_io_set(dev, dev->base_address); + wd_io_set(dev, dev->base_address); memcpy(dev->dp8390->physaddr, dev->maclocal, sizeof(dev->maclocal)); wdlog("%s: I/O=%04x, IRQ=%d, MAC=%02x:%02x:%02x:%02x:%02x:%02x\n", - dev->name, dev->base_address, dev->irq, - dev->dp8390->physaddr[0], dev->dp8390->physaddr[1], dev->dp8390->physaddr[2], - dev->dp8390->physaddr[3], dev->dp8390->physaddr[4], dev->dp8390->physaddr[5]); + dev->name, dev->base_address, dev->irq, + dev->dp8390->physaddr[0], dev->dp8390->physaddr[1], dev->dp8390->physaddr[2], + dev->dp8390->physaddr[3], dev->dp8390->physaddr[4], dev->dp8390->physaddr[5]); /* Reset the board. */ wd_reset(dev); /* Map this system into the memory map. */ mem_mapping_add(&dev->ram_mapping, dev->ram_addr, dev->ram_size, - wd_ram_read, NULL, NULL, - wd_ram_write, NULL, NULL, - NULL, MEM_MAPPING_EXTERNAL, dev); + wd_ram_read, NULL, NULL, + wd_ram_write, NULL, NULL, + NULL, MEM_MAPPING_EXTERNAL, dev); - mem_mapping_disable(&dev->ram_mapping); + mem_mapping_disable(&dev->ram_mapping); /* Attach ourselves to the network module. */ - network_attach(dev->dp8390, dev->dp8390->physaddr, dp8390_rx, NULL, NULL); + dev->dp8390->card = network_attach(dev->dp8390, dev->dp8390->physaddr, dp8390_rx, NULL); if (!(dev->board_chip & WE_ID_BUS_MCA)) { - wdlog("%s: attached IO=0x%X IRQ=%d, RAM addr=0x%06x\n", dev->name, - dev->base_address, dev->irq, dev->ram_addr); + wdlog("%s: attached IO=0x%X IRQ=%d, RAM addr=0x%06x\n", dev->name, + dev->base_address, dev->irq, dev->ram_addr); } - return(dev); + return dev; } - static void wd_close(void *priv) { - wd_t *dev = (wd_t *)priv; + wd_t *dev = (wd_t *) priv; wdlog("%s: closed\n", dev->name); free(dev); } - -static const device_config_t wd8003_config[] = -{ - { - "base", "Address", CONFIG_HEX16, "", 0x300, "", { 0 }, - { - { - "0x240", 0x240 - }, - { - "0x280", 0x280 - }, - { - "0x300", 0x300 - }, - { - "0x380", 0x380 - }, - { - "" - } - }, - }, - { - "irq", "IRQ", CONFIG_SELECTION, "", 3, "", { 0 }, - { - { - "IRQ 2", 2 - }, - { - "IRQ 3", 3 - }, - { - "IRQ 5", 5 - }, - { - "IRQ 7", 7 - }, - { - "" - } - }, - }, - { - "ram_addr", "RAM address", CONFIG_HEX20, "", 0xD0000, "", { 0 }, - { - { - "C800", 0xC8000 - }, - { - "CC00", 0xCC000 - }, - { - "D000", 0xD0000 - }, - { - "D400", 0xD4000 - }, - { - "D800", 0xD8000 - }, - { - "DC00", 0xDC000 - }, - { - "" - } - }, - }, - { - "mac", "MAC Address", CONFIG_MAC, "", -1 - }, - { - "", "", -1 - } +// clang-format off +static const device_config_t wd8003_config[] = { + { + .name = "base", + .description = "Address", + .type = CONFIG_HEX16, + .default_string = "", + .default_int = 0x300, + .file_filter = "", + .spinner = { 0 }, + .selection = { + { .description = "0x240", .value = 0x240 }, + { .description = "0x280", .value = 0x280 }, + { .description = "0x300", .value = 0x300 }, + { .description = "0x380", .value = 0x380 }, + { .description = "" } + }, + }, + { + .name = "irq", + .description = "IRQ", + .type = CONFIG_SELECTION, + .default_string = "", + .default_int = 3, + .file_filter = "", + .spinner = { 0 }, + .selection = { + { .description = "IRQ 2", .value = 2 }, + { .description = "IRQ 3", .value = 3 }, + { .description = "IRQ 5", .value = 5 }, + { .description = "IRQ 7", .value = 7 }, + { .description = "" } + }, + }, + { + .name = "ram_addr", + .description = "RAM address", + .type = CONFIG_HEX20, + .default_string = "", + .default_int = 0xD0000, + .file_filter = "", + .spinner = { 0 }, + .selection = { + { .description = "C800", .value = 0xC8000 }, + { .description = "CC00", .value = 0xCC000 }, + { .description = "D000", .value = 0xD0000 }, + { .description = "D400", .value = 0xD4000 }, + { .description = "D800", .value = 0xD8000 }, + { .description = "DC00", .value = 0xDC000 }, + { .description = "" } + }, + }, + { + .name = "mac", + .description = "MAC Address", + .type = CONFIG_MAC, + .default_string = "", + .default_int = -1 + }, + { .name = "", .description = "", .type = CONFIG_END } }; -static const device_config_t wd8003eb_config[] = -{ - { - "base", "Address", CONFIG_HEX16, "", 0x280, "", { 0 }, - { - { - "0x200", 0x200 - }, - { - "0x220", 0x220 - }, - { - "0x240", 0x240 - }, - { - "0x260", 0x260 - }, - { - "0x280", 0x280 - }, - { - "0x2A0", 0x2A0 - }, - { - "0x2C0", 0x2C0 - }, - { - "0x300", 0x300 - }, - { - "0x340", 0x340 - }, - { - "0x380", 0x380 - }, - { - "" - } - }, - }, - { - "irq", "IRQ", CONFIG_SELECTION, "", 3, "", { 0 }, - { - { - "IRQ 2/9", 9 - }, - { - "IRQ 3", 3 - }, - { - "IRQ 4", 4 - }, - { - "IRQ 7", 7 - }, - { - "" - } - }, - }, - { - "ram_addr", "RAM address", CONFIG_HEX20, "", 0xD0000, "", { 0 }, - { - { - "C000", 0xC0000 - }, - { - "C400", 0xC4000 - }, - { - "C800", 0xC8000 - }, - { - "CC00", 0xCC000 - }, - { - "D000", 0xD0000 - }, - { - "D400", 0xD4000 - }, - { - "D800", 0xD8000 - }, - { - "DC00", 0xDC000 - }, - { - "" - } - }, - }, - { - "ram_size", "RAM size", CONFIG_SELECTION, "", 8192, "", { 0 }, - { - { - "8 kB", 8192 - }, - { - "32 kB", 32768 - }, - { - "" - } - }, - }, - { - "mac", "MAC Address", CONFIG_MAC, "", -1 - }, - { - "", "", -1 - } +static const device_config_t wd8003eb_config[] = { + { + .name = "base", + .description = "Address", + .type = CONFIG_HEX16, + .default_string = "", + .default_int = 0x280, + .file_filter = "", + .spinner = { 0 }, + .selection = { + { .description = "0x200", .value = 0x200 }, + { .description = "0x220", .value = 0x220 }, + { .description = "0x240", .value = 0x240 }, + { .description = "0x260", .value = 0x260 }, + { .description = "0x280", .value = 0x280 }, + { .description = "0x2A0", .value = 0x2A0 }, + { .description = "0x2C0", .value = 0x2C0 }, + { .description = "0x300", .value = 0x300 }, + { .description = "0x340", .value = 0x340 }, + { .description = "0x380", .value = 0x380 }, + { .description = "" } + }, + }, + { + .name = "irq", + .description = "IRQ", + .type = CONFIG_SELECTION, + .default_string = "", + .default_int = 3, + .file_filter = "", + .spinner = { 0 }, + .selection = { + { .description = "IRQ 2/9", .value = 9 }, + { .description = "IRQ 3", .value = 3 }, + { .description = "IRQ 4", .value = 4 }, + { .description = "IRQ 7", .value = 7 }, + { .description = "" } + }, + }, + { + .name = "ram_addr", + .description = "RAM address", + .type = CONFIG_HEX20, + .default_string = "", + .default_int = 0xD0000, + .file_filter = "", + .spinner = { 0 }, + .selection = { + { .description = "C000", .value = 0xC0000 }, + { .description = "C400", .value = 0xC4000 }, + { .description = "C800", .value = 0xC8000 }, + { .description = "CC00", .value = 0xCC000 }, + { .description = "D000", .value = 0xD0000 }, + { .description = "D400", .value = 0xD4000 }, + { .description = "D800", .value = 0xD8000 }, + { .description = "DC00", .value = 0xDC000 }, + { .description = "" } + }, + }, + { + .name = "ram_size", + .description = "RAM size", + .type = CONFIG_SELECTION, + .default_string = "", + .default_int = 8192, + .file_filter = "", + .spinner = { 0 }, + .selection = { + { .description = "8 kB", .value = 8192 }, + { .description = "32 kB", .value = 32768 }, + { .description = "" } + }, + }, + { + .name = "mac", + .description = "MAC Address", + .type = CONFIG_MAC, + .default_string = "", + .default_int = -1 + }, + { .name = "", .description = "", .type = CONFIG_END } }; /* WD8013EBT configuration and defaults set according to this site: http://www.stack.nl/~marcolz/network/wd80x3.html#WD8013EBT */ -static const device_config_t wd8013_config[] = -{ - { - "base", "Address", CONFIG_HEX16, "", 0x280, "", { 0 }, - { - { - "0x200", 0x200 - }, - { - "0x220", 0x220 - }, - { - "0x240", 0x240 - }, - { - "0x260", 0x260 - }, - { - "0x280", 0x280 - }, - { - "0x2A0", 0x2A0 - }, - { - "0x2C0", 0x2C0 - }, - { - "0x300", 0x300 - }, - { - "0x340", 0x340 - }, - { - "0x380", 0x380 - }, - { - "" - } - }, - }, - { - "irq", "IRQ", CONFIG_SELECTION, "", 3, "", { 0 }, - { - { - "IRQ 2/9", 9 - }, - { - "IRQ 3", 3 - }, - { - "IRQ 4", 4 - }, - { - "IRQ 5", 5 - }, - { - "IRQ 7", 7 - }, - { - "IRQ 10", 10 - }, - { - "IRQ 11", 11 - }, - { - "IRQ 15", 15 - }, - { - "" - } - }, - }, - { - "ram_addr", "RAM address", CONFIG_HEX20, "", 0xD0000, "", { 0 }, - { - { - "C000", 0xC0000 - }, - { - "C400", 0xC4000 - }, - { - "C800", 0xC8000 - }, - { - "CC00", 0xCC000 - }, - { - "D000", 0xD0000 - }, - { - "D400", 0xD4000 - }, - { - "D800", 0xD8000 - }, - { - "DC00", 0xDC000 - }, - { - "" - } - }, - }, - { - "ram_size", "RAM size", CONFIG_SELECTION, "", 16384, "", { 0 }, - { - { - "16 kB", 16384 - }, - { - "64 kB", 65536 - }, - { - "" - } - }, - }, - { - "mac", "MAC Address", CONFIG_MAC, "", -1 - }, - { - "", "", -1 - } +static const device_config_t wd8013_config[] = { + { + .name = "base", + .description = "Address", + .type = CONFIG_HEX16, + .default_string = "", + .default_int = 0x280, + .file_filter = "", + .spinner = { 0 }, + .selection = { + { .description = "0x200", .value = 0x200 }, + { .description = "0x220", .value = 0x220 }, + { .description = "0x240", .value = 0x240 }, + { .description = "0x260", .value = 0x260 }, + { .description = "0x280", .value = 0x280 }, + { .description = "0x2A0", .value = 0x2A0 }, + { .description = "0x2C0", .value = 0x2C0 }, + { .description = "0x300", .value = 0x300 }, + { .description = "0x340", .value = 0x340 }, + { .description = "0x380", .value = 0x380 }, + { .description = "" } + }, + }, + { + .name = "irq", + .description = "IRQ", + .type = CONFIG_SELECTION, + .default_string = "", + .default_int = 3, + .file_filter = "", + .spinner = { 0 }, + .selection = { + { .description = "IRQ 2/9", .value = 9 }, + { .description = "IRQ 3", .value = 3 }, + { .description = "IRQ 4", .value = 4 }, + { .description = "IRQ 5", .value = 5 }, + { .description = "IRQ 7", .value = 7 }, + { .description = "IRQ 10", .value = 10 }, + { .description = "IRQ 11", .value = 11 }, + { .description = "IRQ 15", .value = 15 }, + { .description = "" } + }, + }, + { + .name = "ram_addr", + .description = "RAM address", + .type = CONFIG_HEX20, + .default_string = "", + .default_int = 0xD0000, + .file_filter = "", + .spinner = { 0 }, + .selection = { + { .description = "C000", .value = 0xC0000 }, + { .description = "C400", .value = 0xC4000 }, + { .description = "C800", .value = 0xC8000 }, + { .description = "CC00", .value = 0xCC000 }, + { .description = "D000", .value = 0xD0000 }, + { .description = "D400", .value = 0xD4000 }, + { .description = "D800", .value = 0xD8000 }, + { .description = "DC00", .value = 0xDC000 }, + { .description = "" } + }, + }, + { + .name = "ram_size", + .description = "RAM size", + .type = CONFIG_SELECTION, + .default_string = "", + .default_int = 16384, + .file_filter = "", + .spinner = { 0 }, + .selection = { + { .description = "16 kB", .value = 16384 }, + { .description = "64 kB", .value = 65536 }, + { .description = "" } + }, + }, + { + .name = "mac", + .description = "MAC Address", + .type = CONFIG_MAC, + .default_string = "", + .default_int = -1 + }, + { .name = "", .description = "", .type = CONFIG_END } }; -static const device_config_t mca_mac_config[] = -{ - { - "mac", "MAC Address", CONFIG_MAC, "", -1 - }, - { - "", "", -1 - } +static const device_config_t wd8013epa_config[] = { + { + .name = "ram_size", + .description = "Initial RAM size", + .type = CONFIG_SELECTION, + .default_string = "", + .default_int = 16384, + .file_filter = "", + .spinner = { 0 }, + .selection = { + { .description = "8 kB", .value = 8192 }, + { .description = "16 kB", .value = 16384 }, + { .description = "" } + }, + }, + { + .name = "mac", + .description = "MAC Address", + .type = CONFIG_MAC, + .default_string = "", + .default_int = -1 + }, + { .name = "", .description = "", .type = CONFIG_END } }; +static const device_config_t mca_mac_config[] = { + { + .name = "mac", + .description = "MAC Address", + .type = CONFIG_MAC, + .default_string = "", + .default_int = -1 + }, + { .name = "", .description = "", .type = CONFIG_END } +}; +// clang-format on const device_t wd8003e_device = { - "Western Digital WD8003E", - "wd8003e", - DEVICE_ISA, - WD8003E, - wd_init, wd_close, NULL, - { NULL }, NULL, NULL, - wd8003_config + .name = "Western Digital WD8003E", + .internal_name = "wd8003e", + .flags = DEVICE_ISA, + .local = WD8003E, + .init = wd_init, + .close = wd_close, + .reset = NULL, + { .available = NULL }, + .speed_changed = NULL, + .force_redraw = NULL, + .config = wd8003_config }; const device_t wd8003eb_device = { - "Western Digital WD8003EB", - "wd8003eb", - DEVICE_ISA, - WD8003EB, - wd_init, wd_close, NULL, - { NULL }, NULL, NULL, - wd8003eb_config + .name = "Western Digital WD8003EB", + .internal_name = "wd8003eb", + .flags = DEVICE_ISA, + .local = WD8003EB, + .init = wd_init, + .close = wd_close, + .reset = NULL, + { .available = NULL }, + .speed_changed = NULL, + .force_redraw = NULL, + .config = wd8003eb_config }; const device_t wd8013ebt_device = { - "Western Digital WD8013EBT", - "wd8013ebt", - DEVICE_ISA, - WD8013EBT, - wd_init, wd_close, NULL, - { NULL }, NULL, NULL, - wd8013_config + .name = "Western Digital WD8013EBT", + .internal_name = "wd8013ebt", + .flags = DEVICE_ISA, + .local = WD8013EBT, + .init = wd_init, + .close = wd_close, + .reset = NULL, + { .available = NULL }, + .speed_changed = NULL, + .force_redraw = NULL, + .config = wd8013_config }; const device_t wd8003eta_device = { - "Western Digital WD8003ET/A", - "wd8003eta", - DEVICE_MCA, - WD8003ETA, - wd_init, wd_close, NULL, - { NULL }, NULL, NULL, - mca_mac_config + .name = "Western Digital WD8003ET/A", + .internal_name = "wd8003eta", + .flags = DEVICE_MCA, + .local = WD8003ETA, + .init = wd_init, + .close = wd_close, + .reset = NULL, + { .available = NULL }, + .speed_changed = NULL, + .force_redraw = NULL, + .config = mca_mac_config }; const device_t wd8003ea_device = { - "Western Digital WD8003E/A", - "wd8003ea", - DEVICE_MCA, - WD8003EA, - wd_init, wd_close, NULL, - { NULL }, NULL, NULL, - mca_mac_config + .name = "Western Digital WD8003E/A", + .internal_name = "wd8003ea", + .flags = DEVICE_MCA, + .local = WD8003EA, + .init = wd_init, + .close = wd_close, + .reset = NULL, + { .available = NULL }, + .speed_changed = NULL, + .force_redraw = NULL, + .config = mca_mac_config +}; + +const device_t wd8013epa_device = { + .name = "Western Digital WD8013EP/A", + .internal_name = "wd8013epa", + .flags = DEVICE_MCA, + .local = WD8013EPA, + .init = wd_init, + .close = wd_close, + .reset = NULL, + { .available = NULL }, + .speed_changed = NULL, + .force_redraw = NULL, + .config = wd8013epa_config }; diff --git a/src/network/network.c b/src/network/network.c index fad9eacbc..47f009fba 100644 --- a/src/network/network.c +++ b/src/network/network.c @@ -1,40 +1,38 @@ /* - * VARCem Virtual ARchaeological Computer EMulator. - * An emulator of (mostly) x86-based PC systems and devices, - * using the ISA,EISA,VLB,MCA and PCI system buses, roughly - * spanning the era between 1981 and 1995. + * VARCem Virtual ARchaeological Computer EMulator. + * An emulator of (mostly) x86-based PC systems and devices, + * using the ISA,EISA,VLB,MCA and PCI system buses, roughly + * spanning the era between 1981 and 1995. * - * This file is part of the VARCem Project. + * Implementation of the network module. * - * Implementation of the network module. - * - * NOTE The definition of the netcard_t is currently not optimal; - * it should be malloc'ed and then linked to the NETCARD def. - * Will be done later. + * NOTE The definition of the netcard_t is currently not optimal; + * it should be malloc'ed and then linked to the NETCARD def. + * Will be done later. * * * - * Author: Fred N. van Kempen, + * Authors: Fred N. van Kempen, * - * Copyright 2017-2019 Fred N. van Kempen. + * Copyright 2017-2019 Fred N. van Kempen. * - * Redistribution and use in source and binary forms, with - * or without modification, are permitted provided that the - * following conditions are met: + * Redistribution and use in source and binary forms, with + * or without modification, are permitted provided that the + * following conditions are met: * - * 1. Redistributions of source code must retain the entire - * above notice, this list of conditions and the following - * disclaimer. + * 1. Redistributions of source code must retain the entire + * above notice, this list of conditions and the following + * disclaimer. * - * 2. Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the - * following disclaimer in the documentation and/or other - * materials provided with the distribution. + * 2. Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the + * following disclaimer in the documentation and/or other + * materials provided with the distribution. * - * 3. Neither the name of the copyright holder nor the names - * of its contributors may be used to endorse or promote - * products derived from this software without specific - * prior written permission. + * 3. Neither the name of the copyright holder nor the names + * of its contributors may be used to endorse or promote + * products derived from this software without specific + * prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT @@ -56,177 +54,157 @@ #include #include #include +#ifndef _WIN32 +# include +#endif /* _WIN32 */ +#include #define HAVE_STDARG_H #include <86box/86box.h> #include <86box/device.h> #include <86box/timer.h> #include <86box/plat.h> +#include <86box/thread.h> #include <86box/ui.h> +#include <86box/timer.h> #include <86box/network.h> +#include <86box/net_3c501.h> #include <86box/net_3c503.h> #include <86box/net_ne2000.h> #include <86box/net_pcnet.h> #include <86box/net_plip.h> #include <86box/net_wd8003.h> +#ifdef _WIN32 +# define WIN32_LEAN_AND_MEAN +# include +# include +#endif static const device_t net_none_device = { - "None", - "none", - 0, NET_TYPE_NONE, - NULL, NULL, NULL, - { NULL }, NULL, NULL, + .name = "None", + .internal_name = "none", + .flags = 0, + .local = NET_TYPE_NONE, + .init = NULL, + .close = NULL, + .reset = NULL, + { .available = NULL }, + .speed_changed = NULL, + .force_redraw = NULL, + .config = NULL +}; + +static const device_t net_internal_device = { + .name = "Internal", + .internal_name = "internal", + .flags = 0, + .local = NET_TYPE_NONE, + .init = NULL, + .close = NULL, + .reset = NULL, + { .available = NULL }, + .speed_changed = NULL, + .force_redraw = NULL, + .config = NULL +}; + +static const device_t *net_cards[] = { + &net_none_device, + &net_internal_device, + &threec501_device, + &threec503_device, + &pcnet_am79c960_device, + &pcnet_am79c961_device, + &ne1000_device, + &ne2000_device, + &pcnet_am79c960_eb_device, + &rtl8019as_device, + &wd8003e_device, + &wd8003eb_device, + &wd8013ebt_device, + &plip_device, + ðernext_mc_device, + &wd8003eta_device, + &wd8003ea_device, + &wd8013epa_device, + &pcnet_am79c973_device, + &pcnet_am79c970a_device, + &rtl8029as_device, + &pcnet_am79c960_vlb_device, NULL }; - -static netcard_t net_cards[] = { - { &net_none_device, NULL }, - { &threec503_device, NULL }, - { &pcnet_am79c960_device, NULL }, - { &pcnet_am79c961_device, NULL }, - { &ne1000_device, NULL }, - { &ne2000_device, NULL }, - { &pcnet_am79c960_eb_device, NULL }, - { &rtl8019as_device, NULL }, - { &wd8003e_device, NULL }, - { &wd8003eb_device, NULL }, - { &wd8013ebt_device, NULL }, - { &plip_device, NULL }, - { ðernext_mc_device, NULL }, - { &wd8003eta_device, NULL }, - { &wd8003ea_device, NULL }, - { &pcnet_am79c973_device, NULL }, - { &pcnet_am79c970a_device, NULL }, - { &rtl8029as_device, NULL }, - { &pcnet_am79c960_vlb_device, NULL }, - { NULL, NULL } -}; - +netcard_conf_t net_cards_conf[NET_CARD_MAX]; +uint16_t net_card_current = 0; /* Global variables. */ -int network_type; -int network_ndev; -int network_card; -char network_host[522]; -netdev_t network_devs[32]; -int network_rx_pause = 0, - network_tx_pause = 0; - +network_devmap_t network_devmap = {0}; +int network_ndev; +netdev_t network_devs[NET_HOST_INTF_MAX]; /* Local variables. */ -static volatile atomic_int net_wait = 0; -static mutex_t *network_mutex; -static uint8_t *network_mac; -static uint8_t network_timer_active = 0; -static pc_timer_t network_rx_queue_timer; -static netpkt_t *first_pkt[2] = { NULL, NULL }, - *last_pkt[2] = { NULL, NULL }; - -static struct { - volatile int busy, - queue_in_use; - - event_t *wake_poll_thread, - *poll_complete, - *queue_not_in_use; -} poll_data; - - -#ifdef ENABLE_NETWORK_LOG -int network_do_log = ENABLE_NETWORK_LOG; -static FILE *network_dump = NULL; +#if defined ENABLE_NETWORK_LOG && !defined(_WIN32) +int network_do_log = ENABLE_NETWORK_LOG; +static FILE *network_dump = NULL; static mutex_t *network_dump_mutex; - static void network_log(const char *fmt, ...) { va_list ap; if (network_do_log) { - va_start(ap, fmt); - pclog_ex(fmt, ap); - va_end(ap); + va_start(ap, fmt); + pclog_ex(fmt, ap); + va_end(ap); } } - static void network_dump_packet(netpkt_t *pkt) { if (!network_dump) - return; + return; struct timeval tv; gettimeofday(&tv, NULL); struct { - uint32_t ts_sec, ts_usec, incl_len, orig_len; + uint32_t ts_sec, ts_usec, incl_len, orig_len; } pcap_packet_hdr = { - tv.tv_sec, tv.tv_usec, pkt->len, pkt->len + tv.tv_sec, tv.tv_usec, pkt->len, pkt->len }; if (network_dump_mutex) - thread_wait_mutex(network_dump_mutex); + thread_wait_mutex(network_dump_mutex); size_t written; if ((written = fwrite(&pcap_packet_hdr, 1, sizeof(pcap_packet_hdr), network_dump)) < sizeof(pcap_packet_hdr)) { - network_log("NETWORK: failed to write dump packet header\n"); - fseek(network_dump, -written, SEEK_CUR); + network_log("NETWORK: failed to write dump packet header\n"); + fseek(network_dump, -written, SEEK_CUR); } else { - if ((written = fwrite(pkt->data, 1, pkt->len, network_dump)) < pkt->len) { - network_log("NETWORK: failed to write dump packet data\n"); - fseek(network_dump, -written - sizeof(pcap_packet_hdr), SEEK_CUR); - } - fflush(network_dump); + if ((written = fwrite(pkt->data, 1, pkt->len, network_dump)) < pkt->len) { + network_log("NETWORK: failed to write dump packet data\n"); + fseek(network_dump, -written - sizeof(pcap_packet_hdr), SEEK_CUR); + } + fflush(network_dump); } if (network_dump_mutex) - thread_release_mutex(network_dump_mutex); + thread_release_mutex(network_dump_mutex); } #else -#define network_log(fmt, ...) -#define network_dump_packet(pkt) +# define network_log(fmt, ...) +# define network_dump_packet(pkt) #endif - -void -network_wait(uint8_t wait) +#ifdef _WIN32 +static void +network_winsock_clean(void) { - if (wait) - thread_wait_mutex(network_mutex); - else - thread_release_mutex(network_mutex); + WSACleanup(); } - - -void -network_poll(void) -{ - while (poll_data.busy) - thread_wait_event(poll_data.wake_poll_thread, -1); - - thread_reset_event(poll_data.wake_poll_thread); -} - - -void -network_busy(uint8_t set) -{ - poll_data.busy = !!set; - - if (! set) - thread_set_event(poll_data.wake_poll_thread); -} - - -void -network_end(void) -{ - thread_set_event(poll_data.poll_complete); -} - +#endif /* * Initialize the configured network cards. @@ -240,9 +218,11 @@ network_init(void) { int i; - /* Initialize to a known state. */ - network_type = NET_TYPE_NONE; - network_card = 0; +#ifdef _WIN32 + WSADATA Data; + WSAStartup(MAKEWORD(2, 0), &Data); + atexit(network_winsock_clean); +#endif /* Create a first device entry that's always there, as needed by UI. */ strcpy(network_devs[0].device, "none"); @@ -250,130 +230,213 @@ network_init(void) network_ndev = 1; /* Initialize the Pcap system module, if present. */ - i = net_pcap_prepare(&network_devs[network_ndev]); - if (i > 0) - network_ndev += i; -#ifdef ENABLE_NETWORK_LOG + network_devmap.has_slirp = 1; + i = net_pcap_prepare(&network_devs[network_ndev]); + if (i > 0) { + network_devmap.has_pcap = 1; + network_ndev += i; + } + +#ifdef HAS_VDE + // Try to load the VDE plug library + if(net_vde_prepare()==0) { + network_devmap.has_vde = 1; + } +#endif + +#if defined ENABLE_NETWORK_LOG && !defined(_WIN32) /* Start packet dump. */ network_dump = fopen("network.pcap", "wb"); struct { - uint32_t magic_number; - uint16_t version_major, version_minor; - int32_t thiszone; - uint32_t sigfigs, snaplen, network; + uint32_t magic_number; + uint16_t version_major, version_minor; + int32_t thiszone; + uint32_t sigfigs, snaplen, network; } pcap_hdr = { - 0xa1b2c3d4, - 2, 4, - 0, - 0, 65535, 1 + 0xa1b2c3d4, + 2, 4, + 0, + 0, 65535, 1 }; fwrite(&pcap_hdr, sizeof(pcap_hdr), 1, network_dump); fflush(network_dump); #endif } +void +network_queue_init(netqueue_t *queue) +{ + queue->head = queue->tail = 0; + for (int i = 0; i < NET_QUEUE_LEN; i++) { + queue->packets[i].data = calloc(1, NET_MAX_FRAME); + queue->packets[i].len = 0; + } +} + +static bool +network_queue_full(netqueue_t *queue) +{ + return ((queue->head + 1) & NET_QUEUE_LEN_MASK) == queue->tail; +} + +static bool +network_queue_empty(netqueue_t *queue) +{ + return (queue->head == queue->tail); +} + +static inline void +network_swap_packet(netpkt_t *pkt1, netpkt_t *pkt2) +{ + netpkt_t tmp = *pkt2; + *pkt2 = *pkt1; + *pkt1 = tmp; +} + +int +network_queue_put(netqueue_t *queue, uint8_t *data, int len) +{ + if (len == 0 || len > NET_MAX_FRAME || network_queue_full(queue)) { + return 0; + } + + netpkt_t *pkt = &queue->packets[queue->head]; + memcpy(pkt->data, data, len); + pkt->len = len; + queue->head = (queue->head + 1) & NET_QUEUE_LEN_MASK; + return 1; +} + +int +network_queue_put_swap(netqueue_t *queue, netpkt_t *src_pkt) +{ + if (src_pkt->len == 0 || src_pkt->len > NET_MAX_FRAME || network_queue_full(queue)) { +#ifdef DEBUG + if (src_pkt->len == 0) { + network_log("Discarded zero length packet.\n"); + } else if (src_pkt->len > NET_MAX_FRAME) { + network_log("Discarded oversized packet of len=%d.\n", src_pkt->len); + network_dump_packet(src_pkt); + } else { + network_log("Discarded %d bytes packet because the queue is full.\n", src_pkt->len); + network_dump_packet(src_pkt); + } +#endif + return 0; + } + + netpkt_t *dst_pkt = &queue->packets[queue->head]; + network_swap_packet(src_pkt, dst_pkt); + + queue->head = (queue->head + 1) & NET_QUEUE_LEN_MASK; + return 1; +} + +static int +network_queue_get_swap(netqueue_t *queue, netpkt_t *dst_pkt) +{ + if (network_queue_empty(queue)) + return 0; + + netpkt_t *src_pkt = &queue->packets[queue->tail]; + network_swap_packet(src_pkt, dst_pkt); + queue->tail = (queue->tail + 1) & NET_QUEUE_LEN_MASK; + return 1; +} + +static int +network_queue_move(netqueue_t *dst_q, netqueue_t *src_q) +{ + if (network_queue_empty(src_q)) + return 0; + + if (network_queue_full(dst_q)) { + return 0; + } + + netpkt_t *src_pkt = &src_q->packets[src_q->tail]; + netpkt_t *dst_pkt = &dst_q->packets[dst_q->head]; + + network_swap_packet(src_pkt, dst_pkt); + dst_q->head = (dst_q->head + 1) & NET_QUEUE_LEN_MASK; + src_q->tail = (src_q->tail + 1) & NET_QUEUE_LEN_MASK; + + return dst_pkt->len; +} void -network_queue_put(int tx, void *priv, uint8_t *data, int len) +network_queue_clear(netqueue_t *queue) { - netpkt_t *temp; - - temp = (netpkt_t *) malloc(sizeof(netpkt_t)); - memset(temp, 0, sizeof(netpkt_t)); - temp->priv = priv; - memcpy(temp->data, data, len); - temp->len = len; - temp->prev = last_pkt[tx]; - temp->next = NULL; - - if (last_pkt[tx] != NULL) - last_pkt[tx]->next = temp; - last_pkt[tx] = temp; - - if (first_pkt[tx] == NULL) - first_pkt[tx] = temp; + for (int i = 0; i < NET_QUEUE_LEN; i++) { + free(queue->packets[i].data); + queue->packets[i].len = 0; + } + queue->tail = queue->head = 0; } - -static void -network_queue_get(int tx, netpkt_t **pkt) -{ - if (first_pkt[tx] == NULL) - *pkt = NULL; - else - *pkt = first_pkt[tx]; -} - - -static void -network_queue_advance(int tx) -{ - netpkt_t *temp; - - temp = first_pkt[tx]; - - if (temp == NULL) - return; - - first_pkt[tx] = temp->next; - free(temp); - - if (first_pkt[tx] == NULL) - last_pkt[tx] = NULL; -} - - -static void -network_queue_clear(int tx) -{ - netpkt_t *temp = first_pkt[tx], *temp2; - - if (temp == NULL) - return; - - do { - temp2 = temp->next; - free(temp); - temp = temp2; - } while (temp != NULL); - - first_pkt[tx] = last_pkt[tx] = NULL; -} - - static void network_rx_queue(void *priv) { - int ret = 1; + netcard_t *card = (netcard_t *) priv; - if (network_rx_pause) { - timer_on_auto(&network_rx_queue_timer, 0.762939453125 * 2.0 * 128.0); - return; + uint32_t new_link_state = net_cards_conf[card->card_num].link_state; + if (new_link_state != card->link_state) { + if (card->set_link_state) + card->set_link_state(card->card_drv, new_link_state); + card->link_state = new_link_state; } - netpkt_t *pkt = NULL; + uint32_t rx_bytes = 0; + for (int i = 0; i < NET_QUEUE_LEN; i++) { + if (card->queued_pkt.len == 0) { + thread_wait_mutex(card->rx_mutex); + int res = network_queue_get_swap(&card->queues[NET_QUEUE_RX], &card->queued_pkt); + thread_release_mutex(card->rx_mutex); + if (!res) + break; + } - network_busy(1); + network_dump_packet(&card->queued_pkt); + int res = card->rx(card->card_drv, card->queued_pkt.data, card->queued_pkt.len); + if (!res) + break; + rx_bytes += card->queued_pkt.len; + card->queued_pkt.len = 0; + } - network_queue_get(0, &pkt); - if ((pkt != NULL) && (pkt->len > 0)) { - network_dump_packet(pkt); - ret = net_cards[network_card].rx(pkt->priv, pkt->data, pkt->len); - if (pkt->len >= 128) - timer_on_auto(&network_rx_queue_timer, 0.762939453125 * 2.0 * ((double) pkt->len)); - else - timer_on_auto(&network_rx_queue_timer, 0.762939453125 * 2.0 * 128.0); - } else - timer_on_auto(&network_rx_queue_timer, 0.762939453125 * 2.0 * 128.0); - if (ret) - network_queue_advance(0); + /* Transmission. */ + uint32_t tx_bytes = 0; + thread_wait_mutex(card->tx_mutex); + for (int i = 0; i < NET_QUEUE_LEN; i++) { + uint32_t bytes = network_queue_move(&card->queues[NET_QUEUE_TX_HOST], &card->queues[NET_QUEUE_TX_VM]); + if (!bytes) + break; + tx_bytes += bytes; + } + thread_release_mutex(card->tx_mutex); + if (tx_bytes) { + /* Notify host that a packet is available in the TX queue */ + card->host_drv.notify_in(card->host_drv.priv); + } - network_busy(0); + double timer_period = card->byte_period * (rx_bytes > tx_bytes ? rx_bytes : tx_bytes); + if (timer_period < 200) + timer_period = 200; + + timer_on_auto(&card->timer, timer_period); + + bool activity = rx_bytes || tx_bytes; + bool led_on = card->led_timer & 0x80000000; + if ((activity && !led_on) || (card->led_timer & 0x7fffffff) >= 150000) { + ui_sb_update_icon(SB_NETWORK | card->card_num, activity); + card->led_timer = 0 | (activity << 31); + } + + card->led_timer += timer_period; } - /* * Attach a network card to the system. * @@ -381,99 +444,118 @@ network_rx_queue(void *priv) * finished initializing itself, to link itself to the platform support * modules. */ -void -network_attach(void *dev, uint8_t *mac, NETRXCB rx, NETWAITCB wait, NETSETLINKSTATE set_link_state) +netcard_t * +network_attach(void *card_drv, uint8_t *mac, NETRXCB rx, NETSETLINKSTATE set_link_state) { - if (network_card == 0) return; + netcard_t *card = calloc(1, sizeof(netcard_t)); + card->queued_pkt.data = calloc(1, NET_MAX_FRAME); + card->card_drv = card_drv; + card->rx = rx; + card->set_link_state = set_link_state; + card->tx_mutex = thread_create_mutex(); + card->rx_mutex = thread_create_mutex(); + card->card_num = net_card_current; + card->byte_period = NET_PERIOD_10M; - /* Save the card's info. */ - net_cards[network_card].priv = dev; - net_cards[network_card].rx = rx; - net_cards[network_card].wait = wait; - net_cards[network_card].set_link_state = set_link_state; - network_mac = mac; + char net_drv_error[NET_DRV_ERRBUF_SIZE]; + wchar_t tempmsg[NET_DRV_ERRBUF_SIZE * 2]; - network_set_wait(0); - - /* Create the network events. */ - poll_data.poll_complete = thread_create_event(); - poll_data.wake_poll_thread = thread_create_event(); - - /* Activate the platform module. */ - switch(network_type) { - case NET_TYPE_PCAP: - (void)net_pcap_reset(&net_cards[network_card], network_mac); - break; - - case NET_TYPE_SLIRP: - (void)net_slirp_reset(&net_cards[network_card], network_mac); - break; + for (int i = 0; i < NET_QUEUE_COUNT; i++) { + network_queue_init(&card->queues[i]); } - first_pkt[0] = first_pkt[1] = NULL; - last_pkt[0] = last_pkt[1] = NULL; - memset(&network_rx_queue_timer, 0x00, sizeof(pc_timer_t)); - timer_add(&network_rx_queue_timer, network_rx_queue, NULL, 0); - /* 10 mbps. */ - timer_on_auto(&network_rx_queue_timer, 0.762939453125 * 2.0); - network_timer_active = 1; -} + switch (net_cards_conf[net_card_current].net_type) { + case NET_TYPE_SLIRP: + card->host_drv = net_slirp_drv; + card->host_drv.priv = card->host_drv.init(card, mac, NULL, net_drv_error); + break; - -/* Stop the network timer. */ -void -network_timer_stop(void) -{ - if (network_timer_active) { - timer_stop(&network_rx_queue_timer); - memset(&network_rx_queue_timer, 0x00, sizeof(pc_timer_t)); - network_timer_active = 0; + case NET_TYPE_PCAP: + card->host_drv = net_pcap_drv; + card->host_drv.priv = card->host_drv.init(card, mac, net_cards_conf[net_card_current].host_dev_name, net_drv_error); + break; +#ifdef HAS_VDE + case NET_TYPE_VDE: + card->host_drv = net_vde_drv; + card->host_drv.priv = card->host_drv.init(card, mac, net_cards_conf[net_card_current].host_dev_name, net_drv_error); + break; +#endif + default: + card->host_drv.priv = NULL; + break; } + + // Use null driver on: + // * No specific driver selected (card->host_drv.priv is set to null above) + // * Failure to init a specific driver (in which case card->host_drv.priv is null) + if (!card->host_drv.priv) { + + if(net_cards_conf[net_card_current].net_type != NET_TYPE_NONE) { + // We're here because of a failure + swprintf(tempmsg, sizeof_w(tempmsg), L"%ls:

%s

%ls", plat_get_string(IDS_2167), net_drv_error, plat_get_string(IDS_2168)); + ui_msgbox(MBX_ERROR, tempmsg); + net_cards_conf[net_card_current].net_type = NET_TYPE_NONE; + } + + // Init null driver + card->host_drv = net_null_drv; + card->host_drv.priv = card->host_drv.init(card, mac, NULL, net_drv_error); + // Set link state to disconnected by default + network_connect(card->card_num, 0); + ui_sb_update_icon_state(SB_NETWORK | card->card_num, 1); + + // If null fails, something is very wrong + // Clean up and fatal + if(!card->host_drv.priv) { + thread_close_mutex(card->tx_mutex); + thread_close_mutex(card->rx_mutex); + for (int i = 0; i < NET_QUEUE_COUNT; i++) { + network_queue_clear(&card->queues[i]); + } + + free(card->queued_pkt.data); + free(card); + // Placeholder - insert the error message + fatal("Error initializing the network device: Null driver initialization failed"); + return NULL; + } + + } + + timer_add(&card->timer, network_rx_queue, card, 0); + timer_on_auto(&card->timer, 100); + + return card; } +void +netcard_close(netcard_t *card) +{ + timer_stop(&card->timer); + card->host_drv.close(card->host_drv.priv); + + thread_close_mutex(card->tx_mutex); + thread_close_mutex(card->rx_mutex); + for (int i = 0; i < NET_QUEUE_COUNT; i++) { + network_queue_clear(&card->queues[i]); + } + + free(card->queued_pkt.data); + free(card); +} /* Stop any network activity. */ void network_close(void) { - network_timer_stop(); - - /* If already closed, do nothing. */ - if (network_mutex == NULL) return; - - /* Force-close the PCAP module. */ - net_pcap_close(); - - /* Force-close the SLIRP module. */ - net_slirp_close(); - - /* Close the network events. */ - if (poll_data.wake_poll_thread != NULL) { - thread_destroy_event(poll_data.wake_poll_thread); - poll_data.wake_poll_thread = NULL; - } - if (poll_data.poll_complete != NULL) { - thread_destroy_event(poll_data.poll_complete); - poll_data.poll_complete = NULL; - } - - /* Close the network thread mutex. */ - thread_close_mutex(network_mutex); - network_mutex = NULL; - network_mac = NULL; -#ifdef ENABLE_NETWORK_LOG +#if defined ENABLE_NETWORK_LOG && !defined(_WIN32) thread_close_mutex(network_dump_mutex); network_dump_mutex = NULL; #endif - /* Here is where we clear the queues. */ - network_queue_clear(0); - network_queue_clear(1); - network_log("NETWORK: closed.\n"); } - /* * Reset the network card(s). * @@ -485,205 +567,190 @@ network_close(void) void network_reset(void) { - int i = -1; - - network_log("NETWORK: reset (type=%d, card=%d)\n", - network_type, network_card); - ui_sb_update_icon(SB_NETWORK, 0); - /* Just in case.. */ - network_close(); - - /* If no active card, we're done. */ - if ((network_type==NET_TYPE_NONE) || (network_card==0)) return; - - network_mutex = thread_create_mutex(); -#ifdef ENABLE_NETWORK_LOG +#if defined ENABLE_NETWORK_LOG && !defined(_WIN32) network_dump_mutex = thread_create_mutex(); #endif - /* Initialize the platform module. */ - switch(network_type) { - case NET_TYPE_PCAP: - i = net_pcap_init(); - break; + for (uint8_t i = 0; i < NET_CARD_MAX; i++) { + if (!network_dev_available(i)) { + continue; + } - case NET_TYPE_SLIRP: - i = net_slirp_init(); - break; - } - - if (i < 0) { - /* Tell user we can't do this (at the moment.) */ - ui_msgbox_header(MBX_ERROR, (wchar_t *) IDS_2093, (wchar_t *) IDS_2129); - - // FIXME: we should ask in the dialog if they want to - // reconfigure or quit, and throw them into the - // Settings dialog if yes. - - /* Disable network. */ - network_type = NET_TYPE_NONE; - - return; - } - - network_log("NETWORK: set up for %s, card='%s'\n", - (network_type==NET_TYPE_SLIRP)?"SLiRP":"Pcap", - net_cards[network_card].name); - - /* Add the (new?) card to the I/O system. */ - if (net_cards[network_card].device) { - network_log("NETWORK: adding device '%s'\n", - net_cards[network_card].name); - device_add(net_cards[network_card].device); + net_card_current = i; + if (net_cards_conf[i].device_num > NET_INTERNAL) + device_add_inst(net_cards[net_cards_conf[i].device_num], i + 1); } } - /* Queue a packet for transmission to one of the network providers. */ void -network_tx(uint8_t *bufp, int len) +network_tx(netcard_t *card, uint8_t *bufp, int len) { - network_busy(1); - - ui_sb_update_icon(SB_NETWORK, 1); - - network_queue_put(1, NULL, bufp, len); - - ui_sb_update_icon(SB_NETWORK, 0); - - network_busy(0); + network_queue_put(&card->queues[NET_QUEUE_TX_VM], bufp, len); } - -/* Actually transmit the packet. */ -void -network_do_tx(void) -{ - netpkt_t *pkt = NULL; - - if (network_tx_pause) - return; - - network_queue_get(1, &pkt); - if ((pkt != NULL) && (pkt->len > 0)) { - network_dump_packet(pkt); - switch(network_type) { - case NET_TYPE_PCAP: - net_pcap_in(pkt->data, pkt->len); - break; - - case NET_TYPE_SLIRP: - net_slirp_in(pkt->data, pkt->len); - break; - } - } - network_queue_advance(1); -} - - int -network_tx_queue_check(void) +network_tx_pop(netcard_t *card, netpkt_t *out_pkt) { - if ((first_pkt[1] == NULL) && (last_pkt[1] == NULL)) - return 0; + int ret = 0; - return 1; + thread_wait_mutex(card->tx_mutex); + ret = network_queue_get_swap(&card->queues[NET_QUEUE_TX_HOST], out_pkt); + thread_release_mutex(card->tx_mutex); + + return ret; } +int +network_tx_popv(netcard_t *card, netpkt_t *pkt_vec, int vec_size) +{ + int pkt_count = 0; + + netqueue_t *queue = &card->queues[NET_QUEUE_TX_HOST]; + thread_wait_mutex(card->tx_mutex); + for (int i = 0; i < vec_size; i++) { + if (!network_queue_get_swap(queue, pkt_vec)) + break; + pkt_count++; + pkt_vec++; + } + thread_release_mutex(card->tx_mutex); + + return pkt_count; +} + +int +network_rx_put(netcard_t *card, uint8_t *bufp, int len) +{ + int ret = 0; + + thread_wait_mutex(card->rx_mutex); + ret = network_queue_put(&card->queues[NET_QUEUE_RX], bufp, len); + thread_release_mutex(card->rx_mutex); + + return ret; +} + +int +network_rx_put_pkt(netcard_t *card, netpkt_t *pkt) +{ + int ret = 0; + + thread_wait_mutex(card->rx_mutex); + ret = network_queue_put_swap(&card->queues[NET_QUEUE_RX], pkt); + thread_release_mutex(card->rx_mutex); + + return ret; +} + +void +network_connect(int id, int connect) +{ + if (id >= NET_CARD_MAX) + return; + + if (connect) { + net_cards_conf[id].link_state &= ~NET_LINK_DOWN; + } else { + net_cards_conf[id].link_state |= NET_LINK_DOWN; + } +} + +int +network_is_connected(int id) +{ + if (id >= NET_CARD_MAX) + return 0; + + return !(net_cards_conf[id].link_state & NET_LINK_DOWN); +} int network_dev_to_id(char *devname) { - int i = 0; - - for (i=0; i 0); - return(1); + if ((net_cards_conf[id].net_type == NET_TYPE_PCAP) && + (network_dev_to_id(net_cards_conf[id].host_dev_name) <= 0)) + available = 0; + + // TODO: Handle VDE device + + return available; } +int +network_available(void) +{ + int available = 0; + + for (int i = 0; i < NET_CARD_MAX; i++) { + available |= network_dev_available(i); + } + + return available; +} /* UI */ int network_card_available(int card) { - if (net_cards[card].device) - return(device_available(net_cards[card].device)); + if (net_cards[card]) + return (device_available(net_cards[card])); - return(1); + return 1; } - /* UI */ const device_t * network_card_getdevice(int card) { - return(net_cards[card].device); + return (net_cards[card]); } - /* UI */ int network_card_has_config(int card) { - if (! net_cards[card].device) return(0); + if (!net_cards[card]) + return 0; - return(net_cards[card].device->config ? 1 : 0); + return (device_has_config(net_cards[card]) ? 1 : 0); } - /* UI */ -char * +const char * network_card_get_internal_name(int card) { - return device_get_internal_name(net_cards[card].device); + return device_get_internal_name(net_cards[card]); } - /* UI */ int network_card_get_from_internal_name(char *s) { int c = 0; - - while (net_cards[c].device != NULL) { - if (! strcmp((char *)net_cards[c].device->internal_name, s)) - return(c); - c++; + + while (net_cards[c] != NULL) { + if (!strcmp(net_cards[c]->internal_name, s)) + return c; + c++; } - + return 0; } - - -void -network_set_wait(int wait) -{ - net_wait = wait; -} - - -int -network_get_wait(void) -{ - int ret; - - ret = net_wait; - return ret; -} diff --git a/src/network/pcap_if.c b/src/network/pcap_if.c index f168f7ae0..1d3e39221 100644 --- a/src/network/pcap_if.c +++ b/src/network/pcap_if.c @@ -1,38 +1,36 @@ /* - * VARCem Virtual ARchaeological Computer EMulator. - * An emulator of (mostly) x86-based PC systems and devices, - * using the ISA,EISA,VLB,MCA and PCI system buses, roughly - * spanning the era between 1981 and 1995. + * VARCem Virtual ARchaeological Computer EMulator. + * An emulator of (mostly) x86-based PC systems and devices, + * using the ISA,EISA,VLB,MCA and PCI system buses, roughly + * spanning the era between 1981 and 1995. * - * This file is part of the VARCem Project. + * Simple program to show usage of (Win)Pcap. * - * Simple program to show usage of (Win)Pcap. - * - * Based on the "libpcap" examples. + * Based on the "libpcap" examples. * * * - * Author: Fred N. van Kempen, + * Authors: Fred N. van Kempen, * - * Copyright 2017,2018 Fred N. van Kempen. + * Copyright 2017-2018 Fred N. van Kempen. * - * Redistribution and use in source and binary forms, with - * or without modification, are permitted provided that the - * following conditions are met: + * Redistribution and use in source and binary forms, with + * or without modification, are permitted provided that the + * following conditions are met: * - * 1. Redistributions of source code must retain the entire - * above notice, this list of conditions and the following - * disclaimer. + * 1. Redistributions of source code must retain the entire + * above notice, this list of conditions and the following + * disclaimer. * - * 2. Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the - * following disclaimer in the documentation and/or other - * materials provided with the distribution. + * 2. Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the + * following disclaimer in the documentation and/or other + * materials provided with the distribution. * - * 3. Neither the name of the copyright holder nor the names - * of its contributors may be used to endorse or promote - * products derived from this software without specific - * prior written permission. + * 3. Neither the name of the copyright holder nor the names + * of its contributors may be used to endorse or promote + * products derived from this software without specific + * prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT @@ -46,6 +44,7 @@ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ +#include #include #include #include @@ -54,110 +53,106 @@ #include #include #include +#define HAVE_STDARG_H #include <86box/86box.h> #include <86box/plat.h> #include <86box/plat_dynld.h> - -static void *pcap_handle; /* handle to WinPcap DLL */ - +static void *pcap_handle; /* handle to WinPcap DLL */ /* Pointers to the real functions. */ -static int (*f_pcap_findalldevs)(pcap_if_t **,char *); -static void (*f_pcap_freealldevs)(pcap_if_t *); -static pcap_t *(*f_pcap_open_live)(const char *,int,int,int,char *); -static int (*f_pcap_next_ex)(pcap_t*,struct pcap_pkthdr**,const unsigned char**); -static void (*f_pcap_close)(pcap_t *); +static int (*f_pcap_findalldevs)(pcap_if_t **, char *); +static void (*f_pcap_freealldevs)(pcap_if_t *); +static pcap_t *(*f_pcap_open_live)(const char *, int, int, int, char *); +static int (*f_pcap_next_ex)(pcap_t *, struct pcap_pkthdr **, const unsigned char **); +static void (*f_pcap_close)(pcap_t *); static dllimp_t pcap_imports[] = { - { "pcap_findalldevs", &f_pcap_findalldevs }, - { "pcap_freealldevs", &f_pcap_freealldevs }, - { "pcap_open_live", &f_pcap_open_live }, - { "pcap_next_ex", &f_pcap_next_ex }, - { "pcap_close", &f_pcap_close }, - { NULL, NULL }, + // clang-format off + { "pcap_findalldevs", &f_pcap_findalldevs }, + { "pcap_freealldevs", &f_pcap_freealldevs }, + { "pcap_open_live", &f_pcap_open_live }, + { "pcap_next_ex", &f_pcap_next_ex }, + { "pcap_close", &f_pcap_close }, + { NULL, NULL }, + // clang-format on }; - typedef struct { - char device[128]; - char description[128]; + char device[128]; + char description[128]; } capdev_t; - /* Retrieve an easy-to-use list of devices. */ static int get_devlist(capdev_t *list) { - char errbuf[PCAP_ERRBUF_SIZE]; - pcap_if_t *devlist, *dev; - int i = 0; + char errbuf[PCAP_ERRBUF_SIZE]; + pcap_if_t *devlist; + int i = 0; /* Retrieve the device list from the local machine */ if (f_pcap_findalldevs(&devlist, errbuf) == -1) { - fprintf(stderr,"Error in pcap_findalldevs_ex: %s\n", errbuf); - return(-1); + fprintf(stderr, "Error in pcap_findalldevs_ex: %s\n", errbuf); + return (-1); } - for (dev=devlist; dev!=NULL; dev=dev->next) { - strcpy(list->device, dev->name); - if (dev->description) - strcpy(list->description, dev->description); - else - memset(list->description, '\0', sizeof(list->description)); - list++; - i++; + for (pcap_if_t *dev = devlist; dev != NULL; dev = dev->next) { + strcpy(list->device, dev->name); + if (dev->description) + strcpy(list->description, dev->description); + else + memset(list->description, '\0', sizeof(list->description)); + list++; + i++; } /* Release the memory. */ f_pcap_freealldevs(devlist); - return(i); + return i; } - /* Simple HEXDUMP routine for raw data. */ static void hex_dump(unsigned char *bufp, int len) { - char asci[20]; + char asci[20]; unsigned char c; - long addr; + long addr; addr = 0; while (len-- > 0) { - c = bufp[addr]; - if ((addr % 16) == 0) - printf("%04lx %02x", addr, c); - else - printf(" %02x", c); - asci[(addr & 15)] = (uint8_t)isprint(c) ? c : '.'; - if ((++addr % 16) == 0) { - asci[16] = '\0'; - printf(" | %s |\n", asci); - } + c = bufp[addr]; + if ((addr % 16) == 0) + printf("%04lx %02x", addr, c); + else + printf(" %02x", c); + asci[addr & 15] = (uint8_t) isprint(c) ? c : '.'; + if ((++addr % 16) == 0) { + asci[16] = '\0'; + printf(" | %s |\n", asci); + } } if (addr % 16) { - while (addr % 16) { - printf(" "); - asci[(addr & 15)] = ' '; - addr++; - } - asci[16] = '\0'; - printf(" | %s |\n", asci); + while (addr % 16) { + printf(" "); + asci[addr & 15] = ' '; + addr++; + } + asci[16] = '\0'; + printf(" | %s |\n", asci); } } - /* Print a standard Ethernet MAC address. */ static void eth_praddr(unsigned char *ptr) { printf("%02x:%02x:%02x:%02x:%02x:%02x", - ptr[0], ptr[1], ptr[2], ptr[3], ptr[4], ptr[5]); + ptr[0], ptr[1], ptr[2], ptr[3], ptr[4], ptr[5]); } - /* Print a standard Ethernet header. */ static int eth_prhdr(unsigned char *ptr) @@ -165,106 +160,93 @@ eth_prhdr(unsigned char *ptr) unsigned short type; printf("Ethernet "); - eth_praddr(ptr+6); + eth_praddr(ptr + 6); printf(" > "); eth_praddr(ptr); type = (ptr[12] << 8) | ptr[13]; printf(" type %04x\n", type); - return(14); + return 14; } - /* Capture packets from the network, and print them. */ static int start_cap(char *dev) { - char temp[PCAP_ERRBUF_SIZE]; - struct pcap_pkthdr *hdr; + char temp[PCAP_ERRBUF_SIZE]; + struct pcap_pkthdr *hdr; const unsigned char *pkt; - struct tm *ltime; - time_t now; - pcap_t *pcap; - int rc; + const struct tm *ltime; + time_t now; + pcap_t *pcap; + int rc; /* Open the device for reading from it. */ pcap = f_pcap_open_live(dev, - 1518, /* MTU */ - 1, /* promisc mode */ - 10, /* timeout */ - temp); + 1518, /* MTU */ + 1, /* promisc mode */ + 10, /* timeout */ + temp); if (pcap == NULL) { - fprintf(stderr, "Pcap: open_live(%s): %s\n", dev, temp); - return(2); + fprintf(stderr, "Pcap: open_live(%s): %s\n", dev, temp); + return 2; } printf("Listening on '%s'..\n", dev); for (;;) { - rc = f_pcap_next_ex(pcap, &hdr, &pkt); - if (rc < 0) break; + rc = f_pcap_next_ex(pcap, &hdr, &pkt); + if (rc < 0) + break; - /* Did we time out? */ - if (rc == 0) continue; + /* Did we time out? */ + if (rc == 0) + continue; /* Convert the timestamp to readable format. */ - now = hdr->ts.tv_sec; + now = hdr->ts.tv_sec; ltime = localtime(&now); strftime(temp, sizeof(temp), "%H:%M:%S", ltime); - - /* Process and print the packet. */ + + /* Process and print the packet. */ printf("\n<< %s,%.6ld len=%u\n", - temp, hdr->ts.tv_usec, hdr->len); - rc = eth_prhdr((unsigned char *)pkt); - hex_dump((unsigned char *)pkt+rc, hdr->len-rc); + temp, hdr->ts.tv_usec, hdr->len); + rc = eth_prhdr((unsigned char *) pkt); + hex_dump((unsigned char *) pkt + rc, hdr->len - rc); } /* All done, close up. */ f_pcap_close(pcap); - return(0); + return 0; } - /* Show a list of available network interfaces. */ static void show_devs(capdev_t *list, int num) { - int i; - if (num > 0) { - printf("Available network interfaces:\n\n"); + printf("Available network interfaces:\n\n"); - for (i=0; idevice); - if (list->description[0] != '\0') - printf(" (%s)\n", list->description); - else - printf(" (No description available)\n"); - list++; - printf("\n"); - } + for (int i = 0; i < num; i++) { + printf(" %d - %s\n", i + 1, list->device); + if (list->description[0] != '\0') + printf(" (%s)\n", list->description); + else + printf(" (No description available)\n"); + list++; + printf("\n"); + } } else { - printf("No interfaces found!\nMake sure WinPcap is installed.\n"); + printf("No interfaces found!\nMake sure WinPcap is installed.\n"); } } - -void -pclog(const char *fmt, ...) -{ - va_list ap; - - va_start(ap, fmt); - vfprintf(stderr, fmt, ap); - va_end(ap); -} - - int main(int argc, char **argv) { capdev_t interfaces[32]; - int numdev, i; + int numdev; + int i; /* Try loading the DLL. */ #ifdef _WIN32 @@ -276,39 +258,39 @@ main(int argc, char **argv) #endif if (pcap_handle == NULL) { #ifdef _WIN32 - fprintf(stderr, "Unable to load WinPcap DLL !\n"); + fprintf(stderr, "Unable to load WinPcap DLL !\n"); #else - fprintf(stderr, "Unable to load libpcap.so !\n"); + fprintf(stderr, "Unable to load libpcap.so !\n"); #endif - return(1); + return 1; } /* Get the list. */ numdev = get_devlist(interfaces); if (argc == 1) { - /* No arguments, just show the list. */ - show_devs(interfaces, numdev); + /* No arguments, just show the list. */ + show_devs(interfaces, numdev); - dynld_close(pcap_handle); + dynld_close(pcap_handle); - return(numdev); + return numdev; } /* Assume argument to be the interface number to listen on. */ i = atoi(argv[1]); if (i < 0 || i > numdev) { - fprintf(stderr, "Invalid interface number %d !\n", i); + fprintf(stderr, "Invalid interface number %d !\n", i); - dynld_close(pcap_handle); + dynld_close(pcap_handle); - return(1); + return 1; } /* Looks good, go and listen.. */ - i = start_cap(interfaces[i-1].device); + i = start_cap(interfaces[i - 1].device); dynld_close(pcap_handle); - return(i); + return i; } diff --git a/src/network/slirp/CMakeLists.txt b/src/network/slirp/CMakeLists.txt deleted file mode 100644 index 5bb4bceca..000000000 --- a/src/network/slirp/CMakeLists.txt +++ /dev/null @@ -1,34 +0,0 @@ -# -# 86Box A hypervisor and IBM PC system emulator that specializes in -# running old operating systems and software designed for IBM -# PC systems and compatibles from 1981 through fairly recent -# system designs based on the PCI bus. -# -# This file is part of the 86Box distribution. -# -# CMake build script. -# -# Authors: David HrdliÄka, -# -# Copyright 2020,2021 David HrdliÄka. -# - -add_library(slirp STATIC arp_table.c bootp.c cksum.c dnssearch.c if.c ip_icmp.c - ip_input.c ip_output.c mbuf.c misc.c sbuf.c slirp.c socket.c tcp_input.c - tcp_output.c tcp_subr.c tcp_timer.c udp.c util.c version.c) - -if(WIN32) - target_link_libraries(slirp wsock32 iphlpapi) -endif() - -option(SLIRP_GLIB "Use GLib proper with SLiRP" OFF) - -if(SLIRP_GLIB) - find_package(PkgConfig REQUIRED) - pkg_check_modules(GLIB REQUIRED IMPORTED_TARGET glib-2.0) - target_link_libraries(slirp PkgConfig::GLIB) - - target_compile_definitions(slirp PRIVATE TINYGLIB_USE_GLIB) -else() - target_sources(slirp PRIVATE tinyglib.c) -endif() diff --git a/src/network/slirp/arp_table.c b/src/network/slirp/arp_table.c deleted file mode 100644 index 959e5b9ec..000000000 --- a/src/network/slirp/arp_table.c +++ /dev/null @@ -1,92 +0,0 @@ -/* SPDX-License-Identifier: MIT */ -/* - * ARP table - * - * Copyright (c) 2011 AdaCore - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL - * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ - -#include "slirp.h" - -#include - -void arp_table_add(Slirp *slirp, uint32_t ip_addr, - const uint8_t ethaddr[ETH_ALEN]) -{ - const uint32_t broadcast_addr = - ~slirp->vnetwork_mask.s_addr | slirp->vnetwork_addr.s_addr; - ArpTable *arptbl = &slirp->arp_table; - int i; - - DEBUG_CALL("arp_table_add"); - DEBUG_ARG("ip = %s", inet_ntoa((struct in_addr){ .s_addr = ip_addr })); - DEBUG_ARG("hw addr = %02x:%02x:%02x:%02x:%02x:%02x", ethaddr[0], ethaddr[1], - ethaddr[2], ethaddr[3], ethaddr[4], ethaddr[5]); - - if (ip_addr == 0 || ip_addr == 0xffffffff || ip_addr == broadcast_addr) { - /* Do not register broadcast addresses */ - return; - } - - /* Search for an entry */ - for (i = 0; i < ARP_TABLE_SIZE; i++) { - if (arptbl->table[i].ar_sip == ip_addr) { - /* Update the entry */ - memcpy(arptbl->table[i].ar_sha, ethaddr, ETH_ALEN); - return; - } - } - - /* No entry found, create a new one */ - arptbl->table[arptbl->next_victim].ar_sip = ip_addr; - memcpy(arptbl->table[arptbl->next_victim].ar_sha, ethaddr, ETH_ALEN); - arptbl->next_victim = (arptbl->next_victim + 1) % ARP_TABLE_SIZE; -} - -bool arp_table_search(Slirp *slirp, uint32_t ip_addr, - uint8_t out_ethaddr[ETH_ALEN]) -{ - const uint32_t broadcast_addr = - ~slirp->vnetwork_mask.s_addr | slirp->vnetwork_addr.s_addr; - ArpTable *arptbl = &slirp->arp_table; - int i; - - DEBUG_CALL("arp_table_search"); - DEBUG_ARG("ip = %s", inet_ntoa((struct in_addr){ .s_addr = ip_addr })); - - /* If broadcast address */ - if (ip_addr == 0 || ip_addr == 0xffffffff || ip_addr == broadcast_addr) { - /* return Ethernet broadcast address */ - memset(out_ethaddr, 0xff, ETH_ALEN); - return 1; - } - - for (i = 0; i < ARP_TABLE_SIZE; i++) { - if (arptbl->table[i].ar_sip == ip_addr) { - memcpy(out_ethaddr, arptbl->table[i].ar_sha, ETH_ALEN); - DEBUG_ARG("found hw addr = %02x:%02x:%02x:%02x:%02x:%02x", - out_ethaddr[0], out_ethaddr[1], out_ethaddr[2], - out_ethaddr[3], out_ethaddr[4], out_ethaddr[5]); - return 1; - } - } - - return 0; -} diff --git a/src/network/slirp/bootp.c b/src/network/slirp/bootp.c deleted file mode 100644 index 46e96810a..000000000 --- a/src/network/slirp/bootp.c +++ /dev/null @@ -1,369 +0,0 @@ -/* SPDX-License-Identifier: MIT */ -/* - * QEMU BOOTP/DHCP server - * - * Copyright (c) 2004 Fabrice Bellard - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL - * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -#include "slirp.h" - -#if defined(_WIN32) -/* Windows ntohl() returns an u_long value. - * Add a type cast to match the format strings. */ -#define ntohl(n) ((uint32_t)ntohl(n)) -#endif - -/* XXX: only DHCP is supported */ - -#define LEASE_TIME (24 * 3600) - -static const uint8_t rfc1533_cookie[] = { RFC1533_COOKIE }; - -#define DPRINTF(fmt, ...) DEBUG_CALL(fmt, ##__VA_ARGS__) - -static BOOTPClient *get_new_addr(Slirp *slirp, struct in_addr *paddr, - const uint8_t *macaddr) -{ - BOOTPClient *bc; - int i; - - for (i = 0; i < NB_BOOTP_CLIENTS; i++) { - bc = &slirp->bootp_clients[i]; - if (!bc->allocated || !memcmp(macaddr, bc->macaddr, 6)) - goto found; - } - return NULL; -found: - bc = &slirp->bootp_clients[i]; - bc->allocated = 1; - paddr->s_addr = slirp->vdhcp_startaddr.s_addr + htonl(i); - return bc; -} - -static BOOTPClient *request_addr(Slirp *slirp, const struct in_addr *paddr, - const uint8_t *macaddr) -{ - uint32_t req_addr = ntohl(paddr->s_addr); - uint32_t dhcp_addr = ntohl(slirp->vdhcp_startaddr.s_addr); - BOOTPClient *bc; - - if (req_addr >= dhcp_addr && req_addr < (dhcp_addr + NB_BOOTP_CLIENTS)) { - bc = &slirp->bootp_clients[req_addr - dhcp_addr]; - if (!bc->allocated || !memcmp(macaddr, bc->macaddr, 6)) { - bc->allocated = 1; - return bc; - } - } - return NULL; -} - -static BOOTPClient *find_addr(Slirp *slirp, struct in_addr *paddr, - const uint8_t *macaddr) -{ - BOOTPClient *bc; - int i; - - for (i = 0; i < NB_BOOTP_CLIENTS; i++) { - if (!memcmp(macaddr, slirp->bootp_clients[i].macaddr, 6)) - goto found; - } - return NULL; -found: - bc = &slirp->bootp_clients[i]; - bc->allocated = 1; - paddr->s_addr = slirp->vdhcp_startaddr.s_addr + htonl(i); - return bc; -} - -static void dhcp_decode(const struct bootp_t *bp, int *pmsg_type, - struct in_addr *preq_addr) -{ - const uint8_t *p, *p_end; - int len, tag; - - *pmsg_type = 0; - preq_addr->s_addr = htonl(0L); - - p = bp->bp_vend; - p_end = p + DHCP_OPT_LEN; - if (memcmp(p, rfc1533_cookie, 4) != 0) - return; - p += 4; - while (p < p_end) { - tag = p[0]; - if (tag == RFC1533_PAD) { - p++; - } else if (tag == RFC1533_END) { - break; - } else { - p++; - if (p >= p_end) - break; - len = *p++; - if (p + len > p_end) { - break; - } - DPRINTF("dhcp: tag=%d len=%d\n", tag, len); - - switch (tag) { - case RFC2132_MSG_TYPE: - if (len >= 1) - *pmsg_type = p[0]; - break; - case RFC2132_REQ_ADDR: - if (len >= 4) { - memcpy(&(preq_addr->s_addr), p, 4); - } - break; - default: - break; - } - p += len; - } - } - if (*pmsg_type == DHCPREQUEST && preq_addr->s_addr == htonl(0L) && - bp->bp_ciaddr.s_addr) { - memcpy(&(preq_addr->s_addr), &bp->bp_ciaddr, 4); - } -} - -static void bootp_reply(Slirp *slirp, const struct bootp_t *bp) -{ - BOOTPClient *bc = NULL; - struct mbuf *m; - struct bootp_t *rbp; - struct sockaddr_in saddr, daddr; - struct in_addr preq_addr; - int dhcp_msg_type, val; - uint8_t *q; - uint8_t *end; - uint8_t client_ethaddr[ETH_ALEN]; - - /* extract exact DHCP msg type */ - dhcp_decode(bp, &dhcp_msg_type, &preq_addr); - DPRINTF("bootp packet op=%d msgtype=%d", bp->bp_op, dhcp_msg_type); - if (preq_addr.s_addr != htonl(0L)) - DPRINTF(" req_addr=%08" PRIx32 "\n", ntohl(preq_addr.s_addr)); - else { - DPRINTF("\n"); - } - - if (dhcp_msg_type == 0) - dhcp_msg_type = DHCPREQUEST; /* Force reply for old BOOTP clients */ - - if (dhcp_msg_type != DHCPDISCOVER && dhcp_msg_type != DHCPREQUEST) - return; - - /* Get client's hardware address from bootp request */ - memcpy(client_ethaddr, bp->bp_hwaddr, ETH_ALEN); - - m = m_get(slirp); - if (!m) { - return; - } - m->m_data += IF_MAXLINKHDR; - rbp = (struct bootp_t *)m->m_data; - m->m_data += sizeof(struct udpiphdr); - memset(rbp, 0, sizeof(struct bootp_t)); - - if (dhcp_msg_type == DHCPDISCOVER) { - if (preq_addr.s_addr != htonl(0L)) { - bc = request_addr(slirp, &preq_addr, client_ethaddr); - if (bc) { - daddr.sin_addr = preq_addr; - } - } - if (!bc) { - new_addr: - bc = get_new_addr(slirp, &daddr.sin_addr, client_ethaddr); - if (!bc) { - DPRINTF("no address left\n"); - return; - } - } - memcpy(bc->macaddr, client_ethaddr, ETH_ALEN); - } else if (preq_addr.s_addr != htonl(0L)) { - bc = request_addr(slirp, &preq_addr, client_ethaddr); - if (bc) { - daddr.sin_addr = preq_addr; - memcpy(bc->macaddr, client_ethaddr, ETH_ALEN); - } else { - /* DHCPNAKs should be sent to broadcast */ - daddr.sin_addr.s_addr = 0xffffffff; - } - } else { - bc = find_addr(slirp, &daddr.sin_addr, bp->bp_hwaddr); - if (!bc) { - /* if never assigned, behaves as if it was already - assigned (windows fix because it remembers its address) */ - goto new_addr; - } - } - - /* Update ARP table for this IP address */ - arp_table_add(slirp, daddr.sin_addr.s_addr, client_ethaddr); - - saddr.sin_addr = slirp->vhost_addr; - saddr.sin_port = htons(BOOTP_SERVER); - - daddr.sin_port = htons(BOOTP_CLIENT); - - rbp->bp_op = BOOTP_REPLY; - rbp->bp_xid = bp->bp_xid; - rbp->bp_htype = 1; - rbp->bp_hlen = 6; - memcpy(rbp->bp_hwaddr, bp->bp_hwaddr, ETH_ALEN); - - rbp->bp_yiaddr = daddr.sin_addr; /* Client IP address */ - rbp->bp_siaddr = saddr.sin_addr; /* Server IP address */ - - q = rbp->bp_vend; - end = (uint8_t *)&rbp[1]; - memcpy(q, rfc1533_cookie, 4); - q += 4; - - if (bc) { - DPRINTF("%s addr=%08" PRIx32 "\n", - (dhcp_msg_type == DHCPDISCOVER) ? "offered" : "ack'ed", - ntohl(daddr.sin_addr.s_addr)); - - if (dhcp_msg_type == DHCPDISCOVER) { - *q++ = RFC2132_MSG_TYPE; - *q++ = 1; - *q++ = DHCPOFFER; - } else /* DHCPREQUEST */ { - *q++ = RFC2132_MSG_TYPE; - *q++ = 1; - *q++ = DHCPACK; - } - - if (slirp->bootp_filename) { - g_assert(strlen(slirp->bootp_filename) < sizeof(rbp->bp_file)); - strcpy(rbp->bp_file, slirp->bootp_filename); - } - - *q++ = RFC2132_SRV_ID; - *q++ = 4; - memcpy(q, &saddr.sin_addr, 4); - q += 4; - - *q++ = RFC1533_NETMASK; - *q++ = 4; - memcpy(q, &slirp->vnetwork_mask, 4); - q += 4; - - if (!slirp->restricted) { - *q++ = RFC1533_GATEWAY; - *q++ = 4; - memcpy(q, &saddr.sin_addr, 4); - q += 4; - - *q++ = RFC1533_DNS; - *q++ = 4; - memcpy(q, &slirp->vnameserver_addr, 4); - q += 4; - } - - *q++ = RFC2132_LEASE_TIME; - *q++ = 4; - val = htonl(LEASE_TIME); - memcpy(q, &val, 4); - q += 4; - - if (*slirp->client_hostname) { - val = strlen(slirp->client_hostname); - if (q + val + 2 >= end) { - g_warning("DHCP packet size exceeded, " - "omitting host name option."); - } else { - *q++ = RFC1533_HOSTNAME; - *q++ = val; - memcpy(q, slirp->client_hostname, val); - q += val; - } - } - - if (slirp->vdomainname) { - val = strlen(slirp->vdomainname); - if (q + val + 2 >= end) { - g_warning("DHCP packet size exceeded, " - "omitting domain name option."); - } else { - *q++ = RFC1533_DOMAINNAME; - *q++ = val; - memcpy(q, slirp->vdomainname, val); - q += val; - } - } - - if (slirp->tftp_server_name) { - val = strlen(slirp->tftp_server_name); - if (q + val + 2 >= end) { - g_warning("DHCP packet size exceeded, " - "omitting tftp-server-name option."); - } else { - *q++ = RFC2132_TFTP_SERVER_NAME; - *q++ = val; - memcpy(q, slirp->tftp_server_name, val); - q += val; - } - } - - if (slirp->vdnssearch) { - val = slirp->vdnssearch_len; - if (q + val >= end) { - g_warning("DHCP packet size exceeded, " - "omitting domain-search option."); - } else { - memcpy(q, slirp->vdnssearch, val); - q += val; - } - } - } else { - static const char nak_msg[] = "requested address not available"; - - DPRINTF("nak'ed addr=%08" PRIx32 "\n", ntohl(preq_addr.s_addr)); - - *q++ = RFC2132_MSG_TYPE; - *q++ = 1; - *q++ = DHCPNAK; - - *q++ = RFC2132_MESSAGE; - *q++ = sizeof(nak_msg) - 1; - memcpy(q, nak_msg, sizeof(nak_msg) - 1); - q += sizeof(nak_msg) - 1; - } - assert(q < end); - *q = RFC1533_END; - - daddr.sin_addr.s_addr = 0xffffffffu; - - m->m_len = sizeof(struct bootp_t) - sizeof(struct ip) - sizeof(struct udphdr); - udp_output(NULL, m, &saddr, &daddr, IPTOS_LOWDELAY); -} - -void bootp_input(struct mbuf *m) -{ - struct bootp_t *bp = mtod(m, struct bootp_t *); - - if (bp->bp_op == BOOTP_REQUEST) { - bootp_reply(m->slirp, bp); - } -} diff --git a/src/network/slirp/bootp.h b/src/network/slirp/bootp.h deleted file mode 100644 index a57fa51bc..000000000 --- a/src/network/slirp/bootp.h +++ /dev/null @@ -1,129 +0,0 @@ -/* SPDX-License-Identifier: BSD-3-Clause */ -/* bootp/dhcp defines */ - -#ifndef SLIRP_BOOTP_H -#define SLIRP_BOOTP_H - -#define BOOTP_SERVER 67 -#define BOOTP_CLIENT 68 - -#define BOOTP_REQUEST 1 -#define BOOTP_REPLY 2 - -#define RFC1533_COOKIE 99, 130, 83, 99 -#define RFC1533_PAD 0 -#define RFC1533_NETMASK 1 -#define RFC1533_TIMEOFFSET 2 -#define RFC1533_GATEWAY 3 -#define RFC1533_TIMESERVER 4 -#define RFC1533_IEN116NS 5 -#define RFC1533_DNS 6 -#define RFC1533_LOGSERVER 7 -#define RFC1533_COOKIESERVER 8 -#define RFC1533_LPRSERVER 9 -#define RFC1533_IMPRESSSERVER 10 -#define RFC1533_RESOURCESERVER 11 -#define RFC1533_HOSTNAME 12 -#define RFC1533_BOOTFILESIZE 13 -#define RFC1533_MERITDUMPFILE 14 -#define RFC1533_DOMAINNAME 15 -#define RFC1533_SWAPSERVER 16 -#define RFC1533_ROOTPATH 17 -#define RFC1533_EXTENSIONPATH 18 -#define RFC1533_IPFORWARDING 19 -#define RFC1533_IPSOURCEROUTING 20 -#define RFC1533_IPPOLICYFILTER 21 -#define RFC1533_IPMAXREASSEMBLY 22 -#define RFC1533_IPTTL 23 -#define RFC1533_IPMTU 24 -#define RFC1533_IPMTUPLATEAU 25 -#define RFC1533_INTMTU 26 -#define RFC1533_INTLOCALSUBNETS 27 -#define RFC1533_INTBROADCAST 28 -#define RFC1533_INTICMPDISCOVER 29 -#define RFC1533_INTICMPRESPOND 30 -#define RFC1533_INTROUTEDISCOVER 31 -#define RFC1533_INTROUTESOLICIT 32 -#define RFC1533_INTSTATICROUTES 33 -#define RFC1533_LLTRAILERENCAP 34 -#define RFC1533_LLARPCACHETMO 35 -#define RFC1533_LLETHERNETENCAP 36 -#define RFC1533_TCPTTL 37 -#define RFC1533_TCPKEEPALIVETMO 38 -#define RFC1533_TCPKEEPALIVEGB 39 -#define RFC1533_NISDOMAIN 40 -#define RFC1533_NISSERVER 41 -#define RFC1533_NTPSERVER 42 -#define RFC1533_VENDOR 43 -#define RFC1533_NBNS 44 -#define RFC1533_NBDD 45 -#define RFC1533_NBNT 46 -#define RFC1533_NBSCOPE 47 -#define RFC1533_XFS 48 -#define RFC1533_XDM 49 - -#define RFC2132_REQ_ADDR 50 -#define RFC2132_LEASE_TIME 51 -#define RFC2132_MSG_TYPE 53 -#define RFC2132_SRV_ID 54 -#define RFC2132_PARAM_LIST 55 -#define RFC2132_MESSAGE 56 -#define RFC2132_MAX_SIZE 57 -#define RFC2132_RENEWAL_TIME 58 -#define RFC2132_REBIND_TIME 59 -#define RFC2132_TFTP_SERVER_NAME 66 - -#define DHCPDISCOVER 1 -#define DHCPOFFER 2 -#define DHCPREQUEST 3 -#define DHCPACK 5 -#define DHCPNAK 6 - -#define RFC1533_VENDOR_MAJOR 0 -#define RFC1533_VENDOR_MINOR 0 - -#define RFC1533_VENDOR_MAGIC 128 -#define RFC1533_VENDOR_ADDPARM 129 -#define RFC1533_VENDOR_ETHDEV 130 -#define RFC1533_VENDOR_HOWTO 132 -#define RFC1533_VENDOR_MNUOPTS 160 -#define RFC1533_VENDOR_SELECTION 176 -#define RFC1533_VENDOR_MOTD 184 -#define RFC1533_VENDOR_NUMOFMOTD 8 -#define RFC1533_VENDOR_IMG 192 -#define RFC1533_VENDOR_NUMOFIMG 16 - -#define RFC1533_END 255 -#define BOOTP_VENDOR_LEN 64 -#define DHCP_OPT_LEN 312 - -struct bootp_t { - struct ip ip; - struct udphdr udp; - uint8_t bp_op; - uint8_t bp_htype; - uint8_t bp_hlen; - uint8_t bp_hops; - uint32_t bp_xid; - uint16_t bp_secs; - uint16_t unused; - struct in_addr bp_ciaddr; - struct in_addr bp_yiaddr; - struct in_addr bp_siaddr; - struct in_addr bp_giaddr; - uint8_t bp_hwaddr[16]; - uint8_t bp_sname[64]; - char bp_file[128]; - uint8_t bp_vend[DHCP_OPT_LEN]; -}; - -typedef struct { - uint16_t allocated; - uint8_t macaddr[6]; -} BOOTPClient; - -#define NB_BOOTP_CLIENTS 16 - -void bootp_input(struct mbuf *m); - -#endif diff --git a/src/network/slirp/cksum.c b/src/network/slirp/cksum.c deleted file mode 100644 index 4d08380a4..000000000 --- a/src/network/slirp/cksum.c +++ /dev/null @@ -1,179 +0,0 @@ -/* SPDX-License-Identifier: BSD-3-Clause */ -/* - * Copyright (c) 1988, 1992, 1993 - * The Regents of the University of California. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. Neither the name of the University nor the names of its contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - * - * @(#)in_cksum.c 8.1 (Berkeley) 6/10/93 - * in_cksum.c,v 1.2 1994/08/02 07:48:16 davidg Exp - */ - -#include "slirp.h" - -/* - * Checksum routine for Internet Protocol family headers (Portable Version). - * - * This routine is very heavily used in the network - * code and should be modified for each CPU to be as fast as possible. - * - * XXX Since we will never span more than 1 mbuf, we can optimise this - */ - -#define ADDCARRY(x) (x > 65535 ? x -= 65535 : x) -#define REDUCE \ - { \ - l_util.l = sum; \ - sum = l_util.s[0] + l_util.s[1]; \ - (void)ADDCARRY(sum); \ - } - -int cksum(struct mbuf *m, int len) -{ - register uint16_t *w; - register int sum = 0; - register int mlen = 0; - int byte_swapped = 0; - - union { - uint8_t c[2]; - uint16_t s; - } s_util; - union { - uint16_t s[2]; - uint32_t l; - } l_util; - - if (m->m_len == 0) - goto cont; - w = mtod(m, uint16_t *); - - mlen = m->m_len; - - if (len < mlen) - mlen = len; - len -= mlen; - /* - * Force to even boundary. - */ - if ((1 & (uintptr_t)w) && (mlen > 0)) { - REDUCE; - sum <<= 8; - s_util.c[0] = *(uint8_t *)w; - w = (uint16_t *)((int8_t *)w + 1); - mlen--; - byte_swapped = 1; - } - /* - * Unroll the loop to make overhead from - * branches &c small. - */ - while ((mlen -= 32) >= 0) { - sum += w[0]; - sum += w[1]; - sum += w[2]; - sum += w[3]; - sum += w[4]; - sum += w[5]; - sum += w[6]; - sum += w[7]; - sum += w[8]; - sum += w[9]; - sum += w[10]; - sum += w[11]; - sum += w[12]; - sum += w[13]; - sum += w[14]; - sum += w[15]; - w += 16; - } - mlen += 32; - while ((mlen -= 8) >= 0) { - sum += w[0]; - sum += w[1]; - sum += w[2]; - sum += w[3]; - w += 4; - } - mlen += 8; - if (mlen == 0 && byte_swapped == 0) - goto cont; - REDUCE; - while ((mlen -= 2) >= 0) { - sum += *w++; - } - - if (byte_swapped) { - REDUCE; - sum <<= 8; - if (mlen == -1) { - s_util.c[1] = *(uint8_t *)w; - sum += s_util.s; - mlen = 0; - } else - - mlen = -1; - } else if (mlen == -1) - s_util.c[0] = *(uint8_t *)w; - -cont: - if (len) { - DEBUG_ERROR("cksum: out of data"); - DEBUG_ERROR(" len = %d", len); - } - if (mlen == -1) { - /* The last mbuf has odd # of bytes. Follow the - standard (the odd byte may be shifted left by 8 bits - or not as determined by endian-ness of the machine) */ - s_util.c[1] = 0; - sum += s_util.s; - } - REDUCE; - return (~sum & 0xffff); -} - -int ip6_cksum(struct mbuf *m) -{ - /* TODO: Optimize this by being able to pass the ip6_pseudohdr to cksum - * separately from the mbuf */ - struct ip6 save_ip, *ip = mtod(m, struct ip6 *); - struct ip6_pseudohdr *ih = mtod(m, struct ip6_pseudohdr *); - int sum; - - save_ip = *ip; - - ih->ih_src = save_ip.ip_src; - ih->ih_dst = save_ip.ip_dst; - ih->ih_pl = htonl((uint32_t)ntohs(save_ip.ip_pl)); - ih->ih_zero_hi = 0; - ih->ih_zero_lo = 0; - ih->ih_nh = save_ip.ip_nh; - - sum = cksum(m, ((int)sizeof(struct ip6_pseudohdr)) + ntohl(ih->ih_pl)); - - *ip = save_ip; - - return sum; -} diff --git a/src/network/slirp/debug.h b/src/network/slirp/debug.h deleted file mode 100644 index 47712bd78..000000000 --- a/src/network/slirp/debug.h +++ /dev/null @@ -1,51 +0,0 @@ -/* SPDX-License-Identifier: BSD-3-Clause */ -/* - * Copyright (c) 1995 Danny Gasparovski. - */ - -#ifndef DEBUG_H_ -#define DEBUG_H_ - -#define DBG_CALL (1 << 0) -#define DBG_MISC (1 << 1) -#define DBG_ERROR (1 << 2) -#define DBG_TFTP (1 << 3) - -extern int slirp_debug; - -#define DEBUG_CALL(fmt, ...) \ - do { \ - if (G_UNLIKELY(slirp_debug & DBG_CALL)) { \ - g_debug(fmt "...", ##__VA_ARGS__); \ - } \ - } while (0) - -#define DEBUG_ARG(fmt, ...) \ - do { \ - if (G_UNLIKELY(slirp_debug & DBG_CALL)) { \ - g_debug(" " fmt, ##__VA_ARGS__); \ - } \ - } while (0) - -#define DEBUG_MISC(fmt, ...) \ - do { \ - if (G_UNLIKELY(slirp_debug & DBG_MISC)) { \ - g_debug(fmt, ##__VA_ARGS__); \ - } \ - } while (0) - -#define DEBUG_ERROR(fmt, ...) \ - do { \ - if (G_UNLIKELY(slirp_debug & DBG_ERROR)) { \ - g_debug(fmt, ##__VA_ARGS__); \ - } \ - } while (0) - -#define DEBUG_TFTP(fmt, ...) \ - do { \ - if (G_UNLIKELY(slirp_debug & DBG_TFTP)) { \ - g_debug(fmt, ##__VA_ARGS__); \ - } \ - } while (0) - -#endif /* DEBUG_H_ */ diff --git a/src/network/slirp/dhcpv6.c b/src/network/slirp/dhcpv6.c deleted file mode 100644 index 77b451b91..000000000 --- a/src/network/slirp/dhcpv6.c +++ /dev/null @@ -1,224 +0,0 @@ -/* SPDX-License-Identifier: BSD-3-Clause */ -/* - * SLIRP stateless DHCPv6 - * - * We only support stateless DHCPv6, e.g. for network booting. - * See RFC 3315, RFC 3736, RFC 3646 and RFC 5970 for details. - * - * Copyright 2016 Thomas Huth, Red Hat Inc. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * 1. Redistributions of source code must retain the above - * copyright notice, this list of conditions and the following - * disclaimer. - * - * 2. Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following - * disclaimer in the documentation and/or other materials provided - * with the distribution. - * - * 3. Neither the name of the copyright holder nor the names of its - * contributors may be used to endorse or promote products derived - * from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS - * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE - * COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, - * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES - * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR - * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, - * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED - * OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#include "slirp.h" -#include "dhcpv6.h" - -/* DHCPv6 message types */ -#define MSGTYPE_REPLY 7 -#define MSGTYPE_INFO_REQUEST 11 - -/* DHCPv6 option types */ -#define OPTION_CLIENTID 1 -#define OPTION_IAADDR 5 -#define OPTION_ORO 6 -#define OPTION_DNS_SERVERS 23 -#define OPTION_BOOTFILE_URL 59 - -struct requested_infos { - uint8_t *client_id; - int client_id_len; - bool want_dns; - bool want_boot_url; -}; - -/** - * Analyze the info request message sent by the client to see what data it - * provided and what it wants to have. The information is gathered in the - * "requested_infos" struct. Note that client_id (if provided) points into - * the odata region, thus the caller must keep odata valid as long as it - * needs to access the requested_infos struct. - */ -static int dhcpv6_parse_info_request(Slirp *slirp, uint8_t *odata, int olen, - struct requested_infos *ri) -{ - int i, req_opt; - - while (olen > 4) { - /* Parse one option */ - int option = odata[0] << 8 | odata[1]; - int len = odata[2] << 8 | odata[3]; - - if (len + 4 > olen) { - slirp->cb->guest_error("Guest sent bad DHCPv6 packet!", - slirp->opaque); - return -E2BIG; - } - - switch (option) { - case OPTION_IAADDR: - /* According to RFC3315, we must discard requests with IA option */ - return -EINVAL; - case OPTION_CLIENTID: - if (len > 256) { - /* Avoid very long IDs which could cause problems later */ - return -E2BIG; - } - ri->client_id = odata + 4; - ri->client_id_len = len; - break; - case OPTION_ORO: /* Option request option */ - if (len & 1) { - return -EINVAL; - } - /* Check which options the client wants to have */ - for (i = 0; i < len; i += 2) { - req_opt = odata[4 + i] << 8 | odata[4 + i + 1]; - switch (req_opt) { - case OPTION_DNS_SERVERS: - ri->want_dns = true; - break; - case OPTION_BOOTFILE_URL: - ri->want_boot_url = true; - break; - default: - DEBUG_MISC("dhcpv6: Unsupported option request %d", - req_opt); - } - } - break; - default: - DEBUG_MISC("dhcpv6 info req: Unsupported option %d, len=%d", option, - len); - } - - odata += len + 4; - olen -= len + 4; - } - - return 0; -} - - -/** - * Handle information request messages - */ -static void dhcpv6_info_request(Slirp *slirp, struct sockaddr_in6 *srcsas, - uint32_t xid, uint8_t *odata, int olen) -{ - struct requested_infos ri = { NULL }; - struct sockaddr_in6 sa6, da6; - struct mbuf *m; - uint8_t *resp; - - if (dhcpv6_parse_info_request(slirp, odata, olen, &ri) < 0) { - return; - } - - m = m_get(slirp); - if (!m) { - return; - } - memset(m->m_data, 0, m->m_size); - m->m_data += IF_MAXLINKHDR; - resp = (uint8_t *)m->m_data + sizeof(struct ip6) + sizeof(struct udphdr); - - /* Fill in response */ - *resp++ = MSGTYPE_REPLY; - *resp++ = (uint8_t)(xid >> 16); - *resp++ = (uint8_t)(xid >> 8); - *resp++ = (uint8_t)xid; - - if (ri.client_id) { - *resp++ = OPTION_CLIENTID >> 8; /* option-code high byte */ - *resp++ = OPTION_CLIENTID; /* option-code low byte */ - *resp++ = ri.client_id_len >> 8; /* option-len high byte */ - *resp++ = ri.client_id_len; /* option-len low byte */ - memcpy(resp, ri.client_id, ri.client_id_len); - resp += ri.client_id_len; - } - if (ri.want_dns) { - *resp++ = OPTION_DNS_SERVERS >> 8; /* option-code high byte */ - *resp++ = OPTION_DNS_SERVERS; /* option-code low byte */ - *resp++ = 0; /* option-len high byte */ - *resp++ = 16; /* option-len low byte */ - memcpy(resp, &slirp->vnameserver_addr6, 16); - resp += 16; - } - if (ri.want_boot_url) { - uint8_t *sa = slirp->vhost_addr6.s6_addr; - int slen, smaxlen; - - *resp++ = OPTION_BOOTFILE_URL >> 8; /* option-code high byte */ - *resp++ = OPTION_BOOTFILE_URL; /* option-code low byte */ - smaxlen = (uint8_t *)m->m_data + slirp->if_mtu - (resp + 2); - slen = slirp_fmt((char *)resp + 2, smaxlen, - "tftp://[%02x%02x:%02x%02x:%02x%02x:%02x%02x:" - "%02x%02x:%02x%02x:%02x%02x:%02x%02x]/%s", - sa[0], sa[1], sa[2], sa[3], sa[4], sa[5], sa[6], sa[7], - sa[8], sa[9], sa[10], sa[11], sa[12], sa[13], sa[14], - sa[15], slirp->bootp_filename); - *resp++ = slen >> 8; /* option-len high byte */ - *resp++ = slen; /* option-len low byte */ - resp += slen; - } - - sa6.sin6_addr = slirp->vhost_addr6; - sa6.sin6_port = DHCPV6_SERVER_PORT; - da6.sin6_addr = srcsas->sin6_addr; - da6.sin6_port = srcsas->sin6_port; - m->m_data += sizeof(struct ip6) + sizeof(struct udphdr); - m->m_len = resp - (uint8_t *)m->m_data; - udp6_output(NULL, m, &sa6, &da6); -} - -/** - * Handle DHCPv6 messages sent by the client - */ -void dhcpv6_input(struct sockaddr_in6 *srcsas, struct mbuf *m) -{ - uint8_t *data = (uint8_t *)m->m_data + sizeof(struct udphdr); - int data_len = m->m_len - sizeof(struct udphdr); - uint32_t xid; - - if (data_len < 4) { - return; - } - - xid = ntohl(*(uint32_t *)data) & 0xffffff; - - switch (data[0]) { - case MSGTYPE_INFO_REQUEST: - dhcpv6_info_request(m->slirp, srcsas, xid, &data[4], data_len - 4); - break; - default: - DEBUG_MISC("dhcpv6_input: Unsupported message type 0x%x", data[0]); - } -} diff --git a/src/network/slirp/dhcpv6.h b/src/network/slirp/dhcpv6.h deleted file mode 100644 index d12c49b36..000000000 --- a/src/network/slirp/dhcpv6.h +++ /dev/null @@ -1,68 +0,0 @@ -/* SPDX-License-Identifier: BSD-3-Clause */ -/* - * Definitions and prototypes for SLIRP stateless DHCPv6 - * - * Copyright 2016 Thomas Huth, Red Hat Inc. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * 1. Redistributions of source code must retain the above - * copyright notice, this list of conditions and the following - * disclaimer. - * - * 2. Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following - * disclaimer in the documentation and/or other materials provided - * with the distribution. - * - * 3. Neither the name of the copyright holder nor the names of its - * contributors may be used to endorse or promote products derived - * from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS - * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE - * COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, - * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES - * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR - * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, - * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED - * OF THE POSSIBILITY OF SUCH DAMAGE. - */ -#ifndef SLIRP_DHCPV6_H -#define SLIRP_DHCPV6_H - -#define DHCPV6_SERVER_PORT 547 - -#define ALLDHCP_MULTICAST \ - { \ - .s6_addr = { \ - 0xff, \ - 0x02, \ - 0x00, \ - 0x00, \ - 0x00, \ - 0x00, \ - 0x00, \ - 0x00, \ - 0x00, \ - 0x00, \ - 0x00, \ - 0x00, \ - 0x00, \ - 0x01, \ - 0x00, \ - 0x02 \ - } \ - } - -#define in6_dhcp_multicast(a) in6_equal(a, &(struct in6_addr)ALLDHCP_MULTICAST) - -void dhcpv6_input(struct sockaddr_in6 *srcsas, struct mbuf *m); - -#endif diff --git a/src/network/slirp/dnssearch.c b/src/network/slirp/dnssearch.c deleted file mode 100644 index 55497e860..000000000 --- a/src/network/slirp/dnssearch.c +++ /dev/null @@ -1,306 +0,0 @@ -/* SPDX-License-Identifier: MIT */ -/* - * Domain search option for DHCP (RFC 3397) - * - * Copyright (c) 2012 Klaus Stengel - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL - * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ - -#include "slirp.h" - -static const uint8_t RFC3397_OPT_DOMAIN_SEARCH = 119; -static const uint8_t MAX_OPT_LEN = 255; -static const uint8_t OPT_HEADER_LEN = 2; -static const uint8_t REFERENCE_LEN = 2; - -struct compact_domain; - -typedef struct compact_domain { - struct compact_domain *self; - struct compact_domain *refdom; - uint8_t *labels; - size_t len; - size_t common_octets; -} CompactDomain; - -static size_t domain_suffix_diffoff(const CompactDomain *a, - const CompactDomain *b) -{ - size_t la = a->len, lb = b->len; - uint8_t *da = a->labels + la, *db = b->labels + lb; - size_t i, lm = (la < lb) ? la : lb; - - for (i = 0; i < lm; i++) { - da--; - db--; - if (*da != *db) { - break; - } - } - return i; -} - -static int domain_suffix_ord(const void *cva, const void *cvb) -{ - const CompactDomain *a = cva, *b = cvb; - size_t la = a->len, lb = b->len; - size_t doff = domain_suffix_diffoff(a, b); - uint8_t ca = a->labels[la - doff]; - uint8_t cb = b->labels[lb - doff]; - - if (ca < cb) { - return -1; - } - if (ca > cb) { - return 1; - } - if (la < lb) { - return -1; - } - if (la > lb) { - return 1; - } - return 0; -} - -static size_t domain_common_label(CompactDomain *a, CompactDomain *b) -{ - size_t res, doff = domain_suffix_diffoff(a, b); - uint8_t *first_eq_pos = a->labels + (a->len - doff); - uint8_t *label = a->labels; - - while (*label && label < first_eq_pos) { - label += *label + 1; - } - res = a->len - (label - a->labels); - /* only report if it can help to reduce the packet size */ - return (res > REFERENCE_LEN) ? res : 0; -} - -static void domain_fixup_order(CompactDomain *cd, size_t n) -{ - size_t i; - - for (i = 0; i < n; i++) { - CompactDomain *cur = cd + i, *next = cd[i].self; - - while (!cur->common_octets) { - CompactDomain *tmp = next->self; /* backup target value */ - - next->self = cur; - cur->common_octets++; - - cur = next; - next = tmp; - } - } -} - -static void domain_mklabels(CompactDomain *cd, const char *input) -{ - uint8_t *len_marker = cd->labels; - uint8_t *output = len_marker; /* pre-incremented */ - const char *in = input; - char cur_chr; - size_t len = 0; - - if (cd->len == 0) { - goto fail; - } - cd->len++; - - do { - cur_chr = *in++; - if (cur_chr == '.' || cur_chr == '\0') { - len = output - len_marker; - if ((len == 0 && cur_chr == '.') || len >= 64) { - goto fail; - } - *len_marker = len; - - output++; - len_marker = output; - } else { - output++; - *output = cur_chr; - } - } while (cur_chr != '\0'); - - /* ensure proper zero-termination */ - if (len != 0) { - *len_marker = 0; - cd->len++; - } - return; - -fail: - g_warning("failed to parse domain name '%s'\n", input); - cd->len = 0; -} - -static void domain_mkxrefs(CompactDomain *doms, CompactDomain *last, - size_t depth) -{ - CompactDomain *i = doms, *target = doms; - - do { - if (i->labels < target->labels) { - target = i; - } - } while (i++ != last); - - for (i = doms; i != last; i++) { - CompactDomain *group_last; - size_t next_depth; - - if (i->common_octets == depth) { - continue; - } - - next_depth = -1; - for (group_last = i; group_last != last; group_last++) { - size_t co = group_last->common_octets; - if (co <= depth) { - break; - } - if (co < next_depth) { - next_depth = co; - } - } - domain_mkxrefs(i, group_last, next_depth); - - i = group_last; - if (i == last) { - break; - } - } - - if (depth == 0) { - return; - } - - i = doms; - do { - if (i != target && i->refdom == NULL) { - i->refdom = target; - i->common_octets = depth; - } - } while (i++ != last); -} - -static size_t domain_compactify(CompactDomain *domains, size_t n) -{ - uint8_t *start = domains->self->labels, *outptr = start; - size_t i; - - for (i = 0; i < n; i++) { - CompactDomain *cd = domains[i].self; - CompactDomain *rd = cd->refdom; - - if (rd != NULL) { - size_t moff = (rd->labels - start) + (rd->len - cd->common_octets); - if (moff < 0x3FFFu) { - cd->len -= cd->common_octets - 2; - cd->labels[cd->len - 1] = moff & 0xFFu; - cd->labels[cd->len - 2] = 0xC0u | (moff >> 8); - } - } - - if (cd->labels != outptr) { - memmove(outptr, cd->labels, cd->len); - cd->labels = outptr; - } - outptr += cd->len; - } - return outptr - start; -} - -int translate_dnssearch(Slirp *s, const char **names) -{ - size_t blocks, bsrc_start, bsrc_end, bdst_start; - size_t i, num_domains, memreq = 0; - uint8_t *result = NULL, *outptr; - CompactDomain *domains = NULL; - - num_domains = g_strv_length((GStrv)(void *)names); - if (num_domains == 0) { - return -2; - } - - domains = g_malloc(num_domains * sizeof(*domains)); - - for (i = 0; i < num_domains; i++) { - size_t nlen = strlen(names[i]); - memreq += nlen + 2; /* 1 zero octet + 1 label length octet */ - domains[i].self = domains + i; - domains[i].len = nlen; - domains[i].common_octets = 0; - domains[i].refdom = NULL; - } - - /* reserve extra 2 header bytes for each 255 bytes of output */ - memreq += DIV_ROUND_UP(memreq, MAX_OPT_LEN) * OPT_HEADER_LEN; - result = g_malloc(memreq * sizeof(*result)); - - outptr = result; - for (i = 0; i < num_domains; i++) { - domains[i].labels = outptr; - domain_mklabels(domains + i, names[i]); - outptr += domains[i].len; - } - - if (outptr == result) { - g_free(domains); - g_free(result); - return -1; - } - - qsort(domains, num_domains, sizeof(*domains), domain_suffix_ord); - domain_fixup_order(domains, num_domains); - - for (i = 1; i < num_domains; i++) { - size_t cl = domain_common_label(domains + i - 1, domains + i); - domains[i - 1].common_octets = cl; - } - - domain_mkxrefs(domains, domains + num_domains - 1, 0); - memreq = domain_compactify(domains, num_domains); - - blocks = DIV_ROUND_UP(memreq, MAX_OPT_LEN); - bsrc_end = memreq; - bsrc_start = (blocks - 1) * MAX_OPT_LEN; - bdst_start = bsrc_start + blocks * OPT_HEADER_LEN; - memreq += blocks * OPT_HEADER_LEN; - - while (blocks--) { - size_t len = bsrc_end - bsrc_start; - memmove(result + bdst_start, result + bsrc_start, len); - result[bdst_start - 2] = RFC3397_OPT_DOMAIN_SEARCH; - result[bdst_start - 1] = len; - bsrc_end = bsrc_start; - bsrc_start -= MAX_OPT_LEN; - bdst_start -= MAX_OPT_LEN + OPT_HEADER_LEN; - } - - g_free(domains); - s->vdnssearch = result; - s->vdnssearch_len = memreq; - return 0; -} diff --git a/src/network/slirp/if.c b/src/network/slirp/if.c deleted file mode 100644 index 23190b559..000000000 --- a/src/network/slirp/if.c +++ /dev/null @@ -1,213 +0,0 @@ -/* SPDX-License-Identifier: BSD-3-Clause */ -/* - * Copyright (c) 1995 Danny Gasparovski. - */ - -#include "slirp.h" - -static void ifs_insque(struct mbuf *ifm, struct mbuf *ifmhead) -{ - ifm->ifs_next = ifmhead->ifs_next; - ifmhead->ifs_next = ifm; - ifm->ifs_prev = ifmhead; - ifm->ifs_next->ifs_prev = ifm; -} - -static void ifs_remque(struct mbuf *ifm) -{ - ifm->ifs_prev->ifs_next = ifm->ifs_next; - ifm->ifs_next->ifs_prev = ifm->ifs_prev; -} - -void if_init(Slirp *slirp) -{ - slirp->if_fastq.qh_link = slirp->if_fastq.qh_rlink = &slirp->if_fastq; - slirp->if_batchq.qh_link = slirp->if_batchq.qh_rlink = &slirp->if_batchq; -} - -/* - * if_output: Queue packet into an output queue. - * There are 2 output queue's, if_fastq and if_batchq. - * Each output queue is a doubly linked list of double linked lists - * of mbufs, each list belonging to one "session" (socket). This - * way, we can output packets fairly by sending one packet from each - * session, instead of all the packets from one session, then all packets - * from the next session, etc. Packets on the if_fastq get absolute - * priority, but if one session hogs the link, it gets "downgraded" - * to the batchq until it runs out of packets, then it'll return - * to the fastq (eg. if the user does an ls -alR in a telnet session, - * it'll temporarily get downgraded to the batchq) - */ -void if_output(struct socket *so, struct mbuf *ifm) -{ - Slirp *slirp = ifm->slirp; - struct mbuf *ifq; - int on_fastq = 1; - - DEBUG_CALL("if_output"); - DEBUG_ARG("so = %p", so); - DEBUG_ARG("ifm = %p", ifm); - - /* - * First remove the mbuf from m_usedlist, - * since we're gonna use m_next and m_prev ourselves - * XXX Shouldn't need this, gotta change dtom() etc. - */ - if (ifm->m_flags & M_USEDLIST) { - remque(ifm); - ifm->m_flags &= ~M_USEDLIST; - } - - /* - * See if there's already a batchq list for this session. - * This can include an interactive session, which should go on fastq, - * but gets too greedy... hence it'll be downgraded from fastq to batchq. - * We mustn't put this packet back on the fastq (or we'll send it out of - * order) - * XXX add cache here? - */ - if (so) { - for (ifq = (struct mbuf *)slirp->if_batchq.qh_rlink; - (struct quehead *)ifq != &slirp->if_batchq; ifq = ifq->ifq_prev) { - if (so == ifq->ifq_so) { - /* A match! */ - ifm->ifq_so = so; - ifs_insque(ifm, ifq->ifs_prev); - goto diddit; - } - } - } - - /* No match, check which queue to put it on */ - if (so && (so->so_iptos & IPTOS_LOWDELAY)) { - ifq = (struct mbuf *)slirp->if_fastq.qh_rlink; - on_fastq = 1; - /* - * Check if this packet is a part of the last - * packet's session - */ - if (ifq->ifq_so == so) { - ifm->ifq_so = so; - ifs_insque(ifm, ifq->ifs_prev); - goto diddit; - } - } else { - ifq = (struct mbuf *)slirp->if_batchq.qh_rlink; - } - - /* Create a new doubly linked list for this session */ - ifm->ifq_so = so; - ifs_init(ifm); - insque(ifm, ifq); - -diddit: - if (so) { - /* Update *_queued */ - so->so_queued++; - so->so_nqueued++; - /* - * Check if the interactive session should be downgraded to - * the batchq. A session is downgraded if it has queued 6 - * packets without pausing, and at least 3 of those packets - * have been sent over the link - * (XXX These are arbitrary numbers, probably not optimal..) - */ - if (on_fastq && - ((so->so_nqueued >= 6) && (so->so_nqueued - so->so_queued) >= 3)) { - /* Remove from current queue... */ - remque(ifm->ifs_next); - - /* ...And insert in the new. That'll teach ya! */ - insque(ifm->ifs_next, &slirp->if_batchq); - } - } - - /* - * This prevents us from malloc()ing too many mbufs - */ - if_start(ifm->slirp); -} - -/* - * Send one packet from each session. - * If there are packets on the fastq, they are sent FIFO, before - * everything else. Then we choose the first packet from each - * batchq session (socket) and send it. - * For example, if there are 3 ftp sessions fighting for bandwidth, - * one packet will be sent from the first session, then one packet - * from the second session, then one packet from the third. - */ -void if_start(Slirp *slirp) -{ - uint64_t now = slirp->cb->clock_get_ns(slirp->opaque); - bool from_batchq = false; - struct mbuf *ifm, *ifm_next, *ifqt; - - DEBUG_CALL("if_start"); - - if (slirp->if_start_busy) { - return; - } - slirp->if_start_busy = true; - - struct mbuf *batch_head = NULL; - if (slirp->if_batchq.qh_link != &slirp->if_batchq) { - batch_head = (struct mbuf *)slirp->if_batchq.qh_link; - } - - if (slirp->if_fastq.qh_link != &slirp->if_fastq) { - ifm_next = (struct mbuf *)slirp->if_fastq.qh_link; - } else if (batch_head) { - /* Nothing on fastq, pick up from batchq */ - ifm_next = batch_head; - from_batchq = true; - } else { - ifm_next = NULL; - } - - while (ifm_next) { - ifm = ifm_next; - - ifm_next = ifm->ifq_next; - if ((struct quehead *)ifm_next == &slirp->if_fastq) { - /* No more packets in fastq, switch to batchq */ - ifm_next = batch_head; - from_batchq = true; - } - if ((struct quehead *)ifm_next == &slirp->if_batchq) { - /* end of batchq */ - ifm_next = NULL; - } - - /* Try to send packet unless it already expired */ - if (ifm->expiration_date >= now && !if_encap(slirp, ifm)) { - /* Packet is delayed due to pending ARP or NDP resolution */ - continue; - } - - /* Remove it from the queue */ - ifqt = ifm->ifq_prev; - remque(ifm); - - /* If there are more packets for this session, re-queue them */ - if (ifm->ifs_next != ifm) { - struct mbuf *next = ifm->ifs_next; - - insque(next, ifqt); - ifs_remque(ifm); - if (!from_batchq) { - ifm_next = next; - } - } - - /* Update so_queued */ - if (ifm->ifq_so && --ifm->ifq_so->so_queued == 0) { - /* If there's no more queued, reset nqueued */ - ifm->ifq_so->so_nqueued = 0; - } - - m_free(ifm); - } - - slirp->if_start_busy = false; -} diff --git a/src/network/slirp/if.h b/src/network/slirp/if.h deleted file mode 100644 index 7cf9d2750..000000000 --- a/src/network/slirp/if.h +++ /dev/null @@ -1,25 +0,0 @@ -/* SPDX-License-Identifier: BSD-3-Clause */ -/* - * Copyright (c) 1995 Danny Gasparovski. - */ - -#ifndef IF_H -#define IF_H - -#define IF_COMPRESS 0x01 /* We want compression */ -#define IF_NOCOMPRESS 0x02 /* Do not do compression */ -#define IF_AUTOCOMP 0x04 /* Autodetect (default) */ -#define IF_NOCIDCOMP 0x08 /* CID compression */ - -#define IF_MTU_DEFAULT 1500 -#define IF_MTU_MIN 68 -#define IF_MTU_MAX 65521 -#define IF_MRU_DEFAULT 1500 -#define IF_MRU_MIN 68 -#define IF_MRU_MAX 65521 -#define IF_COMP IF_AUTOCOMP /* Flags for compression */ - -/* 2 for alignment, 14 for ethernet */ -#define IF_MAXLINKHDR (2 + ETH_HLEN) - -#endif diff --git a/src/network/slirp/ip.h b/src/network/slirp/ip.h deleted file mode 100644 index fba3defa1..000000000 --- a/src/network/slirp/ip.h +++ /dev/null @@ -1,266 +0,0 @@ -/* SPDX-License-Identifier: BSD-3-Clause */ -/* - * Copyright (c) 1982, 1986, 1993 - * The Regents of the University of California. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. Neither the name of the University nor the names of its contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - * - * @(#)ip.h 8.1 (Berkeley) 6/10/93 - * ip.h,v 1.3 1994/08/21 05:27:30 paul Exp - */ - -#ifndef IP_H -#define IP_H - -#include - -#if G_BYTE_ORDER == G_BIG_ENDIAN -#undef NTOHL -#undef NTOHS -#undef HTONL -#undef HTONS -#define NTOHL(d) -#define NTOHS(d) -#define HTONL(d) -#define HTONS(d) -#else -#ifndef NTOHL -#define NTOHL(d) ((d) = ntohl((d))) -#endif -#ifndef NTOHS -#define NTOHS(d) ((d) = ntohs((uint16_t)(d))) -#endif -#ifndef HTONL -#define HTONL(d) ((d) = htonl((d))) -#endif -#ifndef HTONS -#define HTONS(d) ((d) = htons((uint16_t)(d))) -#endif -#endif - -typedef uint32_t n_long; /* long as received from the net */ - -/* - * Definitions for internet protocol version 4. - * Per RFC 791, September 1981. - */ -#define IPVERSION 4 - -/* - * Structure of an internet header, naked of options. - */ -#if defined(_MSC_VER) && !defined (__clang__) -#pragma pack(push, 1) -#endif -struct ip { -#if G_BYTE_ORDER == G_BIG_ENDIAN - uint8_t ip_v : 4, /* version */ - ip_hl : 4; /* header length */ -#else - uint8_t ip_hl : 4, /* header length */ - ip_v : 4; /* version */ -#endif - uint8_t ip_tos; /* type of service */ - uint16_t ip_len; /* total length */ - uint16_t ip_id; /* identification */ - uint16_t ip_off; /* fragment offset field */ -#define IP_DF 0x4000 /* don't fragment flag */ -#define IP_MF 0x2000 /* more fragments flag */ -#define IP_OFFMASK 0x1fff /* mask for fragmenting bits */ - uint8_t ip_ttl; /* time to live */ - uint8_t ip_p; /* protocol */ - uint16_t ip_sum; /* checksum */ - struct in_addr ip_src, ip_dst; /* source and dest address */ -} SLIRP_PACKED; -#if defined(_MSC_VER) && !defined (__clang__) -#pragma pack(pop) -#endif - -#define IP_MAXPACKET 65535 /* maximum packet size */ - -/* - * Definitions for IP type of service (ip_tos) - */ -#define IPTOS_LOWDELAY 0x10 -#define IPTOS_THROUGHPUT 0x08 -#define IPTOS_RELIABILITY 0x04 - -/* - * Definitions for options. - */ -#define IPOPT_COPIED(o) ((o)&0x80) -#define IPOPT_CLASS(o) ((o)&0x60) -#define IPOPT_NUMBER(o) ((o)&0x1f) - -#define IPOPT_CONTROL 0x00 -#define IPOPT_RESERVED1 0x20 -#define IPOPT_DEBMEAS 0x40 -#define IPOPT_RESERVED2 0x60 - -#define IPOPT_EOL 0 /* end of option list */ -#define IPOPT_NOP 1 /* no operation */ - -#define IPOPT_RR 7 /* record packet route */ -#define IPOPT_TS 68 /* timestamp */ -#define IPOPT_SECURITY 130 /* provide s,c,h,tcc */ -#define IPOPT_LSRR 131 /* loose source route */ -#define IPOPT_SATID 136 /* satnet id */ -#define IPOPT_SSRR 137 /* strict source route */ - -/* - * Offsets to fields in options other than EOL and NOP. - */ -#define IPOPT_OPTVAL 0 /* option ID */ -#define IPOPT_OLEN 1 /* option length */ -#define IPOPT_OFFSET 2 /* offset within option */ -#define IPOPT_MINOFF 4 /* min value of above */ - -/* - * Time stamp option structure. - */ -#if defined(_MSC_VER) && !defined (__clang__) -#pragma pack(push, 1) -#endif -struct ip_timestamp { - uint8_t ipt_code; /* IPOPT_TS */ - uint8_t ipt_len; /* size of structure (variable) */ - uint8_t ipt_ptr; /* index of current entry */ -#if G_BYTE_ORDER == G_BIG_ENDIAN - uint8_t ipt_oflw : 4, /* overflow counter */ - ipt_flg : 4; /* flags, see below */ -#else - uint8_t ipt_flg : 4, /* flags, see below */ - ipt_oflw : 4; /* overflow counter */ -#endif - union ipt_timestamp { - n_long ipt_time[1]; - struct ipt_ta { - struct in_addr ipt_addr; - n_long ipt_time; - } ipt_ta[1]; - } ipt_timestamp; -} SLIRP_PACKED; -#if defined(_MSC_VER) && !defined (__clang__) -#pragma pack(pop) -#endif - -/* flag bits for ipt_flg */ -#define IPOPT_TS_TSONLY 0 /* timestamps only */ -#define IPOPT_TS_TSANDADDR 1 /* timestamps and addresses */ -#define IPOPT_TS_PRESPEC 3 /* specified modules only */ - -/* bits for security (not byte swapped) */ -#define IPOPT_SECUR_UNCLASS 0x0000 -#define IPOPT_SECUR_CONFID 0xf135 -#define IPOPT_SECUR_EFTO 0x789a -#define IPOPT_SECUR_MMMM 0xbc4d -#define IPOPT_SECUR_RESTR 0xaf13 -#define IPOPT_SECUR_SECRET 0xd788 -#define IPOPT_SECUR_TOPSECRET 0x6bc5 - -/* - * Internet implementation parameters. - */ -#define MAXTTL 255 /* maximum time to live (seconds) */ -#define IPDEFTTL 64 /* default ttl, from RFC 1340 */ -#define IPFRAGTTL 60 /* time to live for frags, slowhz */ -#define IPTTLDEC 1 /* subtracted when forwarding */ - -#define IP_MSS 576 /* default maximum segment size */ - -#if defined(_MSC_VER) && !defined (__clang__) -#pragma pack(push, 1) -#endif -#if GLIB_SIZEOF_VOID_P == 4 -struct mbuf_ptr { - struct mbuf *mptr; - uint32_t dummy; -} SLIRP_PACKED; -#else -struct mbuf_ptr { - struct mbuf *mptr; -} SLIRP_PACKED; -#endif -#if defined(_MSC_VER) && !defined (__clang__) -#pragma pack(pop) -#endif -struct qlink { - void *next, *prev; -}; - -/* - * Overlay for ip header used by other protocols (tcp, udp). - */ -#if defined(_MSC_VER) && !defined (__clang__) -#pragma pack(push, 1) -#endif -struct ipovly { - struct mbuf_ptr ih_mbuf; /* backpointer to mbuf */ - uint8_t ih_x1; /* (unused) */ - uint8_t ih_pr; /* protocol */ - uint16_t ih_len; /* protocol length */ - struct in_addr ih_src; /* source internet address */ - struct in_addr ih_dst; /* destination internet address */ -} SLIRP_PACKED; -#if defined(_MSC_VER) && !defined (__clang__) -#pragma pack(pop) -#endif - -/* - * Ip reassembly queue structure. Each fragment - * being reassembled is attached to one of these structures. - * They are timed out after ipq_ttl drops to 0, and may also - * be reclaimed if memory becomes tight. - * size 28 bytes - */ -struct ipq { - struct qlink frag_link; /* to ip headers of fragments */ - struct qlink ip_link; /* to other reass headers */ - uint8_t ipq_ttl; /* time for reass q to live */ - uint8_t ipq_p; /* protocol of this fragment */ - uint16_t ipq_id; /* sequence id for reassembly */ - struct in_addr ipq_src, ipq_dst; -}; - -/* - * Ip header, when holding a fragment. - * - * Note: ipf_link must be at same offset as frag_link above - */ -struct ipasfrag { - struct qlink ipf_link; - struct ip ipf_ip; -}; - -G_STATIC_ASSERT(offsetof(struct ipq, frag_link) == - offsetof(struct ipasfrag, ipf_link)); - -#define ipf_off ipf_ip.ip_off -#define ipf_tos ipf_ip.ip_tos -#define ipf_len ipf_ip.ip_len -#define ipf_next ipf_link.next -#define ipf_prev ipf_link.prev - -#endif diff --git a/src/network/slirp/ip6.h b/src/network/slirp/ip6.h deleted file mode 100644 index 7210964d4..000000000 --- a/src/network/slirp/ip6.h +++ /dev/null @@ -1,214 +0,0 @@ -/* SPDX-License-Identifier: BSD-3-Clause */ -/* - * Copyright (c) 2013 - * Guillaume Subiron, Yann Bordenave, Serigne Modou Wagne. - */ - -#ifndef SLIRP_IP6_H -#define SLIRP_IP6_H - -#include -#include - -#define ALLNODES_MULTICAST \ - { \ - .s6_addr = { \ - 0xff, \ - 0x02, \ - 0x00, \ - 0x00, \ - 0x00, \ - 0x00, \ - 0x00, \ - 0x00, \ - 0x00, \ - 0x00, \ - 0x00, \ - 0x00, \ - 0x00, \ - 0x00, \ - 0x00, \ - 0x01 \ - } \ - } - -#define SOLICITED_NODE_PREFIX \ - { \ - .s6_addr = { \ - 0xff, \ - 0x02, \ - 0x00, \ - 0x00, \ - 0x00, \ - 0x00, \ - 0x00, \ - 0x00, \ - 0x00, \ - 0x00, \ - 0x00, \ - 0x01, \ - 0xff, \ - 0x00, \ - 0x00, \ - 0x00 \ - } \ - } - -#define LINKLOCAL_ADDR \ - { \ - .s6_addr = { \ - 0xfe, \ - 0x80, \ - 0x00, \ - 0x00, \ - 0x00, \ - 0x00, \ - 0x00, \ - 0x00, \ - 0x00, \ - 0x00, \ - 0x00, \ - 0x00, \ - 0x00, \ - 0x00, \ - 0x00, \ - 0x02 \ - } \ - } - -#define ZERO_ADDR \ - { \ - .s6_addr = { \ - 0x00, \ - 0x00, \ - 0x00, \ - 0x00, \ - 0x00, \ - 0x00, \ - 0x00, \ - 0x00, \ - 0x00, \ - 0x00, \ - 0x00, \ - 0x00, \ - 0x00, \ - 0x00, \ - 0x00, \ - 0x00 \ - } \ - } - -static inline bool in6_equal(const struct in6_addr *a, const struct in6_addr *b) -{ - return memcmp(a, b, sizeof(*a)) == 0; -} - -static inline bool in6_equal_net(const struct in6_addr *a, - const struct in6_addr *b, int prefix_len) -{ - if (memcmp(a, b, prefix_len / 8) != 0) { - return 0; - } - - if (prefix_len % 8 == 0) { - return 1; - } - - return a->s6_addr[prefix_len / 8] >> (8 - (prefix_len % 8)) == - b->s6_addr[prefix_len / 8] >> (8 - (prefix_len % 8)); -} - -static inline bool in6_equal_mach(const struct in6_addr *a, - const struct in6_addr *b, int prefix_len) -{ - if (memcmp(&(a->s6_addr[DIV_ROUND_UP(prefix_len, 8)]), - &(b->s6_addr[DIV_ROUND_UP(prefix_len, 8)]), - 16 - DIV_ROUND_UP(prefix_len, 8)) != 0) { - return 0; - } - - if (prefix_len % 8 == 0) { - return 1; - } - - return (a->s6_addr[prefix_len / 8] & - ((1U << (8 - (prefix_len % 8))) - 1)) == - (b->s6_addr[prefix_len / 8] & ((1U << (8 - (prefix_len % 8))) - 1)); -} - - -#define in6_equal_router(a) \ - ((in6_equal_net(a, &slirp->vprefix_addr6, slirp->vprefix_len) && \ - in6_equal_mach(a, &slirp->vhost_addr6, slirp->vprefix_len)) || \ - (in6_equal_net(a, &(struct in6_addr)LINKLOCAL_ADDR, 64) && \ - in6_equal_mach(a, &slirp->vhost_addr6, 64))) - -#define in6_equal_dns(a) \ - ((in6_equal_net(a, &slirp->vprefix_addr6, slirp->vprefix_len) && \ - in6_equal_mach(a, &slirp->vnameserver_addr6, slirp->vprefix_len)) || \ - (in6_equal_net(a, &(struct in6_addr)LINKLOCAL_ADDR, 64) && \ - in6_equal_mach(a, &slirp->vnameserver_addr6, 64))) - -#define in6_equal_host(a) (in6_equal_router(a) || in6_equal_dns(a)) - -#define in6_solicitednode_multicast(a) \ - (in6_equal_net(a, &(struct in6_addr)SOLICITED_NODE_PREFIX, 104)) - -#define in6_zero(a) (in6_equal(a, &(struct in6_addr)ZERO_ADDR)) - -/* Compute emulated host MAC address from its ipv6 address */ -static inline void in6_compute_ethaddr(struct in6_addr ip, - uint8_t eth[ETH_ALEN]) -{ - eth[0] = 0x52; - eth[1] = 0x56; - memcpy(ð[2], &ip.s6_addr[16 - (ETH_ALEN - 2)], ETH_ALEN - 2); -} - -/* - * Definitions for internet protocol version 6. - * Per RFC 2460, December 1998. - */ -#define IP6VERSION 6 -#define IP6_HOP_LIMIT 255 - -/* - * Structure of an internet header, naked of options. - */ -struct ip6 { -#if G_BYTE_ORDER == G_BIG_ENDIAN - uint32_t ip_v : 4, /* version */ - ip_tc_hi : 4, /* traffic class */ - ip_tc_lo : 4, ip_fl_hi : 4, /* flow label */ - ip_fl_lo : 16; -#else - uint32_t ip_tc_hi : 4, ip_v : 4, ip_fl_hi : 4, ip_tc_lo : 4, ip_fl_lo : 16; -#endif - uint16_t ip_pl; /* payload length */ - uint8_t ip_nh; /* next header */ - uint8_t ip_hl; /* hop limit */ - struct in6_addr ip_src, ip_dst; /* source and dest address */ -}; - -/* - * IPv6 pseudo-header used by upper-layer protocols - */ -struct ip6_pseudohdr { - struct in6_addr ih_src; /* source internet address */ - struct in6_addr ih_dst; /* destination internet address */ - uint32_t ih_pl; /* upper-layer packet length */ - uint16_t ih_zero_hi; /* zero */ - uint8_t ih_zero_lo; /* zero */ - uint8_t ih_nh; /* next header */ -}; - -/* - * We don't want to mark these ip6 structs as packed as they are naturally - * correctly aligned; instead assert that there is no stray padding. - * If we marked the struct as packed then we would be unable to take - * the address of any of the fields in it. - */ -G_STATIC_ASSERT(sizeof(struct ip6) == 40); -G_STATIC_ASSERT(sizeof(struct ip6_pseudohdr) == 40); - -#endif diff --git a/src/network/slirp/ip6_icmp.c b/src/network/slirp/ip6_icmp.c deleted file mode 100644 index d9c872bc9..000000000 --- a/src/network/slirp/ip6_icmp.c +++ /dev/null @@ -1,433 +0,0 @@ -/* SPDX-License-Identifier: BSD-3-Clause */ -/* - * Copyright (c) 2013 - * Guillaume Subiron, Yann Bordenave, Serigne Modou Wagne. - */ - -#include "slirp.h" -#include "ip6_icmp.h" - -#define NDP_Interval \ - g_rand_int_range(slirp->grand, NDP_MinRtrAdvInterval, NDP_MaxRtrAdvInterval) - -static void ra_timer_handler(void *opaque) -{ - Slirp *slirp = opaque; - - slirp->cb->timer_mod(slirp->ra_timer, - slirp->cb->clock_get_ns(slirp->opaque) / SCALE_MS + - NDP_Interval, - slirp->opaque); - ndp_send_ra(slirp); -} - -void icmp6_init(Slirp *slirp) -{ - if (!slirp->in6_enabled) { - return; - } - - slirp->ra_timer = - slirp->cb->timer_new(ra_timer_handler, slirp, slirp->opaque); - slirp->cb->timer_mod(slirp->ra_timer, - slirp->cb->clock_get_ns(slirp->opaque) / SCALE_MS + - NDP_Interval, - slirp->opaque); -} - -void icmp6_cleanup(Slirp *slirp) -{ - if (!slirp->in6_enabled) { - return; - } - - slirp->cb->timer_free(slirp->ra_timer, slirp->opaque); -} - -static void icmp6_send_echoreply(struct mbuf *m, Slirp *slirp, struct ip6 *ip, - struct icmp6 *icmp) -{ - struct mbuf *t = m_get(slirp); - t->m_len = sizeof(struct ip6) + ntohs(ip->ip_pl); - memcpy(t->m_data, m->m_data, t->m_len); - - /* IPv6 Packet */ - struct ip6 *rip = mtod(t, struct ip6 *); - rip->ip_dst = ip->ip_src; - rip->ip_src = ip->ip_dst; - - /* ICMPv6 packet */ - t->m_data += sizeof(struct ip6); - struct icmp6 *ricmp = mtod(t, struct icmp6 *); - ricmp->icmp6_type = ICMP6_ECHO_REPLY; - ricmp->icmp6_cksum = 0; - - /* Checksum */ - t->m_data -= sizeof(struct ip6); - ricmp->icmp6_cksum = ip6_cksum(t); - - ip6_output(NULL, t, 0); -} - -void icmp6_send_error(struct mbuf *m, uint8_t type, uint8_t code) -{ - Slirp *slirp = m->slirp; - struct mbuf *t; - struct ip6 *ip = mtod(m, struct ip6 *); - char addrstr[INET6_ADDRSTRLEN]; - - DEBUG_CALL("icmp6_send_error"); - DEBUG_ARG("type = %d, code = %d", type, code); - - if (IN6_IS_ADDR_MULTICAST(&ip->ip_src) || in6_zero(&ip->ip_src)) { - /* TODO icmp error? */ - return; - } - - t = m_get(slirp); - - /* IPv6 packet */ - struct ip6 *rip = mtod(t, struct ip6 *); - rip->ip_src = (struct in6_addr)LINKLOCAL_ADDR; - rip->ip_dst = ip->ip_src; - inet_ntop(AF_INET6, &rip->ip_dst, addrstr, INET6_ADDRSTRLEN); - DEBUG_ARG("target = %s", addrstr); - - rip->ip_nh = IPPROTO_ICMPV6; - const int error_data_len = MIN( - m->m_len, slirp->if_mtu - (sizeof(struct ip6) + ICMP6_ERROR_MINLEN)); - rip->ip_pl = htons(ICMP6_ERROR_MINLEN + error_data_len); - t->m_len = sizeof(struct ip6) + ntohs(rip->ip_pl); - - /* ICMPv6 packet */ - t->m_data += sizeof(struct ip6); - struct icmp6 *ricmp = mtod(t, struct icmp6 *); - ricmp->icmp6_type = type; - ricmp->icmp6_code = code; - ricmp->icmp6_cksum = 0; - - switch (type) { - case ICMP6_UNREACH: - case ICMP6_TIMXCEED: - ricmp->icmp6_err.unused = 0; - break; - case ICMP6_TOOBIG: - ricmp->icmp6_err.mtu = htonl(slirp->if_mtu); - break; - case ICMP6_PARAMPROB: - /* TODO: Handle this case */ - break; - default: - g_assert_not_reached(); - } - t->m_data += ICMP6_ERROR_MINLEN; - memcpy(t->m_data, m->m_data, error_data_len); - - /* Checksum */ - t->m_data -= ICMP6_ERROR_MINLEN; - t->m_data -= sizeof(struct ip6); - ricmp->icmp6_cksum = ip6_cksum(t); - - ip6_output(NULL, t, 0); -} - -/* - * Send NDP Router Advertisement - */ -void ndp_send_ra(Slirp *slirp) -{ - DEBUG_CALL("ndp_send_ra"); - - /* Build IPv6 packet */ - struct mbuf *t = m_get(slirp); - struct ip6 *rip = mtod(t, struct ip6 *); - size_t pl_size = 0; - struct in6_addr addr; - uint32_t scope_id; - - rip->ip_src = (struct in6_addr)LINKLOCAL_ADDR; - rip->ip_dst = (struct in6_addr)ALLNODES_MULTICAST; - rip->ip_nh = IPPROTO_ICMPV6; - - /* Build ICMPv6 packet */ - t->m_data += sizeof(struct ip6); - struct icmp6 *ricmp = mtod(t, struct icmp6 *); - ricmp->icmp6_type = ICMP6_NDP_RA; - ricmp->icmp6_code = 0; - ricmp->icmp6_cksum = 0; - - /* NDP */ - ricmp->icmp6_nra.chl = NDP_AdvCurHopLimit; - ricmp->icmp6_nra.M = NDP_AdvManagedFlag; - ricmp->icmp6_nra.O = NDP_AdvOtherConfigFlag; - ricmp->icmp6_nra.reserved = 0; - ricmp->icmp6_nra.lifetime = htons(NDP_AdvDefaultLifetime); - ricmp->icmp6_nra.reach_time = htonl(NDP_AdvReachableTime); - ricmp->icmp6_nra.retrans_time = htonl(NDP_AdvRetransTime); - t->m_data += ICMP6_NDP_RA_MINLEN; - pl_size += ICMP6_NDP_RA_MINLEN; - - /* Source link-layer address (NDP option) */ - struct ndpopt *opt = mtod(t, struct ndpopt *); - opt->ndpopt_type = NDPOPT_LINKLAYER_SOURCE; - opt->ndpopt_len = NDPOPT_LINKLAYER_LEN / 8; - in6_compute_ethaddr(rip->ip_src, opt->ndpopt_linklayer); - t->m_data += NDPOPT_LINKLAYER_LEN; - pl_size += NDPOPT_LINKLAYER_LEN; - - /* Prefix information (NDP option) */ - struct ndpopt *opt2 = mtod(t, struct ndpopt *); - opt2->ndpopt_type = NDPOPT_PREFIX_INFO; - opt2->ndpopt_len = NDPOPT_PREFIXINFO_LEN / 8; - opt2->ndpopt_prefixinfo.prefix_length = slirp->vprefix_len; - opt2->ndpopt_prefixinfo.L = 1; - opt2->ndpopt_prefixinfo.A = 1; - opt2->ndpopt_prefixinfo.reserved1 = 0; - opt2->ndpopt_prefixinfo.valid_lt = htonl(NDP_AdvValidLifetime); - opt2->ndpopt_prefixinfo.pref_lt = htonl(NDP_AdvPrefLifetime); - opt2->ndpopt_prefixinfo.reserved2 = 0; - opt2->ndpopt_prefixinfo.prefix = slirp->vprefix_addr6; - t->m_data += NDPOPT_PREFIXINFO_LEN; - pl_size += NDPOPT_PREFIXINFO_LEN; - - /* Prefix information (NDP option) */ - if (get_dns6_addr(&addr, &scope_id) >= 0) { - /* Host system does have an IPv6 DNS server, announce our proxy. */ - struct ndpopt *opt3 = mtod(t, struct ndpopt *); - opt3->ndpopt_type = NDPOPT_RDNSS; - opt3->ndpopt_len = NDPOPT_RDNSS_LEN / 8; - opt3->ndpopt_rdnss.reserved = 0; - opt3->ndpopt_rdnss.lifetime = htonl(2 * NDP_MaxRtrAdvInterval); - opt3->ndpopt_rdnss.addr = slirp->vnameserver_addr6; - t->m_data += NDPOPT_RDNSS_LEN; - pl_size += NDPOPT_RDNSS_LEN; - } - - rip->ip_pl = htons(pl_size); - t->m_data -= sizeof(struct ip6) + pl_size; - t->m_len = sizeof(struct ip6) + pl_size; - - /* ICMPv6 Checksum */ - ricmp->icmp6_cksum = ip6_cksum(t); - - ip6_output(NULL, t, 0); -} - -/* - * Send NDP Neighbor Solitication - */ -void ndp_send_ns(Slirp *slirp, struct in6_addr addr) -{ - char addrstr[INET6_ADDRSTRLEN]; - - inet_ntop(AF_INET6, &addr, addrstr, INET6_ADDRSTRLEN); - - DEBUG_CALL("ndp_send_ns"); - DEBUG_ARG("target = %s", addrstr); - - /* Build IPv6 packet */ - struct mbuf *t = m_get(slirp); - struct ip6 *rip = mtod(t, struct ip6 *); - rip->ip_src = slirp->vhost_addr6; - rip->ip_dst = (struct in6_addr)SOLICITED_NODE_PREFIX; - memcpy(&rip->ip_dst.s6_addr[13], &addr.s6_addr[13], 3); - rip->ip_nh = IPPROTO_ICMPV6; - rip->ip_pl = htons(ICMP6_NDP_NS_MINLEN + NDPOPT_LINKLAYER_LEN); - t->m_len = sizeof(struct ip6) + ntohs(rip->ip_pl); - - /* Build ICMPv6 packet */ - t->m_data += sizeof(struct ip6); - struct icmp6 *ricmp = mtod(t, struct icmp6 *); - ricmp->icmp6_type = ICMP6_NDP_NS; - ricmp->icmp6_code = 0; - ricmp->icmp6_cksum = 0; - - /* NDP */ - ricmp->icmp6_nns.reserved = 0; - ricmp->icmp6_nns.target = addr; - - /* Build NDP option */ - t->m_data += ICMP6_NDP_NS_MINLEN; - struct ndpopt *opt = mtod(t, struct ndpopt *); - opt->ndpopt_type = NDPOPT_LINKLAYER_SOURCE; - opt->ndpopt_len = NDPOPT_LINKLAYER_LEN / 8; - in6_compute_ethaddr(slirp->vhost_addr6, opt->ndpopt_linklayer); - - /* ICMPv6 Checksum */ - t->m_data -= ICMP6_NDP_NA_MINLEN; - t->m_data -= sizeof(struct ip6); - ricmp->icmp6_cksum = ip6_cksum(t); - - ip6_output(NULL, t, 1); -} - -/* - * Send NDP Neighbor Advertisement - */ -static void ndp_send_na(Slirp *slirp, struct ip6 *ip, struct icmp6 *icmp) -{ - /* Build IPv6 packet */ - struct mbuf *t = m_get(slirp); - struct ip6 *rip = mtod(t, struct ip6 *); - rip->ip_src = icmp->icmp6_nns.target; - if (in6_zero(&ip->ip_src)) { - rip->ip_dst = (struct in6_addr)ALLNODES_MULTICAST; - } else { - rip->ip_dst = ip->ip_src; - } - rip->ip_nh = IPPROTO_ICMPV6; - rip->ip_pl = htons(ICMP6_NDP_NA_MINLEN + NDPOPT_LINKLAYER_LEN); - t->m_len = sizeof(struct ip6) + ntohs(rip->ip_pl); - - /* Build ICMPv6 packet */ - t->m_data += sizeof(struct ip6); - struct icmp6 *ricmp = mtod(t, struct icmp6 *); - ricmp->icmp6_type = ICMP6_NDP_NA; - ricmp->icmp6_code = 0; - ricmp->icmp6_cksum = 0; - - /* NDP */ - ricmp->icmp6_nna.R = NDP_IsRouter; - ricmp->icmp6_nna.S = !IN6_IS_ADDR_MULTICAST(&rip->ip_dst); - ricmp->icmp6_nna.O = 1; - ricmp->icmp6_nna.reserved_hi = 0; - ricmp->icmp6_nna.reserved_lo = 0; - ricmp->icmp6_nna.target = icmp->icmp6_nns.target; - - /* Build NDP option */ - t->m_data += ICMP6_NDP_NA_MINLEN; - struct ndpopt *opt = mtod(t, struct ndpopt *); - opt->ndpopt_type = NDPOPT_LINKLAYER_TARGET; - opt->ndpopt_len = NDPOPT_LINKLAYER_LEN / 8; - in6_compute_ethaddr(ricmp->icmp6_nna.target, opt->ndpopt_linklayer); - - /* ICMPv6 Checksum */ - t->m_data -= ICMP6_NDP_NA_MINLEN; - t->m_data -= sizeof(struct ip6); - ricmp->icmp6_cksum = ip6_cksum(t); - - ip6_output(NULL, t, 0); -} - -/* - * Process a NDP message - */ -static void ndp_input(struct mbuf *m, Slirp *slirp, struct ip6 *ip, - struct icmp6 *icmp) -{ - m->m_len += ETH_HLEN; - m->m_data -= ETH_HLEN; - struct ethhdr *eth = mtod(m, struct ethhdr *); - m->m_len -= ETH_HLEN; - m->m_data += ETH_HLEN; - - switch (icmp->icmp6_type) { - case ICMP6_NDP_RS: - DEBUG_CALL(" type = Router Solicitation"); - if (ip->ip_hl == 255 && icmp->icmp6_code == 0 && - ntohs(ip->ip_pl) >= ICMP6_NDP_RS_MINLEN) { - /* Gratuitous NDP */ - ndp_table_add(slirp, ip->ip_src, eth->h_source); - - ndp_send_ra(slirp); - } - break; - - case ICMP6_NDP_RA: - DEBUG_CALL(" type = Router Advertisement"); - slirp->cb->guest_error("Warning: guest sent NDP RA, but shouldn't", - slirp->opaque); - break; - - case ICMP6_NDP_NS: - DEBUG_CALL(" type = Neighbor Solicitation"); - if (ip->ip_hl == 255 && icmp->icmp6_code == 0 && - !IN6_IS_ADDR_MULTICAST(&icmp->icmp6_nns.target) && - ntohs(ip->ip_pl) >= ICMP6_NDP_NS_MINLEN && - (!in6_zero(&ip->ip_src) || - in6_solicitednode_multicast(&ip->ip_dst))) { - if (in6_equal_host(&icmp->icmp6_nns.target)) { - /* Gratuitous NDP */ - ndp_table_add(slirp, ip->ip_src, eth->h_source); - ndp_send_na(slirp, ip, icmp); - } - } - break; - - case ICMP6_NDP_NA: - DEBUG_CALL(" type = Neighbor Advertisement"); - if (ip->ip_hl == 255 && icmp->icmp6_code == 0 && - ntohs(ip->ip_pl) >= ICMP6_NDP_NA_MINLEN && - !IN6_IS_ADDR_MULTICAST(&icmp->icmp6_nna.target) && - (!IN6_IS_ADDR_MULTICAST(&ip->ip_dst) || icmp->icmp6_nna.S == 0)) { - ndp_table_add(slirp, ip->ip_src, eth->h_source); - } - break; - - case ICMP6_NDP_REDIRECT: - DEBUG_CALL(" type = Redirect"); - slirp->cb->guest_error( - "Warning: guest sent NDP REDIRECT, but shouldn't", slirp->opaque); - break; - } -} - -/* - * Process a received ICMPv6 message. - */ -void icmp6_input(struct mbuf *m) -{ - struct icmp6 *icmp; - struct ip6 *ip = mtod(m, struct ip6 *); - Slirp *slirp = m->slirp; - int hlen = sizeof(struct ip6); - - DEBUG_CALL("icmp6_input"); - DEBUG_ARG("m = %p", m); - DEBUG_ARG("m_len = %d", m->m_len); - - if (ntohs(ip->ip_pl) < ICMP6_MINLEN) { - goto end; - } - - if (ip6_cksum(m)) { - goto end; - } - - m->m_len -= hlen; - m->m_data += hlen; - icmp = mtod(m, struct icmp6 *); - m->m_len += hlen; - m->m_data -= hlen; - - DEBUG_ARG("icmp6_type = %d", icmp->icmp6_type); - switch (icmp->icmp6_type) { - case ICMP6_ECHO_REQUEST: - if (in6_equal_host(&ip->ip_dst)) { - icmp6_send_echoreply(m, slirp, ip, icmp); - } else { - /* TODO */ - g_critical("external icmpv6 not supported yet"); - } - break; - - case ICMP6_NDP_RS: - case ICMP6_NDP_RA: - case ICMP6_NDP_NS: - case ICMP6_NDP_NA: - case ICMP6_NDP_REDIRECT: - ndp_input(m, slirp, ip, icmp); - break; - - case ICMP6_UNREACH: - case ICMP6_TOOBIG: - case ICMP6_TIMXCEED: - case ICMP6_PARAMPROB: - /* XXX? report error? close socket? */ - default: - break; - } - -end: - m_free(m); -} diff --git a/src/network/slirp/ip6_icmp.h b/src/network/slirp/ip6_icmp.h deleted file mode 100644 index 77772a76b..000000000 --- a/src/network/slirp/ip6_icmp.h +++ /dev/null @@ -1,225 +0,0 @@ -/* SPDX-License-Identifier: BSD-3-Clause */ -/* - * Copyright (c) 2013 - * Guillaume Subiron, Yann Bordenave, Serigne Modou Wagne. - */ - -#ifndef SLIRP_IP6_ICMP_H -#define SLIRP_IP6_ICMP_H - -/* - * Interface Control Message Protocol version 6 Definitions. - * Per RFC 4443, March 2006. - * - * Network Discover Protocol Definitions. - * Per RFC 4861, September 2007. - */ - -struct icmp6_echo { /* Echo Messages */ - uint16_t id; - uint16_t seq_num; -}; - -union icmp6_error_body { - uint32_t unused; - uint32_t pointer; - uint32_t mtu; -}; - -/* - * NDP Messages - */ -struct ndp_rs { /* Router Solicitation Message */ - uint32_t reserved; -}; - -struct ndp_ra { /* Router Advertisement Message */ - uint8_t chl; /* Cur Hop Limit */ -#if G_BYTE_ORDER == G_BIG_ENDIAN - uint8_t M : 1, O : 1, reserved : 6; -#else - uint8_t reserved : 6, O : 1, M : 1; -#endif - uint16_t lifetime; /* Router Lifetime */ - uint32_t reach_time; /* Reachable Time */ - uint32_t retrans_time; /* Retrans Timer */ -}; - -G_STATIC_ASSERT(sizeof(struct ndp_ra) == 12); - -struct ndp_ns { /* Neighbor Solicitation Message */ - uint32_t reserved; - struct in6_addr target; /* Target Address */ -}; - -G_STATIC_ASSERT(sizeof(struct ndp_ns) == 20); - -struct ndp_na { /* Neighbor Advertisement Message */ -#if G_BYTE_ORDER == G_BIG_ENDIAN - uint32_t R : 1, /* Router Flag */ - S : 1, /* Solicited Flag */ - O : 1, /* Override Flag */ - reserved_hi : 5, reserved_lo : 24; -#else - uint32_t reserved_hi : 5, O : 1, S : 1, R : 1, reserved_lo : 24; -#endif - struct in6_addr target; /* Target Address */ -}; - -G_STATIC_ASSERT(sizeof(struct ndp_na) == 20); - -struct ndp_redirect { - uint32_t reserved; - struct in6_addr target; /* Target Address */ - struct in6_addr dest; /* Destination Address */ -}; - -G_STATIC_ASSERT(sizeof(struct ndp_redirect) == 36); - -/* - * Structure of an icmpv6 header. - */ -struct icmp6 { - uint8_t icmp6_type; /* type of message, see below */ - uint8_t icmp6_code; /* type sub code */ - uint16_t icmp6_cksum; /* ones complement cksum of struct */ - union { - union icmp6_error_body error_body; - struct icmp6_echo echo; - struct ndp_rs ndp_rs; - struct ndp_ra ndp_ra; - struct ndp_ns ndp_ns; - struct ndp_na ndp_na; - struct ndp_redirect ndp_redirect; - } icmp6_body; -#define icmp6_err icmp6_body.error_body -#define icmp6_echo icmp6_body.echo -#define icmp6_nrs icmp6_body.ndp_rs -#define icmp6_nra icmp6_body.ndp_ra -#define icmp6_nns icmp6_body.ndp_ns -#define icmp6_nna icmp6_body.ndp_na -#define icmp6_redirect icmp6_body.ndp_redirect -}; - -G_STATIC_ASSERT(sizeof(struct icmp6) == 40); - -#define ICMP6_MINLEN 4 -#define ICMP6_ERROR_MINLEN 8 -#define ICMP6_ECHO_MINLEN 8 -#define ICMP6_NDP_RS_MINLEN 8 -#define ICMP6_NDP_RA_MINLEN 16 -#define ICMP6_NDP_NS_MINLEN 24 -#define ICMP6_NDP_NA_MINLEN 24 -#define ICMP6_NDP_REDIRECT_MINLEN 40 - -/* - * NDP Options - */ -#if defined(_MSC_VER) && !defined (__clang__) -#pragma pack(push, 1) -#endif -struct ndpopt { - uint8_t ndpopt_type; /* Option type */ - uint8_t ndpopt_len; /* /!\ In units of 8 octets */ - union { - unsigned char linklayer_addr[6]; /* Source/Target Link-layer */ -#define ndpopt_linklayer ndpopt_body.linklayer_addr - struct prefixinfo { /* Prefix Information */ - uint8_t prefix_length; -#if G_BYTE_ORDER == G_BIG_ENDIAN - uint8_t L : 1, A : 1, reserved1 : 6; -#else - uint8_t reserved1 : 6, A : 1, L : 1; -#endif - uint32_t valid_lt; /* Valid Lifetime */ - uint32_t pref_lt; /* Preferred Lifetime */ - uint32_t reserved2; - struct in6_addr prefix; - } SLIRP_PACKED prefixinfo; -#define ndpopt_prefixinfo ndpopt_body.prefixinfo - struct rdnss { - uint16_t reserved; - uint32_t lifetime; - struct in6_addr addr; - } SLIRP_PACKED rdnss; -#define ndpopt_rdnss ndpopt_body.rdnss - } ndpopt_body; -} SLIRP_PACKED; -#if defined(_MSC_VER) && !defined (__clang__) -#pragma pack(pop) -#endif - -/* NDP options type */ -#define NDPOPT_LINKLAYER_SOURCE 1 /* Source Link-Layer Address */ -#define NDPOPT_LINKLAYER_TARGET 2 /* Target Link-Layer Address */ -#define NDPOPT_PREFIX_INFO 3 /* Prefix Information */ -#define NDPOPT_RDNSS 25 /* Recursive DNS Server Address */ - -/* NDP options size, in octets. */ -#define NDPOPT_LINKLAYER_LEN 8 -#define NDPOPT_PREFIXINFO_LEN 32 -#define NDPOPT_RDNSS_LEN 24 - -/* - * Definition of type and code field values. - * Per https://www.iana.org/assignments/icmpv6-parameters/icmpv6-parameters.xml - * Last Updated 2012-11-12 - */ - -/* Errors */ -#define ICMP6_UNREACH 1 /* Destination Unreachable */ -#define ICMP6_UNREACH_NO_ROUTE 0 /* no route to dest */ -#define ICMP6_UNREACH_DEST_PROHIB 1 /* com with dest prohibited */ -#define ICMP6_UNREACH_SCOPE 2 /* beyond scope of src addr */ -#define ICMP6_UNREACH_ADDRESS 3 /* address unreachable */ -#define ICMP6_UNREACH_PORT 4 /* port unreachable */ -#define ICMP6_UNREACH_SRC_FAIL 5 /* src addr failed */ -#define ICMP6_UNREACH_REJECT_ROUTE 6 /* reject route to dest */ -#define ICMP6_UNREACH_SRC_HDR_ERROR 7 /* error in src routing header */ -#define ICMP6_TOOBIG 2 /* Packet Too Big */ -#define ICMP6_TIMXCEED 3 /* Time Exceeded */ -#define ICMP6_TIMXCEED_INTRANS 0 /* hop limit exceeded in transit */ -#define ICMP6_TIMXCEED_REASS 1 /* ttl=0 in reass */ -#define ICMP6_PARAMPROB 4 /* Parameter Problem */ -#define ICMP6_PARAMPROB_HDR_FIELD 0 /* err header field */ -#define ICMP6_PARAMPROB_NXTHDR_TYPE 1 /* unrecognized Next Header type */ -#define ICMP6_PARAMPROB_IPV6_OPT 2 /* unrecognized IPv6 option */ - -/* Informational Messages */ -#define ICMP6_ECHO_REQUEST 128 /* Echo Request */ -#define ICMP6_ECHO_REPLY 129 /* Echo Reply */ -#define ICMP6_NDP_RS 133 /* Router Solicitation (NDP) */ -#define ICMP6_NDP_RA 134 /* Router Advertisement (NDP) */ -#define ICMP6_NDP_NS 135 /* Neighbor Solicitation (NDP) */ -#define ICMP6_NDP_NA 136 /* Neighbor Advertisement (NDP) */ -#define ICMP6_NDP_REDIRECT 137 /* Redirect Message (NDP) */ - -/* - * Router Configuration Variables (rfc4861#section-6) - */ -#define NDP_IsRouter 1 -#define NDP_AdvSendAdvertisements 1 -#define NDP_MaxRtrAdvInterval 600000 -#define NDP_MinRtrAdvInterval \ - ((NDP_MaxRtrAdvInterval >= 9) ? NDP_MaxRtrAdvInterval / 3 : \ - NDP_MaxRtrAdvInterval) -#define NDP_AdvManagedFlag 0 -#define NDP_AdvOtherConfigFlag 0 -#define NDP_AdvLinkMTU 0 -#define NDP_AdvReachableTime 0 -#define NDP_AdvRetransTime 0 -#define NDP_AdvCurHopLimit 64 -#define NDP_AdvDefaultLifetime ((3 * NDP_MaxRtrAdvInterval) / 1000) -#define NDP_AdvValidLifetime 86400 -#define NDP_AdvOnLinkFlag 1 -#define NDP_AdvPrefLifetime 14400 -#define NDP_AdvAutonomousFlag 1 - -void icmp6_init(Slirp *slirp); -void icmp6_cleanup(Slirp *slirp); -void icmp6_input(struct mbuf *); -void icmp6_send_error(struct mbuf *m, uint8_t type, uint8_t code); -void ndp_send_ra(Slirp *slirp); -void ndp_send_ns(Slirp *slirp, struct in6_addr addr); - -#endif diff --git a/src/network/slirp/ip6_input.c b/src/network/slirp/ip6_input.c deleted file mode 100644 index a83e4f8e3..000000000 --- a/src/network/slirp/ip6_input.c +++ /dev/null @@ -1,85 +0,0 @@ -/* SPDX-License-Identifier: BSD-3-Clause */ -/* - * Copyright (c) 2013 - * Guillaume Subiron, Yann Bordenave, Serigne Modou Wagne. - */ - -#include "slirp.h" -#include "ip6_icmp.h" - -/* - * IP initialization: fill in IP protocol switch table. - * All protocols not implemented in kernel go to raw IP protocol handler. - */ -void ip6_init(Slirp *slirp) -{ - icmp6_init(slirp); -} - -void ip6_cleanup(Slirp *slirp) -{ - icmp6_cleanup(slirp); -} - -void ip6_input(struct mbuf *m) -{ - struct ip6 *ip6; - Slirp *slirp = m->slirp; - - if (!slirp->in6_enabled) { - goto bad; - } - - DEBUG_CALL("ip6_input"); - DEBUG_ARG("m = %p", m); - DEBUG_ARG("m_len = %d", m->m_len); - - if (m->m_len < sizeof(struct ip6)) { - goto bad; - } - - ip6 = mtod(m, struct ip6 *); - - if (ip6->ip_v != IP6VERSION) { - goto bad; - } - - if (ntohs(ip6->ip_pl) + sizeof(struct ip6) > slirp->if_mtu) { - icmp6_send_error(m, ICMP6_TOOBIG, 0); - goto bad; - } - - // Check if the message size is big enough to hold what's - // set in the payload length header. If not this is an invalid - // packet - if (m->m_len < ntohs(ip6->ip_pl) + sizeof(struct ip6)) { - goto bad; - } - - /* check ip_ttl for a correct ICMP reply */ - if (ip6->ip_hl == 0) { - icmp6_send_error(m, ICMP6_TIMXCEED, ICMP6_TIMXCEED_INTRANS); - goto bad; - } - - /* - * Switch out to protocol's input routine. - */ - switch (ip6->ip_nh) { - case IPPROTO_TCP: - NTOHS(ip6->ip_pl); - tcp_input(m, sizeof(struct ip6), (struct socket *)NULL, AF_INET6); - break; - case IPPROTO_UDP: - udp6_input(m); - break; - case IPPROTO_ICMPV6: - icmp6_input(m); - break; - default: - m_free(m); - } - return; -bad: - m_free(m); -} diff --git a/src/network/slirp/ip6_output.c b/src/network/slirp/ip6_output.c deleted file mode 100644 index b86110662..000000000 --- a/src/network/slirp/ip6_output.c +++ /dev/null @@ -1,39 +0,0 @@ -/* SPDX-License-Identifier: BSD-3-Clause */ -/* - * Copyright (c) 2013 - * Guillaume Subiron, Yann Bordenave, Serigne Modou Wagne. - */ - -#include "slirp.h" - -/* Number of packets queued before we start sending - * (to prevent allocing too many mbufs) */ -#define IF6_THRESH 10 - -/* - * IPv6 output. The packet in mbuf chain m contains a IP header - */ -int ip6_output(struct socket *so, struct mbuf *m, int fast) -{ - struct ip6 *ip = mtod(m, struct ip6 *); - - DEBUG_CALL("ip6_output"); - DEBUG_ARG("so = %p", so); - DEBUG_ARG("m = %p", m); - - /* Fill IPv6 header */ - ip->ip_v = IP6VERSION; - ip->ip_hl = IP6_HOP_LIMIT; - ip->ip_tc_hi = 0; - ip->ip_tc_lo = 0; - ip->ip_fl_hi = 0; - ip->ip_fl_lo = 0; - - if (fast) { - if_encap(m->slirp, m); - } else { - if_output(so, m); - } - - return 0; -} diff --git a/src/network/slirp/ip_icmp.c b/src/network/slirp/ip_icmp.c deleted file mode 100644 index 13a0e5508..000000000 --- a/src/network/slirp/ip_icmp.c +++ /dev/null @@ -1,492 +0,0 @@ -/* SPDX-License-Identifier: BSD-3-Clause */ -/* - * Copyright (c) 1982, 1986, 1988, 1993 - * The Regents of the University of California. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. Neither the name of the University nor the names of its contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - * - * @(#)ip_icmp.c 8.2 (Berkeley) 1/4/94 - * ip_icmp.c,v 1.7 1995/05/30 08:09:42 rgrimes Exp - */ - -#include "slirp.h" -#include "ip_icmp.h" - -#ifndef WITH_ICMP_ERROR_MSG -#define WITH_ICMP_ERROR_MSG 0 -#endif - -/* The message sent when emulating PING */ -/* Be nice and tell them it's just a pseudo-ping packet */ -static const char icmp_ping_msg[] = - "This is a pseudo-PING packet used by Slirp to emulate ICMP ECHO-REQUEST " - "packets.\n"; - -/* list of actions for icmp_send_error() on RX of an icmp message */ -static const int icmp_flush[19] = { - /* ECHO REPLY (0) */ 0, - 1, - 1, - /* DEST UNREACH (3) */ 1, - /* SOURCE QUENCH (4)*/ 1, - /* REDIRECT (5) */ 1, - 1, - 1, - /* ECHO (8) */ 0, - /* ROUTERADVERT (9) */ 1, - /* ROUTERSOLICIT (10) */ 1, - /* TIME EXCEEDED (11) */ 1, - /* PARAMETER PROBLEM (12) */ 1, - /* TIMESTAMP (13) */ 0, - /* TIMESTAMP REPLY (14) */ 0, - /* INFO (15) */ 0, - /* INFO REPLY (16) */ 0, - /* ADDR MASK (17) */ 0, - /* ADDR MASK REPLY (18) */ 0 -}; - -void icmp_init(Slirp *slirp) -{ - slirp->icmp.so_next = slirp->icmp.so_prev = &slirp->icmp; - slirp->icmp_last_so = &slirp->icmp; -} - -void icmp_cleanup(Slirp *slirp) -{ - struct socket *so, *so_next; - - for (so = slirp->icmp.so_next; so != &slirp->icmp; so = so_next) { - so_next = so->so_next; - icmp_detach(so); - } -} - -static int icmp_send(struct socket *so, struct mbuf *m, int hlen) -{ - struct ip *ip = mtod(m, struct ip *); - struct sockaddr_in addr; - - so->s = slirp_socket(AF_INET, SOCK_DGRAM, IPPROTO_ICMP); - if (so->s == -1) { - return -1; - } - - if (slirp_bind_outbound(so, AF_INET) != 0) { - // bind failed - close socket - closesocket(so->s); - so->s = -1; - return -1; - } - - so->so_m = m; - so->so_faddr = ip->ip_dst; - so->so_laddr = ip->ip_src; - so->so_iptos = ip->ip_tos; - so->so_type = IPPROTO_ICMP; - so->so_state = SS_ISFCONNECTED; - so->so_expire = curtime + SO_EXPIRE; - - addr.sin_family = AF_INET; - addr.sin_addr = so->so_faddr; - - insque(so, &so->slirp->icmp); - - if (sendto(so->s, m->m_data + hlen, m->m_len - hlen, 0, - (struct sockaddr *)&addr, sizeof(addr)) == -1) { - DEBUG_MISC("icmp_input icmp sendto tx errno = %d-%s", errno, - strerror(errno)); - icmp_send_error(m, ICMP_UNREACH, ICMP_UNREACH_NET, 0, strerror(errno)); - icmp_detach(so); - } - - return 0; -} - -void icmp_detach(struct socket *so) -{ - so->slirp->cb->unregister_poll_fd(so->s, so->slirp->opaque); - closesocket(so->s); - sofree(so); -} - -/* - * Process a received ICMP message. - */ -void icmp_input(struct mbuf *m, int hlen) -{ - register struct icmp *icp; - register struct ip *ip = mtod(m, struct ip *); - int icmplen = ip->ip_len; - Slirp *slirp = m->slirp; - - DEBUG_CALL("icmp_input"); - DEBUG_ARG("m = %p", m); - DEBUG_ARG("m_len = %d", m->m_len); - - /* - * Locate icmp structure in mbuf, and check - * that its not corrupted and of at least minimum length. - */ - if (icmplen < ICMP_MINLEN) { /* min 8 bytes payload */ - freeit: - m_free(m); - goto end_error; - } - - m->m_len -= hlen; - m->m_data += hlen; - icp = mtod(m, struct icmp *); - if (cksum(m, icmplen)) { - goto freeit; - } - m->m_len += hlen; - m->m_data -= hlen; - - DEBUG_ARG("icmp_type = %d", icp->icmp_type); - switch (icp->icmp_type) { - case ICMP_ECHO: - ip->ip_len += hlen; /* since ip_input subtracts this */ - if (ip->ip_dst.s_addr == slirp->vhost_addr.s_addr || - ip->ip_dst.s_addr == slirp->vnameserver_addr.s_addr) { - icmp_reflect(m); - } else if (slirp->restricted) { - goto freeit; - } else { - struct socket *so; - struct sockaddr_storage addr; - so = socreate(slirp); - if (icmp_send(so, m, hlen) == 0) { - return; - } - if (udp_attach(so, AF_INET) == -1) { - DEBUG_MISC("icmp_input udp_attach errno = %d-%s", errno, - strerror(errno)); - sofree(so); - m_free(m); - goto end_error; - } - so->so_m = m; - so->so_ffamily = AF_INET; - so->so_faddr = ip->ip_dst; - so->so_fport = htons(7); - so->so_lfamily = AF_INET; - so->so_laddr = ip->ip_src; - so->so_lport = htons(9); - so->so_iptos = ip->ip_tos; - so->so_type = IPPROTO_ICMP; - so->so_state = SS_ISFCONNECTED; - - /* Send the packet */ - addr = so->fhost.ss; - if (sotranslate_out(so, &addr) < 0) { - icmp_send_error(m, ICMP_UNREACH, ICMP_UNREACH_NET, 0, - strerror(errno)); - udp_detach(so); - return; - } - - if (sendto(so->s, icmp_ping_msg, strlen(icmp_ping_msg), 0, - (struct sockaddr *)&addr, sockaddr_size(&addr)) == -1) { - DEBUG_MISC("icmp_input udp sendto tx errno = %d-%s", errno, - strerror(errno)); - icmp_send_error(m, ICMP_UNREACH, ICMP_UNREACH_NET, 0, - strerror(errno)); - udp_detach(so); - } - } /* if ip->ip_dst.s_addr == alias_addr.s_addr */ - break; - case ICMP_UNREACH: - /* XXX? report error? close socket? */ - case ICMP_TIMXCEED: - case ICMP_PARAMPROB: - case ICMP_SOURCEQUENCH: - case ICMP_TSTAMP: - case ICMP_MASKREQ: - case ICMP_REDIRECT: - m_free(m); - break; - - default: - m_free(m); - } /* swith */ - -end_error: - /* m is m_free()'d xor put in a socket xor or given to ip_send */ - return; -} - - -/* - * Send an ICMP message in response to a situation - * - * RFC 1122: 3.2.2 MUST send at least the IP header and 8 bytes of header. - *MAY send more (we do). MUST NOT change this header information. MUST NOT reply - *to a multicast/broadcast IP address. MUST NOT reply to a multicast/broadcast - *MAC address. MUST reply to only the first fragment. - */ -/* - * Send ICMP_UNREACH back to the source regarding msrc. - * mbuf *msrc is used as a template, but is NOT m_free()'d. - * It is reported as the bad ip packet. The header should - * be fully correct and in host byte order. - * ICMP fragmentation is illegal. All machines must accept 576 bytes in one - * packet. The maximum payload is 576-20(ip hdr)-8(icmp hdr)=548 - */ - -#define ICMP_MAXDATALEN (IP_MSS - 28) -void icmp_send_error(struct mbuf *msrc, uint8_t type, uint8_t code, int minsize, - const char *message) -{ - unsigned hlen, shlen, s_ip_len; - register struct ip *ip; - register struct icmp *icp; - register struct mbuf *m; - - DEBUG_CALL("icmp_send_error"); - DEBUG_ARG("msrc = %p", msrc); - DEBUG_ARG("msrc_len = %d", msrc->m_len); - - if (type != ICMP_UNREACH && type != ICMP_TIMXCEED) - goto end_error; - - /* check msrc */ - if (!msrc) - goto end_error; - ip = mtod(msrc, struct ip *); - if (slirp_debug & DBG_MISC) { - char bufa[20], bufb[20]; - slirp_pstrcpy(bufa, sizeof(bufa), inet_ntoa(ip->ip_src)); - slirp_pstrcpy(bufb, sizeof(bufb), inet_ntoa(ip->ip_dst)); - DEBUG_MISC(" %.16s to %.16s", bufa, bufb); - } - if (ip->ip_off & IP_OFFMASK) - goto end_error; /* Only reply to fragment 0 */ - - /* Do not reply to source-only IPs */ - if ((ip->ip_src.s_addr & htonl(~(0xf << 28))) == 0) { - goto end_error; - } - - shlen = ip->ip_hl << 2; - s_ip_len = ip->ip_len; - if (ip->ip_p == IPPROTO_ICMP) { - icp = (struct icmp *)((char *)ip + shlen); - /* - * Assume any unknown ICMP type is an error. This isn't - * specified by the RFC, but think about it.. - */ - if (icp->icmp_type > 18 || icmp_flush[icp->icmp_type]) - goto end_error; - } - - /* make a copy */ - m = m_get(msrc->slirp); - if (!m) { - goto end_error; - } - - { - int new_m_size; - new_m_size = - sizeof(struct ip) + ICMP_MINLEN + msrc->m_len + ICMP_MAXDATALEN; - if (new_m_size > m->m_size) - m_inc(m, new_m_size); - } - memcpy(m->m_data, msrc->m_data, msrc->m_len); - m->m_len = msrc->m_len; /* copy msrc to m */ - - /* make the header of the reply packet */ - ip = mtod(m, struct ip *); - hlen = sizeof(struct ip); /* no options in reply */ - - /* fill in icmp */ - m->m_data += hlen; - m->m_len -= hlen; - - icp = mtod(m, struct icmp *); - - if (minsize) - s_ip_len = shlen + ICMP_MINLEN; /* return header+8b only */ - else if (s_ip_len > ICMP_MAXDATALEN) /* maximum size */ - s_ip_len = ICMP_MAXDATALEN; - - m->m_len = ICMP_MINLEN + s_ip_len; /* 8 bytes ICMP header */ - - /* min. size = 8+sizeof(struct ip)+8 */ - - icp->icmp_type = type; - icp->icmp_code = code; - icp->icmp_id = 0; - icp->icmp_seq = 0; - - memcpy(&icp->icmp_ip, msrc->m_data, s_ip_len); /* report the ip packet */ - HTONS(icp->icmp_ip.ip_len); - HTONS(icp->icmp_ip.ip_id); - HTONS(icp->icmp_ip.ip_off); - - if (message && WITH_ICMP_ERROR_MSG) { /* append message to ICMP packet */ - int message_len; - char *cpnt; - message_len = strlen(message); - if (message_len > ICMP_MAXDATALEN) - message_len = ICMP_MAXDATALEN; - cpnt = (char *)m->m_data + m->m_len; - memcpy(cpnt, message, message_len); - m->m_len += message_len; - } - - icp->icmp_cksum = 0; - icp->icmp_cksum = cksum(m, m->m_len); - - m->m_data -= hlen; - m->m_len += hlen; - - /* fill in ip */ - ip->ip_hl = hlen >> 2; - ip->ip_len = m->m_len; - - ip->ip_tos = ((ip->ip_tos & 0x1E) | 0xC0); /* high priority for errors */ - - ip->ip_ttl = MAXTTL; - ip->ip_p = IPPROTO_ICMP; - ip->ip_dst = ip->ip_src; /* ip addresses */ - ip->ip_src = m->slirp->vhost_addr; - - (void)ip_output((struct socket *)NULL, m); - -end_error: - return; -} -#undef ICMP_MAXDATALEN - -/* - * Reflect the ip packet back to the source - */ -void icmp_reflect(struct mbuf *m) -{ - register struct ip *ip = mtod(m, struct ip *); - int hlen = ip->ip_hl << 2; - int optlen = hlen - sizeof(struct ip); - register struct icmp *icp; - - /* - * Send an icmp packet back to the ip level, - * after supplying a checksum. - */ - m->m_data += hlen; - m->m_len -= hlen; - icp = mtod(m, struct icmp *); - - icp->icmp_type = ICMP_ECHOREPLY; - icp->icmp_cksum = 0; - icp->icmp_cksum = cksum(m, ip->ip_len - hlen); - - m->m_data -= hlen; - m->m_len += hlen; - - /* fill in ip */ - if (optlen > 0) { - /* - * Strip out original options by copying rest of first - * mbuf's data back, and adjust the IP length. - */ - memmove((char *)(ip + 1), (char *)ip + hlen, - (unsigned)(m->m_len - hlen)); - hlen -= optlen; - ip->ip_hl = hlen >> 2; - ip->ip_len -= optlen; - m->m_len -= optlen; - } - - ip->ip_ttl = MAXTTL; - { /* swap */ - struct in_addr icmp_dst; - icmp_dst = ip->ip_dst; - ip->ip_dst = ip->ip_src; - ip->ip_src = icmp_dst; - } - - (void)ip_output((struct socket *)NULL, m); -} - -void icmp_receive(struct socket *so) -{ - struct mbuf *m = so->so_m; - struct ip *ip = mtod(m, struct ip *); - int hlen = ip->ip_hl << 2; - uint8_t error_code; - struct icmp *icp; - int id, len; - - m->m_data += hlen; - m->m_len -= hlen; - icp = mtod(m, struct icmp *); - - id = icp->icmp_id; - len = recv(so->s, icp, M_ROOM(m), 0); - /* - * The behavior of reading SOCK_DGRAM+IPPROTO_ICMP sockets is inconsistent - * between host OSes. On Linux, only the ICMP header and payload is - * included. On macOS/Darwin, the socket acts like a raw socket and - * includes the IP header as well. On other BSDs, SOCK_DGRAM+IPPROTO_ICMP - * sockets aren't supported at all, so we treat them like raw sockets. It - * isn't possible to detect this difference at runtime, so we must use an - * #ifdef to determine if we need to remove the IP header. - */ -#ifdef CONFIG_BSD - if (len >= sizeof(struct ip)) { - struct ip *inner_ip = mtod(m, struct ip *); - int inner_hlen = inner_ip->ip_hl << 2; - if (inner_hlen > len) { - len = -1; - errno = -EINVAL; - } else { - len -= inner_hlen; - memmove(icp, (unsigned char *)icp + inner_hlen, len); - } - } else { - len = -1; - errno = -EINVAL; - } -#endif - icp->icmp_id = id; - - m->m_data -= hlen; - m->m_len += hlen; - - if (len == -1 || len == 0) { - if (errno == ENETUNREACH) { - error_code = ICMP_UNREACH_NET; - } else { - error_code = ICMP_UNREACH_HOST; - } - DEBUG_MISC(" udp icmp rx errno = %d-%s", errno, strerror(errno)); - icmp_send_error(so->so_m, ICMP_UNREACH, error_code, 0, strerror(errno)); - } else { - icmp_reflect(so->so_m); - so->so_m = NULL; /* Don't m_free() it again! */ - } - icmp_detach(so); -} diff --git a/src/network/slirp/ip_icmp.h b/src/network/slirp/ip_icmp.h deleted file mode 100644 index 84707db24..000000000 --- a/src/network/slirp/ip_icmp.h +++ /dev/null @@ -1,166 +0,0 @@ -/* SPDX-License-Identifier: BSD-3-Clause */ -/* - * Copyright (c) 1982, 1986, 1993 - * The Regents of the University of California. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. Neither the name of the University nor the names of its contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - * - * @(#)ip_icmp.h 8.1 (Berkeley) 6/10/93 - * ip_icmp.h,v 1.4 1995/05/30 08:09:43 rgrimes Exp - */ - -#ifndef NETINET_IP_ICMP_H -#define NETINET_IP_ICMP_H - -/* - * Interface Control Message Protocol Definitions. - * Per RFC 792, September 1981. - */ - -typedef uint32_t n_time; - -/* - * Structure of an icmp header. - */ -struct icmp { - uint8_t icmp_type; /* type of message, see below */ - uint8_t icmp_code; /* type sub code */ - uint16_t icmp_cksum; /* ones complement cksum of struct */ - union { - uint8_t ih_pptr; /* ICMP_PARAMPROB */ - struct in_addr ih_gwaddr; /* ICMP_REDIRECT */ - struct ih_idseq { - uint16_t icd_id; - uint16_t icd_seq; - } ih_idseq; - int ih_void; - - /* ICMP_UNREACH_NEEDFRAG -- Path MTU Discovery (RFC1191) */ - struct ih_pmtu { - uint16_t ipm_void; - uint16_t ipm_nextmtu; - } ih_pmtu; - } icmp_hun; -#define icmp_pptr icmp_hun.ih_pptr -#define icmp_gwaddr icmp_hun.ih_gwaddr -#define icmp_id icmp_hun.ih_idseq.icd_id -#define icmp_seq icmp_hun.ih_idseq.icd_seq -#define icmp_void icmp_hun.ih_void -#define icmp_pmvoid icmp_hun.ih_pmtu.ipm_void -#define icmp_nextmtu icmp_hun.ih_pmtu.ipm_nextmtu - union { - struct id_ts { - n_time its_otime; - n_time its_rtime; - n_time its_ttime; - } id_ts; - struct id_ip { - struct ip idi_ip; - /* options and then 64 bits of data */ - } id_ip; - uint32_t id_mask; - char id_data[1]; - } icmp_dun; -#define icmp_otime icmp_dun.id_ts.its_otime -#define icmp_rtime icmp_dun.id_ts.its_rtime -#define icmp_ttime icmp_dun.id_ts.its_ttime -#define icmp_ip icmp_dun.id_ip.idi_ip -#define icmp_mask icmp_dun.id_mask -#define icmp_data icmp_dun.id_data -}; - -/* - * Lower bounds on packet lengths for various types. - * For the error advice packets must first ensure that the - * packet is large enough to contain the returned ip header. - * Only then can we do the check to see if 64 bits of packet - * data have been returned, since we need to check the returned - * ip header length. - */ -#define ICMP_MINLEN 8 /* abs minimum */ -#define ICMP_TSLEN (8 + 3 * sizeof(n_time)) /* timestamp */ -#define ICMP_MASKLEN 12 /* address mask */ -#define ICMP_ADVLENMIN (8 + sizeof(struct ip) + 8) /* min */ -#define ICMP_ADVLEN(p) (8 + ((p)->icmp_ip.ip_hl << 2) + 8) -/* N.B.: must separately check that ip_hl >= 5 */ - -/* - * Definition of type and code field values. - */ -#define ICMP_ECHOREPLY 0 /* echo reply */ -#define ICMP_UNREACH 3 /* dest unreachable, codes: */ -#define ICMP_UNREACH_NET 0 /* bad net */ -#define ICMP_UNREACH_HOST 1 /* bad host */ -#define ICMP_UNREACH_PROTOCOL 2 /* bad protocol */ -#define ICMP_UNREACH_PORT 3 /* bad port */ -#define ICMP_UNREACH_NEEDFRAG 4 /* IP_DF caused drop */ -#define ICMP_UNREACH_SRCFAIL 5 /* src route failed */ -#define ICMP_UNREACH_NET_UNKNOWN 6 /* unknown net */ -#define ICMP_UNREACH_HOST_UNKNOWN 7 /* unknown host */ -#define ICMP_UNREACH_ISOLATED 8 /* src host isolated */ -#define ICMP_UNREACH_NET_PROHIB 9 /* prohibited access */ -#define ICMP_UNREACH_HOST_PROHIB 10 /* ditto */ -#define ICMP_UNREACH_TOSNET 11 /* bad tos for net */ -#define ICMP_UNREACH_TOSHOST 12 /* bad tos for host */ -#define ICMP_SOURCEQUENCH 4 /* packet lost, slow down */ -#define ICMP_REDIRECT 5 /* shorter route, codes: */ -#define ICMP_REDIRECT_NET 0 /* for network */ -#define ICMP_REDIRECT_HOST 1 /* for host */ -#define ICMP_REDIRECT_TOSNET 2 /* for tos and net */ -#define ICMP_REDIRECT_TOSHOST 3 /* for tos and host */ -#define ICMP_ECHO 8 /* echo service */ -#define ICMP_ROUTERADVERT 9 /* router advertisement */ -#define ICMP_ROUTERSOLICIT 10 /* router solicitation */ -#define ICMP_TIMXCEED 11 /* time exceeded, code: */ -#define ICMP_TIMXCEED_INTRANS 0 /* ttl==0 in transit */ -#define ICMP_TIMXCEED_REASS 1 /* ttl==0 in reass */ -#define ICMP_PARAMPROB 12 /* ip header bad */ -#define ICMP_PARAMPROB_OPTABSENT 1 /* req. opt. absent */ -#define ICMP_TSTAMP 13 /* timestamp request */ -#define ICMP_TSTAMPREPLY 14 /* timestamp reply */ -#define ICMP_IREQ 15 /* information request */ -#define ICMP_IREQREPLY 16 /* information reply */ -#define ICMP_MASKREQ 17 /* address mask request */ -#define ICMP_MASKREPLY 18 /* address mask reply */ - -#define ICMP_MAXTYPE 18 - -#define ICMP_INFOTYPE(type) \ - ((type) == ICMP_ECHOREPLY || (type) == ICMP_ECHO || \ - (type) == ICMP_ROUTERADVERT || (type) == ICMP_ROUTERSOLICIT || \ - (type) == ICMP_TSTAMP || (type) == ICMP_TSTAMPREPLY || \ - (type) == ICMP_IREQ || (type) == ICMP_IREQREPLY || \ - (type) == ICMP_MASKREQ || (type) == ICMP_MASKREPLY) - -void icmp_init(Slirp *slirp); -void icmp_cleanup(Slirp *slirp); -void icmp_input(struct mbuf *, int); -void icmp_send_error(struct mbuf *msrc, uint8_t type, uint8_t code, int minsize, - const char *message); -void icmp_reflect(struct mbuf *); -void icmp_receive(struct socket *so); -void icmp_detach(struct socket *so); - -#endif diff --git a/src/network/slirp/ip_input.c b/src/network/slirp/ip_input.c deleted file mode 100644 index e04d1506d..000000000 --- a/src/network/slirp/ip_input.c +++ /dev/null @@ -1,462 +0,0 @@ -/* SPDX-License-Identifier: BSD-3-Clause */ -/* - * Copyright (c) 1982, 1986, 1988, 1993 - * The Regents of the University of California. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. Neither the name of the University nor the names of its contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - * - * @(#)ip_input.c 8.2 (Berkeley) 1/4/94 - * ip_input.c,v 1.11 1994/11/16 10:17:08 jkh Exp - */ - -/* - * Changes and additions relating to SLiRP are - * Copyright (c) 1995 Danny Gasparovski. - */ - -#include "slirp.h" -#include "ip_icmp.h" -#include - -static struct ip *ip_reass(Slirp *slirp, struct ip *ip, struct ipq *fp); -static void ip_freef(Slirp *slirp, struct ipq *fp); -static void ip_enq(register struct ipasfrag *p, register struct ipasfrag *prev); -static void ip_deq(register struct ipasfrag *p); - -/* - * IP initialization: fill in IP protocol switch table. - * All protocols not implemented in kernel go to raw IP protocol handler. - */ -void ip_init(Slirp *slirp) -{ - slirp->ipq.ip_link.next = slirp->ipq.ip_link.prev = &slirp->ipq.ip_link; - udp_init(slirp); - tcp_init(slirp); - icmp_init(slirp); -} - -void ip_cleanup(Slirp *slirp) -{ - udp_cleanup(slirp); - tcp_cleanup(slirp); - icmp_cleanup(slirp); -} - -/* - * Ip input routine. Checksum and byte swap header. If fragmented - * try to reassemble. Process options. Pass to next level. - */ -void ip_input(struct mbuf *m) -{ - Slirp *slirp = m->slirp; - register struct ip *ip; - int hlen; - - if (!slirp->in_enabled) { - goto bad; - } - - DEBUG_CALL("ip_input"); - DEBUG_ARG("m = %p", m); - DEBUG_ARG("m_len = %d", m->m_len); - - if (m->m_len < sizeof(struct ip)) { - goto bad; - } - - ip = mtod(m, struct ip *); - - if (ip->ip_v != IPVERSION) { - goto bad; - } - - hlen = ip->ip_hl << 2; - if (hlen < sizeof(struct ip) || hlen > m->m_len) { /* min header length */ - goto bad; /* or packet too short */ - } - - /* keep ip header intact for ICMP reply - * ip->ip_sum = cksum(m, hlen); - * if (ip->ip_sum) { - */ - if (cksum(m, hlen)) { - goto bad; - } - - /* - * Convert fields to host representation. - */ - NTOHS(ip->ip_len); - if (ip->ip_len < hlen) { - goto bad; - } - NTOHS(ip->ip_id); - NTOHS(ip->ip_off); - - /* - * Check that the amount of data in the buffers - * is as at least much as the IP header would have us expect. - * Trim mbufs if longer than we expect. - * Drop packet if shorter than we expect. - */ - if (m->m_len < ip->ip_len) { - goto bad; - } - - /* Should drop packet if mbuf too long? hmmm... */ - if (m->m_len > ip->ip_len) - m_adj(m, ip->ip_len - m->m_len); - - /* check ip_ttl for a correct ICMP reply */ - if (ip->ip_ttl == 0) { - icmp_send_error(m, ICMP_TIMXCEED, ICMP_TIMXCEED_INTRANS, 0, "ttl"); - goto bad; - } - - /* - * If offset or IP_MF are set, must reassemble. - * Otherwise, nothing need be done. - * (We could look in the reassembly queue to see - * if the packet was previously fragmented, - * but it's not worth the time; just let them time out.) - * - * XXX This should fail, don't fragment yet - */ - if (ip->ip_off & ~IP_DF) { - register struct ipq *fp; - struct qlink *l; - /* - * Look for queue of fragments - * of this datagram. - */ - for (l = slirp->ipq.ip_link.next; l != &slirp->ipq.ip_link; - l = l->next) { - fp = container_of(l, struct ipq, ip_link); - if (ip->ip_id == fp->ipq_id && - ip->ip_src.s_addr == fp->ipq_src.s_addr && - ip->ip_dst.s_addr == fp->ipq_dst.s_addr && - ip->ip_p == fp->ipq_p) - goto found; - } - fp = NULL; - found: - - /* - * Adjust ip_len to not reflect header, - * set ip_mff if more fragments are expected, - * convert offset of this to bytes. - */ - ip->ip_len -= hlen; - if (ip->ip_off & IP_MF) - ip->ip_tos |= 1; - else - ip->ip_tos &= ~1; - - ip->ip_off <<= 3; - - /* - * If datagram marked as having more fragments - * or if this is not the first fragment, - * attempt reassembly; if it succeeds, proceed. - */ - if (ip->ip_tos & 1 || ip->ip_off) { - ip = ip_reass(slirp, ip, fp); - if (ip == NULL) - return; - m = dtom(slirp, ip); - } else if (fp) - ip_freef(slirp, fp); - - } else - ip->ip_len -= hlen; - - /* - * Switch out to protocol's input routine. - */ - switch (ip->ip_p) { - case IPPROTO_TCP: - tcp_input(m, hlen, (struct socket *)NULL, AF_INET); - break; - case IPPROTO_UDP: - udp_input(m, hlen); - break; - case IPPROTO_ICMP: - icmp_input(m, hlen); - break; - default: - m_free(m); - } - return; -bad: - m_free(m); -} - -#define iptofrag(P) ((struct ipasfrag *)(((char *)(P)) - sizeof(struct qlink))) -#define fragtoip(P) ((struct ip *)(((char *)(P)) + sizeof(struct qlink))) -/* - * Take incoming datagram fragment and try to - * reassemble it into whole datagram. If a chain for - * reassembly of this datagram already exists, then it - * is given as fp; otherwise have to make a chain. - */ -static struct ip *ip_reass(Slirp *slirp, struct ip *ip, struct ipq *fp) -{ - register struct mbuf *m = dtom(slirp, ip); - register struct ipasfrag *q; - int hlen = ip->ip_hl << 2; - int i, next; - - DEBUG_CALL("ip_reass"); - DEBUG_ARG("ip = %p", ip); - DEBUG_ARG("fp = %p", fp); - DEBUG_ARG("m = %p", m); - - /* - * Presence of header sizes in mbufs - * would confuse code below. - * Fragment m_data is concatenated. - */ - m->m_data += hlen; - m->m_len -= hlen; - - /* - * If first fragment to arrive, create a reassembly queue. - */ - if (fp == NULL) { - struct mbuf *t = m_get(slirp); - - if (t == NULL) { - goto dropfrag; - } - fp = mtod(t, struct ipq *); - insque(&fp->ip_link, &slirp->ipq.ip_link); - fp->ipq_ttl = IPFRAGTTL; - fp->ipq_p = ip->ip_p; - fp->ipq_id = ip->ip_id; - fp->frag_link.next = fp->frag_link.prev = &fp->frag_link; - fp->ipq_src = ip->ip_src; - fp->ipq_dst = ip->ip_dst; - q = (struct ipasfrag *)fp; - goto insert; - } - - /* - * Find a segment which begins after this one does. - */ - for (q = fp->frag_link.next; q != (struct ipasfrag *)&fp->frag_link; - q = q->ipf_next) - if (q->ipf_off > ip->ip_off) - break; - - /* - * If there is a preceding segment, it may provide some of - * our data already. If so, drop the data from the incoming - * segment. If it provides all of our data, drop us. - */ - if (q->ipf_prev != &fp->frag_link) { - struct ipasfrag *pq = q->ipf_prev; - i = pq->ipf_off + pq->ipf_len - ip->ip_off; - if (i > 0) { - if (i >= ip->ip_len) - goto dropfrag; - m_adj(dtom(slirp, ip), i); - ip->ip_off += i; - ip->ip_len -= i; - } - } - - /* - * While we overlap succeeding segments trim them or, - * if they are completely covered, dequeue them. - */ - while (q != (struct ipasfrag *)&fp->frag_link && - ip->ip_off + ip->ip_len > q->ipf_off) { - struct ipasfrag *prev; - i = (ip->ip_off + ip->ip_len) - q->ipf_off; - if (i < q->ipf_len) { - q->ipf_len -= i; - q->ipf_off += i; - m_adj(dtom(slirp, q), i); - break; - } - prev = q; - q = q->ipf_next; - ip_deq(prev); - m_free(dtom(slirp, prev)); - } - -insert: - /* - * Stick new segment in its place; - * check for complete reassembly. - */ - ip_enq(iptofrag(ip), q->ipf_prev); - next = 0; - for (q = fp->frag_link.next; q != (struct ipasfrag *)&fp->frag_link; - q = q->ipf_next) { - if (q->ipf_off != next) - return NULL; - next += q->ipf_len; - } - if (((struct ipasfrag *)(q->ipf_prev))->ipf_tos & 1) - return NULL; - - /* - * Reassembly is complete; concatenate fragments. - */ - q = fp->frag_link.next; - m = dtom(slirp, q); - int delta = (char *)q - (m->m_flags & M_EXT ? m->m_ext : m->m_dat); - - q = (struct ipasfrag *)q->ipf_next; - while (q != (struct ipasfrag *)&fp->frag_link) { - struct mbuf *t = dtom(slirp, q); - q = (struct ipasfrag *)q->ipf_next; - m_cat(m, t); - } - - /* - * Create header for new ip packet by - * modifying header of first packet; - * dequeue and discard fragment reassembly header. - * Make header visible. - */ - q = fp->frag_link.next; - - /* - * If the fragments concatenated to an mbuf that's bigger than the total - * size of the fragment and the mbuf was not already using an m_ext buffer, - * then an m_ext buffer was alloced. But fp->ipq_next points to the old - * buffer (in the mbuf), so we must point ip into the new buffer. - */ - if (m->m_flags & M_EXT) { - q = (struct ipasfrag *)(m->m_ext + delta); - } - - ip = fragtoip(q); - ip->ip_len = next; - ip->ip_tos &= ~1; - ip->ip_src = fp->ipq_src; - ip->ip_dst = fp->ipq_dst; - remque(&fp->ip_link); - (void)m_free(dtom(slirp, fp)); - m->m_len += (ip->ip_hl << 2); - m->m_data -= (ip->ip_hl << 2); - - return ip; - -dropfrag: - m_free(m); - return NULL; -} - -/* - * Free a fragment reassembly header and all - * associated datagrams. - */ -static void ip_freef(Slirp *slirp, struct ipq *fp) -{ - register struct ipasfrag *q, *p; - - for (q = fp->frag_link.next; q != (struct ipasfrag *)&fp->frag_link; - q = p) { - p = q->ipf_next; - ip_deq(q); - m_free(dtom(slirp, q)); - } - remque(&fp->ip_link); - (void)m_free(dtom(slirp, fp)); -} - -/* - * Put an ip fragment on a reassembly chain. - * Like insque, but pointers in middle of structure. - */ -static void ip_enq(register struct ipasfrag *p, register struct ipasfrag *prev) -{ - DEBUG_CALL("ip_enq"); - DEBUG_ARG("prev = %p", prev); - p->ipf_prev = prev; - p->ipf_next = prev->ipf_next; - ((struct ipasfrag *)(prev->ipf_next))->ipf_prev = p; - prev->ipf_next = p; -} - -/* - * To ip_enq as remque is to insque. - */ -static void ip_deq(register struct ipasfrag *p) -{ - ((struct ipasfrag *)(p->ipf_prev))->ipf_next = p->ipf_next; - ((struct ipasfrag *)(p->ipf_next))->ipf_prev = p->ipf_prev; -} - -/* - * IP timer processing; - * if a timer expires on a reassembly - * queue, discard it. - */ -void ip_slowtimo(Slirp *slirp) -{ - struct qlink *l; - - DEBUG_CALL("ip_slowtimo"); - - l = slirp->ipq.ip_link.next; - - if (l == NULL) - return; - - while (l != &slirp->ipq.ip_link) { - struct ipq *fp = container_of(l, struct ipq, ip_link); - l = l->next; - if (--fp->ipq_ttl == 0) { - ip_freef(slirp, fp); - } - } -} - -/* - * Strip out IP options, at higher - * level protocol in the kernel. - * Second argument is buffer to which options - * will be moved, and return value is their length. - * (XXX) should be deleted; last arg currently ignored. - */ -void ip_stripoptions(register struct mbuf *m, struct mbuf *mopt) -{ - register int i; - struct ip *ip = mtod(m, struct ip *); - register char *opts; - int olen; - - olen = (ip->ip_hl << 2) - sizeof(struct ip); - opts = (char *)(ip + 1); - i = m->m_len - (sizeof(struct ip) + olen); - memmove(opts, opts + olen, (unsigned)i); - m->m_len -= olen; - - ip->ip_hl = sizeof(struct ip) >> 2; -} diff --git a/src/network/slirp/ip_output.c b/src/network/slirp/ip_output.c deleted file mode 100644 index 22916a37d..000000000 --- a/src/network/slirp/ip_output.c +++ /dev/null @@ -1,169 +0,0 @@ -/* SPDX-License-Identifier: BSD-3-Clause */ -/* - * Copyright (c) 1982, 1986, 1988, 1990, 1993 - * The Regents of the University of California. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. Neither the name of the University nor the names of its contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - * - * @(#)ip_output.c 8.3 (Berkeley) 1/21/94 - * ip_output.c,v 1.9 1994/11/16 10:17:10 jkh Exp - */ - -/* - * Changes and additions relating to SLiRP are - * Copyright (c) 1995 Danny Gasparovski. - */ - -#include "slirp.h" - -/* Number of packets queued before we start sending - * (to prevent allocing too many mbufs) */ -#define IF_THRESH 10 - -/* - * IP output. The packet in mbuf chain m contains a skeletal IP - * header (with len, off, ttl, proto, tos, src, dst). - * The mbuf chain containing the packet will be freed. - * The mbuf opt, if present, will not be freed. - */ -int ip_output(struct socket *so, struct mbuf *m0) -{ - Slirp *slirp = m0->slirp; - register struct ip *ip; - register struct mbuf *m = m0; - register int hlen = sizeof(struct ip); - int len, off, error = 0; - - DEBUG_CALL("ip_output"); - DEBUG_ARG("so = %p", so); - DEBUG_ARG("m0 = %p", m0); - - ip = mtod(m, struct ip *); - /* - * Fill in IP header. - */ - ip->ip_v = IPVERSION; - ip->ip_off &= IP_DF; - ip->ip_id = htons(slirp->ip_id++); - ip->ip_hl = hlen >> 2; - - /* - * If small enough for interface, can just send directly. - */ - if ((uint16_t)ip->ip_len <= slirp->if_mtu) { - ip->ip_len = htons((uint16_t)ip->ip_len); - ip->ip_off = htons((uint16_t)ip->ip_off); - ip->ip_sum = 0; - ip->ip_sum = cksum(m, hlen); - - if_output(so, m); - goto done; - } - - /* - * Too large for interface; fragment if possible. - * Must be able to put at least 8 bytes per fragment. - */ - if (ip->ip_off & IP_DF) { - error = -1; - goto bad; - } - - len = (slirp->if_mtu - hlen) & ~7; /* ip databytes per packet */ - if (len < 8) { - error = -1; - goto bad; - } - - { - int mhlen, firstlen = len; - struct mbuf **mnext = &m->m_nextpkt; - - /* - * Loop through length of segment after first fragment, - * make new header and copy data of each part and link onto chain. - */ - m0 = m; - mhlen = sizeof(struct ip); - for (off = hlen + len; off < (uint16_t)ip->ip_len; off += len) { - register struct ip *mhip; - m = m_get(slirp); - if (m == NULL) { - error = -1; - goto sendorfree; - } - m->m_data += IF_MAXLINKHDR; - mhip = mtod(m, struct ip *); - *mhip = *ip; - - m->m_len = mhlen; - mhip->ip_off = ((off - hlen) >> 3) + (ip->ip_off & ~IP_MF); - if (ip->ip_off & IP_MF) - mhip->ip_off |= IP_MF; - if (off + len >= (uint16_t)ip->ip_len) - len = (uint16_t)ip->ip_len - off; - else - mhip->ip_off |= IP_MF; - mhip->ip_len = htons((uint16_t)(len + mhlen)); - - if (m_copy(m, m0, off, len) < 0) { - error = -1; - goto sendorfree; - } - - mhip->ip_off = htons((uint16_t)mhip->ip_off); - mhip->ip_sum = 0; - mhip->ip_sum = cksum(m, mhlen); - *mnext = m; - mnext = &m->m_nextpkt; - } - /* - * Update first fragment by trimming what's been copied out - * and updating header, then send each fragment (in order). - */ - m = m0; - m_adj(m, hlen + firstlen - (uint16_t)ip->ip_len); - ip->ip_len = htons((uint16_t)m->m_len); - ip->ip_off = htons((uint16_t)(ip->ip_off | IP_MF)); - ip->ip_sum = 0; - ip->ip_sum = cksum(m, hlen); - sendorfree: - for (m = m0; m; m = m0) { - m0 = m->m_nextpkt; - m->m_nextpkt = NULL; - if (error == 0) - if_output(so, m); - else - m_free(m); - } - } - -done: - return (error); - -bad: - m_free(m0); - goto done; -} diff --git a/src/network/slirp/libslirp-version.h b/src/network/slirp/libslirp-version.h deleted file mode 100644 index 1599206a5..000000000 --- a/src/network/slirp/libslirp-version.h +++ /dev/null @@ -1,24 +0,0 @@ -/* SPDX-License-Identifier: BSD-3-Clause */ -#ifndef LIBSLIRP_VERSION_H_ -#define LIBSLIRP_VERSION_H_ - -#ifdef __cplusplus -extern "C" { -#endif - -#define SLIRP_MAJOR_VERSION 4 -#define SLIRP_MINOR_VERSION 3 -#define SLIRP_MICRO_VERSION 1 -#define SLIRP_VERSION_STRING "4.3.1-git-86Box" - -#define SLIRP_CHECK_VERSION(major,minor,micro) \ - (SLIRP_MAJOR_VERSION > (major) || \ - (SLIRP_MAJOR_VERSION == (major) && SLIRP_MINOR_VERSION > (minor)) || \ - (SLIRP_MAJOR_VERSION == (major) && SLIRP_MINOR_VERSION == (minor) && \ - SLIRP_MICRO_VERSION >= (micro))) - -#ifdef __cplusplus -} /* extern "C" */ -#endif - -#endif /* LIBSLIRP_VERSION_H_ */ diff --git a/src/network/slirp/libslirp.h b/src/network/slirp/libslirp.h deleted file mode 100644 index 7c4340390..000000000 --- a/src/network/slirp/libslirp.h +++ /dev/null @@ -1,186 +0,0 @@ -/* SPDX-License-Identifier: BSD-3-Clause */ -#ifndef LIBSLIRP_H -#define LIBSLIRP_H - -#include -#include -#include - -#ifdef _WIN32 -#include -#include -#else -#include -#include -#endif - -#include "libslirp-version.h" - -/* Windows does not define ssize_t, so we need to define it here. */ -#ifndef _SSIZE_T_DEFINED -# define _SSIZE_T_DEFINED -# undef ssize_t -# ifdef _WIN64 -# define ssize_t int64_t -# else -# define ssize_t int32_t -# endif -#endif - -#ifdef __cplusplus -extern "C" { -#endif - -typedef struct Slirp Slirp; - -enum { - SLIRP_POLL_IN = 1 << 0, - SLIRP_POLL_OUT = 1 << 1, - SLIRP_POLL_PRI = 1 << 2, - SLIRP_POLL_ERR = 1 << 3, - SLIRP_POLL_HUP = 1 << 4, -}; - -typedef ssize_t (*SlirpReadCb)(void *buf, size_t len, void *opaque); -typedef ssize_t (*SlirpWriteCb)(const void *buf, size_t len, void *opaque); -typedef void (*SlirpTimerCb)(void *opaque); -typedef int (*SlirpAddPollCb)(int fd, int events, void *opaque); -typedef int (*SlirpGetREventsCb)(int idx, void *opaque); - -/* - * Callbacks from slirp - */ -typedef struct SlirpCb { - /* - * Send an ethernet frame to the guest network. The opaque - * parameter is the one given to slirp_init(). The function - * doesn't need to send all the data and may return - -#define MBUF_THRESH 30 - -/* - * Find a nice value for msize - */ -#define SLIRP_MSIZE(mtu) \ - (offsetof(struct mbuf, m_dat) + IF_MAXLINKHDR + TCPIPHDR_DELTA + (mtu)) - -void m_init(Slirp *slirp) -{ - slirp->m_freelist.qh_link = slirp->m_freelist.qh_rlink = &slirp->m_freelist; - slirp->m_usedlist.qh_link = slirp->m_usedlist.qh_rlink = &slirp->m_usedlist; -} - -void m_cleanup(Slirp *slirp) -{ - struct mbuf *m, *next; - - m = (struct mbuf *)slirp->m_usedlist.qh_link; - while ((struct quehead *)m != &slirp->m_usedlist) { - next = m->m_next; - if (m->m_flags & M_EXT) { - g_free(m->m_ext); - } - g_free(m); - m = next; - } - m = (struct mbuf *)slirp->m_freelist.qh_link; - while ((struct quehead *)m != &slirp->m_freelist) { - next = m->m_next; - g_free(m); - m = next; - } -} - -/* - * Get an mbuf from the free list, if there are none - * allocate one - * - * Because fragmentation can occur if we alloc new mbufs and - * free old mbufs, we mark all mbufs above mbuf_thresh as M_DOFREE, - * which tells m_free to actually g_free() it - */ -struct mbuf *m_get(Slirp *slirp) -{ - register struct mbuf *m; - int flags = 0; - - DEBUG_CALL("m_get"); - - if (slirp->m_freelist.qh_link == &slirp->m_freelist) { - m = g_malloc(SLIRP_MSIZE(slirp->if_mtu)); - slirp->mbuf_alloced++; - if (slirp->mbuf_alloced > MBUF_THRESH) - flags = M_DOFREE; - m->slirp = slirp; - } else { - m = (struct mbuf *)slirp->m_freelist.qh_link; - remque(m); - } - - /* Insert it in the used list */ - insque(m, &slirp->m_usedlist); - m->m_flags = (flags | M_USEDLIST); - - /* Initialise it */ - m->m_size = SLIRP_MSIZE(slirp->if_mtu) - offsetof(struct mbuf, m_dat); - m->m_data = m->m_dat; - m->m_len = 0; - m->m_nextpkt = NULL; - m->m_prevpkt = NULL; - m->resolution_requested = false; - m->expiration_date = (uint64_t)-1; - DEBUG_ARG("m = %p", m); - return m; -} - -void m_free(struct mbuf *m) -{ - DEBUG_CALL("m_free"); - DEBUG_ARG("m = %p", m); - - if (m) { - /* Remove from m_usedlist */ - if (m->m_flags & M_USEDLIST) - remque(m); - - /* If it's M_EXT, free() it */ - if (m->m_flags & M_EXT) { - g_free(m->m_ext); - } - /* - * Either free() it or put it on the free list - */ - if (m->m_flags & M_DOFREE) { - m->slirp->mbuf_alloced--; - g_free(m); - } else if ((m->m_flags & M_FREELIST) == 0) { - insque(m, &m->slirp->m_freelist); - m->m_flags = M_FREELIST; /* Clobber other flags */ - } - } /* if(m) */ -} - -/* - * Copy data from one mbuf to the end of - * the other.. if result is too big for one mbuf, allocate - * an M_EXT data segment - */ -void m_cat(struct mbuf *m, struct mbuf *n) -{ - /* - * If there's no room, realloc - */ - if (M_FREEROOM(m) < n->m_len) - m_inc(m, m->m_len + n->m_len); - - memcpy(m->m_data + m->m_len, n->m_data, n->m_len); - m->m_len += n->m_len; - - m_free(n); -} - - -/* make m 'size' bytes large from m_data */ -void m_inc(struct mbuf *m, int size) -{ - int gapsize; - - /* some compilers throw up on gotos. This one we can fake. */ - if (M_ROOM(m) > size) { - return; - } - - if (m->m_flags & M_EXT) { - gapsize = m->m_data - m->m_ext; - m->m_ext = g_realloc(m->m_ext, size + gapsize); - } else { - gapsize = m->m_data - m->m_dat; - m->m_ext = g_malloc(size + gapsize); - memcpy(m->m_ext, m->m_dat, m->m_size); - m->m_flags |= M_EXT; - } - - m->m_data = m->m_ext + gapsize; - m->m_size = size + gapsize; -} - - -void m_adj(struct mbuf *m, int len) -{ - if (m == NULL) - return; - if (len >= 0) { - /* Trim from head */ - m->m_data += len; - m->m_len -= len; - } else { - /* Trim from tail */ - len = -len; - m->m_len -= len; - } -} - - -/* - * Copy len bytes from m, starting off bytes into n - */ -int m_copy(struct mbuf *n, struct mbuf *m, int off, int len) -{ - if (len > M_FREEROOM(n)) - return -1; - - memcpy((n->m_data + n->m_len), (m->m_data + off), len); - n->m_len += len; - return 0; -} - - -/* - * Given a pointer into an mbuf, return the mbuf - * XXX This is a kludge, I should eliminate the need for it - * Fortunately, it's not used often - */ -struct mbuf *dtom(Slirp *slirp, void *dat) -{ - struct mbuf *m; - - DEBUG_CALL("dtom"); - DEBUG_ARG("dat = %p", dat); - - /* bug corrected for M_EXT buffers */ - for (m = (struct mbuf *)slirp->m_usedlist.qh_link; - (struct quehead *)m != &slirp->m_usedlist; m = m->m_next) { - if (m->m_flags & M_EXT) { - if ((char *)dat >= m->m_ext && (char *)dat < (m->m_ext + m->m_size)) - return m; - } else { - if ((char *)dat >= m->m_dat && (char *)dat < (m->m_dat + m->m_size)) - return m; - } - } - - DEBUG_ERROR("dtom failed"); - - return (struct mbuf *)0; -} diff --git a/src/network/slirp/mbuf.h b/src/network/slirp/mbuf.h deleted file mode 100644 index 546e7852c..000000000 --- a/src/network/slirp/mbuf.h +++ /dev/null @@ -1,127 +0,0 @@ -/* SPDX-License-Identifier: BSD-3-Clause */ -/* - * Copyright (c) 1982, 1986, 1988, 1993 - * The Regents of the University of California. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. Neither the name of the University nor the names of its contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - * - * @(#)mbuf.h 8.3 (Berkeley) 1/21/94 - * mbuf.h,v 1.9 1994/11/14 13:54:20 bde Exp - */ - -#ifndef MBUF_H -#define MBUF_H - -/* - * Macros for type conversion - * mtod(m,t) - convert mbuf pointer to data pointer of correct type - */ -#define mtod(m, t) ((t)(m)->m_data) - -/* XXX About mbufs for slirp: - * Only one mbuf is ever used in a chain, for each "cell" of data. - * m_nextpkt points to the next packet, if fragmented. - * If the data is too large, the M_EXT is used, and a larger block - * is alloced. Therefore, m_free[m] must check for M_EXT and if set - * free the m_ext. This is inefficient memory-wise, but who cares. - */ - -/* - * mbufs allow to have a gap between the start of the allocated buffer (m_ext if - * M_EXT is set, m_dat otherwise) and the in-use data: - * - * |--gapsize----->|---m_len-------> - * |----------m_size------------------------------> - * |----M_ROOM--------------------> - * |-M_FREEROOM--> - * - * ^ ^ ^ - * m_dat/m_ext m_data end of buffer - */ - -/* - * How much room is in the mbuf, from m_data to the end of the mbuf - */ -#define M_ROOM(m) \ - ((m->m_flags & M_EXT) ? (((m)->m_ext + (m)->m_size) - (m)->m_data) : \ - (((m)->m_dat + (m)->m_size) - (m)->m_data)) - -/* - * How much free room there is - */ -#define M_FREEROOM(m) (M_ROOM(m) - (m)->m_len) - -struct mbuf { - /* XXX should union some of these! */ - /* header at beginning of each mbuf: */ - struct mbuf *m_next; /* Linked list of mbufs */ - struct mbuf *m_prev; - struct mbuf *m_nextpkt; /* Next packet in queue/record */ - struct mbuf *m_prevpkt; /* Flags aren't used in the output queue */ - int m_flags; /* Misc flags */ - - int m_size; /* Size of mbuf, from m_dat or m_ext */ - struct socket *m_so; - - char *m_data; /* Current location of data */ - int m_len; /* Amount of data in this mbuf, from m_data */ - - Slirp *slirp; - bool resolution_requested; - uint64_t expiration_date; - char *m_ext; - /* start of dynamic buffer area, must be last element */ - char m_dat[]; -}; - -#define ifq_prev m_prev -#define ifq_next m_next -#define ifs_prev m_prevpkt -#define ifs_next m_nextpkt -#define ifq_so m_so - -#define M_EXT 0x01 /* m_ext points to more (malloced) data */ -#define M_FREELIST 0x02 /* mbuf is on free list */ -#define M_USEDLIST 0x04 /* XXX mbuf is on used list (for dtom()) */ -#define M_DOFREE \ - 0x08 /* when m_free is called on the mbuf, free() \ - * it rather than putting it on the free list */ - -void m_init(Slirp *); -void m_cleanup(Slirp *slirp); -struct mbuf *m_get(Slirp *); -void m_free(struct mbuf *); -void m_cat(register struct mbuf *, register struct mbuf *); -void m_inc(struct mbuf *, int); -void m_adj(struct mbuf *, int); -int m_copy(struct mbuf *, struct mbuf *, int, int); -struct mbuf *dtom(Slirp *, void *); - -static inline void ifs_init(struct mbuf *ifm) -{ - ifm->ifs_next = ifm->ifs_prev = ifm; -} - -#endif diff --git a/src/network/slirp/misc.c b/src/network/slirp/misc.c deleted file mode 100644 index 3bea32ac1..000000000 --- a/src/network/slirp/misc.c +++ /dev/null @@ -1,397 +0,0 @@ -/* SPDX-License-Identifier: BSD-3-Clause */ -/* - * Copyright (c) 1995 Danny Gasparovski. - */ - -#include "slirp.h" -#include -#ifdef G_OS_UNIX -#include -#include -#ifdef BSD -#define g_strlcpy strlcpy -#else -extern gsize g_strlcpy(gchar* dest, const gchar* src, gsize dest_size); -#endif -#endif - -extern inline void insque(void *a, void *b) -{ - register struct quehead *element = (struct quehead *)a; - register struct quehead *head = (struct quehead *)b; - element->qh_link = head->qh_link; - head->qh_link = (struct quehead *)element; - element->qh_rlink = (struct quehead *)head; - ((struct quehead *)(element->qh_link))->qh_rlink = - (struct quehead *)element; -} - -extern inline void remque(void *a) -{ - register struct quehead *element = (struct quehead *)a; - ((struct quehead *)(element->qh_link))->qh_rlink = element->qh_rlink; - ((struct quehead *)(element->qh_rlink))->qh_link = element->qh_link; - element->qh_rlink = NULL; -} - -/* TODO: IPv6 */ -struct gfwd_list *add_guestfwd(struct gfwd_list **ex_ptr, SlirpWriteCb write_cb, - void *opaque, struct in_addr addr, int port) -{ - struct gfwd_list *f = g_new0(struct gfwd_list, 1); - - f->write_cb = write_cb; - f->opaque = opaque; - f->ex_fport = port; - f->ex_addr = addr; - f->ex_next = *ex_ptr; - *ex_ptr = f; - - return f; -} - -struct gfwd_list *add_exec(struct gfwd_list **ex_ptr, const char *cmdline, - struct in_addr addr, int port) -{ - struct gfwd_list *f = add_guestfwd(ex_ptr, NULL, NULL, addr, port); - - f->ex_exec = g_strdup(cmdline); - - return f; -} - -struct gfwd_list *add_unix(struct gfwd_list **ex_ptr, const char *unixsock, - struct in_addr addr, int port) -{ - struct gfwd_list *f = add_guestfwd(ex_ptr, NULL, NULL, addr, port); - - f->ex_unix = g_strdup(unixsock); - - return f; -} - -int remove_guestfwd(struct gfwd_list **ex_ptr, struct in_addr addr, int port) -{ - for (; *ex_ptr != NULL; ex_ptr = &((*ex_ptr)->ex_next)) { - struct gfwd_list *f = *ex_ptr; - if (f->ex_addr.s_addr == addr.s_addr && f->ex_fport == port) { - *ex_ptr = f->ex_next; - g_free(f->ex_exec); - g_free(f); - return 0; - } - } - return -1; -} - -static int slirp_socketpair_with_oob(int sv[2]) -{ - struct sockaddr_in addr = { - .sin_family = AF_INET, - .sin_port = 0, - .sin_addr.s_addr = INADDR_ANY, - }; - socklen_t addrlen = sizeof(addr); - int ret, s; - - sv[1] = -1; - s = slirp_socket(AF_INET, SOCK_STREAM, 0); - if (s < 0 || bind(s, (struct sockaddr *)&addr, addrlen) < 0 || - listen(s, 1) < 0 || - getsockname(s, (struct sockaddr *)&addr, &addrlen) < 0) { - goto err; - } - - sv[1] = slirp_socket(AF_INET, SOCK_STREAM, 0); - if (sv[1] < 0) { - goto err; - } - /* - * This connect won't block because we've already listen()ed on - * the server end (even though we won't accept() the connection - * until later on). - */ - do { - ret = connect(sv[1], (struct sockaddr *)&addr, addrlen); - } while (ret < 0 && errno == EINTR); - if (ret < 0) { - goto err; - } - - do { - sv[0] = accept(s, (struct sockaddr *)&addr, &addrlen); - } while (sv[0] < 0 && errno == EINTR); - if (sv[0] < 0) { - goto err; - } - - closesocket(s); - return 0; - -err: - g_critical("slirp_socketpair(): %s", strerror(errno)); - if (s >= 0) { - closesocket(s); - } - if (sv[1] >= 0) { - closesocket(sv[1]); - } - return -1; -} - -static void fork_exec_child_setup(gpointer data) -{ -#ifndef _WIN32 - setsid(); -#endif -} - -#pragma GCC diagnostic push -#pragma GCC diagnostic ignored "-Wdeprecated-declarations" - -#if !GLIB_CHECK_VERSION(2, 58, 0) -typedef struct SlirpGSpawnFds { - GSpawnChildSetupFunc child_setup; - gpointer user_data; - gint stdin_fd; - gint stdout_fd; - gint stderr_fd; -} SlirpGSpawnFds; - -static inline void slirp_gspawn_fds_setup(gpointer user_data) -{ - SlirpGSpawnFds *q = (SlirpGSpawnFds *)user_data; - - dup2(q->stdin_fd, 0); - dup2(q->stdout_fd, 1); - dup2(q->stderr_fd, 2); - q->child_setup(q->user_data); -} -#endif - -static inline gboolean -g_spawn_async_with_fds_slirp(const gchar *working_directory, gchar **argv, - gchar **envp, GSpawnFlags flags, - GSpawnChildSetupFunc child_setup, - gpointer user_data, GPid *child_pid, gint stdin_fd, - gint stdout_fd, gint stderr_fd, GError **error) -{ -#if GLIB_CHECK_VERSION(2, 58, 0) - return g_spawn_async_with_fds(working_directory, argv, envp, flags, - child_setup, user_data, child_pid, stdin_fd, - stdout_fd, stderr_fd, error); -#else - SlirpGSpawnFds setup = { - .child_setup = child_setup, - .user_data = user_data, - .stdin_fd = stdin_fd, - .stdout_fd = stdout_fd, - .stderr_fd = stderr_fd, - }; - - return g_spawn_async(working_directory, argv, envp, flags, - slirp_gspawn_fds_setup, &setup, child_pid, error); -#endif -} - -#define g_spawn_async_with_fds(wd, argv, env, f, c, d, p, ifd, ofd, efd, err) \ - g_spawn_async_with_fds_slirp(wd, argv, env, f, c, d, p, ifd, ofd, efd, err) - -#pragma GCC diagnostic pop - -int fork_exec(struct socket *so, const char *ex) -{ - GError *err = NULL; - gint argc = 0; - gchar **argv = NULL; - int opt, sp[2]; - - DEBUG_CALL("fork_exec"); - DEBUG_ARG("so = %p", so); - DEBUG_ARG("ex = %p", ex); - - if (slirp_socketpair_with_oob(sp) < 0) { - return 0; - } - - if (!g_shell_parse_argv(ex, &argc, &argv, &err)) { - g_critical("fork_exec invalid command: %s\nerror: %s", ex, err->message); - g_error_free(err); - return 0; - } - - g_spawn_async_with_fds(NULL /* cwd */, argv, NULL /* env */, - G_SPAWN_SEARCH_PATH, fork_exec_child_setup, - NULL /* data */, NULL /* child_pid */, sp[1], sp[1], - sp[1], &err); - g_strfreev(argv); - - if (err) { - g_critical("fork_exec: %s", err->message); - g_error_free(err); - closesocket(sp[0]); - closesocket(sp[1]); - return 0; - } - - so->s = sp[0]; - closesocket(sp[1]); - slirp_socket_set_fast_reuse(so->s); - opt = 1; - setsockopt(so->s, SOL_SOCKET, SO_OOBINLINE, &opt, sizeof(int)); - slirp_set_nonblock(so->s); - so->slirp->cb->register_poll_fd(so->s, so->slirp->opaque); - return 1; -} - -int open_unix(struct socket *so, const char *unixpath) -{ -#ifdef G_OS_UNIX - struct sockaddr_un sa; - int s; - - DEBUG_CALL("open_unix"); - DEBUG_ARG("so = %p", so); - DEBUG_ARG("unixpath = %s", unixpath); - - memset(&sa, 0, sizeof(sa)); - sa.sun_family = AF_UNIX; - if (g_strlcpy(sa.sun_path, unixpath, sizeof(sa.sun_path)) >= sizeof(sa.sun_path)) { - g_critical("Bad unix path: %s", unixpath); - return 0; - } - - s = slirp_socket(PF_UNIX, SOCK_STREAM, 0); - if (s < 0) { - g_critical("open_unix(): %s", strerror(errno)); - return 0; - } - - if (connect(s, (struct sockaddr *)&sa, sizeof(sa)) < 0) { - g_critical("open_unix(): %s", strerror(errno)); - closesocket(s); - return 0; - } - - so->s = s; - slirp_set_nonblock(so->s); - so->slirp->cb->register_poll_fd(so->s, so->slirp->opaque); - - return 1; -#else - g_assert_not_reached(); -#endif -} - -char *slirp_connection_info(Slirp *slirp) -{ - GString *str = g_string_new(NULL); - const char *const tcpstates[] = { - [TCPS_CLOSED] = "CLOSED", [TCPS_LISTEN] = "LISTEN", - [TCPS_SYN_SENT] = "SYN_SENT", [TCPS_SYN_RECEIVED] = "SYN_RCVD", - [TCPS_ESTABLISHED] = "ESTABLISHED", [TCPS_CLOSE_WAIT] = "CLOSE_WAIT", - [TCPS_FIN_WAIT_1] = "FIN_WAIT_1", [TCPS_CLOSING] = "CLOSING", - [TCPS_LAST_ACK] = "LAST_ACK", [TCPS_FIN_WAIT_2] = "FIN_WAIT_2", - [TCPS_TIME_WAIT] = "TIME_WAIT", - }; - struct in_addr dst_addr; - struct sockaddr_in src; - socklen_t src_len; - uint16_t dst_port; - struct socket *so; - const char *state; - char buf[20]; - - g_string_append_printf(str, - " Protocol[State] FD Source Address Port " - "Dest. Address Port RecvQ SendQ\n"); - - /* TODO: IPv6 */ - - for (so = slirp->tcb.so_next; so != &slirp->tcb; so = so->so_next) { - if (so->so_state & SS_HOSTFWD) { - state = "HOST_FORWARD"; - } else if (so->so_tcpcb) { - state = tcpstates[so->so_tcpcb->t_state]; - } else { - state = "NONE"; - } - if (so->so_state & (SS_HOSTFWD | SS_INCOMING)) { - src_len = sizeof(src); - getsockname(so->s, (struct sockaddr *)&src, &src_len); - dst_addr = so->so_laddr; - dst_port = so->so_lport; - } else { - src.sin_addr = so->so_laddr; - src.sin_port = so->so_lport; - dst_addr = so->so_faddr; - dst_port = so->so_fport; - } - slirp_fmt0(buf, sizeof(buf), " TCP[%s]", state); - g_string_append_printf(str, "%-19s %3d %15s %5d ", buf, so->s, - src.sin_addr.s_addr ? inet_ntoa(src.sin_addr) : - "*", - ntohs(src.sin_port)); - g_string_append_printf(str, "%15s %5d %5d %5d\n", inet_ntoa(dst_addr), - ntohs(dst_port), so->so_rcv.sb_cc, - so->so_snd.sb_cc); - } - - for (so = slirp->udb.so_next; so != &slirp->udb; so = so->so_next) { - if (so->so_state & SS_HOSTFWD) { - slirp_fmt0(buf, sizeof(buf), " UDP[HOST_FORWARD]"); - src_len = sizeof(src); - getsockname(so->s, (struct sockaddr *)&src, &src_len); - dst_addr = so->so_laddr; - dst_port = so->so_lport; - } else { - slirp_fmt0(buf, sizeof(buf), " UDP[%d sec]", - (so->so_expire - curtime) / 1000); - src.sin_addr = so->so_laddr; - src.sin_port = so->so_lport; - dst_addr = so->so_faddr; - dst_port = so->so_fport; - } - g_string_append_printf(str, "%-19s %3d %15s %5d ", buf, so->s, - src.sin_addr.s_addr ? inet_ntoa(src.sin_addr) : - "*", - ntohs(src.sin_port)); - g_string_append_printf(str, "%15s %5d %5d %5d\n", inet_ntoa(dst_addr), - ntohs(dst_port), so->so_rcv.sb_cc, - so->so_snd.sb_cc); - } - - for (so = slirp->icmp.so_next; so != &slirp->icmp; so = so->so_next) { - slirp_fmt0(buf, sizeof(buf), " ICMP[%d sec]", - (so->so_expire - curtime) / 1000); - src.sin_addr = so->so_laddr; - dst_addr = so->so_faddr; - g_string_append_printf(str, "%-19s %3d %15s - ", buf, so->s, - src.sin_addr.s_addr ? inet_ntoa(src.sin_addr) : - "*"); - g_string_append_printf(str, "%15s - %5d %5d\n", inet_ntoa(dst_addr), - so->so_rcv.sb_cc, so->so_snd.sb_cc); - } - - return g_string_free(str, false); -} - -int slirp_bind_outbound(struct socket *so, unsigned short af) -{ - int ret = 0; - struct sockaddr *addr = NULL; - int addr_size = 0; - - if (af == AF_INET && so->slirp->outbound_addr != NULL) { - addr = (struct sockaddr *)so->slirp->outbound_addr; - addr_size = sizeof(struct sockaddr_in); - } else if (af == AF_INET6 && so->slirp->outbound_addr6 != NULL) { - addr = (struct sockaddr *)so->slirp->outbound_addr6; - addr_size = sizeof(struct sockaddr_in6); - } - - if (addr != NULL) { - ret = bind(so->s, addr, addr_size); - } - return ret; -} diff --git a/src/network/slirp/misc.h b/src/network/slirp/misc.h deleted file mode 100644 index 81b370cfb..000000000 --- a/src/network/slirp/misc.h +++ /dev/null @@ -1,72 +0,0 @@ -/* SPDX-License-Identifier: BSD-3-Clause */ -/* - * Copyright (c) 1995 Danny Gasparovski. - */ - -#ifndef MISC_H -#define MISC_H - -#include "libslirp.h" - -struct gfwd_list { - SlirpWriteCb write_cb; - void *opaque; - struct in_addr ex_addr; /* Server address */ - int ex_fport; /* Port to telnet to */ - char *ex_exec; /* Command line of what to exec */ - char *ex_unix; /* unix socket */ - struct gfwd_list *ex_next; -}; - -#define EMU_NONE 0x0 - -/* TCP emulations */ -#define EMU_CTL 0x1 -#define EMU_FTP 0x2 -#define EMU_KSH 0x3 -#define EMU_IRC 0x4 -#define EMU_REALAUDIO 0x5 -#define EMU_RLOGIN 0x6 -#define EMU_IDENT 0x7 - -#define EMU_NOCONNECT 0x10 /* Don't connect */ - -struct tos_t { - uint16_t lport; - uint16_t fport; - uint8_t tos; - uint8_t emu; -}; - -struct emu_t { - uint16_t lport; - uint16_t fport; - uint8_t tos; - uint8_t emu; - struct emu_t *next; -}; - -struct slirp_quehead { - struct slirp_quehead *qh_link; - struct slirp_quehead *qh_rlink; -}; - -void slirp_insque(void *, void *); -void slirp_remque(void *); -int fork_exec(struct socket *so, const char *ex); -int open_unix(struct socket *so, const char *unixsock); - -struct gfwd_list *add_guestfwd(struct gfwd_list **ex_ptr, SlirpWriteCb write_cb, - void *opaque, struct in_addr addr, int port); - -struct gfwd_list *add_exec(struct gfwd_list **ex_ptr, const char *cmdline, - struct in_addr addr, int port); - -struct gfwd_list *add_unix(struct gfwd_list **ex_ptr, const char *unixsock, - struct in_addr addr, int port); - -int remove_guestfwd(struct gfwd_list **ex_ptr, struct in_addr addr, int port); - -int slirp_bind_outbound(struct socket *so, unsigned short af); - -#endif diff --git a/src/network/slirp/ncsi-pkt.h b/src/network/slirp/ncsi-pkt.h deleted file mode 100644 index 7795ad83e..000000000 --- a/src/network/slirp/ncsi-pkt.h +++ /dev/null @@ -1,445 +0,0 @@ -/* SPDX-License-Identifier: BSD-3-Clause */ -/* - * Copyright Gavin Shan, IBM Corporation 2016. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * 1. Redistributions of source code must retain the above - * copyright notice, this list of conditions and the following - * disclaimer. - * - * 2. Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following - * disclaimer in the documentation and/or other materials provided - * with the distribution. - * - * 3. Neither the name of the copyright holder nor the names of its - * contributors may be used to endorse or promote products derived - * from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS - * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE - * COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, - * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES - * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR - * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, - * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED - * OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#ifndef NCSI_PKT_H -#define NCSI_PKT_H - -/* from linux/net/ncsi/ncsi-pkt.h */ -#define __be32 uint32_t -#define __be16 uint16_t - -struct ncsi_pkt_hdr { - unsigned char mc_id; /* Management controller ID */ - unsigned char revision; /* NCSI version - 0x01 */ - unsigned char reserved; /* Reserved */ - unsigned char id; /* Packet sequence number */ - unsigned char type; /* Packet type */ - unsigned char channel; /* Network controller ID */ - __be16 length; /* Payload length */ - __be32 reserved1[2]; /* Reserved */ -}; - -struct ncsi_cmd_pkt_hdr { - struct ncsi_pkt_hdr common; /* Common NCSI packet header */ -}; - -struct ncsi_rsp_pkt_hdr { - struct ncsi_pkt_hdr common; /* Common NCSI packet header */ - __be16 code; /* Response code */ - __be16 reason; /* Response reason */ -}; - -struct ncsi_aen_pkt_hdr { - struct ncsi_pkt_hdr common; /* Common NCSI packet header */ - unsigned char reserved2[3]; /* Reserved */ - unsigned char type; /* AEN packet type */ -}; - -/* NCSI common command packet */ -struct ncsi_cmd_pkt { - struct ncsi_cmd_pkt_hdr cmd; /* Command header */ - __be32 checksum; /* Checksum */ - unsigned char pad[26]; -}; - -struct ncsi_rsp_pkt { - struct ncsi_rsp_pkt_hdr rsp; /* Response header */ - __be32 checksum; /* Checksum */ - unsigned char pad[22]; -}; - -/* Select Package */ -struct ncsi_cmd_sp_pkt { - struct ncsi_cmd_pkt_hdr cmd; /* Command header */ - unsigned char reserved[3]; /* Reserved */ - unsigned char hw_arbitration; /* HW arbitration */ - __be32 checksum; /* Checksum */ - unsigned char pad[22]; -}; - -/* Disable Channel */ -struct ncsi_cmd_dc_pkt { - struct ncsi_cmd_pkt_hdr cmd; /* Command header */ - unsigned char reserved[3]; /* Reserved */ - unsigned char ald; /* Allow link down */ - __be32 checksum; /* Checksum */ - unsigned char pad[22]; -}; - -/* Reset Channel */ -struct ncsi_cmd_rc_pkt { - struct ncsi_cmd_pkt_hdr cmd; /* Command header */ - __be32 reserved; /* Reserved */ - __be32 checksum; /* Checksum */ - unsigned char pad[22]; -}; - -/* AEN Enable */ -struct ncsi_cmd_ae_pkt { - struct ncsi_cmd_pkt_hdr cmd; /* Command header */ - unsigned char reserved[3]; /* Reserved */ - unsigned char mc_id; /* MC ID */ - __be32 mode; /* AEN working mode */ - __be32 checksum; /* Checksum */ - unsigned char pad[18]; -}; - -/* Set Link */ -struct ncsi_cmd_sl_pkt { - struct ncsi_cmd_pkt_hdr cmd; /* Command header */ - __be32 mode; /* Link working mode */ - __be32 oem_mode; /* OEM link mode */ - __be32 checksum; /* Checksum */ - unsigned char pad[18]; -}; - -/* Set VLAN Filter */ -struct ncsi_cmd_svf_pkt { - struct ncsi_cmd_pkt_hdr cmd; /* Command header */ - __be16 reserved; /* Reserved */ - __be16 vlan; /* VLAN ID */ - __be16 reserved1; /* Reserved */ - unsigned char index; /* VLAN table index */ - unsigned char enable; /* Enable or disable */ - __be32 checksum; /* Checksum */ - unsigned char pad[14]; -}; - -/* Enable VLAN */ -struct ncsi_cmd_ev_pkt { - struct ncsi_cmd_pkt_hdr cmd; /* Command header */ - unsigned char reserved[3]; /* Reserved */ - unsigned char mode; /* VLAN filter mode */ - __be32 checksum; /* Checksum */ - unsigned char pad[22]; -}; - -/* Set MAC Address */ -struct ncsi_cmd_sma_pkt { - struct ncsi_cmd_pkt_hdr cmd; /* Command header */ - unsigned char mac[6]; /* MAC address */ - unsigned char index; /* MAC table index */ - unsigned char at_e; /* Addr type and operation */ - __be32 checksum; /* Checksum */ - unsigned char pad[18]; -}; - -/* Enable Broadcast Filter */ -struct ncsi_cmd_ebf_pkt { - struct ncsi_cmd_pkt_hdr cmd; /* Command header */ - __be32 mode; /* Filter mode */ - __be32 checksum; /* Checksum */ - unsigned char pad[22]; -}; - -/* Enable Global Multicast Filter */ -struct ncsi_cmd_egmf_pkt { - struct ncsi_cmd_pkt_hdr cmd; /* Command header */ - __be32 mode; /* Global MC mode */ - __be32 checksum; /* Checksum */ - unsigned char pad[22]; -}; - -/* Set NCSI Flow Control */ -struct ncsi_cmd_snfc_pkt { - struct ncsi_cmd_pkt_hdr cmd; /* Command header */ - unsigned char reserved[3]; /* Reserved */ - unsigned char mode; /* Flow control mode */ - __be32 checksum; /* Checksum */ - unsigned char pad[22]; -}; - -/* Get Link Status */ -struct ncsi_rsp_gls_pkt { - struct ncsi_rsp_pkt_hdr rsp; /* Response header */ - __be32 status; /* Link status */ - __be32 other; /* Other indications */ - __be32 oem_status; /* OEM link status */ - __be32 checksum; - unsigned char pad[10]; -}; - -/* Get Version ID */ -struct ncsi_rsp_gvi_pkt { - struct ncsi_rsp_pkt_hdr rsp; /* Response header */ - __be32 ncsi_version; /* NCSI version */ - unsigned char reserved[3]; /* Reserved */ - unsigned char alpha2; /* NCSI version */ - unsigned char fw_name[12]; /* f/w name string */ - __be32 fw_version; /* f/w version */ - __be16 pci_ids[4]; /* PCI IDs */ - __be32 mf_id; /* Manufacture ID */ - __be32 checksum; -}; - -/* Get Capabilities */ -struct ncsi_rsp_gc_pkt { - struct ncsi_rsp_pkt_hdr rsp; /* Response header */ - __be32 cap; /* Capabilities */ - __be32 bc_cap; /* Broadcast cap */ - __be32 mc_cap; /* Multicast cap */ - __be32 buf_cap; /* Buffering cap */ - __be32 aen_cap; /* AEN cap */ - unsigned char vlan_cnt; /* VLAN filter count */ - unsigned char mixed_cnt; /* Mix filter count */ - unsigned char mc_cnt; /* MC filter count */ - unsigned char uc_cnt; /* UC filter count */ - unsigned char reserved[2]; /* Reserved */ - unsigned char vlan_mode; /* VLAN mode */ - unsigned char channel_cnt; /* Channel count */ - __be32 checksum; /* Checksum */ -}; - -/* Get Parameters */ -struct ncsi_rsp_gp_pkt { - struct ncsi_rsp_pkt_hdr rsp; /* Response header */ - unsigned char mac_cnt; /* Number of MAC addr */ - unsigned char reserved[2]; /* Reserved */ - unsigned char mac_enable; /* MAC addr enable flags */ - unsigned char vlan_cnt; /* VLAN tag count */ - unsigned char reserved1; /* Reserved */ - __be16 vlan_enable; /* VLAN tag enable flags */ - __be32 link_mode; /* Link setting */ - __be32 bc_mode; /* BC filter mode */ - __be32 valid_modes; /* Valid mode parameters */ - unsigned char vlan_mode; /* VLAN mode */ - unsigned char fc_mode; /* Flow control mode */ - unsigned char reserved2[2]; /* Reserved */ - __be32 aen_mode; /* AEN mode */ - unsigned char mac[6]; /* Supported MAC addr */ - __be16 vlan; /* Supported VLAN tags */ - __be32 checksum; /* Checksum */ -}; - -/* Get Controller Packet Statistics */ -struct ncsi_rsp_gcps_pkt { - struct ncsi_rsp_pkt_hdr rsp; /* Response header */ - __be32 cnt_hi; /* Counter cleared */ - __be32 cnt_lo; /* Counter cleared */ - __be32 rx_bytes; /* Rx bytes */ - __be32 tx_bytes; /* Tx bytes */ - __be32 rx_uc_pkts; /* Rx UC packets */ - __be32 rx_mc_pkts; /* Rx MC packets */ - __be32 rx_bc_pkts; /* Rx BC packets */ - __be32 tx_uc_pkts; /* Tx UC packets */ - __be32 tx_mc_pkts; /* Tx MC packets */ - __be32 tx_bc_pkts; /* Tx BC packets */ - __be32 fcs_err; /* FCS errors */ - __be32 align_err; /* Alignment errors */ - __be32 false_carrier; /* False carrier detection */ - __be32 runt_pkts; /* Rx runt packets */ - __be32 jabber_pkts; /* Rx jabber packets */ - __be32 rx_pause_xon; /* Rx pause XON frames */ - __be32 rx_pause_xoff; /* Rx XOFF frames */ - __be32 tx_pause_xon; /* Tx XON frames */ - __be32 tx_pause_xoff; /* Tx XOFF frames */ - __be32 tx_s_collision; /* Single collision frames */ - __be32 tx_m_collision; /* Multiple collision frames */ - __be32 l_collision; /* Late collision frames */ - __be32 e_collision; /* Excessive collision frames */ - __be32 rx_ctl_frames; /* Rx control frames */ - __be32 rx_64_frames; /* Rx 64-bytes frames */ - __be32 rx_127_frames; /* Rx 65-127 bytes frames */ - __be32 rx_255_frames; /* Rx 128-255 bytes frames */ - __be32 rx_511_frames; /* Rx 256-511 bytes frames */ - __be32 rx_1023_frames; /* Rx 512-1023 bytes frames */ - __be32 rx_1522_frames; /* Rx 1024-1522 bytes frames */ - __be32 rx_9022_frames; /* Rx 1523-9022 bytes frames */ - __be32 tx_64_frames; /* Tx 64-bytes frames */ - __be32 tx_127_frames; /* Tx 65-127 bytes frames */ - __be32 tx_255_frames; /* Tx 128-255 bytes frames */ - __be32 tx_511_frames; /* Tx 256-511 bytes frames */ - __be32 tx_1023_frames; /* Tx 512-1023 bytes frames */ - __be32 tx_1522_frames; /* Tx 1024-1522 bytes frames */ - __be32 tx_9022_frames; /* Tx 1523-9022 bytes frames */ - __be32 rx_valid_bytes; /* Rx valid bytes */ - __be32 rx_runt_pkts; /* Rx error runt packets */ - __be32 rx_jabber_pkts; /* Rx error jabber packets */ - __be32 checksum; /* Checksum */ -}; - -/* Get NCSI Statistics */ -struct ncsi_rsp_gns_pkt { - struct ncsi_rsp_pkt_hdr rsp; /* Response header */ - __be32 rx_cmds; /* Rx NCSI commands */ - __be32 dropped_cmds; /* Dropped commands */ - __be32 cmd_type_errs; /* Command type errors */ - __be32 cmd_csum_errs; /* Command checksum errors */ - __be32 rx_pkts; /* Rx NCSI packets */ - __be32 tx_pkts; /* Tx NCSI packets */ - __be32 tx_aen_pkts; /* Tx AEN packets */ - __be32 checksum; /* Checksum */ -}; - -/* Get NCSI Pass-through Statistics */ -struct ncsi_rsp_gnpts_pkt { - struct ncsi_rsp_pkt_hdr rsp; /* Response header */ - __be32 tx_pkts; /* Tx packets */ - __be32 tx_dropped; /* Tx dropped packets */ - __be32 tx_channel_err; /* Tx channel errors */ - __be32 tx_us_err; /* Tx undersize errors */ - __be32 rx_pkts; /* Rx packets */ - __be32 rx_dropped; /* Rx dropped packets */ - __be32 rx_channel_err; /* Rx channel errors */ - __be32 rx_us_err; /* Rx undersize errors */ - __be32 rx_os_err; /* Rx oversize errors */ - __be32 checksum; /* Checksum */ -}; - -/* Get package status */ -struct ncsi_rsp_gps_pkt { - struct ncsi_rsp_pkt_hdr rsp; /* Response header */ - __be32 status; /* Hardware arbitration status */ - __be32 checksum; -}; - -/* Get package UUID */ -struct ncsi_rsp_gpuuid_pkt { - struct ncsi_rsp_pkt_hdr rsp; /* Response header */ - unsigned char uuid[16]; /* UUID */ - __be32 checksum; -}; - -/* AEN: Link State Change */ -struct ncsi_aen_lsc_pkt { - struct ncsi_aen_pkt_hdr aen; /* AEN header */ - __be32 status; /* Link status */ - __be32 oem_status; /* OEM link status */ - __be32 checksum; /* Checksum */ - unsigned char pad[14]; -}; - -/* AEN: Configuration Required */ -struct ncsi_aen_cr_pkt { - struct ncsi_aen_pkt_hdr aen; /* AEN header */ - __be32 checksum; /* Checksum */ - unsigned char pad[22]; -}; - -/* AEN: Host Network Controller Driver Status Change */ -struct ncsi_aen_hncdsc_pkt { - struct ncsi_aen_pkt_hdr aen; /* AEN header */ - __be32 status; /* Status */ - __be32 checksum; /* Checksum */ - unsigned char pad[18]; -}; - -/* NCSI packet revision */ -#define NCSI_PKT_REVISION 0x01 - -/* NCSI packet commands */ -#define NCSI_PKT_CMD_CIS 0x00 /* Clear Initial State */ -#define NCSI_PKT_CMD_SP 0x01 /* Select Package */ -#define NCSI_PKT_CMD_DP 0x02 /* Deselect Package */ -#define NCSI_PKT_CMD_EC 0x03 /* Enable Channel */ -#define NCSI_PKT_CMD_DC 0x04 /* Disable Channel */ -#define NCSI_PKT_CMD_RC 0x05 /* Reset Channel */ -#define NCSI_PKT_CMD_ECNT 0x06 /* Enable Channel Network Tx */ -#define NCSI_PKT_CMD_DCNT 0x07 /* Disable Channel Network Tx */ -#define NCSI_PKT_CMD_AE 0x08 /* AEN Enable */ -#define NCSI_PKT_CMD_SL 0x09 /* Set Link */ -#define NCSI_PKT_CMD_GLS 0x0a /* Get Link */ -#define NCSI_PKT_CMD_SVF 0x0b /* Set VLAN Filter */ -#define NCSI_PKT_CMD_EV 0x0c /* Enable VLAN */ -#define NCSI_PKT_CMD_DV 0x0d /* Disable VLAN */ -#define NCSI_PKT_CMD_SMA 0x0e /* Set MAC address */ -#define NCSI_PKT_CMD_EBF 0x10 /* Enable Broadcast Filter */ -#define NCSI_PKT_CMD_DBF 0x11 /* Disable Broadcast Filter */ -#define NCSI_PKT_CMD_EGMF 0x12 /* Enable Global Multicast Filter */ -#define NCSI_PKT_CMD_DGMF 0x13 /* Disable Global Multicast Filter */ -#define NCSI_PKT_CMD_SNFC 0x14 /* Set NCSI Flow Control */ -#define NCSI_PKT_CMD_GVI 0x15 /* Get Version ID */ -#define NCSI_PKT_CMD_GC 0x16 /* Get Capabilities */ -#define NCSI_PKT_CMD_GP 0x17 /* Get Parameters */ -#define NCSI_PKT_CMD_GCPS 0x18 /* Get Controller Packet Statistics */ -#define NCSI_PKT_CMD_GNS 0x19 /* Get NCSI Statistics */ -#define NCSI_PKT_CMD_GNPTS 0x1a /* Get NCSI Pass-throu Statistics */ -#define NCSI_PKT_CMD_GPS 0x1b /* Get package status */ -#define NCSI_PKT_CMD_OEM 0x50 /* OEM */ -#define NCSI_PKT_CMD_PLDM 0x51 /* PLDM request over NCSI over RBT */ -#define NCSI_PKT_CMD_GPUUID 0x52 /* Get package UUID */ - -/* NCSI packet responses */ -#define NCSI_PKT_RSP_CIS (NCSI_PKT_CMD_CIS + 0x80) -#define NCSI_PKT_RSP_SP (NCSI_PKT_CMD_SP + 0x80) -#define NCSI_PKT_RSP_DP (NCSI_PKT_CMD_DP + 0x80) -#define NCSI_PKT_RSP_EC (NCSI_PKT_CMD_EC + 0x80) -#define NCSI_PKT_RSP_DC (NCSI_PKT_CMD_DC + 0x80) -#define NCSI_PKT_RSP_RC (NCSI_PKT_CMD_RC + 0x80) -#define NCSI_PKT_RSP_ECNT (NCSI_PKT_CMD_ECNT + 0x80) -#define NCSI_PKT_RSP_DCNT (NCSI_PKT_CMD_DCNT + 0x80) -#define NCSI_PKT_RSP_AE (NCSI_PKT_CMD_AE + 0x80) -#define NCSI_PKT_RSP_SL (NCSI_PKT_CMD_SL + 0x80) -#define NCSI_PKT_RSP_GLS (NCSI_PKT_CMD_GLS + 0x80) -#define NCSI_PKT_RSP_SVF (NCSI_PKT_CMD_SVF + 0x80) -#define NCSI_PKT_RSP_EV (NCSI_PKT_CMD_EV + 0x80) -#define NCSI_PKT_RSP_DV (NCSI_PKT_CMD_DV + 0x80) -#define NCSI_PKT_RSP_SMA (NCSI_PKT_CMD_SMA + 0x80) -#define NCSI_PKT_RSP_EBF (NCSI_PKT_CMD_EBF + 0x80) -#define NCSI_PKT_RSP_DBF (NCSI_PKT_CMD_DBF + 0x80) -#define NCSI_PKT_RSP_EGMF (NCSI_PKT_CMD_EGMF + 0x80) -#define NCSI_PKT_RSP_DGMF (NCSI_PKT_CMD_DGMF + 0x80) -#define NCSI_PKT_RSP_SNFC (NCSI_PKT_CMD_SNFC + 0x80) -#define NCSI_PKT_RSP_GVI (NCSI_PKT_CMD_GVI + 0x80) -#define NCSI_PKT_RSP_GC (NCSI_PKT_CMD_GC + 0x80) -#define NCSI_PKT_RSP_GP (NCSI_PKT_CMD_GP + 0x80) -#define NCSI_PKT_RSP_GCPS (NCSI_PKT_CMD_GCPS + 0x80) -#define NCSI_PKT_RSP_GNS (NCSI_PKT_CMD_GNS + 0x80) -#define NCSI_PKT_RSP_GNPTS (NCSI_PKT_CMD_GNPTS + 0x80) -#define NCSI_PKT_RSP_GPS (NCSI_PKT_CMD_GPS + 0x80) -#define NCSI_PKT_RSP_OEM (NCSI_PKT_CMD_OEM + 0x80) -#define NCSI_PKT_RSP_PLDM (NCSI_PKT_CMD_PLDM + 0x80) -#define NCSI_PKT_RSP_GPUUID (NCSI_PKT_CMD_GPUUID + 0x80) - -/* NCSI response code/reason */ -#define NCSI_PKT_RSP_C_COMPLETED 0x0000 /* Command Completed */ -#define NCSI_PKT_RSP_C_FAILED 0x0001 /* Command Failed */ -#define NCSI_PKT_RSP_C_UNAVAILABLE 0x0002 /* Command Unavailable */ -#define NCSI_PKT_RSP_C_UNSUPPORTED 0x0003 /* Command Unsupported */ -#define NCSI_PKT_RSP_R_NO_ERROR 0x0000 /* No Error */ -#define NCSI_PKT_RSP_R_INTERFACE 0x0001 /* Interface not ready */ -#define NCSI_PKT_RSP_R_PARAM 0x0002 /* Invalid Parameter */ -#define NCSI_PKT_RSP_R_CHANNEL 0x0003 /* Channel not Ready */ -#define NCSI_PKT_RSP_R_PACKAGE 0x0004 /* Package not Ready */ -#define NCSI_PKT_RSP_R_LENGTH 0x0005 /* Invalid payload length */ -#define NCSI_PKT_RSP_R_UNKNOWN 0x7fff /* Command type unsupported */ - -/* NCSI AEN packet type */ -#define NCSI_PKT_AEN 0xFF /* AEN Packet */ -#define NCSI_PKT_AEN_LSC 0x00 /* Link status change */ -#define NCSI_PKT_AEN_CR 0x01 /* Configuration required */ -#define NCSI_PKT_AEN_HNCDSC 0x02 /* HNC driver status change */ - -#endif /* NCSI_PKT_H */ diff --git a/src/network/slirp/ncsi.c b/src/network/slirp/ncsi.c deleted file mode 100644 index 3c1dfef1f..000000000 --- a/src/network/slirp/ncsi.c +++ /dev/null @@ -1,193 +0,0 @@ -/* SPDX-License-Identifier: BSD-3-Clause */ -/* - * NC-SI (Network Controller Sideband Interface) "echo" model - * - * Copyright (C) 2016-2018 IBM Corp. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * 1. Redistributions of source code must retain the above - * copyright notice, this list of conditions and the following - * disclaimer. - * - * 2. Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following - * disclaimer in the documentation and/or other materials provided - * with the distribution. - * - * 3. Neither the name of the copyright holder nor the names of its - * contributors may be used to endorse or promote products derived - * from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS - * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE - * COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, - * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES - * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR - * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, - * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED - * OF THE POSSIBILITY OF SUCH DAMAGE. - */ -#include "slirp.h" - -#include "ncsi-pkt.h" - -static uint32_t ncsi_calculate_checksum(uint16_t *data, int len) -{ - uint32_t checksum = 0; - int i; - - /* - * 32-bit unsigned sum of the NC-SI packet header and NC-SI packet - * payload interpreted as a series of 16-bit unsigned integer values. - */ - for (i = 0; i < len / 2; i++) { - checksum += htons(data[i]); - } - - checksum = (~checksum + 1); - return checksum; -} - -/* Get Capabilities */ -static int ncsi_rsp_handler_gc(struct ncsi_rsp_pkt_hdr *rnh) -{ - struct ncsi_rsp_gc_pkt *rsp = (struct ncsi_rsp_gc_pkt *)rnh; - - rsp->cap = htonl(~0); - rsp->bc_cap = htonl(~0); - rsp->mc_cap = htonl(~0); - rsp->buf_cap = htonl(~0); - rsp->aen_cap = htonl(~0); - rsp->vlan_mode = 0xff; - rsp->uc_cnt = 2; - return 0; -} - -/* Get Link status */ -static int ncsi_rsp_handler_gls(struct ncsi_rsp_pkt_hdr *rnh) -{ - struct ncsi_rsp_gls_pkt *rsp = (struct ncsi_rsp_gls_pkt *)rnh; - - rsp->status = htonl(0x1); - return 0; -} - -/* Get Parameters */ -static int ncsi_rsp_handler_gp(struct ncsi_rsp_pkt_hdr *rnh) -{ - struct ncsi_rsp_gp_pkt *rsp = (struct ncsi_rsp_gp_pkt *)rnh; - - /* no MAC address filters or VLAN filters on the channel */ - rsp->mac_cnt = 0; - rsp->mac_enable = 0; - rsp->vlan_cnt = 0; - rsp->vlan_enable = 0; - - return 0; -} - -static const struct ncsi_rsp_handler { - unsigned char type; - int payload; - int (*handler)(struct ncsi_rsp_pkt_hdr *rnh); -} ncsi_rsp_handlers[] = { { NCSI_PKT_RSP_CIS, 4, NULL }, - { NCSI_PKT_RSP_SP, 4, NULL }, - { NCSI_PKT_RSP_DP, 4, NULL }, - { NCSI_PKT_RSP_EC, 4, NULL }, - { NCSI_PKT_RSP_DC, 4, NULL }, - { NCSI_PKT_RSP_RC, 4, NULL }, - { NCSI_PKT_RSP_ECNT, 4, NULL }, - { NCSI_PKT_RSP_DCNT, 4, NULL }, - { NCSI_PKT_RSP_AE, 4, NULL }, - { NCSI_PKT_RSP_SL, 4, NULL }, - { NCSI_PKT_RSP_GLS, 16, ncsi_rsp_handler_gls }, - { NCSI_PKT_RSP_SVF, 4, NULL }, - { NCSI_PKT_RSP_EV, 4, NULL }, - { NCSI_PKT_RSP_DV, 4, NULL }, - { NCSI_PKT_RSP_SMA, 4, NULL }, - { NCSI_PKT_RSP_EBF, 4, NULL }, - { NCSI_PKT_RSP_DBF, 4, NULL }, - { NCSI_PKT_RSP_EGMF, 4, NULL }, - { NCSI_PKT_RSP_DGMF, 4, NULL }, - { NCSI_PKT_RSP_SNFC, 4, NULL }, - { NCSI_PKT_RSP_GVI, 40, NULL }, - { NCSI_PKT_RSP_GC, 32, ncsi_rsp_handler_gc }, - { NCSI_PKT_RSP_GP, 40, ncsi_rsp_handler_gp }, - { NCSI_PKT_RSP_GCPS, 172, NULL }, - { NCSI_PKT_RSP_GNS, 172, NULL }, - { NCSI_PKT_RSP_GNPTS, 172, NULL }, - { NCSI_PKT_RSP_GPS, 8, NULL }, - { NCSI_PKT_RSP_OEM, 0, NULL }, - { NCSI_PKT_RSP_PLDM, 0, NULL }, - { NCSI_PKT_RSP_GPUUID, 20, NULL } }; - -/* - * packet format : ncsi header + payload + checksum - */ -#define NCSI_MAX_PAYLOAD 172 -#define NCSI_MAX_LEN (sizeof(struct ncsi_pkt_hdr) + NCSI_MAX_PAYLOAD + 4) - -void ncsi_input(Slirp *slirp, const uint8_t *pkt, int pkt_len) -{ - const struct ncsi_pkt_hdr *nh = - (const struct ncsi_pkt_hdr *)(pkt + ETH_HLEN); - uint8_t ncsi_reply[ETH_HLEN + NCSI_MAX_LEN]; - struct ethhdr *reh = (struct ethhdr *)ncsi_reply; - struct ncsi_rsp_pkt_hdr *rnh = - (struct ncsi_rsp_pkt_hdr *)(ncsi_reply + ETH_HLEN); - const struct ncsi_rsp_handler *handler = NULL; - int i; - int ncsi_rsp_len = sizeof(*nh); - uint32_t checksum; - uint32_t *pchecksum; - - memset(ncsi_reply, 0, sizeof(ncsi_reply)); - - memset(reh->h_dest, 0xff, ETH_ALEN); - memset(reh->h_source, 0xff, ETH_ALEN); - reh->h_proto = htons(ETH_P_NCSI); - - for (i = 0; i < G_N_ELEMENTS(ncsi_rsp_handlers); i++) { - if (ncsi_rsp_handlers[i].type == nh->type + 0x80) { - handler = &ncsi_rsp_handlers[i]; - break; - } - } - - rnh->common.mc_id = nh->mc_id; - rnh->common.revision = NCSI_PKT_REVISION; - rnh->common.id = nh->id; - rnh->common.type = nh->type + 0x80; - rnh->common.channel = nh->channel; - - if (handler) { - rnh->common.length = htons(handler->payload); - rnh->code = htons(NCSI_PKT_RSP_C_COMPLETED); - rnh->reason = htons(NCSI_PKT_RSP_R_NO_ERROR); - - if (handler->handler) { - /* TODO: handle errors */ - handler->handler(rnh); - } - ncsi_rsp_len += handler->payload; - } else { - rnh->common.length = 0; - rnh->code = htons(NCSI_PKT_RSP_C_UNAVAILABLE); - rnh->reason = htons(NCSI_PKT_RSP_R_UNKNOWN); - } - - /* Add the optional checksum at the end of the frame. */ - checksum = ncsi_calculate_checksum((uint16_t *)rnh, ncsi_rsp_len); - pchecksum = (uint32_t *)((void *)rnh + ncsi_rsp_len); - *pchecksum = htonl(checksum); - ncsi_rsp_len += 4; - - slirp_send_packet_all(slirp, ncsi_reply, ETH_HLEN + ncsi_rsp_len); -} diff --git a/src/network/slirp/ndp_table.c b/src/network/slirp/ndp_table.c deleted file mode 100644 index 110d6ea0e..000000000 --- a/src/network/slirp/ndp_table.c +++ /dev/null @@ -1,87 +0,0 @@ -/* SPDX-License-Identifier: BSD-3-Clause */ -/* - * Copyright (c) 2013 - * Guillaume Subiron, Yann Bordenave, Serigne Modou Wagne. - */ - -#include "slirp.h" - -void ndp_table_add(Slirp *slirp, struct in6_addr ip_addr, - uint8_t ethaddr[ETH_ALEN]) -{ - char addrstr[INET6_ADDRSTRLEN]; - NdpTable *ndp_table = &slirp->ndp_table; - int i; - - inet_ntop(AF_INET6, &(ip_addr), addrstr, INET6_ADDRSTRLEN); - - DEBUG_CALL("ndp_table_add"); - DEBUG_ARG("ip = %s", addrstr); - DEBUG_ARG("hw addr = %02x:%02x:%02x:%02x:%02x:%02x", ethaddr[0], ethaddr[1], - ethaddr[2], ethaddr[3], ethaddr[4], ethaddr[5]); - - if (IN6_IS_ADDR_MULTICAST(&ip_addr) || in6_zero(&ip_addr)) { - /* Do not register multicast or unspecified addresses */ - DEBUG_CALL(" abort: do not register multicast or unspecified address"); - return; - } - - /* Search for an entry */ - for (i = 0; i < NDP_TABLE_SIZE; i++) { - if (in6_equal(&ndp_table->table[i].ip_addr, &ip_addr)) { - DEBUG_CALL(" already in table: update the entry"); - /* Update the entry */ - memcpy(ndp_table->table[i].eth_addr, ethaddr, ETH_ALEN); - return; - } - } - - /* No entry found, create a new one */ - DEBUG_CALL(" create new entry"); - ndp_table->table[ndp_table->next_victim].ip_addr = ip_addr; - memcpy(ndp_table->table[ndp_table->next_victim].eth_addr, ethaddr, - ETH_ALEN); - ndp_table->next_victim = (ndp_table->next_victim + 1) % NDP_TABLE_SIZE; -} - -bool ndp_table_search(Slirp *slirp, struct in6_addr ip_addr, - uint8_t out_ethaddr[ETH_ALEN]) -{ - char addrstr[INET6_ADDRSTRLEN]; - NdpTable *ndp_table = &slirp->ndp_table; - int i; - - inet_ntop(AF_INET6, &(ip_addr), addrstr, INET6_ADDRSTRLEN); - - DEBUG_CALL("ndp_table_search"); - DEBUG_ARG("ip = %s", addrstr); - - assert(!in6_zero(&ip_addr)); - - /* Multicast address: fec0::abcd:efgh/8 -> 33:33:ab:cd:ef:gh */ - if (IN6_IS_ADDR_MULTICAST(&ip_addr)) { - out_ethaddr[0] = 0x33; - out_ethaddr[1] = 0x33; - out_ethaddr[2] = ip_addr.s6_addr[12]; - out_ethaddr[3] = ip_addr.s6_addr[13]; - out_ethaddr[4] = ip_addr.s6_addr[14]; - out_ethaddr[5] = ip_addr.s6_addr[15]; - DEBUG_ARG("multicast addr = %02x:%02x:%02x:%02x:%02x:%02x", - out_ethaddr[0], out_ethaddr[1], out_ethaddr[2], - out_ethaddr[3], out_ethaddr[4], out_ethaddr[5]); - return 1; - } - - for (i = 0; i < NDP_TABLE_SIZE; i++) { - if (in6_equal(&ndp_table->table[i].ip_addr, &ip_addr)) { - memcpy(out_ethaddr, ndp_table->table[i].eth_addr, ETH_ALEN); - DEBUG_ARG("found hw addr = %02x:%02x:%02x:%02x:%02x:%02x", - out_ethaddr[0], out_ethaddr[1], out_ethaddr[2], - out_ethaddr[3], out_ethaddr[4], out_ethaddr[5]); - return 1; - } - } - - DEBUG_CALL(" ip not found in table"); - return 0; -} diff --git a/src/network/slirp/sbuf.c b/src/network/slirp/sbuf.c deleted file mode 100644 index 2fb917614..000000000 --- a/src/network/slirp/sbuf.c +++ /dev/null @@ -1,168 +0,0 @@ -/* SPDX-License-Identifier: BSD-3-Clause */ -/* - * Copyright (c) 1995 Danny Gasparovski. - */ - -#include "slirp.h" - -static void sbappendsb(struct sbuf *sb, struct mbuf *m); - -void sbfree(struct sbuf *sb) -{ - g_free(sb->sb_data); -} - -bool sbdrop(struct sbuf *sb, size_t num) -{ - int limit = sb->sb_datalen / 2; - - g_warn_if_fail(num <= sb->sb_cc); - if (num > sb->sb_cc) - num = sb->sb_cc; - - sb->sb_cc -= num; - sb->sb_rptr += num; - if (sb->sb_rptr >= sb->sb_data + sb->sb_datalen) - sb->sb_rptr -= sb->sb_datalen; - - if (sb->sb_cc < limit && sb->sb_cc + num >= limit) { - return true; - } - - return false; -} - -void sbreserve(struct sbuf *sb, size_t size) -{ - sb->sb_wptr = sb->sb_rptr = sb->sb_data = g_realloc(sb->sb_data, size); - sb->sb_cc = 0; - sb->sb_datalen = size; -} - -/* - * Try and write() to the socket, whatever doesn't get written - * append to the buffer... for a host with a fast net connection, - * this prevents an unnecessary copy of the data - * (the socket is non-blocking, so we won't hang) - */ -void sbappend(struct socket *so, struct mbuf *m) -{ - int ret = 0; - - DEBUG_CALL("sbappend"); - DEBUG_ARG("so = %p", so); - DEBUG_ARG("m = %p", m); - DEBUG_ARG("m->m_len = %d", m->m_len); - - /* Shouldn't happen, but... e.g. foreign host closes connection */ - if (m->m_len <= 0) { - m_free(m); - return; - } - - /* - * If there is urgent data, call sosendoob - * if not all was sent, sowrite will take care of the rest - * (The rest of this function is just an optimisation) - */ - if (so->so_urgc) { - sbappendsb(&so->so_rcv, m); - m_free(m); - (void)sosendoob(so); - return; - } - - /* - * We only write if there's nothing in the buffer, - * ottherwise it'll arrive out of order, and hence corrupt - */ - if (!so->so_rcv.sb_cc) - ret = slirp_send(so, m->m_data, m->m_len, 0); - - if (ret <= 0) { - /* - * Nothing was written - * It's possible that the socket has closed, but - * we don't need to check because if it has closed, - * it will be detected in the normal way by soread() - */ - sbappendsb(&so->so_rcv, m); - } else if (ret != m->m_len) { - /* - * Something was written, but not everything.. - * sbappendsb the rest - */ - m->m_len -= ret; - m->m_data += ret; - sbappendsb(&so->so_rcv, m); - } /* else */ - /* Whatever happened, we free the mbuf */ - m_free(m); -} - -/* - * Copy the data from m into sb - * The caller is responsible to make sure there's enough room - */ -static void sbappendsb(struct sbuf *sb, struct mbuf *m) -{ - int len, n, nn; - - len = m->m_len; - - if (sb->sb_wptr < sb->sb_rptr) { - n = sb->sb_rptr - sb->sb_wptr; - if (n > len) - n = len; - memcpy(sb->sb_wptr, m->m_data, n); - } else { - /* Do the right edge first */ - n = sb->sb_data + sb->sb_datalen - sb->sb_wptr; - if (n > len) - n = len; - memcpy(sb->sb_wptr, m->m_data, n); - len -= n; - if (len) { - /* Now the left edge */ - nn = sb->sb_rptr - sb->sb_data; - if (nn > len) - nn = len; - memcpy(sb->sb_data, m->m_data + n, nn); - n += nn; - } - } - - sb->sb_cc += n; - sb->sb_wptr += n; - if (sb->sb_wptr >= sb->sb_data + sb->sb_datalen) - sb->sb_wptr -= sb->sb_datalen; -} - -/* - * Copy data from sbuf to a normal, straight buffer - * Don't update the sbuf rptr, this will be - * done in sbdrop when the data is acked - */ -void sbcopy(struct sbuf *sb, size_t off, size_t len, char *to) -{ - char *from; - - g_assert(len + off <= sb->sb_cc); - - from = sb->sb_rptr + off; - if (from >= sb->sb_data + sb->sb_datalen) - from -= sb->sb_datalen; - - if (from < sb->sb_wptr) { - memcpy(to, from, len); - } else { - /* re-use off */ - off = (sb->sb_data + sb->sb_datalen) - from; - if (off > len) - off = len; - memcpy(to, from, off); - len -= off; - if (len) - memcpy(to + off, sb->sb_data, len); - } -} diff --git a/src/network/slirp/sbuf.h b/src/network/slirp/sbuf.h deleted file mode 100644 index 01886fbd0..000000000 --- a/src/network/slirp/sbuf.h +++ /dev/null @@ -1,27 +0,0 @@ -/* SPDX-License-Identifier: BSD-3-Clause */ -/* - * Copyright (c) 1995 Danny Gasparovski. - */ - -#ifndef SBUF_H -#define SBUF_H - -#define sbspace(sb) ((sb)->sb_datalen - (sb)->sb_cc) - -struct sbuf { - uint32_t sb_cc; /* actual chars in buffer */ - uint32_t sb_datalen; /* Length of data */ - char *sb_wptr; /* write pointer. points to where the next - * bytes should be written in the sbuf */ - char *sb_rptr; /* read pointer. points to where the next - * byte should be read from the sbuf */ - char *sb_data; /* Actual data */ -}; - -void sbfree(struct sbuf *sb); -bool sbdrop(struct sbuf *sb, size_t len); -void sbreserve(struct sbuf *sb, size_t size); -void sbappend(struct socket *sb, struct mbuf *mb); -void sbcopy(struct sbuf *sb, size_t off, size_t len, char *p); - -#endif diff --git a/src/network/slirp/slirp.c b/src/network/slirp/slirp.c deleted file mode 100644 index 021324cdb..000000000 --- a/src/network/slirp/slirp.c +++ /dev/null @@ -1,1192 +0,0 @@ -/* SPDX-License-Identifier: MIT */ -/* - * libslirp glue - * - * Copyright (c) 2004-2008 Fabrice Bellard - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL - * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -#include "slirp.h" - - -#ifndef _WIN32 -#include -#endif - -/* https://gitlab.freedesktop.org/slirp/libslirp/issues/18 */ -#if defined(__NetBSD__) && defined(if_mtu) -#undef if_mtu -#endif - -int slirp_debug; - -/* Define to 1 if you want KEEPALIVE timers */ -bool slirp_do_keepalive; - -/* host loopback address */ -struct in_addr loopback_addr; -/* host loopback network mask */ -unsigned long loopback_mask; - -/* emulated hosts use the MAC addr 52:55:IP:IP:IP:IP */ -static const uint8_t special_ethaddr[ETH_ALEN] = { 0x52, 0x55, 0x00, - 0x00, 0x00, 0x00 }; - -unsigned curtime; - -static struct in_addr dns_addr; -#ifndef _WIN32 -static struct in6_addr dns6_addr; -#endif -static unsigned dns_addr_time; -#ifndef _WIN32 -static unsigned dns6_addr_time; -#endif - -#define TIMEOUT_FAST 2 /* milliseconds */ -#define TIMEOUT_SLOW 499 /* milliseconds */ -/* for the aging of certain requests like DNS */ -#define TIMEOUT_DEFAULT 1000 /* milliseconds */ - -#ifdef _WIN32 - -int get_dns_addr(struct in_addr *pdns_addr) -{ - FIXED_INFO *FixedInfo = NULL; - ULONG BufLen; - DWORD ret; - IP_ADDR_STRING *pIPAddr; - struct in_addr tmp_addr; - - if (dns_addr.s_addr != 0 && (curtime - dns_addr_time) < TIMEOUT_DEFAULT) { - *pdns_addr = dns_addr; - return 0; - } - - FixedInfo = (FIXED_INFO *)GlobalAlloc(GPTR, sizeof(FIXED_INFO)); - BufLen = sizeof(FIXED_INFO); - - if (ERROR_BUFFER_OVERFLOW == GetNetworkParams(FixedInfo, &BufLen)) { - if (FixedInfo) { - GlobalFree(FixedInfo); - FixedInfo = NULL; - } - FixedInfo = GlobalAlloc(GPTR, BufLen); - } - - if ((ret = GetNetworkParams(FixedInfo, &BufLen)) != ERROR_SUCCESS) { - printf("GetNetworkParams failed. ret = %08x\n", (unsigned)ret); - if (FixedInfo) { - GlobalFree(FixedInfo); - FixedInfo = NULL; - } - return -1; - } - - pIPAddr = &(FixedInfo->DnsServerList); - inet_aton(pIPAddr->IpAddress.String, &tmp_addr); - *pdns_addr = tmp_addr; - dns_addr = tmp_addr; - dns_addr_time = curtime; - if (FixedInfo) { - GlobalFree(FixedInfo); - FixedInfo = NULL; - } - return 0; -} - -int get_dns6_addr(struct in6_addr *pdns6_addr, uint32_t *scope_id) -{ - return -1; -} - -static void winsock_cleanup(void) -{ - WSACleanup(); -} - -#else - -static int get_dns_addr_cached(void *pdns_addr, void *cached_addr, - socklen_t addrlen, struct stat *cached_stat, - unsigned *cached_time) -{ - struct stat old_stat; - if (curtime - *cached_time < TIMEOUT_DEFAULT) { - memcpy(pdns_addr, cached_addr, addrlen); - return 0; - } - old_stat = *cached_stat; - if (stat("/etc/resolv.conf", cached_stat) != 0) { - return -1; - } - if (cached_stat->st_dev == old_stat.st_dev && - cached_stat->st_ino == old_stat.st_ino && - cached_stat->st_size == old_stat.st_size && - cached_stat->st_mtime == old_stat.st_mtime) { - memcpy(pdns_addr, cached_addr, addrlen); - return 0; - } - return 1; -} - -static int get_dns_addr_resolv_conf(int af, void *pdns_addr, void *cached_addr, - socklen_t addrlen, uint32_t *scope_id, - unsigned *cached_time) -{ - char buff[512]; - char buff2[257]; - FILE *f; - int found = 0; - void *tmp_addr = alloca(addrlen); - unsigned if_index; - - f = fopen("/etc/resolv.conf", "r"); - if (!f) - return -1; - - DEBUG_MISC("IP address of your DNS(s):"); - while (fgets(buff, 512, f) != NULL) { - if (sscanf(buff, "nameserver%*[ \t]%256s", buff2) == 1) { - char *c = strchr(buff2, '%'); - if (c) { - if_index = if_nametoindex(c + 1); - *c = '\0'; - } else { - if_index = 0; - } - - if (!inet_pton(af, buff2, tmp_addr)) { - continue; - } - /* If it's the first one, set it to dns_addr */ - if (!found) { - memcpy(pdns_addr, tmp_addr, addrlen); - memcpy(cached_addr, tmp_addr, addrlen); - if (scope_id) { - *scope_id = if_index; - } - *cached_time = curtime; - } - - if (++found > 3) { - DEBUG_MISC(" (more)"); - break; - } else if (slirp_debug & DBG_MISC) { - char s[INET6_ADDRSTRLEN]; - const char *res = inet_ntop(af, tmp_addr, s, sizeof(s)); - if (!res) { - res = " (string conversion error)"; - } - DEBUG_MISC(" %s", res); - } - } - } - fclose(f); - if (!found) - return -1; - return 0; -} - -int get_dns_addr(struct in_addr *pdns_addr) -{ - static struct stat dns_addr_stat; - - if (dns_addr.s_addr != 0) { - int ret; - ret = get_dns_addr_cached(pdns_addr, &dns_addr, sizeof(dns_addr), - &dns_addr_stat, &dns_addr_time); - if (ret <= 0) { - return ret; - } - } - return get_dns_addr_resolv_conf(AF_INET, pdns_addr, &dns_addr, - sizeof(dns_addr), NULL, &dns_addr_time); -} - -int get_dns6_addr(struct in6_addr *pdns6_addr, uint32_t *scope_id) -{ - static struct stat dns6_addr_stat; - - if (!in6_zero(&dns6_addr)) { - int ret; - ret = get_dns_addr_cached(pdns6_addr, &dns6_addr, sizeof(dns6_addr), - &dns6_addr_stat, &dns6_addr_time); - if (ret <= 0) { - return ret; - } - } - return get_dns_addr_resolv_conf(AF_INET6, pdns6_addr, &dns6_addr, - sizeof(dns6_addr), scope_id, - &dns6_addr_time); -} - -#endif - -static void slirp_init_once(void) -{ - static int initialized; - const char *debug; -#ifdef _WIN32 - WSADATA Data; -#endif - - if (initialized) { - return; - } - initialized = 1; - -#ifdef _WIN32 - WSAStartup(MAKEWORD(2, 0), &Data); - atexit(winsock_cleanup); -#endif - - loopback_addr.s_addr = htonl(INADDR_LOOPBACK); - loopback_mask = htonl(IN_CLASSA_NET); - - debug = g_getenv("SLIRP_DEBUG"); - if (debug) { - const GDebugKey keys[] = { - { "call", DBG_CALL }, - { "misc", DBG_MISC }, - { "error", DBG_ERROR }, - { "tftp", DBG_TFTP }, - }; - slirp_debug = g_parse_debug_string(debug, keys, G_N_ELEMENTS(keys)); - } -} - -Slirp *slirp_new(const SlirpConfig *cfg, const SlirpCb *callbacks, void *opaque) -{ - Slirp *slirp; - - g_return_val_if_fail(cfg != NULL, NULL); - g_return_val_if_fail(cfg->version >= SLIRP_CONFIG_VERSION_MIN, NULL); - g_return_val_if_fail(cfg->version <= SLIRP_CONFIG_VERSION_MAX, NULL); - g_return_val_if_fail(cfg->if_mtu >= IF_MTU_MIN || cfg->if_mtu == 0, NULL); - g_return_val_if_fail(cfg->if_mtu <= IF_MTU_MAX, NULL); - g_return_val_if_fail(cfg->if_mru >= IF_MRU_MIN || cfg->if_mru == 0, NULL); - g_return_val_if_fail(cfg->if_mru <= IF_MRU_MAX, NULL); - g_return_val_if_fail(!cfg->bootfile || - (strlen(cfg->bootfile) < - G_SIZEOF_MEMBER(struct bootp_t, bp_file)), NULL); - - slirp = g_malloc0(sizeof(Slirp)); - - slirp_init_once(); - - slirp->opaque = opaque; - slirp->cb = callbacks; - slirp->grand = g_rand_new(); - slirp->restricted = cfg->restricted; - - slirp->in_enabled = cfg->in_enabled; - slirp->in6_enabled = cfg->in6_enabled; - - if_init(slirp); - ip_init(slirp); - ip6_init(slirp); - - m_init(slirp); - - slirp->vnetwork_addr = cfg->vnetwork; - slirp->vnetwork_mask = cfg->vnetmask; - slirp->vhost_addr = cfg->vhost; - slirp->vprefix_addr6 = cfg->vprefix_addr6; - slirp->vprefix_len = cfg->vprefix_len; - slirp->vhost_addr6 = cfg->vhost6; - if (cfg->vhostname) { - slirp_pstrcpy(slirp->client_hostname, sizeof(slirp->client_hostname), - cfg->vhostname); - } - slirp->tftp_prefix = g_strdup(cfg->tftp_path); - slirp->bootp_filename = g_strdup(cfg->bootfile); - slirp->vdomainname = g_strdup(cfg->vdomainname); - slirp->vdhcp_startaddr = cfg->vdhcp_start; - slirp->vnameserver_addr = cfg->vnameserver; - slirp->vnameserver_addr6 = cfg->vnameserver6; - slirp->tftp_server_name = g_strdup(cfg->tftp_server_name); - - if (cfg->vdnssearch) { - translate_dnssearch(slirp, cfg->vdnssearch); - } - slirp->if_mtu = cfg->if_mtu == 0 ? IF_MTU_DEFAULT : cfg->if_mtu; - slirp->if_mru = cfg->if_mru == 0 ? IF_MRU_DEFAULT : cfg->if_mru; - slirp->disable_host_loopback = cfg->disable_host_loopback; - slirp->enable_emu = cfg->enable_emu; - - if (cfg->version >= 2) { - slirp->outbound_addr = cfg->outbound_addr; - slirp->outbound_addr6 = cfg->outbound_addr6; - } else { - slirp->outbound_addr = NULL; - slirp->outbound_addr6 = NULL; - } - - if (cfg->version >= 3) { - slirp->disable_dns = cfg->disable_dns; - } else { - slirp->disable_dns = false; - } - - return slirp; -} - -Slirp *slirp_init(int restricted, bool in_enabled, struct in_addr vnetwork, - struct in_addr vnetmask, struct in_addr vhost, - bool in6_enabled, struct in6_addr vprefix_addr6, - uint8_t vprefix_len, struct in6_addr vhost6, - const char *vhostname, const char *tftp_server_name, - const char *tftp_path, const char *bootfile, - struct in_addr vdhcp_start, struct in_addr vnameserver, - struct in6_addr vnameserver6, const char **vdnssearch, - const char *vdomainname, const SlirpCb *callbacks, - void *opaque) -{ - SlirpConfig cfg; - memset(&cfg, 0, sizeof(cfg)); - cfg.version = 1; - cfg.restricted = restricted; - cfg.in_enabled = in_enabled; - cfg.vnetwork = vnetwork; - cfg.vnetmask = vnetmask; - cfg.vhost = vhost; - cfg.in6_enabled = in6_enabled; - cfg.vprefix_addr6 = vprefix_addr6; - cfg.vprefix_len = vprefix_len; - cfg.vhost6 = vhost6; - cfg.vhostname = vhostname; - cfg.tftp_server_name = tftp_server_name; - cfg.tftp_path = tftp_path; - cfg.bootfile = bootfile; - cfg.vdhcp_start = vdhcp_start; - cfg.vnameserver = vnameserver; - cfg.vnameserver6 = vnameserver6; - cfg.vdnssearch = vdnssearch; - cfg.vdomainname = vdomainname; - return slirp_new(&cfg, callbacks, opaque); -} - -void slirp_cleanup(Slirp *slirp) -{ - struct gfwd_list *e, *next; - - for (e = slirp->guestfwd_list; e; e = next) { - next = e->ex_next; - g_free(e->ex_exec); - g_free(e->ex_unix); - g_free(e); - } - - ip_cleanup(slirp); - ip6_cleanup(slirp); - m_cleanup(slirp); - - g_rand_free(slirp->grand); - - g_free(slirp->vdnssearch); - g_free(slirp->tftp_prefix); - g_free(slirp->bootp_filename); - g_free(slirp->vdomainname); - g_free(slirp); -} - -#define CONN_CANFSEND(so) \ - (((so)->so_state & (SS_FCANTSENDMORE | SS_ISFCONNECTED)) == SS_ISFCONNECTED) -#define CONN_CANFRCV(so) \ - (((so)->so_state & (SS_FCANTRCVMORE | SS_ISFCONNECTED)) == SS_ISFCONNECTED) - -static void slirp_update_timeout(Slirp *slirp, uint32_t *timeout) -{ - uint32_t t; - - if (*timeout <= TIMEOUT_FAST) { - return; - } - - t = MIN(1000, *timeout); - - /* If we have tcp timeout with slirp, then we will fill @timeout with - * more precise value. - */ - if (slirp->time_fasttimo) { - *timeout = TIMEOUT_FAST; - return; - } - if (slirp->do_slowtimo) { - t = MIN(TIMEOUT_SLOW, t); - } - *timeout = t; -} - -void slirp_pollfds_fill(Slirp *slirp, uint32_t *timeout, - SlirpAddPollCb add_poll, void *opaque) -{ - struct socket *so, *so_next; - - /* - * First, TCP sockets - */ - - /* - * *_slowtimo needs calling if there are IP fragments - * in the fragment queue, or there are TCP connections active - */ - slirp->do_slowtimo = ((slirp->tcb.so_next != &slirp->tcb) || - (&slirp->ipq.ip_link != slirp->ipq.ip_link.next)); - - for (so = slirp->tcb.so_next; so != &slirp->tcb; so = so_next) { - int events = 0; - - so_next = so->so_next; - - so->pollfds_idx = -1; - - /* - * See if we need a tcp_fasttimo - */ - if (slirp->time_fasttimo == 0 && so->so_tcpcb->t_flags & TF_DELACK) { - slirp->time_fasttimo = curtime; /* Flag when want a fasttimo */ - } - - /* - * NOFDREF can include still connecting to local-host, - * newly socreated() sockets etc. Don't want to select these. - */ - if (so->so_state & SS_NOFDREF || so->s == -1) { - continue; - } - - /* - * Set for reading sockets which are accepting - */ - if (so->so_state & SS_FACCEPTCONN) { - so->pollfds_idx = add_poll( - so->s, SLIRP_POLL_IN | SLIRP_POLL_HUP | SLIRP_POLL_ERR, opaque); - continue; - } - - /* - * Set for writing sockets which are connecting - */ - if (so->so_state & SS_ISFCONNECTING) { - so->pollfds_idx = - add_poll(so->s, SLIRP_POLL_OUT | SLIRP_POLL_ERR, opaque); - continue; - } - - /* - * Set for writing if we are connected, can send more, and - * we have something to send - */ - if (CONN_CANFSEND(so) && so->so_rcv.sb_cc) { - events |= SLIRP_POLL_OUT | SLIRP_POLL_ERR; - } - - /* - * Set for reading (and urgent data) if we are connected, can - * receive more, and we have room for it XXX /2 ? - */ - if (CONN_CANFRCV(so) && - (so->so_snd.sb_cc < (so->so_snd.sb_datalen / 2))) { - events |= SLIRP_POLL_IN | SLIRP_POLL_HUP | SLIRP_POLL_ERR | - SLIRP_POLL_PRI; - } - - if (events) { - so->pollfds_idx = add_poll(so->s, events, opaque); - } - } - - /* - * UDP sockets - */ - for (so = slirp->udb.so_next; so != &slirp->udb; so = so_next) { - so_next = so->so_next; - - so->pollfds_idx = -1; - - /* - * See if it's timed out - */ - if (so->so_expire) { - if (so->so_expire <= curtime) { - udp_detach(so); - continue; - } else { - slirp->do_slowtimo = true; /* Let socket expire */ - } - } - - /* - * When UDP packets are received from over the - * link, they're sendto()'d straight away, so - * no need for setting for writing - * Limit the number of packets queued by this session - * to 4. Note that even though we try and limit this - * to 4 packets, the session could have more queued - * if the packets needed to be fragmented - * (XXX <= 4 ?) - */ - if ((so->so_state & SS_ISFCONNECTED) && so->so_queued <= 4) { - so->pollfds_idx = add_poll( - so->s, SLIRP_POLL_IN | SLIRP_POLL_HUP | SLIRP_POLL_ERR, opaque); - } - } - - /* - * ICMP sockets - */ - for (so = slirp->icmp.so_next; so != &slirp->icmp; so = so_next) { - so_next = so->so_next; - - so->pollfds_idx = -1; - - /* - * See if it's timed out - */ - if (so->so_expire) { - if (so->so_expire <= curtime) { - icmp_detach(so); - continue; - } else { - slirp->do_slowtimo = true; /* Let socket expire */ - } - } - - if (so->so_state & SS_ISFCONNECTED) { - so->pollfds_idx = add_poll( - so->s, SLIRP_POLL_IN | SLIRP_POLL_HUP | SLIRP_POLL_ERR, opaque); - } - } - - slirp_update_timeout(slirp, timeout); -} - -void slirp_pollfds_poll(Slirp *slirp, int select_error, - SlirpGetREventsCb get_revents, void *opaque) -{ - struct socket *so, *so_next; - int ret; - - curtime = slirp->cb->clock_get_ns(slirp->opaque) / SCALE_MS; - - /* - * See if anything has timed out - */ - if (slirp->time_fasttimo && - ((curtime - slirp->time_fasttimo) >= TIMEOUT_FAST)) { - tcp_fasttimo(slirp); - slirp->time_fasttimo = 0; - } - if (slirp->do_slowtimo && - ((curtime - slirp->last_slowtimo) >= TIMEOUT_SLOW)) { - ip_slowtimo(slirp); - tcp_slowtimo(slirp); - slirp->last_slowtimo = curtime; - } - - /* - * Check sockets - */ - if (!select_error) { - /* - * Check TCP sockets - */ - for (so = slirp->tcb.so_next; so != &slirp->tcb; so = so_next) { - int revents; - - so_next = so->so_next; - - revents = 0; - if (so->pollfds_idx != -1) { - revents = get_revents(so->pollfds_idx, opaque); - } - - if (so->so_state & SS_NOFDREF || so->s == -1) { - continue; - } - - /* - * Check for URG data - * This will soread as well, so no need to - * test for SLIRP_POLL_IN below if this succeeds - */ - if (revents & SLIRP_POLL_PRI) { - ret = sorecvoob(so); - if (ret < 0) { - /* Socket error might have resulted in the socket being - * removed, do not try to do anything more with it. */ - continue; - } - } - /* - * Check sockets for reading - */ - else if (revents & - (SLIRP_POLL_IN | SLIRP_POLL_HUP | SLIRP_POLL_ERR)) { - /* - * Check for incoming connections - */ - if (so->so_state & SS_FACCEPTCONN) { - tcp_connect(so); - continue; - } /* else */ - ret = soread(so); - - /* Output it if we read something */ - if (ret > 0) { - tcp_output(sototcpcb(so)); - } - if (ret < 0) { - /* Socket error might have resulted in the socket being - * removed, do not try to do anything more with it. */ - continue; - } - } - - /* - * Check sockets for writing - */ - if (!(so->so_state & SS_NOFDREF) && - (revents & (SLIRP_POLL_OUT | SLIRP_POLL_ERR))) { - /* - * Check for non-blocking, still-connecting sockets - */ - if (so->so_state & SS_ISFCONNECTING) { - /* Connected */ - so->so_state &= ~SS_ISFCONNECTING; - - ret = send(so->s, (const void *)&ret, 0, 0); - if (ret < 0) { - /* XXXXX Must fix, zero bytes is a NOP */ - if (errno == EAGAIN || errno == EWOULDBLOCK || - errno == EINPROGRESS || errno == ENOTCONN) { - continue; - } - - /* else failed */ - so->so_state &= SS_PERSISTENT_MASK; - so->so_state |= SS_NOFDREF; - } - /* else so->so_state &= ~SS_ISFCONNECTING; */ - - /* - * Continue tcp_input - */ - tcp_input((struct mbuf *)NULL, sizeof(struct ip), so, - so->so_ffamily); - /* continue; */ - } else { - ret = sowrite(so); - if (ret > 0) { - /* Call tcp_output in case we need to send a window - * update to the guest, otherwise it will be stuck - * until it sends a window probe. */ - tcp_output(sototcpcb(so)); - } - } - } - } - - /* - * Now UDP sockets. - * Incoming packets are sent straight away, they're not buffered. - * Incoming UDP data isn't buffered either. - */ - for (so = slirp->udb.so_next; so != &slirp->udb; so = so_next) { - int revents; - - so_next = so->so_next; - - revents = 0; - if (so->pollfds_idx != -1) { - revents = get_revents(so->pollfds_idx, opaque); - } - - if (so->s != -1 && - (revents & (SLIRP_POLL_IN | SLIRP_POLL_HUP | SLIRP_POLL_ERR))) { - sorecvfrom(so); - } - } - - /* - * Check incoming ICMP relies. - */ - for (so = slirp->icmp.so_next; so != &slirp->icmp; so = so_next) { - int revents; - - so_next = so->so_next; - - revents = 0; - if (so->pollfds_idx != -1) { - revents = get_revents(so->pollfds_idx, opaque); - } - - if (so->s != -1 && - (revents & (SLIRP_POLL_IN | SLIRP_POLL_HUP | SLIRP_POLL_ERR))) { - icmp_receive(so); - } - } - } - - if_start(slirp); -} - -static void arp_input(Slirp *slirp, const uint8_t *pkt, int pkt_len) -{ - const struct slirp_arphdr *ah = - (const struct slirp_arphdr *)(pkt + ETH_HLEN); - uint8_t arp_reply[MAX(ETH_HLEN + sizeof(struct slirp_arphdr), 64)]; - struct ethhdr *reh = (struct ethhdr *)arp_reply; - struct slirp_arphdr *rah = (struct slirp_arphdr *)(arp_reply + ETH_HLEN); - int ar_op; - struct gfwd_list *ex_ptr; - - if (!slirp->in_enabled) { - return; - } - - ar_op = ntohs(ah->ar_op); - switch (ar_op) { - case ARPOP_REQUEST: - if (ah->ar_tip == ah->ar_sip) { - /* Gratuitous ARP */ - arp_table_add(slirp, ah->ar_sip, ah->ar_sha); - return; - } - - if ((ah->ar_tip & slirp->vnetwork_mask.s_addr) == - slirp->vnetwork_addr.s_addr) { - if (ah->ar_tip == slirp->vnameserver_addr.s_addr || - ah->ar_tip == slirp->vhost_addr.s_addr) - goto arp_ok; - /* TODO: IPv6 */ - for (ex_ptr = slirp->guestfwd_list; ex_ptr; - ex_ptr = ex_ptr->ex_next) { - if (ex_ptr->ex_addr.s_addr == ah->ar_tip) - goto arp_ok; - } - return; - arp_ok: - memset(arp_reply, 0, sizeof(arp_reply)); - - arp_table_add(slirp, ah->ar_sip, ah->ar_sha); - - /* ARP request for alias/dns mac address */ - memcpy(reh->h_dest, pkt + ETH_ALEN, ETH_ALEN); - memcpy(reh->h_source, special_ethaddr, ETH_ALEN - 4); - memcpy(&reh->h_source[2], &ah->ar_tip, 4); - reh->h_proto = htons(ETH_P_ARP); - - rah->ar_hrd = htons(1); - rah->ar_pro = htons(ETH_P_IP); - rah->ar_hln = ETH_ALEN; - rah->ar_pln = 4; - rah->ar_op = htons(ARPOP_REPLY); - memcpy(rah->ar_sha, reh->h_source, ETH_ALEN); - rah->ar_sip = ah->ar_tip; - memcpy(rah->ar_tha, ah->ar_sha, ETH_ALEN); - rah->ar_tip = ah->ar_sip; - slirp_send_packet_all(slirp, arp_reply, sizeof(arp_reply)); - } - break; - case ARPOP_REPLY: - arp_table_add(slirp, ah->ar_sip, ah->ar_sha); - break; - default: - break; - } -} - -void slirp_input(Slirp *slirp, const uint8_t *pkt, int pkt_len) -{ - struct mbuf *m; - int proto; - - if (pkt_len < ETH_HLEN) - return; - - proto = (((uint16_t)pkt[12]) << 8) + pkt[13]; - switch (proto) { - case ETH_P_ARP: - arp_input(slirp, pkt, pkt_len); - break; - case ETH_P_IP: - case ETH_P_IPV6: - m = m_get(slirp); - if (!m) - return; - /* Note: we add 2 to align the IP header on 4 bytes, - * and add the margin for the tcpiphdr overhead */ - if (M_FREEROOM(m) < pkt_len + TCPIPHDR_DELTA + 2) { - m_inc(m, pkt_len + TCPIPHDR_DELTA + 2); - } - m->m_len = pkt_len + TCPIPHDR_DELTA + 2; - memcpy(m->m_data + TCPIPHDR_DELTA + 2, pkt, pkt_len); - - m->m_data += TCPIPHDR_DELTA + 2 + ETH_HLEN; - m->m_len -= TCPIPHDR_DELTA + 2 + ETH_HLEN; - - if (proto == ETH_P_IP) { - ip_input(m); - } else if (proto == ETH_P_IPV6) { - ip6_input(m); - } - break; - - case ETH_P_NCSI: - ncsi_input(slirp, pkt, pkt_len); - break; - - default: - break; - } -} - -/* Prepare the IPv4 packet to be sent to the ethernet device. Returns 1 if no - * packet should be sent, 0 if the packet must be re-queued, 2 if the packet - * is ready to go. - */ -static int if_encap4(Slirp *slirp, struct mbuf *ifm, struct ethhdr *eh, - uint8_t ethaddr[ETH_ALEN]) -{ - const struct ip *iph = (const struct ip *)ifm->m_data; - - if (!arp_table_search(slirp, iph->ip_dst.s_addr, ethaddr)) { - uint8_t arp_req[ETH_HLEN + sizeof(struct slirp_arphdr)]; - struct ethhdr *reh = (struct ethhdr *)arp_req; - struct slirp_arphdr *rah = (struct slirp_arphdr *)(arp_req + ETH_HLEN); - - if (!ifm->resolution_requested) { - /* If the client addr is not known, send an ARP request */ - memset(reh->h_dest, 0xff, ETH_ALEN); - memcpy(reh->h_source, special_ethaddr, ETH_ALEN - 4); - memcpy(&reh->h_source[2], &slirp->vhost_addr, 4); - reh->h_proto = htons(ETH_P_ARP); - rah->ar_hrd = htons(1); - rah->ar_pro = htons(ETH_P_IP); - rah->ar_hln = ETH_ALEN; - rah->ar_pln = 4; - rah->ar_op = htons(ARPOP_REQUEST); - - /* source hw addr */ - memcpy(rah->ar_sha, special_ethaddr, ETH_ALEN - 4); - memcpy(&rah->ar_sha[2], &slirp->vhost_addr, 4); - - /* source IP */ - rah->ar_sip = slirp->vhost_addr.s_addr; - - /* target hw addr (none) */ - memset(rah->ar_tha, 0, ETH_ALEN); - - /* target IP */ - rah->ar_tip = iph->ip_dst.s_addr; - slirp->client_ipaddr = iph->ip_dst; - slirp_send_packet_all(slirp, arp_req, sizeof(arp_req)); - ifm->resolution_requested = true; - - /* Expire request and drop outgoing packet after 1 second */ - ifm->expiration_date = - slirp->cb->clock_get_ns(slirp->opaque) + 1000000000ULL; - } - return 0; - } else { - memcpy(eh->h_source, special_ethaddr, ETH_ALEN - 4); - /* XXX: not correct */ - memcpy(&eh->h_source[2], &slirp->vhost_addr, 4); - eh->h_proto = htons(ETH_P_IP); - - /* Send this */ - return 2; - } -} - -/* Prepare the IPv6 packet to be sent to the ethernet device. Returns 1 if no - * packet should be sent, 0 if the packet must be re-queued, 2 if the packet - * is ready to go. - */ -static int if_encap6(Slirp *slirp, struct mbuf *ifm, struct ethhdr *eh, - uint8_t ethaddr[ETH_ALEN]) -{ - const struct ip6 *ip6h = mtod(ifm, const struct ip6 *); - if (!ndp_table_search(slirp, ip6h->ip_dst, ethaddr)) { - if (!ifm->resolution_requested) { - ndp_send_ns(slirp, ip6h->ip_dst); - ifm->resolution_requested = true; - ifm->expiration_date = - slirp->cb->clock_get_ns(slirp->opaque) + 1000000000ULL; - } - return 0; - } else { - eh->h_proto = htons(ETH_P_IPV6); - in6_compute_ethaddr(ip6h->ip_src, eh->h_source); - - /* Send this */ - return 2; - } -} - -/* Output the IP packet to the ethernet device. Returns 0 if the packet must be - * re-queued. - */ -int if_encap(Slirp *slirp, struct mbuf *ifm) -{ - uint8_t buf[IF_MTU_MAX + 100]; - struct ethhdr *eh = (struct ethhdr *)buf; - uint8_t ethaddr[ETH_ALEN]; - const struct ip *iph = (const struct ip *)ifm->m_data; - int ret; - - if (ifm->m_len + ETH_HLEN > sizeof(buf)) { - return 1; - } - - switch (iph->ip_v) { - case IPVERSION: - ret = if_encap4(slirp, ifm, eh, ethaddr); - if (ret < 2) { - return ret; - } - break; - - case IP6VERSION: - ret = if_encap6(slirp, ifm, eh, ethaddr); - if (ret < 2) { - return ret; - } - break; - - default: - g_assert_not_reached(); - } - - memcpy(eh->h_dest, ethaddr, ETH_ALEN); - DEBUG_ARG("src = %02x:%02x:%02x:%02x:%02x:%02x", eh->h_source[0], - eh->h_source[1], eh->h_source[2], eh->h_source[3], - eh->h_source[4], eh->h_source[5]); - DEBUG_ARG("dst = %02x:%02x:%02x:%02x:%02x:%02x", eh->h_dest[0], - eh->h_dest[1], eh->h_dest[2], eh->h_dest[3], eh->h_dest[4], - eh->h_dest[5]); - memcpy(buf + sizeof(struct ethhdr), ifm->m_data, ifm->m_len); - slirp_send_packet_all(slirp, buf, ifm->m_len + ETH_HLEN); - return 1; -} - -/* Drop host forwarding rule, return 0 if found. */ -/* TODO: IPv6 */ -int slirp_remove_hostfwd(Slirp *slirp, int is_udp, struct in_addr host_addr, - int host_port) -{ - struct socket *so; - struct socket *head = (is_udp ? &slirp->udb : &slirp->tcb); - struct sockaddr_in addr; - int port = htons(host_port); - socklen_t addr_len; - - for (so = head->so_next; so != head; so = so->so_next) { - addr_len = sizeof(addr); - if ((so->so_state & SS_HOSTFWD) && - getsockname(so->s, (struct sockaddr *)&addr, &addr_len) == 0 && - addr.sin_addr.s_addr == host_addr.s_addr && addr.sin_port == port) { - so->slirp->cb->unregister_poll_fd(so->s, so->slirp->opaque); - closesocket(so->s); - sofree(so); - return 0; - } - } - - return -1; -} - -/* TODO: IPv6 */ -int slirp_add_hostfwd(Slirp *slirp, int is_udp, struct in_addr host_addr, - int host_port, struct in_addr guest_addr, int guest_port) -{ - if (!guest_addr.s_addr) { - guest_addr = slirp->vdhcp_startaddr; - } - if (is_udp) { - if (!udp_listen(slirp, host_addr.s_addr, htons(host_port), - guest_addr.s_addr, htons(guest_port), SS_HOSTFWD)) - return -1; - } else { - if (!tcp_listen(slirp, host_addr.s_addr, htons(host_port), - guest_addr.s_addr, htons(guest_port), SS_HOSTFWD)) - return -1; - } - return 0; -} - -/* TODO: IPv6 */ -static bool check_guestfwd(Slirp *slirp, struct in_addr *guest_addr, - int guest_port) -{ - struct gfwd_list *tmp_ptr; - - if (!guest_addr->s_addr) { - guest_addr->s_addr = slirp->vnetwork_addr.s_addr | - (htonl(0x0204) & ~slirp->vnetwork_mask.s_addr); - } - if ((guest_addr->s_addr & slirp->vnetwork_mask.s_addr) != - slirp->vnetwork_addr.s_addr || - guest_addr->s_addr == slirp->vhost_addr.s_addr || - guest_addr->s_addr == slirp->vnameserver_addr.s_addr) { - return false; - } - - /* check if the port is "bound" */ - for (tmp_ptr = slirp->guestfwd_list; tmp_ptr; tmp_ptr = tmp_ptr->ex_next) { - if (guest_port == tmp_ptr->ex_fport && - guest_addr->s_addr == tmp_ptr->ex_addr.s_addr) - return false; - } - - return true; -} - -int slirp_add_exec(Slirp *slirp, const char *cmdline, - struct in_addr *guest_addr, int guest_port) -{ - if (!check_guestfwd(slirp, guest_addr, guest_port)) { - return -1; - } - - add_exec(&slirp->guestfwd_list, cmdline, *guest_addr, htons(guest_port)); - return 0; -} - -int slirp_add_unix(Slirp *slirp, const char *unixsock, - struct in_addr *guest_addr, int guest_port) -{ -#ifdef G_OS_UNIX - if (!check_guestfwd(slirp, guest_addr, guest_port)) { - return -1; - } - - add_unix(&slirp->guestfwd_list, unixsock, *guest_addr, htons(guest_port)); - return 0; -#else - g_warn_if_reached(); - return -1; -#endif -} - -int slirp_add_guestfwd(Slirp *slirp, SlirpWriteCb write_cb, void *opaque, - struct in_addr *guest_addr, int guest_port) -{ - if (!check_guestfwd(slirp, guest_addr, guest_port)) { - return -1; - } - - add_guestfwd(&slirp->guestfwd_list, write_cb, opaque, *guest_addr, - htons(guest_port)); - return 0; -} - -int slirp_remove_guestfwd(Slirp *slirp, struct in_addr guest_addr, - int guest_port) -{ - return remove_guestfwd(&slirp->guestfwd_list, guest_addr, - htons(guest_port)); -} - -ssize_t slirp_send(struct socket *so, const void *buf, size_t len, int flags) -{ - if (so->s == -1 && so->guestfwd) { - /* XXX this blocks entire thread. Rewrite to use - * qemu_chr_fe_write and background I/O callbacks */ - so->guestfwd->write_cb(buf, len, so->guestfwd->opaque); - return len; - } - - if (so->s == -1) { - /* - * This should in theory not happen but it is hard to be - * sure because some code paths will end up with so->s == -1 - * on a failure but don't dispose of the struct socket. - * Check specifically, so we don't pass -1 to send(). - */ - errno = EBADF; - return -1; - } - - return send(so->s, buf, len, flags); -} - -struct socket *slirp_find_ctl_socket(Slirp *slirp, struct in_addr guest_addr, - int guest_port) -{ - struct socket *so; - - /* TODO: IPv6 */ - for (so = slirp->tcb.so_next; so != &slirp->tcb; so = so->so_next) { - if (so->so_faddr.s_addr == guest_addr.s_addr && - htons(so->so_fport) == guest_port) { - return so; - } - } - return NULL; -} - -size_t slirp_socket_can_recv(Slirp *slirp, struct in_addr guest_addr, - int guest_port) -{ - struct iovec iov[2]; - struct socket *so; - - so = slirp_find_ctl_socket(slirp, guest_addr, guest_port); - - if (!so || so->so_state & SS_NOFDREF) { - return 0; - } - - if (!CONN_CANFRCV(so) || so->so_snd.sb_cc >= (so->so_snd.sb_datalen / 2)) { - return 0; - } - - return sopreprbuf(so, iov, NULL); -} - -void slirp_socket_recv(Slirp *slirp, struct in_addr guest_addr, int guest_port, - const uint8_t *buf, int size) -{ - int ret; - struct socket *so = slirp_find_ctl_socket(slirp, guest_addr, guest_port); - - if (!so) - return; - - ret = soreadbuf(so, (const char *)buf, size); - - if (ret > 0) - tcp_output(sototcpcb(so)); -} - -void slirp_send_packet_all(Slirp *slirp, const void *buf, size_t len) -{ - ssize_t ret = slirp->cb->send_packet(buf, len, slirp->opaque); - - if (ret < 0) { - g_critical("Failed to send packet, ret: %ld", (long)ret); - } else if (ret < len) { - DEBUG_ERROR("send_packet() didn't send all data: %ld < %lu", (long)ret, - (unsigned long)len); - } -} diff --git a/src/network/slirp/slirp.h b/src/network/slirp/slirp.h deleted file mode 100644 index d996b53ed..000000000 --- a/src/network/slirp/slirp.h +++ /dev/null @@ -1,291 +0,0 @@ -/* SPDX-License-Identifier: BSD-3-Clause */ -#ifndef SLIRP_H -#define SLIRP_H - -#ifdef _WIN32 - -/* as defined in sdkddkver.h */ -#ifndef _WIN32_WINNT -#define _WIN32_WINNT 0x0600 /* Vista */ -#endif -/* reduces the number of implicitly included headers */ -#ifndef WIN32_LEAN_AND_MEAN -#define WIN32_LEAN_AND_MEAN -#endif - -#include -#include -#include -#include -#include - -#else -#if !defined(__HAIKU__) -#define O_BINARY 0 -#endif -#endif - -#ifndef _WIN32 -#include -#include -#include -#include -#include -#endif - -#ifdef __APPLE__ -#include -#endif - -/* Avoid conflicting with the libc insque() and remque(), which - have different prototypes. */ -#define insque slirp_insque -#define remque slirp_remque -#define quehead slirp_quehead - -#include "debug.h" -#include "util.h" - -#include "libslirp.h" -#include "ip.h" -#include "ip6.h" -#include "tcp.h" -#include "tcp_timer.h" -#include "tcp_var.h" -#include "tcpip.h" -#include "udp.h" -#include "ip_icmp.h" -#include "ip6_icmp.h" -#include "mbuf.h" -#include "sbuf.h" -#include "socket.h" -#include "if.h" -#include "main.h" -#include "misc.h" - -#include "bootp.h" -#include "tftp.h" - -#define ARPOP_REQUEST 1 /* ARP request */ -#define ARPOP_REPLY 2 /* ARP reply */ - -struct ethhdr { - unsigned char h_dest[ETH_ALEN]; /* destination eth addr */ - unsigned char h_source[ETH_ALEN]; /* source ether addr */ - unsigned short h_proto; /* packet type ID field */ -}; - -#if defined(_MSC_VER) && !defined (__clang__) -#pragma pack(push, 1) -#endif -struct slirp_arphdr { - unsigned short ar_hrd; /* format of hardware address */ - unsigned short ar_pro; /* format of protocol address */ - unsigned char ar_hln; /* length of hardware address */ - unsigned char ar_pln; /* length of protocol address */ - unsigned short ar_op; /* ARP opcode (command) */ - - /* - * Ethernet looks like this : This bit is variable sized however... - */ - unsigned char ar_sha[ETH_ALEN]; /* sender hardware address */ - uint32_t ar_sip; /* sender IP address */ - unsigned char ar_tha[ETH_ALEN]; /* target hardware address */ - uint32_t ar_tip; /* target IP address */ -} SLIRP_PACKED; -#if defined(_MSC_VER) && !defined (__clang__) -#pragma pack(pop) -#endif - -#define ARP_TABLE_SIZE 16 - -typedef struct ArpTable { - struct slirp_arphdr table[ARP_TABLE_SIZE]; - int next_victim; -} ArpTable; - -void arp_table_add(Slirp *slirp, uint32_t ip_addr, - const uint8_t ethaddr[ETH_ALEN]); - -bool arp_table_search(Slirp *slirp, uint32_t ip_addr, - uint8_t out_ethaddr[ETH_ALEN]); - -struct ndpentry { - unsigned char eth_addr[ETH_ALEN]; /* sender hardware address */ - struct in6_addr ip_addr; /* sender IP address */ -}; - -#define NDP_TABLE_SIZE 16 - -typedef struct NdpTable { - struct ndpentry table[NDP_TABLE_SIZE]; - int next_victim; -} NdpTable; - -void ndp_table_add(Slirp *slirp, struct in6_addr ip_addr, - uint8_t ethaddr[ETH_ALEN]); -bool ndp_table_search(Slirp *slirp, struct in6_addr ip_addr, - uint8_t out_ethaddr[ETH_ALEN]); - -struct Slirp { - unsigned time_fasttimo; - unsigned last_slowtimo; - bool do_slowtimo; - - bool in_enabled, in6_enabled; - - /* virtual network configuration */ - struct in_addr vnetwork_addr; - struct in_addr vnetwork_mask; - struct in_addr vhost_addr; - struct in6_addr vprefix_addr6; - uint8_t vprefix_len; - struct in6_addr vhost_addr6; - struct in_addr vdhcp_startaddr; - struct in_addr vnameserver_addr; - struct in6_addr vnameserver_addr6; - - struct in_addr client_ipaddr; - char client_hostname[33]; - - int restricted; - struct gfwd_list *guestfwd_list; - - int if_mtu; - int if_mru; - - bool disable_host_loopback; - - /* mbuf states */ - struct quehead m_freelist; - struct quehead m_usedlist; - int mbuf_alloced; - - /* if states */ - struct quehead if_fastq; /* fast queue (for interactive data) */ - struct quehead if_batchq; /* queue for non-interactive data */ - bool if_start_busy; /* avoid if_start recursion */ - - /* ip states */ - struct ipq ipq; /* ip reass. queue */ - uint16_t ip_id; /* ip packet ctr, for ids */ - - /* bootp/dhcp states */ - BOOTPClient bootp_clients[NB_BOOTP_CLIENTS]; - char *bootp_filename; - size_t vdnssearch_len; - uint8_t *vdnssearch; - char *vdomainname; - - /* tcp states */ - struct socket tcb; - struct socket *tcp_last_so; - tcp_seq tcp_iss; /* tcp initial send seq # */ - uint32_t tcp_now; /* for RFC 1323 timestamps */ - - /* udp states */ - struct socket udb; - struct socket *udp_last_so; - - /* icmp states */ - struct socket icmp; - struct socket *icmp_last_so; - - /* tftp states */ - char *tftp_prefix; - struct tftp_session tftp_sessions[TFTP_SESSIONS_MAX]; - char *tftp_server_name; - - ArpTable arp_table; - NdpTable ndp_table; - - GRand *grand; - void *ra_timer; - - bool enable_emu; - - const SlirpCb *cb; - void *opaque; - - struct sockaddr_in *outbound_addr; - struct sockaddr_in6 *outbound_addr6; - bool disable_dns; /* slirp will not redirect/serve any DNS packet */ -}; - -void if_start(Slirp *); - -int get_dns_addr(struct in_addr *pdns_addr); -int get_dns6_addr(struct in6_addr *pdns6_addr, uint32_t *scope_id); - -/* ncsi.c */ -void ncsi_input(Slirp *slirp, const uint8_t *pkt, int pkt_len); - -#ifndef _WIN32 -#include -#endif - - -extern bool slirp_do_keepalive; - -#define TCP_MAXIDLE (TCPTV_KEEPCNT * TCPTV_KEEPINTVL) - -/* dnssearch.c */ -int translate_dnssearch(Slirp *s, const char **names); - -/* cksum.c */ -int cksum(struct mbuf *m, int len); -int ip6_cksum(struct mbuf *m); - -/* if.c */ -void if_init(Slirp *); -void if_output(struct socket *, struct mbuf *); - -/* ip_input.c */ -void ip_init(Slirp *); -void ip_cleanup(Slirp *); -void ip_input(struct mbuf *); -void ip_slowtimo(Slirp *); -void ip_stripoptions(register struct mbuf *, struct mbuf *); - -/* ip_output.c */ -int ip_output(struct socket *, struct mbuf *); - -/* ip6_input.c */ -void ip6_init(Slirp *); -void ip6_cleanup(Slirp *); -void ip6_input(struct mbuf *); - -/* ip6_output */ -int ip6_output(struct socket *, struct mbuf *, int fast); - -/* tcp_input.c */ -void tcp_input(register struct mbuf *, int, struct socket *, unsigned short af); -int tcp_mss(register struct tcpcb *, unsigned); - -/* tcp_output.c */ -int tcp_output(register struct tcpcb *); -void tcp_setpersist(register struct tcpcb *); - -/* tcp_subr.c */ -void tcp_init(Slirp *); -void tcp_cleanup(Slirp *); -void tcp_template(struct tcpcb *); -void tcp_respond(struct tcpcb *, register struct tcpiphdr *, - register struct mbuf *, tcp_seq, tcp_seq, int, unsigned short); -struct tcpcb *tcp_newtcpcb(struct socket *); -struct tcpcb *tcp_close(register struct tcpcb *); -void tcp_sockclosed(struct tcpcb *); -int tcp_fconnect(struct socket *, unsigned short af); -void tcp_connect(struct socket *); -void tcp_attach(struct socket *); -uint8_t tcp_tos(struct socket *); -int tcp_emu(struct socket *, struct mbuf *); -int tcp_ctl(struct socket *); -struct tcpcb *tcp_drop(struct tcpcb *tp, int err); - -struct socket *slirp_find_ctl_socket(Slirp *slirp, struct in_addr guest_addr, - int guest_port); - -void slirp_send_packet_all(Slirp *slirp, const void *buf, size_t len); - -#endif diff --git a/src/network/slirp/socket.c b/src/network/slirp/socket.c deleted file mode 100644 index 36d005192..000000000 --- a/src/network/slirp/socket.c +++ /dev/null @@ -1,954 +0,0 @@ -/* SPDX-License-Identifier: BSD-3-Clause */ -/* - * Copyright (c) 1995 Danny Gasparovski. - */ - -#include "slirp.h" -#include "ip_icmp.h" -#ifdef __sun__ -#include -#endif - -static void sofcantrcvmore(struct socket *so); -static void sofcantsendmore(struct socket *so); - -struct socket *solookup(struct socket **last, struct socket *head, - struct sockaddr_storage *lhost, - struct sockaddr_storage *fhost) -{ - struct socket *so = *last; - - /* Optimisation */ - if (so != head && sockaddr_equal(&(so->lhost.ss), lhost) && - (!fhost || sockaddr_equal(&so->fhost.ss, fhost))) { - return so; - } - - for (so = head->so_next; so != head; so = so->so_next) { - if (sockaddr_equal(&(so->lhost.ss), lhost) && - (!fhost || sockaddr_equal(&so->fhost.ss, fhost))) { - *last = so; - return so; - } - } - - return (struct socket *)NULL; -} - -/* - * Create a new socket, initialise the fields - * It is the responsibility of the caller to - * insque() it into the correct linked-list - */ -struct socket *socreate(Slirp *slirp) -{ - struct socket *so = g_new(struct socket, 1); - - memset(so, 0, sizeof(struct socket)); - so->so_state = SS_NOFDREF; - so->s = -1; - so->slirp = slirp; - so->pollfds_idx = -1; - - return so; -} - -/* - * Remove references to so from the given message queue. - */ -static void soqfree(struct socket *so, struct quehead *qh) -{ - struct mbuf *ifq; - - for (ifq = (struct mbuf *)qh->qh_link; (struct quehead *)ifq != qh; - ifq = ifq->ifq_next) { - if (ifq->ifq_so == so) { - struct mbuf *ifm; - ifq->ifq_so = NULL; - for (ifm = ifq->ifs_next; ifm != ifq; ifm = ifm->ifs_next) { - ifm->ifq_so = NULL; - } - } - } -} - -/* - * remque and free a socket, clobber cache - */ -void sofree(struct socket *so) -{ - Slirp *slirp = so->slirp; - - soqfree(so, &slirp->if_fastq); - soqfree(so, &slirp->if_batchq); - - if (so == slirp->tcp_last_so) { - slirp->tcp_last_so = &slirp->tcb; - } else if (so == slirp->udp_last_so) { - slirp->udp_last_so = &slirp->udb; - } else if (so == slirp->icmp_last_so) { - slirp->icmp_last_so = &slirp->icmp; - } - m_free(so->so_m); - - if (so->so_next && so->so_prev) - remque(so); /* crashes if so is not in a queue */ - - if (so->so_tcpcb) { - g_free(so->so_tcpcb); - } - g_free(so); -} - -size_t sopreprbuf(struct socket *so, struct iovec *iov, int *np) -{ - int n, lss, total; - struct sbuf *sb = &so->so_snd; - int len = sb->sb_datalen - sb->sb_cc; - int mss = so->so_tcpcb->t_maxseg; - - DEBUG_CALL("sopreprbuf"); - DEBUG_ARG("so = %p", so); - - if (len <= 0) - return 0; - - iov[0].iov_base = sb->sb_wptr; - iov[1].iov_base = NULL; - iov[1].iov_len = 0; - if (sb->sb_wptr < sb->sb_rptr) { - iov[0].iov_len = sb->sb_rptr - sb->sb_wptr; - /* Should never succeed, but... */ - if (iov[0].iov_len > len) - iov[0].iov_len = len; - if (iov[0].iov_len > mss) - iov[0].iov_len -= iov[0].iov_len % mss; - n = 1; - } else { - iov[0].iov_len = (sb->sb_data + sb->sb_datalen) - sb->sb_wptr; - /* Should never succeed, but... */ - if (iov[0].iov_len > len) - iov[0].iov_len = len; - len -= iov[0].iov_len; - if (len) { - iov[1].iov_base = sb->sb_data; - iov[1].iov_len = sb->sb_rptr - sb->sb_data; - if (iov[1].iov_len > len) - iov[1].iov_len = len; - total = iov[0].iov_len + iov[1].iov_len; - if (total > mss) { - lss = total % mss; - if (iov[1].iov_len > lss) { - iov[1].iov_len -= lss; - n = 2; - } else { - lss -= iov[1].iov_len; - iov[0].iov_len -= lss; - n = 1; - } - } else - n = 2; - } else { - if (iov[0].iov_len > mss) - iov[0].iov_len -= iov[0].iov_len % mss; - n = 1; - } - } - if (np) - *np = n; - - return iov[0].iov_len + (n - 1) * iov[1].iov_len; -} - -/* - * Read from so's socket into sb_snd, updating all relevant sbuf fields - * NOTE: This will only be called if it is select()ed for reading, so - * a read() of 0 (or less) means it's disconnected - */ -int soread(struct socket *so) -{ - int n = 0, nn; - size_t buf_len; - struct sbuf *sb = &so->so_snd; - struct iovec iov[2] = {{0, 0}, {0, 0}}; - - DEBUG_CALL("soread"); - DEBUG_ARG("so = %p", so); - - /* - * No need to check if there's enough room to read. - * soread wouldn't have been called if there weren't - */ - buf_len = sopreprbuf(so, iov, &n); - assert(buf_len != 0); - - nn = recv(so->s, iov[0].iov_base, iov[0].iov_len, 0); - if (nn <= 0) { - if (nn < 0 && (errno == EINTR || errno == EAGAIN)) - return 0; - else { - int err; - socklen_t elen = sizeof err; - struct sockaddr_storage addr; - struct sockaddr *paddr = (struct sockaddr *)&addr; - socklen_t alen = sizeof addr; - - err = errno; - if (nn == 0) { - int shutdown_wr = so->so_state & SS_FCANTSENDMORE; - - if (!shutdown_wr && getpeername(so->s, paddr, &alen) < 0) { - err = errno; - } else { - getsockopt(so->s, SOL_SOCKET, SO_ERROR, &err, &elen); - } - } - - DEBUG_MISC(" --- soread() disconnected, nn = %d, errno = %d-%s", nn, - errno, strerror(errno)); - sofcantrcvmore(so); - - if (err == ECONNRESET || err == ECONNREFUSED || err == ENOTCONN || - err == EPIPE) { - tcp_drop(sototcpcb(so), err); - } else { - tcp_sockclosed(sototcpcb(so)); - } - return -1; - } - } - - /* - * If there was no error, try and read the second time round - * We read again if n = 2 (ie, there's another part of the buffer) - * and we read as much as we could in the first read - * We don't test for <= 0 this time, because there legitimately - * might not be any more data (since the socket is non-blocking), - * a close will be detected on next iteration. - * A return of -1 won't (shouldn't) happen, since it didn't happen above - */ - if (n == 2 && nn == iov[0].iov_len) { - int ret; - ret = recv(so->s, iov[1].iov_base, iov[1].iov_len, 0); - if (ret > 0) - nn += ret; - } - - DEBUG_MISC(" ... read nn = %d bytes", nn); - - /* Update fields */ - sb->sb_cc += nn; - sb->sb_wptr += nn; - if (sb->sb_wptr >= (sb->sb_data + sb->sb_datalen)) - sb->sb_wptr -= sb->sb_datalen; - return nn; -} - -int soreadbuf(struct socket *so, const char *buf, int size) -{ - int n, nn, copy = size; - struct sbuf *sb = &so->so_snd; - struct iovec iov[2] = {{0, 0}, {0, 0}}; - - DEBUG_CALL("soreadbuf"); - DEBUG_ARG("so = %p", so); - - /* - * No need to check if there's enough room to read. - * soread wouldn't have been called if there weren't - */ - assert(size > 0); - if (sopreprbuf(so, iov, &n) < size) - goto err; - - nn = MIN(iov[0].iov_len, copy); - memcpy(iov[0].iov_base, buf, nn); - - copy -= nn; - buf += nn; - - if (copy == 0) - goto done; - - memcpy(iov[1].iov_base, buf, copy); - -done: - /* Update fields */ - sb->sb_cc += size; - sb->sb_wptr += size; - if (sb->sb_wptr >= (sb->sb_data + sb->sb_datalen)) - sb->sb_wptr -= sb->sb_datalen; - return size; -err: - - sofcantrcvmore(so); - tcp_sockclosed(sototcpcb(so)); - g_critical("soreadbuf buffer too small"); - return -1; -} - -/* - * Get urgent data - * - * When the socket is created, we set it SO_OOBINLINE, - * so when OOB data arrives, we soread() it and everything - * in the send buffer is sent as urgent data - */ -int sorecvoob(struct socket *so) -{ - struct tcpcb *tp = sototcpcb(so); - int ret; - - DEBUG_CALL("sorecvoob"); - DEBUG_ARG("so = %p", so); - - /* - * We take a guess at how much urgent data has arrived. - * In most situations, when urgent data arrives, the next - * read() should get all the urgent data. This guess will - * be wrong however if more data arrives just after the - * urgent data, or the read() doesn't return all the - * urgent data. - */ - ret = soread(so); - if (ret > 0) { - tp->snd_up = tp->snd_una + so->so_snd.sb_cc; - tp->t_force = 1; - tcp_output(tp); - tp->t_force = 0; - } - - return ret; -} - -/* - * Send urgent data - * There's a lot duplicated code here, but... - */ -int sosendoob(struct socket *so) -{ - struct sbuf *sb = &so->so_rcv; - char buff[2048]; /* XXX Shouldn't be sending more oob data than this */ - - int n; - - DEBUG_CALL("sosendoob"); - DEBUG_ARG("so = %p", so); - DEBUG_ARG("sb->sb_cc = %d", sb->sb_cc); - - if (so->so_urgc > 2048) - so->so_urgc = 2048; /* XXXX */ - - if (sb->sb_rptr < sb->sb_wptr) { - /* We can send it directly */ - n = slirp_send(so, sb->sb_rptr, so->so_urgc, - (MSG_OOB)); /* |MSG_DONTWAIT)); */ - } else { - /* - * Since there's no sendv or sendtov like writev, - * we must copy all data to a linear buffer then - * send it all - */ - uint32_t urgc = so->so_urgc; - int len = (sb->sb_data + sb->sb_datalen) - sb->sb_rptr; - if (len > urgc) { - len = urgc; - } - memcpy(buff, sb->sb_rptr, len); - urgc -= len; - if (urgc) { - n = sb->sb_wptr - sb->sb_data; - if (n > urgc) { - n = urgc; - } - memcpy((buff + len), sb->sb_data, n); - len += n; - } - n = slirp_send(so, buff, len, (MSG_OOB)); /* |MSG_DONTWAIT)); */ -#ifdef DEBUG - if (n != len) { - DEBUG_ERROR("Didn't send all data urgently XXXXX"); - } -#endif - } - - if (n < 0) { - return n; - } - so->so_urgc -= n; - DEBUG_MISC(" ---2 sent %d bytes urgent data, %d urgent bytes left", n, - so->so_urgc); - - sb->sb_cc -= n; - sb->sb_rptr += n; - if (sb->sb_rptr >= (sb->sb_data + sb->sb_datalen)) - sb->sb_rptr -= sb->sb_datalen; - - return n; -} - -/* - * Write data from so_rcv to so's socket, - * updating all sbuf field as necessary - */ -int sowrite(struct socket *so) -{ - int n, nn; - struct sbuf *sb = &so->so_rcv; - int len = sb->sb_cc; - struct iovec iov[2] = {{0, 0}, {0, 0}}; - - DEBUG_CALL("sowrite"); - DEBUG_ARG("so = %p", so); - - if (so->so_urgc) { - uint32_t expected = so->so_urgc; - if (sosendoob(so) < expected) { - /* Treat a short write as a fatal error too, - * rather than continuing on and sending the urgent - * data as if it were non-urgent and leaving the - * so_urgc count wrong. - */ - goto err_disconnected; - } - if (sb->sb_cc == 0) - return 0; - } - - /* - * No need to check if there's something to write, - * sowrite wouldn't have been called otherwise - */ - - iov[0].iov_base = sb->sb_rptr; - iov[1].iov_base = NULL; - iov[1].iov_len = 0; - if (sb->sb_rptr < sb->sb_wptr) { - iov[0].iov_len = sb->sb_wptr - sb->sb_rptr; - /* Should never succeed, but... */ - if (iov[0].iov_len > len) - iov[0].iov_len = len; - n = 1; - } else { - iov[0].iov_len = (sb->sb_data + sb->sb_datalen) - sb->sb_rptr; - if (iov[0].iov_len > len) - iov[0].iov_len = len; - len -= iov[0].iov_len; - if (len) { - iov[1].iov_base = sb->sb_data; - iov[1].iov_len = sb->sb_wptr - sb->sb_data; - if (iov[1].iov_len > len) - iov[1].iov_len = len; - n = 2; - } else - n = 1; - } - /* Check if there's urgent data to send, and if so, send it */ - - nn = slirp_send(so, iov[0].iov_base, iov[0].iov_len, 0); - /* This should never happen, but people tell me it does *shrug* */ - if (nn < 0 && (errno == EAGAIN || errno == EINTR)) - return 0; - - if (nn <= 0) { - goto err_disconnected; - } - - if (n == 2 && nn == iov[0].iov_len) { - int ret; - ret = slirp_send(so, iov[1].iov_base, iov[1].iov_len, 0); - if (ret > 0) - nn += ret; - } - DEBUG_MISC(" ... wrote nn = %d bytes", nn); - - /* Update sbuf */ - sb->sb_cc -= nn; - sb->sb_rptr += nn; - if (sb->sb_rptr >= (sb->sb_data + sb->sb_datalen)) - sb->sb_rptr -= sb->sb_datalen; - - /* - * If in DRAIN mode, and there's no more data, set - * it CANTSENDMORE - */ - if ((so->so_state & SS_FWDRAIN) && sb->sb_cc == 0) - sofcantsendmore(so); - - return nn; - -err_disconnected: - DEBUG_MISC(" --- sowrite disconnected, so->so_state = %x, errno = %d", - so->so_state, errno); - sofcantsendmore(so); - tcp_sockclosed(sototcpcb(so)); - return -1; -} - -/* - * recvfrom() a UDP socket - */ -void sorecvfrom(struct socket *so) -{ - struct sockaddr_storage addr; - struct sockaddr_storage saddr, daddr; - socklen_t addrlen = sizeof(struct sockaddr_storage); - - DEBUG_CALL("sorecvfrom"); - DEBUG_ARG("so = %p", so); - - if (so->so_type == IPPROTO_ICMP) { /* This is a "ping" reply */ - char buff[256]; - int len; - - len = recvfrom(so->s, buff, 256, 0, (struct sockaddr *)&addr, &addrlen); - /* XXX Check if reply is "correct"? */ - - if (len == -1 || len == 0) { - uint8_t code = ICMP_UNREACH_PORT; - - if (errno == EHOSTUNREACH) - code = ICMP_UNREACH_HOST; - else if (errno == ENETUNREACH) - code = ICMP_UNREACH_NET; - - DEBUG_MISC(" udp icmp rx errno = %d-%s", errno, strerror(errno)); - icmp_send_error(so->so_m, ICMP_UNREACH, code, 0, strerror(errno)); - } else { - icmp_reflect(so->so_m); - so->so_m = NULL; /* Don't m_free() it again! */ - } - /* No need for this socket anymore, udp_detach it */ - udp_detach(so); - } else { /* A "normal" UDP packet */ - struct mbuf *m; - int len; -#ifdef _WIN32 - unsigned long n; -#else - int n; -#endif - - if (ioctlsocket(so->s, FIONREAD, &n) != 0) { - DEBUG_MISC(" ioctlsocket errno = %d-%s\n", errno, strerror(errno)); - return; - } - if (n == 0) { - return; - } - - m = m_get(so->slirp); - if (!m) { - return; - } - switch (so->so_ffamily) { - case AF_INET: - m->m_data += IF_MAXLINKHDR + sizeof(struct udpiphdr); - break; - case AF_INET6: - m->m_data += - IF_MAXLINKHDR + sizeof(struct ip6) + sizeof(struct udphdr); - break; - default: - g_assert_not_reached(); - } - - /* - * XXX Shouldn't FIONREAD packets destined for port 53, - * but I don't know the max packet size for DNS lookups - */ - len = M_FREEROOM(m); - /* if (so->so_fport != htons(53)) { */ - - if (n > len) { - n = (m->m_data - m->m_dat) + m->m_len + n + 1; - m_inc(m, n); - len = M_FREEROOM(m); - } - /* } */ - - m->m_len = recvfrom(so->s, m->m_data, len, 0, (struct sockaddr *)&addr, - &addrlen); - DEBUG_MISC(" did recvfrom %d, errno = %d-%s", m->m_len, errno, - strerror(errno)); - if (m->m_len < 0) { - /* Report error as ICMP */ - switch (so->so_lfamily) { - uint8_t code; - case AF_INET: - code = ICMP_UNREACH_PORT; - - if (errno == EHOSTUNREACH) { - code = ICMP_UNREACH_HOST; - } else if (errno == ENETUNREACH) { - code = ICMP_UNREACH_NET; - } - - DEBUG_MISC(" rx error, tx icmp ICMP_UNREACH:%i", code); - icmp_send_error(so->so_m, ICMP_UNREACH, code, 0, - strerror(errno)); - break; - case AF_INET6: - code = ICMP6_UNREACH_PORT; - - if (errno == EHOSTUNREACH) { - code = ICMP6_UNREACH_ADDRESS; - } else if (errno == ENETUNREACH) { - code = ICMP6_UNREACH_NO_ROUTE; - } - - DEBUG_MISC(" rx error, tx icmp6 ICMP_UNREACH:%i", code); - icmp6_send_error(so->so_m, ICMP6_UNREACH, code); - break; - default: - g_assert_not_reached(); - } - m_free(m); - } else { - /* - * Hack: domain name lookup will be used the most for UDP, - * and since they'll only be used once there's no need - * for the 4 minute (or whatever) timeout... So we time them - * out much quicker (10 seconds for now...) - */ - if (so->so_expire) { - if (so->so_fport == htons(53)) - so->so_expire = curtime + SO_EXPIREFAST; - else - so->so_expire = curtime + SO_EXPIRE; - } - - /* - * If this packet was destined for CTL_ADDR, - * make it look like that's where it came from - */ - saddr = addr; - sotranslate_in(so, &saddr); - daddr = so->lhost.ss; - - switch (so->so_ffamily) { - case AF_INET: - udp_output(so, m, (struct sockaddr_in *)&saddr, - (struct sockaddr_in *)&daddr, so->so_iptos); - break; - case AF_INET6: - udp6_output(so, m, (struct sockaddr_in6 *)&saddr, - (struct sockaddr_in6 *)&daddr); - break; - default: - g_assert_not_reached(); - } - } /* rx error */ - } /* if ping packet */ -} - -/* - * sendto() a socket - */ -int sosendto(struct socket *so, struct mbuf *m) -{ - int ret; - struct sockaddr_storage addr; - - DEBUG_CALL("sosendto"); - DEBUG_ARG("so = %p", so); - DEBUG_ARG("m = %p", m); - - addr = so->fhost.ss; - DEBUG_CALL(" sendto()ing)"); - if (sotranslate_out(so, &addr) < 0) { - return -1; - } - - /* Don't care what port we get */ - ret = sendto(so->s, m->m_data, m->m_len, 0, (struct sockaddr *)&addr, - sockaddr_size(&addr)); - if (ret < 0) - return -1; - - /* - * Kill the socket if there's no reply in 4 minutes, - * but only if it's an expirable socket - */ - if (so->so_expire) - so->so_expire = curtime + SO_EXPIRE; - so->so_state &= SS_PERSISTENT_MASK; - so->so_state |= SS_ISFCONNECTED; /* So that it gets select()ed */ - return 0; -} - -/* - * Listen for incoming TCP connections - */ -struct socket *tcp_listen(Slirp *slirp, uint32_t haddr, unsigned hport, - uint32_t laddr, unsigned lport, int flags) -{ - /* TODO: IPv6 */ - struct sockaddr_in addr; - struct socket *so; - int s, opt = 1; - socklen_t addrlen = sizeof(addr); - memset(&addr, 0, addrlen); - - DEBUG_CALL("tcp_listen"); - DEBUG_ARG("haddr = %s", inet_ntoa((struct in_addr){ .s_addr = haddr })); - DEBUG_ARG("hport = %d", ntohs(hport)); - DEBUG_ARG("laddr = %s", inet_ntoa((struct in_addr){ .s_addr = laddr })); - DEBUG_ARG("lport = %d", ntohs(lport)); - DEBUG_ARG("flags = %x", flags); - - so = socreate(slirp); - - /* Don't tcp_attach... we don't need so_snd nor so_rcv */ - if ((so->so_tcpcb = tcp_newtcpcb(so)) == NULL) { - g_free(so); - return NULL; - } - insque(so, &slirp->tcb); - - /* - * SS_FACCEPTONCE sockets must time out. - */ - if (flags & SS_FACCEPTONCE) - so->so_tcpcb->t_timer[TCPT_KEEP] = TCPTV_KEEP_INIT * 2; - - so->so_state &= SS_PERSISTENT_MASK; - so->so_state |= (SS_FACCEPTCONN | flags); - so->so_lfamily = AF_INET; - so->so_lport = lport; /* Kept in network format */ - so->so_laddr.s_addr = laddr; /* Ditto */ - - addr.sin_family = AF_INET; - addr.sin_addr.s_addr = haddr; - addr.sin_port = hport; - - if (((s = slirp_socket(AF_INET, SOCK_STREAM, 0)) < 0) || - (slirp_socket_set_fast_reuse(s) < 0) || - (bind(s, (struct sockaddr *)&addr, sizeof(addr)) < 0) || - (listen(s, 1) < 0)) { - int tmperrno = errno; /* Don't clobber the real reason we failed */ - - if (s >= 0) { - closesocket(s); - } - sofree(so); - /* Restore the real errno */ -#ifdef _WIN32 - WSASetLastError(tmperrno); -#else - errno = tmperrno; -#endif - return NULL; - } - setsockopt(s, SOL_SOCKET, SO_OOBINLINE, &opt, sizeof(int)); - opt = 1; - setsockopt(s, IPPROTO_TCP, TCP_NODELAY, &opt, sizeof(int)); - - getsockname(s, (struct sockaddr *)&addr, &addrlen); - so->so_ffamily = AF_INET; - so->so_fport = addr.sin_port; - if (addr.sin_addr.s_addr == 0 || - addr.sin_addr.s_addr == loopback_addr.s_addr) - so->so_faddr = slirp->vhost_addr; - else - so->so_faddr = addr.sin_addr; - - so->s = s; - return so; -} - -/* - * Various session state calls - * XXX Should be #define's - * The socket state stuff needs work, these often get call 2 or 3 - * times each when only 1 was needed - */ -void soisfconnecting(struct socket *so) -{ - so->so_state &= ~(SS_NOFDREF | SS_ISFCONNECTED | SS_FCANTRCVMORE | - SS_FCANTSENDMORE | SS_FWDRAIN); - so->so_state |= SS_ISFCONNECTING; /* Clobber other states */ -} - -void soisfconnected(struct socket *so) -{ - so->so_state &= ~(SS_ISFCONNECTING | SS_FWDRAIN | SS_NOFDREF); - so->so_state |= SS_ISFCONNECTED; /* Clobber other states */ -} - -static void sofcantrcvmore(struct socket *so) -{ - if ((so->so_state & SS_NOFDREF) == 0) { - shutdown(so->s, 0); - } - so->so_state &= ~(SS_ISFCONNECTING); - if (so->so_state & SS_FCANTSENDMORE) { - so->so_state &= SS_PERSISTENT_MASK; - so->so_state |= SS_NOFDREF; /* Don't select it */ - } else { - so->so_state |= SS_FCANTRCVMORE; - } -} - -static void sofcantsendmore(struct socket *so) -{ - if ((so->so_state & SS_NOFDREF) == 0) { - shutdown(so->s, 1); /* send FIN to fhost */ - } - so->so_state &= ~(SS_ISFCONNECTING); - if (so->so_state & SS_FCANTRCVMORE) { - so->so_state &= SS_PERSISTENT_MASK; - so->so_state |= SS_NOFDREF; /* as above */ - } else { - so->so_state |= SS_FCANTSENDMORE; - } -} - -/* - * Set write drain mode - * Set CANTSENDMORE once all data has been write()n - */ -void sofwdrain(struct socket *so) -{ - if (so->so_rcv.sb_cc) - so->so_state |= SS_FWDRAIN; - else - sofcantsendmore(so); -} - -static bool sotranslate_out4(Slirp *s, struct socket *so, struct sockaddr_in *sin) -{ - if (!s->disable_dns && so->so_faddr.s_addr == s->vnameserver_addr.s_addr) { - return so->so_fport == htons(53) && get_dns_addr(&sin->sin_addr) >= 0; - } - - if (so->so_faddr.s_addr == s->vhost_addr.s_addr || - so->so_faddr.s_addr == 0xffffffff) { - if (s->disable_host_loopback) { - return false; - } - - sin->sin_addr = loopback_addr; - } - - return true; -} - -static bool sotranslate_out6(Slirp *s, struct socket *so, struct sockaddr_in6 *sin) -{ - if (!s->disable_dns && in6_equal(&so->so_faddr6, &s->vnameserver_addr6)) { - uint32_t scope_id; - if (so->so_fport == htons(53) && get_dns6_addr(&sin->sin6_addr, &scope_id) >= 0) { - sin->sin6_scope_id = scope_id; - return true; - } - return false; - } - - if (in6_equal_net(&so->so_faddr6, &s->vprefix_addr6, s->vprefix_len) || - in6_equal(&so->so_faddr6, &(struct in6_addr)ALLNODES_MULTICAST)) { - if (s->disable_host_loopback) { - return false; - } - - sin->sin6_addr = in6addr_loopback; - } - - return true; -} - - -/* - * Translate addr in host addr when it is a virtual address - */ -int sotranslate_out(struct socket *so, struct sockaddr_storage *addr) -{ - bool ok = true; - - switch (addr->ss_family) { - case AF_INET: - ok = sotranslate_out4(so->slirp, so, (struct sockaddr_in *)addr); - break; - case AF_INET6: - ok = sotranslate_out6(so->slirp, so, (struct sockaddr_in6 *)addr); - break; - } - - if (!ok) { - errno = EPERM; - return -1; - } - - return 0; -} - -void sotranslate_in(struct socket *so, struct sockaddr_storage *addr) -{ - Slirp *slirp = so->slirp; - struct sockaddr_in *sin = (struct sockaddr_in *)addr; - struct sockaddr_in6 *sin6 = (struct sockaddr_in6 *)addr; - - switch (addr->ss_family) { - case AF_INET: - if ((so->so_faddr.s_addr & slirp->vnetwork_mask.s_addr) == - slirp->vnetwork_addr.s_addr) { - uint32_t inv_mask = ~slirp->vnetwork_mask.s_addr; - - if ((so->so_faddr.s_addr & inv_mask) == inv_mask) { - sin->sin_addr = slirp->vhost_addr; - } else if (sin->sin_addr.s_addr == loopback_addr.s_addr || - so->so_faddr.s_addr != slirp->vhost_addr.s_addr) { - sin->sin_addr = so->so_faddr; - } - } - break; - - case AF_INET6: - if (in6_equal_net(&so->so_faddr6, &slirp->vprefix_addr6, - slirp->vprefix_len)) { - if (in6_equal(&sin6->sin6_addr, &in6addr_loopback) || - !in6_equal(&so->so_faddr6, &slirp->vhost_addr6)) { - sin6->sin6_addr = so->so_faddr6; - } - } - break; - - default: - break; - } -} - -/* - * Translate connections from localhost to the real hostname - */ -void sotranslate_accept(struct socket *so) -{ - Slirp *slirp = so->slirp; - - switch (so->so_ffamily) { - case AF_INET: - if (so->so_faddr.s_addr == INADDR_ANY || - (so->so_faddr.s_addr & loopback_mask) == - (loopback_addr.s_addr & loopback_mask)) { - so->so_faddr = slirp->vhost_addr; - } - break; - - case AF_INET6: - if (in6_equal(&so->so_faddr6, &in6addr_any) || - in6_equal(&so->so_faddr6, &in6addr_loopback)) { - so->so_faddr6 = slirp->vhost_addr6; - } - break; - - default: - break; - } -} - -void sodrop(struct socket *s, int num) -{ - if (sbdrop(&s->so_snd, num)) { - s->slirp->cb->notify(s->slirp->opaque); - } -} diff --git a/src/network/slirp/socket.h b/src/network/slirp/socket.h deleted file mode 100644 index a6a1e5e21..000000000 --- a/src/network/slirp/socket.h +++ /dev/null @@ -1,164 +0,0 @@ -/* SPDX-License-Identifier: BSD-3-Clause */ -/* - * Copyright (c) 1995 Danny Gasparovski. - */ - -#ifndef SLIRP_SOCKET_H -#define SLIRP_SOCKET_H - -#include "misc.h" - -#define SO_EXPIRE 240000 -#define SO_EXPIREFAST 10000 - -/* - * Our socket structure - */ - -union slirp_sockaddr { - struct sockaddr_storage ss; - struct sockaddr_in sin; - struct sockaddr_in6 sin6; -}; - -struct socket { - struct socket *so_next, *so_prev; /* For a linked list of sockets */ - - int s; /* The actual socket */ - struct gfwd_list *guestfwd; - - int pollfds_idx; /* GPollFD GArray index */ - - Slirp *slirp; /* managing slirp instance */ - - /* XXX union these with not-yet-used sbuf params */ - struct mbuf *so_m; /* Pointer to the original SYN packet, - * for non-blocking connect()'s, and - * PING reply's */ - struct tcpiphdr *so_ti; /* Pointer to the original ti within - * so_mconn, for non-blocking connections */ - uint32_t so_urgc; - union slirp_sockaddr fhost; /* Foreign host */ -#define so_faddr fhost.sin.sin_addr -#define so_fport fhost.sin.sin_port -#define so_faddr6 fhost.sin6.sin6_addr -#define so_fport6 fhost.sin6.sin6_port -#define so_ffamily fhost.ss.ss_family - - union slirp_sockaddr lhost; /* Local host */ -#define so_laddr lhost.sin.sin_addr -#define so_lport lhost.sin.sin_port -#define so_laddr6 lhost.sin6.sin6_addr -#define so_lport6 lhost.sin6.sin6_port -#define so_lfamily lhost.ss.ss_family - - uint8_t so_iptos; /* Type of service */ - uint8_t so_emu; /* Is the socket emulated? */ - - uint8_t so_type; /* Type of socket, UDP or TCP */ - int32_t so_state; /* internal state flags SS_*, below */ - - struct tcpcb *so_tcpcb; /* pointer to TCP protocol control block */ - unsigned so_expire; /* When the socket will expire */ - - int so_queued; /* Number of packets queued from this socket */ - int so_nqueued; /* Number of packets queued in a row - * Used to determine when to "downgrade" a session - * from fastq to batchq */ - - struct sbuf so_rcv; /* Receive buffer */ - struct sbuf so_snd; /* Send buffer */ -}; - - -/* - * Socket state bits. (peer means the host on the Internet, - * local host means the host on the other end of the modem) - */ -#define SS_NOFDREF 0x001 /* No fd reference */ - -#define SS_ISFCONNECTING \ - 0x002 /* Socket is connecting to peer (non-blocking connect()'s) */ -#define SS_ISFCONNECTED 0x004 /* Socket is connected to peer */ -#define SS_FCANTRCVMORE \ - 0x008 /* Socket can't receive more from peer (for half-closes) */ -#define SS_FCANTSENDMORE \ - 0x010 /* Socket can't send more to peer (for half-closes) */ -#define SS_FWDRAIN \ - 0x040 /* We received a FIN, drain data and set SS_FCANTSENDMORE */ - -#define SS_CTL 0x080 -#define SS_FACCEPTCONN \ - 0x100 /* Socket is accepting connections from a host on the internet */ -#define SS_FACCEPTONCE \ - 0x200 /* If set, the SS_FACCEPTCONN socket will die after one accept */ - -#define SS_PERSISTENT_MASK 0xf000 /* Unremovable state bits */ -#define SS_HOSTFWD 0x1000 /* Socket describes host->guest forwarding */ -#define SS_INCOMING \ - 0x2000 /* Connection was initiated by a host on the internet */ - -static inline int sockaddr_equal(struct sockaddr_storage *a, - struct sockaddr_storage *b) -{ - if (a->ss_family != b->ss_family) { - return 0; - } - - switch (a->ss_family) { - case AF_INET: { - struct sockaddr_in *a4 = (struct sockaddr_in *)a; - struct sockaddr_in *b4 = (struct sockaddr_in *)b; - return a4->sin_addr.s_addr == b4->sin_addr.s_addr && - a4->sin_port == b4->sin_port; - } - case AF_INET6: { - struct sockaddr_in6 *a6 = (struct sockaddr_in6 *)a; - struct sockaddr_in6 *b6 = (struct sockaddr_in6 *)b; - return (in6_equal(&a6->sin6_addr, &b6->sin6_addr) && - a6->sin6_port == b6->sin6_port); - } - default: - g_assert_not_reached(); - } - - return 0; -} - -static inline socklen_t sockaddr_size(struct sockaddr_storage *a) -{ - switch (a->ss_family) { - case AF_INET: - return sizeof(struct sockaddr_in); - case AF_INET6: - return sizeof(struct sockaddr_in6); - default: - g_assert_not_reached(); - } -} - -struct socket *solookup(struct socket **, struct socket *, - struct sockaddr_storage *, struct sockaddr_storage *); -struct socket *socreate(Slirp *); -void sofree(struct socket *); -int soread(struct socket *); -int sorecvoob(struct socket *); -int sosendoob(struct socket *); -int sowrite(struct socket *); -void sorecvfrom(struct socket *); -int sosendto(struct socket *, struct mbuf *); -struct socket *tcp_listen(Slirp *, uint32_t, unsigned, uint32_t, unsigned, int); -void soisfconnecting(register struct socket *); -void soisfconnected(register struct socket *); -void sofwdrain(struct socket *); -struct iovec; /* For win32 */ -size_t sopreprbuf(struct socket *so, struct iovec *iov, int *np); -int soreadbuf(struct socket *so, const char *buf, int size); - -int sotranslate_out(struct socket *, struct sockaddr_storage *); -void sotranslate_in(struct socket *, struct sockaddr_storage *); -void sotranslate_accept(struct socket *); -void sodrop(struct socket *, int num); - - -#endif /* SLIRP_SOCKET_H */ diff --git a/src/network/slirp/state.c b/src/network/slirp/state.c deleted file mode 100644 index 22af77b25..000000000 --- a/src/network/slirp/state.c +++ /dev/null @@ -1,379 +0,0 @@ -/* SPDX-License-Identifier: MIT */ -/* - * libslirp - * - * Copyright (c) 2004-2008 Fabrice Bellard - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL - * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -#include "slirp.h" -#include "vmstate.h" -#include "stream.h" - -static int slirp_tcp_post_load(void *opaque, int version) -{ - tcp_template((struct tcpcb *)opaque); - - return 0; -} - -static const VMStateDescription vmstate_slirp_tcp = { - .name = "slirp-tcp", - .version_id = 0, - .post_load = slirp_tcp_post_load, - .fields = (VMStateField[]){ VMSTATE_INT16(t_state, struct tcpcb), - VMSTATE_INT16_ARRAY(t_timer, struct tcpcb, - TCPT_NTIMERS), - VMSTATE_INT16(t_rxtshift, struct tcpcb), - VMSTATE_INT16(t_rxtcur, struct tcpcb), - VMSTATE_INT16(t_dupacks, struct tcpcb), - VMSTATE_UINT16(t_maxseg, struct tcpcb), - VMSTATE_UINT8(t_force, struct tcpcb), - VMSTATE_UINT16(t_flags, struct tcpcb), - VMSTATE_UINT32(snd_una, struct tcpcb), - VMSTATE_UINT32(snd_nxt, struct tcpcb), - VMSTATE_UINT32(snd_up, struct tcpcb), - VMSTATE_UINT32(snd_wl1, struct tcpcb), - VMSTATE_UINT32(snd_wl2, struct tcpcb), - VMSTATE_UINT32(iss, struct tcpcb), - VMSTATE_UINT32(snd_wnd, struct tcpcb), - VMSTATE_UINT32(rcv_wnd, struct tcpcb), - VMSTATE_UINT32(rcv_nxt, struct tcpcb), - VMSTATE_UINT32(rcv_up, struct tcpcb), - VMSTATE_UINT32(irs, struct tcpcb), - VMSTATE_UINT32(rcv_adv, struct tcpcb), - VMSTATE_UINT32(snd_max, struct tcpcb), - VMSTATE_UINT32(snd_cwnd, struct tcpcb), - VMSTATE_UINT32(snd_ssthresh, struct tcpcb), - VMSTATE_INT16(t_idle, struct tcpcb), - VMSTATE_INT16(t_rtt, struct tcpcb), - VMSTATE_UINT32(t_rtseq, struct tcpcb), - VMSTATE_INT16(t_srtt, struct tcpcb), - VMSTATE_INT16(t_rttvar, struct tcpcb), - VMSTATE_UINT16(t_rttmin, struct tcpcb), - VMSTATE_UINT32(max_sndwnd, struct tcpcb), - VMSTATE_UINT8(t_oobflags, struct tcpcb), - VMSTATE_UINT8(t_iobc, struct tcpcb), - VMSTATE_INT16(t_softerror, struct tcpcb), - VMSTATE_UINT8(snd_scale, struct tcpcb), - VMSTATE_UINT8(rcv_scale, struct tcpcb), - VMSTATE_UINT8(request_r_scale, struct tcpcb), - VMSTATE_UINT8(requested_s_scale, struct tcpcb), - VMSTATE_UINT32(ts_recent, struct tcpcb), - VMSTATE_UINT32(ts_recent_age, struct tcpcb), - VMSTATE_UINT32(last_ack_sent, struct tcpcb), - VMSTATE_END_OF_LIST() } -}; - -/* The sbuf has a pair of pointers that are migrated as offsets; - * we calculate the offsets and restore the pointers using - * pre_save/post_load on a tmp structure. - */ -struct sbuf_tmp { - struct sbuf *parent; - uint32_t roff, woff; -}; - -static int sbuf_tmp_pre_save(void *opaque) -{ - struct sbuf_tmp *tmp = opaque; - tmp->woff = tmp->parent->sb_wptr - tmp->parent->sb_data; - tmp->roff = tmp->parent->sb_rptr - tmp->parent->sb_data; - - return 0; -} - -static int sbuf_tmp_post_load(void *opaque, int version) -{ - struct sbuf_tmp *tmp = opaque; - uint32_t requested_len = tmp->parent->sb_datalen; - - /* Allocate the buffer space used by the field after the tmp */ - sbreserve(tmp->parent, tmp->parent->sb_datalen); - - if (tmp->woff >= requested_len || tmp->roff >= requested_len) { - g_critical("invalid sbuf offsets r/w=%u/%u len=%u", tmp->roff, - tmp->woff, requested_len); - return -EINVAL; - } - - tmp->parent->sb_wptr = tmp->parent->sb_data + tmp->woff; - tmp->parent->sb_rptr = tmp->parent->sb_data + tmp->roff; - - return 0; -} - - -static const VMStateDescription vmstate_slirp_sbuf_tmp = { - .name = "slirp-sbuf-tmp", - .post_load = sbuf_tmp_post_load, - .pre_save = sbuf_tmp_pre_save, - .version_id = 0, - .fields = (VMStateField[]){ VMSTATE_UINT32(woff, struct sbuf_tmp), - VMSTATE_UINT32(roff, struct sbuf_tmp), - VMSTATE_END_OF_LIST() } -}; - -static const VMStateDescription vmstate_slirp_sbuf = { - .name = "slirp-sbuf", - .version_id = 0, - .fields = (VMStateField[]){ VMSTATE_UINT32(sb_cc, struct sbuf), - VMSTATE_UINT32(sb_datalen, struct sbuf), - VMSTATE_WITH_TMP(struct sbuf, struct sbuf_tmp, - vmstate_slirp_sbuf_tmp), - VMSTATE_VBUFFER_UINT32(sb_data, struct sbuf, 0, - NULL, sb_datalen), - VMSTATE_END_OF_LIST() } -}; - -static bool slirp_older_than_v4(void *opaque, int version_id) -{ - return version_id < 4; -} - -static bool slirp_family_inet(void *opaque, int version_id) -{ - union slirp_sockaddr *ssa = (union slirp_sockaddr *)opaque; - return ssa->ss.ss_family == AF_INET; -} - -static int slirp_socket_pre_load(void *opaque) -{ - struct socket *so = opaque; - - tcp_attach(so); - /* Older versions don't load these fields */ - so->so_ffamily = AF_INET; - so->so_lfamily = AF_INET; - return 0; -} - -#ifndef _WIN32 -#define VMSTATE_SIN4_ADDR(f, s, t) VMSTATE_UINT32_TEST(f, s, t) -#else -/* Win uses u_long rather than uint32_t - but it's still 32bits long */ -#define VMSTATE_SIN4_ADDR(f, s, t) \ - VMSTATE_SINGLE_TEST(f, s, t, 0, slirp_vmstate_info_uint32, u_long) -#endif - -/* The OS provided ss_family field isn't that portable; it's size - * and type varies (16/8 bit, signed, unsigned) - * and the values it contains aren't fully portable. - */ -typedef struct SS_FamilyTmpStruct { - union slirp_sockaddr *parent; - uint16_t portable_family; -} SS_FamilyTmpStruct; - -#define SS_FAMILY_MIG_IPV4 2 /* Linux, BSD, Win... */ -#define SS_FAMILY_MIG_IPV6 10 /* Linux */ -#define SS_FAMILY_MIG_OTHER 0xffff - -static int ss_family_pre_save(void *opaque) -{ - SS_FamilyTmpStruct *tss = opaque; - - tss->portable_family = SS_FAMILY_MIG_OTHER; - - if (tss->parent->ss.ss_family == AF_INET) { - tss->portable_family = SS_FAMILY_MIG_IPV4; - } else if (tss->parent->ss.ss_family == AF_INET6) { - tss->portable_family = SS_FAMILY_MIG_IPV6; - } - - return 0; -} - -static int ss_family_post_load(void *opaque, int version_id) -{ - SS_FamilyTmpStruct *tss = opaque; - - switch (tss->portable_family) { - case SS_FAMILY_MIG_IPV4: - tss->parent->ss.ss_family = AF_INET; - break; - case SS_FAMILY_MIG_IPV6: - case 23: /* compatibility: AF_INET6 from mingw */ - case 28: /* compatibility: AF_INET6 from FreeBSD sys/socket.h */ - tss->parent->ss.ss_family = AF_INET6; - break; - default: - g_critical("invalid ss_family type %x", tss->portable_family); - return -EINVAL; - } - - return 0; -} - -static const VMStateDescription vmstate_slirp_ss_family = { - .name = "slirp-socket-addr/ss_family", - .pre_save = ss_family_pre_save, - .post_load = ss_family_post_load, - .fields = - (VMStateField[]){ VMSTATE_UINT16(portable_family, SS_FamilyTmpStruct), - VMSTATE_END_OF_LIST() } -}; - -static const VMStateDescription vmstate_slirp_socket_addr = { - .name = "slirp-socket-addr", - .version_id = 4, - .fields = - (VMStateField[]){ - VMSTATE_WITH_TMP(union slirp_sockaddr, SS_FamilyTmpStruct, - vmstate_slirp_ss_family), - VMSTATE_SIN4_ADDR(sin.sin_addr.s_addr, union slirp_sockaddr, - slirp_family_inet), - VMSTATE_UINT16_TEST(sin.sin_port, union slirp_sockaddr, - slirp_family_inet), - -#if 0 - /* Untested: Needs checking by someone with IPv6 test */ - VMSTATE_BUFFER_TEST(sin6.sin6_addr, union slirp_sockaddr, - slirp_family_inet6), - VMSTATE_UINT16_TEST(sin6.sin6_port, union slirp_sockaddr, - slirp_family_inet6), - VMSTATE_UINT32_TEST(sin6.sin6_flowinfo, union slirp_sockaddr, - slirp_family_inet6), - VMSTATE_UINT32_TEST(sin6.sin6_scope_id, union slirp_sockaddr, - slirp_family_inet6), -#endif - - VMSTATE_END_OF_LIST() } -}; - -static const VMStateDescription vmstate_slirp_socket = { - .name = "slirp-socket", - .version_id = 4, - .pre_load = slirp_socket_pre_load, - .fields = - (VMStateField[]){ - VMSTATE_UINT32(so_urgc, struct socket), - /* Pre-v4 versions */ - VMSTATE_SIN4_ADDR(so_faddr.s_addr, struct socket, - slirp_older_than_v4), - VMSTATE_SIN4_ADDR(so_laddr.s_addr, struct socket, - slirp_older_than_v4), - VMSTATE_UINT16_TEST(so_fport, struct socket, slirp_older_than_v4), - VMSTATE_UINT16_TEST(so_lport, struct socket, slirp_older_than_v4), - /* v4 and newer */ - VMSTATE_STRUCT(fhost, struct socket, 4, vmstate_slirp_socket_addr, - union slirp_sockaddr), - VMSTATE_STRUCT(lhost, struct socket, 4, vmstate_slirp_socket_addr, - union slirp_sockaddr), - - VMSTATE_UINT8(so_iptos, struct socket), - VMSTATE_UINT8(so_emu, struct socket), - VMSTATE_UINT8(so_type, struct socket), - VMSTATE_INT32(so_state, struct socket), - VMSTATE_STRUCT(so_rcv, struct socket, 0, vmstate_slirp_sbuf, - struct sbuf), - VMSTATE_STRUCT(so_snd, struct socket, 0, vmstate_slirp_sbuf, - struct sbuf), - VMSTATE_STRUCT_POINTER(so_tcpcb, struct socket, vmstate_slirp_tcp, - struct tcpcb), - VMSTATE_END_OF_LIST() } -}; - -static const VMStateDescription vmstate_slirp_bootp_client = { - .name = "slirp_bootpclient", - .fields = (VMStateField[]){ VMSTATE_UINT16(allocated, BOOTPClient), - VMSTATE_BUFFER(macaddr, BOOTPClient), - VMSTATE_END_OF_LIST() } -}; - -static const VMStateDescription vmstate_slirp = { - .name = "slirp", - .version_id = 4, - .fields = (VMStateField[]){ VMSTATE_UINT16_V(ip_id, Slirp, 2), - VMSTATE_STRUCT_ARRAY( - bootp_clients, Slirp, NB_BOOTP_CLIENTS, 3, - vmstate_slirp_bootp_client, BOOTPClient), - VMSTATE_END_OF_LIST() } -}; - -void slirp_state_save(Slirp *slirp, SlirpWriteCb write_cb, void *opaque) -{ - struct gfwd_list *ex_ptr; - SlirpOStream f = { - .write_cb = write_cb, - .opaque = opaque, - }; - - for (ex_ptr = slirp->guestfwd_list; ex_ptr; ex_ptr = ex_ptr->ex_next) - if (ex_ptr->write_cb) { - struct socket *so; - so = slirp_find_ctl_socket(slirp, ex_ptr->ex_addr, - ntohs(ex_ptr->ex_fport)); - if (!so) { - continue; - } - - slirp_ostream_write_u8(&f, 42); - slirp_vmstate_save_state(&f, &vmstate_slirp_socket, so); - } - slirp_ostream_write_u8(&f, 0); - - slirp_vmstate_save_state(&f, &vmstate_slirp, slirp); -} - - -int slirp_state_load(Slirp *slirp, int version_id, SlirpReadCb read_cb, - void *opaque) -{ - struct gfwd_list *ex_ptr; - SlirpIStream f = { - .read_cb = read_cb, - .opaque = opaque, - }; - - while (slirp_istream_read_u8(&f)) { - int ret; - struct socket *so = socreate(slirp); - - ret = - slirp_vmstate_load_state(&f, &vmstate_slirp_socket, so, version_id); - if (ret < 0) { - return ret; - } - - if ((so->so_faddr.s_addr & slirp->vnetwork_mask.s_addr) != - slirp->vnetwork_addr.s_addr) { - return -EINVAL; - } - for (ex_ptr = slirp->guestfwd_list; ex_ptr; ex_ptr = ex_ptr->ex_next) { - if (ex_ptr->write_cb && - so->so_faddr.s_addr == ex_ptr->ex_addr.s_addr && - so->so_fport == ex_ptr->ex_fport) { - break; - } - } - if (!ex_ptr) { - return -EINVAL; - } - - so->guestfwd = ex_ptr; - } - - return slirp_vmstate_load_state(&f, &vmstate_slirp, slirp, version_id); -} - -int slirp_state_version(void) -{ - return 4; -} diff --git a/src/network/slirp/stream.c b/src/network/slirp/stream.c deleted file mode 100644 index 541986e6c..000000000 --- a/src/network/slirp/stream.c +++ /dev/null @@ -1,120 +0,0 @@ -/* SPDX-License-Identifier: MIT */ -/* - * libslirp io streams - * - * Copyright (c) 2018 Red Hat, Inc. - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL - * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -#include "stream.h" -#include - -bool slirp_istream_read(SlirpIStream *f, void *buf, size_t size) -{ - return f->read_cb(buf, size, f->opaque) == size; -} - -bool slirp_ostream_write(SlirpOStream *f, const void *buf, size_t size) -{ - return f->write_cb(buf, size, f->opaque) == size; -} - -uint8_t slirp_istream_read_u8(SlirpIStream *f) -{ - uint8_t b; - - if (slirp_istream_read(f, &b, sizeof(b))) { - return b; - } - - return 0; -} - -bool slirp_ostream_write_u8(SlirpOStream *f, uint8_t b) -{ - return slirp_ostream_write(f, &b, sizeof(b)); -} - -uint16_t slirp_istream_read_u16(SlirpIStream *f) -{ - uint16_t b; - - if (slirp_istream_read(f, &b, sizeof(b))) { - return GUINT16_FROM_BE(b); - } - - return 0; -} - -bool slirp_ostream_write_u16(SlirpOStream *f, uint16_t b) -{ - b = GUINT16_TO_BE(b); - return slirp_ostream_write(f, &b, sizeof(b)); -} - -uint32_t slirp_istream_read_u32(SlirpIStream *f) -{ - uint32_t b; - - if (slirp_istream_read(f, &b, sizeof(b))) { - return GUINT32_FROM_BE(b); - } - - return 0; -} - -bool slirp_ostream_write_u32(SlirpOStream *f, uint32_t b) -{ - b = GUINT32_TO_BE(b); - return slirp_ostream_write(f, &b, sizeof(b)); -} - -int16_t slirp_istream_read_i16(SlirpIStream *f) -{ - int16_t b; - - if (slirp_istream_read(f, &b, sizeof(b))) { - return GINT16_FROM_BE(b); - } - - return 0; -} - -bool slirp_ostream_write_i16(SlirpOStream *f, int16_t b) -{ - b = GINT16_TO_BE(b); - return slirp_ostream_write(f, &b, sizeof(b)); -} - -int32_t slirp_istream_read_i32(SlirpIStream *f) -{ - int32_t b; - - if (slirp_istream_read(f, &b, sizeof(b))) { - return GINT32_FROM_BE(b); - } - - return 0; -} - -bool slirp_ostream_write_i32(SlirpOStream *f, int32_t b) -{ - b = GINT32_TO_BE(b); - return slirp_ostream_write(f, &b, sizeof(b)); -} diff --git a/src/network/slirp/stream.h b/src/network/slirp/stream.h deleted file mode 100644 index 08bb5b661..000000000 --- a/src/network/slirp/stream.h +++ /dev/null @@ -1,35 +0,0 @@ -/* SPDX-License-Identifier: BSD-3-Clause */ -#ifndef STREAM_H_ -#define STREAM_H_ - -#include "libslirp.h" - -typedef struct SlirpIStream { - SlirpReadCb read_cb; - void *opaque; -} SlirpIStream; - -typedef struct SlirpOStream { - SlirpWriteCb write_cb; - void *opaque; -} SlirpOStream; - -bool slirp_istream_read(SlirpIStream *f, void *buf, size_t size); -bool slirp_ostream_write(SlirpOStream *f, const void *buf, size_t size); - -uint8_t slirp_istream_read_u8(SlirpIStream *f); -bool slirp_ostream_write_u8(SlirpOStream *f, uint8_t b); - -uint16_t slirp_istream_read_u16(SlirpIStream *f); -bool slirp_ostream_write_u16(SlirpOStream *f, uint16_t b); - -uint32_t slirp_istream_read_u32(SlirpIStream *f); -bool slirp_ostream_write_u32(SlirpOStream *f, uint32_t b); - -int16_t slirp_istream_read_i16(SlirpIStream *f); -bool slirp_ostream_write_i16(SlirpOStream *f, int16_t b); - -int32_t slirp_istream_read_i32(SlirpIStream *f); -bool slirp_ostream_write_i32(SlirpOStream *f, int32_t b); - -#endif /* STREAM_H_ */ diff --git a/src/network/slirp/tcp.h b/src/network/slirp/tcp.h deleted file mode 100644 index 9c4a6b693..000000000 --- a/src/network/slirp/tcp.h +++ /dev/null @@ -1,169 +0,0 @@ -/* SPDX-License-Identifier: BSD-3-Clause */ -/* - * Copyright (c) 1982, 1986, 1993 - * The Regents of the University of California. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. Neither the name of the University nor the names of its contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - * - * @(#)tcp.h 8.1 (Berkeley) 6/10/93 - * tcp.h,v 1.3 1994/08/21 05:27:34 paul Exp - */ - -#ifndef TCP_H -#define TCP_H - -#include - -typedef uint32_t tcp_seq; - -#define PR_SLOWHZ 2 /* 2 slow timeouts per second (approx) */ -#define PR_FASTHZ 5 /* 5 fast timeouts per second (not important) */ - -#define TCP_SNDSPACE 1024 * 128 -#define TCP_RCVSPACE 1024 * 128 -#define TCP_MAXSEG_MAX 32768 - -/* - * TCP header. - * Per RFC 793, September, 1981. - */ -#define tcphdr slirp_tcphdr -struct tcphdr { - uint16_t th_sport; /* source port */ - uint16_t th_dport; /* destination port */ - tcp_seq th_seq; /* sequence number */ - tcp_seq th_ack; /* acknowledgement number */ -#if G_BYTE_ORDER == G_BIG_ENDIAN - uint8_t th_off : 4, /* data offset */ - th_x2 : 4; /* (unused) */ -#else - uint8_t th_x2 : 4, /* (unused) */ - th_off : 4; /* data offset */ -#endif - uint8_t th_flags; - uint16_t th_win; /* window */ - uint16_t th_sum; /* checksum */ - uint16_t th_urp; /* urgent pointer */ -}; - -#include "tcp_var.h" - -#ifndef TH_FIN -#define TH_FIN 0x01 -#define TH_SYN 0x02 -#define TH_RST 0x04 -#define TH_PUSH 0x08 -#define TH_ACK 0x10 -#define TH_URG 0x20 -#endif - -#ifndef TCPOPT_EOL -#define TCPOPT_EOL 0 -#define TCPOPT_NOP 1 -#define TCPOPT_MAXSEG 2 -#define TCPOPT_WINDOW 3 -#define TCPOPT_SACK_PERMITTED 4 /* Experimental */ -#define TCPOPT_SACK 5 /* Experimental */ -#define TCPOPT_TIMESTAMP 8 - -#define TCPOPT_TSTAMP_HDR \ - (TCPOPT_NOP << 24 | TCPOPT_NOP << 16 | TCPOPT_TIMESTAMP << 8 | \ - TCPOLEN_TIMESTAMP) -#endif - -#ifndef TCPOLEN_MAXSEG -#define TCPOLEN_MAXSEG 4 -#define TCPOLEN_WINDOW 3 -#define TCPOLEN_SACK_PERMITTED 2 -#define TCPOLEN_TIMESTAMP 10 -#define TCPOLEN_TSTAMP_APPA (TCPOLEN_TIMESTAMP + 2) /* appendix A */ -#endif - -#undef TCP_MAXWIN -#define TCP_MAXWIN 65535 /* largest value for (unscaled) window */ - -#undef TCP_MAX_WINSHIFT -#define TCP_MAX_WINSHIFT 14 /* maximum window shift */ - -/* - * User-settable options (used with setsockopt). - * - * We don't use the system headers on unix because we have conflicting - * local structures. We can't avoid the system definitions on Windows, - * so we undefine them. - */ -#undef TCP_NODELAY -#define TCP_NODELAY 0x01 /* don't delay send to coalesce packets */ -#undef TCP_MAXSEG - -/* - * TCP FSM state definitions. - * Per RFC793, September, 1981. - */ - -#define TCP_NSTATES 11 - -#define TCPS_CLOSED 0 /* closed */ -#define TCPS_LISTEN 1 /* listening for connection */ -#define TCPS_SYN_SENT 2 /* active, have sent syn */ -#define TCPS_SYN_RECEIVED 3 /* have send and received syn */ -/* states < TCPS_ESTABLISHED are those where connections not established */ -#define TCPS_ESTABLISHED 4 /* established */ -#define TCPS_CLOSE_WAIT 5 /* rcvd fin, waiting for close */ -/* states > TCPS_CLOSE_WAIT are those where user has closed */ -#define TCPS_FIN_WAIT_1 6 /* have closed, sent fin */ -#define TCPS_CLOSING 7 /* closed xchd FIN; await FIN ACK */ -#define TCPS_LAST_ACK 8 /* had fin and close; await FIN ACK */ -/* states > TCPS_CLOSE_WAIT && < TCPS_FIN_WAIT_2 await ACK of FIN */ -#define TCPS_FIN_WAIT_2 9 /* have closed, fin is acked */ -#define TCPS_TIME_WAIT 10 /* in 2*msl quiet wait after close */ - -#define TCPS_HAVERCVDSYN(s) ((s) >= TCPS_SYN_RECEIVED) -#define TCPS_HAVEESTABLISHED(s) ((s) >= TCPS_ESTABLISHED) -#define TCPS_HAVERCVDFIN(s) ((s) >= TCPS_TIME_WAIT) - -/* - * TCP sequence numbers are 32 bit integers operated - * on with modular arithmetic. These macros can be - * used to compare such integers. - */ -#define SEQ_LT(a, b) ((int)((a) - (b)) < 0) -#define SEQ_LEQ(a, b) ((int)((a) - (b)) <= 0) -#define SEQ_GT(a, b) ((int)((a) - (b)) > 0) -#define SEQ_GEQ(a, b) ((int)((a) - (b)) >= 0) - -/* - * Macros to initialize tcp sequence numbers for - * send and receive from initial send and receive - * sequence numbers. - */ -#define tcp_rcvseqinit(tp) (tp)->rcv_adv = (tp)->rcv_nxt = (tp)->irs + 1 - -#define tcp_sendseqinit(tp) \ - (tp)->snd_una = (tp)->snd_nxt = (tp)->snd_max = (tp)->snd_up = (tp)->iss - -#define TCP_ISSINCR (125 * 1024) /* increment for tcp_iss each second */ - -#endif diff --git a/src/network/slirp/tcp_input.c b/src/network/slirp/tcp_input.c deleted file mode 100644 index d55b0c81d..000000000 --- a/src/network/slirp/tcp_input.c +++ /dev/null @@ -1,1539 +0,0 @@ -/* SPDX-License-Identifier: BSD-3-Clause */ -/* - * Copyright (c) 1982, 1986, 1988, 1990, 1993, 1994 - * The Regents of the University of California. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. Neither the name of the University nor the names of its contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - * - * @(#)tcp_input.c 8.5 (Berkeley) 4/10/94 - * tcp_input.c,v 1.10 1994/10/13 18:36:32 wollman Exp - */ - -/* - * Changes and additions relating to SLiRP - * Copyright (c) 1995 Danny Gasparovski. - */ - -#include "slirp.h" -#include "ip_icmp.h" - -#define TCPREXMTTHRESH 3 - -#define TCP_PAWS_IDLE (24 * 24 * 60 * 60 * PR_SLOWHZ) - -/* for modulo comparisons of timestamps */ -#define TSTMP_LT(a, b) ((int)((a) - (b)) < 0) -#define TSTMP_GEQ(a, b) ((int)((a) - (b)) >= 0) - -/* - * Insert segment ti into reassembly queue of tcp with - * control block tp. Return TH_FIN if reassembly now includes - * a segment with FIN. The macro form does the common case inline - * (segment is the next to be received on an established connection, - * and the queue is empty), avoiding linkage into and removal - * from the queue and repetition of various conversions. - * Set DELACK for segments received in order, but ack immediately - * when segments are out of order (so fast retransmit can work). - */ -#define TCP_REASS(tp, ti, m, so, flags) \ - { \ - if ((ti)->ti_seq == (tp)->rcv_nxt && tcpfrag_list_empty(tp) && \ - (tp)->t_state == TCPS_ESTABLISHED) { \ - tp->t_flags |= TF_DELACK; \ - (tp)->rcv_nxt += (ti)->ti_len; \ - flags = (ti)->ti_flags & TH_FIN; \ - if (so->so_emu) { \ - if (tcp_emu((so), (m))) \ - sbappend(so, (m)); \ - } else \ - sbappend((so), (m)); \ - } else { \ - (flags) = tcp_reass((tp), (ti), (m)); \ - tp->t_flags |= TF_ACKNOW; \ - } \ - } - -static void tcp_dooptions(struct tcpcb *tp, uint8_t *cp, int cnt, - struct tcpiphdr *ti); -static void tcp_xmit_timer(register struct tcpcb *tp, int rtt); - -static int tcp_reass(register struct tcpcb *tp, register struct tcpiphdr *ti, - struct mbuf *m) -{ - register struct tcpiphdr *q; - struct socket *so = tp->t_socket; - int flags; - - /* - * Call with ti==NULL after become established to - * force pre-ESTABLISHED data up to user socket. - */ - if (ti == NULL) - goto present; - - /* - * Find a segment which begins after this one does. - */ - for (q = tcpfrag_list_first(tp); !tcpfrag_list_end(q, tp); - q = tcpiphdr_next(q)) - if (SEQ_GT(q->ti_seq, ti->ti_seq)) - break; - - /* - * If there is a preceding segment, it may provide some of - * our data already. If so, drop the data from the incoming - * segment. If it provides all of our data, drop us. - */ - if (!tcpfrag_list_end(tcpiphdr_prev(q), tp)) { - register int i; - q = tcpiphdr_prev(q); - /* conversion to int (in i) handles seq wraparound */ - i = q->ti_seq + q->ti_len - ti->ti_seq; - if (i > 0) { - if (i >= ti->ti_len) { - m_free(m); - /* - * Try to present any queued data - * at the left window edge to the user. - * This is needed after the 3-WHS - * completes. - */ - goto present; /* ??? */ - } - m_adj(m, i); - ti->ti_len -= i; - ti->ti_seq += i; - } - q = tcpiphdr_next(q); - } - ti->ti_mbuf = m; - - /* - * While we overlap succeeding segments trim them or, - * if they are completely covered, dequeue them. - */ - while (!tcpfrag_list_end(q, tp)) { - register int i = (ti->ti_seq + ti->ti_len) - q->ti_seq; - if (i <= 0) - break; - if (i < q->ti_len) { - q->ti_seq += i; - q->ti_len -= i; - m_adj(q->ti_mbuf, i); - break; - } - q = tcpiphdr_next(q); - m = tcpiphdr_prev(q)->ti_mbuf; - remque(tcpiphdr2qlink(tcpiphdr_prev(q))); - m_free(m); - } - - /* - * Stick new segment in its place. - */ - insque(tcpiphdr2qlink(ti), tcpiphdr2qlink(tcpiphdr_prev(q))); - -present: - /* - * Present data to user, advancing rcv_nxt through - * completed sequence space. - */ - if (!TCPS_HAVEESTABLISHED(tp->t_state)) - return (0); - ti = tcpfrag_list_first(tp); - if (tcpfrag_list_end(ti, tp) || ti->ti_seq != tp->rcv_nxt) - return (0); - if (tp->t_state == TCPS_SYN_RECEIVED && ti->ti_len) - return (0); - do { - tp->rcv_nxt += ti->ti_len; - flags = ti->ti_flags & TH_FIN; - remque(tcpiphdr2qlink(ti)); - m = ti->ti_mbuf; - ti = tcpiphdr_next(ti); - if (so->so_state & SS_FCANTSENDMORE) - m_free(m); - else { - if (so->so_emu) { - if (tcp_emu(so, m)) - sbappend(so, m); - } else - sbappend(so, m); - } - } while (ti != (struct tcpiphdr *)tp && ti->ti_seq == tp->rcv_nxt); - return (flags); -} - -/* - * TCP input routine, follows pages 65-76 of the - * protocol specification dated September, 1981 very closely. - */ -void tcp_input(struct mbuf *m, int iphlen, struct socket *inso, - unsigned short af) -{ - struct ip save_ip, *ip; - struct ip6 save_ip6, *ip6; - register struct tcpiphdr *ti; - char *optp = NULL; - int optlen = 0; - int len, tlen, off; - register struct tcpcb *tp = NULL; - register int tiflags; - struct socket *so = NULL; - int todrop, acked, ourfinisacked, needoutput = 0; - int iss = 0; - uint32_t tiwin; - int ret; - struct sockaddr_storage lhost, fhost; - struct sockaddr_in *lhost4, *fhost4; - struct sockaddr_in6 *lhost6, *fhost6; - struct gfwd_list *ex_ptr; - Slirp *slirp; - - DEBUG_CALL("tcp_input"); - DEBUG_ARG("m = %p iphlen = %2d inso = %p", m, iphlen, inso); - - /* - * If called with m == 0, then we're continuing the connect - */ - if (m == NULL) { - so = inso; - slirp = so->slirp; - - /* Re-set a few variables */ - tp = sototcpcb(so); - m = so->so_m; - so->so_m = NULL; - ti = so->so_ti; - tiwin = ti->ti_win; - tiflags = ti->ti_flags; - - goto cont_conn; - } - slirp = m->slirp; - - ip = mtod(m, struct ip *); - ip6 = mtod(m, struct ip6 *); - - switch (af) { - case AF_INET: - if (iphlen > sizeof(struct ip)) { - ip_stripoptions(m, (struct mbuf *)0); - iphlen = sizeof(struct ip); - } - /* XXX Check if too short */ - - - /* - * Save a copy of the IP header in case we want restore it - * for sending an ICMP error message in response. - */ - save_ip = *ip; - save_ip.ip_len += iphlen; - - /* - * Get IP and TCP header together in first mbuf. - * Note: IP leaves IP header in first mbuf. - */ - m->m_data -= - sizeof(struct tcpiphdr) - sizeof(struct ip) - sizeof(struct tcphdr); - m->m_len += - sizeof(struct tcpiphdr) - sizeof(struct ip) - sizeof(struct tcphdr); - ti = mtod(m, struct tcpiphdr *); - - /* - * Checksum extended TCP header and data. - */ - tlen = ip->ip_len; - tcpiphdr2qlink(ti)->next = tcpiphdr2qlink(ti)->prev = NULL; - memset(&ti->ih_mbuf, 0, sizeof(struct mbuf_ptr)); - memset(&ti->ti, 0, sizeof(ti->ti)); - ti->ti_x0 = 0; - ti->ti_src = save_ip.ip_src; - ti->ti_dst = save_ip.ip_dst; - ti->ti_pr = save_ip.ip_p; - ti->ti_len = htons((uint16_t)tlen); - break; - - case AF_INET6: - /* - * Save a copy of the IP header in case we want restore it - * for sending an ICMP error message in response. - */ - save_ip6 = *ip6; - /* - * Get IP and TCP header together in first mbuf. - * Note: IP leaves IP header in first mbuf. - */ - m->m_data -= sizeof(struct tcpiphdr) - - (sizeof(struct ip6) + sizeof(struct tcphdr)); - m->m_len += sizeof(struct tcpiphdr) - - (sizeof(struct ip6) + sizeof(struct tcphdr)); - ti = mtod(m, struct tcpiphdr *); - - tlen = ip6->ip_pl; - tcpiphdr2qlink(ti)->next = tcpiphdr2qlink(ti)->prev = NULL; - memset(&ti->ih_mbuf, 0, sizeof(struct mbuf_ptr)); - memset(&ti->ti, 0, sizeof(ti->ti)); - ti->ti_x0 = 0; - ti->ti_src6 = save_ip6.ip_src; - ti->ti_dst6 = save_ip6.ip_dst; - ti->ti_nh6 = save_ip6.ip_nh; - ti->ti_len = htons((uint16_t)tlen); - break; - - default: - g_assert_not_reached(); - } - - len = ((sizeof(struct tcpiphdr) - sizeof(struct tcphdr)) + tlen); - if (cksum(m, len)) { - goto drop; - } - - /* - * Check that TCP offset makes sense, - * pull out TCP options and adjust length. XXX - */ - off = ti->ti_off << 2; - if (off < sizeof(struct tcphdr) || off > tlen) { - goto drop; - } - tlen -= off; - ti->ti_len = tlen; - if (off > sizeof(struct tcphdr)) { - optlen = off - sizeof(struct tcphdr); - optp = mtod(m, char *) + sizeof(struct tcpiphdr); - } - tiflags = ti->ti_flags; - - /* - * Convert TCP protocol specific fields to host format. - */ - NTOHL(ti->ti_seq); - NTOHL(ti->ti_ack); - NTOHS(ti->ti_win); - NTOHS(ti->ti_urp); - - /* - * Drop TCP, IP headers and TCP options. - */ - m->m_data += sizeof(struct tcpiphdr) + off - sizeof(struct tcphdr); - m->m_len -= sizeof(struct tcpiphdr) + off - sizeof(struct tcphdr); - - /* - * Locate pcb for segment. - */ -findso: - lhost.ss_family = af; - fhost.ss_family = af; - switch (af) { - case AF_INET: - lhost4 = (struct sockaddr_in *)&lhost; - lhost4->sin_addr = ti->ti_src; - lhost4->sin_port = ti->ti_sport; - fhost4 = (struct sockaddr_in *)&fhost; - fhost4->sin_addr = ti->ti_dst; - fhost4->sin_port = ti->ti_dport; - break; - case AF_INET6: - lhost6 = (struct sockaddr_in6 *)&lhost; - lhost6->sin6_addr = ti->ti_src6; - lhost6->sin6_port = ti->ti_sport; - fhost6 = (struct sockaddr_in6 *)&fhost; - fhost6->sin6_addr = ti->ti_dst6; - fhost6->sin6_port = ti->ti_dport; - break; - default: - g_assert_not_reached(); - } - - so = solookup(&slirp->tcp_last_so, &slirp->tcb, &lhost, &fhost); - - /* - * If the state is CLOSED (i.e., TCB does not exist) then - * all data in the incoming segment is discarded. - * If the TCB exists but is in CLOSED state, it is embryonic, - * but should either do a listen or a connect soon. - * - * state == CLOSED means we've done socreate() but haven't - * attached it to a protocol yet... - * - * XXX If a TCB does not exist, and the TH_SYN flag is - * the only flag set, then create a session, mark it - * as if it was LISTENING, and continue... - */ - if (so == NULL) { - /* TODO: IPv6 */ - if (slirp->restricted) { - /* Any hostfwds will have an existing socket, so we only get here - * for non-hostfwd connections. These should be dropped, unless it - * happens to be a guestfwd. - */ - for (ex_ptr = slirp->guestfwd_list; ex_ptr; - ex_ptr = ex_ptr->ex_next) { - if (ex_ptr->ex_fport == ti->ti_dport && - ti->ti_dst.s_addr == ex_ptr->ex_addr.s_addr) { - break; - } - } - if (!ex_ptr) { - goto dropwithreset; - } - } - - if ((tiflags & (TH_SYN | TH_FIN | TH_RST | TH_URG | TH_ACK)) != TH_SYN) - goto dropwithreset; - - so = socreate(slirp); - tcp_attach(so); - - sbreserve(&so->so_snd, TCP_SNDSPACE); - sbreserve(&so->so_rcv, TCP_RCVSPACE); - - so->lhost.ss = lhost; - so->fhost.ss = fhost; - - so->so_iptos = tcp_tos(so); - if (so->so_iptos == 0) { - switch (af) { - case AF_INET: - so->so_iptos = ((struct ip *)ti)->ip_tos; - break; - case AF_INET6: - break; - default: - g_assert_not_reached(); - } - } - - tp = sototcpcb(so); - tp->t_state = TCPS_LISTEN; - } - - /* - * If this is a still-connecting socket, this probably - * a retransmit of the SYN. Whether it's a retransmit SYN - * or something else, we nuke it. - */ - if (so->so_state & SS_ISFCONNECTING) - goto drop; - - tp = sototcpcb(so); - - /* XXX Should never fail */ - if (tp == NULL) - goto dropwithreset; - if (tp->t_state == TCPS_CLOSED) - goto drop; - - tiwin = ti->ti_win; - - /* - * Segment received on connection. - * Reset idle time and keep-alive timer. - */ - tp->t_idle = 0; - if (slirp_do_keepalive) - tp->t_timer[TCPT_KEEP] = TCPTV_KEEPINTVL; - else - tp->t_timer[TCPT_KEEP] = TCPTV_KEEP_IDLE; - - /* - * Process options if not in LISTEN state, - * else do it below (after getting remote address). - */ - if (optp && tp->t_state != TCPS_LISTEN) - tcp_dooptions(tp, (uint8_t *)optp, optlen, ti); - - /* - * Header prediction: check for the two common cases - * of a uni-directional data xfer. If the packet has - * no control flags, is in-sequence, the window didn't - * change and we're not retransmitting, it's a - * candidate. If the length is zero and the ack moved - * forward, we're the sender side of the xfer. Just - * free the data acked & wake any higher level process - * that was blocked waiting for space. If the length - * is non-zero and the ack didn't move, we're the - * receiver side. If we're getting packets in-order - * (the reassembly queue is empty), add the data to - * the socket buffer and note that we need a delayed ack. - * - * XXX Some of these tests are not needed - * eg: the tiwin == tp->snd_wnd prevents many more - * predictions.. with no *real* advantage.. - */ - if (tp->t_state == TCPS_ESTABLISHED && - (tiflags & (TH_SYN | TH_FIN | TH_RST | TH_URG | TH_ACK)) == TH_ACK && - ti->ti_seq == tp->rcv_nxt && tiwin && tiwin == tp->snd_wnd && - tp->snd_nxt == tp->snd_max) { - if (ti->ti_len == 0) { - if (SEQ_GT(ti->ti_ack, tp->snd_una) && - SEQ_LEQ(ti->ti_ack, tp->snd_max) && - tp->snd_cwnd >= tp->snd_wnd) { - /* - * this is a pure ack for outstanding data. - */ - if (tp->t_rtt && SEQ_GT(ti->ti_ack, tp->t_rtseq)) - tcp_xmit_timer(tp, tp->t_rtt); - acked = ti->ti_ack - tp->snd_una; - sodrop(so, acked); - tp->snd_una = ti->ti_ack; - m_free(m); - - /* - * If all outstanding data are acked, stop - * retransmit timer, otherwise restart timer - * using current (possibly backed-off) value. - * If process is waiting for space, - * wakeup/selwakeup/signal. If data - * are ready to send, let tcp_output - * decide between more output or persist. - */ - if (tp->snd_una == tp->snd_max) - tp->t_timer[TCPT_REXMT] = 0; - else if (tp->t_timer[TCPT_PERSIST] == 0) - tp->t_timer[TCPT_REXMT] = tp->t_rxtcur; - - /* - * This is called because sowwakeup might have - * put data into so_snd. Since we don't so sowwakeup, - * we don't need this.. XXX??? - */ - if (so->so_snd.sb_cc) - (void)tcp_output(tp); - - return; - } - } else if (ti->ti_ack == tp->snd_una && tcpfrag_list_empty(tp) && - ti->ti_len <= sbspace(&so->so_rcv)) { - /* - * this is a pure, in-sequence data packet - * with nothing on the reassembly queue and - * we have enough buffer space to take it. - */ - tp->rcv_nxt += ti->ti_len; - /* - * Add data to socket buffer. - */ - if (so->so_emu) { - if (tcp_emu(so, m)) - sbappend(so, m); - } else - sbappend(so, m); - - /* - * If this is a short packet, then ACK now - with Nagel - * congestion avoidance sender won't send more until - * he gets an ACK. - * - * It is better to not delay acks at all to maximize - * TCP throughput. See RFC 2581. - */ - tp->t_flags |= TF_ACKNOW; - tcp_output(tp); - return; - } - } /* header prediction */ - /* - * Calculate amount of space in receive window, - * and then do TCP input processing. - * Receive window is amount of space in rcv queue, - * but not less than advertised window. - */ - { - int win; - win = sbspace(&so->so_rcv); - if (win < 0) - win = 0; - tp->rcv_wnd = MAX(win, (int)(tp->rcv_adv - tp->rcv_nxt)); - } - - switch (tp->t_state) { - /* - * If the state is LISTEN then ignore segment if it contains an RST. - * If the segment contains an ACK then it is bad and send a RST. - * If it does not contain a SYN then it is not interesting; drop it. - * Don't bother responding if the destination was a broadcast. - * Otherwise initialize tp->rcv_nxt, and tp->irs, select an initial - * tp->iss, and send a segment: - * - * Also initialize tp->snd_nxt to tp->iss+1 and tp->snd_una to tp->iss. - * Fill in remote peer address fields if not previously specified. - * Enter SYN_RECEIVED state, and process any other fields of this - * segment in this state. - */ - case TCPS_LISTEN: { - if (tiflags & TH_RST) - goto drop; - if (tiflags & TH_ACK) - goto dropwithreset; - if ((tiflags & TH_SYN) == 0) - goto drop; - - /* - * This has way too many gotos... - * But a bit of spaghetti code never hurt anybody :) - */ - - /* - * If this is destined for the control address, then flag to - * tcp_ctl once connected, otherwise connect - */ - /* TODO: IPv6 */ - if (af == AF_INET && - (so->so_faddr.s_addr & slirp->vnetwork_mask.s_addr) == - slirp->vnetwork_addr.s_addr) { - if (so->so_faddr.s_addr != slirp->vhost_addr.s_addr && - so->so_faddr.s_addr != slirp->vnameserver_addr.s_addr) { - /* May be an add exec */ - for (ex_ptr = slirp->guestfwd_list; ex_ptr; - ex_ptr = ex_ptr->ex_next) { - if (ex_ptr->ex_fport == so->so_fport && - so->so_faddr.s_addr == ex_ptr->ex_addr.s_addr) { - so->so_state |= SS_CTL; - break; - } - } - if (so->so_state & SS_CTL) { - goto cont_input; - } - } - /* CTL_ALIAS: Do nothing, tcp_fconnect will be called on it */ - } - - if (so->so_emu & EMU_NOCONNECT) { - so->so_emu &= ~EMU_NOCONNECT; - goto cont_input; - } - - if ((tcp_fconnect(so, so->so_ffamily) == -1) && (errno != EAGAIN) && - (errno != EINPROGRESS) && (errno != EWOULDBLOCK)) { - uint8_t code; - DEBUG_MISC(" tcp fconnect errno = %d-%s", errno, strerror(errno)); - if (errno == ECONNREFUSED) { - /* ACK the SYN, send RST to refuse the connection */ - tcp_respond(tp, ti, m, ti->ti_seq + 1, (tcp_seq)0, - TH_RST | TH_ACK, af); - } else { - switch (af) { - case AF_INET: - code = ICMP_UNREACH_NET; - if (errno == EHOSTUNREACH) { - code = ICMP_UNREACH_HOST; - } - break; - case AF_INET6: - code = ICMP6_UNREACH_NO_ROUTE; - if (errno == EHOSTUNREACH) { - code = ICMP6_UNREACH_ADDRESS; - } - break; - default: - g_assert_not_reached(); - } - HTONL(ti->ti_seq); /* restore tcp header */ - HTONL(ti->ti_ack); - HTONS(ti->ti_win); - HTONS(ti->ti_urp); - m->m_data -= - sizeof(struct tcpiphdr) + off - sizeof(struct tcphdr); - m->m_len += - sizeof(struct tcpiphdr) + off - sizeof(struct tcphdr); - switch (af) { - case AF_INET: - m->m_data += sizeof(struct tcpiphdr) - sizeof(struct ip) - - sizeof(struct tcphdr); - m->m_len -= sizeof(struct tcpiphdr) - sizeof(struct ip) - - sizeof(struct tcphdr); - *ip = save_ip; - icmp_send_error(m, ICMP_UNREACH, code, 0, strerror(errno)); - break; - case AF_INET6: - m->m_data += sizeof(struct tcpiphdr) - - (sizeof(struct ip6) + sizeof(struct tcphdr)); - m->m_len -= sizeof(struct tcpiphdr) - - (sizeof(struct ip6) + sizeof(struct tcphdr)); - *ip6 = save_ip6; - icmp6_send_error(m, ICMP6_UNREACH, code); - break; - default: - g_assert_not_reached(); - } - } - tcp_close(tp); - m_free(m); - } else { - /* - * Haven't connected yet, save the current mbuf - * and ti, and return - * XXX Some OS's don't tell us whether the connect() - * succeeded or not. So we must time it out. - */ - so->so_m = m; - so->so_ti = ti; - tp->t_timer[TCPT_KEEP] = TCPTV_KEEP_INIT; - tp->t_state = TCPS_SYN_RECEIVED; - /* - * Initialize receive sequence numbers now so that we can send a - * valid RST if the remote end rejects our connection. - */ - tp->irs = ti->ti_seq; - tcp_rcvseqinit(tp); - tcp_template(tp); - } - return; - - cont_conn: - /* m==NULL - * Check if the connect succeeded - */ - if (so->so_state & SS_NOFDREF) { - tp = tcp_close(tp); - goto dropwithreset; - } - cont_input: - tcp_template(tp); - - if (optp) - tcp_dooptions(tp, (uint8_t *)optp, optlen, ti); - - if (iss) - tp->iss = iss; - else - tp->iss = slirp->tcp_iss; - slirp->tcp_iss += TCP_ISSINCR / 2; - tp->irs = ti->ti_seq; - tcp_sendseqinit(tp); - tcp_rcvseqinit(tp); - tp->t_flags |= TF_ACKNOW; - tp->t_state = TCPS_SYN_RECEIVED; - tp->t_timer[TCPT_KEEP] = TCPTV_KEEP_INIT; - goto trimthenstep6; - } /* case TCPS_LISTEN */ - - /* - * If the state is SYN_SENT: - * if seg contains an ACK, but not for our SYN, drop the input. - * if seg contains a RST, then drop the connection. - * if seg does not contain SYN, then drop it. - * Otherwise this is an acceptable SYN segment - * initialize tp->rcv_nxt and tp->irs - * if seg contains ack then advance tp->snd_una - * if SYN has been acked change to ESTABLISHED else SYN_RCVD state - * arrange for segment to be acked (eventually) - * continue processing rest of data/controls, beginning with URG - */ - case TCPS_SYN_SENT: - if ((tiflags & TH_ACK) && - (SEQ_LEQ(ti->ti_ack, tp->iss) || SEQ_GT(ti->ti_ack, tp->snd_max))) - goto dropwithreset; - - if (tiflags & TH_RST) { - if (tiflags & TH_ACK) { - tcp_drop(tp, 0); /* XXX Check t_softerror! */ - } - goto drop; - } - - if ((tiflags & TH_SYN) == 0) - goto drop; - if (tiflags & TH_ACK) { - tp->snd_una = ti->ti_ack; - if (SEQ_LT(tp->snd_nxt, tp->snd_una)) - tp->snd_nxt = tp->snd_una; - } - - tp->t_timer[TCPT_REXMT] = 0; - tp->irs = ti->ti_seq; - tcp_rcvseqinit(tp); - tp->t_flags |= TF_ACKNOW; - if (tiflags & TH_ACK && SEQ_GT(tp->snd_una, tp->iss)) { - soisfconnected(so); - tp->t_state = TCPS_ESTABLISHED; - - (void)tcp_reass(tp, (struct tcpiphdr *)0, (struct mbuf *)0); - /* - * if we didn't have to retransmit the SYN, - * use its rtt as our initial srtt & rtt var. - */ - if (tp->t_rtt) - tcp_xmit_timer(tp, tp->t_rtt); - } else - tp->t_state = TCPS_SYN_RECEIVED; - - trimthenstep6: - /* - * Advance ti->ti_seq to correspond to first data byte. - * If data, trim to stay within window, - * dropping FIN if necessary. - */ - ti->ti_seq++; - if (ti->ti_len > tp->rcv_wnd) { - todrop = ti->ti_len - tp->rcv_wnd; - m_adj(m, -todrop); - ti->ti_len = tp->rcv_wnd; - tiflags &= ~TH_FIN; - } - tp->snd_wl1 = ti->ti_seq - 1; - tp->rcv_up = ti->ti_seq; - goto step6; - } /* switch tp->t_state */ - /* - * States other than LISTEN or SYN_SENT. - * Check that at least some bytes of segment are within - * receive window. If segment begins before rcv_nxt, - * drop leading data (and SYN); if nothing left, just ack. - */ - todrop = tp->rcv_nxt - ti->ti_seq; - if (todrop > 0) { - if (tiflags & TH_SYN) { - tiflags &= ~TH_SYN; - ti->ti_seq++; - if (ti->ti_urp > 1) - ti->ti_urp--; - else - tiflags &= ~TH_URG; - todrop--; - } - /* - * Following if statement from Stevens, vol. 2, p. 960. - */ - if (todrop > ti->ti_len || - (todrop == ti->ti_len && (tiflags & TH_FIN) == 0)) { - /* - * Any valid FIN must be to the left of the window. - * At this point the FIN must be a duplicate or out - * of sequence; drop it. - */ - tiflags &= ~TH_FIN; - - /* - * Send an ACK to resynchronize and drop any data. - * But keep on processing for RST or ACK. - */ - tp->t_flags |= TF_ACKNOW; - todrop = ti->ti_len; - } - m_adj(m, todrop); - ti->ti_seq += todrop; - ti->ti_len -= todrop; - if (ti->ti_urp > todrop) - ti->ti_urp -= todrop; - else { - tiflags &= ~TH_URG; - ti->ti_urp = 0; - } - } - /* - * If new data are received on a connection after the - * user processes are gone, then RST the other end. - */ - if ((so->so_state & SS_NOFDREF) && tp->t_state > TCPS_CLOSE_WAIT && - ti->ti_len) { - tp = tcp_close(tp); - goto dropwithreset; - } - - /* - * If segment ends after window, drop trailing data - * (and PUSH and FIN); if nothing left, just ACK. - */ - todrop = (ti->ti_seq + ti->ti_len) - (tp->rcv_nxt + tp->rcv_wnd); - if (todrop > 0) { - if (todrop >= ti->ti_len) { - /* - * If a new connection request is received - * while in TIME_WAIT, drop the old connection - * and start over if the sequence numbers - * are above the previous ones. - */ - if (tiflags & TH_SYN && tp->t_state == TCPS_TIME_WAIT && - SEQ_GT(ti->ti_seq, tp->rcv_nxt)) { - iss = tp->rcv_nxt + TCP_ISSINCR; - tp = tcp_close(tp); - goto findso; - } - /* - * If window is closed can only take segments at - * window edge, and have to drop data and PUSH from - * incoming segments. Continue processing, but - * remember to ack. Otherwise, drop segment - * and ack. - */ - if (tp->rcv_wnd == 0 && ti->ti_seq == tp->rcv_nxt) { - tp->t_flags |= TF_ACKNOW; - } else { - goto dropafterack; - } - } - m_adj(m, -todrop); - ti->ti_len -= todrop; - tiflags &= ~(TH_PUSH | TH_FIN); - } - - /* - * If the RST bit is set examine the state: - * SYN_RECEIVED STATE: - * If passive open, return to LISTEN state. - * If active open, inform user that connection was refused. - * ESTABLISHED, FIN_WAIT_1, FIN_WAIT2, CLOSE_WAIT STATES: - * Inform user that connection was reset, and close tcb. - * CLOSING, LAST_ACK, TIME_WAIT STATES - * Close the tcb. - */ - if (tiflags & TH_RST) - switch (tp->t_state) { - case TCPS_SYN_RECEIVED: - case TCPS_ESTABLISHED: - case TCPS_FIN_WAIT_1: - case TCPS_FIN_WAIT_2: - case TCPS_CLOSE_WAIT: - tp->t_state = TCPS_CLOSED; - tcp_close(tp); - goto drop; - - case TCPS_CLOSING: - case TCPS_LAST_ACK: - case TCPS_TIME_WAIT: - tcp_close(tp); - goto drop; - } - - /* - * If a SYN is in the window, then this is an - * error and we send an RST and drop the connection. - */ - if (tiflags & TH_SYN) { - tp = tcp_drop(tp, 0); - goto dropwithreset; - } - - /* - * If the ACK bit is off we drop the segment and return. - */ - if ((tiflags & TH_ACK) == 0) - goto drop; - - /* - * Ack processing. - */ - switch (tp->t_state) { - /* - * In SYN_RECEIVED state if the ack ACKs our SYN then enter - * ESTABLISHED state and continue processing, otherwise - * send an RST. una<=ack<=max - */ - case TCPS_SYN_RECEIVED: - - if (SEQ_GT(tp->snd_una, ti->ti_ack) || SEQ_GT(ti->ti_ack, tp->snd_max)) - goto dropwithreset; - tp->t_state = TCPS_ESTABLISHED; - /* - * The sent SYN is ack'ed with our sequence number +1 - * The first data byte already in the buffer will get - * lost if no correction is made. This is only needed for - * SS_CTL since the buffer is empty otherwise. - * tp->snd_una++; or: - */ - tp->snd_una = ti->ti_ack; - if (so->so_state & SS_CTL) { - /* So tcp_ctl reports the right state */ - ret = tcp_ctl(so); - if (ret == 1) { - soisfconnected(so); - so->so_state &= ~SS_CTL; /* success XXX */ - } else if (ret == 2) { - so->so_state &= SS_PERSISTENT_MASK; - so->so_state |= SS_NOFDREF; /* CTL_CMD */ - } else { - needoutput = 1; - tp->t_state = TCPS_FIN_WAIT_1; - } - } else { - soisfconnected(so); - } - - (void)tcp_reass(tp, (struct tcpiphdr *)0, (struct mbuf *)0); - tp->snd_wl1 = ti->ti_seq - 1; - /* Avoid ack processing; snd_una==ti_ack => dup ack */ - goto synrx_to_est; - /* fall into ... */ - - /* - * In ESTABLISHED state: drop duplicate ACKs; ACK out of range - * ACKs. If the ack is in the range - * tp->snd_una < ti->ti_ack <= tp->snd_max - * then advance tp->snd_una to ti->ti_ack and drop - * data from the retransmission queue. If this ACK reflects - * more up to date window information we update our window information. - */ - case TCPS_ESTABLISHED: - case TCPS_FIN_WAIT_1: - case TCPS_FIN_WAIT_2: - case TCPS_CLOSE_WAIT: - case TCPS_CLOSING: - case TCPS_LAST_ACK: - case TCPS_TIME_WAIT: - - if (SEQ_LEQ(ti->ti_ack, tp->snd_una)) { - if (ti->ti_len == 0 && tiwin == tp->snd_wnd) { - DEBUG_MISC(" dup ack m = %p so = %p", m, so); - /* - * If we have outstanding data (other than - * a window probe), this is a completely - * duplicate ack (ie, window info didn't - * change), the ack is the biggest we've - * seen and we've seen exactly our rexmt - * threshold of them, assume a packet - * has been dropped and retransmit it. - * Kludge snd_nxt & the congestion - * window so we send only this one - * packet. - * - * We know we're losing at the current - * window size so do congestion avoidance - * (set ssthresh to half the current window - * and pull our congestion window back to - * the new ssthresh). - * - * Dup acks mean that packets have left the - * network (they're now cached at the receiver) - * so bump cwnd by the amount in the receiver - * to keep a constant cwnd packets in the - * network. - */ - if (tp->t_timer[TCPT_REXMT] == 0 || ti->ti_ack != tp->snd_una) - tp->t_dupacks = 0; - else if (++tp->t_dupacks == TCPREXMTTHRESH) { - tcp_seq onxt = tp->snd_nxt; - unsigned win = - MIN(tp->snd_wnd, tp->snd_cwnd) / 2 / tp->t_maxseg; - - if (win < 2) - win = 2; - tp->snd_ssthresh = win * tp->t_maxseg; - tp->t_timer[TCPT_REXMT] = 0; - tp->t_rtt = 0; - tp->snd_nxt = ti->ti_ack; - tp->snd_cwnd = tp->t_maxseg; - (void)tcp_output(tp); - tp->snd_cwnd = - tp->snd_ssthresh + tp->t_maxseg * tp->t_dupacks; - if (SEQ_GT(onxt, tp->snd_nxt)) - tp->snd_nxt = onxt; - goto drop; - } else if (tp->t_dupacks > TCPREXMTTHRESH) { - tp->snd_cwnd += tp->t_maxseg; - (void)tcp_output(tp); - goto drop; - } - } else - tp->t_dupacks = 0; - break; - } - synrx_to_est: - /* - * If the congestion window was inflated to account - * for the other side's cached packets, retract it. - */ - if (tp->t_dupacks > TCPREXMTTHRESH && tp->snd_cwnd > tp->snd_ssthresh) - tp->snd_cwnd = tp->snd_ssthresh; - tp->t_dupacks = 0; - if (SEQ_GT(ti->ti_ack, tp->snd_max)) { - goto dropafterack; - } - acked = ti->ti_ack - tp->snd_una; - - /* - * If transmit timer is running and timed sequence - * number was acked, update smoothed round trip time. - * Since we now have an rtt measurement, cancel the - * timer backoff (cf., Phil Karn's retransmit alg.). - * Recompute the initial retransmit timer. - */ - if (tp->t_rtt && SEQ_GT(ti->ti_ack, tp->t_rtseq)) - tcp_xmit_timer(tp, tp->t_rtt); - - /* - * If all outstanding data is acked, stop retransmit - * timer and remember to restart (more output or persist). - * If there is more data to be acked, restart retransmit - * timer, using current (possibly backed-off) value. - */ - if (ti->ti_ack == tp->snd_max) { - tp->t_timer[TCPT_REXMT] = 0; - needoutput = 1; - } else if (tp->t_timer[TCPT_PERSIST] == 0) - tp->t_timer[TCPT_REXMT] = tp->t_rxtcur; - /* - * When new data is acked, open the congestion window. - * If the window gives us less than ssthresh packets - * in flight, open exponentially (maxseg per packet). - * Otherwise open linearly: maxseg per window - * (maxseg^2 / cwnd per packet). - */ - { - register unsigned cw = tp->snd_cwnd; - register unsigned incr = tp->t_maxseg; - - if (cw > tp->snd_ssthresh) - incr = incr * incr / cw; - tp->snd_cwnd = MIN(cw + incr, TCP_MAXWIN << tp->snd_scale); - } - if (acked > so->so_snd.sb_cc) { - tp->snd_wnd -= so->so_snd.sb_cc; - sodrop(so, (int)so->so_snd.sb_cc); - ourfinisacked = 1; - } else { - sodrop(so, acked); - tp->snd_wnd -= acked; - ourfinisacked = 0; - } - tp->snd_una = ti->ti_ack; - if (SEQ_LT(tp->snd_nxt, tp->snd_una)) - tp->snd_nxt = tp->snd_una; - - switch (tp->t_state) { - /* - * In FIN_WAIT_1 STATE in addition to the processing - * for the ESTABLISHED state if our FIN is now acknowledged - * then enter FIN_WAIT_2. - */ - case TCPS_FIN_WAIT_1: - if (ourfinisacked) { - /* - * If we can't receive any more - * data, then closing user can proceed. - * Starting the timer is contrary to the - * specification, but if we don't get a FIN - * we'll hang forever. - */ - if (so->so_state & SS_FCANTRCVMORE) { - tp->t_timer[TCPT_2MSL] = TCP_MAXIDLE; - } - tp->t_state = TCPS_FIN_WAIT_2; - } - break; - - /* - * In CLOSING STATE in addition to the processing for - * the ESTABLISHED state if the ACK acknowledges our FIN - * then enter the TIME-WAIT state, otherwise ignore - * the segment. - */ - case TCPS_CLOSING: - if (ourfinisacked) { - tp->t_state = TCPS_TIME_WAIT; - tcp_canceltimers(tp); - tp->t_timer[TCPT_2MSL] = 2 * TCPTV_MSL; - } - break; - - /* - * In LAST_ACK, we may still be waiting for data to drain - * and/or to be acked, as well as for the ack of our FIN. - * If our FIN is now acknowledged, delete the TCB, - * enter the closed state and return. - */ - case TCPS_LAST_ACK: - if (ourfinisacked) { - tcp_close(tp); - goto drop; - } - break; - - /* - * In TIME_WAIT state the only thing that should arrive - * is a retransmission of the remote FIN. Acknowledge - * it and restart the finack timer. - */ - case TCPS_TIME_WAIT: - tp->t_timer[TCPT_2MSL] = 2 * TCPTV_MSL; - goto dropafterack; - } - } /* switch(tp->t_state) */ - -step6: - /* - * Update window information. - * Don't look at window if no ACK: TAC's send garbage on first SYN. - */ - if ((tiflags & TH_ACK) && - (SEQ_LT(tp->snd_wl1, ti->ti_seq) || - (tp->snd_wl1 == ti->ti_seq && - (SEQ_LT(tp->snd_wl2, ti->ti_ack) || - (tp->snd_wl2 == ti->ti_ack && tiwin > tp->snd_wnd))))) { - tp->snd_wnd = tiwin; - tp->snd_wl1 = ti->ti_seq; - tp->snd_wl2 = ti->ti_ack; - if (tp->snd_wnd > tp->max_sndwnd) - tp->max_sndwnd = tp->snd_wnd; - needoutput = 1; - } - - /* - * Process segments with URG. - */ - if ((tiflags & TH_URG) && ti->ti_urp && - TCPS_HAVERCVDFIN(tp->t_state) == 0) { - /* - * This is a kludge, but if we receive and accept - * random urgent pointers, we'll crash in - * soreceive. It's hard to imagine someone - * actually wanting to send this much urgent data. - */ - if (ti->ti_urp + so->so_rcv.sb_cc > so->so_rcv.sb_datalen) { - ti->ti_urp = 0; - tiflags &= ~TH_URG; - goto dodata; - } - /* - * If this segment advances the known urgent pointer, - * then mark the data stream. This should not happen - * in CLOSE_WAIT, CLOSING, LAST_ACK or TIME_WAIT STATES since - * a FIN has been received from the remote side. - * In these states we ignore the URG. - * - * According to RFC961 (Assigned Protocols), - * the urgent pointer points to the last octet - * of urgent data. We continue, however, - * to consider it to indicate the first octet - * of data past the urgent section as the original - * spec states (in one of two places). - */ - if (SEQ_GT(ti->ti_seq + ti->ti_urp, tp->rcv_up)) { - tp->rcv_up = ti->ti_seq + ti->ti_urp; - so->so_urgc = - so->so_rcv.sb_cc + (tp->rcv_up - tp->rcv_nxt); /* -1; */ - tp->rcv_up = ti->ti_seq + ti->ti_urp; - } - } else - /* - * If no out of band data is expected, - * pull receive urgent pointer along - * with the receive window. - */ - if (SEQ_GT(tp->rcv_nxt, tp->rcv_up)) - tp->rcv_up = tp->rcv_nxt; -dodata: - - /* - * If this is a small packet, then ACK now - with Nagel - * congestion avoidance sender won't send more until - * he gets an ACK. - */ - if (ti->ti_len && (unsigned)ti->ti_len <= 5 && - ((struct tcpiphdr_2 *)ti)->first_char == (char)27) { - tp->t_flags |= TF_ACKNOW; - } - - /* - * Process the segment text, merging it into the TCP sequencing queue, - * and arranging for acknowledgment of receipt if necessary. - * This process logically involves adjusting tp->rcv_wnd as data - * is presented to the user (this happens in tcp_usrreq.c, - * case PRU_RCVD). If a FIN has already been received on this - * connection then we just ignore the text. - */ - if ((ti->ti_len || (tiflags & TH_FIN)) && - TCPS_HAVERCVDFIN(tp->t_state) == 0) { - TCP_REASS(tp, ti, m, so, tiflags); - } else { - m_free(m); - tiflags &= ~TH_FIN; - } - - /* - * If FIN is received ACK the FIN and let the user know - * that the connection is closing. - */ - if (tiflags & TH_FIN) { - if (TCPS_HAVERCVDFIN(tp->t_state) == 0) { - /* - * If we receive a FIN we can't send more data, - * set it SS_FDRAIN - * Shutdown the socket if there is no rx data in the - * buffer. - * soread() is called on completion of shutdown() and - * will got to TCPS_LAST_ACK, and use tcp_output() - * to send the FIN. - */ - sofwdrain(so); - - tp->t_flags |= TF_ACKNOW; - tp->rcv_nxt++; - } - switch (tp->t_state) { - /* - * In SYN_RECEIVED and ESTABLISHED STATES - * enter the CLOSE_WAIT state. - */ - case TCPS_SYN_RECEIVED: - case TCPS_ESTABLISHED: - if (so->so_emu == EMU_CTL) /* no shutdown on socket */ - tp->t_state = TCPS_LAST_ACK; - else - tp->t_state = TCPS_CLOSE_WAIT; - break; - - /* - * If still in FIN_WAIT_1 STATE FIN has not been acked so - * enter the CLOSING state. - */ - case TCPS_FIN_WAIT_1: - tp->t_state = TCPS_CLOSING; - break; - - /* - * In FIN_WAIT_2 state enter the TIME_WAIT state, - * starting the time-wait timer, turning off the other - * standard timers. - */ - case TCPS_FIN_WAIT_2: - tp->t_state = TCPS_TIME_WAIT; - tcp_canceltimers(tp); - tp->t_timer[TCPT_2MSL] = 2 * TCPTV_MSL; - break; - - /* - * In TIME_WAIT state restart the 2 MSL time_wait timer. - */ - case TCPS_TIME_WAIT: - tp->t_timer[TCPT_2MSL] = 2 * TCPTV_MSL; - break; - } - } - - /* - * Return any desired output. - */ - if (needoutput || (tp->t_flags & TF_ACKNOW)) { - (void)tcp_output(tp); - } - return; - -dropafterack: - /* - * Generate an ACK dropping incoming segment if it occupies - * sequence space, where the ACK reflects our state. - */ - if (tiflags & TH_RST) - goto drop; - m_free(m); - tp->t_flags |= TF_ACKNOW; - (void)tcp_output(tp); - return; - -dropwithreset: - /* reuses m if m!=NULL, m_free() unnecessary */ - if (tiflags & TH_ACK) - tcp_respond(tp, ti, m, (tcp_seq)0, ti->ti_ack, TH_RST, af); - else { - if (tiflags & TH_SYN) - ti->ti_len++; - tcp_respond(tp, ti, m, ti->ti_seq + ti->ti_len, (tcp_seq)0, - TH_RST | TH_ACK, af); - } - - return; - -drop: - /* - * Drop space held by incoming segment and return. - */ - m_free(m); -} - -static void tcp_dooptions(struct tcpcb *tp, uint8_t *cp, int cnt, - struct tcpiphdr *ti) -{ - uint16_t mss; - int opt, optlen; - - DEBUG_CALL("tcp_dooptions"); - DEBUG_ARG("tp = %p cnt=%i", tp, cnt); - - for (; cnt > 0; cnt -= optlen, cp += optlen) { - opt = cp[0]; - if (opt == TCPOPT_EOL) - break; - if (opt == TCPOPT_NOP) - optlen = 1; - else { - optlen = cp[1]; - if (optlen <= 0) - break; - } - switch (opt) { - default: - continue; - - case TCPOPT_MAXSEG: - if (optlen != TCPOLEN_MAXSEG) - continue; - if (!(ti->ti_flags & TH_SYN)) - continue; - memcpy((char *)&mss, (char *)cp + 2, sizeof(mss)); - NTOHS(mss); - (void)tcp_mss(tp, mss); /* sets t_maxseg */ - break; - } - } -} - -/* - * Collect new round-trip time estimate - * and update averages and current timeout. - */ - -static void tcp_xmit_timer(register struct tcpcb *tp, int rtt) -{ - register short delta; - - DEBUG_CALL("tcp_xmit_timer"); - DEBUG_ARG("tp = %p", tp); - DEBUG_ARG("rtt = %d", rtt); - - if (tp->t_srtt != 0) { - /* - * srtt is stored as fixed point with 3 bits after the - * binary point (i.e., scaled by 8). The following magic - * is equivalent to the smoothing algorithm in rfc793 with - * an alpha of .875 (srtt = rtt/8 + srtt*7/8 in fixed - * point). Adjust rtt to origin 0. - */ - delta = rtt - 1 - (tp->t_srtt >> TCP_RTT_SHIFT); - if ((tp->t_srtt += delta) <= 0) - tp->t_srtt = 1; - /* - * We accumulate a smoothed rtt variance (actually, a - * smoothed mean difference), then set the retransmit - * timer to smoothed rtt + 4 times the smoothed variance. - * rttvar is stored as fixed point with 2 bits after the - * binary point (scaled by 4). The following is - * equivalent to rfc793 smoothing with an alpha of .75 - * (rttvar = rttvar*3/4 + |delta| / 4). This replaces - * rfc793's wired-in beta. - */ - if (delta < 0) - delta = -delta; - delta -= (tp->t_rttvar >> TCP_RTTVAR_SHIFT); - if ((tp->t_rttvar += delta) <= 0) - tp->t_rttvar = 1; - } else { - /* - * No rtt measurement yet - use the unsmoothed rtt. - * Set the variance to half the rtt (so our first - * retransmit happens at 3*rtt). - */ - tp->t_srtt = rtt << TCP_RTT_SHIFT; - tp->t_rttvar = rtt << (TCP_RTTVAR_SHIFT - 1); - } - tp->t_rtt = 0; - tp->t_rxtshift = 0; - - /* - * the retransmit should happen at rtt + 4 * rttvar. - * Because of the way we do the smoothing, srtt and rttvar - * will each average +1/2 tick of bias. When we compute - * the retransmit timer, we want 1/2 tick of rounding and - * 1 extra tick because of +-1/2 tick uncertainty in the - * firing of the timer. The bias will give us exactly the - * 1.5 tick we need. But, because the bias is - * statistical, we have to test that we don't drop below - * the minimum feasible timer (which is 2 ticks). - */ - TCPT_RANGESET(tp->t_rxtcur, TCP_REXMTVAL(tp), (short)tp->t_rttmin, - TCPTV_REXMTMAX); /* XXX */ - - /* - * We received an ack for a packet that wasn't retransmitted; - * it is probably safe to discard any error indications we've - * received recently. This isn't quite right, but close enough - * for now (a route might have failed after we sent a segment, - * and the return path might not be symmetrical). - */ - tp->t_softerror = 0; -} - -/* - * Determine a reasonable value for maxseg size. - * If the route is known, check route for mtu. - * If none, use an mss that can be handled on the outgoing - * interface without forcing IP to fragment; if bigger than - * an mbuf cluster (MCLBYTES), round down to nearest multiple of MCLBYTES - * to utilize large mbufs. If no route is found, route has no mtu, - * or the destination isn't local, use a default, hopefully conservative - * size (usually 512 or the default IP max size, but no more than the mtu - * of the interface), as we can't discover anything about intervening - * gateways or networks. We also initialize the congestion/slow start - * window to be a single segment if the destination isn't local. - * While looking at the routing entry, we also initialize other path-dependent - * parameters from pre-set or cached values in the routing entry. - */ - -int tcp_mss(struct tcpcb *tp, unsigned offer) -{ - struct socket *so = tp->t_socket; - int mss; - - DEBUG_CALL("tcp_mss"); - DEBUG_ARG("tp = %p", tp); - DEBUG_ARG("offer = %d", offer); - - switch (so->so_ffamily) { - case AF_INET: - mss = MIN(so->slirp->if_mtu, so->slirp->if_mru) - - sizeof(struct tcphdr) - sizeof(struct ip); - break; - case AF_INET6: - mss = MIN(so->slirp->if_mtu, so->slirp->if_mru) - - sizeof(struct tcphdr) - sizeof(struct ip6); - break; - default: - g_assert_not_reached(); - } - - if (offer) - mss = MIN(mss, offer); - mss = MAX(mss, 32); - if (mss < tp->t_maxseg || offer != 0) - tp->t_maxseg = MIN(mss, TCP_MAXSEG_MAX); - - tp->snd_cwnd = mss; - - sbreserve(&so->so_snd, - TCP_SNDSPACE + - ((TCP_SNDSPACE % mss) ? (mss - (TCP_SNDSPACE % mss)) : 0)); - sbreserve(&so->so_rcv, - TCP_RCVSPACE + - ((TCP_RCVSPACE % mss) ? (mss - (TCP_RCVSPACE % mss)) : 0)); - - DEBUG_MISC(" returning mss = %d", mss); - - return mss; -} diff --git a/src/network/slirp/tcp_output.c b/src/network/slirp/tcp_output.c deleted file mode 100644 index 383fe31dc..000000000 --- a/src/network/slirp/tcp_output.c +++ /dev/null @@ -1,516 +0,0 @@ -/* SPDX-License-Identifier: BSD-3-Clause */ -/* - * Copyright (c) 1982, 1986, 1988, 1990, 1993 - * The Regents of the University of California. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. Neither the name of the University nor the names of its contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - * - * @(#)tcp_output.c 8.3 (Berkeley) 12/30/93 - * tcp_output.c,v 1.3 1994/09/15 10:36:55 davidg Exp - */ - -/* - * Changes and additions relating to SLiRP - * Copyright (c) 1995 Danny Gasparovski. - */ - -#include "slirp.h" - -static const uint8_t tcp_outflags[TCP_NSTATES] = { - TH_RST | TH_ACK, 0, TH_SYN, TH_SYN | TH_ACK, - TH_ACK, TH_ACK, TH_FIN | TH_ACK, TH_FIN | TH_ACK, - TH_FIN | TH_ACK, TH_ACK, TH_ACK, -}; - - -#undef MAX_TCPOPTLEN -#define MAX_TCPOPTLEN 32 /* max # bytes that go in options */ - -/* - * Tcp output routine: figure out what should be sent and send it. - */ -int tcp_output(struct tcpcb *tp) -{ - register struct socket *so = tp->t_socket; - register long len, win; - int off, flags, error; - register struct mbuf *m; - register struct tcpiphdr *ti, tcpiph_save; - struct ip *ip; - struct ip6 *ip6; - uint8_t opt[MAX_TCPOPTLEN]; - unsigned optlen, hdrlen; - int idle, sendalot; - - DEBUG_CALL("tcp_output"); - DEBUG_ARG("tp = %p", tp); - - /* - * Determine length of data that should be transmitted, - * and flags that will be used. - * If there is some data or critical controls (SYN, RST) - * to send, then transmit; otherwise, investigate further. - */ - idle = (tp->snd_max == tp->snd_una); - if (idle && tp->t_idle >= tp->t_rxtcur) - /* - * We have been idle for "a while" and no acks are - * expected to clock out any data we send -- - * slow start to get ack "clock" running again. - */ - tp->snd_cwnd = tp->t_maxseg; -again: - sendalot = 0; - off = tp->snd_nxt - tp->snd_una; - win = MIN(tp->snd_wnd, tp->snd_cwnd); - - flags = tcp_outflags[tp->t_state]; - - DEBUG_MISC(" --- tcp_output flags = 0x%x", flags); - - /* - * If in persist timeout with window of 0, send 1 byte. - * Otherwise, if window is small but nonzero - * and timer expired, we will send what we can - * and go to transmit state. - */ - if (tp->t_force) { - if (win == 0) { - /* - * If we still have some data to send, then - * clear the FIN bit. Usually this would - * happen below when it realizes that we - * aren't sending all the data. However, - * if we have exactly 1 byte of unset data, - * then it won't clear the FIN bit below, - * and if we are in persist state, we wind - * up sending the packet without recording - * that we sent the FIN bit. - * - * We can't just blindly clear the FIN bit, - * because if we don't have any more data - * to send then the probe will be the FIN - * itself. - */ - if (off < so->so_snd.sb_cc) - flags &= ~TH_FIN; - win = 1; - } else { - tp->t_timer[TCPT_PERSIST] = 0; - tp->t_rxtshift = 0; - } - } - - len = MIN(so->so_snd.sb_cc, win) - off; - - if (len < 0) { - /* - * If FIN has been sent but not acked, - * but we haven't been called to retransmit, - * len will be -1. Otherwise, window shrank - * after we sent into it. If window shrank to 0, - * cancel pending retransmit and pull snd_nxt - * back to (closed) window. We will enter persist - * state below. If the window didn't close completely, - * just wait for an ACK. - */ - len = 0; - if (win == 0) { - tp->t_timer[TCPT_REXMT] = 0; - tp->snd_nxt = tp->snd_una; - } - } - - if (len > tp->t_maxseg) { - len = tp->t_maxseg; - sendalot = 1; - } - if (SEQ_LT(tp->snd_nxt + len, tp->snd_una + so->so_snd.sb_cc)) - flags &= ~TH_FIN; - - win = sbspace(&so->so_rcv); - - /* - * Sender silly window avoidance. If connection is idle - * and can send all data, a maximum segment, - * at least a maximum default-size segment do it, - * or are forced, do it; otherwise don't bother. - * If peer's buffer is tiny, then send - * when window is at least half open. - * If retransmitting (possibly after persist timer forced us - * to send into a small window), then must resend. - */ - if (len) { - if (len == tp->t_maxseg) - goto send; - if ((1 || idle || tp->t_flags & TF_NODELAY) && - len + off >= so->so_snd.sb_cc) - goto send; - if (tp->t_force) - goto send; - if (len >= tp->max_sndwnd / 2 && tp->max_sndwnd > 0) - goto send; - if (SEQ_LT(tp->snd_nxt, tp->snd_max)) - goto send; - } - - /* - * Compare available window to amount of window - * known to peer (as advertised window less - * next expected input). If the difference is at least two - * max size segments, or at least 50% of the maximum possible - * window, then want to send a window update to peer. - */ - if (win > 0) { - /* - * "adv" is the amount we can increase the window, - * taking into account that we are limited by - * TCP_MAXWIN << tp->rcv_scale. - */ - long adv = MIN(win, (long)TCP_MAXWIN << tp->rcv_scale) - - (tp->rcv_adv - tp->rcv_nxt); - - if (adv >= (long)(2 * tp->t_maxseg)) - goto send; - if (2 * adv >= (long)so->so_rcv.sb_datalen) - goto send; - } - - /* - * Send if we owe peer an ACK. - */ - if (tp->t_flags & TF_ACKNOW) - goto send; - if (flags & (TH_SYN | TH_RST)) - goto send; - if (SEQ_GT(tp->snd_up, tp->snd_una)) - goto send; - /* - * If our state indicates that FIN should be sent - * and we have not yet done so, or we're retransmitting the FIN, - * then we need to send. - */ - if (flags & TH_FIN && - ((tp->t_flags & TF_SENTFIN) == 0 || tp->snd_nxt == tp->snd_una)) - goto send; - - /* - * TCP window updates are not reliable, rather a polling protocol - * using ``persist'' packets is used to insure receipt of window - * updates. The three ``states'' for the output side are: - * idle not doing retransmits or persists - * persisting to move a small or zero window - * (re)transmitting and thereby not persisting - * - * tp->t_timer[TCPT_PERSIST] - * is set when we are in persist state. - * tp->t_force - * is set when we are called to send a persist packet. - * tp->t_timer[TCPT_REXMT] - * is set when we are retransmitting - * The output side is idle when both timers are zero. - * - * If send window is too small, there is data to transmit, and no - * retransmit or persist is pending, then go to persist state. - * If nothing happens soon, send when timer expires: - * if window is nonzero, transmit what we can, - * otherwise force out a byte. - */ - if (so->so_snd.sb_cc && tp->t_timer[TCPT_REXMT] == 0 && - tp->t_timer[TCPT_PERSIST] == 0) { - tp->t_rxtshift = 0; - tcp_setpersist(tp); - } - - /* - * No reason to send a segment, just return. - */ - return (0); - -send: - /* - * Before ESTABLISHED, force sending of initial options - * unless TCP set not to do any options. - * NOTE: we assume that the IP/TCP header plus TCP options - * always fit in a single mbuf, leaving room for a maximum - * link header, i.e. - * max_linkhdr + sizeof (struct tcpiphdr) + optlen <= MHLEN - */ - optlen = 0; - hdrlen = sizeof(struct tcpiphdr); - if (flags & TH_SYN) { - tp->snd_nxt = tp->iss; - if ((tp->t_flags & TF_NOOPT) == 0) { - uint16_t mss; - - opt[0] = TCPOPT_MAXSEG; - opt[1] = 4; - mss = htons((uint16_t)tcp_mss(tp, 0)); - memcpy((char *)(opt + 2), (char *)&mss, sizeof(mss)); - optlen = 4; - } - } - - hdrlen += optlen; - - /* - * Adjust data length if insertion of options will - * bump the packet length beyond the t_maxseg length. - */ - if (len > tp->t_maxseg - optlen) { - len = tp->t_maxseg - optlen; - sendalot = 1; - } - - /* - * Grab a header mbuf, attaching a copy of data to - * be transmitted, and initialize the header from - * the template for sends on this connection. - */ - if (len) { - m = m_get(so->slirp); - if (m == NULL) { - error = 1; - goto out; - } - m->m_data += IF_MAXLINKHDR; - m->m_len = hdrlen; - - sbcopy(&so->so_snd, off, (int)len, mtod(m, char *) + hdrlen); - m->m_len += len; - - /* - * If we're sending everything we've got, set PUSH. - * (This will keep happy those implementations which only - * give data to the user when a buffer fills or - * a PUSH comes in.) - */ - if (off + len == so->so_snd.sb_cc) - flags |= TH_PUSH; - } else { - m = m_get(so->slirp); - if (m == NULL) { - error = 1; - goto out; - } - m->m_data += IF_MAXLINKHDR; - m->m_len = hdrlen; - } - - ti = mtod(m, struct tcpiphdr *); - - memcpy((char *)ti, &tp->t_template, sizeof(struct tcpiphdr)); - - /* - * Fill in fields, remembering maximum advertised - * window for use in delaying messages about window sizes. - * If resending a FIN, be sure not to use a new sequence number. - */ - if (flags & TH_FIN && tp->t_flags & TF_SENTFIN && - tp->snd_nxt == tp->snd_max) - tp->snd_nxt--; - /* - * If we are doing retransmissions, then snd_nxt will - * not reflect the first unsent octet. For ACK only - * packets, we do not want the sequence number of the - * retransmitted packet, we want the sequence number - * of the next unsent octet. So, if there is no data - * (and no SYN or FIN), use snd_max instead of snd_nxt - * when filling in ti_seq. But if we are in persist - * state, snd_max might reflect one byte beyond the - * right edge of the window, so use snd_nxt in that - * case, since we know we aren't doing a retransmission. - * (retransmit and persist are mutually exclusive...) - */ - if (len || (flags & (TH_SYN | TH_FIN)) || tp->t_timer[TCPT_PERSIST]) - ti->ti_seq = htonl(tp->snd_nxt); - else - ti->ti_seq = htonl(tp->snd_max); - ti->ti_ack = htonl(tp->rcv_nxt); - if (optlen) { - memcpy((char *)(ti + 1), (char *)opt, optlen); - ti->ti_off = (sizeof(struct tcphdr) + optlen) >> 2; - } - ti->ti_flags = flags; - /* - * Calculate receive window. Don't shrink window, - * but avoid silly window syndrome. - */ - if (win < (long)(so->so_rcv.sb_datalen / 4) && win < (long)tp->t_maxseg) - win = 0; - if (win > (long)TCP_MAXWIN << tp->rcv_scale) - win = (long)TCP_MAXWIN << tp->rcv_scale; - if (win < (long)(tp->rcv_adv - tp->rcv_nxt)) - win = (long)(tp->rcv_adv - tp->rcv_nxt); - ti->ti_win = htons((uint16_t)(win >> tp->rcv_scale)); - - if (SEQ_GT(tp->snd_up, tp->snd_una)) { - ti->ti_urp = htons((uint16_t)(tp->snd_up - ntohl(ti->ti_seq))); - ti->ti_flags |= TH_URG; - } else - /* - * If no urgent pointer to send, then we pull - * the urgent pointer to the left edge of the send window - * so that it doesn't drift into the send window on sequence - * number wraparound. - */ - tp->snd_up = tp->snd_una; /* drag it along */ - - /* - * Put TCP length in extended header, and then - * checksum extended header and data. - */ - if (len + optlen) - ti->ti_len = htons((uint16_t)(sizeof(struct tcphdr) + optlen + len)); - ti->ti_sum = cksum(m, (int)(hdrlen + len)); - - /* - * In transmit state, time the transmission and arrange for - * the retransmit. In persist state, just set snd_max. - */ - if (tp->t_force == 0 || tp->t_timer[TCPT_PERSIST] == 0) { - tcp_seq startseq = tp->snd_nxt; - - /* - * Advance snd_nxt over sequence space of this segment. - */ - if (flags & (TH_SYN | TH_FIN)) { - if (flags & TH_SYN) - tp->snd_nxt++; - if (flags & TH_FIN) { - tp->snd_nxt++; - tp->t_flags |= TF_SENTFIN; - } - } - tp->snd_nxt += len; - if (SEQ_GT(tp->snd_nxt, tp->snd_max)) { - tp->snd_max = tp->snd_nxt; - /* - * Time this transmission if not a retransmission and - * not currently timing anything. - */ - if (tp->t_rtt == 0) { - tp->t_rtt = 1; - tp->t_rtseq = startseq; - } - } - - /* - * Set retransmit timer if not currently set, - * and not doing an ack or a keep-alive probe. - * Initial value for retransmit timer is smoothed - * round-trip time + 2 * round-trip time variance. - * Initialize shift counter which is used for backoff - * of retransmit time. - */ - if (tp->t_timer[TCPT_REXMT] == 0 && tp->snd_nxt != tp->snd_una) { - tp->t_timer[TCPT_REXMT] = tp->t_rxtcur; - if (tp->t_timer[TCPT_PERSIST]) { - tp->t_timer[TCPT_PERSIST] = 0; - tp->t_rxtshift = 0; - } - } - } else if (SEQ_GT(tp->snd_nxt + len, tp->snd_max)) - tp->snd_max = tp->snd_nxt + len; - - /* - * Fill in IP length and desired time to live and - * send to IP level. There should be a better way - * to handle ttl and tos; we could keep them in - * the template, but need a way to checksum without them. - */ - m->m_len = hdrlen + len; /* XXX Needed? m_len should be correct */ - tcpiph_save = *mtod(m, struct tcpiphdr *); - - switch (so->so_ffamily) { - case AF_INET: - m->m_data += - sizeof(struct tcpiphdr) - sizeof(struct tcphdr) - sizeof(struct ip); - m->m_len -= - sizeof(struct tcpiphdr) - sizeof(struct tcphdr) - sizeof(struct ip); - ip = mtod(m, struct ip *); - - ip->ip_len = m->m_len; - ip->ip_dst = tcpiph_save.ti_dst; - ip->ip_src = tcpiph_save.ti_src; - ip->ip_p = tcpiph_save.ti_pr; - - ip->ip_ttl = IPDEFTTL; - ip->ip_tos = so->so_iptos; - error = ip_output(so, m); - break; - - case AF_INET6: - m->m_data += sizeof(struct tcpiphdr) - sizeof(struct tcphdr) - - sizeof(struct ip6); - m->m_len -= sizeof(struct tcpiphdr) - sizeof(struct tcphdr) - - sizeof(struct ip6); - ip6 = mtod(m, struct ip6 *); - - ip6->ip_pl = tcpiph_save.ti_len; - ip6->ip_dst = tcpiph_save.ti_dst6; - ip6->ip_src = tcpiph_save.ti_src6; - ip6->ip_nh = tcpiph_save.ti_nh6; - - error = ip6_output(so, m, 0); - break; - - default: - g_assert_not_reached(); - } - - if (error) { - out: - return (error); - } - - /* - * Data sent (as far as we can tell). - * If this advertises a larger window than any other segment, - * then remember the size of the advertised window. - * Any pending ACK has now been sent. - */ - if (win > 0 && SEQ_GT(tp->rcv_nxt + win, tp->rcv_adv)) - tp->rcv_adv = tp->rcv_nxt + win; - tp->last_ack_sent = tp->rcv_nxt; - tp->t_flags &= ~(TF_ACKNOW | TF_DELACK); - if (sendalot) - goto again; - - return (0); -} - -void tcp_setpersist(struct tcpcb *tp) -{ - int t = ((tp->t_srtt >> 2) + tp->t_rttvar) >> 1; - - /* - * Start/restart persistence timer. - */ - TCPT_RANGESET(tp->t_timer[TCPT_PERSIST], t * tcp_backoff[tp->t_rxtshift], - TCPTV_PERSMIN, TCPTV_PERSMAX); - if (tp->t_rxtshift < TCP_MAXRXTSHIFT) - tp->t_rxtshift++; -} diff --git a/src/network/slirp/tcp_subr.c b/src/network/slirp/tcp_subr.c deleted file mode 100644 index a1016d90d..000000000 --- a/src/network/slirp/tcp_subr.c +++ /dev/null @@ -1,980 +0,0 @@ -/* SPDX-License-Identifier: BSD-3-Clause */ -/* - * Copyright (c) 1982, 1986, 1988, 1990, 1993 - * The Regents of the University of California. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. Neither the name of the University nor the names of its contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - * - * @(#)tcp_subr.c 8.1 (Berkeley) 6/10/93 - * tcp_subr.c,v 1.5 1994/10/08 22:39:58 phk Exp - */ - -/* - * Changes and additions relating to SLiRP - * Copyright (c) 1995 Danny Gasparovski. - */ - -#include "slirp.h" - -/* patchable/settable parameters for tcp */ -/* Don't do rfc1323 performance enhancements */ -#define TCP_DO_RFC1323 0 - -/* - * Tcp initialization - */ -void tcp_init(Slirp *slirp) -{ - slirp->tcp_iss = 1; /* wrong */ - slirp->tcb.so_next = slirp->tcb.so_prev = &slirp->tcb; - slirp->tcp_last_so = &slirp->tcb; -} - -void tcp_cleanup(Slirp *slirp) -{ - while (slirp->tcb.so_next != &slirp->tcb) { - tcp_close(sototcpcb(slirp->tcb.so_next)); - } -} - -/* - * Create template to be used to send tcp packets on a connection. - * Call after host entry created, fills - * in a skeletal tcp/ip header, minimizing the amount of work - * necessary when the connection is used. - */ -void tcp_template(struct tcpcb *tp) -{ - struct socket *so = tp->t_socket; - register struct tcpiphdr *n = &tp->t_template; - - n->ti_mbuf = NULL; - memset(&n->ti, 0, sizeof(n->ti)); - n->ti_x0 = 0; - switch (so->so_ffamily) { - case AF_INET: - n->ti_pr = IPPROTO_TCP; - n->ti_len = htons(sizeof(struct tcphdr)); - n->ti_src = so->so_faddr; - n->ti_dst = so->so_laddr; - n->ti_sport = so->so_fport; - n->ti_dport = so->so_lport; - break; - - case AF_INET6: - n->ti_nh6 = IPPROTO_TCP; - n->ti_len = htons(sizeof(struct tcphdr)); - n->ti_src6 = so->so_faddr6; - n->ti_dst6 = so->so_laddr6; - n->ti_sport = so->so_fport6; - n->ti_dport = so->so_lport6; - break; - - default: - g_assert_not_reached(); - } - - n->ti_seq = 0; - n->ti_ack = 0; - n->ti_x2 = 0; - n->ti_off = 5; - n->ti_flags = 0; - n->ti_win = 0; - n->ti_sum = 0; - n->ti_urp = 0; -} - -/* - * Send a single message to the TCP at address specified by - * the given TCP/IP header. If m == 0, then we make a copy - * of the tcpiphdr at ti and send directly to the addressed host. - * This is used to force keep alive messages out using the TCP - * template for a connection tp->t_template. If flags are given - * then we send a message back to the TCP which originated the - * segment ti, and discard the mbuf containing it and any other - * attached mbufs. - * - * In any case the ack and sequence number of the transmitted - * segment are as specified by the parameters. - */ -void tcp_respond(struct tcpcb *tp, struct tcpiphdr *ti, struct mbuf *m, - tcp_seq ack, tcp_seq seq, int flags, unsigned short af) -{ - register int tlen; - int win = 0; - - DEBUG_CALL("tcp_respond"); - DEBUG_ARG("tp = %p", tp); - DEBUG_ARG("ti = %p", ti); - DEBUG_ARG("m = %p", m); - DEBUG_ARG("ack = %u", ack); - DEBUG_ARG("seq = %u", seq); - DEBUG_ARG("flags = %x", flags); - - if (tp) - win = sbspace(&tp->t_socket->so_rcv); - if (m == NULL) { - if (!tp || (m = m_get(tp->t_socket->slirp)) == NULL) - return; - tlen = 0; - m->m_data += IF_MAXLINKHDR; - *mtod(m, struct tcpiphdr *) = *ti; - ti = mtod(m, struct tcpiphdr *); - switch (af) { - case AF_INET: - ti->ti.ti_i4.ih_x1 = 0; - break; - case AF_INET6: - ti->ti.ti_i6.ih_x1 = 0; - break; - default: - g_assert_not_reached(); - } - flags = TH_ACK; - } else { - /* - * ti points into m so the next line is just making - * the mbuf point to ti - */ - m->m_data = (char *)ti; - - m->m_len = sizeof(struct tcpiphdr); - tlen = 0; -#define xchg(a, b, type) \ - { \ - type t; \ - t = a; \ - a = b; \ - b = t; \ - } - switch (af) { - case AF_INET: - xchg(ti->ti_dst.s_addr, ti->ti_src.s_addr, uint32_t); - xchg(ti->ti_dport, ti->ti_sport, uint16_t); - break; - case AF_INET6: - xchg(ti->ti_dst6, ti->ti_src6, struct in6_addr); - xchg(ti->ti_dport, ti->ti_sport, uint16_t); - break; - default: - g_assert_not_reached(); - } -#undef xchg - } - ti->ti_len = htons((uint16_t)(sizeof(struct tcphdr) + tlen)); - tlen += sizeof(struct tcpiphdr); - m->m_len = tlen; - - ti->ti_mbuf = NULL; - ti->ti_x0 = 0; - ti->ti_seq = htonl(seq); - ti->ti_ack = htonl(ack); - ti->ti_x2 = 0; - ti->ti_off = sizeof(struct tcphdr) >> 2; - ti->ti_flags = flags; - if (tp) - ti->ti_win = htons((uint16_t)(win >> tp->rcv_scale)); - else - ti->ti_win = htons((uint16_t)win); - ti->ti_urp = 0; - ti->ti_sum = 0; - ti->ti_sum = cksum(m, tlen); - - struct tcpiphdr tcpiph_save = *(mtod(m, struct tcpiphdr *)); - struct ip *ip; - struct ip6 *ip6; - - switch (af) { - case AF_INET: - m->m_data += - sizeof(struct tcpiphdr) - sizeof(struct tcphdr) - sizeof(struct ip); - m->m_len -= - sizeof(struct tcpiphdr) - sizeof(struct tcphdr) - sizeof(struct ip); - ip = mtod(m, struct ip *); - ip->ip_len = m->m_len; - ip->ip_dst = tcpiph_save.ti_dst; - ip->ip_src = tcpiph_save.ti_src; - ip->ip_p = tcpiph_save.ti_pr; - - if (flags & TH_RST) { - ip->ip_ttl = MAXTTL; - } else { - ip->ip_ttl = IPDEFTTL; - } - - ip_output(NULL, m); - break; - - case AF_INET6: - m->m_data += sizeof(struct tcpiphdr) - sizeof(struct tcphdr) - - sizeof(struct ip6); - m->m_len -= sizeof(struct tcpiphdr) - sizeof(struct tcphdr) - - sizeof(struct ip6); - ip6 = mtod(m, struct ip6 *); - ip6->ip_pl = tcpiph_save.ti_len; - ip6->ip_dst = tcpiph_save.ti_dst6; - ip6->ip_src = tcpiph_save.ti_src6; - ip6->ip_nh = tcpiph_save.ti_nh6; - - ip6_output(NULL, m, 0); - break; - - default: - g_assert_not_reached(); - } -} - -/* - * Create a new TCP control block, making an - * empty reassembly queue and hooking it to the argument - * protocol control block. - */ -struct tcpcb *tcp_newtcpcb(struct socket *so) -{ - register struct tcpcb *tp; - - tp = g_new0(struct tcpcb, 1); - tp->seg_next = tp->seg_prev = (struct tcpiphdr *)tp; - /* - * 40: length of IPv4 header (20) + TCP header (20) - * 60: length of IPv6 header (40) + TCP header (20) - */ - tp->t_maxseg = - MIN(so->slirp->if_mtu - ((so->so_ffamily == AF_INET) ? 40 : 60), - TCP_MAXSEG_MAX); - - tp->t_flags = TCP_DO_RFC1323 ? (TF_REQ_SCALE | TF_REQ_TSTMP) : 0; - tp->t_socket = so; - - /* - * Init srtt to TCPTV_SRTTBASE (0), so we can tell that we have no - * rtt estimate. Set rttvar so that srtt + 2 * rttvar gives - * reasonable initial retransmit time. - */ - tp->t_srtt = TCPTV_SRTTBASE; - tp->t_rttvar = TCPTV_SRTTDFLT << 2; - tp->t_rttmin = TCPTV_MIN; - - TCPT_RANGESET(tp->t_rxtcur, - ((TCPTV_SRTTBASE >> 2) + (TCPTV_SRTTDFLT << 2)) >> 1, - TCPTV_MIN, TCPTV_REXMTMAX); - - tp->snd_cwnd = TCP_MAXWIN << TCP_MAX_WINSHIFT; - tp->snd_ssthresh = TCP_MAXWIN << TCP_MAX_WINSHIFT; - tp->t_state = TCPS_CLOSED; - - so->so_tcpcb = tp; - - return (tp); -} - -/* - * Drop a TCP connection, reporting - * the specified error. If connection is synchronized, - * then send a RST to peer. - */ -struct tcpcb *tcp_drop(struct tcpcb *tp, int err) -{ - DEBUG_CALL("tcp_drop"); - DEBUG_ARG("tp = %p", tp); - DEBUG_ARG("errno = %d", errno); - - if (TCPS_HAVERCVDSYN(tp->t_state)) { - tp->t_state = TCPS_CLOSED; - (void)tcp_output(tp); - } - return (tcp_close(tp)); -} - -/* - * Close a TCP control block: - * discard all space held by the tcp - * discard internet protocol block - * wake up any sleepers - */ -struct tcpcb *tcp_close(struct tcpcb *tp) -{ - register struct tcpiphdr *t; - struct socket *so = tp->t_socket; - Slirp *slirp = so->slirp; - register struct mbuf *m; - - DEBUG_CALL("tcp_close"); - DEBUG_ARG("tp = %p", tp); - - /* free the reassembly queue, if any */ - t = tcpfrag_list_first(tp); - while (!tcpfrag_list_end(t, tp)) { - t = tcpiphdr_next(t); - m = tcpiphdr_prev(t)->ti_mbuf; - remque(tcpiphdr2qlink(tcpiphdr_prev(t))); - m_free(m); - } - g_free(tp); - so->so_tcpcb = NULL; - /* clobber input socket cache if we're closing the cached connection */ - if (so == slirp->tcp_last_so) - slirp->tcp_last_so = &slirp->tcb; - so->slirp->cb->unregister_poll_fd(so->s, so->slirp->opaque); - closesocket(so->s); - sbfree(&so->so_rcv); - sbfree(&so->so_snd); - sofree(so); - return ((struct tcpcb *)0); -} - -/* - * TCP protocol interface to socket abstraction. - */ - -/* - * User issued close, and wish to trail through shutdown states: - * if never received SYN, just forget it. If got a SYN from peer, - * but haven't sent FIN, then go to FIN_WAIT_1 state to send peer a FIN. - * If already got a FIN from peer, then almost done; go to LAST_ACK - * state. In all other cases, have already sent FIN to peer (e.g. - * after PRU_SHUTDOWN), and just have to play tedious game waiting - * for peer to send FIN or not respond to keep-alives, etc. - * We can let the user exit from the close as soon as the FIN is acked. - */ -void tcp_sockclosed(struct tcpcb *tp) -{ - DEBUG_CALL("tcp_sockclosed"); - DEBUG_ARG("tp = %p", tp); - - if (!tp) { - return; - } - - switch (tp->t_state) { - case TCPS_CLOSED: - case TCPS_LISTEN: - case TCPS_SYN_SENT: - tp->t_state = TCPS_CLOSED; - tcp_close(tp); - return; - - case TCPS_SYN_RECEIVED: - case TCPS_ESTABLISHED: - tp->t_state = TCPS_FIN_WAIT_1; - break; - - case TCPS_CLOSE_WAIT: - tp->t_state = TCPS_LAST_ACK; - break; - } - tcp_output(tp); -} - -/* - * Connect to a host on the Internet - * Called by tcp_input - * Only do a connect, the tcp fields will be set in tcp_input - * return 0 if there's a result of the connect, - * else return -1 means we're still connecting - * The return value is almost always -1 since the socket is - * nonblocking. Connect returns after the SYN is sent, and does - * not wait for ACK+SYN. - */ -int tcp_fconnect(struct socket *so, unsigned short af) -{ - int ret = 0; - - DEBUG_CALL("tcp_fconnect"); - DEBUG_ARG("so = %p", so); - - ret = so->s = slirp_socket(af, SOCK_STREAM, 0); - if (ret >= 0) { - ret = slirp_bind_outbound(so, af); - if (ret < 0) { - // bind failed - close socket - closesocket(so->s); - so->s = -1; - return (ret); - } - } - - if (ret >= 0) { - int opt, s = so->s; - struct sockaddr_storage addr; - - slirp_set_nonblock(s); - so->slirp->cb->register_poll_fd(so->s, so->slirp->opaque); - slirp_socket_set_fast_reuse(s); - opt = 1; - setsockopt(s, SOL_SOCKET, SO_OOBINLINE, &opt, sizeof(opt)); - opt = 1; - setsockopt(s, IPPROTO_TCP, TCP_NODELAY, &opt, sizeof(opt)); - - addr = so->fhost.ss; - DEBUG_CALL(" connect()ing"); - if (sotranslate_out(so, &addr) < 0) { - return -1; - } - - /* We don't care what port we get */ - ret = connect(s, (struct sockaddr *)&addr, sockaddr_size(&addr)); - - /* - * If it's not in progress, it failed, so we just return 0, - * without clearing SS_NOFDREF - */ - soisfconnecting(so); - } - - return (ret); -} - -/* - * Accept the socket and connect to the local-host - * - * We have a problem. The correct thing to do would be - * to first connect to the local-host, and only if the - * connection is accepted, then do an accept() here. - * But, a) we need to know who's trying to connect - * to the socket to be able to SYN the local-host, and - * b) we are already connected to the foreign host by - * the time it gets to accept(), so... We simply accept - * here and SYN the local-host. - */ -void tcp_connect(struct socket *inso) -{ - Slirp *slirp = inso->slirp; - struct socket *so; - struct sockaddr_storage addr; - socklen_t addrlen = sizeof(struct sockaddr_storage); - struct tcpcb *tp; - int s, opt; - - DEBUG_CALL("tcp_connect"); - DEBUG_ARG("inso = %p", inso); - - /* - * If it's an SS_ACCEPTONCE socket, no need to socreate() - * another socket, just use the accept() socket. - */ - if (inso->so_state & SS_FACCEPTONCE) { - /* FACCEPTONCE already have a tcpcb */ - so = inso; - } else { - so = socreate(slirp); - tcp_attach(so); - so->lhost = inso->lhost; - so->so_ffamily = inso->so_ffamily; - } - - tcp_mss(sototcpcb(so), 0); - - s = accept(inso->s, (struct sockaddr *)&addr, &addrlen); - if (s < 0) { - tcp_close(sototcpcb(so)); /* This will sofree() as well */ - return; - } - slirp_set_nonblock(s); - so->slirp->cb->register_poll_fd(so->s, so->slirp->opaque); - slirp_socket_set_fast_reuse(s); - opt = 1; - setsockopt(s, SOL_SOCKET, SO_OOBINLINE, &opt, sizeof(int)); - slirp_socket_set_nodelay(s); - - so->fhost.ss = addr; - sotranslate_accept(so); - - /* Close the accept() socket, set right state */ - if (inso->so_state & SS_FACCEPTONCE) { - /* If we only accept once, close the accept() socket */ - so->slirp->cb->unregister_poll_fd(so->s, so->slirp->opaque); - closesocket(so->s); - - /* Don't select it yet, even though we have an FD */ - /* if it's not FACCEPTONCE, it's already NOFDREF */ - so->so_state = SS_NOFDREF; - } - so->s = s; - so->so_state |= SS_INCOMING; - - so->so_iptos = tcp_tos(so); - tp = sototcpcb(so); - - tcp_template(tp); - - tp->t_state = TCPS_SYN_SENT; - tp->t_timer[TCPT_KEEP] = TCPTV_KEEP_INIT; - tp->iss = slirp->tcp_iss; - slirp->tcp_iss += TCP_ISSINCR / 2; - tcp_sendseqinit(tp); - tcp_output(tp); -} - -/* - * Attach a TCPCB to a socket. - */ -void tcp_attach(struct socket *so) -{ - so->so_tcpcb = tcp_newtcpcb(so); - insque(so, &so->slirp->tcb); -} - -/* - * Set the socket's type of service field - */ -static const struct tos_t tcptos[] = { - { 0, 20, IPTOS_THROUGHPUT, 0 }, /* ftp data */ - { 21, 21, IPTOS_LOWDELAY, EMU_FTP }, /* ftp control */ - { 0, 23, IPTOS_LOWDELAY, 0 }, /* telnet */ - { 0, 80, IPTOS_THROUGHPUT, 0 }, /* WWW */ - { 0, 513, IPTOS_LOWDELAY, EMU_RLOGIN | EMU_NOCONNECT }, /* rlogin */ - { 0, 544, IPTOS_LOWDELAY, EMU_KSH }, /* kshell */ - { 0, 543, IPTOS_LOWDELAY, 0 }, /* klogin */ - { 0, 6667, IPTOS_THROUGHPUT, EMU_IRC }, /* IRC */ - { 0, 6668, IPTOS_THROUGHPUT, EMU_IRC }, /* IRC undernet */ - { 0, 7070, IPTOS_LOWDELAY, EMU_REALAUDIO }, /* RealAudio control */ - { 0, 113, IPTOS_LOWDELAY, EMU_IDENT }, /* identd protocol */ - { 0, 0, 0, 0 } -}; - -/* - * Return TOS according to the above table - */ -uint8_t tcp_tos(struct socket *so) -{ - int i = 0; - - while (tcptos[i].tos) { - if ((tcptos[i].fport && (ntohs(so->so_fport) == tcptos[i].fport)) || - (tcptos[i].lport && (ntohs(so->so_lport) == tcptos[i].lport))) { - if (so->slirp->enable_emu) - so->so_emu = tcptos[i].emu; - return tcptos[i].tos; - } - i++; - } - return 0; -} - -/* - * Emulate programs that try and connect to us - * This includes ftp (the data connection is - * initiated by the server) and IRC (DCC CHAT and - * DCC SEND) for now - * - * NOTE: It's possible to crash SLiRP by sending it - * unstandard strings to emulate... if this is a problem, - * more checks are needed here - * - * XXX Assumes the whole command came in one packet - * XXX If there is more than one command in the packet, the others may - * be truncated. - * XXX If the command is too long, it may be truncated. - * - * XXX Some ftp clients will have their TOS set to - * LOWDELAY and so Nagel will kick in. Because of this, - * we'll get the first letter, followed by the rest, so - * we simply scan for ORT instead of PORT... - * DCC doesn't have this problem because there's other stuff - * in the packet before the DCC command. - * - * Return 1 if the mbuf m is still valid and should be - * sbappend()ed - * - * NOTE: if you return 0 you MUST m_free() the mbuf! - */ -int tcp_emu(struct socket *so, struct mbuf *m) -{ - Slirp *slirp = so->slirp; - unsigned n1, n2, n3, n4, n5, n6; - char buff[257]; - uint32_t laddr; - unsigned lport; - char *bptr; - - DEBUG_CALL("tcp_emu"); - DEBUG_ARG("so = %p", so); - DEBUG_ARG("m = %p", m); - - switch (so->so_emu) { - int x, i; - - /* TODO: IPv6 */ - case EMU_IDENT: - /* - * Identification protocol as per rfc-1413 - */ - - { - struct socket *tmpso; - struct sockaddr_in addr; - socklen_t addrlen = sizeof(struct sockaddr_in); - char *eol = g_strstr_len(m->m_data, m->m_len, "\r\n"); - - if (!eol) { - return 1; - } - - *eol = '\0'; - if (sscanf(m->m_data, "%u%*[ ,]%u", &n1, &n2) == 2) { - HTONS(n1); - HTONS(n2); - /* n2 is the one on our host */ - for (tmpso = slirp->tcb.so_next; tmpso != &slirp->tcb; - tmpso = tmpso->so_next) { - if (tmpso->so_laddr.s_addr == so->so_laddr.s_addr && - tmpso->so_lport == n2 && - tmpso->so_faddr.s_addr == so->so_faddr.s_addr && - tmpso->so_fport == n1) { - if (getsockname(tmpso->s, (struct sockaddr *)&addr, - &addrlen) == 0) - n2 = addr.sin_port; - break; - } - } - NTOHS(n1); - NTOHS(n2); - m_inc(m, g_snprintf(NULL, 0, "%d,%d\r\n", n1, n2) + 1); - m->m_len = slirp_fmt(m->m_data, M_ROOM(m), "%d,%d\r\n", n1, n2); - } else { - *eol = '\r'; - } - - return 1; - } - - case EMU_FTP: /* ftp */ - m_inc(m, m->m_len + 1); - *(m->m_data + m->m_len) = 0; /* NUL terminate for strstr */ - if ((bptr = (char *)strstr(m->m_data, "ORT")) != NULL) { - /* - * Need to emulate the PORT command - */ - x = sscanf(bptr, "ORT %u,%u,%u,%u,%u,%u\r\n%256[^\177]", &n1, &n2, - &n3, &n4, &n5, &n6, buff); - if (x < 6) - return 1; - - laddr = htonl((n1 << 24) | (n2 << 16) | (n3 << 8) | (n4)); - lport = htons((n5 << 8) | (n6)); - - if ((so = tcp_listen(slirp, INADDR_ANY, 0, laddr, lport, - SS_FACCEPTONCE)) == NULL) { - return 1; - } - n6 = ntohs(so->so_fport); - - n5 = (n6 >> 8) & 0xff; - n6 &= 0xff; - - laddr = ntohl(so->so_faddr.s_addr); - - n1 = ((laddr >> 24) & 0xff); - n2 = ((laddr >> 16) & 0xff); - n3 = ((laddr >> 8) & 0xff); - n4 = (laddr & 0xff); - - m->m_len = bptr - m->m_data; /* Adjust length */ - m->m_len += slirp_fmt(bptr, M_FREEROOM(m), - "ORT %d,%d,%d,%d,%d,%d\r\n%s", - n1, n2, n3, n4, n5, n6, x == 7 ? buff : ""); - return 1; - } else if ((bptr = (char *)strstr(m->m_data, "27 Entering")) != NULL) { - /* - * Need to emulate the PASV response - */ - x = sscanf( - bptr, - "27 Entering Passive Mode (%u,%u,%u,%u,%u,%u)\r\n%256[^\177]", - &n1, &n2, &n3, &n4, &n5, &n6, buff); - if (x < 6) - return 1; - - laddr = htonl((n1 << 24) | (n2 << 16) | (n3 << 8) | (n4)); - lport = htons((n5 << 8) | (n6)); - - if ((so = tcp_listen(slirp, INADDR_ANY, 0, laddr, lport, - SS_FACCEPTONCE)) == NULL) { - return 1; - } - n6 = ntohs(so->so_fport); - - n5 = (n6 >> 8) & 0xff; - n6 &= 0xff; - - laddr = ntohl(so->so_faddr.s_addr); - - n1 = ((laddr >> 24) & 0xff); - n2 = ((laddr >> 16) & 0xff); - n3 = ((laddr >> 8) & 0xff); - n4 = (laddr & 0xff); - - m->m_len = bptr - m->m_data; /* Adjust length */ - m->m_len += slirp_fmt(bptr, M_FREEROOM(m), - "27 Entering Passive Mode (%d,%d,%d,%d,%d,%d)\r\n%s", - n1, n2, n3, n4, n5, n6, x == 7 ? buff : ""); - return 1; - } - - return 1; - - case EMU_KSH: - /* - * The kshell (Kerberos rsh) and shell services both pass - * a local port port number to carry signals to the server - * and stderr to the client. It is passed at the beginning - * of the connection as a NUL-terminated decimal ASCII string. - */ - so->so_emu = 0; - for (lport = 0, i = 0; i < m->m_len - 1; ++i) { - if (m->m_data[i] < '0' || m->m_data[i] > '9') - return 1; /* invalid number */ - lport *= 10; - lport += m->m_data[i] - '0'; - } - if (m->m_data[m->m_len - 1] == '\0' && lport != 0 && - (so = tcp_listen(slirp, INADDR_ANY, 0, so->so_laddr.s_addr, - htons(lport), SS_FACCEPTONCE)) != NULL) - m->m_len = slirp_fmt0(m->m_data, M_ROOM(m), - "%d", ntohs(so->so_fport)); - return 1; - - case EMU_IRC: - /* - * Need to emulate DCC CHAT, DCC SEND and DCC MOVE - */ - m_inc(m, m->m_len + 1); - *(m->m_data + m->m_len) = 0; /* NULL terminate the string for strstr */ - if ((bptr = (char *)strstr(m->m_data, "DCC")) == NULL) - return 1; - - /* The %256s is for the broken mIRC */ - if (sscanf(bptr, "DCC CHAT %256s %u %u", buff, &laddr, &lport) == 3) { - if ((so = tcp_listen(slirp, INADDR_ANY, 0, htonl(laddr), - htons(lport), SS_FACCEPTONCE)) == NULL) { - return 1; - } - m->m_len = bptr - m->m_data; /* Adjust length */ - m->m_len += slirp_fmt(bptr, M_FREEROOM(m), - "DCC CHAT chat %lu %u%c\n", - (unsigned long)ntohl(so->so_faddr.s_addr), - ntohs(so->so_fport), 1); - } else if (sscanf(bptr, "DCC SEND %256s %u %u %u", buff, &laddr, &lport, - &n1) == 4) { - if ((so = tcp_listen(slirp, INADDR_ANY, 0, htonl(laddr), - htons(lport), SS_FACCEPTONCE)) == NULL) { - return 1; - } - m->m_len = bptr - m->m_data; /* Adjust length */ - m->m_len += slirp_fmt(bptr, M_FREEROOM(m), - "DCC SEND %s %lu %u %u%c\n", buff, - (unsigned long)ntohl(so->so_faddr.s_addr), - ntohs(so->so_fport), n1, 1); - } else if (sscanf(bptr, "DCC MOVE %256s %u %u %u", buff, &laddr, &lport, - &n1) == 4) { - if ((so = tcp_listen(slirp, INADDR_ANY, 0, htonl(laddr), - htons(lport), SS_FACCEPTONCE)) == NULL) { - return 1; - } - m->m_len = bptr - m->m_data; /* Adjust length */ - m->m_len += slirp_fmt(bptr, M_FREEROOM(m), - "DCC MOVE %s %lu %u %u%c\n", buff, - (unsigned long)ntohl(so->so_faddr.s_addr), - ntohs(so->so_fport), n1, 1); - } - return 1; - - case EMU_REALAUDIO: - /* - * RealAudio emulation - JP. We must try to parse the incoming - * data and try to find the two characters that contain the - * port number. Then we redirect an udp port and replace the - * number with the real port we got. - * - * The 1.0 beta versions of the player are not supported - * any more. - * - * A typical packet for player version 1.0 (release version): - * - * 0000:50 4E 41 00 05 - * 0000:00 01 00 02 1B D7 00 00 67 E6 6C DC 63 00 12 50 ........g.l.c..P - * 0010:4E 43 4C 49 45 4E 54 20 31 30 31 20 41 4C 50 48 NCLIENT 101 ALPH - * 0020:41 6C 00 00 52 00 17 72 61 66 69 6C 65 73 2F 76 Al..R..rafiles/v - * 0030:6F 61 2F 65 6E 67 6C 69 73 68 5F 2E 72 61 79 42 oa/english_.rayB - * - * Now the port number 0x1BD7 is found at offset 0x04 of the - * Now the port number 0x1BD7 is found at offset 0x04 of the - * second packet. This time we received five bytes first and - * then the rest. You never know how many bytes you get. - * - * A typical packet for player version 2.0 (beta): - * - * 0000:50 4E 41 00 06 00 02 00 00 00 01 00 02 1B C1 00 PNA............. - * 0010:00 67 75 78 F5 63 00 0A 57 69 6E 32 2E 30 2E 30 .gux.c..Win2.0.0 - * 0020:2E 35 6C 00 00 52 00 1C 72 61 66 69 6C 65 73 2F .5l..R..rafiles/ - * 0030:77 65 62 73 69 74 65 2F 32 30 72 65 6C 65 61 73 website/20releas - * 0040:65 2E 72 61 79 53 00 00 06 36 42 e.rayS...6B - * - * Port number 0x1BC1 is found at offset 0x0d. - * - * This is just a horrible switch statement. Variable ra tells - * us where we're going. - */ - - bptr = m->m_data; - while (bptr < m->m_data + m->m_len) { - uint16_t p; - static int ra = 0; - char ra_tbl[4]; - - ra_tbl[0] = 0x50; - ra_tbl[1] = 0x4e; - ra_tbl[2] = 0x41; - ra_tbl[3] = 0; - - switch (ra) { - case 0: - case 2: - case 3: - if (*bptr++ != ra_tbl[ra]) { - ra = 0; - continue; - } - break; - - case 1: - /* - * We may get 0x50 several times, ignore them - */ - if (*bptr == 0x50) { - ra = 1; - bptr++; - continue; - } else if (*bptr++ != ra_tbl[ra]) { - ra = 0; - continue; - } - break; - - case 4: - /* - * skip version number - */ - bptr++; - break; - - case 5: - if (bptr == m->m_data + m->m_len - 1) - return 1; /* We need two bytes */ - - /* - * The difference between versions 1.0 and - * 2.0 is here. For future versions of - * the player this may need to be modified. - */ - if (*(bptr + 1) == 0x02) - bptr += 8; - else - bptr += 4; - break; - - case 6: - /* This is the field containing the port - * number that RA-player is listening to. - */ - - if (bptr == m->m_data + m->m_len - 1) - return 1; /* We need two bytes */ - - lport = (((uint8_t *)bptr)[0] << 8) + ((uint8_t *)bptr)[1]; - if (lport < 6970) - lport += 256; /* don't know why */ - if (lport < 6970 || lport > 7170) - return 1; /* failed */ - - /* try to get udp port between 6970 - 7170 */ - for (p = 6970; p < 7071; p++) { - if (udp_listen(slirp, INADDR_ANY, htons(p), - so->so_laddr.s_addr, htons(lport), - SS_FACCEPTONCE)) { - break; - } - } - if (p == 7071) - p = 0; - *(uint8_t *)bptr++ = (p >> 8) & 0xff; - *(uint8_t *)bptr = p & 0xff; - ra = 0; - return 1; /* port redirected, we're done */ - break; - - default: - ra = 0; - } - ra++; - } - return 1; - - default: - /* Ooops, not emulated, won't call tcp_emu again */ - so->so_emu = 0; - return 1; - } -} - -/* - * Do misc. config of SLiRP while its running. - * Return 0 if this connections is to be closed, 1 otherwise, - * return 2 if this is a command-line connection - */ -int tcp_ctl(struct socket *so) -{ - Slirp *slirp = so->slirp; - struct sbuf *sb = &so->so_snd; - struct gfwd_list *ex_ptr; - - DEBUG_CALL("tcp_ctl"); - DEBUG_ARG("so = %p", so); - - /* TODO: IPv6 */ - if (so->so_faddr.s_addr != slirp->vhost_addr.s_addr) { - /* Check if it's pty_exec */ - for (ex_ptr = slirp->guestfwd_list; ex_ptr; ex_ptr = ex_ptr->ex_next) { - if (ex_ptr->ex_fport == so->so_fport && - so->so_faddr.s_addr == ex_ptr->ex_addr.s_addr) { - if (ex_ptr->write_cb) { - so->s = -1; - so->guestfwd = ex_ptr; - return 1; - } - DEBUG_MISC(" executing %s", ex_ptr->ex_exec); - if (ex_ptr->ex_unix) - return open_unix(so, ex_ptr->ex_unix); - else - return fork_exec(so, ex_ptr->ex_exec); - } - } - } - sb->sb_cc = slirp_fmt(sb->sb_wptr, sb->sb_datalen - (sb->sb_wptr - sb->sb_data), - "Error: No application configured.\r\n"); - sb->sb_wptr += sb->sb_cc; - return 0; -} diff --git a/src/network/slirp/tcp_timer.c b/src/network/slirp/tcp_timer.c deleted file mode 100644 index 102023e7c..000000000 --- a/src/network/slirp/tcp_timer.c +++ /dev/null @@ -1,286 +0,0 @@ -/* SPDX-License-Identifier: BSD-3-Clause */ -/* - * Copyright (c) 1982, 1986, 1988, 1990, 1993 - * The Regents of the University of California. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. Neither the name of the University nor the names of its contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - * - * @(#)tcp_timer.c 8.1 (Berkeley) 6/10/93 - * tcp_timer.c,v 1.2 1994/08/02 07:49:10 davidg Exp - */ - -#include "slirp.h" - -static struct tcpcb *tcp_timers(register struct tcpcb *tp, int timer); - -/* - * Fast timeout routine for processing delayed acks - */ -void tcp_fasttimo(Slirp *slirp) -{ - register struct socket *so; - register struct tcpcb *tp; - - DEBUG_CALL("tcp_fasttimo"); - - so = slirp->tcb.so_next; - if (so) - for (; so != &slirp->tcb; so = so->so_next) - if ((tp = (struct tcpcb *)so->so_tcpcb) && - (tp->t_flags & TF_DELACK)) { - tp->t_flags &= ~TF_DELACK; - tp->t_flags |= TF_ACKNOW; - (void)tcp_output(tp); - } -} - -/* - * Tcp protocol timeout routine called every 500 ms. - * Updates the timers in all active tcb's and - * causes finite state machine actions if timers expire. - */ -void tcp_slowtimo(Slirp *slirp) -{ - register struct socket *ip, *ipnxt; - register struct tcpcb *tp; - register int i; - - DEBUG_CALL("tcp_slowtimo"); - - /* - * Search through tcb's and update active timers. - */ - ip = slirp->tcb.so_next; - if (ip == NULL) { - return; - } - for (; ip != &slirp->tcb; ip = ipnxt) { - ipnxt = ip->so_next; - tp = sototcpcb(ip); - if (tp == NULL) { - continue; - } - for (i = 0; i < TCPT_NTIMERS; i++) { - if (tp->t_timer[i] && --tp->t_timer[i] == 0) { - tcp_timers(tp, i); - if (ipnxt->so_prev != ip) - goto tpgone; - } - } - tp->t_idle++; - if (tp->t_rtt) - tp->t_rtt++; - tpgone:; - } - slirp->tcp_iss += TCP_ISSINCR / PR_SLOWHZ; /* increment iss */ - slirp->tcp_now++; /* for timestamps */ -} - -/* - * Cancel all timers for TCP tp. - */ -void tcp_canceltimers(struct tcpcb *tp) -{ - register int i; - - for (i = 0; i < TCPT_NTIMERS; i++) - tp->t_timer[i] = 0; -} - -const int tcp_backoff[TCP_MAXRXTSHIFT + 1] = { 1, 2, 4, 8, 16, 32, 64, - 64, 64, 64, 64, 64, 64 }; - -/* - * TCP timer processing. - */ -static struct tcpcb *tcp_timers(register struct tcpcb *tp, int timer) -{ - register int rexmt; - - DEBUG_CALL("tcp_timers"); - - switch (timer) { - /* - * 2 MSL timeout in shutdown went off. If we're closed but - * still waiting for peer to close and connection has been idle - * too long, or if 2MSL time is up from TIME_WAIT, delete connection - * control block. Otherwise, check again in a bit. - */ - case TCPT_2MSL: - if (tp->t_state != TCPS_TIME_WAIT && tp->t_idle <= TCP_MAXIDLE) - tp->t_timer[TCPT_2MSL] = TCPTV_KEEPINTVL; - else - tp = tcp_close(tp); - break; - - /* - * Retransmission timer went off. Message has not - * been acked within retransmit interval. Back off - * to a longer retransmit interval and retransmit one segment. - */ - case TCPT_REXMT: - - /* - * XXXXX If a packet has timed out, then remove all the queued - * packets for that session. - */ - - if (++tp->t_rxtshift > TCP_MAXRXTSHIFT) { - /* - * This is a hack to suit our terminal server here at the uni of - * canberra since they have trouble with zeroes... It usually lets - * them through unharmed, but under some conditions, it'll eat the - * zeros. If we keep retransmitting it, it'll keep eating the - * zeroes, so we keep retransmitting, and eventually the connection - * dies... (this only happens on incoming data) - * - * So, if we were gonna drop the connection from too many - * retransmits, don't... instead halve the t_maxseg, which might - * break up the NULLs and let them through - * - * *sigh* - */ - - tp->t_maxseg >>= 1; - if (tp->t_maxseg < 32) { - /* - * We tried our best, now the connection must die! - */ - tp->t_rxtshift = TCP_MAXRXTSHIFT; - tp = tcp_drop(tp, tp->t_softerror); - /* tp->t_softerror : ETIMEDOUT); */ /* XXX */ - return (tp); /* XXX */ - } - - /* - * Set rxtshift to 6, which is still at the maximum - * backoff time - */ - tp->t_rxtshift = 6; - } - rexmt = TCP_REXMTVAL(tp) * tcp_backoff[tp->t_rxtshift]; - TCPT_RANGESET(tp->t_rxtcur, rexmt, (short)tp->t_rttmin, - TCPTV_REXMTMAX); /* XXX */ - tp->t_timer[TCPT_REXMT] = tp->t_rxtcur; - /* - * If losing, let the lower level know and try for - * a better route. Also, if we backed off this far, - * our srtt estimate is probably bogus. Clobber it - * so we'll take the next rtt measurement as our srtt; - * move the current srtt into rttvar to keep the current - * retransmit times until then. - */ - if (tp->t_rxtshift > TCP_MAXRXTSHIFT / 4) { - tp->t_rttvar += (tp->t_srtt >> TCP_RTT_SHIFT); - tp->t_srtt = 0; - } - tp->snd_nxt = tp->snd_una; - /* - * If timing a segment in this window, stop the timer. - */ - tp->t_rtt = 0; - /* - * Close the congestion window down to one segment - * (we'll open it by one segment for each ack we get). - * Since we probably have a window's worth of unacked - * data accumulated, this "slow start" keeps us from - * dumping all that data as back-to-back packets (which - * might overwhelm an intermediate gateway). - * - * There are two phases to the opening: Initially we - * open by one mss on each ack. This makes the window - * size increase exponentially with time. If the - * window is larger than the path can handle, this - * exponential growth results in dropped packet(s) - * almost immediately. To get more time between - * drops but still "push" the network to take advantage - * of improving conditions, we switch from exponential - * to linear window opening at some threshold size. - * For a threshold, we use half the current window - * size, truncated to a multiple of the mss. - * - * (the minimum cwnd that will give us exponential - * growth is 2 mss. We don't allow the threshold - * to go below this.) - */ - { - unsigned win = MIN(tp->snd_wnd, tp->snd_cwnd) / 2 / tp->t_maxseg; - if (win < 2) - win = 2; - tp->snd_cwnd = tp->t_maxseg; - tp->snd_ssthresh = win * tp->t_maxseg; - tp->t_dupacks = 0; - } - (void)tcp_output(tp); - break; - - /* - * Persistence timer into zero window. - * Force a byte to be output, if possible. - */ - case TCPT_PERSIST: - tcp_setpersist(tp); - tp->t_force = 1; - (void)tcp_output(tp); - tp->t_force = 0; - break; - - /* - * Keep-alive timer went off; send something - * or drop connection if idle for too long. - */ - case TCPT_KEEP: - if (tp->t_state < TCPS_ESTABLISHED) - goto dropit; - - if (slirp_do_keepalive && tp->t_state <= TCPS_CLOSE_WAIT) { - if (tp->t_idle >= TCPTV_KEEP_IDLE + TCP_MAXIDLE) - goto dropit; - /* - * Send a packet designed to force a response - * if the peer is up and reachable: - * either an ACK if the connection is still alive, - * or an RST if the peer has closed the connection - * due to timeout or reboot. - * Using sequence number tp->snd_una-1 - * causes the transmitted zero-length segment - * to lie outside the receive window; - * by the protocol spec, this requires the - * correspondent TCP to respond. - */ - tcp_respond(tp, &tp->t_template, (struct mbuf *)NULL, tp->rcv_nxt, - tp->snd_una - 1, 0, tp->t_socket->so_ffamily); - tp->t_timer[TCPT_KEEP] = TCPTV_KEEPINTVL; - } else - tp->t_timer[TCPT_KEEP] = TCPTV_KEEP_IDLE; - break; - - dropit: - tp = tcp_drop(tp, 0); - break; - } - - return (tp); -} diff --git a/src/network/slirp/tcp_timer.h b/src/network/slirp/tcp_timer.h deleted file mode 100644 index 584a5594e..000000000 --- a/src/network/slirp/tcp_timer.h +++ /dev/null @@ -1,130 +0,0 @@ -/* SPDX-License-Identifier: BSD-3-Clause */ -/* - * Copyright (c) 1982, 1986, 1993 - * The Regents of the University of California. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. Neither the name of the University nor the names of its contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - * - * @(#)tcp_timer.h 8.1 (Berkeley) 6/10/93 - * tcp_timer.h,v 1.4 1994/08/21 05:27:38 paul Exp - */ - -#ifndef TCP_TIMER_H -#define TCP_TIMER_H - -/* - * Definitions of the TCP timers. These timers are counted - * down PR_SLOWHZ times a second. - */ -#define TCPT_NTIMERS 4 - -#define TCPT_REXMT 0 /* retransmit */ -#define TCPT_PERSIST 1 /* retransmit persistence */ -#define TCPT_KEEP 2 /* keep alive */ -#define TCPT_2MSL 3 /* 2*msl quiet time timer */ - -/* - * The TCPT_REXMT timer is used to force retransmissions. - * The TCP has the TCPT_REXMT timer set whenever segments - * have been sent for which ACKs are expected but not yet - * received. If an ACK is received which advances tp->snd_una, - * then the retransmit timer is cleared (if there are no more - * outstanding segments) or reset to the base value (if there - * are more ACKs expected). Whenever the retransmit timer goes off, - * we retransmit one unacknowledged segment, and do a backoff - * on the retransmit timer. - * - * The TCPT_PERSIST timer is used to keep window size information - * flowing even if the window goes shut. If all previous transmissions - * have been acknowledged (so that there are no retransmissions in progress), - * and the window is too small to bother sending anything, then we start - * the TCPT_PERSIST timer. When it expires, if the window is nonzero, - * we go to transmit state. Otherwise, at intervals send a single byte - * into the peer's window to force him to update our window information. - * We do this at most as often as TCPT_PERSMIN time intervals, - * but no more frequently than the current estimate of round-trip - * packet time. The TCPT_PERSIST timer is cleared whenever we receive - * a window update from the peer. - * - * The TCPT_KEEP timer is used to keep connections alive. If an - * connection is idle (no segments received) for TCPTV_KEEP_INIT amount of time, - * but not yet established, then we drop the connection. Once the connection - * is established, if the connection is idle for TCPTV_KEEP_IDLE time - * (and keepalives have been enabled on the socket), we begin to probe - * the connection. We force the peer to send us a segment by sending: - * - * This segment is (deliberately) outside the window, and should elicit - * an ack segment in response from the peer. If, despite the TCPT_KEEP - * initiated segments we cannot elicit a response from a peer in TCPT_MAXIDLE - * amount of time probing, then we drop the connection. - */ - -/* - * Time constants. - */ -#define TCPTV_MSL (5 * PR_SLOWHZ) /* max seg lifetime (hah!) */ - -#define TCPTV_SRTTBASE \ - 0 /* base roundtrip time; \ - if 0, no idea yet */ -#define TCPTV_SRTTDFLT (3 * PR_SLOWHZ) /* assumed RTT if no info */ - -#define TCPTV_PERSMIN (5 * PR_SLOWHZ) /* retransmit persistence */ -#define TCPTV_PERSMAX (60 * PR_SLOWHZ) /* maximum persist interval */ - -#define TCPTV_KEEP_INIT (75 * PR_SLOWHZ) /* initial connect keep alive */ -#define TCPTV_KEEP_IDLE (120 * 60 * PR_SLOWHZ) /* dflt time before probing */ -#define TCPTV_KEEPINTVL (75 * PR_SLOWHZ) /* default probe interval */ -#define TCPTV_KEEPCNT 8 /* max probes before drop */ - -#define TCPTV_MIN (1 * PR_SLOWHZ) /* minimum allowable value */ -#define TCPTV_REXMTMAX (12 * PR_SLOWHZ) /* max allowable REXMT value */ - -#define TCP_LINGERTIME 120 /* linger at most 2 minutes */ - -#define TCP_MAXRXTSHIFT 12 /* maximum retransmits */ - - -/* - * Force a time value to be in a certain range. - */ -#define TCPT_RANGESET(tv, value, tvmin, tvmax) \ - { \ - (tv) = (value); \ - if ((tv) < (tvmin)) \ - (tv) = (tvmin); \ - else if ((tv) > (tvmax)) \ - (tv) = (tvmax); \ - } - -extern const int tcp_backoff[]; - -struct tcpcb; - -void tcp_fasttimo(Slirp *); -void tcp_slowtimo(Slirp *); -void tcp_canceltimers(struct tcpcb *); - -#endif diff --git a/src/network/slirp/tcp_var.h b/src/network/slirp/tcp_var.h deleted file mode 100644 index c8da8cbd1..000000000 --- a/src/network/slirp/tcp_var.h +++ /dev/null @@ -1,161 +0,0 @@ -/* SPDX-License-Identifier: BSD-3-Clause */ -/* - * Copyright (c) 1982, 1986, 1993, 1994 - * The Regents of the University of California. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. Neither the name of the University nor the names of its contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - * - * @(#)tcp_var.h 8.3 (Berkeley) 4/10/94 - * tcp_var.h,v 1.3 1994/08/21 05:27:39 paul Exp - */ - -#ifndef TCP_VAR_H -#define TCP_VAR_H - -#include "tcpip.h" -#include "tcp_timer.h" - -/* - * Tcp control block, one per tcp; fields: - */ -struct tcpcb { - struct tcpiphdr *seg_next; /* sequencing queue */ - struct tcpiphdr *seg_prev; - short t_state; /* state of this connection */ - short t_timer[TCPT_NTIMERS]; /* tcp timers */ - short t_rxtshift; /* log(2) of rexmt exp. backoff */ - short t_rxtcur; /* current retransmit value */ - short t_dupacks; /* consecutive dup acks recd */ - uint16_t t_maxseg; /* maximum segment size */ - uint8_t t_force; /* 1 if forcing out a byte */ - uint16_t t_flags; -#define TF_ACKNOW 0x0001 /* ack peer immediately */ -#define TF_DELACK 0x0002 /* ack, but try to delay it */ -#define TF_NODELAY 0x0004 /* don't delay packets to coalesce */ -#define TF_NOOPT 0x0008 /* don't use tcp options */ -#define TF_SENTFIN 0x0010 /* have sent FIN */ -#define TF_REQ_SCALE 0x0020 /* have/will request window scaling */ -#define TF_RCVD_SCALE 0x0040 /* other side has requested scaling */ -#define TF_REQ_TSTMP 0x0080 /* have/will request timestamps */ -#define TF_RCVD_TSTMP 0x0100 /* a timestamp was received in SYN */ -#define TF_SACK_PERMIT 0x0200 /* other side said I could SACK */ - - struct tcpiphdr t_template; /* static skeletal packet for xmit */ - - struct socket *t_socket; /* back pointer to socket */ - /* - * The following fields are used as in the protocol specification. - * See RFC783, Dec. 1981, page 21. - */ - /* send sequence variables */ - tcp_seq snd_una; /* send unacknowledged */ - tcp_seq snd_nxt; /* send next */ - tcp_seq snd_up; /* send urgent pointer */ - tcp_seq snd_wl1; /* window update seg seq number */ - tcp_seq snd_wl2; /* window update seg ack number */ - tcp_seq iss; /* initial send sequence number */ - uint32_t snd_wnd; /* send window */ - /* receive sequence variables */ - uint32_t rcv_wnd; /* receive window */ - tcp_seq rcv_nxt; /* receive next */ - tcp_seq rcv_up; /* receive urgent pointer */ - tcp_seq irs; /* initial receive sequence number */ - /* - * Additional variables for this implementation. - */ - /* receive variables */ - tcp_seq rcv_adv; /* advertised window */ - /* retransmit variables */ - tcp_seq snd_max; /* highest sequence number sent; - * used to recognize retransmits - */ - /* congestion control (for slow start, source quench, retransmit after loss) - */ - uint32_t snd_cwnd; /* congestion-controlled window */ - uint32_t snd_ssthresh; /* snd_cwnd size threshold for - * for slow start exponential to - * linear switch - */ - /* - * transmit timing stuff. See below for scale of srtt and rttvar. - * "Variance" is actually smoothed difference. - */ - short t_idle; /* inactivity time */ - short t_rtt; /* round trip time */ - tcp_seq t_rtseq; /* sequence number being timed */ - short t_srtt; /* smoothed round-trip time */ - short t_rttvar; /* variance in round-trip time */ - uint16_t t_rttmin; /* minimum rtt allowed */ - uint32_t max_sndwnd; /* largest window peer has offered */ - - /* out-of-band data */ - uint8_t t_oobflags; /* have some */ - uint8_t t_iobc; /* input character */ -#define TCPOOB_HAVEDATA 0x01 -#define TCPOOB_HADDATA 0x02 - short t_softerror; /* possible error not yet reported */ - - /* RFC 1323 variables */ - uint8_t snd_scale; /* window scaling for send window */ - uint8_t rcv_scale; /* window scaling for recv window */ - uint8_t request_r_scale; /* pending window scaling */ - uint8_t requested_s_scale; - uint32_t ts_recent; /* timestamp echo data */ - uint32_t ts_recent_age; /* when last updated */ - tcp_seq last_ack_sent; -}; - -#define sototcpcb(so) ((so)->so_tcpcb) - -/* - * The smoothed round-trip time and estimated variance - * are stored as fixed point numbers scaled by the values below. - * For convenience, these scales are also used in smoothing the average - * (smoothed = (1/scale)sample + ((scale-1)/scale)smoothed). - * With these scales, srtt has 3 bits to the right of the binary point, - * and thus an "ALPHA" of 0.875. rttvar has 2 bits to the right of the - * binary point, and is smoothed with an ALPHA of 0.75. - */ -#define TCP_RTT_SCALE 8 /* multiplier for srtt; 3 bits frac. */ -#define TCP_RTT_SHIFT 3 /* shift for srtt; 3 bits frac. */ -#define TCP_RTTVAR_SCALE 4 /* multiplier for rttvar; 2 bits */ -#define TCP_RTTVAR_SHIFT 2 /* multiplier for rttvar; 2 bits */ - -/* - * The initial retransmission should happen at rtt + 4 * rttvar. - * Because of the way we do the smoothing, srtt and rttvar - * will each average +1/2 tick of bias. When we compute - * the retransmit timer, we want 1/2 tick of rounding and - * 1 extra tick because of +-1/2 tick uncertainty in the - * firing of the timer. The bias will give us exactly the - * 1.5 tick we need. But, because the bias is - * statistical, we have to test that we don't drop below - * the minimum feasible timer (which is 2 ticks). - * This macro assumes that the value of TCP_RTTVAR_SCALE - * is the same as the multiplier for rttvar. - */ -#define TCP_REXMTVAL(tp) (((tp)->t_srtt >> TCP_RTT_SHIFT) + (tp)->t_rttvar) - -#endif diff --git a/src/network/slirp/tcpip.h b/src/network/slirp/tcpip.h deleted file mode 100644 index d3df02149..000000000 --- a/src/network/slirp/tcpip.h +++ /dev/null @@ -1,104 +0,0 @@ -/* SPDX-License-Identifier: BSD-3-Clause */ -/* - * Copyright (c) 1982, 1986, 1993 - * The Regents of the University of California. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. Neither the name of the University nor the names of its contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - * - * @(#)tcpip.h 8.1 (Berkeley) 6/10/93 - * tcpip.h,v 1.3 1994/08/21 05:27:40 paul Exp - */ - -#ifndef TCPIP_H -#define TCPIP_H - -/* - * Tcp+ip header, after ip options removed. - */ -struct tcpiphdr { - struct mbuf_ptr ih_mbuf; /* backpointer to mbuf */ - union { - struct { - struct in_addr ih_src; /* source internet address */ - struct in_addr ih_dst; /* destination internet address */ - uint8_t ih_x1; /* (unused) */ - uint8_t ih_pr; /* protocol */ - } ti_i4; - struct { - struct in6_addr ih_src; - struct in6_addr ih_dst; - uint8_t ih_x1; - uint8_t ih_nh; - } ti_i6; - } ti; - uint16_t ti_x0; - uint16_t ti_len; /* protocol length */ - struct tcphdr ti_t; /* tcp header */ -}; -#define ti_mbuf ih_mbuf.mptr -#define ti_pr ti.ti_i4.ih_pr -#define ti_src ti.ti_i4.ih_src -#define ti_dst ti.ti_i4.ih_dst -#define ti_src6 ti.ti_i6.ih_src -#define ti_dst6 ti.ti_i6.ih_dst -#define ti_nh6 ti.ti_i6.ih_nh -#define ti_sport ti_t.th_sport -#define ti_dport ti_t.th_dport -#define ti_seq ti_t.th_seq -#define ti_ack ti_t.th_ack -#define ti_x2 ti_t.th_x2 -#define ti_off ti_t.th_off -#define ti_flags ti_t.th_flags -#define ti_win ti_t.th_win -#define ti_sum ti_t.th_sum -#define ti_urp ti_t.th_urp - -#define tcpiphdr2qlink(T) \ - ((struct qlink *)(((char *)(T)) - sizeof(struct qlink))) -#define qlink2tcpiphdr(Q) \ - ((struct tcpiphdr *)(((char *)(Q)) + sizeof(struct qlink))) -#define tcpiphdr_next(T) qlink2tcpiphdr(tcpiphdr2qlink(T)->next) -#define tcpiphdr_prev(T) qlink2tcpiphdr(tcpiphdr2qlink(T)->prev) -#define tcpfrag_list_first(T) qlink2tcpiphdr((T)->seg_next) -#define tcpfrag_list_end(F, T) (tcpiphdr2qlink(F) == (struct qlink *)(T)) -#define tcpfrag_list_empty(T) ((T)->seg_next == (struct tcpiphdr *)(T)) - -/* This is the difference between the size of a tcpiphdr structure, and the - * size of actual ip+tcp headers, rounded up since we need to align data. */ -#define TCPIPHDR_DELTA \ - (MAX(0, (sizeof(struct tcpiphdr) - sizeof(struct ip) - \ - sizeof(struct tcphdr) + 3) & \ - ~3)) - -/* - * Just a clean way to get to the first byte - * of the packet - */ -struct tcpiphdr_2 { - struct tcpiphdr dummy; - char first_char; -}; - -#endif diff --git a/src/network/slirp/tftp.c b/src/network/slirp/tftp.c deleted file mode 100644 index c6950ee10..000000000 --- a/src/network/slirp/tftp.c +++ /dev/null @@ -1,464 +0,0 @@ -/* SPDX-License-Identifier: MIT */ -/* - * tftp.c - a simple, read-only tftp server for qemu - * - * Copyright (c) 2004 Magnus Damm - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL - * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ - -#include "slirp.h" - -#include -#include -#include - -static inline int tftp_session_in_use(struct tftp_session *spt) -{ - return (spt->slirp != NULL); -} - -static inline void tftp_session_update(struct tftp_session *spt) -{ - spt->timestamp = curtime; -} - -static void tftp_session_terminate(struct tftp_session *spt) -{ - if (spt->fd >= 0) { - close(spt->fd); - spt->fd = -1; - } - g_free(spt->filename); - spt->slirp = NULL; -} - -static int tftp_session_allocate(Slirp *slirp, struct sockaddr_storage *srcsas, - struct tftp_t *tp) -{ - struct tftp_session *spt; - int k; - - for (k = 0; k < TFTP_SESSIONS_MAX; k++) { - spt = &slirp->tftp_sessions[k]; - - if (!tftp_session_in_use(spt)) - goto found; - - /* sessions time out after 5 inactive seconds */ - if ((int)(curtime - spt->timestamp) > 5000) { - tftp_session_terminate(spt); - goto found; - } - } - - return -1; - -found: - memset(spt, 0, sizeof(*spt)); - memcpy(&spt->client_addr, srcsas, sockaddr_size(srcsas)); - spt->fd = -1; - spt->block_size = 512; - spt->client_port = tp->udp.uh_sport; - spt->slirp = slirp; - - tftp_session_update(spt); - - return k; -} - -static int tftp_session_find(Slirp *slirp, struct sockaddr_storage *srcsas, - struct tftp_t *tp) -{ - struct tftp_session *spt; - int k; - - for (k = 0; k < TFTP_SESSIONS_MAX; k++) { - spt = &slirp->tftp_sessions[k]; - - if (tftp_session_in_use(spt)) { - if (sockaddr_equal(&spt->client_addr, srcsas)) { - if (spt->client_port == tp->udp.uh_sport) { - return k; - } - } - } - } - - return -1; -} - -static int tftp_read_data(struct tftp_session *spt, uint32_t block_nr, - uint8_t *buf, int len) -{ - int bytes_read = 0; - - if (spt->fd < 0) { - spt->fd = open(spt->filename, O_RDONLY | O_BINARY); - } - - if (spt->fd < 0) { - return -1; - } - - if (len) { - if (lseek(spt->fd, block_nr * spt->block_size, SEEK_SET) == (off_t)-1) { - return -1; - } - - bytes_read = read(spt->fd, buf, len); - } - - return bytes_read; -} - -static struct tftp_t *tftp_prep_mbuf_data(struct tftp_session *spt, - struct mbuf *m) -{ - struct tftp_t *tp; - - memset(m->m_data, 0, m->m_size); - - m->m_data += IF_MAXLINKHDR; - if (spt->client_addr.ss_family == AF_INET6) { - m->m_data += sizeof(struct ip6); - } else { - m->m_data += sizeof(struct ip); - } - tp = (void *)m->m_data; - m->m_data += sizeof(struct udphdr); - - return tp; -} - -static void tftp_udp_output(struct tftp_session *spt, struct mbuf *m, - struct tftp_t *recv_tp) -{ - if (spt->client_addr.ss_family == AF_INET6) { - struct sockaddr_in6 sa6, da6; - - sa6.sin6_addr = spt->slirp->vhost_addr6; - sa6.sin6_port = recv_tp->udp.uh_dport; - da6.sin6_addr = ((struct sockaddr_in6 *)&spt->client_addr)->sin6_addr; - da6.sin6_port = spt->client_port; - - udp6_output(NULL, m, &sa6, &da6); - } else { - struct sockaddr_in sa4, da4; - - sa4.sin_addr = spt->slirp->vhost_addr; - sa4.sin_port = recv_tp->udp.uh_dport; - da4.sin_addr = ((struct sockaddr_in *)&spt->client_addr)->sin_addr; - da4.sin_port = spt->client_port; - - udp_output(NULL, m, &sa4, &da4, IPTOS_LOWDELAY); - } -} - -static int tftp_send_oack(struct tftp_session *spt, const char *keys[], - uint32_t values[], int nb, struct tftp_t *recv_tp) -{ - struct mbuf *m; - struct tftp_t *tp; - int i, n = 0; - - m = m_get(spt->slirp); - - if (!m) - return -1; - - tp = tftp_prep_mbuf_data(spt, m); - - tp->tp_op = htons(TFTP_OACK); - for (i = 0; i < nb; i++) { - n += slirp_fmt0(tp->x.tp_buf + n, sizeof(tp->x.tp_buf) - n, "%s", keys[i]); - n += slirp_fmt0(tp->x.tp_buf + n, sizeof(tp->x.tp_buf) - n, "%u", values[i]); - } - - m->m_len = G_SIZEOF_MEMBER(struct tftp_t, tp_op) + n; - tftp_udp_output(spt, m, recv_tp); - - return 0; -} - -static void tftp_send_error(struct tftp_session *spt, uint16_t errorcode, - const char *msg, struct tftp_t *recv_tp) -{ - struct mbuf *m; - struct tftp_t *tp; - - DEBUG_TFTP("tftp error msg: %s", msg); - - m = m_get(spt->slirp); - - if (!m) { - goto out; - } - - tp = tftp_prep_mbuf_data(spt, m); - - tp->tp_op = htons(TFTP_ERROR); - tp->x.tp_error.tp_error_code = htons(errorcode); - slirp_pstrcpy((char *)tp->x.tp_error.tp_msg, sizeof(tp->x.tp_error.tp_msg), - msg); - - m->m_len = sizeof(struct tftp_t) - (TFTP_BLOCKSIZE_MAX + 2) + 3 + - strlen(msg) - sizeof(struct udphdr); - tftp_udp_output(spt, m, recv_tp); - -out: - tftp_session_terminate(spt); -} - -static void tftp_send_next_block(struct tftp_session *spt, - struct tftp_t *recv_tp) -{ - struct mbuf *m; - struct tftp_t *tp; - int nobytes; - - m = m_get(spt->slirp); - - if (!m) { - return; - } - - tp = tftp_prep_mbuf_data(spt, m); - - tp->tp_op = htons(TFTP_DATA); - tp->x.tp_data.tp_block_nr = htons((spt->block_nr + 1) & 0xffff); - - nobytes = tftp_read_data(spt, spt->block_nr, tp->x.tp_data.tp_buf, - spt->block_size); - - if (nobytes < 0) { - m_free(m); - - /* send "file not found" error back */ - - tftp_send_error(spt, 1, "File not found", tp); - - return; - } - - m->m_len = sizeof(struct tftp_t) - (TFTP_BLOCKSIZE_MAX - nobytes) - - sizeof(struct udphdr); - tftp_udp_output(spt, m, recv_tp); - - if (nobytes == spt->block_size) { - tftp_session_update(spt); - } else { - tftp_session_terminate(spt); - } - - spt->block_nr++; -} - -static void tftp_handle_rrq(Slirp *slirp, struct sockaddr_storage *srcsas, - struct tftp_t *tp, int pktlen) -{ - struct tftp_session *spt; - int s, k; - size_t prefix_len; - char *req_fname; - const char *option_name[2]; - uint32_t option_value[2]; - int nb_options = 0; - - /* check if a session already exists and if so terminate it */ - s = tftp_session_find(slirp, srcsas, tp); - if (s >= 0) { - tftp_session_terminate(&slirp->tftp_sessions[s]); - } - - s = tftp_session_allocate(slirp, srcsas, tp); - - if (s < 0) { - return; - } - - spt = &slirp->tftp_sessions[s]; - - /* unspecified prefix means service disabled */ - if (!slirp->tftp_prefix) { - tftp_send_error(spt, 2, "Access violation", tp); - return; - } - - /* skip header fields */ - k = 0; - pktlen -= offsetof(struct tftp_t, x.tp_buf); - - /* prepend tftp_prefix */ - prefix_len = strlen(slirp->tftp_prefix); - spt->filename = g_malloc(prefix_len + TFTP_FILENAME_MAX + 2); - memcpy(spt->filename, slirp->tftp_prefix, prefix_len); - spt->filename[prefix_len] = '/'; - - /* get name */ - req_fname = spt->filename + prefix_len + 1; - - while (1) { - if (k >= TFTP_FILENAME_MAX || k >= pktlen) { - tftp_send_error(spt, 2, "Access violation", tp); - return; - } - req_fname[k] = tp->x.tp_buf[k]; - if (req_fname[k++] == '\0') { - break; - } - } - - DEBUG_TFTP("tftp rrq file: %s", req_fname); - - /* check mode */ - if ((pktlen - k) < 6) { - tftp_send_error(spt, 2, "Access violation", tp); - return; - } - - if (strcasecmp(&tp->x.tp_buf[k], "octet") != 0) { - tftp_send_error(spt, 4, "Unsupported transfer mode", tp); - return; - } - - k += 6; /* skipping octet */ - - /* do sanity checks on the filename */ - if ( -#ifdef G_OS_WIN32 - strstr(req_fname, "..\\") || - req_fname[strlen(req_fname) - 1] == '\\' || -#endif - strstr(req_fname, "../") || - req_fname[strlen(req_fname) - 1] == '/') { - tftp_send_error(spt, 2, "Access violation", tp); - return; - } - - /* check if the file exists */ - if (tftp_read_data(spt, 0, NULL, 0) < 0) { - tftp_send_error(spt, 1, "File not found", tp); - return; - } - - if (tp->x.tp_buf[pktlen - 1] != 0) { - tftp_send_error(spt, 2, "Access violation", tp); - return; - } - - while (k < pktlen && nb_options < G_N_ELEMENTS(option_name)) { - const char *key, *value; - - key = &tp->x.tp_buf[k]; - k += strlen(key) + 1; - - if (k >= pktlen) { - tftp_send_error(spt, 2, "Access violation", tp); - return; - } - - value = &tp->x.tp_buf[k]; - k += strlen(value) + 1; - - if (strcasecmp(key, "tsize") == 0) { - int tsize = atoi(value); - struct stat stat_p; - - if (tsize == 0) { - if (stat(spt->filename, &stat_p) == 0) - tsize = stat_p.st_size; - else { - tftp_send_error(spt, 1, "File not found", tp); - return; - } - } - - option_name[nb_options] = "tsize"; - option_value[nb_options] = tsize; - nb_options++; - } else if (strcasecmp(key, "blksize") == 0) { - int blksize = atoi(value); - - /* Accept blksize up to our maximum size */ - if (blksize > 0) { - spt->block_size = MIN(blksize, TFTP_BLOCKSIZE_MAX); - option_name[nb_options] = "blksize"; - option_value[nb_options] = spt->block_size; - nb_options++; - } - } - } - - if (nb_options > 0) { - assert(nb_options <= G_N_ELEMENTS(option_name)); - tftp_send_oack(spt, option_name, option_value, nb_options, tp); - return; - } - - spt->block_nr = 0; - tftp_send_next_block(spt, tp); -} - -static void tftp_handle_ack(Slirp *slirp, struct sockaddr_storage *srcsas, - struct tftp_t *tp, int pktlen) -{ - int s; - - s = tftp_session_find(slirp, srcsas, tp); - - if (s < 0) { - return; - } - - tftp_send_next_block(&slirp->tftp_sessions[s], tp); -} - -static void tftp_handle_error(Slirp *slirp, struct sockaddr_storage *srcsas, - struct tftp_t *tp, int pktlen) -{ - int s; - - s = tftp_session_find(slirp, srcsas, tp); - - if (s < 0) { - return; - } - - tftp_session_terminate(&slirp->tftp_sessions[s]); -} - -void tftp_input(struct sockaddr_storage *srcsas, struct mbuf *m) -{ - struct tftp_t *tp = (struct tftp_t *)m->m_data; - - switch (ntohs(tp->tp_op)) { - case TFTP_RRQ: - tftp_handle_rrq(m->slirp, srcsas, tp, m->m_len); - break; - - case TFTP_ACK: - tftp_handle_ack(m->slirp, srcsas, tp, m->m_len); - break; - - case TFTP_ERROR: - tftp_handle_error(m->slirp, srcsas, tp, m->m_len); - break; - } -} diff --git a/src/network/slirp/tftp.h b/src/network/slirp/tftp.h deleted file mode 100644 index 663485328..000000000 --- a/src/network/slirp/tftp.h +++ /dev/null @@ -1,60 +0,0 @@ -/* SPDX-License-Identifier: BSD-3-Clause */ -/* tftp defines */ - -#ifndef SLIRP_TFTP_H -#define SLIRP_TFTP_H - -#include "util.h" - -#define TFTP_SESSIONS_MAX 20 - -#define TFTP_SERVER 69 - -#define TFTP_RRQ 1 -#define TFTP_WRQ 2 -#define TFTP_DATA 3 -#define TFTP_ACK 4 -#define TFTP_ERROR 5 -#define TFTP_OACK 6 - -#define TFTP_FILENAME_MAX 512 -#define TFTP_BLOCKSIZE_MAX 1428 - -#if defined(_MSC_VER) && !defined (__clang__) -#pragma pack(push, 1) -#endif -struct tftp_t { - struct udphdr udp; - uint16_t tp_op; - union { - struct { - uint16_t tp_block_nr; - uint8_t tp_buf[TFTP_BLOCKSIZE_MAX]; - } tp_data; - struct { - uint16_t tp_error_code; - uint8_t tp_msg[TFTP_BLOCKSIZE_MAX]; - } tp_error; - char tp_buf[TFTP_BLOCKSIZE_MAX + 2]; - } x; -} SLIRP_PACKED; -#if defined(_MSC_VER) && !defined (__clang__) -#pragma pack(pop) -#endif - -struct tftp_session { - Slirp *slirp; - char *filename; - int fd; - uint16_t block_size; - - struct sockaddr_storage client_addr; - uint16_t client_port; - uint32_t block_nr; - - int timestamp; -}; - -void tftp_input(struct sockaddr_storage *srcsas, struct mbuf *m); - -#endif diff --git a/src/network/slirp/tinyglib.c b/src/network/slirp/tinyglib.c deleted file mode 100644 index 8baa576eb..000000000 --- a/src/network/slirp/tinyglib.c +++ /dev/null @@ -1,133 +0,0 @@ -/* - * 86Box A hypervisor and IBM PC system emulator that specializes in - * running old operating systems and software designed for IBM - * PC systems and compatibles from 1981 through fairly recent - * system designs based on the PCI bus. - * - * This file is part of the 86Box distribution. - * - * Minimal reimplementation of GLib for libslirp. - * - * - * - * Author: RichardG, - * - * Copyright 2020 RichardG. - */ -#include -#include - -/* Must be a function, as libslirp redefines it as a macro. */ -gboolean -g_spawn_async_with_fds(const gchar *working_directory, gchar **argv, - gchar **envp, GSpawnFlags flags, - GSpawnChildSetupFunc child_setup, - gpointer user_data, GPid *child_pid, gint stdin_fd, - gint stdout_fd, gint stderr_fd, GError **error) -{ - return 0; -} - - -/* Needs bounds checking, but not really used by libslirp. */ -GString * -g_string_new(gchar *base) -{ - char *ret = malloc(4096); - if (base) - strcpy(ret, base); - return ret; -} - - -/* Unimplemented, as with anything related to GString. */ -gchar * -g_string_free(GString *string, gboolean free_segment) -{ - return (free_segment ? NULL : string); -} - - -/* Implementation borrowed from GLib itself. */ -gchar * -g_strstr_len(const gchar *haystack, gssize haystack_len, const gchar *needle) -{ - if (haystack_len < 0) - return strstr(haystack, needle); - else { - const gchar *p = haystack; - gsize needle_len = strlen(needle); - gsize haystack_len_unsigned = haystack_len; - const gchar *end; - gsize i; - - if (needle_len == 0) - return (gchar *) haystack; - - if (haystack_len_unsigned < needle_len) - return NULL; - - end = haystack + haystack_len - needle_len; - - while (p <= end && *p) { - for (i = 0; i < needle_len; i++) - if (p[i] != needle[i]) - goto next; - - return (gchar *)p; - -next: - p++; - } - - return NULL; - } -} - - -/* Implementation borrowed from GLib itself. */ -guint -g_strv_length(gchar **str_array) -{ - guint i = 0; - while (str_array[i] != NULL) - ++i; - return i; -} - -/* Implementation borrowed from GLib itself. */ -gsize -g_strlcpy (gchar *dest, - const gchar *src, - gsize dest_size) -{ - gchar *d = dest; - const gchar *s = src; - gsize n = dest_size; - - if (dest == NULL) return 0; - if (src == NULL) return 0; - - /* Copy as many bytes as will fit */ - if (n != 0 && --n != 0) - do - { - gchar c = *s++; - - *d++ = c; - if (c == 0) - break; - } - while (--n != 0); - - /* If not enough room in dest, add NUL and traverse rest of src */ - if (n == 0) - { - if (dest_size != 0) - *d = 0; - while (*s++) - ; - } - - return s - src - 1; /* count does not include NUL */ -} diff --git a/src/network/slirp/udp.c b/src/network/slirp/udp.c deleted file mode 100644 index 0ad44d7c0..000000000 --- a/src/network/slirp/udp.c +++ /dev/null @@ -1,365 +0,0 @@ -/* SPDX-License-Identifier: BSD-3-Clause */ -/* - * Copyright (c) 1982, 1986, 1988, 1990, 1993 - * The Regents of the University of California. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. Neither the name of the University nor the names of its contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - * - * @(#)udp_usrreq.c 8.4 (Berkeley) 1/21/94 - * udp_usrreq.c,v 1.4 1994/10/02 17:48:45 phk Exp - */ - -/* - * Changes and additions relating to SLiRP - * Copyright (c) 1995 Danny Gasparovski. - * - * Please read the file COPYRIGHT for the - * terms and conditions of the copyright. - */ - -#include "slirp.h" -#include "ip_icmp.h" - -static uint8_t udp_tos(struct socket *so); - -void udp_init(Slirp *slirp) -{ - slirp->udb.so_next = slirp->udb.so_prev = &slirp->udb; - slirp->udp_last_so = &slirp->udb; -} - -void udp_cleanup(Slirp *slirp) -{ - struct socket *so, *so_next; - - for (so = slirp->udb.so_next; so != &slirp->udb; so = so_next) { - so_next = so->so_next; - udp_detach(slirp->udb.so_next); - } -} - -/* m->m_data points at ip packet header - * m->m_len length ip packet - * ip->ip_len length data (IPDU) - */ -void udp_input(register struct mbuf *m, int iphlen) -{ - Slirp *slirp = m->slirp; - register struct ip *ip; - register struct udphdr *uh; - int len; - struct ip save_ip; - struct socket *so; - struct sockaddr_storage lhost; - struct sockaddr_in *lhost4; - - DEBUG_CALL("udp_input"); - DEBUG_ARG("m = %p", m); - DEBUG_ARG("iphlen = %d", iphlen); - - /* - * Strip IP options, if any; should skip this, - * make available to user, and use on returned packets, - * but we don't yet have a way to check the checksum - * with options still present. - */ - if (iphlen > sizeof(struct ip)) { - ip_stripoptions(m, (struct mbuf *)0); - iphlen = sizeof(struct ip); - } - - /* - * Get IP and UDP header together in first mbuf. - */ - ip = mtod(m, struct ip *); - uh = (struct udphdr *)((char *)ip + iphlen); - - /* - * Make mbuf data length reflect UDP length. - * If not enough data to reflect UDP length, drop. - */ - len = ntohs((uint16_t)uh->uh_ulen); - - if (ip->ip_len != len) { - if (len > ip->ip_len) { - goto bad; - } - m_adj(m, len - ip->ip_len); - ip->ip_len = len; - } - - /* - * Save a copy of the IP header in case we want restore it - * for sending an ICMP error message in response. - */ - save_ip = *ip; - save_ip.ip_len += iphlen; /* tcp_input subtracts this */ - - /* - * Checksum extended UDP header and data. - */ - if (uh->uh_sum) { - memset(&((struct ipovly *)ip)->ih_mbuf, 0, sizeof(struct mbuf_ptr)); - ((struct ipovly *)ip)->ih_x1 = 0; - ((struct ipovly *)ip)->ih_len = uh->uh_ulen; - if (cksum(m, len + sizeof(struct ip))) { - goto bad; - } - } - - lhost.ss_family = AF_INET; - lhost4 = (struct sockaddr_in *)&lhost; - lhost4->sin_addr = ip->ip_src; - lhost4->sin_port = uh->uh_sport; - - /* - * handle DHCP/BOOTP - */ - if (ntohs(uh->uh_dport) == BOOTP_SERVER && - (ip->ip_dst.s_addr == slirp->vhost_addr.s_addr || - ip->ip_dst.s_addr == 0xffffffff)) { - bootp_input(m); - goto bad; - } - - /* - * handle TFTP - */ - if (ntohs(uh->uh_dport) == TFTP_SERVER && - ip->ip_dst.s_addr == slirp->vhost_addr.s_addr) { - m->m_data += iphlen; - m->m_len -= iphlen; - tftp_input(&lhost, m); - m->m_data -= iphlen; - m->m_len += iphlen; - goto bad; - } - - if (slirp->restricted) { - goto bad; - } - - /* - * Locate pcb for datagram. - */ - so = solookup(&slirp->udp_last_so, &slirp->udb, &lhost, NULL); - - if (so == NULL) { - /* - * If there's no socket for this packet, - * create one - */ - so = socreate(slirp); - if (udp_attach(so, AF_INET) == -1) { - DEBUG_MISC(" udp_attach errno = %d-%s", errno, strerror(errno)); - sofree(so); - goto bad; - } - - /* - * Setup fields - */ - so->so_lfamily = AF_INET; - so->so_laddr = ip->ip_src; - so->so_lport = uh->uh_sport; - - if ((so->so_iptos = udp_tos(so)) == 0) - so->so_iptos = ip->ip_tos; - - /* - * XXXXX Here, check if it's in udpexec_list, - * and if it is, do the fork_exec() etc. - */ - } - - so->so_ffamily = AF_INET; - so->so_faddr = ip->ip_dst; /* XXX */ - so->so_fport = uh->uh_dport; /* XXX */ - - iphlen += sizeof(struct udphdr); - m->m_len -= iphlen; - m->m_data += iphlen; - - /* - * Now we sendto() the packet. - */ - if (sosendto(so, m) == -1) { - m->m_len += iphlen; - m->m_data -= iphlen; - *ip = save_ip; - DEBUG_MISC("udp tx errno = %d-%s", errno, strerror(errno)); - icmp_send_error(m, ICMP_UNREACH, ICMP_UNREACH_NET, 0, strerror(errno)); - goto bad; - } - - m_free(so->so_m); /* used for ICMP if error on sorecvfrom */ - - /* restore the orig mbuf packet */ - m->m_len += iphlen; - m->m_data -= iphlen; - *ip = save_ip; - so->so_m = m; /* ICMP backup */ - - return; -bad: - m_free(m); -} - -int udp_output(struct socket *so, struct mbuf *m, struct sockaddr_in *saddr, - struct sockaddr_in *daddr, int iptos) -{ - register struct udpiphdr *ui; - int error = 0; - - DEBUG_CALL("udp_output"); - DEBUG_ARG("so = %p", so); - DEBUG_ARG("m = %p", m); - DEBUG_ARG("saddr = %s", inet_ntoa(saddr->sin_addr)); - DEBUG_ARG("daddr = %s", inet_ntoa(daddr->sin_addr)); - - /* - * Adjust for header - */ - m->m_data -= sizeof(struct udpiphdr); - m->m_len += sizeof(struct udpiphdr); - - /* - * Fill in mbuf with extended UDP header - * and addresses and length put into network format. - */ - ui = mtod(m, struct udpiphdr *); - memset(&ui->ui_i.ih_mbuf, 0, sizeof(struct mbuf_ptr)); - ui->ui_x1 = 0; - ui->ui_pr = IPPROTO_UDP; - ui->ui_len = htons(m->m_len - sizeof(struct ip)); - /* XXXXX Check for from-one-location sockets, or from-any-location sockets - */ - ui->ui_src = saddr->sin_addr; - ui->ui_dst = daddr->sin_addr; - ui->ui_sport = saddr->sin_port; - ui->ui_dport = daddr->sin_port; - ui->ui_ulen = ui->ui_len; - - /* - * Stuff checksum and output datagram. - */ - ui->ui_sum = 0; - if ((ui->ui_sum = cksum(m, m->m_len)) == 0) - ui->ui_sum = 0xffff; - ((struct ip *)ui)->ip_len = m->m_len; - - ((struct ip *)ui)->ip_ttl = IPDEFTTL; - ((struct ip *)ui)->ip_tos = iptos; - - error = ip_output(so, m); - - return (error); -} - -int udp_attach(struct socket *so, unsigned short af) -{ - so->s = slirp_socket(af, SOCK_DGRAM, 0); - if (so->s != -1) { - if (slirp_bind_outbound(so, af) != 0) { - // bind failed - close socket - closesocket(so->s); - so->s = -1; - return -1; - } - so->so_expire = curtime + SO_EXPIRE; - insque(so, &so->slirp->udb); - } - return (so->s); -} - -void udp_detach(struct socket *so) -{ - so->slirp->cb->unregister_poll_fd(so->s, so->slirp->opaque); - closesocket(so->s); - sofree(so); -} - -static const struct tos_t udptos[] = { { 0, 53, IPTOS_LOWDELAY, 0 }, /* DNS */ - { 0, 0, 0, 0 } }; - -static uint8_t udp_tos(struct socket *so) -{ - int i = 0; - - while (udptos[i].tos) { - if ((udptos[i].fport && ntohs(so->so_fport) == udptos[i].fport) || - (udptos[i].lport && ntohs(so->so_lport) == udptos[i].lport)) { - if (so->slirp->enable_emu) - so->so_emu = udptos[i].emu; - return udptos[i].tos; - } - i++; - } - - return 0; -} - -struct socket *udp_listen(Slirp *slirp, uint32_t haddr, unsigned hport, - uint32_t laddr, unsigned lport, int flags) -{ - /* TODO: IPv6 */ - struct sockaddr_in addr; - struct socket *so; - socklen_t addrlen = sizeof(struct sockaddr_in); - - memset(&addr, 0, sizeof(addr)); - so = socreate(slirp); - so->s = slirp_socket(AF_INET, SOCK_DGRAM, 0); - if (so->s < 0) { - sofree(so); - return NULL; - } - so->so_expire = curtime + SO_EXPIRE; - insque(so, &slirp->udb); - - addr.sin_family = AF_INET; - addr.sin_addr.s_addr = haddr; - addr.sin_port = hport; - - if (bind(so->s, (struct sockaddr *)&addr, addrlen) < 0) { - udp_detach(so); - return NULL; - } - slirp_socket_set_fast_reuse(so->s); - - getsockname(so->s, (struct sockaddr *)&addr, &addrlen); - so->fhost.sin = addr; - sotranslate_accept(so); - so->so_lfamily = AF_INET; - so->so_lport = lport; - so->so_laddr.s_addr = laddr; - if (flags != SS_FACCEPTONCE) - so->so_expire = 0; - - so->so_state &= SS_PERSISTENT_MASK; - so->so_state |= SS_ISFCONNECTED | flags; - - return so; -} diff --git a/src/network/slirp/udp.h b/src/network/slirp/udp.h deleted file mode 100644 index c3b83fdc5..000000000 --- a/src/network/slirp/udp.h +++ /dev/null @@ -1,90 +0,0 @@ -/* SPDX-License-Identifier: BSD-3-Clause */ -/* - * Copyright (c) 1982, 1986, 1993 - * The Regents of the University of California. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. Neither the name of the University nor the names of its contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - * - * @(#)udp.h 8.1 (Berkeley) 6/10/93 - * udp.h,v 1.3 1994/08/21 05:27:41 paul Exp - */ - -#ifndef UDP_H -#define UDP_H - -#define UDP_TTL 0x60 -#define UDP_UDPDATALEN 16192 - -/* - * Udp protocol header. - * Per RFC 768, September, 1981. - */ -struct udphdr { - uint16_t uh_sport; /* source port */ - uint16_t uh_dport; /* destination port */ - int16_t uh_ulen; /* udp length */ - uint16_t uh_sum; /* udp checksum */ -}; - -/* - * UDP kernel structures and variables. - */ -struct udpiphdr { - struct ipovly ui_i; /* overlaid ip structure */ - struct udphdr ui_u; /* udp header */ -}; -#define ui_mbuf ui_i.ih_mbuf.mptr -#define ui_x1 ui_i.ih_x1 -#define ui_pr ui_i.ih_pr -#define ui_len ui_i.ih_len -#define ui_src ui_i.ih_src -#define ui_dst ui_i.ih_dst -#define ui_sport ui_u.uh_sport -#define ui_dport ui_u.uh_dport -#define ui_ulen ui_u.uh_ulen -#define ui_sum ui_u.uh_sum - -/* - * Names for UDP sysctl objects - */ -#define UDPCTL_CHECKSUM 1 /* checksum UDP packets */ -#define UDPCTL_MAXID 2 - -struct mbuf; - -void udp_init(Slirp *); -void udp_cleanup(Slirp *); -void udp_input(register struct mbuf *, int); -int udp_attach(struct socket *, unsigned short af); -void udp_detach(struct socket *); -struct socket *udp_listen(Slirp *, uint32_t, unsigned, uint32_t, unsigned, int); -int udp_output(struct socket *so, struct mbuf *m, struct sockaddr_in *saddr, - struct sockaddr_in *daddr, int iptos); - -void udp6_input(register struct mbuf *); -int udp6_output(struct socket *so, struct mbuf *m, struct sockaddr_in6 *saddr, - struct sockaddr_in6 *daddr); - -#endif diff --git a/src/network/slirp/udp6.c b/src/network/slirp/udp6.c deleted file mode 100644 index 6f9486bbc..000000000 --- a/src/network/slirp/udp6.c +++ /dev/null @@ -1,173 +0,0 @@ -/* SPDX-License-Identifier: BSD-3-Clause */ -/* - * Copyright (c) 2013 - * Guillaume Subiron - */ - -#include "slirp.h" -#include "udp.h" -#include "dhcpv6.h" - -void udp6_input(struct mbuf *m) -{ - Slirp *slirp = m->slirp; - struct ip6 *ip, save_ip; - struct udphdr *uh; - int iphlen = sizeof(struct ip6); - int len; - struct socket *so; - struct sockaddr_in6 lhost; - - DEBUG_CALL("udp6_input"); - DEBUG_ARG("m = %p", m); - - if (slirp->restricted) { - goto bad; - } - - ip = mtod(m, struct ip6 *); - m->m_len -= iphlen; - m->m_data += iphlen; - uh = mtod(m, struct udphdr *); - m->m_len += iphlen; - m->m_data -= iphlen; - - if (ip6_cksum(m)) { - goto bad; - } - - len = ntohs((uint16_t)uh->uh_ulen); - - /* - * Make mbuf data length reflect UDP length. - * If not enough data to reflect UDP length, drop. - */ - if (ntohs(ip->ip_pl) != len) { - if (len > ntohs(ip->ip_pl)) { - goto bad; - } - m_adj(m, len - ntohs(ip->ip_pl)); - ip->ip_pl = htons(len); - } - - /* - * Save a copy of the IP header in case we want restore it - * for sending an ICMP error message in response. - */ - save_ip = *ip; - - /* Locate pcb for datagram. */ - lhost.sin6_family = AF_INET6; - lhost.sin6_addr = ip->ip_src; - lhost.sin6_port = uh->uh_sport; - - /* handle DHCPv6 */ - if (ntohs(uh->uh_dport) == DHCPV6_SERVER_PORT && - (in6_equal(&ip->ip_dst, &slirp->vhost_addr6) || - in6_dhcp_multicast(&ip->ip_dst))) { - m->m_data += iphlen; - m->m_len -= iphlen; - dhcpv6_input(&lhost, m); - m->m_data -= iphlen; - m->m_len += iphlen; - goto bad; - } - - /* handle TFTP */ - if (ntohs(uh->uh_dport) == TFTP_SERVER && - !memcmp(ip->ip_dst.s6_addr, slirp->vhost_addr6.s6_addr, 16)) { - m->m_data += iphlen; - m->m_len -= iphlen; - tftp_input((struct sockaddr_storage *)&lhost, m); - m->m_data -= iphlen; - m->m_len += iphlen; - goto bad; - } - - so = solookup(&slirp->udp_last_so, &slirp->udb, - (struct sockaddr_storage *)&lhost, NULL); - - if (so == NULL) { - /* If there's no socket for this packet, create one. */ - so = socreate(slirp); - if (udp_attach(so, AF_INET6) == -1) { - DEBUG_MISC(" udp6_attach errno = %d-%s", errno, strerror(errno)); - sofree(so); - goto bad; - } - - /* Setup fields */ - so->so_lfamily = AF_INET6; - so->so_laddr6 = ip->ip_src; - so->so_lport6 = uh->uh_sport; - } - - so->so_ffamily = AF_INET6; - so->so_faddr6 = ip->ip_dst; /* XXX */ - so->so_fport6 = uh->uh_dport; /* XXX */ - - iphlen += sizeof(struct udphdr); - m->m_len -= iphlen; - m->m_data += iphlen; - - /* - * Now we sendto() the packet. - */ - if (sosendto(so, m) == -1) { - m->m_len += iphlen; - m->m_data -= iphlen; - *ip = save_ip; - DEBUG_MISC("udp tx errno = %d-%s", errno, strerror(errno)); - icmp6_send_error(m, ICMP6_UNREACH, ICMP6_UNREACH_NO_ROUTE); - goto bad; - } - - m_free(so->so_m); /* used for ICMP if error on sorecvfrom */ - - /* restore the orig mbuf packet */ - m->m_len += iphlen; - m->m_data -= iphlen; - *ip = save_ip; - so->so_m = m; - - return; -bad: - m_free(m); -} - -int udp6_output(struct socket *so, struct mbuf *m, struct sockaddr_in6 *saddr, - struct sockaddr_in6 *daddr) -{ - struct ip6 *ip; - struct udphdr *uh; - - DEBUG_CALL("udp6_output"); - DEBUG_ARG("so = %p", so); - DEBUG_ARG("m = %p", m); - - /* adjust for header */ - m->m_data -= sizeof(struct udphdr); - m->m_len += sizeof(struct udphdr); - uh = mtod(m, struct udphdr *); - m->m_data -= sizeof(struct ip6); - m->m_len += sizeof(struct ip6); - ip = mtod(m, struct ip6 *); - - /* Build IP header */ - ip->ip_pl = htons(m->m_len - sizeof(struct ip6)); - ip->ip_nh = IPPROTO_UDP; - ip->ip_src = saddr->sin6_addr; - ip->ip_dst = daddr->sin6_addr; - - /* Build UDP header */ - uh->uh_sport = saddr->sin6_port; - uh->uh_dport = daddr->sin6_port; - uh->uh_ulen = ip->ip_pl; - uh->uh_sum = 0; - uh->uh_sum = ip6_cksum(m); - if (uh->uh_sum == 0) { - uh->uh_sum = 0xffff; - } - - return ip6_output(so, m, 0); -} diff --git a/src/network/slirp/util.c b/src/network/slirp/util.c deleted file mode 100644 index 8478c48d6..000000000 --- a/src/network/slirp/util.c +++ /dev/null @@ -1,429 +0,0 @@ -/* SPDX-License-Identifier: MIT */ -/* - * util.c (mostly based on QEMU os-win32.c) - * - * Copyright (c) 2003-2008 Fabrice Bellard - * Copyright (c) 2010-2016 Red Hat, Inc. - * - * QEMU library functions for win32 which are shared between QEMU and - * the QEMU tools. - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL - * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -#include "util.h" - -#include -#include -#include -#include - -#if defined(_WIN32) -int slirp_inet_aton(const char *cp, struct in_addr *ia) -{ - uint32_t addr = inet_addr(cp); - if (addr == 0xffffffff) { - return 0; - } - ia->s_addr = addr; - return 1; -} -#endif - -void slirp_set_nonblock(int fd) -{ -#ifndef _WIN32 - int f; - f = fcntl(fd, F_GETFL); - assert(f != -1); - f = fcntl(fd, F_SETFL, f | O_NONBLOCK); - assert(f != -1); -#else - unsigned long opt = 1; - ioctlsocket(fd, FIONBIO, &opt); -#endif -} - -static void slirp_set_cloexec(int fd) -{ -#ifndef _WIN32 - int f; - f = fcntl(fd, F_GETFD); - assert(f != -1); - f = fcntl(fd, F_SETFD, f | FD_CLOEXEC); - assert(f != -1); -#endif -} - -/* - * Opens a socket with FD_CLOEXEC set - */ -int slirp_socket(int domain, int type, int protocol) -{ - int ret; - -#ifdef SOCK_CLOEXEC - ret = socket(domain, type | SOCK_CLOEXEC, protocol); - if (ret != -1 || errno != EINVAL) { - return ret; - } -#endif - ret = socket(domain, type, protocol); - if (ret >= 0) { - slirp_set_cloexec(ret); - } - - return ret; -} - -#ifdef _WIN32 -static int socket_error(void) -{ - switch (WSAGetLastError()) { - case 0: - return 0; - case WSAEINTR: - return EINTR; - case WSAEINVAL: - return EINVAL; - case WSA_INVALID_HANDLE: - return EBADF; - case WSA_NOT_ENOUGH_MEMORY: - return ENOMEM; - case WSA_INVALID_PARAMETER: - return EINVAL; - case WSAENAMETOOLONG: - return ENAMETOOLONG; - case WSAENOTEMPTY: - return ENOTEMPTY; - case WSAEWOULDBLOCK: - /* not using EWOULDBLOCK as we don't want code to have - * to check both EWOULDBLOCK and EAGAIN */ - return EAGAIN; - case WSAEINPROGRESS: - return EINPROGRESS; - case WSAEALREADY: - return EALREADY; - case WSAENOTSOCK: - return ENOTSOCK; - case WSAEDESTADDRREQ: - return EDESTADDRREQ; - case WSAEMSGSIZE: - return EMSGSIZE; - case WSAEPROTOTYPE: - return EPROTOTYPE; - case WSAENOPROTOOPT: - return ENOPROTOOPT; - case WSAEPROTONOSUPPORT: - return EPROTONOSUPPORT; - case WSAEOPNOTSUPP: - return EOPNOTSUPP; - case WSAEAFNOSUPPORT: - return EAFNOSUPPORT; - case WSAEADDRINUSE: - return EADDRINUSE; - case WSAEADDRNOTAVAIL: - return EADDRNOTAVAIL; - case WSAENETDOWN: - return ENETDOWN; - case WSAENETUNREACH: - return ENETUNREACH; - case WSAENETRESET: - return ENETRESET; - case WSAECONNABORTED: - return ECONNABORTED; - case WSAECONNRESET: - return ECONNRESET; - case WSAENOBUFS: - return ENOBUFS; - case WSAEISCONN: - return EISCONN; - case WSAENOTCONN: - return ENOTCONN; - case WSAETIMEDOUT: - return ETIMEDOUT; - case WSAECONNREFUSED: - return ECONNREFUSED; - case WSAELOOP: - return ELOOP; - case WSAEHOSTUNREACH: - return EHOSTUNREACH; - default: - return EIO; - } -} - -#undef ioctlsocket -int slirp_ioctlsocket_wrap(int fd, int req, void *val) -{ - int ret; - ret = ioctlsocket(fd, req, val); - if (ret < 0) { - errno = socket_error(); - } - return ret; -} - -#undef closesocket -int slirp_closesocket_wrap(int fd) -{ - int ret; - ret = closesocket(fd); - if (ret < 0) { - errno = socket_error(); - } - return ret; -} - -#undef connect -int slirp_connect_wrap(int sockfd, const struct sockaddr *addr, int addrlen) -{ - int ret; - ret = connect(sockfd, addr, addrlen); - if (ret < 0) { - errno = socket_error(); - } - return ret; -} - -#undef listen -int slirp_listen_wrap(int sockfd, int backlog) -{ - int ret; - ret = listen(sockfd, backlog); - if (ret < 0) { - errno = socket_error(); - } - return ret; -} - -#undef bind -int slirp_bind_wrap(int sockfd, const struct sockaddr *addr, int addrlen) -{ - int ret; - ret = bind(sockfd, addr, addrlen); - if (ret < 0) { - errno = socket_error(); - } - return ret; -} - -#undef socket -int slirp_socket_wrap(int domain, int type, int protocol) -{ - int ret; - ret = socket(domain, type, protocol); - if (ret < 0) { - errno = socket_error(); - } - return ret; -} - -#undef accept -int slirp_accept_wrap(int sockfd, struct sockaddr *addr, int *addrlen) -{ - int ret; - ret = accept(sockfd, addr, addrlen); - if (ret < 0) { - errno = socket_error(); - } - return ret; -} - -#undef shutdown -int slirp_shutdown_wrap(int sockfd, int how) -{ - int ret; - ret = shutdown(sockfd, how); - if (ret < 0) { - errno = socket_error(); - } - return ret; -} - -#undef getsockopt -int slirp_getsockopt_wrap(int sockfd, int level, int optname, void *optval, - int *optlen) -{ - int ret; - ret = getsockopt(sockfd, level, optname, optval, optlen); - if (ret < 0) { - errno = socket_error(); - } - return ret; -} - -#undef setsockopt -int slirp_setsockopt_wrap(int sockfd, int level, int optname, - const void *optval, int optlen) -{ - int ret; - ret = setsockopt(sockfd, level, optname, optval, optlen); - if (ret < 0) { - errno = socket_error(); - } - return ret; -} - -#undef getpeername -int slirp_getpeername_wrap(int sockfd, struct sockaddr *addr, int *addrlen) -{ - int ret; - ret = getpeername(sockfd, addr, addrlen); - if (ret < 0) { - errno = socket_error(); - } - return ret; -} - -#undef getsockname -int slirp_getsockname_wrap(int sockfd, struct sockaddr *addr, int *addrlen) -{ - int ret; - ret = getsockname(sockfd, addr, addrlen); - if (ret < 0) { - errno = socket_error(); - } - return ret; -} - -#undef send -ssize_t slirp_send_wrap(int sockfd, const void *buf, size_t len, int flags) -{ - int ret; - ret = send(sockfd, buf, len, flags); - if (ret < 0) { - errno = socket_error(); - } - return ret; -} - -#undef sendto -ssize_t slirp_sendto_wrap(int sockfd, const void *buf, size_t len, int flags, - const struct sockaddr *addr, int addrlen) -{ - int ret; - ret = sendto(sockfd, buf, len, flags, addr, addrlen); - if (ret < 0) { - errno = socket_error(); - } - return ret; -} - -#undef recv -ssize_t slirp_recv_wrap(int sockfd, void *buf, size_t len, int flags) -{ - int ret; - ret = recv(sockfd, buf, len, flags); - if (ret < 0) { - errno = socket_error(); - } - return ret; -} - -#undef recvfrom -ssize_t slirp_recvfrom_wrap(int sockfd, void *buf, size_t len, int flags, - struct sockaddr *addr, int *addrlen) -{ - int ret; - ret = recvfrom(sockfd, buf, len, flags, addr, addrlen); - if (ret < 0) { - errno = socket_error(); - } - return ret; -} -#endif /* WIN32 */ - -void slirp_pstrcpy(char *buf, int buf_size, const char *str) -{ - int c; - char *q = buf; - - if (buf_size <= 0) - return; - - for (;;) { - c = *str++; - if (c == 0 || q >= buf + buf_size - 1) - break; - *q++ = c; - } - *q = '\0'; -} - -static int slirp_vsnprintf(char *str, size_t size, - const char *format, va_list args) -{ - int rv = g_vsnprintf(str, size, format, args); - - if (rv < 0) { - g_error("g_vsnprintf() failed: %s", g_strerror(errno)); - } - - return rv; -} - -/* - * A snprintf()-like function that: - * - returns the number of bytes written (excluding optional \0-ending) - * - dies on error - * - warn on truncation - */ -int slirp_fmt(char *str, size_t size, const char *format, ...) -{ - va_list args; - int rv; - - va_start(args, format); - rv = slirp_vsnprintf(str, size, format, args); - va_end(args); - - if (rv >= size) { - g_critical("slirp_fmt() truncation"); - } - - return MIN(rv, size); -} - -/* - * A snprintf()-like function that: - * - always \0-end (unless size == 0) - * - returns the number of bytes actually written, including \0 ending - * - dies on error - * - warn on truncation - */ -int slirp_fmt0(char *str, size_t size, const char *format, ...) -{ - va_list args; - int rv; - - va_start(args, format); - rv = slirp_vsnprintf(str, size, format, args); - va_end(args); - - if (rv >= size) { - g_critical("slirp_fmt0() truncation"); - if (size > 0) - str[size - 1] = '\0'; - rv = size; - } else { - rv += 1; /* include \0 */ - } - - return rv; -} diff --git a/src/network/slirp/util.h b/src/network/slirp/util.h deleted file mode 100644 index 951bfc57d..000000000 --- a/src/network/slirp/util.h +++ /dev/null @@ -1,188 +0,0 @@ -/* SPDX-License-Identifier: MIT */ -/* - * Copyright (c) 2003-2008 Fabrice Bellard - * Copyright (c) 2010-2019 Red Hat, Inc. - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL - * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -#ifndef UTIL_H_ -#define UTIL_H_ - -#include - -#include -#include -#include -#include -#ifndef _WIN32 -#include -#endif -#include -#include -#include - -#ifdef _WIN32 -#include -#include -#else -#include -#include -#include -#endif - -#if defined(_MSC_VER) && !defined(__clang__) -#define SLIRP_PACKED -#elif defined(_WIN32) && (defined(__x86_64__) || defined(__i386__)) && !defined(__clang__) -#define SLIRP_PACKED __attribute__((gcc_struct, packed)) -#else -#define SLIRP_PACKED __attribute__((packed)) -#endif - -#ifndef DIV_ROUND_UP -#define DIV_ROUND_UP(n, d) (((n) + (d)-1) / (d)) -#endif - -#ifndef container_of -#define container_of(ptr, type, member) ((type *)((char *)(ptr) - offsetof(type, member))); -#endif - -#ifndef G_SIZEOF_MEMBER -#define G_SIZEOF_MEMBER(type, member) sizeof(((type *)0)->member) -#endif - -#if defined(_WIN32) /* CONFIG_IOVEC */ -#if !defined(IOV_MAX) /* XXX: to avoid duplicate with QEMU osdep.h */ -struct iovec { - void *iov_base; - size_t iov_len; -}; -#endif -#else -#include -#endif - -#define stringify(s) tostring(s) -#define tostring(s) #s - -#define SCALE_MS 1000000 - -#define ETH_ALEN 6 -#define ETH_HLEN 14 -#define ETH_P_IP (0x0800) /* Internet Protocol packet */ -#define ETH_P_ARP (0x0806) /* Address Resolution packet */ -#define ETH_P_IPV6 (0x86dd) -#define ETH_P_VLAN (0x8100) -#define ETH_P_DVLAN (0x88a8) -#define ETH_P_NCSI (0x88f8) -#define ETH_P_UNKNOWN (0xffff) - -/* FIXME: remove me when made standalone */ -#ifdef _WIN32 -#undef accept -#undef bind -#undef closesocket -#undef connect -#undef getpeername -#undef getsockname -#undef getsockopt -#undef ioctlsocket -#undef listen -#undef recv -#undef recvfrom -#undef send -#undef sendto -#undef setsockopt -#undef shutdown -#undef socket -#endif - -#ifdef _WIN32 -#define connect slirp_connect_wrap -int slirp_connect_wrap(int fd, const struct sockaddr *addr, int addrlen); -#define listen slirp_listen_wrap -int slirp_listen_wrap(int fd, int backlog); -#define bind slirp_bind_wrap -int slirp_bind_wrap(int fd, const struct sockaddr *addr, int addrlen); -#define socket slirp_socket_wrap -int slirp_socket_wrap(int domain, int type, int protocol); -#define accept slirp_accept_wrap -int slirp_accept_wrap(int fd, struct sockaddr *addr, int *addrlen); -#define shutdown slirp_shutdown_wrap -int slirp_shutdown_wrap(int fd, int how); -#define getpeername slirp_getpeername_wrap -int slirp_getpeername_wrap(int fd, struct sockaddr *addr, int *addrlen); -#define getsockname slirp_getsockname_wrap -int slirp_getsockname_wrap(int fd, struct sockaddr *addr, int *addrlen); -#define send slirp_send_wrap -ssize_t slirp_send_wrap(int fd, const void *buf, size_t len, int flags); -#define sendto slirp_sendto_wrap -ssize_t slirp_sendto_wrap(int fd, const void *buf, size_t len, int flags, - const struct sockaddr *dest_addr, int addrlen); -#define recv slirp_recv_wrap -ssize_t slirp_recv_wrap(int fd, void *buf, size_t len, int flags); -#define recvfrom slirp_recvfrom_wrap -ssize_t slirp_recvfrom_wrap(int fd, void *buf, size_t len, int flags, - struct sockaddr *src_addr, int *addrlen); -#define closesocket slirp_closesocket_wrap -int slirp_closesocket_wrap(int fd); -#define ioctlsocket slirp_ioctlsocket_wrap -int slirp_ioctlsocket_wrap(int fd, int req, void *val); -#define getsockopt slirp_getsockopt_wrap -int slirp_getsockopt_wrap(int sockfd, int level, int optname, void *optval, - int *optlen); -#define setsockopt slirp_setsockopt_wrap -int slirp_setsockopt_wrap(int sockfd, int level, int optname, - const void *optval, int optlen); -#define inet_aton slirp_inet_aton -int slirp_inet_aton(const char *cp, struct in_addr *ia); -#else -#define closesocket(s) close(s) -#define ioctlsocket(s, r, v) ioctl(s, r, v) -#endif - -int slirp_socket(int domain, int type, int protocol); -void slirp_set_nonblock(int fd); - -static inline int slirp_socket_set_nodelay(int fd) -{ - int v = 1; - return setsockopt(fd, IPPROTO_TCP, TCP_NODELAY, &v, sizeof(v)); -} - -static inline int slirp_socket_set_fast_reuse(int fd) -{ -#ifndef _WIN32 - int v = 1; - return setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, &v, sizeof(v)); -#else - /* Enabling the reuse of an endpoint that was used by a socket still in - * TIME_WAIT state is usually performed by setting SO_REUSEADDR. On Windows - * fast reuse is the default and SO_REUSEADDR does strange things. So we - * don't have to do anything here. More info can be found at: - * http://msdn.microsoft.com/en-us/library/windows/desktop/ms740621.aspx */ - return 0; -#endif -} - -void slirp_pstrcpy(char *buf, int buf_size, const char *str); - -int slirp_fmt(char *str, size_t size, const char *format, ...) G_GNUC_PRINTF(3, 4); -int slirp_fmt0(char *str, size_t size, const char *format, ...) G_GNUC_PRINTF(3, 4); - -#endif diff --git a/src/network/slirp/version.c b/src/network/slirp/version.c deleted file mode 100644 index 93e0be9c2..000000000 --- a/src/network/slirp/version.c +++ /dev/null @@ -1,8 +0,0 @@ -/* SPDX-License-Identifier: BSD-3-Clause */ -#include "libslirp.h" - -const char * -slirp_version_string(void) -{ - return SLIRP_VERSION_STRING; -} diff --git a/src/network/slirp/vmstate.c b/src/network/slirp/vmstate.c deleted file mode 100644 index b9926ea41..000000000 --- a/src/network/slirp/vmstate.c +++ /dev/null @@ -1,444 +0,0 @@ -/* SPDX-License-Identifier: BSD-3-Clause */ -/* - * VMState interpreter - * - * Copyright (c) 2009-2018 Red Hat Inc - * - * Authors: - * Juan Quintela - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * 1. Redistributions of source code must retain the above - * copyright notice, this list of conditions and the following - * disclaimer. - * - * 2. Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following - * disclaimer in the documentation and/or other materials provided - * with the distribution. - * - * 3. Neither the name of the copyright holder nor the names of its - * contributors may be used to endorse or promote products derived - * from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS - * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE - * COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, - * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES - * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR - * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, - * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED - * OF THE POSSIBILITY OF SUCH DAMAGE. - */ -#include -#include -#include -#include - -#include "stream.h" -#include "vmstate.h" - -static int get_nullptr(SlirpIStream *f, void *pv, size_t size, - const VMStateField *field) -{ - if (slirp_istream_read_u8(f) == VMS_NULLPTR_MARKER) { - return 0; - } - g_warning("vmstate: get_nullptr expected VMS_NULLPTR_MARKER"); - return -EINVAL; -} - -static int put_nullptr(SlirpOStream *f, void *pv, size_t size, - const VMStateField *field) - -{ - if (pv == NULL) { - slirp_ostream_write_u8(f, VMS_NULLPTR_MARKER); - return 0; - } - g_warning("vmstate: put_nullptr must be called with pv == NULL"); - return -EINVAL; -} - -const VMStateInfo slirp_vmstate_info_nullptr = { - .name = "uint64", - .get = get_nullptr, - .put = put_nullptr, -}; - -/* 8 bit unsigned int */ - -static int get_uint8(SlirpIStream *f, void *pv, size_t size, - const VMStateField *field) -{ - uint8_t *v = pv; - *v = slirp_istream_read_u8(f); - return 0; -} - -static int put_uint8(SlirpOStream *f, void *pv, size_t size, - const VMStateField *field) -{ - uint8_t *v = pv; - slirp_ostream_write_u8(f, *v); - return 0; -} - -const VMStateInfo slirp_vmstate_info_uint8 = { - .name = "uint8", - .get = get_uint8, - .put = put_uint8, -}; - -/* 16 bit unsigned int */ - -static int get_uint16(SlirpIStream *f, void *pv, size_t size, - const VMStateField *field) -{ - uint16_t *v = pv; - *v = slirp_istream_read_u16(f); - return 0; -} - -static int put_uint16(SlirpOStream *f, void *pv, size_t size, - const VMStateField *field) -{ - uint16_t *v = pv; - slirp_ostream_write_u16(f, *v); - return 0; -} - -const VMStateInfo slirp_vmstate_info_uint16 = { - .name = "uint16", - .get = get_uint16, - .put = put_uint16, -}; - -/* 32 bit unsigned int */ - -static int get_uint32(SlirpIStream *f, void *pv, size_t size, - const VMStateField *field) -{ - uint32_t *v = pv; - *v = slirp_istream_read_u32(f); - return 0; -} - -static int put_uint32(SlirpOStream *f, void *pv, size_t size, - const VMStateField *field) -{ - uint32_t *v = pv; - slirp_ostream_write_u32(f, *v); - return 0; -} - -const VMStateInfo slirp_vmstate_info_uint32 = { - .name = "uint32", - .get = get_uint32, - .put = put_uint32, -}; - -/* 16 bit int */ - -static int get_int16(SlirpIStream *f, void *pv, size_t size, - const VMStateField *field) -{ - int16_t *v = pv; - *v = slirp_istream_read_i16(f); - return 0; -} - -static int put_int16(SlirpOStream *f, void *pv, size_t size, - const VMStateField *field) -{ - int16_t *v = pv; - slirp_ostream_write_i16(f, *v); - return 0; -} - -const VMStateInfo slirp_vmstate_info_int16 = { - .name = "int16", - .get = get_int16, - .put = put_int16, -}; - -/* 32 bit int */ - -static int get_int32(SlirpIStream *f, void *pv, size_t size, - const VMStateField *field) -{ - int32_t *v = pv; - *v = slirp_istream_read_i32(f); - return 0; -} - -static int put_int32(SlirpOStream *f, void *pv, size_t size, - const VMStateField *field) -{ - int32_t *v = pv; - slirp_ostream_write_i32(f, *v); - return 0; -} - -const VMStateInfo slirp_vmstate_info_int32 = { - .name = "int32", - .get = get_int32, - .put = put_int32, -}; - -/* vmstate_info_tmp, see VMSTATE_WITH_TMP, the idea is that we allocate - * a temporary buffer and the pre_load/pre_save methods in the child vmsd - * copy stuff from the parent into the child and do calculations to fill - * in fields that don't really exist in the parent but need to be in the - * stream. - */ -static int get_tmp(SlirpIStream *f, void *pv, size_t size, - const VMStateField *field) -{ - int ret; - const VMStateDescription *vmsd = field->vmsd; - int version_id = field->version_id; - void *tmp = g_malloc(size); - - /* Writes the parent field which is at the start of the tmp */ - *(void **)tmp = pv; - ret = slirp_vmstate_load_state(f, vmsd, tmp, version_id); - g_free(tmp); - return ret; -} - -static int put_tmp(SlirpOStream *f, void *pv, size_t size, - const VMStateField *field) -{ - const VMStateDescription *vmsd = field->vmsd; - void *tmp = g_malloc(size); - int ret; - - /* Writes the parent field which is at the start of the tmp */ - *(void **)tmp = pv; - ret = slirp_vmstate_save_state(f, vmsd, tmp); - g_free(tmp); - - return ret; -} - -const VMStateInfo slirp_vmstate_info_tmp = { - .name = "tmp", - .get = get_tmp, - .put = put_tmp, -}; - -/* uint8_t buffers */ - -static int get_buffer(SlirpIStream *f, void *pv, size_t size, - const VMStateField *field) -{ - slirp_istream_read(f, pv, size); - return 0; -} - -static int put_buffer(SlirpOStream *f, void *pv, size_t size, - const VMStateField *field) -{ - slirp_ostream_write(f, pv, size); - return 0; -} - -const VMStateInfo slirp_vmstate_info_buffer = { - .name = "buffer", - .get = get_buffer, - .put = put_buffer, -}; - -static int vmstate_n_elems(void *opaque, const VMStateField *field) -{ - int n_elems = 1; - - if (field->flags & VMS_ARRAY) { - n_elems = field->num; - } else if (field->flags & VMS_VARRAY_INT32) { - n_elems = *(int32_t *)(opaque + field->num_offset); - } else if (field->flags & VMS_VARRAY_UINT32) { - n_elems = *(uint32_t *)(opaque + field->num_offset); - } else if (field->flags & VMS_VARRAY_UINT16) { - n_elems = *(uint16_t *)(opaque + field->num_offset); - } else if (field->flags & VMS_VARRAY_UINT8) { - n_elems = *(uint8_t *)(opaque + field->num_offset); - } - - if (field->flags & VMS_MULTIPLY_ELEMENTS) { - n_elems *= field->num; - } - - return n_elems; -} - -static int vmstate_size(void *opaque, const VMStateField *field) -{ - int size = field->size; - - if (field->flags & VMS_VBUFFER) { - size = *(int32_t *)(opaque + field->size_offset); - if (field->flags & VMS_MULTIPLY) { - size *= field->size; - } - } - - return size; -} - -static int vmstate_save_state_v(SlirpOStream *f, const VMStateDescription *vmsd, - void *opaque, int version_id) -{ - int ret = 0; - const VMStateField *field = vmsd->fields; - - if (vmsd->pre_save) { - ret = vmsd->pre_save(opaque); - if (ret) { - g_warning("pre-save failed: %s", vmsd->name); - return ret; - } - } - - while (field->name) { - if ((field->field_exists && field->field_exists(opaque, version_id)) || - (!field->field_exists && field->version_id <= version_id)) { - void *first_elem = opaque + field->offset; - int i, n_elems = vmstate_n_elems(opaque, field); - int size = vmstate_size(opaque, field); - - if (field->flags & VMS_POINTER) { - first_elem = *(void **)first_elem; - assert(first_elem || !n_elems || !size); - } - for (i = 0; i < n_elems; i++) { - void *curr_elem = first_elem + size * i; - - if (field->flags & VMS_ARRAY_OF_POINTER) { - assert(curr_elem); - curr_elem = *(void **)curr_elem; - } - if (!curr_elem && size) { - /* if null pointer write placeholder and do not follow */ - assert(field->flags & VMS_ARRAY_OF_POINTER); - ret = slirp_vmstate_info_nullptr.put(f, curr_elem, size, - NULL); - } else if (field->flags & VMS_STRUCT) { - ret = slirp_vmstate_save_state(f, field->vmsd, curr_elem); - } else if (field->flags & VMS_VSTRUCT) { - ret = vmstate_save_state_v(f, field->vmsd, curr_elem, - field->struct_version_id); - } else { - ret = field->info->put(f, curr_elem, size, field); - } - if (ret) { - g_warning("Save of field %s/%s failed", vmsd->name, - field->name); - return ret; - } - } - } else { - if (field->flags & VMS_MUST_EXIST) { - g_warning("Output state validation failed: %s/%s", vmsd->name, - field->name); - assert(!(field->flags & VMS_MUST_EXIST)); - } - } - field++; - } - - return 0; -} - -int slirp_vmstate_save_state(SlirpOStream *f, const VMStateDescription *vmsd, - void *opaque) -{ - return vmstate_save_state_v(f, vmsd, opaque, vmsd->version_id); -} - -static void vmstate_handle_alloc(void *ptr, VMStateField *field, void *opaque) -{ - if (field->flags & VMS_POINTER && field->flags & VMS_ALLOC) { - size_t size = vmstate_size(opaque, field); - size *= vmstate_n_elems(opaque, field); - if (size) { - *(void **)ptr = g_malloc(size); - } - } -} - -int slirp_vmstate_load_state(SlirpIStream *f, const VMStateDescription *vmsd, - void *opaque, int version_id) -{ - VMStateField *field = vmsd->fields; - int ret = 0; - - if (version_id > vmsd->version_id) { - g_warning("%s: incoming version_id %d is too new " - "for local version_id %d", - vmsd->name, version_id, vmsd->version_id); - return -EINVAL; - } - if (vmsd->pre_load) { - int ret = vmsd->pre_load(opaque); - if (ret) { - return ret; - } - } - while (field->name) { - if ((field->field_exists && field->field_exists(opaque, version_id)) || - (!field->field_exists && field->version_id <= version_id)) { - void *first_elem = opaque + field->offset; - int i, n_elems = vmstate_n_elems(opaque, field); - int size = vmstate_size(opaque, field); - - vmstate_handle_alloc(first_elem, field, opaque); - if (field->flags & VMS_POINTER) { - first_elem = *(void **)first_elem; - assert(first_elem || !n_elems || !size); - } - for (i = 0; i < n_elems; i++) { - void *curr_elem = first_elem + size * i; - - if (field->flags & VMS_ARRAY_OF_POINTER) { - curr_elem = *(void **)curr_elem; - } - if (!curr_elem && size) { - /* if null pointer check placeholder and do not follow */ - assert(field->flags & VMS_ARRAY_OF_POINTER); - ret = slirp_vmstate_info_nullptr.get(f, curr_elem, size, - NULL); - } else if (field->flags & VMS_STRUCT) { - ret = slirp_vmstate_load_state(f, field->vmsd, curr_elem, - field->vmsd->version_id); - } else if (field->flags & VMS_VSTRUCT) { - ret = slirp_vmstate_load_state(f, field->vmsd, curr_elem, - field->struct_version_id); - } else { - ret = field->info->get(f, curr_elem, size, field); - } - if (ret < 0) { - g_warning("Failed to load %s:%s", vmsd->name, field->name); - return ret; - } - } - } else if (field->flags & VMS_MUST_EXIST) { - g_warning("Input validation failed: %s/%s", vmsd->name, - field->name); - return -1; - } - field++; - } - if (vmsd->post_load) { - ret = vmsd->post_load(opaque, version_id); - } - return ret; -} diff --git a/src/network/slirp/vmstate.h b/src/network/slirp/vmstate.h deleted file mode 100644 index e6bed53a6..000000000 --- a/src/network/slirp/vmstate.h +++ /dev/null @@ -1,393 +0,0 @@ -/* SPDX-License-Identifier: BSD-3-Clause */ -/* - * QEMU migration/snapshot declarations - * - * Copyright (c) 2009-2011 Red Hat, Inc. - * - * Original author: Juan Quintela - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * 1. Redistributions of source code must retain the above - * copyright notice, this list of conditions and the following - * disclaimer. - * - * 2. Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following - * disclaimer in the documentation and/or other materials provided - * with the distribution. - * - * 3. Neither the name of the copyright holder nor the names of its - * contributors may be used to endorse or promote products derived - * from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS - * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE - * COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, - * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES - * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR - * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, - * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED - * OF THE POSSIBILITY OF SUCH DAMAGE. - */ -#ifndef VMSTATE_H_ -#define VMSTATE_H_ - -#ifndef _WIN32 -#include -#endif -#include -#include -#include "slirp.h" -#include "stream.h" - -#define stringify(s) tostring(s) -#define tostring(s) #s - -typedef struct VMStateInfo VMStateInfo; -typedef struct VMStateDescription VMStateDescription; -typedef struct VMStateField VMStateField; - -int slirp_vmstate_save_state(SlirpOStream *f, const VMStateDescription *vmsd, - void *opaque); -int slirp_vmstate_load_state(SlirpIStream *f, const VMStateDescription *vmsd, - void *opaque, int version_id); - -/* VMStateInfo allows customized migration of objects that don't fit in - * any category in VMStateFlags. Additional information is always passed - * into get and put in terms of field and vmdesc parameters. However - * these two parameters should only be used in cases when customized - * handling is needed, such as QTAILQ. For primitive data types such as - * integer, field and vmdesc parameters should be ignored inside get/put. - */ -struct VMStateInfo { - const char *name; - int (*get)(SlirpIStream *f, void *pv, size_t size, - const VMStateField *field); - int (*put)(SlirpOStream *f, void *pv, size_t size, - const VMStateField *field); -}; - -enum VMStateFlags { - /* Ignored */ - VMS_SINGLE = 0x001, - - /* The struct member at opaque + VMStateField.offset is a pointer - * to the actual field (e.g. struct a { uint8_t *b; - * }). Dereference the pointer before using it as basis for - * further pointer arithmetic (see e.g. VMS_ARRAY). Does not - * affect the meaning of VMStateField.num_offset or - * VMStateField.size_offset; see VMS_VARRAY* and VMS_VBUFFER for - * those. */ - VMS_POINTER = 0x002, - - /* The field is an array of fixed size. VMStateField.num contains - * the number of entries in the array. The size of each entry is - * given by VMStateField.size and / or opaque + - * VMStateField.size_offset; see VMS_VBUFFER and - * VMS_MULTIPLY. Each array entry will be processed individually - * (VMStateField.info.get()/put() if VMS_STRUCT is not set, - * recursion into VMStateField.vmsd if VMS_STRUCT is set). May not - * be combined with VMS_VARRAY*. */ - VMS_ARRAY = 0x004, - - /* The field is itself a struct, containing one or more - * fields. Recurse into VMStateField.vmsd. Most useful in - * combination with VMS_ARRAY / VMS_VARRAY*, recursing into each - * array entry. */ - VMS_STRUCT = 0x008, - - /* The field is an array of variable size. The int32_t at opaque + - * VMStateField.num_offset contains the number of entries in the - * array. See the VMS_ARRAY description regarding array handling - * in general. May not be combined with VMS_ARRAY or any other - * VMS_VARRAY*. */ - VMS_VARRAY_INT32 = 0x010, - - /* Ignored */ - VMS_BUFFER = 0x020, - - /* The field is a (fixed-size or variable-size) array of pointers - * (e.g. struct a { uint8_t *b[]; }). Dereference each array entry - * before using it. Note: Does not imply any one of VMS_ARRAY / - * VMS_VARRAY*; these need to be set explicitly. */ - VMS_ARRAY_OF_POINTER = 0x040, - - /* The field is an array of variable size. The uint16_t at opaque - * + VMStateField.num_offset (subject to VMS_MULTIPLY_ELEMENTS) - * contains the number of entries in the array. See the VMS_ARRAY - * description regarding array handling in general. May not be - * combined with VMS_ARRAY or any other VMS_VARRAY*. */ - VMS_VARRAY_UINT16 = 0x080, - - /* The size of the individual entries (a single array entry if - * VMS_ARRAY or any of VMS_VARRAY* are set, or the field itself if - * neither is set) is variable (i.e. not known at compile-time), - * but the same for all entries. Use the int32_t at opaque + - * VMStateField.size_offset (subject to VMS_MULTIPLY) to determine - * the size of each (and every) entry. */ - VMS_VBUFFER = 0x100, - - /* Multiply the entry size given by the int32_t at opaque + - * VMStateField.size_offset (see VMS_VBUFFER description) with - * VMStateField.size to determine the number of bytes to be - * allocated. Only valid in combination with VMS_VBUFFER. */ - VMS_MULTIPLY = 0x200, - - /* The field is an array of variable size. The uint8_t at opaque + - * VMStateField.num_offset (subject to VMS_MULTIPLY_ELEMENTS) - * contains the number of entries in the array. See the VMS_ARRAY - * description regarding array handling in general. May not be - * combined with VMS_ARRAY or any other VMS_VARRAY*. */ - VMS_VARRAY_UINT8 = 0x400, - - /* The field is an array of variable size. The uint32_t at opaque - * + VMStateField.num_offset (subject to VMS_MULTIPLY_ELEMENTS) - * contains the number of entries in the array. See the VMS_ARRAY - * description regarding array handling in general. May not be - * combined with VMS_ARRAY or any other VMS_VARRAY*. */ - VMS_VARRAY_UINT32 = 0x800, - - /* Fail loading the serialised VM state if this field is missing - * from the input. */ - VMS_MUST_EXIST = 0x1000, - - /* When loading serialised VM state, allocate memory for the - * (entire) field. Only valid in combination with - * VMS_POINTER. Note: Not all combinations with other flags are - * currently supported, e.g. VMS_ALLOC|VMS_ARRAY_OF_POINTER won't - * cause the individual entries to be allocated. */ - VMS_ALLOC = 0x2000, - - /* Multiply the number of entries given by the integer at opaque + - * VMStateField.num_offset (see VMS_VARRAY*) with VMStateField.num - * to determine the number of entries in the array. Only valid in - * combination with one of VMS_VARRAY*. */ - VMS_MULTIPLY_ELEMENTS = 0x4000, - - /* A structure field that is like VMS_STRUCT, but uses - * VMStateField.struct_version_id to tell which version of the - * structure we are referencing to use. */ - VMS_VSTRUCT = 0x8000, -}; - -struct VMStateField { - const char *name; - size_t offset; - size_t size; - size_t start; - int num; - size_t num_offset; - size_t size_offset; - const VMStateInfo *info; - enum VMStateFlags flags; - const VMStateDescription *vmsd; - int version_id; - int struct_version_id; - bool (*field_exists)(void *opaque, int version_id); -}; - -struct VMStateDescription { - const char *name; - int version_id; - int (*pre_load)(void *opaque); - int (*post_load)(void *opaque, int version_id); - int (*pre_save)(void *opaque); - VMStateField *fields; -}; - - -extern const VMStateInfo slirp_vmstate_info_int16; -extern const VMStateInfo slirp_vmstate_info_int32; -extern const VMStateInfo slirp_vmstate_info_uint8; -extern const VMStateInfo slirp_vmstate_info_uint16; -extern const VMStateInfo slirp_vmstate_info_uint32; - -/** Put this in the stream when migrating a null pointer.*/ -#define VMS_NULLPTR_MARKER (0x30U) /* '0' */ -extern const VMStateInfo slirp_vmstate_info_nullptr; - -extern const VMStateInfo slirp_vmstate_info_buffer; -extern const VMStateInfo slirp_vmstate_info_tmp; - -#define type_check_array(t1, t2, n) ((t1(*)[n])0 - (t2 *)0) -#define type_check_pointer(t1, t2) ((t1 **)0 - (t2 *)0) -#define typeof_field(type, field) typeof(((type *)0)->field) -#define type_check(t1, t2) ((t1 *)0 - (t2 *)0) - -#define vmstate_offset_value(_state, _field, _type) \ - (offsetof(_state, _field) + type_check(_type, typeof_field(_state, _field))) - -#define vmstate_offset_pointer(_state, _field, _type) \ - (offsetof(_state, _field) + \ - type_check_pointer(_type, typeof_field(_state, _field))) - -#define vmstate_offset_array(_state, _field, _type, _num) \ - (offsetof(_state, _field) + \ - type_check_array(_type, typeof_field(_state, _field), _num)) - -#define vmstate_offset_buffer(_state, _field) \ - vmstate_offset_array(_state, _field, uint8_t, \ - sizeof(typeof_field(_state, _field))) - -/* In the macros below, if there is a _version, that means the macro's - * field will be processed only if the version being received is >= - * the _version specified. In general, if you add a new field, you - * would increment the structure's version and put that version - * number into the new field so it would only be processed with the - * new version. - * - * In particular, for VMSTATE_STRUCT() and friends the _version does - * *NOT* pick the version of the sub-structure. It works just as - * specified above. The version of the top-level structure received - * is passed down to all sub-structures. This means that the - * sub-structures must have version that are compatible with all the - * structures that use them. - * - * If you want to specify the version of the sub-structure, use - * VMSTATE_VSTRUCT(), which allows the specific sub-structure version - * to be directly specified. - */ - -#define VMSTATE_SINGLE_TEST(_field, _state, _test, _version, _info, _type) \ - { \ - .name = (stringify(_field)), .version_id = (_version), \ - .field_exists = (_test), .size = sizeof(_type), .info = &(_info), \ - .flags = VMS_SINGLE, \ - .offset = vmstate_offset_value(_state, _field, _type), \ - } - -#define VMSTATE_ARRAY(_field, _state, _num, _version, _info, _type) \ - { \ - .name = (stringify(_field)), .version_id = (_version), .num = (_num), \ - .info = &(_info), .size = sizeof(_type), .flags = VMS_ARRAY, \ - .offset = vmstate_offset_array(_state, _field, _type, _num), \ - } - -#define VMSTATE_STRUCT_TEST(_field, _state, _test, _version, _vmsd, _type) \ - { \ - .name = (stringify(_field)), .version_id = (_version), \ - .field_exists = (_test), .vmsd = &(_vmsd), .size = sizeof(_type), \ - .flags = VMS_STRUCT, \ - .offset = vmstate_offset_value(_state, _field, _type), \ - } - -#define VMSTATE_STRUCT_POINTER_V(_field, _state, _version, _vmsd, _type) \ - { \ - .name = (stringify(_field)), .version_id = (_version), \ - .vmsd = &(_vmsd), .size = sizeof(_type *), \ - .flags = VMS_STRUCT | VMS_POINTER, \ - .offset = vmstate_offset_pointer(_state, _field, _type), \ - } - -#define VMSTATE_STRUCT_ARRAY_TEST(_field, _state, _num, _test, _version, \ - _vmsd, _type) \ - { \ - .name = (stringify(_field)), .num = (_num), .field_exists = (_test), \ - .version_id = (_version), .vmsd = &(_vmsd), .size = sizeof(_type), \ - .flags = VMS_STRUCT | VMS_ARRAY, \ - .offset = vmstate_offset_array(_state, _field, _type, _num), \ - } - -#define VMSTATE_STATIC_BUFFER(_field, _state, _version, _test, _start, _size) \ - { \ - .name = (stringify(_field)), .version_id = (_version), \ - .field_exists = (_test), .size = (_size - _start), \ - .info = &slirp_vmstate_info_buffer, .flags = VMS_BUFFER, \ - .offset = vmstate_offset_buffer(_state, _field) + _start, \ - } - -#define VMSTATE_VBUFFER_UINT32(_field, _state, _version, _test, _field_size) \ - { \ - .name = (stringify(_field)), .version_id = (_version), \ - .field_exists = (_test), \ - .size_offset = vmstate_offset_value(_state, _field_size, uint32_t), \ - .info = &slirp_vmstate_info_buffer, \ - .flags = VMS_VBUFFER | VMS_POINTER, \ - .offset = offsetof(_state, _field), \ - } - -#define QEMU_BUILD_BUG_ON_STRUCT(x) \ - struct { \ - int : (x) ? -1 : 1; \ - } - -#define QEMU_BUILD_BUG_ON_ZERO(x) \ - (sizeof(QEMU_BUILD_BUG_ON_STRUCT(x)) - sizeof(QEMU_BUILD_BUG_ON_STRUCT(x))) - -/* Allocate a temporary of type 'tmp_type', set tmp->parent to _state - * and execute the vmsd on the temporary. Note that we're working with - * the whole of _state here, not a field within it. - * We compile time check that: - * That _tmp_type contains a 'parent' member that's a pointer to the - * '_state' type - * That the pointer is right at the start of _tmp_type. - */ -#define VMSTATE_WITH_TMP(_state, _tmp_type, _vmsd) \ - { \ - .name = "tmp", \ - .size = sizeof(_tmp_type) + \ - QEMU_BUILD_BUG_ON_ZERO(offsetof(_tmp_type, parent) != 0) + \ - type_check_pointer(_state, typeof_field(_tmp_type, parent)), \ - .vmsd = &(_vmsd), .info = &slirp_vmstate_info_tmp, \ - } - -#define VMSTATE_SINGLE(_field, _state, _version, _info, _type) \ - VMSTATE_SINGLE_TEST(_field, _state, NULL, _version, _info, _type) - -#define VMSTATE_STRUCT(_field, _state, _version, _vmsd, _type) \ - VMSTATE_STRUCT_TEST(_field, _state, NULL, _version, _vmsd, _type) - -#define VMSTATE_STRUCT_POINTER(_field, _state, _vmsd, _type) \ - VMSTATE_STRUCT_POINTER_V(_field, _state, 0, _vmsd, _type) - -#define VMSTATE_STRUCT_ARRAY(_field, _state, _num, _version, _vmsd, _type) \ - VMSTATE_STRUCT_ARRAY_TEST(_field, _state, _num, NULL, _version, _vmsd, \ - _type) - -#define VMSTATE_INT16_V(_f, _s, _v) \ - VMSTATE_SINGLE(_f, _s, _v, slirp_vmstate_info_int16, int16_t) -#define VMSTATE_INT32_V(_f, _s, _v) \ - VMSTATE_SINGLE(_f, _s, _v, slirp_vmstate_info_int32, int32_t) - -#define VMSTATE_UINT8_V(_f, _s, _v) \ - VMSTATE_SINGLE(_f, _s, _v, slirp_vmstate_info_uint8, uint8_t) -#define VMSTATE_UINT16_V(_f, _s, _v) \ - VMSTATE_SINGLE(_f, _s, _v, slirp_vmstate_info_uint16, uint16_t) -#define VMSTATE_UINT32_V(_f, _s, _v) \ - VMSTATE_SINGLE(_f, _s, _v, slirp_vmstate_info_uint32, uint32_t) - -#define VMSTATE_INT16(_f, _s) VMSTATE_INT16_V(_f, _s, 0) -#define VMSTATE_INT32(_f, _s) VMSTATE_INT32_V(_f, _s, 0) - -#define VMSTATE_UINT8(_f, _s) VMSTATE_UINT8_V(_f, _s, 0) -#define VMSTATE_UINT16(_f, _s) VMSTATE_UINT16_V(_f, _s, 0) -#define VMSTATE_UINT32(_f, _s) VMSTATE_UINT32_V(_f, _s, 0) - -#define VMSTATE_UINT16_TEST(_f, _s, _t) \ - VMSTATE_SINGLE_TEST(_f, _s, _t, 0, slirp_vmstate_info_uint16, uint16_t) - -#define VMSTATE_UINT32_TEST(_f, _s, _t) \ - VMSTATE_SINGLE_TEST(_f, _s, _t, 0, slirp_vmstate_info_uint32, uint32_t) - -#define VMSTATE_INT16_ARRAY_V(_f, _s, _n, _v) \ - VMSTATE_ARRAY(_f, _s, _n, _v, slirp_vmstate_info_int16, int16_t) - -#define VMSTATE_INT16_ARRAY(_f, _s, _n) VMSTATE_INT16_ARRAY_V(_f, _s, _n, 0) - -#define VMSTATE_BUFFER_V(_f, _s, _v) \ - VMSTATE_STATIC_BUFFER(_f, _s, _v, NULL, 0, sizeof(typeof_field(_s, _f))) - -#define VMSTATE_BUFFER(_f, _s) VMSTATE_BUFFER_V(_f, _s, 0) - -#define VMSTATE_END_OF_LIST() \ - { \ - } - -#endif diff --git a/src/nmi.c b/src/nmi.c index 1e820a82a..fbe3bee19 100644 --- a/src/nmi.c +++ b/src/nmi.c @@ -7,19 +7,19 @@ #include #include <86box/io.h> #include <86box/nmi.h> - +#include <86box/plat_unused.h> int nmi_mask; - -void nmi_write(uint16_t port, uint8_t val, void *p) +void +nmi_write(UNUSED(uint16_t port), uint8_t val, UNUSED(void *priv)) { - nmi_mask = val & 0x80; + nmi_mask = val & 0x80; } - -void nmi_init(void) +void +nmi_init(void) { - io_sethandler(0x00a0, 0x000f, NULL, NULL, NULL, nmi_write, NULL, NULL, NULL); - nmi_mask = 0; + io_sethandler(0x00a0, 0x000f, NULL, NULL, NULL, nmi_write, NULL, NULL, NULL); + nmi_mask = 0; } diff --git a/src/nvr.c b/src/nvr.c index 46e0f6c5a..d833618d0 100644 --- a/src/nvr.c +++ b/src/nvr.c @@ -1,38 +1,36 @@ -/* - * VARCem Virtual ARchaeological Computer EMulator. - * An emulator of (mostly) x86-based PC systems and devices, - * using the ISA,EISA,VLB,MCA and PCI system buses, roughly - * spanning the era between 1981 and 1995. +/* + * VARCem Virtual ARchaeological Computer EMulator. + * An emulator of (mostly) x86-based PC systems and devices, + * using the ISA,EISA,VLB,MCA and PCI system buses, roughly + * spanning the era between 1981 and 1995. * - * This file is part of the VARCem Project. - * - * Implement a generic NVRAM/CMOS/RTC device. + * Implement a generic NVRAM/CMOS/RTC device. * * * - * Authors: Fred N. van Kempen, , - * David HrdliÄka, + * Authors: Fred N. van Kempen, , + * David HrdliÄka, * - * Copyright 2017-2019 Fred N. van Kempen. - * Copyright 2018,2019 David HrdliÄka. + * Copyright 2017-2019 Fred N. van Kempen. + * Copyright 2018-2019 David HrdliÄka. * - * Redistribution and use in source and binary forms, with - * or without modification, are permitted provided that the - * following conditions are met: + * Redistribution and use in source and binary forms, with + * or without modification, are permitted provided that the + * following conditions are met: * - * 1. Redistributions of source code must retain the entire - * above notice, this list of conditions and the following - * disclaimer. + * 1. Redistributions of source code must retain the entire + * above notice, this list of conditions and the following + * disclaimer. * - * 2. Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the - * following disclaimer in the documentation and/or other - * materials provided with the distribution. + * 2. Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the + * following disclaimer in the documentation and/or other + * materials provided with the distribution. * - * 3. Neither the name of the copyright holder nor the names - * of its contributors may be used to endorse or promote - * products derived from this software without specific - * prior written permission. + * 3. Neither the name of the copyright holder nor the names + * of its contributors may be used to endorse or promote + * products derived from this software without specific + * prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT @@ -58,110 +56,104 @@ #include <86box/machine.h> #include <86box/mem.h> #include <86box/timer.h> +#include <86box/path.h> #include <86box/plat.h> #include <86box/nvr.h> +int nvr_dosave; /* NVR is dirty, needs saved */ -int nvr_dosave; /* NVR is dirty, needs saved */ - - -static int8_t days_in_month[12] = { 31,28,31,30,31,30,31,31,30,31,30,31 }; +static int8_t days_in_month[12] = { 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 }; static struct tm intclk; -static nvr_t *saved_nvr = NULL; - +static nvr_t *saved_nvr = NULL; #ifdef ENABLE_NVR_LOG int nvr_do_log = ENABLE_NVR_LOG; - static void nvr_log(const char *fmt, ...) { va_list ap; if (nvr_do_log) { - va_start(ap, fmt); - pclog_ex(fmt, ap); - va_end(ap); + va_start(ap, fmt); + pclog_ex(fmt, ap); + va_end(ap); } } #else -#define nvr_log(fmt, ...) +# define nvr_log(fmt, ...) #endif - /* Determine whether or not the year is leap. */ int nvr_is_leap(int year) { - if (year % 400 == 0) return(1); - if (year % 100 == 0) return(0); - if (year % 4 == 0) return(1); + if (year % 400 == 0) + return 1; + if (year % 100 == 0) + return 0; + if (year % 4 == 0) + return 1; - return(0); + return 0; } - /* Determine the days in the current month. */ int nvr_get_days(int month, int year) { if (month != 2) - return(days_in_month[month - 1]); + return (days_in_month[month - 1]); - return(nvr_is_leap(year) ? 29 : 28); + return (nvr_is_leap(year) ? 29 : 28); } - /* One more second has passed, update the internal clock. */ void rtc_tick(void) { /* Ping the internal clock. */ if (++intclk.tm_sec == 60) { - intclk.tm_sec = 0; - if (++intclk.tm_min == 60) { - intclk.tm_min = 0; - if (++intclk.tm_hour == 24) { - intclk.tm_hour = 0; - if (++intclk.tm_mday == (nvr_get_days(intclk.tm_mon, - intclk.tm_year) + 1)) { - intclk.tm_mday = 1; - if (++intclk.tm_mon == 13) { - intclk.tm_mon = 1; - intclk.tm_year++; - } - } - } - } + intclk.tm_sec = 0; + if (++intclk.tm_min == 60) { + intclk.tm_min = 0; + if (++intclk.tm_hour == 24) { + intclk.tm_hour = 0; + if (++intclk.tm_mday == (nvr_get_days(intclk.tm_mon, intclk.tm_year) + 1)) { + intclk.tm_mday = 1; + if (++intclk.tm_mon == 13) { + intclk.tm_mon = 1; + intclk.tm_year++; + } + } + } + } } } - /* This is the RTC one-second timer. */ static void onesec_timer(void *priv) { - nvr_t *nvr = (nvr_t *)priv; - int is_at; + nvr_t *nvr = (nvr_t *) priv; + int is_at; if (++nvr->onesec_cnt >= 100) { - /* Update the internal clock. */ - is_at = IS_AT(machine); - if (!is_at) - rtc_tick(); + /* Update the internal clock. */ + is_at = IS_AT(machine); + if (!is_at) + rtc_tick(); - /* Update the RTC device if needed. */ - if (nvr->tick != NULL) - (*nvr->tick)(nvr); + /* Update the RTC device if needed. */ + if (nvr->tick != NULL) + (*nvr->tick)(nvr); - nvr->onesec_cnt = 0; + nvr->onesec_cnt = 0; } - timer_advance_u64(&nvr->onesec_time, (uint64_t)(10000ULL * TIMER_USEC)); + timer_advance_u64(&nvr->onesec_time, (uint64_t) (10000ULL * TIMER_USEC)); } - /* Initialize the generic NVRAM/RTC device. */ void nvr_init(nvr_t *nvr) @@ -169,18 +161,18 @@ nvr_init(nvr_t *nvr) int c; /* Set up the NVR file's name. */ - c = strlen(machine_get_internal_name()) + 5; - nvr->fn = (char *)malloc(c + 1); + c = strlen(machine_get_internal_name()) + 5; + nvr->fn = (char *) malloc(c + 1); sprintf(nvr->fn, "%s.nvr", machine_get_internal_name()); /* Initialize the internal clock as needed. */ memset(&intclk, 0x00, sizeof(intclk)); if (time_sync & TIME_SYNC_ENABLED) { - nvr_time_sync(); + nvr_time_sync(); } else { - /* Reset the internal clock to 1980/01/01 00:00. */ - intclk.tm_mon = 1; - intclk.tm_year = 1980; + /* Reset the internal clock to 1980/01/01 00:00. */ + intclk.tm_mon = 1; + intclk.tm_year = 1980; } /* Set up our timer. */ @@ -193,10 +185,9 @@ nvr_init(nvr_t *nvr) saved_nvr = nvr; /* Try to load the saved data. */ - (void)nvr_load(); + (void) nvr_load(); } - /* Get path to the NVR folder. */ char * nvr_path(char *str) @@ -209,17 +200,16 @@ nvr_path(char *str) strcat(temp, NVR_PATH); /* Create the directory if needed. */ - if (! plat_dir_check(temp)) - plat_dir_create(temp); + if (!plat_dir_check(temp)) + plat_dir_create(temp); /* Now append the actual filename. */ - plat_path_slash(temp); + path_slash(temp); strcat(temp, str); - return(temp); + return temp; } - /* * Load an NVR from file. * @@ -234,145 +224,148 @@ nvr_path(char *str) int nvr_load(void) { - char *path; - FILE *fp; + const char *path; + FILE *fp; + uint8_t regs[NVR_MAXSIZE] = { 0 }; /* Make sure we have been initialized. */ - if (saved_nvr == NULL) return(0); + if (saved_nvr == NULL) + return 0; /* Clear out any old data. */ memset(saved_nvr->regs, 0x00, sizeof(saved_nvr->regs)); /* Set the defaults. */ if (saved_nvr->reset != NULL) - saved_nvr->reset(saved_nvr); + saved_nvr->reset(saved_nvr); /* Load the (relevant) part of the NVR contents. */ if (saved_nvr->size != 0) { - path = nvr_path(saved_nvr->fn); - nvr_log("NVR: loading from '%s'\n", path); - fp = plat_fopen(path, "rb"); - saved_nvr->is_new = (fp == NULL); - if (fp != NULL) { - /* Read NVR contents from file. */ - if (fread(saved_nvr->regs, 1, saved_nvr->size, fp) != saved_nvr->size) - fatal("nvr_load(): Error reading data\n"); - (void)fclose(fp); - } + path = nvr_path(saved_nvr->fn); + nvr_log("NVR: loading from '%s'\n", path); + fp = plat_fopen(path, "rb"); + saved_nvr->is_new = (fp == NULL); + if (fp != NULL) { + memcpy(regs, saved_nvr->regs, sizeof(regs)); + /* Read NVR contents from file. */ + if (fread(saved_nvr->regs, 1, saved_nvr->size, fp) != saved_nvr->size) { + memcpy(saved_nvr->regs, regs, sizeof(regs)); + saved_nvr->is_new = 1; + } + (void) fclose(fp); + } } else - saved_nvr->is_new = 1; + saved_nvr->is_new = 1; /* Get the local RTC running! */ if (saved_nvr->start != NULL) - saved_nvr->start(saved_nvr); + saved_nvr->start(saved_nvr); - return(1); + return 1; } - void nvr_set_ven_save(void (*ven_save)(void)) { saved_nvr->ven_save = ven_save; } - /* Save the current NVR to a file. */ int nvr_save(void) { - char *path; - FILE *fp; + const char *path; + FILE *fp; /* Make sure we have been initialized. */ - if (saved_nvr == NULL) return(0); + if (saved_nvr == NULL) + return 0; if (saved_nvr->size != 0) { - path = nvr_path(saved_nvr->fn); - nvr_log("NVR: saving to '%s'\n", path); - fp = plat_fopen(path, "wb"); - if (fp != NULL) { - /* Save NVR contents to file. */ - (void)fwrite(saved_nvr->regs, saved_nvr->size, 1, fp); - fclose(fp); - } + path = nvr_path(saved_nvr->fn); + nvr_log("NVR: saving to '%s'\n", path); + fp = plat_fopen(path, "wb"); + if (fp != NULL) { + /* Save NVR contents to file. */ + (void) fwrite(saved_nvr->regs, saved_nvr->size, 1, fp); + fclose(fp); + } } if (saved_nvr->ven_save) - saved_nvr->ven_save(); + saved_nvr->ven_save(); /* Device is clean again. */ nvr_dosave = 0; - return(1); + return 1; } - void nvr_close(void) { saved_nvr = NULL; } - void nvr_time_sync(void) { struct tm *tm; - time_t now; + time_t now; /* Get the current time of day, and convert to local time. */ - (void)time(&now); - if(time_sync & TIME_SYNC_UTC) - tm = gmtime(&now); + (void) time(&now); + if (time_sync & TIME_SYNC_UTC) + tm = gmtime(&now); else - tm = localtime(&now); + tm = localtime(&now); /* Set the internal clock. */ nvr_time_set(tm); } - /* Get current time from internal clock. */ void nvr_time_get(struct tm *tm) { - uint8_t dom, mon, sum, wd; - uint16_t cent, yr; + uint8_t dom; + uint8_t mon; + uint8_t sum; + uint8_t wd; + uint16_t cent; + uint16_t yr; - tm->tm_sec = intclk.tm_sec; - tm->tm_min = intclk.tm_min; + tm->tm_sec = intclk.tm_sec; + tm->tm_min = intclk.tm_min; tm->tm_hour = intclk.tm_hour; - dom = intclk.tm_mday; - mon = intclk.tm_mon; - yr = (intclk.tm_year % 100); - cent = ((intclk.tm_year - yr) / 100) % 4; - sum = dom+mon+yr+cent; - wd = ((sum + 6) % 7); + dom = intclk.tm_mday; + mon = intclk.tm_mon; + yr = (intclk.tm_year % 100); + cent = ((intclk.tm_year - yr) / 100) % 4; + sum = dom + mon + yr + cent; + wd = ((sum + 6) % 7); tm->tm_wday = wd; tm->tm_mday = intclk.tm_mday; - tm->tm_mon = (intclk.tm_mon - 1); + tm->tm_mon = (intclk.tm_mon - 1); tm->tm_year = (intclk.tm_year - 1900); } - /* Set internal clock time. */ void nvr_time_set(struct tm *tm) { - intclk.tm_sec = tm->tm_sec; - intclk.tm_min = tm->tm_min; + intclk.tm_sec = tm->tm_sec; + intclk.tm_min = tm->tm_min; intclk.tm_hour = tm->tm_hour; intclk.tm_wday = tm->tm_wday; intclk.tm_mday = tm->tm_mday; - intclk.tm_mon = (tm->tm_mon + 1); + intclk.tm_mon = (tm->tm_mon + 1); intclk.tm_year = (tm->tm_year + 1900); } - /* Open or create a file in the NVR area. */ FILE * nvr_fopen(char *str, char *mode) { - return(plat_fopen(nvr_path(str), mode)); + return (plat_fopen(nvr_path(str), mode)); } diff --git a/src/nvr_at.c b/src/nvr_at.c index a7ee53c65..c66799579 100644 --- a/src/nvr_at.c +++ b/src/nvr_at.c @@ -1,1232 +1,1415 @@ -/* - * VARCem Virtual ARchaeological Computer EMulator. - * An emulator of (mostly) x86-based PC systems and devices, - * using the ISA,EISA,VLB,MCA and PCI system buses, roughly - * spanning the era between 1981 and 1995. - * - * This file is part of the VARCem Project. - * - * Implement a more-or-less defacto-standard RTC/NVRAM. - * - * When IBM released the PC/AT machine, it came standard with a - * battery-backed RTC chip to keep the time of day, something - * that was optional on standard PC's with a myriad variants - * being put on the market, often on cheap multi-I/O cards. - * - * The PC/AT had an on-board DS12885-series chip ("the black - * block") which was an RTC/clock chip with onboard oscillator - * and a backup battery (hence the big size.) The chip also had - * a small amount of RAM bytes available to the user, which was - * used by IBM's ROM BIOS to store machine configuration data. - * Later versions and clones used the 12886 and/or 1288(C)7 - * series, or the MC146818 series, all with an external battery. - * Many of those batteries would create corrosion issues later - * on in mainboard life... - * - * Since then, pretty much any PC has an implementation of that - * device, which became known as the "nvr" or "cmos". - * - * NOTES Info extracted from the data sheets: - * - * * The century register at location 32h is a BCD register - * designed to automatically load the BCD value 20 as the - * year register changes from 99 to 00. The MSB of this - * register is not affected when the load of 20 occurs, - * and remains at the value written by the user. - * - * * Rate Selector (RS3:RS0) - * These four rate-selection bits select one of the 13 - * taps on the 15-stage divider or disable the divider - * output. The tap selected can be used to generate an - * output square wave (SQW pin) and/or a periodic interrupt. - * - * The user can do one of the following: - * - enable the interrupt with the PIE bit; - * - enable the SQW output pin with the SQWE bit; - * - enable both at the same time and the same rate; or - * - enable neither. - * - * Table 3 lists the periodic interrupt rates and the square - * wave frequencies that can be chosen with the RS bits. - * These four read/write bits are not affected by !RESET. - * - * * Oscillator (DV2:DV0) - * These three bits are used to turn the oscillator on or - * off and to reset the countdown chain. A pattern of 010 - * is the only combination of bits that turn the oscillator - * on and allow the RTC to keep time. A pattern of 11x - * enables the oscillator but holds the countdown chain in - * reset. The next update occurs at 500ms after a pattern - * of 010 is written to DV0, DV1, and DV2. - * - * * Update-In-Progress (UIP) - * This bit is a status flag that can be monitored. When the - * UIP bit is a 1, the update transfer occurs soon. When - * UIP is a 0, the update transfer does not occur for at - * least 244us. The time, calendar, and alarm information - * in RAM is fully available for access when the UIP bit - * is 0. The UIP bit is read-only and is not affected by - * !RESET. Writing the SET bit in Register B to a 1 - * inhibits any update transfer and clears the UIP status bit. - * - * * Daylight Saving Enable (DSE) - * This bit is a read/write bit that enables two daylight - * saving adjustments when DSE is set to 1. On the first - * Sunday in April (or the last Sunday in April in the - * MC146818A), the time increments from 1:59:59 AM to - * 3:00:00 AM. On the last Sunday in October when the time - * first reaches 1:59:59 AM, it changes to 1:00:00 AM. - * - * When DSE is enabled, the internal logic test for the - * first/last Sunday condition at midnight. If the DSE bit - * is not set when the test occurs, the daylight saving - * function does not operate correctly. These adjustments - * do not occur when the DSE bit is 0. This bit is not - * affected by internal functions or !RESET. - * - * * 24/12 - * The 24/12 control bit establishes the format of the hours - * byte. A 1 indicates the 24-hour mode and a 0 indicates - * the 12-hour mode. This bit is read/write and is not - * affected by internal functions or !RESET. - * - * * Data Mode (DM) - * This bit indicates whether time and calendar information - * is in binary or BCD format. The DM bit is set by the - * program to the appropriate format and can be read as - * required. This bit is not modified by internal functions - * or !RESET. A 1 in DM signifies binary data, while a 0 in - * DM specifies BCD data. - * - * * Square-Wave Enable (SQWE) - * When this bit is set to 1, a square-wave signal at the - * frequency set by the rate-selection bits RS3-RS0 is driven - * out on the SQW pin. When the SQWE bit is set to 0, the - * SQW pin is held low. SQWE is a read/write bit and is - * cleared by !RESET. SQWE is low if disabled, and is high - * impedance when VCC is below VPF. SQWE is cleared to 0 on - * !RESET. - * - * * Update-Ended Interrupt Enable (UIE) - * This bit is a read/write bit that enables the update-end - * flag (UF) bit in Register C to assert !IRQ. The !RESET - * pin going low or the SET bit going high clears the UIE bit. - * The internal functions of the device do not affect the UIE - * bit, but is cleared to 0 on !RESET. - * - * * Alarm Interrupt Enable (AIE) - * This bit is a read/write bit that, when set to 1, permits - * the alarm flag (AF) bit in Register C to assert !IRQ. An - * alarm interrupt occurs for each second that the three time - * bytes equal the three alarm bytes, including a don't-care - * alarm code of binary 11XXXXXX. The AF bit does not - * initiate the !IRQ signal when the AIE bit is set to 0. - * The internal functions of the device do not affect the AIE - * bit, but is cleared to 0 on !RESET. - * - * * Periodic Interrupt Enable (PIE) - * The PIE bit is a read/write bit that allows the periodic - * interrupt flag (PF) bit in Register C to drive the !IRQ pin - * low. When the PIE bit is set to 1, periodic interrupts are - * generated by driving the !IRQ pin low at a rate specified - * by the RS3-RS0 bits of Register A. A 0 in the PIE bit - * blocks the !IRQ output from being driven by a periodic - * interrupt, but the PF bit is still set at the periodic - * rate. PIE is not modified b any internal device functions, - * but is cleared to 0 on !RESET. - * - * * SET - * When the SET bit is 0, the update transfer functions - * normally by advancing the counts once per second. When - * the SET bit is written to 1, any update transfer is - * inhibited, and the program can initialize the time and - * calendar bytes without an update occurring in the midst of - * initializing. Read cycles can be executed in a similar - * manner. SET is a read/write bit and is not affected by - * !RESET or internal functions of the device. - * - * * Update-Ended Interrupt Flag (UF) - * This bit is set after each update cycle. When the UIE - * bit is set to 1, the 1 in UF causes the IRQF bit to be - * a 1, which asserts the !IRQ pin. This bit can be - * cleared by reading Register C or with a !RESET. - * - * * Alarm Interrupt Flag (AF) - * A 1 in the AF bit indicates that the current time has - * matched the alarm time. If the AIE bit is also 1, the - * !IRQ pin goes low and a 1 appears in the IRQF bit. This - * bit can be cleared by reading Register C or with a - * !RESET. - * - * * Periodic Interrupt Flag (PF) - * This bit is read-only and is set to 1 when an edge is - * detected on the selected tap of the divider chain. The - * RS3 through RS0 bits establish the periodic rate. PF is - * set to 1 independent of the state of the PIE bit. When - * both PF and PIE are 1s, the !IRQ signal is active and - * sets the IRQF bit. This bit can be cleared by reading - * Register C or with a !RESET. - * - * * Interrupt Request Flag (IRQF) - * The interrupt request flag (IRQF) is set to a 1 when one - * or more of the following are true: - * - PF == PIE == 1 - * - AF == AIE == 1 - * - UF == UIE == 1 - * Any time the IRQF bit is a 1, the !IRQ pin is driven low. - * All flag bits are cleared after Register C is read by the - * program or when the !RESET pin is low. - * - * * Valid RAM and Time (VRT) - * This bit indicates the condition of the battery connected - * to the VBAT pin. This bit is not writeable and should - * always be 1 when read. If a 0 is ever present, an - * exhausted internal lithium energy source is indicated and - * both the contents of the RTC data and RAM data are - * questionable. This bit is unaffected by !RESET. - * - * This file implements a generic version of the RTC/NVRAM chip, - * including the later update (DS12887A) which implemented a - * "century" register to be compatible with Y2K. - * - * - * - * Authors: Fred N. van Kempen, - * Miran Grca, - * Mahod, - * Sarah Walker, - * - * Copyright 2017-2020 Fred N. van Kempen. - * Copyright 2016-2020 Miran Grca. - * Copyright 2008-2020 Sarah Walker. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the: - * - * Free Software Foundation, Inc. - * 59 Temple Place - Suite 330 - * Boston, MA 02111-1307 - * USA. - */ -#include -#include -#include -#include -#include -#include -#include -#include <86box/86box.h> -#include "cpu.h" -#include <86box/machine.h> -#include <86box/io.h> -#include <86box/mem.h> -#include <86box/nmi.h> -#include <86box/pic.h> -#include <86box/timer.h> -#include <86box/pit.h> -#include <86box/rom.h> -#include <86box/device.h> -#include <86box/nvr.h> - - -/* RTC registers and bit definitions. */ -#define RTC_SECONDS 0 -#define RTC_ALSECONDS 1 -# define AL_DONTCARE 0xc0 /* Alarm time is not set */ -#define RTC_MINUTES 2 -#define RTC_ALMINUTES 3 -#define RTC_HOURS 4 -# define RTC_AMPM 0x80 /* PM flag if 12h format in use */ -#define RTC_ALHOURS 5 -#define RTC_DOW 6 -#define RTC_DOM 7 -#define RTC_MONTH 8 -#define RTC_YEAR 9 -#define RTC_REGA 10 -# define REGA_UIP 0x80 -# define REGA_DV2 0x40 -# define REGA_DV1 0x20 -# define REGA_DV0 0x10 -# define REGA_DV 0x70 -# define REGA_RS3 0x08 -# define REGA_RS2 0x04 -# define REGA_RS1 0x02 -# define REGA_RS0 0x01 -# define REGA_RS 0x0f -#define RTC_REGB 11 -# define REGB_SET 0x80 -# define REGB_PIE 0x40 -# define REGB_AIE 0x20 -# define REGB_UIE 0x10 -# define REGB_SQWE 0x08 -# define REGB_DM 0x04 -# define REGB_2412 0x02 -# define REGB_DSE 0x01 -#define RTC_REGC 12 -# define REGC_IRQF 0x80 -# define REGC_PF 0x40 -# define REGC_AF 0x20 -# define REGC_UF 0x10 -#define RTC_REGD 13 -# define REGD_VRT 0x80 -#define RTC_CENTURY_AT 0x32 /* century register for AT etc */ -#define RTC_CENTURY_PS 0x37 /* century register for PS/1 PS/2 */ -#define RTC_ALDAY 0x7D /* VIA VT82C586B - alarm day */ -#define RTC_ALMONTH 0x7E /* VIA VT82C586B - alarm month */ -#define RTC_CENTURY_VIA 0x7F /* century register for VIA VT82C586B */ - -#define RTC_ALDAY_SIS 0x7E /* Day of Month Alarm for SiS */ -#define RTC_ALMONT_SIS 0x7F /* Month Alarm for SiS */ - -#define RTC_REGS 14 /* number of registers */ - -#define FLAG_AMI_1992_HACK 0x01 -#define FLAG_AMI_1994_HACK 0x02 -#define FLAG_AMI_1995_HACK 0x04 -#define FLAG_P6RP4_HACK 0x08 -#define FLAG_PIIX4 0x10 - - -typedef struct { - int8_t stat; - - uint8_t cent, def, - flags, read_addr, - wp_0d, wp_32, - pad, pad0; - - uint8_t addr[8], wp[2], - bank[8], *lock; - - int16_t count, state; - - uint64_t ecount, - rtc_time; - pc_timer_t update_timer, - rtc_timer; -} local_t; - - -static uint8_t nvr_at_inited = 0; - - -/* Get the current NVR time. */ -static void -time_get(nvr_t *nvr, struct tm *tm) -{ - local_t *local = (local_t *)nvr->data; - int8_t temp; - - if (nvr->regs[RTC_REGB] & REGB_DM) { - /* NVR is in Binary data mode. */ - tm->tm_sec = nvr->regs[RTC_SECONDS]; - tm->tm_min = nvr->regs[RTC_MINUTES]; - temp = nvr->regs[RTC_HOURS]; - tm->tm_wday = (nvr->regs[RTC_DOW] - 1); - tm->tm_mday = nvr->regs[RTC_DOM]; - tm->tm_mon = (nvr->regs[RTC_MONTH] - 1); - tm->tm_year = nvr->regs[RTC_YEAR]; - if (local->cent != 0xFF) - tm->tm_year += (nvr->regs[local->cent] * 100) - 1900; - } else { - /* NVR is in BCD data mode. */ - tm->tm_sec = RTC_DCB(nvr->regs[RTC_SECONDS]); - tm->tm_min = RTC_DCB(nvr->regs[RTC_MINUTES]); - temp = RTC_DCB(nvr->regs[RTC_HOURS]); - tm->tm_wday = (RTC_DCB(nvr->regs[RTC_DOW]) - 1); - tm->tm_mday = RTC_DCB(nvr->regs[RTC_DOM]); - tm->tm_mon = (RTC_DCB(nvr->regs[RTC_MONTH]) - 1); - tm->tm_year = RTC_DCB(nvr->regs[RTC_YEAR]); - if (local->cent != 0xFF) - tm->tm_year += (RTC_DCB(nvr->regs[local->cent]) * 100) - 1900; - } - - /* Adjust for 12/24 hour mode. */ - if (nvr->regs[RTC_REGB] & REGB_2412) - tm->tm_hour = temp; - else - tm->tm_hour = ((temp & ~RTC_AMPM)%12) + ((temp&RTC_AMPM) ? 12 : 0); -} - - -/* Set the current NVR time. */ -static void -time_set(nvr_t *nvr, struct tm *tm) -{ - local_t *local = (local_t *)nvr->data; - int year = (tm->tm_year + 1900); - - if (nvr->regs[RTC_REGB] & REGB_DM) { - /* NVR is in Binary data mode. */ - nvr->regs[RTC_SECONDS] = tm->tm_sec; - nvr->regs[RTC_MINUTES] = tm->tm_min; - nvr->regs[RTC_DOW] = (tm->tm_wday + 1); - nvr->regs[RTC_DOM] = tm->tm_mday; - nvr->regs[RTC_MONTH] = (tm->tm_mon + 1); - nvr->regs[RTC_YEAR] = (year % 100); - if (local->cent != 0xFF) - nvr->regs[local->cent] = (year / 100); - - if (nvr->regs[RTC_REGB] & REGB_2412) { - /* NVR is in 24h mode. */ - nvr->regs[RTC_HOURS] = tm->tm_hour; - } else { - /* NVR is in 12h mode. */ - nvr->regs[RTC_HOURS] = (tm->tm_hour % 12) ? (tm->tm_hour % 12) : 12; - if (tm->tm_hour > 11) - nvr->regs[RTC_HOURS] |= RTC_AMPM; - } - } else { - /* NVR is in BCD data mode. */ - nvr->regs[RTC_SECONDS] = RTC_BCD(tm->tm_sec); - nvr->regs[RTC_MINUTES] = RTC_BCD(tm->tm_min); - nvr->regs[RTC_DOW] = RTC_BCD(tm->tm_wday + 1); - nvr->regs[RTC_DOM] = RTC_BCD(tm->tm_mday); - nvr->regs[RTC_MONTH] = RTC_BCD(tm->tm_mon + 1); - nvr->regs[RTC_YEAR] = RTC_BCD(year % 100); - if (local->cent != 0xFF) - nvr->regs[local->cent] = RTC_BCD(year / 100); - - if (nvr->regs[RTC_REGB] & REGB_2412) { - /* NVR is in 24h mode. */ - nvr->regs[RTC_HOURS] = RTC_BCD(tm->tm_hour); - } else { - /* NVR is in 12h mode. */ - nvr->regs[RTC_HOURS] = (tm->tm_hour % 12) - ? RTC_BCD(tm->tm_hour % 12) - : RTC_BCD(12); - if (tm->tm_hour > 11) - nvr->regs[RTC_HOURS] |= RTC_AMPM; - } - } -} - - -/* Check if the current time matches a set alarm time. */ -static int8_t -check_alarm(nvr_t *nvr, int8_t addr) -{ - return((nvr->regs[addr+1] == nvr->regs[addr]) || - ((nvr->regs[addr+1] & AL_DONTCARE) == AL_DONTCARE)); -} - - -/* Check for VIA stuff. */ -static int8_t -check_alarm_via(nvr_t *nvr, int8_t addr, int8_t addr_2) -{ - local_t *local = (local_t *)nvr->data; - - if (local->cent == RTC_CENTURY_VIA) { - return((nvr->regs[addr_2] == nvr->regs[addr]) || - ((nvr->regs[addr_2] & AL_DONTCARE) == AL_DONTCARE)); - } else - return 1; -} - - -/* Update the NVR registers from the internal clock. */ -static void -timer_update(void *priv) -{ - nvr_t *nvr = (nvr_t *)priv; - local_t *local = (local_t *)nvr->data; - struct tm tm; - - local->ecount = 0LL; - - if (! (nvr->regs[RTC_REGB] & REGB_SET)) { - /* Get the current time from the internal clock. */ - nvr_time_get(&tm); - - /* Update registers with current time. */ - time_set(nvr, &tm); - - /* Clear update status. */ - local->stat = 0x00; - - /* Check for any alarms we need to handle. */ - if (check_alarm(nvr, RTC_SECONDS) && - check_alarm(nvr, RTC_MINUTES) && - check_alarm(nvr, RTC_HOURS) && - check_alarm_via(nvr, RTC_DOM, RTC_ALDAY) && - check_alarm_via(nvr, RTC_MONTH, RTC_ALMONTH)/* && - check_alarm_via(nvr, RTC_DOM, RTC_ALDAY_SIS) && - check_alarm_via(nvr, RTC_MONTH, RTC_ALMONT_SIS)*/) { - nvr->regs[RTC_REGC] |= REGC_AF; - if (nvr->regs[RTC_REGB] & REGB_AIE) { - nvr->regs[RTC_REGC] |= REGC_IRQF; - - /* Generate an interrupt. */ - if (nvr->irq != -1) - picint(1 << nvr->irq); - } - } - - /* - * The flag and interrupt should be issued - * on update ended, not started. - */ - nvr->regs[RTC_REGC] |= REGC_UF; - if (nvr->regs[RTC_REGB] & REGB_UIE) { - nvr->regs[RTC_REGC] |= REGC_IRQF; - - /* Generate an interrupt. */ - if (nvr->irq != -1) - picint(1 << nvr->irq); - } - } -} - - -static void -timer_load_count(nvr_t *nvr) -{ - int c = nvr->regs[RTC_REGA] & REGA_RS; - local_t *local = (local_t *) nvr->data; - - if ((nvr->regs[RTC_REGA] & 0x70) != 0x20) { - local->state = 0; - return; - } - - local->state = 1; - - switch (c) { - case 0: - local->state = 0; - break; - case 1: case 2: - local->count = 1 << (c + 6); - break; - default: - local->count = 1 << (c - 1); - break; - } -} - - -static void -timer_intr(void *priv) -{ - nvr_t *nvr = (nvr_t *)priv; - local_t *local = (local_t *)nvr->data; - - timer_advance_u64(&local->rtc_timer, RTCCONST); - - if (local->state == 1) { - if (--local->count == 0) { - timer_load_count(nvr); - - nvr->regs[RTC_REGC] |= REGC_PF; - if (nvr->regs[RTC_REGB] & REGB_PIE) { - nvr->regs[RTC_REGC] |= REGC_IRQF; - - /* Generate an interrupt. */ - if (nvr->irq != -1) - picint(1 << nvr->irq); - } - } - } -} - - -/* Callback from internal clock, another second passed. */ -static void -timer_tick(nvr_t *nvr) -{ - local_t *local = (local_t *)nvr->data; - - /* Only update it there is no SET in progress. */ - if (! (nvr->regs[RTC_REGB] & REGB_SET)) { - /* Set the UIP bit, announcing the update. */ - local->stat = REGA_UIP; - - rtc_tick(); - - /* Schedule the actual update. */ - local->ecount = (244ULL + 1984ULL) * TIMER_USEC; - timer_set_delay_u64(&local->update_timer, local->ecount); - } -} - - -static void -nvr_reg_common_write(uint16_t reg, uint8_t val, nvr_t *nvr, local_t *local) -{ - if ((reg == 0x2c) && (local->flags & FLAG_AMI_1994_HACK)) - nvr->is_new = 0; - if ((reg == 0x2d) && (local->flags & FLAG_AMI_1992_HACK)) - nvr->is_new = 0; - if ((reg == 0x52) && (local->flags & FLAG_AMI_1995_HACK)) - nvr->is_new = 0; - if ((reg >= 0x38) && (reg <= 0x3f) && local->wp[0]) - return; - if ((reg >= 0xb8) && (reg <= 0xbf) && local->wp[1]) - return; - if (local->lock[reg]) - return; - if (nvr->regs[reg] != val) { - nvr->regs[reg] = val; - nvr_dosave = 1; - } -} - - -/* This must be exposed because ACPI uses it. */ -void -nvr_reg_write(uint16_t reg, uint8_t val, void *priv) -{ - nvr_t *nvr = (nvr_t *)priv; - local_t *local = (local_t *)nvr->data; - struct tm tm; - uint8_t old; - - old = nvr->regs[reg]; - switch(reg) { - case RTC_REGA: - nvr->regs[RTC_REGA] = val; - timer_load_count(nvr); - break; - - case RTC_REGB: - nvr->regs[RTC_REGB] = val; - if (((old^val) & REGB_SET) && (val & REGB_SET)) { - /* According to the datasheet... */ - nvr->regs[RTC_REGA] &= ~REGA_UIP; - nvr->regs[RTC_REGB] &= ~REGB_UIE; - } - break; - - case RTC_REGC: /* R/O */ - break; - - case RTC_REGD: /* R/O */ - /* This is needed for VIA, where writing to this register changes a write-only - bit whose value is read from power management register 42. */ - nvr->regs[RTC_REGD] = val & 0x80; - break; - - case 0x32: - if ((reg == 0x32) && (local->cent == RTC_CENTURY_VIA) && local->wp_32) - break; - nvr_reg_common_write(reg, val, nvr, local); - break; - - default: /* non-RTC registers are just NVRAM */ - nvr_reg_common_write(reg, val, nvr, local); - break; - } - - if ((reg < RTC_REGA) || ((local->cent != 0xff) && (reg == local->cent))) { - if ((reg != 1) && (reg != 3) && (reg != 5)) { - if ((old != val) && !(time_sync & TIME_SYNC_ENABLED)) { - /* Update internal clock. */ - time_get(nvr, &tm); - nvr_time_set(&tm); - nvr_dosave = 1; - } - } - } -} - - -/* Write to one of the NVR registers. */ -static void -nvr_write(uint16_t addr, uint8_t val, void *priv) -{ - nvr_t *nvr = (nvr_t *)priv; - local_t *local = (local_t *)nvr->data; - uint8_t addr_id = (addr & 0x0e) >> 1; - - cycles -= ISA_CYCLES(8); - - if (local->bank[addr_id] == 0xff) - return; - - if (addr & 1) { - // if (local->bank[addr_id] == 0xff) - // return; - nvr_reg_write(local->addr[addr_id], val, priv); - } else { - local->addr[addr_id] = (val & (nvr->size - 1)); - /* Some chipsets use a 256 byte NVRAM but ports 70h and 71h always access only 128 bytes. */ - if (addr_id == 0x0) - local->addr[addr_id] &= 0x7f; - else if ((addr_id == 0x1) && (local->flags & FLAG_PIIX4)) - local->addr[addr_id] = (local->addr[addr_id] & 0x7f) | 0x80; - if (local->bank[addr_id] > 0) - local->addr[addr_id] = (local->addr[addr_id] & 0x7f) | (0x80 * local->bank[addr_id]); - if (!(machines[machine].flags & MACHINE_MCA) && - !(machines[machine].flags & MACHINE_NONMI)) - nmi_mask = (~val & 0x80); - } -} - - -/* Read from one of the NVR registers. */ -static uint8_t -nvr_read(uint16_t addr, void *priv) -{ - nvr_t *nvr = (nvr_t *)priv; - local_t *local = (local_t *)nvr->data; - uint8_t ret; - uint8_t addr_id = (addr & 0x0e) >> 1; - uint16_t i, checksum = 0x0000; - - cycles -= ISA_CYCLES(8); - - if (local->bank[addr_id] == 0xff) - ret = 0xff; - else if (addr & 1) switch(local->addr[addr_id]) { - case RTC_REGA: - ret = (nvr->regs[RTC_REGA] & 0x7f) | local->stat; - break; - - case RTC_REGC: - picintc(1 << nvr->irq); - ret = nvr->regs[RTC_REGC]; - nvr->regs[RTC_REGC] = 0x00; - break; - - case RTC_REGD: - /* Bits 6-0 of this register always read 0. Bit 7 is battery state, - we should always return it set, as that means the battery is OK. */ - ret = REGD_VRT; - break; - - case 0x2c: - if (!nvr->is_new && (local->flags & FLAG_AMI_1994_HACK)) - ret = nvr->regs[local->addr[addr_id]] & 0x7f; - else - ret = nvr->regs[local->addr[addr_id]]; - break; - - case 0x2d: - if (!nvr->is_new && (local->flags & FLAG_AMI_1992_HACK)) - ret = nvr->regs[local->addr[addr_id]] & 0xf7; - else - ret = nvr->regs[local->addr[addr_id]]; - break; - - case 0x2e: - case 0x2f: - if (!nvr->is_new && (local->flags & FLAG_AMI_1992_HACK)) { - for (i = 0x10; i <= 0x2d; i++) { - if (i == 0x2d) - checksum += (nvr->regs[i] & 0xf7); - else - checksum += nvr->regs[i]; - } - if (local->addr[addr_id] == 0x2e) - ret = checksum >> 8; - else - ret = checksum & 0xff; - } else if (!nvr->is_new && (local->flags & FLAG_AMI_1994_HACK)) { - for (i = 0x10; i <= 0x2d; i++) { - if (i == 0x2c) - checksum += (nvr->regs[i] & 0x7f); - else - checksum += nvr->regs[i]; - } - if (local->addr[addr_id] == 0x2e) - ret = checksum >> 8; - else - ret = checksum & 0xff; - } else - ret = nvr->regs[local->addr[addr_id]]; - break; - - case 0x3e: - case 0x3f: - if (!nvr->is_new && (local->flags & FLAG_AMI_1995_HACK)) { - /* The checksum at 3E-3F is for 37-3D and 40-7F. */ - for (i = 0x37; i <= 0x3d; i++) - checksum += nvr->regs[i]; - for (i = 0x40; i <= 0x7f; i++) { - if (i == 0x52) - checksum += (nvr->regs[i] & 0xf3); - else - checksum += nvr->regs[i]; - } - if (local->addr[addr_id] == 0x3e) - ret = checksum >> 8; - else - ret = checksum & 0xff; - } else if (!nvr->is_new && (local->flags & FLAG_P6RP4_HACK)) { - /* The checksum at 3E-3F is for 37-3D and 40-51. */ - for (i = 0x37; i <= 0x3d; i++) - checksum += nvr->regs[i]; - for (i = 0x40; i <= 0x51; i++) { - if (i == 0x43) - checksum += (nvr->regs[i] | 0x02); - else - checksum += nvr->regs[i]; - } - if (local->addr[addr_id] == 0x3e) - ret = checksum >> 8; - else - ret = checksum & 0xff; - } else - ret = nvr->regs[local->addr[addr_id]]; - break; - - case 0x43: - if (!nvr->is_new && (local->flags & FLAG_P6RP4_HACK)) - ret = nvr->regs[local->addr[addr_id]] | 0x02; - else - ret = nvr->regs[local->addr[addr_id]]; - break; - - case 0x52: - if (!nvr->is_new && (local->flags & FLAG_AMI_1995_HACK)) - ret = nvr->regs[local->addr[addr_id]] & 0xf3; - else - ret = nvr->regs[local->addr[addr_id]]; - break; - - default: - ret = nvr->regs[local->addr[addr_id]]; - break; - } else { - ret = local->addr[addr_id]; - if (!local->read_addr) - ret &= 0x80; - if (alt_access) - ret = (ret & 0x7f) | (nmi_mask ? 0x00 : 0x80); - } - - return(ret); -} - -/* Secondary NVR write - used by SMC. */ -static void -nvr_sec_write(uint16_t addr, uint8_t val, void *priv) -{ - nvr_write(0x72 + (addr & 1), val, priv); -} - - -/* Secondary NVR read - used by SMC. */ -static uint8_t -nvr_sec_read(uint16_t addr, void *priv) -{ - return nvr_read(0x72 + (addr & 1), priv); -} - -/* Reset the RTC state to 1980/01/01 00:00. */ -static void -nvr_reset(nvr_t *nvr) -{ - local_t *local = (local_t *)nvr->data; - - /* memset(nvr->regs, local->def, RTC_REGS); */ - memset(nvr->regs, local->def, nvr->size); - nvr->regs[RTC_DOM] = 1; - nvr->regs[RTC_MONTH] = 1; - nvr->regs[RTC_YEAR] = RTC_BCD(80); - if (local->cent != 0xFF) - nvr->regs[local->cent] = RTC_BCD(19); - - nvr->regs[RTC_REGD] = REGD_VRT; -} - -/* Process after loading from file. */ -static void -nvr_start(nvr_t *nvr) -{ - int i; - local_t *local = (local_t *) nvr->data; - - struct tm tm; - int default_found = 0; - - for (i = 0; i < nvr->size; i++) { - if (nvr->regs[i] == local->def) - default_found++; - } - - if (default_found == nvr->size) - nvr->regs[0x0e] = 0xff; /* If load failed or it loaded an uninitialized NVR, - mark everything as bad. */ - - /* Initialize the internal and chip times. */ - if (time_sync & TIME_SYNC_ENABLED) { - /* Use the internal clock's time. */ - nvr_time_get(&tm); - time_set(nvr, &tm); - } else { - /* Set the internal clock from the chip time. */ - time_get(nvr, &tm); - nvr_time_set(&tm); - } - - /* Start the RTC. */ - nvr->regs[RTC_REGA] = (REGA_RS2|REGA_RS1); - nvr->regs[RTC_REGB] = REGB_2412; -} - - -static void -nvr_at_speed_changed(void *priv) -{ - nvr_t *nvr = (nvr_t *) priv; - local_t *local = (local_t *) nvr->data; - - timer_disable(&local->rtc_timer); - timer_set_delay_u64(&local->rtc_timer, RTCCONST); - - timer_disable(&local->update_timer); - if (local->ecount > 0ULL) - timer_set_delay_u64(&local->update_timer, local->ecount); - - timer_disable(&nvr->onesec_time); - timer_set_delay_u64(&nvr->onesec_time, (10000ULL * TIMER_USEC)); -} - - -void -nvr_at_handler(int set, uint16_t base, nvr_t *nvr) -{ - io_handler(set, base, 2, - nvr_read,NULL,NULL, nvr_write,NULL,NULL, nvr); -} - - -void -nvr_at_sec_handler(int set, uint16_t base, nvr_t *nvr) -{ - io_handler(set, base, 2, - nvr_sec_read,NULL,NULL, nvr_sec_write,NULL,NULL, nvr); -} - -void -nvr_read_addr_set(int set, nvr_t *nvr) -{ - local_t *local = (local_t *) nvr->data; - - local->read_addr = set; -} - - -void -nvr_wp_set(int set, int h, nvr_t *nvr) -{ - local_t *local = (local_t *) nvr->data; - - local->wp[h] = set; -} - - -void -nvr_via_wp_set(int set, int reg, nvr_t *nvr) -{ - local_t *local = (local_t *) nvr->data; - - if (reg == 0x0d) - local->wp_0d = set; - else - local->wp_32 = set; -} - - -void -nvr_bank_set(int base, uint8_t bank, nvr_t *nvr) -{ - local_t *local = (local_t *) nvr->data; - - local->bank[base] = bank; -} - - -void -nvr_lock_set(int base, int size, int lock, nvr_t *nvr) -{ - local_t *local = (local_t *) nvr->data; - int i; - - for (i = 0; i < size; i++) - local->lock[base + i] = lock; -} - - -void -nvr_irq_set(int irq, nvr_t *nvr) -{ - nvr->irq = irq; -} - - -static void -nvr_at_reset(void *priv) -{ - nvr_t *nvr = (nvr_t *) priv; - - /* These bits are reset on reset. */ - nvr->regs[RTC_REGB] &= ~(REGB_PIE | REGB_AIE | REGB_UIE | REGB_SQWE); - nvr->regs[RTC_REGC] &= ~(REGC_PF | REGC_AF | REGC_UF | REGC_IRQF); -} - - -static void * -nvr_at_init(const device_t *info) -{ - local_t *local; - nvr_t *nvr; - - /* Allocate an NVR for this machine. */ - nvr = (nvr_t *)malloc(sizeof(nvr_t)); - if (nvr == NULL) return(NULL); - memset(nvr, 0x00, sizeof(nvr_t)); - - local = (local_t *)malloc(sizeof(local_t)); - memset(local, 0x00, sizeof(local_t)); - nvr->data = local; - - /* This is machine specific. */ - nvr->size = machines[machine].nvrmask + 1; - local->lock = (uint8_t *) malloc(nvr->size); - memset(local->lock, 0x00, nvr->size); - local->def = 0xff /*0x00*/; - local->flags = 0x00; - switch(info->local & 7) { - case 0: /* standard AT, no century register */ - if (info->local == 16) { - local->flags |= FLAG_P6RP4_HACK; - nvr->irq = 8; - local->cent = RTC_CENTURY_AT; - } else { - nvr->irq = 8; - local->cent = 0xff; - } - break; - - case 1: /* standard AT */ - case 5: /* AMI WinBIOS 1994 */ - case 6: /* AMI BIOS 1995 */ - if (info->local == 9) - local->flags |= FLAG_PIIX4; - else { - local->def = 0x00; - if ((info->local & 7) == 5) - local->flags |= FLAG_AMI_1994_HACK; - else if ((info->local & 7) == 6) - local->flags |= FLAG_AMI_1995_HACK; - else - local->def = 0xff; - } - nvr->irq = 8; - local->cent = RTC_CENTURY_AT; - break; - - case 2: /* PS/1 or PS/2 */ - nvr->irq = 8; - local->cent = RTC_CENTURY_PS; - local->def = 0x00; - break; - - case 3: /* Amstrad PC's */ - nvr->irq = 1; - local->cent = RTC_CENTURY_AT; - local->def = 0xff; - break; - - case 4: /* IBM AT */ - if (info->local == 12) { - local->def = 0x00; - local->flags |= FLAG_AMI_1992_HACK; - } else - local->def = 0xff; - nvr->irq = 8; - local->cent = RTC_CENTURY_AT; - break; - - case 7: /* VIA VT82C586B */ - nvr->irq = 8; - local->cent = RTC_CENTURY_VIA; - break; - } - - local->read_addr = 1; - - /* Set up any local handlers here. */ - nvr->reset = nvr_reset; - nvr->start = nvr_start; - nvr->tick = timer_tick; - - /* Initialize the generic NVR. */ - nvr_init(nvr); - - if (nvr_at_inited == 0) { - /* Start the timers. */ - timer_add(&local->update_timer, timer_update, nvr, 0); - - timer_add(&local->rtc_timer, timer_intr, nvr, 0); - /* On power on, if the oscillator is disabled, it's reenabled. */ - if ((nvr->regs[RTC_REGA] & 0x70) == 0x00) - nvr->regs[RTC_REGA] = (nvr->regs[RTC_REGA] & 0x8f) | 0x20; - nvr_at_reset(nvr); - timer_load_count(nvr); - timer_set_delay_u64(&local->rtc_timer, RTCCONST); - - /* Set up the I/O handler for this device. */ - io_sethandler(0x0070, 2, - nvr_read,NULL,NULL, nvr_write,NULL,NULL, nvr); - if (info->local & 8) { - io_sethandler(0x0072, 2, - nvr_read,NULL,NULL, nvr_write,NULL,NULL, nvr); - } - - nvr_at_inited = 1; - } - - return(nvr); -} - - -static void -nvr_at_close(void *priv) -{ - nvr_t *nvr = (nvr_t *) priv; - local_t *local = (local_t *) nvr->data; - - nvr_close(); - - timer_disable(&local->rtc_timer); - timer_disable(&local->update_timer); - timer_disable(&nvr->onesec_time); - - if (nvr != NULL) { - if (nvr->fn != NULL) - free(nvr->fn); - - if (nvr->data != NULL) - free(nvr->data); - - free(nvr); - } - - if (nvr_at_inited == 1) - nvr_at_inited = 0; -} - - -const device_t at_nvr_old_device = { - "PC/AT NVRAM (No century)", - "at_nvr_old", - DEVICE_ISA | DEVICE_AT, - 0, - nvr_at_init, nvr_at_close, nvr_at_reset, - { NULL }, nvr_at_speed_changed, - NULL -}; - -const device_t at_nvr_device = { - "PC/AT NVRAM", - "at_nvr", - DEVICE_ISA | DEVICE_AT, - 1, - nvr_at_init, nvr_at_close, nvr_at_reset, - { NULL }, nvr_at_speed_changed, - NULL -}; - -const device_t ps_nvr_device = { - "PS/1 or PS/2 NVRAM", - "ps_nvr", - DEVICE_PS2, - 2, - nvr_at_init, nvr_at_close, nvr_at_reset, - { NULL }, nvr_at_speed_changed, - NULL -}; - -const device_t amstrad_nvr_device = { - "Amstrad NVRAM", - "amstrad_nvr", - DEVICE_ISA | DEVICE_AT, - 3, - nvr_at_init, nvr_at_close, nvr_at_reset, - { NULL }, nvr_at_speed_changed, - NULL -}; - -const device_t ibmat_nvr_device = { - "IBM AT NVRAM", - "ibmat_nvr", - DEVICE_ISA | DEVICE_AT, - 4, - nvr_at_init, nvr_at_close, nvr_at_reset, - { NULL }, nvr_at_speed_changed, - NULL -}; - -const device_t piix4_nvr_device = { - "Intel PIIX4 PC/AT NVRAM", - "piix4_nvr", - DEVICE_ISA | DEVICE_AT, - 9, - nvr_at_init, nvr_at_close, nvr_at_reset, - { NULL }, nvr_at_speed_changed, - NULL -}; - -const device_t ami_1992_nvr_device = { - "AMI Color 1992 PC/AT NVRAM", - "ami_1992_nvr", - DEVICE_ISA | DEVICE_AT, - 12, - nvr_at_init, nvr_at_close, nvr_at_reset, - { NULL }, nvr_at_speed_changed, - NULL -}; - -const device_t ami_1994_nvr_device = { - "AMI WinBIOS 1994 PC/AT NVRAM", - "ami_1994_nvr", - DEVICE_ISA | DEVICE_AT, - 13, - nvr_at_init, nvr_at_close, nvr_at_reset, - { NULL }, nvr_at_speed_changed, - NULL -}; - -const device_t ami_1995_nvr_device = { - "AMI WinBIOS 1995 PC/AT NVRAM", - "ami_1995_nvr", - DEVICE_ISA | DEVICE_AT, - 14, - nvr_at_init, nvr_at_close, nvr_at_reset, - { NULL }, nvr_at_speed_changed, - NULL -}; - -const device_t via_nvr_device = { - "VIA PC/AT NVRAM", - "via_nvr", - DEVICE_ISA | DEVICE_AT, - 15, - nvr_at_init, nvr_at_close, nvr_at_reset, - { NULL }, nvr_at_speed_changed, - NULL -}; - -const device_t p6rp4_nvr_device = { - "ASUS P/I-P6RP4 PC/AT NVRAM", - "p6rp4_nvr", - DEVICE_ISA | DEVICE_AT, - 16, - nvr_at_init, nvr_at_close, nvr_at_reset, - { NULL }, nvr_at_speed_changed, - NULL -}; +/* + * 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. + * + * Implement a more-or-less defacto-standard RTC/NVRAM. + * + * When IBM released the PC/AT machine, it came standard with a + * battery-backed RTC chip to keep the time of day, something + * that was optional on standard PC's with a myriad variants + * being put on the market, often on cheap multi-I/O cards. + * + * The PC/AT had an on-board DS12885-series chip ("the black + * block") which was an RTC/clock chip with onboard oscillator + * and a backup battery (hence the big size.) The chip also had + * a small amount of RAM bytes available to the user, which was + * used by IBM's ROM BIOS to store machine configuration data. + * Later versions and clones used the 12886 and/or 1288(C)7 + * series, or the MC146818 series, all with an external battery. + * Many of those batteries would create corrosion issues later + * on in mainboard life... + * + * Since then, pretty much any PC has an implementation of that + * device, which became known as the "nvr" or "cmos". + * + * NOTES Info extracted from the data sheets: + * + * * The century register at location 32h is a BCD register + * designed to automatically load the BCD value 20 as the + * year register changes from 99 to 00. The MSB of this + * register is not affected when the load of 20 occurs, + * and remains at the value written by the user. + * + * * Rate Selector (RS3:RS0) + * These four rate-selection bits select one of the 13 + * taps on the 15-stage divider or disable the divider + * output. The tap selected can be used to generate an + * output square wave (SQW pin) and/or a periodic interrupt. + * + * The user can do one of the following: + * - enable the interrupt with the PIE bit; + * - enable the SQW output pin with the SQWE bit; + * - enable both at the same time and the same rate; or + * - enable neither. + * + * Table 3 lists the periodic interrupt rates and the square + * wave frequencies that can be chosen with the RS bits. + * These four read/write bits are not affected by !RESET. + * + * * Oscillator (DV2:DV0) + * These three bits are used to turn the oscillator on or + * off and to reset the countdown chain. A pattern of 010 + * is the only combination of bits that turn the oscillator + * on and allow the RTC to keep time. A pattern of 11x + * enables the oscillator but holds the countdown chain in + * reset. The next update occurs at 500ms after a pattern + * of 010 is written to DV0, DV1, and DV2. + * + * * Update-In-Progress (UIP) + * This bit is a status flag that can be monitored. When the + * UIP bit is a 1, the update transfer occurs soon. When + * UIP is a 0, the update transfer does not occur for at + * least 244us. The time, calendar, and alarm information + * in RAM is fully available for access when the UIP bit + * is 0. The UIP bit is read-only and is not affected by + * !RESET. Writing the SET bit in Register B to a 1 + * inhibits any update transfer and clears the UIP status bit. + * + * * Daylight Saving Enable (DSE) + * This bit is a read/write bit that enables two daylight + * saving adjustments when DSE is set to 1. On the first + * Sunday in April (or the last Sunday in April in the + * MC146818A), the time increments from 1:59:59 AM to + * 3:00:00 AM. On the last Sunday in October when the time + * first reaches 1:59:59 AM, it changes to 1:00:00 AM. + * + * When DSE is enabled, the internal logic test for the + * first/last Sunday condition at midnight. If the DSE bit + * is not set when the test occurs, the daylight saving + * function does not operate correctly. These adjustments + * do not occur when the DSE bit is 0. This bit is not + * affected by internal functions or !RESET. + * + * * 24/12 + * The 24/12 control bit establishes the format of the hours + * byte. A 1 indicates the 24-hour mode and a 0 indicates + * the 12-hour mode. This bit is read/write and is not + * affected by internal functions or !RESET. + * + * * Data Mode (DM) + * This bit indicates whether time and calendar information + * is in binary or BCD format. The DM bit is set by the + * program to the appropriate format and can be read as + * required. This bit is not modified by internal functions + * or !RESET. A 1 in DM signifies binary data, while a 0 in + * DM specifies BCD data. + * + * * Square-Wave Enable (SQWE) + * When this bit is set to 1, a square-wave signal at the + * frequency set by the rate-selection bits RS3-RS0 is driven + * out on the SQW pin. When the SQWE bit is set to 0, the + * SQW pin is held low. SQWE is a read/write bit and is + * cleared by !RESET. SQWE is low if disabled, and is high + * impedance when VCC is below VPF. SQWE is cleared to 0 on + * !RESET. + * + * * Update-Ended Interrupt Enable (UIE) + * This bit is a read/write bit that enables the update-end + * flag (UF) bit in Register C to assert !IRQ. The !RESET + * pin going low or the SET bit going high clears the UIE bit. + * The internal functions of the device do not affect the UIE + * bit, but is cleared to 0 on !RESET. + * + * * Alarm Interrupt Enable (AIE) + * This bit is a read/write bit that, when set to 1, permits + * the alarm flag (AF) bit in Register C to assert !IRQ. An + * alarm interrupt occurs for each second that the three time + * bytes equal the three alarm bytes, including a don't-care + * alarm code of binary 11XXXXXX. The AF bit does not + * initiate the !IRQ signal when the AIE bit is set to 0. + * The internal functions of the device do not affect the AIE + * bit, but is cleared to 0 on !RESET. + * + * * Periodic Interrupt Enable (PIE) + * The PIE bit is a read/write bit that allows the periodic + * interrupt flag (PF) bit in Register C to drive the !IRQ pin + * low. When the PIE bit is set to 1, periodic interrupts are + * generated by driving the !IRQ pin low at a rate specified + * by the RS3-RS0 bits of Register A. A 0 in the PIE bit + * blocks the !IRQ output from being driven by a periodic + * interrupt, but the PF bit is still set at the periodic + * rate. PIE is not modified b any internal device functions, + * but is cleared to 0 on !RESET. + * + * * SET + * When the SET bit is 0, the update transfer functions + * normally by advancing the counts once per second. When + * the SET bit is written to 1, any update transfer is + * inhibited, and the program can initialize the time and + * calendar bytes without an update occurring in the midst of + * initializing. Read cycles can be executed in a similar + * manner. SET is a read/write bit and is not affected by + * !RESET or internal functions of the device. + * + * * Update-Ended Interrupt Flag (UF) + * This bit is set after each update cycle. When the UIE + * bit is set to 1, the 1 in UF causes the IRQF bit to be + * a 1, which asserts the !IRQ pin. This bit can be + * cleared by reading Register C or with a !RESET. + * + * * Alarm Interrupt Flag (AF) + * A 1 in the AF bit indicates that the current time has + * matched the alarm time. If the AIE bit is also 1, the + * !IRQ pin goes low and a 1 appears in the IRQF bit. This + * bit can be cleared by reading Register C or with a + * !RESET. + * + * * Periodic Interrupt Flag (PF) + * This bit is read-only and is set to 1 when an edge is + * detected on the selected tap of the divider chain. The + * RS3 through RS0 bits establish the periodic rate. PF is + * set to 1 independent of the state of the PIE bit. When + * both PF and PIE are 1s, the !IRQ signal is active and + * sets the IRQF bit. This bit can be cleared by reading + * Register C or with a !RESET. + * + * * Interrupt Request Flag (IRQF) + * The interrupt request flag (IRQF) is set to a 1 when one + * or more of the following are true: + * - PF == PIE == 1 + * - AF == AIE == 1 + * - UF == UIE == 1 + * Any time the IRQF bit is a 1, the !IRQ pin is driven low. + * All flag bits are cleared after Register C is read by the + * program or when the !RESET pin is low. + * + * * Valid RAM and Time (VRT) + * This bit indicates the condition of the battery connected + * to the VBAT pin. This bit is not writeable and should + * always be 1 when read. If a 0 is ever present, an + * exhausted internal lithium energy source is indicated and + * both the contents of the RTC data and RAM data are + * questionable. This bit is unaffected by !RESET. + * + * This file implements a generic version of the RTC/NVRAM chip, + * including the later update (DS12887A) which implemented a + * "century" register to be compatible with Y2K. + * + * + * + * Authors: Fred N. van Kempen, + * Miran Grca, + * Mahod, + * + * Copyright 2017-2020 Fred N. van Kempen. + * Copyright 2016-2020 Miran Grca. + * Copyright 2016-2020 Mahod. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the: + * + * Free Software Foundation, Inc. + * 59 Temple Place - Suite 330 + * Boston, MA 02111-1307 + * USA. + */ +#include +#include +#include +#include +#include +#include +#include +#include <86box/86box.h> +#include "cpu.h" +#include <86box/machine.h> +#include <86box/io.h> +#include <86box/mem.h> +#include <86box/nmi.h> +#include <86box/pic.h> +#include <86box/timer.h> +#include <86box/pit.h> +#include <86box/rom.h> +#include <86box/device.h> +#include <86box/nvr.h> + +/* RTC registers and bit definitions. */ +#define RTC_SECONDS 0 +#define RTC_ALSECONDS 1 +#define AL_DONTCARE 0xc0 /* Alarm time is not set */ +#define RTC_MINUTES 2 +#define RTC_ALMINUTES 3 +#define RTC_HOURS 4 +#define RTC_AMPM 0x80 /* PM flag if 12h format in use */ +#define RTC_ALHOURS 5 +#define RTC_DOW 6 +#define RTC_DOM 7 +#define RTC_MONTH 8 +#define RTC_YEAR 9 +#define RTC_REGA 10 +#define REGA_UIP 0x80 +#define REGA_DV2 0x40 +#define REGA_DV1 0x20 +#define REGA_DV0 0x10 +#define REGA_DV 0x70 +#define REGA_RS3 0x08 +#define REGA_RS2 0x04 +#define REGA_RS1 0x02 +#define REGA_RS0 0x01 +#define REGA_RS 0x0f +#define RTC_REGB 11 +#define REGB_SET 0x80 +#define REGB_PIE 0x40 +#define REGB_AIE 0x20 +#define REGB_UIE 0x10 +#define REGB_SQWE 0x08 +#define REGB_DM 0x04 +#define REGB_2412 0x02 +#define REGB_DSE 0x01 +#define RTC_REGC 12 +#define REGC_IRQF 0x80 +#define REGC_PF 0x40 +#define REGC_AF 0x20 +#define REGC_UF 0x10 +#define RTC_REGD 13 +#define REGD_VRT 0x80 +#define RTC_CENTURY_AT 0x32 /* century register for AT etc */ +#define RTC_CENTURY_PS 0x37 /* century register for PS/1 PS/2 */ +#define RTC_CENTURY_ELT 0x1A /* century register for Epson Equity LT */ +#define RTC_ALDAY 0x7D /* VIA VT82C586B - alarm day */ +#define RTC_ALMONTH 0x7E /* VIA VT82C586B - alarm month */ +#define RTC_CENTURY_VIA 0x7F /* century register for VIA VT82C586B */ + +#define RTC_ALDAY_SIS 0x7E /* Day of Month Alarm for SiS */ +#define RTC_ALMONT_SIS 0x7F /* Month Alarm for SiS */ + +#define RTC_REGS 14 /* number of registers */ + +#define FLAG_NO_NMI 0x01 +#define FLAG_AMI_1992_HACK 0x02 +#define FLAG_AMI_1994_HACK 0x04 +#define FLAG_AMI_1995_HACK 0x08 +#define FLAG_P6RP4_HACK 0x10 +#define FLAG_PIIX4 0x20 +#define FLAG_MULTI_BANK 0x40 + +typedef struct local_t { + int8_t stat; + + uint8_t cent; + uint8_t def; + uint8_t flags; + uint8_t read_addr; + uint8_t wp_0d; + uint8_t wp_32; + uint8_t irq_state; + uint8_t smi_status; + + uint8_t addr[8]; + uint8_t wp[2]; + uint8_t bank[8]; + uint8_t *lock; + + int16_t count; + int16_t state; + + int32_t smi_enable; + + uint64_t ecount; + uint64_t rtc_time; + pc_timer_t update_timer; + pc_timer_t rtc_timer; +} local_t; + +static uint8_t nvr_at_inited = 0; + +/* Get the current NVR time. */ +static void +time_get(nvr_t *nvr, struct tm *tm) +{ + const local_t *local = (local_t *) nvr->data; + int8_t temp; + + if (nvr->regs[RTC_REGB] & REGB_DM) { + /* NVR is in Binary data mode. */ + tm->tm_sec = nvr->regs[RTC_SECONDS]; + tm->tm_min = nvr->regs[RTC_MINUTES]; + temp = nvr->regs[RTC_HOURS]; + tm->tm_wday = (nvr->regs[RTC_DOW] - 1); + tm->tm_mday = nvr->regs[RTC_DOM]; + tm->tm_mon = (nvr->regs[RTC_MONTH] - 1); + tm->tm_year = nvr->regs[RTC_YEAR]; + if (local->cent != 0xFF) + tm->tm_year += (nvr->regs[local->cent] * 100) - 1900; + } else { + /* NVR is in BCD data mode. */ + tm->tm_sec = RTC_DCB(nvr->regs[RTC_SECONDS]); + tm->tm_min = RTC_DCB(nvr->regs[RTC_MINUTES]); + temp = RTC_DCB(nvr->regs[RTC_HOURS]); + tm->tm_wday = (RTC_DCB(nvr->regs[RTC_DOW]) - 1); + tm->tm_mday = RTC_DCB(nvr->regs[RTC_DOM]); + tm->tm_mon = (RTC_DCB(nvr->regs[RTC_MONTH]) - 1); + tm->tm_year = RTC_DCB(nvr->regs[RTC_YEAR]); + if (local->cent != 0xFF) + tm->tm_year += (RTC_DCB(nvr->regs[local->cent]) * 100) - 1900; + } + + /* Adjust for 12/24 hour mode. */ + if (nvr->regs[RTC_REGB] & REGB_2412) + tm->tm_hour = temp; + else + tm->tm_hour = ((temp & ~RTC_AMPM) % 12) + ((temp & RTC_AMPM) ? 12 : 0); +} + +/* Set the current NVR time. */ +static void +time_set(nvr_t *nvr, struct tm *tm) +{ + const local_t *local = (local_t *) nvr->data; + int year = (tm->tm_year + 1900); + + if (nvr->regs[RTC_REGB] & REGB_DM) { + /* NVR is in Binary data mode. */ + nvr->regs[RTC_SECONDS] = tm->tm_sec; + nvr->regs[RTC_MINUTES] = tm->tm_min; + nvr->regs[RTC_DOW] = (tm->tm_wday + 1); + nvr->regs[RTC_DOM] = tm->tm_mday; + nvr->regs[RTC_MONTH] = (tm->tm_mon + 1); + nvr->regs[RTC_YEAR] = (year % 100); + if (local->cent != 0xFF) + nvr->regs[local->cent] = (year / 100); + + if (nvr->regs[RTC_REGB] & REGB_2412) { + /* NVR is in 24h mode. */ + nvr->regs[RTC_HOURS] = tm->tm_hour; + } else { + /* NVR is in 12h mode. */ + nvr->regs[RTC_HOURS] = (tm->tm_hour % 12) ? (tm->tm_hour % 12) : 12; + if (tm->tm_hour > 11) + nvr->regs[RTC_HOURS] |= RTC_AMPM; + } + } else { + /* NVR is in BCD data mode. */ + nvr->regs[RTC_SECONDS] = RTC_BCD(tm->tm_sec); + nvr->regs[RTC_MINUTES] = RTC_BCD(tm->tm_min); + nvr->regs[RTC_DOW] = RTC_BCD(tm->tm_wday + 1); + nvr->regs[RTC_DOM] = RTC_BCD(tm->tm_mday); + nvr->regs[RTC_MONTH] = RTC_BCD(tm->tm_mon + 1); + nvr->regs[RTC_YEAR] = RTC_BCD(year % 100); + if (local->cent != 0xFF) + nvr->regs[local->cent] = RTC_BCD(year / 100); + + if (nvr->regs[RTC_REGB] & REGB_2412) { + /* NVR is in 24h mode. */ + nvr->regs[RTC_HOURS] = RTC_BCD(tm->tm_hour); + } else { + /* NVR is in 12h mode. */ + nvr->regs[RTC_HOURS] = (tm->tm_hour % 12) + ? RTC_BCD(tm->tm_hour % 12) + : RTC_BCD(12); + if (tm->tm_hour > 11) + nvr->regs[RTC_HOURS] |= RTC_AMPM; + } + } +} + +/* Check if the current time matches a set alarm time. */ +static int8_t +check_alarm(nvr_t *nvr, int8_t addr) +{ + return ((nvr->regs[addr + 1] == nvr->regs[addr]) || ((nvr->regs[addr + 1] & AL_DONTCARE) == AL_DONTCARE)); +} + +/* Check for VIA stuff. */ +static int8_t +check_alarm_via(nvr_t *nvr, int8_t addr, int8_t addr_2) +{ + const local_t *local = (local_t *) nvr->data; + + if (local->cent == RTC_CENTURY_VIA) { + return ((nvr->regs[addr_2] == nvr->regs[addr]) || ((nvr->regs[addr_2] & AL_DONTCARE) == AL_DONTCARE)); + } else + return 1; +} + +static void +timer_update_irq(nvr_t *nvr) +{ + local_t *local = (local_t *) nvr->data; + uint8_t irq = (nvr->regs[RTC_REGB] & nvr->regs[RTC_REGC]) & (REGB_UIE | REGB_AIE | REGB_PIE); + + if (irq || (local->irq_state != !!irq)) { + if (irq) { + nvr->regs[RTC_REGC] |= REGC_IRQF; + picintlevel(1 << nvr->irq, &local->irq_state); + if (local->smi_enable) { + smi_raise(); + local->smi_status = 1; + } + } else { + nvr->regs[RTC_REGC] &= ~REGC_IRQF; + picintclevel(1 << nvr->irq, &local->irq_state); + } + } +} + +/* Update the NVR registers from the internal clock. */ +static void +timer_update(void *priv) +{ + nvr_t *nvr = (nvr_t *) priv; + local_t *local = (local_t *) nvr->data; + struct tm tm; + + if (local->ecount == (244ULL * TIMER_USEC)) { + rtc_tick(); + + /* Get the current time from the internal clock. */ + nvr_time_get(&tm); + + /* Update registers with current time. */ + time_set(nvr, &tm); + + /* Check for any alarms we need to handle. */ + if (check_alarm(nvr, RTC_SECONDS) && check_alarm(nvr, RTC_MINUTES) && check_alarm(nvr, RTC_HOURS) && + check_alarm_via(nvr, RTC_DOM, RTC_ALDAY) && check_alarm_via(nvr, RTC_MONTH, RTC_ALMONTH) /* && + check_alarm_via(nvr, RTC_DOM, RTC_ALDAY_SIS) && check_alarm_via(nvr, RTC_MONTH, RTC_ALMONT_SIS) */) { + nvr->regs[RTC_REGC] |= REGC_AF; + timer_update_irq(nvr); + } + + /* Schedule the end of the update. */ + local->ecount = 1984ULL * TIMER_USEC; + timer_set_delay_u64(&local->update_timer, local->ecount); + } else { + /* + * The flag and interrupt should be issued + * on update ended, not started. + */ + nvr->regs[RTC_REGC] |= REGC_UF; + timer_update_irq(nvr); + + /* Clear update status. */ + local->stat = 0x00; + + local->ecount = 0LL; + } +} + +static void +timer_load_count(nvr_t *nvr) +{ + int c = nvr->regs[RTC_REGA] & REGA_RS; + local_t *local = (local_t *) nvr->data; + + timer_disable(&local->rtc_timer); + + if ((nvr->regs[RTC_REGA] & 0x70) != 0x20) { + local->state = 0; + return; + } + + local->state = 1; + + switch (c) { + case 0: + local->state = 0; + break; + case 1: + case 2: + local->count = 1 << (c + 6); + timer_set_delay_u64(&local->rtc_timer, (local->count) * RTCCONST); + break; + default: + local->count = 1 << (c - 1); + timer_set_delay_u64(&local->rtc_timer, (local->count) * RTCCONST); + break; + } +} + +static void +timer_intr(void *priv) +{ + nvr_t *nvr = (nvr_t *) priv; + const local_t *local = (local_t *) nvr->data; + + if (local->state == 1) { + timer_load_count(nvr); + + nvr->regs[RTC_REGC] |= REGC_PF; + timer_update_irq(nvr); + } +} + +/* Callback from internal clock, another second passed. */ +static void +timer_tick(nvr_t *nvr) +{ + local_t *local = (local_t *) nvr->data; + + /* Only update it there is no SET in progress. + Also avoid updating it is DV2-DV0 are not set to 0, 1, 0. */ + if (((nvr->regs[RTC_REGA] & 0x70) == 0x20) && !(nvr->regs[RTC_REGB] & REGB_SET)) { + /* Set the UIP bit, announcing the update. */ + local->stat = REGA_UIP; + + /* Schedule the actual update. */ + local->ecount = 244ULL * TIMER_USEC; + timer_set_delay_u64(&local->update_timer, local->ecount); + } +} + +static void +nvr_reg_common_write(uint16_t reg, uint8_t val, nvr_t *nvr, local_t *local) +{ + if (local->lock[reg]) + return; + if ((reg == 0x2c) && (local->flags & FLAG_AMI_1994_HACK)) + nvr->is_new = 0; + if ((reg == 0x2d) && (local->flags & FLAG_AMI_1992_HACK)) + nvr->is_new = 0; + if ((reg == 0x52) && (local->flags & FLAG_AMI_1995_HACK)) + nvr->is_new = 0; + if ((reg >= 0x38) && (reg <= 0x3f) && local->wp[0]) + return; + if ((reg >= 0xb8) && (reg <= 0xbf) && local->wp[1]) + return; + if (nvr->regs[reg] != val) { + nvr->regs[reg] = val; + if ((reg >= 0x0d) && ((local->cent == 0xff) || (reg != local->cent))) + nvr_dosave = 1; + } +} + +/* This must be exposed because ACPI uses it. */ +void +nvr_reg_write(uint16_t reg, uint8_t val, void *priv) +{ + nvr_t *nvr = (nvr_t *) priv; + local_t *local = (local_t *) nvr->data; + struct tm tm; + uint8_t old; + + old = nvr->regs[reg]; + switch (reg) { + case RTC_SECONDS: /* bit 7 of seconds is read-only */ + nvr_reg_common_write(reg, val & 0x7f, nvr, local); + break; + + case RTC_REGA: + if ((val & nvr->regs[RTC_REGA]) & ~REGA_UIP) { + nvr->regs[RTC_REGA] = (nvr->regs[RTC_REGA] & REGA_UIP) | (val & ~REGA_UIP); + timer_load_count(nvr); + } + break; + + case RTC_REGB: + if (((old ^ val) & REGB_SET) && (val & REGB_SET)) { + /* According to the datasheet... */ + val &= ~REGB_UIE; + local->stat &= ~REGA_UIP; + } + + nvr->regs[RTC_REGB] = val; + timer_update_irq(nvr); + break; + + case RTC_REGC: /* R/O */ + break; + + case RTC_REGD: /* R/O */ + /* This is needed for VIA, where writing to this register changes a write-only + bit whose value is read from power management register 42. */ + nvr->regs[RTC_REGD] = val & 0x80; + break; + + case 0x32: + if ((reg == 0x32) && (local->cent == RTC_CENTURY_VIA) && local->wp_32) + break; + nvr_reg_common_write(reg, val, nvr, local); + break; + + default: /* non-RTC registers are just NVRAM */ + nvr_reg_common_write(reg, val, nvr, local); + break; + } + + if ((reg < RTC_REGA) || ((local->cent != 0xff) && (reg == local->cent))) { + if ((reg != 1) && (reg != 3) && (reg != 5)) { + if ((old != val) && !(time_sync & TIME_SYNC_ENABLED)) { + /* Update internal clock. */ + time_get(nvr, &tm); + nvr_time_set(&tm); + // nvr_dosave = 1; + } + } + } +} + +/* Write to one of the NVR registers. */ +static void +nvr_write(uint16_t addr, uint8_t val, void *priv) +{ + nvr_t *nvr = (nvr_t *) priv; + local_t *local = (local_t *) nvr->data; + uint8_t addr_id = (addr & 0x0e) >> 1; + + cycles -= ISA_CYCLES(8); + + if (local->bank[addr_id] == 0xff) + return; + + if (addr & 1) { +#if 0 + if (local->bank[addr_id] == 0xff) + return; +#endif + nvr_reg_write(local->addr[addr_id], val, priv); + } else { + local->addr[addr_id] = (val & (nvr->size - 1)); + /* Some chipsets use a 256 byte NVRAM but ports 70h and 71h always access only 128 bytes. */ + if (addr_id == 0x0) { + local->addr[addr_id] &= 0x7f; + /* Needed for OPTi 82C601/82C602 and NSC PC87306. */ + if (local->flags & FLAG_MULTI_BANK) + local->addr[addr_id] |= (0x80 * local->bank[addr_id]); + } else if ((addr_id == 0x1) && (local->flags & FLAG_PIIX4)) + local->addr[addr_id] = (local->addr[addr_id] & 0x7f) | 0x80; + if (local->bank[addr_id] > 0) + local->addr[addr_id] = (local->addr[addr_id] & 0x7f) | (0x80 * local->bank[addr_id]); + if (!(local->flags & FLAG_NO_NMI)) + nmi_mask = (~val & 0x80); + } +} + +/* Read from one of the NVR registers. */ +static uint8_t +nvr_read(uint16_t addr, void *priv) +{ + nvr_t *nvr = (nvr_t *) priv; + const local_t *local = (local_t *) nvr->data; + uint8_t ret; + uint8_t addr_id = (addr & 0x0e) >> 1; + uint16_t i; + uint16_t checksum = 0x0000; + + cycles -= ISA_CYCLES(8); + + if (local->bank[addr_id] == 0xff) + ret = 0xff; + else if (addr & 1) + switch (local->addr[addr_id]) { + case RTC_REGA: + ret = (nvr->regs[RTC_REGA] & 0x7f) | local->stat; + break; + + case RTC_REGC: + ret = nvr->regs[RTC_REGC] & (REGC_IRQF | REGC_PF | REGC_AF | REGC_UF); + nvr->regs[RTC_REGC] &= ~(REGC_IRQF | REGC_PF | REGC_AF | REGC_UF); + timer_update_irq(nvr); + break; + + case RTC_REGD: + /* Bits 6-0 of this register always read 0. Bit 7 is battery state, + we should always return it set, as that means the battery is OK. */ + ret = REGD_VRT; + break; + + case 0x2c: + if (!nvr->is_new && (local->flags & FLAG_AMI_1994_HACK)) + ret = nvr->regs[local->addr[addr_id]] & 0x7f; + else + ret = nvr->regs[local->addr[addr_id]]; + break; + + case 0x2d: + if (!nvr->is_new && (local->flags & FLAG_AMI_1992_HACK)) + ret = nvr->regs[local->addr[addr_id]] & 0xf7; + else + ret = nvr->regs[local->addr[addr_id]]; + break; + + case 0x2e: + case 0x2f: + if (!nvr->is_new && (local->flags & FLAG_AMI_1992_HACK)) { + for (i = 0x10; i <= 0x2d; i++) { + if (i == 0x2d) + checksum += (nvr->regs[i] & 0xf7); + else + checksum += nvr->regs[i]; + } + if (local->addr[addr_id] == 0x2e) + ret = checksum >> 8; + else + ret = checksum & 0xff; + } else if (!nvr->is_new && (local->flags & FLAG_AMI_1994_HACK)) { + for (i = 0x10; i <= 0x2d; i++) { + if (i == 0x2c) + checksum += (nvr->regs[i] & 0x7f); + else + checksum += nvr->regs[i]; + } + if (local->addr[addr_id] == 0x2e) + ret = checksum >> 8; + else + ret = checksum & 0xff; + } else + ret = nvr->regs[local->addr[addr_id]]; + break; + + case 0x3e: + case 0x3f: + if (!nvr->is_new && (local->flags & FLAG_AMI_1995_HACK)) { + /* The checksum at 3E-3F is for 37-3D and 40-7F. */ + for (i = 0x37; i <= 0x3d; i++) + checksum += nvr->regs[i]; + for (i = 0x40; i <= 0x7f; i++) { + if (i == 0x52) + checksum += (nvr->regs[i] & 0xf3); + else + checksum += nvr->regs[i]; + } + if (local->addr[addr_id] == 0x3e) + ret = checksum >> 8; + else + ret = checksum & 0xff; + } else if (!nvr->is_new && (local->flags & FLAG_P6RP4_HACK)) { + /* The checksum at 3E-3F is for 37-3D and 40-51. */ + for (i = 0x37; i <= 0x3d; i++) + checksum += nvr->regs[i]; + for (i = 0x40; i <= 0x51; i++) { + if (i == 0x43) + checksum += (nvr->regs[i] | 0x02); + else + checksum += nvr->regs[i]; + } + if (local->addr[addr_id] == 0x3e) + ret = checksum >> 8; + else + ret = checksum & 0xff; + } else + ret = nvr->regs[local->addr[addr_id]]; + break; + + case 0x43: + if (!nvr->is_new && (local->flags & FLAG_P6RP4_HACK)) + ret = nvr->regs[local->addr[addr_id]] | 0x02; + else + ret = nvr->regs[local->addr[addr_id]]; + break; + + case 0x52: + if (!nvr->is_new && (local->flags & FLAG_AMI_1995_HACK)) + ret = nvr->regs[local->addr[addr_id]] & 0xf3; + else + ret = nvr->regs[local->addr[addr_id]]; + break; + + default: + ret = nvr->regs[local->addr[addr_id]]; + break; + } + else { + ret = local->addr[addr_id]; + if (!local->read_addr) + ret &= 0x80; + if (alt_access) + ret = (ret & 0x7f) | (nmi_mask ? 0x00 : 0x80); + } + + return ret; +} + +/* Secondary NVR write - used by SMC. */ +static void +nvr_sec_write(uint16_t addr, uint8_t val, void *priv) +{ + nvr_write(0x72 + (addr & 1), val, priv); +} + +/* Secondary NVR read - used by SMC. */ +static uint8_t +nvr_sec_read(uint16_t addr, void *priv) +{ + return nvr_read(0x72 + (addr & 1), priv); +} + +/* Reset the RTC state to 1980/01/01 00:00. */ +static void +nvr_reset(nvr_t *nvr) +{ + const local_t *local = (local_t *) nvr->data; + +#if 0 + memset(nvr->regs, local->def, RTC_REGS); +#endif + memset(nvr->regs, local->def, nvr->size); + nvr->regs[RTC_DOM] = 1; + nvr->regs[RTC_MONTH] = 1; + nvr->regs[RTC_YEAR] = RTC_BCD(80); + if (local->cent != 0xFF) + nvr->regs[local->cent] = RTC_BCD(19); + + nvr->regs[RTC_REGD] = REGD_VRT; +} + +/* Process after loading from file. */ +static void +nvr_start(nvr_t *nvr) +{ + const local_t *local = (local_t *) nvr->data; + + struct tm tm; + int default_found = 0; + + for (uint16_t i = 0; i < nvr->size; i++) { + if (nvr->regs[i] == local->def) + default_found++; + } + + if (default_found == nvr->size) + nvr->regs[0x0e] = 0xff; /* If load failed or it loaded an uninitialized NVR, + mark everything as bad. */ + + /* Initialize the internal and chip times. */ + if (time_sync & TIME_SYNC_ENABLED) { + /* Use the internal clock's time. */ + nvr_time_get(&tm); + time_set(nvr, &tm); + } else { + /* Set the internal clock from the chip time. */ + time_get(nvr, &tm); + nvr_time_set(&tm); + } + + /* Start the RTC. */ + nvr->regs[RTC_REGA] = (REGA_RS2 | REGA_RS1); + nvr->regs[RTC_REGB] = REGB_2412; +} + +static void +nvr_at_speed_changed(void *priv) +{ + nvr_t *nvr = (nvr_t *) priv; + local_t *local = (local_t *) nvr->data; + + timer_load_count(nvr); + + timer_disable(&local->update_timer); + if (local->ecount > 0ULL) + timer_set_delay_u64(&local->update_timer, local->ecount); + + timer_disable(&nvr->onesec_time); + timer_set_delay_u64(&nvr->onesec_time, (10000ULL * TIMER_USEC)); +} + +void +nvr_at_handler(int set, uint16_t base, nvr_t *nvr) +{ + io_handler(set, base, 2, + nvr_read, NULL, NULL, nvr_write, NULL, NULL, nvr); +} + +void +nvr_at_index_read_handler(int set, uint16_t base, nvr_t *nvr) +{ + io_handler(0, base, 1, + NULL, NULL, NULL, nvr_write, NULL, NULL, nvr); + nvr_at_handler(0, base, nvr); + + if (set) + nvr_at_handler(1, base, nvr); + else { + io_handler(1, base, 1, + NULL, NULL, NULL, nvr_write, NULL, NULL, nvr); + io_handler(1, base + 1, 1, + nvr_read, NULL, NULL, nvr_write, NULL, NULL, nvr); + } +} + +void +nvr_at_sec_handler(int set, uint16_t base, nvr_t *nvr) +{ + io_handler(set, base, 2, + nvr_sec_read, NULL, NULL, nvr_sec_write, NULL, NULL, nvr); +} + +void +nvr_read_addr_set(int set, nvr_t *nvr) +{ + local_t *local = (local_t *) nvr->data; + + local->read_addr = set; +} + +void +nvr_wp_set(int set, int h, nvr_t *nvr) +{ + local_t *local = (local_t *) nvr->data; + + local->wp[h] = set; +} + +void +nvr_via_wp_set(int set, int reg, nvr_t *nvr) +{ + local_t *local = (local_t *) nvr->data; + + if (reg == 0x0d) + local->wp_0d = set; + else + local->wp_32 = set; +} + +void +nvr_bank_set(int base, uint8_t bank, nvr_t *nvr) +{ + local_t *local = (local_t *) nvr->data; + + local->bank[base] = bank; +} + +void +nvr_lock_set(int base, int size, int lock, nvr_t *nvr) +{ + local_t *local = (local_t *) nvr->data; + + for (int i = 0; i < size; i++) + local->lock[base + i] = lock; +} + +void +nvr_irq_set(int irq, nvr_t *nvr) +{ + nvr->irq = irq; +} + +void +nvr_smi_enable(int enable, nvr_t *nvr) +{ + local_t *local = (local_t *) nvr->data; + + local->smi_enable = enable; + + if (!enable) + local->smi_status = 0; +} + +uint8_t +nvr_smi_status(nvr_t *nvr) +{ + const local_t *local = (local_t *) nvr->data; + + return local->smi_status; +} + +void +nvr_smi_status_clear(nvr_t *nvr) +{ + local_t *local = (local_t *) nvr->data; + + local->smi_status = 0; +} + +static void +nvr_at_reset(void *priv) +{ + nvr_t *nvr = (nvr_t *) priv; + + /* These bits are reset on reset. */ + nvr->regs[RTC_REGB] &= ~(REGB_PIE | REGB_AIE | REGB_UIE | REGB_SQWE); + nvr->regs[RTC_REGC] &= ~(REGC_PF | REGC_AF | REGC_UF | REGC_IRQF); +} + +static void * +nvr_at_init(const device_t *info) +{ + local_t *local; + nvr_t *nvr; + + /* Allocate an NVR for this machine. */ + nvr = (nvr_t *) malloc(sizeof(nvr_t)); + if (nvr == NULL) + return (NULL); + memset(nvr, 0x00, sizeof(nvr_t)); + + local = (local_t *) malloc(sizeof(local_t)); + memset(local, 0x00, sizeof(local_t)); + nvr->data = local; + + /* This is machine specific. */ + nvr->size = machines[machine].nvrmask + 1; + local->lock = (uint8_t *) malloc(nvr->size); + memset(local->lock, 0x00, nvr->size); + local->def = 0xff /*0x00*/; + local->flags = 0x00; + switch (info->local & 0x0f) { + case 0: /* standard AT, no century register */ + if (info->local == 32) { + local->flags |= FLAG_P6RP4_HACK; + nvr->irq = 8; + local->cent = RTC_CENTURY_AT; + } else { + nvr->irq = 8; + local->cent = 0xff; + } + break; + + case 1: /* standard AT */ + case 5: /* AMI WinBIOS 1994 */ + case 6: /* AMI BIOS 1995 */ + if ((info->local & 0x1f) == 0x11) + local->flags |= FLAG_PIIX4; + else { + local->def = 0x00; + if ((info->local & 0x1f) == 0x15) + local->flags |= FLAG_AMI_1994_HACK; + else if ((info->local & 0x1f) == 0x16) + local->flags |= FLAG_AMI_1995_HACK; + else + local->def = 0xff; + } + nvr->irq = 8; + local->cent = RTC_CENTURY_AT; + break; + + case 2: /* PS/1 or PS/2 */ + nvr->irq = 8; + local->cent = RTC_CENTURY_PS; + local->def = 0x00; + if (info->local & 0x10) + local->flags |= FLAG_NO_NMI; + break; + + case 3: /* Amstrad PC's */ + nvr->irq = 1; + local->cent = RTC_CENTURY_AT; + local->def = 0xff; + if (info->local & 0x10) + local->flags |= FLAG_NO_NMI; + break; + + case 4: /* IBM AT */ + if (info->local & 0x10) { + local->def = 0x00; + local->flags |= FLAG_AMI_1992_HACK; + } else if (info->local == 36) + local->def = 0x00; + else + local->def = 0xff; + nvr->irq = 8; + local->cent = RTC_CENTURY_AT; + break; + + case 7: /* VIA VT82C586B */ + nvr->irq = 8; + local->cent = RTC_CENTURY_VIA; + break; + case 8: /* Epson Equity LT */ + nvr->irq = -1; + local->cent = RTC_CENTURY_ELT; + break; + + default: + break; + } + + if (info->local & 0x20) + local->def = 0x00; + + if (info->local & 0x40) + local->flags |= FLAG_MULTI_BANK; + + local->read_addr = 1; + + /* Set up any local handlers here. */ + nvr->reset = nvr_reset; + nvr->start = nvr_start; + nvr->tick = timer_tick; + + /* Initialize the generic NVR. */ + nvr_init(nvr); + + if (nvr_at_inited == 0) { + /* Start the timers. */ + timer_add(&local->update_timer, timer_update, nvr, 0); + + timer_add(&local->rtc_timer, timer_intr, nvr, 0); + /* On power on, if the oscillator is disabled, it's reenabled. */ + if ((nvr->regs[RTC_REGA] & 0x70) == 0x00) + nvr->regs[RTC_REGA] = (nvr->regs[RTC_REGA] & 0x8f) | 0x20; + nvr_at_reset(nvr); + timer_load_count(nvr); + + /* Set up the I/O handler for this device. */ + if (info->local == 8) { + io_sethandler(0x11b4, 2, + nvr_read, NULL, NULL, nvr_write, NULL, NULL, nvr); + } else { + io_sethandler(0x0070, 2, + nvr_read, NULL, NULL, nvr_write, NULL, NULL, nvr); + } + if (((info->local & 0x1f) == 0x11) || ((info->local & 0x1f) == 0x17)) { + io_sethandler(0x0072, 2, + nvr_read, NULL, NULL, nvr_write, NULL, NULL, nvr); + } + + nvr_at_inited = 1; + } + + return nvr; +} + +static void +nvr_at_close(void *priv) +{ + nvr_t *nvr = (nvr_t *) priv; + local_t *local = (local_t *) nvr->data; + + nvr_close(); + + timer_disable(&local->rtc_timer); + timer_disable(&local->update_timer); + timer_disable(&nvr->onesec_time); + + if (nvr != NULL) { + if (nvr->fn != NULL) + free(nvr->fn); + + if (nvr->data != NULL) + free(nvr->data); + + free(nvr); + } + + if (nvr_at_inited == 1) + nvr_at_inited = 0; +} + +const device_t at_nvr_old_device = { + .name = "PC/AT NVRAM (No century)", + .internal_name = "at_nvr_old", + .flags = DEVICE_ISA | DEVICE_AT, + .local = 0, + .init = nvr_at_init, + .close = nvr_at_close, + .reset = nvr_at_reset, + { .available = NULL }, + .speed_changed = nvr_at_speed_changed, + .force_redraw = NULL, + .config = NULL +}; + +const device_t at_nvr_device = { + .name = "PC/AT NVRAM", + .internal_name = "at_nvr", + .flags = DEVICE_ISA | DEVICE_AT, + .local = 1, + .init = nvr_at_init, + .close = nvr_at_close, + .reset = nvr_at_reset, + { .available = NULL }, + .speed_changed = nvr_at_speed_changed, + .force_redraw = NULL, + .config = NULL +}; + +const device_t at_mb_nvr_device = { + .name = "PC/AT NVRAM", + .internal_name = "at_nvr", + .flags = DEVICE_ISA | DEVICE_AT, + .local = 0x40 | 0x20 | 1, + .init = nvr_at_init, + .close = nvr_at_close, + .reset = nvr_at_reset, + { .available = NULL }, + .speed_changed = nvr_at_speed_changed, + .force_redraw = NULL, + .config = NULL +}; + +const device_t ps_nvr_device = { + .name = "PS/1 or PS/2 NVRAM", + .internal_name = "ps_nvr", + .flags = DEVICE_PS2, + .local = 2, + .init = nvr_at_init, + .close = nvr_at_close, + .reset = nvr_at_reset, + { .available = NULL }, + .speed_changed = nvr_at_speed_changed, + .force_redraw = NULL, + .config = NULL +}; + +const device_t amstrad_nvr_device = { + .name = "Amstrad NVRAM", + .internal_name = "amstrad_nvr", + .flags = DEVICE_ISA | DEVICE_AT, + .local = 3, + .init = nvr_at_init, + .close = nvr_at_close, + .reset = nvr_at_reset, + { .available = NULL }, + .speed_changed = nvr_at_speed_changed, + .force_redraw = NULL, + .config = NULL +}; + +const device_t ibmat_nvr_device = { + .name = "IBM AT NVRAM", + .internal_name = "ibmat_nvr", + .flags = DEVICE_ISA | DEVICE_AT, + .local = 4, + .init = nvr_at_init, + .close = nvr_at_close, + .reset = nvr_at_reset, + { .available = NULL }, + .speed_changed = nvr_at_speed_changed, + .force_redraw = NULL, + .config = NULL +}; + +const device_t piix4_nvr_device = { + .name = "Intel PIIX4 PC/AT NVRAM", + .internal_name = "piix4_nvr", + .flags = DEVICE_ISA | DEVICE_AT, + .local = 0x10 | 1, + .init = nvr_at_init, + .close = nvr_at_close, + .reset = nvr_at_reset, + { .available = NULL }, + .speed_changed = nvr_at_speed_changed, + .force_redraw = NULL, + .config = NULL +}; + +const device_t ps_no_nmi_nvr_device = { + .name = "PS/1 or PS/2 NVRAM (No NMI)", + .internal_name = "ps1_nvr", + .flags = DEVICE_PS2, + .local = 0x10 | 2, + .init = nvr_at_init, + .close = nvr_at_close, + .reset = nvr_at_reset, + { .available = NULL }, + .speed_changed = nvr_at_speed_changed, + .force_redraw = NULL, + .config = NULL +}; + +const device_t amstrad_no_nmi_nvr_device = { + .name = "Amstrad NVRAM (No NMI)", + .internal_name = "amstrad_nvr", + .flags = DEVICE_ISA | DEVICE_AT, + .local = 0x10 | 3, + .init = nvr_at_init, + .close = nvr_at_close, + .reset = nvr_at_reset, + { .available = NULL }, + .speed_changed = nvr_at_speed_changed, + .force_redraw = NULL, + .config = NULL +}; + +const device_t ami_1992_nvr_device = { + .name = "AMI Color 1992 PC/AT NVRAM", + .internal_name = "ami_1992_nvr", + .flags = DEVICE_ISA | DEVICE_AT, + .local = 0x10 | 4, + .init = nvr_at_init, + .close = nvr_at_close, + .reset = nvr_at_reset, + { .available = NULL }, + .speed_changed = nvr_at_speed_changed, + .force_redraw = NULL, + .config = NULL +}; + +const device_t ami_1994_nvr_device = { + .name = "AMI WinBIOS 1994 PC/AT NVRAM", + .internal_name = "ami_1994_nvr", + .flags = DEVICE_ISA | DEVICE_AT, + .local = 0x10 | 5, + .init = nvr_at_init, + .close = nvr_at_close, + .reset = nvr_at_reset, + { .available = NULL }, + .speed_changed = nvr_at_speed_changed, + .force_redraw = NULL, + .config = NULL +}; + +const device_t ami_1995_nvr_device = { + .name = "AMI WinBIOS 1995 PC/AT NVRAM", + .internal_name = "ami_1995_nvr", + .flags = DEVICE_ISA | DEVICE_AT, + .local = 0x10 | 6, + .init = nvr_at_init, + .close = nvr_at_close, + .reset = nvr_at_reset, + { .available = NULL }, + .speed_changed = nvr_at_speed_changed, + .force_redraw = NULL, + .config = NULL +}; + +const device_t via_nvr_device = { + .name = "VIA PC/AT NVRAM", + .internal_name = "via_nvr", + .flags = DEVICE_ISA | DEVICE_AT, + .local = 0x10 | 7, + .init = nvr_at_init, + .close = nvr_at_close, + .reset = nvr_at_reset, + { .available = NULL }, + .speed_changed = nvr_at_speed_changed, + .force_redraw = NULL, + .config = NULL +}; + +const device_t p6rp4_nvr_device = { + .name = "ASUS P/I-P6RP4 PC/AT NVRAM", + .internal_name = "p6rp4_nvr", + .flags = DEVICE_ISA | DEVICE_AT, + .local = 32, + .init = nvr_at_init, + .close = nvr_at_close, + .reset = nvr_at_reset, + { .available = NULL }, + .speed_changed = nvr_at_speed_changed, + .force_redraw = NULL, + .config = NULL +}; + +const device_t amstrad_megapc_nvr_device = { + .name = "Amstrad MegaPC NVRAM", + .internal_name = "amstrad_megapc_nvr", + .flags = DEVICE_ISA | DEVICE_AT, + .local = 36, + .init = nvr_at_init, + .close = nvr_at_close, + .reset = nvr_at_reset, + { .available = NULL }, + .speed_changed = nvr_at_speed_changed, + .force_redraw = NULL, + .config = NULL +}; + +const device_t elt_nvr_device = { + .name = "Epson Equity LT NVRAM", + .internal_name = "elt_nvr", + .flags = DEVICE_ISA, + .local = 8, + .init = nvr_at_init, + .close = nvr_at_close, + .reset = nvr_at_reset, + { .available = NULL }, + .speed_changed = nvr_at_speed_changed, + .force_redraw = NULL, + .config = NULL +}; diff --git a/src/nvr_ps2.c b/src/nvr_ps2.c index 5e38d5a57..67eaccc38 100644 --- a/src/nvr_ps2.c +++ b/src/nvr_ps2.c @@ -1,20 +1,20 @@ /* - * VARCem Virtual ARchaeological Computer EMulator. - * An emulator of (mostly) x86-based PC systems and devices, - * using the ISA,EISA,VLB,MCA and PCI system buses, roughly - * spanning the era between 1981 and 1995. + * 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 VARCem Project. + * This file is part of the 86Box distribution. * - * Handling of the PS/2 series CMOS devices. + * Handling of the PS/2 series CMOS devices. * * * - * Authors: Fred N. van Kempen, - * Sarah Walker, + * Authors: Fred N. van Kempen, + * Sarah Walker, * - * Copyright 2017,2018 Fred N. van Kempen. - * Copyright 2008-2018 Sarah Walker. + * Copyright 2017-2018 Fred N. van Kempen. + * Copyright 2008-2018 Sarah Walker. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -49,114 +49,143 @@ #include <86box/nvr_ps2.h> #include <86box/rom.h> +typedef struct ps2_nvr_t { + int addr; -typedef struct { - int addr; + uint8_t *ram; + int size; - uint8_t ram[8192]; - - char *fn; + char *fn; } ps2_nvr_t; - static uint8_t ps2_nvr_read(uint16_t port, void *priv) { - ps2_nvr_t *nvr = (ps2_nvr_t *)priv; - uint8_t ret = 0xff; + const ps2_nvr_t *nvr = (ps2_nvr_t *) priv; + uint8_t ret = 0xff; switch (port) { - case 0x74: - ret = nvr->addr & 0xff; - break; + case 0x74: + ret = nvr->addr & 0xff; + break; - case 0x75: - ret = nvr->addr >> 8; - break; + case 0x75: + ret = nvr->addr >> 8; + break; - case 0x76: - ret = nvr->ram[nvr->addr]; - break; + case 0x76: + ret = nvr->ram[nvr->addr]; + break; + + default: + break; } - return(ret); + return ret; } - static void ps2_nvr_write(uint16_t port, uint8_t val, void *priv) { - ps2_nvr_t *nvr = (ps2_nvr_t *)priv; + ps2_nvr_t *nvr = (ps2_nvr_t *) priv; switch (port) { - case 0x74: - nvr->addr = (nvr->addr & 0x1f00) | val; - break; + case 0x74: + nvr->addr = (nvr->addr & 0x1f00) | val; + break; - case 0x75: - nvr->addr = (nvr->addr & 0xff) | ((val & 0x1f) << 8); - break; + case 0x75: + nvr->addr = (nvr->addr & 0xff) | ((val & 0x1f) << 8); + break; - case 0x76: - nvr->ram[nvr->addr] = val; - break; + case 0x76: + nvr->ram[nvr->addr] = val; + break; + + default: + break; } } - static void * ps2_nvr_init(const device_t *info) { ps2_nvr_t *nvr; - FILE *f = NULL; - int c; + FILE *fp = NULL; + int c; - nvr = (ps2_nvr_t *)malloc(sizeof(ps2_nvr_t)); + nvr = (ps2_nvr_t *) malloc(sizeof(ps2_nvr_t)); memset(nvr, 0x00, sizeof(ps2_nvr_t)); + if (info->local) + nvr->size = 2048; + else + nvr->size = 8192; + /* Set up the NVR file's name. */ - c = strlen(machine_get_internal_name()) + 9; - nvr->fn = (char *)malloc(c + 1); + c = strlen(machine_get_internal_name()) + 9; + nvr->fn = (char *) malloc(c + 1); sprintf(nvr->fn, "%s_sec.nvr", machine_get_internal_name()); io_sethandler(0x0074, 3, - ps2_nvr_read,NULL,NULL, ps2_nvr_write,NULL,NULL, nvr); + ps2_nvr_read, NULL, NULL, ps2_nvr_write, NULL, NULL, nvr); - f = nvr_fopen(nvr->fn, "rb"); + fp = nvr_fopen(nvr->fn, "rb"); - memset(nvr->ram, 0xff, 8192); - if (f != NULL) { - if (fread(nvr->ram, 1, 8192, f) != 8192) - fatal("ps2_nvr_init(): Error reading EEPROM data\n"); - fclose(f); + nvr->ram = (uint8_t *) malloc(nvr->size); + memset(nvr->ram, 0xff, nvr->size); + if (fp != NULL) { + if (fread(nvr->ram, 1, nvr->size, fp) != nvr->size) + fatal("ps2_nvr_init(): Error reading EEPROM data\n"); + fclose(fp); } - return(nvr); + return nvr; } - static void ps2_nvr_close(void *priv) { - ps2_nvr_t *nvr = (ps2_nvr_t *)priv; - FILE *f = NULL; + ps2_nvr_t *nvr = (ps2_nvr_t *) priv; + FILE *fp = NULL; - f = nvr_fopen(nvr->fn, "wb"); + fp = nvr_fopen(nvr->fn, "wb"); - if (f != NULL) { - (void)fwrite(nvr->ram, 8192, 1, f); - fclose(f); + if (fp != NULL) { + (void) fwrite(nvr->ram, nvr->size, 1, fp); + fclose(fp); } + if (nvr->ram != NULL) + free(nvr->ram); + free(nvr); } - const device_t ps2_nvr_device = { - "PS/2 Secondary NVRAM", - "ps2_nvr", - 0, 0, - ps2_nvr_init, ps2_nvr_close, NULL, - { NULL }, NULL, - NULL + .name = "PS/2 Secondary NVRAM for PS/2 Models 70-80", + .internal_name = "ps2_nvr", + .flags = 0, + .local = 0, + .init = ps2_nvr_init, + .close = ps2_nvr_close, + .reset = NULL, + { .available = NULL }, + .speed_changed = NULL, + .force_redraw = NULL, + .config = NULL +}; + +const device_t ps2_nvr_55ls_device = { + .name = "PS/2 Secondary NVRAM for PS/2 Models 55LS-65SX", + .internal_name = "ps2_nvr_55ls", + .flags = 0, + .local = 1, + .init = ps2_nvr_init, + .close = ps2_nvr_close, + .reset = NULL, + { .available = NULL }, + .speed_changed = NULL, + .force_redraw = NULL, + .config = NULL }; diff --git a/src/pci.c b/src/pci.c index b66882bde..7c61545b2 100644 --- a/src/pci.c +++ b/src/pci.c @@ -1,22 +1,18 @@ /* - * 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. + * 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. + * This file is part of the 86Box distribution. * - * Implementation the PCI bus. + * Implementation the PCI bus. * * * - * Authors: Miran Grca, - * Fred N. van Kempen, - * Sarah Walker, + * Authors: Miran Grca, * - * Copyright 2016-2020 Miran Grca. - * Copyright 2017-2020 Fred N. van Kempen. - * Copyright 2008-2020 Sarah Walker. + * Copyright 2023 Miran Grca. */ #include #include @@ -34,726 +30,328 @@ #include <86box/dma.h> #include <86box/pci.h> #include <86box/keyboard.h> +#include <86box/plat_unused.h> +#define PCI_ENABLED 0x80000000 -typedef struct { - uint8_t bus, id, type; - uint8_t irq_routing[4]; +typedef struct pci_card_t { + uint8_t bus; + uint8_t id; + uint8_t type; + uint8_t irq_routing[PCI_INT_PINS_NUM]; - void *priv; - void (*write)(int func, int addr, uint8_t val, void *priv); - uint8_t (*read)(int func, int addr, void *priv); + void * priv; + void (*write)(int func, int addr, uint8_t val, void *priv); + uint8_t (*read)(int func, int addr, void *priv); } pci_card_t; -typedef struct { - uint8_t enabled; - uint8_t irq_line; +typedef struct pci_card_desc_t { + uint8_t type; + void * priv; + void (*write)(int func, int addr, uint8_t val, void *priv); + uint8_t (*read)(int func, int addr, void *priv); + uint8_t *slot; +} pci_card_desc_t; + +typedef struct pci_mirq_t { + uint8_t enabled; + uint8_t irq_line; + uint8_t irq_level; + uint8_t pad; } pci_mirq_t; +int pci_burst_time; +int agp_burst_time; +int pci_nonburst_time; +int agp_nonburst_time; -int pci_burst_time, agp_burst_time, - pci_nonburst_time, agp_nonburst_time; +int pci_flags; -static pci_card_t pci_cards[32]; -static uint8_t pci_pmc = 0, last_pci_card = 0, last_normal_pci_card = 0, last_pci_bus = 1; -static uint8_t pci_card_to_slot_mapping[256][32], pci_bus_number_to_index_mapping[256]; -static uint8_t pci_irqs[16], pci_irq_level[16]; -static uint64_t pci_irq_hold[16]; -static pci_mirq_t pci_mirqs[8]; -static int pci_type, - pci_switch, - pci_index, - pci_func, - pci_card, - pci_bus, - pci_enable, - pci_key; -static int trc_reg = 0; +uint32_t pci_base = 0xc000; +uint32_t pci_size = 0x1000; +static pci_card_t pci_cards[PCI_CARDS_NUM]; +static pci_card_desc_t pci_card_descs[PCI_CARDS_NUM]; +static uint8_t pci_pmc = 0; +static uint8_t last_pci_card = 0; +static uint8_t last_normal_pci_card = 0; +static uint8_t last_normal_pci_card_id = 0; +static uint8_t last_pci_bus = 1; +static uint8_t next_pci_card = 0; +static uint8_t normal_pci_cards = 0; +static uint8_t next_normal_pci_card = 0; +static uint8_t pci_card_to_slot_mapping[256][PCI_CARDS_NUM]; +static uint8_t pci_bus_number_to_index_mapping[256]; +static uint8_t pci_irqs[PCI_IRQS_NUM]; +static uint8_t pci_irq_level[PCI_IRQS_NUM]; +static uint64_t pci_irq_hold[PCI_IRQS_NUM]; +static pci_mirq_t pci_mirqs[PCI_MIRQS_NUM]; +static int pci_index; +static int pci_func; +static int pci_card; +static int pci_bus; +static int pci_key; +static int pci_trc_reg = 0; +static uint32 pci_enable = 0x00000000; -static void pci_reset_regs(void); - +static void pci_reset_regs(void); #ifdef ENABLE_PCI_LOG int pci_do_log = ENABLE_PCI_LOG; - static void pci_log(const char *fmt, ...) { va_list ap; if (pci_do_log) { - va_start(ap, fmt); - pclog_ex(fmt, ap); - va_end(ap); + va_start(ap, fmt); + pclog_ex(fmt, ap); + va_end(ap); } } #else -#define pci_log(fmt, ...) +# define pci_log(fmt, ...) #endif - -static void -pci_cf8_write(uint16_t port, uint32_t val, void *priv) -{ - pci_log("cf8 write: %08X\n", val); - pci_index = val & 0xff; - pci_func = (val >> 8) & 7; - pci_card = (val >> 11) & 31; - pci_bus = (val >> 16) & 0xff; - pci_enable = (val >> 31) & 1; -} - - -static uint32_t -pci_cf8_read(uint16_t port, void *priv) -{ - return pci_index | (pci_func << 8) | - (pci_card << 11) | (pci_bus << 16) | (pci_enable << 31); -} - - -static void -pci_write(uint16_t port, uint8_t val, void *priv) -{ - uint8_t slot = 0; - - if (in_smm) - pci_log("(%i) %03x write: %02X\n", pci_enable, port, val); - - switch (port) { - case 0xcfc: case 0xcfd: case 0xcfe: case 0xcff: - if (! pci_enable) - return; - - pci_log("Writing %02X to PCI card on bus %i, slot %02X (pci_cards[%i]) (%02X:%02X)...\n", val, pci_bus, pci_card, slot, pci_func, pci_index | (port & 3)); - slot = pci_card_to_slot_mapping[pci_bus_number_to_index_mapping[pci_bus]][pci_card]; - if (slot != 0xff) { - if (pci_cards[slot].write) { - pci_log("Writing to PCI card on slot %02X (pci_cards[%i]) (%02X:%02X)...\n", pci_card, slot, pci_func, pci_index | (port & 3)); - pci_cards[slot].write(pci_func, pci_index | (port & 3), val, pci_cards[slot].priv); - } -#ifdef ENABLE_PCI_LOG - else - pci_log("Writing to empty PCI card on slot %02X (pci_cards[%i]) (%02X:%02X)...\n", pci_card, slot, pci_func, pci_index | (port & 3)); -#endif - } -#ifdef ENABLE_PCI_LOG - else - pci_log("Writing to unassigned PCI card on slot %02X (pci_cards[%i]) (%02X:%02X)...\n", pci_card, slot, pci_func, pci_index | (port & 3)); -#endif - - break; - } -} - - -static void -pci_writew(uint16_t port, uint16_t val, void *priv) -{ - uint8_t slot = 0; - - if (in_smm) - pci_log("(%i) %03x write: %02X\n", pci_enable, port, val); - - switch (port) { - case 0xcfc: case 0xcfd: case 0xcfe: case 0xcff: - if (! pci_enable) - return; - - pci_log("Writing %04X to PCI card on bus %i, slot %02X (pci_cards[%i]) (%02X:%02X)...\n", val, pci_bus, pci_card, slot, pci_func, pci_index | (port & 3)); - slot = pci_card_to_slot_mapping[pci_bus_number_to_index_mapping[pci_bus]][pci_card]; - if (slot != 0xff) { - if (pci_cards[slot].write) { - pci_log("Writing to PCI card on slot %02X (pci_cards[%i]) (%02X:%02X)...\n", pci_card, slot, pci_func, pci_index | (port & 3)); - pci_cards[slot].write(pci_func, pci_index | (port & 3), val & 0xff, pci_cards[slot].priv); - pci_cards[slot].write(pci_func, pci_index | ((port & 3) + 1), val >> 8, pci_cards[slot].priv); - } -#ifdef ENABLE_PCI_LOG - else - pci_log("Writing to empty PCI card on slot %02X (pci_cards[%i]) (%02X:%02X)...\n", pci_card, slot, pci_func, pci_index | (port & 3)); -#endif - } -#ifdef ENABLE_PCI_LOG - else - pci_log("Writing to unassigned PCI card on slot %02X (pci_cards[%i]) (%02X:%02X)...\n", pci_card, slot, pci_func, pci_index | (port & 3)); -#endif - - break; - } -} - - -static void -pci_writel(uint16_t port, uint32_t val, void *priv) -{ - uint8_t slot = 0; - - if (in_smm) - pci_log("(%i) %03x write: %02X\n", pci_enable, port, val); - - switch (port) { - case 0xcfc: case 0xcfd: case 0xcfe: case 0xcff: - if (! pci_enable) - return; - - pci_log("Writing %08X to PCI card on bus %i, slot %02X (pci_cards[%i]) (%02X:%02X)...\n", val, pci_bus, pci_card, slot, pci_func, pci_index | (port & 3)); - slot = pci_card_to_slot_mapping[pci_bus_number_to_index_mapping[pci_bus]][pci_card]; - if (slot != 0xff) { - if (pci_cards[slot].write) { - pci_log("Writing to PCI card on slot %02X (pci_cards[%i]) (%02X:%02X)...\n", pci_card, slot, pci_func, pci_index | (port & 3)); - pci_cards[slot].write(pci_func, pci_index | (port & 3), val & 0xff, pci_cards[slot].priv); - pci_cards[slot].write(pci_func, pci_index | ((port & 3) + 1), (val >> 8) & 0xff, pci_cards[slot].priv); - pci_cards[slot].write(pci_func, pci_index | ((port & 3) + 2), (val >> 16) & 0xff, pci_cards[slot].priv); - pci_cards[slot].write(pci_func, pci_index | ((port & 3) + 3), (val >> 24) & 0xff, pci_cards[slot].priv); - } -#ifdef ENABLE_PCI_LOG - else - pci_log("Writing to empty PCI card on slot %02X (pci_cards[%i]) (%02X:%02X)...\n", pci_card, slot, pci_func, pci_index | (port & 3)); -#endif - } -#ifdef ENABLE_PCI_LOG - else - pci_log("Writing to unassigned PCI card on slot %02X (pci_cards[%i]) (%02X:%02X)...\n", pci_card, slot, pci_func, pci_index | (port & 3)); -#endif - - break; - } -} - - -static uint8_t -pci_read(uint16_t port, void *priv) -{ - uint8_t slot = 0; - uint8_t ret = 0xff; - - if (in_smm) - pci_log("(%i) %03x read\n", pci_enable, port); - - switch (port) { - case 0xcfc: case 0xcfd: case 0xcfe: case 0xcff: - if (! pci_enable) - return 0xff; - - slot = pci_card_to_slot_mapping[pci_bus_number_to_index_mapping[pci_bus]][pci_card]; - if (slot != 0xff) { - if (pci_cards[slot].read) - ret = pci_cards[slot].read(pci_func, pci_index | (port & 3), pci_cards[slot].priv); -#ifdef ENABLE_PCI_LOG - else - pci_log("Reading from empty PCI card on slot %02X (pci_cards[%i]) (%02X:%02X)...\n", pci_card, slot, pci_func, pci_index | (port & 3)); -#endif - } -#ifdef ENABLE_PCI_LOG - else - pci_log("Reading from unasisgned PCI card on slot %02X (pci_cards[%i]) (%02X:%02X)...\n", pci_card, slot, pci_func, pci_index | (port & 3)); -#endif - } - - pci_log("Reading %02X, from PCI card on bus %i, slot %02X (pci_cards[%i]) (%02X:%02X)...\n", ret, pci_bus, pci_card, slot, pci_func, pci_index | (port & 3)); - - return ret; -} - - -static uint16_t -pci_readw(uint16_t port, void *priv) -{ - uint8_t slot = 0; - uint16_t ret = 0xffff; - - if (in_smm) - pci_log("(%i) %03x read\n", pci_enable, port); - - switch (port) { - case 0xcfc: case 0xcfd: case 0xcfe: case 0xcff: - if (! pci_enable) - return 0xff; - - slot = pci_card_to_slot_mapping[pci_bus_number_to_index_mapping[pci_bus]][pci_card]; - if (slot != 0xff) { - if (pci_cards[slot].read) { - ret = pci_cards[slot].read(pci_func, pci_index | (port & 3), pci_cards[slot].priv); - ret |= (pci_cards[slot].read(pci_func, (pci_index | (port & 3)) + 1, pci_cards[slot].priv) << 8); - } -#ifdef ENABLE_PCI_LOG - else - pci_log("Reading from empty PCI card on slot %02X (pci_cards[%i]) (%02X:%02X)...\n", pci_card, slot, pci_func, pci_index | (port & 3)); -#endif - } -#ifdef ENABLE_PCI_LOG - else - pci_log("Reading from unasisgned PCI card on slot %02X (pci_cards[%i]) (%02X:%02X)...\n", pci_card, slot, pci_func, pci_index | (port & 3)); -#endif - } - - pci_log("Reading %04X, from PCI card on bus %i, slot %02X (pci_cards[%i]) (%02X:%02X)...\n", ret, pci_bus, pci_card, slot, pci_func, pci_index | (port & 3)); - - return ret; -} - - -static uint32_t -pci_readl(uint16_t port, void *priv) -{ - uint8_t slot = 0; - uint32_t ret = 0xffffffff; - - if (in_smm) - pci_log("(%i) %03x read\n", pci_enable, port); - - switch (port) { - case 0xcfc: case 0xcfd: case 0xcfe: case 0xcff: - if (! pci_enable) - return 0xff; - - slot = pci_card_to_slot_mapping[pci_bus_number_to_index_mapping[pci_bus]][pci_card]; - if (slot != 0xff) { - if (pci_cards[slot].read) { - ret = pci_cards[slot].read(pci_func, pci_index | (port & 3), pci_cards[slot].priv); - ret |= (pci_cards[slot].read(pci_func, (pci_index | (port & 3)) + 1, pci_cards[slot].priv) << 8); - ret |= (pci_cards[slot].read(pci_func, (pci_index | (port & 3)) + 2, pci_cards[slot].priv) << 16); - ret |= (pci_cards[slot].read(pci_func, (pci_index | (port & 3)) + 3, pci_cards[slot].priv) << 24); - } -#ifdef ENABLE_PCI_LOG - else - pci_log("Reading from empty PCI card on slot %02X (pci_cards[%i]) (%02X:%02X)...\n", pci_card, slot, pci_func, pci_index | (port & 3)); -#endif - } -#ifdef ENABLE_PCI_LOG - else - pci_log("Reading from unasisgned PCI card on slot %02X (pci_cards[%i]) (%02X:%02X)...\n", pci_card, slot, pci_func, pci_index | (port & 3)); -#endif - } - - pci_log("Reading %08X, from PCI card on bus %i, slot %02X (pci_cards[%i]) (%02X:%02X)...\n", ret, pci_bus, pci_card, slot, pci_func, pci_index | (port & 3)); - - return ret; -} - - -static void pci_type2_write(uint16_t port, uint8_t val, void *priv); -static uint8_t pci_type2_read(uint16_t port, void *priv); - - -void -pci_set_pmc(uint8_t pmc) -{ - pci_reset_regs(); - - if (!pci_pmc && (pmc & 0x01)) { - io_removehandler(0x0cf8, 1, - pci_type2_read,NULL,NULL, pci_type2_write,NULL,NULL, NULL); - io_removehandler(0x0cfa, 1, - pci_type2_read,NULL,NULL, pci_type2_write,NULL,NULL, NULL); - io_sethandler(0x0cf8, 1, - NULL,NULL,pci_cf8_read, NULL,NULL,pci_cf8_write, NULL); - io_sethandler(0x0cfc, 4, - pci_read,NULL,NULL, pci_write,NULL,NULL, NULL); - } else if (pci_pmc && !(pmc & 0x01)) { - io_removehandler(0x0cf8, 1, - NULL,NULL,pci_cf8_read, NULL,NULL,pci_cf8_write, NULL); - io_removehandler(0x0cfc, 4, - pci_read,NULL,NULL, pci_write,NULL,NULL, NULL); - io_sethandler(0x0cf8, 1, - pci_type2_read,NULL,NULL, pci_type2_write,NULL,NULL, NULL); - io_sethandler(0x0cfa, 1, - pci_type2_read,NULL,NULL, pci_type2_write,NULL,NULL, NULL); - } - - pci_pmc = (pmc & 0x01); -} - - -static void -pci_type2_write(uint16_t port, uint8_t val, void *priv) -{ - uint8_t slot = 0; - - if (port == 0xcf8) { - pci_func = (val >> 1) & 7; - - if (!pci_key && (val & 0xf0)) - io_sethandler(0xc000, 0x1000, - pci_type2_read, NULL, NULL, - pci_type2_write, NULL, NULL, NULL); - else if (pci_key && !(val & 0xf0)) - io_removehandler(0xc000, 0x1000, - pci_type2_read, NULL, NULL, - pci_type2_write, NULL, NULL, NULL); - - pci_key = val & 0xf0; - } else if (port == 0xcfa) - pci_bus = val; - else if (port == 0xcfb) { - pci_log("Write %02X to port 0CFB\n", val); - pci_set_pmc(val); - } else { - pci_card = (port >> 8) & 0xf; - pci_index = port & 0xff; - - slot = pci_card_to_slot_mapping[pci_bus_number_to_index_mapping[pci_bus]][pci_card]; - if (slot != 0xff) { - if (pci_cards[slot].write) - pci_cards[slot].write(pci_func, pci_index | (port & 3), val, pci_cards[slot].priv); -#ifdef ENABLE_PCI_LOG - else - pci_log("Writing to empty PCI card on slot %02X (pci_cards[%i]) (%02X:%02X)...\n", pci_card, slot, pci_func, pci_index); -#endif - } -#ifdef ENABLE_PCI_LOG - else - pci_log("Writing to unassigned PCI card on slot %02X (pci_cards[%i]) (%02X:%02X)...\n", pci_card, slot, pci_func, pci_index); -#endif - } -} - - -static void -pci_type2_writel(uint16_t port, uint32_t val, void *priv) -{ - int i; - - for (i = 0; i < 4; i++) { - /* Make sure to have the DWORD write not pass through to PMC if mechanism 1 is in use, - as otherwise, the PCI enable bits clobber it. */ - if (!pci_pmc || ((port + i) != 0x0cfb)) - pci_type2_write(port + i, val >> 8, priv); - } -} - - -static uint8_t -pci_type2_read(uint16_t port, void *priv) -{ - uint8_t slot = 0; - - if (port == 0xcf8) - return pci_key | (pci_func << 1); - else if (port == 0xcfa) - return pci_bus; - else if (port == 0xcfb) - return pci_pmc; - - pci_card = (port >> 8) & 0xf; - pci_index = port & 0xff; - - slot = pci_card_to_slot_mapping[pci_bus_number_to_index_mapping[pci_bus]][pci_card]; - if (slot != 0xff) { - if (pci_cards[slot].read) - return pci_cards[slot].read(pci_func, pci_index | (port & 3), pci_cards[slot].priv); -#ifdef ENABLE_PCI_LOG - else - pci_log("Reading from empty PCI card on slot %02X (pci_cards[%i]) (%02X:%02X)...\n", pci_card, slot, pci_func, pci_index); -#endif - } -#ifdef ENABLE_PCI_LOG - else - pci_log("Reading from unasisgned PCI card on slot %02X (pci_cards[%i]) (%02X:%02X)...\n", pci_card, slot, pci_func, pci_index); -#endif - - return 0xff; -} - - void pci_set_irq_routing(int pci_int, int irq) { pci_irqs[pci_int - 1] = irq; } - void pci_set_irq_level(int pci_int, int level) { pci_irq_level[pci_int - 1] = !!level; } - void pci_enable_mirq(int mirq) { pci_mirqs[mirq].enabled = 1; } - void -pci_set_mirq_routing(int mirq, int irq) +pci_set_mirq_routing(int mirq, uint8_t irq) { pci_mirqs[mirq].irq_line = irq; } - -void -pci_set_mirq(uint8_t mirq, int level) +uint8_t +pci_get_mirq_level(int mirq) { - uint8_t irq_line = 0; - uint8_t irq_bit; - - if (mirq >= 0xf0) { - irq_line = mirq & 0x0f; - irq_bit = 0x1D; - } else { - if (! pci_mirqs[mirq].enabled) { - pci_log("pci_set_mirq(%02X): MIRQ0 disabled\n", mirq); - return; - } - - if (pci_mirqs[mirq].irq_line > 0x0f) { - pci_log("pci_set_mirq(%02X): IRQ line is disabled\n", mirq); - return; - } - - irq_line = pci_mirqs[mirq].irq_line; - irq_bit = (0x1E + mirq); - } - pci_log("pci_set_mirq(%02X): Using IRQ %i\n", mirq, irq_line); - - if (level && (pci_irq_hold[irq_line] & (1ULL << irq_bit))) { - /* IRQ already held, do nothing. */ - pci_log("pci_set_mirq(%02X): MIRQ is already holding the IRQ\n", mirq); - picintlevel(1 << irq_line); - return; - } - pci_log("pci_set_mirq(%02X): MIRQ not yet holding the IRQ\n", mirq); - - if (!level || !pci_irq_hold[irq_line]) { - pci_log("pci_set_mirq(%02X): Issuing %s-triggered IRQ (%sheld)\n", mirq, level ? "level" : "edge", pci_irq_hold[irq_line] ? "" : "not "); - - /* Only raise the interrupt if it's edge-triggered or level-triggered and not yet being held. */ - if (level) - picintlevel(1 << irq_line); - else - picint(1 << irq_line); - } else if (level && pci_irq_hold[irq_line]) { - pci_log("pci_set_mirq(%02X): IRQ line already being held\n", mirq); - picintlevel(1 << irq_line); - } - - /* If the IRQ is level-triggered, mark that this MIRQ is holding it. */ - if (level) { - pci_log("pci_set_mirq(%02X): Marking that this card is holding the IRQ\n", mirq); - pci_irq_hold[irq_line] |= (1ULL << irq_bit); - } - - pci_log("pci_set_mirq(%02X): Edge-triggered interrupt, not marking\n", mirq); + return pci_mirqs[mirq].irq_level; } - void -pci_set_irq(uint8_t card, uint8_t pci_int) +pci_set_mirq_level(int mirq, uint8_t level) { - uint8_t slot = 0; - uint8_t irq_routing = 0; + pci_mirqs[mirq].irq_level = level; +} + +/* PCI raise IRQ: the first parameter is slot if < PCI_MIRQ_BASE, MIRQ if >= PCI_MIRQ_BASE + and < PCI_DIRQ_BASE, and direct IRQ line if >= PCI_DIRQ_BASE (RichardG's + hack that may no longer be needed). */ +void +pci_irq(uint8_t slot, uint8_t pci_int, int level, int set, uint8_t *irq_state) +{ + uint8_t irq_routing = 0; uint8_t pci_int_index = pci_int - PCI_INTA; - uint8_t irq_line = 0; - uint8_t level = 0; + uint8_t irq_line = 0; + uint8_t is_vfio = 0; - if (! last_pci_card) { - pci_log("pci_set_irq(%02X, %02X): No PCI slots (how are we even here?!)\n", card, pci_int); - return; - } - pci_log("pci_set_irq(%02X, %02X): %i PCI slots\n", card, pci_int, last_pci_card); + /* The fast path out an invalid PCI card. */ + if (slot == PCI_CARD_INVALID) + return; - slot = card; - if (slot == 0xff) { - pci_log("pci_set_irq(%02X, %02X): Card is not on a PCI slot (how are we even here?!)\n", card, pci_int); - return; - } - pci_log("pci_set_irq(%02X, %02X): Card is on PCI slot %02X\n", card, pci_int, slot); + switch (slot) { + default: + return; - if (! pci_cards[slot].irq_routing[pci_int_index]) { - pci_log("pci_set_irq(%02X, %02X): No IRQ routing for this slot and INT pin combination\n", card, pci_int); - return; + case 0x00 ... PCI_CARD_MAX: + /* PCI card. */ + if (!last_pci_card) + return; + + if (pci_flags & FLAG_NO_IRQ_STEERING) + irq_line = pci_cards[slot].read(0, 0x3c, pci_cards[slot].priv); + else { + irq_routing = pci_cards[slot].irq_routing[pci_int_index]; + + switch (irq_routing) { + default: + case 0x00: + return; + + case 0x01 ... PCI_IRQS_NUM: + is_vfio = pci_cards[slot].type & PCI_CARD_VFIO; + irq_routing = (irq_routing - PCI_INTA) & PCI_IRQ_MAX; + + irq_line = pci_irqs[irq_routing]; + /* Ignore what was provided to us as a parameter and override it with whatever + the chipset is set to. */ + level = !!pci_irq_level[irq_routing]; + if (level && is_vfio) + level--; + break; + + /* Sometimes, PCI devices are mapped to direct IRQ's. */ + case (PCI_DIRQ_BASE | 0x00) ... (PCI_DIRQ_BASE | PCI_DIRQ_MAX): + /* Direct IRQ line, always edge-triggered. */ + irq_line = slot & PCI_IRQ_MAX; + break; + } + } + break; + case (PCI_MIRQ_BASE | 0x00) ... (PCI_MIRQ_BASE | PCI_MIRQ_MAX): + /* MIRQ */ + slot &= PCI_MIRQ_MAX; + + if (!pci_mirqs[slot].enabled) + return; + + irq_line = pci_mirqs[slot].irq_line; + break; + case (PCI_DIRQ_BASE | 0x00) ... (PCI_DIRQ_BASE | PCI_DIRQ_MAX): + /* Direct IRQ line (RichardG's ACPI workaround, may no longer be needed). */ + irq_line = slot & PCI_IRQ_MAX; + break; } - if (pci_type & PCI_NO_IRQ_STEERING) - irq_line = pci_cards[slot].read(0, 0x3c, pci_cards[slot].priv); - else { - irq_routing = (pci_cards[slot].irq_routing[pci_int_index] - PCI_INTA) & 3; - pci_log("pci_set_irq(%02X, %02X): IRQ routing for this slot and INT pin combination: %02X\n", card, pci_int, irq_routing); + if (irq_line > PCI_IRQ_MAX) + return; - irq_line = pci_irqs[irq_routing]; - level = pci_irq_level[irq_routing]; - } - - if (irq_line > 0x0f) { - pci_log("pci_set_irq(%02X, %02X): IRQ line is disabled\n", card, pci_int); - return; - } else - pci_log("pci_set_irq(%02X, %02X): Using IRQ %i\n", card, pci_int, irq_line); - - if (level && (pci_irq_hold[irq_line] & (1ULL << slot))) { - /* IRQ already held, do nothing. */ - pci_log("pci_set_irq(%02X, %02X): Card is already holding the IRQ\n", card, pci_int); - picintlevel(1 << irq_line); - return; - } - pci_log("pci_set_irq(%02X, %02X): Card not yet holding the IRQ\n", card, pci_int); - - if (!level || !pci_irq_hold[irq_line]) { - pci_log("pci_set_irq(%02X, %02X): Issuing %s-triggered IRQ (%sheld)\n", card, pci_int, level ? "level" : "edge", pci_irq_hold[irq_line] ? "" : "not "); - - /* Only raise the interrupt if it's edge-triggered or level-triggered and not yet being held. */ - if (level) - picintlevel(1 << irq_line); - else - picint(1 << irq_line); - } else if (level && pci_irq_hold[irq_line]) { - pci_log("pci_set_irq(%02X, %02X): IRQ line already being held\n", card, pci_int); - picintlevel(1 << irq_line); - } - - /* If the IRQ is level-triggered, mark that this card is holding it. */ - if (level) { - pci_log("pci_set_irq(%02X, %02X): Marking that this card is holding the IRQ\n", card, pci_int); - pci_irq_hold[irq_line] |= (1ULL << slot); - } else { - pci_log("pci_set_irq(%02X, %02X): Edge-triggered interrupt, not marking\n", card, pci_int); - } + picint_common(1 << irq_line, level, set, irq_state); } - -void -pci_clear_mirq(uint8_t mirq, int level) -{ - uint8_t irq_line = 0; - uint8_t irq_bit; - - if (mirq >= 0xf0) { - irq_line = mirq & 0x0f; - irq_bit = 0x1D; - } else { - if (mirq > 1) { - pci_log("pci_clear_mirq(%02X): Invalid MIRQ\n", mirq); - return; - } - - if (! pci_mirqs[mirq].enabled) { - pci_log("pci_clear_mirq(%02X): MIRQ0 disabled\n", mirq); - return; - } - - if (pci_mirqs[mirq].irq_line > 0x0f) { - pci_log("pci_clear_mirq(%02X): IRQ line is disabled\n", mirq); - return; - } - - irq_line = pci_mirqs[mirq].irq_line; - irq_bit = (0x1E + mirq); - } - pci_log("pci_clear_mirq(%02X): Using IRQ %i\n", mirq, irq_line); - - if (level && !(pci_irq_hold[irq_line] & (1ULL << irq_bit))) { - /* IRQ not held, do nothing. */ - pci_log("pci_clear_mirq(%02X): MIRQ is not holding the IRQ\n", mirq); - return; - } - - if (level) { - pci_log("pci_clear_mirq(%02X): Releasing this MIRQ's hold on the IRQ\n", mirq); - pci_irq_hold[irq_line] &= ~(1 << irq_bit); - - if (! pci_irq_hold[irq_line]) { - pci_log("pci_clear_mirq(%02X): IRQ no longer held by any card, clearing it\n", mirq); - picintc(1 << irq_line); - } else { - pci_log("pci_clear_mirq(%02X): IRQ is still being held\n", mirq); - } - } else { - pci_log("pci_clear_mirq(%02X): Clearing edge-triggered interrupt\n", mirq); - picintc(1 << irq_line); - } -} - - -void -pci_clear_irq(uint8_t card, uint8_t pci_int) -{ - uint8_t slot = 0; - uint8_t irq_routing = 0; - uint8_t pci_int_index = pci_int - PCI_INTA; - uint8_t irq_line = 0; - uint8_t level = 0; - - if (! last_pci_card) { - // pci_log("pci_clear_irq(%02X, %02X): No PCI slots (how are we even here?!)\n", card, pci_int); - return; - } - // pci_log("pci_clear_irq(%02X, %02X): %i PCI slots\n", card, pci_int, last_pci_card); - - slot = card; - if (slot == 0xff) { - // pci_log("pci_clear_irq(%02X, %02X): Card is not on a PCI slot (how are we even here?!)\n", card, pci_int); - return; - } - // pci_log("pci_clear_irq(%02X, %02X): Card is on PCI slot %02X\n", card, pci_int, slot); - - if (! pci_cards[slot].irq_routing[pci_int_index]) { - // pci_log("pci_clear_irq(%02X, %02X): No IRQ routing for this slot and INT pin combination\n", card, pci_int); - return; - } - - if (pci_type & PCI_NO_IRQ_STEERING) - irq_line = pci_cards[slot].read(0, 0x3c, pci_cards[slot].priv); - else { - irq_routing = (pci_cards[slot].irq_routing[pci_int_index] - PCI_INTA) & 3; - // pci_log("pci_clear_irq(%02X, %02X): IRQ routing for this slot and INT pin combination: %02X\n", card, pci_int, irq_routing); - - irq_line = pci_irqs[irq_routing]; - level = pci_irq_level[irq_routing]; - } - - if (irq_line > 0x0f) { - // pci_log("pci_clear_irq(%02X, %02X): IRQ line is disabled\n", card, pci_int); - return; - } - - // pci_log("pci_clear_irq(%02X, %02X): Using IRQ %i\n", card, pci_int, irq_line); - - if (level && !(pci_irq_hold[irq_line] & (1ULL << slot))) { - /* IRQ not held, do nothing. */ - // pci_log("pci_clear_irq(%02X, %02X): Card is not holding the IRQ\n", card, pci_int); - return; - } - - if (level) { - // pci_log("pci_clear_irq(%02X, %02X): Releasing this card's hold on the IRQ\n", card, pci_int); - pci_irq_hold[irq_line] &= ~(1 << slot); - - if (! pci_irq_hold[irq_line]) { - // pci_log("pci_clear_irq(%02X, %02X): IRQ no longer held by any card, clearing it\n", card, pci_int); - picintc(1 << irq_line); - } // else { - // pci_log("pci_clear_irq(%02X, %02X): IRQ is still being held\n", card, pci_int); - // } - } else { - // pci_log("pci_clear_irq(%02X, %02X): Clearing edge-triggered interrupt\n", card, pci_int); - picintc(1 << irq_line); - } -} - - uint8_t pci_get_int(uint8_t slot, uint8_t pci_int) { return pci_cards[slot].irq_routing[pci_int - PCI_INTA]; } +static void +pci_clear_slot(int card) +{ + pci_card_to_slot_mapping[pci_cards[card].bus][pci_cards[card].id] = PCI_CARD_INVALID; + + pci_cards[card].id = 0xff; + pci_cards[card].type = 0xff; + + for (uint8_t i = 0; i < 4; i++) + pci_cards[card].irq_routing[i] = 0; + + pci_cards[card].read = NULL; + pci_cards[card].write = NULL; + pci_cards[card].priv = NULL; +} + +/* Relocate a PCI device to a new slot, required for the configurable + IDSEL's of ALi M1543(c). */ +void +pci_relocate_slot(int type, int new_slot) +{ + int card = -1; + int old_slot; + + if ((new_slot < 0) || (new_slot > 31)) + return; + + for (uint8_t i = 0; i < PCI_CARDS_NUM; i++) { + if ((pci_cards[i].bus == 0) && (pci_cards[i].type == type)) { + card = i; + break; + } + } + + if (card == -1) + return; + + old_slot = pci_cards[card].id; + pci_cards[card].id = new_slot; + + if (pci_card_to_slot_mapping[0][old_slot] == card) + pci_card_to_slot_mapping[0][old_slot] = PCI_CARD_INVALID; + + if (pci_card_to_slot_mapping[0][new_slot] == PCI_CARD_INVALID) + pci_card_to_slot_mapping[0][new_slot] = card; +} + +/* Write PCI enable/disable key, split for the ALi M1435. */ +void +pci_key_write(uint8_t val) +{ + pci_key = val & 0xf0; + + if (pci_key) + pci_flags |= FLAG_CONFIG_IO_ON; + else + pci_flags &= ~FLAG_CONFIG_IO_ON; +} + +static void +pci_io_handlers(int set) +{ + io_handler(set, 0x0cf8, 4, pci_read, pci_readw, pci_readl, pci_write, pci_writew, pci_writel, NULL); + + if (pci_flags & FLAG_MECHANISM_1) + io_handler(set, 0x0cfc, 4, pci_read, pci_readw, pci_readl, pci_write, pci_writew, pci_writel, NULL); + + if (pci_flags & FLAG_MECHANISM_2) { + if (set && pci_key) + pci_flags |= FLAG_CONFIG_IO_ON; + else + pci_flags &= ~FLAG_CONFIG_IO_ON; + } +} + +/* Set PMC (ie. change PCI configuration mechanism), 0 = #2, 1 = #1. */ +void +pci_set_pmc(uint8_t pmc) +{ + pci_log("pci_set_pmc(%02X)\n", pmc); + + pci_io_handlers(0); + + pci_flags &= ~FLAG_MECHANISM_MASK; + pci_flags |= (FLAG_MECHANISM_1 + !(pmc & 0x01)); + + pci_io_handlers(1); + + pci_pmc = (pmc & 0x01); +} + +static void +pci_reg_write(uint16_t port, uint8_t val) +{ + uint8_t slot = 0; + + if (port >= 0xc000) { + pci_card = (port >> 8) & 0xf; + pci_index = port & 0xfc; + } + + slot = pci_card_to_slot_mapping[pci_bus_number_to_index_mapping[pci_bus]][pci_card]; + if (slot != PCI_CARD_INVALID) { + if (pci_cards[slot].write) + pci_cards[slot].write(pci_func, pci_index | (port & 0x03), val, pci_cards[slot].priv); + } + pci_log("PCI: [WB] Mechanism #%i, slot %02X, %s card %02X:%02X, function %02X, index %02X = %02X\n", + (port >= 0xc000) ? 2 : 1, slot, + (slot == PCI_CARD_INVALID) ? "non-existent" : (pci_cards[slot].write ? "used" : "unused"), + pci_card, pci_bus, pci_func, pci_index | (port & 0x03), val); +} static void pci_reset_regs(void) { pci_index = pci_card = pci_func = pci_bus = pci_key = 0; + pci_enable = 0x00000000; - io_removehandler(0xc000, 0x1000, - pci_type2_read, NULL, NULL, - pci_type2_write, NULL, NULL, NULL); + pci_flags &= ~(FLAG_CONFIG_IO_ON | FLAG_CONFIG_M1_IO_ON); } - void pci_pic_reset(void) { @@ -761,332 +359,603 @@ pci_pic_reset(void) pic_set_pci_flag(last_pci_card > 0); } - static void pci_reset_hard(void) { - int i; - pci_reset_regs(); - for (i = 0; i < 16; i++) { - if (pci_irq_hold[i]) { - pci_irq_hold[i] = 0; + for (uint8_t i = 0; i < PCI_IRQS_NUM; i++) { + if (pci_irq_hold[i]) { + pci_irq_hold[i] = 0; - picintc(1 << i); - } + picintc(1 << i); + } } pci_pic_reset(); } - void pci_reset(void) { - if (pci_switch) { - pci_pmc = 0x00; - - io_removehandler(0x0cf8, 1, - NULL,NULL,pci_cf8_read, NULL,NULL,pci_cf8_write, NULL); - io_removehandler(0x0cfc, 4, - pci_read,NULL,NULL, pci_write,NULL,NULL, NULL); - io_sethandler(0x0cf8, 1, - pci_type2_read,NULL,NULL, pci_type2_write,NULL,NULL, NULL); - io_sethandler(0x0cfa, 1, - pci_type2_read,NULL,NULL, pci_type2_write,NULL,NULL, NULL); + if (pci_flags & FLAG_MECHANISM_SWITCH) { + pci_log("pci_reset(): Switchable configuration mechanism\n"); + pci_set_pmc(0x00); } pci_reset_hard(); } - static void -pci_slots_clear(void) -{ - uint8_t i, j; - - last_pci_card = last_normal_pci_card = 0; - last_pci_bus = 1; - - for (i = 0; i < 32; i++) { - pci_cards[i].id = 0xff; - pci_cards[i].type = 0xff; - - for (j = 0; j < 4; j++) - pci_cards[i].irq_routing[j] = 0; - - pci_cards[i].read = NULL; - pci_cards[i].write = NULL; - pci_cards[i].priv = NULL; - } - - i = 0; - do { - for (j = 0; j < 32; j++) - pci_card_to_slot_mapping[i][j] = 0xff; - pci_bus_number_to_index_mapping[i] = 0xff; - } while (i++ < 0xff); - - pci_bus_number_to_index_mapping[0] = 0; /* always map bus 0 to index 0 */ -} - - -uint32_t -trc_readl(uint16_t port, void *priv) -{ - return 0xffffffff; -} - - -uint16_t -trc_readw(uint16_t port, void *priv) -{ - return 0xffff; -} - - -uint8_t -trc_read(uint16_t port, void *priv) -{ - return trc_reg & 0xfb; -} - - -static void -trc_reset(uint8_t val) +pci_trc_reset(uint8_t val) { if (val & 2) { - dma_reset(); - dma_set_at(1); + dma_reset(); + dma_set_at(1); - device_reset_all(); + device_reset_all(DEVICE_ALL); - cpu_alt_reset = 0; + cpu_alt_reset = 0; - pci_reset(); - keyboard_at_reset(); + pci_reset(); - mem_a20_alt = 0; - mem_a20_recalc(); + mem_a20_alt = 0; + mem_a20_recalc(); - flushmmucache(); + flushmmucache(); } resetx86(); } - void -trc_writel(uint16_t port, uint32_t val, void *priv) +pci_write(uint16_t port, uint8_t val, UNUSED(void *priv)) { -} + pci_log("PCI: [WB] Mechanism #%i port %04X = %02X\n", ((port >= 0xcfc) && (port <= 0xcff)) ? 1 : 2, port, val); + switch (port) { + case 0xcf8: + if (pci_flags & FLAG_MECHANISM_2) { + pci_func = (val >> 1) & 7; + pci_key_write(val); -void -trc_writew(uint16_t port, uint16_t val, void *priv) -{ -} + pci_log("PCI: Mechanism #2 CF8: %sllocating ports %04X-%04X...\n", (pci_flags & FLAG_CONFIG_IO_ON) ? "A" : "Dea", + pci_base, pci_base + pci_size - 1); + } + break; + case 0xcf9: + if (!(pci_trc_reg & 4) && (val & 4)) + pci_trc_reset(val); + pci_trc_reg = val & 0xfd; -void -trc_write(uint16_t port, uint8_t val, void *priv) -{ - pci_log("TRC Write: %02X\n", val); + if (val & 2) + pci_trc_reg &= 0xfb; + break; + case 0xcfa: + if (pci_flags & FLAG_MECHANISM_2) + pci_bus = val; + break; + case 0xcfb: + if (pci_flags & FLAG_MECHANISM_SWITCH) + pci_set_pmc(val); + break; - if (!(trc_reg & 4) && (val & 4)) - trc_reset(val); + case 0xcfc: + case 0xcfd: + case 0xcfe: + case 0xcff: + if ((pci_flags & FLAG_MECHANISM_1) && (pci_flags & FLAG_CONFIG_M1_IO_ON)) + pci_reg_write(port, val); + break; - trc_reg = val & 0xfd; + case 0xc000 ... 0xc0ff: + if ((pci_flags & FLAG_MECHANISM_2) && (pci_flags & (FLAG_CONFIG_IO_ON | FLAG_CONFIG_DEV0_IO_ON))) + pci_reg_write(port, val); + break; - if (val & 2) - trc_reg &= 0xfb; -} + case 0xc100 ... 0xcfff: + if ((pci_flags & FLAG_MECHANISM_2) && (pci_flags & FLAG_CONFIG_IO_ON)) + pci_reg_write(port, val); + break; - -void -trc_init(void) -{ - trc_reg = 0; - - io_sethandler(0x0cf9, 0x0001, - trc_read, trc_readw, trc_readl, trc_write, trc_writew, trc_writel, NULL); -} - - -void -pci_init(int type) -{ - int c; - - pci_slots_clear(); - - pci_reset_hard(); - - trc_init(); - - pci_type = type; - pci_switch = !!(type & PCI_CAN_SWITCH_TYPE); - - if (pci_switch) { - pci_pmc = 0x00; - - io_sethandler(0x0cfb, 1, - pci_type2_read,NULL,NULL, pci_type2_write,NULL,pci_type2_writel, NULL); + default: + break; } +} - if (type & PCI_NO_IRQ_STEERING) { - pic_elcr_io_handler(0); - pic_elcr_set_enabled(0); +void +pci_writew(uint16_t port, uint16_t val, UNUSED(void *priv)) +{ + if (port & 0x0001) { + /* Non-aligned access, split into two byte accesses. */ + pci_write(port, val & 0xff, priv); + pci_write(port + 1, val >> 8, priv); } else { - pic_elcr_io_handler(1); - pic_elcr_set_enabled(1); - } + /* Aligned access, still split because we cheat. */ + switch (port) { + case 0xcfc: + case 0xcfe: + case 0xc000 ... 0xcffe: + pci_write(port, val & 0xff, priv); + pci_write(port + 1, val >> 8, priv); + break; - if ((type & PCI_CONFIG_TYPE_MASK) == PCI_CONFIG_TYPE_1) { - io_sethandler(0x0cf8, 1, - NULL,NULL,pci_cf8_read, NULL,NULL,pci_cf8_write, NULL); - io_sethandler(0x0cfc, 4, - pci_read,pci_readw,pci_readl, pci_write,pci_writew,pci_writel, NULL); - pci_pmc = 1; - } else { - io_sethandler(0x0cf8, 1, - pci_type2_read,NULL,NULL, pci_type2_write,NULL,NULL, NULL); - io_sethandler(0x0cfa, 1, - pci_type2_read,NULL,NULL, pci_type2_write,NULL,NULL, NULL); - pci_pmc = 0; + default: + break; + } } - - for (c = 0; c < 4; c++) { - pci_irqs[c] = PCI_IRQ_DISABLED; - pci_irq_level[c] = (type & PCI_NO_IRQ_STEERING) ? 0 : 1; - } - - for (c = 0; c < 3; c++) { - pci_mirqs[c].enabled = 0; - pci_mirqs[c].irq_line = PCI_IRQ_DISABLED; - } - - pic_set_pci_flag(1); } +void +pci_writel(uint16_t port, uint32_t val, UNUSED(void *priv)) +{ + if (port & 0x0003) { + /* Non-aligned access, split into two word accesses. */ + pci_writew(port, val & 0xffff, priv); + pci_writew(port + 2, val >> 16, priv); + } else { + /* Aligned access. */ + switch (port) { + case 0xcf8: + /* No split here, actual 32-bit access. */ + if (pci_flags & FLAG_MECHANISM_1) { + pci_log("PCI: [WL] Mechanism #1 port 0CF8 = %08X\n", val); + + pci_index = val & 0xff; + pci_func = (val >> 8) & 7; + pci_card = (val >> 11) & 31; + pci_bus = (val >> 16) & 0xff; + pci_enable = (val & PCI_ENABLED); + + if (pci_enable) + pci_flags |= FLAG_CONFIG_M1_IO_ON; + else + pci_flags &= ~FLAG_CONFIG_M1_IO_ON; + break; + } + break; + case 0xcfc: + case 0xc000 ... 0xcffc: + /* Still split because we cheat. */ + pci_writew(port, val & 0xffff, priv); + pci_writew(port + 2, val >> 16, priv); + break; + + default: + break; + } + } +} + +static uint8_t +pci_reg_read(uint16_t port) +{ + uint8_t slot = 0; + uint8_t ret = 0xff; + + if (port >= 0xc000) { + pci_card = (port >> 8) & 0xf; + pci_index = port & 0xfc; + } + + slot = pci_card_to_slot_mapping[pci_bus_number_to_index_mapping[pci_bus]][pci_card]; + if (slot != PCI_CARD_INVALID) { + if (pci_cards[slot].read) + ret = pci_cards[slot].read(pci_func, pci_index | (port & 0x03), pci_cards[slot].priv); + } + pci_log("PCI: [RB] Mechanism #%i, slot %02X, %s card %02X:%02X, function %02X, index %02X = %02X\n", + (port >= 0xc000) ? 2 : 1, slot, + (slot == PCI_CARD_INVALID) ? "non-existent" : (pci_cards[slot].read ? "used" : "unused"), + pci_card, pci_bus, pci_func, pci_index | (port & 0x03), ret); + + return ret; +} uint8_t -pci_register_bus() +pci_read(uint16_t port, UNUSED(void *priv)) +{ + uint8_t ret = 0xff; + + switch (port) { + case 0xcf8: + if (pci_flags & FLAG_MECHANISM_2) + ret = pci_key | (pci_func << 1); + break; + case 0xcf9: + ret = pci_trc_reg & 0xfb; + break; + case 0xcfa: + if (pci_flags & FLAG_MECHANISM_2) + ret = pci_bus; + break; + case 0xcfb: + if (pci_flags & FLAG_MECHANISM_SWITCH) + ret = pci_pmc; + break; + + case 0xcfc: + case 0xcfd: + case 0xcfe: + case 0xcff: + if ((pci_flags & FLAG_MECHANISM_1) && (pci_flags & FLAG_CONFIG_M1_IO_ON)) + ret = pci_reg_read(port); + break; + + case 0xc000 ... 0xc0ff: + if ((pci_flags & FLAG_MECHANISM_2) && (pci_flags & (FLAG_CONFIG_IO_ON | FLAG_CONFIG_DEV0_IO_ON))) + ret = pci_reg_read(port); + break; + + case 0xc100 ... 0xcfff: + if ((pci_flags & FLAG_MECHANISM_2) && (pci_flags & FLAG_CONFIG_IO_ON)) + ret = pci_reg_read(port); + break; + + default: + break; + } + + pci_log("PCI: [RB] Mechanism #%i port %04X = %02X\n", ((port >= 0xcfc) && (port <= 0xcff)) ? 1 : 2, port, ret); + + return ret; +} + +uint16_t +pci_readw(uint16_t port, UNUSED(void *priv)) +{ + uint16_t ret = 0xffff; + + if (port & 0x0001) { + /* Non-aligned access, split into two byte accesses. */ + ret = pci_read(port, priv); + ret |= ((uint16_t) pci_read(port + 1, priv)) << 8; + } else { + /* Aligned access, still split because we cheat. */ + switch (port) { + case 0xcfc: + case 0xcfe: + case 0xc000 ... 0xcffe: + ret = pci_read(port, priv); + ret |= ((uint16_t) pci_read(port + 1, priv)) << 8; + break; + + default: + break; + } + } + + return ret; +} + +uint32_t +pci_readl(uint16_t port, UNUSED(void *priv)) +{ + uint32_t ret = 0xffffffff; + + if (port & 0x0003) { + /* Non-aligned access, split into two word accesses. */ + ret = pci_readw(port, priv); + ret |= ((uint32_t) pci_readw(port + 2, priv)) << 16; + } else { + /* Aligned access. */ + switch (port) { + case 0xcf8: + /* No split here, actual 32-bit access. */ + if (pci_flags & FLAG_MECHANISM_1) { + ret = pci_index | (pci_func << 8) | (pci_card << 11) | (pci_bus << 16); + if (pci_flags & FLAG_CONFIG_M1_IO_ON) + ret |= PCI_ENABLED; + + pci_log("PCI: [RL] Mechanism #1 port 0CF8 = %08X\n", ret); + + return ret; + } + break; + case 0xcfc: + case 0xc000 ... 0xcffc: + /* Still split because we cheat. */ + ret = pci_readw(port, priv); + ret |= ((uint32_t) pci_readw(port + 2, priv)) << 16; + break; + } + } + + return ret; +} + +uint8_t +pci_register_bus(void) { return last_pci_bus++; } - void pci_remap_bus(uint8_t bus_index, uint8_t bus_number) { uint8_t i = 1; do { - if (pci_bus_number_to_index_mapping[i] == bus_index) - pci_bus_number_to_index_mapping[i] = 0xff; + if (pci_bus_number_to_index_mapping[i] == bus_index) + pci_bus_number_to_index_mapping[i] = PCI_BUS_INVALID; } while (i++ < 0xff); if ((bus_number > 0) && (bus_number < 0xff)) - pci_bus_number_to_index_mapping[bus_number] = bus_index; + pci_bus_number_to_index_mapping[bus_number] = bus_index; } - -void -pci_register_slot(int card, int type, int inta, int intb, int intc, int intd) -{ - pci_register_bus_slot(0, card, type, inta, intb, intc, intd); -} - - void pci_register_bus_slot(int bus, int card, int type, int inta, int intb, int intc, int intd) { pci_card_t *dev = &pci_cards[last_pci_card]; - dev->bus = bus; - dev->id = card; - dev->type = type; - dev->irq_routing[0] = inta; - dev->irq_routing[1] = intb; - dev->irq_routing[2] = intc; - dev->irq_routing[3] = intd; - dev->read = NULL; - dev->write = NULL; - dev->priv = NULL; + dev->bus = bus; + dev->id = card; + dev->type = type; + dev->irq_routing[0] = inta; + dev->irq_routing[1] = intb; + dev->irq_routing[2] = intc; + dev->irq_routing[3] = intd; + dev->read = NULL; + dev->write = NULL; + dev->priv = NULL; pci_card_to_slot_mapping[bus][card] = last_pci_card; pci_log("pci_register_slot(): pci_cards[%i].bus = %02X; .id = %02X\n", last_pci_card, bus, card); - if (type == PCI_CARD_NORMAL) - last_normal_pci_card = last_pci_card; + if (type == PCI_CARD_NORMAL) { + last_normal_pci_card++; + /* This is needed to know at what position to add the bridge. */ + last_normal_pci_card_id = last_pci_card; + } + last_pci_card++; } - -uint8_t +static uint8_t pci_find_slot(uint8_t add_type, uint8_t ignore_slot) { - pci_card_t *dev; - uint8_t i, ret = 0xff; + const pci_card_t *dev; + /* Is the device being added with a strict slot type matching requirement? */ + uint8_t strict = (add_type & PCI_ADD_STRICT); + /* The actual type of the device being added, with the strip flag, if any, + masked. */ + uint8_t masked_add_type = (add_type & PCI_ADD_MASK); + /* Is the device being added normal, ie. without the possibility of ever + being used as an on-board device? */ + uint8_t normal_add_type = (masked_add_type >= PCI_CARD_NORMAL); + uint8_t match; + uint8_t normal; + uint8_t empty; + uint8_t process; + uint8_t ret = PCI_CARD_INVALID; - for (i = 0; i < last_pci_card; i++) { - dev = &pci_cards[i]; + /* Iterate i until we have either exhausted all the slot or the value of + ret has changed to something other than PCI_CARD_INVALID. */ + for (uint8_t i = 0; (ret == PCI_CARD_INVALID) && (i < last_pci_card); i++) { + dev = &pci_cards[i]; - if (!dev->read && !dev->write && ((ignore_slot == 0xff) || (i != ignore_slot))) { - if (add_type & PCI_ADD_STRICT) { - if (dev->type == (add_type & 0x7f)) { - ret = i; - break; - } - } else { - if (((dev->type == PCI_CARD_NORMAL) && ((add_type & 0x7f) >= PCI_ADD_NORMAL)) || - (dev->type == (add_type & 0x7f))) { - ret = i; - break; - } - } - } + /* Is the slot we are looking at of the exact same type as the device being + added? */ + match = (dev->type == masked_add_type); + /* Is the slot we are looking at a normal slot (ie. not an on-board chip)? */ + normal = (dev->type == PCI_CARD_NORMAL); + /* Is the slot we are looking at empty? */ + empty = !dev->read && !dev->write; + /* Should we process this slot, ie. were we told to ignore it, if any at all? */ + process = (ignore_slot == PCI_IGNORE_NO_SLOT) || (i != ignore_slot); + + /* This condition is now refactored and made to be easily human-readable. */ + if (empty && process && (match || (!strict && normal && normal_add_type))) + ret = i; } return ret; } - -uint8_t -pci_add_card(uint8_t add_type, uint8_t (*read)(int func, int addr, void *priv), void (*write)(int func, int addr, uint8_t val, void *priv), void *priv) +/* Add a PCI card. */ +void +pci_add_card(uint8_t add_type, uint8_t (*read)(int func, int addr, void *priv), + void (*write)(int func, int addr, uint8_t val, void *priv), void *priv, uint8_t *slot) { - pci_card_t *dev; - uint8_t i, j; + pci_card_desc_t *dev; - if (add_type < PCI_ADD_AGP) - pci_log("pci_add_card(): Adding PCI CARD at specific slot %02X [SPECIFIC]\n", add_type); + pci_log("pci_add_card(): PCI card #%02i: type = %i\n", next_pci_card, add_type); - if (! last_pci_card) { - pci_log("pci_add_card(): Adding PCI CARD failed (no PCI slots) [%s]\n", (add_type == PCI_ADD_NORMAL) ? "NORMAL" : ((add_type == PCI_ADD_AGP) ? "AGP" : ((add_type == PCI_ADD_VIDEO) ? "VIDEO" : ((add_type == PCI_ADD_SCSI) ? "SCSI" : ((add_type == PCI_ADD_SOUND) ? "SOUND" : "SPECIFIC"))))); - return 0xff; + if (next_pci_card < PCI_CARDS_NUM) { + dev = &pci_card_descs[next_pci_card]; + + dev->type = add_type; + dev->read = read; + dev->write = write; + dev->priv = priv; + dev->slot = slot; + + *(dev->slot) = PCI_CARD_INVALID; + + next_pci_card++; + if (add_type == PCI_ADD_NORMAL) + normal_pci_cards++; } - - /* First, find the next available slot. */ - i = pci_find_slot(add_type, 0xff); - - if (i != 0xff) { - dev = &pci_cards[i]; - j = pci_find_slot(add_type, i); - - if (!(pci_type & PCI_NO_BRIDGES) && (dev->type == PCI_CARD_NORMAL) && (add_type != PCI_ADD_BRIDGE) && (j == 0xff)) { - pci_log("pci_add_card(): Reached last NORMAL slot, adding bridge to pci_cards[%i]\n", i); - device_add_inst(&dec21150_device, last_pci_bus); - i = pci_find_slot(add_type, 0xff); - dev = &pci_cards[i]; - } - - dev->read = read; - dev->write = write; - dev->priv = priv; - pci_log("pci_add_card(): Adding PCI CARD to pci_cards[%i] (bus %02X slot %02X) [%s]\n", i, dev->bus, dev->id, (add_type == PCI_ADD_NORMAL) ? "NORMAL" : ((add_type == PCI_ADD_AGP) ? "AGP" : ((add_type == PCI_ADD_VIDEO) ? "VIDEO" : ((add_type == PCI_ADD_SCSI) ? "SCSI" : ((add_type == PCI_ADD_SOUND) ? "SOUND" : "SPECIFIC"))))); - return i; - } - - return 0xff; +} + +static void +pci_clear_card(UNUSED(int pci_card)) +{ + pci_card_desc_t *dev; + + if (next_pci_card < PCI_CARDS_NUM) { + dev = &pci_card_descs[next_pci_card]; + + memset(dev, 0x00, sizeof(pci_card_desc_t)); + } +} + +static uint8_t +pci_register_card(int pci_card) +{ + pci_card_desc_t *dev; + pci_card_t *card; + uint8_t i; + uint8_t ret = PCI_CARD_INVALID; + + if (pci_card < PCI_CARDS_NUM) { + dev = &pci_card_descs[pci_card]; + + if (last_pci_card) { + /* First, find the next available slot. */ + i = pci_find_slot(dev->type, 0xff); + + if (i != PCI_CARD_INVALID) { + card = &pci_cards[i]; + card->read = dev->read; + card->write = dev->write; + card->priv = dev->priv; + card->type |= (dev->type & PCI_CARD_VFIO); + + *(dev->slot) = i; + + ret = i; + } + } + + pci_clear_card(pci_card); + } + + return ret; +} + +/* Add an instance of the PCI bridge. */ +void +pci_add_bridge(uint8_t agp, uint8_t (*read)(int func, int addr, void *priv), void (*write)(int func, int addr, uint8_t val, void *priv), void *priv, uint8_t *slot) +{ + pci_card_t *card; + uint8_t bridge_slot = agp ? pci_find_slot(PCI_ADD_AGPBRIDGE, 0xff) : last_normal_pci_card_id; + + if (bridge_slot != PCI_CARD_INVALID) { + card = &pci_cards[bridge_slot]; + card->read = read; + card->write = write; + card->priv = priv; + } + + *slot = bridge_slot; +} + +/* Register the cards that have been added into slots. */ +void +pci_register_cards(void) +{ + uint8_t normal; +#ifdef ENABLE_PCI_LOG + uint8_t type; + uint8_t *slot; +#endif + + next_normal_pci_card = 0; + + if (next_pci_card > 0) { + for (uint8_t i = 0; i < next_pci_card; i++) { +#ifdef ENABLE_PCI_LOG + type = pci_card_descs[i].type; + slot = pci_card_descs[i].slot; +#endif + normal = (pci_card_descs[i].type == PCI_CARD_NORMAL); + + /* If this is a normal card, increase the next normal card index. */ + if (normal) + next_normal_pci_card++; + + /* If this is a normal card and the next one is going to be beyond the last slot, + add the bridge. */ + if (normal && (next_normal_pci_card >= last_normal_pci_card) && + (normal_pci_cards > last_normal_pci_card) && !(pci_flags & FLAG_NO_BRIDGES)) + device_add_inst(&dec21150_device, last_pci_bus); + + pci_register_card(i); + pci_log("pci_register_cards(): PCI card #%02i: type = %02X, pci device = %02X:%02X\n", + i, type, pci_cards[*slot].bus, pci_cards[*slot].id); + } + } + + next_pci_card = 0; + normal_pci_cards = 0; + + next_normal_pci_card = 0; +} + +static void +pci_slots_clear(void) +{ + uint8_t i; + + last_pci_card = last_normal_pci_card = 0; + last_normal_pci_card = 0; + last_pci_bus = 1; + + next_pci_card = 0; + normal_pci_cards = 0; + + next_normal_pci_card = 0; + + for (i = 0; i < PCI_CARDS_NUM; i++) + pci_clear_slot(i); + + i = 0; + do { + for (uint8_t j = 0; j < PCI_CARDS_NUM; j++) + pci_card_to_slot_mapping[i][j] = PCI_CARD_INVALID; + pci_bus_number_to_index_mapping[i] = PCI_BUS_INVALID; + } while (i++ < 0xff); + + pci_bus_number_to_index_mapping[0] = 0; /* always map bus 0 to index 0 */ +} + +void +pci_init(int flags) +{ + int c; + + pci_base = 0xc000; + pci_size = 0x1000; + + pci_slots_clear(); + + pci_reset_hard(); + + pci_trc_reg = 0; + pci_flags = flags; + + if (pci_flags & FLAG_NO_IRQ_STEERING) { + pic_elcr_io_handler(0); + pic_elcr_set_enabled(0); + } else { + pic_elcr_io_handler(1); + pic_elcr_set_enabled(1); + } + + pci_pmc = (pci_flags & FLAG_MECHANISM_1) ? 0x01 : 0x00; + + if ((pci_flags & FLAG_MECHANISM_2) && (pci_flags & FLAG_CONFIG_DEV0_IO_ON)) { + pci_log("PCI: Always expose device 0\n"); + pci_base = 0xc100; + pci_size = 0x0f00; + } + + if (pci_flags & FLAG_MECHANISM_SWITCH) { + pci_log("PCI: Switchable configuration mechanism\n"); + pci_set_pmc(pci_pmc); + } else + pci_io_handlers(1); + + for (c = 0; c < PCI_IRQS_NUM; c++) { + pci_irqs[c] = PCI_IRQ_DISABLED; + pci_irq_level[c] = (pci_flags & FLAG_NO_IRQ_STEERING) ? 0 : 1; + } + + for (c = 0; c < PCI_MIRQS_NUM; c++) { + pci_mirqs[c].enabled = 0; + pci_mirqs[c].irq_line = PCI_IRQ_DISABLED; + } + + pic_set_pci_flag(1); } diff --git a/src/pci_dummy.c b/src/pci_dummy.c index 066f18dcc..704f85d8c 100644 --- a/src/pci_dummy.c +++ b/src/pci_dummy.c @@ -1,242 +1,312 @@ /* This can also serve as a sample PCI device. */ #include #include +#include #include #include #include <86box/86box.h> +#include <86box/device.h> #include <86box/io.h> #include <86box/pci.h> #include <86box/pci_dummy.h> +#include <86box/plat_fallthrough.h> +#include <86box/plat_unused.h> -static uint8_t pci_regs[256]; +typedef struct pci_dummy_t { + uint8_t pci_regs[256]; -static bar_t pci_bar[2]; + bar_t pci_bar[2]; -static uint8_t interrupt_on = 0x00; -static uint8_t card = 0; + uint8_t pci_slot; + uint8_t irq_state; + uint8_t interrupt_on; -static void pci_dummy_interrupt(int set) + uint8_t irq_level; +} pci_dummy_t; + +static void +pci_dummy_interrupt(int set, pci_dummy_t *dev) { + if (set != dev->irq_level) { if (set) - { - pci_set_irq(card, pci_regs[0x3D]); - } + pci_set_irq(dev->pci_slot, PCI_INTA, &dev->irq_state); else - { - pci_clear_irq(card, pci_regs[0x3D]); - } + pci_clear_irq(dev->pci_slot, PCI_INTA, &dev->irq_state); + } + + dev->irq_level = set; } - -static uint8_t pci_dummy_read(uint16_t Port, void *p) +static uint8_t +pci_dummy_read(uint16_t port, void *priv) { - uint8_t ret = 0; + pci_dummy_t *dev = (pci_dummy_t *) priv; + uint8_t ret = 0xff; - switch(Port & 0x20) - { - case 0x00: - return 0x1A; - case 0x01: - return 0x07; - case 0x02: - return 0x0B; - case 0x03: - return 0xAB; - case 0x04: - return pci_regs[0x3C]; - case 0x05: - return pci_regs[0x3D]; - case 0x06: - ret = interrupt_on; - if (interrupt_on) - { - pci_dummy_interrupt(0); - interrupt_on = 0; - } - return ret; - default: - return 0x00; - } + switch (port & 0x20) { + case 0x00: + ret = 0x1a; + break; + case 0x01: + ret = 0x07; + break; + case 0x02: + ret = 0x0b; + break; + case 0x03: + ret = 0xab; + break; + case 0x04: + ret = dev->pci_regs[0x3c]; + break; + case 0x05: + ret = dev->pci_regs[0x3d]; + break; + case 0x06: + ret = dev->interrupt_on; + if (dev->interrupt_on) { + pci_dummy_interrupt(0, dev); + dev->interrupt_on = 0; + } + break; + + default: + break; + } + + return ret; } -static uint16_t pci_dummy_readw(uint16_t Port, void *p) +static uint16_t +pci_dummy_readw(uint16_t port, void *priv) { - return pci_dummy_read(Port, p); + return pci_dummy_read(port, priv); } - -static uint32_t pci_dummy_readl(uint16_t Port, void *p) +static uint32_t +pci_dummy_readl(uint16_t port, void *priv) { - return pci_dummy_read(Port, p); + return pci_dummy_read(port, priv); } - -static void pci_dummy_write(uint16_t Port, uint8_t Val, void *p) +static void +pci_dummy_write(uint16_t port, UNUSED(uint8_t val), void *priv) { - switch(Port & 0x20) - { - case 0x06: - if (!interrupt_on) - { - interrupt_on = 1; - pci_dummy_interrupt(1); - } - return; - default: - return; - } -} + pci_dummy_t *dev = (pci_dummy_t *) priv; -static void pci_dummy_writew(uint16_t Port, uint16_t Val, void *p) -{ - pci_dummy_write(Port, Val & 0xFF, p); -} + switch (port & 0x20) { + case 0x06: + if (!dev->interrupt_on) { + dev->interrupt_on = 1; + pci_dummy_interrupt(1, dev); + } + break; -static void pci_dummy_writel(uint16_t Port, uint32_t Val, void *p) -{ - pci_dummy_write(Port, Val & 0xFF, p); -} - - -static void pci_dummy_io_remove(void) -{ - io_removehandler(pci_bar[0].addr, 0x0020, pci_dummy_read, pci_dummy_readw, pci_dummy_readl, pci_dummy_write, pci_dummy_writew, pci_dummy_writel, NULL); -} - -static void pci_dummy_io_set(void) -{ - io_sethandler(pci_bar[0].addr, 0x0020, pci_dummy_read, pci_dummy_readw, pci_dummy_readl, pci_dummy_write, pci_dummy_writew, pci_dummy_writel, NULL); -} - - -static uint8_t pci_dummy_pci_read(int func, int addr, void *priv) -{ - pclog("AB0B:071A: PCI_Read(%d, %04x)\n", func, addr); - - switch(addr) { - case 0x00: - return 0x1A; - case 0x01: - return 0x07; - break; - - case 0x02: - return 0x0B; - case 0x03: - return 0xAB; - - case 0x04: /* PCI_COMMAND_LO */ - case 0x05: /* PCI_COMMAND_HI */ - return pci_regs[addr]; - - case 0x06: /* PCI_STATUS_LO */ - case 0x07: /* PCI_STATUS_HI */ - return pci_regs[addr]; - - case 0x08: - case 0x09: - return 0x00; - - case 0x0A: - return pci_regs[addr]; - - case 0x0B: - return pci_regs[addr]; - - case 0x10: /* PCI_BAR 7:5 */ - return (pci_bar[0].addr_regs[0] & 0xe0) | 0x01; - case 0x11: /* PCI_BAR 15:8 */ - return pci_bar[0].addr_regs[1]; - case 0x12: /* PCI_BAR 23:16 */ - return pci_bar[0].addr_regs[2]; - case 0x13: /* PCI_BAR 31:24 */ - return pci_bar[0].addr_regs[3]; - - case 0x2C: - return 0x1A; - case 0x2D: - return 0x07; - - case 0x2E: - return 0x0B; - case 0x2F: - return 0xAB; - - case 0x3C: /* PCI_ILR */ - return pci_regs[addr]; - - case 0x3D: /* PCI_IPR */ - return pci_regs[addr]; - - default: - return 0x00; + default: + break; } } -static void pci_dummy_pci_write(int func, int addr, uint8_t val, void *priv) +static void +pci_dummy_writew(uint16_t port, uint16_t val, void *priv) { - uint8_t valxor; + pci_dummy_write(port, val & 0xFF, priv); +} - pclog("AB0B:071A: PCI_Write(%d, %04x, %02x)\n", func, addr, val); +static void +pci_dummy_writel(uint16_t port, uint32_t val, void *priv) +{ + pci_dummy_write(port, val & 0xFF, priv); +} - switch(addr) { - case 0x04: /* PCI_COMMAND_LO */ - valxor = (val & 0x03) ^ pci_regs[addr]; - if (valxor & PCI_COMMAND_IO) - { - pci_dummy_io_remove(); - if (((pci_bar[0].addr & 0xffe0) != 0) && (val & PCI_COMMAND_IO)) - { - pci_dummy_io_set(); - } - } - pci_regs[addr] = val & 0x03; - break; +static void +pci_dummy_io_remove(pci_dummy_t *dev) +{ + io_removehandler(dev->pci_bar[0].addr, 0x0020, pci_dummy_read, pci_dummy_readw, pci_dummy_readl, pci_dummy_write, pci_dummy_writew, pci_dummy_writel, dev); +} - case 0x10: /* PCI_BAR */ - val &= 0xe0; /* 0xe0 acc to RTL DS */ - val |= 0x01; /* re-enable IOIN bit */ - /*FALLTHROUGH*/ +static void +pci_dummy_io_set(pci_dummy_t *dev) +{ + io_sethandler(dev->pci_bar[0].addr, 0x0020, pci_dummy_read, pci_dummy_readw, pci_dummy_readl, pci_dummy_write, pci_dummy_writew, pci_dummy_writel, dev); +} - case 0x11: /* PCI_BAR */ - case 0x12: /* PCI_BAR */ - case 0x13: /* PCI_BAR */ - /* Remove old I/O. */ - pci_dummy_io_remove(); +static uint8_t +pci_dummy_pci_read(int func, int addr, void *priv) +{ + const pci_dummy_t *dev = (pci_dummy_t *) priv; + uint8_t ret = 0xff; - /* Set new I/O as per PCI request. */ - pci_bar[0].addr_regs[addr & 3] = val; + if (func == 0x00) + switch (addr) { + case 0x00: + case 0x2c: + ret = 0x1a; + break; + case 0x01: + case 0x2d: + ret = 0x07; + break; - /* Then let's calculate the new I/O base. */ - pci_bar[0].addr &= 0xffe0; + case 0x02: + case 0x2e: + ret = 0x0b; + break; + case 0x03: + case 0x2f: + ret = 0xab; + break; - /* Log the new base. */ - pclog("AB0B:071A: PCI: new I/O base is %04X\n", pci_bar[0].addr); + case 0x04: /* PCI_COMMAND_LO */ + case 0x05: /* PCI_COMMAND_HI */ + case 0x06: /* PCI_STATUS_LO */ + case 0x07: /* PCI_STATUS_HI */ + case 0x0a: + case 0x0b: + case 0x3c: /* PCI_ILR */ + ret = dev->pci_regs[addr]; + break; - /* We're done, so get out of the here. */ - if (pci_regs[4] & PCI_COMMAND_IO) - { - if ((pci_bar[0].addr) != 0) - { - pci_dummy_io_set(); - } - } - break; + case 0x08: /* Techncially, revision, but we return the slot here. */ + ret = dev->pci_slot; + break; - case 0x3C: /* PCI_ILR */ - pclog("AB0B:071A: IRQ now: %i\n", val); - pci_regs[addr] = val; - return; + case 0x10: /* PCI_BAR 7:5 */ + ret = (dev->pci_bar[0].addr_regs[0] & 0xe0) | 0x01; + break; + case 0x11: /* PCI_BAR 15:8 */ + ret = dev->pci_bar[0].addr_regs[1]; + break; + + case 0x3d: /* PCI_IPR */ + ret = PCI_INTA; + break; + + default: + ret = 0x00; + break; + } + +#if 0 + pclog("AB0B:071A: PCI_Read(%d, %04X) = %02X\n", func, addr, ret); +#endif + + return ret; +} + +static void +pci_dummy_pci_write(int func, int addr, uint8_t val, void *priv) +{ + pci_dummy_t *dev = (pci_dummy_t *) priv; + uint8_t valxor; + +#if 0 + pclog("AB0B:071A: PCI_Write(%d, %04X, %02X)\n", func, addr, val); +#endif + + if (func == 0x00) + switch (addr) { + case 0x04: /* PCI_COMMAND_LO */ + valxor = (val & 0x03) ^ dev->pci_regs[addr]; + if (valxor & PCI_COMMAND_IO) { + pci_dummy_io_remove(dev); + if ((dev->pci_bar[0].addr != 0) && (val & PCI_COMMAND_IO)) + pci_dummy_io_set(dev); + } + dev->pci_regs[addr] = val & 0x03; + break; + + case 0x10: /* PCI_BAR */ + val &= 0xe0; /* 0xe0 acc to RTL DS */ + fallthrough; + + case 0x11: /* PCI_BAR */ + /* Remove old I/O. */ + pci_dummy_io_remove(dev); + + /* Set new I/O as per PCI request. */ + dev->pci_bar[0].addr_regs[addr & 3] = val; + + /* Then let's calculate the new I/O base. */ + dev->pci_bar[0].addr &= 0xffe0; + + /* Log the new base. */ + // pclog("AB0B:071A: PCI: new I/O base is %04X\n", dev->pci_bar[0].addr); + + /* We're done, so get out of the here. */ + if (dev->pci_regs[4] & PCI_COMMAND_IO) { + if ((dev->pci_bar[0].addr) != 0) + pci_dummy_io_set(dev); + } + break; + + case 0x3c: /* PCI_ILR */ + pclog("AB0B:071A Device %02X: IRQ now: %i\n", dev->pci_slot, val); + dev->pci_regs[addr] = val; + return; + + default: + break; + } +} + +static void +pci_dummy_reset(void *priv) +{ + pci_dummy_t *dev = (pci_dummy_t *) priv; + + /* Lower the IRQ. */ + pci_dummy_interrupt(0, dev); + + /* Disable I/O and memory accesses. */ + pci_dummy_pci_write(0x00, 0x04, 0x00, dev); + + /* Zero all the registers. */ + memset(dev, 0x00, sizeof(pci_dummy_t)); +} + +static void +pci_dummy_close(void *priv) +{ + pci_dummy_t *dev = (pci_dummy_t *) priv; + + free(dev); +} + +static void * +pci_dummy_card_init(UNUSED(const device_t *info)) +{ + pci_dummy_t *dev = (pci_dummy_t *) calloc(1, sizeof(pci_dummy_t)); + + pci_add_card(PCI_ADD_NORMAL, pci_dummy_pci_read, pci_dummy_pci_write, dev, &dev->pci_slot); + + return dev; +} + +const device_t pci_dummy_device = { + .name = "Dummy Device (PCI)", + .internal_name = "pci_dummy", + .flags = DEVICE_PCI, + .local = 0, + .init = pci_dummy_card_init, + .close = pci_dummy_close, + .reset = pci_dummy_reset, + { .available = NULL }, + .speed_changed = NULL, + .force_redraw = NULL, + .config = NULL +}; + +void +pci_dummy_init(int min_slot, int max_slot, int nb_slot, int sb_slot) +{ + int j = 1; + + for (int i = min_slot; i <= max_slot; i++) { + if ((i != nb_slot) && (i != sb_slot)) { + pci_register_slot(i, PCI_CARD_NORMAL, 1, 3, 2, 4); + device_add_inst(&pci_dummy_device, j); + j++; + } } } - - -void pci_dummy_init(void) -{ - card = pci_add_card(PCI_ADD_NORMAL, pci_dummy_pci_read, pci_dummy_pci_write, NULL); - - pci_bar[0].addr_regs[0] = 0x01; - pci_regs[0x04] = 0x03; - - pci_regs[0x3D] = PCI_INTD; -} diff --git a/src/pic.c b/src/pic.c index 899029c14..82905261a 100644 --- a/src/pic.c +++ b/src/pic.c @@ -1,19 +1,21 @@ /* - * 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. + * 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. + * This file is part of the 86Box distribution. * - * Implementation of the Intel PIC chip emulation, partially - * ported from reenigne's XTCE. + * Implementation of the Intel PIC chip emulation, partially + * ported from reenigne's XTCE. * - * Authors: Andrew Jenner, - * Miran Grca, * - * Copyright 2015-2020 Andrew Jenner. - * Copyright 2016-2020 Miran Grca. + * + * Authors: Andrew Jenner, + * Miran Grca, + * + * Copyright 2015-2020 Andrew Jenner. + * Copyright 2016-2020 Miran Grca. */ #include #include @@ -35,68 +37,66 @@ #include <86box/apm.h> #include <86box/nvr.h> #include <86box/acpi.h> +#include <86box/plat_unused.h> - -enum -{ +enum { STATE_NONE = 0, STATE_ICW2, STATE_ICW3, STATE_ICW4 }; +pic_t pic; +pic_t pic2; -pic_t pic, pic2; +static pc_timer_t pic_timer; +static int shadow = 0; +static int elcr_enabled = 0; +static int tmr_inited = 0; +static int pic_pci = 0; +static int kbd_latch = 0; +static int mouse_latch = 0; -static pc_timer_t pic_timer; - -static int shadow = 0, elcr_enabled = 0, - tmr_inited = 0, latched = 0, - pic_pci = 0; - -static uint16_t smi_irq_mask = 0x0000, - smi_irq_status = 0x0000; - -static void (*update_pending)(void); +static uint16_t smi_irq_mask = 0x0000; +static uint16_t smi_irq_status = 0x0000; +static uint16_t latched_irqs = 0x0000; +static void (*update_pending)(void); #ifdef ENABLE_PIC_LOG int pic_do_log = ENABLE_PIC_LOG; - static void pic_log(const char *fmt, ...) { va_list ap; if (pic_do_log) { - va_start(ap, fmt); - pclog_ex(fmt, ap); - va_end(ap); + va_start(ap, fmt); + pclog_ex(fmt, ap); + va_end(ap); } } #else -#define pic_log(fmt, ...) +# define pic_log(fmt, ...) #endif - void pic_reset_smi_irq_mask(void) { smi_irq_mask = 0x0000; } - void pic_set_smi_irq_mask(int irq, int set) { if ((irq >= 0) && (irq <= 15)) { - if (set) - smi_irq_mask |= (1 << irq); - else - smi_irq_mask &= ~(1 << irq); + if (set) + smi_irq_mask |= (1 << irq); + else + smi_irq_mask &= ~(1 << irq); } } @@ -106,15 +106,13 @@ pic_get_smi_irq_status(void) return smi_irq_status; } - void pic_clear_smi_irq_status(int irq) { if ((irq >= 0) && (irq <= 15)) - smi_irq_status &= ~(1 << irq); + smi_irq_status &= ~(1 << irq); } - void pic_elcr_write(uint16_t port, uint8_t val, void *priv) { @@ -123,157 +121,139 @@ pic_elcr_write(uint16_t port, uint8_t val, void *priv) pic_log("ELCR%i: WRITE %02X\n", port & 1, val); if (port & 1) - val &= 0xde; + val &= 0xde; else - val &= 0xf8; + val &= 0xf8; dev->elcr = val; pic_log("ELCR %i: %c %c %c %c %c %c %c %c\n", - port & 1, - (val & 1) ? 'L' : 'E', - (val & 2) ? 'L' : 'E', - (val & 4) ? 'L' : 'E', - (val & 8) ? 'L' : 'E', - (val & 0x10) ? 'L' : 'E', - (val & 0x20) ? 'L' : 'E', - (val & 0x40) ? 'L' : 'E', - (val & 0x80) ? 'L' : 'E'); + port & 1, + (val & 1) ? 'L' : 'E', + (val & 2) ? 'L' : 'E', + (val & 4) ? 'L' : 'E', + (val & 8) ? 'L' : 'E', + (val & 0x10) ? 'L' : 'E', + (val & 0x20) ? 'L' : 'E', + (val & 0x40) ? 'L' : 'E', + (val & 0x80) ? 'L' : 'E'); } - uint8_t -pic_elcr_read(uint16_t port, void *priv) +pic_elcr_read(UNUSED(uint16_t port), void *priv) { - pic_t *dev = (pic_t *) priv; + const pic_t *dev = (pic_t *) priv; pic_log("ELCR%i: READ %02X\n", port & 1, dev->elcr); return dev->elcr; } - int pic_elcr_get_enabled(void) { return elcr_enabled; } - void pic_elcr_set_enabled(int enabled) { elcr_enabled = enabled; } - void pic_elcr_io_handler(int set) { io_handler(set, 0x04d0, 0x0001, - pic_elcr_read, NULL, NULL, - pic_elcr_write, NULL, NULL, &pic); + pic_elcr_read, NULL, NULL, + pic_elcr_write, NULL, NULL, &pic); io_handler(set, 0x04d1, 0x0001, - pic_elcr_read, NULL, NULL, - pic_elcr_write, NULL, NULL, &pic2); + pic_elcr_read, NULL, NULL, + pic_elcr_write, NULL, NULL, &pic2); } - static uint8_t pic_cascade_mode(pic_t *dev) { return !(dev->icw1 & 2); } - static __inline uint8_t pic_slave_on(pic_t *dev, int channel) { pic_log("pic_slave_on(%i): %i, %02X, %02X\n", channel, pic_cascade_mode(dev), dev->icw4 & 0x0c, dev->icw3 & (1 << channel)); - return pic_cascade_mode(dev) && (dev->is_master || ((dev->icw4 & 0x0c) == 0x0c)) && - (dev->icw3 & (1 << channel)); + return pic_cascade_mode(dev) && (dev->is_master || ((dev->icw4 & 0x0c) == 0x0c)) && (dev->icw3 & (1 << channel)); } - static __inline int find_best_interrupt(pic_t *dev) { uint8_t b; uint8_t intr; - int i, j; - int ret = -1; + uint8_t j; + int8_t ret = -1; - for (i = 0; i < 8; i++) { - j = (i + dev->priority) & 7; - b = 1 << j; + for (uint8_t i = 0; i < 8; i++) { + j = (i + dev->priority) & 7; + b = 1 << j; - if (dev->isr & b) - break; - else if ((dev->state == 0) && ((dev->irr & ~dev->imr) & b)) { - ret = j; - break; - } + if (dev->isr & b) + break; + else if ((dev->state == 0) && ((dev->irr & ~dev->imr) & b)) { + ret = j; + break; + } } intr = dev->interrupt = (ret == -1) ? 0x17 : ret; - if (dev->at && (ret != 1)) { - if (dev == &pic2) - intr += 8; + if (dev->at && (ret != -1)) { + if (dev == &pic2) + intr += 8; - if (cpu_fast_off_flags & (1 << intr)) - cpu_fast_off_count = cpu_fast_off_val + 1; + if (cpu_fast_off_flags & (1u << intr)) + cpu_fast_off_advance(); } return ret; } - static __inline void pic_update_pending_xt(void) { - if (find_best_interrupt(&pic) != -1) { - latched++; - if (latched == 1) - timer_on_auto(&pic_timer, 0.35); - } else if (latched == 0) - pic.int_pending = 0; + if (!(pic.interrupt & 0x20)) + pic.int_pending = (find_best_interrupt(&pic) != -1); } - +/* Only check if PIC 1 frozen, because it should not happen + that one is frozen but the other is not. */ static __inline void pic_update_pending_at(void) { - pic2.int_pending = (find_best_interrupt(&pic2) != -1); + if (!(pic.interrupt & 0x20)) { + pic2.int_pending = (find_best_interrupt(&pic2) != -1); + + if (pic2.int_pending) + pic.irr |= (1 << pic2.icw3); + else + pic.irr &= ~(1 << pic2.icw3); - if (pic2.int_pending) - pic.irr |= (1 << pic2.icw3); - else - pic.irr &= ~(1 << pic2.icw3); - - pic.int_pending = (find_best_interrupt(&pic) != -1); + pic.int_pending = (find_best_interrupt(&pic) != -1); + } } - static void pic_callback(void *priv) { - pic_t *dev = (pic_t *) priv; - - dev->int_pending = 1; - - latched--; - if (latched > 0) - timer_on_auto(&pic_timer, 0.35); + update_pending(); } - void -pic_reset() +pic_reset(void) { int is_at = IS_AT(machine); - is_at = is_at || !strcmp(machine_get_internal_name(), "xi8088"); + is_at = is_at || !strcmp(machine_get_internal_name(), "xi8088"); memset(&pic, 0, sizeof(pic_t)); memset(&pic2, 0, sizeof(pic_t)); @@ -282,10 +262,10 @@ pic_reset() pic.interrupt = pic2.interrupt = 0x17; if (is_at) - pic.slaves[2] = &pic2; + pic.slaves[2] = &pic2; if (tmr_inited) - timer_on_auto(&pic_timer, 0.0); + timer_on_auto(&pic_timer, 0.0); memset(&pic_timer, 0x00, sizeof(pc_timer_t)); timer_add(&pic_timer, pic_callback, &pic, 0); tmr_inited = 1; @@ -295,17 +275,21 @@ pic_reset() smi_irq_mask = smi_irq_status = 0x0000; - shadow = 0; + shadow = 0; pic_pci = 0; } - void pic_set_shadow(int sh) { shadow = sh; } +int +pic_get_pci_flag(void) +{ + return pic_pci; +} void pic_set_pci_flag(int pci) @@ -313,58 +297,54 @@ pic_set_pci_flag(int pci) pic_pci = pci; } - static uint8_t pic_level_triggered(pic_t *dev, int irq) { if (elcr_enabled) - return !!(dev->elcr & (1 << irq)); + return !!(dev->elcr & (1 << irq)); else - return !!(dev->icw1 & 8); + return !!(dev->icw1 & 8); } - int picint_is_level(int irq) { return pic_level_triggered(((irq > 7) ? &pic2 : &pic), irq & 7); } - static void pic_acknowledge(pic_t *dev) { - int pic_int = dev->interrupt & 7; + int pic_int = dev->interrupt & 7; int pic_int_num = 1 << pic_int; dev->isr |= pic_int_num; - if (!pic_level_triggered(dev, pic_int) || !(dev->lines & pic_int_num)) - dev->irr &= ~pic_int_num; + if (!pic_level_triggered(dev, pic_int) || (dev->lines[pic_int] == 0)) + dev->irr &= ~pic_int_num; } - /* Find IRQ for non-specific EOI (either by command or automatic) by finding the highest IRQ priority with ISR bit set, that is also not masked if the PIC is in special mask mode. */ static uint8_t pic_non_specific_find(pic_t *dev) { - int i, j; - uint8_t b, irq = 0xff; + uint8_t j; + uint8_t b; + uint8_t irq = 0xff; - for (i = 0; i < 8; i++) { - j = (i + dev->priority) & 7; - b = (1 << j); + for (uint8_t i = 0; i < 8; i++) { + j = (i + dev->priority) & 7; + b = (1 << j); - if ((dev->isr & b) && (!dev->special_mask_mode || !(dev->imr & b))) { - irq = j; - break; - } + if ((dev->isr & b) && (!dev->special_mask_mode || !(dev->imr & b))) { + irq = j; + break; + } } return irq; } - /* Do the EOI and rotation, if either is requested, on the given IRQ. */ static void pic_action(pic_t *dev, uint8_t irq, uint8_t eoi, uint8_t rotate) @@ -372,16 +352,15 @@ pic_action(pic_t *dev, uint8_t irq, uint8_t eoi, uint8_t rotate) uint8_t b = (1 << irq); if (irq != 0xff) { - if (eoi) - dev->isr &= ~b; - if (rotate) - dev->priority = (irq + 1) & 7; + if (eoi) + dev->isr &= ~b; + if (rotate) + dev->priority = (irq + 1) & 7; - update_pending(); + update_pending(); } } - /* Automatic non-specific EOI. */ static __inline void pic_auto_non_specific_eoi(pic_t *dev) @@ -389,30 +368,87 @@ pic_auto_non_specific_eoi(pic_t *dev) uint8_t irq; if (dev->icw4 & 2) { - irq = pic_non_specific_find(dev); + irq = pic_non_specific_find(dev); - pic_action(dev, irq, 1, dev->auto_eoi_rotate); + pic_action(dev, irq, 1, dev->auto_eoi_rotate); } } - /* Do the PIC command specified by bits 7-5 of the value written to the OCW2 register. */ static void pic_command(pic_t *dev) { uint8_t irq = 0xff; - if (dev->ocw2 & 0x60) { /* SL and/or EOI set */ - if (dev->ocw2 & 0x40) /* SL set, specific priority level */ - irq = (dev->ocw2 & 0x07); - else /* SL clear, non-specific priority level (find highest with ISR set) */ - irq = pic_non_specific_find(dev); + if (dev->ocw2 & 0x60) { /* SL and/or EOI set */ + if (dev->ocw2 & 0x40) /* SL set, specific priority level */ + irq = (dev->ocw2 & 0x07); + else /* SL clear, non-specific priority level (find highest with ISR set) */ + irq = pic_non_specific_find(dev); pic_action(dev, irq, dev->ocw2 & 0x20, dev->ocw2 & 0x80); - } else /* SL and EOI clear */ - dev->auto_eoi_rotate = !!(dev->ocw2 & 0x80); + } else /* SL and EOI clear */ + dev->auto_eoi_rotate = !!(dev->ocw2 & 0x80); } +uint8_t +pic_latch_read(UNUSED(uint16_t addr), UNUSED(void *priv)) +{ + uint8_t ret = 0xff; + + pic_log("pic_latch_read(%i, %i)\n", kbd_latch, mouse_latch); + + if (kbd_latch && (latched_irqs & 0x0002)) + picintc(0x0002); + + if (mouse_latch && (latched_irqs & 0x1000)) + picintc(0x1000); + + /* Return FF - we just lower IRQ 1 and IRQ 12. */ + return ret; +} + +uint8_t +pic_read_icw(uint8_t pic_id, uint8_t icw) +{ + pic_t *dev = pic_id ? &pic2 : &pic; + uint8_t ret = 0xff; + + switch (icw) { + case 0x00: + ret = dev->icw1; + break; + case 0x01: + ret = dev->icw2; + break; + case 0x02: + ret = dev->icw3; + break; + case 0x03: + ret = dev->icw4; + break; + } + + return ret; +} + +uint8_t +pic_read_ocw(uint8_t pic_id, uint8_t ocw) +{ + pic_t *dev = pic_id ? &pic2 : &pic; + uint8_t ret = 0xff; + + switch (ocw) { + case 0x00: + ret = dev->ocw2; + break; + case 0x01: + ret = dev->ocw3; + break; + } + + return ret; +} uint8_t pic_read(uint16_t addr, void *priv) @@ -420,43 +456,44 @@ pic_read(uint16_t addr, void *priv) pic_t *dev = (pic_t *) priv; if (shadow) { - /* VIA PIC shadow read */ - if (addr & 0x0001) - dev->data_bus = ((dev->icw2 & 0xf8) >> 3) << 0; - else { - dev->data_bus = ((dev->ocw3 & 0x20) >> 5) << 4; - dev->data_bus |= ((dev->ocw2 & 0x80) >> 7) << 3; - dev->data_bus |= ((dev->icw4 & 0x10) >> 4) << 2; - dev->data_bus |= ((dev->icw4 & 0x02) >> 1) << 1; - dev->data_bus |= ((dev->icw4 & 0x08) >> 3) << 0; - } + /* VIA PIC shadow read */ + if (addr & 0x0001) + dev->data_bus = ((dev->icw2 & 0xf8) >> 3) << 0; + else { + dev->data_bus = ((dev->ocw3 & 0x20) >> 5) << 4; + dev->data_bus |= ((dev->ocw2 & 0x80) >> 7) << 3; + dev->data_bus |= ((dev->icw4 & 0x10) >> 4) << 2; + dev->data_bus |= ((dev->icw4 & 0x02) >> 1) << 1; + dev->data_bus |= ((dev->icw4 & 0x08) >> 3) << 0; + } } else { - /* Standard 8259 PIC read */ + /* Standard 8259 PIC read */ #ifndef UNDEFINED_READ - /* Put the IRR on to the data bus by default until the real PIC is probed. */ - dev->data_bus = dev->irr; + /* Put the IRR on to the data bus by default until the real PIC is probed. */ + dev->data_bus = dev->irr; #endif - if (dev->ocw3 & 0x04) { - if (dev->int_pending) { - dev->data_bus = 0x80 | (dev->interrupt & 7); - pic_acknowledge(dev); - dev->int_pending = 0; - update_pending(); - } else - dev->data_bus = 0x00; - dev->ocw3 &= ~0x04; - } else if (addr & 0x0001) - dev->data_bus = dev->imr; - else if (dev->ocw3 & 0x02) { - if (dev->ocw3 & 0x01) - dev->data_bus = dev->isr; + if (dev->ocw3 & 0x04) { + dev->interrupt &= ~0x20; /* Freeze the interrupt until the poll is over. */ + if (dev->int_pending) { + dev->data_bus = 0x80 | (dev->interrupt & 7); + pic_acknowledge(dev); + dev->int_pending = 0; + update_pending(); + } else + dev->data_bus = 0x00; + dev->ocw3 &= ~0x04; + } else if (addr & 0x0001) + dev->data_bus = dev->imr; + else if (dev->ocw3 & 0x02) { + if (dev->ocw3 & 0x01) + dev->data_bus = dev->isr; #ifdef UNDEFINED_READ - else - dev->data_bus = 0x00; + else + dev->data_bus = 0x00; #endif - } - /* If A0 = 0, VIA shadow is disabled, and poll mode is disabled, - simply read whatever is currently on the data bus. */ + } + /* If A0 = 0, VIA shadow is disabled, and poll mode is disabled, + simply read whatever is currently on the data bus. */ } pic_log("pic_read(%04X, %08X) = %02X\n", addr, priv, dev->data_bus); @@ -464,7 +501,6 @@ pic_read(uint16_t addr, void *priv) return dev->data_bus; } - static void pic_write(uint16_t addr, uint8_t val, void *priv) { @@ -475,95 +511,150 @@ pic_write(uint16_t addr, uint8_t val, void *priv) dev->data_bus = val; if (addr & 0x0001) { - switch (dev->state) { - case STATE_ICW2: - dev->icw2 = val; - if (pic_cascade_mode(dev)) - dev->state = STATE_ICW3; - else - dev->state = (dev->icw1 & 1) ? STATE_ICW4 : STATE_NONE; - break; - case STATE_ICW3: - dev->icw3 = val; - dev->state = (dev->icw1 & 1) ? STATE_ICW4 : STATE_NONE; - break; - case STATE_ICW4: - dev->icw4 = val; - dev->state = STATE_NONE; - break; - case STATE_NONE: - dev->imr = val; - update_pending(); - break; - } - } else { - if (val & 0x10) { - /* Treat any write with any of the bits 7 to 5 set as invalid if PCI. */ - if (pic_pci && (val & 0xe0)) - return; + switch (dev->state) { + case STATE_ICW2: + dev->icw2 = val; + if (pic_cascade_mode(dev)) + dev->state = STATE_ICW3; + else + dev->state = (dev->icw1 & 1) ? STATE_ICW4 : STATE_NONE; + break; + case STATE_ICW3: + dev->icw3 = val; + dev->state = (dev->icw1 & 1) ? STATE_ICW4 : STATE_NONE; + break; + case STATE_ICW4: + dev->icw4 = val; + dev->state = STATE_NONE; + break; + case STATE_NONE: + dev->imr = val; + if (is286) + update_pending(); + else + timer_on_auto(&pic_timer, .0 * ((10000000.0 * (double) xt_cpu_multi) / (double) cpu_s->rspeed)); + break; - dev->icw1 = val; - dev->icw2 = dev->icw3 = 0x00; - if (!(dev->icw1 & 1)) - dev->icw4 = 0x00; - dev->ocw2 = dev->ocw3 = 0x00; - dev->irr = dev->lines; - dev->imr = dev->isr = 0x00; - dev->ack_bytes = dev->priority = 0x00; - dev->auto_eoi_rotate = dev->special_mask_mode = 0x00; - dev->interrupt = 0x17; - dev->int_pending = 0x00; - dev->state = STATE_ICW2; - update_pending(); - } else if (val & 0x08) { - dev->ocw3 = val; - if (dev->ocw3 & 0x40) - dev->special_mask_mode = !!(dev->ocw3 & 0x20); - } else { - dev->ocw2 = val; - pic_command(dev); - } + default: + break; + } + } else { + if (val & 0x10) { + /* Treat any write with any of the bits 7 to 5 set as invalid if PCI. */ + if (pic_pci && (val & 0xe0)) + return; + + dev->icw1 = val; + dev->icw2 = dev->icw3 = 0x00; + if (!(dev->icw1 & 1)) + dev->icw4 = 0x00; + dev->ocw2 = dev->ocw3 = 0x00; + dev->irr = 0x00; + for (uint8_t i = 0; i <= 7; i++) { + if (dev->lines[i] > 0) + dev->irr |= (1 << i); + } + dev->imr = dev->isr = 0x00; + dev->ack_bytes = dev->priority = 0x00; + dev->auto_eoi_rotate = dev->special_mask_mode = 0x00; + dev->interrupt = 0x17; + dev->int_pending = 0x00; + dev->state = STATE_ICW2; + update_pending(); + } else if (val & 0x08) { + dev->ocw3 = val; + if (dev->ocw3 & 0x04) + dev->interrupt |= 0x20; /* Freeze the interrupt until the poll is over. */ + if (dev->ocw3 & 0x40) + dev->special_mask_mode = !!(dev->ocw3 & 0x20); + } else { + dev->ocw2 = val; + pic_command(dev); + } } } - void pic_set_pci(void) { - int i; - - for (i = 0x0024; i < 0x0040; i += 4) { - io_sethandler(i, 0x0002, pic_read, NULL, NULL, pic_write, NULL, NULL, &pic); - io_sethandler(i + 0x0080, 0x0002, pic_read, NULL, NULL, pic_write, NULL, NULL, &pic2); + for (uint8_t i = 0x0024; i < 0x0040; i += 4) { + io_sethandler(i, 0x0002, pic_read, NULL, NULL, pic_write, NULL, NULL, &pic); + io_sethandler(i + 0x0080, 0x0002, pic_read, NULL, NULL, pic_write, NULL, NULL, &pic2); } - for (i = 0x1120; i < 0x1140; i += 4) { - io_sethandler(i, 0x0002, pic_read, NULL, NULL, pic_write, NULL, NULL, &pic); - io_sethandler(i + 0x0080, 0x0002, pic_read, NULL, NULL, pic_write, NULL, NULL, &pic2); + for (uint16_t i = 0x1120; i < 0x1140; i += 4) { + io_sethandler(i, 0x0002, pic_read, NULL, NULL, pic_write, NULL, NULL, &pic); + io_sethandler(i + 0x0080, 0x0002, pic_read, NULL, NULL, pic_write, NULL, NULL, &pic2); } } +void +pic_kbd_latch(int enable) +{ + pic_log("PIC keyboard latch now %sabled\n", enable ? "en" : "dis"); + + if (!!(enable | mouse_latch) != !!(kbd_latch | mouse_latch)) + io_handler(!!(enable | mouse_latch), 0x0060, 0x0001, pic_latch_read, NULL, NULL, NULL, NULL, NULL, NULL); + + kbd_latch = !!enable; + + if (!enable) + picintc(0x0002); +} + +void +pic_mouse_latch(int enable) +{ + pic_log("PIC mouse latch now %sabled\n", enable ? "en" : "dis"); + + if (!!(kbd_latch | enable) != !!(kbd_latch | mouse_latch)) + io_handler(!!(kbd_latch | enable), 0x0060, 0x0001, pic_latch_read, NULL, NULL, NULL, NULL, NULL, NULL); + + mouse_latch = !!enable; + + if (!enable) + picintc(0x1000); +} + +static void +pic_reset_hard(void) +{ + pic_reset(); + + /* Explicitly reset the latches. */ + kbd_latch = mouse_latch = 0; + latched_irqs = 0x0000; + + /* The situation is as follows: There is a giant mess when it comes to these latches on real hardware, + to the point that there's even boards with board-level latched that get used in place of the latches + on the chipset, therefore, I'm just doing this here for the sake of simplicity. */ + if (machine_has_bus(machine, MACHINE_BUS_PS2_LATCH)) { + pic_kbd_latch(0x01); + pic_mouse_latch(0x01); + } else { + pic_kbd_latch(0x00); + pic_mouse_latch(0x00); + } +} void pic_init(void) { - pic_reset(); + pic_reset_hard(); shadow = 0; io_sethandler(0x0020, 0x0002, pic_read, NULL, NULL, pic_write, NULL, NULL, &pic); } - void pic_init_pcjr(void) { - pic_reset(); + pic_reset_hard(); shadow = 0; io_sethandler(0x0020, 0x0008, pic_read, NULL, NULL, pic_write, NULL, NULL, &pic); } - void pic2_init(void) { @@ -571,201 +662,238 @@ pic2_init(void) pic.slaves[2] = &pic2; } - void -picint_common(uint16_t num, int level, int set) +picint_common(uint16_t num, int level, int set, uint8_t *irq_state) { - int i, raise; - uint8_t b, slaves = 0; + int raise; + int max = 16; + uint8_t b; + uint8_t slaves = 0; + uint16_t w; + uint16_t lines = level ? 0x0000 : num; + pic_t *dev; /* Make sure to ignore all slave IRQ's, and in case of AT+, translate IRQ 2 to IRQ 9. */ - for (i = 0; i < 8; i++) { - b = (1 << i); - raise = num & b; + for (uint8_t i = 0; i < 8; i++) { + b = (uint8_t) (1 << i); + raise = num & b; - if (pic.icw3 & b) { - slaves++; + if (pic.icw3 & b) { + slaves++; - if (raise) { - num &= ~b; - if (pic.at && (i == 2)) - num |= (1 << 9); - } - } + if (raise) { + num &= ~b; + if (pic.at && (i == 2)) + num |= (1 << 9); + } + } } if (!slaves) - num &= 0x00ff; + max = 8; if (!num) { - pic_log("Attempting to %s null IRQ\n", set ? "raise" : "lower"); - return; + pic_log("Attempting to %s null IRQ\n", set ? "raise" : "lower"); + return; } - if (num & 0x0100) - acpi_rtc_status = !!set; + if (level) { + dev = &pic; - if (set) { - if (smi_irq_mask & num) { - smi_line = 1; - smi_irq_status |= num; - } + for (uint16_t i = 0; i < max; i++) { + if (i == 8) + dev = &pic2; - if (num & 0xff00) { - if (level) - pic2.lines |= (num >> 8); + b = i & 7; + w = 1 << i; - pic2.irr |= (num >> 8); - } + if (num & w) { + if ((!!*irq_state) != !!set) + set ? dev->lines[b]++ : dev->lines[b]--; - if (num & 0x00ff) { - if (level) - pic.lines |= (num >> 8); + if (!pic_level_triggered(dev, b) || + (((!!*irq_state) != !!set) && (dev->lines[b] == (!!set)))) + lines |= w; + } + } - pic.irr |= num; - } - } else { - smi_irq_status &= ~num; + if ((!!*irq_state) != !!set) + *irq_state = set; - if (num & 0xff00) { - pic2.lines &= ~(num >> 8); - pic2.irr &= ~(num >> 8); - } + num = lines; + } - if (num & 0x00ff) { - pic.lines &= ~num; - pic.irr &= ~num; - } + if (!slaves) + num &= 0x00ff; + + if (num & 0x0100) + acpi_rtc_status = !!set; + + if (num) { + if (set) { + if (smi_irq_mask & num) { + smi_raise(); + smi_irq_status |= num; + } + + if (num & 0xff00) { + /* Latch IRQ 12 if the mouse latch is enabled. */ + if ((num & 0x1000) && mouse_latch) + latched_irqs |= 0x1000; + + pic2.irr |= (num >> 8); + } + + if (num & 0x00ff) { + /* Latch IRQ 1 if the keyboard latch is enabled. */ + if (kbd_latch && (num & 0x0002)) + latched_irqs |= 0x0002; + + pic.irr |= (num & 0x00ff); + } + } else { + smi_irq_status &= ~num; + + if (num & 0xff00) { + /* Unlatch IRQ 12 if the mouse latch is enabled. */ + if ((num & 0x1000) && mouse_latch) + latched_irqs &= 0xefff; + + pic2.irr &= ~(num >> 8); + } + + if (num & 0x00ff) { + /* Unlatch IRQ 1 if the keyboard latch is enabled. */ + if (kbd_latch && (num & 0x0002)) + latched_irqs &= 0xfffd; + + pic.irr &= ~(num & 0x00ff); + } + } + + update_pending(); } - - if (!(pic.interrupt & 0x20) && !(pic2.interrupt & 0x20)) - update_pending(); } - -void -picint(uint16_t num) -{ - picint_common(num, 0, 1); -} - - -void -picintlevel(uint16_t num) -{ - picint_common(num, 1, 1); -} - - -void -picintc(uint16_t num) -{ - picint_common(num, 0, 0); -} - - static uint8_t pic_i86_mode(pic_t *dev) { return !!(dev->icw4 & 1); } - static uint8_t pic_irq_ack_read(pic_t *dev, int phase) { - uint8_t intr = dev->interrupt & 0x47; + uint8_t intr = dev->interrupt & 0x47; uint8_t slave = intr & 0x40; intr &= 0x07; pic_log(" pic_irq_ack_read(%08X, %i)\n", dev, phase); if (dev != NULL) { - if (phase == 0) { - dev->interrupt |= 0x20; /* Freeze it so it still takes interrupts but they do not - override the one currently being processed. */ - pic_acknowledge(dev); - if (slave) - dev->data_bus = pic_irq_ack_read(dev->slaves[intr], phase); - else - dev->data_bus = pic_i86_mode(dev) ? 0xff : 0xcd; - } else if (pic_i86_mode(dev)) { - dev->int_pending = 0; - if (slave) - dev->data_bus = pic_irq_ack_read(dev->slaves[intr], phase); - else - dev->data_bus = intr + (dev->icw2 & 0xf8); - pic_auto_non_specific_eoi(dev); - } else if (phase == 1) { - if (slave) - dev->data_bus = pic_irq_ack_read(dev->slaves[intr], phase); - else if (dev->icw1 & 0x04) - dev->data_bus = (intr << 2) + (dev->icw1 & 0xe0); - else - dev->data_bus = (intr << 3) + (dev->icw1 & 0xc0); - } else if (phase == 2) { - dev->int_pending = 0; - if (slave) - dev->data_bus = pic_irq_ack_read(dev->slaves[intr], phase); - else - dev->data_bus = dev->icw2; - pic_auto_non_specific_eoi(dev); - } + if (phase == 0) { + dev->interrupt |= 0x20; /* Freeze it so it still takes interrupts but they do not + override the one currently being processed. */ + pic_acknowledge(dev); + if (slave) + dev->data_bus = pic_irq_ack_read(dev->slaves[intr], phase); + else + dev->data_bus = pic_i86_mode(dev) ? 0xff : 0xcd; + } else if (pic_i86_mode(dev)) { + dev->int_pending = 0; + if (slave) + dev->data_bus = pic_irq_ack_read(dev->slaves[intr], phase); + else + dev->data_bus = intr + (dev->icw2 & 0xf8); + pic_auto_non_specific_eoi(dev); + } else if (phase == 1) { + if (slave) + dev->data_bus = pic_irq_ack_read(dev->slaves[intr], phase); + else if (dev->icw1 & 0x04) + dev->data_bus = (intr << 2) + (dev->icw1 & 0xe0); + else + dev->data_bus = (intr << 3) + (dev->icw1 & 0xc0); + } else if (phase == 2) { + dev->int_pending = 0; + if (slave) + dev->data_bus = pic_irq_ack_read(dev->slaves[intr], phase); + else + dev->data_bus = dev->icw2; + pic_auto_non_specific_eoi(dev); + } } return dev->data_bus; } - uint8_t pic_irq_ack(void) { - int ret; + uint8_t ret; - ret = pic_irq_ack_read(&pic, pic.ack_bytes); + /* Needed for Xi8088. */ + if ((pic.ack_bytes == 0) && pic.int_pending && pic_slave_on(&pic, pic.interrupt)) { + if (!pic.slaves[pic.interrupt]->int_pending) { + /* If we are on AT, IRQ 2 is pending, and we cannot find a pending IRQ on PIC 2, fatal out. */ + fatal("IRQ %i pending on AT without a pending IRQ on PIC %i (normal)\n", pic.interrupt, pic.interrupt); + exit(-1); + } + + pic.interrupt |= 0x40; /* Mark slave pending. */ + } + + ret = pic_irq_ack_read(&pic, pic.ack_bytes); pic.ack_bytes = (pic.ack_bytes + 1) % (pic_i86_mode(&pic) ? 2 : 3); if (pic.ack_bytes == 0) { - pic.interrupt = 0x17; - update_pending(); + /* Needed for Xi8088. */ + if (pic.interrupt & 0x40) + pic2.interrupt = 0x17; + pic.interrupt = 0x17; + update_pending(); } return ret; } - int -picinterrupt() +picinterrupt(void) { - int i, ret = -1; + int ret = -1; if (pic.int_pending) { - if (pic_slave_on(&pic, pic.interrupt)) { - if (!pic.slaves[pic.interrupt]->int_pending) { - /* If we are on AT, IRQ 2 is pending, and we cannot find a pending IRQ on PIC 2, fatal out. */ - fatal("IRQ %i pending on AT without a pending IRQ on PIC %i (normal)\n", pic.interrupt, pic.interrupt); - exit(-1); - return -1; - } + if (pic_slave_on(&pic, pic.interrupt)) { + if (!pic.slaves[pic.interrupt]->int_pending) { + /* If we are on AT, IRQ 2 is pending, and we cannot find a pending IRQ on PIC 2, fatal out. */ + // fatal("IRQ %i pending on AT without a pending IRQ on PIC %i (normal)\n", pic.interrupt, pic.interrupt); + // exit(-1); + /* Error correction mechanism: Do a supurious IRQ 15 (spurious IRQ 7 on PIC 2). */ + pic.slaves[pic.interrupt]->int_pending = 1; + pic.slaves[pic.interrupt]->interrupt = 0x07; + } else + pic.interrupt |= 0x40; /* Mark slave pending. */ + } + } else { + /* pic.int_pending was somehow cleared despite the fact we made it here, + do a spurious IRQ 7. */ + pic.int_pending = 1; + pic.interrupt = 0x07; + } - pic.interrupt |= 0x40; /* Mark slave pending. */ - } + if ((pic.interrupt == 0) && (pit_devs[1].data != NULL)) + pit_devs[1].set_gate(pit_devs[1].data, 0, 0); - if ((pic.interrupt == 0) && (pit2 != NULL)) - pit_ctr_set_gate(&pit2->counters[0], 0); + /* Two ACK's - do them in a loop to avoid potential compiler misoptimizations. */ + for (uint8_t i = 0; i < 2; i++) { + ret = pic_irq_ack_read(&pic, pic.ack_bytes); + pic.ack_bytes = (pic.ack_bytes + 1) % (pic_i86_mode(&pic) ? 2 : 3); - /* Two ACK's - do them in a loop to avoid potential compiler misoptimizations. */ - for (i = 0; i < 2; i++) { - ret = pic_irq_ack_read(&pic, pic.ack_bytes); - pic.ack_bytes = (pic.ack_bytes + 1) % (pic_i86_mode(&pic) ? 2 : 3); - - if (pic.ack_bytes == 0) { - if (pic.interrupt & 0x40) - pic2.interrupt = 0x17; - pic.interrupt = 0x17; - update_pending(); - } - } + if (pic.ack_bytes == 0) { + if (pic.interrupt & 0x40) + pic2.interrupt = 0x17; + pic.interrupt = 0x17; + update_pending(); + } } return ret; diff --git a/src/pit.c b/src/pit.c index 5057b6efa..f5816aaf5 100644 --- a/src/pit.c +++ b/src/pit.c @@ -1,18 +1,19 @@ /* - * 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. + * 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. + * This file is part of the 86Box distribution. * - * Implementation of the Intel 8253/8254 Programmable Interval - * Timer. + * Implementation of the Intel 8253/8254 Programmable Interval + * Timer. * * * - * Author: Miran Grca, - * Copyright 2019 Miran Grca. + * Authors: Miran Grca, + * + * Copyright 2019 Miran Grca. */ #include #include @@ -34,105 +35,102 @@ #include <86box/pic.h> #include <86box/timer.h> #include <86box/pit.h> +#include <86box/pit_fast.h> #include <86box/ppi.h> #include <86box/machine.h> #include <86box/sound.h> #include <86box/snd_speaker.h> #include <86box/video.h> +#include <86box/plat_unused.h> +pit_intf_t pit_devs[2]; -pit_t *pit, *pit2; -double cpuclock, PITCONSTD, - SYSCLK, - isa_timing, - bus_timing, pci_timing, agp_timing, - PCICLK, AGPCLK; +double cpuclock; +double PITCONSTD; +double SYSCLK; +double isa_timing; +double bus_timing; +double pci_timing; +double agp_timing; +double PCICLK; +double AGPCLK; -uint64_t PITCONST, ISACONST, - CGACONST, - MDACONST, HERCCONST, - VGACONST1, VGACONST2, - RTCCONST, ACPICONST; +uint64_t PITCONST; +uint64_t ISACONST; +uint64_t CGACONST; +uint64_t MDACONST; +uint64_t HERCCONST; +uint64_t VGACONST1; +uint64_t VGACONST2; +uint64_t RTCCONST; +uint64_t ACPICONST; -int refresh_at_enable = 1, - io_delay = 5; +int refresh_at_enable = 1; +int io_delay = 5; +int64_t firsttime = 1; -int64_t firsttime = 1; - - -#define PIT_PS2 16 /* The PIT is the PS/2's second PIT. */ -#define PIT_EXT_IO 32 /* The PIT has externally specified port I/O. */ -#define PIT_CUSTOM_CLOCK 64 /* The PIT uses custom clock inputs provided by another provider. */ -#define PIT_SECONDARY 128 /* The PIT is secondary (ports 0048-004B). */ - - -enum { - PIT_8253 = 0, - PIT_8254 -}; - +#define PIT_PS2 16 /* The PIT is the PS/2's second PIT. */ +#define PIT_EXT_IO 32 /* The PIT has externally specified port I/O. */ +#define PIT_CUSTOM_CLOCK 64 /* The PIT uses custom clock inputs provided by another provider. */ +#define PIT_SECONDARY 128 /* The PIT is secondary (ports 0048-004B). */ #ifdef ENABLE_PIT_LOG int pit_do_log = ENABLE_PIT_LOG; - static void pit_log(const char *fmt, ...) { va_list ap; if (pit_do_log) { - va_start(ap, fmt); - pclog_ex(fmt, ap); - va_end(ap); + va_start(ap, fmt); + pclog_ex(fmt, ap); + va_end(ap); } } #else -#define pit_log(fmt, ...) +# define pit_log(fmt, ...) #endif - static void ctr_set_out(ctr_t *ctr, int out) { if (ctr == NULL) - return; + return; if (ctr->out_func != NULL) - ctr->out_func(out, ctr->out); + ctr->out_func(out, ctr->out); ctr->out = out; } - static void ctr_decrease_count(ctr_t *ctr) { if (ctr->bcd) { - ctr->units--; - if (ctr->units == -1) { - ctr->units = -7; - ctr->tens--; - if (ctr->tens == -1) { - ctr->tens = -7; - ctr->hundreds--; - if (ctr->hundreds == -1) { - ctr->hundreds = -7; - ctr->thousands--; - if (ctr->thousands == -1) { - ctr->thousands = -7; - ctr->myriads--; - if (ctr->myriads == -1) - ctr->myriads = -7; /* 0 - 1 should wrap around to 9999. */ - } - } - } - } + ctr->units--; + if (ctr->units == -1) { + ctr->units = -7; + ctr->tens--; + if (ctr->tens == -1) { + ctr->tens = -7; + ctr->hundreds--; + if (ctr->hundreds == -1) { + ctr->hundreds = -7; + ctr->thousands--; + if (ctr->thousands == -1) { + ctr->thousands = -7; + ctr->myriads--; + if (ctr->myriads == -1) + ctr->myriads = -7; /* 0 - 1 should wrap around to 9999. */ + } + } + } + } } else - ctr->count = (ctr->count - 1) & 0xffff; + ctr->count = (ctr->count - 1) & 0xffff; } - static void ctr_load_count(ctr_t *ctr) { @@ -141,297 +139,330 @@ ctr_load_count(ctr_t *ctr) ctr->count = l; pit_log("ctr->count = %i\n", l); ctr->null_count = 0; - ctr->newcount = !!(l & 1); -} + ctr->newcount = !!(l & 1); + /* Undocumented feature - writing MSB after reload after writing LSB causes an instant reload. */ + ctr->incomplete = !!(ctr->wm & 0x80); +} static void ctr_tick(ctr_t *ctr) { uint8_t state = ctr->state; - if (state == 1) { - /* This is true for all modes */ - ctr_load_count(ctr); - ctr->state = 2; - if ((ctr->m & 0x07) == 0x01) - ctr_set_out(ctr, 0); - return; - } + if ((state & 0x03) == 0x01) { + /* This is true for all modes */ + ctr_load_count(ctr); + ctr->state++; + if (((ctr->m & 0x07) == 0x01) && (ctr->state == 2)) + ctr_set_out(ctr, 0); + } else switch (ctr->m & 0x07) { + case 0: + /* Interrupt on terminal count */ + switch (state) { + case 2: + if (ctr->gate && (ctr->count >= 1)) { + ctr_decrease_count(ctr); + if (ctr->count < 1) { + ctr->state = 3; + ctr_set_out(ctr, 1); + } + } + break; + case 3: + ctr_decrease_count(ctr); + break; - switch(ctr->m & 0x07) { - case 0: - /* Interrupt on terminal count */ - switch (state) { - case 2: - if (ctr->gate && (ctr->count >= 1)) { - ctr_decrease_count(ctr); - if (ctr->count < 1) { - ctr->state = 3; - ctr_set_out(ctr, 1); - } - } - break; - case 3: - ctr_decrease_count(ctr); - break; - } - break; - case 1: - /* Hardware retriggerable one-shot */ - switch (state) { - case 1: - ctr_load_count(ctr); - ctr->state = 2; - ctr_set_out(ctr, 0); - break; - case 2: - if (ctr->count >= 1) { - ctr_decrease_count(ctr); - if (ctr->count < 1) { - ctr->state = 3; - ctr_set_out(ctr, 1); - } - } - break; - case 3: - ctr_decrease_count(ctr); - break; - } - break; - case 2: case 6: - /* Rate generator */ - switch (state) { - case 3: - ctr_load_count(ctr); - ctr->state = 2; - ctr_set_out(ctr, 1); - break; - case 2: - if (ctr->gate == 0) - break; - else if (ctr->count >= 2) { - ctr_decrease_count(ctr); - if (ctr->count < 2) { - ctr->state = 3; - ctr_set_out(ctr, 0); - } - } - break; - } - break; - case 3: case 7: - /* Square wave mode */ - switch (state) { - case 2: - if (ctr->gate == 0) - break; - else if (ctr->count >= 0) { - if (ctr->bcd) { - ctr_decrease_count(ctr); - if (!ctr->newcount) - ctr_decrease_count(ctr); - } else - ctr->count -= (ctr->newcount ? 1 : 2); - if (ctr->count < 0) { - ctr_load_count(ctr); - ctr->state = 3; - ctr_set_out(ctr, 0); - } else if (ctr->newcount) - ctr->newcount = 0; - } - break; - case 3: - if (ctr->gate == 0) - break; - else if (ctr->count >= 0) { - if (ctr->bcd) { - ctr_decrease_count(ctr); - ctr_decrease_count(ctr); - if (ctr->newcount) - ctr_decrease_count(ctr); - } else - ctr->count -= (ctr->newcount ? 3 : 2); - if (ctr->count < 0) { - ctr_load_count(ctr); - ctr->state = 2; - ctr_set_out(ctr, 1); - } else if (ctr->newcount) - ctr->newcount = 0; - } - break; - } - break; - case 4: case 5: - /* Software triggered strobe */ - /* Hardware triggered strobe */ - if ((ctr->gate != 0) || (ctr->m != 4)) { - switch(state) { - case 0: - ctr_decrease_count(ctr); - break; - case 2: - if (ctr->count >= 1) { - ctr_decrease_count(ctr); - if (ctr->count < 1) { - ctr->state = 3; - ctr_set_out(ctr, 0); - } - } - break; - case 3: - ctr->state = 0; - ctr_set_out(ctr, 1); - break; - } - } - break; - default: - break; + default: + break; + } + break; + case 1: + /* Hardware retriggerable one-shot */ + switch (state) { + case 2: + if (ctr->count >= 1) { + ctr_decrease_count(ctr); + if (ctr->count < 1) { + ctr->state = 3; + ctr_set_out(ctr, 1); + } + } + break; + case 3: + case 6: + ctr_decrease_count(ctr); + break; + + default: + break; + } + break; + case 2: + case 6: + /* Rate generator */ + switch (state) { + case 3: + ctr_load_count(ctr); + ctr->state = 2; + ctr_set_out(ctr, 1); + break; + case 2: + if (ctr->gate == 0) + break; + else if (ctr->count >= 2) { + ctr_decrease_count(ctr); + if (ctr->count < 2) { + ctr->state = 3; + ctr_set_out(ctr, 0); + } + } + break; + + default: + break; + } + break; + case 3: + case 7: + /* Square wave mode */ + switch (state) { + case 2: + if (ctr->gate == 0) + break; + else if (ctr->count >= 0) { + if (ctr->bcd) { + ctr_decrease_count(ctr); + if (!ctr->newcount) + ctr_decrease_count(ctr); + } else + ctr->count -= (ctr->newcount ? 1 : 2); + if (ctr->count < 0) { + ctr_load_count(ctr); + ctr->state = 3; + ctr_set_out(ctr, 0); + } else if (ctr->newcount) + ctr->newcount = 0; + } + break; + case 3: + if (ctr->gate == 0) + break; + else if (ctr->count >= 0) { + if (ctr->bcd) { + ctr_decrease_count(ctr); + ctr_decrease_count(ctr); + if (ctr->newcount) + ctr_decrease_count(ctr); + } else + ctr->count -= (ctr->newcount ? 3 : 2); + if (ctr->count < 0) { + ctr_load_count(ctr); + ctr->state = 2; + ctr_set_out(ctr, 1); + } else if (ctr->newcount) + ctr->newcount = 0; + } + break; + + default: + break; + } + break; + case 4: + case 5: + /* Software triggered strobe */ + /* Hardware triggered strobe */ + if ((ctr->gate != 0) || (ctr->m != 4)) { + switch (state) { + case 0: + case 6: + ctr_decrease_count(ctr); + break; + case 2: + if (ctr->count >= 1) { + ctr_decrease_count(ctr); + if (ctr->count < 1) { + ctr->state = 3; + ctr_set_out(ctr, 0); + } + } + break; + case 3: + ctr->state = 0; + ctr_set_out(ctr, 1); + break; + + default: + break; + } + } + break; + default: + break; } } - static void -ctr_clock(ctr_t *ctr) +ctr_clock(void *data, int counter_id) { - /* FIXME: Is this even needed? */ + pit_t *pit = (pit_t *) data; + ctr_t *ctr = &pit->counters[counter_id]; + + /* FIXME: Is this even needed? */ if ((ctr->state == 3) && (ctr->m != 2) && (ctr->m != 3)) - return; + return; if (ctr->using_timer) - return; + return; ctr_tick(ctr); } - static void ctr_set_state_1(ctr_t *ctr) { uint8_t mode = (ctr->m & 0x03); + int do_reload = !!ctr->incomplete || (mode == 0) || (ctr->state == 0); - if ((mode == 0) || ((mode > 1) && (ctr->state == 0))) - ctr->state = 1; + ctr->incomplete = 0; + + if (do_reload) + ctr->state = 1 + ((mode == 1) << 2); } - static void ctr_load(ctr_t *ctr) { if (ctr->l == 1) { - /* Count of 1 is illegal in modes 2 and 3. What happens here was - determined experimentally. */ - if (ctr->m == 2) - ctr->l = 2; - else if (ctr->m == 3) - ctr->l = 0; + /* Count of 1 is illegal in modes 2 and 3. What happens here was + determined experimentally. */ + if (ctr->m == 2) + ctr->l = 2; + else if (ctr->m == 3) + ctr->l = 0; } if (ctr->using_timer) - ctr->latch = 1; + ctr->latch = 1; else - ctr_set_state_1(ctr); + ctr_set_state_1(ctr); if (ctr->load_func != NULL) - ctr->load_func(ctr->m, ctr->l ? ctr->l : 0x10000); + ctr->load_func(ctr->m, ctr->l ? ctr->l : 0x10000); pit_log("Counter loaded, state = %i, gate = %i\n", ctr->state, ctr->gate); } - static __inline void ctr_latch_status(ctr_t *ctr) { - ctr->read_status = (ctr->ctrl & 0x3f) | (ctr->out ? 0x80 : 0) | (ctr->null_count ? 0x40 : 0); + ctr->read_status = (ctr->ctrl & 0x3f) | (ctr->out ? 0x80 : 0) | (ctr->null_count ? 0x40 : 0); ctr->do_read_status = 1; } - static __inline void ctr_latch_count(ctr_t *ctr) { int count = (ctr->latch || (ctr->state == 1)) ? ctr->l : ctr->count; switch (ctr->rm & 0x03) { - case 0x00: - /* This should never happen. */ - break; - case 0x01: - /* Latch bits 0-7 only. */ - ctr->rl = ((count << 8) & 0xff00) | (count & 0xff); - ctr->latched = 1; - break; - case 0x02: - /* Latch bit 8-15 only. */ - ctr->rl = (count & 0xff00) | ((count >> 8) & 0xff); - ctr->latched = 1; - break; - case 0x03: - /* Latch all 16 bits. */ - ctr->rl = count; - ctr->latched = 2; - break; + case 0x00: + /* This should never happen. */ + break; + case 0x01: + /* Latch bits 0-7 only. */ + ctr->rl = ((count << 8) & 0xff00) | (count & 0xff); + ctr->latched = 1; + break; + case 0x02: + /* Latch bit 8-15 only. */ + ctr->rl = (count & 0xff00) | ((count >> 8) & 0xff); + ctr->latched = 1; + break; + case 0x03: + /* Latch all 16 bits. */ + ctr->rl = count; + ctr->latched = 2; + break; + + default: + break; } pit_log("latched counter = %04X\n", ctr->rl & 0xffff); } - uint16_t -pit_ctr_get_count(ctr_t *ctr) +pit_ctr_get_count(void *data, int counter_id) { + const pit_t *pit = (pit_t *) data; + const ctr_t *ctr = &pit->counters[counter_id]; + return (uint16_t) ctr->l; } - void -pit_ctr_set_load_func(ctr_t *ctr, void (*func)(uint8_t new_m, int new_count)) +pit_ctr_set_load_func(void *data, int counter_id, void (*func)(uint8_t new_m, int new_count)) { - if (ctr == NULL) - return; + if (data == NULL) + return; + + pit_t *pit = (pit_t *) data; + ctr_t *ctr = &pit->counters[counter_id]; ctr->load_func = func; } - void -pit_ctr_set_out_func(ctr_t *ctr, void (*func)(int new_out, int old_out)) +pit_ctr_set_out_func(void *data, int counter_id, void (*func)(int new_out, int old_out)) { - if (ctr == NULL) - return; + if (data == NULL) + return; + + pit_t *pit = (pit_t *) data; + ctr_t *ctr = &pit->counters[counter_id]; ctr->out_func = func; } - void -pit_ctr_set_gate(ctr_t *ctr, int gate) +pit_ctr_set_gate(void *data, int counter_id, int gate) { - int old = ctr->gate; + pit_t *pit = (pit_t *) data; + ctr_t *ctr = &pit->counters[counter_id]; + + int old = ctr->gate; uint8_t mode = ctr->m & 3; ctr->gate = gate; switch (mode) { - case 1: case 2: case 3: case 5: case 6: case 7: - if (!old && gate) { - /* Here we handle the rising edges. */ - if (mode & 1) { - if (mode != 1) - ctr_set_out(ctr, 1); - ctr->state = 1; - } else if (mode == 2) - ctr->state = 3; - } else if (old && !gate) { - /* Here we handle the lowering edges. */ - if (mode & 2) - ctr_set_out(ctr, 1); - } - break; - } -} + case 1: + case 2: + case 3: + case 5: + case 6: + case 7: + if (!old && gate) { + /* Here we handle the rising edges. */ + if (mode & 1) { + if (mode != 1) + ctr_set_out(ctr, 1); + ctr->state = 1; + } else if (mode == 2) + ctr->state = 3; + } else if (old && !gate) { + /* Here we handle the lowering edges. */ + if (mode & 2) + ctr_set_out(ctr, 1); + } + break; + default: + break; + } +} static __inline void pit_ctr_set_clock_common(ctr_t *ctr, int clock) @@ -441,230 +472,280 @@ pit_ctr_set_clock_common(ctr_t *ctr, int clock) ctr->clock = clock; if (ctr->using_timer && ctr->latch) { - if (old && !ctr->clock) { - ctr_set_state_1(ctr); - ctr->latch = 0; - } + if (old && !ctr->clock) { + ctr_set_state_1(ctr); + ctr->latch = 0; + } } else if (ctr->using_timer && !ctr->latch) { - if (ctr->state == 1) { - if (!old && ctr->clock) - ctr->s1_det = 1; /* Rising edge. */ - else if (old && !ctr->clock) { - ctr->s1_det++; /* Falling edge. */ - if (ctr->s1_det >= 2) { - ctr->s1_det = 0; - ctr_tick(ctr); - } - } - } else if (old && !ctr->clock) - ctr_tick(ctr); + if (ctr->state == 1) { + if (!old && ctr->clock) + ctr->s1_det = 1; /* Rising edge. */ + else if (old && !ctr->clock) { + ctr->s1_det++; /* Falling edge. */ + if (ctr->s1_det >= 2) { + ctr->s1_det = 0; + ctr_tick(ctr); + } + } + } else if (old && !ctr->clock) + ctr_tick(ctr); } } - void pit_ctr_set_clock(ctr_t *ctr, int clock) { pit_ctr_set_clock_common(ctr, clock); } - void -pit_ctr_set_using_timer(ctr_t *ctr, int using_timer) +pit_ctr_set_using_timer(void *data, int counter_id, int using_timer) { - timer_process(); - + if (tsc > 0) + timer_process(); + pit_t *pit = (pit_t *) data; + ctr_t *ctr = &pit->counters[counter_id]; ctr->using_timer = using_timer; } - static void -pit_timer_over(void *p) +pit_timer_over(void *priv) { - pit_t *dev = (pit_t *) p; - int i; + pit_t *dev = (pit_t *) priv; dev->clock ^= 1; - for (i = 0; i < 3; i++) - pit_ctr_set_clock_common(&dev->counters[i], dev->clock); + for (uint8_t i = 0; i < 3; i++) + pit_ctr_set_clock_common(&dev->counters[i], dev->clock); timer_advance_u64(&dev->callback_timer, PITCONST >> 1ULL); } - static void pit_write(uint16_t addr, uint8_t val, void *priv) { - pit_t *dev = (pit_t *)priv; - int t = (addr & 3); + pit_t *dev = (pit_t *) priv; + int t = (addr & 3); ctr_t *ctr; pit_log("[%04X:%08X] pit_write(%04X, %02X, %08X)\n", CS, cpu_state.pc, addr, val, priv); switch (addr & 3) { - case 3: /* control */ - t = val >> 6; + case 3: /* control */ + t = val >> 6; - if (t == 3) { - if (dev->flags & PIT_8254) { - /* This is 8254-only. */ - if (!(val & 0x20)) { - if (val & 2) - ctr_latch_count(&dev->counters[0]); - if (val & 4) - ctr_latch_count(&dev->counters[1]); - if (val & 8) - ctr_latch_count(&dev->counters[2]); - pit_log("PIT %i: Initiated readback command\n", t); - } - if (!(val & 0x10)) { - if (val & 2) - ctr_latch_status(&dev->counters[0]); - if (val & 4) - ctr_latch_status(&dev->counters[1]); - if (val & 8) - ctr_latch_status(&dev->counters[2]); - } - } - } else { - dev->ctrl = val; - ctr = &dev->counters[t]; + if (t == 3) { + if (dev->flags & PIT_8254) { + /* This is 8254-only. */ + if (!(val & 0x20)) { + if (val & 2) + ctr_latch_count(&dev->counters[0]); + if (val & 4) + ctr_latch_count(&dev->counters[1]); + if (val & 8) + ctr_latch_count(&dev->counters[2]); + pit_log("PIT %i: Initiated readback command\n", t); + } + if (!(val & 0x10)) { + if (val & 2) + ctr_latch_status(&dev->counters[0]); + if (val & 4) + ctr_latch_status(&dev->counters[1]); + if (val & 8) + ctr_latch_status(&dev->counters[2]); + } + } + } else { + dev->ctrl = val; + ctr = &dev->counters[t]; - if (!(dev->ctrl & 0x30)) { - ctr_latch_count(ctr); - pit_log("PIT %i: Initiated latched read, %i bytes latched\n", - t, ctr->latched); - } else { - ctr->ctrl = val; - ctr->rm = ctr->wm = (ctr->ctrl >> 4) & 3; - ctr->m = (val >> 1) & 7; - if (ctr->m > 5) - ctr->m &= 3; - ctr->null_count = 1; - ctr->bcd = (ctr->ctrl & 0x01); - ctr_set_out(ctr, !!ctr->m); - ctr->state = 0; - if (ctr->latched) { - pit_log("PIT %i: Reload while counter is latched\n", t); - ctr->rl--; - } + if (!(dev->ctrl & 0x30)) { + ctr_latch_count(ctr); + pit_log("PIT %i: Initiated latched read, %i bytes latched\n", + t, ctr->latched); + } else { + ctr->ctrl = val; + ctr->rm = ctr->wm = (ctr->ctrl >> 4) & 3; + ctr->m = (val >> 1) & 7; + if (ctr->m > 5) + ctr->m &= 3; + ctr->null_count = 1; + ctr->bcd = (ctr->ctrl & 0x01); + ctr_set_out(ctr, !!ctr->m); + ctr->state = 0; + if (ctr->latched) { + pit_log("PIT %i: Reload while counter is latched\n", t); + ctr->rl--; + } - pit_log("PIT %i: M = %i, RM/WM = %i, State = %i, Out = %i\n", t, ctr->m, ctr->rm, ctr->state, ctr->out); - } - } - break; + pit_log("PIT %i: M = %i, RM/WM = %i, State = %i, Out = %i\n", t, ctr->m, ctr->rm, ctr->state, ctr->out); + } + } + break; - case 0: - case 1: - case 2: /* the actual timers */ - ctr = &dev->counters[t]; + case 0: + case 1: + case 2: /* the actual timers */ + ctr = &dev->counters[t]; - switch (ctr->wm) { - case 0: - /* This should never happen. */ - break; - case 1: - ctr->l = val; - if (ctr->m == 0) - ctr_set_out(ctr, 0); - ctr_load(ctr); - break; - case 2: - ctr->l = (val << 8); - if (ctr->m == 0) - ctr_set_out(ctr, 0); - ctr_load(ctr); - break; - case 3: case 0x83: - if (ctr->wm & 0x80) { - ctr->l = (ctr->l & 0x00ff) | (val << 8); - pit_log("PIT %i: Written high byte %02X, latch now %04X\n", t, val, ctr->l); - ctr_load(ctr); - } else { - ctr->l = (ctr->l & 0xff00) | val; - pit_log("PIT %i: Written low byte %02X, latch now %04X\n", t, val, ctr->l); - if (ctr->m == 0) { - ctr->state = 0; - ctr_set_out(ctr, 0); - } - } + switch (ctr->wm) { + case 0: + /* This should never happen. */ + break; + case 1: + ctr->l = val; + if (ctr->m == 0) + ctr_set_out(ctr, 0); + ctr_load(ctr); + break; + case 2: + ctr->l = (val << 8); + if (ctr->m == 0) + ctr_set_out(ctr, 0); + ctr_load(ctr); + break; + case 3: + case 0x83: + if (ctr->wm & 0x80) { + ctr->l = (ctr->l & 0x00ff) | (val << 8); + pit_log("PIT %i: Written high byte %02X, latch now %04X\n", t, val, ctr->l); + ctr_load(ctr); + } else { + ctr->l = (ctr->l & 0xff00) | val; + pit_log("PIT %i: Written low byte %02X, latch now %04X\n", t, val, ctr->l); + if (ctr->m == 0) { + ctr->state = 0; + ctr_set_out(ctr, 0); + } + } - if (ctr->wm & 0x80) - ctr->wm &= ~0x80; - else - ctr->wm |= 0x80; - break; - } - break; + if (ctr->wm & 0x80) + ctr->wm &= ~0x80; + else + ctr->wm |= 0x80; + break; + + default: + break; + } + break; + + default: + break; } } +extern uint8_t *ram; + +uint8_t +pit_read_reg(void *priv, uint8_t reg) +{ + pit_t *dev = (pit_t *) priv; + uint8_t ret = 0xff; + + switch (reg) { + case 0x00: + case 0x02: + case 0x04: + ret = dev->counters[reg >> 1].l & 0xff; + break; + case 0x01: + case 0x03: + case 0x05: + ret = (dev->counters[reg >> 1].l >> 8) & 0xff; + break; + case 0x06: + ret = dev->ctrl; + break; + case 0x07: + /* The SiS 551x datasheet is unclear about how exactly + this register is structured. */ + ret = (dev->counters[0].rm & 0x80) ? 0x01 : 0x00; + ret = (dev->counters[0].wm & 0x80) ? 0x02 : 0x00; + ret = (dev->counters[1].rm & 0x80) ? 0x04 : 0x00; + ret = (dev->counters[1].wm & 0x80) ? 0x08 : 0x00; + ret = (dev->counters[2].rm & 0x80) ? 0x10 : 0x00; + ret = (dev->counters[2].wm & 0x80) ? 0x20 : 0x00; + break; + } + + return ret; +} static uint8_t pit_read(uint16_t addr, void *priv) { - pit_t *dev = (pit_t *)priv; + pit_t *dev = (pit_t *) priv; uint8_t ret = 0xff; - int count, t = (addr & 3); - ctr_t *ctr; + int count; + int t = (addr & 3); + ctr_t *ctr; switch (addr & 3) { - case 3: /* Control. */ - /* This is 8254-only, 8253 returns 0x00. */ - ret = (dev->flags & PIT_8254) ? dev->ctrl : 0x00; - break; + case 3: /* Control. */ + /* This is 8254-only, 8253 returns 0x00. */ + ret = (dev->flags & PIT_8254) ? dev->ctrl : 0x00; + break; - case 0: - case 1: - case 2: /* The actual timers. */ - ctr = &dev->counters[t]; + case 0: + case 1: + case 2: /* The actual timers. */ + ctr = &dev->counters[t]; - if (ctr->do_read_status) { - ctr->do_read_status = 0; - ret = ctr->read_status; - break; - } + if (ctr->do_read_status) { + ctr->do_read_status = 0; + ret = ctr->read_status; + break; + } - count = (ctr->state == 1) ? ctr->l : ctr->count; + count = (ctr->state == 1) ? ctr->l : ctr->count; - if (ctr->latched) { - ret = (ctr->rl) >> ((ctr->rm & 0x80) ? 8 : 0); + if (ctr->latched) { + ret = (ctr->rl) >> ((ctr->rm & 0x80) ? 8 : 0); - if (ctr->rm & 0x80) - ctr->rm &= ~0x80; - else - ctr->rm |= 0x80; + if (ctr->rm & 0x80) + ctr->rm &= ~0x80; + else + ctr->rm |= 0x80; - ctr->latched--; - } else switch (ctr->rm) { - case 0: case 0x80: - ret = 0x00; - break; + ctr->latched--; + } else + switch (ctr->rm) { + case 0: + case 0x80: + ret = 0x00; + break; - case 1: - ret = count & 0xff; - break; + case 1: + ret = count & 0xff; + break; - case 2: - ret = count >> 8; - break; + case 2: + ret = count >> 8; + break; - case 3: case 0x83: - /* Yes, wm is correct here - this is to ensure correct readout while the - count is being written. */ - if (ctr->wm & 0x80) - ret = ~(ctr->l & 0xff); - else - ret = count >> ((ctr->rm & 0x80) ? 8 : 0); + case 3: + case 0x83: + /* Yes, wm is correct here - this is to ensure correct readout while the + count is being written. */ + if (ctr->wm & 0x80) + ret = ~(ctr->l & 0xff); + else + ret = count >> ((ctr->rm & 0x80) ? 8 : 0); - if (ctr->rm & 0x80) - ctr->rm &= ~0x80; - else - ctr->rm |= 0x80; - break; - } - break; + if (ctr->rm & 0x80) + ctr->rm &= ~0x80; + else + ctr->rm |= 0x80; + break; + + default: + break; + } + break; + + default: + break; } pit_log("[%04X:%08X] pit_read(%04X, %08X) = %02X\n", CS, cpu_state.pc, addr, priv, ret); @@ -672,154 +753,116 @@ pit_read(uint16_t addr, void *priv) return ret; } - -/* FIXME: Should be moved to machine.c (default for most machine). */ -void -pit_irq0_timer(int new_out, int old_out) -{ - if (new_out && !old_out) - picint(1); - - if (!new_out) - picintc(1); -} - - -void -pit_irq0_timer_pcjr(int new_out, int old_out) -{ - if (new_out && !old_out) { - picint(1); - ctr_clock(&pit->counters[1]); - } - - if (!new_out) - picintc(1); -} - - void pit_irq0_timer_ps2(int new_out, int old_out) { - ctr_t *ctr = &pit2->counters[0]; - if (new_out && !old_out) { - picint(1); - pit_ctr_set_gate(ctr, 1); + picint(1); + pit_devs[1].set_gate(pit_devs[1].data, 0, 1); } if (!new_out) - picintc(1); + picintc(1); if (!new_out && old_out) - ctr_clock(ctr); + pit_devs[1].ctr_clock(pit_devs[1].data, 0); } - void pit_refresh_timer_xt(int new_out, int old_out) { if (new_out && !old_out) - dma_channel_read(0); + dma_channel_read(0); } - void pit_refresh_timer_at(int new_out, int old_out) { if (refresh_at_enable && new_out && !old_out) - ppi.pb ^= 0x10; + ppi.pb ^= 0x10; } - void -pit_speaker_timer(int new_out, int old_out) +pit_speaker_timer(int new_out, UNUSED(int old_out)) { int l; if (cassette != NULL) - pc_cas_set_out(cassette, new_out); + pc_cas_set_out(cassette, new_out); speaker_update(); - l = pit->counters[2].l ? pit->counters[2].l : 0x10000; + uint16_t count = pit_devs[0].get_count(pit_devs[0].data, 2); + l = count ? count : 0x10000; if (l < 25) - speakon = 0; + speakon = 0; else - speakon = new_out; + speakon = new_out; ppispeakon = new_out; } - void -pit_nmi_timer_ps2(int new_out, int old_out) +pit_nmi_timer_ps2(int new_out, UNUSED(int old_out)) { nmi = new_out; if (nmi) - nmi_auto_clear = 1; + nmi_auto_clear = 1; } - static void ctr_reset(ctr_t *ctr) { - ctr->ctrl = 0; - ctr->m = 0; - ctr->gate = 0; - ctr->l = 0xffff; + ctr->ctrl = 0; + ctr->m = 0; + ctr->gate = 0; + ctr->l = 0xffff; ctr->using_timer = 1; - ctr->state = 0; - ctr->null_count = 1; + ctr->state = 0; + ctr->null_count = 1; ctr->latch = 0; ctr->s1_det = 0; - ctr->l_det = 0; + ctr->l_det = 0; } - void pit_reset(pit_t *dev) { - int i; - memset(dev, 0, sizeof(pit_t)); dev->clock = 0; - for (i = 0; i < 3; i++) - ctr_reset(&dev->counters[i]); + for (uint8_t i = 0; i < 3; i++) + ctr_reset(&dev->counters[i]); /* Disable speaker gate. */ dev->counters[2].gate = 0; } - void pit_handler(int set, uint16_t base, int size, void *priv) { io_handler(set, base, size, pit_read, NULL, NULL, pit_write, NULL, NULL, priv); } - static void pit_close(void *priv) { pit_t *dev = (pit_t *) priv; - if (dev == pit) - pit = NULL; + if (dev == pit_devs[0].data) + pit_devs[0].data = NULL; - if (dev == pit2) - pit2 = NULL; + if (dev == pit_devs[1].data) + pit_devs[1].data = NULL; if (dev != NULL) - free(dev); + free(dev); } - static void * pit_init(const device_t *info) { @@ -827,231 +870,295 @@ pit_init(const device_t *info) pit_reset(dev); if (!(dev->flags & PIT_PS2) && !(dev->flags & PIT_CUSTOM_CLOCK)) { - timer_add(&dev->callback_timer, pit_timer_over, (void *) dev, 0); - timer_set_delay_u64(&dev->callback_timer, PITCONST >> 1ULL); + timer_add(&dev->callback_timer, pit_timer_over, (void *) dev, 0); + timer_set_delay_u64(&dev->callback_timer, PITCONST >> 1ULL); } dev->flags = info->local; if (!(dev->flags & PIT_EXT_IO)) { - io_sethandler((dev->flags & PIT_SECONDARY) ? 0x0048 : 0x0040, 0x0004, - pit_read, NULL, NULL, pit_write, NULL, NULL, dev); + io_sethandler((dev->flags & PIT_SECONDARY) ? 0x0048 : 0x0040, 0x0004, + pit_read, NULL, NULL, pit_write, NULL, NULL, dev); } return dev; } - -const device_t i8253_device = -{ - "Intel 8253/8253-5 Programmable Interval Timer", - "i8253", - DEVICE_ISA, - PIT_8253, - pit_init, pit_close, NULL, - { NULL }, NULL, NULL, - NULL +const device_t i8253_device = { + .name = "Intel 8253/8253-5 Programmable Interval Timer", + .internal_name = "i8253", + .flags = DEVICE_ISA | DEVICE_PIT, + .local = PIT_8253, + .init = pit_init, + .close = pit_close, + .reset = NULL, + { .available = NULL }, + .speed_changed = NULL, + .force_redraw = NULL, + .config = NULL }; - -const device_t i8254_device = -{ - "Intel 8254 Programmable Interval Timer", - "i8254", - DEVICE_ISA, - PIT_8254, - pit_init, pit_close, NULL, - { NULL }, NULL, NULL, - NULL +const device_t i8254_device = { + .name = "Intel 8254 Programmable Interval Timer", + .internal_name = "i8254", + .flags = DEVICE_ISA | DEVICE_PIT, + .local = PIT_8254, + .init = pit_init, + .close = pit_close, + .reset = NULL, + { .available = NULL }, + .speed_changed = NULL, + .force_redraw = NULL, + .config = NULL }; - -const device_t i8254_sec_device = -{ - "Intel 8254 Programmable Interval Timer (Secondary)", - "i8254_sec", - DEVICE_ISA, - PIT_8254 | PIT_SECONDARY, - pit_init, pit_close, NULL, - { NULL }, NULL, NULL, - NULL +const device_t i8254_sec_device = { + .name = "Intel 8254 Programmable Interval Timer (Secondary)", + .internal_name = "i8254_sec", + .flags = DEVICE_ISA, + .local = PIT_8254 | PIT_SECONDARY, + .init = pit_init, + .close = pit_close, + .reset = NULL, + { .available = NULL }, + .speed_changed = NULL, + .force_redraw = NULL, + .config = NULL }; - -const device_t i8254_ext_io_device = -{ - "Intel 8254 Programmable Interval Timer (External I/O)", - "i8254_ext_io", - DEVICE_ISA, - PIT_8254 | PIT_EXT_IO, - pit_init, pit_close, NULL, - { NULL }, NULL, NULL, - NULL +const device_t i8254_ext_io_device = { + .name = "Intel 8254 Programmable Interval Timer (External I/O)", + .internal_name = "i8254_ext_io", + .flags = DEVICE_ISA, + .local = PIT_8254 | PIT_EXT_IO, + .init = pit_init, + .close = pit_close, + .reset = NULL, + { .available = NULL }, + .speed_changed = NULL, + .force_redraw = NULL, + .config = NULL }; - -const device_t i8254_ps2_device = -{ - "Intel 8254 Programmable Interval Timer (PS/2)", - "i8254_ps2", - DEVICE_ISA, - PIT_8254 | PIT_PS2 | PIT_EXT_IO, - pit_init, pit_close, NULL, - { NULL }, NULL, NULL, - NULL +const device_t i8254_ps2_device = { + .name = "Intel 8254 Programmable Interval Timer (PS/2)", + .internal_name = "i8254_ps2", + .flags = DEVICE_ISA, + .local = PIT_8254 | PIT_PS2 | PIT_EXT_IO, + .init = pit_init, + .close = pit_close, + .reset = NULL, + { .available = NULL }, + .speed_changed = NULL, + .force_redraw = NULL, + .config = NULL }; - pit_t * pit_common_init(int type, void (*out0)(int new_out, int old_out), void (*out1)(int new_out, int old_out)) { - int i; + void *pit; + + pit_intf_t *pit_intf = &pit_devs[0]; switch (type) { - case PIT_8253: - default: - pit = device_add(&i8253_device); - break; - case PIT_8254: - pit = device_add(&i8254_device); - break; + default: + case PIT_8253: + pit = device_add(&i8253_device); + *pit_intf = pit_classic_intf; + break; + case PIT_8254: + pit = device_add(&i8254_device); + *pit_intf = pit_classic_intf; + break; + case PIT_8253_FAST: + pit = device_add(&i8253_fast_device); + *pit_intf = pit_fast_intf; + break; + case PIT_8254_FAST: + pit = device_add(&i8254_fast_device); + *pit_intf = pit_fast_intf; + break; } - for (i = 0; i < 3; i++) { - pit->counters[i].gate = 1; - pit->counters[i].using_timer = 1; + pit_intf->data = pit; + + for (uint8_t i = 0; i < 3; i++) { + pit_intf->set_gate(pit_intf->data, i, 1); + pit_intf->set_using_timer(pit_intf->data, i, 1); } - pit_ctr_set_out_func(&pit->counters[0], out0); - pit_ctr_set_out_func(&pit->counters[1], out1); - pit_ctr_set_out_func(&pit->counters[2], pit_speaker_timer); - pit_ctr_set_load_func(&pit->counters[2], speaker_set_count); - pit->counters[2].gate = 0; + pit_intf->set_out_func(pit_intf->data, 0, out0); + pit_intf->set_out_func(pit_intf->data, 1, out1); + pit_intf->set_out_func(pit_intf->data, 2, pit_speaker_timer); + pit_intf->set_load_func(pit_intf->data, 2, speaker_set_count); + + pit_intf->set_gate(pit_intf->data, 2, 0); return pit; } - pit_t * -pit_ps2_init(void) +pit_ps2_init(int type) { - pit2 = device_add(&i8254_ps2_device); + void *pit; - pit_handler(1, 0x0044, 0x0001, pit2); - pit_handler(1, 0x0047, 0x0001, pit2); + pit_intf_t *ps2_pit = &pit_devs[1]; - pit2->counters[0].gate = 0; - pit2->counters[0].using_timer = pit2->counters[1].using_timer = pit2->counters[2].using_timer = 0; + switch (type) { + default: + case PIT_8254: + pit = device_add(&i8254_ps2_device); + *ps2_pit = pit_classic_intf; + break; - pit_ctr_set_out_func(&pit->counters[0], pit_irq0_timer_ps2); - pit_ctr_set_out_func(&pit2->counters[0], pit_nmi_timer_ps2); + case PIT_8254_FAST: + pit = device_add(&i8254_ps2_fast_device); + *ps2_pit = pit_fast_intf; + break; + } - return pit2; + ps2_pit->data = pit; + + ps2_pit->set_gate(ps2_pit->data, 0, 0); + for (int i = 0; i < 3; i++) { + ps2_pit->set_using_timer(ps2_pit->data, i, 0); + } + + io_sethandler(0x0044, 0x0001, ps2_pit->read, NULL, NULL, ps2_pit->write, NULL, NULL, pit); + io_sethandler(0x0047, 0x0001, ps2_pit->read, NULL, NULL, ps2_pit->write, NULL, NULL, pit); + + pit_devs[0].set_out_func(pit_devs[0].data, 0, pit_irq0_timer_ps2); + ps2_pit->set_out_func(ps2_pit->data, 0, pit_nmi_timer_ps2); + + return pit; } - void -pit_set_clock(int clock) +pit_set_clock(uint32_t clock) { /* Set default CPU/crystal clock and xt_cpu_multi. */ if (cpu_s->cpu_type >= CPU_286) { - int remainder = (clock % 100000000); - if (remainder == 66666666) - cpuclock = (double) (clock - remainder) + (200000000.0 / 3.0); - else if (remainder == 33333333) - cpuclock = (double) (clock - remainder) + (100000000.0 / 3.0); - else - cpuclock = (double) clock; + uint32_t remainder = (clock % 100000000); + if (remainder == 66666666) + cpuclock = (double) (clock - remainder) + (200000000.0 / 3.0); + else if (remainder == 33333333) + cpuclock = (double) (clock - remainder) + (100000000.0 / 3.0); + else + cpuclock = (double) clock; - PITCONSTD = (cpuclock / 1193182.0); - PITCONST = (uint64_t) (PITCONSTD * (double)(1ull << 32)); - CGACONST = (uint64_t) ((cpuclock / (19687503.0/11.0)) * (double)(1ull << 32)); - ISACONST = (uint64_t) ((cpuclock / (double)cpu_isa_speed) * (double)(1ull << 32)); - xt_cpu_multi = 1ULL; + PITCONSTD = (cpuclock / 1193182.0); + PITCONST = (uint64_t) (PITCONSTD * (double) (1ULL << 32)); +#ifdef IMPRECISE_CGACONST + CGACONST = (uint64_t) ((cpuclock / (19687503.0 / 11.0)) * (double) (1ULL << 32)); +#else + CGACONST = (uint64_t) ((cpuclock / (157500000.0 / 88.0)) * (double) (1ULL << 32)); +#endif + ISACONST = (uint64_t) ((cpuclock / (double) cpu_isa_speed) * (double) (1ULL << 32)); + xt_cpu_multi = 1ULL; } else { - cpuclock = 14318184.0; - PITCONSTD = 12.0; - PITCONST = (12ULL << 32ULL); - CGACONST = (8ULL << 32ULL); - xt_cpu_multi = 3ULL; + cpuclock = (157500000.0 / 11.0); + PITCONSTD = 12.0; + PITCONST = (12ULL << 32ULL); + CGACONST = (8ULL << 32ULL); + xt_cpu_multi = 3ULL; - switch (cpu_s->rspeed) { - case 7159092: - if (cpu_s->cpu_flags & CPU_ALTERNATE_XTAL) { - cpuclock = 28636368.0; - xt_cpu_multi = 4ULL; - } else - xt_cpu_multi = 2ULL; - break; + switch (cpu_s->rspeed) { + case 7159092: + if (cpu_s->cpu_flags & CPU_ALTERNATE_XTAL) { + cpuclock = 28636368.0; + xt_cpu_multi = 4ULL; + } else + xt_cpu_multi = 2ULL; + break; - case 8000000: - cpuclock = 24000000.0; - break; - case 9545456: - cpuclock = 28636368.0; - break; - case 10000000: - cpuclock = 30000000.0; - break; - case 12000000: - cpuclock = 36000000.0; - break; - case 16000000: - cpuclock = 48000000.0; - break; + case 8000000: + cpuclock = 24000000.0; + break; + case 9545456: + cpuclock = 28636368.0; + break; + case 10000000: + cpuclock = 30000000.0; + break; + case 12000000: + cpuclock = 36000000.0; + break; + case 16000000: + cpuclock = 48000000.0; + break; - default: - if (cpu_s->cpu_flags & CPU_ALTERNATE_XTAL) { - cpuclock = 28636368.0; - xt_cpu_multi = 6ULL; - } - break; - } + default: + if (cpu_s->cpu_flags & CPU_ALTERNATE_XTAL) { + cpuclock = 28636368.0; + xt_cpu_multi = 6ULL; + } + break; + } - if (cpuclock == 28636368.0) { - PITCONSTD = 24.0; - PITCONST = (24ULL << 32LL); - CGACONST = (16ULL << 32LL); - } else if (cpuclock != 14318184.0) { - PITCONSTD = (cpuclock / 1193182.0); - PITCONST = (uint64_t) (PITCONSTD * (double)(1ull << 32)); - CGACONST = (uint64_t) (((cpuclock/(19687503.0/11.0)) * (double)(1ull << 32))); - } + if (cpuclock == 28636368.0) { + PITCONSTD = 24.0; + PITCONST = (24ULL << 32LL); + CGACONST = (16ULL << 32LL); + } else if (cpuclock != 14318184.0) { + PITCONSTD = (cpuclock / 1193182.0); + PITCONST = (uint64_t) (PITCONSTD * (double) (1ULL << 32)); +#ifdef IMPRECISE_CGACONST + CGACONST = (uint64_t) ((cpuclock / (19687503.0 / 11.0)) * (double) (1ULL << 32)); +#else + CGACONST = (uint64_t) ((cpuclock / (157500000.0 / 88.0)) * (double) (1ULL << 32)); +#endif + } - ISACONST = (1ULL << 32ULL); + ISACONST = (1ULL << 32ULL); } xt_cpu_multi <<= 32ULL; /* Delay for empty I/O ports. */ io_delay = (int) round(((double) cpu_s->rspeed) / 3000000.0); - MDACONST = (uint64_t) (cpuclock / 2032125.0 * (double)(1ull << 32)); +#ifdef WRONG_MDACONST + MDACONST = (uint64_t) (cpuclock / 2032125.0 * (double) (1ULL << 32)); +#else + MDACONST = (uint64_t) (cpuclock / (16257000.0 / 9.0) * (double) (1ULL << 32)); +#endif HERCCONST = MDACONST; - VGACONST1 = (uint64_t) (cpuclock / 25175000.0 * (double)(1ull << 32)); - VGACONST2 = (uint64_t) (cpuclock / 28322000.0 * (double)(1ull << 32)); - RTCCONST = (uint64_t) (cpuclock / 32768.0 * (double)(1ull << 32)); - ACPICONST = (uint64_t) (cpuclock / 3579545.0 * (double)(1ull << 32)); + VGACONST1 = (uint64_t) (cpuclock / 25175000.0 * (double) (1ULL << 32)); + VGACONST2 = (uint64_t) (cpuclock / 28322000.0 * (double) (1ULL << 32)); + RTCCONST = (uint64_t) (cpuclock / 32768.0 * (double) (1ULL << 32)); - TIMER_USEC = (uint64_t)((cpuclock / 1000000.0) * (double)(1ull << 32)); + TIMER_USEC = (uint64_t) ((cpuclock / 1000000.0) * (double) (1ULL << 32)); - isa_timing = (cpuclock / (double)cpu_isa_speed); + isa_timing = (cpuclock / (double) cpu_isa_speed); if (cpu_64bitbus) - bus_timing = (cpuclock / ((double)cpu_busspeed / 2)); + bus_timing = (cpuclock / (cpu_busspeed / 2)); else - bus_timing = (cpuclock / (double)cpu_busspeed); - pci_timing = (cpuclock / (double)cpu_pci_speed); - agp_timing = (cpuclock / (double)cpu_agp_speed); + bus_timing = (cpuclock / cpu_busspeed); + pci_timing = (cpuclock / (double) cpu_pci_speed); + agp_timing = (cpuclock / (double) cpu_agp_speed); /* PCICLK in us for use with timer_on_auto(). */ PCICLK = pci_timing / (cpuclock / 1000000.0); AGPCLK = agp_timing / (cpuclock / 1000000.0); if (cpu_busspeed >= 30000000) - SYSCLK = bus_timing * 4.0; + SYSCLK = bus_timing * 4.0; else - SYSCLK = bus_timing * 3.0; + SYSCLK = bus_timing * 3.0; video_update_timing(); device_speed_changed(); } + +const pit_intf_t pit_classic_intf = { + &pit_read, + &pit_write, + &pit_ctr_get_count, + &pit_ctr_set_gate, + &pit_ctr_set_using_timer, + &pit_ctr_set_out_func, + &pit_ctr_set_load_func, + &ctr_clock, + NULL, +}; diff --git a/src/pit_fast.c b/src/pit_fast.c new file mode 100644 index 000000000..1168cb3c5 --- /dev/null +++ b/src/pit_fast.c @@ -0,0 +1,773 @@ +/* + * 86Box A hypervisor and IBM PC system emulator that specializes in + * running old operating systems and software designed for IBM + * PC systems and compatibles from 1981 through fairly recent + * system designs based on the PCI bus. + * + * This file is part of the 86Box distribution. + * + * Implementation of the Intel 8253/8254 Programmable Interval + * Timer. + * + * + * + * Authors: Miran Grca, + * + * Copyright 2019 Miran Grca. + */ +#include +#include +#include +#include +#include +#include +#include +#include +#define HAVE_STDARG_H +#include <86box/86box.h> +#include "cpu.h" +#include <86box/device.h> +#include <86box/timer.h> +#include <86box/cassette.h> +#include <86box/dma.h> +#include <86box/io.h> +#include <86box/nmi.h> +#include <86box/pic.h> +#include <86box/timer.h> +#include <86box/pit.h> +#include <86box/pit_fast.h> +#include <86box/ppi.h> +#include <86box/machine.h> +#include <86box/sound.h> +#include <86box/snd_speaker.h> +#include <86box/video.h> + +#define PIT_PS2 16 /* The PIT is the PS/2's second PIT. */ +#define PIT_EXT_IO 32 /* The PIT has externally specified port I/O. */ +#define PIT_CUSTOM_CLOCK 64 /* The PIT uses custom clock inputs provided by another provider. */ +#define PIT_SECONDARY 128 /* The PIT is secondary (ports 0048-004B). */ + +#ifdef ENABLE_PIT_LOG +int pit_do_log = ENABLE_PIT_LOG; + +static void +pit_log(const char *fmt, ...) +{ + va_list ap; + + if (pit_do_log) { + va_start(ap, fmt); + pclog_ex(fmt, ap); + va_end(ap); + } +} +#else +# define pit_log(fmt, ...) +#endif + +static void +pitf_ctr_set_out(ctrf_t *ctr, int out) +{ + if (ctr == NULL) + return; + + if (ctr->out_func != NULL) + ctr->out_func(out, ctr->out); + ctr->out = out; +} + +static void +pitf_ctr_set_load_func(void *data, int counter_id, void (*func)(uint8_t new_m, int new_count)) +{ + if (data == NULL) + return; + + pitf_t *pit = (pitf_t *) data; + ctrf_t *ctr = &pit->counters[counter_id]; + + ctr->load_func = func; +} + +static uint16_t +pitf_ctr_get_count(void *data, int counter_id) +{ + const pitf_t *pit = (pitf_t *) data; + const ctrf_t *ctr = &pit->counters[counter_id]; + + return (uint16_t) ctr->l; +} + +static void +pitf_ctr_set_out_func(void *data, int counter_id, void (*func)(int new_out, int old_out)) +{ + if (data == NULL) + return; + + pitf_t *pit = (pitf_t *) data; + ctrf_t *ctr = &pit->counters[counter_id]; + + ctr->out_func = func; +} + +static void +pitf_ctr_set_using_timer(void *data, int counter_id, int using_timer) +{ + if (tsc > 0) + timer_process(); + + pitf_t *pit = (pitf_t *) data; + ctrf_t *ctr = &pit->counters[counter_id]; + ctr->using_timer = using_timer; +} + +static int +pitf_read_timer(ctrf_t *ctr) +{ + if (ctr->using_timer && !(ctr->m == 3 && !ctr->gate) && timer_is_enabled(&ctr->timer)) { + int read = (int) ((timer_get_remaining_u64(&ctr->timer)) / PITCONST); + if (ctr->m == 2) + read++; + if (read < 0) + read = 0; + if (read > 0x10000) + read = 0x10000; + if (ctr->m == 3) + read <<= 1; + return read; + } + if (ctr->m == 2) + return ctr->count + 1; + return ctr->count; +} + +/*Dump timer count back to pit->count[], and disable timer. This should be used + when stopping a PIT timer, to ensure the correct value can be read back.*/ +static void +pitf_dump_and_disable_timer(ctrf_t *ctr) +{ + if (ctr->using_timer && timer_is_enabled(&ctr->timer)) { + ctr->count = pitf_read_timer(ctr); + if (ctr->m == 2) + ctr->count--; /* Don't store the offset from pitf_read_timer */ + timer_disable(&ctr->timer); + } +} + +static void +pitf_ctr_load(ctrf_t *ctr) +{ + int l = ctr->l ? ctr->l : 0x10000; + + ctr->newcount = 0; + ctr->disabled = 0; + + switch (ctr->m) { + case 0: /*Interrupt on terminal count*/ + ctr->count = l; + if (ctr->using_timer) + timer_set_delay_u64(&ctr->timer, (uint64_t) (l * PITCONST)); + pitf_ctr_set_out(ctr, 0); + ctr->thit = 0; + ctr->enabled = ctr->gate; + break; + case 1: /*Hardware retriggerable one-shot*/ + ctr->enabled = 1; + break; + case 2: /*Rate generator*/ + if (ctr->initial) { + ctr->count = l - 1; + if (ctr->using_timer) + timer_set_delay_u64(&ctr->timer, (uint64_t) ((l - 1) * PITCONST)); + pitf_ctr_set_out(ctr, 1); + ctr->thit = 0; + } + ctr->enabled = ctr->gate; + break; + case 3: /*Square wave mode*/ + if (ctr->initial) { + ctr->count = l; + if (ctr->using_timer) + timer_set_delay_u64(&ctr->timer, (uint64_t) (((l + 1) >> 1) * PITCONST)); + pitf_ctr_set_out(ctr, 1); + ctr->thit = 0; + } + ctr->enabled = ctr->gate; + break; + case 4: /*Software triggered stobe*/ + if (!ctr->thit && !ctr->initial) + ctr->newcount = 1; + else { + ctr->count = l; + if (ctr->using_timer) + timer_set_delay_u64(&ctr->timer, (uint64_t) (l * PITCONST)); + pitf_ctr_set_out(ctr, 0); + ctr->thit = 0; + } + ctr->enabled = ctr->gate; + break; + case 5: /*Hardware triggered stobe*/ + ctr->enabled = 1; + break; + + default: + break; + } + + if (ctr->load_func != NULL) + ctr->load_func(ctr->m, l); + + ctr->initial = 0; + ctr->running = ctr->enabled && ctr->using_timer && !ctr->disabled; + if (ctr->using_timer && !ctr->running) + pitf_dump_and_disable_timer(ctr); +} + +static void +pitf_set_gate_no_timer(ctrf_t *ctr, int gate) +{ + int l = ctr->l ? ctr->l : 0x10000; + + if (ctr->disabled) { + ctr->gate = gate; + return; + } + + switch (ctr->m) { + case 0: /*Interrupt on terminal count*/ + case 4: /*Software triggered stobe*/ + if (ctr->using_timer && !ctr->running) + timer_set_delay_u64(&ctr->timer, (uint64_t) (l * PITCONST)); + ctr->enabled = gate; + break; + case 1: /*Hardware retriggerable one-shot*/ + case 5: /*Hardware triggered stobe*/ + if (gate && !ctr->gate) { + ctr->count = l; + if (ctr->using_timer) + timer_set_delay_u64(&ctr->timer, (uint64_t) (l * PITCONST)); + pitf_ctr_set_out(ctr, 0); + ctr->thit = 0; + ctr->enabled = 1; + } + break; + case 2: /*Rate generator*/ + if (gate && !ctr->gate) { + ctr->count = l - 1; + if (ctr->using_timer) + timer_set_delay_u64(&ctr->timer, (uint64_t) (l * PITCONST)); + pitf_ctr_set_out(ctr, 1); + ctr->thit = 0; + } + ctr->enabled = gate; + break; + case 3: /*Square wave mode*/ + if (gate && !ctr->gate) { + ctr->count = l; + if (ctr->using_timer) + timer_set_delay_u64(&ctr->timer, (uint64_t) (((l + 1) >> 1) * PITCONST)); + pitf_ctr_set_out(ctr, 1); + ctr->thit = 0; + } + ctr->enabled = gate; + break; + + default: + break; + } + ctr->gate = gate; + ctr->running = ctr->enabled && ctr->using_timer && !ctr->disabled; + if (ctr->using_timer && !ctr->running) + pitf_dump_and_disable_timer(ctr); +} + +static void +pitf_ctr_set_gate(void *data, int counter_id, int gate) +{ + pitf_t *pit = (pitf_t *) data; + ctrf_t *ctr = &pit->counters[counter_id]; + + if (ctr->disabled) { + ctr->gate = gate; + return; + } + + pitf_set_gate_no_timer(ctr, gate); +} + +static void +pitf_over(ctrf_t *ctr) +{ + int l = ctr->l ? ctr->l : 0x10000; + if (ctr->disabled) { + ctr->count += 0xffff; + if (ctr->using_timer) + timer_advance_u64(&ctr->timer, (uint64_t) (0xffff * PITCONST)); + return; + } + + switch (ctr->m) { + case 0: /*Interrupt on terminal count*/ + case 1: /*Hardware retriggerable one-shot*/ + if (!ctr->thit) + pitf_ctr_set_out(ctr, 1); + ctr->thit = 1; + ctr->count += 0xffff; + if (ctr->using_timer) + timer_advance_u64(&ctr->timer, (uint64_t) (0xffff * PITCONST)); + break; + case 2: /*Rate generator*/ + ctr->count += l; + if (ctr->using_timer) + timer_advance_u64(&ctr->timer, (uint64_t) (l * PITCONST)); + pitf_ctr_set_out(ctr, 0); + pitf_ctr_set_out(ctr, 1); + break; + case 3: /*Square wave mode*/ + if (ctr->out) { + pitf_ctr_set_out(ctr, 0); + ctr->count += (l >> 1); + if (ctr->using_timer) + timer_advance_u64(&ctr->timer, (uint64_t) ((l >> 1) * PITCONST)); + } else { + pitf_ctr_set_out(ctr, 1); + ctr->count += ((l + 1) >> 1); + if (ctr->using_timer) + timer_advance_u64(&ctr->timer, (uint64_t) (((l + 1) >> 1) * PITCONST)); + } +#if 0 + if (!t) + pclog("pit_over: square wave mode c=%x %lli %f\n", pit.c[t], tsc, PITCONST); +#endif + break; + case 4: /*Software triggered strove*/ + if (!ctr->thit) { + pitf_ctr_set_out(ctr, 0); + pitf_ctr_set_out(ctr, 1); + } + if (ctr->newcount) { + ctr->newcount = 0; + ctr->count += l; + if (ctr->using_timer) + timer_advance_u64(&ctr->timer, (uint64_t) (l * PITCONST)); + } else { + ctr->thit = 1; + ctr->count += 0xffff; + if (ctr->using_timer) + timer_advance_u64(&ctr->timer, (uint64_t) (0xffff * PITCONST)); + } + break; + case 5: /*Hardware triggered strove*/ + if (!ctr->thit) { + pitf_ctr_set_out(ctr, 0); + pitf_ctr_set_out(ctr, 1); + } + ctr->thit = 1; + ctr->count += 0xffff; + if (ctr->using_timer) + timer_advance_u64(&ctr->timer, (uint64_t) (0xffff * PITCONST)); + break; + + default: + break; + } + ctr->running = ctr->enabled && ctr->using_timer && !ctr->disabled; + if (ctr->using_timer && !ctr->running) + pitf_dump_and_disable_timer(ctr); +} + +static __inline void +pitf_ctr_latch_count(ctrf_t *ctr) +{ + ctr->rl = pitf_read_timer(ctr); +#if 0 + pclog("Timer latch %f %04X %04X\n",pit->c[0],pit->rl[0],pit->l[0]); + pit->ctrl |= 0x30; +#endif + ctr->rereadlatch = 0; + ctr->rm = 3; + ctr->latched = 1; +} + +static __inline void +pitf_ctr_latch_status(ctrf_t *ctr) +{ + ctr->read_status = (ctr->ctrl & 0x3f) | (ctr->out ? 0x80 : 0); + ctr->do_read_status = 1; +} + +static void +pitf_write(uint16_t addr, uint8_t val, void *priv) +{ + pitf_t *dev = (pitf_t *) priv; + int t = (addr & 3); + ctrf_t *ctr; + + pit_log("[%04X:%08X] pit_write(%04X, %02X, %08X)\n", CS, cpu_state.pc, addr, val, priv); + + cycles -= ISA_CYCLES(8); + + switch (addr & 3) { + case 3: /* control */ + t = val >> 6; + + if (t == 3) { + if (dev->flags & PIT_8254) { + /* This is 8254-only. */ + if (!(val & 0x20)) { + if (val & 2) + pitf_ctr_latch_count(&dev->counters[0]); + if (val & 4) + pitf_ctr_latch_count(&dev->counters[1]); + if (val & 8) + pitf_ctr_latch_count(&dev->counters[2]); + pit_log("PIT %i: Initiated readback command\n", t); + } + if (!(val & 0x10)) { + if (val & 2) + pitf_ctr_latch_status(&dev->counters[0]); + if (val & 4) + pitf_ctr_latch_status(&dev->counters[1]); + if (val & 8) + pitf_ctr_latch_status(&dev->counters[2]); + } + } + } else { + dev->ctrl = val; + ctr = &dev->counters[t]; + + if (!(dev->ctrl & 0x30)) { + pitf_ctr_latch_count(ctr); + dev->ctrl |= 0x30; + pit_log("PIT %i: Initiated latched read, %i bytes latched\n", + t, ctr->latched); + } else { + ctr->ctrl = val; + ctr->rm = ctr->wm = (ctr->ctrl >> 4) & 3; + ctr->m = (val >> 1) & 7; + if (ctr->m > 5) + ctr->m &= 3; + if (!(ctr->rm)) { + ctr->rm = 3; + ctr->rl = pitf_read_timer(ctr); + } + ctr->rereadlatch = 1; + ctr->initial = 1; + if (!ctr->m) + pitf_ctr_set_out(ctr, 0); + else + pitf_ctr_set_out(ctr, 1); + ctr->disabled = 1; + + pit_log("PIT %i: M = %i, RM/WM = %i, State = %i, Out = %i\n", t, ctr->m, ctr->rm, ctr->state, ctr->out); + } + ctr->thit = 0; + } + break; + + case 0: + case 1: + case 2: /* the actual timers */ + ctr = &dev->counters[t]; + + switch (ctr->wm) { + case 1: + ctr->l = val; + pitf_ctr_load(ctr); + break; + case 2: + ctr->l = (val << 8); + pitf_ctr_load(ctr); + break; + case 0: + ctr->l &= 0xFF; + ctr->l |= (val << 8); + pitf_ctr_load(ctr); + ctr->wm = 3; + break; + case 3: + ctr->l &= 0xFF00; + ctr->l |= val; + ctr->wm = 0; + break; + + default: + break; + } + break; + + default: + break; + } +} + +uint8_t +pitf_read_reg(void *priv, uint8_t reg) +{ + pitf_t *dev = (pitf_t *) priv; + uint8_t ret = 0xff; + + switch (reg) { + case 0x00: + case 0x02: + case 0x04: + ret = dev->counters[reg >> 1].l & 0xff; + break; + case 0x01: + case 0x03: + case 0x05: + ret = (dev->counters[reg >> 1].l >> 8) & 0xff; + break; + case 0x06: + ret = dev->ctrl; + break; + case 0x07: + /* The SiS 551x datasheet is unclear about how exactly + this register is structured. */ + ret = (dev->counters[0].rm & 0x80) ? 0x01 : 0x00; + ret = (dev->counters[0].wm & 0x80) ? 0x02 : 0x00; + ret = (dev->counters[1].rm & 0x80) ? 0x04 : 0x00; + ret = (dev->counters[1].wm & 0x80) ? 0x08 : 0x00; + ret = (dev->counters[2].rm & 0x80) ? 0x10 : 0x00; + ret = (dev->counters[2].wm & 0x80) ? 0x20 : 0x00; + break; + } + + return ret; +} + +static uint8_t +pitf_read(uint16_t addr, void *priv) +{ + pitf_t *dev = (pitf_t *) priv; + uint8_t ret = 0xff; + int t = (addr & 3); + ctrf_t *ctr; + + cycles -= ISA_CYCLES(8); + + switch (addr & 3) { + case 3: /* Control. */ + /* This is 8254-only, 8253 returns 0x00. */ + ret = (dev->flags & PIT_8254) ? dev->ctrl : 0x00; + break; + + case 0: + case 1: + case 2: /* The actual timers. */ + ctr = &dev->counters[t]; + + if (ctr->do_read_status) { + ctr->do_read_status = 0; + ret = ctr->read_status; + break; + } + + if (ctr->rereadlatch && !ctr->latched) { + ctr->rereadlatch = 0; + ctr->rl = pitf_read_timer(ctr); + } + switch (ctr->rm) { + case 0: + ret = ctr->rl >> 8; + ctr->rm = 3; + ctr->latched = 0; + ctr->rereadlatch = 1; + break; + case 1: + ret = (ctr->rl) & 0xFF; + ctr->latched = 0; + ctr->rereadlatch = 1; + break; + case 2: + ret = (ctr->rl) >> 8; + ctr->latched = 0; + ctr->rereadlatch = 1; + break; + case 3: + ret = (ctr->rl) & 0xFF; + if (ctr->m & 0x80) + ctr->m &= 7; + else + ctr->rm = 0; + break; + + default: + break; + } + break; + + default: + break; + } + + pit_log("[%04X:%08X] pit_read(%04X, %08X) = %02X\n", CS, cpu_state.pc, addr, priv, ret); + + return ret; +} + +static void +pitf_timer_over(void *priv) +{ + ctrf_t *ctr = (ctrf_t *) priv; + pitf_over(ctr); +} + +static void +pitf_ctr_clock(void *data, int counter_id) +{ + pitf_t *pit = (pitf_t *) data; + ctrf_t *ctr = &pit->counters[counter_id]; + + if (ctr->thit || !ctr->enabled) + return; + + if (ctr->using_timer) + return; + + ctr->count -= (ctr->m == 3) ? 2 : 1; + if (!ctr->count) + pitf_over(ctr); +} + +static void +ctr_reset(ctrf_t *ctr) +{ + ctr->ctrl = 0; + ctr->m = 0; + ctr->gate = 0; + ctr->l = 0xffff; + ctr->thit = 1; + ctr->using_timer = 1; +} + +static void +pitf_reset(pitf_t *dev) +{ + memset(dev, 0, sizeof(pitf_t)); + + for (uint8_t i = 0; i < 3; i++) + ctr_reset(&dev->counters[i]); + + /* Disable speaker gate. */ + dev->counters[2].gate = 0; +} + +static void +pitf_close(void *priv) +{ + pitf_t *dev = (pitf_t *) priv; + + if (dev == pit_devs[0].data) + pit_devs[0].data = NULL; + + if (dev == pit_devs[1].data) + pit_devs[1].data = NULL; + + if (dev != NULL) + free(dev); +} + +static void * +pitf_init(const device_t *info) +{ + pitf_t *dev = (pitf_t *) malloc(sizeof(pitf_t)); + pitf_reset(dev); + + dev->flags = info->local; + + if (!(dev->flags & PIT_PS2) && !(dev->flags & PIT_CUSTOM_CLOCK)) { + for (int i = 0; i < 3; i++) { + ctrf_t *ctr = &dev->counters[i]; + timer_add(&ctr->timer, pitf_timer_over, (void *) ctr, 0); + } + } + + if (!(dev->flags & PIT_EXT_IO)) { + io_sethandler((dev->flags & PIT_SECONDARY) ? 0x0048 : 0x0040, 0x0004, + pitf_read, NULL, NULL, pitf_write, NULL, NULL, dev); + } + + return dev; +} + +const device_t i8253_fast_device = { + .name = "Intel 8253/8253-5 Programmable Interval Timer", + .internal_name = "i8253_fast", + .flags = DEVICE_ISA | DEVICE_PIT, + .local = PIT_8253, + .init = pitf_init, + .close = pitf_close, + .reset = NULL, + { .available = NULL }, + .speed_changed = NULL, + .force_redraw = NULL, + .config = NULL +}; + +const device_t i8254_fast_device = { + .name = "Intel 8254 Programmable Interval Timer", + .internal_name = "i8254_fast", + .flags = DEVICE_ISA | DEVICE_PIT, + .local = PIT_8254, + .init = pitf_init, + .close = pitf_close, + .reset = NULL, + { .available = NULL }, + .speed_changed = NULL, + .force_redraw = NULL, + .config = NULL +}; + +const device_t i8254_sec_fast_device = { + .name = "Intel 8254 Programmable Interval Timer (Secondary)", + .internal_name = "i8254_sec_fast", + .flags = DEVICE_ISA, + .local = PIT_8254 | PIT_SECONDARY, + .init = pitf_init, + .close = pitf_close, + .reset = NULL, + { .available = NULL }, + .speed_changed = NULL, + .force_redraw = NULL, + .config = NULL +}; + +const device_t i8254_ext_io_fast_device = { + .name = "Intel 8254 Programmable Interval Timer (External I/O)", + .internal_name = "i8254_ext_io_fast", + .flags = DEVICE_ISA, + .local = PIT_8254 | PIT_EXT_IO, + .init = pitf_init, + .close = pitf_close, + .reset = NULL, + { .available = NULL }, + .speed_changed = NULL, + .force_redraw = NULL, + .config = NULL +}; + +const device_t i8254_ps2_fast_device = { + .name = "Intel 8254 Programmable Interval Timer (PS/2)", + .internal_name = "i8254_ps2_fast", + .flags = DEVICE_ISA, + .local = PIT_8254 | PIT_PS2 | PIT_EXT_IO, + .init = pitf_init, + .close = pitf_close, + .reset = NULL, + { .available = NULL }, + .speed_changed = NULL, + .force_redraw = NULL, + .config = NULL +}; + +const pit_intf_t pit_fast_intf = { + &pitf_read, + &pitf_write, + &pitf_ctr_get_count, + &pitf_ctr_set_gate, + &pitf_ctr_set_using_timer, + &pitf_ctr_set_out_func, + &pitf_ctr_set_load_func, + &pitf_ctr_clock, + NULL, +}; diff --git a/src/port_6x.c b/src/port_6x.c index ef6c8365d..750b9678c 100644 --- a/src/port_6x.c +++ b/src/port_6x.c @@ -1,17 +1,19 @@ /* - * 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. + * 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. + * This file is part of the 86Box distribution. * - * Implementation of Ports 61, 62, and 63 used by various - * machines. + * Implementation of Ports 61, 62, and 63 used by various + * machines. * - * Authors: Miran Grca, * - * Copyright 2021 Miran Grca. + * + * Authors: Miran Grca, + * + * Copyright 2021 Miran Grca. */ #include #include @@ -34,107 +36,121 @@ #include <86box/ppi.h> #include <86box/video.h> #include <86box/port_6x.h> +#include <86box/plat_unused.h> +#include <86box/random.h> +#define PS2_REFRESH_TIME (16 * TIMER_USEC) -#define PS2_REFRESH_TIME (16 * TIMER_USEC) - -#define PORT_6X_TURBO 1 -#define PORT_6X_EXT_REF 2 -#define PORT_6X_MIRROR 4 -#define PORT_6X_SWA 8 - +#define PORT_6X_TURBO 1 +#define PORT_6X_EXT_REF 2 +#define PORT_6X_MIRROR 4 +#define PORT_6X_SWA 8 static void port_6x_write(uint16_t port, uint8_t val, void *priv) { - port_6x_t *dev = (port_6x_t *) priv; + const port_6x_t *dev = (port_6x_t *) priv; port &= 3; + cycles -= ISA_CYCLES(8); + if ((port == 3) && (dev->flags & PORT_6X_MIRROR)) - port = 1; + port = 1; switch (port) { - case 1: - ppi.pb = (ppi.pb & 0x10) | (val & 0x0f); + case 1: + ppi.pb = (ppi.pb & 0x10) | (val & 0x0f); - speaker_update(); - speaker_gated = val & 1; - speaker_enable = val & 2; - if (speaker_enable) - was_speaker_enable = 1; - pit_ctr_set_gate(&pit->counters[2], val & 1); + speaker_update(); + speaker_gated = val & 1; + speaker_enable = val & 2; + if (speaker_enable) + was_speaker_enable = 1; + pit_devs[0].set_gate(pit_devs[0].data, 2, val & 1); - if (dev->flags & PORT_6X_TURBO) - xi8088_turbo_set(!!(val & 0x04)); - break; + if (dev->flags & PORT_6X_TURBO) + xi8088_turbo_set(!!(val & 0x04)); + break; + + default: + break; } } - static uint8_t -port_6x_read(uint16_t port, void *priv) +port_61_read_simple(UNUSED(uint16_t port), UNUSED(void *priv)) { - port_6x_t *dev = (port_6x_t *) priv; - uint8_t ret = 0xff; + uint8_t ret = ppi.pb & 0x1f; - port &= 3; + cycles -= ISA_CYCLES(8); - if ((port == 3) && (dev->flags & PORT_6X_MIRROR)) - port = 1; + if (ppispeakon) + ret |= 0x20; - switch (port) { - case 1: - if (dev->flags & PORT_6X_EXT_REF) { - ret = ppi.pb & 0x0f; - - if (dev->refresh) - ret |= 0x10; - } else - ret = ppi.pb & 0x1f; - - if (ppispeakon) - ret |= 0x20; - - if (dev->flags & PORT_6X_TURBO) - ret = (ret & 0xfb) | (xi8088_turbo_get() ? 0x04 : 0x00); - break; - case 2: - if (dev->flags & PORT_6X_SWA) { - /* SWA on Olivetti M240 mainboard (off=1) */ - ret = 0x00; - if (ppi.pb & 0x8) { - /* Switches 4, 5 - floppy drives (number) */ - int i, fdd_count = 0; - for (i = 0; i < FDD_NUM; i++) { - if (fdd_get_flags(i)) - fdd_count++; - } - if (!fdd_count) - ret |= 0x00; - else - ret |= ((fdd_count - 1) << 2); - /* Switches 6, 7 - monitor type */ - if (video_is_mda()) - ret |= 0x3; - else if (video_is_cga()) - ret |= 0x2; /* 0x10 would be 40x25 */ - else - ret |= 0x0; - } else { - /* bit 2 always on */ - ret |= 0x4; - /* Switch 8 - 8087 FPU. */ - if (hasfpu) - ret |= 0x02; - } - } - break; - } - - return(ret); + return ret; } +static uint8_t +port_61_read(UNUSED(uint16_t port), void *priv) +{ + const port_6x_t *dev = (port_6x_t *) priv; + uint8_t ret = 0xff; + + cycles -= ISA_CYCLES(8); + + if (dev->flags & PORT_6X_EXT_REF) { + ret = ppi.pb & 0x0f; + + if (dev->refresh) + ret |= 0x10; + } else + ret = ppi.pb & 0x1f; + + if (ppispeakon) + ret |= 0x20; + + if (dev->flags & PORT_6X_TURBO) + ret = (ret & 0xfb) | (xi8088_turbo_get() ? 0x04 : 0x00); + + return ret; +} + +static uint8_t +port_62_read(UNUSED(uint16_t port), UNUSED(void *priv)) +{ + uint8_t ret = 0xff; + + /* SWA on Olivetti M240 mainboard (off=1) */ + ret = 0x00; + if (ppi.pb & 0x8) { + /* Switches 4, 5 - floppy drives (number) */ + int fdd_count = 0; + for (uint8_t i = 0; i < FDD_NUM; i++) { + if (fdd_get_flags(i)) + fdd_count++; + } + if (!fdd_count) + ret |= 0x00; + else + ret |= ((fdd_count - 1) << 2); + /* Switches 6, 7 - monitor type */ + if (video_is_mda()) + ret |= 0x3; + else if (video_is_cga()) + ret |= 0x2; /* 0x10 would be 40x25 */ + else + ret |= 0x0; + } else { + /* bit 2 always on */ + ret |= 0x4; + /* Switch 8 - 8087 FPU. */ + if (hasfpu) + ret |= 0x02; + } + + return ret; +} static void port_6x_refresh(void *priv) @@ -145,7 +161,6 @@ port_6x_refresh(void *priv) timer_advance_u64(&dev->refresh_timer, PS2_REFRESH_TIME); } - static void port_6x_close(void *priv) { @@ -156,7 +171,6 @@ port_6x_close(void *priv) free(dev); } - void * port_6x_init(const device_t *info) { @@ -165,54 +179,79 @@ port_6x_init(const device_t *info) dev->flags = info->local & 0xff; - io_sethandler(0x0061, 3, port_6x_read, NULL, NULL, port_6x_write, NULL, NULL, dev); + if (dev->flags & (PORT_6X_TURBO | PORT_6X_EXT_REF)) { + io_sethandler(0x0061, 1, port_61_read, NULL, NULL, port_6x_write, NULL, NULL, dev); - if (dev->flags & PORT_6X_EXT_REF) - timer_add(&dev->refresh_timer, port_6x_refresh, dev, 1); + if (dev->flags & PORT_6X_EXT_REF) + timer_add(&dev->refresh_timer, port_6x_refresh, dev, 1); + + if (dev->flags & PORT_6X_MIRROR) + io_sethandler(0x0063, 1, port_61_read, NULL, NULL, port_6x_write, NULL, NULL, dev); + } else { + io_sethandler(0x0061, 1, port_61_read_simple, NULL, NULL, port_6x_write, NULL, NULL, dev); + + if (dev->flags & PORT_6X_MIRROR) + io_sethandler(0x0063, 1, port_61_read_simple, NULL, NULL, port_6x_write, NULL, NULL, dev); + } + + if (dev->flags & PORT_6X_SWA) + io_sethandler(0x0062, 1, port_62_read, NULL, NULL, NULL, NULL, NULL, dev); return dev; } - const device_t port_6x_device = { - "Port 6x Registers", - "port_6x", - 0, - 0, - port_6x_init, port_6x_close, NULL, - { NULL }, NULL, NULL, - NULL + .name = "Port 6x Registers", + .internal_name = "port_6x", + .flags = 0, + .local = 0, + .init = port_6x_init, + .close = port_6x_close, + .reset = NULL, + { .available = NULL }, + .speed_changed = NULL, + .force_redraw = NULL, + .config = NULL }; - const device_t port_6x_xi8088_device = { - "Port 6x Registers (Xi8088)", - "port_6x_xi8088", - 0, - PORT_6X_TURBO | PORT_6X_EXT_REF | PORT_6X_MIRROR, - port_6x_init, port_6x_close, NULL, - { NULL }, NULL, NULL, - NULL + .name = "Port 6x Registers (Xi8088)", + .internal_name = "port_6x_xi8088", + .flags = 0, + .local = PORT_6X_TURBO | PORT_6X_EXT_REF | PORT_6X_MIRROR, + .init = port_6x_init, + .close = port_6x_close, + .reset = NULL, + { .available = NULL }, + .speed_changed = NULL, + .force_redraw = NULL, + .config = NULL }; - const device_t port_6x_ps2_device = { - "Port 6x Registers (IBM PS/2)", - "port_6x_ps2", - 0, - PORT_6X_EXT_REF, - port_6x_init, port_6x_close, NULL, - { NULL }, NULL, NULL, - NULL + .name = "Port 6x Registers (IBM PS/2)", + .internal_name = "port_6x_ps2", + .flags = 0, + .local = PORT_6X_EXT_REF, + .init = port_6x_init, + .close = port_6x_close, + .reset = NULL, + { .available = NULL }, + .speed_changed = NULL, + .force_redraw = NULL, + .config = NULL }; - const device_t port_6x_olivetti_device = { - "Port 6x Registers (Olivetti)", - "port_6x_olivetti", - 0, - PORT_6X_SWA, - port_6x_init, port_6x_close, NULL, - { NULL }, NULL, NULL, - NULL + .name = "Port 6x Registers (Olivetti)", + .internal_name = "port_6x_olivetti", + .flags = 0, + .local = PORT_6X_SWA, + .init = port_6x_init, + .close = port_6x_close, + .reset = NULL, + { .available = NULL }, + .speed_changed = NULL, + .force_redraw = NULL, + .config = NULL }; diff --git a/src/port_92.c b/src/port_92.c index 6981a3596..1307ecba9 100644 --- a/src/port_92.c +++ b/src/port_92.c @@ -1,19 +1,19 @@ /* - * 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. + * 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. + * This file is part of the 86Box distribution. * - * Implementation of Port 92 used by PS/2 machines and 386+ - * clones. + * Implementation of Port 92 used by PS/2 machines and 386+ + * clones. * * * - * Authors: Miran Grca, + * Authors: Miran Grca, * - * Copyright 2019 Miran Grca. + * Copyright 2019 Miran Grca. */ #include #include @@ -29,58 +29,60 @@ #include <86box/mem.h> #include <86box/pit.h> #include <86box/port_92.h> +#include <86box/plat_unused.h> - -#define PORT_92_INV 1 -#define PORT_92_WORD 2 -#define PORT_92_PCI 4 -#define PORT_92_RESET 8 -#define PORT_92_A20 16 - +#define PORT_92_INV 1 +#define PORT_92_WORD 2 +#define PORT_92_PCI 4 +#define PORT_92_RESET 8 +#define PORT_92_A20 16 static uint8_t port_92_readb(uint16_t port, void *priv) { - uint8_t ret = 0x00; - port_92_t *dev = (port_92_t *) priv; + uint8_t ret = 0x00; + const port_92_t *dev = (port_92_t *) priv; if (port == 0x92) { - /* Return bit 1 directly from mem_a20_alt, so the - pin can be reset independently of the device. */ - ret = (dev->reg & ~0x03) | (mem_a20_alt & 2) | - (cpu_alt_reset & 1); + /* Return bit 1 directly from mem_a20_alt, so the + pin can be reset independently of the device. */ + ret = (dev->reg & ~0x03) | (mem_a20_alt & 2) | (cpu_alt_reset & 1); - if (dev->flags & PORT_92_INV) - ret |= 0xfc; - else if (dev->flags & PORT_92_PCI) - ret |= 0x24; /* Intel SIO datasheet says bits 2 and 5 are always 1. */ + if (dev->flags & PORT_92_INV) + ret |= 0xfc; + else if (dev->flags & PORT_92_PCI) + ret |= 0x24; /* Intel SIO datasheet says bits 2 and 5 are always 1. */ } else if (dev->flags & PORT_92_INV) - ret = 0xff; + ret = 0xff; return ret; } - static uint16_t port_92_readw(uint16_t port, void *priv) { - uint16_t ret = 0xffff; - port_92_t *dev = (port_92_t *) priv; + uint16_t ret = 0xffff; + const port_92_t *dev = (port_92_t *) priv; if (!(dev->flags & PORT_92_PCI)) - ret = port_92_readb(port, priv); + ret = port_92_readb(port, priv); return ret; } - +/* + This does the exact same thing as keyboard controller reset. + TODO: ALi M1543(c) behavior. + */ static void -port_92_pulse(void *priv) +port_92_pulse(UNUSED(void *priv)) { - resetx86(); + softresetx86(); /* Pulse reset! */ cpu_set_edx(); -} + flushmmucache(); + cpu_alt_reset = 1; +} static void port_92_writeb(uint16_t port, uint8_t val, void *priv) @@ -88,37 +90,35 @@ port_92_writeb(uint16_t port, uint8_t val, void *priv) port_92_t *dev = (port_92_t *) priv; if (port != 0x92) - return; + return; dev->reg = val & 0x03; if ((mem_a20_alt ^ val) & 2) { - mem_a20_alt = (val & 2); - mem_a20_recalc(); + mem_a20_alt = (val & 2); + mem_a20_recalc(); } if ((~cpu_alt_reset & val) & 1) - timer_set_delay_u64(&dev->pulse_timer, dev->pulse_period); + timer_set_delay_u64(&dev->pulse_timer, dev->pulse_period); else if (!(val & 1)) - timer_disable(&dev->pulse_timer); + timer_disable(&dev->pulse_timer); cpu_alt_reset = (val & 1); if (dev->flags & PORT_92_INV) - dev->reg |= 0xfc; + dev->reg |= 0xfc; } - static void port_92_writew(uint16_t port, uint16_t val, void *priv) { - port_92_t *dev = (port_92_t *) priv; + const port_92_t *dev = (port_92_t *) priv; if (!(dev->flags & PORT_92_PCI)) - port_92_writeb(port, val & 0xff, priv); + port_92_writeb(port, val & 0xff, priv); } - void port_92_set_period(void *priv, uint64_t pulse_period) { @@ -127,7 +127,6 @@ port_92_set_period(void *priv, uint64_t pulse_period) dev->pulse_period = pulse_period; } - void port_92_set_features(void *priv, int reset, int a20) { @@ -136,47 +135,53 @@ port_92_set_features(void *priv, int reset, int a20) dev->flags &= ~(PORT_92_RESET | PORT_92_A20); if (reset) - dev->flags |= PORT_92_RESET; + dev->flags |= PORT_92_RESET; timer_disable(&dev->pulse_timer); if (a20) { - dev->flags |= PORT_92_A20; - mem_a20_alt = (dev->reg & 2); + dev->flags |= PORT_92_A20; + mem_a20_alt = (dev->reg & 2); } else - mem_a20_alt = 0; + mem_a20_alt = 0; mem_a20_recalc(); } - void port_92_add(void *priv) { port_92_t *dev = (port_92_t *) priv; if (dev->flags & (PORT_92_WORD | PORT_92_PCI)) - io_sethandler(0x0092, 2, - port_92_readb, port_92_readw, NULL, port_92_writeb, port_92_writew, NULL, dev); + io_sethandler(0x0092, 2, + port_92_readb, port_92_readw, NULL, port_92_writeb, port_92_writew, NULL, dev); else - io_sethandler(0x0092, 1, - port_92_readb, NULL, NULL, port_92_writeb, NULL, NULL, dev); + io_sethandler(0x0092, 1, + port_92_readb, NULL, NULL, port_92_writeb, NULL, NULL, dev); } - void port_92_remove(void *priv) { port_92_t *dev = (port_92_t *) priv; if (dev->flags & (PORT_92_WORD | PORT_92_PCI)) - io_removehandler(0x0092, 2, - port_92_readb, port_92_readw, NULL, port_92_writeb, port_92_writew, NULL, dev); + io_removehandler(0x0092, 2, + port_92_readb, port_92_readw, NULL, port_92_writeb, port_92_writew, NULL, dev); else - io_removehandler(0x0092, 1, - port_92_readb, NULL, NULL, port_92_writeb, NULL, NULL, dev); + io_removehandler(0x0092, 1, + port_92_readb, NULL, NULL, port_92_writeb, NULL, NULL, dev); } +static void +port_92_reset(UNUSED(void *priv)) +{ + cpu_alt_reset = 0; + + mem_a20_alt = 0x00; + mem_a20_recalc(); +} static void port_92_close(void *priv) @@ -188,7 +193,6 @@ port_92_close(void *priv) free(dev); } - void * port_92_init(const device_t *info) { @@ -199,7 +203,7 @@ port_92_init(const device_t *info) timer_add(&dev->pulse_timer, port_92_pulse, dev, 0); - dev->reg = 0; + dev->reg = 0; mem_a20_alt = 0; mem_a20_recalc(); @@ -209,53 +213,65 @@ port_92_init(const device_t *info) port_92_add(dev); - dev->pulse_period = (uint64_t) (4.0 * SYSCLK * (double)(1ULL << 32ULL)); + dev->pulse_period = (uint64_t) (4.0 * SYSCLK * (double) (1ULL << 32ULL)); dev->flags |= (PORT_92_RESET | PORT_92_A20); return dev; } - const device_t port_92_device = { - "Port 92 Register", - "port_92", - 0, - 0, - port_92_init, port_92_close, NULL, - { NULL }, NULL, NULL, - NULL + .name = "Port 92 Register", + .internal_name = "port_92", + .flags = 0, + .local = 0, + .init = port_92_init, + .close = port_92_close, + .reset = NULL, + { .available = NULL }, + .speed_changed = NULL, + .force_redraw = NULL, + .config = NULL }; - const device_t port_92_inv_device = { - "Port 92 Register (inverted bits 2-7)", - "port_92_inv", - 0, - PORT_92_INV, - port_92_init, port_92_close, NULL, - { NULL }, NULL, NULL, - NULL + .name = "Port 92 Register (inverted bits 2-7)", + .internal_name = "port_92_inv", + .flags = 0, + .local = PORT_92_INV, + .init = port_92_init, + .close = port_92_close, + .reset = NULL, + { .available = NULL }, + .speed_changed = NULL, + .force_redraw = NULL, + .config = NULL }; - const device_t port_92_word_device = { - "Port 92 Register (16-bit)", - "port_92_word", - 0, - PORT_92_WORD, - port_92_init, port_92_close, NULL, - { NULL }, NULL, NULL, - NULL + .name = "Port 92 Register (16-bit)", + .internal_name = "port_92_word", + .flags = 0, + .local = PORT_92_WORD, + .init = port_92_init, + .close = port_92_close, + .reset = NULL, + { .available = NULL }, + .speed_changed = NULL, + .force_redraw = NULL, + .config = NULL }; - const device_t port_92_pci_device = { - "Port 92 Register (PCI)", - "port_92_pci", - 0, - PORT_92_PCI, - port_92_init, port_92_close, NULL, - { NULL }, NULL, NULL, - NULL + .name = "Port 92 Register (PCI)", + .internal_name = "port_92_pci", + .flags = 0, + .local = PORT_92_PCI, + .init = port_92_init, + .close = port_92_close, + .reset = port_92_reset, + { .available = NULL }, + .speed_changed = NULL, + .force_redraw = NULL, + .config = NULL }; diff --git a/src/ppi.c b/src/ppi.c index c70d01ece..54ac8d037 100644 --- a/src/ppi.c +++ b/src/ppi.c @@ -15,11 +15,9 @@ #include <86box/pit.h> #include <86box/ppi.h> - PPI ppi; int ppispeakon; - void ppi_reset(void) { diff --git a/src/printer/CMakeLists.txt b/src/printer/CMakeLists.txt index 0f6c0e38d..dea0c7fbe 100644 --- a/src/printer/CMakeLists.txt +++ b/src/printer/CMakeLists.txt @@ -1,16 +1,34 @@ # -# 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. +# 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. +# This file is part of the 86Box distribution. # -# CMake build script. +# CMake build script. # -# Authors: David HrdliÄka, +# Authors: David HrdliÄka, # -# Copyright 2020,2021 David HrdliÄka. +# Copyright 2020-2021 David HrdliÄka. # -add_library(print OBJECT png.c prt_cpmap.c prt_escp.c prt_text.c prt_ps.c) \ No newline at end of file +add_library(print OBJECT png.c prt_cpmap.c prt_escp.c prt_text.c prt_ps.c) + +if(APPLE) + find_library(GHOSTSCRIPT_LIB gs) + 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() + +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/png.c b/src/printer/png.c index 22488a9ba..c7443252b 100644 --- a/src/printer/png.c +++ b/src/printer/png.c @@ -1,36 +1,34 @@ /* - * VARCem Virtual ARchaeological Computer EMulator. - * An emulator of (mostly) x86-based PC systems and devices, - * using the ISA,EISA,VLB,MCA and PCI system buses, roughly - * spanning the era between 1981 and 1995. + * VARCem Virtual ARchaeological Computer EMulator. + * An emulator of (mostly) x86-based PC systems and devices, + * using the ISA,EISA,VLB,MCA and PCI system buses, roughly + * spanning the era between 1981 and 1995. * - * This file is part of the VARCem Project. - * - * Provide centralized access to the PNG image handler. + * Provide centralized access to the PNG image handler. * * * - * Author: Fred N. van Kempen, + * Authors: Fred N. van Kempen, * - * Copyright 2018 Fred N. van Kempen. + * Copyright 2018 Fred N. van Kempen. * - * Redistribution and use in source and binary forms, with - * or without modification, are permitted provided that the - * following conditions are met: + * Redistribution and use in source and binary forms, with + * or without modification, are permitted provided that the + * following conditions are met: * - * 1. Redistributions of source code must retain the entire - * above notice, this list of conditions and the following - * disclaimer. + * 1. Redistributions of source code must retain the entire + * above notice, this list of conditions and the following + * disclaimer. * - * 2. Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the - * following disclaimer in the documentation and/or other - * materials provided with the distribution. + * 2. Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the + * following disclaimer in the documentation and/or other + * materials provided with the distribution. * - * 3. Neither the name of the copyright holder nor the names - * of its contributors may be used to endorse or promote - * products derived from this software without specific - * prior written permission. + * 3. Neither the name of the copyright holder nor the names + * of its contributors may be used to endorse or promote + * products derived from this software without specific + * prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT @@ -44,6 +42,7 @@ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ +#include #include #include #include @@ -52,6 +51,7 @@ #include #define PNG_DEBUG 0 #include +#define HAVE_STDARG_H #include <86box/86box.h> #include <86box/plat.h> #include <86box/plat_dynld.h> @@ -60,210 +60,221 @@ #include <86box/png_struct.h> #ifdef _WIN32 -# define PATH_PNG_DLL "libpng16-16.dll" +# define PATH_PNG_DLL "libpng16-16.dll" #elif defined __APPLE__ -# define PATH_PNG_DLL "libpng16.dylib" +# define PATH_PNG_DLL "libpng16.dylib" #else -# define PATH_PNG_DLL "libpng16.so" +# define PATH_PNG_DLL "libpng16.so" #endif #ifndef PNG_Z_DEFAULT_STRATEGY -#define PNG_Z_DEFAULT_STRATEGY 1 +# define PNG_Z_DEFAULT_STRATEGY 1 #endif -# define PNGFUNC(x) png_ ## x - - -#ifdef ENABLE_ESCP_LOG -int png_do_log = ENABLE_ESCP_LOG; +#define PNGFUNC(x) png_##x +#ifdef ENABLE_PNG_LOG +int png_do_log = ENABLE_PNG_LOG; static void png_log(const char *fmt, ...) { va_list ap; - if (escp_do_log) { - va_start(ap, fmt); - pclog_ex(fmt, ap); - va_end(ap); + if (png_do_log) { + va_start(ap, fmt); + pclog_ex(fmt, ap); + va_end(ap); } } #else -#define png_log(fmt, ...) +# define png_log(fmt, ...) #endif - static void -error_handler(png_structp arg, const char *str) +error_handler(UNUSED(png_structp arg), UNUSED(const char *str)) { png_log("PNG: stream 0x%08lx error '%s'\n", arg, str); } - static void -warning_handler(png_structp arg, const char *str) +warning_handler(UNUSED(png_structp arg), UNUSED(const char *str)) { png_log("PNG: stream 0x%08lx warning '%s'\n", arg, str); } - /* Write the given image as an 8-bit GrayScale PNG image file. */ int png_write_gray(char *fn, int inv, uint8_t *pix, int16_t w, int16_t h) { - png_structp png = NULL; - png_infop info = NULL; - png_bytep row; - int16_t x, y; - FILE *fp; + png_structp png = NULL; + png_infop info = NULL; + png_bytep row; + FILE *fp; /* Create the image file. */ fp = plat_fopen(fn, "wb"); if (fp == NULL) { - /* Yes, this looks weird. */ - if (fp == NULL) - png_log("PNG: file %s could not be opened for writing!\n", fn); - else + /* Yes, this looks weird. */ + if (fp == NULL) + png_log("PNG: file %s could not be opened for writing!\n", fn); + else error: - png_log("PNG: fatal error, bailing out, error = %i\n", errno); - if (png != NULL) - PNGFUNC(destroy_write_struct)(&png, &info); - if (fp != NULL) - (void)fclose(fp); - return(0); + png_log("PNG: fatal error, bailing out, error = %i\n", errno); + if (png != NULL) + PNGFUNC(destroy_write_struct) + (&png, &info); + if (fp != NULL) + (void) fclose(fp); + return 0; } /* Initialize PNG stuff. */ png = PNGFUNC(create_write_struct)(PNG_LIBPNG_VER_STRING, NULL, - error_handler, warning_handler); + error_handler, warning_handler); if (png == NULL) { - png_log("PNG: create_write_struct failed!\n"); - goto error; + png_log("PNG: create_write_struct failed!\n"); + goto error; } info = PNGFUNC(create_info_struct)(png); if (info == NULL) { - png_log("PNG: create_info_struct failed!\n"); - goto error; + png_log("PNG: create_info_struct failed!\n"); + goto error; } + PNGFUNC(init_io) + (png, fp); - PNGFUNC(init_io)(png, fp); + PNGFUNC(set_IHDR) + (png, info, w, h, 8, PNG_COLOR_TYPE_GRAY, + PNG_INTERLACE_NONE, PNG_COMPRESSION_TYPE_DEFAULT, + PNG_FILTER_TYPE_DEFAULT); - PNGFUNC(set_IHDR)(png, info, w, h, 8, PNG_COLOR_TYPE_GRAY, - PNG_INTERLACE_NONE, PNG_COMPRESSION_TYPE_DEFAULT, - PNG_FILTER_TYPE_DEFAULT); - - PNGFUNC(write_info)(png, info); + PNGFUNC(write_info) + (png, info); /* Create a buffer for one scanline of pixels. */ - row = (png_bytep)malloc(PNGFUNC(get_rowbytes)(png, info)); + row = (png_bytep) malloc(PNGFUNC(get_rowbytes)(png, info)); /* Process all scanlines in the image. */ - for (y = 0; y < h; y++) { - for (x = 0; x < w; x++) { - /* Copy the pixel data. */ - if (inv) - row[x] = 255 - pix[(y * w) + x]; - else - row[x] = pix[(y * w) + x]; - } + for (int16_t y = 0; y < h; y++) { + for (int16_t x = 0; x < w; x++) { + /* Copy the pixel data. */ + if (inv) + row[x] = 255 - pix[(y * w) + x]; + else + row[x] = pix[(y * w) + x]; + } - /* Write image to the file. */ - PNGFUNC(write_rows)(png, &row, 1); + /* Write image to the file. */ + PNGFUNC(write_rows) + (png, &row, 1); } /* No longer need the row buffer. */ free(row); - PNGFUNC(write_end)(png, NULL); + PNGFUNC(write_end) + (png, NULL); - PNGFUNC(destroy_write_struct)(&png, &info); + PNGFUNC(destroy_write_struct) + (&png, &info); /* Clean up. */ - (void)fclose(fp); + (void) fclose(fp); - return(1); + return 1; } - /* Write the given BITMAP-format image as an 8-bit RGBA PNG image file. */ void png_write_rgb(char *fn, uint8_t *pix, int16_t w, int16_t h, uint16_t pitch, PALETTE palcol) { - png_structp png = NULL; - png_infop info = NULL; - png_bytep* rows; - png_color palette[256]; - FILE *fp; - int i; + png_structp png = NULL; + png_infop info = NULL; + png_bytep *rows; + png_color palette[256]; + FILE *fp; /* Create the image file. */ fp = plat_fopen(fn, "wb"); if (fp == NULL) { - png_log("PNG: File %s could not be opened for writing!\n", fn); + png_log("PNG: File %s could not be opened for writing!\n", fn); error: - if (png != NULL) - PNGFUNC(destroy_write_struct)(&png, &info); - if (fp != NULL) - (void)fclose(fp); - return; + if (png != NULL) + PNGFUNC(destroy_write_struct) + (&png, &info); + if (fp != NULL) + (void) fclose(fp); + return; } /* Initialize PNG stuff. */ png = PNGFUNC(create_write_struct)(PNG_LIBPNG_VER_STRING, NULL, - error_handler, warning_handler); + error_handler, warning_handler); if (png == NULL) { - png_log("PNG: create_write_struct failed!\n"); - goto error; + png_log("PNG: create_write_struct failed!\n"); + goto error; } info = PNGFUNC(create_info_struct)(png); if (info == NULL) { - png_log("PNG: create_info_struct failed!\n"); - goto error; + png_log("PNG: create_info_struct failed!\n"); + goto error; } /* Finalize the initing of png library */ - PNGFUNC(init_io)(png, fp); - PNGFUNC(set_compression_level)(png, 9); + PNGFUNC(init_io) + (png, fp); + PNGFUNC(set_compression_level) + (png, 9); /* set other zlib parameters */ - PNGFUNC(set_compression_mem_level)(png, 8); - PNGFUNC(set_compression_strategy)(png, PNG_Z_DEFAULT_STRATEGY); - PNGFUNC(set_compression_window_bits)(png, 15); - PNGFUNC(set_compression_method)(png, 8); - PNGFUNC(set_compression_buffer_size)(png, 8192); - - PNGFUNC(set_IHDR)(png, info, w, h, 8, PNG_COLOR_TYPE_PALETTE, - PNG_INTERLACE_NONE, PNG_COMPRESSION_TYPE_DEFAULT, - PNG_FILTER_TYPE_DEFAULT); + PNGFUNC(set_compression_mem_level) + (png, 8); + PNGFUNC(set_compression_strategy) + (png, PNG_Z_DEFAULT_STRATEGY); + PNGFUNC(set_compression_window_bits) + (png, 15); + PNGFUNC(set_compression_method) + (png, 8); + PNGFUNC(set_compression_buffer_size) + (png, 8192); - for (i = 0; i < 256; i++) { - palette[i].red = palcol[i].r; - palette[i].green = palcol[i].g; - palette[i].blue = palcol[i].b; + PNGFUNC(set_IHDR) + (png, info, w, h, 8, PNG_COLOR_TYPE_PALETTE, + PNG_INTERLACE_NONE, PNG_COMPRESSION_TYPE_DEFAULT, + PNG_FILTER_TYPE_DEFAULT); + + for (uint16_t i = 0; i < 256; i++) { + palette[i].red = palcol[i].r; + palette[i].green = palcol[i].g; + palette[i].blue = palcol[i].b; } - PNGFUNC(set_PLTE)(png, info, palette, 256); - + PNGFUNC(set_PLTE) + (png, info, palette, 256); + /* Create a buffer for scanlines of pixels. */ - rows = (png_bytep *)malloc(sizeof(png_bytep) * h); - for (i = 0; i < h; i++) { - /* Create a buffer for this scanline. */ - rows[i] = (pix + (i * pitch)); + rows = (png_bytep *) malloc(sizeof(png_bytep) * h); + for (int16_t i = 0; i < h; i++) { + /* Create a buffer for this scanline. */ + rows[i] = (pix + (i * pitch)); } - PNGFUNC(set_rows)(png, info, rows); - - PNGFUNC(write_png)(png, info, 0, NULL); + PNGFUNC(set_rows) + (png, info, rows); + + PNGFUNC(write_png) + (png, info, 0, NULL); /* Clean up. */ - (void)fclose(fp); + (void) fclose(fp); + + PNGFUNC(destroy_write_struct) + (&png, &info); - PNGFUNC(destroy_write_struct)(&png, &info); - /* No longer need the row buffers. */ free(rows); } diff --git a/src/printer/prt_cpmap.c b/src/printer/prt_cpmap.c index f5da0e91d..153008f35 100644 --- a/src/printer/prt_cpmap.c +++ b/src/printer/prt_cpmap.c @@ -1,40 +1,38 @@ /* - * VARCem Virtual ARchaeological Computer EMulator. - * An emulator of (mostly) x86-based PC systems and devices, - * using the ISA,EISA,VLB,MCA and PCI system buses, roughly - * spanning the era between 1981 and 1995. + * VARCem Virtual ARchaeological Computer EMulator. + * An emulator of (mostly) x86-based PC systems and devices, + * using the ISA,EISA,VLB,MCA and PCI system buses, roughly + * spanning the era between 1981 and 1995. * - * This file is part of the VARCem Project. - * - * Various ASCII to Unicode maps, for the various codepages. + * Various ASCII to Unicode maps, for the various codepages. * * * - * Authors: Michael Drüing, - * Fred N. van Kempen, + * Authors: Michael Drüing, + * Fred N. van Kempen, * - * Based on code by Frederic Weymann (originally for DosBox.) + * Based on code by Frederic Weymann (originally for DosBox.) * - * Copyright 2018 Michael Drüing. - * Copyright 2018 Fred N. van Kempen. + * Copyright 2018 Michael Drüing. + * Copyright 2018 Fred N. van Kempen. * - * Redistribution and use in source and binary forms, with - * or without modification, are permitted provided that the - * following conditions are met: + * Redistribution and use in source and binary forms, with + * or without modification, are permitted provided that the + * following conditions are met: * - * 1. Redistributions of source code must retain the entire - * above notice, this list of conditions and the following - * disclaimer. + * 1. Redistributions of source code must retain the entire + * above notice, this list of conditions and the following + * disclaimer. * - * 2. Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the - * following disclaimer in the documentation and/or other - * materials provided with the distribution. + * 2. Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the + * following disclaimer in the documentation and/or other + * materials provided with the distribution. * - * 3. Neither the name of the copyright holder nor the names - * of its contributors may be used to endorse or promote - * products derived from this software without specific - * prior written permission. + * 3. Neither the name of the copyright holder nor the names + * of its contributors may be used to endorse or promote + * products derived from this software without specific + * prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT @@ -54,540 +52,539 @@ #include #include #include <86box/86box.h> -#include <86box/plat.h> +#include <86box/plat.h> #include <86box/printer.h> - static const uint16_t cp437Map[256] = { - 0x0000,0x0001,0x0002,0x0003,0x0004,0x0005,0x0006,0x0007, - 0x0008,0x0009,0x000a,0x000b,0x000c,0x000d,0x000e,0x000f, - 0x0010,0x0011,0x0012,0x0013,0x0014,0x0015,0x0016,0x0017, - 0x0018,0x0019,0x001a,0x001b,0x001c,0x001d,0x001e,0x001f, - 0x0020,0x0021,0x0022,0x0023,0x0024,0x0025,0x0026,0x0027, - 0x0028,0x0029,0x002a,0x002b,0x002c,0x002d,0x002e,0x002f, - 0x0030,0x0031,0x0032,0x0033,0x0034,0x0035,0x0036,0x0037, - 0x0038,0x0039,0x003a,0x003b,0x003c,0x003d,0x003e,0x003f, - 0x0040,0x0041,0x0042,0x0043,0x0044,0x0045,0x0046,0x0047, - 0x0048,0x0049,0x004a,0x004b,0x004c,0x004d,0x004e,0x004f, - 0x0050,0x0051,0x0052,0x0053,0x0054,0x0055,0x0056,0x0057, - 0x0058,0x0059,0x005a,0x005b,0x005c,0x005d,0x005e,0x005f, - 0x0060,0x0061,0x0062,0x0063,0x0064,0x0065,0x0066,0x0067, - 0x0068,0x0069,0x006a,0x006b,0x006c,0x006d,0x006e,0x006f, - 0x0070,0x0071,0x0072,0x0073,0x0074,0x0075,0x0076,0x0077, - 0x0078,0x0079,0x007a,0x007b,0x007c,0x007d,0x007e,0x007f, - 0x00c7,0x00fc,0x00e9,0x00e2,0x00e4,0x00e0,0x00e5,0x00e7, - 0x00ea,0x00eb,0x00e8,0x00ef,0x00ee,0x00ec,0x00c4,0x00c5, - 0x00c9,0x00e6,0x00c6,0x00f4,0x00f6,0x00f2,0x00fb,0x00f9, - 0x00ff,0x00d6,0x00dc,0x00a2,0x00a3,0x00a5,0x20a7,0x0192, - 0x00e1,0x00ed,0x00f3,0x00fa,0x00f1,0x00d1,0x00aa,0x00ba, - 0x00bf,0x2310,0x00ac,0x00bd,0x00bc,0x00a1,0x00ab,0x00bb, - 0x2591,0x2592,0x2593,0x2502,0x2524,0x2561,0x2562,0x2556, - 0x2555,0x2563,0x2551,0x2557,0x255d,0x255c,0x255b,0x2510, - 0x2514,0x2534,0x252c,0x251c,0x2500,0x253c,0x255e,0x255f, - 0x255a,0x2554,0x2569,0x2566,0x2560,0x2550,0x256c,0x2567, - 0x2568,0x2564,0x2565,0x2559,0x2558,0x2552,0x2553,0x256b, - 0x256a,0x2518,0x250c,0x2588,0x2584,0x258c,0x2590,0x2580, - 0x03b1,0x00df,0x0393,0x03c0,0x03a3,0x03c3,0x00b5,0x03c4, - 0x03a6,0x0398,0x03a9,0x03b4,0x221e,0x03c6,0x03b5,0x2229, - 0x2261,0x00b1,0x2265,0x2264,0x2320,0x2321,0x00f7,0x2248, - 0x00b0,0x2219,0x00b7,0x221a,0x207f,0x00b2,0x25a0,0x00a0 + 0x0000, 0x0001, 0x0002, 0x0003, 0x0004, 0x0005, 0x0006, 0x0007, + 0x0008, 0x0009, 0x000a, 0x000b, 0x000c, 0x000d, 0x000e, 0x000f, + 0x0010, 0x0011, 0x0012, 0x0013, 0x0014, 0x0015, 0x0016, 0x0017, + 0x0018, 0x0019, 0x001a, 0x001b, 0x001c, 0x001d, 0x001e, 0x001f, + 0x0020, 0x0021, 0x0022, 0x0023, 0x0024, 0x0025, 0x0026, 0x0027, + 0x0028, 0x0029, 0x002a, 0x002b, 0x002c, 0x002d, 0x002e, 0x002f, + 0x0030, 0x0031, 0x0032, 0x0033, 0x0034, 0x0035, 0x0036, 0x0037, + 0x0038, 0x0039, 0x003a, 0x003b, 0x003c, 0x003d, 0x003e, 0x003f, + 0x0040, 0x0041, 0x0042, 0x0043, 0x0044, 0x0045, 0x0046, 0x0047, + 0x0048, 0x0049, 0x004a, 0x004b, 0x004c, 0x004d, 0x004e, 0x004f, + 0x0050, 0x0051, 0x0052, 0x0053, 0x0054, 0x0055, 0x0056, 0x0057, + 0x0058, 0x0059, 0x005a, 0x005b, 0x005c, 0x005d, 0x005e, 0x005f, + 0x0060, 0x0061, 0x0062, 0x0063, 0x0064, 0x0065, 0x0066, 0x0067, + 0x0068, 0x0069, 0x006a, 0x006b, 0x006c, 0x006d, 0x006e, 0x006f, + 0x0070, 0x0071, 0x0072, 0x0073, 0x0074, 0x0075, 0x0076, 0x0077, + 0x0078, 0x0079, 0x007a, 0x007b, 0x007c, 0x007d, 0x007e, 0x007f, + 0x00c7, 0x00fc, 0x00e9, 0x00e2, 0x00e4, 0x00e0, 0x00e5, 0x00e7, + 0x00ea, 0x00eb, 0x00e8, 0x00ef, 0x00ee, 0x00ec, 0x00c4, 0x00c5, + 0x00c9, 0x00e6, 0x00c6, 0x00f4, 0x00f6, 0x00f2, 0x00fb, 0x00f9, + 0x00ff, 0x00d6, 0x00dc, 0x00a2, 0x00a3, 0x00a5, 0x20a7, 0x0192, + 0x00e1, 0x00ed, 0x00f3, 0x00fa, 0x00f1, 0x00d1, 0x00aa, 0x00ba, + 0x00bf, 0x2310, 0x00ac, 0x00bd, 0x00bc, 0x00a1, 0x00ab, 0x00bb, + 0x2591, 0x2592, 0x2593, 0x2502, 0x2524, 0x2561, 0x2562, 0x2556, + 0x2555, 0x2563, 0x2551, 0x2557, 0x255d, 0x255c, 0x255b, 0x2510, + 0x2514, 0x2534, 0x252c, 0x251c, 0x2500, 0x253c, 0x255e, 0x255f, + 0x255a, 0x2554, 0x2569, 0x2566, 0x2560, 0x2550, 0x256c, 0x2567, + 0x2568, 0x2564, 0x2565, 0x2559, 0x2558, 0x2552, 0x2553, 0x256b, + 0x256a, 0x2518, 0x250c, 0x2588, 0x2584, 0x258c, 0x2590, 0x2580, + 0x03b1, 0x00df, 0x0393, 0x03c0, 0x03a3, 0x03c3, 0x00b5, 0x03c4, + 0x03a6, 0x0398, 0x03a9, 0x03b4, 0x221e, 0x03c6, 0x03b5, 0x2229, + 0x2261, 0x00b1, 0x2265, 0x2264, 0x2320, 0x2321, 0x00f7, 0x2248, + 0x00b0, 0x2219, 0x00b7, 0x221a, 0x207f, 0x00b2, 0x25a0, 0x00a0 }; static const uint16_t cp737Map[256] = { - 0x0000,0x0001,0x0002,0x0003,0x0004,0x0005,0x0006,0x0007, - 0x0008,0x0009,0x000a,0x000b,0x000c,0x000d,0x000e,0x000f, - 0x0010,0x0011,0x0012,0x0013,0x0014,0x0015,0x0016,0x0017, - 0x0018,0x0019,0x001a,0x001b,0x001c,0x001d,0x001e,0x001f, - 0x0020,0x0021,0x0022,0x0023,0x0024,0x0025,0x0026,0x0027, - 0x0028,0x0029,0x002a,0x002b,0x002c,0x002d,0x002e,0x002f, - 0x0030,0x0031,0x0032,0x0033,0x0034,0x0035,0x0036,0x0037, - 0x0038,0x0039,0x003a,0x003b,0x003c,0x003d,0x003e,0x003f, - 0x0040,0x0041,0x0042,0x0043,0x0044,0x0045,0x0046,0x0047, - 0x0048,0x0049,0x004a,0x004b,0x004c,0x004d,0x004e,0x004f, - 0x0050,0x0051,0x0052,0x0053,0x0054,0x0055,0x0056,0x0057, - 0x0058,0x0059,0x005a,0x005b,0x005c,0x005d,0x005e,0x005f, - 0x0060,0x0061,0x0062,0x0063,0x0064,0x0065,0x0066,0x0067, - 0x0068,0x0069,0x006a,0x006b,0x006c,0x006d,0x006e,0x006f, - 0x0070,0x0071,0x0072,0x0073,0x0074,0x0075,0x0076,0x0077, - 0x0078,0x0079,0x007a,0x007b,0x007c,0x007d,0x007e,0x007f, - 0x0391,0x0392,0x0393,0x0394,0x0395,0x0396,0x0397,0x0398, - 0x0399,0x039a,0x039b,0x039c,0x039d,0x039e,0x039f,0x03a0, - 0x03a1,0x03a3,0x03a4,0x03a5,0x03a6,0x03a7,0x03a8,0x03a9, - 0x03b1,0x03b2,0x03b3,0x03b4,0x03b5,0x03b6,0x03b7,0x03b8, - 0x03b9,0x03ba,0x03bb,0x03bc,0x03bd,0x03be,0x03bf,0x03c0, - 0x03c1,0x03c3,0x03c2,0x03c4,0x03c5,0x03c6,0x03c7,0x03c8, - 0x2591,0x2592,0x2593,0x2502,0x2524,0x2561,0x2562,0x2556, - 0x2555,0x2563,0x2551,0x2557,0x255d,0x255c,0x255b,0x2510, - 0x2514,0x2534,0x252c,0x251c,0x2500,0x253c,0x255e,0x255f, - 0x255a,0x2554,0x2569,0x2566,0x2560,0x2550,0x256c,0x2567, - 0x2568,0x2564,0x2565,0x2559,0x2558,0x2552,0x2553,0x256b, - 0x256a,0x2518,0x250c,0x2588,0x2584,0x258c,0x2590,0x2580, - 0x03c9,0x03ac,0x03ad,0x03ae,0x03ca,0x03af,0x03cc,0x03cd, - 0x03cb,0x03ce,0x0386,0x0388,0x0389,0x038a,0x038c,0x038e, - 0x038f,0x00b1,0x2265,0x2264,0x03aa,0x03ab,0x00f7,0x2248, - 0x00b0,0x2219,0x00b7,0x221a,0x207f,0x00b2,0x25a0,0x00a0 + 0x0000, 0x0001, 0x0002, 0x0003, 0x0004, 0x0005, 0x0006, 0x0007, + 0x0008, 0x0009, 0x000a, 0x000b, 0x000c, 0x000d, 0x000e, 0x000f, + 0x0010, 0x0011, 0x0012, 0x0013, 0x0014, 0x0015, 0x0016, 0x0017, + 0x0018, 0x0019, 0x001a, 0x001b, 0x001c, 0x001d, 0x001e, 0x001f, + 0x0020, 0x0021, 0x0022, 0x0023, 0x0024, 0x0025, 0x0026, 0x0027, + 0x0028, 0x0029, 0x002a, 0x002b, 0x002c, 0x002d, 0x002e, 0x002f, + 0x0030, 0x0031, 0x0032, 0x0033, 0x0034, 0x0035, 0x0036, 0x0037, + 0x0038, 0x0039, 0x003a, 0x003b, 0x003c, 0x003d, 0x003e, 0x003f, + 0x0040, 0x0041, 0x0042, 0x0043, 0x0044, 0x0045, 0x0046, 0x0047, + 0x0048, 0x0049, 0x004a, 0x004b, 0x004c, 0x004d, 0x004e, 0x004f, + 0x0050, 0x0051, 0x0052, 0x0053, 0x0054, 0x0055, 0x0056, 0x0057, + 0x0058, 0x0059, 0x005a, 0x005b, 0x005c, 0x005d, 0x005e, 0x005f, + 0x0060, 0x0061, 0x0062, 0x0063, 0x0064, 0x0065, 0x0066, 0x0067, + 0x0068, 0x0069, 0x006a, 0x006b, 0x006c, 0x006d, 0x006e, 0x006f, + 0x0070, 0x0071, 0x0072, 0x0073, 0x0074, 0x0075, 0x0076, 0x0077, + 0x0078, 0x0079, 0x007a, 0x007b, 0x007c, 0x007d, 0x007e, 0x007f, + 0x0391, 0x0392, 0x0393, 0x0394, 0x0395, 0x0396, 0x0397, 0x0398, + 0x0399, 0x039a, 0x039b, 0x039c, 0x039d, 0x039e, 0x039f, 0x03a0, + 0x03a1, 0x03a3, 0x03a4, 0x03a5, 0x03a6, 0x03a7, 0x03a8, 0x03a9, + 0x03b1, 0x03b2, 0x03b3, 0x03b4, 0x03b5, 0x03b6, 0x03b7, 0x03b8, + 0x03b9, 0x03ba, 0x03bb, 0x03bc, 0x03bd, 0x03be, 0x03bf, 0x03c0, + 0x03c1, 0x03c3, 0x03c2, 0x03c4, 0x03c5, 0x03c6, 0x03c7, 0x03c8, + 0x2591, 0x2592, 0x2593, 0x2502, 0x2524, 0x2561, 0x2562, 0x2556, + 0x2555, 0x2563, 0x2551, 0x2557, 0x255d, 0x255c, 0x255b, 0x2510, + 0x2514, 0x2534, 0x252c, 0x251c, 0x2500, 0x253c, 0x255e, 0x255f, + 0x255a, 0x2554, 0x2569, 0x2566, 0x2560, 0x2550, 0x256c, 0x2567, + 0x2568, 0x2564, 0x2565, 0x2559, 0x2558, 0x2552, 0x2553, 0x256b, + 0x256a, 0x2518, 0x250c, 0x2588, 0x2584, 0x258c, 0x2590, 0x2580, + 0x03c9, 0x03ac, 0x03ad, 0x03ae, 0x03ca, 0x03af, 0x03cc, 0x03cd, + 0x03cb, 0x03ce, 0x0386, 0x0388, 0x0389, 0x038a, 0x038c, 0x038e, + 0x038f, 0x00b1, 0x2265, 0x2264, 0x03aa, 0x03ab, 0x00f7, 0x2248, + 0x00b0, 0x2219, 0x00b7, 0x221a, 0x207f, 0x00b2, 0x25a0, 0x00a0 }; static const uint16_t cp775Map[256] = { - 0x0000,0x0001,0x0002,0x0003,0x0004,0x0005,0x0006,0x0007, - 0x0008,0x0009,0x000a,0x000b,0x000c,0x000d,0x000e,0x000f, - 0x0010,0x0011,0x0012,0x0013,0x0014,0x0015,0x0016,0x0017, - 0x0018,0x0019,0x001a,0x001b,0x001c,0x001d,0x001e,0x001f, - 0x0020,0x0021,0x0022,0x0023,0x0024,0x0025,0x0026,0x0027, - 0x0028,0x0029,0x002a,0x002b,0x002c,0x002d,0x002e,0x002f, - 0x0030,0x0031,0x0032,0x0033,0x0034,0x0035,0x0036,0x0037, - 0x0038,0x0039,0x003a,0x003b,0x003c,0x003d,0x003e,0x003f, - 0x0040,0x0041,0x0042,0x0043,0x0044,0x0045,0x0046,0x0047, - 0x0048,0x0049,0x004a,0x004b,0x004c,0x004d,0x004e,0x004f, - 0x0050,0x0051,0x0052,0x0053,0x0054,0x0055,0x0056,0x0057, - 0x0058,0x0059,0x005a,0x005b,0x005c,0x005d,0x005e,0x005f, - 0x0060,0x0061,0x0062,0x0063,0x0064,0x0065,0x0066,0x0067, - 0x0068,0x0069,0x006a,0x006b,0x006c,0x006d,0x006e,0x006f, - 0x0070,0x0071,0x0072,0x0073,0x0074,0x0075,0x0076,0x0077, - 0x0078,0x0079,0x007a,0x007b,0x007c,0x007d,0x007e,0x007f, - 0x0106,0x00fc,0x00e9,0x0101,0x00e4,0x0123,0x00e5,0x0107, - 0x0142,0x0113,0x0156,0x0157,0x012b,0x0179,0x00c4,0x00c5, - 0x00c9,0x00e6,0x00c6,0x014d,0x00f6,0x0122,0x00a2,0x015a, - 0x015b,0x00d6,0x00dc,0x00f8,0x00a3,0x00d8,0x00d7,0x00a4, - 0x0100,0x012a,0x00f3,0x017b,0x017c,0x017a,0x201d,0x00a6, - 0x00a9,0x00ae,0x00ac,0x00bd,0x00bc,0x0141,0x00ab,0x00bb, - 0x2591,0x2592,0x2593,0x2502,0x2524,0x0104,0x010c,0x0118, - 0x0116,0x2563,0x2551,0x2557,0x255d,0x012e,0x0160,0x2510, - 0x2514,0x2534,0x252c,0x251c,0x2500,0x253c,0x0172,0x016a, - 0x255a,0x2554,0x2569,0x2566,0x2560,0x2550,0x256c,0x017d, - 0x0105,0x010d,0x0119,0x0117,0x012f,0x0161,0x0173,0x016b, - 0x017e,0x2518,0x250c,0x2588,0x2584,0x258c,0x2590,0x2580, - 0x00d3,0x00df,0x014c,0x0143,0x00f5,0x00d5,0x00b5,0x0144, - 0x0136,0x0137,0x013b,0x013c,0x0146,0x0112,0x0145,0x2019, - 0x00ad,0x00b1,0x201c,0x00be,0x00b6,0x00a7,0x00f7,0x201e, - 0x00b0,0x2219,0x00b7,0x00b9,0x00b3,0x00b2,0x25a0,0x00a0 + 0x0000, 0x0001, 0x0002, 0x0003, 0x0004, 0x0005, 0x0006, 0x0007, + 0x0008, 0x0009, 0x000a, 0x000b, 0x000c, 0x000d, 0x000e, 0x000f, + 0x0010, 0x0011, 0x0012, 0x0013, 0x0014, 0x0015, 0x0016, 0x0017, + 0x0018, 0x0019, 0x001a, 0x001b, 0x001c, 0x001d, 0x001e, 0x001f, + 0x0020, 0x0021, 0x0022, 0x0023, 0x0024, 0x0025, 0x0026, 0x0027, + 0x0028, 0x0029, 0x002a, 0x002b, 0x002c, 0x002d, 0x002e, 0x002f, + 0x0030, 0x0031, 0x0032, 0x0033, 0x0034, 0x0035, 0x0036, 0x0037, + 0x0038, 0x0039, 0x003a, 0x003b, 0x003c, 0x003d, 0x003e, 0x003f, + 0x0040, 0x0041, 0x0042, 0x0043, 0x0044, 0x0045, 0x0046, 0x0047, + 0x0048, 0x0049, 0x004a, 0x004b, 0x004c, 0x004d, 0x004e, 0x004f, + 0x0050, 0x0051, 0x0052, 0x0053, 0x0054, 0x0055, 0x0056, 0x0057, + 0x0058, 0x0059, 0x005a, 0x005b, 0x005c, 0x005d, 0x005e, 0x005f, + 0x0060, 0x0061, 0x0062, 0x0063, 0x0064, 0x0065, 0x0066, 0x0067, + 0x0068, 0x0069, 0x006a, 0x006b, 0x006c, 0x006d, 0x006e, 0x006f, + 0x0070, 0x0071, 0x0072, 0x0073, 0x0074, 0x0075, 0x0076, 0x0077, + 0x0078, 0x0079, 0x007a, 0x007b, 0x007c, 0x007d, 0x007e, 0x007f, + 0x0106, 0x00fc, 0x00e9, 0x0101, 0x00e4, 0x0123, 0x00e5, 0x0107, + 0x0142, 0x0113, 0x0156, 0x0157, 0x012b, 0x0179, 0x00c4, 0x00c5, + 0x00c9, 0x00e6, 0x00c6, 0x014d, 0x00f6, 0x0122, 0x00a2, 0x015a, + 0x015b, 0x00d6, 0x00dc, 0x00f8, 0x00a3, 0x00d8, 0x00d7, 0x00a4, + 0x0100, 0x012a, 0x00f3, 0x017b, 0x017c, 0x017a, 0x201d, 0x00a6, + 0x00a9, 0x00ae, 0x00ac, 0x00bd, 0x00bc, 0x0141, 0x00ab, 0x00bb, + 0x2591, 0x2592, 0x2593, 0x2502, 0x2524, 0x0104, 0x010c, 0x0118, + 0x0116, 0x2563, 0x2551, 0x2557, 0x255d, 0x012e, 0x0160, 0x2510, + 0x2514, 0x2534, 0x252c, 0x251c, 0x2500, 0x253c, 0x0172, 0x016a, + 0x255a, 0x2554, 0x2569, 0x2566, 0x2560, 0x2550, 0x256c, 0x017d, + 0x0105, 0x010d, 0x0119, 0x0117, 0x012f, 0x0161, 0x0173, 0x016b, + 0x017e, 0x2518, 0x250c, 0x2588, 0x2584, 0x258c, 0x2590, 0x2580, + 0x00d3, 0x00df, 0x014c, 0x0143, 0x00f5, 0x00d5, 0x00b5, 0x0144, + 0x0136, 0x0137, 0x013b, 0x013c, 0x0146, 0x0112, 0x0145, 0x2019, + 0x00ad, 0x00b1, 0x201c, 0x00be, 0x00b6, 0x00a7, 0x00f7, 0x201e, + 0x00b0, 0x2219, 0x00b7, 0x00b9, 0x00b3, 0x00b2, 0x25a0, 0x00a0 }; static const uint16_t cp850Map[256] = { - 0x0000,0x0001,0x0002,0x0003,0x0004,0x0005,0x0006,0x0007, - 0x0008,0x0009,0x000a,0x000b,0x000c,0x000d,0x000e,0x000f, - 0x0010,0x0011,0x0012,0x0013,0x0014,0x0015,0x0016,0x0017, - 0x0018,0x0019,0x001a,0x001b,0x001c,0x001d,0x001e,0x001f, - 0x0020,0x0021,0x0022,0x0023,0x0024,0x0025,0x0026,0x0027, - 0x0028,0x0029,0x002a,0x002b,0x002c,0x002d,0x002e,0x002f, - 0x0030,0x0031,0x0032,0x0033,0x0034,0x0035,0x0036,0x0037, - 0x0038,0x0039,0x003a,0x003b,0x003c,0x003d,0x003e,0x003f, - 0x0040,0x0041,0x0042,0x0043,0x0044,0x0045,0x0046,0x0047, - 0x0048,0x0049,0x004a,0x004b,0x004c,0x004d,0x004e,0x004f, - 0x0050,0x0051,0x0052,0x0053,0x0054,0x0055,0x0056,0x0057, - 0x0058,0x0059,0x005a,0x005b,0x005c,0x005d,0x005e,0x005f, - 0x0060,0x0061,0x0062,0x0063,0x0064,0x0065,0x0066,0x0067, - 0x0068,0x0069,0x006a,0x006b,0x006c,0x006d,0x006e,0x006f, - 0x0070,0x0071,0x0072,0x0073,0x0074,0x0075,0x0076,0x0077, - 0x0078,0x0079,0x007a,0x007b,0x007c,0x007d,0x007e,0x007f, - 0x00c7,0x00fc,0x00e9,0x00e2,0x00e4,0x00e0,0x00e5,0x00e7, - 0x00ea,0x00eb,0x00e8,0x00ef,0x00ee,0x00ec,0x00c4,0x00c5, - 0x00c9,0x00e6,0x00c6,0x00f4,0x00f6,0x00f2,0x00fb,0x00f9, - 0x00ff,0x00d6,0x00dc,0x00f8,0x00a3,0x00d8,0x00d7,0x0192, - 0x00e1,0x00ed,0x00f3,0x00fa,0x00f1,0x00d1,0x00aa,0x00ba, - 0x00bf,0x00ae,0x00ac,0x00bd,0x00bc,0x00a1,0x00ab,0x00bb, - 0x2591,0x2592,0x2593,0x2502,0x2524,0x00c1,0x00c2,0x00c0, - 0x00a9,0x2563,0x2551,0x2557,0x255d,0x00a2,0x00a5,0x2510, - 0x2514,0x2534,0x252c,0x251c,0x2500,0x253c,0x00e3,0x00c3, - 0x255a,0x2554,0x2569,0x2566,0x2560,0x2550,0x256c,0x00a4, - 0x00f0,0x00d0,0x00ca,0x00cb,0x00c8,0x0131,0x00cd,0x00ce, - 0x00cf,0x2518,0x250c,0x2588,0x2584,0x00a6,0x00cc,0x2580, - 0x00d3,0x00df,0x00d4,0x00d2,0x00f5,0x00d5,0x00b5,0x00fe, - 0x00de,0x00da,0x00db,0x00d9,0x00fd,0x00dd,0x00af,0x00b4, - 0x00ad,0x00b1,0x2017,0x00be,0x00b6,0x00a7,0x00f7,0x00b8, - 0x00b0,0x00a8,0x00b7,0x00b9,0x00b3,0x00b2,0x25a0,0x00a0 + 0x0000, 0x0001, 0x0002, 0x0003, 0x0004, 0x0005, 0x0006, 0x0007, + 0x0008, 0x0009, 0x000a, 0x000b, 0x000c, 0x000d, 0x000e, 0x000f, + 0x0010, 0x0011, 0x0012, 0x0013, 0x0014, 0x0015, 0x0016, 0x0017, + 0x0018, 0x0019, 0x001a, 0x001b, 0x001c, 0x001d, 0x001e, 0x001f, + 0x0020, 0x0021, 0x0022, 0x0023, 0x0024, 0x0025, 0x0026, 0x0027, + 0x0028, 0x0029, 0x002a, 0x002b, 0x002c, 0x002d, 0x002e, 0x002f, + 0x0030, 0x0031, 0x0032, 0x0033, 0x0034, 0x0035, 0x0036, 0x0037, + 0x0038, 0x0039, 0x003a, 0x003b, 0x003c, 0x003d, 0x003e, 0x003f, + 0x0040, 0x0041, 0x0042, 0x0043, 0x0044, 0x0045, 0x0046, 0x0047, + 0x0048, 0x0049, 0x004a, 0x004b, 0x004c, 0x004d, 0x004e, 0x004f, + 0x0050, 0x0051, 0x0052, 0x0053, 0x0054, 0x0055, 0x0056, 0x0057, + 0x0058, 0x0059, 0x005a, 0x005b, 0x005c, 0x005d, 0x005e, 0x005f, + 0x0060, 0x0061, 0x0062, 0x0063, 0x0064, 0x0065, 0x0066, 0x0067, + 0x0068, 0x0069, 0x006a, 0x006b, 0x006c, 0x006d, 0x006e, 0x006f, + 0x0070, 0x0071, 0x0072, 0x0073, 0x0074, 0x0075, 0x0076, 0x0077, + 0x0078, 0x0079, 0x007a, 0x007b, 0x007c, 0x007d, 0x007e, 0x007f, + 0x00c7, 0x00fc, 0x00e9, 0x00e2, 0x00e4, 0x00e0, 0x00e5, 0x00e7, + 0x00ea, 0x00eb, 0x00e8, 0x00ef, 0x00ee, 0x00ec, 0x00c4, 0x00c5, + 0x00c9, 0x00e6, 0x00c6, 0x00f4, 0x00f6, 0x00f2, 0x00fb, 0x00f9, + 0x00ff, 0x00d6, 0x00dc, 0x00f8, 0x00a3, 0x00d8, 0x00d7, 0x0192, + 0x00e1, 0x00ed, 0x00f3, 0x00fa, 0x00f1, 0x00d1, 0x00aa, 0x00ba, + 0x00bf, 0x00ae, 0x00ac, 0x00bd, 0x00bc, 0x00a1, 0x00ab, 0x00bb, + 0x2591, 0x2592, 0x2593, 0x2502, 0x2524, 0x00c1, 0x00c2, 0x00c0, + 0x00a9, 0x2563, 0x2551, 0x2557, 0x255d, 0x00a2, 0x00a5, 0x2510, + 0x2514, 0x2534, 0x252c, 0x251c, 0x2500, 0x253c, 0x00e3, 0x00c3, + 0x255a, 0x2554, 0x2569, 0x2566, 0x2560, 0x2550, 0x256c, 0x00a4, + 0x00f0, 0x00d0, 0x00ca, 0x00cb, 0x00c8, 0x0131, 0x00cd, 0x00ce, + 0x00cf, 0x2518, 0x250c, 0x2588, 0x2584, 0x00a6, 0x00cc, 0x2580, + 0x00d3, 0x00df, 0x00d4, 0x00d2, 0x00f5, 0x00d5, 0x00b5, 0x00fe, + 0x00de, 0x00da, 0x00db, 0x00d9, 0x00fd, 0x00dd, 0x00af, 0x00b4, + 0x00ad, 0x00b1, 0x2017, 0x00be, 0x00b6, 0x00a7, 0x00f7, 0x00b8, + 0x00b0, 0x00a8, 0x00b7, 0x00b9, 0x00b3, 0x00b2, 0x25a0, 0x00a0 }; static const uint16_t cp852Map[256] = { - 0x0000,0x0001,0x0002,0x0003,0x0004,0x0005,0x0006,0x0007, - 0x0008,0x0009,0x000a,0x000b,0x000c,0x000d,0x000e,0x000f, - 0x0010,0x0011,0x0012,0x0013,0x0014,0x0015,0x0016,0x0017, - 0x0018,0x0019,0x001a,0x001b,0x001c,0x001d,0x001e,0x001f, - 0x0020,0x0021,0x0022,0x0023,0x0024,0x0025,0x0026,0x0027, - 0x0028,0x0029,0x002a,0x002b,0x002c,0x002d,0x002e,0x002f, - 0x0030,0x0031,0x0032,0x0033,0x0034,0x0035,0x0036,0x0037, - 0x0038,0x0039,0x003a,0x003b,0x003c,0x003d,0x003e,0x003f, - 0x0040,0x0041,0x0042,0x0043,0x0044,0x0045,0x0046,0x0047, - 0x0048,0x0049,0x004a,0x004b,0x004c,0x004d,0x004e,0x004f, - 0x0050,0x0051,0x0052,0x0053,0x0054,0x0055,0x0056,0x0057, - 0x0058,0x0059,0x005a,0x005b,0x005c,0x005d,0x005e,0x005f, - 0x0060,0x0061,0x0062,0x0063,0x0064,0x0065,0x0066,0x0067, - 0x0068,0x0069,0x006a,0x006b,0x006c,0x006d,0x006e,0x006f, - 0x0070,0x0071,0x0072,0x0073,0x0074,0x0075,0x0076,0x0077, - 0x0078,0x0079,0x007a,0x007b,0x007c,0x007d,0x007e,0x007f, - 0x00c7,0x00fc,0x00e9,0x00e2,0x00e4,0x016f,0x0107,0x00e7, - 0x0142,0x00eb,0x0150,0x0151,0x00ee,0x0179,0x00c4,0x0106, - 0x00c9,0x0139,0x013a,0x00f4,0x00f6,0x013d,0x013e,0x015a, - 0x015b,0x00d6,0x00dc,0x0164,0x0165,0x0141,0x00d7,0x010d, - 0x00e1,0x00ed,0x00f3,0x00fa,0x0104,0x0105,0x017d,0x017e, - 0x0118,0x0119,0x00ac,0x017a,0x010c,0x015f,0x00ab,0x00bb, - 0x2591,0x2592,0x2593,0x2502,0x2524,0x00c1,0x00c2,0x011a, - 0x015e,0x2563,0x2551,0x2557,0x255d,0x017b,0x017c,0x2510, - 0x2514,0x2534,0x252c,0x251c,0x2500,0x253c,0x0102,0x0103, - 0x255a,0x2554,0x2569,0x2566,0x2560,0x2550,0x256c,0x00a4, - 0x0111,0x0110,0x010e,0x00cb,0x010f,0x0147,0x00cd,0x00ce, - 0x011b,0x2518,0x250c,0x2588,0x2584,0x0162,0x016e,0x2580, - 0x00d3,0x00df,0x00d4,0x0143,0x0144,0x0148,0x0160,0x0161, - 0x0154,0x00da,0x0155,0x0170,0x00fd,0x00dd,0x0163,0x00b4, - 0x00ad,0x02dd,0x02db,0x02c7,0x02d8,0x00a7,0x00f7,0x00b8, - 0x00b0,0x00a8,0x02d9,0x0171,0x0158,0x0159,0x25a0,0x00a0 + 0x0000, 0x0001, 0x0002, 0x0003, 0x0004, 0x0005, 0x0006, 0x0007, + 0x0008, 0x0009, 0x000a, 0x000b, 0x000c, 0x000d, 0x000e, 0x000f, + 0x0010, 0x0011, 0x0012, 0x0013, 0x0014, 0x0015, 0x0016, 0x0017, + 0x0018, 0x0019, 0x001a, 0x001b, 0x001c, 0x001d, 0x001e, 0x001f, + 0x0020, 0x0021, 0x0022, 0x0023, 0x0024, 0x0025, 0x0026, 0x0027, + 0x0028, 0x0029, 0x002a, 0x002b, 0x002c, 0x002d, 0x002e, 0x002f, + 0x0030, 0x0031, 0x0032, 0x0033, 0x0034, 0x0035, 0x0036, 0x0037, + 0x0038, 0x0039, 0x003a, 0x003b, 0x003c, 0x003d, 0x003e, 0x003f, + 0x0040, 0x0041, 0x0042, 0x0043, 0x0044, 0x0045, 0x0046, 0x0047, + 0x0048, 0x0049, 0x004a, 0x004b, 0x004c, 0x004d, 0x004e, 0x004f, + 0x0050, 0x0051, 0x0052, 0x0053, 0x0054, 0x0055, 0x0056, 0x0057, + 0x0058, 0x0059, 0x005a, 0x005b, 0x005c, 0x005d, 0x005e, 0x005f, + 0x0060, 0x0061, 0x0062, 0x0063, 0x0064, 0x0065, 0x0066, 0x0067, + 0x0068, 0x0069, 0x006a, 0x006b, 0x006c, 0x006d, 0x006e, 0x006f, + 0x0070, 0x0071, 0x0072, 0x0073, 0x0074, 0x0075, 0x0076, 0x0077, + 0x0078, 0x0079, 0x007a, 0x007b, 0x007c, 0x007d, 0x007e, 0x007f, + 0x00c7, 0x00fc, 0x00e9, 0x00e2, 0x00e4, 0x016f, 0x0107, 0x00e7, + 0x0142, 0x00eb, 0x0150, 0x0151, 0x00ee, 0x0179, 0x00c4, 0x0106, + 0x00c9, 0x0139, 0x013a, 0x00f4, 0x00f6, 0x013d, 0x013e, 0x015a, + 0x015b, 0x00d6, 0x00dc, 0x0164, 0x0165, 0x0141, 0x00d7, 0x010d, + 0x00e1, 0x00ed, 0x00f3, 0x00fa, 0x0104, 0x0105, 0x017d, 0x017e, + 0x0118, 0x0119, 0x00ac, 0x017a, 0x010c, 0x015f, 0x00ab, 0x00bb, + 0x2591, 0x2592, 0x2593, 0x2502, 0x2524, 0x00c1, 0x00c2, 0x011a, + 0x015e, 0x2563, 0x2551, 0x2557, 0x255d, 0x017b, 0x017c, 0x2510, + 0x2514, 0x2534, 0x252c, 0x251c, 0x2500, 0x253c, 0x0102, 0x0103, + 0x255a, 0x2554, 0x2569, 0x2566, 0x2560, 0x2550, 0x256c, 0x00a4, + 0x0111, 0x0110, 0x010e, 0x00cb, 0x010f, 0x0147, 0x00cd, 0x00ce, + 0x011b, 0x2518, 0x250c, 0x2588, 0x2584, 0x0162, 0x016e, 0x2580, + 0x00d3, 0x00df, 0x00d4, 0x0143, 0x0144, 0x0148, 0x0160, 0x0161, + 0x0154, 0x00da, 0x0155, 0x0170, 0x00fd, 0x00dd, 0x0163, 0x00b4, + 0x00ad, 0x02dd, 0x02db, 0x02c7, 0x02d8, 0x00a7, 0x00f7, 0x00b8, + 0x00b0, 0x00a8, 0x02d9, 0x0171, 0x0158, 0x0159, 0x25a0, 0x00a0 }; static const uint16_t cp855Map[256] = { - 0x0000,0x0001,0x0002,0x0003,0x0004,0x0005,0x0006,0x0007, - 0x0008,0x0009,0x000a,0x000b,0x000c,0x000d,0x000e,0x000f, - 0x0010,0x0011,0x0012,0x0013,0x0014,0x0015,0x0016,0x0017, - 0x0018,0x0019,0x001a,0x001b,0x001c,0x001d,0x001e,0x001f, - 0x0020,0x0021,0x0022,0x0023,0x0024,0x0025,0x0026,0x0027, - 0x0028,0x0029,0x002a,0x002b,0x002c,0x002d,0x002e,0x002f, - 0x0030,0x0031,0x0032,0x0033,0x0034,0x0035,0x0036,0x0037, - 0x0038,0x0039,0x003a,0x003b,0x003c,0x003d,0x003e,0x003f, - 0x0040,0x0041,0x0042,0x0043,0x0044,0x0045,0x0046,0x0047, - 0x0048,0x0049,0x004a,0x004b,0x004c,0x004d,0x004e,0x004f, - 0x0050,0x0051,0x0052,0x0053,0x0054,0x0055,0x0056,0x0057, - 0x0058,0x0059,0x005a,0x005b,0x005c,0x005d,0x005e,0x005f, - 0x0060,0x0061,0x0062,0x0063,0x0064,0x0065,0x0066,0x0067, - 0x0068,0x0069,0x006a,0x006b,0x006c,0x006d,0x006e,0x006f, - 0x0070,0x0071,0x0072,0x0073,0x0074,0x0075,0x0076,0x0077, - 0x0078,0x0079,0x007a,0x007b,0x007c,0x007d,0x007e,0x007f, - 0x0452,0x0402,0x0453,0x0403,0x0451,0x0401,0x0454,0x0404, - 0x0455,0x0405,0x0456,0x0406,0x0457,0x0407,0x0458,0x0408, - 0x0459,0x0409,0x045a,0x040a,0x045b,0x040b,0x045c,0x040c, - 0x045e,0x040e,0x045f,0x040f,0x044e,0x042e,0x044a,0x042a, - 0x0430,0x0410,0x0431,0x0411,0x0446,0x0426,0x0434,0x0414, - 0x0435,0x0415,0x0444,0x0424,0x0433,0x0413,0x00ab,0x00bb, - 0x2591,0x2592,0x2593,0x2502,0x2524,0x0445,0x0425,0x0438, - 0x0418,0x2563,0x2551,0x2557,0x255d,0x0439,0x0419,0x2510, - 0x2514,0x2534,0x252c,0x251c,0x2500,0x253c,0x043a,0x041a, - 0x255a,0x2554,0x2569,0x2566,0x2560,0x2550,0x256c,0x00a4, - 0x043b,0x041b,0x043c,0x041c,0x043d,0x041d,0x043e,0x041e, - 0x043f,0x2518,0x250c,0x2588,0x2584,0x041f,0x044f,0x2580, - 0x042f,0x0440,0x0420,0x0441,0x0421,0x0442,0x0422,0x0443, - 0x0423,0x0436,0x0416,0x0432,0x0412,0x044c,0x042c,0x2116, - 0x00ad,0x044b,0x042b,0x0437,0x0417,0x0448,0x0428,0x044d, - 0x042d,0x0449,0x0429,0x0447,0x0427,0x00a7,0x25a0,0x00a0 + 0x0000, 0x0001, 0x0002, 0x0003, 0x0004, 0x0005, 0x0006, 0x0007, + 0x0008, 0x0009, 0x000a, 0x000b, 0x000c, 0x000d, 0x000e, 0x000f, + 0x0010, 0x0011, 0x0012, 0x0013, 0x0014, 0x0015, 0x0016, 0x0017, + 0x0018, 0x0019, 0x001a, 0x001b, 0x001c, 0x001d, 0x001e, 0x001f, + 0x0020, 0x0021, 0x0022, 0x0023, 0x0024, 0x0025, 0x0026, 0x0027, + 0x0028, 0x0029, 0x002a, 0x002b, 0x002c, 0x002d, 0x002e, 0x002f, + 0x0030, 0x0031, 0x0032, 0x0033, 0x0034, 0x0035, 0x0036, 0x0037, + 0x0038, 0x0039, 0x003a, 0x003b, 0x003c, 0x003d, 0x003e, 0x003f, + 0x0040, 0x0041, 0x0042, 0x0043, 0x0044, 0x0045, 0x0046, 0x0047, + 0x0048, 0x0049, 0x004a, 0x004b, 0x004c, 0x004d, 0x004e, 0x004f, + 0x0050, 0x0051, 0x0052, 0x0053, 0x0054, 0x0055, 0x0056, 0x0057, + 0x0058, 0x0059, 0x005a, 0x005b, 0x005c, 0x005d, 0x005e, 0x005f, + 0x0060, 0x0061, 0x0062, 0x0063, 0x0064, 0x0065, 0x0066, 0x0067, + 0x0068, 0x0069, 0x006a, 0x006b, 0x006c, 0x006d, 0x006e, 0x006f, + 0x0070, 0x0071, 0x0072, 0x0073, 0x0074, 0x0075, 0x0076, 0x0077, + 0x0078, 0x0079, 0x007a, 0x007b, 0x007c, 0x007d, 0x007e, 0x007f, + 0x0452, 0x0402, 0x0453, 0x0403, 0x0451, 0x0401, 0x0454, 0x0404, + 0x0455, 0x0405, 0x0456, 0x0406, 0x0457, 0x0407, 0x0458, 0x0408, + 0x0459, 0x0409, 0x045a, 0x040a, 0x045b, 0x040b, 0x045c, 0x040c, + 0x045e, 0x040e, 0x045f, 0x040f, 0x044e, 0x042e, 0x044a, 0x042a, + 0x0430, 0x0410, 0x0431, 0x0411, 0x0446, 0x0426, 0x0434, 0x0414, + 0x0435, 0x0415, 0x0444, 0x0424, 0x0433, 0x0413, 0x00ab, 0x00bb, + 0x2591, 0x2592, 0x2593, 0x2502, 0x2524, 0x0445, 0x0425, 0x0438, + 0x0418, 0x2563, 0x2551, 0x2557, 0x255d, 0x0439, 0x0419, 0x2510, + 0x2514, 0x2534, 0x252c, 0x251c, 0x2500, 0x253c, 0x043a, 0x041a, + 0x255a, 0x2554, 0x2569, 0x2566, 0x2560, 0x2550, 0x256c, 0x00a4, + 0x043b, 0x041b, 0x043c, 0x041c, 0x043d, 0x041d, 0x043e, 0x041e, + 0x043f, 0x2518, 0x250c, 0x2588, 0x2584, 0x041f, 0x044f, 0x2580, + 0x042f, 0x0440, 0x0420, 0x0441, 0x0421, 0x0442, 0x0422, 0x0443, + 0x0423, 0x0436, 0x0416, 0x0432, 0x0412, 0x044c, 0x042c, 0x2116, + 0x00ad, 0x044b, 0x042b, 0x0437, 0x0417, 0x0448, 0x0428, 0x044d, + 0x042d, 0x0449, 0x0429, 0x0447, 0x0427, 0x00a7, 0x25a0, 0x00a0 }; static const uint16_t cp857Map[256] = { - 0x0000,0x0001,0x0002,0x0003,0x0004,0x0005,0x0006,0x0007, - 0x0008,0x0009,0x000a,0x000b,0x000c,0x000d,0x000e,0x000f, - 0x0010,0x0011,0x0012,0x0013,0x0014,0x0015,0x0016,0x0017, - 0x0018,0x0019,0x001a,0x001b,0x001c,0x001d,0x001e,0x001f, - 0x0020,0x0021,0x0022,0x0023,0x0024,0x0025,0x0026,0x0027, - 0x0028,0x0029,0x002a,0x002b,0x002c,0x002d,0x002e,0x002f, - 0x0030,0x0031,0x0032,0x0033,0x0034,0x0035,0x0036,0x0037, - 0x0038,0x0039,0x003a,0x003b,0x003c,0x003d,0x003e,0x003f, - 0x0040,0x0041,0x0042,0x0043,0x0044,0x0045,0x0046,0x0047, - 0x0048,0x0049,0x004a,0x004b,0x004c,0x004d,0x004e,0x004f, - 0x0050,0x0051,0x0052,0x0053,0x0054,0x0055,0x0056,0x0057, - 0x0058,0x0059,0x005a,0x005b,0x005c,0x005d,0x005e,0x005f, - 0x0060,0x0061,0x0062,0x0063,0x0064,0x0065,0x0066,0x0067, - 0x0068,0x0069,0x006a,0x006b,0x006c,0x006d,0x006e,0x006f, - 0x0070,0x0071,0x0072,0x0073,0x0074,0x0075,0x0076,0x0077, - 0x0078,0x0079,0x007a,0x007b,0x007c,0x007d,0x007e,0x007f, - 0x00c7,0x00fc,0x00e9,0x00e2,0x00e4,0x00e0,0x00e5,0x00e7, - 0x00ea,0x00eb,0x00e8,0x00ef,0x00ee,0x0131,0x00c4,0x00c5, - 0x00c9,0x00e6,0x00c6,0x00f4,0x00f6,0x00f2,0x00fb,0x00f9, - 0x0130,0x00d6,0x00dc,0x00f8,0x00a3,0x00d8,0x015e,0x015f, - 0x00e1,0x00ed,0x00f3,0x00fa,0x00f1,0x00d1,0x011e,0x011f, - 0x00bf,0x00ae,0x00ac,0x00bd,0x00bc,0x00a1,0x00ab,0x00bb, - 0x2591,0x2592,0x2593,0x2502,0x2524,0x00c1,0x00c2,0x00c0, - 0x00a9,0x2563,0x2551,0x2557,0x255d,0x00a2,0x00a5,0x2510, - 0x2514,0x2534,0x252c,0x251c,0x2500,0x253c,0x00e3,0x00c3, - 0x255a,0x2554,0x2569,0x2566,0x2560,0x2550,0x256c,0x00a4, - 0x00ba,0x00aa,0x00ca,0x00cb,0x00c8,0x0000,0x00cd,0x00ce, - 0x00cf,0x2518,0x250c,0x2588,0x2584,0x00a6,0x00cc,0x2580, - 0x00d3,0x00df,0x00d4,0x00d2,0x00f5,0x00d5,0x00b5,0x0000, - 0x00d7,0x00da,0x00db,0x00d9,0x00ec,0x00ff,0x00af,0x00b4, - 0x00ad,0x00b1,0x0000,0x00be,0x00b6,0x00a7,0x00f7,0x00b8, - 0x00b0,0x00a8,0x00b7,0x00b9,0x00b3,0x00b2,0x25a0,0x00a0 + 0x0000, 0x0001, 0x0002, 0x0003, 0x0004, 0x0005, 0x0006, 0x0007, + 0x0008, 0x0009, 0x000a, 0x000b, 0x000c, 0x000d, 0x000e, 0x000f, + 0x0010, 0x0011, 0x0012, 0x0013, 0x0014, 0x0015, 0x0016, 0x0017, + 0x0018, 0x0019, 0x001a, 0x001b, 0x001c, 0x001d, 0x001e, 0x001f, + 0x0020, 0x0021, 0x0022, 0x0023, 0x0024, 0x0025, 0x0026, 0x0027, + 0x0028, 0x0029, 0x002a, 0x002b, 0x002c, 0x002d, 0x002e, 0x002f, + 0x0030, 0x0031, 0x0032, 0x0033, 0x0034, 0x0035, 0x0036, 0x0037, + 0x0038, 0x0039, 0x003a, 0x003b, 0x003c, 0x003d, 0x003e, 0x003f, + 0x0040, 0x0041, 0x0042, 0x0043, 0x0044, 0x0045, 0x0046, 0x0047, + 0x0048, 0x0049, 0x004a, 0x004b, 0x004c, 0x004d, 0x004e, 0x004f, + 0x0050, 0x0051, 0x0052, 0x0053, 0x0054, 0x0055, 0x0056, 0x0057, + 0x0058, 0x0059, 0x005a, 0x005b, 0x005c, 0x005d, 0x005e, 0x005f, + 0x0060, 0x0061, 0x0062, 0x0063, 0x0064, 0x0065, 0x0066, 0x0067, + 0x0068, 0x0069, 0x006a, 0x006b, 0x006c, 0x006d, 0x006e, 0x006f, + 0x0070, 0x0071, 0x0072, 0x0073, 0x0074, 0x0075, 0x0076, 0x0077, + 0x0078, 0x0079, 0x007a, 0x007b, 0x007c, 0x007d, 0x007e, 0x007f, + 0x00c7, 0x00fc, 0x00e9, 0x00e2, 0x00e4, 0x00e0, 0x00e5, 0x00e7, + 0x00ea, 0x00eb, 0x00e8, 0x00ef, 0x00ee, 0x0131, 0x00c4, 0x00c5, + 0x00c9, 0x00e6, 0x00c6, 0x00f4, 0x00f6, 0x00f2, 0x00fb, 0x00f9, + 0x0130, 0x00d6, 0x00dc, 0x00f8, 0x00a3, 0x00d8, 0x015e, 0x015f, + 0x00e1, 0x00ed, 0x00f3, 0x00fa, 0x00f1, 0x00d1, 0x011e, 0x011f, + 0x00bf, 0x00ae, 0x00ac, 0x00bd, 0x00bc, 0x00a1, 0x00ab, 0x00bb, + 0x2591, 0x2592, 0x2593, 0x2502, 0x2524, 0x00c1, 0x00c2, 0x00c0, + 0x00a9, 0x2563, 0x2551, 0x2557, 0x255d, 0x00a2, 0x00a5, 0x2510, + 0x2514, 0x2534, 0x252c, 0x251c, 0x2500, 0x253c, 0x00e3, 0x00c3, + 0x255a, 0x2554, 0x2569, 0x2566, 0x2560, 0x2550, 0x256c, 0x00a4, + 0x00ba, 0x00aa, 0x00ca, 0x00cb, 0x00c8, 0x0000, 0x00cd, 0x00ce, + 0x00cf, 0x2518, 0x250c, 0x2588, 0x2584, 0x00a6, 0x00cc, 0x2580, + 0x00d3, 0x00df, 0x00d4, 0x00d2, 0x00f5, 0x00d5, 0x00b5, 0x0000, + 0x00d7, 0x00da, 0x00db, 0x00d9, 0x00ec, 0x00ff, 0x00af, 0x00b4, + 0x00ad, 0x00b1, 0x0000, 0x00be, 0x00b6, 0x00a7, 0x00f7, 0x00b8, + 0x00b0, 0x00a8, 0x00b7, 0x00b9, 0x00b3, 0x00b2, 0x25a0, 0x00a0 }; static const uint16_t cp860Map[256] = { - 0x0000,0x0001,0x0002,0x0003,0x0004,0x0005,0x0006,0x0007, - 0x0008,0x0009,0x000a,0x000b,0x000c,0x000d,0x000e,0x000f, - 0x0010,0x0011,0x0012,0x0013,0x0014,0x0015,0x0016,0x0017, - 0x0018,0x0019,0x001a,0x001b,0x001c,0x001d,0x001e,0x001f, - 0x0020,0x0021,0x0022,0x0023,0x0024,0x0025,0x0026,0x0027, - 0x0028,0x0029,0x002a,0x002b,0x002c,0x002d,0x002e,0x002f, - 0x0030,0x0031,0x0032,0x0033,0x0034,0x0035,0x0036,0x0037, - 0x0038,0x0039,0x003a,0x003b,0x003c,0x003d,0x003e,0x003f, - 0x0040,0x0041,0x0042,0x0043,0x0044,0x0045,0x0046,0x0047, - 0x0048,0x0049,0x004a,0x004b,0x004c,0x004d,0x004e,0x004f, - 0x0050,0x0051,0x0052,0x0053,0x0054,0x0055,0x0056,0x0057, - 0x0058,0x0059,0x005a,0x005b,0x005c,0x005d,0x005e,0x005f, - 0x0060,0x0061,0x0062,0x0063,0x0064,0x0065,0x0066,0x0067, - 0x0068,0x0069,0x006a,0x006b,0x006c,0x006d,0x006e,0x006f, - 0x0070,0x0071,0x0072,0x0073,0x0074,0x0075,0x0076,0x0077, - 0x0078,0x0079,0x007a,0x007b,0x007c,0x007d,0x007e,0x007f, - 0x00c7,0x00fc,0x00e9,0x00e2,0x00e3,0x00e0,0x00c1,0x00e7, - 0x00ea,0x00ca,0x00e8,0x00cd,0x00d4,0x00ec,0x00c3,0x00c2, - 0x00c9,0x00c0,0x00c8,0x00f4,0x00f5,0x00f2,0x00da,0x00f9, - 0x00cc,0x00d5,0x00dc,0x00a2,0x00a3,0x00d9,0x20a7,0x00d3, - 0x00e1,0x00ed,0x00f3,0x00fa,0x00f1,0x00d1,0x00aa,0x00ba, - 0x00bf,0x00d2,0x00ac,0x00bd,0x00bc,0x00a1,0x00ab,0x00bb, - 0x2591,0x2592,0x2593,0x2502,0x2524,0x2561,0x2562,0x2556, - 0x2555,0x2563,0x2551,0x2557,0x255d,0x255c,0x255b,0x2510, - 0x2514,0x2534,0x252c,0x251c,0x2500,0x253c,0x255e,0x255f, - 0x255a,0x2554,0x2569,0x2566,0x2560,0x2550,0x256c,0x2567, - 0x2568,0x2564,0x2565,0x2559,0x2558,0x2552,0x2553,0x256b, - 0x256a,0x2518,0x250c,0x2588,0x2584,0x258c,0x2590,0x2580, - 0x03b1,0x00df,0x0393,0x03c0,0x03a3,0x03c3,0x00b5,0x03c4, - 0x03a6,0x0398,0x03a9,0x03b4,0x221e,0x03c6,0x03b5,0x2229, - 0x2261,0x00b1,0x2265,0x2264,0x2320,0x2321,0x00f7,0x2248, - 0x00b0,0x2219,0x00b7,0x221a,0x207f,0x00b2,0x25a0,0x00a0 + 0x0000, 0x0001, 0x0002, 0x0003, 0x0004, 0x0005, 0x0006, 0x0007, + 0x0008, 0x0009, 0x000a, 0x000b, 0x000c, 0x000d, 0x000e, 0x000f, + 0x0010, 0x0011, 0x0012, 0x0013, 0x0014, 0x0015, 0x0016, 0x0017, + 0x0018, 0x0019, 0x001a, 0x001b, 0x001c, 0x001d, 0x001e, 0x001f, + 0x0020, 0x0021, 0x0022, 0x0023, 0x0024, 0x0025, 0x0026, 0x0027, + 0x0028, 0x0029, 0x002a, 0x002b, 0x002c, 0x002d, 0x002e, 0x002f, + 0x0030, 0x0031, 0x0032, 0x0033, 0x0034, 0x0035, 0x0036, 0x0037, + 0x0038, 0x0039, 0x003a, 0x003b, 0x003c, 0x003d, 0x003e, 0x003f, + 0x0040, 0x0041, 0x0042, 0x0043, 0x0044, 0x0045, 0x0046, 0x0047, + 0x0048, 0x0049, 0x004a, 0x004b, 0x004c, 0x004d, 0x004e, 0x004f, + 0x0050, 0x0051, 0x0052, 0x0053, 0x0054, 0x0055, 0x0056, 0x0057, + 0x0058, 0x0059, 0x005a, 0x005b, 0x005c, 0x005d, 0x005e, 0x005f, + 0x0060, 0x0061, 0x0062, 0x0063, 0x0064, 0x0065, 0x0066, 0x0067, + 0x0068, 0x0069, 0x006a, 0x006b, 0x006c, 0x006d, 0x006e, 0x006f, + 0x0070, 0x0071, 0x0072, 0x0073, 0x0074, 0x0075, 0x0076, 0x0077, + 0x0078, 0x0079, 0x007a, 0x007b, 0x007c, 0x007d, 0x007e, 0x007f, + 0x00c7, 0x00fc, 0x00e9, 0x00e2, 0x00e3, 0x00e0, 0x00c1, 0x00e7, + 0x00ea, 0x00ca, 0x00e8, 0x00cd, 0x00d4, 0x00ec, 0x00c3, 0x00c2, + 0x00c9, 0x00c0, 0x00c8, 0x00f4, 0x00f5, 0x00f2, 0x00da, 0x00f9, + 0x00cc, 0x00d5, 0x00dc, 0x00a2, 0x00a3, 0x00d9, 0x20a7, 0x00d3, + 0x00e1, 0x00ed, 0x00f3, 0x00fa, 0x00f1, 0x00d1, 0x00aa, 0x00ba, + 0x00bf, 0x00d2, 0x00ac, 0x00bd, 0x00bc, 0x00a1, 0x00ab, 0x00bb, + 0x2591, 0x2592, 0x2593, 0x2502, 0x2524, 0x2561, 0x2562, 0x2556, + 0x2555, 0x2563, 0x2551, 0x2557, 0x255d, 0x255c, 0x255b, 0x2510, + 0x2514, 0x2534, 0x252c, 0x251c, 0x2500, 0x253c, 0x255e, 0x255f, + 0x255a, 0x2554, 0x2569, 0x2566, 0x2560, 0x2550, 0x256c, 0x2567, + 0x2568, 0x2564, 0x2565, 0x2559, 0x2558, 0x2552, 0x2553, 0x256b, + 0x256a, 0x2518, 0x250c, 0x2588, 0x2584, 0x258c, 0x2590, 0x2580, + 0x03b1, 0x00df, 0x0393, 0x03c0, 0x03a3, 0x03c3, 0x00b5, 0x03c4, + 0x03a6, 0x0398, 0x03a9, 0x03b4, 0x221e, 0x03c6, 0x03b5, 0x2229, + 0x2261, 0x00b1, 0x2265, 0x2264, 0x2320, 0x2321, 0x00f7, 0x2248, + 0x00b0, 0x2219, 0x00b7, 0x221a, 0x207f, 0x00b2, 0x25a0, 0x00a0 }; static const uint16_t cp861Map[256] = { - 0x0000,0x0001,0x0002,0x0003,0x0004,0x0005,0x0006,0x0007, - 0x0008,0x0009,0x000a,0x000b,0x000c,0x000d,0x000e,0x000f, - 0x0010,0x0011,0x0012,0x0013,0x0014,0x0015,0x0016,0x0017, - 0x0018,0x0019,0x001a,0x001b,0x001c,0x001d,0x001e,0x001f, - 0x0020,0x0021,0x0022,0x0023,0x0024,0x0025,0x0026,0x0027, - 0x0028,0x0029,0x002a,0x002b,0x002c,0x002d,0x002e,0x002f, - 0x0030,0x0031,0x0032,0x0033,0x0034,0x0035,0x0036,0x0037, - 0x0038,0x0039,0x003a,0x003b,0x003c,0x003d,0x003e,0x003f, - 0x0040,0x0041,0x0042,0x0043,0x0044,0x0045,0x0046,0x0047, - 0x0048,0x0049,0x004a,0x004b,0x004c,0x004d,0x004e,0x004f, - 0x0050,0x0051,0x0052,0x0053,0x0054,0x0055,0x0056,0x0057, - 0x0058,0x0059,0x005a,0x005b,0x005c,0x005d,0x005e,0x005f, - 0x0060,0x0061,0x0062,0x0063,0x0064,0x0065,0x0066,0x0067, - 0x0068,0x0069,0x006a,0x006b,0x006c,0x006d,0x006e,0x006f, - 0x0070,0x0071,0x0072,0x0073,0x0074,0x0075,0x0076,0x0077, - 0x0078,0x0079,0x007a,0x007b,0x007c,0x007d,0x007e,0x007f, - 0x00c7,0x00fc,0x00e9,0x00e2,0x00e4,0x00e0,0x00e5,0x00e7, - 0x00ea,0x00eb,0x00e8,0x00d0,0x00f0,0x00de,0x00c4,0x00c5, - 0x00c9,0x00e6,0x00c6,0x00f4,0x00f6,0x00fe,0x00fb,0x00dd, - 0x00fd,0x00d6,0x00dc,0x00f8,0x00a3,0x00d8,0x20a7,0x0192, - 0x00e1,0x00ed,0x00f3,0x00fa,0x00c1,0x00cd,0x00d3,0x00da, - 0x00bf,0x2310,0x00ac,0x00bd,0x00bc,0x00a1,0x00ab,0x00bb, - 0x2591,0x2592,0x2593,0x2502,0x2524,0x2561,0x2562,0x2556, - 0x2555,0x2563,0x2551,0x2557,0x255d,0x255c,0x255b,0x2510, - 0x2514,0x2534,0x252c,0x251c,0x2500,0x253c,0x255e,0x255f, - 0x255a,0x2554,0x2569,0x2566,0x2560,0x2550,0x256c,0x2567, - 0x2568,0x2564,0x2565,0x2559,0x2558,0x2552,0x2553,0x256b, - 0x256a,0x2518,0x250c,0x2588,0x2584,0x258c,0x2590,0x2580, - 0x03b1,0x00df,0x0393,0x03c0,0x03a3,0x03c3,0x00b5,0x03c4, - 0x03a6,0x0398,0x03a9,0x03b4,0x221e,0x03c6,0x03b5,0x2229, - 0x2261,0x00b1,0x2265,0x2264,0x2320,0x2321,0x00f7,0x2248, - 0x00b0,0x2219,0x00b7,0x221a,0x207f,0x00b2,0x25a0,0x00a0 + 0x0000, 0x0001, 0x0002, 0x0003, 0x0004, 0x0005, 0x0006, 0x0007, + 0x0008, 0x0009, 0x000a, 0x000b, 0x000c, 0x000d, 0x000e, 0x000f, + 0x0010, 0x0011, 0x0012, 0x0013, 0x0014, 0x0015, 0x0016, 0x0017, + 0x0018, 0x0019, 0x001a, 0x001b, 0x001c, 0x001d, 0x001e, 0x001f, + 0x0020, 0x0021, 0x0022, 0x0023, 0x0024, 0x0025, 0x0026, 0x0027, + 0x0028, 0x0029, 0x002a, 0x002b, 0x002c, 0x002d, 0x002e, 0x002f, + 0x0030, 0x0031, 0x0032, 0x0033, 0x0034, 0x0035, 0x0036, 0x0037, + 0x0038, 0x0039, 0x003a, 0x003b, 0x003c, 0x003d, 0x003e, 0x003f, + 0x0040, 0x0041, 0x0042, 0x0043, 0x0044, 0x0045, 0x0046, 0x0047, + 0x0048, 0x0049, 0x004a, 0x004b, 0x004c, 0x004d, 0x004e, 0x004f, + 0x0050, 0x0051, 0x0052, 0x0053, 0x0054, 0x0055, 0x0056, 0x0057, + 0x0058, 0x0059, 0x005a, 0x005b, 0x005c, 0x005d, 0x005e, 0x005f, + 0x0060, 0x0061, 0x0062, 0x0063, 0x0064, 0x0065, 0x0066, 0x0067, + 0x0068, 0x0069, 0x006a, 0x006b, 0x006c, 0x006d, 0x006e, 0x006f, + 0x0070, 0x0071, 0x0072, 0x0073, 0x0074, 0x0075, 0x0076, 0x0077, + 0x0078, 0x0079, 0x007a, 0x007b, 0x007c, 0x007d, 0x007e, 0x007f, + 0x00c7, 0x00fc, 0x00e9, 0x00e2, 0x00e4, 0x00e0, 0x00e5, 0x00e7, + 0x00ea, 0x00eb, 0x00e8, 0x00d0, 0x00f0, 0x00de, 0x00c4, 0x00c5, + 0x00c9, 0x00e6, 0x00c6, 0x00f4, 0x00f6, 0x00fe, 0x00fb, 0x00dd, + 0x00fd, 0x00d6, 0x00dc, 0x00f8, 0x00a3, 0x00d8, 0x20a7, 0x0192, + 0x00e1, 0x00ed, 0x00f3, 0x00fa, 0x00c1, 0x00cd, 0x00d3, 0x00da, + 0x00bf, 0x2310, 0x00ac, 0x00bd, 0x00bc, 0x00a1, 0x00ab, 0x00bb, + 0x2591, 0x2592, 0x2593, 0x2502, 0x2524, 0x2561, 0x2562, 0x2556, + 0x2555, 0x2563, 0x2551, 0x2557, 0x255d, 0x255c, 0x255b, 0x2510, + 0x2514, 0x2534, 0x252c, 0x251c, 0x2500, 0x253c, 0x255e, 0x255f, + 0x255a, 0x2554, 0x2569, 0x2566, 0x2560, 0x2550, 0x256c, 0x2567, + 0x2568, 0x2564, 0x2565, 0x2559, 0x2558, 0x2552, 0x2553, 0x256b, + 0x256a, 0x2518, 0x250c, 0x2588, 0x2584, 0x258c, 0x2590, 0x2580, + 0x03b1, 0x00df, 0x0393, 0x03c0, 0x03a3, 0x03c3, 0x00b5, 0x03c4, + 0x03a6, 0x0398, 0x03a9, 0x03b4, 0x221e, 0x03c6, 0x03b5, 0x2229, + 0x2261, 0x00b1, 0x2265, 0x2264, 0x2320, 0x2321, 0x00f7, 0x2248, + 0x00b0, 0x2219, 0x00b7, 0x221a, 0x207f, 0x00b2, 0x25a0, 0x00a0 }; static const uint16_t cp862Map[256] = { - 0x0000,0x0001,0x0002,0x0003,0x0004,0x0005,0x0006,0x0007, - 0x0008,0x0009,0x000a,0x000b,0x000c,0x000d,0x000e,0x000f, - 0x0010,0x0011,0x0012,0x0013,0x0014,0x0015,0x0016,0x0017, - 0x0018,0x0019,0x001a,0x001b,0x001c,0x001d,0x001e,0x001f, - 0x0020,0x0021,0x0022,0x0023,0x0024,0x0025,0x0026,0x0027, - 0x0028,0x0029,0x002a,0x002b,0x002c,0x002d,0x002e,0x002f, - 0x0030,0x0031,0x0032,0x0033,0x0034,0x0035,0x0036,0x0037, - 0x0038,0x0039,0x003a,0x003b,0x003c,0x003d,0x003e,0x003f, - 0x0040,0x0041,0x0042,0x0043,0x0044,0x0045,0x0046,0x0047, - 0x0048,0x0049,0x004a,0x004b,0x004c,0x004d,0x004e,0x004f, - 0x0050,0x0051,0x0052,0x0053,0x0054,0x0055,0x0056,0x0057, - 0x0058,0x0059,0x005a,0x005b,0x005c,0x005d,0x005e,0x005f, - 0x0060,0x0061,0x0062,0x0063,0x0064,0x0065,0x0066,0x0067, - 0x0068,0x0069,0x006a,0x006b,0x006c,0x006d,0x006e,0x006f, - 0x0070,0x0071,0x0072,0x0073,0x0074,0x0075,0x0076,0x0077, - 0x0078,0x0079,0x007a,0x007b,0x007c,0x007d,0x007e,0x007f, - 0x05d0,0x05d1,0x05d2,0x05d3,0x05d4,0x05d5,0x05d6,0x05d7, - 0x05d8,0x05d9,0x05da,0x05db,0x05dc,0x05dd,0x05de,0x05df, - 0x05e0,0x05e1,0x05e2,0x05e3,0x05e4,0x05e5,0x05e6,0x05e7, - 0x05e8,0x05e9,0x05ea,0x00a2,0x00a3,0x00a5,0x20a7,0x0192, - 0x00e1,0x00ed,0x00f3,0x00fa,0x00f1,0x00d1,0x00aa,0x00ba, - 0x00bf,0x2310,0x00ac,0x00bd,0x00bc,0x00a1,0x00ab,0x00bb, - 0x2591,0x2592,0x2593,0x2502,0x2524,0x2561,0x2562,0x2556, - 0x2555,0x2563,0x2551,0x2557,0x255d,0x255c,0x255b,0x2510, - 0x2514,0x2534,0x252c,0x251c,0x2500,0x253c,0x255e,0x255f, - 0x255a,0x2554,0x2569,0x2566,0x2560,0x2550,0x256c,0x2567, - 0x2568,0x2564,0x2565,0x2559,0x2558,0x2552,0x2553,0x256b, - 0x256a,0x2518,0x250c,0x2588,0x2584,0x258c,0x2590,0x2580, - 0x03b1,0x00df,0x0393,0x03c0,0x03a3,0x03c3,0x00b5,0x03c4, - 0x03a6,0x0398,0x03a9,0x03b4,0x221e,0x03c6,0x03b5,0x2229, - 0x2261,0x00b1,0x2265,0x2264,0x2320,0x2321,0x00f7,0x2248, - 0x00b0,0x2219,0x00b7,0x221a,0x207f,0x00b2,0x25a0,0x00a0 + 0x0000, 0x0001, 0x0002, 0x0003, 0x0004, 0x0005, 0x0006, 0x0007, + 0x0008, 0x0009, 0x000a, 0x000b, 0x000c, 0x000d, 0x000e, 0x000f, + 0x0010, 0x0011, 0x0012, 0x0013, 0x0014, 0x0015, 0x0016, 0x0017, + 0x0018, 0x0019, 0x001a, 0x001b, 0x001c, 0x001d, 0x001e, 0x001f, + 0x0020, 0x0021, 0x0022, 0x0023, 0x0024, 0x0025, 0x0026, 0x0027, + 0x0028, 0x0029, 0x002a, 0x002b, 0x002c, 0x002d, 0x002e, 0x002f, + 0x0030, 0x0031, 0x0032, 0x0033, 0x0034, 0x0035, 0x0036, 0x0037, + 0x0038, 0x0039, 0x003a, 0x003b, 0x003c, 0x003d, 0x003e, 0x003f, + 0x0040, 0x0041, 0x0042, 0x0043, 0x0044, 0x0045, 0x0046, 0x0047, + 0x0048, 0x0049, 0x004a, 0x004b, 0x004c, 0x004d, 0x004e, 0x004f, + 0x0050, 0x0051, 0x0052, 0x0053, 0x0054, 0x0055, 0x0056, 0x0057, + 0x0058, 0x0059, 0x005a, 0x005b, 0x005c, 0x005d, 0x005e, 0x005f, + 0x0060, 0x0061, 0x0062, 0x0063, 0x0064, 0x0065, 0x0066, 0x0067, + 0x0068, 0x0069, 0x006a, 0x006b, 0x006c, 0x006d, 0x006e, 0x006f, + 0x0070, 0x0071, 0x0072, 0x0073, 0x0074, 0x0075, 0x0076, 0x0077, + 0x0078, 0x0079, 0x007a, 0x007b, 0x007c, 0x007d, 0x007e, 0x007f, + 0x05d0, 0x05d1, 0x05d2, 0x05d3, 0x05d4, 0x05d5, 0x05d6, 0x05d7, + 0x05d8, 0x05d9, 0x05da, 0x05db, 0x05dc, 0x05dd, 0x05de, 0x05df, + 0x05e0, 0x05e1, 0x05e2, 0x05e3, 0x05e4, 0x05e5, 0x05e6, 0x05e7, + 0x05e8, 0x05e9, 0x05ea, 0x00a2, 0x00a3, 0x00a5, 0x20a7, 0x0192, + 0x00e1, 0x00ed, 0x00f3, 0x00fa, 0x00f1, 0x00d1, 0x00aa, 0x00ba, + 0x00bf, 0x2310, 0x00ac, 0x00bd, 0x00bc, 0x00a1, 0x00ab, 0x00bb, + 0x2591, 0x2592, 0x2593, 0x2502, 0x2524, 0x2561, 0x2562, 0x2556, + 0x2555, 0x2563, 0x2551, 0x2557, 0x255d, 0x255c, 0x255b, 0x2510, + 0x2514, 0x2534, 0x252c, 0x251c, 0x2500, 0x253c, 0x255e, 0x255f, + 0x255a, 0x2554, 0x2569, 0x2566, 0x2560, 0x2550, 0x256c, 0x2567, + 0x2568, 0x2564, 0x2565, 0x2559, 0x2558, 0x2552, 0x2553, 0x256b, + 0x256a, 0x2518, 0x250c, 0x2588, 0x2584, 0x258c, 0x2590, 0x2580, + 0x03b1, 0x00df, 0x0393, 0x03c0, 0x03a3, 0x03c3, 0x00b5, 0x03c4, + 0x03a6, 0x0398, 0x03a9, 0x03b4, 0x221e, 0x03c6, 0x03b5, 0x2229, + 0x2261, 0x00b1, 0x2265, 0x2264, 0x2320, 0x2321, 0x00f7, 0x2248, + 0x00b0, 0x2219, 0x00b7, 0x221a, 0x207f, 0x00b2, 0x25a0, 0x00a0 }; static const uint16_t cp863Map[256] = { - 0x0000,0x0001,0x0002,0x0003,0x0004,0x0005,0x0006,0x0007, - 0x0008,0x0009,0x000a,0x000b,0x000c,0x000d,0x000e,0x000f, - 0x0010,0x0011,0x0012,0x0013,0x0014,0x0015,0x0016,0x0017, - 0x0018,0x0019,0x001a,0x001b,0x001c,0x001d,0x001e,0x001f, - 0x0020,0x0021,0x0022,0x0023,0x0024,0x0025,0x0026,0x0027, - 0x0028,0x0029,0x002a,0x002b,0x002c,0x002d,0x002e,0x002f, - 0x0030,0x0031,0x0032,0x0033,0x0034,0x0035,0x0036,0x0037, - 0x0038,0x0039,0x003a,0x003b,0x003c,0x003d,0x003e,0x003f, - 0x0040,0x0041,0x0042,0x0043,0x0044,0x0045,0x0046,0x0047, - 0x0048,0x0049,0x004a,0x004b,0x004c,0x004d,0x004e,0x004f, - 0x0050,0x0051,0x0052,0x0053,0x0054,0x0055,0x0056,0x0057, - 0x0058,0x0059,0x005a,0x005b,0x005c,0x005d,0x005e,0x005f, - 0x0060,0x0061,0x0062,0x0063,0x0064,0x0065,0x0066,0x0067, - 0x0068,0x0069,0x006a,0x006b,0x006c,0x006d,0x006e,0x006f, - 0x0070,0x0071,0x0072,0x0073,0x0074,0x0075,0x0076,0x0077, - 0x0078,0x0079,0x007a,0x007b,0x007c,0x007d,0x007e,0x007f, - 0x00c7,0x00fc,0x00e9,0x00e2,0x00c2,0x00e0,0x00b6,0x00e7, - 0x00ea,0x00eb,0x00e8,0x00ef,0x00ee,0x2017,0x00c0,0x00a7, - 0x00c9,0x00c8,0x00ca,0x00f4,0x00cb,0x00cf,0x00fb,0x00f9, - 0x00a4,0x00d4,0x00dc,0x00a2,0x00a3,0x00d9,0x00db,0x0192, - 0x00a6,0x00b4,0x00f3,0x00fa,0x00a8,0x00b8,0x00b3,0x00af, - 0x00ce,0x2310,0x00ac,0x00bd,0x00bc,0x00be,0x00ab,0x00bb, - 0x2591,0x2592,0x2593,0x2502,0x2524,0x2561,0x2562,0x2556, - 0x2555,0x2563,0x2551,0x2557,0x255d,0x255c,0x255b,0x2510, - 0x2514,0x2534,0x252c,0x251c,0x2500,0x253c,0x255e,0x255f, - 0x255a,0x2554,0x2569,0x2566,0x2560,0x2550,0x256c,0x2567, - 0x2568,0x2564,0x2565,0x2559,0x2558,0x2552,0x2553,0x256b, - 0x256a,0x2518,0x250c,0x2588,0x2584,0x258c,0x2590,0x2580, - 0x03b1,0x00df,0x0393,0x03c0,0x03a3,0x03c3,0x00b5,0x03c4, - 0x03a6,0x0398,0x03a9,0x03b4,0x221e,0x03c6,0x03b5,0x2229, - 0x2261,0x00b1,0x2265,0x2264,0x2320,0x2321,0x00f7,0x2248, - 0x00b0,0x2219,0x00b7,0x221a,0x207f,0x00b2,0x25a0,0x00a0 + 0x0000, 0x0001, 0x0002, 0x0003, 0x0004, 0x0005, 0x0006, 0x0007, + 0x0008, 0x0009, 0x000a, 0x000b, 0x000c, 0x000d, 0x000e, 0x000f, + 0x0010, 0x0011, 0x0012, 0x0013, 0x0014, 0x0015, 0x0016, 0x0017, + 0x0018, 0x0019, 0x001a, 0x001b, 0x001c, 0x001d, 0x001e, 0x001f, + 0x0020, 0x0021, 0x0022, 0x0023, 0x0024, 0x0025, 0x0026, 0x0027, + 0x0028, 0x0029, 0x002a, 0x002b, 0x002c, 0x002d, 0x002e, 0x002f, + 0x0030, 0x0031, 0x0032, 0x0033, 0x0034, 0x0035, 0x0036, 0x0037, + 0x0038, 0x0039, 0x003a, 0x003b, 0x003c, 0x003d, 0x003e, 0x003f, + 0x0040, 0x0041, 0x0042, 0x0043, 0x0044, 0x0045, 0x0046, 0x0047, + 0x0048, 0x0049, 0x004a, 0x004b, 0x004c, 0x004d, 0x004e, 0x004f, + 0x0050, 0x0051, 0x0052, 0x0053, 0x0054, 0x0055, 0x0056, 0x0057, + 0x0058, 0x0059, 0x005a, 0x005b, 0x005c, 0x005d, 0x005e, 0x005f, + 0x0060, 0x0061, 0x0062, 0x0063, 0x0064, 0x0065, 0x0066, 0x0067, + 0x0068, 0x0069, 0x006a, 0x006b, 0x006c, 0x006d, 0x006e, 0x006f, + 0x0070, 0x0071, 0x0072, 0x0073, 0x0074, 0x0075, 0x0076, 0x0077, + 0x0078, 0x0079, 0x007a, 0x007b, 0x007c, 0x007d, 0x007e, 0x007f, + 0x00c7, 0x00fc, 0x00e9, 0x00e2, 0x00c2, 0x00e0, 0x00b6, 0x00e7, + 0x00ea, 0x00eb, 0x00e8, 0x00ef, 0x00ee, 0x2017, 0x00c0, 0x00a7, + 0x00c9, 0x00c8, 0x00ca, 0x00f4, 0x00cb, 0x00cf, 0x00fb, 0x00f9, + 0x00a4, 0x00d4, 0x00dc, 0x00a2, 0x00a3, 0x00d9, 0x00db, 0x0192, + 0x00a6, 0x00b4, 0x00f3, 0x00fa, 0x00a8, 0x00b8, 0x00b3, 0x00af, + 0x00ce, 0x2310, 0x00ac, 0x00bd, 0x00bc, 0x00be, 0x00ab, 0x00bb, + 0x2591, 0x2592, 0x2593, 0x2502, 0x2524, 0x2561, 0x2562, 0x2556, + 0x2555, 0x2563, 0x2551, 0x2557, 0x255d, 0x255c, 0x255b, 0x2510, + 0x2514, 0x2534, 0x252c, 0x251c, 0x2500, 0x253c, 0x255e, 0x255f, + 0x255a, 0x2554, 0x2569, 0x2566, 0x2560, 0x2550, 0x256c, 0x2567, + 0x2568, 0x2564, 0x2565, 0x2559, 0x2558, 0x2552, 0x2553, 0x256b, + 0x256a, 0x2518, 0x250c, 0x2588, 0x2584, 0x258c, 0x2590, 0x2580, + 0x03b1, 0x00df, 0x0393, 0x03c0, 0x03a3, 0x03c3, 0x00b5, 0x03c4, + 0x03a6, 0x0398, 0x03a9, 0x03b4, 0x221e, 0x03c6, 0x03b5, 0x2229, + 0x2261, 0x00b1, 0x2265, 0x2264, 0x2320, 0x2321, 0x00f7, 0x2248, + 0x00b0, 0x2219, 0x00b7, 0x221a, 0x207f, 0x00b2, 0x25a0, 0x00a0 }; static const uint16_t cp864Map[256] = { - 0x0000,0x0001,0x0002,0x0003,0x0004,0x0005,0x0006,0x0007, - 0x0008,0x0009,0x000a,0x000b,0x000c,0x000d,0x000e,0x000f, - 0x0010,0x0011,0x0012,0x0013,0x0014,0x0015,0x0016,0x0017, - 0x0018,0x0019,0x001a,0x001b,0x001c,0x001d,0x001e,0x001f, - 0x0020,0x0021,0x0022,0x0023,0x0024,0x066a,0x0026,0x0027, - 0x0028,0x0029,0x002a,0x002b,0x002c,0x002d,0x002e,0x002f, - 0x0030,0x0031,0x0032,0x0033,0x0034,0x0035,0x0036,0x0037, - 0x0038,0x0039,0x003a,0x003b,0x003c,0x003d,0x003e,0x003f, - 0x0040,0x0041,0x0042,0x0043,0x0044,0x0045,0x0046,0x0047, - 0x0048,0x0049,0x004a,0x004b,0x004c,0x004d,0x004e,0x004f, - 0x0050,0x0051,0x0052,0x0053,0x0054,0x0055,0x0056,0x0057, - 0x0058,0x0059,0x005a,0x005b,0x005c,0x005d,0x005e,0x005f, - 0x0060,0x0061,0x0062,0x0063,0x0064,0x0065,0x0066,0x0067, - 0x0068,0x0069,0x006a,0x006b,0x006c,0x006d,0x006e,0x006f, - 0x0070,0x0071,0x0072,0x0073,0x0074,0x0075,0x0076,0x0077, - 0x0078,0x0079,0x007a,0x007b,0x007c,0x007d,0x007e,0x007f, - 0x00b0,0x00b7,0x2219,0x221a,0x2592,0x2500,0x2502,0x253c, - 0x2524,0x252c,0x251c,0x2534,0x2510,0x250c,0x2514,0x2518, - 0x03b2,0x221e,0x03c6,0x00b1,0x00bd,0x00bc,0x2248,0x00ab, - 0x00bb,0xfef7,0xfef8,0x0000,0x0000,0xfefb,0xfefc,0x0000, - 0x00a0,0x00ad,0xfe82,0x00a3,0x00a4,0xfe84,0x0000,0x0000, - 0xfe8e,0xfe8f,0xfe95,0xfe99,0x060c,0xfe9d,0xfea1,0xfea5, - 0x0660,0x0661,0x0662,0x0663,0x0664,0x0665,0x0666,0x0667, - 0x0668,0x0669,0xfed1,0x061b,0xfeb1,0xfeb5,0xfeb9,0x061f, - 0x00a2,0xfe80,0xfe81,0xfe83,0xfe85,0xfeca,0xfe8b,0xfe8d, - 0xfe91,0xfe93,0xfe97,0xfe9b,0xfe9f,0xfea3,0xfea7,0xfea9, - 0xfeab,0xfead,0xfeaf,0xfeb3,0xfeb7,0xfebb,0xfebf,0xfec1, - 0xfec5,0xfecb,0xfecf,0x00a6,0x00ac,0x00f7,0x00d7,0xfec9, - 0x0640,0xfed3,0xfed7,0xfedb,0xfedf,0xfee3,0xfee7,0xfeeb, - 0xfeed,0xfeef,0xfef3,0xfebd,0xfecc,0xfece,0xfecd,0xfee1, - 0xfe7d,0x0651,0xfee5,0xfee9,0xfeec,0xfef0,0xfef2,0xfed0, - 0xfed5,0xfef5,0xfef6,0xfedd,0xfed9,0xfef1,0x25a0,0x00a0 + 0x0000, 0x0001, 0x0002, 0x0003, 0x0004, 0x0005, 0x0006, 0x0007, + 0x0008, 0x0009, 0x000a, 0x000b, 0x000c, 0x000d, 0x000e, 0x000f, + 0x0010, 0x0011, 0x0012, 0x0013, 0x0014, 0x0015, 0x0016, 0x0017, + 0x0018, 0x0019, 0x001a, 0x001b, 0x001c, 0x001d, 0x001e, 0x001f, + 0x0020, 0x0021, 0x0022, 0x0023, 0x0024, 0x066a, 0x0026, 0x0027, + 0x0028, 0x0029, 0x002a, 0x002b, 0x002c, 0x002d, 0x002e, 0x002f, + 0x0030, 0x0031, 0x0032, 0x0033, 0x0034, 0x0035, 0x0036, 0x0037, + 0x0038, 0x0039, 0x003a, 0x003b, 0x003c, 0x003d, 0x003e, 0x003f, + 0x0040, 0x0041, 0x0042, 0x0043, 0x0044, 0x0045, 0x0046, 0x0047, + 0x0048, 0x0049, 0x004a, 0x004b, 0x004c, 0x004d, 0x004e, 0x004f, + 0x0050, 0x0051, 0x0052, 0x0053, 0x0054, 0x0055, 0x0056, 0x0057, + 0x0058, 0x0059, 0x005a, 0x005b, 0x005c, 0x005d, 0x005e, 0x005f, + 0x0060, 0x0061, 0x0062, 0x0063, 0x0064, 0x0065, 0x0066, 0x0067, + 0x0068, 0x0069, 0x006a, 0x006b, 0x006c, 0x006d, 0x006e, 0x006f, + 0x0070, 0x0071, 0x0072, 0x0073, 0x0074, 0x0075, 0x0076, 0x0077, + 0x0078, 0x0079, 0x007a, 0x007b, 0x007c, 0x007d, 0x007e, 0x007f, + 0x00b0, 0x00b7, 0x2219, 0x221a, 0x2592, 0x2500, 0x2502, 0x253c, + 0x2524, 0x252c, 0x251c, 0x2534, 0x2510, 0x250c, 0x2514, 0x2518, + 0x03b2, 0x221e, 0x03c6, 0x00b1, 0x00bd, 0x00bc, 0x2248, 0x00ab, + 0x00bb, 0xfef7, 0xfef8, 0x0000, 0x0000, 0xfefb, 0xfefc, 0x0000, + 0x00a0, 0x00ad, 0xfe82, 0x00a3, 0x00a4, 0xfe84, 0x0000, 0x0000, + 0xfe8e, 0xfe8f, 0xfe95, 0xfe99, 0x060c, 0xfe9d, 0xfea1, 0xfea5, + 0x0660, 0x0661, 0x0662, 0x0663, 0x0664, 0x0665, 0x0666, 0x0667, + 0x0668, 0x0669, 0xfed1, 0x061b, 0xfeb1, 0xfeb5, 0xfeb9, 0x061f, + 0x00a2, 0xfe80, 0xfe81, 0xfe83, 0xfe85, 0xfeca, 0xfe8b, 0xfe8d, + 0xfe91, 0xfe93, 0xfe97, 0xfe9b, 0xfe9f, 0xfea3, 0xfea7, 0xfea9, + 0xfeab, 0xfead, 0xfeaf, 0xfeb3, 0xfeb7, 0xfebb, 0xfebf, 0xfec1, + 0xfec5, 0xfecb, 0xfecf, 0x00a6, 0x00ac, 0x00f7, 0x00d7, 0xfec9, + 0x0640, 0xfed3, 0xfed7, 0xfedb, 0xfedf, 0xfee3, 0xfee7, 0xfeeb, + 0xfeed, 0xfeef, 0xfef3, 0xfebd, 0xfecc, 0xfece, 0xfecd, 0xfee1, + 0xfe7d, 0x0651, 0xfee5, 0xfee9, 0xfeec, 0xfef0, 0xfef2, 0xfed0, + 0xfed5, 0xfef5, 0xfef6, 0xfedd, 0xfed9, 0xfef1, 0x25a0, 0x00a0 }; static const uint16_t cp865Map[256] = { - 0x0000,0x0001,0x0002,0x0003,0x0004,0x0005,0x0006,0x0007, - 0x0008,0x0009,0x000a,0x000b,0x000c,0x000d,0x000e,0x000f, - 0x0010,0x0011,0x0012,0x0013,0x0014,0x0015,0x0016,0x0017, - 0x0018,0x0019,0x001a,0x001b,0x001c,0x001d,0x001e,0x001f, - 0x0020,0x0021,0x0022,0x0023,0x0024,0x0025,0x0026,0x0027, - 0x0028,0x0029,0x002a,0x002b,0x002c,0x002d,0x002e,0x002f, - 0x0030,0x0031,0x0032,0x0033,0x0034,0x0035,0x0036,0x0037, - 0x0038,0x0039,0x003a,0x003b,0x003c,0x003d,0x003e,0x003f, - 0x0040,0x0041,0x0042,0x0043,0x0044,0x0045,0x0046,0x0047, - 0x0048,0x0049,0x004a,0x004b,0x004c,0x004d,0x004e,0x004f, - 0x0050,0x0051,0x0052,0x0053,0x0054,0x0055,0x0056,0x0057, - 0x0058,0x0059,0x005a,0x005b,0x005c,0x005d,0x005e,0x005f, - 0x0060,0x0061,0x0062,0x0063,0x0064,0x0065,0x0066,0x0067, - 0x0068,0x0069,0x006a,0x006b,0x006c,0x006d,0x006e,0x006f, - 0x0070,0x0071,0x0072,0x0073,0x0074,0x0075,0x0076,0x0077, - 0x0078,0x0079,0x007a,0x007b,0x007c,0x007d,0x007e,0x007f, - 0x00c7,0x00fc,0x00e9,0x00e2,0x00e4,0x00e0,0x00e5,0x00e7, - 0x00ea,0x00eb,0x00e8,0x00ef,0x00ee,0x00ec,0x00c4,0x00c5, - 0x00c9,0x00e6,0x00c6,0x00f4,0x00f6,0x00f2,0x00fb,0x00f9, - 0x00ff,0x00d6,0x00dc,0x00f8,0x00a3,0x00d8,0x20a7,0x0192, - 0x00e1,0x00ed,0x00f3,0x00fa,0x00f1,0x00d1,0x00aa,0x00ba, - 0x00bf,0x2310,0x00ac,0x00bd,0x00bc,0x00a1,0x00ab,0x00a4, - 0x2591,0x2592,0x2593,0x2502,0x2524,0x2561,0x2562,0x2556, - 0x2555,0x2563,0x2551,0x2557,0x255d,0x255c,0x255b,0x2510, - 0x2514,0x2534,0x252c,0x251c,0x2500,0x253c,0x255e,0x255f, - 0x255a,0x2554,0x2569,0x2566,0x2560,0x2550,0x256c,0x2567, - 0x2568,0x2564,0x2565,0x2559,0x2558,0x2552,0x2553,0x256b, - 0x256a,0x2518,0x250c,0x2588,0x2584,0x258c,0x2590,0x2580, - 0x03b1,0x00df,0x0393,0x03c0,0x03a3,0x03c3,0x00b5,0x03c4, - 0x03a6,0x0398,0x03a9,0x03b4,0x221e,0x03c6,0x03b5,0x2229, - 0x2261,0x00b1,0x2265,0x2264,0x2320,0x2321,0x00f7,0x2248, - 0x00b0,0x2219,0x00b7,0x221a,0x207f,0x00b2,0x25a0,0x00a0 + 0x0000, 0x0001, 0x0002, 0x0003, 0x0004, 0x0005, 0x0006, 0x0007, + 0x0008, 0x0009, 0x000a, 0x000b, 0x000c, 0x000d, 0x000e, 0x000f, + 0x0010, 0x0011, 0x0012, 0x0013, 0x0014, 0x0015, 0x0016, 0x0017, + 0x0018, 0x0019, 0x001a, 0x001b, 0x001c, 0x001d, 0x001e, 0x001f, + 0x0020, 0x0021, 0x0022, 0x0023, 0x0024, 0x0025, 0x0026, 0x0027, + 0x0028, 0x0029, 0x002a, 0x002b, 0x002c, 0x002d, 0x002e, 0x002f, + 0x0030, 0x0031, 0x0032, 0x0033, 0x0034, 0x0035, 0x0036, 0x0037, + 0x0038, 0x0039, 0x003a, 0x003b, 0x003c, 0x003d, 0x003e, 0x003f, + 0x0040, 0x0041, 0x0042, 0x0043, 0x0044, 0x0045, 0x0046, 0x0047, + 0x0048, 0x0049, 0x004a, 0x004b, 0x004c, 0x004d, 0x004e, 0x004f, + 0x0050, 0x0051, 0x0052, 0x0053, 0x0054, 0x0055, 0x0056, 0x0057, + 0x0058, 0x0059, 0x005a, 0x005b, 0x005c, 0x005d, 0x005e, 0x005f, + 0x0060, 0x0061, 0x0062, 0x0063, 0x0064, 0x0065, 0x0066, 0x0067, + 0x0068, 0x0069, 0x006a, 0x006b, 0x006c, 0x006d, 0x006e, 0x006f, + 0x0070, 0x0071, 0x0072, 0x0073, 0x0074, 0x0075, 0x0076, 0x0077, + 0x0078, 0x0079, 0x007a, 0x007b, 0x007c, 0x007d, 0x007e, 0x007f, + 0x00c7, 0x00fc, 0x00e9, 0x00e2, 0x00e4, 0x00e0, 0x00e5, 0x00e7, + 0x00ea, 0x00eb, 0x00e8, 0x00ef, 0x00ee, 0x00ec, 0x00c4, 0x00c5, + 0x00c9, 0x00e6, 0x00c6, 0x00f4, 0x00f6, 0x00f2, 0x00fb, 0x00f9, + 0x00ff, 0x00d6, 0x00dc, 0x00f8, 0x00a3, 0x00d8, 0x20a7, 0x0192, + 0x00e1, 0x00ed, 0x00f3, 0x00fa, 0x00f1, 0x00d1, 0x00aa, 0x00ba, + 0x00bf, 0x2310, 0x00ac, 0x00bd, 0x00bc, 0x00a1, 0x00ab, 0x00a4, + 0x2591, 0x2592, 0x2593, 0x2502, 0x2524, 0x2561, 0x2562, 0x2556, + 0x2555, 0x2563, 0x2551, 0x2557, 0x255d, 0x255c, 0x255b, 0x2510, + 0x2514, 0x2534, 0x252c, 0x251c, 0x2500, 0x253c, 0x255e, 0x255f, + 0x255a, 0x2554, 0x2569, 0x2566, 0x2560, 0x2550, 0x256c, 0x2567, + 0x2568, 0x2564, 0x2565, 0x2559, 0x2558, 0x2552, 0x2553, 0x256b, + 0x256a, 0x2518, 0x250c, 0x2588, 0x2584, 0x258c, 0x2590, 0x2580, + 0x03b1, 0x00df, 0x0393, 0x03c0, 0x03a3, 0x03c3, 0x00b5, 0x03c4, + 0x03a6, 0x0398, 0x03a9, 0x03b4, 0x221e, 0x03c6, 0x03b5, 0x2229, + 0x2261, 0x00b1, 0x2265, 0x2264, 0x2320, 0x2321, 0x00f7, 0x2248, + 0x00b0, 0x2219, 0x00b7, 0x221a, 0x207f, 0x00b2, 0x25a0, 0x00a0 }; static const uint16_t cp866Map[256] = { - 0x0000,0x0001,0x0002,0x0003,0x0004,0x0005,0x0006,0x0007, - 0x0008,0x0009,0x000a,0x000b,0x000c,0x000d,0x000e,0x000f, - 0x0010,0x0011,0x0012,0x0013,0x0014,0x0015,0x0016,0x0017, - 0x0018,0x0019,0x001a,0x001b,0x001c,0x001d,0x001e,0x001f, - 0x0020,0x0021,0x0022,0x0023,0x0024,0x0025,0x0026,0x0027, - 0x0028,0x0029,0x002a,0x002b,0x002c,0x002d,0x002e,0x002f, - 0x0030,0x0031,0x0032,0x0033,0x0034,0x0035,0x0036,0x0037, - 0x0038,0x0039,0x003a,0x003b,0x003c,0x003d,0x003e,0x003f, - 0x0040,0x0041,0x0042,0x0043,0x0044,0x0045,0x0046,0x0047, - 0x0048,0x0049,0x004a,0x004b,0x004c,0x004d,0x004e,0x004f, - 0x0050,0x0051,0x0052,0x0053,0x0054,0x0055,0x0056,0x0057, - 0x0058,0x0059,0x005a,0x005b,0x005c,0x005d,0x005e,0x005f, - 0x0060,0x0061,0x0062,0x0063,0x0064,0x0065,0x0066,0x0067, - 0x0068,0x0069,0x006a,0x006b,0x006c,0x006d,0x006e,0x006f, - 0x0070,0x0071,0x0072,0x0073,0x0074,0x0075,0x0076,0x0077, - 0x0078,0x0079,0x007a,0x007b,0x007c,0x007d,0x007e,0x007f, - 0x0410,0x0411,0x0412,0x0413,0x0414,0x0415,0x0416,0x0417, - 0x0418,0x0419,0x041a,0x041b,0x041c,0x041d,0x041e,0x041f, - 0x0420,0x0421,0x0422,0x0423,0x0424,0x0425,0x0426,0x0427, - 0x0428,0x0429,0x042a,0x042b,0x042c,0x042d,0x042e,0x042f, - 0x0430,0x0431,0x0432,0x0433,0x0434,0x0435,0x0436,0x0437, - 0x0438,0x0439,0x043a,0x043b,0x043c,0x043d,0x043e,0x043f, - 0x2591,0x2592,0x2593,0x2502,0x2524,0x2561,0x2562,0x2556, - 0x2555,0x2563,0x2551,0x2557,0x255d,0x255c,0x255b,0x2510, - 0x2514,0x2534,0x252c,0x251c,0x2500,0x253c,0x255e,0x255f, - 0x255a,0x2554,0x2569,0x2566,0x2560,0x2550,0x256c,0x2567, - 0x2568,0x2564,0x2565,0x2559,0x2558,0x2552,0x2553,0x256b, - 0x256a,0x2518,0x250c,0x2588,0x2584,0x258c,0x2590,0x2580, - 0x0440,0x0441,0x0442,0x0443,0x0444,0x0445,0x0446,0x0447, - 0x0448,0x0449,0x044a,0x044b,0x044c,0x044d,0x044e,0x044f, - 0x0401,0x0451,0x0404,0x0454,0x0407,0x0457,0x040e,0x045e, - 0x00b0,0x2219,0x00b7,0x221a,0x2116,0x00a4,0x25a0,0x00a0 + 0x0000, 0x0001, 0x0002, 0x0003, 0x0004, 0x0005, 0x0006, 0x0007, + 0x0008, 0x0009, 0x000a, 0x000b, 0x000c, 0x000d, 0x000e, 0x000f, + 0x0010, 0x0011, 0x0012, 0x0013, 0x0014, 0x0015, 0x0016, 0x0017, + 0x0018, 0x0019, 0x001a, 0x001b, 0x001c, 0x001d, 0x001e, 0x001f, + 0x0020, 0x0021, 0x0022, 0x0023, 0x0024, 0x0025, 0x0026, 0x0027, + 0x0028, 0x0029, 0x002a, 0x002b, 0x002c, 0x002d, 0x002e, 0x002f, + 0x0030, 0x0031, 0x0032, 0x0033, 0x0034, 0x0035, 0x0036, 0x0037, + 0x0038, 0x0039, 0x003a, 0x003b, 0x003c, 0x003d, 0x003e, 0x003f, + 0x0040, 0x0041, 0x0042, 0x0043, 0x0044, 0x0045, 0x0046, 0x0047, + 0x0048, 0x0049, 0x004a, 0x004b, 0x004c, 0x004d, 0x004e, 0x004f, + 0x0050, 0x0051, 0x0052, 0x0053, 0x0054, 0x0055, 0x0056, 0x0057, + 0x0058, 0x0059, 0x005a, 0x005b, 0x005c, 0x005d, 0x005e, 0x005f, + 0x0060, 0x0061, 0x0062, 0x0063, 0x0064, 0x0065, 0x0066, 0x0067, + 0x0068, 0x0069, 0x006a, 0x006b, 0x006c, 0x006d, 0x006e, 0x006f, + 0x0070, 0x0071, 0x0072, 0x0073, 0x0074, 0x0075, 0x0076, 0x0077, + 0x0078, 0x0079, 0x007a, 0x007b, 0x007c, 0x007d, 0x007e, 0x007f, + 0x0410, 0x0411, 0x0412, 0x0413, 0x0414, 0x0415, 0x0416, 0x0417, + 0x0418, 0x0419, 0x041a, 0x041b, 0x041c, 0x041d, 0x041e, 0x041f, + 0x0420, 0x0421, 0x0422, 0x0423, 0x0424, 0x0425, 0x0426, 0x0427, + 0x0428, 0x0429, 0x042a, 0x042b, 0x042c, 0x042d, 0x042e, 0x042f, + 0x0430, 0x0431, 0x0432, 0x0433, 0x0434, 0x0435, 0x0436, 0x0437, + 0x0438, 0x0439, 0x043a, 0x043b, 0x043c, 0x043d, 0x043e, 0x043f, + 0x2591, 0x2592, 0x2593, 0x2502, 0x2524, 0x2561, 0x2562, 0x2556, + 0x2555, 0x2563, 0x2551, 0x2557, 0x255d, 0x255c, 0x255b, 0x2510, + 0x2514, 0x2534, 0x252c, 0x251c, 0x2500, 0x253c, 0x255e, 0x255f, + 0x255a, 0x2554, 0x2569, 0x2566, 0x2560, 0x2550, 0x256c, 0x2567, + 0x2568, 0x2564, 0x2565, 0x2559, 0x2558, 0x2552, 0x2553, 0x256b, + 0x256a, 0x2518, 0x250c, 0x2588, 0x2584, 0x258c, 0x2590, 0x2580, + 0x0440, 0x0441, 0x0442, 0x0443, 0x0444, 0x0445, 0x0446, 0x0447, + 0x0448, 0x0449, 0x044a, 0x044b, 0x044c, 0x044d, 0x044e, 0x044f, + 0x0401, 0x0451, 0x0404, 0x0454, 0x0407, 0x0457, 0x040e, 0x045e, + 0x00b0, 0x2219, 0x00b7, 0x221a, 0x2116, 0x00a4, 0x25a0, 0x00a0 }; - static const struct { - uint16_t code; - const uint16_t *map; + uint16_t code; + const uint16_t *map; } maps[] = { - { 437, cp437Map }, - { 737, cp737Map }, - { 775, cp775Map }, - { 850, cp850Map }, - { 852, cp852Map }, - { 855, cp855Map }, - { 857, cp857Map }, - { 860, cp860Map }, - { 861, cp861Map }, - { 862, cp862Map }, - { 863, cp863Map }, - { 864, cp864Map }, - { 865, cp865Map }, - { 866, cp866Map }, - { -1, NULL } + // clang-format off + { 437, cp437Map }, + { 737, cp737Map }, + { 775, cp775Map }, + { 850, cp850Map }, + { 852, cp852Map }, + { 855, cp855Map }, + { 857, cp857Map }, + { 860, cp860Map }, + { 861, cp861Map }, + { 862, cp862Map }, + { 863, cp863Map }, + { 864, cp864Map }, + { 865, cp865Map }, + { 866, cp866Map }, + { -1, NULL } + // clang-format on }; - /* Select a ASCII->Unicode mapping by CP number */ void select_codepage(uint16_t code, uint16_t *curmap) { - int i = 0; + uint16_t i = 0; const uint16_t *map_to_use; map_to_use = maps[0].map; while (maps[i].code != 0) { - if (maps[i].code == code) { - map_to_use = maps[i].map; - break; - } - i++; + if (maps[i].code == code) { + map_to_use = maps[i].map; + break; + } + i++; } - - for (i = 0; i < 256; i++) - curmap[i] = map_to_use[i]; + + for (uint16_t j = 0; j < 256; j++) + curmap[j] = map_to_use[j]; } diff --git a/src/printer/prt_escp.c b/src/printer/prt_escp.c index 22bd86e06..707590134 100644 --- a/src/printer/prt_escp.c +++ b/src/printer/prt_escp.c @@ -1,40 +1,38 @@ /* - * VARCem Virtual ARchaeological Computer EMulator. - * An emulator of (mostly) x86-based PC systems and devices, - * using the ISA,EISA,VLB,MCA and PCI system buses, roughly - * spanning the era between 1981 and 1995. + * VARCem Virtual ARchaeological Computer EMulator. + * An emulator of (mostly) x86-based PC systems and devices, + * using the ISA,EISA,VLB,MCA and PCI system buses, roughly + * spanning the era between 1981 and 1995. * - * This file is part of the VARCem Project. - * - * Implementation of the Generic ESC/P Dot-Matrix printer. + * Implementation of the Generic ESC/P Dot-Matrix printer. * * * - * Authors: Michael Drüing, - * Fred N. van Kempen, + * Authors: Michael Drüing, + * Fred N. van Kempen, * - * Based on code by Frederic Weymann (originally for DosBox.) + * Based on code by Frederic Weymann (originally for DosBox.) * - * Copyright 2018,2019 Michael Drüing. - * Copyright 2019,2019 Fred N. van Kempen. + * Copyright 2018-2019 Michael Drüing. + * Copyright 2019 Fred N. van Kempen. * - * Redistribution and use in source and binary forms, with - * or without modification, are permitted provided that the - * following conditions are met: + * Redistribution and use in source and binary forms, with + * or without modification, are permitted provided that the + * following conditions are met: * - * 1. Redistributions of source code must retain the entire - * above notice, this list of conditions and the following - * disclaimer. + * 1. Redistributions of source code must retain the entire + * above notice, this list of conditions and the following + * disclaimer. * - * 2. Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the - * following disclaimer in the documentation and/or other - * materials provided with the distribution. + * 2. Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the + * following disclaimer in the documentation and/or other + * materials provided with the distribution. * - * 3. Neither the name of the copyright holder nor the names - * of its contributors may be used to endorse or promote - * products derived from this software without specific - * prior written permission. + * 3. Neither the name of the copyright holder nor the names + * of its contributors may be used to endorse or promote + * products derived from this software without specific + * prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT @@ -48,6 +46,7 @@ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ +#include #include #include #include @@ -56,15 +55,16 @@ #include #include #include FT_FREETYPE_H +#define HAVE_STDARG_H #include <86box/86box.h> #include "cpu.h" #include <86box/machine.h> #include <86box/timer.h> #include <86box/mem.h> -#include <86box/rom.h> +#include <86box/rom.h> #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> @@ -72,230 +72,187 @@ #include <86box/printer.h> #include <86box/prt_devs.h> - /* Default page values (for now.) */ -#define COLOR_BLACK 7<<5 -#define PAGE_WIDTH 8.5 /* standard U.S. Letter */ -#define PAGE_HEIGHT 11.0 -#define PAGE_LMARGIN 0.0 -#define PAGE_RMARGIN PAGE_WIDTH -#define PAGE_TMARGIN 0.0 -#define PAGE_BMARGIN PAGE_HEIGHT -#define PAGE_DPI 360 -#define PAGE_CPI 10.0 /* standard 10 cpi */ -#define PAGE_LPI 6.0 /* standard 6 lpi */ - - -#ifdef _WIN32 -# define PATH_FREETYPE_DLL "freetype.dll" -#else -# define PATH_FREETYPE_DLL "libfreetype.so.6" -#endif - +#define COLOR_BLACK 7 << 5 +#define PAGE_WIDTH 8.5 /* standard U.S. Letter */ +#define PAGE_HEIGHT 11.0 +#define PAGE_LMARGIN 0.0 +#define PAGE_RMARGIN PAGE_WIDTH +#define PAGE_TMARGIN 0.0 +#define PAGE_BMARGIN PAGE_HEIGHT +#define PAGE_DPI 360 +#define PAGE_CPI 10.0 /* standard 10 cpi */ +#define PAGE_LPI 6.0 /* standard 6 lpi */ /* 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 -#define FONT_ROMAN 1 -#define FONT_SANSSERIF 2 -#define FONT_COURIER 3 -#define FONT_SCRIPT 4 -#define FONT_OCRA 5 -#define FONT_OCRB 6 +#define FONT_DEFAULT 0 +#define FONT_ROMAN 1 +#define FONT_SANSSERIF 2 +#define FONT_COURIER 3 +#define FONT_SCRIPT 4 +#define FONT_OCRA 5 +#define FONT_OCRB 6 /* Font styles. */ -#define STYLE_PROP 0x0001 -#define STYLE_CONDENSED 0x0002 -#define STYLE_BOLD 0x0004 -#define STYLE_DOUBLESTRIKE 0x0008 -#define STYLE_DOUBLEWIDTH 0x0010 -#define STYLE_ITALICS 0x0020 -#define STYLE_UNDERLINE 0x0040 -#define STYLE_SUPERSCRIPT 0x0080 -#define STYLE_SUBSCRIPT 0x0100 -#define STYLE_STRIKETHROUGH 0x0200 -#define STYLE_OVERSCORE 0x0400 +#define STYLE_PROP 0x0001 +#define STYLE_CONDENSED 0x0002 +#define STYLE_BOLD 0x0004 +#define STYLE_DOUBLESTRIKE 0x0008 +#define STYLE_DOUBLEWIDTH 0x0010 +#define STYLE_ITALICS 0x0020 +#define STYLE_UNDERLINE 0x0040 +#define STYLE_SUPERSCRIPT 0x0080 +#define STYLE_SUBSCRIPT 0x0100 +#define STYLE_STRIKETHROUGH 0x0200 +#define STYLE_OVERSCORE 0x0400 #define STYLE_DOUBLEWIDTHONELINE 0x0800 -#define STYLE_DOUBLEHEIGHT 0x1000 +#define STYLE_DOUBLEHEIGHT 0x1000 /* Underlining styles. */ -#define SCORE_NONE 0x00 -#define SCORE_SINGLE 0x01 -#define SCORE_DOUBLE 0x02 -#define SCORE_SINGLEBROKEN 0x05 -#define SCORE_DOUBLEBROKEN 0x06 +#define SCORE_NONE 0x00 +#define SCORE_SINGLE 0x01 +#define SCORE_DOUBLE 0x02 +#define SCORE_SINGLEBROKEN 0x05 +#define SCORE_DOUBLEBROKEN 0x06 /* Print quality. */ -#define QUALITY_DRAFT 0x01 -#define QUALITY_LQ 0x02 +#define QUALITY_DRAFT 0x01 +#define QUALITY_LQ 0x02 /* Typefaces. */ -#define TYPEFACE_ROMAN 0 -#define TYPEFACE_SANSSERIF 1 -#define TYPEFACE_COURIER 2 -#define TYPEFACE_PRESTIGE 3 -#define TYPEFACE_SCRIPT 4 -#define TYPEFACE_OCRB 5 -#define TYPEFACE_OCRA 6 -#define TYPEFACE_ORATOR 7 -#define TYPEFACE_ORATORS 8 -#define TYPEFACE_SCRIPTC 9 -#define TYPEFACE_ROMANT 10 -#define TYPEFACE_SANSSERIFH 11 -#define TYPEFACE_SVBUSABA 30 -#define TYPEFACE_SVJITTRA 31 - +#define TYPEFACE_ROMAN 0 +#define TYPEFACE_SANSSERIF 1 +#define TYPEFACE_COURIER 2 +#define TYPEFACE_PRESTIGE 3 +#define TYPEFACE_SCRIPT 4 +#define TYPEFACE_OCRB 5 +#define TYPEFACE_OCRA 6 +#define TYPEFACE_ORATOR 7 +#define TYPEFACE_ORATORS 8 +#define TYPEFACE_SCRIPTC 9 +#define TYPEFACE_ROMANT 10 +#define TYPEFACE_SANSSERIFH 11 +#define TYPEFACE_SVBUSABA 30 +#define TYPEFACE_SVJITTRA 31 /* Some helper macros. */ -#define PARAM16(x) (dev->esc_parms[x+1] * 256 + dev->esc_parms[x]) -#define PIXX ((unsigned)floor(dev->curr_x * dev->dpi + 0.5)) -#define PIXY ((unsigned)floor(dev->curr_y * dev->dpi + 0.5)) +#define PARAM16(x) (dev->esc_parms[x + 1] * 256 + dev->esc_parms[x]) +#define PIXX ((unsigned) floor(dev->curr_x * dev->dpi + 0.5)) +#define PIXY ((unsigned) floor(dev->curr_y * dev->dpi + 0.5)) +typedef struct psurface_t { + int8_t dirty; /* has the page been printed on? */ + char pad; -typedef struct { - int8_t dirty; /* has the page been printed on? */ - char pad; + uint16_t w; /* size and pitch //INFO */ + uint16_t h; + uint16_t pitch; - uint16_t w; /* size and pitch //INFO */ - uint16_t h; - uint16_t pitch; - - uint8_t *pixels; /* grayscale pixel data */ + uint8_t *pixels; /* grayscale pixel data */ } psurface_t; +typedef struct escp_t { + const char *name; -typedef struct { - const char *name; + void *lpt; - void *lpt; + pc_timer_t pulse_timer; + pc_timer_t timeout_timer; - pc_timer_t pulse_timer; - pc_timer_t timeout_timer; + char page_fn[260]; + uint8_t color; - char page_fn[260]; - uint8_t color; - /* page data (TODO: make configurable) */ - double page_width, /* all in inches */ - page_height, - left_margin, - top_margin, - right_margin, - bottom_margin; - uint16_t dpi; - double cpi; /* defined chars per inch */ - double lpi; /* defined lines per inch */ + double page_width; /* all in inches */ + double page_height; + double left_margin; + double top_margin; + double right_margin; + double bottom_margin; + uint16_t dpi; + double cpi; /* defined chars per inch */ + double lpi; /* defined lines per inch */ /* font data */ - double actual_cpi; /* actual cpi as with current font */ - double linespacing; /* in inch */ - double hmi; /* hor. motion index (inch); overrides CPI */ + double actual_cpi; /* actual cpi as with current font */ + double linespacing; /* in inch */ + double hmi; /* hor. motion index (inch); overrides CPI */ /* tabstops */ - double horizontal_tabs[32]; - uint8_t num_horizontal_tabs; - double vertical_tabs[16]; - int8_t num_vertical_tabs; + double horizontal_tabs[32]; + uint8_t num_horizontal_tabs; + double vertical_tabs[16]; + int8_t num_vertical_tabs; /* bit graphics data */ - uint16_t bg_h_density; /* in dpi */ - uint16_t bg_v_density; /* in dpi */ - int8_t bg_adjacent; /* print adjacent pixels (ignored) */ - uint8_t bg_bytes_per_column; - uint16_t bg_remaining_bytes; /* #bytes left before img is complete */ - uint8_t bg_column[6]; /* #bytes of the current and last col */ - uint8_t bg_bytes_read; /* #bytes read so far for current col */ + uint16_t bg_h_density; /* in dpi */ + uint16_t bg_v_density; /* in dpi */ + int8_t bg_adjacent; /* print adjacent pixels (ignored) */ + uint8_t bg_bytes_per_column; + uint16_t bg_remaining_bytes; /* #bytes left before img is complete */ + uint8_t bg_column[6]; /* #bytes of the current and last col */ + uint8_t bg_bytes_read; /* #bytes read so far for current col */ /* handshake data */ - uint8_t data; - uint8_t ack; - uint8_t select; - uint8_t busy; - uint8_t int_pending; - uint8_t error; - uint8_t autofeed; + uint8_t data; + uint8_t ack; + uint8_t select; + uint8_t busy; + uint8_t int_pending; + uint8_t error; + uint8_t autofeed; /* ESC command data */ - int8_t esc_seen; /* set to 1 if an ESC char was seen */ - int8_t fss_seen; - uint16_t esc_pending; /* in which ESC command are we */ - uint8_t esc_parms_req; - uint8_t esc_parms_curr; - uint8_t esc_parms[20]; /* 20 should be enough for everybody */ + int8_t esc_seen; /* set to 1 if an ESC char was seen */ + int8_t fss_seen; + uint16_t esc_pending; /* in which ESC command are we */ + uint8_t esc_parms_req; + uint8_t esc_parms_curr; + uint8_t esc_parms[20]; /* 20 should be enough for everybody */ /* internal page data */ - char fontpath[1024]; - char pagepath[1024]; - psurface_t *page; - double curr_x, curr_y; /* print head position (inch) */ - uint16_t current_font; - FT_Face fontface; - int8_t lq_typeface; - uint16_t font_style; - uint8_t print_quality; - uint8_t font_score; - double extra_intra_space; /* extra spacing between chars (inch) */ + char fontpath[1024]; + char pagepath[1024]; + psurface_t *page; + double curr_x; /* print head position (x, inch) */ + double curr_y; /* print head position (y, inch) */ + uint16_t current_font; + FT_Face fontface; + int8_t lq_typeface; + uint16_t font_style; + uint8_t print_quality; + uint8_t font_score; + double extra_intra_space; /* extra spacing between chars (inch) */ /* other internal data */ - uint16_t char_tables[4]; /* the character tables for ESC t */ - uint8_t curr_char_table; /* the active char table index */ - uint16_t curr_cpmap[256]; /* current ASCII->Unicode map table */ + uint16_t char_tables[4]; /* the character tables for ESC t */ + uint8_t curr_char_table; /* the active char table index */ + uint16_t curr_cpmap[256]; /* current ASCII->Unicode map table */ - int8_t multipoint_mode; /* multipoint mode, ESC X */ - double multipoint_size; /* size of font, in points */ - double multipoint_cpi; /* chars per inch in multipoint mode */ + int8_t multipoint_mode; /* multipoint mode, ESC X */ + double multipoint_size; /* size of font, in points */ + double multipoint_cpi; /* chars per inch in multipoint mode */ - uint8_t density_k; /* density modes for ESC K/L/Y/Z */ - uint8_t density_l; - uint8_t density_y; - uint8_t density_z; + uint8_t density_k; /* density modes for ESC K/L/Y/Z */ + uint8_t density_l; + uint8_t density_y; + uint8_t density_z; - int8_t print_upper_control; /* ESC 6, ESC 7 */ - int8_t print_everything_count; /* for ESC ( ^ */ + int8_t print_upper_control; /* ESC 6, ESC 7 */ + int8_t print_everything_count; /* for ESC ( ^ */ - double defined_unit; /* internal unit for some ESC/P - * commands. -1 = use default */ + double defined_unit; /* internal unit for some ESC/P + * commands. -1 = use default */ - uint8_t msb; /* MSB mode, -1 = off */ - uint8_t ctrl; - - PALETTE palcol; + uint8_t msb; /* MSB mode, -1 = off */ + uint8_t ctrl; + + PALETTE palcol; } escp_t; - static void update_font(escp_t *dev); static void @@ -313,89 +270,84 @@ print_bit_graph(escp_t *dev, uint8_t ch); static void new_page(escp_t *dev, int8_t save, int8_t resetx); - /* Codepage table, needed for ESC t ( */ static const uint16_t codepages[15] = { - 0, 437, 932, 850, 851, 853, 855, 860, + 0, 437, 932, 850, 851, 853, 855, 860, 863, 865, 852, 857, 862, 864, 866 }; - -/* "patches" to the codepage for the international charsets +/* "patches" to the codepage for the international charsets * these bytes patch the following 12 positions of the char table, in order: - * 0x23 0x24 0x40 0x5b 0x5c 0x5d 0x5e 0x60 0x7b 0x7c 0x7d 0x7e + * 0x23 0x24 0x40 0x5b 0x5c 0x5d 0x5e 0x60 0x7b 0x7c 0x7d 0x7e * TODO: Implement the missing international charsets */ static const uint16_t intCharSets[15][12] = { - { 0x0023, 0x0024, 0x0040, 0x005b, 0x005c, 0x005d, /* 0 USA */ - 0x005e, 0x0060, 0x007b, 0x007c, 0x007d, 0x007e }, + {0x0023, 0x0024, 0x0040, 0x005b, 0x005c, 0x005d, /* 0 USA */ + 0x005e, 0x0060, 0x007b, 0x007c, 0x007d, 0x007e}, - { 0x0023, 0x0024, 0x00e0, 0x00ba, 0x00e7, 0x00a7, /* 1 France */ - 0x005e, 0x0060, 0x00e9, 0x00f9, 0x00e8, 0x00a8 }, + { 0x0023, 0x0024, 0x00e0, 0x00ba, 0x00e7, 0x00a7, /* 1 France */ + 0x005e, 0x0060, 0x00e9, 0x00f9, 0x00e8, 0x00a8}, - { 0x0023, 0x0024, 0x00a7, 0x00c4, 0x00d6, 0x00dc, /* 2 Germany */ - 0x005e, 0x0060, 0x00e4, 0x00f6, 0x00fc, 0x00df }, + { 0x0023, 0x0024, 0x00a7, 0x00c4, 0x00d6, 0x00dc, /* 2 Germany */ + 0x005e, 0x0060, 0x00e4, 0x00f6, 0x00fc, 0x00df}, - { 0x00a3, 0x0024, 0x0040, 0x005b, 0x005c, 0x005d, /* 3 UK */ - 0x005e, 0x0060, 0x007b, 0x007c, 0x007d, 0x007e }, + { 0x00a3, 0x0024, 0x0040, 0x005b, 0x005c, 0x005d, /* 3 UK */ + 0x005e, 0x0060, 0x007b, 0x007c, 0x007d, 0x007e}, - { 0x0023, 0x0024, 0x0040, 0x00c6, 0x00d8, 0x00c5, /* 4 Denmark (1) */ - 0x005e, 0x0060, 0x00e6, 0x00f8, 0x00e5, 0x007e }, + { 0x0023, 0x0024, 0x0040, 0x00c6, 0x00d8, 0x00c5, /* 4 Denmark (1) */ + 0x005e, 0x0060, 0x00e6, 0x00f8, 0x00e5, 0x007e}, - { 0x0023, 0x00a4, 0x00c9, 0x00c4, 0x00d6, 0x00c5, /* 5 Sweden */ - 0x00dc, 0x00e9, 0x00e4, 0x00f6, 0x00e5, 0x00fc }, + { 0x0023, 0x00a4, 0x00c9, 0x00c4, 0x00d6, 0x00c5, /* 5 Sweden */ + 0x00dc, 0x00e9, 0x00e4, 0x00f6, 0x00e5, 0x00fc}, - { 0x0023, 0x0024, 0x0040, 0x00ba, 0x005c, 0x00e9, /* 6 Italy */ - 0x005e, 0x00f9, 0x00e0, 0x00f2, 0x00e8, 0x00ec }, + { 0x0023, 0x0024, 0x0040, 0x00ba, 0x005c, 0x00e9, /* 6 Italy */ + 0x005e, 0x00f9, 0x00e0, 0x00f2, 0x00e8, 0x00ec}, - { 0x0023, 0x0024, 0x0040, 0x005b, 0x005c, 0x005d, /* 7 Spain 1 */ - 0x005e, 0x0060, 0x007b, 0x007c, 0x007d, 0x007e }, /* TODO */ + { 0x0023, 0x0024, 0x0040, 0x005b, 0x005c, 0x005d, /* 7 Spain 1 */ + 0x005e, 0x0060, 0x007b, 0x007c, 0x007d, 0x007e}, /* TODO */ - { 0x0023, 0x0024, 0x0040, 0x005b, 0x005c, 0x005d, /* 8 Japan (English) */ - 0x005e, 0x0060, 0x007b, 0x007c, 0x007d, 0x007e }, /* TODO */ + { 0x0023, 0x0024, 0x0040, 0x005b, 0x005c, 0x005d, /* 8 Japan (English) */ + 0x005e, 0x0060, 0x007b, 0x007c, 0x007d, 0x007e}, /* TODO */ - { 0x0023, 0x0024, 0x0040, 0x005b, 0x005c, 0x005d, /* 9 Norway */ - 0x005e, 0x0060, 0x007b, 0x007c, 0x007d, 0x007e }, /* TODO */ + { 0x0023, 0x0024, 0x0040, 0x005b, 0x005c, 0x005d, /* 9 Norway */ + 0x005e, 0x0060, 0x007b, 0x007c, 0x007d, 0x007e}, /* TODO */ - { 0x0023, 0x0024, 0x0040, 0x005b, 0x005c, 0x005d, /* 10 Denmark (2) */ - 0x005e, 0x0060, 0x007b, 0x007c, 0x007d, 0x007e }, /* TODO */ + { 0x0023, 0x0024, 0x0040, 0x005b, 0x005c, 0x005d, /* 10 Denmark (2) */ + 0x005e, 0x0060, 0x007b, 0x007c, 0x007d, 0x007e}, /* TODO */ - { 0x0023, 0x0024, 0x0040, 0x005b, 0x005c, 0x005d, /* 11 Spain (2) */ - 0x005e, 0x0060, 0x007b, 0x007c, 0x007d, 0x007e }, /* TODO */ + { 0x0023, 0x0024, 0x0040, 0x005b, 0x005c, 0x005d, /* 11 Spain (2) */ + 0x005e, 0x0060, 0x007b, 0x007c, 0x007d, 0x007e}, /* TODO */ - { 0x0023, 0x0024, 0x0040, 0x005b, 0x005c, 0x005d, /* 12 Latin America */ - 0x005e, 0x0060, 0x007b, 0x007c, 0x007d, 0x007e }, /* TODO */ + { 0x0023, 0x0024, 0x0040, 0x005b, 0x005c, 0x005d, /* 12 Latin America */ + 0x005e, 0x0060, 0x007b, 0x007c, 0x007d, 0x007e}, /* TODO */ - { 0x0023, 0x0024, 0x0040, 0x005b, 0x005c, 0x005d, /* 13 Korea */ - 0x005e, 0x0060, 0x007b, 0x007c, 0x007d, 0x007e }, /* TODO */ + { 0x0023, 0x0024, 0x0040, 0x005b, 0x005c, 0x005d, /* 13 Korea */ + 0x005e, 0x0060, 0x007b, 0x007c, 0x007d, 0x007e}, /* TODO */ - { 0x0023, 0x0024, 0x00a7, 0x00c4, 0x0027, 0x0022, /* 14 Legal */ - 0x00b6, 0x0060, 0x00a9, 0x00ae, 0x2020, 0x2122 } + { 0x0023, 0x0024, 0x00a7, 0x00c4, 0x0027, 0x0022, /* 14 Legal */ + 0x00b6, 0x0060, 0x00a9, 0x00ae, 0x2020, 0x2122} }; - #ifdef ENABLE_ESCP_LOG int escp_do_log = ENABLE_ESCP_LOG; - static void escp_log(const char *fmt, ...) { va_list ap; if (escp_do_log) { - va_start(ap, fmt); - pclog_ex(fmt, ap); - va_end(ap); + va_start(ap, fmt); + pclog_ex(fmt, ap); + va_end(ap); } } #else -#define escp_log(fmt, ...) +# define escp_log(fmt, ...) #endif - /* Dump the current page into a formatted file. */ -static void +static void dump_page(escp_t *dev) { char path[1024]; @@ -405,131 +357,122 @@ dump_page(escp_t *dev) png_write_rgb(path, dev->page->pixels, dev->page->w, dev->page->h, dev->page->pitch, dev->palcol); } - static void new_page(escp_t *dev, int8_t save, int8_t resetx) { /* Dump the current page if needed. */ if (save && dev->page) - dump_page(dev); + dump_page(dev); if (resetx) - dev->curr_x = dev->left_margin; + dev->curr_x = dev->left_margin; /* Clear page. */ dev->curr_y = dev->top_margin; if (dev->page) { - dev->page->dirty = 0; - memset(dev->page->pixels, 0x00, dev->page->pitch * dev->page->h); + dev->page->dirty = 0; + memset(dev->page->pixels, 0x00, (size_t) dev->page->pitch * dev->page->h); } /* Make the page's file name. */ plat_tempfile(dev->page_fn, NULL, ".png"); } - static void pulse_timer(void *priv) { escp_t *dev = (escp_t *) priv; if (dev->ack) { - dev->ack = 0; - lpt_irq(dev->lpt, 1); + dev->ack = 0; + lpt_irq(dev->lpt, 1); } timer_disable(&dev->pulse_timer); } - static void timeout_timer(void *priv) { escp_t *dev = (escp_t *) priv; if (dev->page->dirty) - new_page(dev, 1, 1); + new_page(dev, 1, 1); timer_disable(&dev->timeout_timer); } - -static void +static void fill_palette(uint8_t redmax, uint8_t greenmax, uint8_t bluemax, uint8_t colorID, escp_t *dev) { uint8_t colormask; - int i; - float red = (float)redmax / (float)30.9; - float green = (float)greenmax / (float)30.9; - float blue = (float)bluemax / (float)30.9; + double red = (double) redmax / (double) 30.9; + double green = (double) greenmax / (double) 30.9; + double blue = (double) bluemax / (double) 30.9; - colormask = colorID<<=5; + colormask = colorID <<= 5; - for(i = 0; i < 32; i++) { - dev->palcol[i+colormask].r = 255 - (uint8_t)floor(red * (float)i); - dev->palcol[i+colormask].g = 255 - (uint8_t)floor(green * (float)i); - dev->palcol[i+colormask].b = 255 - (uint8_t)floor(blue * (float)i); + for (uint8_t i = 0; i < 32; i++) { + dev->palcol[i + colormask].r = 255 - (uint8_t) floor(red * (double) i); + dev->palcol[i + colormask].g = 255 - (uint8_t) floor(green * (double) i); + dev->palcol[i + colormask].b = 255 - (uint8_t) floor(blue * (double) i); } } - static void reset_printer(escp_t *dev) { - int i; - /* TODO: these should be configurable. */ - dev->color = COLOR_BLACK; + dev->color = COLOR_BLACK; dev->curr_x = dev->curr_y = 0.0; - dev->esc_seen = 0; - dev->fss_seen = 0; - dev->esc_pending = 0; + dev->esc_seen = 0; + dev->fss_seen = 0; + dev->esc_pending = 0; dev->esc_parms_req = dev->esc_parms_curr = 0; dev->top_margin = dev->left_margin = 0.0; dev->right_margin = dev->page_width = PAGE_WIDTH; dev->bottom_margin = dev->page_height = PAGE_HEIGHT; - dev->lpi = PAGE_LPI; - dev->linespacing = 1.0 / dev->lpi; - dev->cpi = PAGE_CPI; - dev->curr_char_table = 1; - dev->font_style = 0; - dev->extra_intra_space = 0.0; - dev->print_upper_control = 1; - dev->bg_remaining_bytes = 0; - dev->density_k = 0; - dev->density_l = 1; - dev->density_y = 2; - dev->density_z = 3; - dev->char_tables[0] = 0; /* italics */ + dev->lpi = PAGE_LPI; + dev->linespacing = 1.0 / dev->lpi; + dev->cpi = PAGE_CPI; + dev->curr_char_table = 1; + dev->font_style = 0; + dev->extra_intra_space = 0.0; + dev->print_upper_control = 1; + dev->bg_remaining_bytes = 0; + dev->density_k = 0; + dev->density_l = 1; + dev->density_y = 2; + dev->density_z = 3; + dev->char_tables[0] = 0; /* italics */ dev->char_tables[1] = dev->char_tables[2] = dev->char_tables[3] = 437; /* all other tables use CP437 */ - dev->defined_unit = -1.0; - dev->multipoint_mode = 0; - dev->multipoint_size = 0.0; - dev->multipoint_cpi = 0.0; - dev->hmi = -1; - dev->msb = 255; - dev->print_everything_count = 0; - dev->lq_typeface = TYPEFACE_COURIER; - + dev->defined_unit = -1.0; + dev->multipoint_mode = 0; + dev->multipoint_size = 0.0; + dev->multipoint_cpi = 0.0; + dev->hmi = -1; + dev->msb = 255; + dev->print_everything_count = 0; + dev->lq_typeface = TYPEFACE_COURIER; + init_codepage(dev, dev->char_tables[dev->curr_char_table]); update_font(dev); new_page(dev, 0, 1); - for (i = 0; i < 32; i++) - dev->horizontal_tabs[i] = i * 8.0 * (1.0 / dev->cpi); + for (uint8_t i = 0; i < 32; i++) + dev->horizontal_tabs[i] = i * 8.0 * (1.0 / dev->cpi); dev->num_horizontal_tabs = 32; - dev->num_vertical_tabs = -1; - - if (dev->page != NULL) - dev->page->dirty = 0; - - escp_log("ESC/P: width=%.1fin,height=%.1fin dpi=%i cpi=%i lpi=%i\n", - dev->page_width, dev->page_height, (int)dev->dpi, - (int)dev->cpi, (int)dev->lpi); -} + dev->num_vertical_tabs = -1; + if (dev->page != NULL) + dev->page->dirty = 0; + + escp_log("ESC/P: width=%.1fin,height=%.1fin dpi=%i cpi=%i lpi=%i\n", + dev->page_width, dev->page_height, (int) dev->dpi, + (int) dev->cpi, (int) dev->lpi); +} static void reset_printer_hard(escp_t *dev) @@ -540,7 +483,6 @@ reset_printer_hard(escp_t *dev) reset_printer(dev); } - /* Select a ASCII->Unicode mapping by CP number */ static void init_codepage(escp_t *dev, uint16_t num) @@ -549,1061 +491,1055 @@ init_codepage(escp_t *dev, uint16_t num) select_codepage(num, dev->curr_cpmap); } - static void update_font(escp_t *dev) { - char path[1024]; - char *fn; - FT_Matrix matrix; - double hpoints = 10.5; - double vpoints = 10.5; + char path[1024]; + const char *fn; + FT_Matrix matrix; + double hpoints = 10.5; + double vpoints = 10.5; /* We need the FreeType library. */ if (ft_lib == NULL) - return; + return; /* 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; - else switch (dev->lq_typeface) { - case TYPEFACE_ROMAN: - fn = FONT_FILE_ROMAN; - break; - case TYPEFACE_SANSSERIF: - fn = FONT_FILE_SANSSERIF; - break; - case TYPEFACE_COURIER: - fn = FONT_FILE_COURIER; - break; - case TYPEFACE_SCRIPT: - fn = FONT_FILE_SCRIPT; - break; - case TYPEFACE_OCRA: - fn = FONT_FILE_OCRA; - break; - case TYPEFACE_OCRB: - fn = FONT_FILE_OCRB; - break; - default: - fn = FONT_FILE_DOTMATRIX; - } + fn = FONT_FILE_DOTMATRIX; + else + switch (dev->lq_typeface) { + case TYPEFACE_ROMAN: + fn = FONT_FILE_ROMAN; + break; + case TYPEFACE_SANSSERIF: + fn = FONT_FILE_SANSSERIF; + break; + case TYPEFACE_COURIER: + fn = FONT_FILE_COURIER; + break; + case TYPEFACE_SCRIPT: + fn = FONT_FILE_SCRIPT; + break; + case TYPEFACE_OCRA: + fn = FONT_FILE_OCRA; + break; + case TYPEFACE_OCRB: + fn = FONT_FILE_OCRB; + break; + default: + fn = FONT_FILE_DOTMATRIX; + } /* Create a full pathname for the ROM file. */ strcpy(path, dev->fontpath); - plat_path_slash(path); + path_slash(path); strcat(path, fn); escp_log("Temp file=%s\n", path); /* Load the new font. */ - if (ft_New_Face(ft_lib, path, 0, &dev->fontface)) { - escp_log("ESC/P: unable to load font '%s'\n", path); - dev->fontface = NULL; + if (FT_New_Face(ft_lib, path, 0, &dev->fontface)) { + escp_log("ESC/P: unable to load font '%s'\n", path); + dev->fontface = NULL; } if (!dev->multipoint_mode) { - dev->actual_cpi = dev->cpi; + dev->actual_cpi = dev->cpi; - if (!(dev->font_style & STYLE_CONDENSED)) { - hpoints *= 10.0 / dev->cpi; - vpoints *= 10.0 / dev->cpi; - } + if (!(dev->font_style & STYLE_CONDENSED)) { + hpoints *= 10.0 / dev->cpi; + vpoints *= 10.0 / dev->cpi; + } - if (!(dev->font_style & STYLE_PROP)) { - if ((dev->cpi == 10.0) && (dev->font_style & STYLE_CONDENSED)) { - dev->actual_cpi = 17.14; - hpoints *= 10.0 / 17.14; - } + if (!(dev->font_style & STYLE_PROP)) { + if ((dev->cpi == 10.0) && (dev->font_style & STYLE_CONDENSED)) { + dev->actual_cpi = 17.14; + hpoints *= 10.0 / 17.14; + } - if ((dev->cpi == 12) && (dev->font_style & STYLE_CONDENSED)) { - dev->actual_cpi = 20.0; - hpoints *= 10.0 / 20.0; - vpoints *= 10.0 / 12.0; - } - } - else if (dev->font_style & STYLE_CONDENSED) - hpoints /= 2.0; + if ((dev->cpi == 12) && (dev->font_style & STYLE_CONDENSED)) { + dev->actual_cpi = 20.0; + hpoints *= 10.0 / 20.0; + vpoints *= 10.0 / 12.0; + } + } else if (dev->font_style & STYLE_CONDENSED) + hpoints /= 2.0; - if ((dev->font_style & STYLE_DOUBLEWIDTH) || - (dev->font_style & STYLE_DOUBLEWIDTHONELINE)) { - dev->actual_cpi /= 2.0; - hpoints *= 2.0; - } + if ((dev->font_style & STYLE_DOUBLEWIDTH) || (dev->font_style & STYLE_DOUBLEWIDTHONELINE)) { + dev->actual_cpi /= 2.0; + hpoints *= 2.0; + } - if (dev->font_style & STYLE_DOUBLEHEIGHT) - vpoints *= 2.0; + if (dev->font_style & STYLE_DOUBLEHEIGHT) + vpoints *= 2.0; } else { - /* Multipoint mode. */ - dev->actual_cpi = dev->multipoint_cpi; - hpoints = vpoints = dev->multipoint_size; + /* Multipoint mode. */ + dev->actual_cpi = dev->multipoint_cpi; + hpoints = vpoints = dev->multipoint_size; } if ((dev->font_style & STYLE_SUPERSCRIPT) || (dev->font_style & STYLE_SUBSCRIPT)) { - hpoints *= 2.0 / 3.0; - vpoints *= 2.0 / 3.0; - dev->actual_cpi /= 2.0 / 3.0; + hpoints *= 2.0 / 3.0; + vpoints *= 2.0 / 3.0; + dev->actual_cpi /= 2.0 / 3.0; } - ft_Set_Char_Size(dev->fontface, - (uint16_t)(hpoints * 64), (uint16_t)(vpoints * 64), - dev->dpi, dev->dpi); + FT_Set_Char_Size(dev->fontface, + (uint16_t) (hpoints * 64), (uint16_t) (vpoints * 64), + dev->dpi, dev->dpi); - if ((dev->font_style & STYLE_ITALICS) || - (dev->char_tables[dev->curr_char_table] == 0)) { - /* Italics transformation. */ - matrix.xx = 0x10000L; - matrix.xy = (FT_Fixed)(0.20 * 0x10000L); - matrix.yx = 0; - matrix.yy = 0x10000L; - ft_Set_Transform(dev->fontface, &matrix, 0); + if ((dev->font_style & STYLE_ITALICS) || (dev->char_tables[dev->curr_char_table] == 0)) { + /* Italics transformation. */ + matrix.xx = 0x10000L; + matrix.xy = (FT_Fixed) (0.20 * 0x10000L); + matrix.yx = 0; + matrix.yy = 0x10000L; + FT_Set_Transform(dev->fontface, &matrix, 0); } } - /* This is the actual ESC/P interpreter. */ static int process_char(escp_t *dev, uint8_t ch) { - double new_x, new_y; - double move_to; - double unit_size; - double reverse; - double new_top, new_bottom; + double new_x; + double new_y; + double move_to; + double unit_size; + double reverse; + double new_top; + double new_bottom; uint16_t rel_move; - int16_t i; + int16_t i; escp_log("Esc_seen=%d, fss_seen=%d\n", dev->esc_seen, dev->fss_seen); /* Determine number of additional command params that are expected. */ if (dev->esc_seen || dev->fss_seen) { - dev->esc_pending = ch; - if (dev->fss_seen) - dev->esc_pending |= 0x800; - dev->esc_seen = dev->fss_seen = 0; - dev->esc_parms_curr = 0; + dev->esc_pending = ch; + if (dev->fss_seen) + dev->esc_pending |= 0x800; + dev->esc_seen = dev->fss_seen = 0; + dev->esc_parms_curr = 0; - escp_log("Command pending=%02x, font path=%s\n", dev->esc_pending, dev->fontpath); - switch (dev->esc_pending) { - case 0x02: // Undocumented - case 0x0a: // Reverse line feed - case 0x0c: // Return to top of current page - case 0x0e: // Select double-width printing (one line) (ESC SO) - case 0x0f: // Select condensed printing (ESC SI) - case 0x23: // Cancel MSB control (ESC #) - case 0x30: // Select 1/8-inch line spacing (ESC 0) - case 0x31: // Select 7/60-inch line spacing - case 0x32: // Select 1/6-inch line spacing (ESC 2) - case 0x34: // Select italic font (ESC 4) - case 0x35: // Cancel italic font (ESC 5) - case 0x36: // Enable printing of upper control codes (ESC 6) - case 0x37: // Enable upper control codes (ESC 7) - case 0x38: // Disable paper-out detector - case 0x39: // Enable paper-out detector - case 0x3c: // Unidirectional mode (one line) (ESC <) - case 0x3d: // Set MSB to 0 (ESC =) - case 0x3e: // Set MSB to 1 (ESC >) - case 0x40: // Initialize printer (ESC @) - case 0x45: // Select bold font (ESC E) - case 0x46: // Cancel bold font (ESC F) - case 0x47: // Select double-strike printing (ESC G) - case 0x48: // Cancel double-strike printing (ESC H) - case 0x4d: // Select 10.5-point, 12-cpi (ESC M) - case 0x4f: // Cancel bottom margin - case 0x50: // Select 10.5-point, 10-cpi (ESC P) - case 0x54: // Cancel superscript/subscript printing (ESC T) - case 0x5e: // Enable printing of all character codes on next character - case 0x67: // Select 10.5-point, 15-cpi (ESC g) + escp_log("Command pending=%02x, font path=%s\n", dev->esc_pending, dev->fontpath); + switch (dev->esc_pending) { + case 0x02: // Undocumented + case 0x0a: // Reverse line feed + case 0x0c: // Return to top of current page + case 0x0e: // Select double-width printing (one line) (ESC SO) + case 0x0f: // Select condensed printing (ESC SI) + case 0x23: // Cancel MSB control (ESC #) + case 0x30: // Select 1/8-inch line spacing (ESC 0) + case 0x31: // Select 7/60-inch line spacing + case 0x32: // Select 1/6-inch line spacing (ESC 2) + case 0x34: // Select italic font (ESC 4) + case 0x35: // Cancel italic font (ESC 5) + case 0x36: // Enable printing of upper control codes (ESC 6) + case 0x37: // Enable upper control codes (ESC 7) + case 0x38: // Disable paper-out detector + case 0x39: // Enable paper-out detector + case 0x3c: // Unidirectional mode (one line) (ESC <) + case 0x3d: // Set MSB to 0 (ESC =) + case 0x3e: // Set MSB to 1 (ESC >) + case 0x40: // Initialize printer (ESC @) + case 0x45: // Select bold font (ESC E) + case 0x46: // Cancel bold font (ESC F) + case 0x47: // Select double-strike printing (ESC G) + case 0x48: // Cancel double-strike printing (ESC H) + case 0x4d: // Select 10.5-point, 12-cpi (ESC M) + case 0x4f: // Cancel bottom margin + case 0x50: // Select 10.5-point, 10-cpi (ESC P) + case 0x54: // Cancel superscript/subscript printing (ESC T) + case 0x5e: // Enable printing of all character codes on next character + case 0x67: // Select 10.5-point, 15-cpi (ESC g) - case 0x834: // Select italic font (FS 4) (= ESC 4) - case 0x835: // Cancel italic font (FS 5) (= ESC 5) - case 0x846: // Select forward feed mode (FS F) - case 0x852: // Select reverse feed mode (FS R) - dev->esc_parms_req = 0; - break; - - case 0x19: // Control paper loading/ejecting (ESC EM) - case 0x20: // Set intercharacter space (ESC SP) - case 0x21: // Master select (ESC !) - case 0x2b: // Set n/360-inch line spacing (ESC +) - case 0x2d: // Turn underline on/off (ESC -) - case 0x2f: // Select vertical tab channel (ESC /) - case 0x33: // Set n/180-inch line spacing (ESC 3) - case 0x41: // Set n/60-inch line spacing - case 0x43: // Set page length in lines (ESC C) - case 0x49: // Select character type and print pitch - case 0x4a: // Advance print position vertically (ESC J n) - case 0x4e: // Set bottom margin (ESC N) - case 0x51: // Set right margin (ESC Q) - case 0x52: // Select an international character set (ESC R) - case 0x53: // Select superscript/subscript printing (ESC S) - case 0x55: // Turn unidirectional mode on/off (ESC U) - case 0x57: // Turn double-width printing on/off (ESC W) - case 0x61: // Select justification (ESC a) - case 0x66: // Absolute horizontal tab in columns [conflict] - case 0x68: // Select double or quadruple size - case 0x69: // Immediate print - case 0x6a: // Reverse paper feed - case 0x6b: // Select typeface (ESC k) - case 0x6c: // Set left margin (ESC 1) - case 0x70: // Turn proportional mode on/off (ESC p) - case 0x72: // Select printing color (ESC r) - case 0x73: // Select low-speed mode (ESC s) - case 0x74: // Select character table (ESC t) - case 0x77: // Turn double-height printing on/off (ESC w) - case 0x78: // Select LQ or draft (ESC x) - case 0x7e: // Select/Deselect slash zero (ESC ~) - case 0x832: // Select 1/6-inch line spacing (FS 2) (= ESC 2) - case 0x833: // Set n/360-inch line spacing (FS 3) (= ESC +) - case 0x841: // Set n/60-inch line spacing (FS A) (= ESC A) - case 0x843: // Select LQ type style (FS C) (= ESC k) - case 0x845: // Select character width (FS E) - case 0x849: // Select character table (FS I) (= ESC t) - case 0x853: // Select High Speed/High Density elite pitch (FS S) - case 0x856: // Turn double-height printing on/off (FS V) (= ESC w) - dev->esc_parms_req = 1; - break; + case 0x834: // Select italic font (FS 4) (= ESC 4) + case 0x835: // Cancel italic font (FS 5) (= ESC 5) + case 0x846: // Select forward feed mode (FS F) + case 0x852: // Select reverse feed mode (FS R) + dev->esc_parms_req = 0; + break; - case 0x24: // Set absolute horizontal print position (ESC $) - case 0x3f: // Reassign bit-image mode (ESC ?) - case 0x4b: // Select 60-dpi graphics (ESC K) - case 0x4c: // Select 120-dpi graphics (ESC L) - case 0x59: // Select 120-dpi, double-speed graphics (ESC Y) - case 0x5a: // Select 240-dpi graphics (ESC Z) - case 0x5c: // Set relative horizontal print position (ESC \) - case 0x63: // Set horizontal motion index (HMI) (ESC c) - case 0x65: // Set vertical tab stops every n lines (ESC e) - case 0x85a: // Print 24-bit hex-density graphics (FS Z) - dev->esc_parms_req = 2; - break; + case 0x19: // Control paper loading/ejecting (ESC EM) + case 0x20: // Set intercharacter space (ESC SP) + case 0x21: // Master select (ESC !) + case 0x2b: // Set n/360-inch line spacing (ESC +) + case 0x2d: // Turn underline on/off (ESC -) + case 0x2f: // Select vertical tab channel (ESC /) + case 0x33: // Set n/180-inch line spacing (ESC 3) + case 0x41: // Set n/60-inch line spacing + case 0x43: // Set page length in lines (ESC C) + case 0x49: // Select character type and print pitch + case 0x4a: // Advance print position vertically (ESC J n) + case 0x4e: // Set bottom margin (ESC N) + case 0x51: // Set right margin (ESC Q) + case 0x52: // Select an international character set (ESC R) + case 0x53: // Select superscript/subscript printing (ESC S) + case 0x55: // Turn unidirectional mode on/off (ESC U) + case 0x57: // Turn double-width printing on/off (ESC W) + case 0x61: // Select justification (ESC a) + case 0x66: // Absolute horizontal tab in columns [conflict] + case 0x68: // Select double or quadruple size + case 0x69: // Immediate print + case 0x6a: // Reverse paper feed + case 0x6b: // Select typeface (ESC k) + case 0x6c: // Set left margin (ESC 1) + case 0x70: // Turn proportional mode on/off (ESC p) + case 0x72: // Select printing color (ESC r) + case 0x73: // Select low-speed mode (ESC s) + case 0x74: // Select character table (ESC t) + case 0x77: // Turn double-height printing on/off (ESC w) + case 0x78: // Select LQ or draft (ESC x) + case 0x7e: // Select/Deselect slash zero (ESC ~) + case 0x832: // Select 1/6-inch line spacing (FS 2) (= ESC 2) + case 0x833: // Set n/360-inch line spacing (FS 3) (= ESC +) + case 0x841: // Set n/60-inch line spacing (FS A) (= ESC A) + case 0x843: // Select LQ type style (FS C) (= ESC k) + case 0x845: // Select character width (FS E) + case 0x849: // Select character table (FS I) (= ESC t) + case 0x853: // Select High Speed/High Density elite pitch (FS S) + case 0x856: // Turn double-height printing on/off (FS V) (= ESC w) + dev->esc_parms_req = 1; + break; - case 0x2a: // Select bit image (ESC *) - case 0x58: // Select font by pitch and point (ESC X) - dev->esc_parms_req = 3; - break; + case 0x24: // Set absolute horizontal print position (ESC $) + case 0x3f: // Reassign bit-image mode (ESC ?) + case 0x4b: // Select 60-dpi graphics (ESC K) + case 0x4c: // Select 120-dpi graphics (ESC L) + case 0x59: // Select 120-dpi, double-speed graphics (ESC Y) + case 0x5a: // Select 240-dpi graphics (ESC Z) + case 0x5c: // Set relative horizontal print position (ESC \) + case 0x63: // Set horizontal motion index (HMI) (ESC c) + case 0x65: // Set vertical tab stops every n lines (ESC e) + case 0x85a: // Print 24-bit hex-density graphics (FS Z) + dev->esc_parms_req = 2; + break; - case 0x5b: // Select character height, width, line spacing - dev->esc_parms_req = 7; - break; - - case 0x62: // Set vertical tabs in VFU channels (ESC b) - case 0x42: // Set vertical tabs (ESC B) - dev->num_vertical_tabs = 0; - return 1; + case 0x2a: // Select bit image (ESC *) + case 0x58: // Select font by pitch and point (ESC X) + dev->esc_parms_req = 3; + break; - case 0x44: // Set horizontal tabs (ESC D) - dev->num_horizontal_tabs = 0; - return 1; + case 0x5b: // Select character height, width, line spacing + dev->esc_parms_req = 7; + break; - case 0x25: // Select user-defined set (ESC %) - case 0x26: // Define user-defined characters (ESC &) - case 0x3a: // Copy ROM to RAM (ESC :) - escp_log("ESC/P: User-defined characters not supported (0x%02x).\n", dev->esc_pending); - return 1; + case 0x62: // Set vertical tabs in VFU channels (ESC b) + case 0x42: // Set vertical tabs (ESC B) + dev->num_vertical_tabs = 0; + return 1; - case 0x28: // Two bytes sequence - /* return and wait for second ESC byte */ - return 1; + case 0x44: // Set horizontal tabs (ESC D) + dev->num_horizontal_tabs = 0; + return 1; - case 0x2e: - fatal("ESC/P: Print Raster Graphics (2E) command is not implemented.\nTerminating the emulator to avoid endless PNG generation.\n"); - exit(-1); - return 1; + case 0x25: // Select user-defined set (ESC %) + case 0x26: // Define user-defined characters (ESC &) + case 0x3a: // Copy ROM to RAM (ESC :) + escp_log("ESC/P: User-defined characters not supported (0x%02x).\n", dev->esc_pending); + return 1; - default: - escp_log("ESC/P: Unknown command ESC %c (0x%02x). Unable to skip parameters.\n", - dev->esc_pending >= 0x20 ? dev->esc_pending : '?', dev->esc_pending); - dev->esc_parms_req = 0; - dev->esc_pending = 0; - return 1; - } + case 0x28: // Two bytes sequence + /* return and wait for second ESC byte */ + return 1; - if (dev->esc_parms_req > 0) { - /* return and wait for parameters to appear */ - return 1; - } + case 0x2e: + fatal("ESC/P: Print Raster Graphics (2E) command is not implemented.\nTerminating the emulator to avoid endless PNG generation.\n"); + exit(-1); + + default: + escp_log("ESC/P: Unknown command ESC %c (0x%02x). Unable to skip parameters.\n", + dev->esc_pending >= 0x20 ? dev->esc_pending : '?', dev->esc_pending); + dev->esc_parms_req = 0; + dev->esc_pending = 0; + return 1; + } + + if (dev->esc_parms_req > 0) { + /* return and wait for parameters to appear */ + return 1; + } } /* parameter checking for the 2-byte ESC/P2 commands */ if (dev->esc_pending == '(') { - dev->esc_pending = 0x0200 + ch; + dev->esc_pending = 0x0200 + ch; - escp_log("Two-byte command pending=%03x, font path=%s\n", dev->esc_pending, dev->fontpath); - switch (dev->esc_pending) { - case 0x0242: // Bar code setup and print (ESC (B) - case 0x025e: // Print data as characters (ESC (^) - dev->esc_parms_req = 2; - break; + escp_log("Two-byte command pending=%03x, font path=%s\n", dev->esc_pending, dev->fontpath); + switch (dev->esc_pending) { + case 0x0242: // Bar code setup and print (ESC (B) + case 0x025e: // Print data as characters (ESC (^) + dev->esc_parms_req = 2; + break; - case 0x0255: // Set unit (ESC (U) - dev->esc_parms_req = 3; - break; + case 0x0255: // Set unit (ESC (U) + dev->esc_parms_req = 3; + break; - case 0x0243: // Set page length in defined unit (ESC (C) - case 0x0256: // Set absolute vertical print position (ESC (V) - case 0x0276: // Set relative vertical print position (ESC (v) - dev->esc_parms_req = 4; - break; + case 0x0243: // Set page length in defined unit (ESC (C) + case 0x0256: // Set absolute vertical print position (ESC (V) + case 0x0276: // Set relative vertical print position (ESC (v) + dev->esc_parms_req = 4; + break; - case 0x0228: // Assign character table (ESC (t) - case 0x022d: // Select line/score (ESC (-) - dev->esc_parms_req = 5; - break; + case 0x0228: // Assign character table (ESC (t) + case 0x022d: // Select line/score (ESC (-) + dev->esc_parms_req = 5; + break; - case 0x0263: // Set page format (ESC (c) - dev->esc_parms_req = 6; - break; + case 0x0263: // Set page format (ESC (c) + dev->esc_parms_req = 6; + break; - default: - /* ESC ( commands are always followed by a "number of parameters" word parameter */ - dev->esc_parms_req = 2; - dev->esc_pending = 0x101; /* dummy value to be checked later */ - return 1; - } + default: + /* ESC ( commands are always followed by a "number of parameters" word parameter */ + dev->esc_parms_req = 2; + dev->esc_pending = 0x101; /* dummy value to be checked later */ + return 1; + } - /* If we need parameters, return and wait for them to appear. */ - if (dev->esc_parms_req > 0) - return 1; + /* If we need parameters, return and wait for them to appear. */ + if (dev->esc_parms_req > 0) + return 1; } /* Ignore VFU channel setting. */ if (dev->esc_pending == 0x62) { - dev->esc_pending = 0x42; - return 1; + dev->esc_pending = 0x42; + return 1; } /* Collect vertical tabs. */ if (dev->esc_pending == 0x42) { - /* check if we're done */ - if ((ch == 0) || - (dev->num_vertical_tabs > 0 && dev->vertical_tabs[dev->num_vertical_tabs - 1] > (double)ch * dev->linespacing)) { - dev->esc_pending = 0; - } else { - if (dev->num_vertical_tabs >= 0 && dev->num_vertical_tabs < 16) - dev->vertical_tabs[dev->num_vertical_tabs++] = (double)ch * dev->linespacing; - } + /* check if we're done */ + if ((ch == 0) || (dev->num_vertical_tabs > 0 && dev->vertical_tabs[dev->num_vertical_tabs - 1] > (double) ch * dev->linespacing)) { + dev->esc_pending = 0; + } else { + if (dev->num_vertical_tabs >= 0 && dev->num_vertical_tabs < 16) + dev->vertical_tabs[dev->num_vertical_tabs++] = (double) ch * dev->linespacing; + } } /* Collect horizontal tabs. */ if (dev->esc_pending == 0x44) { - /* check if we're done... */ - if ((ch == 0) || - (dev->num_horizontal_tabs > 0 && dev->horizontal_tabs[dev->num_horizontal_tabs - 1] > (double)ch * (1.0 / dev->cpi))) { - dev->esc_pending = 0; - } else { - if (dev->num_horizontal_tabs < 32) - dev->horizontal_tabs[dev->num_horizontal_tabs++] = (double)ch * (1.0 / dev->cpi); - } + /* check if we're done... */ + if ((ch == 0) || (dev->num_horizontal_tabs > 0 && dev->horizontal_tabs[dev->num_horizontal_tabs - 1] > (double) ch * (1.0 / dev->cpi))) { + dev->esc_pending = 0; + } else { + if (dev->num_horizontal_tabs < 32) + dev->horizontal_tabs[dev->num_horizontal_tabs++] = (double) ch * (1.0 / dev->cpi); + } } /* Check if we're still collecting parameters for the current command. */ if (dev->esc_parms_curr < dev->esc_parms_req) { - /* store current parameter */ - dev->esc_parms[dev->esc_parms_curr++] = ch; + /* store current parameter */ + dev->esc_parms[dev->esc_parms_curr++] = ch; - /* do we still need to continue collecting parameters? */ - if (dev->esc_parms_curr < dev->esc_parms_req) - return 1; + /* do we still need to continue collecting parameters? */ + if (dev->esc_parms_curr < dev->esc_parms_req) + return 1; } /* Handle the pending ESC command. */ if (dev->esc_pending != 0) { - switch (dev->esc_pending) { - case 0x02: /* undocumented; ignore */ - break; - - case 0x0e: /* select double-width (one line) (ESC SO) */ - if (! dev->multipoint_mode) { - dev->hmi = -1; - dev->font_style |= STYLE_DOUBLEWIDTHONELINE; - update_font(dev); - } - break; - - case 0x0f: /* select condensed printing (ESC SI) */ - if (! dev->multipoint_mode && (dev->cpi != 15.0)) { - dev->hmi = -1; - dev->font_style |= STYLE_CONDENSED; - update_font(dev); - } - break; - - case 0x19: /* control paper loading/ejecting (ESC EM) */ - /* We are not really loading paper, so most - * commands can be ignored */ - if (dev->esc_parms[0] == 'R') - new_page(dev, 1, 0); - - break; - case 0x20: /* set intercharacter space (ESC SP) */ - if (! dev->multipoint_mode) { - dev->extra_intra_space = (double)dev->esc_parms[0] / (dev->print_quality == QUALITY_DRAFT ? 120.0 : 180.0); - dev->hmi = -1; - update_font(dev); - } - break; - - case 0x21: /* master select (ESC !) */ - dev->cpi = dev->esc_parms[0] & 0x01 ? 12.0 : 10.0; - - /* Reset first seven bits. */ - dev->font_style &= 0xFF80; - if (dev->esc_parms[0] & 0x02) - dev->font_style |= STYLE_PROP; - if (dev->esc_parms[0] & 0x04) - dev->font_style |= STYLE_CONDENSED; - if (dev->esc_parms[0] & 0x08) - dev->font_style |= STYLE_BOLD; - if (dev->esc_parms[0] & 0x10) - dev->font_style |= STYLE_DOUBLESTRIKE; - if (dev->esc_parms[0] & 0x20) - dev->font_style |= STYLE_DOUBLEWIDTH; - if (dev->esc_parms[0] & 0x40) - dev->font_style |= STYLE_ITALICS; - if (dev->esc_parms[0] & 0x80) { - dev->font_score = SCORE_SINGLE; - dev->font_style |= STYLE_UNDERLINE; - } - - dev->hmi = -1; - dev->multipoint_mode = 0; - update_font(dev); - break; - - case 0x23: /* cancel MSB control (ESC #) */ - dev->msb = 255; - break; - - case 0x24: /* set abs horizontal print position (ESC $) */ - unit_size = dev->defined_unit; - if (unit_size < 0) - unit_size = 60.0; - - new_x = dev->left_margin + ((double)PARAM16(0) / unit_size); - if (new_x <= dev->right_margin) - dev->curr_x = new_x; - break; - - case 0x85a: /* Print 24-bit hex-density graphics (FS Z) */ - setup_bit_image(dev, 40, PARAM16(0)); - break; - - case 0x2a: /* select bit image (ESC *) */ - setup_bit_image(dev, dev->esc_parms[0], PARAM16(1)); - break; - - case 0x2b: /* set n/360-inch line spacing (ESC +) */ - case 0x833: /* Set n/360-inch line spacing (FS 3) */ - dev->linespacing = (double)dev->esc_parms[0] / 360.0; - break; - - case 0x2d: /* turn underline on/off (ESC -) */ - if (dev->esc_parms[0] == 0 || dev->esc_parms[0] == '0') - dev->font_style &= ~STYLE_UNDERLINE; - if (dev->esc_parms[0] == 1 || dev->esc_parms[0] == '1') { - dev->font_style |= STYLE_UNDERLINE; - dev->font_score = SCORE_SINGLE; - } - update_font(dev); - break; - - case 0x2f: /* select vertical tab channel (ESC /) */ - /* Ignore */ - break; - - case 0x30: /* select 1/8-inch line spacing (ESC 0) */ - dev->linespacing = 1.0 / 8.0; - break; - - case 0x31: /* select 7/60-inch line spacing */ - dev->linespacing = 7.0 / 60.0; - break; - - case 0x32: /* select 1/6-inch line spacing (ESC 2) */ - dev->linespacing = 1.0 / 6.0; - break; - - case 0x33: /* set n/180-inch line spacing (ESC 3) */ - dev->linespacing = (double)dev->esc_parms[0] / 180.0; - break; - - case 0x34: /* select italic font (ESC 4) */ - dev->font_style |= STYLE_ITALICS; - update_font(dev); - break; - - case 0x35: /* cancel italic font (ESC 5) */ - dev->font_style &= ~STYLE_ITALICS; - update_font(dev); - break; - - case 0x36: /* enable printing of upper control codes (ESC 6) */ - dev->print_upper_control = 1; - break; - - case 0x37: /* enable upper control codes (ESC 7) */ - dev->print_upper_control = 0; - break; - - case 0x3c: /* unidirectional mode (one line) (ESC <) */ - /* We don't have a print head, so just - * ignore this. */ - break; - - case 0x3d: /* set MSB to 0 (ESC =) */ - dev->msb = 0; - break; - - case 0x3e: /* set MSB to 1 (ESC >) */ - dev->msb = 1; - break; - - case 0x3f: /* reassign bit-image mode (ESC ?) */ - if (dev->esc_parms[0] == 'K') - dev->density_k = dev->esc_parms[1]; - if (dev->esc_parms[0] == 'L') - dev->density_l = dev->esc_parms[1]; - if (dev->esc_parms[0] == 'Y') - dev->density_y = dev->esc_parms[1]; - if (dev->esc_parms[0] == 'Z') - dev->density_z = dev->esc_parms[1]; - break; - - case 0x40: /* initialize printer (ESC @) */ - reset_printer(dev); - break; - - case 0x41: /* set n/60-inch line spacing */ - case 0x841: - dev->linespacing = (double)dev->esc_parms[0] / 60.0; - break; - - case 0x43: /* set page length in lines (ESC C) */ - if (dev->esc_parms[0] != 0) { - dev->page_height = dev->bottom_margin = (double)dev->esc_parms[0] * dev->linespacing; - } else { /* == 0 => Set page length in inches */ - dev->esc_parms_req = 1; - dev->esc_parms_curr = 0; - dev->esc_pending = 0x100; /* dummy value for later */ - return 1; - } - break; - - case 0x45: /* select bold font (ESC E) */ - dev->font_style |= STYLE_BOLD; - update_font(dev); - break; - - case 0x46: /* cancel bold font (ESC F) */ - dev->font_style &= ~STYLE_BOLD; - update_font(dev); - break; - - case 0x47: /* select dobule-strike printing (ESC G) */ - dev->font_style |= STYLE_DOUBLESTRIKE; - break; - - case 0x48: /* cancel double-strike printing (ESC H) */ - dev->font_style &= ~STYLE_DOUBLESTRIKE; - break; - - case 0x4a: /* advance print pos vertically (ESC J n) */ - dev->curr_y += (double)((double)dev->esc_parms[0] / 180.0); - if (dev->curr_y > dev->bottom_margin) - new_page(dev, 1, 0); - break; - - case 0x4b: /* select 60-dpi graphics (ESC K) */ - /* TODO: graphics stuff */ - setup_bit_image(dev, dev->density_k, PARAM16(0)); - break; - - case 0x4c: /* select 120-dpi graphics (ESC L) */ - /* TODO: graphics stuff */ - setup_bit_image(dev, dev->density_l, PARAM16(0)); - break; - - case 0x4d: /* select 10.5-point, 12-cpi (ESC M) */ - dev->cpi = 12.0; - dev->hmi = -1; - dev->multipoint_mode = 0; - update_font(dev); - break; - - case 0x4e: /* set bottom margin (ESC N) */ - dev->top_margin = 0.0; - dev->bottom_margin = (double)dev->esc_parms[0] * dev->linespacing; - break; - - case 0x4f: /* cancel bottom (and top) margin */ - dev->top_margin = 0.0; - dev->bottom_margin = dev->page_height; - break; - - case 0x50: /* select 10.5-point, 10-cpi (ESC P) */ - dev->cpi = 10.0; - dev->hmi = -1; - dev->multipoint_mode = 0; - update_font(dev); - break; - - case 0x51: /* set right margin */ - dev->right_margin = ((double)dev->esc_parms[0] - 1.0) / dev->cpi; - break; - - case 0x52: /* select an intl character set (ESC R) */ - if (dev->esc_parms[0] <= 13 || dev->esc_parms[0] == '@') { - if (dev->esc_parms[0] == '@') - dev->esc_parms[0] = 14; - - dev->curr_cpmap[0x23] = intCharSets[dev->esc_parms[0]][0]; - dev->curr_cpmap[0x24] = intCharSets[dev->esc_parms[0]][1]; - dev->curr_cpmap[0x40] = intCharSets[dev->esc_parms[0]][2]; - dev->curr_cpmap[0x5b] = intCharSets[dev->esc_parms[0]][3]; - dev->curr_cpmap[0x5c] = intCharSets[dev->esc_parms[0]][4]; - dev->curr_cpmap[0x5d] = intCharSets[dev->esc_parms[0]][5]; - dev->curr_cpmap[0x5e] = intCharSets[dev->esc_parms[0]][6]; - dev->curr_cpmap[0x60] = intCharSets[dev->esc_parms[0]][7]; - dev->curr_cpmap[0x7b] = intCharSets[dev->esc_parms[0]][8]; - dev->curr_cpmap[0x7c] = intCharSets[dev->esc_parms[0]][9]; - dev->curr_cpmap[0x7d] = intCharSets[dev->esc_parms[0]][10]; - dev->curr_cpmap[0x7e] = intCharSets[dev->esc_parms[0]][11]; - } - break; - - case 0x53: /* select superscript/subscript printing (ESC S) */ - if (dev->esc_parms[0] == 0 || dev->esc_parms[0] == '0') - dev->font_style |= STYLE_SUBSCRIPT; - if (dev->esc_parms[0] == 1 || dev->esc_parms[1] == '1') - dev->font_style |= STYLE_SUPERSCRIPT; - update_font(dev); - break; - - case 0x54: /* cancel superscript/subscript printing (ESC T) */ - dev->font_style &= 0xFFFF - STYLE_SUPERSCRIPT - STYLE_SUBSCRIPT; - update_font(dev); - break; - - case 0x55: /* turn unidirectional mode on/off (ESC U) */ - /* We don't have a print head, so just ignore this. */ - break; - - case 0x57: /* turn double-width printing on/off (ESC W) */ - if (!dev->multipoint_mode) { - dev->hmi = -1; - if (dev->esc_parms[0] == 0 || dev->esc_parms[0] == '0') - dev->font_style &= ~STYLE_DOUBLEWIDTH; - if (dev->esc_parms[0] == 1 || dev->esc_parms[0] == '1') - dev->font_style |= STYLE_DOUBLEWIDTH; - update_font(dev); - } - break; - - case 0x58: /* select font by pitch and point (ESC X) */ - dev->multipoint_mode = 1; - /* Copy currently non-multipoint CPI if no value was set so far. */ - if (dev->multipoint_cpi == 0.0) { - dev->multipoint_cpi= dev->cpi; - } - if (dev->esc_parms[0] > 0) { /* set CPI */ - if (dev->esc_parms[0] == 1) { - /* Proportional spacing. */ - dev->font_style |= STYLE_PROP; - } else if (dev->esc_parms[0] >= 5) - dev->multipoint_cpi = 360.0 / (double)dev->esc_parms[0]; - } - if (dev->multipoint_size == 0.0) - dev->multipoint_size = 10.5; - if (PARAM16(1) > 0) { - /* set points */ - dev->multipoint_size = ((double)PARAM16(1)) / 2.0; - } - update_font(dev); - break; - - case 0x59: /* select 120-dpi, double-speed graphics (ESC Y) */ - /* TODO: graphics stuff */ - setup_bit_image(dev, dev->density_y, PARAM16(0)); - break; - - case 0x5a: /* select 240-dpi graphics (ESC Z) */ - /* TODO: graphics stuff */ - setup_bit_image(dev, dev->density_z, PARAM16(0)); - break; - - case 0x5c: /* set relative horizontal print pos (ESC \) */ - rel_move = PARAM16(0); - unit_size = dev->defined_unit; - if (unit_size < 0) - unit_size = (dev->print_quality == QUALITY_DRAFT ? 120.0 : 180.0); - dev->curr_x += ((double)rel_move / unit_size); - break; - - case 0x61: /* select justification (ESC a) */ - /* Ignore. */ - break; - - case 0x63: /* set horizontal motion index (HMI) (ESC c) */ - dev->hmi = (double)PARAM16(0) / 360.0; - dev->extra_intra_space = 0.0; - break; - - case 0x67: /* select 10.5-point, 15-cpi (ESC g) */ - dev->cpi = 15; - dev->hmi = -1; - dev->multipoint_mode = 0; - update_font(dev); - break; - - case 0x846: // Select forward feed mode (FS F) - set reverse not implemented yet - if (dev->linespacing < 0) - dev->linespacing *= -1; - break; - - case 0x6a: // Reverse paper feed (ESC j) - reverse = (double)PARAM16(0) / (double)216.0; - reverse = dev->curr_y - reverse; - if (reverse < dev->left_margin) - dev->curr_y = dev->left_margin; - else - dev->curr_y = reverse; - break; - - case 0x6b: /* select typeface (ESC k) */ - if (dev->esc_parms[0] <= 11 || dev->esc_parms[0] == 30 || dev->esc_parms[0] == 31) { - dev->lq_typeface = dev->esc_parms[0]; - } - update_font(dev); - break; - - case 0x6c: /* set left margin (ESC 1) */ - dev->left_margin = ((double)dev->esc_parms[0] - 1.0) / dev->cpi; - if (dev->curr_x < dev->left_margin) - dev->curr_x = dev->left_margin; - break; - - case 0x70: /* Turn proportional mode on/off (ESC p) */ - if (dev->esc_parms[0] == 0 || dev->esc_parms[0] == '0') - dev->font_style &= ~STYLE_PROP; - if (dev->esc_parms[0] == 1 || dev->esc_parms[0] == '1') { - dev->font_style |= STYLE_PROP; - dev->print_quality = QUALITY_LQ; - } - dev->multipoint_mode = 0; - dev->hmi = -1; - update_font(dev); - break; - - case 0x72: /* select printing color (ESC r) */ - if (dev->esc_parms[0] == 0 || dev->esc_parms[0] > 6) - dev->color = COLOR_BLACK; - else - dev->color = dev->esc_parms[0] << 5; - break; - - case 0x73: /* select low-speed mode (ESC s) */ - /* Ignore. */ - break; - - case 0x74: /* select character table (ESC t) */ - case 0x849: /* Select character table (FS I) */ - if (dev->esc_parms[0] < 4) { - dev->curr_char_table = dev->esc_parms[0]; - } else if ((dev->esc_parms[0] >= '0') && (dev->esc_parms[0] <= '3')) { - dev->curr_char_table = dev->esc_parms[0] - '0'; - } - init_codepage(dev, dev->char_tables[dev->curr_char_table]); - update_font(dev); - break; - - case 0x77: /* turn double-height printing on/off (ESC w) */ - if (! dev->multipoint_mode) { - if (dev->esc_parms[0] == 0 || dev->esc_parms[0] == '0') - dev->font_style &= ~STYLE_DOUBLEHEIGHT; - if (dev->esc_parms[0] == 1 || dev->esc_parms[0] == '1') - dev->font_style |= STYLE_DOUBLEHEIGHT; - update_font(dev); - } - break; - - case 0x78: /* select LQ or draft (ESC x) */ - if (dev->esc_parms[0] == 0 || dev->esc_parms[0] == '0') { - dev->print_quality = QUALITY_DRAFT; - dev->font_style |= STYLE_CONDENSED; - } - if (dev->esc_parms[0] == 1 || dev->esc_parms[0] == '1') { - dev->print_quality = QUALITY_LQ; - dev->font_style &= ~STYLE_CONDENSED; - } - dev->hmi = -1; - update_font(dev); - break; - - /* Our special command markers. */ - case 0x0100: /* set page length in inches (ESC C NUL) */ - dev->page_height = (double)dev->esc_parms[0]; - dev->bottom_margin = dev->page_height; - dev->top_margin = 0.0; - break; - - case 0x0101: /* skip unsupported ESC ( command */ - dev->esc_parms_req = PARAM16(0); - dev->esc_parms_curr = 0; - break; - - /* Extended ESC ( commands */ - case 0x0228: /* assign character table (ESC (t) */ - case 0x0274: - if (dev->esc_parms[2] < 4 && dev->esc_parms[3] < 16) { - dev->char_tables[dev->esc_parms[2]] = codepages[dev->esc_parms[3]]; - if (dev->esc_parms[2] == dev->curr_char_table) - init_codepage(dev, dev->char_tables[dev->curr_char_table]); - } - break; - - case 0x022d: /* select line/score (ESC (-) */ - dev->font_style &= ~(STYLE_UNDERLINE | STYLE_STRIKETHROUGH | STYLE_OVERSCORE); - dev->font_score = dev->esc_parms[4]; - if (dev->font_score) { - if (dev->esc_parms[3] == 1) - dev->font_style |= STYLE_UNDERLINE; - if (dev->esc_parms[3] == 2) - dev->font_style |= STYLE_STRIKETHROUGH; - if (dev->esc_parms[3] == 3) - dev->font_style |= STYLE_OVERSCORE; - } - update_font(dev); - break; - - case 0x0242: /* bar code setup and print (ESC (B) */ - //ERRLOG("ESC/P: Barcode printing not supported.\n"); - - /* Find out how many bytes to skip. */ - dev->esc_parms_req = PARAM16(0); - dev->esc_parms_curr = 0; - break; - - case 0x0243: /* set page length in defined unit (ESC (C) */ - if (dev->esc_parms[0] && (dev->defined_unit> 0)) { - dev->page_height = dev->bottom_margin = (double)PARAM16(2) * dev->defined_unit; - dev->top_margin = 0.0; - } - break; - - case 0x0255: /* set unit (ESC (U) */ - dev->defined_unit = 3600.0 / (double)dev->esc_parms[2]; - break; - - case 0x0256: /* set abse vertical print pos (ESC (V) */ - unit_size = dev->defined_unit; - if (unit_size < 0) - unit_size = 360.0; - new_y = dev->top_margin + (double)PARAM16(2) * unit_size; - if (new_y > dev->bottom_margin) - new_page(dev, 1, 0); - else - dev->curr_y = new_y; - break; - - case 0x025e: /* print data as characters (ESC (^) */ - dev->print_everything_count = PARAM16(0); - break; - - case 0x0263: /* set page format (ESC (c) */ - if (dev->defined_unit > 0.0) { - new_top = (double)PARAM16(2) * dev->defined_unit; - new_bottom = (double)PARAM16(4) * dev->defined_unit; - if (new_top >= new_bottom) - break; - if (new_top < dev->page_height) - dev->top_margin = new_top; - if (new_bottom < dev->page_height) - dev->bottom_margin = new_bottom; - if (dev->top_margin > dev->curr_y) - dev->curr_y = dev->top_margin; - } - break; - - case 0x0276: /* set relative vertical print pos (ESC (v) */ - { - unit_size = dev->defined_unit; - if (unit_size < 0.0) - unit_size = 360.0; - new_y = dev->curr_y + (double)((int16_t)PARAM16(2)) * unit_size; - if (new_y > dev->top_margin) { - if (new_y > dev->bottom_margin) - new_page(dev, 1, 0); - else - dev->curr_y = new_y; - } - } - break; - - default: - break; - } - - dev->esc_pending = 0; - return 1; + switch (dev->esc_pending) { + case 0x02: /* undocumented; ignore */ + break; + + case 0x0e: /* select double-width (one line) (ESC SO) */ + if (!dev->multipoint_mode) { + dev->hmi = -1; + dev->font_style |= STYLE_DOUBLEWIDTHONELINE; + update_font(dev); + } + break; + + case 0x0f: /* select condensed printing (ESC SI) */ + if (!dev->multipoint_mode && (dev->cpi != 15.0)) { + dev->hmi = -1; + dev->font_style |= STYLE_CONDENSED; + update_font(dev); + } + break; + + case 0x19: /* control paper loading/ejecting (ESC EM) */ + /* We are not really loading paper, so most + * commands can be ignored */ + if (dev->esc_parms[0] == 'R') + new_page(dev, 1, 0); + + break; + case 0x20: /* set intercharacter space (ESC SP) */ + if (!dev->multipoint_mode) { + dev->extra_intra_space = (double) dev->esc_parms[0] / (dev->print_quality == QUALITY_DRAFT ? 120.0 : 180.0); + dev->hmi = -1; + update_font(dev); + } + break; + + case 0x21: /* master select (ESC !) */ + dev->cpi = dev->esc_parms[0] & 0x01 ? 12.0 : 10.0; + + /* Reset first seven bits. */ + dev->font_style &= 0xFF80; + if (dev->esc_parms[0] & 0x02) + dev->font_style |= STYLE_PROP; + if (dev->esc_parms[0] & 0x04) + dev->font_style |= STYLE_CONDENSED; + if (dev->esc_parms[0] & 0x08) + dev->font_style |= STYLE_BOLD; + if (dev->esc_parms[0] & 0x10) + dev->font_style |= STYLE_DOUBLESTRIKE; + if (dev->esc_parms[0] & 0x20) + dev->font_style |= STYLE_DOUBLEWIDTH; + if (dev->esc_parms[0] & 0x40) + dev->font_style |= STYLE_ITALICS; + if (dev->esc_parms[0] & 0x80) { + dev->font_score = SCORE_SINGLE; + dev->font_style |= STYLE_UNDERLINE; + } + + dev->hmi = -1; + dev->multipoint_mode = 0; + update_font(dev); + break; + + case 0x23: /* cancel MSB control (ESC #) */ + dev->msb = 255; + break; + + case 0x24: /* set abs horizontal print position (ESC $) */ + unit_size = dev->defined_unit; + if (unit_size < 0) + unit_size = 60.0; + + new_x = dev->left_margin + ((double) PARAM16(0) / unit_size); + if (new_x <= dev->right_margin) + dev->curr_x = new_x; + break; + + case 0x85a: /* Print 24-bit hex-density graphics (FS Z) */ + setup_bit_image(dev, 40, PARAM16(0)); + break; + + case 0x2a: /* select bit image (ESC *) */ + setup_bit_image(dev, dev->esc_parms[0], PARAM16(1)); + break; + + case 0x2b: /* set n/360-inch line spacing (ESC +) */ + case 0x833: /* Set n/360-inch line spacing (FS 3) */ + dev->linespacing = (double) dev->esc_parms[0] / 360.0; + break; + + case 0x2d: /* turn underline on/off (ESC -) */ + if (dev->esc_parms[0] == 0 || dev->esc_parms[0] == '0') + dev->font_style &= ~STYLE_UNDERLINE; + if (dev->esc_parms[0] == 1 || dev->esc_parms[0] == '1') { + dev->font_style |= STYLE_UNDERLINE; + dev->font_score = SCORE_SINGLE; + } + update_font(dev); + break; + + case 0x2f: /* select vertical tab channel (ESC /) */ + /* Ignore */ + break; + + case 0x30: /* select 1/8-inch line spacing (ESC 0) */ + dev->linespacing = 1.0 / 8.0; + break; + + case 0x31: /* select 7/60-inch line spacing */ + dev->linespacing = 7.0 / 60.0; + break; + + case 0x32: /* select 1/6-inch line spacing (ESC 2) */ + dev->linespacing = 1.0 / 6.0; + break; + + case 0x33: /* set n/180-inch line spacing (ESC 3) */ + dev->linespacing = (double) dev->esc_parms[0] / 180.0; + break; + + case 0x34: /* select italic font (ESC 4) */ + dev->font_style |= STYLE_ITALICS; + update_font(dev); + break; + + case 0x35: /* cancel italic font (ESC 5) */ + dev->font_style &= ~STYLE_ITALICS; + update_font(dev); + break; + + case 0x36: /* enable printing of upper control codes (ESC 6) */ + dev->print_upper_control = 1; + break; + + case 0x37: /* enable upper control codes (ESC 7) */ + dev->print_upper_control = 0; + break; + + case 0x3c: /* unidirectional mode (one line) (ESC <) */ + /* We don't have a print head, so just + * ignore this. */ + break; + + case 0x3d: /* set MSB to 0 (ESC =) */ + dev->msb = 0; + break; + + case 0x3e: /* set MSB to 1 (ESC >) */ + dev->msb = 1; + break; + + case 0x3f: /* reassign bit-image mode (ESC ?) */ + if (dev->esc_parms[0] == 'K') + dev->density_k = dev->esc_parms[1]; + if (dev->esc_parms[0] == 'L') + dev->density_l = dev->esc_parms[1]; + if (dev->esc_parms[0] == 'Y') + dev->density_y = dev->esc_parms[1]; + if (dev->esc_parms[0] == 'Z') + dev->density_z = dev->esc_parms[1]; + break; + + case 0x40: /* initialize printer (ESC @) */ + reset_printer(dev); + break; + + case 0x41: /* set n/60-inch line spacing */ + case 0x841: + dev->linespacing = (double) dev->esc_parms[0] / 60.0; + break; + + case 0x43: /* set page length in lines (ESC C) */ + if (dev->esc_parms[0] != 0) { + dev->page_height = dev->bottom_margin = (double) dev->esc_parms[0] * dev->linespacing; + } else { /* == 0 => Set page length in inches */ + dev->esc_parms_req = 1; + dev->esc_parms_curr = 0; + dev->esc_pending = 0x100; /* dummy value for later */ + return 1; + } + break; + + case 0x45: /* select bold font (ESC E) */ + dev->font_style |= STYLE_BOLD; + update_font(dev); + break; + + case 0x46: /* cancel bold font (ESC F) */ + dev->font_style &= ~STYLE_BOLD; + update_font(dev); + break; + + case 0x47: /* select dobule-strike printing (ESC G) */ + dev->font_style |= STYLE_DOUBLESTRIKE; + break; + + case 0x48: /* cancel double-strike printing (ESC H) */ + dev->font_style &= ~STYLE_DOUBLESTRIKE; + break; + + case 0x4a: /* advance print pos vertically (ESC J n) */ + dev->curr_y += (double) ((double) dev->esc_parms[0] / 180.0); + if (dev->curr_y > dev->bottom_margin) + new_page(dev, 1, 0); + break; + + case 0x4b: /* select 60-dpi graphics (ESC K) */ + /* TODO: graphics stuff */ + setup_bit_image(dev, dev->density_k, PARAM16(0)); + break; + + case 0x4c: /* select 120-dpi graphics (ESC L) */ + /* TODO: graphics stuff */ + setup_bit_image(dev, dev->density_l, PARAM16(0)); + break; + + case 0x4d: /* select 10.5-point, 12-cpi (ESC M) */ + dev->cpi = 12.0; + dev->hmi = -1; + dev->multipoint_mode = 0; + update_font(dev); + break; + + case 0x4e: /* set bottom margin (ESC N) */ + dev->top_margin = 0.0; + dev->bottom_margin = (double) dev->esc_parms[0] * dev->linespacing; + break; + + case 0x4f: /* cancel bottom (and top) margin */ + dev->top_margin = 0.0; + dev->bottom_margin = dev->page_height; + break; + + case 0x50: /* select 10.5-point, 10-cpi (ESC P) */ + dev->cpi = 10.0; + dev->hmi = -1; + dev->multipoint_mode = 0; + update_font(dev); + break; + + case 0x51: /* set right margin */ + dev->right_margin = ((double) dev->esc_parms[0] - 1.0) / dev->cpi; + break; + + case 0x52: /* select an intl character set (ESC R) */ + if (dev->esc_parms[0] <= 13 || dev->esc_parms[0] == '@') { + if (dev->esc_parms[0] == '@') + dev->esc_parms[0] = 14; + + dev->curr_cpmap[0x23] = intCharSets[dev->esc_parms[0]][0]; + dev->curr_cpmap[0x24] = intCharSets[dev->esc_parms[0]][1]; + dev->curr_cpmap[0x40] = intCharSets[dev->esc_parms[0]][2]; + dev->curr_cpmap[0x5b] = intCharSets[dev->esc_parms[0]][3]; + dev->curr_cpmap[0x5c] = intCharSets[dev->esc_parms[0]][4]; + dev->curr_cpmap[0x5d] = intCharSets[dev->esc_parms[0]][5]; + dev->curr_cpmap[0x5e] = intCharSets[dev->esc_parms[0]][6]; + dev->curr_cpmap[0x60] = intCharSets[dev->esc_parms[0]][7]; + dev->curr_cpmap[0x7b] = intCharSets[dev->esc_parms[0]][8]; + dev->curr_cpmap[0x7c] = intCharSets[dev->esc_parms[0]][9]; + dev->curr_cpmap[0x7d] = intCharSets[dev->esc_parms[0]][10]; + dev->curr_cpmap[0x7e] = intCharSets[dev->esc_parms[0]][11]; + } + break; + + case 0x53: /* select superscript/subscript printing (ESC S) */ + if (dev->esc_parms[0] == 0 || dev->esc_parms[0] == '0') + dev->font_style |= STYLE_SUBSCRIPT; + if (dev->esc_parms[0] == 1 || dev->esc_parms[1] == '1') + dev->font_style |= STYLE_SUPERSCRIPT; + update_font(dev); + break; + + case 0x54: /* cancel superscript/subscript printing (ESC T) */ + dev->font_style &= 0xFFFF - STYLE_SUPERSCRIPT - STYLE_SUBSCRIPT; + update_font(dev); + break; + + case 0x55: /* turn unidirectional mode on/off (ESC U) */ + /* We don't have a print head, so just ignore this. */ + break; + + case 0x57: /* turn double-width printing on/off (ESC W) */ + if (!dev->multipoint_mode) { + dev->hmi = -1; + if (dev->esc_parms[0] == 0 || dev->esc_parms[0] == '0') + dev->font_style &= ~STYLE_DOUBLEWIDTH; + if (dev->esc_parms[0] == 1 || dev->esc_parms[0] == '1') + dev->font_style |= STYLE_DOUBLEWIDTH; + update_font(dev); + } + break; + + case 0x58: /* select font by pitch and point (ESC X) */ + dev->multipoint_mode = 1; + /* Copy currently non-multipoint CPI if no value was set so far. */ + if (dev->multipoint_cpi == 0.0) { + dev->multipoint_cpi = dev->cpi; + } + if (dev->esc_parms[0] > 0) { /* set CPI */ + if (dev->esc_parms[0] == 1) { + /* Proportional spacing. */ + dev->font_style |= STYLE_PROP; + } else if (dev->esc_parms[0] >= 5) + dev->multipoint_cpi = 360.0 / (double) dev->esc_parms[0]; + } + if (dev->multipoint_size == 0.0) + dev->multipoint_size = 10.5; + if (PARAM16(1) > 0) { + /* set points */ + dev->multipoint_size = ((double) PARAM16(1)) / 2.0; + } + update_font(dev); + break; + + case 0x59: /* select 120-dpi, double-speed graphics (ESC Y) */ + /* TODO: graphics stuff */ + setup_bit_image(dev, dev->density_y, PARAM16(0)); + break; + + case 0x5a: /* select 240-dpi graphics (ESC Z) */ + /* TODO: graphics stuff */ + setup_bit_image(dev, dev->density_z, PARAM16(0)); + break; + + case 0x5c: /* set relative horizontal print pos (ESC \) */ + rel_move = PARAM16(0); + unit_size = dev->defined_unit; + if (unit_size < 0) + unit_size = (dev->print_quality == QUALITY_DRAFT ? 120.0 : 180.0); + dev->curr_x += ((double) rel_move / unit_size); + break; + + case 0x61: /* select justification (ESC a) */ + /* Ignore. */ + break; + + case 0x63: /* set horizontal motion index (HMI) (ESC c) */ + dev->hmi = (double) PARAM16(0) / 360.0; + dev->extra_intra_space = 0.0; + break; + + case 0x67: /* select 10.5-point, 15-cpi (ESC g) */ + dev->cpi = 15; + dev->hmi = -1; + dev->multipoint_mode = 0; + update_font(dev); + break; + + case 0x846: // Select forward feed mode (FS F) - set reverse not implemented yet + if (dev->linespacing < 0) + dev->linespacing *= -1; + break; + + case 0x6a: // Reverse paper feed (ESC j) + reverse = (double) PARAM16(0) / (double) 216.0; + reverse = dev->curr_y - reverse; + if (reverse < dev->left_margin) + dev->curr_y = dev->left_margin; + else + dev->curr_y = reverse; + break; + + case 0x6b: /* select typeface (ESC k) */ + if (dev->esc_parms[0] <= 11 || dev->esc_parms[0] == 30 || dev->esc_parms[0] == 31) { + dev->lq_typeface = dev->esc_parms[0]; + } + update_font(dev); + break; + + case 0x6c: /* set left margin (ESC 1) */ + dev->left_margin = ((double) dev->esc_parms[0] - 1.0) / dev->cpi; + if (dev->curr_x < dev->left_margin) + dev->curr_x = dev->left_margin; + break; + + case 0x70: /* Turn proportional mode on/off (ESC p) */ + if (dev->esc_parms[0] == 0 || dev->esc_parms[0] == '0') + dev->font_style &= ~STYLE_PROP; + if (dev->esc_parms[0] == 1 || dev->esc_parms[0] == '1') { + dev->font_style |= STYLE_PROP; + dev->print_quality = QUALITY_LQ; + } + dev->multipoint_mode = 0; + dev->hmi = -1; + update_font(dev); + break; + + case 0x72: /* select printing color (ESC r) */ + if (dev->esc_parms[0] == 0 || dev->esc_parms[0] > 6) + dev->color = COLOR_BLACK; + else + dev->color = dev->esc_parms[0] << 5; + break; + + case 0x73: /* select low-speed mode (ESC s) */ + /* Ignore. */ + break; + + case 0x74: /* select character table (ESC t) */ + case 0x849: /* Select character table (FS I) */ + if (dev->esc_parms[0] < 4) { + dev->curr_char_table = dev->esc_parms[0]; + } else if ((dev->esc_parms[0] >= '0') && (dev->esc_parms[0] <= '3')) { + dev->curr_char_table = dev->esc_parms[0] - '0'; + } + init_codepage(dev, dev->char_tables[dev->curr_char_table]); + update_font(dev); + break; + + case 0x77: /* turn double-height printing on/off (ESC w) */ + if (!dev->multipoint_mode) { + if (dev->esc_parms[0] == 0 || dev->esc_parms[0] == '0') + dev->font_style &= ~STYLE_DOUBLEHEIGHT; + if (dev->esc_parms[0] == 1 || dev->esc_parms[0] == '1') + dev->font_style |= STYLE_DOUBLEHEIGHT; + update_font(dev); + } + break; + + case 0x78: /* select LQ or draft (ESC x) */ + if (dev->esc_parms[0] == 0 || dev->esc_parms[0] == '0') { + dev->print_quality = QUALITY_DRAFT; + dev->font_style |= STYLE_CONDENSED; + } + if (dev->esc_parms[0] == 1 || dev->esc_parms[0] == '1') { + dev->print_quality = QUALITY_LQ; + dev->font_style &= ~STYLE_CONDENSED; + } + dev->hmi = -1; + update_font(dev); + break; + + /* Our special command markers. */ + case 0x0100: /* set page length in inches (ESC C NUL) */ + dev->page_height = (double) dev->esc_parms[0]; + dev->bottom_margin = dev->page_height; + dev->top_margin = 0.0; + break; + + case 0x0101: /* skip unsupported ESC ( command */ + dev->esc_parms_req = PARAM16(0); + dev->esc_parms_curr = 0; + break; + + /* Extended ESC ( commands */ + case 0x0228: /* assign character table (ESC (t) */ + case 0x0274: + if (dev->esc_parms[2] < 4 && dev->esc_parms[3] < 16) { + dev->char_tables[dev->esc_parms[2]] = codepages[dev->esc_parms[3]]; + if (dev->esc_parms[2] == dev->curr_char_table) + init_codepage(dev, dev->char_tables[dev->curr_char_table]); + } + break; + + case 0x022d: /* select line/score (ESC (-) */ + dev->font_style &= ~(STYLE_UNDERLINE | STYLE_STRIKETHROUGH | STYLE_OVERSCORE); + dev->font_score = dev->esc_parms[4]; + if (dev->font_score) { + if (dev->esc_parms[3] == 1) + dev->font_style |= STYLE_UNDERLINE; + if (dev->esc_parms[3] == 2) + dev->font_style |= STYLE_STRIKETHROUGH; + if (dev->esc_parms[3] == 3) + dev->font_style |= STYLE_OVERSCORE; + } + update_font(dev); + break; + + case 0x0242: /* bar code setup and print (ESC (B) */ + // ERRLOG("ESC/P: Barcode printing not supported.\n"); + + /* Find out how many bytes to skip. */ + dev->esc_parms_req = PARAM16(0); + dev->esc_parms_curr = 0; + break; + + case 0x0243: /* set page length in defined unit (ESC (C) */ + if (dev->esc_parms[0] && (dev->defined_unit > 0)) { + dev->page_height = dev->bottom_margin = (double) PARAM16(2) * dev->defined_unit; + dev->top_margin = 0.0; + } + break; + + case 0x0255: /* set unit (ESC (U) */ + dev->defined_unit = 3600.0 / (double) dev->esc_parms[2]; + break; + + case 0x0256: /* set abse vertical print pos (ESC (V) */ + unit_size = dev->defined_unit; + if (unit_size < 0) + unit_size = 360.0; + new_y = dev->top_margin + (double) PARAM16(2) * unit_size; + if (new_y > dev->bottom_margin) + new_page(dev, 1, 0); + else + dev->curr_y = new_y; + break; + + case 0x025e: /* print data as characters (ESC (^) */ + dev->print_everything_count = PARAM16(0); + break; + + case 0x0263: /* set page format (ESC (c) */ + if (dev->defined_unit > 0.0) { + new_top = (double) PARAM16(2) * dev->defined_unit; + new_bottom = (double) PARAM16(4) * dev->defined_unit; + if (new_top >= new_bottom) + break; + if (new_top < dev->page_height) + dev->top_margin = new_top; + if (new_bottom < dev->page_height) + dev->bottom_margin = new_bottom; + if (dev->top_margin > dev->curr_y) + dev->curr_y = dev->top_margin; + } + break; + + case 0x0276: /* set relative vertical print pos (ESC (v) */ + { + unit_size = dev->defined_unit; + if (unit_size < 0.0) + unit_size = 360.0; + new_y = dev->curr_y + (double) ((int16_t) PARAM16(2)) * unit_size; + if (new_y > dev->top_margin) { + if (new_y > dev->bottom_margin) + new_page(dev, 1, 0); + else + dev->curr_y = new_y; + } + } + break; + + default: + break; + } + + dev->esc_pending = 0; + return 1; } escp_log("CH=%02x\n", ch); /* Now handle the "regular" control characters. */ switch (ch) { - case 0x00: - return 1; - - case 0x07: /* Beeper (BEL) */ - /* TODO: beep? */ - return 1; + case 0x00: + return 1; - case 0x08: /* Backspace (BS) */ - new_x = dev->curr_x - (1.0 / dev->actual_cpi); - if (dev->hmi > 0) - new_x = dev->curr_x - dev->hmi; - if (new_x >= dev->left_margin) - dev->curr_x = new_x; - return 1; + case 0x07: /* Beeper (BEL) */ + /* TODO: beep? */ + return 1; - case 0x09: /* Tab horizontally (HT) */ - /* Find tab right to current pos. */ - move_to = -1.0; - for (i = 0; i < dev->num_horizontal_tabs; i++) { - if (dev->horizontal_tabs[i] > dev->curr_x) - move_to = dev->horizontal_tabs[i]; - } + case 0x08: /* Backspace (BS) */ + new_x = dev->curr_x - (1.0 / dev->actual_cpi); + if (dev->hmi > 0) + new_x = dev->curr_x - dev->hmi; + if (new_x >= dev->left_margin) + dev->curr_x = new_x; + return 1; - /* Nothing found or out of page bounds => Ignore. */ - if (move_to > 0.0 && move_to < dev->right_margin) - dev->curr_x = move_to; + case 0x09: /* Tab horizontally (HT) */ + /* Find tab right to current pos. */ + move_to = -1.0; + for (i = 0; i < dev->num_horizontal_tabs; i++) { + if (dev->horizontal_tabs[i] > dev->curr_x) + move_to = dev->horizontal_tabs[i]; + } - return 1; + /* Nothing found or out of page bounds => Ignore. */ + if (move_to > 0.0 && move_to < dev->right_margin) + dev->curr_x = move_to; - case 0x0b: /* Tab vertically (VT) */ - if (dev->num_vertical_tabs == 0) { - /* All tabs cleared? => Act like CR */ - dev->curr_x = dev->left_margin; - } else if (dev->num_vertical_tabs < 0) { - /* No tabs set since reset => Act like LF */ - dev->curr_x = dev->left_margin; - dev->curr_y += dev->linespacing; - if (dev->curr_y > dev->bottom_margin) - new_page(dev, 1, 0); - } else { - /* Find tab below current pos. */ - move_to = -1; - for (i = 0; i < dev->num_vertical_tabs; i++) { - if (dev->vertical_tabs[i] > dev->curr_y) - move_to = dev->vertical_tabs[i]; - } + return 1; - /* Nothing found => Act like FF. */ - if (move_to > dev->bottom_margin || move_to < 0) - new_page(dev, 1, 0); - else - dev->curr_y = move_to; - } + case 0x0b: /* Tab vertically (VT) */ + if (dev->num_vertical_tabs == 0) { + /* All tabs cleared? => Act like CR */ + dev->curr_x = dev->left_margin; + } else if (dev->num_vertical_tabs < 0) { + /* No tabs set since reset => Act like LF */ + dev->curr_x = dev->left_margin; + dev->curr_y += dev->linespacing; + if (dev->curr_y > dev->bottom_margin) + new_page(dev, 1, 0); + } else { + /* Find tab below current pos. */ + move_to = -1; + for (i = 0; i < dev->num_vertical_tabs; i++) { + if (dev->vertical_tabs[i] > dev->curr_y) + move_to = dev->vertical_tabs[i]; + } - if (dev->font_style & STYLE_DOUBLEWIDTHONELINE) { - dev->font_style &= 0xFFFF - STYLE_DOUBLEWIDTHONELINE; - update_font(dev); - } - return 1; + /* Nothing found => Act like FF. */ + if (move_to > dev->bottom_margin || move_to < 0) + new_page(dev, 1, 0); + else + dev->curr_y = move_to; + } - case 0x0c: /* Form feed (FF) */ - if (dev->font_style & STYLE_DOUBLEWIDTHONELINE) { - dev->font_style &= ~STYLE_DOUBLEWIDTHONELINE; - update_font(dev); - } - new_page(dev, 1, 1); - return 1; + if (dev->font_style & STYLE_DOUBLEWIDTHONELINE) { + dev->font_style &= 0xFFFF - STYLE_DOUBLEWIDTHONELINE; + update_font(dev); + } + return 1; - case 0x0d: /* Carriage Return (CR) */ - dev->curr_x = dev->left_margin; - if (!dev->autofeed) - return 1; - /*FALLTHROUGH*/ + case 0x0c: /* Form feed (FF) */ + if (dev->font_style & STYLE_DOUBLEWIDTHONELINE) { + dev->font_style &= ~STYLE_DOUBLEWIDTHONELINE; + update_font(dev); + } + new_page(dev, 1, 1); + return 1; - case 0x0a: /* Line feed */ - if (dev->font_style & STYLE_DOUBLEWIDTHONELINE) { - dev->font_style &= ~STYLE_DOUBLEWIDTHONELINE; - update_font(dev); - } - dev->curr_x = dev->left_margin; - dev->curr_y += dev->linespacing; - if (dev->curr_y > dev->bottom_margin) - new_page(dev, 1, 0); - return 1; + case 0x0d: /* Carriage Return (CR) */ + dev->curr_x = dev->left_margin; + if (!dev->autofeed) + return 1; + fallthrough; - case 0x0e: /* select Real64-width printing (one line) (SO) */ - if (! dev->multipoint_mode) { - dev->hmi = -1; - dev->font_style |= STYLE_DOUBLEWIDTHONELINE; - update_font(dev); - } - return 1; + case 0x0a: /* Line feed */ + if (dev->font_style & STYLE_DOUBLEWIDTHONELINE) { + dev->font_style &= ~STYLE_DOUBLEWIDTHONELINE; + update_font(dev); + } + dev->curr_x = dev->left_margin; + dev->curr_y += dev->linespacing; + if (dev->curr_y > dev->bottom_margin) + new_page(dev, 1, 0); + return 1; - case 0x0f: /* select condensed printing (SI) */ - if (! dev->multipoint_mode) { - dev->hmi = -1; - dev->font_style |= STYLE_CONDENSED; - update_font(dev); - } - return 1; + case 0x0e: /* select Real64-width printing (one line) (SO) */ + if (!dev->multipoint_mode) { + dev->hmi = -1; + dev->font_style |= STYLE_DOUBLEWIDTHONELINE; + update_font(dev); + } + return 1; - case 0x11: /* select printer (DC1) */ - /* Ignore. */ - return 0; + case 0x0f: /* select condensed printing (SI) */ + if (!dev->multipoint_mode) { + dev->hmi = -1; + dev->font_style |= STYLE_CONDENSED; + update_font(dev); + } + return 1; - case 0x12: /* cancel condensed printing (DC2) */ - dev->hmi = -1; - dev->font_style &= ~STYLE_CONDENSED; - update_font(dev); - return 1; + case 0x11: /* select printer (DC1) */ + /* Ignore. */ + return 0; - case 0x13: /* deselect printer (DC3) */ - /* Ignore. */ - return 1; + case 0x12: /* cancel condensed printing (DC2) */ + dev->hmi = -1; + dev->font_style &= ~STYLE_CONDENSED; + update_font(dev); + return 1; - case 0x14: /* cancel double-width printing (one line) (DC4) */ - dev->hmi = -1; - dev->font_style &= ~STYLE_DOUBLEWIDTHONELINE; - update_font(dev); - return 1; + case 0x13: /* deselect printer (DC3) */ + /* Ignore. */ + return 1; - case 0x18: /* cancel line (CAN) */ - return 1; + case 0x14: /* cancel double-width printing (one line) (DC4) */ + dev->hmi = -1; + dev->font_style &= ~STYLE_DOUBLEWIDTHONELINE; + update_font(dev); + return 1; - case 0x1b: /* ESC */ - dev->esc_seen = 1; - return 1; - - case 0x1c: /* FS (IBM commands) */ - dev->fss_seen = 1; - return 1; + case 0x18: /* cancel line (CAN) */ + return 1; - default: - return 0; + case 0x1b: /* ESC */ + dev->esc_seen = 1; + return 1; + + case 0x1c: /* FS (IBM commands) */ + dev->fss_seen = 1; + return 1; + + default: + /* This is a printable character -> print it. */ + return 0; } - - /* This is a printable character -> print it. */ - return 0; } - static void handle_char(escp_t *dev, uint8_t ch) { - FT_UInt char_index; - uint16_t pen_x, pen_y; - uint16_t line_start, line_y; - double x_advance; + FT_UInt char_index; + uint16_t pen_x; + uint16_t pen_y; + uint16_t line_start; + uint16_t line_y; + double x_advance; if (dev->page == NULL) - return; + return; /* MSB mode */ if (dev->msb != 255) { @@ -1614,70 +1550,70 @@ handle_char(escp_t *dev, uint8_t ch) } if (dev->bg_remaining_bytes > 0) { - print_bit_graph(dev, ch); - return; + print_bit_graph(dev, ch); + return; } /* "print everything" mode? aka. ESC ( ^ */ if (dev->print_everything_count > 0) { - escp_log("Print everything count=%d\n", dev->print_everything_count); - /* do not process command char, just continue */ - dev->print_everything_count--; + escp_log("Print everything count=%d\n", dev->print_everything_count); + /* do not process command char, just continue */ + dev->print_everything_count--; } else if (process_char(dev, ch)) { - /* command was processed */ - return; + /* command was processed */ + return; } /* We cannot print if we have no font loaded. */ if (dev->fontface == NULL) - return; + return; if (ch == 0x01) - ch = 0x20; + ch = 0x20; /* 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; - pen_y = (uint16_t)(PIXY - dev->fontface->glyph->bitmap_top + dev->fontface->size->metrics.ascender / 64); + pen_y = (uint16_t) (PIXY - dev->fontface->glyph->bitmap_top + dev->fontface->size->metrics.ascender / 64); if (dev->font_style & STYLE_SUBSCRIPT) - pen_y += dev->fontface->glyph->bitmap.rows / 2; + pen_y += dev->fontface->glyph->bitmap.rows / 2; /* mark the page as dirty if anything is drawn */ if ((ch != 0x20) || (dev->font_score != SCORE_NONE)) - dev->page->dirty = 1; - + dev->page->dirty = 1; + /* draw the glyph */ blit_glyph(dev, pen_x, pen_y, 0); blit_glyph(dev, pen_x + 1, pen_y, 1); /* doublestrike -> draw glyph a second time, 1px below */ if (dev->font_style & STYLE_DOUBLESTRIKE) { - blit_glyph(dev, pen_x, pen_y + 1, 1); - blit_glyph(dev, pen_x + 1, pen_y + 1, 1); + blit_glyph(dev, pen_x, pen_y + 1, 1); + blit_glyph(dev, pen_x + 1, pen_y + 1, 1); } /* bold -> draw glyph a second time, 1px to the right */ if (dev->font_style & STYLE_BOLD) { - blit_glyph(dev, pen_x + 1, pen_y, 1); - blit_glyph(dev, pen_x + 2, pen_y, 1); - blit_glyph(dev, pen_x + 3, pen_y, 1); + blit_glyph(dev, pen_x + 1, pen_y, 1); + blit_glyph(dev, pen_x + 2, pen_y, 1); + blit_glyph(dev, pen_x + 3, pen_y, 1); } line_start = PIXX; if (dev->font_style & STYLE_PROP) - x_advance = dev->fontface->glyph->advance.x / (dev->dpi * 64.0); + x_advance = dev->fontface->glyph->advance.x / (dev->dpi * 64.0); else { - if (dev->hmi < 0) - x_advance = 1.0 / dev->actual_cpi; - else - x_advance = dev->hmi; + if (dev->hmi < 0) + x_advance = 1.0 / dev->actual_cpi; + else + x_advance = dev->hmi; } x_advance += dev->extra_intra_space; @@ -1685,243 +1621,237 @@ handle_char(escp_t *dev, uint8_t ch) /* Line printing (underline etc.) */ if (dev->font_score != SCORE_NONE && (dev->font_style & (STYLE_UNDERLINE | STYLE_STRIKETHROUGH | STYLE_OVERSCORE))) { - /* Find out where to put the line. */ - line_y = PIXY; - - if (dev->font_style & STYLE_UNDERLINE) - line_y = (PIXY + (uint16_t)(dev->fontface->size->metrics.height * 0.9)); - if (dev->font_style & STYLE_STRIKETHROUGH) - line_y = (PIXY + (uint16_t)(dev->fontface->size->metrics.height * 0.45)); - if (dev->font_style & STYLE_OVERSCORE) - line_y = PIXY - ((dev->font_score == SCORE_DOUBLE || dev->font_score == SCORE_DOUBLEBROKEN) ? 5 : 0); - - draw_hline(dev, pen_x, PIXX, line_y, dev->font_score == SCORE_SINGLEBROKEN || dev->font_score == SCORE_DOUBLEBROKEN); - - if (dev->font_score == SCORE_DOUBLE || dev->font_score == SCORE_DOUBLEBROKEN) - draw_hline(dev, line_start, PIXX, line_y + 5, dev->font_score == SCORE_SINGLEBROKEN || dev->font_score == SCORE_DOUBLEBROKEN); + /* Find out where to put the line. */ + line_y = PIXY; + + if (dev->font_style & STYLE_UNDERLINE) + line_y = (PIXY + (uint16_t) (dev->fontface->size->metrics.height * 0.9)); + if (dev->font_style & STYLE_STRIKETHROUGH) + line_y = (PIXY + (uint16_t) (dev->fontface->size->metrics.height * 0.45)); + if (dev->font_style & STYLE_OVERSCORE) + line_y = PIXY - ((dev->font_score == SCORE_DOUBLE || dev->font_score == SCORE_DOUBLEBROKEN) ? 5 : 0); + + draw_hline(dev, pen_x, PIXX, line_y, dev->font_score == SCORE_SINGLEBROKEN || dev->font_score == SCORE_DOUBLEBROKEN); + + if (dev->font_score == SCORE_DOUBLE || dev->font_score == SCORE_DOUBLEBROKEN) + draw_hline(dev, line_start, PIXX, line_y + 5, dev->font_score == SCORE_SINGLEBROKEN || dev->font_score == SCORE_DOUBLEBROKEN); } - + if ((dev->curr_x + x_advance) > dev->right_margin) { - dev->curr_x = dev->left_margin; - dev->curr_y += dev->linespacing; - if (dev->curr_y > dev->bottom_margin) - new_page(dev, 1, 0); + dev->curr_x = dev->left_margin; + dev->curr_y += dev->linespacing; + if (dev->curr_y > dev->bottom_margin) + new_page(dev, 1, 0); } } - /* TODO: This can be optimized quite a bit... I'm just too lazy right now ;-) */ static void blit_glyph(escp_t *dev, unsigned destx, unsigned desty, int8_t add) { - FT_Bitmap *bitmap = &dev->fontface->glyph->bitmap; - unsigned x, y; - uint8_t src, *dst; + const FT_Bitmap *bitmap = &dev->fontface->glyph->bitmap; + uint8_t src; + uint8_t *dst; /* check if freetype is available */ if (ft_lib == NULL) - return; + return; - for (y = 0; y < bitmap->rows; y++) { - for (x = 0; x < bitmap->width; x++) { - src = *(bitmap->buffer + x + y * bitmap->pitch); - /* ignore background, and respect page size */ - if (src > 0 && (destx + x < (unsigned)dev->page->w) && (desty + y < (unsigned)dev->page->h)) { - dst = (uint8_t *)dev->page->pixels + (x + destx) + (y + desty) * dev->page->pitch; - src >>= 3; + for (unsigned int y = 0; y < bitmap->rows; y++) { + for (unsigned int x = 0; x < bitmap->width; x++) { + src = *(bitmap->buffer + x + y * bitmap->pitch); + /* ignore background, and respect page size */ + if (src > 0 && (destx + x < (unsigned) dev->page->w) && (desty + y < (unsigned) dev->page->h)) { + dst = (uint8_t *) dev->page->pixels + (x + destx) + (y + desty) * dev->page->pitch; + src >>= 3; - if (add) { - if (((*dst) & 0x1f) + src > 31) - *dst |= (dev->color | 0x1f); - else { - *dst += src; - *dst |= dev->color; - } - } else - *dst = src|dev->color; - } - } + if (add) { + if (((*dst) & 0x1f) + src > 31) + *dst |= (dev->color | 0x1f); + else { + *dst += src; + *dst |= dev->color; + } + } else + *dst = src | dev->color; + } + } } } - /* Draw anti-aliased line. */ static void draw_hline(escp_t *dev, unsigned from_x, unsigned to_x, unsigned y, int8_t broken) { unsigned breakmod = dev->dpi / 15; unsigned gapstart = (breakmod * 4) / 5; - unsigned x; - for (x = from_x; x <= to_x; x++) { - /* Skip parts if broken line or going over the border. */ - if ((!broken || (x % breakmod <= gapstart)) && (x < dev->page->w)) { - if (y > 0 && (y - 1) < dev->page->h) - *((uint8_t*)dev->page->pixels + x + (y - 1) * (unsigned)dev->page->pitch) = 240; - if (y < dev->page->h) - *((uint8_t*)dev->page->pixels + x + y * (unsigned)dev->page->pitch) = !broken ? 255 : 240; - if (y + 1 < dev->page->h) - *((uint8_t*)dev->page->pixels + x + (y + 1) * (unsigned)dev->page->pitch) = 240; - } + for (unsigned int x = from_x; x <= to_x; x++) { + /* Skip parts if broken line or going over the border. */ + if ((!broken || (x % breakmod <= gapstart)) && (x < dev->page->w)) { + if (y > 0 && (y - 1) < dev->page->h) + *((uint8_t *) dev->page->pixels + x + (y - 1) * (unsigned) dev->page->pitch) = 240; + if (y < dev->page->h) + *((uint8_t *) dev->page->pixels + x + y * (unsigned) dev->page->pitch) = !broken ? 255 : 240; + if (y + 1 < dev->page->h) + *((uint8_t *) dev->page->pixels + x + (y + 1) * (unsigned) dev->page->pitch) = 240; + } } } - static void setup_bit_image(escp_t *dev, uint8_t density, uint16_t num_columns) { escp_log("Density=%d\n", density); switch (density) { - case 0: - dev->bg_h_density = 60; - dev->bg_v_density = 60; - dev->bg_adjacent = 1; - dev->bg_bytes_per_column = 1; - break; + case 0: + dev->bg_h_density = 60; + dev->bg_v_density = 60; + dev->bg_adjacent = 1; + dev->bg_bytes_per_column = 1; + break; - case 1: - dev->bg_h_density = 120; - dev->bg_v_density = 60; - dev->bg_adjacent = 1; - dev->bg_bytes_per_column = 1; - break; + case 1: + dev->bg_h_density = 120; + dev->bg_v_density = 60; + dev->bg_adjacent = 1; + dev->bg_bytes_per_column = 1; + break; - case 2: - dev->bg_h_density = 120; - dev->bg_v_density = 60; - dev->bg_adjacent = 0; - dev->bg_bytes_per_column = 1; - break; + case 2: + dev->bg_h_density = 120; + dev->bg_v_density = 60; + dev->bg_adjacent = 0; + dev->bg_bytes_per_column = 1; + break; - case 3: - dev->bg_h_density = 60; - dev->bg_v_density = 240; - dev->bg_adjacent = 0; - dev->bg_bytes_per_column = 1; - break; + case 3: + dev->bg_h_density = 60; + dev->bg_v_density = 240; + dev->bg_adjacent = 0; + dev->bg_bytes_per_column = 1; + break; - case 4: - dev->bg_h_density = 80; - dev->bg_v_density = 60; - dev->bg_adjacent = 1; - dev->bg_bytes_per_column = 1; - break; + case 4: + dev->bg_h_density = 80; + dev->bg_v_density = 60; + dev->bg_adjacent = 1; + dev->bg_bytes_per_column = 1; + break; - case 6: - dev->bg_h_density = 90; - dev->bg_v_density = 60; - dev->bg_adjacent = 1; - dev->bg_bytes_per_column = 1; - break; + case 6: + dev->bg_h_density = 90; + dev->bg_v_density = 60; + dev->bg_adjacent = 1; + dev->bg_bytes_per_column = 1; + break; - case 32: - dev->bg_h_density = 60; - dev->bg_v_density = 180; - dev->bg_adjacent = 1; - dev->bg_bytes_per_column = 3; - break; + case 32: + dev->bg_h_density = 60; + dev->bg_v_density = 180; + dev->bg_adjacent = 1; + dev->bg_bytes_per_column = 3; + break; - case 33: - dev->bg_h_density = 120; - dev->bg_v_density = 180; - dev->bg_adjacent = 1; - dev->bg_bytes_per_column = 3; - break; + case 33: + dev->bg_h_density = 120; + dev->bg_v_density = 180; + dev->bg_adjacent = 1; + dev->bg_bytes_per_column = 3; + break; - case 38: - dev->bg_h_density = 90; - dev->bg_v_density = 180; - dev->bg_adjacent = 1; - dev->bg_bytes_per_column = 3; - break; + case 38: + dev->bg_h_density = 90; + dev->bg_v_density = 180; + dev->bg_adjacent = 1; + dev->bg_bytes_per_column = 3; + break; - case 39: - dev->bg_h_density = 180; - dev->bg_v_density = 180; - dev->bg_adjacent = 1; - dev->bg_bytes_per_column = 3; - break; + case 39: + dev->bg_h_density = 180; + dev->bg_v_density = 180; + dev->bg_adjacent = 1; + dev->bg_bytes_per_column = 3; + break; - case 40: - dev->bg_h_density = 360; - dev->bg_v_density = 180; - dev->bg_adjacent = 0; - dev->bg_bytes_per_column = 3; - break; + case 40: + dev->bg_h_density = 360; + dev->bg_v_density = 180; + dev->bg_adjacent = 0; + dev->bg_bytes_per_column = 3; + break; - case 71: - dev->bg_h_density = 180; - dev->bg_v_density = 360; - dev->bg_adjacent = 1; - dev->bg_bytes_per_column = 6; - break; + case 71: + dev->bg_h_density = 180; + dev->bg_v_density = 360; + dev->bg_adjacent = 1; + dev->bg_bytes_per_column = 6; + break; - case 72: - dev->bg_h_density = 360; - dev->bg_v_density = 360; - dev->bg_adjacent = 0; - dev->bg_bytes_per_column = 6; - break; + case 72: + dev->bg_h_density = 360; + dev->bg_v_density = 360; + dev->bg_adjacent = 0; + dev->bg_bytes_per_column = 6; + break; - case 73: - dev->bg_h_density = 360; - dev->bg_v_density = 360; - dev->bg_adjacent = 1; - dev->bg_bytes_per_column = 6; - break; + case 73: + dev->bg_h_density = 360; + dev->bg_v_density = 360; + dev->bg_adjacent = 1; + dev->bg_bytes_per_column = 6; + break; - default: - escp_log("ESC/P: Unsupported bit image density %d.\n", density); - break; + default: + escp_log("ESC/P: Unsupported bit image density %d.\n", density); + break; } dev->bg_remaining_bytes = num_columns * dev->bg_bytes_per_column; - dev->bg_bytes_read = 0; + dev->bg_bytes_read = 0; } - static void print_bit_graph(escp_t *dev, uint8_t ch) { - uint8_t pixel_w; /* width of the "pixel" */ - uint8_t pixel_h; /* height of the "pixel" */ - unsigned i, j, xx, yy; - double old_y; + uint8_t pixel_w; /* width of the "pixel" */ + uint8_t pixel_h; /* height of the "pixel" */ + double old_y; dev->bg_column[dev->bg_bytes_read++] = ch; dev->bg_remaining_bytes--; /* Only print after reading a full column. */ if (dev->bg_bytes_read < dev->bg_bytes_per_column) - return; + return; old_y = dev->curr_y; pixel_w = 1; pixel_h = 1; - + if (dev->bg_adjacent) { - /* if page DPI is bigger than bitgraphics DPI, drawn pixels get "bigger" */ - pixel_w = dev->dpi / dev->bg_h_density > 0 ? dev->dpi / dev->bg_h_density : 1; - pixel_h = dev->dpi / dev->bg_v_density > 0 ? dev->dpi / dev->bg_v_density : 1; + /* if page DPI is bigger than bitgraphics DPI, drawn pixels get "bigger" */ + pixel_w = dev->dpi / dev->bg_h_density > 0 ? dev->dpi / dev->bg_h_density : 1; + pixel_h = dev->dpi / dev->bg_v_density > 0 ? dev->dpi / dev->bg_v_density : 1; } - for (i = 0; i < dev->bg_bytes_per_column; i++) { - /* for each byte */ - for (j = 128; j != 0; j >>= 1) { - /* for each bit */ - if (dev->bg_column[i] & j) { - /* draw a "pixel" */ - for (xx = 0; xx < pixel_w; xx++) { - for (yy = 0; yy < pixel_h; yy++) { - if (((PIXX + xx) < (unsigned)dev->page->w) && ((PIXY + yy) < (unsigned)dev->page->h)) - *((uint8_t *)dev->page->pixels + (PIXX + xx) + (PIXY + yy)*dev->page->pitch) |= (dev->color | 0x1f); - } - } - } + for (uint8_t i = 0; i < dev->bg_bytes_per_column; i++) { + /* for each byte */ + for (uint8_t j = 128; j != 0; j >>= 1) { + /* for each bit */ + if (dev->bg_column[i] & j) { + /* draw a "pixel" */ + for (uint8_t xx = 0; xx < pixel_w; xx++) { + for (uint8_t yy = 0; yy < pixel_h; yy++) { + if (((PIXX + xx) < (unsigned) dev->page->w) && ((PIXY + yy) < (unsigned) dev->page->h)) + *((uint8_t *) dev->page->pixels + (PIXX + xx) + (PIXY + yy) * dev->page->pitch) |= (dev->color | 0x1f); + } + } + } - dev->curr_y += 1.0 / (double)dev->bg_v_density; - } + dev->curr_y += 1.0 / (double) dev->bg_v_density; + } } /* Mark page dirty. */ @@ -1936,219 +1866,201 @@ print_bit_graph(escp_t *dev, uint8_t ch) dev->curr_x += 1.0 / dev->bg_h_density; } - static void write_data(uint8_t val, void *priv) { - escp_t *dev = (escp_t *)priv; + escp_t *dev = (escp_t *) priv; if (dev == NULL) - return; + return; dev->data = val; } - static void write_ctrl(uint8_t val, void *priv) { - escp_t *dev = (escp_t *)priv; + escp_t *dev = (escp_t *) priv; if (dev == NULL) - return; + return; - if (val & 0x08) { /* SELECT */ - /* select printer */ - dev->select = 1; + if (val & 0x08) { /* SELECT */ + /* select printer */ + dev->select = 1; } if ((val & 0x04) && !(dev->ctrl & 0x04)) { - /* reset printer */ - dev->select = 0; + /* reset printer */ + dev->select = 0; - reset_printer_hard(dev); + reset_printer_hard(dev); } /* Data is strobed to the parallel printer on the falling edge of the strobe bit. */ if (!(val & 0x01) && (dev->ctrl & 0x01)) { - /* Process incoming character. */ - handle_char(dev, dev->data); + /* Process incoming character. */ + handle_char(dev, dev->data); - /* ACK it, will be read on next READ STATUS. */ - dev->ack = 1; - timer_set_delay_u64(&dev->pulse_timer, ISACONST); + /* ACK it, will be read on next READ STATUS. */ + dev->ack = 1; + timer_set_delay_u64(&dev->pulse_timer, ISACONST); - timer_set_delay_u64(&dev->timeout_timer, 5000000 * TIMER_USEC); + timer_set_delay_u64(&dev->timeout_timer, 5000000 * TIMER_USEC); } dev->ctrl = val; - + dev->autofeed = ((val & 0x02) > 0); } - static uint8_t read_data(void *priv) { - escp_t *dev = (escp_t *)priv; + const escp_t *dev = (escp_t *) priv; return dev->data; } - static uint8_t read_ctrl(void *priv) { - escp_t *dev = (escp_t *)priv; + const escp_t *dev = (escp_t *) priv; return 0xe0 | (dev->autofeed ? 0x02 : 0x00) | (dev->ctrl & 0xfd); } - static uint8_t read_status(void *priv) { - escp_t *dev = (escp_t *)priv; + const escp_t *dev = (escp_t *) priv; uint8_t ret = 0x1f; ret |= 0x80; if (!dev->ack) - ret |= 0x40; + ret |= 0x40; - return(ret); + return ret; } - static void * escp_init(void *lpt) { - const char *fn = PATH_FREETYPE_DLL; escp_t *dev; - int i; - - /* 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_2110, (wchar_t *) IDS_2131); - return(NULL); - } - } /* Initialize FreeType. */ if (ft_lib == NULL) { - if (ft_Init_FreeType(&ft_lib)) { - ui_msgbox_header(MBX_ERROR, (wchar_t *) IDS_2110, (wchar_t *) IDS_2131); - dynld_close(ft_lib); - ft_lib = NULL; - return(NULL); - } + if (FT_Init_FreeType(&ft_lib)) { + pclog("ESC/P: FT_Init_FreeType failed\n"); + ft_lib = NULL; + return (NULL); + } } /* Initialize a device instance. */ - dev = (escp_t *)malloc(sizeof(escp_t)); + dev = (escp_t *) malloc(sizeof(escp_t)); memset(dev, 0x00, sizeof(escp_t)); dev->ctrl = 0x04; - dev->lpt = lpt; + dev->lpt = lpt; /* Create a full pathname for the font files. */ - if(strlen(exe_path) >= sizeof(dev->fontpath)) { - free(dev); - return(NULL); + if (strlen(exe_path) >= sizeof(dev->fontpath)) { + free(dev); + return (NULL); } strcpy(dev->fontpath, exe_path); - plat_path_slash(dev->fontpath); + path_slash(dev->fontpath); strcat(dev->fontpath, "roms/printer/fonts/"); /* Create the full path for the page images. */ - plat_append_filename(dev->pagepath, usr_path, "printer"); - if (! plat_dir_check(dev->pagepath)) + path_append_filename(dev->pagepath, usr_path, "printer"); + if (!plat_dir_check(dev->pagepath)) plat_dir_create(dev->pagepath); - plat_path_slash(dev->pagepath); + path_slash(dev->pagepath); - dev->page_width = PAGE_WIDTH; + dev->page_width = PAGE_WIDTH; dev->page_height = PAGE_HEIGHT; - dev->dpi = PAGE_DPI; + dev->dpi = PAGE_DPI; /* Create 8-bit grayscale buffer for the page. */ - dev->page = (psurface_t *)malloc(sizeof(psurface_t)); - dev->page->w = (int)(dev->dpi * dev->page_width); - dev->page->h = (int)(dev->dpi * dev->page_height); - dev->page->pitch = dev->page->w; - dev->page->pixels = (uint8_t *)malloc(dev->page->pitch * dev->page->h); - memset(dev->page->pixels, 0x00, dev->page->pitch * dev->page->h); + dev->page = (psurface_t *) malloc(sizeof(psurface_t)); + dev->page->w = (int) (dev->dpi * dev->page_width); + dev->page->h = (int) (dev->dpi * dev->page_height); + dev->page->pitch = dev->page->w; + dev->page->pixels = (uint8_t *) malloc((size_t) dev->page->pitch * dev->page->h); + memset(dev->page->pixels, 0x00, (size_t) dev->page->pitch * dev->page->h); - /* Initialize parameters. */ - for (i = 0; i < 32; i++) { - dev->palcol[i].r = 255; - dev->palcol[i].g = 255; - dev->palcol[i].b = 255; + /* Initialize parameters. */ + for (uint8_t i = 0; i < 32; i++) { + dev->palcol[i].r = 255; + dev->palcol[i].g = 255; + dev->palcol[i].b = 255; } /* 0 = all white needed for logic 000 */ - fill_palette( 0, 0, 0, 1, dev); + fill_palette(0, 0, 0, 1, dev); /* 1 = magenta* 001 */ - fill_palette( 0, 255, 0, 1, dev); + fill_palette(0, 255, 0, 1, dev); /* 2 = cyan* 010 */ - fill_palette(255, 0, 0, 2, dev); + fill_palette(255, 0, 0, 2, dev); /* 3 = "violet" 011 */ - fill_palette(255, 255, 0, 3, dev); + fill_palette(255, 255, 0, 3, dev); /* 4 = yellow* 100 */ - fill_palette( 0, 0, 255, 4, dev); + fill_palette(0, 0, 255, 4, dev); /* 5 = red 101 */ - fill_palette( 0, 255, 255, 5, dev); + fill_palette(0, 255, 255, 5, dev); /* 6 = green 110 */ - fill_palette(255, 0, 255, 6, dev); + fill_palette(255, 0, 255, 6, dev); /* 7 = black 111 */ fill_palette(255, 255, 255, 7, dev); - dev->color = COLOR_BLACK; + dev->color = COLOR_BLACK; dev->fontface = 0; dev->autofeed = 0; reset_printer(dev); escp_log("ESC/P: created a virtual page of dimensions %d x %d pixels.\n", - dev->page->w, dev->page->h); + dev->page->w, dev->page->h); timer_add(&dev->pulse_timer, pulse_timer, dev, 0); timer_add(&dev->timeout_timer, timeout_timer, dev, 0); - return(dev); + return dev; } - static void escp_close(void *priv) { - escp_t *dev = (escp_t *)priv; + escp_t *dev = (escp_t *) priv; - if (dev == NULL) return; + if (dev == NULL) + return; if (dev->page != NULL) { - /* Print last page if it contains data. */ - if (dev->page->dirty) - dump_page(dev); + /* Print last page if it contains data. */ + if (dev->page->dirty) + dump_page(dev); - if (dev->page->pixels != NULL) - free(dev->page->pixels); - free(dev->page); + if (dev->page->pixels != NULL) + free(dev->page->pixels); + free(dev->page); } free(dev); } - const lpt_device_t lpt_prt_escp_device = { - "Generic ESC/P Dot-Matrix", - escp_init, - escp_close, - write_data, - write_ctrl, - read_data, - read_status, - read_ctrl + .name = "Generic ESC/P Dot-Matrix", + .internal_name = "dot_matrix", + .init = escp_init, + .close = escp_close, + .write_data = write_data, + .write_ctrl = write_ctrl, + .read_data = read_data, + .read_status = read_status, + .read_ctrl = read_ctrl }; diff --git a/src/printer/prt_ps.c b/src/printer/prt_ps.c index 73bd56b63..c0e3958b2 100644 --- a/src/printer/prt_ps.c +++ b/src/printer/prt_ps.c @@ -1,18 +1,18 @@ /* - * 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. + * 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. + * This file is part of the 86Box distribution. * - * Implementation of a generic PostScript printer. + * Implementation of a generic PostScript printer. * * * - * Authors: David HrdliÄka, + * Authors: David HrdliÄka, * - * Copyright 2019 David HrdliÄka. + * Copyright 2019 David HrdliÄka. */ #include @@ -27,130 +27,129 @@ #include <86box/lpt.h> #include <86box/timer.h> #include <86box/pit.h> +#include <86box/path.h> #include <86box/plat.h> #include <86box/plat_dynld.h> #include <86box/ui.h> #include <86box/prt_devs.h> - #ifdef _WIN32 -# define GSDLLAPI __stdcall +# define GSDLLAPI __stdcall #else -# define GSDLLAPI +# define GSDLLAPI #endif - -#define GS_ARG_ENCODING_UTF8 1 -#define gs_error_Quit -101 +#define GS_ARG_ENCODING_UTF8 1 +#define gs_error_Quit -101 #ifdef _WIN32 -#if (!(defined __amd64__ || defined _M_X64 || defined __aarch64__ || defined _M_ARM64)) -# define PATH_GHOSTSCRIPT_DLL "gsdll32.dll" -#else -# define PATH_GHOSTSCRIPT_DLL "gsdll64.dll" -#endif +# if (!(defined __amd64__ || defined _M_X64 || defined __aarch64__ || defined _M_ARM64)) +# define PATH_GHOSTSCRIPT_DLL "gsdll32.dll" +# else +# define PATH_GHOSTSCRIPT_DLL "gsdll64.dll" +# endif #elif defined __APPLE__ -#define PATH_GHOSTSCRIPT_DLL "libgs.dylib" +# 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 +#define POSTSCRIPT_BUFFER_LENGTH 65536 +typedef struct ps_t { + const char *name; -typedef struct -{ - const char *name; + void *lpt; - void *lpt; + pc_timer_t pulse_timer; + pc_timer_t timeout_timer; - pc_timer_t pulse_timer; - pc_timer_t timeout_timer; + char data; + bool ack; + bool select; + bool busy; + bool int_pending; + bool error; + bool autofeed; + uint8_t ctrl; - char data; - bool ack; - bool select; - bool busy; - bool int_pending; - bool error; - bool autofeed; - uint8_t ctrl; + char printer_path[260]; - char printer_path[260]; + char filename[260]; - char filename[260]; - - char buffer[POSTSCRIPT_BUFFER_LENGTH]; - size_t buffer_pos; + char buffer[POSTSCRIPT_BUFFER_LENGTH]; + size_t buffer_pos; } ps_t; typedef struct gsapi_revision_s { const char *product; const char *copyright; - long revision; - long revisiondate; + long revision; + long revisiondate; } gsapi_revision_t; - -static int (GSDLLAPI *gsapi_revision)(gsapi_revision_t *pr, int len); -static int (GSDLLAPI *gsapi_new_instance)(void **pinstance, void *caller_handle); -static void (GSDLLAPI *gsapi_delete_instance)(void *instance); -static int (GSDLLAPI *gsapi_set_arg_encoding)(void *instance, int encoding); -static int (GSDLLAPI *gsapi_init_with_args)(void *instance, int argc, char **argv); -static int (GSDLLAPI *gsapi_exit)(void *instance); +static int(GSDLLAPI *gsapi_revision)(gsapi_revision_t *pr, int len); +static int(GSDLLAPI *gsapi_new_instance)(void **pinstance, void *caller_handle); +static void(GSDLLAPI *gsapi_delete_instance)(void *instance); +static int(GSDLLAPI *gsapi_set_arg_encoding)(void *instance, int encoding); +static int(GSDLLAPI *gsapi_init_with_args)(void *instance, int argc, char **argv); +static int(GSDLLAPI *gsapi_exit)(void *instance); static dllimp_t ghostscript_imports[] = { - { "gsapi_revision", &gsapi_revision }, - { "gsapi_new_instance", &gsapi_new_instance }, - { "gsapi_delete_instance", &gsapi_delete_instance }, - { "gsapi_set_arg_encoding", &gsapi_set_arg_encoding }, - { "gsapi_init_with_args", &gsapi_init_with_args }, - { "gsapi_exit", &gsapi_exit }, - { NULL, NULL } + // clang-format off + { "gsapi_revision", &gsapi_revision }, + { "gsapi_new_instance", &gsapi_new_instance }, + { "gsapi_delete_instance", &gsapi_delete_instance }, + { "gsapi_set_arg_encoding", &gsapi_set_arg_encoding }, + { "gsapi_init_with_args", &gsapi_init_with_args }, + { "gsapi_exit", &gsapi_exit }, + { NULL, NULL } + // clang-format on }; -static void *ghostscript_handle = NULL; - +static void *ghostscript_handle = NULL; static void reset_ps(ps_t *dev) { if (dev == NULL) - return; + return; dev->ack = false; - dev->buffer[0] = 0; + dev->buffer[0] = 0; dev->buffer_pos = 0; timer_disable(&dev->pulse_timer); timer_disable(&dev->timeout_timer); } - static void pulse_timer(void *priv) { ps_t *dev = (ps_t *) priv; if (dev->ack) { - dev->ack = 0; - lpt_irq(dev->lpt, 1); + dev->ack = 0; + lpt_irq(dev->lpt, 1); } timer_disable(&dev->pulse_timer); } - static int convert_to_pdf(ps_t *dev) { volatile int code; - void *instance = NULL; - char input_fn[1024], output_fn[1024], *gsargv[9]; + void *instance = NULL; + char input_fn[1024]; + char output_fn[1024]; + char *gsargv[9]; strcpy(input_fn, dev->printer_path); - plat_path_slash(input_fn); + path_slash(input_fn); strcat(input_fn, dev->filename); strcpy(output_fn, input_fn); @@ -168,48 +167,47 @@ convert_to_pdf(ps_t *dev) code = gsapi_new_instance(&instance, dev); if (code < 0) - return code; + return code; code = gsapi_set_arg_encoding(instance, GS_ARG_ENCODING_UTF8); if (code == 0) - code = gsapi_init_with_args(instance, 9, gsargv); + code = gsapi_init_with_args(instance, 9, gsargv); if (code == 0 || code == gs_error_Quit) - code = gsapi_exit(instance); + code = gsapi_exit(instance); else - gsapi_exit(instance); + gsapi_exit(instance); gsapi_delete_instance(instance); if (code == 0) - plat_remove(input_fn); + plat_remove(input_fn); else - plat_remove(output_fn); + plat_remove(output_fn); return code; } - static void write_buffer(ps_t *dev, bool finish) { - char path[1024]; + char path[1024]; FILE *fp; if (dev->buffer[0] == 0) - return; + return; if (dev->filename[0] == 0) - plat_tempfile(dev->filename, NULL, ".ps"); + plat_tempfile(dev->filename, NULL, ".ps"); strcpy(path, dev->printer_path); - plat_path_slash(path); + path_slash(path); strcat(path, dev->filename); fp = plat_fopen(path, "a"); if (fp == NULL) - return; + return; fseek(fp, 0, SEEK_END); @@ -217,18 +215,17 @@ write_buffer(ps_t *dev, bool finish) fclose(fp); - dev->buffer[0] = 0; + dev->buffer[0] = 0; dev->buffer_pos = 0; if (finish) { - if (ghostscript_handle != NULL) - convert_to_pdf(dev); + if (ghostscript_handle != NULL) + convert_to_pdf(dev); - dev->filename[0] = 0; + dev->filename[0] = 0; } } - static void timeout_timer(void *priv) { @@ -239,171 +236,174 @@ timeout_timer(void *priv) timer_disable(&dev->timeout_timer); } - static void -ps_write_data(uint8_t val, void *p) +ps_write_data(uint8_t val, void *priv) { - ps_t *dev = (ps_t *) p; + ps_t *dev = (ps_t *) priv; if (dev == NULL) - return; + return; dev->data = (char) val; } - static void process_data(ps_t *dev) { /* Check for non-printable characters */ if ((dev->data < 0x20) || (dev->data == 0x7f)) { - switch (dev->data) { - /* The following characters are considered white-space - by the PostScript specification */ - case '\t': - case '\n': - case '\f': - case '\r': - break; + switch (dev->data) { + /* The following characters are considered white-space + by the PostScript specification */ + case '\t': + case '\n': + case '\f': + case '\r': + break; - /* Same with NUL, except we better change it to a space first */ - case '\0': - dev->data = ' '; - break; + /* Same with NUL, except we better change it to a space first */ + case '\0': + dev->data = ' '; + break; - /* Ctrl+D (0x04) marks the end of the document */ - case '\4': - write_buffer(dev, true); - return; + /* Ctrl+D (0x04) marks the end of the document */ + case '\4': + write_buffer(dev, true); + return; - /* Don't bother with the others */ - default: - return; - } + /* Don't bother with the others */ + default: + return; + } } /* Flush the buffer if we have run to its end */ if (dev->buffer_pos == POSTSCRIPT_BUFFER_LENGTH - 1) - write_buffer(dev, false); + write_buffer(dev, false); dev->buffer[dev->buffer_pos++] = dev->data; - dev->buffer[dev->buffer_pos] = 0; + dev->buffer[dev->buffer_pos] = 0; } - static void -ps_write_ctrl(uint8_t val, void *p) +ps_write_ctrl(uint8_t val, void *priv) { - ps_t *dev = (ps_t *) p; + ps_t *dev = (ps_t *) priv; if (dev == NULL) - return; + return; dev->autofeed = val & 0x02 ? true : false; if (val & 0x08) - dev->select = true; + dev->select = true; if ((val & 0x04) && !(dev->ctrl & 0x04)) { - /* Reset printer */ - dev->select = false; + /* Reset printer */ + dev->select = false; - reset_ps(dev); + reset_ps(dev); } if (!(val & 0x01) && (dev->ctrl & 0x01)) { - process_data(dev); + process_data(dev); - dev->ack = true; + dev->ack = true; - timer_set_delay_u64(&dev->pulse_timer, ISACONST); - timer_set_delay_u64(&dev->timeout_timer, 5000000 * TIMER_USEC); + timer_set_delay_u64(&dev->pulse_timer, ISACONST); + timer_set_delay_u64(&dev->timeout_timer, 5000000 * TIMER_USEC); } dev->ctrl = val; } - static uint8_t -ps_read_status(void *p) +ps_read_status(void *priv) { - ps_t *dev = (ps_t *) p; - uint8_t ret = 0x9f; + const ps_t *dev = (ps_t *) priv; + uint8_t ret = 0x9f; if (!dev->ack) - ret |= 0x40; + ret |= 0x40; - return(ret); + return ret; } - static void * ps_init(void *lpt) { - ps_t *dev; + ps_t *dev; gsapi_revision_t rev; dev = (ps_t *) malloc(sizeof(ps_t)); memset(dev, 0x00, sizeof(ps_t)); dev->ctrl = 0x04; - dev->lpt = lpt; + dev->lpt = lpt; /* Try loading the DLL. */ ghostscript_handle = dynld_module(PATH_GHOSTSCRIPT_DLL, ghostscript_imports); - if (ghostscript_handle == NULL) - ui_msgbox_header(MBX_ERROR, (wchar_t *) IDS_2114, (wchar_t *) IDS_2132); - else { - if (gsapi_revision(&rev, sizeof(rev)) == 0) - pclog("Loaded %s, rev %ld (%ld)\n", rev.product, rev.revision, rev.revisiondate); - else { - dynld_close(ghostscript_handle); - 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) { + pclog("Loaded %s, rev %ld (%ld)\n", rev.product, rev.revision, rev.revisiondate); + } else { + dynld_close(ghostscript_handle); + ghostscript_handle = NULL; + } } /* Cache print folder path. */ memset(dev->printer_path, 0x00, sizeof(dev->printer_path)); - plat_append_filename(dev->printer_path, usr_path, "printer"); + path_append_filename(dev->printer_path, usr_path, "printer"); if (!plat_dir_check(dev->printer_path)) - plat_dir_create(dev->printer_path); - plat_path_slash(dev->printer_path); + plat_dir_create(dev->printer_path); + path_slash(dev->printer_path); timer_add(&dev->pulse_timer, pulse_timer, dev, 0); timer_add(&dev->timeout_timer, timeout_timer, dev, 0); reset_ps(dev); - return(dev); + return dev; } - static void -ps_close(void *p) +ps_close(void *priv) { - ps_t *dev = (ps_t *) p; + ps_t *dev = (ps_t *) priv; if (dev == NULL) - return; + return; if (dev->buffer[0] != 0) - write_buffer(dev, true); + write_buffer(dev, true); if (ghostscript_handle != NULL) { - dynld_close(ghostscript_handle); - ghostscript_handle = NULL; + dynld_close(ghostscript_handle); + ghostscript_handle = NULL; } free(dev); } - const lpt_device_t lpt_prt_ps_device = { - .name = "Generic PostScript Printer", - .init = ps_init, - .close = ps_close, - .write_data = ps_write_data, - .write_ctrl = ps_write_ctrl, - .read_data = NULL, - .read_status = ps_read_status, - .read_ctrl = NULL + .name = "Generic PostScript Printer", + .internal_name = "postscript", + .init = ps_init, + .close = ps_close, + .write_data = ps_write_data, + .write_ctrl = ps_write_ctrl, + .read_data = NULL, + .read_status = ps_read_status, + .read_ctrl = NULL }; diff --git a/src/printer/prt_text.c b/src/printer/prt_text.c index b0f0b5daa..ddf9faf53 100644 --- a/src/printer/prt_text.c +++ b/src/printer/prt_text.c @@ -1,43 +1,41 @@ /* - * VARCem Virtual ARchaeological Computer EMulator. - * An emulator of (mostly) x86-based PC systems and devices, - * using the ISA,EISA,VLB,MCA and PCI system buses, roughly - * spanning the era between 1981 and 1995. + * VARCem Virtual ARchaeological Computer EMulator. + * An emulator of (mostly) x86-based PC systems and devices, + * using the ISA,EISA,VLB,MCA and PCI system buses, roughly + * spanning the era between 1981 and 1995. * - * This file is part of the VARCem Project. + * Implementation of a generic text printer. * - * Implementation of a generic text printer. - * - * Simple old text printers were unable to do any formatting - * of the text. They were just sheets of paper with a fixed - * size (in the U.S., this would be Letter, 8.5"x11") with a - * set of fixed margings to allow for proper operation of the - * printer mechanics. This would lead to a page being 66 lines - * of 80 characters each. + * Simple old text printers were unable to do any formatting + * of the text. They were just sheets of paper with a fixed + * size (in the U.S., this would be Letter, 8.5"x11") with a + * set of fixed margings to allow for proper operation of the + * printer mechanics. This would lead to a page being 66 lines + * of 80 characters each. * * * - * Author: Fred N. van Kempen, + * Authors: Fred N. van Kempen, * - * Copyright 2018,2019 Fred N. van Kempen. + * Copyright 2018-2019 Fred N. van Kempen. * - * Redistribution and use in source and binary forms, with - * or without modification, are permitted provided that the - * following conditions are met: + * Redistribution and use in source and binary forms, with + * or without modification, are permitted provided that the + * following conditions are met: * - * 1. Redistributions of source code must retain the entire - * above notice, this list of conditions and the following - * disclaimer. + * 1. Redistributions of source code must retain the entire + * above notice, this list of conditions and the following + * disclaimer. * - * 2. Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the - * following disclaimer in the documentation and/or other - * materials provided with the distribution. + * 2. Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the + * following disclaimer in the documentation and/or other + * materials provided with the distribution. * - * 3. Neither the name of the copyright holder nor the names - * of its contributors may be used to endorse or promote - * products derived from this software without specific - * prior written permission. + * 3. Neither the name of the copyright holder nor the names + * of its contributors may be used to endorse or promote + * products derived from this software without specific + * prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT @@ -60,194 +58,185 @@ #include <86box/device.h> #include <86box/timer.h> #include <86box/pit.h> -#include <86box/plat.h> +#include <86box/path.h> +#include <86box/plat.h> #include <86box/lpt.h> #include <86box/printer.h> #include <86box/prt_devs.h> - -#define FULL_PAGE 1 /* set if no top/bot margins */ - +#define FULL_PAGE 1 /* set if no top/bot margins */ /* Default page values (for now.) */ -#define PAGE_WIDTH 8.5 /* standard U.S. Letter */ -#define PAGE_HEIGHT 11 -#define PAGE_LMARGIN 0.25 /* 0.25" left and right */ -#define PAGE_RMARGIN 0.25 +#define PAGE_WIDTH 8.5 /* standard U.S. Letter */ +#define PAGE_HEIGHT 11 +#define PAGE_LMARGIN 0.25 /* 0.25" left and right */ +#define PAGE_RMARGIN 0.25 #if FULL_PAGE -# define PAGE_TMARGIN 0 -# define PAGE_BMARGIN 0 +# define PAGE_TMARGIN 0 +# define PAGE_BMARGIN 0 #else -# define PAGE_TMARGIN 0.25 -# define PAGE_BMARGIN 0.25 +# define PAGE_TMARGIN 0.25 +# define PAGE_BMARGIN 0.25 #endif -#define PAGE_CPI 10.0 /* standard 10 cpi */ -#define PAGE_LPI 6.0 /* standard 6 lpi */ +#define PAGE_CPI 10.0 /* standard 10 cpi */ +#define PAGE_LPI 6.0 /* standard 6 lpi */ +typedef struct psurface_t { + int8_t dirty; /* has the page been printed on? */ + char pad; -typedef struct { - int8_t dirty; /* has the page been printed on? */ - char pad; + uint8_t w; /* size //INFO */ + uint8_t h; - uint8_t w; /* size //INFO */ - uint8_t h; - - char *chars; /* character data */ + char *chars; /* character data */ } psurface_t; - -typedef struct { +typedef struct prnt_t { const char *name; - void * lpt; + void *lpt; /* Output file name. */ - char filename[1024]; + char filename[1024]; /* Printer timeout. */ - pc_timer_t pulse_timer; - pc_timer_t timeout_timer; + pc_timer_t pulse_timer; + pc_timer_t timeout_timer; /* page data (TODO: make configurable) */ - double page_width, /* all in inches */ - page_height, - left_margin, - top_margin, - right_margin, - bot_margin; + double page_width; /* all in inches */ + double page_height; + double left_margin; + double top_margin; + double right_margin; + double bot_margin; /* internal page data */ - psurface_t *page; - uint8_t max_chars, - max_lines; - uint8_t curr_x, /* print head position (chars) */ - curr_y; + psurface_t *page; + uint8_t max_chars; + uint8_t max_lines; + uint8_t curr_x; /* print head position (x, chars) */ + uint8_t curr_y; /* print head position (y, chars) */ /* font data */ - double cpi, /* defined chars per inch */ - lpi; /* defined lines per inch */ + double cpi; /* defined chars per inch */ + double lpi; /* defined lines per inch */ /* handshake data */ - uint8_t data; - int8_t ack; - int8_t select; - int8_t busy; - int8_t int_pending; - int8_t error; - int8_t autofeed; - uint8_t ctrl; + uint8_t data; + int8_t ack; + int8_t select; + int8_t busy; + int8_t int_pending; + int8_t error; + int8_t autofeed; + uint8_t ctrl; } prnt_t; - /* Dump the current page into a formatted file. */ -static void +static void dump_page(prnt_t *dev) { - char path[1024]; - uint16_t x, y; - uint8_t ch; - FILE *fp; + char path[1024]; + uint8_t ch; + FILE *fp; /* Create the full path for this file. */ memset(path, 0x00, sizeof(path)); - plat_append_filename(path, usr_path, "printer"); - if (! plat_dir_check(path)) + path_append_filename(path, usr_path, "printer"); + if (!plat_dir_check(path)) plat_dir_create(path); - plat_path_slash(path); + path_slash(path); strcat(path, dev->filename); /* Create the file. */ fp = plat_fopen(path, "a"); if (fp == NULL) { - //ERRLOG("PRNT: unable to create print page '%s'\n", path); - return; + // ERRLOG("PRNT: unable to create print page '%s'\n", path); + return; } fseek(fp, 0, SEEK_END); /* If this is not a new file, add a formfeed first. */ if (ftell(fp) != 0) - fputc('\014', fp); + fputc('\014', fp); - for (y = 0; y < dev->curr_y; y++) { - for (x = 0; x < dev->page->w; x++) { - ch = dev->page->chars[(y * dev->page->w) + x]; - if (ch == 0x00) { - /* End of line marker. */ - fputc('\n', fp); - break; - } else { - fputc(ch, fp); - } - } + for (uint16_t y = 0; y < dev->curr_y; y++) { + for (uint16_t x = 0; x < dev->page->w; x++) { + ch = dev->page->chars[(y * dev->page->w) + x]; + if (ch == 0x00) { + /* End of line marker. */ + fputc('\n', fp); + break; + } else { + fputc(ch, fp); + } + } } /* All done, close the file. */ fclose(fp); } - static void new_page(prnt_t *dev) { /* Dump the current page if needed. */ if (dev->page->dirty) - dump_page(dev); + dump_page(dev); /* Clear page. */ memset(dev->page->chars, 0x00, dev->page->h * dev->page->w); - dev->curr_y = 0; + dev->curr_y = 0; dev->page->dirty = 0; } - static void pulse_timer(void *priv) { prnt_t *dev = (prnt_t *) priv; if (dev->ack) { - dev->ack = 0; - lpt_irq(dev->lpt, 1); + dev->ack = 0; + lpt_irq(dev->lpt, 1); } timer_disable(&dev->pulse_timer); } - static void timeout_timer(void *priv) { prnt_t *dev = (prnt_t *) priv; if (dev->page->dirty) - new_page(dev); + new_page(dev); timer_disable(&dev->timeout_timer); } - static void reset_printer(prnt_t *dev) { /* TODO: these three should be configurable */ - dev->page_width = PAGE_WIDTH; - dev->page_height = PAGE_HEIGHT; - dev->left_margin = PAGE_LMARGIN; + dev->page_width = PAGE_WIDTH; + dev->page_height = PAGE_HEIGHT; + dev->left_margin = PAGE_LMARGIN; dev->right_margin = PAGE_RMARGIN; - dev->top_margin = PAGE_TMARGIN; - dev->bot_margin = PAGE_BMARGIN; - dev->cpi = PAGE_CPI; - dev->lpi = PAGE_LPI; - dev->ack = 0; + dev->top_margin = PAGE_TMARGIN; + dev->bot_margin = PAGE_BMARGIN; + dev->cpi = PAGE_CPI; + dev->lpi = PAGE_LPI; + dev->ack = 0; /* Default page layout. */ dev->max_chars = (int) ((dev->page_width - dev->left_margin - dev->right_margin) * dev->cpi); - dev->max_lines = (int) ((dev->page_height -dev->top_margin - dev->bot_margin) * dev->lpi); + dev->max_lines = (int) ((dev->page_height - dev->top_margin - dev->bot_margin) * dev->lpi); dev->curr_x = dev->curr_y = 0; if (dev->page != NULL) - dev->page->dirty = 0; + dev->page->dirty = 0; /* Create a file for this page. */ plat_tempfile(dev->filename, NULL, ".txt"); @@ -256,239 +245,235 @@ reset_printer(prnt_t *dev) timer_disable(&dev->timeout_timer); } - static int process_char(prnt_t *dev, uint8_t ch) { uint8_t i; switch (ch) { - case 0x07: /* Beeper (BEL) */ - /* TODO: beep? */ - return 1; + case 0x07: /* Beeper (BEL) */ + /* TODO: beep? */ + return 1; - case 0x08: /* Backspace (BS) */ - if (dev->curr_x > 0) - dev->curr_x--; - return 1; + case 0x08: /* Backspace (BS) */ + if (dev->curr_x > 0) + dev->curr_x--; + return 1; - case 0x09: /* Tab horizontally (HT) */ - /* Find tab right to current pos. */ - i = dev->curr_x; - dev->page->chars[(dev->curr_y * dev->page->w) + i++] = ' '; - while ((i < dev->max_chars) && ((i % 8) != 0)) { - dev->page->chars[(dev->curr_y * dev->page->w) + i] = ' '; - i++; - } - dev->curr_x = i; - return 1; + case 0x09: /* Tab horizontally (HT) */ + /* Find tab right to current pos. */ + i = dev->curr_x; + dev->page->chars[(dev->curr_y * dev->page->w) + i++] = ' '; + while ((i < dev->max_chars) && ((i % 8) != 0)) { + dev->page->chars[(dev->curr_y * dev->page->w) + i] = ' '; + i++; + } + dev->curr_x = i; + return 1; - case 0x0b: /* Tab vertically (VT) */ - dev->curr_x = 0; - return 1; + case 0x0b: /* Tab vertically (VT) */ + dev->curr_x = 0; + return 1; - case 0x0c: /* Form feed (FF) */ - new_page(dev); - return 1; + case 0x0c: /* Form feed (FF) */ + new_page(dev); + return 1; - case 0x0d: /* Carriage Return (CR) */ - dev->curr_x = 0; - if (! dev->autofeed) - return 1; - /*FALLTHROUGH*/ + case 0x0d: /* Carriage Return (CR) */ + dev->curr_x = 0; + if (!dev->autofeed) + return 1; + fallthrough; - case 0x0a: /* Line feed */ - dev->curr_x = 0; - if (++dev->curr_y >= dev->max_lines) - new_page(dev); - return 1; + case 0x0a: /* Line feed */ + dev->curr_x = 0; + if (++dev->curr_y >= dev->max_lines) + new_page(dev); + return 1; - case 0x0e: /* select wide printing (SO) */ - /* Ignore. */ - return 1; + case 0x0e: /* select wide printing (SO) */ + /* Ignore. */ + return 1; - case 0x0f: /* select condensed printing (SI) */ - /* Ignore. */ - return 1; + case 0x0f: /* select condensed printing (SI) */ + /* Ignore. */ + return 1; - case 0x11: /* select printer (DC1) */ - /* Ignore. */ - return 0; + case 0x11: /* select printer (DC1) */ + /* Ignore. */ + return 0; - case 0x12: /* cancel condensed printing (DC2) */ - /* Ignore. */ - return 1; + case 0x12: /* cancel condensed printing (DC2) */ + /* Ignore. */ + return 1; - case 0x13: /* deselect printer (DC3) */ - /* Ignore. */ - return 1; + case 0x13: /* deselect printer (DC3) */ + /* Ignore. */ + return 1; - case 0x14: /* cancel double-width printing (one line) (DC4) */ - /* Ignore. */ - return 1; + case 0x14: /* cancel double-width printing (one line) (DC4) */ + /* Ignore. */ + return 1; - case 0x18: /* cancel line (CAN) */ - /* Ignore. */ - return 1; + case 0x18: /* cancel line (CAN) */ + /* Ignore. */ + return 1; - case 0x1b: /* ESC */ - /* Ignore. */ - return 1; + case 0x1b: /* ESC */ + /* Ignore. */ + return 1; - default: - break; + default: + break; } /* Just a printable character. */ - return(0); + return 0; } - static void handle_char(prnt_t *dev) { uint8_t ch = dev->data; - if (dev->page == NULL) return; + if (dev->page == NULL) + return; if (process_char(dev, ch) == 1) { - /* Command was processed. */ - return; + /* Command was processed. */ + return; } /* Store character in the page buffer. */ dev->page->chars[(dev->curr_y * dev->page->w) + dev->curr_x] = ch; - dev->page->dirty = 1; + dev->page->dirty = 1; /* Update print head position. */ if (++dev->curr_x >= dev->max_chars) { - dev->curr_x = 0; - if (++dev->curr_y >= dev->max_lines) - new_page(dev); + dev->curr_x = 0; + if (++dev->curr_y >= dev->max_lines) + new_page(dev); } } - static void write_data(uint8_t val, void *priv) { - prnt_t *dev = (prnt_t *)priv; + prnt_t *dev = (prnt_t *) priv; - if (dev == NULL) return; + if (dev == NULL) + return; dev->data = val; } - static void write_ctrl(uint8_t val, void *priv) { - prnt_t *dev = (prnt_t *)priv; + prnt_t *dev = (prnt_t *) priv; - if (dev == NULL) return; + if (dev == NULL) + return; /* set autofeed value */ dev->autofeed = val & 0x02 ? 1 : 0; - if (val & 0x08) { /* SELECT */ - /* select printer */ - dev->select = 1; + if (val & 0x08) { /* SELECT */ + /* select printer */ + dev->select = 1; } if ((val & 0x04) && !(dev->ctrl & 0x04)) { - /* reset printer */ - dev->select = 0; + /* reset printer */ + dev->select = 0; - reset_printer(dev); + reset_printer(dev); } - if (!(val & 0x01) && (dev->ctrl & 0x01)) { /* STROBE */ - /* Process incoming character. */ - handle_char(dev); + if (!(val & 0x01) && (dev->ctrl & 0x01)) { /* STROBE */ + /* Process incoming character. */ + handle_char(dev); - /* ACK it, will be read on next READ STATUS. */ - dev->ack = 1; + /* ACK it, will be read on next READ STATUS. */ + dev->ack = 1; - timer_set_delay_u64(&dev->pulse_timer, ISACONST); - timer_set_delay_u64(&dev->timeout_timer, 5000000 * TIMER_USEC); + timer_set_delay_u64(&dev->pulse_timer, ISACONST); + timer_set_delay_u64(&dev->timeout_timer, 5000000 * TIMER_USEC); } dev->ctrl = val; } - static uint8_t read_status(void *priv) { - prnt_t *dev = (prnt_t *)priv; - uint8_t ret = 0x1f; + const prnt_t *dev = (prnt_t *) priv; + uint8_t ret = 0x1f; ret |= 0x80; if (!dev->ack) - ret |= 0x40; + ret |= 0x40; - return(ret); + return ret; } - static void * prnt_init(void *lpt) { prnt_t *dev; /* Initialize a device instance. */ - dev = (prnt_t *)malloc(sizeof(prnt_t)); + dev = (prnt_t *) malloc(sizeof(prnt_t)); memset(dev, 0x00, sizeof(prnt_t)); dev->ctrl = 0x04; - dev->lpt = lpt; + dev->lpt = lpt; /* Initialize parameters. */ reset_printer(dev); /* Create a page buffer. */ - dev->page = (psurface_t *)malloc(sizeof(psurface_t)); - dev->page->w = dev->max_chars; - dev->page->h = dev->max_lines; - dev->page->chars = (char *)malloc(dev->page->w * dev->page->h); + dev->page = (psurface_t *) malloc(sizeof(psurface_t)); + dev->page->w = dev->max_chars; + dev->page->h = dev->max_lines; + dev->page->chars = (char *) malloc(dev->page->w * dev->page->h); memset(dev->page->chars, 0x00, dev->page->w * dev->page->h); timer_add(&dev->pulse_timer, pulse_timer, dev, 0); timer_add(&dev->timeout_timer, timeout_timer, dev, 0); - return(dev); + return dev; } - static void prnt_close(void *priv) { - prnt_t *dev = (prnt_t *)priv; + prnt_t *dev = (prnt_t *) priv; if (dev == NULL) - return; + return; if (dev->page) { - /* print last page if it contains data */ - if (dev->page->dirty) - dump_page(dev); + /* print last page if it contains data */ + if (dev->page->dirty) + dump_page(dev); - if (dev->page->chars != NULL) - free(dev->page->chars); - free(dev->page); + if (dev->page->chars != NULL) + free(dev->page->chars); + free(dev->page); } free(dev); } - const lpt_device_t lpt_prt_text_device = { - "Generic Text Printer", - prnt_init, - prnt_close, - write_data, - write_ctrl, - NULL, - read_status, - NULL + .name = "Generic Text Printer", + .internal_name = "text_prt", + .init = prnt_init, + .close = prnt_close, + .write_data = write_data, + .write_ctrl = write_ctrl, + .read_data = NULL, + .read_status = read_status, + .read_ctrl = NULL }; diff --git a/src/qt/CMakeLists.txt b/src/qt/CMakeLists.txt index d48f17115..7ef93b4c0 100644 --- a/src/qt/CMakeLists.txt +++ b/src/qt/CMakeLists.txt @@ -1,3 +1,14 @@ +# +# 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. +# + # Find includes in corresponding build directories set(CMAKE_INCLUDE_CURRENT_DIR ON) set(CMAKE_AUTOMOC ON) @@ -19,9 +30,28 @@ if(QT_STATIC AND MINGW) set(CMAKE_PREFIX_PATH "$ENV{MSYSTEM_PREFIX}/qt${QT_MAJOR}-static") endif() +if(VCPKG_TOOLCHAIN AND VCPKG_USE_HOST_TOOLS) + set(QT_HOST_PATH "${VCPKG_INSTALLED_DIR}/${VCPKG_HOST_TRIPLET}/tools/Qt${QT_MAJOR}") + set(QT_HOST_PATH_CMAKE_DIR ${VCPKG_INSTALLED_DIR}/${VCPKG_HOST_TRIPLET}) + set(Qt${QT_MAJOR}LinguistTools_ROOT ${QT_HOST_PATH_CMAKE_DIR}) +endif() + +# CMake is a bitch and calls the Harfbuzz config twice on MinGW + Qt6 +# if config mode is preferred :) +set(CMAKE_FIND_PACKAGE_PREFER_CONFIG OFF) + find_package(Threads REQUIRED) -find_package(Qt${QT_MAJOR} COMPONENTS Core Widgets OpenGL REQUIRED) -find_package(Qt${QT_MAJOR}LinguistTools REQUIRED) +find_package(Qt${QT_MAJOR} COMPONENTS Core Widgets Network OpenGL REQUIRED) +find_package(Qt${QT_MAJOR}LinguistTools REQUIRED NO_CMAKE_FIND_ROOT_PATH) + +# TODO: Is this the correct way to do this, and is it required on any +# other platforms or with Qt 5? +if(APPLE AND USE_QT6) + find_package(Qt6Gui/Qt6QCocoaIntegrationPlugin REQUIRED) + find_package(Qt6Widgets/Qt6QMacStylePlugin REQUIRED) + find_package(Qt6Gui/Qt6QICOPlugin REQUIRED) + find_package(Qt6Gui/Qt6QICNSPlugin REQUIRED) +endif() add_library(plat STATIC qt.c @@ -49,6 +79,13 @@ add_library(ui STATIC qt_softwarerenderer.hpp qt_hardwarerenderer.cpp qt_hardwarerenderer.hpp + qt_openglrenderer.cpp + qt_openglrenderer.hpp + qt_opengloptions.cpp + qt_opengloptions.hpp + qt_opengloptionsdialog.cpp + qt_opengloptionsdialog.hpp + qt_opengloptionsdialog.ui qt_settings.cpp qt_settings.hpp @@ -127,15 +164,41 @@ add_library(ui STATIC qt_util.hpp qt_util.cpp + qt_unixmanagerfilter.cpp + qt_unixmanagerfilter.hpp + + qt_vulkanwindowrenderer.hpp + qt_vulkanwindowrenderer.cpp + + qt_vulkanrenderer.hpp + qt_vulkanrenderer.cpp + + qt_mcadevicelist.hpp + qt_mcadevicelist.cpp + qt_mcadevicelist.ui + + qt_mediahistorymanager.cpp + qt_mediahistorymanager.hpp + ../qt_resources.qrc ) +if(RTMIDI) + target_compile_definitions(ui PRIVATE USE_RTMIDI) +endif() if(WIN32) enable_language(RC) target_sources(86Box PUBLIC ../win/86Box-qt.rc) - target_sources(plat PRIVATE win_joystick_rawinput.c) - target_link_libraries(86Box hid) + target_sources(plat PRIVATE win_dynld.c) + if(DINPUT) + target_sources(plat PRIVATE win_joystick.cpp) + target_link_libraries(86Box dinput8) + else() + target_sources(plat PRIVATE win_joystick_rawinput.c) + endif() + target_sources(ui PRIVATE qt_d3d9renderer.hpp qt_d3d9renderer.cpp) + target_link_libraries(86Box hid d3d9) # CMake 3.22 messed this up for clang/clang++ # See https://gitlab.kitware.com/cmake/cmake/-/issues/22611 @@ -143,7 +206,7 @@ if(WIN32) # MSVC linker adds its own manifest to the executable, which fails if # we include ours in 86Box.rc. We therefore need to pass the manifest # directly as as a source file, so the linker can use that instead. - set_property(SOURCE ../win/86Box-qt.rc PROPERTY COMPILE_DEFINITIONS NO_INCLUDE_MANIFEST) + set_property(SOURCE ../win/86Box-qt.rc DIRECTORY .. PROPERTY COMPILE_DEFINITIONS NO_INCLUDE_MANIFEST) target_sources(86Box PRIVATE ../win/86Box.manifest) endif() @@ -158,8 +221,25 @@ if(WIN32 AND NOT MINGW) target_sources(plat PRIVATE ../win/win_opendir.c) endif() +if(WIN32) + target_sources(plat PRIVATE ../win/win_serial_passthrough.c) +else() + target_sources(plat PRIVATE ../unix/unix_serial_passthrough.c) +endif() + if (APPLE) target_sources(ui PRIVATE macos_event_filter.mm) + if(MOLTENVK) + find_path(MOLTENVK_INCLUDE "vulkan/vulkan.h" PATHS "/opt/homebrew/opt/molten-vk/libexec/include" "/usr/local/opt/molten-vk/libexec/include" ${MOLTENVK_INCLUDE_DIR}) + if (NOT MOLTENVK_INCLUDE) + message(FATAL_ERROR "Could not find vulkan/vulkan.h. If the headers are installed please use -DMOLTENVK_INCLUDE_DIR=/path/to/headers") + endif() + target_include_directories(ui PRIVATE ${MOLTENVK_INCLUDE}) + find_library(MOLTENVK_LIB MoltenVK) + if (NOT MOLTENVK_LIB) + message(FATAL_ERROR "Could not find MoltenVK library") + endif() + endif() endif() if (WIN32) @@ -176,6 +256,7 @@ target_link_libraries( PRIVATE Qt${QT_MAJOR}::Widgets Qt${QT_MAJOR}::Gui + Qt${QT_MAJOR}::Network Threads::Threads ) @@ -185,48 +266,85 @@ target_link_libraries( Qt${QT_MAJOR}::Widgets Qt${QT_MAJOR}::Gui Qt${QT_MAJOR}::OpenGL + Qt${QT_MAJOR}::Network Threads::Threads ) -# needed for static builds -if (WIN32) - qt_import_plugins(plat INCLUDE Qt${QT_MAJOR}::QWindowsIntegrationPlugin Qt${QT_MAJOR}::QICOPlugin QWindowsVistaStylePlugin) +if(WIN32) + if(STATIC_BUILD) + # needed for static builds + qt_import_plugins(plat INCLUDE Qt${QT_MAJOR}::QWindowsIntegrationPlugin Qt${QT_MAJOR}::QICOPlugin Qt${QT_MAJOR}::QWindowsVistaStylePlugin) + else() + if(USE_QT6) + install(CODE " + get_filename_component(CMAKE_INSTALL_PREFIX_ABSOLUTE \${CMAKE_INSTALL_PREFIX} ABSOLUTE) + execute_process( + COMMAND $ + \"\${CMAKE_INSTALL_PREFIX_ABSOLUTE}/$\") + ") + else() + find_program(WINDEPLOYQT_EXECUTABLE windeployqt) + if(WINDEPLOYQT_EXECUTABLE) + install(CODE " + get_filename_component(CMAKE_INSTALL_PREFIX_ABSOLUTE \${CMAKE_INSTALL_PREFIX} ABSOLUTE) + execute_process( + COMMAND ${WINDEPLOYQT_EXECUTABLE} + \"\${CMAKE_INSTALL_PREFIX_ABSOLUTE}/$\") + ") + endif() + endif() + endif() endif() # loads a macro to install Qt5 plugins on macOS # based on https://stackoverflow.com/questions/35612687/cmake-macos-x-bundle-with-bundleutiliies-for-qt-application -macro(install_qt5_plugin _qt_plugin_name _qt_plugins_var _prefix) +macro(install_qt5_plugin _qt_plugin_name _runtime_plugins_var _prefix) get_target_property(_qt_plugin_path "${_qt_plugin_name}" LOCATION) if(EXISTS "${_qt_plugin_path}") get_filename_component(_qt_plugin_file "${_qt_plugin_path}" NAME) get_filename_component(_qt_plugin_type "${_qt_plugin_path}" PATH) get_filename_component(_qt_plugin_type "${_qt_plugin_type}" NAME) set(_qt_plugin_dest "${_prefix}/PlugIns/${_qt_plugin_type}") - install(FILES "${_qt_plugin_path}" - DESTINATION "${_qt_plugin_dest}") - list(APPEND ${_qt_plugins_var} "${_qt_plugin_dest}/${_qt_plugin_file}") + install(FILES "${_qt_plugin_path}" DESTINATION "${_qt_plugin_dest}") + list(APPEND ${_runtime_plugins_var} "\${CMAKE_INSTALL_PREFIX_ABSOLUTE}/${_qt_plugin_dest}/${_qt_plugin_file}") else() message(FATAL_ERROR "QT plugin ${_qt_plugin_name} not found") endif() endmacro() +macro(install_bundle_library _library_path _installed_name _runtime_plugins_var _prefix) + if(EXISTS "${_library_path}") + file(REAL_PATH "${_library_path}" _lib_resolved) + if(EXISTS "${_lib_resolved}") + install(FILES "${_lib_resolved}" DESTINATION "${_prefix}" RENAME "${_installed_name}") + list(APPEND ${_runtime_plugins_var} "\${CMAKE_INSTALL_PREFIX_ABSOLUTE}/${_prefix}/${_installed_name}") + else() + message(WARNING "Library ${_installed_name} will not be bundled: The library was found but could not be resolved.") + endif() + else() + message(STATUS "Library ${_installed_name} was not found - skipping") + endif() +endmacro() + if (APPLE AND CMAKE_MACOSX_BUNDLE) set(prefix "86Box.app/Contents") set(INSTALL_RUNTIME_DIR "${prefix}/MacOS") set(INSTALL_CMAKE_DIR "${prefix}/Resources") + set(INSTALL_LIB_DIR "${prefix}/Frameworks") # using the install_qt5_plugin to add Qt plugins into the macOS app bundle - if (USE_QT6) - install_qt5_plugin("Qt6::QCocoaIntegrationPlugin" QT_PLUGINS ${prefix}) - else() - install_qt5_plugin("Qt5::QCocoaIntegrationPlugin" QT_PLUGINS ${prefix}) - install_qt5_plugin("Qt5::QMacStylePlugin" QT_PLUGINS ${prefix}) - install_qt5_plugin("Qt5::QICOPlugin" QT_PLUGINS ${prefix}) - install_qt5_plugin("Qt5::QICNSPlugin" QT_PLUGINS ${prefix}) - endif() - + install_qt5_plugin("Qt${QT_MAJOR}::QCocoaIntegrationPlugin" RUNTIME_PLUGINS ${prefix}) + install_qt5_plugin("Qt${QT_MAJOR}::QMacStylePlugin" RUNTIME_PLUGINS ${prefix}) + install_qt5_plugin("Qt${QT_MAJOR}::QICOPlugin" RUNTIME_PLUGINS ${prefix}) + install_qt5_plugin("Qt${QT_MAJOR}::QICNSPlugin" RUNTIME_PLUGINS ${prefix}) + + # Install libraries that are loaded at runtime and not linked + install_bundle_library("${GHOSTSCRIPT_LIB}" "libgs.dylib" RUNTIME_PLUGINS ${INSTALL_LIB_DIR}) + install_bundle_library("${VDE_LIB}" "libvdeplug.dylib" RUNTIME_PLUGINS ${INSTALL_LIB_DIR}) + install_bundle_library("${MOLTENVK_LIB}" "libVulkan.dylib" RUNTIME_PLUGINS ${INSTALL_LIB_DIR}) + file(WRITE "${CMAKE_CURRENT_BINARY_DIR}/qt.conf" - "[Paths]\nPlugins = ${_qt_plugin_dir}\n") + "[Paths]\nPlugins = PlugIns\n") install(FILES "${CMAKE_CURRENT_BINARY_DIR}/qt.conf" DESTINATION "${INSTALL_CMAKE_DIR}") @@ -237,25 +355,25 @@ if (APPLE AND CMAKE_MACOSX_BUNDLE) endforeach() endif() - # Append Qt's lib folder which is two levels above Qt5Widgets_DIR - list(APPEND DIRS "${Qt5Widgets_DIR}/../..") + # Append Qt's lib folder which is two levels above Qt*Widgets_DIR + list(APPEND DIRS "${Qt${QT_MAJOR}Widgets_DIR}/../..") include(InstallRequiredSystemLibraries) install(CODE " include(BundleUtilities) get_filename_component(CMAKE_INSTALL_PREFIX_ABSOLUTE \$ENV{DESTDIR}\${CMAKE_INSTALL_PREFIX} ABSOLUTE) - foreach(PLUGIN ${QT_PLUGINS}) - get_filename_component(PLUGIN_ABSOLUTE \${PLUGIN} ABSOLUTE BASE_DIR \${CMAKE_INSTALL_PREFIX_ABSOLUTE}) - list(APPEND QT_PLUGINS_ABSOLUTE \${PLUGIN_ABSOLUTE}) - endforeach() - fixup_bundle(\"\${CMAKE_INSTALL_PREFIX_ABSOLUTE}/86Box.app\" \"${QT_PLUGINS_ABSOLUTE}\" \"${DIRS}\")") + fixup_bundle(\"\${CMAKE_INSTALL_PREFIX_ABSOLUTE}/86Box.app\" \"${RUNTIME_PLUGINS}\" \"${DIRS}\") + execute_process( + COMMAND ${CMAKE_INSTALL_NAME_TOOL} -add_rpath \"@executable_path/../Frameworks/\" + \"\${CMAKE_INSTALL_PREFIX_ABSOLUTE}/${INSTALL_RUNTIME_DIR}/86Box\") + ") endif() -if (UNIX AND NOT APPLE) +if (UNIX AND NOT APPLE AND NOT HAIKU) find_package(X11 REQUIRED) target_link_libraries(ui PRIVATE X11::X11 X11::Xi) - target_sources(ui PRIVATE xinput2_mouse.cpp) + target_sources(ui PRIVATE evdev_keyboard.cpp xinput2_mouse.cpp) find_package(PkgConfig REQUIRED) pkg_check_modules(LIBEVDEV IMPORTED_TARGET libevdev) if (LIBEVDEV_FOUND) @@ -263,6 +381,22 @@ if (UNIX AND NOT APPLE) target_link_libraries(ui PUBLIC PkgConfig::LIBEVDEV) target_sources(ui PRIVATE evdev_mouse.cpp) endif() + pkg_check_modules(XKBCOMMON IMPORTED_TARGET xkbcommon) + if (XKBCOMMON_FOUND) + target_compile_definitions(ui PRIVATE XKBCOMMON) + target_link_libraries(ui PUBLIC PkgConfig::XKBCOMMON) + target_sources(ui PRIVATE xkbcommon_keyboard.cpp) + + if (X11_xcb_FOUND) + pkg_check_modules(XKBCOMMON_X11 IMPORTED_TARGET xkbcommon-x11) + if (XKBCOMMON_X11_FOUND) + target_compile_definitions(ui PRIVATE XKBCOMMON_X11) + target_link_libraries(ui PRIVATE X11::xcb PUBLIC PkgConfig::XKBCOMMON_X11) + target_sources(ui PRIVATE xkbcommon_x11_keyboard.cpp) + set(QT5_PRIVATE_HEADERS ON) + endif() + endif() + endif() find_package(ECM NO_MODULE) if (ECM_FOUND) @@ -277,21 +411,29 @@ if (UNIX AND NOT APPLE) ecm_add_wayland_client_protocol(WL_SOURCE_VAR PROTOCOL ${CMAKE_SOURCE_DIR}/wl_protocols/pointer-constraints-unstable-v1.xml BASENAME pointer-constraints-unstable-v1) target_include_directories(ui PRIVATE ${CMAKE_CURRENT_BINARY_DIR} ${Qt${QT_MAJOR}Gui_PRIVATE_INCLUDE_DIRS}) target_sources(ui PRIVATE ${WL_SOURCE_VAR} wl_mouse.cpp) + if (XKBCOMMON_FOUND) + target_sources(ui PRIVATE xkbcommon_wl_keyboard.cpp) + endif() target_compile_definitions(ui PRIVATE WAYLAND) + set(QT5_PRIVATE_HEADERS ON) endif() endif() endif() + + # Add private headers for Qt5 if required. + if (NOT USE_QT6 AND DEFINED QT5_PRIVATE_HEADERS) + find_package(Qt${QT_MAJOR}Gui) + if (Qt${QT_MAJOR}Gui_FOUND) + include_directories(${Qt${QT_MAJOR}Gui_PRIVATE_INCLUDE_DIRS}) + endif() + endif() endif() set(QM_FILES) file(GLOB po_files "${CMAKE_CURRENT_SOURCE_DIR}/languages/*.po") foreach(po_file ${po_files}) - get_target_property(LCONVERT_EXECUTABLE Qt${QT_MAJOR}::lconvert IMPORTED_LOCATION) - get_filename_component(_lconvert_bin_dir "${LCONVERT_EXECUTABLE}" DIRECTORY) - find_program(LCONVERT_EXECUTABLE lconvert HINTS "${_lconvert_bin_dir}") - get_filename_component(PO_FILE_NAME ${po_file} NAME_WE) add_custom_command(OUTPUT "${CMAKE_CURRENT_BINARY_DIR}/86box_${PO_FILE_NAME}.qm" - COMMAND ${LCONVERT_EXECUTABLE} -i ${po_file} -o ${CMAKE_CURRENT_BINARY_DIR}/86box_${PO_FILE_NAME}.qm + COMMAND "$" -i ${po_file} -o ${CMAKE_CURRENT_BINARY_DIR}/86box_${PO_FILE_NAME}.qm WORKING_DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}" DEPENDS "${po_file}") list(APPEND QM_FILES "${CMAKE_CURRENT_BINARY_DIR}/86box_${PO_FILE_NAME}.qm") diff --git a/src/qt/TODO b/src/qt/TODO deleted file mode 100644 index a8b0b4970..000000000 --- a/src/qt/TODO +++ /dev/null @@ -1 +0,0 @@ -* Joystick support diff --git a/src/qt/be_keyboard.hpp b/src/qt/be_keyboard.hpp new file mode 100644 index 000000000..cc2bbabac --- /dev/null +++ b/src/qt/be_keyboard.hpp @@ -0,0 +1,112 @@ +static std::unordered_map be_keycodes = { + {B_F1_KEY, 0x3b}, + {B_F2_KEY, 0x3c}, + {B_F3_KEY, 0x3d}, + {B_F4_KEY, 0x3e}, + {B_F5_KEY, 0x3f}, + {B_F6_KEY, 0x40}, + {B_F7_KEY, 0x41}, + {B_F8_KEY, 0x42}, + {B_F9_KEY, 0x43}, + {B_F10_KEY, 0x44}, + {B_F11_KEY, 0x57}, + {B_F12_KEY, 0x58}, + {B_PRINT_KEY, 0x137}, + {B_SCROLL_KEY, 0x46}, + {B_PAUSE_KEY, 0x145}, + {B_KATAKANA_HIRAGANA, 0x70}, + {B_HANKAKU_ZENKAKU, 0x76}, + + {0x01, 0x01}, /* Escape */ + {0x11, 0x29}, + {0x12, 0x02}, + {0x13, 0x03}, + {0x14, 0x04}, + {0x15, 0x05}, + {0x16, 0x06}, + {0x17, 0x07}, + {0x18, 0x08}, + {0x19, 0x09}, + {0x1a, 0x0a}, + {0x1b, 0x0b}, + {0x1c, 0x0c}, + {0x1d, 0x0d}, + {0x1e, 0x0e}, /* Backspace */ + {0x1f, 0x152}, /* Insert */ + {0x20, 0x147}, /* Home */ + {0x21, 0x149}, /* Page Up */ + {0x22, 0x45}, + {0x23, 0x135}, + {0x24, 0x37}, + {0x25, 0x4a}, + {0x26, 0x0f}, /* Tab */ + {0x27, 0x10}, + {0x28, 0x11}, + {0x29, 0x12}, + {0x2a, 0x13}, + {0x2b, 0x14}, + {0x2c, 0x15}, + {0x2d, 0x16}, + {0x2e, 0x17}, + {0x2f, 0x18}, + {0x30, 0x19}, + {0x31, 0x1a}, + {0x32, 0x1b}, + {0x33, 0x2b}, + {0x34, 0x153}, /* Delete */ + {0x35, 0x14f}, /* End */ + {0x36, 0x151}, /* Page Down */ + {0x37, 0x47}, + {0x38, 0x48}, + {0x39, 0x49}, + {0x3a, 0x4e}, + {0x3b, 0x3a}, + {0x3c, 0x1e}, + {0x3d, 0x1f}, + {0x3e, 0x20}, + {0x3f, 0x21}, + {0x40, 0x22}, + {0x41, 0x23}, + {0x42, 0x24}, + {0x43, 0x25}, + {0x44, 0x26}, + {0x45, 0x27}, + {0x46, 0x28}, + {0x47, 0x1c}, /* Enter */ + {0x48, 0x4b}, + {0x49, 0x4c}, + {0x4a, 0x4d}, + {0x4b, 0x2a}, + {0x4c, 0x2c}, + {0x4d, 0x2d}, + {0x4e, 0x2e}, + {0x4f, 0x2f}, + {0x50, 0x30}, + {0x51, 0x31}, + {0x52, 0x32}, + {0x53, 0x33}, + {0x54, 0x34}, + {0x55, 0x35}, + {0x56, 0x36}, + {0x57, 0x148}, /* up arrow */ + {0x58, 0x51}, + {0x59, 0x50}, + {0x5a, 0x4f}, + {0x5b, 0x11c}, + {0x5c, 0x1d}, + {0x5d, 0x38}, + {0x5e, 0x39}, /* space bar */ + {0x5f, 0x138}, + {0x60, 0x11d}, + {0x61, 0x14b}, /* left arrow */ + {0x62, 0x150}, /* down arrow */ + {0x63, 0x14d}, /* right arrow */ + {0x64, 0x52}, + {0x65, 0x53}, + {0x66, 0x15b}, + {0x67, 0x15c}, + {0x68, 0x15d}, + {0x69, 0x56}, + {0x7e, 0x137}, /* System Request */ + {0x7f, 0x145}, /* Break */ +}; diff --git a/src/qt/cocoa_keyboard.hpp b/src/qt/cocoa_keyboard.hpp new file mode 100644 index 000000000..da3161bb2 --- /dev/null +++ b/src/qt/cocoa_keyboard.hpp @@ -0,0 +1,135 @@ +static std::array cocoa_keycodes = { /* key names in parentheses are not declared by Apple headers */ + 0x1e, /* ANSI_A */ + 0x1f, /* ANSI_S */ + 0x20, /* ANSI_D */ + 0x21, /* ANSI_F */ + 0x23, /* ANSI_H */ + 0x22, /* ANSI_G */ + 0x2c, /* ANSI_Z */ + 0x2d, /* ANSI_X */ + 0x2e, /* ANSI_C */ + 0x2f, /* ANSI_V */ + 0x56, /* ISO_Section */ + 0x30, /* ANSI_B */ + 0x10, /* ANSI_Q */ + 0x11, /* ANSI_W */ + 0x12, /* ANSI_E */ + 0x13, /* ANSI_R */ + 0x15, /* ANSI_Y */ + 0x14, /* ANSI_T */ + 0x02, /* ANSI_1 */ + 0x03, /* ANSI_2 */ + 0x04, /* ANSI_3 */ + 0x05, /* ANSI_4 */ + 0x07, /* ANSI_6 */ + 0x06, /* ANSI_5 */ + 0x0d, /* ANSI_Equal */ + 0x0a, /* ANSI_9 */ + 0x08, /* ANSI_7 */ + 0x0c, /* ANSI_Minus */ + 0x09, /* ANSI_8 */ + 0x0b, /* ANSI_0 */ + 0x1b, /* ANSI_RightBracket */ + 0x18, /* ANSI_O */ + 0x16, /* ANSI_U */ + 0x1a, /* ANSI_LeftBracket */ + 0x17, /* ANSI_I */ + 0x19, /* ANSI_P */ + 0x1c, /* Return */ + 0x26, /* ANSI_L */ + 0x24, /* ANSI_J */ + 0x28, /* ANSI_Quote */ + 0x25, /* ANSI_K */ + 0x27, /* ANSI_Semicolon */ + 0x2b, /* ANSI_Backslash */ + 0x33, /* ANSI_Comma */ + 0x35, /* ANSI_Slash */ + 0x31, /* ANSI_N */ + 0x32, /* ANSI_M */ + 0x34, /* ANSI_Period */ + 0x0f, /* Tab */ + 0x39, /* Space */ + 0x29, /* ANSI_Grave */ + 0x0e, /* Delete => Backspace */ + 0x11c, /* (ANSI_KeypadEnter) */ + 0x01, /* Escape */ + 0x15c, /* (RightCommand) => Right Windows */ + 0x15b, /* (Left)Command => Left Windows */ + 0x2a, /* Shift */ + 0x3a, /* CapsLock */ + 0x38, /* Option */ + 0x1d, /* Control */ + 0x36, /* RightShift */ + 0x138, /* RightOption */ + 0x11d, /* RightControl */ + 0x15c, /* Function */ + 0x5e, /* F17 => F14 */ + 0x53, /* ANSI_KeypadDecimal */ + 0, + 0x37, /* ANSI_KeypadMultiply */ + 0, + 0x4e, /* ANSI_KeypadPlus */ + 0, + 0x45, /* ANSI_KeypadClear => Num Lock (location equivalent) */ + 0x130, /* VolumeUp */ + 0x12e, /* VolumeDown */ + 0x120, /* Mute */ + 0x135, /* ANSI_KeypadDivide */ + 0x11c, /* ANSI_KeypadEnter */ + 0, + 0x4a, /* ANSI_KeypadMinus */ + 0x5f, /* F18 => F15 */ + 0, /* F19 */ + 0x59, /* ANSI_KeypadEquals */ + 0x52, /* ANSI_Keypad0 */ + 0x4f, /* ANSI_Keypad1 */ + 0x50, /* ANSI_Keypad2 */ + 0x51, /* ANSI_Keypad3 */ + 0x4b, /* ANSI_Keypad4 */ + 0x4c, /* ANSI_Keypad5 */ + 0x4d, /* ANSI_Keypad6 */ + 0x47, /* ANSI_Keypad7 */ + 0, /* F20 */ + 0x48, /* ANSI_Keypad8 */ + 0x49, /* ANSI_Keypad9 */ + 0x7d, /* JIS_Yen */ + 0x73, /* JIS_Underscore */ + 0x5c, /* JIS_KeypadComma */ + 0x3f, /* F5 */ + 0x40, /* F6 */ + 0x41, /* F7 */ + 0x3d, /* F3 */ + 0x42, /* F8 */ + 0x43, /* F9 */ + 0x7b, /* JIS_Eisu => muhenkan (location equivalent) */ + 0x57, /* F11 */ + 0x79, /* JIS_Kana => henkan (location equivalent) */ + 0x137, /* F13 => SysRq (location equivalent) */ + 0x5d, /* F16 => F13 */ + 0x46, /* F14 => Scroll Lock (location equivalent) */ + 0, + 0x44, /* F10 */ + 0x15d, /* (Menu) */ + 0x58, /* F12 */ + 0, + 0x145, /* F15 => Pause (location equivalent) */ + 0x152, /* Help => Insert (location equivalent) */ + 0x147, /* Home */ + 0x149, /* PageUp */ + 0x153, /* ForwardDelete */ + 0x3e, /* F4 */ + 0x14f, /* End */ + 0x3c, /* F2 */ + 0x151, /* PageDown */ + 0x3b, /* F1 */ + 0x14b, /* LeftArrow */ + 0x14d, /* RightArrow */ + 0x150, /* DownArrow */ + 0x148, /* UpArrow */ +}; + +// https://developer.apple.com/documentation/appkit/nseventmodifierflags/ +qint32 NSEventModifierFlagCommand = 1 << 20; + +qint32 nvk_Delete = 0x75; +qint32 nvk_Insert = 0x72; \ No newline at end of file diff --git a/src/qt/cocoa_mouse.hpp b/src/qt/cocoa_mouse.hpp index 8db79d9e8..af78abad6 100644 --- a/src/qt/cocoa_mouse.hpp +++ b/src/qt/cocoa_mouse.hpp @@ -2,13 +2,12 @@ #include #if QT_VERSION_MAJOR >= 6 -#define result_t qintptr +# define result_t qintptr #else -#define result_t long +# define result_t long #endif -class CocoaEventFilter : public QAbstractNativeEventFilter -{ +class CocoaEventFilter : public QAbstractNativeEventFilter { public: CocoaEventFilter() {}; ~CocoaEventFilter(); diff --git a/src/qt/evdev_keyboard.cpp b/src/qt/evdev_keyboard.cpp new file mode 100644 index 000000000..9bc2ebdb2 --- /dev/null +++ b/src/qt/evdev_keyboard.cpp @@ -0,0 +1,163 @@ +/* + * 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. + * + * evdev keyboard input module. + * + * + * + * Authors: RichardG, + * + * Copyright 2023 RichardG. + */ +#include +#include + +static std::unordered_map evdev_keycodes = { + {184, 0x46}, /* F14 => Scroll Lock (for Apple keyboards) */ + {86, 0x56}, /* 102ND */ + {87, 0x57}, /* F11 */ + {88, 0x58}, /* F12 */ + {186, 0x5d}, /* F16 => F13 */ + {187, 0x5e}, /* F17 => F14 */ + {188, 0x5f}, /* F18 => F15 */ + + /* Japanese keys. */ + {95, 0x5c}, /* KPJPCOMMA */ + {93, 0x70}, /* KATAKANAHIRAGANA */ + {89, 0x73}, /* RO */ + {85, 0x76}, /* ZENKAKUHANKAKU */ + {91, 0x77}, /* HIRAGANA */ + {90, 0x78}, /* KATAKANA */ + {92, 0x79}, /* HENKAN */ + {94, 0x7b}, /* MUHENKAN */ + {124, 0x7d}, /* YEN */ + {121, 0x7e}, /* KPCOMMA */ + + /* Korean keys. */ + {123, 0xf1}, /* HANJA */ + {122, 0xf2}, /* HANGUL */ + + {96, 0x11c}, /* KPENTER */ + {97, 0x11d}, /* RIGHTCTRL */ + {98, 0x135}, /* KPSLASH */ + {99, 0x137}, /* SYSRQ */ + {183, 0x137}, /* F13 => SysRq (for Apple keyboards) */ + {100, 0x138}, /* RIGHTALT */ + {119, 0x145}, /* PAUSE */ + {411, 0x145}, /* BREAK */ + {185, 0x145}, /* F15 => Pause (for Apple keyboards) */ + {102, 0x147}, /* HOME */ + {103, 0x148}, /* UP */ + {104, 0x149}, /* PAGEUP */ + {105, 0x14b}, /* LEFT */ + {106, 0x14d}, /* RIGHT */ + {107, 0x14f}, /* END */ + {108, 0x150}, /* DOWN */ + {109, 0x151}, /* PAGEDOWN */ + {110, 0x152}, /* INSERT */ + {111, 0x153}, /* DELETE */ + + {125, 0x15b}, /* LEFTMETA */ + {126, 0x15c}, /* RIGHTMETA */ + {127, 0x15d}, /* COMPOSE => Menu */ + + /* Multimedia keys. Guideline is to try and follow the Microsoft standard, then + fill in remaining scancodes with OEM-specific keys for redundancy sake. Keys + marked with # are not translated into evdev codes by the standard atkbd driver. */ + {634, 0x54}, /* SELECTIVE_SCREENSHOT# => Alt+SysRq */ + {117, 0x59}, /* KPEQUAL */ + {418, 0x6a}, /* ZOOMIN# => Logitech */ + {420, 0x6b}, /* ZOOMRESET# => Logitech */ + {223, 0x6d}, /* CANCEL# => Logitech */ + {132, 0x101}, /* # Logitech Task Select */ + {148, 0x102}, /* PROG1# => Samsung */ + {149, 0x103}, /* PROG2# => Samsung */ + {419, 0x104}, /* ZOOMOUT# => Logitech */ + {144, 0x105}, /* FILE# => Messenger/Files */ + {216, 0x105}, /* CHAT# => Messenger/Files */ + {430, 0x105}, /* MESSENGER# */ + {182, 0x107}, /* REDO# */ + {131, 0x108}, /* UNDO# */ + {135, 0x10a}, /* PASTE# */ + {177, 0x10b}, /* SCROLLUP# => normal speed */ + {165, 0x110}, /* PREVIOUSSONG */ + {136, 0x112}, /* FIND# => Logitech */ + {421, 0x113}, /* WORDPROCESSOR# => Word */ + {423, 0x114}, /* SPREADSHEET# => Excel */ + {397, 0x115}, /* CALENDAR# */ + {433, 0x116}, /* LOGOFF# */ + {137, 0x117}, /* CUT# */ + {133, 0x118}, /* COPY# */ + {163, 0x119}, /* NEXTSONG */ + {154, 0x11e}, /* CYCLEWINDOWS => Application Right (no left counterpart) */ + {113, 0x120}, /* MUTE */ + {140, 0x121}, /* CALC */ + {164, 0x122}, /* PLAYPAUSE */ + {432, 0x123}, /* SPELLCHECK# */ + {166, 0x124}, /* STOPCD */ + {139, 0x126}, /* MENU# => Shortcut/Menu/Help for a few OEMs */ + {114, 0x12e}, /* VOL- */ + {160, 0x12f}, /* CLOSECD# => Logitech Eject */ + {161, 0x12f}, /* EJECTCD# => Logitech */ + {162, 0x12f}, /* EJECTCLOSECD# => Logitech */ + {115, 0x130}, /* VOL+ */ + {150, 0x132}, /* WWW# */ + {172, 0x132}, /* HOMEPAGE */ + {138, 0x13b}, /* HELP# */ + {213, 0x13c}, /* SOUND# => My Music/Office Home */ + {360, 0x13c}, /* VENDOR# => My Music/Office Home */ + {204, 0x13d}, /* DASHBOARD# => Task Pane */ + {181, 0x13e}, /* NEW# */ + {134, 0x13f}, /* OPEN# */ + {206, 0x140}, /* CLOSE# */ + {232, 0x141}, /* REPLY# */ + {233, 0x142}, /* FORWARDMAIL# */ + {231, 0x143}, /* SEND# */ + {151, 0x144}, /* MSDOS# */ + {112, 0x14c}, /* MACRO */ + {179, 0x14c}, /* KPLEFTPAREN# */ + {118, 0x14e}, /* KPPLUSMINUS */ + {235, 0x155}, /* DOCUMENTS# => Logitech */ + {234, 0x157}, /* SAVE# */ + {210, 0x158}, /* PRINT# */ + {116, 0x15e}, /* POWER */ + {142, 0x15f}, /* SLEEP */ + {143, 0x163}, /* WAKEUP */ + {180, 0x164}, /* KPRIGHTPAREN# */ + {212, 0x164}, /* CAMERA# => My Pictures */ + {217, 0x165}, /* SEARCH */ + {156, 0x166}, /* BOOKMARKS => Favorites */ + {364, 0x166}, /* FAVORITES# */ + {173, 0x167}, /* REFRESH */ + {128, 0x168}, /* STOP */ + {159, 0x169}, /* FORWARD */ + {158, 0x16a}, /* BACK */ + {157, 0x16b}, /* COMPUTER */ + {155, 0x16c}, /* MAIL */ + {215, 0x16c}, /* EMAIL# */ + {226, 0x16d}, /* MEDIA */ + {167, 0x178}, /* RECORD# => Logitech */ + {152, 0x17a}, /* COFFEE/SCREENLOCK# */ + {178, 0x18b}, /* SCROLLDOWN# => normal speed */ +}; + +uint16_t +evdev_translate(uint32_t keycode) +{ + /* "for 1-83 (0x01-0x53) scancode equals keycode" */ + auto ret = (keycode <= 0x53) ? keycode : evdev_keycodes[keycode]; + + if (!ret) + qWarning() << "Evdev Keyboard: Unknown key" << keycode; +#if 0 + else + qInfo() << "Evdev Keyboard: Key" << keycode << "scancode" << QString::number(ret, 16); +#endif + + return ret; +} diff --git a/src/qt/evdev_keyboard.hpp b/src/qt/evdev_keyboard.hpp new file mode 100644 index 000000000..5efe5958d --- /dev/null +++ b/src/qt/evdev_keyboard.hpp @@ -0,0 +1,20 @@ +/* + * 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. + * + * Definitions for evdev keyboard input module. + * + * + * + * Authors: RichardG, + * + * Copyright 2023 RichardG. + */ +#ifndef EVDEV_KEYBOARD_HPP +#define EVDEV_KEYBOARD_HPP +uint16_t evdev_translate(uint32_t keycode); +#endif diff --git a/src/qt/evdev_mouse.cpp b/src/qt/evdev_mouse.cpp index c04c8c8d6..b5f68a286 100644 --- a/src/qt/evdev_mouse.cpp +++ b/src/qt/evdev_mouse.cpp @@ -1,18 +1,18 @@ /* - * 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. + * 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. + * This file is part of the 86Box distribution. * - * Linux/FreeBSD libevdev mouse input module. + * Linux/FreeBSD libevdev mouse input module. * * * - * Authors: Cacodemon345 + * Authors: Cacodemon345 * - * Copyright 2021-2022 Cacodemon345 + * Copyright 2021-2022 Cacodemon345 */ #include "evdev_mouse.hpp" #include @@ -26,91 +26,88 @@ #include -extern "C" -{ +extern "C" { #include <86box/86box.h> #include <86box/plat.h> #include <86box/mouse.h> +#include } -static std::vector> evdev_mice; -static std::atomic stopped = false; -static QThread* evdev_thread; +static std::vector> evdev_mice; +static std::atomic stopped = false; +static QThread *evdev_thread; -static std::atomic evdev_mouse_rel_x = 0, evdev_mouse_rel_y = 0; - -void evdev_mouse_poll() +void +evdev_thread_func() { - if (!evdev_mice.size() || !mouse_capture) - { - evdev_mouse_rel_x = 0; - evdev_mouse_rel_y = 0; - return; + struct pollfd *pfds = (struct pollfd *) calloc(evdev_mice.size(), sizeof(struct pollfd)); + for (unsigned int i = 0; i < evdev_mice.size(); i++) { + pfds[i].fd = libevdev_get_fd(evdev_mice[i].second); + pfds[i].events = POLLIN; } - mouse_x = evdev_mouse_rel_x; - mouse_y = evdev_mouse_rel_y; - evdev_mouse_rel_x = evdev_mouse_rel_y = 0; -} -void evdev_thread_func() -{ - while (!stopped) - { - for (int i = 0; i < evdev_mice.size(); i++) - { + while (!stopped) { + poll(pfds, evdev_mice.size(), 500); + for (unsigned int i = 0; i < evdev_mice.size(); i++) { struct input_event ev; - int rc = libevdev_next_event(evdev_mice[i].second, LIBEVDEV_READ_FLAG_NORMAL, &ev); - if (rc == 0 && ev.type == EV_REL && mouse_capture) - { - if (ev.code == REL_X) evdev_mouse_rel_x += ev.value; - if (ev.code == REL_Y) evdev_mouse_rel_y += ev.value; + if (pfds[i].revents & POLLIN) { + while (libevdev_next_event(evdev_mice[i].second, LIBEVDEV_READ_FLAG_NORMAL, &ev) == 0) { + if (evdev_mice.size() && (ev.type == EV_REL) && mouse_capture) { + if (ev.code == REL_X) + mouse_scale_x(ev.value); + if (ev.code == REL_Y) + mouse_scale_y(ev.value); + } + } } } } - for (int i = 0; i < evdev_mice.size(); i++) - { + + for (unsigned int i = 0; i < evdev_mice.size(); i++) { libevdev_free(evdev_mice[i].second); + evdev_mice[i].second = nullptr; close(evdev_mice[i].first); } + free(pfds); evdev_mice.clear(); } -void evdev_stop() +void +evdev_stop() { - stopped = true; - evdev_thread->wait(); + if (evdev_thread) { + stopped = true; + evdev_thread->wait(); + evdev_thread = nullptr; + } } -void evdev_init() +void +evdev_init() { - for (int i = 0; i < 256; i++) - { + if (evdev_thread) + return; + for (int i = 0; i < 256; i++) { std::string evdev_device_path = "/dev/input/event" + std::to_string(i); - int fd = open(evdev_device_path.c_str(), O_NONBLOCK | O_RDONLY); - if (fd != -1) - { - libevdev* input_struct = nullptr; - int rc = libevdev_new_from_fd(fd, &input_struct); - if (rc <= -1) - { + int fd = open(evdev_device_path.c_str(), O_NONBLOCK | O_RDONLY); + if (fd != -1) { + libevdev *input_struct = nullptr; + int rc = libevdev_new_from_fd(fd, &input_struct); + if (rc <= -1) { close(fd); continue; - } - else - { - if (!libevdev_has_event_type(input_struct, EV_REL) || !libevdev_has_event_code(input_struct, EV_KEY, BTN_LEFT)) - { + } else { + if (!libevdev_has_event_type(input_struct, EV_REL) || !libevdev_has_event_code(input_struct, EV_KEY, BTN_LEFT)) { libevdev_free(input_struct); close(fd); continue; } evdev_mice.push_back(std::make_pair(fd, input_struct)); } - } - else if (errno == ENOENT) break; + } else if (errno == ENOENT) + break; } - if (evdev_mice.size() != 0) - { + if (evdev_mice.size() != 0) { evdev_thread = QThread::create(evdev_thread_func); evdev_thread->start(); atexit(evdev_stop); diff --git a/src/qt/evdev_mouse.hpp b/src/qt/evdev_mouse.hpp index 7681771c6..0b0b8b26f 100644 --- a/src/qt/evdev_mouse.hpp +++ b/src/qt/evdev_mouse.hpp @@ -1,4 +1,3 @@ #ifdef EVDEV_INPUT void evdev_init(); -void evdev_mouse_poll(); #endif diff --git a/src/qt/languages/ca-ES.po b/src/qt/languages/ca-ES.po new file mode 100644 index 000000000..371781b7a --- /dev/null +++ b/src/qt/languages/ca-ES.po @@ -0,0 +1,1226 @@ +msgid "&Action" +msgstr "&Acció" + +msgid "&Keyboard requires capture" +msgstr "&Teclat requereix captura" + +msgid "&Right CTRL is left ALT" +msgstr "CTRL &dret és ALT esquerre" + +msgid "&Hard Reset..." +msgstr "&Reinicialització completa..." + +msgid "&Ctrl+Alt+Del\tCtrl+F12" +msgstr "&Ctrl+Alt+Del\tCtrl+F12" + +msgid "Ctrl+Alt+&Esc" +msgstr "Ctrl+Alt+&Esc" + +msgid "&Pause" +msgstr "&Pausa" + +msgid "E&xit..." +msgstr "&Sortir..." + +msgid "&View" +msgstr "&Vista" + +msgid "&Hide status bar" +msgstr "&Amagar barra d'estat" + +msgid "Hide &toolbar" +msgstr "Amagar &barra d'eines" + +msgid "&Resizeable window" +msgstr "&Finestra redimensionable" + +msgid "R&emember size && position" +msgstr "&Recordar mida i posició" + +msgid "Re&nderer" +msgstr "Re&nderitzador" + +msgid "&SDL (Software)" +msgstr "&SDL (Software)" + +msgid "SDL (&Hardware)" +msgstr "SDL (&Hardware)" + +msgid "SDL (&OpenGL)" +msgstr "SDL (&OpenGL)" + +msgid "Open&GL (3.0 Core)" +msgstr "Open&GL (3.0 Core)" + +msgid "&VNC" +msgstr "&VNC" + +msgid "Specify dimensions..." +msgstr "E&specificar dimensions..." + +msgid "F&orce 4:3 display ratio" +msgstr "F&orçar ràtio 4:3" + +msgid "&Window scale factor" +msgstr "&Factor d'escalat de finestra" + +msgid "&0.5x" +msgstr "&0.5x" + +msgid "&1x" +msgstr "&1x" + +msgid "1.&5x" +msgstr "1.&5x" + +msgid "&2x" +msgstr "&2x" + +msgid "&3x" +msgstr "&3x" + +msgid "&4x" +msgstr "&4x" + +msgid "&5x" +msgstr "&5x" + +msgid "&6x" +msgstr "&6x" + +msgid "&7x" +msgstr "&7x" + +msgid "&8x" +msgstr "&8x" + +msgid "Filter method" +msgstr "&Mètode de filtrat" + +msgid "&Nearest" +msgstr "&Més proper" + +msgid "&Linear" +msgstr "&Lineal" + +msgid "Hi&DPI scaling" +msgstr "&Escalat alta densitat" + +msgid "&Fullscreen\tCtrl+Alt+PgUp" +msgstr "&Pantalla completa\tCtrl+Alt+PgUp" + +msgid "Fullscreen &stretch mode" +msgstr "Escalat pantalla completa" + +msgid "&Full screen stretch" +msgstr "&Estirar" + +msgid "&4:3" +msgstr "&4:3" + +msgid "&Square pixels (Keep ratio)" +msgstr "&Píxels quadrats (Mant. aspecte)" + +msgid "&Integer scale" +msgstr "&Escala de valor enter" + +msgid "4:&3 Integer scale" +msgstr "Escala de valor enter 4:&3" + +msgid "E&GA/(S)VGA settings" +msgstr "&Ajustaments EGA/(S)VGA" + +msgid "&Inverted VGA monitor" +msgstr "&Monitor VGA invertit" + +msgid "VGA screen &type" +msgstr "&Tipus de pantalla VGA" + +msgid "RGB &Color" +msgstr "RGB &Color" + +msgid "&RGB Grayscale" +msgstr "RGB &Grisos" + +msgid "&Amber monitor" +msgstr "Monitor & Ambre" + +msgid "&Green monitor" +msgstr "Monitor &Verd" + +msgid "&White monitor" +msgstr "Monitor &Blanc" + +msgid "Grayscale &conversion type" +msgstr "&Conversió a grisos" + +msgid "BT&601 (NTSC/PAL)" +msgstr "BT&601 (NTSC/PAL)" + +msgid "BT&709 (HDTV)" +msgstr "BT&709 (HDTV)" + +msgid "&Average" +msgstr "&Mitjana" + +msgid "CGA/PCjr/Tandy/E&GA/(S)VGA overscan" +msgstr "&Overscan CGA/PCjr/Tandy/EGA/(S)VGA" + +msgid "Change contrast for &monochrome display" +msgstr "Canviar contrast per a pantalla &monocroma" + +msgid "&Media" +msgstr "&Mitjans" + +msgid "&Tools" +msgstr "&Eines" + +msgid "&Settings..." +msgstr "&Ajustaments..." + +msgid "&Update status bar icons" +msgstr "&Actualitzar icones a la barra d'estat" + +msgid "Take s&creenshot\tCtrl+F11" +msgstr "Prendre c&aptura\tCtrl+F11" + +msgid "&Preferences..." +msgstr "&Preferències..." + +msgid "Enable &Discord integration" +msgstr "Habilita la integració amb el &Discord" + +msgid "Sound &gain..." +msgstr "&Guany de so..." + +msgid "Begin trace\tCtrl+T" +msgstr "Començar traça\tCtrl+T" + +msgid "End trace\tCtrl+T" +msgstr "Acabar traça\tCtrl+T" + +msgid "&Help" +msgstr "&Ajuda" + +msgid "&Documentation..." +msgstr "&Documentació..." + +msgid "&About 86Box..." +msgstr "&Quant a 86Box..." + +msgid "&New image..." +msgstr "&Nova imatge..." + +msgid "&Existing image..." +msgstr "Imatge &Existent..." + +msgid "Existing image (&Write-protected)..." +msgstr "Imatge Existent (&Només-lectura)..." + +msgid "&Record" +msgstr "&Gravar" + +msgid "&Play" +msgstr "&Reproduir" + +msgid "&Rewind to the beginning" +msgstr "&Rebobinar a l'inici" + +msgid "&Fast forward to the end" +msgstr "&Avanç ràpid al final" + +msgid "E&ject" +msgstr "E&xtreure" + +msgid "&Image..." +msgstr "&Imatge..." + +msgid "E&xport to 86F..." +msgstr "E&xportar a 86F..." + +msgid "&Mute" +msgstr "&Silenciar" + +msgid "E&mpty" +msgstr "E&xtreure disc" + +msgid "&Reload previous image" +msgstr "&Recarregar imatge prèvia" + +msgid "&Folder..." +msgstr "&Carpeta..." + +msgid "Target &framerate" +msgstr "&Taxa de refresc objectiu" + +msgid "&Sync with video" +msgstr "&Sincronitzar amb vídeo" + +msgid "&25 fps" +msgstr "&25 fps" + +msgid "&30 fps" +msgstr "&30 fps" + +msgid "&50 fps" +msgstr "&50 fps" + +msgid "&60 fps" +msgstr "&60 fps" + +msgid "&75 fps" +msgstr "&75 fps" + +msgid "&VSync" +msgstr "&VSync" + +msgid "&Select shader..." +msgstr "&Seleccionar shader..." + +msgid "&Remove shader" +msgstr "&Eliminar shader" + +msgid "Preferences" +msgstr "Preferències" + +msgid "Sound Gain" +msgstr "Guany de So" + +msgid "New Image" +msgstr "Nova Imatge" + +msgid "Settings" +msgstr "Ajustaments" + +msgid "Specify Main Window Dimensions" +msgstr "Especificar Dimensions de la Finestra Principal" + +msgid "OK" +msgstr "D'acord" + +msgid "Cancel" +msgstr "AnuÅ€lació" + +msgid "Save these settings as &global defaults" +msgstr "Salvar aquests paràmetres com per &defecte globalment" + +msgid "&Default" +msgstr "&Per defecte" + +msgid "Language:" +msgstr "Idioma:" + +msgid "Icon set:" +msgstr "Conjunt d'icones:" + +msgid "Gain" +msgstr "Guany" + +msgid "File name:" +msgstr "Nom del fitxer:" + +msgid "Disk size:" +msgstr "Grandària de disc:" + +msgid "RPM mode:" +msgstr "Mode RPM:" + +msgid "Progress:" +msgstr "Progrés:" + +msgid "Width:" +msgstr "Amplada:" + +msgid "Height:" +msgstr "Alçada:" + +msgid "Lock to this size" +msgstr "Bloquejar aquesta mida" + +msgid "Machine type:" +msgstr "Tipus de màquina:" + +msgid "Machine:" +msgstr "Màquina:" + +msgid "Configure" +msgstr "Configurar" + +msgid "CPU type:" +msgstr "Tipus de CPU:" + +msgid "Speed:" +msgstr "Velocitat:" + +msgid "FPU:" +msgstr "FPU:" + +msgid "Wait states:" +msgstr "Estats en espera:" + +msgid "MB" +msgstr "MB" + +msgid "Memory:" +msgstr "Memòria:" + +msgid "Time synchronization" +msgstr "Sincronització horària" + +msgid "Disabled" +msgstr "Desactuvat" + +msgid "Enabled (local time)" +msgstr "Activat (hora local)" + +msgid "Enabled (UTC)" +msgstr "Activat (UTC)" + +msgid "Dynamic Recompiler" +msgstr "Recopilador Dinàmic" + +msgid "Video:" +msgstr "Vídeo:" + +msgid "Voodoo Graphics" +msgstr "Gràfics Voodoo" + +msgid "IBM 8514/a Graphics" +msgstr "Gràfics IBM 8514/a" + +msgid "XGA Graphics" +msgstr "Gràfics XGA" + +msgid "Mouse:" +msgstr "Ratolí:" + +msgid "Joystick:" +msgstr "Joystick:" + +msgid "Joystick 1..." +msgstr "Joystick 1..." + +msgid "Joystick 2..." +msgstr "Joystick 2..." + +msgid "Joystick 3..." +msgstr "Joystick 3..." + +msgid "Joystick 4..." +msgstr "Joystick 4..." + +msgid "Sound card 1:" +msgstr "Targeta de so 1:" + +msgid "Sound card 2:" +msgstr "Targeta de so 2:" + +msgid "Sound card 3:" +msgstr "Targeta de so 3:" + +msgid "Sound card 4:" +msgstr "Targeta de so 4:" + +msgid "MIDI Out Device:" +msgstr "Dispositiu de sortida MIDI:" + +msgid "MIDI In Device:" +msgstr "Dispositiu d'entrada MIDI:" + +msgid "Standalone MPU-401" +msgstr "MPU-401 autònom" + +msgid "Use FLOAT32 sound" +msgstr "Usar so FLOAT32" + +msgid "FM synth driver" +msgstr "Manejador de sintet. FM" + +msgid "Nuked (more accurate)" +msgstr "Nuked (més acurat)" + +msgid "YMFM (faster)" +msgstr "YMFM (més ràpid)" + +msgid "Network type:" +msgstr "Tipus de xarxa:" + +msgid "PCap device:" +msgstr "Dispositiu PCap:" + +msgid "Network adapter:" +msgstr "Adaptador de xarxa:" + +msgid "COM1 Device:" +msgstr "Dispositiu COM1:" + +msgid "COM2 Device:" +msgstr "Dispositiu COM2:" + +msgid "COM3 Device:" +msgstr "Dispositiu COM3:" + +msgid "COM4 Device:" +msgstr "Dispositiu COM4:" + +msgid "LPT1 Device:" +msgstr "Dispositiu LPT1:" + +msgid "LPT2 Device:" +msgstr "Dispositiu LPT2:" + +msgid "LPT3 Device:" +msgstr "Dispositiu LPT3:" + +msgid "LPT4 Device:" +msgstr "Dispositiu LPT4:" + +msgid "Serial port 1" +msgstr "Port sèrie 1" + +msgid "Serial port 2" +msgstr "Port sèrie 2" + +msgid "Serial port 3" +msgstr "Port sèrie 3" + +msgid "Serial port 4" +msgstr "Port sèrie 4" + +msgid "Parallel port 1" +msgstr "Port paral·lel 1" + +msgid "Parallel port 2" +msgstr "Port paral·lel 2" + +msgid "Parallel port 3" +msgstr "Port paral·lel 3" + +msgid "Parallel port 4" +msgstr "Port paral·lel 4" + +msgid "HD Controller:" +msgstr "Controlador de HD:" + +msgid "FD Controller:" +msgstr "Controlador de FD:" + +msgid "Tertiary IDE Controller" +msgstr "Controlador IDE terciari" + +msgid "Quaternary IDE Controller" +msgstr "Controlador IDE quaternari" + +msgid "SCSI" +msgstr "SCSI" + +msgid "Controller 1:" +msgstr "Controlador 1:" + +msgid "Controller 2:" +msgstr "Controlador 2:" + +msgid "Controller 3:" +msgstr "Controlador 3:" + +msgid "Controller 4:" +msgstr "Controlador 4:" + +msgid "Cassette" +msgstr "Casset" + +msgid "Hard disks:" +msgstr "Discs durs:" + +msgid "&New..." +msgstr "&Nou..." + +msgid "&Existing..." +msgstr "&Existent..." + +msgid "&Remove" +msgstr "E&liminar" + +msgid "Bus:" +msgstr "Bus:" + +msgid "Channel:" +msgstr "Canal:" + +msgid "ID:" +msgstr "ID:" + +msgid "&Specify..." +msgstr "E&specificar..." + +msgid "Sectors:" +msgstr "Sectors:" + +msgid "Heads:" +msgstr "Caps:" + +msgid "Cylinders:" +msgstr "Cilindres:" + +msgid "Size (MB):" +msgstr "Mida (MB):" + +msgid "Type:" +msgstr "Tipus:" + +msgid "Image Format:" +msgstr "Format d'imatge:" + +msgid "Block Size:" +msgstr "Mida del bloc:" + +msgid "Floppy drives:" +msgstr "Unitats de disquet:" + +msgid "Turbo timings" +msgstr "Temps turbo" + +msgid "Check BPB" +msgstr "Comprovar BPB" + +msgid "CD-ROM drives:" +msgstr "Unitats de CD-ROM:" + +msgid "Earlier drive" +msgstr "Unitat anterior" + +msgid "MO drives:" +msgstr "Unitats MO:" + +msgid "ZIP drives:" +msgstr "Unitats ZIP:" + +msgid "ZIP 250" +msgstr "ZIP 250" + +msgid "ISA RTC:" +msgstr "ISA RTC:" + +msgid "ISA Memory Expansion" +msgstr "Expansió de memòria ISA" + +msgid "Card 1:" +msgstr "Targeta 1:" + +msgid "Card 2:" +msgstr "Targeta 2:" + +msgid "Card 3:" +msgstr "Targeta 3:" + +msgid "Card 4:" +msgstr "Targeta 4:" + +msgid "ISABugger device" +msgstr "Dispositiu ISABugger" + +msgid "POST card" +msgstr "Targeta POST" + +msgid "FONT_SIZE" +msgstr "9" + +msgid "FONT_NAME" +msgstr "Segoe UI" + +msgid "86Box" +msgstr "86Box" + +msgid "Error" +msgstr "Error" + +msgid "Fatal error" +msgstr "Error fatal" + +msgid " - PAUSED" +msgstr " - EN PAUSA" + +msgid "Press Ctrl+Alt+PgDn to return to windowed mode." +msgstr "Premeu Ctrl+Alt+PgDn per tornar al mode de finestra." + +msgid "Speed" +msgstr "Velocitat" + +msgid "ZIP %03i %i (%s): %ls" +msgstr "ZIP %03i %i (%s): %ls" + +msgid "ZIP images" +msgstr "Imatges ZIP" + +msgid "86Box could not find any usable ROM images.\n\nPlease download a ROM set and extract it into the \"roms\" directory." +msgstr "86Box no ha pogut trobar cap imatge ROM utilitzable.\n\nSi us plau, descarregueu un conjunt de ROM i extreu-lo al directori \"roms\"." + +msgid "(empty)" +msgstr "(buit)" + +msgid "All files" +msgstr "Tots els fitxers" + +msgid "Turbo" +msgstr "Turbo" + +msgid "On" +msgstr "On" + +msgid "Off" +msgstr "Off" + +msgid "All images" +msgstr "Totes les imatges" + +msgid "Basic sector images" +msgstr "Imatges sectorials bàsiques" + +msgid "Surface images" +msgstr "Imatges superficials" + +msgid "Machine \"%hs\" is not available due to missing ROMs in the roms/machines directory. Switching to an available machine." +msgstr "La màquina \"%hs\" no està disponible perquè falten ROM al directori roms/machines. Canvi a una màquina disponible." + +msgid "Video card \"%hs\" is not available due to missing ROMs in the roms/video directory. Switching to an available video card." +msgstr "La targeta de vídeo \"%hs\" no està disponible perquè falten ROM al directori roms/video. Canvi a una targeta de vídeo disponible." + +msgid "Machine" +msgstr "Màquina" + +msgid "Display" +msgstr "Vídeo" + +msgid "Input devices" +msgstr "Dispositius d'entrada" + +msgid "Sound" +msgstr "So" + +msgid "Network" +msgstr "Xarxa" + +msgid "Ports (COM & LPT)" +msgstr "Ports (COM i LPT)" + +msgid "Storage controllers" +msgstr "Controladors d'emmagatzematge" + +msgid "Hard disks" +msgstr "Discs durs" + +msgid "Floppy & CD-ROM drives" +msgstr "Unitats de disquet i CD-ROM" + +msgid "Other removable devices" +msgstr "Altres dispositius extraïbles" + +msgid "Other peripherals" +msgstr "Altres perifèrics" + +msgid "Click to capture mouse" +msgstr "Feu clic per capturar el ratolí" + +msgid "Press F8+F12 to release mouse" +msgstr "Premeu F8+F12 per alliberar el ratolí" + +msgid "Press F8+F12 or middle button to release mouse" +msgstr "Premeu F8+F12 o el botó central per alliberar el ratolí" + +msgid "Bus" +msgstr "Bus" + +msgid "File" +msgstr "Fitxer" + +msgid "C" +msgstr "C" + +msgid "H" +msgstr "H" + +msgid "S" +msgstr "S" + +msgid "KB" +msgstr "KB" + +msgid "Could not initialize the video renderer." +msgstr "No has estat possible inicialitzar el renderitzador de vídeo." + +msgid "Default" +msgstr "Per defecte" + +msgid "%i estat(s) d'espera" +msgstr "%i estado(s) de Espera" + +msgid "Type" +msgstr "Tipus" + +msgid "Failed to set up PCap" +msgstr "No s'ha pogut configurar PCap" + +msgid "No PCap devices found" +msgstr "No s'han trobat dispositius PCap" + +msgid "Invalid PCap device" +msgstr "El dispositiu PCap no és vàlid" + +msgid "Standard 2-button joystick(s)" +msgstr "Joystick(s) estàndard de 2 botons" + +msgid "Standard 4-button joystick" +msgstr "Joystick(s) estàndard de 4 botons" + +msgid "Standard 6-button joystick" +msgstr "Joystick(s) estàndard de 6 botons" + +msgid "Standard 8-button joystick" +msgstr "Joystick(s) estàndard de 8 botons" + +msgid "CH Flightstick Pro" +msgstr "CH Flightstick Pro" + +msgid "Microsoft SideWinder Pad" +msgstr "Microsoft SideWinder Pad" + +msgid "Thrustmaster Flight Control System" +msgstr "Thrustmaster Flight Control System" + +msgid "None" +msgstr "Cap" + +msgid "Unable to load keyboard accelerators." +msgstr "No has estat possible carregar els acceleradors del teclat." + +msgid "Unable to register raw input." +msgstr "No has estat possible registrar l'entrada en brut." + +msgid "%u" +msgstr "%u" + +msgid "%u MB (CHS: %i, %i, %i)" +msgstr "%u MB (CHS: %i, %i, %i)" + +msgid "Floppy %i (%s): %ls" +msgstr "Disquet %i (%s): %ls" + +msgid "Advanced sector images" +msgstr "Imatges avançates del sector" + +msgid "Flux images" +msgstr "Imatges de flux" + +msgid "Unable to initialize SDL, SDL2.dll is required" +msgstr "No has estat possible inicialitzar SDL, és necessari SDL2.dll" + +msgid "Are you sure you want to hard reset the emulated machine?" +msgstr "Esteu segur que voleu restablir la màquina emulada?" + +msgid "Are you sure you want to exit 86Box?" +msgstr "Esteu segur que voleu sortir de 86Box?" + +msgid "Unable to initialize Ghostscript" +msgstr "No es pot inicialitzar Ghostscript" + +msgid "MO %i (%ls): %ls" +msgstr "MO %i (%ls): %ls" + +msgid "MO images" +msgstr "Imatges MO" + +msgid "Welcome to 86Box!" +msgstr "Benvingut a 86Box!" + +msgid "Internal controller" +msgstr "Controlador intern" + +msgid "Exit" +msgstr "Sortir" + +msgid "No ROMs found" +msgstr "No s'ha trobat cap ROM" + +msgid "Do you want to save the settings?" +msgstr "Voleu desar les configuracions?" + +msgid "This will hard reset the emulated machine." +msgstr "Es farà una reinicialització completa de la màquina emulada." + +msgid "Save" +msgstr "Desar" + +msgid "About 86Box" +msgstr "Quant a 86Box" + +msgid "86Box v" +msgstr "86Box v" + +msgid "An emulator of old computers\n\nAuthors: Miran GrÄa (OBattler), RichardG867, Jasmine Iwanek, TC1995, coldbrewed, Teemu Korhonen (Manaatti), Joakim L. Gilje, Adrien Moulin (elyosh), Daniel Balsom (gloriouscow), Cacodemon345, Fred N. van Kempen (waltje), Tiseno100, reenigne, and others.\n\nWith previous core contributions from Sarah Walker, leilei, JohnElliott, greatpsycho, and others.\n\nReleased under the GNU General Public License version 2 or later. See LICENSE for more information." +msgstr "Un emulador d'ordinadors antics\n\nAutors: Miran GrÄa (OBattler), RichardG867, Jasmine Iwanek, TC1995, coldbrewed, Teemu Korhonen (Manaatti), Joakim L. Gilje, Adrien Moulin (elyosh), Daniel Balsom (gloriouscow), Cacodemon345, Fred N. van Kempen (waltje), Tiseno100, reenigne i altres.\n\nWith previous core contributions from Sarah Walker, leilei, JohnElliott, greatpsycho i altres.\n\nAlliberat sota la GNU General Public License versió 2 o posterior. Veure LLICENSE per a més informació." + +msgid "Hardware not available" +msgstr "Maquinari no disponible" + +msgid "WinPcap" +msgstr "WinPcap" + +msgid "libpcap" +msgstr "libpcap" + +msgid "Make sure libpcap is installed and that you are on a libpcap-compatible network connection." +msgstr "Assegureu-vos que el libpcap està instal·lat i que està en una connexió de xarxa compatible amb libpcap." + +msgid "Invalid configuration" +msgstr "Configuració invàlida" + +msgid "gsdll32.dll" +msgstr "gsdll32.dll" + +msgid "libgs" +msgstr "libgs" + +msgid " is required for automatic conversion of PostScript files to PDF.\n\nAny documents sent to the generic PostScript printer will be saved as PostScript (.ps) files." +msgstr " és necessària per a la conversió automàtica de fitxers PostScript a PDF.\n\nQualsevol document enviat a la impressora genèrica postScript es desarà com a fitxer PostScript (.ps)." + +msgid "Entering fullscreen mode" +msgstr "Entrant en mode pantalla completa" + +msgid "Don't show this message again" +msgstr "No mostreu més aquest missatge" + +msgid "Don't exit" +msgstr "No sortir" + +msgid "Reset" +msgstr "Resetejar" + +msgid "Don't reset" +msgstr "No resetejar" + +msgid "CD-ROM images" +msgstr "Imatges de CD-ROM" + +msgid "%hs Device Configuration" +msgstr "%hs Configuració de Dispositiu" + +msgid "Monitor in sleep mode" +msgstr "Monitor en mode estalvi" + +msgid "OpenGL Shaders" +msgstr "Shaders OpenGL" + +msgid "OpenGL options" +msgstr "Opcions OpenGL" + +msgid "You are loading an unsupported configuration" +msgstr "S'està carregant una configuració no suportada" + +msgid "CPU type filtering based on selected machine is disabled for this emulated machine.\n\nThis makes it possible to choose a CPU that is otherwise incompatible with the selected machine. However, you may run into incompatibilities with the machine BIOS or other software.\n\nEnabling this setting is not officially supported and any bug reports filed may be closed as invalid." +msgstr "El Filtratge de tipus de CPU basat en màquina seleccionada està deshabilitat per a aquesta màquina.\n\nAixò fa possible seleccionar una CPU que sigui incompatible amb aquesta màquina. Per això, poden aparèixer incompatibilitat amb la BIOS de la màquina o un altre programari.\n\nActivar aquest ajustament no està oficialment suportat i qualsevol informe de fallada pot ser tancat com a invàlid." + +msgid "Continue" +msgstr "Continuar" + +msgid "Cassette: %s" +msgstr "Casset: %s" + +msgid "Cassette images" +msgstr "Imatges de casset" + +msgid "Cartridge %i: %ls" +msgstr "Cartutx %i: %ls" + +msgid "Cartridge images" +msgstr "Imatges de cartutx" + +msgid "Error initializing renderer" +msgstr "Error en inicialitzar el renderitzador" + +msgid "OpenGL (3.0 Core) renderer could not be initialized. Use another renderer." +msgstr "No has estat possible inicialitzar el renderitzador OpenGL (3.0 Core). Utilitzar un altre renderitzador." + +msgid "Resume execution" +msgstr "Reprendre l'execució" + +msgid "Pause execution" +msgstr "Pausar l'execució" + +msgid "Press Ctrl+Alt+Del" +msgstr "Pulsar Ctrl+Alt+Supr" + +msgid "Press Ctrl+Alt+Esc" +msgstr "Pulsar Ctrl+Alt+Esc" + +msgid "Hard reset" +msgstr "Reinicialització completa" + +msgid "ACPI shutdown" +msgstr "Apagada ACPI" + +msgid "Hard disk (%s)" +msgstr "Disc dur (%s)" + +msgid "%01i:%01i" +msgstr "%01i:%01i" + +msgid "%01i" +msgstr "%01i" + +msgid "MFM/RLL or ESDI CD-ROM drives never existed" +msgstr "Les unitats de CD-ROM MFM/RLL o ESDI no van existir mai" + +msgid "Custom..." +msgstr "Personalitzat..." + +msgid "Custom (large)..." +msgstr "Personalitzat (gran)..." + +msgid "Add New Hard Disk" +msgstr "Afegir disc dur nou" + +msgid "Add Existing Hard Disk" +msgstr "Afegir disc dur existent" + +msgid "HDI disk images cannot be larger than 4 GB." +msgstr "Les imatges de disc HDI no poden superar els 4 GB." + +msgid "Disk images cannot be larger than 127 GB." +msgstr "Les imatges del disc no poden superar els 127 GB." + +msgid "Hard disk images" +msgstr "Imatges del disc dur" + +msgid "Unable to read file" +msgstr "No has estat possible llegir el fitxer" + +msgid "Unable to write file" +msgstr "No has estat possible escriure el fitxer" + +msgid "HDI or HDX images with a sector size other than 512 are not supported." +msgstr "Les imatges HDI o HDX amb una mida de sector diferent de 512 no s'admeten." + +msgid "USB is not yet supported" +msgstr "L'USB encara no s'admete" + +msgid "Disk image file already exists" +msgstr "El fitxer d'imatge de disc ja existeix" + +msgid "Please specify a valid file name." +msgstr "Especifiqueu un nom de fitxer vàlid." + +msgid "Disk image created" +msgstr "La imatge de disc ha estat creada" + +msgid "Make sure the file exists and is readable." +msgstr "Assegureu-vos que el fitxer existeix i és llegible." + +msgid "Make sure the file is being saved to a writable directory." +msgstr "Assegureu-vos que el fitxer s'està desant en un directori que es pugui escriure." + +msgid "Disk image too large" +msgstr "La imatge del disc és massa gran" + +msgid "Remember to partition and format the newly-created drive." +msgstr "Recordeu particionar i formatar la unitat de nova creació." + +msgid "The selected file will be overwritten. Are you sure you want to use it?" +msgstr "El fitxer seleccionat se sobreescriurà. Esteu segur que voleu utilitzar-lo?" + +msgid "Unsupported disk image" +msgstr "Imatge de disc no compatible" + +msgid "Overwrite" +msgstr "Sobreescriure" + +msgid "Don't overwrite" +msgstr "No sobreescriure" + +msgid "Raw image (.img)" +msgstr "Imatge crua (.img)" + +msgid "HDI image (.hdi)" +msgstr "Imatge HDI (.hdi)" + +msgid "HDX image (.hdx)" +msgstr "Imatge HDX (.hdx)" + +msgid "Fixed-size VHD (.vhd)" +msgstr "VHD de mida fixa (.vhd)" + +msgid "Dynamic-size VHD (.vhd)" +msgstr "VHD de mida dinàmica (.vhd)" + +msgid "Differencing VHD (.vhd)" +msgstr "VHD diferencial (.vhd)" + +msgid "Large blocks (2 MB)" +msgstr "Blocs grans (2 MB)" + +msgid "Small blocks (512 KB)" +msgstr "Blocs petits (512 KB)" + +msgid "VHD files" +msgstr "Fitxers VHD" + +msgid "Select the parent VHD" +msgstr "Seleccioneu el VHD pare" + +msgid "This could mean that the parent image was modified after the differencing image was created.\n\nIt can also happen if the image files were moved or copied, or by a bug in the program that created this disk.\n\nDo you want to fix the timestamps?" +msgstr "Això pot ser perquè la imatge pare es va modificar després que la imatge diferencial es creés.\n\nTambé pot passar si les imatges van ser mogudes o copiades, o per una fallada al programa que va crear aquest disc.\n\n¿ Voleu corregir els registres de temps?" + +msgid "Parent and child disk timestamps do not match" +msgstr "Les marques de temps del pare i el fill no coincideixen" + +msgid "Could not fix VHD timestamp." +msgstr "No has estat possible corregir la marca de temps del VHD." + +msgid "%01i:%02i" +msgstr "%01i:%02i" + +msgid "MFM/RLL" +msgstr "MFM/RLL" + +msgid "XTA" +msgstr "XTA" + +msgid "ESDI" +msgstr "ESDI" + +msgid "IDE" +msgstr "IDE" + +msgid "ATAPI" +msgstr "ATAPI" + +msgid "MFM/RLL (%01i:%01i)" +msgstr "MFM/RLL (%01i:%01i)" + +msgid "XTA (%01i:%01i)" +msgstr "XTA (%01i:%01i)" + +msgid "ESDI (%01i:%01i)" +msgstr "ESDI (%01i:%01i)" + +msgid "IDE (%01i:%01i)" +msgstr "IDE (%01i:%01i)" + +msgid "ATAPI (%01i:%01i)" +msgstr "ATAPI (%01i:%01i)" + +msgid "SCSI (%01i:%02i)" +msgstr "SCSI (%01i:%02i)" + +msgid "CD-ROM %i (%s): %s" +msgstr "CD-ROM %i (%s): %s" + +msgid "160 kB" +msgstr "160 kB" + +msgid "180 kB" +msgstr "180 kB" + +msgid "320 kB" +msgstr "320 kB" + +msgid "360 kB" +msgstr "360 kB" + +msgid "640 kB" +msgstr "640 kB" + +msgid "720 kB" +msgstr "720 kB" + +msgid "1.2 MB" +msgstr "1.2 MB" + +msgid "1.25 MB" +msgstr "1.25 MB" + +msgid "1.44 MB" +msgstr "1.44 MB" + +msgid "DMF (cluster 1024)" +msgstr "DMF (clúster 1024)" + +msgid "DMF (cluster 2048)" +msgstr "DMF (clúster 2048)" + +msgid "2.88 MB" +msgstr "2.88 MB" + +msgid "ZIP 100" +msgstr "ZIP 100" + +msgid "3.5\" 128 MB (ISO 10090)" +msgstr "3.5\" 128 MB (ISO 10090)" + +msgid "3.5\" 230 MB (ISO 13963)" +msgstr "3.5\" 230 MB (ISO 13963)" + +msgid "3.5\" 540 MB (ISO 15498)" +msgstr "3.5\" 540 MB (ISO 15498)" + +msgid "3.5\" 640 MB (ISO 15498)" +msgstr "3.5\" 640 MB (ISO 15498)" + +msgid "3.5\" 1.3 GB (GigaMO)" +msgstr "3.5\" 1.3 GB (GigaMO)" + +msgid "3.5\" 2.3 GB (GigaMO 2)" +msgstr "3.5\" 2.3 GB (GigaMO 2)" + +msgid "5.25\" 600 MB" +msgstr "5.25\" 600 MB" + +msgid "5.25\" 650 MB" +msgstr "5.25\" 650 MB" + +msgid "5.25\" 1 GB" +msgstr "5.25\" 1 GB" + +msgid "5.25\" 1.3 GB" +msgstr "5.25\" 1.3 GB" + +msgid "Perfect RPM" +msgstr "RPM perfectes" + +msgid "1% below perfect RPM" +msgstr "1% per sota de RPM perfectes" + +msgid "1.5% below perfect RPM" +msgstr "1.5% per sota de RPM perfectes" + +msgid "2% below perfect RPM" +msgstr "2% per sota de RPM perfectes" + +msgid "(System Default)" +msgstr "(Per defecte del sistema)" + +msgid "Failed to initialize network driver" +msgstr "No has estat possible inicialitzar el controlador de xarxa" + +msgid "The network configuration will be switched to the null driver" +msgstr "La configuració de la xarxa es canviarà al controlador nul" + +msgid "Mouse sensitivity:" +msgstr "Sensibilitat del ratolí:" + +msgid "Select media images from program working directory" +msgstr "Seleccioneu imatges multimèdia del directori de treball del programa" + +msgid "PIT mode:" +msgstr "Mode PIT:" + +msgid "Auto" +msgstr "Automàtic" + +msgid "Slow" +msgstr "Lent" + +msgid "Fast" +msgstr "Ràpid" + +msgid "&Auto-pause on focus loss" +msgstr "&Pausa automàtica en la pèrdua del focus" diff --git a/src/qt/languages/cs-CZ.po b/src/qt/languages/cs-CZ.po index 6f7ecc69e..d86f5b635 100644 --- a/src/qt/languages/cs-CZ.po +++ b/src/qt/languages/cs-CZ.po @@ -76,6 +76,24 @@ msgstr "1.&5x" msgid "&2x" msgstr "&2x" +msgid "&3x" +msgstr "&3x" + +msgid "&4x" +msgstr "&4x" + +msgid "&5x" +msgstr "&5x" + +msgid "&6x" +msgstr "&6x" + +msgid "&7x" +msgstr "&7x" + +msgid "&8x" +msgstr "&8x" + msgid "Filter method" msgstr "Metoda &filtrování" @@ -106,6 +124,9 @@ msgstr "&Zachovat pomÄ›r stran" msgid "&Integer scale" msgstr "&CeloÄíselné Å¡kálování" +msgid "4:&3 Integer scale" +msgstr "4:&3 CeloÄíselné Å¡kálování" + msgid "E&GA/(S)VGA settings" msgstr "Nastavení pro E&GA a (S)VGA" @@ -226,8 +247,8 @@ msgstr "&Vyjmout" msgid "&Reload previous image" msgstr "&NaÄíst znova pÅ™edchozí obraz" -msgid "&Image" -msgstr "&Obraz..." +msgid "&Folder..." +msgstr "&Složka..." msgid "Target &framerate" msgstr "&Cílová snímková frekvence" @@ -364,6 +385,12 @@ msgstr "Grafika:" msgid "Voodoo Graphics" msgstr "Použít grafický akcelerátor Voodoo" +msgid "IBM 8514/a Graphics" +msgstr "Grafika IBM 8514/a" + +msgid "XGA Graphics" +msgstr "Grafika XGA" + msgid "Mouse:" msgstr "MyÅ¡:" @@ -382,8 +409,17 @@ msgstr "Joystick 3..." msgid "Joystick 4..." msgstr "Joystick 4..." -msgid "Sound card:" -msgstr "Zvuková karta:" +msgid "Sound card 1:" +msgstr "Zvuková karta 1:" + +msgid "Sound card 2:" +msgstr "Zvuková karta 2:" + +msgid "Sound card 3:" +msgstr "Zvuková karta 3:" + +msgid "Sound card 4:" +msgstr "Zvuková karta 4:" msgid "MIDI Out Device:" msgstr "MIDI výstup:" @@ -394,18 +430,18 @@ msgstr "MIDI vstup:" msgid "Standalone MPU-401" msgstr "Samostatný MPU-401" -msgid "Innovation SSI-2001" -msgstr "Innovation SSI-2001" - -msgid "CMS / Game Blaster" -msgstr "CMS / Game Blaster" - -msgid "Gravis Ultrasound" -msgstr "Gravis Ultrasound" - msgid "Use FLOAT32 sound" msgstr "Použít zvuk FLOAT32" +msgid "FM synth driver" +msgstr "FM synth driver" + +msgid "Nuked (more accurate)" +msgstr "Nuked (pÅ™esnÄ›jší)" + +msgid "YMFM (faster)" +msgstr "YMFM (rychlejší)" + msgid "Network type:" msgstr "Druh sítÄ›:" @@ -550,6 +586,9 @@ msgstr "Kontrola BPB" msgid "CD-ROM drives:" msgstr "Mechaniky CD-ROM:" +msgid "Earlier drive" +msgstr "ÄŒasná mechanika" + msgid "MO drives:" msgstr "Magnetooptické mechaniky:" @@ -620,7 +659,7 @@ msgid "(empty)" msgstr "(prázdné)" msgid "All files" -msgstr "All files" +msgstr "VÅ¡echny soubory" msgid "Turbo" msgstr "Turbo" @@ -688,9 +727,6 @@ msgstr "StisknÄ›te F8+F12 pro uvolnÄ›ní myÅ¡i" msgid "Press F8+F12 or middle button to release mouse" msgstr "StisknÄ›te F8+F12 nebo prostÅ™ední tlaÄítko pro uvolnÄ›ní myÅ¡i" -msgid "Unable to initialize FluidSynth" -msgstr "Nastala chyba pÅ™i inicializaci knihovny FluidSynth." - msgid "Bus" msgstr "SbÄ›rnice" @@ -775,9 +811,6 @@ msgstr "Rozšířené sektorové obrazy" msgid "Flux images" msgstr "Obrazy magnetického toku" -msgid "Unable to initialize FreeType" -msgstr "Nastala chyba pÅ™i inicializaci knihovny FreeType" - msgid "Unable to initialize SDL, SDL2.dll is required" msgstr "Nastala chyba pÅ™i inicializaci knihovny SDL, je potÅ™eba SDL2.dll" @@ -823,8 +856,8 @@ msgstr "O programu 86Box" msgid "86Box v" msgstr "86Box v" -msgid "An emulator of old computers\n\nAuthors: Sarah Walker, Miran Grca, Fred N. van Kempen (waltje), SA1988, Tiseno100, reenigne, leilei, JohnElliott, greatpsycho, and others.\n\nReleased under the GNU General Public License version 2 or later. See LICENSE for more information." -msgstr "Emulátor starých poÄítaÄů\n\nAutoÅ™i: Sarah Walker, Miran Grca, Fred N. van Kempen (waltje), SA1988, Tiseno100, reenigne, leilei, JohnElliott, greatpsycho, and others.\n\nZveÅ™ejnÄ›no pod licencí GNU General Public License verze 2 nebo novÄ›jší. Viz soubor LICENSE pro více informací." +msgid "An emulator of old computers\n\nAuthors: Miran GrÄa (OBattler), RichardG867, Jasmine Iwanek, TC1995, coldbrewed, Teemu Korhonen (Manaatti), Joakim L. Gilje, Adrien Moulin (elyosh), Daniel Balsom (gloriouscow), Cacodemon345, Fred N. van Kempen (waltje), Tiseno100, reenigne, and others.\n\nWith previous core contributions from Sarah Walker, leilei, JohnElliott, greatpsycho, and others.\n\nReleased under the GNU General Public License version 2 or later. See LICENSE for more information." +msgstr "Emulátor starých poÄítaÄů\n\nAutoÅ™i: Miran GrÄa (OBattler), RichardG867, Jasmine Iwanek, TC1995, coldbrewed, Teemu Korhonen (Manaatti), Joakim L. Gilje, Adrien Moulin (elyosh), Daniel Balsom (gloriouscow), Cacodemon345, Fred N. van Kempen (waltje), Tiseno100, reenigne, and others.\n\nWith previous core contributions from Sarah Walker, leilei, JohnElliott, greatpsycho, and others.\n\nZveÅ™ejnÄ›no pod licencí GNU General Public License verze 2 nebo novÄ›jší. Viz soubor LICENSE pro více informací." msgid "Hardware not available" msgstr "Hardware není dostupný" @@ -841,15 +874,6 @@ msgstr "UjistÄ›te se, že je nainstalován libpcap a používáte síťové pÅ™i msgid "Invalid configuration" msgstr "Neplatná konfigurace" -msgid "freetype.dll" -msgstr "freetype.dll" - -msgid "libfreetype" -msgstr "libfreetype" - -msgid " is required for ESC/P printer emulation." -msgstr " je potÅ™eba pro emulaci ESC/P tiskáren." - msgid "gsdll32.dll" msgstr "gsdll32.dll" @@ -859,15 +883,6 @@ msgstr "libgs" msgid " is required for automatic conversion of PostScript files to PDF.\n\nAny documents sent to the generic PostScript printer will be saved as PostScript (.ps) files." msgstr " je potÅ™eba pro automatický pÅ™evod PostScript dokumentů do PDF.\n\nJakékoliv dokumenty vytisknuté pÅ™es obecnou PostScriptovou tiskárnu budou uloženy jako PostScript (.ps) soubory." -msgid "libfluidsynth.dll" -msgstr "libfluidsynth.dll" - -msgid "libfluidsynth" -msgstr "libfluidsynth" - -msgid " is required for FluidSynth MIDI output." -msgstr " je potÅ™eba pro MIDI výstup pÅ™es knihovnu FluidSynth." - msgid "Entering fullscreen mode" msgstr "Vstup do režimu celé obrazovky" @@ -920,10 +935,10 @@ msgid "Cartridge images" msgstr "Obrazy cartridge" msgid "Error initializing renderer" -msgstr "Error initializing renderer" +msgstr "Chyba pÅ™i inicializaci vykreslovaÄe" msgid "OpenGL (3.0 Core) renderer could not be initialized. Use another renderer." -msgstr "OpenGL (3.0 Core) renderer could not be initialized. Use another renderer." +msgstr "VykreslovaÄ OpenGL (3.0 Core) se nepodaÅ™ilo inicializovat. Použijte jiný renderer." msgid "Resume execution" msgstr "Obnovit" @@ -1183,3 +1198,29 @@ msgstr "2% pod dokonalými ot./m" msgid "(System Default)" msgstr "(Výchozí nastavení systému)" +msgid "Failed to initialize network driver" +msgstr "NepodaÅ™ilo se inicializovat síťový ovladaÄ" + +msgid "The network configuration will be switched to the null driver" +msgstr "Konfigurace sítÄ› bude pÅ™epnuta na nulový ovladaÄ" + +msgid "Mouse sensitivity:" +msgstr "Citlivost myší:" + +msgid "Select media images from program working directory" +msgstr "VýbÄ›r mediálních obrazů z pracovního adresáře programu" + +msgid "PIT mode:" +msgstr "Režim PIT:" + +msgid "Auto" +msgstr "Automatický" + +msgid "Slow" +msgstr "Pomalý" + +msgid "Fast" +msgstr "Rychlý" + +msgid "&Auto-pause on focus loss" +msgstr "&Automatická pauza pÅ™i ztrátÄ› zaměření okna" diff --git a/src/qt/languages/de-DE.po b/src/qt/languages/de-DE.po index 2951c7b85..9c985d871 100644 --- a/src/qt/languages/de-DE.po +++ b/src/qt/languages/de-DE.po @@ -29,7 +29,7 @@ msgid "&Hide status bar" msgstr "&Statusleiste ausblenden" msgid "Hide &toolbar" -msgstr "Werkzeugleiste &ausblenden" +msgstr "&Werkzeugleiste ausblenden" msgid "&Resizeable window" msgstr "&Größenverstellbares Fenster" @@ -76,11 +76,29 @@ msgstr "1,&5x" msgid "&2x" msgstr "&2x" +msgid "&3x" +msgstr "&3x" + +msgid "&4x" +msgstr "&4x" + +msgid "&5x" +msgstr "&5x" + +msgid "&6x" +msgstr "&6x" + +msgid "&7x" +msgstr "&7x" + +msgid "&8x" +msgstr "&8x" + msgid "Filter method" msgstr "Filteringmethode" msgid "&Nearest" -msgstr "&Nearest" +msgstr "&Nächst" msgid "&Linear" msgstr "&Linear" @@ -106,6 +124,9 @@ msgstr "&Quadratische Pixel (Seitenverhältnis beibehalten)" msgid "&Integer scale" msgstr "&Integer-Skalierung" +msgid "4:&3 Integer scale" +msgstr "4:&3 Integer-Skalierung" + msgid "E&GA/(S)VGA settings" msgstr "E&GA/(S)VGA-Einstellungen" @@ -226,8 +247,8 @@ msgstr "L&eer" msgid "&Reload previous image" msgstr "&Voriges Image neu laden" -msgid "&Image" -msgstr "&Image" +msgid "&Folder..." +msgstr "&Verzeichnis..." msgid "Target &framerate" msgstr "Ziel&framerate" @@ -329,7 +350,7 @@ msgid "CPU type:" msgstr "CPU-Typ:" msgid "Speed:" -msgstr "Geschwindigkeit:" +msgstr "Takt:" msgid "FPU:" msgstr "FPU-Einheit:" @@ -364,6 +385,12 @@ msgstr "Videokarte:" msgid "Voodoo Graphics" msgstr "Voodoo-Grafik" +msgid "IBM 8514/a Graphics" +msgstr "IBM 8514/a-Grafik" + +msgid "XGA Graphics" +msgstr "XGA-Grafik" + msgid "Mouse:" msgstr "Maus:" @@ -382,8 +409,17 @@ msgstr "Joystick 3..." msgid "Joystick 4..." msgstr "Joystick 4..." -msgid "Sound card:" -msgstr "Soundkarte:" +msgid "Sound card 1:" +msgstr "Soundkarte 1:" + +msgid "Sound card 2:" +msgstr "Soundkarte 2:" + +msgid "Sound card 3:" +msgstr "Soundkarte 3:" + +msgid "Sound card 4:" +msgstr "Soundkarte 4:" msgid "MIDI Out Device:" msgstr "MIDI Out-Gerät:" @@ -394,18 +430,18 @@ msgstr "MIDI In-Gerät:" msgid "Standalone MPU-401" msgstr "Standalone-MPU-401-Gerät" -msgid "Innovation SSI-2001" -msgstr "Innovation SSI-2001" - -msgid "CMS / Game Blaster" -msgstr "CMS / Game Blaster" - -msgid "Gravis Ultrasound" -msgstr "Gravis Ultrasound" - msgid "Use FLOAT32 sound" msgstr "FLOAT32-Wiedergabe benutzen" +msgid "FM synth driver" +msgstr "FM-Synth-Treiber" + +msgid "Nuked (more accurate)" +msgstr "Nuked (genauer)" + +msgid "YMFM (faster)" +msgstr "YMFM (schneller)" + msgid "Network type:" msgstr "Netzwerktyp:" @@ -550,6 +586,9 @@ msgstr "BPB überprüfen" msgid "CD-ROM drives:" msgstr "CD-ROM-Laufwerke:" +msgid "Earlier drive" +msgstr "Früheres Laufwerk" + msgid "MO drives:" msgstr "MO-Laufwerke:" @@ -688,9 +727,6 @@ msgstr "Bitte F8+F12 zur Mausfreigabe drücken" msgid "Press F8+F12 or middle button to release mouse" msgstr "Bitte F8+F12 oder die mittlere Maustaste zur Mausfreigabe drücken" -msgid "Unable to initialize FluidSynth" -msgstr "FluidSynth konnte nicht initialisiert werden" - msgid "Bus" msgstr "Bus" @@ -775,9 +811,6 @@ msgstr "Fortgeschrittene Sektorimages" msgid "Flux images" msgstr "Fluximages" -msgid "Unable to initialize FreeType" -msgstr "FreeType konnte nicht initialisiert werden" - msgid "Unable to initialize SDL, SDL2.dll is required" msgstr "SDL konnte nicht initialisiert werden, die Datei SDL2.dll wird benötigt" @@ -823,8 +856,8 @@ msgstr "Über 86Box" msgid "86Box v" msgstr "86Box Version " -msgid "An emulator of old computers\n\nAuthors: Sarah Walker, Miran Grca, Fred N. van Kempen (waltje), SA1988, Tiseno100, reenigne, leilei, JohnElliott, greatpsycho, and others.\n\nReleased under the GNU General Public License version 2 or later. See LICENSE for more information." -msgstr "Ein Emulator für alte Computer\n\nAutoren: Sarah Walker, Miran GrÄa, Fred N. van Kempen (waltje), SA1988, Tiseno100, reenigne, leilei, JohnElliott, greatpsycho sowie andere.\n\nÜbersetzt von: dob205\n\nVeröffentlicht unter der GNU General Public License in der Version 2 oder neuer. Siehe LICENSE für mehr Informationen." +msgid "An emulator of old computers\n\nAuthors: Miran GrÄa (OBattler), RichardG867, Jasmine Iwanek, TC1995, coldbrewed, Teemu Korhonen (Manaatti), Joakim L. Gilje, Adrien Moulin (elyosh), Daniel Balsom (gloriouscow), Cacodemon345, Fred N. van Kempen (waltje), Tiseno100, reenigne, and others.\n\nWith previous core contributions from Sarah Walker, leilei, JohnElliott, greatpsycho, and others.\n\nReleased under the GNU General Public License version 2 or later. See LICENSE for more information." +msgstr "Ein Emulator für alte Computer\n\nAutoren: Miran GrÄa (OBattler), RichardG867, Jasmine Iwanek, TC1995, coldbrewed, Teemu Korhonen (Manaatti), Joakim L. Gilje, Adrien Moulin (elyosh), Daniel Balsom (gloriouscow), Cacodemon345, Fred N. van Kempen (waltje), Tiseno100, reenigne sowie andere.\n\nWith previous core contributions from Sarah Walker, leilei, JohnElliott, greatpsycho sowie andere.\n\nÜbersetzt von: dob205\n\nVeröffentlicht unter der GNU General Public License in der Version 2 oder neuer. Siehe LICENSE für mehr Informationen." msgid "Hardware not available" msgstr "Hardware nicht verfügbar" @@ -841,15 +874,6 @@ msgstr "Bitte stellen Sie sicher, dass libpcap installiert ist und sie eine libp msgid "Invalid configuration" msgstr "Ungültige Konfiguration" -msgid "freetype.dll" -msgstr "freetype.dll" - -msgid "libfreetype" -msgstr "libfreetype" - -msgid " is required for ESC/P printer emulation." -msgstr " wird für die ESC/P-Druckeremulation benötigt." - msgid "gsdll32.dll" msgstr "gsdll32.dll" @@ -859,15 +883,6 @@ msgstr "libgs" msgid " is required for automatic conversion of PostScript files to PDF.\n\nAny documents sent to the generic PostScript printer will be saved as PostScript (.ps) files." msgstr " wird zur automatischen Konversion von PostScript-Dateien in das PDF-Format benötigt.\n\nSämtliche an den generischen PostScript-Drucker gesendete Dateien werden als PostScript (.ps)-Dateien gesichert." -msgid "libfluidsynth.dll" -msgstr "libfluidsynth.dll" - -msgid "libfluidsynth" -msgstr "libfluidsynth" - -msgid " is required for FluidSynth MIDI output." -msgstr " wird für die FluidSynth-MIDI-Ausgabe benötigt." - msgid "Entering fullscreen mode" msgstr "Vollbildmodus wird aktiviert" @@ -1183,3 +1198,29 @@ msgstr "2% unterhalb der perfekten Drehzahl" msgid "(System Default)" msgstr "(Systemstandard)" +msgid "Failed to initialize network driver" +msgstr "Netzwerktreiber konnte nicht initialisiert werden" + +msgid "The network configuration will be switched to the null driver" +msgstr "Die Netzwerkkonfiguration wird auf den Nulltreiber umgestellt" + +msgid "Mouse sensitivity:" +msgstr "Empfindlichkeit der Maus:" + +msgid "Select media images from program working directory" +msgstr "Medienbilder aus dem Arbeitsverzeichnis des Programms auswählen" + +msgid "PIT mode:" +msgstr "PIT-Modus:" + +msgid "Auto" +msgstr "Auto" + +msgid "Slow" +msgstr "Langsam" + +msgid "Fast" +msgstr "Schnell" + +msgid "&Auto-pause on focus loss" +msgstr "&Auto-Pause bei Fokusverlust" diff --git a/src/qt/languages/en-GB.po b/src/qt/languages/en-GB.po index 90820a569..4a6a58db6 100644 --- a/src/qt/languages/en-GB.po +++ b/src/qt/languages/en-GB.po @@ -76,6 +76,24 @@ msgstr "1.&5x" msgid "&2x" msgstr "&2x" +msgid "&3x" +msgstr "&3x" + +msgid "&4x" +msgstr "&4x" + +msgid "&5x" +msgstr "&5x" + +msgid "&6x" +msgstr "&6x" + +msgid "&7x" +msgstr "&7x" + +msgid "&8x" +msgstr "&8x" + msgid "Filter method" msgstr "Filter method" @@ -106,6 +124,9 @@ msgstr "&Square pixels (Keep ratio)" msgid "&Integer scale" msgstr "&Integer scale" +msgid "4:&3 Integer scale" +msgstr "4:&3 Integer scale" + msgid "E&GA/(S)VGA settings" msgstr "E&GA/(S)VGA settings" @@ -226,8 +247,8 @@ msgstr "E&mpty" msgid "&Reload previous image" msgstr "&Reload previous image" -msgid "&Image" -msgstr "&Image" +msgid "&Folder..." +msgstr "&Folder..." msgid "Target &framerate" msgstr "Target &framerate" @@ -364,6 +385,12 @@ msgstr "Video:" msgid "Voodoo Graphics" msgstr "Voodoo Graphics" +msgid "IBM 8514/a Graphics" +msgstr "IBM 8514/a Graphics" + +msgid "XGA Graphics" +msgstr "XGA Graphics" + msgid "Mouse:" msgstr "Mouse:" @@ -382,8 +409,17 @@ msgstr "Joystick 3..." msgid "Joystick 4..." msgstr "Joystick 4..." -msgid "Sound card:" -msgstr "Sound card:" +msgid "Sound card 1:" +msgstr "Sound card 1:" + +msgid "Sound card 2:" +msgstr "Sound card 2:" + +msgid "Sound card 3:" +msgstr "Sound card 3:" + +msgid "Sound card 4:" +msgstr "Sound card 4:" msgid "MIDI Out Device:" msgstr "MIDI Out Device:" @@ -394,18 +430,18 @@ msgstr "MIDI In Device:" msgid "Standalone MPU-401" msgstr "Standalone MPU-401" -msgid "Innovation SSI-2001" -msgstr "Innovation SSI-2001" - -msgid "CMS / Game Blaster" -msgstr "CMS / Game Blaster" - -msgid "Gravis Ultrasound" -msgstr "Gravis Ultrasound" - msgid "Use FLOAT32 sound" msgstr "Use FLOAT32 sound" +msgid "FM synth driver" +msgstr "FM synth driver" + +msgid "Nuked (more accurate)" +msgstr "Nuked (more accurate)" + +msgid "YMFM (faster)" +msgstr "YMFM (faster)" + msgid "Network type:" msgstr "Network type:" @@ -550,6 +586,9 @@ msgstr "Check BPB" msgid "CD-ROM drives:" msgstr "CD-ROM drives:" +msgid "Earlier drive" +msgstr "Earlier drive" + msgid "MO drives:" msgstr "MO drives:" @@ -688,9 +727,6 @@ msgstr "Press F8+F12 to release mouse" msgid "Press F8+F12 or middle button to release mouse" msgstr "Press F8+F12 or middle button to release mouse" -msgid "Unable to initialize FluidSynth" -msgstr "Unable to initialize FluidSynth" - msgid "Bus" msgstr "Bus" @@ -775,9 +811,6 @@ msgstr "Advanced sector images" msgid "Flux images" msgstr "Flux images" -msgid "Unable to initialize FreeType" -msgstr "Unable to initialize FreeType" - msgid "Unable to initialize SDL, SDL2.dll is required" msgstr "Unable to initialize SDL, SDL2.dll is required" @@ -823,8 +856,8 @@ msgstr "About 86Box" msgid "86Box v" msgstr "86Box v" -msgid "An emulator of old computers\n\nAuthors: Sarah Walker, Miran Grca, Fred N. van Kempen (waltje), SA1988, Tiseno100, reenigne, leilei, JohnElliott, greatpsycho, and others.\n\nReleased under the GNU General Public License version 2 or later. See LICENSE for more information." -msgstr "An emulator of old computers\n\nAuthors: Sarah Walker, Miran Grca, Fred N. van Kempen (waltje), SA1988, Tiseno100, reenigne, leilei, JohnElliott, greatpsycho, and others.\n\nReleased under the GNU General Public License version 2 or later. See LICENSE for more information." +msgid "An emulator of old computers\n\nAuthors: Miran GrÄa (OBattler), RichardG867, Jasmine Iwanek, TC1995, coldbrewed, Teemu Korhonen (Manaatti), Joakim L. Gilje, Adrien Moulin (elyosh), Daniel Balsom (gloriouscow), Cacodemon345, Fred N. van Kempen (waltje), Tiseno100, reenigne, and others.\n\nWith previous core contributions from Sarah Walker, leilei, JohnElliott, greatpsycho, and others.\n\nReleased under the GNU General Public License version 2 or later. See LICENSE for more information." +msgstr "An emulator of old computers\n\nAuthors: Miran GrÄa (OBattler), RichardG867, Jasmine Iwanek, TC1995, coldbrewed, Teemu Korhonen (Manaatti), Joakim L. Gilje, Adrien Moulin (elyosh), Daniel Balsom (gloriouscow), Cacodemon345, Fred N. van Kempen (waltje), Tiseno100, reenigne, and others.\n\nWith previous core contributions from Sarah Walker, leilei, JohnElliott, greatpsycho, and others.\n\nReleased under the GNU General Public License version 2 or later. See LICENSE for more information." msgid "Hardware not available" msgstr "Hardware not available" @@ -841,15 +874,6 @@ msgstr "Make sure libpcap is installed and that you are on a libpcap-compatible msgid "Invalid configuration" msgstr "Invalid configuration" -msgid "freetype.dll" -msgstr "freetype.dll" - -msgid "libfreetype" -msgstr "libfreetype" - -msgid " is required for ESC/P printer emulation." -msgstr " is required for ESC/P printer emulation." - msgid "gsdll32.dll" msgstr "gsdll32.dll" @@ -859,15 +883,6 @@ msgstr "libgs" msgid " is required for automatic conversion of PostScript files to PDF.\n\nAny documents sent to the generic PostScript printer will be saved as PostScript (.ps) files." msgstr " is required for automatic conversion of PostScript files to PDF.\n\nAny documents sent to the generic PostScript printer will be saved as PostScript (.ps) files." -msgid "libfluidsynth.dll" -msgstr "libfluidsynth.dll" - -msgid "libfluidsynth" -msgstr "libfluidsynth" - -msgid " is required for FluidSynth MIDI output." -msgstr " is required for FluidSynth MIDI output." - msgid "Entering fullscreen mode" msgstr "Entering fullscreen mode" @@ -1183,3 +1198,29 @@ msgstr "2% below perfect RPM" msgid "(System Default)" msgstr "(System Default)" +msgid "Failed to initialize network driver" +msgstr "Failed to initialize network driver" + +msgid "The network configuration will be switched to the null driver" +msgstr "The network configuration will be switched to the null driver" + +msgid "Mouse sensitivity:" +msgstr "Mouse sensitivity:" + +msgid "Select media images from program working directory" +msgstr "Select media images from program working directory" + +msgid "PIT mode:" +msgstr "PIT mode:" + +msgid "Auto" +msgstr "Auto" + +msgid "Slow" +msgstr "Slow" + +msgid "Fast" +msgstr "Fast" + +msgid "&Auto-pause on focus loss" +msgstr "&Auto-pause on focus loss" diff --git a/src/qt/languages/en-US.po b/src/qt/languages/en-US.po index b11e1cdea..ce7ceb149 100644 --- a/src/qt/languages/en-US.po +++ b/src/qt/languages/en-US.po @@ -76,6 +76,24 @@ msgstr "1.&5x" msgid "&2x" msgstr "&2x" +msgid "&3x" +msgstr "&3x" + +msgid "&4x" +msgstr "&4x" + +msgid "&5x" +msgstr "&5x" + +msgid "&6x" +msgstr "&6x" + +msgid "&7x" +msgstr "&7x" + +msgid "&8x" +msgstr "&8x" + msgid "Filter method" msgstr "Filter method" @@ -106,6 +124,9 @@ msgstr "&Square pixels (Keep ratio)" msgid "&Integer scale" msgstr "&Integer scale" +msgid "4:&3 Integer scale" +msgstr "4:&3 Integer scale" + msgid "E&GA/(S)VGA settings" msgstr "E&GA/(S)VGA settings" @@ -226,8 +247,8 @@ msgstr "E&mpty" msgid "&Reload previous image" msgstr "&Reload previous image" -msgid "&Image" -msgstr "&Image" +msgid "&Folder..." +msgstr "&Folder..." msgid "Target &framerate" msgstr "Target &framerate" @@ -364,6 +385,12 @@ msgstr "Video:" msgid "Voodoo Graphics" msgstr "Voodoo Graphics" +msgid "IBM 8514/a Graphics" +msgstr "IBM 8514/a Graphics" + +msgid "XGA Graphics" +msgstr "XGA Graphics" + msgid "Mouse:" msgstr "Mouse:" @@ -382,8 +409,17 @@ msgstr "Joystick 3..." msgid "Joystick 4..." msgstr "Joystick 4..." -msgid "Sound card:" -msgstr "Sound card:" +msgid "Sound card 1:" +msgstr "Sound card 1:" + +msgid "Sound card 2:" +msgstr "Sound card 2:" + +msgid "Sound card 3:" +msgstr "Sound card 3:" + +msgid "Sound card 4:" +msgstr "Sound card 4:" msgid "MIDI Out Device:" msgstr "MIDI Out Device:" @@ -394,18 +430,18 @@ msgstr "MIDI In Device:" msgid "Standalone MPU-401" msgstr "Standalone MPU-401" -msgid "Innovation SSI-2001" -msgstr "Innovation SSI-2001" - -msgid "CMS / Game Blaster" -msgstr "CMS / Game Blaster" - -msgid "Gravis Ultrasound" -msgstr "Gravis Ultrasound" - msgid "Use FLOAT32 sound" msgstr "Use FLOAT32 sound" +msgid "FM synth driver" +msgstr "FM synth driver" + +msgid "Nuked (more accurate)" +msgstr "Nuked (more accurate)" + +msgid "YMFM (faster)" +msgstr "YMFM (faster)" + msgid "Network type:" msgstr "Network type:" @@ -550,6 +586,9 @@ msgstr "Check BPB" msgid "CD-ROM drives:" msgstr "CD-ROM drives:" +msgid "Earlier drive" +msgstr "Earlier drive" + msgid "MO drives:" msgstr "MO drives:" @@ -688,9 +727,6 @@ msgstr "Press F8+F12 to release mouse" msgid "Press F8+F12 or middle button to release mouse" msgstr "Press F8+F12 or middle button to release mouse" -msgid "Unable to initialize FluidSynth" -msgstr "Unable to initialize FluidSynth" - msgid "Bus" msgstr "Bus" @@ -775,9 +811,6 @@ msgstr "Advanced sector images" msgid "Flux images" msgstr "Flux images" -msgid "Unable to initialize FreeType" -msgstr "Unable to initialize FreeType" - msgid "Unable to initialize SDL, SDL2.dll is required" msgstr "Unable to initialize SDL, SDL2.dll is required" @@ -823,8 +856,8 @@ msgstr "About 86Box" msgid "86Box v" msgstr "86Box v" -msgid "An emulator of old computers\n\nAuthors: Sarah Walker, Miran Grca, Fred N. van Kempen (waltje), SA1988, Tiseno100, reenigne, leilei, JohnElliott, greatpsycho, and others.\n\nReleased under the GNU General Public License version 2 or later. See LICENSE for more information." -msgstr "An emulator of old computers\n\nAuthors: Sarah Walker, Miran Grca, Fred N. van Kempen (waltje), SA1988, Tiseno100, reenigne, leilei, JohnElliott, greatpsycho, and others.\n\nReleased under the GNU General Public License version 2 or later. See LICENSE for more information." +msgid "An emulator of old computers\n\nAuthors: Miran GrÄa (OBattler), RichardG867, Jasmine Iwanek, TC1995, coldbrewed, Teemu Korhonen (Manaatti), Joakim L. Gilje, Adrien Moulin (elyosh), Daniel Balsom (gloriouscow), Cacodemon345, Fred N. van Kempen (waltje), Tiseno100, reenigne, and others.\n\nWith previous core contributions from Sarah Walker, leilei, JohnElliott, greatpsycho, and others.\n\nReleased under the GNU General Public License version 2 or later. See LICENSE for more information." +msgstr "An emulator of old computers\n\nAuthors: Miran GrÄa (OBattler), RichardG867, Jasmine Iwanek, TC1995, coldbrewed, Teemu Korhonen (Manaatti), Joakim L. Gilje, Adrien Moulin (elyosh), Daniel Balsom (gloriouscow), Cacodemon345, Fred N. van Kempen (waltje), Tiseno100, reenigne, and others.\n\nWith previous core contributions from Sarah Walker, leilei, JohnElliott, greatpsycho, and others.\n\nReleased under the GNU General Public License version 2 or later. See LICENSE for more information." msgid "Hardware not available" msgstr "Hardware not available" @@ -841,15 +874,6 @@ msgstr "Make sure libpcap is installed and that you are on a libpcap-compatible msgid "Invalid configuration" msgstr "Invalid configuration" -msgid "freetype.dll" -msgstr "freetype.dll" - -msgid "libfreetype" -msgstr "libfreetype" - -msgid " is required for ESC/P printer emulation." -msgstr " is required for ESC/P printer emulation." - msgid "gsdll32.dll" msgstr "gsdll32.dll" @@ -859,15 +883,6 @@ msgstr "libgs" msgid " is required for automatic conversion of PostScript files to PDF.\n\nAny documents sent to the generic PostScript printer will be saved as PostScript (.ps) files." msgstr " is required for automatic conversion of PostScript files to PDF.\n\nAny documents sent to the generic PostScript printer will be saved as PostScript (.ps) files." -msgid "libfluidsynth.dll" -msgstr "libfluidsynth.dll" - -msgid "libfluidsynth" -msgstr "libfluidsynth" - -msgid " is required for FluidSynth MIDI output." -msgstr " is required for FluidSynth MIDI output." - msgid "Entering fullscreen mode" msgstr "Entering fullscreen mode" @@ -1183,3 +1198,29 @@ msgstr "2% below perfect RPM" msgid "(System Default)" msgstr "(System Default)" +msgid "Failed to initialize network driver" +msgstr "Failed to initialize network driver" + +msgid "The network configuration will be switched to the null driver" +msgstr "The network configuration will be switched to the null driver" + +msgid "Mouse sensitivity:" +msgstr "Mouse sensitivity:" + +msgid "Select media images from program working directory" +msgstr "Select media images from program working directory" + +msgid "PIT mode:" +msgstr "PIT mode:" + +msgid "Auto" +msgstr "Auto" + +msgid "Slow" +msgstr "Slow" + +msgid "Fast" +msgstr "Fast" + +msgid "&Auto-pause on focus loss" +msgstr "&Auto-pause on focus loss" diff --git a/src/qt/languages/es-ES.po b/src/qt/languages/es-ES.po index c7b306e1c..d8d648691 100644 --- a/src/qt/languages/es-ES.po +++ b/src/qt/languages/es-ES.po @@ -29,7 +29,7 @@ msgid "&Hide status bar" msgstr "&Ocultar barra de estado" msgid "Hide &toolbar" -msgstr "Hide &toolbar" +msgstr "Ocultar &barra de herramientas" msgid "&Resizeable window" msgstr "&Ventana redimensionable" @@ -76,6 +76,24 @@ msgstr "1.&5x" msgid "&2x" msgstr "&2x" +msgid "&3x" +msgstr "&3x" + +msgid "&4x" +msgstr "&4x" + +msgid "&5x" +msgstr "&5x" + +msgid "&6x" +msgstr "&6x" + +msgid "&7x" +msgstr "&7x" + +msgid "&8x" +msgstr "&8x" + msgid "Filter method" msgstr "&Método de filtrado" @@ -106,8 +124,11 @@ msgstr "&Píxeles cuadrados (Mant. aspecto)" msgid "&Integer scale" msgstr "&Escalado valor entero" +msgid "4:&3 Integer scale" +msgstr "Escalado valor entero 4:&3" + msgid "E&GA/(S)VGA settings" -msgstr "&Ajustes EGA/(S)VGA" +msgstr "&Configuraciones EGA/(S)VGA" msgid "&Inverted VGA monitor" msgstr "&Monitor VGA invertido" @@ -155,7 +176,7 @@ msgid "&Tools" msgstr "&Herramientas" msgid "&Settings..." -msgstr "&Ajustes..." +msgstr "&Configuraciones..." msgid "&Update status bar icons" msgstr "&Actualizar iconos en barra de estado" @@ -226,8 +247,8 @@ msgstr "E&xtraer disco" msgid "&Reload previous image" msgstr "&Recargar imagen previa" -msgid "&Image" -msgstr "&Imagen..." +msgid "&Folder..." +msgstr "&Carpeta..." msgid "Target &framerate" msgstr "&Tasa de refresco objetivo" @@ -269,7 +290,7 @@ msgid "New Image" msgstr "Nueva Imagen" msgid "Settings" -msgstr "Ajustes" +msgstr "Configuraciones" msgid "Specify Main Window Dimensions" msgstr "Especificar Dimensiones de la Ventana Principal" @@ -281,7 +302,7 @@ msgid "Cancel" msgstr "Cancelar" msgid "Save these settings as &global defaults" -msgstr "Salvar estos ajustes como por &defecto globalmente" +msgstr "Salvar estos configuraciones como por &defecto globalmente" msgid "&Default" msgstr "&Por defecto" @@ -364,6 +385,12 @@ msgstr "Vídeo:" msgid "Voodoo Graphics" msgstr "Voodoo Graphics" +msgid "IBM 8514/a Graphics" +msgstr "IBM 8514/a Graphics" + +msgid "XGA Graphics" +msgstr "XGA Graphics" + msgid "Mouse:" msgstr "Ratón:" @@ -382,8 +409,17 @@ msgstr "Mando 3..." msgid "Joystick 4..." msgstr "Mando 4..." -msgid "Sound card:" -msgstr "Tarjeta de sonido:" +msgid "Sound card 1:" +msgstr "Tarjeta de sonido 1:" + +msgid "Sound card 2:" +msgstr "Tarjeta de sonido 2:" + +msgid "Sound card 3:" +msgstr "Tarjeta de sonido 3:" + +msgid "Sound card 4:" +msgstr "Tarjeta de sonido 4:" msgid "MIDI Out Device:" msgstr "Dispositivo MIDI de salida:" @@ -394,18 +430,18 @@ msgstr "Dispositivo MIDI de entrada:" msgid "Standalone MPU-401" msgstr "MPU-401 independiente" -msgid "Innovation SSI-2001" -msgstr "Innovation SSI-2001" - -msgid "CMS / Game Blaster" -msgstr "CMS / Game Blaster" - -msgid "Gravis Ultrasound" -msgstr "Gravis Ultrasound" - msgid "Use FLOAT32 sound" msgstr "Usar sonido FLOAT32" +msgid "FM synth driver" +msgstr "Controlador de sintet. FM" + +msgid "Nuked (more accurate)" +msgstr "Nuked (más preciso)" + +msgid "YMFM (faster)" +msgstr "YMFM (más rápido)" + msgid "Network type:" msgstr "Tipo de red:" @@ -550,6 +586,9 @@ msgstr "Chequear BPB" msgid "CD-ROM drives:" msgstr "Unidades de CD-ROM:" +msgid "Earlier drive" +msgstr "Unidad anterior" + msgid "MO drives:" msgstr "Unidades MO:" @@ -614,13 +653,13 @@ msgid "ZIP images" msgstr "Imagenes ZIP" msgid "86Box could not find any usable ROM images.\n\nPlease download a ROM set and extract it into the \"roms\" directory." -msgstr "86Box no pudo encontrar ninguna imagen ROM usable.\n\nPor favor descarga un grupo de imágenes y extráelas en el directorio \"roms\"." +msgstr "86Box no pudo encontrar ninguna imagen ROM usable.\n\nPor favor descargue un conjunte de ROMs y extráigalo en el directorio \"roms\"." msgid "(empty)" msgstr "(vacío)" msgid "All files" -msgstr "All files" +msgstr "Todos los archivos" msgid "Turbo" msgstr "Turbo" @@ -680,16 +719,13 @@ msgid "Other peripherals" msgstr "Otros periféricos" msgid "Click to capture mouse" -msgstr "Haz click para capturar el ratón" +msgstr "Haga click para capturar el ratón" msgid "Press F8+F12 to release mouse" -msgstr "Pulsa F8+F12 para liberar el ratón" +msgstr "Pulse F8+F12 para liberar el ratón" msgid "Press F8+F12 or middle button to release mouse" -msgstr "Pulsa F8+F12 o el botón central para liberar el ratón" - -msgid "Unable to initialize FluidSynth" -msgstr "Incapaz de inicializar FluidSynth" +msgstr "Pulse F8+F12 o el botón central para liberar el ratón" msgid "Bus" msgstr "Bus" @@ -710,7 +746,7 @@ msgid "KB" msgstr "KB" msgid "Could not initialize the video renderer." -msgstr "Incapaz de inicializar el renderizador de vídeo." +msgstr "No fué posible inicializar el renderizador de vídeo." msgid "Default" msgstr "Por defecto" @@ -755,10 +791,10 @@ msgid "None" msgstr "Ninguno" msgid "Unable to load keyboard accelerators." -msgstr "Incapaz de cargar aceleradores de teclado." +msgstr "No fué posible cargar aceleradores de teclado." msgid "Unable to register raw input." -msgstr "Incapaz de registrar entrada directa." +msgstr "No fué posible registrar entrada directa." msgid "%u" msgstr "%u" @@ -770,25 +806,22 @@ msgid "Floppy %i (%s): %ls" msgstr "Disquete %i (%s): %ls" msgid "Advanced sector images" -msgstr "Advanced sector images" +msgstr "Imágenes avanzadas de sector" msgid "Flux images" -msgstr "Flux images" - -msgid "Unable to initialize FreeType" -msgstr "Incapaz de inicializar FreeType" +msgstr "Imágenes de fluxo" msgid "Unable to initialize SDL, SDL2.dll is required" msgstr "Incapaz de inicializar SDL, se requiere SDL2.dll" msgid "Are you sure you want to hard reset the emulated machine?" -msgstr "¿Seguro que quieres resetear la máquina emulada?" +msgstr "¿Está seguro de que quieres hacer una reinicialización completa de la máquina emulada?" msgid "Are you sure you want to exit 86Box?" -msgstr "¿Seguro que quieres cerrar 86Box?" +msgstr "¿Está seguro de que quiere cerrar a 86Box?" msgid "Unable to initialize Ghostscript" -msgstr "Incapaz de inicializar Ghostscript" +msgstr "No fué posible inicializar Ghostscript" msgid "MO %i (%ls): %ls" msgstr "MO %i (%ls): %ls" @@ -809,10 +842,10 @@ msgid "No ROMs found" msgstr "No se encontraron ROMs" msgid "Do you want to save the settings?" -msgstr "¿Quieres guardar los ajustes?" +msgstr "¿Quiere guardar los configuraciones?" msgid "This will hard reset the emulated machine." -msgstr "Se hará hard reset de la máquina emulada." +msgstr "Se hará una reinicialización completa de la máquina emulada." msgid "Save" msgstr "Guardar" @@ -823,11 +856,11 @@ msgstr "Acerca de 86Box" msgid "86Box v" msgstr "86Box v" -msgid "An emulator of old computers\n\nAuthors: Sarah Walker, Miran Grca, Fred N. van Kempen (waltje), SA1988, Tiseno100, reenigne, leilei, JohnElliott, greatpsycho, and others.\n\nReleased under the GNU General Public License version 2 or later. See LICENSE for more information." -msgstr "Un emulador de ordenadores antigüos\n\nAutores: Sarah Walker, Miran Grca, Fred N. van Kempen (waltje), SA1988, Tiseno100, reenigne, leilei, JohnElliott, greatpsycho, y otros.\n\nLiberado bajo la GNU General Public License versión 2 o posterior. Ver LICENSE para más información." +msgid "An emulator of old computers\n\nAuthors: Miran GrÄa (OBattler), RichardG867, Jasmine Iwanek, TC1995, coldbrewed, Teemu Korhonen (Manaatti), Joakim L. Gilje, Adrien Moulin (elyosh), Daniel Balsom (gloriouscow), Cacodemon345, Fred N. van Kempen (waltje), Tiseno100, reenigne, and others.\n\nWith previous core contributions from Sarah Walker, leilei, JohnElliott, greatpsycho, and others.\n\nReleased under the GNU General Public License version 2 or later. See LICENSE for more information." +msgstr "Un emulador de ordenadores antigüos\n\nAutores: Miran GrÄa (OBattler), RichardG867, Jasmine Iwanek, TC1995, coldbrewed, Teemu Korhonen (Manaatti), Joakim L. Gilje, Adrien Moulin (elyosh), Daniel Balsom (gloriouscow), Cacodemon345, Fred N. van Kempen (waltje), Tiseno100, reenigne, y otros.\n\nWith previous core contributions from Sarah Walker, leilei, JohnElliott, greatpsycho, y otros.\n\nLiberado bajo la GNU General Public License versión 2 o posterior. Ver LICENSE para más información." msgid "Hardware not available" -msgstr "Hardware no disponible" +msgstr "Equipo no disponible" msgid "WinPcap" msgstr "WinPcap" @@ -841,15 +874,6 @@ msgstr "Asegúrate de que libpcap está instalado y de que estás en una conexi msgid "Invalid configuration" msgstr "Configuración inválida" -msgid "freetype.dll" -msgstr "freetype.dll" - -msgid "libfreetype" -msgstr "libfreetype" - -msgid " is required for ESC/P printer emulation." -msgstr " es necesaria para emulación de impresión ESC/P." - msgid "gsdll32.dll" msgstr "gsdll32.dll" @@ -859,15 +883,6 @@ msgstr "libgs" msgid " is required for automatic conversion of PostScript files to PDF.\n\nAny documents sent to the generic PostScript printer will be saved as PostScript (.ps) files." msgstr " es necesaria para la conversión automática de archivos PostScript a PDF.\n\nCualquier documento enviado a la impresora genérica postScript se guardará como archivo PostScript (.ps)." -msgid "libfluidsynth.dll" -msgstr "libfluidsynth.dll" - -msgid "libfluidsynth" -msgstr "libfluidsynth" - -msgid " is required for FluidSynth MIDI output." -msgstr " es necesario para salida MIDI FluidSynth." - msgid "Entering fullscreen mode" msgstr "Entrando en modo pantalla completa" @@ -878,10 +893,10 @@ msgid "Don't exit" msgstr "No salir" msgid "Reset" -msgstr "Resetear" +msgstr "Reinicializar" msgid "Don't reset" -msgstr "No resetear" +msgstr "No reinicializar" msgid "CD-ROM images" msgstr "Imágenes de CD-ROM" @@ -899,10 +914,10 @@ msgid "OpenGL options" msgstr "Opciones OpenGL" msgid "You are loading an unsupported configuration" -msgstr "Estás cargando una configuración no soportada" +msgstr "Está cargando una configuración no soportada" msgid "CPU type filtering based on selected machine is disabled for this emulated machine.\n\nThis makes it possible to choose a CPU that is otherwise incompatible with the selected machine. However, you may run into incompatibilities with the machine BIOS or other software.\n\nEnabling this setting is not officially supported and any bug reports filed may be closed as invalid." -msgstr "El Filtrado de tipo de CPU basado en máquina seleccionada está deshabilitado para la esta máquina.\n\nEsto hace posible seleccionar una CPU que sea incompatible con esta máquina. Por ello, pueden aparecer incompatibilidader con la BIOS de la máquina u otro software.\n\nActivar este ajuste no está oficialmente soportado y cualquier reporte de fallo puede ser cerrado como inválido." +msgstr "El Filtrado de tipo de CPU basado en máquina seleccionada está deshabilitado para la esta máquina.\n\nEsto hace posible seleccionar una CPU que sea incompatible con esta máquina. Por ello, pueden aparecer incompatibilidader con la BIOS de la máquina u otro software.\n\nActivar esta configuración no está oficialmente soportado y cualquier reporte de fallo puede ser cerrado como inválido." msgid "Continue" msgstr "Continuar" @@ -920,28 +935,28 @@ msgid "Cartridge images" msgstr "Imágenes de Cartucho" msgid "Error initializing renderer" -msgstr "Error initializing renderer" +msgstr "Error al inicializar el renderizador" msgid "OpenGL (3.0 Core) renderer could not be initialized. Use another renderer." -msgstr "OpenGL (3.0 Core) renderer could not be initialized. Use another renderer." +msgstr "No fué posible inicializar el renderizador OpenGL (3.0 Core). Utilice otro renderizador." msgid "Resume execution" -msgstr "Resume execution" +msgstr "Retomar la ejecución" msgid "Pause execution" -msgstr "Pause execution" +msgstr "Pausar la ejecución" msgid "Press Ctrl+Alt+Del" -msgstr "Press Ctrl+Alt+Del" +msgstr "Pulsar Ctrl+Alt+Supr" msgid "Press Ctrl+Alt+Esc" -msgstr "Press Ctrl+Alt+Esc" +msgstr "Pulsar Ctrl+Alt+Esc" msgid "Hard reset" msgstr "Hard reset" msgid "ACPI shutdown" -msgstr "ACPI shutdown" +msgstr "Parada ACPI" msgid "Hard disk (%s)" msgstr "Disco duro (%s)" @@ -953,7 +968,7 @@ msgid "%01i" msgstr "%01i" msgid "MFM/RLL or ESDI CD-ROM drives never existed" -msgstr "Nunca hubo unidades de CD-ROM MFM/RLL o ESDI" +msgstr "Nunca existieron unidades de CD-ROM MFM/RLL o ESDI" msgid "Custom..." msgstr "A medida..." @@ -1058,7 +1073,7 @@ msgid "Parent and child disk timestamps do not match" msgstr "Las marcas de tiempo del padre e hijo no coinciden" msgid "Could not fix VHD timestamp." -msgstr "No se pudo corregir la marca de tiempo del VHD." +msgstr "No fué posible corregir la marca de tiempo del VHD." msgid "%01i:%02i" msgstr "%01i:%02i" @@ -1183,3 +1198,29 @@ msgstr "2% por debajo de RPM perfectas" msgid "(System Default)" msgstr "(Por defecto del sistema)" +msgid "Failed to initialize network driver" +msgstr "No fué posible inicializar el controlador de red" + +msgid "The network configuration will be switched to the null driver" +msgstr "La configuración de red se cambiará al controlador nulo" + +msgid "Mouse sensitivity:" +msgstr "Sensibilidad del ratón:" + +msgid "Select media images from program working directory" +msgstr "Seleccionar imágenes de media del directorio de trabajo del programa" + +msgid "PIT mode:" +msgstr "Modalidad PIT:" + +msgid "Auto" +msgstr "Automática" + +msgid "Slow" +msgstr "Lenta" + +msgid "Fast" +msgstr "Rápida" + +msgid "&Auto-pause on focus loss" +msgstr "&Pausa automática al perder el foco" diff --git a/src/qt/languages/fi-FI.po b/src/qt/languages/fi-FI.po index c243c83cb..217827f74 100644 --- a/src/qt/languages/fi-FI.po +++ b/src/qt/languages/fi-FI.po @@ -29,7 +29,7 @@ msgid "&Hide status bar" msgstr "&Piilota tilapalkki" msgid "Hide &toolbar" -msgstr "Hide &toolbar" +msgstr "Piilota &työkalupalkki" msgid "&Resizeable window" msgstr "&Salli koon muuttaminen" @@ -59,7 +59,7 @@ msgid "Specify dimensions..." msgstr "&Määritä koko..." msgid "F&orce 4:3 display ratio" -msgstr "Pakota 4:3 näyttösuhde" +msgstr "Pakota 4:3-näyttösuhde" msgid "&Window scale factor" msgstr "&Ikkunan kokokerroin" @@ -76,6 +76,24 @@ msgstr "1.&5x" msgid "&2x" msgstr "&2x" +msgid "&3x" +msgstr "&3x" + +msgid "&4x" +msgstr "&4x" + +msgid "&5x" +msgstr "&5x" + +msgid "&6x" +msgstr "&6x" + +msgid "&7x" +msgstr "&7x" + +msgid "&8x" +msgstr "&8x" + msgid "Filter method" msgstr "&Suodatusmetodi" @@ -106,20 +124,23 @@ msgstr "&Tasasivuiset kuvapisteet (säilytä kuvasuhde)" msgid "&Integer scale" msgstr "&Kokonaislukuskaalaus" +msgid "4:&3 Integer scale" +msgstr "4:&3 Kokonaislukuskaalaus" + msgid "E&GA/(S)VGA settings" -msgstr "&EGA/(S)VGA asetukset" +msgstr "&EGA/(S)VGA-asetukset" msgid "&Inverted VGA monitor" -msgstr "&VGA näyttö käänteisillä väreillä" +msgstr "&VGA-näyttö käänteisillä väreillä" msgid "VGA screen &type" -msgstr "VGA näytön &tyyppi" +msgstr "VGA-näytön &tyyppi" msgid "RGB &Color" -msgstr "RGB &värit" +msgstr "RGB, &värit" msgid "&RGB Grayscale" -msgstr "&RGB harmaasävyinen" +msgstr "&RGB, harmaasävy" msgid "&Amber monitor" msgstr "&Meripihkanvärinen" @@ -152,7 +173,7 @@ msgid "&Media" msgstr "&Media" msgid "&Tools" -msgstr "&Työkalut" +msgstr "Työ&kalut" msgid "&Settings..." msgstr "&Kokoonpano..." @@ -167,10 +188,10 @@ msgid "&Preferences..." msgstr "&Sovellusasetukset..." msgid "Enable &Discord integration" -msgstr "Käytä &Discord integraatiota" +msgstr "Käytä &Discord-integraatiota" msgid "Sound &gain..." -msgstr "&Äänen tulotaso..." +msgstr "&Äänitasot..." msgid "Begin trace\tCtrl+T" msgstr "Aloita jäljitys\tCtrl+T" @@ -182,10 +203,10 @@ msgid "&Help" msgstr "&Ohje" msgid "&Documentation..." -msgstr "&Dokumentaatio..." +msgstr "&Ohjekirja..." msgid "&About 86Box..." -msgstr "&Tietoja 86Box:sta..." +msgstr "&Tietoja 86Boxista..." msgid "&New image..." msgstr "&Uusi kasettikuva..." @@ -226,8 +247,8 @@ msgstr "&Tyhjä" msgid "&Reload previous image" msgstr "&Lataa edellinen levykuva uudelleen" -msgid "&Image" -msgstr "L&evykuva" +msgid "&Folder..." +msgstr "&Kansio..." msgid "Target &framerate" msgstr "&Kuvataajuustavoite" @@ -263,7 +284,7 @@ msgid "Preferences" msgstr "Sovellusasetukset" msgid "Sound Gain" -msgstr "Äänen tulotaso" +msgstr "Äänen taso" msgid "New Image" msgstr "Uusi levykuva" @@ -302,7 +323,7 @@ msgid "Disk size:" msgstr "Levyn koko:" msgid "RPM mode:" -msgstr "RPM tila:" +msgstr "Kierroslukutila:" msgid "Progress:" msgstr "Edistyminen:" @@ -364,6 +385,12 @@ msgstr "Näytönohjain:" msgid "Voodoo Graphics" msgstr "Voodoo-grafiikkasuoritin" +msgid "IBM 8514/a Graphics" +msgstr "IBM 8514/a-grafiikkasuoritin" + +msgid "XGA Graphics" +msgstr "XGA-grafiikkasuoritin" + msgid "Mouse:" msgstr "Hiiri:" @@ -382,8 +409,17 @@ msgstr "Peliohjain 3..." msgid "Joystick 4..." msgstr "Peliohjain 4..." -msgid "Sound card:" -msgstr "Äänikortti:" +msgid "Sound card 1:" +msgstr "Äänikortti 1:" + +msgid "Sound card 2:" +msgstr "Äänikortti 2:" + +msgid "Sound card 3:" +msgstr "Äänikortti 3:" + +msgid "Sound card 4:" +msgstr "Äänikortti 4:" msgid "MIDI Out Device:" msgstr "MIDI-ulostulo:" @@ -394,18 +430,18 @@ msgstr "MIDI-sisääntulo:" msgid "Standalone MPU-401" msgstr "Erillinen MPU-401" -msgid "Innovation SSI-2001" -msgstr "Innovation SSI-2001" - -msgid "CMS / Game Blaster" -msgstr "CMS / Game Blaster" - -msgid "Gravis Ultrasound" -msgstr "Gravis Ultrasound" - msgid "Use FLOAT32 sound" msgstr "Käytä FLOAT32-ääntä" +msgid "FM synth driver" +msgstr "FM-syntetisaattoriohjain" + +msgid "Nuked (more accurate)" +msgstr "Nuked (tarkempi)" + +msgid "YMFM (faster)" +msgstr "YMFM (nopeampi)" + msgid "Network type:" msgstr "Verkon tyyppi:" @@ -470,10 +506,10 @@ msgid "FD Controller:" msgstr "Levykeohjain:" msgid "Tertiary IDE Controller" -msgstr "Tertinäärinen IDE-ohjain" +msgstr "Kolmas IDE-ohjain" msgid "Quaternary IDE Controller" -msgstr "Kvaternaarinen IDE-ohjain" +msgstr "Neljäs IDE-ohjain" msgid "SCSI" msgstr "SCSI" @@ -521,7 +557,7 @@ msgid "Sectors:" msgstr "Sektorit:" msgid "Heads:" -msgstr "Päät:" +msgstr "Lukupäät:" msgid "Cylinders:" msgstr "Sylinterit:" @@ -550,6 +586,9 @@ msgstr "Tarkista BPB" msgid "CD-ROM drives:" msgstr "CD-ROM-asemat:" +msgid "Earlier drive" +msgstr "Aiemmat asemat" + msgid "MO drives:" msgstr "Magneettisoptiset asemat (MO):" @@ -599,7 +638,7 @@ msgid "Fatal error" msgstr "Vakava virhe" msgid " - PAUSED" -msgstr " - PAUSED" +msgstr " - TAUKO" msgid "Press Ctrl+Alt+PgDn to return to windowed mode." msgstr "Paina Ctrl+Alt+PgDn palataksesi ikkunoituun tilaan." @@ -614,7 +653,7 @@ msgid "ZIP images" msgstr "ZIP-levykuvat" msgid "86Box could not find any usable ROM images.\n\nPlease download a ROM set and extract it into the \"roms\" directory." -msgstr "86Box ei löytänyt käyttökelpoisia ROM-tiedostoja.\n\nVoit ladata ROM-paketin ja purkaa sen \"roms\" hakemistoon." +msgstr "86Box ei löytänyt käyttökelpoisia ROM-tiedostoja.\n\nVoit ladata ROM-paketin ja purkaa sen \"roms\"-hakemistoon." msgid "(empty)" msgstr "(tyhjä)" @@ -688,9 +727,6 @@ msgstr "Paina F8+F12 vapauttaaksesi hiiren" msgid "Press F8+F12 or middle button to release mouse" msgstr "Paina F8+F12 tai keskipainiketta vapauttaaksesi hiiren" -msgid "Unable to initialize FluidSynth" -msgstr "FluidSynth:in alustus epäonnistui" - msgid "Bus" msgstr "Väylä" @@ -710,7 +746,7 @@ msgid "KB" msgstr "kt" msgid "Could not initialize the video renderer." -msgstr "Video-renderöijän alustus epäonnistui" +msgstr "Videorenderöijän alustus epäonnistui" msgid "Default" msgstr "Oletus" @@ -775,20 +811,17 @@ msgstr "Kehittyneet sektorilevykuvat" msgid "Flux images" msgstr "Flux-levykuvat" -msgid "Unable to initialize FreeType" -msgstr "FreeType:n alustus epäonnistui" - msgid "Unable to initialize SDL, SDL2.dll is required" msgstr "SDL:n alustus epäonnistui. Tarvitaan SDL2.dll" msgid "Are you sure you want to hard reset the emulated machine?" -msgstr "Oletko varma, että haluat käynnistää emuloidun tietokoneen uudelleen?" +msgstr "Haluatko varmasti käynnistää emuloidun tietokoneen uudelleen?" msgid "Are you sure you want to exit 86Box?" -msgstr "Haluatko varmasti sulkea 86Box:in?" +msgstr "Haluatko varmasti sulkea 86Boxin?" msgid "Unable to initialize Ghostscript" -msgstr "Ghostscript:in alustus epäonnistui" +msgstr "Ghostscriptin alustus epäonnistui" msgid "MO %i (%ls): %ls" msgstr "MO %i (%ls): %ls" @@ -797,7 +830,7 @@ msgid "MO images" msgstr "MO-levykuvat" msgid "Welcome to 86Box!" -msgstr "Tervetuloa 86Box:iin!" +msgstr "Tervetuloa 86Boxiin!" msgid "Internal controller" msgstr "Sisäinen ohjain" @@ -823,8 +856,8 @@ msgstr "Tietoja 86Box:sta" msgid "86Box v" msgstr "86Box v" -msgid "An emulator of old computers\n\nAuthors: Sarah Walker, Miran Grca, Fred N. van Kempen (waltje), SA1988, Tiseno100, reenigne, leilei, JohnElliott, greatpsycho, and others.\n\nReleased under the GNU General Public License version 2 or later. See LICENSE for more information." -msgstr "Vanhojen tietokoneiden emulaattori\n\nTekijät: Sarah Walker, Miran Grca, Fred N. van Kempen (waltje), SA1988, Tiseno100, reenigne, leilei, JohnElliott, greatpsycho ja muut.\n\nJulkaistu GNU General Public License 2. version tai myöhemmän alaisena. Tarkempia tietoja LICENSE-tiedostossa." +msgid "An emulator of old computers\n\nAuthors: Miran GrÄa (OBattler), RichardG867, Jasmine Iwanek, TC1995, coldbrewed, Teemu Korhonen (Manaatti), Joakim L. Gilje, Adrien Moulin (elyosh), Daniel Balsom (gloriouscow), Cacodemon345, Fred N. van Kempen (waltje), Tiseno100, reenigne, and others.\n\nWith previous core contributions from Sarah Walker, leilei, JohnElliott, greatpsycho, and others.\n\nReleased under the GNU General Public License version 2 or later. See LICENSE for more information." +msgstr "Vanhojen tietokoneiden emulaattori\n\nTekijät: Miran GrÄa (OBattler), RichardG867, Jasmine Iwanek, TC1995, coldbrewed, Teemu Korhonen (Manaatti), Joakim L. Gilje, Adrien Moulin (elyosh), Daniel Balsom (gloriouscow), Cacodemon345, Fred N. van Kempen (waltje), Tiseno100, reenigne ja muut.\n\nWith previous core contributions from Sarah Walker, leilei, JohnElliott, greatpsycho ja muut.\n\nJulkaistu GNU General Public License 2. version tai myöhemmän alaisena. Tarkempia tietoja LICENSE-tiedostossa." msgid "Hardware not available" msgstr "Laitteisto ei ole saatavilla" @@ -841,15 +874,6 @@ msgstr "Varmista, että libpcap on asennettu ja että verkkoyhteytesi on libpcap msgid "Invalid configuration" msgstr "Virheelliset määritykset" -msgid "freetype.dll" -msgstr "freetype.dll" - -msgid "libfreetype" -msgstr "libfreetype" - -msgid " is required for ESC/P printer emulation." -msgstr " vaaditaan ESC/P-tulostimen emuloimiseksi." - msgid "gsdll32.dll" msgstr "gsdll32.dll" @@ -859,15 +883,6 @@ msgstr "libgs" msgid " is required for automatic conversion of PostScript files to PDF.\n\nAny documents sent to the generic PostScript printer will be saved as PostScript (.ps) files." msgstr " vaaditaan PostScript-tiedostojen automaattiseen muuntamiseen PDF-tiedostoiksi.\n\nKaikki geneeriselle PostScript-tulostimelle lähetetyt asiakirjat tallennetaan PostScript (.ps) -tiedostoina." -msgid "libfluidsynth.dll" -msgstr "libfluidsynth.dll" - -msgid "libfluidsynth" -msgstr "libfluidsynth" - -msgid " is required for FluidSynth MIDI output." -msgstr " vaaditaan FluidSynth MIDI-ulostuloa varten." - msgid "Entering fullscreen mode" msgstr "Siirrytään koko näytön tilaan" @@ -911,7 +926,7 @@ msgid "Cassette: %s" msgstr "Kasetti: %s" msgid "Cassette images" -msgstr "Kasetti-tiedostot" +msgstr "Kasettitiedostot" msgid "Cartridge %i: %ls" msgstr "ROM-moduuli %i: %ls" @@ -923,25 +938,25 @@ msgid "Error initializing renderer" msgstr "Virhe renderöijän alustuksessa" msgid "OpenGL (3.0 Core) renderer could not be initialized. Use another renderer." -msgstr "OpenGL (3.0 Core) renderöijän alustus epäonnistui. Käytä toista renderöijää." +msgstr "OpenGL (3.0 Core) -renderöijän alustus epäonnistui. Käytä toista renderöijää." msgid "Resume execution" -msgstr "Resume execution" +msgstr "Jatka suoritusta" msgid "Pause execution" -msgstr "Pause execution" +msgstr "Pysäytä suoritus" msgid "Press Ctrl+Alt+Del" -msgstr "Press Ctrl+Alt+Del" +msgstr "Paina Ctrl+Alt+Del" msgid "Press Ctrl+Alt+Esc" -msgstr "Press Ctrl+Alt+Esc" +msgstr "Paina Ctrl+Alt+Esc" msgid "Hard reset" -msgstr "Hard reset" +msgstr "Kylmä uudelleenkäynnistys" msgid "ACPI shutdown" -msgstr "ACPI shutdown" +msgstr "ACPI-sammutus" msgid "Hard disk (%s)" msgstr "Kiintolevy (%s)" @@ -953,7 +968,7 @@ msgid "%01i" msgstr "%01i" msgid "MFM/RLL or ESDI CD-ROM drives never existed" -msgstr "MFM/RLL tai ESDI CD-ROM asemia ei ole koskaan ollut olemassa" +msgstr "MFM/RLL- tai ESDI-CD-ROM-asemia ei ole koskaan ollut olemassa" msgid "Custom..." msgstr "Mukautettu..." @@ -968,7 +983,7 @@ msgid "Add Existing Hard Disk" msgstr "Lisää olemassaoleva kiintolevy" msgid "HDI disk images cannot be larger than 4 GB." -msgstr "HDI levykuvan suurin mahdollinen koko on 4 Gt." +msgstr "HDI-levykuvan suurin mahdollinen koko on 4 Gt." msgid "Disk images cannot be larger than 127 GB." msgstr "Levykuvien suurin mahdollinen koko on 127 Gt." @@ -1010,16 +1025,16 @@ msgid "Remember to partition and format the newly-created drive." msgstr "Muista osioida ja alustaa juuri luomasi asema." msgid "The selected file will be overwritten. Are you sure you want to use it?" -msgstr "Valittu tiedosto ylikirjoitetaan. Oletko varma, että haluat käyttää sitä?" +msgstr "Valittu tiedosto korvataan. Oletko varma, että haluat käyttää sitä?" msgid "Unsupported disk image" -msgstr "Levynkuvaa ei tueta" +msgstr "Levykuvaa ei tueta" msgid "Overwrite" -msgstr "Ylikirjoita" +msgstr "Korvaa" msgid "Don't overwrite" -msgstr "Älä ylikirjoita" +msgstr "Älä korvaa" msgid "Raw image (.img)" msgstr "Raaka levykuva (.img)" @@ -1183,3 +1198,29 @@ msgstr "2% alle täydellisen RPM:n" msgid "(System Default)" msgstr "(Järjestelmän oletus)" +msgid "Failed to initialize network driver" +msgstr "Verkkoajurin alustaminen epäonnistui" + +msgid "The network configuration will be switched to the null driver" +msgstr "Verkkokokoonpano vaihtuu nolla-ajuriin" + +msgid "Mouse sensitivity:" +msgstr "Hiiren herkkyys:" + +msgid "Select media images from program working directory" +msgstr "Valitse mediakuvat ohjelman työhakemistosta" + +msgid "PIT mode:" +msgstr "PIT-tila:" + +msgid "Auto" +msgstr "Automaattinen" + +msgid "Slow" +msgstr "Hidas" + +msgid "Fast" +msgstr "Nopea" + +msgid "&Auto-pause on focus loss" +msgstr "&Automaattinen tauko tarkennuksen hävitessä" diff --git a/src/qt/languages/fr-FR.po b/src/qt/languages/fr-FR.po index 7fa029045..be66e5924 100644 --- a/src/qt/languages/fr-FR.po +++ b/src/qt/languages/fr-FR.po @@ -76,6 +76,24 @@ msgstr "1.&5x" msgid "&2x" msgstr "&2x" +msgid "&3x" +msgstr "&3x" + +msgid "&4x" +msgstr "&4x" + +msgid "&5x" +msgstr "&5x" + +msgid "&6x" +msgstr "&6x" + +msgid "&7x" +msgstr "&7x" + +msgid "&8x" +msgstr "&8x" + msgid "Filter method" msgstr "Methode Filtre" @@ -106,6 +124,9 @@ msgstr "pixels &Carrés(Keep ratio)" msgid "&Integer scale" msgstr "Echelle &Entière" +msgid "4:&3 Integer scale" +msgstr "Echelle Entière 4:&3" + msgid "E&GA/(S)VGA settings" msgstr "Réglages E&GA/(S)VGA" @@ -226,8 +247,8 @@ msgstr "E&jecter" msgid "&Reload previous image" msgstr "&Recharger image précedente" -msgid "&Image" -msgstr "&Image" +msgid "&Folder..." +msgstr "&Dossier..." msgid "Target &framerate" msgstr "&Taux de rafraîchissement cible" @@ -364,6 +385,12 @@ msgstr "Vidéo:" msgid "Voodoo Graphics" msgstr "Graphique Voodoo" +msgid "IBM 8514/a Graphics" +msgstr "Graphique IBM 8514/a" + +msgid "XGA Graphics" +msgstr "Graphique XGA" + msgid "Mouse:" msgstr "Souris:" @@ -382,8 +409,17 @@ msgstr "Manette 3..." msgid "Joystick 4..." msgstr "Manette 4..." -msgid "Sound card:" -msgstr "Carte son:" +msgid "Sound card 1:" +msgstr "Carte son 1:" + +msgid "Sound card 2:" +msgstr "Carte son 2:" + +msgid "Sound card 3:" +msgstr "Carte son 3:" + +msgid "Sound card 4:" +msgstr "Carte son 4:" msgid "MIDI Out Device:" msgstr "Sortie MIDI:" @@ -394,18 +430,18 @@ msgstr "Entrée MIDI:" msgid "Standalone MPU-401" msgstr "MPU-401 autonome" -msgid "Innovation SSI-2001" -msgstr "Innovation SSI-2001" - -msgid "CMS / Game Blaster" -msgstr "CMS / Game Blaster" - -msgid "Gravis Ultrasound" -msgstr "Gravis Ultrasound" - msgid "Use FLOAT32 sound" msgstr "Utiliser le son FLOAT32" +msgid "FM synth driver" +msgstr "Pilote de synthétiseur FM" + +msgid "Nuked (more accurate)" +msgstr "Nuked (plus précis)" + +msgid "YMFM (faster)" +msgstr "YMFM (plus rapide)" + msgid "Network type:" msgstr "Type de réseau:" @@ -550,6 +586,9 @@ msgstr "Vérifier BPB" msgid "CD-ROM drives:" msgstr "Lecterus CD-ROM:" +msgid "Earlier drive" +msgstr "Lecteur plus tôt" + msgid "MO drives:" msgstr "Lecteurs magnéto-optiques:" @@ -688,9 +727,6 @@ msgstr "Appuyer sur F8+F12 pour libérer la souris" msgid "Press F8+F12 or middle button to release mouse" msgstr "Appuyer sur F8+F12 ou le bouton central pour libérer la souris" -msgid "Unable to initialize FluidSynth" -msgstr "Impossible d'initialiser FluidSynth" - msgid "Bus" msgstr "Bus" @@ -775,9 +811,6 @@ msgstr "Images du secteur avancés" msgid "Flux images" msgstr "Images du flux" -msgid "Unable to initialize FreeType" -msgstr "Impossible d'initialiser FreeType" - msgid "Unable to initialize SDL, SDL2.dll is required" msgstr "Impossible d'initialiser SDL, SDL2.dll est nécessaire" @@ -823,8 +856,8 @@ msgstr "À propos de 86Box" msgid "86Box v" msgstr "86Box v" -msgid "An emulator of old computers\n\nAuthors: Sarah Walker, Miran Grca, Fred N. van Kempen (waltje), SA1988, Tiseno100, reenigne, leilei, JohnElliott, greatpsycho, and others.\n\nReleased under the GNU General Public License version 2 or later. See LICENSE for more information." -msgstr "Un émulateur de vieux ordinateurs\n\nAuteurs: Sarah Walker, Miran Grca, Fred N. van Kempen (waltje), SA1988, Tiseno100, reenigne, leilei, JohnElliott, greatpsycho, and others.\n\nLibéré sous la licence GNU General Public License version 2 ou ultérieure. Pour plus d'informations, voir le fichier LICENSE." +msgid "An emulator of old computers\n\nAuthors: Miran GrÄa (OBattler), RichardG867, Jasmine Iwanek, TC1995, coldbrewed, Teemu Korhonen (Manaatti), Joakim L. Gilje, Adrien Moulin (elyosh), Daniel Balsom (gloriouscow), Cacodemon345, Fred N. van Kempen (waltje), Tiseno100, reenigne, and others.\n\nWith previous core contributions from Sarah Walker, leilei, JohnElliott, greatpsycho, and others.\n\nReleased under the GNU General Public License version 2 or later. See LICENSE for more information." +msgstr "Un émulateur de vieux ordinateurs\n\nAuteurs: Miran GrÄa (OBattler), RichardG867, Jasmine Iwanek, TC1995, coldbrewed, Teemu Korhonen (Manaatti), Joakim L. Gilje, Adrien Moulin (elyosh), Daniel Balsom (gloriouscow), Cacodemon345, Fred N. van Kempen (waltje), Tiseno100, reenigne, and others.\n\nWith previous core contributions from Sarah Walker, leilei, JohnElliott, greatpsycho, and others.\n\nLibéré sous la licence GNU General Public License version 2 ou ultérieure. Pour plus d'informations, voir le fichier LICENSE." msgid "Hardware not available" msgstr "Matériel non disponible" @@ -841,15 +874,6 @@ msgstr "Assurez-vous que libpcap est installé et que vou utilisez une connexion msgid "Invalid configuration" msgstr "Configuration non valide" -msgid "freetype.dll" -msgstr "freetype.dll" - -msgid "libfreetype" -msgstr "libfreetype" - -msgid " is required for ESC/P printer emulation." -msgstr " est nécessaire pour l'émulation de l'imprimante ESC/P." - msgid "gsdll32.dll" msgstr "gsdll32.dll" @@ -859,15 +883,6 @@ msgstr "libgs" msgid " is required for automatic conversion of PostScript files to PDF.\n\nAny documents sent to the generic PostScript printer will be saved as PostScript (.ps) files." msgstr " est nécessair pour la conversion automatique des fichiers PostScript dans PDF.\n\nTous les documents envoyés à l'imprimante générique PostScript seront sauvés comme des fichiers PostScript (.ps)." -msgid "libfluidsynth.dll" -msgstr "libfluidsynth.dll" - -msgid "libfluidsynth" -msgstr "libfluidsynth" - -msgid " is required for FluidSynth MIDI output." -msgstr " est nécessaire pour la sortie MIDI FluidSynth." - msgid "Entering fullscreen mode" msgstr "Entrer en mode plein écran" @@ -920,28 +935,28 @@ msgid "Cartridge images" msgstr "Images cartouche" msgid "Error initializing renderer" -msgstr "Error initializing renderer" +msgstr "Erreur d'initialisation du moteur de rendu" msgid "OpenGL (3.0 Core) renderer could not be initialized. Use another renderer." -msgstr "OpenGL (3.0 Core) renderer could not be initialized. Use another renderer." +msgstr "Le moteur de rendu OpenGL (3.0 Core) n'a pas pu être initialisé. Utilisez un autre moteur de rendu." msgid "Resume execution" -msgstr "Resume execution" +msgstr "Reprendre l'exécution" msgid "Pause execution" -msgstr "Pause execution" +msgstr "Pause de l'exécution" msgid "Press Ctrl+Alt+Del" -msgstr "Press Ctrl+Alt+Del" +msgstr "Appuyer sur Ctrl+Alt+Suppr." msgid "Press Ctrl+Alt+Esc" -msgstr "Press Ctrl+Alt+Esc" +msgstr "Appuyer sur Ctrl+Alt+Esc" msgid "Hard reset" msgstr "Hard reset" msgid "ACPI shutdown" -msgstr "ACPI shutdown" +msgstr "Arrêt ACPI" msgid "Hard disk (%s)" msgstr "Disque dur (%s)" @@ -1183,3 +1198,30 @@ msgstr "Précision RPM de moins 2%" msgid "(System Default)" msgstr "(Défaut du système)" +msgid "Failed to initialize network driver" +msgstr "Échec de l'initialisation du pilote réseau" + +msgid "The network configuration will be switched to the null driver" +msgstr "La configuration du réseau passera au pilote nul" + +msgid "Mouse sensitivity:" +msgstr "Sensibilité de la souris:" + +msgid "Select media images from program working directory" +msgstr "Sélectionner des images dans le répertoire de travail du programme" + +msgid "PIT mode:" +msgstr "Mode PIT:" + +msgid "Auto" +msgstr "Auto" + +msgid "Slow" +msgstr "Lent" + +msgid "Fast" +msgstr "Rapide" + +msgid "&Auto-pause on focus loss" +msgstr "&Pause automatique à perte de mise au point" + diff --git a/src/qt/languages/hr-HR.po b/src/qt/languages/hr-HR.po index 1d3ab11a2..b2aa40d28 100644 --- a/src/qt/languages/hr-HR.po +++ b/src/qt/languages/hr-HR.po @@ -76,6 +76,24 @@ msgstr "1,&5x" msgid "&2x" msgstr "&2x" +msgid "&3x" +msgstr "&3x" + +msgid "&4x" +msgstr "&4x" + +msgid "&5x" +msgstr "&5x" + +msgid "&6x" +msgstr "&6x" + +msgid "&7x" +msgstr "&7x" + +msgid "&8x" +msgstr "&8x" + msgid "Filter method" msgstr "Metoda filtriranja" @@ -106,6 +124,9 @@ msgstr "&Kvadratni pikseli (zadrži omjer)" msgid "&Integer scale" msgstr "&Cijelobrojno skaliranje" +msgid "4:&3 Integer scale" +msgstr "4:&3 Cijelobrojno skaliranje" + msgid "E&GA/(S)VGA settings" msgstr "E&GA/(S)VGA postavke" @@ -226,8 +247,8 @@ msgstr "&Prazno" msgid "&Reload previous image" msgstr "&Ponovo uÄitaj prethodnu sliku" -msgid "&Image" -msgstr "&Slika" +msgid "&Folder..." +msgstr "&Mapa..." msgid "Target &framerate" msgstr "&Ciljni broj okvira u sekundi" @@ -364,6 +385,12 @@ msgstr "Video:" msgid "Voodoo Graphics" msgstr "Voodoo grafika" +msgid "IBM 8514/a Graphics" +msgstr "IBM 8514/a grafika" + +msgid "XGA Graphics" +msgstr "XGA grafika" + msgid "Mouse:" msgstr "MiÅ¡:" @@ -382,8 +409,17 @@ msgstr "Palica za igru 3..." msgid "Joystick 4..." msgstr "Palica za igru 4..." -msgid "Sound card:" -msgstr "ZvuÄna kartica:" +msgid "Sound card 1:" +msgstr "ZvuÄna kartica 1:" + +msgid "Sound card 2:" +msgstr "ZvuÄna kartica 2:" + +msgid "Sound card 3:" +msgstr "ZvuÄna kartica 3:" + +msgid "Sound card 4:" +msgstr "ZvuÄna kartica 4:" msgid "MIDI Out Device:" msgstr "Izlazni ureÄ‘aj MIDI:" @@ -394,18 +430,18 @@ msgstr "Ulazni ureÄ‘aj MIDI:" msgid "Standalone MPU-401" msgstr "Samostalni MPU-401" -msgid "Innovation SSI-2001" -msgstr "Innovation SSI-2001" - -msgid "CMS / Game Blaster" -msgstr "CMS / Game Blaster" - -msgid "Gravis Ultrasound" -msgstr "Gravis Ultrasound" - msgid "Use FLOAT32 sound" msgstr "Koristi FLOAT32 za zvuk" +msgid "FM synth driver" +msgstr "Drajver za FM sintisajzer" + +msgid "Nuked (more accurate)" +msgstr "Nuked (precizniji)" + +msgid "YMFM (faster)" +msgstr "YMFM (brži)" + msgid "Network type:" msgstr "Tip mreže:" @@ -550,6 +586,9 @@ msgstr "Provjeraj BPB" msgid "CD-ROM drives:" msgstr "CD-ROM pogoni:" +msgid "Earlier drive" +msgstr "Raniji pogon" + msgid "MO drives:" msgstr "MO pogoni:" @@ -688,9 +727,6 @@ msgstr "Pritisnite F8+F12 za otpustanje miÅ¡a" msgid "Press F8+F12 or middle button to release mouse" msgstr "Pritisnite F8+F12 ili srednji gumb miÅ¡a za otpuÅ¡tanje miÅ¡a" -msgid "Unable to initialize FluidSynth" -msgstr "Nije moguće inicijalizirati FluidSynth" - msgid "Bus" msgstr "Bus" @@ -775,9 +811,6 @@ msgstr "Napredne sektorske slike" msgid "Flux images" msgstr "Flux slike" -msgid "Unable to initialize FreeType" -msgstr "Nije moguće inicijalizirati FreeType" - msgid "Unable to initialize SDL, SDL2.dll is required" msgstr "Nije moguće inicijalizirati SDL, SDL2.dll je potrebno" @@ -823,8 +856,8 @@ msgstr "O programu 86Box" msgid "86Box v" msgstr "86Box verzija " -msgid "An emulator of old computers\n\nAuthors: Sarah Walker, Miran Grca, Fred N. van Kempen (waltje), SA1988, Tiseno100, reenigne, leilei, JohnElliott, greatpsycho, and others.\n\nReleased under the GNU General Public License version 2 or later. See LICENSE for more information." -msgstr "Emulator starih raÄunala\n\nAutori: Sarah Walker, Miran Grca, Fred N. van Kempen (waltje), SA1988, Tiseno100, reenigne, leilei, JohnElliott, greatpsycho, i drugi.\n\nPreveo: dob205\n\nObjavljeno pod licencom GNU General Public License, verzija 2 ili novije. Za viÅ¡e informacija pogledajte datoteku LICENCE." +msgid "An emulator of old computers\n\nAuthors: Miran GrÄa (OBattler), RichardG867, Jasmine Iwanek, TC1995, coldbrewed, Teemu Korhonen (Manaatti), Joakim L. Gilje, Adrien Moulin (elyosh), Daniel Balsom (gloriouscow), Cacodemon345, Fred N. van Kempen (waltje), Tiseno100, reenigne, and others.\n\nWith previous core contributions from Sarah Walker, leilei, JohnElliott, greatpsycho, and others.\n\nReleased under the GNU General Public License version 2 or later. See LICENSE for more information." +msgstr "Emulator starih raÄunala\n\nAutori: Miran GrÄa (OBattler), RichardG867, Jasmine Iwanek, TC1995, coldbrewed, Teemu Korhonen (Manaatti), Joakim L. Gilje, Adrien Moulin (elyosh), Daniel Balsom (gloriouscow), Cacodemon345, Fred N. van Kempen (waltje), Tiseno100, reenigne, i drugi.\n\nWith previous core contributions from Sarah Walker, leilei, JohnElliott, greatpsycho, i drugi.\n\nPreveo: dob205\n\nObjavljeno pod licencom GNU General Public License, verzija 2 ili novije. Za viÅ¡e informacija pogledajte datoteku LICENCE." msgid "Hardware not available" msgstr "Hardver nije dostupan" @@ -841,15 +874,6 @@ msgstr "Provjerite je li libpcap instaliran i jeste li na mreži, kompadibilnoj msgid "Invalid configuration" msgstr "Nevažeća konfiguracija" -msgid "freetype.dll" -msgstr "freetype.dll" - -msgid "libfreetype" -msgstr "libfreetype" - -msgid " is required for ESC/P printer emulation." -msgstr " je potrebno za emuliranje ESC/P pisaÄa." - msgid "gsdll32.dll" msgstr "gsdll32.dll" @@ -859,15 +883,6 @@ msgstr "libgs" msgid " is required for automatic conversion of PostScript files to PDF.\n\nAny documents sent to the generic PostScript printer will be saved as PostScript (.ps) files." msgstr " je potrebno za automatsku konverziju PostScript datoteke u PDF datoteke.\n\nSvi dokumenti poslani na generiÄki PostScript pisaÄ bit će spremljeni kao PostScript (.ps) datoteke." -msgid "libfluidsynth.dll" -msgstr "libfluidsynth.dll" - -msgid "libfluidsynth" -msgstr "libfluidsynth" - -msgid " is required for FluidSynth MIDI output." -msgstr " je potrebno za FluidSynth MIDI izlaz." - msgid "Entering fullscreen mode" msgstr "Ulazim u cijelozaslonski naÄin" @@ -1183,3 +1198,29 @@ msgstr "2% ispod savrÅ¡enog broja okretaja" msgid "(System Default)" msgstr "(Zadana postavka operativnog sustava)" +msgid "Failed to initialize network driver" +msgstr "NeuspjeÅ¡no pokretanje mrežnog upravljaÄkog programa" + +msgid "The network configuration will be switched to the null driver" +msgstr "Konfiguracija mreže bit će prebaÄena na nulti upravljaÄki program" + +msgid "Mouse sensitivity:" +msgstr "Osjetljivost miÅ¡a:" + +msgid "Select media images from program working directory" +msgstr "Medijske slike su odabrane iz radnog direktorija programa" + +msgid "PIT mode:" +msgstr "PIT naÄin:" + +msgid "Auto" +msgstr "Auto" + +msgid "Slow" +msgstr "Spori" + +msgid "Fast" +msgstr "Brzi" + +msgid "&Auto-pause on focus loss" +msgstr "&Automatska pauza pri gubitku fokusa" diff --git a/src/qt/languages/hu-HU.po b/src/qt/languages/hu-HU.po index 716ad22fc..352a64749 100644 --- a/src/qt/languages/hu-HU.po +++ b/src/qt/languages/hu-HU.po @@ -76,6 +76,24 @@ msgstr "1,&5x" msgid "&2x" msgstr "&2x" +msgid "&3x" +msgstr "&3x" + +msgid "&4x" +msgstr "&4x" + +msgid "&5x" +msgstr "&5x" + +msgid "&6x" +msgstr "&6x" + +msgid "&7x" +msgstr "&7x" + +msgid "&8x" +msgstr "&8x" + msgid "Filter method" msgstr "Szűrési mód" @@ -106,6 +124,9 @@ msgstr "&Négyzetes képpontok (aránytartás)" msgid "&Integer scale" msgstr "&Egész tényezÅ‘s nagyítás" +msgid "4:&3 Integer scale" +msgstr "4:&3 Egész tényezÅ‘s nagyítás" + msgid "E&GA/(S)VGA settings" msgstr "E&GA/(S)VGA beállítások" @@ -226,8 +247,8 @@ msgstr "&Kiadás" msgid "&Reload previous image" msgstr "ElÅ‘zÅ‘ képfájl &újratöltése" -msgid "&Image" -msgstr "&MeglévÅ‘ képfájl &megnyitása..." +msgid "&Folder..." +msgstr "&Mappa..." msgid "Target &framerate" msgstr "Cél &képkockasebesség" @@ -364,6 +385,12 @@ msgstr "Videokártya:" msgid "Voodoo Graphics" msgstr "Voodoo-gyorsítókártya" +msgid "IBM 8514/a Graphics" +msgstr "IBM 8514/a-gyorsítókártya" + +msgid "XGA Graphics" +msgstr "XGA-gyorsítókártya" + msgid "Mouse:" msgstr "Egér:" @@ -382,8 +409,17 @@ msgstr "Játékvez. 3..." msgid "Joystick 4..." msgstr "Játékvez. 4..." -msgid "Sound card:" -msgstr "Hangkártya:" +msgid "Sound card 1:" +msgstr "Hangkártya 1:" + +msgid "Sound card 2:" +msgstr "Hangkártya 2:" + +msgid "Sound card 3:" +msgstr "Hangkártya 3:" + +msgid "Sound card 4:" +msgstr "Hangkártya 4:" msgid "MIDI Out Device:" msgstr "MIDI-kimenet:" @@ -394,18 +430,18 @@ msgstr "MIDI-bemenet:" msgid "Standalone MPU-401" msgstr "Különálló MPU-401" -msgid "Innovation SSI-2001" -msgstr "Innovation SSI-2001" - -msgid "CMS / Game Blaster" -msgstr "CMS / Game Blaster" - -msgid "Gravis Ultrasound" -msgstr "Gravis Ultrasound" - msgid "Use FLOAT32 sound" msgstr "FLOAT32 használata" +msgid "FM synth driver" +msgstr "FM szintetizátor meghajtó" + +msgid "Nuked (more accurate)" +msgstr "Nuked (pontosabb)" + +msgid "YMFM (faster)" +msgstr "YMFM (gyorsabb)" + msgid "Network type:" msgstr "Hálózati típusa:" @@ -550,6 +586,9 @@ msgstr "BPB ellenÅ‘rzés" msgid "CD-ROM drives:" msgstr "CD-ROM meghajtók:" +msgid "Earlier drive" +msgstr "Korábbi meghajtó" + msgid "MO drives:" msgstr "MO-meghajtók:" @@ -688,9 +727,6 @@ msgstr "Nyomja meg az F8+F12-t az egér elengédéséhez" msgid "Press F8+F12 or middle button to release mouse" msgstr "Nyomja meg az F8+F12-t vagy a középsÅ‘ gombot az egér elengédéséhez" -msgid "Unable to initialize FluidSynth" -msgstr "Nem sikerült a FluidSynth inicializálása" - msgid "Bus" msgstr "Busz" @@ -775,9 +811,6 @@ msgstr "Továbbfejlesztett szektor képek" msgid "Flux images" msgstr "Flux képekfájlok" -msgid "Unable to initialize FreeType" -msgstr "A FreeType inicializálása nem lehetséges" - msgid "Unable to initialize SDL, SDL2.dll is required" msgstr "Az SDL inicializálása nem lehetséges, az SDL2.dll fájl szükséges" @@ -823,8 +856,8 @@ msgstr "A 86Box névjegye" msgid "86Box v" msgstr "86Box v" -msgid "An emulator of old computers\n\nAuthors: Sarah Walker, Miran Grca, Fred N. van Kempen (waltje), SA1988, Tiseno100, reenigne, leilei, JohnElliott, greatpsycho, and others.\n\nReleased under the GNU General Public License version 2 or later. See LICENSE for more information." -msgstr "Régi számítógépek emulátora\n\nFejlesztÅ‘k: Sarah Walker, Miran Grca, Fred N. van Kempen (waltje), SA1988, Tiseno100, reenigne, leilei, JohnElliott, greatpsycho, and others.\n\nFordította: Laci bá'\n\nMegjelent a GNU General Public License v2 vagy újabb alatt. További információért lásd a LICENSE fájlt." +msgid "An emulator of old computers\n\nAuthors: Miran GrÄa (OBattler), RichardG867, Jasmine Iwanek, TC1995, coldbrewed, Teemu Korhonen (Manaatti), Joakim L. Gilje, Adrien Moulin (elyosh), Daniel Balsom (gloriouscow), Cacodemon345, Fred N. van Kempen (waltje), Tiseno100, reenigne, and others.\n\nWith previous core contributions from Sarah Walker, leilei, JohnElliott, greatpsycho, and others.\n\nReleased under the GNU General Public License version 2 or later. See LICENSE for more information." +msgstr "Régi számítógépek emulátora\n\nFejlesztÅ‘k: Miran GrÄa (OBattler), RichardG867, Jasmine Iwanek, TC1995, coldbrewed, Teemu Korhonen (Manaatti), Joakim L. Gilje, Adrien Moulin (elyosh), Daniel Balsom (gloriouscow), Cacodemon345, Fred N. van Kempen (waltje), Tiseno100, reenigne, and others.\n\nWith previous core contributions from Sarah Walker, leilei, JohnElliott, greatpsycho, and others.\n\nFordította: Laci bá'\n\nMegjelent a GNU General Public License v2 vagy újabb alatt. További információért lásd a LICENSE fájlt." msgid "Hardware not available" msgstr "Hardver nem elérhetÅ‘" @@ -841,15 +874,6 @@ msgstr "GyÅ‘zÅ‘djön meg hogy a(z) libpcap telepítve van és jelenleg a libpcap msgid "Invalid configuration" msgstr "Érvénytelen konfiguráció" -msgid "freetype.dll" -msgstr "freetype.dll" - -msgid "libfreetype" -msgstr "libfreetype" - -msgid " is required for ESC/P printer emulation." -msgstr " szükséges az ESC/P nyomtató emulációhoz." - msgid "gsdll32.dll" msgstr "gsdll32.dll" @@ -859,15 +883,6 @@ msgstr "libgs" msgid " is required for automatic conversion of PostScript files to PDF.\n\nAny documents sent to the generic PostScript printer will be saved as PostScript (.ps) files." msgstr " szükséges a PostScript fájlok PDF formátumba való automatikus konvertálásához.\n\nAz általános PostScript nyomtatóra küldött dokumentumok PostScript (.ps) fájlként kerülnek mentésre." -msgid "libfluidsynth.dll" -msgstr "libfluidsynth.dll" - -msgid "libfluidsynth" -msgstr "libfluidsynth" - -msgid " is required for FluidSynth MIDI output." -msgstr " szükséges a FluidSynth MIDI kimenethez." - msgid "Entering fullscreen mode" msgstr "Teljes képernyÅ‘s módra váltás" @@ -926,22 +941,22 @@ msgid "OpenGL (3.0 Core) renderer could not be initialized. Use another renderer msgstr "Az OpenGL (3.0 Core) megjelenítÅ‘-motort nem sikerült inicializálni. Kérem használjon másik renderelÅ‘t." msgid "Resume execution" -msgstr "Resume execution" +msgstr "Folytassa a végrehajtást" msgid "Pause execution" -msgstr "Pause execution" +msgstr "Kivitelezés szüneteltetése" msgid "Press Ctrl+Alt+Del" -msgstr "Press Ctrl+Alt+Del" +msgstr "Nyomja meg a Ctrl+Alt+Del" msgid "Press Ctrl+Alt+Esc" -msgstr "Press Ctrl+Alt+Esc" +msgstr "Nyomja meg a Ctrl+Alt+Esc" msgid "Hard reset" -msgstr "Hard reset" +msgstr "Hardveres újraindítás" msgid "ACPI shutdown" -msgstr "ACPI shutdown" +msgstr "ACPI leállítás" msgid "Hard disk (%s)" msgstr "Merevlemez (%s)" @@ -1183,3 +1198,29 @@ msgstr "2%-kal a tökéletes RPM alatt" msgid "(System Default)" msgstr "(A rendszer nyelve)" +msgid "Failed to initialize network driver" +msgstr "Nem sikerült inicializálni a hálózati illesztÅ‘programot" + +msgid "The network configuration will be switched to the null driver" +msgstr "A hálózati konfiguráció átvált a null illesztÅ‘programra" + +msgid "Mouse sensitivity:" +msgstr "Egér érzékenység:" + +msgid "Select media images from program working directory" +msgstr "Médiaképek kiválasztása a program munkakönyvtárából" + +msgid "PIT mode:" +msgstr "PIT üzemmód:" + +msgid "Auto" +msgstr "Automatikus" + +msgid "Slow" +msgstr "Lassú" + +msgid "Fast" +msgstr "Gyors" + +msgid "&Auto-pause on focus loss" +msgstr "&Automatikus szünet fókuszvesztéskor" diff --git a/src/qt/languages/it-IT.po b/src/qt/languages/it-IT.po index ee5e2a01a..df71d148b 100644 --- a/src/qt/languages/it-IT.po +++ b/src/qt/languages/it-IT.po @@ -76,6 +76,24 @@ msgstr "1.&5x" msgid "&2x" msgstr "&2x" +msgid "&3x" +msgstr "&3x" + +msgid "&4x" +msgstr "&4x" + +msgid "&5x" +msgstr "&5x" + +msgid "&6x" +msgstr "&6x" + +msgid "&7x" +msgstr "&7x" + +msgid "&8x" +msgstr "&8x" + msgid "Filter method" msgstr "Metodo filtro" @@ -106,6 +124,9 @@ msgstr "&Pixel quadrati (mantiene l'aspetto)" msgid "&Integer scale" msgstr "&Scala intera" +msgid "4:&3 Integer scale" +msgstr "Scala intera 4:&3" + msgid "E&GA/(S)VGA settings" msgstr "Impostazioni E&GA/(S)VGA" @@ -226,8 +247,8 @@ msgstr "&Espelli" msgid "&Reload previous image" msgstr "&Ricarica l'immagine precedente" -msgid "&Image" -msgstr "&Immagine" +msgid "&Folder..." +msgstr "&Cartella..." msgid "Target &framerate" msgstr "Imposta obiettivo &fotogrammi" @@ -364,6 +385,12 @@ msgstr "Video:" msgid "Voodoo Graphics" msgstr "Grafica Voodoo" +msgid "IBM 8514/a Graphics" +msgstr "Grafica IBM 8514/a" + +msgid "XGA Graphics" +msgstr "Grafica XGA" + msgid "Mouse:" msgstr "Mouse:" @@ -382,8 +409,17 @@ msgstr "Joystick 3..." msgid "Joystick 4..." msgstr "Joystick 4..." -msgid "Sound card:" -msgstr "Scheda audio:" +msgid "Sound card 1:" +msgstr "Scheda audio 1:" + +msgid "Sound card 2:" +msgstr "Scheda audio 2:" + +msgid "Sound card 3:" +msgstr "Scheda audio 3:" + +msgid "Sound card 4:" +msgstr "Scheda audio 4:" msgid "MIDI Out Device:" msgstr "Uscita MIDI:" @@ -394,18 +430,18 @@ msgstr "Entrata MIDI:" msgid "Standalone MPU-401" msgstr "MPU-401 autonomo" -msgid "Innovation SSI-2001" -msgstr "Innovation SSI-2001" - -msgid "CMS / Game Blaster" -msgstr "CMS / Game Blaster" - -msgid "Gravis Ultrasound" -msgstr "Gravis Ultrasound" - msgid "Use FLOAT32 sound" msgstr "Usa suono FLOAT32" +msgid "FM synth driver" +msgstr "Driver sint. FM" + +msgid "Nuked (more accurate)" +msgstr "Nuked (più accurato)" + +msgid "YMFM (faster)" +msgstr "YMFM (più veloce)" + msgid "Network type:" msgstr "Tipo di rete:" @@ -550,6 +586,9 @@ msgstr "Verifica BPB" msgid "CD-ROM drives:" msgstr "Unità CD-ROM:" +msgid "Earlier drive" +msgstr "Unità anteriore" + msgid "MO drives:" msgstr "Unità magneto-ottiche:" @@ -688,9 +727,6 @@ msgstr "Premi F8+F12 per rilasciare il mouse" msgid "Press F8+F12 or middle button to release mouse" msgstr "Premi F8+F12 o pulsante centrale per rilasciare il mouse" -msgid "Unable to initialize FluidSynth" -msgstr "Impossibile inizializzare FluidSynth" - msgid "Bus" msgstr "Bus" @@ -775,9 +811,6 @@ msgstr "Immagini da settori avanzati" msgid "Flux images" msgstr "Immagini flusso" -msgid "Unable to initialize FreeType" -msgstr "Impossibile inizializzare FreeType" - msgid "Unable to initialize SDL, SDL2.dll is required" msgstr "Impossibile inizializzare SDL, SDL2.dll è necessario" @@ -823,8 +856,8 @@ msgstr "Informazioni su 86Box" msgid "86Box v" msgstr "86Box v" -msgid "An emulator of old computers\n\nAuthors: Sarah Walker, Miran Grca, Fred N. van Kempen (waltje), SA1988, Tiseno100, reenigne, leilei, JohnElliott, greatpsycho, and others.\n\nReleased under the GNU General Public License version 2 or later. See LICENSE for more information." -msgstr "Un emulatore di computer vecchi\n\nAutori: Sarah Walker, Miran Grca, Fred N. van Kempen (waltje), SA1988, Tiseno100, reenigne, leilei, JohnElliott, greatpsycho, and others.\n\nTradotto da: explorerdotexe\n\nRilasciato sotto la Licenza Pubblica GNU versione 2 o dopo. Vedi LICENSE per maggior informazioni." +msgid "An emulator of old computers\n\nAuthors: Miran GrÄa (OBattler), RichardG867, Jasmine Iwanek, TC1995, coldbrewed, Teemu Korhonen (Manaatti), Joakim L. Gilje, Adrien Moulin (elyosh), Daniel Balsom (gloriouscow), Cacodemon345, Fred N. van Kempen (waltje), Tiseno100, reenigne, and others.\n\nWith previous core contributions from Sarah Walker, leilei, JohnElliott, greatpsycho, and others.\n\nReleased under the GNU General Public License version 2 or later. See LICENSE for more information." +msgstr "Un emulatore di computer vecchi\n\nAutori: Miran GrÄa (OBattler), RichardG867, Jasmine Iwanek, TC1995, coldbrewed, Teemu Korhonen (Manaatti), Joakim L. Gilje, Adrien Moulin (elyosh), Daniel Balsom (gloriouscow), Cacodemon345, Fred N. van Kempen (waltje), Tiseno100, reenigne, and others.\n\nWith previous core contributions from Sarah Walker, leilei, JohnElliott, greatpsycho, and others.\n\nTradotto da: explorerdotexe\n\nRilasciato sotto la Licenza Pubblica GNU versione 2 o dopo. Vedi LICENSE per maggior informazioni." msgid "Hardware not available" msgstr "Hardware non disponibile" @@ -836,20 +869,11 @@ msgid "libpcap" msgstr "libpcap" msgid "Make sure libpcap is installed and that you are on a libpcap-compatible network connection." -msgstr "Controlla se libpcap è installato e che tu sia connesso ad una connessione libpcap compatibile." +msgstr "Controllare se libpcap è installato e che tu sia connesso ad una connessione libpcap compatibile." msgid "Invalid configuration" msgstr "Configurazione invalida" -msgid "freetype.dll" -msgstr "freetype.dll" - -msgid "libfreetype" -msgstr "libfreetype" - -msgid " is required for ESC/P printer emulation." -msgstr " è richesto per l'emuazione di stampanti ESC/P." - msgid "gsdll32.dll" msgstr "gsdll32.dll" @@ -859,15 +883,6 @@ msgstr "libgs" msgid " is required for automatic conversion of PostScript files to PDF.\n\nAny documents sent to the generic PostScript printer will be saved as PostScript (.ps) files." msgstr " è richiesto per la conversione automatica di file PostScript a file PDF.\n\nQualsiasi documento mandato alla stampante generica PostScript sarà salvato come file PostScript. (.ps)" -msgid "libfluidsynth.dll" -msgstr "libfluidsynth.dll" - -msgid "libfluidsynth" -msgstr "libfluidsynth" - -msgid " is required for FluidSynth MIDI output." -msgstr " è richiesto per l'output FluidSynth MIDI." - msgid "Entering fullscreen mode" msgstr "Entrando nella modalità schermo intero" @@ -920,28 +935,28 @@ msgid "Cartridge images" msgstr "Immagini cartuccia" msgid "Error initializing renderer" -msgstr "Error initializing renderer" +msgstr "Errore nell'inizializzazione del renderer" msgid "OpenGL (3.0 Core) renderer could not be initialized. Use another renderer." -msgstr "OpenGL (3.0 Core) renderer could not be initialized. Use another renderer." +msgstr "Non è stato possibile inizializzare il renderer OpenGL (3.0 Core). Utilizzare un altro renderer." msgid "Resume execution" -msgstr "Resume execution" +msgstr "Riprendere l'esecuzione" msgid "Pause execution" -msgstr "Pause execution" +msgstr "Sospendere l'esecuzione" msgid "Press Ctrl+Alt+Del" -msgstr "Press Ctrl+Alt+Del" +msgstr "Premere Ctrl+Alt+Canc" msgid "Press Ctrl+Alt+Esc" -msgstr "Press Ctrl+Alt+Esc" +msgstr "Premere Ctrl+Alt+Esc" msgid "Hard reset" -msgstr "Hard reset" +msgstr "Riavvia" msgid "ACPI shutdown" -msgstr "ACPI shutdown" +msgstr "Arresto ACPI" msgid "Hard disk (%s)" msgstr "Hard disk (%s)" @@ -1183,3 +1198,29 @@ msgstr "RPM 2% sotto perfezione" msgid "(System Default)" msgstr "(Predefinito del sistema)" +msgid "Failed to initialize network driver" +msgstr "Impossibile inizializzare il driver di rete" + +msgid "The network configuration will be switched to the null driver" +msgstr "La configurazione di rete verrà commutata sul driver nullo" + +msgid "Mouse sensitivity:" +msgstr "Sensitività del mouse:" + +msgid "Select media images from program working directory" +msgstr "Seleziona le immagini media dalla directory di lavoro del programma" + +msgid "PIT mode:" +msgstr "Modalità PIT:" + +msgid "Auto" +msgstr "Automatica" + +msgid "Slow" +msgstr "Lenta" + +msgid "Fast" +msgstr "Veloce" + +msgid "&Auto-pause on focus loss" +msgstr "&Pausa automatica alla perdita della messa a fuoco" diff --git a/src/qt/languages/ja-JP.po b/src/qt/languages/ja-JP.po index d1da289c4..7ea47bc1a 100644 --- a/src/qt/languages/ja-JP.po +++ b/src/qt/languages/ja-JP.po @@ -1,14 +1,14 @@ msgid "&Action" -msgstr "動作(&A)" +msgstr "æ“作(&A)" msgid "&Keyboard requires capture" msgstr "キーボードã¯ã‚­ãƒ£ãƒ—ãƒãƒ£ãŒå¿…è¦(&K)" msgid "&Right CTRL is left ALT" -msgstr "å³CTRLã‚’å·¦ALTã¸(&R)" +msgstr "å³CTRLã‚’å·¦ALTã¸å¤‰æ›(&R)" msgid "&Hard Reset..." -msgstr "ãƒãƒ¼ãƒ‰ãƒªã‚»ãƒƒãƒˆ(&H)..." +msgstr "ãƒãƒ¼ãƒ‰ リセット(&H)..." msgid "&Ctrl+Alt+Del\tCtrl+F12" msgstr "Ctrl+Alt+Del(&C)\tCtrl+F12" @@ -26,16 +26,16 @@ msgid "&View" msgstr "表示(&V)" msgid "&Hide status bar" -msgstr "ステータスãƒãƒ¼ã‚’éš ã™(&H)" +msgstr "ステータス ãƒãƒ¼ã‚’éš ã™(&H)" msgid "Hide &toolbar" -msgstr "ツールãƒãƒ¼ã‚’éš ã™(&T)" +msgstr "ツール ãƒãƒ¼ã‚’éš ã™(&T)" msgid "&Resizeable window" -msgstr "ウィンドウã®ã‚µã‚¤ã‚ºã‚’リサイズå¯èƒ½(&R)" +msgstr "ウィンドウã®ã‚µã‚¤ã‚ºã‚’変更å¯èƒ½(&R)" msgid "R&emember size && position" -msgstr "ウィンドウã®ã‚µã‚¤ã‚ºã¨ä½ç½®ã‚’記憶(&E)" +msgstr "ウィンドウã®ã‚µã‚¤ã‚ºã¨ä½ç½®ã‚’ä¿å­˜(&E)" msgid "Re&nderer" msgstr "レンダラー(&N)" @@ -56,10 +56,10 @@ msgid "&VNC" msgstr "VNC(&V)" msgid "Specify dimensions..." -msgstr "ウィンドウã®ã‚µã‚¤ã‚ºã‚’指定..." +msgstr "ディメンションを指定..." msgid "F&orce 4:3 display ratio" -msgstr "4:3アスペクト比を固定(&O)" +msgstr "4:3ã®ç¸¦æ¨ªæ¯”を強制表示(&O)" msgid "&Window scale factor" msgstr "ウィンドウã®è¡¨ç¤ºå€çއ(&W)" @@ -76,6 +76,24 @@ msgstr "1.5x(&5)" msgid "&2x" msgstr "2x(&2)" +msgid "&3x" +msgstr "3x(&3)" + +msgid "&4x" +msgstr "4x(&4)" + +msgid "&5x" +msgstr "5x(&5)" + +msgid "&6x" +msgstr "6x(&6)" + +msgid "&7x" +msgstr "7x(&7)" + +msgid "&8x" +msgstr "8x(&8)" + msgid "Filter method" msgstr "フィルター方å¼" @@ -89,13 +107,13 @@ msgid "Hi&DPI scaling" msgstr "HiDPIスケーリング(&D)" msgid "&Fullscreen\tCtrl+Alt+PgUp" -msgstr "フルスクリーン(&F)\tCtrl+Alt+PgUp" +msgstr "全画é¢è¡¨ç¤º(&F)\tCtrl+Alt+PgUp" msgid "Fullscreen &stretch mode" -msgstr "フルスクリーンã®ã‚¹ã‚±ãƒ¼ãƒ«(&S)" +msgstr "全画é¢ã®æ‹¡å¤§è¡¨ç¤ºãƒ¢ãƒ¼ãƒ‰(&S)" msgid "&Full screen stretch" -msgstr "ãƒ•ãƒ«ã‚¹ã‚¯ãƒªãƒ¼ãƒ³ã«æ‹¡å¤§(&F)" +msgstr "全画é¢ã®æ‹¡å¤§è¡¨ç¤º(&F)" msgid "&4:3" msgstr "4:3(&4)" @@ -106,11 +124,14 @@ msgstr "正方形ピクセル(アスペクト比を維æŒ)(&S)" msgid "&Integer scale" msgstr "æ•´æ•°å€(&I)" +msgid "4:&3 Integer scale" +msgstr "4:3 æ•´æ•°å€(&3)" + msgid "E&GA/(S)VGA settings" msgstr "E&GA/(S)VGAã®è¨­å®š" msgid "&Inverted VGA monitor" -msgstr "色をå転(&I)" +msgstr "色å転(&I)" msgid "VGA screen &type" msgstr "ç”»é¢ã‚¿ã‚¤ãƒ—(&T)" @@ -122,7 +143,7 @@ msgid "&RGB Grayscale" msgstr "RGB(グレースケール)(&R)" msgid "&Amber monitor" -msgstr "モニター(ç¥ç€è‰²)(&A)" +msgstr "モニター(黄色)(&A)" msgid "&Green monitor" msgstr "モニター(緑色)(&G)" @@ -167,10 +188,10 @@ msgid "&Preferences..." msgstr "環境設定(&P)..." msgid "Enable &Discord integration" -msgstr "Discordã¨ã®é€£æºæ©Ÿèƒ½(&D)" +msgstr "Discordé€£æºæ©Ÿèƒ½(&D)" msgid "Sound &gain..." -msgstr "音é‡ã‚’調節(&G)..." +msgstr "音é‡èª¿æ•´(&G)..." msgid "Begin trace\tCtrl+T" msgstr "トレース開始\tCtrl+T" @@ -182,7 +203,7 @@ msgid "&Help" msgstr "ヘルプ(&H)" msgid "&Documentation..." -msgstr "ドキュメント(&D)..." +msgstr "文書(&D)..." msgid "&About 86Box..." msgstr "86Boxã®ãƒãƒ¼ã‚¸ãƒ§ãƒ³æƒ…å ±(&A)..." @@ -194,7 +215,7 @@ msgid "&Existing image..." msgstr "既存ã®ã‚¤ãƒ¡ãƒ¼ã‚¸ã‚’é–‹ã(&E)..." msgid "Existing image (&Write-protected)..." -msgstr "既存ã®ã‚¤ãƒ¡ãƒ¼ã‚¸ã‚’é–‹ã(書ãè¾¼ã¿ä¿è­·)(&W)..." +msgstr "既存ã®ã‚¤ãƒ¡ãƒ¼ã‚¸ã‚’é–‹ã(書ãè¾¼ã¿ç¦æ­¢)(&W)..." msgid "&Record" msgstr "録音(&R)" @@ -203,7 +224,7 @@ msgid "&Play" msgstr "å†ç”Ÿ(&P)" msgid "&Rewind to the beginning" -msgstr "冒頭ã«å·»ã戻ã™(&R)" +msgstr "先頭ã¾ã§å·»ã戻ã™(&R)" msgid "&Fast forward to the end" msgstr "最後ã¾ã§æ—©é€ã‚Š(&F)" @@ -221,13 +242,13 @@ msgid "&Mute" msgstr "ミュート(&M)" msgid "E&mpty" -msgstr "空(&M)" +msgstr "ãªã—(&M)" msgid "&Reload previous image" msgstr "å‰ã®ã‚¤ãƒ¡ãƒ¼ã‚¸ã‚’å†èª­ã¿è¾¼ã¿(&R)" -msgid "&Image" -msgstr "イメージ(&I)" +msgid "&Folder..." +msgstr "フォルダ(&F)..." msgid "Target &framerate" msgstr "目標フレームレート(&F)" @@ -281,7 +302,7 @@ msgid "Cancel" msgstr "キャンセル" msgid "Save these settings as &global defaults" -msgstr "ã“れらã®è¨­å®šã‚’グローãƒãƒ«æ—¢å®šå€¤ã¨ã—ã¦ä¿å­˜ã™ã‚‹(&G)" +msgstr "ã“れらã®è¨­å®šã‚’グローãƒãƒ«æ—¢å®šå€¤ã¨ã—ã¦ä¿å­˜(&G)" msgid "&Default" msgstr "既定値(&D)" @@ -293,7 +314,7 @@ msgid "Icon set:" msgstr "アイコンセット:" msgid "Gain" -msgstr "ゲイン値" +msgstr "音é‡" msgid "File name:" msgstr "ファイルå:" @@ -302,7 +323,7 @@ msgid "Disk size:" msgstr "ディスクサイズ:" msgid "RPM mode:" -msgstr "回転数モード:" +msgstr "RPMモード:" msgid "Progress:" msgstr "進行状æ³:" @@ -314,7 +335,7 @@ msgid "Height:" msgstr "高ã•:" msgid "Lock to this size" -msgstr "ã“ã®ã‚µã‚¤ã‚ºã‚’ロックã™ã‚‹" +msgstr "サイズを固定" msgid "Machine type:" msgstr "マシンタイプ:" @@ -335,7 +356,7 @@ msgid "FPU:" msgstr "FPU:" msgid "Wait states:" -msgstr "待機状態:" +msgstr "ウェイトステート:" msgid "MB" msgstr "MB" @@ -347,16 +368,16 @@ msgid "Time synchronization" msgstr "æ™‚åˆ»åŒæœŸæ©Ÿèƒ½" msgid "Disabled" -msgstr "無効ã«ã™ã‚‹" +msgstr "無効" msgid "Enabled (local time)" -msgstr "有効ã«ã™ã‚‹ (ç¾åœ°æ™‚é–“)" +msgstr "有効(ç¾åœ°æ™‚é–“)" msgid "Enabled (UTC)" -msgstr "有効ã«ã™ã‚‹ (UTC)" +msgstr "有効(UTC)" msgid "Dynamic Recompiler" -msgstr "動的リコンパイラ" +msgstr "å‹•çš„å†ã‚³ãƒ³ãƒ‘イル" msgid "Video:" msgstr "ビデオカード:" @@ -364,6 +385,12 @@ msgstr "ビデオカード:" msgid "Voodoo Graphics" msgstr "Voodooグラフィック" +msgid "IBM 8514/a Graphics" +msgstr "IBM 8514/aグラフィック" + +msgid "XGA Graphics" +msgstr "XGAグラフィック" + msgid "Mouse:" msgstr "マウス:" @@ -382,8 +409,17 @@ msgstr "ジョイスティック3..." msgid "Joystick 4..." msgstr "ジョイスティック4..." -msgid "Sound card:" -msgstr "サウンドカード:" +msgid "Sound card 1:" +msgstr "サウンドカード1:" + +msgid "Sound card 2:" +msgstr "サウンドカード2:" + +msgid "Sound card 3:" +msgstr "サウンドカード3:" + +msgid "Sound card 4:" +msgstr "サウンドカード4:" msgid "MIDI Out Device:" msgstr "MIDI出力デãƒã‚¤ã‚¹:" @@ -394,20 +430,20 @@ msgstr "MIDI入力デãƒã‚¤ã‚¹:" msgid "Standalone MPU-401" msgstr "独立型MPU-401" -msgid "Innovation SSI-2001" -msgstr "Innovation SSI-2001" - -msgid "CMS / Game Blaster" -msgstr "CMS / Game Blaster" - -msgid "Gravis Ultrasound" -msgstr "Gravis Ultrasound" - msgid "Use FLOAT32 sound" msgstr "FLOAT32サウンドを使用ã™ã‚‹" +msgid "FM synth driver" +msgstr "FMシンセドライãƒãƒ¼" + +msgid "Nuked (more accurate)" +msgstr "Nuked(高精度化)" + +msgid "YMFM (faster)" +msgstr "YMFM(より速ã)" + msgid "Network type:" -msgstr "ãƒãƒƒãƒˆãƒ¯ãƒ¼ã‚¯ã‚¿ã‚¤ãƒ—:" +msgstr "ãƒãƒƒãƒˆãƒ¯ãƒ¼ã‚¯ タイプ:" msgid "PCap device:" msgstr "PCapデãƒã‚¤ã‚¹:" @@ -464,16 +500,16 @@ msgid "Parallel port 4" msgstr "パラレルãƒãƒ¼ãƒˆ4" msgid "HD Controller:" -msgstr "HDコントローラー:" +msgstr "HDDコントローラー:" msgid "FD Controller:" -msgstr "FDコントローラー:" +msgstr "FDDコントローラー:" msgid "Tertiary IDE Controller" -msgstr "第三ã®IDEコントローラー" +msgstr "第三IDEコントローラー" msgid "Quaternary IDE Controller" -msgstr "第四ã®IDEコントローラー" +msgstr "第四IDEコントローラー" msgid "SCSI" msgstr "SCSI" @@ -494,7 +530,7 @@ msgid "Cassette" msgstr "カセット" msgid "Hard disks:" -msgstr "ãƒãƒ¼ãƒ‰ãƒ‡ã‚£ã‚¹ã‚¯:" +msgstr "ãƒãƒ¼ãƒ‰ ディスク:" msgid "&New..." msgstr "æ–°è¦(&N)..." @@ -503,7 +539,7 @@ msgid "&Existing..." msgstr "既定(&E)..." msgid "&Remove" -msgstr "除去(&R)" +msgstr "削除(&R)" msgid "Bus:" msgstr "ãƒã‚¹:" @@ -545,11 +581,14 @@ msgid "Turbo timings" msgstr "高速タイミング" msgid "Check BPB" -msgstr "BPBã‚’ãƒã‚§ãƒƒã‚¯" +msgstr "BPBãƒã‚§ãƒƒã‚¯" msgid "CD-ROM drives:" msgstr "CD-ROMドライブ:" +msgid "Earlier drive" +msgstr "å…ˆã®ãƒ‰ãƒ©ã‚¤ãƒ–" + msgid "MO drives:" msgstr "å…‰ç£æ°—ドライブ:" @@ -563,7 +602,7 @@ msgid "ISA RTC:" msgstr "ISA RTCカード:" msgid "ISA Memory Expansion" -msgstr "ISAメモリー拡張カード" +msgstr "ISAメモリ拡張カード" msgid "Card 1:" msgstr "カード1:" @@ -602,7 +641,7 @@ msgid " - PAUSED" msgstr " - ä¸€æ™‚åœæ­¢" msgid "Press Ctrl+Alt+PgDn to return to windowed mode." -msgstr "Ctrl+Alt+PgDnã§ã‚¦ã‚£ãƒ³ãƒ‰ã‚¦ãƒ¢ãƒ¼ãƒ‰ã«æˆ»ã‚Šã¾ã™ã€‚" +msgstr "Ctrl+Alt+PgDnã§ã‚¦ã‚£ãƒ³ãƒ‰ã‚¦ ãƒ¢ãƒ¼ãƒ‰ã«æˆ»ã‚Šã¾ã™ã€‚" msgid "Speed" msgstr "速度" @@ -614,7 +653,7 @@ msgid "ZIP images" msgstr "ZIPイメージ" msgid "86Box could not find any usable ROM images.\n\nPlease download a ROM set and extract it into the \"roms\" directory." -msgstr "86Boxã§ä½¿ç”¨å¯èƒ½ãªROMイメージãŒè¦‹ã¤ã‹ã‚Šã¾ã›ã‚“ã§ã—ãŸã€‚\n\nROMセットをダウンロードã—ã¦ã€ã€Œromsã€ãƒ‡ã‚£ãƒ¬ã‚¯ãƒˆãƒªã«è§£å‡ã—ã¦ãã ã•ã„。" +msgstr "86Boxã§ä½¿ç”¨å¯èƒ½ãªROMイメージãŒè¦‹ã¤ã‹ã‚Šã¾ã›ã‚“。\n\nROMセットをダウンロードã—ã¦ã€roms ディレクトリã«è§£å‡ã—ã¦ãã ã•ã„。" msgid "(empty)" msgstr "(空)" @@ -635,22 +674,22 @@ msgid "All images" msgstr "ã™ã¹ã¦ã®ã‚¤ãƒ¡ãƒ¼ã‚¸" msgid "Basic sector images" -msgstr "基本的ãªã‚»ã‚¯ã‚¿ãƒ¼ã‚¤ãƒ¡ãƒ¼ã‚¸" +msgstr "ベーシック セクター イメージ" msgid "Surface images" -msgstr "表é¢ã‚¤ãƒ¡ãƒ¼ã‚¸" +msgstr "サーフェス イメージ" msgid "Machine \"%hs\" is not available due to missing ROMs in the roms/machines directory. Switching to an available machine." -msgstr "roms/machinesディレクトリã«ROMãŒãªã„ãŸã‚ã€ãƒžã‚·ãƒ³ã€Œ%hsã€ã¯ä½¿ç”¨ã§ãã¾ã›ã‚“。使用å¯èƒ½ãªãƒžã‚·ãƒ³ã«åˆ‡ã‚Šæ›¿ãˆã¾ã™ã€‚" +msgstr "roms/machines ディレクトリã«ROMãŒãªã„ãŸã‚ã€ãƒžã‚·ãƒ³ã€Œ%hsã€ã¯ä½¿ç”¨ã§ãã¾ã›ã‚“。使用å¯èƒ½ãªãƒžã‚·ãƒ³ã«åˆ‡ã‚Šæ›¿ãˆã¾ã™ã€‚" msgid "Video card \"%hs\" is not available due to missing ROMs in the roms/video directory. Switching to an available video card." -msgstr "roms/videoディレクトリã«ROMãŒãªã„ãŸã‚ã€ãƒ“デオカード「%hsã€ã¯ä½¿ç”¨ã§ãã¾ã›ã‚“。使用å¯èƒ½ãªãƒ“デオカードã«åˆ‡ã‚Šæ›¿ãˆã¾ã™ã€‚" +msgstr "roms/video ディレクトリã«ROMãŒãªã„ãŸã‚ã€ãƒ“デオ カード「%hsã€ã¯ä½¿ç”¨ã§ãã¾ã›ã‚“。使用å¯èƒ½ãªãƒ“デオカードã«åˆ‡ã‚Šæ›¿ãˆã¾ã™ã€‚" msgid "Machine" msgstr "マシン" msgid "Display" -msgstr "ç”»é¢è¡¨ç¤º" +msgstr "ディスプレイ" msgid "Input devices" msgstr "入力デãƒã‚¤ã‚¹" @@ -662,7 +701,7 @@ msgid "Network" msgstr "ãƒãƒƒãƒˆãƒ¯ãƒ¼ã‚¯" msgid "Ports (COM & LPT)" -msgstr "ãƒãƒ¼ãƒˆ (COM & LPT)" +msgstr "ãƒãƒ¼ãƒˆ (COM/LPT)" msgid "Storage controllers" msgstr "ストレージコントローラ" @@ -671,25 +710,22 @@ msgid "Hard disks" msgstr "ãƒãƒ¼ãƒ‰ãƒ‡ã‚£ã‚¹ã‚¯" msgid "Floppy & CD-ROM drives" -msgstr "フロッピー/CD-ROMドライブ" +msgstr "フロッピーï¼CD-ROMドライブ" msgid "Other removable devices" -msgstr "ãã®ä»–ã®ãƒªãƒ ãƒ¼ãƒãƒ–ルデãƒã‚¤ã‚¹" +msgstr "ä»–ã®ãƒªãƒ ãƒ¼ãƒãƒ–ルデãƒã‚¤ã‚¹" msgid "Other peripherals" -msgstr "ãã®ä»–ã®å‘¨è¾ºè£…ç½®" +msgstr "ä»–ã®å‘¨è¾ºãƒ‡ãƒã‚¤ã‚¹" msgid "Click to capture mouse" -msgstr "クリックã™ã‚‹ã¨ãƒžã‚¦ã‚¹ã‚’キャプãƒãƒ£ã—ã¾ã™" +msgstr "左クリックã§ãƒžã‚¦ã‚¹ã‚’キャプãƒãƒ£ã—ã¾ã™" msgid "Press F8+F12 to release mouse" msgstr "F8+F12キーã§ãƒžã‚¦ã‚¹ã‚’解放ã—ã¾ã™" msgid "Press F8+F12 or middle button to release mouse" -msgstr "F8+F12キーã¾ãŸã¯ä¸­ãƒœã‚¿ãƒ³ã§ãƒžã‚¦ã‚¹ã‚’解放ã—ã¾ã™" - -msgid "Unable to initialize FluidSynth" -msgstr "FluidSynthãŒåˆæœŸåŒ–ã§ãã¾ã›ã‚“" +msgstr "F8+F12キーã¾ãŸã¯ä¸­ã‚¯ãƒªãƒƒã‚¯ã§ãƒžã‚¦ã‚¹ã‚’解放ã—ã¾ã™" msgid "Bus" msgstr "ãƒã‚¹" @@ -716,7 +752,7 @@ msgid "Default" msgstr "既定値" msgid "%i Wait state(s)" -msgstr "%iã¤ã®å¾…機状態" +msgstr "%iã¤ã®ã‚¦ã‚§ã‚¤ãƒˆ ステート" msgid "Type" msgstr "タイプ" @@ -728,7 +764,7 @@ msgid "No PCap devices found" msgstr "PCapデãƒã‚¤ã‚¹ãŒã‚りã¾ã›ã‚“" msgid "Invalid PCap device" -msgstr "䏿­£ãªPCapデãƒã‚¤ã‚¹ã§ã™" +msgstr "䏿­£ãªPCapデãƒã‚¤ã‚¹" msgid "Standard 2-button joystick(s)" msgstr "標準ジョイスティック(2ボタン)" @@ -746,10 +782,10 @@ msgid "CH Flightstick Pro" msgstr "CH Flightstick Pro" msgid "Microsoft SideWinder Pad" -msgstr "Microsoft SideWinder Pad" +msgstr "Microsoft SideWinderパッド" msgid "Thrustmaster Flight Control System" -msgstr "Thrustmaster Flight Control System" +msgstr "Thrustmaster飛行制御システム" msgid "None" msgstr "ãªã—" @@ -758,13 +794,13 @@ msgid "Unable to load keyboard accelerators." msgstr "キーボードアクセラレータを読ã¿è¾¼ã‚ã¾ã›ã‚“。" msgid "Unable to register raw input." -msgstr "生ã®å…¥åŠ›ãŒç™»éŒ²ã§ãã¾ã›ã‚“。" +msgstr "生入力ãŒç™»éŒ²ã§ãã¾ã›ã‚“。" msgid "%u" msgstr "%u" msgid "%u MB (CHS: %i, %i, %i)" -msgstr "%u MB (CHS: %i, %i, %i)" +msgstr "%u MB (CHS値: %iã€%iã€%i)" msgid "Floppy %i (%s): %ls" msgstr "フロッピー %i (%s): %ls" @@ -773,16 +809,13 @@ msgid "Advanced sector images" msgstr "アドãƒãƒ³ã‚¹ãƒ‰ã‚»ã‚¯ã‚¿ãƒ¼ã‚¤ãƒ¡ãƒ¼ã‚¸" msgid "Flux images" -msgstr "フラックスイメージ" - -msgid "Unable to initialize FreeType" -msgstr "FreeTypeãŒåˆæœŸåŒ–ã§ãã¾ã›ã‚“" +msgstr "Fluxイメージ" msgid "Unable to initialize SDL, SDL2.dll is required" msgstr "SDLãŒåˆæœŸåŒ–ã§ãã¾ã›ã‚“。SDL2.dllãŒå¿…è¦ã§ã™" msgid "Are you sure you want to hard reset the emulated machine?" -msgstr "使用中ã®ãƒžã‚·ãƒ³ã‚’ãƒãƒ¼ãƒ‰ãƒªã‚»ãƒƒãƒˆã—ã¾ã™ã‹ï¼Ÿ" +msgstr "使用中ã®ãƒžã‚·ãƒ³ã‚’ãƒãƒ¼ãƒ‰ リセットã—ã¾ã™ã‹ï¼Ÿ" msgid "Are you sure you want to exit 86Box?" msgstr "86Boxを終了ã—ã¾ã™ã‹ï¼Ÿ" @@ -812,7 +845,7 @@ msgid "Do you want to save the settings?" msgstr "設定をä¿å­˜ã—ã¾ã™ã‹ï¼Ÿ" msgid "This will hard reset the emulated machine." -msgstr "ä¿å­˜ã™ã‚‹ã¨ä½¿ç”¨ä¸­ã®ãƒžã‚·ãƒ³ãŒãƒãƒ¼ãƒ‰ãƒªã‚»ãƒƒãƒˆã•れã¾ã™ã€‚" +msgstr "使用中ã®ãƒžã‚·ãƒ³ãŒãƒãƒ¼ãƒ‰ãƒªã‚»ãƒƒãƒˆã•れã¾ã™ã€‚" msgid "Save" msgstr "ä¿å­˜" @@ -823,8 +856,8 @@ msgstr "86Boxã®ãƒãƒ¼ã‚¸ãƒ§ãƒ³æƒ…å ±" msgid "86Box v" msgstr "86Box v" -msgid "An emulator of old computers\n\nAuthors: Sarah Walker, Miran Grca, Fred N. van Kempen (waltje), SA1988, Tiseno100, reenigne, leilei, JohnElliott, greatpsycho, and others.\n\nReleased under the GNU General Public License version 2 or later. See LICENSE for more information." -msgstr "å¤ã„パソコンã®ã‚¨ãƒŸãƒ¥ãƒ¬ãƒ¼ã‚¿ãƒ¼\n\n著者: Sarah Walker, Miran Grca, Fred N. van Kempen (waltje), SA1988, Tiseno100, reenigne, leilei, JohnElliott, greatpsycho, and others.\n\nGNU General Public License version 2以é™ã§ãƒªãƒªãƒ¼ã‚¹ã•れã¦ã„ã¾ã™ã€‚詳ã—ã㯠LICENSE ã‚’ã”覧ãã ã•ã„。" +msgid "An emulator of old computers\n\nAuthors: Miran GrÄa (OBattler), RichardG867, Jasmine Iwanek, TC1995, coldbrewed, Teemu Korhonen (Manaatti), Joakim L. Gilje, Adrien Moulin (elyosh), Daniel Balsom (gloriouscow), Cacodemon345, Fred N. van Kempen (waltje), Tiseno100, reenigne, and others.\n\nWith previous core contributions from Sarah Walker, leilei, JohnElliott, greatpsycho, and others.\n\nReleased under the GNU General Public License version 2 or later. See LICENSE for more information." +msgstr "å¤ã„パソコンã®ã‚¨ãƒŸãƒ¥ãƒ¬ãƒ¼ã‚¿ãƒ¼\n\n著者: Miran GrÄa (OBattler), RichardG867, Jasmine Iwanek, TC1995, coldbrewed, Teemu Korhonen (Manaatti), Joakim L. Gilje, Adrien Moulin (elyosh), Daniel Balsom (gloriouscow), Cacodemon345, Fred N. van Kempen (waltje), Tiseno100, reenigne, and others.\n\nWith previous core contributions from Sarah Walker, leilei, JohnElliott, greatpsycho, and others.\n\nGNU General Public License version 2以é™ã§ãƒªãƒªãƒ¼ã‚¹ã•れã¦ã„ã¾ã™ã€‚詳ã—ã㯠LICENSE ã‚’ã”覧ãã ã•ã„。" msgid "Hardware not available" msgstr "ãƒãƒ¼ãƒ‰ã‚¦ã‚§ã‚¢ãŒåˆ©ç”¨ã§ãã¾ã›ã‚“" @@ -841,15 +874,6 @@ msgstr "ãŒã‚¤ãƒ³ã‚¹ãƒˆãƒ¼ãƒ«ã•れã¦ã‚‹ã‹ã€libpcapã«å¯¾å¿œã—ãŸãƒãƒƒãƒˆ msgid "Invalid configuration" msgstr "䏿­£ãªè¨­å®šã§ã™" -msgid "freetype.dll" -msgstr "freetype.dll" - -msgid "libfreetype" -msgstr "libfreetype" - -msgid " is required for ESC/P printer emulation." -msgstr "ESC/Pプリンタã®ã‚¨ãƒŸãƒ¥ãƒ¬ãƒ¼ã‚·ãƒ§ãƒ³ã«ã¯libfreetypeãŒå¿…è¦ã§ã™ã€‚" - msgid "gsdll32.dll" msgstr "gsdll32.dll" @@ -857,19 +881,10 @@ msgid "libgs" msgstr "libgs" msgid " is required for automatic conversion of PostScript files to PDF.\n\nAny documents sent to the generic PostScript printer will be saved as PostScript (.ps) files." -msgstr "PostScriptファイルをPDFã«è‡ªå‹•変æ›ã™ã‚‹ã«ã¯libgsãŒå¿…è¦ã§ã™ã€‚\n\n汎用PostScriptプリンターã«é€ä¿¡ã•れãŸãƒ‰ã‚­ãƒ¥ãƒ¡ãƒ³ãƒˆã¯ã€PostScript(.ps)ファイルã¨ã—ã¦ä¿å­˜ã•れã¾ã™ã€‚" - -msgid "libfluidsynth.dll" -msgstr "libfluidsynth.dll" - -msgid "libfluidsynth" -msgstr "libfluidsynth" - -msgid " is required for FluidSynth MIDI output." -msgstr "FluidSynthã®MIDI出力ã«ã¯libfluidsynthãŒå¿…è¦ã§ã™ã€‚" +msgstr "PostScriptファイルをPDFã«è‡ªå‹•変æ›ã™ã‚‹ã«ã¯libgsãŒå¿…è¦ã§ã™ã€‚\n\n汎用PostScriptプリンターã«é€ä¿¡ã•ã‚ŒãŸæ–‡æ›¸ã¯ã€PostScript (.ps) ファイルã¨ã—ã¦ä¿å­˜ã•れã¾ã™ã€‚" msgid "Entering fullscreen mode" -msgstr "フルスクリーンã«åˆ‡ã‚Šæ›¿ãˆã¦ã„ã¾ã™" +msgstr "全画é¢ãƒ¢ãƒ¼ãƒ‰ã‚’入力" msgid "Don't show this message again" msgstr "今後ã€ã“ã®ãƒ¡ãƒƒã‚»ãƒ¼ã‚¸ã‚’表示ã—ãªã„" @@ -887,7 +902,7 @@ msgid "CD-ROM images" msgstr "CD-ROMイメージ" msgid "%hs Device Configuration" -msgstr "%hs デãƒã‚¤ã‚¹ã®è¨­å®š" +msgstr "%hs ã®ãƒ‡ãƒã‚¤ã‚¹è¨­å®š" msgid "Monitor in sleep mode" msgstr "モニターã®ã‚¹ãƒªãƒ¼ãƒ—モード" @@ -899,10 +914,10 @@ msgid "OpenGL options" msgstr "OpenGL設定" msgid "You are loading an unsupported configuration" -msgstr "サãƒãƒ¼ãƒˆã•れã¦ã„ãªã„設定を読ã¿è¾¼ã‚“ã§ã„ã¾ã™" +msgstr "読ã¿è¾¼ã‚“ã§ã„る設定ãŒã‚µãƒãƒ¼ãƒˆã•れã¾ã›ã‚“" msgid "CPU type filtering based on selected machine is disabled for this emulated machine.\n\nThis makes it possible to choose a CPU that is otherwise incompatible with the selected machine. However, you may run into incompatibilities with the machine BIOS or other software.\n\nEnabling this setting is not officially supported and any bug reports filed may be closed as invalid." -msgstr "é¸æŠžã—ãŸãƒžã‚·ãƒ³ã«åŸºã¥ãCPUタイプã®ãƒ•ィルタリングã¯ã€ã“ã®ã‚¨ãƒŸãƒ¥ãƒ¬ãƒ¼ãƒˆã•れãŸãƒžã‚·ãƒ³ã§ã¯ç„¡åйã«ãªã£ã¦ã„ã¾ã™ã€‚\n\nã“れã«ã‚ˆã‚Šã€é¸æŠžã—ãŸãƒžã‚·ãƒ³ã¨äº’æ›æ€§ã®ãªã„CPUãŒé¸æŠžã§ãã¾ã™ã€‚ãŸã ã—ã€ãƒžã‚·ãƒ³ã®BIOSã¾ãŸã¯ä»–ã®ã‚½ãƒ•トウェアã¨ã®äº’æ›æ€§ãŒå¤±ã‚れるå¯èƒ½æ€§ãŒã‚りã¾ã™ã€‚\n\nã“ã®è¨­å®šã®æœ‰åŠ¹åŒ–ã¯å…¬å¼ã‚µãƒãƒ¼ãƒˆãŒã§ãã¾ã›ã‚“。ã¾ãŸã€ãƒã‚°ãƒ¬ãƒãƒ¼ãƒˆãŒç„¡åйã¨ã—ã¦é–‰ã˜ã‚‰ã‚Œã‚‹å ´åˆãŒã‚りã¾ã™ã€‚" +msgstr "é¸æŠžã—ãŸãƒžã‚·ãƒ³ã«åŸºã¥ãCPUタイプã®ãƒ•ィルター機能ã¯ã€ä½¿ç”¨ä¸­ã®ãƒžã‚·ãƒ³ã§ã¯ç„¡åйã«ãªã£ã¦ã„ã¾ã™ã€‚\n\nã“れã«ã‚ˆã‚Šã€é¸æŠžã—ãŸãƒžã‚·ãƒ³ã¨äº’æ›æ€§ã®ãªã„CPUãŒé¸æŠžã§ãã¾ã™ã€‚ã—ã‹ã—ã€ãƒžã‚·ãƒ³ã®BIOSã‚„ä»–ã®ã‚½ãƒ•トウェアã¨äº’æ›æ€§ãŒãªã„å ´åˆãŒã‚りã¾ã™ã€‚\n\nã“ã®è¨­å®šã‚’有効ã«ã™ã‚‹ã“ã¨ã¯å…¬å¼ã«ã¯ã‚µãƒãƒ¼ãƒˆã•れã¦ãŠã‚‰ãšã€ãƒã‚°ãƒ¬ãƒãƒ¼ãƒˆã¯ç„¡åйã¨ã—ã¦ä¸­æ­¢ã•れるå¯èƒ½æ€§ãŒã‚りã¾ã™ã€‚" msgid "Continue" msgstr "続行" @@ -923,7 +938,7 @@ msgid "Error initializing renderer" msgstr "レンダラーã®åˆæœŸåŒ–エラー" msgid "OpenGL (3.0 Core) renderer could not be initialized. Use another renderer." -msgstr "OpenGL (3.0コア) レンダラーãŒåˆæœŸåŒ–ã§ãã¾ã›ã‚“ã§ã—ãŸã€‚別ã®ãƒ¬ãƒ³ãƒ€ãƒ©ãƒ¼ã‚’使用ã—ã¦ãã ã•ã„。" +msgstr "OpenGL (3.0コア) レンダラーãŒåˆæœŸåŒ–ã§ãã¾ã›ã‚“。別ã®ãƒ¬ãƒ³ãƒ€ãƒ©ãƒ¼ã‚’使用ã—ã¦ãã ã•ã„。" msgid "Resume execution" msgstr "実行をå†é–‹" @@ -932,10 +947,10 @@ msgid "Pause execution" msgstr "å®Ÿè¡Œã‚’ä¸€æ™‚åœæ­¢" msgid "Press Ctrl+Alt+Del" -msgstr "Ctrl+Alt+DELを押ã—" +msgstr "Ctrl+Alt+DELを押ã™" msgid "Press Ctrl+Alt+Esc" -msgstr "Ctrl+Alt+Escを押ã—" +msgstr "Ctrl+Alt+Escを押ã™" msgid "Hard reset" msgstr "ãƒãƒ¼ãƒ‰ãƒªã‚»ãƒƒãƒˆ" @@ -953,13 +968,13 @@ msgid "%01i" msgstr "%01i" msgid "MFM/RLL or ESDI CD-ROM drives never existed" -msgstr "MFM/RLLã¾ãŸã¯ESDIã®CD-ROMドライブãŒå­˜åœ¨ã—ã¾ã›ã‚“" +msgstr "MFM/RLLã‚„ESDI CD-ROMドライブãŒå­˜åœ¨ã—ã¾ã›ã‚“" msgid "Custom..." msgstr "カスタム..." msgid "Custom (large)..." -msgstr "カスタム (大型)..." +msgstr "カスタム (大容é‡)..." msgid "Add New Hard Disk" msgstr "æ–°è¦ã®ãƒ‡ã‚£ã‚¹ã‚¯ã‚’追加" @@ -986,7 +1001,7 @@ msgid "HDI or HDX images with a sector size other than 512 are not supported." msgstr "512以外ã®ã‚»ã‚¯ã‚¿ã‚µã‚¤ã‚ºã‚’æŒã¤HDIã¾ãŸã¯HDXイメージã¯ã‚µãƒãƒ¼ãƒˆã•れã¦ã„ã¾ã›ã‚“。" msgid "USB is not yet supported" -msgstr "USBã¯ã¾ã ã‚µãƒãƒ¼ãƒˆã•れã¦ã„ã¾ã›ã‚“" +msgstr "USBã¯ã¾ã éžå¯¾å¿œã§ã™" msgid "Disk image file already exists" msgstr "ãƒ‡ã‚£ã‚¹ã‚¯ã‚¤ãƒ¡ãƒ¼ã‚¸ãƒ•ã‚¡ã‚¤ãƒ«ãŒæ—¢ã«å­˜åœ¨ã—ã¾ã™" @@ -1010,10 +1025,10 @@ msgid "Remember to partition and format the newly-created drive." msgstr "æ–°è¦ãƒ‰ãƒ©ã‚¤ãƒ–をパーティション分割ã—ã€ãƒ•ォーマットを必ãšã—ã¨ã„ã¦ãã ã•ã„。" msgid "The selected file will be overwritten. Are you sure you want to use it?" -msgstr "é¸æŠžã—ãŸãƒ•ァイルãŒä¸Šæ›¸ãã•れã¾ã™ã€‚使ã£ã¦ã„ã„ã§ã™ã‹ï¼Ÿ" +msgstr "é¸æŠžã—ãŸãƒ•ァイルã¯ä¸Šæ›¸ãã•れã¾ã™ã€‚よã‚ã—ã„ã§ã™ã‹ï¼Ÿ" msgid "Unsupported disk image" -msgstr "サãƒãƒ¼ãƒˆã•れã¦ã„ãªã„ディスクイメージ" +msgstr "éžå¯¾å¿œã®ãƒ‡ã‚£ã‚¹ã‚¯ã‚¤ãƒ¡ãƒ¼ã‚¸ã‚¸" msgid "Overwrite" msgstr "上書ã" @@ -1031,19 +1046,19 @@ msgid "HDX image (.hdx)" msgstr "HDXイメージ (.hdx)" msgid "Fixed-size VHD (.vhd)" -msgstr "VHD(容é‡å›ºå®š)(.vhd)" +msgstr "VHD (容é‡å›ºå®š) (.vhd)" msgid "Dynamic-size VHD (.vhd)" -msgstr "VHD(容é‡å¯å¤‰)(.vhd)" +msgstr "VHD (容é‡å¯å¤‰) (.vhd)" msgid "Differencing VHD (.vhd)" -msgstr "VHD(差分)(.vhd)" +msgstr "VHD (差分) (.vhd)" msgid "Large blocks (2 MB)" -msgstr "大型ブロック (2 MB)" +msgstr "大ããªãƒ–ロック (2 MB)" msgid "Small blocks (512 KB)" -msgstr "å°åž‹ãƒ–ロック (512 KB)" +msgstr "å°ã•ãªãƒ–ロック (512 KB)" msgid "VHD files" msgstr "VHDファイル" @@ -1052,13 +1067,13 @@ msgid "Select the parent VHD" msgstr "親VHDã®é¸æŠž" msgid "This could mean that the parent image was modified after the differencing image was created.\n\nIt can also happen if the image files were moved or copied, or by a bug in the program that created this disk.\n\nDo you want to fix the timestamps?" -msgstr "親イメージãŒãƒ‡ã‚£ãƒ•ァレンシングイメージã®ä½œæˆã®å¾Œã«ä¿®æ­£ã—ãŸå¯èƒ½æ€§ãŒã‚りã¾ã™ã€‚\n\nイメージファイルã®ç§»å‹•ã€ã‚³ãƒ”ーã¾ãŸã¯ã“ã®ãƒ‡ã‚£ã‚¹ã‚¯ã‚’作æˆã—ãŸãƒ—ログラムã«ãƒã‚°ãŒç™ºç”Ÿã—ãŸå¯èƒ½æ€§ãŒã‚りã¾ã™ã€‚\n\nタイムスタンプを修正ã—ã¾ã™ã‹ï¼Ÿ" +msgstr "親イメージãŒå·®åˆ†ã‚¤ãƒ¡ãƒ¼ã‚¸ã®ä½œæˆã®å¾Œã«å¤‰æ›´ã•れるå¯èƒ½æ€§ãŒã‚りã¾ã™ã€‚\n\nイメージ ファイルãŒç§»å‹•ã¾ãŸã¯ã‚³ãƒ”ーã•れãŸã‹ã€ã‚¤ãƒ¡ãƒ¼ã‚¸ ファイルを作æˆã—ãŸãƒ—ログラムã«ãƒã‚°ãŒç™ºç”Ÿã—ãŸå¯èƒ½æ€§ãŒã‚りã¾ã™ã€‚\n\nタイムスタンプを修正ã—ã¾ã™ã‹ï¼Ÿ" msgid "Parent and child disk timestamps do not match" -msgstr "親ディスクã¨å­ãƒ‡ã‚£ã‚¹ã‚¯ã®ã‚¿ã‚¤ãƒ ã‚¹ã‚¿ãƒ³ãƒ—ãŒä¸€è‡´ã—ã¾ã›ã‚“" +msgstr "親ディスクã¨å­ãƒ‡ã‚£ã‚¹ã‚¯ã®ã‚¿ã‚¤ãƒ ã‚¹ タンプãŒä¸€è‡´ã—ã¾ã›ã‚“" msgid "Could not fix VHD timestamp." -msgstr "VHD ã®ã‚¿ã‚¤ãƒ ã‚¹ã‚¿ãƒ³ãƒ—を修正ã§ãã¾ã›ã‚“ã§ã—ãŸã€‚" +msgstr "VHD ã®ã‚¿ã‚¤ãƒ ã‚¹ã‚¿ãƒ³ãƒ—を修正ã§ãã¾ã›ã‚“。" msgid "%01i:%02i" msgstr "%01i:%02i" @@ -1169,17 +1184,43 @@ msgid "5.25\" 1.3 GB" msgstr "5.25\" 1.3 GB" msgid "Perfect RPM" -msgstr "è¦å®šã®å›žè»¢æ•°" +msgstr "既定RPM" msgid "1% below perfect RPM" -msgstr "1%低ã„回転数" +msgstr "1%低ã„RPM" msgid "1.5% below perfect RPM" -msgstr "1.5%低ã„回転数" +msgstr "1.5%低ã„RPM" msgid "2% below perfect RPM" -msgstr "2%低ã„回転数" +msgstr "2%低ã„RPM" msgid "(System Default)" msgstr "(システム既定値)" +msgid "Failed to initialize network driver" +msgstr "ãƒãƒƒãƒˆãƒ¯ãƒ¼ã‚¯ãƒ‰ãƒ©ã‚¤ãƒã®åˆæœŸåŒ–ã«å¤±æ•—ã—ã¾ã—ãŸ" + +msgid "The network configuration will be switched to the null driver" +msgstr "ãƒãƒƒãƒˆãƒ¯ãƒ¼ã‚¯è¨­å®šãŒãƒŒãƒ«ãƒ‰ãƒ©ã‚¤ãƒã«åˆ‡ã‚Šæ›¿ãˆã‚‰ã‚Œã¾ã™" + +msgid "Mouse sensitivity:" +msgstr "ãƒžã‚¦ã‚¹ã®æ„Ÿåº¦:" + +msgid "Select media images from program working directory" +msgstr "プログラムã®ä½œæ¥­ãƒ‡ã‚£ãƒ¬ã‚¯ãƒˆãƒªã‹ã‚‰ãƒ¡ãƒ‡ã‚£ã‚¢ã‚¤ãƒ¡ãƒ¼ã‚¸ã‚’é¸æŠžã—ã¦ãã ã•ã„" + +msgid "PIT mode:" +msgstr "PITモード:" + +msgid "Auto" +msgstr "自動" + +msgid "Slow" +msgstr "é…ã„" + +msgid "Fast" +msgstr "速ã„" + +msgid "&Auto-pause on focus loss" +msgstr "フォーカスãŒå¥ªã‚れるã¨è‡ªå‹•åœæ­¢(&A)" diff --git a/src/qt/languages/ko-KR.po b/src/qt/languages/ko-KR.po index bd5cd3e37..ac4476ca8 100644 --- a/src/qt/languages/ko-KR.po +++ b/src/qt/languages/ko-KR.po @@ -76,6 +76,24 @@ msgstr "1.5ë°°(&5)" msgid "&2x" msgstr "2ë°°(&2)" +msgid "&3x" +msgstr "3ë°°(&3)" + +msgid "&4x" +msgstr "4ë°°(&4)" + +msgid "&5x" +msgstr "5ë°°(&5)" + +msgid "&6x" +msgstr "6ë°°(&6)" + +msgid "&7x" +msgstr "7ë°°(&7)" + +msgid "&8x" +msgstr "8ë°°(&8)" + msgid "Filter method" msgstr "í•„í„° 형ì‹" @@ -106,6 +124,9 @@ msgstr "정사ê°í˜• 픽셀 (비율 유지)(&S)" msgid "&Integer scale" msgstr "정수배 확대(&I)" +msgid "4:&3 Integer scale" +msgstr "4:3 정수배 확대(&3)" + msgid "E&GA/(S)VGA settings" msgstr "E&GA/(S)VGA 설정" @@ -226,8 +247,8 @@ msgstr "비었ìŒ(&M)" msgid "&Reload previous image" msgstr "ì´ì „ ì´ë¯¸ì§€ 다시 불러오기(&R)" -msgid "&Image" -msgstr "ì´ë¯¸ì§€(&I)" +msgid "&Folder..." +msgstr "í´ë”(&F)..." msgid "Target &framerate" msgstr "목표 프레임 ë ˆì´íЏ(&F)" @@ -364,6 +385,12 @@ msgstr "비디오 카드:" msgid "Voodoo Graphics" msgstr "Voodoo 그래픽" +msgid "IBM 8514/a Graphics" +msgstr "IBM 8514/a 그래픽" + +msgid "XGA Graphics" +msgstr "XGA 그래픽" + msgid "Mouse:" msgstr "마우스:" @@ -382,8 +409,17 @@ msgstr "ì¡°ì´ìŠ¤í‹± 3..." msgid "Joystick 4..." msgstr "ì¡°ì´ìŠ¤í‹± 4..." -msgid "Sound card:" -msgstr "사운드 카드:" +msgid "Sound card 1:" +msgstr "사운드 카드 1:" + +msgid "Sound card 2:" +msgstr "사운드 카드 2:" + +msgid "Sound card 3:" +msgstr "사운드 카드 3:" + +msgid "Sound card 4:" +msgstr "사운드 카드 4:" msgid "MIDI Out Device:" msgstr "MIDI 출력 장치:" @@ -394,18 +430,18 @@ msgstr "MIDI ìž…ë ¥ 장치:" msgid "Standalone MPU-401" msgstr "MPU-401 ë‹¨ë… ì‚¬ìš©" -msgid "Innovation SSI-2001" -msgstr "Innovation SSI-2001" - -msgid "CMS / Game Blaster" -msgstr "CMS / Game Blaster" - -msgid "Gravis Ultrasound" -msgstr "Gravis Ultrasound" - msgid "Use FLOAT32 sound" msgstr "FLOAT32 사운드 사용" +msgid "FM synth driver" +msgstr "FM 신디사ì´ì € 드ë¼ì´ë²„" + +msgid "Nuked (more accurate)" +msgstr "Nuked (ë” ì •í™•í•œ)" + +msgid "YMFM (faster)" +msgstr "YMFM (ë” ë¹ ë¥´ê²Œ)" + msgid "Network type:" msgstr "ë„¤íŠ¸ì›Œí¬ ì¢…ë¥˜:" @@ -550,6 +586,9 @@ msgstr "BPB 확ì¸" msgid "CD-ROM drives:" msgstr "CD-ROM 드ë¼ì´ë¸Œ:" +msgid "Earlier drive" +msgstr "ì´ì „ 드ë¼ì´ë¸Œ" + msgid "MO drives:" msgstr "ê´‘ìžê¸° 드ë¼ì´ë¸Œ:" @@ -688,9 +727,6 @@ msgstr "F12+F8키를 누르면 마우스를 해제합니다" msgid "Press F8+F12 or middle button to release mouse" msgstr "F12+F8키 ë˜ëŠ” ê°€ìš´ë° ë²„íŠ¼ì„ í´ë¦­í•˜ë©´ 마우스를 해제합니다" -msgid "Unable to initialize FluidSynth" -msgstr "FluidSynth를 초기화할 수 없습니다" - msgid "Bus" msgstr "버스" @@ -775,9 +811,6 @@ msgstr "어드밴스드 섹터 ì´ë¯¸ì§€" msgid "Flux images" msgstr "플럭스 ì´ë¯¸ì§€" -msgid "Unable to initialize FreeType" -msgstr "FreeTypeì„ ì´ˆê¸°í™”í•  수 없습니다" - msgid "Unable to initialize SDL, SDL2.dll is required" msgstr "SDLì„ ì´ˆê¸°í™”í•  수 없습니다. SDL2.dllì´ í•„ìš”í•©ë‹ˆë‹¤" @@ -823,8 +856,8 @@ msgstr "86Boxì— ëŒ€í•´" msgid "86Box v" msgstr "86Box v" -msgid "An emulator of old computers\n\nAuthors: Sarah Walker, Miran Grca, Fred N. van Kempen (waltje), SA1988, Tiseno100, reenigne, leilei, JohnElliott, greatpsycho, and others.\n\nReleased under the GNU General Public License version 2 or later. See LICENSE for more information." -msgstr "ê³ ì „ 컴퓨터 ì—뮬레ì´í„°\n\nì €ìž: Sarah Walker, Miran Grca, Fred N. van Kempen (waltje), SA1988, Tiseno100, reenigne, leilei, JohnElliott, greatpsycho, and others.\n\nGNU General Public ë¼ì´ì„ ìФ (버전 2 ì´ìƒ)ì— ì˜í•´ ë°°í¬ë˜ì—ˆìŠµë‹ˆë‹¤. ìžì„¸í•œ ë‚´ìš©ì€ LICENSE 파ì¼ì„ ì½ì–´ 주세요." +msgid "An emulator of old computers\n\nAuthors: Miran GrÄa (OBattler), RichardG867, Jasmine Iwanek, TC1995, coldbrewed, Teemu Korhonen (Manaatti), Joakim L. Gilje, Adrien Moulin (elyosh), Daniel Balsom (gloriouscow), Cacodemon345, Fred N. van Kempen (waltje), Tiseno100, reenigne, and others.\n\nWith previous core contributions from Sarah Walker, leilei, JohnElliott, greatpsycho, and others.\n\nReleased under the GNU General Public License version 2 or later. See LICENSE for more information." +msgstr "ê³ ì „ 컴퓨터 ì—뮬레ì´í„°\n\nì €ìž: Miran GrÄa (OBattler), RichardG867, Jasmine Iwanek, TC1995, coldbrewed, Teemu Korhonen (Manaatti), Joakim L. Gilje, Adrien Moulin (elyosh), Daniel Balsom (gloriouscow), Cacodemon345, Fred N. van Kempen (waltje), Tiseno100, reenigne, and others.\n\nWith previous core contributions from Sarah Walker, leilei, JohnElliott, greatpsycho, and others.\n\nGNU General Public ë¼ì´ì„ ìФ (버전 2 ì´ìƒ)ì— ì˜í•´ ë°°í¬ë˜ì—ˆìŠµë‹ˆë‹¤. ìžì„¸í•œ ë‚´ìš©ì€ LICENSE 파ì¼ì„ ì½ì–´ 주세요." msgid "Hardware not available" msgstr "하드웨어를 ì´ìš©í•  수 없습니다" @@ -841,15 +874,6 @@ msgstr "ì´ ì„¤ì¹˜ë˜ì—ˆëŠ”ì§€ libpcapì— ëŒ€ì‘하는 네트워í¬ì— ì ‘ì†ë˜ msgid "Invalid configuration" msgstr "올바르지 ì•Šì€ ì„¤ì •ìž…ë‹ˆë‹¤" -msgid "freetype.dll" -msgstr "freetype.dll" - -msgid "libfreetype" -msgstr "libfreetype" - -msgid " is required for ESC/P printer emulation." -msgstr "ESC/P 프린터 ì—뮬레ì´ì…˜ì— libfreetypeì´(ê°€) 필요합니다." - msgid "gsdll32.dll" msgstr "gsdll32.dll" @@ -859,15 +883,6 @@ msgstr "libgs" msgid " is required for automatic conversion of PostScript files to PDF.\n\nAny documents sent to the generic PostScript printer will be saved as PostScript (.ps) files." msgstr "ì€(는) PostScript 파ì¼ì„ PDF로 ìžë™ë³€í™˜í•˜ëŠ” ë°ì— 필요합니다.\n\n표준 PostScript 프린터로 ë³´ë‚´ì‹  ìž„ì˜ì˜ 문서는 PostScript (.ps) 파ì¼ë¡œ 저장ë©ë‹ˆë‹¤." -msgid "libfluidsynth.dll" -msgstr "libfluidsynth.dll" - -msgid "libfluidsynth" -msgstr "libfluidsynth" - -msgid " is required for FluidSynth MIDI output." -msgstr "FluidSynthì˜ MIDI ì¶œë ¥ì— libfluidsynthì´(ê°€) 필요합니다." - msgid "Entering fullscreen mode" msgstr "ì „ì²´ 화면으로 전환" @@ -920,28 +935,28 @@ msgid "Cartridge images" msgstr "카트리지 ì´ë¯¸ì§€" msgid "Error initializing renderer" -msgstr "Error initializing renderer" +msgstr "ë Œë”러 초기화 오류" msgid "OpenGL (3.0 Core) renderer could not be initialized. Use another renderer." -msgstr "OpenGL (3.0 Core) renderer could not be initialized. Use another renderer." +msgstr "OpenGL (3.0 Core) ë Œë”러를 초기화할 수 없습니다. 다른 ë Œë”러를 사용하십시오." msgid "Resume execution" -msgstr "Resume execution" +msgstr "실행 재개" msgid "Pause execution" -msgstr "Pause execution" +msgstr "실행 ì¼ì‹œ 중지" msgid "Press Ctrl+Alt+Del" -msgstr "Press Ctrl+Alt+Del" +msgstr "Ctrl+Alt+Del" msgid "Press Ctrl+Alt+Esc" -msgstr "Press Ctrl+Alt+Esc" +msgstr "Ctrl+Alt+Esc" msgid "Hard reset" -msgstr "Hard reset" +msgstr "재시작" msgid "ACPI shutdown" -msgstr "ACPI shutdown" +msgstr "ACPI 종료" msgid "Hard disk (%s)" msgstr "하드 ë””ìŠ¤í¬ (%s)" @@ -1183,3 +1198,29 @@ msgstr "2% ë‚®ì€ íšŒì „ìˆ˜" msgid "(System Default)" msgstr "(시스템 기본값)" +msgid "Failed to initialize network driver" +msgstr "ë„¤íŠ¸ì›Œí¬ ë“œë¼ì´ë²„를 초기화하지 못했습니다" + +msgid "The network configuration will be switched to the null driver" +msgstr "ë„¤íŠ¸ì›Œí¬ êµ¬ì„±ì´ ë„ ë“œë¼ì´ë²„로 전환ë©ë‹ˆë‹¤" + +msgid "Mouse sensitivity:" +msgstr "마우스 ê°ë„:" + +msgid "Select media images from program working directory" +msgstr "프로그램 작업 디렉토리ì—서 미디어 ì´ë¯¸ì§€ ì„ íƒ" + +msgid "PIT mode:" +msgstr "PIT 모드:" + +msgid "Auto" +msgstr "ìžë™" + +msgid "Slow" +msgstr "ëŠë¦°" + +msgid "Fast" +msgstr "빠른" + +msgid "&Auto-pause on focus loss" +msgstr "집중력 저하 시 ìžë™ ì¼ì‹œ 중지(&A)" diff --git a/src/qt/languages/pl-PL.po b/src/qt/languages/pl-PL.po index 5c60b1eda..b24e338f4 100644 --- a/src/qt/languages/pl-PL.po +++ b/src/qt/languages/pl-PL.po @@ -76,6 +76,24 @@ msgstr "1.&5x" msgid "&2x" msgstr "&2x" +msgid "&3x" +msgstr "&3x" + +msgid "&4x" +msgstr "&4x" + +msgid "&5x" +msgstr "&5x" + +msgid "&6x" +msgstr "&6x" + +msgid "&7x" +msgstr "&7x" + +msgid "&8x" +msgstr "&8x" + msgid "Filter method" msgstr "Metoda filtrowania" @@ -106,6 +124,9 @@ msgstr "&Kwadratowe piksele (Zachowaj proporcje)" msgid "&Integer scale" msgstr "&Skalowanie caÅ‚kowite" +msgid "4:&3 Integer scale" +msgstr "Skalowanie caÅ‚kowite 4:&3" + msgid "E&GA/(S)VGA settings" msgstr "Ustawienia E&GA/(S)VGA" @@ -226,8 +247,8 @@ msgstr "P&usty" msgid "&Reload previous image" msgstr "&PrzeÅ‚aduj poprzedni obraz" -msgid "&Image" -msgstr "&Obraz" +msgid "&Folder..." +msgstr "&Teczka..." msgid "Target &framerate" msgstr "Docelowa &liczba klatek na sekundÄ™" @@ -364,6 +385,12 @@ msgstr "Wideo:" msgid "Voodoo Graphics" msgstr "Grafika Voodoo" +msgid "IBM 8514/a Graphics" +msgstr "Grafika IBM 8514/a" + +msgid "XGA Graphics" +msgstr "Grafika XGA" + msgid "Mouse:" msgstr "Mysz:" @@ -382,8 +409,17 @@ msgstr "Joystick 3..." msgid "Joystick 4..." msgstr "Joystick 4..." -msgid "Sound card:" -msgstr "Karta dźwiÄ™kowa:" +msgid "Sound card 1:" +msgstr "Karta dźwiÄ™kowa 1:" + +msgid "Sound card 2:" +msgstr "Karta dźwiÄ™kowa 2:" + +msgid "Sound card 3:" +msgstr "Karta dźwiÄ™kowa 3:" + +msgid "Sound card 4:" +msgstr "Karta dźwiÄ™kowa 4:" msgid "MIDI Out Device:" msgstr "UrzÄ…dzenie wyjÅ›ciowe MIDI:" @@ -394,18 +430,18 @@ msgstr "UrzÄ…dzenie wejÅ›ciowe MIDI:" msgid "Standalone MPU-401" msgstr "Samodzielne urzÄ…dzenie MPU-401" -msgid "Innovation SSI-2001" -msgstr "Innovation SSI-2001" - -msgid "CMS / Game Blaster" -msgstr "CMS / Game Blaster" - -msgid "Gravis Ultrasound" -msgstr "Gravis Ultrasound" - msgid "Use FLOAT32 sound" msgstr "Użyj dźwiÄ™ku FLOAT32" +msgid "FM synth driver" +msgstr "Sterownik syntezy FM" + +msgid "Nuked (more accurate)" +msgstr "Nuked (dokÅ‚adniejszy)" + +msgid "YMFM (faster)" +msgstr "YMFM (szybszy)" + msgid "Network type:" msgstr "Rodzaj sieci:" @@ -550,6 +586,9 @@ msgstr "Sprawdzaj BPB" msgid "CD-ROM drives:" msgstr "NapÄ™dy CD-ROM:" +msgid "Earlier drive" +msgstr "WczeÅ›niejszy napÄ™d" + msgid "MO drives:" msgstr "NapÄ™dy MO:" @@ -688,9 +727,6 @@ msgstr "NaciÅ›nij klawisze F8+F12 w celu uwolnienia myszy" msgid "Press F8+F12 or middle button to release mouse" msgstr "NaciÅ›nij klawisze F8+F12 lub Å›rodkowy przycisk w celu uwolnienia myszy" -msgid "Unable to initialize FluidSynth" -msgstr "Nie można zainicjować FluidSynth" - msgid "Bus" msgstr "Magistrala" @@ -775,9 +811,6 @@ msgstr "Zaawansowane obrazy sektorów" msgid "Flux images" msgstr "Flux images" -msgid "Unable to initialize FreeType" -msgstr "Nie można zainicjować FreeType" - msgid "Unable to initialize SDL, SDL2.dll is required" msgstr "Nie można zainicjować SDL, wymagany SDL2.dll" @@ -823,8 +856,8 @@ msgstr "O 86Box" msgid "86Box v" msgstr "86Box v" -msgid "An emulator of old computers\n\nAuthors: Sarah Walker, Miran Grca, Fred N. van Kempen (waltje), SA1988, Tiseno100, reenigne, leilei, JohnElliott, greatpsycho, and others.\n\nReleased under the GNU General Public License version 2 or later. See LICENSE for more information." -msgstr "Emulator starych komputerów\n\nAutorzy: Sarah Walker, Miran Grca, Fred N. van Kempen (waltje), SA1988, Tiseno100, reenigne, leilei, JohnElliott, greatpsycho, i inni.\n\nPrzetÅ‚umaczony przez: Fanta-Shokata\n\nWydany na licencji GNU General Public License w wersji 2 lub nowszej. Zobacz LICENSE aby uzyskać wiÄ™cej informacji." +msgid "An emulator of old computers\n\nAuthors: Miran GrÄa (OBattler), RichardG867, Jasmine Iwanek, TC1995, coldbrewed, Teemu Korhonen (Manaatti), Joakim L. Gilje, Adrien Moulin (elyosh), Daniel Balsom (gloriouscow), Cacodemon345, Fred N. van Kempen (waltje), Tiseno100, reenigne, and others.\n\nWith previous core contributions from Sarah Walker, leilei, JohnElliott, greatpsycho, and others.\n\nReleased under the GNU General Public License version 2 or later. See LICENSE for more information." +msgstr "Emulator starych komputerów\n\nAutorzy: Miran GrÄa (OBattler), RichardG867, Jasmine Iwanek, TC1995, coldbrewed, Teemu Korhonen (Manaatti), Joakim L. Gilje, Adrien Moulin (elyosh), Daniel Balsom (gloriouscow), Cacodemon345, Fred N. van Kempen (waltje), Tiseno100, reenigne, i inni.\n\nWith previous core contributions from Sarah Walker, leilei, JohnElliott, greatpsycho, i inni.\n\nPrzetÅ‚umaczony przez: Fanta-Shokata\n\nWydany na licencji GNU General Public License w wersji 2 lub nowszej. Zobacz LICENSE aby uzyskać wiÄ™cej informacji." msgid "Hardware not available" msgstr "SprzÄ™t niedostÄ™pny" @@ -841,15 +874,6 @@ msgstr "Sprawdź, czy libpcap jest zainstalowany i czy posiadasz połączenie si msgid "Invalid configuration" msgstr "NieprawidÅ‚owa konfiguracja" -msgid "freetype.dll" -msgstr "freetype.dll" - -msgid "libfreetype" -msgstr "libfreetype" - -msgid " is required for ESC/P printer emulation." -msgstr " jest wymagany do emulacji drukarki ESC-P." - msgid "gsdll32.dll" msgstr "gsdll32.dll" @@ -859,15 +883,6 @@ msgstr "libgs" msgid " is required for automatic conversion of PostScript files to PDF.\n\nAny documents sent to the generic PostScript printer will be saved as PostScript (.ps) files." msgstr " jest wymagany do automatycznej konwersji plików PostScript do PDF.\n\nDokumenty wysÅ‚ane do ogólnej drukarki PostScript zostanÄ… zapisane jako pliki PostScript (.ps)." -msgid "libfluidsynth.dll" -msgstr "libfluidsynth.dll" - -msgid "libfluidsynth" -msgstr "libfluidsynth" - -msgid " is required for FluidSynth MIDI output." -msgstr " jest wymagany dla wyjÅ›cia FluidSynth MIDI." - msgid "Entering fullscreen mode" msgstr "Przechodzenie do trybu peÅ‚noekranowego" @@ -1183,3 +1198,29 @@ msgstr "2% poniżej idealnych obrotów" msgid "(System Default)" msgstr "(DomyÅ›lne ustawienie systemowe)" +msgid "Failed to initialize network driver" +msgstr "Nie udaÅ‚o siÄ™ zainicjować sterownika sieciowego" + +msgid "The network configuration will be switched to the null driver" +msgstr "Konfiguracja sieci zostanie przełączona na sterownik null" + +msgid "Mouse sensitivity:" +msgstr "Wrażliwość myszy:" + +msgid "Select media images from program working directory" +msgstr "Wybór obrazów multimedialnych z katalogu roboczego programu" + +msgid "PIT mode:" +msgstr "Tryb PIT:" + +msgid "Auto" +msgstr "Automatyczny" + +msgid "Slow" +msgstr "Powolny" + +msgid "Fast" +msgstr "Szybki" + +msgid "&Auto-pause on focus loss" +msgstr "&Automatyczna pauza po utracie fokusu" diff --git a/src/qt/languages/pt-BR.po b/src/qt/languages/pt-BR.po index 7d1eecb09..0db661b4f 100644 --- a/src/qt/languages/pt-BR.po +++ b/src/qt/languages/pt-BR.po @@ -76,6 +76,24 @@ msgstr "1,&5x" msgid "&2x" msgstr "&2x" +msgid "&3x" +msgstr "&3x" + +msgid "&4x" +msgstr "&4x" + +msgid "&5x" +msgstr "&5x" + +msgid "&6x" +msgstr "&6x" + +msgid "&7x" +msgstr "&7x" + +msgid "&8x" +msgstr "&8x" + msgid "Filter method" msgstr "Método de filtragem" @@ -106,6 +124,9 @@ msgstr "Pixel&s quadrados (manter proporção)" msgid "&Integer scale" msgstr "&Redimensionamento com valores inteiros" +msgid "4:&3 Integer scale" +msgstr "Redimensionamento com valores inteiros 4:&3" + msgid "E&GA/(S)VGA settings" msgstr "Configurações E&GA/(S)VGA" @@ -116,7 +137,7 @@ msgid "VGA screen &type" msgstr "&Tipo de tela VGA" msgid "RGB &Color" -msgstr "&Cor RGB" +msgstr "&Cores RGB" msgid "&RGB Grayscale" msgstr "Tons de cinza &RGB" @@ -226,8 +247,8 @@ msgstr "&Vazio" msgid "&Reload previous image" msgstr "&Recarregar imagem anterior" -msgid "&Image" -msgstr "&Imagem" +msgid "&Folder..." +msgstr "&Pasta..." msgid "Target &framerate" msgstr "&Taxa de quadro pretendida" @@ -347,13 +368,13 @@ msgid "Time synchronization" msgstr "Sincronização da hora" msgid "Disabled" -msgstr "Desativada" +msgstr "Desativar" msgid "Enabled (local time)" -msgstr "Ativada (hora local)" +msgstr "Ativar (hora local)" msgid "Enabled (UTC)" -msgstr "Ativada (UTC)" +msgstr "Ativar (UTC)" msgid "Dynamic Recompiler" msgstr "Recompilador dinâmico" @@ -364,6 +385,12 @@ msgstr "Vídeo:" msgid "Voodoo Graphics" msgstr "3DFX Voodoo" +msgid "IBM 8514/a Graphics" +msgstr "Gráficos IBM 8514/a" + +msgid "XGA Graphics" +msgstr "Gráficos XGA" + msgid "Mouse:" msgstr "Mouse:" @@ -382,30 +409,39 @@ msgstr "Joystick 3..." msgid "Joystick 4..." msgstr "Joystick 4..." -msgid "Sound card:" -msgstr "Placa de som:" +msgid "Sound card 1:" +msgstr "Placa de som 1:" + +msgid "Sound card 2:" +msgstr "Placa de som 2:" + +msgid "Sound card 3:" +msgstr "Placa de som 3:" + +msgid "Sound card 4:" +msgstr "Placa de som 4:" msgid "MIDI Out Device:" -msgstr "Disp. saída MIDI:" +msgstr "Disp. de saída MIDI:" msgid "MIDI In Device:" -msgstr "Disp. entrada MIDI:" +msgstr "Disp. de entrada MIDI:" msgid "Standalone MPU-401" msgstr "MPU-401 autônomo" -msgid "Innovation SSI-2001" -msgstr "Innovation SSI-2001" - -msgid "CMS / Game Blaster" -msgstr "CMS / Game Blaster" - -msgid "Gravis Ultrasound" -msgstr "Gravis Ultrasound" - msgid "Use FLOAT32 sound" msgstr "Usar som FLOAT32" +msgid "FM synth driver" +msgstr "Controlador de sint. FM" + +msgid "Nuked (more accurate)" +msgstr "Nuked (mais preciso)" + +msgid "YMFM (faster)" +msgstr "YMFM (mais rápido)" + msgid "Network type:" msgstr "Tipo de rede:" @@ -506,7 +542,7 @@ msgid "&Remove" msgstr "&Remover" msgid "Bus:" -msgstr "Bar.:" +msgstr "Barramento:" msgid "Channel:" msgstr "Canal:" @@ -536,7 +572,7 @@ msgid "Image Format:" msgstr "Formato:" msgid "Block Size:" -msgstr "Bloco:" +msgstr "Blocos:" msgid "Floppy drives:" msgstr "Unidades de disquete:" @@ -550,6 +586,9 @@ msgstr "Verificar BPB" msgid "CD-ROM drives:" msgstr "Unidades de CD-ROM:" +msgid "Earlier drive" +msgstr "Unidade anterior" + msgid "MO drives:" msgstr "Unidades magneto-ópticas:" @@ -599,7 +638,7 @@ msgid "Fatal error" msgstr "Erro fatal" msgid " - PAUSED" -msgstr " - PAUSED" +msgstr " - PAUSADO" msgid "Press Ctrl+Alt+PgDn to return to windowed mode." msgstr "Use Ctrl+Alt+PgDn para retornar ao modo janela" @@ -688,9 +727,6 @@ msgstr "Aperte F8+F12 para liberar o mouse" msgid "Press F8+F12 or middle button to release mouse" msgstr "Aperte F8+F12 ou botão do meio para liberar o mouse" -msgid "Unable to initialize FluidSynth" -msgstr "Não foi possível inicializar o FluidSynth" - msgid "Bus" msgstr "Barramento" @@ -749,7 +785,7 @@ msgid "Microsoft SideWinder Pad" msgstr "Microsoft SideWinder Pad" msgid "Thrustmaster Flight Control System" -msgstr "Thrustmaster Flight Control System" +msgstr "Sistema de Controle de Voo Thrustmaster" msgid "None" msgstr "Nada" @@ -775,9 +811,6 @@ msgstr "Imagens de setor avançado" msgid "Flux images" msgstr "Imagens de fluxo" -msgid "Unable to initialize FreeType" -msgstr "Não foi possível inicializar o FreeType" - msgid "Unable to initialize SDL, SDL2.dll is required" msgstr "Não é possível inicializar o SDL, é necessário o SDL2.dll" @@ -823,8 +856,8 @@ msgstr "Sobre o 86Box" msgid "86Box v" msgstr "86Box versão" -msgid "An emulator of old computers\n\nAuthors: Sarah Walker, Miran Grca, Fred N. van Kempen (waltje), SA1988, Tiseno100, reenigne, leilei, JohnElliott, greatpsycho, and others.\n\nReleased under the GNU General Public License version 2 or later. See LICENSE for more information." -msgstr "Um emulador de computadores antigos\n\nAutores: Sarah Walker, Miran Grca, Fred N. van Kempen (waltje), SA1988, Tiseno100, reenigne, leilei, JohnElliott, greatpsycho, e outros.\n\nTraduzido por: Altieres Lima da Silva\n\nLançado sob a Licença Pública Geral GNU versão 2 ou posterior. Veja o arquivo LICENSE para mais informações." +msgid "An emulator of old computers\n\nAuthors: Miran GrÄa (OBattler), RichardG867, Jasmine Iwanek, TC1995, coldbrewed, Teemu Korhonen (Manaatti), Joakim L. Gilje, Adrien Moulin (elyosh), Daniel Balsom (gloriouscow), Cacodemon345, Fred N. van Kempen (waltje), Tiseno100, reenigne, and others.\n\nWith previous core contributions from Sarah Walker, leilei, JohnElliott, greatpsycho, and others.\n\nReleased under the GNU General Public License version 2 or later. See LICENSE for more information." +msgstr "Um emulador de computadores antigos\n\nAutores: Miran GrÄa (OBattler), RichardG867, Jasmine Iwanek, TC1995, coldbrewed, Teemu Korhonen (Manaatti), Joakim L. Gilje, Adrien Moulin (elyosh), Daniel Balsom (gloriouscow), Cacodemon345, Fred N. van Kempen (waltje), Tiseno100, reenigne, e outros.\n\nWith previous core contributions from Sarah Walker, leilei, JohnElliott, greatpsycho, e outros.\n\nTraduzido por: Altieres Lima da Silva\n\nLançado sob a Licença Pública Geral GNU versão 2 ou posterior. Veja o arquivo LICENSE para mais informações." msgid "Hardware not available" msgstr "Hardware não disponível" @@ -841,15 +874,6 @@ msgstr "Certifique-se de que libpcap esteja instalado e que você tenha uma cone msgid "Invalid configuration" msgstr "Configuração inválida" -msgid "freetype.dll" -msgstr "freetype.dll" - -msgid "libfreetype" -msgstr "libfreetype" - -msgid " is required for ESC/P printer emulation." -msgstr " é necessário para emulação de impressora ESC/P." - msgid "gsdll32.dll" msgstr "gsdll32.dll" @@ -859,15 +883,6 @@ msgstr "libgs" msgid " is required for automatic conversion of PostScript files to PDF.\n\nAny documents sent to the generic PostScript printer will be saved as PostScript (.ps) files." msgstr " é necessário para a conversão automática de arquivos PostScript para PDF.\n\nQualquer documento enviado para a impressora genérica PostScript será salvo como arquivos PostScript (.ps)." -msgid "libfluidsynth.dll" -msgstr "libfluidsynth.dll" - -msgid "libfluidsynth" -msgstr "libfluidsynth" - -msgid " is required for FluidSynth MIDI output." -msgstr " é necessário para a saída MIDI FluidSynth." - msgid "Entering fullscreen mode" msgstr "Entrando no modo de tela cheia" @@ -1183,3 +1198,29 @@ msgstr "2% abaixo das RPM perfeita" msgid "(System Default)" msgstr "(Padrão do sistema)" +msgid "Failed to initialize network driver" +msgstr "Falha ao inicializar o driver de rede" + +msgid "The network configuration will be switched to the null driver" +msgstr "A configuração de rede será alterada para o driver nulo" + +msgid "Mouse sensitivity:" +msgstr "Sensibilidade do rato:" + +msgid "Select media images from program working directory" +msgstr "Selecione imagens de mídia do diretório de trabalho do programa" + +msgid "PIT mode:" +msgstr "Modo PIT:" + +msgid "Auto" +msgstr "Automático" + +msgid "Slow" +msgstr "Lento" + +msgid "Fast" +msgstr "Rápido" + +msgid "&Auto-pause on focus loss" +msgstr "Pausa &automática ao perder o foco" diff --git a/src/qt/languages/pt-PT.po b/src/qt/languages/pt-PT.po index 301b52566..8f080e423 100644 --- a/src/qt/languages/pt-PT.po +++ b/src/qt/languages/pt-PT.po @@ -76,6 +76,24 @@ msgstr "1.&5x" msgid "&2x" msgstr "&2x" +msgid "&3x" +msgstr "&3x" + +msgid "&4x" +msgstr "&4x" + +msgid "&5x" +msgstr "&5x" + +msgid "&6x" +msgstr "&6x" + +msgid "&7x" +msgstr "&7x" + +msgid "&8x" +msgstr "&8x" + msgid "Filter method" msgstr "Método de filtragem" @@ -106,6 +124,9 @@ msgstr "Pixels &quadrados (Manter rácio)" msgid "&Integer scale" msgstr "Escala &inteira" +msgid "4:&3 Integer scale" +msgstr "Escala inteira 4:&3" + msgid "E&GA/(S)VGA settings" msgstr "Definições E&GA/(S)VGA" @@ -226,8 +247,8 @@ msgstr "&CDROM vazio" msgid "&Reload previous image" msgstr "&Recarregar imagem anterior" -msgid "&Image" -msgstr "&Imagem" +msgid "&Folder..." +msgstr "&Pasta..." msgid "Target &framerate" msgstr "&Taxa de quadros de destino" @@ -364,6 +385,12 @@ msgstr "Vídeo:" msgid "Voodoo Graphics" msgstr "Gráficos Voodoo" +msgid "IBM 8514/a Graphics" +msgstr "Gráficos IBM 8514/a" + +msgid "XGA Graphics" +msgstr "Gráficos XGA" + msgid "Mouse:" msgstr "Rato:" @@ -382,8 +409,17 @@ msgstr "Joystick 3..." msgid "Joystick 4..." msgstr "Joystick 4..." -msgid "Sound card:" -msgstr "Placa de som:" +msgid "Sound card 1:" +msgstr "Placa de som 1:" + +msgid "Sound card 2:" +msgstr "Placa de som 2:" + +msgid "Sound card 3:" +msgstr "Placa de som 3:" + +msgid "Sound card 4:" +msgstr "Placa de som 4:" msgid "MIDI Out Device:" msgstr "Disp. saída MIDI:" @@ -394,18 +430,18 @@ msgstr "Disp. entrada MIDI:" msgid "Standalone MPU-401" msgstr "MPU-401 autónomo" -msgid "Innovation SSI-2001" -msgstr "Innovation SSI-2001" - -msgid "CMS / Game Blaster" -msgstr "CMS / Game Blaster" - -msgid "Gravis Ultrasound" -msgstr "Gravis Ultrasound" - msgid "Use FLOAT32 sound" msgstr "Utilizar som FLOAT32" +msgid "FM synth driver" +msgstr "Controlador de sint. FM" + +msgid "Nuked (more accurate)" +msgstr "Nuked (mais exacto)" + +msgid "YMFM (faster)" +msgstr "YMFM (mais rápido)" + msgid "Network type:" msgstr "Tipo de rede:" @@ -550,6 +586,9 @@ msgstr "Verificar BPB" msgid "CD-ROM drives:" msgstr "Unidades CD-ROM:" +msgid "Earlier drive" +msgstr "Unidade anterior" + msgid "MO drives:" msgstr "Unidades magneto-ópticas:" @@ -688,9 +727,6 @@ msgstr "Pressione F8+F12 para soltar o rato" msgid "Press F8+F12 or middle button to release mouse" msgstr "Pressione F8+F12 ou tecla média para soltar o rato" -msgid "Unable to initialize FluidSynth" -msgstr "Não foi possível inicializar o FluidSynth" - msgid "Bus" msgstr "Barramento" @@ -775,9 +811,6 @@ msgstr "Imagens avançadas de sector" msgid "Flux images" msgstr "Imagens de fluxo" -msgid "Unable to initialize FreeType" -msgstr "Não foi possível inicializar o FreeType" - msgid "Unable to initialize SDL, SDL2.dll is required" msgstr "Não foi possível inicializar o SDL. O ficheiro SDL2.dll é necessário!" @@ -823,8 +856,8 @@ msgstr "Acerca do 86Box" msgid "86Box v" msgstr "86Box v" -msgid "An emulator of old computers\n\nAuthors: Sarah Walker, Miran Grca, Fred N. van Kempen (waltje), SA1988, Tiseno100, reenigne, leilei, JohnElliott, greatpsycho, and others.\n\nReleased under the GNU General Public License version 2 or later. See LICENSE for more information." -msgstr "Um emulador de computadores antigos\n\nAutores: Sarah Walker, Miran Grca, Fred N. van Kempen (waltje), SA1988, Tiseno100, reenigne, leilei, JohnElliott, greatpsycho, and others.\n\nUsado sob a licença GNU General Public License versão 2 ou posterior. Veja o ficheiro LICENSE para mais informações." +msgid "An emulator of old computers\n\nAuthors: Miran GrÄa (OBattler), RichardG867, Jasmine Iwanek, TC1995, coldbrewed, Teemu Korhonen (Manaatti), Joakim L. Gilje, Adrien Moulin (elyosh), Daniel Balsom (gloriouscow), Cacodemon345, Fred N. van Kempen (waltje), Tiseno100, reenigne, and others.\n\nWith previous core contributions from Sarah Walker, leilei, JohnElliott, greatpsycho, and others.\n\nReleased under the GNU General Public License version 2 or later. See LICENSE for more information." +msgstr "Um emulador de computadores antigos\n\nAutores: Miran GrÄa (OBattler), RichardG867, Jasmine Iwanek, TC1995, coldbrewed, Teemu Korhonen (Manaatti), Joakim L. Gilje, Adrien Moulin (elyosh), Daniel Balsom (gloriouscow), Cacodemon345, Fred N. van Kempen (waltje), Tiseno100, reenigne, and others.\n\nWith previous core contributions from Sarah Walker, leilei, JohnElliott, greatpsycho, and others.\n\nUsado sob a licença GNU General Public License versão 2 ou posterior. Veja o ficheiro LICENSE para mais informações." msgid "Hardware not available" msgstr "Hardware não disponível" @@ -841,15 +874,6 @@ msgstr "Certifique-se de que a biblioteca libpcap está instalada e de que está msgid "Invalid configuration" msgstr "Configuração inválida" -msgid "freetype.dll" -msgstr "freetype.dll" - -msgid "libfreetype" -msgstr "libfreetype" - -msgid " is required for ESC/P printer emulation." -msgstr " é requerida para a emulação de impressora ESC/P." - msgid "gsdll32.dll" msgstr "gsdll32.dll" @@ -859,15 +883,6 @@ msgstr "libgs" msgid " is required for automatic conversion of PostScript files to PDF.\n\nAny documents sent to the generic PostScript printer will be saved as PostScript (.ps) files." msgstr " é requerido para a conversão automática de ficheiros PostScript para ficheiros PDF.\n\nQualquer documento enviado para a impressora PostScript genérica será gravado como um ficheiro PostScript (.ps)." -msgid "libfluidsynth.dll" -msgstr "libfluidsynth.dll" - -msgid "libfluidsynth" -msgstr "libfluidsynth" - -msgid " is required for FluidSynth MIDI output." -msgstr " é necessário para a saída MIDI FluidSynth MIDI." - msgid "Entering fullscreen mode" msgstr "A entrar no modo de ecrã cheio" @@ -920,28 +935,28 @@ msgid "Cartridge images" msgstr "Imagens de cartucho" msgid "Error initializing renderer" -msgstr "Error initializing renderer" +msgstr "Erro na inicialização do renderizador" msgid "OpenGL (3.0 Core) renderer could not be initialized. Use another renderer." -msgstr "OpenGL (3.0 Core) renderer could not be initialized. Use another renderer." +msgstr "Não foi possível inicializar o renderizador OpenGL (3.0 Core). Utilize outro renderizador." msgid "Resume execution" -msgstr "Resume execution" +msgstr "Retomar execução" msgid "Pause execution" -msgstr "Pause execution" +msgstr "Pausar execução" msgid "Press Ctrl+Alt+Del" -msgstr "Press Ctrl+Alt+Del" +msgstr "Ctrl+Alt+Del" msgid "Press Ctrl+Alt+Esc" -msgstr "Press Ctrl+Alt+Esc" +msgstr "Ctrl+Alt+Esc" msgid "Hard reset" -msgstr "Hard reset" +msgstr "Reinicialização completa" msgid "ACPI shutdown" -msgstr "ACPI shutdown" +msgstr "Encerramento ACPI" msgid "Hard disk (%s)" msgstr "Disco rígido (%s)" @@ -1183,3 +1198,29 @@ msgstr "RPM 2% abaixo do RPM perfeito" msgid "(System Default)" msgstr "(Padrão do sistema)" +msgid "Failed to initialize network driver" +msgstr "Falha ao inicializar o driver de rede" + +msgid "The network configuration will be switched to the null driver" +msgstr "A configuração da rede será alterada para o controlador nulo" + +msgid "Mouse sensitivity:" +msgstr "Sensibilidade do rato:" + +msgid "Select media images from program working directory" +msgstr "Selecionar imagens multimédia do diretório de trabalho do programa" + +msgid "PIT mode:" +msgstr "Modo PIT:" + +msgid "Auto" +msgstr "Automático" + +msgid "Slow" +msgstr "Lento" + +msgid "Fast" +msgstr "Rápido" + +msgid "&Auto-pause on focus loss" +msgstr "Pausa &automática na perda de focagem" diff --git a/src/qt/languages/ru-RU.po b/src/qt/languages/ru-RU.po index a33cc81dd..b0bcc0e1e 100644 --- a/src/qt/languages/ru-RU.po +++ b/src/qt/languages/ru-RU.po @@ -76,6 +76,24 @@ msgstr "1.&5x" msgid "&2x" msgstr "&2x" +msgid "&3x" +msgstr "&3x" + +msgid "&4x" +msgstr "&4x" + +msgid "&5x" +msgstr "&5x" + +msgid "&6x" +msgstr "&6x" + +msgid "&7x" +msgstr "&7x" + +msgid "&8x" +msgstr "&8x" + msgid "Filter method" msgstr "Метод фильтрации" @@ -106,6 +124,9 @@ msgstr "&Квадратные пикÑели (Ñохранить Ñоотнош msgid "&Integer scale" msgstr "&ЦелочиÑленное маÑштабирование" +msgid "4:&3 Integer scale" +msgstr "4:&3 ЦелочиÑленное маÑштабирование" + msgid "E&GA/(S)VGA settings" msgstr "ÐаÑтройки E&GA/(S)VGA" @@ -226,8 +247,8 @@ msgstr "П&уÑтой" msgid "&Reload previous image" msgstr "&Снова загрузить предыдущий образ" -msgid "&Image" -msgstr "&Образ..." +msgid "&Folder..." +msgstr "&Папка..." msgid "Target &framerate" msgstr "Ð¦ÐµÐ»ÐµÐ²Ð°Ñ &чаÑтота кадров" @@ -364,6 +385,12 @@ msgstr "Видеокарта:" msgid "Voodoo Graphics" msgstr "УÑкоритель Voodoo" +msgid "IBM 8514/a Graphics" +msgstr "УÑкоритель IBM 8514/a" + +msgid "XGA Graphics" +msgstr "УÑкоритель XGA" + msgid "Mouse:" msgstr "Мышь:" @@ -382,8 +409,17 @@ msgstr "ДжойÑтик 3..." msgid "Joystick 4..." msgstr "ДжойÑтик 4..." -msgid "Sound card:" -msgstr "Ð—Ð²ÑƒÐºÐ¾Ð²Ð°Ñ ÐºÐ°Ñ€Ñ‚Ð°:" +msgid "Sound card 1:" +msgstr "Ð—Ð²ÑƒÐºÐ¾Ð²Ð°Ñ ÐºÐ°Ñ€Ñ‚Ð° 1:" + +msgid "Sound card 2:" +msgstr "Ð—Ð²ÑƒÐºÐ¾Ð²Ð°Ñ ÐºÐ°Ñ€Ñ‚Ð° 2:" + +msgid "Sound card 3:" +msgstr "Ð—Ð²ÑƒÐºÐ¾Ð²Ð°Ñ ÐºÐ°Ñ€Ñ‚Ð° 3:" + +msgid "Sound card 4:" +msgstr "Ð—Ð²ÑƒÐºÐ¾Ð²Ð°Ñ ÐºÐ°Ñ€Ñ‚Ð° 4:" msgid "MIDI Out Device:" msgstr "MIDI Out уÑтр-во:" @@ -394,18 +430,18 @@ msgstr "MIDI In уÑтр-во:" msgid "Standalone MPU-401" msgstr "Отдельный MPU-401" -msgid "Innovation SSI-2001" -msgstr "Innovation SSI-2001" - -msgid "CMS / Game Blaster" -msgstr "CMS / Game Blaster" - -msgid "Gravis Ultrasound" -msgstr "Gravis Ultrasound" - msgid "Use FLOAT32 sound" msgstr "FLOAT32 звук" +msgid "FM synth driver" +msgstr "Драйвер FM-Ñинтезатора" + +msgid "Nuked (more accurate)" +msgstr "Nuked (более точный)" + +msgid "YMFM (faster)" +msgstr "YMFM (быÑтрей)" + msgid "Network type:" msgstr "Тип Ñети:" @@ -550,6 +586,9 @@ msgstr "ПроверÑть BPB" msgid "CD-ROM drives:" msgstr "ДиÑководы CD-ROM:" +msgid "Earlier drive" +msgstr "Предыдущий диÑковод" + msgid "MO drives:" msgstr "МагнитооптичеÑкие диÑководы:" @@ -688,9 +727,6 @@ msgstr "Ðажмите F8+F12 чтобы оÑвободить курÑор" msgid "Press F8+F12 or middle button to release mouse" msgstr "Ðажмите F8+F12 или Ñреднюю кнопку мыши чтобы оÑвободить курÑор" -msgid "Unable to initialize FluidSynth" -msgstr "Ðевозможно инициализировать FluidSynth" - msgid "Bus" msgstr "Шина" @@ -775,9 +811,6 @@ msgstr "РаÑширенные образы Ñекторов" msgid "Flux images" msgstr "Образы Flux" -msgid "Unable to initialize FreeType" -msgstr "Ðевозможно инициализировать FreeType" - msgid "Unable to initialize SDL, SDL2.dll is required" msgstr "Ðевозможно инициализировать SDL, требуетÑÑ SDL2.dll" @@ -823,8 +856,8 @@ msgstr "О 86Box" msgid "86Box v" msgstr "86Box v." -msgid "An emulator of old computers\n\nAuthors: Sarah Walker, Miran Grca, Fred N. van Kempen (waltje), SA1988, Tiseno100, reenigne, leilei, JohnElliott, greatpsycho, and others.\n\nReleased under the GNU General Public License version 2 or later. See LICENSE for more information." -msgstr "ЭмулÑтор Ñтарых компьютеров\n\nÐвторы: Sarah Walker, Miran Grca, Fred N. van Kempen (waltje), SA1988, Tiseno100, reenigne, leilei, JohnElliott, greatpsycho, and others.\n\nВыпуÑкаетÑÑ Ð¿Ð¾Ð´ лицензией GNU General Public License верÑии 2 или более поздней. Дополнительную информацию Ñм. в файле LICENSE." +msgid "An emulator of old computers\n\nAuthors: Miran GrÄa (OBattler), RichardG867, Jasmine Iwanek, TC1995, coldbrewed, Teemu Korhonen (Manaatti), Joakim L. Gilje, Adrien Moulin (elyosh), Daniel Balsom (gloriouscow), Cacodemon345, Fred N. van Kempen (waltje), Tiseno100, reenigne, and others.\n\nWith previous core contributions from Sarah Walker, leilei, JohnElliott, greatpsycho, and others.\n\nReleased under the GNU General Public License version 2 or later. See LICENSE for more information." +msgstr "ЭмулÑтор Ñтарых компьютеров\n\nÐвторы: Miran GrÄa (OBattler), RichardG867, Jasmine Iwanek, TC1995, coldbrewed, Teemu Korhonen (Manaatti), Joakim L. Gilje, Adrien Moulin (elyosh), Daniel Balsom (gloriouscow), Cacodemon345, Fred N. van Kempen (waltje), Tiseno100, reenigne, and others.\n\nWith previous core contributions from Sarah Walker, leilei, JohnElliott, greatpsycho, and others.\n\nВыпуÑкаетÑÑ Ð¿Ð¾Ð´ лицензией GNU General Public License верÑии 2 или более поздней. Дополнительную информацию Ñм. в файле LICENSE." msgid "Hardware not available" msgstr "Оборудование недоÑтупно" @@ -841,15 +874,6 @@ msgstr "УбедитеÑÑŒ, что libpcap уÑтановлен и ваше Ñе msgid "Invalid configuration" msgstr "ÐедопуÑÑ‚Ð¸Ð¼Ð°Ñ ÐºÐ¾Ð½Ñ„Ð¸Ð³ÑƒÑ€Ð°Ñ†Ð¸Ñ" -msgid "freetype.dll" -msgstr "freetype.dll" - -msgid "libfreetype" -msgstr "libfreetype" - -msgid " is required for ESC/P printer emulation." -msgstr "Ð”Ð»Ñ ÑмулÑции принтера ESC/P требуетÑÑ libfreetype." - msgid "gsdll32.dll" msgstr "gsdll32.dll" @@ -859,15 +883,6 @@ msgstr "libgs" msgid " is required for automatic conversion of PostScript files to PDF.\n\nAny documents sent to the generic PostScript printer will be saved as PostScript (.ps) files." msgstr " требуетÑÑ Ð´Ð»Ñ Ð°Ð²Ñ‚Ð¾Ð¼Ð°Ñ‚Ð¸Ñ‡ÐµÑкого Ð¿Ñ€ÐµÐ¾Ð±Ñ€Ð°Ð·Ð¾Ð²Ð°Ð½Ð¸Ñ Ñ„Ð°Ð¹Ð»Ð¾Ð² PostScript в PDF.\n\nÐ’Ñе документы, отправленные на общий принтер PostScript, будут Ñохранены в виде файлов PostScript (.ps)." -msgid "libfluidsynth.dll" -msgstr "libfluidsynth.dll" - -msgid "libfluidsynth" -msgstr "libfluidsynth" - -msgid " is required for FluidSynth MIDI output." -msgstr "Ð”Ð»Ñ FluidSynth MIDI-вывода требуетÑÑ libfluidsynth." - msgid "Entering fullscreen mode" msgstr "Вход в полноÑкранный режим" @@ -1183,3 +1198,29 @@ msgstr "Ðа 2% медленнее точного RPM" msgid "(System Default)" msgstr "(СиÑтемный)" +msgid "Failed to initialize network driver" +msgstr "Ðе удалоÑÑŒ инициализировать Ñетевой драйвер" + +msgid "The network configuration will be switched to the null driver" +msgstr "Ð¡ÐµÑ‚ÐµÐ²Ð°Ñ ÐºÐ¾Ð½Ñ„Ð¸Ð³ÑƒÑ€Ð°Ñ†Ð¸Ñ Ð±ÑƒÐ´ÐµÑ‚ переключена на нулевой драйвер" + +msgid "Mouse sensitivity:" +msgstr "ЧувÑтвительноÑть мыши:" + +msgid "Select media images from program working directory" +msgstr "Выбор медиа-образов из рабочего каталога программы" + +msgid "PIT mode:" +msgstr "Режим PIT:" + +msgid "Auto" +msgstr "Ðвто" + +msgid "Slow" +msgstr "Медленный" + +msgid "Fast" +msgstr "БыÑтрый" + +msgid "&Auto-pause on focus loss" +msgstr "&Ðвтопауза при потере фокуÑа" diff --git a/src/qt/languages/sk-SK.po b/src/qt/languages/sk-SK.po new file mode 100644 index 000000000..a8f60b861 --- /dev/null +++ b/src/qt/languages/sk-SK.po @@ -0,0 +1,1226 @@ +msgid "&Action" +msgstr "&Podujatia" + +msgid "&Keyboard requires capture" +msgstr "&Klávesnica vyžaduje záber" + +msgid "&Right CTRL is left ALT" +msgstr "&Pravý Ctrl je ľavý Alt" + +msgid "&Hard Reset..." +msgstr "&ResetovaÅ¥" + +msgid "&Ctrl+Alt+Del\tCtrl+F12" +msgstr "&Ctrl+Alt+Del\tCtrl+F12" + +msgid "Ctrl+Alt+&Esc" +msgstr "Ctrl+Alt+&Esc" + +msgid "&Pause" +msgstr "P&ozastaviÅ¥" + +msgid "E&xit..." +msgstr "&UkonÄiÅ¥" + +msgid "&View" +msgstr "&Zobrazenie" + +msgid "&Hide status bar" +msgstr "&SkryÅ¥ stavový riadok" + +msgid "Hide &toolbar" +msgstr "SkryÅ¥ panel &nástrojov" + +msgid "&Resizeable window" +msgstr "&Premenná veľkosÅ¥ okna" + +msgid "R&emember size && position" +msgstr "&PamätaÅ¥ si veľkosÅ¥ a polohu" + +msgid "Re&nderer" +msgstr "&Renderer" + +msgid "&SDL (Software)" +msgstr "&SDL (Software)" + +msgid "SDL (&Hardware)" +msgstr "SDL (&Hardware)" + +msgid "SDL (&OpenGL)" +msgstr "SDL (&OpenGL)" + +msgid "Open&GL (3.0 Core)" +msgstr "Open&GL (3.0 Core)" + +msgid "&VNC" +msgstr "&VNC" + +msgid "Specify dimensions..." +msgstr "&ZadaÅ¥ veľkosÅ¥..." + +msgid "F&orce 4:3 display ratio" +msgstr "&ZachovaÅ¥ pomer strán 4:3" + +msgid "&Window scale factor" +msgstr "&Násobné zväÄÅ¡enie okna" + +msgid "&0.5x" +msgstr "&0.5x" + +msgid "&1x" +msgstr "&1x" + +msgid "1.&5x" +msgstr "1.&5x" + +msgid "&2x" +msgstr "&2x" + +msgid "&3x" +msgstr "&3x" + +msgid "&4x" +msgstr "&4x" + +msgid "&5x" +msgstr "&5x" + +msgid "&6x" +msgstr "&6x" + +msgid "&7x" +msgstr "&7x" + +msgid "&8x" +msgstr "&8x" + +msgid "Filter method" +msgstr "Spôsob &filtrovania" + +msgid "&Nearest" +msgstr "&Najbližší" + +msgid "&Linear" +msgstr "&Lineárny" + +msgid "Hi&DPI scaling" +msgstr "Å &kálovanie HiDPI" + +msgid "&Fullscreen\tCtrl+Alt+PgUp" +msgstr "&Celá obrazovka\tCtrl+Alt+PgUp" + +msgid "Fullscreen &stretch mode" +msgstr "Režim roztia&hnutia na celú obrazovku" + +msgid "&Full screen stretch" +msgstr "&RozšíriÅ¥" + +msgid "&4:3" +msgstr "&4:3" + +msgid "&Square pixels (Keep ratio)" +msgstr "&ZachovaÅ¥ pomer strán" + +msgid "&Integer scale" +msgstr "&CeloÄíselné Å¡kálovanie" + +msgid "4:&3 Integer scale" +msgstr "4:&3 CeloÄíselné Å¡kálovanie" + +msgid "E&GA/(S)VGA settings" +msgstr "Nastavenia pre E&GA a (S)VGA" + +msgid "&Inverted VGA monitor" +msgstr "&ObrátiÅ¥ farby" + +msgid "VGA screen &type" +msgstr "&Typ monitora VGA" + +msgid "RGB &Color" +msgstr "RGB &farebný" + +msgid "&RGB Grayscale" +msgstr "&Odtiene sivej" + +msgid "&Amber monitor" +msgstr "&Jantárová obrazovka" + +msgid "&Green monitor" +msgstr "&Zelená obrazovka" + +msgid "&White monitor" +msgstr "&Biela obrazovka" + +msgid "Grayscale &conversion type" +msgstr "Konverzia na &odtiene sivej" + +msgid "BT&601 (NTSC/PAL)" +msgstr "BT&601 (NTSC/PAL)" + +msgid "BT&709 (HDTV)" +msgstr "BT&709 (HDTV)" + +msgid "&Average" +msgstr "&Priemer" + +msgid "CGA/PCjr/Tandy/E&GA/(S)VGA overscan" +msgstr "Prekrytie obrazu CGA/PCjr/Tandy/E&GA/(S)VGA" + +msgid "Change contrast for &monochrome display" +msgstr "&Úprava kontrastu Äiernobielej obrazovky" + +msgid "&Media" +msgstr "&Média" + +msgid "&Tools" +msgstr "&Nástroje" + +msgid "&Settings..." +msgstr "&Nastavenia..." + +msgid "&Update status bar icons" +msgstr "&AktualizovaÅ¥ ikony na stavovom riadku" + +msgid "Take s&creenshot\tCtrl+F11" +msgstr "UrobiÅ¥ snímku &obrazovky\tCtrl+F11" + +msgid "&Preferences..." +msgstr "&Predvoľby..." + +msgid "Enable &Discord integration" +msgstr "Povolenie integrácie s &Discordem" + +msgid "Sound &gain..." +msgstr "&Zosilnenie zvuku" + +msgid "Begin trace\tCtrl+T" +msgstr "ZaÄaÅ¥ trace\tCtrl+T" + +msgid "End trace\tCtrl+T" +msgstr "ZastaviÅ¥ trace\tCtrl+T" + +msgid "&Help" +msgstr "&Pomoc" + +msgid "&Documentation..." +msgstr "&Dokumentácia" + +msgid "&About 86Box..." +msgstr "&O programu 86Box" + +msgid "&New image..." +msgstr "&Nový obraz..." + +msgid "&Existing image..." +msgstr "&Existujúci obraz..." + +msgid "Existing image (&Write-protected)..." +msgstr "Existujúci obraz (&ochrana proti zápisu)..." + +msgid "&Record" +msgstr "&NahrávaÅ¥" + +msgid "&Play" +msgstr "&PrehraÅ¥" + +msgid "&Rewind to the beginning" +msgstr "PrevinuÅ¥ na &zaÄiatok" + +msgid "&Fast forward to the end" +msgstr "PrevinuÅ¥ na &koniec" + +msgid "E&ject" +msgstr "&Vystrihnúť" + +msgid "&Image..." +msgstr "&Obraz..." + +msgid "E&xport to 86F..." +msgstr "E&xportovaÅ¥ do 86F..." + +msgid "&Mute" +msgstr "&StíšiÅ¥" + +msgid "E&mpty" +msgstr "&Vystrihnúť" + +msgid "&Reload previous image" +msgstr "&NaÄítaÅ¥ znova predchádzajúci obraz" + +msgid "&Folder..." +msgstr "&Zložka..." + +msgid "Target &framerate" +msgstr "&Cieľová snímková frekvencia" + +msgid "&Sync with video" +msgstr "&SynchronizovaÅ¥ s obrazom" + +msgid "&25 fps" +msgstr "&25 fps" + +msgid "&30 fps" +msgstr "&30 fps" + +msgid "&50 fps" +msgstr "&50 fps" + +msgid "&60 fps" +msgstr "&60 fps" + +msgid "&75 fps" +msgstr "&75 fps" + +msgid "&VSync" +msgstr "&VSync" + +msgid "&Select shader..." +msgstr "&ZvoliÅ¥ shader..." + +msgid "&Remove shader" +msgstr "&OdobraÅ¥ shader" + +msgid "Preferences" +msgstr "Predvoľby" + +msgid "Sound Gain" +msgstr "Zosilnenie zvuku" + +msgid "New Image" +msgstr "Nový obraz" + +msgid "Settings" +msgstr "Nastavenia" + +msgid "Specify Main Window Dimensions" +msgstr "ZadaÅ¥ rozmery hlavného okna" + +msgid "OK" +msgstr "OK" + +msgid "Cancel" +msgstr "Storno" + +msgid "Save these settings as &global defaults" +msgstr "UložiÅ¥ toto nastavenie ako &globálny východiskový stav" + +msgid "&Default" +msgstr "&Východiskové" + +msgid "Language:" +msgstr "Jazyk:" + +msgid "Icon set:" +msgstr "Súprava ikon:" + +msgid "Gain" +msgstr "Zosilnenie" + +msgid "File name:" +msgstr "Názov súboru:" + +msgid "Disk size:" +msgstr "VeľkosÅ¥ disku:" + +msgid "RPM mode:" +msgstr "Režim ot./m:" + +msgid "Progress:" +msgstr "Priebeh:" + +msgid "Width:" +msgstr "Šírka:" + +msgid "Height:" +msgstr "Výška:" + +msgid "Lock to this size" +msgstr "Uzamknúť na tieto rozmery" + +msgid "Machine type:" +msgstr "Typ poÄítaÄa:" + +msgid "Machine:" +msgstr "PoÄítaÄ:" + +msgid "Configure" +msgstr "NastaviÅ¥" + +msgid "CPU type:" +msgstr "Procesor:" + +msgid "Speed:" +msgstr "RýchlosÅ¥:" + +msgid "FPU:" +msgstr "Koprocesor:" + +msgid "Wait states:" +msgstr "ÄŒakacie stavy:" + +msgid "MB" +msgstr "MB" + +msgid "Memory:" +msgstr "Pamäť:" + +msgid "Time synchronization" +msgstr "Synchronizácia Äasu" + +msgid "Disabled" +msgstr "Vypnutá" + +msgid "Enabled (local time)" +msgstr "Zapnutá (miestny Äas)" + +msgid "Enabled (UTC)" +msgstr "Zapnutá (UTC)" + +msgid "Dynamic Recompiler" +msgstr "Dynamický prekladaÄ" + +msgid "Video:" +msgstr "Grafika:" + +msgid "Voodoo Graphics" +msgstr "PoužiÅ¥ grafický akcelerátor Voodoo" + +msgid "IBM 8514/a Graphics" +msgstr "Grafika IBM 8514/a" + +msgid "XGA Graphics" +msgstr "Grafika XGA" + +msgid "Mouse:" +msgstr "MyÅ¡:" + +msgid "Joystick:" +msgstr "Joystick:" + +msgid "Joystick 1..." +msgstr "Joystick 1..." + +msgid "Joystick 2..." +msgstr "Joystick 2..." + +msgid "Joystick 3..." +msgstr "Joystick 3..." + +msgid "Joystick 4..." +msgstr "Joystick 4..." + +msgid "Sound card 1:" +msgstr "Zvuková karta 1:" + +msgid "Sound card 2:" +msgstr "Zvuková karta 2:" + +msgid "Sound card 3:" +msgstr "Zvuková karta 3:" + +msgid "Sound card 4:" +msgstr "Zvuková karta 4:" + +msgid "MIDI Out Device:" +msgstr "MIDI výstup:" + +msgid "MIDI In Device:" +msgstr "MIDI vstup:" + +msgid "Standalone MPU-401" +msgstr "Samostatný MPU-401" + +msgid "Use FLOAT32 sound" +msgstr "PoužiÅ¥ zvuk FLOAT32" + +msgid "FM synth driver" +msgstr "OvládaÄ FM syntetizátora" + +msgid "Nuked (more accurate)" +msgstr "Nuked (presnejší)" + +msgid "YMFM (faster)" +msgstr "YMFM (rýchlejší)" + +msgid "Network type:" +msgstr "Druh siete:" + +msgid "PCap device:" +msgstr "PCap zariadenia:" + +msgid "Network adapter:" +msgstr "SieÅ¥ový adaptér:" + +msgid "COM1 Device:" +msgstr "Zariadenie na COM1:" + +msgid "COM2 Device:" +msgstr "Zariadenie na COM2:" + +msgid "COM3 Device:" +msgstr "Zariadenie na COM3:" + +msgid "COM4 Device:" +msgstr "Zariadenie na COM4:" + +msgid "LPT1 Device:" +msgstr "Zariadenie na LPT1:" + +msgid "LPT2 Device:" +msgstr "Zariadenie na LPT2:" + +msgid "LPT3 Device:" +msgstr "Zariadenie na LPT3:" + +msgid "LPT4 Device:" +msgstr "Zariadenie na LPT4:" + +msgid "Serial port 1" +msgstr "PovoliÅ¥ port COM1" + +msgid "Serial port 2" +msgstr "PovoliÅ¥ port COM2" + +msgid "Serial port 3" +msgstr "PovoliÅ¥ port COM3" + +msgid "Serial port 4" +msgstr "PovoliÅ¥ port COM4" + +msgid "Parallel port 1" +msgstr "PovoliÅ¥ port LPT1" + +msgid "Parallel port 2" +msgstr "PovoliÅ¥ port LPT2" + +msgid "Parallel port 3" +msgstr "PovoliÅ¥ port LPT3" + +msgid "Parallel port 4" +msgstr "PovoliÅ¥ port LPT4" + +msgid "HD Controller:" +msgstr "RadiÄ disku:" + +msgid "FD Controller:" +msgstr "Disketový radiÄ:" + +msgid "Tertiary IDE Controller" +msgstr "Tretí radiÄ IDE" + +msgid "Quaternary IDE Controller" +msgstr "Å tvrtý radiÄ IDE" + +msgid "SCSI" +msgstr "SCSI" + +msgid "Controller 1:" +msgstr "RadiÄ 1:" + +msgid "Controller 2:" +msgstr "RadiÄ 2:" + +msgid "Controller 3:" +msgstr "RadiÄ 3:" + +msgid "Controller 4:" +msgstr "RadiÄ 4:" + +msgid "Cassette" +msgstr "Kazeta" + +msgid "Hard disks:" +msgstr "Pevné disky:" + +msgid "&New..." +msgstr "&Nový..." + +msgid "&Existing..." +msgstr "&Existujúcý..." + +msgid "&Remove" +msgstr "&OdobraÅ¥" + +msgid "Bus:" +msgstr "Zbernica:" + +msgid "Channel:" +msgstr "Kanál:" + +msgid "ID:" +msgstr "ID:" + +msgid "&Specify..." +msgstr "&ZadaÅ¥..." + +msgid "Sectors:" +msgstr "Sektory:" + +msgid "Heads:" +msgstr "Hlavy:" + +msgid "Cylinders:" +msgstr "Cylindre:" + +msgid "Size (MB):" +msgstr "VeľkosÅ¥ (MB):" + +msgid "Type:" +msgstr "Typ:" + +msgid "Image Format:" +msgstr "Formát obrazu:" + +msgid "Block Size:" +msgstr "VeľkosÅ¥ blokov:" + +msgid "Floppy drives:" +msgstr "Disketové mechaniky:" + +msgid "Turbo timings" +msgstr "Turbo Äasovanie" + +msgid "Check BPB" +msgstr "Kontrola BPB" + +msgid "CD-ROM drives:" +msgstr "Mechaniky CD-ROM:" + +msgid "Earlier drive" +msgstr "Skorá mechanika" + +msgid "MO drives:" +msgstr "Magnetooptické mechaniky:" + +msgid "ZIP drives:" +msgstr "Mechaniky ZIP:" + +msgid "ZIP 250" +msgstr "ZIP 250" + +msgid "ISA RTC:" +msgstr "ISA hodiny:" + +msgid "ISA Memory Expansion" +msgstr "ISA rozšírenie pamäte" + +msgid "Card 1:" +msgstr "Karta 1:" + +msgid "Card 2:" +msgstr "Karta 2:" + +msgid "Card 3:" +msgstr "Karta 3:" + +msgid "Card 4:" +msgstr "Karta 4:" + +msgid "ISABugger device" +msgstr "Zariadenie ISABugger" + +msgid "POST card" +msgstr "Karta pre kódy POST" + +msgid "FONT_SIZE" +msgstr "9" + +msgid "FONT_NAME" +msgstr "Segoe UI" + +msgid "86Box" +msgstr "86Box" + +msgid "Error" +msgstr "Chyba" + +msgid "Fatal error" +msgstr "Kritická chyba" + +msgid " - PAUSED" +msgstr " - POZASTAVENÃ" + +msgid "Press Ctrl+Alt+PgDn to return to windowed mode." +msgstr "StlaÄte Ctrl+Alt+PgDn pre návrat z režimu celej obrazovky." + +msgid "Speed" +msgstr "RýchlosÅ¥" + +msgid "ZIP %03i %i (%s): %ls" +msgstr "ZIP %03i %i (%s): %ls" + +msgid "ZIP images" +msgstr "Obrazy ZIP diskov" + +msgid "86Box could not find any usable ROM images.\n\nPlease download a ROM set and extract it into the \"roms\" directory." +msgstr "86Box nenaÅ¡iel žiadne použiteľné imidž pamätí ROM.\n\nStiahnite sadu obrazov ROM a extrahujte ju do zložky \"roms\"." + +msgid "(empty)" +msgstr "(prázdne)" + +msgid "All files" +msgstr "VÅ¡etky súbory" + +msgid "Turbo" +msgstr "Turbo" + +msgid "On" +msgstr "Zap." + +msgid "Off" +msgstr "Vyp." + +msgid "All images" +msgstr "VÅ¡etky obrazy diskov" + +msgid "Basic sector images" +msgstr "Základné sektorové obrazy" + +msgid "Surface images" +msgstr "Obrazy povrchu" + +msgid "Machine \"%hs\" is not available due to missing ROMs in the roms/machines directory. Switching to an available machine." +msgstr "PoÄítaÄ \"%hs\" ie je dostupný, pretože chýba obraz jeho pamäte ROM v zložke \"roms/machines\". Konfigurácia sa prepne na iný dostupný poÄítaÄ." + +msgid "Video card \"%hs\" is not available due to missing ROMs in the roms/video directory. Switching to an available video card." +msgstr "Video adaptér \"%hs\" nie je dostupný, pretože chýba obraz jeho pamäte ROM v zložke \"roms/video\". Konfigurácia sa prepne na iný dostupný adaptér." + +msgid "Machine" +msgstr "PoÄítaÄ" + +msgid "Display" +msgstr "Obraz" + +msgid "Input devices" +msgstr "Vstupné zariadenie" + +msgid "Sound" +msgstr "Zvuk" + +msgid "Network" +msgstr "SieÅ¥" + +msgid "Ports (COM & LPT)" +msgstr "COM a LPT porty" + +msgid "Storage controllers" +msgstr "RadiÄe úložiska" + +msgid "Hard disks" +msgstr "Pevné disky" + +msgid "Floppy & CD-ROM drives" +msgstr "Disketové a CD-ROM mechaniky" + +msgid "Other removable devices" +msgstr "ÄŽalÅ¡ie vymeniteľné zariadenia" + +msgid "Other peripherals" +msgstr "Iné prísluÅ¡enstvo" + +msgid "Click to capture mouse" +msgstr "Kliknite pre zabráni myÅ¡i" + +msgid "Press F8+F12 to release mouse" +msgstr "StlaÄte F8+F12 pre uvoľnenie myÅ¡i" + +msgid "Press F8+F12 or middle button to release mouse" +msgstr "StlaÄte F8+F12 alebo prostredné tlaÄidlo na uvoľnenie myÅ¡i" + +msgid "Bus" +msgstr "Zbernica" + +msgid "File" +msgstr "Súbor" + +msgid "C" +msgstr "C" + +msgid "H" +msgstr "H" + +msgid "S" +msgstr "S" + +msgid "KB" +msgstr "KB" + +msgid "Could not initialize the video renderer." +msgstr "Nastala chyba pri inicializácii video renderera." + +msgid "Default" +msgstr "Východiskové" + +msgid "%i Wait state(s)" +msgstr "%i Äakací stav(y)" + +msgid "Type" +msgstr "Typ" + +msgid "Failed to set up PCap" +msgstr "Nastala chyba pri inicializácii knižnice PCap" + +msgid "No PCap devices found" +msgstr "Neboli nájdené žiadne PCap zariadenia" + +msgid "Invalid PCap device" +msgstr "Neplatné PCap zariadenie" + +msgid "Standard 2-button joystick(s)" +msgstr "Å tandardný 2tlaÄidlový joystick" + +msgid "Standard 4-button joystick" +msgstr "Å tandardný 4tlaÄidlový joystick" + +msgid "Standard 6-button joystick" +msgstr "Å tandardný 6tlaÄidlový joystick" + +msgid "Standard 8-button joystick" +msgstr "Å tandardný 8tlaÄidlový joystick" + +msgid "CH Flightstick Pro" +msgstr "CH Flightstick Pro" + +msgid "Microsoft SideWinder Pad" +msgstr "Microsoft SideWinder Pad" + +msgid "Thrustmaster Flight Control System" +msgstr "Thrustmaster Flight Control System" + +msgid "None" +msgstr "Žiadne" + +msgid "Unable to load keyboard accelerators." +msgstr "Nebolo možné nahraÅ¥ klávesnicové skratky." + +msgid "Unable to register raw input." +msgstr "Nebolo možné zaregistrovaÅ¥ raw input." + +msgid "%u" +msgstr "%u" + +msgid "%u MB (CHS: %i, %i, %i)" +msgstr "%u MB (CHS: %i, %i, %i)" + +msgid "Floppy %i (%s): %ls" +msgstr "Disketová mechanika %i (%s): %ls" + +msgid "Advanced sector images" +msgstr "Rozšírené sektorové obrazy" + +msgid "Flux images" +msgstr "Obrazy magnetického toku" + +msgid "Unable to initialize SDL, SDL2.dll is required" +msgstr "Nastala chyba pri inicializácii knižnice SDL, je potreba SDL2.dll" + +msgid "Are you sure you want to hard reset the emulated machine?" +msgstr "Naozaj chcete resetovaÅ¥ emulovaný poÄítaÄ?" + +msgid "Are you sure you want to exit 86Box?" +msgstr "Naozaj chcete ukonÄiÅ¥ 86Box?" + +msgid "Unable to initialize Ghostscript" +msgstr "Nastala chyba pri inicializácii knižnice Ghostscript" + +msgid "MO %i (%ls): %ls" +msgstr "MO %i (%ls): %ls" + +msgid "MO images" +msgstr "Obrazy MO" + +msgid "Welcome to 86Box!" +msgstr "Vitajte v programe 86Box!" + +msgid "Internal controller" +msgstr "Vstavaný radiÄ" + +msgid "Exit" +msgstr "UkonÄiÅ¥" + +msgid "No ROMs found" +msgstr "Neboli nájdené žiadne obrazy ROM" + +msgid "Do you want to save the settings?" +msgstr "Chcete uložiÅ¥ nastavenia?" + +msgid "This will hard reset the emulated machine." +msgstr "PokraÄovaním sa resetuje emulovaný poÄítaÄ." + +msgid "Save" +msgstr "UložiÅ¥" + +msgid "About 86Box" +msgstr "O programe 86Box" + +msgid "86Box v" +msgstr "86Box v" + +msgid "An emulator of old computers\n\nAuthors: Miran GrÄa (OBattler), RichardG867, Jasmine Iwanek, TC1995, coldbrewed, Teemu Korhonen (Manaatti), Joakim L. Gilje, Adrien Moulin (elyosh), Daniel Balsom (gloriouscow), Cacodemon345, Fred N. van Kempen (waltje), Tiseno100, reenigne, and others.\n\nWith previous core contributions from Sarah Walker, leilei, JohnElliott, greatpsycho, and others.\n\nReleased under the GNU General Public License version 2 or later. See LICENSE for more information." +msgstr "Emulátor starých poÄítaÄov\n\nAutori: Miran GrÄa (OBattler), RichardG867, Jasmine Iwanek, TC1995, coldbrewed, Teemu Korhonen (Manaatti), Joakim L. Gilje, Adrien Moulin (elyosh), Daniel Balsom (gloriouscow), Cacodemon345, Fred N. van Kempen (waltje), Tiseno100, reenigne, and others.\n\nWith previous core contributions from Sarah Walker, leilei, JohnElliott, greatpsycho, and others.\n\nZverejnené pod licenciou GNU General Public License verzie 2 alebo novÅ¡ej. Pozri súbor LICENSE pre viac informácií." + +msgid "Hardware not available" +msgstr "Hardvér nie je dostupný" + +msgid "WinPcap" +msgstr "WinPcap" + +msgid "libpcap" +msgstr "libpcap" + +msgid "Make sure libpcap is installed and that you are on a libpcap-compatible network connection." +msgstr "Uistite sa, že je nainÅ¡talovaný libpcap a používate sieÅ¥ové pripojenie s ním kompatibilné." + +msgid "Invalid configuration" +msgstr "Neplatná konfigurácia" + +msgid "gsdll32.dll" +msgstr "gsdll32.dll" + +msgid "libgs" +msgstr "libgs" + +msgid " is required for automatic conversion of PostScript files to PDF.\n\nAny documents sent to the generic PostScript printer will be saved as PostScript (.ps) files." +msgstr " je potrebná pre automatický prevod PostScript dokumentov do PDF.\n\nAkékoľvek dokumenty vytlaÄené cez vÅ¡eobecnú PostScriptovú tlaÄiareň budú uložené ako PostScript (.ps) súbory." + +msgid "Entering fullscreen mode" +msgstr "Vstup do režimu celej obrazovky" + +msgid "Don't show this message again" +msgstr "NezobrazovaÅ¥ Äalej túto správu" + +msgid "Don't exit" +msgstr "NeukonÄovaÅ¥" + +msgid "Reset" +msgstr "ResetovaÅ¥" + +msgid "Don't reset" +msgstr "NeresetovaÅ¥" + +msgid "CD-ROM images" +msgstr "Obraz CD-ROM disku" + +msgid "%hs Device Configuration" +msgstr "Konfigurácia zariadenia %hs" + +msgid "Monitor in sleep mode" +msgstr "Monitor je v režime spánku" + +msgid "OpenGL Shaders" +msgstr "Shadery OpenGL" + +msgid "OpenGL options" +msgstr "Možnosti OpenGL" + +msgid "You are loading an unsupported configuration" +msgstr "Pokúšate sa spustiÅ¥ nepodporovanú konfiguráciu" + +msgid "CPU type filtering based on selected machine is disabled for this emulated machine.\n\nThis makes it possible to choose a CPU that is otherwise incompatible with the selected machine. However, you may run into incompatibilities with the machine BIOS or other software.\n\nEnabling this setting is not officially supported and any bug reports filed may be closed as invalid." +msgstr "Pre túto konfiguráciu bolo vypnuté filtrovanie procesorov podľa zvoleného poÄítaÄa.\n\nToto umožňuje zvoliÅ¥ procesor, ktorý by inak so zvoleným poÄítaÄom nebol kompatibilný. Môžu vÅ¡ak nastaÅ¥ problémy s BIOSom alebo iným softvérom.\n\nPovolenie tohto nastavenia nie je oficiálne podporované a akékoľvek hlásenia o chybách môžu byÅ¥ uzavreté ako neplatné." + +msgid "Continue" +msgstr "PokraÄovaÅ¥" + +msgid "Cassette: %s" +msgstr "Kazeta: %s" + +msgid "Cassette images" +msgstr "Kazetové nahrávky" + +msgid "Cartridge %i: %ls" +msgstr "Cartridge %i: %ls" + +msgid "Cartridge images" +msgstr "Obrazy cartridge" + +msgid "Error initializing renderer" +msgstr "Chyba pri inicializácii vykresľovaÄa" + +msgid "OpenGL (3.0 Core) renderer could not be initialized. Use another renderer." +msgstr "VykresľovaÄ OpenGL (3.0 Core) sa nepodarilo inicializovaÅ¥. Použite iný renderer." + +msgid "Resume execution" +msgstr "ObnoviÅ¥" + +msgid "Pause execution" +msgstr "PozastaviÅ¥" + +msgid "Press Ctrl+Alt+Del" +msgstr "StlaÄiÅ¥ Ctrl+Alt+Delete" + +msgid "Press Ctrl+Alt+Esc" +msgstr "StlaÄiÅ¥ Ctrl+Alt+Esc" + +msgid "Hard reset" +msgstr "ResetovaÅ¥" + +msgid "ACPI shutdown" +msgstr "Vypnúť cez rozhranie ACPI" + +msgid "Hard disk (%s)" +msgstr "Pevný disk (%s)" + +msgid "%01i:%01i" +msgstr "%01i:%01i" + +msgid "%01i" +msgstr "%01i" + +msgid "MFM/RLL or ESDI CD-ROM drives never existed" +msgstr "CD-ROM mechaniky pre rozhranie MFM/RLL alebo ESDI nikdy neexistovali" + +msgid "Custom..." +msgstr "Vlastná..." + +msgid "Custom (large)..." +msgstr "Vlastná (veľká)..." + +msgid "Add New Hard Disk" +msgstr "PridaÅ¥ nový pevný disk" + +msgid "Add Existing Hard Disk" +msgstr "PridaÅ¥ existujúci pevný disk" + +msgid "HDI disk images cannot be larger than 4 GB." +msgstr "Obraz disku formátu HDI nemôžu byÅ¥ väÄší ako 4 GB." + +msgid "Disk images cannot be larger than 127 GB." +msgstr "Obraz disku nemôžu byÅ¥ väÄší ako 127 GB." + +msgid "Hard disk images" +msgstr "Obrazy pevného disku" + +msgid "Unable to read file" +msgstr "Nebolo možné preÄítaÅ¥ súbor" + +msgid "Unable to write file" +msgstr "Nebolo možné zapisovaÅ¥ do súboru" + +msgid "HDI or HDX images with a sector size other than 512 are not supported." +msgstr "Obraz disku vo formáte HDI alebo HDX s veľkosÅ¥ou sektora inou ako 512 bajtov nie sú podporované." + +msgid "USB is not yet supported" +msgstr "USB zatiaľ nie je podporované." + +msgid "Disk image file already exists" +msgstr "Súbor obrazu disku už existuje" + +msgid "Please specify a valid file name." +msgstr "Zadajte platný názov súboru." + +msgid "Disk image created" +msgstr "Obraz disku bol vytvorený" + +msgid "Make sure the file exists and is readable." +msgstr "Uistite sa, že súbor existuje a možno ho preÄítaÅ¥." + +msgid "Make sure the file is being saved to a writable directory." +msgstr "Uistite sa, že sa do zložky, kde sa má súbor uložiÅ¥, dá zapisovaÅ¥." + +msgid "Disk image too large" +msgstr "Obraz disku je príliÅ¡ veľký" + +msgid "Remember to partition and format the newly-created drive." +msgstr "Nezabudnite novo vytvorený disk rozdeliÅ¥ a naformátovaÅ¥." + +msgid "The selected file will be overwritten. Are you sure you want to use it?" +msgstr "Zvolený súbor bude prepísaný. Naozaj ho chcete použiÅ¥?" + +msgid "Unsupported disk image" +msgstr "Nepodporovaný obraz disku" + +msgid "Overwrite" +msgstr "PrepísaÅ¥" + +msgid "Don't overwrite" +msgstr "NeprepisovaÅ¥" + +msgid "Raw image (.img)" +msgstr "Surový obraz (.img)" + +msgid "HDI image (.hdi)" +msgstr "HDI obraz (.hdi)" + +msgid "HDX image (.hdx)" +msgstr "HDX obraz (.hdx)" + +msgid "Fixed-size VHD (.vhd)" +msgstr "VHD s pevnou veľkosÅ¥ou (.vhd)" + +msgid "Dynamic-size VHD (.vhd)" +msgstr "VHD s dynamickou veľkosÅ¥ou (.vhd)" + +msgid "Differencing VHD (.vhd)" +msgstr "Rozdielový VHD (.vhd)" + +msgid "Large blocks (2 MB)" +msgstr "Veľké bloky (2 MB)" + +msgid "Small blocks (512 KB)" +msgstr "Malé bloky (512 KB)" + +msgid "VHD files" +msgstr "Súbory VHD" + +msgid "Select the parent VHD" +msgstr "Vyberte nadradený virtuálny disk" + +msgid "This could mean that the parent image was modified after the differencing image was created.\n\nIt can also happen if the image files were moved or copied, or by a bug in the program that created this disk.\n\nDo you want to fix the timestamps?" +msgstr "To môže znamenaÅ¥, že sa obsahy nadradeného disku zmenili po vytvorení rozdielového disku.\n\nTáto chyba tiež môže nastaÅ¥, ak bol obraz disku kopírovaný alebo presunutý, alebo kvôli chybe v programe, ktorý ho vytvoril.\n\nChcete Äasové peÄiatky opraviÅ¥?" + +msgid "Parent and child disk timestamps do not match" +msgstr "ÄŒasové peÄiatky nadradeného a podradeného disku nesúhlasia" + +msgid "Could not fix VHD timestamp." +msgstr "Nebolo možné opraviÅ¥ Äasovú peÄiatku VHD." + +msgid "%01i:%02i" +msgstr "%01i:%02i" + +msgid "MFM/RLL" +msgstr "MFM/RLL" + +msgid "XTA" +msgstr "XTA" + +msgid "ESDI" +msgstr "ESDI" + +msgid "IDE" +msgstr "IDE" + +msgid "ATAPI" +msgstr "ATAPI" + +msgid "MFM/RLL (%01i:%01i)" +msgstr "MFM/RLL (%01i:%01i)" + +msgid "XTA (%01i:%01i)" +msgstr "XTA (%01i:%01i)" + +msgid "ESDI (%01i:%01i)" +msgstr "ESDI (%01i:%01i)" + +msgid "IDE (%01i:%01i)" +msgstr "IDE (%01i:%01i)" + +msgid "ATAPI (%01i:%01i)" +msgstr "ATAPI (%01i:%01i)" + +msgid "SCSI (%01i:%02i)" +msgstr "SCSI (%01i:%02i)" + +msgid "CD-ROM %i (%s): %s" +msgstr "CD-ROM %i (%s): %s" + +msgid "160 kB" +msgstr "160 kB" + +msgid "180 kB" +msgstr "180 kB" + +msgid "320 kB" +msgstr "320 kB" + +msgid "360 kB" +msgstr "360 kB" + +msgid "640 kB" +msgstr "640 kB" + +msgid "720 kB" +msgstr "720 kB" + +msgid "1.2 MB" +msgstr "1.2 MB" + +msgid "1.25 MB" +msgstr "1.25 MB" + +msgid "1.44 MB" +msgstr "1.44 MB" + +msgid "DMF (cluster 1024)" +msgstr "DMF (cluster 1024)" + +msgid "DMF (cluster 2048)" +msgstr "DMF (cluster 2048)" + +msgid "2.88 MB" +msgstr "2.88 MB" + +msgid "ZIP 100" +msgstr "ZIP 100" + +msgid "3.5\" 128 MB (ISO 10090)" +msgstr "3.5\" 128 MB (ISO 10090)" + +msgid "3.5\" 230 MB (ISO 13963)" +msgstr "3.5\" 230 MB (ISO 13963)" + +msgid "3.5\" 540 MB (ISO 15498)" +msgstr "3.5\" 540 MB (ISO 15498)" + +msgid "3.5\" 640 MB (ISO 15498)" +msgstr "3.5\" 640 MB (ISO 15498)" + +msgid "3.5\" 1.3 GB (GigaMO)" +msgstr "3.5\" 1.3 GB (GigaMO)" + +msgid "3.5\" 2.3 GB (GigaMO 2)" +msgstr "3.5\" 2.3 GB (GigaMO 2)" + +msgid "5.25\" 600 MB" +msgstr "5.25\" 600 MB" + +msgid "5.25\" 650 MB" +msgstr "5.25\" 650 MB" + +msgid "5.25\" 1 GB" +msgstr "5.25\" 1 GB" + +msgid "5.25\" 1.3 GB" +msgstr "5.25\" 1.3 GB" + +msgid "Perfect RPM" +msgstr "Dokonalé otáÄky za minútu" + +msgid "1% below perfect RPM" +msgstr "1% pod dokonalými ot./m" + +msgid "1.5% below perfect RPM" +msgstr "1.5% pod dokonalými ot./m" + +msgid "2% below perfect RPM" +msgstr "2% pod dokonalými ot./m" + +msgid "(System Default)" +msgstr "(Predvolené nastavenie systému)" + +msgid "Failed to initialize network driver" +msgstr "Nepodarilo sa inicializovaÅ¥ sieÅ¥ový ovládaÄ" + +msgid "The network configuration will be switched to the null driver" +msgstr "Konfigurácia siete bude prepnutá na nulový ovládaÄ" + +msgid "Mouse sensitivity:" +msgstr "CitlivosÅ¥ myší:" + +msgid "Select media images from program working directory" +msgstr "Výber mediálnych obrazov z pracovného adresára programu" + +msgid "PIT mode:" +msgstr "Režim PIT:" + +msgid "Auto" +msgstr "Automatický" + +msgid "Slow" +msgstr "Pomalý" + +msgid "Fast" +msgstr "Rýchly" + +msgid "&Auto-pause on focus loss" +msgstr "&Automatická pauza pri strate fokusu okna" diff --git a/src/qt/languages/sl-SI.po b/src/qt/languages/sl-SI.po index 5a396c855..98a51d863 100644 --- a/src/qt/languages/sl-SI.po +++ b/src/qt/languages/sl-SI.po @@ -76,6 +76,24 @@ msgstr "1.&5x" msgid "&2x" msgstr "&2x" +msgid "&3x" +msgstr "&3x" + +msgid "&4x" +msgstr "&4x" + +msgid "&5x" +msgstr "&5x" + +msgid "&6x" +msgstr "&6x" + +msgid "&7x" +msgstr "&7x" + +msgid "&8x" +msgstr "&8x" + msgid "Filter method" msgstr "&Metoda filtriranja" @@ -106,6 +124,9 @@ msgstr "&Kvadratni piksli (ohrani razmerje)" msgid "&Integer scale" msgstr "&CeloÅ¡tevilsko raztezanje" +msgid "4:&3 Integer scale" +msgstr "CeloÅ¡tevilsko raztezanje 4:&3" + msgid "E&GA/(S)VGA settings" msgstr "Nastavitve E&GA/(S)VGA" @@ -226,8 +247,8 @@ msgstr "&Prazen" msgid "&Reload previous image" msgstr "&Naloži zadnjo sliko" -msgid "&Image" -msgstr "&Slika" +msgid "&Folder..." +msgstr "&Mapa..." msgid "Target &framerate" msgstr "&Ciljno Å¡t. sliÄic na sekundo" @@ -364,6 +385,12 @@ msgstr "Video:" msgid "Voodoo Graphics" msgstr "Voodoo grafika" +msgid "IBM 8514/a Graphics" +msgstr "IBM 8514/a grafika" + +msgid "XGA Graphics" +msgstr "XGA grafika" + msgid "Mouse:" msgstr "MiÅ¡ka:" @@ -382,8 +409,17 @@ msgstr "Igralna palica 3..." msgid "Joystick 4..." msgstr "Igralna palica 4..." -msgid "Sound card:" -msgstr "ZvoÄna kartica:" +msgid "Sound card 1:" +msgstr "ZvoÄna kartica 1:" + +msgid "Sound card 2:" +msgstr "ZvoÄna kartica 2:" + +msgid "Sound card 3:" +msgstr "ZvoÄna kartica 3:" + +msgid "Sound card 4:" +msgstr "ZvoÄna kartica 4:" msgid "MIDI Out Device:" msgstr "Izhodna naprava MIDI:" @@ -394,18 +430,18 @@ msgstr "Vhodna naprava MIDI:" msgid "Standalone MPU-401" msgstr "Samostojen MPU-401" -msgid "Innovation SSI-2001" -msgstr "Innovation SSI-2001" - -msgid "CMS / Game Blaster" -msgstr "CMS / Game Blaster" - -msgid "Gravis Ultrasound" -msgstr "Gravis Ultrasound" - msgid "Use FLOAT32 sound" msgstr "Uporabi FLOAT32 za zvok" +msgid "FM synth driver" +msgstr "Gonilnik sintetizacije FM" + +msgid "Nuked (more accurate)" +msgstr "Nuked (toÄnejÅ¡i)" + +msgid "YMFM (faster)" +msgstr "YMFM (hitrejÅ¡i)" + msgid "Network type:" msgstr "Vrsta omrežja:" @@ -550,6 +586,9 @@ msgstr "Preverjaj BPB" msgid "CD-ROM drives:" msgstr "Pogoni CD-ROM:" +msgid "Earlier drive" +msgstr "ZgodnejÅ¡i pogon" + msgid "MO drives:" msgstr "Magnetno-optiÄni pogoni:" @@ -688,9 +727,6 @@ msgstr "Pritisnite F8+F12 za izpust miÅ¡ke" msgid "Press F8+F12 or middle button to release mouse" msgstr "Pritisnite F8+F12 ali srednji gumb za izpust miÅ¡ke" -msgid "Unable to initialize FluidSynth" -msgstr "Ne morem inicializirati FluidSynth" - msgid "Bus" msgstr "Vodilo" @@ -775,9 +811,6 @@ msgstr "Napredne sektorske slike" msgid "Flux images" msgstr "Tokovne slike" -msgid "Unable to initialize FreeType" -msgstr "Ne morem inicializirati FreeType" - msgid "Unable to initialize SDL, SDL2.dll is required" msgstr "Ne morem inicializirati SDL, potrebna je knjižica SDL2.dll" @@ -823,8 +856,8 @@ msgstr "O programu 86Box" msgid "86Box v" msgstr "86Box v" -msgid "An emulator of old computers\n\nAuthors: Sarah Walker, Miran Grca, Fred N. van Kempen (waltje), SA1988, Tiseno100, reenigne, leilei, JohnElliott, greatpsycho, and others.\n\nReleased under the GNU General Public License version 2 or later. See LICENSE for more information." -msgstr "Emulator starih raÄunalnikov\n\nAvtorji: Sarah Walker, Miran Grca, Fred N. van Kempen (waltje), SA1988, Tiseno100, reenigne, leilei, JohnElliott, greatpsycho in drugi.\n\nIzdano pod licenco GNU General Public License razliÄica 2 ali novejÅ¡a. Glej datoteko LICENSE za veÄ informacij." +msgid "An emulator of old computers\n\nAuthors: Miran GrÄa (OBattler), RichardG867, Jasmine Iwanek, TC1995, coldbrewed, Teemu Korhonen (Manaatti), Joakim L. Gilje, Adrien Moulin (elyosh), Daniel Balsom (gloriouscow), Cacodemon345, Fred N. van Kempen (waltje), Tiseno100, reenigne, and others.\n\nWith previous core contributions from Sarah Walker, leilei, JohnElliott, greatpsycho, and others.\n\nReleased under the GNU General Public License version 2 or later. See LICENSE for more information." +msgstr "Emulator starih raÄunalnikov\n\nAvtorji: Miran GrÄa (OBattler), RichardG867, Jasmine Iwanek, TC1995, coldbrewed, Teemu Korhonen (Manaatti), Joakim L. Gilje, Adrien Moulin (elyosh), Daniel Balsom (gloriouscow), Cacodemon345, Fred N. van Kempen (waltje), Tiseno100, reenigne in drugi.\n\nWith previous core contributions from Sarah Walker, leilei, JohnElliott, greatpsycho in drugi.\n\nIzdano pod licenco GNU General Public License razliÄica 2 ali novejÅ¡a. Glej datoteko LICENSE za veÄ informacij." msgid "Hardware not available" msgstr "Strojna oprema ni na voljo" @@ -841,15 +874,6 @@ msgstr "PrepiÄajte se, da je nameÅ¡Äen libpcap in da ste na omrežni povezavi, msgid "Invalid configuration" msgstr "Neveljavna konfiguracija" -msgid "freetype.dll" -msgstr "freetype.dll" - -msgid "libfreetype" -msgstr "libfreetype" - -msgid " is required for ESC/P printer emulation." -msgstr " je potreben za emuliranje ESC/P tiskalnika." - msgid "gsdll32.dll" msgstr "gsdll32.dll" @@ -859,15 +883,6 @@ msgstr "libgs" msgid " is required for automatic conversion of PostScript files to PDF.\n\nAny documents sent to the generic PostScript printer will be saved as PostScript (.ps) files." msgstr " je potreben za samodejno pretvorbo PostScript datotek v PDF.\n\nVsi dokumenti, poslani generiÄnemu PostScript tiskalniku bodo shranjeni kot PostScript (.ps) datoteke." -msgid "libfluidsynth.dll" -msgstr "libfluidsynth.dll" - -msgid "libfluidsynth" -msgstr "libfluidsynth" - -msgid " is required for FluidSynth MIDI output." -msgstr " je potreben za FluidSynth MIDI izhod." - msgid "Entering fullscreen mode" msgstr "Preklapljam v celozaslonski naÄin" @@ -920,28 +935,28 @@ msgid "Cartridge images" msgstr "Slike spominskega vložka" msgid "Error initializing renderer" -msgstr "Error initializing renderer" +msgstr "Napaka pri zagonu sistema za upodabljanje" msgid "OpenGL (3.0 Core) renderer could not be initialized. Use another renderer." -msgstr "OpenGL (3.0 Core) renderer could not be initialized. Use another renderer." +msgstr "Sistema za upodabljanje OpenGL (3.0 Core) ni bilo mogoÄe zagnati. Uporabite drug sistem za upodabljanje." msgid "Resume execution" -msgstr "Resume execution" +msgstr "Nadaljuj izvajanje" msgid "Pause execution" -msgstr "Pause execution" +msgstr "Prekini izvajanje" msgid "Press Ctrl+Alt+Del" -msgstr "Press Ctrl+Alt+Del" +msgstr "Pritisni Ctrl+Alt+Del" msgid "Press Ctrl+Alt+Esc" -msgstr "Press Ctrl+Alt+Esc" +msgstr "Pritisni Ctrl+Alt+Esc" msgid "Hard reset" -msgstr "Hard reset" +msgstr "Ponovni zagon" msgid "ACPI shutdown" -msgstr "ACPI shutdown" +msgstr "Zaustavitev ACPI" msgid "Hard disk (%s)" msgstr "Trdi disk (%s)" @@ -1183,3 +1198,29 @@ msgstr "2% pod popolnimi obrati" msgid "(System Default)" msgstr "(Sistemsko privzeto)" +msgid "Failed to initialize network driver" +msgstr "Ni uspelo inicializirati omrežnega gonilnika" + +msgid "The network configuration will be switched to the null driver" +msgstr "Omrežne nastavitve bodo preklopljene na niÄelni gonilnik" + +msgid "Mouse sensitivity:" +msgstr "ObÄutljivost miÅ¡ke:" + +msgid "Select media images from program working directory" +msgstr "Izberi slike medijev iz delovnega imenika programa" + +msgid "PIT mode:" +msgstr "NaÄin PIT:" + +msgid "Auto" +msgstr "Samodejni" + +msgid "Slow" +msgstr "PoÄasni" + +msgid "Fast" +msgstr "Hitri" + +msgid "&Auto-pause on focus loss" +msgstr "&Samodejni premor ob izgubi fokusa" diff --git a/src/qt/languages/tr-TR.po b/src/qt/languages/tr-TR.po index 2a12b3d85..0d6875eb8 100644 --- a/src/qt/languages/tr-TR.po +++ b/src/qt/languages/tr-TR.po @@ -76,6 +76,24 @@ msgstr "1.&5x" msgid "&2x" msgstr "&2x" +msgid "&3x" +msgstr "&3x" + +msgid "&4x" +msgstr "&4x" + +msgid "&5x" +msgstr "&5x" + +msgid "&6x" +msgstr "&6x" + +msgid "&7x" +msgstr "&7x" + +msgid "&8x" +msgstr "&8x" + msgid "Filter method" msgstr "&Filtre metodu" @@ -106,6 +124,9 @@ msgstr "&Kare piksel (ölçeÄŸi koru)" msgid "&Integer scale" msgstr "Tam &sayı ölçeklemesi" +msgid "4:&3 Integer scale" +msgstr "4:&3 Tam sayı ölçeklemesi" + msgid "E&GA/(S)VGA settings" msgstr "EGA/&(S)VGA ayarları" @@ -226,8 +247,8 @@ msgstr "İmajı &çıkar" msgid "&Reload previous image" msgstr "&Önceki imajı seç" -msgid "&Image" -msgstr "&İmaj seç" +msgid "&Folder..." +msgstr "&Klasör..." msgid "Target &framerate" msgstr "Hedef &kare oranı" @@ -364,6 +385,12 @@ msgstr "Ekran kartı:" msgid "Voodoo Graphics" msgstr "Voodoo Grafikleri" +msgid "IBM 8514/a Graphics" +msgstr "IBM 8514/a Grafikleri" + +msgid "XGA Graphics" +msgstr "XGA Grafikleri" + msgid "Mouse:" msgstr "Fare:" @@ -382,8 +409,17 @@ msgstr "Oyun kolu 3..." msgid "Joystick 4..." msgstr "Oyun kolu 4..." -msgid "Sound card:" -msgstr "Ses kartı:" +msgid "Sound card 1:" +msgstr "Ses kartı 1:" + +msgid "Sound card 2:" +msgstr "Ses kartı 2:" + +msgid "Sound card 3:" +msgstr "Ses kartı 3:" + +msgid "Sound card 4:" +msgstr "Ses kartı 4:" msgid "MIDI Out Device:" msgstr "MIDI Çıkış Cihazı:" @@ -394,18 +430,18 @@ msgstr "MIDI GiriÅŸ Cihazı:" msgid "Standalone MPU-401" msgstr "Bağımsız MPU-401" -msgid "Innovation SSI-2001" -msgstr "Innovation SSI-2001" - -msgid "CMS / Game Blaster" -msgstr "CMS / Game Blaster" - -msgid "Gravis Ultrasound" -msgstr "Gravis Ultrasound" - msgid "Use FLOAT32 sound" msgstr "FLOAT32 ses kullan" +msgid "FM synth driver" +msgstr "FM sentez sürücüsü" + +msgid "Nuked (more accurate)" +msgstr "Nuked (daha doÄŸru)" + +msgid "YMFM (faster)" +msgstr "YMFM (daha hızlı)" + msgid "Network type:" msgstr "AÄŸ tipi:" @@ -550,6 +586,9 @@ msgstr "BPB'yi denetle" msgid "CD-ROM drives:" msgstr "CD-ROM sürücüleri:" +msgid "Earlier drive" +msgstr "Daha erken sürüş" + msgid "MO drives:" msgstr "MO sürücüleri:" @@ -688,9 +727,6 @@ msgstr "Farenin bırakılması için F8+F12 tuÅŸlarına basın" msgid "Press F8+F12 or middle button to release mouse" msgstr "Farenin bırakılması için F8+F12 veya farenin orta tuÅŸuna basın" -msgid "Unable to initialize FluidSynth" -msgstr "FluidSynth baÅŸlatılamadı" - msgid "Bus" msgstr "Veri yolu" @@ -775,9 +811,6 @@ msgstr "GeliÅŸmiÅŸ sektör imajları" msgid "Flux images" msgstr "Flux images" -msgid "Unable to initialize FreeType" -msgstr "FreeType baÅŸlatılamadı" - msgid "Unable to initialize SDL, SDL2.dll is required" msgstr "SDL baÅŸlatılamadı, SDL2.dll gerekmektedir" @@ -823,8 +856,8 @@ msgstr "86Box Hakkında" msgid "86Box v" msgstr "86Box v" -msgid "An emulator of old computers\n\nAuthors: Sarah Walker, Miran Grca, Fred N. van Kempen (waltje), SA1988, Tiseno100, reenigne, leilei, JohnElliott, greatpsycho, and others.\n\nReleased under the GNU General Public License version 2 or later. See LICENSE for more information." -msgstr "Bir eski bilgisayar emülatörü\n\nYapanlar: Sarah Walker, Miran Grca, Fred N. van Kempen (waltje), SA1988, Tiseno100, reenigne, leilei, JohnElliott, greatpsycho, ve diÄŸerleri.\n\nGNU Genel Kamu Lisansı versiyon 2 veya sonrası altında yayınlanmıştır. Daha fazla bilgi için LICENSE'ı gözden geçirin." +msgid "An emulator of old computers\n\nAuthors: Miran GrÄa (OBattler), RichardG867, Jasmine Iwanek, TC1995, coldbrewed, Teemu Korhonen (Manaatti), Joakim L. Gilje, Adrien Moulin (elyosh), Daniel Balsom (gloriouscow), Cacodemon345, Fred N. van Kempen (waltje), Tiseno100, reenigne, and others.\n\nWith previous core contributions from Sarah Walker, leilei, JohnElliott, greatpsycho, and others.\n\nReleased under the GNU General Public License version 2 or later. See LICENSE for more information." +msgstr "Bir eski bilgisayar emülatörü\n\nYapanlar: Miran GrÄa (OBattler), RichardG867, Jasmine Iwanek, TC1995, coldbrewed, Teemu Korhonen (Manaatti), Joakim L. Gilje, Adrien Moulin (elyosh), Daniel Balsom (gloriouscow), Cacodemon345, Fred N. van Kempen (waltje), Tiseno100, reenigne, ve diÄŸerleri.\n\nWith previous core contributions from Sarah Walker, leilei, JohnElliott, greatpsycho, ve diÄŸerleri.\n\nGNU Genel Kamu Lisansı versiyon 2 veya sonrası altında yayınlanmıştır. Daha fazla bilgi için LICENSE'ı gözden geçirin." msgid "Hardware not available" msgstr "Donanım mevcut deÄŸil" @@ -841,15 +874,6 @@ msgstr "libpcap kurulu olduÄŸundan ve libpcap-uyumlu bir internet ağında bulun msgid "Invalid configuration" msgstr "Geçersiz konfigürasyon" -msgid "freetype.dll" -msgstr "freetype.dll" - -msgid "libfreetype" -msgstr "libfreetype" - -msgid " is required for ESC/P printer emulation." -msgstr " ESC/P yazıcı emülasyonu için gereklidir." - msgid "gsdll32.dll" msgstr "gsdll32.dll" @@ -859,15 +883,6 @@ msgstr "libgs" msgid " is required for automatic conversion of PostScript files to PDF.\n\nAny documents sent to the generic PostScript printer will be saved as PostScript (.ps) files." msgstr " PostScript dosyalarının otomatik olarak PDF dosyalarına çevirilmesi için gereklidir.\n\nGenel PostScript yazıcısına gönderilen tüm dökümanlar PostScript (.ps) dosyaları olarak kaydedilecektir." -msgid "libfluidsynth.dll" -msgstr "libfluidsynth.dll" - -msgid "libfluidsynth" -msgstr "libfluidsynth" - -msgid " is required for FluidSynth MIDI output." -msgstr " FluidSynth MIDI çıkışı için gereklidir." - msgid "Entering fullscreen mode" msgstr "Tam ekran moduna geçiliyor" @@ -920,28 +935,28 @@ msgid "Cartridge images" msgstr "KartuÅŸ imajları" msgid "Error initializing renderer" -msgstr "Error initializing renderer" +msgstr "OluÅŸturucu baÅŸlatılırken hata oluÅŸtu" msgid "OpenGL (3.0 Core) renderer could not be initialized. Use another renderer." -msgstr "OpenGL (3.0 Core) renderer could not be initialized. Use another renderer." +msgstr "OpenGL (3.0 Core) görüntüleyici baÅŸlatılamadı. BaÅŸka bir görüntüleyici kullanın." msgid "Resume execution" -msgstr "Resume execution" +msgstr "Yürütmeye devam et" msgid "Pause execution" -msgstr "Pause execution" +msgstr "Yürütmeyi duraklat" msgid "Press Ctrl+Alt+Del" -msgstr "Press Ctrl+Alt+Del" +msgstr "Ctrl+Alt+Del" msgid "Press Ctrl+Alt+Esc" -msgstr "Press Ctrl+Alt+Esc" +msgstr "Ctrl+Alt+Esc" msgid "Hard reset" -msgstr "Hard reset" +msgstr "Makineyi yeniden baÅŸlat" msgid "ACPI shutdown" -msgstr "ACPI shutdown" +msgstr "ACPI kapatma" msgid "Hard disk (%s)" msgstr "Hard disk (%s)" @@ -1183,3 +1198,29 @@ msgstr "mükemmel RPM deÄŸerinin 2% altı" msgid "(System Default)" msgstr "(Sistem Varsayılanı)" +msgid "Failed to initialize network driver" +msgstr "AÄŸ sürücüsü baÅŸlatılamadı" + +msgid "The network configuration will be switched to the null driver" +msgstr "AÄŸ yapılandırması null sürücüye geçirilecektir" + +msgid "Mouse sensitivity:" +msgstr "Fare hassasiyeti:" + +msgid "Select media images from program working directory" +msgstr "Program çalışma dizininden medya görüntülerini seçme" + +msgid "PIT mode:" +msgstr "PIT modu:" + +msgid "Auto" +msgstr "Otomatik" + +msgid "Slow" +msgstr "YavaÅŸ" + +msgid "Fast" +msgstr "Hızlı" + +msgid "&Auto-pause on focus loss" +msgstr "&Odak kaybında otomatik duraklatma" diff --git a/src/qt/languages/uk-UA.po b/src/qt/languages/uk-UA.po index 76382a9c7..6f8ecac52 100644 --- a/src/qt/languages/uk-UA.po +++ b/src/qt/languages/uk-UA.po @@ -76,6 +76,24 @@ msgstr "1.&5x" msgid "&2x" msgstr "&2x" +msgid "&3x" +msgstr "&3x" + +msgid "&4x" +msgstr "&4x" + +msgid "&5x" +msgstr "&5x" + +msgid "&6x" +msgstr "&6x" + +msgid "&7x" +msgstr "&7x" + +msgid "&8x" +msgstr "&8x" + msgid "Filter method" msgstr "Метод фільтрації" @@ -106,6 +124,9 @@ msgstr "&Квадратні пікÑелі (зберегти відношенн msgid "&Integer scale" msgstr "&ЦіліÑночиÑленне маÑштабуваннÑ" +msgid "4:&3 Integer scale" +msgstr "ЦіліÑночиÑленне маÑÑˆÑ‚Ð°Ð±ÑƒÐ²Ð°Ð½Ð½Ñ 4:&3" + msgid "E&GA/(S)VGA settings" msgstr "ÐÐ°Ð»Ð°ÑˆÑ‚ÑƒÐ²Ð°Ð½Ð½Ñ E&GA/(S)VGA" @@ -226,8 +247,8 @@ msgstr "&ПуÑтий" msgid "&Reload previous image" msgstr "&Знову завантажити попередній образ" -msgid "&Image" -msgstr "&Образ..." +msgid "&Folder..." +msgstr "&Тека..." msgid "Target &framerate" msgstr "Цільова &чаÑтота кадрів" @@ -287,7 +308,7 @@ msgid "&Default" msgstr "&За замовчуваннÑм" msgid "Language:" -msgstr "Язык:" +msgstr "Мова:" msgid "Icon set:" msgstr "Ðабір іконок:" @@ -364,6 +385,12 @@ msgstr "Відеокарта:" msgid "Voodoo Graphics" msgstr "ПриÑкорювач Voodoo" +msgid "IBM 8514/a Graphics" +msgstr "ПриÑкорювач IBM 8514/a" + +msgid "XGA Graphics" +msgstr "ПриÑкорювач XGA" + msgid "Mouse:" msgstr "Миша:" @@ -382,8 +409,17 @@ msgstr "ДжойÑтик 3..." msgid "Joystick 4..." msgstr "ДжойÑтик 4..." -msgid "Sound card:" -msgstr "Звукова карта:" +msgid "Sound card 1:" +msgstr "Звукова карта 1:" + +msgid "Sound card 2:" +msgstr "Звукова карта 2:" + +msgid "Sound card 3:" +msgstr "Звукова карта 3:" + +msgid "Sound card 4:" +msgstr "Звукова карта 4:" msgid "MIDI Out Device:" msgstr "MIDI Out при-ій:" @@ -394,18 +430,18 @@ msgstr "MIDI In при-ій:" msgid "Standalone MPU-401" msgstr "Окремий MPU-401" -msgid "Innovation SSI-2001" -msgstr "Innovation SSI-2001" - -msgid "CMS / Game Blaster" -msgstr "CMS / Game Blaster" - -msgid "Gravis Ultrasound" -msgstr "Gravis Ultrasound" - msgid "Use FLOAT32 sound" msgstr "FLOAT32 звук" +msgid "FM synth driver" +msgstr "Драйвер FM-Ñинтезатора" + +msgid "Nuked (more accurate)" +msgstr "Nuked (більш точний)" + +msgid "YMFM (faster)" +msgstr "YMFM (швидший)" + msgid "Network type:" msgstr "Тип мережі:" @@ -413,7 +449,7 @@ msgid "PCap device:" msgstr "ПриÑтрій PCap:" msgid "Network adapter:" -msgstr "Мережева карта:" +msgstr "Мережевий адаптер:" msgid "COM1 Device:" msgstr "ПриÑтрій COM1:" @@ -550,6 +586,9 @@ msgstr "ПеревірÑти BPB" msgid "CD-ROM drives:" msgstr "ДиÑководи CD-ROM:" +msgid "Earlier drive" +msgstr "Більш ранній диÑковод" + msgid "MO drives:" msgstr "Магнітооптичні диÑководи:" @@ -688,9 +727,6 @@ msgstr "ÐатиÑніть F8+F12, щоб звільнити курÑор" msgid "Press F8+F12 or middle button to release mouse" msgstr "ÐатиÑніть F8+F12 або Ñередню кнопку миші, щоб звільнити курÑор" -msgid "Unable to initialize FluidSynth" -msgstr "Ðеможливо ініціалізувати FluidSynth" - msgid "Bus" msgstr "Шина" @@ -775,9 +811,6 @@ msgstr "Розширені образи Ñекторів" msgid "Flux images" msgstr "Образи Flux" -msgid "Unable to initialize FreeType" -msgstr "Ðеможливо ініціалізувати FreeType" - msgid "Unable to initialize SDL, SDL2.dll is required" msgstr "Ðеможливо ініціалізувати SDL, потрібно SDL2.dll" @@ -823,8 +856,8 @@ msgstr "Про 86Box" msgid "86Box v" msgstr "86Box v." -msgid "An emulator of old computers\n\nAuthors: Sarah Walker, Miran Grca, Fred N. van Kempen (waltje), SA1988, Tiseno100, reenigne, leilei, JohnElliott, greatpsycho, and others.\n\nReleased under the GNU General Public License version 2 or later. See LICENSE for more information." -msgstr "ЕмулÑтор Ñтарих комп'ютерів\n\nÐвтори: Sarah Walker, Miran Grca, Fred N. van Kempen (waltje), SA1988, Tiseno100, reenigne, leilei, JohnElliott, greatpsycho, and others.\n\nВипуÑкаєтÑÑ Ð¿Ñ–Ð´ ліцензією GNU General Public License верÑÑ–Ñ— 2 або більше пізніше. Додадкову інформацію Ñм. у файлі LICENSE." +msgid "An emulator of old computers\n\nAuthors: Miran GrÄa (OBattler), RichardG867, Jasmine Iwanek, TC1995, coldbrewed, Teemu Korhonen (Manaatti), Joakim L. Gilje, Adrien Moulin (elyosh), Daniel Balsom (gloriouscow), Cacodemon345, Fred N. van Kempen (waltje), Tiseno100, reenigne, and others.\n\nWith previous core contributions from Sarah Walker, leilei, JohnElliott, greatpsycho, and others.\n\nReleased under the GNU General Public License version 2 or later. See LICENSE for more information." +msgstr "ЕмулÑтор Ñтарих комп'ютерів\n\nÐвтори: Miran GrÄa (OBattler), RichardG867, Jasmine Iwanek, TC1995, coldbrewed, Teemu Korhonen (Manaatti), Joakim L. Gilje, Adrien Moulin (elyosh), Daniel Balsom (gloriouscow), Cacodemon345, Fred N. van Kempen (waltje), Tiseno100, reenigne, and others.\n\nWith previous core contributions from Sarah Walker, leilei, JohnElliott, greatpsycho, and others.\n\nВипуÑкаєтÑÑ Ð¿Ñ–Ð´ ліцензією GNU General Public License верÑÑ–Ñ— 2 або більше пізніше. Додадкову інформацію Ñм. у файлі LICENSE." msgid "Hardware not available" msgstr "ÐžÐ±Ð»Ð°Ð´Ð½Ð°Ð½Ð½Ñ Ð½ÐµÐ´Ð¾Ñтупне" @@ -841,15 +874,6 @@ msgstr "ПереконайтеÑÑŒ, що libpcap вÑтановлений Ñ– в msgid "Invalid configuration" msgstr "ÐеприпуÑтима конфігураціÑ" -msgid "freetype.dll" -msgstr "freetype.dll" - -msgid "libfreetype" -msgstr "libfreetype" - -msgid " is required for ESC/P printer emulation." -msgstr "Ð”Ð»Ñ ÐµÐ¼ÑƒÐ»Ñції принтера ESC/P потрібно libfreetype." - msgid "gsdll32.dll" msgstr "gsdll32.dll" @@ -859,15 +883,6 @@ msgstr "libgs" msgid " is required for automatic conversion of PostScript files to PDF.\n\nAny documents sent to the generic PostScript printer will be saved as PostScript (.ps) files." msgstr " потрібно Ð´Ð»Ñ Ð°Ð²Ñ‚Ð¾Ð¼Ð°Ñ‚Ð¸Ñ‡Ð½Ð¾Ð³Ð¾ Ð¿ÐµÑ€ÐµÑ‚Ð²Ð¾Ñ€ÐµÐ½Ð½Ñ Ñ„Ð°Ð¹Ð»Ñ–Ð² PostScript в PDF.\n\nÐ’ÑÑ– документи, відправлені на загальний принтер PostScript, будуть збережені у виглÑді файлів PostScript (.ps)." -msgid "libfluidsynth.dll" -msgstr "libfluidsynth.dll" - -msgid "libfluidsynth" -msgstr "libfluidsynth" - -msgid " is required for FluidSynth MIDI output." -msgstr "Ð”Ð»Ñ FluidSynth MIDI-виÑновку потрібно libfluidsynth." - msgid "Entering fullscreen mode" msgstr "Вхід у повноекранний режим" @@ -1183,3 +1198,29 @@ msgstr "Ðа 2% повільніше точного RPM" msgid "(System Default)" msgstr "(СиÑтемний)" +msgid "Failed to initialize network driver" +msgstr "Ðе вдалоÑÑ Ñ–Ð½Ñ–Ñ†Ñ–Ð°Ð»Ñ–Ð·ÑƒÐ²Ð°Ñ‚Ð¸ мережевий драйвер" + +msgid "The network configuration will be switched to the null driver" +msgstr "Конфігурацію мережі буде змінено на нульовий драйвер" + +msgid "Mouse sensitivity:" +msgstr "ЧутливіÑть миші:" + +msgid "Select media images from program working directory" +msgstr "Виберіть медіа-Ð·Ð¾Ð±Ñ€Ð°Ð¶ÐµÐ½Ð½Ñ Ð· робочої директорії програми" + +msgid "PIT mode:" +msgstr "Режим PIT:" + +msgid "Auto" +msgstr "Ðвто" + +msgid "Slow" +msgstr "Повільний" + +msgid "Fast" +msgstr "Швидкий" + +msgid "&Auto-pause on focus loss" +msgstr "&Ðвтопауза при втраті фокуÑу" diff --git a/src/qt/languages/zh-CN.po b/src/qt/languages/zh-CN.po index b9c6f6c98..3d045b74e 100644 --- a/src/qt/languages/zh-CN.po +++ b/src/qt/languages/zh-CN.po @@ -76,6 +76,24 @@ msgstr "1.5x(&5)" msgid "&2x" msgstr "2x(&2)" +msgid "&3x" +msgstr "3x(&3)" + +msgid "&4x" +msgstr "4x(&4)" + +msgid "&5x" +msgstr "5x(&5)" + +msgid "&6x" +msgstr "6x(&6)" + +msgid "&7x" +msgstr "7x(&7)" + +msgid "&8x" +msgstr "8x(&8)" + msgid "Filter method" msgstr "过滤方å¼" @@ -106,6 +124,9 @@ msgstr "ä¿æŒæ¯”例(&S)" msgid "&Integer scale" msgstr "整数比例(&I)" +msgid "4:&3 Integer scale" +msgstr "4:3 整数比例(&3)" + msgid "E&GA/(S)VGA settings" msgstr "EGA/(S)VGA 设置(&G)" @@ -188,13 +209,13 @@ msgid "&About 86Box..." msgstr "关于 86Box(&A)..." msgid "&New image..." -msgstr "新建镜åƒ(&N)..." +msgstr "新建映åƒ(&N)..." msgid "&Existing image..." -msgstr "打开已存在的镜åƒ(&E)..." +msgstr "打开已存在的映åƒ(&E)..." msgid "Existing image (&Write-protected)..." -msgstr "打开已存在的镜åƒå¹¶å†™ä¿æŠ¤(&W)..." +msgstr "打开已存在的映åƒå¹¶å†™ä¿æŠ¤(&W)..." msgid "&Record" msgstr "录制(&R)" @@ -212,7 +233,7 @@ msgid "E&ject" msgstr "弹出(&J)" msgid "&Image..." -msgstr "镜åƒ(&I)..." +msgstr "映åƒ(&I)..." msgid "E&xport to 86F..." msgstr "导出为 86F æ ¼å¼(&x)..." @@ -224,10 +245,10 @@ msgid "E&mpty" msgstr "空置驱动器(&M)" msgid "&Reload previous image" -msgstr "载入上一个镜åƒ(&R)" +msgstr "载入上一个映åƒ(&R)" -msgid "&Image" -msgstr "镜åƒ(&I)" +msgid "&Folder..." +msgstr "文件夹(&F)..." msgid "Target &framerate" msgstr "目标帧率(&F)" @@ -266,7 +287,7 @@ msgid "Sound Gain" msgstr "音é‡å¢žç›Š" msgid "New Image" -msgstr "新建镜åƒ" +msgstr "新建映åƒ" msgid "Settings" msgstr "设置" @@ -364,6 +385,12 @@ msgstr "显å¡:" msgid "Voodoo Graphics" msgstr "Voodoo Graphics" +msgid "IBM 8514/a Graphics" +msgstr "IBM 8514/a Graphics" + +msgid "XGA Graphics" +msgstr "XGA Graphics" + msgid "Mouse:" msgstr "é¼ æ ‡:" @@ -382,8 +409,17 @@ msgstr "æ“çºµæ† 3..." msgid "Joystick 4..." msgstr "æ“çºµæ† 4..." -msgid "Sound card:" -msgstr "声å¡:" +msgid "Sound card 1:" +msgstr "å£°å¡ 1:" + +msgid "Sound card 2:" +msgstr "å£°å¡ 2:" + +msgid "Sound card 3:" +msgstr "å£°å¡ 3:" + +msgid "Sound card 4:" +msgstr "å£°å¡ 4:" msgid "MIDI Out Device:" msgstr "MIDI 输出设备:" @@ -394,18 +430,18 @@ msgstr "MIDI 输入设备:" msgid "Standalone MPU-401" msgstr "独立 MPU-401" -msgid "Innovation SSI-2001" -msgstr "Innovation SSI-2001" - -msgid "CMS / Game Blaster" -msgstr "CMS / Game Blaster" - -msgid "Gravis Ultrasound" -msgstr "Gravis Ultrasound" - msgid "Use FLOAT32 sound" msgstr "使用å•精度浮点 (FLOAT32)" +msgid "FM synth driver" +msgstr "è°ƒé¢‘åˆæˆå™¨é©±åЍ噍" + +msgid "Nuked (more accurate)" +msgstr "Nuked (更准确)" + +msgid "YMFM (faster)" +msgstr "YMFM (æ›´å¿«)" + msgid "Network type:" msgstr "网络类型:" @@ -500,7 +536,7 @@ msgid "&New..." msgstr "新建(&N)..." msgid "&Existing..." -msgstr "已有镜åƒ(&E)..." +msgstr "已有映åƒ(&E)..." msgid "&Remove" msgstr "移除(&R)" @@ -533,7 +569,7 @@ msgid "Type:" msgstr "类型:" msgid "Image Format:" -msgstr "é•œåƒæ ¼å¼:" +msgstr "æ˜ åƒæ ¼å¼:" msgid "Block Size:" msgstr "å—大å°:" @@ -550,6 +586,9 @@ msgstr "检查 BPB" msgid "CD-ROM drives:" msgstr "光盘驱动器:" +msgid "Earlier drive" +msgstr "早先的驱动器" + msgid "MO drives:" msgstr "ç£å…‰ç›˜é©±åЍ噍:" @@ -563,7 +602,7 @@ msgid "ISA RTC:" msgstr "ISA 实时时钟:" msgid "ISA Memory Expansion" -msgstr "ISA 内存扩充" +msgstr "ISA 内存扩展" msgid "Card 1:" msgstr "æ‰©å±•å¡ 1:" @@ -611,10 +650,10 @@ msgid "ZIP %03i %i (%s): %ls" msgstr "ZIP %03i %i (%s): %ls" msgid "ZIP images" -msgstr "ZIP 镜åƒ" +msgstr "ZIP 映åƒ" msgid "86Box could not find any usable ROM images.\n\nPlease download a ROM set and extract it into the \"roms\" directory." -msgstr "86Box 找ä¸åˆ°ä»»ä½•å¯ç”¨çš„ ROM 镜åƒã€‚\n\n请下载ROM 包并将其解压到 \"roms\" 文件夹。" +msgstr "86Box 找ä¸åˆ°ä»»ä½•å¯ç”¨çš„ ROM 映åƒã€‚\n\n请下载 ROM 包并将其解压到 \"roms\" 文件夹中。" msgid "(empty)" msgstr "(空)" @@ -632,13 +671,13 @@ msgid "Off" msgstr "å…³" msgid "All images" -msgstr "所有镜åƒ" +msgstr "所有映åƒ" msgid "Basic sector images" -msgstr "基本扇区镜åƒ" +msgstr "基本扇区映åƒ" msgid "Surface images" -msgstr "表é¢é•œåƒ" +msgstr "è¡¨é¢æ˜ åƒ" msgid "Machine \"%hs\" is not available due to missing ROMs in the roms/machines directory. Switching to an available machine." msgstr "由于 roms/machines 文件夹中缺少åˆé€‚çš„ ROM,机型 \"%hs\" ä¸å¯ç”¨ã€‚将切æ¢åˆ°å…¶ä»–å¯ç”¨æœºåž‹ã€‚" @@ -688,9 +727,6 @@ msgstr "按下 F8+F12 释放鼠标" msgid "Press F8+F12 or middle button to release mouse" msgstr "按下 F8+F12 或鼠标中键释放鼠标" -msgid "Unable to initialize FluidSynth" -msgstr "无法åˆå§‹åŒ– FluidSynth" - msgid "Bus" msgstr "总线" @@ -770,13 +806,10 @@ msgid "Floppy %i (%s): %ls" msgstr "软盘 %i (%s): %ls" msgid "Advanced sector images" -msgstr "高级扇区镜åƒ" +msgstr "高级扇区映åƒ" msgid "Flux images" -msgstr "Flux 镜åƒ" - -msgid "Unable to initialize FreeType" -msgstr "无法åˆå§‹åŒ– FreeType" +msgstr "Flux 映åƒ" msgid "Unable to initialize SDL, SDL2.dll is required" msgstr "无法åˆå§‹åŒ– SDLï¼Œéœ€è¦ SDL2.dll" @@ -794,7 +827,7 @@ msgid "MO %i (%ls): %ls" msgstr "ç£å…‰ç›˜ %i (%ls): %ls" msgid "MO images" -msgstr "ç£å…‰ç›˜é•œåƒ" +msgstr "ç£å…‰ç›˜æ˜ åƒ" msgid "Welcome to 86Box!" msgstr "欢迎使用 86Boxï¼" @@ -823,8 +856,8 @@ msgstr "关于 86Box" msgid "86Box v" msgstr "86Box v" -msgid "An emulator of old computers\n\nAuthors: Sarah Walker, Miran Grca, Fred N. van Kempen (waltje), SA1988, Tiseno100, reenigne, leilei, JohnElliott, greatpsycho, and others.\n\nReleased under the GNU General Public License version 2 or later. See LICENSE for more information." -msgstr "一个旧å¼è®¡ç®—机模拟器\n\n作者: Sarah Walkerã€Miran Grcaã€Fred N. van Kempen (waltje)ã€SA1988ã€Tiseno100ã€reenigneã€leileiã€JohnElliottã€greatpsycho 等人。\n\næœ¬è½¯ä»¶ä¾æ® GNU 通用公共许å¯è¯ç¬¬äºŒç‰ˆæˆ–更新版本å‘å¸ƒã€‚è¯¦æƒ…è§ LICENSE 文件。" +msgid "An emulator of old computers\n\nAuthors: Miran GrÄa (OBattler), RichardG867, Jasmine Iwanek, TC1995, coldbrewed, Teemu Korhonen (Manaatti), Joakim L. Gilje, Adrien Moulin (elyosh), Daniel Balsom (gloriouscow), Cacodemon345, Fred N. van Kempen (waltje), Tiseno100, reenigne, and others.\n\nWith previous core contributions from Sarah Walker, leilei, JohnElliott, greatpsycho, and others.\n\nReleased under the GNU General Public License version 2 or later. See LICENSE for more information." +msgstr "一个旧å¼è®¡ç®—机模拟器\n\n作者: Miran GrÄa (OBattler)ã€RichardG867ã€Jasmine Iwanekã€TC1995ã€coldbrewedã€Teemu Korhonen (Manaatti)ã€Joakim L. Giljeã€Adrien Moulin (elyosh)ã€Daniel Balsom (gloriouscow)ã€Cacodemon345ã€Fred N. van Kempen (waltje)ã€Tiseno100ã€reenigne 等人。\n\nWith previous core contributions from Sarah Walker, leilei, JohnElliott, greatpsycho, and others.\n\næœ¬è½¯ä»¶ä¾æ® GNU 通用公共许å¯è¯ç¬¬äºŒç‰ˆæˆ–更新版本å‘å¸ƒã€‚è¯¦æƒ…è§ LICENSE 文件。" msgid "Hardware not available" msgstr "硬件ä¸å¯ç”¨" @@ -841,15 +874,6 @@ msgstr "请确认 libpcap 已安装且使用兼容 libpcap 的网络连接。" msgid "Invalid configuration" msgstr "无效é…ç½®" -msgid "freetype.dll" -msgstr "freetype.dll" - -msgid "libfreetype" -msgstr "libfreetype" - -msgid " is required for ESC/P printer emulation." -msgstr "ESC/P æ‰“å°æœºæ¨¡æ‹Ÿéœ€è¦" - msgid "gsdll32.dll" msgstr "gsdll32.dll" @@ -859,15 +883,6 @@ msgstr "libgs" msgid " is required for automatic conversion of PostScript files to PDF.\n\nAny documents sent to the generic PostScript printer will be saved as PostScript (.ps) files." msgstr " 是将 PostScript 文件转æ¢ä¸º PDF 所需è¦çš„库。\n\n使用通用 PostScript æ‰“å°æœºæ‰“å°çš„æ–‡æ¡£å°†è¢«ä¿å­˜ä¸º PostScript (.ps) 文件。" -msgid "libfluidsynth.dll" -msgstr "libfluidsynth.dll" - -msgid "libfluidsynth" -msgstr "libfluidsynth" - -msgid " is required for FluidSynth MIDI output." -msgstr "FluidSynth MIDI 输出需è¦" - msgid "Entering fullscreen mode" msgstr "æ­£åœ¨è¿›å…¥å…¨å±æ¨¡å¼" @@ -884,7 +899,7 @@ msgid "Don't reset" msgstr "ä¸é‡ç½®" msgid "CD-ROM images" -msgstr "光盘镜åƒ" +msgstr "光盘映åƒ" msgid "%hs Device Configuration" msgstr "%hs 设备é…ç½®" @@ -911,13 +926,13 @@ msgid "Cassette: %s" msgstr "ç£å¸¦: %s" msgid "Cassette images" -msgstr "ç£å¸¦é•œåƒ" +msgstr "ç£å¸¦æ˜ åƒ" msgid "Cartridge %i: %ls" msgstr "å¡å¸¦ %i: %ls" msgid "Cartridge images" -msgstr "å¡å¸¦é•œåƒ" +msgstr "å¡å¸¦æ˜ åƒ" msgid "Error initializing renderer" msgstr "åˆå§‹åŒ–渲染器时出错" @@ -968,13 +983,13 @@ msgid "Add Existing Hard Disk" msgstr "添加已存在的硬盘" msgid "HDI disk images cannot be larger than 4 GB." -msgstr "HDI ç£ç›˜é•œåƒä¸èƒ½è¶…过 4 GB。" +msgstr "HDI ç£ç›˜æ˜ åƒä¸èƒ½è¶…过 4 GB。" msgid "Disk images cannot be larger than 127 GB." -msgstr "ç£ç›˜é•œåƒä¸èƒ½è¶…过 127 GB。" +msgstr "ç£ç›˜æ˜ åƒä¸èƒ½è¶…过 127 GB。" msgid "Hard disk images" -msgstr "硬盘镜åƒ" +msgstr "硬盘映åƒ" msgid "Unable to read file" msgstr "æ— æ³•è¯»å–æ–‡ä»¶" @@ -983,19 +998,19 @@ msgid "Unable to write file" msgstr "无法写入文件" msgid "HDI or HDX images with a sector size other than 512 are not supported." -msgstr "䏿”¯æŒéž 512 字节扇区大å°çš„ HDI 或 HDX 镜åƒã€‚" +msgstr "䏿”¯æŒéž 512 字节扇区大å°çš„ HDI 或 HDX 映åƒã€‚" msgid "USB is not yet supported" msgstr "å°šæœªæ”¯æŒ USB" msgid "Disk image file already exists" -msgstr "ç£ç›˜é•œåƒæ–‡ä»¶å·²å­˜åœ¨" +msgstr "ç£ç›˜æ˜ åƒæ–‡ä»¶å·²å­˜åœ¨" msgid "Please specify a valid file name." msgstr "请指定有效的文件å。" msgid "Disk image created" -msgstr "已创建ç£ç›˜é•œåƒ" +msgstr "已创建ç£ç›˜æ˜ åƒ" msgid "Make sure the file exists and is readable." msgstr "请确定此文件已存在并å¯è¯»å–。" @@ -1004,16 +1019,16 @@ msgid "Make sure the file is being saved to a writable directory." msgstr "请确定此文件ä¿å­˜åœ¨å¯å†™ç›®å½•中。" msgid "Disk image too large" -msgstr "ç£ç›˜é•œåƒå¤ªå¤§" +msgstr "ç£ç›˜æ˜ åƒå¤ªå¤§" msgid "Remember to partition and format the newly-created drive." -msgstr "请记得为新创建的镜åƒåˆ†åŒºå¹¶æ ¼å¼åŒ–。" +msgstr "请记得为新创建的映åƒåˆ†åŒºå¹¶æ ¼å¼åŒ–。" msgid "The selected file will be overwritten. Are you sure you want to use it?" msgstr "选定的文件将被覆盖。确定继续使用此文件å—?" msgid "Unsupported disk image" -msgstr "䏿”¯æŒçš„ç£ç›˜é•œåƒ" +msgstr "䏿”¯æŒçš„ç£ç›˜æ˜ åƒ" msgid "Overwrite" msgstr "覆盖" @@ -1022,13 +1037,13 @@ msgid "Don't overwrite" msgstr "ä¸è¦†ç›–" msgid "Raw image (.img)" -msgstr "åŽŸå§‹é•œåƒ (.img)" +msgstr "åŽŸå§‹æ˜ åƒ (.img)" msgid "HDI image (.hdi)" -msgstr "HDI é•œåƒ (.hdi)" +msgstr "HDI æ˜ åƒ (.hdi)" msgid "HDX image (.hdx)" -msgstr "HDX é•œåƒ (.hdx)" +msgstr "HDX æ˜ åƒ (.hdx)" msgid "Fixed-size VHD (.vhd)" msgstr "å›ºå®šå¤§å° VHD (.vhd)" @@ -1052,7 +1067,7 @@ msgid "Select the parent VHD" msgstr "选择父 VHD 文件" msgid "This could mean that the parent image was modified after the differencing image was created.\n\nIt can also happen if the image files were moved or copied, or by a bug in the program that created this disk.\n\nDo you want to fix the timestamps?" -msgstr "父映åƒå¯èƒ½åœ¨åˆ›å»ºå·®å¼‚镜åƒåŽè¢«ä¿®æ”¹ã€‚\n\nå¦‚æžœé•œåƒæ–‡ä»¶è¢«ç§»åŠ¨æˆ–å¤åˆ¶ï¼Œæˆ–创建此ç£ç›˜çš„程åºä¸­å­˜åœ¨é”™è¯¯ï¼Œä¹Ÿå¯èƒ½å‘ç”Ÿè¿™ç§æƒ…况。\n\n是å¦éœ€è¦ä¿®å¤æ—¶é—´æˆ³ï¼Ÿ" +msgstr "父映åƒå¯èƒ½åœ¨åˆ›å»ºå·®å¼‚映åƒåŽè¢«ä¿®æ”¹ã€‚\n\nå¦‚æžœæ˜ åƒæ–‡ä»¶è¢«ç§»åŠ¨æˆ–å¤åˆ¶ï¼Œæˆ–创建此ç£ç›˜çš„程åºä¸­å­˜åœ¨é”™è¯¯ï¼Œä¹Ÿå¯èƒ½å‘ç”Ÿè¿™ç§æƒ…况。\n\n是å¦éœ€è¦ä¿®å¤æ—¶é—´æˆ³ï¼Ÿ" msgid "Parent and child disk timestamps do not match" msgstr "父盘与å­ç›˜çš„æ—¶é—´æˆ³ä¸åŒ¹é…" @@ -1183,3 +1198,30 @@ msgstr "低于标准转速的 2%" msgid "(System Default)" msgstr "(系统默认)" +msgid "Failed to initialize network driver" +msgstr "网络驱动程åºåˆå§‹åŒ–失败" + +msgid "The network configuration will be switched to the null driver" +msgstr "网络é…置将切æ¢ä¸ºç©ºé©±åŠ¨ç¨‹åº" + +msgid "Mouse sensitivity:" +msgstr "é¼ æ ‡æ•æ„Ÿåº¦:" + +msgid "Select media images from program working directory" +msgstr "从程åºå·¥ä½œç›®å½•中选择介质映åƒ" + +msgid "PIT mode:" +msgstr "PIT 模å¼:" + +msgid "Auto" +msgstr "自动" + +msgid "Slow" +msgstr "æ…¢" + +msgid "Fast" +msgstr "å¿«" + +msgid "&Auto-pause on focus loss" +msgstr "失去焦点时自动暂åœ(&A)" + diff --git a/src/qt/languages/zh-TW.po b/src/qt/languages/zh-TW.po new file mode 100644 index 000000000..2d2ea473e --- /dev/null +++ b/src/qt/languages/zh-TW.po @@ -0,0 +1,1226 @@ +msgid "&Action" +msgstr "動作(&A)" + +msgid "&Keyboard requires capture" +msgstr "éµç›¤éœ€è¦æ•æ‰(&K)" + +msgid "&Right CTRL is left ALT" +msgstr "å°‡å³ CTRL 鵿˜ å°„為左 ALT éµ(&R)" + +msgid "&Hard Reset..." +msgstr "硬é‡è¨­(&H)..." + +msgid "&Ctrl+Alt+Del\tCtrl+F12" +msgstr "Ctrl+Alt+Del(&C)\tCtrl+F12" + +msgid "Ctrl+Alt+&Esc" +msgstr "Ctrl+Alt+Esc(&E)" + +msgid "&Pause" +msgstr "æš«åœ(&P)" + +msgid "E&xit..." +msgstr "退出(&X)..." + +msgid "&View" +msgstr "檢視(&V)" + +msgid "&Hide status bar" +msgstr "éš±è—狀態列(&H)" + +msgid "Hide &toolbar" +msgstr "éš±è—工具列(&T)" + +msgid "&Resizeable window" +msgstr "視窗大å°å¯èª¿(&R)" + +msgid "R&emember size && position" +msgstr "記ä½è¦–窗大å°å’Œä½ç½®(&E)" + +msgid "Re&nderer" +msgstr "渲染器(&N)" + +msgid "&SDL (Software)" +msgstr "SDL (軟體)(&S)" + +msgid "SDL (&Hardware)" +msgstr "SDL (硬體)(&H)" + +msgid "SDL (&OpenGL)" +msgstr "SDL (OpenGL)(&O)" + +msgid "Open&GL (3.0 Core)" +msgstr "OpenGL (3.0 核心)(&G)" + +msgid "&VNC" +msgstr "VNC(&V)" + +msgid "Specify dimensions..." +msgstr "指定視窗大å°..." + +msgid "F&orce 4:3 display ratio" +msgstr "強制 4:3 顯示比例(&O)" + +msgid "&Window scale factor" +msgstr "視窗縮放係數(&W)" + +msgid "&0.5x" +msgstr "0.5x(&0)" + +msgid "&1x" +msgstr "1x(&1)" + +msgid "1.&5x" +msgstr "1.5x(&5)" + +msgid "&2x" +msgstr "2x(&2)" + +msgid "&3x" +msgstr "3x(&3)" + +msgid "&4x" +msgstr "4x(&4)" + +msgid "&5x" +msgstr "5x(&5)" + +msgid "&6x" +msgstr "6x(&6)" + +msgid "&7x" +msgstr "7x(&7)" + +msgid "&8x" +msgstr "8x(&8)" + +msgid "Filter method" +msgstr "éŽæ¿¾æ–¹å¼" + +msgid "&Nearest" +msgstr "é„°è¿‘(&N)" + +msgid "&Linear" +msgstr "線性(&L)" + +msgid "Hi&DPI scaling" +msgstr "HiDPI 縮放(&D)" + +msgid "&Fullscreen\tCtrl+Alt+PgUp" +msgstr "全螢幕(&F)\tCtrl+Alt+PgUp" + +msgid "Fullscreen &stretch mode" +msgstr "全螢幕拉伸模å¼(&S)" + +msgid "&Full screen stretch" +msgstr "全螢幕拉伸(&F)" + +msgid "&4:3" +msgstr "4:3(&4)" + +msgid "&Square pixels (Keep ratio)" +msgstr "ä¿æŒæ¯”例(&S)" + +msgid "&Integer scale" +msgstr "整數比例(&I)" + +msgid "4:&3 Integer scale" +msgstr "4:3 整數比例(&3)" + +msgid "E&GA/(S)VGA settings" +msgstr "EGA/(S)VGA 設定(&G)" + +msgid "&Inverted VGA monitor" +msgstr "VGA 顯示器å色顯示(&I)" + +msgid "VGA screen &type" +msgstr "VGA 螢幕類型(&T)" + +msgid "RGB &Color" +msgstr "RGB 彩色(&C)" + +msgid "&RGB Grayscale" +msgstr "RGB ç°åº¦(&R)" + +msgid "&Amber monitor" +msgstr "ç¥ç€è‰²å–®è‰²é¡¯ç¤ºå™¨(&A)" + +msgid "&Green monitor" +msgstr "綠色單色顯示器(&G)" + +msgid "&White monitor" +msgstr "白色單色顯示器(&W)" + +msgid "Grayscale &conversion type" +msgstr "ç°åº¦è½‰æ›é¡žåž‹(&C)" + +msgid "BT&601 (NTSC/PAL)" +msgstr "BT601 (NTSC/PAL)(&6)" + +msgid "BT&709 (HDTV)" +msgstr "BT709 (HDTV)(&7)" + +msgid "&Average" +msgstr "å¹³å‡(&A)" + +msgid "CGA/PCjr/Tandy/E&GA/(S)VGA overscan" +msgstr "CGA/PCjr/Tandy/EGA/(S)VGA éŽæŽƒæ(&G)" + +msgid "Change contrast for &monochrome display" +msgstr "è®Šæ›´å–®è‰²é¡¯ç¤ºå°æ¯”度(&M)" + +msgid "&Media" +msgstr "介質(&M)" + +msgid "&Tools" +msgstr "工具(&T)" + +msgid "&Settings..." +msgstr "設定(&S)..." + +msgid "&Update status bar icons" +msgstr "更新狀態列圖示(&U)" + +msgid "Take s&creenshot\tCtrl+F11" +msgstr "擷圖(&C)\tCtrl+F11" + +msgid "&Preferences..." +msgstr "å好設定(&P)..." + +msgid "Enable &Discord integration" +msgstr "啟用 Discord æ•´åˆ(&D)" + +msgid "Sound &gain..." +msgstr "音é‡å¢žç›Š(&G)..." + +msgid "Begin trace\tCtrl+T" +msgstr "開始追踪\tCtrl+T" + +msgid "End trace\tCtrl+T" +msgstr "çµæŸè¿½è¸ª\tCtrl+T" + +msgid "&Help" +msgstr "說明(&H)" + +msgid "&Documentation..." +msgstr "文件(&D)..." + +msgid "&About 86Box..." +msgstr "關於 86Box(&A)..." + +msgid "&New image..." +msgstr "新增映åƒ(&N)..." + +msgid "&Existing image..." +msgstr "開啟已存在的映åƒ(&E)..." + +msgid "Existing image (&Write-protected)..." +msgstr "開啟已存在的映åƒä¸¦å¯«ä¿è­·(&W)..." + +msgid "&Record" +msgstr "錄製(&R)" + +msgid "&Play" +msgstr "播放(&P)" + +msgid "&Rewind to the beginning" +msgstr "倒帶至起點(&R)" + +msgid "&Fast forward to the end" +msgstr "快進至終點(&F)" + +msgid "E&ject" +msgstr "退出(&J)" + +msgid "&Image..." +msgstr "映åƒ(&I)..." + +msgid "E&xport to 86F..." +msgstr "匯出為 86F æ ¼å¼(&x)..." + +msgid "&Mute" +msgstr "éœéŸ³(&M)" + +msgid "E&mpty" +msgstr "空置光碟機(&M)" + +msgid "&Reload previous image" +msgstr "載入上一個映åƒ(&R)" + +msgid "&Folder..." +msgstr "資料夾(&F)..." + +msgid "Target &framerate" +msgstr "目標幀率(&F)" + +msgid "&Sync with video" +msgstr "èˆ‡è¦–è¨ŠåŒæ­¥(&S)" + +msgid "&25 fps" +msgstr "25 fps(&2)" + +msgid "&30 fps" +msgstr "30 fps(&3)" + +msgid "&50 fps" +msgstr "50 fps(&5)" + +msgid "&60 fps" +msgstr "60 fps(&6)" + +msgid "&75 fps" +msgstr "75 fps(&7)" + +msgid "&VSync" +msgstr "åž‚ç›´åŒæ­¥(&V)" + +msgid "&Select shader..." +msgstr "é¸å–著色器(&S)..." + +msgid "&Remove shader" +msgstr "移除著色器(&R)" + +msgid "Preferences" +msgstr "å好設定" + +msgid "Sound Gain" +msgstr "音é‡å¢žç›Š" + +msgid "New Image" +msgstr "新增映åƒ" + +msgid "Settings" +msgstr "設定" + +msgid "Specify Main Window Dimensions" +msgstr "指定主視窗大å°" + +msgid "OK" +msgstr "確定" + +msgid "Cancel" +msgstr "å–æ¶ˆ" + +msgid "Save these settings as &global defaults" +msgstr "將以上設定存儲為全局é è¨­å€¼(&G)" + +msgid "&Default" +msgstr "é è¨­(&D)" + +msgid "Language:" +msgstr "語言:" + +msgid "Icon set:" +msgstr "圖示集:" + +msgid "Gain" +msgstr "增益" + +msgid "File name:" +msgstr "檔案å:" + +msgid "Disk size:" +msgstr "ç£ç¢Ÿå¤§å°:" + +msgid "RPM mode:" +msgstr "轉速 (RPM) 模å¼:" + +msgid "Progress:" +msgstr "進度:" + +msgid "Width:" +msgstr "寬度:" + +msgid "Height:" +msgstr "高度:" + +msgid "Lock to this size" +msgstr "鎖定此大å°" + +msgid "Machine type:" +msgstr "機器類型:" + +msgid "Machine:" +msgstr "機型:" + +msgid "Configure" +msgstr "設定" + +msgid "CPU type:" +msgstr "CPU 類型:" + +msgid "Speed:" +msgstr "速度:" + +msgid "FPU:" +msgstr "浮點處ç†å™¨ (FPU):" + +msgid "Wait states:" +msgstr "等待狀態 (WS):" + +msgid "MB" +msgstr "MB" + +msgid "Memory:" +msgstr "記憶體:" + +msgid "Time synchronization" +msgstr "æ™‚é–“åŒæ­¥" + +msgid "Disabled" +msgstr "ç¦ç”¨" + +msgid "Enabled (local time)" +msgstr "啟用 (本地時間)" + +msgid "Enabled (UTC)" +msgstr "啟用 (UTC)" + +msgid "Dynamic Recompiler" +msgstr "å‹•æ…‹é‡ç·¨è­¯å™¨" + +msgid "Video:" +msgstr "顯示å¡:" + +msgid "Voodoo Graphics" +msgstr "Voodoo Graphics" + +msgid "IBM 8514/a Graphics" +msgstr "IBM 8514/a Graphics" + +msgid "XGA Graphics" +msgstr "XGA Graphics" + +msgid "Mouse:" +msgstr "滑鼠:" + +msgid "Joystick:" +msgstr "æ–æ¡¿:" + +msgid "Joystick 1..." +msgstr "æ–æ¡¿ 1..." + +msgid "Joystick 2..." +msgstr "æ–æ¡¿ 2..." + +msgid "Joystick 3..." +msgstr "æ–æ¡¿ 3..." + +msgid "Joystick 4..." +msgstr "æ–æ¡¿ 4..." + +msgid "Sound card 1:" +msgstr "éŸ³æ•ˆå¡ 1:" + +msgid "Sound card 2:" +msgstr "éŸ³æ•ˆå¡ 2:" + +msgid "Sound card 3:" +msgstr "éŸ³æ•ˆå¡ 3:" + +msgid "Sound card 4:" +msgstr "éŸ³æ•ˆå¡ 4:" + +msgid "MIDI Out Device:" +msgstr "MIDI 輸出è£ç½®:" + +msgid "MIDI In Device:" +msgstr "MIDI 輸入è£ç½®:" + +msgid "Standalone MPU-401" +msgstr "ç¨ç«‹ MPU-401" + +msgid "Use FLOAT32 sound" +msgstr "使用單精度浮點 (FLOAT32)" + +msgid "FM synth driver" +msgstr "èª¿é »åˆæˆå™¨é©…動器" + +msgid "Nuked (more accurate)" +msgstr "Nuked (更準確)" + +msgid "YMFM (faster)" +msgstr "YMFM (æ›´å¿«)" + +msgid "Network type:" +msgstr "網路類型:" + +msgid "PCap device:" +msgstr "PCap è£ç½®:" + +msgid "Network adapter:" +msgstr "ç¶²è·¯é…æŽ¥å™¨:" + +msgid "COM1 Device:" +msgstr "COM1 è£ç½®:" + +msgid "COM2 Device:" +msgstr "COM2 è£ç½®:" + +msgid "COM3 Device:" +msgstr "COM3 è£ç½®:" + +msgid "COM4 Device:" +msgstr "COM4 è£ç½®:" + +msgid "LPT1 Device:" +msgstr "LPT1 è£ç½®:" + +msgid "LPT2 Device:" +msgstr "LPT2 è£ç½®:" + +msgid "LPT3 Device:" +msgstr "LPT3 è£ç½®:" + +msgid "LPT4 Device:" +msgstr "LPT4 è£ç½®:" + +msgid "Serial port 1" +msgstr "åºåˆ—埠 1" + +msgid "Serial port 2" +msgstr "åºåˆ—埠 2" + +msgid "Serial port 3" +msgstr "åºåˆ—埠 3" + +msgid "Serial port 4" +msgstr "åºåˆ—埠 4" + +msgid "Parallel port 1" +msgstr "並列埠 1" + +msgid "Parallel port 2" +msgstr "並列埠 2" + +msgid "Parallel port 3" +msgstr "並列埠 3" + +msgid "Parallel port 4" +msgstr "並列埠 4" + +msgid "HD Controller:" +msgstr "硬碟控制器:" + +msgid "FD Controller:" +msgstr "軟碟控制器:" + +msgid "Tertiary IDE Controller" +msgstr "第三 IDE 控制器" + +msgid "Quaternary IDE Controller" +msgstr "第四 IDE 控制器" + +msgid "SCSI" +msgstr "SCSI" + +msgid "Controller 1:" +msgstr "控制器 1:" + +msgid "Controller 2:" +msgstr "控制器 2:" + +msgid "Controller 3:" +msgstr "控制器 3:" + +msgid "Controller 4:" +msgstr "控制器 4:" + +msgid "Cassette" +msgstr "ç£å¸¶" + +msgid "Hard disks:" +msgstr "硬碟:" + +msgid "&New..." +msgstr "新增(&N)..." + +msgid "&Existing..." +msgstr "已有映åƒ(&E)..." + +msgid "&Remove" +msgstr "移除(&R)" + +msgid "Bus:" +msgstr "åŒ¯æµæŽ’:" + +msgid "Channel:" +msgstr "通é“:" + +msgid "ID:" +msgstr "ID:" + +msgid "&Specify..." +msgstr "指定(&S)..." + +msgid "Sectors:" +msgstr "ç£å€(S):" + +msgid "Heads:" +msgstr "ç£é ­(H):" + +msgid "Cylinders:" +msgstr "ç£æŸ±(C):" + +msgid "Size (MB):" +msgstr "å¤§å° (MB):" + +msgid "Type:" +msgstr "類型:" + +msgid "Image Format:" +msgstr "æ˜ åƒæ ¼å¼:" + +msgid "Block Size:" +msgstr "å€å¡Šå¤§å°:" + +msgid "Floppy drives:" +msgstr "軟碟機:" + +msgid "Turbo timings" +msgstr "加速時åº" + +msgid "Check BPB" +msgstr "檢查 BPB" + +msgid "CD-ROM drives:" +msgstr "光碟機:" + +msgid "Earlier drive" +msgstr "早先的光碟機" + +msgid "MO drives:" +msgstr "ç£å…‰ç¢Ÿæ©Ÿ:" + +msgid "ZIP drives:" +msgstr "ZIP ç£ç¢Ÿæ©Ÿ:" + +msgid "ZIP 250" +msgstr "ZIP 250" + +msgid "ISA RTC:" +msgstr "ISA 實時時é˜:" + +msgid "ISA Memory Expansion" +msgstr "ISA 記憶體擴充" + +msgid "Card 1:" +msgstr "æ“´å……å¡ 1:" + +msgid "Card 2:" +msgstr "æ“´å……å¡ 2:" + +msgid "Card 3:" +msgstr "æ“´å……å¡ 3:" + +msgid "Card 4:" +msgstr "æ“´å……å¡ 4:" + +msgid "ISABugger device" +msgstr "ISABugger è£ç½®" + +msgid "POST card" +msgstr "自檢 (POST) å¡" + +msgid "FONT_SIZE" +msgstr "9" + +msgid "FONT_NAME" +msgstr "Microsoft JhengHei" + +msgid "86Box" +msgstr "86Box" + +msgid "Error" +msgstr "錯誤" + +msgid "Fatal error" +msgstr "致命錯誤" + +msgid " - PAUSED" +msgstr " - 已暫åœ" + +msgid "Press Ctrl+Alt+PgDn to return to windowed mode." +msgstr "按下 Ctrl+Alt+PgDn 返回到視窗模å¼ã€‚" + +msgid "Speed" +msgstr "速度" + +msgid "ZIP %03i %i (%s): %ls" +msgstr "ZIP %03i %i (%s): %ls" + +msgid "ZIP images" +msgstr "ZIP 映åƒ" + +msgid "86Box could not find any usable ROM images.\n\nPlease download a ROM set and extract it into the \"roms\" directory." +msgstr "86Box 找ä¸åˆ°ä»»ä½•å¯ç”¨çš„ ROM 映åƒã€‚\n\n請下載 ROM 套件並將其解壓到 \"roms\" 資料夾。" + +msgid "(empty)" +msgstr "(空)" + +msgid "All files" +msgstr "所有檔案" + +msgid "Turbo" +msgstr "加速" + +msgid "On" +msgstr "é–‹" + +msgid "Off" +msgstr "é—œ" + +msgid "All images" +msgstr "所有映åƒ" + +msgid "Basic sector images" +msgstr "基本ç£å€æ˜ åƒ" + +msgid "Surface images" +msgstr "è¡¨é¢æ˜ åƒ" + +msgid "Machine \"%hs\" is not available due to missing ROMs in the roms/machines directory. Switching to an available machine." +msgstr "由於 roms/machines 資料夾中缺少åˆé©çš„ ROM,機型 \"%hs\" ä¸å¯ç”¨ã€‚將切æ›åˆ°å…¶ä»–å¯ç”¨æ©Ÿåž‹ã€‚" + +msgid "Video card \"%hs\" is not available due to missing ROMs in the roms/video directory. Switching to an available video card." +msgstr "由於 roms/video 資料夾中缺少åˆé©çš„ ROMï¼Œé¡¯ç¤ºå¡ \"%hs\" ä¸å¯ç”¨ã€‚將切æ›åˆ°å…¶ä»–å¯ç”¨é¡¯ç¤ºå¡ã€‚" + +msgid "Machine" +msgstr "機型" + +msgid "Display" +msgstr "顯示" + +msgid "Input devices" +msgstr "輸入è£ç½®" + +msgid "Sound" +msgstr "è²éŸ³" + +msgid "Network" +msgstr "網路" + +msgid "Ports (COM & LPT)" +msgstr "連接埠 (COM å’Œ LPT)" + +msgid "Storage controllers" +msgstr "存儲控制器" + +msgid "Hard disks" +msgstr "硬碟" + +msgid "Floppy & CD-ROM drives" +msgstr "軟碟/光碟機" + +msgid "Other removable devices" +msgstr "å…¶ä»–å¸é™¤å¼è£ç½®" + +msgid "Other peripherals" +msgstr "其他周邊è£ç½®" + +msgid "Click to capture mouse" +msgstr "é»žæ“Šè¦–çª—æ•æ‰æ»‘é¼ " + +msgid "Press F8+F12 to release mouse" +msgstr "按下 F8+F12 釋放滑鼠" + +msgid "Press F8+F12 or middle button to release mouse" +msgstr "按下 F8+F12 或滑鼠中éµé‡‹æ”¾æ»‘é¼ " + +msgid "Bus" +msgstr "åŒ¯æµæŽ’" + +msgid "File" +msgstr "檔案" + +msgid "C" +msgstr "C" + +msgid "H" +msgstr "H" + +msgid "S" +msgstr "S" + +msgid "KB" +msgstr "KB" + +msgid "Could not initialize the video renderer." +msgstr "無法åˆå§‹åŒ–視訊渲染器。" + +msgid "Default" +msgstr "é è¨­" + +msgid "%i Wait state(s)" +msgstr "%i 等待狀態 (WS)" + +msgid "Type" +msgstr "類型" + +msgid "Failed to set up PCap" +msgstr "設定 PCap 失敗" + +msgid "No PCap devices found" +msgstr "未找到 PCap è£ç½®" + +msgid "Invalid PCap device" +msgstr "無效 PCap è£ç½®" + +msgid "Standard 2-button joystick(s)" +msgstr "標準 2 鵿–æ¡¿" + +msgid "Standard 4-button joystick" +msgstr "標準 4 鵿–æ¡¿" + +msgid "Standard 6-button joystick" +msgstr "標準 6 鵿–æ¡¿" + +msgid "Standard 8-button joystick" +msgstr "標準 8 鵿–æ¡¿" + +msgid "CH Flightstick Pro" +msgstr "CH Flightstick Pro" + +msgid "Microsoft SideWinder Pad" +msgstr "Microsoft SideWinder Pad" + +msgid "Thrustmaster Flight Control System" +msgstr "Thrustmaster Flight Control System" + +msgid "None" +msgstr "ç„¡" + +msgid "Unable to load keyboard accelerators." +msgstr "無法載入éµç›¤åŠ é€Ÿå™¨ã€‚" + +msgid "Unable to register raw input." +msgstr "無法註冊原始輸入。" + +msgid "%u" +msgstr "%u" + +msgid "%u MB (CHS: %i, %i, %i)" +msgstr "%u MB (CHS: %i, %i, %i)" + +msgid "Floppy %i (%s): %ls" +msgstr "軟碟 %i (%s): %ls" + +msgid "Advanced sector images" +msgstr "進階ç£å€æ˜ åƒ" + +msgid "Flux images" +msgstr "Flux 映åƒ" + +msgid "Unable to initialize SDL, SDL2.dll is required" +msgstr "無法åˆå§‹åŒ– SDLï¼Œéœ€è¦ SDL2.dll" + +msgid "Are you sure you want to hard reset the emulated machine?" +msgstr "確定è¦ç¡¬é‡è¨­æ¨¡æ“¬å™¨å—Žï¼Ÿ" + +msgid "Are you sure you want to exit 86Box?" +msgstr "確定è¦é€€å‡º 86Box 嗎?" + +msgid "Unable to initialize Ghostscript" +msgstr "無法åˆå§‹åŒ– Ghostscript" + +msgid "MO %i (%ls): %ls" +msgstr "ç£å…‰ç¢Ÿ %i (%ls): %ls" + +msgid "MO images" +msgstr "ç£å…‰ç¢Ÿæ˜ åƒ" + +msgid "Welcome to 86Box!" +msgstr "歡迎使用 86Boxï¼" + +msgid "Internal controller" +msgstr "內部控制器" + +msgid "Exit" +msgstr "退出" + +msgid "No ROMs found" +msgstr "找ä¸åˆ° ROM" + +msgid "Do you want to save the settings?" +msgstr "è¦å„²å­˜è¨­å®šå—Žï¼Ÿ" + +msgid "This will hard reset the emulated machine." +msgstr "æ­¤æ“作將硬é‡è¨­æ¨¡æ“¬å™¨ã€‚" + +msgid "Save" +msgstr "儲存" + +msgid "About 86Box" +msgstr "關於 86Box" + +msgid "86Box v" +msgstr "86Box v" + +msgid "An emulator of old computers\n\nAuthors: Miran GrÄa (OBattler), RichardG867, Jasmine Iwanek, TC1995, coldbrewed, Teemu Korhonen (Manaatti), Joakim L. Gilje, Adrien Moulin (elyosh), Daniel Balsom (gloriouscow), Cacodemon345, Fred N. van Kempen (waltje), Tiseno100, reenigne, and others.\n\nWith previous core contributions from Sarah Walker, leilei, JohnElliott, greatpsycho, and others.\n\nReleased under the GNU General Public License version 2 or later. See LICENSE for more information." +msgstr "一個舊å¼é›»è…¦æ¨¡æ“¬å™¨\n\n作者: Miran GrÄa (OBattler)ã€RichardG867ã€Jasmine Iwanekã€TC1995ã€coldbrewedã€Teemu Korhonen (Manaatti)ã€Joakim L. Giljeã€Adrien Moulin (elyosh)ã€Daniel Balsom (gloriouscow)ã€Cacodemon345ã€Fred N. van Kempen (waltje)ã€Tiseno100ã€reenigne 等人。\n\nWith previous core contributions from Sarah Walker, leilei, JohnElliott, greatpsycho, and others.\n\næœ¬è»Ÿé«”ä¾æ“š GNU 通用公共授權第二版或更新版本發布。詳情見 LICENSE 檔案。" + +msgid "Hardware not available" +msgstr "硬體ä¸å¯ç”¨" + +msgid "WinPcap" +msgstr "WinPcap" + +msgid "libpcap" +msgstr "libpcap" + +msgid "Make sure libpcap is installed and that you are on a libpcap-compatible network connection." +msgstr "è«‹ç¢ºèª libpcap 已安è£ä¸”使用相容 libpcap 的網路連線。" + +msgid "Invalid configuration" +msgstr "無效設定" + +msgid "gsdll32.dll" +msgstr "gsdll32.dll" + +msgid "libgs" +msgstr "libgs" + +msgid " is required for automatic conversion of PostScript files to PDF.\n\nAny documents sent to the generic PostScript printer will be saved as PostScript (.ps) files." +msgstr " 是將 PostScript 檔案轉æ›ç‚º PDF 所需è¦çš„庫。\n\n使用通用 PostScript å°è¡¨æ©Ÿåˆ—å°çš„æ–‡ä»¶å°‡è¢«å„²å­˜ç‚º PostScript (.ps) 檔案。" + +msgid "Entering fullscreen mode" +msgstr "正在進入全螢幕模å¼" + +msgid "Don't show this message again" +msgstr "ä¸è¦å†é¡¯ç¤ºæ­¤æ¶ˆæ¯" + +msgid "Don't exit" +msgstr "ä¸é€€å‡º" + +msgid "Reset" +msgstr "é‡è¨­" + +msgid "Don't reset" +msgstr "ä¸é‡è¨­" + +msgid "CD-ROM images" +msgstr "光碟映åƒ" + +msgid "%hs Device Configuration" +msgstr "%hs è£ç½®è¨­å®š" + +msgid "Monitor in sleep mode" +msgstr "顯示器處在ç¡çœ ç‹€æ…‹" + +msgid "OpenGL Shaders" +msgstr "OpenGL 著色器" + +msgid "OpenGL options" +msgstr "OpenGL é¸é …" + +msgid "You are loading an unsupported configuration" +msgstr "正在載入一個ä¸å—支æ´çš„設定" + +msgid "CPU type filtering based on selected machine is disabled for this emulated machine.\n\nThis makes it possible to choose a CPU that is otherwise incompatible with the selected machine. However, you may run into incompatibilities with the machine BIOS or other software.\n\nEnabling this setting is not officially supported and any bug reports filed may be closed as invalid." +msgstr "此模擬電腦ç¦ç”¨äº†åŸºæ–¼é¸å®šé›»è…¦çš„ CPU é¡žåž‹éŽæ¿¾ã€‚\n\n能夠é¸ä¸­èˆ‡æ‰€é¸æ©Ÿå™¨æœ¬ä¸ç›¸å®¹çš„ CPU,但是å¯èƒ½æœƒé‡åˆ°èˆ‡æ©Ÿå™¨ BIOS 或其他軟體ä¸ç›¸å®¹çš„å•題。\n\n啟用此設定ä¸å—官方支æ´ï¼Œä¸¦ä¸”æäº¤çš„任何錯誤報告å¯èƒ½æœƒè¦–為無效而關閉。" + +msgid "Continue" +msgstr "繼續" + +msgid "Cassette: %s" +msgstr "ç£å¸¶: %s" + +msgid "Cassette images" +msgstr "ç£å¸¶æ˜ åƒ" + +msgid "Cartridge %i: %ls" +msgstr "å¡å¸¶ %i: %ls" + +msgid "Cartridge images" +msgstr "å¡å¸¶æ˜ åƒ" + +msgid "Error initializing renderer" +msgstr "åˆå§‹åŒ–渲染器時出錯" + +msgid "OpenGL (3.0 Core) renderer could not be initialized. Use another renderer." +msgstr "無法åˆå§‹åŒ– OpenGL (3.0 核心) 渲染器。請使用其他渲染器。" + +msgid "Resume execution" +msgstr "æ¢å¾©åŸ·è¡Œ" + +msgid "Pause execution" +msgstr "æš«åœåŸ·è¡Œ" + +msgid "Press Ctrl+Alt+Del" +msgstr "按下 Ctrl+Alt+Del" + +msgid "Press Ctrl+Alt+Esc" +msgstr "按下 Ctrl+Alt+Esc" + +msgid "Hard reset" +msgstr "硬é‡è¨­" + +msgid "ACPI shutdown" +msgstr "ACPI 關機" + +msgid "Hard disk (%s)" +msgstr "硬碟 (%s)" + +msgid "%01i:%01i" +msgstr "%01i:%01i" + +msgid "%01i" +msgstr "%01i" + +msgid "MFM/RLL or ESDI CD-ROM drives never existed" +msgstr "ä¸å­˜åœ¨ MFM/RLL 或 ESDI CD-ROM 光碟機" + +msgid "Custom..." +msgstr "自訂..." + +msgid "Custom (large)..." +msgstr "自訂 (大容é‡)..." + +msgid "Add New Hard Disk" +msgstr "增加新硬碟" + +msgid "Add Existing Hard Disk" +msgstr "增加已存在的硬碟" + +msgid "HDI disk images cannot be larger than 4 GB." +msgstr "HDI ç£ç¢Ÿæ˜ åƒä¸èƒ½è¶…éŽ 4 GB。" + +msgid "Disk images cannot be larger than 127 GB." +msgstr "ç£ç¢Ÿæ˜ åƒä¸èƒ½è¶…éŽ 127 GB。" + +msgid "Hard disk images" +msgstr "硬碟映åƒ" + +msgid "Unable to read file" +msgstr "ç„¡æ³•è®€å–æª”案" + +msgid "Unable to write file" +msgstr "無法寫入檔案" + +msgid "HDI or HDX images with a sector size other than 512 are not supported." +msgstr "䏿”¯æ´éž 512 ä½å…ƒçµ„ç£å€å¤§å°çš„ HDI 或 HDX 映åƒã€‚" + +msgid "USB is not yet supported" +msgstr "å°šæœªæ”¯æ´ USB" + +msgid "Disk image file already exists" +msgstr "ç£ç¢Ÿæ˜ åƒæª”案已存在" + +msgid "Please specify a valid file name." +msgstr "請指定有效的檔案å。" + +msgid "Disk image created" +msgstr "已創建ç£ç¢Ÿæ˜ åƒ" + +msgid "Make sure the file exists and is readable." +msgstr "請確定此檔案已存在並å¯è®€å–。" + +msgid "Make sure the file is being saved to a writable directory." +msgstr "請確定此檔案儲存在å¯å¯«ç›®éŒ„中。" + +msgid "Disk image too large" +msgstr "ç£ç¢Ÿæ˜ åƒå¤ªå¤§" + +msgid "Remember to partition and format the newly-created drive." +msgstr "請記得為新創建的映åƒåˆ†å€ä¸¦æ ¼å¼åŒ–。" + +msgid "The selected file will be overwritten. Are you sure you want to use it?" +msgstr "é¸å®šçš„æª”案將被覆蓋。確定繼續使用此檔案嗎?" + +msgid "Unsupported disk image" +msgstr "䏿”¯æ´çš„ç£ç¢Ÿæ˜ åƒ" + +msgid "Overwrite" +msgstr "覆蓋" + +msgid "Don't overwrite" +msgstr "ä¸è¦†è“‹" + +msgid "Raw image (.img)" +msgstr "åŽŸå§‹æ˜ åƒ (.img)" + +msgid "HDI image (.hdi)" +msgstr "HDI æ˜ åƒ (.hdi)" + +msgid "HDX image (.hdx)" +msgstr "HDX æ˜ åƒ (.hdx)" + +msgid "Fixed-size VHD (.vhd)" +msgstr "å›ºå®šå¤§å° VHD (.vhd)" + +msgid "Dynamic-size VHD (.vhd)" +msgstr "å‹•æ…‹å¤§å° VHD (.vhd)" + +msgid "Differencing VHD (.vhd)" +msgstr "差分 VHD (.vhd)" + +msgid "Large blocks (2 MB)" +msgstr "大å€å¡Š (2 MB)" + +msgid "Small blocks (512 KB)" +msgstr "å°å€å¡Š (512 KB)" + +msgid "VHD files" +msgstr "VHD 檔案" + +msgid "Select the parent VHD" +msgstr "é¸å–父 VHD 檔案" + +msgid "This could mean that the parent image was modified after the differencing image was created.\n\nIt can also happen if the image files were moved or copied, or by a bug in the program that created this disk.\n\nDo you want to fix the timestamps?" +msgstr "父映åƒå¯èƒ½åœ¨å‰µå»ºå·®ç•°æ˜ åƒå¾Œè¢«ä¿®æ”¹ã€‚\n\nå¦‚æžœæ˜ åƒæª”案被移動或複製,或創建此ç£ç¢Ÿçš„程å¼ä¸­å­˜åœ¨éŒ¯èª¤ï¼Œä¹Ÿå¯èƒ½ç™¼ç”Ÿé€™ç¨®æƒ…æ³ã€‚\n\n是å¦éœ€è¦ä¿®å¾©æ™‚間戳?" + +msgid "Parent and child disk timestamps do not match" +msgstr "父碟與å­ç¢Ÿçš„æ™‚間戳ä¸åŒ¹é…" + +msgid "Could not fix VHD timestamp." +msgstr "無法修復 VHD 時間戳。" + +msgid "%01i:%02i" +msgstr "%01i:%02i" + +msgid "MFM/RLL" +msgstr "MFM/RLL" + +msgid "XTA" +msgstr "XTA" + +msgid "ESDI" +msgstr "ESDI" + +msgid "IDE" +msgstr "IDE" + +msgid "ATAPI" +msgstr "ATAPI" + +msgid "MFM/RLL (%01i:%01i)" +msgstr "MFM/RLL (%01i:%01i)" + +msgid "XTA (%01i:%01i)" +msgstr "XTA (%01i:%01i)" + +msgid "ESDI (%01i:%01i)" +msgstr "ESDI (%01i:%01i)" + +msgid "IDE (%01i:%01i)" +msgstr "IDE (%01i:%01i)" + +msgid "ATAPI (%01i:%01i)" +msgstr "ATAPI (%01i:%01i)" + +msgid "SCSI (%01i:%02i)" +msgstr "SCSI (%01i:%02i)" + +msgid "CD-ROM %i (%s): %s" +msgstr "光碟 %i (%s): %s" + +msgid "160 kB" +msgstr "160 kB" + +msgid "180 kB" +msgstr "180 kB" + +msgid "320 kB" +msgstr "320 kB" + +msgid "360 kB" +msgstr "360 kB" + +msgid "640 kB" +msgstr "640 kB" + +msgid "720 kB" +msgstr "720 kB" + +msgid "1.2 MB" +msgstr "1.2 MB" + +msgid "1.25 MB" +msgstr "1.25 MB" + +msgid "1.44 MB" +msgstr "1.44 MB" + +msgid "DMF (cluster 1024)" +msgstr "DMF (1024 ç°‡)" + +msgid "DMF (cluster 2048)" +msgstr "DMF (2048 ç°‡)" + +msgid "2.88 MB" +msgstr "2.88 MB" + +msgid "ZIP 100" +msgstr "ZIP 100" + +msgid "3.5\" 128 MB (ISO 10090)" +msgstr "3.5 è‹±å‹ 128 MB (ISO 10090)" + +msgid "3.5\" 230 MB (ISO 13963)" +msgstr "3.5 è‹±å‹ 230 MB (ISO 13963)" + +msgid "3.5\" 540 MB (ISO 15498)" +msgstr "3.5 è‹±å‹ 540 MB (ISO 15498)" + +msgid "3.5\" 640 MB (ISO 15498)" +msgstr "3.5 è‹±å‹ 640 MB (ISO 15498)" + +msgid "3.5\" 1.3 GB (GigaMO)" +msgstr "3.5 è‹±å‹ 1.3 GB (GigaMO)" + +msgid "3.5\" 2.3 GB (GigaMO 2)" +msgstr "3.5 è‹±å‹ 2.3 GB (GigaMO 2)" + +msgid "5.25\" 600 MB" +msgstr "5.25 è‹±å‹ 600 MB" + +msgid "5.25\" 650 MB" +msgstr "5.25 è‹±å‹ 650 MB" + +msgid "5.25\" 1 GB" +msgstr "5.25 è‹±å‹ 1 GB" + +msgid "5.25\" 1.3 GB" +msgstr "5.25 è‹±å‹ 1.3 GB" + +msgid "Perfect RPM" +msgstr "標準轉速 (RPM)" + +msgid "1% below perfect RPM" +msgstr "低於標準轉速的 1%" + +msgid "1.5% below perfect RPM" +msgstr "低於標準轉速的 1.5%" + +msgid "2% below perfect RPM" +msgstr "低於標準轉速的 2%" + +msgid "(System Default)" +msgstr "(系統é è¨­)" + +msgid "Failed to initialize network driver" +msgstr "åˆå§‹åŒ–網路驅動程å¼å¤±æ•—" + +msgid "The network configuration will be switched to the null driver" +msgstr "網路設定將切æ›ç‚ºç©ºé©…動程å¼" + +msgid "Mouse sensitivity:" +msgstr "æ»‘é¼ éˆæ•度:" + +msgid "Select media images from program working directory" +msgstr "從程å¼å·¥ä½œç›®éŒ„䏭鏿“‡ä»‹è³ªæ˜ åƒ" + +msgid "PIT mode:" +msgstr "PIT模å¼:" + +msgid "Auto" +msgstr "自動" + +msgid "Slow" +msgstr "æ…¢" + +msgid "Fast" +msgstr "å¿«" + +msgid "&Auto-pause on focus loss" +msgstr "失去焦點時自動暫åœ(&A)" diff --git a/src/qt/macos_event_filter.mm b/src/qt/macos_event_filter.mm index 0ea799f99..ff4e7c4d2 100644 --- a/src/qt/macos_event_filter.mm +++ b/src/qt/macos_event_filter.mm @@ -1,103 +1,91 @@ #include -//#include "86box/plat.h" +// #include "86box/plat.h" #include "cocoa_mouse.hpp" #import -extern "C" -{ +extern "C" { #include <86box/86box.h> #include <86box/keyboard.h> #include <86box/mouse.h> #include <86box/config.h> -//#include <86box/plat.h> +// #include <86box/plat.h> #include <86box/plat_dynld.h> #include <86box/device.h> #include <86box/timer.h> #include <86box/ui.h> #include <86box/video.h> -extern int mouse_capture; +extern int mouse_capture; extern void plat_mouse_capture(int); } -typedef struct mouseinputdata -{ - int deltax, deltay, deltaz; - int mousebuttons; -} mouseinputdata; - -static mouseinputdata mousedata; - CocoaEventFilter::~CocoaEventFilter() { - } -bool CocoaEventFilter::nativeEventFilter(const QByteArray &eventType, void *message, result_t *result) +bool +CocoaEventFilter::nativeEventFilter(const QByteArray &eventType, void *message, result_t *result) { - if (mouse_capture) - { - if (eventType == "mac_generic_NSEvent") - { - NSEvent* event = (NSEvent*)message; + int b = 0; + + if (mouse_capture) { + if (eventType == "mac_generic_NSEvent") { + NSEvent *event = (NSEvent *) message; if ([event type] == NSEventTypeMouseMoved || [event type] == NSEventTypeLeftMouseDragged || [event type] == NSEventTypeRightMouseDragged - || [event type] == NSEventTypeOtherMouseDragged) - { - mousedata.deltax += [event deltaX]; - mousedata.deltay += [event deltaY]; + || [event type] == NSEventTypeOtherMouseDragged) { + mouse_scalef((double) [event deltaX], (double) [event deltaY]); return true; } - if ([event type] == NSEventTypeScrollWheel) - { - mousedata.deltaz += [event deltaY]; + if ([event type] == NSEventTypeScrollWheel) { + mouse_set_z([event deltaY]); return true; } - switch ([event type]) - { - default: return false; + switch ([event type]) { + default: + return false; case NSEventTypeLeftMouseDown: - { - mousedata.mousebuttons |= 1; - break; - } + { + b = mouse_get_buttons_ex() | 1; + mouse_set_buttons_ex(b); + break; + } case NSEventTypeLeftMouseUp: - { - mousedata.mousebuttons &= ~1; - break; - } + { + b = mouse_get_buttons_ex() & ~1; + mouse_set_buttons_ex(b); + break; + } case NSEventTypeRightMouseDown: - { - mousedata.mousebuttons |= 2; - break; - } + { + b = mouse_get_buttons_ex() | 2; + mouse_set_buttons_ex(b); + break; + } case NSEventTypeRightMouseUp: - { - mousedata.mousebuttons &= ~2; - break; - } + { + b = mouse_get_buttons_ex() & ~2; + mouse_set_buttons_ex(b); + break; + } case NSEventTypeOtherMouseDown: - { - mousedata.mousebuttons |= 4; - break; - } + { + b = mouse_get_buttons_ex() | 4; + mouse_set_buttons_ex(b); + break; + } case NSEventTypeOtherMouseUp: - { - if (mouse_get_buttons() < 3) { plat_mouse_capture(0); return true; } - mousedata.mousebuttons &= ~4; - break; - } + { + if (mouse_get_buttons() < 3) { + plat_mouse_capture(0); + return true; + } + b = mouse_get_buttons_ex() & ~4; + mouse_set_buttons_ex(b); + break; + } } return true; } } return false; } - -extern "C" void macos_poll_mouse() -{ - mouse_x = mousedata.deltax; - mouse_y = mousedata.deltay; - mouse_z = mousedata.deltaz; - mousedata.deltax = mousedata.deltay = mousedata.deltaz = 0; - mouse_buttons = mousedata.mousebuttons; -} diff --git a/src/qt/qt.c b/src/qt/qt.c index 259f79c88..c2a5396da 100644 --- a/src/qt/qt.c +++ b/src/qt/qt.c @@ -1,23 +1,23 @@ /* - * 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. + * 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. + * This file is part of the 86Box distribution. * * * - * Authors: Joakim L. Gilje + * Authors: Joakim L. Gilje * - * Copyright 2021 Joakim L. Gilje + * Copyright 2021 Joakim L. Gilje */ /* * C functionality for Qt platform, where the C equivalent is not easily * implemented in Qt */ #if !defined(_WIN32) || !defined(__clang__) -#include +# include #endif #include #include @@ -29,14 +29,17 @@ #include <86box/timer.h> #include <86box/nvr.h> -int qt_nvr_save(void) { +int +qt_nvr_save(void) +{ return nvr_save(); } -char icon_set[256] = ""; /* name of the iconset to be used */ +char icon_set[256] = ""; /* name of the iconset to be used */ int -plat_vidapi(char* api) { +plat_vidapi(char *api) +{ if (!strcasecmp(api, "default") || !strcasecmp(api, "system")) { return 0; } else if (!strcasecmp(api, "qt_software")) { @@ -47,30 +50,47 @@ plat_vidapi(char* api) { return 2; } else if (!strcasecmp(api, "qt_opengl3")) { return 3; + } else if (!strcasecmp(api, "qt_vulkan")) { + return 4; + } else if (!strcasecmp(api, "qt_d3d9")) { + return 5; + } else if (!strcasecmp(api, "vnc")) { + return 6; } return 0; } -char* plat_vidapi_name(int api) { - char* name = "default"; +char * +plat_vidapi_name(int api) +{ + char *name = "default"; switch (api) { - case 0: - name = "qt_software"; - break; - case 1: - name = "qt_opengl"; - break; - case 2: - name = "qt_opengles"; - break; - case 3: - name = "qt_opengl3"; - break; - default: - fatal("Unknown renderer: %i\n", api); - break; + case 0: + name = "qt_software"; + break; + case 1: + name = "qt_opengl"; + break; + case 2: + name = "qt_opengles"; + break; + case 3: + name = "qt_opengl3"; + break; + case 4: + name = "qt_vulkan"; + break; + case 5: + name = "qt_d3d9"; + break; + case 6: + name = "vnc"; + break; + default: + fatal("Unknown renderer: %i\n", api); + break; } return name; diff --git a/src/qt/qt_cdrom.c b/src/qt/qt_cdrom.c index a15e9c600..1facae486 100644 --- a/src/qt/qt_cdrom.c +++ b/src/qt/qt_cdrom.c @@ -1,21 +1,20 @@ /* - * 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. + * 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. + * This file is part of the 86Box distribution. * - * Handle the platform-side of CDROM/ZIP/MO drives. + * Handle the platform-side of CDROM/ZIP/MO drives. * * * - * Authors: Sarah Walker, - * Miran Grca, - * Fred N. van Kempen, + * Authors: Miran Grca, + * Fred N. van Kempen, * - * Copyright 2016-2018 Miran Grca. - * Copyright 2017,2018 Fred N. van Kempen. + * Copyright 2016-2018 Miran Grca. + * Copyright 2017-2018 Fred N. van Kempen. */ #include @@ -45,11 +44,11 @@ plat_cdrom_ui_update(uint8_t id, uint8_t reload) cdrom_t *drv = &cdrom[id]; if (drv->host_drive == 0) { - ui_sb_update_icon_state(SB_CDROM|id, 1); + ui_sb_update_icon_state(SB_CDROM | id, 1); } else { - ui_sb_update_icon_state(SB_CDROM|id, 0); + ui_sb_update_icon_state(SB_CDROM | id, 0); } - //media_menu_update_cdrom(id); - ui_sb_update_tip(SB_CDROM|id); + // media_menu_update_cdrom(id); + ui_sb_update_tip(SB_CDROM | id); } diff --git a/src/qt/qt_d3d9renderer.cpp b/src/qt/qt_d3d9renderer.cpp new file mode 100644 index 000000000..868f58274 --- /dev/null +++ b/src/qt/qt_d3d9renderer.cpp @@ -0,0 +1,200 @@ +#include "qt_mainwindow.hpp" +#include "qt_d3d9renderer.hpp" +#include +#include + +extern "C" { +#include <86box/86box.h> +#include <86box/video.h> +} + +D3D9Renderer::D3D9Renderer(QWidget *parent, int monitor_index) + : QWidget { parent } + , RendererCommon() +{ + QPalette pal = palette(); + pal.setColor(QPalette::Window, Qt::black); + setAutoFillBackground(true); + setPalette(pal); + + setAttribute(Qt::WA_NativeWindow); + setAttribute(Qt::WA_PaintOnScreen); + setAttribute(Qt::WA_NoSystemBackground); + setAttribute(Qt::WA_OpaquePaintEvent); + + windowHandle = (HWND) winId(); + surfaceInUse = true; + finalized = true; + + RendererCommon::parentWidget = parent; + + this->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding); + this->m_monitor_index = monitor_index; + + d3d9surface = nullptr; + d3d9dev = nullptr; + d3d9 = nullptr; +} + +D3D9Renderer::~D3D9Renderer() +{ + finalize(); +} + +void +D3D9Renderer::finalize() +{ + if (!finalized) { + while (surfaceInUse) { } + finalized = true; + } + surfaceInUse = true; + if (d3d9surface) { + d3d9surface->Release(); + d3d9surface = nullptr; + } + if (d3d9dev) { + d3d9dev->Release(); + d3d9dev = nullptr; + } + if (d3d9) { + d3d9->Release(); + d3d9 = nullptr; + } +} + +void +D3D9Renderer::hideEvent(QHideEvent *event) +{ + finalize(); +} + +void +D3D9Renderer::showEvent(QShowEvent *event) +{ + if (d3d9) finalize(); + params = {}; + + if (FAILED(Direct3DCreate9Ex(D3D_SDK_VERSION, &d3d9))) { + return error("Failed to create Direct3D 9 context"); + } + + params.Windowed = true; + params.SwapEffect = D3DSWAPEFFECT_FLIPEX; + params.BackBufferWidth = width() * devicePixelRatioF(); + params.BackBufferHeight = height() * devicePixelRatioF(); + params.BackBufferCount = 1; + params.FullScreen_RefreshRateInHz = D3DPRESENT_RATE_DEFAULT; + params.PresentationInterval = D3DPRESENT_INTERVAL_IMMEDIATE; + params.hDeviceWindow = (HWND) winId(); + + HRESULT result = d3d9->CreateDeviceEx(D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, windowHandle, D3DCREATE_MULTITHREADED | D3DCREATE_HARDWARE_VERTEXPROCESSING, ¶ms, nullptr, &d3d9dev); + if (FAILED(result)) + result = d3d9->CreateDeviceEx(D3DADAPTER_DEFAULT, D3DDEVTYPE_REF, windowHandle, D3DCREATE_MULTITHREADED | D3DCREATE_SOFTWARE_VERTEXPROCESSING, ¶ms, nullptr, &d3d9dev); + if (FAILED(result)) { + return error("Failed to create Direct3D 9 device"); + } + + result = d3d9dev->CreateOffscreenPlainSurface(2048, 2048, D3DFMT_A8R8G8B8, D3DPOOL_DEFAULT, &d3d9surface, nullptr); + if (FAILED(result)) + result = d3d9dev->CreateOffscreenPlainSurface(1024, 1024, D3DFMT_A8R8G8B8, D3DPOOL_DEFAULT, &d3d9surface, nullptr); + if (FAILED(result)) { + return error("Failed to create Direct3D 9 surface"); + } + if (!alreadyInitialized) { + emit initialized(); + alreadyInitialized = true; + } + surfaceInUse = false; + finalized = false; +} + +void +D3D9Renderer::paintEvent(QPaintEvent *event) +{ + IDirect3DSurface9 *backbuffer = nullptr; + RECT srcRect; + RECT dstRect; + HRESULT result = d3d9dev->GetBackBuffer(0, 0, D3DBACKBUFFER_TYPE_MONO, &backbuffer); + + if (FAILED(result)) { + return; + } + + srcRect.top = source.top(); + srcRect.bottom = source.bottom(); + srcRect.left = source.left(); + srcRect.right = source.right(); + dstRect.top = destination.top() * devicePixelRatioF(); + dstRect.bottom = destination.bottom() * devicePixelRatioF(); + dstRect.left = destination.left() * devicePixelRatioF(); + dstRect.right = destination.right() * devicePixelRatioF(); + d3d9dev->BeginScene(); + d3d9dev->Clear(0, nullptr, D3DCLEAR_TARGET, 0xFF000000, 0, 0); + while (surfaceInUse) { } + surfaceInUse = true; + d3d9dev->StretchRect(d3d9surface, &srcRect, backbuffer, &dstRect, video_filter_method == 0 ? D3DTEXF_POINT : D3DTEXF_LINEAR); + result = d3d9dev->EndScene(); + surfaceInUse = false; + if (SUCCEEDED(result)) { + if (FAILED(d3d9dev->PresentEx(nullptr, nullptr, 0, nullptr, 0))) { + finalize(); + showEvent(nullptr); + } + } +} + +bool +D3D9Renderer::event(QEvent *event) +{ + bool res = false; + if (!eventDelegate(event, res)) + return QWidget::event(event); + return res; +} + +void +D3D9Renderer::resizeEvent(QResizeEvent *event) +{ + onResize(event->size().width() * devicePixelRatioF(), event->size().height() * devicePixelRatioF()); + + params.BackBufferWidth = event->size().width() * devicePixelRatioF(); + params.BackBufferHeight = event->size().height() * devicePixelRatioF(); + if (d3d9dev) + d3d9dev->Reset(¶ms); + QWidget::resizeEvent(event); +} + +void +D3D9Renderer::blit(int x, int y, int w, int h) +{ + if (blitDummied || (x < 0) || (y < 0) || (w <= 0) || (h <= 0) || (w > 2048) || (h > 2048) || (monitors[m_monitor_index].target_buffer == NULL) || surfaceInUse) { + video_blit_complete_monitor(m_monitor_index); + return; + } + surfaceInUse = true; + auto origSource = source; + source.setRect(x, y, w, h); + RECT srcRect; + D3DLOCKED_RECT lockRect; + srcRect.top = source.top(); + srcRect.bottom = source.bottom(); + srcRect.left = source.left(); + srcRect.right = source.right(); + + if (monitors[m_monitor_index].mon_screenshots) { + video_screenshot_monitor((uint32_t *) &(monitors[m_monitor_index].target_buffer->line[y][x]), 0, 0, 2048, m_monitor_index); + } + if (SUCCEEDED(d3d9surface->LockRect(&lockRect, &srcRect, 0))) { + for (int y1 = 0; y1 < h; y1++) { + video_copy(((uint8_t *) lockRect.pBits) + (y1 * lockRect.Pitch), &(monitors[m_monitor_index].target_buffer->line[y + y1][x]), w * 4); + } + video_blit_complete_monitor(m_monitor_index); + d3d9surface->UnlockRect(); + } else + video_blit_complete_monitor(m_monitor_index); + if (origSource != source) + onResize(this->width() * devicePixelRatioF(), this->height() * devicePixelRatioF()); + surfaceInUse = false; + QTimer::singleShot(0, this, [this] { this->update(); }); +} diff --git a/src/qt/qt_d3d9renderer.hpp b/src/qt/qt_d3d9renderer.hpp new file mode 100644 index 000000000..37c27443b --- /dev/null +++ b/src/qt/qt_d3d9renderer.hpp @@ -0,0 +1,45 @@ +#ifndef D3D9RENDERER_HPP +#define D3D9RENDERER_HPP + +#include +#include "qt_renderercommon.hpp" + +#include +#include +#include + +class D3D9Renderer : public QWidget, public RendererCommon { + Q_OBJECT +public: + explicit D3D9Renderer(QWidget *parent = nullptr, int monitor_index = 0); + ~D3D9Renderer(); + bool hasBlitFunc() override { return true; } + void blit(int x, int y, int w, int h) override; + void finalize() override; + +protected: + void showEvent(QShowEvent *event) override; + void hideEvent(QHideEvent *event) override; + void resizeEvent(QResizeEvent *event) override; + void paintEvent(QPaintEvent *event) override; + bool event(QEvent *event) override; + QPaintEngine *paintEngine() const override { return nullptr; } + +signals: + void initialized(); + void error(QString); + +private: + HWND windowHandle = 0; + D3DPRESENT_PARAMETERS params {}; + IDirect3D9Ex *d3d9 = nullptr; + IDirect3DDevice9Ex *d3d9dev = nullptr; + IDirect3DSurface9 *d3d9surface = nullptr; + + std::atomic surfaceInUse { false }; + std::atomic finalized { false }; + bool alreadyInitialized = false; + int m_monitor_index = 0; +}; + +#endif // D3D9RENDERER_HPP diff --git a/src/qt/qt_deviceconfig.cpp b/src/qt/qt_deviceconfig.cpp index ac967f678..6c7db0f3d 100644 --- a/src/qt/qt_deviceconfig.cpp +++ b/src/qt/qt_deviceconfig.cpp @@ -1,20 +1,20 @@ /* - * 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. + * 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. + * This file is part of the 86Box distribution. * - * Device configuration UI code. + * Device configuration UI code. * * * - * Authors: Joakim L. Gilje + * Authors: Joakim L. Gilje * Cacodemon345 * - * Copyright 2021 Joakim L. Gilje - * Copyright 2022 Cacodemon345 + * Copyright 2021 Joakim L. Gilje + * Copyright 2022 Cacodemon345 */ #include "qt_deviceconfig.hpp" #include "ui_qt_deviceconfig.h" @@ -25,20 +25,35 @@ #include #include #include +#include +#include +#include +#include +#include extern "C" { #include <86box/86box.h> +#include <86box/ini.h> #include <86box/config.h> #include <86box/device.h> #include <86box/midi_rtmidi.h> +#include <86box/mem.h> +#include <86box/rom.h> } #include "qt_filefield.hpp" #include "qt_models_common.hpp" +#ifdef Q_OS_LINUX +# include +# include +#endif +#ifdef Q_OS_WINDOWS +#include +#endif -DeviceConfig::DeviceConfig(QWidget *parent) : - QDialog(parent), - ui(new Ui::DeviceConfig) +DeviceConfig::DeviceConfig(QWidget *parent) + : QDialog(parent) + , ui(new Ui::DeviceConfig) { ui->setupUi(this); } @@ -48,120 +63,234 @@ DeviceConfig::~DeviceConfig() delete ui; } -void DeviceConfig::ConfigureDevice(const _device_* device, int instance, Settings* settings) { +static QStringList +EnumerateSerialDevices() +{ + QStringList serialDevices; + QStringList ttyEntries; + QByteArray devstr(1024, 0); +#ifdef Q_OS_LINUX + QDir class_dir("/sys/class/tty/"); + QDir dev_dir("/dev/"); + ttyEntries = class_dir.entryList(QDir::Dirs | QDir::NoDotAndDotDot | QDir::System, QDir::SortFlag::Name); + for (int i = 0; i < ttyEntries.size(); i++) { + if (class_dir.exists(ttyEntries[i] + "/device/driver/") && dev_dir.exists(ttyEntries[i]) + && QFileInfo(dev_dir.canonicalPath() + '/' + ttyEntries[i]).isReadable() + && QFileInfo(dev_dir.canonicalPath() + '/' + ttyEntries[i]).isWritable()) { + serialDevices.push_back("/dev/" + ttyEntries[i]); + } + } +#endif +#ifdef Q_OS_WINDOWS + for (int i = 1; i < 256; i++) { + devstr[0] = 0; + snprintf(devstr.data(), 1024, "\\\\.\\COM%d", i); + auto handle = CreateFileA(devstr.data(), GENERIC_READ | GENERIC_WRITE, 0, nullptr, OPEN_EXISTING, 0, 0); + auto dwError = GetLastError(); + if (handle != INVALID_HANDLE_VALUE || (handle == INVALID_HANDLE_VALUE && ((dwError == ERROR_ACCESS_DENIED) || (dwError == ERROR_GEN_FAILURE) || (dwError == ERROR_SHARING_VIOLATION) || (dwError == ERROR_SEM_TIMEOUT)))) { + if (handle != INVALID_HANDLE_VALUE) CloseHandle(handle); + serialDevices.push_back(QString(devstr)); + } + } +#endif +#ifdef Q_OS_MACOS + QDir dev_dir("/dev/"); + dev_dir.setNameFilters({ "tty.*", "cu.*" }); + QDir::Filters serial_dev_flags = QDir::Files | QDir::NoSymLinks | QDir::Readable | QDir::Writable | QDir::NoDotAndDotDot | QDir::System; + for (const auto &device : dev_dir.entryInfoList(serial_dev_flags, QDir::SortFlag::Name)) { + serialDevices.push_back(device.canonicalFilePath()); + } +#endif + return serialDevices; +} + +void +DeviceConfig::ConfigureDevice(const _device_ *device, int instance, Settings *settings) +{ DeviceConfig dc(settings); dc.setWindowTitle(QString("%1 Device Configuration").arg(device->name)); + int p; + int q; device_context_t device_context; device_set_context(&device_context, device, instance); - const auto* config = device->config; + auto device_label = new QLabel(device->name); + dc.ui->formLayout->addRow(device_label); + auto line = new QFrame; + line->setFrameShape(QFrame::HLine); + line->setFrameShadow(QFrame::Sunken); + dc.ui->formLayout->addRow(line); + const auto *config = device->config; while (config->type != -1) { switch (config->type) { - case CONFIG_BINARY: - { - auto value = config_get_int(device_context.name, const_cast(config->name), config->default_int); - auto* cbox = new QCheckBox(); - cbox->setObjectName(config->name); - cbox->setChecked(value > 0); - dc.ui->formLayout->addRow(config->description, cbox); - break; - } - case CONFIG_MIDI: - { - auto* cbox = new QComboBox(); - cbox->setObjectName(config->name); - auto* model = cbox->model(); - int currentIndex = -1; - int selected = config_get_int(device_context.name, const_cast(config->name), config->default_int); - for (int i = 0; i < rtmidi_get_num_devs(); i++) { - char midiName[512] = { 0 }; - rtmidi_get_dev_name(i, midiName); - - Models::AddEntry(model, midiName, i); - if (selected == i) { - currentIndex = i; + case CONFIG_BINARY: + { + auto value = config_get_int(device_context.name, const_cast(config->name), config->default_int); + auto *cbox = new QCheckBox(); + cbox->setObjectName(config->name); + cbox->setChecked(value > 0); + dc.ui->formLayout->addRow(config->description, cbox); + break; } - } - dc.ui->formLayout->addRow(config->description, cbox); - cbox->setCurrentIndex(currentIndex); - break; - } - case CONFIG_MIDI_IN: - { - auto* cbox = new QComboBox(); - cbox->setObjectName(config->name); - auto* model = cbox->model(); - int currentIndex = -1; - int selected = config_get_int(device_context.name, const_cast(config->name), config->default_int); - for (int i = 0; i < rtmidi_in_get_num_devs(); i++) { - char midiName[512] = { 0 }; - rtmidi_in_get_dev_name(i, midiName); +#ifdef USE_RTMIDI + case CONFIG_MIDI_OUT: + { + auto *cbox = new QComboBox(); + cbox->setObjectName(config->name); + cbox->setMaxVisibleItems(30); + auto *model = cbox->model(); + int currentIndex = -1; + int selected = config_get_int(device_context.name, const_cast(config->name), config->default_int); + for (int i = 0; i < rtmidi_out_get_num_devs(); i++) { + char midiName[512] = { 0 }; + rtmidi_out_get_dev_name(i, midiName); - Models::AddEntry(model, midiName, i); - if (selected == i) { - currentIndex = i; + Models::AddEntry(model, midiName, i); + if (selected == i) { + currentIndex = i; + } + } + dc.ui->formLayout->addRow(config->description, cbox); + cbox->setCurrentIndex(currentIndex); + break; } - } - dc.ui->formLayout->addRow(config->description, cbox); - cbox->setCurrentIndex(currentIndex); - break; - } - case CONFIG_SELECTION: - case CONFIG_HEX16: - case CONFIG_HEX20: - { - auto* cbox = new QComboBox(); - cbox->setObjectName(config->name); - auto* model = cbox->model(); - int currentIndex = -1; - int selected; - switch (config->type) { + case CONFIG_MIDI_IN: + { + auto *cbox = new QComboBox(); + cbox->setObjectName(config->name); + cbox->setMaxVisibleItems(30); + auto *model = cbox->model(); + int currentIndex = -1; + int selected = config_get_int(device_context.name, const_cast(config->name), config->default_int); + for (int i = 0; i < rtmidi_in_get_num_devs(); i++) { + char midiName[512] = { 0 }; + rtmidi_in_get_dev_name(i, midiName); + + Models::AddEntry(model, midiName, i); + if (selected == i) { + currentIndex = i; + } + } + dc.ui->formLayout->addRow(config->description, cbox); + cbox->setCurrentIndex(currentIndex); + break; + } +#endif case CONFIG_SELECTION: - selected = config_get_int(device_context.name, const_cast(config->name), config->default_int); - break; case CONFIG_HEX16: - selected = config_get_hex16(device_context.name, const_cast(config->name), config->default_int); - break; case CONFIG_HEX20: - selected = config_get_hex20(device_context.name, const_cast(config->name), config->default_int); - break; - } + { + auto *cbox = new QComboBox(); + cbox->setObjectName(config->name); + cbox->setMaxVisibleItems(30); + auto *model = cbox->model(); + int currentIndex = -1; + int selected = 0; + switch (config->type) { + case CONFIG_SELECTION: + selected = config_get_int(device_context.name, const_cast(config->name), config->default_int); + break; + case CONFIG_HEX16: + selected = config_get_hex16(device_context.name, const_cast(config->name), config->default_int); + break; + case CONFIG_HEX20: + selected = config_get_hex20(device_context.name, const_cast(config->name), config->default_int); + break; + } - for (auto* sel = config->selection; (sel->description != nullptr) && (strlen(sel->description) > 0); ++sel) { - int row = Models::AddEntry(model, sel->description, sel->value); - if (selected == sel->value) { - currentIndex = row; + for (auto *sel = config->selection; (sel != nullptr) && (sel->description != nullptr) && (strlen(sel->description) > 0); ++sel) { + int row = Models::AddEntry(model, sel->description, sel->value); + if (selected == sel->value) { + currentIndex = row; + } + } + dc.ui->formLayout->addRow(config->description, cbox); + cbox->setCurrentIndex(currentIndex); + break; + } + case CONFIG_BIOS: + { + auto *cbox = new QComboBox(); + cbox->setObjectName(config->name); + cbox->setMaxVisibleItems(30); + auto *model = cbox->model(); + int currentIndex = -1; + char *selected; + selected = config_get_string(device_context.name, const_cast(config->name), const_cast(config->default_string)); + + q = 0; + for (auto *bios = config->bios; (bios != nullptr) && (bios->name != nullptr) && (strlen(bios->name) > 0); ++bios) { + p = 0; + for (int d = 0; d < bios->files_no; d++) + p += !!rom_present(const_cast(bios->files[d])); + if (p == bios->files_no) { + int row = Models::AddEntry(model, bios->name, q); + if (!strcmp(selected, bios->internal_name)) { + currentIndex = row; + } + } + q++; + } + dc.ui->formLayout->addRow(config->description, cbox); + cbox->setCurrentIndex(currentIndex); + break; + } + case CONFIG_SPINNER: + { + int value = config_get_int(device_context.name, const_cast(config->name), config->default_int); + auto *spinBox = new QSpinBox(); + spinBox->setObjectName(config->name); + spinBox->setMaximum(config->spinner.max); + spinBox->setMinimum(config->spinner.min); + if (config->spinner.step > 0) { + spinBox->setSingleStep(config->spinner.step); + } + spinBox->setValue(value); + dc.ui->formLayout->addRow(config->description, spinBox); + break; + } + case CONFIG_FNAME: + { + auto *fileName = config_get_string(device_context.name, const_cast(config->name), const_cast(config->default_string)); + auto *fileField = new FileField(); + fileField->setObjectName(config->name); + fileField->setFileName(fileName); + fileField->setFilter(QString(config->file_filter).left(strcspn(config->file_filter, "|"))); + dc.ui->formLayout->addRow(config->description, fileField); + break; + } + case CONFIG_STRING: + { + auto lineEdit = new QLineEdit; + lineEdit->setObjectName(config->name); + lineEdit->setCursor(Qt::IBeamCursor); + lineEdit->setText(config_get_string(device_context.name, const_cast(config->name), const_cast(config->default_string))); + dc.ui->formLayout->addRow(config->description, lineEdit); + break; + } + case CONFIG_SERPORT: + { + auto *cbox = new QComboBox(); + cbox->setObjectName(config->name); + cbox->setMaxVisibleItems(30); + auto *model = cbox->model(); + int currentIndex = 0; + auto serialDevices = EnumerateSerialDevices(); + char *selected = config_get_string(device_context.name, const_cast(config->name), const_cast(config->default_string)); + + Models::AddEntry(model, "None", -1); + for (int i = 0; i < serialDevices.size(); i++) { + int row = Models::AddEntry(model, serialDevices[i], i); + if (selected == serialDevices[i]) { + currentIndex = row; + } + } + + dc.ui->formLayout->addRow(config->description, cbox); + cbox->setCurrentIndex(currentIndex); + break; } - } - dc.ui->formLayout->addRow(config->description, cbox); - cbox->setCurrentIndex(currentIndex); - break; - } - case CONFIG_SPINNER: - { - int value = config_get_int(device_context.name, const_cast(config->name), config->default_int); - auto* spinBox = new QSpinBox(); - spinBox->setObjectName(config->name); - spinBox->setMaximum(config->spinner.max); - spinBox->setMinimum(config->spinner.min); - if (config->spinner.step > 0) { - spinBox->setSingleStep(config->spinner.step); - } - spinBox->setValue(value); - dc.ui->formLayout->addRow(config->description, spinBox); - break; - } - case CONFIG_FNAME: - { - auto* fileName = config_get_string(device_context.name, const_cast(config->name), const_cast(config->default_string)); - auto* fileField = new FileField(); - fileField->setObjectName(config->name); - fileField->setFileName(fileName); - fileField->setFilter(QString(config->file_filter).left(strcspn(config->file_filter, "|"))); - dc.ui->formLayout->addRow(config->description, fileField); - break; - } } ++config; } @@ -172,52 +301,76 @@ void DeviceConfig::ConfigureDevice(const _device_* device, int instance, Setting config = device->config; while (config->type != -1) { switch (config->type) { - case CONFIG_BINARY: - { - auto* cbox = dc.findChild(config->name); - config_set_int(device_context.name, const_cast(config->name), cbox->isChecked() ? 1 : 0); - break; - } - case CONFIG_MIDI: - case CONFIG_MIDI_IN: - case CONFIG_SELECTION: - { - auto* cbox = dc.findChild(config->name); - config_set_int(device_context.name, const_cast(config->name), cbox->currentData().toInt()); - break; - } - case CONFIG_HEX16: - { - auto* cbox = dc.findChild(config->name); - config_set_hex16(device_context.name, const_cast(config->name), cbox->currentData().toInt()); - break; - } - case CONFIG_HEX20: - { - auto* cbox = dc.findChild(config->name); - config_set_hex20(device_context.name, const_cast(config->name), cbox->currentData().toInt()); - break; - } - case CONFIG_FNAME: - { - auto* fbox = dc.findChild(config->name); - auto fileName = fbox->fileName().toUtf8(); - config_set_string(device_context.name, const_cast(config->name), fileName.data()); - break; - } - case CONFIG_SPINNER: - { - auto* spinBox = dc.findChild(config->name); - config_set_int(device_context.name, const_cast(config->name), spinBox->value()); - break; - } + case CONFIG_BINARY: + { + auto *cbox = dc.findChild(config->name); + config_set_int(device_context.name, const_cast(config->name), cbox->isChecked() ? 1 : 0); + break; + } + case CONFIG_MIDI_OUT: + case CONFIG_MIDI_IN: + case CONFIG_SELECTION: + { + auto *cbox = dc.findChild(config->name); + config_set_int(device_context.name, const_cast(config->name), cbox->currentData().toInt()); + break; + } + case CONFIG_BIOS: + { + auto *cbox = dc.findChild(config->name); + int idx = cbox->currentData().toInt(); + config_set_string(device_context.name, const_cast(config->name), const_cast(config->bios[idx].internal_name)); + break; + } + case CONFIG_SERPORT: + { + auto *cbox = dc.findChild(config->name); + auto path = cbox->currentText().toUtf8(); + if (path == "None") + path = ""; + config_set_string(device_context.name, const_cast(config->name), path); + break; + } + case CONFIG_STRING: + { + auto *lineEdit = dc.findChild(config->name); + config_set_string(device_context.name, const_cast(config->name), lineEdit->text().toUtf8()); + break; + } + case CONFIG_HEX16: + { + auto *cbox = dc.findChild(config->name); + config_set_hex16(device_context.name, const_cast(config->name), cbox->currentData().toInt()); + break; + } + case CONFIG_HEX20: + { + auto *cbox = dc.findChild(config->name); + config_set_hex20(device_context.name, const_cast(config->name), cbox->currentData().toInt()); + break; + } + case CONFIG_FNAME: + { + auto *fbox = dc.findChild(config->name); + auto fileName = fbox->fileName().toUtf8(); + config_set_string(device_context.name, const_cast(config->name), fileName.data()); + break; + } + case CONFIG_SPINNER: + { + auto *spinBox = dc.findChild(config->name); + config_set_int(device_context.name, const_cast(config->name), spinBox->value()); + break; + } } config++; } } } -QString DeviceConfig::DeviceName(const _device_* device, const char *internalName, int bus) { +QString +DeviceConfig::DeviceName(const _device_ *device, const char *internalName, int bus) +{ if (QStringLiteral("none") == internalName) { return tr("None"); } else if (QStringLiteral("internal") == internalName) { diff --git a/src/qt/qt_deviceconfig.hpp b/src/qt/qt_deviceconfig.hpp index 2662df11c..1ed24d618 100644 --- a/src/qt/qt_deviceconfig.hpp +++ b/src/qt/qt_deviceconfig.hpp @@ -15,16 +15,16 @@ class DeviceConfig; class Settings; -class DeviceConfig : public QDialog -{ +class DeviceConfig : public QDialog { Q_OBJECT public: explicit DeviceConfig(QWidget *parent = nullptr); ~DeviceConfig(); - static void ConfigureDevice(const _device_* device, int instance = 0, Settings* settings = nullptr); - static QString DeviceName(const _device_* device, const char* internalName, int bus); + static void ConfigureDevice(const _device_ *device, int instance = 0, Settings *settings = nullptr); + static QString DeviceName(const _device_ *device, const char *internalName, int bus); + private: Ui::DeviceConfig *ui; }; diff --git a/src/qt/qt_filefield.cpp b/src/qt/qt_filefield.cpp index 0639ad0fc..9272e31a1 100644 --- a/src/qt/qt_filefield.cpp +++ b/src/qt/qt_filefield.cpp @@ -1,36 +1,42 @@ /* - * 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. + * 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. + * This file is part of the 86Box distribution. * - * File field widget. + * File field widget. * * * - * Authors: Joakim L. Gilje + * Authors: Joakim L. Gilje * Cacodemon345 * - * Copyright 2021 Joakim L. Gilje - * Copyright 2022 Cacodemon345 + * Copyright 2021 Joakim L. Gilje + * Copyright 2022 Cacodemon345 */ #include "qt_filefield.hpp" #include "ui_qt_filefield.h" #include -FileField::FileField(QWidget *parent) : - QWidget(parent), - ui(new Ui::FileField) +FileField::FileField(QWidget *parent) + : QWidget(parent) + , ui(new Ui::FileField) { ui->setupUi(this); - connect(ui->label, &QLineEdit::editingFinished, this, [this] () { + connect(ui->label, &QLineEdit::editingFinished, this, [this]() { fileName_ = ui->label->text(); - emit fileSelected(ui->label->text()); + emit fileSelected(ui->label->text(), true); }); + + connect(ui->label, &QLineEdit::textChanged, this, [this]() { + fileName_ = ui->label->text(); + emit fileTextEntered(ui->label->text(), true); + }); + this->setFixedWidth(this->sizeHint().width() + ui->pushButton->sizeHint().width()); } @@ -39,12 +45,16 @@ FileField::~FileField() delete ui; } -void FileField::setFileName(const QString &fileName) { +void +FileField::setFileName(const QString &fileName) +{ fileName_ = fileName; ui->label->setText(fileName); } -void FileField::on_pushButton_clicked() { +void +FileField::on_pushButton_clicked() +{ QString fileName; if (createFile_) { fileName = QFileDialog::getSaveFileName(this, QString(), QString(), filter_, &selectedFilter_); diff --git a/src/qt/qt_filefield.hpp b/src/qt/qt_filefield.hpp index 00c4a5e12..e3569fd31 100644 --- a/src/qt/qt_filefield.hpp +++ b/src/qt/qt_filefield.hpp @@ -7,8 +7,7 @@ namespace Ui { class FileField; } -class FileField : public QWidget -{ +class FileField : public QWidget { Q_OBJECT public: @@ -16,26 +15,28 @@ public: ~FileField(); QString fileName() const { return fileName_; } - void setFileName(const QString& fileName); + void setFileName(const QString &fileName); - void setFilter(const QString& filter) { filter_ = filter; } + void setFilter(const QString &filter) { filter_ = filter; } QString selectedFilter() const { return selectedFilter_; } + void setselectedFilter(const QString &selectedFilter) { selectedFilter_ = selectedFilter; } void setCreateFile(bool createFile) { createFile_ = createFile; } bool createFile() { return createFile_; } signals: - void fileSelected(const QString& fileName); + void fileSelected(const QString &fileName, bool precheck = false); + void fileTextEntered(const QString &fileName, bool precheck = false); private slots: void on_pushButton_clicked(); private: Ui::FileField *ui; - QString fileName_; - QString selectedFilter_; - QString filter_; - bool createFile_ = false; + QString fileName_; + QString selectedFilter_; + QString filter_; + bool createFile_ = false; }; #endif // QT_FILEFIELD_HPP diff --git a/src/qt/qt_harddiskdialog.cpp b/src/qt/qt_harddiskdialog.cpp index 3e933ddab..5dab101b8 100644 --- a/src/qt/qt_harddiskdialog.cpp +++ b/src/qt/qt_harddiskdialog.cpp @@ -1,20 +1,20 @@ /* - * 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. + * 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. + * This file is part of the 86Box distribution. * - * Hard disk dialog code. + * Hard disk dialog code. * * * - * Authors: Joakim L. Gilje + * Authors: Joakim L. Gilje * Cacodemon345 * - * Copyright 2021 Joakim L. Gilje - * Copyright 2022 Cacodemon345 + * Copyright 2021 Joakim L. Gilje + * Copyright 2022 Cacodemon345 */ #include "qt_harddiskdialog.hpp" #include "ui_qt_harddiskdialog.h" @@ -23,7 +23,6 @@ extern "C" { #include <86box/86box.h> #include <86box/hdd.h> #include "../disk/minivhd/minivhd.h" -#include "../disk/minivhd/minivhd_util.h" } #include @@ -38,37 +37,20 @@ extern "C" { #include #include #include +#include #include "qt_harddrive_common.hpp" #include "qt_settings_bus_tracking.hpp" #include "qt_models_common.hpp" #include "qt_util.hpp" -HarddiskDialog::HarddiskDialog(bool existing, QWidget *parent) : - QDialog(parent), - ui(new Ui::HarddiskDialog) +HarddiskDialog::HarddiskDialog(bool existing, QWidget *parent) + : QDialog(parent) + , ui(new Ui::HarddiskDialog) { ui->setupUi(this); - ui->fileField->setFilter(tr("Hard disk images") % util::DlgFilter({ "hd?","im?","vhd" }) % tr("All files") % util::DlgFilter({ "*" }, true)); - if (existing) { - setWindowTitle(tr("Add Existing Hard Disk")); - ui->lineEditCylinders->setEnabled(false); - ui->lineEditHeads->setEnabled(false); - ui->lineEditSectors->setEnabled(false); - ui->lineEditSize->setEnabled(false); - ui->comboBoxType->setEnabled(false); - - ui->comboBoxFormat->hide(); - ui->labelFormat->hide(); - - connect(ui->fileField, &FileField::fileSelected, this, &HarddiskDialog::onExistingFileSelected); - } else { - setWindowTitle(tr("Add New Hard Disk")); - ui->fileField->setCreateFile(true); - } - - auto* model = ui->comboBoxFormat->model(); + auto *model = ui->comboBoxFormat->model(); model->insertRows(0, 6); model->setData(model->index(0, 0), tr("Raw image (.img)")); model->setData(model->index(1, 0), tr("HDI image (.hdi)")); @@ -90,10 +72,10 @@ HarddiskDialog::HarddiskDialog(bool existing, QWidget *parent) : model = ui->comboBoxType->model(); for (int i = 0; i < 127; i++) { - uint64_t size = ((uint64_t) hdd_table[i][0]) * hdd_table[i][1] * hdd_table[i][2]; + uint64_t size = ((uint64_t) hdd_table[i][0]) * hdd_table[i][1] * hdd_table[i][2]; uint32_t size_mb = size >> 11LL; - //QString text = QString("%1 MiB (CHS: %2, %3, %4)").arg(size_mb).arg(hdd_table[i][0]).arg(hdd_table[i][1]).arg(hdd_table[i][2]); - QString text = QString::asprintf(tr("%u MB (CHS: %i, %i, %i)").toUtf8().constData(), (size_mb), (hdd_table[i][0]), (hdd_table[i][1]), (hdd_table[i][2])); + // QString text = QString("%1 MiB (CHS: %2, %3, %4)").arg(size_mb).arg(hdd_table[i][0]).arg(hdd_table[i][1]).arg(hdd_table[i][2]); + QString text = QString::asprintf(tr("%u MB (CHS: %i, %i, %i)").toUtf8().constData(), size_mb, (hdd_table[i][0]), (hdd_table[i][1]), (hdd_table[i][2])); Models::AddEntry(model, text, i); } Models::AddEntry(model, tr("Custom..."), 127); @@ -101,9 +83,50 @@ HarddiskDialog::HarddiskDialog(bool existing, QWidget *parent) : ui->lineEditSize->setValidator(new QIntValidator()); ui->buttonBox->button(QDialogButtonBox::Ok)->setEnabled(false); - if (!existing) connect(ui->fileField, &FileField::fileSelected, this, [this] { - ui->buttonBox->button(QDialogButtonBox::Ok)->setEnabled(true); - }); + + filters = QStringList({ tr("Raw image") % util::DlgFilter({ "img" }, true), + tr("HDI image") % util::DlgFilter({ "hdi" }, true), + tr("HDX image") % util::DlgFilter({ "hdx" }, true), + tr("Fixed-size VHD") % util::DlgFilter({ "vhd" }, true), + tr("Dynamic-size VHD") % util::DlgFilter({ "vhd" }, true), + tr("Differencing VHD") % util::DlgFilter({ "vhd" }, true) }); + + if (existing) { + ui->fileField->setFilter(tr("Hard disk images") % util::DlgFilter({ "hd?", "im?", "vhd" }) % tr("All files") % util::DlgFilter({ "*" }, true)); + + setWindowTitle(tr("Add Existing Hard Disk")); + ui->lineEditCylinders->setEnabled(false); + ui->lineEditHeads->setEnabled(false); + ui->lineEditSectors->setEnabled(false); + ui->lineEditSize->setEnabled(false); + ui->comboBoxType->setEnabled(false); + + ui->comboBoxFormat->hide(); + ui->labelFormat->hide(); + + connect(ui->fileField, &FileField::fileSelected, this, &HarddiskDialog::onExistingFileSelected); + } else { + ui->fileField->setFilter(filters.join(";;")); + + setWindowTitle(tr("Add New Hard Disk")); + ui->fileField->setCreateFile(true); + + // Enable the OK button as long as the filename length is non-zero + connect(ui->fileField, &FileField::fileTextEntered, this, [this] { + ui->buttonBox->button(QDialogButtonBox::Ok)->setEnabled((this->fileName().length() > 0)); + }); + + connect(ui->fileField, &FileField::fileSelected, this, [this] { + int filter = filters.indexOf(ui->fileField->selectedFilter()); + if (filter > -1) + ui->comboBoxFormat->setCurrentIndex(filter); + ui->buttonBox->button(QDialogButtonBox::Ok)->setEnabled(true); + }); + // Set the default format to Dynamic-size VHD. Do it last after everything is set up + // so the currentIndexChanged signal can do what is needed + ui->comboBoxFormat->setCurrentIndex(DEFAULT_DISK_FORMAT); + ui->fileField->setselectedFilter(filters.value(DEFAULT_DISK_FORMAT)); + } } HarddiskDialog::~HarddiskDialog() @@ -111,19 +134,33 @@ HarddiskDialog::~HarddiskDialog() delete ui; } -uint8_t HarddiskDialog::bus() const { +uint8_t +HarddiskDialog::bus() const +{ return static_cast(ui->comboBoxBus->currentData().toUInt()); } -uint8_t HarddiskDialog::channel() const { +uint8_t +HarddiskDialog::channel() const +{ return static_cast(ui->comboBoxChannel->currentData().toUInt()); } -QString HarddiskDialog::fileName() const { +QString +HarddiskDialog::fileName() const +{ return ui->fileField->fileName(); } -void HarddiskDialog::on_comboBoxFormat_currentIndexChanged(int index) { +uint32_t +HarddiskDialog::speed() const +{ + return static_cast(ui->comboBoxSpeed->currentData().toUInt()); +} + +void +HarddiskDialog::on_comboBoxFormat_currentIndexChanged(int index) +{ bool enabled; if (index == 5) { /* They switched to a diff VHD; disable the geometry fields. */ enabled = false; @@ -151,6 +188,7 @@ void HarddiskDialog::on_comboBoxFormat_currentIndexChanged(int index) { ui->comboBoxBlockSize->show(); ui->labelBlockSize->show(); } + ui->fileField->setselectedFilter(filters.value(index)); } /* If the disk geometry requested in the 86Box GUI is not compatible with the internal VHD geometry, @@ -158,12 +196,13 @@ void HarddiskDialog::on_comboBoxFormat_currentIndexChanged(int index) { * of about 21 MB, and should only be necessary for VHDs larger than 31.5 GB, so should never be more * than a tenth of a percent change in size. */ -static void adjust_86box_geometry_for_vhd(MVHDGeom *_86box_geometry, MVHDGeom *vhd_geometry) +static void +adjust_86box_geometry_for_vhd(MVHDGeom *_86box_geometry, MVHDGeom *vhd_geometry) { if (_86box_geometry->cyl <= 65535) { - vhd_geometry->cyl = _86box_geometry->cyl; + vhd_geometry->cyl = _86box_geometry->cyl; vhd_geometry->heads = _86box_geometry->heads; - vhd_geometry->spt = _86box_geometry->spt; + vhd_geometry->spt = _86box_geometry->spt; return; } @@ -175,33 +214,35 @@ static void adjust_86box_geometry_for_vhd(MVHDGeom *_86box_geometry, MVHDGeom *v if (remainder > 0) desired_sectors += (85680 - remainder); - _86box_geometry->cyl = desired_sectors / (16 * 63); + _86box_geometry->cyl = desired_sectors / (16 * 63); _86box_geometry->heads = 16; - _86box_geometry->spt = 63; + _86box_geometry->spt = 63; - vhd_geometry->cyl = desired_sectors / (16 * 255); + vhd_geometry->cyl = desired_sectors / (16 * 255); vhd_geometry->heads = 16; - vhd_geometry->spt = 255; + vhd_geometry->spt = 255; } -static HarddiskDialog* callbackPtr = nullptr; -static MVHDGeom create_drive_vhd_fixed(const QString& fileName, HarddiskDialog* p, uint16_t cyl, uint8_t heads, uint8_t spt) { +static HarddiskDialog *callbackPtr = nullptr; +static MVHDGeom +create_drive_vhd_fixed(const QString &fileName, HarddiskDialog *p, uint16_t cyl, uint8_t heads, uint8_t spt) +{ MVHDGeom _86box_geometry = { .cyl = cyl, .heads = heads, .spt = spt }; MVHDGeom vhd_geometry; adjust_86box_geometry_for_vhd(&_86box_geometry, &vhd_geometry); - int vhd_error = 0; + int vhd_error = 0; QByteArray filenameBytes = fileName.toUtf8(); - callbackPtr = p; - MVHDMeta *vhd = mvhd_create_fixed(filenameBytes.data(), vhd_geometry, &vhd_error, [](uint32_t current_sector, uint32_t total_sectors) { + callbackPtr = p; + MVHDMeta *vhd = mvhd_create_fixed(filenameBytes.data(), vhd_geometry, &vhd_error, [](uint32_t current_sector, uint32_t total_sectors) { callbackPtr->fileProgress((current_sector * 100) / total_sectors); }); - callbackPtr = nullptr; + callbackPtr = nullptr; if (vhd == NULL) { - _86box_geometry.cyl = 0; + _86box_geometry.cyl = 0; _86box_geometry.heads = 0; - _86box_geometry.spt = 0; + _86box_geometry.spt = 0; } else { mvhd_close(vhd); } @@ -209,24 +250,26 @@ static MVHDGeom create_drive_vhd_fixed(const QString& fileName, HarddiskDialog* return _86box_geometry; } -static MVHDGeom create_drive_vhd_dynamic(const QString& fileName, uint16_t cyl, uint8_t heads, uint8_t spt, int blocksize) { +static MVHDGeom +create_drive_vhd_dynamic(const QString &fileName, uint16_t cyl, uint8_t heads, uint8_t spt, int blocksize) +{ MVHDGeom _86box_geometry = { .cyl = cyl, .heads = heads, .spt = spt }; MVHDGeom vhd_geometry; adjust_86box_geometry_for_vhd(&_86box_geometry, &vhd_geometry); - int vhd_error = 0; - QByteArray filenameBytes = fileName.toUtf8(); + int vhd_error = 0; + QByteArray filenameBytes = fileName.toUtf8(); MVHDCreationOptions options; options.block_size_in_sectors = blocksize; - options.path = filenameBytes.data(); - options.size_in_bytes = 0; - options.geometry = vhd_geometry; - options.type = MVHD_TYPE_DYNAMIC; + options.path = filenameBytes.data(); + options.size_in_bytes = 0; + options.geometry = vhd_geometry; + options.type = MVHD_TYPE_DYNAMIC; MVHDMeta *vhd = mvhd_create_ex(options, &vhd_error); if (vhd == NULL) { - _86box_geometry.cyl = 0; + _86box_geometry.cyl = 0; _86box_geometry.heads = 0; - _86box_geometry.spt = 0; + _86box_geometry.spt = 0; } else { mvhd_close(vhd); } @@ -234,29 +277,31 @@ static MVHDGeom create_drive_vhd_dynamic(const QString& fileName, uint16_t cyl, return _86box_geometry; } -static MVHDGeom create_drive_vhd_diff(const QString& fileName, const QString& parentFileName, int blocksize) { - int vhd_error = 0; - QByteArray filenameBytes = fileName.toUtf8(); - QByteArray parentFilenameBytes = fileName.toUtf8(); +static MVHDGeom +create_drive_vhd_diff(const QString &fileName, const QString &parentFileName, int blocksize) +{ + int vhd_error = 0; + QByteArray filenameBytes = fileName.toUtf8(); + QByteArray parentFilenameBytes = parentFileName.toUtf8(); MVHDCreationOptions options; options.block_size_in_sectors = blocksize; - options.path = filenameBytes.data(); - options.parent_path = parentFilenameBytes.data(); - options.type = MVHD_TYPE_DIFF; + options.path = filenameBytes.data(); + options.parent_path = parentFilenameBytes.data(); + options.type = MVHD_TYPE_DIFF; MVHDMeta *vhd = mvhd_create_ex(options, &vhd_error); - MVHDGeom vhd_geometry; + MVHDGeom vhd_geometry; if (vhd == NULL) { - vhd_geometry.cyl = 0; + vhd_geometry.cyl = 0; vhd_geometry.heads = 0; - vhd_geometry.spt = 0; + vhd_geometry.spt = 0; } else { vhd_geometry = mvhd_get_geometry(vhd); if (vhd_geometry.spt > 63) { - vhd_geometry.cyl = mvhd_calc_size_sectors(&vhd_geometry) / (16 * 63); + vhd_geometry.cyl = mvhd_calc_size_sectors(&vhd_geometry) / (16 * 63); vhd_geometry.heads = 16; - vhd_geometry.spt = 63; + vhd_geometry.spt = 63; } mvhd_close(vhd); @@ -265,130 +310,128 @@ static MVHDGeom create_drive_vhd_diff(const QString& fileName, const QString& pa return vhd_geometry; } -void HarddiskDialog::onCreateNewFile() { +void +HarddiskDialog::onCreateNewFile() +{ - for (auto& curObject : children()) - { - if (qobject_cast(curObject)) qobject_cast(curObject)->setDisabled(true); + for (auto &curObject : children()) { + if (qobject_cast(curObject)) + qobject_cast(curObject)->setDisabled(true); } ui->progressBar->setEnabled(true); setResult(QDialog::Rejected); - qint64 size = ui->lineEditSize->text().toUInt() << 20U; - if (size > 0x1FFFFFFE00ll) { + uint32_t sector_size = 512; + quint64 size = (static_cast(cylinders_) * static_cast(heads_) * static_cast(sectors_) * static_cast(sector_size)); + if (size > 0x1FFFFFFE00LL) { QMessageBox::critical(this, tr("Disk image too large"), tr("Disk images cannot be larger than 127 GB.")); return; } - int img_format = ui->comboBoxFormat->currentIndex(); - uint32_t zero = 0; - uint32_t base = 0x1000; - uint32_t sector_size = 512; + int img_format = ui->comboBoxFormat->currentIndex(); + uint32_t zero = 0; + uint32_t base = 0x1000; - auto fileName = ui->fileField->fileName(); + auto fileName = ui->fileField->fileName(); QString expectedSuffix; switch (img_format) { - case 1: - expectedSuffix = "hdi"; - break; - case 2: - expectedSuffix = "hdx"; - break; - case 3: - case 4: - case 5: - expectedSuffix = "vhd"; - break; + case IMG_FMT_HDI: + expectedSuffix = "hdi"; + break; + case IMG_FMT_HDX: + expectedSuffix = "hdx"; + break; + case IMG_FMT_VHD_FIXED: + case IMG_FMT_VHD_DYNAMIC: + case IMG_FMT_VHD_DIFF: + expectedSuffix = "vhd"; + break; } - if (! expectedSuffix.isEmpty()) { + if (!expectedSuffix.isEmpty()) { QFileInfo fileInfo(fileName); if (fileInfo.suffix().compare(expectedSuffix, Qt::CaseInsensitive) != 0) { fileName = QString("%1.%2").arg(fileName, expectedSuffix); ui->fileField->setFileName(fileName); } } + QFileInfo fi(fileName); + fileName = (fi.isRelative() && !fi.filePath().isEmpty()) ? usr_path + fi.filePath() : fi.filePath(); + ui->fileField->setFileName(fileName); QFile file(fileName); - if (! file.open(QIODevice::WriteOnly)) { + if (!file.open(QIODevice::WriteOnly)) { QMessageBox::critical(this, tr("Unable to write file"), tr("Make sure the file is being saved to a writable directory.")); return; } - if (img_format == 1) { /* HDI file */ + if (img_format == IMG_FMT_HDI) { /* HDI file */ QDataStream stream(&file); stream.setByteOrder(QDataStream::LittleEndian); - if (size >= 0x100000000ll) { + if (size >= 0x100000000LL) { QMessageBox::critical(this, tr("Disk image too large"), tr("HDI disk images cannot be larger than 4 GB.")); return; } uint32_t s = static_cast(size); - stream << zero; /* 00000000: Zero/unknown */ - stream << zero; /* 00000004: Zero/unknown */ - stream << base; /* 00000008: Offset at which data starts */ - stream << s; /* 0000000C: Full size of the data (32-bit) */ - stream << sector_size; /* 00000010: Sector size in bytes */ - stream << sectors_; /* 00000014: Sectors per cylinder */ - stream << heads_; /* 00000018: Heads per cylinder */ - stream << cylinders_; /* 0000001C: Cylinders */ + stream << zero; /* 00000000: Zero/unknown */ + stream << zero; /* 00000004: Zero/unknown */ + stream << base; /* 00000008: Offset at which data starts */ + stream << s; /* 0000000C: Full size of the data (32-bit) */ + stream << sector_size; /* 00000010: Sector size in bytes */ + stream << sectors_; /* 00000014: Sectors per cylinder */ + stream << heads_; /* 00000018: Heads per cylinder */ + stream << cylinders_; /* 0000001C: Cylinders */ for (int i = 0; i < 0x3f8; i++) { stream << zero; } - } else if (img_format == 2) { /* HDX file */ + } else if (img_format == IMG_FMT_HDX) { /* HDX file */ QDataStream stream(&file); stream.setByteOrder(QDataStream::LittleEndian); quint64 signature = 0xD778A82044445459; - stream << signature; /* 00000000: Signature */ - stream << size; /* 00000008: Full size of the data (64-bit) */ - stream << sector_size; /* 00000010: Sector size in bytes */ - stream << sectors_; /* 00000014: Sectors per cylinder */ - stream << heads_; /* 00000018: Heads per cylinder */ - stream << cylinders_; /* 0000001C: Cylinders */ - stream << zero; /* 00000020: [Translation] Sectors per cylinder */ - stream << zero; /* 00000004: [Translation] Heads per cylinder */ - } else if (img_format >= 3) { /* VHD file */ + stream << signature; /* 00000000: Signature */ + stream << size; /* 00000008: Full size of the data (64-bit) */ + stream << sector_size; /* 00000010: Sector size in bytes */ + stream << sectors_; /* 00000014: Sectors per cylinder */ + stream << heads_; /* 00000018: Heads per cylinder */ + stream << cylinders_; /* 0000001C: Cylinders */ + stream << zero; /* 00000020: [Translation] Sectors per cylinder */ + stream << zero; /* 00000004: [Translation] Heads per cylinder */ + } else if (img_format >= IMG_FMT_VHD_FIXED) { /* VHD file */ file.close(); - MVHDGeom _86box_geometry{}; - int block_size = ui->comboBoxBlockSize->currentIndex() == 0 ? MVHD_BLOCK_LARGE : MVHD_BLOCK_SMALL; + MVHDGeom _86box_geometry {}; + int block_size = ui->comboBoxBlockSize->currentIndex() == 0 ? MVHD_BLOCK_LARGE : MVHD_BLOCK_SMALL; switch (img_format) { - case 3: - { - connect(this, &HarddiskDialog::fileProgress, this, [this] (int value) { ui->progressBar->setValue(value); QApplication::processEvents(); } ); - ui->progressBar->setVisible(true); - [&_86box_geometry, fileName, this] { - _86box_geometry = create_drive_vhd_fixed(fileName, this, cylinders_, heads_, sectors_); - }(); - } - break; - case 4: - _86box_geometry = create_drive_vhd_dynamic(fileName, cylinders_, heads_, sectors_, block_size); - break; - case 5: - QString vhdParent = QFileDialog::getOpenFileName( - this, - tr("Select the parent VHD"), - QString(), - tr("VHD files") % - util::DlgFilter({ "vhd" }) % - tr("All files") % - util::DlgFilter({ "*" }, true)); + case IMG_FMT_VHD_FIXED: + { + connect(this, &HarddiskDialog::fileProgress, this, [this](int value) { ui->progressBar->setValue(value); QApplication::processEvents(); }); + ui->progressBar->setVisible(true); + [&_86box_geometry, fileName, this] { + _86box_geometry = create_drive_vhd_fixed(fileName, this, cylinders_, heads_, sectors_); + }(); + } + break; + case IMG_FMT_VHD_DYNAMIC: + _86box_geometry = create_drive_vhd_dynamic(fileName, cylinders_, heads_, sectors_, block_size); + break; + case IMG_FMT_VHD_DIFF: + QString vhdParent = QFileDialog::getOpenFileName( + this, + tr("Select the parent VHD"), + QString(), + tr("VHD files") % util::DlgFilter({ "vhd" }) % tr("All files") % util::DlgFilter({ "*" }, true)); - if (vhdParent.isEmpty()) { - return; - } - _86box_geometry = create_drive_vhd_diff(fileName, vhdParent, block_size); - break; + if (vhdParent.isEmpty()) { + return; + } + _86box_geometry = create_drive_vhd_diff(fileName, vhdParent, block_size); + break; } - if (_86box_geometry.cyl == 0 && - _86box_geometry.heads == 0 && - _86box_geometry.spt == 0) - { + if (_86box_geometry.cyl == 0 && _86box_geometry.heads == 0 && _86box_geometry.spt == 0) { QMessageBox::critical(this, tr("Unable to write file"), tr("Make sure the file is being saved to a writable directory.")); return; - } - else if (img_format != 5) { + } else if (img_format != IMG_FMT_VHD_DIFF) { QMessageBox::information(this, tr("Disk image created"), tr("Remember to partition and format the newly-created drive.")); } @@ -396,23 +439,23 @@ void HarddiskDialog::onCreateNewFile() { ui->lineEditHeads->setText(QString::number(_86box_geometry.heads)); ui->lineEditSectors->setText(QString::number(_86box_geometry.spt)); cylinders_ = _86box_geometry.cyl; - heads_ = _86box_geometry.heads; - sectors_ = _86box_geometry.spt; + heads_ = _86box_geometry.heads; + sectors_ = _86box_geometry.spt; setResult(QDialog::Accepted); return; } // formats 0, 1 and 2 - connect(this, &HarddiskDialog::fileProgress, this, [this] (int value) { ui->progressBar->setValue(value); QApplication::processEvents(); } ); + connect(this, &HarddiskDialog::fileProgress, this, [this](int value) { ui->progressBar->setValue(value); QApplication::processEvents(); }); ui->progressBar->setVisible(true); [size, &file, this] { QDataStream stream(&file); stream.setByteOrder(QDataStream::LittleEndian); QByteArray buf(1048576, 0); - uint64_t mibBlocks = size >> 20; - uint64_t restBlock = size & 0xfffff; + uint64_t mibBlocks = size >> 20; + uint64_t restBlock = size & 0xfffff; if (restBlock) { stream.writeRawData(buf.data(), restBlock); @@ -431,7 +474,9 @@ void HarddiskDialog::onCreateNewFile() { setResult(QDialog::Accepted); } -static void adjust_vhd_geometry_for_86box(MVHDGeom *vhd_geometry) { +static void +adjust_vhd_geometry_for_86box(MVHDGeom *vhd_geometry) +{ if (vhd_geometry->spt <= 63) return; @@ -443,17 +488,17 @@ static void adjust_vhd_geometry_for_86box(MVHDGeom *vhd_geometry) { if (remainder > 0) desired_sectors -= remainder; - vhd_geometry->cyl = desired_sectors / (16 * 63); + vhd_geometry->cyl = desired_sectors / (16 * 63); vhd_geometry->heads = 16; - vhd_geometry->spt = 63; + vhd_geometry->spt = 63; } -void HarddiskDialog::recalcSelection() { +void +HarddiskDialog::recalcSelection() +{ int selection = 127; for (int i = 0; i < 127; i++) { - if ((cylinders_ == hdd_table[i][0]) && - (heads_ == hdd_table[i][1]) && - (sectors_ == hdd_table[i][2])) + if ((cylinders_ == hdd_table[i][0]) && (heads_ == hdd_table[i][1]) && (sectors_ == hdd_table[i][2])) selection = i; } if ((selection == 127) && (heads_ == 16) && (sectors_ == 63)) { @@ -462,38 +507,44 @@ void HarddiskDialog::recalcSelection() { ui->comboBoxType->setCurrentIndex(selection); } -void HarddiskDialog::onExistingFileSelected(const QString &fileName) { +void +HarddiskDialog::onExistingFileSelected(const QString &fileName, bool precheck) +{ // TODO : Over to non-existing file selected - /* +#if 0 if (!(existing & 1)) { - f = _wfopen(wopenfilestring, L"rb"); - if (f != NULL) { - fclose(f); + fp = _wfopen(wopenfilestring, L"rb"); + if (fp != NULL) { + fclose(fp); if (settings_msgbox_ex(MBX_QUESTION_YN, (wchar_t *) IDS_4111, (wchar_t *) IDS_4118, (wchar_t *) IDS_4120, (wchar_t *) IDS_4121, NULL) != 0) / * yes * / return FALSE; } } - f = _wfopen(wopenfilestring, (existing & 1) ? L"rb" : L"wb"); - if (f == NULL) { + fp = _wfopen(wopenfilestring, (existing & 1) ? L"rb" : L"wb"); + if (fp == NULL) { hdd_add_file_open_error: - fclose(f); + fclose(fp); settings_msgbox_header(MBX_ERROR, (existing & 1) ? (wchar_t *) IDS_4114 : (wchar_t *) IDS_4115, (existing & 1) ? (wchar_t *) IDS_4107 : (wchar_t *) IDS_4108); return TRUE; } - */ +#endif - uint64_t size = 0; + uint64_t size = 0; uint32_t sector_size = 0; - uint32_t sectors = 0; - uint32_t heads = 0; - uint32_t cylinders = 0; - int vhd_error = 0; + uint32_t sectors = 0; + uint32_t heads = 0; + uint32_t cylinders = 0; + int vhd_error = 0; ui->buttonBox->button(QDialogButtonBox::Ok)->setEnabled(false); QFile file(fileName); - if (! file.open(QIODevice::ReadOnly)) { - QMessageBox::critical(this, tr("Unable to read file"), tr("Make sure the file exists and is readable.")); + if (!file.open(QIODevice::ReadOnly)) { + // No message box during precheck (performed when the file input loses focus and this function is called) + // If precheck is false, the file has been chosen from a file dialog and the alert should display. + if(!precheck) { + QMessageBox::critical(this, tr("Unable to read file"), tr("Make sure the file exists and is readable.")); + } return; } QByteArray fileNameUtf8 = fileName.toUtf8(); @@ -514,7 +565,7 @@ void HarddiskDialog::onExistingFileSelected(const QString &fileName) { stream >> heads; stream >> cylinders; } else if (image_is_vhd(fileNameUtf8.data(), 1)) { - MVHDMeta* vhd = mvhd_open(fileNameUtf8.data(), 0, &vhd_error); + MVHDMeta *vhd = mvhd_open(fileNameUtf8.data(), 0, &vhd_error); if (vhd == nullptr) { QMessageBox::critical(this, tr("Unable to read file"), tr("Make sure the file exists and is readable")); return; @@ -536,9 +587,9 @@ void HarddiskDialog::onExistingFileSelected(const QString &fileName) { MVHDGeom vhd_geom = mvhd_get_geometry(vhd); adjust_vhd_geometry_for_86box(&vhd_geom); cylinders = vhd_geom.cyl; - heads = vhd_geom.heads; - sectors = vhd_geom.spt; - size = static_cast(cylinders * heads * sectors * 512); + heads = vhd_geom.heads; + sectors = vhd_geom.spt; + size = static_cast(cylinders * heads * sectors * 512); mvhd_close(vhd); } else { size = file.size(); @@ -549,7 +600,7 @@ void HarddiskDialog::onExistingFileSelected(const QString &fileName) { else if (((size % 3072) == 0) && (size <= 53477376)) heads = 6; else { - int i; + uint32_t i; for (i = 5; i < 16; i++) { if (((size % (i << 9)) == 0) && (size <= ((i * 17) << 19))) break; @@ -560,7 +611,7 @@ void HarddiskDialog::onExistingFileSelected(const QString &fileName) { } } else { sectors = 63; - heads = 16; + heads = 16; } cylinders = ((size >> 9) / heads) / sectors; @@ -571,8 +622,8 @@ void HarddiskDialog::onExistingFileSelected(const QString &fileName) { return; } - heads_ = heads; - sectors_ = sectors; + heads_ = heads; + sectors_ = sectors; cylinders_ = cylinders; ui->lineEditCylinders->setText(QString::number(cylinders)); ui->lineEditHeads->setText(QString::number(heads)); @@ -588,12 +639,18 @@ void HarddiskDialog::onExistingFileSelected(const QString &fileName) { ui->buttonBox->button(QDialogButtonBox::Ok)->setEnabled(true); } -void HarddiskDialog::recalcSize() { +void +HarddiskDialog::recalcSize() +{ + if (disallowSizeModifications) + return; uint64_t size = (static_cast(cylinders_) * static_cast(heads_) * static_cast(sectors_)) << 9; ui->lineEditSize->setText(QString::number(size >> 20)); } -bool HarddiskDialog::checkAndAdjustSectors() { +bool +HarddiskDialog::checkAndAdjustSectors() +{ if (sectors_ > max_sectors) { sectors_ = max_sectors; ui->lineEditSectors->setText(QString::number(max_sectors)); @@ -604,7 +661,9 @@ bool HarddiskDialog::checkAndAdjustSectors() { return true; } -bool HarddiskDialog::checkAndAdjustHeads() { +bool +HarddiskDialog::checkAndAdjustHeads() +{ if (heads_ > max_heads) { heads_ = max_heads; ui->lineEditHeads->setText(QString::number(max_heads)); @@ -615,7 +674,9 @@ bool HarddiskDialog::checkAndAdjustHeads() { return true; } -bool HarddiskDialog::checkAndAdjustCylinders() { +bool +HarddiskDialog::checkAndAdjustCylinders() +{ if (cylinders_ > max_cylinders) { cylinders_ = max_cylinders; ui->lineEditCylinders->setText(QString::number(max_cylinders)); @@ -626,44 +687,45 @@ bool HarddiskDialog::checkAndAdjustCylinders() { return true; } - -void HarddiskDialog::on_comboBoxBus_currentIndexChanged(int index) { +void +HarddiskDialog::on_comboBoxBus_currentIndexChanged(int index) +{ int chanIdx = 0; if (index < 0) { return; } switch (ui->comboBoxBus->currentData().toInt()) { - case HDD_BUS_DISABLED: - default: - max_sectors = max_heads = max_cylinders = 0; - break; - case HDD_BUS_MFM: - max_sectors = 26; /* 17 for MFM, 26 for RLL. */ - max_heads = 15; - max_cylinders = 2047; - break; - case HDD_BUS_XTA: - max_sectors = 63; - max_heads = 16; - max_cylinders = 1023; - break; - case HDD_BUS_ESDI: - max_sectors = 99; /* ESDI drives usually had 32 to 43 sectors per track. */ - max_heads = 16; - max_cylinders = 266305; - break; - case HDD_BUS_IDE: - max_sectors = 63; - max_heads = 255; - max_cylinders = 266305; - break; - case HDD_BUS_ATAPI: - case HDD_BUS_SCSI: - max_sectors = 99; - max_heads = 255; - max_cylinders = 266305; - break; + case HDD_BUS_DISABLED: + default: + max_sectors = max_heads = max_cylinders = 0; + break; + case HDD_BUS_MFM: + max_sectors = 26; /* 17 for MFM, 26 for RLL. */ + max_heads = 15; + max_cylinders = 2047; + break; + case HDD_BUS_XTA: + max_sectors = 63; + max_heads = 16; + max_cylinders = 1023; + break; + case HDD_BUS_ESDI: + max_sectors = 99; /* ESDI drives usually had 32 to 43 sectors per track. */ + max_heads = 16; + max_cylinders = 266305; + break; + case HDD_BUS_IDE: + max_sectors = 255; + max_heads = 255; + max_cylinders = 266305; + break; + case HDD_BUS_ATAPI: + case HDD_BUS_SCSI: + max_sectors = 255; + max_heads = 255; + max_cylinders = 266305; + break; } checkAndAdjustCylinders(); @@ -685,8 +747,9 @@ void HarddiskDialog::on_comboBoxBus_currentIndexChanged(int index) { ui->lineEditSectors->setValidator(new QIntValidator(1, max_sectors, this)); Harddrives::populateBusChannels(ui->comboBoxChannel->model(), ui->comboBoxBus->currentData().toInt()); - switch (ui->comboBoxBus->currentData().toInt()) - { + Harddrives::populateSpeeds(ui->comboBoxSpeed->model(), ui->comboBoxBus->currentData().toInt()); + + switch (ui->comboBoxBus->currentData().toInt()) { case HDD_BUS_MFM: chanIdx = (Harddrives::busTrackClass->next_free_mfm_channel()); break; @@ -705,11 +768,16 @@ void HarddiskDialog::on_comboBoxBus_currentIndexChanged(int index) { break; } + if (chanIdx == 0xFF) + chanIdx = 0; ui->comboBoxChannel->setCurrentIndex(chanIdx); } -void HarddiskDialog::on_lineEditSize_textEdited(const QString &text) { - uint32_t size = text.toUInt(); +void +HarddiskDialog::on_lineEditSize_textEdited(const QString &text) +{ + disallowSizeModifications = true; + uint32_t size = text.toUInt(); /* This is needed to ensure VHD standard compliance. */ hdd_image_calc_chs(&cylinders_, &heads_, §ors_, size); ui->lineEditCylinders->setText(QString::number(cylinders_)); @@ -720,9 +788,13 @@ void HarddiskDialog::on_lineEditSize_textEdited(const QString &text) { checkAndAdjustCylinders(); checkAndAdjustHeads(); checkAndAdjustSectors(); + + disallowSizeModifications = false; } -void HarddiskDialog::on_lineEditCylinders_textEdited(const QString &text) { +void +HarddiskDialog::on_lineEditCylinders_textEdited(const QString &text) +{ cylinders_ = text.toUInt(); if (checkAndAdjustCylinders()) { recalcSize(); @@ -730,7 +802,9 @@ void HarddiskDialog::on_lineEditCylinders_textEdited(const QString &text) { } } -void HarddiskDialog::on_lineEditHeads_textEdited(const QString &text) { +void +HarddiskDialog::on_lineEditHeads_textEdited(const QString &text) +{ heads_ = text.toUInt(); if (checkAndAdjustHeads()) { recalcSize(); @@ -738,7 +812,9 @@ void HarddiskDialog::on_lineEditHeads_textEdited(const QString &text) { } } -void HarddiskDialog::on_lineEditSectors_textEdited(const QString &text) { +void +HarddiskDialog::on_lineEditSectors_textEdited(const QString &text) +{ sectors_ = text.toUInt(); if (checkAndAdjustSectors()) { recalcSize(); @@ -746,21 +822,23 @@ void HarddiskDialog::on_lineEditSectors_textEdited(const QString &text) { } } -void HarddiskDialog::on_comboBoxType_currentIndexChanged(int index) { +void +HarddiskDialog::on_comboBoxType_currentIndexChanged(int index) +{ if (index < 0) { return; } if ((index != 127) && (index != 128)) { cylinders_ = hdd_table[index][0]; - heads_ = hdd_table[index][1]; - sectors_ = hdd_table[index][2]; + heads_ = hdd_table[index][1]; + sectors_ = hdd_table[index][2]; ui->lineEditCylinders->setText(QString::number(cylinders_)); ui->lineEditHeads->setText(QString::number(heads_)); ui->lineEditSectors->setText(QString::number(sectors_)); recalcSize(); } else if (index == 128) { - heads_ = 16; + heads_ = 16; sectors_ = 63; ui->lineEditHeads->setText(QString::number(heads_)); ui->lineEditSectors->setText(QString::number(sectors_)); @@ -772,9 +850,12 @@ void HarddiskDialog::on_comboBoxType_currentIndexChanged(int index) { checkAndAdjustSectors(); } -void HarddiskDialog::accept() +void +HarddiskDialog::accept() { - if (ui->fileField->createFile()) onCreateNewFile(); - else setResult(QDialog::Accepted); + if (ui->fileField->createFile()) + onCreateNewFile(); + else + setResult(QDialog::Accepted); QDialog::done(result()); } diff --git a/src/qt/qt_harddiskdialog.hpp b/src/qt/qt_harddiskdialog.hpp index 321dc4708..9de61c51b 100644 --- a/src/qt/qt_harddiskdialog.hpp +++ b/src/qt/qt_harddiskdialog.hpp @@ -7,20 +7,20 @@ namespace Ui { class HarddiskDialog; } -class HarddiskDialog : public QDialog -{ +class HarddiskDialog : public QDialog { Q_OBJECT public: explicit HarddiskDialog(bool existing, QWidget *parent = nullptr); ~HarddiskDialog(); - uint8_t bus() const; - uint8_t channel() const; - QString fileName() const; + uint8_t bus() const; + uint8_t channel() const; + QString fileName() const; uint32_t cylinders() const { return cylinders_; } uint32_t heads() const { return heads_; } uint32_t sectors() const { return sectors_; } + uint32_t speed() const; signals: void fileProgress(int i); @@ -37,7 +37,8 @@ private slots: void on_comboBoxBus_currentIndexChanged(int index); void on_comboBoxFormat_currentIndexChanged(int index); void onCreateNewFile(); - void onExistingFileSelected(const QString& fileName); + void onExistingFileSelected(const QString &fileName, bool precheck); + private: Ui::HarddiskDialog *ui; @@ -45,10 +46,17 @@ private: uint32_t heads_; uint32_t sectors_; - uint32_t max_sectors = 0; - uint32_t max_heads = 0; + uint32_t max_sectors = 0; + uint32_t max_heads = 0; uint32_t max_cylinders = 0; + bool disallowSizeModifications = false; + + QStringList filters; + // "Dynamic-size VHD" is number 4 in the `filters` list and the + // comboBoxFormat model + const uint8_t DEFAULT_DISK_FORMAT = 4; + bool checkAndAdjustCylinders(); bool checkAndAdjustHeads(); bool checkAndAdjustSectors(); diff --git a/src/qt/qt_harddiskdialog.ui b/src/qt/qt_harddiskdialog.ui index 823652aa6..91499d2cb 100644 --- a/src/qt/qt_harddiskdialog.ui +++ b/src/qt/qt_harddiskdialog.ui @@ -42,6 +42,20 @@ + + + + Speed: + + + + + + + 30 + + + @@ -96,7 +110,11 @@ - + + + 30 + + @@ -162,7 +180,11 @@ - + + + 30 + + @@ -172,10 +194,18 @@ - + + + 30 + + - + + + 30 + + @@ -197,7 +227,11 @@ - + + + 30 + + diff --git a/src/qt/qt_harddrive_common.cpp b/src/qt/qt_harddrive_common.cpp index fa08f7f2c..dda36917f 100644 --- a/src/qt/qt_harddrive_common.cpp +++ b/src/qt/qt_harddrive_common.cpp @@ -1,18 +1,18 @@ /* - * 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. + * 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. + * This file is part of the 86Box distribution. * - * Common storage devices module. + * Common storage devices module. * * * - * Authors: Joakim L. Gilje + * Authors: Joakim L. Gilje * - * Copyright 2021 Joakim L. Gilje + * Copyright 2021 Joakim L. Gilje */ #include "qt_harddrive_common.hpp" @@ -20,15 +20,18 @@ extern "C" { #include <86box/hdd.h> +#include <86box/cdrom.h> } #include -void Harddrives::populateBuses(QAbstractItemModel *model) { +void +Harddrives::populateBuses(QAbstractItemModel *model) +{ model->removeRows(0, model->rowCount()); model->insertRows(0, 6); model->setData(model->index(0, 0), "MFM/RLL"); - model->setData(model->index(1, 0), "XT IDE"); + model->setData(model->index(1, 0), "XTA"); model->setData(model->index(2, 0), "ESDI"); model->setData(model->index(3, 0), "IDE"); model->setData(model->index(4, 0), "ATAPI"); @@ -42,41 +45,81 @@ void Harddrives::populateBuses(QAbstractItemModel *model) { model->setData(model->index(5, 0), HDD_BUS_SCSI, Qt::UserRole); } -void Harddrives::populateRemovableBuses(QAbstractItemModel *model) { +void +Harddrives::populateRemovableBuses(QAbstractItemModel *model) +{ model->removeRows(0, model->rowCount()); +#if 0 + model->insertRows(0, 4); +#else model->insertRows(0, 3); +#endif model->setData(model->index(0, 0), QObject::tr("Disabled")); model->setData(model->index(1, 0), QObject::tr("ATAPI")); model->setData(model->index(2, 0), QObject::tr("SCSI")); +#if 0 + model->setData(model->index(3, 0), QObject::tr("Mitsumi")); +#endif model->setData(model->index(0, 0), HDD_BUS_DISABLED, Qt::UserRole); model->setData(model->index(1, 0), HDD_BUS_ATAPI, Qt::UserRole); model->setData(model->index(2, 0), HDD_BUS_SCSI, Qt::UserRole); +#if 0 + model->setData(model->index(3, 0), CDROM_BUS_MITSUMI, Qt::UserRole); +#endif } -void Harddrives::populateBusChannels(QAbstractItemModel *model, int bus) { +void +Harddrives::populateSpeeds(QAbstractItemModel *model, int bus) +{ + int num_preset; + + switch (bus) { + case HDD_BUS_ESDI: + case HDD_BUS_IDE: + case HDD_BUS_ATAPI: + case HDD_BUS_SCSI: + num_preset = hdd_preset_get_num(); + break; + + default: + num_preset = 1; + } + + model->removeRows(0, model->rowCount()); + model->insertRows(0, num_preset); + + for (int i = 0; i < num_preset; i++) { + model->setData(model->index(i, 0), QObject::tr(hdd_preset_getname(i))); + model->setData(model->index(i, 0), i, Qt::UserRole); + } +} + +void +Harddrives::populateBusChannels(QAbstractItemModel *model, int bus) +{ model->removeRows(0, model->rowCount()); - int busRows = 0; - int shifter = 1; - int orer = 1; + int busRows = 0; + int shifter = 1; + int orer = 1; int subChannelWidth = 1; switch (bus) { - case HDD_BUS_MFM: - case HDD_BUS_XTA: - case HDD_BUS_ESDI: - busRows = 2; - break; - case HDD_BUS_IDE: - case HDD_BUS_ATAPI: - busRows = 8; - break; - case HDD_BUS_SCSI: - shifter = 4; - orer = 15; - busRows = 64; - subChannelWidth = 2; - break; + case HDD_BUS_MFM: + case HDD_BUS_XTA: + case HDD_BUS_ESDI: + busRows = 2; + break; + case HDD_BUS_IDE: + case HDD_BUS_ATAPI: + busRows = 8; + break; + case HDD_BUS_SCSI: + shifter = 4; + orer = 15; + busRows = 64; + subChannelWidth = 2; + break; } model->insertRows(0, busRows); @@ -87,30 +130,35 @@ void Harddrives::populateBusChannels(QAbstractItemModel *model, int bus) { } } -QString Harddrives::BusChannelName(uint8_t bus, uint8_t channel) { +QString +Harddrives::BusChannelName(uint8_t bus, uint8_t channel) +{ QString busName; - switch(bus) { - case HDD_BUS_DISABLED: - busName = QString(QObject::tr("Disabled")); - break; - case HDD_BUS_MFM: - busName = QString("MFM/RLL (%1:%2)").arg(channel >> 1).arg(channel & 1); - break; - case HDD_BUS_XTA: - busName = QString("XT IDE (%1:%2)").arg(channel >> 1).arg(channel & 1); - break; - case HDD_BUS_ESDI: - busName = QString("ESDI (%1:%2)").arg(channel >> 1).arg(channel & 1); - break; - case HDD_BUS_IDE: - busName = QString("IDE (%1:%2)").arg(channel >> 1).arg(channel & 1); - break; - case HDD_BUS_ATAPI: - busName = QString("ATAPI (%1:%2)").arg(channel >> 1).arg(channel & 1); - break; - case HDD_BUS_SCSI: - busName = QString("SCSI (%1:%2)").arg(channel >> 4).arg(channel & 15, 2, 10, QChar('0')); - break; + switch (bus) { + case HDD_BUS_DISABLED: + busName = QString(QObject::tr("Disabled")); + break; + case HDD_BUS_MFM: + busName = QString("MFM/RLL (%1:%2)").arg(channel >> 1).arg(channel & 1); + break; + case HDD_BUS_XTA: + busName = QString("XTA (%1:%2)").arg(channel >> 1).arg(channel & 1); + break; + case HDD_BUS_ESDI: + busName = QString("ESDI (%1:%2)").arg(channel >> 1).arg(channel & 1); + break; + case HDD_BUS_IDE: + busName = QString("IDE (%1:%2)").arg(channel >> 1).arg(channel & 1); + break; + case HDD_BUS_ATAPI: + busName = QString("ATAPI (%1:%2)").arg(channel >> 1).arg(channel & 1); + break; + case HDD_BUS_SCSI: + busName = QString("SCSI (%1:%2)").arg(channel >> 4).arg(channel & 15, 2, 10, QChar('0')); + break; + case CDROM_BUS_MITSUMI: + busName = QString("Mitsumi"); + break; } return busName; diff --git a/src/qt/qt_harddrive_common.hpp b/src/qt/qt_harddrive_common.hpp index 5d4bbc9e0..2aca184b3 100644 --- a/src/qt/qt_harddrive_common.hpp +++ b/src/qt/qt_harddrive_common.hpp @@ -7,9 +7,10 @@ class QAbstractItemModel; class SettingsBusTracking; namespace Harddrives { - void populateBuses(QAbstractItemModel* model); - void populateRemovableBuses(QAbstractItemModel* model); - void populateBusChannels(QAbstractItemModel* model, int bus); - QString BusChannelName(uint8_t bus, uint8_t channel); - inline SettingsBusTracking* busTrackClass = nullptr; +void populateBuses(QAbstractItemModel *model); +void populateRemovableBuses(QAbstractItemModel *model); +void populateBusChannels(QAbstractItemModel *model, int bus); +void populateSpeeds(QAbstractItemModel *model, int bus); +QString BusChannelName(uint8_t bus, uint8_t channel); +inline SettingsBusTracking *busTrackClass = nullptr; }; diff --git a/src/qt/qt_hardwarerenderer.cpp b/src/qt/qt_hardwarerenderer.cpp index e4d2b4900..47f0de718 100644 --- a/src/qt/qt_hardwarerenderer.cpp +++ b/src/qt/qt_hardwarerenderer.cpp @@ -1,27 +1,30 @@ /* - * 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. + * 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. + * This file is part of the 86Box distribution. * - * Hardware renderer module. + * Hardware renderer module. * * * - * Authors: Joakim L. Gilje + * Authors: Joakim L. Gilje * Cacodemon345 * Teemu Korhonen * - * Copyright 2021 Joakim L. Gilje - * Copyright 2021-2022 Cacodemon345 - * Copyright 2021-2022 Teemu Korhonen + * Copyright 2021 Joakim L. Gilje + * Copyright 2021-2022 Cacodemon345 + * Copyright 2021-2022 Teemu Korhonen */ #include "qt_hardwarerenderer.hpp" #include #include +#include + #include +#include #include extern "C" { @@ -30,84 +33,77 @@ extern "C" { #include <86box/video.h> } -void HardwareRenderer::resizeGL(int w, int h) +void +HardwareRenderer::resizeGL(int w, int h) { + m_context->makeCurrent(this); glViewport(0, 0, qRound(w * devicePixelRatio()), qRound(h * devicePixelRatio())); } -#define PROGRAM_VERTEX_ATTRIBUTE 0 +#define PROGRAM_VERTEX_ATTRIBUTE 0 #define PROGRAM_TEXCOORD_ATTRIBUTE 1 -void HardwareRenderer::initializeGL() +void +HardwareRenderer::initializeGL() { m_context->makeCurrent(this); initializeOpenGLFunctions(); - m_texture = new QOpenGLTexture(QImage(2048,2048, QImage::Format::Format_RGB32)); - m_blt = new QOpenGLTextureBlitter; + auto image = QImage(2048, 2048, QImage::Format_RGB32); + image.fill(0xff000000); + m_texture = new QOpenGLTexture(image); + m_blt = new QOpenGLTextureBlitter; m_blt->setRedBlueSwizzle(true); m_blt->create(); - QOpenGLShader *vshader = new QOpenGLShader(QOpenGLShader::Vertex, this); - const char *vsrc = - "attribute highp vec4 VertexCoord;\n" - "attribute mediump vec4 TexCoord;\n" - "varying mediump vec4 texc;\n" - "uniform mediump mat4 MVPMatrix;\n" - "void main(void)\n" - "{\n" - " gl_Position = MVPMatrix * VertexCoord;\n" - " texc = TexCoord;\n" - "}\n"; - QString vsrccore = - "in highp vec4 VertexCoord;\n" - "in mediump vec4 TexCoord;\n" - "out mediump vec4 texc;\n" - "uniform mediump mat4 MVPMatrix;\n" - "void main(void)\n" - "{\n" - " gl_Position = MVPMatrix * VertexCoord;\n" - " texc = TexCoord;\n" - "}\n"; - if (m_context->isOpenGLES() && m_context->format().version() >= qMakePair(3, 0)) - { + QOpenGLShader *vshader = new QOpenGLShader(QOpenGLShader::Vertex, this); + const char *vsrc = "attribute highp vec4 VertexCoord;\n" + "attribute mediump vec4 TexCoord;\n" + "varying mediump vec4 texc;\n" + "uniform mediump mat4 MVPMatrix;\n" + "void main(void)\n" + "{\n" + " gl_Position = MVPMatrix * VertexCoord;\n" + " texc = TexCoord;\n" + "}\n"; + QString vsrccore = "in highp vec4 VertexCoord;\n" + "in mediump vec4 TexCoord;\n" + "out mediump vec4 texc;\n" + "uniform mediump mat4 MVPMatrix;\n" + "void main(void)\n" + "{\n" + " gl_Position = MVPMatrix * VertexCoord;\n" + " texc = TexCoord;\n" + "}\n"; + if (m_context->isOpenGLES() && m_context->format().version() >= qMakePair(3, 0)) { vsrccore.prepend("#version 300 es\n"); vshader->compileSourceCode(vsrccore); - } - else if (m_context->format().version() >= qMakePair(3, 0) && m_context->format().profile() == QSurfaceFormat::CoreProfile) - { + } else if (m_context->format().version() >= qMakePair(3, 0) && m_context->format().profile() == QSurfaceFormat::CoreProfile) { vsrccore.prepend("#version 130\n"); vshader->compileSourceCode(vsrccore); - } - else vshader->compileSourceCode(vsrc); + } else + vshader->compileSourceCode(vsrc); - QOpenGLShader *fshader = new QOpenGLShader(QOpenGLShader::Fragment, this); - const char *fsrc = - "uniform sampler2D texture;\n" - "varying mediump vec4 texc;\n" - "void main(void)\n" - "{\n" - " gl_FragColor = texture2D(texture, texc.st).bgra;\n" - " gl_FragColor.a = 1.0;\n" - "}\n"; - QString fsrccore = - "uniform sampler2D texture;\n" - "in mediump vec4 texc;\n" - "out highp vec4 FragColor;\n" - "void main(void)\n" - "{\n" - " FragColor = texture2D(texture, texc.st).bgra;\n" - " FragColor.a = 1.0;\n" - "}\n"; - if (m_context->isOpenGLES() && m_context->format().version() >= qMakePair(3, 0)) - { + QOpenGLShader *fshader = new QOpenGLShader(QOpenGLShader::Fragment, this); + const char *fsrc = "uniform sampler2D texture;\n" + "varying mediump vec4 texc;\n" + "void main(void)\n" + "{\n" + " gl_FragColor = texture2D(texture, texc.st).bgra;\n" + "}\n"; + QString fsrccore = "uniform sampler2D texture;\n" + "in mediump vec4 texc;\n" + "out highp vec4 FragColor;\n" + "void main(void)\n" + "{\n" + " FragColor = texture2D(texture, texc.st).bgra;\n" + "}\n"; + if (m_context->isOpenGLES() && m_context->format().version() >= qMakePair(3, 0)) { fsrccore.prepend("#version 300 es\n"); fshader->compileSourceCode(fsrccore); - } - else if (m_context->format().version() >= qMakePair(3, 0) && m_context->format().profile() == QSurfaceFormat::CoreProfile) - { + } else if (m_context->format().version() >= qMakePair(3, 0) && m_context->format().profile() == QSurfaceFormat::CoreProfile) { fsrccore.prepend("#version 130\n"); fshader->compileSourceCode(fsrccore); - } - else fshader->compileSourceCode(fsrc); + } else + fshader->compileSourceCode(fsrc); m_prog = new QOpenGLShaderProgram; m_prog->addShader(vshader); @@ -135,14 +131,17 @@ void HardwareRenderer::initializeGL() pclog("OpenGL version: %s\n", glGetString(GL_VERSION)); pclog("OpenGL shader language version: %s\n", glGetString(GL_SHADING_LANGUAGE_VERSION)); glClearColor(0, 0, 0, 1); + m_texture->setWrapMode(QOpenGLTexture::ClampToEdge); + glClear(GL_COLOR_BUFFER_BIT); + m_context->swapBuffers(this); } -void HardwareRenderer::paintOverGL() +void +HardwareRenderer::paintOverGL() { - // Context switching is needed to make use of QPainter to draw status bar icons in fullscreen. - // Especially since it seems to be impossible to use QPainter on externally-created OpenGL contexts. - if (video_fullscreen && status_icons_fullscreen) - { + /* Context switching is needed to make use of QPainter to draw status bar icons in fullscreen. + Especially since it seems to be impossible to use QPainter on externally-created OpenGL contexts. */ + if (video_fullscreen && status_icons_fullscreen) { m_context->makeCurrent(nullptr); makeCurrent(); QPainter painter(this); @@ -153,85 +152,116 @@ void HardwareRenderer::paintOverGL() } } -void HardwareRenderer::paintGL() { +void +HardwareRenderer::paintGL() +{ m_context->makeCurrent(this); glClear(GL_COLOR_BUFFER_BIT); - QVector verts, texcoords; - QMatrix4x4 mat; + QVector verts; + QVector texcoords; + QMatrix4x4 mat; mat.setToIdentity(); - mat.ortho(QRectF(0, 0, (qreal)width(), (qreal)height())); - verts.push_back(QVector2D((float)destination.x(), (float)destination.y())); - verts.push_back(QVector2D((float)destination.x(), (float)destination.y() + (float)destination.height())); - verts.push_back(QVector2D((float)destination.x() + (float)destination.width(), (float)destination.y() + (float)destination.height())); - verts.push_back(QVector2D((float)destination.x() + (float)destination.width(), (float)destination.y())); - texcoords.push_back(QVector2D((float)source.x() / 2048.f, (float)(source.y()) / 2048.f)); - texcoords.push_back(QVector2D((float)source.x() / 2048.f, (float)(source.y() + source.height()) / 2048.f)); - texcoords.push_back(QVector2D((float)(source.x() + source.width()) / 2048.f, (float)(source.y() + source.height()) / 2048.f)); - texcoords.push_back(QVector2D((float)(source.x() + source.width()) / 2048.f, (float)(source.y()) / 2048.f)); - m_vbo[PROGRAM_VERTEX_ATTRIBUTE].bind(); m_vbo[PROGRAM_VERTEX_ATTRIBUTE].write(0, verts.data(), sizeof(QVector2D) * 4); m_vbo[PROGRAM_VERTEX_ATTRIBUTE].release(); - m_vbo[PROGRAM_TEXCOORD_ATTRIBUTE].bind(); m_vbo[PROGRAM_TEXCOORD_ATTRIBUTE].write(0, texcoords.data(), sizeof(QVector2D) * 4); m_vbo[PROGRAM_TEXCOORD_ATTRIBUTE].release(); + mat.ortho(QRectF(0, 0, (qreal) width(), (qreal) height())); + verts.push_back(QVector2D((float) destination.x(), (float) destination.y())); + verts.push_back(QVector2D((float) destination.x(), (float) destination.y() + (float) destination.height())); + verts.push_back(QVector2D((float) destination.x() + (float) destination.width(), (float) destination.y() + (float) destination.height())); + verts.push_back(QVector2D((float) destination.x() + (float) destination.width(), (float) destination.y())); + texcoords.push_back(QVector2D((float) source.x() / 2048.f, (float) (source.y()) / 2048.f)); + texcoords.push_back(QVector2D((float) source.x() / 2048.f, (float) (source.y() + source.height()) / 2048.f)); + texcoords.push_back(QVector2D((float) (source.x() + source.width()) / 2048.f, (float) (source.y() + source.height()) / 2048.f)); + texcoords.push_back(QVector2D((float) (source.x() + source.width()) / 2048.f, (float) (source.y()) / 2048.f)); + + m_vbo[PROGRAM_VERTEX_ATTRIBUTE].bind(); + m_vbo[PROGRAM_VERTEX_ATTRIBUTE].write(0, verts.data(), sizeof(QVector2D) * 4); + m_vbo[PROGRAM_VERTEX_ATTRIBUTE].release(); + m_vbo[PROGRAM_TEXCOORD_ATTRIBUTE].bind(); + m_vbo[PROGRAM_TEXCOORD_ATTRIBUTE].write(0, texcoords.data(), sizeof(QVector2D) * 4); + m_vbo[PROGRAM_TEXCOORD_ATTRIBUTE].release(); m_prog->setUniformValue("MVPMatrix", mat); m_prog->enableAttributeArray(PROGRAM_VERTEX_ATTRIBUTE); m_prog->enableAttributeArray(PROGRAM_TEXCOORD_ATTRIBUTE); - m_vbo[PROGRAM_VERTEX_ATTRIBUTE].bind(); m_prog->setAttributeBuffer(PROGRAM_VERTEX_ATTRIBUTE, GL_FLOAT, 0, 2, 0); m_vbo[PROGRAM_VERTEX_ATTRIBUTE].release(); - m_vbo[PROGRAM_TEXCOORD_ATTRIBUTE].bind(); m_prog->setAttributeBuffer(PROGRAM_TEXCOORD_ATTRIBUTE, GL_FLOAT, 0, 2, 0); m_vbo[PROGRAM_TEXCOORD_ATTRIBUTE].release(); + m_vbo[PROGRAM_VERTEX_ATTRIBUTE].bind(); + m_prog->setAttributeBuffer(PROGRAM_VERTEX_ATTRIBUTE, GL_FLOAT, 0, 2, 0); + m_vbo[PROGRAM_VERTEX_ATTRIBUTE].release(); + m_vbo[PROGRAM_TEXCOORD_ATTRIBUTE].bind(); + m_prog->setAttributeBuffer(PROGRAM_TEXCOORD_ATTRIBUTE, GL_FLOAT, 0, 2, 0); + m_vbo[PROGRAM_TEXCOORD_ATTRIBUTE].release(); m_texture->bind(); m_texture->setMinMagFilters(video_filter_method ? QOpenGLTexture::Linear : QOpenGLTexture::Nearest, video_filter_method ? QOpenGLTexture::Linear : QOpenGLTexture::Nearest); glDrawArrays(GL_TRIANGLE_FAN, 0, 4); } -void HardwareRenderer::setRenderType(RenderType type) { +void +HardwareRenderer::setRenderType(RenderType type) +{ QSurfaceFormat format; switch (type) { - case RenderType::OpenGL3: - format.setVersion(3, 0); - format.setProfile(QSurfaceFormat::CoreProfile); - case RenderType::OpenGL: - format.setRenderableType(QSurfaceFormat::OpenGL); - break; - case RenderType::OpenGLES: - format.setRenderableType(QSurfaceFormat::OpenGLES); - break; + case RenderType::OpenGL3: + format.setVersion(3, 0); + format.setProfile(QSurfaceFormat::CoreProfile); + case RenderType::OpenGL: + format.setRenderableType(QSurfaceFormat::OpenGL); + break; + case RenderType::OpenGLES: + format.setRenderableType(QSurfaceFormat::OpenGLES); + break; } format.setSwapInterval(0); setFormat(format); } -void HardwareRenderer::onBlit(int buf_idx, int x, int y, int w, int h) { - auto tval = this; - void* nuldata = 0; - if (memcmp(&tval, &nuldata, sizeof(void*)) == 0) return; - if (!m_texture || !m_texture->isCreated()) - { +void +HardwareRenderer::onBlit(int buf_idx, int x, int y, int w, int h) +{ + auto tval = this; + void *nuldata = 0; + if (memcmp(&tval, &nuldata, sizeof(void *)) == 0) + return; + auto origSource = source; + if (!m_texture || !m_texture->isCreated()) { buf_usage[buf_idx].clear(); source.setRect(x, y, w, h); return; } m_context->makeCurrent(this); - m_texture->setData(QOpenGLTexture::PixelFormat::RGBA, QOpenGLTexture::PixelType::UInt8, (const void*)imagebufs[buf_idx].get()); +#if QT_VERSION >= QT_VERSION_CHECK(5, 14, 0) + m_texture->setData(x, y, 0, w, h, 0, QOpenGLTexture::PixelFormat::RGBA, QOpenGLTexture::PixelType::UInt8, (const void *) ((uintptr_t) imagebufs[buf_idx].get() + (uintptr_t) (2048 * 4 * y + x * 4)), &m_transferOptions); +#else + m_texture->bind(); + glPixelStorei(GL_UNPACK_ROW_LENGTH, 2048); + glTexSubImage2D(GL_TEXTURE_2D, 0, x, y, w, h, QOpenGLTexture::PixelFormat::RGBA, QOpenGLTexture::PixelType::UInt8, (const void *) ((uintptr_t) imagebufs[buf_idx].get() + (uintptr_t) (2048 * 4 * y + x * 4))); + m_texture->release(); +#endif buf_usage[buf_idx].clear(); source.setRect(x, y, w, h); + if (origSource != source) + onResize(this->width(), this->height()); update(); } -void HardwareRenderer::resizeEvent(QResizeEvent *event) { +void +HardwareRenderer::resizeEvent(QResizeEvent *event) +{ onResize(width(), height()); QOpenGLWindow::resizeEvent(event); } -bool HardwareRenderer::event(QEvent *event) +bool +HardwareRenderer::event(QEvent *event) { bool res = false; - if (!eventDelegate(event, res)) return QOpenGLWindow::event(event); + if (!eventDelegate(event, res)) + return QOpenGLWindow::event(event); return res; } -std::vector> HardwareRenderer::getBuffers() +std::vector> +HardwareRenderer::getBuffers() { - std::vector> buffers; + std::vector> buffers; buffers.push_back(std::make_tuple(imagebufs[0].get(), &buf_usage[0])); buffers.push_back(std::make_tuple(imagebufs[1].get(), &buf_usage[1])); diff --git a/src/qt/qt_hardwarerenderer.hpp b/src/qt/qt_hardwarerenderer.hpp index 9720a8c2e..1918cda18 100644 --- a/src/qt/qt_hardwarerenderer.hpp +++ b/src/qt/qt_hardwarerenderer.hpp @@ -8,6 +8,7 @@ #include #include #include +#include #include #include #include @@ -23,21 +24,22 @@ #include "qt_renderercommon.hpp" #ifdef WAYLAND -#include "wl_mouse.hpp" +# include "wl_mouse.hpp" #endif -class HardwareRenderer : public QOpenGLWindow, protected QOpenGLFunctions, public RendererCommon -{ - Q_OBJECT +class HardwareRenderer : public QOpenGLWindow, protected QOpenGLFunctions, public RendererCommon { + Q_OBJECT private: - bool wayland = false; - QOpenGLContext* m_context; - QOpenGLTexture* m_texture{nullptr}; - QOpenGLShaderProgram* m_prog{nullptr}; - QOpenGLTextureBlitter* m_blt{nullptr}; - QOpenGLBuffer m_vbo[2]; - QOpenGLVertexArrayObject m_vao; + bool wayland = false; + QOpenGLContext *m_context; + QOpenGLTexture *m_texture { nullptr }; + QOpenGLShaderProgram *m_prog { nullptr }; + QOpenGLTextureBlitter *m_blt { nullptr }; + QOpenGLBuffer m_vbo[2]; + QOpenGLVertexArrayObject m_vao; + QOpenGLPixelTransferOptions m_transferOptions; + public: enum class RenderType { OpenGL, @@ -47,10 +49,15 @@ public: void resizeGL(int w, int h) override; void initializeGL() override; void paintGL() override; + void exposeEvent(QExposeEvent *event) override + { + onResize(size().width(), size().height()); + } void paintOverGL() override; - std::vector> getBuffers() override; - HardwareRenderer(QWidget* parent = nullptr, RenderType rtype = RenderType::OpenGL) - : QOpenGLWindow(QOpenGLWindow::NoPartialUpdate, parent->windowHandle()), QOpenGLFunctions() + std::vector> getBuffers() override; + HardwareRenderer(QWidget *parent = nullptr, RenderType rtype = RenderType::OpenGL) + : QOpenGLWindow(QOpenGLWindow::NoPartialUpdate, parent->windowHandle()) + , QOpenGLFunctions() { imagebufs[0] = std::unique_ptr(new uint8_t[2048 * 2048 * 4]); imagebufs[1] = std::unique_ptr(new uint8_t[2048 * 2048 * 4]); @@ -64,14 +71,18 @@ public: parentWidget = parent; setRenderType(rtype); + m_transferOptions.setRowLength(2048); + m_context = new QOpenGLContext(); m_context->setFormat(format()); m_context->create(); + update(); } ~HardwareRenderer() { m_context->makeCurrent(this); - if (m_blt) m_blt->destroy(); + if (m_blt) + m_blt->destroy(); m_prog->release(); delete m_prog; m_prog = nullptr; @@ -79,7 +90,6 @@ public: delete m_context; } - void setRenderType(RenderType type); public slots: @@ -89,5 +99,5 @@ protected: std::array, 2> imagebufs; void resizeEvent(QResizeEvent *event) override; - bool event(QEvent* event) override; + bool event(QEvent *event) override; }; diff --git a/src/qt/qt_joystickconfiguration.cpp b/src/qt/qt_joystickconfiguration.cpp index 594a1ef17..8523a258d 100644 --- a/src/qt/qt_joystickconfiguration.cpp +++ b/src/qt/qt_joystickconfiguration.cpp @@ -1,18 +1,18 @@ /* - * 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. + * 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. + * This file is part of the 86Box distribution. * - * Joystick configuration UI module. + * Joystick configuration UI module. * * * - * Authors: Joakim L. Gilje + * Authors: Joakim L. Gilje * - * Copyright 2021 Joakim L. Gilje + * Copyright 2021 Joakim L. Gilje */ #include "qt_joystickconfiguration.hpp" #include "ui_qt_joystickconfiguration.h" @@ -22,28 +22,27 @@ extern "C" { #include <86box/gameport.h> } - #include #include #include #include "qt_models_common.hpp" -JoystickConfiguration::JoystickConfiguration(int type, int joystick_nr, QWidget *parent) : - QDialog(parent), - ui(new Ui::JoystickConfiguration), - type(type), - joystick_nr(joystick_nr) +JoystickConfiguration::JoystickConfiguration(int type, int joystick_nr, QWidget *parent) + : QDialog(parent) + , ui(new Ui::JoystickConfiguration) + , type(type) + , joystick_nr(joystick_nr) { ui->setupUi(this); auto model = ui->comboBoxDevice->model(); Models::AddEntry(model, "None", 0); for (int c = 0; c < joysticks_present; c++) { - Models::AddEntry(model, plat_joystick_state[c].name, c+1); + Models::AddEntry(model, plat_joystick_state[c].name, c + 1); } ui->comboBoxDevice->setCurrentIndex(joystick_state[joystick_nr].plat_joystick_nr); - setFixedSize(minimumSizeHint()); + layout()->setSizeConstraint(QLayout::SetFixedSize); } JoystickConfiguration::~JoystickConfiguration() @@ -51,50 +50,63 @@ JoystickConfiguration::~JoystickConfiguration() delete ui; } -int JoystickConfiguration::selectedDevice() { +int +JoystickConfiguration::selectedDevice() +{ return ui->comboBoxDevice->currentIndex(); } -int JoystickConfiguration::selectedAxis(int axis) { - auto* cbox = findChild(QString("cboxAxis%1").arg(QString::number(axis))); +int +JoystickConfiguration::selectedAxis(int axis) +{ + auto *cbox = findChild(QString("cboxAxis%1").arg(QString::number(axis))); if (cbox == nullptr) { return 0; } return cbox->currentIndex(); } -int JoystickConfiguration::selectedButton(int button) { - auto* cbox = findChild(QString("cboxButton%1").arg(QString::number(button))); +int +JoystickConfiguration::selectedButton(int button) +{ + auto *cbox = findChild(QString("cboxButton%1").arg(QString::number(button))); if (cbox == nullptr) { return 0; } return cbox->currentIndex(); } -int JoystickConfiguration::selectedPov(int pov) { - auto* cbox = findChild(QString("cboxPov%1").arg(QString::number(pov))); +int +JoystickConfiguration::selectedPov(int pov) +{ + auto *cbox = findChild(QString("cboxPov%1").arg(QString::number(pov))); if (cbox == nullptr) { return 0; } return cbox->currentIndex(); } -void JoystickConfiguration::on_comboBoxDevice_currentIndexChanged(int index) { +void +JoystickConfiguration::on_comboBoxDevice_currentIndexChanged(int index) +{ for (auto w : widgets) { ui->ct->removeWidget(w); + w->deleteLater(); } + widgets.clear(); if (index == 0) { return; } int joystick = index - 1; - int row = 0; + int row = 0; for (int c = 0; c < joystick_get_axis_count(type); c++) { /*Combo box*/ auto label = new QLabel(joystick_get_axis_name(type, c), this); - auto cbox = new QComboBox(this); + auto cbox = new QComboBox(this); cbox->setObjectName(QString("cboxAxis%1").arg(QString::number(c))); + cbox->setMaxVisibleItems(30); auto model = cbox->model(); for (int d = 0; d < plat_joystick_state[joystick].nr_axes; d++) { @@ -133,8 +145,9 @@ void JoystickConfiguration::on_comboBoxDevice_currentIndexChanged(int index) { for (int c = 0; c < joystick_get_button_count(type); c++) { auto label = new QLabel(joystick_get_button_name(type, c), this); - auto cbox = new QComboBox(this); + auto cbox = new QComboBox(this); cbox->setObjectName(QString("cboxButton%1").arg(QString::number(c))); + cbox->setMaxVisibleItems(30); auto model = cbox->model(); for (int d = 0; d < plat_joystick_state[joystick].nr_buttons; d++) { @@ -153,14 +166,15 @@ void JoystickConfiguration::on_comboBoxDevice_currentIndexChanged(int index) { } for (int c = 0; c < joystick_get_pov_count(type) * 2; c++) { - QLabel* label; + QLabel *label; if (c & 1) { - label = new QLabel(QString("%1 (Y axis)").arg(joystick_get_pov_name(type, c/2)), this); + label = new QLabel(QString("%1 (Y axis)").arg(joystick_get_pov_name(type, c / 2)), this); } else { - label = new QLabel(QString("%1 (X axis)").arg(joystick_get_pov_name(type, c/2)), this); + label = new QLabel(QString("%1 (X axis)").arg(joystick_get_pov_name(type, c / 2)), this); } auto cbox = new QComboBox(this); cbox->setObjectName(QString("cboxPov%1").arg(QString::number(c))); + cbox->setMaxVisibleItems(30); auto model = cbox->model(); for (int d = 0; d < plat_joystick_state[joystick].nr_povs; d++) { @@ -177,17 +191,17 @@ void JoystickConfiguration::on_comboBoxDevice_currentIndexChanged(int index) { if (mapping & POV_X) cbox->setCurrentIndex((mapping & 3) * 2); else if (mapping & POV_Y) - cbox->setCurrentIndex((mapping & 3)*2 + 1); + cbox->setCurrentIndex((mapping & 3) * 2 + 1); else cbox->setCurrentIndex(mapping + nr_povs * 2); mapping = joystick_state[joystick_nr].pov_mapping[c][1]; if (mapping & POV_X) - cbox->setCurrentIndex((mapping & 3)*2); + cbox->setCurrentIndex((mapping & 3) * 2); else if (mapping & POV_Y) - cbox->setCurrentIndex((mapping & 3)*2 + 1); + cbox->setCurrentIndex((mapping & 3) * 2 + 1); else - cbox->setCurrentIndex(mapping + nr_povs*2); + cbox->setCurrentIndex(mapping + nr_povs * 2); ui->ct->addWidget(label, row, 0); ui->ct->addWidget(cbox, row, 1); @@ -197,6 +211,4 @@ void JoystickConfiguration::on_comboBoxDevice_currentIndexChanged(int index) { ++row; } - - setFixedSize(minimumSizeHint()); } diff --git a/src/qt/qt_joystickconfiguration.hpp b/src/qt/qt_joystickconfiguration.hpp index b6882c52b..0b185ad73 100644 --- a/src/qt/qt_joystickconfiguration.hpp +++ b/src/qt/qt_joystickconfiguration.hpp @@ -7,8 +7,7 @@ namespace Ui { class JoystickConfiguration; } -class JoystickConfiguration : public QDialog -{ +class JoystickConfiguration : public QDialog { Q_OBJECT public: @@ -24,9 +23,9 @@ private slots: private: Ui::JoystickConfiguration *ui; - QList widgets; - int type; - int joystick_nr; + QList widgets; + int type; + int joystick_nr; }; #endif // QT_JOYSTICKCONFIGURATION_HPP diff --git a/src/qt/qt_joystickconfiguration.ui b/src/qt/qt_joystickconfiguration.ui index abe17b5cc..139b99ca5 100644 --- a/src/qt/qt_joystickconfiguration.ui +++ b/src/qt/qt_joystickconfiguration.ui @@ -11,7 +11,7 @@ - Dialog + Joystick configuration @@ -25,7 +25,11 @@ - + + + 30 + + diff --git a/src/qt/qt_machinestatus.cpp b/src/qt/qt_machinestatus.cpp index 71be8c232..bb3002df2 100644 --- a/src/qt/qt_machinestatus.cpp +++ b/src/qt/qt_machinestatus.cpp @@ -1,26 +1,26 @@ /* - * 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. + * 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. + * This file is part of the 86Box distribution. * - * Joystick configuration UI module. + * Joystick configuration UI module. * * * - * Authors: Joakim L. Gilje + * Authors: Joakim L. Gilje * Cacodemon345 * - * Copyright 2021 Joakim L. Gilje - * Copyright 2021-2022 Cacodemon345 + * Copyright 2021 Joakim L. Gilje + * Copyright 2021-2022 Cacodemon345 */ #include "qt_machinestatus.hpp" extern "C" { #define EMU_CPU_H // superhack - don't want timer.h to include cpu.h here, and some combo is preventing a compile -extern uint64_t tsc; +extern uint64_t tsc; #include <86box/hdd.h> #include <86box/timer.h> @@ -29,6 +29,7 @@ extern uint64_t tsc; #include <86box/cartridge.h> #include <86box/cassette.h> #include <86box/cdrom.h> +#include <86box/cdrom_interface.h> #include <86box/fdd.h> #include <86box/hdc.h> #include <86box/scsi.h> @@ -37,8 +38,10 @@ extern uint64_t tsc; #include <86box/mo.h> #include <86box/plat.h> #include <86box/machine.h> +#include <86box/thread.h> #include <86box/network.h> #include <86box/ui.h> +#include <86box/machine_status.h> }; #include @@ -56,127 +59,154 @@ extern uint64_t tsc; #include -extern MainWindow* main_window; +extern MainWindow *main_window; namespace { - struct PixmapSetActive { - QPixmap normal; - QPixmap active; - void load(const QString& basePath); - }; - struct PixmapSetEmpty { - QPixmap normal; - QPixmap empty; - void load(const QString& basePath); - }; - struct PixmapSetEmptyActive { - QPixmap normal; - QPixmap active; - QPixmap empty; - QPixmap empty_active; - void load(QString basePath); - }; - struct Pixmaps { - PixmapSetEmpty cartridge; - PixmapSetEmptyActive cassette; - PixmapSetEmptyActive floppy_disabled; - PixmapSetEmptyActive floppy_525; - PixmapSetEmptyActive floppy_35; - PixmapSetEmptyActive cdrom; - PixmapSetEmptyActive zip; - PixmapSetEmptyActive mo; - PixmapSetActive hd; - PixmapSetActive net; - QPixmap sound; - }; +struct PixmapSetActive { + QPixmap normal; + QPixmap active; + void load(const QString &basePath); +}; +struct PixmapSetEmpty { + QPixmap normal; + QPixmap empty; + void load(const QString &basePath); +}; +struct PixmapSetEmptyActive { + QPixmap normal; + QPixmap active; + QPixmap empty; + QPixmap empty_active; + void load(QString basePath); +}; +struct Pixmaps { + PixmapSetEmpty cartridge; + PixmapSetEmptyActive cassette; + PixmapSetEmptyActive floppy_disabled; + PixmapSetEmptyActive floppy_525; + PixmapSetEmptyActive floppy_35; + PixmapSetEmptyActive cdrom; + PixmapSetEmptyActive zip; + PixmapSetEmptyActive mo; + PixmapSetActive hd; + PixmapSetEmptyActive net; + QPixmap sound; +}; - struct StateActive { - std::unique_ptr label; - QTimer timer; - PixmapSetActive* pixmaps = nullptr; - bool active = false; +struct StateActive { + std::unique_ptr label; + PixmapSetActive *pixmaps = nullptr; + bool active = false; - void setActive(bool b) { - active = b; - if (! label) { - return; - } + void setActive(bool b) + { + if (!label || b == active) + return; + active = b; + + refresh(); + } + + void refresh() + { + if (!label) + return; + label->setPixmap(active ? pixmaps->active : pixmaps->normal); + } +}; +struct StateEmpty { + std::unique_ptr label; + PixmapSetEmpty *pixmaps = nullptr; + bool empty = false; + + void setEmpty(bool e) + { + if (!label || e == empty) + return; + empty = e; + + refresh(); + } + + void refresh() + { + if (!label) + return; + label->setPixmap(empty ? pixmaps->empty : pixmaps->normal); + } +}; +struct StateEmptyActive { + std::unique_ptr label; + PixmapSetEmptyActive *pixmaps = nullptr; + bool empty = false; + bool active = false; + + void setActive(bool b) + { + if (!label || b == active) + return; + + active = b; + refresh(); + } + void setEmpty(bool b) + { + if (!label || b == empty) + return; + + empty = b; + refresh(); + } + void refresh() + { + if (!label) + return; + if (empty) { + label->setPixmap(active ? pixmaps->empty_active : pixmaps->empty); + } else { label->setPixmap(active ? pixmaps->active : pixmaps->normal); - timer.start(75); } - }; - struct StateEmpty { - std::unique_ptr label; - PixmapSetEmpty* pixmaps = nullptr; - bool empty = false; - - void setEmpty(bool e) { - empty = e; - if (! label) { - return; - } - label->setPixmap(empty ? pixmaps->empty : pixmaps->normal); - } - }; - struct StateEmptyActive { - std::unique_ptr label; - QTimer timer; - PixmapSetEmptyActive* pixmaps = nullptr; - bool empty = false; - bool active = false; - - void setActive(bool b) { - active = b; - refresh(); - timer.start(75); - } - void setEmpty(bool b) { - empty = b; - refresh(); - } - void refresh() { - if (! label) { - return; - } - if (empty) { - label->setPixmap(active ? pixmaps->empty_active : pixmaps->empty); - } else { - label->setPixmap(active ? pixmaps->active : pixmaps->normal); - } - } - }; - - static QSize pixmap_size(16, 16); - static const QString pixmap_empty = QStringLiteral("_empty"); - static const QString pixmap_active = QStringLiteral("_active"); - static const QString pixmap_empty_active = QStringLiteral("_empty_active"); - void PixmapSetEmpty::load(const QString &basePath) { - normal = ProgSettings::loadIcon(basePath.arg(QStringLiteral(""))).pixmap(pixmap_size); - empty = ProgSettings::loadIcon(basePath.arg(pixmap_empty)).pixmap(pixmap_size); } +}; - void PixmapSetActive::load(const QString &basePath) { - normal = ProgSettings::loadIcon(basePath.arg(QStringLiteral(""))).pixmap(pixmap_size); - active = ProgSettings::loadIcon(basePath.arg(pixmap_active)).pixmap(pixmap_size); - } +static QSize pixmap_size(16, 16); +static const QString pixmap_empty = QStringLiteral("_empty"); +static const QString pixmap_active = QStringLiteral("_active"); +static const QString pixmap_empty_active = QStringLiteral("_empty_active"); +void +PixmapSetEmpty::load(const QString &basePath) +{ + normal = ProgSettings::loadIcon(basePath.arg(QStringLiteral(""))).pixmap(pixmap_size); + empty = ProgSettings::loadIcon(basePath.arg(pixmap_empty)).pixmap(pixmap_size); +} - void PixmapSetEmptyActive::load(QString basePath) { - normal = ProgSettings::loadIcon(basePath.arg(QStringLiteral(""))).pixmap(pixmap_size); - active = ProgSettings::loadIcon(basePath.arg(pixmap_active)).pixmap(pixmap_size); - empty = ProgSettings::loadIcon(basePath.arg(pixmap_empty)).pixmap(pixmap_size); - empty_active = ProgSettings::loadIcon(basePath.arg(pixmap_empty_active)).pixmap(pixmap_size); - } +void +PixmapSetActive::load(const QString &basePath) +{ + normal = ProgSettings::loadIcon(basePath.arg(QStringLiteral(""))).pixmap(pixmap_size); + active = ProgSettings::loadIcon(basePath.arg(pixmap_active)).pixmap(pixmap_size); +} + +void +PixmapSetEmptyActive::load(QString basePath) +{ + normal = ProgSettings::loadIcon(basePath.arg(QStringLiteral(""))).pixmap(pixmap_size); + active = ProgSettings::loadIcon(basePath.arg(pixmap_active)).pixmap(pixmap_size); + empty = ProgSettings::loadIcon(basePath.arg(pixmap_empty)).pixmap(pixmap_size); + empty_active = ProgSettings::loadIcon(basePath.arg(pixmap_empty_active)).pixmap(pixmap_size); +} } struct MachineStatus::States { Pixmaps pixmaps; - States(QObject* parent) { + States(QObject *parent) + { pixmaps.cartridge.load("/cartridge%1.ico"); pixmaps.cassette.load("/cassette%1.ico"); - pixmaps.floppy_disabled.normal = ProgSettings::loadIcon(QStringLiteral("/floppy_disabled.ico")).pixmap(pixmap_size); - pixmaps.floppy_disabled.active = pixmaps.floppy_disabled.normal; - pixmaps.floppy_disabled.empty = pixmaps.floppy_disabled.normal; + pixmaps.floppy_disabled.normal = ProgSettings::loadIcon(QStringLiteral("/floppy_disabled.ico")).pixmap(pixmap_size); + pixmaps.floppy_disabled.active = pixmaps.floppy_disabled.normal; + pixmaps.floppy_disabled.empty = pixmaps.floppy_disabled.normal; pixmaps.floppy_disabled.empty_active = pixmaps.floppy_disabled.normal; pixmaps.floppy_525.load("/floppy_525%1.ico"); pixmaps.floppy_35.load("/floppy_35%1.ico"); @@ -189,64 +219,71 @@ struct MachineStatus::States { cartridge[0].pixmaps = &pixmaps.cartridge; cartridge[1].pixmaps = &pixmaps.cartridge; - cassette.pixmaps = &pixmaps.cassette; - QObject::connect(&cassette.timer, &QTimer::timeout, parent, [&]{ cassette.setActive(false); }); - for (auto& f : fdd) { + cassette.pixmaps = &pixmaps.cassette; + for (auto &f : fdd) { f.pixmaps = &pixmaps.floppy_disabled; - QObject::connect(&f.timer, &QTimer::timeout, parent, [&]{ f.setActive(false); }); } - for (auto& c : cdrom) { + for (auto &c : cdrom) { c.pixmaps = &pixmaps.cdrom; - QObject::connect(&c.timer, &QTimer::timeout, parent, [&]{ c.setActive(false); }); } - for (auto& z : zip) { + for (auto &z : zip) { z.pixmaps = &pixmaps.zip; - QObject::connect(&z.timer, &QTimer::timeout, parent, [&]{ z.setActive(false); }); } - for (auto& m : mo) { + for (auto &m : mo) { m.pixmaps = &pixmaps.mo; - QObject::connect(&m.timer, &QTimer::timeout, parent, [&]{ m.setActive(false); }); } - for (auto& h : hdds) { + for (auto &h : hdds) { h.pixmaps = &pixmaps.hd; - QObject::connect(&h.timer, &QTimer::timeout, parent, [&]{ h.setActive(false); }); } - net.pixmaps = &pixmaps.net; + for (auto &n : net) { + n.pixmaps = &pixmaps.net; + } } - std::array cartridge; - StateEmptyActive cassette; - std::array fdd; - std::array cdrom; - std::array zip; - std::array mo; - std::array hdds; - StateActive net; - std::unique_ptr sound; - std::unique_ptr text; + std::array cartridge; + StateEmptyActive cassette; + std::array fdd; + std::array cdrom; + std::array zip; + std::array mo; + std::array hdds; + std::array net; + std::unique_ptr sound; + std::unique_ptr text; }; -MachineStatus::MachineStatus(QObject *parent) : - QObject(parent) +MachineStatus::MachineStatus(QObject *parent) + : QObject(parent) + , refreshTimer(new QTimer(this)) { d = std::make_unique(this); + connect(refreshTimer, &QTimer::timeout, this, &MachineStatus::refreshIcons); + refreshTimer->start(75); } MachineStatus::~MachineStatus() = default; -bool MachineStatus::hasCassette() { +bool +MachineStatus::hasCassette() +{ return cassette_enable > 0 ? true : false; } -bool MachineStatus::hasIDE() { +bool +MachineStatus::hasIDE() +{ return machine_has_flags(machine, MACHINE_IDE_QUAD) > 0; } -bool MachineStatus::hasSCSI() { - return machine_has_flags(machine, MACHINE_SCSI_DUAL) > 0; +bool +MachineStatus::hasSCSI() +{ + return machine_has_flags(machine, MACHINE_SCSI) > 0; } -void MachineStatus::iterateFDD(const std::function &cb) { +void +MachineStatus::iterateFDD(const std::function &cb) +{ for (int i = 0; i < FDD_NUM; ++i) { if (fdd_get_type(i) != 0) { cb(i); @@ -254,17 +291,17 @@ void MachineStatus::iterateFDD(const std::function &cb) { } } -void MachineStatus::iterateCDROM(const std::function &cb) { +void +MachineStatus::iterateCDROM(const std::function &cb) +{ auto hdc_name = QString(hdc_get_internal_name(hdc_current)); for (size_t i = 0; i < CDROM_NUM; i++) { /* Could be Internal or External IDE.. */ - if ((cdrom[i].bus_type == CDROM_BUS_ATAPI) && - !hasIDE() && hdc_name != QStringLiteral("ide") && - hdc_name != QStringLiteral("xtide")) + if ((cdrom[i].bus_type == CDROM_BUS_ATAPI) && !hasIDE() && hdc_name.left(3) != QStringLiteral("ide") && hdc_name.left(5) != QStringLiteral("xtide")) continue; - if ((cdrom[i].bus_type == CDROM_BUS_SCSI) && !hasSCSI() && - (scsi_card_current[0] == 0) && (scsi_card_current[1] == 0) && - (scsi_card_current[2] == 0) && (scsi_card_current[3] == 0)) + if ((cdrom[i].bus_type == CDROM_BUS_SCSI) && !hasSCSI() && (scsi_card_current[0] == 0) && (scsi_card_current[1] == 0) && (scsi_card_current[2] == 0) && (scsi_card_current[3] == 0)) + continue; + if ((cdrom[i].bus_type == CDROM_BUS_MITSUMI) && (cdrom_interface_current == 0)) continue; if (cdrom[i].bus_type != 0) { cb(i); @@ -272,17 +309,15 @@ void MachineStatus::iterateCDROM(const std::function &cb) { } } -void MachineStatus::iterateZIP(const std::function &cb) { +void +MachineStatus::iterateZIP(const std::function &cb) +{ auto hdc_name = QString(hdc_get_internal_name(hdc_current)); for (size_t i = 0; i < ZIP_NUM; i++) { /* Could be Internal or External IDE.. */ - if ((zip_drives[i].bus_type == ZIP_BUS_ATAPI) && - !hasIDE() && hdc_name != QStringLiteral("ide") && - hdc_name != QStringLiteral("xtide")) + if ((zip_drives[i].bus_type == ZIP_BUS_ATAPI) && !hasIDE() && hdc_name.left(3) != QStringLiteral("ide") && hdc_name.left(5) != QStringLiteral("xtide")) continue; - if ((zip_drives[i].bus_type == ZIP_BUS_SCSI) && !hasSCSI() && - (scsi_card_current[0] == 0) && (scsi_card_current[1] == 0) && - (scsi_card_current[2] == 0) && (scsi_card_current[3] == 0)) + if ((zip_drives[i].bus_type == ZIP_BUS_SCSI) && !hasSCSI() && (scsi_card_current[0] == 0) && (scsi_card_current[1] == 0) && (scsi_card_current[2] == 0) && (scsi_card_current[3] == 0)) continue; if (zip_drives[i].bus_type != 0) { cb(i); @@ -290,17 +325,15 @@ void MachineStatus::iterateZIP(const std::function &cb) { } } -void MachineStatus::iterateMO(const std::function &cb) { +void +MachineStatus::iterateMO(const std::function &cb) +{ auto hdc_name = QString(hdc_get_internal_name(hdc_current)); for (size_t i = 0; i < MO_NUM; i++) { /* Could be Internal or External IDE.. */ - if ((mo_drives[i].bus_type == MO_BUS_ATAPI) && - !hasIDE() && hdc_name != QStringLiteral("ide") && - hdc_name != QStringLiteral("xtide")) + if ((mo_drives[i].bus_type == MO_BUS_ATAPI) && !hasIDE() && hdc_name.left(3) != QStringLiteral("ide") && hdc_name.left(5) != QStringLiteral("xtide")) continue; - if ((mo_drives[i].bus_type == MO_BUS_SCSI) && !hasSCSI() && - (scsi_card_current[0] == 0) && (scsi_card_current[1] == 0) && - (scsi_card_current[2] == 0) && (scsi_card_current[3] == 0)) + if ((mo_drives[i].bus_type == MO_BUS_SCSI) && !hasSCSI() && (scsi_card_current[0] == 0) && (scsi_card_current[1] == 0) && (scsi_card_current[2] == 0) && (scsi_card_current[3] == 0)) continue; if (mo_drives[i].bus_type != 0) { cb(i); @@ -308,30 +341,99 @@ void MachineStatus::iterateMO(const std::function &cb) { } } -static int hdd_count(int bus) { - int c = 0; - int i; +void +MachineStatus::iterateNIC(const std::function &cb) +{ + for (int i = 0; i < NET_CARD_MAX; i++) { + if (network_dev_available(i)) { + cb(i); + } + } +} - for (i = 0; i < HDD_NUM; i++) { +static int +hdd_count(int bus) +{ + int c = 0; + + for (uint8_t i = 0; i < HDD_NUM; i++) { if (hdd[i].bus == bus) { c++; } } - return(c); + return c; } -void MachineStatus::refresh(QStatusBar* sbar) { - bool has_mfm = machine_has_flags(machine, MACHINE_MFM) > 0; - bool has_xta = machine_has_flags(machine, MACHINE_XTA) > 0; +void +MachineStatus::refreshIcons() +{ + /* Check if icons should show activity. */ + if (!update_icons) + return; + + for (size_t i = 0; i < FDD_NUM; ++i) { + d->fdd[i].setActive(machine_status.fdd[i].active); + d->fdd[i].setEmpty(machine_status.fdd[i].empty); + } + for (size_t i = 0; i < CDROM_NUM; ++i) { + d->cdrom[i].setActive(machine_status.cdrom[i].active); + d->cdrom[i].setEmpty(machine_status.cdrom[i].empty); + } + for (size_t i = 0; i < ZIP_NUM; i++) { + d->zip[i].setActive(machine_status.zip[i].active); + d->zip[i].setEmpty(machine_status.zip[i].empty); + } + for (size_t i = 0; i < MO_NUM; i++) { + d->mo[i].setActive(machine_status.mo[i].active); + d->mo[i].setEmpty(machine_status.mo[i].empty); + } + + d->cassette.setEmpty(machine_status.cassette.empty); + + for (size_t i = 0; i < HDD_BUS_USB; i++) { + d->hdds[i].setActive(machine_status.hdd[i].active); + } + + for (size_t i = 0; i < NET_CARD_MAX; i++) { + d->net[i].setActive(machine_status.net[i].active); + d->net[i].setEmpty(machine_status.net[i].empty); + } + + for (int i = 0; i < 2; ++i) { + d->cartridge[i].setEmpty(machine_status.cartridge[i].empty); + } +} + +void +MachineStatus::clearActivity() +{ + for (auto &fdd : d->fdd) + fdd.setActive(false); + for (auto &cdrom : d->cdrom) + cdrom.setActive(false); + for (auto &zip : d->zip) + zip.setActive(false); + for (auto &mo : d->mo) + mo.setActive(false); + for (auto &hdd : d->hdds) + hdd.setActive(false); + for (auto &net : d->net) + net.setActive(false); +} + +void +MachineStatus::refresh(QStatusBar *sbar) +{ + bool has_mfm = machine_has_flags(machine, MACHINE_MFM) > 0; + bool has_xta = machine_has_flags(machine, MACHINE_XTA) > 0; bool has_esdi = machine_has_flags(machine, MACHINE_ESDI) > 0; - int c_mfm = hdd_count(HDD_BUS_MFM); + int c_mfm = hdd_count(HDD_BUS_MFM); int c_esdi = hdd_count(HDD_BUS_ESDI); - int c_xta = hdd_count(HDD_BUS_XTA); - int c_ide = hdd_count(HDD_BUS_IDE); + int c_xta = hdd_count(HDD_BUS_XTA); + int c_ide = hdd_count(HDD_BUS_IDE); int c_scsi = hdd_count(HDD_BUS_SCSI); - int do_net = network_available(); sbar->removeWidget(d->cassette.label.get()); for (int i = 0; i < 2; ++i) { @@ -352,16 +454,23 @@ void MachineStatus::refresh(QStatusBar* sbar) { for (size_t i = 0; i < HDD_BUS_USB; i++) { sbar->removeWidget(d->hdds[i].label.get()); } - sbar->removeWidget(d->net.label.get()); + for (size_t i = 0; i < NET_CARD_MAX; i++) { + sbar->removeWidget(d->net[i].label.get()); + } sbar->removeWidget(d->sound.get()); if (cassette_enable) { d->cassette.label = std::make_unique(); d->cassette.setEmpty(QString(cassette_fname).isEmpty()); - connect((ClickableLabel*)d->cassette.label.get(), &ClickableLabel::clicked, [this](QPoint pos) { + d->cassette.refresh(); + connect((ClickableLabel *) d->cassette.label.get(), &ClickableLabel::clicked, [](QPoint pos) { MediaMenu::ptr->cassetteMenu->popup(pos - QPoint(0, MediaMenu::ptr->cassetteMenu->sizeHint().height())); }); + connect((ClickableLabel *) d->cassette.label.get(), &ClickableLabel::dropped, [](QString str) { + MediaMenu::ptr->cassetteMount(str, false); + }); d->cassette.label->setToolTip(MediaMenu::ptr->cassetteMenu->title()); + d->cassette.label->setAcceptDrops(true); sbar->addWidget(d->cassette.label.get()); } @@ -369,10 +478,15 @@ void MachineStatus::refresh(QStatusBar* sbar) { for (int i = 0; i < 2; ++i) { d->cartridge[i].label = std::make_unique(); d->cartridge[i].setEmpty(QString(cart_fns[i]).isEmpty()); - connect((ClickableLabel*)d->cartridge[i].label.get(), &ClickableLabel::clicked, [this, i](QPoint pos) { + d->cartridge[i].refresh(); + connect((ClickableLabel *) d->cartridge[i].label.get(), &ClickableLabel::clicked, [i](QPoint pos) { MediaMenu::ptr->cartridgeMenus[i]->popup(pos - QPoint(0, MediaMenu::ptr->cartridgeMenus[i]->sizeHint().height())); }); + connect((ClickableLabel *) d->cartridge[i].label.get(), &ClickableLabel::dropped, [i](QString str) { + MediaMenu::ptr->cartridgeMount(i, str); + }); d->cartridge[i].label->setToolTip(MediaMenu::ptr->cartridgeMenus[i]->title()); + d->cartridge[i].label->setAcceptDrops(true); sbar->addWidget(d->cartridge[i].label.get()); } } @@ -389,10 +503,15 @@ void MachineStatus::refresh(QStatusBar* sbar) { d->fdd[i].label = std::make_unique(); d->fdd[i].setEmpty(QString(floppyfns[i]).isEmpty()); d->fdd[i].setActive(false); - connect((ClickableLabel*)d->fdd[i].label.get(), &ClickableLabel::clicked, [this, i](QPoint pos) { + d->fdd[i].refresh(); + connect((ClickableLabel *) d->fdd[i].label.get(), &ClickableLabel::clicked, [i](QPoint pos) { MediaMenu::ptr->floppyMenus[i]->popup(pos - QPoint(0, MediaMenu::ptr->floppyMenus[i]->sizeHint().height())); }); + connect((ClickableLabel *) d->fdd[i].label.get(), &ClickableLabel::dropped, [i](QString str) { + MediaMenu::ptr->floppyMount(i, str, false); + }); d->fdd[i].label->setToolTip(MediaMenu::ptr->floppyMenus[i]->title()); + d->fdd[i].label->setAcceptDrops(true); sbar->addWidget(d->fdd[i].label.get()); }); @@ -400,10 +519,15 @@ void MachineStatus::refresh(QStatusBar* sbar) { d->cdrom[i].label = std::make_unique(); d->cdrom[i].setEmpty(cdrom[i].host_drive != 200 || QString(cdrom[i].image_path).isEmpty()); d->cdrom[i].setActive(false); - connect((ClickableLabel*)d->cdrom[i].label.get(), &ClickableLabel::clicked, [this, i](QPoint pos) { + d->cdrom[i].refresh(); + connect((ClickableLabel *) d->cdrom[i].label.get(), &ClickableLabel::clicked, [i](QPoint pos) { MediaMenu::ptr->cdromMenus[i]->popup(pos - QPoint(0, MediaMenu::ptr->cdromMenus[i]->sizeHint().height())); }); + connect((ClickableLabel *) d->cdrom[i].label.get(), &ClickableLabel::dropped, [i](QString str) { + MediaMenu::ptr->cdromMount(i, str); + }); d->cdrom[i].label->setToolTip(MediaMenu::ptr->cdromMenus[i]->title()); + d->cdrom[i].label->setAcceptDrops(true); sbar->addWidget(d->cdrom[i].label.get()); }); @@ -411,10 +535,15 @@ void MachineStatus::refresh(QStatusBar* sbar) { d->zip[i].label = std::make_unique(); d->zip[i].setEmpty(QString(zip_drives[i].image_path).isEmpty()); d->zip[i].setActive(false); - connect((ClickableLabel*)d->zip[i].label.get(), &ClickableLabel::clicked, [this, i](QPoint pos) { + d->zip[i].refresh(); + connect((ClickableLabel *) d->zip[i].label.get(), &ClickableLabel::clicked, [i](QPoint pos) { MediaMenu::ptr->zipMenus[i]->popup(pos - QPoint(0, MediaMenu::ptr->zipMenus[i]->sizeHint().height())); }); + connect((ClickableLabel *) d->zip[i].label.get(), &ClickableLabel::dropped, [i](QString str) { + MediaMenu::ptr->zipMount(i, str, false); + }); d->zip[i].label->setToolTip(MediaMenu::ptr->zipMenus[i]->title()); + d->zip[i].label->setAcceptDrops(true); sbar->addWidget(d->zip[i].label.get()); }); @@ -422,56 +551,71 @@ void MachineStatus::refresh(QStatusBar* sbar) { d->mo[i].label = std::make_unique(); d->mo[i].setEmpty(QString(mo_drives[i].image_path).isEmpty()); d->mo[i].setActive(false); - connect((ClickableLabel*)d->mo[i].label.get(), &ClickableLabel::clicked, [this, i](QPoint pos) { + d->mo[i].refresh(); + connect((ClickableLabel *) d->mo[i].label.get(), &ClickableLabel::clicked, [i](QPoint pos) { MediaMenu::ptr->moMenus[i]->popup(pos - QPoint(0, MediaMenu::ptr->moMenus[i]->sizeHint().height())); }); + connect((ClickableLabel *) d->mo[i].label.get(), &ClickableLabel::dropped, [i](QString str) { + MediaMenu::ptr->moMount(i, str, false); + }); d->mo[i].label->setToolTip(MediaMenu::ptr->moMenus[i]->title()); + d->mo[i].label->setAcceptDrops(true); sbar->addWidget(d->mo[i].label.get()); }); + iterateNIC([this, sbar](int i) { + d->net[i].label = std::make_unique(); + d->net[i].setEmpty(!network_is_connected(i)); + d->net[i].setActive(false); + d->net[i].refresh(); + d->net[i].label->setToolTip(MediaMenu::ptr->netMenus[i]->title()); + connect((ClickableLabel *) d->net[i].label.get(), &ClickableLabel::clicked, [i](QPoint pos) { + MediaMenu::ptr->netMenus[i]->popup(pos - QPoint(0, MediaMenu::ptr->netMenus[i]->sizeHint().height())); + }); + sbar->addWidget(d->net[i].label.get()); + }); + auto hdc_name = QString(hdc_get_internal_name(hdc_current)); if ((has_mfm || hdc_name.left(5) == QStringLiteral("st506")) && c_mfm > 0) { d->hdds[HDD_BUS_MFM].label = std::make_unique(); d->hdds[HDD_BUS_MFM].setActive(false); + d->hdds[HDD_BUS_MFM].refresh(); d->hdds[HDD_BUS_MFM].label->setToolTip(tr("Hard disk (%s)").replace("%s", "MFM/RLL")); sbar->addWidget(d->hdds[HDD_BUS_MFM].label.get()); } if ((has_esdi || hdc_name.left(4) == QStringLiteral("esdi")) && c_esdi > 0) { d->hdds[HDD_BUS_ESDI].label = std::make_unique(); d->hdds[HDD_BUS_ESDI].setActive(false); + d->hdds[HDD_BUS_ESDI].refresh(); d->hdds[HDD_BUS_ESDI].label->setToolTip(tr("Hard disk (%s)").replace("%s", "ESDI")); sbar->addWidget(d->hdds[HDD_BUS_ESDI].label.get()); } if ((has_xta || hdc_name.left(3) == QStringLiteral("xta")) && c_xta > 0) { d->hdds[HDD_BUS_XTA].label = std::make_unique(); d->hdds[HDD_BUS_XTA].setActive(false); + d->hdds[HDD_BUS_XTA].refresh(); d->hdds[HDD_BUS_XTA].label->setToolTip(tr("Hard disk (%s)").replace("%s", "XTA")); sbar->addWidget(d->hdds[HDD_BUS_XTA].label.get()); } if ((hasIDE() || hdc_name.left(5) == QStringLiteral("xtide") || hdc_name.left(3) == QStringLiteral("ide")) && c_ide > 0) { d->hdds[HDD_BUS_IDE].label = std::make_unique(); d->hdds[HDD_BUS_IDE].setActive(false); + d->hdds[HDD_BUS_IDE].refresh(); d->hdds[HDD_BUS_IDE].label->setToolTip(tr("Hard disk (%s)").replace("%s", "IDE")); sbar->addWidget(d->hdds[HDD_BUS_IDE].label.get()); } - if ((hasSCSI() || (scsi_card_current[0] != 0) || (scsi_card_current[1] != 0) || - (scsi_card_current[2] != 0) || (scsi_card_current[3] != 0)) && c_scsi > 0) { + if ((hasSCSI() || (scsi_card_current[0] != 0) || (scsi_card_current[1] != 0) || (scsi_card_current[2] != 0) || (scsi_card_current[3] != 0)) && c_scsi > 0) { d->hdds[HDD_BUS_SCSI].label = std::make_unique(); d->hdds[HDD_BUS_SCSI].setActive(false); + d->hdds[HDD_BUS_SCSI].refresh(); d->hdds[HDD_BUS_SCSI].label->setToolTip(tr("Hard disk (%s)").replace("%s", "SCSI")); sbar->addWidget(d->hdds[HDD_BUS_SCSI].label.get()); } - if (do_net) { - d->net.label = std::make_unique(); - d->net.setActive(false); - d->net.label->setToolTip(tr("Network")); - sbar->addWidget(d->net.label.get()); - } d->sound = std::make_unique(); d->sound->setPixmap(d->pixmaps.sound); - connect(d->sound.get(), &ClickableLabel::doubleClicked, d->sound.get(), [this](QPoint pos) { + connect(d->sound.get(), &ClickableLabel::doubleClicked, d->sound.get(), [](QPoint pos) { SoundGain gain(main_window); gain.exec(); }); @@ -481,110 +625,57 @@ void MachineStatus::refresh(QStatusBar* sbar) { sbar->addWidget(d->text.get()); } -void MachineStatus::setActivity(int tag, bool active) { - int category = tag & 0xfffffff0; - int item = tag & 0xf; - switch (category) { - case SB_CASSETTE: - break; - case SB_CARTRIDGE: - break; - case SB_FLOPPY: - d->fdd[item].setActive(active); - break; - case SB_CDROM: - d->cdrom[item].setActive(active); - break; - case SB_ZIP: - d->zip[item].setActive(active); - break; - case SB_MO: - d->mo[item].setActive(active); - break; - case SB_HDD: - d->hdds[item].setActive(active); - break; - case SB_NETWORK: - d->net.setActive(active); - break; - case SB_SOUND: - break; - case SB_TEXT: - break; - } -} - -void MachineStatus::setEmpty(int tag, bool empty) { - int category = tag & 0xfffffff0; - int item = tag & 0xf; - switch (category) { - case SB_CASSETTE: - d->cassette.setEmpty(empty); - break; - case SB_CARTRIDGE: - d->cartridge[item].setEmpty(empty); - break; - case SB_FLOPPY: - d->fdd[item].setEmpty(empty); - break; - case SB_CDROM: - d->cdrom[item].setEmpty(empty); - break; - case SB_ZIP: - d->zip[item].setEmpty(empty); - break; - case SB_MO: - d->mo[item].setEmpty(empty); - break; - case SB_HDD: - break; - case SB_NETWORK: - break; - case SB_SOUND: - break; - case SB_TEXT: - break; - } -} - -void MachineStatus::message(const QString &msg) { +void +MachineStatus::message(const QString &msg) +{ d->text->setText(msg); } -QString MachineStatus::getMessage() { +QString +MachineStatus::getMessage() +{ return d->text->text(); } -void MachineStatus::updateTip(int tag) +void +MachineStatus::updateTip(int tag) { int category = tag & 0xfffffff0; - int item = tag & 0xf; + int item = tag & 0xf; + if (!MediaMenu::ptr) + return; switch (category) { - case SB_CASSETTE: - d->cassette.label->setToolTip(MediaMenu::ptr->cassetteMenu->title()); - break; - case SB_CARTRIDGE: - d->cartridge[item].label->setToolTip(MediaMenu::ptr->cartridgeMenus[item]->title()); - break; - case SB_FLOPPY: - d->fdd[item].label->setToolTip(MediaMenu::ptr->floppyMenus[item]->title()); - break; - case SB_CDROM: - d->cdrom[item].label->setToolTip(MediaMenu::ptr->cdromMenus[item]->title()); - break; - case SB_ZIP: - d->zip[item].label->setToolTip(MediaMenu::ptr->zipMenus[item]->title()); - break; - case SB_MO: - d->mo[item].label->setToolTip(MediaMenu::ptr->moMenus[item]->title()); - break; - case SB_HDD: - break; - case SB_NETWORK: - break; - case SB_SOUND: - break; - case SB_TEXT: - break; + case SB_CASSETTE: + if (d->cassette.label && MediaMenu::ptr->cassetteMenu) + d->cassette.label->setToolTip(MediaMenu::ptr->cassetteMenu->title()); + break; + case SB_CARTRIDGE: + if (d->cartridge[item].label && MediaMenu::ptr->cartridgeMenus[item]) + d->cartridge[item].label->setToolTip(MediaMenu::ptr->cartridgeMenus[item]->title()); + break; + case SB_FLOPPY: + if (d->fdd[item].label && MediaMenu::ptr->floppyMenus[item]) + d->fdd[item].label->setToolTip(MediaMenu::ptr->floppyMenus[item]->title()); + break; + case SB_CDROM: + if (d->cdrom[item].label && MediaMenu::ptr->cdromMenus[item]) + d->cdrom[item].label->setToolTip(MediaMenu::ptr->cdromMenus[item]->title()); + break; + case SB_ZIP: + if (d->zip[item].label && MediaMenu::ptr->zipMenus[item]) + d->zip[item].label->setToolTip(MediaMenu::ptr->zipMenus[item]->title()); + break; + case SB_MO: + if (d->mo[item].label && MediaMenu::ptr->moMenus[item]) + d->mo[item].label->setToolTip(MediaMenu::ptr->moMenus[item]->title()); + break; + case SB_HDD: + break; + case SB_NETWORK: + break; + case SB_SOUND: + break; + case SB_TEXT: + break; } } diff --git a/src/qt/qt_machinestatus.hpp b/src/qt/qt_machinestatus.hpp index 6f83234df..cf706180d 100644 --- a/src/qt/qt_machinestatus.hpp +++ b/src/qt/qt_machinestatus.hpp @@ -4,6 +4,7 @@ #include #include #include +#include #include @@ -11,22 +12,48 @@ class QStatusBar; class ClickableLabel : public QLabel { Q_OBJECT; - public: - explicit ClickableLabel(QWidget* parent = nullptr) - : QLabel(parent) {} - ~ClickableLabel() {}; - signals: - void clicked(QPoint); - void doubleClicked(QPoint); +public: + explicit ClickableLabel(QWidget *parent = nullptr) + : QLabel(parent) + { + } + ~ClickableLabel() {}; - protected: - void mousePressEvent(QMouseEvent* event) override { emit clicked(event->globalPos()); } - void mouseDoubleClickEvent(QMouseEvent* event) override { emit doubleClicked(event->globalPos()); } +signals: + void clicked(QPoint); + void doubleClicked(QPoint); + void dropped(QString); + +protected: + void mousePressEvent(QMouseEvent *event) override { emit clicked(event->globalPos()); } + void mouseDoubleClickEvent(QMouseEvent *event) override { emit doubleClicked(event->globalPos()); } + void dragEnterEvent(QDragEnterEvent *event) override + { + if (event->mimeData()->hasUrls() && event->mimeData()->urls().size() == 1) { + event->setDropAction(Qt::CopyAction); + event->acceptProposedAction(); + } else + event->ignore(); + } + void dragMoveEvent(QDragMoveEvent *event) override + { + if (event->mimeData()->hasUrls() && event->mimeData()->urls().size() == 1) { + event->setDropAction(Qt::CopyAction); + event->acceptProposedAction(); + } else + event->ignore(); + } + void dropEvent(QDropEvent *event) override + { + if (event->dropAction() == Qt::CopyAction) { + emit dropped(event->mimeData()->urls()[0].toLocalFile()); + } else + event->ignore(); + } }; -class MachineStatus : public QObject -{ +class MachineStatus : public QObject { Q_OBJECT public: @@ -36,22 +63,24 @@ public: static bool hasCassette(); static bool hasIDE(); static bool hasSCSI(); - static void iterateFDD(const std::function& cb); - static void iterateCDROM(const std::function& cb); - static void iterateZIP(const std::function& cb); - static void iterateMO(const std::function& cb); + static void iterateFDD(const std::function &cb); + static void iterateCDROM(const std::function &cb); + static void iterateZIP(const std::function &cb); + static void iterateMO(const std::function &cb); + static void iterateNIC(const std::function &cb); QString getMessage(); + void clearActivity(); public slots: - void refresh(QStatusBar* sbar); - void setActivity(int tag, bool active); - void setEmpty(int tag, bool active); - void message(const QString& msg); + void refresh(QStatusBar *sbar); + void message(const QString &msg); void updateTip(int tag); + void refreshIcons(); private: struct States; std::unique_ptr d; + QTimer *refreshTimer; }; #endif // QT_MACHINESTATUS_HPP diff --git a/src/qt/qt_main.cpp b/src/qt/qt_main.cpp index cae6c6e5c..845ff705f 100644 --- a/src/qt/qt_main.cpp +++ b/src/qt/qt_main.cpp @@ -1,21 +1,21 @@ /* - * 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. + * 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. + * This file is part of the 86Box distribution. * - * Main entry point module + * Main entry point module * * - * Authors: Joakim L. Gilje + * Authors: Joakim L. Gilje * Cacodemon345 * Teemu Korhonen * - * Copyright 2021 Joakim L. Gilje - * Copyright 2021-2022 Cacodemon345 - * Copyright 2021-2022 Teemu Korhonen + * Copyright 2021 Joakim L. Gilje + * Copyright 2021-2022 Cacodemon345 + * Copyright 2021-2022 Teemu Korhonen */ #include #include @@ -28,32 +28,36 @@ #include #include #include +#include +#include #ifdef QT_STATIC /* Static builds need plugin imports */ -#include +# include Q_IMPORT_PLUGIN(QICOPlugin) -#ifdef Q_OS_WINDOWS +# ifdef Q_OS_WINDOWS Q_IMPORT_PLUGIN(QWindowsIntegrationPlugin) Q_IMPORT_PLUGIN(QWindowsVistaStylePlugin) -#endif +# endif #endif #ifdef Q_OS_WINDOWS -#include "qt_winrawinputfilter.hpp" -#include "qt_winmanagerfilter.hpp" -#include <86box/win.h> -#include +# include "qt_winrawinputfilter.hpp" +# include "qt_winmanagerfilter.hpp" +# include <86box/win.h> +# include #endif -extern "C" -{ +extern "C" { #include <86box/86box.h> #include <86box/config.h> #include <86box/plat.h> #include <86box/ui.h> #include <86box/video.h> -#include <86box/discord.h> +#ifdef DISCORD +# include <86box/discord.h> +#endif +#include <86box/gdbstub.h> } #include @@ -65,18 +69,18 @@ extern "C" #include "qt_settings.hpp" #include "cocoa_mouse.hpp" #include "qt_styleoverride.hpp" - +#include "qt_unixmanagerfilter.hpp" // Void Cast -#define VC(x) const_cast(x) +#define VC(x) const_cast(x) extern QElapsedTimer elapsed_timer; -extern MainWindow* main_window; +extern MainWindow *main_window; extern "C" { #include <86box/timer.h> #include <86box/nvr.h> - extern int qt_nvr_save(void); +extern int qt_nvr_save(void); } void qt_set_sequence_auto_mnemonic(bool b); @@ -84,18 +88,25 @@ void qt_set_sequence_auto_mnemonic(bool b); void main_thread_fn() { - uint64_t old_time, new_time; - int drawits, frames; + uint64_t old_time; + uint64_t new_time; + int drawits; + int frames; QThread::currentThread()->setPriority(QThread::HighestPriority); framecountx = 0; - //title_update = 1; + // title_update = 1; old_time = elapsed_timer.elapsed(); drawits = frames = 0; while (!is_quit && cpu_thread_run) { /* See if it is time to run a frame of code. */ new_time = elapsed_timer.elapsed(); - drawits += (new_time - old_time); +#ifdef USE_GDBSTUB + if (gdbstub_next_asap && (drawits <= 0)) + drawits = 10; + else +#endif + drawits += (new_time - old_time); old_time = new_time; if (drawits > 0 && !dopause) { /* Yes, so do one frame now. */ @@ -103,36 +114,48 @@ main_thread_fn() if (drawits > 50) drawits = 0; +#ifdef USE_INSTRUMENT + uint64_t start_time = elapsed_timer.nsecsElapsed(); +#endif /* Run a block of code. */ pc_run(); +#ifdef USE_INSTRUMENT + if (instru_enabled) { + uint64_t elapsed_us = (elapsed_timer.nsecsElapsed() - start_time) / 1000; + uint64_t total_elapsed_ms = (uint64_t) ((double) tsc / cpu_s->rspeed * 1000); + printf("[instrument] %llu, %llu\n", total_elapsed_ms, elapsed_us); + if (instru_run_ms && total_elapsed_ms >= instru_run_ms) + break; + } +#endif /* Every 200 frames we save the machine status. */ if (++frames >= 200 && nvr_dosave) { qt_nvr_save(); nvr_dosave = 0; - frames = 0; + frames = 0; } } else { /* Just so we dont overload the host OS. */ - if (drawits < -1) - std::this_thread::sleep_for(std::chrono::milliseconds(1)); - else - std::this_thread::yield(); - } - - /* If needed, handle a screen resize. */ - if (!atomic_flag_test_and_set(&doresize) && !video_fullscreen && !is_quit) { - if (vid_resize & 2) - plat_resize(fixed_size_x, fixed_size_y); - else - plat_resize(scrnsz_x, scrnsz_y); + if (dopause) + ack_pause(); + std::this_thread::sleep_for(std::chrono::milliseconds(1)); } } is_quit = 1; + if (gfxcard[1]) { + ui_deinit_monitor(1); + std::this_thread::sleep_for(std::chrono::milliseconds(500)); + } + QTimer::singleShot(0, QApplication::instance(), []() { QApplication::processEvents(); QApplication::instance()->quit(); }); } -int main(int argc, char* argv[]) { +static std::thread *main_thread; + +int +main(int argc, char *argv[]) +{ #if QT_VERSION < QT_VERSION_CHECK(6, 0, 0) QApplication::setAttribute(Qt::AA_DisableHighDpiScaling, false); QApplication::setAttribute(Qt::AA_UseHighDpiPixmaps); @@ -158,10 +181,12 @@ int main(int argc, char* argv[]) { #endif elapsed_timer.start(); - if (!pc_init(argc, argv)) - { + if (!pc_init(argc, argv)) { return 0; } + + bool startMaximized = window_remember && monitor_settings[0].mon_window_maximized; + fprintf(stderr, "Qt: version %s, platform \"%s\"\n", qVersion(), QApplication::platformName().toUtf8().data()); ProgSettings::loadTranslators(&app); #ifdef Q_OS_WINDOWS auto font_name = QObject::tr("FONT_NAME"); @@ -169,47 +194,63 @@ int main(int argc, char* argv[]) { QApplication::setFont(QFont(font_name, font_size.toInt())); SetCurrentProcessExplicitAppUserModelID(L"86Box.86Box"); #endif - if (! pc_init_modules()) { - ui_msgbox_header(MBX_FATAL, (void*)IDS_2120, (void*)IDS_2056); + if (!pc_init_modules()) { + ui_msgbox_header(MBX_FATAL, (void *) IDS_2121, (void *) IDS_2056); return 6; } - if (settings_only) - { + if (settings_only) { Settings settings; - if (settings.exec() == QDialog::Accepted) - { + if (settings.exec() == QDialog::Accepted) { settings.save(); config_save(); } return 0; } + /* Warn the user about unsupported configs */ + if (cpu_override) { + QMessageBox warningbox(QMessageBox::Icon::Warning, QObject::tr("You are loading an unsupported configuration"), + QObject::tr("CPU type filtering based on selected machine is disabled for this emulated machine.\n\nThis makes it possible to choose a CPU that is otherwise incompatible with the selected machine. However, you may run into incompatibilities with the machine BIOS or other software.\n\nEnabling this setting is not officially supported and any bug reports filed may be closed as invalid."), + QMessageBox::NoButton); + warningbox.addButton(QObject::tr("Continue"), QMessageBox::AcceptRole); + warningbox.addButton(QObject::tr("Exit"), QMessageBox::RejectRole); + warningbox.exec(); + if (warningbox.result() == QDialog::Accepted) + return 0; + } + +#ifdef DISCORD discord_load(); +#endif main_window = new MainWindow(); - main_window->show(); + if (startMaximized) { + main_window->showMaximized(); + } else { + main_window->show(); + } + app.installEventFilter(main_window); #ifdef Q_OS_WINDOWS /* Setup VM-manager messages */ std::unique_ptr wmfilter; - if (source_hwnd) - { - HWND main_hwnd = (HWND)main_window->winId(); + if (source_hwnd) { + HWND main_hwnd = (HWND) main_window->winId(); wmfilter.reset(new WindowsManagerFilter()); QObject::connect(wmfilter.get(), &WindowsManagerFilter::showsettings, main_window, &MainWindow::showSettings); QObject::connect(wmfilter.get(), &WindowsManagerFilter::pause, main_window, &MainWindow::togglePause); QObject::connect(wmfilter.get(), &WindowsManagerFilter::reset, main_window, &MainWindow::hardReset); QObject::connect(wmfilter.get(), &WindowsManagerFilter::request_shutdown, main_window, &MainWindow::close); - QObject::connect(wmfilter.get(), &WindowsManagerFilter::force_shutdown, [](){ + QObject::connect(wmfilter.get(), &WindowsManagerFilter::force_shutdown, []() { do_stop(); emit main_window->close(); }); - QObject::connect(wmfilter.get(), &WindowsManagerFilter::ctrlaltdel, [](){ pc_send_cad(); }); - QObject::connect(wmfilter.get(), &WindowsManagerFilter::dialogstatus, [main_hwnd](bool open){ - PostMessage((HWND)(uintptr_t)source_hwnd, WM_SENDDLGSTATUS, (WPARAM)(open ? 1 : 0), (LPARAM)main_hwnd); + QObject::connect(wmfilter.get(), &WindowsManagerFilter::ctrlaltdel, []() { pc_send_cad(); }); + QObject::connect(wmfilter.get(), &WindowsManagerFilter::dialogstatus, [main_hwnd](bool open) { + PostMessage((HWND) (uintptr_t) source_hwnd, WM_SENDDLGSTATUS, (WPARAM) (open ? 1 : 0), (LPARAM) main_hwnd); }); /* Native filter to catch VM-managers commands */ @@ -219,36 +260,50 @@ int main(int argc, char* argv[]) { main_window->installEventFilter(wmfilter.get()); /* Send main window HWND to manager */ - PostMessage((HWND)(uintptr_t)source_hwnd, WM_SENDHWND, (WPARAM)unique_id, (LPARAM)main_hwnd); + PostMessage((HWND) (uintptr_t) source_hwnd, WM_SENDHWND, (WPARAM) unique_id, (LPARAM) main_hwnd); /* Send shutdown message to manager */ - QObject::connect(&app, &QApplication::destroyed, [main_hwnd](QObject*) { - PostMessage((HWND)(uintptr_t)source_hwnd, WM_HAS_SHUTDOWN, (WPARAM)0, (LPARAM)main_hwnd); + QObject::connect(&app, &QApplication::destroyed, [main_hwnd](QObject *) { + PostMessage((HWND) (uintptr_t) source_hwnd, WM_HAS_SHUTDOWN, (WPARAM) 0, (LPARAM) main_hwnd); }); } /* Setup raw input */ auto rawInputFilter = WindowsRawInputFilter::Register(main_window); - if (rawInputFilter) - { + if (rawInputFilter) { app.installNativeEventFilter(rawInputFilter.get()); - QObject::disconnect(main_window, &MainWindow::pollMouse, 0, 0); - QObject::connect(main_window, &MainWindow::pollMouse, (WindowsRawInputFilter*)rawInputFilter.get(), &WindowsRawInputFilter::mousePoll, Qt::DirectConnection); main_window->setSendKeyboardInput(false); - } + } #endif - pc_reset_hard_init(); + UnixManagerSocket socket; + if (qgetenv("86BOX_MANAGER_SOCKET").size()) { + QObject::connect(&socket, &UnixManagerSocket::showsettings, main_window, &MainWindow::showSettings); + QObject::connect(&socket, &UnixManagerSocket::pause, main_window, &MainWindow::togglePause); + QObject::connect(&socket, &UnixManagerSocket::resetVM, main_window, &MainWindow::hardReset); + QObject::connect(&socket, &UnixManagerSocket::request_shutdown, main_window, &MainWindow::close); + QObject::connect(&socket, &UnixManagerSocket::force_shutdown, []() { + do_stop(); + emit main_window->close(); + }); + QObject::connect(&socket, &UnixManagerSocket::ctrlaltdel, []() { pc_send_cad(); }); + main_window->installEventFilter(&socket); + socket.connectToServer(qgetenv("86BOX_MANAGER_SOCKET")); + } + + // pc_reset_hard_init(); /* Set the PAUSE mode depending on the renderer. */ // plat_pause(0); QTimer onesec; - QTimer discordupdate; QObject::connect(&onesec, &QTimer::timeout, &app, [] { pc_onesec(); }); onesec.setTimerType(Qt::PreciseTimer); onesec.start(1000); + +#ifdef DISCORD + QTimer discordupdate; if (discord_loaded) { QTimer::singleShot(1000, &app, [] { if (enable_discord) { @@ -260,17 +315,22 @@ int main(int argc, char* argv[]) { QObject::connect(&discordupdate, &QTimer::timeout, &app, [] { discord_run_callbacks(); }); - discordupdate.start(0); + discordupdate.start(1000); } +#endif /* Initialize the rendering window, or fullscreen. */ - auto main_thread = std::thread([] { - main_thread_fn(); + QTimer::singleShot(0, &app, [] { + pc_reset_hard_init(); + main_thread = new std::thread(main_thread_fn); }); - auto ret = app.exec(); + auto ret = app.exec(); cpu_thread_run = 0; - main_thread.join(); + main_thread->join(); + pc_close(nullptr); + endblit(); + socket.close(); return ret; } diff --git a/src/qt/qt_mainwindow.cpp b/src/qt/qt_mainwindow.cpp index 134efb6b4..4b849edd6 100644 --- a/src/qt/qt_mainwindow.cpp +++ b/src/qt/qt_mainwindow.cpp @@ -1,31 +1,34 @@ /* - * 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. + * 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. + * This file is part of the 86Box distribution. * - * Main window module. + * Main window module. * * * - * Authors: Joakim L. Gilje + * Authors: Joakim L. Gilje * Cacodemon345 * Teemu Korhonen * dob205 * - * Copyright 2021 Joakim L. Gilje - * Copyright 2021-2022 Cacodemon345 - * Copyright 2021-2022 Teemu Korhonen - * Copyright 2022 dob205 + * Copyright 2021 Joakim L. Gilje + * Copyright 2021-2022 Cacodemon345 + * Copyright 2021-2022 Teemu Korhonen + * Copyright 2022 dob205 */ +#include + #include "qt_mainwindow.hpp" #include "ui_qt_mainwindow.h" #include "qt_specifydimensions.h" #include "qt_soundgain.hpp" #include "qt_progsettings.hpp" +#include "qt_mcadevicelist.hpp" #include "qt_rendererstack.hpp" #include "qt_renderercommon.hpp" @@ -35,15 +38,30 @@ extern "C" { #include <86box/config.h> #include <86box/keyboard.h> #include <86box/plat.h> -#include <86box/discord.h> +#include <86box/ui.h> +#ifdef DISCORD +# include <86box/discord.h> +#endif +#include <86box/device.h> #include <86box/video.h> +#include <86box/mouse.h> +#include <86box/machine.h> #include <86box/vid_ega.h> #include <86box/version.h> +#if 0 +#include <86box/acpi.h> /* Requires timer.h include, which conflicts with Qt headers */ +#endif +extern atomic_int acpi_pwrbut_pressed; +extern int acpi_enabled; - extern int qt_nvr_save(void); +#ifdef USE_VNC +# include <86box/vnc.h> +#endif + +extern int qt_nvr_save(void); #ifdef MTR_ENABLED -#include +# include #endif }; @@ -52,17 +70,25 @@ extern "C" { #include #include #include +#include #include #include #include #include #include #include +#include #include #include #include #include #include +#include +#include +#if QT_CONFIG(vulkan) +# include +# include +#endif #include #include @@ -72,34 +98,92 @@ extern "C" { #include "qt_mediamenu.hpp" #include "qt_util.hpp" -#ifdef __unix__ -#ifdef WAYLAND -#include "wl_mouse.hpp" -#endif -#include -#include -#undef KeyPress -#undef KeyRelease +#if defined __unix__ && !defined __HAIKU__ +# ifndef Q_OS_MACOS +# include "evdev_keyboard.hpp" +# endif +# ifdef XKBCOMMON +# include "xkbcommon_keyboard.hpp" +# ifdef XKBCOMMON_X11 +# include "xkbcommon_x11_keyboard.hpp" +# endif +# ifdef WAYLAND +# include "xkbcommon_wl_keyboard.hpp" +# endif +# endif +# include +# include +# undef KeyPress +# undef KeyRelease #endif -extern void qt_mouse_capture(int); -extern "C" void qt_blit(int x, int y, int w, int h); +#ifdef Q_OS_MACOS +# include "cocoa_keyboard.hpp" +// The namespace is required to avoid clashing typedefs; we only use this +// header for its #defines anyway. +namespace IOKit { +# include +} +#endif -MainWindow::MainWindow(QWidget *parent) : - QMainWindow(parent), - ui(new Ui::MainWindow) +#ifdef __HAIKU__ +# include +# include +# include "be_keyboard.hpp" + +extern MainWindow *main_window; + +filter_result +keyb_filter(BMessage *message, BHandler **target, BMessageFilter *filter) { - mm = std::make_shared(this); - MediaMenu::ptr = mm; - status = std::make_unique(this); + if (message->what == B_KEY_DOWN || message->what == B_KEY_UP + || message->what == B_UNMAPPED_KEY_DOWN || message->what == B_UNMAPPED_KEY_UP) { + int key_state = 0, key_scancode = 0; + key_state = message->what == B_KEY_DOWN || message->what == B_UNMAPPED_KEY_DOWN; + message->FindInt32("key", &key_scancode); + QGuiApplication::postEvent(main_window, new QKeyEvent(key_state ? QEvent::KeyPress : QEvent::KeyRelease, 0, QGuiApplication::keyboardModifiers(), key_scancode, 0, 0)); + if (key_scancode == 0x68 && key_state) { + QGuiApplication::postEvent(main_window, new QKeyEvent(QEvent::KeyRelease, 0, QGuiApplication::keyboardModifiers(), key_scancode, 0, 0)); + } + } + return B_DISPATCH_MESSAGE; +} +static BMessageFilter *filter; +#endif + +std::atomic blitDummied { false }; + +extern void qt_mouse_capture(int); +extern "C" void qt_blit(int x, int y, int w, int h, int monitor_index); + +extern MainWindow *main_window; + +MainWindow::MainWindow(QWidget *parent) + : QMainWindow(parent) + , ui(new Ui::MainWindow) +{ + mm = std::make_shared(this); + MediaMenu::ptr = mm; + status = std::make_unique(this); + +#ifdef __HAIKU__ + filter = new BMessageFilter(B_PROGRAMMED_DELIVERY, B_ANY_SOURCE, keyb_filter); + ((BWindow *) this->winId())->AddFilter(filter); +#endif setUnifiedTitleAndToolBarOnMac(true); + extern MainWindow *main_window; + main_window = this; ui->setupUi(this); ui->stackedWidget->setMouseTracking(true); statusBar()->setVisible(!hide_status_bar); statusBar()->setStyleSheet("QStatusBar::item {border: None; } QStatusBar QLabel { margin-right: 2px; margin-bottom: 1px; }"); + this->centralWidget()->setStyleSheet("background-color: black;"); ui->toolBar->setVisible(!hide_tool_bar); - +#ifdef _WIN32 + ui->toolBar->setBackgroundRole(QPalette::Light); +#endif + renderers[0].reset(nullptr); auto toolbar_spacer = new QWidget(); toolbar_spacer->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding); ui->toolBar->addWidget(toolbar_spacer); @@ -120,14 +204,24 @@ MainWindow::MainWindow(QWidget *parent) : this->setWindowFlag(Qt::WindowMaximizeButtonHint, vid_resize == 1); QString vmname(vm_name); - if (vmname.at(vmname.size() - 1) == '"' || vmname.at(vmname.size() - 1) == '\'') vmname.truncate(vmname.size() - 1); + if (vmname.at(vmname.size() - 1) == '"' || vmname.at(vmname.size() - 1) == '\'') + vmname.truncate(vmname.size() - 1); this->setWindowTitle(QString("%1 - %2 %3").arg(vmname, EMU_NAME, EMU_VERSION_FULL)); + connect(this, &MainWindow::hardResetCompleted, this, [this]() { + ui->actionMCA_devices->setVisible(machine_has_bus(machine, MACHINE_BUS_MCA)); + QApplication::setOverrideCursor(Qt::ArrowCursor); +#ifdef USE_WACOM + ui->menuTablet_tool->menuAction()->setVisible(mouse_input_mode >= 1); +#else + ui->menuTablet_tool->menuAction()->setVisible(false); +#endif + }); + connect(this, &MainWindow::showMessageForNonQtThread, this, &MainWindow::showMessage_, Qt::BlockingQueuedConnection); - connect(this, &MainWindow::setTitle, this, [this,toolbar_label](const QString& title) { - if (dopause && !hide_tool_bar) - { + connect(this, &MainWindow::setTitle, this, [this, toolbar_label](const QString &title) { + if (dopause && !hide_tool_bar) { toolbar_label->setText(toolbar_label->text() + tr(" - PAUSED")); return; } @@ -146,7 +240,8 @@ MainWindow::MainWindow(QWidget *parent) : } } #endif - ui->actionPause->setChecked(dopause); + ui->actionPause->setChecked(false); + ui->actionPause->setCheckable(false); }); connect(this, &MainWindow::getTitleForNonQtThread, this, &MainWindow::getTitle_, Qt::BlockingQueuedConnection); @@ -162,47 +257,73 @@ MainWindow::MainWindow(QWidget *parent) : emit updateMenuResizeOptions(); - connect(this, &MainWindow::pollMouse, ui->stackedWidget, &RendererStack::mousePoll, Qt::DirectConnection); - connect(this, &MainWindow::setMouseCapture, this, [this](bool state) { mouse_capture = state ? 1 : 0; qt_mouse_capture(mouse_capture); if (mouse_capture) { this->grabKeyboard(); -#ifdef WAYLAND - if (QGuiApplication::platformName().contains("wayland")) { - wl_mouse_capture(this->windowHandle()); - } -#endif + if (ui->stackedWidget->mouse_capture_func) + ui->stackedWidget->mouse_capture_func(this->windowHandle()); } else { this->releaseKeyboard(); -#ifdef WAYLAND - if (QGuiApplication::platformName().contains("wayland")) { - wl_mouse_uncapture(); + if (ui->stackedWidget->mouse_uncapture_func) + ui->stackedWidget->mouse_uncapture_func(); + } + }); + + connect(qApp, &QGuiApplication::applicationStateChanged, [this](Qt::ApplicationState state) { + if (state == Qt::ApplicationState::ApplicationActive) { + if (auto_paused) { + plat_pause(0); + auto_paused = 0; + } + } else { + if (mouse_capture) + emit setMouseCapture(false); + + if (do_auto_pause && !dopause) { + auto_paused = 1; + plat_pause(1); } -#endif } }); connect(this, &MainWindow::resizeContents, this, [this](int w, int h) { - if (!QApplication::platformName().contains("eglfs") && vid_resize == 0) { - w = qRound(w / (!dpi_scale ? util::screenOfWidget(this)->devicePixelRatio() : 1.)); + if (shownonce) { + if (resizableonce == false) + ui->stackedWidget->setFixedSize(QWIDGETSIZE_MAX, QWIDGETSIZE_MAX); + resizableonce = true; + } + if (!QApplication::platformName().contains("eglfs") && vid_resize != 1) { + w = (w / (!dpi_scale ? util::screenOfWidget(this)->devicePixelRatio() : 1.)); - int modifiedHeight = qRound(h / (!dpi_scale ? util::screenOfWidget(this)->devicePixelRatio() : 1.)) + int modifiedHeight = (h / (!dpi_scale ? util::screenOfWidget(this)->devicePixelRatio() : 1.)) + menuBar()->height() + (statusBar()->height() * !hide_status_bar) + (ui->toolBar->height() * !hide_tool_bar); - ui->stackedWidget->resize(w, h); + ui->stackedWidget->resize(w, (h / (!dpi_scale ? util::screenOfWidget(this)->devicePixelRatio() : 1.))); setFixedSize(w, modifiedHeight); } }); + connect(this, &MainWindow::resizeContentsMonitor, this, [this](int w, int h, int monitor_index) { + if (!QApplication::platformName().contains("eglfs") && vid_resize != 1) { +#ifdef QT_RESIZE_DEBUG + qDebug() << "Resize"; +#endif + w = (w / (!dpi_scale ? util::screenOfWidget(renderers[monitor_index].get())->devicePixelRatio() : 1.)); + + int modifiedHeight = (h / (!dpi_scale ? util::screenOfWidget(renderers[monitor_index].get())->devicePixelRatio() : 1.)); + + renderers[monitor_index]->setFixedSize(w, modifiedHeight); + } + }); + connect(ui->menubar, &QMenuBar::triggered, this, [this] { config_save(); - if (QApplication::activeWindow() == this) - { - ui->stackedWidget->current->setFocus(); + if (QApplication::activeWindow() == this) { + ui->stackedWidget->setFocusRenderer(); } }); @@ -211,9 +332,7 @@ MainWindow::MainWindow(QWidget *parent) : }); connect(this, &MainWindow::updateStatusBarPanes, this, &MainWindow::refreshMediaMenu); connect(this, &MainWindow::updateStatusBarTip, status.get(), &MachineStatus::updateTip); - connect(this, &MainWindow::updateStatusBarActivity, status.get(), &MachineStatus::setActivity); - connect(this, &MainWindow::updateStatusBarEmpty, status.get(), &MachineStatus::setEmpty); - connect(this, &MainWindow::statusBarMessage, status.get(), &MachineStatus::message); + connect(this, &MainWindow::statusBarMessage, status.get(), &MachineStatus::message, Qt::QueuedConnection); ui->actionKeyboard_requires_capture->setChecked(kbd_req_capture); ui->actionRight_CTRL_is_left_ALT->setChecked(rctrl_is_lalt); @@ -223,109 +342,237 @@ MainWindow::MainWindow(QWidget *parent) : ui->actionHiDPI_scaling->setChecked(dpi_scale); ui->actionHide_status_bar->setChecked(hide_status_bar); ui->actionHide_tool_bar->setChecked(hide_tool_bar); + ui->actionShow_non_primary_monitors->setChecked(show_second_monitors); ui->actionUpdate_status_bar_icons->setChecked(update_icons); ui->actionEnable_Discord_integration->setChecked(enable_discord); + ui->actionApply_fullscreen_stretch_mode_when_maximized->setChecked(video_fullscreen_scale_maximized); ui->actionShow_status_icons_in_fullscreen->setChecked(status_icons_fullscreen); +#ifndef DISCORD + ui->actionEnable_Discord_integration->setVisible(false); +#else + ui->actionEnable_Discord_integration->setEnabled(discord_loaded); +#endif + #if defined Q_OS_WINDOWS || defined Q_OS_MACOS /* Make the option visible only if ANGLE is loaded. */ ui->actionHardware_Renderer_OpenGL_ES->setVisible(QOpenGLContext::openGLModuleType() == QOpenGLContext::LibGLES); - if (QOpenGLContext::openGLModuleType() != QOpenGLContext::LibGLES && vid_api == 2) vid_api = 1; + if (QOpenGLContext::openGLModuleType() != QOpenGLContext::LibGLES && vid_api == 2) + vid_api = 1; +#endif + ui->actionHardware_Renderer_OpenGL->setVisible(QOpenGLContext::openGLModuleType() != QOpenGLContext::LibGLES); + if (QOpenGLContext::openGLModuleType() == QOpenGLContext::LibGLES && vid_api == 1) + vid_api = 0; + + if ((QApplication::platformName().contains("eglfs") || QApplication::platformName() == "haiku")) { + if (vid_api >= 1) + fprintf(stderr, "OpenGL renderers are unsupported on %s.\n", QApplication::platformName().toUtf8().data()); + vid_api = 0; + ui->actionHardware_Renderer_OpenGL->setVisible(false); + ui->actionHardware_Renderer_OpenGL_ES->setVisible(false); + ui->actionVulkan->setVisible(false); + ui->actionOpenGL_3_0_Core->setVisible(false); + } +#if !defined Q_OS_WINDOWS + ui->actionDirect3D_9->setVisible(false); + if (vid_api == 5) + vid_api = 0; #endif - if (QApplication::platformName().contains("eglfs") && vid_api >= 1) { - fprintf(stderr, "OpenGL renderers are unsupported on EGLFS.\n"); +#ifndef USE_VNC + if (vid_api == 6) vid_api = 0; + ui->actionVNC->setVisible(false); +#endif + +#if QT_CONFIG(vulkan) + bool vulkanAvailable = false; + { + QVulkanInstance instance; + instance.setApiVersion(QVersionNumber(1, 0)); + if (instance.create()) { + uint32_t physicalDevices = 0; + instance.functions()->vkEnumeratePhysicalDevices(instance.vkInstance(), &physicalDevices, nullptr); + if (physicalDevices != 0) { + vulkanAvailable = true; + } + } } - QActionGroup* actGroup = nullptr; - switch (vid_api) { - case 0: - ui->stackedWidget->switchRenderer(RendererStack::Renderer::Software); - ui->actionSoftware_Renderer->setChecked(true); - break; - case 1: - ui->stackedWidget->switchRenderer(RendererStack::Renderer::OpenGL); - ui->actionHardware_Renderer_OpenGL->setChecked(true); - break; - case 2: - ui->stackedWidget->switchRenderer(RendererStack::Renderer::OpenGLES); - ui->actionHardware_Renderer_OpenGL_ES->setChecked(true); - break; - case 3: - ui->stackedWidget->switchRenderer(RendererStack::Renderer::OpenGL3); - ui->actionOpenGL_3_0_Core->setChecked(true); - break; + if (!vulkanAvailable) +#endif + { + if (vid_api == 4) + vid_api = 0; + ui->actionVulkan->setVisible(false); } + + QActionGroup *actGroup = nullptr; + actGroup = new QActionGroup(this); actGroup->addAction(ui->actionSoftware_Renderer); actGroup->addAction(ui->actionHardware_Renderer_OpenGL); actGroup->addAction(ui->actionHardware_Renderer_OpenGL_ES); actGroup->addAction(ui->actionOpenGL_3_0_Core); + actGroup->addAction(ui->actionVulkan); + actGroup->addAction(ui->actionDirect3D_9); + actGroup->addAction(ui->actionVNC); + actGroup->setExclusive(true); + + connect(actGroup, &QActionGroup::triggered, [this](QAction *action) { + vid_api = action->property("vid_api").toInt(); +#ifdef USE_VNC + if (vnc_enabled && vid_api != 6) { + startblit(); + vnc_enabled = 0; + vnc_close(); + video_setblit(qt_blit); + endblit(); + } +#endif + RendererStack::Renderer newVidApi = RendererStack::Renderer::Software; + switch (vid_api) { + case 0: + newVidApi = RendererStack::Renderer::Software; + break; + case 1: + newVidApi = RendererStack::Renderer::OpenGL; + break; + case 2: + newVidApi = RendererStack::Renderer::OpenGLES; + break; + case 3: + newVidApi = RendererStack::Renderer::OpenGL3; + break; + case 4: + newVidApi = RendererStack::Renderer::Vulkan; + break; + case 5: + newVidApi = RendererStack::Renderer::Direct3D9; + break; +#ifdef USE_VNC + case 6: + { + newVidApi = RendererStack::Renderer::Software; + startblit(); + vnc_enabled = vnc_init(nullptr); + endblit(); + } +#endif + } + ui->stackedWidget->switchRenderer(newVidApi); + if (!show_second_monitors) + return; + for (int i = 1; i < MONITORS_NUM; i++) { + if (renderers[i]) + renderers[i]->switchRenderer(newVidApi); + } + }); + + connect(ui->stackedWidget, &RendererStack::rendererChanged, [this]() { + ui->actionRenderer_options->setVisible(ui->stackedWidget->hasOptions()); + }); + + /* Trigger initial renderer switch */ + for (auto action : actGroup->actions()) + if (action->property("vid_api").toInt() == vid_api) { + action->setChecked(true); + emit actGroup->triggered(action); + break; + } + switch (scale) { - case 0: - ui->action0_5x->setChecked(true); - break; - case 1: - ui->action1x->setChecked(true); - break; - case 2: - ui->action1_5x->setChecked(true); - break; - case 3: - ui->action2x->setChecked(true); - break; + case 0: + ui->action0_5x->setChecked(true); + break; + case 1: + ui->action1x->setChecked(true); + break; + case 2: + ui->action1_5x->setChecked(true); + break; + case 3: + ui->action2x->setChecked(true); + break; + case 4: + ui->action3x->setChecked(true); + break; + case 5: + ui->action4x->setChecked(true); + break; + case 6: + ui->action5x->setChecked(true); + break; + case 7: + ui->action6x->setChecked(true); + break; + case 8: + ui->action7x->setChecked(true); + break; + case 9: + ui->action8x->setChecked(true); + break; } actGroup = new QActionGroup(this); actGroup->addAction(ui->action0_5x); actGroup->addAction(ui->action1x); actGroup->addAction(ui->action1_5x); actGroup->addAction(ui->action2x); + actGroup->addAction(ui->action3x); + actGroup->addAction(ui->action4x); + actGroup->addAction(ui->action5x); + actGroup->addAction(ui->action6x); + actGroup->addAction(ui->action7x); + actGroup->addAction(ui->action8x); switch (video_filter_method) { - case 0: - ui->actionNearest->setChecked(true); - break; - case 1: - ui->actionLinear->setChecked(true); - break; + case 0: + ui->actionNearest->setChecked(true); + break; + case 1: + ui->actionLinear->setChecked(true); + break; } actGroup = new QActionGroup(this); actGroup->addAction(ui->actionNearest); actGroup->addAction(ui->actionLinear); switch (video_fullscreen_scale) { - case FULLSCR_SCALE_FULL: - ui->actionFullScreen_stretch->setChecked(true); - break; - case FULLSCR_SCALE_43: - ui->actionFullScreen_43->setChecked(true); - break; - case FULLSCR_SCALE_KEEPRATIO: - ui->actionFullScreen_keepRatio->setChecked(true); - break; - case FULLSCR_SCALE_INT: - ui->actionFullScreen_int->setChecked(true); - break; + case FULLSCR_SCALE_FULL: + ui->actionFullScreen_stretch->setChecked(true); + break; + case FULLSCR_SCALE_43: + ui->actionFullScreen_43->setChecked(true); + break; + case FULLSCR_SCALE_KEEPRATIO: + ui->actionFullScreen_keepRatio->setChecked(true); + break; + case FULLSCR_SCALE_INT: + ui->actionFullScreen_int->setChecked(true); + break; + case FULLSCR_SCALE_INT43: + ui->actionFullScreen_int43->setChecked(true); + break; } actGroup = new QActionGroup(this); actGroup->addAction(ui->actionFullScreen_stretch); actGroup->addAction(ui->actionFullScreen_43); actGroup->addAction(ui->actionFullScreen_keepRatio); actGroup->addAction(ui->actionFullScreen_int); + actGroup->addAction(ui->actionFullScreen_int43); switch (video_grayscale) { - case 0: - ui->actionRGB_Color->setChecked(true); - break; - case 1: - ui->actionRGB_Grayscale->setChecked(true); - break; - case 2: - ui->actionAmber_monitor->setChecked(true); - break; - case 3: - ui->actionGreen_monitor->setChecked(true); - break; - case 4: - ui->actionWhite_monitor->setChecked(true); - break; + case 0: + ui->actionRGB_Color->setChecked(true); + break; + case 1: + ui->actionRGB_Grayscale->setChecked(true); + break; + case 2: + ui->actionAmber_monitor->setChecked(true); + break; + case 3: + ui->actionGreen_monitor->setChecked(true); + break; + case 4: + ui->actionWhite_monitor->setChecked(true); + break; } actGroup = new QActionGroup(this); actGroup->addAction(ui->actionRGB_Grayscale); @@ -334,15 +581,15 @@ MainWindow::MainWindow(QWidget *parent) : actGroup->addAction(ui->actionWhite_monitor); actGroup->addAction(ui->actionRGB_Color); switch (video_graytype) { - case 0: - ui->actionBT601_NTSC_PAL->setChecked(true); - break; - case 1: - ui->actionBT709_HDTV->setChecked(true); - break; - case 2: - ui->actionAverage->setChecked(true); - break; + case 0: + ui->actionBT601_NTSC_PAL->setChecked(true); + break; + case 1: + ui->actionBT709_HDTV->setChecked(true); + break; + case 2: + ui->actionAverage->setChecked(true); + break; } actGroup = new QActionGroup(this); actGroup->addAction(ui->actionBT601_NTSC_PAL); @@ -357,22 +604,16 @@ MainWindow::MainWindow(QWidget *parent) : if (vid_cga_contrast > 0) { ui->actionChange_contrast_for_monochrome_display->setChecked(true); } + if (do_auto_pause > 0) { + ui->actionAuto_pause->setChecked(true); + } #ifdef Q_OS_MACOS - ui->actionFullscreen->setShortcutVisibleInContextMenu(true); ui->actionCtrl_Alt_Del->setShortcutVisibleInContextMenu(true); ui->actionTake_screenshot->setShortcutVisibleInContextMenu(true); #endif - video_setblit(qt_blit); - - if (start_in_fullscreen) { - connect(ui->stackedWidget, &RendererStack::blitToRenderer, this, [this] () { - if (start_in_fullscreen) { - QTimer::singleShot(100, ui->actionFullscreen, &QAction::trigger); - start_in_fullscreen = 0; - } - }); - } + if (!vnc_enabled) + video_setblit(qt_blit); #ifdef MTR_ENABLED { @@ -381,32 +622,30 @@ MainWindow::MainWindow(QWidget *parent) : ui->actionBegin_trace->setShortcut(QKeySequence(Qt::Key_Control + Qt::Key_T)); ui->actionEnd_trace->setShortcut(QKeySequence(Qt::Key_Control + Qt::Key_T)); ui->actionEnd_trace->setDisabled(true); - static auto init_trace = [&] - { + static auto init_trace = [&] { mtr_init("trace.json"); mtr_start(); }; - static auto shutdown_trace = [&] - { + static auto shutdown_trace = [&] { mtr_stop(); mtr_shutdown(); }; -#ifdef Q_OS_MACOS +# ifdef Q_OS_MACOS ui->actionBegin_trace->setShortcutVisibleInContextMenu(true); ui->actionEnd_trace->setShortcutVisibleInContextMenu(true); -#endif +# endif static bool trace = false; - connect(ui->actionBegin_trace, &QAction::triggered, this, [this] - { - if (trace) return; + connect(ui->actionBegin_trace, &QAction::triggered, this, [this] { + if (trace) + return; ui->actionBegin_trace->setDisabled(true); ui->actionEnd_trace->setDisabled(false); init_trace(); trace = true; }); - connect(ui->actionEnd_trace, &QAction::triggered, this, [this] - { - if (!trace) return; + connect(ui->actionEnd_trace, &QAction::triggered, this, [this] { + if (!trace) + return; ui->actionBegin_trace->setDisabled(false); ui->actionEnd_trace->setDisabled(true); shutdown_trace(); @@ -416,16 +655,70 @@ MainWindow::MainWindow(QWidget *parent) : #endif setContextMenuPolicy(Qt::PreventContextMenu); + /* Remove default Shift+F10 handler, which unfocuses keyboard input even with no context menu. */ + connect(new QShortcut(QKeySequence(Qt::SHIFT + Qt::Key_F10), this), &QShortcut::activated, this, [](){}); + + connect(this, &MainWindow::initRendererMonitor, this, &MainWindow::initRendererMonitorSlot); + connect(this, &MainWindow::initRendererMonitorForNonQtThread, this, &MainWindow::initRendererMonitorSlot, Qt::BlockingQueuedConnection); + connect(this, &MainWindow::destroyRendererMonitor, this, &MainWindow::destroyRendererMonitorSlot); + connect(this, &MainWindow::destroyRendererMonitorForNonQtThread, this, &MainWindow::destroyRendererMonitorSlot, Qt::BlockingQueuedConnection); + +#ifdef Q_OS_MACOS + QTimer::singleShot(0, this, [this]() { + for (auto curObj : this->menuBar()->children()) { + if (qobject_cast(curObj)) { + auto menu = qobject_cast(curObj); + menu->setSeparatorsCollapsible(false); + for (auto curObj2 : menu->children()) { + if (qobject_cast(curObj2)) { + auto menu2 = qobject_cast(curObj2); + menu2->setSeparatorsCollapsible(false); + } + } + } + } + }); +#endif + + actGroup = new QActionGroup(this); + actGroup->addAction(ui->actionCursor_Puck); + actGroup->addAction(ui->actionPen); + + if (tablet_tool_type == 1) { + ui->actionPen->setChecked(true); + } else { + ui->actionCursor_Puck->setChecked(true); + } + +#ifdef XKBCOMMON +# ifdef XKBCOMMON_X11 + if (QApplication::platformName().contains("xcb")) + xkbcommon_x11_init(); + else +# endif +# ifdef WAYLAND + if (QApplication::platformName().contains("wayland")) + xkbcommon_wl_init(); + else +# endif + {} +#endif } -void MainWindow::closeEvent(QCloseEvent *event) { - if (confirm_exit && confirm_exit_cmdl && cpu_thread_run) - { +void +MainWindow::closeEvent(QCloseEvent *event) +{ + if (mouse_capture) { + event->ignore(); + return; + } + + if (confirm_exit && confirm_exit_cmdl && cpu_thread_run) { QMessageBox questionbox(QMessageBox::Icon::Question, "86Box", tr("Are you sure you want to exit 86Box?"), QMessageBox::Yes | QMessageBox::No, this); - QCheckBox *chkbox = new QCheckBox(tr("Don't show this message again")); + QCheckBox *chkbox = new QCheckBox(tr("Don't show this message again")); questionbox.setCheckBox(chkbox); chkbox->setChecked(!confirm_exit); - bool confirm_exit_temp = false; + QObject::connect(chkbox, &QCheckBox::stateChanged, [](int state) { confirm_exit = (state == Qt::CheckState::Unchecked); }); @@ -443,64 +736,145 @@ void MainWindow::closeEvent(QCloseEvent *event) { window_x = this->geometry().x(); window_y = this->geometry().y(); } + for (int i = 1; i < MONITORS_NUM; i++) { + if (renderers[i]) { + monitor_settings[i].mon_window_w = renderers[i]->geometry().width(); + monitor_settings[i].mon_window_h = renderers[i]->geometry().height(); + if (QApplication::platformName().contains("wayland")) + continue; + monitor_settings[i].mon_window_x = renderers[i]->geometry().x(); + monitor_settings[i].mon_window_y = renderers[i]->geometry().y(); + } + } } + + if (ui->stackedWidget->mouse_exit_func) + ui->stackedWidget->mouse_exit_func(); + + ui->stackedWidget->switchRenderer(RendererStack::Renderer::Software); + qt_nvr_save(); config_save(); + QApplication::processEvents(); + cpu_thread_run = 0; event->accept(); } -MainWindow::~MainWindow() { +void +MainWindow::initRendererMonitorSlot(int monitor_index) +{ + auto &secondaryRenderer = this->renderers[monitor_index]; + secondaryRenderer.reset(new RendererStack(nullptr, monitor_index)); + if (secondaryRenderer) { + connect(secondaryRenderer.get(), &RendererStack::rendererChanged, this, [this, monitor_index] { + this->renderers[monitor_index]->show(); + }); + secondaryRenderer->setWindowFlags(Qt::CustomizeWindowHint | Qt::WindowTitleHint | Qt::WindowCloseButtonHint); + secondaryRenderer->setWindowTitle(QObject::tr("86Box Monitor #") + QString::number(monitor_index + 1)); + + if (vid_resize == 2) { + secondaryRenderer->setFixedSize(fixed_size_x, fixed_size_y); + } + secondaryRenderer->setWindowIcon(this->windowIcon()); + if (show_second_monitors) { + secondaryRenderer->show(); + if (window_remember) { + secondaryRenderer->setGeometry(monitor_settings[monitor_index].mon_window_x < 120 ? 120 : monitor_settings[monitor_index].mon_window_x, + monitor_settings[monitor_index].mon_window_y < 120 ? 120 : monitor_settings[monitor_index].mon_window_y, + monitor_settings[monitor_index].mon_window_w > 2048 ? 2048 : monitor_settings[monitor_index].mon_window_w, + monitor_settings[monitor_index].mon_window_h > 2048 ? 2048 : monitor_settings[monitor_index].mon_window_h); + } + if (monitor_settings[monitor_index].mon_window_maximized) { + secondaryRenderer->showMaximized(); + } + secondaryRenderer->switchRenderer((RendererStack::Renderer) vid_api); + secondaryRenderer->setMouseTracking(true); + } + } +} + +void +MainWindow::destroyRendererMonitorSlot(int monitor_index) +{ + if (this->renderers[monitor_index]) { + if (window_remember) { + monitor_settings[monitor_index].mon_window_w = renderers[monitor_index]->geometry().width(); + monitor_settings[monitor_index].mon_window_h = renderers[monitor_index]->geometry().height(); + monitor_settings[monitor_index].mon_window_x = renderers[monitor_index]->geometry().x(); + monitor_settings[monitor_index].mon_window_y = renderers[monitor_index]->geometry().y(); + } + config_save(); + this->renderers[monitor_index].release()->deleteLater(); + ui->stackedWidget->switchRenderer((RendererStack::Renderer) vid_api); + } +} + +MainWindow::~MainWindow() +{ delete ui; } -void MainWindow::showEvent(QShowEvent *event) { - if (shownonce) return; +void +MainWindow::showEvent(QShowEvent *event) +{ + if (shownonce) + return; shownonce = true; + if (window_remember) { + if (window_w == 0) + window_w = 320; + if (window_h == 0) + window_h = 200; + } + if (window_remember && !QApplication::platformName().contains("wayland")) { setGeometry(window_x, window_y, window_w, window_h + menuBar()->height() + (hide_status_bar ? 0 : statusBar()->height()) + (hide_tool_bar ? 0 : ui->toolBar->height())); } if (vid_resize == 2) { - setFixedSize(fixed_size_x, fixed_size_y - + menuBar()->height() - + (hide_status_bar ? 0 : statusBar()->height()) - + (hide_tool_bar ? 0 : ui->toolBar->height())); + setFixedSize(fixed_size_x, fixed_size_y + menuBar()->height() + (hide_status_bar ? 0 : statusBar()->height()) + (hide_tool_bar ? 0 : ui->toolBar->height())); - scrnsz_x = fixed_size_x; - scrnsz_y = fixed_size_y; + monitors[0].mon_scrnsz_x = fixed_size_x; + monitors[0].mon_scrnsz_y = fixed_size_y; } - else if (window_remember && vid_resize == 1) { + if (window_remember && vid_resize == 1) { ui->stackedWidget->setFixedSize(window_w, window_h); - adjustSize(); - ui->stackedWidget->setFixedSize(QWIDGETSIZE_MAX, QWIDGETSIZE_MAX); - scrnsz_x = window_w; - scrnsz_y = window_h; + QApplication::processEvents(); + this->adjustSize(); + } + if (start_in_fullscreen) { + start_in_fullscreen = 0; + QTimer::singleShot(0, ui->actionFullscreen, &QAction::trigger); } } -void MainWindow::on_actionKeyboard_requires_capture_triggered() { +void +MainWindow::on_actionKeyboard_requires_capture_triggered() +{ kbd_req_capture ^= 1; } -void MainWindow::on_actionRight_CTRL_is_left_ALT_triggered() { +void +MainWindow::on_actionRight_CTRL_is_left_ALT_triggered() +{ rctrl_is_lalt ^= 1; } -void MainWindow::on_actionHard_Reset_triggered() { - if (confirm_reset) - { +void +MainWindow::on_actionHard_Reset_triggered() +{ + if (confirm_reset) { QMessageBox questionbox(QMessageBox::Icon::Question, "86Box", tr("Are you sure you want to hard reset the emulated machine?"), QMessageBox::NoButton, this); - questionbox.addButton(tr("Don't reset"), QMessageBox::AcceptRole); - questionbox.addButton(tr("Reset"), QMessageBox::RejectRole); + questionbox.addButton(tr("Reset"), QMessageBox::AcceptRole); + questionbox.addButton(tr("Don't reset"), QMessageBox::RejectRole); QCheckBox *chkbox = new QCheckBox(tr("Don't show this message again")); questionbox.setCheckBox(chkbox); chkbox->setChecked(!confirm_reset); - bool confirm_exit_temp = false; + QObject::connect(chkbox, &QCheckBox::stateChanged, [](int state) { confirm_reset = (state == Qt::CheckState::Unchecked); }); questionbox.exec(); - if (questionbox.result() == QDialog::Rejected) - { + if (questionbox.result() == QDialog::Accepted) { confirm_reset = true; return; } @@ -509,616 +883,307 @@ void MainWindow::on_actionHard_Reset_triggered() { pc_reset_hard(); } -void MainWindow::on_actionCtrl_Alt_Del_triggered() { +void +MainWindow::on_actionCtrl_Alt_Del_triggered() +{ pc_send_cad(); } -void MainWindow::on_actionCtrl_Alt_Esc_triggered() { +void +MainWindow::on_actionCtrl_Alt_Esc_triggered() +{ pc_send_cae(); } -void MainWindow::on_actionPause_triggered() { +void +MainWindow::on_actionPause_triggered() +{ plat_pause(dopause ^ 1); } -void MainWindow::on_actionExit_triggered() { +void +MainWindow::on_actionExit_triggered() +{ close(); } -void MainWindow::on_actionSettings_triggered() { +void +MainWindow::on_actionSettings_triggered() +{ int currentPause = dopause; plat_pause(1); Settings settings(this); settings.setModal(true); settings.setWindowModality(Qt::WindowModal); + settings.setWindowFlag(Qt::CustomizeWindowHint, true); + settings.setWindowFlag(Qt::WindowTitleHint, true); + settings.setWindowFlag(Qt::WindowSystemMenuHint, false); settings.exec(); switch (settings.result()) { - case QDialog::Accepted: - /* - pc_reset_hard_close(); - settings.save(); - config_changed = 2; - pc_reset_hard_init(); - */ - settings.save(); - config_changed = 2; - pc_reset_hard(); - - break; - case QDialog::Rejected: - break; + case QDialog::Accepted: + pc_reset_hard_close(); + settings.save(); + config_changed = 2; + pc_reset_hard_init(); + break; + case QDialog::Rejected: + break; } plat_pause(currentPause); } -std::array x11_to_xt_base +void +MainWindow::processKeyboardInput(bool down, uint32_t keycode) { - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0x01, - 0x02, - 0x03, - 0x04, - 0x05, - 0x06, - 0x07, - 0x08, - 0x09, - 0x0A, - 0x0B, - 0x0C, - 0x0D, - 0x0E, - 0x0F, - 0x10, - 0x11, - 0x12, - 0x13, - 0x14, - 0x15, - 0x16, - 0x17, - 0x18, - 0x19, - 0x1A, - 0x1B, - 0x1C, - 0x1D, - 0x1E, - 0x1F, - 0x20, - 0x21, - 0x22, - 0x23, - 0x24, - 0x25, - 0x26, - 0x27, - 0x28, - 0x29, - 0x2A, - 0x2B, - 0x2C, - 0x2D, - 0x2E, - 0x2F, - 0x30, - 0x31, - 0x32, - 0x33, - 0x34, - 0x35, - 0x36, - 0x37, - 0x38, - 0x39, - 0x3A, - 0x3B, - 0x3C, - 0x3D, - 0x3E, - 0x3F, - 0x40, - 0x41, - 0x42, - 0x43, - 0x44, - 0x45, - 0x46, - 0x47, - 0x48, - 0x49, - 0x4A, - 0x4B, - 0x4C, - 0x4D, - 0x4E, - 0x4F, - 0x50, - 0x51, - 0x52, - 0x53, - 0x54, - 0x55, - 0x56, - 0x57, - 0x58, - 0x147, - 0x148, - 0x149, - 0, - 0x14B, - 0, - 0x14D, - 0x14F, - 0x150, - 0x151, - 0x152, - 0x153, - 0x11C, - 0x11D, - 0, // Pause/Break key. - 0x137, - 0x135, - 0x138, - 0, // Ditto as above comment. - 0x15B, - 0x15C, - 0x15D, -}; - -std::array x11_to_xt_2 -{ - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0x01, - 0x02, - 0x03, - 0x04, - 0x05, - 0x06, - 0x07, - 0x08, - 0x09, - 0x0A, - 0x0B, - 0x0C, - 0x0D, - 0x0E, - 0x0F, - 0x10, - 0x11, - 0x12, - 0x13, - 0x14, - 0x15, - 0x16, - 0x17, - 0x18, - 0x19, - 0x1A, - 0x1B, - 0x1C, - 0x1D, - 0x1E, - 0x1F, - 0x20, - 0x21, - 0x22, - 0x23, - 0x24, - 0x25, - 0x26, - 0x27, - 0x28, - 0x29, - 0x2A, - 0x2B, - 0x2C, - 0x2D, - 0x2E, - 0x2F, - 0x30, - 0x31, - 0x32, - 0x33, - 0x34, - 0x35, - 0x36, - 0x37, - 0x38, - 0x39, - 0x3A, - 0x3B, - 0x3C, - 0x3D, - 0x3E, - 0x3F, - 0x40, - 0x41, - 0x42, - 0x43, - 0x44, - 0x45, - 0x46, - 0x47, - 0x48, - 0x49, - 0x4A, - 0x4B, - 0x4C, - 0x4D, - 0x4E, - 0x4F, - 0x50, - 0x51, - 0x52, - 0x53, - 0x54, - 0x55, - 0x56, - 0x57, - 0x58, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0x11C, - 0x11D, - 0x135, - 0x137, - 0x138, - 0, - 0x147, - 0x148, - 0x149, - 0x14B, - 0x14D, - 0x14F, - 0x150, - 0x151, - 0x152, - 0x153 -}; - -std::array x11_to_xt_vnc -{ - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0x1D, - 0x11D, - 0x2A, - 0x36, - 0, - 0, - 0x38, - 0x138, - 0x39, - 0x0B, - 0x02, - 0x03, - 0x04, - 0x05, - 0x06, - 0x07, - 0x08, - 0x09, - 0x0A, - 0x0C, - 0x0D, - 0x1A, - 0x1B, - 0x27, - 0x28, - 0x29, - 0x33, - 0x34, - 0x35, - 0x2B, - 0x1E, - 0x30, - 0x2E, - 0x20, - 0x12, - 0x21, - 0x22, - 0x23, - 0x17, - 0x24, - 0x25, - 0x26, - 0x32, - 0x31, - 0x18, - 0x19, - 0x10, - 0x13, - 0x1F, - 0x14, - 0x16, - 0x2F, - 0x11, - 0x2D, - 0x15, - 0x2C, - 0x0E, - 0x1C, - 0x0F, - 0x01, - 0x153, - 0x147, - 0x14F, - 0x149, - 0x151, - 0x148, - 0x150, - 0x14B, - 0x14D, -}; - -std::array darwin_to_xt -{ - 0x1E, - 0x1F, - 0x20, - 0x21, - 0x23, - 0x22, - 0x2C, - 0x2D, - 0x2E, - 0x2F, - 0x2B, - 0x30, - 0x10, - 0x11, - 0x12, - 0x13, - 0x15, - 0x14, - 0x02, - 0x03, - 0x04, - 0x05, - 0x07, - 0x06, - 0x0D, - 0x0A, - 0x08, - 0x0C, - 0x09, - 0x0B, - 0x1B, - 0x18, - 0x16, - 0x1A, - 0x17, - 0x19, - 0x1C, - 0x26, - 0x24, - 0x28, - 0x25, - 0x27, - 0x2B, - 0x33, - 0x35, - 0x31, - 0x32, - 0x34, - 0x0F, - 0x39, - 0x29, - 0x0E, - 0x11C, - 0x01, - 0x15C, - 0x15B, - 0x2A, - 0x3A, - 0x38, - 0x1D, - 0x36, - 0x138, - 0x11D, - 0x15C, - 0, - 0x53, - 0, - 0x37, - 0, - 0x4E, - 0, - 0x45, - 0x130, - 0x12E, - 0x120, - 0x135, - 0x11C, - 0, - 0x4A, - 0, - 0, - 0, - 0x52, - 0x4F, - 0x50, - 0x51, - 0x4B, - 0x4C, - 0x4D, - 0x47, - 0, - 0x48, - 0x49, - 0, - 0, - 0, - 0x3F, - 0x40, - 0x41, - 0x3D, - 0x42, - 0x43, - 0, - 0x57, - 0, - 0x137, - 0, - 0x46, - 0, - 0x44, - 0x15D, - 0x58, - 0, - 0, // Pause/Break key. - 0x152, - 0x147, - 0x149, - 0x153, - 0x3E, - 0x14F, - 0x3C, - 0x151, - 0x3B, - 0x14B, - 0x14D, - 0x150, - 0x148, - 0, -}; - -static std::unordered_map evdev_to_xt = - { - {96, 0x11C}, - {97, 0x11D}, - {98, 0x135}, - {99, 0x71}, - {100, 0x138}, - {101, 0x1C}, - {102, 0x147}, - {103, 0x148}, - {104, 0x149}, - {105, 0x14B}, - {106, 0x14D}, - {107, 0x14F}, - {108, 0x150}, - {109, 0x151}, - {110, 0x152}, - {111, 0x153} -}; - -static std::array& selected_keycode = x11_to_xt_base; - -uint16_t x11_keycode_to_keysym(uint32_t keycode) -{ - uint16_t finalkeycode = 0; -#if defined(Q_OS_WINDOWS) - finalkeycode = (keycode & 0xFFFF); -#elif defined(__APPLE__) - finalkeycode = darwin_to_xt[keycode]; +#if defined(Q_OS_WINDOWS) /* non-raw input */ + keycode &= 0xffff; +#elif defined(Q_OS_MACOS) + keycode = (keycode < 127) ? cocoa_keycodes[keycode] : 0; +#elif defined(__HAIKU__) + keycode = be_keycodes[keycode]; #else - static Display* x11display = nullptr; - if (QApplication::platformName().contains("wayland")) - { - selected_keycode = x11_to_xt_2; - } - else if (QApplication::platformName().contains("eglfs")) - { - keycode -= 8; - if (keycode <= 88) finalkeycode = keycode; - else finalkeycode = evdev_to_xt[keycode]; - } - else if (!x11display) - { - x11display = XOpenDisplay(nullptr); - if (XKeysymToKeycode(x11display, XK_Home) == 110) - { - selected_keycode = x11_to_xt_2; - } - else if (XKeysymToKeycode(x11display, XK_Home) == 69) - { - selected_keycode = x11_to_xt_vnc; - } - } - if (!QApplication::platformName().contains("eglfs")) finalkeycode = selected_keycode[keycode]; +# ifdef XKBCOMMON + if (xkbcommon_keymap) + keycode = xkbcommon_translate(keycode); + else +# endif +# ifdef EVDEV_KEYBOARD_HPP + keycode = evdev_translate(keycode - 8); +# else + keycode = 0; +# endif #endif - if (rctrl_is_lalt && finalkeycode == 0x11D) - { - finalkeycode = 0x38; + + /* Apply special cases. */ + switch (keycode) { + case 0x54: /* Alt + Print Screen (special case, i.e. evdev SELECTIVE_SCREENSHOT) */ + /* Send Alt as well. */ + if (down) { + keyboard_input(down, 0x38); + } else { + keyboard_input(down, keycode); + keycode = 0x38; + } + break; + + case 0x80 ... 0xff: /* regular break codes */ + case 0x10b: /* Microsoft scroll up normal */ + case 0x180 ... 0x1ff: /* E0 break codes (including Microsoft scroll down normal) */ + /* This key uses a break code as make. Send it manually, only on press. */ + if (down) { + if (keycode & 0x100) + keyboard_send(0xe0); + keyboard_send(keycode & 0xff); + } + return; + + case 0x11d: /* Right Ctrl */ + if (rctrl_is_lalt) + keycode = 0x38; /* map to Left Alt */ + break; + + case 0x137: /* Print Screen */ + if (keyboard_recv(0x38) || keyboard_recv(0x138)) { /* Alt+ */ + keycode = 0x54; + } else if (down) { + keyboard_input(down, 0x12a); + } else { + keyboard_input(down, keycode); + keycode = 0x12a; + } + break; + + case 0x145: /* Pause */ + if (keyboard_recv(0x1d) || keyboard_recv(0x11d)) { /* Ctrl+ */ + keycode = 0x146; + } else { + keyboard_input(down, 0xe11d); + keycode &= 0x00ff; + } + break; } - return finalkeycode; + + keyboard_input(down, keycode); } -void MainWindow::on_actionFullscreen_triggered() { - if (video_fullscreen > 0) { - showNormal(); - ui->menubar->show(); - if (!hide_status_bar) ui->statusbar->show(); - if (!hide_tool_bar) ui->toolBar->show(); - video_fullscreen = 0; - if (vid_resize != 1) { - if (vid_resize == 2) setFixedSize(fixed_size_x, fixed_size_y - + menuBar()->height() - + (!hide_status_bar ? statusBar()->height() : 0) - + (!hide_tool_bar ? ui->toolBar->height() : 0)); +#ifdef Q_OS_MACOS +// These modifiers are listed as "device-dependent" in IOLLEvent.h, but +// that's followed up with "(really?)". It's the only way to distinguish +// left and right modifiers with Qt 6 on macOS, so let's just roll with it. +static std::unordered_map mac_modifiers_to_xt = { + {NX_DEVICELCTLKEYMASK, 0x1D }, + { NX_DEVICELSHIFTKEYMASK, 0x2A }, + { NX_DEVICERSHIFTKEYMASK, 0x36 }, + { NX_DEVICELCMDKEYMASK, 0x15B}, + { NX_DEVICERCMDKEYMASK, 0x15C}, + { NX_DEVICELALTKEYMASK, 0x38 }, + { NX_DEVICERALTKEYMASK, 0x138}, + { NX_DEVICE_ALPHASHIFT_STATELESS_MASK, 0x3A }, + { NX_DEVICERCTLKEYMASK, 0x11D}, +}; +static bool mac_iso_swap = false; - emit resizeContents(scrnsz_x, scrnsz_y); +void +MainWindow::processMacKeyboardInput(bool down, const QKeyEvent *event) +{ + // Per QTBUG-69608 (https://bugreports.qt.io/browse/QTBUG-69608), + // QKeyEvents QKeyEvents for presses/releases of modifiers on macOS give + // nativeVirtualKey() == 0 (at least in Qt 6). Handle this by manually + // processing the nativeModifiers(). We need to check whether the key() is + // a known modifier because because kVK_ANSI_A is also 0, so the + // nativeVirtualKey() == 0 condition is ambiguous... + if (event->nativeVirtualKey() == 0 + && (event->key() == Qt::Key_Shift + || event->key() == Qt::Key_Control + || event->key() == Qt::Key_Meta + || event->key() == Qt::Key_Alt + || event->key() == Qt::Key_AltGr + || event->key() == Qt::Key_CapsLock)) { + // We only process one modifier at a time since events from Qt seem to + // always be non-coalesced (NX_NONCOALESCEDMASK is always set). + uint32_t changed_modifiers = last_modifiers ^ event->nativeModifiers(); + for (auto const &pair : mac_modifiers_to_xt) { + if (changed_modifiers & pair.first) { + last_modifiers ^= pair.first; + keyboard_input(down, pair.second); + return; + } + } + + // Caps Lock seems to be delivered as a single key press event when + // enabled and a single key release event when disabled, so we can't + // detect Caps Lock being held down; just send an infinitesimally-long + // press and release as a compromise. + // + // The event also doesn't get delivered if you turn Caps Lock off after + // turning it on when the window isn't focused. Doing better than this + // probably requires bypassing Qt input processing. + // + // It's possible that other lock keys get delivered in this way, but + // standard Apple keyboards don't have them, so this is untested. + if (event->key() == Qt::Key_CapsLock) { + keyboard_input(1, 0x3a); + keyboard_input(0, 0x3a); } } else { - if (video_fullscreen_first) - { + /* Apple ISO keyboards are notorious for swapping ISO_Section and ANSI_Grave + on *some* layouts and/or models. While macOS can sort this mess out at + keymap level, it still provides applications with unfiltered, ambiguous + keycodes, so we have to disambiguate them by making some bold assumptions + about the user's keyboard layout based on the OS-provided key mappings. */ + auto nvk = event->nativeVirtualKey(); + if ((nvk == 0x0a) || (nvk == 0x32)) { + /* Flaws: + - Layouts with `~ on ISO_Section are partially detected due to a conflict with ANSI + - Czech and Slovak are not detected as they have <> ANSI_Grave and \| ISO_Section (differing from PC actually) + - Italian is partially detected due to \| conflicting with Brazilian + - Romanian third level ANSI_Grave is unknown + - Russian clusters <>, plusminus and paragraph into a four-level ANSI_Grave, with the aforementioned `~ on ISO_Section */ + auto key = event->key(); + if ((nvk == 0x32) && ( /* system reports ANSI_Grave for ISO_Section keys: */ + (key == Qt::Key_Less) || (key == Qt::Key_Greater) || /* Croatian, French, German, Icelandic, Italian, Norwegian, Portuguese, Spanish, Spanish Latin America, Turkish Q */ + (key == Qt::Key_Ugrave) || /* French Canadian */ + (key == Qt::Key_Icircumflex) || /* Romanian */ + (key == Qt::Key_Iacute) || /* Hungarian */ + (key == Qt::Key_BracketLeft) || (key == Qt::Key_BracketRight) || /* Russian upper two levels */ + (key == Qt::Key_W) /* Turkish F */ + )) + mac_iso_swap = true; + else if ((nvk == 0x0a) && ( /* system reports ISO_Section for ANSI_Grave keys: */ + (key == Qt::Key_paragraph) || (key == Qt::Key_plusminus) || /* Arabic, British, Bulgarian, Danish shifted, Dutch, Greek, Hebrew, Hungarian shifted, International English, Norwegian shifted, Portuguese, Russian lower two levels, Swiss unshifted, Swedish unshifted, Turkish F */ + (key == Qt::Key_At) || (key == Qt::Key_NumberSign) || /* Belgian, French */ + (key == Qt::Key_Apostrophe) || /* Brazilian unshifted */ + (key == Qt::Key_QuoteDbl) || /* Brazilian shifted, Turkish Q unshifted */ + (key == Qt::Key_QuoteLeft) || /* Croatian (right quote unknown) */ + (key == Qt::Key_Dollar) || /* Danish unshifted */ + (key == Qt::Key_AsciiCircum) || (key == 0x1ffffff) || /* German unshifted (0x1ffffff according to one tester), Polish unshifted */ + (key == Qt::Key_degree) || /* German shifted, Icelandic unshifted, Spanish Latin America shifted, Swiss shifted, Swedish shifted */ + (key == Qt::Key_0) || /* Hungarian unshifted */ + (key == Qt::Key_diaeresis) || /* Icelandic shifted */ + (key == Qt::Key_acute) || /* Norwegian unshifted */ + (key == Qt::Key_Asterisk) || /* Polish shifted */ + (key == Qt::Key_masculine) || (key == Qt::Key_ordfeminine) || /* Spanish (masculine unconfirmed) */ + (key == Qt::Key_Eacute) || /* Turkish Q shifted */ + (key == Qt::Key_Slash) /* French Canadian unshifted, Ukrainian shifted */ + )) + mac_iso_swap = true; +#if 0 + if (down) { + QMessageBox questionbox(QMessageBox::Icon::Information, QString("Mac key swap test"), QString("nativeVirtualKey 0x%1\nnativeScanCode 0x%2\nkey 0x%3\nmac_iso_swap %4").arg(nvk, 0, 16).arg(event->nativeScanCode(), 0, 16).arg(key, 0, 16).arg(mac_iso_swap ? "yes" : "no"), QMessageBox::Ok, this); + questionbox.exec(); + } +#endif + if (mac_iso_swap) + nvk = (nvk == 0x0a) ? 0x32 : 0x0a; + } + // Special case for command + forward delete to send insert. + if ((event->nativeModifiers() & NSEventModifierFlagCommand) && + ((event->nativeVirtualKey() == nvk_Delete) || event->key() == Qt::Key_Delete)) { + nvk = nvk_Insert; // Qt::Key_Help according to event->key() + } + + processKeyboardInput(down, nvk); + } +} +#endif + +void +MainWindow::on_actionFullscreen_triggered() +{ + if (video_fullscreen > 0) { + showNormal(); + if (vid_api == 5) + QTimer::singleShot(0, this, [this]() { ui->stackedWidget->switchRenderer(RendererStack::Renderer::Direct3D9); }); + ui->menubar->show(); + if (!hide_status_bar) + ui->statusbar->show(); + if (!hide_tool_bar) + ui->toolBar->show(); + video_fullscreen = 0; + if (vid_resize != 1) { + emit resizeContents(vid_resize == 2 ? fixed_size_x : monitors[0].mon_scrnsz_x, vid_resize == 2 ? fixed_size_y : monitors[0].mon_scrnsz_y); + } + } else { + if (video_fullscreen_first) { + bool wasCaptured = mouse_capture == 1; + QMessageBox questionbox(QMessageBox::Icon::Information, tr("Entering fullscreen mode"), tr("Press Ctrl+Alt+PgDn to return to windowed mode."), QMessageBox::Ok, this); - QCheckBox *chkbox = new QCheckBox(tr("Don't show this message again")); + QCheckBox *chkbox = new QCheckBox(tr("Don't show this message again")); questionbox.setCheckBox(chkbox); chkbox->setChecked(!video_fullscreen_first); - bool confirm_exit_temp = false; + QObject::connect(chkbox, &QCheckBox::stateChanged, [](int state) { video_fullscreen_first = (state == Qt::CheckState::Unchecked); }); questionbox.exec(); config_save(); + + /* (re-capture mouse after dialog). */ + if (wasCaptured) + emit setMouseCapture(true); } + video_fullscreen = 1; setFixedSize(QWIDGETSIZE_MAX, QWIDGETSIZE_MAX); ui->menubar->hide(); ui->statusbar->hide(); ui->toolBar->hide(); + ui->stackedWidget->setFixedSize(QWIDGETSIZE_MAX, QWIDGETSIZE_MAX); showFullScreen(); - video_fullscreen = 1; + if (vid_api == 5) + QTimer::singleShot(0, this, [this]() { ui->stackedWidget->switchRenderer(RendererStack::Renderer::Direct3D9); }); } - ui->stackedWidget->rendererWindow->onResize(width(), height()); + ui->stackedWidget->onResize(width(), height()); } -void MainWindow::getTitle_(wchar_t *title) +void +MainWindow::getTitle_(wchar_t *title) { this->windowTitle().toWCharArray(title); } -void MainWindow::getTitle(wchar_t *title) +void +MainWindow::getTitle(wchar_t *title) { if (QThread::currentThread() == this->thread()) { getTitle_(title); @@ -1127,146 +1192,213 @@ void MainWindow::getTitle(wchar_t *title) } } -bool MainWindow::eventFilter(QObject* receiver, QEvent* event) +bool +MainWindow::eventFilter(QObject *receiver, QEvent *event) { - if (this->keyboardGrabber() == this) { + if (!dopause && (mouse_capture || !kbd_req_capture)) { + if (event->type() == QEvent::Shortcut) { + auto shortcutEvent = (QShortcutEvent *) event; + if (shortcutEvent->key() == ui->actionExit->shortcut()) { + event->accept(); + return true; + } + } if (event->type() == QEvent::KeyPress) { event->accept(); - this->keyPressEvent((QKeyEvent*)event); + this->keyPressEvent((QKeyEvent *) event); return true; } if (event->type() == QEvent::KeyRelease) { event->accept(); - this->keyReleaseEvent((QKeyEvent*)event); + this->keyReleaseEvent((QKeyEvent *) event); return true; } } - if (receiver == this) - { + if (receiver == this) { static auto curdopause = dopause; - if (event->type() == QEvent::WindowBlocked) { curdopause = dopause; plat_pause(1); } - else if (event->type() == QEvent::WindowUnblocked) { plat_pause(curdopause); } + if (event->type() == QEvent::WindowBlocked) { + curdopause = dopause; + plat_pause(1); + emit setMouseCapture(false); + } else if (event->type() == QEvent::WindowUnblocked) { + plat_pause(curdopause); + } } + return QMainWindow::eventFilter(receiver, event); } -void MainWindow::refreshMediaMenu() { +void +MainWindow::refreshMediaMenu() +{ mm->refresh(ui->menuMedia); status->refresh(ui->statusbar); + ui->actionMCA_devices->setVisible(machine_has_bus(machine, MACHINE_BUS_MCA)); + ui->actionACPI_Shutdown->setEnabled(!!acpi_enabled); } -void MainWindow::showMessage(const QString& header, const QString& message) { +void +MainWindow::showMessage(int flags, const QString &header, const QString &message) +{ if (QThread::currentThread() == this->thread()) { - showMessage_(header, message); + showMessage_(flags, header, message); } else { - emit showMessageForNonQtThread(header, message); + emit showMessageForNonQtThread(flags, header, message); } } -void MainWindow::showMessage_(const QString &header, const QString &message) { +void +MainWindow::showMessage_(int flags, const QString &header, const QString &message) +{ QMessageBox box(QMessageBox::Warning, header, message, QMessageBox::NoButton, this); + if (flags & (MBX_FATAL)) { + box.setIcon(QMessageBox::Critical); + } else if (!(flags & (MBX_ERROR | MBX_WARNING))) { + box.setIcon(QMessageBox::Warning); + } box.setTextFormat(Qt::TextFormat::RichText); box.exec(); + if (cpu_thread_run == 0) + QApplication::exit(-1); } -void MainWindow::keyPressEvent(QKeyEvent* event) +void +MainWindow::keyPressEvent(QKeyEvent *event) { - if (send_keyboard_input && !(kbd_req_capture && !mouse_capture && !video_fullscreen)) - { -#ifdef __APPLE__ - keyboard_input(1, x11_keycode_to_keysym(event->nativeVirtualKey())); + if (send_keyboard_input && !(kbd_req_capture && !mouse_capture)) { +#ifdef Q_OS_MACOS + processMacKeyboardInput(true, event); #else - keyboard_input(1, x11_keycode_to_keysym(event->nativeScanCode())); + processKeyboardInput(true, event->nativeScanCode()); #endif } - if ((video_fullscreen > 0) && keyboard_isfsexit()) { - ui->actionFullscreen->trigger(); + checkFullscreenHotkey(); + + if (keyboard_ismsexit()) + plat_mouse_capture(0); + + if ((video_fullscreen > 0) && (keyboard_recv(0x1D) || keyboard_recv(0x11D))) { + if (keyboard_recv(0x57)) + ui->actionTake_screenshot->trigger(); + else if (keyboard_recv(0x58)) + pc_send_cad(); } - if (keyboard_ismsexit()) { - plat_mouse_capture(0); - } event->accept(); } -void MainWindow::blitToWidget(int x, int y, int w, int h) +void +MainWindow::blitToWidget(int x, int y, int w, int h, int monitor_index) { - ui->stackedWidget->blit(x, y, w, h); + if (monitor_index >= 1) { + if (!blitDummied && renderers[monitor_index] && renderers[monitor_index]->isVisible()) + renderers[monitor_index]->blit(x, y, w, h); + else + video_blit_complete_monitor(monitor_index); + } else + ui->stackedWidget->blit(x, y, w, h); } -void MainWindow::keyReleaseEvent(QKeyEvent* event) +void +MainWindow::keyReleaseEvent(QKeyEvent *event) { - if (!send_keyboard_input) - return; + if (event->key() == Qt::Key_Pause) { + if (keyboard_recv(0x38) && keyboard_recv(0x138)) { + plat_pause(dopause ^ 1); + } + } -#ifdef __APPLE__ - keyboard_input(0, x11_keycode_to_keysym(event->nativeVirtualKey())); + if (send_keyboard_input && !event->isAutoRepeat()) { +#ifdef Q_OS_MACOS + processMacKeyboardInput(false, event); #else - keyboard_input(0, x11_keycode_to_keysym(event->nativeScanCode())); + processKeyboardInput(false, event->nativeScanCode()); #endif + } + + checkFullscreenHotkey(); } -QSize MainWindow::getRenderWidgetSize() +void +MainWindow::checkFullscreenHotkey() +{ + if (!fs_off_signal && video_fullscreen && keyboard_isfsexit()) { + /* Signal "exit fullscreen mode". */ + fs_off_signal = 1; + } else if (fs_off_signal && video_fullscreen && keyboard_isfsexit_up()) { + ui->actionFullscreen->trigger(); + fs_off_signal = 0; + } + + if (!fs_on_signal && !video_fullscreen && keyboard_isfsenter()) { + /* Signal "enter fullscreen mode". */ + fs_on_signal = 1; + } else if (fs_on_signal && !video_fullscreen && keyboard_isfsenter_up()) { + ui->actionFullscreen->trigger(); + fs_on_signal = 0; + } +} + +QSize +MainWindow::getRenderWidgetSize() { return ui->stackedWidget->size(); } -void MainWindow::on_actionSoftware_Renderer_triggered() { - ui->stackedWidget->switchRenderer(RendererStack::Renderer::Software); - ui->actionHardware_Renderer_OpenGL->setChecked(false); - ui->actionHardware_Renderer_OpenGL_ES->setChecked(false); - ui->actionOpenGL_3_0_Core->setChecked(false); - vid_api = 0; -} - -void MainWindow::on_actionHardware_Renderer_OpenGL_triggered() { - ui->stackedWidget->switchRenderer(RendererStack::Renderer::OpenGL); - ui->actionSoftware_Renderer->setChecked(false); - ui->actionHardware_Renderer_OpenGL_ES->setChecked(false); - ui->actionOpenGL_3_0_Core->setChecked(false); - vid_api = 1; -} - -void MainWindow::on_actionHardware_Renderer_OpenGL_ES_triggered() { - ui->stackedWidget->switchRenderer(RendererStack::Renderer::OpenGLES); - ui->actionSoftware_Renderer->setChecked(false); - ui->actionHardware_Renderer_OpenGL->setChecked(false); - ui->actionOpenGL_3_0_Core->setChecked(false); - vid_api = 2; -} - -void MainWindow::focusInEvent(QFocusEvent* event) +void +MainWindow::focusInEvent(QFocusEvent *event) { this->grabKeyboard(); } -void MainWindow::focusOutEvent(QFocusEvent* event) +void +MainWindow::focusOutEvent(QFocusEvent *event) { this->releaseKeyboard(); } -void MainWindow::on_actionResizable_window_triggered(bool checked) { +void +MainWindow::on_actionResizable_window_triggered(bool checked) +{ if (checked) { vid_resize = 1; setWindowFlag(Qt::WindowMaximizeButtonHint); setWindowFlag(Qt::MSWindowsFixedSizeDialogHint, false); setFixedSize(QWIDGETSIZE_MAX, QWIDGETSIZE_MAX); + for (int i = 1; i < MONITORS_NUM; i++) { + if (monitors[i].target_buffer) { + renderers[i]->setWindowFlag(Qt::WindowMaximizeButtonHint); + renderers[i]->setFixedSize(QWIDGETSIZE_MAX, QWIDGETSIZE_MAX); + } + } } else { vid_resize = 0; setWindowFlag(Qt::WindowMaximizeButtonHint, false); setWindowFlag(Qt::MSWindowsFixedSizeDialogHint); + for (int i = 1; i < MONITORS_NUM; i++) { + if (monitors[i].target_buffer) { + renderers[i]->setWindowFlag(Qt::WindowMaximizeButtonHint, false); + emit resizeContentsMonitor(monitors[i].mon_scrnsz_x, monitors[i].mon_scrnsz_y, i); + } + } } show(); - ui->stackedWidget->switchRenderer((RendererStack::Renderer)vid_api); - - ui->menuWindow_scale_factor->setEnabled(! checked); - emit resizeContents(scrnsz_x, scrnsz_y); + ui->menuWindow_scale_factor->setEnabled(!checked); + emit resizeContents(monitors[0].mon_scrnsz_x, monitors[0].mon_scrnsz_y); + ui->stackedWidget->switchRenderer((RendererStack::Renderer) vid_api); + for (int i = 1; i < MONITORS_NUM; i++) { + if (monitors[i].target_buffer && show_second_monitors) { + renderers[i]->show(); + renderers[i]->switchRenderer((RendererStack::Renderer) vid_api); + QApplication::processEvents(); + } + } } static void -video_toggle_option(QAction* action, int *val) +video_toggle_option(QAction *action, int *val) { startblit(); *val ^= 1; @@ -1274,93 +1406,189 @@ video_toggle_option(QAction* action, int *val) action->setChecked(*val > 0 ? true : false); endblit(); config_save(); + reset_screen_size(); device_force_redraw(); + for (int i = 0; i < MONITORS_NUM; i++) { + if (monitors[i].target_buffer) + video_force_resize_set_monitor(1, i); + } } -void MainWindow::on_actionInverted_VGA_monitor_triggered() { +void +MainWindow::on_actionInverted_VGA_monitor_triggered() +{ video_toggle_option(ui->actionInverted_VGA_monitor, &invert_display); } -static void update_scaled_checkboxes(Ui::MainWindow* ui, QAction* selected) { +static void +update_scaled_checkboxes(Ui::MainWindow *ui, QAction *selected) +{ ui->action0_5x->setChecked(ui->action0_5x == selected); ui->action1x->setChecked(ui->action1x == selected); ui->action1_5x->setChecked(ui->action1_5x == selected); ui->action2x->setChecked(ui->action2x == selected); + ui->action3x->setChecked(ui->action3x == selected); + ui->action4x->setChecked(ui->action4x == selected); + ui->action5x->setChecked(ui->action5x == selected); + ui->action6x->setChecked(ui->action6x == selected); + ui->action7x->setChecked(ui->action7x == selected); + ui->action8x->setChecked(ui->action8x == selected); reset_screen_size(); device_force_redraw(); - video_force_resize_set(1); - atomic_flag_clear(&doresize); + for (int i = 0; i < MONITORS_NUM; i++) { + if (monitors[i].target_buffer) + video_force_resize_set_monitor(1, i); + } config_save(); } -void MainWindow::on_action0_5x_triggered() { +void +MainWindow::on_action0_5x_triggered() +{ scale = 0; update_scaled_checkboxes(ui, ui->action0_5x); } -void MainWindow::on_action1x_triggered() { +void +MainWindow::on_action1x_triggered() +{ scale = 1; update_scaled_checkboxes(ui, ui->action1x); } -void MainWindow::on_action1_5x_triggered() { +void +MainWindow::on_action1_5x_triggered() +{ scale = 2; update_scaled_checkboxes(ui, ui->action1_5x); } -void MainWindow::on_action2x_triggered() { +void +MainWindow::on_action2x_triggered() +{ scale = 3; update_scaled_checkboxes(ui, ui->action2x); } -void MainWindow::on_actionNearest_triggered() { +void +MainWindow::on_action3x_triggered() +{ + scale = 4; + update_scaled_checkboxes(ui, ui->action3x); +} + +void +MainWindow::on_action4x_triggered() +{ + scale = 5; + update_scaled_checkboxes(ui, ui->action4x); +} + +void +MainWindow::on_action5x_triggered() +{ + scale = 6; + update_scaled_checkboxes(ui, ui->action5x); +} + +void +MainWindow::on_action6x_triggered() +{ + scale = 7; + update_scaled_checkboxes(ui, ui->action6x); +} + +void +MainWindow::on_action7x_triggered() +{ + scale = 8; + update_scaled_checkboxes(ui, ui->action7x); +} + +void +MainWindow::on_action8x_triggered() +{ + scale = 9; + update_scaled_checkboxes(ui, ui->action8x); +} + +void +MainWindow::on_actionNearest_triggered() +{ video_filter_method = 0; ui->actionLinear->setChecked(false); } -void MainWindow::on_actionLinear_triggered() { +void +MainWindow::on_actionLinear_triggered() +{ video_filter_method = 1; ui->actionNearest->setChecked(false); } -static void update_fullscreen_scale_checkboxes(Ui::MainWindow* ui, QAction* selected) { - ui->actionFullScreen_stretch->setChecked(ui->actionFullScreen_stretch == selected); - ui->actionFullScreen_43->setChecked(ui->actionFullScreen_43 == selected); - ui->actionFullScreen_keepRatio->setChecked(ui->actionFullScreen_keepRatio == selected); - ui->actionFullScreen_int->setChecked(ui->actionFullScreen_int == selected); +static void +update_fullscreen_scale_checkboxes(Ui::MainWindow *ui, QAction *selected) +{ + ui->actionFullScreen_stretch->setChecked(selected == ui->actionFullScreen_stretch); + ui->actionFullScreen_43->setChecked(selected == ui->actionFullScreen_43); + ui->actionFullScreen_keepRatio->setChecked(selected == ui->actionFullScreen_keepRatio); + ui->actionFullScreen_int->setChecked(selected == ui->actionFullScreen_int); + ui->actionFullScreen_int43->setChecked(selected == ui->actionFullScreen_int43); - if (video_fullscreen > 0) { + { auto widget = ui->stackedWidget->currentWidget(); - auto rc = ui->stackedWidget->rendererWindow; - rc->onResize(widget->width(), widget->height()); + ui->stackedWidget->onResize(widget->width(), widget->height()); + } + + for (int i = 1; i < MONITORS_NUM; i++) { + if (main_window->renderers[i]) + main_window->renderers[i]->onResize(main_window->renderers[i]->width(), + main_window->renderers[i]->height()); } device_force_redraw(); config_save(); } -void MainWindow::on_actionFullScreen_stretch_triggered() { +void +MainWindow::on_actionFullScreen_stretch_triggered() +{ video_fullscreen_scale = FULLSCR_SCALE_FULL; update_fullscreen_scale_checkboxes(ui, ui->actionFullScreen_stretch); } -void MainWindow::on_actionFullScreen_43_triggered() { +void +MainWindow::on_actionFullScreen_43_triggered() +{ video_fullscreen_scale = FULLSCR_SCALE_43; update_fullscreen_scale_checkboxes(ui, ui->actionFullScreen_43); } -void MainWindow::on_actionFullScreen_keepRatio_triggered() { +void +MainWindow::on_actionFullScreen_keepRatio_triggered() +{ video_fullscreen_scale = FULLSCR_SCALE_KEEPRATIO; update_fullscreen_scale_checkboxes(ui, ui->actionFullScreen_keepRatio); } -void MainWindow::on_actionFullScreen_int_triggered() { +void +MainWindow::on_actionFullScreen_int_triggered() +{ video_fullscreen_scale = FULLSCR_SCALE_INT; update_fullscreen_scale_checkboxes(ui, ui->actionFullScreen_int); } -static void update_greyscale_checkboxes(Ui::MainWindow* ui, QAction* selected, int value) { +void +MainWindow::on_actionFullScreen_int43_triggered() +{ + video_fullscreen_scale = FULLSCR_SCALE_INT43; + update_fullscreen_scale_checkboxes(ui, ui->actionFullScreen_int43); +} + +static void +update_greyscale_checkboxes(Ui::MainWindow *ui, QAction *selected, int value) +{ ui->actionRGB_Color->setChecked(ui->actionRGB_Color == selected); ui->actionRGB_Grayscale->setChecked(ui->actionRGB_Grayscale == selected); ui->actionAmber_monitor->setChecked(ui->actionAmber_monitor == selected); @@ -1369,33 +1597,45 @@ static void update_greyscale_checkboxes(Ui::MainWindow* ui, QAction* selected, i startblit(); video_grayscale = value; - video_copy = (video_grayscale || invert_display) ? video_transform_copy : memcpy; + video_copy = (video_grayscale || invert_display) ? video_transform_copy : memcpy; endblit(); device_force_redraw(); config_save(); } -void MainWindow::on_actionRGB_Color_triggered() { +void +MainWindow::on_actionRGB_Color_triggered() +{ update_greyscale_checkboxes(ui, ui->actionRGB_Color, 0); } -void MainWindow::on_actionRGB_Grayscale_triggered() { +void +MainWindow::on_actionRGB_Grayscale_triggered() +{ update_greyscale_checkboxes(ui, ui->actionRGB_Grayscale, 1); } -void MainWindow::on_actionAmber_monitor_triggered() { +void +MainWindow::on_actionAmber_monitor_triggered() +{ update_greyscale_checkboxes(ui, ui->actionAmber_monitor, 2); } -void MainWindow::on_actionGreen_monitor_triggered() { +void +MainWindow::on_actionGreen_monitor_triggered() +{ update_greyscale_checkboxes(ui, ui->actionGreen_monitor, 3); } -void MainWindow::on_actionWhite_monitor_triggered() { +void +MainWindow::on_actionWhite_monitor_triggered() +{ update_greyscale_checkboxes(ui, ui->actionWhite_monitor, 4); } -static void update_greyscale_type_checkboxes(Ui::MainWindow* ui, QAction* selected, int value) { +static void +update_greyscale_type_checkboxes(Ui::MainWindow *ui, QAction *selected, int value) +{ ui->actionBT601_NTSC_PAL->setChecked(ui->actionBT601_NTSC_PAL == selected); ui->actionBT709_HDTV->setChecked(ui->actionBT709_HDTV == selected); ui->actionAverage->setChecked(ui->actionAverage == selected); @@ -1405,38 +1645,55 @@ static void update_greyscale_type_checkboxes(Ui::MainWindow* ui, QAction* select config_save(); } -void MainWindow::on_actionBT601_NTSC_PAL_triggered() { +void +MainWindow::on_actionBT601_NTSC_PAL_triggered() +{ update_greyscale_type_checkboxes(ui, ui->actionBT601_NTSC_PAL, 0); } -void MainWindow::on_actionBT709_HDTV_triggered() { +void +MainWindow::on_actionBT709_HDTV_triggered() +{ update_greyscale_type_checkboxes(ui, ui->actionBT709_HDTV, 1); } -void MainWindow::on_actionAverage_triggered() { +void +MainWindow::on_actionAverage_triggered() +{ update_greyscale_type_checkboxes(ui, ui->actionAverage, 2); } -void MainWindow::on_actionAbout_Qt_triggered() +void +MainWindow::on_actionAbout_Qt_triggered() { QApplication::aboutQt(); } -void MainWindow::on_actionAbout_86Box_triggered() +void +MainWindow::on_actionAbout_86Box_triggered() { QMessageBox msgBox; msgBox.setTextFormat(Qt::RichText); - QString githash; + QString versioninfo; #ifdef EMU_GIT_HASH - githash = QString(" [%1]").arg(EMU_GIT_HASH); + versioninfo = QString(" [%1]").arg(EMU_GIT_HASH); #endif - msgBox.setText(QString("%3%1%2").arg(EMU_VERSION_FULL, githash, tr("86Box v"))); - msgBox.setInformativeText(tr("An emulator of old computers\n\nAuthors: Sarah Walker, Miran Grca, Fred N. van Kempen (waltje), SA1988, Tiseno100, reenigne, leilei, JohnElliott, greatpsycho, and others.\n\nReleased under the GNU General Public License version 2 or later. See LICENSE for more information.")); +#ifdef USE_DYNAREC +# ifdef USE_NEW_DYNAREC +# define DYNAREC_STR "new dynarec" +# else +# define DYNAREC_STR "old dynarec" +# endif +#else +# define DYNAREC_STR "no dynarec" +#endif + versioninfo.append(QString(" [%1, %2]").arg(QSysInfo::buildCpuArchitecture(), tr(DYNAREC_STR))); + msgBox.setText(QString("%3%1%2").arg(EMU_VERSION_FULL, versioninfo, tr("86Box v"))); + msgBox.setInformativeText(tr("An emulator of old computers\n\nAuthors: Miran GrÄa (OBattler), RichardG867, Jasmine Iwanek, TC1995, coldbrewed, Teemu Korhonen (Manaatti), Joakim L. Gilje, Adrien Moulin (elyosh), Daniel Balsom (gloriouscow), Cacodemon345, Fred N. van Kempen (waltje), Tiseno100, reenigne, and others.\n\nWith previous core contributions from Sarah Walker, leilei, JohnElliott, greatpsycho, and others.\n\nReleased under the GNU General Public License version 2 or later. See LICENSE for more information.")); msgBox.setWindowTitle("About 86Box"); msgBox.addButton("OK", QMessageBox::ButtonRole::AcceptRole); - auto webSiteButton = msgBox.addButton(QString::fromWCharArray(EMU_SITE_W), QMessageBox::ButtonRole::HelpRole); - webSiteButton->connect(webSiteButton, &QPushButton::released, []() - { + auto webSiteButton = msgBox.addButton(EMU_SITE, QMessageBox::ButtonRole::HelpRole); + webSiteButton->connect(webSiteButton, &QPushButton::released, []() { QDesktopServices::openUrl(QUrl("https://" EMU_SITE)); }); #ifdef RELEASE_BUILD @@ -1452,168 +1709,324 @@ void MainWindow::on_actionAbout_86Box_triggered() msgBox.exec(); } -void MainWindow::on_actionDocumentation_triggered() +void +MainWindow::on_actionDocumentation_triggered() { - QDesktopServices::openUrl(QUrl(EMU_DOCS_URL)); + QDesktopServices::openUrl(QUrl(EMU_DOCS_URL)); } -void MainWindow::on_actionCGA_PCjr_Tandy_EGA_S_VGA_overscan_triggered() { +void +MainWindow::on_actionCGA_PCjr_Tandy_EGA_S_VGA_overscan_triggered() +{ update_overscan = 1; video_toggle_option(ui->actionCGA_PCjr_Tandy_EGA_S_VGA_overscan, &enable_overscan); } -void MainWindow::on_actionChange_contrast_for_monochrome_display_triggered() { +void +MainWindow::on_actionChange_contrast_for_monochrome_display_triggered() +{ vid_cga_contrast ^= 1; cgapal_rebuild(); config_save(); } -void MainWindow::on_actionForce_4_3_display_ratio_triggered() { +void +MainWindow::on_actionForce_4_3_display_ratio_triggered() +{ video_toggle_option(ui->actionForce_4_3_display_ratio, &force_43); - video_force_resize_set(1); } -void MainWindow::on_actionRemember_size_and_position_triggered() +void +MainWindow::on_actionAuto_pause_triggered() +{ + do_auto_pause ^= 1; + ui->actionAuto_pause->setChecked(do_auto_pause > 0 ? true : false); +} + +void +MainWindow::on_actionRemember_size_and_position_triggered() { window_remember ^= 1; - window_w = ui->stackedWidget->width(); - window_h = ui->stackedWidget->height(); - if (!QApplication::platformName().contains("wayland")) { - window_x = geometry().x(); - window_y = geometry().y(); + if (!video_fullscreen) { + window_w = ui->stackedWidget->width(); + window_h = ui->stackedWidget->height(); + if (!QApplication::platformName().contains("wayland")) { + window_x = geometry().x(); + window_y = geometry().y(); + } + for (int i = 1; i < MONITORS_NUM; i++) { + if (window_remember && renderers[i]) { + monitor_settings[i].mon_window_w = renderers[i]->geometry().width(); + monitor_settings[i].mon_window_h = renderers[i]->geometry().height(); + monitor_settings[i].mon_window_x = renderers[i]->geometry().x(); + monitor_settings[i].mon_window_y = renderers[i]->geometry().y(); + } + } } ui->actionRemember_size_and_position->setChecked(window_remember); } -void MainWindow::on_actionSpecify_dimensions_triggered() +void +MainWindow::on_actionSpecify_dimensions_triggered() { SpecifyDimensions dialog(this); dialog.setWindowModality(Qt::WindowModal); dialog.exec(); } -void MainWindow::on_actionHiDPI_scaling_triggered() +void +MainWindow::on_actionHiDPI_scaling_triggered() { dpi_scale ^= 1; ui->actionHiDPI_scaling->setChecked(dpi_scale); - emit resizeContents(scrnsz_x, scrnsz_y); + emit resizeContents(monitors[0].mon_scrnsz_x, monitors[0].mon_scrnsz_y); + for (int i = 1; i < MONITORS_NUM; i++) { + if (renderers[i]) + emit resizeContentsMonitor(monitors[i].mon_scrnsz_x, monitors[i].mon_scrnsz_y, i); + } } -void MainWindow::on_actionHide_status_bar_triggered() +void +MainWindow::on_actionHide_status_bar_triggered() { + auto w = ui->stackedWidget->width(); + auto h = ui->stackedWidget->height(); hide_status_bar ^= 1; ui->actionHide_status_bar->setChecked(hide_status_bar); statusBar()->setVisible(!hide_status_bar); if (vid_resize >= 2) { - setFixedSize(fixed_size_x, fixed_size_y - + menuBar()->height() - + (hide_status_bar ? 0 : statusBar()->height()) - + (hide_tool_bar ? 0 : ui->toolBar->height())); + setFixedSize(fixed_size_x, fixed_size_y + menuBar()->height() + (hide_status_bar ? 0 : statusBar()->height()) + (hide_tool_bar ? 0 : ui->toolBar->height())); } else { int vid_resize_orig = vid_resize; - vid_resize = 0; - emit resizeContents(scrnsz_x, scrnsz_y); + vid_resize = 0; + emit resizeContents(w, h); vid_resize = vid_resize_orig; + if (vid_resize == 1) + setFixedSize(QWIDGETSIZE_MAX, QWIDGETSIZE_MAX); } } -void MainWindow::on_actionHide_tool_bar_triggered() +void +MainWindow::on_actionHide_tool_bar_triggered() { + auto w = ui->stackedWidget->width(); + auto h = ui->stackedWidget->height(); hide_tool_bar ^= 1; ui->actionHide_tool_bar->setChecked(hide_tool_bar); ui->toolBar->setVisible(!hide_tool_bar); if (vid_resize >= 2) { - setFixedSize(fixed_size_x, fixed_size_y - + menuBar()->height() - + (hide_status_bar ? 0 : statusBar()->height()) - + (hide_tool_bar ? 0 : ui->toolBar->height())); + setFixedSize(fixed_size_x, fixed_size_y + menuBar()->height() + (hide_status_bar ? 0 : statusBar()->height()) + (hide_tool_bar ? 0 : ui->toolBar->height())); } else { int vid_resize_orig = vid_resize; - vid_resize = 0; - emit resizeContents(scrnsz_x, scrnsz_y); + vid_resize = 0; + emit resizeContents(w, h); vid_resize = vid_resize_orig; + if (vid_resize == 1) + setFixedSize(QWIDGETSIZE_MAX, QWIDGETSIZE_MAX); } } -void MainWindow::on_actionUpdate_status_bar_icons_triggered() +void +MainWindow::on_actionUpdate_status_bar_icons_triggered() { update_icons ^= 1; ui->actionUpdate_status_bar_icons->setChecked(update_icons); + + /* Prevent icons staying when disabled during activity. */ + status->clearActivity(); } -void MainWindow::on_actionTake_screenshot_triggered() +void +MainWindow::on_actionTake_screenshot_triggered() { startblit(); - screenshots++; + for (int i = 0; i < MONITORS_NUM; i++) + monitors[i].mon_screenshots++; endblit(); device_force_redraw(); } -void MainWindow::on_actionSound_gain_triggered() +void +MainWindow::on_actionSound_gain_triggered() { SoundGain gain(this); gain.exec(); } -void MainWindow::setSendKeyboardInput(bool enabled) +void +MainWindow::setSendKeyboardInput(bool enabled) { send_keyboard_input = enabled; } -void MainWindow::on_actionOpenGL_3_0_Core_triggered() +void +MainWindow::updateUiPauseState() { - ui->stackedWidget->switchRenderer(RendererStack::Renderer::OpenGL3); - ui->actionSoftware_Renderer->setChecked(false); - ui->actionHardware_Renderer_OpenGL->setChecked(false); - ui->actionHardware_Renderer_OpenGL_ES->setChecked(false); - ui->actionOpenGL_3_0_Core->setChecked(true); - vid_api = 3; + auto pause_icon = dopause ? QIcon(":/menuicons/win/icons/run.ico") : QIcon(":/menuicons/win/icons/pause.ico"); + auto tooltip_text = dopause ? QString(tr("Resume execution")) : QString(tr("Pause execution")); + ui->actionPause->setIcon(pause_icon); + ui->actionPause->setToolTip(tooltip_text); } -void MainWindow::on_actionPreferences_triggered() +void +MainWindow::on_actionPreferences_triggered() { ProgSettings progsettings(this); progsettings.exec(); } - -void MainWindow::on_actionEnable_Discord_integration_triggered(bool checked) +void +MainWindow::on_actionEnable_Discord_integration_triggered(bool checked) { enable_discord = checked; - if(enable_discord) { +#ifdef DISCORD + if (enable_discord) { discord_init(); discord_update_activity(dopause); } else discord_close(); +#endif } -void MainWindow::showSettings() +void +MainWindow::showSettings() { - if (findChild() == nullptr) + if (findChild() == nullptr) ui->actionSettings->trigger(); } -void MainWindow::hardReset() +void +MainWindow::hardReset() { ui->actionHard_Reset->trigger(); } -void MainWindow::togglePause() +void +MainWindow::togglePause() { ui->actionPause->trigger(); } -void MainWindow::changeEvent(QEvent* event) +void +MainWindow::changeEvent(QEvent *event) { #ifdef Q_OS_WINDOWS - if (event->type() == QEvent::LanguageChange) - { + if (event->type() == QEvent::LanguageChange) { auto font_name = tr("FONT_NAME"); auto font_size = tr("FONT_SIZE"); QApplication::setFont(QFont(font_name, font_size.toInt())); } #endif QWidget::changeEvent(event); + if (isVisible()) { + monitor_settings[0].mon_window_maximized = isMaximized(); + config_save(); + } +} + +void +MainWindow::on_actionRenderer_options_triggered() +{ + auto dlg = ui->stackedWidget->getOptions(this); + + if (dlg) { + if (dlg->exec() == QDialog::Accepted) { + for (int i = 1; i < MONITORS_NUM; i++) { + if (renderers[i] && renderers[i]->hasOptions()) + renderers[i]->reloadOptions(); + } + } + } +} + +void +MainWindow::on_actionMCA_devices_triggered() +{ + auto dlg = new MCADeviceList(this); + + if (dlg) + dlg->exec(); +} + +void +MainWindow::on_actionShow_non_primary_monitors_triggered() +{ + show_second_monitors = (int) ui->actionShow_non_primary_monitors->isChecked(); + + blitDummied = true; + + if (show_second_monitors) { + for (int monitor_index = 1; monitor_index < MONITORS_NUM; monitor_index++) { + auto &secondaryRenderer = renderers[monitor_index]; + if (!renderers[monitor_index]) + continue; + secondaryRenderer->show(); + if (window_remember) { + secondaryRenderer->setGeometry(monitor_settings[monitor_index].mon_window_x < 120 ? 120 : monitor_settings[monitor_index].mon_window_x, + monitor_settings[monitor_index].mon_window_y < 120 ? 120 : monitor_settings[monitor_index].mon_window_y, + monitor_settings[monitor_index].mon_window_w > 2048 ? 2048 : monitor_settings[monitor_index].mon_window_w, + monitor_settings[monitor_index].mon_window_h > 2048 ? 2048 : monitor_settings[monitor_index].mon_window_h); + } + secondaryRenderer->switchRenderer((RendererStack::Renderer) vid_api); + ui->stackedWidget->switchRenderer((RendererStack::Renderer) vid_api); + } + } else { + for (int monitor_index = 1; monitor_index < MONITORS_NUM; monitor_index++) { + auto &secondaryRenderer = renderers[monitor_index]; + if (!renderers[monitor_index]) + continue; + secondaryRenderer->hide(); + if (window_remember && renderers[monitor_index]) { + monitor_settings[monitor_index].mon_window_w = renderers[monitor_index]->geometry().width(); + monitor_settings[monitor_index].mon_window_h = renderers[monitor_index]->geometry().height(); + monitor_settings[monitor_index].mon_window_x = renderers[monitor_index]->geometry().x(); + monitor_settings[monitor_index].mon_window_y = renderers[monitor_index]->geometry().y(); + } + } + } + + blitDummied = false; +} + +void +MainWindow::on_actionOpen_screenshots_folder_triggered() +{ + QDir(QString(usr_path) + QString("/screenshots/")).mkpath("."); + QDesktopServices::openUrl(QUrl(QString("file:///") + usr_path + QString("/screenshots/"))); +} + +void +MainWindow::on_actionApply_fullscreen_stretch_mode_when_maximized_triggered(bool checked) +{ + video_fullscreen_scale_maximized = checked; + + auto widget = ui->stackedWidget->currentWidget(); + ui->stackedWidget->onResize(widget->width(), widget->height()); + + for (int i = 1; i < MONITORS_NUM; i++) { + if (renderers[i]) + renderers[i]->onResize(renderers[i]->width(), renderers[i]->height()); + } + + device_force_redraw(); + config_save(); +} + +void MainWindow::on_actionCursor_Puck_triggered() +{ + tablet_tool_type = 0; + config_save(); +} + +void MainWindow::on_actionPen_triggered() +{ + tablet_tool_type = 1; + config_save(); +} + +void MainWindow::on_actionACPI_Shutdown_triggered() +{ + acpi_pwrbut_pressed = 1; } void MainWindow::on_actionShow_status_icons_in_fullscreen_triggered() diff --git a/src/qt/qt_mainwindow.hpp b/src/qt/qt_mainwindow.hpp index 90f7ddcff..553f9602c 100644 --- a/src/qt/qt_mainwindow.hpp +++ b/src/qt/qt_mainwindow.hpp @@ -7,8 +7,12 @@ #include #include +#include class MediaMenu; +class RendererStack; + +extern std::atomic blitDummied; namespace Ui { class MainWindow; @@ -16,63 +20,78 @@ class MainWindow; class MachineStatus; -class MainWindow : public QMainWindow -{ +class MainWindow : public QMainWindow { Q_OBJECT public: explicit MainWindow(QWidget *parent = nullptr); ~MainWindow(); - void showMessage(const QString& header, const QString& message); - void getTitle(wchar_t* title); - void blitToWidget(int x, int y, int w, int h); + void showMessage(int flags, const QString &header, const QString &message); + void getTitle(wchar_t *title); + void blitToWidget(int x, int y, int w, int h, int monitor_index); QSize getRenderWidgetSize(); - void setSendKeyboardInput(bool enabled); + void setSendKeyboardInput(bool enabled); + void checkFullscreenHotkey(); + + std::array, 8> renderers; signals: - void paint(const QImage& image); + void paint(const QImage &image); void resizeContents(int w, int h); - void pollMouse(); - void statusBarMessage(const QString& msg); + void resizeContentsMonitor(int w, int h, int monitor_index); + void statusBarMessage(const QString &msg); void updateStatusBarPanes(); void updateStatusBarActivity(int tag, bool active); void updateStatusBarEmpty(int tag, bool empty); void updateStatusBarTip(int tag); void updateMenuResizeOptions(); void updateWindowRememberOption(); + void initRendererMonitor(int monitor_index); + void destroyRendererMonitor(int monitor_index); + void initRendererMonitorForNonQtThread(int monitor_index); + void destroyRendererMonitorForNonQtThread(int monitor_index); + void hardResetCompleted(); - void setTitle(const QString& title); + void setTitle(const QString &title); void setFullscreen(bool state); void setMouseCapture(bool state); - void showMessageForNonQtThread(const QString& header, const QString& message); - void getTitleForNonQtThread(wchar_t* title); + void showMessageForNonQtThread(int flags, const QString &header, const QString &message); + void getTitleForNonQtThread(wchar_t *title); public slots: void showSettings(); void hardReset(); void togglePause(); + void initRendererMonitorSlot(int monitor_index); + void destroyRendererMonitorSlot(int monitor_index); + void updateUiPauseState(); private slots: void on_actionFullscreen_triggered(); void on_actionSettings_triggered(); void on_actionExit_triggered(); + void on_actionAuto_pause_triggered(); void on_actionPause_triggered(); void on_actionCtrl_Alt_Del_triggered(); void on_actionCtrl_Alt_Esc_triggered(); void on_actionHard_Reset_triggered(); void on_actionRight_CTRL_is_left_ALT_triggered(); void on_actionKeyboard_requires_capture_triggered(); - void on_actionHardware_Renderer_OpenGL_ES_triggered(); - void on_actionHardware_Renderer_OpenGL_triggered(); - void on_actionSoftware_Renderer_triggered(); void on_actionResizable_window_triggered(bool checked); void on_actionInverted_VGA_monitor_triggered(); void on_action0_5x_triggered(); void on_action1x_triggered(); void on_action1_5x_triggered(); void on_action2x_triggered(); + void on_action3x_triggered(); + void on_action4x_triggered(); + void on_action5x_triggered(); + void on_action6x_triggered(); + void on_action7x_triggered(); + void on_action8x_triggered(); void on_actionLinear_triggered(); void on_actionNearest_triggered(); void on_actionFullScreen_int_triggered(); + void on_actionFullScreen_int43_triggered(); void on_actionFullScreen_keepRatio_triggered(); void on_actionFullScreen_43_triggered(); void on_actionFullScreen_stretch_triggered(); @@ -96,44 +115,69 @@ private slots: void on_actionHide_status_bar_triggered(); void on_actionHide_tool_bar_triggered(); void on_actionUpdate_status_bar_icons_triggered(); + void on_actionTake_screenshot_triggered(); + void on_actionSound_gain_triggered(); + void on_actionPreferences_triggered(); + void on_actionEnable_Discord_integration_triggered(bool checked); + void on_actionRenderer_options_triggered(); void refreshMediaMenu(); - void showMessage_(const QString& header, const QString& message); - void getTitle_(wchar_t* title); - void on_actionTake_screenshot_triggered(); + void showMessage_(int flags, const QString &header, const QString &message); + void getTitle_(wchar_t *title); - void on_actionSound_gain_triggered(); - - void on_actionOpenGL_3_0_Core_triggered(); - - void on_actionPreferences_triggered(); - - void on_actionEnable_Discord_integration_triggered(bool checked); - - void on_actionShow_status_icons_in_fullscreen_triggered(); + void on_actionMCA_devices_triggered(); protected: - void keyPressEvent(QKeyEvent* event) override; - void keyReleaseEvent(QKeyEvent* event) override; - void focusInEvent(QFocusEvent* event) override; - void focusOutEvent(QFocusEvent* event) override; - bool eventFilter(QObject* receiver, QEvent* event) override; - void showEvent(QShowEvent* event) override; - void closeEvent(QCloseEvent* event) override; - void changeEvent(QEvent* event) override; + void keyPressEvent(QKeyEvent *event) override; + void keyReleaseEvent(QKeyEvent *event) override; + void focusInEvent(QFocusEvent *event) override; + void focusOutEvent(QFocusEvent *event) override; + bool eventFilter(QObject *receiver, QEvent *event) override; + void showEvent(QShowEvent *event) override; + void closeEvent(QCloseEvent *event) override; + void changeEvent(QEvent *event) override; + +private slots: + void on_actionPen_triggered(); + +private slots: + void on_actionCursor_Puck_triggered(); + + void on_actionACPI_Shutdown_triggered(); + void on_actionShow_status_icons_in_fullscreen_triggered(); + +private slots: + void on_actionShow_non_primary_monitors_triggered(); + + void on_actionOpen_screenshots_folder_triggered(); + + void on_actionApply_fullscreen_stretch_mode_when_maximized_triggered(bool checked); private: - Ui::MainWindow *ui; + Ui::MainWindow *ui; std::unique_ptr status; - std::shared_ptr mm; + std::shared_ptr mm; + + void processKeyboardInput(bool down, uint32_t keycode); +#ifdef Q_OS_MACOS + uint32_t last_modifiers = 0; + void processMacKeyboardInput(bool down, const QKeyEvent *event); +#endif /* If main window should send keyboard input */ bool send_keyboard_input = true; - bool shownonce = false; + bool shownonce = false; + bool resizableonce = false; + bool vnc_enabled = false; + + /* Full screen ON and OFF signals */ + bool fs_on_signal = false; + bool fs_off_signal = false; friend class SpecifyDimensions; friend class ProgSettings; friend class RendererCommon; + friend class RendererStack; // For UI variable access by non-primary renderer windows. }; #endif // QT_MAINWINDOW_HPP diff --git a/src/qt/qt_mainwindow.ui b/src/qt/qt_mainwindow.ui index 6803e6a8c..d682815bb 100644 --- a/src/qt/qt_mainwindow.ui +++ b/src/qt/qt_mainwindow.ui @@ -15,7 +15,7 @@ - + 0 0 @@ -37,7 +37,14 @@ 0 - + + + + 0 + 0 + + + @@ -47,23 +54,33 @@ 0 0 724 - 22 + 23 &Action + + + Tablet tool + + + + + + + + + - - @@ -82,6 +99,10 @@ + + + + @@ -95,6 +116,9 @@ + + + @@ -104,6 +128,12 @@ + + + + + + @@ -120,6 +150,7 @@ + @@ -151,10 +182,13 @@ + + + @@ -163,6 +197,7 @@ + @@ -195,6 +230,9 @@ toolBar + + true + false @@ -221,6 +259,7 @@ + @@ -228,6 +267,14 @@ + + + true + + + &Auto-pause on focus loss + + true @@ -328,12 +375,6 @@ &Fullscreen - - Ctrl+Alt+PgUp - - - false - @@ -342,6 +383,9 @@ &Qt (Software) + + 0 + @@ -350,6 +394,9 @@ Qt (&OpenGL) + + 1 + @@ -358,6 +405,9 @@ Qt (OpenGL &ES) + + 2 + @@ -452,6 +502,54 @@ &2x + + + true + + + &3x + + + + + true + + + &4x + + + + + true + + + &5x + + + + + true + + + &6x + + + + + true + + + &7x + + + + + true + + + &8x + + true @@ -500,6 +598,14 @@ &Integer scale + + + true + + + 4:&3 Integer scale + + true @@ -627,6 +733,9 @@ Open&GL (3.0 Core) + + 3 + @@ -657,7 +766,7 @@ - false + true @@ -670,7 +779,7 @@ ACPI Shutdown - false + true @@ -701,6 +810,78 @@ false + + + Renderer options... + + + + + true + + + &Vulkan + + + 4 + + + + + MCA devices... + + + + + true + + + Direct3D 9 + + + 5 + + + + + true + + + Show non-primary monitors + + + + + true + + + VNC + + + 6 + + + + + Open screenshots folder... + + + + + true + + + Apply fullscreen stretch mode when maximized + + + + + true + + + Cursor/Puck + + true @@ -709,6 +890,14 @@ Show status icons in fullscreen + + + true + + + Pen + + diff --git a/src/qt/qt_mcadevicelist.cpp b/src/qt/qt_mcadevicelist.cpp new file mode 100644 index 000000000..b8c3ed3c9 --- /dev/null +++ b/src/qt/qt_mcadevicelist.cpp @@ -0,0 +1,36 @@ +#include "qt_mcadevicelist.hpp" +#include "ui_qt_mcadevicelist.h" + +extern "C" { +#include <86box/86box.h> +#include <86box/video.h> +#include <86box/mca.h> +#include <86box/plat.h> +} + +MCADeviceList::MCADeviceList(QWidget *parent) + : QDialog(parent) + , ui(new Ui::MCADeviceList) +{ + ui->setupUi(this); + + startblit(); + if (mca_get_nr_cards() == 0) { + ui->listWidget->addItem(QObject::tr("No MCA devices.")); + ui->listWidget->setDisabled(true); + } else { + for (int i = 0; i < mca_get_nr_cards(); i++) { + uint32_t deviceId = (mca_read_index(0x00, i) | (mca_read_index(0x01, i) << 8)); + if (deviceId != 0xFFFF) { + QString hexRepresentation = QString::asprintf("%04X", deviceId); + ui->listWidget->addItem(QString("Slot %1: 0x%2 (@%3.ADF)").arg(i + 1).arg(hexRepresentation, hexRepresentation)); + } + } + } + endblit(); +} + +MCADeviceList::~MCADeviceList() +{ + delete ui; +} diff --git a/src/qt/qt_mcadevicelist.hpp b/src/qt/qt_mcadevicelist.hpp new file mode 100644 index 000000000..41b23c943 --- /dev/null +++ b/src/qt/qt_mcadevicelist.hpp @@ -0,0 +1,21 @@ +#ifndef QT_MCADEVICELIST_HPP +#define QT_MCADEVICELIST_HPP + +#include + +namespace Ui { +class MCADeviceList; +} + +class MCADeviceList : public QDialog { + Q_OBJECT + +public: + explicit MCADeviceList(QWidget *parent = nullptr); + ~MCADeviceList(); + +private: + Ui::MCADeviceList *ui; +}; + +#endif // QT_MCADEVICELIST_HPP diff --git a/src/qt/qt_mcadevicelist.ui b/src/qt/qt_mcadevicelist.ui new file mode 100644 index 000000000..2efac1886 --- /dev/null +++ b/src/qt/qt_mcadevicelist.ui @@ -0,0 +1,74 @@ + + + MCADeviceList + + + + 0 + 0 + 400 + 300 + + + + MCA devices + + + + + + List of MCA devices: + + + + + + + + + + Qt::Horizontal + + + QDialogButtonBox::Ok + + + + + + + + + buttonBox + accepted() + MCADeviceList + accept() + + + 248 + 254 + + + 157 + 274 + + + + + buttonBox + rejected() + MCADeviceList + reject() + + + 316 + 260 + + + 286 + 274 + + + + + diff --git a/src/qt/qt_mediahistorymanager.cpp b/src/qt/qt_mediahistorymanager.cpp new file mode 100644 index 000000000..9d003f464 --- /dev/null +++ b/src/qt/qt_mediahistorymanager.cpp @@ -0,0 +1,343 @@ +/* + * 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. + * + * Media history management module + * + * + * + * Authors: cold-brewed + * + * Copyright 2022 The 86Box development team + */ + +#include +#include +#include +#include +#include +#include "qt_mediahistorymanager.hpp" + +extern "C" { +#include <86box/timer.h> +#include <86box/cdrom.h> +#include <86box/fdd.h> +} + +namespace ui { + +MediaHistoryManager::MediaHistoryManager() +{ + initializeImageHistory(); + deserializeAllImageHistory(); + initialDeduplication(); +} + +MediaHistoryManager::~MediaHistoryManager() + = default; + +master_list_t & +MediaHistoryManager::blankImageHistory(master_list_t &initialized_master_list) const +{ + for (const auto device_type : ui::AllSupportedMediaHistoryTypes) { + device_media_history_t device_media_history; + // Loop for all possible media devices + for (int device_index = 0; device_index < maxDevicesSupported(device_type); device_index++) { + device_index_list_t indexing_list; + device_media_history[device_index] = indexing_list; + // Loop for each history slot + for (int slot_index = 0; slot_index < max_images; slot_index++) { + device_media_history[device_index].append(QString()); + } + } + initialized_master_list.insert(device_type, device_media_history); + } + return initialized_master_list; +} + +const device_index_list_t & +MediaHistoryManager::getHistoryListForDeviceIndex(int index, ui::MediaType type) +{ + if (master_list.contains(type)) { + if ((index >= 0) && (index < master_list[type].size())) { + return master_list[type][index]; + } else { + qWarning("Media device index %i for device type %s was requested but index %i is out of range (valid range: >= 0 && < %lli)", + index, mediaTypeToString(type).toUtf8().constData(), index, static_cast(master_list[type].size())); + } + } + // Failure gets an empty list + return empty_device_index_list; +} + +void +MediaHistoryManager::setHistoryListForDeviceIndex(int index, ui::MediaType type, device_index_list_t history_list) +{ + master_list[type][index] = std::move(history_list); +} + +QString +MediaHistoryManager::getImageForSlot(int index, int slot, ui::MediaType type) +{ + QString image_name; + device_index_list_t device_history = getHistoryListForDeviceIndex(index, type); + if ((slot >= 0) && (slot < device_history.size())) { + image_name = device_history[slot]; + } else { + qWarning("Media history slot %i, index %i for device type %s was requested but slot %i is out of range (valid range: >= 0 && < %i, device_history.size() is %lli)", + slot, index, mediaTypeToString(type).toUtf8().constData(), slot, maxDevicesSupported(type), static_cast(device_history.size())); + } + return image_name; +} + +// These are hardcoded since we can't include the various +// header files where they are defined (e.g., fdd.h, mo.h). +// However, all in ui::MediaType support 4 except cassette. +int +MediaHistoryManager::maxDevicesSupported(ui::MediaType type) +{ + return type == ui::MediaType::Cassette ? 1 : 4; +} + +void +MediaHistoryManager::deserializeImageHistoryType(ui::MediaType type) +{ + for (int device = 0; device < maxDevicesSupported(type); device++) { + char **device_history_ptr = getEmuHistoryVarForType(type, device); + if (device_history_ptr == nullptr) { + // Device not supported, return and do not deserialize. + // This will leave the image listing at the default initialization state + // from the ui side (this class) + continue; + } + for (int slot = 0; slot < MAX_PREV_IMAGES; slot++) { + master_list[type][device][slot] = device_history_ptr[slot]; + } + } +} +void +MediaHistoryManager::deserializeAllImageHistory() +{ + for (const auto device_type : ui::AllSupportedMediaHistoryTypes) { + deserializeImageHistoryType(device_type); + } +} +void +MediaHistoryManager::serializeImageHistoryType(ui::MediaType type) +{ + for (int device = 0; device < maxDevicesSupported(type); device++) { + char **device_history_ptr = getEmuHistoryVarForType(type, device); + if (device_history_ptr == nullptr) { + // Device not supported, return and do not serialize. + // This will leave the image listing at the current state, + // and it will not be saved on the emu side + continue; + } + for (int slot = 0; slot < MAX_PREV_IMAGES; slot++) { + if (device_history_ptr[slot] != nullptr) { + strncpy(device_history_ptr[slot], master_list[type][device][slot].toUtf8().constData(), MAX_IMAGE_PATH_LEN); + } + } + } +} + +void +MediaHistoryManager::serializeAllImageHistory() +{ + for (const auto device_type : ui::AllSupportedMediaHistoryTypes) { + serializeImageHistoryType(device_type); + } +} + +void +MediaHistoryManager::initialDeduplication() +{ + + QString current_image; + // Perform initial dedup if an image is loaded + for (const auto device_type : ui::AllSupportedMediaHistoryTypes) { + for (int device_index = 0; device_index < maxDevicesSupported(device_type); device_index++) { + device_index_list_t device_history = getHistoryListForDeviceIndex(device_index, device_type); + switch (device_type) { + case ui::MediaType::Optical: + current_image = cdrom[device_index].image_path; + break; + case ui::MediaType::Floppy: + current_image = floppyfns[device_index]; + break; + default: + continue; + break; + } + deduplicateList(device_history, QVector(1, current_image)); + // Fill in missing, if any + int missing = MAX_PREV_IMAGES - device_history.size(); + if (missing) { + for (int i = 0; i < missing; i++) { + device_history.push_back(QString()); + } + } + setHistoryListForDeviceIndex(device_index, device_type, device_history); + } + } +} + +char ** +MediaHistoryManager::getEmuHistoryVarForType(ui::MediaType type, int index) +{ + switch (type) { + case ui::MediaType::Optical: + return &cdrom[index].image_history[0]; + case ui::MediaType::Floppy: + return &fdd_image_history[index][0]; + default: + return nullptr; + } +} + +device_index_list_t & +MediaHistoryManager::deduplicateList(device_index_list_t &device_history, const QVector &filenames) +{ + QVector items_to_delete; + for (auto &list_item_path : device_history) { + if (list_item_path.isEmpty()) { + continue; + } + for (const auto &path_to_check : filenames) { + if (path_to_check.isEmpty()) { + continue; + } + QString adjusted_path = pathAdjustSingle(path_to_check); + int match = QString::localeAwareCompare(list_item_path, adjusted_path); + if (match == 0) { + items_to_delete.append(list_item_path); + } + } + } + // Remove by name rather than index because the index would change + // after each removal + for (const auto &path : items_to_delete) { + device_history.removeAll(path); + } + return device_history; +} + +void +MediaHistoryManager::addImageToHistory(int index, ui::MediaType type, const QString &image_name, const QString &new_image_name) +{ + device_index_list_t device_history = getHistoryListForDeviceIndex(index, type); + QVector files_to_check; + + files_to_check.append(image_name); + files_to_check.append(new_image_name); + device_history = deduplicateList(device_history, files_to_check); + + if (!image_name.isEmpty()) { + device_history.push_front(image_name); + } + + // Pop any extras + if (device_history.size() > MAX_PREV_IMAGES) { + device_history.pop_back(); + } + + // Fill in missing, if any + int missing = MAX_PREV_IMAGES - device_history.size(); + if (missing) { + for (int i = 0; i < missing; i++) { + device_history.push_back(QString()); + } + } + + device_history = removeMissingImages(device_history); + device_history = pathAdjustFull(device_history); + + setHistoryListForDeviceIndex(index, type, device_history); + serializeImageHistoryType(type); +} + +QString +MediaHistoryManager::mediaTypeToString(ui::MediaType type) +{ + QMetaEnum qme = QMetaEnum::fromType(); + return qme.valueToKey(static_cast(type)); +} + +QString +MediaHistoryManager::pathAdjustSingle(QString checked_path) +{ + QString current_usr_path = getUsrPath(); + QFileInfo file_info(checked_path); + if (file_info.filePath().isEmpty() || current_usr_path.isEmpty() || file_info.isRelative()) { + return checked_path; + } + if (file_info.filePath().startsWith(current_usr_path)) { + checked_path = file_info.filePath().remove(current_usr_path); + } + return checked_path; +} + +device_index_list_t & +MediaHistoryManager::pathAdjustFull(device_index_list_t &device_history) +{ + for (auto &checked_path : device_history) { + checked_path = pathAdjustSingle(checked_path); + } + return device_history; +} +QString +MediaHistoryManager::getUsrPath() +{ + QString current_usr_path(usr_path); + // Ensure `usr_path` has a trailing slash + return current_usr_path.endsWith("/") ? current_usr_path : current_usr_path.append("/"); +} +device_index_list_t & +MediaHistoryManager::removeMissingImages(device_index_list_t &device_history) +{ + for (auto &checked_path : device_history) { + QFileInfo file_info(checked_path); + if (file_info.filePath().isEmpty()) { + continue; + } + // For this check, explicitly prepend `usr_path` to relative paths to account for $CWD platform variances + QFileInfo absolute_path = file_info.isRelative() ? QFileInfo(getUsrPath().append(file_info.filePath())) : file_info; + if (!absolute_path.exists()) { + qWarning("Image file %s does not exist - removing from history", qPrintable(file_info.filePath())); + checked_path = ""; + } + } + return device_history; +} + +void +MediaHistoryManager::initializeImageHistory() +{ + auto initial_master_list = getMasterList(); + setMasterList(blankImageHistory(initial_master_list)); +} + +const master_list_t & +MediaHistoryManager::getMasterList() const +{ + return master_list; +} + +void +MediaHistoryManager::setMasterList(const master_list_t &masterList) +{ + master_list = masterList; +} + +void +MediaHistoryManager::clearImageHistory() +{ + initializeImageHistory(); + serializeAllImageHistory(); +} + +} // ui \ No newline at end of file diff --git a/src/qt/qt_mediahistorymanager.hpp b/src/qt/qt_mediahistorymanager.hpp new file mode 100644 index 000000000..4eae46f9c --- /dev/null +++ b/src/qt/qt_mediahistorymanager.hpp @@ -0,0 +1,140 @@ +/* + * 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. + * + * Header for the media history management module + * + * + * + * Authors: cold-brewed + * + * Copyright 2022 The 86Box development team + */ + +#ifndef QT_MEDIAHISTORYMANAGER_HPP +#define QT_MEDIAHISTORYMANAGER_HPP + +#include +#include +#include + +#include + +extern "C" { +#include <86box/86box.h> +} + +// This macro helps give us the required `qHash()` function in order to use the +// enum as a hash key +#define QHASH_FOR_CLASS_ENUM(T) \ + inline uint qHash(const T &t, uint seed) \ + { \ + return ::qHash(static_cast::type>(t), seed); \ + } + +typedef QVector device_index_list_t; +typedef QHash> device_media_history_t; + +namespace ui { +Q_NAMESPACE + +enum class MediaType { + Floppy, + Optical, + Zip, + Mo, + Cassette +}; +// This macro allows us to do a reverse lookup of the enum with `QMetaEnum` +Q_ENUM_NS(MediaType) + +QHASH_FOR_CLASS_ENUM(MediaType) + +typedef QHash master_list_t; + +// Used to iterate over all supported types when preparing data structures +// Also useful to indicate which types support history +static const MediaType AllSupportedMediaHistoryTypes[] = { + MediaType::Optical, + MediaType::Floppy, +}; + +class MediaHistoryManager { + +public: + MediaHistoryManager(); + virtual ~MediaHistoryManager(); + + // Get the image name for a particular slot, + // index, and type combination + QString getImageForSlot(int index, int slot, ui::MediaType type); + + // Add an image to history + void addImageToHistory(int index, ui::MediaType type, const QString &image_name, const QString &new_image_name); + + // Convert the enum value to a string + static QString mediaTypeToString(ui::MediaType type); + + // Clear out the image history + void clearImageHistory(); + +private: + int max_images = MAX_PREV_IMAGES; + + // Main hash of hash of vector of strings + master_list_t master_list; + [[nodiscard]] const master_list_t &getMasterList() const; + void setMasterList(const master_list_t &masterList); + + device_index_list_t index_list; + device_index_list_t empty_device_index_list; + + // Return a blank, initialized image history list + master_list_t &blankImageHistory(master_list_t &initialized_master_list) const; + + // Initialize the image history + void initializeImageHistory(); + + // Max number of devices supported by media type + static int maxDevicesSupported(ui::MediaType type); + + // Serialize the data back into the C array + // on the emu side + void serializeImageHistoryType(ui::MediaType type); + void serializeAllImageHistory(); + + // Deserialize the data from C array on the emu side + // for the ui side + void deserializeImageHistoryType(ui::MediaType type); + void deserializeAllImageHistory(); + + // Get emu history variable for a device type + static char **getEmuHistoryVarForType(ui::MediaType type, int index); + + // Get or set the history for a specific device/index combo + const device_index_list_t &getHistoryListForDeviceIndex(int index, ui::MediaType type); + void setHistoryListForDeviceIndex(int index, ui::MediaType type, device_index_list_t history_list); + + // Remove missing image files from history list + static device_index_list_t &removeMissingImages(device_index_list_t &device_history); + + // If an absolute path is contained within `usr_path`, convert to a relative path + static device_index_list_t &pathAdjustFull(device_index_list_t &device_history); + static QString pathAdjustSingle(QString checked_path); + + // Deduplicate history entries + static device_index_list_t &deduplicateList(device_index_list_t &device_history, const QVector &filenames); + void initialDeduplication(); + + // Gets the `usr_path` from the emu side and appends a + // trailing slash if necessary + static QString getUsrPath(); +}; + +} // ui + +#endif // QT_MEDIAHISTORYMANAGER_HPP diff --git a/src/qt/qt_mediamenu.cpp b/src/qt/qt_mediamenu.cpp index 8ffccffdd..26169b0d0 100644 --- a/src/qt/qt_mediamenu.cpp +++ b/src/qt/qt_mediamenu.cpp @@ -1,38 +1,41 @@ /* - * 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. + * 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. + * This file is part of the 86Box distribution. * - * Media menu UI module. + * Media menu UI module. * * * - * Authors: Joakim L. Gilje + * Authors: Joakim L. Gilje * Cacodemon345 * Teemu Korhonen * - * Copyright 2021 Joakim L. Gilje - * Copyright 2021-2022 Cacodemon345 - * Copyright 2021-2022 Teemu Korhonen + * Copyright 2021 Joakim L. Gilje + * Copyright 2021-2022 Cacodemon345 + * Copyright 2021-2022 Teemu Korhonen */ -#include "qt_mediamenu.hpp" - +#include "qt_progsettings.hpp" #include "qt_machinestatus.hpp" #include #include #include #include +#include +#include extern "C" { +#include <86box/86box.h> #include <86box/config.h> #include <86box/device.h> #include <86box/timer.h> #include <86box/plat.h> #include <86box/cassette.h> +#include <86box/machine.h> #include <86box/cartridge.h> #include <86box/fdd.h> #include <86box/fdd_86f.h> @@ -42,21 +45,30 @@ extern "C" { #include <86box/mo.h> #include <86box/sound.h> #include <86box/ui.h> +#include <86box/thread.h> +#include <86box/network.h> }; #include "qt_newfloppydialog.hpp" #include "qt_util.hpp" +#include "qt_deviceconfig.hpp" +#include "qt_mediahistorymanager.hpp" +#include "qt_mediamenu.hpp" std::shared_ptr MediaMenu::ptr; -MediaMenu::MediaMenu(QWidget* parent) : QObject(parent) { +MediaMenu::MediaMenu(QWidget *parent) + : QObject(parent) +{ parentWidget = parent; } -void MediaMenu::refresh(QMenu *parentMenu) { +void +MediaMenu::refresh(QMenu *parentMenu) +{ parentMenu->clear(); - if(MachineStatus::hasCassette()) { + if (MachineStatus::hasCassette()) { cassetteMenu = parentMenu->addMenu(""); cassetteMenu->addAction(tr("&New image..."), [this]() { cassetteNewImage(); }); cassetteMenu->addSeparator(); @@ -79,8 +91,8 @@ void MediaMenu::refresh(QMenu *parentMenu) { cartridgeMenus.clear(); if (machine_has_cartridge(machine)) { - for(int i = 0; i < 2; i++) { - auto* menu = parentMenu->addMenu(""); + for (int i = 0; i < 2; i++) { + auto *menu = parentMenu->addMenu(""); menu->addAction(tr("&Image..."), [this, i]() { cartridgeSelectImage(i); }); menu->addSeparator(); cartridgeEjectPos = menu->children().count(); @@ -92,12 +104,17 @@ void MediaMenu::refresh(QMenu *parentMenu) { floppyMenus.clear(); MachineStatus::iterateFDD([this, parentMenu](int i) { - auto* menu = parentMenu->addMenu(""); + auto *menu = parentMenu->addMenu(""); menu->addAction(tr("&New image..."), [this, i]() { floppyNewImage(i); }); menu->addSeparator(); menu->addAction(tr("&Existing image..."), [this, i]() { floppySelectImage(i, false); }); menu->addAction(tr("Existing image (&Write-protected)..."), [this, i]() { floppySelectImage(i, true); }); menu->addSeparator(); + for (int slot = 0; slot < MAX_PREV_IMAGES; slot++) { + floppyImageHistoryPos[slot] = menu->children().count(); + menu->addAction(QString::asprintf(tr("Image %i").toUtf8().constData(), slot), [this, i, slot]() { floppyMenuSelect(i, slot); })->setCheckable(false); + } + menu->addSeparator(); floppyExportPos = menu->children().count(); menu->addAction(tr("E&xport to 86F..."), [this, i]() { floppyExportTo86f(i); }); menu->addSeparator(); @@ -109,24 +126,28 @@ void MediaMenu::refresh(QMenu *parentMenu) { cdromMenus.clear(); MachineStatus::iterateCDROM([this, parentMenu](int i) { - auto* menu = parentMenu->addMenu(""); + auto *menu = parentMenu->addMenu(""); cdromMutePos = menu->children().count(); - menu->addAction(tr("&Mute"), [this, i]() { cdromMute(i); })->setCheckable(true); + menu->addAction(QApplication::style()->standardIcon(QStyle::SP_MediaVolumeMuted), tr("&Mute"), [this, i]() { cdromMute(i); })->setCheckable(true); menu->addSeparator(); - cdromEmptyPos = menu->children().count(); - menu->addAction(tr("E&mpty"), [this, i]() { cdromEject(i); })->setCheckable(true); - cdromReloadPos = menu->children().count(); - menu->addAction(tr("&Reload previous image"), [this, i]() { cdromReload(i); }); + menu->addAction(ProgSettings::loadIcon("/cdrom.ico"), tr("&Image..."), [this, i]() { cdromMount(i, 0); })->setCheckable(false); + menu->addAction(QApplication::style()->standardIcon(QStyle::SP_DirIcon), tr("&Folder..."), [this, i]() { cdromMount(i, 1); })->setCheckable(false); + menu->addSeparator(); + for (int slot = 0; slot < MAX_PREV_IMAGES; slot++) { + cdromImageHistoryPos[slot] = menu->children().count(); + menu->addAction(QString::asprintf(tr("Image %i").toUtf8().constData(), slot), [this, i, slot]() { cdromReload(i, slot); })->setCheckable(false); + } menu->addSeparator(); cdromImagePos = menu->children().count(); - menu->addAction(tr("&Image"), [this, i]() { cdromMount(i); })->setCheckable(true); + cdromDirPos = menu->children().count(); + menu->addAction(tr("E&ject"), [this, i]() { cdromEject(i); })->setCheckable(false); cdromMenus[i] = menu; cdromUpdateMenu(i); }); zipMenus.clear(); MachineStatus::iterateZIP([this, parentMenu](int i) { - auto* menu = parentMenu->addMenu(""); + auto *menu = parentMenu->addMenu(""); menu->addAction(tr("&New image..."), [this, i]() { zipNewImage(i); }); menu->addSeparator(); menu->addAction(tr("&Existing image..."), [this, i]() { zipSelectImage(i, false); }); @@ -142,7 +163,7 @@ void MediaMenu::refresh(QMenu *parentMenu) { moMenus.clear(); MachineStatus::iterateMO([this, parentMenu](int i) { - auto* menu = parentMenu->addMenu(""); + auto *menu = parentMenu->addMenu(""); menu->addAction(tr("&New image..."), [this, i]() { moNewImage(i); }); menu->addSeparator(); menu->addAction(tr("&Existing image..."), [this, i]() { moSelectImage(i, false); }); @@ -155,40 +176,57 @@ void MediaMenu::refresh(QMenu *parentMenu) { moMenus[i] = menu; moUpdateMenu(i); }); + + netMenus.clear(); + MachineStatus::iterateNIC([this, parentMenu](int i) { + auto *menu = parentMenu->addMenu(""); + netDisconnPos = menu->children().count(); + auto *action = menu->addAction(tr("&Connected"), [this, i] { network_is_connected(i) ? nicDisconnect(i) : nicConnect(i); }); + action->setCheckable(true); + netMenus[i] = menu; + nicUpdateMenu(i); + }); + parentMenu->addAction(tr("Clear image history"), [this]() { clearImageHistory(); }); } -void MediaMenu::cassetteNewImage() { - auto filename = QFileDialog::getSaveFileName(parentWidget, tr("Create...")); +void +MediaMenu::cassetteNewImage() +{ + auto filename = QFileDialog::getSaveFileName(parentWidget, tr("Create...")); QFileInfo fileinfo(filename); if (fileinfo.suffix().isEmpty()) { filename.append(".cas"); } if (!filename.isNull()) { - if (filename.isEmpty()) cassetteEject(); - else cassetteMount(filename, false); + if (filename.isEmpty()) + cassetteEject(); + else + cassetteMount(filename, false); } } -void MediaMenu::cassetteSelectImage(bool wp) { +void +MediaMenu::cassetteSelectImage(bool wp) +{ auto filename = QFileDialog::getOpenFileName(parentWidget, - QString(), - QString(), - tr("Cassette images") % - util::DlgFilter({ "pcm","raw","wav","cas" }) % - tr("All files") % - util::DlgFilter({ "*" }, true)); + QString(), + getMediaOpenDirectory(), + tr("Cassette images") % util::DlgFilter({ "pcm", "raw", "wav", "cas" }) % tr("All files") % util::DlgFilter({ "*" }, true)); - if (!filename.isEmpty()) cassetteMount(filename, wp); + if (!filename.isEmpty()) + cassetteMount(filename, wp); } -void MediaMenu::cassetteMount(const QString& filename, bool wp) { +void +MediaMenu::cassetteMount(const QString &filename, bool wp) +{ pc_cas_set_fname(cassette, nullptr); memset(cassette_fname, 0, sizeof(cassette_fname)); cassette_ui_writeprot = wp ? 1 : 0; - if (! filename.isEmpty()) { + if (!filename.isEmpty()) { QByteArray filenameBytes = filename.toUtf8(); - strncpy(cassette_fname, filenameBytes.data(), sizeof(cassette_fname)); + strncpy(cassette_fname, filenameBytes.data(), sizeof(cassette_fname) - 1); pc_cas_set_fname(cassette, cassette_fname); } @@ -198,7 +236,9 @@ void MediaMenu::cassetteMount(const QString& filename, bool wp) { config_save(); } -void MediaMenu::cassetteEject() { +void +MediaMenu::cassetteEject() +{ pc_cas_set_fname(cassette, nullptr); memset(cassette_fname, 0, sizeof(cassette_fname)); ui_sb_update_icon_state(SB_CASSETTE, 1); @@ -207,15 +247,17 @@ void MediaMenu::cassetteEject() { config_save(); } -void MediaMenu::cassetteUpdateMenu() { - QString name = cassette_fname; - QString mode = cassette_mode; - auto childs = cassetteMenu->children(); - auto* recordMenu = dynamic_cast(childs[cassetteRecordPos]); - auto* playMenu = dynamic_cast(childs[cassettePlayPos]); - auto* rewindMenu = dynamic_cast(childs[cassetteRewindPos]); - auto* fastFwdMenu = dynamic_cast(childs[cassetteFastFwdPos]); - auto* ejectMenu = dynamic_cast(childs[cassetteEjectPos]); +void +MediaMenu::cassetteUpdateMenu() +{ + QString name = cassette_fname; + QString mode = cassette_mode; + auto childs = cassetteMenu->children(); + auto *recordMenu = dynamic_cast(childs[cassetteRecordPos]); + auto *playMenu = dynamic_cast(childs[cassettePlayPos]); + auto *rewindMenu = dynamic_cast(childs[cassetteRewindPos]); + auto *fastFwdMenu = dynamic_cast(childs[cassetteFastFwdPos]); + auto *ejectMenu = dynamic_cast(childs[cassetteEjectPos]); recordMenu->setEnabled(!name.isEmpty()); playMenu->setEnabled(!name.isEmpty()); @@ -225,24 +267,14 @@ void MediaMenu::cassetteUpdateMenu() { bool isSaving = mode == QStringLiteral("save"); recordMenu->setChecked(isSaving); - playMenu->setChecked(! isSaving); + playMenu->setChecked(!isSaving); cassetteMenu->setTitle(QString::asprintf(tr("Cassette: %s").toUtf8().constData(), (name.isEmpty() ? tr("(empty)") : name).toUtf8().constData())); } -void MediaMenu::cartridgeSelectImage(int i) { - auto filename = QFileDialog::getOpenFileName( - parentWidget, - QString(), - QString(), - tr("Cartridge images") % - util::DlgFilter({ "a","b","jrc" }) % - tr("All files") % - util::DlgFilter({ "*" }, true)); - - if (filename.isEmpty()) { - return; - } +void +MediaMenu::cartridgeMount(int i, const QString &filename) +{ cart_close(i); QByteArray filenameBytes = filename.toUtf8(); cart_load(i, filenameBytes.data()); @@ -253,7 +285,24 @@ void MediaMenu::cartridgeSelectImage(int i) { config_save(); } -void MediaMenu::cartridgeEject(int i) { +void +MediaMenu::cartridgeSelectImage(int i) +{ + auto filename = QFileDialog::getOpenFileName( + parentWidget, + QString(), + getMediaOpenDirectory(), + tr("Cartridge images") % util::DlgFilter({ "a", "b", "jrc" }) % tr("All files") % util::DlgFilter({ "*" }, true)); + + if (filename.isEmpty()) { + return; + } + cartridgeMount(i, filename); +} + +void +MediaMenu::cartridgeEject(int i) +{ cart_close(i); ui_sb_update_icon_state(SB_CARTRIDGE | i, 1); cartridgeUpdateMenu(i); @@ -261,31 +310,37 @@ void MediaMenu::cartridgeEject(int i) { config_save(); } -void MediaMenu::cartridgeUpdateMenu(int i) { - QString name = cart_fns[i]; - auto* menu = cartridgeMenus[i]; - auto childs = menu->children(); - auto* ejectMenu = dynamic_cast(childs[cartridgeEjectPos]); +void +MediaMenu::cartridgeUpdateMenu(int i) +{ + QString name = cart_fns[i]; + auto *menu = cartridgeMenus[i]; + auto childs = menu->children(); + auto *ejectMenu = dynamic_cast(childs[cartridgeEjectPos]); ejectMenu->setEnabled(!name.isEmpty()); - //menu->setTitle(tr("Cartridge %1: %2").arg(QString::number(i+1), name.isEmpty() ? tr("(empty)") : name)); + // menu->setTitle(tr("Cartridge %1: %2").arg(QString::number(i+1), name.isEmpty() ? tr("(empty)") : name)); menu->setTitle(QString::asprintf(tr("Cartridge %i: %ls").toUtf8().constData(), i + 1, name.isEmpty() ? tr("(empty)").toStdU16String().data() : name.toStdU16String().data())); } -void MediaMenu::floppyNewImage(int i) { +void +MediaMenu::floppyNewImage(int i) +{ NewFloppyDialog dialog(NewFloppyDialog::MediaType::Floppy, parentWidget); switch (dialog.exec()) { - case QDialog::Accepted: - QByteArray filename = dialog.fileName().toUtf8(); - floppyMount(i, filename, false); - break; + case QDialog::Accepted: + QByteArray filename = dialog.fileName().toUtf8(); + floppyMount(i, filename, false); + break; } } -void MediaMenu::floppySelectImage(int i, bool wp) { +void +MediaMenu::floppySelectImage(int i, bool wp) +{ auto filename = QFileDialog::getOpenFileName( parentWidget, QString(), - QString(), + getMediaOpenDirectory(), tr("All images") % util::DlgFilter({ "0??","1??","??0","86f","bin","cq?","d??","flp","hdm","im?","json","td0","*fd?","mfm","xdf" }) % tr("Advanced sector images") % @@ -302,20 +357,27 @@ void MediaMenu::floppySelectImage(int i, bool wp) { if (!filename.isEmpty()) floppyMount(i, filename, wp); } -void MediaMenu::floppyMount(int i, const QString &filename, bool wp) { +void +MediaMenu::floppyMount(int i, const QString &filename, bool wp) +{ + auto previous_image = QFileInfo(floppyfns[i]); fdd_close(i); ui_writeprot[i] = wp ? 1 : 0; - if (! filename.isEmpty()) { + if (!filename.isEmpty()) { QByteArray filenameBytes = filename.toUtf8(); fdd_load(i, filenameBytes.data()); } ui_sb_update_icon_state(SB_FLOPPY | i, filename.isEmpty() ? 1 : 0); + mhm.addImageToHistory(i, ui::MediaType::Floppy, previous_image.filePath(), filename); floppyUpdateMenu(i); ui_sb_update_tip(SB_FLOPPY | i); config_save(); } -void MediaMenu::floppyEject(int i) { +void +MediaMenu::floppyEject(int i) +{ + mhm.addImageToHistory(i, ui::MediaType::Floppy, floppyfns[i], QString()); fdd_close(i); ui_sb_update_icon_state(SB_FLOPPY | i, 1); floppyUpdateMenu(i); @@ -323,9 +385,11 @@ void MediaMenu::floppyEject(int i) { config_save(); } -void MediaMenu::floppyExportTo86f(int i) { +void +MediaMenu::floppyExportTo86f(int i) +{ auto filename = QFileDialog::getSaveFileName(parentWidget, QString(), QString(), tr("Surface images") % util::DlgFilter({ "86f" }, true)); - if (! filename.isEmpty()) { + if (!filename.isEmpty()) { QByteArray filenameBytes = filename.toUtf8(); plat_pause(1); if (d86f_export(i, filenameBytes.data()) == 0) { @@ -335,45 +399,54 @@ void MediaMenu::floppyExportTo86f(int i) { } } -void MediaMenu::floppyUpdateMenu(int i) { - QString name = floppyfns[i]; +void +MediaMenu::floppyUpdateMenu(int i) +{ + QString name = floppyfns[i]; + QFileInfo fi(floppyfns[i]); - auto* menu = floppyMenus[i]; - auto childs = menu->children(); + if (!floppyMenus.contains(i)) + return; - auto* ejectMenu = dynamic_cast(childs[floppyEjectPos]); - auto* exportMenu = dynamic_cast(childs[floppyExportPos]); + auto *menu = floppyMenus[i]; + auto childs = menu->children(); + + auto *ejectMenu = dynamic_cast(childs[floppyEjectPos]); + auto *exportMenu = dynamic_cast(childs[floppyExportPos]); ejectMenu->setEnabled(!name.isEmpty()); + ejectMenu->setText(QString::asprintf(tr("Eject %s").toUtf8().constData(), name.isEmpty() ? QString().toUtf8().constData() : fi.fileName().toUtf8().constData())); exportMenu->setEnabled(!name.isEmpty()); + for (int slot = 0; slot < MAX_PREV_IMAGES; slot++) { + updateImageHistory(i, slot, ui::MediaType::Floppy); + } + int type = fdd_get_type(i); - //floppyMenus[i]->setTitle(tr("Floppy %1 (%2): %3").arg(QString::number(i+1), fdd_getname(type), name.isEmpty() ? tr("(empty)") : name)); + // floppyMenus[i]->setTitle(tr("Floppy %1 (%2): %3").arg(QString::number(i+1), fdd_getname(type), name.isEmpty() ? tr("(empty)") : name)); floppyMenus[i]->setTitle(QString::asprintf(tr("Floppy %i (%s): %ls").toUtf8().constData(), i + 1, fdd_getname(type), name.isEmpty() ? tr("(empty)").toStdU16String().data() : name.toStdU16String().data())); } -void MediaMenu::cdromMute(int i) { +void +MediaMenu::floppyMenuSelect(int index, int slot) +{ + QString filename = mhm.getImageForSlot(index, slot, ui::MediaType::Floppy); + floppyMount(index, filename.toUtf8().constData(), false); + floppyUpdateMenu(index); + ui_sb_update_tip(SB_FLOPPY | index); +} + +void +MediaMenu::cdromMute(int i) +{ cdrom[i].sound_on ^= 1; config_save(); cdromUpdateMenu(i); sound_cd_thread_reset(); } -void MediaMenu::cdromMount(int i) { - QString dir; - QFileInfo fi(cdrom[i].image_path); - - auto filename = QFileDialog::getOpenFileName( - parentWidget, - QString(), - QString(), - tr("CD-ROM images") % - util::DlgFilter({ "iso","cue" }) % - tr("All files") % - util::DlgFilter({ "*" }, true)); - - if (filename.isEmpty()) { - return; - } +void +MediaMenu::cdromMount(int i, const QString &filename) +{ QByteArray fn = filename.toUtf8().data(); cdrom[i].prev_host_drive = cdrom[i].host_drive; @@ -393,82 +466,176 @@ void MediaMenu::cdromMount(int i) { } else { ui_sb_update_icon_state(SB_CDROM | i, 1); } + mhm.addImageToHistory(i, ui::MediaType::Optical, cdrom[i].prev_image_path, cdrom[i].image_path); cdromUpdateMenu(i); ui_sb_update_tip(SB_CDROM | i); config_save(); } -void MediaMenu::cdromEject(int i) { +void +MediaMenu::cdromMount(int i, int dir) +{ + QString filename; + QFileInfo fi(cdrom[i].image_path); + + if (dir) { + filename = QFileDialog::getExistingDirectory( + parentWidget); + } else { + filename = QFileDialog::getOpenFileName( + parentWidget, + QString(), + QString(), + tr("CD-ROM images") % util::DlgFilter({ "iso", "cue" }) % tr("All files") % util::DlgFilter({ "*" }, true)); + } + + if (filename.isEmpty()) { + return; + } + + cdromMount(i, filename); +} + +void +MediaMenu::cdromEject(int i) +{ + mhm.addImageToHistory(i, ui::MediaType::Optical, cdrom[i].image_path, QString()); cdrom_eject(i); cdromUpdateMenu(i); ui_sb_update_tip(SB_CDROM | i); } -void MediaMenu::cdromReload(int i) { - cdrom_reload(i); - cdromUpdateMenu(i); - ui_sb_update_tip(SB_CDROM | i); +void +MediaMenu::cdromReload(int index, int slot) +{ + QString filename = mhm.getImageForSlot(index, slot, ui::MediaType::Optical); + cdromMount(index, filename.toUtf8().constData()); + cdromUpdateMenu(index); + ui_sb_update_tip(SB_CDROM | index); } -void MediaMenu::cdromUpdateMenu(int i) { - QString name = cdrom[i].image_path; - auto* menu = cdromMenus[i]; - auto childs = menu->children(); +void +MediaMenu::updateImageHistory(int index, int slot, ui::MediaType type) +{ + QMenu *menu; + QAction *imageHistoryUpdatePos; + QObjectList children; + QFileInfo fi; + QIcon menu_icon; - auto* muteMenu = dynamic_cast(childs[cdromMutePos]); - muteMenu->setChecked(cdrom[i].sound_on == 0); + switch (type) { + case ui::MediaType::Optical: + if (!cdromMenus.contains(index)) + return; + menu = cdromMenus[index]; + children = menu->children(); + imageHistoryUpdatePos = dynamic_cast(children[cdromImageHistoryPos[slot]]); + fi.setFile(mhm.getImageForSlot(index, slot, type)); + menu_icon = fi.isDir() ? QApplication::style()->standardIcon(QStyle::SP_DirIcon) : ProgSettings::loadIcon("/cdrom.ico"); + imageHistoryUpdatePos->setIcon(menu_icon); + break; + case ui::MediaType::Floppy: + if (!floppyMenus.contains(index)) + return; + menu = floppyMenus[index]; + children = menu->children(); + imageHistoryUpdatePos = dynamic_cast(children[floppyImageHistoryPos[slot]]); + fi.setFile(mhm.getImageForSlot(index, slot, type)); + break; + default: + pclog("History not yet implemented for media type %s\n", qPrintable(mhm.mediaTypeToString(type))); + return; + } - auto* imageMenu = dynamic_cast(childs[cdromImagePos]); - auto* emptyMenu = dynamic_cast(childs[cdromEmptyPos]); - imageMenu->setChecked(cdrom[i].host_drive == 200); - emptyMenu->setChecked(cdrom[i].host_drive != 200); + QString menu_item_name = fi.fileName().isEmpty() ? tr("previous image").toUtf8().constData() : fi.fileName().toUtf8().constData(); + imageHistoryUpdatePos->setText(QString::asprintf(tr("%s").toUtf8().constData(), menu_item_name.toUtf8().constData())); + imageHistoryUpdatePos->setVisible(!fi.fileName().isEmpty()); + imageHistoryUpdatePos->setVisible(fi.exists()); +} - auto* prevMenu = dynamic_cast(childs[cdromReloadPos]); - prevMenu->setEnabled(cdrom[i].prev_host_drive != 0); +void +MediaMenu::clearImageHistory() +{ + mhm.clearImageHistory(); + ui_sb_update_panes(); +} + +void +MediaMenu::cdromUpdateMenu(int i) +{ + QString name = cdrom[i].image_path; + QFileInfo fi(cdrom[i].image_path); + + if (!cdromMenus.contains(i)) + return; + auto *menu = cdromMenus[i]; + auto childs = menu->children(); + + auto *muteMenu = dynamic_cast(childs[cdromMutePos]); + muteMenu->setIcon(QApplication::style()->standardIcon((cdrom[i].sound_on == 0) ? QStyle::SP_MediaVolume : QStyle::SP_MediaVolumeMuted)); + muteMenu->setText((cdrom[i].sound_on == 0) ? tr("&Unmute") : tr("&Mute")); + + auto *imageMenu = dynamic_cast(childs[cdromImagePos]); + imageMenu->setEnabled(!name.isEmpty()); + QString menu_item_name = name.isEmpty() ? QString().toUtf8().constData() : fi.fileName().toUtf8().constData(); + auto menu_icon = fi.isDir() ? QApplication::style()->standardIcon(QStyle::SP_DirIcon) : ProgSettings::loadIcon("/cdrom.ico"); + imageMenu->setIcon(menu_icon); + imageMenu->setText(QString::asprintf(tr("Eject %s").toUtf8().constData(), menu_item_name.toUtf8().constData())); + + for (int slot = 0; slot < MAX_PREV_IMAGES; slot++) { + updateImageHistory(i, slot, ui::MediaType::Optical); + } QString busName = tr("Unknown Bus"); switch (cdrom[i].bus_type) { - case CDROM_BUS_ATAPI: - busName = "ATAPI"; - break; - case CDROM_BUS_SCSI: - busName = "SCSI"; - break; + case CDROM_BUS_ATAPI: + busName = "ATAPI"; + break; + case CDROM_BUS_SCSI: + busName = "SCSI"; + break; + case CDROM_BUS_MITSUMI: + busName = "Mitsumi"; + break; } - //menu->setTitle(tr("CD-ROM %1 (%2): %3").arg(QString::number(i+1), busName, name.isEmpty() ? tr("(empty)") : name)); + // menu->setTitle(tr("CD-ROM %1 (%2): %3").arg(QString::number(i+1), busName, name.isEmpty() ? tr("(empty)") : name)); menu->setTitle(QString::asprintf(tr("CD-ROM %i (%s): %s").toUtf8().constData(), i + 1, busName.toUtf8().data(), name.isEmpty() ? tr("(empty)").toUtf8().data() : name.toUtf8().data())); } -void MediaMenu::zipNewImage(int i) { +void +MediaMenu::zipNewImage(int i) +{ NewFloppyDialog dialog(NewFloppyDialog::MediaType::Zip, parentWidget); switch (dialog.exec()) { - case QDialog::Accepted: - QByteArray filename = dialog.fileName().toUtf8(); - zipMount(i, filename, false); - break; + case QDialog::Accepted: + QByteArray filename = dialog.fileName().toUtf8(); + zipMount(i, filename, false); + break; } } -void MediaMenu::zipSelectImage(int i, bool wp) { +void +MediaMenu::zipSelectImage(int i, bool wp) +{ auto filename = QFileDialog::getOpenFileName( parentWidget, QString(), QString(), - tr("ZIP images") % - util::DlgFilter({ "im?","zdi" }) % - tr("All files") % - util::DlgFilter({ "*" }, true)); + tr("ZIP images") % util::DlgFilter({ "im?", "zdi" }) % tr("All files") % util::DlgFilter({ "*" }, true)); - if (!filename.isEmpty()) zipMount(i, filename, wp); + if (!filename.isEmpty()) + zipMount(i, filename, wp); } -void MediaMenu::zipMount(int i, const QString &filename, bool wp) { +void +MediaMenu::zipMount(int i, const QString &filename, bool wp) +{ zip_t *dev = (zip_t *) zip_drives[i].priv; zip_disk_close(dev); zip_drives[i].read_only = wp; - if (! filename.isEmpty()) { + if (!filename.isEmpty()) { QByteArray filenameBytes = filename.toUtf8(); zip_load(dev, filenameBytes.data()); zip_insert(dev); @@ -481,10 +648,13 @@ void MediaMenu::zipMount(int i, const QString &filename, bool wp) { config_save(); } -void MediaMenu::zipEject(int i) { +void +MediaMenu::zipEject(int i) +{ zip_t *dev = (zip_t *) zip_drives[i].priv; zip_disk_close(dev); + zip_drives[i].image_path[0] = 0; if (zip_drives[i].bus_type) { /* Signal disk change to the emulated machine. */ zip_insert(dev); @@ -496,76 +666,89 @@ void MediaMenu::zipEject(int i) { config_save(); } -void MediaMenu::zipReload(int i) { +void +MediaMenu::zipReload(int i) +{ zip_t *dev = (zip_t *) zip_drives[i].priv; zip_disk_reload(dev); if (strlen(zip_drives[i].image_path) == 0) { - ui_sb_update_icon_state(SB_ZIP|i, 1); + ui_sb_update_icon_state(SB_ZIP | i, 1); } else { - ui_sb_update_icon_state(SB_ZIP|i, 0); + ui_sb_update_icon_state(SB_ZIP | i, 0); } zipUpdateMenu(i); - ui_sb_update_tip(SB_ZIP|i); + ui_sb_update_tip(SB_ZIP | i); config_save(); } -void MediaMenu::zipUpdateMenu(int i) { - QString name = zip_drives[i].image_path; +void +MediaMenu::zipUpdateMenu(int i) +{ + QString name = zip_drives[i].image_path; QString prev_name = zip_drives[i].prev_image_path; - auto* menu = zipMenus[i]; - auto childs = menu->children(); + if (!zipMenus.contains(i)) + return; + auto *menu = zipMenus[i]; + auto childs = menu->children(); - auto* ejectMenu = dynamic_cast(childs[zipEjectPos]); - auto* reloadMenu = dynamic_cast(childs[zipReloadPos]); + auto *ejectMenu = dynamic_cast(childs[zipEjectPos]); + auto *reloadMenu = dynamic_cast(childs[zipReloadPos]); ejectMenu->setEnabled(!name.isEmpty()); reloadMenu->setEnabled(!prev_name.isEmpty()); QString busName = tr("Unknown Bus"); switch (zip_drives[i].bus_type) { - case ZIP_BUS_ATAPI: - busName = "ATAPI"; - break; - case ZIP_BUS_SCSI: - busName = "SCSI"; - break; + case ZIP_BUS_ATAPI: + busName = "ATAPI"; + break; + case ZIP_BUS_SCSI: + busName = "SCSI"; + break; } - //menu->setTitle(tr("ZIP %1 %2 (%3): %4").arg((zip_drives[i].is_250 > 0) ? "250" : "100", QString::number(i+1), busName, name.isEmpty() ? tr("(empty)") : name)); + // menu->setTitle(tr("ZIP %1 %2 (%3): %4").arg((zip_drives[i].is_250 > 0) ? "250" : "100", QString::number(i+1), busName, name.isEmpty() ? tr("(empty)") : name)); menu->setTitle(QString::asprintf(tr("ZIP %03i %i (%s): %ls").toUtf8().constData(), (zip_drives[i].is_250 > 0) ? 250 : 100, i + 1, busName.toUtf8().data(), name.isEmpty() ? tr("(empty)").toStdU16String().data() : name.toStdU16String().data())); } -void MediaMenu::moNewImage(int i) { +void +MediaMenu::moNewImage(int i) +{ NewFloppyDialog dialog(NewFloppyDialog::MediaType::Mo, parentWidget); switch (dialog.exec()) { - case QDialog::Accepted: - QByteArray filename = dialog.fileName().toUtf8(); - moMount(i, filename, false); - break; + case QDialog::Accepted: + QByteArray filename = dialog.fileName().toUtf8(); + moMount(i, filename, false); + break; } } -void MediaMenu::moSelectImage(int i, bool wp) { +void +MediaMenu::moSelectImage(int i, bool wp) +{ auto filename = QFileDialog::getOpenFileName( parentWidget, QString(), - QString(), - tr("MO images") % - util::DlgFilter({ "im?", "mdi" }) % - tr("All files") % - util::DlgFilter({ "*", }, true)); + getMediaOpenDirectory(), + tr("MO images") % util::DlgFilter({ "im?", "mdi" }) % tr("All files") % util::DlgFilter({ + "*", + }, + true)); - if (!filename.isEmpty()) moMount(i, filename, wp); + if (!filename.isEmpty()) + moMount(i, filename, wp); } -void MediaMenu::moMount(int i, const QString &filename, bool wp) { +void +MediaMenu::moMount(int i, const QString &filename, bool wp) +{ mo_t *dev = (mo_t *) mo_drives[i].priv; mo_disk_close(dev); mo_drives[i].read_only = wp; - if (! filename.isEmpty()) { + if (!filename.isEmpty()) { QByteArray filenameBytes = filename.toUtf8(); mo_load(dev, filenameBytes.data()); mo_insert(dev); @@ -578,10 +761,13 @@ void MediaMenu::moMount(int i, const QString &filename, bool wp) { config_save(); } -void MediaMenu::moEject(int i) { +void +MediaMenu::moEject(int i) +{ mo_t *dev = (mo_t *) mo_drives[i].priv; mo_disk_close(dev); + mo_drives[i].image_path[0] = 0; if (mo_drives[i].bus_type) { /* Signal disk change to the emulated machine. */ mo_insert(dev); @@ -593,64 +779,133 @@ void MediaMenu::moEject(int i) { config_save(); } -void MediaMenu::moReload(int i) { +void +MediaMenu::moReload(int i) +{ mo_t *dev = (mo_t *) mo_drives[i].priv; mo_disk_reload(dev); if (strlen(mo_drives[i].image_path) == 0) { - ui_sb_update_icon_state(SB_MO|i, 1); + ui_sb_update_icon_state(SB_MO | i, 1); } else { - ui_sb_update_icon_state(SB_MO|i, 0); + ui_sb_update_icon_state(SB_MO | i, 0); } moUpdateMenu(i); - ui_sb_update_tip(SB_MO|i); + ui_sb_update_tip(SB_MO | i); config_save(); } -void MediaMenu::moUpdateMenu(int i) { - QString name = mo_drives[i].image_path; +void +MediaMenu::moUpdateMenu(int i) +{ + QString name = mo_drives[i].image_path; QString prev_name = mo_drives[i].prev_image_path; - auto* menu = moMenus[i]; - auto childs = menu->children(); + if (!moMenus.contains(i)) + return; + auto *menu = moMenus[i]; + auto childs = menu->children(); - auto* ejectMenu = dynamic_cast(childs[moEjectPos]); - auto* reloadMenu = dynamic_cast(childs[moReloadPos]); + auto *ejectMenu = dynamic_cast(childs[moEjectPos]); + auto *reloadMenu = dynamic_cast(childs[moReloadPos]); ejectMenu->setEnabled(!name.isEmpty()); reloadMenu->setEnabled(!prev_name.isEmpty()); QString busName = tr("Unknown Bus"); switch (mo_drives[i].bus_type) { - case MO_BUS_ATAPI: - busName = "ATAPI"; - break; - case MO_BUS_SCSI: - busName = "SCSI"; - break; + case MO_BUS_ATAPI: + busName = "ATAPI"; + break; + case MO_BUS_SCSI: + busName = "SCSI"; + break; } menu->setTitle(QString::asprintf(tr("MO %i (%ls): %ls").toUtf8().constData(), i + 1, busName.toStdU16String().data(), name.isEmpty() ? tr("(empty)").toStdU16String().data() : name.toStdU16String().data())); } +void +MediaMenu::nicConnect(int i) +{ + network_connect(i, 1); + ui_sb_update_icon_state(SB_NETWORK | i, 0); + nicUpdateMenu(i); + config_save(); +} + +void +MediaMenu::nicDisconnect(int i) +{ + network_connect(i, 0); + ui_sb_update_icon_state(SB_NETWORK | i, 1); + nicUpdateMenu(i); + config_save(); +} + +void +MediaMenu::nicUpdateMenu(int i) +{ + if (!netMenus.contains(i)) + return; + + QString netType = tr("Null Driver"); + switch (net_cards_conf[i].net_type) { + case NET_TYPE_SLIRP: + netType = "SLiRP"; + break; + case NET_TYPE_PCAP: + netType = "PCAP"; + break; + case NET_TYPE_VDE: + netType = "VDE"; + break; + } + + QString devName = DeviceConfig::DeviceName(network_card_getdevice(net_cards_conf[i].device_num), network_card_get_internal_name(net_cards_conf[i].device_num), 1); + + auto *menu = netMenus[i]; + auto childs = menu->children(); + auto *connectedAction = dynamic_cast(childs[netDisconnPos]); + connectedAction->setChecked(network_is_connected(i)); + + menu->setTitle(QString::asprintf(tr("NIC %02i (%ls) %ls").toUtf8().constData(), i + 1, netType.toStdU16String().data(), devName.toStdU16String().data())); +} + +QString +MediaMenu::getMediaOpenDirectory() +{ + QString openDirectory; + if (open_dir_usr_path > 0) { + openDirectory = QString::fromUtf8(usr_path); + } + return openDirectory; +} // callbacks from 86box C code extern "C" { -void zip_eject(uint8_t id) { +void +zip_eject(uint8_t id) +{ MediaMenu::ptr->zipEject(id); } -void zip_reload(uint8_t id) { +void +zip_reload(uint8_t id) +{ MediaMenu::ptr->zipReload(id); } -void mo_eject(uint8_t id) { +void +mo_eject(uint8_t id) +{ MediaMenu::ptr->moEject(id); } -void mo_reload(uint8_t id) { +void +mo_reload(uint8_t id) +{ MediaMenu::ptr->moReload(id); } - } diff --git a/src/qt/qt_mediamenu.hpp b/src/qt/qt_mediamenu.hpp index 3dc859fe9..57fd8dfc2 100644 --- a/src/qt/qt_mediamenu.hpp +++ b/src/qt/qt_mediamenu.hpp @@ -3,16 +3,19 @@ #include #include #include +#include "qt_mediahistorymanager.hpp" +extern "C" { +#include <86box/86box.h> +} class QMenu; -class MediaMenu : QObject -{ +class MediaMenu : QObject { Q_OBJECT public: - MediaMenu(QWidget* parent); + MediaMenu(QWidget *parent); - void refresh(QMenu* parentMenu); + void refresh(QMenu *parentMenu); // because some 86box C-only code needs to call zip and // mo eject directly @@ -20,49 +23,63 @@ public: void cassetteNewImage(); void cassetteSelectImage(bool wp); - void cassetteMount(const QString& filename, bool wp); + void cassetteMount(const QString &filename, bool wp); void cassetteEject(); void cassetteUpdateMenu(); void cartridgeSelectImage(int i); + void cartridgeMount(int i, const QString &filename); void cartridgeEject(int i); void cartridgeUpdateMenu(int i); void floppyNewImage(int i); void floppySelectImage(int i, bool wp); - void floppyMount(int i, const QString& filename, bool wp); + void floppyMount(int i, const QString &filename, bool wp); void floppyEject(int i); + void floppyMenuSelect(int index, int slot); void floppyExportTo86f(int i); void floppyUpdateMenu(int i); void cdromMute(int i); - void cdromMount(int i); + void cdromMount(int i, int dir); + void cdromMount(int i, const QString &filename); void cdromEject(int i); - void cdromReload(int i); + void cdromReload(int index, int slot); + void updateImageHistory(int index, int slot, ui::MediaType type); + void clearImageHistory(); void cdromUpdateMenu(int i); void zipNewImage(int i); void zipSelectImage(int i, bool wp); - void zipMount(int i, const QString& filename, bool wp); + void zipMount(int i, const QString &filename, bool wp); void zipEject(int i); void zipReload(int i); void zipUpdateMenu(int i); void moNewImage(int i); void moSelectImage(int i, bool wp); - void moMount(int i, const QString& filename, bool wp); + void moMount(int i, const QString &filename, bool wp); void moEject(int i); void moReload(int i); void moUpdateMenu(int i); -private: - QWidget* parentWidget = nullptr; - QMenu* cassetteMenu = nullptr; - QMap cartridgeMenus; - QMap floppyMenus; - QMap cdromMenus; - QMap zipMenus; - QMap moMenus; + void nicConnect(int i); + void nicDisconnect(int i); + void nicUpdateMenu(int i); + +private: + QWidget *parentWidget = nullptr; + + QMenu *cassetteMenu = nullptr; + QMap cartridgeMenus; + QMap floppyMenus; + QMap cdromMenus; + QMap zipMenus; + QMap moMenus; + QMap netMenus; + + QString getMediaOpenDirectory(); + ui::MediaHistoryManager mhm; int cassetteRecordPos; int cassettePlayPos; @@ -76,9 +93,11 @@ private: int floppyEjectPos; int cdromMutePos; - int cdromEmptyPos; int cdromReloadPos; int cdromImagePos; + int cdromDirPos; + int cdromImageHistoryPos[MAX_PREV_IMAGES]; + int floppyImageHistoryPos[MAX_PREV_IMAGES]; int zipEjectPos; int zipReloadPos; @@ -86,5 +105,7 @@ private: int moEjectPos; int moReloadPos; + int netDisconnPos; + friend class MachineStatus; }; diff --git a/src/qt/qt_midi.cpp b/src/qt/qt_midi.cpp index a9b741c9e..2ea8ad3b1 100644 --- a/src/qt/qt_midi.cpp +++ b/src/qt/qt_midi.cpp @@ -2,43 +2,65 @@ extern "C" { -void plat_midi_play_msg(uint8_t *msg) -{} +void +plat_midi_play_msg(uint8_t *msg) +{ +} -void plat_midi_play_sysex(uint8_t *sysex, unsigned int len) -{} +void +plat_midi_play_sysex(uint8_t *sysex, unsigned int len) +{ +} -void plat_midi_input_init(void) -{} +void +plat_midi_input_init(void) +{ +} -void plat_midi_input_close(void) -{} +void +plat_midi_input_close(void) +{ +} -int plat_midi_write(uint8_t val) -{ return 0; } +int +plat_midi_write(uint8_t val) +{ + return 0; +} -void plat_midi_init() -{} +void +plat_midi_init() +{ +} -void plat_midi_close() -{} +void +plat_midi_close() +{ +} -int plat_midi_get_num_devs() -{ return 0; } +int +plat_midi_get_num_devs() +{ + return 0; +} -int plat_midi_in_get_num_devs(void) -{ return 0; } +int +plat_midi_in_get_num_devs(void) +{ + return 0; +} -void plat_midi_get_dev_name(int num, char *s) +void +plat_midi_get_dev_name(int num, char *s) { s[0] = ' '; s[1] = 0; } -void plat_midi_in_get_dev_name(int num, char *s) +void +plat_midi_in_get_dev_name(int num, char *s) { s[0] = ' '; s[1] = 0; } - } diff --git a/src/qt/qt_models_common.cpp b/src/qt/qt_models_common.cpp index eaa14bc0d..ed6aeaa7d 100644 --- a/src/qt/qt_models_common.cpp +++ b/src/qt/qt_models_common.cpp @@ -1,24 +1,25 @@ /* - * 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. + * 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. + * This file is part of the 86Box distribution. * - * Common storage devices module. + * Common storage devices module. * * * - * Authors: Joakim L. Gilje + * Authors: Joakim L. Gilje * - * Copyright 2021 Joakim L. Gilje + * Copyright 2021 Joakim L. Gilje */ #include "qt_models_common.hpp" #include -int Models::AddEntry(QAbstractItemModel *model, const QString& displayRole, int userRole) +int +Models::AddEntry(QAbstractItemModel *model, const QString &displayRole, int userRole) { int row = model->rowCount(); model->insertRow(row); diff --git a/src/qt/qt_models_common.hpp b/src/qt/qt_models_common.hpp index 91cda3836..98674a68f 100644 --- a/src/qt/qt_models_common.hpp +++ b/src/qt/qt_models_common.hpp @@ -2,7 +2,6 @@ class QString; class QAbstractItemModel; -namespace Models -{ - int AddEntry(QAbstractItemModel* model, const QString& displayRole, int userRole); +namespace Models { +int AddEntry(QAbstractItemModel *model, const QString &displayRole, int userRole); }; diff --git a/src/qt/qt_newfloppydialog.cpp b/src/qt/qt_newfloppydialog.cpp index 76fbb8aca..e24ad9aa1 100644 --- a/src/qt/qt_newfloppydialog.cpp +++ b/src/qt/qt_newfloppydialog.cpp @@ -1,22 +1,22 @@ /* - * 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. + * 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. + * This file is part of the 86Box distribution. * - * Common storage devices module. + * Common storage devices module. * * * - * Authors: Joakim L. Gilje + * Authors: Joakim L. Gilje * Cacodemon345 * Teemu Korhonen * - * Copyright 2021 Joakim L. Gilje - * Copyright 2022 Cacodemon345 - * Copyright 2022 Teemu Korhonen + * Copyright 2021 Joakim L. Gilje + * Copyright 2022 Cacodemon345 + * Copyright 2022 Teemu Korhonen */ #include "qt_newfloppydialog.hpp" #include "ui_qt_newfloppydialog.h" @@ -25,12 +25,17 @@ #include "qt_util.hpp" extern "C" { +#include <86box/86box.h> +#include <86box/plat.h> #include <86box/random.h> #include <86box/scsi_device.h> #include <86box/zip.h> #include <86box/mo.h> } +#include +#include + #include #include #include @@ -45,8 +50,8 @@ struct disk_size_t { int encoding; int rpm; int tracks; - int sectors; /* For IMG and Japanese FDI only. */ - int sector_len; /* For IMG and Japanese FDI only. */ + int sectors; /* For IMG and Japanese FDI only. */ + int sector_len; /* For IMG and Japanese FDI only. */ int media_desc; int spc; int num_fats; @@ -54,20 +59,34 @@ struct disk_size_t { int root_dir_entries; }; -static const disk_size_t disk_sizes[14] = { { 0, 1, 2, 1, 0, 40, 8, 2, 0xfe, 2, 2, 1, 64 }, /* 160k */ - { 0, 1, 2, 1, 0, 40, 9, 2, 0xfc, 2, 2, 1, 64 }, /* 180k */ - { 0, 2, 2, 1, 0, 40, 8, 2, 0xff, 2, 2, 1, 112 }, /* 320k */ - { 0, 2, 2, 1, 0, 40, 9, 2, 0xfd, 2, 2, 2, 112 }, /* 360k */ - { 0, 2, 2, 1, 0, 80, 8, 2, 0xfb, 2, 2, 2, 112 }, /* 640k */ - { 0, 2, 2, 1, 0, 80, 9, 2, 0xf9, 2, 2, 3, 112 }, /* 720k */ - { 1, 2, 0, 1, 1, 80, 15, 2, 0xf9, 1, 2, 7, 224 }, /* 1.2M */ - { 1, 2, 0, 1, 1, 77, 8, 3, 0xfe, 1, 2, 2, 192 }, /* 1.25M */ - { 1, 2, 0, 1, 0, 80, 18, 2, 0xf0, 1, 2, 9, 224 }, /* 1.44M */ - { 1, 2, 0, 1, 0, 80, 21, 2, 0xf0, 2, 2, 5, 16 }, /* DMF cluster 1024 */ - { 1, 2, 0, 1, 0, 80, 21, 2, 0xf0, 4, 2, 3, 16 }, /* DMF cluster 2048 */ - { 2, 2, 3, 1, 0, 80, 36, 2, 0xf0, 2, 2, 9, 240 }, /* 2.88M */ - { 0, 64, 0, 0, 0, 96, 32, 2, 0, 0, 0, 0, 0 }, /* ZIP 100 */ - { 0, 64, 0, 0, 0, 239, 32, 2, 0, 0, 0, 0, 0 } }; /* ZIP 250 */ +static const disk_size_t disk_sizes[14] = { +// clang-format off +#if 0 + { 1, 1, 2, 1, 1, 77, 26, 0, 0, 4, 2, 6, 68 }, /* 250k 8" */ + { 1, 2, 2, 1, 1, 77, 26, 0, 0, 4, 2, 6, 68 }, /* 500k 8" */ + { 1, 1, 2, 1, 1, 77, 8, 3, 0, 1, 2, 2, 192 }, /* 616k 8" */ + { 1, 2, 0, 1, 1, 77, 8, 3, 0, 1, 2, 2, 192 }, /* 1232k 8" */ +#endif + { 0, 1, 2, 1, 0, 40, 8, 2, 0xfe, 2, 2, 1, 64 }, /* 160k */ + { 0, 1, 2, 1, 0, 40, 9, 2, 0xfc, 2, 2, 1, 64 }, /* 180k */ + { 0, 2, 2, 1, 0, 40, 8, 2, 0xff, 2, 2, 1, 112 }, /* 320k */ + { 0, 2, 2, 1, 0, 40, 9, 2, 0xfd, 2, 2, 2, 112 }, /* 360k */ + { 0, 2, 2, 1, 0, 80, 8, 2, 0xfb, 2, 2, 2, 112 }, /* 640k */ + { 0, 2, 2, 1, 0, 80, 9, 2, 0xf9, 2, 2, 3, 112 }, /* 720k */ + { 1, 2, 0, 1, 1, 80, 15, 2, 0xf9, 1, 2, 7, 224 }, /* 1.2M */ + { 1, 2, 0, 1, 1, 77, 8, 3, 0xfe, 1, 2, 2, 192 }, /* 1.25M */ + { 1, 2, 0, 1, 0, 80, 18, 2, 0xf0, 1, 2, 9, 224 }, /* 1.44M */ + { 1, 2, 0, 1, 0, 80, 21, 2, 0xf0, 2, 2, 5, 16 }, /* DMF cluster 1024 */ + { 1, 2, 0, 1, 0, 80, 21, 2, 0xf0, 4, 2, 3, 16 }, /* DMF cluster 2048 */ + { 2, 2, 3, 1, 0, 80, 36, 2, 0xf0, 2, 2, 9, 240 }, /* 2.88M */ + { 0, 64, 0, 0, 0, 96, 32, 2, 0, 0, 0, 0, 0 }, /* ZIP 100 */ + { 0, 64, 0, 0, 0, 239, 32, 2, 0, 0, 0, 0, 0 }, /* ZIP 250 */ +#if 0 + { 0, 8, 0, 0, 0, 963, 32, 2, 0, 0, 0, 0, 0 }, /* LS-120 */ + { 0, 32, 0, 0, 0, 262, 56, 2, 0, 0, 0, 0, 0 } /* LS-240 */ +#endif +// clang-format on +}; static const QStringList rpmModes = { "Perfect RPM", @@ -109,41 +128,36 @@ static const QStringList moTypes = { "5.25\" 1.3 GB", }; -NewFloppyDialog::NewFloppyDialog(MediaType type, QWidget *parent) : - QDialog(parent), - ui(new Ui::NewFloppyDialog), - mediaType_(type) +NewFloppyDialog::NewFloppyDialog(MediaType type, QWidget *parent) + : QDialog(parent) + , ui(new Ui::NewFloppyDialog) + , mediaType_(type) { ui->setupUi(this); ui->fileField->setCreateFile(true); - auto* model = ui->comboBoxSize->model(); + auto *model = ui->comboBoxSize->model(); switch (type) { - case MediaType::Floppy: - for (int i = 0; i < floppyTypes.size(); ++i) { - Models::AddEntry(model, tr(floppyTypes[i].toUtf8().data()), i); - } - ui->fileField->setFilter( - tr("All images") % - util::DlgFilter({ "86f","dsk","flp","im?","*fd?" }) % - tr("Basic sector images") % - util::DlgFilter({ "dsk","flp","im?","img","*fd?" }) % - tr("Surface images") % - util::DlgFilter({ "86f" }, true)); - - break; - case MediaType::Zip: - for (int i = 0; i < zipTypes.size(); ++i) { - Models::AddEntry(model, tr(zipTypes[i].toUtf8().data()), i); - } - ui->fileField->setFilter(tr("ZIP images") % util::DlgFilter({ "im?","zdi" }, true)); - break; - case MediaType::Mo: - for (int i = 0; i < moTypes.size(); ++i) { - Models::AddEntry(model, tr(moTypes[i].toUtf8().data()), i); - } - ui->fileField->setFilter(tr("MO images") % util::DlgFilter({ "im?","mdi" }) % tr("All files") % util::DlgFilter({ "*" }, true)); - break; + case MediaType::Floppy: + for (int i = 0; i < floppyTypes.size(); ++i) { + Models::AddEntry(model, tr(floppyTypes[i].toUtf8().data()), i); + } + ui->fileField->setFilter( + tr("All images") % util::DlgFilter({ "86f", "dsk", "flp", "im?", "img", "*fd?" }) % tr("Basic sector images") % util::DlgFilter({ "dsk", "flp", "im?", "img", "*fd?" }) % tr("Surface images") % util::DlgFilter({ "86f" }, true)); + + break; + case MediaType::Zip: + for (int i = 0; i < zipTypes.size(); ++i) { + Models::AddEntry(model, tr(zipTypes[i].toUtf8().data()), i); + } + ui->fileField->setFilter(tr("ZIP images") % util::DlgFilter({ "im?", "img", "zdi" }, true)); + break; + case MediaType::Mo: + for (int i = 0; i < moTypes.size(); ++i) { + Models::AddEntry(model, tr(moTypes[i].toUtf8().data()), i); + } + ui->fileField->setFilter(tr("MO images") % util::DlgFilter({ "im?", "img", "mdi" }) % tr("All files") % util::DlgFilter({ "*" }, true)); + break; } model = ui->comboBoxRpm->model(); @@ -151,7 +165,7 @@ NewFloppyDialog::NewFloppyDialog(MediaType type, QWidget *parent) : Models::AddEntry(model, tr(rpmModes[i].toUtf8().data()), i); } - connect(ui->fileField, &FileField::fileSelected, this, [this](const QString& filename) { + connect(ui->fileField, &FileField::fileSelected, this, [this](const QString &filename) { bool hide = true; if (mediaType_ == MediaType::Floppy) { if (QFileInfo(filename).suffix().toLower() == QStringLiteral("86f")) { @@ -168,148 +182,160 @@ NewFloppyDialog::NewFloppyDialog(MediaType type, QWidget *parent) : ui->comboBoxRpm->setHidden(true); } -NewFloppyDialog::~NewFloppyDialog() { +NewFloppyDialog::~NewFloppyDialog() +{ delete ui; } -QString NewFloppyDialog::fileName() const{ +QString +NewFloppyDialog::fileName() const +{ return ui->fileField->fileName(); } -void NewFloppyDialog::onCreate() { - auto filename = ui->fileField->fileName(); +void +NewFloppyDialog::onCreate() +{ + auto filename = ui->fileField->fileName(); QFileInfo fi(filename); - FileType fileType; + filename = (fi.isRelative() && !fi.filePath().isEmpty()) ? (usr_path + fi.filePath()) : fi.filePath(); + ui->fileField->setFileName(filename); + FileType fileType; QProgressDialog progress("Creating floppy image", QString(), 0, 100, this); connect(this, &NewFloppyDialog::fileProgress, &progress, &QProgressDialog::setValue); + connect(this, &NewFloppyDialog::fileProgress, [] { QApplication::processEvents(); }); switch (mediaType_) { - case MediaType::Floppy: - if (fi.suffix().toLower() == QStringLiteral("86f")) { - if (create86f(filename, disk_sizes[ui->comboBoxSize->currentIndex()], ui->comboBoxRpm->currentIndex())) { - return; + case MediaType::Floppy: + if (fi.suffix().toLower() == QStringLiteral("86f")) { + if (create86f(filename, disk_sizes[ui->comboBoxSize->currentIndex()], ui->comboBoxRpm->currentIndex())) { + return; + } + } else { + fileType = fi.suffix().toLower() == QStringLiteral("zdi") ? FileType::Fdi : FileType::Img; + if (createSectorImage(filename, disk_sizes[ui->comboBoxSize->currentIndex()], fileType)) { + return; + } } - } else { - fileType = fi.suffix().toLower() == QStringLiteral("zdi") ? FileType::Fdi : FileType::Img; - if (createSectorImage(filename, disk_sizes[ui->comboBoxSize->currentIndex()], fileType)) { - return; + break; + case MediaType::Zip: + { + fileType = fi.suffix().toLower() == QStringLiteral("zdi") ? FileType::Zdi : FileType::Img; + + std::atomic_bool res; + std::thread t([this, &res, filename, fileType, &progress] { + res = createZipSectorImage(filename, disk_sizes[ui->comboBoxSize->currentIndex() + 12], fileType, progress); + }); + progress.exec(); + t.join(); + + if (res) { + return; + } } - } - break; - case MediaType::Zip: - { - fileType = fi.suffix().toLower() == QStringLiteral("zdi") ? FileType::Zdi: FileType::Img; + break; + case MediaType::Mo: + { + fileType = fi.suffix().toLower() == QStringLiteral("mdi") ? FileType::Mdi : FileType::Img; - std::atomic_bool res; - std::thread t([this, &res, filename, fileType, &progress] { - res = createZipSectorImage(filename, disk_sizes[ui->comboBoxSize->currentIndex() + 12], fileType, progress); - }); - progress.exec(); - t.join(); + std::atomic_bool res; + std::thread t([this, &res, filename, fileType, &progress] { + res = createMoSectorImage(filename, ui->comboBoxSize->currentIndex(), fileType, progress); + }); + progress.exec(); + t.join(); - if (res) { - return; - } - } - break; - case MediaType::Mo: - { - fileType = fi.suffix().toLower() == QStringLiteral("mdi") ? FileType::Mdi: FileType::Img; - - std::atomic_bool res; - std::thread t([this, &res, filename, fileType, &progress] { - res = createMoSectorImage(filename, ui->comboBoxSize->currentIndex(), fileType, progress); - }); - progress.exec(); - t.join(); - - if (res) { - return; - } - } - break; + if (res) { + return; + } + } + break; } QMessageBox::critical(this, tr("Unable to write file"), tr("Make sure the file is being saved to a writable directory")); reject(); } -bool NewFloppyDialog::create86f(const QString& filename, const disk_size_t& disk_size, uint8_t rpm_mode) +bool +NewFloppyDialog::create86f(const QString &filename, const disk_size_t &disk_size, uint8_t rpm_mode) { - uint32_t magic = 0x46423638; - uint16_t version = 0x020C; - uint16_t dflags = 0; - uint16_t tflags = 0; + FILE *fp; + + uint32_t magic = 0x46423638; + uint16_t version = 0x020C; + uint16_t dflags = 0; + uint16_t tflags = 0; uint32_t index_hole_pos = 0; uint32_t tarray[512]; uint32_t array_size; - uint32_t track_base, track_size; - int i; + uint32_t track_base; + uint32_t track_size; + int i; uint32_t shift = 0; - dflags = 0; /* Has surface data? - Assume no for now. */ - dflags |= (disk_size.hole << 1); /* Hole */ - dflags |= ((disk_size.sides - 1) << 3); /* Sides. */ - dflags |= (0 << 4); /* Write protect? - Assume no for now. */ - dflags |= (rpm_mode << 5); /* RPM mode. */ - dflags |= (0 << 7); /* Has extra bit cells? - Assume no for now. */ + dflags = 0; /* Has surface data? - Assume no for now. */ + dflags |= (disk_size.hole << 1); /* Hole */ + dflags |= ((disk_size.sides - 1) << 3); /* Sides. */ + dflags |= (0 << 4); /* Write protect? - Assume no for now. */ + dflags |= (rpm_mode << 5); /* RPM mode. */ + dflags |= (0 << 7); /* Has extra bit cells? - Assume no for now. */ - tflags = disk_size.data_rate; /* Data rate. */ - tflags |= (disk_size.encoding << 3); /* Encoding. */ - tflags |= (disk_size.rpm << 5); /* RPM. */ + tflags = disk_size.data_rate; /* Data rate. */ + tflags |= (disk_size.encoding << 3); /* Encoding. */ + tflags |= (disk_size.rpm << 5); /* RPM. */ switch (disk_size.hole) { - case 0: - case 1: - default: - switch(rpm_mode) { + case 0: case 1: - array_size = 25250; + default: + switch (rpm_mode) { + case 1: + array_size = 25250; + break; + case 2: + array_size = 25374; + break; + case 3: + array_size = 25750; + break; + default: + array_size = 25000; + break; + } break; case 2: - array_size = 25374; + switch (rpm_mode) { + case 1: + array_size = 50500; + break; + case 2: + array_size = 50750; + break; + case 3: + array_size = 51000; + break; + default: + array_size = 50000; + break; + } break; - case 3: - array_size = 25750; - break; - default: - array_size = 25000; - break; - } - break; - case 2: - switch(rpm_mode) { - case 1: - array_size = 50500; - break; - case 2: - array_size = 50750; - break; - case 3: - array_size = 51000; - break; - default: - array_size = 50000; - break; - } - break; } - QByteArray bytes(array_size, 0); + auto empty = (unsigned char *) malloc(array_size); + memset(tarray, 0, 2048); + memset(empty, 0, array_size); - QFile file(filename); - if (! file.open(QIODevice::WriteOnly)) { + fp = plat_fopen(filename.toUtf8().data(), "wb"); + if (!fp) return false; - } - QDataStream stream(&file); - stream.setByteOrder(QDataStream::LittleEndian); - stream << magic; - stream << version; - stream << dflags; + fwrite(&magic, 4, 1, fp); + fwrite(&version, 2, 1, fp); + fwrite(&dflags, 2, 1, fp); track_size = array_size + 6; + track_base = 8 + ((disk_size.sides == 2) ? 2048 : 1024); if (disk_size.tracks <= 43) @@ -318,70 +344,79 @@ bool NewFloppyDialog::create86f(const QString& filename, const disk_size_t& disk for (i = 0; i < (disk_size.tracks * disk_size.sides) << shift; i++) tarray[i] = track_base + (i * track_size); - stream.writeRawData(reinterpret_cast(tarray), (disk_size.sides == 2) ? 2048 : 1024); + fwrite(tarray, 1, (disk_size.sides == 2) ? 2048 : 1024, fp); - int max = i < (disk_size.tracks * disk_size.sides) << shift; - for (i = 0; i < max; i++) { - stream << tflags; - stream << index_hole_pos; - stream.writeRawData(bytes, bytes.size()); + for (i = 0; i < (disk_size.tracks * disk_size.sides) << shift; i++) { + fwrite(&tflags, 2, 1, fp); + fwrite(&index_hole_pos, 4, 1, fp); + fwrite(empty, 1, array_size, fp); } + free(empty); + + fclose(fp); + return true; } -bool NewFloppyDialog::createSectorImage(const QString &filename, const disk_size_t& disk_size, FileType type) +/* Ignore false positive warning caused by a bug on gcc */ +#if __GNUC__ >= 11 +# pragma GCC diagnostic ignored "-Wstringop-overflow" +#endif + +bool +NewFloppyDialog::createSectorImage(const QString &filename, const disk_size_t &disk_size, FileType type) { - uint32_t total_size = 0; - uint32_t total_sectors = 0; - uint32_t sector_bytes = 0; + uint32_t total_size = 0; + uint32_t total_sectors = 0; + uint32_t sector_bytes = 0; uint32_t root_dir_bytes = 0; - uint32_t fat_size = 0; - uint32_t fat1_offs = 0; - uint32_t fat2_offs = 0; - uint32_t zero_bytes = 0; - uint16_t base = 0x1000; + uint32_t fat_size = 0; + uint32_t fat1_offs = 0; + uint32_t fat2_offs = 0; + uint32_t zero_bytes = 0; + uint16_t base = 0x1000; QFile file(filename); - if (! file.open(QIODevice::WriteOnly)) { + if (!file.open(QIODevice::WriteOnly)) { return false; } QDataStream stream(&file); stream.setByteOrder(QDataStream::LittleEndian); - sector_bytes = (128 << disk_size.sector_len); + sector_bytes = (128 << disk_size.sector_len); total_sectors = disk_size.sides * disk_size.tracks * disk_size.sectors; if (total_sectors > ZIP_SECTORS) total_sectors = ZIP_250_SECTORS; - total_size = total_sectors * sector_bytes; + total_size = total_sectors * sector_bytes; root_dir_bytes = (disk_size.root_dir_entries << 5); - fat_size = (disk_size.spfat * sector_bytes); - fat1_offs = sector_bytes; - fat2_offs = fat1_offs + fat_size; - zero_bytes = fat2_offs + fat_size + root_dir_bytes; + fat_size = (disk_size.spfat * sector_bytes); + fat1_offs = sector_bytes; + fat2_offs = fat1_offs + fat_size; + zero_bytes = fat2_offs + fat_size + root_dir_bytes; if (type == FileType::Fdi) { QByteArray bytes(base, 0); - auto empty = bytes.data(); + auto empty = bytes.data(); *(uint32_t *) &(empty[0x08]) = (uint32_t) base; *(uint32_t *) &(empty[0x0C]) = total_size; *(uint16_t *) &(empty[0x10]) = (uint16_t) sector_bytes; - *(uint8_t *) &(empty[0x14]) = (uint8_t) disk_size.sectors; - *(uint8_t *) &(empty[0x18]) = (uint8_t) disk_size.sides; - *(uint8_t *) &(empty[0x1C]) = (uint8_t) disk_size.tracks; + *(uint8_t *) &(empty[0x14]) = (uint8_t) disk_size.sectors; + *(uint8_t *) &(empty[0x18]) = (uint8_t) disk_size.sides; + *(uint8_t *) &(empty[0x1C]) = (uint8_t) disk_size.tracks; stream.writeRawData(empty, base); } QByteArray bytes(total_size, 0); - auto empty = bytes.data(); + auto empty = bytes.data(); memset(empty + zero_bytes, 0xF6, total_size - zero_bytes); - empty[0x00] = 0xEB; /* Jump to make MS-DOS happy. */ + empty[0x00] = 0xEB; /* Jump to make MS-DOS happy. */ empty[0x01] = 0x58; empty[0x02] = 0x90; - empty[0x03] = 0x38; /* '86BOX5.0' OEM ID. */ + empty[0x03] = 0x38; /* '86BOX5.0' OEM ID. */ empty[0x04] = 0x36; empty[0x05] = 0x42; empty[0x06] = 0x4F; @@ -391,17 +426,17 @@ bool NewFloppyDialog::createSectorImage(const QString &filename, const disk_size empty[0x0A] = 0x30; *(uint16_t *) &(empty[0x0B]) = (uint16_t) sector_bytes; - *(uint8_t *) &(empty[0x0D]) = (uint8_t) disk_size.spc; + *(uint8_t *) &(empty[0x0D]) = (uint8_t) disk_size.spc; *(uint16_t *) &(empty[0x0E]) = (uint16_t) 1; - *(uint8_t *) &(empty[0x10]) = (uint8_t) disk_size.num_fats; + *(uint8_t *) &(empty[0x10]) = (uint8_t) disk_size.num_fats; *(uint16_t *) &(empty[0x11]) = (uint16_t) disk_size.root_dir_entries; *(uint16_t *) &(empty[0x13]) = (uint16_t) total_sectors; - *(uint8_t *) &(empty[0x15]) = (uint8_t) disk_size.media_desc; + *(uint8_t *) &(empty[0x15]) = (uint8_t) disk_size.media_desc; *(uint16_t *) &(empty[0x16]) = (uint16_t) disk_size.spfat; - *(uint8_t *) &(empty[0x18]) = (uint8_t) disk_size.sectors; - *(uint8_t *) &(empty[0x1A]) = (uint8_t) disk_size.sides; + *(uint8_t *) &(empty[0x18]) = (uint8_t) disk_size.sectors; + *(uint8_t *) &(empty[0x1A]) = (uint8_t) disk_size.sides; - empty[0x26] = 0x29; /* ')' followed by randomly-generated volume serial number. */ + empty[0x26] = 0x29; /* ')' followed by randomly-generated volume serial number. */ empty[0x27] = random_generate(); empty[0x28] = random_generate(); empty[0x29] = random_generate(); @@ -427,36 +462,27 @@ bool NewFloppyDialog::createSectorImage(const QString &filename, const disk_size return true; } -bool NewFloppyDialog::createZipSectorImage(const QString &filename, const disk_size_t& disk_size, FileType type, QProgressDialog& pbar) +bool +NewFloppyDialog::createZipSectorImage(const QString &filename, const disk_size_t &disk_size, FileType type, QProgressDialog &pbar) { - uint32_t total_size = 0; + uint32_t total_size = 0; uint32_t total_sectors = 0; - uint32_t sector_bytes = 0; - uint32_t root_dir_bytes = 0; - uint32_t fat_size = 0; - uint32_t fat1_offs = 0; - uint32_t fat2_offs = 0; - uint32_t zero_bytes = 0; - uint16_t base = 0x1000; - uint32_t pbar_max = 0; + uint32_t sector_bytes = 0; + uint16_t base = 0x1000; + uint32_t pbar_max = 0; QFile file(filename); - if (! file.open(QIODevice::WriteOnly)) { + if (!file.open(QIODevice::WriteOnly)) { return false; } QDataStream stream(&file); stream.setByteOrder(QDataStream::LittleEndian); - sector_bytes = (128 << disk_size.sector_len); + sector_bytes = (128 << disk_size.sector_len); total_sectors = disk_size.sides * disk_size.tracks * disk_size.sectors; if (total_sectors > ZIP_SECTORS) total_sectors = ZIP_250_SECTORS; total_size = total_sectors * sector_bytes; - root_dir_bytes = (disk_size.root_dir_entries << 5); - fat_size = (disk_size.spfat * sector_bytes); - fat1_offs = sector_bytes; - fat2_offs = fat1_offs + fat_size; - zero_bytes = fat2_offs + fat_size + root_dir_bytes; pbar_max = total_size; if (type == FileType::Zdi) { @@ -466,21 +492,21 @@ bool NewFloppyDialog::createZipSectorImage(const QString &filename, const disk_s if (type == FileType::Zdi) { QByteArray data(base, 0); - auto empty = data.data(); + auto empty = data.data(); *(uint32_t *) &(empty[0x08]) = (uint32_t) base; *(uint32_t *) &(empty[0x0C]) = total_size; *(uint16_t *) &(empty[0x10]) = (uint16_t) sector_bytes; - *(uint8_t *) &(empty[0x14]) = (uint8_t) disk_size.sectors; - *(uint8_t *) &(empty[0x18]) = (uint8_t) disk_size.sides; - *(uint8_t *) &(empty[0x1C]) = (uint8_t) disk_size.tracks; + *(uint8_t *) &(empty[0x14]) = (uint8_t) disk_size.sectors; + *(uint8_t *) &(empty[0x18]) = (uint8_t) disk_size.sides; + *(uint8_t *) &(empty[0x1C]) = (uint8_t) disk_size.tracks; stream.writeRawData(empty, base); pbar_max -= 2; } QByteArray bytes(total_size, 0); - auto empty = bytes.data(); + auto empty = bytes.data(); if (total_sectors == ZIP_SECTORS) { /* ZIP 100 */ @@ -510,7 +536,7 @@ bool NewFloppyDialog::createZipSectorImage(const QString &filename, const disk_s *(uint32_t *) &(empty[0x4020]) = 0x0002FFE0; *(uint16_t *) &(empty[0x4024]) = 0x0080; - empty[0x4026] = 0x29; /* ')' followed by randomly-generated volume serial number. */ + empty[0x4026] = 0x29; /* ')' followed by randomly-generated volume serial number. */ empty[0x4027] = random_generate(); empty[0x4028] = random_generate(); empty[0x4029] = random_generate(); @@ -535,7 +561,7 @@ bool NewFloppyDialog::createZipSectorImage(const QString &filename, const disk_s empty[0x5003] = empty[0x1D003] = 0xFF; /* Root directory = 0x35000 - Data = 0x39000 */ + Data = 0x39000 */ } else { /* ZIP 250 */ /* MBR */ @@ -557,7 +583,7 @@ bool NewFloppyDialog::createZipSectorImage(const QString &filename, const disk_s memset(&(empty[0x0200]), 0x48, 0x3E00); /* The second sector begins with some strange data - in my reference image. */ + in my reference image. */ *(uint64_t *) &(empty[0x0200]) = 0x3831393230334409LL; *(uint64_t *) &(empty[0x0208]) = 0x6A57766964483130LL; *(uint64_t *) &(empty[0x0210]) = 0x3C3A34676063653FLL; @@ -581,7 +607,7 @@ bool NewFloppyDialog::createZipSectorImage(const QString &filename, const disk_s *(uint32_t *) &(empty[0x4020]) = 0x000777E0; *(uint16_t *) &(empty[0x4024]) = 0x0080; - empty[0x4026] = 0x29; /* ')' followed by randomly-generated volume serial number. */ + empty[0x4026] = 0x29; /* ')' followed by randomly-generated volume serial number. */ empty[0x4027] = random_generate(); empty[0x4028] = random_generate(); empty[0x4029] = random_generate(); @@ -606,7 +632,7 @@ bool NewFloppyDialog::createZipSectorImage(const QString &filename, const disk_s empty[0x4203] = empty[0x22003] = 0xFF; /* Root directory = 0x3FE00 - Data = 0x38200 */ + Data = 0x38200 */ } pbar.setMaximum(pbar_max); @@ -619,26 +645,28 @@ bool NewFloppyDialog::createZipSectorImage(const QString &filename, const disk_s return true; } - -bool NewFloppyDialog::createMoSectorImage(const QString& filename, int8_t disk_size, FileType type, QProgressDialog& pbar) +bool +NewFloppyDialog::createMoSectorImage(const QString &filename, int8_t disk_size, FileType type, QProgressDialog &pbar) { - const mo_type_t *dp = &mo_types[disk_size]; - uint32_t total_size = 0, total_size2; - uint32_t total_sectors = 0; - uint32_t sector_bytes = 0; - uint16_t base = 0x1000; - uint32_t pbar_max = 0, blocks_num; + const mo_type_t *dp = &mo_types[disk_size]; + uint32_t total_size = 0; + uint32_t total_size2; + uint32_t total_sectors = 0; + uint32_t sector_bytes = 0; + uint16_t base = 0x1000; + uint32_t pbar_max = 0; + uint32_t blocks_num; QFile file(filename); - if (! file.open(QIODevice::WriteOnly)) { + if (!file.open(QIODevice::WriteOnly)) { return false; } QDataStream stream(&file); stream.setByteOrder(QDataStream::LittleEndian); - sector_bytes = dp->bytes_per_sector; + sector_bytes = dp->bytes_per_sector; total_sectors = dp->sectors; - total_size = total_sectors * sector_bytes; + total_size = total_sectors * sector_bytes; total_size2 = (total_size >> 20) << 20; total_size2 = total_size - total_size2; @@ -653,20 +681,20 @@ bool NewFloppyDialog::createMoSectorImage(const QString& filename, int8_t disk_s if (type == FileType::Mdi) { QByteArray bytes(base, 0); - auto empty = bytes.data(); + auto empty = bytes.data(); *(uint32_t *) &(empty[0x08]) = (uint32_t) base; *(uint32_t *) &(empty[0x0C]) = total_size; *(uint16_t *) &(empty[0x10]) = (uint16_t) sector_bytes; - *(uint8_t *) &(empty[0x14]) = (uint8_t) 25; - *(uint8_t *) &(empty[0x18]) = (uint8_t) 64; - *(uint8_t *) &(empty[0x1C]) = (uint8_t) (dp->sectors / 64) / 25; + *(uint8_t *) &(empty[0x14]) = (uint8_t) 25; + *(uint8_t *) &(empty[0x18]) = (uint8_t) 64; + *(uint8_t *) &(empty[0x1C]) = (uint8_t) (dp->sectors / 64) / 25; stream.writeRawData(empty, base); } QByteArray bytes(1048576, 0); - auto empty = bytes.data(); + auto empty = bytes.data(); pbar.setMaximum(blocks_num); for (uint32_t i = 0; i < blocks_num; i++) { diff --git a/src/qt/qt_newfloppydialog.hpp b/src/qt/qt_newfloppydialog.hpp index 12e761cdf..a342df567 100644 --- a/src/qt/qt_newfloppydialog.hpp +++ b/src/qt/qt_newfloppydialog.hpp @@ -10,8 +10,7 @@ class NewFloppyDialog; struct disk_size_t; class QProgressDialog; -class NewFloppyDialog : public QDialog -{ +class NewFloppyDialog : public QDialog { Q_OBJECT public: @@ -39,12 +38,12 @@ private slots: private: Ui::NewFloppyDialog *ui; - MediaType mediaType_; + MediaType mediaType_; - bool create86f(const QString& filename, const disk_size_t& disk_size, uint8_t rpm_mode); - bool createSectorImage(const QString& filename, const disk_size_t& disk_size, FileType type); - bool createZipSectorImage(const QString& filename, const disk_size_t& disk_size, FileType type, QProgressDialog& pbar); - bool createMoSectorImage(const QString& filename, int8_t disk_size, FileType type, QProgressDialog& pbar); + bool create86f(const QString &filename, const disk_size_t &disk_size, uint8_t rpm_mode); + bool createSectorImage(const QString &filename, const disk_size_t &disk_size, FileType type); + bool createZipSectorImage(const QString &filename, const disk_size_t &disk_size, FileType type, QProgressDialog &pbar); + bool createMoSectorImage(const QString &filename, int8_t disk_size, FileType type, QProgressDialog &pbar); }; #endif // QT_NEWFLOPPYDIALOG_HPP diff --git a/src/qt/qt_newfloppydialog.ui b/src/qt/qt_newfloppydialog.ui index 7fb044fcc..c0437d810 100644 --- a/src/qt/qt_newfloppydialog.ui +++ b/src/qt/qt_newfloppydialog.ui @@ -52,6 +52,9 @@ + + 30 + 0 @@ -69,6 +72,9 @@ + + 30 + 0 diff --git a/src/qt/qt_opengloptions.cpp b/src/qt/qt_opengloptions.cpp new file mode 100644 index 000000000..58030b467 --- /dev/null +++ b/src/qt/qt_opengloptions.cpp @@ -0,0 +1,196 @@ +/* + * 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. + * + * OpenGL renderer options for Qt + * + * + * + * Authors: Teemu Korhonen + * + * Copyright 2022 Teemu Korhonen + */ + +#include +#include +#include +#include + +#include + +#include "qt_opengloptions.hpp" + +extern "C" { +#include <86box/86box.h> +} + +/* Default vertex shader. */ +static const GLchar *vertex_shader = "\ +in vec2 VertexCoord;\n\ +in vec2 TexCoord;\n\ +out vec2 tex;\n\ +void main(){\n\ + gl_Position = vec4(VertexCoord, 0.0, 1.0);\n\ + tex = TexCoord;\n\ +}\n"; + +/* Default fragment shader. */ +static const GLchar *fragment_shader = "\ +in vec2 tex;\n\ +uniform sampler2D texsampler;\n\ +out vec4 color;\n\ +void main() {\n\ + color = texture(texsampler, tex);\n\ +}\n"; + +OpenGLOptions::OpenGLOptions(QObject *parent, bool loadConfig, const QString &glslVersion) + : QObject(parent) + , m_glslVersion(glslVersion) +{ + m_filter = video_filter_method == 0 + ? FilterType::Nearest + : FilterType::Linear; + + if (!loadConfig) + return; + + /* Initialize with config. */ + m_vsync = video_vsync != 0; + m_framerate = video_framerate; + + m_renderBehavior = video_framerate == -1 + ? RenderBehaviorType::SyncWithVideo + : RenderBehaviorType::TargetFramerate; + + QString shaderPath(video_shader); + + if (shaderPath.isEmpty()) { + addDefaultShader(); + } else { + try { + addShader(shaderPath); + } catch (const std::runtime_error &) { + /* Fallback to default shader */ + addDefaultShader(); + } + } +} + +void +OpenGLOptions::save() const +{ + video_vsync = m_vsync ? 1 : 0; + video_framerate = m_renderBehavior == RenderBehaviorType::SyncWithVideo ? -1 : m_framerate; + video_filter_method = m_filter == FilterType::Nearest ? 0 : 1; + + /* TODO: multiple shaders */ + auto path = m_shaders.first().path().toLocal8Bit(); + + if (!path.isEmpty()) + qstrncpy(video_shader, path.constData(), sizeof(video_shader)); + else + video_shader[0] = '\0'; +} + +OpenGLOptions::FilterType +OpenGLOptions::filter() const +{ + /* Filter method is controlled externally */ + return video_filter_method == 0 + ? FilterType::Nearest + : FilterType::Linear; +} + +void +OpenGLOptions::setRenderBehavior(RenderBehaviorType value) +{ + m_renderBehavior = value; +} + +void +OpenGLOptions::setFrameRate(int value) +{ + m_framerate = value; +} + +void +OpenGLOptions::setVSync(bool value) +{ + m_vsync = value; +} + +void +OpenGLOptions::setFilter(FilterType value) +{ + m_filter = value; +} + +void +OpenGLOptions::addShader(const QString &path) +{ + QFile shader_file(path); + + if (!shader_file.open(QIODevice::ReadOnly | QIODevice::Text)) { + throw std::runtime_error( + QString(tr("Error opening \"%1\": %2")) + .arg(path) + .arg(shader_file.errorString()) + .toStdString()); + } + + auto shader_text = QString(shader_file.readAll()); + + shader_file.close(); + + /* Remove parameter lines */ + shader_text.remove(QRegularExpression("^\\s*#pragma parameter.*?\\n", QRegularExpression::MultilineOption)); + + QRegularExpression version("^\\s*(#version\\s+\\w+)", QRegularExpression::MultilineOption); + + auto match = version.match(shader_text); + + QString version_line(m_glslVersion); + + if (match.hasMatch()) { + /* Extract existing version and remove it. */ + version_line = match.captured(1); + shader_text.remove(version); + } + + auto shader = new QOpenGLShaderProgram(this); + + auto throw_shader_error = [path, shader](const QString &what) { + throw std::runtime_error( + QString(what % ":\n\n %2") + .arg(path) + .arg(shader->log()) + .toStdString()); + }; + + static const char *extension = "\n#extension GL_ARB_shading_language_420pack : enable\n"; + + if (!shader->addShaderFromSourceCode(QOpenGLShader::Vertex, version_line % extension % "\n#define VERTEX\n#line 1\n" % shader_text)) + throw_shader_error(tr("Error compiling vertex shader in file \"%1\"")); + + if (!shader->addShaderFromSourceCode(QOpenGLShader::Fragment, version_line % extension % "\n#define FRAGMENT\n#line 1\n" % shader_text)) + throw_shader_error(tr("Error compiling fragment shader in file \"%1\"")); + + if (!shader->link()) + throw_shader_error(tr("Error linking shader program in file \"%1\"")); + + m_shaders << OpenGLShaderPass(shader, path); +} + +void +OpenGLOptions::addDefaultShader() +{ + auto shader = new QOpenGLShaderProgram(this); + shader->addShaderFromSourceCode(QOpenGLShader::Vertex, m_glslVersion % "\n" % vertex_shader); + shader->addShaderFromSourceCode(QOpenGLShader::Fragment, m_glslVersion % "\n" % fragment_shader); + shader->link(); + m_shaders << OpenGLShaderPass(shader, QString()); +} diff --git a/src/qt/qt_opengloptions.hpp b/src/qt/qt_opengloptions.hpp new file mode 100644 index 000000000..64f761670 --- /dev/null +++ b/src/qt/qt_opengloptions.hpp @@ -0,0 +1,102 @@ +/* + * 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. + * + * Header for OpenGL renderer options + * + * + * + * Authors: Teemu Korhonen + * + * Copyright 2022 Teemu Korhonen + */ + +#ifndef QT_OPENGLOPTIONS_HPP +#define QT_OPENGLOPTIONS_HPP + +#include +#include +#include +#include + +class OpenGLShaderPass { +public: + OpenGLShaderPass(QOpenGLShaderProgram *shader, const QString &path) + : m_shader(shader) + , m_path(path) + , m_vertex_coord(shader->attributeLocation("VertexCoord")) + , m_tex_coord(shader->attributeLocation("TexCoord")) + , m_color(shader->attributeLocation("Color")) + , m_mvp_matrix(shader->uniformLocation("MVPMatrix")) + , m_input_size(shader->uniformLocation("InputSize")) + , m_output_size(shader->uniformLocation("OutputSize")) + , m_texture_size(shader->uniformLocation("TextureSize")) + , m_frame_count(shader->uniformLocation("FrameCount")) + { + } + + bool bind() const { return m_shader->bind(); } + const QString &path() const { return m_path; } + const GLint &vertex_coord() const { return m_vertex_coord; } + const GLint &tex_coord() const { return m_tex_coord; } + const GLint &color() const { return m_color; } + const GLint &mvp_matrix() const { return m_mvp_matrix; } + const GLint &input_size() const { return m_input_size; } + const GLint &output_size() const { return m_output_size; } + const GLint &texture_size() const { return m_texture_size; } + const GLint &frame_count() const { return m_frame_count; } + +private: + QOpenGLShaderProgram *m_shader; + QString m_path; + GLint m_vertex_coord; + GLint m_tex_coord; + GLint m_color; + GLint m_mvp_matrix; + GLint m_input_size; + GLint m_output_size; + GLint m_texture_size; + GLint m_frame_count; +}; + +class OpenGLOptions : public QObject { + Q_OBJECT + +public: + enum RenderBehaviorType { SyncWithVideo, + TargetFramerate }; + + enum FilterType { Nearest, + Linear }; + + OpenGLOptions(QObject *parent, bool loadConfig, const QString &glslVersion); + + RenderBehaviorType renderBehavior() const { return m_renderBehavior; } + int framerate() const { return m_framerate; } + bool vSync() const { return m_vsync; } + FilterType filter() const; + + const QList &shaders() const { return m_shaders; } + + void setRenderBehavior(RenderBehaviorType value); + void setFrameRate(int value); + void setVSync(bool value); + void setFilter(FilterType value); + void addShader(const QString &path); + void addDefaultShader(); + void save() const; + +private: + RenderBehaviorType m_renderBehavior = SyncWithVideo; + int m_framerate = -1; + bool m_vsync = false; + FilterType m_filter = Nearest; + QList m_shaders; + QString m_glslVersion; +}; + +#endif diff --git a/src/qt/qt_opengloptionsdialog.cpp b/src/qt/qt_opengloptionsdialog.cpp new file mode 100644 index 000000000..acb2ce9f2 --- /dev/null +++ b/src/qt/qt_opengloptionsdialog.cpp @@ -0,0 +1,116 @@ +/* + * 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. + * + * OpenGL renderer options dialog for Qt + * + * + * + * Authors: Teemu Korhonen + * + * Copyright 2022 Teemu Korhonen + */ + +#include +#include +#include + +#include + +#include "qt_opengloptionsdialog.hpp" +#include "qt_util.hpp" +#include "ui_qt_opengloptionsdialog.h" + +OpenGLOptionsDialog::OpenGLOptionsDialog(QWidget *parent, const OpenGLOptions &options, std::function optionsFactory) + : QDialog(parent) + , ui(new Ui::OpenGLOptionsDialog) + , createOptions(optionsFactory) +{ + ui->setupUi(this); + + if (options.renderBehavior() == OpenGLOptions::SyncWithVideo) + ui->syncWithVideo->setChecked(true); + else { + ui->syncToFramerate->setChecked(true); + ui->targetFps->setValue(options.framerate()); + } + + ui->vsync->setChecked(options.vSync()); + + if (!options.shaders().isEmpty()) { + auto path = options.shaders().first().path(); + if (!path.isEmpty()) + ui->shader->setPlainText(path); + } +} + +OpenGLOptionsDialog::~OpenGLOptionsDialog() +{ + delete ui; +} + +void +OpenGLOptionsDialog::accept() +{ + auto options = createOptions(); + + options->setRenderBehavior( + ui->syncWithVideo->isChecked() + ? OpenGLOptions::SyncWithVideo + : OpenGLOptions::TargetFramerate); + + options->setFrameRate(ui->targetFps->value()); + + options->setVSync(ui->vsync->isChecked()); + + auto shader = ui->shader->toPlainText(); + + try { + + if (!shader.isEmpty()) + options->addShader(shader); + else + options->addDefaultShader(); + + } catch (const std::runtime_error &e) { + delete options; + + QMessageBox msgBox(this); + msgBox.setWindowTitle(tr("Shader error")); + msgBox.setText(tr("Could not load shaders.")); + msgBox.setInformativeText(tr("More information in details.")); + msgBox.setDetailedText(e.what()); + msgBox.setIcon(QMessageBox::Critical); + msgBox.setStandardButtons(QMessageBox::Close); + msgBox.setDefaultButton(QMessageBox::Close); + msgBox.setStyleSheet("QTextEdit { min-width: 45em; }"); + msgBox.exec(); + + return; + } + + options->save(); + + emit optionsChanged(options); + + QDialog::accept(); +} + +void +OpenGLOptionsDialog::on_addShader_clicked() +{ + auto shader = QFileDialog::getOpenFileName( + this, + QString(), + QString(), + tr("OpenGL Shaders") % util::DlgFilter({ "glsl" }, true)); + + if (shader.isNull()) + return; + + ui->shader->setPlainText(shader); +} diff --git a/src/qt/qt_opengloptionsdialog.hpp b/src/qt/qt_opengloptionsdialog.hpp new file mode 100644 index 000000000..f34d74d75 --- /dev/null +++ b/src/qt/qt_opengloptionsdialog.hpp @@ -0,0 +1,51 @@ +/* + * 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. + * + * Header for OpenGL renderer options dialog + * + * Authors: Teemu Korhonen + * + * Copyright 2022 Teemu Korhonen + */ + +#ifndef QT_OPENGLOPTIONSDIALOG_H +#define QT_OPENGLOPTIONSDIALOG_H + +#include + +#include + +#include "qt_opengloptions.hpp" + +namespace Ui { +class OpenGLOptionsDialog; +} + +class OpenGLOptionsDialog : public QDialog { + Q_OBJECT + +public: + explicit OpenGLOptionsDialog(QWidget *parent, const OpenGLOptions &options, std::function optionsFactory); + ~OpenGLOptionsDialog(); + +signals: + void optionsChanged(OpenGLOptions *options); + +public slots: + void accept() override; + +private: + Ui::OpenGLOptionsDialog *ui; + + std::function createOptions; + +private slots: + void on_addShader_clicked(); +}; + +#endif // QT_OPENGLOPTIONSDIALOG_H diff --git a/src/qt/qt_opengloptionsdialog.ui b/src/qt/qt_opengloptionsdialog.ui new file mode 100644 index 000000000..a6f86b6c2 --- /dev/null +++ b/src/qt/qt_opengloptionsdialog.ui @@ -0,0 +1,280 @@ + + + OpenGLOptionsDialog + + + + 0 + 0 + 400 + 320 + + + + OpenGL 3.0 renderer options + + + + + + Render behavior + + + + + + Use target framerate: + + + + + + + false + + + fps + + + 15 + + + 240 + + + 60 + + + + + + + VSync + + + + + + + <html><head/><body><p>Render each frame immediately, in sync with the emulated display.</p><p><span style=" font-style:italic;">This is the recommended option if the shaders in use don't utilize frametime for animated effects.</span></p></body></html> + + + Synchronize with video + + + true + + + + + + + false + + + 15 + + + 240 + + + 60 + + + Qt::Horizontal + + + false + + + QSlider::NoTicks + + + + + + + + + + Shaders + + + + + + Remove + + + + + + + Qt::Vertical + + + + 20 + 40 + + + + + + + + true + + + No shader selected + + + + + + + Browse... + + + + + + + + + + Qt::Horizontal + + + QDialogButtonBox::Cancel|QDialogButtonBox::Ok + + + + + + + syncWithVideo + syncToFramerate + fpsSlider + targetFps + vsync + shader + addShader + removeShader + + + + + buttonBox + accepted() + OpenGLOptionsDialog + accept() + + + 257 + 310 + + + 157 + 274 + + + + + buttonBox + rejected() + OpenGLOptionsDialog + reject() + + + 325 + 310 + + + 286 + 274 + + + + + syncToFramerate + toggled(bool) + targetFps + setEnabled(bool) + + + 140 + 71 + + + 380 + 98 + + + + + syncToFramerate + toggled(bool) + fpsSlider + setEnabled(bool) + + + 158 + 66 + + + 168 + 87 + + + + + fpsSlider + valueChanged(int) + targetFps + setValue(int) + + + 252 + 90 + + + 308 + 89 + + + + + targetFps + valueChanged(int) + fpsSlider + setValue(int) + + + 364 + 93 + + + 134 + 93 + + + + + removeShader + clicked() + shader + clear() + + + 333 + 201 + + + 235 + 208 + + + + + diff --git a/src/qt/qt_openglrenderer.cpp b/src/qt/qt_openglrenderer.cpp new file mode 100644 index 000000000..60aa998a9 --- /dev/null +++ b/src/qt/qt_openglrenderer.cpp @@ -0,0 +1,468 @@ +/* + * 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. + * + * OpenGL renderer for Qt + * + * + * + * Authors: Teemu Korhonen + * + * Copyright 2022 Teemu Korhonen + */ + +#include +#include +#include +#include +#include +#include + +#include + +#include "qt_opengloptionsdialog.hpp" +#include "qt_openglrenderer.hpp" + +#ifndef GL_MAP_PERSISTENT_BIT +# define GL_MAP_PERSISTENT_BIT 0x0040 +#endif + +#ifndef GL_MAP_COHERENT_BIT +# define GL_MAP_COHERENT_BIT 0x0080 +#endif + +OpenGLRenderer::OpenGLRenderer(QWidget *parent) + : QWindow(parent->windowHandle()) + , renderTimer(new QTimer(this)) + , options(nullptr) +{ + renderTimer->setTimerType(Qt::PreciseTimer); + /* TODO: need's more accuracy, maybe target 1ms earlier and spin yield */ + connect(renderTimer, &QTimer::timeout, this, &OpenGLRenderer::render); + + buf_usage = std::vector(BUFFERCOUNT); + for (auto &flag : buf_usage) + flag.clear(); + + setSurfaceType(QWindow::OpenGLSurface); + + QSurfaceFormat format; + +#ifdef Q_OS_MACOS + format.setVersion(4, 1); +#else + format.setVersion(3, 2); +#endif + format.setProfile(QSurfaceFormat::OpenGLContextProfile::CoreProfile); + + if (QOpenGLContext::openGLModuleType() == QOpenGLContext::LibGLES) + format.setRenderableType(QSurfaceFormat::OpenGLES); + + setFormat(format); + + parentWidget = parent; + + source.setRect(0, 0, INIT_WIDTH, INIT_HEIGHT); +} + +OpenGLRenderer::~OpenGLRenderer() +{ + finalize(); +} + +void +OpenGLRenderer::exposeEvent(QExposeEvent *event) +{ + Q_UNUSED(event); + + if (!isInitialized) + initialize(); + + onResize(size().width(), size().height()); +} + +void +OpenGLRenderer::resizeEvent(QResizeEvent *event) +{ + Q_UNUSED(event); + + onResize(event->size().width(), event->size().height()); + + if (notReady()) + return; + + context->makeCurrent(this); + + glViewport( + destination.x() * devicePixelRatio(), + destination.y() * devicePixelRatio(), + destination.width() * devicePixelRatio(), + destination.height() * devicePixelRatio()); +} + +bool +OpenGLRenderer::event(QEvent *event) +{ + Q_UNUSED(event); + + bool res = false; + if (!eventDelegate(event, res)) + return QWindow::event(event); + return res; +} + +void +OpenGLRenderer::initialize() +{ + try { + context = new QOpenGLContext(this); + + context->setFormat(format()); + + if (!context->create()) + throw opengl_init_error(tr("Couldn't create OpenGL context.")); + + if (!context->makeCurrent(this)) + throw opengl_init_error(tr("Couldn't switch to OpenGL context.")); + + auto version = context->format().version(); + + if (version.first < 3) + throw opengl_init_error(tr("OpenGL version 3.0 or greater is required. Current version is %1.%2").arg(version.first).arg(version.second)); + + initializeOpenGLFunctions(); + + /* Prepare the shader version string */ + glslVersion = reinterpret_cast(glGetString(GL_SHADING_LANGUAGE_VERSION)); + glslVersion.truncate(4); + glslVersion.remove('.'); + glslVersion.prepend("#version "); + if (QOpenGLContext::openGLModuleType() == QOpenGLContext::LibGLES) + glslVersion.append(" es"); + else if (context->format().profile() == QSurfaceFormat::CoreProfile) + glslVersion.append(" core"); + + initializeExtensions(); + + initializeBuffers(); + + /* Vertex, texture 2d coordinates and color (white) making a quad as triangle strip */ + const GLfloat surface[] = { + -1.f, 1.f, 0.f, 0.f, 1.f, 1.f, 1.f, 1.f, + 1.f, 1.f, 1.f, 0.f, 1.f, 1.f, 1.f, 1.f, + -1.f, -1.f, 0.f, 1.f, 1.f, 1.f, 1.f, 1.f, + 1.f, -1.f, 1.f, 1.f, 1.f, 1.f, 1.f, 1.f + }; + + glGenVertexArrays(1, &vertexArrayID); + + glBindVertexArray(vertexArrayID); + + glGenBuffers(1, &vertexBufferID); + glBindBuffer(GL_ARRAY_BUFFER, vertexBufferID); + glBufferData(GL_ARRAY_BUFFER, sizeof(surface), surface, GL_STATIC_DRAW); + + glGenTextures(1, &textureID); + glBindTexture(GL_TEXTURE_2D, textureID); + + const GLfloat border_color[] = { 0.f, 0.f, 0.f, 1.f }; + + glTexParameterfv(GL_TEXTURE_2D, GL_TEXTURE_BORDER_COLOR, border_color); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_BORDER); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_BORDER); + + glTexImage2D(GL_TEXTURE_2D, 0, QOpenGLTexture::RGBA8_UNorm, INIT_WIDTH, INIT_HEIGHT, 0, QOpenGLTexture::BGRA, QOpenGLTexture::UInt32_RGBA8_Rev, NULL); + + reloadOptions(); + + glClearColor(0.f, 0.f, 0.f, 1.f); + + glViewport( + destination.x() * devicePixelRatio(), + destination.y() * devicePixelRatio(), + destination.width() * devicePixelRatio(), + destination.height() * devicePixelRatio()); + + GLenum error = glGetError(); + if (error != GL_NO_ERROR) + throw opengl_init_error(tr("OpenGL initialization failed. Error %1.").arg(error)); + + isInitialized = true; + + emit initialized(); + + glClear(GL_COLOR_BUFFER_BIT); + + context->swapBuffers(this); + } catch (const opengl_init_error &e) { + /* Mark all buffers as in use */ + for (auto &flag : buf_usage) + flag.test_and_set(); + + QMessageBox::critical((QWidget *) qApp->findChild(), tr("Error initializing OpenGL"), e.what() % tr("\nFalling back to software rendering.")); + + context->doneCurrent(); + isFinalized = true; + isInitialized = true; + + emit errorInitializing(); + } +} + +void +OpenGLRenderer::finalize() +{ + if (isFinalized) + return; + + renderTimer->stop(); + + context->makeCurrent(this); + + if (hasBufferStorage) + glUnmapBuffer(GL_PIXEL_UNPACK_BUFFER); + + glDeleteBuffers(1, &unpackBufferID); + glDeleteTextures(1, &textureID); + glDeleteBuffers(1, &vertexBufferID); + glDeleteVertexArrays(1, &vertexArrayID); + + if (!hasBufferStorage && unpackBuffer) + free(unpackBuffer); + + context->doneCurrent(); + + isFinalized = true; +} + +QDialog * +OpenGLRenderer::getOptions(QWidget *parent) +{ + auto dialog = new OpenGLOptionsDialog(parent, *options, [this]() { return new OpenGLOptions(this, false, glslVersion); }); + + connect(dialog, &OpenGLOptionsDialog::optionsChanged, this, &OpenGLRenderer::updateOptions); + + return dialog; +} + +void +OpenGLRenderer::initializeExtensions() +{ +#ifndef NO_BUFFER_STORAGE + if (context->hasExtension("GL_ARB_buffer_storage") || context->hasExtension("GL_EXT_buffer_storage")) { + hasBufferStorage = true; + + glBufferStorage = (PFNGLBUFFERSTORAGEEXTPROC_LOCAL) context->getProcAddress(context->hasExtension("GL_EXT_buffer_storage") ? "glBufferStorageEXT" : "glBufferStorage"); + if (!glBufferStorage) + glBufferStorage = (PFNGLBUFFERSTORAGEEXTPROC_LOCAL) context->getProcAddress("glBufferStorage"); + } +#endif +} + +void +OpenGLRenderer::initializeBuffers() +{ + glGenBuffers(1, &unpackBufferID); + + glBindBuffer(GL_PIXEL_UNPACK_BUFFER, unpackBufferID); + + if (hasBufferStorage) { +#ifndef NO_BUFFER_STORAGE + /* Create persistent buffer for pixel transfer. */ + glBufferStorage(GL_PIXEL_UNPACK_BUFFER, BUFFERBYTES * BUFFERCOUNT, NULL, GL_MAP_WRITE_BIT | GL_MAP_PERSISTENT_BIT | GL_MAP_COHERENT_BIT); + + unpackBuffer = glMapBufferRange(GL_PIXEL_UNPACK_BUFFER, 0, BUFFERBYTES * BUFFERCOUNT, GL_MAP_WRITE_BIT | GL_MAP_PERSISTENT_BIT | GL_MAP_COHERENT_BIT); +#endif + } else { + /* Fallback; create our own buffer. */ + unpackBuffer = malloc(BUFFERBYTES * BUFFERCOUNT); + + if (unpackBuffer == nullptr) + throw opengl_init_error(tr("Allocating memory for unpack buffer failed.")); + + glBufferData(GL_PIXEL_UNPACK_BUFFER, BUFFERBYTES * BUFFERCOUNT, NULL, GL_STREAM_DRAW); + } +} + +void +OpenGLRenderer::applyOptions() +{ + /* TODO: change detection in options */ + + if (options->framerate() > 0) { + int interval = (int) ceilf(1000.f / (float) options->framerate()); + renderTimer->setInterval(std::chrono::milliseconds(interval)); + } + + if (options->renderBehavior() == OpenGLOptions::TargetFramerate) + renderTimer->start(); + else + renderTimer->stop(); + + auto format = this->format(); + int interval = options->vSync() ? 1 : 0; + + if (format.swapInterval() != interval) { + format.setSwapInterval(interval); + setFormat(format); + context->setFormat(format); + } + + GLint filter = options->filter() == OpenGLOptions::Linear ? GL_LINEAR : GL_NEAREST; + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, filter); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, filter); + + currentFilter = options->filter(); +} + +void +OpenGLRenderer::reloadOptions() +{ + if (options) { + delete options; + options = nullptr; + } + options = new OpenGLOptions(this, true, glslVersion); + + applyOptions(); +} + +void +OpenGLRenderer::applyShader(const OpenGLShaderPass &shader) +{ + if (!shader.bind()) + return; + + if (shader.vertex_coord() != -1) { + glEnableVertexAttribArray(shader.vertex_coord()); + glVertexAttribPointer(shader.vertex_coord(), 2, GL_FLOAT, GL_FALSE, 8 * sizeof(GLfloat), 0); + } + + if (shader.tex_coord() != -1) { + glEnableVertexAttribArray(shader.tex_coord()); + glVertexAttribPointer(shader.tex_coord(), 2, GL_FLOAT, GL_FALSE, 8 * sizeof(GLfloat), (void *) (2 * sizeof(GLfloat))); + } + + if (shader.color() != -1) { + glEnableVertexAttribArray(shader.color()); + glVertexAttribPointer(shader.color(), 4, GL_FLOAT, GL_FALSE, 8 * sizeof(GLfloat), (void *) (4 * sizeof(GLfloat))); + } + + if (shader.mvp_matrix() != -1) { + static const GLfloat mvp[] = { + 1.f, 0.f, 0.f, 0.f, + 0.f, 1.f, 0.f, 0.f, + 0.f, 0.f, 1.f, 0.f, + 0.f, 0.f, 0.f, 1.f + }; + glUniformMatrix4fv(shader.mvp_matrix(), 1, GL_FALSE, mvp); + } + + if (shader.output_size() != -1) + glUniform2f(shader.output_size(), destination.width(), destination.height()); + + if (shader.input_size() != -1) + glUniform2f(shader.input_size(), source.width(), source.height()); + + if (shader.texture_size() != -1) + glUniform2f(shader.texture_size(), source.width(), source.height()); + + if (shader.frame_count() != -1) + glUniform1i(shader.frame_count(), frameCounter); +} + +void +OpenGLRenderer::render() +{ + context->makeCurrent(this); + + if (options->filter() != currentFilter) + applyOptions(); + + /* TODO: multiple shader passes */ + applyShader(options->shaders().first()); + + glClear(GL_COLOR_BUFFER_BIT); + glDrawArrays(GL_TRIANGLE_STRIP, 0, 4); + + context->swapBuffers(this); + + frameCounter = (frameCounter + 1) & 1023; +} + +void +OpenGLRenderer::updateOptions(OpenGLOptions *newOptions) +{ + context->makeCurrent(this); + + glUseProgram(0); + + delete options; + + options = newOptions; + + options->setParent(this); + + applyOptions(); +} + +std::vector> +OpenGLRenderer::getBuffers() +{ + std::vector> buffers; + + if (notReady() || !unpackBuffer) + return buffers; + + /* Split the buffer area */ + for (int i = 0; i < BUFFERCOUNT; i++) { + buffers.push_back(std::make_tuple((uint8_t *) unpackBuffer + BUFFERBYTES * i, &buf_usage[i])); + } + + return buffers; +} + +void +OpenGLRenderer::onBlit(int buf_idx, int x, int y, int w, int h) +{ + if (notReady()) + return; + + context->makeCurrent(this); + +#ifdef Q_OS_MACOS + glViewport( + destination.x() * devicePixelRatio(), + destination.y() * devicePixelRatio(), + destination.width() * devicePixelRatio(), + destination.height() * devicePixelRatio()); +#endif + + if (source.width() != w || source.height() != h) { + source.setRect(0, 0, w, h); + + /* Resize the texture */ + glBindBuffer(GL_PIXEL_UNPACK_BUFFER, 0); + glTexImage2D(GL_TEXTURE_2D, 0, (GLenum) QOpenGLTexture::RGBA8_UNorm, source.width(), source.height(), 0, (GLenum) QOpenGLTexture::BGRA, (GLenum) QOpenGLTexture::UInt32_RGBA8_Rev, NULL); + glBindBuffer(GL_PIXEL_UNPACK_BUFFER, unpackBufferID); + } + + if (!hasBufferStorage) + glBufferSubData(GL_PIXEL_UNPACK_BUFFER, BUFFERBYTES * buf_idx, h * ROW_LENGTH * sizeof(uint32_t) + (y * ROW_LENGTH * sizeof(uint32_t)), (uint8_t *) unpackBuffer + BUFFERBYTES * buf_idx); + + glPixelStorei(GL_UNPACK_SKIP_PIXELS, BUFFERPIXELS * buf_idx + y * ROW_LENGTH + x); + glPixelStorei(GL_UNPACK_ROW_LENGTH, ROW_LENGTH); + glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, w, h, (GLenum) QOpenGLTexture::BGRA, (GLenum) QOpenGLTexture::UInt32_RGBA8_Rev, NULL); + + /* TODO: check if fence sync is implementable here and still has any benefit. */ + glFinish(); + + buf_usage[buf_idx].clear(); + + if (options->renderBehavior() == OpenGLOptions::SyncWithVideo) + render(); +} diff --git a/src/qt/qt_openglrenderer.hpp b/src/qt/qt_openglrenderer.hpp new file mode 100644 index 000000000..27822600c --- /dev/null +++ b/src/qt/qt_openglrenderer.hpp @@ -0,0 +1,125 @@ +/* + * 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. + * + * Header file for OpenGL renderer + * + * + * + * Authors: Teemu Korhonen + * + * Copyright 2022 Teemu Korhonen + */ + +#ifndef QT_OPENGLRENDERER_HPP +#define QT_OPENGLRENDERER_HPP + +#if defined Q_OS_MACOS || __arm__ +# define NO_BUFFER_STORAGE +#endif + +#include +#include +#include +#include +#include +#include +#if !defined NO_BUFFER_STORAGE && !(QT_VERSION >= QT_VERSION_CHECK(6, 0, 0)) +# include +#endif + +#include +#include +#include +#include + +#include "qt_opengloptions.hpp" +#include "qt_renderercommon.hpp" + +typedef void(QOPENGLF_APIENTRYP PFNGLBUFFERSTORAGEEXTPROC_LOCAL)(GLenum target, GLsizeiptr size, const void *data, GLbitfield flags); + +class OpenGLRenderer : public QWindow, protected QOpenGLExtraFunctions, public RendererCommon { + Q_OBJECT + +public: + QOpenGLContext *context; + + OpenGLRenderer(QWidget *parent = nullptr); + ~OpenGLRenderer(); + + std::vector> getBuffers() override; + + void finalize() override final; + bool hasOptions() const override { return true; } + QDialog *getOptions(QWidget *parent) override; + void reloadOptions() override; + +signals: + void initialized(); + void errorInitializing(); + +public slots: + void onBlit(int buf_idx, int x, int y, int w, int h); + +protected: + void exposeEvent(QExposeEvent *event) override; + void resizeEvent(QResizeEvent *event) override; + bool event(QEvent *event) override; + +private: + static constexpr int INIT_WIDTH = 640; + static constexpr int INIT_HEIGHT = 400; + static constexpr int ROW_LENGTH = 2048; + static constexpr int BUFFERPIXELS = 4194304; + static constexpr int BUFFERBYTES = 16777216; /* Pixel is 4 bytes. */ + static constexpr int BUFFERCOUNT = 3; /* How many buffers to use for pixel transfer (2-3 is commonly recommended). */ + + QTimer *renderTimer; + OpenGLOptions *options; + + QString glslVersion; + + bool isInitialized = false; + bool isFinalized = false; + + GLuint unpackBufferID = 0; + GLuint vertexArrayID = 0; + GLuint vertexBufferID = 0; + GLuint textureID = 0; + int frameCounter = 0; + + OpenGLOptions::FilterType currentFilter; + + void *unpackBuffer = nullptr; + + void initialize(); + void initializeExtensions(); + void initializeBuffers(); + void applyOptions(); + void applyShader(const OpenGLShaderPass &shader); + bool notReady() const { return !isInitialized || isFinalized; } + + /* GL_ARB_buffer_storage */ + bool hasBufferStorage = false; +#ifndef NO_BUFFER_STORAGE + PFNGLBUFFERSTORAGEEXTPROC_LOCAL glBufferStorage = nullptr; +#endif + +private slots: + void render(); + void updateOptions(OpenGLOptions *newOptions); +}; + +class opengl_init_error : public std::runtime_error { +public: + opengl_init_error(const QString &what) + : std::runtime_error(what.toStdString()) + { + } +}; + +#endif diff --git a/src/qt/qt_platform.cpp b/src/qt/qt_platform.cpp index 7c329c074..f306b6138 100644 --- a/src/qt/qt_platform.cpp +++ b/src/qt/qt_platform.cpp @@ -1,21 +1,22 @@ /* - * 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. + * 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. + * This file is part of the 86Box distribution. * - * Common platform functions. + * Common platform functions. * * - * Authors: Joakim L. Gilje + * + * Authors: Joakim L. Gilje * Cacodemon345 * Teemu Korhonen * - * Copyright 2021 Joakim L. Gilje - * Copyright 2021-2022 Cacodemon345 - * Copyright 2021-2022 Teemu Korhonen + * Copyright 2021 Joakim L. Gilje + * Copyright 2021-2022 Cacodemon345 + * Copyright 2021-2022 Teemu Korhonen */ #include @@ -30,33 +31,49 @@ #include #include #include +#include #include #include +#include +#include +#include +#include #include #include +#include + +#include "qt_rendererstack.hpp" #include "qt_mainwindow.hpp" #include "qt_progsettings.hpp" +#include "qt_util.hpp" #ifdef Q_OS_UNIX -#include +# include #endif -// static QByteArray buf; +#if 0 +static QByteArray buf; +#endif extern QElapsedTimer elapsed_timer; -extern MainWindow* main_window; -QElapsedTimer elapsed_timer; +extern MainWindow *main_window; +QElapsedTimer elapsed_timer; -static std::atomic_int blitmx_contention = 0; -static std::mutex blitmx; +static std::atomic_int blitmx_contention = 0; +static std::recursive_mutex blitmx; class CharPointer { public: - CharPointer(char* buf, int size) : b(buf), s(size) {} - CharPointer& operator=(const QByteArray &ba) { + CharPointer(char *buf, int size) + : b(buf) + , s(size) + { + } + CharPointer &operator=(const QByteArray &ba) + { if (s > 0) { - strncpy(b, ba.data(), s-1); + strncpy(b, ba.data(), s - 1); b[s] = 0; } else { // if we haven't been told the length of b, just assume enough @@ -66,44 +83,53 @@ public: } return *this; } + private: - char* b; - int s; + char *b; + int s; }; extern "C" { #ifdef Q_OS_WINDOWS -#define NOMINMAX -#include -#include <86box/win.h> +# ifndef NOMINMAX +# define NOMINMAX +# endif +# include +# include <86box/win.h> #else -#include +# include #endif #include <86box/86box.h> #include <86box/device.h> #include <86box/gameport.h> #include <86box/timer.h> #include <86box/nvr.h> +#include <86box/path.h> #include <86box/plat_dynld.h> +#include <86box/mem.h> +#include <86box/rom.h> #include <86box/config.h> #include <86box/ui.h> -#include <86box/discord.h> +#ifdef DISCORD +# include <86box/discord.h> +#endif #include "../cpu/cpu.h" #include <86box/plat.h> -volatile int cpu_thread_run = 1; -int mouse_capture = 0; -int fixed_size_x = 640; -int fixed_size_y = 480; -int rctrl_is_lalt = 0; -int update_icons = 1; -int kbd_req_capture = 0; -int hide_status_bar = 0; -int hide_tool_bar = 0; -uint32_t lang_id = 0x0409, lang_sys = 0x0409; // Multilangual UI variables, for now all set to LCID of en-US +volatile int cpu_thread_run = 1; +int mouse_capture = 0; +int fixed_size_x = 640; +int fixed_size_y = 480; +int rctrl_is_lalt = 0; +int update_icons = 1; +int kbd_req_capture = 0; +int hide_status_bar = 0; +int hide_tool_bar = 0; +uint32_t lang_id = 0x0409, lang_sys = 0x0409; // Multilangual UI variables, for now all set to LCID of en-US -int stricmp(const char* s1, const char* s2) +int +stricmp(const char *s1, const char *s2) { #ifdef Q_OS_WINDOWS return _stricmp(s1, s2); @@ -112,7 +138,8 @@ int stricmp(const char* s1, const char* s2) #endif } -int strnicmp(const char *s1, const char *s2, size_t n) +int +strnicmp(const char *s1, const char *s2, size_t n) { #ifdef Q_OS_WINDOWS return _strnicmp(s1, s2, n); @@ -125,16 +152,19 @@ void do_stop(void) { cpu_thread_run = 0; - //main_window->close(); +#if 0 + main_window->close(); +#endif } -void plat_get_exe_name(char *s, int size) +void +plat_get_exe_name(char *s, int size) { QByteArray exepath_temp = QCoreApplication::applicationDirPath().toLocal8Bit(); - memcpy(s, exepath_temp.data(), std::min((qsizetype)exepath_temp.size(),(qsizetype)size)); + memcpy(s, exepath_temp.data(), std::min((qsizetype) exepath_temp.size(), (qsizetype) size)); - plat_path_slash(s); + path_slash(s); } uint32_t @@ -152,13 +182,25 @@ plat_timer_read(void) FILE * plat_fopen(const char *path, const char *mode) { +#if defined(Q_OS_MACOS) or defined(Q_OS_LINUX) + QFileInfo fi(path); + QString filename = (fi.isRelative() && !fi.filePath().isEmpty()) ? usr_path + fi.filePath() : fi.filePath(); + return fopen(filename.toUtf8().constData(), mode); +#else return fopen(QString::fromUtf8(path).toLocal8Bit(), mode); +#endif } FILE * plat_fopen64(const char *path, const char *mode) { - return fopen(path, mode); +#if defined(Q_OS_MACOS) or defined(Q_OS_LINUX) + QFileInfo fi(path); + QString filename = (fi.isRelative() && !fi.filePath().isEmpty()) ? usr_path + fi.filePath() : fi.filePath(); + return fopen(filename.toUtf8().constData(), mode); +#else + return fopen(QString::fromUtf8(path).toLocal8Bit(), mode); +#endif } int @@ -177,52 +219,57 @@ plat_dir_check(char *path) int plat_getcwd(char *bufp, int max) { +#ifdef __APPLE__ + /* Working directory for .app bundles is undefined. */ + strncpy(bufp, exe_path, max); +#else CharPointer(bufp, max) = QDir::currentPath().toUtf8(); +#endif return 0; } void -plat_get_dirname(char *dest, const char *path) +path_get_dirname(char *dest, const char *path) { QFileInfo fi(path); CharPointer(dest, -1) = fi.dir().path().toUtf8(); } char * -plat_get_extension(char *s) +path_get_extension(char *s) { auto len = strlen(s); auto idx = QByteArray::fromRawData(s, len).lastIndexOf('.'); if (idx >= 0) { - return s+idx+1; + return s + idx + 1; } - return s+len; + return s + len; } char * -plat_get_filename(char *s) +path_get_filename(char *s) { #ifdef Q_OS_WINDOWS int c = strlen(s) - 1; while (c > 0) { - if (s[c] == '/' || s[c] == '\\') - return(&s[c+1]); - c--; + if (s[c] == '/' || s[c] == '\\') + return (&s[c + 1]); + c--; } - return(s); + return s; #else - auto idx = QByteArray::fromRawData(s, strlen(s)).lastIndexOf(QDir::separator().toLatin1()); + auto idx = QByteArray::fromRawData(s, strlen(s)).lastIndexOf(QDir::separator().toLatin1()); if (idx >= 0) { - return s+idx+1; + return s + idx + 1; } return s; #endif } int -plat_path_abs(char *path) +path_abs(char *path) { #ifdef Q_OS_WINDOWS if ((path[1] == ':') || (path[0] == '\\') || (path[0] == '/')) @@ -235,21 +282,39 @@ plat_path_abs(char *path) } void -plat_path_slash(char *path) +path_normalize(char *path) { - auto len = strlen(path); - auto separator = QDir::separator().toLatin1(); - if (path[len-1] != separator) { - path[len] = separator; - path[len+1] = 0; +#ifdef Q_OS_WINDOWS + while (*path++ != 0) { + if (*path == '\\') + *path = '/'; } +#endif } void -plat_append_filename(char *dest, const char *s1, const char *s2) +path_slash(char *path) +{ + auto len = strlen(path); + auto separator = '/'; + if (path[len - 1] != separator) { + path[len] = separator; + path[len + 1] = 0; + } + path_normalize(path); +} + +const char * +path_get_slash(char *path) +{ + return QString(path).endsWith("/") ? "" : "/"; +} + +void +path_append_filename(char *dest, const char *s1, const char *s2) { strcpy(dest, s1); - plat_path_slash(dest); + path_slash(dest); strcat(dest, s2); } @@ -262,12 +327,14 @@ plat_tempfile(char *bufp, char *prefix, char *suffix) name.append(QString("%1-").arg(prefix)); } - name.append(QDateTime::currentDateTime().toString("yyyyMMdd-hhmmss-zzzz")); - if (suffix) name.append(suffix); - strcpy(bufp, name.toUtf8().data()); + name.append(QDateTime::currentDateTime().toString("yyyyMMdd-hhmmss-zzz")); + if (suffix) + name.append(suffix); + strcpy(bufp, name.toUtf8().data()); } -void plat_remove(char* path) +void +plat_remove(char *path) { QFile(path).remove(); } @@ -278,11 +345,11 @@ plat_mmap(size_t size, uint8_t executable) #if defined Q_OS_WINDOWS return VirtualAlloc(NULL, size, MEM_COMMIT, executable ? PAGE_EXECUTE_READWRITE : PAGE_READWRITE); #elif defined Q_OS_UNIX -#if defined Q_OS_DARWIN && defined MAP_JIT +# if defined Q_OS_DARWIN && defined MAP_JIT void *ret = mmap(0, size, PROT_READ | PROT_WRITE | (executable ? PROT_EXEC : 0), MAP_ANON | MAP_PRIVATE | (executable ? MAP_JIT : 0), -1, 0); -#else +# else void *ret = mmap(0, size, PROT_READ | PROT_WRITE | (executable ? PROT_EXEC : 0), MAP_ANON | MAP_PRIVATE, -1, 0); -#endif +# endif return (ret == MAP_FAILED) ? nullptr : ret; #endif } @@ -301,42 +368,50 @@ void plat_pause(int p) { static wchar_t oldtitle[512]; - wchar_t title[512], paused_msg[64]; + wchar_t title[1024]; + wchar_t paused_msg[512]; if (p == dopause) { #ifdef Q_OS_WINDOWS if (source_hwnd) - PostMessage((HWND)(uintptr_t)source_hwnd, WM_SENDSTATUS, (WPARAM)!!p, (LPARAM)(HWND)main_window->winId()); + PostMessage((HWND) (uintptr_t) source_hwnd, WM_SENDSTATUS, (WPARAM) !!p, (LPARAM) (HWND) main_window->winId()); #endif return; } + if ((p == 0) && (time_sync & TIME_SYNC_ENABLED)) nvr_time_sync(); - dopause = p; + do_pause(p); if (p) { + if (mouse_capture) + plat_mouse_capture(0); + wcsncpy(oldtitle, ui_window_title(NULL), sizeof_w(oldtitle) - 1); wcscpy(title, oldtitle); - QObject::tr(" - PAUSED").toWCharArray(paused_msg); + paused_msg[QObject::tr(" - PAUSED").toWCharArray(paused_msg)] = 0; wcscat(title, paused_msg); ui_window_title(title); } else { ui_window_title(oldtitle); } + +#ifdef DISCORD discord_update_activity(dopause); +#endif + + QTimer::singleShot(0, main_window, &MainWindow::updateUiPauseState); #ifdef Q_OS_WINDOWS if (source_hwnd) - PostMessage((HWND)(uintptr_t)source_hwnd, WM_SENDSTATUS, (WPARAM)!!p, (LPARAM)(HWND)main_window->winId()); + PostMessage((HWND) (uintptr_t) source_hwnd, WM_SENDSTATUS, (WPARAM) !!p, (LPARAM) (HWND) main_window->winId()); #endif } -// because we can't include nvr.h because it's got fields named new -extern int nvr_save(void); - void plat_power_off(void) { + plat_mouse_capture(0); confirm_exit = 0; nvr_save(); config_save(); @@ -346,47 +421,50 @@ plat_power_off(void) cycles -= 99999999; cpu_thread_run = 0; - main_window->close(); + QTimer::singleShot(0, (const QWidget *) main_window, &QMainWindow::close); } -void set_language(uint32_t id) { +void +set_language(uint32_t id) +{ lang_id = id; } -extern "C++" -{ - QMap> ProgSettings::lcid_langcode = - { - {0x0405, {"cs-CZ", "Czech (Czech Republic)"} }, - {0x0407, {"de-DE", "German (Germany)"} }, - {0x0408, {"en-US", "English (United States)"} }, - {0x0809, {"en-GB", "English (United Kingdom)"} }, - {0x0C0A, {"es-ES", "Spanish (Spain)"} }, - {0x040B, {"fi-FI", "Finnish (Finland)"} }, - {0x040C, {"fr-FR", "French (France)"} }, - {0x041A, {"hr-HR", "Croatian (Croatia)"} }, - {0x040E, {"hu-HU", "Hungarian (Hungary)"} }, - {0x0410, {"it-IT", "Italian (Italy)"} }, - {0x0411, {"ja-JP", "Japanese (Japan)"} }, - {0x0412, {"ko-KR", "Korean (Korea)"} }, - {0x0415, {"pl-PL", "Polish (Poland)"} }, - {0x0416, {"pt-BR", "Portuguese (Brazil)"} }, - {0x0816, {"pt-PT", "Portuguese (Portugal)"} }, - {0x0419, {"ru-RU", "Russian (Russia)"} }, - {0x0424, {"sl-SI", "Slovenian (Slovenia)"} }, - {0x041F, {"tr-TR", "Turkish (Turkey)"} }, - {0x0422, {"uk-UA", "Ukrainian (Ukraine)"} }, - {0x0804, {"zh-CN", "Chinese (China)"} }, - {0xFFFF, {"system", "(System Default)"} }, - }; +extern "C++" { +QMap> ProgSettings::lcid_langcode = { + { 0x0403, { "ca-ES", "Catalan (Spain)" } }, + { 0x0804, { "zh-CN", "Chinese (Simplified)" } }, + { 0x0404, { "zh-TW", "Chinese (Traditional)" } }, + { 0x041A, { "hr-HR", "Croatian (Croatia)" } }, + { 0x0405, { "cs-CZ", "Czech (Czech Republic)" } }, + { 0x0407, { "de-DE", "German (Germany)" } }, + { 0x0809, { "en-GB", "English (United Kingdom)" }}, + { 0x0409, { "en-US", "English (United States)" } }, + { 0x040B, { "fi-FI", "Finnish (Finland)" } }, + { 0x040C, { "fr-FR", "French (France)" } }, + { 0x040E, { "hu-HU", "Hungarian (Hungary)" } }, + { 0x0410, { "it-IT", "Italian (Italy)" } }, + { 0x0411, { "ja-JP", "Japanese (Japan)" } }, + { 0x0412, { "ko-KR", "Korean (Korea)" } }, + { 0x0415, { "pl-PL", "Polish (Poland)" } }, + { 0x0416, { "pt-BR", "Portuguese (Brazil)" } }, + { 0x0816, { "pt-PT", "Portuguese (Portugal)" } }, + { 0x0419, { "ru-RU", "Russian (Russia)" } }, + { 0x041B, { "sk-SK", "Slovak (Slovakia)" } }, + { 0x0424, { "sl-SI", "Slovenian (Slovenia)" } }, + { 0x0C0A, { "es-ES", "Spanish (Spain, Modern Sort)" } }, + { 0x041F, { "tr-TR", "Turkish (Turkey)" } }, + { 0x0422, { "uk-UA", "Ukrainian (Ukraine)" } }, + { 0xFFFF, { "system", "(System Default)" } }, +}; } /* Sets up the program language before initialization. */ -uint32_t plat_language_code(char* langcode) { - for (auto& curKey : ProgSettings::lcid_langcode.keys()) - { - if (ProgSettings::lcid_langcode[curKey].first == langcode) - { +uint32_t +plat_language_code(char *langcode) +{ + for (auto &curKey : ProgSettings::lcid_langcode.keys()) { + if (ProgSettings::lcid_langcode[curKey].first == langcode) { return curKey; } } @@ -394,9 +472,10 @@ uint32_t plat_language_code(char* langcode) { } /* Converts back the language code to LCID */ -void plat_language_code_r(uint32_t lcid, char* outbuf, int len) { - if (!ProgSettings::lcid_langcode.contains(lcid)) - { +void +plat_language_code_r(uint32_t lcid, char *outbuf, int len) +{ + if (!ProgSettings::lcid_langcode.contains(lcid)) { qstrncpy(outbuf, "system", len); return; } @@ -404,25 +483,26 @@ void plat_language_code_r(uint32_t lcid, char* outbuf, int len) { return; } -void* dynld_module(const char *name, dllimp_t *table) +#ifndef Q_OS_WINDOWS +void * +dynld_module(const char *name, dllimp_t *table) { - QString libraryName = name; - QFileInfo fi(libraryName); - QStringList removeSuffixes = {"dll", "dylib", "so"}; + QString libraryName = name; + QFileInfo fi(libraryName); + QStringList removeSuffixes = { "dll", "dylib", "so" }; if (removeSuffixes.contains(fi.suffix())) { libraryName = fi.completeBaseName(); } auto lib = std::unique_ptr(new QLibrary(libraryName)); if (lib->load()) { - for (auto imp = table; imp->name != nullptr; imp++) - { + for (auto imp = table; imp->name != nullptr; imp++) { auto ptr = lib->resolve(imp->name); if (ptr == nullptr) { return nullptr; } - auto imp_ptr = reinterpret_cast(imp->func); - *imp_ptr = reinterpret_cast(ptr); + auto imp_ptr = reinterpret_cast(imp->func); + *imp_ptr = reinterpret_cast(ptr); } } else { return nullptr; @@ -431,12 +511,15 @@ void* dynld_module(const char *name, dllimp_t *table) return lib.release(); } -void dynld_close(void *handle) +void +dynld_close(void *handle) { - delete reinterpret_cast(handle); + delete reinterpret_cast(handle); } +#endif -void startblit() +void +startblit() { blitmx_contention++; if (blitmx.try_lock()) { @@ -446,7 +529,8 @@ void startblit() blitmx.lock(); } -void endblit() +void +endblit() { blitmx_contention--; blitmx.unlock(); @@ -457,33 +541,38 @@ void endblit() std::this_thread::sleep_for(std::chrono::milliseconds(1)); } } - } #ifdef Q_OS_WINDOWS -size_t mbstoc16s(uint16_t dst[], const char src[], int len) +size_t +mbstoc16s(uint16_t dst[], const char src[], int len) { - if (src == NULL) return 0; - if (len < 0) return 0; + if (src == NULL) + return 0; + if (len < 0) + return 0; size_t ret = MultiByteToWideChar(CP_UTF8, 0, src, -1, reinterpret_cast(dst), dst == NULL ? 0 : len); if (!ret) { - return -1; + return -1; } return ret; } -size_t c16stombs(char dst[], const uint16_t src[], int len) +size_t +c16stombs(char dst[], const uint16_t src[], int len) { - if (src == NULL) return 0; - if (len < 0) return 0; + if (src == NULL) + return 0; + if (len < 0) + return 0; size_t ret = WideCharToMultiByte(CP_UTF8, 0, reinterpret_cast(src), -1, dst, dst == NULL ? 0 : len, NULL, NULL); if (!ret) { - return -1; + return -1; } return ret; @@ -491,71 +580,53 @@ size_t c16stombs(char dst[], const uint16_t src[], int len) #endif #ifdef _WIN32 -#define LIB_NAME_FLUIDSYNTH "libfluidsynth.dll" -#define LIB_NAME_GS "gsdll32.dll" -#define LIB_NAME_FREETYPE "freetype.dll" -#define MOUSE_CAPTURE_KEYSEQ "F8+F12" +# define LIB_NAME_GS "gsdll32.dll" +# define MOUSE_CAPTURE_KEYSEQ "F8+F12" #else -#define LIB_NAME_FLUIDSYNTH "libfluidsynth" -#define LIB_NAME_GS "libgs" -#define LIB_NAME_FREETYPE "libfreetype" -#define MOUSE_CAPTURE_KEYSEQ "CTRL-END" +# define LIB_NAME_GS "libgs" +# define MOUSE_CAPTURE_KEYSEQ "CTRL-END" #endif -#ifdef Q_OS_MACOS -#define ROMDIR "~/Library/Application Support/net.86box.86box/roms" -#else -#define ROMDIR "roms" -#endif - QMap ProgSettings::translatedstrings; -void ProgSettings::reloadStrings() +void +ProgSettings::reloadStrings() { translatedstrings.clear(); translatedstrings[IDS_2077] = QCoreApplication::translate("", "Click to capture mouse").toStdWString(); translatedstrings[IDS_2078] = QCoreApplication::translate("", "Press F8+F12 to release mouse").replace("F8+F12", MOUSE_CAPTURE_KEYSEQ).replace("CTRL-END", QLocale::system().name() == "de_DE" ? "Strg+Ende" : "CTRL-END").toStdWString(); translatedstrings[IDS_2079] = QCoreApplication::translate("", "Press F8+F12 or middle button to release mouse").replace("F8+F12", MOUSE_CAPTURE_KEYSEQ).replace("CTRL-END", QLocale::system().name() == "de_DE" ? "Strg+Ende" : "CTRL-END").toStdWString(); - translatedstrings[IDS_2080] = QCoreApplication::translate("", "Failed to initialize FluidSynth").toStdWString(); + translatedstrings[IDS_2131] = QCoreApplication::translate("", "Invalid configuration").toStdWString(); translatedstrings[IDS_4099] = QCoreApplication::translate("", "MFM/RLL or ESDI CD-ROM drives never existed").toStdWString(); - translatedstrings[IDS_2093] = QCoreApplication::translate("", "Failed to set up PCap").toStdWString(); - translatedstrings[IDS_2094] = QCoreApplication::translate("", "No PCap devices found").toStdWString(); - translatedstrings[IDS_2110] = QCoreApplication::translate("", "Unable to initialize FreeType").toStdWString(); - translatedstrings[IDS_2111] = QCoreApplication::translate("", "Unable to initialize SDL, libsdl2 is required").toStdWString(); - translatedstrings[IDS_2129] = QCoreApplication::translate("", "Make sure libpcap is installed and that you are on a libpcap-compatible network connection.").toStdWString(); - translatedstrings[IDS_2114] = QCoreApplication::translate("", "Unable to initialize Ghostscript").toStdWString(); + translatedstrings[IDS_2094] = QCoreApplication::translate("", "Failed to set up PCap").toStdWString(); + translatedstrings[IDS_2095] = QCoreApplication::translate("", "No PCap devices found").toStdWString(); + translatedstrings[IDS_2096] = QCoreApplication::translate("", "Invalid PCap device").toStdWString(); + translatedstrings[IDS_2112] = QCoreApplication::translate("", "Unable to initialize SDL, libsdl2 is required").toStdWString(); + translatedstrings[IDS_2130] = QCoreApplication::translate("", "Make sure libpcap is installed and that you are on a libpcap-compatible network connection.").toStdWString(); + translatedstrings[IDS_2115] = QCoreApplication::translate("", "Unable to initialize Ghostscript").toStdWString(); translatedstrings[IDS_2063] = QCoreApplication::translate("", "Machine \"%hs\" is not available due to missing ROMs in the roms/machines directory. Switching to an available machine.").toStdWString(); translatedstrings[IDS_2064] = QCoreApplication::translate("", "Video card \"%hs\" is not available due to missing ROMs in the roms/video directory. Switching to an available video card.").toStdWString(); - translatedstrings[IDS_2128] = QCoreApplication::translate("", "Hardware not available").toStdWString(); - translatedstrings[IDS_2120] = QCoreApplication::translate("", "No ROMs found").toStdWString(); - translatedstrings[IDS_2056] = QCoreApplication::translate("", "86Box could not find any usable ROM images.\n\nPlease download a ROM set and extract it into the \"roms\" directory.").replace("roms", ROMDIR).toStdWString(); + translatedstrings[IDS_2163] = QCoreApplication::translate("", "Video card #2 \"%hs\" is not available due to missing ROMs in the roms/video directory. Disabling the second video card.").toStdWString(); + translatedstrings[IDS_2129] = QCoreApplication::translate("", "Hardware not available").toStdWString(); + translatedstrings[IDS_2143] = QCoreApplication::translate("", "Monitor in sleep mode").toStdWString(); + translatedstrings[IDS_2121] = QCoreApplication::translate("", "No ROMs found").toStdWString(); + translatedstrings[IDS_2056] = QCoreApplication::translate("", "86Box could not find any usable ROM images.\n\nPlease download a ROM set and extract it into the \"roms\" directory.").toStdWString(); + translatedstrings[IDS_2167] = QCoreApplication::translate("", "Failed to initialize network driver").toStdWString(); + translatedstrings[IDS_2168] = QCoreApplication::translate("", "The network configuration will be switched to the null driver").toStdWString(); - auto flsynthstr = QCoreApplication::translate("", " is required for FluidSynth MIDI output."); - if (flsynthstr.contains("libfluidsynth")) - { - flsynthstr.replace("libfluidsynth", LIB_NAME_FLUIDSYNTH); - } - else flsynthstr.prepend(LIB_NAME_FLUIDSYNTH); - translatedstrings[IDS_2133] = flsynthstr.toStdWString(); - auto gssynthstr = QCoreApplication::translate("", " is required for automatic conversion of PostScript files to PDF.\n\nAny documents sent to the generic PostScript printer will be saved as PostScript (.ps) files."); - if (gssynthstr.contains("libgs")) - { - gssynthstr.replace("libgs", LIB_NAME_GS); - } - else gssynthstr.prepend(LIB_NAME_GS); - translatedstrings[IDS_2132] = flsynthstr.toStdWString(); - auto ftsynthstr = QCoreApplication::translate("", " is required for ESC/P printer emulation."); - if (ftsynthstr.contains("libfreetype")) - { - ftsynthstr.replace("libfreetype", LIB_NAME_FREETYPE); - } - else ftsynthstr.prepend(LIB_NAME_FREETYPE); - translatedstrings[IDS_2131] = ftsynthstr.toStdWString(); + auto gsstr = QCoreApplication::translate("", " is required for automatic conversion of PostScript files to PDF.\n\nAny documents sent to the generic PostScript printer will be saved as PostScript (.ps) files."); + if (gsstr.contains("libgs")) { + gsstr.replace("libgs", LIB_NAME_GS); + } else + gsstr.prepend(LIB_NAME_GS); + translatedstrings[IDS_2133] = gsstr.toStdWString(); } -wchar_t* plat_get_string(int i) +wchar_t * +plat_get_string(int i) { - if (ProgSettings::translatedstrings.empty()) ProgSettings::reloadStrings(); + if (ProgSettings::translatedstrings.empty()) + ProgSettings::reloadStrings(); return ProgSettings::translatedstrings[i].data(); } @@ -564,3 +635,110 @@ plat_chdir(char *path) { return QDir::setCurrent(QString(path)) ? 0 : -1; } + +void +plat_get_global_config_dir(char* strptr) +{ +#ifdef __APPLE__ + auto dir = QDir(QStandardPaths::standardLocations(QStandardPaths::GenericConfigLocation)[0] + "/net.86Box.86Box/"); +#else + auto dir = QDir(QStandardPaths::standardLocations(QStandardPaths::GenericConfigLocation)[0] + "/86Box/"); +#endif + if (!dir.exists()) dir.mkpath("."); + strncpy(strptr, dir.canonicalPath().toUtf8().constData(), 1024); +} + +void +plat_init_rom_paths(void) +{ + auto paths = QStandardPaths::standardLocations(QStandardPaths::GenericDataLocation); + +#ifdef _WIN32 + // HACK: The standard locations returned for GenericDataLocation include + // the EXE path and a `data` directory within it as the last two entries. + + // Remove the entries as we don't need them. + paths.removeLast(); + paths.removeLast(); +#endif + + for (auto &path : paths) { +#ifdef __APPLE__ + rom_add_path(QDir(path).filePath("net.86Box.86Box/roms").toUtf8().constData()); +#else + rom_add_path(QDir(path).filePath("86Box/roms").toUtf8().constData()); +#endif + } +} + +void +plat_get_cpu_string(char *outbuf, uint8_t len) { + auto cpu_string = QString("Unknown"); + /* Write the default string now in case we have to exit early from an error */ + qstrncpy(outbuf, cpu_string.toUtf8().constData(), len); + +#if defined(Q_OS_MACOS) + auto *process = new QProcess(nullptr); + QStringList arguments; + QString program = "/usr/sbin/sysctl"; + arguments << "machdep.cpu.brand_string"; + process->start(program, arguments); + if (!process->waitForStarted()) { + return; + } + if (!process->waitForFinished()) { + return; + } + QByteArray result = process->readAll(); + auto command_result = QString(result).split(": ").last(); + if(!command_result.isEmpty()) { + cpu_string = command_result; + } +#elif defined(Q_OS_WINDOWS) + const LPCSTR keyName = "HARDWARE\\DESCRIPTION\\System\\CentralProcessor\\0"; + const LPCSTR valueName = "ProcessorNameString"; + unsigned char buf[32768]; + DWORD bufSize; + HKEY hKey; + bufSize = 32768; + if (RegOpenKeyExA(HKEY_LOCAL_MACHINE, keyName, 0, 1, &hKey) == ERROR_SUCCESS) { + if (RegQueryValueExA(hKey, valueName, NULL, NULL, buf, &bufSize) == ERROR_SUCCESS) { + cpu_string = reinterpret_cast(buf); + } + RegCloseKey(hKey); + } +#elif defined(Q_OS_LINUX) + auto cpuinfo = QString("/proc/cpuinfo"); + auto cpuinfo_fi = QFileInfo(cpuinfo); + if(!cpuinfo_fi.isReadable()) { + return; + } + QFile file(cpuinfo); + if (file.open(QIODevice::ReadOnly | QIODevice::Text)) { + QTextStream textStream(&file); + while(true) { + QString line = textStream.readLine(); + if (line.isNull()) { + break; + } + if(QRegularExpression("model name.*:").match(line).hasMatch()) { + auto list = line.split(": "); + if(!list.last().isEmpty()) { + cpu_string = list.last(); + break; + } + } + + } + } +#endif + + qstrncpy(outbuf, cpu_string.toUtf8().constData(), len); + +} + +double +plat_get_dpi(void) +{ + return util::screenOfWidget(main_window)->devicePixelRatio(); +} diff --git a/src/qt/qt_progsettings.cpp b/src/qt/qt_progsettings.cpp index 08e972801..4dda901d7 100644 --- a/src/qt/qt_progsettings.cpp +++ b/src/qt/qt_progsettings.cpp @@ -1,18 +1,18 @@ /* - * 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. + * 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. + * This file is part of the 86Box distribution. * - * Program settings UI module. + * Program settings UI module. * * * * Authors: Cacodemon345 * - * Copyright 2021-2022 Cacodemon345 + * Copyright 2021-2022 Cacodemon345 */ #include @@ -27,111 +27,117 @@ #include #include -extern "C" -{ +extern "C" { #include <86box/86box.h> #include <86box/version.h> #include <86box/config.h> #include <86box/plat.h> +#include <86box/mem.h> +#include <86box/rom.h> } - static QMap iconset_to_qt; -extern MainWindow* main_window; +extern MainWindow *main_window; -ProgSettings::CustomTranslator* ProgSettings::translator = nullptr; -QTranslator* ProgSettings::qtTranslator = nullptr; -QString ProgSettings::getIconSetPath() +ProgSettings::CustomTranslator *ProgSettings::translator = nullptr; +QTranslator *ProgSettings::qtTranslator = nullptr; +QString +ProgSettings::getIconSetPath() { - QString roms_root; - if (rom_path[0]) - roms_root = rom_path; - else { - roms_root = QString("%1/roms").arg(exe_path); - } - - if (iconset_to_qt.isEmpty()) - { + if (iconset_to_qt.isEmpty()) { + // Always include default bundled icons iconset_to_qt.insert("", ":/settings/win/icons"); - QDir dir(roms_root + "/icons/"); - if (dir.isReadable()) - { - auto dirList = dir.entryList(QDir::AllDirs | QDir::Executable | QDir::Readable); - for (auto &curIconSet : dirList) - { - if (curIconSet == "." || curIconSet == "..") continue; - iconset_to_qt.insert(curIconSet, (dir.canonicalPath() + '/') + curIconSet); + // Walk rom_paths to get the candidates + for (rom_path_t *emu_rom_path = &rom_paths; emu_rom_path != nullptr; emu_rom_path = emu_rom_path->next) { + // Check for icons subdir in each candidate + QDir roms_icons_dir(QString(emu_rom_path->path) + "/icons"); + if (roms_icons_dir.isReadable()) { + auto dirList = roms_icons_dir.entryList(QDir::AllDirs | QDir::Executable | QDir::Readable); + for (auto &curIconSet : dirList) { + if (curIconSet == "." || curIconSet == "..") { + continue; + } + iconset_to_qt.insert(curIconSet, (roms_icons_dir.canonicalPath() + '/') + curIconSet); + } } } } return iconset_to_qt[icon_set]; } -QIcon ProgSettings::loadIcon(QString file) +QIcon +ProgSettings::loadIcon(QString file) { - (void)getIconSetPath(); - if (!QFile::exists(iconset_to_qt[icon_set] + file)) return QIcon(iconset_to_qt[""] + file); + (void) getIconSetPath(); + if (!QFile::exists(iconset_to_qt[icon_set] + file)) + return QIcon(iconset_to_qt[""] + file); return QIcon(iconset_to_qt[icon_set] + file); } -ProgSettings::ProgSettings(QWidget *parent) : - QDialog(parent), - ui(new Ui::ProgSettings) +ProgSettings::ProgSettings(QWidget *parent) + : QDialog(parent) + , ui(new Ui::ProgSettings) { ui->setupUi(this); - (void)getIconSetPath(); + (void) getIconSetPath(); ui->comboBox->setItemData(0, ""); ui->comboBox->setCurrentIndex(0); - for (auto i = iconset_to_qt.begin(); i != iconset_to_qt.end(); i++) - { - if (i.key() == "") continue; + for (auto i = iconset_to_qt.begin(); i != iconset_to_qt.end(); i++) { + if (i.key() == "") + continue; QFile iconfile(i.value() + "/iconinfo.txt"); iconfile.open(QFile::ReadOnly); QString friendlyName; QString iconsetinfo(iconfile.readAll()); iconfile.close(); - if (iconsetinfo.isEmpty()) friendlyName = i.key(); - else friendlyName = iconsetinfo.split('\n')[0]; + if (iconsetinfo.isEmpty()) + friendlyName = i.key(); + else + friendlyName = iconsetinfo.split('\n')[0]; ui->comboBox->addItem(friendlyName, i.key()); - if (strcmp(icon_set, i.key().toUtf8().data()) == 0) - { + if (strcmp(icon_set, i.key().toUtf8().data()) == 0) { ui->comboBox->setCurrentIndex(ui->comboBox->findData(i.key())); } } ui->comboBox->setItemData(0, '(' + tr("Default") + ')', Qt::DisplayRole); ui->comboBoxLanguage->setItemData(0, 0xFFFF); - for (auto i = lcid_langcode.begin(); i != lcid_langcode.end(); i++) - { - if (i.key() == 0xFFFF) continue; + for (auto i = lcid_langcode.begin(); i != lcid_langcode.end(); i++) { + if (i.key() == 0xFFFF) + continue; ui->comboBoxLanguage->addItem(lcid_langcode[i.key()].second, i.key()); - if (i.key() == lang_id) - { + if (i.key() == lang_id) { ui->comboBoxLanguage->setCurrentIndex(ui->comboBoxLanguage->findData(i.key())); } } + + mouseSensitivity = mouse_sensitivity; + ui->horizontalSlider->setValue(mouseSensitivity * 100.); + ui->openDirUsrPath->setChecked(open_dir_usr_path > 0); } -void ProgSettings::accept() +void +ProgSettings::accept() { strcpy(icon_set, ui->comboBox->currentData().toString().toUtf8().data()); - lang_id = ui->comboBoxLanguage->currentData().toUInt(); + lang_id = ui->comboBoxLanguage->currentData().toUInt(); + open_dir_usr_path = ui->openDirUsrPath->isChecked() ? 1 : 0; loadTranslators(QCoreApplication::instance()); reloadStrings(); update_mouse_msg(); main_window->ui->retranslateUi(main_window); QString vmname(vm_name); - if (vmname.at(vmname.size() - 1) == '"' || vmname.at(vmname.size() - 1) == '\'') vmname.truncate(vmname.size() - 1); + if (vmname.at(vmname.size() - 1) == '"' || vmname.at(vmname.size() - 1) == '\'') + vmname.truncate(vmname.size() - 1); main_window->setWindowTitle(QString("%1 - %2 %3").arg(vmname, EMU_NAME, EMU_VERSION_FULL)); QString msg = main_window->status->getMessage(); main_window->status.reset(new MachineStatus(main_window)); main_window->refreshMediaMenu(); main_window->status->message(msg); connect(main_window, &MainWindow::updateStatusBarTip, main_window->status.get(), &MachineStatus::updateTip); - connect(main_window, &MainWindow::updateStatusBarActivity, main_window->status.get(), &MachineStatus::setActivity); - connect(main_window, &MainWindow::updateStatusBarEmpty, main_window->status.get(), &MachineStatus::setEmpty); - connect(main_window, &MainWindow::statusBarMessage, main_window->status.get(), &MachineStatus::message); + connect(main_window, &MainWindow::statusBarMessage, main_window->status.get(), &MachineStatus::message, Qt::QueuedConnection); + mouse_sensitivity = mouseSensitivity; QDialog::accept(); } @@ -140,47 +146,42 @@ ProgSettings::~ProgSettings() delete ui; } -void ProgSettings::on_pushButton_released() +void +ProgSettings::on_pushButton_released() { ui->comboBox->setCurrentIndex(0); } -void ProgSettings::loadTranslators(QObject *parent) +void +ProgSettings::loadTranslators(QObject *parent) { - if (qtTranslator) - { + if (qtTranslator) { QApplication::removeTranslator(qtTranslator); qtTranslator = nullptr; } - if (translator) - { + if (translator) { QApplication::removeTranslator(translator); translator = nullptr; } - qtTranslator = new QTranslator(parent); - translator = new CustomTranslator(parent); + qtTranslator = new QTranslator(parent); + translator = new CustomTranslator(parent); QString localetofilename = ""; - if (lang_id == 0xFFFF || lcid_langcode.contains(lang_id) == false) - { - for (int i = 0; i < QLocale::system().uiLanguages().size(); i++) - { + if (lang_id == 0xFFFF || lcid_langcode.contains(lang_id) == false) { + for (int i = 0; i < QLocale::system().uiLanguages().size(); i++) { localetofilename = QLocale::system().uiLanguages()[i]; - if (translator->load(QLatin1String("86box_") + localetofilename, QLatin1String(":/"))) - { + if (translator->load(QLatin1String("86box_") + localetofilename, QLatin1String(":/"))) { qDebug() << "Translations loaded.\n"; QCoreApplication::installTranslator(translator); if (!qtTranslator->load(QLatin1String("qtbase_") + localetofilename.replace('-', '_'), QLibraryInfo::location(QLibraryInfo::TranslationsPath))) qtTranslator->load(QLatin1String("qt_") + localetofilename.replace('-', '_'), QApplication::applicationDirPath() + "/./translations/"); - if (QApplication::installTranslator(qtTranslator)) - { - qDebug() << "Qt translations loaded." << "\n"; + if (QApplication::installTranslator(qtTranslator)) { + qDebug() << "Qt translations loaded." + << "\n"; } break; } } - } - else - { + } else { translator->load(QLatin1String("86box_") + lcid_langcode[lang_id].first, QLatin1String(":/")); QCoreApplication::installTranslator(translator); if (!qtTranslator->load(QLatin1String("qtbase_") + QString(lcid_langcode[lang_id].first).replace('-', '_'), QLibraryInfo::location(QLibraryInfo::TranslationsPath))) @@ -189,8 +190,21 @@ void ProgSettings::loadTranslators(QObject *parent) } } -void ProgSettings::on_pushButtonLanguage_released() +void +ProgSettings::on_pushButtonLanguage_released() { ui->comboBoxLanguage->setCurrentIndex(0); } +void +ProgSettings::on_horizontalSlider_valueChanged(int value) +{ + mouseSensitivity = (double) value / 100.; +} + +void +ProgSettings::on_pushButton_2_clicked() +{ + mouseSensitivity = 1.0; + ui->horizontalSlider->setValue(100); +} diff --git a/src/qt/qt_progsettings.hpp b/src/qt/qt_progsettings.hpp index 75fba149a..7565869b0 100644 --- a/src/qt/qt_progsettings.hpp +++ b/src/qt/qt_progsettings.hpp @@ -8,32 +8,36 @@ namespace Ui { class ProgSettings; } -class ProgSettings : public QDialog -{ +class ProgSettings : public QDialog { Q_OBJECT public: explicit ProgSettings(QWidget *parent = nullptr); ~ProgSettings(); static QString getIconSetPath(); - static QIcon loadIcon(QString file); - static void loadTranslators(QObject* parent = nullptr); - static void reloadStrings(); - class CustomTranslator : public QTranslator - { + static QIcon loadIcon(QString file); + static void loadTranslators(QObject *parent = nullptr); + static void reloadStrings(); + class CustomTranslator : public QTranslator { public: - CustomTranslator(QObject* parent = nullptr) : QTranslator(parent) {}; + CustomTranslator(QObject *parent = nullptr) + : QTranslator(parent) {}; + protected: QString translate(const char *context, const char *sourceText, - const char *disambiguation = nullptr, int n = -1) const override + const char *disambiguation = nullptr, int n = -1) const override { - if (strcmp(sourceText, "&Fullscreen") == 0) sourceText = "&Fullscreen\tCtrl+Alt+PgUp"; - if (strcmp(sourceText, "&Ctrl+Alt+Del") == 0) sourceText = "&Ctrl+Alt+Del\tCtrl+F12"; - if (strcmp(sourceText, "Take s&creenshot") == 0) sourceText = "Take s&creenshot\tCtrl+F11"; - if (strcmp(sourceText, "Begin trace") == 0) sourceText = "Begin trace\tCtrl+T"; - if (strcmp(sourceText, "End trace") == 0) sourceText = "End trace\tCtrl+T"; - if (strcmp(sourceText, "&Qt (Software)") == 0) - { + if (strcmp(sourceText, "&Fullscreen") == 0) + sourceText = "&Fullscreen\tCtrl+Alt+PgUp"; + if (strcmp(sourceText, "&Ctrl+Alt+Del") == 0) + sourceText = "&Ctrl+Alt+Del\tCtrl+F12"; + if (strcmp(sourceText, "Take s&creenshot") == 0) + sourceText = "Take s&creenshot\tCtrl+F11"; + if (strcmp(sourceText, "Begin trace") == 0) + sourceText = "Begin trace\tCtrl+T"; + if (strcmp(sourceText, "End trace") == 0) + sourceText = "End trace\tCtrl+T"; + if (strcmp(sourceText, "&Qt (Software)") == 0) { QString finalstr = QTranslator::translate("", "&SDL (Software)", disambiguation, n); finalstr.replace("SDL", "Qt"); finalstr.replace("(&S)", "(&Q)"); @@ -41,15 +45,16 @@ public: } QString finalstr = QTranslator::translate("", sourceText, disambiguation, n); #ifdef Q_OS_MACOS - if (finalstr.contains('\t')) finalstr.truncate(finalstr.indexOf('\t')); + if (finalstr.contains('\t')) + finalstr.truncate(finalstr.indexOf('\t')); #endif return finalstr; } }; - static CustomTranslator* translator; - static QTranslator* qtTranslator; + static CustomTranslator *translator; + static QTranslator *qtTranslator; static QMap> lcid_langcode; - static QMap translatedstrings; + static QMap translatedstrings; protected slots: void accept() override; @@ -57,10 +62,15 @@ private slots: void on_pushButton_released(); void on_pushButtonLanguage_released(); + void on_horizontalSlider_valueChanged(int value); + + void on_pushButton_2_clicked(); + private: Ui::ProgSettings *ui; friend class MainWindow; + double mouseSensitivity; }; #endif // QT_PROGSETTINGS_HPP diff --git a/src/qt/qt_progsettings.ui b/src/qt/qt_progsettings.ui index b64272f8b..16fb439be 100644 --- a/src/qt/qt_progsettings.ui +++ b/src/qt/qt_progsettings.ui @@ -6,48 +6,58 @@ 0 0 - 370 - 228 + 458 + 374 - 370 - 228 + 0 + 0 - 370 - 228 + 16777215 + 16777215 Preferences - - - - Qt::Vertical + + QLayout::SetFixedSize + + + + + false - - - 20 - 40 - + + 30 - - - - - (System Default) + (Default) + + + + Mouse sensitivity: + + + + + + + Icon set: + + + @@ -55,6 +65,63 @@ + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + Qt::Horizontal + + + QDialogButtonBox::Cancel|QDialogButtonBox::Ok + + + + + + + 10 + + + 200 + + + 10 + + + 20 + + + 100 + + + Qt::Horizontal + + + + + + + 30 + + + + (System Default) + + + + @@ -62,25 +129,17 @@ - - - - false + + + + Default - - - (Default) - - - - - - Qt::Horizontal - - - QDialogButtonBox::Cancel|QDialogButtonBox::Ok + + + + Default @@ -97,20 +156,6 @@ - - - - Icon set: - - - - - - - Default - - - @@ -124,6 +169,16 @@ + + + + <html><head/><body><p>When selecting media images (CD-ROM, floppy, etc.) the open dialog will start in the same directory as the 86Box configuration file. This setting will likely only make a difference on macOS.</p></body></html> + + + Select media images from program working directory + + + diff --git a/src/qt/qt_renderercommon.cpp b/src/qt/qt_renderercommon.cpp index c76067add..db0612312 100644 --- a/src/qt/qt_renderercommon.cpp +++ b/src/qt/qt_renderercommon.cpp @@ -1,18 +1,18 @@ /* - * 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. + * 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. + * This file is part of the 86Box distribution. * - * Program settings UI module. + * Program settings UI module. * * * * Authors: Joakim L. Gilje * - * Copyright 2021 Joakim L. Gilje + * Copyright 2021 Joakim L. Gilje */ #include "qt_renderercommon.hpp" @@ -39,73 +39,102 @@ int status_icons_fullscreen = 0; RendererCommon::RendererCommon() = default; -extern MainWindow* main_window; +extern MainWindow *main_window; -static void integer_scale(double *d, double *g) { +static void +integer_scale(double *d, double *g) +{ double ratio; if (*d > *g) { ratio = std::floor(*d / *g); - *d = *g * ratio; + *d = *g * ratio; } else { ratio = std::ceil(*d / *g); - *d = *g / ratio; + *d = *g / ratio; } } -void RendererCommon::onResize(int width, int height) { - if (video_fullscreen == 0) { +void +RendererCommon::onResize(int width, int height) +{ + /* This is needed so that the if below does not take like, 5 lines. */ + bool is_fs = (video_fullscreen == 0); + bool parent_max = (parentWidget->isMaximized() == false); + bool main_is_ancestor = main_window->isAncestorOf(parentWidget); + bool main_max = main_window->isMaximized(); + bool main_is_max = (main_is_ancestor && main_max == false); + + if (is_fs && (video_fullscreen_scale_maximized ? (parent_max && main_is_max) : 1)) destination.setRect(0, 0, width, height); - return; + else { + double dx; + double dy; + double dw; + double dh; + double gsr; + + double hw = width; + double hh = height; + double gw = source.width(); + double gh = source.height(); + double hsr = hw / hh; + double r43 = 4.0 / 3.0; + + switch (video_fullscreen_scale) { + case FULLSCR_SCALE_INT: + case FULLSCR_SCALE_INT43: + gsr = gw / gh; + + if (video_fullscreen_scale == FULLSCR_SCALE_INT43) { + gh = gw / r43; + gw = gw; + + gsr = r43; + } + + if (gsr <= hsr) { + dw = hh * gsr; + dh = hh; + } else { + dw = hw; + dh = hw / gsr; + } + + integer_scale(&dw, &gw); + integer_scale(&dh, &gh); + + dx = (hw - dw) / 2.0; + dy = (hh - dh) / 2.0; + destination.setRect((int) dx, (int) dy, (int) dw, (int) dh); + break; + case FULLSCR_SCALE_43: + case FULLSCR_SCALE_KEEPRATIO: + if (video_fullscreen_scale == FULLSCR_SCALE_43) + gsr = r43; + else + gsr = gw / gh; + + if (gsr <= hsr) { + dw = hh * gsr; + dh = hh; + } else { + dw = hw; + dh = hw / gsr; + } + dx = (hw - dw) / 2.0; + dy = (hh - dh) / 2.0; + destination.setRect((int) dx, (int) dy, (int) dw, (int) dh); + break; + case FULLSCR_SCALE_FULL: + default: + destination.setRect(0, 0, (int) hw, (int) hh); + break; + } } - double dx, dy, dw, dh, gsr; - double hw = width; - double hh = height; - double gw = source.width(); - double gh = source.height(); - double hsr = hw / hh; - - switch (video_fullscreen_scale) { - case FULLSCR_SCALE_INT: - gsr = gw / gh; - if (gsr <= hsr) { - dw = hh * gsr; - dh = hh; - } else { - dw = hw; - dh = hw / gsr; - } - integer_scale(&dw, &gw); - integer_scale(&dh, &gh); - dx = (hw - dw) / 2.0; - dy = (hh - dh) / 2.0; - destination.setRect(dx, dy, dw, dh); - break; - case FULLSCR_SCALE_43: - case FULLSCR_SCALE_KEEPRATIO: - if (video_fullscreen_scale == FULLSCR_SCALE_43) { - gsr = 4.0 / 3.0; - } else { - gsr = gw / gh; - } - - if (gsr <= hsr) { - dw = hh * gsr; - dh = hh; - } else { - dw = hw; - dh = hw / gsr; - } - dx = (hw - dw) / 2.0; - dy = (hh - dh) / 2.0; - destination.setRect(dx, dy, dw, dh); - break; - case FULLSCR_SCALE_FULL: - default: - destination.setRect(0, 0, hw, hh); - break; - } + monitors[r_monitor_index].mon_res_x = (double) destination.width(); + monitors[r_monitor_index].mon_res_y = (double) destination.height(); } void RendererCommon::drawStatusBarIcons(QPainter* painter) @@ -113,47 +142,49 @@ void RendererCommon::drawStatusBarIcons(QPainter* painter) uint32_t x = 0; auto prevcompositionMode = painter->compositionMode(); painter->setCompositionMode(QPainter::CompositionMode::CompositionMode_SourceOver); - for (int i = 0; i < main_window->statusBar()->children().count(); i++) - { + for (int i = 0; i < main_window->statusBar()->children().count(); i++) { QLabel* label = qobject_cast(main_window->statusBar()->children()[i]); - if (label) - { + if (label) { #if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0) const QPixmap pixmap = label->pixmap(); #else const QPixmap pixmap = label->pixmap() ? *label->pixmap() : QPixmap(); #endif - if (!pixmap.isNull()) - { + if (!pixmap.isNull()) { painter->setBrush(QColor::fromRgbF(0, 0, 0, 1.)); - painter->fillRect(x, painter->device()->height() - pixmap.height() - 5, pixmap.width(), pixmap.height() + 5, QColor::fromRgbF(0, 0, 0, .5)); - painter->drawPixmap(x + main_window->statusBar()->layout()->spacing() / 2, painter->device()->height() - pixmap.height() - 3, pixmap); + painter->fillRect(x, painter->device()->height() - pixmap.height() - 5, + pixmap.width(), pixmap.height() + 5, QColor::fromRgbF(0, 0, 0, .5)); + painter->drawPixmap(x + main_window->statusBar()->layout()->spacing() / 2, + painter->device()->height() - pixmap.height() - 3, pixmap); x += pixmap.width(); - if (i <= main_window->statusBar()->children().count() - 3) - { - painter->fillRect(x, painter->device()->height() - pixmap.height() - 5, main_window->statusBar()->layout()->spacing(), pixmap.height() + 5, QColor::fromRgbF(0, 0, 0, .5)); + if (i <= main_window->statusBar()->children().count() - 3) { + painter->fillRect(x, painter->device()->height() - pixmap.height() - 5, + main_window->statusBar()->layout()->spacing(), pixmap.height() + 5, + QColor::fromRgbF(0, 0, 0, .5)); x += main_window->statusBar()->layout()->spacing(); - } - else painter->fillRect(x, painter->device()->height() - pixmap.height() - 4, 4, pixmap.height() + 4, QColor::fromRgbF(0, 0, 0, .5)); + } else + painter->fillRect(x, painter->device()->height() - pixmap.height() - 4, 4, + pixmap.height() + 4, QColor::fromRgbF(0, 0, 0, .5)); } } } - if (main_window->status->getMessage().isEmpty() == false) - { + if (main_window->status->getMessage().isEmpty() == false) { auto curStatusMsg = main_window->status->getMessage(); auto textSize = painter->fontMetrics().size(Qt::TextSingleLine, QChar(' ') + curStatusMsg + QChar(' ')); painter->setPen(QColor(0, 0, 0, 127)); - painter->fillRect(painter->device()->width() - textSize.width(), painter->device()->height() - textSize.height(), textSize.width(), textSize.height(), QColor(0, 0, 0, 127)); + painter->fillRect(painter->device()->width() - textSize.width(), painter->device()->height() - textSize.height(), + textSize.width(), textSize.height(), QColor(0, 0, 0, 127)); painter->setPen(QColor(255, 255, 255, 255)); - painter->drawText(QRectF(painter->device()->width() - textSize.width(), painter->device()->height() - textSize.height(), textSize.width(), textSize.height()), Qt::TextSingleLine, QChar(' ') + curStatusMsg + QChar(' ')); + painter->drawText(QRectF(painter->device()->width() - textSize.width(), painter->device()->height() - textSize.height(), + textSize.width(), textSize.height()), Qt::TextSingleLine, QChar(' ') + curStatusMsg + QChar(' ')); } painter->setCompositionMode(prevcompositionMode); } -bool RendererCommon::eventDelegate(QEvent *event, bool& result) +bool +RendererCommon::eventDelegate(QEvent *event, bool &result) { - switch (event->type()) - { + switch (event->type()) { default: return false; case QEvent::KeyPress: @@ -169,5 +200,4 @@ bool RendererCommon::eventDelegate(QEvent *event, bool& result) result = QApplication::sendEvent(parentWidget, event); return true; } - return false; } diff --git a/src/qt/qt_renderercommon.hpp b/src/qt/qt_renderercommon.hpp index fe4d278c7..897240d27 100644 --- a/src/qt/qt_renderercommon.hpp +++ b/src/qt/qt_renderercommon.hpp @@ -1,29 +1,52 @@ #pragma once -#include -#include +#include #include +#include +#include +#include -#include -#include #include #include +#include +#include class QWidget; -class RendererCommon -{ +class RendererCommon { public: RendererCommon(); - void onResize(int width, int height); - virtual std::vector> getBuffers() = 0; -protected: - bool eventDelegate(QEvent* event, bool& result); - void drawStatusBarIcons(QPainter* painter); + void onResize(int width, int height); + virtual void finalize() { } - QRect source, destination; - QWidget* parentWidget{nullptr}; + virtual uint32_t getBytesPerRow() { return 2048 * 4; } + + virtual std::vector> getBuffers() + { + std::vector> buffers; + return buffers; + } + + /* Does renderer implement options dialog */ + virtual bool hasOptions() const { return false; } + /* Returns options dialog for renderer */ + virtual QDialog *getOptions(QWidget *parent) { return nullptr; } + /* Reloads options of renderer */ + virtual void reloadOptions() { } + + virtual bool hasBlitFunc() { return false; } + virtual void blit(int x, int y, int w, int h) { } + + int r_monitor_index = 0; + +protected: + bool eventDelegate(QEvent *event, bool &result); + void drawStatusBarIcons(QPainter* painter); + + QRect source { 0, 0, 0, 0 }; + QRect destination; + QWidget *parentWidget { nullptr }; std::vector buf_usage; }; diff --git a/src/qt/qt_rendererstack.cpp b/src/qt/qt_rendererstack.cpp index 541bb4cf6..1b1ed45c3 100644 --- a/src/qt/qt_rendererstack.cpp +++ b/src/qt/qt_rendererstack.cpp @@ -1,12 +1,12 @@ /* - * 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. + * 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. + * This file is part of the 86Box distribution. * - * Program settings UI module. + * Program settings UI module. * * * @@ -14,72 +14,119 @@ * Cacodemon345 * Teemu Korhonen * - * Copyright 2021 Joakim L. Gilje - * Copyright 2021-2021 Teemu Korhonen - * Copyright 2021-2022 Cacodemon345 + * Copyright 2021 Joakim L. Gilje + * Copyright 2021-2021 Teemu Korhonen + * Copyright 2021-2022 Cacodemon345 */ #include "qt_rendererstack.hpp" #include "ui_qt_rendererstack.h" -#include "qt_softwarerenderer.hpp" #include "qt_hardwarerenderer.hpp" +#include "qt_openglrenderer.hpp" +#include "qt_softwarerenderer.hpp" +#include "qt_vulkanwindowrenderer.hpp" +#ifdef Q_OS_WIN +# include "qt_d3d9renderer.hpp" +#endif #include "qt_mainwindow.hpp" #include "qt_util.hpp" +#include "ui_qt_mainwindow.h" + #include "evdev_mouse.hpp" +#include +#include + #include +#include #ifdef __APPLE__ -#include +# include #endif -extern "C" -{ -#include <86box/mouse.h> +extern "C" { +#include <86box/86box.h> +#include <86box/config.h> #include <86box/plat.h> #include <86box/video.h> +#include <86box/mouse.h> } -extern MainWindow* main_window; -RendererStack::RendererStack(QWidget *parent) : - QStackedWidget(parent), - ui(new Ui::RendererStack) +struct mouseinputdata { + atomic_bool mouse_tablet_in_proximity; + + char *mouse_type; +}; +static mouseinputdata mousedata; + +extern MainWindow *main_window; +RendererStack::RendererStack(QWidget *parent, int monitor_index) + : QStackedWidget(parent) + , ui(new Ui::RendererStack) { +#ifdef Q_OS_WINDOWS + int raw = 1; +#else + int raw = 0; +#endif + ui->setupUi(this); -#ifdef __unix__ -#ifdef WAYLAND - if (QApplication::platformName().contains("wayland")) { + m_monitor_index = monitor_index; +#if defined __unix__ && !defined __HAIKU__ + char auto_mouse_type[16]; + mousedata.mouse_type = getenv("EMU86BOX_MOUSE"); + if (!mousedata.mouse_type || (mousedata.mouse_type[0] == '\0') || !stricmp(mousedata.mouse_type, "auto")) { + if (QApplication::platformName().contains("wayland")) + strcpy(auto_mouse_type, "wayland"); + else if (QApplication::platformName() == "eglfs") + strcpy(auto_mouse_type, "evdev"); + else if (QApplication::platformName() == "xcb") + strcpy(auto_mouse_type, "xinput2"); + else + auto_mouse_type[0] = '\0'; + mousedata.mouse_type = auto_mouse_type; + } + +# ifdef WAYLAND + if (!stricmp(mousedata.mouse_type, "wayland")) { wl_init(); + this->mouse_capture_func = wl_mouse_capture; + this->mouse_uncapture_func = wl_mouse_uncapture; } -#endif -#ifdef EVDEV_INPUT - if (QApplication::platformName() == "eglfs") { +# endif +# ifdef EVDEV_INPUT + if (!stricmp(mousedata.mouse_type, "evdev")) { evdev_init(); + raw = 0; } -#endif - if (QApplication::platformName() == "xcb") { +# endif + if (!stricmp(mousedata.mouse_type, "xinput2")) { extern void xinput2_init(); + extern void xinput2_exit(); xinput2_init(); + this->mouse_exit_func = xinput2_exit; } #endif + + if (monitor_index == 0) + mouse_set_raw(raw); } RendererStack::~RendererStack() { + QApplication::restoreOverrideCursor(); delete ui; } -extern "C" void macos_poll_mouse(); void qt_mouse_capture(int on) { - if (!on) - { + if (!on) { mouse_capture = 0; - QApplication::setOverrideCursor(Qt::ArrowCursor); + if (QApplication::overrideCursor()) QApplication::restoreOverrideCursor(); #ifdef __APPLE__ CGAssociateMouseAndMouseCursorPosition(true); #endif @@ -93,196 +140,434 @@ qt_mouse_capture(int on) return; } -void RendererStack::mousePoll() -{ -#ifdef __APPLE__ - return macos_poll_mouse(); -#else /* !defined __APPLE__ */ - mouse_x = mousedata.deltax; - mouse_y = mousedata.deltay; - mouse_z = mousedata.deltaz; - mousedata.deltax = mousedata.deltay = mousedata.deltaz = 0; - mouse_buttons = mousedata.mousebuttons; - -#ifdef __unix__ -#ifdef WAYLAND - if (QApplication::platformName().contains("wayland")) - wl_mouse_poll(); -#endif - -#ifdef EVDEV_INPUT - if (QApplication::platformName() == "eglfs") evdev_mouse_poll(); - else -#endif - if (QApplication::platformName() == "xcb") - { - extern void xinput2_poll(); - xinput2_poll(); - } -#endif /* defined __unix__ */ -#endif /* !defined __APPLE__ */ - -} - int ignoreNextMouseEvent = 1; -void RendererStack::mouseReleaseEvent(QMouseEvent *event) +void +RendererStack::mouseReleaseEvent(QMouseEvent *event) { - if (this->geometry().contains(event->pos()) && event->button() == Qt::LeftButton && !mouse_capture && (isMouseDown & 1)) - { + if (!dopause && this->geometry().contains(event->pos()) && + (event->button() == Qt::LeftButton) && !mouse_capture && + (isMouseDown & 1) && (kbd_req_capture || (mouse_get_buttons() != 0)) && + (mouse_input_mode == 0)) { plat_mouse_capture(1); this->setCursor(Qt::BlankCursor); - if (!ignoreNextMouseEvent) ignoreNextMouseEvent++; // Avoid jumping cursor when moved. + if (!ignoreNextMouseEvent) + ignoreNextMouseEvent++; // Avoid jumping cursor when moved. isMouseDown &= ~1; return; } - if (mouse_capture && event->button() == Qt::MiddleButton && mouse_get_buttons() < 3) - { + if (mouse_capture && (event->button() == Qt::MiddleButton) && (mouse_get_buttons() < 3)) { plat_mouse_capture(0); this->setCursor(Qt::ArrowCursor); isMouseDown &= ~1; return; } - if (mouse_capture) - { - mousedata.mousebuttons &= ~event->button(); + if (mouse_capture || (mouse_input_mode >= 1)) { +#ifdef Q_OS_WINDOWS + if (((m_monitor_index >= 1) && (mouse_input_mode >= 1) && mousedata.mouse_tablet_in_proximity) || + ((m_monitor_index < 1) && (mouse_input_mode >= 1))) +#else +#ifndef __APPLE__ + if (((m_monitor_index >= 1) && (mouse_input_mode >= 1) && mousedata.mouse_tablet_in_proximity) || + (m_monitor_index < 1)) +#else + if ((m_monitor_index >= 1) && (mouse_input_mode >= 1) && mousedata.mouse_tablet_in_proximity) +#endif +#endif + mouse_set_buttons_ex(mouse_get_buttons_ex() & ~event->button()); } isMouseDown &= ~1; } -void RendererStack::mousePressEvent(QMouseEvent *event) + +void +RendererStack::mousePressEvent(QMouseEvent *event) { isMouseDown |= 1; - if (mouse_capture) - { - mousedata.mousebuttons |= event->button(); + if (mouse_capture || (mouse_input_mode >= 1)) { +#ifdef Q_OS_WINDOWS + if (((m_monitor_index >= 1) && (mouse_input_mode >= 1) && mousedata.mouse_tablet_in_proximity) || + ((m_monitor_index < 1) && (mouse_input_mode >= 1))) +#else +#ifndef __APPLE__ + if (((m_monitor_index >= 1) && (mouse_input_mode >= 1) && mousedata.mouse_tablet_in_proximity) || + (m_monitor_index < 1)) +#else + if ((m_monitor_index >= 1) && (mouse_input_mode >= 1) && mousedata.mouse_tablet_in_proximity) +#endif +#endif + mouse_set_buttons_ex(mouse_get_buttons_ex() | event->button()); } event->accept(); } -void RendererStack::wheelEvent(QWheelEvent *event) + +void +RendererStack::wheelEvent(QWheelEvent *event) { - if (mouse_capture) - { - mousedata.deltaz += event->pixelDelta().y(); - } + mouse_set_z(event->pixelDelta().y()); } -void RendererStack::mouseMoveEvent(QMouseEvent *event) +void +RendererStack::mouseMoveEvent(QMouseEvent *event) { - if (QApplication::platformName().contains("wayland")) - { + if (QApplication::platformName().contains("wayland")) { event->accept(); return; } - if (!mouse_capture) { event->ignore(); return; } -#ifdef __APPLE__ + if (!mouse_capture) { + event->ignore(); + return; + } +#if defined __APPLE__ || defined _WIN32 event->accept(); return; #else static QPoint oldPos = QCursor::pos(); - if (ignoreNextMouseEvent) { oldPos = event->pos(); ignoreNextMouseEvent--; event->accept(); return; } - mousedata.deltax += event->pos().x() - oldPos.x(); - mousedata.deltay += event->pos().y() - oldPos.y(); - if (QApplication::platformName() == "eglfs") - { - leaveEvent((QEvent*)event); + if (ignoreNextMouseEvent) { + oldPos = event->pos(); + ignoreNextMouseEvent--; + event->accept(); + return; + } + +#if defined __unix__ && !defined __HAIKU__ + if (!stricmp(mousedata.mouse_type, "wayland")) + mouse_scale(event->pos().x() - oldPos.x(), event->pos().y() - oldPos.y()); +#endif + + if (QApplication::platformName() == "eglfs") { + leaveEvent((QEvent *) event); ignoreNextMouseEvent--; } QCursor::setPos(mapToGlobal(QPoint(width() / 2, height() / 2))); ignoreNextMouseEvent = 2; - oldPos = event->pos(); + oldPos = event->pos(); #endif } -void RendererStack::leaveEvent(QEvent* event) +void +#if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0) +RendererStack::enterEvent(QEnterEvent *event) +#else +RendererStack::enterEvent(QEvent *event) +#endif { - if (QApplication::platformName().contains("wayland")) - { + mousedata.mouse_tablet_in_proximity = 1; + + if (mouse_input_mode == 1) + QApplication::setOverrideCursor(Qt::BlankCursor); +} + +void +RendererStack::leaveEvent(QEvent *event) +{ + mousedata.mouse_tablet_in_proximity = 0; + + if (mouse_input_mode == 1 && QApplication::overrideCursor()) + QApplication::restoreOverrideCursor(); + if (QApplication::platformName().contains("wayland")) { event->accept(); return; } - if (!mouse_capture) return; + if (!mouse_capture) + return; + QCursor::setPos(mapToGlobal(QPoint(width() / 2, height() / 2))); ignoreNextMouseEvent = 2; event->accept(); } -void RendererStack::switchRenderer(Renderer renderer) { +void +RendererStack::switchRenderer(Renderer renderer) +{ startblit(); if (current) { - removeWidget(current.get()); - } + if ((current_vid_api == Renderer::Direct3D9 && renderer != Renderer::Direct3D9) + || (current_vid_api != Renderer::Direct3D9 && renderer == Renderer::Direct3D9)) { + rendererWindow->finalize(); + if (rendererWindow->hasBlitFunc()) { + while (directBlitting) { } + connect(this, &RendererStack::blit, this, &RendererStack::blitDummy, Qt::DirectConnection); + disconnect(this, &RendererStack::blit, this, &RendererStack::blitRenderer); + } else { + connect(this, &RendererStack::blit, this, &RendererStack::blitDummy, Qt::DirectConnection); + disconnect(this, &RendererStack::blit, this, &RendererStack::blitCommon); + } + removeWidget(current.get()); + disconnect(this, &RendererStack::blitToRenderer, nullptr, nullptr); + + /* Create new renderer only after previous is destroyed! */ + connect(current.get(), &QObject::destroyed, [this, renderer](QObject *) { + createRenderer(renderer); + disconnect(this, &RendererStack::blit, this, &RendererStack::blitDummy); + blitDummied = false; + QTimer::singleShot(1000, this, []() { blitDummied = false; }); + }); + + rendererWindow->hasBlitFunc() ? current.reset() : current.release()->deleteLater(); + } else { + rendererWindow->finalize(); + removeWidget(current.get()); + disconnect(this, &RendererStack::blitToRenderer, nullptr, nullptr); + + /* Create new renderer only after previous is destroyed! */ + connect(current.get(), &QObject::destroyed, [this, renderer](QObject *) { createRenderer(renderer); }); + + current.release()->deleteLater(); + } + } else { + createRenderer(renderer); + } +} + +void +RendererStack::createRenderer(Renderer renderer) +{ + current_vid_api = renderer; switch (renderer) { - case Renderer::Software: - { - auto sw = new SoftwareRenderer(this); - rendererWindow = sw; - connect(this, &RendererStack::blitToRenderer, sw, &SoftwareRenderer::onBlit, Qt::QueuedConnection); - current.reset(this->createWindowContainer(sw, this)); + default: + case Renderer::Software: + { + auto sw = new SoftwareRenderer(this); + rendererWindow = sw; + connect(this, &RendererStack::blitToRenderer, sw, &SoftwareRenderer::onBlit, Qt::QueuedConnection); +#ifdef __HAIKU__ + current.reset(sw); +#else + current.reset(this->createWindowContainer(sw, this)); +#endif + } + break; + case Renderer::OpenGL: + { + this->createWinId(); + auto hw = new HardwareRenderer(this); + rendererWindow = hw; + connect(this, &RendererStack::blitToRenderer, hw, &HardwareRenderer::onBlit, Qt::QueuedConnection); + current.reset(this->createWindowContainer(hw, this)); + break; + } + case Renderer::OpenGLES: + { + this->createWinId(); + auto hw = new HardwareRenderer(this, HardwareRenderer::RenderType::OpenGLES); + rendererWindow = hw; + connect(this, &RendererStack::blitToRenderer, hw, &HardwareRenderer::onBlit, Qt::QueuedConnection); + current.reset(this->createWindowContainer(hw, this)); + break; + } + case Renderer::OpenGL3: + { + this->createWinId(); + auto hw = new OpenGLRenderer(this); + rendererWindow = hw; + connect(this, &RendererStack::blitToRenderer, hw, &OpenGLRenderer::onBlit, Qt::QueuedConnection); + connect(hw, &OpenGLRenderer::initialized, [=]() { + /* Buffers are available only after initialization. */ + imagebufs = rendererWindow->getBuffers(); + endblit(); + emit rendererChanged(); + }); + connect(hw, &OpenGLRenderer::errorInitializing, [=]() { + /* Renderer not could initialize, fallback to software. */ + imagebufs = {}; + QTimer::singleShot(0, this, [this]() { switchRenderer(Renderer::Software); }); + }); + current.reset(this->createWindowContainer(hw, this)); + break; + } +#ifdef Q_OS_WIN + case Renderer::Direct3D9: + { + this->createWinId(); + auto hw = new D3D9Renderer(this, m_monitor_index); + rendererWindow = hw; + connect(hw, &D3D9Renderer::error, this, [this](QString str) { + auto msgBox = new QMessageBox(QMessageBox::Critical, "86Box", QString("Failed to initialize D3D9 renderer. Falling back to software rendering.\n\n") + str, QMessageBox::Ok); + msgBox->setAttribute(Qt::WA_DeleteOnClose); + msgBox->show(); + imagebufs = {}; + QTimer::singleShot(0, this, [this]() { switchRenderer(Renderer::Software); }); + }); + connect(hw, &D3D9Renderer::initialized, this, [this]() { + endblit(); + emit rendererChanged(); + }); + current.reset(hw); + break; + } +#endif +#if QT_CONFIG(vulkan) + case Renderer::Vulkan: + { + this->createWinId(); + VulkanWindowRenderer *hw = nullptr; + try { + hw = new VulkanWindowRenderer(this); + } catch (std::runtime_error &e) { + auto msgBox = new QMessageBox(QMessageBox::Critical, "86Box", e.what() + QString("\nFalling back to software rendering."), QMessageBox::Ok); + msgBox->setAttribute(Qt::WA_DeleteOnClose); + msgBox->show(); + imagebufs = {}; + QTimer::singleShot(0, this, [this]() { switchRenderer(Renderer::Software); }); + current.reset(nullptr); + break; + } + rendererWindow = hw; + connect(this, &RendererStack::blitToRenderer, hw, &VulkanWindowRenderer::onBlit, Qt::QueuedConnection); + connect(hw, &VulkanWindowRenderer::rendererInitialized, [=]() { + /* Buffers are available only after initialization. */ + imagebufs = rendererWindow->getBuffers(); + endblit(); + emit rendererChanged(); + }); + connect(hw, &VulkanWindowRenderer::errorInitializing, [=]() { + /* Renderer could not initialize, fallback to software. */ + auto msgBox = new QMessageBox(QMessageBox::Critical, "86Box", QString("Failed to initialize Vulkan renderer.\nFalling back to software rendering."), QMessageBox::Ok); + msgBox->setAttribute(Qt::WA_DeleteOnClose); + msgBox->show(); + imagebufs = {}; + QTimer::singleShot(0, this, [this]() { switchRenderer(Renderer::Software); }); + }); + current.reset(this->createWindowContainer(hw, this)); + break; + } +#endif } - break; - case Renderer::OpenGL: - { - this->createWinId(); - auto hw = new HardwareRenderer(this); - rendererWindow = hw; - connect(this, &RendererStack::blitToRenderer, hw, &HardwareRenderer::onBlit, Qt::QueuedConnection); - current.reset(this->createWindowContainer(hw, this)); - break; - } - case Renderer::OpenGLES: - { - this->createWinId(); - auto hw = new HardwareRenderer(this, HardwareRenderer::RenderType::OpenGLES); - rendererWindow = hw; - connect(this, &RendererStack::blitToRenderer, hw, &HardwareRenderer::onBlit, Qt::QueuedConnection); - current.reset(this->createWindowContainer(hw, this)); - break; - } - case Renderer::OpenGL3: - { - this->createWinId(); - auto hw = new HardwareRenderer(this, HardwareRenderer::RenderType::OpenGL3); - rendererWindow = hw; - connect(this, &RendererStack::blitToRenderer, hw, &HardwareRenderer::onBlit, Qt::QueuedConnection); - current.reset(this->createWindowContainer(hw, this)); - break; - } - } - - imagebufs = std::move(rendererWindow->getBuffers()); - + if (current.get() == nullptr) + return; current->setFocusPolicy(Qt::NoFocus); current->setFocusProxy(this); + current->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding); + current->setStyleSheet("background-color: black"); addWidget(current.get()); this->setStyleSheet("background-color: black"); - endblit(); + currentBuf = 0; + + if (rendererWindow->hasBlitFunc()) { + connect(this, &RendererStack::blit, this, &RendererStack::blitRenderer, Qt::DirectConnection); + } else { + connect(this, &RendererStack::blit, this, &RendererStack::blitCommon, Qt::DirectConnection); + } + + if (renderer != Renderer::OpenGL3 && renderer != Renderer::Vulkan && renderer != Renderer::Direct3D9) { + imagebufs = rendererWindow->getBuffers(); + endblit(); + emit rendererChanged(); + } +} + +void +RendererStack::blitDummy(int x, int y, int w, int h) +{ + video_blit_complete_monitor(m_monitor_index); + blitDummied = true; +} + +void +RendererStack::blitRenderer(int x, int y, int w, int h) +{ + if (blitDummied) { + blitDummied = false; + video_blit_complete_monitor(m_monitor_index); + return; + } + directBlitting = true; + rendererWindow->blit(x, y, w, h); + directBlitting = false; } // called from blitter thread -void RendererStack::blit(int x, int y, int w, int h) +void +RendererStack::blitCommon(int x, int y, int w, int h) { - if ((w <= 0) || (h <= 0) || (w > 2048) || (h > 2048) || (buffer32 == NULL) || std::get(imagebufs[currentBuf])->test_and_set()) - { - video_blit_complete(); + if (blitDummied || (x < 0) || (y < 0) || (w <= 0) || (h <= 0) || (w > 2048) || (h > 2048) || (monitors[m_monitor_index].target_buffer == NULL) || imagebufs.empty() || std::get(imagebufs[currentBuf])->test_and_set()) { + video_blit_complete_monitor(m_monitor_index); return; } sx = x; sy = y; sw = this->w = w; - sh = this->h = h; - uint8_t* imagebits = std::get(imagebufs[currentBuf]); - for (int y1 = y; y1 < (y + h); y1++) - { - auto scanline = imagebits + (y1 * (2048) * 4) + (x * 4); - video_copy(scanline, &(buffer32->line[y1][x]), w * 4); + sh = this->h = h; + uint8_t *imagebits = std::get(imagebufs[currentBuf]); + for (int y1 = y; y1 < (y + h); y1++) { + auto scanline = imagebits + (y1 * rendererWindow->getBytesPerRow()) + (x * 4); + video_copy(scanline, &(monitors[m_monitor_index].target_buffer->line[y1][x]), w * 4); } - if (screenshots) - { - video_screenshot((uint32_t *)imagebits, x, y, 2048); + if (monitors[m_monitor_index].mon_screenshots) { + video_screenshot_monitor((uint32_t *) imagebits, x, y, 2048, m_monitor_index); } - video_blit_complete(); + video_blit_complete_monitor(m_monitor_index); emit blitToRenderer(currentBuf, sx, sy, sw, sh); currentBuf = (currentBuf + 1) % imagebufs.size(); } + +void +RendererStack::closeEvent(QCloseEvent *event) +{ + if (cpu_thread_run == 1 || is_quit == 0) { + event->accept(); + main_window->ui->actionShow_non_primary_monitors->setChecked(false); + return; + } + event->ignore(); + main_window->close(); +} + +void +RendererStack::changeEvent(QEvent *event) +{ + if (m_monitor_index != 0 && isVisible()) { + monitor_settings[m_monitor_index].mon_window_maximized = isMaximized(); + config_save(); + } +} + +bool +RendererStack::event(QEvent* event) +{ + if (event->type() == QEvent::MouseMove) { + QMouseEvent* mouse_event = (QMouseEvent*)event; + + if (m_monitor_index >= 1) { + if (mouse_input_mode >= 1) { + mouse_x_abs = (mouse_event->localPos().x()) / (long double)width(); + mouse_y_abs = (mouse_event->localPos().y()) / (long double)height(); + if (!mouse_tablet_in_proximity) + mouse_tablet_in_proximity = mousedata.mouse_tablet_in_proximity; + } + return QStackedWidget::event(event); + } + +#ifdef Q_OS_WINDOWS + if (mouse_input_mode == 0) { + mouse_x_abs = (mouse_event->localPos().x()) / (long double)width(); + mouse_y_abs = (mouse_event->localPos().y()) / (long double)height(); + return QStackedWidget::event(event); + } +#endif + + mouse_x_abs = (mouse_event->localPos().x()) / (long double)width(); + mouse_y_abs = (mouse_event->localPos().y()) / (long double)height(); + mouse_tablet_in_proximity = mousedata.mouse_tablet_in_proximity; + } + + return QStackedWidget::event(event); +} + +void +RendererStack::setFocusRenderer() +{ + if (current) + current->setFocus(); +} + +void +RendererStack::onResize(int width, int height) +{ + if (rendererWindow) { + rendererWindow->r_monitor_index = m_monitor_index; + rendererWindow->onResize(width, height); + } +} diff --git a/src/qt/qt_rendererstack.hpp b/src/qt/qt_rendererstack.hpp index 9bff340f0..c9d90869b 100644 --- a/src/qt/qt_rendererstack.hpp +++ b/src/qt/qt_rendererstack.hpp @@ -1,75 +1,119 @@ #ifndef QT_RENDERERCONTAINER_HPP #define QT_RENDERERCONTAINER_HPP -#include -#include +#include #include -#include -#include +#include +#include +#include +#include + #include +#include #include +#include + +#include "qt_renderercommon.hpp" namespace Ui { class RendererStack; } class RendererCommon; -class RendererStack : public QStackedWidget -{ +class RendererStack : public QStackedWidget { Q_OBJECT public: - explicit RendererStack(QWidget *parent = nullptr); + explicit RendererStack(QWidget *parent = nullptr, int monitor_index = 0); ~RendererStack(); - void mousePressEvent(QMouseEvent* event) override; - void mouseReleaseEvent(QMouseEvent* event) override; - void mouseMoveEvent(QMouseEvent* event) override; + void mousePressEvent(QMouseEvent *event) override; + void mouseReleaseEvent(QMouseEvent *event) override; + void mouseMoveEvent(QMouseEvent *event) override; void wheelEvent(QWheelEvent *event) override; +#if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0) + void enterEvent(QEnterEvent *event) override; +#else + void enterEvent(QEvent *event) override; +#endif void leaveEvent(QEvent *event) override; - void keyPressEvent(QKeyEvent* event) override + void closeEvent(QCloseEvent *event) override; + void changeEvent(QEvent *event) override; + void resizeEvent(QResizeEvent *event) override + { + onResize(event->size().width(), event->size().height()); + } + void keyPressEvent(QKeyEvent *event) override { event->ignore(); } - void keyReleaseEvent(QKeyEvent* event) override + void keyReleaseEvent(QKeyEvent *event) override { event->ignore(); } + bool event(QEvent* event) override; enum class Renderer { Software, OpenGL, OpenGLES, - OpenGL3 + OpenGL3, + Vulkan, + Direct3D9, + None = -1 }; void switchRenderer(Renderer renderer); - RendererCommon* rendererWindow{nullptr}; + /* Does current renderer implement options dialog */ + bool hasOptions() const { return rendererWindow ? rendererWindow->hasOptions() : false; } + /* Reloads options of current renderer */ + void reloadOptions() const { return rendererWindow->reloadOptions(); } + /* Returns options dialog for current renderer */ + QDialog *getOptions(QWidget *parent) { return rendererWindow ? rendererWindow->getOptions(parent) : nullptr; } + + void setFocusRenderer(); + void onResize(int width, int height); + + void (*mouse_capture_func)(QWindow *window) = nullptr; + void (*mouse_uncapture_func)() = nullptr; + + void (*mouse_exit_func)() = nullptr; + signals: void blitToRenderer(int buf_idx, int x, int y, int w, int h); + void blit(int x, int y, int w, int h); + void rendererChanged(); public slots: - void blit(int x, int y, int w, int h); - void mousePoll(); + void blitCommon(int x, int y, int w, int h); + void blitRenderer(int x, int y, int w, int h); + void blitDummy(int x, int y, int w, int h); private: + void createRenderer(Renderer renderer); + Ui::RendererStack *ui; - struct mouseinputdata { - int deltax, deltay, deltaz; - int mousebuttons; - }; - mouseinputdata mousedata; + int x; + int y; + int w; + int h; + int sx; + int sy; + int sw; + int sh; - int x, y, w, h, sx, sy, sw, sh; + int currentBuf = 0; + int isMouseDown = 0; + int m_monitor_index = 0; - int currentBuf = 0; - int isMouseDown = 0; - std::vector> imagebufs; + Renderer current_vid_api = Renderer::None; + std::vector> imagebufs; + + RendererCommon *rendererWindow { nullptr }; std::unique_ptr current; - - friend class MainWindow; + std::atomic directBlitting { false }; }; #endif // QT_RENDERERCONTAINER_HPP diff --git a/src/qt/qt_sdl.c b/src/qt/qt_sdl.c index 08f240862..15af4d7b6 100644 --- a/src/qt/qt_sdl.c +++ b/src/qt/qt_sdl.c @@ -1,42 +1,42 @@ /* - * 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. + * 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. + * This file is part of the 86Box distribution. * - * Rendering module for libSDL2 + * Rendering module for libSDL2 * - * NOTE: Given all the problems reported with FULLSCREEN use of SDL, - * we will not use that, but, instead, use a new window which - * coverrs the entire desktop. + * NOTE: Given all the problems reported with FULLSCREEN use of SDL, + * we will not use that, but, instead, use a new window which + * covers the entire desktop. * * * - * Authors: Fred N. van Kempen, - * Michael Drüing, + * Authors: Fred N. van Kempen, + * Michael Drüing, * - * Copyright 2018-2020 Fred N. van Kempen. - * Copyright 2018-2020 Michael Drüing. + * Copyright 2018-2020 Fred N. van Kempen. + * Copyright 2018-2020 Michael Drüing. * - * Redistribution and use in source and binary forms, with - * or without modification, are permitted provided that the - * following conditions are met: + * Redistribution and use in source and binary forms, with + * or without modification, are permitted provided that the + * following conditions are met: * - * 1. Redistributions of source code must retain the entire - * above notice, this list of conditions and the following - * disclaimer. + * 1. Redistributions of source code must retain the entire + * above notice, this list of conditions and the following + * disclaimer. * - * 2. Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the - * following disclaimer in the documentation and/or other - * materials provided with the distribution. + * 2. Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the + * following disclaimer in the documentation and/or other + * materials provided with the distribution. * - * 3. Neither the name of the copyright holder nor the names - * of its contributors may be used to endorse or promote - * products derived from this software without specific - * prior written permission. + * 3. Neither the name of the copyright holder nor the names + * of its contributors may be used to endorse or promote + * products derived from this software without specific + * prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT @@ -71,138 +71,133 @@ #include "qt_sdl.h" -#define RENDERER_FULL_SCREEN 1 -#define RENDERER_HARDWARE 2 -#define RENDERER_OPENGL 4 +#define RENDERER_FULL_SCREEN 1 +#define RENDERER_HARDWARE 2 +#define RENDERER_OPENGL 4 +static SDL_Window *sdl_win = NULL; +static SDL_Renderer *sdl_render = NULL; +static SDL_Texture *sdl_tex = NULL; +static int sdl_w; +static int sdl_h; +static int sdl_fs; +static int sdl_flags = -1; +static int cur_w; +static int cur_h; +static int cur_ww = 0; +static int cur_wh = 0; +static volatile int sdl_enabled = 0; +static SDL_mutex *sdl_mutex = NULL; -static SDL_Window *sdl_win = NULL; -static SDL_Renderer *sdl_render = NULL; -static SDL_Texture *sdl_tex = NULL; -static int sdl_w, sdl_h; -static int sdl_fs, sdl_flags = -1; -static int cur_w, cur_h; -static int cur_ww = 0, cur_wh = 0; -static volatile int sdl_enabled = 0; -static SDL_mutex* sdl_mutex = NULL; +static const uint16_t sdl_to_xt[0x200] = { + [SDL_SCANCODE_ESCAPE] = 0x01, + [SDL_SCANCODE_1] = 0x02, + [SDL_SCANCODE_2] = 0x03, + [SDL_SCANCODE_3] = 0x04, + [SDL_SCANCODE_4] = 0x05, + [SDL_SCANCODE_5] = 0x06, + [SDL_SCANCODE_6] = 0x07, + [SDL_SCANCODE_7] = 0x08, + [SDL_SCANCODE_8] = 0x09, + [SDL_SCANCODE_9] = 0x0A, + [SDL_SCANCODE_0] = 0x0B, + [SDL_SCANCODE_MINUS] = 0x0C, + [SDL_SCANCODE_EQUALS] = 0x0D, + [SDL_SCANCODE_BACKSPACE] = 0x0E, + [SDL_SCANCODE_TAB] = 0x0F, + [SDL_SCANCODE_Q] = 0x10, + [SDL_SCANCODE_W] = 0x11, + [SDL_SCANCODE_E] = 0x12, + [SDL_SCANCODE_R] = 0x13, + [SDL_SCANCODE_T] = 0x14, + [SDL_SCANCODE_Y] = 0x15, + [SDL_SCANCODE_U] = 0x16, + [SDL_SCANCODE_I] = 0x17, + [SDL_SCANCODE_O] = 0x18, + [SDL_SCANCODE_P] = 0x19, + [SDL_SCANCODE_LEFTBRACKET] = 0x1A, + [SDL_SCANCODE_RIGHTBRACKET] = 0x1B, + [SDL_SCANCODE_RETURN] = 0x1C, + [SDL_SCANCODE_LCTRL] = 0x1D, + [SDL_SCANCODE_A] = 0x1E, + [SDL_SCANCODE_S] = 0x1F, + [SDL_SCANCODE_D] = 0x20, + [SDL_SCANCODE_F] = 0x21, + [SDL_SCANCODE_G] = 0x22, + [SDL_SCANCODE_H] = 0x23, + [SDL_SCANCODE_J] = 0x24, + [SDL_SCANCODE_K] = 0x25, + [SDL_SCANCODE_L] = 0x26, + [SDL_SCANCODE_SEMICOLON] = 0x27, + [SDL_SCANCODE_APOSTROPHE] = 0x28, + [SDL_SCANCODE_GRAVE] = 0x29, + [SDL_SCANCODE_LSHIFT] = 0x2A, + [SDL_SCANCODE_BACKSLASH] = 0x2B, + [SDL_SCANCODE_Z] = 0x2C, + [SDL_SCANCODE_X] = 0x2D, + [SDL_SCANCODE_C] = 0x2E, + [SDL_SCANCODE_V] = 0x2F, + [SDL_SCANCODE_B] = 0x30, + [SDL_SCANCODE_N] = 0x31, + [SDL_SCANCODE_M] = 0x32, + [SDL_SCANCODE_COMMA] = 0x33, + [SDL_SCANCODE_PERIOD] = 0x34, + [SDL_SCANCODE_SLASH] = 0x35, + [SDL_SCANCODE_RSHIFT] = 0x36, + [SDL_SCANCODE_KP_MULTIPLY] = 0x37, + [SDL_SCANCODE_LALT] = 0x38, + [SDL_SCANCODE_SPACE] = 0x39, + [SDL_SCANCODE_CAPSLOCK] = 0x3A, + [SDL_SCANCODE_F1] = 0x3B, + [SDL_SCANCODE_F2] = 0x3C, + [SDL_SCANCODE_F3] = 0x3D, + [SDL_SCANCODE_F4] = 0x3E, + [SDL_SCANCODE_F5] = 0x3F, + [SDL_SCANCODE_F6] = 0x40, + [SDL_SCANCODE_F7] = 0x41, + [SDL_SCANCODE_F8] = 0x42, + [SDL_SCANCODE_F9] = 0x43, + [SDL_SCANCODE_F10] = 0x44, + [SDL_SCANCODE_NUMLOCKCLEAR] = 0x45, + [SDL_SCANCODE_SCROLLLOCK] = 0x46, + [SDL_SCANCODE_HOME] = 0x147, + [SDL_SCANCODE_UP] = 0x148, + [SDL_SCANCODE_PAGEUP] = 0x149, + [SDL_SCANCODE_KP_MINUS] = 0x4A, + [SDL_SCANCODE_LEFT] = 0x14B, + [SDL_SCANCODE_KP_5] = 0x4C, + [SDL_SCANCODE_RIGHT] = 0x14D, + [SDL_SCANCODE_KP_PLUS] = 0x4E, + [SDL_SCANCODE_END] = 0x14F, + [SDL_SCANCODE_DOWN] = 0x150, + [SDL_SCANCODE_PAGEDOWN] = 0x151, + [SDL_SCANCODE_INSERT] = 0x152, + [SDL_SCANCODE_DELETE] = 0x153, + [SDL_SCANCODE_F11] = 0x57, + [SDL_SCANCODE_F12] = 0x58, -static const uint16_t sdl_to_xt[0x200] = - { - [SDL_SCANCODE_ESCAPE] = 0x01, - [SDL_SCANCODE_1] = 0x02, - [SDL_SCANCODE_2] = 0x03, - [SDL_SCANCODE_3] = 0x04, - [SDL_SCANCODE_4] = 0x05, - [SDL_SCANCODE_5] = 0x06, - [SDL_SCANCODE_6] = 0x07, - [SDL_SCANCODE_7] = 0x08, - [SDL_SCANCODE_8] = 0x09, - [SDL_SCANCODE_9] = 0x0A, - [SDL_SCANCODE_0] = 0x0B, - [SDL_SCANCODE_MINUS] = 0x0C, - [SDL_SCANCODE_EQUALS] = 0x0D, - [SDL_SCANCODE_BACKSPACE] = 0x0E, - [SDL_SCANCODE_TAB] = 0x0F, - [SDL_SCANCODE_Q] = 0x10, - [SDL_SCANCODE_W] = 0x11, - [SDL_SCANCODE_E] = 0x12, - [SDL_SCANCODE_R] = 0x13, - [SDL_SCANCODE_T] = 0x14, - [SDL_SCANCODE_Y] = 0x15, - [SDL_SCANCODE_U] = 0x16, - [SDL_SCANCODE_I] = 0x17, - [SDL_SCANCODE_O] = 0x18, - [SDL_SCANCODE_P] = 0x19, - [SDL_SCANCODE_LEFTBRACKET] = 0x1A, - [SDL_SCANCODE_RIGHTBRACKET] = 0x1B, - [SDL_SCANCODE_RETURN] = 0x1C, - [SDL_SCANCODE_LCTRL] = 0x1D, - [SDL_SCANCODE_A] = 0x1E, - [SDL_SCANCODE_S] = 0x1F, - [SDL_SCANCODE_D] = 0x20, - [SDL_SCANCODE_F] = 0x21, - [SDL_SCANCODE_G] = 0x22, - [SDL_SCANCODE_H] = 0x23, - [SDL_SCANCODE_J] = 0x24, - [SDL_SCANCODE_K] = 0x25, - [SDL_SCANCODE_L] = 0x26, - [SDL_SCANCODE_SEMICOLON] = 0x27, - [SDL_SCANCODE_APOSTROPHE] = 0x28, - [SDL_SCANCODE_GRAVE] = 0x29, - [SDL_SCANCODE_LSHIFT] = 0x2A, - [SDL_SCANCODE_BACKSLASH] = 0x2B, - [SDL_SCANCODE_Z] = 0x2C, - [SDL_SCANCODE_X] = 0x2D, - [SDL_SCANCODE_C] = 0x2E, - [SDL_SCANCODE_V] = 0x2F, - [SDL_SCANCODE_B] = 0x30, - [SDL_SCANCODE_N] = 0x31, - [SDL_SCANCODE_M] = 0x32, - [SDL_SCANCODE_COMMA] = 0x33, - [SDL_SCANCODE_PERIOD] = 0x34, - [SDL_SCANCODE_SLASH] = 0x35, - [SDL_SCANCODE_RSHIFT] = 0x36, - [SDL_SCANCODE_KP_MULTIPLY] = 0x37, - [SDL_SCANCODE_LALT] = 0x38, - [SDL_SCANCODE_SPACE] = 0x39, - [SDL_SCANCODE_CAPSLOCK] = 0x3A, - [SDL_SCANCODE_F1] = 0x3B, - [SDL_SCANCODE_F2] = 0x3C, - [SDL_SCANCODE_F3] = 0x3D, - [SDL_SCANCODE_F4] = 0x3E, - [SDL_SCANCODE_F5] = 0x3F, - [SDL_SCANCODE_F6] = 0x40, - [SDL_SCANCODE_F7] = 0x41, - [SDL_SCANCODE_F8] = 0x42, - [SDL_SCANCODE_F9] = 0x43, - [SDL_SCANCODE_F10] = 0x44, - [SDL_SCANCODE_NUMLOCKCLEAR] = 0x45, - [SDL_SCANCODE_SCROLLLOCK] = 0x46, - [SDL_SCANCODE_HOME] = 0x147, - [SDL_SCANCODE_UP] = 0x148, - [SDL_SCANCODE_PAGEUP] = 0x149, - [SDL_SCANCODE_KP_MINUS] = 0x4A, - [SDL_SCANCODE_LEFT] = 0x14B, - [SDL_SCANCODE_KP_5] = 0x4C, - [SDL_SCANCODE_RIGHT] = 0x14D, - [SDL_SCANCODE_KP_PLUS] = 0x4E, - [SDL_SCANCODE_END] = 0x14F, - [SDL_SCANCODE_DOWN] = 0x150, - [SDL_SCANCODE_PAGEDOWN] = 0x151, - [SDL_SCANCODE_INSERT] = 0x152, - [SDL_SCANCODE_DELETE] = 0x153, - [SDL_SCANCODE_F11] = 0x57, - [SDL_SCANCODE_F12] = 0x58, + [SDL_SCANCODE_KP_ENTER] = 0x11c, + [SDL_SCANCODE_RCTRL] = 0x11d, + [SDL_SCANCODE_KP_DIVIDE] = 0x135, + [SDL_SCANCODE_RALT] = 0x138, + [SDL_SCANCODE_KP_9] = 0x49, + [SDL_SCANCODE_KP_8] = 0x48, + [SDL_SCANCODE_KP_7] = 0x47, + [SDL_SCANCODE_KP_6] = 0x4D, + [SDL_SCANCODE_KP_4] = 0x4B, + [SDL_SCANCODE_KP_3] = 0x51, + [SDL_SCANCODE_KP_2] = 0x50, + [SDL_SCANCODE_KP_1] = 0x4F, + [SDL_SCANCODE_KP_0] = 0x52, + [SDL_SCANCODE_KP_PERIOD] = 0x53, - [SDL_SCANCODE_KP_ENTER] = 0x11c, - [SDL_SCANCODE_RCTRL] = 0x11d, - [SDL_SCANCODE_KP_DIVIDE] = 0x135, - [SDL_SCANCODE_RALT] = 0x138, - [SDL_SCANCODE_KP_9] = 0x49, - [SDL_SCANCODE_KP_8] = 0x48, - [SDL_SCANCODE_KP_7] = 0x47, - [SDL_SCANCODE_KP_6] = 0x4D, - [SDL_SCANCODE_KP_4] = 0x4B, - [SDL_SCANCODE_KP_3] = 0x51, - [SDL_SCANCODE_KP_2] = 0x50, - [SDL_SCANCODE_KP_1] = 0x4F, - [SDL_SCANCODE_KP_0] = 0x52, - [SDL_SCANCODE_KP_PERIOD] = 0x53, - - [SDL_SCANCODE_LGUI] = 0x15B, - [SDL_SCANCODE_RGUI] = 0x15C, - [SDL_SCANCODE_APPLICATION] = 0x15D, - [SDL_SCANCODE_PRINTSCREEN] = 0x137, - [SDL_SCANCODE_NONUSBACKSLASH] = 0x56, + [SDL_SCANCODE_LGUI] = 0x15B, + [SDL_SCANCODE_RGUI] = 0x15C, + [SDL_SCANCODE_APPLICATION] = 0x15D, + [SDL_SCANCODE_PRINTSCREEN] = 0x137, + [SDL_SCANCODE_NONUSBACKSLASH] = 0x56, }; -typedef struct mouseinputdata -{ - int deltax, deltay, deltaz; - int mousebuttons; -} mouseinputdata; -static mouseinputdata mousedata; - // #define ENABLE_SDL_LOG 3 #ifdef ENABLE_SDL_LOG int sdl_do_log = ENABLE_SDL_LOG; @@ -213,88 +208,95 @@ sdl_log(const char *fmt, ...) va_list ap; if (sdl_do_log) { - va_start(ap, fmt); - pclog_ex(fmt, ap); - va_end(ap); + va_start(ap, fmt); + pclog_ex(fmt, ap); + va_end(ap); } } #else -#define sdl_log(fmt, ...) +# define sdl_log(fmt, ...) #endif - static void sdl_integer_scale(double *d, double *g) { double ratio; if (*d > *g) { - ratio = floor(*d / *g); - *d = *g * ratio; + ratio = floor(*d / *g); + *d = *g * ratio; } else { - ratio = ceil(*d / *g); - *d = *g / ratio; + ratio = ceil(*d / *g); + *d = *g / ratio; } } - static void sdl_stretch(int *w, int *h, int *x, int *y) { - double hw, gw, hh, gh, dx, dy, dw, dh, gsr, hsr; + double hw; + double gw; + double hh; + double gh; + double dx; + double dy; + double dw; + double dh; + double gsr; + double hsr; - hw = (double) sdl_w; - hh = (double) sdl_h; - gw = (double) *w; - gh = (double) *h; + hw = (double) sdl_w; + hh = (double) sdl_h; + gw = (double) *w; + gh = (double) *h; hsr = hw / hh; switch (video_fullscreen_scale) { - case FULLSCR_SCALE_FULL: - default: - *w = sdl_w; - *h = sdl_h; - *x = 0; - *y = 0; - break; - case FULLSCR_SCALE_43: - case FULLSCR_SCALE_KEEPRATIO: - if (video_fullscreen_scale == FULLSCR_SCALE_43) - gsr = 4.0 / 3.0; - else - gsr = gw / gh; - if (gsr <= hsr) { - dw = hh * gsr; - dh = hh; - } else { - dw = hw; - dh = hw / gsr; - } - dx = (hw - dw) / 2.0; - dy = (hh - dh) / 2.0; - *w = (int) dw; - *h = (int) dh; - *x = (int) dx; - *y = (int) dy; - break; - case FULLSCR_SCALE_INT: - gsr = gw / gh; - if (gsr <= hsr) { - dw = hh * gsr; - dh = hh; - } else { - dw = hw; - dh = hw / gsr; - } - sdl_integer_scale(&dw, &gw); - sdl_integer_scale(&dh, &gh); - dx = (hw - dw) / 2.0; - dy = (hh - dh) / 2.0; - *w = (int) dw; - *h = (int) dh; - *x = (int) dx; - *y = (int) dy; - break; + case FULLSCR_SCALE_FULL: + default: + *w = sdl_w; + *h = sdl_h; + *x = 0; + *y = 0; + break; + case FULLSCR_SCALE_43: + case FULLSCR_SCALE_KEEPRATIO: + if (video_fullscreen_scale == FULLSCR_SCALE_43) + gsr = 4.0 / 3.0; + else + gsr = gw / gh; + if (gsr <= hsr) { + dw = hh * gsr; + dh = hh; + } else { + dw = hw; + dh = hw / gsr; + } + dx = (hw - dw) / 2.0; + dy = (hh - dh) / 2.0; + *w = (int) dw; + *h = (int) dh; + *x = (int) dx; + *y = (int) dy; + break; + case FULLSCR_SCALE_INT: + gsr = gw / gh; + if (gsr <= hsr) { + dw = hh * gsr; + dh = hh; + } else { + dw = hw; + dh = hw / gsr; + } + sdl_integer_scale(&dw, &gw); + sdl_integer_scale(&dh, &gh); + dx = (hw - dw) / 2.0; + dy = (hh - dh) / 2.0; + *w = (int) dw; + *h = (int) dh; + *x = (int) dx; + *y = (int) dy; + break; } } @@ -302,8 +304,9 @@ static void sdl_blit(int x, int y, int w, int h) { SDL_Rect r_src; - void *pixeldata; - int ret, pitch; + void *pixeldata; + int ret; + int pitch; if (!sdl_enabled || (x < 0) || (y < 0) || (w <= 0) || (h <= 0) || (w > 2048) || (h > 2048) || (buffer32 == NULL) || (sdl_render == NULL) || (sdl_tex == NULL)) { video_blit_complete(); @@ -315,7 +318,7 @@ sdl_blit(int x, int y, int w, int h) video_copy(pixeldata, &(buffer32->line[y][x]), h * (2048) * sizeof(uint32_t)); - if (screenshots) + if (monitors[m_monitor_index].mon_screenshots) video_screenshot((uint32_t *) pixeldata, 0, 0, (2048)); SDL_UnlockTexture(sdl_tex); @@ -338,48 +341,45 @@ sdl_blit(int x, int y, int w, int h) SDL_UnlockMutex(sdl_mutex); } - static void sdl_destroy_window(void) { if (sdl_win != NULL) { - SDL_DestroyWindow(sdl_win); - sdl_win = NULL; + SDL_DestroyWindow(sdl_win); + sdl_win = NULL; } } - static void sdl_destroy_texture(void) { if (sdl_tex != NULL) { - SDL_DestroyTexture(sdl_tex); - sdl_tex = NULL; + SDL_DestroyTexture(sdl_tex); + sdl_tex = NULL; } /* SDL_DestroyRenderer also automatically destroys all associated textures. */ if (sdl_render != NULL) { - SDL_DestroyRenderer(sdl_render); - sdl_render = NULL; + SDL_DestroyRenderer(sdl_render); + sdl_render = NULL; } } - void sdl_close(void) { if (sdl_mutex != NULL) - SDL_LockMutex(sdl_mutex); + SDL_LockMutex(sdl_mutex); /* Unregister our renderer! */ video_setblit(NULL); if (sdl_enabled) - sdl_enabled = 0; + sdl_enabled = 0; if (sdl_mutex != NULL) { - SDL_DestroyMutex(sdl_mutex); - sdl_mutex = NULL; + SDL_DestroyMutex(sdl_mutex); + sdl_mutex = NULL; } sdl_destroy_texture(); @@ -390,11 +390,12 @@ sdl_close(void) sdl_flags = -1; } -static void sdl_select_best_hw_driver(void) { - int i; +static void +sdl_select_best_hw_driver(void) +{ SDL_RendererInfo renderInfo; - for (i = 0; i < SDL_GetNumRenderDrivers(); ++i) { + for (int i = 0; i < SDL_GetNumRenderDrivers(); ++i) { SDL_GetRenderDriverInfo(i, &renderInfo); if (renderInfo.flags & SDL_RENDERER_ACCELERATED) { SDL_SetHint(SDL_HINT_RENDER_DRIVER, renderInfo.name); @@ -414,7 +415,7 @@ sdl_init_texture(void) } sdl_tex = SDL_CreateTexture(sdl_render, SDL_PIXELFORMAT_ARGB8888, - SDL_TEXTUREACCESS_STREAMING, (2048), (2048)); + SDL_TEXTUREACCESS_STREAMING, 2048, 2048); if (sdl_render == NULL) { sdl_log("SDL: unable to SDL_CreateRenderer (%s)\n", SDL_GetError()); @@ -424,7 +425,6 @@ sdl_init_texture(void) } } - static void sdl_reinit_texture(void) { @@ -435,10 +435,11 @@ sdl_reinit_texture(void) sdl_init_texture(); } - -void sdl_set_fs(int fs) { +void +sdl_set_fs(int fs) +{ SDL_SetWindowFullscreen(sdl_win, fs ? SDL_WINDOW_FULLSCREEN_DESKTOP : 0); - SDL_SetRelativeMouseMode((SDL_bool)mouse_capture); + SDL_SetRelativeMouseMode((SDL_bool) mouse_capture); sdl_fs = fs; @@ -451,11 +452,10 @@ void sdl_set_fs(int fs) { sdl_reinit_texture(); } - static int -sdl_init_common(void* win, int flags) +sdl_init_common(void *win, int flags) { - wchar_t temp[128]; + wchar_t temp[128]; SDL_version ver; sdl_log("SDL: init (fs=%d)\n", 0); @@ -467,7 +467,7 @@ sdl_init_common(void* win, int flags) /* Initialize the SDL system. */ if (SDL_Init(SDL_INIT_VIDEO) < 0) { sdl_log("SDL: initialization failed (%s)\n", SDL_GetError()); - return(0); + return (0); } if (flags & RENDERER_HARDWARE) { @@ -481,10 +481,10 @@ sdl_init_common(void* win, int flags) SDL_DisplayMode dm; if (SDL_GetDesktopDisplayMode(0, &dm) != 0) { sdl_log("SDL: SDL_GetDesktopDisplayMode failed (%s)\n", SDL_GetError()); - return(0); + return (0); } - sdl_w = dm.w; - sdl_h = dm.h; + sdl_w = dm.w; + sdl_h = dm.h; sdl_flags = flags; sdl_win = SDL_CreateWindow("86Box renderer", 640, 480, 100, 100, sdl_flags); @@ -501,50 +501,46 @@ sdl_init_common(void* win, int flags) video_setblit(sdl_blit); sdl_enabled = 1; - sdl_mutex = SDL_CreateMutex(); + sdl_mutex = SDL_CreateMutex(); - return(1); + return (1); } - int -sdl_inits(void* win) +sdl_inits(void *win) { return sdl_init_common(win, 0); } - int -sdl_inith(void* win) +sdl_inith(void *win) { return sdl_init_common(win, RENDERER_HARDWARE); } - int -sdl_initho(void* win) +sdl_initho(void *win) { return sdl_init_common(win, RENDERER_HARDWARE | RENDERER_OPENGL); } - int sdl_pause(void) { - return(0); + return 0; } - void sdl_resize(int w, int h) { - int ww = 0, wh = 0; + int ww = 0; + int wh = 0; if (video_fullscreen & 2) - return; + return; if ((w == cur_w) && (h == cur_h)) - return; + return; SDL_LockMutex(sdl_mutex); @@ -552,8 +548,8 @@ sdl_resize(int w, int h) wh = h; if (sdl_fs) { -// sdl_stretch(&ww, &wh, &wx, &wy); -// MoveWindow(hwndRender, wx, wy, ww, wh, TRUE); + // sdl_stretch(&ww, &wh, &wx, &wy); + // MoveWindow(hwndRender, wx, wy, ww, wh, TRUE); } cur_w = w; @@ -568,12 +564,11 @@ sdl_resize(int w, int h) SDL_UnlockMutex(sdl_mutex); } - void sdl_enable(int enable) { if (sdl_flags == -1) - return; + return; SDL_LockMutex(sdl_mutex); sdl_enabled = !!enable; @@ -586,126 +581,113 @@ sdl_enable(int enable) SDL_UnlockMutex(sdl_mutex); } - void sdl_reload(void) { if (sdl_flags & RENDERER_HARDWARE) { - SDL_LockMutex(sdl_mutex); + SDL_LockMutex(sdl_mutex); - SDL_SetHint(SDL_HINT_RENDER_SCALE_QUALITY, video_filter_method ? "1" : "0"); - sdl_reinit_texture(); + SDL_SetHint(SDL_HINT_RENDER_SCALE_QUALITY, video_filter_method ? "1" : "0"); + sdl_reinit_texture(); - SDL_UnlockMutex(sdl_mutex); + SDL_UnlockMutex(sdl_mutex); } } static int mouse_inside = 0; -enum sdl_main_status sdl_main() { - int ret = SdlMainOk; - SDL_Rect r_src; +enum sdl_main_status +sdl_main() +{ + int ret = SdlMainOk; + SDL_Rect r_src; SDL_Event event; - while (SDL_PollEvent(&event)) - { - switch(event.type) - { - case SDL_QUIT: - ret = SdlMainQuit; - break; - case SDL_MOUSEWHEEL: - { - if (mouse_capture || video_fullscreen) - { - if (event.wheel.direction == SDL_MOUSEWHEEL_FLIPPED) + while (SDL_PollEvent(&event)) { + switch (event.type) { + case SDL_QUIT: + ret = SdlMainQuit; + break; + case SDL_MOUSEWHEEL: { - event.wheel.x *= -1; - event.wheel.y *= -1; + if (mouse_capture || video_fullscreen) { + if (event.wheel.direction == SDL_MOUSEWHEEL_FLIPPED) { + event.wheel.x *= -1; + event.wheel.y *= -1; + } + mouse_set_z(event.wheel.y); + } + break; } - mousedata.deltaz = event.wheel.y; - } - break; - } - case SDL_MOUSEMOTION: - { - if (mouse_capture || video_fullscreen) - { - mousedata.deltax += event.motion.xrel; - mousedata.deltay += event.motion.yrel; - } - break; - } - case SDL_MOUSEBUTTONDOWN: - case SDL_MOUSEBUTTONUP: - { - if ((event.button.button == SDL_BUTTON_LEFT) - && !(mouse_capture || video_fullscreen) - && event.button.state == SDL_RELEASED - && mouse_inside) - { - plat_mouse_capture(1); - break; - } - if (mouse_get_buttons() < 3 && event.button.button == SDL_BUTTON_MIDDLE && !video_fullscreen) - { - plat_mouse_capture(0); - break; - } - if (mouse_capture || video_fullscreen) - { - int buttonmask = 0; + case SDL_MOUSEMOTION: + { + if (mouse_capture || video_fullscreen) + mouse_scale(event.motion.xrel, event.motion.yrel); + break; + } + case SDL_MOUSEBUTTONDOWN: + case SDL_MOUSEBUTTONUP: + { + if (!dopause && (event.button.button == SDL_BUTTON_LEFT) + && !(mouse_capture || video_fullscreen) + && event.button.state == SDL_RELEASED + && mouse_inside) { + plat_mouse_capture(1); + break; + } + if (mouse_get_buttons() < 3 && event.button.button == SDL_BUTTON_MIDDLE && !video_fullscreen) { + plat_mouse_capture(0); + break; + } + if (mouse_capture || video_fullscreen) { + int buttonmask = 0; - switch(event.button.button) - { - case SDL_BUTTON_LEFT: - buttonmask = 1; - break; - case SDL_BUTTON_RIGHT: - buttonmask = 2; - break; - case SDL_BUTTON_MIDDLE: - buttonmask = 4; + switch (event.button.button) { + case SDL_BUTTON_LEFT: + buttonmask = 1; + break; + case SDL_BUTTON_RIGHT: + buttonmask = 2; + break; + case SDL_BUTTON_MIDDLE: + buttonmask = 4; + break; + } + if (event.button.state == SDL_PRESSED) + mouse_set_buttons_ex(mouse_get_buttons_ex() | buttonmask); + else + mouse_set_buttons_ex(mouse_get_buttons_ex() & ~buttonmask); + } break; } - if (event.button.state == SDL_PRESSED) + case SDL_RENDER_DEVICE_RESET: + case SDL_RENDER_TARGETS_RESET: { - mousedata.mousebuttons |= buttonmask; + sdl_reinit_texture(); + break; + } + case SDL_KEYDOWN: + case SDL_KEYUP: + { + uint16_t xtkey = 0; + switch (event.key.keysym.scancode) { + default: + xtkey = sdl_to_xt[event.key.keysym.scancode]; + break; + } + keyboard_input(event.key.state == SDL_PRESSED, xtkey); } - else mousedata.mousebuttons &= ~buttonmask; - } - break; - } - case SDL_RENDER_DEVICE_RESET: - case SDL_RENDER_TARGETS_RESET: - { - sdl_reinit_texture(); - break; - } - case SDL_KEYDOWN: - case SDL_KEYUP: - { - uint16_t xtkey = 0; - switch(event.key.keysym.scancode) - { - default: - xtkey = sdl_to_xt[event.key.keysym.scancode]; break; - } - keyboard_input(event.key.state == SDL_PRESSED, xtkey); - } - break; - case SDL_WINDOWEVENT: - { - switch (event.window.event) - { - case SDL_WINDOWEVENT_ENTER: - mouse_inside = 1; - break; - case SDL_WINDOWEVENT_LEAVE: - mouse_inside = 0; - break; - } - } + case SDL_WINDOWEVENT: + { + switch (event.window.event) { + case SDL_WINDOWEVENT_ENTER: + mouse_inside = 1; + break; + case SDL_WINDOWEVENT_LEAVE: + mouse_inside = 0; + break; + } + } } } @@ -719,14 +701,8 @@ enum sdl_main_status sdl_main() { return ret; } -void sdl_mouse_capture(int on) { - SDL_SetRelativeMouseMode((SDL_bool)on); -} - -void sdl_mouse_poll() { - mouse_x = mousedata.deltax; - mouse_y = mousedata.deltay; - mouse_z = mousedata.deltaz; - mousedata.deltax = mousedata.deltay = mousedata.deltaz = 0; - mouse_buttons = mousedata.mousebuttons; +void +sdl_mouse_capture(int on) +{ + SDL_SetRelativeMouseMode((SDL_bool) on); } diff --git a/src/qt/qt_sdl.h b/src/qt/qt_sdl.h index 02fd47ddf..f9709c857 100644 --- a/src/qt/qt_sdl.h +++ b/src/qt/qt_sdl.h @@ -1,38 +1,38 @@ /* - * 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. + * 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. + * This file is part of the 86Box distribution. * - * Definitions for the libSDL2 rendering module. + * Definitions for the libSDL2 rendering module. * * * - * Authors: Fred N. van Kempen, - * Michael Drüing, + * Authors: Fred N. van Kempen, + * Michael Drüing, * - * Copyright 2018,2019 Fred N. van Kempen. - * Copyright 2018,2019 Michael Drüing. + * Copyright 2018-2019 Fred N. van Kempen. + * Copyright 2018-2019 Michael Drüing. * - * Redistribution and use in source and binary forms, with - * or without modification, are permitted provided that the - * following conditions are met: + * Redistribution and use in source and binary forms, with + * or without modification, are permitted provided that the + * following conditions are met: * - * 1. Redistributions of source code must retain the entire - * above notice, this list of conditions and the following - * disclaimer. + * 1. Redistributions of source code must retain the entire + * above notice, this list of conditions and the following + * disclaimer. * - * 2. Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the - * following disclaimer in the documentation and/or other - * materials provided with the distribution. + * 2. Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the + * following disclaimer in the documentation and/or other + * materials provided with the distribution. * - * 3. Neither the name of the copyright holder nor the names - * of its contributors may be used to endorse or promote - * products derived from this software without specific - * prior written permission. + * 3. Neither the name of the copyright holder nor the names + * of its contributors may be used to endorse or promote + * products derived from this software without specific + * prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT @@ -47,18 +47,18 @@ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #ifndef WIN_SDL_H -# define WIN_SDL_H +#define WIN_SDL_H -extern void* sdl_win_handle; -extern void sdl_close(void); -extern int sdl_inits(); -extern int sdl_inith(); -extern int sdl_initho(); -extern int sdl_pause(void); -extern void sdl_resize(int w, int h); -extern void sdl_enable(int enable); -extern void sdl_set_fs(int fs); -extern void sdl_reload(void); +extern void *sdl_win_handle; +extern void sdl_close(void); +extern int sdl_inits(); +extern int sdl_inith(); +extern int sdl_initho(); +extern int sdl_pause(void); +extern void sdl_resize(int w, int h); +extern void sdl_enable(int enable); +extern void sdl_set_fs(int fs); +extern void sdl_reload(void); enum sdl_main_status { SdlMainOk, @@ -68,6 +68,5 @@ enum sdl_main_status { extern enum sdl_main_status sdl_main(); extern void sdl_mouse_capture(int on); -extern void sdl_mouse_poll(); -#endif /*WIN_SDL_H*/ +#endif /*WIN_SDL_H*/ diff --git a/src/qt/qt_settings.cpp b/src/qt/qt_settings.cpp index 25493ae2d..c7cb99086 100644 --- a/src/qt/qt_settings.cpp +++ b/src/qt/qt_settings.cpp @@ -1,20 +1,20 @@ /* - * 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. + * 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. + * This file is part of the 86Box distribution. * - * Program settings UI module. + * Program settings UI module. * * * * Authors: Joakim L. Gilje * Cacodemon345 * - * Copyright 2021 Joakim L. Gilje - * Copyright 2021-2022 Cacodemon345 + * Copyright 2021 Joakim L. Gilje + * Copyright 2021-2022 Cacodemon345 */ #include "qt_settings.hpp" #include "ui_qt_settings.h" @@ -35,21 +35,26 @@ #include "qt_harddrive_common.hpp" #include "qt_settings_bus_tracking.hpp" -extern "C" -{ +extern "C" { #include <86box/86box.h> } #include #include #include +#include +#include class SettingsModel : public QAbstractListModel { public: - SettingsModel(QObject* parent) : QAbstractListModel(parent) {} + SettingsModel(QObject *parent) + : QAbstractListModel(parent) + { + } QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const override; - int rowCount(const QModelIndex &parent = QModelIndex()) const override; + int rowCount(const QModelIndex &parent = QModelIndex()) const override; + private: QStringList pages = { "Machine", @@ -79,45 +84,50 @@ private: }; }; -QVariant SettingsModel::data(const QModelIndex &index, int role) const { +QVariant +SettingsModel::data(const QModelIndex &index, int role) const +{ Q_ASSERT(checkIndex(index, QAbstractItemModel::CheckIndexOption::IndexIsValid | QAbstractItemModel::CheckIndexOption::ParentIsInvalid)); switch (role) { - case Qt::DisplayRole: - return tr(pages.at(index.row()).toUtf8().data()); - case Qt::DecorationRole: - return QIcon(QString("%1/%2.ico").arg(ProgSettings::getIconSetPath(), page_icons[index.row()])); - default: - return {}; + case Qt::DisplayRole: + return tr(pages.at(index.row()).toUtf8().data()); + case Qt::DecorationRole: + return QIcon(QString("%1/%2.ico").arg(ProgSettings::getIconSetPath(), page_icons[index.row()])); + default: + return {}; } } -int SettingsModel::rowCount(const QModelIndex &parent) const { +int +SettingsModel::rowCount(const QModelIndex &parent) const +{ (void) parent; return pages.size(); } -Settings* Settings::settings = nullptr;; -Settings::Settings(QWidget *parent) : - QDialog(parent), - ui(new Ui::Settings) +Settings *Settings::settings = nullptr; +; +Settings::Settings(QWidget *parent) + : QDialog(parent) + , ui(new Ui::Settings) { ui->setupUi(this); - - ui->listView->setModel(new SettingsModel(this)); + auto *model = new SettingsModel(this); + ui->listView->setModel(model); Harddrives::busTrackClass = new SettingsBusTracking; - machine = new SettingsMachine(this); - display = new SettingsDisplay(this); - input = new SettingsInput(this); - sound = new SettingsSound(this); - network = new SettingsNetwork(this); - ports = new SettingsPorts(this); - storageControllers = new SettingsStorageControllers(this); - harddisks = new SettingsHarddisks(this); - floppyCdrom = new SettingsFloppyCDROM(this); - otherRemovable = new SettingsOtherRemovable(this); - otherPeripherals = new SettingsOtherPeripherals(this); + machine = new SettingsMachine(this); + display = new SettingsDisplay(this); + input = new SettingsInput(this); + sound = new SettingsSound(this); + network = new SettingsNetwork(this); + ports = new SettingsPorts(this); + storageControllers = new SettingsStorageControllers(this); + harddisks = new SettingsHarddisks(this); + floppyCdrom = new SettingsFloppyCDROM(this); + otherRemovable = new SettingsOtherRemovable(this); + otherPeripherals = new SettingsOtherPeripherals(this); ui->stackedWidget->addWidget(machine); ui->stackedWidget->addWidget(display); @@ -131,18 +141,27 @@ Settings::Settings(QWidget *parent) : ui->stackedWidget->addWidget(otherRemovable); ui->stackedWidget->addWidget(otherPeripherals); - ui->listView->setFixedWidth(ui->listView->sizeHintForColumn(0) + 5); + connect(machine, &SettingsMachine::currentMachineChanged, display, + &SettingsDisplay::onCurrentMachineChanged); + connect(machine, &SettingsMachine::currentMachineChanged, input, + &SettingsInput::onCurrentMachineChanged); + connect(machine, &SettingsMachine::currentMachineChanged, sound, + &SettingsSound::onCurrentMachineChanged); + connect(machine, &SettingsMachine::currentMachineChanged, network, + &SettingsNetwork::onCurrentMachineChanged); + connect(machine, &SettingsMachine::currentMachineChanged, storageControllers, + &SettingsStorageControllers::onCurrentMachineChanged); + connect(machine, &SettingsMachine::currentMachineChanged, otherPeripherals, + &SettingsOtherPeripherals::onCurrentMachineChanged); - connect(machine, &SettingsMachine::currentMachineChanged, display, &SettingsDisplay::onCurrentMachineChanged); - connect(machine, &SettingsMachine::currentMachineChanged, input, &SettingsInput::onCurrentMachineChanged); - connect(machine, &SettingsMachine::currentMachineChanged, sound, &SettingsSound::onCurrentMachineChanged); - connect(machine, &SettingsMachine::currentMachineChanged, network, &SettingsNetwork::onCurrentMachineChanged); - connect(machine, &SettingsMachine::currentMachineChanged, storageControllers, &SettingsStorageControllers::onCurrentMachineChanged); - connect(machine, &SettingsMachine::currentMachineChanged, otherPeripherals, &SettingsOtherPeripherals::onCurrentMachineChanged); + connect(ui->listView->selectionModel(), &QItemSelectionModel::currentChanged, this, + [this](const QModelIndex ¤t, const QModelIndex &previous) { + ui->stackedWidget->setCurrentIndex(current.row()); }); - connect(ui->listView->selectionModel(), &QItemSelectionModel::currentChanged, this, [this](const QModelIndex ¤t, const QModelIndex &previous) { - ui->stackedWidget->setCurrentIndex(current.row()); - }); + ui->listView->setMinimumWidth(ui->listView->sizeHintForColumn(0) + + qApp->style()->pixelMetric(QStyle::PM_ScrollBarExtent)); + + ui->listView->setCurrentIndex(model->index(0, 0)); Settings::settings = this; } @@ -152,10 +171,12 @@ Settings::~Settings() delete ui; delete Harddrives::busTrackClass; Harddrives::busTrackClass = nullptr; - Settings::settings = nullptr; + Settings::settings = nullptr; } -void Settings::save() { +void +Settings::save() +{ machine->save(); display->save(); input->save(); @@ -169,17 +190,19 @@ void Settings::save() { otherPeripherals->save(); } -void Settings::accept() +void +Settings::accept() { - if (confirm_save && !settings_only) - { - QMessageBox questionbox(QMessageBox::Icon::Question, "86Box", QStringLiteral("%1\n\n%2").arg(tr("Do you want to save the settings?"), tr("This will hard reset the emulated machine.")), QMessageBox::Save | QMessageBox::Cancel, this); - QCheckBox *chkbox = new QCheckBox(tr("Don't show this message again")); + if (confirm_save && !settings_only) { + QMessageBox questionbox(QMessageBox::Icon::Question, "86Box", + QStringLiteral("%1\n\n%2").arg(tr("Do you want to save the settings?"), + tr("This will hard reset the emulated machine.")), + QMessageBox::Save | QMessageBox::Cancel, this); + QCheckBox *chkbox = new QCheckBox(tr("Don't show this message again")); questionbox.setCheckBox(chkbox); chkbox->setChecked(!confirm_save); QObject::connect(chkbox, &QCheckBox::stateChanged, [](int state) { - confirm_save = (state == Qt::CheckState::Unchecked); - }); + confirm_save = (state == Qt::CheckState::Unchecked); }); questionbox.exec(); if (questionbox.result() == QMessageBox::Cancel) { confirm_save = true; diff --git a/src/qt/qt_settings.hpp b/src/qt/qt_settings.hpp index 7e0a78cfa..8603c42b6 100644 --- a/src/qt/qt_settings.hpp +++ b/src/qt/qt_settings.hpp @@ -19,32 +19,31 @@ class SettingsFloppyCDROM; class SettingsOtherRemovable; class SettingsOtherPeripherals; -class Settings : public QDialog -{ +class Settings : public QDialog { Q_OBJECT public: - explicit Settings(QWidget *parent = nullptr); + explicit Settings(QWidget *parent = nullptr); ~Settings(); - void save(); + void save(); - static Settings* settings; + static Settings *settings; protected slots: - void accept() override; + void accept() override; private: - Ui::Settings *ui; - SettingsMachine* machine; - SettingsDisplay* display; - SettingsInput* input; - SettingsSound* sound; - SettingsNetwork* network; - SettingsPorts* ports; - SettingsStorageControllers* storageControllers; - SettingsHarddisks* harddisks; - SettingsFloppyCDROM* floppyCdrom; - SettingsOtherRemovable* otherRemovable; - SettingsOtherPeripherals* otherPeripherals; + Ui::Settings *ui; + SettingsMachine *machine; + SettingsDisplay *display; + SettingsInput *input; + SettingsSound *sound; + SettingsNetwork *network; + SettingsPorts *ports; + SettingsStorageControllers *storageControllers; + SettingsHarddisks *harddisks; + SettingsFloppyCDROM *floppyCdrom; + SettingsOtherRemovable *otherRemovable; + SettingsOtherPeripherals *otherPeripherals; }; #endif // QT_SETTINGS_HPP diff --git a/src/qt/qt_settings.ui b/src/qt/qt_settings.ui index 66047cffd..7b4d28bec 100644 --- a/src/qt/qt_settings.ui +++ b/src/qt/qt_settings.ui @@ -6,20 +6,20 @@ 0 0 - 831 - 595 + 800 + 570 - 831 - 595 + 800 + 570 - 831 - 595 + 800 + 570 @@ -29,8 +29,18 @@ + + 0 + + + 0 + - + + + QListView::ListMode + + diff --git a/src/qt/qt_settings_bus_tracking.cpp b/src/qt/qt_settings_bus_tracking.cpp index 41c7990da..4fe112627 100644 --- a/src/qt/qt_settings_bus_tracking.cpp +++ b/src/qt/qt_settings_bus_tracking.cpp @@ -1,274 +1,256 @@ -/* - * 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. - * - * Program settings UI module. - * - * - * - * Authors: Miran Grca - * Cacodemon345 - * - * Copyright 2022 Miran Grca - * Copyright 2022 Cacodemon345 - */ -#include -#include -#include -#include - -#include "86box/hdd.h" -#include "qt_settings_bus_tracking.hpp" - - -SettingsBusTracking::SettingsBusTracking() -{ - int i; - - mfm_tracking = 0x0000000000000000ULL; - esdi_tracking = 0x0000000000000000ULL; - xta_tracking = 0x0000000000000000ULL; - - for (i = 0; i < 8; i++) { - if (i < 4) - ide_tracking[i] = 0x0000000000000000ULL; - - scsi_tracking[i] = 0x0000000000000000ULL; - } -} - - -uint8_t -SettingsBusTracking::next_free_mfm_channel() -{ - if ((mfm_tracking & 0xff00ULL) && !(mfm_tracking & 0x00ffULL)) - return 1; - - if (!(mfm_tracking & 0xff00ULL) && (mfm_tracking & 0x00ffULL)) - return 0; - - return CHANNEL_NONE; -} - - -uint8_t -SettingsBusTracking::next_free_esdi_channel() -{ - if ((esdi_tracking & 0xff00ULL) && !(esdi_tracking & 0x00ffULL)) - return 1; - - if (!(esdi_tracking & 0xff00ULL) && (esdi_tracking & 0x00ffULL)) - return 0; - - return CHANNEL_NONE; -} - - -uint8_t -SettingsBusTracking::next_free_xta_channel() -{ - if ((xta_tracking & 0xff00ULL) && !(xta_tracking & 0x00ffULL)) - return 1; - - if (!(xta_tracking & 0xff00ULL) && (xta_tracking & 0x00ffULL)) - return 0; - - return CHANNEL_NONE; -} - - -uint8_t -SettingsBusTracking::next_free_ide_channel() -{ - int i, element; - uint64_t mask; - uint8_t ret = CHANNEL_NONE; - - for (i = 0; i < 32; i++) { - element = ((i << 3) >> 6); - mask = 0xffULL << ((uint64_t) ((i << 3) & 0x3f)); - - if (!(ide_tracking[element] & mask)) { - ret = (uint8_t) i; - break; - } - } - - return ret; -} - - -uint8_t -SettingsBusTracking::next_free_scsi_id() -{ - int i, element; - uint64_t mask; - uint8_t ret = CHANNEL_NONE; - - for (i = 0; i < 64; i++) { - element = ((i << 3) >> 6); - mask = 0xffULL << ((uint64_t) ((i << 3) & 0x3f)); - - if (!(scsi_tracking[element] & mask)) { - ret = (uint8_t) i; - break; - } - } - - return ret; -} - - -int -SettingsBusTracking::mfm_bus_full() -{ - int i; - uint64_t mask; - uint8_t count = 0; - - for (i = 0; i < 2; i++) { - mask = 0xffULL << ((uint64_t) ((i << 3) & 0x3f)); - - if (mfm_tracking & mask) - count++; - } - - return (count == 2); -} - - -int -SettingsBusTracking::esdi_bus_full() -{ - int i; - uint64_t mask; - uint8_t count = 0; - - for (i = 0; i < 2; i++) { - mask = 0xffULL << ((uint64_t) ((i << 3) & 0x3f)); - - if (esdi_tracking & mask) - count++; - } - - return (count == 2); -} - - -int -SettingsBusTracking::xta_bus_full() -{ - int i; - uint64_t mask; - uint8_t count = 0; - - for (i = 0; i < 2; i++) { - mask = 0xffULL << ((uint64_t) ((i << 3) & 0x3f)); - - if (xta_tracking & mask) - count++; - } - - return (count == 2); -} - - -int -SettingsBusTracking::ide_bus_full() -{ - int i, element; - uint64_t mask; - uint8_t count = 0; - - for (i = 0; i < 32; i++) { - element = ((i << 3) >> 6); - mask = 0xffULL << ((uint64_t) ((i << 3) & 0x3f)); - - if (ide_tracking[element] & mask) - count++; - } - - return (count == 32); -} - - -int -SettingsBusTracking::scsi_bus_full() -{ - int i, element; - uint64_t mask; - uint8_t count = 0; - - for (i = 0; i < 64; i++) { - element = ((i << 3) >> 6); - mask = 0xffULL << ((uint64_t) ((i << 3) & 0x3f)); - - if (scsi_tracking[element] & mask) - count++; - } - - return (count == 64); -} - - -void -SettingsBusTracking::device_track(int set, uint8_t dev_type, int bus, int channel) -{ - int i, element; - uint64_t mask; - uint8_t count = 0; - - switch (bus) { - case HDD_BUS_MFM: - mask = ((uint64_t) dev_type) << ((uint64_t) ((channel << 3) & 0x3f)); - - if (set) - mfm_tracking |= mask; - else - mfm_tracking &= ~mask; - break; - - case HDD_BUS_ESDI: - mask = ((uint64_t) dev_type) << ((uint64_t) ((channel << 3) & 0x3f)); - - if (set) - esdi_tracking |= mask; - else - esdi_tracking &= ~mask; - break; - - case HDD_BUS_XTA: - mask = ((uint64_t) dev_type) << ((uint64_t) ((channel << 3) & 0x3f)); - - if (set) - xta_tracking |= mask; - else - xta_tracking &= ~mask; - break; - - case HDD_BUS_IDE: - case HDD_BUS_ATAPI: - element = ((channel << 3) >> 6); - mask = ((uint64_t) dev_type) << ((uint64_t) ((channel << 3) & 0x3f)); - - if (set) - ide_tracking[element] |= mask; - else - ide_tracking[element] &= ~mask; - break; - - case HDD_BUS_SCSI: - element = ((channel << 3) >> 6); - mask = ((uint64_t) dev_type) << ((uint64_t) ((channel << 3) & 0x3f)); - - if (set) - scsi_tracking[element] |= mask; - else - scsi_tracking[element] &= ~mask; - break; - } -} +/* + * 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. + * + * Program settings UI module. + * + * + * + * Authors: Miran Grca + * Cacodemon345 + * + * Copyright 2022 Miran Grca + * Copyright 2022 Cacodemon345 + */ +#include +#include +#include +#include + +#include "86box/hdd.h" +#include "qt_settings_bus_tracking.hpp" + +SettingsBusTracking::SettingsBusTracking() +{ + mfm_tracking = 0x0000000000000000ULL; + esdi_tracking = 0x0000000000000000ULL; + xta_tracking = 0x0000000000000000ULL; + + for (uint8_t i = 0; i < 8; i++) { + if (i < 4) + ide_tracking[i] = 0x0000000000000000ULL; + + scsi_tracking[i] = 0x0000000000000000ULL; + } +} + +uint8_t +SettingsBusTracking::next_free_mfm_channel() +{ + if ((mfm_tracking & 0xff00ULL) && !(mfm_tracking & 0x00ffULL)) + return 1; + + if (!(mfm_tracking & 0xff00ULL) && (mfm_tracking & 0x00ffULL)) + return 0; + + return CHANNEL_NONE; +} + +uint8_t +SettingsBusTracking::next_free_esdi_channel() +{ + if ((esdi_tracking & 0xff00ULL) && !(esdi_tracking & 0x00ffULL)) + return 1; + + if (!(esdi_tracking & 0xff00ULL) && (esdi_tracking & 0x00ffULL)) + return 0; + + return CHANNEL_NONE; +} + +uint8_t +SettingsBusTracking::next_free_xta_channel() +{ + if ((xta_tracking & 0xff00ULL) && !(xta_tracking & 0x00ffULL)) + return 1; + + if (!(xta_tracking & 0xff00ULL) && (xta_tracking & 0x00ffULL)) + return 0; + + return CHANNEL_NONE; +} + +uint8_t +SettingsBusTracking::next_free_ide_channel() +{ + int element; + uint64_t mask; + uint8_t ret = CHANNEL_NONE; + + for (uint8_t i = 0; i < 32; i++) { + element = ((i << 3) >> 6); + mask = 0xffULL << ((uint64_t) ((i << 3) & 0x3f)); + + if (!(ide_tracking[element] & mask)) { + ret = (uint8_t) i; + break; + } + } + + return ret; +} + +uint8_t +SettingsBusTracking::next_free_scsi_id() +{ + int element; + uint64_t mask; + uint8_t ret = CHANNEL_NONE; + + for (uint8_t i = 0; i < 64; i++) { + element = ((i << 3) >> 6); + mask = 0xffULL << ((uint64_t) ((i << 3) & 0x3f)); + + if (!(scsi_tracking[element] & mask)) { + ret = (uint8_t) i; + break; + } + } + + return ret; +} + +int +SettingsBusTracking::mfm_bus_full() +{ + uint64_t mask; + uint8_t count = 0; + + for (uint8_t i = 0; i < 2; i++) { + mask = 0xffULL << ((uint64_t) ((i << 3) & 0x3f)); + + if (mfm_tracking & mask) + count++; + } + + return (count == 2); +} + +int +SettingsBusTracking::esdi_bus_full() +{ + uint64_t mask; + uint8_t count = 0; + + for (uint8_t i = 0; i < 2; i++) { + mask = 0xffULL << ((uint64_t) ((i << 3) & 0x3f)); + + if (esdi_tracking & mask) + count++; + } + + return (count == 2); +} + +int +SettingsBusTracking::xta_bus_full() +{ + uint64_t mask; + uint8_t count = 0; + + for (uint8_t i = 0; i < 2; i++) { + mask = 0xffULL << ((uint64_t) ((i << 3) & 0x3f)); + + if (xta_tracking & mask) + count++; + } + + return (count == 2); +} + +int +SettingsBusTracking::ide_bus_full() +{ + int element; + uint64_t mask; + uint8_t count = 0; + + for (uint8_t i = 0; i < 32; i++) { + element = ((i << 3) >> 6); + mask = 0xffULL << ((uint64_t) ((i << 3) & 0x3f)); + + if (ide_tracking[element] & mask) + count++; + } + + return (count == 32); +} + +int +SettingsBusTracking::scsi_bus_full() +{ + int element; + uint64_t mask; + uint8_t count = 0; + + for (uint8_t i = 0; i < 64; i++) { + element = ((i << 3) >> 6); + mask = 0xffULL << ((uint64_t) ((i << 3) & 0x3f)); + + if (scsi_tracking[element] & mask) + count++; + } + + return (count == 64); +} + +void +SettingsBusTracking::device_track(int set, uint8_t dev_type, int bus, int channel) +{ + int element; + uint64_t mask; + + switch (bus) { + case HDD_BUS_MFM: + mask = ((uint64_t) dev_type) << ((uint64_t) ((channel << 3) & 0x3f)); + + if (set) + mfm_tracking |= mask; + else + mfm_tracking &= ~mask; + break; + + case HDD_BUS_ESDI: + mask = ((uint64_t) dev_type) << ((uint64_t) ((channel << 3) & 0x3f)); + + if (set) + esdi_tracking |= mask; + else + esdi_tracking &= ~mask; + break; + + case HDD_BUS_XTA: + mask = ((uint64_t) dev_type) << ((uint64_t) ((channel << 3) & 0x3f)); + + if (set) + xta_tracking |= mask; + else + xta_tracking &= ~mask; + break; + + case HDD_BUS_IDE: + case HDD_BUS_ATAPI: + element = ((channel << 3) >> 6); + mask = ((uint64_t) dev_type) << ((uint64_t) ((channel << 3) & 0x3f)); + + if (set) + ide_tracking[element] |= mask; + else + ide_tracking[element] &= ~mask; + break; + + case HDD_BUS_SCSI: + element = ((channel << 3) >> 6); + mask = ((uint64_t) dev_type) << ((uint64_t) ((channel << 3) & 0x3f)); + + if (set) + scsi_tracking[element] |= mask; + else + scsi_tracking[element] &= ~mask; + break; + } +} diff --git a/src/qt/qt_settings_bus_tracking.hpp b/src/qt/qt_settings_bus_tracking.hpp index 0272b4359..3ec61dfb7 100644 --- a/src/qt/qt_settings_bus_tracking.hpp +++ b/src/qt/qt_settings_bus_tracking.hpp @@ -1,63 +1,62 @@ -#ifndef QT_SETTINGS_BUS_TRACKING_HPP -#define QT_SETTINGS_BUS_TRACKING_HPP - -#include - -#define TRACK_CLEAR 0 -#define TRACK_SET 1 - -#define DEV_HDD 0x01 -#define DEV_CDROM 0x02 -#define DEV_ZIP 0x04 -#define DEV_MO 0x08 - -#define BUS_MFM 0 -#define BUS_ESDI 1 -#define BUS_XTA 2 -#define BUS_IDE 3 -#define BUS_SCSI 4 - -#define CHANNEL_NONE 0xff - -namespace Ui { -class SettingsBusTracking; -} - -class SettingsBusTracking -{ -public: - explicit SettingsBusTracking(); - ~SettingsBusTracking() = default; - - /* These return 0xff is none is free. */ - uint8_t next_free_mfm_channel(); - uint8_t next_free_esdi_channel(); - uint8_t next_free_xta_channel(); - uint8_t next_free_ide_channel(); - uint8_t next_free_scsi_id(); - - int mfm_bus_full(); - int esdi_bus_full(); - int xta_bus_full(); - int ide_bus_full(); - int scsi_bus_full(); - - /* Set: 0 = Clear the device from the tracking, 1 = Set the device on the tracking. - Device type: 1 = Hard Disk, 2 = CD-ROM, 4 = ZIP, 8 = Magneto-Optical. - Bus: 0 = MFM, 1 = ESDI, 2 = XTA, 3 = IDE, 4 = SCSI. */ - void device_track(int set, uint8_t dev_type, int bus, int channel); - -private: - /* 1 channel, 2 devices per channel, 8 bits per device = 16 bits. */ - uint64_t mfm_tracking{0}; - /* 1 channel, 2 devices per channel, 8 bits per device = 16 bits. */ - uint64_t esdi_tracking{0}; - /* 1 channel, 2 devices per channel, 8 bits per device = 16 bits. */ - uint64_t xta_tracking{0}; - /* 16 channels (prepatation for that weird IDE card), 2 devices per channel, 8 bits per device = 256 bits. */ - uint64_t ide_tracking[4]{0, 0, 0, 0}; - /* 4 buses, 16 devices per bus, 8 bits per device (future-proofing) = 512 bits. */ - uint64_t scsi_tracking[8]{0, 0, 0, 0, 0, 0, 0, 0}; -}; - -#endif // QT_SETTINGS_BUS_TRACKING_HPP +#ifndef QT_SETTINGS_BUS_TRACKING_HPP +#define QT_SETTINGS_BUS_TRACKING_HPP + +#include + +#define TRACK_CLEAR 0 +#define TRACK_SET 1 + +#define DEV_HDD 0x01 +#define DEV_CDROM 0x02 +#define DEV_ZIP 0x04 +#define DEV_MO 0x08 + +#define BUS_MFM 0 +#define BUS_ESDI 1 +#define BUS_XTA 2 +#define BUS_IDE 3 +#define BUS_SCSI 4 + +#define CHANNEL_NONE 0xff + +namespace Ui { +class SettingsBusTracking; +} + +class SettingsBusTracking { +public: + explicit SettingsBusTracking(); + ~SettingsBusTracking() = default; + + /* These return 0xff is none is free. */ + uint8_t next_free_mfm_channel(); + uint8_t next_free_esdi_channel(); + uint8_t next_free_xta_channel(); + uint8_t next_free_ide_channel(); + uint8_t next_free_scsi_id(); + + int mfm_bus_full(); + int esdi_bus_full(); + int xta_bus_full(); + int ide_bus_full(); + int scsi_bus_full(); + + /* Set: 0 = Clear the device from the tracking, 1 = Set the device on the tracking. + Device type: 1 = Hard Disk, 2 = CD-ROM, 4 = ZIP, 8 = Magneto-Optical. + Bus: 0 = MFM, 1 = ESDI, 2 = XTA, 3 = IDE, 4 = SCSI. */ + void device_track(int set, uint8_t dev_type, int bus, int channel); + +private: + /* 1 channel, 2 devices per channel, 8 bits per device = 16 bits. */ + uint64_t mfm_tracking { 0 }; + /* 1 channel, 2 devices per channel, 8 bits per device = 16 bits. */ + uint64_t esdi_tracking { 0 }; + /* 1 channel, 2 devices per channel, 8 bits per device = 16 bits. */ + uint64_t xta_tracking { 0 }; + /* 16 channels (prepatation for that weird IDE card), 2 devices per channel, 8 bits per device = 256 bits. */ + uint64_t ide_tracking[4] { 0, 0, 0, 0 }; + /* 4 buses, 16 devices per bus, 8 bits per device (future-proofing) = 512 bits. */ + uint64_t scsi_tracking[8] { 0, 0, 0, 0, 0, 0, 0, 0 }; +}; + +#endif // QT_SETTINGS_BUS_TRACKING_HPP diff --git a/src/qt/qt_settingsdisplay.cpp b/src/qt/qt_settingsdisplay.cpp index 394033a47..fcb70f8c5 100644 --- a/src/qt/qt_settingsdisplay.cpp +++ b/src/qt/qt_settingsdisplay.cpp @@ -1,18 +1,18 @@ /* - * 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. + * 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. + * This file is part of the 86Box distribution. * - * Display settings UI module. + * Display settings UI module. * * * - * Authors: Joakim L. Gilje + * Authors: Joakim L. Gilje * - * Copyright 2021 Joakim L. Gilje + * Copyright 2021 Joakim L. Gilje */ #include "qt_settingsdisplay.hpp" #include "ui_qt_settingsdisplay.h" @@ -24,17 +24,20 @@ extern "C" { #include <86box/device.h> #include <86box/machine.h> #include <86box/video.h> +#include <86box/vid_xga_device.h> } #include "qt_deviceconfig.hpp" #include "qt_models_common.hpp" -SettingsDisplay::SettingsDisplay(QWidget *parent) : - QWidget(parent), - ui(new Ui::SettingsDisplay) +SettingsDisplay::SettingsDisplay(QWidget *parent) + : QWidget(parent) + , ui(new Ui::SettingsDisplay) { ui->setupUi(this); + videoCard[0] = gfxcard[0]; + videoCard[1] = gfxcard[1]; onCurrentMachineChanged(machine); } @@ -43,19 +46,27 @@ SettingsDisplay::~SettingsDisplay() delete ui; } -void SettingsDisplay::save() { - gfxcard = ui->comboBoxVideo->currentData().toInt(); - voodoo_enabled = ui->checkBoxVoodoo->isChecked() ? 1 : 0; +void +SettingsDisplay::save() +{ + gfxcard[0] = ui->comboBoxVideo->currentData().toInt(); + gfxcard[1] = ui->comboBoxVideoSecondary->currentData().toInt(); + voodoo_enabled = ui->checkBoxVoodoo->isChecked() ? 1 : 0; + ibm8514_standalone_enabled = ui->checkBox8514->isChecked() ? 1 : 0; + xga_standalone_enabled = ui->checkBoxXga->isChecked() ? 1 : 0; } -void SettingsDisplay::onCurrentMachineChanged(int machineId) { +void +SettingsDisplay::onCurrentMachineChanged(int machineId) +{ // win_settings_video_proc, WM_INITDIALOG this->machineId = machineId; + auto curVideoCard = videoCard[0]; - auto* model = ui->comboBoxVideo->model(); - auto removeRows = model->rowCount(); + auto *model = ui->comboBoxVideo->model(); + auto removeRows = model->rowCount(); - int c = 0; + int c = 0; int selectedRow = 0; while (true) { /* Skip "internal" if machine doesn't have it. */ @@ -64,16 +75,15 @@ void SettingsDisplay::onCurrentMachineChanged(int machineId) { continue; } - const device_t* video_dev = video_card_getdevice(c); - QString name = DeviceConfig::DeviceName(video_dev, video_get_internal_name(c), 1); + const device_t *video_dev = video_card_getdevice(c); + QString name = DeviceConfig::DeviceName(video_dev, video_get_internal_name(c), 1); if (name.isEmpty()) { break; } - if (video_card_available(c) && - device_is_valid(video_dev, machineId)) { + if (video_card_available(c) && device_is_valid(video_dev, machineId)) { int row = Models::AddEntry(model, name, c); - if (c == gfxcard) { + if (c == curVideoCard) { selectedRow = row - removeRows; } } @@ -84,37 +94,146 @@ void SettingsDisplay::onCurrentMachineChanged(int machineId) { if (machine_has_flags(machineId, MACHINE_VIDEO_ONLY) > 0) { ui->comboBoxVideo->setEnabled(false); + ui->comboBoxVideoSecondary->setEnabled(false); + ui->pushButtonConfigureSecondary->setEnabled(false); selectedRow = 1; } else { ui->comboBoxVideo->setEnabled(true); + ui->comboBoxVideoSecondary->setEnabled(true); + ui->pushButtonConfigureSecondary->setEnabled(true); } ui->comboBoxVideo->setCurrentIndex(selectedRow); + if (gfxcard[1] == 0) + ui->pushButtonConfigureSecondary->setEnabled(false); } -void SettingsDisplay::on_pushButtonConfigure_clicked() { - auto* device = video_card_getdevice(ui->comboBoxVideo->currentData().toInt()); - DeviceConfig::ConfigureDevice(device, 0, qobject_cast(Settings::settings)); +void +SettingsDisplay::on_pushButtonConfigure_clicked() +{ + int videoCard = ui->comboBoxVideo->currentData().toInt(); + auto *device = video_card_getdevice(videoCard); + if (videoCard == VID_INTERNAL) + device = machine_get_vid_device(machineId); + DeviceConfig::ConfigureDevice(device, 0, qobject_cast(Settings::settings)); } -void SettingsDisplay::on_pushButtonConfigureVoodoo_clicked() { - DeviceConfig::ConfigureDevice(&voodoo_device, 0, qobject_cast(Settings::settings)); +void +SettingsDisplay::on_pushButtonConfigureVoodoo_clicked() +{ + DeviceConfig::ConfigureDevice(&voodoo_device, 0, qobject_cast(Settings::settings)); } -void SettingsDisplay::on_comboBoxVideo_currentIndexChanged(int index) { +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)); + } +} + +void +SettingsDisplay::on_comboBoxVideo_currentIndexChanged(int index) +{ if (index < 0) { return; } - int videoCard = ui->comboBoxVideo->currentData().toInt(); - ui->pushButtonConfigure->setEnabled(video_card_has_config(videoCard) > 0); - + auto curVideoCard_2 = videoCard[1]; + videoCard[0] = ui->comboBoxVideo->currentData().toInt(); + if (videoCard[0] == VID_INTERNAL) + ui->pushButtonConfigure->setEnabled(machine_has_flags(machineId, MACHINE_VIDEO) && + device_has_config(machine_get_vid_device(machineId))); + else + 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) { ui->checkBoxVoodoo->setChecked(voodoo_enabled); } ui->pushButtonConfigureVoodoo->setEnabled(machineHasPci && ui->checkBoxVoodoo->isChecked()); + + bool machineHasIsa16 = machine_has_bus(machineId, MACHINE_BUS_ISA16) > 0; + bool machineHasMca = machine_has_bus(machineId, MACHINE_BUS_MCA) > 0; + + bool videoCardHas8514 = ((videoCard[0] == VID_INTERNAL) ? machine_has_flags(machineId, MACHINE_VIDEO_8514A) : (video_card_get_flags(videoCard[0]) == VIDEO_FLAG_TYPE_8514)); + bool videoCardHasXga = ((videoCard[0] == VID_INTERNAL) ? machine_has_flags(machineId, MACHINE_VIDEO_XGA) : (video_card_get_flags(videoCard[0]) == VIDEO_FLAG_TYPE_XGA)); + + ui->checkBox8514->setEnabled((machineHasIsa16 || machineHasMca) && !videoCardHas8514); + if (machineHasIsa16 || machineHasMca) + ui->checkBox8514->setChecked(ibm8514_standalone_enabled && !videoCardHas8514); + + ui->checkBoxXga->setEnabled((machineHasIsa16 || machineHasMca) && !videoCardHasXga); + if (machineHasIsa16 || machineHasMca) + ui->checkBoxXga->setChecked(xga_standalone_enabled && !videoCardHasXga); + + ui->pushButtonConfigureXga->setEnabled((machineHasIsa16 || machineHasMca) && ui->checkBoxXga->isChecked() && !videoCardHasXga); + + int c = 2; + + ui->comboBoxVideoSecondary->clear(); + ui->comboBoxVideoSecondary->addItem(QObject::tr("None"), 0); + + ui->comboBoxVideoSecondary->setCurrentIndex(0); + // TODO: Implement support for selecting non-MDA secondary cards properly when MDA cards are the primary ones. + if (video_card_get_flags(videoCard[0]) == VIDEO_FLAG_TYPE_MDA) { + ui->comboBoxVideoSecondary->setCurrentIndex(0); + return; + } + while (true) { + const device_t *video_dev = video_card_getdevice(c); + QString name = DeviceConfig::DeviceName(video_dev, video_get_internal_name(c), 1); + if (name.isEmpty()) { + break; + } + + int primaryFlags = video_card_get_flags(videoCard[0]); + int secondaryFlags = video_card_get_flags(c); + if (video_card_available(c) + && device_is_valid(video_dev, machineId) + && !((secondaryFlags == primaryFlags) && (secondaryFlags != VIDEO_FLAG_TYPE_SPECIAL)) + && !(((primaryFlags == VIDEO_FLAG_TYPE_8514) || (primaryFlags == VIDEO_FLAG_TYPE_XGA)) && (secondaryFlags != VIDEO_FLAG_TYPE_MDA) && (secondaryFlags != VIDEO_FLAG_TYPE_SPECIAL)) + && !((primaryFlags != VIDEO_FLAG_TYPE_MDA) && (primaryFlags != VIDEO_FLAG_TYPE_SPECIAL) && ((secondaryFlags == VIDEO_FLAG_TYPE_8514) || (secondaryFlags == VIDEO_FLAG_TYPE_XGA)))) { + ui->comboBoxVideoSecondary->addItem(name, c); + if (c == curVideoCard_2) + ui->comboBoxVideoSecondary->setCurrentIndex(ui->comboBoxVideoSecondary->count() - 1); + } + + c++; + } + + if ((videoCard[1] == 0) || (machine_has_flags(machineId, MACHINE_VIDEO_ONLY) > 0)) { + ui->comboBoxVideoSecondary->setCurrentIndex(0); + ui->pushButtonConfigureSecondary->setEnabled(false); + } } -void SettingsDisplay::on_checkBoxVoodoo_stateChanged(int state) { +void +SettingsDisplay::on_checkBoxVoodoo_stateChanged(int state) +{ ui->pushButtonConfigureVoodoo->setEnabled(state == Qt::Checked); } + +void +SettingsDisplay::on_checkBoxXga_stateChanged(int state) +{ + ui->pushButtonConfigureXga->setEnabled(state == Qt::Checked); +} + +void +SettingsDisplay::on_comboBoxVideoSecondary_currentIndexChanged(int index) +{ + if (index < 0) { + ui->pushButtonConfigureSecondary->setEnabled(false); + return; + } + videoCard[1] = ui->comboBoxVideoSecondary->currentData().toInt(); + ui->pushButtonConfigureSecondary->setEnabled(index != 0 && video_card_has_config(videoCard[1]) > 0); +} + +void +SettingsDisplay::on_pushButtonConfigureSecondary_clicked() +{ + auto *device = video_card_getdevice(ui->comboBoxVideoSecondary->currentData().toInt()); + DeviceConfig::ConfigureDevice(device, 0, qobject_cast(Settings::settings)); +} diff --git a/src/qt/qt_settingsdisplay.hpp b/src/qt/qt_settingsdisplay.hpp index 768f40311..8331bbb5b 100644 --- a/src/qt/qt_settingsdisplay.hpp +++ b/src/qt/qt_settingsdisplay.hpp @@ -7,8 +7,7 @@ namespace Ui { class SettingsDisplay; } -class SettingsDisplay : public QWidget -{ +class SettingsDisplay : public QWidget { Q_OBJECT public: @@ -20,15 +19,24 @@ public: public slots: void onCurrentMachineChanged(int machineId); +private slots: + void on_pushButtonConfigureSecondary_clicked(); + +private slots: + void on_comboBoxVideoSecondary_currentIndexChanged(int index); + private slots: void on_checkBoxVoodoo_stateChanged(int state); + void on_checkBoxXga_stateChanged(int state); void on_comboBoxVideo_currentIndexChanged(int index); void on_pushButtonConfigureVoodoo_clicked(); + void on_pushButtonConfigureXga_clicked(); void on_pushButtonConfigure_clicked(); private: Ui::SettingsDisplay *ui; - int machineId = 0; + int machineId = 0; + int videoCard[2] = { 0, 0 }; }; #endif // QT_SETTINGSDISPLAY_HPP diff --git a/src/qt/qt_settingsdisplay.ui b/src/qt/qt_settingsdisplay.ui index 2ed153a21..dfda43c40 100644 --- a/src/qt/qt_settingsdisplay.ui +++ b/src/qt/qt_settingsdisplay.ui @@ -13,7 +13,7 @@ Form - + 0 @@ -26,20 +26,10 @@ 0 - - - - - - - Video: - - - - + - + 0 0 @@ -49,21 +39,101 @@ - + + + + XGA + + + + + + + + 0 + 0 + + + + Video: + + + + + + + 30 + + + + 0 + 0 + + + + + Configure - + + + + + 0 + 0 + + + + Video #2: + + + + + + + 8514/A + + + + Voodoo Graphics - + + + + Configure + + + + + + + Configure + + + + + + + 30 + + + + 0 + 0 + + + + + Qt::Vertical diff --git a/src/qt/qt_settingsfloppycdrom.cpp b/src/qt/qt_settingsfloppycdrom.cpp index ba2c1d601..988f9e856 100644 --- a/src/qt/qt_settingsfloppycdrom.cpp +++ b/src/qt/qt_settingsfloppycdrom.cpp @@ -1,25 +1,34 @@ /* - * 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. + * 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. + * This file is part of the 86Box distribution. * - * Floppy/CD-ROM devices configuration UI module. + * Floppy/CD-ROM devices configuration UI module. * * * - * Authors: Joakim L. Gilje + * Authors: Joakim L. Gilje * Cacodemon345 * - * Copyright 2021-2022 Cacodemon345 - * Copyright 2021 Joakim L. Gilje + * Copyright 2021-2022 Cacodemon345 + * Copyright 2021 Joakim L. Gilje */ #include "qt_settingsfloppycdrom.hpp" #include "ui_qt_settingsfloppycdrom.h" extern "C" { +#include +#include +#include +#include +#include +#include +#include +#define HAVE_STDARG_H +#include <86box/86box.h> #include <86box/timer.h> #include <86box/fdd.h> #include <86box/cdrom.h> @@ -32,31 +41,36 @@ extern "C" { #include "qt_settings_bus_tracking.hpp" #include "qt_progsettings.hpp" -static void setFloppyType(QAbstractItemModel* model, const QModelIndex& idx, int type) { +static void +setFloppyType(QAbstractItemModel *model, const QModelIndex &idx, int type) +{ QIcon icon; - if (type == 0) { + if (type == 0) icon = ProgSettings::loadIcon("/floppy_disabled.ico"); - } else if (type >= 1 && type <= 6) { + else if (type >= 1 && type <= 6) icon = ProgSettings::loadIcon("/floppy_525.ico"); - } else { + else icon = ProgSettings::loadIcon("/floppy_35.ico"); - } model->setData(idx, QObject::tr(fdd_getname(type))); model->setData(idx, type, Qt::UserRole); model->setData(idx, icon, Qt::DecorationRole); } -static void setCDROMBus(QAbstractItemModel* model, const QModelIndex& idx, uint8_t bus, uint8_t channel) { +static void +setCDROMBus(QAbstractItemModel *model, const QModelIndex &idx, uint8_t bus, uint8_t channel) +{ QIcon icon; + switch (bus) { - case CDROM_BUS_DISABLED: - icon = ProgSettings::loadIcon("/cdrom_disabled.ico"); - break; - case CDROM_BUS_ATAPI: - case CDROM_BUS_SCSI: - icon = ProgSettings::loadIcon("/cdrom.ico"); - break; + case CDROM_BUS_DISABLED: + icon = ProgSettings::loadIcon("/cdrom_disabled.ico"); + break; + case CDROM_BUS_ATAPI: + case CDROM_BUS_SCSI: + case CDROM_BUS_MITSUMI: + icon = ProgSettings::loadIcon("/cdrom.ico"); + break; } auto i = idx.siblingAtColumn(0); @@ -66,25 +80,39 @@ static void setCDROMBus(QAbstractItemModel* model, const QModelIndex& idx, uint8 model->setData(i, icon, Qt::DecorationRole); } -static void setCDROMSpeed(QAbstractItemModel* model, const QModelIndex& idx, uint8_t speed) { +static void +setCDROMSpeed(QAbstractItemModel *model, const QModelIndex &idx, uint8_t speed) +{ + if (!speed) + speed = 8; auto i = idx.siblingAtColumn(1); model->setData(i, QString("%1x").arg(speed)); model->setData(i, speed, Qt::UserRole); } -SettingsFloppyCDROM::SettingsFloppyCDROM(QWidget *parent) : - QWidget(parent), - ui(new Ui::SettingsFloppyCDROM) +static void +setCDROMType(QAbstractItemModel *model, const QModelIndex &idx, int type) +{ + auto i = idx.siblingAtColumn(2); + if (idx.siblingAtColumn(0).data(Qt::UserRole).toUInt() == CDROM_BUS_DISABLED) + model->setData(i, QCoreApplication::translate("", "None")); + else if (idx.siblingAtColumn(0).data(Qt::UserRole).toUInt() != CDROM_BUS_MITSUMI) + model->setData(i, QObject::tr(cdrom_getname(type))); + model->setData(i, type, Qt::UserRole); +} + +SettingsFloppyCDROM::SettingsFloppyCDROM(QWidget *parent) + : QWidget(parent) + , ui(new Ui::SettingsFloppyCDROM) { ui->setupUi(this); - auto* model = ui->comboBoxFloppyType->model(); - int i = 0; + auto *model = ui->comboBoxFloppyType->model(); + int i = 0; while (true) { QString name = tr(fdd_getname(i)); - if (name.isEmpty()) { + if (name.isEmpty()) break; - } Models::AddEntry(model, name, i); ++i; @@ -99,8 +127,8 @@ SettingsFloppyCDROM::SettingsFloppyCDROM(QWidget *parent) : model->insertRows(0, FDD_NUM); /* Floppy drives category */ for (int i = 0; i < FDD_NUM; i++) { - auto idx = model->index(i, 0); - int type = fdd_get_type(i); + auto idx = model->index(i, 0); + int type = fdd_get_type(i); setFloppyType(model, idx, type); model->setData(idx.siblingAtColumn(1), fdd_get_turbo(i) > 0 ? tr("On") : tr("Off")); model->setData(idx.siblingAtColumn(2), fdd_get_check_bpb(i) > 0 ? tr("On") : tr("Off")); @@ -109,32 +137,67 @@ SettingsFloppyCDROM::SettingsFloppyCDROM(QWidget *parent) : ui->tableViewFloppy->resizeColumnsToContents(); ui->tableViewFloppy->horizontalHeader()->setSectionResizeMode(0, QHeaderView::Stretch); - connect(ui->tableViewFloppy->selectionModel(), &QItemSelectionModel::currentRowChanged, this, &SettingsFloppyCDROM::onFloppyRowChanged); + connect(ui->tableViewFloppy->selectionModel(), &QItemSelectionModel::currentRowChanged, + this, &SettingsFloppyCDROM::onFloppyRowChanged); ui->tableViewFloppy->setCurrentIndex(model->index(0, 0)); - Harddrives::populateRemovableBuses(ui->comboBoxBus->model()); model = ui->comboBoxSpeed->model(); - for (int i = 0; i < 72; i++) { + for (int i = 0; i < 72; i++) Models::AddEntry(model, QString("%1x").arg(i + 1), i + 1); - } - model = new QStandardItemModel(0, 2, this); + model = new QStandardItemModel(0, 3, this); ui->tableViewCDROM->setModel(model); model->setHeaderData(0, Qt::Horizontal, tr("Bus")); model->setHeaderData(1, Qt::Horizontal, tr("Speed")); + model->setHeaderData(2, Qt::Horizontal, tr("Type")); model->insertRows(0, CDROM_NUM); for (int i = 0; i < CDROM_NUM; i++) { auto idx = model->index(i, 0); + int type = cdrom_get_type(i); setCDROMBus(model, idx, cdrom[i].bus_type, cdrom[i].res); setCDROMSpeed(model, idx.siblingAtColumn(1), cdrom[i].speed); - Harddrives::busTrackClass->device_track(1, DEV_CDROM, cdrom[i].bus_type, cdrom[i].bus_type == CDROM_BUS_ATAPI ? cdrom[i].ide_channel : cdrom[i].scsi_device_id); + setCDROMType(model, idx.siblingAtColumn(2), type); + if (cdrom[i].bus_type == CDROM_BUS_ATAPI) + Harddrives::busTrackClass->device_track(1, DEV_CDROM, cdrom[i].bus_type, cdrom[i].ide_channel); + else if (cdrom[i].bus_type == CDROM_BUS_SCSI) + Harddrives::busTrackClass->device_track(1, DEV_CDROM, cdrom[i].bus_type, + cdrom[i].scsi_device_id); + else if (cdrom[i].bus_type == CDROM_BUS_MITSUMI) + Harddrives::busTrackClass->device_track(1, DEV_CDROM, cdrom[i].bus_type, 0); } ui->tableViewCDROM->resizeColumnsToContents(); ui->tableViewCDROM->horizontalHeader()->setSectionResizeMode(0, QHeaderView::Stretch); - connect(ui->tableViewCDROM->selectionModel(), &QItemSelectionModel::currentRowChanged, this, &SettingsFloppyCDROM::onCDROMRowChanged); + connect(ui->tableViewCDROM->selectionModel(), &QItemSelectionModel::currentRowChanged, + this, &SettingsFloppyCDROM::onCDROMRowChanged); ui->tableViewCDROM->setCurrentIndex(model->index(0, 0)); + + uint8_t bus_type = ui->comboBoxBus->currentData().toUInt(); + int cdromIdx = ui->tableViewCDROM->selectionModel()->currentIndex().data().toInt(); + + auto *modelType = ui->comboBoxCDROMType->model(); + int removeRows = modelType->rowCount(); + + uint32_t j = 0; + int selectedTypeRow = 0; + int eligibleRows = 0; + while (cdrom_drive_types[j].bus_type != BUS_TYPE_NONE) { + if (((bus_type == CDROM_BUS_ATAPI) || (bus_type == CDROM_BUS_SCSI)) && + ((cdrom_drive_types[j].bus_type == bus_type) || + (cdrom_drive_types[j].bus_type == BUS_TYPE_BOTH))) { + QString name = tr(cdrom_getname(j)); + Models::AddEntry(modelType, name, j); + if ((cdrom[cdromIdx].bus_type == bus_type) && (cdrom[cdromIdx].type == j)) + selectedTypeRow = eligibleRows; + ++eligibleRows; + } + ++j; + } + modelType->removeRows(0, removeRows); + ui->comboBoxCDROMType->setEnabled(eligibleRows > 1); + ui->comboBoxCDROMType->setCurrentIndex(-1); + ui->comboBoxCDROMType->setCurrentIndex(selectedTypeRow); } SettingsFloppyCDROM::~SettingsFloppyCDROM() @@ -142,8 +205,10 @@ SettingsFloppyCDROM::~SettingsFloppyCDROM() delete ui; } -void SettingsFloppyCDROM::save() { - auto* model = ui->tableViewFloppy->model(); +void +SettingsFloppyCDROM::save() +{ + auto *model = ui->tableViewFloppy->model(); for (int i = 0; i < FDD_NUM; i++) { fdd_set_type(i, model->index(i, 0).data(Qt::UserRole).toInt()); fdd_set_turbo(i, model->index(i, 1).data() == tr("On") ? 1 : 0); @@ -153,7 +218,7 @@ void SettingsFloppyCDROM::save() { /* Removable devices category */ model = ui->tableViewCDROM->model(); for (int i = 0; i < CDROM_NUM; i++) { - cdrom[i].img_fp = NULL; + cdrom[i].is_dir = 0; cdrom[i].priv = NULL; cdrom[i].ops = NULL; cdrom[i].image = NULL; @@ -164,90 +229,161 @@ void SettingsFloppyCDROM::save() { cdrom[i].bus_type = model->index(i, 0).data(Qt::UserRole).toUInt(); cdrom[i].res = model->index(i, 0).data(Qt::UserRole + 1).toUInt(); cdrom[i].speed = model->index(i, 1).data(Qt::UserRole).toUInt(); + cdrom_set_type(i, model->index(i, 2).data(Qt::UserRole).toInt()); } } -void SettingsFloppyCDROM::onFloppyRowChanged(const QModelIndex ¤t) { +void +SettingsFloppyCDROM::onFloppyRowChanged(const QModelIndex ¤t) +{ int type = current.siblingAtColumn(0).data(Qt::UserRole).toInt(); ui->comboBoxFloppyType->setCurrentIndex(type); ui->checkBoxTurboTimings->setChecked(current.siblingAtColumn(1).data() == tr("On")); ui->checkBoxCheckBPB->setChecked(current.siblingAtColumn(2).data() == tr("On")); } -void SettingsFloppyCDROM::onCDROMRowChanged(const QModelIndex ¤t) { - uint8_t bus = current.siblingAtColumn(0).data(Qt::UserRole).toUInt(); +void +SettingsFloppyCDROM::onCDROMRowChanged(const QModelIndex ¤t) +{ + uint8_t bus = current.siblingAtColumn(0).data(Qt::UserRole).toUInt(); uint8_t channel = current.siblingAtColumn(0).data(Qt::UserRole + 1).toUInt(); - uint8_t speed = current.siblingAtColumn(1).data(Qt::UserRole).toUInt(); + uint8_t speed = current.siblingAtColumn(1).data(Qt::UserRole).toUInt(); + int type = current.siblingAtColumn(2).data(Qt::UserRole).toInt(); ui->comboBoxBus->setCurrentIndex(-1); auto* model = ui->comboBoxBus->model(); auto match = model->match(model->index(0, 0), Qt::UserRole, bus); - if (! match.isEmpty()) { + if (! match.isEmpty()) ui->comboBoxBus->setCurrentIndex(match.first().row()); - } model = ui->comboBoxChannel->model(); match = model->match(model->index(0, 0), Qt::UserRole, channel); - if (! match.isEmpty()) { + if (!match.isEmpty()) ui->comboBoxChannel->setCurrentIndex(match.first().row()); - } ui->comboBoxSpeed->setCurrentIndex(speed == 0 ? 7 : speed - 1); + ui->comboBoxCDROMType->setCurrentIndex(type); } -void SettingsFloppyCDROM::on_checkBoxTurboTimings_stateChanged(int arg1) { +void +SettingsFloppyCDROM::on_checkBoxTurboTimings_stateChanged(int arg1) +{ auto idx = ui->tableViewFloppy->selectionModel()->currentIndex(); - ui->tableViewFloppy->model()->setData(idx.siblingAtColumn(1), arg1 == Qt::Checked ? tr("On") : tr("Off")); + ui->tableViewFloppy->model()->setData(idx.siblingAtColumn(1), arg1 == Qt::Checked ? + tr("On") : tr("Off")); } -void SettingsFloppyCDROM::on_checkBoxCheckBPB_stateChanged(int arg1) { +void +SettingsFloppyCDROM::on_checkBoxCheckBPB_stateChanged(int arg1) +{ auto idx = ui->tableViewFloppy->selectionModel()->currentIndex(); - ui->tableViewFloppy->model()->setData(idx.siblingAtColumn(2), arg1 == Qt::Checked ? tr("On") : tr("Off")); + ui->tableViewFloppy->model()->setData(idx.siblingAtColumn(2), arg1 == Qt::Checked ? + tr("On") : tr("Off")); } -void SettingsFloppyCDROM::on_comboBoxFloppyType_activated(int index) { - setFloppyType(ui->tableViewFloppy->model(), ui->tableViewFloppy->selectionModel()->currentIndex(), index); +void +SettingsFloppyCDROM::on_comboBoxFloppyType_activated(int index) +{ + setFloppyType(ui->tableViewFloppy->model(), + ui->tableViewFloppy->selectionModel()->currentIndex(), index); } -void SettingsFloppyCDROM::on_comboBoxBus_currentIndexChanged(int index) { - if (index < 0) { - return; +void +SettingsFloppyCDROM::on_comboBoxBus_currentIndexChanged(int index) +{ + if (index >= 0) { + int bus = ui->comboBoxBus->currentData().toInt(); + bool enabled = (bus != CDROM_BUS_DISABLED); + ui->comboBoxChannel->setEnabled((bus == CDROM_BUS_MITSUMI) ? 0 : enabled); + ui->comboBoxSpeed->setEnabled((bus == CDROM_BUS_MITSUMI) ? 0 : enabled); + ui->comboBoxCDROMType->setEnabled((bus == CDROM_BUS_MITSUMI) ? 0 : enabled); + + Harddrives::populateBusChannels(ui->comboBoxChannel->model(), bus); } - - int bus = ui->comboBoxBus->currentData().toInt(); - bool enabled = (bus != CDROM_BUS_DISABLED); - ui->comboBoxChannel->setEnabled(enabled); - ui->comboBoxSpeed->setEnabled(enabled); - Harddrives::populateBusChannels(ui->comboBoxChannel->model(), bus); } -void SettingsFloppyCDROM::on_comboBoxSpeed_activated(int index) { +void +SettingsFloppyCDROM::on_comboBoxSpeed_activated(int index) +{ auto idx = ui->tableViewCDROM->selectionModel()->currentIndex(); setCDROMSpeed(ui->tableViewCDROM->model(), idx.siblingAtColumn(1), index + 1); } - -void SettingsFloppyCDROM::on_comboBoxBus_activated(int) { +void +SettingsFloppyCDROM::on_comboBoxBus_activated(int) +{ auto i = ui->tableViewCDROM->selectionModel()->currentIndex().siblingAtColumn(0); - Harddrives::busTrackClass->device_track(0, DEV_CDROM, ui->tableViewCDROM->model()->data(i, Qt::UserRole).toInt(), ui->tableViewCDROM->model()->data(i, Qt::UserRole + 1).toInt()); - ui->comboBoxChannel->setCurrentIndex(ui->comboBoxBus->currentData().toUInt() == CDROM_BUS_ATAPI ? Harddrives::busTrackClass->next_free_ide_channel() : Harddrives::busTrackClass->next_free_scsi_id()); - setCDROMBus( - ui->tableViewCDROM->model(), - ui->tableViewCDROM->selectionModel()->currentIndex(), - ui->comboBoxBus->currentData().toUInt(), - ui->comboBoxChannel->currentData().toUInt()); - Harddrives::busTrackClass->device_track(1, DEV_CDROM, ui->tableViewCDROM->model()->data(i, Qt::UserRole).toInt(), ui->tableViewCDROM->model()->data(i, Qt::UserRole + 1).toInt()); + uint8_t bus_type = ui->comboBoxBus->currentData().toUInt(); + int cdromIdx = ui->tableViewCDROM->selectionModel()->currentIndex().data().toInt(); + + Harddrives::busTrackClass->device_track(0, DEV_CDROM, ui->tableViewCDROM->model()->data(i, + Qt::UserRole).toInt(), ui->tableViewCDROM->model()->data(i, + Qt::UserRole + 1).toInt()); + if (bus_type == CDROM_BUS_ATAPI) + ui->comboBoxChannel->setCurrentIndex(Harddrives::busTrackClass->next_free_ide_channel()); + else if (bus_type == CDROM_BUS_SCSI) + ui->comboBoxChannel->setCurrentIndex(Harddrives::busTrackClass->next_free_scsi_id()); + else if (bus_type == CDROM_BUS_MITSUMI) + ui->comboBoxChannel->setCurrentIndex(0); + + setCDROMBus(ui->tableViewCDROM->model(), + ui->tableViewCDROM->selectionModel()->currentIndex(), + bus_type, + ui->comboBoxChannel->currentData().toUInt()); + Harddrives::busTrackClass->device_track(1, DEV_CDROM, ui->tableViewCDROM->model()->data(i, + Qt::UserRole).toInt(), ui->tableViewCDROM->model()->data(i, + Qt::UserRole + 1).toInt()); + + auto *modelType = ui->comboBoxCDROMType->model(); + int removeRows = modelType->rowCount(); + + uint32_t j = 0; + int selectedTypeRow = 0; + int eligibleRows = 0; + while (cdrom_drive_types[j].bus_type != BUS_TYPE_NONE) { + if (((bus_type == CDROM_BUS_ATAPI) || (bus_type == CDROM_BUS_SCSI)) && + ((cdrom_drive_types[j].bus_type == bus_type) || + (cdrom_drive_types[j].bus_type == BUS_TYPE_BOTH))) { + QString name = tr(cdrom_getname(j)); + Models::AddEntry(modelType, name, j); + if ((cdrom[cdromIdx].bus_type == bus_type) && (cdrom[cdromIdx].type == j)) + selectedTypeRow = eligibleRows; + ++eligibleRows; + } + ++j; + } + modelType->removeRows(0, removeRows); + ui->comboBoxCDROMType->setEnabled(eligibleRows > 1); + ui->comboBoxCDROMType->setCurrentIndex(-1); + ui->comboBoxCDROMType->setCurrentIndex(selectedTypeRow); + + setCDROMType(ui->tableViewCDROM->model(), + ui->tableViewCDROM->selectionModel()->currentIndex(), + ui->comboBoxCDROMType->currentData().toUInt()); } - -void SettingsFloppyCDROM::on_comboBoxChannel_activated(int) { +void +SettingsFloppyCDROM::on_comboBoxChannel_activated(int) +{ auto i = ui->tableViewCDROM->selectionModel()->currentIndex().siblingAtColumn(0); - Harddrives::busTrackClass->device_track(0, DEV_CDROM, ui->tableViewCDROM->model()->data(i, Qt::UserRole).toInt(), ui->tableViewCDROM->model()->data(i, Qt::UserRole + 1).toInt()); - setCDROMBus( - ui->tableViewCDROM->model(), - ui->tableViewCDROM->selectionModel()->currentIndex(), - ui->comboBoxBus->currentData().toUInt(), - ui->comboBoxChannel->currentData().toUInt()); - Harddrives::busTrackClass->device_track(1, DEV_CDROM, ui->tableViewCDROM->model()->data(i, Qt::UserRole).toInt(), ui->tableViewCDROM->model()->data(i, Qt::UserRole + 1).toInt()); + Harddrives::busTrackClass->device_track(0, DEV_CDROM, ui->tableViewCDROM->model()->data(i, + Qt::UserRole).toInt(), ui->tableViewCDROM->model()->data(i, + Qt::UserRole + 1).toInt()); + setCDROMBus(ui->tableViewCDROM->model(), + ui->tableViewCDROM->selectionModel()->currentIndex(), + ui->comboBoxBus->currentData().toUInt(), + ui->comboBoxChannel->currentData().toUInt()); + Harddrives::busTrackClass->device_track(1, DEV_CDROM, ui->tableViewCDROM->model()->data(i, + Qt::UserRole).toInt(), ui->tableViewCDROM->model()->data(i, + Qt::UserRole + 1).toInt()); } +void +SettingsFloppyCDROM::on_comboBoxCDROMType_activated(int) +{ + setCDROMType(ui->tableViewCDROM->model(), + ui->tableViewCDROM->selectionModel()->currentIndex(), + ui->comboBoxCDROMType->currentData().toUInt()); + ui->tableViewCDROM->resizeColumnsToContents(); + ui->tableViewCDROM->horizontalHeader()->setSectionResizeMode(0, QHeaderView::Stretch); +} diff --git a/src/qt/qt_settingsfloppycdrom.hpp b/src/qt/qt_settingsfloppycdrom.hpp index f68646ab0..3d6dd0e45 100644 --- a/src/qt/qt_settingsfloppycdrom.hpp +++ b/src/qt/qt_settingsfloppycdrom.hpp @@ -7,8 +7,7 @@ namespace Ui { class SettingsFloppyCDROM; } -class SettingsFloppyCDROM : public QWidget -{ +class SettingsFloppyCDROM : public QWidget { Q_OBJECT public: @@ -18,6 +17,7 @@ public: void save(); private slots: + void on_comboBoxCDROMType_activated(int index); void on_comboBoxChannel_activated(int index); void on_comboBoxBus_activated(int index); void on_comboBoxSpeed_activated(int index); diff --git a/src/qt/qt_settingsfloppycdrom.ui b/src/qt/qt_settingsfloppycdrom.ui index 8f7ffa995..d7ad853b3 100644 --- a/src/qt/qt_settingsfloppycdrom.ui +++ b/src/qt/qt_settingsfloppycdrom.ui @@ -35,6 +35,9 @@ + + QAbstractItemView::NoEditTriggers + QAbstractItemView::SingleSelection @@ -59,7 +62,11 @@ - + + + 30 + + @@ -99,6 +106,9 @@ + + QAbstractItemView::NoEditTriggers + QAbstractItemView::SingleSelection @@ -115,16 +125,20 @@ + + + + Bus: + + + - + Channel: - - - @@ -132,18 +146,40 @@ - - + + - Bus: + Type: + + + + + + + 30 - + + + 30 + + - + + + 30 + + + + + + + 30 + + diff --git a/src/qt/qt_settingsharddisks.cpp b/src/qt/qt_settingsharddisks.cpp index 25fc06bfe..a66203406 100644 --- a/src/qt/qt_settingsharddisks.cpp +++ b/src/qt/qt_settingsharddisks.cpp @@ -1,20 +1,20 @@ /* - * 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. + * 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. + * This file is part of the 86Box distribution. * - * Hard disk configuration UI module. + * Hard disk configuration UI module. * * * - * Authors: Joakim L. Gilje + * Authors: Joakim L. Gilje * Cacodemon345 * - * Copyright 2021-2022 Cacodemon345 - * Copyright 2021 Joakim L. Gilje + * Copyright 2021-2022 Cacodemon345 + * Copyright 2021 Joakim L. Gilje */ #include "qt_settingsharddisks.hpp" #include "ui_qt_settingsharddisks.h" @@ -31,29 +31,30 @@ extern "C" { #include "qt_settings_bus_tracking.hpp" #include "qt_progsettings.hpp" -const int ColumnBus = 0; -const int ColumnFilename = 1; -const int ColumnCylinders = 2; -const int ColumnHeads = 3; -const int ColumnSectors = 4; -const int ColumnSize = 5; +const int ColumnBus = 0; +const int ColumnFilename = 1; +const int ColumnCylinders = 2; +const int ColumnHeads = 3; +const int ColumnSectors = 4; +const int ColumnSize = 5; +const int ColumnSpeed = 6; -const int DataBus = Qt::UserRole; -const int DataBusChannel = Qt::UserRole + 1; -const int DataBusPrevious = Qt::UserRole + 2; -const int DataBusChannelPrevious = Qt::UserRole + 3; +const int DataBus = Qt::UserRole; +const int DataBusChannel = Qt::UserRole + 1; +const int DataBusPrevious = Qt::UserRole + 2; +const int DataBusChannelPrevious = Qt::UserRole + 3; -/* +#if 0 static void normalize_hd_list() { hard_disk_t ihdd[HDD_NUM]; - int i, j; + int j; j = 0; memset(ihdd, 0x00, HDD_NUM * sizeof(hard_disk_t)); - for (i = 0; i < HDD_NUM; i++) { + for (uint8_t i = 0; i < HDD_NUM; i++) { if (temp_hdd[i].bus != HDD_BUS_DISABLED) { memcpy(&(ihdd[j]), &(temp_hdd[i]), sizeof(hard_disk_t)); j++; @@ -62,13 +63,17 @@ normalize_hd_list() memcpy(temp_hdd, ihdd, HDD_NUM * sizeof(hard_disk_t)); } -*/ +#endif -static QString busChannelName(const QModelIndex& idx) { +static QString +busChannelName(const QModelIndex &idx) +{ return Harddrives::BusChannelName(idx.data(DataBus).toUInt(), idx.data(DataBusChannel).toUInt()); } -static void addRow(QAbstractItemModel* model, hard_disk_t* hd) { +static void +addRow(QAbstractItemModel *model, hard_disk_t *hd) +{ const QString userPath = usr_path; int row = model->rowCount(); @@ -76,7 +81,7 @@ static void addRow(QAbstractItemModel* model, hard_disk_t* hd) { QString busName = Harddrives::BusChannelName(hd->bus, hd->channel); model->setData(model->index(row, ColumnBus), busName); - model->setData(model->index(row, ColumnBus), ProgSettings::loadIcon( "/hard_disk.ico"), Qt::DecorationRole); + model->setData(model->index(row, ColumnBus), ProgSettings::loadIcon("/hard_disk.ico"), Qt::DecorationRole); model->setData(model->index(row, ColumnBus), hd->bus, DataBus); model->setData(model->index(row, ColumnBus), hd->bus, DataBusPrevious); model->setData(model->index(row, ColumnBus), hd->channel, DataBusChannel); @@ -94,21 +99,24 @@ static void addRow(QAbstractItemModel* model, hard_disk_t* hd) { model->setData(model->index(row, ColumnHeads), hd->hpc); model->setData(model->index(row, ColumnSectors), hd->spt); model->setData(model->index(row, ColumnSize), (hd->tracks * hd->hpc * hd->spt) >> 11); + model->setData(model->index(row, ColumnSpeed), hdd_preset_getname(hd->speed_preset)); + model->setData(model->index(row, ColumnSpeed), hd->speed_preset, Qt::UserRole); } -SettingsHarddisks::SettingsHarddisks(QWidget *parent) : - QWidget(parent), - ui(new Ui::SettingsHarddisks) +SettingsHarddisks::SettingsHarddisks(QWidget *parent) + : QWidget(parent) + , ui(new Ui::SettingsHarddisks) { ui->setupUi(this); - QAbstractItemModel* model = new QStandardItemModel(0, 6, this); + QAbstractItemModel *model = new QStandardItemModel(0, 7, this); model->setHeaderData(ColumnBus, Qt::Horizontal, tr("Bus")); model->setHeaderData(ColumnFilename, Qt::Horizontal, tr("File")); model->setHeaderData(ColumnCylinders, Qt::Horizontal, tr("C")); model->setHeaderData(ColumnHeads, Qt::Horizontal, tr("H")); model->setHeaderData(ColumnSectors, Qt::Horizontal, tr("S")); model->setHeaderData(ColumnSize, Qt::Horizontal, tr("MiB")); + model->setHeaderData(ColumnSpeed, Qt::Horizontal, tr("Speed")); ui->tableView->setModel(model); for (int i = 0; i < HDD_NUM; i++) { @@ -116,15 +124,14 @@ SettingsHarddisks::SettingsHarddisks(QWidget *parent) : addRow(model, &hdd[i]); } } - if (model->rowCount() == HDD_NUM) - { + if (model->rowCount() == HDD_NUM) { ui->pushButtonNew->setEnabled(false); ui->pushButtonExisting->setEnabled(false); } ui->tableView->resizeColumnsToContents(); ui->tableView->horizontalHeader()->setSectionResizeMode(ColumnFilename, QHeaderView::Stretch); - auto* tableSelectionModel = ui->tableView->selectionModel(); + auto *tableSelectionModel = ui->tableView->selectionModel(); connect(tableSelectionModel, &QItemSelectionModel::currentRowChanged, this, &SettingsHarddisks::onTableRowChanged); onTableRowChanged(QModelIndex()); @@ -137,35 +144,40 @@ SettingsHarddisks::~SettingsHarddisks() delete ui; } -void SettingsHarddisks::save() { +void +SettingsHarddisks::save() +{ memset(hdd, 0, sizeof(hdd)); - auto* model = ui->tableView->model(); - int rows = model->rowCount(); + auto *model = ui->tableView->model(); + int rows = model->rowCount(); for (int i = 0; i < rows; ++i) { - auto idx = model->index(i, ColumnBus); - hdd[i].bus = idx.data(DataBus).toUInt(); - hdd[i].channel = idx.data(DataBusChannel).toUInt(); - hdd[i].tracks = idx.siblingAtColumn(ColumnCylinders).data().toUInt(); - hdd[i].hpc = idx.siblingAtColumn(ColumnHeads).data().toUInt(); - hdd[i].spt = idx.siblingAtColumn(ColumnSectors).data().toUInt(); + auto idx = model->index(i, ColumnBus); + hdd[i].bus = idx.data(DataBus).toUInt(); + hdd[i].channel = idx.data(DataBusChannel).toUInt(); + hdd[i].tracks = idx.siblingAtColumn(ColumnCylinders).data().toUInt(); + hdd[i].hpc = idx.siblingAtColumn(ColumnHeads).data().toUInt(); + hdd[i].spt = idx.siblingAtColumn(ColumnSectors).data().toUInt(); + hdd[i].speed_preset = idx.siblingAtColumn(ColumnSpeed).data(Qt::UserRole).toUInt(); QByteArray fileName = idx.siblingAtColumn(ColumnFilename).data(Qt::UserRole).toString().toUtf8(); - strncpy(hdd[i].fn, fileName.data(), sizeof(hdd[i].fn)); + strncpy(hdd[i].fn, fileName.data(), sizeof(hdd[i].fn) - 1); hdd[i].priv = nullptr; } } -void SettingsHarddisks::on_comboBoxBus_currentIndexChanged(int index) { +void +SettingsHarddisks::on_comboBoxBus_currentIndexChanged(int index) +{ if (index < 0) { return; } buschangeinprogress = true; - auto idx = ui->tableView->selectionModel()->currentIndex(); + auto idx = ui->tableView->selectionModel()->currentIndex(); if (idx.isValid()) { - auto* model = ui->tableView->model(); - auto col = idx.siblingAtColumn(ColumnBus); + auto *model = ui->tableView->model(); + auto col = idx.siblingAtColumn(ColumnBus); model->setData(col, ui->comboBoxBus->currentData(Qt::UserRole), DataBus); model->setData(col, busChannelName(col), Qt::DisplayRole); Harddrives::busTrackClass->device_track(0, DEV_HDD, model->data(col, DataBusPrevious).toInt(), model->data(col, DataBusChannelPrevious).toInt()); @@ -173,10 +185,10 @@ void SettingsHarddisks::on_comboBoxBus_currentIndexChanged(int index) { } Harddrives::populateBusChannels(ui->comboBoxChannel->model(), ui->comboBoxBus->currentData().toInt()); + Harddrives::populateSpeeds(ui->comboBoxSpeed->model(), ui->comboBoxBus->currentData().toInt()); int chanIdx = 0; - switch (ui->comboBoxBus->currentData().toInt()) - { + switch (ui->comboBoxBus->currentData().toInt()) { case HDD_BUS_MFM: chanIdx = (Harddrives::busTrackClass->next_free_mfm_channel()); break; @@ -196,102 +208,140 @@ void SettingsHarddisks::on_comboBoxBus_currentIndexChanged(int index) { } if (idx.isValid()) { - auto* model = ui->tableView->model(); - auto col = idx.siblingAtColumn(ColumnBus); + auto *model = ui->tableView->model(); + auto col = idx.siblingAtColumn(ColumnBus); model->setData(col, chanIdx, DataBusChannelPrevious); } ui->comboBoxChannel->setCurrentIndex(chanIdx); buschangeinprogress = false; } -void SettingsHarddisks::on_comboBoxChannel_currentIndexChanged(int index) { +void +SettingsHarddisks::on_comboBoxChannel_currentIndexChanged(int index) +{ if (index < 0) { return; } auto idx = ui->tableView->selectionModel()->currentIndex(); if (idx.isValid()) { - auto* model = ui->tableView->model(); - auto col = idx.siblingAtColumn(ColumnBus); + auto *model = ui->tableView->model(); + auto col = idx.siblingAtColumn(ColumnBus); model->setData(col, ui->comboBoxChannel->currentData(Qt::UserRole), DataBusChannel); model->setData(col, busChannelName(col), Qt::DisplayRole); - if (!buschangeinprogress) Harddrives::busTrackClass->device_track(0, DEV_HDD, model->data(col, DataBus).toInt(), model->data(col, DataBusChannelPrevious).toUInt()); + if (!buschangeinprogress) + Harddrives::busTrackClass->device_track(0, DEV_HDD, model->data(col, DataBus).toInt(), model->data(col, DataBusChannelPrevious).toUInt()); Harddrives::busTrackClass->device_track(1, DEV_HDD, model->data(col, DataBus).toInt(), model->data(col, DataBusChannel).toUInt()); model->setData(col, ui->comboBoxChannel->currentData(Qt::UserRole), DataBusChannelPrevious); } } -void SettingsHarddisks::onTableRowChanged(const QModelIndex ¤t) { +void +SettingsHarddisks::on_comboBoxSpeed_currentIndexChanged(int index) +{ + if (index < 0) { + return; + } + + auto idx = ui->tableView->selectionModel()->currentIndex(); + if (idx.isValid()) { + auto *model = ui->tableView->model(); + auto col = idx.siblingAtColumn(ColumnSpeed); + model->setData(col, ui->comboBoxSpeed->currentData(Qt::UserRole), Qt::UserRole); + model->setData(col, hdd_preset_getname(ui->comboBoxSpeed->currentData(Qt::UserRole).toUInt())); + } +} + +void +SettingsHarddisks::onTableRowChanged(const QModelIndex ¤t) +{ bool hidden = !current.isValid(); ui->labelBus->setHidden(hidden); ui->labelChannel->setHidden(hidden); + ui->labelSpeed->setHidden(hidden); ui->comboBoxBus->setHidden(hidden); ui->comboBoxChannel->setHidden(hidden); + ui->comboBoxSpeed->setHidden(hidden); - uint32_t bus = current.siblingAtColumn(ColumnBus).data(DataBus).toUInt(); + uint32_t bus = current.siblingAtColumn(ColumnBus).data(DataBus).toUInt(); uint32_t busChannel = current.siblingAtColumn(ColumnBus).data(DataBusChannel).toUInt(); + uint32_t speed = current.siblingAtColumn(ColumnSpeed).data(Qt::UserRole).toUInt(); - auto* model = ui->comboBoxBus->model(); - auto match = model->match(model->index(0, 0), Qt::UserRole, bus); - if (! match.isEmpty()) { + auto *model = ui->comboBoxBus->model(); + auto match = model->match(model->index(0, 0), Qt::UserRole, bus); + if (!match.isEmpty()) { ui->comboBoxBus->setCurrentIndex(match.first().row()); } model = ui->comboBoxChannel->model(); match = model->match(model->index(0, 0), Qt::UserRole, busChannel); - if (! match.isEmpty()) { + if (!match.isEmpty()) { ui->comboBoxChannel->setCurrentIndex(match.first().row()); } + + model = ui->comboBoxSpeed->model(); + match = model->match(model->index(0, 0), Qt::UserRole, speed); + if (!match.isEmpty()) { + ui->comboBoxSpeed->setCurrentIndex(match.first().row()); + } } -static void addDriveFromDialog(Ui::SettingsHarddisks* ui, const HarddiskDialog& dlg) { +static void +addDriveFromDialog(Ui::SettingsHarddisks *ui, const HarddiskDialog &dlg) +{ QByteArray fn = dlg.fileName().toUtf8(); hard_disk_t hd; - hd.bus = dlg.bus(); + memset(&hd, 0, sizeof(hd)); + + hd.bus = dlg.bus(); hd.channel = dlg.channel(); - hd.tracks = dlg.cylinders(); - hd.hpc = dlg.heads(); - hd.spt = dlg.sectors(); - strncpy(hd.fn, fn.data(), sizeof(hd.fn)); + hd.tracks = dlg.cylinders(); + hd.hpc = dlg.heads(); + hd.spt = dlg.sectors(); + strncpy(hd.fn, fn.data(), sizeof(hd.fn) - 1); + hd.speed_preset = dlg.speed(); addRow(ui->tableView->model(), &hd); ui->tableView->resizeColumnsToContents(); ui->tableView->horizontalHeader()->setSectionResizeMode(1, QHeaderView::Stretch); - if (ui->tableView->model()->rowCount() == HDD_NUM) - { + if (ui->tableView->model()->rowCount() == HDD_NUM) { ui->pushButtonNew->setEnabled(false); ui->pushButtonExisting->setEnabled(false); } } -void SettingsHarddisks::on_pushButtonNew_clicked() { +void +SettingsHarddisks::on_pushButtonNew_clicked() +{ HarddiskDialog dialog(false, this); switch (dialog.exec()) { - case QDialog::Accepted: - addDriveFromDialog(ui, dialog); - break; + case QDialog::Accepted: + addDriveFromDialog(ui, dialog); + break; } } - -void SettingsHarddisks::on_pushButtonExisting_clicked() { +void +SettingsHarddisks::on_pushButtonExisting_clicked() +{ HarddiskDialog dialog(true, this); switch (dialog.exec()) { - case QDialog::Accepted: - addDriveFromDialog(ui, dialog); - break; + case QDialog::Accepted: + addDriveFromDialog(ui, dialog); + break; } } -void SettingsHarddisks::on_pushButtonRemove_clicked() { +void +SettingsHarddisks::on_pushButtonRemove_clicked() +{ auto idx = ui->tableView->selectionModel()->currentIndex(); - if (! idx.isValid()) { + if (!idx.isValid()) { return; } - auto* model = ui->tableView->model(); + auto *model = ui->tableView->model(); model->removeRow(idx.row()); ui->pushButtonNew->setEnabled(true); ui->pushButtonExisting->setEnabled(true); } - diff --git a/src/qt/qt_settingsharddisks.hpp b/src/qt/qt_settingsharddisks.hpp index b10e79029..68d7ca3d6 100644 --- a/src/qt/qt_settingsharddisks.hpp +++ b/src/qt/qt_settingsharddisks.hpp @@ -7,8 +7,7 @@ namespace Ui { class SettingsHarddisks; } -class SettingsHarddisks : public QWidget -{ +class SettingsHarddisks : public QWidget { Q_OBJECT public: @@ -19,6 +18,7 @@ public: private slots: void on_comboBoxChannel_currentIndexChanged(int index); + void on_comboBoxSpeed_currentIndexChanged(int index); private slots: void on_pushButtonRemove_clicked(); @@ -26,11 +26,11 @@ private slots: void on_pushButtonNew_clicked(); void on_comboBoxBus_currentIndexChanged(int index); - void onTableRowChanged(const QModelIndex& current); + void onTableRowChanged(const QModelIndex ¤t); private: Ui::SettingsHarddisks *ui; - bool buschangeinprogress = false; + bool buschangeinprogress = false; }; #endif // QT_SETTINGSHARDDISKS_HPP diff --git a/src/qt/qt_settingsharddisks.ui b/src/qt/qt_settingsharddisks.ui index fa913beea..3ae20fee1 100644 --- a/src/qt/qt_settingsharddisks.ui +++ b/src/qt/qt_settingsharddisks.ui @@ -28,6 +28,9 @@ + + QAbstractItemView::NoEditTriggers + QAbstractItemView::SingleSelection @@ -52,7 +55,11 @@ - + + + 30 + + @@ -62,7 +69,25 @@ - + + + 30 + + + + + + + Speed: + + + + + + + 30 + + diff --git a/src/qt/qt_settingsinput.cpp b/src/qt/qt_settingsinput.cpp index c735153d9..66d6e3de0 100644 --- a/src/qt/qt_settingsinput.cpp +++ b/src/qt/qt_settingsinput.cpp @@ -1,18 +1,18 @@ /* - * 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. + * 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. + * This file is part of the 86Box distribution. * - * Mouse/Joystick configuration UI module. + * Mouse/Joystick configuration UI module. * * * - * Authors: Joakim L. Gilje + * Authors: Joakim L. Gilje * - * Copyright 2021 Joakim L. Gilje + * Copyright 2021 Joakim L. Gilje */ #include "qt_settingsinput.hpp" #include "ui_qt_settingsinput.h" @@ -31,9 +31,9 @@ extern "C" { #include "qt_deviceconfig.hpp" #include "qt_joystickconfiguration.hpp" -SettingsInput::SettingsInput(QWidget *parent) : - QWidget(parent), - ui(new Ui::SettingsInput) +SettingsInput::SettingsInput(QWidget *parent) + : QWidget(parent) + , ui(new Ui::SettingsInput) { ui->setupUi(this); @@ -45,22 +45,25 @@ SettingsInput::~SettingsInput() delete ui; } -void SettingsInput::save() { - mouse_type = ui->comboBoxMouse->currentData().toInt(); +void +SettingsInput::save() +{ + mouse_type = ui->comboBoxMouse->currentData().toInt(); joystick_type = ui->comboBoxJoystick->currentData().toInt(); } -void SettingsInput::onCurrentMachineChanged(int machineId) { +void +SettingsInput::onCurrentMachineChanged(int machineId) +{ // win_settings_video_proc, WM_INITDIALOG this->machineId = machineId; - const auto* machine = &machines[machineId]; - auto* mouseModel = ui->comboBoxMouse->model(); - auto removeRows = mouseModel->rowCount(); + auto *mouseModel = ui->comboBoxMouse->model(); + auto removeRows = mouseModel->rowCount(); int selectedRow = 0; for (int i = 0; i < mouse_get_ndev(); ++i) { - const auto* dev = mouse_get_device(i); + const auto *dev = mouse_get_device(i); if ((i == MOUSE_TYPE_INTERNAL) && (machine_has_flags(machineId, MACHINE_MOUSE) == 0)) { continue; } @@ -70,7 +73,7 @@ void SettingsInput::onCurrentMachineChanged(int machineId) { } QString name = DeviceConfig::DeviceName(dev, mouse_get_internal_name(i), 0); - int row = mouseModel->rowCount(); + int row = mouseModel->rowCount(); mouseModel->insertRow(row); auto idx = mouseModel->index(row, 0); @@ -84,12 +87,11 @@ void SettingsInput::onCurrentMachineChanged(int machineId) { mouseModel->removeRows(0, removeRows); ui->comboBoxMouse->setCurrentIndex(selectedRow); - - int i = 0; - char* joyName = joystick_get_name(i); - auto* joystickModel = ui->comboBoxJoystick->model(); - removeRows = joystickModel->rowCount(); - selectedRow = 0; + int i = 0; + const char *joyName = joystick_get_name(i); + auto *joystickModel = ui->comboBoxJoystick->model(); + removeRows = joystickModel->rowCount(); + selectedRow = 0; while (joyName) { int row = Models::AddEntry(joystickModel, tr(joyName).toUtf8().data(), i); if (i == joystick_type) { @@ -103,16 +105,19 @@ void SettingsInput::onCurrentMachineChanged(int machineId) { ui->comboBoxJoystick->setCurrentIndex(selectedRow); } -void SettingsInput::on_comboBoxMouse_currentIndexChanged(int index) { +void +SettingsInput::on_comboBoxMouse_currentIndexChanged(int index) +{ int mouseId = ui->comboBoxMouse->currentData().toInt(); ui->pushButtonConfigureMouse->setEnabled(mouse_has_config(mouseId) > 0); } - -void SettingsInput::on_comboBoxJoystick_currentIndexChanged(int index) { +void +SettingsInput::on_comboBoxJoystick_currentIndexChanged(int index) +{ int joystickId = ui->comboBoxJoystick->currentData().toInt(); - for (int i = 0; i < 4; ++i) { - auto* btn = findChild(QString("pushButtonJoystick%1").arg(i+1)); + for (int i = 0; i < MAX_JOYSTICKS; ++i) { + auto *btn = findChild(QString("pushButtonJoystick%1").arg(i + 1)); if (btn == nullptr) { continue; } @@ -120,15 +125,19 @@ void SettingsInput::on_comboBoxJoystick_currentIndexChanged(int index) { } } -void SettingsInput::on_pushButtonConfigureMouse_clicked() { +void +SettingsInput::on_pushButtonConfigureMouse_clicked() +{ int mouseId = ui->comboBoxMouse->currentData().toInt(); - DeviceConfig::ConfigureDevice(mouse_get_device(mouseId), 0, qobject_cast(Settings::settings)); + DeviceConfig::ConfigureDevice(mouse_get_device(mouseId), 0, qobject_cast(Settings::settings)); } -static int get_axis(JoystickConfiguration& jc, int axis, int joystick_nr) { +static int +get_axis(JoystickConfiguration &jc, int axis, int joystick_nr) +{ int axis_sel = jc.selectedAxis(axis); - int nr_axes = plat_joystick_state[joystick_state[joystick_nr].plat_joystick_nr - 1].nr_axes; - int nr_povs = plat_joystick_state[joystick_state[joystick_nr].plat_joystick_nr - 1].nr_povs; + int nr_axes = plat_joystick_state[joystick_state[joystick_nr].plat_joystick_nr - 1].nr_axes; + int nr_povs = plat_joystick_state[joystick_state[joystick_nr].plat_joystick_nr - 1].nr_povs; if (axis_sel < nr_axes) { return axis_sel; @@ -146,12 +155,13 @@ static int get_axis(JoystickConfiguration& jc, int axis, int joystick_nr) { return SLIDER | (axis_sel >> 1); } -static int get_pov(JoystickConfiguration& jc, int pov, int joystick_nr) { +static int +get_pov(JoystickConfiguration &jc, int pov, int joystick_nr) +{ int pov_sel = jc.selectedPov(pov); - int nr_povs = plat_joystick_state[joystick_state[joystick_nr].plat_joystick_nr-1].nr_povs*2; + int nr_povs = plat_joystick_state[joystick_state[joystick_nr].plat_joystick_nr - 1].nr_povs * 2; - if (pov_sel < nr_povs) - { + if (pov_sel < nr_povs) { if (pov_sel & 1) return POV_Y | (pov_sel >> 1); else @@ -161,13 +171,15 @@ static int get_pov(JoystickConfiguration& jc, int pov, int joystick_nr) { return pov_sel - nr_povs; } -static void updateJoystickConfig(int type, int joystick_nr, QWidget* parent) { +static void +updateJoystickConfig(int type, int joystick_nr, QWidget *parent) +{ JoystickConfiguration jc(type, joystick_nr, parent); switch (jc.exec()) { - case QDialog::Rejected: - return; - case QDialog::Accepted: - break; + case QDialog::Rejected: + return; + case QDialog::Accepted: + break; } joystick_state[joystick_nr].plat_joystick_nr = jc.selectedDevice(); @@ -185,19 +197,26 @@ static void updateJoystickConfig(int type, int joystick_nr, QWidget* parent) { } } -void SettingsInput::on_pushButtonJoystick1_clicked() { +void +SettingsInput::on_pushButtonJoystick1_clicked() +{ updateJoystickConfig(ui->comboBoxJoystick->currentData().toInt(), 0, this); } -void SettingsInput::on_pushButtonJoystick2_clicked() { +void +SettingsInput::on_pushButtonJoystick2_clicked() +{ updateJoystickConfig(ui->comboBoxJoystick->currentData().toInt(), 1, this); } -void SettingsInput::on_pushButtonJoystick3_clicked() { +void +SettingsInput::on_pushButtonJoystick3_clicked() +{ updateJoystickConfig(ui->comboBoxJoystick->currentData().toInt(), 2, this); } -void SettingsInput::on_pushButtonJoystick4_clicked() { +void +SettingsInput::on_pushButtonJoystick4_clicked() +{ updateJoystickConfig(ui->comboBoxJoystick->currentData().toInt(), 3, this); } - diff --git a/src/qt/qt_settingsinput.hpp b/src/qt/qt_settingsinput.hpp index f9e44740d..0b8b665aa 100644 --- a/src/qt/qt_settingsinput.hpp +++ b/src/qt/qt_settingsinput.hpp @@ -7,8 +7,7 @@ namespace Ui { class SettingsInput; } -class SettingsInput : public QWidget -{ +class SettingsInput : public QWidget { Q_OBJECT public: @@ -31,7 +30,7 @@ private slots: private: Ui::SettingsInput *ui; - int machineId = 0; + int machineId = 0; }; #endif // QT_SETTINGSINPUT_HPP diff --git a/src/qt/qt_settingsinput.ui b/src/qt/qt_settingsinput.ui index 8f4f46167..839461119 100644 --- a/src/qt/qt_settingsinput.ui +++ b/src/qt/qt_settingsinput.ui @@ -96,6 +96,9 @@ + + 30 + 0 @@ -105,7 +108,11 @@ - + + + 30 + + diff --git a/src/qt/qt_settingsmachine.cpp b/src/qt/qt_settingsmachine.cpp index 56456000b..475730db9 100644 --- a/src/qt/qt_settingsmachine.cpp +++ b/src/qt/qt_settingsmachine.cpp @@ -1,18 +1,18 @@ /* - * 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. + * 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. + * This file is part of the 86Box distribution. * - * Machine selection and configuration UI module. + * Machine selection and configuration UI module. * * * - * Authors: Joakim L. Gilje + * Authors: Joakim L. Gilje * - * Copyright 2021 Joakim L. Gilje + * Copyright 2021 Joakim L. Gilje */ #include "qt_settingsmachine.hpp" #include "ui_qt_settingsmachine.h" @@ -35,53 +35,67 @@ extern "C" { } // from nvr.h, which we can't import into CPP code -#define TIME_SYNC_DISABLED 0 -#define TIME_SYNC_ENABLED 1 -#define TIME_SYNC_UTC 2 +#define TIME_SYNC_DISABLED 0 +#define TIME_SYNC_ENABLED 1 +#define TIME_SYNC_UTC 2 #include "qt_deviceconfig.hpp" #include "qt_models_common.hpp" -SettingsMachine::SettingsMachine(QWidget *parent) : - QWidget(parent), - ui(new Ui::SettingsMachine) +SettingsMachine::SettingsMachine(QWidget *parent) + : QWidget(parent) + , ui(new Ui::SettingsMachine) { ui->setupUi(this); switch (time_sync) { - case TIME_SYNC_ENABLED: - ui->radioButtonLocalTime->setChecked(true); - break; - case TIME_SYNC_ENABLED | TIME_SYNC_UTC: - ui->radioButtonUTC->setChecked(true); - break; - case TIME_SYNC_DISABLED: - default: - ui->radioButtonDisabled->setChecked(true); - break; + case TIME_SYNC_ENABLED: + ui->radioButtonLocalTime->setChecked(true); + break; + case TIME_SYNC_ENABLED | TIME_SYNC_UTC: + ui->radioButtonUTC->setChecked(true); + break; + case TIME_SYNC_DISABLED: + default: + ui->radioButtonDisabled->setChecked(true); + break; } - auto* waitStatesModel = ui->comboBoxWaitStates->model(); + auto *waitStatesModel = ui->comboBoxWaitStates->model(); waitStatesModel->insertRows(0, 9); auto idx = waitStatesModel->index(0, 0); waitStatesModel->setData(idx, tr("Default"), Qt::DisplayRole); waitStatesModel->setData(idx, 0, Qt::UserRole); for (int i = 0; i < 8; ++i) { - idx = waitStatesModel->index(i+1, 0); + idx = waitStatesModel->index(i + 1, 0); waitStatesModel->setData(idx, QString::asprintf(tr("%i Wait state(s)").toUtf8().constData(), i), Qt::DisplayRole); - waitStatesModel->setData(idx, i+1, Qt::UserRole); + waitStatesModel->setData(idx, i + 1, Qt::UserRole); } - int selectedMachineType = 0; - auto* machineTypesModel = ui->comboBoxMachineType->model(); + auto *pitModeModel = ui->comboBoxPitMode->model(); + pitModeModel->insertRows(0, 3); + idx = pitModeModel->index(0, 0); + pitModeModel->setData(idx, tr("Auto"), Qt::DisplayRole); + pitModeModel->setData(idx, -1, Qt::UserRole); + idx = pitModeModel->index(1, 0); + pitModeModel->setData(idx, tr("Slow"), Qt::DisplayRole); + pitModeModel->setData(idx, 0, Qt::UserRole); + idx = pitModeModel->index(2, 0); + pitModeModel->setData(idx, tr("Fast"), Qt::DisplayRole); + pitModeModel->setData(idx, 1, Qt::UserRole); + + ui->comboBoxPitMode->setCurrentIndex(-1); + ui->comboBoxPitMode->setCurrentIndex(pit_mode + 1); + + int selectedMachineType = 0; + auto *machineTypesModel = ui->comboBoxMachineType->model(); for (int i = 1; i < MACHINE_TYPE_MAX; ++i) { int j = 0; while (machine_get_internal_name_ex(j) != nullptr) { if (machine_available(j) && (machine_get_type(j) == i)) { int row = Models::AddEntry(machineTypesModel, machine_types[i].name, machine_types[i].id); - if (machine_types[i].id == machine_get_type(machine)) { + if (machine_types[i].id == machine_get_type(machine)) selectedMachineType = row; - } break; } j++; @@ -90,210 +104,236 @@ SettingsMachine::SettingsMachine(QWidget *parent) : ui->comboBoxMachineType->setCurrentIndex(-1); ui->comboBoxMachineType->setCurrentIndex(selectedMachineType); + +#ifndef USE_DYNAREC + ui->checkBoxDynamicRecompiler->setEnabled(false); + ui->checkBoxDynamicRecompiler->setVisible(false); +#endif } -SettingsMachine::~SettingsMachine() { +SettingsMachine::~SettingsMachine() +{ delete ui; } -void SettingsMachine::save() { - machine = ui->comboBoxMachine->currentData().toInt(); - cpu_f = const_cast(&cpu_families[ui->comboBoxCPU->currentData().toInt()]); - cpu = ui->comboBoxSpeed->currentData().toInt(); - fpu_type = ui->comboBoxFPU->currentData().toInt(); +void +SettingsMachine::save() +{ + machine = ui->comboBoxMachine->currentData().toInt(); + cpu_f = const_cast(&cpu_families[ui->comboBoxCPU->currentData().toInt()]); + cpu = ui->comboBoxSpeed->currentData().toInt(); + fpu_type = ui->comboBoxFPU->currentData().toInt(); cpu_use_dynarec = ui->checkBoxDynamicRecompiler->isChecked() ? 1 : 0; + fpu_softfloat = ui->checkBoxFPUSoftfloat->isChecked() ? 1 : 0; + int64_t temp_mem_size; - if (machine_get_ram_granularity(machine) < 1024) { + if (machine_get_ram_granularity(machine) < 1024) temp_mem_size = ui->spinBoxRAM->value(); - } else { + else temp_mem_size = ui->spinBoxRAM->value() * 1024; - } temp_mem_size &= ~(machine_get_ram_granularity(machine) - 1); - if (temp_mem_size < machine_get_min_ram(machine)) { + if (temp_mem_size < machine_get_min_ram(machine)) temp_mem_size = machine_get_min_ram(machine); - } else if (temp_mem_size > machine_get_max_ram(machine)) { + else if (temp_mem_size > machine_get_max_ram(machine)) temp_mem_size = machine_get_max_ram(machine); - } mem_size = static_cast(temp_mem_size); - if (ui->comboBoxWaitStates->isEnabled()) { + if (ui->comboBoxWaitStates->isEnabled()) cpu_waitstates = ui->comboBoxWaitStates->currentData().toInt(); - } else { + else cpu_waitstates = 0; - } + + pit_mode = ui->comboBoxPitMode->currentData().toInt(); time_sync = 0; - if (ui->radioButtonLocalTime->isChecked()) { + if (ui->radioButtonLocalTime->isChecked()) time_sync = TIME_SYNC_ENABLED; - } - if (ui->radioButtonUTC->isChecked()) { + if (ui->radioButtonUTC->isChecked()) time_sync = TIME_SYNC_ENABLED | TIME_SYNC_UTC; - } } -void SettingsMachine::on_comboBoxMachineType_currentIndexChanged(int index) { - if (index < 0) { - return; - } +void +SettingsMachine::on_comboBoxMachineType_currentIndexChanged(int index) +{ + if (index >= 0) { + auto *model = ui->comboBoxMachine->model(); + int removeRows = model->rowCount(); - auto* model = ui->comboBoxMachine->model(); - int removeRows = model->rowCount(); - - int selectedMachineRow = 0; - for (int i = 0; i < machine_count(); ++i) { - if ((machine_get_type(i) == ui->comboBoxMachineType->currentData().toInt()) && machine_available(i)) { - int row = Models::AddEntry(model, machines[i].name, i); - if (i == machine) { - selectedMachineRow = row - removeRows; + int selectedMachineRow = 0; + for (int i = 0; i < machine_count(); ++i) { + if ((machine_get_type(i) == ui->comboBoxMachineType->currentData().toInt()) && + machine_available(i)) { + int row = Models::AddEntry(model, machines[i].name, i); + if (i == machine) + selectedMachineRow = row - removeRows; } } - } - model->removeRows(0, removeRows); + model->removeRows(0, removeRows); - ui->comboBoxMachine->setCurrentIndex(-1); - ui->comboBoxMachine->setCurrentIndex(selectedMachineRow); + ui->comboBoxMachine->setCurrentIndex(-1); + ui->comboBoxMachine->setCurrentIndex(selectedMachineRow); + } } - -void SettingsMachine::on_comboBoxMachine_currentIndexChanged(int index) { +void +SettingsMachine::on_comboBoxMachine_currentIndexChanged(int index) +{ // win_settings_machine_recalc_machine - if (index < 0) { - return; - } + if (index >= 0) { + int machineId = ui->comboBoxMachine->currentData().toInt(); + const auto *device = machine_get_device(machineId); + ui->pushButtonConfigure->setEnabled((device != nullptr) && (device->config != nullptr)); - int machineId = ui->comboBoxMachine->currentData().toInt(); - const auto* device = machine_getdevice(machineId); - ui->pushButtonConfigure->setEnabled((device != nullptr) && (device->config != nullptr)); + auto *modelCpu = ui->comboBoxCPU->model(); + int removeRows = modelCpu->rowCount(); - auto* modelCpu = ui->comboBoxCPU->model(); - int removeRows = modelCpu->rowCount(); - - int i = 0; - int eligibleRows = 0; - int selectedCpuFamilyRow = 0; - while (cpu_families[i].package != 0) { - if (cpu_family_is_eligible(&cpu_families[i], machineId)) { - Models::AddEntry(modelCpu, QString("%1 %2").arg(cpu_families[i].manufacturer, cpu_families[i].name), i); - if (&cpu_families[i] == cpu_f) { - selectedCpuFamilyRow = eligibleRows; + int i = 0; + int eligibleRows = 0; + int selectedCpuFamilyRow = 0; + while (cpu_families[i].package != 0) { + if (cpu_family_is_eligible(&cpu_families[i], machineId)) { + Models::AddEntry(modelCpu, QString("%1 %2").arg(cpu_families[i].manufacturer, + cpu_families[i].name), i); + if (&cpu_families[i] == cpu_f) + selectedCpuFamilyRow = eligibleRows; + ++eligibleRows; } - ++eligibleRows; + ++i; } - ++i; - } - modelCpu->removeRows(0, removeRows); - ui->comboBoxCPU->setEnabled(eligibleRows > 1); - ui->comboBoxCPU->setCurrentIndex(-1); - ui->comboBoxCPU->setCurrentIndex(selectedCpuFamilyRow); + modelCpu->removeRows(0, removeRows); + ui->comboBoxCPU->setEnabled(eligibleRows > 1); + ui->comboBoxCPU->setCurrentIndex(-1); + ui->comboBoxCPU->setCurrentIndex(selectedCpuFamilyRow); - int divisor; - if ((machine_get_ram_granularity(machineId) < 1024)) { - divisor = 1; - ui->spinBoxRAM->setSuffix(QCoreApplication::translate("", "KB").prepend(' ')); - } else { - divisor = 1024; - ui->spinBoxRAM->setSuffix(QCoreApplication::translate("", "MB").prepend(' ')); - } - ui->spinBoxRAM->setMinimum(machine_get_min_ram(machineId) / divisor); - ui->spinBoxRAM->setMaximum(machine_get_max_ram(machineId) / divisor); - ui->spinBoxRAM->setSingleStep(machine_get_ram_granularity(machineId) / divisor); - ui->spinBoxRAM->setValue(mem_size / divisor); - ui->spinBoxRAM->setEnabled(machine_get_min_ram(machineId) != machine_get_max_ram(machineId)); + int divisor; + if (machine_get_ram_granularity(machineId) < 1024) { + divisor = 1; + ui->spinBoxRAM->setSuffix(QCoreApplication::translate("", "KB").prepend(' ')); + } else { + divisor = 1024; + ui->spinBoxRAM->setSuffix(QCoreApplication::translate("", "MB").prepend(' ')); + } + ui->spinBoxRAM->setMinimum(machine_get_min_ram(machineId) / divisor); + ui->spinBoxRAM->setMaximum(machine_get_max_ram(machineId) / divisor); + ui->spinBoxRAM->setSingleStep(machine_get_ram_granularity(machineId) / divisor); + ui->spinBoxRAM->setValue(mem_size / divisor); + ui->spinBoxRAM->setEnabled(machine_get_min_ram(machineId) != machine_get_max_ram(machineId)); - emit currentMachineChanged(machineId); + emit currentMachineChanged(machineId); + } } +void +SettingsMachine::on_comboBoxCPU_currentIndexChanged(int index) +{ + if (index >= 0) { + int machineId = ui->comboBoxMachine->currentData().toInt(); + int cpuFamilyId = ui->comboBoxCPU->currentData().toInt(); + const auto *cpuFamily = &cpu_families[cpuFamilyId]; -void SettingsMachine::on_comboBoxCPU_currentIndexChanged(int index) { - if (index < 0) { - return; - } + auto *modelSpeed = ui->comboBoxSpeed->model(); + int removeRows = modelSpeed->rowCount(); - int machineId = ui->comboBoxMachine->currentData().toInt(); - int cpuFamilyId = ui->comboBoxCPU->currentData().toInt(); - const auto* cpuFamily = &cpu_families[cpuFamilyId]; - - auto* modelSpeed = ui->comboBoxSpeed->model(); - int removeRows = modelSpeed->rowCount(); - - // win_settings_machine_recalc_cpu_m - int i = 0; - int eligibleRows = 0; - int selectedSpeedRow = 0; - while (cpuFamily->cpus[i].cpu_type != 0) { - if (cpu_is_eligible(cpuFamily, i, machineId)) { - Models::AddEntry(modelSpeed, QString("%1").arg(cpuFamily->cpus[i].name), i); - if (cpu == i) { - selectedSpeedRow = eligibleRows; + // win_settings_machine_recalc_cpu_m + int i = 0; + int eligibleRows = 0; + int selectedSpeedRow = 0; + while (cpuFamily->cpus[i].cpu_type != 0) { + if (cpu_is_eligible(cpuFamily, i, machineId)) { + Models::AddEntry(modelSpeed, QString("%1").arg(cpuFamily->cpus[i].name), i); + if (cpu == i) + selectedSpeedRow = eligibleRows; + ++eligibleRows; } - ++eligibleRows; + ++i; } - ++i; + modelSpeed->removeRows(0, removeRows); + ui->comboBoxSpeed->setEnabled(eligibleRows > 1); + ui->comboBoxSpeed->setCurrentIndex(-1); + ui->comboBoxSpeed->setCurrentIndex(selectedSpeedRow); } - modelSpeed->removeRows(0, removeRows); - ui->comboBoxSpeed->setEnabled(eligibleRows > 1); - ui->comboBoxSpeed->setCurrentIndex(-1); - ui->comboBoxSpeed->setCurrentIndex(selectedSpeedRow); } +void +SettingsMachine::on_comboBoxSpeed_currentIndexChanged(int index) +{ + if (index >= 0) { + // win_settings_machine_recalc_cpu + int cpuFamilyId = ui->comboBoxCPU->currentData().toInt(); + const auto *cpuFamily = &cpu_families[cpuFamilyId]; + int cpuId = ui->comboBoxSpeed->currentData().toInt(); + uint cpuType = cpuFamily->cpus[cpuId].cpu_type; -void SettingsMachine::on_comboBoxSpeed_currentIndexChanged(int index) { - if (index < 0) { - return; - } - - // win_settings_machine_recalc_cpu - int cpuFamilyId = ui->comboBoxCPU->currentData().toInt(); - const auto* cpuFamily = &cpu_families[cpuFamilyId]; - int cpuId = ui->comboBoxSpeed->currentData().toInt(); - uint cpuType = cpuFamily->cpus[cpuId].cpu_type; - - if ((cpuType >= CPU_286) && (cpuType <= CPU_386DX)) { - ui->comboBoxWaitStates->setEnabled(true); - ui->comboBoxWaitStates->setCurrentIndex(cpu_waitstates); - } else { - ui->comboBoxWaitStates->setCurrentIndex(0); - ui->comboBoxWaitStates->setEnabled(false); - } + if ((cpuType >= CPU_286) && (cpuType <= CPU_386DX)) { + ui->comboBoxWaitStates->setEnabled(true); + ui->comboBoxWaitStates->setCurrentIndex(cpu_waitstates); + } else { + ui->comboBoxWaitStates->setCurrentIndex(0); + ui->comboBoxWaitStates->setEnabled(false); + } #ifdef USE_DYNAREC - uint8_t flags = cpuFamily->cpus[cpuId].cpu_flags; - if (! (flags & CPU_SUPPORTS_DYNAREC)) { - ui->checkBoxDynamicRecompiler->setChecked(false); - ui->checkBoxDynamicRecompiler->setEnabled(false); - } else if (flags & CPU_REQUIRES_DYNAREC) { - ui->checkBoxDynamicRecompiler->setChecked(true); - ui->checkBoxDynamicRecompiler->setEnabled(false); - } else { - ui->checkBoxDynamicRecompiler->setChecked(cpu_use_dynarec); - ui->checkBoxDynamicRecompiler->setEnabled(true); - } + uint8_t flags = cpuFamily->cpus[cpuId].cpu_flags; + if (!(flags & CPU_SUPPORTS_DYNAREC)) { + ui->checkBoxDynamicRecompiler->setChecked(false); + ui->checkBoxDynamicRecompiler->setEnabled(false); + } else if ((flags & CPU_REQUIRES_DYNAREC) && !cpu_override) { + ui->checkBoxDynamicRecompiler->setChecked(true); + ui->checkBoxDynamicRecompiler->setEnabled(false); + } else { + ui->checkBoxDynamicRecompiler->setChecked(cpu_use_dynarec); + ui->checkBoxDynamicRecompiler->setEnabled(true); + } #endif - // win_settings_machine_recalc_fpu - auto* modelFpu = ui->comboBoxFPU->model(); - int removeRows = modelFpu->rowCount(); + // win_settings_machine_recalc_fpu + auto *modelFpu = ui->comboBoxFPU->model(); + int removeRows = modelFpu->rowCount(); - int i = 0; - int selectedFpuRow = 0; - for (const char* fpuName = fpu_get_name_from_index(cpuFamily, cpuId, i); fpuName != nullptr; fpuName = fpu_get_name_from_index(cpuFamily, cpuId, ++i)) { - auto fpuType = fpu_get_type_from_index(cpuFamily, cpuId, i); - Models::AddEntry(modelFpu, QString("%1").arg(fpuName), fpuType); - if (fpu_type == fpuType) { - selectedFpuRow = i; + int i = 0; + int selectedFpuRow = 0; + for (const char *fpuName = fpu_get_name_from_index(cpuFamily, cpuId, i); + fpuName != nullptr; fpuName = fpu_get_name_from_index(cpuFamily, cpuId, ++i)) { + auto fpuType = fpu_get_type_from_index(cpuFamily, cpuId, i); + Models::AddEntry(modelFpu, QString("%1").arg(fpuName), fpuType); + if (fpu_type == fpuType) + selectedFpuRow = i; + } + + modelFpu->removeRows(0, removeRows); + ui->comboBoxFPU->setEnabled(modelFpu->rowCount() > 1); + ui->comboBoxFPU->setCurrentIndex(-1); + ui->comboBoxFPU->setCurrentIndex(selectedFpuRow); + } +} + +void +SettingsMachine::on_comboBoxFPU_currentIndexChanged(int index) +{ + if (index >= 0) { + int cpuFamilyId = ui->comboBoxCPU->currentData().toInt(); + const auto *cpuFamily = &cpu_families[cpuFamilyId]; + int cpuId = ui->comboBoxSpeed->currentData().toInt(); + int machineId = ui->comboBoxMachine->currentData().toInt(); + + if (fpu_get_type_from_index(cpuFamily, cpuId, index) == FPU_NONE) { + ui->checkBoxFPUSoftfloat->setChecked(false); + ui->checkBoxFPUSoftfloat->setEnabled(false); + } else { + ui->checkBoxFPUSoftfloat->setChecked(machine_has_flags(machineId, MACHINE_SOFTFLOAT_ONLY) ? + true : fpu_softfloat); + ui->checkBoxFPUSoftfloat->setEnabled(machine_has_flags(machineId, MACHINE_SOFTFLOAT_ONLY) ? + false : true); } } - - modelFpu->removeRows(0, removeRows); - ui->comboBoxFPU->setEnabled(modelFpu->rowCount() > 1); - ui->comboBoxFPU->setCurrentIndex(-1); - ui->comboBoxFPU->setCurrentIndex(selectedFpuRow); } -void SettingsMachine::on_pushButtonConfigure_clicked() { +void +SettingsMachine::on_pushButtonConfigure_clicked() +{ // deviceconfig_inst_open - int machineId = ui->comboBoxMachine->currentData().toInt(); - const auto* device = machine_getdevice(machineId); - DeviceConfig::ConfigureDevice(device, 0, qobject_cast(Settings::settings)); + int machineId = ui->comboBoxMachine->currentData().toInt(); + const auto *device = machine_get_device(machineId); + DeviceConfig::ConfigureDevice(device, 0, qobject_cast(Settings::settings)); } diff --git a/src/qt/qt_settingsmachine.hpp b/src/qt/qt_settingsmachine.hpp index d0d4aabd2..9d0ec62ff 100644 --- a/src/qt/qt_settingsmachine.hpp +++ b/src/qt/qt_settingsmachine.hpp @@ -7,21 +7,23 @@ namespace Ui { class SettingsMachine; } -class SettingsMachine : public QWidget -{ +class SettingsMachine : public QWidget { Q_OBJECT public: - explicit SettingsMachine(QWidget *parent = nullptr); + explicit SettingsMachine(QWidget *parent = nullptr); ~SettingsMachine(); - void save(); + void save(); signals: - void currentMachineChanged(int machineId); + void currentMachineChanged(int machineId); private slots: void on_pushButtonConfigure_clicked(); +private slots: + void on_comboBoxFPU_currentIndexChanged(int index); + private slots: void on_comboBoxSpeed_currentIndexChanged(int index); @@ -32,7 +34,7 @@ private slots: void on_comboBoxMachine_currentIndexChanged(int index); private slots: - void on_comboBoxMachineType_currentIndexChanged(int index); + void on_comboBoxMachineType_currentIndexChanged(int index); private: Ui::SettingsMachine *ui; diff --git a/src/qt/qt_settingsmachine.ui b/src/qt/qt_settingsmachine.ui index fabb52fe9..22ecc15df 100644 --- a/src/qt/qt_settingsmachine.ui +++ b/src/qt/qt_settingsmachine.ui @@ -7,7 +7,7 @@ 0 0 458 - 390 + 434 @@ -28,7 +28,7 @@ - + 0 @@ -41,68 +41,93 @@ 0 - - - - Machine type: - - - - - - - - - - Machine: - - - - - - - CPU type: - - - - - - FPU: - - - - Wait states: - + + + + 30 + + + + Memory: - - - - - - - - - - - 0 - 0 - + + + + 30 - + + + + + 0 + + + 0 + + + 0 + + + 0 + + + + + 30 + + + + 0 + 0 + + + + + + + + PIT Mode: + + + + + + + 30 + + + + 0 + 0 + + + + + + + + + + + CPU type: + + + + @@ -119,6 +144,9 @@ + + 30 + 0 @@ -139,6 +167,9 @@ + + 30 + 0 @@ -150,7 +181,17 @@ - + + + + + 0 + 0 + + + + + @@ -166,7 +207,11 @@ 0 - + + + 30 + + @@ -184,6 +229,27 @@ + + + + Machine type: + + + + + + + Machine: + + + + + + + FPU: + + + @@ -200,8 +266,27 @@ + + + + + 3 + 3 + + + + Softfloat FPU + + + + + + 0 + 0 + + Time synchronization diff --git a/src/qt/qt_settingsnetwork.cpp b/src/qt/qt_settingsnetwork.cpp index 290fea43b..2aa3705fd 100644 --- a/src/qt/qt_settingsnetwork.cpp +++ b/src/qt/qt_settingsnetwork.cpp @@ -1,18 +1,18 @@ /* - * 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. + * 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. + * This file is part of the 86Box distribution. * - * Network devices configuration UI module. + * Network devices configuration UI module. * * * - * Authors: Joakim L. Gilje + * Authors: Joakim L. Gilje * - * Copyright 2021 Joakim L. Gilje + * Copyright 2021 Joakim L. Gilje */ #include "qt_settingsnetwork.hpp" #include "ui_qt_settingsnetwork.h" @@ -21,49 +21,58 @@ extern "C" { #include <86box/86box.h> #include <86box/device.h> #include <86box/machine.h> +#include <86box/timer.h> +#include <86box/thread.h> #include <86box/network.h> } #include "qt_models_common.hpp" #include "qt_deviceconfig.hpp" -static void enableElements(Ui::SettingsNetwork *ui) { - int netType = ui->comboBoxNetwork->currentData().toInt(); - ui->comboBoxPcap->setEnabled(netType == NET_TYPE_PCAP); +void +SettingsNetwork::enableElements(Ui::SettingsNetwork *ui) +{ + for (int i = 0; i < NET_CARD_MAX; ++i) { + auto *nic_cbox = findChild(QString("comboBoxNIC%1").arg(i + 1)); + auto *net_type_cbox = findChild(QString("comboBoxNet%1").arg(i + 1)); + auto *intf_cbox = findChild(QString("comboBoxIntf%1").arg(i + 1)); + auto *conf_btn = findChild(QString("pushButtonConf%1").arg(i + 1)); + auto *socket_line = findChild(QString("socketVDENIC%1").arg(i + 1)); - bool adaptersEnabled = netType == NET_TYPE_SLIRP || - (netType == NET_TYPE_PCAP && ui->comboBoxPcap->currentData().toInt() > 0); - ui->comboBoxAdapter->setEnabled(adaptersEnabled); - ui->pushButtonConfigure->setEnabled(adaptersEnabled && ui->comboBoxAdapter->currentIndex() > 0 && network_card_has_config(ui->comboBoxAdapter->currentData().toInt())); + int netType = net_type_cbox->currentData().toInt(); + bool adaptersEnabled = netType == NET_TYPE_NONE + || netType == NET_TYPE_SLIRP + || netType == NET_TYPE_VDE + || (netType == NET_TYPE_PCAP && intf_cbox->currentData().toInt() > 0); + + intf_cbox->setEnabled(net_type_cbox->currentData().toInt() == NET_TYPE_PCAP); + nic_cbox->setEnabled(adaptersEnabled); + int netCard = nic_cbox->currentData().toInt(); + if ((i == 0) && (netCard == NET_INTERNAL)) + conf_btn->setEnabled(adaptersEnabled && machine_has_flags(machineId, MACHINE_NIC) && + device_has_config(machine_get_net_device(machineId))); + else + conf_btn->setEnabled(adaptersEnabled && network_card_has_config(nic_cbox->currentData().toInt())); + socket_line->setEnabled(net_type_cbox->currentData().toInt() == NET_TYPE_VDE); + } } -SettingsNetwork::SettingsNetwork(QWidget *parent) : - QWidget(parent), - ui(new Ui::SettingsNetwork) +SettingsNetwork::SettingsNetwork(QWidget *parent) + : QWidget(parent) + , ui(new Ui::SettingsNetwork) { ui->setupUi(this); - auto* model = ui->comboBoxNetwork->model(); - Models::AddEntry(model, tr("None"), NET_TYPE_NONE); - Models::AddEntry(model, "PCap", NET_TYPE_PCAP); - Models::AddEntry(model, "SLiRP", NET_TYPE_SLIRP); - ui->comboBoxNetwork->setCurrentIndex(network_type); - - int selectedRow = 0; - model = ui->comboBoxPcap->model(); - QString currentPcapDevice = network_host; - for (int c = 0; c < network_ndev; c++) { - - Models::AddEntry(model, tr(network_devs[c].description), c); - if (QString(network_devs[c].device) == currentPcapDevice) { - selectedRow = c; - } - } - ui->comboBoxPcap->setCurrentIndex(-1); - ui->comboBoxPcap->setCurrentIndex(selectedRow); - onCurrentMachineChanged(machine); enableElements(ui); + for (int i = 0; i < NET_CARD_MAX; i++) { + auto *nic_cbox = findChild(QString("comboBoxNIC%1").arg(i + 1)); + auto *net_type_cbox = findChild(QString("comboBoxNet%1").arg(i + 1)); + auto *intf_cbox = findChild(QString("comboBoxIntf%1").arg(i + 1)); + connect(nic_cbox, QOverload::of(&QComboBox::currentIndexChanged), this, &SettingsNetwork::on_comboIndexChanged); + connect(net_type_cbox, QOverload::of(&QComboBox::currentIndexChanged), this, &SettingsNetwork::on_comboIndexChanged); + connect(intf_cbox, QOverload::of(&QComboBox::currentIndexChanged), this, &SettingsNetwork::on_comboIndexChanged); + } } SettingsNetwork::~SettingsNetwork() @@ -71,43 +80,109 @@ SettingsNetwork::~SettingsNetwork() delete ui; } -void SettingsNetwork::save() { - network_type = ui->comboBoxNetwork->currentData().toInt(); - memset(network_host, '\0', sizeof(network_host)); - strcpy(network_host, network_devs[ui->comboBoxPcap->currentData().toInt()].device); - network_card = ui->comboBoxAdapter->currentData().toInt(); +void +SettingsNetwork::save() +{ + for (int i = 0; i < NET_CARD_MAX; ++i) { + auto *cbox = findChild(QString("comboBoxNIC%1").arg(i + 1)); + auto *socket_line = findChild(QString("socketVDENIC%1").arg(i + 1)); + net_cards_conf[i].device_num = cbox->currentData().toInt(); + cbox = findChild(QString("comboBoxNet%1").arg(i + 1)); + net_cards_conf[i].net_type = cbox->currentData().toInt(); + cbox = findChild(QString("comboBoxIntf%1").arg(i + 1)); + memset(net_cards_conf[i].host_dev_name, '\0', sizeof(net_cards_conf[i].host_dev_name)); + if (net_cards_conf[i].net_type == NET_TYPE_PCAP) { + strncpy(net_cards_conf[i].host_dev_name, network_devs[cbox->currentData().toInt()].device, sizeof(net_cards_conf[i].host_dev_name) - 1); + } else if (net_cards_conf[i].net_type == NET_TYPE_VDE) { + strncpy(net_cards_conf[i].host_dev_name, socket_line->text().toUtf8().constData(), sizeof(net_cards_conf[i].host_dev_name)); + } + } } -void SettingsNetwork::onCurrentMachineChanged(int machineId) { +void +SettingsNetwork::onCurrentMachineChanged(int machineId) +{ this->machineId = machineId; - auto* machine = &machines[machineId]; - auto* model = ui->comboBoxAdapter->model(); - auto removeRows = model->rowCount(); - int c = 0; + int c = 0; int selectedRow = 0; - while (true) { - auto name = DeviceConfig::DeviceName(network_card_getdevice(c), network_card_get_internal_name(c), 1); - if (name.isEmpty()) { - break; - } - if (network_card_available(c) && device_is_valid(network_card_getdevice(c), machineId)) { - int row = Models::AddEntry(model, name, c); - if (c == network_card) { - selectedRow = row - removeRows; + for (int i = 0; i < NET_CARD_MAX; ++i) { + auto *cbox = findChild(QString("comboBoxNIC%1").arg(i + 1)); + auto *model = cbox->model(); + auto removeRows = model->rowCount(); + c = 0; + selectedRow = 0; + + while (true) { + /* Skip "internal" if machine doesn't have it or this is not the primary card. */ + if ((c == 1) && ((i > 0) || (machine_has_flags(machineId, MACHINE_NIC) == 0))) { + c++; + continue; } + + auto name = DeviceConfig::DeviceName(network_card_getdevice(c), network_card_get_internal_name(c), 1); + if (name.isEmpty()) { + break; + } + + if (network_card_available(c) && device_is_valid(network_card_getdevice(c), machineId)) { + int row = Models::AddEntry(model, name, c); + if (c == net_cards_conf[i].device_num) { + selectedRow = row - removeRows; + } + } + c++; } - c++; + model->removeRows(0, removeRows); + cbox->setEnabled(model->rowCount() > 0); + cbox->setCurrentIndex(-1); + cbox->setCurrentIndex(selectedRow); + + cbox = findChild(QString("comboBoxNet%1").arg(i + 1)); + model = cbox->model(); + removeRows = model->rowCount(); + Models::AddEntry(model, tr("Null Driver"), NET_TYPE_NONE); + Models::AddEntry(model, "SLiRP", NET_TYPE_SLIRP); + + if (network_ndev > 1) { + Models::AddEntry(model, "PCap", NET_TYPE_PCAP); + } + if (network_devmap.has_vde) { + Models::AddEntry(model, "VDE", NET_TYPE_VDE); + } + + model->removeRows(0, removeRows); + cbox->setCurrentIndex(net_cards_conf[i].net_type); + + selectedRow = 0; + + if (network_ndev > 0) { + QString currentPcapDevice = net_cards_conf[i].host_dev_name; + cbox = findChild(QString("comboBoxIntf%1").arg(i + 1)); + model = cbox->model(); + removeRows = model->rowCount(); + for (int c = 0; c < network_ndev; c++) { + Models::AddEntry(model, tr(network_devs[c].description), c); + if (QString(network_devs[c].device) == currentPcapDevice) { + selectedRow = c; + } + } + model->removeRows(0, removeRows); + cbox->setCurrentIndex(selectedRow); + } + if (net_cards_conf[i].net_type == NET_TYPE_VDE) { + QString currentVdeSocket = net_cards_conf[i].host_dev_name; + auto editline = findChild(QString("socketVDENIC%1").arg(i+1)); + editline->setText(currentVdeSocket); + } } - model->removeRows(0, removeRows); - ui->comboBoxAdapter->setEnabled(model->rowCount() > 0); - ui->comboBoxAdapter->setCurrentIndex(-1); - ui->comboBoxAdapter->setCurrentIndex(selectedRow); } -void SettingsNetwork::on_comboBoxNetwork_currentIndexChanged(int index) { +void +SettingsNetwork::on_comboIndexChanged(int index) +{ if (index < 0) { return; } @@ -115,15 +190,36 @@ void SettingsNetwork::on_comboBoxNetwork_currentIndexChanged(int index) { enableElements(ui); } -void SettingsNetwork::on_comboBoxAdapter_currentIndexChanged(int index) { - if (index < 0) { - return; - } - - enableElements(ui); +void +SettingsNetwork::on_pushButtonConf1_clicked() +{ + int netCard = ui->comboBoxNIC1->currentData().toInt(); + auto *device = network_card_getdevice(netCard); + if (netCard == NET_INTERNAL) + device = machine_get_net_device(machineId); + DeviceConfig::ConfigureDevice(device, 1, qobject_cast(Settings::settings)); } -void SettingsNetwork::on_pushButtonConfigure_clicked() { - DeviceConfig::ConfigureDevice(network_card_getdevice(ui->comboBoxAdapter->currentData().toInt()), 0, qobject_cast(Settings::settings)); +void +SettingsNetwork::on_pushButtonConf2_clicked() +{ + int netCard = ui->comboBoxNIC2->currentData().toInt(); + auto *device = network_card_getdevice(netCard); + DeviceConfig::ConfigureDevice(device, 2, qobject_cast(Settings::settings)); } +void +SettingsNetwork::on_pushButtonConf3_clicked() +{ + int netCard = ui->comboBoxNIC3->currentData().toInt(); + auto *device = network_card_getdevice(netCard); + DeviceConfig::ConfigureDevice(device, 3, qobject_cast(Settings::settings)); +} + +void +SettingsNetwork::on_pushButtonConf4_clicked() +{ + int netCard = ui->comboBoxNIC4->currentData().toInt(); + auto *device = network_card_getdevice(netCard); + DeviceConfig::ConfigureDevice(device, 4, qobject_cast(Settings::settings)); +} diff --git a/src/qt/qt_settingsnetwork.hpp b/src/qt/qt_settingsnetwork.hpp index f17eb98f1..d39d90896 100644 --- a/src/qt/qt_settingsnetwork.hpp +++ b/src/qt/qt_settingsnetwork.hpp @@ -7,8 +7,7 @@ namespace Ui { class SettingsNetwork; } -class SettingsNetwork : public QWidget -{ +class SettingsNetwork : public QWidget { Q_OBJECT public: @@ -21,13 +20,17 @@ public slots: void onCurrentMachineChanged(int machineId); private slots: - void on_pushButtonConfigure_clicked(); - void on_comboBoxAdapter_currentIndexChanged(int index); - void on_comboBoxNetwork_currentIndexChanged(int index); + void on_pushButtonConf1_clicked(); + void on_pushButtonConf2_clicked(); + void on_pushButtonConf3_clicked(); + void on_pushButtonConf4_clicked(); + void on_comboIndexChanged(int index); + + void enableElements(Ui::SettingsNetwork *ui); private: Ui::SettingsNetwork *ui; - int machineId = 0; + int machineId = 0; }; #endif // QT_SETTINGSNETWORK_HPP diff --git a/src/qt/qt_settingsnetwork.ui b/src/qt/qt_settingsnetwork.ui index 751e3854d..8f1eb5a79 100644 --- a/src/qt/qt_settingsnetwork.ui +++ b/src/qt/qt_settingsnetwork.ui @@ -6,14 +6,14 @@ 0 0 - 400 - 300 + 548 + 488 Form - + 0 @@ -26,70 +26,519 @@ 0 - - - - Qt::Vertical - - - - 20 - 40 - - - - - - - - PCap device: + + + + 0 + + + Network Card #1 + + + + + + + 0 + 0 + + + + Mode + + + + + + + 30 + + + + 0 + 0 + + + + + + + + + 0 + 0 + + + + Interface + + + + + + + 30 + + + + 0 + 0 + + + + + + + + + 0 + 0 + + + + Adapter + + + + + + + 30 + + + + 0 + 0 + + + + QComboBox::AdjustToContents + + + + + + + + 0 + 0 + + + + Configure + + + + + + + VDE Socket + + + + + + + 127 + + + + + + + Qt::Vertical + + + + 20 + 40 + + + + + + + + + Network Card #2 + + + + + + + 0 + 0 + + + + Mode + + + + + + + 30 + + + + 0 + 0 + + + + + + + + + 0 + 0 + + + + Interface + + + + + + + 30 + + + + 0 + 0 + + + + + + + + + 0 + 0 + + + + Adapter + + + + + + + 30 + + + + 0 + 0 + + + + QComboBox::AdjustToContents + + + + + + + Configure + + + + + + + VDE Socket + + + + + + + 127 + + + + + + + Qt::Vertical + + + + 20 + 40 + + + + + + + + + Network Card #3 + + + + + + + 0 + 0 + + + + Mode + + + + + + + 30 + + + + 0 + 0 + + + + + + + + + 0 + 0 + + + + Interface + + + + + + + 30 + + + + 0 + 0 + + + + + + + + + 0 + 0 + + + + Adapter + + + + + + + 30 + + + + 0 + 0 + + + + QComboBox::AdjustToContents + + + + + + + + 0 + 0 + + + + Configure + + + + + + + VDE Socket + + + + + + + 127 + + + + + + + Qt::Vertical + + + + 20 + 40 + + + + + + + + + Network Card #4 + + + + + + + 0 + 0 + + + + Mode + + + + + + + 30 + + + + 0 + 0 + + + + + + + + + 0 + 0 + + + + Interface + + + + + + + 30 + + + + 0 + 0 + + + + + + + + + 0 + 0 + + + + Adapter + + + + + + + 30 + + + + 0 + 0 + + + + QComboBox::AdjustToContents + + + + + + + + 0 + 0 + + + + Configure + + + + + + + 127 + + + + + + + VDE Socket + + + + + + + Qt::Vertical + + + + 20 + 40 + + + + + + - - - - Network type: - - - - - - - - 0 - 0 - - - - - - - - Network adapter: - - - - - - - Configure - - - - - - - - 0 - 0 - - - - - - - diff --git a/src/qt/qt_settingsotherperipherals.cpp b/src/qt/qt_settingsotherperipherals.cpp index ebf849d28..d168138a5 100644 --- a/src/qt/qt_settingsotherperipherals.cpp +++ b/src/qt/qt_settingsotherperipherals.cpp @@ -1,18 +1,18 @@ /* - * 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. + * 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. + * This file is part of the 86Box distribution. * - * Other peripherals configuration UI module. + * Other peripherals configuration UI module. * * * - * Authors: Joakim L. Gilje + * Authors: Joakim L. Gilje * - * Copyright 2021 Joakim L. Gilje + * Copyright 2021 Joakim L. Gilje */ #include "qt_settingsotherperipherals.hpp" #include "ui_qt_settingsotherperipherals.h" @@ -28,23 +28,25 @@ extern "C" { #include "qt_deviceconfig.hpp" #include "qt_models_common.hpp" -SettingsOtherPeripherals::SettingsOtherPeripherals(QWidget *parent) : - QWidget(parent), - ui(new Ui::SettingsOtherPeripherals) +SettingsOtherPeripherals::SettingsOtherPeripherals(QWidget *parent) + : QWidget(parent) + , ui(new Ui::SettingsOtherPeripherals) { ui->setupUi(this); onCurrentMachineChanged(machine); } -void SettingsOtherPeripherals::onCurrentMachineChanged(int machineId) +void +SettingsOtherPeripherals::onCurrentMachineChanged(int machineId) { this->machineId = machineId; - ui->checkBoxISABugger->setChecked(bugger_enabled > 0 ? true : false); + bool machineHasIsa = (machine_has_bus(machineId, MACHINE_BUS_ISA) > 0); + ui->checkBoxISABugger->setChecked((machineHasIsa && (bugger_enabled > 0)) ? true : false); ui->checkBoxPOSTCard->setChecked(postcard_enabled > 0 ? true : false); - ui->checkBoxISABugger->setEnabled(machine_has_bus(machineId, MACHINE_BUS_ISA)); - ui->comboBoxRTC->setEnabled(machine_has_bus(machineId, MACHINE_BUS_ISA)); - ui->pushButtonConfigureRTC->setEnabled(machine_has_bus(machineId, MACHINE_BUS_ISA)); + ui->checkBoxISABugger->setEnabled(machineHasIsa); + ui->comboBoxRTC->setEnabled(machineHasIsa); + ui->pushButtonConfigureRTC->setEnabled(machineHasIsa); ui->comboBoxCard1->clear(); ui->comboBoxCard2->clear(); @@ -52,9 +54,9 @@ void SettingsOtherPeripherals::onCurrentMachineChanged(int machineId) ui->comboBoxCard4->clear(); ui->comboBoxRTC->clear(); - auto* model = ui->comboBoxRTC->model(); - int d = 0; - int selectedRow = 0; + auto *model = ui->comboBoxRTC->model(); + int d = 0; + int selectedRow = 0; while (true) { QString name = DeviceConfig::DeviceName(isartc_get_device(d), isartc_get_internal_name(d), 0); if (name.isEmpty()) { @@ -74,9 +76,9 @@ void SettingsOtherPeripherals::onCurrentMachineChanged(int machineId) ui->comboBoxRTC->setCurrentIndex(selectedRow); for (int c = 0; c < ISAMEM_MAX; c++) { - auto* cbox = findChild(QString("comboBoxCard%1").arg(c + 1)); - model = cbox->model(); - d = 0; + auto *cbox = findChild(QString("comboBoxCard%1").arg(c + 1)); + model = cbox->model(); + d = 0; selectedRow = 0; while (true) { QString name = DeviceConfig::DeviceName(isamem_get_device(d), isamem_get_internal_name(d), 0); @@ -96,8 +98,8 @@ void SettingsOtherPeripherals::onCurrentMachineChanged(int machineId) } cbox->setCurrentIndex(-1); cbox->setCurrentIndex(selectedRow); - cbox->setEnabled(machine_has_bus(machineId, MACHINE_BUS_ISA)); - findChild(QString("pushButtonConfigureCard%1").arg(c + 1))->setEnabled(isamem_type[c] != 0 && machine_has_bus(machineId, MACHINE_BUS_ISA)); + cbox->setEnabled(machineHasIsa); + findChild(QString("pushButtonConfigureCard%1").arg(c + 1))->setEnabled(isamem_type[c] != 0 && machineHasIsa); } } @@ -106,70 +108,92 @@ SettingsOtherPeripherals::~SettingsOtherPeripherals() delete ui; } -void SettingsOtherPeripherals::save() { +void +SettingsOtherPeripherals::save() +{ /* Other peripherals category */ - bugger_enabled = ui->checkBoxISABugger->isChecked() ? 1 : 0; + bugger_enabled = ui->checkBoxISABugger->isChecked() ? 1 : 0; postcard_enabled = ui->checkBoxPOSTCard->isChecked() ? 1 : 0; - isartc_type = ui->comboBoxRTC->currentData().toInt(); + isartc_type = ui->comboBoxRTC->currentData().toInt(); /* ISA memory boards. */ for (int i = 0; i < ISAMEM_MAX; i++) { - auto* cbox = findChild(QString("comboBoxCard%1").arg(i + 1)); + auto *cbox = findChild(QString("comboBoxCard%1").arg(i + 1)); isamem_type[i] = cbox->currentData().toInt(); } } -void SettingsOtherPeripherals::on_comboBoxRTC_currentIndexChanged(int index) { +void +SettingsOtherPeripherals::on_comboBoxRTC_currentIndexChanged(int index) +{ if (index < 0) { return; } ui->pushButtonConfigureRTC->setEnabled(index != 0 && machine_has_bus(machineId, MACHINE_BUS_ISA)); } -void SettingsOtherPeripherals::on_pushButtonConfigureRTC_clicked() { - DeviceConfig::ConfigureDevice(isartc_get_device(ui->comboBoxRTC->currentData().toInt()), 0, qobject_cast(Settings::settings)); +void +SettingsOtherPeripherals::on_pushButtonConfigureRTC_clicked() +{ + DeviceConfig::ConfigureDevice(isartc_get_device(ui->comboBoxRTC->currentData().toInt()), 0, qobject_cast(Settings::settings)); } -void SettingsOtherPeripherals::on_comboBoxCard1_currentIndexChanged(int index) { +void +SettingsOtherPeripherals::on_comboBoxCard1_currentIndexChanged(int index) +{ if (index < 0) { return; } ui->pushButtonConfigureCard1->setEnabled(index != 0 && machine_has_bus(machineId, MACHINE_BUS_ISA)); } -void SettingsOtherPeripherals::on_pushButtonConfigureCard1_clicked() { - DeviceConfig::ConfigureDevice(isamem_get_device(ui->comboBoxCard1->currentData().toInt()), 1, qobject_cast(Settings::settings)); +void +SettingsOtherPeripherals::on_pushButtonConfigureCard1_clicked() +{ + DeviceConfig::ConfigureDevice(isamem_get_device(ui->comboBoxCard1->currentData().toInt()), 1, qobject_cast(Settings::settings)); } -void SettingsOtherPeripherals::on_comboBoxCard2_currentIndexChanged(int index) { +void +SettingsOtherPeripherals::on_comboBoxCard2_currentIndexChanged(int index) +{ if (index < 0) { return; } ui->pushButtonConfigureCard2->setEnabled(index != 0 && machine_has_bus(machineId, MACHINE_BUS_ISA)); } -void SettingsOtherPeripherals::on_pushButtonConfigureCard2_clicked() { - DeviceConfig::ConfigureDevice(isamem_get_device(ui->comboBoxCard2->currentData().toInt()), 2, qobject_cast(Settings::settings)); +void +SettingsOtherPeripherals::on_pushButtonConfigureCard2_clicked() +{ + DeviceConfig::ConfigureDevice(isamem_get_device(ui->comboBoxCard2->currentData().toInt()), 2, qobject_cast(Settings::settings)); } -void SettingsOtherPeripherals::on_comboBoxCard3_currentIndexChanged(int index) { +void +SettingsOtherPeripherals::on_comboBoxCard3_currentIndexChanged(int index) +{ if (index < 0) { return; } ui->pushButtonConfigureCard3->setEnabled(index != 0 && machine_has_bus(machineId, MACHINE_BUS_ISA)); } -void SettingsOtherPeripherals::on_pushButtonConfigureCard3_clicked() { - DeviceConfig::ConfigureDevice(isamem_get_device(ui->comboBoxCard3->currentData().toInt()), 3, qobject_cast(Settings::settings)); +void +SettingsOtherPeripherals::on_pushButtonConfigureCard3_clicked() +{ + DeviceConfig::ConfigureDevice(isamem_get_device(ui->comboBoxCard3->currentData().toInt()), 3, qobject_cast(Settings::settings)); } -void SettingsOtherPeripherals::on_comboBoxCard4_currentIndexChanged(int index) { +void +SettingsOtherPeripherals::on_comboBoxCard4_currentIndexChanged(int index) +{ if (index < 0) { return; } ui->pushButtonConfigureCard4->setEnabled(index != 0 && machine_has_bus(machineId, MACHINE_BUS_ISA)); } -void SettingsOtherPeripherals::on_pushButtonConfigureCard4_clicked() { - DeviceConfig::ConfigureDevice(isamem_get_device(ui->comboBoxCard4->currentData().toInt()), 4, qobject_cast(Settings::settings)); +void +SettingsOtherPeripherals::on_pushButtonConfigureCard4_clicked() +{ + DeviceConfig::ConfigureDevice(isamem_get_device(ui->comboBoxCard4->currentData().toInt()), 4, qobject_cast(Settings::settings)); } diff --git a/src/qt/qt_settingsotherperipherals.hpp b/src/qt/qt_settingsotherperipherals.hpp index f8eed2c9e..97e47c90e 100644 --- a/src/qt/qt_settingsotherperipherals.hpp +++ b/src/qt/qt_settingsotherperipherals.hpp @@ -7,8 +7,7 @@ namespace Ui { class SettingsOtherPeripherals; } -class SettingsOtherPeripherals : public QWidget -{ +class SettingsOtherPeripherals : public QWidget { Q_OBJECT public: @@ -34,7 +33,7 @@ private slots: private: Ui::SettingsOtherPeripherals *ui; - int machineId{0}; + int machineId { 0 }; }; #endif // QT_SETTINGSOTHERPERIPHERALS_HPP diff --git a/src/qt/qt_settingsotherperipherals.ui b/src/qt/qt_settingsotherperipherals.ui index 62a4b9308..01f5545f8 100644 --- a/src/qt/qt_settingsotherperipherals.ui +++ b/src/qt/qt_settingsotherperipherals.ui @@ -37,6 +37,9 @@ + + 30 + 0 @@ -68,7 +71,17 @@ - + + + 30 + + + + 0 + 0 + + + @@ -100,6 +113,9 @@ + + 30 + 0 @@ -116,10 +132,30 @@ - + + + 30 + + + + 0 + 0 + + + - + + + 30 + + + + 0 + 0 + + + diff --git a/src/qt/qt_settingsotherremovable.cpp b/src/qt/qt_settingsotherremovable.cpp index 574fdccb5..f8b29dac5 100644 --- a/src/qt/qt_settingsotherremovable.cpp +++ b/src/qt/qt_settingsotherremovable.cpp @@ -1,20 +1,20 @@ /* - * 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. + * 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. + * This file is part of the 86Box distribution. * - * Other removable devices configuration UI module. + * Other removable devices configuration UI module. * * * - * Authors: Joakim L. Gilje + * Authors: Joakim L. Gilje * Cacodemon345 * - * Copyright 2021-2022 Cacodemon345 - * Copyright 2021 Joakim L. Gilje + * Copyright 2021-2022 Cacodemon345 + * Copyright 2021 Joakim L. Gilje */ #include "qt_settingsotherremovable.hpp" #include "ui_qt_settingsotherremovable.h" @@ -33,20 +33,28 @@ extern "C" { #include "qt_settings_bus_tracking.hpp" #include "qt_progsettings.hpp" -static QString moDriveTypeName(int i) { - return QString("%1 %2 %3").arg(mo_drive_types[i].vendor, mo_drive_types[i].model, mo_drive_types[i].revision); +static QString +moDriveTypeName(int i) +{ + return QString("%1 %2 %3").arg(mo_drive_types[i].vendor, mo_drive_types[i].model, + mo_drive_types[i].revision); } -static void setMOBus(QAbstractItemModel* model, const QModelIndex& idx, uint8_t bus, uint8_t channel) { +static void +setMOBus(QAbstractItemModel *model, const QModelIndex &idx, uint8_t bus, uint8_t channel) +{ QIcon icon; switch (bus) { - case MO_BUS_DISABLED: - icon = ProgSettings::loadIcon("/mo_disabled.ico"); - break; - case MO_BUS_ATAPI: - case MO_BUS_SCSI: - icon = ProgSettings::loadIcon("/mo.ico"); - break; + case MO_BUS_DISABLED: + icon = ProgSettings::loadIcon("/mo_disabled.ico"); + break; + case MO_BUS_ATAPI: + case MO_BUS_SCSI: + icon = ProgSettings::loadIcon("/mo.ico"); + break; + + default: + break; } auto i = idx.siblingAtColumn(0); @@ -56,26 +64,32 @@ static void setMOBus(QAbstractItemModel* model, const QModelIndex& idx, uint8_t model->setData(i, icon, Qt::DecorationRole); } -static void setMOType(QAbstractItemModel* model, const QModelIndex& idx, uint32_t type) { +static void +setMOType(QAbstractItemModel *model, const QModelIndex &idx, uint32_t type) +{ auto i = idx.siblingAtColumn(1); - if (idx.siblingAtColumn(0).data(Qt::UserRole).toUInt() == MO_BUS_DISABLED) { + if (idx.siblingAtColumn(0).data(Qt::UserRole).toUInt() == MO_BUS_DISABLED) model->setData(i, QCoreApplication::translate("", "None")); - } else { + else model->setData(i, moDriveTypeName(type)); - } model->setData(i, type, Qt::UserRole); } -static void setZIPBus(QAbstractItemModel* model, const QModelIndex& idx, uint8_t bus, uint8_t channel) { +static void +setZIPBus(QAbstractItemModel *model, const QModelIndex &idx, uint8_t bus, uint8_t channel) +{ QIcon icon; switch (bus) { - case ZIP_BUS_DISABLED: - icon = ProgSettings::loadIcon("/zip_disabled.ico"); - break; - case ZIP_BUS_ATAPI: - case ZIP_BUS_SCSI: - icon = ProgSettings::loadIcon("/zip.ico"); - break; + case ZIP_BUS_DISABLED: + icon = ProgSettings::loadIcon("/zip_disabled.ico"); + break; + case ZIP_BUS_ATAPI: + case ZIP_BUS_SCSI: + icon = ProgSettings::loadIcon("/zip.ico"); + break; + + default: + break; } auto i = idx.siblingAtColumn(0); @@ -85,20 +99,22 @@ static void setZIPBus(QAbstractItemModel* model, const QModelIndex& idx, uint8_t model->setData(i, icon, Qt::DecorationRole); } -static void setZIPType(QAbstractItemModel* model, const QModelIndex& idx, bool is250) { +static void +setZIPType(QAbstractItemModel *model, const QModelIndex &idx, bool is250) +{ auto i = idx.siblingAtColumn(1); model->setData(i, is250 ? "ZIP 250" : "ZIP 100"); model->setData(i, is250, Qt::UserRole); } -SettingsOtherRemovable::SettingsOtherRemovable(QWidget *parent) : - QWidget(parent), - ui(new Ui::SettingsOtherRemovable) +SettingsOtherRemovable::SettingsOtherRemovable(QWidget *parent) + : QWidget(parent) + , ui(new Ui::SettingsOtherRemovable) { ui->setupUi(this); Harddrives::populateRemovableBuses(ui->comboBoxMOBus->model()); - auto* model = ui->comboBoxMOType->model(); + auto *model = ui->comboBoxMOType->model(); for (uint32_t i = 0; i < KNOWN_MO_DRIVE_TYPES; i++) { Models::AddEntry(model, moDriveTypeName(i), i); } @@ -120,9 +136,6 @@ SettingsOtherRemovable::SettingsOtherRemovable(QWidget *parent) : connect(ui->tableViewMO->selectionModel(), &QItemSelectionModel::currentRowChanged, this, &SettingsOtherRemovable::onMORowChanged); ui->tableViewMO->setCurrentIndex(model->index(0, 0)); - - - Harddrives::populateRemovableBuses(ui->comboBoxZIPBus->model()); model = new QStandardItemModel(0, 2, this); @@ -148,155 +161,182 @@ SettingsOtherRemovable::~SettingsOtherRemovable() delete ui; } -void SettingsOtherRemovable::save() { - auto* model = ui->tableViewMO->model(); - for (int i = 0; i < MO_NUM; i++) { - mo_drives[i].f = NULL; - mo_drives[i].priv = NULL; +void +SettingsOtherRemovable::save() +{ + const auto *model = ui->tableViewMO->model(); + for (uint8_t i = 0; i < MO_NUM; i++) { + mo_drives[i].fp = NULL; + mo_drives[i].priv = NULL; mo_drives[i].bus_type = model->index(i, 0).data(Qt::UserRole).toUInt(); - mo_drives[i].res = model->index(i, 0).data(Qt::UserRole + 1).toUInt(); - mo_drives[i].type = model->index(i, 1).data(Qt::UserRole).toUInt(); + mo_drives[i].res = model->index(i, 0).data(Qt::UserRole + 1).toUInt(); + mo_drives[i].type = model->index(i, 1).data(Qt::UserRole).toUInt(); } model = ui->tableViewZIP->model(); - for (int i = 0; i < ZIP_NUM; i++) { - zip_drives[i].f = NULL; - zip_drives[i].priv = NULL; + for (uint8_t i = 0; i < ZIP_NUM; i++) { + zip_drives[i].fp = NULL; + zip_drives[i].priv = NULL; zip_drives[i].bus_type = model->index(i, 0).data(Qt::UserRole).toUInt(); - zip_drives[i].res = model->index(i, 0).data(Qt::UserRole + 1).toUInt(); - zip_drives[i].is_250 = model->index(i, 1).data(Qt::UserRole).toBool() ? 1 : 0; + zip_drives[i].res = model->index(i, 0).data(Qt::UserRole + 1).toUInt(); + zip_drives[i].is_250 = model->index(i, 1).data(Qt::UserRole).toBool() ? 1 : 0; } } -void SettingsOtherRemovable::onMORowChanged(const QModelIndex ¤t) { - uint8_t bus = current.siblingAtColumn(0).data(Qt::UserRole).toUInt(); +void +SettingsOtherRemovable::onMORowChanged(const QModelIndex ¤t) +{ + uint8_t bus = current.siblingAtColumn(0).data(Qt::UserRole).toUInt(); uint8_t channel = current.siblingAtColumn(0).data(Qt::UserRole + 1).toUInt(); - uint8_t type = current.siblingAtColumn(1).data(Qt::UserRole).toUInt(); + uint8_t type = current.siblingAtColumn(1).data(Qt::UserRole).toUInt(); ui->comboBoxMOBus->setCurrentIndex(-1); - auto* model = ui->comboBoxMOBus->model(); - auto match = model->match(model->index(0, 0), Qt::UserRole, bus); - if (! match.isEmpty()) { + const auto *model = ui->comboBoxMOBus->model(); + auto match = model->match(model->index(0, 0), Qt::UserRole, bus); + if (!match.isEmpty()) ui->comboBoxMOBus->setCurrentIndex(match.first().row()); - } model = ui->comboBoxMOChannel->model(); match = model->match(model->index(0, 0), Qt::UserRole, channel); - if (! match.isEmpty()) { + if (!match.isEmpty()) ui->comboBoxMOChannel->setCurrentIndex(match.first().row()); - } ui->comboBoxMOType->setCurrentIndex(type); } -void SettingsOtherRemovable::onZIPRowChanged(const QModelIndex ¤t) { - uint8_t bus = current.siblingAtColumn(0).data(Qt::UserRole).toUInt(); +void +SettingsOtherRemovable::onZIPRowChanged(const QModelIndex ¤t) +{ + uint8_t bus = current.siblingAtColumn(0).data(Qt::UserRole).toUInt(); uint8_t channel = current.siblingAtColumn(0).data(Qt::UserRole + 1).toUInt(); - bool is250 = current.siblingAtColumn(1).data(Qt::UserRole).toBool(); + bool is250 = current.siblingAtColumn(1).data(Qt::UserRole).toBool(); ui->comboBoxZIPBus->setCurrentIndex(-1); - auto* model = ui->comboBoxZIPBus->model(); - auto match = model->match(model->index(0, 0), Qt::UserRole, bus); - if (! match.isEmpty()) { + const auto *model = ui->comboBoxZIPBus->model(); + auto match = model->match(model->index(0, 0), Qt::UserRole, bus); + if (!match.isEmpty()) ui->comboBoxZIPBus->setCurrentIndex(match.first().row()); - } model = ui->comboBoxZIPChannel->model(); match = model->match(model->index(0, 0), Qt::UserRole, channel); - if (! match.isEmpty()) { + if (!match.isEmpty()) ui->comboBoxZIPChannel->setCurrentIndex(match.first().row()); - } ui->checkBoxZIP250->setChecked(is250); } -void SettingsOtherRemovable::on_comboBoxMOBus_currentIndexChanged(int index) { - if (index < 0) { - return; +void +SettingsOtherRemovable::on_comboBoxMOBus_currentIndexChanged(int index) +{ + if (index >= 0) { + int bus = ui->comboBoxMOBus->currentData().toInt(); + bool enabled = (bus != MO_BUS_DISABLED); + ui->comboBoxMOChannel->setEnabled(enabled); + ui->comboBoxMOType->setEnabled(enabled); + Harddrives::populateBusChannels(ui->comboBoxMOChannel->model(), bus); } - - int bus = ui->comboBoxMOBus->currentData().toInt(); - bool enabled = (bus != MO_BUS_DISABLED); - ui->comboBoxMOChannel->setEnabled(enabled); - ui->comboBoxMOType->setEnabled(enabled); - Harddrives::populateBusChannels(ui->comboBoxMOChannel->model(), bus); } -void SettingsOtherRemovable::on_comboBoxMOBus_activated(int) { +void +SettingsOtherRemovable::on_comboBoxMOBus_activated(int) +{ auto i = ui->tableViewMO->selectionModel()->currentIndex().siblingAtColumn(0); - Harddrives::busTrackClass->device_track(0, DEV_MO, ui->tableViewMO->model()->data(i, Qt::UserRole).toInt(), ui->tableViewMO->model()->data(i, Qt::UserRole + 1).toInt()); - ui->comboBoxMOChannel->setCurrentIndex(ui->comboBoxMOBus->currentData().toUInt() == MO_BUS_ATAPI ? Harddrives::busTrackClass->next_free_ide_channel() : Harddrives::busTrackClass->next_free_scsi_id()); + Harddrives::busTrackClass->device_track(0, DEV_MO, ui->tableViewMO->model()->data(i, + Qt::UserRole).toInt(), ui->tableViewMO->model()->data(i, + Qt::UserRole + 1).toInt()); + ui->comboBoxMOChannel->setCurrentIndex(ui->comboBoxMOBus->currentData().toUInt() == + MO_BUS_ATAPI ? Harddrives::busTrackClass->next_free_ide_channel() : + Harddrives::busTrackClass->next_free_scsi_id()); ui->tableViewMO->model()->data(i, Qt::UserRole + 1); - setMOBus( - ui->tableViewMO->model(), - ui->tableViewMO->selectionModel()->currentIndex(), - ui->comboBoxMOBus->currentData().toUInt(), - ui->comboBoxMOChannel->currentData().toUInt()); - setMOType( - ui->tableViewMO->model(), - ui->tableViewMO->selectionModel()->currentIndex(), - ui->comboBoxMOType->currentData().toUInt()); + setMOBus(ui->tableViewMO->model(), + ui->tableViewMO->selectionModel()->currentIndex(), + ui->comboBoxMOBus->currentData().toUInt(), + ui->comboBoxMOChannel->currentData().toUInt()); + setMOType(ui->tableViewMO->model(), + ui->tableViewMO->selectionModel()->currentIndex(), + ui->comboBoxMOType->currentData().toUInt()); ui->tableViewMO->resizeColumnsToContents(); ui->tableViewMO->horizontalHeader()->setSectionResizeMode(0, QHeaderView::Stretch); - Harddrives::busTrackClass->device_track(1, DEV_MO, ui->tableViewMO->model()->data(i, Qt::UserRole).toInt(), ui->tableViewMO->model()->data(i, Qt::UserRole + 1).toInt()); + Harddrives::busTrackClass->device_track(1, DEV_MO, ui->tableViewMO->model()->data(i, + Qt::UserRole).toInt(), ui->tableViewMO->model()->data(i, + Qt::UserRole + 1).toInt()); } -void SettingsOtherRemovable::on_comboBoxMOChannel_activated(int) { +void +SettingsOtherRemovable::on_comboBoxMOChannel_activated(int) +{ auto i = ui->tableViewMO->selectionModel()->currentIndex().siblingAtColumn(0); - Harddrives::busTrackClass->device_track(0, DEV_MO, ui->tableViewMO->model()->data(i, Qt::UserRole).toInt(), ui->tableViewMO->model()->data(i, Qt::UserRole + 1).toInt()); - setMOBus( - ui->tableViewMO->model(), - ui->tableViewMO->selectionModel()->currentIndex(), - ui->comboBoxMOBus->currentData().toUInt(), - ui->comboBoxMOChannel->currentData().toUInt()); - Harddrives::busTrackClass->device_track(1, DEV_MO, ui->tableViewMO->model()->data(i, Qt::UserRole).toInt(), ui->tableViewMO->model()->data(i, Qt::UserRole + 1).toInt()); + Harddrives::busTrackClass->device_track(0, DEV_MO, ui->tableViewMO->model()->data(i, + Qt::UserRole).toInt(), ui->tableViewMO->model()->data(i, + Qt::UserRole + 1).toInt()); + setMOBus(ui->tableViewMO->model(), + ui->tableViewMO->selectionModel()->currentIndex(), + ui->comboBoxMOBus->currentData().toUInt(), + ui->comboBoxMOChannel->currentData().toUInt()); + Harddrives::busTrackClass->device_track(1, DEV_MO, ui->tableViewMO->model()->data(i, + Qt::UserRole).toInt(), ui->tableViewMO->model()->data(i, + Qt::UserRole + 1).toInt()); } -void SettingsOtherRemovable::on_comboBoxMOType_activated(int) { - setMOType( - ui->tableViewMO->model(), - ui->tableViewMO->selectionModel()->currentIndex(), - ui->comboBoxMOType->currentData().toUInt()); +void +SettingsOtherRemovable::on_comboBoxMOType_activated(int) +{ + setMOType(ui->tableViewMO->model(), + ui->tableViewMO->selectionModel()->currentIndex(), + ui->comboBoxMOType->currentData().toUInt()); ui->tableViewMO->resizeColumnsToContents(); ui->tableViewMO->horizontalHeader()->setSectionResizeMode(0, QHeaderView::Stretch); } -void SettingsOtherRemovable::on_comboBoxZIPBus_currentIndexChanged(int index) { - if (index < 0) { - return; +void +SettingsOtherRemovable::on_comboBoxZIPBus_currentIndexChanged(int index) +{ + if (index >= 0) { + int bus = ui->comboBoxZIPBus->currentData().toInt(); + bool enabled = (bus != ZIP_BUS_DISABLED); + ui->comboBoxZIPChannel->setEnabled(enabled); + ui->checkBoxZIP250->setEnabled(enabled); + Harddrives::populateBusChannels(ui->comboBoxZIPChannel->model(), bus); } - - int bus = ui->comboBoxZIPBus->currentData().toInt(); - bool enabled = (bus != ZIP_BUS_DISABLED); - ui->comboBoxZIPChannel->setEnabled(enabled); - ui->checkBoxZIP250->setEnabled(enabled); - Harddrives::populateBusChannels(ui->comboBoxZIPChannel->model(), bus); } -void SettingsOtherRemovable::on_comboBoxZIPBus_activated(int) { +void +SettingsOtherRemovable::on_comboBoxZIPBus_activated(int) +{ auto i = ui->tableViewZIP->selectionModel()->currentIndex().siblingAtColumn(0); - Harddrives::busTrackClass->device_track(0, DEV_ZIP, ui->tableViewZIP->model()->data(i, Qt::UserRole).toInt(), ui->tableViewZIP->model()->data(i, Qt::UserRole + 1).toInt()); - ui->comboBoxZIPChannel->setCurrentIndex(ui->comboBoxZIPBus->currentData().toUInt() == ZIP_BUS_ATAPI ? Harddrives::busTrackClass->next_free_ide_channel() : Harddrives::busTrackClass->next_free_scsi_id()); - setZIPBus( - ui->tableViewZIP->model(), - ui->tableViewZIP->selectionModel()->currentIndex(), - ui->comboBoxZIPBus->currentData().toUInt(), - ui->comboBoxZIPChannel->currentData().toUInt()); - Harddrives::busTrackClass->device_track(1, DEV_ZIP, ui->tableViewZIP->model()->data(i, Qt::UserRole).toInt(), ui->tableViewZIP->model()->data(i, Qt::UserRole + 1).toInt()); + Harddrives::busTrackClass->device_track(0, DEV_ZIP, ui->tableViewZIP->model()->data(i, + Qt::UserRole).toInt(), ui->tableViewZIP->model()->data(i, + Qt::UserRole + 1).toInt()); + ui->comboBoxZIPChannel->setCurrentIndex(ui->comboBoxZIPBus->currentData().toUInt() == ZIP_BUS_ATAPI ? + Harddrives::busTrackClass->next_free_ide_channel() : + Harddrives::busTrackClass->next_free_scsi_id()); + setZIPBus(ui->tableViewZIP->model(), + ui->tableViewZIP->selectionModel()->currentIndex(), + ui->comboBoxZIPBus->currentData().toUInt(), + ui->comboBoxZIPChannel->currentData().toUInt()); + Harddrives::busTrackClass->device_track(1, DEV_ZIP, ui->tableViewZIP->model()->data(i, + Qt::UserRole).toInt(), ui->tableViewZIP->model()->data(i, + Qt::UserRole + 1).toInt()); } -void SettingsOtherRemovable::on_comboBoxZIPChannel_activated(int) { +void +SettingsOtherRemovable::on_comboBoxZIPChannel_activated(int) +{ auto i = ui->tableViewZIP->selectionModel()->currentIndex().siblingAtColumn(0); - Harddrives::busTrackClass->device_track(0, DEV_ZIP, ui->tableViewZIP->model()->data(i, Qt::UserRole).toInt(), ui->tableViewZIP->model()->data(i, Qt::UserRole + 1).toInt()); - setZIPBus( - ui->tableViewZIP->model(), - ui->tableViewZIP->selectionModel()->currentIndex(), - ui->comboBoxZIPBus->currentData().toUInt(), - ui->comboBoxZIPChannel->currentData().toUInt()); - Harddrives::busTrackClass->device_track(1, DEV_ZIP, ui->tableViewZIP->model()->data(i, Qt::UserRole).toInt(), ui->tableViewZIP->model()->data(i, Qt::UserRole + 1).toInt()); + Harddrives::busTrackClass->device_track(0, DEV_ZIP, ui->tableViewZIP->model()->data(i, + Qt::UserRole).toInt(), ui->tableViewZIP->model()->data(i, + Qt::UserRole + 1).toInt()); + setZIPBus(ui->tableViewZIP->model(), + ui->tableViewZIP->selectionModel()->currentIndex(), + ui->comboBoxZIPBus->currentData().toUInt(), + ui->comboBoxZIPChannel->currentData().toUInt()); + Harddrives::busTrackClass->device_track(1, DEV_ZIP, ui->tableViewZIP->model()->data(i, + Qt::UserRole).toInt(), + ui->tableViewZIP->model()->data(i, Qt::UserRole + 1).toInt()); } -void SettingsOtherRemovable::on_checkBoxZIP250_stateChanged(int state) { - setZIPType( - ui->tableViewZIP->model(), - ui->tableViewZIP->selectionModel()->currentIndex(), - state == Qt::Checked); +void +SettingsOtherRemovable::on_checkBoxZIP250_stateChanged(int state) +{ + setZIPType(ui->tableViewZIP->model(), + ui->tableViewZIP->selectionModel()->currentIndex(), + state == Qt::Checked); } diff --git a/src/qt/qt_settingsotherremovable.hpp b/src/qt/qt_settingsotherremovable.hpp index c48f6f819..8b81fb0f0 100644 --- a/src/qt/qt_settingsotherremovable.hpp +++ b/src/qt/qt_settingsotherremovable.hpp @@ -7,8 +7,7 @@ namespace Ui { class SettingsOtherRemovable; } -class SettingsOtherRemovable : public QWidget -{ +class SettingsOtherRemovable : public QWidget { Q_OBJECT public: diff --git a/src/qt/qt_settingsotherremovable.ui b/src/qt/qt_settingsotherremovable.ui index a82c296ae..219333376 100644 --- a/src/qt/qt_settingsotherremovable.ui +++ b/src/qt/qt_settingsotherremovable.ui @@ -35,6 +35,9 @@ + + QAbstractItemView::NoEditTriggers + QAbstractItemView::SingleSelection @@ -66,10 +69,18 @@ - + + + 30 + + - + + + 30 + + @@ -79,7 +90,11 @@ - + + + 30 + + @@ -105,6 +120,9 @@ + + QAbstractItemView::NoEditTriggers + QAbstractItemView::SingleSelection @@ -129,7 +147,11 @@ - + + + 30 + + @@ -139,7 +161,11 @@ - + + + 30 + + diff --git a/src/qt/qt_settingsports.cpp b/src/qt/qt_settingsports.cpp index dbabae73c..9b19df68d 100644 --- a/src/qt/qt_settingsports.cpp +++ b/src/qt/qt_settingsports.cpp @@ -1,20 +1,21 @@ /* - * 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. + * 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. + * This file is part of the 86Box distribution. * - * Serial/Parallel ports configuration UI module. + * Serial/Parallel ports configuration UI module. * * * - * Authors: Joakim L. Gilje + * Authors: Joakim L. Gilje * Cacodemon345 * - * Copyright 2022 Cacodemon345 - * Copyright 2021 Joakim L. Gilje + * Copyright 2022 Cacodemon345 + * Copyright 2022 Jasmine Iwanek + * Copyright 2021 Joakim L. Gilje */ #include "qt_settingsports.hpp" #include "ui_qt_settingsports.h" @@ -25,24 +26,26 @@ extern "C" { #include <86box/device.h> #include <86box/machine.h> #include <86box/lpt.h> +#include <86box/serial.h> +#include <86box/serial_passthrough.h> } #include "qt_deviceconfig.hpp" #include "qt_models_common.hpp" -SettingsPorts::SettingsPorts(QWidget *parent) : - QWidget(parent), - ui(new Ui::SettingsPorts) +SettingsPorts::SettingsPorts(QWidget *parent) + : QWidget(parent) + , ui(new Ui::SettingsPorts) { ui->setupUi(this); - for (int i = 0; i < 4; i++) { - auto* cbox = findChild(QString("comboBoxLpt%1").arg(i+1)); - auto* model = cbox->model(); - int c = 0; - int selectedRow = 0; + for (int i = 0; i < PARALLEL_MAX; i++) { + auto *cbox = findChild(QString("comboBoxLpt%1").arg(i + 1)); + auto *model = cbox->model(); + int c = 0; + int selectedRow = 0; while (true) { - const char* lptName = lpt_device_get_name(c); + const char *lptName = lpt_device_get_name(c); if (lptName == nullptr) { break; } @@ -55,15 +58,24 @@ SettingsPorts::SettingsPorts(QWidget *parent) : } cbox->setCurrentIndex(selectedRow); - auto* checkBox = findChild(QString("checkBoxParallel%1").arg(i+1)); + auto *checkBox = findChild(QString("checkBoxParallel%1").arg(i + 1)); checkBox->setChecked(lpt_ports[i].enabled > 0); cbox->setEnabled(lpt_ports[i].enabled > 0); } - for (int i = 0; i < 4; i++) { - auto* checkBox = findChild(QString("checkBoxSerial%1").arg(i+1)); - checkBox->setChecked(serial_enabled[i] > 0); + for (int i = 0; i < SERIAL_MAX; i++) { + auto *checkBox = findChild(QString("checkBoxSerial%1").arg(i + 1)); + checkBox->setChecked(com_ports[i].enabled > 0); } + + ui->checkBoxSerialPassThru1->setChecked(serial_passthrough_enabled[0]); + ui->pushButtonSerialPassThru1->setEnabled(serial_passthrough_enabled[0]); + ui->checkBoxSerialPassThru2->setChecked(serial_passthrough_enabled[1]); + ui->pushButtonSerialPassThru2->setEnabled(serial_passthrough_enabled[1]); + ui->checkBoxSerialPassThru3->setChecked(serial_passthrough_enabled[2]); + ui->pushButtonSerialPassThru3->setEnabled(serial_passthrough_enabled[2]); + ui->checkBoxSerialPassThru4->setChecked(serial_passthrough_enabled[3]); + ui->pushButtonSerialPassThru4->setEnabled(serial_passthrough_enabled[3]); } SettingsPorts::~SettingsPorts() @@ -71,34 +83,95 @@ SettingsPorts::~SettingsPorts() delete ui; } -void SettingsPorts::save() { - for (int i = 0; i < 3; i++) { - auto* cbox = findChild(QString("comboBoxLpt%1").arg(i+1)); - auto* checkBox = findChild(QString("checkBoxParallel%1").arg(i+1)); - lpt_ports[i].device = cbox->currentData().toInt(); +void +SettingsPorts::save() +{ + for (int i = 0; i < PARALLEL_MAX; i++) { + auto *cbox = findChild(QString("comboBoxLpt%1").arg(i + 1)); + auto *checkBox = findChild(QString("checkBoxParallel%1").arg(i + 1)); + lpt_ports[i].device = cbox->currentData().toInt(); lpt_ports[i].enabled = checkBox->isChecked() ? 1 : 0; } - for (int i = 0; i < 4; i++) { - auto* checkBox = findChild(QString("checkBoxSerial%1").arg(i+1)); - serial_enabled[i] = checkBox->isChecked() ? 1 : 0; + for (int i = 0; i < SERIAL_MAX; i++) { + auto *checkBox = findChild(QString("checkBoxSerial%1").arg(i + 1)); + com_ports[i].enabled = checkBox->isChecked() ? 1 : 0; } + + serial_passthrough_enabled[0] = ui->checkBoxSerialPassThru1->isChecked(); + serial_passthrough_enabled[1] = ui->checkBoxSerialPassThru2->isChecked(); + serial_passthrough_enabled[2] = ui->checkBoxSerialPassThru3->isChecked(); + serial_passthrough_enabled[3] = ui->checkBoxSerialPassThru4->isChecked(); } -void SettingsPorts::on_checkBoxParallel1_stateChanged(int state) { +void +SettingsPorts::on_checkBoxParallel1_stateChanged(int state) +{ ui->comboBoxLpt1->setEnabled(state == Qt::Checked); } -void SettingsPorts::on_checkBoxParallel2_stateChanged(int state) { +void +SettingsPorts::on_checkBoxParallel2_stateChanged(int state) +{ ui->comboBoxLpt2->setEnabled(state == Qt::Checked); } -void SettingsPorts::on_checkBoxParallel3_stateChanged(int state) { +void +SettingsPorts::on_checkBoxParallel3_stateChanged(int state) +{ ui->comboBoxLpt3->setEnabled(state == Qt::Checked); } - -void SettingsPorts::on_checkBoxParallel4_stateChanged(int state) { +void +SettingsPorts::on_checkBoxParallel4_stateChanged(int state) +{ ui->comboBoxLpt4->setEnabled(state == Qt::Checked); } +void +SettingsPorts::on_pushButtonSerialPassThru1_clicked() +{ + DeviceConfig::ConfigureDevice(&serial_passthrough_device, 1, qobject_cast(Settings::settings)); +} + +void +SettingsPorts::on_pushButtonSerialPassThru2_clicked() +{ + DeviceConfig::ConfigureDevice(&serial_passthrough_device, 2, qobject_cast(Settings::settings)); +} + +void +SettingsPorts::on_pushButtonSerialPassThru3_clicked() +{ + DeviceConfig::ConfigureDevice(&serial_passthrough_device, 3, qobject_cast(Settings::settings)); +} + +void +SettingsPorts::on_pushButtonSerialPassThru4_clicked() +{ + DeviceConfig::ConfigureDevice(&serial_passthrough_device, 4, qobject_cast(Settings::settings)); +} + +void +SettingsPorts::on_checkBoxSerialPassThru1_clicked(bool checked) +{ + ui->pushButtonSerialPassThru1->setEnabled(checked); +} + +void +SettingsPorts::on_checkBoxSerialPassThru2_clicked(bool checked) +{ + ui->pushButtonSerialPassThru2->setEnabled(checked); +} + +void +SettingsPorts::on_checkBoxSerialPassThru3_clicked(bool checked) +{ + ui->pushButtonSerialPassThru3->setEnabled(checked); +} + +void +SettingsPorts::on_checkBoxSerialPassThru4_clicked(bool checked) +{ + ui->pushButtonSerialPassThru4->setEnabled(checked); +} diff --git a/src/qt/qt_settingsports.hpp b/src/qt/qt_settingsports.hpp index c5deef80a..a5129d35f 100644 --- a/src/qt/qt_settingsports.hpp +++ b/src/qt/qt_settingsports.hpp @@ -7,8 +7,7 @@ namespace Ui { class SettingsPorts; } -class SettingsPorts : public QWidget -{ +class SettingsPorts : public QWidget { Q_OBJECT public: @@ -16,6 +15,30 @@ public: ~SettingsPorts(); void save(); +private slots: + void on_checkBoxSerialPassThru4_clicked(bool checked); + +private slots: + void on_checkBoxSerialPassThru3_clicked(bool checked); + +private slots: + void on_checkBoxSerialPassThru2_clicked(bool checked); + +private slots: + void on_pushButtonSerialPassThru4_clicked(); + +private slots: + void on_pushButtonSerialPassThru3_clicked(); + +private slots: + void on_pushButtonSerialPassThru2_clicked(); + +private slots: + void on_pushButtonSerialPassThru1_clicked(); + +private slots: + void on_checkBoxSerialPassThru1_clicked(bool checked); + private slots: void on_checkBoxParallel3_stateChanged(int arg1); void on_checkBoxParallel2_stateChanged(int arg1); diff --git a/src/qt/qt_settingsports.ui b/src/qt/qt_settingsports.ui index a1fbb47e7..bca870e5d 100644 --- a/src/qt/qt_settingsports.ui +++ b/src/qt/qt_settingsports.ui @@ -13,7 +13,7 @@ Form - + 0 @@ -26,7 +26,7 @@ 0 - + @@ -36,7 +36,11 @@ - + + + 30 + + @@ -46,7 +50,11 @@ - + + + 30 + + @@ -56,7 +64,11 @@ - + + + 30 + + @@ -66,33 +78,16 @@ - + + + 30 + + - + - - - - Serial port 1 - - - - - - - Parallel port 1 - - - - - - - Serial port 2 - - - @@ -100,13 +95,6 @@ - - - - Serial port 3 - - - @@ -114,10 +102,17 @@ - - + + - Serial port 4 + Serial port 3 + + + + + + + Serial port 1 @@ -128,20 +123,117 @@ + + + + Serial port 2 + + + + + + + Parallel port 1 + + + + + + + Serial port 4 + + + - - - - Qt::Vertical + + + + QLayout::SetDefaultConstraint - - - 20 - 40 - - - + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + Serial port passthrough 3 + + + + + + + Qt::Vertical + + + + 20 + 40 + + + + + + + + Configure + + + + + + + Serial port passthrough 1 + + + + + + + Serial port passthrough 2 + + + + + + + Serial port passthrough 4 + + + + + + + Configure + + + + + + + Configure + + + + + + + Configure + + + + diff --git a/src/qt/qt_settingssound.cpp b/src/qt/qt_settingssound.cpp index 5cf1114b0..b4df4ff69 100644 --- a/src/qt/qt_settingssound.cpp +++ b/src/qt/qt_settingssound.cpp @@ -1,18 +1,20 @@ /* - * 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. + * 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. + * This file is part of the 86Box distribution. * - * Sound/MIDI devices configuration UI module. + * Sound/MIDI devices configuration UI module. * * * - * Authors: Joakim L. Gilje + * Authors: Joakim L. Gilje + * Jasmine Iwanek * - * Copyright 2021 Joakim L. Gilje + * Copyright 2021 Joakim L. Gilje + * Copyright 2022-2023 Jasmine Iwanek */ #include "qt_settingssound.hpp" #include "ui_qt_settingssound.h" @@ -25,14 +27,15 @@ extern "C" { #include <86box/sound.h> #include <86box/midi.h> #include <86box/snd_mpu401.h> +#include <86box/snd_opl.h> } #include "qt_deviceconfig.hpp" #include "qt_models_common.hpp" -SettingsSound::SettingsSound(QWidget *parent) : - QWidget(parent), - ui(new Ui::SettingsSound) +SettingsSound::SettingsSound(QWidget *parent) + : QWidget(parent) + , ui(new Ui::SettingsSound) { ui->setupUi(this); onCurrentMachineChanged(machine); @@ -43,66 +46,81 @@ SettingsSound::~SettingsSound() delete ui; } -void SettingsSound::save() { - sound_card_current = ui->comboBoxSoundCard->currentData().toInt(); - midi_device_current = ui->comboBoxMidiOut->currentData().toInt(); - midi_input_device_current = ui->comboBoxMidiIn->currentData().toInt(); - mpu401_standalone_enable = ui->checkBoxMPU401->isChecked() ? 1 : 0; - SSI2001 = ui->checkBoxSSI2001->isChecked() ? 1 : 0;; - GAMEBLASTER = ui->checkBoxCMS->isChecked() ? 1 : 0; - GUS = ui->checkBoxGUS->isChecked() ? 1 : 0;; - sound_is_float = ui->checkBoxFloat32->isChecked() ? 1 : 0;; +void +SettingsSound::save() +{ + for (uint8_t i = 0; i < SOUND_CARD_MAX; ++i) { + auto *cbox = findChild(QString("comboBoxSoundCard%1").arg(i + 1)); + sound_card_current[i] = cbox->currentData().toInt(); + } + + midi_output_device_current = ui->comboBoxMidiOut->currentData().toInt(); + midi_input_device_current = ui->comboBoxMidiIn->currentData().toInt(); + mpu401_standalone_enable = ui->checkBoxMPU401->isChecked() ? 1 : 0; + + sound_is_float = ui->checkBoxFloat32->isChecked() ? 1 : 0; + + if (ui->radioButtonYMFM->isChecked()) + fm_driver = FM_DRV_YMFM; + else + fm_driver = FM_DRV_NUKED; } -void SettingsSound::onCurrentMachineChanged(int machineId) { +void +SettingsSound::onCurrentMachineChanged(int machineId) +{ this->machineId = machineId; - auto* model = ui->comboBoxSoundCard->model(); - auto removeRows = model->rowCount(); - int c = 0; + int c = 0; int selectedRow = 0; - while (true) { - /* Skip "internal" if machine doesn't have it. */ - if ((c == 1) && (machine_has_flags(machineId, MACHINE_SOUND) == 0)) { - c++; - continue; - } - auto* sound_dev = sound_card_getdevice(c); - QString name = DeviceConfig::DeviceName(sound_dev, sound_card_get_internal_name(c), 1); - if (name.isEmpty()) { - break; - } + for (uint8_t i = 0; i < SOUND_CARD_MAX; ++i) { + auto *cbox = findChild(QString("comboBoxSoundCard%1").arg(i + 1)); + auto *model = cbox->model(); + auto removeRows = model->rowCount(); + c = 0; + selectedRow = 0; - if (sound_card_available(c)) { - if (device_is_valid(sound_dev, machineId)) { + while (true) { + /* Skip "internal" if machine doesn't have it or this is not the primary card. */ + if ((c == 1) && ((i > 0) || (machine_has_flags(machineId, MACHINE_SOUND) == 0))) { + c++; + continue; + } + + auto name = DeviceConfig::DeviceName(sound_card_getdevice(c), sound_card_get_internal_name(c), 1); + if (name.isEmpty()) { + break; + } + + if (sound_card_available(c) && device_is_valid(sound_card_getdevice(c), machineId)) { int row = Models::AddEntry(model, name, c); - if (c == sound_card_current) { + if (c == sound_card_current[i]) { selectedRow = row - removeRows; } } + c++; } - c++; + model->removeRows(0, removeRows); + cbox->setEnabled(model->rowCount() > 0); + cbox->setCurrentIndex(-1); + cbox->setCurrentIndex(selectedRow); } - model->removeRows(0, removeRows); - ui->comboBoxSoundCard->setEnabled(model->rowCount() > 0); - ui->comboBoxSoundCard->setCurrentIndex(-1); - ui->comboBoxSoundCard->setCurrentIndex(selectedRow); - model = ui->comboBoxMidiOut->model(); - removeRows = model->rowCount(); - c = 0; + auto model = ui->comboBoxMidiOut->model(); + auto removeRows = model->rowCount(); + c = 0; selectedRow = 0; while (true) { - QString name = DeviceConfig::DeviceName(midi_device_getdevice(c), midi_device_get_internal_name(c), 0); + QString name = DeviceConfig::DeviceName(midi_out_device_getdevice(c), midi_out_device_get_internal_name(c), 0); if (name.isEmpty()) { break; } - if (midi_device_available(c)) { + if (midi_out_device_available(c)) { int row = Models::AddEntry(model, name, c); - if (c == midi_device_current) { + if (c == midi_output_device_current) { selectedRow = row - removeRows; } } @@ -113,12 +131,12 @@ void SettingsSound::onCurrentMachineChanged(int machineId) { ui->comboBoxMidiOut->setCurrentIndex(-1); ui->comboBoxMidiOut->setCurrentIndex(selectedRow); - model = ui->comboBoxMidiIn->model(); - removeRows = model->rowCount(); - c = 0; + model = ui->comboBoxMidiIn->model(); + removeRows = model->rowCount(); + c = 0; selectedRow = 0; while (true) { - QString name = DeviceConfig::DeviceName(midi_in_device_getdevice(c), midi_device_get_internal_name(c), 0); + QString name = DeviceConfig::DeviceName(midi_in_device_getdevice(c), midi_in_device_get_internal_name(c), 0); if (name.isEmpty()) { break; } @@ -138,23 +156,23 @@ void SettingsSound::onCurrentMachineChanged(int machineId) { ui->comboBoxMidiIn->setCurrentIndex(selectedRow); ui->checkBoxMPU401->setChecked(mpu401_standalone_enable > 0); - ui->checkBoxSSI2001->setChecked(SSI2001 > 0); - ui->checkBoxCMS->setChecked(GAMEBLASTER > 0); - ui->checkBoxGUS->setChecked(GUS > 0); ui->checkBoxFloat32->setChecked(sound_is_float > 0); - bool hasIsa = machine_has_bus(machineId, MACHINE_BUS_ISA) > 0; - bool hasIsa16 = machine_has_bus(machineId, MACHINE_BUS_ISA) > 0; - ui->checkBoxCMS->setEnabled(hasIsa); - ui->pushButtonConfigureCMS->setEnabled((GAMEBLASTER > 0) && hasIsa); - ui->checkBoxGUS->setEnabled(hasIsa16); - ui->pushButtonConfigureGUS->setEnabled((GUS > 0) && hasIsa16); - ui->checkBoxSSI2001->setEnabled(hasIsa); - ui->pushButtonConfigureSSI2001->setEnabled((SSI2001 > 0) && hasIsa); + switch (fm_driver) { + case FM_DRV_YMFM: + ui->radioButtonYMFM->setChecked(true); + break; + case FM_DRV_NUKED: + default: + ui->radioButtonNuked->setChecked(true); + break; + } } -static bool allowMpu401(Ui::SettingsSound *ui) { - QString midiOut = midi_device_get_internal_name(ui->comboBoxMidiOut->currentData().toInt()); +static bool +allowMpu401(Ui::SettingsSound *ui) +{ + QString midiOut = midi_out_device_get_internal_name(ui->comboBoxMidiOut->currentData().toInt()); QString midiIn = midi_in_device_get_internal_name(ui->comboBoxMidiIn->currentData().toInt()); if (midiOut.isEmpty()) { @@ -168,32 +186,104 @@ static bool allowMpu401(Ui::SettingsSound *ui) { return true; } -void SettingsSound::on_comboBoxSoundCard_currentIndexChanged(int index) { +void +SettingsSound::on_comboBoxSoundCard1_currentIndexChanged(int index) +{ if (index < 0) { return; } - ui->pushButtonConfigureSoundCard->setEnabled(sound_card_has_config(ui->comboBoxSoundCard->currentData().toInt())); + int sndCard = ui->comboBoxSoundCard1->currentData().toInt(); + if (sndCard == SOUND_INTERNAL) + ui->pushButtonConfigureSoundCard1->setEnabled(machine_has_flags(machineId, MACHINE_SOUND) && + device_has_config(machine_get_snd_device(machineId))); + else + ui->pushButtonConfigureSoundCard1->setEnabled(sound_card_has_config(sndCard)); } - -void SettingsSound::on_pushButtonConfigureSoundCard_clicked() { - DeviceConfig::ConfigureDevice(sound_card_getdevice(ui->comboBoxSoundCard->currentData().toInt()), 0, qobject_cast(Settings::settings)); +void +SettingsSound::on_pushButtonConfigureSoundCard1_clicked() +{ + int sndCard = ui->comboBoxSoundCard1->currentData().toInt(); + auto *device = sound_card_getdevice(sndCard); + if (sndCard == SOUND_INTERNAL) + device = machine_get_snd_device(machineId); + DeviceConfig::ConfigureDevice(device, 0, qobject_cast(Settings::settings)); } -void SettingsSound::on_comboBoxMidiOut_currentIndexChanged(int index) { +void +SettingsSound::on_comboBoxSoundCard2_currentIndexChanged(int index) +{ if (index < 0) { return; } - ui->pushButtonConfigureMidiOut->setEnabled(midi_device_has_config(ui->comboBoxMidiOut->currentData().toInt())); + int sndCard = ui->comboBoxSoundCard2->currentData().toInt(); + ui->pushButtonConfigureSoundCard2->setEnabled(sound_card_has_config(sndCard)); +} + +void +SettingsSound::on_pushButtonConfigureSoundCard2_clicked() +{ + int sndCard = ui->comboBoxSoundCard2->currentData().toInt(); + auto *device = sound_card_getdevice(sndCard); + DeviceConfig::ConfigureDevice(device, 0, qobject_cast(Settings::settings)); +} + +void +SettingsSound::on_comboBoxSoundCard3_currentIndexChanged(int index) +{ + if (index < 0) { + return; + } + int sndCard = ui->comboBoxSoundCard3->currentData().toInt(); + ui->pushButtonConfigureSoundCard3->setEnabled(sound_card_has_config(sndCard)); +} + +void +SettingsSound::on_pushButtonConfigureSoundCard3_clicked() +{ + int sndCard = ui->comboBoxSoundCard3->currentData().toInt(); + auto *device = sound_card_getdevice(sndCard); + DeviceConfig::ConfigureDevice(device, 0, qobject_cast(Settings::settings)); +} + +void +SettingsSound::on_comboBoxSoundCard4_currentIndexChanged(int index) +{ + if (index < 0) { + return; + } + int sndCard = ui->comboBoxSoundCard4->currentData().toInt(); + ui->pushButtonConfigureSoundCard4->setEnabled(sound_card_has_config(sndCard)); +} + +void +SettingsSound::on_pushButtonConfigureSoundCard4_clicked() +{ + int sndCard = ui->comboBoxSoundCard4->currentData().toInt(); + auto *device = sound_card_getdevice(sndCard); + DeviceConfig::ConfigureDevice(device, 0, qobject_cast(Settings::settings)); +} + +void +SettingsSound::on_comboBoxMidiOut_currentIndexChanged(int index) +{ + if (index < 0) { + return; + } + ui->pushButtonConfigureMidiOut->setEnabled(midi_out_device_has_config(ui->comboBoxMidiOut->currentData().toInt())); ui->checkBoxMPU401->setEnabled(allowMpu401(ui) && (machine_has_bus(machineId, MACHINE_BUS_ISA) || machine_has_bus(machineId, MACHINE_BUS_MCA))); ui->pushButtonConfigureMPU401->setEnabled(allowMpu401(ui) && ui->checkBoxMPU401->isChecked()); } -void SettingsSound::on_pushButtonConfigureMidiOut_clicked() { - DeviceConfig::ConfigureDevice(midi_device_getdevice(ui->comboBoxMidiOut->currentData().toInt()), 0, qobject_cast(Settings::settings)); +void +SettingsSound::on_pushButtonConfigureMidiOut_clicked() +{ + DeviceConfig::ConfigureDevice(midi_out_device_getdevice(ui->comboBoxMidiOut->currentData().toInt()), 0, qobject_cast(Settings::settings)); } -void SettingsSound::on_comboBoxMidiIn_currentIndexChanged(int index) { +void +SettingsSound::on_comboBoxMidiIn_currentIndexChanged(int index) +{ if (index < 0) { return; } @@ -202,42 +292,24 @@ void SettingsSound::on_comboBoxMidiIn_currentIndexChanged(int index) { ui->pushButtonConfigureMPU401->setEnabled(allowMpu401(ui) && ui->checkBoxMPU401->isChecked()); } -void SettingsSound::on_pushButtonConfigureMidiIn_clicked() { - DeviceConfig::ConfigureDevice(midi_in_device_getdevice(ui->comboBoxMidiIn->currentData().toInt()), 0, qobject_cast(Settings::settings)); +void +SettingsSound::on_pushButtonConfigureMidiIn_clicked() +{ + DeviceConfig::ConfigureDevice(midi_in_device_getdevice(ui->comboBoxMidiIn->currentData().toInt()), 0, qobject_cast(Settings::settings)); } -void SettingsSound::on_checkBoxMPU401_stateChanged(int state) { +void +SettingsSound::on_checkBoxMPU401_stateChanged(int state) +{ ui->pushButtonConfigureMPU401->setEnabled(state == Qt::Checked); } -void SettingsSound::on_checkBoxSSI2001_stateChanged(int state) { - ui->pushButtonConfigureSSI2001->setEnabled(state == Qt::Checked); -} - -void SettingsSound::on_checkBoxCMS_stateChanged(int state) { - ui->pushButtonConfigureCMS->setEnabled(state == Qt::Checked); -} - -void SettingsSound::on_checkBoxGUS_stateChanged(int state) { - ui->pushButtonConfigureGUS->setEnabled(state == Qt::Checked); -} - -void SettingsSound::on_pushButtonConfigureMPU401_clicked() { +void +SettingsSound::on_pushButtonConfigureMPU401_clicked() +{ if (machine_has_bus(machineId, MACHINE_BUS_MCA) > 0) { - DeviceConfig::ConfigureDevice(&mpu401_mca_device, 0, qobject_cast(Settings::settings)); + DeviceConfig::ConfigureDevice(&mpu401_mca_device, 0, qobject_cast(Settings::settings)); } else { - DeviceConfig::ConfigureDevice(&mpu401_device, 0, qobject_cast(Settings::settings)); + DeviceConfig::ConfigureDevice(&mpu401_device, 0, qobject_cast(Settings::settings)); } } - -void SettingsSound::on_pushButtonConfigureSSI2001_clicked() { - DeviceConfig::ConfigureDevice(&ssi2001_device, 0, qobject_cast(Settings::settings)); -} - -void SettingsSound::on_pushButtonConfigureCMS_clicked() { - DeviceConfig::ConfigureDevice(&cms_device, 0, qobject_cast(Settings::settings)); -} - -void SettingsSound::on_pushButtonConfigureGUS_clicked() { - DeviceConfig::ConfigureDevice(&gus_device, 0, qobject_cast(Settings::settings)); -} diff --git a/src/qt/qt_settingssound.hpp b/src/qt/qt_settingssound.hpp index c649eb2a2..92b700c92 100644 --- a/src/qt/qt_settingssound.hpp +++ b/src/qt/qt_settingssound.hpp @@ -7,8 +7,7 @@ namespace Ui { class SettingsSound; } -class SettingsSound : public QWidget -{ +class SettingsSound : public QWidget { Q_OBJECT public: @@ -21,24 +20,24 @@ public slots: void onCurrentMachineChanged(int machineId); private slots: - void on_pushButtonConfigureGUS_clicked(); - void on_pushButtonConfigureCMS_clicked(); - void on_pushButtonConfigureSSI2001_clicked(); void on_pushButtonConfigureMPU401_clicked(); - void on_checkBoxGUS_stateChanged(int arg1); - void on_checkBoxCMS_stateChanged(int arg1); - void on_checkBoxSSI2001_stateChanged(int arg1); void on_checkBoxMPU401_stateChanged(int arg1); void on_pushButtonConfigureMidiIn_clicked(); void on_pushButtonConfigureMidiOut_clicked(); void on_comboBoxMidiIn_currentIndexChanged(int index); void on_comboBoxMidiOut_currentIndexChanged(int index); - void on_pushButtonConfigureSoundCard_clicked(); - void on_comboBoxSoundCard_currentIndexChanged(int index); + void on_pushButtonConfigureSoundCard1_clicked(); + void on_comboBoxSoundCard1_currentIndexChanged(int index); + void on_pushButtonConfigureSoundCard2_clicked(); + void on_comboBoxSoundCard2_currentIndexChanged(int index); + void on_pushButtonConfigureSoundCard3_clicked(); + void on_comboBoxSoundCard3_currentIndexChanged(int index); + void on_pushButtonConfigureSoundCard4_clicked(); + void on_comboBoxSoundCard4_currentIndexChanged(int index); private: Ui::SettingsSound *ui; - int machineId = 0; + int machineId = 0; }; #endif // QT_SETTINGSSOUND_HPP diff --git a/src/qt/qt_settingssound.ui b/src/qt/qt_settingssound.ui index 65f5d7fd6..1d5ab0050 100644 --- a/src/qt/qt_settingssound.ui +++ b/src/qt/qt_settingssound.ui @@ -26,43 +26,77 @@ 0 - + MIDI In Device: - - - - Innovation SSI-2001 - - - - - - - Gravis Ultrasound - - - - Sound card: + Sound card #1: - + Configure - + + + + Sound card #2: + + + + + + + Configure + + + + + + + Sound card #3: + + + + + + + Configure + + + + + + + + Sound card #4: + + + + + + + Configure + + + + + + + + 30 + 0 @@ -71,50 +105,39 @@ - + MIDI Out Device: - + Standalone MPU-401 - + Configure - + Configure - - - - Configure - - - - - - - CMS / Game Blaster - - - - + + + 30 + 0 @@ -123,35 +146,50 @@ - + Configure - + Use FLOAT32 sound - - - - Configure + + + + + 0 + 0 + + + FM synth driver + + + + + + Nuked (more accurate) + + + + + + + YMFM (faster) + + + + - - - - Configure - - - - + Qt::Vertical @@ -165,7 +203,49 @@ - + + + 30 + + + + 0 + 0 + + + + + + + + 30 + + + + 0 + 0 + + + + + + + + 30 + + + + 0 + 0 + + + + + + + + 30 + 0 diff --git a/src/qt/qt_settingsstoragecontrollers.cpp b/src/qt/qt_settingsstoragecontrollers.cpp index 2427b5774..30949de3a 100644 --- a/src/qt/qt_settingsstoragecontrollers.cpp +++ b/src/qt/qt_settingsstoragecontrollers.cpp @@ -1,18 +1,18 @@ /* - * 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. + * 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. + * This file is part of the 86Box distribution. * - * Storage devices configuration UI module. + * Storage devices configuration UI module. * * * - * Authors: Joakim L. Gilje + * Authors: Joakim L. Gilje * - * Copyright 2021 Joakim L. Gilje + * Copyright 2021 Joakim L. Gilje */ #include "qt_settingsstoragecontrollers.hpp" #include "ui_qt_settingsstoragecontrollers.h" @@ -25,6 +25,7 @@ extern "C" { #include <86box/hdc.h> #include <86box/hdc_ide.h> #include <86box/fdc_ext.h> +#include <86box/cdrom_interface.h> #include <86box/scsi.h> #include <86box/scsi_device.h> #include <86box/cassette.h> @@ -33,14 +34,12 @@ extern "C" { #include "qt_deviceconfig.hpp" #include "qt_models_common.hpp" -SettingsStorageControllers::SettingsStorageControllers(QWidget *parent) : - QWidget(parent), - ui(new Ui::SettingsStorageControllers) +SettingsStorageControllers::SettingsStorageControllers(QWidget *parent) + : QWidget(parent) + , ui(new Ui::SettingsStorageControllers) { ui->setupUi(this); - ui->checkBoxCassette->setChecked(cassette_enable > 0); - onCurrentMachineChanged(machine); } @@ -49,28 +48,32 @@ SettingsStorageControllers::~SettingsStorageControllers() delete ui; } -void SettingsStorageControllers::save() { +void +SettingsStorageControllers::save() +{ /* Storage devices category */ for (int i = 0; i < SCSI_BUS_MAX; ++i) { - auto* cbox = findChild(QString("comboBoxSCSI%1").arg(i+1)); + auto *cbox = findChild(QString("comboBoxSCSI%1").arg(i + 1)); scsi_card_current[i] = cbox->currentData().toInt(); } - hdc_current = ui->comboBoxHD->currentData().toInt(); - fdc_type = ui->comboBoxFD->currentData().toInt(); - ide_ter_enabled = ui->checkBoxTertiaryIDE->isChecked() ? 1 : 0; - ide_qua_enabled = ui->checkBoxQuaternaryIDE->isChecked() ? 1 : 0; - cassette_enable = ui->checkBoxCassette->isChecked() ? 1 : 0; + hdc_current = ui->comboBoxHD->currentData().toInt(); + fdc_type = ui->comboBoxFD->currentData().toInt(); + cdrom_interface_current = ui->comboBoxCDInterface->currentData().toInt(); + ide_ter_enabled = ui->checkBoxTertiaryIDE->isChecked() ? 1 : 0; + ide_qua_enabled = ui->checkBoxQuaternaryIDE->isChecked() ? 1 : 0; + cassette_enable = ui->checkBoxCassette->isChecked() ? 1 : 0; } -void SettingsStorageControllers::onCurrentMachineChanged(int machineId) { +void +SettingsStorageControllers::onCurrentMachineChanged(int machineId) +{ this->machineId = machineId; - auto* machine = &machines[machineId]; /*HD controller config*/ - auto* model = ui->comboBoxHD->model(); - auto removeRows = model->rowCount(); - int c = 0; - int selectedRow = 0; + auto *model = ui->comboBoxHD->model(); + auto removeRows = model->rowCount(); + int c = 0; + int selectedRow = 0; while (true) { /* Skip "internal" if machine doesn't have it. */ if ((c == 1) && (machine_has_flags(machineId, MACHINE_HDC) == 0)) { @@ -84,7 +87,7 @@ void SettingsStorageControllers::onCurrentMachineChanged(int machineId) { } if (hdc_available(c)) { - auto* hdc_dev = hdc_get_device(c); + auto *hdc_dev = hdc_get_device(c); if (device_is_valid(hdc_dev, machineId)) { int row = Models::AddEntry(model, name, c); @@ -101,9 +104,9 @@ void SettingsStorageControllers::onCurrentMachineChanged(int machineId) { ui->comboBoxHD->setCurrentIndex(selectedRow); /*FD controller config*/ - model = ui->comboBoxFD->model(); - removeRows = model->rowCount(); - c = 0; + model = ui->comboBoxFD->model(); + removeRows = model->rowCount(); + c = 0; selectedRow = 0; while (true) { QString name = DeviceConfig::DeviceName(fdc_card_getdevice(c), fdc_card_get_internal_name(c), 1); @@ -112,7 +115,7 @@ void SettingsStorageControllers::onCurrentMachineChanged(int machineId) { } if (fdc_card_available(c)) { - auto* fdc_dev = fdc_card_getdevice(c); + auto *fdc_dev = fdc_card_getdevice(c); if (device_is_valid(fdc_dev, machineId)) { int row = Models::AddEntry(model, name, c); @@ -128,11 +131,40 @@ void SettingsStorageControllers::onCurrentMachineChanged(int machineId) { ui->comboBoxFD->setCurrentIndex(-1); ui->comboBoxFD->setCurrentIndex(selectedRow); + /*CD interface controller config*/ + model = ui->comboBoxCDInterface->model(); + removeRows = model->rowCount(); + c = 0; + selectedRow = 0; + while (true) { + /* Skip "internal" if machine doesn't have it. */ + QString name = DeviceConfig::DeviceName(cdrom_interface_get_device(c), cdrom_interface_get_internal_name(c), 1); + if (name.isEmpty()) { + break; + } + + if (cdrom_interface_available(c)) { + auto *cdrom_interface_dev = cdrom_interface_get_device(c); + + if (device_is_valid(cdrom_interface_dev, machineId)) { + int row = Models::AddEntry(model, name, c); + if (c == cdrom_interface_current) { + selectedRow = row - removeRows; + } + } + } + c++; + } + model->removeRows(0, removeRows); + ui->comboBoxCDInterface->setEnabled(model->rowCount() > 0); + ui->comboBoxCDInterface->setCurrentIndex(-1); + ui->comboBoxCDInterface->setCurrentIndex(selectedRow); + for (int i = 0; i < SCSI_BUS_MAX; ++i) { - auto* cbox = findChild(QString("comboBoxSCSI%1").arg(i+1)); - model = cbox->model(); - removeRows = model->rowCount(); - c = 0; + auto *cbox = findChild(QString("comboBoxSCSI%1").arg(i + 1)); + model = cbox->model(); + removeRows = model->rowCount(); + c = 0; selectedRow = 0; while (true) { @@ -142,7 +174,7 @@ void SettingsStorageControllers::onCurrentMachineChanged(int machineId) { } if (scsi_card_available(c)) { - auto* scsi_dev = scsi_card_getdevice(c); + auto *scsi_dev = scsi_card_getdevice(c); if (device_is_valid(scsi_dev, machineId)) { int row = Models::AddEntry(model, name, c); if (c == scsi_card_current[i]) { @@ -162,88 +194,142 @@ void SettingsStorageControllers::onCurrentMachineChanged(int machineId) { int is_at = IS_AT(machineId); ui->checkBoxTertiaryIDE->setEnabled(is_at > 0); ui->checkBoxQuaternaryIDE->setEnabled(is_at > 0); + ui->checkBoxTertiaryIDE->setChecked(ui->checkBoxTertiaryIDE->isEnabled() && ide_ter_enabled); + ui->checkBoxQuaternaryIDE->setChecked(ui->checkBoxQuaternaryIDE->isEnabled() && ide_qua_enabled); + + if (machine_has_bus(machineId, MACHINE_BUS_CASSETTE)) { + ui->checkBoxCassette->setChecked(cassette_enable > 0); + ui->checkBoxCassette->setEnabled(true); + } else { + ui->checkBoxCassette->setChecked(false); + ui->checkBoxCassette->setEnabled(false); + } } -void SettingsStorageControllers::on_comboBoxHD_currentIndexChanged(int index) { +void +SettingsStorageControllers::on_comboBoxHD_currentIndexChanged(int index) +{ if (index < 0) { return; } ui->pushButtonHD->setEnabled(hdc_has_config(ui->comboBoxHD->currentData().toInt()) > 0); } -void SettingsStorageControllers::on_comboBoxFD_currentIndexChanged(int index) { +void +SettingsStorageControllers::on_comboBoxFD_currentIndexChanged(int index) +{ if (index < 0) { return; } ui->pushButtonFD->setEnabled(hdc_has_config(ui->comboBoxFD->currentData().toInt()) > 0); } -void SettingsStorageControllers::on_checkBoxTertiaryIDE_stateChanged(int arg1) { +void SettingsStorageControllers::on_comboBoxCDInterface_currentIndexChanged(int index) +{ + if (index < 0) { + return; + } + ui->pushButtonCDInterface->setEnabled(cdrom_interface_has_config(ui->comboBoxCDInterface->currentData().toInt()) > 0); +} + +void +SettingsStorageControllers::on_checkBoxTertiaryIDE_stateChanged(int arg1) +{ ui->pushButtonTertiaryIDE->setEnabled(arg1 == Qt::Checked); } - -void SettingsStorageControllers::on_checkBoxQuaternaryIDE_stateChanged(int arg1) { +void +SettingsStorageControllers::on_checkBoxQuaternaryIDE_stateChanged(int arg1) +{ ui->pushButtonQuaternaryIDE->setEnabled(arg1 == Qt::Checked); } -void SettingsStorageControllers::on_pushButtonHD_clicked() { - DeviceConfig::ConfigureDevice(hdc_get_device(ui->comboBoxHD->currentData().toInt()), 0, qobject_cast(Settings::settings)); +void +SettingsStorageControllers::on_pushButtonHD_clicked() +{ + DeviceConfig::ConfigureDevice(hdc_get_device(ui->comboBoxHD->currentData().toInt()), 0, qobject_cast(Settings::settings)); } -void SettingsStorageControllers::on_pushButtonFD_clicked() { - DeviceConfig::ConfigureDevice(fdc_card_getdevice(ui->comboBoxFD->currentData().toInt()), 0, qobject_cast(Settings::settings)); +void +SettingsStorageControllers::on_pushButtonFD_clicked() +{ + DeviceConfig::ConfigureDevice(fdc_card_getdevice(ui->comboBoxFD->currentData().toInt()), 0, qobject_cast(Settings::settings)); } -void SettingsStorageControllers::on_pushButtonTertiaryIDE_clicked() { - DeviceConfig::ConfigureDevice(&ide_ter_device, 0, qobject_cast(Settings::settings)); +void +SettingsStorageControllers::on_pushButtonCDInterface_clicked() +{ + DeviceConfig::ConfigureDevice(cdrom_interface_get_device(ui->comboBoxCDInterface->currentData().toInt()), 0, qobject_cast(Settings::settings)); } -void SettingsStorageControllers::on_pushButtonQuaternaryIDE_clicked() { - DeviceConfig::ConfigureDevice(&ide_qua_device, 0, qobject_cast(Settings::settings)); +void +SettingsStorageControllers::on_pushButtonTertiaryIDE_clicked() +{ + DeviceConfig::ConfigureDevice(&ide_ter_device, 0, qobject_cast(Settings::settings)); } -void SettingsStorageControllers::on_comboBoxSCSI1_currentIndexChanged(int index) { +void +SettingsStorageControllers::on_pushButtonQuaternaryIDE_clicked() +{ + DeviceConfig::ConfigureDevice(&ide_qua_device, 0, qobject_cast(Settings::settings)); +} + +void +SettingsStorageControllers::on_comboBoxSCSI1_currentIndexChanged(int index) +{ if (index < 0) { return; } ui->pushButtonSCSI1->setEnabled(scsi_card_has_config(ui->comboBoxSCSI1->currentData().toInt()) > 0); } -void SettingsStorageControllers::on_comboBoxSCSI2_currentIndexChanged(int index) { +void +SettingsStorageControllers::on_comboBoxSCSI2_currentIndexChanged(int index) +{ if (index < 0) { return; } ui->pushButtonSCSI2->setEnabled(scsi_card_has_config(ui->comboBoxSCSI2->currentData().toInt()) > 0); } -void SettingsStorageControllers::on_comboBoxSCSI3_currentIndexChanged(int index) { +void +SettingsStorageControllers::on_comboBoxSCSI3_currentIndexChanged(int index) +{ if (index < 0) { return; } ui->pushButtonSCSI3->setEnabled(scsi_card_has_config(ui->comboBoxSCSI3->currentData().toInt()) > 0); } -void SettingsStorageControllers::on_comboBoxSCSI4_currentIndexChanged(int index) { +void +SettingsStorageControllers::on_comboBoxSCSI4_currentIndexChanged(int index) +{ if (index < 0) { return; } ui->pushButtonSCSI4->setEnabled(scsi_card_has_config(ui->comboBoxSCSI4->currentData().toInt()) > 0); } - -void SettingsStorageControllers::on_pushButtonSCSI1_clicked() { - DeviceConfig::ConfigureDevice(scsi_card_getdevice(ui->comboBoxSCSI1->currentData().toInt()), 1, qobject_cast(Settings::settings)); +void +SettingsStorageControllers::on_pushButtonSCSI1_clicked() +{ + DeviceConfig::ConfigureDevice(scsi_card_getdevice(ui->comboBoxSCSI1->currentData().toInt()), 1, qobject_cast(Settings::settings)); } -void SettingsStorageControllers::on_pushButtonSCSI2_clicked() { - DeviceConfig::ConfigureDevice(scsi_card_getdevice(ui->comboBoxSCSI2->currentData().toInt()), 2, qobject_cast(Settings::settings)); +void +SettingsStorageControllers::on_pushButtonSCSI2_clicked() +{ + DeviceConfig::ConfigureDevice(scsi_card_getdevice(ui->comboBoxSCSI2->currentData().toInt()), 2, qobject_cast(Settings::settings)); } -void SettingsStorageControllers::on_pushButtonSCSI3_clicked() { - DeviceConfig::ConfigureDevice(scsi_card_getdevice(ui->comboBoxSCSI3->currentData().toInt()), 3, qobject_cast(Settings::settings)); +void +SettingsStorageControllers::on_pushButtonSCSI3_clicked() +{ + DeviceConfig::ConfigureDevice(scsi_card_getdevice(ui->comboBoxSCSI3->currentData().toInt()), 3, qobject_cast(Settings::settings)); } -void SettingsStorageControllers::on_pushButtonSCSI4_clicked() { - DeviceConfig::ConfigureDevice(scsi_card_getdevice(ui->comboBoxSCSI4->currentData().toInt()), 4, qobject_cast(Settings::settings)); +void +SettingsStorageControllers::on_pushButtonSCSI4_clicked() +{ + DeviceConfig::ConfigureDevice(scsi_card_getdevice(ui->comboBoxSCSI4->currentData().toInt()), 4, qobject_cast(Settings::settings)); } diff --git a/src/qt/qt_settingsstoragecontrollers.hpp b/src/qt/qt_settingsstoragecontrollers.hpp index e4596b567..5641889e4 100644 --- a/src/qt/qt_settingsstoragecontrollers.hpp +++ b/src/qt/qt_settingsstoragecontrollers.hpp @@ -7,8 +7,7 @@ namespace Ui { class SettingsStorageControllers; } -class SettingsStorageControllers : public QWidget -{ +class SettingsStorageControllers : public QWidget { Q_OBJECT public: @@ -33,14 +32,16 @@ private slots: void on_pushButtonTertiaryIDE_clicked(); void on_pushButtonFD_clicked(); void on_pushButtonHD_clicked(); + void on_pushButtonCDInterface_clicked(); void on_checkBoxQuaternaryIDE_stateChanged(int arg1); void on_checkBoxTertiaryIDE_stateChanged(int arg1); void on_comboBoxFD_currentIndexChanged(int index); void on_comboBoxHD_currentIndexChanged(int index); + void on_comboBoxCDInterface_currentIndexChanged(int index); private: Ui::SettingsStorageControllers *ui; - int machineId = 0; + int machineId = 0; }; #endif // QT_SETTINGSSTORAGECONTROLLERS_HPP diff --git a/src/qt/qt_settingsstoragecontrollers.ui b/src/qt/qt_settingsstoragecontrollers.ui index c4c44b019..d67127e2d 100644 --- a/src/qt/qt_settingsstoragecontrollers.ui +++ b/src/qt/qt_settingsstoragecontrollers.ui @@ -49,8 +49,41 @@ + + + + CD-ROM Controller: + + + false + + + + + + + 30 + + + false + + + + + + + Configure + + + false + + + + + 30 + 0 @@ -67,23 +100,27 @@ - + + + 30 + + - + Tertiary IDE Controller - + Quaternary IDE Controller - + false @@ -93,7 +130,7 @@ - + false @@ -134,6 +171,9 @@ + + 30 + 0 @@ -150,13 +190,43 @@ - + + + 30 + + + + 0 + 0 + + + - + + + 30 + + + + 0 + 0 + + + - + + + 30 + + + + 0 + 0 + + + @@ -172,7 +242,7 @@ - + Controller 4: diff --git a/src/qt/qt_softwarerenderer.cpp b/src/qt/qt_softwarerenderer.cpp index 2d260eca3..ab9ed932d 100644 --- a/src/qt/qt_softwarerenderer.cpp +++ b/src/qt/qt_softwarerenderer.cpp @@ -1,22 +1,22 @@ /* - * 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. + * 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. + * This file is part of the 86Box distribution. * - * Software renderer module. + * Software renderer module. * * * - * Authors: Joakim L. Gilje + * Authors: Joakim L. Gilje * Cacodemon345 * Teemu Korhonen * - * Copyright 2021 Joakim L. Gilje - * Copyright 2021-2022 Cacodemon345 - * Copyright 2021-2022 Teemu Korhonen + * Copyright 2021 Joakim L. Gilje + * Copyright 2021-2022 Cacodemon345 + * Copyright 2021-2022 Teemu Korhonen */ #include "qt_softwarerenderer.hpp" #include @@ -29,9 +29,13 @@ extern "C" { } SoftwareRenderer::SoftwareRenderer(QWidget *parent) +#ifdef __HAIKU__ + : QWidget(parent) +#else : QRasterWindow(parent->windowHandle()) +#endif { - parentWidget = parent; + RendererCommon::parentWidget = parent; images[0] = std::make_unique(QSize(2048, 2048), QImage::Format_RGB32); images[1] = std::make_unique(QSize(2048, 2048), QImage::Format_RGB32); @@ -39,39 +43,65 @@ SoftwareRenderer::SoftwareRenderer(QWidget *parent) buf_usage = std::vector(2); buf_usage[0].clear(); buf_usage[1].clear(); +#ifdef __HAIKU__ + this->setMouseTracking(true); +#endif } -void SoftwareRenderer::paintEvent(QPaintEvent* event) { - (void)event; +void +SoftwareRenderer::paintEvent(QPaintEvent *event) +{ + (void) event; onPaint(this); } -void SoftwareRenderer::onBlit(int buf_idx, int x, int y, int w, int h) { +void +SoftwareRenderer::onBlit(int buf_idx, int x, int y, int w, int h) +{ /* TODO: should look into deleteLater() */ - auto tval = this; - void* nuldata = 0; - if (memcmp(&tval, &nuldata, sizeof(void*)) == 0) return; + auto tval = this; + void *nuldata = 0; + if (memcmp(&tval, &nuldata, sizeof(void *)) == 0) + return; + auto origSource = source; cur_image = buf_idx; buf_usage[(buf_idx + 1) % 2].clear(); - source.setRect(x, y, w, h), + source.setRect(x, y, w, h); + + if (source != origSource) + onResize(this->width(), this->height()); update(); } -void SoftwareRenderer::resizeEvent(QResizeEvent *event) { +void +SoftwareRenderer::resizeEvent(QResizeEvent *event) +{ onResize(width(), height()); +#ifdef __HAIKU__ + QWidget::resizeEvent(event); +#else QRasterWindow::resizeEvent(event); +#endif } -bool SoftwareRenderer::event(QEvent *event) +bool +SoftwareRenderer::event(QEvent *event) { bool res = false; - if (!eventDelegate(event, res)) return QRasterWindow::event(event); + if (!eventDelegate(event, res)) +#ifdef __HAIKU__ + return QWidget::event(event); +#else + return QRasterWindow::event(event); +#endif return res; } -void SoftwareRenderer::onPaint(QPaintDevice* device) { +void +SoftwareRenderer::onPaint(QPaintDevice *device) +{ if (cur_image == -1) return; @@ -80,16 +110,17 @@ void SoftwareRenderer::onPaint(QPaintDevice* device) { #if QT_VERSION >= QT_VERSION_CHECK(5, 14, 0) painter.fillRect(0, 0, device->width(), device->height(), QColorConstants::Black); #else - painter.fillRect(0,0, device->width(), device->height(), Qt::black); + painter.fillRect(0, 0, device->width(), device->height(), Qt::black); #endif painter.setCompositionMode(QPainter::CompositionMode_Plus); painter.drawImage(destination, *images[cur_image], source); if (video_fullscreen && status_icons_fullscreen) drawStatusBarIcons(&painter); } -std::vector> SoftwareRenderer::getBuffers() +std::vector> +SoftwareRenderer::getBuffers() { - std::vector> buffers; + std::vector> buffers; buffers.push_back(std::make_tuple(images[0]->bits(), &buf_usage[0])); buffers.push_back(std::make_tuple(images[1]->bits(), &buf_usage[1])); diff --git a/src/qt/qt_softwarerenderer.hpp b/src/qt/qt_softwarerenderer.hpp index 8e646c14d..ec64f7000 100644 --- a/src/qt/qt_softwarerenderer.hpp +++ b/src/qt/qt_softwarerenderer.hpp @@ -8,24 +8,29 @@ #include #include "qt_renderercommon.hpp" -class SoftwareRenderer : public QRasterWindow, public RendererCommon -{ +class SoftwareRenderer : +#ifdef __HAIKU__ + public QWidget, +#else + public QRasterWindow, +#endif + public RendererCommon { Q_OBJECT public: explicit SoftwareRenderer(QWidget *parent = nullptr); - void paintEvent(QPaintEvent* event) override; + void paintEvent(QPaintEvent *event) override; - std::vector> getBuffers() override; + std::vector> getBuffers() override; public slots: void onBlit(int buf_idx, int x, int y, int w, int h); protected: std::array, 2> images; - int cur_image = -1; + int cur_image = -1; - void onPaint(QPaintDevice* device); + void onPaint(QPaintDevice *device); void resizeEvent(QResizeEvent *event) override; bool event(QEvent *event) override; }; diff --git a/src/qt/qt_soundgain.cpp b/src/qt/qt_soundgain.cpp index 7b3f7cc04..725a5b115 100644 --- a/src/qt/qt_soundgain.cpp +++ b/src/qt/qt_soundgain.cpp @@ -1,32 +1,31 @@ /* - * 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. + * 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. + * This file is part of the 86Box distribution. * - * Sound gain dialog UI module. + * Sound gain dialog UI module. * * * - * Authors: Cacodemon345 + * Authors: Cacodemon345 * - * Copyright 2021-2022 Cacodemon345 + * Copyright 2021-2022 Cacodemon345 */ #include "qt_soundgain.hpp" #include "ui_qt_soundgain.h" -extern "C" -{ +extern "C" { #include <86box/86box.h> #include <86box/plat.h> #include <86box/sound.h> } -SoundGain::SoundGain(QWidget *parent) : - QDialog(parent), - ui(new Ui::SoundGain) +SoundGain::SoundGain(QWidget *parent) + : QDialog(parent) + , ui(new Ui::SoundGain) { ui->setupUi(this); ui->verticalSlider->setValue(sound_gain); @@ -38,14 +37,14 @@ SoundGain::~SoundGain() delete ui; } -void SoundGain::on_verticalSlider_valueChanged(int value) +void +SoundGain::on_verticalSlider_valueChanged(int value) { sound_gain = value; } - -void SoundGain::on_SoundGain_rejected() +void +SoundGain::on_SoundGain_rejected() { sound_gain = sound_gain_orig; } - diff --git a/src/qt/qt_soundgain.hpp b/src/qt/qt_soundgain.hpp index 0e19bab53..e4b52d959 100644 --- a/src/qt/qt_soundgain.hpp +++ b/src/qt/qt_soundgain.hpp @@ -7,8 +7,7 @@ namespace Ui { class SoundGain; } -class SoundGain : public QDialog -{ +class SoundGain : public QDialog { Q_OBJECT public: @@ -22,7 +21,7 @@ private slots: private: Ui::SoundGain *ui; - int sound_gain_orig; + int sound_gain_orig; }; #endif // QT_SOUNDGAIN_HPP diff --git a/src/qt/qt_specifydimensions.cpp b/src/qt/qt_specifydimensions.cpp index caf831466..c01ef2ae4 100644 --- a/src/qt/qt_specifydimensions.cpp +++ b/src/qt/qt_specifydimensions.cpp @@ -1,18 +1,18 @@ /* - * 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. + * 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. + * This file is part of the 86Box distribution. * - * Specify dimensions UI module. + * Specify dimensions UI module. * * * - * Authors: Cacodemon345 + * Authors: Cacodemon345 * - * Copyright 2021-2022 Cacodemon345 + * Copyright 2021-2022 Cacodemon345 */ #include "qt_specifydimensions.h" #include "ui_qt_specifydimensions.h" @@ -20,23 +20,25 @@ #include "qt_mainwindow.hpp" #include "ui_qt_mainwindow.h" +#include "qt_util.hpp" + #include #include #include +#include -extern "C" -{ +extern "C" { #include <86box/86box.h> #include <86box/plat.h> #include <86box/ui.h> #include <86box/video.h> } -extern MainWindow* main_window; +extern MainWindow *main_window; -SpecifyDimensions::SpecifyDimensions(QWidget *parent) : - QDialog(parent), - ui(new Ui::SpecifyDimensions) +SpecifyDimensions::SpecifyDimensions(QWidget *parent) + : QDialog(parent) + , ui(new Ui::SpecifyDimensions) { ui->setupUi(this); ui->checkBox->setChecked(vid_resize == 2); @@ -44,6 +46,11 @@ SpecifyDimensions::SpecifyDimensions(QWidget *parent) : ui->spinBoxWidth->setValue(main_window->getRenderWidgetSize().width()); ui->spinBoxHeight->setRange(16, 2048); ui->spinBoxHeight->setValue(main_window->getRenderWidgetSize().height()); + + if (dpi_scale == 0) { + ui->spinBoxWidth->setValue(main_window->getRenderWidgetSize().width() * util::screenOfWidget(main_window)->devicePixelRatio()); + ui->spinBoxHeight->setValue(main_window->getRenderWidgetSize().height() * util::screenOfWidget(main_window)->devicePixelRatio()); + } } SpecifyDimensions::~SpecifyDimensions() @@ -51,42 +58,58 @@ SpecifyDimensions::~SpecifyDimensions() delete ui; } -void SpecifyDimensions::on_SpecifyDimensions_accepted() +void +SpecifyDimensions::on_SpecifyDimensions_accepted() { - if (ui->checkBox->isChecked()) - { + if (ui->checkBox->isChecked()) { vid_resize = 2; main_window->setWindowFlag(Qt::WindowMaximizeButtonHint, false); main_window->setWindowFlag(Qt::MSWindowsFixedSizeDialogHint); window_remember = 0; - fixed_size_x = ui->spinBoxWidth->value(); - fixed_size_y = ui->spinBoxHeight->value(); + fixed_size_x = ui->spinBoxWidth->value(); + fixed_size_y = ui->spinBoxHeight->value(); + + main_window->resizeContents(fixed_size_x, fixed_size_y); - main_window->setFixedSize(ui->spinBoxWidth->value(), - ui->spinBoxHeight->value() - + (!hide_status_bar ? main_window->statusBar()->height() : 0) - + (!hide_tool_bar ? main_window->ui->toolBar->height() : 0) - + main_window->menuBar()->height()); - emit main_window->updateMenuResizeOptions(); main_window->show(); - main_window->ui->stackedWidget->switchRenderer((RendererStack::Renderer)vid_api); - } - else - { + for (int i = 1; i < MONITORS_NUM; i++) { + if (main_window->renderers[i]) { + main_window->renderers[i]->setWindowFlag(Qt::WindowMaximizeButtonHint, false); + main_window->renderers[i]->setWindowFlag(Qt::MSWindowsFixedSizeDialogHint); + emit main_window->resizeContentsMonitor(fixed_size_x, fixed_size_y, i); + if (show_second_monitors) { + main_window->renderers[i]->show(); + main_window->renderers[i]->switchRenderer((RendererStack::Renderer) vid_api); + } + } + } + main_window->ui->stackedWidget->switchRenderer((RendererStack::Renderer) vid_api); + } else { main_window->setFixedSize(QWIDGETSIZE_MAX, QWIDGETSIZE_MAX); main_window->ui->actionResizable_window->setChecked(false); vid_resize = 0; main_window->ui->actionResizable_window->trigger(); window_remember = 1; - window_w = ui->spinBoxWidth->value(); - window_h = ui->spinBoxHeight->value(); + window_w = ui->spinBoxWidth->value(); + window_h = ui->spinBoxHeight->value(); main_window->setFixedSize(QWIDGETSIZE_MAX, QWIDGETSIZE_MAX); emit main_window->resizeContents(ui->spinBoxWidth->value(), ui->spinBoxHeight->value()); + for (int i = 1; i < MONITORS_NUM; i++) { + if (main_window->renderers[i]) { + main_window->renderers[i]->setWindowFlag(Qt::WindowMaximizeButtonHint); + main_window->renderers[i]->setWindowFlag(Qt::MSWindowsFixedSizeDialogHint, false); + emit main_window->resizeContentsMonitor(ui->spinBoxWidth->value(), ui->spinBoxHeight->value(), i); + main_window->renderers[i]->setFixedSize(QWIDGETSIZE_MAX, QWIDGETSIZE_MAX); + if (show_second_monitors) { + main_window->renderers[i]->show(); + main_window->renderers[i]->switchRenderer((RendererStack::Renderer) vid_api); + } + } + } vid_resize = 1; emit main_window->updateMenuResizeOptions(); } main_window->show(); emit main_window->updateWindowRememberOption(); } - diff --git a/src/qt/qt_specifydimensions.h b/src/qt/qt_specifydimensions.h index 2aa820455..812e38707 100644 --- a/src/qt/qt_specifydimensions.h +++ b/src/qt/qt_specifydimensions.h @@ -7,8 +7,7 @@ namespace Ui { class SpecifyDimensions; } -class SpecifyDimensions : public QDialog -{ +class SpecifyDimensions : public QDialog { Q_OBJECT public: diff --git a/src/qt/qt_styleoverride.cpp b/src/qt/qt_styleoverride.cpp index a2af1296b..7ec5a341c 100644 --- a/src/qt/qt_styleoverride.cpp +++ b/src/qt/qt_styleoverride.cpp @@ -1,29 +1,30 @@ /* - * 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. + * 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. + * This file is part of the 86Box distribution. * - * Style override class. + * Style override class. * * * - * Authors: Teemu Korhonen + * Authors: Teemu Korhonen * - * Copyright 2022 Teemu Korhonen + * Copyright 2022 Teemu Korhonen */ #include "qt_styleoverride.hpp" #include #include -int StyleOverride::styleHint( - StyleHint hint, - const QStyleOption *option, - const QWidget *widget, - QStyleHintReturn *returnData) const +int +StyleOverride::styleHint( + StyleHint hint, + const QStyleOption *option, + const QWidget *widget, + QStyleHintReturn *returnData) const { /* Disable using menu with alt key */ if (hint == QStyle::SH_MenuBar_AltKeyNavigation) @@ -32,7 +33,8 @@ int StyleOverride::styleHint( return QProxyStyle::styleHint(hint, option, widget, returnData); } -void StyleOverride::polish(QWidget* widget) +void +StyleOverride::polish(QWidget *widget) { QProxyStyle::polish(widget); /* Disable title bar context help buttons globally as they are unused. */ @@ -48,7 +50,7 @@ void StyleOverride::polish(QWidget* widget) widget->setWindowFlag(Qt::WindowContextHelpButtonHint, false); } - if (qobject_cast(widget)) { - qobject_cast(widget)->view()->setMinimumWidth(widget->minimumSizeHint().width()); + if (qobject_cast(widget)) { + qobject_cast(widget)->view()->setMinimumWidth(widget->minimumSizeHint().width()); } } diff --git a/src/qt/qt_styleoverride.hpp b/src/qt/qt_styleoverride.hpp index 9a2223322..c04d01a12 100644 --- a/src/qt/qt_styleoverride.hpp +++ b/src/qt/qt_styleoverride.hpp @@ -5,16 +5,15 @@ #include #include -class StyleOverride : public QProxyStyle -{ +class StyleOverride : public QProxyStyle { public: int styleHint( - StyleHint hint, - const QStyleOption *option = nullptr, - const QWidget *widget = nullptr, - QStyleHintReturn *returnData = nullptr) const override; + StyleHint hint, + const QStyleOption *option = nullptr, + const QWidget *widget = nullptr, + QStyleHintReturn *returnData = nullptr) const override; - void polish(QWidget* widget) override; + void polish(QWidget *widget) override; }; #endif diff --git a/src/qt/qt_translations.qrc b/src/qt/qt_translations.qrc index 1de212273..017354f82 100644 --- a/src/qt/qt_translations.qrc +++ b/src/qt/qt_translations.qrc @@ -1,24 +1,27 @@ - 86box_cs-CZ.qm - 86box_de-DE.qm - 86box_en-US.qm - 86box_en-GB.qm - 86box_es-ES.qm - 86box_fi-FI.qm - 86box_fr-FR.qm - 86box_hr-HR.qm - 86box_hu-HU.qm - 86box_it-IT.qm - 86box_ja-JP.qm - 86box_ko-KR.qm - 86box_pl-PL.qm - 86box_pt-BR.qm - 86box_pt-PT.qm - 86box_ru-RU.qm - 86box_sl-SI.qm - 86box_tr-TR.qm - 86box_uk-UA.qm - 86box_zh-CN.qm + 86box_ca-ES.qm + 86box_cs-CZ.qm + 86box_de-DE.qm + 86box_en-US.qm + 86box_en-GB.qm + 86box_es-ES.qm + 86box_fi-FI.qm + 86box_fr-FR.qm + 86box_hr-HR.qm + 86box_hu-HU.qm + 86box_it-IT.qm + 86box_ja-JP.qm + 86box_ko-KR.qm + 86box_pl-PL.qm + 86box_pt-BR.qm + 86box_pt-PT.qm + 86box_ru-RU.qm + 86box_sk-SK.qm + 86box_sl-SI.qm + 86box_tr-TR.qm + 86box_uk-UA.qm + 86box_zh-CN.qm + 86box_zh-TW.qm diff --git a/src/qt/qt_ui.cpp b/src/qt/qt_ui.cpp index c9f5c5451..47e6b48a2 100644 --- a/src/qt/qt_ui.cpp +++ b/src/qt/qt_ui.cpp @@ -1,20 +1,20 @@ /* - * 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. + * 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. + * This file is part of the 86Box distribution. * - * Common UI functions. + * Common UI functions. * * * - * Authors: Joakim L. Gilje + * Authors: Joakim L. Gilje * Cacodemon345 * - * Copyright 2021 Joakim L. Gilje - * Copyright 2021-2022 Cacodemon345 + * Copyright 2021 Joakim L. Gilje + * Copyright 2021-2022 Cacodemon345 */ #include @@ -25,15 +25,36 @@ #include #include "qt_mainwindow.hpp" +#include "qt_machinestatus.hpp" -MainWindow* main_window = nullptr; +MainWindow *main_window = nullptr; -static QString sb_text, sb_buguitext, sb_mt32lcdtext; +static QString sb_text; +static QString sb_buguitext; +static QString sb_mt32lcdtext; extern "C" { +#include "86box/86box.h" #include <86box/plat.h> #include <86box/ui.h> +#include <86box/mouse.h> +#include <86box/timer.h> +#include <86box/86box.h> +#include <86box/device.h> +#include <86box/fdd.h> +#include <86box/hdc.h> +#include <86box/scsi.h> +#include <86box/scsi_device.h> +#include <86box/cartridge.h> +#include <86box/cassette.h> +#include <86box/cdrom.h> +#include <86box/zip.h> +#include <86box/mo.h> +#include <86box/hdd.h> +#include <86box/thread.h> +#include <86box/network.h> +#include <86box/machine_status.h> void plat_delay_ms(uint32_t count) @@ -41,7 +62,8 @@ plat_delay_ms(uint32_t count) QThread::msleep(count); } -wchar_t* ui_window_title(wchar_t* str) +wchar_t * +ui_window_title(wchar_t *str) { if (str == nullptr) { static wchar_t title[512]; @@ -54,33 +76,65 @@ wchar_t* ui_window_title(wchar_t* str) return str; } -extern "C" void qt_blit(int x, int y, int w, int h) +void +ui_hard_reset_completed() { - main_window->blitToWidget(x, y, w, h); + emit main_window->hardResetCompleted(); } -void mouse_poll() { - main_window->pollMouse(); +extern "C" void +qt_blit(int x, int y, int w, int h, int monitor_index) +{ + main_window->blitToWidget(x, y, w, h, monitor_index); } -void plat_resize(int w, int h) { - main_window->resizeContents(w, h); +extern "C" int vid_resize; +void +plat_resize_request(int w, int h, int monitor_index) +{ + if (video_fullscreen || is_quit) + return; + if (vid_resize & 2) { + plat_resize_monitor(fixed_size_x, fixed_size_y, monitor_index); + } else { + plat_resize_monitor(w, h, monitor_index); + } } -void plat_setfullscreen(int on) { +void +plat_resize_monitor(int w, int h, int monitor_index) +{ + if (monitor_index >= 1) + main_window->resizeContentsMonitor(w, h, monitor_index); + else + main_window->resizeContents(w, h); +} + +void +plat_setfullscreen(int on) +{ main_window->setFullscreen(on > 0 ? true : false); } -void plat_mouse_capture(int on) { +void +plat_mouse_capture(int on) +{ + if (!kbd_req_capture && (mouse_type == MOUSE_TYPE_NONE) && !machine_has_mouse()) + return; + main_window->setMouseCapture(on > 0 ? true : false); } -int ui_msgbox_header(int flags, void *header, void* message) { - if (header <= (void*)7168) header = plat_get_string((uintptr_t)header); - if (message <= (void*)7168) message = plat_get_string((uintptr_t)message); +int +ui_msgbox_header(int flags, void *header, void *message) +{ + if (header <= (void *) 7168) + header = plat_get_string((uintptr_t) header); + if (message <= (void *) 7168) + message = plat_get_string((uintptr_t) message); - auto hdr = (flags & MBX_ANSI) ? QString((char*)header) : QString::fromWCharArray(reinterpret_cast(header)); - auto msg = (flags & MBX_ANSI) ? QString((char*)message) : QString::fromWCharArray(reinterpret_cast(message)); + auto hdr = (flags & MBX_ANSI) ? QString((char *) header) : QString::fromWCharArray(reinterpret_cast(header)); + auto msg = (flags & MBX_ANSI) ? QString((char *) message) : QString::fromWCharArray(reinterpret_cast(message)); // any error in early init if (main_window == nullptr) { @@ -89,51 +143,85 @@ int ui_msgbox_header(int flags, void *header, void* message) { msgBox.exec(); } else { // else scope it to main_window - main_window->showMessage(hdr, msg); + main_window->showMessage(flags, hdr, msg); } return 0; } -int ui_msgbox(int flags, void *message) { +void +ui_init_monitor(int monitor_index) +{ + if (QThread::currentThread() == main_window->thread()) { + emit main_window->initRendererMonitor(monitor_index); + } else + emit main_window->initRendererMonitorForNonQtThread(monitor_index); +} + +void +ui_deinit_monitor(int monitor_index) +{ + if (QThread::currentThread() == main_window->thread()) { + emit main_window->destroyRendererMonitor(monitor_index); + } else + emit main_window->destroyRendererMonitorForNonQtThread(monitor_index); +} + +int +ui_msgbox(int flags, void *message) +{ return ui_msgbox_header(flags, nullptr, message); } -void ui_sb_update_text() { - emit main_window->statusBarMessage( !sb_mt32lcdtext.isEmpty() ? sb_mt32lcdtext : sb_text.isEmpty() ? sb_buguitext : sb_text); +void +ui_sb_update_text() +{ + emit main_window->statusBarMessage(!sb_mt32lcdtext.isEmpty() ? sb_mt32lcdtext : sb_text.isEmpty() ? sb_buguitext + : sb_text); } -void ui_sb_mt32lcd(char* str) +void +ui_sb_mt32lcd(char *str) { sb_mt32lcdtext = QString(str); ui_sb_update_text(); } -void ui_sb_set_text_w(wchar_t *wstr) { +void +ui_sb_set_text_w(wchar_t *wstr) +{ sb_text = QString::fromWCharArray(wstr); ui_sb_update_text(); } -void ui_sb_set_text(char *str) { +void +ui_sb_set_text(char *str) +{ sb_text = str; ui_sb_update_text(); } void -ui_sb_update_tip(int arg) { +ui_sb_update_tip(int arg) +{ main_window->updateStatusBarTip(arg); } void -ui_sb_update_panes() { +ui_sb_update_panes() +{ main_window->updateStatusBarPanes(); } -void ui_sb_bugui(char *str) { +void +ui_sb_bugui(char *str) +{ sb_buguitext = str; - ui_sb_update_text();; + ui_sb_update_text(); } -void ui_sb_set_ready(int ready) { +void +ui_sb_set_ready(int ready) +{ if (ready == 0) { ui_sb_bugui(nullptr); ui_sb_set_text(nullptr); @@ -141,17 +229,73 @@ void ui_sb_set_ready(int ready) { } void -ui_sb_update_icon_state(int tag, int state) { - if (main_window == nullptr) { - return; +ui_sb_update_icon_state(int tag, int state) +{ + int category = tag & 0xfffffff0; + int item = tag & 0xf; + switch (category) { + case SB_CASSETTE: + machine_status.cassette.empty = state > 0 ? true : false; + break; + case SB_CARTRIDGE: + machine_status.cartridge[item].empty = state > 0 ? true : false; + break; + case SB_FLOPPY: + machine_status.fdd[item].empty = state > 0 ? true : false; + break; + case SB_CDROM: + machine_status.cdrom[item].empty = state > 0 ? true : false; + break; + case SB_ZIP: + machine_status.zip[item].empty = state > 0 ? true : false; + break; + case SB_MO: + machine_status.mo[item].empty = state > 0 ? true : false; + break; + case SB_HDD: + break; + case SB_NETWORK: + machine_status.net[item].empty = state > 0 ? true : false; + break; + case SB_SOUND: + break; + case SB_TEXT: + break; } - main_window->updateStatusBarEmpty(tag, state > 0 ? true : false); } void -ui_sb_update_icon(int tag, int active) { - if (!update_icons) return; - main_window->updateStatusBarActivity(tag, active > 0 ? true : false); +ui_sb_update_icon(int tag, int active) +{ + int category = tag & 0xfffffff0; + int item = tag & 0xf; + switch (category) { + case SB_CASSETTE: + break; + case SB_CARTRIDGE: + break; + case SB_FLOPPY: + machine_status.fdd[item].active = active > 0 ? true : false; + break; + case SB_CDROM: + machine_status.cdrom[item].active = active > 0 ? true : false; + break; + case SB_ZIP: + machine_status.zip[item].active = active > 0 ? true : false; + break; + case SB_MO: + machine_status.mo[item].active = active > 0 ? true : false; + break; + case SB_HDD: + machine_status.hdd[item].active = active > 0 ? true : false; + break; + case SB_NETWORK: + machine_status.net[item].active = active > 0 ? true : false; + break; + case SB_SOUND: + break; + case SB_TEXT: + break; + } } - } diff --git a/src/qt/qt_unixmanagerfilter.cpp b/src/qt/qt_unixmanagerfilter.cpp new file mode 100644 index 000000000..5d94584e6 --- /dev/null +++ b/src/qt/qt_unixmanagerfilter.cpp @@ -0,0 +1,64 @@ +/* + * 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. + * + * Source file for Unix VM-managers (client-side) + * + * + * + * Authors: Teemu Korhonen + * Cacodemon345 + * + * Copyright 2022 Teemu Korhonen + * Copyright 2022 Cacodemon345 + */ + +#include "qt_unixmanagerfilter.hpp" + +UnixManagerSocket::UnixManagerSocket(QObject *obj) + : QLocalSocket(obj) +{ + connect(this, &QLocalSocket::readyRead, this, &UnixManagerSocket::readyToRead); +} + +void +UnixManagerSocket::readyToRead() +{ + if (canReadLine()) { + QByteArray line = readLine(); + if (line.size()) { + line.resize(line.size() - 1); + if (line == "showsettings") { + emit showsettings(); + } else if (line == "pause") { + emit pause(); + } else if (line == "cad") { + emit ctrlaltdel(); + } else if (line == "reset") { + emit resetVM(); + } else if (line == "shutdownnoprompt") { + emit force_shutdown(); + } else if (line == "shutdown") { + emit request_shutdown(); + } + } + } +} + +bool +UnixManagerSocket::eventFilter(QObject *obj, QEvent *event) +{ + if (state() == QLocalSocket::ConnectedState) { + if (event->type() == QEvent::WindowBlocked) { + write(QByteArray { "1" }); + } else if (event->type() == QEvent::WindowUnblocked) { + write(QByteArray { "0" }); + } + } + + return QObject::eventFilter(obj, event); +} diff --git a/src/qt/qt_unixmanagerfilter.hpp b/src/qt/qt_unixmanagerfilter.hpp new file mode 100644 index 000000000..0587e06ee --- /dev/null +++ b/src/qt/qt_unixmanagerfilter.hpp @@ -0,0 +1,50 @@ +/* + * 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. + * + * Header file for Unix VM-managers (client-side) + * + * + * + * Authors: Teemu Korhonen + * Cacodemon345 + * + * Copyright 2022 Teemu Korhonen + * Copyright 2022 Cacodemon345 + */ + +#ifndef QT_UNIXMANAGERFILTER_HPP +#define QT_UNIXMANAGERFILTER_HPP + +#include +#include +#include + +/* + * Filters messages from VM-manager and + * window blocked events to notify about open modal dialogs. + */ +class UnixManagerSocket : public QLocalSocket { + Q_OBJECT +public: + UnixManagerSocket(QObject *object = nullptr); +signals: + void pause(); + void ctrlaltdel(); + void showsettings(); + void resetVM(); + void request_shutdown(); + void force_shutdown(); + void dialogstatus(bool open); + +protected: + bool eventFilter(QObject *obj, QEvent *event) override; +protected slots: + void readyToRead(); +}; + +#endif diff --git a/src/qt/qt_util.cpp b/src/qt/qt_util.cpp index 771c6d94a..b05b656bb 100644 --- a/src/qt/qt_util.cpp +++ b/src/qt/qt_util.cpp @@ -1,60 +1,59 @@ /* - * 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. + * 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. + * This file is part of the 86Box distribution. * - * Utility functions. + * Utility functions. * * * - * Authors: Teemu Korhonen + * Authors: Teemu Korhonen * - * Copyright 2022 Teemu Korhonen + * Copyright 2022 Teemu Korhonen */ #include #include #include #include #if QT_VERSION <= QT_VERSION_CHECK(5, 14, 0) -#include +# include #endif #include "qt_util.hpp" -namespace util +namespace util { +QScreen * +screenOfWidget(QWidget *widget) { - QScreen* screenOfWidget(QWidget* widget) - { #if QT_VERSION <= QT_VERSION_CHECK(5, 14, 0) - return QApplication::screens()[QApplication::desktop()->screenNumber(widget) == -1 ? 0 : QApplication::desktop()->screenNumber(widget)]; + return QApplication::screens()[QApplication::desktop()->screenNumber(widget) == -1 ? 0 : QApplication::desktop()->screenNumber(widget)]; #else - return widget->screen(); + return widget->screen(); #endif - } +} - QString DlgFilter(std::initializer_list extensions, bool last) - { - QStringList temp; +QString +DlgFilter(std::initializer_list extensions, bool last) +{ + QStringList temp; - for (auto ext : extensions) - { + for (auto ext : extensions) { #ifdef Q_OS_UNIX - if (ext == "*") - { - temp.append("*"); - continue; - } - temp.append("*." % ext.toUpper()); -#endif - temp.append("*." % ext); + if (ext == "*") { + temp.append("*"); + continue; } + temp.append("*." % ext.toUpper()); +#endif + temp.append("*." % ext); + } #ifdef Q_OS_UNIX - temp.removeDuplicates(); + temp.removeDuplicates(); #endif - return " (" % temp.join(' ') % ")" % (!last ? ";;" : ""); - } + return " (" % temp.join(' ') % ")" % (!last ? ";;" : ""); +} } diff --git a/src/qt/qt_util.hpp b/src/qt/qt_util.hpp index 4e62c8e12..6ecd904b3 100644 --- a/src/qt/qt_util.hpp +++ b/src/qt/qt_util.hpp @@ -7,12 +7,11 @@ #include class QScreen; -namespace util -{ - /* Creates extension list for qt filedialog */ - QString DlgFilter(std::initializer_list extensions, bool last = false); - /* Returns screen the widget is on */ - QScreen* screenOfWidget(QWidget* widget); +namespace util { +/* Creates extension list for qt filedialog */ +QString DlgFilter(std::initializer_list extensions, bool last = false); +/* Returns screen the widget is on */ +QScreen *screenOfWidget(QWidget *widget); }; #endif diff --git a/src/qt/qt_vulkanrenderer.cpp b/src/qt/qt_vulkanrenderer.cpp new file mode 100644 index 000000000..9227cdcb3 --- /dev/null +++ b/src/qt/qt_vulkanrenderer.cpp @@ -0,0 +1,1012 @@ +/**************************************************************************** +** +** Copyright (C) 2022 Cacodemon345 +** Copyright (C) 2017 The Qt Company Ltd. +** +** "Redistribution and use in source and binary forms, with or without +** modification, are permitted provided that the following conditions are +** met: +** * Redistributions of source code must retain the above copyright +** notice, this list of conditions and the following disclaimer. +** * Redistributions in binary form must reproduce the above copyright +** notice, this list of conditions and the following disclaimer in +** the documentation and/or other materials provided with the +** distribution. +** * Neither the name of The Qt Company Ltd nor the names of its +** contributors may be used to endorse or promote products derived +** from this software without specific prior written permission. +** +** +** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." +** +****************************************************************************/ + +#include +#include +#include "qt_vulkanrenderer.hpp" +#if QT_CONFIG(vulkan) +# include + +extern "C" { +# include <86box/86box.h> +} + +// Use a triangle strip to get a quad. +// +// Note that the vertex data and the projection matrix assume OpenGL. With +// Vulkan Y is negated in clip space and the near/far plane is at 0/1 instead +// of -1/1. These will be corrected for by an extra transformation when +// calculating the modelview-projection matrix. +static float vertexData[] = { // Y up, front = CW + // x, y, z, u, v + -1, -1, 0, 0, 1, + -1, 1, 0, 0, 0, + 1, -1, 0, 1, 1, + 1, 1, 0, 1, 0 +}; + +static const int UNIFORM_DATA_SIZE = 16 * sizeof(float); + +static inline VkDeviceSize +aligned(VkDeviceSize v, VkDeviceSize byteAlign) +{ + return (v + byteAlign - 1) & ~(byteAlign - 1); +} + +VulkanRenderer2::VulkanRenderer2(QVulkanWindow *w) + : m_window(w) +{ +} + +VkShaderModule +VulkanRenderer2::createShader(const QString &name) +{ + QFile file(name); + if (!file.open(QIODevice::ReadOnly)) { + qWarning("Failed to read shader %s", qPrintable(name)); + return VK_NULL_HANDLE; + } + QByteArray blob = file.readAll(); + file.close(); + + VkShaderModuleCreateInfo shaderInfo; + memset(&shaderInfo, 0, sizeof(shaderInfo)); + shaderInfo.sType = VK_STRUCTURE_TYPE_SHADER_MODULE_CREATE_INFO; + shaderInfo.codeSize = blob.size(); + shaderInfo.pCode = reinterpret_cast(blob.constData()); + VkShaderModule shaderModule; + VkResult err = m_devFuncs->vkCreateShaderModule(m_window->device(), &shaderInfo, nullptr, &shaderModule); + if (err != VK_SUCCESS) { + qWarning("Failed to create shader module: %d", err); + return VK_NULL_HANDLE; + } + + return shaderModule; +} + +bool +VulkanRenderer2::createTexture() +{ + QImage img(2048, 2048, QImage::Format_RGBA8888_Premultiplied); + img.fill(QColor(0, 0, 0)); + + QVulkanFunctions *f = m_window->vulkanInstance()->functions(); + VkDevice dev = m_window->device(); + + m_texFormat = VK_FORMAT_B8G8R8A8_UNORM; + + // Now we can either map and copy the image data directly, or have to go + // through a staging buffer to copy and convert into the internal optimal + // tiling format. + VkFormatProperties props; + f->vkGetPhysicalDeviceFormatProperties(m_window->physicalDevice(), m_texFormat, &props); + const bool canSampleLinear = (props.linearTilingFeatures & VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT); + const bool canSampleOptimal = (props.optimalTilingFeatures & VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT); + if (!canSampleLinear && !canSampleOptimal) { + qWarning("Neither linear nor optimal image sampling is supported for RGBA8"); + return false; + } + + static bool alwaysStage = qEnvironmentVariableIntValue("QT_VK_FORCE_STAGE_TEX"); + + if (canSampleLinear && !alwaysStage) { + if (!createTextureImage(img.size(), &m_texImage, &m_texMem, + VK_IMAGE_TILING_LINEAR, VK_IMAGE_USAGE_SAMPLED_BIT, + m_window->hostVisibleMemoryIndex())) + return false; + + if (!writeLinearImage(img, m_texImage, m_texMem)) + return false; + + m_texLayoutPending = true; + } else { + if (!createTextureImage(img.size(), &m_texStaging, &m_texStagingMem, + VK_IMAGE_TILING_LINEAR, VK_IMAGE_USAGE_TRANSFER_SRC_BIT, + m_window->hostVisibleMemoryIndex())) + return false; + + if (!createTextureImage(img.size(), &m_texImage, &m_texMem, + VK_IMAGE_TILING_OPTIMAL, VK_IMAGE_USAGE_TRANSFER_DST_BIT | VK_IMAGE_USAGE_SAMPLED_BIT, + m_window->deviceLocalMemoryIndex())) + return false; + + if (!writeLinearImage(img, m_texStaging, m_texStagingMem)) + return false; + + m_texStagingPending = true; + } + + VkImageViewCreateInfo viewInfo; + memset(&viewInfo, 0, sizeof(viewInfo)); + viewInfo.sType = VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO; + viewInfo.image = m_texImage; + viewInfo.viewType = VK_IMAGE_VIEW_TYPE_2D; + viewInfo.format = m_texFormat; + viewInfo.components.r = VK_COMPONENT_SWIZZLE_R; + viewInfo.components.g = VK_COMPONENT_SWIZZLE_G; + viewInfo.components.b = VK_COMPONENT_SWIZZLE_B; + viewInfo.components.a = VK_COMPONENT_SWIZZLE_A; + viewInfo.subresourceRange.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT; + viewInfo.subresourceRange.levelCount = viewInfo.subresourceRange.layerCount = 1; + + VkResult err = m_devFuncs->vkCreateImageView(dev, &viewInfo, nullptr, &m_texView); + if (err != VK_SUCCESS) { + qWarning("Failed to create image view for texture: %d", err); + return false; + } + + m_texSize = img.size(); + + return true; +} + +bool +VulkanRenderer2::createTextureImage(const QSize &size, VkImage *image, VkDeviceMemory *mem, + VkImageTiling tiling, VkImageUsageFlags usage, uint32_t memIndex) +{ + VkDevice dev = m_window->device(); + + VkImageCreateInfo imageInfo; + memset(&imageInfo, 0, sizeof(imageInfo)); + imageInfo.sType = VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO; + imageInfo.imageType = VK_IMAGE_TYPE_2D; + imageInfo.format = m_texFormat; + imageInfo.extent.width = size.width(); + imageInfo.extent.height = size.height(); + imageInfo.extent.depth = 1; + imageInfo.mipLevels = 1; + imageInfo.arrayLayers = 1; + imageInfo.samples = VK_SAMPLE_COUNT_1_BIT; + imageInfo.tiling = tiling; + imageInfo.usage = usage; + imageInfo.initialLayout = VK_IMAGE_LAYOUT_PREINITIALIZED; + + VkResult err = m_devFuncs->vkCreateImage(dev, &imageInfo, nullptr, image); + if (err != VK_SUCCESS) { + qWarning("Failed to create linear image for texture: %d", err); + return false; + } + + VkMemoryRequirements memReq; + m_devFuncs->vkGetImageMemoryRequirements(dev, *image, &memReq); + + if (!(memReq.memoryTypeBits & (1 << memIndex))) { + VkPhysicalDeviceMemoryProperties physDevMemProps; + m_window->vulkanInstance()->functions()->vkGetPhysicalDeviceMemoryProperties(m_window->physicalDevice(), &physDevMemProps); + for (uint32_t i = 0; i < physDevMemProps.memoryTypeCount; ++i) { + if (!(memReq.memoryTypeBits & (1 << i))) + continue; + memIndex = i; + } + } + + VkMemoryAllocateInfo allocInfo = { + VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO, + nullptr, + memReq.size, + memIndex + }; + qDebug("allocating %u bytes for texture image", uint32_t(memReq.size)); + + err = m_devFuncs->vkAllocateMemory(dev, &allocInfo, nullptr, mem); + if (err != VK_SUCCESS) { + qWarning("Failed to allocate memory for linear image: %d", err); + return false; + } + + err = m_devFuncs->vkBindImageMemory(dev, *image, *mem, 0); + if (err != VK_SUCCESS) { + qWarning("Failed to bind linear image memory: %d", err); + return false; + } + + return true; +} + +bool +VulkanRenderer2::writeLinearImage(const QImage &img, VkImage image, VkDeviceMemory memory) +{ + VkDevice dev = m_window->device(); + + VkImageSubresource subres = { + VK_IMAGE_ASPECT_COLOR_BIT, + 0, // mip level + 0 + }; + VkSubresourceLayout layout; + m_devFuncs->vkGetImageSubresourceLayout(dev, image, &subres, &layout); + + uchar *p; + VkResult err = m_devFuncs->vkMapMemory(dev, memory, layout.offset, layout.size, 0, reinterpret_cast(&p)); + if (err != VK_SUCCESS) { + qWarning("Failed to map memory for linear image: %d", err); + return false; + } + + for (int y = 0; y < img.height(); ++y) { + const uchar *line = img.constScanLine(y); + memcpy(p, line, img.width() * 4); + p += layout.rowPitch; + } + + m_devFuncs->vkUnmapMemory(dev, memory); + return true; +} + +void +VulkanRenderer2::ensureTexture() +{ + if (!m_texLayoutPending && !m_texStagingPending) + return; + + Q_ASSERT(m_texLayoutPending != m_texStagingPending); + VkCommandBuffer cb = m_window->currentCommandBuffer(); + + VkImageMemoryBarrier barrier; + memset(&barrier, 0, sizeof(barrier)); + barrier.sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER; + barrier.subresourceRange.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT; + barrier.subresourceRange.levelCount = barrier.subresourceRange.layerCount = 1; + + if (m_texLayoutPending) { + m_texLayoutPending = false; + + barrier.oldLayout = VK_IMAGE_LAYOUT_PREINITIALIZED; + barrier.newLayout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL; + barrier.srcAccessMask = VK_ACCESS_HOST_WRITE_BIT; + barrier.dstAccessMask = VK_ACCESS_SHADER_READ_BIT; + barrier.image = m_texImage; + + m_devFuncs->vkCmdPipelineBarrier(cb, + VK_PIPELINE_STAGE_HOST_BIT, + VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT, + 0, 0, nullptr, 0, nullptr, + 1, &barrier); + + VkDevice dev = m_window->device(); + + VkImageSubresource subres = { + VK_IMAGE_ASPECT_COLOR_BIT, + 0, // mip level + 0 + }; + VkSubresourceLayout layout; + m_devFuncs->vkGetImageSubresourceLayout(dev, m_texImage, &subres, &layout); + + VkResult err = m_devFuncs->vkMapMemory(dev, m_texMem, layout.offset, layout.size, 0, reinterpret_cast(&mappedPtr)); + if (err != VK_SUCCESS) { + qWarning("Failed to map memory for linear image: %d", err); + return emit qobject_cast(m_window)->errorInitializing(); + } + imagePitch = layout.rowPitch; + + if (qobject_cast(m_window)) { + emit qobject_cast(m_window)->rendererInitialized(); + } + } else { + m_texStagingPending = false; + + if (!m_texStagingTransferLayout) { + barrier.oldLayout = VK_IMAGE_LAYOUT_PREINITIALIZED; + barrier.newLayout = VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL; + barrier.srcAccessMask = VK_ACCESS_HOST_WRITE_BIT; + barrier.dstAccessMask = VK_ACCESS_TRANSFER_READ_BIT; + barrier.image = m_texStaging; + m_devFuncs->vkCmdPipelineBarrier(cb, + VK_PIPELINE_STAGE_HOST_BIT, + VK_PIPELINE_STAGE_TRANSFER_BIT, + 0, 0, nullptr, 0, nullptr, + 1, &barrier); + + barrier.oldLayout = VK_IMAGE_LAYOUT_PREINITIALIZED; + barrier.newLayout = VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL; + barrier.srcAccessMask = 0; + barrier.dstAccessMask = VK_ACCESS_TRANSFER_WRITE_BIT; + barrier.image = m_texImage; + m_devFuncs->vkCmdPipelineBarrier(cb, + VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT, + VK_PIPELINE_STAGE_TRANSFER_BIT, + 0, 0, nullptr, 0, nullptr, + 1, &barrier); + + VkDevice dev = m_window->device(); + + VkImageSubresource subres = { + VK_IMAGE_ASPECT_COLOR_BIT, + 0, // mip level + 0 + }; + VkSubresourceLayout layout; + m_devFuncs->vkGetImageSubresourceLayout(dev, m_texStaging, &subres, &layout); + + VkResult err = m_devFuncs->vkMapMemory(dev, m_texStagingMem, layout.offset, layout.size, 0, reinterpret_cast(&mappedPtr)); + if (err != VK_SUCCESS) { + qWarning("Failed to map memory for linear image: %d", err); + return emit qobject_cast(m_window)->errorInitializing(); + } + imagePitch = layout.rowPitch; + + if (qobject_cast(m_window)) { + emit qobject_cast(m_window)->rendererInitialized(); + } + + m_texStagingTransferLayout = true; + } + + VkImageCopy copyInfo; + memset(©Info, 0, sizeof(copyInfo)); + copyInfo.srcSubresource.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT; + copyInfo.srcSubresource.layerCount = 1; + copyInfo.dstSubresource.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT; + copyInfo.dstSubresource.layerCount = 1; + copyInfo.extent.width = m_texSize.width(); + copyInfo.extent.height = m_texSize.height(); + copyInfo.extent.depth = 1; + m_devFuncs->vkCmdCopyImage(cb, m_texStaging, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, + m_texImage, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, 1, ©Info); + + barrier.oldLayout = VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL; + barrier.newLayout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL; + barrier.srcAccessMask = VK_ACCESS_TRANSFER_WRITE_BIT; + barrier.dstAccessMask = VK_ACCESS_SHADER_READ_BIT; + barrier.image = m_texImage; + m_devFuncs->vkCmdPipelineBarrier(cb, + VK_PIPELINE_STAGE_TRANSFER_BIT, + VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT, + 0, 0, nullptr, 0, nullptr, + 1, &barrier); + } +} + +void +VulkanRenderer2::updateSamplers() +{ + static int cur_video_filter_method = -1; + + if (cur_video_filter_method != video_filter_method) { + cur_video_filter_method = video_filter_method; + m_devFuncs->vkDeviceWaitIdle(m_window->device()); + + VkDescriptorImageInfo descImageInfo = { + cur_video_filter_method == 1 ? m_linearSampler : m_sampler, + m_texView, + VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL + }; + + for (int i = 0; i < m_window->concurrentFrameCount(); i++) { + VkWriteDescriptorSet descWrite[2]; + memset(descWrite, 0, sizeof(descWrite)); + descWrite[0].sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET; + descWrite[0].dstSet = m_descSet[i]; + descWrite[0].dstBinding = 0; + descWrite[0].descriptorCount = 1; + descWrite[0].descriptorType = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER; + descWrite[0].pBufferInfo = &m_uniformBufInfo[i]; + + descWrite[1].sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET; + descWrite[1].dstSet = m_descSet[i]; + descWrite[1].dstBinding = 1; + descWrite[1].descriptorCount = 1; + descWrite[1].descriptorType = VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER; + descWrite[1].pImageInfo = &descImageInfo; + m_devFuncs->vkUpdateDescriptorSets(m_window->device(), 2, descWrite, 0, nullptr); + } + } +} + +void +VulkanRenderer2::initResources() +{ + qDebug("initResources"); + + VkDevice dev = m_window->device(); + m_devFuncs = m_window->vulkanInstance()->deviceFunctions(dev); + + // The setup is similar to hellovulkantriangle. The difference is the + // presence of a second vertex attribute (texcoord), a sampler, and that we + // need blending. + + const int concurrentFrameCount = m_window->concurrentFrameCount(); + const VkPhysicalDeviceLimits *pdevLimits = &m_window->physicalDeviceProperties()->limits; + const VkDeviceSize uniAlign = pdevLimits->minUniformBufferOffsetAlignment; + qDebug("uniform buffer offset alignment is %u", (uint) uniAlign); + VkBufferCreateInfo bufInfo; + memset(&bufInfo, 0, sizeof(bufInfo)); + bufInfo.sType = VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO; + // Our internal layout is vertex, uniform, uniform, ... with each uniform buffer start offset aligned to uniAlign. + const VkDeviceSize vertexAllocSize = aligned(sizeof(vertexData), uniAlign); + const VkDeviceSize uniformAllocSize = aligned(UNIFORM_DATA_SIZE, uniAlign); + bufInfo.size = vertexAllocSize + concurrentFrameCount * uniformAllocSize; + bufInfo.usage = VK_BUFFER_USAGE_VERTEX_BUFFER_BIT | VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT; + + VkResult err = m_devFuncs->vkCreateBuffer(dev, &bufInfo, nullptr, &m_buf); + if (err != VK_SUCCESS) { + qWarning("Failed to create buffer: %d", err); + return emit qobject_cast(m_window)->errorInitializing(); + } + + VkMemoryRequirements memReq; + m_devFuncs->vkGetBufferMemoryRequirements(dev, m_buf, &memReq); + + VkMemoryAllocateInfo memAllocInfo = { + VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO, + nullptr, + memReq.size, + m_window->hostVisibleMemoryIndex() + }; + + err = m_devFuncs->vkAllocateMemory(dev, &memAllocInfo, nullptr, &m_bufMem); + if (err != VK_SUCCESS) { + qWarning("Failed to allocate memory: %d", err); + return emit qobject_cast(m_window)->errorInitializing(); + } + + err = m_devFuncs->vkBindBufferMemory(dev, m_buf, m_bufMem, 0); + if (err != VK_SUCCESS) { + qWarning("Failed to bind buffer memory: %d", err); + return emit qobject_cast(m_window)->errorInitializing(); + } + + quint8 *p; + err = m_devFuncs->vkMapMemory(dev, m_bufMem, 0, memReq.size, 0, reinterpret_cast(&p)); + if (err != VK_SUCCESS) { + qWarning("Failed to map memory: %d", err); + return emit qobject_cast(m_window)->errorInitializing(); + } + memcpy(p, vertexData, sizeof(vertexData)); + QMatrix4x4 ident; + memset(m_uniformBufInfo, 0, sizeof(m_uniformBufInfo)); + for (int i = 0; i < concurrentFrameCount; ++i) { + const VkDeviceSize offset = vertexAllocSize + i * uniformAllocSize; + memcpy(p + offset, ident.constData(), 16 * sizeof(float)); + m_uniformBufInfo[i].buffer = m_buf; + m_uniformBufInfo[i].offset = offset; + m_uniformBufInfo[i].range = uniformAllocSize; + } + m_devFuncs->vkUnmapMemory(dev, m_bufMem); + + VkVertexInputBindingDescription vertexBindingDesc = { + 0, // binding + 5 * sizeof(float), + VK_VERTEX_INPUT_RATE_VERTEX + }; + VkVertexInputAttributeDescription vertexAttrDesc[] = { + {// position + 0, // location + 0, // binding + VK_FORMAT_R32G32B32_SFLOAT, + 0 }, + { // texcoord + 1, + 0, + VK_FORMAT_R32G32_SFLOAT, + 3 * sizeof(float)} + }; + + VkPipelineVertexInputStateCreateInfo vertexInputInfo; + vertexInputInfo.sType = VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO; + vertexInputInfo.pNext = nullptr; + vertexInputInfo.flags = 0; + vertexInputInfo.vertexBindingDescriptionCount = 1; + vertexInputInfo.pVertexBindingDescriptions = &vertexBindingDesc; + vertexInputInfo.vertexAttributeDescriptionCount = 2; + vertexInputInfo.pVertexAttributeDescriptions = vertexAttrDesc; + + // Sampler. + VkSamplerCreateInfo samplerInfo; + memset(&samplerInfo, 0, sizeof(samplerInfo)); + samplerInfo.sType = VK_STRUCTURE_TYPE_SAMPLER_CREATE_INFO; + samplerInfo.magFilter = VK_FILTER_NEAREST; + samplerInfo.minFilter = VK_FILTER_NEAREST; + samplerInfo.addressModeU = VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE; + samplerInfo.addressModeV = VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE; + samplerInfo.addressModeW = VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE; + samplerInfo.maxAnisotropy = 1.0f; + samplerInfo.maxLod = 0.25; + err = m_devFuncs->vkCreateSampler(dev, &samplerInfo, nullptr, &m_sampler); + if (err != VK_SUCCESS) { + qWarning("Failed to create sampler: %d", err); + return emit qobject_cast(m_window)->errorInitializing(); + } + + samplerInfo.magFilter = VK_FILTER_LINEAR; + samplerInfo.minFilter = VK_FILTER_LINEAR; + err = m_devFuncs->vkCreateSampler(dev, &samplerInfo, nullptr, &m_linearSampler); + if (err != VK_SUCCESS) { + qWarning("Failed to create sampler: %d", err); + return emit qobject_cast(m_window)->errorInitializing(); + } + + // Texture. + if (!createTexture()) { + qWarning("Failed to create texture"); + return emit qobject_cast(m_window)->errorInitializing(); + } + + // Set up descriptor set and its layout. + VkDescriptorPoolSize descPoolSizes[2] = { + {VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, uint32_t(concurrentFrameCount)}, + { VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, uint32_t(concurrentFrameCount)} + }; + VkDescriptorPoolCreateInfo descPoolInfo; + memset(&descPoolInfo, 0, sizeof(descPoolInfo)); + descPoolInfo.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_POOL_CREATE_INFO; + descPoolInfo.maxSets = concurrentFrameCount; + descPoolInfo.poolSizeCount = 2; + descPoolInfo.pPoolSizes = descPoolSizes; + err = m_devFuncs->vkCreateDescriptorPool(dev, &descPoolInfo, nullptr, &m_descPool); + if (err != VK_SUCCESS) { + qWarning("Failed to create descriptor pool: %d", err); + return emit qobject_cast(m_window)->errorInitializing(); + } + + VkDescriptorSetLayoutBinding layoutBinding[2] = { + {0, // binding + VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, + 1, // descriptorCount + VK_SHADER_STAGE_VERTEX_BIT, + nullptr}, + { 1, // binding + VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, + 1, // descriptorCount + VK_SHADER_STAGE_FRAGMENT_BIT, + nullptr} + }; + VkDescriptorSetLayoutCreateInfo descLayoutInfo = { + VK_STRUCTURE_TYPE_DESCRIPTOR_SET_LAYOUT_CREATE_INFO, + nullptr, + 0, + 2, // bindingCount + layoutBinding + }; + err = m_devFuncs->vkCreateDescriptorSetLayout(dev, &descLayoutInfo, nullptr, &m_descSetLayout); + if (err != VK_SUCCESS) { + qWarning("Failed to create descriptor set layout: %d", err); + return emit qobject_cast(m_window)->errorInitializing(); + } + + for (int i = 0; i < concurrentFrameCount; ++i) { + VkDescriptorSetAllocateInfo descSetAllocInfo = { + VK_STRUCTURE_TYPE_DESCRIPTOR_SET_ALLOCATE_INFO, + nullptr, + m_descPool, + 1, + &m_descSetLayout + }; + err = m_devFuncs->vkAllocateDescriptorSets(dev, &descSetAllocInfo, &m_descSet[i]); + if (err != VK_SUCCESS) { + qWarning("Failed to allocate descriptor set: %d", err); + return emit qobject_cast(m_window)->errorInitializing(); + } + + VkWriteDescriptorSet descWrite[2]; + memset(descWrite, 0, sizeof(descWrite)); + descWrite[0].sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET; + descWrite[0].dstSet = m_descSet[i]; + descWrite[0].dstBinding = 0; + descWrite[0].descriptorCount = 1; + descWrite[0].descriptorType = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER; + descWrite[0].pBufferInfo = &m_uniformBufInfo[i]; + + VkDescriptorImageInfo descImageInfo = { + video_filter_method == 1 ? m_linearSampler : m_sampler, + m_texView, + VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL + }; + + descWrite[1].sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET; + descWrite[1].dstSet = m_descSet[i]; + descWrite[1].dstBinding = 1; + descWrite[1].descriptorCount = 1; + descWrite[1].descriptorType = VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER; + descWrite[1].pImageInfo = &descImageInfo; + + m_devFuncs->vkUpdateDescriptorSets(dev, 2, descWrite, 0, nullptr); + } + + // Pipeline cache + VkPipelineCacheCreateInfo pipelineCacheInfo; + memset(&pipelineCacheInfo, 0, sizeof(pipelineCacheInfo)); + pipelineCacheInfo.sType = VK_STRUCTURE_TYPE_PIPELINE_CACHE_CREATE_INFO; + err = m_devFuncs->vkCreatePipelineCache(dev, &pipelineCacheInfo, nullptr, &m_pipelineCache); + if (err != VK_SUCCESS) { + qWarning("Failed to create pipeline cache: %d", err); + return emit qobject_cast(m_window)->errorInitializing(); + } + + // Pipeline layout + VkPipelineLayoutCreateInfo pipelineLayoutInfo; + memset(&pipelineLayoutInfo, 0, sizeof(pipelineLayoutInfo)); + pipelineLayoutInfo.sType = VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO; + pipelineLayoutInfo.setLayoutCount = 1; + pipelineLayoutInfo.pSetLayouts = &m_descSetLayout; + err = m_devFuncs->vkCreatePipelineLayout(dev, &pipelineLayoutInfo, nullptr, &m_pipelineLayout); + if (err != VK_SUCCESS) { + qWarning("Failed to create pipeline layout: %d", err); + return emit qobject_cast(m_window)->errorInitializing(); + } + + // Shaders +#if 0 + #version 440 + + layout(location = 0) in vec4 position; + layout(location = 1) in vec2 texcoord; + + layout(location = 0) out vec2 v_texcoord; + + layout(std140, binding = 0) uniform buf { + mat4 mvp; + } ubuf; + + out gl_PerVertex { vec4 gl_Position; }; + + void main() + { + v_texcoord = texcoord; + gl_Position = ubuf.mvp * position; + } +#endif + VkShaderModule vertShaderModule = createShader(QStringLiteral(":/texture_vert.spv")); +#if 0 + #version 440 + + layout(location = 0) in vec2 v_texcoord; + + layout(location = 0) out vec4 fragColor; + + layout(binding = 1) uniform sampler2D tex; + + void main() + { + fragColor = texture(tex, v_texcoord); + } +#endif + VkShaderModule fragShaderModule = createShader(QStringLiteral(":/texture_frag.spv")); + + // Graphics pipeline + VkGraphicsPipelineCreateInfo pipelineInfo; + memset(&pipelineInfo, 0, sizeof(pipelineInfo)); + pipelineInfo.sType = VK_STRUCTURE_TYPE_GRAPHICS_PIPELINE_CREATE_INFO; + + VkPipelineShaderStageCreateInfo shaderStages[2] = { + { + VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO, + nullptr, + 0, + VK_SHADER_STAGE_VERTEX_BIT, + vertShaderModule, + "main", + nullptr + }, + { + VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO, + nullptr, + 0, + VK_SHADER_STAGE_FRAGMENT_BIT, + fragShaderModule, + "main", + nullptr + } + }; + pipelineInfo.stageCount = 2; + pipelineInfo.pStages = shaderStages; + + pipelineInfo.pVertexInputState = &vertexInputInfo; + + VkPipelineInputAssemblyStateCreateInfo ia; + memset(&ia, 0, sizeof(ia)); + ia.sType = VK_STRUCTURE_TYPE_PIPELINE_INPUT_ASSEMBLY_STATE_CREATE_INFO; + ia.topology = VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP; + pipelineInfo.pInputAssemblyState = &ia; + + // The viewport and scissor will be set dynamically via vkCmdSetViewport/Scissor. + // This way the pipeline does not need to be touched when resizing the window. + VkPipelineViewportStateCreateInfo vp; + memset(&vp, 0, sizeof(vp)); + vp.sType = VK_STRUCTURE_TYPE_PIPELINE_VIEWPORT_STATE_CREATE_INFO; + vp.viewportCount = 1; + vp.scissorCount = 1; + pipelineInfo.pViewportState = &vp; + + VkPipelineRasterizationStateCreateInfo rs; + memset(&rs, 0, sizeof(rs)); + rs.sType = VK_STRUCTURE_TYPE_PIPELINE_RASTERIZATION_STATE_CREATE_INFO; + rs.polygonMode = VK_POLYGON_MODE_FILL; + rs.cullMode = VK_CULL_MODE_BACK_BIT; + rs.frontFace = VK_FRONT_FACE_CLOCKWISE; + rs.lineWidth = 1.0f; + pipelineInfo.pRasterizationState = &rs; + + VkPipelineMultisampleStateCreateInfo ms; + memset(&ms, 0, sizeof(ms)); + ms.sType = VK_STRUCTURE_TYPE_PIPELINE_MULTISAMPLE_STATE_CREATE_INFO; + ms.rasterizationSamples = VK_SAMPLE_COUNT_1_BIT; + pipelineInfo.pMultisampleState = &ms; + + VkPipelineDepthStencilStateCreateInfo ds; + memset(&ds, 0, sizeof(ds)); + ds.sType = VK_STRUCTURE_TYPE_PIPELINE_DEPTH_STENCIL_STATE_CREATE_INFO; + ds.depthTestEnable = VK_TRUE; + ds.depthWriteEnable = VK_TRUE; + ds.depthCompareOp = VK_COMPARE_OP_LESS_OR_EQUAL; + pipelineInfo.pDepthStencilState = &ds; + + VkPipelineColorBlendStateCreateInfo cb; + memset(&cb, 0, sizeof(cb)); + cb.sType = VK_STRUCTURE_TYPE_PIPELINE_COLOR_BLEND_STATE_CREATE_INFO; + // assume pre-multiplied alpha, blend, write out all of rgba + VkPipelineColorBlendAttachmentState att; + memset(&att, 0, sizeof(att)); + att.colorWriteMask = 0xF; + att.blendEnable = VK_TRUE; + att.srcColorBlendFactor = VK_BLEND_FACTOR_ONE; + att.dstColorBlendFactor = VK_BLEND_FACTOR_ONE_MINUS_SRC_ALPHA; + att.colorBlendOp = VK_BLEND_OP_ADD; + att.srcAlphaBlendFactor = VK_BLEND_FACTOR_ONE; + att.dstAlphaBlendFactor = VK_BLEND_FACTOR_ONE_MINUS_SRC_ALPHA; + att.alphaBlendOp = VK_BLEND_OP_ADD; + cb.attachmentCount = 1; + cb.pAttachments = &att; + pipelineInfo.pColorBlendState = &cb; + + VkDynamicState dynEnable[] = { VK_DYNAMIC_STATE_VIEWPORT, VK_DYNAMIC_STATE_SCISSOR }; + VkPipelineDynamicStateCreateInfo dyn; + memset(&dyn, 0, sizeof(dyn)); + dyn.sType = VK_STRUCTURE_TYPE_PIPELINE_DYNAMIC_STATE_CREATE_INFO; + dyn.dynamicStateCount = sizeof(dynEnable) / sizeof(VkDynamicState); + dyn.pDynamicStates = dynEnable; + pipelineInfo.pDynamicState = &dyn; + + pipelineInfo.layout = m_pipelineLayout; + pipelineInfo.renderPass = m_window->defaultRenderPass(); + + err = m_devFuncs->vkCreateGraphicsPipelines(dev, m_pipelineCache, 1, &pipelineInfo, nullptr, &m_pipeline); + if (err != VK_SUCCESS) { + qWarning("Failed to create graphics pipeline: %d", err); + return emit qobject_cast(m_window)->errorInitializing(); + } + + if (vertShaderModule) + m_devFuncs->vkDestroyShaderModule(dev, vertShaderModule, nullptr); + if (fragShaderModule) + m_devFuncs->vkDestroyShaderModule(dev, fragShaderModule, nullptr); + + pclog("Vulkan device: %s\n", m_window->physicalDeviceProperties()->deviceName); + pclog("Vulkan API version: %d.%d.%d\n", VK_VERSION_MAJOR(m_window->physicalDeviceProperties()->apiVersion), VK_VERSION_MINOR(m_window->physicalDeviceProperties()->apiVersion), VK_VERSION_PATCH(m_window->physicalDeviceProperties()->apiVersion)); + pclog("Vulkan driver version: %d.%d.%d\n", VK_VERSION_MAJOR(m_window->physicalDeviceProperties()->driverVersion), VK_VERSION_MINOR(m_window->physicalDeviceProperties()->driverVersion), VK_VERSION_PATCH(m_window->physicalDeviceProperties()->driverVersion)); +} + +void +VulkanRenderer2::initSwapChainResources() +{ + qDebug("initSwapChainResources"); + + // Projection matrix + m_proj = m_window->clipCorrectionMatrix(); // adjust for Vulkan-OpenGL clip space differences +} + +void +VulkanRenderer2::releaseSwapChainResources() +{ + qDebug("releaseSwapChainResources"); +} + +void +VulkanRenderer2::releaseResources() +{ + qDebug("releaseResources"); + + VkDevice dev = m_window->device(); + + if (m_sampler) { + m_devFuncs->vkDestroySampler(dev, m_sampler, nullptr); + m_sampler = VK_NULL_HANDLE; + } + + if (m_linearSampler) { + m_devFuncs->vkDestroySampler(dev, m_linearSampler, nullptr); + m_linearSampler = VK_NULL_HANDLE; + } + + if (m_texStaging) { + m_devFuncs->vkDestroyImage(dev, m_texStaging, nullptr); + m_texStaging = VK_NULL_HANDLE; + } + + if (m_texStagingMem) { + m_devFuncs->vkFreeMemory(dev, m_texStagingMem, nullptr); + m_texStagingMem = VK_NULL_HANDLE; + } + + if (m_texView) { + m_devFuncs->vkDestroyImageView(dev, m_texView, nullptr); + m_texView = VK_NULL_HANDLE; + } + + if (m_texImage) { + m_devFuncs->vkDestroyImage(dev, m_texImage, nullptr); + m_texImage = VK_NULL_HANDLE; + } + + if (m_texMem) { + m_devFuncs->vkFreeMemory(dev, m_texMem, nullptr); + m_texMem = VK_NULL_HANDLE; + } + + if (m_pipeline) { + m_devFuncs->vkDestroyPipeline(dev, m_pipeline, nullptr); + m_pipeline = VK_NULL_HANDLE; + } + + if (m_pipelineLayout) { + m_devFuncs->vkDestroyPipelineLayout(dev, m_pipelineLayout, nullptr); + m_pipelineLayout = VK_NULL_HANDLE; + } + + if (m_pipelineCache) { + m_devFuncs->vkDestroyPipelineCache(dev, m_pipelineCache, nullptr); + m_pipelineCache = VK_NULL_HANDLE; + } + + if (m_descSetLayout) { + m_devFuncs->vkDestroyDescriptorSetLayout(dev, m_descSetLayout, nullptr); + m_descSetLayout = VK_NULL_HANDLE; + } + + if (m_descPool) { + m_devFuncs->vkDestroyDescriptorPool(dev, m_descPool, nullptr); + m_descPool = VK_NULL_HANDLE; + } + + if (m_buf) { + m_devFuncs->vkDestroyBuffer(dev, m_buf, nullptr); + m_buf = VK_NULL_HANDLE; + } + + if (m_bufMem) { + m_devFuncs->vkFreeMemory(dev, m_bufMem, nullptr); + m_bufMem = VK_NULL_HANDLE; + } +} + +void +VulkanRenderer2::startNextFrame() +{ + VkDevice dev = m_window->device(); + VkCommandBuffer cb = m_window->currentCommandBuffer(); + const QSize sz = m_window->swapChainImageSize(); + + updateSamplers(); + // Add the necessary barriers and do the host-linear -> device-optimal copy, if not yet done. + ensureTexture(); + + VkClearColorValue clearColor = { + {0, 0, 0, 1} + }; + VkClearDepthStencilValue clearDS = { 1, 0 }; + VkClearValue clearValues[2]; + memset(clearValues, 0, sizeof(clearValues)); + clearValues[0].color = clearColor; + clearValues[1].depthStencil = clearDS; + + VkRenderPassBeginInfo rpBeginInfo; + memset(&rpBeginInfo, 0, sizeof(rpBeginInfo)); + rpBeginInfo.sType = VK_STRUCTURE_TYPE_RENDER_PASS_BEGIN_INFO; + rpBeginInfo.renderPass = m_window->defaultRenderPass(); + rpBeginInfo.framebuffer = m_window->currentFramebuffer(); + rpBeginInfo.renderArea.extent.width = sz.width(); + rpBeginInfo.renderArea.extent.height = sz.height(); + rpBeginInfo.clearValueCount = 2; + rpBeginInfo.pClearValues = clearValues; + VkCommandBuffer cmdBuf = m_window->currentCommandBuffer(); + m_devFuncs->vkCmdBeginRenderPass(cmdBuf, &rpBeginInfo, VK_SUBPASS_CONTENTS_INLINE); + + quint8 *p; + VkResult err = m_devFuncs->vkMapMemory(dev, m_bufMem, m_uniformBufInfo[m_window->currentFrame()].offset, + UNIFORM_DATA_SIZE, 0, reinterpret_cast(&p)); + if (err != VK_SUCCESS) + qFatal("Failed to map memory: %d", err); + QMatrix4x4 m = m_proj; + memcpy(p, m.constData(), 16 * sizeof(float)); + m_devFuncs->vkUnmapMemory(dev, m_bufMem); + p = nullptr; + + // Second pass for texture coordinates. + err = m_devFuncs->vkMapMemory(dev, m_bufMem, 0, + sizeof(vertexData), 0, reinterpret_cast(&p)); + if (err != VK_SUCCESS) + qFatal("Failed to map memory: %d", err); + + float *floatData = (float *) p; + auto source = qobject_cast(m_window)->source; + auto destination = qobject_cast(m_window)->destination; + floatData[3] = (float) source.x() / 2048.f; + floatData[9] = (float) (source.y()) / 2048.f; + floatData[8] = (float) source.x() / 2048.f; + floatData[4] = (float) (source.y() + source.height()) / 2048.f; + floatData[13] = (float) (source.x() + source.width()) / 2048.f; + floatData[19] = (float) (source.y()) / 2048.f; + floatData[18] = (float) (source.x() + source.width()) / 2048.f; + floatData[14] = (float) (source.y() + source.height()) / 2048.f; + + m_devFuncs->vkUnmapMemory(dev, m_bufMem); + + m_devFuncs->vkCmdBindPipeline(cb, VK_PIPELINE_BIND_POINT_GRAPHICS, m_pipeline); + m_devFuncs->vkCmdBindDescriptorSets(cb, VK_PIPELINE_BIND_POINT_GRAPHICS, m_pipelineLayout, 0, 1, + &m_descSet[m_window->currentFrame()], 0, nullptr); + VkDeviceSize vbOffset = 0; + m_devFuncs->vkCmdBindVertexBuffers(cb, 0, 1, &m_buf, &vbOffset); + + VkViewport viewport; + viewport.x = destination.x() * m_window->devicePixelRatio(); + viewport.y = destination.y() * m_window->devicePixelRatio(); + viewport.width = destination.width() * m_window->devicePixelRatio(); + viewport.height = destination.height() * m_window->devicePixelRatio(); + viewport.minDepth = 0; + viewport.maxDepth = 1; + m_devFuncs->vkCmdSetViewport(cb, 0, 1, &viewport); + + VkRect2D scissor; + scissor.offset.x = viewport.x; + scissor.offset.y = viewport.y; + scissor.extent.width = viewport.width; + scissor.extent.height = viewport.height; + m_devFuncs->vkCmdSetScissor(cb, 0, 1, &scissor); + + m_devFuncs->vkCmdDraw(cb, 4, 1, 0, 0); + + m_devFuncs->vkCmdEndRenderPass(cmdBuf); + + if (m_texStagingTransferLayout) { + VkImageMemoryBarrier barrier {}; + barrier.sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER; + barrier.subresourceRange.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT; + barrier.subresourceRange.levelCount = barrier.subresourceRange.layerCount = 1; + barrier.newLayout = VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL; + barrier.oldLayout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL; + barrier.dstAccessMask = VK_ACCESS_TRANSFER_WRITE_BIT; + barrier.srcAccessMask = VK_ACCESS_SHADER_READ_BIT; + barrier.image = m_texImage; + m_devFuncs->vkCmdPipelineBarrier(cb, + VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT, + VK_PIPELINE_STAGE_TRANSFER_BIT, + 0, 0, nullptr, 0, nullptr, + 1, &barrier); + m_texStagingPending = true; + } + + m_window->frameReady(); + m_window->requestUpdate(); // render continuously, throttled by the presentation rate +} +#endif diff --git a/src/qt/qt_vulkanrenderer.hpp b/src/qt/qt_vulkanrenderer.hpp new file mode 100644 index 000000000..d4580d848 --- /dev/null +++ b/src/qt/qt_vulkanrenderer.hpp @@ -0,0 +1,93 @@ +#pragma once +/**************************************************************************** +** +** Copyright (C) 2022 Cacodemon345 +** Copyright (C) 2017 The Qt Company Ltd. +** +** "Redistribution and use in source and binary forms, with or without +** modification, are permitted provided that the following conditions are +** met: +** * Redistributions of source code must retain the above copyright +** notice, this list of conditions and the following disclaimer. +** * Redistributions in binary form must reproduce the above copyright +** notice, this list of conditions and the following disclaimer in +** the documentation and/or other materials provided with the +** distribution. +** * Neither the name of The Qt Company Ltd nor the names of its +** contributors may be used to endorse or promote products derived +** from this software without specific prior written permission. +** +** +** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." +** +****************************************************************************/ + +#include +#include + +#if QT_CONFIG(vulkan) +# include "qt_vulkanwindowrenderer.hpp" + +class VulkanRenderer2 : public QVulkanWindowRenderer { +public: + void *mappedPtr = nullptr; + size_t imagePitch = 2048 * 4; + VulkanRenderer2(QVulkanWindow *w); + + void initResources() override; + void initSwapChainResources() override; + void releaseSwapChainResources() override; + void releaseResources() override; + + void startNextFrame() override; + +private: + VkShaderModule createShader(const QString &name); + bool createTexture(); + bool createTextureImage(const QSize &size, VkImage *image, VkDeviceMemory *mem, + VkImageTiling tiling, VkImageUsageFlags usage, uint32_t memIndex); + bool writeLinearImage(const QImage &img, VkImage image, VkDeviceMemory memory); + void ensureTexture(); + void updateSamplers(); + + QVulkanWindow *m_window; + QVulkanDeviceFunctions *m_devFuncs; + + VkDeviceMemory m_bufMem = VK_NULL_HANDLE; + VkBuffer m_buf = VK_NULL_HANDLE; + VkDescriptorBufferInfo m_uniformBufInfo[QVulkanWindow::MAX_CONCURRENT_FRAME_COUNT]; + + VkDescriptorPool m_descPool = VK_NULL_HANDLE; + VkDescriptorSetLayout m_descSetLayout = VK_NULL_HANDLE; + VkDescriptorSet m_descSet[QVulkanWindow::MAX_CONCURRENT_FRAME_COUNT]; + + VkPipelineCache m_pipelineCache = VK_NULL_HANDLE; + VkPipelineLayout m_pipelineLayout = VK_NULL_HANDLE; + VkPipeline m_pipeline = VK_NULL_HANDLE; + + VkSampler m_sampler = VK_NULL_HANDLE; + VkSampler m_linearSampler = VK_NULL_HANDLE; + VkImage m_texImage = VK_NULL_HANDLE; + VkDeviceMemory m_texMem = VK_NULL_HANDLE; + bool m_texLayoutPending = false; + VkImageView m_texView = VK_NULL_HANDLE; + VkImage m_texStaging = VK_NULL_HANDLE; + VkDeviceMemory m_texStagingMem = VK_NULL_HANDLE; + bool m_texStagingPending = false; + bool m_texStagingTransferLayout = false; + QSize m_texSize; + VkFormat m_texFormat; + + QMatrix4x4 m_proj; +}; +#endif diff --git a/src/qt/qt_vulkanwindowrenderer.cpp b/src/qt/qt_vulkanwindowrenderer.cpp new file mode 100644 index 000000000..60ad5be96 --- /dev/null +++ b/src/qt/qt_vulkanwindowrenderer.cpp @@ -0,0 +1,854 @@ +#include "qt_vulkanwindowrenderer.hpp" + +#include +#include + +#if QT_CONFIG(vulkan) +# include +# include +# include +# include + +# include "qt_mainwindow.hpp" +# include "qt_vulkanrenderer.hpp" + +extern "C" { +# include <86box/86box.h> +# include <86box/video.h> +} +# if 0 +extern MainWindow* main_window; +/* +#version 450 + +layout(location = 0) out vec2 v_texcoord; + +mat4 mvp = mat4( +vec4(1.0, 0, 0, 0), +vec4(0, 1.0, 0, 0), +vec4(0, 0, 1.0, 0), +vec4(0, 0, 0, 1.0) +); + +// Y coordinate in Vulkan viewport space is flipped as compared to OpenGL. +vec4 vertCoords[4] = vec4[]( +vec4(-1.0, -1.0, 0, 1), +vec4(1.0, -1.0, 0, 1), +vec4(-1.0, 1.0, 0, 1), +vec4(1.0, 1.0, 0, 1) +); + +layout(push_constant) uniform texCoordBuf { + vec2 texCoords[4]; +} texCoordUniform; + +out gl_PerVertex { vec4 gl_Position; }; + +void main() +{ + v_texcoord = texCoordUniform.texCoords[gl_VertexIndex]; + gl_Position = mvp * vertCoords[gl_VertexIndex]; +} +*/ +// Compiled with glslangValidator -V +static const uint8_t vertShaderCode[] = { + 0x03, 0x02, 0x23, 0x07, 0x00, 0x00, 0x01, 0x00, 0x0a, 0x00, 0x08, 0x00, + 0x37, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x11, 0x00, 0x02, 0x00, + 0x01, 0x00, 0x00, 0x00, 0x0b, 0x00, 0x06, 0x00, 0x01, 0x00, 0x00, 0x00, + 0x47, 0x4c, 0x53, 0x4c, 0x2e, 0x73, 0x74, 0x64, 0x2e, 0x34, 0x35, 0x30, + 0x00, 0x00, 0x00, 0x00, 0x0e, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x01, 0x00, 0x00, 0x00, 0x0f, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x04, 0x00, 0x00, 0x00, 0x6d, 0x61, 0x69, 0x6e, 0x00, 0x00, 0x00, 0x00, + 0x1f, 0x00, 0x00, 0x00, 0x27, 0x00, 0x00, 0x00, 0x2e, 0x00, 0x00, 0x00, + 0x03, 0x00, 0x03, 0x00, 0x02, 0x00, 0x00, 0x00, 0xc2, 0x01, 0x00, 0x00, + 0x05, 0x00, 0x04, 0x00, 0x04, 0x00, 0x00, 0x00, 0x6d, 0x61, 0x69, 0x6e, + 0x00, 0x00, 0x00, 0x00, 0x05, 0x00, 0x03, 0x00, 0x0a, 0x00, 0x00, 0x00, + 0x6d, 0x76, 0x70, 0x00, 0x05, 0x00, 0x05, 0x00, 0x16, 0x00, 0x00, 0x00, + 0x76, 0x65, 0x72, 0x74, 0x43, 0x6f, 0x6f, 0x72, 0x64, 0x73, 0x00, 0x00, + 0x05, 0x00, 0x05, 0x00, 0x1f, 0x00, 0x00, 0x00, 0x76, 0x5f, 0x74, 0x65, + 0x78, 0x63, 0x6f, 0x6f, 0x72, 0x64, 0x00, 0x00, 0x05, 0x00, 0x05, 0x00, + 0x21, 0x00, 0x00, 0x00, 0x74, 0x65, 0x78, 0x43, 0x6f, 0x6f, 0x72, 0x64, + 0x42, 0x75, 0x66, 0x00, 0x06, 0x00, 0x06, 0x00, 0x21, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x74, 0x65, 0x78, 0x43, 0x6f, 0x6f, 0x72, 0x64, + 0x73, 0x00, 0x00, 0x00, 0x05, 0x00, 0x06, 0x00, 0x23, 0x00, 0x00, 0x00, + 0x74, 0x65, 0x78, 0x43, 0x6f, 0x6f, 0x72, 0x64, 0x55, 0x6e, 0x69, 0x66, + 0x6f, 0x72, 0x6d, 0x00, 0x05, 0x00, 0x06, 0x00, 0x27, 0x00, 0x00, 0x00, + 0x67, 0x6c, 0x5f, 0x56, 0x65, 0x72, 0x74, 0x65, 0x78, 0x49, 0x6e, 0x64, + 0x65, 0x78, 0x00, 0x00, 0x05, 0x00, 0x06, 0x00, 0x2c, 0x00, 0x00, 0x00, + 0x67, 0x6c, 0x5f, 0x50, 0x65, 0x72, 0x56, 0x65, 0x72, 0x74, 0x65, 0x78, + 0x00, 0x00, 0x00, 0x00, 0x06, 0x00, 0x06, 0x00, 0x2c, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x67, 0x6c, 0x5f, 0x50, 0x6f, 0x73, 0x69, 0x74, + 0x69, 0x6f, 0x6e, 0x00, 0x05, 0x00, 0x03, 0x00, 0x2e, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x47, 0x00, 0x04, 0x00, 0x1f, 0x00, 0x00, 0x00, + 0x1e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x47, 0x00, 0x04, 0x00, + 0x20, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, + 0x48, 0x00, 0x05, 0x00, 0x21, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x23, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x47, 0x00, 0x03, 0x00, + 0x21, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x47, 0x00, 0x04, 0x00, + 0x27, 0x00, 0x00, 0x00, 0x0b, 0x00, 0x00, 0x00, 0x2a, 0x00, 0x00, 0x00, + 0x48, 0x00, 0x05, 0x00, 0x2c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x0b, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x47, 0x00, 0x03, 0x00, + 0x2c, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x13, 0x00, 0x02, 0x00, + 0x02, 0x00, 0x00, 0x00, 0x21, 0x00, 0x03, 0x00, 0x03, 0x00, 0x00, 0x00, + 0x02, 0x00, 0x00, 0x00, 0x16, 0x00, 0x03, 0x00, 0x06, 0x00, 0x00, 0x00, + 0x20, 0x00, 0x00, 0x00, 0x17, 0x00, 0x04, 0x00, 0x07, 0x00, 0x00, 0x00, + 0x06, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x18, 0x00, 0x04, 0x00, + 0x08, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, + 0x20, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, + 0x08, 0x00, 0x00, 0x00, 0x3b, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, + 0x0a, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x2b, 0x00, 0x04, 0x00, + 0x06, 0x00, 0x00, 0x00, 0x0b, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x3f, + 0x2b, 0x00, 0x04, 0x00, 0x06, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x2c, 0x00, 0x07, 0x00, 0x07, 0x00, 0x00, 0x00, + 0x0d, 0x00, 0x00, 0x00, 0x0b, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00, + 0x0c, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x2c, 0x00, 0x07, 0x00, + 0x07, 0x00, 0x00, 0x00, 0x0e, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00, + 0x0b, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00, + 0x2c, 0x00, 0x07, 0x00, 0x07, 0x00, 0x00, 0x00, 0x0f, 0x00, 0x00, 0x00, + 0x0c, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x0b, 0x00, 0x00, 0x00, + 0x0c, 0x00, 0x00, 0x00, 0x2c, 0x00, 0x07, 0x00, 0x07, 0x00, 0x00, 0x00, + 0x10, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00, + 0x0c, 0x00, 0x00, 0x00, 0x0b, 0x00, 0x00, 0x00, 0x2c, 0x00, 0x07, 0x00, + 0x08, 0x00, 0x00, 0x00, 0x11, 0x00, 0x00, 0x00, 0x0d, 0x00, 0x00, 0x00, + 0x0e, 0x00, 0x00, 0x00, 0x0f, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, + 0x15, 0x00, 0x04, 0x00, 0x12, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x2b, 0x00, 0x04, 0x00, 0x12, 0x00, 0x00, 0x00, + 0x13, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x1c, 0x00, 0x04, 0x00, + 0x14, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, 0x13, 0x00, 0x00, 0x00, + 0x20, 0x00, 0x04, 0x00, 0x15, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, + 0x14, 0x00, 0x00, 0x00, 0x3b, 0x00, 0x04, 0x00, 0x15, 0x00, 0x00, 0x00, + 0x16, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x2b, 0x00, 0x04, 0x00, + 0x06, 0x00, 0x00, 0x00, 0x17, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0xbf, + 0x2c, 0x00, 0x07, 0x00, 0x07, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, + 0x17, 0x00, 0x00, 0x00, 0x17, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00, + 0x0b, 0x00, 0x00, 0x00, 0x2c, 0x00, 0x07, 0x00, 0x07, 0x00, 0x00, 0x00, + 0x19, 0x00, 0x00, 0x00, 0x0b, 0x00, 0x00, 0x00, 0x17, 0x00, 0x00, 0x00, + 0x0c, 0x00, 0x00, 0x00, 0x0b, 0x00, 0x00, 0x00, 0x2c, 0x00, 0x07, 0x00, + 0x07, 0x00, 0x00, 0x00, 0x1a, 0x00, 0x00, 0x00, 0x17, 0x00, 0x00, 0x00, + 0x0b, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x0b, 0x00, 0x00, 0x00, + 0x2c, 0x00, 0x07, 0x00, 0x07, 0x00, 0x00, 0x00, 0x1b, 0x00, 0x00, 0x00, + 0x0b, 0x00, 0x00, 0x00, 0x0b, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00, + 0x0b, 0x00, 0x00, 0x00, 0x2c, 0x00, 0x07, 0x00, 0x14, 0x00, 0x00, 0x00, + 0x1c, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0x19, 0x00, 0x00, 0x00, + 0x1a, 0x00, 0x00, 0x00, 0x1b, 0x00, 0x00, 0x00, 0x17, 0x00, 0x04, 0x00, + 0x1d, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, + 0x20, 0x00, 0x04, 0x00, 0x1e, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, + 0x1d, 0x00, 0x00, 0x00, 0x3b, 0x00, 0x04, 0x00, 0x1e, 0x00, 0x00, 0x00, + 0x1f, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x1c, 0x00, 0x04, 0x00, + 0x20, 0x00, 0x00, 0x00, 0x1d, 0x00, 0x00, 0x00, 0x13, 0x00, 0x00, 0x00, + 0x1e, 0x00, 0x03, 0x00, 0x21, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, + 0x20, 0x00, 0x04, 0x00, 0x22, 0x00, 0x00, 0x00, 0x09, 0x00, 0x00, 0x00, + 0x21, 0x00, 0x00, 0x00, 0x3b, 0x00, 0x04, 0x00, 0x22, 0x00, 0x00, 0x00, + 0x23, 0x00, 0x00, 0x00, 0x09, 0x00, 0x00, 0x00, 0x15, 0x00, 0x04, 0x00, + 0x24, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, + 0x2b, 0x00, 0x04, 0x00, 0x24, 0x00, 0x00, 0x00, 0x25, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x20, 0x00, 0x04, 0x00, 0x26, 0x00, 0x00, 0x00, + 0x01, 0x00, 0x00, 0x00, 0x24, 0x00, 0x00, 0x00, 0x3b, 0x00, 0x04, 0x00, + 0x26, 0x00, 0x00, 0x00, 0x27, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, + 0x20, 0x00, 0x04, 0x00, 0x29, 0x00, 0x00, 0x00, 0x09, 0x00, 0x00, 0x00, + 0x1d, 0x00, 0x00, 0x00, 0x1e, 0x00, 0x03, 0x00, 0x2c, 0x00, 0x00, 0x00, + 0x07, 0x00, 0x00, 0x00, 0x20, 0x00, 0x04, 0x00, 0x2d, 0x00, 0x00, 0x00, + 0x03, 0x00, 0x00, 0x00, 0x2c, 0x00, 0x00, 0x00, 0x3b, 0x00, 0x04, 0x00, + 0x2d, 0x00, 0x00, 0x00, 0x2e, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, + 0x20, 0x00, 0x04, 0x00, 0x31, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, + 0x07, 0x00, 0x00, 0x00, 0x20, 0x00, 0x04, 0x00, 0x35, 0x00, 0x00, 0x00, + 0x03, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, 0x36, 0x00, 0x05, 0x00, + 0x02, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x03, 0x00, 0x00, 0x00, 0xf8, 0x00, 0x02, 0x00, 0x05, 0x00, 0x00, 0x00, + 0x3e, 0x00, 0x03, 0x00, 0x0a, 0x00, 0x00, 0x00, 0x11, 0x00, 0x00, 0x00, + 0x3e, 0x00, 0x03, 0x00, 0x16, 0x00, 0x00, 0x00, 0x1c, 0x00, 0x00, 0x00, + 0x3d, 0x00, 0x04, 0x00, 0x24, 0x00, 0x00, 0x00, 0x28, 0x00, 0x00, 0x00, + 0x27, 0x00, 0x00, 0x00, 0x41, 0x00, 0x06, 0x00, 0x29, 0x00, 0x00, 0x00, + 0x2a, 0x00, 0x00, 0x00, 0x23, 0x00, 0x00, 0x00, 0x25, 0x00, 0x00, 0x00, + 0x28, 0x00, 0x00, 0x00, 0x3d, 0x00, 0x04, 0x00, 0x1d, 0x00, 0x00, 0x00, + 0x2b, 0x00, 0x00, 0x00, 0x2a, 0x00, 0x00, 0x00, 0x3e, 0x00, 0x03, 0x00, + 0x1f, 0x00, 0x00, 0x00, 0x2b, 0x00, 0x00, 0x00, 0x3d, 0x00, 0x04, 0x00, + 0x08, 0x00, 0x00, 0x00, 0x2f, 0x00, 0x00, 0x00, 0x0a, 0x00, 0x00, 0x00, + 0x3d, 0x00, 0x04, 0x00, 0x24, 0x00, 0x00, 0x00, 0x30, 0x00, 0x00, 0x00, + 0x27, 0x00, 0x00, 0x00, 0x41, 0x00, 0x05, 0x00, 0x31, 0x00, 0x00, 0x00, + 0x32, 0x00, 0x00, 0x00, 0x16, 0x00, 0x00, 0x00, 0x30, 0x00, 0x00, 0x00, + 0x3d, 0x00, 0x04, 0x00, 0x07, 0x00, 0x00, 0x00, 0x33, 0x00, 0x00, 0x00, + 0x32, 0x00, 0x00, 0x00, 0x91, 0x00, 0x05, 0x00, 0x07, 0x00, 0x00, 0x00, + 0x34, 0x00, 0x00, 0x00, 0x2f, 0x00, 0x00, 0x00, 0x33, 0x00, 0x00, 0x00, + 0x41, 0x00, 0x05, 0x00, 0x35, 0x00, 0x00, 0x00, 0x36, 0x00, 0x00, 0x00, + 0x2e, 0x00, 0x00, 0x00, 0x25, 0x00, 0x00, 0x00, 0x3e, 0x00, 0x03, 0x00, + 0x36, 0x00, 0x00, 0x00, 0x34, 0x00, 0x00, 0x00, 0xfd, 0x00, 0x01, 0x00, + 0x38, 0x00, 0x01, 0x00 +}; + +/* +#version 440 + +layout(location = 0) in vec2 v_texcoord; + +layout(location = 0) out vec4 fragColor; + +layout(binding = 1) uniform sampler2D tex; + +void main() +{ + fragColor = texture(tex, v_texcoord); +} +*/ + +static const uint8_t fragShaderCode[] +{ + 0x03, 0x02, 0x23, 0x07, 0x00, 0x00, 0x01, 0x00, 0x0a, 0x00, 0x08, 0x00, + 0x19, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x11, 0x00, 0x02, 0x00, + 0x01, 0x00, 0x00, 0x00, 0x0b, 0x00, 0x06, 0x00, 0x01, 0x00, 0x00, 0x00, + 0x47, 0x4c, 0x53, 0x4c, 0x2e, 0x73, 0x74, 0x64, 0x2e, 0x34, 0x35, 0x30, + 0x00, 0x00, 0x00, 0x00, 0x0e, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x01, 0x00, 0x00, 0x00, 0x0f, 0x00, 0x07, 0x00, 0x04, 0x00, 0x00, 0x00, + 0x04, 0x00, 0x00, 0x00, 0x6d, 0x61, 0x69, 0x6e, 0x00, 0x00, 0x00, 0x00, + 0x09, 0x00, 0x00, 0x00, 0x11, 0x00, 0x00, 0x00, 0x10, 0x00, 0x03, 0x00, + 0x04, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, 0x03, 0x00, 0x03, 0x00, + 0x02, 0x00, 0x00, 0x00, 0xb8, 0x01, 0x00, 0x00, 0x05, 0x00, 0x04, 0x00, + 0x04, 0x00, 0x00, 0x00, 0x6d, 0x61, 0x69, 0x6e, 0x00, 0x00, 0x00, 0x00, + 0x05, 0x00, 0x05, 0x00, 0x09, 0x00, 0x00, 0x00, 0x66, 0x72, 0x61, 0x67, + 0x43, 0x6f, 0x6c, 0x6f, 0x72, 0x00, 0x00, 0x00, 0x05, 0x00, 0x03, 0x00, + 0x0d, 0x00, 0x00, 0x00, 0x74, 0x65, 0x78, 0x00, 0x05, 0x00, 0x05, 0x00, + 0x11, 0x00, 0x00, 0x00, 0x76, 0x5f, 0x74, 0x65, 0x78, 0x63, 0x6f, 0x6f, + 0x72, 0x64, 0x00, 0x00, 0x47, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, + 0x1e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x47, 0x00, 0x04, 0x00, + 0x0d, 0x00, 0x00, 0x00, 0x22, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x47, 0x00, 0x04, 0x00, 0x0d, 0x00, 0x00, 0x00, 0x21, 0x00, 0x00, 0x00, + 0x01, 0x00, 0x00, 0x00, 0x47, 0x00, 0x04, 0x00, 0x11, 0x00, 0x00, 0x00, + 0x1e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x13, 0x00, 0x02, 0x00, + 0x02, 0x00, 0x00, 0x00, 0x21, 0x00, 0x03, 0x00, 0x03, 0x00, 0x00, 0x00, + 0x02, 0x00, 0x00, 0x00, 0x16, 0x00, 0x03, 0x00, 0x06, 0x00, 0x00, 0x00, + 0x20, 0x00, 0x00, 0x00, 0x17, 0x00, 0x04, 0x00, 0x07, 0x00, 0x00, 0x00, + 0x06, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x20, 0x00, 0x04, 0x00, + 0x08, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, + 0x3b, 0x00, 0x04, 0x00, 0x08, 0x00, 0x00, 0x00, 0x09, 0x00, 0x00, 0x00, + 0x03, 0x00, 0x00, 0x00, 0x19, 0x00, 0x09, 0x00, 0x0a, 0x00, 0x00, 0x00, + 0x06, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x1b, 0x00, 0x03, 0x00, 0x0b, 0x00, 0x00, 0x00, + 0x0a, 0x00, 0x00, 0x00, 0x20, 0x00, 0x04, 0x00, 0x0c, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x0b, 0x00, 0x00, 0x00, 0x3b, 0x00, 0x04, 0x00, + 0x0c, 0x00, 0x00, 0x00, 0x0d, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x17, 0x00, 0x04, 0x00, 0x0f, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, + 0x02, 0x00, 0x00, 0x00, 0x20, 0x00, 0x04, 0x00, 0x10, 0x00, 0x00, 0x00, + 0x01, 0x00, 0x00, 0x00, 0x0f, 0x00, 0x00, 0x00, 0x3b, 0x00, 0x04, 0x00, + 0x10, 0x00, 0x00, 0x00, 0x11, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, + 0x2b, 0x00, 0x04, 0x00, 0x06, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x80, 0x3f, 0x15, 0x00, 0x04, 0x00, 0x15, 0x00, 0x00, 0x00, + 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x2b, 0x00, 0x04, 0x00, + 0x15, 0x00, 0x00, 0x00, 0x16, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, + 0x20, 0x00, 0x04, 0x00, 0x17, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, + 0x06, 0x00, 0x00, 0x00, 0x36, 0x00, 0x05, 0x00, 0x02, 0x00, 0x00, 0x00, + 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, + 0xf8, 0x00, 0x02, 0x00, 0x05, 0x00, 0x00, 0x00, 0x3d, 0x00, 0x04, 0x00, + 0x0b, 0x00, 0x00, 0x00, 0x0e, 0x00, 0x00, 0x00, 0x0d, 0x00, 0x00, 0x00, + 0x3d, 0x00, 0x04, 0x00, 0x0f, 0x00, 0x00, 0x00, 0x12, 0x00, 0x00, 0x00, + 0x11, 0x00, 0x00, 0x00, 0x57, 0x00, 0x05, 0x00, 0x07, 0x00, 0x00, 0x00, + 0x13, 0x00, 0x00, 0x00, 0x0e, 0x00, 0x00, 0x00, 0x12, 0x00, 0x00, 0x00, + 0x3e, 0x00, 0x03, 0x00, 0x09, 0x00, 0x00, 0x00, 0x13, 0x00, 0x00, 0x00, + 0x41, 0x00, 0x05, 0x00, 0x17, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, + 0x09, 0x00, 0x00, 0x00, 0x16, 0x00, 0x00, 0x00, 0x3e, 0x00, 0x03, 0x00, + 0x18, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, 0xfd, 0x00, 0x01, 0x00, + 0x38, 0x00, 0x01, 0x00 +}; + +class VulkanRendererEmu : public QVulkanWindowRenderer +{ + VulkanWindowRenderer* m_window{nullptr}; + QVulkanDeviceFunctions* m_devFuncs{nullptr}; + VmaAllocator allocator{nullptr}; + VmaAllocation allocation{nullptr}; + VkImage image{nullptr}; + VkImageView imageView{nullptr}; + VkPipeline pipeline{nullptr}; + VkPipelineLayout pipelineLayout{nullptr}; + VkDescriptorSetLayout descLayout{nullptr}; + VkDescriptorPool descPool{nullptr}; + VkDescriptorSet descSet{nullptr}; + VkSampler sampler{nullptr}, nearestSampler{nullptr}; + bool imageLayoutTransitioned{false}; + int cur_video_filter_method = -1; +private: + void updateOptions() { + VkResult res; + if (cur_video_filter_method == video_filter_method) return; + if (!descPool) { + VkDescriptorPoolSize descSize{}; + descSize.type = VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER; + descSize.descriptorCount = 2; + + VkDescriptorPoolCreateInfo poolInfo{}; + poolInfo.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_POOL_CREATE_INFO; + poolInfo.poolSizeCount = 1; + poolInfo.pPoolSizes = &descSize; + poolInfo.maxSets = 2; + + if ((res = m_devFuncs->vkCreateDescriptorPool(m_window->device(), &poolInfo, nullptr, &descPool)) != VK_SUCCESS) { + QMessageBox::critical(main_window, "86Box", "Could not create descriptor pool. Switch to another renderer. " + Vulkan_GetResultString(res)); + return; + } + + VkDescriptorSetAllocateInfo allocInfo{}; + allocInfo.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_ALLOCATE_INFO; + allocInfo.descriptorPool = descPool; + allocInfo.descriptorSetCount = 1; + allocInfo.pSetLayouts = &descLayout; + + if ((res = m_devFuncs->vkAllocateDescriptorSets(m_window->device(), &allocInfo, &descSet)) != VK_SUCCESS) { + QMessageBox::critical(main_window, "86Box", "Could not create descriptor set. Switch to another renderer. " + Vulkan_GetResultString(res)); + return; + }} + VkDescriptorImageInfo imageDescInfo{}; + imageDescInfo.imageLayout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL; + imageDescInfo.imageView = imageView; + imageDescInfo.sampler = video_filter_method == 0 ? nearestSampler : sampler; + + VkWriteDescriptorSet descWrite{}; + descWrite.sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET; + descWrite.dstSet = descSet; + descWrite.dstBinding = 1; + descWrite.dstArrayElement = 0; + descWrite.descriptorType = VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER; + descWrite.descriptorCount = 1; + descWrite.pImageInfo = &imageDescInfo; + + m_devFuncs->vkUpdateDescriptorSets(m_window->device(), 1, &descWrite, 0, nullptr); + cur_video_filter_method = video_filter_method; + } +public: + void* mappedPtr = nullptr; + uint32_t imagePitch{2048 * 4}; + VulkanRendererEmu(VulkanWindowRenderer *w) : m_window(w), m_devFuncs(nullptr) { } + + void initResources() override + { + VmaAllocatorCreateInfo info{}; + info.instance = m_window->vulkanInstance()->vkInstance(); + info.device = m_window->device(); + info.physicalDevice = m_window->physicalDevice(); + VmaVulkanFunctions funcs{}; + funcs.vkGetInstanceProcAddr = (PFN_vkGetInstanceProcAddr)m_window->vulkanInstance()->getInstanceProcAddr("vkGetInstanceProcAddr"); + funcs.vkGetDeviceProcAddr = (PFN_vkGetDeviceProcAddr)m_window->vulkanInstance()->getInstanceProcAddr("vkGetDeviceProcAddr"); + info.pVulkanFunctions = &funcs; + if (vmaCreateAllocator(&info, &allocator) != VK_SUCCESS) { + QMessageBox::critical(main_window, "86Box", "Could not create Vulkan allocator. Switch to another renderer"); + return; + } + + m_devFuncs = m_window->vulkanInstance()->deviceFunctions(m_window->device()); + + VkResult res; + VkImageCreateInfo imageInfo{}; + imageInfo.sType = VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO; + imageInfo.imageType = VK_IMAGE_TYPE_2D; + imageInfo.format = VK_FORMAT_B8G8R8A8_UNORM; + imageInfo.extent.width = imageInfo.extent.height = 2048; + imageInfo.extent.depth = imageInfo.arrayLayers = imageInfo.mipLevels = 1; + imageInfo.tiling = VK_IMAGE_TILING_LINEAR; + imageInfo.usage = VK_IMAGE_USAGE_TRANSFER_SRC_BIT | VK_IMAGE_USAGE_TRANSFER_DST_BIT | VK_IMAGE_USAGE_SAMPLED_BIT; + imageInfo.samples = VK_SAMPLE_COUNT_1_BIT; + imageInfo.sharingMode = VK_SHARING_MODE_EXCLUSIVE; + imageInfo.initialLayout = VK_IMAGE_LAYOUT_PREINITIALIZED; + + VmaAllocationInfo allocatedInfo{}; + VmaAllocationCreateInfo allocInfo{}; + allocInfo.pUserData = allocInfo.pool = nullptr; + allocInfo.requiredFlags = allocInfo.preferredFlags = 0; + allocInfo.usage = VmaMemoryUsage::VMA_MEMORY_USAGE_AUTO; + allocInfo.flags = VMA_ALLOCATION_CREATE_HOST_ACCESS_SEQUENTIAL_WRITE_BIT | + VMA_ALLOCATION_CREATE_MAPPED_BIT; + + if ((res = vmaCreateImage(allocator, &imageInfo, &allocInfo, &image, &allocation, &allocatedInfo)) != VK_SUCCESS) { + QMessageBox::critical(main_window, "86Box", "Could not create Vulkan image. Switch to another renderer. " + Vulkan_GetResultString(res)); + return; + }; + + VkImageViewCreateInfo imageViewInfo{}; + imageViewInfo.viewType = VK_IMAGE_VIEW_TYPE_2D; + imageViewInfo.sType = VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO; + imageViewInfo.format = VK_FORMAT_B8G8R8A8_UNORM; + imageViewInfo.image = image; + imageViewInfo.subresourceRange.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT; + imageViewInfo.subresourceRange.baseMipLevel = 0; + imageViewInfo.subresourceRange.levelCount = 1; + imageViewInfo.subresourceRange.baseArrayLayer = 0; + imageViewInfo.subresourceRange.layerCount = 1; + imageViewInfo.components.r = VK_COMPONENT_SWIZZLE_R; + imageViewInfo.components.g = VK_COMPONENT_SWIZZLE_G; + imageViewInfo.components.b = VK_COMPONENT_SWIZZLE_B; + imageViewInfo.components.a = VK_COMPONENT_SWIZZLE_A; + + if ((res = m_devFuncs->vkCreateImageView(m_window->device(), &imageViewInfo, nullptr, &imageView)) != VK_SUCCESS) { + QMessageBox::critical(main_window, "86Box", "Could not create Vulkan image view. Switch to another renderer. " + Vulkan_GetResultString(res)); + return; + } + + // Begin Pipeline creation. + { + VkPipelineVertexInputStateCreateInfo vertexInputInfo{}; + vertexInputInfo.sType = VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO; + vertexInputInfo.vertexBindingDescriptionCount = 0; + vertexInputInfo.pVertexBindingDescriptions = nullptr; + vertexInputInfo.vertexAttributeDescriptionCount = 0; + vertexInputInfo.pVertexAttributeDescriptions = nullptr; + + VkPipelineInputAssemblyStateCreateInfo inputAssembly{}; + inputAssembly.sType = VK_STRUCTURE_TYPE_PIPELINE_INPUT_ASSEMBLY_STATE_CREATE_INFO; + inputAssembly.topology = VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP; + inputAssembly.primitiveRestartEnable = VK_FALSE; + + VkRect2D scissor{}; + scissor.offset = {0, 0}; + scissor.extent = {2048, 2048}; + + VkViewport viewport{}; + viewport.x = m_window->destination.x(); + viewport.y = m_window->destination.y(); + viewport.width = (float)m_window->destination.width(); + viewport.height = (float)m_window->destination.height(); + viewport.minDepth = 0.0f; + viewport.maxDepth = 1.0f; + + VkPipelineViewportStateCreateInfo viewportState{}; + viewportState.sType = VK_STRUCTURE_TYPE_PIPELINE_VIEWPORT_STATE_CREATE_INFO; + viewportState.viewportCount = 1; + viewportState.pViewports = &viewport; + viewportState.scissorCount = 1; + viewportState.pScissors = &scissor; + + VkPipelineRasterizationStateCreateInfo rasterizer{}; + rasterizer.sType = VK_STRUCTURE_TYPE_PIPELINE_RASTERIZATION_STATE_CREATE_INFO; + rasterizer.depthClampEnable = VK_FALSE; + rasterizer.rasterizerDiscardEnable = VK_FALSE; + rasterizer.polygonMode = VK_POLYGON_MODE_FILL; + rasterizer.lineWidth = 1.0f; + rasterizer.cullMode = VK_CULL_MODE_BACK_BIT; + rasterizer.frontFace = VK_FRONT_FACE_CLOCKWISE; + rasterizer.depthBiasEnable = VK_FALSE; + rasterizer.depthBiasConstantFactor = 0.0f; + rasterizer.depthBiasClamp = 0.0f; + rasterizer.depthBiasSlopeFactor = 0.0f; + + VkPipelineMultisampleStateCreateInfo multisampling{}; + multisampling.sType = VK_STRUCTURE_TYPE_PIPELINE_MULTISAMPLE_STATE_CREATE_INFO; + multisampling.sampleShadingEnable = VK_FALSE; + multisampling.rasterizationSamples = VK_SAMPLE_COUNT_1_BIT; + multisampling.minSampleShading = 1.0f; + multisampling.pSampleMask = nullptr; + multisampling.alphaToCoverageEnable = VK_FALSE; + multisampling.alphaToOneEnable = VK_FALSE; + + VkPipelineColorBlendAttachmentState colorBlendAttachment{}; + colorBlendAttachment.colorWriteMask = VK_COLOR_COMPONENT_R_BIT | VK_COLOR_COMPONENT_G_BIT | VK_COLOR_COMPONENT_B_BIT | VK_COLOR_COMPONENT_A_BIT; + colorBlendAttachment.blendEnable = VK_TRUE; + colorBlendAttachment.srcColorBlendFactor = VK_BLEND_FACTOR_ONE; + colorBlendAttachment.dstColorBlendFactor = VK_BLEND_FACTOR_ONE_MINUS_SRC_ALPHA; + colorBlendAttachment.colorBlendOp = VK_BLEND_OP_ADD; + colorBlendAttachment.srcAlphaBlendFactor = VK_BLEND_FACTOR_ONE; + colorBlendAttachment.dstAlphaBlendFactor = VK_BLEND_FACTOR_ONE_MINUS_SRC_ALPHA; + colorBlendAttachment.alphaBlendOp = VK_BLEND_OP_ADD; + + VkPipelineColorBlendStateCreateInfo colorBlending{}; + colorBlending.sType = VK_STRUCTURE_TYPE_PIPELINE_COLOR_BLEND_STATE_CREATE_INFO; + colorBlending.logicOpEnable = VK_FALSE; + colorBlending.logicOp = VK_LOGIC_OP_COPY; + colorBlending.attachmentCount = 1; + colorBlending.pAttachments = &colorBlendAttachment; + colorBlending.blendConstants[0] = 0.0f; + colorBlending.blendConstants[1] = 0.0f; + colorBlending.blendConstants[2] = 0.0f; + colorBlending.blendConstants[3] = 0.0f; + + VkDynamicState dynState = VK_DYNAMIC_STATE_VIEWPORT; + VkPipelineDynamicStateCreateInfo dynamicState{}; + dynamicState.sType = VK_STRUCTURE_TYPE_PIPELINE_DYNAMIC_STATE_CREATE_INFO; + dynamicState.dynamicStateCount = 1; + dynamicState.pDynamicStates = &dynState; + + VkPushConstantRange range{}; + range.offset = 0; + range.size = sizeof(float) * 8; + range.stageFlags = VK_SHADER_STAGE_VERTEX_BIT; + + // Sampler binding start. + VkDescriptorSetLayoutBinding samplerLayoutBinding{}; + samplerLayoutBinding.binding = 1; + samplerLayoutBinding.descriptorCount = 1; + samplerLayoutBinding.descriptorType = VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER; + samplerLayoutBinding.pImmutableSamplers = nullptr; + samplerLayoutBinding.stageFlags = VK_SHADER_STAGE_FRAGMENT_BIT; + + VkDescriptorSetLayoutCreateInfo layoutInfo{}; + layoutInfo.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_LAYOUT_CREATE_INFO; + layoutInfo.bindingCount = 1; + layoutInfo.pBindings = &samplerLayoutBinding; + + if ((res = m_devFuncs->vkCreateDescriptorSetLayout(m_window->device(), &layoutInfo, nullptr, &descLayout))) { + QMessageBox::critical(main_window, "86Box", "Could not create descriptor set layout. Switch to another renderer. " + Vulkan_GetResultString(res)); + return; + } + // Sampler binding end. + + VkPipelineLayoutCreateInfo pipelineLayoutInfo{}; + pipelineLayoutInfo.sType = VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO; + pipelineLayoutInfo.setLayoutCount = 1; + pipelineLayoutInfo.pSetLayouts = &descLayout; + pipelineLayoutInfo.pushConstantRangeCount = 1; + pipelineLayoutInfo.pPushConstantRanges = ⦥ + + if ((res = m_devFuncs->vkCreatePipelineLayout(m_window->device(), &pipelineLayoutInfo, nullptr, &pipelineLayout)) != VK_SUCCESS) { + QMessageBox::critical(main_window, "86Box", "Could not create pipeline layout. Switch to another renderer. " + Vulkan_GetResultString(res)); + return; + } + + // Shader loading start. + VkShaderModuleCreateInfo createInfo{}; + createInfo.sType = VK_STRUCTURE_TYPE_SHADER_MODULE_CREATE_INFO; + createInfo.codeSize = sizeof(vertShaderCode); + createInfo.pCode = (uint32_t*)vertShaderCode; + VkShaderModule vertModule{nullptr}, fragModule{nullptr}; + if ((res = m_devFuncs->vkCreateShaderModule(m_window->device(), &createInfo, nullptr, &vertModule)) != VK_SUCCESS) { + QMessageBox::critical(main_window, "86Box", "Could not create vertex shader. Switch to another renderer. " + Vulkan_GetResultString(res)); + return; + } + + createInfo.codeSize = sizeof(fragShaderCode); + createInfo.pCode = (uint32_t*)fragShaderCode; + if ((res = m_devFuncs->vkCreateShaderModule(m_window->device(), &createInfo, nullptr, &fragModule)) != VK_SUCCESS) { + QMessageBox::critical(main_window, "86Box", "Could not create fragment shader. Switch to another renderer. " + Vulkan_GetResultString(res)); + return; + } + + VkPipelineShaderStageCreateInfo vertShaderStageInfo{}; + vertShaderStageInfo.sType = VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO; + vertShaderStageInfo.stage = VK_SHADER_STAGE_VERTEX_BIT; + vertShaderStageInfo.module = vertModule; + vertShaderStageInfo.pName = "main"; + + VkPipelineShaderStageCreateInfo fragShaderStageInfo{vertShaderStageInfo}; + fragShaderStageInfo.stage = VK_SHADER_STAGE_FRAGMENT_BIT; + fragShaderStageInfo.module = fragModule; + + VkPipelineShaderStageCreateInfo shaderStages[] = {vertShaderStageInfo, fragShaderStageInfo}; + // Shader loading end. + + VkPipelineDepthStencilStateCreateInfo depthInfo{}; + depthInfo.sType = VK_STRUCTURE_TYPE_PIPELINE_DEPTH_STENCIL_STATE_CREATE_INFO; + depthInfo.pNext = nullptr; + depthInfo.depthTestEnable = VK_TRUE; + depthInfo.depthWriteEnable = VK_TRUE; + depthInfo.depthBoundsTestEnable = VK_FALSE; + depthInfo.depthCompareOp = VK_COMPARE_OP_LESS_OR_EQUAL; + depthInfo.stencilTestEnable = VK_FALSE; + depthInfo.maxDepthBounds = 1.0f; + + VkGraphicsPipelineCreateInfo pipelineInfo{}; + pipelineInfo.sType = VK_STRUCTURE_TYPE_GRAPHICS_PIPELINE_CREATE_INFO; + pipelineInfo.stageCount = 2; + pipelineInfo.pStages = shaderStages; + pipelineInfo.pVertexInputState = &vertexInputInfo; + pipelineInfo.pInputAssemblyState = &inputAssembly; + pipelineInfo.pViewportState = &viewportState; + pipelineInfo.pRasterizationState = &rasterizer; + pipelineInfo.pMultisampleState = &multisampling; + pipelineInfo.pDepthStencilState = &depthInfo; + pipelineInfo.pColorBlendState = &colorBlending; + pipelineInfo.pDynamicState = &dynamicState; + pipelineInfo.layout = pipelineLayout; + pipelineInfo.renderPass = m_window->defaultRenderPass(); + pipelineInfo.subpass = 0; + + if ((res = m_devFuncs->vkCreateGraphicsPipelines(m_window->device(), VK_NULL_HANDLE, 1, &pipelineInfo, nullptr, &pipeline)) != VK_SUCCESS) { + m_devFuncs->vkDestroyShaderModule(m_window->device(), vertModule, nullptr); + m_devFuncs->vkDestroyShaderModule(m_window->device(), fragModule, nullptr); + QMessageBox::critical(main_window, "86Box", "Could not create graphics pipeline. Switch to another renderer. " + Vulkan_GetResultString(res)); + return; + } + m_devFuncs->vkDestroyShaderModule(m_window->device(), vertModule, nullptr); + m_devFuncs->vkDestroyShaderModule(m_window->device(), fragModule, nullptr); + } + + VkSamplerCreateInfo samplerInfo{}; + samplerInfo.sType = VK_STRUCTURE_TYPE_SAMPLER_CREATE_INFO; + samplerInfo.magFilter = VK_FILTER_LINEAR; + samplerInfo.minFilter = VK_FILTER_LINEAR; + samplerInfo.addressModeU = VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE; + samplerInfo.addressModeV = VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE; + samplerInfo.addressModeW = VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE; + samplerInfo.anisotropyEnable = VK_FALSE; + samplerInfo.unnormalizedCoordinates = VK_FALSE; + samplerInfo.compareEnable = VK_FALSE; + samplerInfo.compareOp = VK_COMPARE_OP_ALWAYS; + samplerInfo.mipmapMode = VK_SAMPLER_MIPMAP_MODE_LINEAR; + samplerInfo.mipLodBias = 0.0f; + samplerInfo.minLod = 0.0f; + samplerInfo.maxLod = 0.0; + + if ((res = m_devFuncs->vkCreateSampler(m_window->device(), &samplerInfo, nullptr, &sampler)) != VK_SUCCESS) { + QMessageBox::critical(main_window, "86Box", "Could not create linear image sampler. Switch to another renderer. " + Vulkan_GetResultString(res)); + return; + } + + samplerInfo.magFilter = samplerInfo.minFilter = VK_FILTER_NEAREST; + samplerInfo.mipmapMode = VK_SAMPLER_MIPMAP_MODE_NEAREST; + + if ((res = m_devFuncs->vkCreateSampler(m_window->device(), &samplerInfo, nullptr, &nearestSampler)) != VK_SUCCESS) { + QMessageBox::critical(main_window, "86Box", "Could not create nearest image sampler. Switch to another renderer. " + Vulkan_GetResultString(res)); + return; + } + + updateOptions(); + + VkImageSubresource resource{}; + resource.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT; + resource.arrayLayer = 0; + resource.mipLevel = 0; + VkSubresourceLayout layout{}; + m_devFuncs->vkGetImageSubresourceLayout(m_window->device(), image, &resource, &layout); + + imagePitch = layout.rowPitch; + mappedPtr = (uint8_t*)allocatedInfo.pMappedData + layout.offset; + emit m_window->rendererInitialized(); + } + + void releaseResources() override + { + if (pipeline) m_devFuncs->vkDestroyPipeline(m_window->device(), pipeline, nullptr); + if (pipelineLayout) m_devFuncs->vkDestroyPipelineLayout(m_window->device(), pipelineLayout, nullptr); + if (descSet) m_devFuncs->vkDestroyDescriptorPool(m_window->device(), descPool, nullptr); + if (descLayout) m_devFuncs->vkDestroyDescriptorSetLayout(m_window->device(), descLayout, nullptr); + if (imageView) m_devFuncs->vkDestroyImageView(m_window->device(), imageView, nullptr); + if (image) vmaDestroyImage(allocator, image, allocation); + if (sampler) m_devFuncs->vkDestroySampler(m_window->device(), sampler, nullptr); + if (nearestSampler) m_devFuncs->vkDestroySampler(m_window->device(), nearestSampler, nullptr); + image = nullptr; + pipeline = nullptr; + pipelineLayout = nullptr; + imageView = nullptr; + descLayout = nullptr; + descPool = nullptr; + descSet = nullptr; + sampler = nullptr; + vmaDestroyAllocator(allocator); + allocator = nullptr; + } + + QString Vulkan_GetResultString(VkResult result) + { + switch ((int)result) { + case VK_SUCCESS: + return "VK_SUCCESS"; + case VK_NOT_READY: + return "VK_NOT_READY"; + case VK_TIMEOUT: + return "VK_TIMEOUT"; + case VK_EVENT_SET: + return "VK_EVENT_SET"; + case VK_EVENT_RESET: + return "VK_EVENT_RESET"; + case VK_INCOMPLETE: + return "VK_INCOMPLETE"; + case VK_ERROR_OUT_OF_HOST_MEMORY: + return "VK_ERROR_OUT_OF_HOST_MEMORY"; + case VK_ERROR_OUT_OF_DEVICE_MEMORY: + return "VK_ERROR_OUT_OF_DEVICE_MEMORY"; + case VK_ERROR_INITIALIZATION_FAILED: + return "VK_ERROR_INITIALIZATION_FAILED"; + case VK_ERROR_DEVICE_LOST: + return "VK_ERROR_DEVICE_LOST"; + case VK_ERROR_MEMORY_MAP_FAILED: + return "VK_ERROR_MEMORY_MAP_FAILED"; + case VK_ERROR_LAYER_NOT_PRESENT: + return "VK_ERROR_LAYER_NOT_PRESENT"; + case VK_ERROR_EXTENSION_NOT_PRESENT: + return "VK_ERROR_EXTENSION_NOT_PRESENT"; + case VK_ERROR_FEATURE_NOT_PRESENT: + return "VK_ERROR_FEATURE_NOT_PRESENT"; + case VK_ERROR_INCOMPATIBLE_DRIVER: + return "VK_ERROR_INCOMPATIBLE_DRIVER"; + case VK_ERROR_TOO_MANY_OBJECTS: + return "VK_ERROR_TOO_MANY_OBJECTS"; + case VK_ERROR_FORMAT_NOT_SUPPORTED: + return "VK_ERROR_FORMAT_NOT_SUPPORTED"; + case VK_ERROR_FRAGMENTED_POOL: + return "VK_ERROR_FRAGMENTED_POOL"; + case VK_ERROR_UNKNOWN: + return "VK_ERROR_UNKNOWN"; + case VK_ERROR_OUT_OF_POOL_MEMORY: + return "VK_ERROR_OUT_OF_POOL_MEMORY"; + case VK_ERROR_INVALID_EXTERNAL_HANDLE: + return "VK_ERROR_INVALID_EXTERNAL_HANDLE"; + case VK_ERROR_FRAGMENTATION: + return "VK_ERROR_FRAGMENTATION"; + case VK_ERROR_INVALID_OPAQUE_CAPTURE_ADDRESS: + return "VK_ERROR_INVALID_OPAQUE_CAPTURE_ADDRESS"; + case VK_ERROR_SURFACE_LOST_KHR: + return "VK_ERROR_SURFACE_LOST_KHR"; + case VK_ERROR_NATIVE_WINDOW_IN_USE_KHR: + return "VK_ERROR_NATIVE_WINDOW_IN_USE_KHR"; + case VK_SUBOPTIMAL_KHR: + return "VK_SUBOPTIMAL_KHR"; + case VK_ERROR_OUT_OF_DATE_KHR: + return "VK_ERROR_OUT_OF_DATE_KHR"; + case VK_ERROR_INCOMPATIBLE_DISPLAY_KHR: + return "VK_ERROR_INCOMPATIBLE_DISPLAY_KHR"; + case VK_ERROR_VALIDATION_FAILED_EXT: + return "VK_ERROR_VALIDATION_FAILED_EXT"; + case VK_ERROR_INVALID_SHADER_NV: + return "VK_ERROR_INVALID_SHADER_NV"; +# if VK_HEADER_VERSION >= 135 && VK_HEADER_VERSION < 162 + case VK_ERROR_INCOMPATIBLE_VERSION_KHR: + return "VK_ERROR_INCOMPATIBLE_VERSION_KHR"; +# endif + case VK_ERROR_INVALID_DRM_FORMAT_MODIFIER_PLANE_LAYOUT_EXT: + return "VK_ERROR_INVALID_DRM_FORMAT_MODIFIER_PLANE_LAYOUT_EXT"; + case VK_ERROR_NOT_PERMITTED_EXT: + return "VK_ERROR_NOT_PERMITTED_EXT"; + case VK_ERROR_FULL_SCREEN_EXCLUSIVE_MODE_LOST_EXT: + return "VK_ERROR_FULL_SCREEN_EXCLUSIVE_MODE_LOST_EXT"; + case VK_THREAD_IDLE_KHR: + return "VK_THREAD_IDLE_KHR"; + case VK_THREAD_DONE_KHR: + return "VK_THREAD_DONE_KHR"; + case VK_OPERATION_DEFERRED_KHR: + return "VK_OPERATION_DEFERRED_KHR"; + case VK_OPERATION_NOT_DEFERRED_KHR: + return "VK_OPERATION_NOT_DEFERRED_KHR"; + case VK_PIPELINE_COMPILE_REQUIRED_EXT: + return "VK_PIPELINE_COMPILE_REQUIRED_EXT"; + default: + break; + } + if (result < 0) { + return "VK_ERROR_"; + } + return "VK_"; + } + + void startNextFrame() override + { + m_devFuncs->vkDeviceWaitIdle(m_window->device()); + VkClearValue values[2]; + auto cmdBufs = m_window->currentCommandBuffer(); + memset(values, 0, sizeof(values)); + values[0].depthStencil = { 1, 0 }; + values[1].depthStencil = { 1, 0 }; + VkRenderPassBeginInfo info{}; + VkSubpassDependency deps{}; + info.pClearValues = values; + info.sType = VK_STRUCTURE_TYPE_RENDER_PASS_BEGIN_INFO; + info.framebuffer = m_window->currentFramebuffer(); + info.renderArea = VkRect2D{{0, 0}, {(uint32_t)m_window->swapChainImageSize().width(), (uint32_t)m_window->swapChainImageSize().height()}}; + info.clearValueCount = 2; + info.renderPass = m_window->defaultRenderPass(); + + updateOptions(); + if (!imageLayoutTransitioned) { + VkPipelineStageFlags srcflags = VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT | VK_PIPELINE_STAGE_HOST_BIT, dstflags = VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT; + + VkImageMemoryBarrier barrier{}; + barrier.sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER; + barrier.image = image; + barrier.oldLayout = VK_IMAGE_LAYOUT_PREINITIALIZED; + barrier.newLayout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL; + barrier.srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED; + barrier.dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED; + barrier.subresourceRange.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT; + barrier.subresourceRange.baseMipLevel = 0; + barrier.subresourceRange.levelCount = 1; + barrier.subresourceRange.baseArrayLayer = 0; + barrier.subresourceRange.layerCount = 1; + barrier.srcAccessMask = VK_ACCESS_HOST_WRITE_BIT; + barrier.dstAccessMask = VK_ACCESS_SHADER_READ_BIT; + + m_devFuncs->vkCmdPipelineBarrier(cmdBufs, srcflags, dstflags, 0, 0, nullptr, 0, nullptr, 1, &barrier); + imageLayoutTransitioned = true; + } + vmaFlushAllocation(allocator, allocation, 0, VK_WHOLE_SIZE); + VkViewport viewport{}; + viewport.x = m_window->destination.x(); + viewport.y = m_window->destination.y(); + viewport.width = (float)m_window->destination.width(); + viewport.height = (float)m_window->destination.height(); + viewport.minDepth = 0.0f; + viewport.maxDepth = 1.0f; + m_devFuncs->vkCmdSetViewport(cmdBufs, 0, 1, &viewport); + m_devFuncs->vkCmdBeginRenderPass(m_window->currentCommandBuffer(), &info, VK_SUBPASS_CONTENTS_INLINE); + m_devFuncs->vkCmdBindPipeline(cmdBufs, VkPipelineBindPoint::VK_PIPELINE_BIND_POINT_GRAPHICS, pipeline); + m_devFuncs->vkCmdBindDescriptorSets(cmdBufs, VK_PIPELINE_BIND_POINT_GRAPHICS, pipelineLayout, 0, 1, &descSet, 0, nullptr); + std::array texcoords; + auto source = m_window->source; + texcoords[0] = (QVector2D((float)source.x() / 2048.f, (float)(source.y()) / 2048.f)); + texcoords[2] = (QVector2D((float)source.x() / 2048.f, (float)(source.y() + source.height()) / 2048.f)); + texcoords[1] = (QVector2D((float)(source.x() + source.width()) / 2048.f, (float)(source.y()) / 2048.f)); + texcoords[3] = (QVector2D((float)(source.x() + source.width()) / 2048.f, (float)(source.y() + source.height()) / 2048.f)); + m_devFuncs->vkCmdPushConstants(cmdBufs, pipelineLayout, VK_SHADER_STAGE_VERTEX_BIT, 0, sizeof(QVector2D) * 4, texcoords.data()); + m_devFuncs->vkCmdDraw(cmdBufs, 4, 1, 0, 0); + m_devFuncs->vkCmdEndRenderPass(cmdBufs); + + m_window->frameReady(); + m_devFuncs->vkDeviceWaitIdle(m_window->device()); + } +}; +# endif + +VulkanWindowRenderer::VulkanWindowRenderer(QWidget *parent) + : QVulkanWindow(parent->windowHandle()) +{ + parentWidget = parent; + instance.setApiVersion(QVersionNumber(1, 0)); + instance.create(); + setVulkanInstance(&instance); + setPhysicalDeviceIndex(0); + setPreferredColorFormats({ VK_FORMAT_B8G8R8A8_UNORM, VK_FORMAT_R8G8B8A8_UNORM, VK_FORMAT_A8B8G8R8_UNORM_PACK32 }); + setFlags(Flag::PersistentResources); + buf_usage = std::vector(1); + buf_usage[0].clear(); +} + +QVulkanWindowRenderer * +VulkanWindowRenderer::createRenderer() +{ + renderer = new VulkanRenderer2(this); + return renderer; +} + +void +VulkanWindowRenderer::resizeEvent(QResizeEvent *event) +{ + onResize(width(), height()); + + QVulkanWindow::resizeEvent(event); +} + +bool +VulkanWindowRenderer::event(QEvent *event) +{ + bool res = false; + if (!eventDelegate(event, res)) + return QVulkanWindow::event(event); + return res; +} + +void +VulkanWindowRenderer::onBlit(int buf_idx, int x, int y, int w, int h) +{ + auto origSource = source; + source.setRect(x, y, w, h); + if (isExposed()) + requestUpdate(); + buf_usage[0].clear(); + if (origSource != source) + onResize(this->width(), this->height()); +} + +uint32_t +VulkanWindowRenderer::getBytesPerRow() +{ + return renderer->imagePitch; +} + +std::vector> +VulkanWindowRenderer::getBuffers() +{ + return std::vector { std::make_tuple((uint8_t *) renderer->mappedPtr, &this->buf_usage[0]) }; +} +#endif diff --git a/src/qt/qt_vulkanwindowrenderer.hpp b/src/qt/qt_vulkanwindowrenderer.hpp new file mode 100644 index 000000000..828d091e6 --- /dev/null +++ b/src/qt/qt_vulkanwindowrenderer.hpp @@ -0,0 +1,40 @@ +#ifndef VULKANWINDOWRENDERER_HPP +#define VULKANWINDOWRENDERER_HPP + +#include + +#if QT_CONFIG(vulkan) +# include "qt_renderercommon.hpp" +# include "qt_vulkanrenderer.hpp" + +class VulkanRenderer2; + +class VulkanWindowRenderer : public QVulkanWindow, public RendererCommon { + Q_OBJECT +public: + VulkanWindowRenderer(QWidget *parent); +public slots: + void onBlit(int buf_idx, int x, int y, int w, int h); +signals: + void rendererInitialized(); + void errorInitializing(); + +protected: + virtual std::vector> getBuffers() override; + void resizeEvent(QResizeEvent *) override; + bool event(QEvent *) override; + uint32_t getBytesPerRow() override; + +private: + QVulkanInstance instance; + + QVulkanWindowRenderer *createRenderer() override; + + friend class VulkanRendererEmu; + friend class VulkanRenderer2; + + VulkanRenderer2 *renderer; +}; +#endif + +#endif // VULKANWINDOWRENDERER_HPP diff --git a/src/qt/qt_winmanagerfilter.cpp b/src/qt/qt_winmanagerfilter.cpp index 6eb6d9cd5..cdb81fcd5 100644 --- a/src/qt/qt_winmanagerfilter.cpp +++ b/src/qt/qt_winmanagerfilter.cpp @@ -1,32 +1,32 @@ /* - * 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. + * 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. + * This file is part of the 86Box distribution. * - * Windows VM-managers native messages filter - * - * Authors: - * Teemu Korhonen - * - * Copyright 2022 Teemu Korhonen + * Windows VM-managers native messages filter + * + * + * + * Authors: Teemu Korhonen + * + * Copyright 2022 Teemu Korhonen */ #include "qt_winmanagerfilter.hpp" -#include +#include #include <86box/win.h> -bool WindowsManagerFilter::nativeEventFilter(const QByteArray &eventType, void *message, long *result) +bool +WindowsManagerFilter::nativeEventFilter(const QByteArray &eventType, void *message, result_t *result) { - if (eventType == "windows_generic_MSG") - { + if (eventType == "windows_generic_MSG") { MSG *msg = static_cast(message); - switch (msg->message) - { + switch (msg->message) { case WM_SHOWSETTINGS: emit showsettings(); return true; @@ -51,16 +51,14 @@ bool WindowsManagerFilter::nativeEventFilter(const QByteArray &eventType, void * return false; } -bool WindowsManagerFilter::eventFilter(QObject *obj, QEvent *event) +bool +WindowsManagerFilter::eventFilter(QObject *obj, QEvent *event) { - if (event->type() == QEvent::WindowBlocked) - { + if (event->type() == QEvent::WindowBlocked) { emit dialogstatus(1); - } - else if (event->type() == QEvent::WindowUnblocked) - { + } else if (event->type() == QEvent::WindowUnblocked) { emit dialogstatus(0); } return QObject::eventFilter(obj, event); -} \ No newline at end of file +} diff --git a/src/qt/qt_winmanagerfilter.hpp b/src/qt/qt_winmanagerfilter.hpp index 924011e30..e8fb06d90 100644 --- a/src/qt/qt_winmanagerfilter.hpp +++ b/src/qt/qt_winmanagerfilter.hpp @@ -1,17 +1,18 @@ /* - * 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. + * 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. + * This file is part of the 86Box distribution. * - * Header file for Windows VM-managers native messages filter - * - * Authors: - * Teemu Korhonen - * - * Copyright 2022 Teemu Korhonen + * Header file for Windows VM-managers native messages filter + * + * + * + * Authors: Teemu Korhonen + * + * Copyright 2022 Teemu Korhonen */ #ifndef QT_WINDOWSMANAGERFILTER_HPP @@ -23,17 +24,16 @@ #include #if QT_VERSION_MAJOR >= 6 -#define result_t qintptr -#else -#define result_t long +# define result_t qintptr +#else +# define result_t long #endif /* * Filters native events for messages from VM-manager and * window blocked events to notify about open modal dialogs. */ -class WindowsManagerFilter : public QObject, public QAbstractNativeEventFilter -{ +class WindowsManagerFilter : public QObject, public QAbstractNativeEventFilter { Q_OBJECT public: diff --git a/src/qt/qt_winrawinputfilter.cpp b/src/qt/qt_winrawinputfilter.cpp index 59a808065..b8e7d1038 100644 --- a/src/qt/qt_winrawinputfilter.cpp +++ b/src/qt/qt_winrawinputfilter.cpp @@ -1,20 +1,21 @@ /* - * 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. + * 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. + * This file is part of the 86Box distribution. + * + * Windows raw input native filter for QT + * + * + * + * Authors: Teemu Korhonen + * Miran Grca, + * + * Copyright 2021 Teemu Korhonen + * Copyright 2016-2018 Miran Grca. * - * Windows raw input native filter for QT - * - * Authors: - * Teemu Korhonen - * Miran Grca, - * - * Copyright 2021 Teemu Korhonen - * Copyright 2016-2018 Miran Grca. - * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 @@ -34,7 +35,9 @@ #include -#include +#include + +#include #include <86box/keyboard.h> #include <86box/mouse.h> @@ -44,25 +47,23 @@ #include #include -extern "C" void win_joystick_handle(PRAWINPUT); -std::unique_ptr WindowsRawInputFilter::Register(QMainWindow *window) -{ - HWND wnd = (HWND)window->winId(); +#include "qt_rendererstack.hpp" - RAWINPUTDEVICE rid[2] = - { - { - .usUsagePage = 0x01, - .usUsage = 0x06, - .dwFlags = RIDEV_NOHOTKEYS, - .hwndTarget = wnd - }, - { - .usUsagePage = 0x01, - .usUsage = 0x02, - .dwFlags = 0, - .hwndTarget = wnd - } +extern "C" void win_joystick_handle(PRAWINPUT); +std::unique_ptr +WindowsRawInputFilter::Register(MainWindow *window) +{ + HWND wnd = (HWND) window->winId(); + + RAWINPUTDEVICE rid[2] = { + {.usUsagePage = 0x01, + .usUsage = 0x06, + .dwFlags = RIDEV_NOHOTKEYS, + .hwndTarget = wnd}, + { .usUsagePage = 0x01, + .usUsage = 0x02, + .dwFlags = 0, + .hwndTarget = wnd} }; if (RegisterRawInputDevices(rid, 2, sizeof(rid[0])) == FALSE) @@ -73,12 +74,11 @@ std::unique_ptr WindowsRawInputFilter::Register(QMainWind return inputfilter; } -WindowsRawInputFilter::WindowsRawInputFilter(QMainWindow *window) +WindowsRawInputFilter::WindowsRawInputFilter(MainWindow *window) { this->window = window; - for (auto menu : window->findChildren()) - { + for (auto menu : window->findChildren()) { connect(menu, &QMenu::aboutToShow, this, [=]() { menus_open++; }); connect(menu, &QMenu::aboutToHide, this, [=]() { menus_open--; }); } @@ -91,44 +91,56 @@ WindowsRawInputFilter::WindowsRawInputFilter(QMainWindow *window) WindowsRawInputFilter::~WindowsRawInputFilter() { - RAWINPUTDEVICE rid[2] = - { - { - .usUsagePage = 0x01, - .usUsage = 0x06, - .dwFlags = RIDEV_REMOVE, - .hwndTarget = NULL - }, - { - .usUsagePage = 0x01, - .usUsage = 0x02, - .dwFlags = RIDEV_REMOVE, - .hwndTarget = NULL - } + RAWINPUTDEVICE rid[2] = { + {.usUsagePage = 0x01, + .usUsage = 0x06, + .dwFlags = RIDEV_REMOVE, + .hwndTarget = NULL}, + { .usUsagePage = 0x01, + .usUsage = 0x02, + .dwFlags = RIDEV_REMOVE, + .hwndTarget = NULL} }; RegisterRawInputDevices(rid, 2, sizeof(rid[0])); } -bool WindowsRawInputFilter::nativeEventFilter(const QByteArray &eventType, void *message, long *result) +bool +WindowsRawInputFilter::nativeEventFilter(const QByteArray &eventType, void *message, result_t *result) { - if (eventType == "windows_generic_MSG") - { + if (eventType == "windows_generic_MSG") { MSG *msg = static_cast(message); - if (msg->message == WM_INPUT) - { + if (msg->message == WM_INPUT) { + if (window->isActiveWindow() && menus_open == 0) - handle_input((HRAWINPUT)msg->lParam); - + handle_input((HRAWINPUT) msg->lParam); + else + { + for (auto &w : window->renderers) { + if (w && w->isActiveWindow()) { + handle_input((HRAWINPUT) msg->lParam); + break; + } + } + } + return true; } + + /* Stop processing of Alt-F4 */ + if (msg->message == WM_SYSKEYDOWN) { + if (msg->wParam == 0x73) { + return true; + } + } } return false; } -void WindowsRawInputFilter::handle_input(HRAWINPUT input) +void +WindowsRawInputFilter::handle_input(HRAWINPUT input) { UINT size = 0; @@ -136,12 +148,10 @@ void WindowsRawInputFilter::handle_input(HRAWINPUT input) std::vector buf(size); - if (GetRawInputData(input, RID_INPUT, buf.data(), &size, sizeof(RAWINPUTHEADER)) == size) - { - PRAWINPUT raw = (PRAWINPUT)buf.data(); + if (GetRawInputData(input, RID_INPUT, buf.data(), &size, sizeof(RAWINPUTHEADER)) == size) { + PRAWINPUT raw = (PRAWINPUT) buf.data(); - switch(raw->header.dwType) - { + switch (raw->header.dwType) { case RIM_TYPEKEYBOARD: keyboard_handle(raw); break; @@ -150,30 +160,40 @@ void WindowsRawInputFilter::handle_input(HRAWINPUT input) mouse_handle(raw); break; case RIM_TYPEHID: - { - win_joystick_handle(raw); - break; - } + { + win_joystick_handle(raw); + break; + } } } } /* The following is more or less a direct copy of the old WIN32 implementation */ -void WindowsRawInputFilter::keyboard_handle(PRAWINPUT raw) +void +WindowsRawInputFilter::keyboard_handle(PRAWINPUT raw) { - USHORT scancode; - static int recv_lalt = 0, recv_ralt = 0, recv_tab = 0; + USHORT scancode; RAWKEYBOARD rawKB = raw->data.keyboard; - scancode = rawKB.MakeCode; + scancode = rawKB.MakeCode; - if (kbd_req_capture && !mouse_capture && !video_fullscreen) + if (kbd_req_capture && !mouse_capture) return; /* If it's not a scan code that starts with 0xE1 */ - if (!(rawKB.Flags & RI_KEY_E1)) - { + if ((rawKB.Flags & RI_KEY_E1)) { + if (rawKB.MakeCode == 0x1D) { + scancode = scancode_map[0x100]; /* Translate E1 1D to 0x100 (which would + otherwise be E0 00 but that is invalid + anyway). + Also, take a potential mapping into + account. */ + } else + scancode = 0xFFFF; + if (scancode != 0xFFFF) + keyboard_input(!(rawKB.Flags & RI_KEY_BREAK), scancode); + } else { if (rawKB.Flags & RI_KEY_E0) scancode |= 0x100; @@ -186,92 +206,29 @@ void WindowsRawInputFilter::keyboard_handle(PRAWINPUT raw) scancode = scancode_map[scancode]; /* If it's not 0xFFFF, send it to the emulated - keyboard. - We use scan code 0xFFFF to mean a mapping that - has a prefix other than E0 and that is not E1 1D, - which is, for our purposes, invalid. */ - if ((scancode == 0x00F) && - !(rawKB.Flags & RI_KEY_BREAK) && - (recv_lalt || recv_ralt) && - !mouse_capture) - { - /* We received a TAB while ALT was pressed, while the mouse - is not captured, suppress the TAB and send an ALT key up. */ - if (recv_lalt) - { - keyboard_input(0, 0x038); - /* Extra key press and release so the guest is not stuck in the - menu bar. */ - keyboard_input(1, 0x038); - keyboard_input(0, 0x038); - recv_lalt = 0; - } - if (recv_ralt) - { - keyboard_input(0, 0x138); - /* Extra key press and release so the guest is not stuck in the - menu bar. */ - keyboard_input(1, 0x138); - keyboard_input(0, 0x138); - recv_ralt = 0; - } - } - else if (((scancode == 0x038) || (scancode == 0x138)) && - !(rawKB.Flags & RI_KEY_BREAK) && - recv_tab && - !mouse_capture) - { - /* We received an ALT while TAB was pressed, while the mouse - is not captured, suppress the ALT and send a TAB key up. */ - keyboard_input(0, 0x00F); - recv_tab = 0; - } - else - { - switch (scancode) - { - case 0x00F: - recv_tab = !(rawKB.Flags & RI_KEY_BREAK); - break; - case 0x038: - recv_lalt = !(rawKB.Flags & RI_KEY_BREAK); - break; - case 0x138: - recv_ralt = !(rawKB.Flags & RI_KEY_BREAK); - break; - } + keyboard. + We use scan code 0xFFFF to mean a mapping that + has a prefix other than E0 and that is not E1 1D, + which is, for our purposes, invalid. */ - /* Translate right CTRL to left ALT if the user has so + /* Translate right CTRL to left ALT if the user has so chosen. */ - if ((scancode == 0x11D) && rctrl_is_lalt) - scancode = 0x038; + if ((scancode == 0x11d) && rctrl_is_lalt) + scancode = 0x038; - /* Normal scan code pass through, pass it through as is if + /* Normal scan code pass through, pass it through as is if it's not an invalid scan code. */ - if (scancode != 0xFFFF) - keyboard_input(!(rawKB.Flags & RI_KEY_BREAK), scancode); - } - } - else - { - if (rawKB.MakeCode == 0x1D) - { - scancode = scancode_map[0x100]; /* Translate E1 1D to 0x100 (which would - otherwise be E0 00 but that is invalid - anyway). - Also, take a potential mapping into - account. */ - } - else - scancode = 0xFFFF; if (scancode != 0xFFFF) keyboard_input(!(rawKB.Flags & RI_KEY_BREAK), scancode); + + window->checkFullscreenHotkey(); } } /* This is so we can disambiguate scan codes that would otherwise conflict and get passed on incorrectly. */ -UINT16 WindowsRawInputFilter::convert_scan_code(UINT16 scan_code) +UINT16 +WindowsRawInputFilter::convert_scan_code(UINT16 scan_code) { if ((scan_code & 0xff00) == 0xe000) scan_code = (scan_code & 0xff) | 0x0100; @@ -287,19 +244,20 @@ UINT16 WindowsRawInputFilter::convert_scan_code(UINT16 scan_code) return scan_code; } -void WindowsRawInputFilter::keyboard_getkeymap() +void +WindowsRawInputFilter::keyboard_getkeymap() { - const LPCSTR keyName = "SYSTEM\\CurrentControlSet\\Control\\Keyboard Layout"; - const LPCSTR valueName = "Scancode Map"; + const LPCSTR keyName = "SYSTEM\\CurrentControlSet\\Control\\Keyboard Layout"; + const LPCSTR valueName = "Scancode Map"; unsigned char buf[32768]; - DWORD bufSize; - HKEY hKey; - int j; - UINT32 *bufEx2; - int scMapCount; - UINT16 *bufEx; - int scancode_unmapped; - int scancode_mapped; + DWORD bufSize; + HKEY hKey; + int j; + UINT32 *bufEx2; + int scMapCount; + UINT16 *bufEx; + int scancode_unmapped; + int scancode_mapped; /* First, prepare the default scan code map list which is 1:1. * Remappings will be inserted directly into it. @@ -312,24 +270,20 @@ void WindowsRawInputFilter::keyboard_getkeymap() /* Get the scan code remappings from: HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\Keyboard Layout */ bufSize = 32768; - if (RegOpenKeyEx(HKEY_LOCAL_MACHINE, keyName, 0, 1, &hKey) == ERROR_SUCCESS) - { - if (RegQueryValueEx(hKey, valueName, NULL, NULL, buf, &bufSize) == ERROR_SUCCESS) - { - bufEx2 = (UINT32 *)buf; + if (RegOpenKeyExA(HKEY_LOCAL_MACHINE, keyName, 0, 1, &hKey) == ERROR_SUCCESS) { + if (RegQueryValueExA(hKey, valueName, NULL, NULL, buf, &bufSize) == ERROR_SUCCESS) { + bufEx2 = (UINT32 *) buf; scMapCount = bufEx2[2]; - if ((bufSize != 0) && (scMapCount != 0)) - { - bufEx = (UINT16 *)(buf + 12); - for (j = 0; j < scMapCount * 2; j += 2) - { + if ((bufSize != 0) && (scMapCount != 0)) { + bufEx = (UINT16 *) (buf + 12); + for (j = 0; j < scMapCount * 2; j += 2) { /* Each scan code is 32-bit: 16 bits of remapped scan code, and 16 bits of original scan code. */ scancode_unmapped = bufEx[j + 1]; - scancode_mapped = bufEx[j]; + scancode_mapped = bufEx[j]; scancode_unmapped = convert_scan_code(scancode_unmapped); - scancode_mapped = convert_scan_code(scancode_mapped); + scancode_mapped = convert_scan_code(scancode_mapped); /* Ignore source scan codes with prefixes other than E1 that are not E1 1D. */ @@ -342,49 +296,67 @@ void WindowsRawInputFilter::keyboard_getkeymap() } } -void WindowsRawInputFilter::mouse_handle(PRAWINPUT raw) +void +WindowsRawInputFilter::mouse_handle(PRAWINPUT raw) { - RAWMOUSE state = raw->data.mouse; - static int x, y; + RAWMOUSE state = raw->data.mouse; + static int x, delta_x; + static int y, delta_y; + static int b, delta_z; + + b = mouse_get_buttons_ex(); /* read mouse buttons and wheel */ if (state.usButtonFlags & RI_MOUSE_LEFT_BUTTON_DOWN) - buttons |= 1; + b |= 1; else if (state.usButtonFlags & RI_MOUSE_LEFT_BUTTON_UP) - buttons &= ~1; + b &= ~1; if (state.usButtonFlags & RI_MOUSE_MIDDLE_BUTTON_DOWN) - buttons |= 4; + b |= 4; else if (state.usButtonFlags & RI_MOUSE_MIDDLE_BUTTON_UP) - buttons &= ~4; + b &= ~4; if (state.usButtonFlags & RI_MOUSE_RIGHT_BUTTON_DOWN) - buttons |= 2; + b |= 2; else if (state.usButtonFlags & RI_MOUSE_RIGHT_BUTTON_UP) - buttons &= ~2; + b &= ~2; - if (state.usButtonFlags & RI_MOUSE_WHEEL) - { - dwheel += (SHORT)state.usButtonData / 120; - } + if (state.usButtonFlags & RI_MOUSE_BUTTON_4_DOWN) + b |= 8; + else if (state.usButtonFlags & RI_MOUSE_BUTTON_4_UP) + b &= ~8; - if (state.usFlags & MOUSE_MOVE_ABSOLUTE) - { - /* absolute mouse, i.e. RDP or VNC + if (state.usButtonFlags & RI_MOUSE_BUTTON_5_DOWN) + b |= 16; + else if (state.usButtonFlags & RI_MOUSE_BUTTON_5_UP) + b &= ~16; + + mouse_set_buttons_ex(b); + + if (state.usButtonFlags & RI_MOUSE_WHEEL) { + delta_z = (SHORT) state.usButtonData / 120; + mouse_set_z(delta_z); + } else + delta_z = 0; + + if (state.usFlags & MOUSE_MOVE_ABSOLUTE) { + /* absolute mouse, i.e. RDP or VNC * seems to work fine for RDP on Windows 10 * Not sure about other environments. */ - dx += (state.lLastX - x) / 25; - dy += (state.lLastY - y) / 25; + delta_x = (state.lLastX - x) / 25; + delta_y = (state.lLastY - y) / 25; x = state.lLastX; y = state.lLastY; - } - else - { + } else { /* relative mouse, i.e. regular mouse */ - dx += state.lLastX; - dy += state.lLastY; + delta_x = state.lLastX; + delta_y = state.lLastY; } + + mouse_scale(delta_x, delta_y); + HWND wnd = (HWND)window->winId(); RECT rect; @@ -396,28 +368,3 @@ void WindowsRawInputFilter::mouse_handle(PRAWINPUT raw) SetCursorPos(left, top); } - -void WindowsRawInputFilter::mousePoll() -{ - if (mouse_capture || video_fullscreen) - { - static int b = 0; - - if (dx != 0 || dy != 0 || dwheel != 0) - { - mouse_x += dx; - mouse_y += dy; - mouse_z = dwheel; - - dx = 0; - dy = 0; - dwheel = 0; - } - - if (b != buttons) - { - mouse_buttons = buttons; - b = buttons; - } - } -} diff --git a/src/qt/qt_winrawinputfilter.hpp b/src/qt/qt_winrawinputfilter.hpp index 7a73a2eca..f687164ca 100644 --- a/src/qt/qt_winrawinputfilter.hpp +++ b/src/qt/qt_winrawinputfilter.hpp @@ -1,18 +1,19 @@ /* - * 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. + * 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. + * This file is part of the 86Box distribution. + * + * Header file for windows raw input native filter for QT + * + * + * + * Authors: Teemu Korhonen + * + * Copyright 2021 Teemu Korhonen * - * Header file for windows raw input native filter for QT - * - * Authors: - * Teemu Korhonen - * - * Copyright 2021 Teemu Korhonen - * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 @@ -36,47 +37,44 @@ #include #include -#include +#include #include -#if QT_VERSION_MAJOR >= 6 -#define result_t qintptr -#else -#define result_t long +#include "qt_mainwindow.hpp" + +#if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0) +# define result_t qintptr +#else +# define result_t long #endif - -class WindowsRawInputFilter : public QObject, public QAbstractNativeEventFilter -{ +class WindowsRawInputFilter : public QObject, public QAbstractNativeEventFilter { Q_OBJECT public: - static std::unique_ptr Register(QMainWindow *window); + static std::unique_ptr Register(MainWindow *window); bool nativeEventFilter(const QByteArray &eventType, void *message, result_t *result) override; ~WindowsRawInputFilter(); -public slots: - void mousePoll(); - private: - QMainWindow *window; - uint16_t scancode_map[768]; - int buttons = 0; - int dx = 0; - int dy = 0; - int dwheel = 0; - int menus_open = 0; + MainWindow *window; + uint16_t scancode_map[768]; + int buttons = 0; + int dx = 0; + int dy = 0; + int dwheel = 0; + int menus_open = 0; - WindowsRawInputFilter(QMainWindow *window); + WindowsRawInputFilter(MainWindow *window); - void handle_input(HRAWINPUT input); - void keyboard_handle(PRAWINPUT raw); - void mouse_handle(PRAWINPUT raw); + void handle_input(HRAWINPUT input); + void keyboard_handle(PRAWINPUT raw); + void mouse_handle(PRAWINPUT raw); static UINT16 convert_scan_code(UINT16 scan_code); - void keyboard_getkeymap(); + void keyboard_getkeymap(); }; #endif diff --git a/src/qt/sdl_joystick.cpp b/src/qt/sdl_joystick.cpp index 0e7bfd619..cdbf102b8 100644 --- a/src/qt/sdl_joystick.cpp +++ b/src/qt/sdl_joystick.cpp @@ -8,108 +8,112 @@ extern "C" { #include <86box/device.h> #include <86box/gameport.h> -int joysticks_present; -joystick_t joystick_state[MAX_JOYSTICKS]; -plat_joystick_t plat_joystick_state[MAX_PLAT_JOYSTICKS]; +int joysticks_present; +joystick_t joystick_state[MAX_JOYSTICKS]; +plat_joystick_t plat_joystick_state[MAX_PLAT_JOYSTICKS]; static SDL_Joystick *sdl_joy[MAX_PLAT_JOYSTICKS]; } #include #ifndef M_PI -#define M_PI 3.14159265358979323846 +# define M_PI 3.14159265358979323846 #endif -void joystick_init() { +void +joystick_init() +{ if (SDL_InitSubSystem(SDL_INIT_JOYSTICK) != 0) { return; } joysticks_present = SDL_NumJoysticks(); memset(sdl_joy, 0, sizeof(sdl_joy)); - for (int c = 0; c < joysticks_present; c++) - { + for (int c = 0; c < joysticks_present; c++) { sdl_joy[c] = SDL_JoystickOpen(c); - if (sdl_joy[c]) - { + if (sdl_joy[c]) { int d; strncpy(plat_joystick_state[c].name, SDL_JoystickNameForIndex(c), 64); - plat_joystick_state[c].nr_axes = SDL_JoystickNumAxes(sdl_joy[c]); + plat_joystick_state[c].nr_axes = SDL_JoystickNumAxes(sdl_joy[c]); plat_joystick_state[c].nr_buttons = SDL_JoystickNumButtons(sdl_joy[c]); - plat_joystick_state[c].nr_povs = SDL_JoystickNumHats(sdl_joy[c]); + plat_joystick_state[c].nr_povs = SDL_JoystickNumHats(sdl_joy[c]); - for (d = 0; d < std::min(plat_joystick_state[c].nr_axes, 8); d++) - { - sprintf(plat_joystick_state[c].axis[d].name, "Axis %i", d); + for (d = 0; d < std::min(plat_joystick_state[c].nr_axes, 8); d++) { + snprintf(plat_joystick_state[c].axis[d].name, sizeof(plat_joystick_state[c].axis[d].name), "Axis %i", d); plat_joystick_state[c].axis[d].id = d; } - for (d = 0; d < std::min(plat_joystick_state[c].nr_buttons, 8); d++) - { - sprintf(plat_joystick_state[c].button[d].name, "Button %i", d); + for (d = 0; d < std::min(plat_joystick_state[c].nr_buttons, 8); d++) { + snprintf(plat_joystick_state[c].button[d].name, sizeof(plat_joystick_state[c].button[d].name), "Button %i", d); plat_joystick_state[c].button[d].id = d; } - for (d = 0; d < std::min(plat_joystick_state[c].nr_povs, 4); d++) - { - sprintf(plat_joystick_state[c].pov[d].name, "POV %i", d); + for (d = 0; d < std::min(plat_joystick_state[c].nr_povs, 4); d++) { + snprintf(plat_joystick_state[c].pov[d].name, sizeof(plat_joystick_state[c].pov[d].name), "POV %i", d); plat_joystick_state[c].pov[d].id = d; } } } } -void joystick_close() +void +joystick_close() { int c; - for (c = 0; c < joysticks_present; c++) - { + for (c = 0; c < joysticks_present; c++) { if (sdl_joy[c]) SDL_JoystickClose(sdl_joy[c]); } } -static int joystick_get_axis(int joystick_nr, int mapping) +static int +joystick_get_axis(int joystick_nr, int mapping) { - if (mapping & POV_X) - { - switch (plat_joystick_state[joystick_nr].p[mapping & 3]) - { - case SDL_HAT_LEFTUP: case SDL_HAT_LEFT: case SDL_HAT_LEFTDOWN: - return -32767; + if (mapping & POV_X) { + switch (plat_joystick_state[joystick_nr].p[mapping & 3]) { + case SDL_HAT_LEFTUP: + case SDL_HAT_LEFT: + case SDL_HAT_LEFTDOWN: + return -32767; - case SDL_HAT_RIGHTUP: case SDL_HAT_RIGHT: case SDL_HAT_RIGHTDOWN: - return 32767; + case SDL_HAT_RIGHTUP: + case SDL_HAT_RIGHT: + case SDL_HAT_RIGHTDOWN: + return 32767; - default: - return 0; + default: + return 0; } - } - else if (mapping & POV_Y) - { - switch (plat_joystick_state[joystick_nr].p[mapping & 3]) - { - case SDL_HAT_LEFTUP: case SDL_HAT_UP: case SDL_HAT_RIGHTUP: - return -32767; + } else if (mapping & POV_Y) { + switch (plat_joystick_state[joystick_nr].p[mapping & 3]) { + case SDL_HAT_LEFTUP: + case SDL_HAT_UP: + case SDL_HAT_RIGHTUP: + return -32767; - case SDL_HAT_LEFTDOWN: case SDL_HAT_DOWN: case SDL_HAT_RIGHTDOWN: - return 32767; + case SDL_HAT_LEFTDOWN: + case SDL_HAT_DOWN: + case SDL_HAT_RIGHTDOWN: + return 32767; - default: - return 0; + default: + return 0; } - } - else + } else return plat_joystick_state[joystick_nr].a[plat_joystick_state[joystick_nr].axis[mapping].id]; } -void joystick_process() +void +joystick_process() { - int c, d; + int c; + int d; + + if (!joystick_type) + return; SDL_JoystickUpdate(); - for (c = 0; c < joysticks_present; c++) - { + for (c = 0; c < joysticks_present; c++) { int b; plat_joystick_state[c].a[0] = SDL_JoystickGetAxis(sdl_joy[c], 0); @@ -127,35 +131,30 @@ void joystick_process() // pclog("joystick %i - x=%i y=%i b[0]=%i b[1]=%i %i\n", c, joystick_state[c].x, joystick_state[c].y, joystick_state[c].b[0], joystick_state[c].b[1], joysticks_present); } - for (c = 0; c < joystick_get_max_joysticks(joystick_type); c++) - { - if (joystick_state[c].plat_joystick_nr) - { + for (c = 0; c < joystick_get_max_joysticks(joystick_type); c++) { + if (joystick_state[c].plat_joystick_nr) { int joystick_nr = joystick_state[c].plat_joystick_nr - 1; for (d = 0; d < joystick_get_axis_count(joystick_type); d++) joystick_state[c].axis[d] = joystick_get_axis(joystick_nr, joystick_state[c].axis_mapping[d]); for (d = 0; d < joystick_get_button_count(joystick_type); d++) joystick_state[c].button[d] = plat_joystick_state[joystick_nr].b[joystick_state[c].button_mapping[d]]; - for (d = 0; d < joystick_get_pov_count(joystick_type); d++) - { - int x, y; + for (d = 0; d < joystick_get_pov_count(joystick_type); d++) { + int x, y; double angle, magnitude; x = joystick_get_axis(joystick_nr, joystick_state[c].pov_mapping[d][0]); y = joystick_get_axis(joystick_nr, joystick_state[c].pov_mapping[d][1]); - angle = (atan2((double)y, (double)x) * 360.0) / (2*M_PI); - magnitude = sqrt((double)x*(double)x + (double)y*(double)y); + angle = (atan2((double) y, (double) x) * 360.0) / (2 * M_PI); + magnitude = sqrt((double) x * (double) x + (double) y * (double) y); if (magnitude < 16384) joystick_state[c].pov[d] = -1; else - joystick_state[c].pov[d] = ((int)angle + 90 + 360) % 360; + joystick_state[c].pov[d] = ((int) angle + 90 + 360) % 360; } - } - else - { + } else { for (d = 0; d < joystick_get_axis_count(joystick_type); d++) joystick_state[c].axis[d] = 0; for (d = 0; d < joystick_get_button_count(joystick_type); d++) diff --git a/src/qt/texture_frag.spv b/src/qt/texture_frag.spv new file mode 100644 index 000000000..7521ef6ee Binary files /dev/null and b/src/qt/texture_frag.spv differ diff --git a/src/qt/texture_vert.spv b/src/qt/texture_vert.spv new file mode 100644 index 000000000..6292c0de3 Binary files /dev/null and b/src/qt/texture_vert.spv differ diff --git a/src/qt/win_dynld.c b/src/qt/win_dynld.c new file mode 100644 index 000000000..88fb632bc --- /dev/null +++ b/src/qt/win_dynld.c @@ -0,0 +1,83 @@ +/* + * 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. + * + * Try to load a support DLL. + * + * + * + * Authors: Fred N. van Kempen, + * + * Copyright 2017-2018 Fred N. van Kempen + */ +#include +#include +#include +#include +#include +#include +#include +#define HAVE_STDARG_H +#include <86box/86box.h> +#include <86box/plat_dynld.h> + +#ifdef ENABLE_DYNLD_LOG +int dynld_do_log = ENABLE_DYNLD_LOG; + +static void +dynld_log(const char *fmt, ...) +{ + va_list ap; + + if (dynld_do_log) { + va_start(ap, fmt); + pclog_ex(fmt, ap); + va_end(ap); + } +} +#else +# define dynld_log(fmt, ...) +#endif + +void * +dynld_module(const char *name, dllimp_t *table) +{ + HMODULE h; + dllimp_t *imp; + void *func; + + /* See if we can load the desired module. */ + if ((h = LoadLibrary(name)) == NULL) { + dynld_log("DynLd(\"%s\"): library not found! (%08X)\n", name, GetLastError()); + return (NULL); + } + + /* Now load the desired function pointers. */ + for (imp = table; imp->name != NULL; imp++) { + func = GetProcAddress(h, imp->name); + if (func == NULL) { + dynld_log("DynLd(\"%s\"): function '%s' not found! (%08X)\n", + name, imp->name, GetLastError()); + FreeLibrary(h); + return (NULL); + } + + /* To overcome typing issues.. */ + *(char **) imp->func = (char *) func; + } + + /* All good. */ + dynld_log("loaded %s\n", name); + return ((void *) h); +} + +void +dynld_close(void *handle) +{ + if (handle != NULL) + FreeLibrary((HMODULE) handle); +} diff --git a/src/qt/win_joystick_rawinput.c b/src/qt/win_joystick_rawinput.c index be808fc47..7ee0e8227 100644 --- a/src/qt/win_joystick_rawinput.c +++ b/src/qt/win_joystick_rawinput.c @@ -1,20 +1,22 @@ /* - * 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. + * 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. + * This file is part of the 86Box distribution. * - * RawInput joystick interface. + * RawInput joystick interface. * - * Authors: Sarah Walker, - * Miran Grca, - * GH Cao, * - * Copyright 2008-2018 Sarah Walker. - * Copyright 2016-2018 Miran Grca. - * Copyright 2020 GH Cao. + * + * Authors: Miran Grca, + * GH Cao, + * Jasmine Iwanek, + * + * Copyright 2016-2018 Miran Grca. + * Copyright 2020 GH Cao. + * Copyright 2021-2023 Jasmine Iwanek. */ #include #include @@ -36,436 +38,449 @@ #ifdef ENABLE_JOYSTICK_LOG int joystick_do_log = ENABLE_JOYSTICK_LOG; - static void joystick_log(const char *fmt, ...) { - va_list ap; + va_list ap; - if (joystick_do_log) { - va_start(ap, fmt); - pclog_ex(fmt, ap); - va_end(ap); - } + if (joystick_do_log) { + va_start(ap, fmt); + pclog_ex(fmt, ap); + va_end(ap); + } } #else -#define joystick_log(fmt, ...) +# define joystick_log(fmt, ...) #endif typedef struct { - HANDLE hdevice; - PHIDP_PREPARSED_DATA data; - - USAGE usage_button[256]; + HANDLE hdevice; + PHIDP_PREPARSED_DATA data; - struct raw_axis_t { - USAGE usage; - USHORT link; - USHORT bitsize; - LONG max; - LONG min; - } axis[8]; + USAGE usage_button[256]; - struct raw_pov_t { - USAGE usage; - USHORT link; - LONG max; - LONG min; - } pov[4]; + struct raw_axis_t { + USAGE usage; + USHORT link; + USHORT bitsize; + LONG max; + LONG min; + } axis[8]; + + struct raw_pov_t { + USAGE usage; + USHORT link; + LONG max; + LONG min; + } pov[4]; } raw_joystick_t; plat_joystick_t plat_joystick_state[MAX_PLAT_JOYSTICKS]; -joystick_t joystick_state[MAX_JOYSTICKS]; -int joysticks_present = 0; +joystick_t joystick_state[MAX_JOYSTICKS]; +int joysticks_present = 0; raw_joystick_t raw_joystick_state[MAX_PLAT_JOYSTICKS]; /* We only use the first 32 buttons reported, from Usage ID 1-128 */ -void joystick_add_button(raw_joystick_t* rawjoy, plat_joystick_t* joy, USAGE usage) { - if (joy->nr_buttons >= 32) return; - if (usage < 1 || usage > 128) return; - - rawjoy->usage_button[usage] = joy->nr_buttons; - sprintf(joy->button[joy->nr_buttons].name, "Button %d", usage); - joy->nr_buttons++; -} - -void joystick_add_axis(raw_joystick_t* rawjoy, plat_joystick_t* joy, PHIDP_VALUE_CAPS prop) { - if (joy->nr_axes >= 8) return; - - switch (prop->Range.UsageMin) { - case HID_USAGE_GENERIC_X: - sprintf(joy->axis[joy->nr_axes].name, "X"); - break; - case HID_USAGE_GENERIC_Y: - sprintf(joy->axis[joy->nr_axes].name, "Y"); - break; - case HID_USAGE_GENERIC_Z: - sprintf(joy->axis[joy->nr_axes].name, "Z"); - break; - case HID_USAGE_GENERIC_RX: - sprintf(joy->axis[joy->nr_axes].name, "RX"); - break; - case HID_USAGE_GENERIC_RY: - sprintf(joy->axis[joy->nr_axes].name, "RY"); - break; - case HID_USAGE_GENERIC_RZ: - sprintf(joy->axis[joy->nr_axes].name, "RZ"); - break; - default: - return; - } - - joy->axis[joy->nr_axes].id = joy->nr_axes; - rawjoy->axis[joy->nr_axes].usage = prop->Range.UsageMin; - rawjoy->axis[joy->nr_axes].link = prop->LinkCollection; - rawjoy->axis[joy->nr_axes].bitsize = prop->BitSize; - - /* Assume unsigned when min >= 0 */ - if (prop->LogicalMin < 0) { - rawjoy->axis[joy->nr_axes].max = prop->LogicalMax; - } else { - /* - * Some joysticks will send -1 in LogicalMax, like Xbox Controllers - * so we need to mask that to appropriate value (instead of 0xFFFFFFFF) - */ - rawjoy->axis[joy->nr_axes].max = prop->LogicalMax & ((1 << prop->BitSize) - 1); - } - rawjoy->axis[joy->nr_axes].min = prop->LogicalMin; - - joy->nr_axes++; -} - -void joystick_add_pov(raw_joystick_t* rawjoy, plat_joystick_t* joy, PHIDP_VALUE_CAPS prop) { - if (joy->nr_povs >= 4) return; - - sprintf(joy->pov[joy->nr_povs].name, "POV %d", joy->nr_povs+1); - rawjoy->pov[joy->nr_povs].usage = prop->Range.UsageMin; - rawjoy->pov[joy->nr_povs].link = prop->LinkCollection; - rawjoy->pov[joy->nr_povs].min = prop->LogicalMin; - rawjoy->pov[joy->nr_povs].max = prop->LogicalMax; - - joy->nr_povs++; -} - -void joystick_get_capabilities(raw_joystick_t* rawjoy, plat_joystick_t* joy) { - UINT size = 0; - PHIDP_BUTTON_CAPS btn_caps = NULL; - PHIDP_VALUE_CAPS val_caps = NULL; - - /* Get preparsed data (HID data format) */ - GetRawInputDeviceInfoW(rawjoy->hdevice, RIDI_PREPARSEDDATA, NULL, &size); - rawjoy->data = malloc(size); - if (GetRawInputDeviceInfoW(rawjoy->hdevice, RIDI_PREPARSEDDATA, rawjoy->data, &size) <= 0) - fatal("joystick_get_capabilities: Failed to get preparsed data.\n"); - - HIDP_CAPS caps; - HidP_GetCaps(rawjoy->data, &caps); - - /* Buttons */ - if (caps.NumberInputButtonCaps > 0) { - btn_caps = calloc(caps.NumberInputButtonCaps, sizeof(HIDP_BUTTON_CAPS)); - if (HidP_GetButtonCaps(HidP_Input, btn_caps, &caps.NumberInputButtonCaps, rawjoy->data) != HIDP_STATUS_SUCCESS) { - joystick_log("joystick_get_capabilities: Failed to query input buttons.\n"); - goto end; - } - /* We only detect generic stuff */ - for (int c=0; c 0) { - val_caps = calloc(caps.NumberInputValueCaps, sizeof(HIDP_VALUE_CAPS)); - if (HidP_GetValueCaps(HidP_Input, val_caps, &caps.NumberInputValueCaps, rawjoy->data) != HIDP_STATUS_SUCCESS) { - joystick_log("joystick_get_capabilities: Failed to query axes and povs.\n"); - goto end; - } - /* We only detect generic stuff */ - for (int c=0; chdevice, RIDI_DEVICENAME, device_name, &size); - device_name = calloc(size, sizeof(char)); - if (GetRawInputDeviceInfoA(rawjoy->hdevice, RIDI_DEVICENAME, device_name, &size) <= 0) - fatal("joystick_get_capabilities: Failed to get device name.\n"); - - HANDLE hDevObj = CreateFile(device_name, GENERIC_READ | GENERIC_WRITE, - FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING, 0, NULL); - if (hDevObj) { - HidD_GetProductString(hDevObj, device_desc_wide, sizeof(WCHAR) * 200); - CloseHandle(hDevObj); - } - free(device_name); - - int result = WideCharToMultiByte(CP_ACP, 0, device_desc_wide, 200, joy->name, 260, NULL, NULL); - if (result == 0 || strlen(joy->name) == 0) - sprintf(joy->name, - "RawInput %s, VID:%04lX PID:%04lX", - info->hid.usUsage == HID_USAGE_GENERIC_JOYSTICK ? "Joystick" : "Gamepad", - info->hid.dwVendorId, - info->hid.dwProductId); -} - -void joystick_init() +void +joystick_add_button(raw_joystick_t *rawjoy, plat_joystick_t *joy, USAGE usage) { - UINT size = 0; - atexit(joystick_close); + if (joy->nr_buttons >= 32) + return; + if (usage < 1 || usage > 128) + return; - joysticks_present = 0; - memset(raw_joystick_state, 0, sizeof(raw_joystick_t) * MAX_PLAT_JOYSTICKS); - - /* Get a list of raw input devices from Windows */ - UINT raw_devices = 0; - GetRawInputDeviceList(NULL, &raw_devices, sizeof(RAWINPUTDEVICELIST)); - PRAWINPUTDEVICELIST deviceList = calloc(raw_devices, sizeof(RAWINPUTDEVICELIST)); - GetRawInputDeviceList(deviceList, &raw_devices, sizeof(RAWINPUTDEVICELIST)); - - for (int i=0; i= MAX_PLAT_JOYSTICKS) break; - if (deviceList[i].dwType != RIM_TYPEHID) continue; - - /* Get device info: hardware IDs and usage IDs */ - GetRawInputDeviceInfoA(deviceList[i].hDevice, RIDI_DEVICEINFO, NULL, &size); - info = malloc(size); - info->cbSize = sizeof(RID_DEVICE_INFO); - if (GetRawInputDeviceInfoA(deviceList[i].hDevice, RIDI_DEVICEINFO, info, &size) <= 0) - goto end_loop; - - /* If this is not a joystick/gamepad, skip */ - if (info->hid.usUsagePage != HID_USAGE_PAGE_GENERIC) goto end_loop; - if (info->hid.usUsage != HID_USAGE_GENERIC_JOYSTICK && - info->hid.usUsage != HID_USAGE_GENERIC_GAMEPAD) goto end_loop; - - plat_joystick_t *joy = &plat_joystick_state[joysticks_present]; - raw_joystick_t *rawjoy = &raw_joystick_state[joysticks_present]; - rawjoy->hdevice = deviceList[i].hDevice; - - joystick_get_capabilities(rawjoy, joy); - joystick_get_device_name(rawjoy, joy, info); - - joystick_log("joystick_init: %s - %d buttons, %d axes, %d POVs\n", - joy->name, joy->nr_buttons, joy->nr_axes, joy->nr_povs); - - joysticks_present++; - - end_loop: - free(info); - } - - joystick_log("joystick_init: joysticks_present=%i\n", joysticks_present); - - /* Initialize the RawInput (joystick and gamepad) module. */ - RAWINPUTDEVICE ridev[2]; - ridev[0].dwFlags = 0; - ridev[0].hwndTarget = NULL; - ridev[0].usUsagePage = HID_USAGE_PAGE_GENERIC; - ridev[0].usUsage = HID_USAGE_GENERIC_JOYSTICK; - - ridev[1].dwFlags = 0; - ridev[1].hwndTarget = NULL; - ridev[1].usUsagePage = HID_USAGE_PAGE_GENERIC; - ridev[1].usUsage = HID_USAGE_GENERIC_GAMEPAD; - - if (!RegisterRawInputDevices(ridev, 2, sizeof(RAWINPUTDEVICE))) - fatal("plat_joystick_init: RegisterRawInputDevices failed\n"); + rawjoy->usage_button[usage] = joy->nr_buttons; + sprintf(joy->button[joy->nr_buttons].name, "Button %d", usage); + joy->nr_buttons++; } -void joystick_close() +void +joystick_add_axis(raw_joystick_t *rawjoy, plat_joystick_t *joy, PHIDP_VALUE_CAPS prop) { - RAWINPUTDEVICE ridev[2]; - ridev[0].dwFlags = RIDEV_REMOVE; - ridev[0].hwndTarget = NULL; - ridev[0].usUsagePage = HID_USAGE_PAGE_GENERIC; - ridev[0].usUsage = HID_USAGE_GENERIC_JOYSTICK; + if (joy->nr_axes >= 8) + return; - ridev[1].dwFlags = RIDEV_REMOVE; - ridev[1].hwndTarget = NULL; - ridev[1].usUsagePage = HID_USAGE_PAGE_GENERIC; - ridev[1].usUsage = HID_USAGE_GENERIC_GAMEPAD; + switch (prop->Range.UsageMin) { + case HID_USAGE_GENERIC_X: + sprintf(joy->axis[joy->nr_axes].name, "X"); + break; + case HID_USAGE_GENERIC_Y: + sprintf(joy->axis[joy->nr_axes].name, "Y"); + break; + case HID_USAGE_GENERIC_Z: + sprintf(joy->axis[joy->nr_axes].name, "Z"); + break; + case HID_USAGE_GENERIC_RX: + sprintf(joy->axis[joy->nr_axes].name, "RX"); + break; + case HID_USAGE_GENERIC_RY: + sprintf(joy->axis[joy->nr_axes].name, "RY"); + break; + case HID_USAGE_GENERIC_RZ: + sprintf(joy->axis[joy->nr_axes].name, "RZ"); + break; + default: + return; + } - RegisterRawInputDevices(ridev, 2, sizeof(RAWINPUTDEVICE)); + joy->axis[joy->nr_axes].id = joy->nr_axes; + rawjoy->axis[joy->nr_axes].usage = prop->Range.UsageMin; + rawjoy->axis[joy->nr_axes].link = prop->LinkCollection; + rawjoy->axis[joy->nr_axes].bitsize = prop->BitSize; + + /* Assume unsigned when min >= 0 */ + if (prop->LogicalMin < 0) { + rawjoy->axis[joy->nr_axes].max = prop->LogicalMax; + } else { + /* + * Some joysticks will send -1 in LogicalMax, like Xbox Controllers + * so we need to mask that to appropriate value (instead of 0xFFFFFFFF) + */ + rawjoy->axis[joy->nr_axes].max = prop->LogicalMax & ((1ULL << prop->BitSize) - 1); + } + rawjoy->axis[joy->nr_axes].min = prop->LogicalMin; + + joy->nr_axes++; } - -void win_joystick_handle(PRAWINPUT raw) +void +joystick_add_pov(raw_joystick_t *rawjoy, plat_joystick_t *joy, PHIDP_VALUE_CAPS prop) { - HRESULT r; - int j = -1; /* current joystick index, -1 when not found */ + if (joy->nr_povs >= 4) + return; - /* If the input is not from a known device, we ignore it */ - for (int i=0; iheader.hDevice) { - j = i; - break; - } - } - if (j == -1) return; - - /* Read buttons */ - USAGE usage_list[128] = {0}; - ULONG usage_length = plat_joystick_state[j].nr_buttons; - memset(plat_joystick_state[j].b, 0, 32 * sizeof(int)); + sprintf(joy->pov[joy->nr_povs].name, "POV %d", joy->nr_povs + 1); + rawjoy->pov[joy->nr_povs].usage = prop->Range.UsageMin; + rawjoy->pov[joy->nr_povs].link = prop->LinkCollection; + rawjoy->pov[joy->nr_povs].min = prop->LogicalMin; + rawjoy->pov[joy->nr_povs].max = prop->LogicalMax; - r = HidP_GetUsages(HidP_Input, HID_USAGE_PAGE_BUTTON, 0, usage_list, &usage_length, - raw_joystick_state[j].data, (PCHAR)raw->data.hid.bRawData, raw->data.hid.dwSizeHid); - - if (r == HIDP_STATUS_SUCCESS) { - for (int i=0; imax - axis->min + 1) / 2; - - r = HidP_GetUsageValue(HidP_Input, HID_USAGE_PAGE_GENERIC, axis->link, axis->usage, &uvalue, - raw_joystick_state[j].data, (PCHAR)raw->data.hid.bRawData, raw->data.hid.dwSizeHid); - - if (r == HIDP_STATUS_SUCCESS) { - if (axis->min < 0) { - /* extend signed uvalue to LONG */ - if (uvalue & (1 << (axis->bitsize-1))) { - ULONG mask = (1 << axis->bitsize) - 1; - value = -1U ^ mask; - value |= uvalue; - } else { - value = uvalue; - } - } else { - /* Assume unsigned when min >= 0, convert to a signed value */ - value = (LONG)uvalue - center; - } - if (abs(value) == 1) value = 0; - value = value * 32768 / center; - } - - plat_joystick_state[j].a[a] = value; - //joystick_log("%s %-06d ", plat_joystick_state[j].axis[a].name, plat_joystick_state[j].a[a]); - } - - /* read povs */ - for (int p=0; plink, pov->usage, &uvalue, - raw_joystick_state[j].data, (PCHAR)raw->data.hid.bRawData, raw->data.hid.dwSizeHid); - - if (r == HIDP_STATUS_SUCCESS && (uvalue >= pov->min && uvalue <= pov->max)) { - value = (uvalue - pov->min) * 36000; - value /= (pov->max - pov->min + 1); - value %= 36000; - } - - plat_joystick_state[j].p[p] = value; - - //joystick_log("%s %-3d ", plat_joystick_state[j].pov[p].name, plat_joystick_state[j].p[p]); - - } - //joystick_log("\n"); + joy->nr_povs++; } - -static int joystick_get_axis(int joystick_nr, int mapping) +void +joystick_get_capabilities(raw_joystick_t *rawjoy, plat_joystick_t *joy) { - if (mapping & POV_X) - { - int pov = plat_joystick_state[joystick_nr].p[mapping & 3]; - if (LOWORD(pov) == 0xFFFF) - return 0; - else - return sin((2*M_PI * (double)pov) / 36000.0) * 32767; - } - else if (mapping & POV_Y) - { - int pov = plat_joystick_state[joystick_nr].p[mapping & 3]; - - if (LOWORD(pov) == 0xFFFF) - return 0; - else - return -cos((2*M_PI * (double)pov) / 36000.0) * 32767; - } - else - return plat_joystick_state[joystick_nr].a[plat_joystick_state[joystick_nr].axis[mapping].id]; - + UINT size = 0; + PHIDP_BUTTON_CAPS btn_caps = NULL; + PHIDP_VALUE_CAPS val_caps = NULL; + + /* Get preparsed data (HID data format) */ + GetRawInputDeviceInfoW(rawjoy->hdevice, RIDI_PREPARSEDDATA, NULL, &size); + rawjoy->data = malloc(size); + if (GetRawInputDeviceInfoW(rawjoy->hdevice, RIDI_PREPARSEDDATA, rawjoy->data, &size) <= 0) + fatal("joystick_get_capabilities: Failed to get preparsed data.\n"); + + HIDP_CAPS caps; + HidP_GetCaps(rawjoy->data, &caps); + + /* Buttons */ + if (caps.NumberInputButtonCaps > 0) { + btn_caps = calloc(caps.NumberInputButtonCaps, sizeof(HIDP_BUTTON_CAPS)); + if (HidP_GetButtonCaps(HidP_Input, btn_caps, &caps.NumberInputButtonCaps, rawjoy->data) != HIDP_STATUS_SUCCESS) { + joystick_log("joystick_get_capabilities: Failed to query input buttons.\n"); + goto end; + } + /* We only detect generic stuff */ + for (int c = 0; c < caps.NumberInputButtonCaps; c++) { + if (btn_caps[c].UsagePage != HID_USAGE_PAGE_BUTTON) + continue; + + int button_count = btn_caps[c].Range.UsageMax - btn_caps[c].Range.UsageMin + 1; + for (int b = 0; b < button_count; b++) { + joystick_add_button(rawjoy, joy, b + btn_caps[c].Range.UsageMin); + } + } + } + + /* Values (axes and povs) */ + if (caps.NumberInputValueCaps > 0) { + val_caps = calloc(caps.NumberInputValueCaps, sizeof(HIDP_VALUE_CAPS)); + if (HidP_GetValueCaps(HidP_Input, val_caps, &caps.NumberInputValueCaps, rawjoy->data) != HIDP_STATUS_SUCCESS) { + joystick_log("joystick_get_capabilities: Failed to query axes and povs.\n"); + goto end; + } + /* We only detect generic stuff */ + for (int c = 0; c < caps.NumberInputValueCaps; c++) { + if (val_caps[c].UsagePage != HID_USAGE_PAGE_GENERIC) + continue; + + if (val_caps[c].Range.UsageMin == HID_USAGE_GENERIC_HATSWITCH) + joystick_add_pov(rawjoy, joy, &val_caps[c]); + else + joystick_add_axis(rawjoy, joy, &val_caps[c]); + } + } + +end: + free(btn_caps); + free(val_caps); } - -void joystick_process(void) +void +joystick_get_device_name(raw_joystick_t *rawjoy, plat_joystick_t *joy, PRID_DEVICE_INFO info) { - int c, d; + UINT size = 0; + WCHAR *device_name = NULL; + WCHAR device_desc_wide[200] = { 0 }; - if (joystick_type == 7) return; + GetRawInputDeviceInfoW(rawjoy->hdevice, RIDI_DEVICENAME, device_name, &size); + device_name = calloc(size, sizeof(WCHAR)); + if (GetRawInputDeviceInfoW(rawjoy->hdevice, RIDI_DEVICENAME, device_name, &size) <= 0) + fatal("joystick_get_capabilities: Failed to get device name.\n"); - for (c = 0; c < joystick_get_max_joysticks(joystick_type); c++) - { - if (joystick_state[c].plat_joystick_nr) - { - int joystick_nr = joystick_state[c].plat_joystick_nr - 1; - - for (d = 0; d < joystick_get_axis_count(joystick_type); d++) - joystick_state[c].axis[d] = joystick_get_axis(joystick_nr, joystick_state[c].axis_mapping[d]); - for (d = 0; d < joystick_get_button_count(joystick_type); d++) - joystick_state[c].button[d] = plat_joystick_state[joystick_nr].b[joystick_state[c].button_mapping[d]]; + HANDLE hDevObj = CreateFileW(device_name, GENERIC_READ | GENERIC_WRITE, + FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING, 0, NULL); + if (hDevObj) { + HidD_GetProductString(hDevObj, device_desc_wide, sizeof(WCHAR) * 200); + CloseHandle(hDevObj); + } + free(device_name); - for (d = 0; d < joystick_get_pov_count(joystick_type); d++) - { - int x, y; - double angle, magnitude; - - x = joystick_get_axis(joystick_nr, joystick_state[c].pov_mapping[d][0]); - y = joystick_get_axis(joystick_nr, joystick_state[c].pov_mapping[d][1]); - - angle = (atan2((double)y, (double)x) * 360.0) / (2*M_PI); - magnitude = sqrt((double)x*(double)x + (double)y*(double)y); - - if (magnitude < 16384) - joystick_state[c].pov[d] = -1; - else - joystick_state[c].pov[d] = ((int)angle + 90 + 360) % 360; - } - } - else - { - for (d = 0; d < joystick_get_axis_count(joystick_type); d++) - joystick_state[c].axis[d] = 0; - for (d = 0; d < joystick_get_button_count(joystick_type); d++) - joystick_state[c].button[d] = 0; - for (d = 0; d < joystick_get_pov_count(joystick_type); d++) - joystick_state[c].pov[d] = -1; - } - } + int result = WideCharToMultiByte(CP_ACP, 0, device_desc_wide, 200, joy->name, 260, NULL, NULL); + if (result == 0 || strlen(joy->name) == 0) + sprintf(joy->name, + "RawInput %s, VID:%04lX PID:%04lX", + info->hid.usUsage == HID_USAGE_GENERIC_JOYSTICK ? "Joystick" : "Gamepad", + info->hid.dwVendorId, + info->hid.dwProductId); } +void +joystick_init(void) +{ + UINT size = 0; + atexit(joystick_close); + + joysticks_present = 0; + memset(raw_joystick_state, 0, sizeof(raw_joystick_t) * MAX_PLAT_JOYSTICKS); + + /* Get a list of raw input devices from Windows */ + UINT raw_devices = 0; + GetRawInputDeviceList(NULL, &raw_devices, sizeof(RAWINPUTDEVICELIST)); + PRAWINPUTDEVICELIST deviceList = calloc(raw_devices, sizeof(RAWINPUTDEVICELIST)); + GetRawInputDeviceList(deviceList, &raw_devices, sizeof(RAWINPUTDEVICELIST)); + + for (int i = 0; i < raw_devices; i++) { + PRID_DEVICE_INFO info = NULL; + + if (joysticks_present >= MAX_PLAT_JOYSTICKS) + break; + if (deviceList[i].dwType != RIM_TYPEHID) + continue; + + /* Get device info: hardware IDs and usage IDs */ + GetRawInputDeviceInfoA(deviceList[i].hDevice, RIDI_DEVICEINFO, NULL, &size); + info = malloc(size); + info->cbSize = sizeof(RID_DEVICE_INFO); + if (GetRawInputDeviceInfoA(deviceList[i].hDevice, RIDI_DEVICEINFO, info, &size) <= 0) + goto end_loop; + + /* If this is not a joystick/gamepad, skip */ + if (info->hid.usUsagePage != HID_USAGE_PAGE_GENERIC) + goto end_loop; + if (info->hid.usUsage != HID_USAGE_GENERIC_JOYSTICK && info->hid.usUsage != HID_USAGE_GENERIC_GAMEPAD) + goto end_loop; + + plat_joystick_t *joy = &plat_joystick_state[joysticks_present]; + raw_joystick_t *rawjoy = &raw_joystick_state[joysticks_present]; + rawjoy->hdevice = deviceList[i].hDevice; + + joystick_get_capabilities(rawjoy, joy); + joystick_get_device_name(rawjoy, joy, info); + + joystick_log("joystick_init: %s - %d buttons, %d axes, %d POVs\n", + joy->name, joy->nr_buttons, joy->nr_axes, joy->nr_povs); + + joysticks_present++; + +end_loop: + free(info); + } + + joystick_log("joystick_init: joysticks_present=%i\n", joysticks_present); + + /* Initialize the RawInput (joystick and gamepad) module. */ + RAWINPUTDEVICE ridev[2]; + ridev[0].dwFlags = 0; + ridev[0].hwndTarget = NULL; + ridev[0].usUsagePage = HID_USAGE_PAGE_GENERIC; + ridev[0].usUsage = HID_USAGE_GENERIC_JOYSTICK; + + ridev[1].dwFlags = 0; + ridev[1].hwndTarget = NULL; + ridev[1].usUsagePage = HID_USAGE_PAGE_GENERIC; + ridev[1].usUsage = HID_USAGE_GENERIC_GAMEPAD; + + if (!RegisterRawInputDevices(ridev, 2, sizeof(RAWINPUTDEVICE))) + fatal("plat_joystick_init: RegisterRawInputDevices failed\n"); +} + +void +joystick_close(void) +{ + RAWINPUTDEVICE ridev[2]; + ridev[0].dwFlags = RIDEV_REMOVE; + ridev[0].hwndTarget = NULL; + ridev[0].usUsagePage = HID_USAGE_PAGE_GENERIC; + ridev[0].usUsage = HID_USAGE_GENERIC_JOYSTICK; + + ridev[1].dwFlags = RIDEV_REMOVE; + ridev[1].hwndTarget = NULL; + ridev[1].usUsagePage = HID_USAGE_PAGE_GENERIC; + ridev[1].usUsage = HID_USAGE_GENERIC_GAMEPAD; + + RegisterRawInputDevices(ridev, 2, sizeof(RAWINPUTDEVICE)); +} + +void +win_joystick_handle(PRAWINPUT raw) +{ + HRESULT r; + int j = -1; /* current joystick index, -1 when not found */ + + /* If the input is not from a known device, we ignore it */ + for (int i = 0; i < joysticks_present; i++) { + if (raw_joystick_state[i].hdevice == raw->header.hDevice) { + j = i; + break; + } + } + if (j == -1) + return; + + /* Read buttons */ + USAGE usage_list[128] = { 0 }; + ULONG usage_length = plat_joystick_state[j].nr_buttons; + memset(plat_joystick_state[j].b, 0, 32 * sizeof(int)); + + r = HidP_GetUsages(HidP_Input, HID_USAGE_PAGE_BUTTON, 0, usage_list, &usage_length, + raw_joystick_state[j].data, (PCHAR) raw->data.hid.bRawData, raw->data.hid.dwSizeHid); + + if (r == HIDP_STATUS_SUCCESS) { + for (int i = 0; i < usage_length; i++) { + int button = raw_joystick_state[j].usage_button[usage_list[i]]; + plat_joystick_state[j].b[button] = 128; + } + } + + /* Read axes */ + for (int a = 0; a < plat_joystick_state[j].nr_axes; a++) { + struct raw_axis_t *axis = &raw_joystick_state[j].axis[a]; + ULONG uvalue = 0; + LONG value = 0; + LONG center = (axis->max - axis->min + 1) / 2; + + r = HidP_GetUsageValue(HidP_Input, HID_USAGE_PAGE_GENERIC, axis->link, axis->usage, &uvalue, + raw_joystick_state[j].data, (PCHAR) raw->data.hid.bRawData, raw->data.hid.dwSizeHid); + + if (r == HIDP_STATUS_SUCCESS) { + if (axis->min < 0) { + /* extend signed uvalue to LONG */ + if (uvalue & (1 << (axis->bitsize - 1))) { + ULONG mask = (1 << axis->bitsize) - 1; + value = -1U ^ mask; + value |= uvalue; + } else { + value = uvalue; + } + } else { + /* Assume unsigned when min >= 0, convert to a signed value */ + value = (LONG) uvalue - center; + } + if (abs(value) == 1) + value = 0; + value = value * 32768 / center; + } + + plat_joystick_state[j].a[a] = value; + // joystick_log("%s %-06d ", plat_joystick_state[j].axis[a].name, plat_joystick_state[j].a[a]); + } + + /* read povs */ + for (int p = 0; p < plat_joystick_state[j].nr_povs; p++) { + struct raw_pov_t *pov = &raw_joystick_state[j].pov[p]; + ULONG uvalue = 0; + LONG value = -1; + + r = HidP_GetUsageValue(HidP_Input, HID_USAGE_PAGE_GENERIC, pov->link, pov->usage, &uvalue, + raw_joystick_state[j].data, (PCHAR) raw->data.hid.bRawData, raw->data.hid.dwSizeHid); + + if (r == HIDP_STATUS_SUCCESS && (uvalue >= pov->min && uvalue <= pov->max)) { + value = (uvalue - pov->min) * 36000; + value /= (pov->max - pov->min + 1); + value %= 36000; + } + + plat_joystick_state[j].p[p] = value; + + // joystick_log("%s %-3d ", plat_joystick_state[j].pov[p].name, plat_joystick_state[j].p[p]); + } + // joystick_log("\n"); +} + +static int +joystick_get_axis(int joystick_nr, int mapping) +{ + if (mapping & POV_X) { + int pov = plat_joystick_state[joystick_nr].p[mapping & 3]; + if (LOWORD(pov) == 0xFFFF) + return 0; + else + return sin((2 * M_PI * (double) pov) / 36000.0) * 32767; + } else if (mapping & POV_Y) { + int pov = plat_joystick_state[joystick_nr].p[mapping & 3]; + + if (LOWORD(pov) == 0xFFFF) + return 0; + else + return -cos((2 * M_PI * (double) pov) / 36000.0) * 32767; + } else + return plat_joystick_state[joystick_nr].a[plat_joystick_state[joystick_nr].axis[mapping].id]; +} + +void +joystick_process(void) +{ + int d; + + if (joystick_type == JS_TYPE_NONE) + return; + + for (int c = 0; c < joystick_get_max_joysticks(joystick_type); c++) { + if (joystick_state[c].plat_joystick_nr) { + int joystick_nr = joystick_state[c].plat_joystick_nr - 1; + + for (d = 0; d < joystick_get_axis_count(joystick_type); d++) + joystick_state[c].axis[d] = joystick_get_axis(joystick_nr, joystick_state[c].axis_mapping[d]); + for (d = 0; d < joystick_get_button_count(joystick_type); d++) + joystick_state[c].button[d] = plat_joystick_state[joystick_nr].b[joystick_state[c].button_mapping[d]]; + + for (d = 0; d < joystick_get_pov_count(joystick_type); d++) { + int x; + int y; + double angle; + double magnitude; + + x = joystick_get_axis(joystick_nr, joystick_state[c].pov_mapping[d][0]); + y = joystick_get_axis(joystick_nr, joystick_state[c].pov_mapping[d][1]); + + angle = (atan2((double) y, (double) x) * 360.0) / (2 * M_PI); + magnitude = sqrt((double) x * (double) x + (double) y * (double) y); + + if (magnitude < 16384) + joystick_state[c].pov[d] = -1; + else + joystick_state[c].pov[d] = ((int) angle + 90 + 360) % 360; + } + } else { + for (d = 0; d < joystick_get_axis_count(joystick_type); d++) + joystick_state[c].axis[d] = 0; + for (d = 0; d < joystick_get_button_count(joystick_type); d++) + joystick_state[c].button[d] = 0; + for (d = 0; d < joystick_get_pov_count(joystick_type); d++) + joystick_state[c].pov[d] = -1; + } + } +} diff --git a/src/qt/wl_mouse.cpp b/src/qt/wl_mouse.cpp index 36a91b68e..5d6d95a0a 100644 --- a/src/qt/wl_mouse.cpp +++ b/src/qt/wl_mouse.cpp @@ -1,18 +1,18 @@ /* - * 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. + * 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. + * This file is part of the 86Box distribution. * - * Wayland mouse input module. + * Wayland mouse input module. * * * - * Authors: Cacodemon345 + * Authors: Cacodemon345 * - * Copyright 2021-2022 Cacodemon345 + * Copyright 2021-2022 Cacodemon345 */ #include "wl_mouse.hpp" #include @@ -25,34 +25,25 @@ #include #include -static zwp_relative_pointer_manager_v1* rel_manager = nullptr; -static zwp_relative_pointer_v1* rel_pointer = nullptr; -static zwp_pointer_constraints_v1* conf_pointer_interface = nullptr; -static zwp_locked_pointer_v1* conf_pointer = nullptr; - -static int rel_mouse_x = 0, rel_mouse_y = 0; - -void rel_mouse_event(void* data, zwp_relative_pointer_v1* zwp_relative_pointer_v1, uint32_t tstmp, uint32_t tstmpl, wl_fixed_t dx, wl_fixed_t dy, wl_fixed_t dx_real, wl_fixed_t dy_real) -{ - rel_mouse_x += wl_fixed_to_int(dx_real); - rel_mouse_y += wl_fixed_to_int(dy_real); +extern "C" { +#include <86box/mouse.h> +#include <86box/plat.h> } -extern "C" +static zwp_relative_pointer_manager_v1 *rel_manager = nullptr; +static zwp_relative_pointer_v1 *rel_pointer = nullptr; +static zwp_pointer_constraints_v1 *conf_pointer_interface = nullptr; +static zwp_locked_pointer_v1 *conf_pointer = nullptr; + +static bool wl_init_ok = false; + +void +rel_mouse_event(void *data, zwp_relative_pointer_v1 *zwp_relative_pointer_v1, uint32_t tstmp, uint32_t tstmpl, wl_fixed_t dx, wl_fixed_t dy, wl_fixed_t dx_real, wl_fixed_t dy_real) { - extern int mouse_x, mouse_y; + mouse_scale(wl_fixed_to_int(dx_real), wl_fixed_to_int(dy_real)); } -void wl_mouse_poll() -{ - mouse_x = rel_mouse_x; - mouse_y = rel_mouse_y; - rel_mouse_x = 0; - rel_mouse_y = 0; -} - -static struct zwp_relative_pointer_v1_listener rel_listener = -{ +static struct zwp_relative_pointer_v1_listener rel_listener = { rel_mouse_event }; @@ -60,46 +51,63 @@ static void display_handle_global(void *data, struct wl_registry *registry, uint32_t id, const char *interface, uint32_t version) { - if (!strcmp(interface, "zwp_relative_pointer_manager_v1")) - { - rel_manager = (zwp_relative_pointer_manager_v1*)wl_registry_bind(registry, id, &zwp_relative_pointer_manager_v1_interface, version); + if (!strcmp(interface, "zwp_relative_pointer_manager_v1")) { + rel_manager = (zwp_relative_pointer_manager_v1 *) wl_registry_bind(registry, id, &zwp_relative_pointer_manager_v1_interface, version); } - if (!strcmp(interface, "zwp_pointer_constraints_v1")) - { - conf_pointer_interface = (zwp_pointer_constraints_v1*)wl_registry_bind(registry, id, &zwp_pointer_constraints_v1_interface, version); + if (!strcmp(interface, "zwp_pointer_constraints_v1")) { + conf_pointer_interface = (zwp_pointer_constraints_v1 *) wl_registry_bind(registry, id, &zwp_pointer_constraints_v1_interface, version); } } +static void +display_global_remove(void *data, struct wl_registry *wl_registry, uint32_t name) +{ + plat_mouse_capture(0); + zwp_relative_pointer_manager_v1_destroy(rel_manager); + zwp_pointer_constraints_v1_destroy(conf_pointer_interface); + rel_manager = nullptr; + conf_pointer_interface = nullptr; +} + static const struct wl_registry_listener registry_listener = { display_handle_global, - nullptr + display_global_remove }; -void wl_init() +void +wl_init() { - wl_display* display = (wl_display*)QGuiApplication::platformNativeInterface()->nativeResourceForIntegration("wl_display"); - if (display) - { - auto registry = wl_display_get_registry(display); - if (registry) - { - wl_registry_add_listener(registry, ®istry_listener, nullptr); - wl_display_roundtrip(display); + if (!wl_init_ok) { + wl_display *display = (wl_display *) QGuiApplication::platformNativeInterface()->nativeResourceForIntegration("wl_display"); + if (display) { + auto registry = wl_display_get_registry(display); + if (registry) { + wl_registry_add_listener(registry, ®istry_listener, nullptr); + wl_display_roundtrip(display); + } } + wl_init_ok = true; } } -void wl_mouse_capture(QWindow *window) +void +wl_mouse_capture(QWindow *window) { - rel_pointer = zwp_relative_pointer_manager_v1_get_relative_pointer(rel_manager, (wl_pointer*)QGuiApplication::platformNativeInterface()->nativeResourceForIntegration("wl_pointer")); - zwp_relative_pointer_v1_add_listener(rel_pointer, &rel_listener, nullptr); - conf_pointer = zwp_pointer_constraints_v1_lock_pointer(conf_pointer_interface, (wl_surface*)QGuiApplication::platformNativeInterface()->nativeResourceForWindow("surface", window), (wl_pointer*)QGuiApplication::platformNativeInterface()->nativeResourceForIntegration("wl_pointer"), nullptr, ZWP_POINTER_CONSTRAINTS_V1_LIFETIME_PERSISTENT); + if (rel_manager) { + rel_pointer = zwp_relative_pointer_manager_v1_get_relative_pointer(rel_manager, (wl_pointer *) QGuiApplication::platformNativeInterface()->nativeResourceForIntegration("wl_pointer")); + zwp_relative_pointer_v1_add_listener(rel_pointer, &rel_listener, nullptr); + } + if (conf_pointer_interface) + conf_pointer = zwp_pointer_constraints_v1_lock_pointer(conf_pointer_interface, (wl_surface *) QGuiApplication::platformNativeInterface()->nativeResourceForWindow("surface", window), (wl_pointer *) QGuiApplication::platformNativeInterface()->nativeResourceForIntegration("wl_pointer"), nullptr, ZWP_POINTER_CONSTRAINTS_V1_LIFETIME_PERSISTENT); } -void wl_mouse_uncapture() +void +wl_mouse_uncapture() { - zwp_locked_pointer_v1_destroy(conf_pointer); - zwp_relative_pointer_v1_destroy(rel_pointer); - rel_pointer = nullptr; + if (conf_pointer) + zwp_locked_pointer_v1_destroy(conf_pointer); + if (rel_pointer) + zwp_relative_pointer_v1_destroy(rel_pointer); + rel_pointer = nullptr; conf_pointer = nullptr; } diff --git a/src/qt/wl_mouse.hpp b/src/qt/wl_mouse.hpp index 73e81c208..e1751fd82 100644 --- a/src/qt/wl_mouse.hpp +++ b/src/qt/wl_mouse.hpp @@ -1,5 +1,4 @@ class QWindow; -void wl_mouse_capture(QWindow* window); +void wl_mouse_capture(QWindow *window); void wl_mouse_uncapture(); -void wl_mouse_poll(); -void wl_init(); \ No newline at end of file +void wl_init(); diff --git a/src/qt/xinput2_mouse.cpp b/src/qt/xinput2_mouse.cpp index ff67b6a2c..1be6ec826 100644 --- a/src/qt/xinput2_mouse.cpp +++ b/src/qt/xinput2_mouse.cpp @@ -1,21 +1,22 @@ /* - * 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. + * 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. + * This file is part of the 86Box distribution. * - * X11 Xinput2 mouse input module. + * X11 Xinput2 mouse input module. * * * - * Authors: Cacodemon345 + * Authors: Cacodemon345 + * RichardG * - * Copyright 2022 Cacodemon345 + * Copyright 2022 Cacodemon345. + * Copyright 2023 RichardG. */ -/* Valuator parsing and duplicate event checking code from SDL2. */ #include #include #include @@ -23,7 +24,7 @@ #include #include "qt_mainwindow.hpp" -extern MainWindow* main_window; +extern MainWindow *main_window; #include #include @@ -31,8 +32,7 @@ extern MainWindow* main_window; #include -extern "C" -{ +extern "C" { #include #include #include @@ -44,31 +44,31 @@ extern "C" #include <86box/plat.h> } -int xi2flides[2] = { 0, 0 }; +static Display *disp = nullptr; +static QThread *procThread = nullptr; +static XIEventMask ximask; +static std::atomic exitfromthread = false; +static std::atomic xi2_mouse_abs_x = 0, xi2_mouse_abs_y = 0; +static int xi2opcode = 0; +static double prev_coords[2] = { 0.0 }; +static Time prev_time = 0; -static Display* disp = nullptr; -static QThread* procThread = nullptr; -static bool xi2childinit = false; -static XIEventMask ximask; -static std::atomic exitfromthread = false; -static std::atomic xi2_mouse_x = 0, xi2_mouse_y = 0, xi2_mouse_abs_x = 0, xi2_mouse_abs_y = 0; -static int xi2opcode = 0; -static double prev_rel_coords[2] = { 0., 0. }; -static Time prev_time = 0; - -// From SDL2. -static void parse_valuators(const double *input_values, const unsigned char *mask,int mask_len, - double *output_values,int output_values_len) { - int i = 0,z = 0; +/* Based on SDL2. */ +static void +parse_valuators(const double *input_values, + const unsigned char *mask, int mask_len, + double *output_values, int output_values_len) +{ + int i = 0; + int z = 0; int top = mask_len * 8; if (top > 16) top = 16; - memset(output_values,0,output_values_len * sizeof(double)); + memset(output_values, 0, output_values_len * sizeof(output_values[0])); for (; i < top && z < output_values_len; i++) { if (XIMaskIsSet(mask, i)) { - const int value = (int) *input_values; - output_values[z] = value; + output_values[z] = *input_values; input_values++; } z++; @@ -77,112 +77,199 @@ static void parse_valuators(const double *input_values, const unsigned char *mas static bool exitthread = false; -void xinput2_proc() +static int +xinput2_get_xtest_pointer() +{ + /* The XTEST pointer events injected by VNC servers to move the cursor always report + absolute coordinates, despite XTEST declaring relative axes (related: SDL issue 1836). + This looks for the XTEST pointer so that we can assume it's absolute as a workaround. + + TigerVNC publishes both the XTEST pointer and a TigerVNC pointer, but actual + RawMotion events are published using the TigerVNC pointer */ + int devs; + XIDeviceInfo *info = XIQueryDevice(disp, XIAllDevices, &devs), *dev; + for (int i = 0; i < devs; i++) { + dev = &info[i]; + if ((dev->use == XISlavePointer) && !strcmp(dev->name, "TigerVNC pointer")) + return dev->deviceid; + } + /* Steam Input on SteamOS uses XTEST the intended way for trackpad movement. + Hope nobody is remoting into their Steam Deck with a non-TigerVNC server. */ + for (int i = 0; i < devs; i++) { + dev = &info[i]; + if ((dev->use == XISlavePointer) && !strncmp(dev->name, "Valve Software Steam Deck", 25)) + return -1; + } + for (int i = 0; i < devs; i++) { + dev = &info[i]; + if ((dev->use == XISlavePointer) && !strcmp(dev->name, "Virtual core XTEST pointer")) + return dev->deviceid; + } + return -1; +} + +void +xinput2_proc() { Window win; win = DefaultRootWindow(disp); - // XIAllMasterDevices doesn't work for click-and-drag operations. - ximask.deviceid = XIAllDevices; - ximask.mask_len = XIMaskLen(XI_LASTEVENT); - ximask.mask = (unsigned char*)calloc(ximask.mask_len, sizeof(unsigned char)); + int xtest_pointer = xinput2_get_xtest_pointer(); + + ximask.deviceid = XIAllMasterDevices; + ximask.mask_len = XIMaskLen(XI_LASTEVENT); + ximask.mask = (unsigned char *) calloc(ximask.mask_len, sizeof(unsigned char)); - XISetMask(ximask.mask, XI_RawKeyPress); - XISetMask(ximask.mask, XI_RawKeyRelease); - XISetMask(ximask.mask, XI_RawButtonPress); - XISetMask(ximask.mask, XI_RawButtonRelease); XISetMask(ximask.mask, XI_RawMotion); - if (XKeysymToKeycode(disp, XK_Home) == 69) XISetMask(ximask.mask, XI_Motion); + XISetMask(ximask.mask, XI_Motion); + XISetMask(ximask.mask, XI_DeviceChanged); XISelectEvents(disp, win, &ximask, 1); XSync(disp, False); - while(true) - { - XEvent ev; - XGenericEventCookie *cookie = (XGenericEventCookie*)&ev.xcookie; - XNextEvent(disp, (XEvent*)&ev); + while (true) { + XEvent ev; + XGenericEventCookie *cookie = (XGenericEventCookie *) &ev.xcookie; + XNextEvent(disp, (XEvent *) &ev); + + if (XGetEventData(disp, cookie) && (cookie->type == GenericEvent) && (cookie->extension == xi2opcode)) { + const XIRawEvent *rawev = (const XIRawEvent *) cookie->data; + double coords[2] = { 0.0 }; - if (XGetEventData(disp, cookie) && cookie->type == GenericEvent && cookie->extension == xi2opcode) { switch (cookie->evtype) { - case XI_RawMotion: { - static int ss = 0; - const XIRawEvent *rawev = (const XIRawEvent*)cookie->data; - double relative_coords[2] = { 0., 0. }; - parse_valuators(rawev->raw_values,rawev->valuators.mask, - rawev->valuators.mask_len,relative_coords,2); + case XI_Motion: + { + const XIDeviceEvent *devev = (const XIDeviceEvent *) cookie->data; + parse_valuators(devev->valuators.values, devev->valuators.mask, devev->valuators.mask_len, coords, 2); - if ((rawev->time == prev_time) && (relative_coords[0] == prev_rel_coords[0]) && (relative_coords[1] == prev_rel_coords[1])) { - break; // Ignore duplicated events. + /* XIDeviceEvent and XIRawEvent share the XIEvent base struct, which + doesn't contain deviceid, but that's at the same offset on both. */ + goto common_motion; } - xi2_mouse_x = xi2_mouse_x + relative_coords[0]; - xi2_mouse_y = xi2_mouse_y + relative_coords[1]; - prev_rel_coords[0] = relative_coords[0]; - prev_rel_coords[1] = relative_coords[1]; - prev_time = rawev->time; - } - case XI_Motion: { - if (XKeysymToKeycode(disp, XK_Home) == 69) { - // No chance we will get raw motion events on VNC. - const XIDeviceEvent *motionev = (const XIDeviceEvent*)cookie->data; - if (xi2_mouse_abs_x != 0 || xi2_mouse_abs_y != 0) { - xi2_mouse_x = xi2_mouse_x + (motionev->event_x - xi2_mouse_abs_x); - xi2_mouse_y = xi2_mouse_y + (motionev->event_y - xi2_mouse_abs_y); + + case XI_RawMotion: + { + parse_valuators(rawev->raw_values, rawev->valuators.mask, rawev->valuators.mask_len, coords, 2); +common_motion: + /* Ignore duplicated events. */ + if ((rawev->time == prev_time) && (coords[0] == prev_coords[0]) && (coords[1] == prev_coords[1])) + break; + + /* SDL2 queries the device on every event, so doing that should be fine. */ + int i; + XIDeviceInfo *xidevinfo = XIQueryDevice(disp, rawev->deviceid, &i); + if (xidevinfo) { + /* Process the device's axes. */ + int axis = 0; + for (i = 0; i < xidevinfo->num_classes; i++) { + const XIValuatorClassInfo *v = (const XIValuatorClassInfo *) xidevinfo->classes[i]; + if (v->type == XIValuatorClass) { + /* Is this an absolute or relative axis? */ + if ((v->mode == XIModeRelative) && (rawev->sourceid != xtest_pointer)) { + /* Set relative coordinates. */ + if (axis == 0) + mouse_scale_x(coords[axis]); + else + mouse_scale_y(coords[axis]); + } else { + /* Convert absolute value range to pixel granularity, then to relative coordinates. */ + int disp_screen = XDefaultScreen(disp); + double abs_div; + if (axis == 0) { + if (v->mode == XIModeRelative) { + /* XTEST axes have dummy min/max values because they're nominally relative, + but in practice, the injected absolute coordinates are already in pixels. */ + abs_div = coords[axis]; + } else { + abs_div = (v->max - v->min) / (double) XDisplayWidth(disp, disp_screen); + if (abs_div <= 0) + abs_div = 1; + abs_div = (coords[axis] - v->min) / abs_div; + } + + if (xi2_mouse_abs_x != 0) + mouse_scale_x(abs_div - xi2_mouse_abs_x); + xi2_mouse_abs_x = abs_div; + } else { + if (v->mode == XIModeRelative) { + /* Same as above. */ + abs_div = coords[axis]; + } else { + abs_div = (v->max - v->min) / (double) XDisplayHeight(disp, disp_screen); + if (abs_div <= 0) + abs_div = 1; + abs_div = (coords[axis] - v->min) / abs_div; + } + + if (xi2_mouse_abs_y != 0) + mouse_scale_y(abs_div - xi2_mouse_abs_y); + xi2_mouse_abs_y = abs_div; + } + } + prev_coords[axis] = coords[axis]; + if (++axis >= 2) /* stop after X and Y processed */ + break; + } + } } - xi2_mouse_abs_x = motionev->event_x; - xi2_mouse_abs_y = motionev->event_y; + + prev_time = rawev->time; + if (!mouse_capture) + break; + XWindowAttributes winattrib {}; + if (XGetWindowAttributes(disp, main_window->winId(), &winattrib)) { + auto globalPoint = main_window->mapToGlobal(QPoint(main_window->width() / 2, main_window->height() / 2)); + XWarpPointer(disp, XRootWindow(disp, XScreenNumberOfScreen(winattrib.screen)), XRootWindow(disp, XScreenNumberOfScreen(winattrib.screen)), 0, 0, 0, 0, globalPoint.x(), globalPoint.y()); + XFlush(disp); + } + + break; + } + + case XI_DeviceChanged: + { + /* Re-scan for XTEST pointer, just in case. */ + xtest_pointer = xinput2_get_xtest_pointer(); + + break; } - } } } XFreeEventData(disp, cookie); - if (exitthread) break; + if (exitthread) + break; } XCloseDisplay(disp); } -void xinput2_exit() +void +xinput2_exit() { - exitthread = true; - procThread->wait(5000); - procThread->terminate(); + if (!exitthread) { + exitthread = true; + procThread->wait(5000); + procThread->terminate(); + } } -void xinput2_init() +void +xinput2_init() { disp = XOpenDisplay(nullptr); - if (!disp) - { + if (!disp) { qWarning() << "Cannot open current X11 display"; return; } - auto event = 0, err = 0, minor = 0, major = 2; - if (XQueryExtension(disp, "XInputExtension", &xi2opcode, &event, &err)) - { - if (XIQueryVersion(disp, &major, &minor) == Success) - { + auto event = 0; + auto err = 0; + auto minor = 1; + auto major = 2; + if (XQueryExtension(disp, "XInputExtension", &xi2opcode, &event, &err)) { + if (XIQueryVersion(disp, &major, &minor) == Success) { procThread = QThread::create(xinput2_proc); procThread->start(); atexit(xinput2_exit); } } } - -void xinput2_poll() -{ - if (procThread && mouse_capture) - { - mouse_x = xi2_mouse_x; - mouse_y = xi2_mouse_y; - XWindowAttributes winattrib{}; - if (XGetWindowAttributes(disp, main_window->winId(), &winattrib)) - { - auto globalPoint = main_window->mapToGlobal(QPoint(main_window->width() / 2, main_window->height() / 2)); - XWarpPointer(disp, XRootWindow(disp, XScreenNumberOfScreen(winattrib.screen)), XRootWindow(disp, XScreenNumberOfScreen(winattrib.screen)), 0, 0, 0, 0, globalPoint.x(), globalPoint.y()); - XFlush(disp); - } - } - xi2_mouse_x = 0; - xi2_mouse_y = 0; -} diff --git a/src/qt/xkbcommon_keyboard.cpp b/src/qt/xkbcommon_keyboard.cpp new file mode 100644 index 000000000..969552229 --- /dev/null +++ b/src/qt/xkbcommon_keyboard.cpp @@ -0,0 +1,240 @@ +/* + * 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. + * + * xkbcommon keyboard input module. + * + * + * + * Authors: RichardG, + * + * Copyright 2023 RichardG. + */ +extern "C" { +#include +}; + +#include +#include +#include "evdev_keyboard.hpp" + +#define IS_DEC_DIGIT(c) (((c) >= '0') && ((c) <= '9')) +#define IS_HEX_DIGIT(c) (IS_DEC_DIGIT(c) || (((c) >= 'A') && ((c) <= 'F')) || (((c) >= 'a') && ((c) <= 'f'))) + +static std::unordered_map xkb_keycodes = { + {"ESC", 0x01}, + {"AE01", 0x02}, + {"AE02", 0x03}, + {"AE03", 0x04}, + {"AE04", 0x05}, + {"AE05", 0x06}, + {"AE06", 0x07}, + {"AE07", 0x08}, + {"AE08", 0x09}, + {"AE09", 0x0a}, + {"AE10", 0x0b}, + {"AE11", 0x0c}, + {"AE12", 0x0d}, + {"BKSP", 0x0e}, + + {"TAB", 0x0f}, + {"AD01", 0x10}, + {"AD02", 0x11}, + {"AD03", 0x12}, + {"AD04", 0x13}, + {"AD05", 0x14}, + {"AD06", 0x15}, + {"AD07", 0x16}, + {"AD08", 0x17}, + {"AD09", 0x18}, + {"AD10", 0x19}, + {"AD11", 0x1a}, + {"AD12", 0x1b}, + {"RTRN", 0x1c}, + {"LNFD", 0x1c}, /* linefeed => Enter */ + + {"LCTL", 0x1d}, + {"CTRL", 0x1d}, + {"AC01", 0x1e}, + {"AC02", 0x1f}, + {"AC03", 0x20}, + {"AC04", 0x21}, + {"AC05", 0x22}, + {"AC06", 0x23}, + {"AC07", 0x24}, + {"AC08", 0x25}, + {"AC09", 0x26}, + {"AC10", 0x27}, + {"AC11", 0x28}, + + {"TLDE", 0x29}, + {"AE00", 0x29}, /* alias of TLDE on keycodes/xfree86 (i.e. X11 forwarding) */ + {"LFSH", 0x2a}, + {"BKSL", 0x2b}, + {"AC12", 0x2b}, + {"AB01", 0x2c}, + {"AB02", 0x2d}, + {"AB03", 0x2e}, + {"AB04", 0x2f}, + {"AB05", 0x30}, + {"AB06", 0x31}, + {"AB07", 0x32}, + {"AB08", 0x33}, + {"AB09", 0x34}, + {"AB10", 0x35}, + {"RTSH", 0x36}, + + {"KPMU", 0x37}, + {"LALT", 0x38}, + {"ALT", 0x38}, + {"SPCE", 0x39}, + {"CAPS", 0x3a}, + {"FK01", 0x3b}, + {"FK02", 0x3c}, + {"FK03", 0x3d}, + {"FK04", 0x3e}, + {"FK05", 0x3f}, + {"FK06", 0x40}, + {"FK07", 0x41}, + {"FK08", 0x42}, + {"FK09", 0x43}, + {"FK10", 0x44}, + + {"NMLK", 0x45}, + {"SCLK", 0x46}, + {"FK14", 0x46}, /* F14 => Scroll Lock (for Apple keyboards) */ + {"KP7", 0x47}, + {"KP8", 0x48}, + {"KP9", 0x49}, + {"KPSU", 0x4a}, + {"KP4", 0x4b}, + {"KP5", 0x4c}, + {"KP6", 0x4d}, + {"KPAD", 0x4e}, + {"KP1", 0x4f}, + {"KP2", 0x50}, + {"KP3", 0x51}, + {"KP0", 0x52}, + {"KPDL", 0x53}, + + {"LSGT", 0x56}, + {"FK11", 0x57}, + {"FK12", 0x58}, + {"FK16", 0x5d}, /* F16 => F13 */ + {"FK17", 0x5e}, /* F17 => F14 */ + {"FK18", 0x5f}, /* F18 => F15 */ + + /* Japanese keys. */ + {"JPCM", 0x5c}, /* Num, */ + {"KPDC", 0x5c}, + {"HKTG", 0x70}, /* hiragana-katakana toggle */ + {"AB11", 0x73}, /* \_ and Brazilian /? */ + {"HZTG", 0x76}, /* hankaku-zenkaku toggle */ + {"HIRA", 0x77}, + {"KATA", 0x78}, + {"HENK", 0x79}, + {"KANA", 0x79}, /* kana => henkan (for Apple keyboards) */ + {"MUHE", 0x7b}, + {"EISU", 0x7b}, /* eisu => muhenkan (for Apple keyboards) */ + {"AE13", 0x7d}, /* \| */ + {"KPPT", 0x7e}, /* Brazilian Num. */ + {"I06", 0x7e}, /* alias of KPPT on keycodes/xfree86 (i.e. X11 forwarding) */ + + /* Korean keys. */ + {"HJCV", 0xf1}, /* hancha toggle */ + {"HNGL", 0xf2}, /* latin toggle */ + + {"KPEN", 0x11c}, + {"RCTL", 0x11d}, + {"KPDV", 0x135}, + {"PRSC", 0x137}, + {"SYRQ", 0x137}, + {"FK13", 0x137}, /* F13 => SysRq (for Apple keyboards) */ + {"RALT", 0x138}, + {"ALGR", 0x138}, + {"LVL3", 0x138}, /* observed on TigerVNC with AltGr-enabled layout */ + {"PAUS", 0x145}, + {"FK15", 0x145}, /* F15 => Pause (for Apple keyboards) */ + {"BRK", 0x145}, + {"HOME", 0x147}, + {"UP", 0x148}, + {"PGUP", 0x149}, + {"LEFT", 0x14b}, + {"RGHT", 0x14d}, + {"END", 0x14f}, + {"DOWN", 0x150}, + {"PGDN", 0x151}, + {"INS", 0x152}, + {"DELE", 0x153}, + + {"LWIN", 0x15b}, + {"WIN", 0x15b}, + {"LMTA", 0x15b}, + {"META", 0x15b}, + {"RWIN", 0x15c}, + {"RMTA", 0x15c}, + {"MENU", 0x15d}, + {"COMP", 0x15d}, /* Compose as Menu */ + + /* Multimedia keys. Same notes as evdev_keyboard apply here. */ + {"KPEQ", 0x59}, /* Num= */ + {"FRNT", 0x101}, /* # Logitech Task Select */ + {"UNDO", 0x108}, /* # */ + {"PAST", 0x10a}, /* # Paste */ + {"FIND", 0x112}, /* # Logitech */ + {"CUT", 0x117}, /* # */ + {"COPY", 0x118}, /* # */ + {"MUTE", 0x120}, + {"VOL-", 0x12e}, + {"VOL+", 0x130}, + {"HELP", 0x13b}, + {"OPEN", 0x13f}, + {"POWR", 0x15e}, + {"STOP", 0x168}, +}; +struct xkb_keymap *xkbcommon_keymap = nullptr; + +void +xkbcommon_init(struct xkb_keymap *keymap) +{ + if (keymap) + xkbcommon_keymap = keymap; +} + +void +xkbcommon_close() +{ + xkbcommon_keymap = nullptr; +} + +uint16_t +xkbcommon_translate(uint32_t keycode) +{ + const char *key_name = xkb_keymap_key_get_name(xkbcommon_keymap, keycode); + + /* If XKB doesn't know the key name for this keycode, assume an unnamed Ixxx key. + This is useful for older XKB versions with an incomplete evdev keycode map. */ + auto key_name_s = key_name ? std::string(key_name) : QString("I%1").arg(keycode).toStdString(); + auto ret = xkb_keycodes[key_name_s]; + + /* Observed with multimedia keys on Windows VcXsrv. */ + if (!ret && (key_name_s.length() == 3) && (key_name_s[0] == 'I') && IS_HEX_DIGIT(key_name_s[1]) && IS_HEX_DIGIT(key_name_s[2])) + ret = 0x100 | stoi(key_name_s.substr(1), nullptr, 16); + + /* Translate unnamed evdev-specific keycodes. */ + if (!ret && (key_name_s.length() >= 2) && (key_name_s[0] == 'I') && IS_DEC_DIGIT(key_name_s[1])) + ret = evdev_translate(stoi(key_name_s.substr(1)) - 8); + + if (!ret) + qWarning() << "XKB Keyboard: Unknown key" << QString::number(keycode, 16) << QString::fromStdString(key_name_s); +#if 0 + else + qInfo() << "XKB Keyboard: Key" << QString::number(keycode, 16) << QString::fromStdString(key_name_s) << "scancode" << QString::number(ret, 16); +#endif + + return ret; +} diff --git a/src/qt/xkbcommon_keyboard.hpp b/src/qt/xkbcommon_keyboard.hpp new file mode 100644 index 000000000..c3b28eeec --- /dev/null +++ b/src/qt/xkbcommon_keyboard.hpp @@ -0,0 +1,20 @@ +/* + * 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. + * + * Definitions for xkbcommon keyboard input module. + * + * + * + * Authors: RichardG, + * + * Copyright 2023 RichardG. + */ +extern void *xkbcommon_keymap; +void xkbcommon_init(struct xkb_keymap *keymap); +void xkbcommon_close(); +uint16_t xkbcommon_translate(uint32_t keycode); diff --git a/src/qt/xkbcommon_wl_keyboard.cpp b/src/qt/xkbcommon_wl_keyboard.cpp new file mode 100644 index 000000000..8b7e6399a --- /dev/null +++ b/src/qt/xkbcommon_wl_keyboard.cpp @@ -0,0 +1,243 @@ +/* + * 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. + * + * xkbcommon Wayland keyboard input module. + * + * Heavily inspired by libxkbcommon interactive-wayland.c + * + * + * + * Authors: RichardG, + * + * Copyright 2023 RichardG. + */ +extern "C" { +#include +#include +#include +#include <86box/86box.h> +}; +#include "xkbcommon_keyboard.hpp" +#include +#include + +#include +#include +#include + +typedef struct { + struct wl_seat *wl_seat; + struct wl_keyboard *wl_kbd; + uint32_t version; + + struct xkb_keymap *keymap; + + struct wl_list link; +} seat_t; + +static bool wl_init_ok = false; +static struct wl_list seats; +static struct xkb_context *ctx; + +static void +xkbcommon_wl_set_keymap() +{ + /* Grab keymap from the first seat with one. */ + seat_t *seat; + seat_t *tmp; + wl_list_for_each_safe(seat, tmp, &seats, link) { + if (seat->keymap) { + xkbcommon_init(seat->keymap); + return; + } + } + xkbcommon_close(); /* none found */ +} + +static void +kbd_keymap(void *data, struct wl_keyboard *wl_kbd, uint32_t format, + int fd, uint32_t size) +{ + seat_t *seat = (seat_t *) data; + + char *buf = (char *) mmap(NULL, size, PROT_READ, MAP_SHARED, fd, 0); + if (!buf) { + qWarning() << "XKB Keyboard: Failed to mmap keymap with error" << errno; + return; + } + + if (seat->keymap) { + struct xkb_keymap *keymap = seat->keymap; + seat->keymap = NULL; + xkbcommon_wl_set_keymap(); + xkb_keymap_unref(keymap); + } + + seat->keymap = xkb_keymap_new_from_buffer(ctx, buf, size - 1, + XKB_KEYMAP_FORMAT_TEXT_V1, + XKB_KEYMAP_COMPILE_NO_FLAGS); + munmap(buf, size); + close(fd); + if (!seat->keymap) + qWarning() << "XKB Keyboard: Keymap compilation failed"; + + xkbcommon_wl_set_keymap(); +} + +static void +kbd_enter(void *data, struct wl_keyboard *wl_kbd, uint32_t serial, + struct wl_surface *surf, struct wl_array *keys) +{ +} + +static void +kbd_leave(void *data, struct wl_keyboard *wl_kbd, uint32_t serial, + struct wl_surface *surf) +{ +} + +static void +kbd_key(void *data, struct wl_keyboard *wl_kbd, uint32_t serial, uint32_t time, + uint32_t key, uint32_t state) +{ +} + +static void +kbd_modifiers(void *data, struct wl_keyboard *wl_kbd, uint32_t serial, + uint32_t mods_depressed, uint32_t mods_latched, + uint32_t mods_locked, uint32_t group) +{ +} + +static void +kbd_repeat_info(void *data, struct wl_keyboard *wl_kbd, int32_t rate, + int32_t delay) +{ +} + +static const struct wl_keyboard_listener kbd_listener = { + kbd_keymap, + kbd_enter, + kbd_leave, + kbd_key, + kbd_modifiers, + kbd_repeat_info +}; + +static void +seat_capabilities(void *data, struct wl_seat *wl_seat, uint32_t caps) +{ + seat_t *seat = (seat_t *) data; + + if (!seat->wl_kbd && (caps & WL_SEAT_CAPABILITY_KEYBOARD)) { + seat->wl_kbd = wl_seat_get_keyboard(seat->wl_seat); + wl_keyboard_add_listener(seat->wl_kbd, &kbd_listener, seat); + } else if (seat->wl_kbd && !(caps & WL_SEAT_CAPABILITY_KEYBOARD)) { + if (seat->version >= WL_SEAT_RELEASE_SINCE_VERSION) + wl_keyboard_release(seat->wl_kbd); + else + wl_keyboard_destroy(seat->wl_kbd); + + struct xkb_keymap *keymap = seat->keymap; + seat->keymap = NULL; + xkbcommon_wl_set_keymap(); + xkb_keymap_unref(keymap); + + seat->wl_kbd = NULL; + } +} + +static void +seat_name(void *data, struct wl_seat *wl_seat, const char *name) +{ +} + +static const struct wl_seat_listener seat_listener = { + seat_capabilities, + seat_name +}; + +static void +display_handle_global(void *data, struct wl_registry *wl_registry, uint32_t id, + const char *interface, uint32_t version) +{ + if (!strcmp(interface, "wl_seat")) { + seat_t *seat = (seat_t *) malloc(sizeof(seat_t)); + memset(seat, 0, sizeof(seat_t)); + + seat->wl_seat = (wl_seat *) wl_registry_bind(wl_registry, id, &wl_seat_interface, MIN(version, 5)); + wl_seat_add_listener(seat->wl_seat, &seat_listener, seat); + wl_list_insert(&seats, &seat->link); + } +} + +static void +display_global_remove(void *data, struct wl_registry *wl_registry, uint32_t id) +{ + xkbcommon_close(); + + seat_t *seat; + seat_t *tmp; + wl_list_for_each_safe(seat, tmp, &seats, link) { + if (seat->wl_kbd) { + if (seat->version >= WL_SEAT_RELEASE_SINCE_VERSION) + wl_keyboard_release(seat->wl_kbd); + else + wl_keyboard_destroy(seat->wl_kbd); + + xkb_keymap_unref(seat->keymap); + } + + if (seat->version >= WL_SEAT_RELEASE_SINCE_VERSION) + wl_seat_release(seat->wl_seat); + else + wl_seat_destroy(seat->wl_seat); + + wl_list_remove(&seat->link); + free(seat); + } +} + +static const struct wl_registry_listener registry_listener = { + display_handle_global, + display_global_remove +}; + +void +xkbcommon_wl_init() +{ + if (wl_init_ok) + return; + + wl_list_init(&seats); + + ctx = xkb_context_new(XKB_CONTEXT_NO_FLAGS); + if (!ctx) { + qWarning() << "XKB Keyboard: XKB context creation failed"; + return; + } + + wl_display *display = (wl_display *) QGuiApplication::platformNativeInterface()->nativeResourceForIntegration("wl_display"); + if (display) { + auto registry = wl_display_get_registry(display); + if (registry) { + wl_registry_add_listener(registry, ®istry_listener, nullptr); + wl_display_roundtrip(display); + wl_display_roundtrip(display); + } else { + goto err_ctx; + } + } else { + goto err_ctx; + } + wl_init_ok = true; + return; + +err_ctx: + xkb_context_unref(ctx); +} diff --git a/src/qt/xkbcommon_wl_keyboard.hpp b/src/qt/xkbcommon_wl_keyboard.hpp new file mode 100644 index 000000000..a70cb9e9b --- /dev/null +++ b/src/qt/xkbcommon_wl_keyboard.hpp @@ -0,0 +1,17 @@ +/* + * 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. + * + * Definitions for xkbcommon Wayland keyboard input module. + * + * + * + * Authors: RichardG, + * + * Copyright 2023 RichardG. + */ +void xkbcommon_wl_init(); diff --git a/src/qt/xkbcommon_x11_keyboard.cpp b/src/qt/xkbcommon_x11_keyboard.cpp new file mode 100644 index 000000000..8e0167518 --- /dev/null +++ b/src/qt/xkbcommon_x11_keyboard.cpp @@ -0,0 +1,86 @@ +/* + * 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. + * + * xkbcommon-x11 keyboard input module. + * + * Heavily inspired by libxkbcommon interactive-x11.c + * + * + * + * Authors: RichardG, + * + * Copyright 2023 RichardG. + */ +extern "C" { +/* xkb.h has identifiers named "explicit", which is a C++ keyword now... */ +#ifdef __clang__ +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wkeyword-macro" +#endif +#define explicit explicit_ +#ifdef __clang__ +#pragma clang diagnostic pop +#endif +#include +#undef explicit + +#include +}; +#include "xkbcommon_keyboard.hpp" + +#include +#include +#include + +void +xkbcommon_x11_init() +{ + xcb_connection_t *conn; + struct xkb_context *ctx; + int32_t core_kbd_device_id; + struct xkb_keymap *keymap; + + conn = (xcb_connection_t *) QGuiApplication::platformNativeInterface()->nativeResourceForIntegration("connection"); + if (!conn) { + qWarning() << "XKB Keyboard: X server connection failed"; + return; + } + + int ret = xkb_x11_setup_xkb_extension(conn, + XKB_X11_MIN_MAJOR_XKB_VERSION, XKB_X11_MIN_MINOR_XKB_VERSION, + XKB_X11_SETUP_XKB_EXTENSION_NO_FLAGS, + NULL, NULL, NULL, NULL); + if (!ret) { + qWarning() << "XKB Keyboard: XKB extension setup failed"; + return; + } + + ctx = xkb_context_new(XKB_CONTEXT_NO_FLAGS); + if (!ctx) { + qWarning() << "XKB Keyboard: XKB context creation failed"; + return; + } + + core_kbd_device_id = xkb_x11_get_core_keyboard_device_id(conn); + if (core_kbd_device_id == -1) { + qWarning() << "XKB Keyboard: Core keyboard device not found"; + goto err_ctx; + } + + keymap = xkb_x11_keymap_new_from_device(ctx, conn, core_kbd_device_id, XKB_KEYMAP_COMPILE_NO_FLAGS); + if (!keymap) { + qWarning() << "XKB Keyboard: Keymap loading failed"; + goto err_ctx; + } + + xkbcommon_init(keymap); + return; + +err_ctx: + xkb_context_unref(ctx); +} diff --git a/src/qt/xkbcommon_x11_keyboard.hpp b/src/qt/xkbcommon_x11_keyboard.hpp new file mode 100644 index 000000000..d8c063acb --- /dev/null +++ b/src/qt/xkbcommon_x11_keyboard.hpp @@ -0,0 +1,17 @@ +/* + * 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. + * + * Definitions for xkbcommon-x11 keyboard input module. + * + * + * + * Authors: RichardG, + * + * Copyright 2023 RichardG. + */ +void xkbcommon_x11_init(); diff --git a/src/qt_resources.qrc b/src/qt_resources.qrc index 045c3659d..67f9cadac 100644 --- a/src/qt_resources.qrc +++ b/src/qt_resources.qrc @@ -33,6 +33,7 @@ win/icons/mo_empty_active.ico win/icons/network.ico win/icons/network_active.ico + win/icons/network_empty.ico win/icons/other_peripherals.ico win/icons/other_removable_devices.ico win/icons/ports.ico @@ -57,4 +58,8 @@ win/icons/send_cae.ico win/icons/settings.ico + + qt/texture_vert.spv + qt/texture_frag.spv + diff --git a/src/random.c b/src/random.c index fb1fead52..3f5fed1b9 100644 --- a/src/random.c +++ b/src/random.c @@ -1,96 +1,102 @@ /* - * 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. + * 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. + * This file is part of the 86Box distribution. * - * A better random number generation, used for floppy weak bits - * and network MAC address generation. + * A better random number generation, used for floppy weak bits + * and network MAC address generation. * * * - * Author: Miran Grca, - * Copyright 2016-2018 Miran Grca. + * Authors: Miran Grca, + * + * Copyright 2016-2018 Miran Grca. */ #include #include #include <86box/random.h> -#if !(defined(__i386__) || defined (__x86_64__)) -#include +#if !(defined(__i386__) || defined(__x86_64__)) +# include #endif uint32_t preconst = 0x6ED9EBA1; - -static __inline uint32_t rotl32c (uint32_t x, uint32_t n) +static __inline uint32_t +rotl32c(uint32_t x, uint32_t n) { #if 0 assert (n<32); #endif - return (x<>(-n&31)); + return (x << n) | (x >> (-n & 31)); } -static __inline uint32_t rotr32c (uint32_t x, uint32_t n) +static __inline uint32_t +rotr32c(uint32_t x, uint32_t n) { #if 0 assert (n<32); #endif - return (x>>n) | (x<<(-n&31)); + return (x >> n) | (x << (-n & 31)); } -#define ROTATE_LEFT rotl32c +#define ROTATE_LEFT rotl32c #define ROTATE_RIGHT rotr32c -static __inline unsigned long long rdtsc(void) +static __inline unsigned long long +rdtsc(void) { -#if defined(__i386__) || defined (__x86_64__) - unsigned hi, lo; -#ifdef _MSC_VER +#if defined(__i386__) || defined(__x86_64__) + unsigned int hi; + unsigned int lo; +# ifdef _MSC_VER __asm { - rdtsc - mov hi, edx ; EDX:EAX is already standard return!! - mov lo, eax + rdtsc + mov hi, edx ; EDX:EAX is already standard return!! + mov lo, eax } +# else + __asm__ __volatile__("rdtsc" + : "=a"(lo), "=d"(hi)); +# endif + return ((unsigned long long) lo) | (((unsigned long long) hi) << 32); #else - __asm__ __volatile__ ("rdtsc" : "=a"(lo), "=d"(hi)); -#endif - return ( (unsigned long long)lo)|( ((unsigned long long)hi)<<32 ); -#else - return time(NULL); + return time(NULL); #endif } -static uint32_t RDTSC(void) +static uint32_t +RDTSC(void) { - return (uint32_t) (rdtsc()); + return (uint32_t) (rdtsc()); } - -static void random_twist(uint32_t *val) +static void +random_twist(uint32_t *val) { - *val = ROTATE_LEFT(*val, rand() % 32); - *val ^= 0x5A827999; - *val = ROTATE_RIGHT(*val, rand() % 32); - *val ^= 0x4ED32706; + *val = ROTATE_LEFT(*val, rand() % 32); + *val ^= 0x5A827999; + *val = ROTATE_RIGHT(*val, rand() % 32); + *val ^= 0x4ED32706; } - -uint8_t random_generate(void) +uint8_t +random_generate(void) { - uint16_t r = 0; - r = (RDTSC() ^ ROTATE_LEFT(preconst, rand() % 32)) % 256; - random_twist(&preconst); - return (r & 0xff); + uint16_t r = 0; + r = (RDTSC() ^ ROTATE_LEFT(preconst, rand() % 32)) % 256; + random_twist(&preconst); + return (r & 0xff); } - -void random_init(void) +void +random_init(void) { - uint32_t seed = RDTSC(); - srand(seed); - return; + uint32_t seed = RDTSC(); + srand(seed); + return; } diff --git a/src/scsi/CMakeLists.txt b/src/scsi/CMakeLists.txt index 6b0ebd10e..addde844e 100644 --- a/src/scsi/CMakeLists.txt +++ b/src/scsi/CMakeLists.txt @@ -1,18 +1,18 @@ # -# 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. +# 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. +# This file is part of the 86Box distribution. # -# CMake build script. +# CMake build script. # -# Authors: David HrdliÄka, +# Authors: David HrdliÄka, # -# Copyright 2020,2021 David HrdliÄka. +# Copyright 2020-2021 David HrdliÄka. # add_library(scsi OBJECT scsi.c scsi_device.c scsi_cdrom.c scsi_disk.c scsi_x54x.c scsi_aha154x.c scsi_buslogic.c scsi_ncr5380.c - scsi_ncr53c8xx.c scsi_pcscsi.c scsi_spock.c) \ No newline at end of file + scsi_ncr53c8xx.c scsi_pcscsi.c scsi_spock.c) diff --git a/src/scsi/scsi.c b/src/scsi/scsi.c index 1eab6bf32..238fa7cb3 100644 --- a/src/scsi/scsi.c +++ b/src/scsi/scsi.c @@ -1,21 +1,21 @@ /* - * 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. + * 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. + * This file is part of the 86Box distribution. * - * Handling of the SCSI controllers. + * Handling of the SCSI controllers. * * * - * Authors: Miran Grca, - * Fred N. van Kempen, - * TheCollector1995, + * Authors: Miran Grca, + * Fred N. van Kempen, + * TheCollector1995, * - * Copyright 2016-2018 Miran Grca. - * Copyright 2017,2018 Fred N. van Kempen. + * Copyright 2016-2018 Miran Grca. + * Copyright 2017-2018 Fred N. van Kempen. */ #include #include @@ -41,154 +41,158 @@ #include <86box/scsi_ncr53c8xx.h> #include <86box/scsi_pcscsi.h> #include <86box/scsi_spock.h> -#ifdef WALTJE -# include "scsi_wd33c93.h" -#endif +int scsi_card_current[SCSI_BUS_MAX] = { 0, 0, 0, 0 }; +double scsi_bus_speed[SCSI_BUS_MAX] = { 0.0, 0.0, 0.0, 0.0 }; -int scsi_card_current[SCSI_BUS_MAX] = { 0, 0 }; - -static uint8_t next_scsi_bus = 0; - +static uint8_t next_scsi_bus = 0; static const device_t scsi_none_device = { - "None", - "none", - 0, 0, - NULL, NULL, NULL, - { NULL }, NULL, NULL, - NULL + .name = "None", + .internal_name = "none", + .flags = 0, + .local = 0, + .init = NULL, + .close = NULL, + .reset = NULL, + { .available = NULL }, + .speed_changed = NULL, + .force_redraw = NULL, + .config = NULL }; - typedef const struct { - const device_t *device; + const device_t *device; } SCSI_CARD; - static SCSI_CARD scsi_cards[] = { - { &scsi_none_device, }, - { &aha154xa_device, }, - { &aha154xb_device, }, - { &aha154xc_device, }, - { &aha154xcf_device, }, - { &aha154xcp_device, }, - { &buslogic_542b_device, }, - { &buslogic_542bh_device, }, - { &buslogic_545s_device, }, - { &buslogic_545c_device, }, - { &scsi_lcs6821n_device, }, - { &scsi_rt1000b_device, }, - { &scsi_t128_device, }, - { &scsi_t130b_device, }, -#ifdef WALTJE - { &scsi_wd33c93_device, }, -#endif - { &aha1640_device, }, - { &buslogic_640a_device, }, - { &ncr53c90_mca_device, }, - { &spock_device, }, - { &buslogic_958d_pci_device, }, - { &ncr53c810_pci_device, }, - { &ncr53c815_pci_device, }, - { &ncr53c820_pci_device, }, - { &ncr53c825a_pci_device, }, - { &ncr53c860_pci_device, }, - { &ncr53c875_pci_device, }, - { &dc390_pci_device, }, - { &buslogic_445s_device, }, - { &buslogic_445c_device, }, - { NULL, }, + // clang-format off + { &scsi_none_device, }, + { &aha154xa_device, }, + { &aha154xb_device, }, + { &aha154xc_device, }, + { &aha154xcf_device, }, + { &aha154xcp_device, }, + { &buslogic_542b_device, }, + { &buslogic_542bh_device, }, + { &buslogic_545s_device, }, + { &buslogic_545c_device, }, + { &scsi_ls2000_device, }, + { &scsi_lcs6821n_device, }, + { &scsi_rt1000b_device, }, + { &scsi_rt1000mc_device, }, + { &scsi_t128_device, }, + { &scsi_t130b_device, }, + { &aha1640_device, }, + { &buslogic_640a_device, }, + { &ncr53c90_mca_device, }, + { &spock_device, }, + { &tribble_device, }, + { &buslogic_958d_pci_device, }, + { &ncr53c810_pci_device, }, + { &ncr53c815_pci_device, }, + { &ncr53c820_pci_device, }, + { &ncr53c825a_pci_device, }, + { &ncr53c860_pci_device, }, + { &ncr53c875_pci_device, }, + { &dc390_pci_device, }, + { &buslogic_445s_device, }, + { &buslogic_445c_device, }, + { NULL, }, + // clang-format on }; - void scsi_reset(void) { next_scsi_bus = 0; } - uint8_t scsi_get_bus(void) { uint8_t ret = next_scsi_bus; if (next_scsi_bus >= SCSI_BUS_MAX) - return 0xff; + return 0xff; next_scsi_bus++; return ret; } - int scsi_card_available(int card) { if (scsi_cards[card].device) - return(device_available(scsi_cards[card].device)); + return (device_available(scsi_cards[card].device)); - return(1); + return 1; } - const device_t * scsi_card_getdevice(int card) { - return(scsi_cards[card].device); + return (scsi_cards[card].device); } - int scsi_card_has_config(int card) { - if (! scsi_cards[card].device) return(0); + if (!scsi_cards[card].device) + return 0; - return(scsi_cards[card].device->config ? 1 : 0); + return (device_has_config(scsi_cards[card].device) ? 1 : 0); } - -char * +const char * scsi_card_get_internal_name(int card) { return device_get_internal_name(scsi_cards[card].device); } - int scsi_card_get_from_internal_name(char *s) { int c = 0; while (scsi_cards[c].device != NULL) { - if (!strcmp((char *) scsi_cards[c].device->internal_name, s)) - return(c); - c++; + if (!strcmp(scsi_cards[c].device->internal_name, s)) + return c; + c++; } - - return(0); -} + return 0; +} void scsi_card_init(void) { - int i = 0, max = SCSI_BUS_MAX; + int max = SCSI_BUS_MAX; /* On-board SCSI controllers get the first bus, so if one is present, increase our instance number here. */ if (machine_has_flags(machine, MACHINE_SCSI)) - max--; + max--; /* Do not initialize any controllers if we have do not have any SCSI - bus left. */ + bus left. */ if (max > 0) { - for (i = 0; i < max; i++) { - if (!scsi_cards[scsi_card_current[i]].device) - continue; - - device_add_inst(scsi_cards[scsi_card_current[i]].device, i + 1); - } + for (int i = 0; i < max; i++) { + if ((scsi_card_current[i] > 0) && scsi_cards[scsi_card_current[i]].device) + device_add_inst(scsi_cards[scsi_card_current[i]].device, i + 1); + } } } + +void +scsi_bus_set_speed(uint8_t bus, double speed) +{ + scsi_bus_speed[bus] = speed; +} + +double +scsi_bus_get_speed(uint8_t bus) +{ + return scsi_bus_speed[bus]; +} diff --git a/src/scsi/scsi_aha154x.c b/src/scsi/scsi_aha154x.c index d0c81a08d..05b8b2726 100644 --- a/src/scsi/scsi_aha154x.c +++ b/src/scsi/scsi_aha154x.c @@ -1,21 +1,21 @@ /* - * 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. + * 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. + * This file is part of the 86Box distribution. * - * Implementation of the AHA-154x series of SCSI Host Adapters - * made by Adaptec, Inc. These controllers were designed for - * the ISA bus. + * Implementation of the AHA-154x series of SCSI Host Adapters + * made by Adaptec, Inc. These controllers were designed for + * the ISA bus. * * * - * Authors: Fred N. van Kempen, - * Original Buslogic version by SA1988 and Miran Grca. + * Authors: Fred N. van Kempen, + * Original Buslogic version by SA1988 and Miran Grca. * - * Copyright 2017,2018 Fred N. van Kempen. + * Copyright 2017-2018 Fred N. van Kempen. */ #include #include @@ -44,7 +44,6 @@ #include <86box/scsi_aha154x.h> #include <86box/scsi_x54x.h> - enum { AHA_154xA, AHA_154xB, @@ -54,59 +53,52 @@ enum { AHA_1640 }; +#define CMD_WRITE_EEPROM 0x22 /* UNDOC: Write EEPROM */ +#define CMD_READ_EEPROM 0x23 /* UNDOC: Read EEPROM */ +#define CMD_SHADOW_RAM 0x24 /* UNDOC: BIOS shadow ram */ +#define CMD_BIOS_MBINIT 0x25 /* UNDOC: BIOS mailbox initialization */ +#define CMD_MEMORY_MAP_1 0x26 /* UNDOC: Memory Mapper */ +#define CMD_MEMORY_MAP_2 0x27 /* UNDOC: Memory Mapper */ +#define CMD_EXTBIOS 0x28 /* UNDOC: return extended BIOS info */ +#define CMD_MBENABLE 0x29 /* set mailbox interface enable */ +#define CMD_BIOS_SCSI 0x82 /* start ROM BIOS SCSI command */ - -#define CMD_WRITE_EEPROM 0x22 /* UNDOC: Write EEPROM */ -#define CMD_READ_EEPROM 0x23 /* UNDOC: Read EEPROM */ -#define CMD_SHADOW_RAM 0x24 /* UNDOC: BIOS shadow ram */ -#define CMD_BIOS_MBINIT 0x25 /* UNDOC: BIOS mailbox initialization */ -#define CMD_MEMORY_MAP_1 0x26 /* UNDOC: Memory Mapper */ -#define CMD_MEMORY_MAP_2 0x27 /* UNDOC: Memory Mapper */ -#define CMD_EXTBIOS 0x28 /* UNDOC: return extended BIOS info */ -#define CMD_MBENABLE 0x29 /* set mailbox interface enable */ -#define CMD_BIOS_SCSI 0x82 /* start ROM BIOS SCSI command */ - - -uint16_t aha_ports[] = { +uint16_t aha_ports[] = { 0x0330, 0x0334, 0x0230, 0x0234, 0x0130, 0x0134, 0x0000, 0x0000 }; static uint8_t *aha1542cp_pnp_rom = NULL; - -#pragma pack(push,1) -typedef struct { - uint8_t CustomerSignature[20]; - uint8_t uAutoRetry; - uint8_t uBoardSwitches; - uint8_t uChecksum; - uint8_t uUnknown; - addr24 BIOSMailboxAddress; +#pragma pack(push, 1) +typedef struct aha_setup_t { + uint8_t CustomerSignature[20]; + uint8_t uAutoRetry; + uint8_t uBoardSwitches; + uint8_t uChecksum; + uint8_t uUnknown; + addr24_t BIOSMailboxAddress; } aha_setup_t; #pragma pack(pop) - #ifdef ENABLE_AHA154X_LOG int aha_do_log = ENABLE_AHA154X_LOG; - static void aha_log(const char *fmt, ...) { va_list ap; if (aha_do_log) { - va_start(ap, fmt); - pclog_ex(fmt, ap); - va_end(ap); + va_start(ap, fmt); + pclog_ex(fmt, ap); + va_end(ap); } } #else -#define aha_log(fmt, ...) +# define aha_log(fmt, ...) #endif - /* * Write data to the BIOS space. * @@ -120,422 +112,406 @@ aha_log(const char *fmt, ...) static void aha_mem_write(uint32_t addr, uint8_t val, void *priv) { - x54x_t *dev = (x54x_t *)priv; + x54x_t *dev = (x54x_t *) priv; addr &= 0x3fff; if ((addr >= dev->rom_shram) && (dev->shram_mode & 1)) - dev->shadow_ram[addr & (dev->rom_shramsz - 1)] = val; + dev->shadow_ram[addr & (dev->rom_shramsz - 1)] = val; } - static uint8_t aha_mem_read(uint32_t addr, void *priv) { - x54x_t *dev = (x54x_t *)priv; - rom_t *rom = &dev->bios; + const x54x_t *dev = (x54x_t *) priv; + const rom_t *rom = &dev->bios; addr &= 0x3fff; if ((addr >= dev->rom_shram) && (dev->shram_mode & 2)) - return dev->shadow_ram[addr & (dev->rom_shramsz - 1)]; + return dev->shadow_ram[addr & (dev->rom_shramsz - 1)]; - return(rom->rom[addr]); + return (rom->rom[addr]); } - static uint8_t aha154x_shram(x54x_t *dev, uint8_t cmd) { /* If not supported, give up. */ - if (dev->rom_shram == 0x0000) return(0x04); + if (dev->rom_shram == 0x0000) + return 0x04; /* Bit 0 = Shadow RAM write enable; Bit 1 = Shadow RAM read enable. */ dev->shram_mode = cmd; /* Firmware expects 04 status. */ - return(0x04); + return 0x04; } - static void aha_eeprom_save(x54x_t *dev) { - FILE *f; + FILE *fp; - f = nvr_fopen(dev->nvr_path, "wb"); - if (f) - { - fwrite(dev->nvr, 1, NVR_SIZE, f); - fclose(f); - f = NULL; + fp = nvr_fopen(dev->nvr_path, "wb"); + if (fp) { + fwrite(dev->nvr, 1, NVR_SIZE, fp); + fclose(fp); + fp = NULL; } } - static uint8_t -aha154x_eeprom(x54x_t *dev, uint8_t cmd,uint8_t arg,uint8_t len,uint8_t off,uint8_t *bufp) +aha154x_eeprom(x54x_t *dev, uint8_t cmd, UNUSED(uint8_t arg), uint8_t len, uint8_t off, uint8_t *bufp) { uint8_t r = 0xff; - int c; + int c; aha_log("%s: EEPROM cmd=%02x, arg=%02x len=%d, off=%02x\n", - dev->name, cmd, arg, len, off); + dev->name, cmd, arg, len, off); /* Only if we can handle it.. */ - if (dev->nvr == NULL) return(r); + if (dev->nvr == NULL) + return r; if (cmd == 0x22) { - /* Write data to the EEPROM. */ - for (c = 0; c < len; c++) - dev->nvr[(off + c) & 0xff] = bufp[c]; - r = 0; + /* Write data to the EEPROM. */ + for (c = 0; c < len; c++) + dev->nvr[(off + c) & 0xff] = bufp[c]; + r = 0; - aha_eeprom_save(dev); + aha_eeprom_save(dev); - if (dev->type == AHA_154xCF) { - if (dev->fdc_address > 0) { - fdc_remove(dev->fdc); - fdc_set_base(dev->fdc, (dev->nvr[0] & EE0_ALTFLOP) ? 0x370 : 0x3f0); - } - } + if (dev->type == AHA_154xCF) { + if (dev->fdc_address > 0) { + fdc_remove(dev->fdc); + fdc_set_base(dev->fdc, (dev->nvr[0] & EE0_ALTFLOP) ? FDC_SECONDARY_ADDR : FDC_PRIMARY_ADDR); + } + } } if (cmd == 0x23) { - /* Read data from the EEPROM. */ - for (c = 0; c < len; c++) - bufp[c] = dev->nvr[(off + c) & 0xff]; - r = len; + /* Read data from the EEPROM. */ + for (c = 0; c < len; c++) + bufp[c] = dev->nvr[(off + c) & 0xff]; + r = len; } - return(r); + return r; } - /* Map either the main or utility (Select) ROM into the memory space. */ static uint8_t aha154x_mmap(x54x_t *dev, uint8_t cmd) { aha_log("%s: MEMORY cmd=%02x\n", dev->name, cmd); - switch(cmd) { - case 0x26: - /* Disable the mapper, so, set ROM1 active. */ - dev->bios.rom = dev->rom1; - break; + switch (cmd) { + case 0x26: + /* Disable the mapper, so, set ROM1 active. */ + dev->bios.rom = dev->rom1; + break; - case 0x27: - /* Enable the mapper, so, set ROM2 active. */ - dev->bios.rom = dev->rom2; - break; + case 0x27: + /* Enable the mapper, so, set ROM2 active. */ + dev->bios.rom = dev->rom2; + break; + + default: + break; } - return(0); + return 0; } - static uint8_t -aha_get_host_id(void *p) +aha_get_host_id(void *priv) { - x54x_t *dev = (x54x_t *)p; + const x54x_t *dev = (x54x_t *) priv; return dev->nvr[0] & 0x07; } - static uint8_t -aha_get_irq(void *p) +aha_get_irq(void *priv) { - x54x_t *dev = (x54x_t *)p; + const x54x_t *dev = (x54x_t *) priv; return (dev->nvr[1] & 0x07) + 9; } - static uint8_t -aha_get_dma(void *p) +aha_get_dma(void *priv) { - x54x_t *dev = (x54x_t *)p; + const x54x_t *dev = (x54x_t *) priv; return (dev->nvr[1] >> 4) & 0x07; } - static uint8_t -aha_cmd_is_fast(void *p) +aha_cmd_is_fast(void *priv) { - x54x_t *dev = (x54x_t *)p; + const x54x_t *dev = (x54x_t *) priv; if (dev->Command == CMD_BIOS_SCSI) - return 1; + return 1; else - return 0; + return 0; } - static uint8_t -aha_fast_cmds(void *p, uint8_t cmd) +aha_fast_cmds(void *priv, uint8_t cmd) { - x54x_t *dev = (x54x_t *)p; + x54x_t *dev = (x54x_t *) priv; if (cmd == CMD_BIOS_SCSI) { - dev->BIOSMailboxReq++; - return 1; + dev->BIOSMailboxReq++; + return 1; } return 0; } - static uint8_t -aha_param_len(void *p) +aha_param_len(void *priv) { - x54x_t *dev = (x54x_t *)p; + const x54x_t *dev = (x54x_t *) priv; switch (dev->Command) { - case CMD_BIOS_MBINIT: - /* Same as 0x01 for AHA. */ - return sizeof(MailboxInit_t); - break; + case CMD_BIOS_MBINIT: + /* Same as 0x01 for AHA. */ + return sizeof(MailboxInit_t); - case CMD_SHADOW_RAM: - return 1; - break; + case CMD_SHADOW_RAM: + return 1; - case CMD_WRITE_EEPROM: - return 35; - break; + case CMD_WRITE_EEPROM: + return 35; - case CMD_READ_EEPROM: - return 3; + case CMD_READ_EEPROM: + return 3; - case CMD_MBENABLE: - return 2; + case CMD_MBENABLE: + return 2; - case 0x39: - return 3; + case 0x39: + return 3; - case 0x40: - return 2; + case 0x40: + return 2; - default: - return 0; + default: + return 0; } } - static uint8_t -aha_cmds(void *p) +aha_cmds(void *priv) { - x54x_t *dev = (x54x_t *)p; - MailboxInit_t *mbi; + x54x_t *dev = (x54x_t *) priv; + const MailboxInit_t *mbi; - if (! dev->CmdParamLeft) { - aha_log("Running Operation Code 0x%02X\n", dev->Command); - switch (dev->Command) { - case CMD_WRITE_EEPROM: /* write EEPROM */ - /* Sent by CF BIOS. */ - dev->DataReplyLeft = - aha154x_eeprom(dev, - dev->Command, - dev->CmdBuf[0], - dev->CmdBuf[1], - dev->CmdBuf[2], - &(dev->CmdBuf[3])); - if (dev->DataReplyLeft == 0xff) { - dev->DataReplyLeft = 0; - dev->Status |= STAT_INVCMD; - } - break; + if (!dev->CmdParamLeft) { + aha_log("Running Operation Code 0x%02X\n", dev->Command); + switch (dev->Command) { + case CMD_WRITE_EEPROM: /* write EEPROM */ + /* Sent by CF BIOS. */ + dev->DataReplyLeft = aha154x_eeprom(dev, + dev->Command, + dev->CmdBuf[0], + dev->CmdBuf[1], + dev->CmdBuf[2], + &(dev->CmdBuf[3])); + if (dev->DataReplyLeft == 0xff) { + dev->DataReplyLeft = 0; + dev->Status |= STAT_INVCMD; + } + break; - case CMD_READ_EEPROM: /* read EEPROM */ - /* Sent by CF BIOS. */ - dev->DataReplyLeft = - aha154x_eeprom(dev, - dev->Command, - dev->CmdBuf[0], - dev->CmdBuf[1], - dev->CmdBuf[2], - dev->DataBuf); - if (dev->DataReplyLeft == 0xff) { - dev->DataReplyLeft = 0; - dev->Status |= STAT_INVCMD; - } - break; + case CMD_READ_EEPROM: /* read EEPROM */ + /* Sent by CF BIOS. */ + dev->DataReplyLeft = aha154x_eeprom(dev, + dev->Command, + dev->CmdBuf[0], + dev->CmdBuf[1], + dev->CmdBuf[2], + dev->DataBuf); + if (dev->DataReplyLeft == 0xff) { + dev->DataReplyLeft = 0; + dev->Status |= STAT_INVCMD; + } + break; - case CMD_SHADOW_RAM: /* Shadow RAM */ - /* - * For AHA1542CF, this is the command - * to play with the Shadow RAM. BIOS - * gives us one argument (00,02,03) - * and expects a 0x04 back in the INTR - * register. --FvK - */ - /* dev->Interrupt = aha154x_shram(dev,val); */ - dev->Interrupt = aha154x_shram(dev, dev->CmdBuf[0]); - break; + case CMD_SHADOW_RAM: /* Shadow RAM */ + /* + * For AHA1542CF, this is the command + * to play with the Shadow RAM. BIOS + * gives us one argument (00,02,03) + * and expects a 0x04 back in the INTR + * register. --FvK + */ +#if 0 + dev->Interrupt = aha154x_shram(dev,val); +#endif + dev->Interrupt = aha154x_shram(dev, dev->CmdBuf[0]); + break; - case CMD_BIOS_MBINIT: /* BIOS Mailbox Initialization */ - /* Sent by CF BIOS. */ - dev->flags |= X54X_MBX_24BIT; + case CMD_BIOS_MBINIT: /* BIOS Mailbox Initialization */ + /* Sent by CF BIOS. */ + dev->flags |= X54X_MBX_24BIT; - mbi = (MailboxInit_t *)dev->CmdBuf; + mbi = (MailboxInit_t *) dev->CmdBuf; - dev->BIOSMailboxInit = 1; - dev->BIOSMailboxCount = mbi->Count; - dev->BIOSMailboxOutAddr = ADDR_TO_U32(mbi->Address); + dev->BIOSMailboxInit = 1; + dev->BIOSMailboxCount = mbi->Count; + dev->BIOSMailboxOutAddr = ADDR_TO_U32(mbi->Address); - aha_log("Initialize BIOS Mailbox: MBO=0x%08lx, %d entries at 0x%08lx\n", - dev->BIOSMailboxOutAddr, - mbi->Count, - ADDR_TO_U32(mbi->Address)); + aha_log("Initialize BIOS Mailbox: MBO=0x%08lx, %d entries at 0x%08lx\n", + dev->BIOSMailboxOutAddr, + mbi->Count, + ADDR_TO_U32(mbi->Address)); - dev->Status &= ~STAT_INIT; - dev->DataReplyLeft = 0; - break; + dev->Status &= ~STAT_INIT; + dev->DataReplyLeft = 0; + break; - case CMD_MEMORY_MAP_1: /* AHA memory mapper */ - case CMD_MEMORY_MAP_2: /* AHA memory mapper */ - /* Sent by CF BIOS. */ - dev->DataReplyLeft = - aha154x_mmap(dev, dev->Command); - break; + case CMD_MEMORY_MAP_1: /* AHA memory mapper */ + case CMD_MEMORY_MAP_2: /* AHA memory mapper */ + /* Sent by CF BIOS. */ + dev->DataReplyLeft = aha154x_mmap(dev, dev->Command); + break; - case CMD_EXTBIOS: /* Return extended BIOS information */ - dev->DataBuf[0] = 0x08; - dev->DataBuf[1] = dev->Lock; - dev->DataReplyLeft = 2; - break; - - case CMD_MBENABLE: /* Mailbox interface enable Command */ - dev->DataReplyLeft = 0; - if (dev->CmdBuf[1] == dev->Lock) { - if (dev->CmdBuf[0] & 1) { - dev->Lock = 1; - } else { - dev->Lock = 0; - } - } - break; + case CMD_EXTBIOS: /* Return extended BIOS information */ + dev->DataBuf[0] = 0x08; + dev->DataBuf[1] = dev->Lock; + dev->DataReplyLeft = 2; + break; - case 0x2C: /* Detect termination status */ - /* Bits 7,6 are termination status and must be 1,0 for the BIOS to work. */ - dev->DataBuf[0] = 0x40; - dev->DataReplyLeft = 1; - break; + case CMD_MBENABLE: /* Mailbox interface enable Command */ + dev->DataReplyLeft = 0; + if (dev->CmdBuf[1] == dev->Lock) { + if (dev->CmdBuf[0] & 1) { + dev->Lock = 1; + } else { + dev->Lock = 0; + } + } + break; - case 0x2D: /* ???? - Returns two bytes according to the microcode */ - dev->DataBuf[0] = 0x00; - dev->DataBuf[0] = 0x00; - dev->DataReplyLeft = 2; - break; + case 0x2C: /* Detect termination status */ + /* Bits 7,6 are termination status and must be 1,0 for the BIOS to work. */ + dev->DataBuf[0] = 0x40; + dev->DataReplyLeft = 1; + break; - case 0x33: /* Send the SCSISelect code decompressor program */ - if (dev->cmd_33_len == 0x0000) { - /* If we are on a controller without this command, return invalid command. */ - dev->DataReplyLeft = 0; - dev->Status |= STAT_INVCMD; - break; - } + case 0x2D: /* ???? - Returns two bytes according to the microcode */ + dev->DataBuf[0] = 0x00; + dev->DataBuf[0] = 0x00; + dev->DataReplyLeft = 2; + break; - /* We have to send (decompressor program length + 2 bytes of little endian size). */ - dev->DataReplyLeft = dev->cmd_33_len + 2; - memset(dev->DataBuf, 0x00, dev->DataReplyLeft); - dev->DataBuf[0] = dev->cmd_33_len & 0xff; - dev->DataBuf[1] = (dev->cmd_33_len >> 8) & 0xff; - memcpy(&(dev->DataBuf[2]), dev->cmd_33_buf, dev->cmd_33_len); - break; + case 0x33: /* Send the SCSISelect code decompressor program */ + if (dev->cmd_33_len == 0x0000) { + /* If we are on a controller without this command, return invalid command. */ + dev->DataReplyLeft = 0; + dev->Status |= STAT_INVCMD; + break; + } - case 0x39: /* Receive 3 bytes: address high, address low, byte to write to that address. */ - /* Since we are not running the actual microcode, just log the received values - (if logging is enabled) and break. */ - aha_log("aha_cmds(): Command 0x39: %02X -> %02X%02X\n", - dev->CmdBuf[2], dev->CmdBuf[0], dev->CmdBuf[1]); - break; + /* We have to send (decompressor program length + 2 bytes of little endian size). */ + dev->DataReplyLeft = dev->cmd_33_len + 2; + memset(dev->DataBuf, 0x00, dev->DataReplyLeft); + dev->DataBuf[0] = dev->cmd_33_len & 0xff; + dev->DataBuf[1] = (dev->cmd_33_len >> 8) & 0xff; + memcpy(&(dev->DataBuf[2]), dev->cmd_33_buf, dev->cmd_33_len); + break; - case 0x40: /* Receive 2 bytes: address high, address low, then return one byte from that - address. */ - aha_log("aha_cmds(): Command 0x40: %02X%02X\n", - dev->CmdBuf[0], dev->CmdBuf[1]); - dev->DataReplyLeft = 1; - dev->DataBuf[0] = 0xff; - break; + case 0x39: /* Receive 3 bytes: address high, address low, byte to write to that address. */ + /* Since we are not running the actual microcode, just log the received values + (if logging is enabled) and break. */ + aha_log("aha_cmds(): Command 0x39: %02X -> %02X%02X\n", + dev->CmdBuf[2], dev->CmdBuf[0], dev->CmdBuf[1]); + break; - default: - dev->DataReplyLeft = 0; - dev->Status |= STAT_INVCMD; - break; - } + case 0x40: /* Receive 2 bytes: address high, address low, then return one byte from that + address. */ + aha_log("aha_cmds(): Command 0x40: %02X%02X\n", + dev->CmdBuf[0], dev->CmdBuf[1]); + dev->DataReplyLeft = 1; + dev->DataBuf[0] = 0xff; + break; + + default: + dev->DataReplyLeft = 0; + dev->Status |= STAT_INVCMD; + break; + } } return 0; } - static void -aha_setup_data(void *p) +aha_setup_data(void *priv) { - x54x_t *dev = (x54x_t *)p; + x54x_t *dev = (x54x_t *) priv; ReplyInquireSetupInformation *ReplyISI; - aha_setup_t *aha_setup; + aha_setup_t *aha_setup; - ReplyISI = (ReplyInquireSetupInformation *)dev->DataBuf; - aha_setup = (aha_setup_t *)ReplyISI->VendorSpecificData; + ReplyISI = (ReplyInquireSetupInformation *) dev->DataBuf; + aha_setup = (aha_setup_t *) ReplyISI->VendorSpecificData; ReplyISI->fSynchronousInitiationEnabled = dev->sync & 1; - ReplyISI->fParityCheckingEnabled = dev->parity & 1; + ReplyISI->fParityCheckingEnabled = dev->parity & 1; U32_TO_ADDR(aha_setup->BIOSMailboxAddress, dev->BIOSMailboxOutAddr); aha_setup->uChecksum = 0xA3; - aha_setup->uUnknown = 0xC2; + aha_setup->uUnknown = 0xC2; } - static void aha_do_bios_mail(x54x_t *dev) { dev->MailboxIsBIOS = 1; if (!dev->BIOSMailboxCount) { - aha_log("aha_do_bios_mail(): No BIOS Mailboxes\n"); - return; + aha_log("aha_do_bios_mail(): No BIOS Mailboxes\n"); + return; } /* Search for a filled mailbox - stop if we have scanned all mailboxes. */ for (dev->BIOSMailboxOutPosCur = 0; dev->BIOSMailboxOutPosCur < dev->BIOSMailboxCount; dev->BIOSMailboxOutPosCur++) { - if (x54x_mbo_process(dev)) - break; + if (x54x_mbo_process(dev)) + break; } } - static void -aha_callback(void *p) +aha_callback(void *priv) { - x54x_t *dev = (x54x_t *)p; + x54x_t *dev = (x54x_t *) priv; if (dev->BIOSMailboxInit && dev->BIOSMailboxReq) - aha_do_bios_mail(dev); + aha_do_bios_mail(dev); } - static uint8_t aha_mca_read(int port, void *priv) { - x54x_t *dev = (x54x_t *)priv; + const x54x_t *dev = (x54x_t *) priv; - return(dev->pos_regs[port & 7]); + return (dev->pos_regs[port & 7]); } - static void aha_mca_write(int port, uint8_t val, void *priv) { - x54x_t *dev = (x54x_t *)priv; + x54x_t *dev = (x54x_t *) priv; /* MCA does not write registers below 0x0100. */ - if (port < 0x0102) return; + if (port < 0x0102) + return; /* Save the MCA register value. */ dev->pos_regs[port & 7] = val; @@ -545,40 +521,45 @@ aha_mca_write(int port, uint8_t val, void *priv) /* Get the new assigned I/O base address. */ dev->Base = (dev->pos_regs[3] & 7) << 8; - dev->Base |= ((dev->pos_regs[3] & 0xc0) ? 0x34 : 0x30); + dev->Base |= ((dev->pos_regs[3] & 0x40) ? 0x34 : 0x30); /* Save the new IRQ and DMA channel values. */ - dev->Irq = (dev->pos_regs[4] & 0x07) + 8; - dev->DmaChannel = dev->pos_regs[5] & 0x0f; + dev->Irq = (dev->pos_regs[4] & 0x07) + 8; + dev->DmaChannel = dev->pos_regs[5] & 0x0f; /* Extract the BIOS ROM address info. */ - if (! (dev->pos_regs[2] & 0x80)) switch(dev->pos_regs[3] & 0x38) { - case 0x38: /* [1]=xx11 1xxx */ - dev->rom_addr = 0xDC000; - break; + if (!(dev->pos_regs[2] & 0x80)) + switch (dev->pos_regs[3] & 0x38) { + case 0x38: /* [1]=xx11 1xxx */ + dev->rom_addr = 0xDC000; + break; - case 0x30: /* [1]=xx11 0xxx */ - dev->rom_addr = 0xD8000; - break; + case 0x30: /* [1]=xx11 0xxx */ + dev->rom_addr = 0xD8000; + break; - case 0x28: /* [1]=xx10 1xxx */ - dev->rom_addr = 0xD4000; - break; + case 0x28: /* [1]=xx10 1xxx */ + dev->rom_addr = 0xD4000; + break; - case 0x20: /* [1]=xx10 0xxx */ - dev->rom_addr = 0xD0000; - break; + case 0x20: /* [1]=xx10 0xxx */ + dev->rom_addr = 0xD0000; + break; - case 0x18: /* [1]=xx01 1xxx */ - dev->rom_addr = 0xCC000; - break; + case 0x18: /* [1]=xx01 1xxx */ + dev->rom_addr = 0xCC000; + break; - case 0x10: /* [1]=xx01 0xxx */ - dev->rom_addr = 0xC8000; - break; - } else { - /* Disabled. */ - dev->rom_addr = 0x000000; + case 0x10: /* [1]=xx01 0xxx */ + dev->rom_addr = 0xC8000; + break; + + default: + break; + } + else { + /* Disabled. */ + dev->rom_addr = 0x000000; } /* @@ -595,7 +576,7 @@ aha_mca_write(int port, uint8_t val, void *priv) * * SCSI Parity is pos[2]=xxx1xxxx. */ - dev->sync = (dev->pos_regs[4] >> 3) & 1; + dev->sync = (dev->pos_regs[4] >> 3) & 1; dev->parity = (dev->pos_regs[4] >> 4) & 1; /* @@ -609,122 +590,122 @@ aha_mca_write(int port, uint8_t val, void *priv) /* Initialize the device if fully configured. */ if (dev->pos_regs[2] & 0x01) { - /* Card enabled; register (new) I/O handler. */ - x54x_io_set(dev, dev->Base, 4); + /* Card enabled; register (new) I/O handler. */ + x54x_io_set(dev, dev->Base, 4); - /* Reset the device. */ - x54x_reset_ctrl(dev, CTRL_HRST); + /* Reset the device. */ + x54x_reset_ctrl(dev, CTRL_HRST); - /* Enable or disable the BIOS ROM. */ - if (dev->rom_addr != 0x000000) { - mem_mapping_enable(&dev->bios.mapping); - mem_mapping_set_addr(&dev->bios.mapping, dev->rom_addr, ROM_SIZE); - } + /* Enable or disable the BIOS ROM. */ + if (dev->rom_addr != 0x000000) { + mem_mapping_enable(&dev->bios.mapping); + mem_mapping_set_addr(&dev->bios.mapping, dev->rom_addr, ROM_SIZE); + } - /* Say hello. */ - aha_log("AHA-1640: I/O=%04x, IRQ=%d, DMA=%d, BIOS @%05X, HOST ID %i\n", - dev->Base, dev->Irq, dev->DmaChannel, dev->rom_addr, dev->HostID); + /* Say hello. */ + aha_log("AHA-1640: I/O=%04x, IRQ=%d, DMA=%d, BIOS @%05X, HOST ID %i\n", + dev->Base, dev->Irq, dev->DmaChannel, dev->rom_addr, dev->HostID); } } - static uint8_t aha_mca_feedb(void *priv) { - x54x_t *dev = (x54x_t *)priv; + const x54x_t *dev = (x54x_t *) priv; return (dev->pos_regs[2] & 0x01); } - static void aha_pnp_config_changed(uint8_t ld, isapnp_device_config_t *config, void *priv) { x54x_t *dev = (x54x_t *) priv; - int i; + int i; switch (ld) { - case 0: - if (dev->Base) { - x54x_io_remove(dev, dev->Base, 4); - dev->Base = 0; - } + case 0: + if (dev->Base) { + x54x_io_remove(dev, dev->Base, 4); + dev->Base = 0; + } - dev->Irq = 0; - dev->DmaChannel = ISAPNP_DMA_DISABLED; - dev->rom_addr = 0; + dev->Irq = 0; + dev->DmaChannel = ISAPNP_DMA_DISABLED; + dev->rom_addr = 0; - mem_mapping_disable(&dev->bios.mapping); + mem_mapping_disable(&dev->bios.mapping); - if (config->activate) { - dev->Base = config->io[0].base; - if (dev->Base != ISAPNP_IO_DISABLED) - x54x_io_set(dev, dev->Base, 4); + if (config->activate) { + dev->Base = config->io[0].base; + if (dev->Base != ISAPNP_IO_DISABLED) + x54x_io_set(dev, dev->Base, 4); - /* - * Patch the ROM BIOS image for stuff Adaptec deliberately - * made hard to understand. Well, maybe not, maybe it was - * their way of handling issues like these at the time.. - * - * Patch 1: emulate the I/O ADDR SW setting by patching a - * byte in the BIOS that indicates the I/O ADDR - * switch setting on the board. - */ - if (dev->rom_ioaddr != 0x0000) { - /* Look up the I/O address in the table. */ - for (i=0; i<8; i++) - if (aha_ports[i] == dev->Base) break; - if (i == 8) { - aha_log("%s: invalid I/O address %04x selected!\n", - dev->name, dev->Base); - return; - } - dev->bios.rom[dev->rom_ioaddr] = (uint8_t)i; - /* Negation of the DIP switches to satify the checksum. */ - dev->bios.rom[dev->rom_ioaddr + 1] = (uint8_t)((i ^ 0xff) + 1); - } + /* + * Patch the ROM BIOS image for stuff Adaptec deliberately + * made hard to understand. Well, maybe not, maybe it was + * their way of handling issues like these at the time.. + * + * Patch 1: emulate the I/O ADDR SW setting by patching a + * byte in the BIOS that indicates the I/O ADDR + * switch setting on the board. + */ + if (dev->rom_ioaddr != 0x0000) { + /* Look up the I/O address in the table. */ + for (i = 0; i < 8; i++) + if (aha_ports[i] == dev->Base) + break; + if (i == 8) { + aha_log("%s: invalid I/O address %04x selected!\n", + dev->name, dev->Base); + return; + } + dev->bios.rom[dev->rom_ioaddr] = (uint8_t) i; + /* Negation of the DIP switches to satify the checksum. */ + dev->bios.rom[dev->rom_ioaddr + 1] = (uint8_t) ((i ^ 0xff) + 1); + } - dev->Irq = config->irq[0].irq; - dev->DmaChannel = config->dma[0].dma; + dev->Irq = config->irq[0].irq; + dev->DmaChannel = config->dma[0].dma; - dev->nvr[1] = (dev->Irq - 9) | (dev->DmaChannel << 4); - aha_eeprom_save(dev); + dev->nvr[1] = (dev->Irq - 9) | (dev->DmaChannel << 4); + aha_eeprom_save(dev); - dev->rom_addr = config->mem[0].base; - if (dev->rom_addr) { - mem_mapping_enable(&dev->bios.mapping); - aha_log("SCSI BIOS set to: %08X-%08X\n", dev->rom_addr, dev->rom_addr + config->mem[0].size - 1); - mem_mapping_set_addr(&dev->bios.mapping, dev->rom_addr, config->mem[0].size); - } - } + dev->rom_addr = config->mem[0].base; + if (dev->rom_addr) { + mem_mapping_enable(&dev->bios.mapping); + aha_log("SCSI BIOS set to: %08X-%08X\n", dev->rom_addr, dev->rom_addr + config->mem[0].size - 1); + mem_mapping_set_addr(&dev->bios.mapping, dev->rom_addr, config->mem[0].size); + } + } - break; + break; #ifdef AHA1542CP_FDC - case 1: - if (dev->fdc_address) { - fdc_remove(dev->fdc); - dev->fdc_address = 0; - } + case 1: + if (dev->fdc_address) { + fdc_remove(dev->fdc); + dev->fdc_address = 0; + } - fdc_set_irq(dev->fdc, 0); - fdc_set_dma_ch(dev->fdc, ISAPNP_DMA_DISABLED); + fdc_set_irq(dev->fdc, 0); + fdc_set_dma_ch(dev->fdc, ISAPNP_DMA_DISABLED); - if (config->activate) { - dev->fdc_address = config->io[0].base; - if (dev->fdc_address != ISAPNP_IO_DISABLED) - fdc_set_base(dev->fdc, dev->fdc_address); + if (config->activate) { + dev->fdc_address = config->io[0].base; + if (dev->fdc_address != ISAPNP_IO_DISABLED) + fdc_set_base(dev->fdc, dev->fdc_address); - fdc_set_irq(dev->fdc, config->irq[0].irq); - fdc_set_dma_ch(dev->fdc, config->dma[0].dma); - } + fdc_set_irq(dev->fdc, config->irq[0].irq); + fdc_set_dma_ch(dev->fdc, config->dma[0].dma); + } - break; + break; #endif + default: + break; } } - /* Initialize the board's ROM BIOS. */ static void aha_setbios(x54x_t *dev) @@ -732,17 +713,18 @@ aha_setbios(x54x_t *dev) uint32_t size; uint32_t mask; uint32_t temp; - FILE *f; - int i; + FILE *fp; + int i; /* Only if this device has a BIOS ROM. */ - if (dev->bios_path == NULL) return; + if (dev->bios_path == NULL) + return; /* Open the BIOS image file and make sure it exists. */ aha_log("%s: loading BIOS from '%s'\n", dev->name, dev->bios_path); - if ((f = rom_fopen(dev->bios_path, "rb")) == NULL) { - aha_log("%s: BIOS ROM not found!\n", dev->name); - return; + if ((fp = rom_fopen(dev->bios_path, "rb")) == NULL) { + aha_log("%s: BIOS ROM not found!\n", dev->name); + return; } /* @@ -752,45 +734,45 @@ aha_setbios(x54x_t *dev) * this special case, we can't: we may need WRITE access to the * memory later on. */ - (void)fseek(f, 0L, SEEK_END); - temp = ftell(f); - (void)fseek(f, 0L, SEEK_SET); + (void) fseek(fp, 0L, SEEK_END); + temp = ftell(fp); + (void) fseek(fp, 0L, SEEK_SET); /* Load first chunk of BIOS (which is the main BIOS, aka ROM1.) */ dev->rom1 = malloc(ROM_SIZE); - (void)fread(dev->rom1, ROM_SIZE, 1, f); + (void) !fread(dev->rom1, ROM_SIZE, 1, fp); temp -= ROM_SIZE; if (temp > 0) { - dev->rom2 = malloc(ROM_SIZE); - (void)fread(dev->rom2, ROM_SIZE, 1, f); - temp -= ROM_SIZE; + dev->rom2 = malloc(ROM_SIZE); + (void) !fread(dev->rom2, ROM_SIZE, 1, fp); + temp -= ROM_SIZE; } else { - dev->rom2 = NULL; + dev->rom2 = NULL; } if (temp != 0) { - aha_log("%s: BIOS ROM size invalid!\n", dev->name); - free(dev->rom1); - if (dev->rom2 != NULL) - free(dev->rom2); - (void)fclose(f); - return; + aha_log("%s: BIOS ROM size invalid!\n", dev->name); + free(dev->rom1); + if (dev->rom2 != NULL) + free(dev->rom2); + (void) fclose(fp); + return; } - temp = ftell(f); + temp = ftell(fp); if (temp > ROM_SIZE) - temp = ROM_SIZE; - (void)fclose(f); + temp = ROM_SIZE; + (void) fclose(fp); /* Adjust BIOS size in chunks of 2K, as per BIOS spec. */ size = 0x10000; if (temp <= 0x8000) - size = 0x8000; + size = 0x8000; if (temp <= 0x4000) - size = 0x4000; + size = 0x4000; if (temp <= 0x2000) - size = 0x2000; + size = 0x2000; mask = (size - 1); aha_log("%s: BIOS at 0x%06lX, size %lu, mask %08lx\n", - dev->name, dev->rom_addr, size, mask); + dev->name, dev->rom_addr, size, mask); /* Initialize the ROM entry for this BIOS. */ memset(&dev->bios, 0x00, sizeof(rom_t)); @@ -803,9 +785,9 @@ aha_setbios(x54x_t *dev) /* Map this system into the memory map. */ mem_mapping_add(&dev->bios.mapping, dev->rom_addr, size, - aha_mem_read, NULL, NULL, /* aha_mem_readw, aha_mem_readl, */ - aha_mem_write, NULL, NULL, - dev->bios.rom, MEM_MAPPING_EXTERNAL, dev); + aha_mem_read, NULL, NULL, /* aha_mem_readw, aha_mem_readl, */ + aha_mem_write, NULL, NULL, + dev->bios.rom, MEM_MAPPING_EXTERNAL, dev); mem_mapping_disable(&dev->bios.mapping); /* @@ -814,41 +796,42 @@ aha_setbios(x54x_t *dev) * their way of handling issues like these at the time.. * * Patch 1: emulate the I/O ADDR SW setting by patching a - * byte in the BIOS that indicates the I/O ADDR - * switch setting on the board. + * byte in the BIOS that indicates the I/O ADDR + * switch setting on the board. */ if (dev->rom_ioaddr != 0x0000) { - /* Look up the I/O address in the table. */ - for (i=0; i<8; i++) - if (aha_ports[i] == dev->Base) break; - if (i == 8) { - aha_log("%s: invalid I/O address %04x selected!\n", - dev->name, dev->Base); - return; - } - dev->bios.rom[dev->rom_ioaddr] = (uint8_t)i; - /* Negation of the DIP switches to satify the checksum. */ - dev->bios.rom[dev->rom_ioaddr + 1] = (uint8_t)((i ^ 0xff) + 1); + /* Look up the I/O address in the table. */ + for (i = 0; i < 8; i++) + if (aha_ports[i] == dev->Base) + break; + if (i == 8) { + aha_log("%s: invalid I/O address %04x selected!\n", + dev->name, dev->Base); + return; + } + dev->bios.rom[dev->rom_ioaddr] = (uint8_t) i; + /* Negation of the DIP switches to satify the checksum. */ + dev->bios.rom[dev->rom_ioaddr + 1] = (uint8_t) ((i ^ 0xff) + 1); } } - /* Get the SCSISelect code decompressor program from the microcode rom for the AHA-1542CP. */ static void aha_setmcode(x54x_t *dev) { uint32_t temp; - FILE *f; + FILE *fp; /* Only if this device has a BIOS ROM. */ - if (dev->mcode_path == NULL) return; + if (dev->mcode_path == NULL) + return; /* Open the microcode image file and make sure it exists. */ aha_log("%s: loading microcode from '%ls'\n", dev->name, dev->bios_path); - if ((f = rom_fopen(dev->mcode_path, "rb")) == NULL) { - aha_log("%s: microcode ROM not found!\n", dev->name); - return; + if ((fp = rom_fopen(dev->mcode_path, "rb")) == NULL) { + aha_log("%s: microcode ROM not found!\n", dev->name); + return; } /* @@ -858,27 +841,27 @@ aha_setmcode(x54x_t *dev) * this special case, we can't: we may need WRITE access to the * memory later on. */ - (void)fseek(f, 0L, SEEK_END); - temp = ftell(f); - (void)fseek(f, 0L, SEEK_SET); + (void) fseek(fp, 0L, SEEK_END); + temp = ftell(fp); + (void) fseek(fp, 0L, SEEK_SET); if (temp < (dev->cmd_33_offset + dev->cmd_33_len - 1)) { - aha_log("%s: microcode ROM size invalid!\n", dev->name); - (void)fclose(f); - return; + aha_log("%s: microcode ROM size invalid!\n", dev->name); + (void) fclose(fp); + return; } /* Allocate the buffer and then read the real PnP ROM into it. */ if (aha1542cp_pnp_rom != NULL) { - free(aha1542cp_pnp_rom); - aha1542cp_pnp_rom = NULL; + free(aha1542cp_pnp_rom); + aha1542cp_pnp_rom = NULL; } aha1542cp_pnp_rom = (uint8_t *) malloc(dev->pnp_len + 7); - fseek(f, dev->pnp_offset, SEEK_SET); - (void)fread(aha1542cp_pnp_rom, dev->pnp_len, 1, f); + fseek(fp, dev->pnp_offset, SEEK_SET); + (void) !fread(aha1542cp_pnp_rom, dev->pnp_len, 1, fp); memset(&(aha1542cp_pnp_rom[4]), 0x00, 5); - fseek(f, dev->pnp_offset + 4, SEEK_SET); - (void)fread(&(aha1542cp_pnp_rom[9]), dev->pnp_len - 4, 1, f); + fseek(fp, dev->pnp_offset + 4, SEEK_SET); + (void) !fread(&(aha1542cp_pnp_rom[9]), dev->pnp_len - 4, 1, fp); /* Even the real AHA-1542CP microcode seem to be flipping bit 4 to not erroneously indicate there is a range length. */ aha1542cp_pnp_rom[0x87] |= 0x04; @@ -888,75 +871,72 @@ aha_setmcode(x54x_t *dev) aha1542cp_pnp_rom[dev->pnp_len + 6] = 0x00; /* Load the SCSISelect decompression code. */ - fseek(f, dev->cmd_33_offset, SEEK_SET); - (void)fread(dev->cmd_33_buf, dev->cmd_33_len, 1, f); + fseek(fp, dev->cmd_33_offset, SEEK_SET); + (void) !fread(dev->cmd_33_buf, dev->cmd_33_len, 1, fp); - (void)fclose(f); + (void) fclose(fp); } - static void aha_initnvr(x54x_t *dev) { /* Initialize the on-board EEPROM. */ - dev->nvr[0] = dev->HostID; /* SCSI ID 7 */ + dev->nvr[0] = dev->HostID; /* SCSI ID 7 */ dev->nvr[0] |= (0x10 | 0x20 | 0x40); - if (dev->fdc_address == 0x370) - dev->nvr[0] |= EE0_ALTFLOP; - dev->nvr[1] = dev->Irq-9; /* IRQ15 */ - dev->nvr[1] |= (dev->DmaChannel<<4); /* DMA6 */ - dev->nvr[2] = (EE2_HABIOS | /* BIOS enabled */ - EE2_DYNSCAN | /* scan bus */ - EE2_EXT1G | EE2_RMVOK); /* Imm return on seek */ - dev->nvr[3] = SPEED_50; /* speed 5.0 MB/s */ - dev->nvr[6] = (EE6_TERM | /* host term enable */ - EE6_RSTBUS); /* reset SCSI bus on boot*/ + if (dev->fdc_address == FDC_SECONDARY_ADDR) + dev->nvr[0] |= EE0_ALTFLOP; + dev->nvr[1] = dev->Irq - 9; /* IRQ15 */ + dev->nvr[1] |= (dev->DmaChannel << 4); /* DMA6 */ + dev->nvr[2] = (EE2_HABIOS | /* BIOS enabled */ + EE2_DYNSCAN | /* scan bus */ + EE2_EXT1G | EE2_RMVOK); /* Imm return on seek */ + dev->nvr[3] = SPEED_50; /* speed 5.0 MB/s */ + dev->nvr[6] = (EE6_TERM | /* host term enable */ + EE6_RSTBUS); /* reset SCSI bus on boot*/ } - /* Initialize the board's EEPROM (NVR.) */ static void aha_setnvr(x54x_t *dev) { - FILE *f; + FILE *fp; /* Only if this device has an EEPROM. */ - if (dev->nvr_path == NULL) return; + if (dev->nvr_path == NULL) + return; /* Allocate and initialize the EEPROM. */ - dev->nvr = (uint8_t *)malloc(NVR_SIZE); + dev->nvr = (uint8_t *) malloc(NVR_SIZE); memset(dev->nvr, 0x00, NVR_SIZE); - f = nvr_fopen(dev->nvr_path, "rb"); - if (f) { - if (fread(dev->nvr, 1, NVR_SIZE, f) != NVR_SIZE) - fatal("aha_setnvr(): Error reading data\n"); - fclose(f); - f = NULL; + fp = nvr_fopen(dev->nvr_path, "rb"); + if (fp) { + if (fread(dev->nvr, 1, NVR_SIZE, fp) != NVR_SIZE) + fatal("aha_setnvr(): Error reading data\n"); + fclose(fp); + fp = NULL; } else - aha_initnvr(dev); + aha_initnvr(dev); if (dev->type == AHA_154xCF) { - if (dev->fdc_address > 0) { - fdc_remove(dev->fdc); - fdc_set_base(dev->fdc, (dev->nvr[0] & EE0_ALTFLOP) ? 0x370 : 0x3f0); - } + if (dev->fdc_address > 0) { + fdc_remove(dev->fdc); + fdc_set_base(dev->fdc, (dev->nvr[0] & EE0_ALTFLOP) ? FDC_SECONDARY_ADDR : FDC_PRIMARY_ADDR); + } } } - void aha1542cp_close(void *priv) { if (aha1542cp_pnp_rom != NULL) { - free(aha1542cp_pnp_rom); - aha1542cp_pnp_rom = NULL; + free(aha1542cp_pnp_rom); + aha1542cp_pnp_rom = NULL; } x54x_close(priv); } - /* General initialization routine for all boards. */ static void * aha_init(const device_t *info) @@ -964,7 +944,7 @@ aha_init(const device_t *info) x54x_t *dev; /* Call common initializer. */ - dev = x54x_init(info); + dev = x54x_init(info); dev->bus = scsi_get_bus(); /* @@ -974,144 +954,154 @@ aha_init(const device_t *info) * and so any info we get here will be overwritten by the * MCA-assigned values later on! */ - dev->Base = device_get_config_hex16("base"); - dev->Irq = device_get_config_int("irq"); + dev->Base = device_get_config_hex16("base"); + dev->Irq = device_get_config_int("irq"); dev->DmaChannel = device_get_config_int("dma"); - dev->rom_addr = device_get_config_hex20("bios_addr"); + dev->rom_addr = device_get_config_hex20("bios_addr"); if (!(dev->card_bus & DEVICE_MCA)) - dev->fdc_address = device_get_config_hex16("fdc_addr"); + dev->fdc_address = device_get_config_hex16("fdc_addr"); else - dev->fdc_address = 0; - dev->HostID = 7; /* default HA ID */ + dev->fdc_address = 0; + dev->HostID = 7; /* default HA ID */ dev->setup_info_len = sizeof(aha_setup_t); - dev->max_id = 7; - dev->flags = 0; + dev->max_id = 7; + dev->flags = 0; - dev->ven_callback = aha_callback; - dev->ven_cmd_is_fast = aha_cmd_is_fast; - dev->ven_fast_cmds = aha_fast_cmds; + dev->ven_callback = aha_callback; + dev->ven_cmd_is_fast = aha_cmd_is_fast; + dev->ven_fast_cmds = aha_fast_cmds; dev->get_ven_param_len = aha_param_len; - dev->ven_cmds = aha_cmds; - dev->get_ven_data = aha_setup_data; + dev->ven_cmds = aha_cmds; + dev->get_ven_data = aha_setup_data; - dev->mcode_path = NULL; - dev->cmd_33_len = 0x0000; + dev->mcode_path = NULL; + dev->cmd_33_len = 0x0000; dev->cmd_33_offset = 0x0000; memset(dev->cmd_33_buf, 0x00, 4096); strcpy(dev->vendor, "Adaptec"); /* Perform per-board initialization. */ - switch(dev->type) { - case AHA_154xA: - strcpy(dev->name, "AHA-154xA"); - dev->fw_rev = "A003"; /* The 3.07 microcode says A006. */ - dev->bios_path = "roms/scsi/adaptec/aha1540a307.bin"; /*Only for port 0x330*/ - /* This is configurable from the configuration for the 154xB, the rest of the controllers read it from the EEPROM. */ - dev->HostID = device_get_config_int("hostid"); - dev->rom_shram = 0x3F80; /* shadow RAM address base */ - dev->rom_shramsz = 128; /* size of shadow RAM */ - dev->ha_bps = 5000000.0; /* normal SCSI */ - break; - - case AHA_154xB: - strcpy(dev->name, "AHA-154xB"); - switch(dev->Base) { - case 0x0330: - dev->bios_path = - "roms/scsi/adaptec/aha1540b320_330.bin"; - break; + switch (dev->type) { + case AHA_154xA: + strcpy(dev->name, "AHA-154xA"); + dev->fw_rev = "A003"; /* The 3.07 microcode says A006. */ + dev->bios_path = "roms/scsi/adaptec/aha1540a307.bin"; /*Only for port 0x330*/ + /* This is configurable from the configuration for the 154xB, the rest of the controllers read it from the EEPROM. */ + dev->HostID = device_get_config_int("hostid"); + dev->rom_shram = 0x3F80; /* shadow RAM address base */ + dev->rom_shramsz = 128; /* size of shadow RAM */ + dev->ha_bps = 5000000.0; /* normal SCSI */ + break; - case 0x0334: - dev->bios_path = - "roms/scsi/adaptec/aha1540b320_334.bin"; - break; - } - dev->fw_rev = "A005"; /* The 3.2 microcode says A012. */ - /* This is configurable from the configuration for the 154xB, the rest of the controllers read it from the EEPROM. */ - dev->HostID = device_get_config_int("hostid"); - dev->rom_shram = 0x3F80; /* shadow RAM address base */ - dev->rom_shramsz = 128; /* size of shadow RAM */ - dev->ha_bps = 5000000.0; /* normal SCSI */ - break; + case AHA_154xB: + strcpy(dev->name, "AHA-154xB"); + switch (dev->Base) { + case 0x0330: + dev->bios_path = "roms/scsi/adaptec/aha1540b320_330.bin"; + break; - case AHA_154xC: - strcpy(dev->name, "AHA-154xC"); - dev->bios_path = "roms/scsi/adaptec/aha1542c102.bin"; - dev->nvr_path = "aha1542c.nvr"; - dev->fw_rev = "D001"; - dev->rom_shram = 0x3F80; /* shadow RAM address base */ - dev->rom_shramsz = 128; /* size of shadow RAM */ - dev->rom_ioaddr = 0x3F7E; /* [2:0] idx into addr table */ - dev->rom_fwhigh = 0x0022; /* firmware version (hi/lo) */ - dev->ven_get_host_id = aha_get_host_id; /* function to return host ID from EEPROM */ - dev->ven_get_irq = aha_get_irq; /* function to return IRQ from EEPROM */ - dev->ven_get_dma = aha_get_dma; /* function to return DMA channel from EEPROM */ - dev->ha_bps = 5000000.0; /* normal SCSI */ - break; + case 0x0334: + dev->bios_path = "roms/scsi/adaptec/aha1540b320_334.bin"; + break; - case AHA_154xCF: - strcpy(dev->name, "AHA-154xCF"); - dev->bios_path = "roms/scsi/adaptec/aha1542cf211.bin"; - dev->nvr_path = "aha1542cf.nvr"; - dev->fw_rev = "E001"; - dev->rom_shram = 0x3F80; /* shadow RAM address base */ - dev->rom_shramsz = 128; /* size of shadow RAM */ - dev->rom_ioaddr = 0x3F7E; /* [2:0] idx into addr table */ - dev->rom_fwhigh = 0x0022; /* firmware version (hi/lo) */ - dev->flags |= X54X_CDROM_BOOT; - dev->ven_get_host_id = aha_get_host_id; /* function to return host ID from EEPROM */ - dev->ven_get_irq = aha_get_irq; /* function to return IRQ from EEPROM */ - dev->ven_get_dma = aha_get_dma; /* function to return DMA channel from EEPROM */ - dev->ha_bps = 10000000.0; /* fast SCSI */ - if (dev->fdc_address > 0) - dev->fdc = device_add(&fdc_at_device); - break; + default: + break; + } + dev->fw_rev = "A005"; /* The 3.2 microcode says A012. */ + /* This is configurable from the configuration for the 154xB, the rest of the controllers read it from the EEPROM. */ + dev->HostID = device_get_config_int("hostid"); + dev->rom_shram = 0x3F80; /* shadow RAM address base */ + dev->rom_shramsz = 128; /* size of shadow RAM */ + dev->ha_bps = 5000000.0; /* normal SCSI */ + break; - case AHA_154xCP: - strcpy(dev->name, "AHA-154xCP"); - dev->bios_path = "roms/scsi/adaptec/aha1542cp102.bin"; - dev->mcode_path = "roms/scsi/adaptec/908301-00_f_mcode_17c9.u12"; - dev->nvr_path = "aha1542cp.nvr"; - dev->fw_rev = "F001"; - dev->rom_shram = 0x3F80; /* shadow RAM address base */ - dev->rom_shramsz = 128; /* size of shadow RAM */ - dev->rom_ioaddr = 0x3F7E; /* [2:0] idx into addr table */ - dev->rom_fwhigh = 0x0055; /* firmware version (hi/lo) */ - dev->flags |= X54X_CDROM_BOOT; - dev->flags |= X54X_ISAPNP; - dev->ven_get_host_id = aha_get_host_id; /* function to return host ID from EEPROM */ - dev->ven_get_irq = aha_get_irq; /* function to return IRQ from EEPROM */ - dev->ven_get_dma = aha_get_dma; /* function to return DMA channel from EEPROM */ - dev->ha_bps = 10000000.0; /* fast SCSI */ - dev->pnp_len = 0x00be; /* length of the PnP ROM */ - dev->pnp_offset = 0x533d; /* offset of the PnP ROM in the microcode ROM */ - dev->cmd_33_len = 0x06dc; /* length of the SCSISelect code expansion routine returned by - SCSI controller command 0x33 */ - dev->cmd_33_offset = 0x7000; /* offset of the SCSISelect code expansion routine in the - microcode ROM */ - aha_setmcode(dev); - if (aha1542cp_pnp_rom) - isapnp_add_card(aha1542cp_pnp_rom, dev->pnp_len + 7, aha_pnp_config_changed, NULL, NULL, NULL, dev); + case AHA_154xC: + strcpy(dev->name, "AHA-154xC"); + dev->bios_path = "roms/scsi/adaptec/aha1542c102.bin"; + dev->nvr_path = "aha1542c.nvr"; + dev->fw_rev = "D001"; + dev->rom_shram = 0x3F80; /* shadow RAM address base */ + dev->rom_shramsz = 128; /* size of shadow RAM */ + dev->rom_ioaddr = 0x3F7E; /* [2:0] idx into addr table */ + dev->rom_fwhigh = 0x0022; /* firmware version (hi/lo) */ + dev->flags |= X54X_HAS_SIGNATURE; + dev->ven_get_host_id = aha_get_host_id; /* function to return host ID from EEPROM */ + dev->ven_get_irq = aha_get_irq; /* function to return IRQ from EEPROM */ + dev->ven_get_dma = aha_get_dma; /* function to return DMA channel from EEPROM */ + dev->ha_bps = 5000000.0; /* normal SCSI */ + break; + + case AHA_154xCF: + strcpy(dev->name, "AHA-154xCF"); + dev->bios_path = "roms/scsi/adaptec/aha1542cf211.bin"; + dev->nvr_path = "aha1542cf.nvr"; + dev->fw_rev = "E001"; + dev->rom_shram = 0x3F80; /* shadow RAM address base */ + dev->rom_shramsz = 128; /* size of shadow RAM */ + dev->rom_ioaddr = 0x3F7E; /* [2:0] idx into addr table */ + dev->rom_fwhigh = 0x0022; /* firmware version (hi/lo) */ + dev->flags |= X54X_CDROM_BOOT; + dev->flags |= X54X_HAS_SIGNATURE; + dev->ven_get_host_id = aha_get_host_id; /* function to return host ID from EEPROM */ + dev->ven_get_irq = aha_get_irq; /* function to return IRQ from EEPROM */ + dev->ven_get_dma = aha_get_dma; /* function to return DMA channel from EEPROM */ + dev->ha_bps = 10000000.0; /* fast SCSI */ + if (dev->fdc_address > 0) + dev->fdc = device_add(&fdc_at_device); + break; + + case AHA_154xCP: + strcpy(dev->name, "AHA-154xCP"); + dev->bios_path = "roms/scsi/adaptec/aha1542cp102.bin"; + dev->mcode_path = "roms/scsi/adaptec/908301-00_f_mcode_17c9.u12"; + dev->nvr_path = "aha1542cp.nvr"; + dev->fw_rev = "F001"; + dev->rom_shram = 0x3F80; /* shadow RAM address base */ + dev->rom_shramsz = 128; /* size of shadow RAM */ + dev->rom_ioaddr = 0x3F7E; /* [2:0] idx into addr table */ + dev->rom_fwhigh = 0x0055; /* firmware version (hi/lo) */ + dev->flags |= X54X_CDROM_BOOT; + dev->flags |= X54X_ISAPNP; + dev->flags |= X54X_HAS_SIGNATURE; + dev->ven_get_host_id = aha_get_host_id; /* function to return host ID from EEPROM */ + dev->ven_get_irq = aha_get_irq; /* function to return IRQ from EEPROM */ + dev->ven_get_dma = aha_get_dma; /* function to return DMA channel from EEPROM */ + dev->ha_bps = 10000000.0; /* fast SCSI */ + dev->pnp_len = 0x00be; /* length of the PnP ROM */ + dev->pnp_offset = 0x533d; /* offset of the PnP ROM in the microcode ROM */ + dev->cmd_33_len = 0x06dc; /* length of the SCSISelect code expansion routine returned by + SCSI controller command 0x33 */ + dev->cmd_33_offset = 0x7000; /* offset of the SCSISelect code expansion routine in the + microcode ROM */ + aha_setmcode(dev); + if (aha1542cp_pnp_rom) + isapnp_add_card(aha1542cp_pnp_rom, dev->pnp_len + 7, aha_pnp_config_changed, NULL, NULL, NULL, dev); #ifdef AHA1542CP_FDC - dev->fdc = device_add(&fdc_at_device); + dev->fdc = device_add(&fdc_at_device); #endif - break; + break; - case AHA_1640: - strcpy(dev->name, "AHA-1640"); - dev->bios_path = "roms/scsi/adaptec/aha1640.bin"; - dev->fw_rev = "BB01"; + case AHA_1640: + strcpy(dev->name, "AHA-1640"); + dev->bios_path = "roms/scsi/adaptec/aha1640.bin"; + dev->fw_rev = "BB01"; - dev->flags |= X54X_LBA_BIOS; + dev->flags |= X54X_LBA_BIOS; + dev->flags |= X54X_HAS_SIGNATURE; /*To be confirmed*/ - /* Enable MCA. */ - dev->pos_regs[0] = 0x1F; /* MCA board ID */ - dev->pos_regs[1] = 0x0F; - mca_add(aha_mca_read, aha_mca_write, aha_mca_feedb, NULL, dev); - dev->ha_bps = 5000000.0; /* normal SCSI */ - break; - } + /* Enable MCA. */ + dev->pos_regs[0] = 0x1F; /* MCA board ID */ + dev->pos_regs[1] = 0x0F; + mca_add(aha_mca_read, aha_mca_write, aha_mca_feedb, NULL, dev); + dev->ha_bps = 5000000.0; /* normal SCSI */ + break; + + default: + break; + } + + scsi_bus_set_speed(dev->bus, dev->ha_bps); /* Initialize ROM BIOS if needed. */ aha_setbios(dev); @@ -1120,441 +1110,362 @@ aha_init(const device_t *info) aha_setnvr(dev); if (dev->Base != 0) { - /* Initialize the device. */ - x54x_device_reset(dev); + /* Initialize the device. */ + x54x_device_reset(dev); if (!(dev->card_bus & DEVICE_MCA) && !(dev->flags & X54X_ISAPNP)) { - /* Register our address space. */ - x54x_io_set(dev, dev->Base, 4); + /* Register our address space. */ + x54x_io_set(dev, dev->Base, 4); - /* Enable the memory. */ - if (dev->rom_addr != 0x000000) { - mem_mapping_enable(&dev->bios.mapping); - mem_mapping_set_addr(&dev->bios.mapping, dev->rom_addr, ROM_SIZE); - } - } + /* Enable the memory. */ + if (dev->rom_addr != 0x000000) { + mem_mapping_enable(&dev->bios.mapping); + mem_mapping_set_addr(&dev->bios.mapping, dev->rom_addr, ROM_SIZE); + } + } } - return(dev); + return dev; } - +// clang-format off static const device_config_t aha_154xb_config[] = { - { - "base", "Address", CONFIG_HEX16, "", 0x334, "", { 0 }, - { - { - "None", 0 - }, - { - "0x330", 0x330 - }, - { - "0x334", 0x334 - }, - { - "0x230", 0x230 - }, - { - "0x234", 0x234 - }, - { - "0x130", 0x130 - }, - { - "0x134", 0x134 - }, - { - "" - } - }, + { + .name = "base", + .description = "Address", + .type = CONFIG_HEX16, + .default_string = "", + .default_int = 0x334, + .file_filter = "", + .spinner = { 0 }, + .selection = { + { .description = "None", .value = 0 }, + { .description = "0x330", .value = 0x330 }, + { .description = "0x334", .value = 0x334 }, + { .description = "0x230", .value = 0x230 }, + { .description = "0x234", .value = 0x234 }, + { .description = "0x130", .value = 0x130 }, + { .description = "0x134", .value = 0x134 }, + { .description = "" } }, - { - "irq", "IRQ", CONFIG_SELECTION, "", 11, "", { 0 }, - { - { - "IRQ 9", 9 - }, - { - "IRQ 10", 10 - }, - { - "IRQ 11", 11 - }, - { - "IRQ 12", 12 - }, - { - "IRQ 14", 14 - }, - { - "IRQ 15", 15 - }, - { - "" - } - }, + }, + { + .name = "irq", + .description = "IRQ", + .type = CONFIG_SELECTION, + .default_string = "", + .default_int = 11, + .file_filter = "", + .spinner = { 0 }, + .selection = { + { .description = "IRQ 9", .value = 9 }, + { .description = "IRQ 10", .value = 10 }, + { .description = "IRQ 11", .value = 11 }, + { .description = "IRQ 12", .value = 12 }, + { .description = "IRQ 14", .value = 14 }, + { .description = "IRQ 15", .value = 15 }, + { .description = "" } }, - { - "dma", "DMA channel", CONFIG_SELECTION, "", 6, "", { 0 }, - { - { - "DMA 5", 5 - }, - { - "DMA 6", 6 - }, - { - "DMA 7", 7 - }, - { - "" - } - }, + }, + { + .name = "dma", + .description = "DMA channel", + .type = CONFIG_SELECTION, + .default_string = "", + .default_int = 6, + .file_filter = "", + .spinner = { 0 }, + .selection = { + { .description = "DMA 5", .value = 5 }, + { .description = "DMA 6", .value = 6 }, + { .description = "DMA 7", .value = 7 }, + { .description = "" } }, - { - "hostid", "Host ID", CONFIG_SELECTION, "", 7, "", { 0 }, - { - { - "0", 0 - }, - { - "1", 1 - }, - { - "2", 2 - }, - { - "3", 3 - }, - { - "4", 4 - }, - { - "5", 5 - }, - { - "6", 6 - }, - { - "7", 7 - }, - { - "" - } - }, + }, + { + .name = "hostid", + .description = "Host ID", + .type = CONFIG_SELECTION, + .default_string = "", + .default_int = 7, + .file_filter = "", + .spinner = { 0 }, + .selection = { + { .description = "0", .value = 0 }, + { .description = "1", .value = 1 }, + { .description = "2", .value = 2 }, + { .description = "3", .value = 3 }, + { .description = "4", .value = 4 }, + { .description = "5", .value = 5 }, + { .description = "6", .value = 6 }, + { .description = "7", .value = 7 }, + { .description = "" } }, - { - "bios_addr", "BIOS Address", CONFIG_HEX20, "", 0, "", { 0 }, - { - { - "Disabled", 0 - }, - { - "C800H", 0xc8000 - }, - { - "D000H", 0xd0000 - }, - { - "D800H", 0xd8000 - }, - { - "DC00H", 0xdc000 - }, - { - "" - } - }, + }, + { + .name = "bios_addr", + .description = "BIOS Address", + .type = CONFIG_HEX20, + .default_string = "", + .default_int = 0, + .file_filter = "", + .spinner = { 0 }, + .selection = { + { .description = "Disabled", .value = 0 }, + { .description = "C800H", .value = 0xc8000 }, + { .description = "D000H", .value = 0xd0000 }, + { .description = "D800H", .value = 0xd8000 }, + { .description = "DC00H", .value = 0xdc000 }, + { .description = "" } }, - { - "", "", -1 - } + }, + { .name = "", .description = "", .type = CONFIG_END } }; static const device_config_t aha_154x_config[] = { - { - "base", "Address", CONFIG_HEX16, "", 0x334, "", { 0 }, - { - { - "None", 0 - }, - { - "0x330", 0x330 - }, - { - "0x334", 0x334 - }, - { - "0x230", 0x230 - }, - { - "0x234", 0x234 - }, - { - "0x130", 0x130 - }, - { - "0x134", 0x134 - }, - { - "" - } - }, + { + .name = "base", + .description = "Address", + .type = CONFIG_HEX16, + .default_string = "", + .default_int = 0x334, + .file_filter = "", + .spinner = { 0 }, + .selection = { + { .description = "None", .value = 0 }, + { .description = "0x330", .value = 0x330 }, + { .description = "0x334", .value = 0x334 }, + { .description = "0x230", .value = 0x230 }, + { .description = "0x234", .value = 0x234 }, + { .description = "0x130", .value = 0x130 }, + { .description = "0x134", .value = 0x134 }, + { .description = "" } }, - { - "irq", "IRQ", CONFIG_SELECTION, "", 11, "", { 0 }, - { - { - "IRQ 9", 9 - }, - { - "IRQ 10", 10 - }, - { - "IRQ 11", 11 - }, - { - "IRQ 12", 12 - }, - { - "IRQ 14", 14 - }, - { - "IRQ 15", 15 - }, - { - "" - } - }, + }, + { + .name = "irq", + .description = "IRQ", + .type = CONFIG_SELECTION, + .default_string = "", + .default_int = 11, + .file_filter = "", + .spinner = { 0 }, + .selection = { + { .description = "IRQ 9", .value = 9 }, + { .description = "IRQ 10", .value = 10 }, + { .description = "IRQ 11", .value = 11 }, + { .description = "IRQ 12", .value = 12 }, + { .description = "IRQ 14", .value = 14 }, + { .description = "IRQ 15", .value = 15 }, + { .description = "" } }, - { - "dma", "DMA channel", CONFIG_SELECTION, "", 6, "", { 0 }, - { - { - "DMA 5", 5 - }, - { - "DMA 6", 6 - }, - { - "DMA 7", 7 - }, - { - "" - } - }, + }, + { + .name = "dma", + .description = "DMA channel", + .type = CONFIG_SELECTION, + .default_string = "", + .default_int = 6, + .file_filter = "", + .spinner = { 0 }, + .selection = { + { .description = "DMA 5", .value = 5 }, + { .description = "DMA 6", .value = 6 }, + { .description = "DMA 7", .value = 7 }, + { .description = "" } }, - { - "bios_addr", "BIOS Address", CONFIG_HEX20, "", 0, "", { 0 }, - { - { - "Disabled", 0 - }, - { - "C800H", 0xc8000 - }, - { - "D000H", 0xd0000 - }, - { - "D800H", 0xd8000 - }, - { - "DC00H", 0xdc000 - }, - { - "" - } - }, + }, + { + .name = "bios_addr", + .description = "BIOS Address", + .type = CONFIG_HEX20, + .default_string = "", + .default_int = 0, + .file_filter = "", + .spinner = { 0 }, + .selection = { + { .description = "Disabled", .value = 0 }, + { .description = "C800H", .value = 0xc8000 }, + { .description = "D000H", .value = 0xd0000 }, + { .description = "D800H", .value = 0xd8000 }, + { .description = "DC00H", .value = 0xdc000 }, + { .description = "" } + }, }, - { - "", "", -1 - } + { .name = "", .description = "", .type = CONFIG_END } }; - static const device_config_t aha_154xcf_config[] = { - { - "base", "Address", CONFIG_HEX16, "", 0x334, "", { 0 }, - { - { - "None", 0 - }, - { - "0x330", 0x330 - }, - { - "0x334", 0x334 - }, - { - "0x230", 0x230 - }, - { - "0x234", 0x234 - }, - { - "0x130", 0x130 - }, - { - "0x134", 0x134 - }, - { - "" - } - }, + { + .name = "base", + .description = "Address", + .type = CONFIG_HEX16, + .default_string = "", + .default_int = 0x334, + .file_filter = "", + .spinner = { 0 }, + .selection = { + { .description = "None", .value = 0 }, + { .description = "0x330", .value = 0x330 }, + { .description = "0x334", .value = 0x334 }, + { .description = "0x230", .value = 0x230 }, + { .description = "0x234", .value = 0x234 }, + { .description = "0x130", .value = 0x130 }, + { .description = "0x134", .value = 0x134 }, + { .description = "" } }, - { - "irq", "IRQ", CONFIG_SELECTION, "", 11, "", { 0 }, - { - { - "IRQ 9", 9 - }, - { - "IRQ 10", 10 - }, - { - "IRQ 11", 11 - }, - { - "IRQ 12", 12 - }, - { - "IRQ 14", 14 - }, - { - "IRQ 15", 15 - }, - { - "" - } - }, + }, + { + .name = "irq", + .description = "IRQ", + .type = CONFIG_SELECTION, + .default_string = "", + .default_int = 11, + .file_filter = "", + .spinner = { 0 }, + .selection = { + { .description = "IRQ 9", .value = 9 }, + { .description = "IRQ 10", .value = 10 }, + { .description = "IRQ 11", .value = 11 }, + { .description = "IRQ 12", .value = 12 }, + { .description = "IRQ 14", .value = 14 }, + { .description = "IRQ 15", .value = 15 }, + { .description = "" } }, - { - "dma", "DMA channel", CONFIG_SELECTION, "", 6, "", { 0 }, - { - { - "DMA 5", 5 - }, - { - "DMA 6", 6 - }, - { - "DMA 7", 7 - }, - { - "" - } - }, + }, + { + .name = "dma", + .description = "DMA channel", + .type = CONFIG_SELECTION, + .default_string = "", + .default_int = 6, + .file_filter = "", + .spinner = { 0 }, + .selection = { + { .description = "DMA 5", .value = 5 }, + { .description = "DMA 6", .value = 6 }, + { .description = "DMA 7", .value = 7 }, + { .description = "" } }, - { - "bios_addr", "BIOS Address", CONFIG_HEX20, "", 0, "", { 0 }, - { - { - "Disabled", 0 - }, - { - "C800H", 0xc8000 - }, - { - "CC00H", 0xcc000 - }, - { - "D000H", 0xd0000 - }, - { - "D400H", 0xd4000 - }, - { - "D800H", 0xd8000 - }, - { - "DC00H", 0xdc000 - }, - { - "" - } - }, + }, + { + .name = "bios_addr", + .description = "BIOS Address", + .type = CONFIG_HEX20, + .default_string = "", + .default_int = 0, + .file_filter = "", + .spinner = { 0 }, + .selection = { + { .description = "Disabled", .value = 0 }, + { .description = "C800H", .value = 0xc8000 }, + { .description = "CC00H", .value = 0xcc000 }, + { .description = "D000H", .value = 0xd0000 }, + { .description = "D400H", .value = 0xd4000 }, + { .description = "D800H", .value = 0xd8000 }, + { .description = "DC00H", .value = 0xdc000 }, + { .description = "" } }, - { - "fdc_addr", "FDC address", CONFIG_HEX16, "", 0, "", { 0 }, - { - { - "None", 0 - }, - { - "0x3f0", 0x3f0 - }, - { - "0x370", 0x370 - }, - { - "" - } - }, + }, + { + .name = "fdc_addr", + .description = "FDC address", + .type = CONFIG_HEX16, + .default_string = "", + .default_int = 0, + .file_filter = "", + .spinner = { 0 }, + .selection = { + { .description = "None", .value = 0 }, + { .description = "0x3f0", .value = FDC_PRIMARY_ADDR }, + { .description = "0x370", .value = FDC_SECONDARY_ADDR }, + { .description = "" } }, - { - "", "", -1 - } + }, + { .name = "", .description = "", .type = CONFIG_END } }; - +// clang-format on const device_t aha154xa_device = { - "Adaptec AHA-154xA", - "aha154xa", - DEVICE_ISA | DEVICE_AT, - AHA_154xA, - aha_init, x54x_close, NULL, - { NULL }, NULL, NULL, - aha_154xb_config + .name = "Adaptec AHA-154xA", + .internal_name = "aha154xa", + .flags = DEVICE_ISA | DEVICE_AT, + .local = AHA_154xA, + .init = aha_init, + .close = x54x_close, + .reset = NULL, + { .available = NULL }, + .speed_changed = NULL, + .force_redraw = NULL, + .config = aha_154xb_config }; const device_t aha154xb_device = { - "Adaptec AHA-154xB", - "aha154xb", - DEVICE_ISA | DEVICE_AT, - AHA_154xB, - aha_init, x54x_close, NULL, - { NULL }, NULL, NULL, - aha_154xb_config + .name = "Adaptec AHA-154xB", + .internal_name = "aha154xb", + .flags = DEVICE_ISA | DEVICE_AT, + .local = AHA_154xB, + .init = aha_init, + .close = x54x_close, + .reset = NULL, + { .available = NULL }, + .speed_changed = NULL, + .force_redraw = NULL, + .config = aha_154xb_config }; const device_t aha154xc_device = { - "Adaptec AHA-154xC", - "aha154xc", - DEVICE_ISA | DEVICE_AT, - AHA_154xC, - aha_init, x54x_close, NULL, - { NULL }, NULL, NULL, - aha_154x_config + .name = "Adaptec AHA-154xC", + .internal_name = "aha154xc", + .flags = DEVICE_ISA | DEVICE_AT, + .local = AHA_154xC, + .init = aha_init, + .close = x54x_close, + .reset = NULL, + { .available = NULL }, + .speed_changed = NULL, + .force_redraw = NULL, + .config = aha_154x_config }; const device_t aha154xcf_device = { - "Adaptec AHA-154xCF", - "aha154xcf", - DEVICE_ISA | DEVICE_AT, - AHA_154xCF, - aha_init, x54x_close, NULL, - { NULL }, NULL, NULL, - aha_154xcf_config + .name = "Adaptec AHA-154xCF", + .internal_name = "aha154xcf", + .flags = DEVICE_ISA | DEVICE_AT, + .local = AHA_154xCF, + .init = aha_init, + .close = x54x_close, + .reset = NULL, + { .available = NULL }, + .speed_changed = NULL, + .force_redraw = NULL, + .config = aha_154xcf_config }; const device_t aha154xcp_device = { - "Adaptec AHA-154xCP", - "aha154xcp", - DEVICE_ISA | DEVICE_AT, - AHA_154xCP, - aha_init, aha1542cp_close, NULL, - { NULL }, NULL, NULL, - NULL + .name = "Adaptec AHA-154xCP", + .internal_name = "aha154xcp", + .flags = DEVICE_ISA | DEVICE_AT, + .local = AHA_154xCP, + .init = aha_init, + .close = aha1542cp_close, + .reset = NULL, + { .available = NULL }, + .speed_changed = NULL, + .force_redraw = NULL, + .config = NULL }; const device_t aha1640_device = { - "Adaptec AHA-1640", - "aha1640", - DEVICE_MCA, - AHA_1640, - aha_init, x54x_close, NULL, - { NULL }, NULL, NULL, - NULL + .name = "Adaptec AHA-1640", + .internal_name = "aha1640", + .flags = DEVICE_MCA, + .local = AHA_1640, + .init = aha_init, + .close = x54x_close, + .reset = NULL, + { .available = NULL }, + .speed_changed = NULL, + .force_redraw = NULL, + .config = NULL }; diff --git a/src/scsi/scsi_buslogic.c b/src/scsi/scsi_buslogic.c index 5dd9003c1..ac3b464a8 100644 --- a/src/scsi/scsi_buslogic.c +++ b/src/scsi/scsi_buslogic.c @@ -1,30 +1,30 @@ /* - * 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. + * 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. * - * Emulation of BusLogic ISA and PCI SCSI controllers. Boards - * supported: + * Emulation of BusLogic ISA and PCI SCSI controllers. Boards + * supported: * - * 0 - BT-542BH ISA; - * 1 - BT-545S ISA; - * 2 - BT-958D PCI + * 0 - BT-542BH ISA; + * 1 - BT-545S ISA; + * 2 - BT-958D PCI * * * - * Authors: TheCollector1995, - * Miran Grca, - * Fred N. van Kempen, + * Authors: TheCollector1995, + * Miran Grca, + * Fred N. van Kempen, * - * Copyright 2016-2018 Miran Grca. - * Copyright 2017,2018 Fred N. van Kempen. + * Copyright 2016-2018 Miran Grca. + * Copyright 2017-2018 Fred N. van Kempen. */ +#include #include #include #include #include -#include #include #define HAVE_STDARG_H #include <86box/86box.h> @@ -47,65 +47,64 @@ #include <86box/scsi_device.h> #include <86box/scsi_x54x.h> - /* * Auto SCSI structure which is located * in host adapter RAM and contains several * configuration parameters. */ -#pragma pack(push,1) -typedef struct { - uint8_t aInternalSignature[2]; - uint8_t cbInformation; - uint8_t aHostAdaptertype[6]; - uint8_t uReserved1; - uint8_t fFloppyEnabled :1, - fFloppySecondary :1, - fLevelSensitiveInterrupt:1, - uReserved2 :2, - uSystemRAMAreForBIOS :3; - uint8_t uDMAChannel :7, - fDMAAutoConfiguration :1, - uIrqChannel :7, - fIrqAutoConfiguration :1; - uint8_t uDMATransferRate; - uint8_t uSCSIId; - uint8_t uSCSIConfiguration; - uint8_t uBusOnDelay; - uint8_t uBusOffDelay; - uint8_t uBIOSConfiguration; - uint16_t u16DeviceEnabledMask; - uint16_t u16WidePermittedMask; - uint16_t u16FastPermittedMask; - uint16_t u16SynchronousPermittedMask; - uint16_t u16DisconnectPermittedMask; - uint16_t u16SendStartUnitCommandMask; - uint16_t u16IgnoreInBIOSScanMask; - unsigned char uPCIInterruptPin : 2; - unsigned char uHostAdapterIoPortAddress : 2; - uint8_t fRoundRobinScheme : 1; - uint8_t fVesaBusSpeedGreaterThan33MHz : 1; - uint8_t fVesaBurstWrite : 1; - uint8_t fVesaBurstRead : 1; +#pragma pack(push, 1) +typedef struct AutoSCSIRam_t { + uint8_t aInternalSignature[2]; + uint8_t cbInformation; + uint8_t aHostAdaptertype[6]; + uint8_t uReserved1; + uint8_t fFloppyEnabled : 1; + uint8_t fFloppySecondary : 1; + uint8_t fLevelSensitiveInterrupt : 1; + uint8_t uReserved2 : 2; + uint8_t uSystemRAMAreForBIOS : 3; + uint8_t uDMAChannel : 7; + uint8_t fDMAAutoConfiguration : 1; + uint8_t uIrqChannel : 7; + uint8_t fIrqAutoConfiguration : 1; + uint8_t uDMATransferRate; + uint8_t uSCSIId; + uint8_t uSCSIConfiguration; + uint8_t uBusOnDelay; + uint8_t uBusOffDelay; + uint8_t uBIOSConfiguration; + uint16_t u16DeviceEnabledMask; + uint16_t u16WidePermittedMask; + uint16_t u16FastPermittedMask; + uint16_t u16SynchronousPermittedMask; + uint16_t u16DisconnectPermittedMask; + uint16_t u16SendStartUnitCommandMask; + uint16_t u16IgnoreInBIOSScanMask; + unsigned char uPCIInterruptPin : 2; + unsigned char uHostAdapterIoPortAddress : 2; + uint8_t fRoundRobinScheme : 1; + uint8_t fVesaBusSpeedGreaterThan33MHz : 1; + uint8_t fVesaBurstWrite : 1; + uint8_t fVesaBurstRead : 1; uint16_t u16UltraPermittedMask; uint32_t uReserved5; uint8_t uReserved6; uint8_t uAutoSCSIMaximumLUN; - uint8_t fReserved7 : 1; - uint8_t fSCAMDominant : 1; - uint8_t fSCAMenabled : 1; - uint8_t fSCAMLevel2 : 1; - unsigned char uReserved8 : 4; - uint8_t fInt13Extension : 1; - uint8_t fReserved9 : 1; - uint8_t fCDROMBoot : 1; - unsigned char uReserved10 : 2; - uint8_t fMultiBoot : 1; - unsigned char uReserved11 : 2; - unsigned char uBootTargetId : 4; - unsigned char uBootChannel : 4; - uint8_t fForceBusDeviceScanningOrder : 1; - unsigned char uReserved12 : 7; + uint8_t fReserved7 : 1; + uint8_t fSCAMDominant : 1; + uint8_t fSCAMenabled : 1; + uint8_t fSCAMLevel2 : 1; + unsigned char uReserved8 : 4; + uint8_t fInt13Extension : 1; + uint8_t fReserved9 : 1; + uint8_t fCDROMBoot : 1; + unsigned char uReserved10 : 2; + uint8_t fMultiBoot : 1; + unsigned char uReserved11 : 2; + unsigned char uBootTargetId : 4; + unsigned char uBootChannel : 4; + uint8_t fForceBusDeviceScanningOrder : 1; + unsigned char uReserved12 : 7; uint16_t u16NonTaggedToAlternateLunPermittedMask; uint16_t u16RenegotiateSyncAfterCheckConditionMask; uint8_t aReserved14[10]; @@ -115,186 +114,179 @@ typedef struct { #pragma pack(pop) /* The local RAM. */ -#pragma pack(push,1) +#pragma pack(push, 1) typedef union { - uint8_t u8View[256]; /* byte view */ - struct { /* structured view */ - uint8_t u8Bios[64]; /* offset 0 - 63 is for BIOS */ - AutoSCSIRam autoSCSIData; /* Auto SCSI structure */ + uint8_t u8View[256]; /* byte view */ + struct { /* structured view */ + uint8_t u8Bios[64]; /* offset 0 - 63 is for BIOS */ + AutoSCSIRam autoSCSIData; /* Auto SCSI structure */ } structured; } HALocalRAM; #pragma pack(pop) /** Structure for the INQUIRE_SETUP_INFORMATION reply. */ -#pragma pack(push,1) +#pragma pack(push, 1) typedef struct { - uint8_t uSignature; - uint8_t uCharacterD; - uint8_t uHostBusType; - uint8_t uWideTransferPermittedId0To7; - uint8_t uWideTransfersActiveId0To7; + uint8_t uSignature; + uint8_t uCharacterD; + uint8_t uHostBusType; + uint8_t uWideTransferPermittedId0To7; + uint8_t uWideTransfersActiveId0To7; ReplyInquireSetupInformationSynchronousValue SynchronousValuesId8To15[8]; - uint8_t uDisconnectPermittedId8To15; - uint8_t uReserved2; - uint8_t uWideTransferPermittedId8To15; - uint8_t uWideTransfersActiveId8To15; + uint8_t uDisconnectPermittedId8To15; + uint8_t uReserved2; + uint8_t uWideTransferPermittedId8To15; + uint8_t uWideTransfersActiveId8To15; } buslogic_setup_t; #pragma pack(pop) /* Structure for the INQUIRE_EXTENDED_SETUP_INFORMATION. */ -#pragma pack(push,1) -typedef struct { - uint8_t uBusType; - uint8_t uBiosAddress; - uint16_t u16ScatterGatherLimit; - uint8_t cMailbox; - uint32_t uMailboxAddressBase; - uint8_t uReserved1 :2, - fFastEISA :1, - uReserved2 :3, - fLevelSensitiveInterrupt:1, - uReserved3 :1; - uint8_t aFirmwareRevision[3]; - uint8_t fHostWideSCSI :1, - fHostDifferentialSCSI :1, - fHostSupportsSCAM :1, - fHostUltraSCSI :1, - fHostSmartTermination :1, - uReserved4 :3; +#pragma pack(push, 1) +typedef struct ReplyInquireExtendedSetupInformation_t { + uint8_t uBusType; + uint8_t uBiosAddress; + uint16_t u16ScatterGatherLimit; + uint8_t cMailbox; + uint32_t uMailboxAddressBase; + uint8_t uReserved1 : 2; + uint8_t fFastEISA : 1; + uint8_t uReserved2 : 3; + uint8_t fLevelSensitiveInterrupt : 1; + uint8_t uReserved3 : 1; + uint8_t aFirmwareRevision[3]; + uint8_t fHostWideSCSI : 1; + uint8_t fHostDifferentialSCSI : 1; + uint8_t fHostSupportsSCAM : 1; + uint8_t fHostUltraSCSI : 1; + uint8_t fHostSmartTermination : 1; + uint8_t uReserved4 : 3; } ReplyInquireExtendedSetupInformation; #pragma pack(pop) /* Structure for the INQUIRE_PCI_HOST_ADAPTER_INFORMATION reply. */ -#pragma pack(push,1) -typedef struct { - uint8_t IsaIOPort; - uint8_t IRQ; - uint8_t LowByteTerminated :1, - HighByteTerminated :1, - uReserved :2, /* Reserved. */ - JP1 :1, /* Whatever that means. */ - JP2 :1, /* Whatever that means. */ - JP3 :1, /* Whatever that means. */ - InformationIsValid :1; - uint8_t uReserved2; /* Reserved. */ +#pragma pack(push, 1) +typedef struct BuslogicPCIInformation_t { + uint8_t IsaIOPort; + uint8_t IRQ; + uint8_t LowByteTerminated : 1; + uint8_t HighByteTerminated : 1; + uint8_t uReserved : 2; /* Reserved. */ + uint8_t JP1 : 1; /* Whatever that means. */ + uint8_t JP2 : 1; /* Whatever that means. */ + uint8_t JP3 : 1; /* Whatever that means. */ + uint8_t InformationIsValid : 1; + uint8_t uReserved2; /* Reserved. */ } BuslogicPCIInformation_t; #pragma pack(pop) -#pragma pack(push,1) -typedef struct -{ +#pragma pack(push, 1) +typedef struct ESCMD_t { /** Data length. */ - uint32_t DataLength; + uint32_t DataLength; /** Data pointer. */ - uint32_t DataPointer; + uint32_t DataPointer; /** The device the request is sent to. */ - uint8_t TargetId; + uint8_t TargetId; /** The LUN in the device. */ - uint8_t LogicalUnit; + uint8_t LogicalUnit; /** Reserved */ - unsigned char Reserved1 : 3; + unsigned char Reserved1 : 3; /** Data direction for the request. */ - unsigned char DataDirection : 2; + unsigned char DataDirection : 2; /** Reserved */ - unsigned char Reserved2 : 3; + unsigned char Reserved2 : 3; /** Length of the SCSI CDB. */ - uint8_t CDBLength; + uint8_t CDBLength; /** The SCSI CDB. (A CDB can be 12 bytes long.) */ - uint8_t CDB[12]; + uint8_t CDB[12]; } ESCMD; #pragma pack(pop) -#pragma pack(push,1) -typedef struct { - uint8_t Count; - uint32_t Address; +#pragma pack(push, 1) +typedef struct MailboxInitExtended_t { + uint8_t Count; + uint32_t Address; } MailboxInitExtended_t; #pragma pack(pop) -#pragma pack(push,1) -typedef struct { - rom_t bios; - int ExtendedLUNCCBFormat; - int fAggressiveRoundRobinMode; - HALocalRAM LocalRAM; - int PCIBase; - int MMIOBase; - int chip; - int has_bios; - uint32_t bios_addr, - bios_size, - bios_mask; - uint8_t AutoSCSIROM[32768]; - uint8_t SCAMData[65536]; +#pragma pack(push, 1) +typedef struct buslogic_data_t { + rom_t bios; + int ExtendedLUNCCBFormat; + int fAggressiveRoundRobinMode; + HALocalRAM LocalRAM; + int PCIBase; + int MMIOBase; + int chip; + int has_bios; + uint32_t bios_addr; + uint32_t bios_size; + uint32_t bios_mask; + uint8_t AutoSCSIROM[32768]; + uint8_t SCAMData[65536]; } buslogic_data_t; #pragma pack(pop) - enum { CHIP_BUSLOGIC_ISA_542B_1991_12_14, CHIP_BUSLOGIC_ISA_545S_1992_10_05, CHIP_BUSLOGIC_ISA_542BH_1993_05_23, CHIP_BUSLOGIC_ISA_545C_1994_12_01, - CHIP_BUSLOGIC_VLB_445S_1993_11_16, - CHIP_BUSLOGIC_VLB_445C_1994_12_01, + CHIP_BUSLOGIC_VLB_445S_1993_11_16, + CHIP_BUSLOGIC_VLB_445C_1994_12_01, CHIP_BUSLOGIC_MCA_640A_1993_05_23, - CHIP_BUSLOGIC_PCI_958D_1995_12_30 + CHIP_BUSLOGIC_PCI_958D_1995_12_30 }; - #ifdef ENABLE_BUSLOGIC_LOG int buslogic_do_log = ENABLE_BUSLOGIC_LOG; - static void buslogic_log(const char *fmt, ...) { va_list ap; if (buslogic_do_log) { - va_start(ap, fmt); - pclog_ex(fmt, ap); - va_end(ap); + va_start(ap, fmt); + pclog_ex(fmt, ap); + va_end(ap); } } #else -#define buslogic_log(fmt, ...) +# define buslogic_log(fmt, ...) #endif - static char * BuslogicGetNVRFileName(buslogic_data_t *bl) { - switch(bl->chip) - { - case CHIP_BUSLOGIC_ISA_542B_1991_12_14: - return "bt542b.nvr"; - case CHIP_BUSLOGIC_ISA_545S_1992_10_05: - return "bt545s.nvr"; - case CHIP_BUSLOGIC_ISA_542BH_1993_05_23: - return "bt542bh.nvr"; - case CHIP_BUSLOGIC_ISA_545C_1994_12_01: - return "bt545c.nvr"; - case CHIP_BUSLOGIC_VLB_445S_1993_11_16: - return "bt445s.nvr"; - case CHIP_BUSLOGIC_VLB_445C_1994_12_01: - return "bt445c.nvr"; - case CHIP_BUSLOGIC_MCA_640A_1993_05_23: - return "bt640a.nvr"; - case CHIP_BUSLOGIC_PCI_958D_1995_12_30: - return "bt958d.nvr"; - default: - fatal("Unrecognized BusLogic chip: %i\n", bl->chip); - return NULL; - } + switch (bl->chip) { + case CHIP_BUSLOGIC_ISA_542B_1991_12_14: + return "bt542b.nvr"; + case CHIP_BUSLOGIC_ISA_545S_1992_10_05: + return "bt545s.nvr"; + case CHIP_BUSLOGIC_ISA_542BH_1993_05_23: + return "bt542bh.nvr"; + case CHIP_BUSLOGIC_ISA_545C_1994_12_01: + return "bt545c.nvr"; + case CHIP_BUSLOGIC_VLB_445S_1993_11_16: + return "bt445s.nvr"; + case CHIP_BUSLOGIC_VLB_445C_1994_12_01: + return "bt445c.nvr"; + case CHIP_BUSLOGIC_MCA_640A_1993_05_23: + return "bt640a.nvr"; + case CHIP_BUSLOGIC_PCI_958D_1995_12_30: + return "bt958d.nvr"; + default: + fatal("Unrecognized BusLogic chip: %i\n", bl->chip); + return NULL; + } } - static void BuslogicAutoSCSIRamSetDefaults(x54x_t *dev, uint8_t safe) { - buslogic_data_t *bl = (buslogic_data_t *) dev->ven_data; - HALocalRAM *HALR = &bl->LocalRAM; + buslogic_data_t *bl = (buslogic_data_t *) dev->ven_data; + HALocalRAM *HALR = &bl->LocalRAM; memset(&(HALR->structured.autoSCSIData), 0, sizeof(AutoSCSIRam)); @@ -308,290 +300,273 @@ BuslogicAutoSCSIRamSetDefaults(x54x_t *dev, uint8_t safe) HALR->structured.autoSCSIData.aHostAdaptertype[0] = ' '; HALR->structured.autoSCSIData.aHostAdaptertype[5] = ' '; switch (bl->chip) { - case CHIP_BUSLOGIC_ISA_542B_1991_12_14: - memcpy(&(HALR->structured.autoSCSIData.aHostAdaptertype[1]), "542B", 4); - break; - case CHIP_BUSLOGIC_ISA_545S_1992_10_05: - memcpy(&(HALR->structured.autoSCSIData.aHostAdaptertype[1]), "545S", 4); - break; - case CHIP_BUSLOGIC_ISA_542BH_1993_05_23: - memcpy(&(HALR->structured.autoSCSIData.aHostAdaptertype[1]), "542BH", 5); - break; - case CHIP_BUSLOGIC_ISA_545C_1994_12_01: - memcpy(&(HALR->structured.autoSCSIData.aHostAdaptertype[1]), "545C", 4); - break; - case CHIP_BUSLOGIC_VLB_445S_1993_11_16: - memcpy(&(HALR->structured.autoSCSIData.aHostAdaptertype[1]), "445S", 4); - break; - case CHIP_BUSLOGIC_VLB_445C_1994_12_01: - memcpy(&(HALR->structured.autoSCSIData.aHostAdaptertype[1]), "445C", 4); - break; - case CHIP_BUSLOGIC_MCA_640A_1993_05_23: - memcpy(&(HALR->structured.autoSCSIData.aHostAdaptertype[1]), "640A", 4); - break; - case CHIP_BUSLOGIC_PCI_958D_1995_12_30: - memcpy(&(HALR->structured.autoSCSIData.aHostAdaptertype[1]), "958D", 4); - break; + case CHIP_BUSLOGIC_ISA_542B_1991_12_14: + memcpy(&(HALR->structured.autoSCSIData.aHostAdaptertype[1]), "542B", 4); + break; + case CHIP_BUSLOGIC_ISA_545S_1992_10_05: + memcpy(&(HALR->structured.autoSCSIData.aHostAdaptertype[1]), "545S", 4); + break; + case CHIP_BUSLOGIC_ISA_542BH_1993_05_23: + memcpy(&(HALR->structured.autoSCSIData.aHostAdaptertype[1]), "542BH", 5); + break; + case CHIP_BUSLOGIC_ISA_545C_1994_12_01: + memcpy(&(HALR->structured.autoSCSIData.aHostAdaptertype[1]), "545C", 4); + break; + case CHIP_BUSLOGIC_VLB_445S_1993_11_16: + memcpy(&(HALR->structured.autoSCSIData.aHostAdaptertype[1]), "445S", 4); + break; + case CHIP_BUSLOGIC_VLB_445C_1994_12_01: + memcpy(&(HALR->structured.autoSCSIData.aHostAdaptertype[1]), "445C", 4); + break; + case CHIP_BUSLOGIC_MCA_640A_1993_05_23: + memcpy(&(HALR->structured.autoSCSIData.aHostAdaptertype[1]), "640A", 4); + break; + case CHIP_BUSLOGIC_PCI_958D_1995_12_30: + memcpy(&(HALR->structured.autoSCSIData.aHostAdaptertype[1]), "958D", 4); + break; + + default: + break; } HALR->structured.autoSCSIData.fLevelSensitiveInterrupt = (bl->chip == CHIP_BUSLOGIC_PCI_958D_1995_12_30) ? 1 : 0; - HALR->structured.autoSCSIData.uSystemRAMAreForBIOS = 6; + HALR->structured.autoSCSIData.uSystemRAMAreForBIOS = 6; if (bl->chip != CHIP_BUSLOGIC_PCI_958D_1995_12_30) { - switch(dev->DmaChannel) { - case 5: - HALR->structured.autoSCSIData.uDMAChannel = 1; - break; - case 6: - HALR->structured.autoSCSIData.uDMAChannel = 2; - break; - case 7: - HALR->structured.autoSCSIData.uDMAChannel = 3; - break; - default: - HALR->structured.autoSCSIData.uDMAChannel = 0; - break; - } + switch (dev->DmaChannel) { + case 5: + HALR->structured.autoSCSIData.uDMAChannel = 1; + break; + case 6: + HALR->structured.autoSCSIData.uDMAChannel = 2; + break; + case 7: + HALR->structured.autoSCSIData.uDMAChannel = 3; + break; + default: + HALR->structured.autoSCSIData.uDMAChannel = 0; + break; + } } HALR->structured.autoSCSIData.fDMAAutoConfiguration = (bl->chip == CHIP_BUSLOGIC_PCI_958D_1995_12_30) ? 0 : 1; if (bl->chip != CHIP_BUSLOGIC_PCI_958D_1995_12_30) { - switch(dev->Irq) { - case 9: - HALR->structured.autoSCSIData.uIrqChannel = 1; - break; - case 10: - HALR->structured.autoSCSIData.uIrqChannel = 2; - break; - case 11: - HALR->structured.autoSCSIData.uIrqChannel = 3; - break; - case 12: - HALR->structured.autoSCSIData.uIrqChannel = 4; - break; - case 14: - HALR->structured.autoSCSIData.uIrqChannel = 5; - break; - case 15: - HALR->structured.autoSCSIData.uIrqChannel = 6; - break; - default: - HALR->structured.autoSCSIData.uIrqChannel = 0; - break; - } + switch (dev->Irq) { + case 9: + HALR->structured.autoSCSIData.uIrqChannel = 1; + break; + case 10: + HALR->structured.autoSCSIData.uIrqChannel = 2; + break; + case 11: + HALR->structured.autoSCSIData.uIrqChannel = 3; + break; + case 12: + HALR->structured.autoSCSIData.uIrqChannel = 4; + break; + case 14: + HALR->structured.autoSCSIData.uIrqChannel = 5; + break; + case 15: + HALR->structured.autoSCSIData.uIrqChannel = 6; + break; + default: + HALR->structured.autoSCSIData.uIrqChannel = 0; + break; + } } HALR->structured.autoSCSIData.fIrqAutoConfiguration = (bl->chip == CHIP_BUSLOGIC_PCI_958D_1995_12_30) ? 0 : 1; HALR->structured.autoSCSIData.uDMATransferRate = (bl->chip == CHIP_BUSLOGIC_PCI_958D_1995_12_30) ? 0 : 1; - HALR->structured.autoSCSIData.uSCSIId = 7; + HALR->structured.autoSCSIData.uSCSIId = 7; HALR->structured.autoSCSIData.uSCSIConfiguration = 0x3F; - HALR->structured.autoSCSIData.uBusOnDelay = (bl->chip == CHIP_BUSLOGIC_PCI_958D_1995_12_30) ? 0 : 7; - HALR->structured.autoSCSIData.uBusOffDelay = (bl->chip == CHIP_BUSLOGIC_PCI_958D_1995_12_30) ? 0 : 4; + HALR->structured.autoSCSIData.uBusOnDelay = (bl->chip == CHIP_BUSLOGIC_PCI_958D_1995_12_30) ? 0 : 7; + HALR->structured.autoSCSIData.uBusOffDelay = (bl->chip == CHIP_BUSLOGIC_PCI_958D_1995_12_30) ? 0 : 4; HALR->structured.autoSCSIData.uBIOSConfiguration = (bl->has_bios) ? 0x33 : 0x32; if (!safe) - HALR->structured.autoSCSIData.uBIOSConfiguration |= 0x04; + HALR->structured.autoSCSIData.uBIOSConfiguration |= 0x04; - HALR->structured.autoSCSIData.u16DeviceEnabledMask = 0xffff; - HALR->structured.autoSCSIData.u16WidePermittedMask = 0xffff; - HALR->structured.autoSCSIData.u16FastPermittedMask = 0xffff; + HALR->structured.autoSCSIData.u16DeviceEnabledMask = 0xffff; + HALR->structured.autoSCSIData.u16WidePermittedMask = 0xffff; + HALR->structured.autoSCSIData.u16FastPermittedMask = 0xffff; HALR->structured.autoSCSIData.u16DisconnectPermittedMask = 0xffff; - HALR->structured.autoSCSIData.uPCIInterruptPin = PCI_INTA; + HALR->structured.autoSCSIData.uPCIInterruptPin = PCI_INTA; HALR->structured.autoSCSIData.fVesaBusSpeedGreaterThan33MHz = 1; HALR->structured.autoSCSIData.uAutoSCSIMaximumLUN = 7; HALR->structured.autoSCSIData.fForceBusDeviceScanningOrder = 1; - HALR->structured.autoSCSIData.fInt13Extension = safe ? 0 : 1; - HALR->structured.autoSCSIData.fCDROMBoot = safe ? 0 : 1; - HALR->structured.autoSCSIData.fMultiBoot = safe ? 0 : 1; - HALR->structured.autoSCSIData.fRoundRobinScheme = safe ? 1 : 0; /* 1 = aggressive, 0 = strict */ + HALR->structured.autoSCSIData.fInt13Extension = safe ? 0 : 1; + HALR->structured.autoSCSIData.fCDROMBoot = safe ? 0 : 1; + HALR->structured.autoSCSIData.fMultiBoot = safe ? 0 : 1; + HALR->structured.autoSCSIData.fRoundRobinScheme = safe ? 1 : 0; /* 1 = aggressive, 0 = strict */ - HALR->structured.autoSCSIData.uHostAdapterIoPortAddress = 2; /* 0 = primary (330h), 1 = secondary (334h), 2 = disable, 3 = reserved */ + HALR->structured.autoSCSIData.uHostAdapterIoPortAddress = 2; /* 0 = primary (330h), 1 = secondary (334h), 2 = disable, 3 = reserved */ } - static void BuslogicInitializeAutoSCSIRam(x54x_t *dev) { - buslogic_data_t *bl = (buslogic_data_t *) dev->ven_data; - HALocalRAM *HALR = &bl->LocalRAM; + buslogic_data_t *bl = (buslogic_data_t *) dev->ven_data; + const HALocalRAM *HALR = &bl->LocalRAM; - FILE *f; + FILE *fp; - f = nvr_fopen(BuslogicGetNVRFileName(bl), "rb"); - if (f) - { - if (fread(&(bl->LocalRAM.structured.autoSCSIData), 1, 64, f) != 64) - fatal("BuslogicInitializeAutoSCSIRam(): Error reading data\n"); - fclose(f); - f = NULL; - if (bl->chip == CHIP_BUSLOGIC_PCI_958D_1995_12_30) { - x54x_io_remove(dev, dev->Base, 4); - switch(HALR->structured.autoSCSIData.uHostAdapterIoPortAddress) { - case 0: - dev->Base = 0x330; - break; - case 1: - dev->Base = 0x334; - break; - default: - dev->Base = 0; - break; - } - x54x_io_set(dev, dev->Base, 4); - } - } - else - { - BuslogicAutoSCSIRamSetDefaults(dev, 0); + fp = nvr_fopen(BuslogicGetNVRFileName(bl), "rb"); + if (fp) { + if (fread(&(bl->LocalRAM.structured.autoSCSIData), 1, 64, fp) != 64) + fatal("BuslogicInitializeAutoSCSIRam(): Error reading data\n"); + fclose(fp); + fp = NULL; + if (bl->chip == CHIP_BUSLOGIC_PCI_958D_1995_12_30) { + x54x_io_remove(dev, dev->Base, 4); + switch (HALR->structured.autoSCSIData.uHostAdapterIoPortAddress) { + case 0: + dev->Base = 0x330; + break; + case 1: + dev->Base = 0x334; + break; + default: + dev->Base = 0; + break; + } + x54x_io_set(dev, dev->Base, 4); + } + } else { + BuslogicAutoSCSIRamSetDefaults(dev, 0); } } - static void -buslogic_cmd_phase1(void *p) +buslogic_cmd_phase1(void *priv) { - x54x_t *dev = (x54x_t *)p; + x54x_t *dev = (x54x_t *) priv; if ((dev->CmdParam == 2) && (dev->Command == 0x90)) { - dev->CmdParamLeft = dev->CmdBuf[1]; + dev->CmdParamLeft = dev->CmdBuf[1]; } if ((dev->CmdParam == 10) && ((dev->Command == 0x97) || (dev->Command == 0xA7))) { - dev->CmdParamLeft = dev->CmdBuf[6]; - dev->CmdParamLeft <<= 8; - dev->CmdParamLeft |= dev->CmdBuf[7]; - dev->CmdParamLeft <<= 8; - dev->CmdParamLeft |= dev->CmdBuf[8]; + dev->CmdParamLeft = dev->CmdBuf[6]; + dev->CmdParamLeft <<= 8; + dev->CmdParamLeft |= dev->CmdBuf[7]; + dev->CmdParamLeft <<= 8; + dev->CmdParamLeft |= dev->CmdBuf[8]; } if ((dev->CmdParam == 4) && (dev->Command == 0xA9)) { - dev->CmdParamLeft = dev->CmdBuf[3]; - dev->CmdParamLeft <<= 8; - dev->CmdParamLeft |= dev->CmdBuf[2]; + dev->CmdParamLeft = dev->CmdBuf[3]; + dev->CmdParamLeft <<= 8; + dev->CmdParamLeft |= dev->CmdBuf[2]; } } - static uint8_t -buslogic_get_host_id(void *p) +buslogic_get_host_id(void *priv) { - x54x_t *dev = (x54x_t *)p; - buslogic_data_t *bl = (buslogic_data_t *) dev->ven_data; + x54x_t *dev = (x54x_t *) priv; + const buslogic_data_t *bl = (buslogic_data_t *) dev->ven_data; - HALocalRAM *HALR = &bl->LocalRAM; + const HALocalRAM *HALR = &bl->LocalRAM; - if ((bl->chip == CHIP_BUSLOGIC_ISA_542B_1991_12_14) || - (bl->chip == CHIP_BUSLOGIC_ISA_545S_1992_10_05) || - (bl->chip == CHIP_BUSLOGIC_ISA_542BH_1993_05_23) || - (bl->chip == CHIP_BUSLOGIC_VLB_445S_1993_11_16)) - return dev->HostID; + if ((bl->chip == CHIP_BUSLOGIC_ISA_542B_1991_12_14) || (bl->chip == CHIP_BUSLOGIC_ISA_545S_1992_10_05) || (bl->chip == CHIP_BUSLOGIC_ISA_542BH_1993_05_23) || (bl->chip == CHIP_BUSLOGIC_VLB_445S_1993_11_16)) + return dev->HostID; else - return HALR->structured.autoSCSIData.uSCSIId; + return HALR->structured.autoSCSIData.uSCSIId; } - static uint8_t -buslogic_get_irq(void *p) +buslogic_get_irq(void *priv) { - x54x_t *dev = (x54x_t *)p; - buslogic_data_t *bl = (buslogic_data_t *) dev->ven_data; + x54x_t *dev = (x54x_t *) priv; + const buslogic_data_t *bl = (buslogic_data_t *) dev->ven_data; uint8_t bl_irq[7] = { 0, 9, 10, 11, 12, 14, 15 }; - HALocalRAM *HALR = &bl->LocalRAM; + const HALocalRAM *HALR = &bl->LocalRAM; - if ((bl->chip == CHIP_BUSLOGIC_ISA_542B_1991_12_14) || - (bl->chip == CHIP_BUSLOGIC_ISA_545S_1992_10_05) || - (bl->chip == CHIP_BUSLOGIC_ISA_542BH_1993_05_23) || - (bl->chip == CHIP_BUSLOGIC_VLB_445S_1993_11_16) || - (bl->chip == CHIP_BUSLOGIC_PCI_958D_1995_12_30)) - return dev->Irq; + if ((bl->chip == CHIP_BUSLOGIC_ISA_542B_1991_12_14) || (bl->chip == CHIP_BUSLOGIC_ISA_545S_1992_10_05) || (bl->chip == CHIP_BUSLOGIC_ISA_542BH_1993_05_23) || (bl->chip == CHIP_BUSLOGIC_VLB_445S_1993_11_16) || (bl->chip == CHIP_BUSLOGIC_PCI_958D_1995_12_30)) + return dev->Irq; else - return bl_irq[HALR->structured.autoSCSIData.uIrqChannel]; + return bl_irq[HALR->structured.autoSCSIData.uIrqChannel]; } - static uint8_t -buslogic_get_dma(void *p) +buslogic_get_dma(void *priv) { - x54x_t *dev = (x54x_t *)p; - buslogic_data_t *bl = (buslogic_data_t *) dev->ven_data; + x54x_t *dev = (x54x_t *) priv; + const buslogic_data_t *bl = (buslogic_data_t *) dev->ven_data; uint8_t bl_dma[4] = { 0, 5, 6, 7 }; - HALocalRAM *HALR = &bl->LocalRAM; + const HALocalRAM *HALR = &bl->LocalRAM; if (bl->chip == CHIP_BUSLOGIC_PCI_958D_1995_12_30) - return (dev->Base ? 7 : 0); - else if ((bl->chip == CHIP_BUSLOGIC_ISA_542B_1991_12_14) || - (bl->chip == CHIP_BUSLOGIC_ISA_545S_1992_10_05) || - (bl->chip == CHIP_BUSLOGIC_ISA_542BH_1993_05_23) || - (bl->chip == CHIP_BUSLOGIC_VLB_445S_1993_11_16)) - return dev->DmaChannel; + return (dev->Base ? 7 : 0); + else if ((bl->chip == CHIP_BUSLOGIC_ISA_542B_1991_12_14) || (bl->chip == CHIP_BUSLOGIC_ISA_545S_1992_10_05) || (bl->chip == CHIP_BUSLOGIC_ISA_542BH_1993_05_23) || (bl->chip == CHIP_BUSLOGIC_VLB_445S_1993_11_16)) + return dev->DmaChannel; else - return bl_dma[HALR->structured.autoSCSIData.uDMAChannel]; + return bl_dma[HALR->structured.autoSCSIData.uDMAChannel]; } - static uint8_t -buslogic_param_len(void *p) +buslogic_param_len(void *priv) { - x54x_t *dev = (x54x_t *)p; - buslogic_data_t *bl = (buslogic_data_t *) dev->ven_data; + x54x_t *dev = (x54x_t *) priv; + const buslogic_data_t *bl = (buslogic_data_t *) dev->ven_data; switch (dev->Command) { - case 0x21: - return 5; - case 0x25: - case 0x8B: - case 0x8C: - case 0x8D: - case 0x8F: - case 0x92: - case 0x96: - return 1; - case 0x81: - return sizeof(MailboxInitExtended_t); - case 0x83: - return 12; - case 0x90: - case 0x91: - return 2; - case 0x94: - case 0xFB: - return 3; - case 0x93: /* Valid only for VLB */ - return (bl->chip == CHIP_BUSLOGIC_VLB_445C_1994_12_01 || bl->chip == CHIP_BUSLOGIC_VLB_445S_1993_11_16) ? 1 : 0; - case 0x95: /* Valid only for PCI */ - return (bl->chip == CHIP_BUSLOGIC_PCI_958D_1995_12_30) ? 1 : 0; - case 0x97: /* Valid only for PCI */ - case 0xA7: /* Valid only for PCI */ - return (bl->chip == CHIP_BUSLOGIC_PCI_958D_1995_12_30) ? 10 : 0; - case 0xA8: /* Valid only for PCI */ - case 0xA9: /* Valid only for PCI */ - return (bl->chip == CHIP_BUSLOGIC_PCI_958D_1995_12_30) ? 4 : 0; - default: - return 0; + case 0x21: + return 5; + case 0x25: + case 0x8B: + case 0x8C: + case 0x8D: + case 0x8F: + case 0x92: + case 0x96: + return 1; + case 0x81: + return sizeof(MailboxInitExtended_t); + case 0x83: + return 12; + case 0x90: + case 0x91: + return 2; + case 0x94: + case 0xFB: + return 3; + case 0x93: /* Valid only for VLB */ + return (bl->chip == CHIP_BUSLOGIC_VLB_445C_1994_12_01 || bl->chip == CHIP_BUSLOGIC_VLB_445S_1993_11_16) ? 1 : 0; + case 0x95: /* Valid only for PCI */ + return (bl->chip == CHIP_BUSLOGIC_PCI_958D_1995_12_30) ? 1 : 0; + case 0x97: /* Valid only for PCI */ + case 0xA7: /* Valid only for PCI */ + return (bl->chip == CHIP_BUSLOGIC_PCI_958D_1995_12_30) ? 10 : 0; + case 0xA8: /* Valid only for PCI */ + case 0xA9: /* Valid only for PCI */ + return (bl->chip == CHIP_BUSLOGIC_PCI_958D_1995_12_30) ? 4 : 0; + default: + return 0; } } - static void BuslogicSCSIBIOSDMATransfer(x54x_t *dev, ESCMD *ESCSICmd, uint8_t TargetID, int dir, int transfer_size) { - uint32_t DataPointer = ESCSICmd->DataPointer; - int DataLength = ESCSICmd->DataLength; - uint32_t Address; - uint32_t TransferLength; + uint32_t DataPointer = ESCSICmd->DataPointer; + int DataLength = ESCSICmd->DataLength; + uint32_t Address; + uint32_t TransferLength; scsi_device_t *sd = &scsi_devices[dev->bus][TargetID]; if (ESCSICmd->DataDirection == 0x03) { - /* Non-data command. */ - buslogic_log("BuslogicSCSIBIOSDMATransfer(): Non-data control byte\n"); - return; + /* Non-data command. */ + buslogic_log("BuslogicSCSIBIOSDMATransfer(): Non-data control byte\n"); + return; } buslogic_log("BuslogicSCSIBIOSDMATransfer(): BIOS Data Buffer read: length %d, pointer 0x%04X\n", DataLength, DataPointer); @@ -599,74 +574,73 @@ BuslogicSCSIBIOSDMATransfer(x54x_t *dev, ESCMD *ESCSICmd, uint8_t TargetID, int /* If the control byte is 0x00, it means that the transfer direction is set up by the SCSI command without checking its length, so do this procedure for both read/write commands. */ if ((DataLength > 0) && (sd->buffer_length > 0)) { - Address = DataPointer; - TransferLength = MIN(DataLength, sd->buffer_length); + Address = DataPointer; + TransferLength = MIN(DataLength, sd->buffer_length); - if (dir && ((ESCSICmd->DataDirection == CCB_DATA_XFER_OUT) || (ESCSICmd->DataDirection == 0x00))) { - buslogic_log("BusLogic BIOS DMA: Reading %i bytes from %08X\n", TransferLength, Address); - dma_bm_read(Address, (uint8_t *)sd->sc->temp_buffer, TransferLength, transfer_size); - } else if (!dir && ((ESCSICmd->DataDirection == CCB_DATA_XFER_IN) || (ESCSICmd->DataDirection == 0x00))) { - buslogic_log("BusLogic BIOS DMA: Writing %i bytes at %08X\n", TransferLength, Address); - dma_bm_write(Address, (uint8_t *)sd->sc->temp_buffer, TransferLength, transfer_size); - } + if (dir && ((ESCSICmd->DataDirection == CCB_DATA_XFER_OUT) || (ESCSICmd->DataDirection == 0x00))) { + buslogic_log("BusLogic BIOS DMA: Reading %i bytes from %08X\n", TransferLength, Address); + dma_bm_read(Address, sd->sc->temp_buffer, TransferLength, transfer_size); + } else if (!dir && ((ESCSICmd->DataDirection == CCB_DATA_XFER_IN) || (ESCSICmd->DataDirection == 0x00))) { + buslogic_log("BusLogic BIOS DMA: Writing %i bytes at %08X\n", TransferLength, Address); + dma_bm_write(Address, sd->sc->temp_buffer, TransferLength, transfer_size); + } } } - static void BuslogicSCSIBIOSRequestSetup(x54x_t *dev, uint8_t *CmdBuf, uint8_t *DataInBuf, uint8_t DataReply) -{ - ESCMD *ESCSICmd = (ESCMD *)CmdBuf; - uint32_t i; - uint8_t temp_cdb[12]; - int target_cdb_len = 12; +{ + ESCMD *ESCSICmd = (ESCMD *) CmdBuf; + uint8_t temp_cdb[12]; + int target_cdb_len = 12; #ifdef ENABLE_BUSLOGIC_LOG uint8_t target_id = 0; #endif - int phase; + int phase; scsi_device_t *sd = &scsi_devices[dev->bus][ESCSICmd->TargetId]; DataInBuf[0] = DataInBuf[1] = 0; if ((ESCSICmd->TargetId > 15) || (ESCSICmd->LogicalUnit > 7)) { - DataInBuf[2] = CCB_INVALID_CCB; - DataInBuf[3] = SCSI_STATUS_OK; - return; + DataInBuf[2] = CCB_INVALID_CCB; + DataInBuf[3] = SCSI_STATUS_OK; + return; } - - buslogic_log("Scanning SCSI Target ID %i\n", ESCSICmd->TargetId); + + buslogic_log("Scanning SCSI Target ID %i\n", ESCSICmd->TargetId); sd->status = SCSI_STATUS_OK; if (!scsi_device_present(sd) || (ESCSICmd->LogicalUnit > 0)) { - buslogic_log("SCSI Target ID %i has no device attached\n", ESCSICmd->TargetId); - DataInBuf[2] = CCB_SELECTION_TIMEOUT; - DataInBuf[3] = SCSI_STATUS_OK; - return; + buslogic_log("SCSI Target ID %i has no device attached\n", ESCSICmd->TargetId); + DataInBuf[2] = CCB_SELECTION_TIMEOUT; + DataInBuf[3] = SCSI_STATUS_OK; + return; } else { - buslogic_log("SCSI Target ID %i detected and working\n", ESCSICmd->TargetId); - scsi_device_identify(sd, ESCSICmd->LogicalUnit); + buslogic_log("SCSI Target ID %i detected and working\n", ESCSICmd->TargetId); + scsi_device_identify(sd, ESCSICmd->LogicalUnit); - buslogic_log("Transfer Control %02X\n", ESCSICmd->DataDirection); - buslogic_log("CDB Length %i\n", ESCSICmd->CDBLength); + buslogic_log("Transfer Control %02X\n", ESCSICmd->DataDirection); + buslogic_log("CDB Length %i\n", ESCSICmd->CDBLength); } target_cdb_len = 12; - if (!scsi_device_valid(sd)) fatal("SCSI target on ID %02i has disappeared\n", ESCSICmd->TargetId); + if (!scsi_device_valid(sd)) + fatal("SCSI target on ID %02i has disappeared\n", ESCSICmd->TargetId); buslogic_log("SCSI target command being executed on: SCSI ID %i, SCSI LUN %i, Target %i\n", ESCSICmd->TargetId, ESCSICmd->LogicalUnit, target_id); buslogic_log("SCSI Cdb[0]=0x%02X\n", ESCSICmd->CDB[0]); - for (i = 1; i < ESCSICmd->CDBLength; i++) { - buslogic_log("SCSI Cdb[%i]=%i\n", i, ESCSICmd->CDB[i]); + for (uint8_t i = 1; i < ESCSICmd->CDBLength; i++) { + buslogic_log("SCSI Cdb[%i]=%i\n", i, ESCSICmd->CDB[i]); } memset(temp_cdb, 0, target_cdb_len); if (ESCSICmd->CDBLength <= target_cdb_len) { - memcpy(temp_cdb, ESCSICmd->CDB, ESCSICmd->CDBLength); + memcpy(temp_cdb, ESCSICmd->CDB, ESCSICmd->CDBLength); } else { - memcpy(temp_cdb, ESCSICmd->CDB, target_cdb_len); + memcpy(temp_cdb, ESCSICmd->CDB, target_cdb_len); } sd->buffer_length = ESCSICmd->DataLength; @@ -675,459 +649,451 @@ BuslogicSCSIBIOSRequestSetup(x54x_t *dev, uint8_t *CmdBuf, uint8_t *DataInBuf, u phase = sd->phase; if (phase != SCSI_PHASE_STATUS) { - BuslogicSCSIBIOSDMATransfer(dev, ESCSICmd, ESCSICmd->TargetId, (phase == SCSI_PHASE_DATA_OUT), dev->transfer_size); - scsi_device_command_phase1(sd); + BuslogicSCSIBIOSDMATransfer(dev, ESCSICmd, ESCSICmd->TargetId, (phase == SCSI_PHASE_DATA_OUT), dev->transfer_size); + scsi_device_command_phase1(sd); } buslogic_log("BIOS Request complete\n"); scsi_device_identify(sd, SCSI_LUN_USE_CDB); if (sd->status == SCSI_STATUS_OK) { - DataInBuf[2] = CCB_COMPLETE; - DataInBuf[3] = SCSI_STATUS_OK; + DataInBuf[2] = CCB_COMPLETE; + DataInBuf[3] = SCSI_STATUS_OK; } else if (scsi_devices[dev->bus][ESCSICmd->TargetId].status == SCSI_STATUS_CHECK_CONDITION) { - DataInBuf[2] = CCB_COMPLETE; - DataInBuf[3] = SCSI_STATUS_CHECK_CONDITION; + DataInBuf[2] = CCB_COMPLETE; + DataInBuf[3] = SCSI_STATUS_CHECK_CONDITION; } dev->DataReplyLeft = DataReply; } - static uint8_t -buslogic_cmds(void *p) +buslogic_cmds(void *priv) { - x54x_t *dev = (x54x_t *)p; - buslogic_data_t *bl = (buslogic_data_t *) dev->ven_data; + x54x_t *dev = (x54x_t *) priv; + buslogic_data_t *bl = (buslogic_data_t *) dev->ven_data; - HALocalRAM *HALR = &bl->LocalRAM; + const HALocalRAM *HALR = &bl->LocalRAM; - FILE *f; - uint16_t TargetsPresentMask = 0; - uint32_t Offset; - int i = 0; - MailboxInitExtended_t *MailboxInitE; + FILE *fp; + uint16_t TargetsPresentMask = 0; + uint32_t Offset; + int i = 0; + const MailboxInitExtended_t *MailboxInitE; ReplyInquireExtendedSetupInformation *ReplyIESI; - BuslogicPCIInformation_t *ReplyPI; - int cCharsToTransfer; + BuslogicPCIInformation_t *ReplyPI; + int cCharsToTransfer; - buslogic_log("Buslogic cmds = 0x%02x\n", dev->Command); + buslogic_log("Buslogic cmds = 0x%02x\n", dev->Command); switch (dev->Command) { - case 0x20: - dev->DataReplyLeft = 0; - x54x_reset_ctrl(dev, 1); - break; - case 0x21: - if (dev->CmdParam == 1) - dev->CmdParamLeft = dev->CmdBuf[0]; - dev->DataReplyLeft = 0; - break; - case 0x23: - memset(dev->DataBuf, 0, 8); - for (i = 8; i < 15; i++) { - dev->DataBuf[i - 8] = 0; - if (scsi_device_present(&scsi_devices[dev->bus][i]) && (i != buslogic_get_host_id(dev))) - dev->DataBuf[i - 8] |= 1; - } - dev->DataReplyLeft = 8; - break; - case 0x24: - for (i = 0; i < 15; i++) { - if (scsi_device_present(&scsi_devices[dev->bus][i]) && (i != buslogic_get_host_id(dev))) - TargetsPresentMask |= (1 << i); - } - dev->DataBuf[0] = TargetsPresentMask & 0xFF; - dev->DataBuf[1] = TargetsPresentMask >> 8; - dev->DataReplyLeft = 2; - break; - case 0x25: - if (dev->CmdBuf[0] == 0) - dev->IrqEnabled = 0; - else - dev->IrqEnabled = 1; - return 1; - case 0x81: - dev->flags &= ~X54X_MBX_24BIT; + case 0x20: + dev->DataReplyLeft = 0; + x54x_reset_ctrl(dev, 1); + break; + case 0x21: + if (dev->CmdParam == 1) + dev->CmdParamLeft = dev->CmdBuf[0]; + dev->DataReplyLeft = 0; + break; + case 0x23: + memset(dev->DataBuf, 0, 8); + for (i = 8; i < 15; i++) { + dev->DataBuf[i - 8] = 0; + if (scsi_device_present(&scsi_devices[dev->bus][i]) && (i != buslogic_get_host_id(dev))) + dev->DataBuf[i - 8] |= 1; + } + dev->DataReplyLeft = 8; + break; + case 0x24: + for (i = 0; i < 15; i++) { + if (scsi_device_present(&scsi_devices[dev->bus][i]) && (i != buslogic_get_host_id(dev))) + TargetsPresentMask |= (1 << i); + } + dev->DataBuf[0] = TargetsPresentMask & 0xFF; + dev->DataBuf[1] = TargetsPresentMask >> 8; + dev->DataReplyLeft = 2; + break; + case 0x25: + if (dev->CmdBuf[0] == 0) + dev->IrqEnabled = 0; + else + dev->IrqEnabled = 1; + return 1; + case 0x81: + dev->flags &= ~X54X_MBX_24BIT; - MailboxInitE = (MailboxInitExtended_t *)dev->CmdBuf; + MailboxInitE = (MailboxInitExtended_t *) dev->CmdBuf; - dev->MailboxInit = 1; - dev->MailboxCount = MailboxInitE->Count; - dev->MailboxOutAddr = MailboxInitE->Address; - dev->MailboxInAddr = MailboxInitE->Address + (dev->MailboxCount * sizeof(Mailbox32_t)); + dev->MailboxInit = 1; + dev->MailboxCount = MailboxInitE->Count; + dev->MailboxOutAddr = MailboxInitE->Address; + dev->MailboxInAddr = MailboxInitE->Address + (dev->MailboxCount * sizeof(Mailbox32_t)); - buslogic_log("Buslogic Extended Initialize Mailbox Command\n"); - buslogic_log("Mailbox Out Address=0x%08X\n", dev->MailboxOutAddr); - buslogic_log("Mailbox In Address=0x%08X\n", dev->MailboxInAddr); - buslogic_log("Initialized Extended Mailbox, %d entries at 0x%08X\n", MailboxInitE->Count, MailboxInitE->Address); + buslogic_log("Buslogic Extended Initialize Mailbox Command\n"); + buslogic_log("Mailbox Out Address=0x%08X\n", dev->MailboxOutAddr); + buslogic_log("Mailbox In Address=0x%08X\n", dev->MailboxInAddr); + buslogic_log("Initialized Extended Mailbox, %d entries at 0x%08X\n", MailboxInitE->Count, MailboxInitE->Address); - dev->Status &= ~STAT_INIT; - dev->DataReplyLeft = 0; - break; - case 0x83: - if (dev->CmdParam == 12) { - dev->CmdParamLeft = dev->CmdBuf[11]; - buslogic_log("Execute SCSI BIOS Command: %u more bytes follow\n", dev->CmdParamLeft); - } else { - buslogic_log("Execute SCSI BIOS Command: received %u bytes\n", dev->CmdBuf[0]); - BuslogicSCSIBIOSRequestSetup(dev, dev->CmdBuf, dev->DataBuf, 4); - } - break; - case 0x84: - dev->DataBuf[0] = dev->fw_rev[4]; - dev->DataReplyLeft = 1; - break; - case 0x85: - if (strlen(dev->fw_rev) == 6) - dev->DataBuf[0] = dev->fw_rev[5]; - else - dev->DataBuf[0] = ' '; - dev->DataReplyLeft = 1; - break; - case 0x86: - if (bl->chip == CHIP_BUSLOGIC_PCI_958D_1995_12_30) { - ReplyPI = (BuslogicPCIInformation_t *) dev->DataBuf; - memset(ReplyPI, 0, sizeof(BuslogicPCIInformation_t)); - ReplyPI->InformationIsValid = 0; - switch(dev->Base) { - case 0x330: - ReplyPI->IsaIOPort = 0; - break; - case 0x334: - ReplyPI->IsaIOPort = 1; - break; - case 0x230: - ReplyPI->IsaIOPort = 2; - break; - case 0x234: - ReplyPI->IsaIOPort = 3; - break; - case 0x130: - ReplyPI->IsaIOPort = 4; - break; - case 0x134: - ReplyPI->IsaIOPort = 5; - break; - default: - ReplyPI->IsaIOPort = 6; - break; - } - ReplyPI->IRQ = dev->Irq; - dev->DataReplyLeft = sizeof(BuslogicPCIInformation_t); - } else { - dev->DataReplyLeft = 0; - dev->Status |= STAT_INVCMD; - } - break; - case 0x8B: - /* The reply length is set by the guest and is found in the first byte of the command buffer. */ - dev->DataReplyLeft = dev->CmdBuf[0]; - memset(dev->DataBuf, 0, dev->DataReplyLeft); - if (bl->chip == CHIP_BUSLOGIC_ISA_542BH_1993_05_23) - i = 5; - else - i = 4; - cCharsToTransfer = MIN(dev->DataReplyLeft, i); + dev->Status &= ~STAT_INIT; + dev->DataReplyLeft = 0; + break; + case 0x83: + if (dev->CmdParam == 12) { + dev->CmdParamLeft = dev->CmdBuf[11]; + buslogic_log("Execute SCSI BIOS Command: %u more bytes follow\n", dev->CmdParamLeft); + } else { + buslogic_log("Execute SCSI BIOS Command: received %u bytes\n", dev->CmdBuf[0]); + BuslogicSCSIBIOSRequestSetup(dev, dev->CmdBuf, dev->DataBuf, 4); + } + break; + case 0x84: + dev->DataBuf[0] = dev->fw_rev[4]; + dev->DataReplyLeft = 1; + break; + case 0x85: + if (strlen(dev->fw_rev) == 6) + dev->DataBuf[0] = dev->fw_rev[5]; + else + dev->DataBuf[0] = ' '; + dev->DataReplyLeft = 1; + break; + case 0x86: + if (bl->chip == CHIP_BUSLOGIC_PCI_958D_1995_12_30) { + ReplyPI = (BuslogicPCIInformation_t *) dev->DataBuf; + memset(ReplyPI, 0, sizeof(BuslogicPCIInformation_t)); + ReplyPI->InformationIsValid = 0; + switch (dev->Base) { + case 0x330: + ReplyPI->IsaIOPort = 0; + break; + case 0x334: + ReplyPI->IsaIOPort = 1; + break; + case 0x230: + ReplyPI->IsaIOPort = 2; + break; + case 0x234: + ReplyPI->IsaIOPort = 3; + break; + case 0x130: + ReplyPI->IsaIOPort = 4; + break; + case 0x134: + ReplyPI->IsaIOPort = 5; + break; + default: + ReplyPI->IsaIOPort = 6; + break; + } + ReplyPI->IRQ = dev->Irq; + dev->DataReplyLeft = sizeof(BuslogicPCIInformation_t); + } else { + dev->DataReplyLeft = 0; + dev->Status |= STAT_INVCMD; + } + break; + case 0x8B: + /* The reply length is set by the guest and is found in the first byte of the command buffer. */ + dev->DataReplyLeft = dev->CmdBuf[0]; + memset(dev->DataBuf, 0, dev->DataReplyLeft); + if (bl->chip == CHIP_BUSLOGIC_ISA_542BH_1993_05_23) + i = 5; + else + i = 4; + cCharsToTransfer = MIN(dev->DataReplyLeft, i); - memcpy(dev->DataBuf, &(bl->LocalRAM.structured.autoSCSIData.aHostAdaptertype[1]), cCharsToTransfer); - break; - case 0x8C: - dev->DataReplyLeft = dev->CmdBuf[0]; - memset(dev->DataBuf, 0, dev->DataReplyLeft); - break; - case 0x8D: - dev->DataReplyLeft = dev->CmdBuf[0]; - ReplyIESI = (ReplyInquireExtendedSetupInformation *)dev->DataBuf; - memset(ReplyIESI, 0, sizeof(ReplyInquireExtendedSetupInformation)); + memcpy(dev->DataBuf, &(bl->LocalRAM.structured.autoSCSIData.aHostAdaptertype[1]), cCharsToTransfer); + break; + case 0x8C: + dev->DataReplyLeft = dev->CmdBuf[0]; + memset(dev->DataBuf, 0, dev->DataReplyLeft); + break; + case 0x8D: + dev->DataReplyLeft = dev->CmdBuf[0]; + ReplyIESI = (ReplyInquireExtendedSetupInformation *) dev->DataBuf; + memset(ReplyIESI, 0, sizeof(ReplyInquireExtendedSetupInformation)); - switch (bl->chip) { - case CHIP_BUSLOGIC_ISA_542B_1991_12_14: - case CHIP_BUSLOGIC_ISA_545S_1992_10_05: - case CHIP_BUSLOGIC_ISA_542BH_1993_05_23: - case CHIP_BUSLOGIC_ISA_545C_1994_12_01: - case CHIP_BUSLOGIC_VLB_445S_1993_11_16: - case CHIP_BUSLOGIC_VLB_445C_1994_12_01: - ReplyIESI->uBusType = 'A'; /* ISA style */ - break; - case CHIP_BUSLOGIC_MCA_640A_1993_05_23: - ReplyIESI->uBusType = 'M'; /* MCA style */ - break; - case CHIP_BUSLOGIC_PCI_958D_1995_12_30: - ReplyIESI->uBusType = 'E'; /* PCI style */ - break; - } - ReplyIESI->uBiosAddress = 0xd8; - ReplyIESI->u16ScatterGatherLimit = 8192; - ReplyIESI->cMailbox = dev->MailboxCount; - ReplyIESI->uMailboxAddressBase = dev->MailboxOutAddr; - ReplyIESI->fHostWideSCSI = (bl->chip == CHIP_BUSLOGIC_PCI_958D_1995_12_30) ? 1 : 0; - if ((bl->chip != CHIP_BUSLOGIC_ISA_542B_1991_12_14) && (bl->chip != CHIP_BUSLOGIC_ISA_545S_1992_10_05) && - (bl->chip != CHIP_BUSLOGIC_ISA_542BH_1993_05_23) && (bl->chip != CHIP_BUSLOGIC_MCA_640A_1993_05_23) && - (bl->chip != CHIP_BUSLOGIC_VLB_445S_1993_11_16)) - ReplyIESI->fLevelSensitiveInterrupt = bl->LocalRAM.structured.autoSCSIData.fLevelSensitiveInterrupt; - if (bl->chip == CHIP_BUSLOGIC_PCI_958D_1995_12_30) - ReplyIESI->fHostUltraSCSI = 1; - memcpy(ReplyIESI->aFirmwareRevision, &(dev->fw_rev[strlen(dev->fw_rev) - 3]), sizeof(ReplyIESI->aFirmwareRevision)); - buslogic_log("Return Extended Setup Information: %d\n", dev->CmdBuf[0]); - break; - case 0x8F: - bl->fAggressiveRoundRobinMode = dev->CmdBuf[0] & 1; - buslogic_log("Aggressive Round Robin Mode = %d\n", bl->fAggressiveRoundRobinMode); - dev->DataReplyLeft = 0; - break; - case 0x90: - buslogic_log("Store Local RAM\n"); - Offset = dev->CmdBuf[0]; - dev->DataReplyLeft = 0; - memcpy(&(bl->LocalRAM.u8View[Offset]), &(dev->CmdBuf[2]), dev->CmdBuf[1]); - - dev->DataReply = 0; - break; - case 0x91: - buslogic_log("Fetch Local RAM\n"); - Offset = dev->CmdBuf[0]; - dev->DataReplyLeft = dev->CmdBuf[1]; - memcpy(dev->DataBuf, &(bl->LocalRAM.u8View[Offset]), dev->CmdBuf[1]); + switch (bl->chip) { + case CHIP_BUSLOGIC_ISA_542B_1991_12_14: + case CHIP_BUSLOGIC_ISA_545S_1992_10_05: + case CHIP_BUSLOGIC_ISA_542BH_1993_05_23: + case CHIP_BUSLOGIC_ISA_545C_1994_12_01: + case CHIP_BUSLOGIC_VLB_445S_1993_11_16: + case CHIP_BUSLOGIC_VLB_445C_1994_12_01: + ReplyIESI->uBusType = 'A'; /* ISA style */ + break; + case CHIP_BUSLOGIC_MCA_640A_1993_05_23: + ReplyIESI->uBusType = 'M'; /* MCA style */ + break; + case CHIP_BUSLOGIC_PCI_958D_1995_12_30: + ReplyIESI->uBusType = 'E'; /* PCI style */ + break; - dev->DataReply = 0; - break; - case 0x93: - if ((bl->chip != CHIP_BUSLOGIC_VLB_445C_1994_12_01) && (bl->chip != CHIP_BUSLOGIC_VLB_445S_1993_11_16)) { - dev->DataReplyLeft = 0; - dev->Status |= STAT_INVCMD; - break; - } - case 0x92: - if ((bl->chip == CHIP_BUSLOGIC_ISA_542B_1991_12_14) || - (bl->chip == CHIP_BUSLOGIC_ISA_545S_1992_10_05) || - (bl->chip == CHIP_BUSLOGIC_ISA_542BH_1993_05_23) || - (bl->chip == CHIP_BUSLOGIC_MCA_640A_1993_05_23)) { - dev->DataReplyLeft = 0; - dev->Status |= STAT_INVCMD; - break; - } + default: + break; + } + ReplyIESI->uBiosAddress = 0xd8; + ReplyIESI->u16ScatterGatherLimit = 8192; + ReplyIESI->cMailbox = dev->MailboxCount; + ReplyIESI->uMailboxAddressBase = dev->MailboxOutAddr; + ReplyIESI->fHostWideSCSI = (bl->chip == CHIP_BUSLOGIC_PCI_958D_1995_12_30) ? 1 : 0; + if ((bl->chip != CHIP_BUSLOGIC_ISA_542B_1991_12_14) && (bl->chip != CHIP_BUSLOGIC_ISA_545S_1992_10_05) && (bl->chip != CHIP_BUSLOGIC_ISA_542BH_1993_05_23) && (bl->chip != CHIP_BUSLOGIC_MCA_640A_1993_05_23) && (bl->chip != CHIP_BUSLOGIC_VLB_445S_1993_11_16)) + ReplyIESI->fLevelSensitiveInterrupt = bl->LocalRAM.structured.autoSCSIData.fLevelSensitiveInterrupt; + if (bl->chip == CHIP_BUSLOGIC_PCI_958D_1995_12_30) + ReplyIESI->fHostUltraSCSI = 1; + memcpy(ReplyIESI->aFirmwareRevision, &(dev->fw_rev[strlen(dev->fw_rev) - 3]), sizeof(ReplyIESI->aFirmwareRevision)); + buslogic_log("Return Extended Setup Information: %d\n", dev->CmdBuf[0]); + break; + case 0x8F: + bl->fAggressiveRoundRobinMode = dev->CmdBuf[0] & 1; + buslogic_log("Aggressive Round Robin Mode = %d\n", bl->fAggressiveRoundRobinMode); + dev->DataReplyLeft = 0; + break; + case 0x90: + buslogic_log("Store Local RAM\n"); + Offset = dev->CmdBuf[0]; + dev->DataReplyLeft = 0; + memcpy(&(bl->LocalRAM.u8View[Offset]), &(dev->CmdBuf[2]), dev->CmdBuf[1]); - dev->DataReplyLeft = 0; + dev->DataReply = 0; + break; + case 0x91: + buslogic_log("Fetch Local RAM\n"); + Offset = dev->CmdBuf[0]; + dev->DataReplyLeft = dev->CmdBuf[1]; + memcpy(dev->DataBuf, &(bl->LocalRAM.u8View[Offset]), dev->CmdBuf[1]); - switch (dev->CmdBuf[0]) { - case 0: - case 2: - BuslogicAutoSCSIRamSetDefaults(dev, 0); - break; - case 3: - BuslogicAutoSCSIRamSetDefaults(dev, 3); - break; - case 1: - f = nvr_fopen(BuslogicGetNVRFileName(bl), "wb"); - if (f) { - fwrite(&(bl->LocalRAM.structured.autoSCSIData), 1, 64, f); - fclose(f); - f = NULL; - } - break; - default: - dev->Status |= STAT_INVCMD; - break; - } + dev->DataReply = 0; + break; + case 0x93: + if ((bl->chip != CHIP_BUSLOGIC_VLB_445C_1994_12_01) && (bl->chip != CHIP_BUSLOGIC_VLB_445S_1993_11_16)) { + dev->DataReplyLeft = 0; + dev->Status |= STAT_INVCMD; + break; + } + fallthrough; + case 0x92: + if ((bl->chip == CHIP_BUSLOGIC_ISA_542B_1991_12_14) || (bl->chip == CHIP_BUSLOGIC_ISA_545S_1992_10_05) || (bl->chip == CHIP_BUSLOGIC_ISA_542BH_1993_05_23) || (bl->chip == CHIP_BUSLOGIC_MCA_640A_1993_05_23)) { + dev->DataReplyLeft = 0; + dev->Status |= STAT_INVCMD; + break; + } - if ((bl->chip == CHIP_BUSLOGIC_PCI_958D_1995_12_30) && !(dev->Status & STAT_INVCMD)) { - x54x_io_remove(dev, dev->Base, 4); - switch(HALR->structured.autoSCSIData.uHostAdapterIoPortAddress) { - case 0: - dev->Base = 0x330; - break; - case 1: - dev->Base = 0x334; - break; - default: - dev->Base = 0; - break; - } - x54x_io_set(dev, dev->Base, 4); - } - break; - case 0x94: - if ((bl->chip == CHIP_BUSLOGIC_ISA_542B_1991_12_14) || (bl->chip == CHIP_BUSLOGIC_ISA_545S_1992_10_05) || (bl->chip == CHIP_BUSLOGIC_MCA_640A_1993_05_23) || - (bl->chip == CHIP_BUSLOGIC_ISA_542BH_1993_05_23)) { - dev->DataReplyLeft = 0; - dev->Status |= STAT_INVCMD; - break; - } + dev->DataReplyLeft = 0; - if (dev->CmdBuf[0]) { - buslogic_log("Invalid AutoSCSI command mode %x\n", dev->CmdBuf[0]); - dev->DataReplyLeft = 0; - dev->Status |= STAT_INVCMD; - } else { - dev->DataReplyLeft = dev->CmdBuf[2]; - dev->DataReplyLeft <<= 8; - dev->DataReplyLeft |= dev->CmdBuf[1]; - memcpy(dev->DataBuf, bl->AutoSCSIROM, dev->DataReplyLeft); - buslogic_log("Returning AutoSCSI ROM (%04X %04X %04X %04X)\n", dev->DataBuf[0], dev->DataBuf[1], dev->DataBuf[2], dev->DataBuf[3]); - } - break; - case 0x95: - if (bl->chip == CHIP_BUSLOGIC_PCI_958D_1995_12_30) { - if (dev->Base != 0) - x54x_io_remove(dev, dev->Base, 4); - if (dev->CmdBuf[0] < 6) { - dev->Base = ((3 - (dev->CmdBuf[0] >> 1)) << 8) | ((dev->CmdBuf[0] & 1) ? 0x34 : 0x30); - x54x_io_set(dev, dev->Base, 4); - } else - dev->Base = 0; - dev->DataReplyLeft = 0; - return 1; - } else { - dev->DataReplyLeft = 0; - dev->Status |= STAT_INVCMD; - } - break; - case 0x96: - if (dev->CmdBuf[0] == 0) - bl->ExtendedLUNCCBFormat = 0; - else if (dev->CmdBuf[0] == 1) - bl->ExtendedLUNCCBFormat = 1; - - dev->DataReplyLeft = 0; - break; - case 0x97: - case 0xA7: - /* TODO: Actually correctly implement this whole SCSI BIOS Flash stuff. */ - dev->DataReplyLeft = 0; - break; - case 0xA8: - if (bl->chip != CHIP_BUSLOGIC_PCI_958D_1995_12_30) { - dev->DataReplyLeft = 0; - dev->Status |= STAT_INVCMD; - break; - } + switch (dev->CmdBuf[0]) { + case 0: + case 2: + BuslogicAutoSCSIRamSetDefaults(dev, 0); + break; + case 3: + BuslogicAutoSCSIRamSetDefaults(dev, 3); + break; + case 1: + fp = nvr_fopen(BuslogicGetNVRFileName(bl), "wb"); + if (fp) { + fwrite(&(bl->LocalRAM.structured.autoSCSIData), 1, 64, fp); + fclose(fp); + fp = NULL; + } + break; + default: + dev->Status |= STAT_INVCMD; + break; + } - Offset = dev->CmdBuf[1]; - Offset <<= 8; - Offset |= dev->CmdBuf[0]; + if ((bl->chip == CHIP_BUSLOGIC_PCI_958D_1995_12_30) && !(dev->Status & STAT_INVCMD)) { + x54x_io_remove(dev, dev->Base, 4); + switch (HALR->structured.autoSCSIData.uHostAdapterIoPortAddress) { + case 0: + dev->Base = 0x330; + break; + case 1: + dev->Base = 0x334; + break; + default: + dev->Base = 0; + break; + } + x54x_io_set(dev, dev->Base, 4); + } + break; + case 0x94: + if ((bl->chip == CHIP_BUSLOGIC_ISA_542B_1991_12_14) || (bl->chip == CHIP_BUSLOGIC_ISA_545S_1992_10_05) || (bl->chip == CHIP_BUSLOGIC_MCA_640A_1993_05_23) || (bl->chip == CHIP_BUSLOGIC_ISA_542BH_1993_05_23)) { + dev->DataReplyLeft = 0; + dev->Status |= STAT_INVCMD; + break; + } - dev->DataReplyLeft = dev->CmdBuf[3]; - dev->DataReplyLeft <<= 8; - dev->DataReplyLeft |= dev->CmdBuf[2]; + if (dev->CmdBuf[0]) { + buslogic_log("Invalid AutoSCSI command mode %x\n", dev->CmdBuf[0]); + dev->DataReplyLeft = 0; + dev->Status |= STAT_INVCMD; + } else { + dev->DataReplyLeft = dev->CmdBuf[2]; + dev->DataReplyLeft <<= 8; + dev->DataReplyLeft |= dev->CmdBuf[1]; + memcpy(dev->DataBuf, bl->AutoSCSIROM, dev->DataReplyLeft); + buslogic_log("Returning AutoSCSI ROM (%04X %04X %04X %04X)\n", dev->DataBuf[0], dev->DataBuf[1], dev->DataBuf[2], dev->DataBuf[3]); + } + break; + case 0x95: + if (bl->chip == CHIP_BUSLOGIC_PCI_958D_1995_12_30) { + if (dev->Base != 0) + x54x_io_remove(dev, dev->Base, 4); + if (dev->CmdBuf[0] < 6) { + dev->Base = ((3 - (dev->CmdBuf[0] >> 1)) << 8) | ((dev->CmdBuf[0] & 1) ? 0x34 : 0x30); + x54x_io_set(dev, dev->Base, 4); + } else + dev->Base = 0; + dev->DataReplyLeft = 0; + return 1; + } else { + dev->DataReplyLeft = 0; + dev->Status |= STAT_INVCMD; + } + break; + case 0x96: + if (dev->CmdBuf[0] == 0) + bl->ExtendedLUNCCBFormat = 0; + else if (dev->CmdBuf[0] == 1) + bl->ExtendedLUNCCBFormat = 1; - memcpy(dev->DataBuf, &(bl->SCAMData[Offset]), dev->DataReplyLeft); + dev->DataReplyLeft = 0; + break; + case 0x97: + case 0xA7: + /* TODO: Actually correctly implement this whole SCSI BIOS Flash stuff. */ + dev->DataReplyLeft = 0; + break; + case 0xA8: + if (bl->chip != CHIP_BUSLOGIC_PCI_958D_1995_12_30) { + dev->DataReplyLeft = 0; + dev->Status |= STAT_INVCMD; + break; + } - dev->DataReply = 0; - break; - case 0xA9: - if (bl->chip != CHIP_BUSLOGIC_PCI_958D_1995_12_30) { - dev->DataReplyLeft = 0; - dev->Status |= STAT_INVCMD; - break; - } + Offset = dev->CmdBuf[1]; + Offset <<= 8; + Offset |= dev->CmdBuf[0]; - Offset = dev->CmdBuf[1]; - Offset <<= 8; - Offset |= dev->CmdBuf[0]; + dev->DataReplyLeft = dev->CmdBuf[3]; + dev->DataReplyLeft <<= 8; + dev->DataReplyLeft |= dev->CmdBuf[2]; - dev->DataReplyLeft = dev->CmdBuf[3]; - dev->DataReplyLeft <<= 8; - dev->DataReplyLeft |= dev->CmdBuf[2]; + memcpy(dev->DataBuf, &(bl->SCAMData[Offset]), dev->DataReplyLeft); - memcpy(&(bl->SCAMData[Offset]), &(dev->CmdBuf[4]), dev->DataReplyLeft); - dev->DataReplyLeft = 0; + dev->DataReply = 0; + break; + case 0xA9: + if (bl->chip != CHIP_BUSLOGIC_PCI_958D_1995_12_30) { + dev->DataReplyLeft = 0; + dev->Status |= STAT_INVCMD; + break; + } - dev->DataReply = 0; - break; - case 0xFB: - dev->DataReplyLeft = dev->CmdBuf[2]; - break; - default: - dev->DataReplyLeft = 0; - dev->Status |= STAT_INVCMD; - break; + Offset = dev->CmdBuf[1]; + Offset <<= 8; + Offset |= dev->CmdBuf[0]; + + dev->DataReplyLeft = dev->CmdBuf[3]; + dev->DataReplyLeft <<= 8; + dev->DataReplyLeft |= dev->CmdBuf[2]; + + memcpy(&(bl->SCAMData[Offset]), &(dev->CmdBuf[4]), dev->DataReplyLeft); + dev->DataReplyLeft = 0; + + dev->DataReply = 0; + break; + case 0xFB: + dev->DataReplyLeft = dev->CmdBuf[2]; + break; + default: + dev->DataReplyLeft = 0; + dev->Status |= STAT_INVCMD; + break; } return 0; } - static void -buslogic_setup_data(void *p) +buslogic_setup_data(void *priv) { - x54x_t *dev = (x54x_t *)p; + x54x_t *dev = (x54x_t *) priv; ReplyInquireSetupInformation *ReplyISI; - buslogic_setup_t *bl_setup; - buslogic_data_t *bl = (buslogic_data_t *) dev->ven_data; - HALocalRAM *HALR = &bl->LocalRAM; + buslogic_setup_t *bl_setup; + const buslogic_data_t *bl = (buslogic_data_t *) dev->ven_data; + const HALocalRAM *HALR = &bl->LocalRAM; - ReplyISI = (ReplyInquireSetupInformation *)dev->DataBuf; - bl_setup = (buslogic_setup_t *)ReplyISI->VendorSpecificData; + ReplyISI = (ReplyInquireSetupInformation *) dev->DataBuf; + bl_setup = (buslogic_setup_t *) ReplyISI->VendorSpecificData; ReplyISI->fSynchronousInitiationEnabled = HALR->structured.autoSCSIData.u16SynchronousPermittedMask ? 1 : 0; - ReplyISI->fParityCheckingEnabled = (HALR->structured.autoSCSIData.uSCSIConfiguration & 2) ? 1 : 0; + ReplyISI->fParityCheckingEnabled = (HALR->structured.autoSCSIData.uSCSIConfiguration & 2) ? 1 : 0; bl_setup->uSignature = 'B'; /* The 'D' signature prevents Buslogic's OS/2 drivers from getting too * friendly with Adaptec hardware and upsetting the HBA state. - */ - bl_setup->uCharacterD = 'D'; /* BusLogic model. */ - switch(bl->chip) - { - case CHIP_BUSLOGIC_ISA_542B_1991_12_14: - case CHIP_BUSLOGIC_ISA_545S_1992_10_05: - case CHIP_BUSLOGIC_ISA_542BH_1993_05_23: - case CHIP_BUSLOGIC_ISA_545C_1994_12_01: - bl_setup->uHostBusType = 'A'; - break; - case CHIP_BUSLOGIC_MCA_640A_1993_05_23: - bl_setup->uHostBusType = 'B'; - break; - case CHIP_BUSLOGIC_VLB_445S_1993_11_16: - case CHIP_BUSLOGIC_VLB_445C_1994_12_01: - bl_setup->uHostBusType = 'E'; - break; - case CHIP_BUSLOGIC_PCI_958D_1995_12_30: - bl_setup->uHostBusType = 'F'; - break; + */ + bl_setup->uCharacterD = 'D'; /* BusLogic model. */ + switch (bl->chip) { + case CHIP_BUSLOGIC_ISA_542B_1991_12_14: + case CHIP_BUSLOGIC_ISA_545S_1992_10_05: + case CHIP_BUSLOGIC_ISA_542BH_1993_05_23: + case CHIP_BUSLOGIC_ISA_545C_1994_12_01: + bl_setup->uHostBusType = 'A'; + break; + case CHIP_BUSLOGIC_MCA_640A_1993_05_23: + bl_setup->uHostBusType = 'B'; + break; + case CHIP_BUSLOGIC_VLB_445S_1993_11_16: + case CHIP_BUSLOGIC_VLB_445C_1994_12_01: + bl_setup->uHostBusType = 'E'; + break; + case CHIP_BUSLOGIC_PCI_958D_1995_12_30: + bl_setup->uHostBusType = 'F'; + break; + + default: + break; } } - static uint8_t -buslogic_is_aggressive_mode(void *p) +buslogic_is_aggressive_mode(void *priv) { - x54x_t *dev = (x54x_t *)p; - buslogic_data_t *bl = (buslogic_data_t *) dev->ven_data; + x54x_t *dev = (x54x_t *) priv; + const buslogic_data_t *bl = (buslogic_data_t *) dev->ven_data; - buslogic_log("Buslogic: Aggressive mode = %d\n", bl->fAggressiveRoundRobinMode); + buslogic_log("Buslogic: Aggressive mode = %d\n", bl->fAggressiveRoundRobinMode); return bl->fAggressiveRoundRobinMode; } - static uint8_t -buslogic_interrupt_type(void *p) +buslogic_interrupt_type(void *priv) { - x54x_t *dev = (x54x_t *)p; - buslogic_data_t *bl = (buslogic_data_t *) dev->ven_data; + x54x_t *dev = (x54x_t *) priv; + const buslogic_data_t *bl = (buslogic_data_t *) dev->ven_data; - if ((bl->chip == CHIP_BUSLOGIC_ISA_542B_1991_12_14) || (bl->chip == CHIP_BUSLOGIC_ISA_545S_1992_10_05) || (bl->chip == CHIP_BUSLOGIC_ISA_542BH_1993_05_23) || - (bl->chip == CHIP_BUSLOGIC_VLB_445S_1993_11_16) || (bl->chip == CHIP_BUSLOGIC_MCA_640A_1993_05_23)) - return 0; + if ((bl->chip == CHIP_BUSLOGIC_ISA_542B_1991_12_14) || (bl->chip == CHIP_BUSLOGIC_ISA_545S_1992_10_05) || (bl->chip == CHIP_BUSLOGIC_ISA_542BH_1993_05_23) || (bl->chip == CHIP_BUSLOGIC_VLB_445S_1993_11_16) || (bl->chip == CHIP_BUSLOGIC_MCA_640A_1993_05_23)) + return 0; else - return !!bl->LocalRAM.structured.autoSCSIData.fLevelSensitiveInterrupt; + return !!bl->LocalRAM.structured.autoSCSIData.fLevelSensitiveInterrupt; } - static void -buslogic_reset(void *p) +buslogic_reset(void *priv) { - x54x_t *dev = (x54x_t *)p; - buslogic_data_t *bl = (buslogic_data_t *) dev->ven_data; + x54x_t *dev = (x54x_t *) priv; + buslogic_data_t *bl = (buslogic_data_t *) dev->ven_data; bl->ExtendedLUNCCBFormat = 0; } - -uint8_t buslogic_pci_regs[256]; -bar_t buslogic_pci_bar[3]; - +uint8_t buslogic_pci_regs[256]; +bar_t buslogic_pci_bar[3]; static void BuslogicBIOSUpdate(buslogic_data_t *bl) @@ -1135,25 +1101,25 @@ BuslogicBIOSUpdate(buslogic_data_t *bl) int bios_enabled = buslogic_pci_bar[2].addr_regs[0] & 0x01; if (!bl->has_bios) { - return; + return; } /* PCI BIOS stuff, just enable_disable. */ if ((bl->bios_addr > 0) && bios_enabled) { - mem_mapping_enable(&bl->bios.mapping); - mem_mapping_set_addr(&bl->bios.mapping, - bl->bios_addr, bl->bios_size); - buslogic_log("BT-958D: BIOS now at: %06X\n", bl->bios_addr); + mem_mapping_enable(&bl->bios.mapping); + mem_mapping_set_addr(&bl->bios.mapping, + bl->bios_addr, bl->bios_size); + buslogic_log("BT-958D: BIOS now at: %06X\n", bl->bios_addr); } else { - buslogic_log("BT-958D: BIOS disabled\n"); - mem_mapping_disable(&bl->bios.mapping); + buslogic_log("BT-958D: BIOS disabled\n"); + mem_mapping_disable(&bl->bios.mapping); } } static uint8_t -BuslogicPCIRead(int func, int addr, void *p) +BuslogicPCIRead(UNUSED(int func), int addr, void *priv) { - x54x_t *dev = (x54x_t *)p; + const x54x_t *dev = (x54x_t *) priv; #ifdef ENABLE_BUSLOGIC_LOG buslogic_data_t *bl = (buslogic_data_t *) dev->ven_data; #endif @@ -1161,218 +1127,226 @@ BuslogicPCIRead(int func, int addr, void *p) buslogic_log("BT-958D: Reading register %02X\n", addr & 0xff); switch (addr) { - case 0x00: - return 0x4b; - case 0x01: - return 0x10; - case 0x02: - return 0x40; - case 0x03: - return 0x10; - case 0x04: - return buslogic_pci_regs[0x04] & 0x03; /*Respond to IO and memory accesses*/ - case 0x05: - return 0; - case 0x07: - return 2; - case 0x08: - return 1; /*Revision ID*/ - case 0x09: - return 0; /*Programming interface*/ - case 0x0A: - return 0; /*Subclass*/ - case 0x0B: - return 1; /*Class code*/ - case 0x0E: - return 0; /*Header type */ - case 0x10: - return (buslogic_pci_bar[0].addr_regs[0] & 0xe0) | 1; /*I/O space*/ - case 0x11: - return buslogic_pci_bar[0].addr_regs[1]; - case 0x12: - return buslogic_pci_bar[0].addr_regs[2]; - case 0x13: - return buslogic_pci_bar[0].addr_regs[3]; - case 0x14: - // return (buslogic_pci_bar[1].addr_regs[0] & 0xe0); /*Memory space*/ - return 0x00; - case 0x15: - return buslogic_pci_bar[1].addr_regs[1] & 0xc0; - case 0x16: - return buslogic_pci_bar[1].addr_regs[2]; - case 0x17: - return buslogic_pci_bar[1].addr_regs[3]; - case 0x2C: - return 0x4b; - case 0x2D: - return 0x10; - case 0x2E: - return 0x40; - case 0x2F: - return 0x10; - case 0x30: /* PCI_ROMBAR */ - buslogic_log("BT-958D: BIOS BAR 00 = %02X\n", buslogic_pci_bar[2].addr_regs[0] & 0x01); - return buslogic_pci_bar[2].addr_regs[0] & 0x01; - case 0x31: /* PCI_ROMBAR 15:11 */ - buslogic_log("BT-958D: BIOS BAR 01 = %02X\n", (buslogic_pci_bar[2].addr_regs[1] & bl->bios_mask)); - return buslogic_pci_bar[2].addr_regs[1]; - break; - case 0x32: /* PCI_ROMBAR 23:16 */ - buslogic_log("BT-958D: BIOS BAR 02 = %02X\n", buslogic_pci_bar[2].addr_regs[2]); - return buslogic_pci_bar[2].addr_regs[2]; - break; - case 0x33: /* PCI_ROMBAR 31:24 */ - buslogic_log("BT-958D: BIOS BAR 03 = %02X\n", buslogic_pci_bar[2].addr_regs[3]); - return buslogic_pci_bar[2].addr_regs[3]; - break; - case 0x3C: - return dev->Irq; - case 0x3D: - return PCI_INTA; + case 0x00: + return 0x4b; + case 0x01: + return 0x10; + case 0x02: + return 0x40; + case 0x03: + return 0x10; + case 0x04: + return buslogic_pci_regs[0x04] & 0x03; /*Respond to IO and memory accesses*/ + case 0x05: + return 0; + case 0x07: + return 2; + case 0x08: + return 1; /*Revision ID*/ + case 0x09: + return 0; /*Programming interface*/ + case 0x0A: + return 0; /*Subclass*/ + case 0x0B: + return 1; /*Class code*/ + case 0x0E: + return 0; /*Header type */ + case 0x10: + return (buslogic_pci_bar[0].addr_regs[0] & 0xe0) | 1; /*I/O space*/ + case 0x11: + return buslogic_pci_bar[0].addr_regs[1]; + case 0x12: + return buslogic_pci_bar[0].addr_regs[2]; + case 0x13: + return buslogic_pci_bar[0].addr_regs[3]; + case 0x14: +#if 0 + return (buslogic_pci_bar[1].addr_regs[0] & 0xe0); /*Memory space*/ +#endif + return 0x00; + case 0x15: + return buslogic_pci_bar[1].addr_regs[1] & 0xc0; + case 0x16: + return buslogic_pci_bar[1].addr_regs[2]; + case 0x17: + return buslogic_pci_bar[1].addr_regs[3]; + case 0x2C: + return 0x4b; + case 0x2D: + return 0x10; + case 0x2E: + return 0x40; + case 0x2F: + return 0x10; + case 0x30: /* PCI_ROMBAR */ + buslogic_log("BT-958D: BIOS BAR 00 = %02X\n", buslogic_pci_bar[2].addr_regs[0] & 0x01); + return buslogic_pci_bar[2].addr_regs[0] & 0x01; + case 0x31: /* PCI_ROMBAR 15:11 */ + buslogic_log("BT-958D: BIOS BAR 01 = %02X\n", (buslogic_pci_bar[2].addr_regs[1] & bl->bios_mask)); + return buslogic_pci_bar[2].addr_regs[1]; + case 0x32: /* PCI_ROMBAR 23:16 */ + buslogic_log("BT-958D: BIOS BAR 02 = %02X\n", buslogic_pci_bar[2].addr_regs[2]); + return buslogic_pci_bar[2].addr_regs[2]; + case 0x33: /* PCI_ROMBAR 31:24 */ + buslogic_log("BT-958D: BIOS BAR 03 = %02X\n", buslogic_pci_bar[2].addr_regs[3]); + return buslogic_pci_bar[2].addr_regs[3]; + case 0x3C: + return dev->Irq; + case 0x3D: + return PCI_INTA; + + default: + break; } - return(0); + return 0; } - static void -BuslogicPCIWrite(int func, int addr, uint8_t val, void *p) +BuslogicPCIWrite(UNUSED(int func), int addr, uint8_t val, void *priv) { - x54x_t *dev = (x54x_t *)p; - buslogic_data_t *bl = (buslogic_data_t *) dev->ven_data; + x54x_t *dev = (x54x_t *) priv; + buslogic_data_t *bl = (buslogic_data_t *) dev->ven_data; uint8_t valxor; buslogic_log("BT-958D: Write value %02X to register %02X\n", val, addr & 0xff); switch (addr) { - case 0x04: - valxor = (val & 0x27) ^ buslogic_pci_regs[addr]; - if (valxor & PCI_COMMAND_IO) { - x54x_io_remove(dev, bl->PCIBase, 32); - if ((bl->PCIBase != 0) && (val & PCI_COMMAND_IO)) { - x54x_io_set(dev, bl->PCIBase, 32); - } - } - if (valxor & PCI_COMMAND_MEM) { - x54x_mem_disable(dev); - if ((bl->MMIOBase != 0) && (val & PCI_COMMAND_MEM)) { - x54x_mem_set_addr(dev, bl->MMIOBase); - } - } - buslogic_pci_regs[addr] = val & 0x27; - break; + case 0x04: + valxor = (val & 0x27) ^ buslogic_pci_regs[addr]; + if (valxor & PCI_COMMAND_IO) { + x54x_io_remove(dev, bl->PCIBase, 32); + if ((bl->PCIBase != 0) && (val & PCI_COMMAND_IO)) { + x54x_io_set(dev, bl->PCIBase, 32); + } + } + if (valxor & PCI_COMMAND_MEM) { + x54x_mem_disable(dev); + if ((bl->MMIOBase != 0) && (val & PCI_COMMAND_MEM)) { + x54x_mem_set_addr(dev, bl->MMIOBase); + } + } + buslogic_pci_regs[addr] = val & 0x27; + break; - case 0x10: - val &= 0xe0; - val |= 1; - /*FALLTHROUGH*/ + case 0x10: + val &= 0xe0; + val |= 1; + fallthrough; - case 0x11: case 0x12: case 0x13: - /* I/O Base set. */ - /* First, remove the old I/O. */ - x54x_io_remove(dev, bl->PCIBase, 32); - /* Then let's set the PCI regs. */ - buslogic_pci_bar[0].addr_regs[addr & 3] = val; - /* Then let's calculate the new I/O base. */ - bl->PCIBase = buslogic_pci_bar[0].addr & 0xffe0; - /* Log the new base. */ - buslogic_log("BusLogic PCI: New I/O base is %04X\n" , bl->PCIBase); - /* We're done, so get out of the here. */ - if (buslogic_pci_regs[4] & PCI_COMMAND_IO) { - if (bl->PCIBase != 0) { - x54x_io_set(dev, bl->PCIBase, 32); - } - } - return; + case 0x11: + case 0x12: + case 0x13: + /* I/O Base set. */ + /* First, remove the old I/O. */ + x54x_io_remove(dev, bl->PCIBase, 32); + /* Then let's set the PCI regs. */ + buslogic_pci_bar[0].addr_regs[addr & 3] = val; + /* Then let's calculate the new I/O base. */ + bl->PCIBase = buslogic_pci_bar[0].addr & 0xffe0; + /* Log the new base. */ + buslogic_log("BusLogic PCI: New I/O base is %04X\n", bl->PCIBase); + /* We're done, so get out of the here. */ + if (buslogic_pci_regs[4] & PCI_COMMAND_IO) { + if (bl->PCIBase != 0) { + x54x_io_set(dev, bl->PCIBase, 32); + } + } + return; - case 0x14: - val &= 0xe0; - /*FALLTHROUGH*/ + case 0x14: + val &= 0xe0; + fallthrough; - case 0x15: case 0x16: case 0x17: - /* MMIO Base set. */ - /* First, remove the old I/O. */ - x54x_mem_disable(dev); - /* Then let's set the PCI regs. */ - buslogic_pci_bar[1].addr_regs[addr & 3] = val; - /* Then let's calculate the new I/O base. */ - // bl->MMIOBase = buslogic_pci_bar[1].addr & 0xffffffe0; - /* Give it a 4 kB alignment as that's this emulator's granularity. */ - buslogic_pci_bar[1].addr &= 0xffffc000; - bl->MMIOBase = buslogic_pci_bar[1].addr & 0xffffc000; - /* Log the new base. */ - buslogic_log("BusLogic PCI: New MMIO base is %04X\n" , bl->MMIOBase); - /* We're done, so get out of the here. */ - if (buslogic_pci_regs[4] & PCI_COMMAND_MEM) { - if (bl->MMIOBase != 0) { - x54x_mem_set_addr(dev, bl->MMIOBase); - } - } - return; + case 0x15: + case 0x16: + case 0x17: + /* MMIO Base set. */ + /* First, remove the old I/O. */ + x54x_mem_disable(dev); + /* Then let's set the PCI regs. */ + buslogic_pci_bar[1].addr_regs[addr & 3] = val; + /* Then let's calculate the new I/O base. */ +#if 0 + bl->MMIOBase = buslogic_pci_bar[1].addr & 0xffffffe0; +#endif + /* Give it a 4 kB alignment as that's this emulator's granularity. */ + buslogic_pci_bar[1].addr &= 0xffffc000; + bl->MMIOBase = buslogic_pci_bar[1].addr & 0xffffc000; + /* Log the new base. */ + buslogic_log("BusLogic PCI: New MMIO base is %04X\n", bl->MMIOBase); + /* We're done, so get out of the here. */ + if (buslogic_pci_regs[4] & PCI_COMMAND_MEM) { + if (bl->MMIOBase != 0) { + x54x_mem_set_addr(dev, bl->MMIOBase); + } + } + return; - case 0x30: /* PCI_ROMBAR */ - case 0x31: /* PCI_ROMBAR */ - case 0x32: /* PCI_ROMBAR */ - case 0x33: /* PCI_ROMBAR */ - buslogic_pci_bar[2].addr_regs[addr & 3] = val; - buslogic_pci_bar[2].addr &= 0xffffc001; - bl->bios_addr = buslogic_pci_bar[2].addr & 0xffffc000; - buslogic_log("BT-958D: BIOS BAR %02X = NOW %02X (%02X)\n", addr & 3, buslogic_pci_bar[2].addr_regs[addr & 3], val); - BuslogicBIOSUpdate(bl); - return; + case 0x30: /* PCI_ROMBAR */ + case 0x31: /* PCI_ROMBAR */ + case 0x32: /* PCI_ROMBAR */ + case 0x33: /* PCI_ROMBAR */ + buslogic_pci_bar[2].addr_regs[addr & 3] = val; + buslogic_pci_bar[2].addr &= 0xffffc001; + bl->bios_addr = buslogic_pci_bar[2].addr & 0xffffc000; + buslogic_log("BT-958D: BIOS BAR %02X = NOW %02X (%02X)\n", addr & 3, buslogic_pci_bar[2].addr_regs[addr & 3], val); + BuslogicBIOSUpdate(bl); + return; - case 0x3C: - buslogic_pci_regs[addr] = val; - if (val != 0xFF) { - buslogic_log("BusLogic IRQ now: %i\n", val); - dev->Irq = val; - } else - dev->Irq = 0; - return; + case 0x3C: + buslogic_pci_regs[addr] = val; + if (val != 0xFF) { + buslogic_log("BusLogic IRQ now: %i\n", val); + dev->Irq = val; + } else + dev->Irq = 0; + return; + + default: + break; } } - static void BuslogicInitializeLocalRAM(buslogic_data_t *bl) { memset(bl->LocalRAM.u8View, 0, sizeof(HALocalRAM)); if (bl->chip == CHIP_BUSLOGIC_PCI_958D_1995_12_30) { - bl->LocalRAM.structured.autoSCSIData.fLevelSensitiveInterrupt = 1; + bl->LocalRAM.structured.autoSCSIData.fLevelSensitiveInterrupt = 1; } else { - bl->LocalRAM.structured.autoSCSIData.fLevelSensitiveInterrupt = 0; + bl->LocalRAM.structured.autoSCSIData.fLevelSensitiveInterrupt = 0; } - bl->LocalRAM.structured.autoSCSIData.u16DeviceEnabledMask = ~0; - bl->LocalRAM.structured.autoSCSIData.u16WidePermittedMask = ~0; - bl->LocalRAM.structured.autoSCSIData.u16FastPermittedMask = ~0; + bl->LocalRAM.structured.autoSCSIData.u16DeviceEnabledMask = ~0; + bl->LocalRAM.structured.autoSCSIData.u16WidePermittedMask = ~0; + bl->LocalRAM.structured.autoSCSIData.u16FastPermittedMask = ~0; bl->LocalRAM.structured.autoSCSIData.u16SynchronousPermittedMask = ~0; - bl->LocalRAM.structured.autoSCSIData.u16DisconnectPermittedMask = ~0; - bl->LocalRAM.structured.autoSCSIData.fRoundRobinScheme = 0; - bl->LocalRAM.structured.autoSCSIData.u16UltraPermittedMask = ~0; + bl->LocalRAM.structured.autoSCSIData.u16DisconnectPermittedMask = ~0; + bl->LocalRAM.structured.autoSCSIData.fRoundRobinScheme = 0; + bl->LocalRAM.structured.autoSCSIData.u16UltraPermittedMask = ~0; } - static uint8_t buslogic_mca_read(int port, void *priv) { - x54x_t *dev = (x54x_t *)priv; + const x54x_t *dev = (x54x_t *) priv; - return(dev->pos_regs[port & 7]); + return (dev->pos_regs[port & 7]); } - static void buslogic_mca_write(int port, uint8_t val, void *priv) { - x54x_t *dev = (x54x_t *) priv; - buslogic_data_t *bl = (buslogic_data_t *) dev->ven_data; + x54x_t *dev = (x54x_t *) priv; + buslogic_data_t *bl = (buslogic_data_t *) dev->ven_data; HALocalRAM *HALR = &bl->LocalRAM; /* MCA does not write registers below 0x0100. */ - if (port < 0x0102) return; + if (port < 0x0102) + return; /* Save the MCA register value. */ dev->pos_regs[port & 7] = val; @@ -1382,52 +1356,57 @@ buslogic_mca_write(int port, uint8_t val, void *priv) /* Get the new assigned I/O base address. */ if (dev->pos_regs[3]) { - dev->Base = dev->pos_regs[3] << 8; - dev->Base |= ((dev->pos_regs[2] & 0x10) ? 0x34 : 0x30); + dev->Base = dev->pos_regs[3] << 8; + dev->Base |= ((dev->pos_regs[2] & 0x10) ? 0x34 : 0x30); } else { - dev->Base = 0x0000; + dev->Base = 0x0000; } /* Save the new IRQ and DMA channel values. */ - dev->Irq = ((dev->pos_regs[2] >> 1) & 0x07) + 8; - dev->DmaChannel = dev->pos_regs[5] & 0x0f; + dev->Irq = ((dev->pos_regs[2] >> 1) & 0x07) + 8; + dev->DmaChannel = dev->pos_regs[5] & 0x0f; /* Extract the BIOS ROM address info. */ - if (dev->pos_regs[2] & 0xe0) switch(dev->pos_regs[2] & 0xe0) { - case 0xe0: /* [0]=111x xxxx */ - bl->bios_addr = 0xDC000; - break; + if (dev->pos_regs[2] & 0xe0) + switch (dev->pos_regs[2] & 0xe0) { + case 0xe0: /* [0]=111x xxxx */ + bl->bios_addr = 0xDC000; + break; - case 0x00: /* [0]=000x xxxx */ - bl->bios_addr = 0; - break; - - case 0xc0: /* [0]=110x xxxx */ - bl->bios_addr = 0xD8000; - break; + case 0x00: /* [0]=000x xxxx */ + bl->bios_addr = 0; + break; - case 0xa0: /* [0]=101x xxxx */ - bl->bios_addr = 0xD4000; - break; + case 0xc0: /* [0]=110x xxxx */ + bl->bios_addr = 0xD8000; + break; - case 0x80: /* [0]=100x xxxx */ - bl->bios_addr = 0xD0000; - break; + case 0xa0: /* [0]=101x xxxx */ + bl->bios_addr = 0xD4000; + break; - case 0x60: /* [0]=011x xxxx */ - bl->bios_addr = 0xCC000; - break; + case 0x80: /* [0]=100x xxxx */ + bl->bios_addr = 0xD0000; + break; - case 0x40: /* [0]=010x xxxx */ - bl->bios_addr = 0xC8000; - break; + case 0x60: /* [0]=011x xxxx */ + bl->bios_addr = 0xCC000; + break; - case 0x20: /* [0]=001x xxxx */ - bl->bios_addr = 0xC4000; - break; - } else { - /* Disabled. */ - bl->bios_addr = 0x000000; + case 0x40: /* [0]=010x xxxx */ + bl->bios_addr = 0xC8000; + break; + + case 0x20: /* [0]=001x xxxx */ + bl->bios_addr = 0xC4000; + break; + + default: + break; + } + else { + /* Disabled. */ + bl->bios_addr = 0x000000; } /* @@ -1437,7 +1416,7 @@ buslogic_mca_write(int port, uint8_t val, void *priv) * pos[2]=111xxxxx = 7 * pos[2]=000xxxxx = 0 */ - dev->HostID = (dev->pos_regs[4] >> 5) & 0x07; + dev->HostID = (dev->pos_regs[4] >> 5) & 0x07; HALR->structured.autoSCSIData.uSCSIId = dev->HostID; /* @@ -1458,43 +1437,43 @@ buslogic_mca_write(int port, uint8_t val, void *priv) HALR->structured.autoSCSIData.uBIOSConfiguration &= ~4; HALR->structured.autoSCSIData.uBIOSConfiguration |= (dev->pos_regs[4] & 8) ? 4 : 0; - switch(dev->DmaChannel) { - case 5: - HALR->structured.autoSCSIData.uDMAChannel = 1; - break; - case 6: - HALR->structured.autoSCSIData.uDMAChannel = 2; - break; - case 7: - HALR->structured.autoSCSIData.uDMAChannel = 3; - break; - default: - HALR->structured.autoSCSIData.uDMAChannel = 0; - break; + switch (dev->DmaChannel) { + case 5: + HALR->structured.autoSCSIData.uDMAChannel = 1; + break; + case 6: + HALR->structured.autoSCSIData.uDMAChannel = 2; + break; + case 7: + HALR->structured.autoSCSIData.uDMAChannel = 3; + break; + default: + HALR->structured.autoSCSIData.uDMAChannel = 0; + break; } - switch(dev->Irq) { - case 9: - HALR->structured.autoSCSIData.uIrqChannel = 1; - break; - case 10: - HALR->structured.autoSCSIData.uIrqChannel = 2; - break; - case 11: - HALR->structured.autoSCSIData.uIrqChannel = 3; - break; - case 12: - HALR->structured.autoSCSIData.uIrqChannel = 4; - break; - case 14: - HALR->structured.autoSCSIData.uIrqChannel = 5; - break; - case 15: - HALR->structured.autoSCSIData.uIrqChannel = 6; - break; - default: - HALR->structured.autoSCSIData.uIrqChannel = 0; - break; + switch (dev->Irq) { + case 9: + HALR->structured.autoSCSIData.uIrqChannel = 1; + break; + case 10: + HALR->structured.autoSCSIData.uIrqChannel = 2; + break; + case 11: + HALR->structured.autoSCSIData.uIrqChannel = 3; + break; + case 12: + HALR->structured.autoSCSIData.uIrqChannel = 4; + break; + case 14: + HALR->structured.autoSCSIData.uIrqChannel = 5; + break; + case 15: + HALR->structured.autoSCSIData.uIrqChannel = 6; + break; + default: + HALR->structured.autoSCSIData.uIrqChannel = 0; + break; } /* @@ -1508,39 +1487,37 @@ buslogic_mca_write(int port, uint8_t val, void *priv) /* Initialize the device if fully configured. */ if (dev->pos_regs[2] & 0x01) { - /* Card enabled; register (new) I/O handler. */ - x54x_io_set(dev, dev->Base, 4); + /* Card enabled; register (new) I/O handler. */ + x54x_io_set(dev, dev->Base, 4); - /* Reset the device. */ - x54x_reset_ctrl(dev, CTRL_HRST); + /* Reset the device. */ + x54x_reset_ctrl(dev, CTRL_HRST); - /* Enable or disable the BIOS ROM. */ - if (bl->has_bios && (bl->bios_addr != 0x000000)) { - mem_mapping_enable(&bl->bios.mapping); - mem_mapping_set_addr(&bl->bios.mapping, bl->bios_addr, ROM_SIZE); - } + /* Enable or disable the BIOS ROM. */ + if (bl->has_bios && (bl->bios_addr != 0x000000)) { + mem_mapping_enable(&bl->bios.mapping); + mem_mapping_set_addr(&bl->bios.mapping, bl->bios_addr, ROM_SIZE); + } - /* Say hello. */ - buslogic_log("BT-640A: I/O=%04x, IRQ=%d, DMA=%d, BIOS @%05X, HOST ID %i\n", - dev->Base, dev->Irq, dev->DmaChannel, bl->bios_addr, dev->HostID); + /* Say hello. */ + buslogic_log("BT-640A: I/O=%04x, IRQ=%d, DMA=%d, BIOS @%05X, HOST ID %i\n", + dev->Base, dev->Irq, dev->DmaChannel, bl->bios_addr, dev->HostID); } } - static uint8_t buslogic_mca_feedb(void *priv) { - x54x_t *dev = (x54x_t *)priv; + const x54x_t *dev = (x54x_t *) priv; return (dev->pos_regs[2] & 0x01); } - void -BuslogicDeviceReset(void *p) +BuslogicDeviceReset(void *priv) { - x54x_t *dev = (x54x_t *) p; - buslogic_data_t *bl = (buslogic_data_t *) dev->ven_data; + x54x_t *dev = (x54x_t *) priv; + buslogic_data_t *bl = (buslogic_data_t *) dev->ven_data; x54x_device_reset(dev); @@ -1548,26 +1525,25 @@ BuslogicDeviceReset(void *p) BuslogicInitializeAutoSCSIRam(dev); } - static void * buslogic_init(const device_t *info) { - x54x_t *dev; - char *bios_rom_name; - uint16_t bios_rom_size; - uint16_t bios_rom_mask; - uint8_t has_autoscsi_rom; - char *autoscsi_rom_name; - uint16_t autoscsi_rom_size; - uint8_t has_scam_rom; - char *scam_rom_name; - uint16_t scam_rom_size; - FILE *f; + x54x_t *dev; + const char *bios_rom_name; + uint16_t bios_rom_size = 0; + uint16_t bios_rom_mask = 0; + uint8_t has_autoscsi_rom; + const char *autoscsi_rom_name = NULL; + uint16_t autoscsi_rom_size = 0; + uint8_t has_scam_rom; + const char *scam_rom_name = NULL; + uint16_t scam_rom_size = 0; + FILE *fp; buslogic_data_t *bl; - uint32_t bios_rom_addr; + uint32_t bios_rom_addr; /* Call common initializer. */ - dev = x54x_init(info); + dev = x54x_init(info); dev->bus = scsi_get_bus(); dev->ven_data = malloc(sizeof(buslogic_data_t)); @@ -1577,413 +1553,423 @@ buslogic_init(const device_t *info) dev->card_bus = info->flags; if (!(info->flags & DEVICE_MCA) && !(info->flags & DEVICE_PCI)) { - dev->Base = device_get_config_hex16("base"); - dev->Irq = device_get_config_int("irq"); - dev->DmaChannel = device_get_config_int("dma"); + dev->Base = device_get_config_hex16("base"); + dev->Irq = device_get_config_int("irq"); + dev->DmaChannel = device_get_config_int("dma"); + } else if (info->flags & DEVICE_PCI) { + dev->Base = 0; } - else if (info->flags & DEVICE_PCI) { - dev->Base = 0; - } - dev->HostID = 7; /* default HA ID */ + dev->HostID = 7; /* default HA ID */ dev->setup_info_len = sizeof(buslogic_setup_t); - dev->max_id = 7; - dev->flags = X54X_INT_GEOM_WRITABLE; + dev->max_id = 7; + dev->flags = X54X_INT_GEOM_WRITABLE; - bl->chip = info->local; - bl->PCIBase = 0; + bl->chip = info->local; + bl->PCIBase = 0; bl->MMIOBase = 0; if (info->flags & DEVICE_PCI) { - bios_rom_addr = 0xd8000; - bl->has_bios = device_get_config_int("bios"); + bios_rom_addr = 0xd8000; + bl->has_bios = device_get_config_int("bios"); } else if (info->flags & DEVICE_MCA) { - bios_rom_addr = 0xd8000; - bl->has_bios = 1; + bios_rom_addr = 0xd8000; + bl->has_bios = 1; } else { - bios_rom_addr = device_get_config_hex20("bios_addr"); - bl->has_bios = !!bios_rom_addr; + bios_rom_addr = device_get_config_hex20("bios_addr"); + bl->has_bios = !!bios_rom_addr; } - dev->ven_cmd_phase1 = buslogic_cmd_phase1; - dev->ven_get_host_id = buslogic_get_host_id; - dev->ven_get_irq = buslogic_get_irq; - dev->ven_get_dma = buslogic_get_dma; - dev->get_ven_param_len = buslogic_param_len; - dev->ven_cmds = buslogic_cmds; - dev->interrupt_type = buslogic_interrupt_type; + dev->ven_cmd_phase1 = buslogic_cmd_phase1; + dev->ven_get_host_id = buslogic_get_host_id; + dev->ven_get_irq = buslogic_get_irq; + dev->ven_get_dma = buslogic_get_dma; + dev->get_ven_param_len = buslogic_param_len; + dev->ven_cmds = buslogic_cmds; + dev->interrupt_type = buslogic_interrupt_type; dev->is_aggressive_mode = buslogic_is_aggressive_mode; - dev->get_ven_data = buslogic_setup_data; - dev->ven_reset = buslogic_reset; + dev->get_ven_data = buslogic_setup_data; + dev->ven_reset = buslogic_reset; strcpy(dev->vendor, "BusLogic"); bl->fAggressiveRoundRobinMode = 1; - bios_rom_name = NULL; - has_autoscsi_rom = 0; - has_scam_rom = 0; + bios_rom_name = NULL; + has_autoscsi_rom = 0; + has_scam_rom = 0; - switch (bl->chip) { - case CHIP_BUSLOGIC_ISA_542B_1991_12_14: /*Dated December 14th, 1991*/ - strcpy(dev->name, "BT-542B"); - bios_rom_name = "roms/scsi/buslogic/BT-542B_BIOS.ROM"; - bios_rom_size = 0x4000; - bios_rom_mask = 0x3fff; - has_autoscsi_rom = 0; - has_scam_rom = 0; - dev->fw_rev = "AA221"; - dev->ha_bps = 5000000.0; /* normal SCSI */ - dev->max_id = 7; /* narrow SCSI */ - break; - case CHIP_BUSLOGIC_ISA_545S_1992_10_05: /*Dated October 5th, 1992*/ - strcpy(dev->name, "BT-545S"); - bios_rom_name = "roms/scsi/buslogic/BT-545S_BIOS.rom"; - bios_rom_size = 0x4000; - bios_rom_mask = 0x3fff; - has_autoscsi_rom = 0; - has_scam_rom = 0; - dev->fw_rev = "AA331"; - dev->ha_bps = 5000000.0; /* normal SCSI */ - dev->max_id = 7; /* narrow SCSI */ - break; - case CHIP_BUSLOGIC_ISA_542BH_1993_05_23: /*Dated May 23rd, 1993*/ - strcpy(dev->name, "BT-542BH"); - bios_rom_name = "roms/scsi/buslogic/BT-542BH_BIOS.rom"; - bios_rom_size = 0x4000; - bios_rom_mask = 0x3fff; - has_autoscsi_rom = 0; - has_scam_rom = 0; - dev->fw_rev = "AA335"; - dev->ha_bps = 5000000.0; /* normal SCSI */ - dev->max_id = 7; /* narrow SCSI */ - break; - case CHIP_BUSLOGIC_ISA_545C_1994_12_01: /*Dated December 1st, 1994*/ - strcpy(dev->name, "BT-545C"); - bios_rom_name = "roms/scsi/buslogic/BT-545C_BIOS.rom"; - bios_rom_size = 0x4000; - bios_rom_mask = 0x3fff; - has_autoscsi_rom = 1; - autoscsi_rom_name = "roms/scsi/buslogic/BT-545C_AutoSCSI.rom"; - autoscsi_rom_size = 0x4000; - has_scam_rom = 0; - dev->fw_rev = "AA425J"; - dev->ha_bps = 10000000.0; /* fast SCSI */ - dev->max_id = 7; /* narrow SCSI */ - break; - case CHIP_BUSLOGIC_MCA_640A_1993_05_23: /*Dated May 23rd, 1993*/ - strcpy(dev->name, "BT-640A"); - bios_rom_name = "roms/scsi/buslogic/BT-640A_BIOS.rom"; - bios_rom_size = 0x4000; - bios_rom_mask = 0x3fff; - has_autoscsi_rom = 0; - has_scam_rom = 0; - dev->fw_rev = "BA335"; - dev->flags |= X54X_32BIT; - dev->pos_regs[0] = 0x08; /* MCA board ID */ - dev->pos_regs[1] = 0x07; - mca_add(buslogic_mca_read, buslogic_mca_write, buslogic_mca_feedb, NULL, dev); - dev->ha_bps = 5000000.0; /* normal SCSI */ - dev->max_id = 7; /* narrow SCSI */ - break; - case CHIP_BUSLOGIC_VLB_445S_1993_11_16: /*Dated November 16th, 1993*/ - strcpy(dev->name, "BT-445S"); - bios_rom_name = "roms/scsi/buslogic/BT-445S_BIOS.rom"; - bios_rom_size = 0x4000; - bios_rom_mask = 0x3fff; - has_autoscsi_rom = 0; - has_scam_rom = 0; - dev->fw_rev = "AA335"; - dev->flags |= X54X_32BIT; - dev->ha_bps = 5000000.0; /* normal SCSI */ - dev->max_id = 7; /* narrow SCSI */ - break; - case CHIP_BUSLOGIC_VLB_445C_1994_12_01: /*Dated December 1st, 1994*/ - strcpy(dev->name, "BT-445C"); - bios_rom_name = "roms/scsi/buslogic/BT-445C_BIOS.rom"; - bios_rom_size = 0x4000; - bios_rom_mask = 0x3fff; - has_autoscsi_rom = 1; - autoscsi_rom_name = "roms/scsi/buslogic/BT-445C_AutoSCSI.rom"; - autoscsi_rom_size = 0x4000; - has_scam_rom = 0; - dev->fw_rev = "AA425J"; - dev->flags |= X54X_32BIT; - dev->ha_bps = 10000000.0; /* fast SCSI */ - dev->max_id = 7; /* narrow SCSI */ - break; - case CHIP_BUSLOGIC_PCI_958D_1995_12_30: /*Dated December 30th, 1995*/ - strcpy(dev->name, "BT-958D"); - bios_rom_name = "roms/scsi/buslogic/BT-958D_BIOS.rom"; - bios_rom_size = 0x4000; - bios_rom_mask = 0x3fff; - has_autoscsi_rom = 1; - autoscsi_rom_name = "roms/scsi/buslogic/BT-958D_AutoSCSI.rom"; - autoscsi_rom_size = 0x8000; - has_scam_rom = 1; - scam_rom_name = "roms/scsi/buslogic/BT-958D_SCAM.rom"; - scam_rom_size = 0x0200; - dev->fw_rev = "AA507B"; - dev->flags |= (X54X_CDROM_BOOT | X54X_32BIT); - dev->ha_bps = 20000000.0; /* ultra SCSI */ - dev->max_id = 15; /* wide SCSI */ - break; - } + switch (bl->chip) { + case CHIP_BUSLOGIC_ISA_542B_1991_12_14: /*Dated December 14th, 1991*/ + strcpy(dev->name, "BT-542B"); + bios_rom_name = "roms/scsi/buslogic/BT-542B_BIOS.ROM"; + bios_rom_size = 0x4000; + bios_rom_mask = 0x3fff; + has_autoscsi_rom = 0; + has_scam_rom = 0; + dev->fw_rev = "AA221"; + dev->ha_bps = 5000000.0; /* normal SCSI */ + dev->max_id = 7; /* narrow SCSI */ + break; + case CHIP_BUSLOGIC_ISA_545S_1992_10_05: /*Dated October 5th, 1992*/ + strcpy(dev->name, "BT-545S"); + bios_rom_name = "roms/scsi/buslogic/BT-545S_BIOS.rom"; + bios_rom_size = 0x4000; + bios_rom_mask = 0x3fff; + has_autoscsi_rom = 0; + has_scam_rom = 0; + dev->fw_rev = "AA331"; + dev->ha_bps = 5000000.0; /* normal SCSI */ + dev->max_id = 7; /* narrow SCSI */ + break; + case CHIP_BUSLOGIC_ISA_542BH_1993_05_23: /*Dated May 23rd, 1993*/ + strcpy(dev->name, "BT-542BH"); + bios_rom_name = "roms/scsi/buslogic/BT-542BH_BIOS.rom"; + bios_rom_size = 0x4000; + bios_rom_mask = 0x3fff; + has_autoscsi_rom = 0; + has_scam_rom = 0; + dev->fw_rev = "AA335"; + dev->ha_bps = 5000000.0; /* normal SCSI */ + dev->max_id = 7; /* narrow SCSI */ + break; + case CHIP_BUSLOGIC_ISA_545C_1994_12_01: /*Dated December 1st, 1994*/ + strcpy(dev->name, "BT-545C"); + bios_rom_name = "roms/scsi/buslogic/BT-545C_BIOS.rom"; + bios_rom_size = 0x4000; + bios_rom_mask = 0x3fff; + has_autoscsi_rom = 1; + autoscsi_rom_name = "roms/scsi/buslogic/BT-545C_AutoSCSI.rom"; + autoscsi_rom_size = 0x4000; + has_scam_rom = 0; + dev->fw_rev = "AA425J"; + dev->ha_bps = 10000000.0; /* fast SCSI */ + dev->max_id = 7; /* narrow SCSI */ + break; + case CHIP_BUSLOGIC_MCA_640A_1993_05_23: /*Dated May 23rd, 1993*/ + strcpy(dev->name, "BT-640A"); + bios_rom_name = "roms/scsi/buslogic/BT-640A_BIOS.rom"; + bios_rom_size = 0x4000; + bios_rom_mask = 0x3fff; + has_autoscsi_rom = 0; + has_scam_rom = 0; + dev->fw_rev = "BA335"; + dev->flags |= X54X_32BIT; + dev->pos_regs[0] = 0x08; /* MCA board ID */ + dev->pos_regs[1] = 0x07; + mca_add(buslogic_mca_read, buslogic_mca_write, buslogic_mca_feedb, NULL, dev); + dev->ha_bps = 5000000.0; /* normal SCSI */ + dev->max_id = 7; /* narrow SCSI */ + break; + case CHIP_BUSLOGIC_VLB_445S_1993_11_16: /*Dated November 16th, 1993*/ + strcpy(dev->name, "BT-445S"); + bios_rom_name = "roms/scsi/buslogic/BT-445S_BIOS.rom"; + bios_rom_size = 0x4000; + bios_rom_mask = 0x3fff; + has_autoscsi_rom = 0; + has_scam_rom = 0; + dev->fw_rev = "AA335"; + dev->flags |= X54X_32BIT; + dev->ha_bps = 5000000.0; /* normal SCSI */ + dev->max_id = 7; /* narrow SCSI */ + break; + case CHIP_BUSLOGIC_VLB_445C_1994_12_01: /*Dated December 1st, 1994*/ + strcpy(dev->name, "BT-445C"); + bios_rom_name = "roms/scsi/buslogic/BT-445C_BIOS.rom"; + bios_rom_size = 0x4000; + bios_rom_mask = 0x3fff; + has_autoscsi_rom = 1; + autoscsi_rom_name = "roms/scsi/buslogic/BT-445C_AutoSCSI.rom"; + autoscsi_rom_size = 0x4000; + has_scam_rom = 0; + dev->fw_rev = "AA425J"; + dev->flags |= X54X_32BIT; + dev->ha_bps = 10000000.0; /* fast SCSI */ + dev->max_id = 7; /* narrow SCSI */ + break; + case CHIP_BUSLOGIC_PCI_958D_1995_12_30: /*Dated December 30th, 1995*/ + strcpy(dev->name, "BT-958D"); + bios_rom_name = "roms/scsi/buslogic/BT-958D_BIOS.rom"; + bios_rom_size = 0x4000; + bios_rom_mask = 0x3fff; + has_autoscsi_rom = 1; + autoscsi_rom_name = "roms/scsi/buslogic/BT-958D_AutoSCSI.rom"; + autoscsi_rom_size = 0x8000; + has_scam_rom = 1; + scam_rom_name = "roms/scsi/buslogic/BT-958D_SCAM.rom"; + scam_rom_size = 0x0200; + dev->fw_rev = "AA507B"; + dev->flags |= (X54X_CDROM_BOOT | X54X_32BIT); + dev->ha_bps = 20000000.0; /* ultra SCSI */ + dev->max_id = 15; /* wide SCSI */ + break; - if ((dev->Base != 0) && !(dev->card_bus & DEVICE_MCA) && !(dev->card_bus & DEVICE_PCI)) { - x54x_io_set(dev, dev->Base, 4); + default: + break; } + scsi_bus_set_speed(dev->bus, dev->ha_bps); + + if ((dev->Base != 0) && !(dev->card_bus & DEVICE_MCA) && !(dev->card_bus & DEVICE_PCI)) + x54x_io_set(dev, dev->Base, 4); + memset(bl->AutoSCSIROM, 0xff, 32768); memset(bl->SCAMData, 0x00, 65536); - if (bl->has_bios) - { - bl->bios_size = bios_rom_size; + if (bl->has_bios) { + bl->bios_size = bios_rom_size; - bl->bios_mask = 0xffffc000; + bl->bios_mask = 0xffffc000; - rom_init(&bl->bios, bios_rom_name, bios_rom_addr, bios_rom_size, bios_rom_mask, 0, MEM_MAPPING_EXTERNAL); + rom_init(&bl->bios, bios_rom_name, bios_rom_addr, bios_rom_size, bios_rom_mask, 0, MEM_MAPPING_EXTERNAL); - if (has_autoscsi_rom) { - f = rom_fopen(autoscsi_rom_name, "rb"); - if (f) { - fread(bl->AutoSCSIROM, 1, autoscsi_rom_size, f); - fclose(f); - f = NULL; - } - } + if (has_autoscsi_rom) { + fp = rom_fopen(autoscsi_rom_name, "rb"); + if (fp) { + (void) !fread(bl->AutoSCSIROM, 1, autoscsi_rom_size, fp); + fclose(fp); + fp = NULL; + } + } - if (has_scam_rom) { - f = rom_fopen(scam_rom_name, "rb"); - if (f) { - fread(bl->SCAMData, 1, scam_rom_size, f); - fclose(f); - f = NULL; - } - } - } - else { - bl->bios_size = 0; + if (has_scam_rom) { + fp = rom_fopen(scam_rom_name, "rb"); + if (fp) { + (void) !fread(bl->SCAMData, 1, scam_rom_size, fp); + fclose(fp); + fp = NULL; + } + } + } else { + bl->bios_size = 0; - bl->bios_mask = 0; + bl->bios_mask = 0; } if (bl->chip == CHIP_BUSLOGIC_PCI_958D_1995_12_30) { - dev->pci_slot = pci_add_card(PCI_ADD_NORMAL, BuslogicPCIRead, BuslogicPCIWrite, dev); + pci_add_card(PCI_ADD_NORMAL, BuslogicPCIRead, BuslogicPCIWrite, dev, &dev->pci_slot); - buslogic_pci_bar[0].addr_regs[0] = 1; - buslogic_pci_bar[1].addr_regs[0] = 0; - buslogic_pci_regs[0x04] = 3; + buslogic_pci_bar[0].addr_regs[0] = 1; + buslogic_pci_bar[1].addr_regs[0] = 0; + buslogic_pci_regs[0x04] = 3; - /* Enable our BIOS space in PCI, if needed. */ - if (bl->has_bios) { - buslogic_pci_bar[2].addr = 0xFFFFC000; - } else { - buslogic_pci_bar[2].addr = 0; - } + /* Enable our BIOS space in PCI, if needed. */ + if (bl->has_bios) { + buslogic_pci_bar[2].addr = 0xFFFFC000; + } else { + buslogic_pci_bar[2].addr = 0; + } - x54x_mem_init(dev, 0xfffd0000); - x54x_mem_disable(dev); + x54x_mem_init(dev, 0xfffd0000); + x54x_mem_disable(dev); } if ((bl->chip == CHIP_BUSLOGIC_MCA_640A_1993_05_23) || (bl->chip == CHIP_BUSLOGIC_PCI_958D_1995_12_30)) - mem_mapping_disable(&bl->bios.mapping); - + mem_mapping_disable(&bl->bios.mapping); + buslogic_log("Buslogic on port 0x%04X\n", dev->Base); - + x54x_device_reset(dev); - if ((bl->chip != CHIP_BUSLOGIC_ISA_542B_1991_12_14) && (bl->chip != CHIP_BUSLOGIC_ISA_545S_1992_10_05) && (bl->chip != CHIP_BUSLOGIC_ISA_542BH_1993_05_23) && - (bl->chip != CHIP_BUSLOGIC_VLB_445S_1993_11_16) && (bl->chip != CHIP_BUSLOGIC_MCA_640A_1993_05_23)) { - BuslogicInitializeLocalRAM(bl); - BuslogicInitializeAutoSCSIRam(dev); + if ((bl->chip != CHIP_BUSLOGIC_ISA_542B_1991_12_14) && (bl->chip != CHIP_BUSLOGIC_ISA_545S_1992_10_05) && (bl->chip != CHIP_BUSLOGIC_ISA_542BH_1993_05_23) && (bl->chip != CHIP_BUSLOGIC_VLB_445S_1993_11_16) && (bl->chip != CHIP_BUSLOGIC_MCA_640A_1993_05_23)) { + BuslogicInitializeLocalRAM(bl); + BuslogicInitializeAutoSCSIRam(dev); } - return(dev); + return dev; } - +// clang-format off static const device_config_t BT_ISA_Config[] = { - { - "base", "Address", CONFIG_HEX16, "", 0x334, "", { 0 }, - { - { - "0x330", 0x330 - }, - { - "0x334", 0x334 - }, - { - "0x230", 0x230 - }, - { - "0x234", 0x234 - }, - { - "0x130", 0x130 - }, - { - "0x134", 0x134 - }, - { - "", 0 - } - }, + { + .name = "base", + .description = "Address", + .type = CONFIG_HEX16, + .default_string = "", + .default_int = 0x334, + .file_filter = "", + .spinner = { 0 }, + .selection = { + { .description = "0x330", .value = 0x330 }, + { .description = "0x334", .value = 0x334 }, + { .description = "0x230", .value = 0x230 }, + { .description = "0x234", .value = 0x234 }, + { .description = "0x130", .value = 0x130 }, + { .description = "0x134", .value = 0x134 }, + { .description = "", .value = 0 } }, - { - "irq", "IRQ", CONFIG_SELECTION, "", 11, "", { 0 }, - { - { - "IRQ 9", 9 - }, - { - "IRQ 10", 10 - }, - { - "IRQ 11", 11 - }, - { - "IRQ 12", 12 - }, - { - "IRQ 14", 14 - }, - { - "IRQ 15", 15 - }, - { - "", 0 - } - }, + }, + { + .name = "irq", + .description = "IRQ", + .type = CONFIG_SELECTION, + .default_string = "", + .default_int = 11, + .file_filter = "", + .spinner = { 0 }, + .selection = { + { .description = "IRQ 9", .value = 9 }, + { .description = "IRQ 10", .value = 10 }, + { .description = "IRQ 11", .value = 11 }, + { .description = "IRQ 12", .value = 12 }, + { .description = "IRQ 14", .value = 14 }, + { .description = "IRQ 15", .value = 15 }, + { .description = "", 0 } }, - { - "dma", "DMA channel", CONFIG_SELECTION, "", 6, "", { 0 }, - { - { - "DMA 5", 5 - }, - { - "DMA 6", 6 - }, - { - "DMA 7", 7 - }, - { - "", 0 - } - }, + }, + { + .name = "dma", + .description = "DMA channel", + .type = CONFIG_SELECTION, + .default_string = "", + .default_int = 6, + .file_filter = "", + .spinner = { 0 }, + .selection = { + { .description = "DMA 5", .value = 5 }, + { .description = "DMA 6", .value = 6 }, + { .description = "DMA 7", .value = 7 }, + { .description = "", .value = 0 } }, - { - "bios_addr", "BIOS Address", CONFIG_HEX20, "", 0, "", { 0 }, - { - { - "Disabled", 0 - }, - { - "C800H", 0xc8000 - }, - { - "D000H", 0xd0000 - }, - { - "D800H", 0xd8000 - }, - { - "", 0 - } - }, + }, + { + .name = "bios_addr", + .description = "BIOS Address", + .type = CONFIG_HEX20, + .default_string = "", + .default_int = 0, + .file_filter = "", + .spinner = { 0 }, + .selection = { + { .description = "Disabled", .value = 0 }, + { .description = "C800H", .value = 0xc8000 }, + { .description = "D000H", .value = 0xd0000 }, + { .description = "D800H", .value = 0xd8000 }, + { .description = "", .value = 0 } }, - { - "", "", -1 - } + }, + { .name = "", .description = "", .type = CONFIG_END } }; - static const device_config_t BT958D_Config[] = { - { - "bios", "Enable BIOS", CONFIG_BINARY, "", 0 - }, - { - "", "", -1 - } + { + .name = "bios", + .description = "Enable BIOS", + .type = CONFIG_BINARY, + .default_string = "", + .default_int = 0 + }, + { .name = "", .description = "", .type = CONFIG_END } }; +// clang-format on const device_t buslogic_542b_device = { - "BusLogic BT-542B ISA", - "bt542b", - DEVICE_ISA | DEVICE_AT, - CHIP_BUSLOGIC_ISA_542B_1991_12_14, - buslogic_init, x54x_close, NULL, - { NULL }, NULL, NULL, - BT_ISA_Config + .name = "BusLogic BT-542B ISA", + .internal_name = "bt542b", + .flags = DEVICE_ISA | DEVICE_AT, + .local = CHIP_BUSLOGIC_ISA_542B_1991_12_14, + .init = buslogic_init, + .close = x54x_close, + .reset = NULL, + { .available = NULL }, + .speed_changed = NULL, + .force_redraw = NULL, + .config = BT_ISA_Config }; const device_t buslogic_545s_device = { - "BusLogic BT-545S ISA", - "bt545s", - DEVICE_ISA | DEVICE_AT, - CHIP_BUSLOGIC_ISA_545S_1992_10_05, - buslogic_init, x54x_close, NULL, - { NULL }, NULL, NULL, - BT_ISA_Config + .name = "BusLogic BT-545S ISA", + .internal_name = "bt545s", + .flags = DEVICE_ISA | DEVICE_AT, + .local = CHIP_BUSLOGIC_ISA_545S_1992_10_05, + .init = buslogic_init, + .close = x54x_close, + .reset = NULL, + { .available = NULL }, + .speed_changed = NULL, + .force_redraw = NULL, + .config = BT_ISA_Config }; const device_t buslogic_542bh_device = { - "BusLogic BT-542BH ISA", - "bt542bh", - DEVICE_ISA | DEVICE_AT, - CHIP_BUSLOGIC_ISA_542BH_1993_05_23, - buslogic_init, x54x_close, NULL, - { NULL }, NULL, NULL, - BT_ISA_Config + .name = "BusLogic BT-542BH ISA", + .internal_name = "bt542bh", + .flags = DEVICE_ISA | DEVICE_AT, + .local = CHIP_BUSLOGIC_ISA_542BH_1993_05_23, + .init = buslogic_init, + .close = x54x_close, + .reset = NULL, + { .available = NULL }, + .speed_changed = NULL, + .force_redraw = NULL, + .config = BT_ISA_Config }; const device_t buslogic_545c_device = { - "BusLogic BT-545C ISA", - "bt545c", - DEVICE_ISA | DEVICE_AT, - CHIP_BUSLOGIC_ISA_545C_1994_12_01, - buslogic_init, x54x_close, NULL, - { NULL }, NULL, NULL, - BT_ISA_Config + .name = "BusLogic BT-545C ISA", + .internal_name = "bt545c", + .flags = DEVICE_ISA | DEVICE_AT, + .local = CHIP_BUSLOGIC_ISA_545C_1994_12_01, + .init = buslogic_init, + .close = x54x_close, + .reset = NULL, + { .available = NULL }, + .speed_changed = NULL, + .force_redraw = NULL, + .config = BT_ISA_Config }; const device_t buslogic_640a_device = { - "BusLogic BT-640A MCA", - "bt640a", - DEVICE_MCA, - CHIP_BUSLOGIC_MCA_640A_1993_05_23, - buslogic_init, x54x_close, NULL, - { NULL }, NULL, NULL, - NULL + .name = "BusLogic BT-640A MCA", + .internal_name = "bt640a", + .flags = DEVICE_MCA, + .local = CHIP_BUSLOGIC_MCA_640A_1993_05_23, + .init = buslogic_init, + .close = x54x_close, + .reset = NULL, + { .available = NULL }, + .speed_changed = NULL, + .force_redraw = NULL, + .config = NULL }; const device_t buslogic_445s_device = { - "BusLogic BT-445S VLB", - "bt445s", - DEVICE_VLB, - CHIP_BUSLOGIC_VLB_445S_1993_11_16, - buslogic_init, x54x_close, NULL, - { NULL }, NULL, NULL, - BT_ISA_Config + .name = "BusLogic BT-445S VLB", + .internal_name = "bt445s", + .flags = DEVICE_VLB, + .local = CHIP_BUSLOGIC_VLB_445S_1993_11_16, + .init = buslogic_init, + .close = x54x_close, + .reset = NULL, + { .available = NULL }, + .speed_changed = NULL, + .force_redraw = NULL, + .config = BT_ISA_Config }; const device_t buslogic_445c_device = { - "BusLogic BT-445C VLB", - "bt445c", - DEVICE_VLB, - CHIP_BUSLOGIC_VLB_445C_1994_12_01, - buslogic_init, x54x_close, NULL, - { NULL }, NULL, NULL, - BT_ISA_Config + .name = "BusLogic BT-445C VLB", + .internal_name = "bt445c", + .flags = DEVICE_VLB, + .local = CHIP_BUSLOGIC_VLB_445C_1994_12_01, + .init = buslogic_init, + .close = x54x_close, + .reset = NULL, + { .available = NULL }, + .speed_changed = NULL, + .force_redraw = NULL, + .config = BT_ISA_Config }; const device_t buslogic_958d_pci_device = { - "BusLogic BT-958D PCI", - "bt958d", - DEVICE_PCI, - CHIP_BUSLOGIC_PCI_958D_1995_12_30, - buslogic_init, x54x_close, NULL, - { NULL }, NULL, NULL, - BT958D_Config + .name = "BusLogic BT-958D PCI", + .internal_name = "bt958d", + .flags = DEVICE_PCI, + .local = CHIP_BUSLOGIC_PCI_958D_1995_12_30, + .init = buslogic_init, + .close = x54x_close, + .reset = NULL, + { .available = NULL }, + .speed_changed = NULL, + .force_redraw = NULL, + .config = BT958D_Config }; diff --git a/src/scsi/scsi_cdrom.c b/src/scsi/scsi_cdrom.c index 8a443dd77..056c7fdfe 100644 --- a/src/scsi/scsi_cdrom.c +++ b/src/scsi/scsi_cdrom.c @@ -1,22 +1,23 @@ /* - * 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. + * 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. + * This file is part of the 86Box distribution. * - * Implementation of the CD-ROM drive with SCSI(-like) - * commands, for both ATAPI and SCSI usage. + * Implementation of the CD-ROM drive with SCSI(-like) + * commands, for both ATAPI and SCSI usage. * * * - * Author: Miran Grca, + * Authors: Miran Grca, * - * Copyright 2016-2020 Miran Grca. + * Copyright 2016-2020 Miran Grca. */ -#include #include +#include +#include #include #include #include @@ -27,7 +28,9 @@ #include <86box/config.h> #include <86box/timer.h> #include <86box/device.h> +#include <86box/scsi.h> #include <86box/scsi_device.h> +#include <86box/machine.h> #include <86box/nvr.h> #include <86box/hdc.h> #include <86box/hdc_ide.h> @@ -38,317 +41,471 @@ #include <86box/scsi_cdrom.h> #include <86box/version.h> +#define IDE_ATAPI_IS_EARLY id->sc->pad0 -#pragma pack(push,1) -typedef struct -{ - uint8_t opcode; - uint8_t polled; - uint8_t reserved2[2]; - uint8_t class; - uint8_t reserved3[2]; - uint16_t len; - uint8_t control; +#pragma pack(push, 1) +typedef struct gesn_cdb_t { + uint8_t opcode; + uint8_t polled; + uint8_t reserved2[2]; + uint8_t class; + uint8_t reserved3[2]; + uint16_t len; + uint8_t control; } gesn_cdb_t; -typedef struct -{ - uint16_t len; - uint8_t notification_class; - uint8_t supported_events; +typedef struct gesn_event_header_t { + uint16_t len; + uint8_t notification_class; + uint8_t supported_events; } gesn_event_header_t; #pragma pack(pop) - /* Table of all SCSI commands and their flags, needed for the new disc change / not ready handler. */ -const uint8_t scsi_cdrom_command_flags[0x100] = -{ - IMPLEMENTED | CHECK_READY | NONDATA, /* 0x00 */ - IMPLEMENTED | ALLOW_UA | NONDATA | SCSI_ONLY, /* 0x01 */ - 0, /* 0x02 */ - IMPLEMENTED | ALLOW_UA, /* 0x03 */ - 0, 0, 0, 0, /* 0x04-0x07 */ - IMPLEMENTED | CHECK_READY, /* 0x08 */ - 0, 0, /* 0x09-0x0A */ - IMPLEMENTED | CHECK_READY | NONDATA, /* 0x0B */ - 0, 0, 0, 0, 0, 0, /* 0x0C-0x11 */ - IMPLEMENTED | ALLOW_UA, /* 0x12 */ - IMPLEMENTED | CHECK_READY | NONDATA | SCSI_ONLY, /* 0x13 */ - 0, /* 0x14 */ - IMPLEMENTED, /* 0x15 */ - 0, 0, 0, 0, /* 0x16-0x19 */ - IMPLEMENTED, /* 0x1A */ - IMPLEMENTED | CHECK_READY, /* 0x1B */ - 0, 0, /* 0x1C-0x1D */ - IMPLEMENTED | CHECK_READY, /* 0x1E */ - 0, 0, 0, 0, 0, 0, /* 0x1F-0x24 */ - IMPLEMENTED | CHECK_READY, /* 0x25 */ - 0, 0, /* 0x26-0x27 */ - IMPLEMENTED | CHECK_READY, /* 0x28 */ - 0, 0, /* 0x29-0x2A */ - IMPLEMENTED | CHECK_READY | NONDATA, /* 0x2B */ - 0, 0, 0, /* 0x2C-0x2E */ - IMPLEMENTED | CHECK_READY | NONDATA | SCSI_ONLY, /* 0x2F */ - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0x30-0x3F */ - 0, 0, /* 0x40-0x41 */ - IMPLEMENTED | CHECK_READY, /* 0x42 */ - IMPLEMENTED | CHECK_READY, /* 0x43 - Read TOC - can get through UNIT_ATTENTION, per VIDE-CDD.SYS - NOTE: The ATAPI reference says otherwise, but I think this is a question of - interpreting things right - the UNIT ATTENTION condition we have here - is a tradition from not ready to ready, by definition the drive - eventually becomes ready, make the condition go away. */ - IMPLEMENTED | CHECK_READY, /* 0x44 */ - IMPLEMENTED | CHECK_READY, /* 0x45 */ - IMPLEMENTED | ALLOW_UA, /* 0x46 */ - IMPLEMENTED | CHECK_READY, /* 0x47 */ - IMPLEMENTED | CHECK_READY, /* 0x48 */ - IMPLEMENTED | CHECK_READY, /* 0x49 */ - IMPLEMENTED | ALLOW_UA, /* 0x4A */ - IMPLEMENTED | CHECK_READY, /* 0x4B */ - 0, 0, /* 0x4C-0x4D */ - IMPLEMENTED | CHECK_READY, /* 0x4E */ - 0, 0, /* 0x4F-0x50 */ - IMPLEMENTED | CHECK_READY, /* 0x51 */ - IMPLEMENTED | CHECK_READY, /* 0x52 */ - 0, 0, /* 0x53-0x54 */ - IMPLEMENTED, /* 0x55 */ - 0, 0, 0, 0, /* 0x56-0x59 */ - IMPLEMENTED, /* 0x5A */ - 0, 0, 0, 0, 0, /* 0x5B-0x5F */ - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0x60-0x6F */ - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0x70-0x7F */ - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0x80-0x8F */ - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0x90-0x9F */ - 0, 0, 0, 0, 0, /* 0xA0-0xA4 */ - IMPLEMENTED | CHECK_READY, /* 0xA5 */ - 0, 0, /* 0xA6-0xA7 */ - IMPLEMENTED | CHECK_READY, /* 0xA8 */ - IMPLEMENTED | CHECK_READY, /* 0xA9 */ - 0, 0, 0, /* 0xAA-0xAC */ - IMPLEMENTED | CHECK_READY, /* 0xAD */ - 0, /* 0xAE */ - IMPLEMENTED | CHECK_READY | NONDATA | SCSI_ONLY, /* 0xAF */ - 0, 0, 0, 0, /* 0xB0-0xB3 */ - IMPLEMENTED | CHECK_READY | ATAPI_ONLY, /* 0xB4 */ - 0, 0, 0, /* 0xB5-0xB7 */ - IMPLEMENTED | CHECK_READY | ATAPI_ONLY, /* 0xB8 */ - IMPLEMENTED | CHECK_READY, /* 0xB9 */ - IMPLEMENTED | CHECK_READY, /* 0xBA */ - IMPLEMENTED, /* 0xBB */ - IMPLEMENTED | CHECK_READY, /* 0xBC */ - IMPLEMENTED, /* 0xBD */ - IMPLEMENTED | CHECK_READY, /* 0xBE */ - IMPLEMENTED | CHECK_READY, /* 0xBF */ - IMPLEMENTED | CHECK_READY | SCSI_ONLY, /* 0xC0 */ - IMPLEMENTED | CHECK_READY | SCSI_ONLY, /* 0xC1 */ - IMPLEMENTED | CHECK_READY | SCSI_ONLY, /* 0xC2 */ - 0, /* 0xC3 */ - IMPLEMENTED | CHECK_READY | SCSI_ONLY, /* 0xC4 */ - 0, /* 0xC5 */ - IMPLEMENTED | CHECK_READY | SCSI_ONLY, /* 0xC6 */ - IMPLEMENTED | CHECK_READY | SCSI_ONLY, /* 0xC7 */ - 0, 0, 0, 0, 0, /* 0xC8-0xCC */ - IMPLEMENTED | CHECK_READY | SCSI_ONLY, /* 0xCD */ - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0xCE-0xD9 */ - IMPLEMENTED | SCSI_ONLY, /* 0xDA */ - 0, 0, 0, 0, 0, /* 0xDB-0xDF */ - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0xE0-0xEF */ - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 /* 0xF0-0xFF */ +uint8_t scsi_cdrom_command_flags[0x100] = { + IMPLEMENTED | CHECK_READY | NONDATA, /* 0x00 */ + IMPLEMENTED | ALLOW_UA | NONDATA | SCSI_ONLY, /* 0x01 */ + 0, /* 0x02 */ + IMPLEMENTED | ALLOW_UA, /* 0x03 */ + 0, 0, 0, 0, /* 0x04-0x07 */ + IMPLEMENTED | CHECK_READY, /* 0x08 */ + 0, 0, /* 0x09-0x0A */ + IMPLEMENTED | CHECK_READY | NONDATA, /* 0x0B */ + 0, /* 0x0C */ + IMPLEMENTED | CHECK_READY | SCSI_ONLY, /* 0x0D */ + 0, 0, 0, 0, /* 0x0E-0x11 */ + IMPLEMENTED | ALLOW_UA, /* 0x12 */ + IMPLEMENTED | CHECK_READY | NONDATA | SCSI_ONLY, /* 0x13 */ + 0, /* 0x14 */ + IMPLEMENTED, /* 0x15 */ + 0, 0, 0, 0, /* 0x16-0x19 */ + IMPLEMENTED, /* 0x1A */ + IMPLEMENTED | CHECK_READY, /* 0x1B */ + 0, 0, /* 0x1C-0x1D */ + IMPLEMENTED | CHECK_READY, /* 0x1E */ + 0, 0, 0, /* 0x1F-0x21*/ + IMPLEMENTED | CHECK_READY | SCSI_ONLY, /* 0x22*/ + 0, 0, /* 0x23-0x24 */ + IMPLEMENTED | CHECK_READY, /* 0x25 */ + IMPLEMENTED | CHECK_READY | SCSI_ONLY, /* 0x26 */ + 0, /* 0x27 */ + IMPLEMENTED | CHECK_READY, /* 0x28 */ + 0, 0, /* 0x29-0x2A */ + IMPLEMENTED | CHECK_READY | NONDATA, /* 0x2B */ + 0, 0, 0, /* 0x2C-0x2E */ + IMPLEMENTED | CHECK_READY | NONDATA | SCSI_ONLY, /* 0x2F */ + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0x30-0x3F */ + 0, 0, /* 0x40-0x41 */ + IMPLEMENTED | CHECK_READY, /* 0x42 */ + IMPLEMENTED | CHECK_READY, /* 0x43 - Read TOC - can get through UNIT_ATTENTION, per VIDE-CDD.SYS + NOTE: The ATAPI reference says otherwise, but I think this is a question of + interpreting things right - the UNIT ATTENTION condition we have here + is a tradition from not ready to ready, by definition the drive + eventually becomes ready, make the condition go away. */ + IMPLEMENTED | CHECK_READY, /* 0x44 */ + IMPLEMENTED | CHECK_READY, /* 0x45 */ + IMPLEMENTED | ALLOW_UA, /* 0x46 */ + IMPLEMENTED | CHECK_READY, /* 0x47 */ + IMPLEMENTED | CHECK_READY, /* 0x48 */ + IMPLEMENTED | CHECK_READY, /* 0x49 */ + IMPLEMENTED | ALLOW_UA, /* 0x4A */ + IMPLEMENTED | CHECK_READY, /* 0x4B */ + 0, 0, /* 0x4C-0x4D */ + IMPLEMENTED | CHECK_READY, /* 0x4E */ + 0, 0, /* 0x4F-0x50 */ + IMPLEMENTED | CHECK_READY, /* 0x51 */ + IMPLEMENTED | CHECK_READY, /* 0x52 */ + 0, 0, /* 0x53-0x54 */ + IMPLEMENTED, /* 0x55 */ + 0, 0, 0, 0, /* 0x56-0x59 */ + IMPLEMENTED, /* 0x5A */ + 0, 0, 0, 0, 0, /* 0x5B-0x5F */ + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0x60-0x6F */ + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0x70-0x7F */ + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0x80-0x8F */ + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0x90-0x9F */ + 0, 0, 0, 0, 0, /* 0xA0-0xA4 */ + IMPLEMENTED | CHECK_READY, /* 0xA5 */ + 0, 0, /* 0xA6-0xA7 */ + IMPLEMENTED | CHECK_READY, /* 0xA8 */ + IMPLEMENTED | CHECK_READY, /* 0xA9 */ + 0, 0, 0, /* 0xAA-0xAC */ + IMPLEMENTED | CHECK_READY, /* 0xAD */ + 0, /* 0xAE */ + IMPLEMENTED | CHECK_READY | NONDATA | SCSI_ONLY, /* 0xAF */ + 0, 0, 0, 0, /* 0xB0-0xB3 */ + IMPLEMENTED | CHECK_READY | ATAPI_ONLY, /* 0xB4 */ + 0, 0, 0, /* 0xB5-0xB7 */ + IMPLEMENTED | CHECK_READY | ATAPI_ONLY, /* 0xB8 */ + IMPLEMENTED | CHECK_READY, /* 0xB9 */ + IMPLEMENTED | CHECK_READY, /* 0xBA */ + IMPLEMENTED, /* 0xBB */ + IMPLEMENTED | CHECK_READY, /* 0xBC */ + IMPLEMENTED, /* 0xBD */ + IMPLEMENTED | CHECK_READY, /* 0xBE */ + IMPLEMENTED | CHECK_READY, /* 0xBF */ + IMPLEMENTED | CHECK_READY | SCSI_ONLY, /* 0xC0 */ + IMPLEMENTED | CHECK_READY | SCSI_ONLY, /* 0xC1 */ + IMPLEMENTED | CHECK_READY | SCSI_ONLY, /* 0xC2 */ + IMPLEMENTED | CHECK_READY | SCSI_ONLY, /* 0xC3 */ + IMPLEMENTED | CHECK_READY | SCSI_ONLY, /* 0xC4 */ + IMPLEMENTED | CHECK_READY | SCSI_ONLY, /* 0xC5 */ + IMPLEMENTED | CHECK_READY | SCSI_ONLY, /* 0xC6 */ + IMPLEMENTED | CHECK_READY | SCSI_ONLY, /* 0xC7 */ + IMPLEMENTED | CHECK_READY | SCSI_ONLY, /* 0xC8 */ + IMPLEMENTED | CHECK_READY | SCSI_ONLY, /* 0xC9 */ + IMPLEMENTED | CHECK_READY | SCSI_ONLY, /* 0xCA */ + IMPLEMENTED | CHECK_READY | SCSI_ONLY, /* 0xCB */ + IMPLEMENTED | CHECK_READY | SCSI_ONLY, /* 0xCC */ + IMPLEMENTED | CHECK_READY | SCSI_ONLY, /* 0xCD */ + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0xCE-0xD7 */ + IMPLEMENTED | CHECK_READY | SCSI_ONLY, /* 0xD8 */ + IMPLEMENTED | CHECK_READY | SCSI_ONLY, /* 0xD9 */ + IMPLEMENTED | CHECK_READY | SCSI_ONLY, /* 0xDA */ + IMPLEMENTED | CHECK_READY | SCSI_ONLY, /* 0xDB */ + IMPLEMENTED | CHECK_READY | SCSI_ONLY, /* 0xDC */ + IMPLEMENTED | CHECK_READY | SCSI_ONLY, /* 0xDD */ + IMPLEMENTED | CHECK_READY | SCSI_ONLY, /* 0xDE */ + 0, /* 0xDF */ + IMPLEMENTED | CHECK_READY | SCSI_ONLY, /* 0xE0 */ + IMPLEMENTED | CHECK_READY | SCSI_ONLY, /* 0xE1 */ + 0, /* 0xE2 */ + IMPLEMENTED | CHECK_READY | SCSI_ONLY, /* 0xE3 */ + IMPLEMENTED | CHECK_READY | SCSI_ONLY, /* 0xE4 */ + IMPLEMENTED | CHECK_READY | SCSI_ONLY, /* 0xE5 */ + IMPLEMENTED | CHECK_READY | SCSI_ONLY, /* 0xE6 */ + IMPLEMENTED | CHECK_READY | SCSI_ONLY, /* 0xE7 */ + IMPLEMENTED | CHECK_READY | SCSI_ONLY, /* 0xE8 */ + IMPLEMENTED | CHECK_READY | SCSI_ONLY, /* 0xE9 */ + 0, /* 0xEA */ + IMPLEMENTED | CHECK_READY | SCSI_ONLY, /* 0xEB */ + 0, /* 0xEC */ + IMPLEMENTED | CHECK_READY | SCSI_ONLY, /* 0xED */ + IMPLEMENTED | CHECK_READY | SCSI_ONLY, /* 0xEE */ + 0, /* 0xEF */ + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 /* 0xF0-0xFF */ }; -static uint64_t scsi_cdrom_mode_sense_page_flags = (GPMODEP_R_W_ERROR_PAGE | - GPMODEP_DISCONNECT_PAGE | - GPMODEP_CDROM_PAGE | - GPMODEP_CDROM_AUDIO_PAGE | - (1ULL << 0x0fULL) | - GPMODEP_CAPABILITIES_PAGE | - GPMODEP_ALL_PAGES); +static uint64_t scsi_cdrom_mode_sense_page_flags = (GPMODEP_UNIT_ATN_PAGE | GPMODEP_R_W_ERROR_PAGE | GPMODEP_DISCONNECT_PAGE | GPMODEP_FORMAT_DEVICE_PAGE | GPMODEP_CDROM_PAGE | GPMODEP_CDROM_AUDIO_PAGE | (1ULL << 0x0fULL) | GPMODEP_CAPABILITIES_PAGE | GPMODEP_ALL_PAGES); +static uint64_t scsi_cdrom_mode_sense_page_flags_sony = (GPMODEP_R_W_ERROR_PAGE | GPMODEP_DISCONNECT_PAGE | GPMODEP_CDROM_PAGE_SONY | GPMODEP_CDROM_AUDIO_PAGE_SONY | (1ULL << 0x0fULL) | GPMODEP_CAPABILITIES_PAGE | GPMODEP_ALL_PAGES); +static uint64_t scsi_cdrom_drive_status_page_flags = ((1ULL << 0x01ULL) | (1ULL << 0x02ULL) | (1ULL << 0x0fULL) | GPMODEP_ALL_PAGES); -static const mode_sense_pages_t scsi_cdrom_mode_sense_pages_default = -{ { - { 0, 0 }, - { GPMODE_R_W_ERROR_PAGE, 6, 0, 5, 0, 0, 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { GPMODE_CDROM_PAGE, 6, 0, 1, 0, 60, 0, 75 }, - { 0x8E, 0xE, 4, 0, 0, 0, 0, 75, 1, 255, 2, 255, 0, 0, 0, 0 }, - { 0x0F, 0x14, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { GPMODE_CAPABILITIES_PAGE, 0x12, 0, 0, 1, 0, 0, 0, 2, 0xC2, 1, 0, 0, 0, 2, 0xC2, 0, 0, 0, 0 } -} }; +static const mode_sense_pages_t scsi_cdrom_drive_status_pages = { + {{ 0, 0 }, + { 0x01, 0, 2, 0x0f, 0xbf }, /*Drive Status Data Format*/ + { 0x02, 0, 1, 0 }, /*Audio Play Status Format*/ + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }} +}; -static const mode_sense_pages_t scsi_cdrom_mode_sense_pages_default_scsi = -{ { - { 0, 0 }, - { GPMODE_R_W_ERROR_PAGE, 6, 0, 5, 0, 0, 0, 0 }, - { GPMODE_DISCONNECT_PAGE, 0x0e, 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { GPMODE_CDROM_PAGE, 6, 0, 1, 0, 60, 0, 75 }, - { 0x8E, 0xE, 5, 4, 0,128, 0, 75, 1, 255, 2, 255, 0, 0, 0, 0 }, - { 0x0F, 0x14, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { GPMODE_CAPABILITIES_PAGE, 0x12, 0, 0, 1, 0, 0, 0, 2, 0xC2, 1, 0, 0, 0, 2, 0xC2, 0, 0, 0, 0 } -} }; +static const mode_sense_pages_t scsi_cdrom_mode_sense_pages_default = { + {{ 0, 0 }, + { GPMODE_R_W_ERROR_PAGE, 6, 0, 5, 0, 0, 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { GPMODE_CDROM_PAGE, 6, 0, 1, 0, 60, 0, 75 }, + { GPMODE_CDROM_AUDIO_PAGE | 0x80, 0xE, 4, 0, 0, 0, 0, 75, 1, 255, 2, 255, 0, 0, 0, 0 }, + { 0x0F, 0x14, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { GPMODE_CAPABILITIES_PAGE, 0x12, 0, 0, 1, 0, 0, 0, 2, 0xC2, 1, 0, 0, 0, 2, 0xC2, 0, 0, 0, 0 }} +}; -static const mode_sense_pages_t scsi_cdrom_mode_sense_pages_changeable = -{ { - { 0, 0 }, - { GPMODE_R_W_ERROR_PAGE, 6, 0xFF, 0xFF, 0, 0, 0, 0 }, - { GPMODE_DISCONNECT_PAGE, 0x0E, 0xFF, 0, 0, 0, 0, 0, 0, 0, 0xFF, 0xFF, 0, 0, 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { GPMODE_CDROM_PAGE, 6, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF }, - { 0x8E, 0xE, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF }, - { 0x0F, 0x14, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { GPMODE_CAPABILITIES_PAGE, 0x12, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 } -} }; +static const mode_sense_pages_t scsi_cdrom_mode_sense_pages_default_scsi = { + {{ GPMODE_UNIT_ATN_PAGE, 6, 0, 0, 0, 0, 0, 0 }, /*Guess-work*/ + { GPMODE_R_W_ERROR_PAGE, 6, 0, 5, 0, 0, 0, 0 }, + { GPMODE_DISCONNECT_PAGE, 0x0e, 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, + { GPMODE_FORMAT_DEVICE_PAGE, 0x16, 0, 1, 0, 1, 0, 1, 0, 1, 1, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { GPMODE_CDROM_PAGE, 6, 0, 1, 0, 60, 0, 75 }, + { GPMODE_CDROM_AUDIO_PAGE | 0x80, 0xE, 5, 4, 0, 128, 0, 75, 1, 255, 2, 255, 0, 0, 0, 0 }, + { 0x0F, 0x14, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { GPMODE_CAPABILITIES_PAGE, 0x12, 0, 0, 1, 0, 0, 0, 2, 0xC2, 1, 0, 0, 0, 2, 0xC2, 0, 0, 0, 0 }} +}; -static gesn_cdb_t *gesn_cdb; +static const mode_sense_pages_t scsi_cdrom_mode_sense_pages_default_sony_scsi = { + {{ 0, 0 }, + { GPMODE_R_W_ERROR_PAGE, 6, 0, 5, 0, 0, 0, 0 }, + { GPMODE_DISCONNECT_PAGE, 0x0e, 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { GPMODE_CDROM_PAGE_SONY, 2, 0, 5 }, + { GPMODE_CDROM_AUDIO_PAGE_SONY | 0x80, 0xE, 5, 0, 0, 0, 0, 0, 1, 255, 2, 255, 0, 0, 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { GPMODE_CDROM_PAGE, 6, 0, 1, 0, 60, 0, 75 }, + { GPMODE_CDROM_AUDIO_PAGE | 0x80, 0xE, 5, 4, 0, 128, 0, 75, 1, 255, 2, 255, 0, 0, 0, 0 }, + { 0x0F, 0x14, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { GPMODE_CAPABILITIES_PAGE, 0x12, 0, 0, 1, 0, 0, 0, 2, 0xC2, 1, 0, 0, 0, 2, 0xC2, 0, 0, 0, 0 }} +}; + +static const mode_sense_pages_t scsi_cdrom_mode_sense_pages_changeable = { + {{ GPMODE_UNIT_ATN_PAGE, 6, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF }, /*Guess-work*/ + { GPMODE_R_W_ERROR_PAGE, 6, 0xFF, 0xFF, 0, 0, 0, 0 }, + { GPMODE_DISCONNECT_PAGE, 0x0E, 0xFF, 0, 0, 0, 0, 0, 0, 0, 0xFF, 0xFF, 0, 0, 0, 0 }, + { GPMODE_FORMAT_DEVICE_PAGE, 0x16, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { GPMODE_CDROM_PAGE, 6, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF }, + { GPMODE_CDROM_AUDIO_PAGE | 0x80, 0xE, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF }, + { 0x0F, 0x14, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { GPMODE_CAPABILITIES_PAGE, 0x12, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }} +}; + +static const mode_sense_pages_t scsi_cdrom_mode_sense_pages_changeable_sony = { + {{ 0, 0 }, + { GPMODE_R_W_ERROR_PAGE, 6, 0xFF, 0xFF, 0, 0, 0, 0 }, + { GPMODE_DISCONNECT_PAGE, 0x0E, 0xFF, 0, 0, 0, 0, 0, 0, 0, 0xFF, 0xFF, 0, 0, 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { GPMODE_CDROM_PAGE_SONY, 2, 0xFF, 0xFF }, + { GPMODE_CDROM_AUDIO_PAGE_SONY | 0x80, 0xE, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { GPMODE_CDROM_PAGE, 6, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF }, + { GPMODE_CDROM_AUDIO_PAGE | 0x80, 0xE, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF }, + { 0x0F, 0x14, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { GPMODE_CAPABILITIES_PAGE, 0x12, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }} +}; + +static gesn_cdb_t *gesn_cdb; static gesn_event_header_t *gesn_event_header; +static void scsi_cdrom_command_complete(scsi_cdrom_t *dev); -static void scsi_cdrom_command_complete(scsi_cdrom_t *dev); - -static void scsi_cdrom_mode_sense_load(scsi_cdrom_t *dev); - -static void scsi_cdrom_init(scsi_cdrom_t *dev); +static void scsi_cdrom_mode_sense_load(scsi_cdrom_t *dev); +static void scsi_cdrom_drive_status_load(scsi_cdrom_t *dev); +static void scsi_cdrom_init(scsi_cdrom_t *dev); #ifdef ENABLE_SCSI_CDROM_LOG int scsi_cdrom_do_log = ENABLE_SCSI_CDROM_LOG; - static void scsi_cdrom_log(const char *format, ...) { va_list ap; if (scsi_cdrom_do_log) { - va_start(ap, format); - pclog_ex(format, ap); - va_end(ap); + va_start(ap, format); + pclog_ex(format, ap); + va_end(ap); } } #else -#define scsi_cdrom_log(format, ...) +# define scsi_cdrom_log(format, ...) #endif - static void scsi_cdrom_set_callback(scsi_cdrom_t *dev) { if (dev && dev->drv && (dev->drv->bus_type != CDROM_BUS_SCSI)) - ide_set_callback(ide_drives[dev->drv->ide_channel], dev->callback); + ide_set_callback(ide_drives[dev->drv->ide_channel], dev->callback); } - static void scsi_cdrom_init(scsi_cdrom_t *dev) { if (!dev) - return; + return; /* Do a reset (which will also rezero it). */ scsi_cdrom_reset((scsi_common_t *) dev); @@ -358,372 +515,580 @@ scsi_cdrom_init(scsi_cdrom_t *dev) dev->drv->bus_mode = 0; if (dev->drv->bus_type >= CDROM_BUS_ATAPI) - dev->drv->bus_mode |= 2; + dev->drv->bus_mode |= 2; if (dev->drv->bus_type < CDROM_BUS_SCSI) - dev->drv->bus_mode |= 1; - scsi_cdrom_log("CD-ROM %i: Bus type %i, bus mode %i\n", dev->id, dev->drv->bus_type, dev->drv->bus_mode); + dev->drv->bus_mode |= 1; + scsi_cdrom_log("CD-ROM %i: Bus type %i, bus mode %i\n", + dev->id, dev->drv->bus_type, dev->drv->bus_mode); dev->sense[0] = 0xf0; dev->sense[7] = 10; - dev->status = READY_STAT | DSC_STAT; - dev->pos = 0; - dev->packet_status = PHASE_NONE; + /* NEC only */ + if ((dev->drv->type == CDROM_TYPE_NEC_260_100) || (dev->drv->type == CDROM_TYPE_NEC_260_101)) + dev->tf->status = READY_STAT | DSC_STAT; + else + dev->tf->status = 0; + dev->tf->pos = 0; + dev->packet_status = PHASE_NONE; scsi_cdrom_sense_key = scsi_cdrom_asc = scsi_cdrom_ascq = dev->unit_attention = 0; - dev->drv->cur_speed = dev->drv->speed; + dev->drv->cur_speed = dev->drv->speed; scsi_cdrom_mode_sense_load(dev); + if (dev->drv->type == CDROM_TYPE_PIONEER_DRM604X_2403) + scsi_cdrom_drive_status_load(dev); } - /* Returns: 0 for none, 1 for PIO, 2 for DMA. */ static int scsi_cdrom_current_mode(scsi_cdrom_t *dev) { if (dev->drv->bus_type == CDROM_BUS_SCSI) - return 2; + return 2; else if (dev->drv->bus_type == CDROM_BUS_ATAPI) { - scsi_cdrom_log("CD-ROM %i: ATAPI drive, setting to %s\n", dev->id, - (dev->features & 1) ? "DMA" : "PIO", - dev->id); - return (dev->features & 1) ? 2 : 1; + scsi_cdrom_log("CD-ROM %i: ATAPI drive, setting to %s\n", dev->id, + (dev->tf->features & 1) ? "DMA" : "PIO", + dev->id); + return (dev->tf->features & 1) ? 2 : 1; } return 0; } - -/* Translates ATAPI phase (DRQ, I/O, C/D) to SCSI phase (MSG, C/D, I/O). */ -int -scsi_cdrom_atapi_phase_to_scsi(scsi_cdrom_t *dev) +static uint32_t +scsi_cdrom_get_channel(void *priv, int channel) { - if (dev->status & 8) { - switch (dev->phase & 3) { - case 0: - return 0; - case 1: - return 2; - case 2: - return 1; - case 3: - return 7; - } - } else { - if ((dev->phase & 3) == 3) - return 3; - else - return 4; + const scsi_cdrom_t *dev = (scsi_cdrom_t *) priv; + uint32_t ret; + + if (!dev) + return channel + 1; + + switch (dev->drv->type) { + case CDROM_TYPE_DEC_RRD45_0436: + case CDROM_TYPE_SONY_CDU541_10i: + case CDROM_TYPE_SONY_CDU561_18k: + case CDROM_TYPE_SONY_CDU76S_100: + case CDROM_TYPE_TEXEL_DMXX24_100: + ret = dev->ms_pages_saved_sony.pages[dev->sony_vendor ? GPMODE_CDROM_AUDIO_PAGE_SONY : GPMODE_CDROM_AUDIO_PAGE][channel ? 10 : 8]; + break; + default: + ret = dev->ms_pages_saved.pages[GPMODE_CDROM_AUDIO_PAGE][channel ? 10 : 8]; + break; } - return 0; + return ret; } - static uint32_t -scsi_cdrom_get_channel(void *p, int channel) +scsi_cdrom_get_volume(void *priv, int channel) { - scsi_cdrom_t *dev = (scsi_cdrom_t *) p; + const scsi_cdrom_t *dev = (scsi_cdrom_t *) priv; + uint32_t ret; + if (!dev) - return channel + 1; + return 255; - return dev->ms_pages_saved.pages[GPMODE_CDROM_AUDIO_PAGE][channel ? 10 : 8]; + switch (dev->drv->type) { + case CDROM_TYPE_DEC_RRD45_0436: + case CDROM_TYPE_SONY_CDU541_10i: + case CDROM_TYPE_SONY_CDU561_18k: + case CDROM_TYPE_SONY_CDU76S_100: + case CDROM_TYPE_TEXEL_DMXX24_100: + ret = dev->ms_pages_saved_sony.pages[dev->sony_vendor ? GPMODE_CDROM_AUDIO_PAGE_SONY : + GPMODE_CDROM_AUDIO_PAGE][channel ? 11 : 9]; + break; + default: + ret = dev->ms_pages_saved.pages[GPMODE_CDROM_AUDIO_PAGE][channel ? 11 : 9]; + break; + } + + return ret; } - -static uint32_t -scsi_cdrom_get_volume(void *p, int channel) -{ - scsi_cdrom_t *dev = (scsi_cdrom_t *) p; - if (!dev) - return 255; - - return dev->ms_pages_saved.pages[GPMODE_CDROM_AUDIO_PAGE][channel ? 11 : 9]; -} - - static void scsi_cdrom_mode_sense_load(scsi_cdrom_t *dev) { - FILE *f; - char file_name[512]; + FILE *fp; + char file_name[512]; - memset(&dev->ms_pages_saved, 0, sizeof(mode_sense_pages_t)); - if (dev->drv->bus_type == CDROM_BUS_SCSI) - memcpy(&dev->ms_pages_saved, &scsi_cdrom_mode_sense_pages_default_scsi, sizeof(mode_sense_pages_t)); - else - memcpy(&dev->ms_pages_saved, &scsi_cdrom_mode_sense_pages_default, sizeof(mode_sense_pages_t)); + switch (dev->drv->type) { + case CDROM_TYPE_DEC_RRD45_0436: + case CDROM_TYPE_SONY_CDU541_10i: + case CDROM_TYPE_SONY_CDU561_18k: + case CDROM_TYPE_SONY_CDU76S_100: + case CDROM_TYPE_TEXEL_DMXX24_100: + memset(&dev->ms_pages_saved_sony, 0, sizeof(mode_sense_pages_t)); + memcpy(&dev->ms_pages_saved_sony, &scsi_cdrom_mode_sense_pages_default_sony_scsi, + sizeof(mode_sense_pages_t)); - memset(file_name, 0, 512); - if (dev->drv->bus_type == CDROM_BUS_SCSI) - sprintf(file_name, "scsi_cdrom_%02i_mode_sense_bin", dev->id); - else - sprintf(file_name, "cdrom_%02i_mode_sense_bin", dev->id); - f = plat_fopen(nvr_path(file_name), "rb"); - if (f) { - if (fread(dev->ms_pages_saved.pages[GPMODE_CDROM_AUDIO_PAGE], 1, 0x10, f) != 0x10) - fatal("scsi_cdrom_mode_sense_load(): Error reading data\n"); - fclose(f); + memset(file_name, 0, 512); + sprintf(file_name, "scsi_cdrom_%02i_mode_sense_sony_bin", dev->id); + fp = plat_fopen(nvr_path(file_name), "rb"); + if (fp) { + if (fread(dev->ms_pages_saved_sony.pages[GPMODE_CDROM_AUDIO_PAGE_SONY], 1, + 0x10, fp) != 0x10) + fatal("scsi_cdrom_mode_sense_load(): Error reading data\n"); + fclose(fp); + } + break; + default: + memset(&dev->ms_pages_saved, 0, sizeof(mode_sense_pages_t)); + if (dev->drv->bus_type == CDROM_BUS_SCSI) + memcpy(&dev->ms_pages_saved, &scsi_cdrom_mode_sense_pages_default_scsi, + sizeof(mode_sense_pages_t)); + else + memcpy(&dev->ms_pages_saved, &scsi_cdrom_mode_sense_pages_default, + sizeof(mode_sense_pages_t)); + + memset(file_name, 0, 512); + if (dev->drv->bus_type == CDROM_BUS_SCSI) + sprintf(file_name, "scsi_cdrom_%02i_mode_sense_bin", dev->id); + else + sprintf(file_name, "cdrom_%02i_mode_sense_bin", dev->id); + fp = plat_fopen(nvr_path(file_name), "rb"); + if (fp) { + if (fread(dev->ms_pages_saved.pages[GPMODE_CDROM_AUDIO_PAGE], 1, 0x10, fp) != 0x10) + fatal("scsi_cdrom_mode_sense_load(): Error reading data\n"); + fclose(fp); + } + break; } } - static void scsi_cdrom_mode_sense_save(scsi_cdrom_t *dev) { - FILE *f; - char file_name[512]; + FILE *fp; + char file_name[512]; memset(file_name, 0, 512); - if (dev->drv->bus_type == CDROM_BUS_SCSI) - sprintf(file_name, "scsi_cdrom_%02i_mode_sense_bin", dev->id); - else - sprintf(file_name, "cdrom_%02i_mode_sense_bin", dev->id); - f = plat_fopen(nvr_path(file_name), "wb"); - if (f) { - fwrite(dev->ms_pages_saved.pages[GPMODE_CDROM_AUDIO_PAGE], 1, 0x10, f); - fclose(f); + + switch (dev->drv->type) { + case CDROM_TYPE_DEC_RRD45_0436: + case CDROM_TYPE_SONY_CDU541_10i: + case CDROM_TYPE_SONY_CDU561_18k: + case CDROM_TYPE_SONY_CDU76S_100: + case CDROM_TYPE_TEXEL_DMXX24_100: + sprintf(file_name, "scsi_cdrom_%02i_mode_sense_sony_bin", dev->id); + fp = plat_fopen(nvr_path(file_name), "wb"); + if (fp) { + fwrite(dev->ms_pages_saved_sony.pages[GPMODE_CDROM_AUDIO_PAGE_SONY], 1, 0x10, fp); + fclose(fp); + } + break; + default: + if (dev->drv->bus_type == CDROM_BUS_SCSI) + sprintf(file_name, "scsi_cdrom_%02i_mode_sense_bin", dev->id); + else + sprintf(file_name, "cdrom_%02i_mode_sense_bin", dev->id); + fp = plat_fopen(nvr_path(file_name), "wb"); + if (fp) { + fwrite(dev->ms_pages_saved.pages[GPMODE_CDROM_AUDIO_PAGE], 1, 0x10, fp); + fclose(fp); + } + break; } } - -/*SCSI Mode Sense 6/10*/ -static uint8_t -scsi_cdrom_mode_sense_read(scsi_cdrom_t *dev, uint8_t page_control, uint8_t page, uint8_t pos) +/*SCSI Drive Status (Pioneer only)*/ +static void +scsi_cdrom_drive_status_load(scsi_cdrom_t *dev) { - switch (page_control) { - case 0: - case 3: - return dev->ms_pages_saved.pages[page][pos]; - break; - case 1: - return scsi_cdrom_mode_sense_pages_changeable.pages[page][pos]; - break; - case 2: - if (dev->drv->bus_type == CDROM_BUS_SCSI) - return scsi_cdrom_mode_sense_pages_default_scsi.pages[page][pos]; - else - return scsi_cdrom_mode_sense_pages_default.pages[page][pos]; - break; - } - - return 0; + memset(&dev->ms_drive_status_pages_saved, 0, sizeof(mode_sense_pages_t)); + memcpy(&dev->ms_drive_status_pages_saved, &scsi_cdrom_drive_status_pages, sizeof(mode_sense_pages_t)); } +static uint8_t +scsi_cdrom_drive_status_read(scsi_cdrom_t *dev, UNUSED(uint8_t page_control), uint8_t page, uint8_t pos) +{ + return dev->ms_drive_status_pages_saved.pages[page][pos]; +} static uint32_t -scsi_cdrom_mode_sense(scsi_cdrom_t *dev, uint8_t *buf, uint32_t pos, uint8_t page, uint8_t block_descriptor_len) +scsi_cdrom_drive_status(scsi_cdrom_t *dev, uint8_t *buf, uint32_t pos, uint8_t page) { uint8_t page_control = (page >> 6) & 3; - int i = 0, j = 0; - - uint8_t msplen; + uint16_t msplen; page &= 0x3f; - if (block_descriptor_len) { - buf[pos++] = 1; /* Density code. */ - buf[pos++] = 0; /* Number of blocks (0 = all). */ - buf[pos++] = 0; - buf[pos++] = 0; - buf[pos++] = 0; /* Reserved. */ - buf[pos++] = 0; /* Block length (0x800 = 2048 bytes). */ - buf[pos++] = 8; - buf[pos++] = 0; - } - - for (i = 0; i < 0x40; i++) { - if ((page == GPMODE_ALL_PAGES) || (page == i)) { - if (scsi_cdrom_mode_sense_page_flags & (1LL << ((uint64_t) (page & 0x3f)))) { - buf[pos++] = scsi_cdrom_mode_sense_read(dev, page_control, i, 0); - msplen = scsi_cdrom_mode_sense_read(dev, page_control, i, 1); - buf[pos++] = msplen; - scsi_cdrom_log("CD-ROM %i: MODE SENSE: Page [%02X] length %i\n", dev->id, i, msplen); - for (j = 0; j < msplen; j++) { - if ((i == GPMODE_CAPABILITIES_PAGE) && (j >= 6) && (j <= 7)) { - if (j & 1) - buf[pos++] = ((dev->drv->speed * 176) & 0xff); - else - buf[pos++] = ((dev->drv->speed * 176) >> 8); - } else if ((i == GPMODE_CAPABILITIES_PAGE) && (j >= 12) && (j <= 13)) { - if (j & 1) - buf[pos++] = ((dev->drv->cur_speed * 176) & 0xff); - else - buf[pos++] = ((dev->drv->cur_speed * 176) >> 8); - } else - buf[pos++] = scsi_cdrom_mode_sense_read(dev, page_control, i, 2 + j); - } - } - } + for (uint8_t i = 0; i < 0x40; i++) { + if (page == i) { + if (scsi_cdrom_drive_status_page_flags & (1LL << ((uint64_t) (page & 0x3f)))) { + buf[pos++] = scsi_cdrom_drive_status_read(dev, page_control, i, 0); + msplen = (scsi_cdrom_drive_status_read(dev, page_control, i, 1) << 8); + msplen |= scsi_cdrom_drive_status_read(dev, page_control, i, 2); + buf[pos++] = (msplen >> 8) & 0xff; + buf[pos++] = msplen & 0xff; + scsi_cdrom_log("CD-ROM %i: DRIVE STATUS: Page [%02X] length %i\n", dev->id, i, msplen); + for (uint16_t j = 0; j < msplen; j++) { + if (i == 0x01) { + buf[pos++] = scsi_cdrom_drive_status_read(dev, page_control, i, 3 + j); + if (!(j & 1)) { /*MSB of Drive Status*/ + if (dev->drv->ops) /*Bit 11 of Drive Status, */ + buf[pos] &= ~0x08; /*Disc is present*/ + else + buf[pos] |= 0x08; /*Disc not present*/ + } + } else if ((i == 0x02) && (j == 0)) { + buf[pos++] = ((dev->drv->cd_status == CD_STATUS_PLAYING) ? 0x01 : 0x00); + } else + buf[pos++] = scsi_cdrom_drive_status_read(dev, page_control, i, 3 + j); + } + } + } } return pos; } +/*SCSI Mode Sense 6/10*/ +static uint8_t +scsi_cdrom_mode_sense_read(scsi_cdrom_t *dev, uint8_t page_control, uint8_t page, uint8_t pos) +{ + switch (dev->drv->type) { + case CDROM_TYPE_DEC_RRD45_0436: + case CDROM_TYPE_SONY_CDU541_10i: + case CDROM_TYPE_SONY_CDU561_18k: + case CDROM_TYPE_SONY_CDU76S_100: + case CDROM_TYPE_TEXEL_DMXX24_100: + switch (page_control) { + case 0: + case 3: + return dev->ms_pages_saved_sony.pages[page][pos]; + case 1: + return scsi_cdrom_mode_sense_pages_changeable_sony.pages[page][pos]; + case 2: + return scsi_cdrom_mode_sense_pages_default_sony_scsi.pages[page][pos]; + + default: + break; + } + break; + default: + switch (page_control) { + case 0: + case 3: + return dev->ms_pages_saved.pages[page][pos]; + case 1: + return scsi_cdrom_mode_sense_pages_changeable.pages[page][pos]; + case 2: + if (dev->drv->bus_type == CDROM_BUS_SCSI) + return scsi_cdrom_mode_sense_pages_default_scsi.pages[page][pos]; + else + return scsi_cdrom_mode_sense_pages_default.pages[page][pos]; + + default: + break; + } + break; + } + + return 0; +} + +static uint32_t +scsi_cdrom_mode_sense(scsi_cdrom_t *dev, uint8_t *buf, uint32_t pos, uint8_t page, uint8_t block_descriptor_len) +{ + uint8_t page_control = (page >> 6) & 3; + uint8_t msplen; + + page &= 0x3f; + + if (block_descriptor_len) { + buf[pos++] = 1; /* Density code. */ + buf[pos++] = 0; /* Number of blocks (0 = all). */ + buf[pos++] = 0; + buf[pos++] = 0; + buf[pos++] = 0; /* Reserved. */ + buf[pos++] = 0; /* Block length (0x800 = 2048 bytes). */ + buf[pos++] = 8; + buf[pos++] = 0; + } + + for (uint8_t i = 0; i < 0x40; i++) { + if ((page == GPMODE_ALL_PAGES) || (page == i)) { + if (scsi_cdrom_mode_sense_page_flags & (1LL << ((uint64_t) (page & 0x3f)))) { + buf[pos++] = scsi_cdrom_mode_sense_read(dev, page_control, i, 0); + msplen = scsi_cdrom_mode_sense_read(dev, page_control, i, 1); + buf[pos++] = msplen; + scsi_cdrom_log("CD-ROM %i: MODE SENSE: Page [%02X] length %i\n", dev->id, i, msplen); + for (uint8_t j = 0; j < msplen; j++) { + /* If we are returning changeable values, always return them from the page, + so they are all correctly. */ + if (page_control == 1) + buf[pos++] = scsi_cdrom_mode_sense_read(dev, page_control, i, 2 + j); + else { + if ((i == GPMODE_CAPABILITIES_PAGE) && (j == 4)) { + buf[pos] = scsi_cdrom_mode_sense_read(dev, page_control, i, 2 + j) & 0x1f; + /* The early CD-ROM drives we emulate (NEC CDR-260 for ATAPI and + early vendor SCSI CD-ROM models) are caddy drives, the later + ones are tray drives. */ + if (dev->drv->bus_type == CDROM_BUS_SCSI) + buf[pos++] |= ((dev->drv->type == CDROM_TYPE_86BOX_100) ? 0x20 : 0x00); + else + buf[pos++] |= ((dev->drv->type == CDROM_TYPE_NEC_260_100) || + ((dev->drv->type == CDROM_TYPE_NEC_260_101)) ? 0x00 : 0x20); + } else if ((i == GPMODE_CAPABILITIES_PAGE) && (j >= 6) && (j <= 7)) { + if (j & 1) + buf[pos++] = ((dev->drv->speed * 176) & 0xff); + else + buf[pos++] = ((dev->drv->speed * 176) >> 8); + } else if ((i == GPMODE_CAPABILITIES_PAGE) && (j >= 8) && (j <= 9) && + (dev->drv->type == CDROM_TYPE_PIONEER_DRM604X_2403)) { + if (j & 1) + buf[pos++] = ((dev->drv->speed * 176) & 0xff); + else + buf[pos++] = ((dev->drv->speed * 176) >> 8); + } else if ((i == GPMODE_CAPABILITIES_PAGE) && (j >= 12) && (j <= 13)) { + if (j & 1) + buf[pos++] = ((dev->drv->cur_speed * 176) & 0xff); + else + buf[pos++] = ((dev->drv->cur_speed * 176) >> 8); + } else + buf[pos++] = scsi_cdrom_mode_sense_read(dev, page_control, i, 2 + j); + } + } + } + } + } + + return pos; +} static void scsi_cdrom_update_request_length(scsi_cdrom_t *dev, int len, int block_len) { - int32_t bt, min_len = 0; + int32_t bt; + int32_t min_len = 0; + double dlen; - dev->max_transfer_len = dev->request_length; + dev->max_transfer_len = dev->tf->request_length; /* For media access commands, make sure the requested DRQ length matches the block length. */ switch (dev->current_cdb[0]) { - case 0x08: - case 0x28: - case 0xa8: - /* Round it to the nearest 2048 bytes. */ - dev->max_transfer_len = (dev->max_transfer_len >> 11) << 11; - /* FALLTHROUGH */ + case 0x08: + case 0x28: + case 0xa8: + case 0xb9: + case 0xbe: + /* Round it to the nearest (block length) bytes. */ + if ((dev->current_cdb[0] == 0xb9) || (dev->current_cdb[0] == 0xbe)) { + /* READ CD MSF and READ CD: Round the request length to the sector size - the device must ensure + that a media access comand does not DRQ in the middle of a sector. One of the drivers that + relies on the correctness of this behavior is MTMCDAI.SYS (the Mitsumi CD-ROM driver) for DOS + which uses the READ CD command to read data on some CD types. */ - case 0xb9: - case 0xbe: - /* Make sure total length is not bigger than sum of the lengths of - all the requested blocks. */ - bt = (dev->requested_blocks * block_len); - if (len > bt) - len = bt; + /* Round to sector length. */ + dlen = ((double) dev->max_transfer_len) / ((double) block_len); + dev->max_transfer_len = ((uint16_t) floor(dlen)) * block_len; + } else { + /* Round it to the nearest 2048 bytes. */ + dev->max_transfer_len = (dev->max_transfer_len >> 11) << 11; + } - min_len = block_len; + /* Make sure total length is not bigger than sum of the lengths of + all the requested blocks. */ + bt = (dev->requested_blocks * block_len); + if (len > bt) + len = bt; - if (len <= block_len) { - /* Total length is less or equal to block length. */ - if (dev->max_transfer_len < block_len) { - /* Transfer a minimum of (block size) bytes. */ - dev->max_transfer_len = block_len; - dev->packet_len = block_len; - break; - } - } - /*FALLTHROUGH*/ - default: - dev->packet_len = len; - break; + min_len = block_len; + + if (len <= block_len) { + /* Total length is less or equal to block length. */ + if (dev->max_transfer_len < block_len) { + /* Transfer a minimum of (block size) bytes. */ + dev->max_transfer_len = block_len; + dev->packet_len = block_len; + break; + } + } + fallthrough; + + default: + dev->packet_len = len; + break; } /* If the DRQ length is odd, and the total remaining length is bigger, make sure it's even. */ if ((dev->max_transfer_len & 1) && (dev->max_transfer_len < len)) - dev->max_transfer_len &= 0xfffe; + dev->max_transfer_len &= 0xfffe; /* If the DRQ length is smaller or equal in size to the total remaining length, set it to that. */ if (!dev->max_transfer_len) - dev->max_transfer_len = 65534; + dev->max_transfer_len = 65534; if ((len <= dev->max_transfer_len) && (len >= min_len)) - dev->request_length = dev->max_transfer_len = len; + dev->tf->request_length = dev->max_transfer_len = len; else if (len > dev->max_transfer_len) - dev->request_length = dev->max_transfer_len; + dev->tf->request_length = dev->max_transfer_len; return; } - static double scsi_cdrom_bus_speed(scsi_cdrom_t *dev) { double ret = -1.0; if (dev && dev->drv && (dev->drv->bus_type == CDROM_BUS_SCSI)) { - dev->callback = -1.0; /* Speed depends on SCSI controller */ - return 0.0; + dev->callback = -1.0; /* Speed depends on SCSI controller */ + return 0.0; } else { - if (dev && dev->drv) - ret = ide_atapi_get_period(dev->drv->ide_channel); - if (ret == -1.0) { - if (dev) - dev->callback = -1.0; - return 0.0; - } else - return ret * 1000000.0; + if (dev && dev->drv) + ret = ide_atapi_get_period(dev->drv->ide_channel); + if (ret == -1.0) { + if (dev) + dev->callback = -1.0; + return 0.0; + } else + return ret * 1000000.0; } } - static void scsi_cdrom_command_common(scsi_cdrom_t *dev) { - double bytes_per_second, period; + double bytes_per_second = 0.0; + double period; - dev->status = BUSY_STAT; - dev->phase = 1; - dev->pos = 0; - dev->callback = 0; + /* MAP: BUSY_STAT, no DRQ, phase 1. */ + dev->tf->status = BUSY_STAT; + dev->tf->phase = 1; + dev->tf->pos = 0; + dev->callback = 0; scsi_cdrom_log("CD-ROM %i: Current speed: %ix\n", dev->id, dev->drv->cur_speed); if (dev->packet_status == PHASE_COMPLETE) - dev->callback = 0; + dev->callback = 0; else { - switch(dev->current_cdb[0]) { - case GPCMD_REZERO_UNIT: - case 0x0b: - case 0x2b: - /* Seek time is in us. */ - period = cdrom_seek_time(dev->drv); - scsi_cdrom_log("CD-ROM %i: Seek period: %" PRIu64 " us\n", - dev->id, (uint64_t) period); - dev->callback += period; - scsi_cdrom_set_callback(dev); - return; - case 0x08: - case 0x28: - case 0xa8: - /* Seek time is in us. */ - period = cdrom_seek_time(dev->drv); - scsi_cdrom_log("CD-ROM %i: Seek period: %" PRIu64 " us\n", - dev->id, (uint64_t) period); - dev->callback += period; - /*FALLTHROUGH*/ - case 0x25: - case 0x42: - case 0x43: - case 0x44: - case 0x51: - case 0x52: - case 0xad: - case 0xb8: - case 0xb9: - case 0xbe: - case 0xc6: - case 0xc7: - if (dev->current_cdb[0] == 0x42) - dev->callback += 40.0; - /* Account for seek time. */ - bytes_per_second = 176.0 * 1024.0; - bytes_per_second *= (double) dev->drv->cur_speed; - break; - default: - bytes_per_second = scsi_cdrom_bus_speed(dev); - if (bytes_per_second == 0.0) { - dev->callback = -1; /* Speed depends on SCSI controller */ - return; - } - break; - } + switch (dev->current_cdb[0]) { + case GPCMD_REZERO_UNIT: + case 0x0b: + case 0x2b: + /* Seek time is in us. */ + period = cdrom_seek_time(dev->drv); + scsi_cdrom_log("CD-ROM %i: Seek period: %" PRIu64 " us\n", + dev->id, (uint64_t) period); + dev->callback += period; + scsi_cdrom_set_callback(dev); + return; + case 0x08: + case 0x28: + case 0xa8: + /* Seek time is in us. */ + period = cdrom_seek_time(dev->drv); + scsi_cdrom_log("CD-ROM %i: Seek period: %" PRIu64 " us\n", + dev->id, (uint64_t) period); + dev->callback += period; + fallthrough; + case 0x25: + case 0x42 ... 0x44: + case 0x51 ... 0x52: + case 0xad: + case 0xb8 ... 0xb9: + case 0xbe: + if (dev->current_cdb[0] == 0x42) + dev->callback += 40.0; + /* Account for seek time. */ + bytes_per_second = 176.0 * 1024.0; + bytes_per_second *= (double) dev->drv->cur_speed; + break; + case 0xc6 ... 0xc7: + switch (dev->drv->type) { + case CDROM_TYPE_TOSHIBA_XM_3433: + case CDROM_TYPE_TOSHIBA_XM3201B_3232: + case CDROM_TYPE_TOSHIBA_XM3301TA_0272: + case CDROM_TYPE_TOSHIBA_XM5701TA_3136: + case CDROM_TYPE_TOSHIBA_SDM1401_1008: + bytes_per_second = 176.0 * 1024.0; + bytes_per_second *= (double) dev->drv->cur_speed; + break; + } + case 0xc0: + switch (dev->drv->type) { + case CDROM_TYPE_DEC_RRD45_0436: + case CDROM_TYPE_SONY_CDU541_10i: + case CDROM_TYPE_SONY_CDU561_18k: + case CDROM_TYPE_SONY_CDU76S_100: + case CDROM_TYPE_TEXEL_DMXX24_100: + bytes_per_second = 176.0 * 1024.0; + bytes_per_second *= (double) dev->drv->cur_speed; + break; + } + case 0xc1: + switch (dev->drv->type) { + case CDROM_TYPE_DEC_RRD45_0436: + case CDROM_TYPE_SONY_CDU541_10i: + case CDROM_TYPE_SONY_CDU561_18k: + case CDROM_TYPE_SONY_CDU76S_100: + case CDROM_TYPE_PIONEER_DRM604X_2403: + case CDROM_TYPE_TEXEL_DMXX24_100: + bytes_per_second = 176.0 * 1024.0; + bytes_per_second *= (double) dev->drv->cur_speed; + break; + } + case 0xc2 ... 0xc3: + switch (dev->drv->type) { + case CDROM_TYPE_DEC_RRD45_0436: + case CDROM_TYPE_SONY_CDU541_10i: + case CDROM_TYPE_SONY_CDU561_18k: + case CDROM_TYPE_SONY_CDU76S_100: + case CDROM_TYPE_PIONEER_DRM604X_2403: + case CDROM_TYPE_TEXEL_DMXX24_100: + if (dev->current_cdb[0] == 0xc2) + dev->callback += 40.0; + bytes_per_second = 176.0 * 1024.0; + bytes_per_second *= (double) dev->drv->cur_speed; + break; + } + case 0xdd ... 0xde: + switch (dev->drv->type) { + case CDROM_TYPE_NEC_25_10a: + case CDROM_TYPE_NEC_38_103: + case CDROM_TYPE_NEC_75_103: + case CDROM_TYPE_NEC_77_106: + case CDROM_TYPE_NEC_211_100: + case CDROM_TYPE_NEC_464_105: + bytes_per_second = 176.0 * 1024.0; + bytes_per_second *= (double) dev->drv->cur_speed; + break; + } + fallthrough; + default: + bytes_per_second = scsi_cdrom_bus_speed(dev); + if (bytes_per_second == 0.0) { + dev->callback = -1; /* Speed depends on SCSI controller */ + return; + } + break; + } - period = 1000000.0 / bytes_per_second; - scsi_cdrom_log("CD-ROM %i: Byte transfer period: %" PRIu64 " us\n", dev->id, (uint64_t) period); - period = period * (double) (dev->packet_len); - scsi_cdrom_log("CD-ROM %i: Sector transfer period: %" PRIu64 " us\n", dev->id, (uint64_t) period); - dev->callback += period; + period = 1000000.0 / bytes_per_second; + scsi_cdrom_log("CD-ROM %i: Byte transfer period: %" PRIu64 " us\n", dev->id, (uint64_t) period); + period = period * (double) (dev->packet_len); + scsi_cdrom_log("CD-ROM %i: Sector transfer period: %" PRIu64 " us\n", dev->id, (uint64_t) period); + dev->callback += period; } scsi_cdrom_set_callback(dev); } - static void scsi_cdrom_command_complete(scsi_cdrom_t *dev) { ui_sb_update_icon(SB_CDROM | dev->id, 0); dev->packet_status = PHASE_COMPLETE; scsi_cdrom_command_common(dev); + dev->tf->phase = 3; } - static void scsi_cdrom_command_read(scsi_cdrom_t *dev) { dev->packet_status = PHASE_DATA_IN; scsi_cdrom_command_common(dev); + dev->tf->phase = !(dev->packet_status & 0x01) << 1; } - static void scsi_cdrom_command_read_dma(scsi_cdrom_t *dev) { @@ -731,140 +1096,135 @@ scsi_cdrom_command_read_dma(scsi_cdrom_t *dev) scsi_cdrom_command_common(dev); } - static void scsi_cdrom_command_write(scsi_cdrom_t *dev) { dev->packet_status = PHASE_DATA_OUT; scsi_cdrom_command_common(dev); + dev->tf->phase = !(dev->packet_status & 0x01) << 1; } - -static void scsi_cdrom_command_write_dma(scsi_cdrom_t *dev) +static void +scsi_cdrom_command_write_dma(scsi_cdrom_t *dev) { dev->packet_status = PHASE_DATA_OUT_DMA; scsi_cdrom_command_common(dev); } - /* id = Current CD-ROM device ID; len = Total transfer length; block_len = Length of a single block (it matters because media access commands on ATAPI); alloc_len = Allocated transfer length; direction = Transfer direction (0 = read from host, 1 = write to host). */ -static void scsi_cdrom_data_command_finish(scsi_cdrom_t *dev, int len, int block_len, int alloc_len, int direction) +static void +scsi_cdrom_data_command_finish(scsi_cdrom_t *dev, int len, int block_len, int alloc_len, int direction) { scsi_cdrom_log("CD-ROM %i: Finishing command (%02X): %i, %i, %i, %i, %i\n", - dev->id, dev->current_cdb[0], len, block_len, alloc_len, direction, dev->request_length); - dev->pos = 0; + dev->id, dev->current_cdb[0], len, block_len, alloc_len, direction, + dev->tf->request_length); + dev->tf->pos = 0; if (alloc_len >= 0) { - if (alloc_len < len) - len = alloc_len; + if (alloc_len < len) + len = alloc_len; } if ((len == 0) || (scsi_cdrom_current_mode(dev) == 0)) { - if (dev->drv->bus_type != CDROM_BUS_SCSI) - dev->packet_len = 0; + if (dev->drv->bus_type != CDROM_BUS_SCSI) + dev->packet_len = 0; - scsi_cdrom_command_complete(dev); + scsi_cdrom_command_complete(dev); } else { - if (scsi_cdrom_current_mode(dev) == 2) { - if (dev->drv->bus_type != CDROM_BUS_SCSI) - dev->packet_len = alloc_len; + if (scsi_cdrom_current_mode(dev) == 2) { + if (dev->drv->bus_type != CDROM_BUS_SCSI) + dev->packet_len = alloc_len; - if (direction == 0) - scsi_cdrom_command_read_dma(dev); - else - scsi_cdrom_command_write_dma(dev); - } else { - scsi_cdrom_update_request_length(dev, len, block_len); - if (direction == 0) - scsi_cdrom_command_read(dev); - else - scsi_cdrom_command_write(dev); - } + if (direction == 0) + scsi_cdrom_command_read_dma(dev); + else + scsi_cdrom_command_write_dma(dev); + } else { + scsi_cdrom_update_request_length(dev, len, block_len); + if (direction == 0) + scsi_cdrom_command_read(dev); + else + scsi_cdrom_command_write(dev); + } } scsi_cdrom_log("CD-ROM %i: Status: %i, cylinder %i, packet length: %i, position: %i, phase: %i\n", - dev->id, dev->packet_status, dev->request_length, dev->packet_len, dev->pos, dev->phase); + dev->id, dev->packet_status, dev->tf->request_length, dev->packet_len, dev->tf->pos, + dev->tf->phase); } - static void -scsi_cdrom_sense_clear(scsi_cdrom_t *dev, int command) +scsi_cdrom_sense_clear(scsi_cdrom_t *dev, UNUSED(int command)) { scsi_cdrom_sense_key = scsi_cdrom_asc = scsi_cdrom_ascq = 0; } - static void scsi_cdrom_set_phase(scsi_cdrom_t *dev, uint8_t phase) { uint8_t scsi_bus = (dev->drv->scsi_device_id >> 4) & 0x0f; - uint8_t scsi_id = dev->drv->scsi_device_id & 0x0f; + uint8_t scsi_id = dev->drv->scsi_device_id & 0x0f; if (dev->drv->bus_type != CDROM_BUS_SCSI) - return; + return; scsi_devices[scsi_bus][scsi_id].phase = phase; } - static void scsi_cdrom_cmd_error(scsi_cdrom_t *dev) { scsi_cdrom_set_phase(dev, SCSI_PHASE_STATUS); - dev->error = ((scsi_cdrom_sense_key & 0xf) << 4) | ABRT_ERR; + dev->tf->error = ((scsi_cdrom_sense_key & 0xf) << 4) | ABRT_ERR; if (dev->unit_attention) - dev->error |= MCR_ERR; - dev->status = READY_STAT | ERR_STAT; - dev->phase = 3; - dev->pos = 0; - dev->packet_status = PHASE_ERROR; - dev->callback = 50.0 * CDROM_TIME; + dev->tf->error |= MCR_ERR; + dev->tf->status = READY_STAT | ERR_STAT; + dev->tf->phase = 3; + dev->tf->pos = 0; + dev->packet_status = PHASE_ERROR; + dev->callback = 50.0 * CDROM_TIME; scsi_cdrom_set_callback(dev); ui_sb_update_icon(SB_CDROM | dev->id, 0); scsi_cdrom_log("CD-ROM %i: ERROR: %02X/%02X/%02X\n", dev->id, scsi_cdrom_sense_key, scsi_cdrom_asc, scsi_cdrom_ascq); } - static void scsi_cdrom_unit_attention(scsi_cdrom_t *dev) { scsi_cdrom_set_phase(dev, SCSI_PHASE_STATUS); - dev->error = (SENSE_UNIT_ATTENTION << 4) | ABRT_ERR; + dev->tf->error = (SENSE_UNIT_ATTENTION << 4) | ABRT_ERR; if (dev->unit_attention) - dev->error |= MCR_ERR; - dev->status = READY_STAT | ERR_STAT; - dev->phase = 3; - dev->pos = 0; + dev->tf->error |= MCR_ERR; + dev->tf->status = READY_STAT | ERR_STAT; + dev->tf->phase = 3; + dev->tf->pos = 0; dev->packet_status = PHASE_ERROR; - dev->callback = 50.0 * CDROM_TIME; + dev->callback = 50.0 * CDROM_TIME; scsi_cdrom_set_callback(dev); ui_sb_update_icon(SB_CDROM | dev->id, 0); scsi_cdrom_log("CD-ROM %i: UNIT ATTENTION\n", dev->id); } - static void scsi_cdrom_buf_alloc(scsi_cdrom_t *dev, uint32_t len) { - scsi_cdrom_log("CD-ROM %i: Allocated buffer length: %i\n", dev->id, len); if (!dev->buffer) - dev->buffer = (uint8_t *) malloc(len); + dev->buffer = (uint8_t *) malloc(len); + scsi_cdrom_log("CD-ROM %i: Allocated buffer length: %i, buffer = %p\n", dev->id, len, dev->buffer); } - static void scsi_cdrom_buf_free(scsi_cdrom_t *dev) { if (dev->buffer) { - scsi_cdrom_log("CD-ROM %i: Freeing buffer...\n", dev->id); - free(dev->buffer); - dev->buffer = NULL; + scsi_cdrom_log("CD-ROM %i: Freeing buffer...\n", dev->id); + free(dev->buffer); + dev->buffer = NULL; } } - static void scsi_cdrom_bus_master_error(scsi_common_t *sc) { @@ -875,189 +1235,181 @@ scsi_cdrom_bus_master_error(scsi_common_t *sc) scsi_cdrom_cmd_error(dev); } - static void scsi_cdrom_not_ready(scsi_cdrom_t *dev) { scsi_cdrom_sense_key = SENSE_NOT_READY; - scsi_cdrom_asc = ASC_MEDIUM_NOT_PRESENT; - scsi_cdrom_ascq = 0; + scsi_cdrom_asc = ASC_MEDIUM_NOT_PRESENT; + scsi_cdrom_ascq = 0; scsi_cdrom_cmd_error(dev); } - static void scsi_cdrom_invalid_lun(scsi_cdrom_t *dev) { scsi_cdrom_sense_key = SENSE_ILLEGAL_REQUEST; - scsi_cdrom_asc = ASC_INV_LUN; - scsi_cdrom_ascq = 0; + scsi_cdrom_asc = ASC_INV_LUN; + scsi_cdrom_ascq = 0; scsi_cdrom_cmd_error(dev); } - static void scsi_cdrom_illegal_opcode(scsi_cdrom_t *dev) { scsi_cdrom_sense_key = SENSE_ILLEGAL_REQUEST; - scsi_cdrom_asc = ASC_ILLEGAL_OPCODE; - scsi_cdrom_ascq = 0; + scsi_cdrom_asc = ASC_ILLEGAL_OPCODE; + scsi_cdrom_ascq = 0; scsi_cdrom_cmd_error(dev); } - static void scsi_cdrom_lba_out_of_range(scsi_cdrom_t *dev) { scsi_cdrom_sense_key = SENSE_ILLEGAL_REQUEST; - scsi_cdrom_asc = ASC_LBA_OUT_OF_RANGE; - scsi_cdrom_ascq = 0; + scsi_cdrom_asc = ASC_LBA_OUT_OF_RANGE; + scsi_cdrom_ascq = 0; scsi_cdrom_cmd_error(dev); } - static void scsi_cdrom_invalid_field(scsi_cdrom_t *dev) { scsi_cdrom_sense_key = SENSE_ILLEGAL_REQUEST; - scsi_cdrom_asc = ASC_INV_FIELD_IN_CMD_PACKET; - scsi_cdrom_ascq = 0; + scsi_cdrom_asc = ASC_INV_FIELD_IN_CMD_PACKET; + scsi_cdrom_ascq = 0; scsi_cdrom_cmd_error(dev); - dev->status = 0x53; + dev->tf->status = 0x53; } - static void scsi_cdrom_invalid_field_pl(scsi_cdrom_t *dev) { scsi_cdrom_sense_key = SENSE_ILLEGAL_REQUEST; - scsi_cdrom_asc = ASC_INV_FIELD_IN_PARAMETER_LIST; - scsi_cdrom_ascq = 0; + scsi_cdrom_asc = ASC_INV_FIELD_IN_PARAMETER_LIST; + scsi_cdrom_ascq = 0; scsi_cdrom_cmd_error(dev); - dev->status = 0x53; + dev->tf->status = 0x53; } - static void scsi_cdrom_illegal_mode(scsi_cdrom_t *dev) { scsi_cdrom_sense_key = SENSE_ILLEGAL_REQUEST; - scsi_cdrom_asc = ASC_ILLEGAL_MODE_FOR_THIS_TRACK; - scsi_cdrom_ascq = 0; + scsi_cdrom_asc = ASC_ILLEGAL_MODE_FOR_THIS_TRACK; + scsi_cdrom_ascq = 0; scsi_cdrom_cmd_error(dev); } - static void scsi_cdrom_incompatible_format(scsi_cdrom_t *dev) { scsi_cdrom_sense_key = SENSE_ILLEGAL_REQUEST; - scsi_cdrom_asc = ASC_INCOMPATIBLE_FORMAT; - scsi_cdrom_ascq = 2; + scsi_cdrom_asc = ASC_INCOMPATIBLE_FORMAT; + scsi_cdrom_ascq = 2; scsi_cdrom_cmd_error(dev); } - static void scsi_cdrom_data_phase_error(scsi_cdrom_t *dev) { scsi_cdrom_sense_key = SENSE_ILLEGAL_REQUEST; - scsi_cdrom_asc = ASC_DATA_PHASE_ERROR; - scsi_cdrom_ascq = 0; + scsi_cdrom_asc = ASC_DATA_PHASE_ERROR; + scsi_cdrom_ascq = 0; scsi_cdrom_cmd_error(dev); } - static int -scsi_cdrom_read_data(scsi_cdrom_t *dev, int msf, int type, int flags, int32_t *len) +scsi_cdrom_read_data(scsi_cdrom_t *dev, int msf, int type, int flags, int32_t *len, int vendor_type) { - int ret = 0, data_pos = 0; - int i = 0, temp_len = 0; - uint32_t cdsize = 0; + int ret = 0; + int data_pos = 0; + int temp_len = 0; + uint32_t cdsize = 0; if (dev->drv->cd_status == CD_STATUS_EMPTY) { - scsi_cdrom_not_ready(dev); - return 0; + scsi_cdrom_not_ready(dev); + return 0; } cdsize = dev->drv->cdrom_capacity; if (dev->sector_pos >= cdsize) { - scsi_cdrom_log("CD-ROM %i: Trying to read from beyond the end of disc (%i >= %i)\n", dev->id, - dev->sector_pos, cdsize); - scsi_cdrom_lba_out_of_range(dev); - return -1; + scsi_cdrom_log("CD-ROM %i: Trying to read from beyond the end of disc (%i >= %i)\n", dev->id, + dev->sector_pos, cdsize); + scsi_cdrom_lba_out_of_range(dev); + return -1; } /* FIXME: Temporarily disabled this because the Triones ATAPI DMA driver seems to - always request a 4-sector read but sets the DMA bus master to transfer less - data than that. */ + always request a 4-sector read but sets the DMA bus master to transfer less + data than that. */ #if 0 if ((dev->sector_pos + dev->sector_len - 1) >= cdsize) { - scsi_cdrom_log("CD-ROM %i: Trying to read to beyond the end of disc (%i >= %i)\n", dev->id, - (dev->sector_pos + dev->sector_len - 1), cdsize); - scsi_cdrom_lba_out_of_range(dev); - return -1; + scsi_cdrom_log("CD-ROM %i: Trying to read to beyond the end of disc (%i >= %i)\n", dev->id, + (dev->sector_pos + dev->sector_len - 1), cdsize); + scsi_cdrom_lba_out_of_range(dev); + return -1; } #endif dev->old_len = 0; - *len = 0; + *len = 0; - for (i = 0; i < dev->requested_blocks; i++) { - ret = cdrom_readsector_raw(dev->drv, dev->buffer + data_pos, - dev->sector_pos + i, msf, type, flags, &temp_len); + for (int i = 0; i < dev->requested_blocks; i++) { + ret = cdrom_readsector_raw(dev->drv, dev->buffer + data_pos, + dev->sector_pos + i, msf, type, flags, &temp_len, vendor_type); - data_pos += temp_len; - dev->old_len += temp_len; + data_pos += temp_len; + dev->old_len += temp_len; - *len += temp_len; + *len += temp_len; - if (!ret) { - scsi_cdrom_illegal_mode(dev); - return 0; - } + if (!ret) { + scsi_cdrom_illegal_mode(dev); + return 0; + } } return 1; } - static int -scsi_cdrom_read_blocks(scsi_cdrom_t *dev, int32_t *len, int first_batch) +scsi_cdrom_read_blocks(scsi_cdrom_t *dev, int32_t *len, int first_batch, int vendor_type) { - int ret = 0, msf = 0; - int type = 0, flags = 0; + int ret = 0; + int msf = 0; + int type = 0; + int flags = 0; if (dev->current_cdb[0] == GPCMD_READ_CD_MSF) - msf = 1; + msf = 1; if ((dev->current_cdb[0] == GPCMD_READ_CD_MSF) || (dev->current_cdb[0] == GPCMD_READ_CD)) { - type = (dev->current_cdb[1] >> 2) & 7; - flags = dev->current_cdb[9] | (((uint32_t) dev->current_cdb[10]) << 8); + type = (dev->current_cdb[1] >> 2) & 7; + flags = dev->current_cdb[9] | (((uint32_t) dev->current_cdb[10]) << 8); } else { - type = 8; - flags = 0x10; + type = 8; + flags = 0x10; } if (!dev->sector_len) { - scsi_cdrom_command_complete(dev); - return -1; + scsi_cdrom_command_complete(dev); + return -1; } scsi_cdrom_log("Reading %i blocks starting from %i...\n", dev->requested_blocks, dev->sector_pos); - ret = scsi_cdrom_read_data(dev, msf, type, flags, len); + ret = scsi_cdrom_read_data(dev, msf, type, flags, len, vendor_type); scsi_cdrom_log("Read %i bytes of blocks...\n", *len); if (ret == -1) - return 0; - else if (!ret || ((dev->old_len != *len) && !first_batch)) { - if ((dev->old_len != *len) && !first_batch) - scsi_cdrom_illegal_mode(dev); + return 0; + else if (!ret || (!first_batch && (dev->old_len != *len))) { + if (!first_batch && (dev->old_len != *len)) + scsi_cdrom_illegal_mode(dev); - return 0; + return 0; } dev->sector_pos += dev->requested_blocks; @@ -1066,131 +1418,129 @@ scsi_cdrom_read_blocks(scsi_cdrom_t *dev, int32_t *len, int first_batch) return 1; } - /*SCSI Read DVD Structure*/ static int scsi_cdrom_read_dvd_structure(scsi_cdrom_t *dev, int format, const uint8_t *packet, uint8_t *buf) { - int layer = packet[6]; + int layer = packet[6]; uint64_t total_sectors = 0; switch (format) { - case 0x00: /* Physical format information */ - if (dev->drv->cd_status == CD_STATUS_EMPTY) { - scsi_cdrom_not_ready(dev); - return 0; - } + case 0x00: /* Physical format information */ + if (dev->drv->cd_status == CD_STATUS_EMPTY) { + scsi_cdrom_not_ready(dev); + return 0; + } - total_sectors = (uint64_t) dev->drv->cdrom_capacity; + total_sectors = (uint64_t) dev->drv->cdrom_capacity; - if (layer != 0) { - scsi_cdrom_invalid_field(dev); - return 0; - } + if (layer != 0) { + scsi_cdrom_invalid_field(dev); + return 0; + } - total_sectors >>= 2; - if (total_sectors == 0) { - /* return -ASC_MEDIUM_NOT_PRESENT; */ - scsi_cdrom_not_ready(dev); - return 0; - } + total_sectors >>= 2; + if (total_sectors == 0) { + /* return -ASC_MEDIUM_NOT_PRESENT; */ + scsi_cdrom_not_ready(dev); + return 0; + } - buf[4] = 18; /* Length of Layer Information */ - buf[5] = 0; + buf[4] = 18; /* Length of Layer Information */ + buf[5] = 0; - buf[6] = 1; /* DVD-ROM, part version 1 */ - buf[7] = 0xf; /* 120mm disc, minimum rate unspecified */ - buf[8] = 1; /* one layer, read-only (per MMC-2 spec) */ - buf[9] = 0; /* default densities */ + buf[6] = 1; /* DVD-ROM, part version 1 */ + buf[7] = 0xf; /* 120mm disc, minimum rate unspecified */ + buf[8] = 1; /* one layer, read-only (per MMC-2 spec) */ + buf[9] = 0; /* default densities */ - /* FIXME: 0x30000 per spec? */ - buf[10] = 0x00; - buf[11] = 0x03; - buf[12] = buf[13] = 0; /* start sector */ + /* FIXME: 0x30000 per spec? */ + buf[10] = 0x00; + buf[11] = 0x03; + buf[12] = buf[13] = 0; /* start sector */ - buf[14] = 0x00; - buf[15] = (total_sectors >> 16) & 0xff; /* end sector */ - buf[16] = (total_sectors >> 8) & 0xff; - buf[17] = total_sectors & 0xff; + buf[14] = 0x00; + buf[15] = (total_sectors >> 16) & 0xff; /* end sector */ + buf[16] = (total_sectors >> 8) & 0xff; + buf[17] = total_sectors & 0xff; - buf[18] = 0x00; - buf[19] = (total_sectors >> 16) & 0xff; /* l0 end sector */ - buf[20] = (total_sectors >> 8) & 0xff; - buf[21] = total_sectors & 0xff; + buf[18] = 0x00; + buf[19] = (total_sectors >> 16) & 0xff; /* l0 end sector */ + buf[20] = (total_sectors >> 8) & 0xff; + buf[21] = total_sectors & 0xff; - /* 20 bytes of data + 4 byte header */ - return (20 + 4); + /* 20 bytes of data + 4 byte header */ + return (20 + 4); - case 0x01: /* DVD copyright information */ - buf[4] = 0; /* no copyright data */ - buf[5] = 0; /* no region restrictions */ + case 0x01: /* DVD copyright information */ + buf[4] = 0; /* no copyright data */ + buf[5] = 0; /* no region restrictions */ - /* Size of buffer, not including 2 byte size field */ - buf[0] = ((4 + 2) >> 8) & 0xff; - buf[1] = (4 + 2) & 0xff; + /* Size of buffer, not including 2 byte size field */ + buf[0] = ((4 + 2) >> 8) & 0xff; + buf[1] = (4 + 2) & 0xff; - /* 4 byte header + 4 byte data */ - return (4 + 4); + /* 4 byte header + 4 byte data */ + return (4 + 4); - case 0x03: /* BCA information - invalid field for no BCA info */ - scsi_cdrom_invalid_field(dev); - return 0; + case 0x03: /* BCA information - invalid field for no BCA info */ + scsi_cdrom_invalid_field(dev); + return 0; - case 0x04: /* DVD disc manufacturing information */ - /* Size of buffer, not including 2 byte size field */ - buf[0] = ((2048 + 2) >> 8) & 0xff; - buf[1] = (2048 + 2) & 0xff; + case 0x04: /* DVD disc manufacturing information */ + /* Size of buffer, not including 2 byte size field */ + buf[0] = ((2048 + 2) >> 8) & 0xff; + buf[1] = (2048 + 2) & 0xff; - /* 2k data + 4 byte header */ - return (2048 + 4); + /* 2k data + 4 byte header */ + return (2048 + 4); - case 0xff: - /* - * This lists all the command capabilities above. Add new ones - * in order and update the length and buffer return values. - */ + case 0xff: + /* + * This lists all the command capabilities above. Add new ones + * in order and update the length and buffer return values. + */ - buf[4] = 0x00; /* Physical format */ - buf[5] = 0x40; /* Not writable, is readable */ - buf[6] = ((20 + 4) >> 8) & 0xff; - buf[7] = (20 + 4) & 0xff; + buf[4] = 0x00; /* Physical format */ + buf[5] = 0x40; /* Not writable, is readable */ + buf[6] = ((20 + 4) >> 8) & 0xff; + buf[7] = (20 + 4) & 0xff; - buf[8] = 0x01; /* Copyright info */ - buf[9] = 0x40; /* Not writable, is readable */ - buf[10] = ((4 + 4) >> 8) & 0xff; - buf[11] = (4 + 4) & 0xff; + buf[8] = 0x01; /* Copyright info */ + buf[9] = 0x40; /* Not writable, is readable */ + buf[10] = ((4 + 4) >> 8) & 0xff; + buf[11] = (4 + 4) & 0xff; - buf[12] = 0x03; /* BCA info */ - buf[13] = 0x40; /* Not writable, is readable */ - buf[14] = ((188 + 4) >> 8) & 0xff; - buf[15] = (188 + 4) & 0xff; + buf[12] = 0x03; /* BCA info */ + buf[13] = 0x40; /* Not writable, is readable */ + buf[14] = ((188 + 4) >> 8) & 0xff; + buf[15] = (188 + 4) & 0xff; - buf[16] = 0x04; /* Manufacturing info */ - buf[17] = 0x40; /* Not writable, is readable */ - buf[18] = ((2048 + 4) >> 8) & 0xff; - buf[19] = (2048 + 4) & 0xff; + buf[16] = 0x04; /* Manufacturing info */ + buf[17] = 0x40; /* Not writable, is readable */ + buf[18] = ((2048 + 4) >> 8) & 0xff; + buf[19] = (2048 + 4) & 0xff; - /* Size of buffer, not including 2 byte size field */ - buf[6] = ((16 + 2) >> 8) & 0xff; - buf[7] = (16 + 2) & 0xff; + /* Size of buffer, not including 2 byte size field */ + buf[6] = ((16 + 2) >> 8) & 0xff; + buf[7] = (16 + 2) & 0xff; - /* data written + 4 byte header */ - return (16 + 4); + /* data written + 4 byte header */ + return (16 + 4); - default: /* TODO: formats beyond DVD-ROM requires */ - scsi_cdrom_invalid_field(dev); - return 0; + default: /* TODO: formats beyond DVD-ROM requires */ + scsi_cdrom_invalid_field(dev); + return 0; } } - static void -scsi_cdrom_insert(void *p) +scsi_cdrom_insert(void *priv) { - scsi_cdrom_t *dev = (scsi_cdrom_t *) p; + scsi_cdrom_t *dev = (scsi_cdrom_t *) priv; if (!dev) - return; + return; dev->unit_attention = 1; /* Turn off the medium changed status. */ @@ -1198,48 +1548,45 @@ scsi_cdrom_insert(void *p) scsi_cdrom_log("CD-ROM %i: Media insert\n", dev->id); } - static int scsi_cdrom_pre_execution_check(scsi_cdrom_t *dev, uint8_t *cdb) { int ready = 0; - if (dev->drv->bus_type == CDROM_BUS_SCSI) { - if ((cdb[0] != GPCMD_REQUEST_SENSE) && (dev->cur_lun == SCSI_LUN_USE_CDB) && (cdb[1] & 0xe0)) { - scsi_cdrom_log("CD-ROM %i: Attempting to execute a unknown command targeted at SCSI LUN %i\n", - dev->id, ((dev->request_length >> 5) & 7)); - scsi_cdrom_invalid_lun(dev); - return 0; - } + if ((cdb[0] != GPCMD_REQUEST_SENSE) && (dev->cur_lun == SCSI_LUN_USE_CDB) && (cdb[1] & 0xe0)) { + scsi_cdrom_log("CD-ROM %i: Attempting to execute a unknown command targeted at SCSI LUN %i\n", + dev->id, ((dev->tf->request_length >> 5) & 7)); + scsi_cdrom_invalid_lun(dev); + return 0; } if (!(scsi_cdrom_command_flags[cdb[0]] & IMPLEMENTED)) { - scsi_cdrom_log("CD-ROM %i: Attempting to execute unknown command %02X over %s\n", dev->id, cdb[0], - (dev->drv->bus_type == CDROM_BUS_SCSI) ? "SCSI" : "ATAPI"); + scsi_cdrom_log("CD-ROM %i: Attempting to execute unknown command %02X over %s\n", dev->id, cdb[0], + (dev->drv->bus_type == CDROM_BUS_SCSI) ? "SCSI" : "ATAPI"); - scsi_cdrom_illegal_opcode(dev); - return 0; + scsi_cdrom_illegal_opcode(dev); + return 0; } if ((dev->drv->bus_type < CDROM_BUS_SCSI) && (scsi_cdrom_command_flags[cdb[0]] & SCSI_ONLY)) { - scsi_cdrom_log("CD-ROM %i: Attempting to execute SCSI-only command %02X over ATAPI\n", dev->id, cdb[0]); - scsi_cdrom_illegal_opcode(dev); - return 0; + scsi_cdrom_log("CD-ROM %i: Attempting to execute SCSI-only command %02X over ATAPI\n", dev->id, cdb[0]); + scsi_cdrom_illegal_opcode(dev); + return 0; } if ((dev->drv->bus_type == CDROM_BUS_SCSI) && (scsi_cdrom_command_flags[cdb[0]] & ATAPI_ONLY)) { - scsi_cdrom_log("CD-ROM %i: Attempting to execute ATAPI-only command %02X over SCSI\n", dev->id, cdb[0]); - scsi_cdrom_illegal_opcode(dev); - return 0; + scsi_cdrom_log("CD-ROM %i: Attempting to execute ATAPI-only command %02X over SCSI\n", dev->id, cdb[0]); + scsi_cdrom_illegal_opcode(dev); + return 0; } if ((dev->drv->cd_status == CD_STATUS_PLAYING) || (dev->drv->cd_status == CD_STATUS_PAUSED)) { - ready = 1; - goto skip_ready_check; + ready = 1; + goto skip_ready_check; } if (dev->drv->cd_status & CD_STATUS_MEDIUM_CHANGED) - scsi_cdrom_insert((void *) dev); + scsi_cdrom_insert((void *) dev); ready = (dev->drv->cd_status != CD_STATUS_EMPTY); @@ -1248,42 +1595,42 @@ skip_ready_check: UNIT ATTENTION condition present, as we only use it to mark disc changes. */ if (!ready && dev->unit_attention) - dev->unit_attention = 0; + dev->unit_attention = 0; /* If the UNIT ATTENTION condition is set and the command does not allow execution under it, error out and report the condition. */ if (dev->unit_attention == 1) { - /* Only increment the unit attention phase if the command can not pass through it. */ - if (!(scsi_cdrom_command_flags[cdb[0]] & ALLOW_UA)) { - /* scsi_cdrom_log("CD-ROM %i: Unit attention now 2\n", dev->id); */ - dev->unit_attention++; - scsi_cdrom_log("CD-ROM %i: UNIT ATTENTION: Command %02X not allowed to pass through\n", - dev->id, cdb[0]); - scsi_cdrom_unit_attention(dev); - return 0; - } + /* Only increment the unit attention phase if the command can not pass through it. */ + if (!(scsi_cdrom_command_flags[cdb[0]] & ALLOW_UA)) { + /* scsi_cdrom_log("CD-ROM %i: Unit attention now 2\n", dev->id); */ + dev->unit_attention++; + scsi_cdrom_log("CD-ROM %i: UNIT ATTENTION: Command %02X not allowed to pass through\n", + dev->id, cdb[0]); + scsi_cdrom_unit_attention(dev); + return 0; + } } else if (dev->unit_attention == 2) { - if (cdb[0] != GPCMD_REQUEST_SENSE) { - /* scsi_cdrom_log("CD-ROM %i: Unit attention now 0\n", dev->id); */ - dev->unit_attention = 0; - } + if (cdb[0] != GPCMD_REQUEST_SENSE) { + /* scsi_cdrom_log("CD-ROM %i: Unit attention now 0\n", dev->id); */ + dev->unit_attention = 0; + } } /* Unless the command is REQUEST SENSE, clear the sense. This will *NOT* the UNIT ATTENTION condition if it's set. */ if (cdb[0] != GPCMD_REQUEST_SENSE) - scsi_cdrom_sense_clear(dev, cdb[0]); + scsi_cdrom_sense_clear(dev, cdb[0]); /* Next it's time for NOT READY. */ if (!ready) - dev->media_status = MEC_MEDIA_REMOVAL; + dev->media_status = MEC_MEDIA_REMOVAL; else - dev->media_status = (dev->unit_attention) ? MEC_NEW_MEDIA : MEC_NO_CHANGE; + dev->media_status = (dev->unit_attention) ? MEC_NEW_MEDIA : MEC_NO_CHANGE; if ((scsi_cdrom_command_flags[cdb[0]] & CHECK_READY) && !ready) { - scsi_cdrom_log("CD-ROM %i: Not ready (%02X)\n", dev->id, cdb[0]); - scsi_cdrom_not_ready(dev); - return 0; + scsi_cdrom_log("CD-ROM %i: Not ready (%02X)\n", dev->id, cdb[0]); + scsi_cdrom_not_ready(dev); + return 0; } scsi_cdrom_log("CD-ROM %i: Continuing with command %02X\n", dev->id, cdb[0]); @@ -1291,109 +1638,102 @@ skip_ready_check: return 1; } - static void scsi_cdrom_rezero(scsi_cdrom_t *dev) { dev->sector_pos = dev->sector_len = 0; - cdrom_seek(dev->drv, 0); + cdrom_seek(dev->drv, 0, 0); } - void scsi_cdrom_reset(scsi_common_t *sc) { scsi_cdrom_t *dev = (scsi_cdrom_t *) sc; if (!dev) - return; + return; scsi_cdrom_rezero(dev); - dev->status = 0; - dev->callback = 0.0; + dev->tf->status = 0; + dev->callback = 0.0; scsi_cdrom_set_callback(dev); - dev->phase = 1; - dev->request_length = 0xEB14; - dev->packet_status = PHASE_NONE; - dev->unit_attention = 0xff; - dev->cur_lun = SCSI_LUN_USE_CDB; + dev->tf->phase = 1; + dev->tf->request_length = 0xeb14; + dev->packet_status = PHASE_NONE; + dev->unit_attention = 0xff; + dev->cur_lun = SCSI_LUN_USE_CDB; } - static void scsi_cdrom_request_sense(scsi_cdrom_t *dev, uint8_t *buffer, uint8_t alloc_length) { /*Will return 18 bytes of 0*/ if (alloc_length != 0) { - memset(buffer, 0, alloc_length); - memcpy(buffer, dev->sense, alloc_length); + memset(buffer, 0, alloc_length); + memcpy(buffer, dev->sense, alloc_length); } buffer[0] = 0x70; if ((scsi_cdrom_sense_key > 0) && (dev->drv->cd_status == CD_STATUS_PLAYING_COMPLETED)) { - buffer[2]=SENSE_ILLEGAL_REQUEST; - buffer[12]=ASC_AUDIO_PLAY_OPERATION; - buffer[13]=ASCQ_AUDIO_PLAY_OPERATION_COMPLETED; - } else if ((scsi_cdrom_sense_key == 0) && ((dev->drv->cd_status == CD_STATUS_PAUSED) || - ((dev->drv->cd_status >= CD_STATUS_PLAYING) && (dev->drv->cd_status != CD_STATUS_STOPPED)))) { - buffer[2]=SENSE_ILLEGAL_REQUEST; - buffer[12]=ASC_AUDIO_PLAY_OPERATION; - buffer[13]=(dev->drv->cd_status == CD_STATUS_PLAYING) ? ASCQ_AUDIO_PLAY_OPERATION_IN_PROGRESS : ASCQ_AUDIO_PLAY_OPERATION_PAUSED; + buffer[2] = SENSE_ILLEGAL_REQUEST; + buffer[12] = ASC_AUDIO_PLAY_OPERATION; + buffer[13] = ASCQ_AUDIO_PLAY_OPERATION_COMPLETED; + } else if ((scsi_cdrom_sense_key == 0) && ((dev->drv->cd_status == CD_STATUS_PAUSED) || ((dev->drv->cd_status >= CD_STATUS_PLAYING) && (dev->drv->cd_status != CD_STATUS_STOPPED)))) { + buffer[2] = SENSE_ILLEGAL_REQUEST; + buffer[12] = ASC_AUDIO_PLAY_OPERATION; + buffer[13] = (dev->drv->cd_status == CD_STATUS_PLAYING) ? ASCQ_AUDIO_PLAY_OPERATION_IN_PROGRESS : ASCQ_AUDIO_PLAY_OPERATION_PAUSED; } else if (dev->unit_attention && (scsi_cdrom_sense_key == 0)) { - buffer[2]=SENSE_UNIT_ATTENTION; - buffer[12]=ASC_MEDIUM_MAY_HAVE_CHANGED; - buffer[13]=0; + buffer[2] = SENSE_UNIT_ATTENTION; + buffer[12] = ASC_MEDIUM_MAY_HAVE_CHANGED; + buffer[13] = 0; } scsi_cdrom_log("CD-ROM %i: Reporting sense: %02X %02X %02X\n", dev->id, buffer[2], buffer[12], buffer[13]); if (buffer[2] == SENSE_UNIT_ATTENTION) { - /* If the last remaining sense is unit attention, clear - that condition. */ - dev->unit_attention = 0; + /* If the last remaining sense is unit attention, clear + that condition. */ + dev->unit_attention = 0; } /* Clear the sense stuff as per the spec. */ scsi_cdrom_sense_clear(dev, GPCMD_REQUEST_SENSE); } - void scsi_cdrom_request_sense_for_scsi(scsi_common_t *sc, uint8_t *buffer, uint8_t alloc_length) { scsi_cdrom_t *dev = (scsi_cdrom_t *) sc; if (dev->drv->cd_status & CD_STATUS_MEDIUM_CHANGED) - scsi_cdrom_insert((void *) dev); + scsi_cdrom_insert((void *) dev); if ((dev->drv->cd_status == CD_STATUS_EMPTY) && dev->unit_attention) { - /* If the drive is not ready, there is no reason to keep the - UNIT ATTENTION condition present, as we only use it to mark - disc changes. */ - dev->unit_attention = 0; + /* If the drive is not ready, there is no reason to keep the + UNIT ATTENTION condition present, as we only use it to mark + disc changes. */ + dev->unit_attention = 0; } /* Do *NOT* advance the unit attention phase. */ scsi_cdrom_request_sense(dev, buffer, alloc_length); } - static void scsi_cdrom_set_buf_len(scsi_cdrom_t *dev, int32_t *BufLen, int32_t *src_len) { if (dev->drv->bus_type == CDROM_BUS_SCSI) { - if (*BufLen == -1) - *BufLen = *src_len; - else { - *BufLen = MIN(*src_len, *BufLen); - *src_len = *BufLen; - } - scsi_cdrom_log("CD-ROM %i: Actual transfer length: %i\n", dev->id, *BufLen); + if (*BufLen == -1) + *BufLen = *src_len; + else { + *BufLen = MIN(*src_len, *BufLen); + *src_len = *BufLen; + } + scsi_cdrom_log("CD-ROM %i: Actual transfer length: %i\n", dev->id, *BufLen); } } - static void scsi_cdrom_stop(scsi_common_t *sc) { @@ -1402,1112 +1742,2019 @@ scsi_cdrom_stop(scsi_common_t *sc) cdrom_stop(dev->drv); } - void scsi_cdrom_command(scsi_common_t *sc, uint8_t *cdb) { scsi_cdrom_t *dev = (scsi_cdrom_t *) sc; - int len, max_len, used_len, alloc_length, msf; - int pos = 0, i= 0, size_idx, idx = 0; - uint32_t feature; - unsigned preamble_len; - int toc_format, block_desc = 0; - int ret, format = 0; - int real_pos, track = 0; - char device_identify[9] = { '8', '6', 'B', '_', 'C', 'D', '0', '0', 0 }; - char device_identify_ex[15] = { '8', '6', 'B', '_', 'C', 'D', '0', '0', ' ', 'v', '1', '.', '0', '0', 0 }; - int32_t blen = 0, *BufLen; - uint8_t *b; - uint32_t profiles[2] = { MMC_PROFILE_CD_ROM, MMC_PROFILE_DVD_ROM }; - uint8_t scsi_bus = (dev->drv->scsi_device_id >> 4) & 0x0f; - uint8_t scsi_id = dev->drv->scsi_device_id & 0x0f; + int len; + int max_len; + int used_len; + int alloc_length; + int msf; + int pos = 0; + int size_idx; + int idx = 0; + uint32_t feature; + unsigned preamble_len; + int toc_format; + int block_desc = 0; + int ret; + int format = 0; + int real_pos; + int track = 0; + char device_identify[9] = { '8', '6', 'B', '_', 'C', 'D', '0', '0', 0 }; + char device_identify_ex[15] = { '8', '6', 'B', '_', 'C', 'D', '0', '0', ' ', 'v', '1', '.', '0', '0', 0 }; + int32_t blen = 0; + int32_t *BufLen; + uint8_t *b; + uint32_t profiles[2] = { MMC_PROFILE_CD_ROM, MMC_PROFILE_DVD_ROM }; + uint8_t scsi_bus = (dev->drv->scsi_device_id >> 4) & 0x0f; + uint8_t scsi_id = dev->drv->scsi_device_id & 0x0f; if (dev->drv->bus_type == CDROM_BUS_SCSI) { - BufLen = &scsi_devices[scsi_bus][scsi_id].buffer_length; - dev->status &= ~ERR_STAT; + BufLen = &scsi_devices[scsi_bus][scsi_id].buffer_length; + dev->tf->status &= ~ERR_STAT; } else { - BufLen = &blen; - dev->error = 0; + BufLen = &blen; + dev->tf->error = 0; } - dev->packet_len = 0; + dev->packet_len = 0; dev->request_pos = 0; device_identify[7] = dev->id + 0x30; - device_identify_ex[7] = dev->id + 0x30; + device_identify_ex[7] = dev->id + 0x30; device_identify_ex[10] = EMU_VERSION_EX[0]; device_identify_ex[12] = EMU_VERSION_EX[2]; device_identify_ex[13] = EMU_VERSION_EX[3]; memcpy(dev->current_cdb, cdb, 12); + dev->sony_vendor = 0; if (cdb[0] != 0) { - scsi_cdrom_log("CD-ROM %i: Command 0x%02X, Sense Key %02X, Asc %02X, Ascq %02X, Unit attention: %i\n", - dev->id, cdb[0], scsi_cdrom_sense_key, scsi_cdrom_asc, scsi_cdrom_ascq, dev->unit_attention); - scsi_cdrom_log("CD-ROM %i: Request length: %04X\n", dev->id, dev->request_length); + scsi_cdrom_log("CD-ROM %i: Command 0x%02X, Sense Key %02X, Asc %02X, Ascq %02X, Unit attention: %i\n", + dev->id, cdb[0], scsi_cdrom_sense_key, scsi_cdrom_asc, scsi_cdrom_ascq, + dev->unit_attention); + scsi_cdrom_log("CD-ROM %i: Request length: %04X\n", dev->id, dev->tf->request_length); - scsi_cdrom_log("CD-ROM %i: CDB: %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X\n", dev->id, - cdb[0], cdb[1], cdb[2], cdb[3], cdb[4], cdb[5], cdb[6], cdb[7], - cdb[8], cdb[9], cdb[10], cdb[11]); + scsi_cdrom_log("CD-ROM %i: CDB: %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X\n", + dev->id, cdb[0], cdb[1], cdb[2], cdb[3], cdb[4], cdb[5], cdb[6], cdb[7], + cdb[8], cdb[9], cdb[10], cdb[11]); } - msf = cdb[1] & 2; + msf = cdb[1] & 2; dev->sector_len = 0; scsi_cdrom_set_phase(dev, SCSI_PHASE_STATUS); /* This handles the Not Ready/Unit Attention check if it has to be handled at this point. */ if (scsi_cdrom_pre_execution_check(dev, cdb) == 0) - return; + return; +begin: switch (cdb[0]) { - case GPCMD_TEST_UNIT_READY: - scsi_cdrom_set_phase(dev, SCSI_PHASE_STATUS); - scsi_cdrom_command_complete(dev); - break; - - case GPCMD_REZERO_UNIT: - scsi_cdrom_stop(sc); - dev->sector_pos = dev->sector_len = 0; - dev->drv->seek_diff = dev->drv->seek_pos; - cdrom_seek(dev->drv, 0); - scsi_cdrom_set_phase(dev, SCSI_PHASE_STATUS); - break; - - case GPCMD_REQUEST_SENSE: - /* If there's a unit attention condition and there's a buffered not ready, a standalone REQUEST SENSE - should forget about the not ready, and report unit attention straight away. */ - scsi_cdrom_set_phase(dev, SCSI_PHASE_DATA_IN); - max_len = cdb[4]; - - if (!max_len) { - scsi_cdrom_set_phase(dev, SCSI_PHASE_STATUS); - dev->packet_status = PHASE_COMPLETE; - dev->callback = 20.0 * CDROM_TIME; - scsi_cdrom_set_callback(dev); - break; - } - - scsi_cdrom_buf_alloc(dev, 256); - scsi_cdrom_set_buf_len(dev, BufLen, &max_len); - scsi_cdrom_request_sense(dev, dev->buffer, max_len); - scsi_cdrom_data_command_finish(dev, 18, 18, cdb[4], 0); - break; - - case GPCMD_SET_SPEED: - case GPCMD_SET_SPEED_ALT: - dev->drv->cur_speed = (cdb[3] | (cdb[2] << 8)) / 176; - if (dev->drv->cur_speed < 1) - dev->drv->cur_speed = 1; - else if (dev->drv->cur_speed > dev->drv->speed) - dev->drv->cur_speed = dev->drv->speed; - scsi_cdrom_set_phase(dev, SCSI_PHASE_STATUS); - scsi_cdrom_command_complete(dev); - break; - - case GPCMD_MECHANISM_STATUS: - scsi_cdrom_set_phase(dev, SCSI_PHASE_DATA_IN); - len = (cdb[7] << 16) | (cdb[8] << 8) | cdb[9]; - - scsi_cdrom_buf_alloc(dev, 8); - - scsi_cdrom_set_buf_len(dev, BufLen, &len); - - memset(dev->buffer, 0, 8); - dev->buffer[5] = 1; - - scsi_cdrom_data_command_finish(dev, 8, 8, len, 0); - break; - - case GPCMD_READ_TOC_PMA_ATIP: - scsi_cdrom_set_phase(dev, SCSI_PHASE_DATA_IN); - - max_len = cdb[7]; - max_len <<= 8; - max_len |= cdb[8]; - - scsi_cdrom_buf_alloc(dev, 65536); - - toc_format = cdb[2] & 0xf; - - if (toc_format == 0) - toc_format = (cdb[9] >> 6) & 3; - - if (!dev->drv->ops) { - scsi_cdrom_not_ready(dev); - return; - } - - if (toc_format < 3) { - len = cdrom_read_toc(dev->drv, dev->buffer, toc_format, cdb[6], msf, max_len); - if (len == -1) { - /* If the returned length is -1, this means cdrom_read_toc() has encountered an error. */ - scsi_cdrom_invalid_field(dev); - scsi_cdrom_buf_free(dev); - return; - } - } else { - scsi_cdrom_invalid_field(dev); - scsi_cdrom_buf_free(dev); - return; - } - - scsi_cdrom_set_buf_len(dev, BufLen, &len); - - scsi_cdrom_data_command_finish(dev, len, len, len, 0); - /* scsi_cdrom_log("CD-ROM %i: READ_TOC_PMA_ATIP format %02X, length %i (%i)\n", dev->id, - toc_format, ide->cylinder, dev->buffer[1]); */ - return; - - case GPCMD_READ_DISC_INFORMATION_TOSHIBA: - scsi_cdrom_set_phase(dev, SCSI_PHASE_DATA_IN); - - scsi_cdrom_buf_alloc(dev, 65536); - - if ((!dev->drv->ops) && ((cdb[1] & 3) == 2)) { - scsi_cdrom_not_ready(dev); - return; - } - - memset(dev->buffer, 0, 4); - - cdrom_read_disc_info_toc(dev->drv, dev->buffer, cdb[2], cdb[1] & 3); - - len = 4; - scsi_cdrom_set_buf_len(dev, BufLen, &len); - - scsi_cdrom_data_command_finish(dev, len, len, len, 0); - return; - - case GPCMD_READ_CD_OLD: - /* IMPORTANT: Convert the command to new read CD - for pass through purposes. */ - dev->current_cdb[0] = 0xbe; - /*FALLTHROUGH*/ - - case GPCMD_READ_6: - case GPCMD_READ_10: - case GPCMD_READ_12: - case GPCMD_READ_CD: - case GPCMD_READ_CD_MSF: - scsi_cdrom_set_phase(dev, SCSI_PHASE_DATA_IN); - alloc_length = 2048; - - switch(cdb[0]) { - case GPCMD_READ_6: - dev->sector_len = cdb[4]; - if (dev->sector_len == 0) - dev->sector_len = 256; /* For READ (6) and WRITE (6), a length of 0 indicates a transfer of 256 sector. */ - dev->sector_pos = ((((uint32_t) cdb[1]) & 0x1f) << 16) | (((uint32_t) cdb[2]) << 8) | ((uint32_t) cdb[3]); - msf = 0; - break; - case GPCMD_READ_10: - dev->sector_len = (cdb[7] << 8) | cdb[8]; - dev->sector_pos = (cdb[2] << 24) | (cdb[3] << 16) | (cdb[4] << 8) | cdb[5]; - scsi_cdrom_log("CD-ROM %i: Length: %i, LBA: %i\n", dev->id, dev->sector_len, - dev->sector_pos); - msf = 0; - break; - case GPCMD_READ_12: - dev->sector_len = (((uint32_t) cdb[6]) << 24) | (((uint32_t) cdb[7]) << 16) | (((uint32_t) cdb[8]) << 8) | ((uint32_t) cdb[9]); - dev->sector_pos = (((uint32_t) cdb[2]) << 24) | (((uint32_t) cdb[3]) << 16) | (((uint32_t) cdb[4]) << 8) | ((uint32_t) cdb[5]); - scsi_cdrom_log("CD-ROM %i: Length: %i, LBA: %i\n", dev->id, dev->sector_len, - dev->sector_pos); - msf = 0; - break; - case GPCMD_READ_CD_MSF: - alloc_length = 2856; - dev->sector_len = MSFtoLBA(cdb[6], cdb[7], cdb[8]); - dev->sector_pos = MSFtoLBA(cdb[3], cdb[4], cdb[5]); - - dev->sector_len -= dev->sector_pos; - dev->sector_len++; - - msf = 1; - - if ((cdb[9] & 0xf8) == 0x08) { - /* 0x08 is an illegal mode */ - scsi_cdrom_invalid_field(dev); - return; - } - - /* If all the flag bits are cleared, then treat it as a non-data command. */ - if ((cdb[9] == 0x00) && ((cdb[10] & 0x07) == 0x00)) - dev->sector_len = 0; - else if ((cdb[9] == 0x00) && ((cdb[10] & 0x07) != 0x00)) { - scsi_cdrom_invalid_field(dev); - return; - } - break; - case GPCMD_READ_CD_OLD: - case GPCMD_READ_CD: - alloc_length = 2856; - dev->sector_len = (cdb[6] << 16) | (cdb[7] << 8) | cdb[8]; - dev->sector_pos = (cdb[2] << 24) | (cdb[3] << 16) | (cdb[4] << 8) | cdb[5]; - - msf = 0; - - if ((cdb[9] & 0xf8) == 0x08) { - /* 0x08 is an illegal mode */ - scsi_cdrom_invalid_field(dev); - return; - } - - /* If all the flag bits are cleared, then treat it as a non-data command. */ - if ((cdb[9] == 0x00) && ((cdb[10] & 0x07) == 0x00)) - dev->sector_len = 0; - else if ((cdb[9] == 0x00) && ((cdb[10] & 0x07) != 0x00)) { - scsi_cdrom_invalid_field(dev); - return; - } - break; - } - - if (!dev->sector_len) { - scsi_cdrom_set_phase(dev, SCSI_PHASE_STATUS); - /* scsi_cdrom_log("CD-ROM %i: All done - callback set\n", dev->id); */ - dev->packet_status = PHASE_COMPLETE; - dev->callback = 20.0 * CDROM_TIME; - scsi_cdrom_set_callback(dev); - break; - } - - max_len = dev->sector_len; - dev->requested_blocks = max_len; /* If we're reading all blocks in one go for DMA, why not also for PIO, it should NOT - matter anyway, this step should be identical and only the way the read dat is - transferred to the host should be different. */ - - dev->packet_len = max_len * alloc_length; - scsi_cdrom_buf_alloc(dev, dev->packet_len); - - dev->drv->seek_diff = ABS((int) (pos - dev->sector_pos)); - - ret = scsi_cdrom_read_blocks(dev, &alloc_length, 1); - if (ret <= 0) { - scsi_cdrom_set_phase(dev, SCSI_PHASE_STATUS); - dev->packet_status = PHASE_COMPLETE; - dev->callback = 20.0 * CDROM_TIME; - scsi_cdrom_set_callback(dev); - scsi_cdrom_buf_free(dev); - return; - } - - dev->requested_blocks = max_len; - dev->packet_len = alloc_length; - - scsi_cdrom_set_buf_len(dev, BufLen, (int32_t *) &dev->packet_len); - - scsi_cdrom_data_command_finish(dev, alloc_length, alloc_length / dev->requested_blocks, - alloc_length, 0); - - if (dev->packet_status != PHASE_COMPLETE) - ui_sb_update_icon(SB_CDROM | dev->id, 1); - else - ui_sb_update_icon(SB_CDROM | dev->id, 0); - return; - - case GPCMD_READ_HEADER: - scsi_cdrom_set_phase(dev, SCSI_PHASE_DATA_IN); - - alloc_length = ((cdb[7] << 8) | cdb[8]); - scsi_cdrom_buf_alloc(dev, 8); - - dev->sector_len = 1; - dev->sector_pos = (cdb[2] << 24) | (cdb[3] << 16) | (cdb[4]<<8) | cdb[5]; - if (msf) - real_pos = cdrom_lba_to_msf_accurate(dev->sector_pos); - else - real_pos = dev->sector_pos; - dev->buffer[0] = 1; /*2048 bytes user data*/ - dev->buffer[1] = dev->buffer[2] = dev->buffer[3] = 0; - dev->buffer[4] = (real_pos >> 24); - dev->buffer[5] = ((real_pos >> 16) & 0xff); - dev->buffer[6] = ((real_pos >> 8) & 0xff); - dev->buffer[7] = real_pos & 0xff; - - len = 8; - len = MIN(len, alloc_length); - - scsi_cdrom_set_buf_len(dev, BufLen, &len); - - scsi_cdrom_data_command_finish(dev, len, len, len, 0); - return; - - case GPCMD_MODE_SENSE_6: - case GPCMD_MODE_SENSE_10: - scsi_cdrom_set_phase(dev, SCSI_PHASE_DATA_IN); - - if (dev->drv->bus_type == CDROM_BUS_SCSI) - block_desc = ((cdb[1] >> 3) & 1) ? 0 : 1; - else - block_desc = 0; - - if (cdb[0] == GPCMD_MODE_SENSE_6) { - len = cdb[4]; - scsi_cdrom_buf_alloc(dev, 256); - } else { - len = (cdb[8] | (cdb[7] << 8)); - scsi_cdrom_buf_alloc(dev, 65536); - } - - if (!(scsi_cdrom_mode_sense_page_flags & (1LL << (uint64_t) (cdb[2] & 0x3f)))) { - scsi_cdrom_invalid_field(dev); - scsi_cdrom_buf_free(dev); - return; - } - - memset(dev->buffer, 0, len); - alloc_length = len; - - /* This determines the media type ID to return - this is - a SCSI/ATAPI-specific thing, so it makes the most sense - to keep this here. - Also, the max_len variable is reused as this command - does otherwise not use it, to avoid having to declare - another variable. */ - if (dev->drv->cd_status == CD_STATUS_EMPTY) - max_len = 70; /* No media inserted. */ - else if (dev->drv->cdrom_capacity > 405000) - max_len = 65; /* DVD. */ - else if (dev->drv->cd_status == CD_STATUS_DATA_ONLY) - max_len = 1; /* Data CD. */ - else - max_len = 3; /* Audio or mixed-mode CD. */ - - if (cdb[0] == GPCMD_MODE_SENSE_6) { - len = scsi_cdrom_mode_sense(dev, dev->buffer, 4, cdb[2], block_desc); - len = MIN(len, alloc_length); - dev->buffer[0] = len - 1; - dev->buffer[1] = max_len; - if (block_desc) - dev->buffer[3] = 8; - } else { - len = scsi_cdrom_mode_sense(dev, dev->buffer, 8, cdb[2], block_desc); - len = MIN(len, alloc_length); - dev->buffer[0] = (len - 2) >> 8; - dev->buffer[1] = (len - 2) & 255; - dev->buffer[2] = max_len; - if (block_desc) { - dev->buffer[6] = 0; - dev->buffer[7] = 8; - } - } - - scsi_cdrom_set_buf_len(dev, BufLen, &len); - - scsi_cdrom_log("CD-ROM %i: Reading mode page: %02X...\n", dev->id, cdb[2]); - - scsi_cdrom_data_command_finish(dev, len, len, alloc_length, 0); - return; - - case GPCMD_MODE_SELECT_6: - case GPCMD_MODE_SELECT_10: - scsi_cdrom_set_phase(dev, SCSI_PHASE_DATA_OUT); - - if (cdb[0] == GPCMD_MODE_SELECT_6) { - len = cdb[4]; - scsi_cdrom_buf_alloc(dev, 256); - } else { - len = (cdb[7] << 8) | cdb[8]; - scsi_cdrom_buf_alloc(dev, 65536); - } - - scsi_cdrom_set_buf_len(dev, BufLen, &len); - - dev->total_length = len; - dev->do_page_save = cdb[1] & 1; - - scsi_cdrom_data_command_finish(dev, len, len, len, 1); - return; - - case GPCMD_GET_CONFIGURATION: - scsi_cdrom_set_phase(dev, SCSI_PHASE_DATA_IN); - - /* XXX: could result in alignment problems in some architectures */ - feature = (cdb[2] << 8) | cdb[3]; - max_len = (cdb[7] << 8) | cdb[8]; - - /* only feature 0 is supported */ - if ((cdb[2] != 0) || (cdb[3] > 2)) { - scsi_cdrom_invalid_field(dev); - scsi_cdrom_buf_free(dev); - return; - } - - scsi_cdrom_buf_alloc(dev, 65536); - memset(dev->buffer, 0, max_len); - - alloc_length = 0; - b = dev->buffer; - - /* - * the number of sectors from the media tells us which profile - * to use as current. 0 means there is no media - */ - if (dev->drv->cd_status != CD_STATUS_EMPTY) { - len = dev->drv->cdrom_capacity; - if (len > CD_MAX_SECTORS) { - b[6] = (MMC_PROFILE_DVD_ROM >> 8) & 0xff; - b[7] = MMC_PROFILE_DVD_ROM & 0xff; - ret = 1; - } else { - b[6] = (MMC_PROFILE_CD_ROM >> 8) & 0xff; - b[7] = MMC_PROFILE_CD_ROM & 0xff; - ret = 0; - } - } else - ret = 2; - - alloc_length = 8; - b += 8; - - if ((feature == 0) || ((cdb[1] & 3) < 2)) { - b[2] = (0 << 2) | 0x02 | 0x01; /* persistent and current */ - b[3] = 8; - - alloc_length += 4; - b += 4; - - for (i = 0; i < 2; i++) { - b[0] = (profiles[i] >> 8) & 0xff; - b[1] = profiles[i] & 0xff; - - if (ret == i) - b[2] |= 1; - - alloc_length += 4; - b += 4; - } - } - if ((feature == 1) || ((cdb[1] & 3) < 2)) { - b[1] = 1; - b[2] = (2 << 2) | 0x02 | 0x01; /* persistent and current */ - b[3] = 8; - - if (dev->drv->bus_type == CDROM_BUS_SCSI) - b[7] = 1; - else - b[7] = 2; - b[8] = 1; - - alloc_length += 12; - b += 12; - } - if ((feature == 2) || ((cdb[1] & 3) < 2)) { - b[1] = 2; - b[2] = (1 << 2) | 0x02 | 0x01; /* persistent and current */ - b[3] = 4; - - b[4] = 2; - - alloc_length += 8; - b += 8; - } - - dev->buffer[0] = ((alloc_length - 4) >> 24) & 0xff; - dev->buffer[1] = ((alloc_length - 4) >> 16) & 0xff; - dev->buffer[2] = ((alloc_length - 4) >> 8) & 0xff; - dev->buffer[3] = (alloc_length - 4) & 0xff; - - alloc_length = MIN(alloc_length, max_len); - - scsi_cdrom_set_buf_len(dev, BufLen, &alloc_length); - - scsi_cdrom_data_command_finish(dev, alloc_length, alloc_length, alloc_length, 0); - break; - - case GPCMD_GET_EVENT_STATUS_NOTIFICATION: - scsi_cdrom_set_phase(dev, SCSI_PHASE_DATA_IN); - - scsi_cdrom_buf_alloc(dev, 8 + sizeof(gesn_event_header_t)); - - gesn_cdb = (void *) cdb; - gesn_event_header = (void *) dev->buffer; - - /* It is fine by the MMC spec to not support async mode operations. */ - if (!(gesn_cdb->polled & 0x01)) { - /* asynchronous mode */ - /* Only polling is supported, asynchronous mode is not. */ - scsi_cdrom_invalid_field(dev); - scsi_cdrom_buf_free(dev); - return; - } - - /* - * These are the supported events. - * - * We currently only support requests of the 'media' type. - * Notification class requests and supported event classes are bitmasks, - * but they are built from the same values as the "notification class" - * field. - */ - gesn_event_header->supported_events = 1 << GESN_MEDIA; - - /* - * We use |= below to set the class field; other bits in this byte - * are reserved now but this is useful to do if we have to use the - * reserved fields later. - */ - gesn_event_header->notification_class = 0; - - /* - * Responses to requests are to be based on request priority. The - * notification_class_request_type enum above specifies the - * priority: upper elements are higher prio than lower ones. - */ - if (gesn_cdb->class & (1 << GESN_MEDIA)) { - gesn_event_header->notification_class |= GESN_MEDIA; - - dev->buffer[4] = dev->media_status; /* Bits 7-4 = Reserved, Bits 4-1 = Media Status */ - dev->buffer[5] = 1; /* Power Status (1 = Active) */ - dev->buffer[6] = 0; - dev->buffer[7] = 0; - used_len = 8; - } else { - gesn_event_header->notification_class = 0x80; /* No event available */ - used_len = sizeof(*gesn_event_header); - } - gesn_event_header->len = used_len - sizeof(*gesn_event_header); - - memmove(dev->buffer, gesn_event_header, 4); - - scsi_cdrom_set_buf_len(dev, BufLen, &used_len); - - scsi_cdrom_data_command_finish(dev, used_len, used_len, used_len, 0); - break; - - case GPCMD_READ_DISC_INFORMATION: - scsi_cdrom_set_phase(dev, SCSI_PHASE_DATA_IN); - - max_len = cdb[7]; - max_len <<= 8; - max_len |= cdb[8]; - - scsi_cdrom_buf_alloc(dev, 65536); - - memset(dev->buffer, 0, 34); - memset(dev->buffer, 1, 9); - dev->buffer[0] = 0; - dev->buffer[1] = 32; - dev->buffer[2] = 0xe; /* last session complete, disc finalized */ - dev->buffer[7] = 0x20; /* unrestricted use */ - dev->buffer[8] = 0x00; /* CD-ROM */ - - len=34; - len = MIN(len, max_len); - - scsi_cdrom_set_buf_len(dev, BufLen, &len); - - scsi_cdrom_data_command_finish(dev, len, len, len, 0); - break; - - case GPCMD_READ_TRACK_INFORMATION: - scsi_cdrom_set_phase(dev, SCSI_PHASE_DATA_IN); - - max_len = cdb[7]; - max_len <<= 8; - max_len |= cdb[8]; - - scsi_cdrom_buf_alloc(dev, 65536); - - track = ((uint32_t) cdb[2]) << 24; - track |= ((uint32_t) cdb[3]) << 16; - track |= ((uint32_t) cdb[4]) << 8; - track |= (uint32_t) cdb[5]; - - if (((cdb[1] & 0x03) != 1) || (track != 1)) { - scsi_cdrom_invalid_field(dev); - scsi_cdrom_buf_free(dev); - return; - } - - len = 36; - - memset(dev->buffer, 0, 36); - dev->buffer[0] = 0; - dev->buffer[1] = 34; - dev->buffer[2] = 1; /* track number (LSB) */ - dev->buffer[3] = 1; /* session number (LSB) */ - dev->buffer[5] = (0 << 5) | (0 << 4) | (4 << 0); /* not damaged, primary copy, data track */ - dev->buffer[6] = (0 << 7) | (0 << 6) | (0 << 5) | (0 << 6) | (1 << 0); /* not reserved track, not blank, not packet writing, not fixed packet, data mode 1 */ - dev->buffer[7] = (0 << 1) | (0 << 0); /* last recorded address not valid, next recordable address not valid */ - - dev->buffer[24] = ((dev->drv->cdrom_capacity - 1) >> 24) & 0xff; /* track size */ - dev->buffer[25] = ((dev->drv->cdrom_capacity - 1) >> 16) & 0xff; /* track size */ - dev->buffer[26] = ((dev->drv->cdrom_capacity - 1) >> 8) & 0xff; /* track size */ - dev->buffer[27] = (dev->drv->cdrom_capacity - 1) & 0xff; /* track size */ - - if (len > max_len) { - len = max_len; - dev->buffer[0] = ((max_len - 2) >> 8) & 0xff; - dev->buffer[1] = (max_len - 2) & 0xff; - } - - scsi_cdrom_set_buf_len(dev, BufLen, &len); - - scsi_cdrom_data_command_finish(dev, len, len, max_len, 0); - break; - - case GPCMD_AUDIO_TRACK_SEARCH: - scsi_cdrom_set_phase(dev, SCSI_PHASE_STATUS); - if ((dev->drv->host_drive < 1) || (dev->drv->cd_status <= CD_STATUS_DATA_ONLY)) { - scsi_cdrom_illegal_mode(dev); - break; - } - pos = (cdb[2] << 24) | (cdb[3] << 16) | (cdb[4] << 8) | cdb[5]; - ret = cdrom_audio_track_search(dev->drv, pos, cdb[9], cdb[1] & 1); - - if (ret) - scsi_cdrom_command_complete(dev); - else - scsi_cdrom_illegal_mode(dev); - break; - - case GPCMD_TOSHIBA_PLAY_AUDIO: - scsi_cdrom_set_phase(dev, SCSI_PHASE_STATUS); - if ((dev->drv->host_drive < 1) || (dev->drv->cd_status <= CD_STATUS_DATA_ONLY)) { - scsi_cdrom_illegal_mode(dev); - break; - } - pos = (cdb[2] << 24) | (cdb[3] << 16) | (cdb[4] << 8) | cdb[5]; - ret = cdrom_toshiba_audio_play(dev->drv, pos, cdb[9]); - - if (ret) - scsi_cdrom_command_complete(dev); - else - scsi_cdrom_illegal_mode(dev); - break; - - case GPCMD_PLAY_AUDIO_10: - case GPCMD_PLAY_AUDIO_12: - case GPCMD_PLAY_AUDIO_MSF: - case GPCMD_PLAY_AUDIO_TRACK_INDEX: - case GPCMD_PLAY_AUDIO_TRACK_RELATIVE_10: - case GPCMD_PLAY_AUDIO_TRACK_RELATIVE_12: - len = 0; - - scsi_cdrom_set_phase(dev, SCSI_PHASE_STATUS); - - switch(cdb[0]) { - case GPCMD_PLAY_AUDIO_10: - msf = 0; - pos = (cdb[2] << 24) | (cdb[3] << 16) | (cdb[4] << 8) | cdb[5]; - len = (cdb[7] << 8) | cdb[8]; - break; - case GPCMD_PLAY_AUDIO_12: - /* This is apparently deprecated in the ATAPI spec, and apparently - has been since 1995 (!). Hence I'm having to guess most of it. */ - msf = 0; - pos = (cdb[2] << 24) | (cdb[3] << 16) | (cdb[4] << 8) | cdb[5]; - len = (cdb[6] << 24) | (cdb[7] << 16) | (cdb[8] << 8) | cdb[9]; - break; - case GPCMD_PLAY_AUDIO_MSF: - msf = 1; - pos = (cdb[3] << 16) | (cdb[4] << 8) | cdb[5]; - len = (cdb[6] << 16) | (cdb[7] << 8) | cdb[8]; - break; - case GPCMD_PLAY_AUDIO_TRACK_INDEX: - msf = 2; - if ((cdb[5] != 1) || (cdb[8] != 1)) { - scsi_cdrom_illegal_mode(dev); - break; - } - pos = cdb[4]; - len = cdb[7]; - break; - case GPCMD_PLAY_AUDIO_TRACK_RELATIVE_10: - msf = 0x100 | cdb[6]; - pos = (cdb[2] << 24) | (cdb[3] << 16) | (cdb[4] << 8) | cdb[5]; - len = (cdb[7] << 8) | cdb[8]; - break; - case GPCMD_PLAY_AUDIO_TRACK_RELATIVE_12: - msf = 0x100 | cdb[10]; - pos = (cdb[2] << 24) | (cdb[3] << 16) | (cdb[4] << 8) | cdb[5]; - len = (cdb[6] << 24) | (cdb[7] << 16) | (cdb[8] << 8) | cdb[9]; - break; - } - - if ((dev->drv->host_drive < 1) || (dev->drv->cd_status <= CD_STATUS_DATA_ONLY)) { - scsi_cdrom_illegal_mode(dev); - break; - } - - ret = cdrom_audio_play(dev->drv, pos, len, msf); - - if (ret) - scsi_cdrom_command_complete(dev); - else - scsi_cdrom_illegal_mode(dev); - break; - - case GPCMD_READ_SUBCHANNEL: - scsi_cdrom_set_phase(dev, SCSI_PHASE_DATA_IN); - - max_len = cdb[7]; - max_len <<= 8; - max_len |= cdb[8]; - msf = (cdb[1] >> 1) & 1; - - scsi_cdrom_buf_alloc(dev, 32); - - scsi_cdrom_log("CD-ROM %i: Getting page %i (%s)\n", dev->id, cdb[3], msf ? "MSF" : "LBA"); - - if (cdb[3] > 3) { - /* scsi_cdrom_log("CD-ROM %i: Read subchannel check condition %02X\n", dev->id, - cdb[3]); */ - scsi_cdrom_invalid_field(dev); - scsi_cdrom_buf_free(dev); - return; - } - - if (!(cdb[2] & 0x40)) - alloc_length = 4; - else switch(cdb[3]) { - case 0: - /* SCSI-2: Q-type subchannel, ATAPI: reserved */ - alloc_length = (dev->drv->bus_type == CDROM_BUS_SCSI) ? 48 : 4; - break; - case 1: - alloc_length = 16; - break; - default: - alloc_length = 24; - break; - } - - len = alloc_length; - - memset(dev->buffer, 0, 24); - pos = 0; - dev->buffer[pos++] = 0; - dev->buffer[pos++] = 0; /*Audio status*/ - dev->buffer[pos++] = 0; dev->buffer[pos++] = 0; /*Subchannel length*/ - /* Mode 0 = Q subchannel mode, first 16 bytes are indentical to mode 1 (current position), - the rest are stuff like ISRC etc., which can be all zeroes. */ - if (cdb[3] <= 3) { - dev->buffer[pos++] = cdb[3]; /*Format code*/ - - if (alloc_length != 4) { - dev->buffer[1] = cdrom_get_current_subchannel(dev->drv, &dev->buffer[4], msf); - dev->buffer[2] = alloc_length - 4; - } - - switch(dev->drv->cd_status) { - case CD_STATUS_PLAYING: - dev->buffer[1] = 0x11; - break; - case CD_STATUS_PAUSED: - dev->buffer[1] = 0x12; - break; - case CD_STATUS_DATA_ONLY: - dev->buffer[1] = 0x15; - break; - default: - dev->buffer[1] = 0x13; - break; - } - - scsi_cdrom_log("Audio Status = %02x\n", dev->buffer[1]); - } - - len = MIN(len, max_len); - scsi_cdrom_set_buf_len(dev, BufLen, &len); - - scsi_cdrom_data_command_finish(dev, len, len, len, 0); - break; - - case GPCMD_READ_SUBCODEQ_PLAYING_STATUS: - scsi_cdrom_set_phase(dev, SCSI_PHASE_DATA_IN); - - alloc_length = cdb[1] & 0x1f; - - scsi_cdrom_buf_alloc(dev, alloc_length); - - if (!dev->drv->ops) { - scsi_cdrom_not_ready(dev); - return; - } - - if (!alloc_length) { - scsi_cdrom_set_phase(dev, SCSI_PHASE_STATUS); - scsi_cdrom_log("CD-ROM %i: All done - callback set\n", dev->id); - dev->packet_status = PHASE_COMPLETE; - dev->callback = 20.0 * CDROM_TIME; - scsi_cdrom_set_callback(dev); - break; - } - - len = alloc_length; - - memset(dev->buffer, 0, len); - dev->buffer[0] = cdrom_get_current_subcodeq_playstatus(dev->drv, &dev->buffer[1]); - scsi_cdrom_log("Audio Status = %02x\n", dev->buffer[0]); - - scsi_cdrom_set_buf_len(dev, BufLen, &alloc_length); - scsi_cdrom_data_command_finish(dev, len, len, len, 0); - break; - - case GPCMD_READ_DVD_STRUCTURE: - scsi_cdrom_set_phase(dev, SCSI_PHASE_DATA_IN); - - alloc_length = (((uint32_t) cdb[8]) << 8) | ((uint32_t) cdb[9]); - - scsi_cdrom_buf_alloc(dev, alloc_length); - - if ((cdb[7] < 0xc0) && (dev->drv->cdrom_capacity <= CD_MAX_SECTORS)) { - scsi_cdrom_incompatible_format(dev); - scsi_cdrom_buf_free(dev); - return; - } - - memset(dev->buffer, 0, alloc_length); - - if ((cdb[7] <= 0x7f) || (cdb[7] == 0xff)) { - if (cdb[1] == 0) { - ret = scsi_cdrom_read_dvd_structure(dev, format, cdb, dev->buffer); - dev->buffer[0] = (ret >> 8); - dev->buffer[1] = (ret & 0xff); - dev->buffer[2] = dev->buffer[3] = 0x00; - if (ret) { - scsi_cdrom_set_buf_len(dev, BufLen, &alloc_length); - scsi_cdrom_data_command_finish(dev, alloc_length, alloc_length, - alloc_length, 0); - } else - scsi_cdrom_buf_free(dev); - return; - } - } else { - scsi_cdrom_invalid_field(dev); - scsi_cdrom_buf_free(dev); - return; - } - break; - - case GPCMD_START_STOP_UNIT: - scsi_cdrom_set_phase(dev, SCSI_PHASE_STATUS); - - switch(cdb[4] & 3) { - case 0: /* Stop the disc. */ - scsi_cdrom_stop(sc); - break; - case 1: /* Start the disc and read the TOC. */ - /* This makes no sense under emulation as this would do - absolutely nothing, so just break. */ - break; - case 2: /* Eject the disc if possible. */ - scsi_cdrom_stop(sc); - cdrom_eject(dev->id); - break; - case 3: /* Load the disc (close tray). */ - cdrom_reload(dev->id); - break; - } - - scsi_cdrom_command_complete(dev); - break; - - case GPCMD_CADDY_EJECT: - scsi_cdrom_set_phase(dev, SCSI_PHASE_STATUS); - scsi_cdrom_stop(sc); - cdrom_eject(dev->id); - scsi_cdrom_command_complete(dev); - break; - - case GPCMD_INQUIRY: - scsi_cdrom_set_phase(dev, SCSI_PHASE_DATA_IN); - - max_len = cdb[3]; - max_len <<= 8; - max_len |= cdb[4]; - - scsi_cdrom_buf_alloc(dev, 65536); - - if (cdb[1] & 1) { - preamble_len = 4; - size_idx = 3; - - dev->buffer[idx++] = 05; - dev->buffer[idx++] = cdb[2]; - dev->buffer[idx++] = 0; - - idx++; - - switch (cdb[2]) { - case 0x00: - dev->buffer[idx++] = 0x00; - dev->buffer[idx++] = 0x83; - break; - case 0x83: - if (idx + 24 > max_len) { - scsi_cdrom_data_phase_error(dev); - scsi_cdrom_buf_free(dev); - return; - } - - dev->buffer[idx++] = 0x02; - dev->buffer[idx++] = 0x00; - dev->buffer[idx++] = 0x00; - dev->buffer[idx++] = 20; - ide_padstr8(dev->buffer + idx, 20, "53R141"); /* Serial */ - idx += 20; - - if (idx + 72 > cdb[4]) - goto atapi_out; - dev->buffer[idx++] = 0x02; - dev->buffer[idx++] = 0x01; - dev->buffer[idx++] = 0x00; - dev->buffer[idx++] = 68; - if (dev->drv->bus_type == CDROM_BUS_SCSI) - ide_padstr8(dev->buffer + idx, 8, "TOSHIBA"); /* Vendor */ - else - ide_padstr8(dev->buffer + idx, 8, EMU_NAME); /* Vendor */ - idx += 8; - if (dev->drv->bus_type == CDROM_BUS_SCSI) - ide_padstr8(dev->buffer + idx, 40, "XM6201TASUN32XCD1103"); /* Product */ - else - ide_padstr8(dev->buffer + idx, 40, device_identify_ex); /* Product */ - idx += 40; - ide_padstr8(dev->buffer + idx, 20, "53R141"); /* Product */ - idx += 20; - break; - default: - scsi_cdrom_log("INQUIRY: Invalid page: %02X\n", cdb[2]); - scsi_cdrom_invalid_field(dev); - scsi_cdrom_buf_free(dev); - return; - } - } else { - preamble_len = 5; - size_idx = 4; - - memset(dev->buffer, 0, 8); - dev->buffer[0] = 5; /*CD-ROM*/ - dev->buffer[1] = 0x80; /*Removable*/ - - if (dev->drv->bus_type == CDROM_BUS_SCSI) { - dev->buffer[2] = 0x02; - dev->buffer[3] = 0x02; - } - else { - dev->buffer[2] = 0x00; - dev->buffer[3] = 0x21; - } - - dev->buffer[4] = 31; - if (dev->drv->bus_type == CDROM_BUS_SCSI) { - dev->buffer[6] = 1; /* 16-bit transfers supported */ - dev->buffer[7] = 0x20; /* Wide bus supported */ - } - - if (dev->drv->bus_type == CDROM_BUS_SCSI) { - ide_padstr8(dev->buffer + 8, 8, "TOSHIBA"); /* Vendor */ - ide_padstr8(dev->buffer + 16, 16, "XM6201TASUN32XCD"); /* Product */ - ide_padstr8(dev->buffer + 32, 4, "1103"); /* Revision */ - } else { - ide_padstr8(dev->buffer + 8, 8, EMU_NAME); /* Vendor */ - ide_padstr8(dev->buffer + 16, 16, device_identify); /* Product */ - ide_padstr8(dev->buffer + 32, 4, EMU_VERSION_EX); /* Revision */ - } - - idx = 36; - - if (max_len == 96) { - dev->buffer[4] = 91; - idx = 96; - } - } + case GPCMD_TEST_UNIT_READY: + scsi_cdrom_set_phase(dev, SCSI_PHASE_STATUS); + scsi_cdrom_command_complete(dev); + break; + + case GPCMD_REZERO_UNIT: + scsi_cdrom_stop(sc); + dev->sector_pos = dev->sector_len = 0; + dev->drv->seek_diff = dev->drv->seek_pos; + cdrom_seek(dev->drv, 0, 0); + scsi_cdrom_set_phase(dev, SCSI_PHASE_STATUS); + break; + + case GPCMD_REQUEST_SENSE: + /* If there's a unit attention condition and there's a buffered not ready, a standalone REQUEST SENSE + should forget about the not ready, and report unit attention straight away. */ + scsi_cdrom_set_phase(dev, SCSI_PHASE_DATA_IN); + max_len = cdb[4]; + + if (!max_len) { + scsi_cdrom_set_phase(dev, SCSI_PHASE_STATUS); + dev->packet_status = PHASE_COMPLETE; + dev->callback = 20.0 * CDROM_TIME; + scsi_cdrom_set_callback(dev); + break; + } + + scsi_cdrom_buf_alloc(dev, 256); + scsi_cdrom_set_buf_len(dev, BufLen, &max_len); + scsi_cdrom_request_sense(dev, dev->buffer, max_len); + scsi_cdrom_data_command_finish(dev, 18, 18, cdb[4], 0); + break; + + case 0xDA: /*GPCMD_SPEED_ALT*/ + switch (dev->drv->type) { + case CDROM_TYPE_NEC_25_10a: + case CDROM_TYPE_NEC_38_103: + case CDROM_TYPE_NEC_75_103: + case CDROM_TYPE_NEC_77_106: + case CDROM_TYPE_NEC_211_100: + case CDROM_TYPE_NEC_464_105: /*GPCMD_STILL_NEC*/ + scsi_cdrom_set_phase(dev, SCSI_PHASE_STATUS); + cdrom_audio_pause_resume(dev->drv, 0x00); + dev->drv->audio_op = 0x01; + scsi_cdrom_command_complete(dev); + break; + } + fallthrough; + case GPCMD_SET_SPEED: + dev->drv->cur_speed = (cdb[3] | (cdb[2] << 8)) / 176; + if (dev->drv->cur_speed < 1) + dev->drv->cur_speed = 1; + else if (dev->drv->cur_speed > dev->drv->speed) + dev->drv->cur_speed = dev->drv->speed; + scsi_cdrom_set_phase(dev, SCSI_PHASE_STATUS); + scsi_cdrom_command_complete(dev); + break; + + case 0xCD: + case GPCMD_AUDIO_SCAN: + scsi_cdrom_set_phase(dev, SCSI_PHASE_STATUS); + + if ((dev->drv->host_drive < 1) || (dev->drv->cd_status <= CD_STATUS_DATA_ONLY)) { + scsi_cdrom_illegal_mode(dev); + break; + } + + pos = (cdb[2] << 24) | (cdb[3] << 16) | (cdb[4] << 8) | cdb[5]; + ret = cdrom_audio_scan(dev->drv, pos, 0); + + if (ret) + scsi_cdrom_command_complete(dev); + else + scsi_cdrom_illegal_mode(dev); + break; + + case GPCMD_MECHANISM_STATUS: + scsi_cdrom_set_phase(dev, SCSI_PHASE_DATA_IN); + len = (cdb[7] << 16) | (cdb[8] << 8) | cdb[9]; + + scsi_cdrom_buf_alloc(dev, 8); + + scsi_cdrom_set_buf_len(dev, BufLen, &len); + + memset(dev->buffer, 0, 8); + dev->buffer[5] = 1; + + scsi_cdrom_data_command_finish(dev, 8, 8, len, 0); + break; + + case GPCMD_READ_TOC_PMA_ATIP: + scsi_cdrom_set_phase(dev, SCSI_PHASE_DATA_IN); + + max_len = cdb[7]; + max_len <<= 8; + max_len |= cdb[8]; + + scsi_cdrom_buf_alloc(dev, 65536); + + toc_format = cdb[2] & 0xf; + + if (toc_format == 0) + toc_format = (cdb[9] >> 6) & 3; + + if (!dev->drv->ops) { + scsi_cdrom_not_ready(dev); + return; + } + + if (toc_format < 3) { + len = cdrom_read_toc(dev->drv, dev->buffer, toc_format, cdb[6], msf, max_len); + if (len == -1) { + /* If the returned length is -1, this means cdrom_read_toc() has encountered an error. */ + scsi_cdrom_invalid_field(dev); + scsi_cdrom_buf_free(dev); + return; + } + } else { + scsi_cdrom_invalid_field(dev); + scsi_cdrom_buf_free(dev); + return; + } + scsi_cdrom_set_buf_len(dev, BufLen, &len); + + scsi_cdrom_data_command_finish(dev, len, len, len, 0); + return; + + case 0xC7: + switch (dev->drv->type) { + case CDROM_TYPE_MATSHITA_501_10b: /*GPCMD_PLAY_AUDIO_MSF_MATSUSHITA*/ + cdb[0] = GPCMD_PLAY_AUDIO_MSF; + dev->current_cdb[0] = cdb[0]; + goto begin; + break; + case CDROM_TYPE_DEC_RRD45_0436: + case CDROM_TYPE_SONY_CDU541_10i: + case CDROM_TYPE_SONY_CDU561_18k: + case CDROM_TYPE_SONY_CDU76S_100: + case CDROM_TYPE_TEXEL_DMXX24_100: /*GPCMD_PLAY_MSF_SONY*/ + cdb[0] = GPCMD_PLAY_AUDIO_MSF; + dev->current_cdb[0] = cdb[0]; + dev->sony_vendor = 1; + goto begin; + break; + case CDROM_TYPE_TOSHIBA_XM_3433: + case CDROM_TYPE_TOSHIBA_XM3201B_3232: + case CDROM_TYPE_TOSHIBA_XM3301TA_0272: + case CDROM_TYPE_TOSHIBA_XM5701TA_3136: + case CDROM_TYPE_TOSHIBA_SDM1401_1008: /*GPCMD_READ_DISC_INFORMATION_TOSHIBA*/ + scsi_cdrom_set_phase(dev, SCSI_PHASE_DATA_IN); + scsi_cdrom_buf_alloc(dev, 4); + + if (!dev->drv->ops) { + scsi_cdrom_not_ready(dev); + return; + } + + ret = cdrom_read_disc_info_toc(dev->drv, dev->buffer, cdb[2], cdb[1] & 3); + len = 4; + if (!ret) { + scsi_cdrom_invalid_field(dev); + scsi_cdrom_buf_free(dev); + return; + } + + scsi_cdrom_set_buf_len(dev, BufLen, &len); + scsi_cdrom_data_command_finish(dev, len, len, len, 0); + return; + default: + scsi_cdrom_illegal_opcode(dev); + break; + } + break; + + case 0xDE: + switch (dev->drv->type) { + case CDROM_TYPE_NEC_25_10a: + case CDROM_TYPE_NEC_38_103: + case CDROM_TYPE_NEC_75_103: + case CDROM_TYPE_NEC_77_106: + case CDROM_TYPE_NEC_211_100: + case CDROM_TYPE_NEC_464_105: /*GPCMD_READ_DISC_INFORMATION_NEC*/ + scsi_cdrom_set_phase(dev, SCSI_PHASE_DATA_IN); + scsi_cdrom_buf_alloc(dev, 22); /*NEC manual claims 4 bytes, but the Android source code (namely sr_vendor.c) actually states otherwise.*/ + + if (!dev->drv->ops) { + scsi_cdrom_not_ready(dev); + return; + } + + ret = cdrom_read_disc_info_toc(dev->drv, dev->buffer, cdb[2], cdb[1] & 3); + len = 22; + if (!ret) { + scsi_cdrom_invalid_field(dev); + scsi_cdrom_buf_free(dev); + return; + } + + scsi_cdrom_set_buf_len(dev, BufLen, &len); + scsi_cdrom_data_command_finish(dev, len, len, len, 0); + return; + default: + scsi_cdrom_illegal_opcode(dev); + break; + } + break; + case GPCMD_READ_CD_OLD: + /* IMPORTANT: Convert the command to new read CD + for pass through purposes. */ + dev->current_cdb[0] = GPCMD_READ_CD; + fallthrough; + + case GPCMD_READ_6: + case GPCMD_READ_10: + case GPCMD_READ_12: + case GPCMD_READ_CD: + case GPCMD_READ_CD_MSF: + scsi_cdrom_set_phase(dev, SCSI_PHASE_DATA_IN); + alloc_length = 2048; + + switch (cdb[0]) { + case GPCMD_READ_6: + dev->sector_len = cdb[4]; + if (dev->sector_len == 0) + dev->sector_len = 256; /* For READ (6) and WRITE (6), a length of 0 indicates a transfer of 256 sector. */ + dev->sector_pos = ((((uint32_t) cdb[1]) & 0x1f) << 16) | (((uint32_t) cdb[2]) << 8) | ((uint32_t) cdb[3]); + msf = 0; + break; + case GPCMD_READ_10: + dev->sector_len = (cdb[7] << 8) | cdb[8]; + dev->sector_pos = (cdb[2] << 24) | (cdb[3] << 16) | (cdb[4] << 8) | cdb[5]; + scsi_cdrom_log("CD-ROM %i: Length: %i, LBA: %i\n", dev->id, dev->sector_len, + dev->sector_pos); + msf = 0; + break; + case GPCMD_READ_12: + dev->sector_len = (((uint32_t) cdb[6]) << 24) | (((uint32_t) cdb[7]) << 16) | (((uint32_t) cdb[8]) << 8) | ((uint32_t) cdb[9]); + dev->sector_pos = (((uint32_t) cdb[2]) << 24) | (((uint32_t) cdb[3]) << 16) | (((uint32_t) cdb[4]) << 8) | ((uint32_t) cdb[5]); + scsi_cdrom_log("CD-ROM %i: Length: %i, LBA: %i\n", dev->id, dev->sector_len, + dev->sector_pos); + msf = 0; + break; + case GPCMD_READ_CD_MSF: + alloc_length = 2856; + dev->sector_len = MSFtoLBA(cdb[6], cdb[7], cdb[8]); + dev->sector_pos = MSFtoLBA(cdb[3], cdb[4], cdb[5]); + + dev->sector_len -= dev->sector_pos; + dev->sector_len++; + + msf = 1; + + if ((cdb[9] & 0xf8) == 0x08) { + /* 0x08 is an illegal mode */ + scsi_cdrom_invalid_field(dev); + return; + } + + /* If all the flag bits are cleared, then treat it as a non-data command. */ + if ((cdb[9] == 0x00) && ((cdb[10] & 0x07) == 0x00)) + dev->sector_len = 0; + else if ((cdb[9] == 0x00) && ((cdb[10] & 0x07) != 0x00)) { + scsi_cdrom_invalid_field(dev); + return; + } + break; + case GPCMD_READ_CD_OLD: + case GPCMD_READ_CD: + alloc_length = 2856; + dev->sector_len = (cdb[6] << 16) | (cdb[7] << 8) | cdb[8]; + dev->sector_pos = (cdb[2] << 24) | (cdb[3] << 16) | (cdb[4] << 8) | cdb[5]; + + msf = 0; + + if ((cdb[9] & 0xf8) == 0x08) { + /* 0x08 is an illegal mode */ + scsi_cdrom_invalid_field(dev); + return; + } + + /* If all the flag bits are cleared, then treat it as a non-data command. */ + if ((cdb[9] == 0x00) && ((cdb[10] & 0x07) == 0x00)) + dev->sector_len = 0; + else if ((cdb[9] == 0x00) && ((cdb[10] & 0x07) != 0x00)) { + scsi_cdrom_invalid_field(dev); + return; + } + break; + + default: + break; + } + + if (!dev->sector_len) { + scsi_cdrom_set_phase(dev, SCSI_PHASE_STATUS); + /* scsi_cdrom_log("CD-ROM %i: All done - callback set\n", dev->id); */ + dev->packet_status = PHASE_COMPLETE; + dev->callback = 20.0 * CDROM_TIME; + scsi_cdrom_set_callback(dev); + break; + } + + max_len = dev->sector_len; + dev->requested_blocks = max_len; /* If we're reading all blocks in one go for DMA, why not also for PIO, it should NOT + matter anyway, this step should be identical and only the way the read dat is + transferred to the host should be different. */ + + dev->packet_len = max_len * alloc_length; + scsi_cdrom_buf_alloc(dev, dev->packet_len); + + dev->drv->seek_diff = ABS((int) (pos - dev->sector_pos)); + + if ((cdb[0] == GPCMD_READ_10) || (cdb[0] == GPCMD_READ_12)) { + switch (dev->drv->type) { + case CDROM_TYPE_NEC_25_10a: + case CDROM_TYPE_NEC_38_103: + case CDROM_TYPE_NEC_75_103: + case CDROM_TYPE_NEC_77_106: + case CDROM_TYPE_NEC_211_100: + case CDROM_TYPE_NEC_464_105: + case CDROM_TYPE_TOSHIBA_XM_3433: + case CDROM_TYPE_TOSHIBA_XM3201B_3232: + case CDROM_TYPE_TOSHIBA_XM3301TA_0272: + case CDROM_TYPE_TOSHIBA_XM5701TA_3136: + case CDROM_TYPE_TOSHIBA_SDM1401_1008: + ret = scsi_cdrom_read_blocks(dev, &alloc_length, 1, cdb[9] & 0xc0); + break; + default: + ret = scsi_cdrom_read_blocks(dev, &alloc_length, 1, 0); + break; + } + } else + ret = scsi_cdrom_read_blocks(dev, &alloc_length, 1, 0); + + if (ret <= 0) { + scsi_cdrom_set_phase(dev, SCSI_PHASE_STATUS); + dev->packet_status = PHASE_COMPLETE; + dev->callback = 20.0 * CDROM_TIME; + scsi_cdrom_set_callback(dev); + scsi_cdrom_buf_free(dev); + return; + } + + dev->requested_blocks = max_len; + dev->packet_len = alloc_length; + + scsi_cdrom_set_buf_len(dev, BufLen, (int32_t *) &dev->packet_len); + + scsi_cdrom_data_command_finish(dev, alloc_length, alloc_length / dev->requested_blocks, + alloc_length, 0); + + if (dev->packet_status != PHASE_COMPLETE) + ui_sb_update_icon(SB_CDROM | dev->id, 1); + else + ui_sb_update_icon(SB_CDROM | dev->id, 0); + return; + + case GPCMD_READ_HEADER: + scsi_cdrom_set_phase(dev, SCSI_PHASE_DATA_IN); + + alloc_length = ((cdb[7] << 8) | cdb[8]); + scsi_cdrom_buf_alloc(dev, 8); + + dev->sector_len = 1; + dev->sector_pos = (cdb[2] << 24) | (cdb[3] << 16) | (cdb[4] << 8) | cdb[5]; + if (msf) + real_pos = cdrom_lba_to_msf_accurate(dev->sector_pos); + else + real_pos = dev->sector_pos; + dev->buffer[0] = 1; /*2048 bytes user data*/ + dev->buffer[1] = dev->buffer[2] = dev->buffer[3] = 0; + dev->buffer[4] = (real_pos >> 24); + dev->buffer[5] = ((real_pos >> 16) & 0xff); + dev->buffer[6] = ((real_pos >> 8) & 0xff); + dev->buffer[7] = real_pos & 0xff; + + len = 8; + len = MIN(len, alloc_length); + + scsi_cdrom_set_buf_len(dev, BufLen, &len); + + scsi_cdrom_data_command_finish(dev, len, len, len, 0); + return; + + case GPCMD_MODE_SENSE_6: + case GPCMD_MODE_SENSE_10: + scsi_cdrom_set_phase(dev, SCSI_PHASE_DATA_IN); + + if (dev->drv->bus_type == CDROM_BUS_SCSI) + block_desc = ((cdb[1] >> 3) & 1) ? 0 : 1; + else + block_desc = 0; + + if (cdb[0] == GPCMD_MODE_SENSE_6) { + len = cdb[4]; + scsi_cdrom_buf_alloc(dev, 256); + } else { + len = (cdb[8] | (cdb[7] << 8)); + scsi_cdrom_buf_alloc(dev, 65536); + } + + switch (dev->drv->type) { + case CDROM_TYPE_DEC_RRD45_0436: + case CDROM_TYPE_SONY_CDU541_10i: + case CDROM_TYPE_SONY_CDU561_18k: + case CDROM_TYPE_SONY_CDU76S_100: + case CDROM_TYPE_TEXEL_DMXX24_100: + if (!(scsi_cdrom_mode_sense_page_flags_sony & (1LL << (uint64_t) (cdb[2] & 0x3f)))) { + scsi_cdrom_invalid_field(dev); + scsi_cdrom_buf_free(dev); + return; + } + break; + default: + if (!(scsi_cdrom_mode_sense_page_flags & (1LL << (uint64_t) (cdb[2] & 0x3f)))) { + scsi_cdrom_invalid_field(dev); + scsi_cdrom_buf_free(dev); + return; + } + break; + } + memset(dev->buffer, 0, len); + alloc_length = len; + + /* This determines the media type ID to return - this is + a SCSI/ATAPI-specific thing, so it makes the most sense + to keep this here. + Also, the max_len variable is reused as this command + does otherwise not use it, to avoid having to declare + another variable. */ + if (dev->drv->cd_status == CD_STATUS_EMPTY) + max_len = 70; /* No media inserted. */ + else if (dev->drv->cdrom_capacity > CD_MAX_SECTORS) + max_len = 65; /* DVD. */ + else if (dev->drv->cd_status == CD_STATUS_DATA_ONLY) + max_len = 1; /* Data CD. */ + else + max_len = 3; /* Audio or mixed-mode CD. */ + + if (cdb[0] == GPCMD_MODE_SENSE_6) { + len = scsi_cdrom_mode_sense(dev, dev->buffer, 4, cdb[2], block_desc); + len = MIN(len, alloc_length); + dev->buffer[0] = len - 1; + dev->buffer[1] = max_len; + if (block_desc) + dev->buffer[3] = 8; + } else { + len = scsi_cdrom_mode_sense(dev, dev->buffer, 8, cdb[2], block_desc); + len = MIN(len, alloc_length); + dev->buffer[0] = (len - 2) >> 8; + dev->buffer[1] = (len - 2) & 255; + dev->buffer[2] = max_len; + if (block_desc) { + dev->buffer[6] = 0; + dev->buffer[7] = 8; + } + } + + scsi_cdrom_set_buf_len(dev, BufLen, &len); + + scsi_cdrom_log("CD-ROM %i: Reading mode page: %02X...\n", dev->id, cdb[2]); + + scsi_cdrom_data_command_finish(dev, len, len, alloc_length, 0); + return; + + case GPCMD_MODE_SELECT_6: + case GPCMD_MODE_SELECT_10: + scsi_cdrom_set_phase(dev, SCSI_PHASE_DATA_OUT); + + if (cdb[0] == GPCMD_MODE_SELECT_6) { + len = cdb[4]; + scsi_cdrom_buf_alloc(dev, 256); + } else { + len = (cdb[7] << 8) | cdb[8]; + scsi_cdrom_buf_alloc(dev, 65536); + } + + scsi_cdrom_set_buf_len(dev, BufLen, &len); + + dev->total_length = len; + dev->do_page_save = cdb[1] & 1; + + scsi_cdrom_data_command_finish(dev, len, len, len, 1); + return; + + case GPCMD_GET_CONFIGURATION: + scsi_cdrom_set_phase(dev, SCSI_PHASE_DATA_IN); + + /* XXX: could result in alignment problems in some architectures */ + feature = (cdb[2] << 8) | cdb[3]; + max_len = (cdb[7] << 8) | cdb[8]; + + /* only feature 0 is supported */ + if ((cdb[2] != 0) || (cdb[3] > 2)) { + scsi_cdrom_invalid_field(dev); + scsi_cdrom_buf_free(dev); + return; + } + + scsi_cdrom_buf_alloc(dev, 65536); + memset(dev->buffer, 0, max_len); + + alloc_length = 0; + b = dev->buffer; + + /* + * the number of sectors from the media tells us which profile + * to use as current. 0 means there is no media + */ + if (dev->drv->cd_status != CD_STATUS_EMPTY) { + len = dev->drv->cdrom_capacity; + if (len > CD_MAX_SECTORS) { + b[6] = (MMC_PROFILE_DVD_ROM >> 8) & 0xff; + b[7] = MMC_PROFILE_DVD_ROM & 0xff; + ret = 1; + } else { + b[6] = (MMC_PROFILE_CD_ROM >> 8) & 0xff; + b[7] = MMC_PROFILE_CD_ROM & 0xff; + ret = 0; + } + } else + ret = 2; + + alloc_length = 8; + b += 8; + + if ((feature == 0) || ((cdb[1] & 3) < 2)) { + b[2] = (0 << 2) | 0x02 | 0x01; /* persistent and current */ + b[3] = 8; + + alloc_length += 4; + b += 4; + + for (uint8_t i = 0; i < 2; i++) { + b[0] = (profiles[i] >> 8) & 0xff; + b[1] = profiles[i] & 0xff; + + if (ret == i) + b[2] |= 1; + + alloc_length += 4; + b += 4; + } + } + if ((feature == 1) || ((cdb[1] & 3) < 2)) { + b[1] = 1; + b[2] = (2 << 2) | 0x02 | 0x01; /* persistent and current */ + b[3] = 8; + + if (dev->drv->bus_type == CDROM_BUS_SCSI) + b[7] = 1; + else + b[7] = 2; + b[8] = 1; + + alloc_length += 12; + b += 12; + } + if ((feature == 2) || ((cdb[1] & 3) < 2)) { + b[1] = 2; + b[2] = (1 << 2) | 0x02 | 0x01; /* persistent and current */ + b[3] = 4; + + b[4] = 2; + + alloc_length += 8; + b += 8; + } + + dev->buffer[0] = ((alloc_length - 4) >> 24) & 0xff; + dev->buffer[1] = ((alloc_length - 4) >> 16) & 0xff; + dev->buffer[2] = ((alloc_length - 4) >> 8) & 0xff; + dev->buffer[3] = (alloc_length - 4) & 0xff; + + alloc_length = MIN(alloc_length, max_len); + + scsi_cdrom_set_buf_len(dev, BufLen, &alloc_length); + + scsi_cdrom_data_command_finish(dev, alloc_length, alloc_length, alloc_length, 0); + break; + + case GPCMD_GET_EVENT_STATUS_NOTIFICATION: + scsi_cdrom_set_phase(dev, SCSI_PHASE_DATA_IN); + + scsi_cdrom_buf_alloc(dev, 8 + sizeof(gesn_event_header_t)); + + gesn_cdb = (void *) cdb; + gesn_event_header = (void *) dev->buffer; + + /* It is fine by the MMC spec to not support async mode operations. */ + if (!(gesn_cdb->polled & 0x01)) { + /* asynchronous mode */ + /* Only polling is supported, asynchronous mode is not. */ + scsi_cdrom_invalid_field(dev); + scsi_cdrom_buf_free(dev); + return; + } + + /* + * These are the supported events. + * + * We currently only support requests of the 'media' type. + * Notification class requests and supported event classes are bitmasks, + * but they are built from the same values as the "notification class" + * field. + */ + gesn_event_header->supported_events = 1 << GESN_MEDIA; + + /* + * We use |= below to set the class field; other bits in this byte + * are reserved now but this is useful to do if we have to use the + * reserved fields later. + */ + gesn_event_header->notification_class = 0; + + /* + * Responses to requests are to be based on request priority. The + * notification_class_request_type enum above specifies the + * priority: upper elements are higher prio than lower ones. + */ + if (gesn_cdb->class & (1 << GESN_MEDIA)) { + gesn_event_header->notification_class |= GESN_MEDIA; + + dev->buffer[4] = dev->media_status; /* Bits 7-4 = Reserved, Bits 4-1 = Media Status */ + dev->buffer[5] = 1; /* Power Status (1 = Active) */ + dev->buffer[6] = 0; + dev->buffer[7] = 0; + used_len = 8; + } else { + gesn_event_header->notification_class = 0x80; /* No event available */ + used_len = sizeof(*gesn_event_header); + } + gesn_event_header->len = used_len - sizeof(*gesn_event_header); + + memmove(dev->buffer, gesn_event_header, 4); + + scsi_cdrom_set_buf_len(dev, BufLen, &used_len); + + scsi_cdrom_data_command_finish(dev, used_len, used_len, used_len, 0); + break; + + case GPCMD_READ_DISC_INFORMATION: + scsi_cdrom_set_phase(dev, SCSI_PHASE_DATA_IN); + + max_len = cdb[7]; + max_len <<= 8; + max_len |= cdb[8]; + + scsi_cdrom_buf_alloc(dev, 65536); + + memset(dev->buffer, 0, 34); + memset(dev->buffer, 1, 9); + dev->buffer[0] = 0; + dev->buffer[1] = 32; + dev->buffer[2] = 0xe; /* last session complete, disc finalized */ + dev->buffer[7] = 0x20; /* unrestricted use */ + dev->buffer[8] = 0x00; /* CD-ROM */ + + len = 34; + len = MIN(len, max_len); + + scsi_cdrom_set_buf_len(dev, BufLen, &len); + + scsi_cdrom_data_command_finish(dev, len, len, len, 0); + break; + + case GPCMD_READ_TRACK_INFORMATION: + scsi_cdrom_set_phase(dev, SCSI_PHASE_DATA_IN); + + max_len = cdb[7]; + max_len <<= 8; + max_len |= cdb[8]; + + scsi_cdrom_buf_alloc(dev, 65536); + + track = ((uint32_t) cdb[2]) << 24; + track |= ((uint32_t) cdb[3]) << 16; + track |= ((uint32_t) cdb[4]) << 8; + track |= (uint32_t) cdb[5]; + + if (((cdb[1] & 0x03) != 1) || (track != 1)) { + scsi_cdrom_invalid_field(dev); + scsi_cdrom_buf_free(dev); + return; + } + + len = 36; + + memset(dev->buffer, 0, 36); + dev->buffer[0] = 0; + dev->buffer[1] = 34; + dev->buffer[2] = 1; /* track number (LSB) */ + dev->buffer[3] = 1; /* session number (LSB) */ + dev->buffer[5] = (0 << 5) | (0 << 4) | (4 << 0); /* not damaged, primary copy, data track */ + dev->buffer[6] = (0 << 7) | (0 << 6) | (0 << 5) | (0 << 6) | (1 << 0); /* not reserved track, not blank, not packet writing, not fixed packet, data mode 1 */ + dev->buffer[7] = (0 << 1) | (0 << 0); /* last recorded address not valid, next recordable address not valid */ + + dev->buffer[24] = ((dev->drv->cdrom_capacity - 1) >> 24) & 0xff; /* track size */ + dev->buffer[25] = ((dev->drv->cdrom_capacity - 1) >> 16) & 0xff; /* track size */ + dev->buffer[26] = ((dev->drv->cdrom_capacity - 1) >> 8) & 0xff; /* track size */ + dev->buffer[27] = (dev->drv->cdrom_capacity - 1) & 0xff; /* track size */ + + if (len > max_len) { + len = max_len; + dev->buffer[0] = ((max_len - 2) >> 8) & 0xff; + dev->buffer[1] = (max_len - 2) & 0xff; + } + + scsi_cdrom_set_buf_len(dev, BufLen, &len); + + scsi_cdrom_data_command_finish(dev, len, len, max_len, 0); + break; + + case 0xC0: + switch (dev->drv->type) { + case CDROM_TYPE_DEC_RRD45_0436: + case CDROM_TYPE_SONY_CDU541_10i: + case CDROM_TYPE_SONY_CDU561_18k: + case CDROM_TYPE_SONY_CDU76S_100: + case CDROM_TYPE_TEXEL_DMXX24_100: /*GPCMD_SET_ADDRESS_FORMAT_SONY*/ + scsi_cdrom_set_phase(dev, SCSI_PHASE_STATUS); + dev->sony_vendor = 1; + dev->drv->sony_msf = cdb[8] & 1; + scsi_cdrom_command_complete(dev); + break; + case CDROM_TYPE_PIONEER_DRM604X_2403: /*GPCMD_MAGAZINE_EJECT_PIONEER*/ + case CDROM_TYPE_CHINON_CDS431_H42: /*GPCMD_EJECT_CHINON*/ + scsi_cdrom_set_phase(dev, SCSI_PHASE_STATUS); + scsi_cdrom_stop(sc); + cdrom_eject(dev->id); + scsi_cdrom_command_complete(dev); + break; + case CDROM_TYPE_TOSHIBA_XM_3433: + case CDROM_TYPE_TOSHIBA_XM3201B_3232: + case CDROM_TYPE_TOSHIBA_XM3301TA_0272: + case CDROM_TYPE_TOSHIBA_XM5701TA_3136: + case CDROM_TYPE_TOSHIBA_SDM1401_1008: /*GPCMD_AUDIO_TRACK_SEARCH_TOSHIBA*/ + scsi_cdrom_set_phase(dev, SCSI_PHASE_STATUS); + if ((dev->drv->host_drive < 1) || (dev->drv->cd_status <= CD_STATUS_DATA_ONLY)) { + scsi_cdrom_illegal_mode(dev); + break; + } + pos = (cdb[2] << 24) | (cdb[3] << 16) | (cdb[4] << 8) | cdb[5]; + ret = cdrom_audio_track_search(dev->drv, pos, cdb[9] & 0xc0, cdb[1] & 1); + dev->drv->audio_op = (cdb[1] & 1) ? 0x03 : 0x02; + + if (ret) + scsi_cdrom_command_complete(dev); + else + scsi_cdrom_illegal_mode(dev); + break; + default: + scsi_cdrom_illegal_opcode(dev); + break; + } + break; + + case 0xD8: + switch (dev->drv->type) { + case CDROM_TYPE_NEC_25_10a: + case CDROM_TYPE_NEC_38_103: + case CDROM_TYPE_NEC_75_103: + case CDROM_TYPE_NEC_77_106: + case CDROM_TYPE_NEC_211_100: + case CDROM_TYPE_NEC_464_105: /*GPCMD_AUDIO_TRACK_SEARCH_NEC*/ + scsi_cdrom_set_phase(dev, SCSI_PHASE_STATUS); + if ((dev->drv->host_drive < 1) || (dev->drv->cd_status <= CD_STATUS_DATA_ONLY)) { + scsi_cdrom_illegal_mode(dev); + break; + } + pos = (cdb[2] << 24) | (cdb[3] << 16) | (cdb[4] << 8) | cdb[5]; + ret = cdrom_audio_track_search(dev->drv, pos, cdb[9] & 0xc0, cdb[1] & 1); + dev->drv->audio_op = (cdb[1] & 1) ? 0x03 : 0x02; + + if (ret) + scsi_cdrom_command_complete(dev); + else + scsi_cdrom_illegal_mode(dev); + break; + default: + scsi_cdrom_illegal_opcode(dev); + break; + } + break; + + case 0xC1: + switch (dev->drv->type) { + case CDROM_TYPE_DEC_RRD45_0436: + case CDROM_TYPE_SONY_CDU541_10i: + case CDROM_TYPE_SONY_CDU561_18k: + case CDROM_TYPE_SONY_CDU76S_100: + case CDROM_TYPE_TEXEL_DMXX24_100: /*GPCMD_READ_TOC_SONY*/ + scsi_cdrom_set_phase(dev, SCSI_PHASE_DATA_IN); + msf = dev->ms_pages_saved_sony.pages[GPMODE_CDROM_PAGE_SONY][2] & 0x01; + dev->sony_vendor = 1; + + max_len = cdb[7]; + max_len <<= 8; + max_len |= cdb[8]; + + scsi_cdrom_buf_alloc(dev, 65536); + + if (!dev->drv->ops) { + scsi_cdrom_not_ready(dev); + return; + } + + len = cdrom_read_toc_sony(dev->drv, dev->buffer, cdb[5], msf || dev->drv->sony_msf, max_len); + if (len == -1) { + /* If the returned length is -1, this means cdrom_read_toc_sony() has encountered an error. */ + scsi_cdrom_invalid_field(dev); + scsi_cdrom_buf_free(dev); + return; + } + + scsi_cdrom_set_buf_len(dev, BufLen, &len); + + scsi_cdrom_data_command_finish(dev, len, len, len, 0); + return; + case CDROM_TYPE_PIONEER_DRM604X_2403: /*GPCMD_READ_TOC_PIONEER*/ + scsi_cdrom_set_phase(dev, SCSI_PHASE_DATA_IN); + scsi_cdrom_buf_alloc(dev, 4); + + if (!dev->drv->ops) { + scsi_cdrom_not_ready(dev); + return; + } + + ret = cdrom_read_disc_info_toc(dev->drv, dev->buffer, cdb[2], cdb[1] & 3); + len = 4; + if (!ret) { + scsi_cdrom_invalid_field(dev); + scsi_cdrom_buf_free(dev); + return; + } + + scsi_cdrom_set_buf_len(dev, BufLen, &len); + scsi_cdrom_data_command_finish(dev, len, len, len, 0); + return; + case CDROM_TYPE_TOSHIBA_XM_3433: + case CDROM_TYPE_TOSHIBA_XM3201B_3232: + case CDROM_TYPE_TOSHIBA_XM3301TA_0272: + case CDROM_TYPE_TOSHIBA_XM5701TA_3136: + case CDROM_TYPE_TOSHIBA_SDM1401_1008: /*GPCMD_PLAY_AUDIO_TOSHIBA*/ + scsi_cdrom_set_phase(dev, SCSI_PHASE_STATUS); + if ((dev->drv->host_drive < 1) || (dev->drv->cd_status <= CD_STATUS_DATA_ONLY)) { + scsi_cdrom_illegal_mode(dev); + break; + } + pos = (cdb[2] << 24) | (cdb[3] << 16) | (cdb[4] << 8) | cdb[5]; + ret = cdrom_audio_play_toshiba(dev->drv, pos, cdb[9] & 0xc0); + + if (ret) + scsi_cdrom_command_complete(dev); + else + scsi_cdrom_illegal_mode(dev); + break; + default: + scsi_cdrom_illegal_opcode(dev); + break; + } + break; + + case 0xD9: + switch (dev->drv->type) { + case CDROM_TYPE_NEC_25_10a: + case CDROM_TYPE_NEC_38_103: + case CDROM_TYPE_NEC_75_103: + case CDROM_TYPE_NEC_77_106: + case CDROM_TYPE_NEC_211_100: + case CDROM_TYPE_NEC_464_105: /*GPCMD_PLAY_AUDIO_NEC*/ + scsi_cdrom_set_phase(dev, SCSI_PHASE_STATUS); + if ((dev->drv->host_drive < 1) || (dev->drv->cd_status <= CD_STATUS_DATA_ONLY)) { + scsi_cdrom_illegal_mode(dev); + break; + } + pos = (cdb[2] << 24) | (cdb[3] << 16) | (cdb[4] << 8) | cdb[5]; + ret = cdrom_audio_play_toshiba(dev->drv, pos, cdb[9] & 0xc0); + + if (ret) + scsi_cdrom_command_complete(dev); + else + scsi_cdrom_illegal_mode(dev); + break; + default: + scsi_cdrom_illegal_opcode(dev); + break; + } + break; + + case GPCMD_PLAY_AUDIO_10: + case GPCMD_PLAY_AUDIO_12: + case GPCMD_PLAY_AUDIO_MSF: + case GPCMD_PLAY_AUDIO_TRACK_INDEX: + case GPCMD_PLAY_AUDIO_TRACK_RELATIVE_10: + case GPCMD_PLAY_AUDIO_TRACK_RELATIVE_12: + len = 0; + + scsi_cdrom_set_phase(dev, SCSI_PHASE_STATUS); + + switch (cdb[0]) { + case GPCMD_PLAY_AUDIO_10: + msf = 0; + pos = (cdb[2] << 24) | (cdb[3] << 16) | (cdb[4] << 8) | cdb[5]; + len = (cdb[7] << 8) | cdb[8]; + break; + case GPCMD_PLAY_AUDIO_12: + msf = 0; + pos = (cdb[2] << 24) | (cdb[3] << 16) | (cdb[4] << 8) | cdb[5]; + len = (cdb[6] << 24) | (cdb[7] << 16) | (cdb[8] << 8) | cdb[9]; + break; + case GPCMD_PLAY_AUDIO_MSF: + msf = 1; + pos = (cdb[3] << 16) | (cdb[4] << 8) | cdb[5]; + len = (cdb[6] << 16) | (cdb[7] << 8) | cdb[8]; + break; + case GPCMD_PLAY_AUDIO_TRACK_INDEX: + msf = 2; + if ((cdb[5] != 1) || (cdb[8] != 1)) { + scsi_cdrom_illegal_mode(dev); + break; + } + pos = cdb[4]; + len = cdb[7]; + break; + case GPCMD_PLAY_AUDIO_TRACK_RELATIVE_10: + msf = 0x100 | cdb[6]; + pos = (cdb[2] << 24) | (cdb[3] << 16) | (cdb[4] << 8) | cdb[5]; + len = (cdb[7] << 8) | cdb[8]; + break; + case GPCMD_PLAY_AUDIO_TRACK_RELATIVE_12: + msf = 0x100 | cdb[10]; + pos = (cdb[2] << 24) | (cdb[3] << 16) | (cdb[4] << 8) | cdb[5]; + len = (cdb[6] << 24) | (cdb[7] << 16) | (cdb[8] << 8) | cdb[9]; + break; + + default: + break; + } + + if ((dev->drv->host_drive < 1) || (dev->drv->cd_status <= CD_STATUS_DATA_ONLY)) { + scsi_cdrom_illegal_mode(dev); + break; + } + + ret = cdrom_audio_play(dev->drv, pos, len, msf); + + if (ret) + scsi_cdrom_command_complete(dev); + else + scsi_cdrom_illegal_mode(dev); + break; + + case GPCMD_READ_SUBCHANNEL: + scsi_cdrom_set_phase(dev, SCSI_PHASE_DATA_IN); + + max_len = cdb[7]; + max_len <<= 8; + max_len |= cdb[8]; + msf = (cdb[1] >> 1) & 1; + + scsi_cdrom_buf_alloc(dev, 32); + + scsi_cdrom_log("CD-ROM %i: Getting page %i (%s)\n", dev->id, cdb[3], msf ? "MSF" : "LBA"); + + if (cdb[3] > 3) { + /* scsi_cdrom_log("CD-ROM %i: Read subchannel check condition %02X\n", dev->id, + cdb[3]); */ + scsi_cdrom_invalid_field(dev); + scsi_cdrom_buf_free(dev); + return; + } + + if (!(cdb[2] & 0x40)) + alloc_length = 4; + else + switch (cdb[3]) { + case 0: + /* SCSI-2: Q-type subchannel, ATAPI: reserved */ + alloc_length = (dev->drv->bus_type == CDROM_BUS_SCSI) ? 48 : 4; + break; + case 1: + alloc_length = 16; + break; + default: + alloc_length = 24; + break; + } + + len = alloc_length; + + memset(dev->buffer, 0, 24); + pos = 0; + dev->buffer[pos++] = 0; + dev->buffer[pos++] = 0; /*Audio status*/ + dev->buffer[pos++] = 0; + dev->buffer[pos++] = 0; /*Subchannel length*/ + /* Mode 0 = Q subchannel mode, first 16 bytes are indentical to mode 1 (current position), + the rest are stuff like ISRC etc., which can be all zeroes. */ + if (cdb[3] <= 3) { + dev->buffer[pos++] = cdb[3]; /*Format code*/ + + if (alloc_length != 4) { + dev->buffer[1] = cdrom_get_current_subchannel(dev->drv, &dev->buffer[4], msf); + dev->buffer[2] = alloc_length - 4; + } + + switch (dev->drv->cd_status) { + case CD_STATUS_PLAYING: + dev->buffer[1] = 0x11; + break; + case CD_STATUS_PAUSED: + dev->buffer[1] = (dev->drv->type == CDROM_TYPE_CHINON_CDS431_H42) ? 0x15 : 0x12; + break; + case CD_STATUS_DATA_ONLY: + dev->buffer[1] = (dev->drv->type == CDROM_TYPE_CHINON_CDS431_H42) ? 0x00 : 0x15; + break; + default: + dev->buffer[1] = (dev->drv->type == CDROM_TYPE_CHINON_CDS431_H42) ? 0x00 : 0x13; + break; + } + + scsi_cdrom_log("Audio Status = %02x\n", dev->buffer[1]); + } + + len = MIN(len, max_len); + scsi_cdrom_set_buf_len(dev, BufLen, &len); + + scsi_cdrom_data_command_finish(dev, len, len, len, 0); + break; + + case 0xC6: + switch (dev->drv->type) { + case CDROM_TYPE_DEC_RRD45_0436: + case CDROM_TYPE_SONY_CDU541_10i: + case CDROM_TYPE_SONY_CDU561_18k: + case CDROM_TYPE_SONY_CDU76S_100: + case CDROM_TYPE_TEXEL_DMXX24_100: /*GPCMD_PLAY_TRACK_SONY*/ + scsi_cdrom_set_phase(dev, SCSI_PHASE_STATUS); + dev->sony_vendor = 1; + + msf = 3; + if ((cdb[5] != 1) || (cdb[8] != 1)) { + scsi_cdrom_illegal_mode(dev); + break; + } + pos = cdb[4]; + + if ((dev->drv->host_drive < 1) || (dev->drv->cd_status <= CD_STATUS_DATA_ONLY)) { + scsi_cdrom_illegal_mode(dev); + break; + } + + /* In this case, len is unused so just pass a fixed value of 1 intead. */ + ret = cdrom_audio_play(dev->drv, pos, 1 /*len*/, msf); + + if (ret) + scsi_cdrom_command_complete(dev); + else + scsi_cdrom_illegal_mode(dev); + break; + case CDROM_TYPE_CHINON_CDS431_H42: /*GPCMD_STOP_CHINON*/ + scsi_cdrom_set_phase(dev, SCSI_PHASE_STATUS); + scsi_cdrom_stop(sc); + scsi_cdrom_command_complete(dev); + break; + case CDROM_TYPE_TOSHIBA_XM_3433: + case CDROM_TYPE_TOSHIBA_XM3201B_3232: + case CDROM_TYPE_TOSHIBA_XM3301TA_0272: + case CDROM_TYPE_TOSHIBA_XM5701TA_3136: + case CDROM_TYPE_TOSHIBA_SDM1401_1008: /*GPCMD_READ_SUBCODEQ_PLAYING_STATUS_TOSHIBA*/ + scsi_cdrom_set_phase(dev, SCSI_PHASE_DATA_IN); + + alloc_length = cdb[1] & 0x1f; + len = 10; + + if (!dev->drv->ops) { + scsi_cdrom_not_ready(dev); + return; + } + + if (!alloc_length) { + scsi_cdrom_set_phase(dev, SCSI_PHASE_STATUS); + scsi_cdrom_log("CD-ROM %i: Subcode Q All done - callback set\n", dev->id); + dev->packet_status = PHASE_COMPLETE; + dev->callback = 20.0 * CDROM_TIME; + scsi_cdrom_set_callback(dev); + break; + } + + scsi_cdrom_buf_alloc(dev, len); + len = MIN(len, alloc_length); + + memset(dev->buffer, 0, len); + dev->buffer[0] = cdrom_get_current_subcodeq_playstatus(dev->drv, &dev->buffer[1]); + scsi_cdrom_log("Audio Status = %02x\n", dev->buffer[0]); + + scsi_cdrom_set_buf_len(dev, BufLen, &alloc_length); + scsi_cdrom_data_command_finish(dev, len, len, len, 0); + break; + default: + scsi_cdrom_illegal_opcode(dev); + break; + } + break; + + case 0xDD: + switch (dev->drv->type) { + case CDROM_TYPE_NEC_25_10a: + case CDROM_TYPE_NEC_38_103: + case CDROM_TYPE_NEC_75_103: + case CDROM_TYPE_NEC_77_106: + case CDROM_TYPE_NEC_211_100: + case CDROM_TYPE_NEC_464_105: /*GPCMD_READ_SUBCODEQ_PLAYING_STATUS_NEC*/ + scsi_cdrom_set_phase(dev, SCSI_PHASE_DATA_IN); + + alloc_length = cdb[1] & 0x1f; + len = 10; + + if (!dev->drv->ops) { + scsi_cdrom_not_ready(dev); + return; + } + + if (!alloc_length) { + scsi_cdrom_set_phase(dev, SCSI_PHASE_STATUS); + scsi_cdrom_log("CD-ROM %i: Subcode Q All done - callback set\n", dev->id); + dev->packet_status = PHASE_COMPLETE; + dev->callback = 20.0 * CDROM_TIME; + scsi_cdrom_set_callback(dev); + break; + } + + scsi_cdrom_buf_alloc(dev, len); + len = MIN(len, alloc_length); + + memset(dev->buffer, 0, len); + dev->buffer[0] = cdrom_get_current_subcodeq_playstatus(dev->drv, &dev->buffer[1]); + scsi_cdrom_log("Audio Status = %02x\n", dev->buffer[0]); + + scsi_cdrom_set_buf_len(dev, BufLen, &alloc_length); + scsi_cdrom_data_command_finish(dev, len, len, len, 0); + break; + default: + scsi_cdrom_illegal_opcode(dev); + break; + } + break; + + case GPCMD_READ_DVD_STRUCTURE: + scsi_cdrom_set_phase(dev, SCSI_PHASE_DATA_IN); + + alloc_length = (((uint32_t) cdb[8]) << 8) | ((uint32_t) cdb[9]); + + scsi_cdrom_buf_alloc(dev, alloc_length); + + if ((cdb[7] < 0xc0) && (dev->drv->cdrom_capacity <= CD_MAX_SECTORS)) { + scsi_cdrom_incompatible_format(dev); + scsi_cdrom_buf_free(dev); + return; + } + + memset(dev->buffer, 0, alloc_length); + + if ((cdb[7] <= 0x7f) || (cdb[7] == 0xff)) { + if (cdb[1] == 0) { + ret = scsi_cdrom_read_dvd_structure(dev, format, cdb, dev->buffer); + dev->buffer[0] = (ret >> 8); + dev->buffer[1] = (ret & 0xff); + dev->buffer[2] = dev->buffer[3] = 0x00; + if (ret) { + scsi_cdrom_set_buf_len(dev, BufLen, &alloc_length); + scsi_cdrom_data_command_finish(dev, alloc_length, alloc_length, + alloc_length, 0); + } else + scsi_cdrom_buf_free(dev); + return; + } + } else { + scsi_cdrom_invalid_field(dev); + scsi_cdrom_buf_free(dev); + return; + } + break; + + case 0x26: + if (dev->drv->type == CDROM_TYPE_CHINON_CDS431_H42) { /*GPCMD_UNKNOWN_CHINON*/ + scsi_cdrom_set_phase(dev, SCSI_PHASE_STATUS); + scsi_cdrom_stop(sc); + scsi_cdrom_command_complete(dev); + } else { + scsi_cdrom_illegal_opcode(dev); + } + break; + + case GPCMD_START_STOP_UNIT: + scsi_cdrom_set_phase(dev, SCSI_PHASE_STATUS); + + switch (cdb[4] & 3) { + case 0: /* Stop the disc. */ + scsi_cdrom_stop(sc); + break; + case 1: /* Start the disc and read the TOC. */ + /* This makes no sense under emulation as this would do + absolutely nothing, so just break. */ + break; + case 2: /* Eject the disc if possible. */ + scsi_cdrom_stop(sc); + cdrom_eject(dev->id); + break; + case 3: /* Load the disc (close tray). */ + cdrom_reload(dev->id); + break; + + default: + break; + } + + scsi_cdrom_command_complete(dev); + break; + + case 0xC4: + switch (dev->drv->type) { + case CDROM_TYPE_MATSHITA_501_10b: /*GPCMD_READ_HEADER_MATSUSHITA*/ + cdb[0] = GPCMD_READ_HEADER; + dev->current_cdb[0] = cdb[0]; + goto begin; + break; + case CDROM_TYPE_DEC_RRD45_0436: + case CDROM_TYPE_SONY_CDU541_10i: + case CDROM_TYPE_SONY_CDU561_18k: + case CDROM_TYPE_SONY_CDU76S_100: + case CDROM_TYPE_TEXEL_DMXX24_100: /*GPCMD_PLAYBACK_STATUS_SONY*/ + scsi_cdrom_set_phase(dev, SCSI_PHASE_DATA_IN); + dev->sony_vendor = 1; + + max_len = cdb[7]; + max_len <<= 8; + max_len |= cdb[8]; + msf = dev->ms_pages_saved_sony.pages[GPMODE_CDROM_PAGE_SONY][2] & 0x01; + + scsi_cdrom_buf_alloc(dev, 18); + + len = 18; + + memset(dev->buffer, 0, 18); + dev->buffer[0] = 0x00; /*Reserved*/ + dev->buffer[1] = 0x00; /*Reserved*/ + dev->buffer[2] = 0x00; /*Audio Status data length*/ + dev->buffer[3] = 0x00; /*Audio Status data length*/ + dev->buffer[4] = cdrom_get_audio_status_sony(dev->drv, &dev->buffer[6], msf || dev->drv->sony_msf); /*Audio status*/ + dev->buffer[5] = 0x00; + + scsi_cdrom_log("Audio Status = %02x\n", dev->buffer[4]); + + len = MIN(len, max_len); + scsi_cdrom_set_buf_len(dev, BufLen, &len); + + scsi_cdrom_data_command_finish(dev, len, len, len, 0); + break; + case CDROM_TYPE_TOSHIBA_XM_3433: + case CDROM_TYPE_TOSHIBA_XM3201B_3232: + case CDROM_TYPE_TOSHIBA_XM3301TA_0272: + case CDROM_TYPE_TOSHIBA_XM5701TA_3136: + case CDROM_TYPE_TOSHIBA_SDM1401_1008: /*GPCMD_CADDY_EJECT_TOSHIBA*/ + scsi_cdrom_set_phase(dev, SCSI_PHASE_STATUS); + scsi_cdrom_stop(sc); + cdrom_eject(dev->id); + scsi_cdrom_command_complete(dev); + break; + default: + scsi_cdrom_illegal_opcode(dev); + break; + } + break; + + case 0xDC: + switch (dev->drv->type) { + case CDROM_TYPE_NEC_25_10a: + case CDROM_TYPE_NEC_38_103: + case CDROM_TYPE_NEC_75_103: + case CDROM_TYPE_NEC_77_106: + case CDROM_TYPE_NEC_211_100: + case CDROM_TYPE_NEC_464_105: /*GPCMD_CADDY_EJECT_NEC*/ + scsi_cdrom_set_phase(dev, SCSI_PHASE_STATUS); + scsi_cdrom_stop(sc); + cdrom_eject(dev->id); + scsi_cdrom_command_complete(dev); + break; + default: + scsi_cdrom_illegal_opcode(dev); + break; + } + break; + + case GPCMD_INQUIRY: + scsi_cdrom_set_phase(dev, SCSI_PHASE_DATA_IN); + + max_len = cdb[3]; + max_len <<= 8; + max_len |= cdb[4]; + + scsi_cdrom_buf_alloc(dev, 65536); + + if (cdb[1] & 1) { + preamble_len = 4; + size_idx = 3; + + dev->buffer[idx++] = 5; + dev->buffer[idx++] = cdb[2]; + dev->buffer[idx++] = 0; + + idx++; + + switch (cdb[2]) { + case 0x00: + dev->buffer[idx++] = 0x00; + dev->buffer[idx++] = 0x83; + break; + case 0x83: + if (idx + 24 > max_len) { + scsi_cdrom_data_phase_error(dev); + scsi_cdrom_buf_free(dev); + return; + } + + dev->buffer[idx++] = 0x02; + dev->buffer[idx++] = 0x00; + dev->buffer[idx++] = 0x00; + dev->buffer[idx++] = 20; + ide_padstr8(dev->buffer + idx, 20, "53R141"); /* Serial */ + idx += 20; + + if (idx + 72 > cdb[4]) + goto atapi_out; + dev->buffer[idx++] = 0x02; + dev->buffer[idx++] = 0x01; + dev->buffer[idx++] = 0x00; + dev->buffer[idx++] = 68; + + if (dev->drv->type == CDROM_TYPE_86BOX_100) + ide_padstr8(dev->buffer + idx, 8, EMU_NAME); /* Vendor */ + else + ide_padstr8(dev->buffer + idx, 8, cdrom_drive_types[dev->drv->type].vendor); /* Vendor */ + + idx += 8; + + if (dev->drv->type == CDROM_TYPE_86BOX_100) + ide_padstr8(dev->buffer + idx, 40, device_identify_ex); /* Product */ + else + ide_padstr8(dev->buffer + idx, 40, cdrom_drive_types[dev->drv->type].model); /* Product */ + + idx += 40; + ide_padstr8(dev->buffer + idx, 20, "53R141"); /* Serial */ + idx += 20; + break; + + default: + scsi_cdrom_log("INQUIRY: Invalid page: %02X\n", cdb[2]); + scsi_cdrom_invalid_field(dev); + scsi_cdrom_buf_free(dev); + return; + } + } else { + preamble_len = 5; + size_idx = 4; + + memset(dev->buffer, 0, 8); + dev->buffer[0] = 5; /*CD-ROM*/ + dev->buffer[1] = 0x80; /*Removable*/ + + if (dev->drv->bus_type == CDROM_BUS_SCSI) { + dev->buffer[3] = 0x02; + switch (dev->drv->type) { + case CDROM_TYPE_86BOX_100: + dev->buffer[2] = 0x05; /*SCSI-2 compliant*/ + break; + case CDROM_TYPE_CHINON_CDS431_H42: + case CDROM_TYPE_DEC_RRD45_0436: + case CDROM_TYPE_MATSHITA_501_10b: + case CDROM_TYPE_SONY_CDU541_10i: + case CDROM_TYPE_SONY_CDU76S_100: + case CDROM_TYPE_TEAC_CD50_100: + case CDROM_TYPE_TEAC_R55S_10R: + case CDROM_TYPE_TEXEL_DMXX24_100: + case CDROM_TYPE_TOSHIBA_XM3201B_3232: + dev->buffer[2] = 0x00; + dev->buffer[3] = 0x01; /*SCSI-1 compliant*/ + break; + case CDROM_TYPE_NEC_25_10a: + case CDROM_TYPE_NEC_38_103: + case CDROM_TYPE_NEC_75_103: + case CDROM_TYPE_NEC_77_106: + case CDROM_TYPE_NEC_211_100: + case CDROM_TYPE_NEC_464_105: + dev->buffer[3] = 0x00; /*SCSI unknown version per NEC manuals*/ + break; + default: + dev->buffer[2] = 0x02; /*SCSI-2 compliant*/ + break; + } + } else { + dev->buffer[2] = 0x00; + dev->buffer[3] = 0x21; + } + + dev->buffer[4] = 31; + if (dev->drv->bus_type == CDROM_BUS_SCSI) { + switch (dev->drv->type) { + case CDROM_TYPE_TOSHIBA_XM_3433: + case CDROM_TYPE_TOSHIBA_XM3201B_3232: + case CDROM_TYPE_TOSHIBA_XM3301TA_0272: + case CDROM_TYPE_TOSHIBA_XM5701TA_3136: + dev->buffer[4] = 91; /* Always 91 on Toshiba SCSI-1 (or SCSI-2) CD-ROM drives from 1989-1990*/ + dev->buffer[7] = 0x88; /* Linked Command and Relative Addressing supported */ + break; + case CDROM_TYPE_PIONEER_DRM604X_2403: + dev->buffer[4] = 42; + break; + case CDROM_TYPE_NEC_25_10a: + case CDROM_TYPE_NEC_38_103: + case CDROM_TYPE_NEC_75_103: + case CDROM_TYPE_NEC_77_106: + case CDROM_TYPE_NEC_211_100: + case CDROM_TYPE_NEC_464_105: + break; + default: + dev->buffer[6] = 0x01; /* 16-bit transfers supported */ + dev->buffer[7] = 0x20; /* Wide bus supported */ + break; + } + } + + if (dev->drv->type == CDROM_TYPE_86BOX_100) { + ide_padstr8(dev->buffer + 8, 8, EMU_NAME); /* Vendor */ + ide_padstr8(dev->buffer + 16, 16, device_identify); /* Product */ + ide_padstr8(dev->buffer + 32, 4, EMU_VERSION_EX); /* Revision */ + } else { + ide_padstr8(dev->buffer + 8, 8, cdrom_drive_types[dev->drv->type].vendor); /* Vendor */ + ide_padstr8(dev->buffer + 16, 16, cdrom_drive_types[dev->drv->type].model); /* Product */ + ide_padstr8(dev->buffer + 32, 4, cdrom_drive_types[dev->drv->type].revision); /* Revision */ + if (dev->drv->type == CDROM_TYPE_PIONEER_DRM604X_2403) { + dev->buffer[36] = 0x20; + ide_padstr8(dev->buffer + 37, 10, "1991/01/01"); /* Date */ + } + } + + idx = 36; + if (dev->drv->type == CDROM_TYPE_PIONEER_DRM604X_2403) + idx = 47; + else { + switch (dev->drv->type) { + case CDROM_TYPE_TOSHIBA_XM_3433: + case CDROM_TYPE_TOSHIBA_XM3201B_3232: + case CDROM_TYPE_TOSHIBA_XM3301TA_0272: + case CDROM_TYPE_TOSHIBA_XM5701TA_3136: + idx = 96; + break; + default: + if (max_len == 96) { + dev->buffer[4] = 91; + idx = 96; + } + break; + } + } + } atapi_out: - dev->buffer[size_idx] = idx - preamble_len; - len=idx; + dev->buffer[size_idx] = idx - preamble_len; + len = idx; - len = MIN(len, max_len); - scsi_cdrom_set_buf_len(dev, BufLen, &len); + len = MIN(len, max_len); - scsi_cdrom_data_command_finish(dev, len, len, max_len, 0); - break; + scsi_cdrom_set_buf_len(dev, BufLen, &len); + scsi_cdrom_log("Inquiry = %d, max = %d, BufLen = %d.\n", len, max_len, *BufLen); - case GPCMD_PREVENT_REMOVAL: - scsi_cdrom_set_phase(dev, SCSI_PHASE_STATUS); - scsi_cdrom_command_complete(dev); - break; + scsi_cdrom_data_command_finish(dev, len, len, max_len, 0); + break; -#if 0 - case GPCMD_PAUSE_RESUME_ALT: -#endif - case GPCMD_PAUSE_RESUME: - scsi_cdrom_set_phase(dev, SCSI_PHASE_STATUS); - cdrom_audio_pause_resume(dev->drv, cdb[8] & 0x01); - scsi_cdrom_command_complete(dev); - break; + case 0x0D: /*GPCMD_NO_OPERATION_TOSHIBA and GPCMD_NO_OPERATION_NEC*/ + scsi_cdrom_set_phase(dev, SCSI_PHASE_STATUS); + scsi_cdrom_command_complete(dev); + break; - case GPCMD_STILL: - scsi_cdrom_set_phase(dev, SCSI_PHASE_STATUS); - dev->drv->cd_status = CD_STATUS_PAUSED; - scsi_cdrom_command_complete(dev); - break; + case GPCMD_PREVENT_REMOVAL: + scsi_cdrom_set_phase(dev, SCSI_PHASE_STATUS); + scsi_cdrom_command_complete(dev); + break; - case GPCMD_SEEK_6: - case GPCMD_SEEK_10: - scsi_cdrom_set_phase(dev, SCSI_PHASE_STATUS); + case GPCMD_PAUSE_RESUME: + scsi_cdrom_set_phase(dev, SCSI_PHASE_STATUS); + cdrom_audio_pause_resume(dev->drv, cdb[8] & 0x01); + dev->drv->audio_op = (cdb[8] & 0x01) ? 0x03 : 0x01; + scsi_cdrom_command_complete(dev); + break; - switch(cdb[0]) { - case GPCMD_SEEK_6: - pos = (cdb[2] << 8) | cdb[3]; - break; - case GPCMD_SEEK_10: - pos = (cdb[2] << 24) | (cdb[3]<<16) | (cdb[4]<<8) | cdb[5]; - break; - } - dev->drv->seek_diff = ABS((int) (pos - dev->drv->seek_pos)); - cdrom_seek(dev->drv, pos); - scsi_cdrom_command_complete(dev); - break; + case 0xC3: + switch (dev->drv->type) { + case CDROM_TYPE_MATSHITA_501_10b: /*GPCMD_READ_TOC_MATSUSHITA*/ + cdb[0] = GPCMD_READ_TOC_PMA_ATIP; + dev->current_cdb[0] = cdb[0]; + goto begin; + break; + case CDROM_TYPE_DEC_RRD45_0436: + case CDROM_TYPE_SONY_CDU541_10i: + case CDROM_TYPE_SONY_CDU561_18k: + case CDROM_TYPE_SONY_CDU76S_100: + case CDROM_TYPE_TEXEL_DMXX24_100: /*GPCMD_READ_HEADER_SONY*/ + scsi_cdrom_set_phase(dev, SCSI_PHASE_DATA_IN); + dev->sony_vendor = 1; - case GPCMD_READ_CDROM_CAPACITY: - scsi_cdrom_set_phase(dev, SCSI_PHASE_DATA_IN); + alloc_length = ((cdb[7] << 8) | cdb[8]); + scsi_cdrom_buf_alloc(dev, 4); - scsi_cdrom_buf_alloc(dev, 8); + dev->sector_len = 1; + dev->sector_pos = (cdb[2] << 24) | (cdb[3] << 16) | (cdb[4] << 8) | cdb[5]; + real_pos = cdrom_lba_to_msf_accurate(dev->sector_pos); + dev->buffer[0] = ((real_pos >> 16) & 0xff); + dev->buffer[1] = ((real_pos >> 8) & 0xff); + dev->buffer[2] = real_pos & 0xff; + dev->buffer[3] = 1; /*2048 bytes user data*/ - /* IMPORTANT: What's returned is the last LBA block. */ - memset(dev->buffer, 0, 8); - dev->buffer[0] = ((dev->drv->cdrom_capacity - 1) >> 24) & 0xff; - dev->buffer[1] = ((dev->drv->cdrom_capacity - 1) >> 16) & 0xff; - dev->buffer[2] = ((dev->drv->cdrom_capacity - 1) >> 8) & 0xff; - dev->buffer[3] = (dev->drv->cdrom_capacity - 1) & 0xff; - dev->buffer[6] = 8; - len = 8; + len = 4; + len = MIN(len, alloc_length); - scsi_cdrom_set_buf_len(dev, BufLen, &len); + scsi_cdrom_set_buf_len(dev, BufLen, &len); - scsi_cdrom_data_command_finish(dev, len, len, len, 0); - break; + scsi_cdrom_data_command_finish(dev, len, len, len, 0); + return; + case CDROM_TYPE_TOSHIBA_XM_3433: + case CDROM_TYPE_TOSHIBA_XM3201B_3232: + case CDROM_TYPE_TOSHIBA_XM3301TA_0272: + case CDROM_TYPE_TOSHIBA_XM5701TA_3136: + case CDROM_TYPE_TOSHIBA_SDM1401_1008: /*GPCMD_SET_STOP_TIME_TOSHIBA*/ + scsi_cdrom_set_phase(dev, SCSI_PHASE_STATUS); + scsi_cdrom_command_complete(dev); + break; + default: + scsi_cdrom_illegal_opcode(dev); + break; + } + break; - case GPCMD_STOP_PLAY_SCAN: - scsi_cdrom_set_phase(dev, SCSI_PHASE_STATUS); + case 0xDB: + switch (dev->drv->type) { + case CDROM_TYPE_NEC_25_10a: + case CDROM_TYPE_NEC_38_103: + case CDROM_TYPE_NEC_75_103: + case CDROM_TYPE_NEC_77_106: + case CDROM_TYPE_NEC_211_100: + case CDROM_TYPE_NEC_464_105: /*GPCMD_SET_STOP_TIME_NEC*/ + scsi_cdrom_set_phase(dev, SCSI_PHASE_STATUS); + scsi_cdrom_command_complete(dev); + break; + default: + scsi_cdrom_illegal_opcode(dev); + break; + } + break; - if (dev->drv->cd_status <= CD_STATUS_DATA_ONLY) { - scsi_cdrom_illegal_mode(dev); - break; - } + case 0xC2: + switch (dev->drv->type) { + case CDROM_TYPE_MATSHITA_501_10b: /*GPCMD_READ_SUBCHANNEL_MATSUSHITA*/ + cdb[0] = GPCMD_READ_SUBCHANNEL; + dev->current_cdb[0] = cdb[0]; + goto begin; + break; + case CDROM_TYPE_DEC_RRD45_0436: + case CDROM_TYPE_SONY_CDU541_10i: + case CDROM_TYPE_SONY_CDU561_18k: + case CDROM_TYPE_SONY_CDU76S_100: + case CDROM_TYPE_TEXEL_DMXX24_100: /*GPCMD_READ_SUBCHANNEL_SONY*/ + scsi_cdrom_set_phase(dev, SCSI_PHASE_DATA_IN); + dev->sony_vendor = 1; - scsi_cdrom_stop(sc); - scsi_cdrom_command_complete(dev); - break; + max_len = cdb[7]; + max_len <<= 8; + max_len |= cdb[8]; + msf = dev->ms_pages_saved_sony.pages[GPMODE_CDROM_PAGE_SONY][2] & 0x01; - default: - scsi_cdrom_illegal_opcode(dev); - break; + scsi_cdrom_log("CD-ROM %i: Getting sub-channel type (%s), code-q = %02x\n", dev->id, msf ? "MSF" : "LBA", cdb[2] & 0x40); + + if (cdb[2] & 0x40) { + scsi_cdrom_buf_alloc(dev, 9); + memset(dev->buffer, 0, 9); + len = 9; + cdrom_get_current_subchannel_sony(dev->drv, dev->buffer, msf || dev->drv->sony_msf); + len = MIN(len, max_len); + scsi_cdrom_set_buf_len(dev, BufLen, &len); + scsi_cdrom_data_command_finish(dev, len, len, len, 0); + } else { + scsi_cdrom_set_phase(dev, SCSI_PHASE_STATUS); + scsi_cdrom_log("CD-ROM %i: Drive Status All done - callback set\n", dev->id); + dev->packet_status = PHASE_COMPLETE; + dev->callback = 20.0 * CDROM_TIME; + scsi_cdrom_set_callback(dev); + } + break; + case CDROM_TYPE_PIONEER_DRM604X_2403: /*GPCMD_READ_SUBCODEQ_PIONEER*/ + scsi_cdrom_set_phase(dev, SCSI_PHASE_DATA_IN); + + alloc_length = cdb[1] & 0x1f; + len = 9; + + if (!dev->drv->ops) { + scsi_cdrom_not_ready(dev); + return; + } + + if (!alloc_length) { + scsi_cdrom_set_phase(dev, SCSI_PHASE_STATUS); + scsi_cdrom_log("CD-ROM %i: Subcode Q All done - callback set\n", dev->id); + dev->packet_status = PHASE_COMPLETE; + dev->callback = 20.0 * CDROM_TIME; + scsi_cdrom_set_callback(dev); + break; + } + + scsi_cdrom_buf_alloc(dev, len); + len = MIN(len, alloc_length); + + memset(dev->buffer, 0, len); + cdrom_get_current_subcodeq(dev->drv, &dev->buffer[1]); + scsi_cdrom_log("Audio Status = %02x\n", dev->buffer[0]); + + scsi_cdrom_set_buf_len(dev, BufLen, &alloc_length); + scsi_cdrom_data_command_finish(dev, len, len, len, 0); + break; + case CDROM_TYPE_TOSHIBA_XM_3433: + case CDROM_TYPE_TOSHIBA_XM3201B_3232: + case CDROM_TYPE_TOSHIBA_XM3301TA_0272: + case CDROM_TYPE_TOSHIBA_XM5701TA_3136: + case CDROM_TYPE_TOSHIBA_SDM1401_1008: /*GPCMD_STILL_TOSHIBA*/ + scsi_cdrom_set_phase(dev, SCSI_PHASE_STATUS); + cdrom_audio_pause_resume(dev->drv, 0x00); + dev->drv->audio_op = 0x01; + scsi_cdrom_command_complete(dev); + break; + default: + scsi_cdrom_illegal_opcode(dev); + break; + } + break; + + case GPCMD_SEEK_6: + case GPCMD_SEEK_10: + scsi_cdrom_set_phase(dev, SCSI_PHASE_STATUS); + + switch (cdb[0]) { + case GPCMD_SEEK_6: + pos = (cdb[2] << 8) | cdb[3]; + break; + case GPCMD_SEEK_10: + pos = (cdb[2] << 24) | (cdb[3] << 16) | (cdb[4] << 8) | cdb[5]; + break; + + default: + break; + } + dev->drv->seek_diff = ABS((int) (pos - dev->drv->seek_pos)); + if (cdb[0] == GPCMD_SEEK_10) { + switch (dev->drv->type) { + case CDROM_TYPE_NEC_25_10a: + case CDROM_TYPE_NEC_38_103: + case CDROM_TYPE_NEC_75_103: + case CDROM_TYPE_NEC_77_106: + case CDROM_TYPE_NEC_211_100: + case CDROM_TYPE_NEC_464_105: + case CDROM_TYPE_TOSHIBA_XM_3433: + case CDROM_TYPE_TOSHIBA_XM3201B_3232: + case CDROM_TYPE_TOSHIBA_XM3301TA_0272: + case CDROM_TYPE_TOSHIBA_XM5701TA_3136: + case CDROM_TYPE_TOSHIBA_SDM1401_1008: + cdrom_seek(dev->drv, pos, cdb[9] & 0xc0); + break; + default: + cdrom_seek(dev->drv, pos, 0); + break; + } + } else + cdrom_seek(dev->drv, pos, 0); + + scsi_cdrom_command_complete(dev); + break; + + case GPCMD_READ_CDROM_CAPACITY: + scsi_cdrom_set_phase(dev, SCSI_PHASE_DATA_IN); + + scsi_cdrom_buf_alloc(dev, 8); + + /* IMPORTANT: What's returned is the last LBA block. */ + memset(dev->buffer, 0, 8); + dev->buffer[0] = ((dev->drv->cdrom_capacity - 1) >> 24) & 0xff; + dev->buffer[1] = ((dev->drv->cdrom_capacity - 1) >> 16) & 0xff; + dev->buffer[2] = ((dev->drv->cdrom_capacity - 1) >> 8) & 0xff; + dev->buffer[3] = (dev->drv->cdrom_capacity - 1) & 0xff; + dev->buffer[6] = 8; + len = 8; + + scsi_cdrom_set_buf_len(dev, BufLen, &len); + + scsi_cdrom_data_command_finish(dev, len, len, len, 0); + break; + + case GPCMD_STOP_PLAY_SCAN: + scsi_cdrom_set_phase(dev, SCSI_PHASE_STATUS); + + if (dev->drv->cd_status <= CD_STATUS_DATA_ONLY) { + scsi_cdrom_illegal_mode(dev); + break; + } + + scsi_cdrom_stop(sc); + scsi_cdrom_command_complete(dev); + break; + + case 0xC5: + switch (dev->drv->type) { + case CDROM_TYPE_MATSHITA_501_10b: /*GPCMD_PLAY_AUDIO_MATSUSHITA*/ + cdb[0] = GPCMD_PLAY_AUDIO_10; + dev->current_cdb[0] = cdb[0]; + goto begin; + break; + case CDROM_TYPE_DEC_RRD45_0436: + case CDROM_TYPE_SONY_CDU541_10i: + case CDROM_TYPE_SONY_CDU561_18k: + case CDROM_TYPE_SONY_CDU76S_100: + case CDROM_TYPE_TEXEL_DMXX24_100: /*GPCMD_PAUSE_SONY*/ + scsi_cdrom_set_phase(dev, SCSI_PHASE_STATUS); + dev->sony_vendor = 1; + cdrom_audio_pause_resume(dev->drv, !(cdb[1] & 0x10)); + scsi_cdrom_command_complete(dev); + break; + default: + scsi_cdrom_illegal_opcode(dev); + break; + } + break; + + case 0xC8: + switch (dev->drv->type) { + case CDROM_TYPE_MATSHITA_501_10b: /*GPCMD_PLAY_AUDIO_TRACK_INDEX_MATSUSHITA*/ + cdb[0] = GPCMD_PLAY_AUDIO_TRACK_INDEX; + dev->current_cdb[0] = cdb[0]; + goto begin; + break; + case CDROM_TYPE_DEC_RRD45_0436: + case CDROM_TYPE_SONY_CDU541_10i: + case CDROM_TYPE_SONY_CDU561_18k: + case CDROM_TYPE_SONY_CDU76S_100: + case CDROM_TYPE_TEXEL_DMXX24_100: /*GPCMD_PLAY_AUDIO_SONY*/ + cdb[0] = GPCMD_PLAY_AUDIO_10; + dev->current_cdb[0] = cdb[0]; + dev->sony_vendor = 1; + goto begin; + break; + case CDROM_TYPE_PIONEER_DRM604X_2403: /*GPCMD_AUDIO_TRACK_SEARCH_PIONEER*/ + scsi_cdrom_set_phase(dev, SCSI_PHASE_STATUS); + if ((dev->drv->host_drive < 1) || (dev->drv->cd_status <= CD_STATUS_DATA_ONLY)) { + scsi_cdrom_illegal_mode(dev); + break; + } + pos = (cdb[2] << 24) | (cdb[3] << 16) | (cdb[4] << 8) | cdb[5]; + ret = cdrom_audio_track_search_pioneer(dev->drv, pos, cdb[1] & 1); + dev->drv->audio_op = (cdb[1] & 1) ? 0x03 : 0x02; + + if (ret) + scsi_cdrom_command_complete(dev); + else + scsi_cdrom_illegal_mode(dev); + break; + default: + scsi_cdrom_illegal_opcode(dev); + break; + } + break; + + case 0xC9: + switch (dev->drv->type) { + case CDROM_TYPE_MATSHITA_501_10b: /*GPCMD_PLAY_AUDIO_TRACK_RELATIVE_10_MATSUSHITA*/ + cdb[0] = GPCMD_PLAY_AUDIO_TRACK_RELATIVE_10; + dev->current_cdb[0] = cdb[0]; + goto begin; + break; + case CDROM_TYPE_DEC_RRD45_0436: + case CDROM_TYPE_SONY_CDU541_10i: + case CDROM_TYPE_SONY_CDU561_18k: + case CDROM_TYPE_SONY_CDU76S_100: + case CDROM_TYPE_TEXEL_DMXX24_100: /*GPCMD_PLAYBACK_CONTROL_SONY*/ + scsi_cdrom_set_phase(dev, SCSI_PHASE_DATA_OUT); + dev->sony_vendor = 1; + + len = (cdb[7] << 8) | cdb[8]; + scsi_cdrom_buf_alloc(dev, 65536); + + scsi_cdrom_set_buf_len(dev, BufLen, &len); + scsi_cdrom_data_command_finish(dev, len, len, len, 1); + break; + case CDROM_TYPE_PIONEER_DRM604X_2403: /*GPCMD_PLAY_AUDIO_PIONEER*/ + scsi_cdrom_set_phase(dev, SCSI_PHASE_STATUS); + if ((dev->drv->host_drive < 1) || (dev->drv->cd_status <= CD_STATUS_DATA_ONLY)) { + scsi_cdrom_illegal_mode(dev); + break; + } + pos = (cdb[2] << 24) | (cdb[3] << 16) | (cdb[4] << 8) | cdb[5]; + ret = cdrom_audio_play_pioneer(dev->drv, pos); + + if (ret) + scsi_cdrom_command_complete(dev); + else + scsi_cdrom_illegal_mode(dev); + break; + default: + scsi_cdrom_illegal_opcode(dev); + break; + } + break; + + case 0xCA: + if (dev->drv->type == CDROM_TYPE_PIONEER_DRM604X_2403) { /*GPCMD_PAUSE_PIONEER*/ + scsi_cdrom_set_phase(dev, SCSI_PHASE_STATUS); + cdrom_audio_pause_resume(dev->drv, !(cdb[1] & 0x10)); + scsi_cdrom_command_complete(dev); + } else { + scsi_cdrom_illegal_opcode(dev); + } + break; + + case 0xCB: + switch (dev->drv->type) { + case CDROM_TYPE_MATSHITA_501_10b: /*GPCMD_PAUSE_RESUME_MATSUSHITA*/ + cdb[0] = GPCMD_PAUSE_RESUME; + dev->current_cdb[0] = cdb[0]; + goto begin; + break; + case CDROM_TYPE_PIONEER_DRM604X_2403: /*GPCMD_STOP_PIONEER*/ + scsi_cdrom_set_phase(dev, SCSI_PHASE_STATUS); + scsi_cdrom_stop(sc); + scsi_cdrom_command_complete(dev); + break; + default: + scsi_cdrom_illegal_opcode(dev); + break; + } + break; + + case 0xCC: + if (dev->drv->type == CDROM_TYPE_PIONEER_DRM604X_2403) { /*GPCMD_PLAYBACK_STATUS_PIONEER*/ + scsi_cdrom_set_phase(dev, SCSI_PHASE_DATA_IN); + + max_len = cdb[7]; + max_len <<= 8; + max_len |= cdb[8]; + + scsi_cdrom_buf_alloc(dev, 6); + + len = 6; + + memset(dev->buffer, 0, 6); + dev->buffer[0] = cdrom_get_audio_status_pioneer(dev->drv, &dev->buffer[1]); /*Audio status*/ + + scsi_cdrom_log("Audio Status = %02x\n", dev->buffer[4]); + + len = MIN(len, max_len); + scsi_cdrom_set_buf_len(dev, BufLen, &len); + + scsi_cdrom_data_command_finish(dev, len, len, len, 0); + } else { + scsi_cdrom_illegal_opcode(dev); + } + break; + + case 0xE0: + if (dev->drv->type == CDROM_TYPE_PIONEER_DRM604X_2403) { /*GPCMD_DRIVE_STATUS_PIONEER*/ + scsi_cdrom_set_phase(dev, SCSI_PHASE_DATA_IN); + + len = (cdb[9] | (cdb[8] << 8)); + scsi_cdrom_buf_alloc(dev, 65536); + + if (!(scsi_cdrom_drive_status_page_flags & (1LL << (uint64_t) (cdb[2] & 0x3f)))) { + scsi_cdrom_invalid_field(dev); + scsi_cdrom_buf_free(dev); + return; + } + + if (!len) { + scsi_cdrom_set_phase(dev, SCSI_PHASE_STATUS); + scsi_cdrom_log("CD-ROM %i: Drive Status All done - callback set\n", dev->id); + dev->packet_status = PHASE_COMPLETE; + dev->callback = 20.0 * CDROM_TIME; + scsi_cdrom_set_callback(dev); + break; + } + + memset(dev->buffer, 0, len); + alloc_length = len; + + len = scsi_cdrom_drive_status(dev, dev->buffer, 0, cdb[2]); + len = MIN(len, alloc_length); + + scsi_cdrom_set_buf_len(dev, BufLen, &len); + + scsi_cdrom_log("CD-ROM %i: Reading drive status page: %02X...\n", dev->id, cdb[2]); + + scsi_cdrom_data_command_finish(dev, len, len, alloc_length, 0); + return; + } else { + scsi_cdrom_illegal_opcode(dev); + } + break; + + case 0xE5: + if (dev->drv->type == CDROM_TYPE_MATSHITA_501_10b) { /*GPCMD_PLAY_AUDIO_12_MATSUSHITA*/ + cdb[0] = GPCMD_PLAY_AUDIO_12; + dev->current_cdb[0] = cdb[0]; + goto begin; + } else { + scsi_cdrom_illegal_opcode(dev); + } + break; + + case 0xE9: + if (dev->drv->type == CDROM_TYPE_MATSHITA_501_10b) { /*GPCMD_PLAY_AUDIO_TRACK_RELATIVE_12_MATSUSHITA*/ + cdb[0] = GPCMD_PLAY_AUDIO_TRACK_RELATIVE_12; + dev->current_cdb[0] = cdb[0]; + goto begin; + } + fallthrough; + default: + scsi_cdrom_illegal_opcode(dev); + break; } - /* scsi_cdrom_log("CD-ROM %i: Phase: %02X, request length: %i\n", dev->phase, dev->request_length); */ + /* scsi_cdrom_log("CD-ROM %i: Phase: %02X, request length: %i\n", dev->tf->phase, + dev->tf->request_length); */ - if (scsi_cdrom_atapi_phase_to_scsi(dev) == SCSI_PHASE_STATUS) - scsi_cdrom_buf_free(dev); + if ((dev->packet_status == PHASE_COMPLETE) || (dev->packet_status == PHASE_ERROR)) + scsi_cdrom_buf_free(dev); } - static void scsi_cdrom_command_stop(scsi_common_t *sc) { @@ -2517,280 +3764,435 @@ scsi_cdrom_command_stop(scsi_common_t *sc) scsi_cdrom_buf_free(dev); } - /* The command second phase function, needed for Mode Select. */ static uint8_t scsi_cdrom_phase_data_out(scsi_common_t *sc) { scsi_cdrom_t *dev = (scsi_cdrom_t *) sc; - uint16_t block_desc_len, pos; - uint16_t param_list_len; - uint16_t i = 0; + uint16_t block_desc_len; + uint16_t pos; + uint16_t param_list_len; + uint16_t i = 0; uint8_t error = 0; - uint8_t page, page_len, hdr_len, val, old_val, ch; + uint8_t page; + uint8_t page_len; + uint8_t hdr_len; + uint8_t val; + uint8_t old_val; + uint8_t ch; - switch(dev->current_cdb[0]) { - case GPCMD_MODE_SELECT_6: - case GPCMD_MODE_SELECT_10: - if (dev->current_cdb[0] == GPCMD_MODE_SELECT_10) { - hdr_len = 8; - param_list_len = dev->current_cdb[7]; - param_list_len <<= 8; - param_list_len |= dev->current_cdb[8]; - } else { - hdr_len = 4; - param_list_len = dev->current_cdb[4]; - } + switch (dev->current_cdb[0]) { + case GPCMD_MODE_SELECT_6: + case GPCMD_MODE_SELECT_10: + if (dev->current_cdb[0] == GPCMD_MODE_SELECT_10) { + hdr_len = 8; + param_list_len = dev->current_cdb[7]; + param_list_len <<= 8; + param_list_len |= dev->current_cdb[8]; + } else { + hdr_len = 4; + param_list_len = dev->current_cdb[4]; + } - if (dev->drv->bus_type == CDROM_BUS_SCSI) { - if (dev->current_cdb[0] == GPCMD_MODE_SELECT_6) { - block_desc_len = dev->buffer[2]; - block_desc_len <<= 8; - block_desc_len |= dev->buffer[3]; - } else { - block_desc_len = dev->buffer[6]; - block_desc_len <<= 8; - block_desc_len |= dev->buffer[7]; - } - } else - block_desc_len = 0; + if (dev->drv->bus_type == CDROM_BUS_SCSI) { + if (dev->current_cdb[0] == GPCMD_MODE_SELECT_6) { + block_desc_len = dev->buffer[2]; + block_desc_len <<= 8; + block_desc_len |= dev->buffer[3]; + } else { + block_desc_len = dev->buffer[6]; + block_desc_len <<= 8; + block_desc_len |= dev->buffer[7]; + } + } else + block_desc_len = 0; - pos = hdr_len + block_desc_len; + pos = hdr_len + block_desc_len; - while(1) { - if (pos >= param_list_len) { - scsi_cdrom_log("CD-ROM %i: Buffer has only block descriptor\n", dev->id); - break; - } + while (1) { + if (pos >= param_list_len) { + scsi_cdrom_log("CD-ROM %i: Buffer has only block descriptor\n", dev->id); + break; + } - page = dev->buffer[pos] & 0x3F; - page_len = dev->buffer[pos + 1]; + page = dev->buffer[pos] & 0x3F; + page_len = dev->buffer[pos + 1]; - pos += 2; + pos += 2; - if (!(scsi_cdrom_mode_sense_page_flags & (1LL << ((uint64_t) page)))) { - scsi_cdrom_log("CD-ROM %i: Unimplemented page %02X\n", dev->id, page); - error |= 1; - } else { - for (i = 0; i < page_len; i++) { - ch = scsi_cdrom_mode_sense_pages_changeable.pages[page][i + 2]; - val = dev->buffer[pos + i]; - old_val = dev->ms_pages_saved.pages[page][i + 2]; - if (val != old_val) { - if (ch) - dev->ms_pages_saved.pages[page][i + 2] = val; - else { - scsi_cdrom_log("CD-ROM %i: Unchangeable value on position %02X on page %02X\n", dev->id, i + 2, page); - error |= 1; - } - } - } - } + switch (dev->drv->type) { + case CDROM_TYPE_DEC_RRD45_0436: + case CDROM_TYPE_SONY_CDU541_10i: + case CDROM_TYPE_SONY_CDU561_18k: + case CDROM_TYPE_SONY_CDU76S_100: + case CDROM_TYPE_TEXEL_DMXX24_100: + if (!(scsi_cdrom_mode_sense_page_flags_sony & (1LL << ((uint64_t) page)))) { + scsi_cdrom_log("CD-ROM %i: Unimplemented page %02X\n", dev->id, page); + error |= 1; + } else { + for (i = 0; i < page_len; i++) { + ch = scsi_cdrom_mode_sense_pages_changeable_sony.pages[page][i + 2]; + val = dev->buffer[pos + i]; + old_val = dev->ms_pages_saved_sony.pages[page][i + 2]; + if (val != old_val) { + if (ch) + dev->ms_pages_saved_sony.pages[page][i + 2] = val; + else { + scsi_cdrom_log("CD-ROM %i: Unchangeable value on position %02X on page %02X\n", dev->id, i + 2, page); + error |= 1; + } + } + } + } + break; + default: + if (!(scsi_cdrom_mode_sense_page_flags & (1LL << ((uint64_t) page)))) { + scsi_cdrom_log("CD-ROM %i: Unimplemented page %02X\n", dev->id, page); + error |= 1; + } else { + for (i = 0; i < page_len; i++) { + ch = scsi_cdrom_mode_sense_pages_changeable.pages[page][i + 2]; + val = dev->buffer[pos + i]; + old_val = dev->ms_pages_saved.pages[page][i + 2]; + if (val != old_val) { + if (ch) + dev->ms_pages_saved.pages[page][i + 2] = val; + else { + scsi_cdrom_log("CD-ROM %i: Unchangeable value on position %02X on page %02X\n", dev->id, i + 2, page); + error |= 1; + } + } + } + } + break; + } - pos += page_len; + pos += page_len; - if (dev->drv->bus_type == CDROM_BUS_SCSI) - val = scsi_cdrom_mode_sense_pages_default_scsi.pages[page][0] & 0x80; - else - val = scsi_cdrom_mode_sense_pages_default.pages[page][0] & 0x80; + switch (dev->drv->type) { + case CDROM_TYPE_DEC_RRD45_0436: + case CDROM_TYPE_SONY_CDU541_10i: + case CDROM_TYPE_SONY_CDU561_18k: + case CDROM_TYPE_SONY_CDU76S_100: + case CDROM_TYPE_TEXEL_DMXX24_100: + val = scsi_cdrom_mode_sense_pages_default_sony_scsi.pages[page][0] & 0x80; + break; + default: + if (dev->drv->bus_type == CDROM_BUS_SCSI) + val = scsi_cdrom_mode_sense_pages_default_scsi.pages[page][0] & 0x80; + else + val = scsi_cdrom_mode_sense_pages_default.pages[page][0] & 0x80; + break; + } + if (dev->do_page_save && val) + scsi_cdrom_mode_sense_save(dev); - if (dev->do_page_save && val) - scsi_cdrom_mode_sense_save(dev); + if (pos >= dev->total_length) + break; + } - if (pos >= dev->total_length) - break; - } + if (error) { + scsi_cdrom_invalid_field_pl(dev); + scsi_cdrom_buf_free(dev); + return 0; + } + break; + case 0xC9: + switch (dev->drv->type) { + case CDROM_TYPE_DEC_RRD45_0436: + case CDROM_TYPE_SONY_CDU541_10i: + case CDROM_TYPE_SONY_CDU561_18k: + case CDROM_TYPE_SONY_CDU76S_100: + case CDROM_TYPE_TEXEL_DMXX24_100: + for (i = 0; i < 18; i++) { + dev->ms_pages_saved_sony.pages[GPMODE_CDROM_AUDIO_PAGE_SONY][i] = dev->buffer[i]; + } + break; + default: + break; + } + break; - if (error) { - scsi_cdrom_invalid_field_pl(dev); - scsi_cdrom_buf_free(dev); - return 0; - } - break; + default: + break; } scsi_cdrom_command_stop((scsi_common_t *) dev); return 1; } - static void -scsi_cdrom_close(void *p) +scsi_cdrom_close(void *priv) { - scsi_cdrom_t *dev = (scsi_cdrom_t *) p; + scsi_cdrom_t *dev = (scsi_cdrom_t *) priv; + + if (dev->tf) + free(dev->tf); if (dev) - free(dev); + free(dev); } - static int scsi_cdrom_get_max(int ide_has_dma, int type) { int ret; - switch(type) { - case TYPE_PIO: - ret = ide_has_dma ? 4 : 0; - break; - case TYPE_SDMA: - ret = ide_has_dma ? 2 : -1; - break; - case TYPE_MDMA: - ret = ide_has_dma ? 2 : -1; - break; - case TYPE_UDMA: - ret = ide_has_dma ? 5 : -1; - break; - default: - ret = -1; - break; + switch (type) { + case TYPE_PIO: + ret = ide_has_dma ? 4 : 0; + break; + case TYPE_SDMA: + ret = ide_has_dma ? 2 : -1; + break; + case TYPE_MDMA: + ret = ide_has_dma ? 2 : -1; + break; + case TYPE_UDMA: + ret = ide_has_dma ? 5 : -1; + break; + default: + ret = -1; + break; } return ret; } - static int scsi_cdrom_get_timings(int ide_has_dma, int type) { int ret; - switch(type) { - case TIMINGS_DMA: - ret = ide_has_dma ? 120 : 0; - break; - case TIMINGS_PIO: - ret = ide_has_dma ? 120 : 0; - break; - case TIMINGS_PIO_FC: - ret = 0; - break; - default: - ret = 0; - break; + switch (type) { + case TIMINGS_DMA: + ret = ide_has_dma ? 120 : 0; + break; + case TIMINGS_PIO: + ret = ide_has_dma ? 120 : 0; + break; + case TIMINGS_PIO_FC: + ret = 0; + break; + default: + ret = 0; + break; } return ret; } - /** * Fill in ide->buffer with the output of the "IDENTIFY PACKET DEVICE" command */ static void scsi_cdrom_identify(ide_t *ide, int ide_has_dma) { -#if 0 - scsi_cdrom_t *dev; - char device_identify[9] = { '8', '6', 'B', '_', 'C', 'D', '0', '0', 0 }; + const scsi_cdrom_t *dev; + char device_identify[9] = { '8', '6', 'B', '_', 'C', 'D', '0', '0', 0 }; - dev = (scsi_cdrom_t *) ide->p; + dev = (scsi_cdrom_t *) ide->sc; device_identify[7] = dev->id + 0x30; scsi_cdrom_log("ATAPI Identify: %s\n", device_identify); -#endif - ide->buffer[0] = 0x8000 | (5<<8) | 0x80 | (2<<5); /* ATAPI device, CD-ROM drive, removable media, accelerated DRQ */ - ide_padstr((char *) (ide->buffer + 10), "", 20); /* Serial Number */ -#if 0 - ide_padstr((char *) (ide->buffer + 23), EMU_VERSION_EX, 8); /* Firmware */ - ide_padstr((char *) (ide->buffer + 27), device_identify, 40); /* Model */ -#else - ide_padstr((char *) (ide->buffer + 23), "4.20 ", 8); /* Firmware */ - ide_padstr((char *) (ide->buffer + 27), "NEC CD-ROM DRIVE:273 ", 40); /* Model */ -#endif - ide->buffer[49] = 0x200; /* LBA supported */ + if ((dev->drv->type == CDROM_TYPE_NEC_260_100) || (dev->drv->type == CDROM_TYPE_NEC_260_101)) /*NEC only*/ + ide->buffer[0] = 0x8000 | (5 << 8) | 0x80 | (1 << 5); /* ATAPI device, CD-ROM drive, removable media, interrupt DRQ */ + else + ide->buffer[0] = 0x8000 | (5 << 8) | 0x80 | (2 << 5); /* ATAPI device, CD-ROM drive, removable media, accelerated DRQ */ + ide_padstr((char *) (ide->buffer + 10), "", 20); /* Serial Number */ + + if (dev->drv->type == CDROM_TYPE_86BOX_100) { + ide_padstr((char *) (ide->buffer + 23), EMU_VERSION_EX, 8); /* Firmware */ + ide_padstr((char *) (ide->buffer + 27), device_identify, 40); /* Model */ + } else { + switch (dev->drv->type) { + case CDROM_TYPE_AZT_CDA46802I_115: + ide_padstr((char *) (ide->buffer + 23), "1.15 ", 8); /* Firmware */ + ide_padstr((char *) (ide->buffer + 27), "AZT CDA46802I ", 40); /* Model */ + break; + case CDROM_TYPE_BTC_BCD36XH_U10: + ide_padstr((char *) (ide->buffer + 23), "U1.0 ", 8); /* Firmware */ + ide_padstr((char *) (ide->buffer + 27), "BTC CD-ROM BCD36XH ", 40); /* Model */ + break; + case CDROM_TYPE_GOLDSTAR_CRD_8160B_314: + ide_padstr((char *) (ide->buffer + 23), "3.14 ", 8); /* Firmware */ + ide_padstr((char *) (ide->buffer + 27), "GOLDSTAR CRD-8160B ", 40); /* Model */ + break; + case CDROM_TYPE_HITACHI_CDR_8130_0020: + ide_padstr((char *) (ide->buffer + 23), "0020 ", 8); /* Firmware */ + ide_padstr((char *) (ide->buffer + 27), "HITACHI CDR-8130 ", 40); /* Model */ + break; + case CDROM_TYPE_KENWOOD_UCR_421_208E: + ide_padstr((char *) (ide->buffer + 23), "208E ", 8); /* Firmware */ + ide_padstr((char *) (ide->buffer + 27), "KENWOOD CD-ROM UCR-421 ", 40); /* Model */ + break; + case CDROM_TYPE_MATSHITA_587_7S13: + ide_padstr((char *) (ide->buffer + 23), "7S13 ", 8); /* Firmware */ + ide_padstr((char *) (ide->buffer + 27), "MATSHITA CD-ROM CR-587 ", 40); /* Model */ + break; + case CDROM_TYPE_MATSHITA_588_LS15: + ide_padstr((char *) (ide->buffer + 23), "LS15 ", 8); /* Firmware */ + ide_padstr((char *) (ide->buffer + 27), "MATSHITA CD-ROM CR-588 ", 40); /* Model */ + break; + case CDROM_TYPE_MATSHITA_571_10e: + ide_padstr((char *) (ide->buffer + 23), "1.0e ", 8); /* Firmware */ + ide_padstr((char *) (ide->buffer + 27), "MATSHITA CR-571 ", 40); /* Model */ + break; + case CDROM_TYPE_MATSHITA_572_10j: + ide_padstr((char *) (ide->buffer + 23), "1.0j ", 8); /* Firmware */ + ide_padstr((char *) (ide->buffer + 27), "MATSHITA CR-572 ", 40); /* Model */ + break; + case CDROM_TYPE_MITSUMI_FX4820T_D02A: + ide_padstr((char *) (ide->buffer + 23), "D02A ", 8); /* Firmware */ + ide_padstr((char *) (ide->buffer + 27), "MITSUMI CRMC-FX4820T ", 40); /* Model */ + break; + case CDROM_TYPE_NEC_260_100: + ide_padstr((char *) (ide->buffer + 23), ".100 ", 8); /* Firmware */ + ide_padstr((char *) (ide->buffer + 27), "EN C DCR-MOD IREV2:06 ", 40); /* Model */ + break; + case CDROM_TYPE_NEC_260_101: + ide_padstr((char *) (ide->buffer + 23), ".110 ", 8); /* Firmware */ + ide_padstr((char *) (ide->buffer + 27), "EN C DCR-MOD IREV2:06 ", 40); /* Model */ + break; + case CDROM_TYPE_NEC_273_420: + ide_padstr((char *) (ide->buffer + 23), "4.20 ", 8); /* Firmware */ + ide_padstr((char *) (ide->buffer + 27), "NEC CD-ROM DRIVE:273 ", 40); /* Model */ + break; + case CDROM_TYPE_NEC_280_105: + ide_padstr((char *) (ide->buffer + 23), "1.05 ", 8); /* Firmware */ + ide_padstr((char *) (ide->buffer + 27), "NEC CD-ROM DRIVE:280 ", 40); /* Model */ + break; + case CDROM_TYPE_NEC_280_308: + ide_padstr((char *) (ide->buffer + 23), "3.08 ", 8); /* Firmware */ + ide_padstr((char *) (ide->buffer + 27), "NEC CD-ROM DRIVE:280 ", 40); /* Model */ + break; + case CDROM_TYPE_PHILIPS_PCA403CD_U31P: + ide_padstr((char *) (ide->buffer + 23), "U31P ", 8); /* Firmware */ + ide_padstr((char *) (ide->buffer + 27), "PHILIPS CD-ROM PCA403CD ", 40); /* Model */ + break; + case CDROM_TYPE_SONY_CDU76_10i: + ide_padstr((char *) (ide->buffer + 23), "1.0i ", 8); /* Firmware */ + ide_padstr((char *) (ide->buffer + 27), "SONY CD-ROM CDU76 ", 40); /* Model */ + break; + case CDROM_TYPE_SONY_CDU311_30h: + ide_padstr((char *) (ide->buffer + 23), "3.0h ", 8); /* Firmware */ + ide_padstr((char *) (ide->buffer + 27), "SONY CD-ROM CDU311 ", 40); /* Model */ + break; + case CDROM_TYPE_TOSHIBA_5302TA_0305: + ide_padstr((char *) (ide->buffer + 23), "0305 ", 8); /* Firmware */ + ide_padstr((char *) (ide->buffer + 27), "TOSHIBA CD-ROM XM-5302TA ", 40); /* Model */ + break; + case CDROM_TYPE_TOSHIBA_5702B_TA70: + ide_padstr((char *) (ide->buffer + 23), "TA70 ", 8); /* Firmware */ + ide_padstr((char *) (ide->buffer + 27), "TOSHIBA CD-ROM XM-5702B ", 40); /* Model */ + break; + } + } + + ide->buffer[49] = 0x200; /* LBA supported */ ide->buffer[126] = 0xfffe; /* Interpret zero byte count limit as maximum length */ if (ide_has_dma) { - ide->buffer[71] = 30; - ide->buffer[72] = 30; - ide->buffer[80] = 0x7e; /*ATA-1 to ATA-6 supported*/ - ide->buffer[81] = 0x19; /*ATA-6 revision 3a supported*/ + ide->buffer[71] = 30; + ide->buffer[72] = 30; + ide->buffer[80] = 0x7e; /*ATA-1 to ATA-6 supported*/ + ide->buffer[81] = 0x19; /*ATA-6 revision 3a supported*/ } } - void scsi_cdrom_drive_reset(int c) { - cdrom_t *drv = &cdrom[c]; - scsi_cdrom_t *dev; + cdrom_t *drv = &cdrom[c]; + scsi_cdrom_t *dev; scsi_device_t *sd; - ide_t *id; - uint8_t scsi_bus = (drv->scsi_device_id >> 4) & 0x0f; - uint8_t scsi_id = drv->scsi_device_id & 0x0f; + ide_t *id; + uint8_t scsi_bus = (drv->scsi_device_id >> 4) & 0x0f; + uint8_t scsi_id = drv->scsi_device_id & 0x0f; + uint8_t valid = 0; if (drv->bus_type == CDROM_BUS_SCSI) { - /* Make sure to ignore any SCSI CD-ROM drive that has an out of range SCSI bus. */ - if (scsi_bus >= SCSI_BUS_MAX) - return; + /* Make sure to ignore any SCSI CD-ROM drive that has an out of range SCSI bus. */ + if (scsi_bus >= SCSI_BUS_MAX) + return; - /* Make sure to ignore any SCSI CD-ROM drive that has an out of range ID. */ - if (scsi_id >= SCSI_ID_MAX) - return; + /* Make sure to ignore any SCSI CD-ROM drive that has an out of range ID. */ + if (scsi_id >= SCSI_ID_MAX) + return; } /* Make sure to ignore any ATAPI CD-ROM drive that has an out of range IDE channel. */ if ((drv->bus_type == CDROM_BUS_ATAPI) && (drv->ide_channel > 7)) - return; + return; if (!drv->priv) { - drv->priv = (scsi_cdrom_t *) malloc(sizeof(scsi_cdrom_t)); - memset(drv->priv, 0, sizeof(scsi_cdrom_t)); + drv->priv = (scsi_cdrom_t *) malloc(sizeof(scsi_cdrom_t)); + memset(drv->priv, 0, sizeof(scsi_cdrom_t)); } dev = (scsi_cdrom_t *) drv->priv; - dev->id = c; + dev->id = c; dev->drv = drv; dev->cur_lun = SCSI_LUN_USE_CDB; - drv->insert = scsi_cdrom_insert; - drv->get_volume = scsi_cdrom_get_volume; + drv->insert = scsi_cdrom_insert; + drv->get_volume = scsi_cdrom_get_volume; drv->get_channel = scsi_cdrom_get_channel; - drv->close = scsi_cdrom_close; - - scsi_cdrom_init(dev); + drv->close = scsi_cdrom_close; if (drv->bus_type == CDROM_BUS_SCSI) { - /* SCSI CD-ROM, attach to the SCSI bus. */ - sd = &scsi_devices[scsi_bus][scsi_id]; + valid = 1; - sd->sc = (scsi_common_t *) dev; - sd->command = scsi_cdrom_command; - sd->request_sense = scsi_cdrom_request_sense_for_scsi; - sd->reset = scsi_cdrom_reset; - sd->phase_data_out = scsi_cdrom_phase_data_out; - sd->command_stop = scsi_cdrom_command_stop; - sd->type = SCSI_REMOVABLE_CDROM; + if (!dev->tf) + dev->tf = (ide_tf_t *) calloc(1, sizeof(ide_tf_t)); - scsi_cdrom_log("SCSI CD-ROM drive %i attached to SCSI ID %i\n", c, cdrom[c].scsi_device_id); + /* SCSI CD-ROM, attach to the SCSI bus. */ + sd = &scsi_devices[scsi_bus][scsi_id]; + + sd->sc = (scsi_common_t *) dev; + sd->command = scsi_cdrom_command; + sd->request_sense = scsi_cdrom_request_sense_for_scsi; + sd->reset = scsi_cdrom_reset; + sd->phase_data_out = scsi_cdrom_phase_data_out; + sd->command_stop = scsi_cdrom_command_stop; + sd->type = SCSI_REMOVABLE_CDROM; + + scsi_cdrom_log("SCSI CD-ROM drive %i attached to SCSI ID %i\n", c, cdrom[c].scsi_device_id); } else if (drv->bus_type == CDROM_BUS_ATAPI) { - /* ATAPI CD-ROM, attach to the IDE bus. */ - id = ide_get_drive(drv->ide_channel); - /* If the IDE channel is initialized, we attach to it, - otherwise, we do nothing - it's going to be a drive - that's not attached to anything. */ - if (id) { - id->sc = (scsi_common_t *) dev; - id->get_max = scsi_cdrom_get_max; - id->get_timings = scsi_cdrom_get_timings; - id->identify = scsi_cdrom_identify; - id->stop = scsi_cdrom_stop; - id->packet_command = scsi_cdrom_command; - id->device_reset = scsi_cdrom_reset; - id->phase_data_out = scsi_cdrom_phase_data_out; - id->command_stop = scsi_cdrom_command_stop; - id->bus_master_error = scsi_cdrom_bus_master_error; - id->interrupt_drq = 0; + /* ATAPI CD-ROM, attach to the IDE bus. */ + id = ide_get_drive(drv->ide_channel); + /* If the IDE channel is initialized, we attach to it, + otherwise, we do nothing - it's going to be a drive + that's not attached to anything. */ + if (id) { + valid = 1; - ide_atapi_attach(id); - } + id->sc = (scsi_common_t *) dev; + dev->tf = id->tf; + if ((dev->drv->type == CDROM_TYPE_NEC_260_100) || (dev->drv->type == CDROM_TYPE_NEC_260_101)) + IDE_ATAPI_IS_EARLY = 1; + id->get_max = scsi_cdrom_get_max; + id->get_timings = scsi_cdrom_get_timings; + id->identify = scsi_cdrom_identify; + id->stop = scsi_cdrom_stop; + id->packet_command = scsi_cdrom_command; + id->device_reset = scsi_cdrom_reset; + id->phase_data_out = scsi_cdrom_phase_data_out; + id->command_stop = scsi_cdrom_command_stop; + id->bus_master_error = scsi_cdrom_bus_master_error; + id->interrupt_drq = ((dev->drv->type == CDROM_TYPE_NEC_260_100) || + (dev->drv->type == CDROM_TYPE_NEC_260_101)); - scsi_cdrom_log("ATAPI CD-ROM drive %i attached to IDE channel %i\n", c, cdrom[c].ide_channel); + ide_atapi_attach(id); + } + + scsi_cdrom_log("ATAPI CD-ROM drive %i attached to IDE channel %i\n", c, cdrom[c].ide_channel); } + + if (valid) + scsi_cdrom_init(dev); } diff --git a/src/scsi/scsi_device.c b/src/scsi/scsi_device.c index 09e44a914..4442b2680 100644 --- a/src/scsi/scsi_device.c +++ b/src/scsi/scsi_device.c @@ -1,20 +1,20 @@ /* - * 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. + * 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. + * This file is part of the 86Box distribution. * - * The generic SCSI device command handler. + * The generic SCSI device command handler. * * * - * Authors: Miran Grca, - * Fred N. van Kempen, + * Authors: Miran Grca, + * Fred N. van Kempen, * - * Copyright 2016-2018 Miran Grca. - * Copyright 2017,2018 Fred N. van Kempen. + * Copyright 2016-2018 Miran Grca. + * Copyright 2017-2018 Fred N. van Kempen. */ #include #include @@ -23,184 +23,169 @@ #include <86box/86box.h> #include <86box/device.h> #include <86box/hdd.h> +#include <86box/hdc_ide.h> #include <86box/scsi.h> #include <86box/scsi_device.h> +#include <86box/plat_unused.h> +scsi_device_t scsi_devices[SCSI_BUS_MAX][SCSI_ID_MAX]; -scsi_device_t scsi_devices[SCSI_BUS_MAX][SCSI_ID_MAX]; - -uint8_t scsi_null_device_sense[18] = { 0x70,0,SENSE_ILLEGAL_REQUEST,0,0,0,0,0,0,0,0,0,ASC_INV_LUN,0,0,0,0,0 }; - +uint8_t scsi_null_device_sense[18] = { 0x70, 0, SENSE_ILLEGAL_REQUEST, 0, 0, 0, 0, 0, 0, 0, 0, 0, ASC_INV_LUN, 0, 0, 0, 0, 0 }; static uint8_t scsi_device_target_command(scsi_device_t *dev, uint8_t *cdb) { if (dev->command) { - dev->command(dev->sc, cdb); + dev->command(dev->sc, cdb); - if (dev->sc->status & ERR_STAT) - return SCSI_STATUS_CHECK_CONDITION; - else - return SCSI_STATUS_OK; + if (dev->sc->tf->status & ERR_STAT) + return SCSI_STATUS_CHECK_CONDITION; + else + return SCSI_STATUS_OK; } else - return SCSI_STATUS_CHECK_CONDITION; + return SCSI_STATUS_CHECK_CONDITION; } - double scsi_device_get_callback(scsi_device_t *dev) { if (dev->sc) - return dev->sc->callback; + return dev->sc->callback; else - return -1.0; + return -1.0; } - uint8_t * scsi_device_sense(scsi_device_t *dev) { if (dev->sc) - return dev->sc->sense; + return dev->sc->sense; else - return scsi_null_device_sense; + return scsi_null_device_sense; } - void scsi_device_request_sense(scsi_device_t *dev, uint8_t *buffer, uint8_t alloc_length) { if (dev->request_sense) - dev->request_sense(dev->sc, buffer, alloc_length); + dev->request_sense(dev->sc, buffer, alloc_length); else - memcpy(buffer, scsi_null_device_sense, alloc_length); + memcpy(buffer, scsi_null_device_sense, alloc_length); } - void scsi_device_reset(scsi_device_t *dev) { if (dev->reset) - dev->reset(dev->sc); + dev->reset(dev->sc); } - int scsi_device_present(scsi_device_t *dev) { if (dev->type == SCSI_NONE) - return 0; + return 0; else - return 1; + return 1; } - int scsi_device_valid(scsi_device_t *dev) { if (dev->sc) - return 1; + return 1; else - return 0; + return 0; } - int -scsi_device_cdb_length(scsi_device_t *dev) +scsi_device_cdb_length(UNUSED(scsi_device_t *dev)) { /* Right now, it's 12 for all devices. */ return 12; } - void scsi_device_command_phase0(scsi_device_t *dev, uint8_t *cdb) { if (!dev->sc) { - dev->phase = SCSI_PHASE_STATUS; - dev->status = SCSI_STATUS_CHECK_CONDITION; - return; + dev->phase = SCSI_PHASE_STATUS; + dev->status = SCSI_STATUS_CHECK_CONDITION; + return; } /* Finally, execute the SCSI command immediately and get the transfer length. */ - dev->phase = SCSI_PHASE_COMMAND; + dev->phase = SCSI_PHASE_COMMAND; dev->status = scsi_device_target_command(dev, cdb); } - void scsi_device_command_stop(scsi_device_t *dev) { if (dev->command_stop) { - dev->command_stop(dev->sc); - dev->status = SCSI_STATUS_OK; + dev->command_stop(dev->sc); + dev->status = SCSI_STATUS_OK; } } - void scsi_device_command_phase1(scsi_device_t *dev) { if (!dev->sc) - return; + return; /* Call the second phase. */ if (dev->phase == SCSI_PHASE_DATA_OUT) { - if (dev->phase_data_out) - dev->phase_data_out(dev->sc); + if (dev->phase_data_out) + dev->phase_data_out(dev->sc); } else - scsi_device_command_stop(dev); + scsi_device_command_stop(dev); - if (dev->sc->status & ERR_STAT) - dev->status = SCSI_STATUS_CHECK_CONDITION; + if (dev->sc->tf->status & ERR_STAT) + dev->status = SCSI_STATUS_CHECK_CONDITION; else - dev->status = SCSI_STATUS_OK; + dev->status = SCSI_STATUS_OK; } - /* When LUN is FF, there has been no IDENTIFY message, otherwise there has been one. */ void scsi_device_identify(scsi_device_t *dev, uint8_t lun) { if ((dev == NULL) || (dev->type == SCSI_NONE) || !dev->sc) - return; + return; dev->sc->cur_lun = lun; /* TODO: This should return a value, should IDENTIFY fail due to a - a LUN not supported by the target. */ + a LUN not supported by the target. */ } - void scsi_device_close_all(void) { - int i, j; scsi_device_t *dev; - for (i = 0; i < SCSI_BUS_MAX; i++) { - for (j = 0; j < SCSI_ID_MAX; j++) { - dev = &(scsi_devices[i][j]); - if (dev->command_stop && dev->sc) - dev->command_stop(dev->sc); - } + for (uint8_t i = 0; i < SCSI_BUS_MAX; i++) { + for (uint8_t j = 0; j < SCSI_ID_MAX; j++) { + dev = &(scsi_devices[i][j]); + if (dev->command_stop && dev->sc) + dev->command_stop(dev->sc); + } } } - void scsi_device_init(void) { - int i, j; scsi_device_t *dev; - for (i = 0; i < SCSI_BUS_MAX; i++) { - for (j = 0; j < SCSI_ID_MAX; j++) { - dev = &(scsi_devices[i][j]); + for (uint8_t i = 0; i < SCSI_BUS_MAX; i++) { + for (uint8_t j = 0; j < SCSI_ID_MAX; j++) { + dev = &(scsi_devices[i][j]); - memset(dev, 0, sizeof(scsi_device_t)); - dev->type = SCSI_NONE; - } + memset(dev, 0, sizeof(scsi_device_t)); + dev->type = SCSI_NONE; + } } } diff --git a/src/scsi/scsi_disk.c b/src/scsi/scsi_disk.c index 85cefaacb..93d29a672 100644 --- a/src/scsi/scsi_disk.c +++ b/src/scsi/scsi_disk.c @@ -1,100 +1,106 @@ /* - * 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. + * 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. * - * Emulation of SCSI fixed disks. + * Emulation of SCSI fixed disks. * * * - * Author: Miran Grca, + * Authors: Miran Grca, * - * Copyright 2017,2018 Miran Grca. + * Copyright 2017-2018 Miran Grca. */ +#include +#include +#include #include #include #include #include -#include #include #define HAVE_STDARG_H #include <86box/86box.h> +#include <86box/config.h> #include <86box/timer.h> #include <86box/device.h> -#include <86box/nvr.h> -#include <86box/hdd.h> -#include <86box/hdc.h> +#include <86box/scsi.h> #include <86box/scsi_device.h> +#include <86box/machine.h> +#include <86box/nvr.h> +#include <86box/hdc.h> #include <86box/hdc_ide.h> +#include <86box/sound.h> #include <86box/plat.h> #include <86box/ui.h> +#include <86box/hdd.h> #include <86box/scsi_disk.h> #include <86box/version.h> +#define IDE_ATAPI_IS_EARLY id->sc->pad0 #define scsi_disk_sense_error dev->sense[0] -#define scsi_disk_sense_key dev->sense[2] -#define scsi_disk_asc dev->sense[12] -#define scsi_disk_ascq dev->sense[13] - +#define scsi_disk_sense_key dev->sense[2] +#define scsi_disk_asc dev->sense[12] +#define scsi_disk_ascq dev->sense[13] /* Table of all SCSI commands and their flags, needed for the new disc change / not ready handler. */ const uint8_t scsi_disk_command_flags[0x100] = { - IMPLEMENTED | CHECK_READY | NONDATA, /* 0x00 */ - IMPLEMENTED | ALLOW_UA | NONDATA | SCSI_ONLY, /* 0x01 */ + IMPLEMENTED | CHECK_READY | NONDATA, /* 0x00 */ + IMPLEMENTED | ALLOW_UA | NONDATA | SCSI_ONLY, /* 0x01 */ 0, - IMPLEMENTED | ALLOW_UA, /* 0x03 */ - IMPLEMENTED | CHECK_READY | ALLOW_UA | NONDATA | SCSI_ONLY, /* 0x04 */ + IMPLEMENTED | ALLOW_UA, /* 0x03 */ + IMPLEMENTED | CHECK_READY | ALLOW_UA | NONDATA | SCSI_ONLY, /* 0x04 */ 0, 0, 0, - IMPLEMENTED | CHECK_READY, /* 0x08 */ + IMPLEMENTED | CHECK_READY, /* 0x08 */ 0, - IMPLEMENTED | CHECK_READY, /* 0x0A */ - IMPLEMENTED | CHECK_READY | NONDATA, /* 0x0B */ + IMPLEMENTED | CHECK_READY, /* 0x0A */ + IMPLEMENTED | CHECK_READY | NONDATA, /* 0x0B */ 0, 0, 0, 0, 0, 0, - IMPLEMENTED | ALLOW_UA, /* 0x12 */ - IMPLEMENTED | CHECK_READY | NONDATA | SCSI_ONLY, /* 0x13 */ + IMPLEMENTED | ALLOW_UA, /* 0x12 */ + IMPLEMENTED | CHECK_READY | NONDATA | SCSI_ONLY, /* 0x13 */ 0, - IMPLEMENTED, /* 0x15 */ - IMPLEMENTED | SCSI_ONLY, /* 0x16 */ - IMPLEMENTED | SCSI_ONLY, /* 0x17 */ + IMPLEMENTED, /* 0x15 */ + IMPLEMENTED | SCSI_ONLY, /* 0x16 */ + IMPLEMENTED | SCSI_ONLY, /* 0x17 */ 0, 0, - IMPLEMENTED, /* 0x1A */ + IMPLEMENTED, /* 0x1A */ 0, 0, - IMPLEMENTED, /* 0x1D */ - IMPLEMENTED | CHECK_READY, /* 0x1E */ + IMPLEMENTED, /* 0x1D */ + IMPLEMENTED | CHECK_READY, /* 0x1E */ 0, 0, 0, 0, 0, 0, - IMPLEMENTED | CHECK_READY, /* 0x25 */ + IMPLEMENTED | CHECK_READY, /* 0x25 */ 0, 0, - IMPLEMENTED | CHECK_READY, /* 0x28 */ + IMPLEMENTED | CHECK_READY, /* 0x28 */ 0, - IMPLEMENTED | CHECK_READY, /* 0x2A */ - IMPLEMENTED | CHECK_READY | NONDATA, /* 0x2B */ + IMPLEMENTED | CHECK_READY, /* 0x2A */ + IMPLEMENTED | CHECK_READY | NONDATA, /* 0x2B */ 0, 0, - IMPLEMENTED | CHECK_READY, /* 0x2E */ - IMPLEMENTED | CHECK_READY | NONDATA | SCSI_ONLY, /* 0x2F */ + IMPLEMENTED | CHECK_READY, /* 0x2E */ + IMPLEMENTED | CHECK_READY | NONDATA | SCSI_ONLY, /* 0x2F */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - IMPLEMENTED | CHECK_READY, /* 0x41 */ + IMPLEMENTED | CHECK_READY, /* 0x41 */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - IMPLEMENTED, /* 0x55 */ + IMPLEMENTED, /* 0x55 */ 0, 0, 0, 0, - IMPLEMENTED, /* 0x5A */ + IMPLEMENTED, /* 0x5A */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - IMPLEMENTED | CHECK_READY, /* 0xA8 */ + IMPLEMENTED | CHECK_READY, /* 0xA8 */ 0, - IMPLEMENTED | CHECK_READY, /* 0xAA */ + IMPLEMENTED | CHECK_READY, /* 0xAA */ 0, 0, 0, - IMPLEMENTED | CHECK_READY, /* 0xAE */ - IMPLEMENTED | CHECK_READY | NONDATA | SCSI_ONLY, /* 0xAF */ + IMPLEMENTED | CHECK_READY, /* 0xAE */ + IMPLEMENTED | CHECK_READY | NONDATA | SCSI_ONLY, /* 0xAF */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - IMPLEMENTED, /* 0xBD */ + IMPLEMENTED, /* 0xBD */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, @@ -102,195 +108,405 @@ const uint8_t scsi_disk_command_flags[0x100] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }; - -uint64_t scsi_disk_mode_sense_page_flags = (GPMODEP_FORMAT_DEVICE_PAGE | - GPMODEP_RIGID_DISK_PAGE | - GPMODEP_UNK_VENDOR_PAGE | - GPMODEP_ALL_PAGES); +uint64_t scsi_disk_mode_sense_page_flags = (GPMODEP_FORMAT_DEVICE_PAGE | GPMODEP_RIGID_DISK_PAGE | GPMODEP_UNK_VENDOR_PAGE | GPMODEP_ALL_PAGES); /* This should be done in a better way but for time being, it's been done this way so it's not as huge and more readable. */ -static const mode_sense_pages_t scsi_disk_mode_sense_pages_default = -{ { [GPMODE_FORMAT_DEVICE_PAGE] = { GPMODE_FORMAT_DEVICE_PAGE, 0x16, 0, 1, 0, 1, 0, 1, 0, 1, 1, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, - [GPMODE_RIGID_DISK_PAGE ] = { GPMODE_RIGID_DISK_PAGE, 0x16, 0, 0x10, 0, 64, 0, 0, 0, 0, 0, 0, 0, 200, 0xff, 0xff, 0xff, 0, 0, 0, 0x15, 0x18, 0, 0 }, - [GPMODE_UNK_VENDOR_PAGE ] = { 0xB0, 0x16, '8', '6', 'B', 'o', 'x', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ' } -} }; +static const mode_sense_pages_t scsi_disk_mode_sense_pages_default = { + {[GPMODE_FORMAT_DEVICE_PAGE] = { GPMODE_FORMAT_DEVICE_PAGE, 0x16, 0, 1, 0, 1, 0, 1, 0, 1, 1, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, + [GPMODE_RIGID_DISK_PAGE] = { GPMODE_RIGID_DISK_PAGE, 0x16, 0, 0x10, 0, 64, 0, 0, 0, 0, 0, 0, 0, 200, 0xff, 0xff, 0xff, 0, 0, 0, 0x15, 0x18, 0, 0 }, + [GPMODE_UNK_VENDOR_PAGE] = { 0xB0, 0x16, '8', '6', 'B', 'o', 'x', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ' }} +}; -static const mode_sense_pages_t scsi_disk_mode_sense_pages_changeable = -{ { [GPMODE_FORMAT_DEVICE_PAGE] = { GPMODE_FORMAT_DEVICE_PAGE, 0x16, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, - [GPMODE_RIGID_DISK_PAGE ] = { GPMODE_RIGID_DISK_PAGE, 0x16, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, - [GPMODE_UNK_VENDOR_PAGE ] = { 0xB0, 0x16, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF } -} }; +static const mode_sense_pages_t scsi_disk_mode_sense_pages_changeable = { + {[GPMODE_FORMAT_DEVICE_PAGE] = { GPMODE_FORMAT_DEVICE_PAGE, 0x16, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, + [GPMODE_RIGID_DISK_PAGE] = { GPMODE_RIGID_DISK_PAGE, 0x16, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, + [GPMODE_UNK_VENDOR_PAGE] = { 0xB0, 0x16, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF }} +}; +static void scsi_disk_command_complete(scsi_disk_t *dev); + +static void scsi_disk_mode_sense_load(scsi_disk_t *dev); + +static void scsi_disk_init(scsi_disk_t *dev); #ifdef ENABLE_SCSI_DISK_LOG int scsi_disk_do_log = ENABLE_SCSI_DISK_LOG; - static void scsi_disk_log(const char *fmt, ...) { va_list ap; if (scsi_disk_do_log) { - va_start(ap, fmt); - pclog_ex(fmt, ap); - va_end(ap); + va_start(ap, fmt); + pclog_ex(fmt, ap); + va_end(ap); } } #else -#define scsi_disk_log(fmt, ...) +# define scsi_disk_log(fmt, ...) #endif +static void +scsi_disk_set_callback(scsi_disk_t *dev) +{ + if (dev->drv->bus != HDD_BUS_SCSI) + ide_set_callback(ide_drives[dev->drv->ide_channel], dev->callback); +} + +static void +scsi_disk_init(scsi_disk_t *dev) +{ + if (!dev) + return; + + /* Do a reset (which will also rezero it). */ + scsi_disk_reset((scsi_common_t *) dev); + + /* Configure the drive. */ + dev->requested_blocks = 1; + + dev->drv->bus_mode = 0; + if (dev->drv->bus >= HDD_BUS_ATAPI) + dev->drv->bus_mode |= 2; + if (dev->drv->bus < HDD_BUS_SCSI) + dev->drv->bus_mode |= 1; + scsi_disk_log("SCSI HDD %i: Bus type %i, bus mode %i\n", + dev->id, dev->drv->bus, dev->drv->bus_mode); + + dev->sense[0] = 0xf0; + dev->sense[7] = 10; + /* NEC only */ + dev->tf->status = 0; + dev->tf->pos = 0; + dev->packet_status = PHASE_NONE; + scsi_disk_sense_key = scsi_disk_asc = scsi_disk_ascq = dev->unit_attention = 0; + scsi_disk_mode_sense_load(dev); +} + +/* Returns: 0 for none, 1 for PIO, 2 for DMA. */ +static int +scsi_disk_current_mode(scsi_disk_t *dev) +{ + if (dev->drv->bus == HDD_BUS_SCSI) + return 2; + else if (dev->drv->bus == HDD_BUS_ATAPI) { + scsi_disk_log("SCSI DISK %i: ATAPI drive, setting to %s\n", dev->id, + (dev->tf->features & 1) ? "DMA" : "PIO", + dev->id); + return (dev->tf->features & 1) ? 2 : 1; + } + + return 0; +} void scsi_disk_mode_sense_load(scsi_disk_t *dev) { - FILE *f; - char file_name[512]; + FILE *fp; + char file_name[512]; memset(&dev->ms_pages_saved, 0, sizeof(mode_sense_pages_t)); memcpy(&dev->ms_pages_saved, &scsi_disk_mode_sense_pages_default, sizeof(mode_sense_pages_t)); memset(file_name, 0, 512); sprintf(file_name, "scsi_disk_%02i_mode_sense.bin", dev->id); - f = plat_fopen(nvr_path(file_name), "rb"); - if (f) { - if (fread(dev->ms_pages_saved.pages[0x30], 1, 0x18, f) != 0x18) - fatal("scsi_disk_mode_sense_load(): Error reading data\n"); - fclose(f); + fp = plat_fopen(nvr_path(file_name), "rb"); + if (fp) { + if (fread(dev->ms_pages_saved.pages[0x30], 1, 0x18, fp) != 0x18) + fatal("scsi_disk_mode_sense_load(): Error reading data\n"); + fclose(fp); } } - void scsi_disk_mode_sense_save(scsi_disk_t *dev) { - FILE *f; - char file_name[512]; + FILE *fp; + char file_name[512]; memset(file_name, 0, 512); sprintf(file_name, "scsi_disk_%02i_mode_sense.bin", dev->id); - f = plat_fopen(nvr_path(file_name), "wb"); - if (f) { - fwrite(dev->ms_pages_saved.pages[0x30], 1, 0x18, f); - fclose(f); + fp = plat_fopen(nvr_path(file_name), "wb"); + if (fp) { + fwrite(dev->ms_pages_saved.pages[0x30], 1, 0x18, fp); + fclose(fp); } } - /*SCSI Mode Sense 6/10*/ uint8_t scsi_disk_mode_sense_read(scsi_disk_t *dev, uint8_t page_control, uint8_t page, uint8_t pos) { if (page_control == 1) - return scsi_disk_mode_sense_pages_changeable.pages[page][pos]; + return scsi_disk_mode_sense_pages_changeable.pages[page][pos]; - if (page == GPMODE_RIGID_DISK_PAGE) switch (page_control) { - /* Rigid disk geometry page. */ - case 0: - case 2: - case 3: - switch(pos) { - case 0: - case 1: - default: - return scsi_disk_mode_sense_pages_default.pages[page][pos]; - case 2: - case 6: - case 9: - return (dev->drv->tracks >> 16) & 0xff; - case 3: - case 7: - case 10: - return (dev->drv->tracks >> 8) & 0xff; - case 4: - case 8: - case 11: - return dev->drv->tracks & 0xff; - case 5: - return dev->drv->hpc & 0xff; - } - break; - } else if (page == GPMODE_FORMAT_DEVICE_PAGE) switch (page_control) { - /* Format device page. */ - case 0: - case 2: - case 3: - switch(pos) { - case 0: - case 1: - default: - return scsi_disk_mode_sense_pages_default.pages[page][pos]; - /* Actual sectors + the 1 "alternate sector" we report. */ - case 10: - return ((dev->drv->spt + 1) >> 8) & 0xff; - case 11: - return (dev->drv->spt + 1) & 0xff; - } - break; - } else switch (page_control) { - case 0: - case 3: - return dev->ms_pages_saved.pages[page][pos]; - case 2: - return scsi_disk_mode_sense_pages_default.pages[page][pos]; - } + if (page == GPMODE_RIGID_DISK_PAGE) + switch (page_control) { + /* Rigid disk geometry page. */ + case 0: + case 2: + case 3: + switch (pos) { + default: + case 0: + case 1: + return scsi_disk_mode_sense_pages_default.pages[page][pos]; + case 2: + case 6: + case 9: + return (dev->drv->tracks >> 16) & 0xff; + case 3: + case 7: + case 10: + return (dev->drv->tracks >> 8) & 0xff; + case 4: + case 8: + case 11: + return dev->drv->tracks & 0xff; + case 5: + return dev->drv->hpc & 0xff; + } + + default: + break; + } + else if (page == GPMODE_FORMAT_DEVICE_PAGE) + switch (page_control) { + /* Format device page. */ + case 0: + case 2: + case 3: + switch (pos) { + default: + case 0: + case 1: + return scsi_disk_mode_sense_pages_default.pages[page][pos]; + /* Actual sectors + the 1 "alternate sector" we report. */ + case 10: + return ((dev->drv->spt + 1) >> 8) & 0xff; + case 11: + return (dev->drv->spt + 1) & 0xff; + } + + default: + break; + } + else + switch (page_control) { + case 0: + case 3: + return dev->ms_pages_saved.pages[page][pos]; + case 2: + return scsi_disk_mode_sense_pages_default.pages[page][pos]; + + default: + break; + } return 0; } - uint32_t scsi_disk_mode_sense(scsi_disk_t *dev, uint8_t *buf, uint32_t pos, uint8_t page, uint8_t block_descriptor_len) { - uint8_t msplen, page_control = (page >> 6) & 3; - - int i = 0, j = 0; - int size = 0; + uint8_t msplen; + uint8_t page_control = (page >> 6) & 3; + int size = 0; page &= 0x3f; size = hdd_image_get_last_sector(dev->id); if (block_descriptor_len) { - buf[pos++] = 1; /* Density code. */ - buf[pos++] = (size >> 16) & 0xff; /* Number of blocks (0 = all). */ - buf[pos++] = (size >> 8) & 0xff; - buf[pos++] = size & 0xff; - buf[pos++] = 0; /* Reserved. */ - buf[pos++] = 0; /* Block length (0x200 = 512 bytes). */ - buf[pos++] = 2; - buf[pos++] = 0; + buf[pos++] = 1; /* Density code. */ + buf[pos++] = (size >> 16) & 0xff; /* Number of blocks (0 = all). */ + buf[pos++] = (size >> 8) & 0xff; + buf[pos++] = size & 0xff; + buf[pos++] = 0; /* Reserved. */ + buf[pos++] = 0; /* Block length (0x200 = 512 bytes). */ + buf[pos++] = 2; + buf[pos++] = 0; } - for (i = 0; i < 0x40; i++) { + for (uint8_t i = 0; i < 0x40; i++) { if ((page == GPMODE_ALL_PAGES) || (page == i)) { - if (scsi_disk_mode_sense_page_flags & (1LL << (uint64_t) page)) { - buf[pos++] = scsi_disk_mode_sense_read(dev, page_control, i, 0); - msplen = scsi_disk_mode_sense_read(dev, page_control, i, 1); - buf[pos++] = msplen; - scsi_disk_log("SCSI HDD %i: MODE SENSE: Page [%02X] length %i\n", dev->id, i, msplen); - for (j = 0; j < msplen; j++) - buf[pos++] = scsi_disk_mode_sense_read(dev, page_control, i, 2 + j); - } - } + if (scsi_disk_mode_sense_page_flags & (1LL << (uint64_t) page)) { + buf[pos++] = scsi_disk_mode_sense_read(dev, page_control, i, 0); + msplen = scsi_disk_mode_sense_read(dev, page_control, i, 1); + buf[pos++] = msplen; + scsi_disk_log("SCSI HDD %i: MODE SENSE: Page [%02X] length %i\n", dev->id, i, msplen); + for (uint8_t j = 0; j < msplen; j++) + buf[pos++] = scsi_disk_mode_sense_read(dev, page_control, i, 2 + j); + } + } } return pos; } - static void -scsi_disk_command_common(scsi_disk_t *dev) +scsi_disk_update_request_length(scsi_disk_t *dev, int len, int block_len) { - dev->status = BUSY_STAT; - dev->phase = 1; - if (dev->packet_status == PHASE_COMPLETE) - dev->callback = 0.0; - else - dev->callback = -1.0; /* Speed depends on SCSI controller */ + int bt; + int min_len = 0; + + dev->max_transfer_len = dev->tf->request_length; + + /* For media access commands, make sure the requested DRQ length matches the block length. */ + switch (dev->current_cdb[0]) { + case 0x08: + case 0x0a: + case 0x28: + case 0x2a: + case 0xa8: + case 0xaa: + /* Round it to the nearest 2048 bytes. */ + dev->max_transfer_len = (dev->max_transfer_len >> 9) << 9; + + /* Make sure total length is not bigger than sum of the lengths of + all the requested blocks. */ + bt = (dev->requested_blocks * block_len); + if (len > bt) + len = bt; + + min_len = block_len; + + if (len <= block_len) { + /* Total length is less or equal to block length. */ + if (dev->max_transfer_len < block_len) { + /* Transfer a minimum of (block size) bytes. */ + dev->max_transfer_len = block_len; + dev->packet_len = block_len; + break; + } + } + fallthrough; + + default: + dev->packet_len = len; + break; + } + /* If the DRQ length is odd, and the total remaining length is bigger, make sure it's even. */ + if ((dev->max_transfer_len & 1) && (dev->max_transfer_len < len)) + dev->max_transfer_len &= 0xfffe; + /* If the DRQ length is smaller or equal in size to the total remaining length, set it to that. */ + if (!dev->max_transfer_len) + dev->max_transfer_len = 65534; + + if ((len <= dev->max_transfer_len) && (len >= min_len)) + dev->tf->request_length = dev->max_transfer_len = len; + else if (len > dev->max_transfer_len) + dev->tf->request_length = dev->max_transfer_len; + + return; } +static double +scsi_disk_bus_speed(scsi_disk_t *dev) +{ + double ret = -1.0; + + if (dev && dev->drv && (dev->drv->bus == HDD_BUS_SCSI)) { + dev->callback = -1.0; /* Speed depends on SCSI controller */ + return 0.0; + } else { + if (dev && dev->drv) + ret = ide_atapi_get_period(dev->drv->ide_channel); + if (ret == -1.0) { + if (dev) + dev->callback = -1.0; + return 0.0; + } else + return ret * 1000000.0; + } +} + +void +scsi_disk_command_common(scsi_disk_t *dev) +{ + double bytes_per_second = 0.0; + double period; + + /* MAP: BUSY_STAT, no DRQ, phase 1. */ + dev->tf->status = BUSY_STAT; + dev->tf->phase = 1; + dev->tf->pos = 0; + dev->callback = 0; + + if (dev->packet_status == PHASE_COMPLETE) { + switch (dev->current_cdb[0]) { + case GPCMD_VERIFY_6: + case GPCMD_VERIFY_10: + case GPCMD_VERIFY_12: + case GPCMD_WRITE_6: + case GPCMD_WRITE_10: + case GPCMD_WRITE_AND_VERIFY_10: + case GPCMD_WRITE_12: + case GPCMD_WRITE_AND_VERIFY_12: + case GPCMD_WRITE_SAME_10: + /* Seek time is in us. */ + period = hdd_timing_write(dev->drv, dev->sector_pos, dev->packet_len >> 9); + scsi_disk_log("SCSI HD %i: Seek period: %" PRIu64 " us\n", + dev->id, (uint64_t) period); + dev->callback += period; + /* Account for seek time. */ + bytes_per_second = scsi_bus_get_speed(dev->drv->scsi_id >> 4); + + period = 1000000.0 / bytes_per_second; + scsi_disk_log("SCSI HD %i: Byte transfer period: %" PRIu64 " us\n", dev->id, + (uint64_t) period); + period = period * (double) (dev->packet_len); + scsi_disk_log("CD-ROM %i: Sector transfer period: %" PRIu64 " us\n", dev->id, + (uint64_t) period); + dev->callback += period; + break; + default: + dev->callback = 0; + break; + } + } else { + switch (dev->current_cdb[0]) { + case GPCMD_REZERO_UNIT: + case 0x0b: + case 0x2b: + /* Seek time is in us. */ + period = hdd_seek_get_time(dev->drv, (dev->current_cdb[0] == GPCMD_REZERO_UNIT) ? + 0 : dev->sector_pos, HDD_OP_SEEK, 0, 0.0); + scsi_disk_log("SCSI HD %i: Seek period: %" PRIu64 " us\n", + dev->id, (uint64_t) period); + dev->callback += period; + scsi_disk_set_callback(dev); + return; + case 0x08: + case 0x28: + case 0xa8: + /* Seek time is in us. */ + period = hdd_timing_read(dev->drv, dev->sector_pos, dev->packet_len >> 9); + scsi_disk_log("SCSI HD %i: Seek period: %" PRIu64 " us\n", + dev->id, (uint64_t) period); + dev->callback += period; + /* Account for seek time. */ + bytes_per_second = scsi_bus_get_speed(dev->drv->scsi_id >> 4); + break; + case 0x25: + default: + bytes_per_second = scsi_disk_bus_speed(dev); + if (bytes_per_second == 0.0) { + dev->callback = -1; /* Speed depends on SCSI controller */ + return; + } + break; + } + + period = 1000000.0 / bytes_per_second; + scsi_disk_log("SCSI HD %i: Byte transfer period: %" PRIu64 " us\n", dev->id, (uint64_t) period); + period = period * (double) (dev->packet_len); + scsi_disk_log("SCSI HD %i: Sector transfer period: %" PRIu64 " us\n", dev->id, (uint64_t) period); + dev->callback += period; + } + scsi_disk_set_callback(dev); +} static void scsi_disk_command_complete(scsi_disk_t *dev) @@ -300,6 +516,12 @@ scsi_disk_command_complete(scsi_disk_t *dev) scsi_disk_command_common(dev); } +static void +scsi_disk_command_read(scsi_disk_t *dev) +{ + dev->packet_status = PHASE_DATA_IN; + scsi_disk_command_common(dev); +} static void scsi_disk_command_read_dma(scsi_disk_t *dev) @@ -308,6 +530,12 @@ scsi_disk_command_read_dma(scsi_disk_t *dev) scsi_disk_command_common(dev); } +static void +scsi_disk_command_write(scsi_disk_t *dev) +{ + dev->packet_status = PHASE_DATA_OUT; + scsi_disk_command_common(dev); +} static void scsi_disk_command_write_dma(scsi_disk_t *dev) @@ -316,151 +544,231 @@ scsi_disk_command_write_dma(scsi_disk_t *dev) scsi_disk_command_common(dev); } - +/* id = Current ZIP device ID; + len = Total transfer length; + block_len = Length of a single block (why does it matter?!); + alloc_len = Allocated transfer length; + direction = Transfer direction (0 = read from host, 1 = write to host). */ static void scsi_disk_data_command_finish(scsi_disk_t *dev, int len, int block_len, int alloc_len, int direction) { - scsi_disk_log("SCSI HD %i: Finishing command (%02X): %i, %i, %i, %i, %i\n", dev->id, - dev->current_cdb[0], len, block_len, alloc_len, direction, dev->request_length); + scsi_disk_log("SCSI HD %i: Finishing command (%02X): %i, %i, %i, %i, %i\n", + dev->id, dev->current_cdb[0], len, block_len, alloc_len, direction, + dev->tf->request_length); + dev->tf->pos = 0; if (alloc_len >= 0) { - if (alloc_len < len) - len = alloc_len; + if (alloc_len < len) + len = alloc_len; } - if (len == 0) - scsi_disk_command_complete(dev); - else { - if (direction == 0) - scsi_disk_command_read_dma(dev); - else - scsi_disk_command_write_dma(dev); + if ((len == 0) || (scsi_disk_current_mode(dev) == 0)) { + if (dev->drv->bus != HDD_BUS_SCSI) + dev->packet_len = 0; + + scsi_disk_command_complete(dev); + } else { + if (scsi_disk_current_mode(dev) == 2) { + if (dev->drv->bus != HDD_BUS_SCSI) + dev->packet_len = alloc_len; + + if (direction == 0) + scsi_disk_command_read_dma(dev); + else + scsi_disk_command_write_dma(dev); + } else { + scsi_disk_update_request_length(dev, len, block_len); + if (direction == 0) + scsi_disk_command_read(dev); + else + scsi_disk_command_write(dev); + } } + + scsi_disk_log("SCSI HD %i: Status: %i, cylinder %i, packet length: %i, position: %i, phase: %i\n", + dev->id, dev->packet_status, dev->tf->request_length, dev->packet_len, dev->tf->pos, + dev->tf->phase); } - static void -scsi_disk_sense_clear(scsi_disk_t *dev, int command) +scsi_disk_sense_clear(scsi_disk_t *dev, UNUSED(int command)) { scsi_disk_sense_key = scsi_disk_asc = scsi_disk_ascq = 0; } - static void scsi_disk_set_phase(scsi_disk_t *dev, uint8_t phase) { uint8_t scsi_bus = (dev->drv->scsi_id >> 4) & 0x0f; - uint8_t scsi_id = dev->drv->scsi_id & 0x0f; + uint8_t scsi_id = dev->drv->scsi_id & 0x0f; if (dev->drv->bus != HDD_BUS_SCSI) - return; + return; scsi_devices[scsi_bus][scsi_id].phase = phase; } - static void scsi_disk_cmd_error(scsi_disk_t *dev) { scsi_disk_set_phase(dev, SCSI_PHASE_STATUS); - dev->error = ((scsi_disk_sense_key & 0xf) << 4) | ABRT_ERR; - dev->status = READY_STAT | ERR_STAT; - dev->phase = 3; + dev->tf->error = ((scsi_disk_sense_key & 0xf) << 4) | ABRT_ERR; + dev->tf->status = READY_STAT | ERR_STAT; + dev->tf->phase = 3; dev->packet_status = PHASE_ERROR; - dev->callback = 50.0 * SCSI_TIME; + dev->callback = 50.0 * SCSI_TIME; + scsi_disk_set_callback(dev); ui_sb_update_icon(SB_HDD | dev->drv->bus, 0); scsi_disk_log("SCSI HD %i: ERROR: %02X/%02X/%02X\n", dev->id, scsi_disk_sense_key, scsi_disk_asc, scsi_disk_ascq); } +static void +scsi_disk_buf_alloc(scsi_disk_t *dev, uint32_t len) +{ + scsi_disk_log("SCSI HD %i: Allocated buffer length: %i\n", dev->id, len); + if (!dev->temp_buffer) + dev->temp_buffer = (uint8_t *) malloc(len); +} + +static void +scsi_disk_buf_free(scsi_disk_t *dev) +{ + if (dev->temp_buffer) { + scsi_disk_log("SCSI HD %i: Freeing buffer...\n", dev->id); + free(dev->temp_buffer); + dev->temp_buffer = NULL; + } +} + +static void +scsi_disk_bus_master_error(scsi_common_t *sc) +{ + scsi_disk_t *dev = (scsi_disk_t *) sc; + + scsi_disk_buf_free(dev); + scsi_disk_sense_key = scsi_disk_asc = scsi_disk_ascq = 0; + scsi_disk_cmd_error(dev); +} static void scsi_disk_invalid_lun(scsi_disk_t *dev) { scsi_disk_sense_key = SENSE_ILLEGAL_REQUEST; - scsi_disk_asc = ASC_INV_LUN; - scsi_disk_ascq = 0; + scsi_disk_asc = ASC_INV_LUN; + scsi_disk_ascq = 0; scsi_disk_set_phase(dev, SCSI_PHASE_STATUS); scsi_disk_cmd_error(dev); } - static void scsi_disk_illegal_opcode(scsi_disk_t *dev) { scsi_disk_sense_key = SENSE_ILLEGAL_REQUEST; - scsi_disk_asc = ASC_ILLEGAL_OPCODE; - scsi_disk_ascq = 0; + scsi_disk_asc = ASC_ILLEGAL_OPCODE; + scsi_disk_ascq = 0; scsi_disk_cmd_error(dev); } - static void scsi_disk_lba_out_of_range(scsi_disk_t *dev) { scsi_disk_sense_key = SENSE_ILLEGAL_REQUEST; - scsi_disk_asc = ASC_LBA_OUT_OF_RANGE; - scsi_disk_ascq = 0; + scsi_disk_asc = ASC_LBA_OUT_OF_RANGE; + scsi_disk_ascq = 0; scsi_disk_cmd_error(dev); } - static void scsi_disk_invalid_field(scsi_disk_t *dev) { scsi_disk_sense_key = SENSE_ILLEGAL_REQUEST; - scsi_disk_asc = ASC_INV_FIELD_IN_CMD_PACKET; - scsi_disk_ascq = 0; + scsi_disk_asc = ASC_INV_FIELD_IN_CMD_PACKET; + scsi_disk_ascq = 0; scsi_disk_cmd_error(dev); - dev->status = 0x53; + dev->tf->status = 0x53; } - static void scsi_disk_invalid_field_pl(scsi_disk_t *dev) { scsi_disk_sense_key = SENSE_ILLEGAL_REQUEST; - scsi_disk_asc = ASC_INV_FIELD_IN_PARAMETER_LIST; - scsi_disk_ascq = 0; + scsi_disk_asc = ASC_INV_FIELD_IN_PARAMETER_LIST; + scsi_disk_ascq = 0; scsi_disk_cmd_error(dev); - dev->status = 0x53; + dev->tf->status = 0x53; } - static void scsi_disk_data_phase_error(scsi_disk_t *dev) { scsi_disk_sense_key = SENSE_ILLEGAL_REQUEST; - scsi_disk_asc = ASC_DATA_PHASE_ERROR; - scsi_disk_ascq = 0; + scsi_disk_asc = ASC_DATA_PHASE_ERROR; + scsi_disk_ascq = 0; scsi_disk_cmd_error(dev); } +static int +scsi_disk_blocks(scsi_disk_t *dev, int32_t *len, UNUSED(int first_batch), int out) +{ + *len = 0; + uint32_t medium_size = hdd_image_get_last_sector(dev->id); + + if (!dev->sector_len) { + scsi_disk_command_complete(dev); + return -1; + } + + scsi_disk_log("%sing %i blocks starting from %i...\n", out ? "Writ" : "Read", + dev->requested_blocks, dev->sector_pos); + + if (dev->sector_pos >= medium_size) { + scsi_disk_log("SCSI HD %i: Trying to %s beyond the end of disk\n", dev->id, out ? "write" : "read"); + scsi_disk_lba_out_of_range(dev); + return 0; + } + + *len = dev->requested_blocks << 9; + + for (int i = 0; i < dev->requested_blocks; i++) { + if (out) + hdd_image_write(dev->id, dev->sector_pos + i, 1, dev->temp_buffer + (i << 9)); + else + hdd_image_read(dev->id, dev->sector_pos + i, 1, dev->temp_buffer + (i << 9)); + } + + scsi_disk_log("%s %i bytes of blocks...\n", out ? "Written" : "Read", *len); + + dev->sector_pos += dev->requested_blocks; + dev->sector_len -= dev->requested_blocks; + + return 1; +} static int scsi_disk_pre_execution_check(scsi_disk_t *dev, uint8_t *cdb) { if ((cdb[0] != GPCMD_REQUEST_SENSE) && (dev->cur_lun == SCSI_LUN_USE_CDB) && (cdb[1] & 0xe0)) { - scsi_disk_log("SCSI HD %i: Attempting to execute a unknown command targeted at SCSI LUN %i\n", - dev->id, ((dev->request_length >> 5) & 7)); - scsi_disk_invalid_lun(dev); - return 0; + scsi_disk_log("SCSI HD %i: Attempting to execute a unknown command targeted at SCSI LUN %i\n", + dev->id, ((dev->tf->request_length >> 5) & 7)); + scsi_disk_invalid_lun(dev); + return 0; } if (!(scsi_disk_command_flags[cdb[0]] & IMPLEMENTED)) { - scsi_disk_log("SCSI HD %i: Attempting to execute unknown command %02X\n", dev->id, cdb[0]); - scsi_disk_illegal_opcode(dev); - return 0; + scsi_disk_log("SCSI HD %i: Attempting to execute unknown command %02X over %s\n", dev->id, cdb[0], + (dev->drv->bus == HDD_BUS_SCSI) ? "SCSI" : "ATAPI"); + scsi_disk_illegal_opcode(dev); + return 0; } /* Unless the command is REQUEST SENSE, clear the sense. This will *NOT* the UNIT ATTENTION condition if it's set. */ if (cdb[0] != GPCMD_REQUEST_SENSE) - scsi_disk_sense_clear(dev, cdb[0]); + scsi_disk_sense_clear(dev, cdb[0]); scsi_disk_log("SCSI HD %i: Continuing with command\n", dev->id); return 1; } - static void scsi_disk_seek(scsi_disk_t *dev, uint32_t pos) { @@ -468,46 +776,47 @@ scsi_disk_seek(scsi_disk_t *dev, uint32_t pos) hdd_image_seek(dev->id, pos); } - static void scsi_disk_rezero(scsi_disk_t *dev) { if (dev->id == 0xff) - return; + return; dev->sector_pos = dev->sector_len = 0; scsi_disk_seek(dev, 0); } - -static void +void scsi_disk_reset(scsi_common_t *sc) { scsi_disk_t *dev = (scsi_disk_t *) sc; scsi_disk_rezero(dev); - dev->status = 0; - dev->callback = 0.0; - dev->packet_status = PHASE_NONE; - dev->cur_lun = SCSI_LUN_USE_CDB; + dev->tf->status = 0; + dev->callback = 0.0; + scsi_disk_set_callback(dev); + dev->tf->phase = 1; + dev->tf->request_length = 0xEB14; + dev->packet_status = PHASE_NONE; + dev->unit_attention = 0; + dev->cur_lun = SCSI_LUN_USE_CDB; } - void scsi_disk_request_sense(scsi_disk_t *dev, uint8_t *buffer, uint8_t alloc_length, int desc) -{ +{ /*Will return 18 bytes of 0*/ if (alloc_length != 0) { - memset(buffer, 0, alloc_length); - if (!desc) - memcpy(buffer, dev->sense, alloc_length); - else { - buffer[1] = scsi_disk_sense_key; - buffer[2] = scsi_disk_asc; - buffer[3] = scsi_disk_ascq; - } + memset(buffer, 0, alloc_length); + if (!desc) + memcpy(buffer, dev->sense, alloc_length); + else { + buffer[1] = scsi_disk_sense_key; + buffer[2] = scsi_disk_asc; + buffer[3] = scsi_disk_ascq; + } } else - return; + return; buffer[0] = 0x70; @@ -517,7 +826,6 @@ scsi_disk_request_sense(scsi_disk_t *dev, uint8_t *buffer, uint8_t alloc_length, scsi_disk_sense_clear(dev, GPCMD_REQUEST_SENSE); } - static void scsi_disk_request_sense_for_scsi(scsi_common_t *sc, uint8_t *buffer, uint8_t alloc_length) { @@ -526,68 +834,59 @@ scsi_disk_request_sense_for_scsi(scsi_common_t *sc, uint8_t *buffer, uint8_t all scsi_disk_request_sense(dev, buffer, alloc_length, 0); } - static void scsi_disk_set_buf_len(scsi_disk_t *dev, int32_t *BufLen, int32_t *src_len) { - if (*BufLen == -1) - *BufLen = *src_len; - else { - *BufLen = MIN(*src_len, *BufLen); - *src_len = *BufLen; - } - scsi_disk_log("SCSI HD %i: Actual transfer length: %i\n", dev->id, *BufLen); -} - - -static void -scsi_disk_buf_alloc(scsi_disk_t *dev, uint32_t len) -{ - scsi_disk_log("SCSI HD %i: Allocated buffer length: %i\n", dev->id, len); - if (!dev->temp_buffer) - dev->temp_buffer = (uint8_t *) malloc(len); -} - - -static void -scsi_disk_buf_free(scsi_disk_t *dev) -{ - if (dev->temp_buffer) { - scsi_disk_log("SCSI HD %i: Freeing buffer...\n", dev->id); - free(dev->temp_buffer); - dev->temp_buffer = NULL; + if (dev->drv->bus == HDD_BUS_SCSI) { + if (*BufLen == -1) + *BufLen = *src_len; + else { + *BufLen = MIN(*src_len, *BufLen); + *src_len = *BufLen; + } + scsi_disk_log("SCSI HD %i: Actual transfer length: %i\n", dev->id, *BufLen); } } - static void scsi_disk_command(scsi_common_t *sc, uint8_t *cdb) { scsi_disk_t *dev = (scsi_disk_t *) sc; - int32_t *BufLen; - int32_t len, max_len, alloc_length; - int pos = 0; - int idx = 0; - unsigned size_idx, preamble_len; - uint32_t last_sector = 0; - char device_identify[9] = { '8', '6', 'B', '_', 'H', 'D', '0', '0', 0 }; - char device_identify_ex[15] = { '8', '6', 'B', '_', 'H', 'D', '0', '0', ' ', 'v', '1', '.', '0', '0', 0 }; - int block_desc = 0; - uint8_t scsi_bus = (dev->drv->scsi_id >> 4) & 0x0f; - uint8_t scsi_id = dev->drv->scsi_id & 0x0f; + int ret; + int32_t blen = 0; + int32_t *BufLen; + int32_t len; + int32_t max_len; + int32_t alloc_length; + int pos = 0; + int idx = 0; + unsigned size_idx; + unsigned preamble_len; + uint32_t last_sector = 0; + char device_identify[9] = { '8', '6', 'B', '_', 'H', 'D', '0', '0', 0 }; + char device_identify_ex[15] = { '8', '6', 'B', '_', 'H', 'D', '0', '0', ' ', 'v', '1', '.', '0', '0', 0 }; + int block_desc = 0; + uint8_t scsi_bus = (dev->drv->scsi_id >> 4) & 0x0f; + uint8_t scsi_id = dev->drv->scsi_id & 0x0f; - BufLen = &scsi_devices[scsi_bus][scsi_id].buffer_length; + if (dev->drv->bus == HDD_BUS_SCSI) { + BufLen = &scsi_devices[scsi_bus][scsi_id].buffer_length; + dev->tf->status &= ~ERR_STAT; + } else { + BufLen = &blen; + dev->tf->error = 0; + } last_sector = hdd_image_get_last_sector(dev->id); - dev->status &= ~ERR_STAT; dev->packet_len = 0; + dev->request_pos = 0; device_identify[6] = (dev->id / 10) + 0x30; device_identify[7] = (dev->id % 10) + 0x30; - device_identify_ex[6] = (dev->id / 10) + 0x30; - device_identify_ex[7] = (dev->id % 10) + 0x30; + device_identify_ex[6] = (dev->id / 10) + 0x30; + device_identify_ex[7] = (dev->id % 10) + 0x30; device_identify_ex[10] = EMU_VERSION_EX[0]; device_identify_ex[12] = EMU_VERSION_EX[2]; device_identify_ex[13] = EMU_VERSION_EX[3]; @@ -595,13 +894,13 @@ scsi_disk_command(scsi_common_t *sc, uint8_t *cdb) memcpy(dev->current_cdb, cdb, 12); if (cdb[0] != 0) { - scsi_disk_log("SCSI HD %i: Command 0x%02X, Sense Key %02X, Asc %02X, Ascq %02X\n", - dev->id, cdb[0], scsi_disk_sense_key, scsi_disk_asc, scsi_disk_ascq); - scsi_disk_log("SCSI HD %i: Request length: %04X\n", dev->id, dev->request_length); + scsi_disk_log("SCSI HD %i: Command 0x%02X, Sense Key %02X, Asc %02X, Ascq %02X\n", + dev->id, cdb[0], scsi_disk_sense_key, scsi_disk_asc, scsi_disk_ascq); + scsi_disk_log("SCSI HD %i: Request length: %04X\n", dev->id, dev->tf->request_length); - scsi_disk_log("SCSI HD %i: CDB: %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X\n", dev->id, - cdb[0], cdb[1], cdb[2], cdb[3], cdb[4], cdb[5], cdb[6], cdb[7], - cdb[8], cdb[9], cdb[10], cdb[11]); + scsi_disk_log("SCSI HD %i: CDB: %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X\n", dev->id, + cdb[0], cdb[1], cdb[2], cdb[3], cdb[4], cdb[5], cdb[6], cdb[7], + cdb[8], cdb[9], cdb[10], cdb[11]); } dev->sector_len = 0; @@ -610,457 +909,503 @@ scsi_disk_command(scsi_common_t *sc, uint8_t *cdb) /* This handles the Not Ready/Unit Attention check if it has to be handled at this point. */ if (scsi_disk_pre_execution_check(dev, cdb) == 0) - return; + return; switch (cdb[0]) { - case GPCMD_SEND_DIAGNOSTIC: - if (!(cdb[1] & (1 << 2))) { - scsi_disk_invalid_field(dev); - return; - } - /*FALLTHROUGH*/ - case GPCMD_SCSI_RESERVE: - case GPCMD_SCSI_RELEASE: - case GPCMD_TEST_UNIT_READY: - case GPCMD_FORMAT_UNIT: - scsi_disk_set_phase(dev, SCSI_PHASE_STATUS); - scsi_disk_command_complete(dev); - break; + case GPCMD_SEND_DIAGNOSTIC: + if (!(cdb[1] & (1 << 2))) { + scsi_disk_invalid_field(dev); + return; + } + fallthrough; + case GPCMD_SCSI_RESERVE: + case GPCMD_SCSI_RELEASE: + case GPCMD_TEST_UNIT_READY: + case GPCMD_FORMAT_UNIT: + scsi_disk_set_phase(dev, SCSI_PHASE_STATUS); + scsi_disk_command_complete(dev); + break; - case GPCMD_REZERO_UNIT: - dev->sector_pos = dev->sector_len = 0; - scsi_disk_seek(dev, 0); - scsi_disk_set_phase(dev, SCSI_PHASE_STATUS); - break; + case GPCMD_REZERO_UNIT: + dev->sector_pos = dev->sector_len = 0; + scsi_disk_seek(dev, 0); + scsi_disk_set_phase(dev, SCSI_PHASE_STATUS); + break; - case GPCMD_REQUEST_SENSE: - /* If there's a unit attention condition and there's a buffered not ready, a standalone REQUEST SENSE - should forget about the not ready, and report unit attention straight away. */ - len = cdb[4]; + case GPCMD_REQUEST_SENSE: + /* If there's a unit attention condition and there's a buffered not + ready, a standalone REQUEST SENSE should forget about the not + ready, and report unit attention straight away. */ + len = cdb[4]; - if (!len) { - scsi_disk_set_phase(dev, SCSI_PHASE_STATUS); - dev->packet_status = PHASE_COMPLETE; - dev->callback = 20.0 * SCSI_TIME; - break; - } + if (!len) { + scsi_disk_set_phase(dev, SCSI_PHASE_STATUS); + dev->packet_status = PHASE_COMPLETE; + dev->callback = 20.0 * SCSI_TIME; + scsi_disk_set_callback(dev); + break; + } - scsi_disk_buf_alloc(dev, 256); - scsi_disk_set_buf_len(dev, BufLen, &len); + scsi_disk_buf_alloc(dev, 256); + scsi_disk_set_buf_len(dev, BufLen, &len); - if (*BufLen < cdb[4]) - cdb[4] = *BufLen; + if (*BufLen < cdb[4]) + cdb[4] = *BufLen; - len = (cdb[1] & 1) ? 8 : 18; + len = (cdb[1] & 1) ? 8 : 18; - scsi_disk_request_sense(dev, dev->temp_buffer, *BufLen, cdb[1] & 1); - scsi_disk_set_phase(dev, SCSI_PHASE_DATA_IN); - scsi_disk_data_command_finish(dev, len, len, cdb[4], 0); - break; + scsi_disk_request_sense(dev, dev->temp_buffer, *BufLen, cdb[1] & 1); + scsi_disk_set_phase(dev, SCSI_PHASE_DATA_IN); + scsi_disk_data_command_finish(dev, len, len, cdb[4], 0); + break; - case GPCMD_MECHANISM_STATUS: - scsi_disk_set_phase(dev, SCSI_PHASE_DATA_IN); - len = (cdb[8] << 8) | cdb[9]; + case GPCMD_MECHANISM_STATUS: + scsi_disk_set_phase(dev, SCSI_PHASE_DATA_IN); + len = (cdb[8] << 8) | cdb[9]; - scsi_disk_buf_alloc(dev, 8); - scsi_disk_set_buf_len(dev, BufLen, &len); + scsi_disk_buf_alloc(dev, 8); + scsi_disk_set_buf_len(dev, BufLen, &len); - memset(dev->temp_buffer, 0, 8); - dev->temp_buffer[5] = 1; + memset(dev->temp_buffer, 0, 8); + dev->temp_buffer[5] = 1; - scsi_disk_data_command_finish(dev, 8, 8, len, 0); - break; + scsi_disk_data_command_finish(dev, 8, 8, len, 0); + break; - case GPCMD_READ_6: - case GPCMD_READ_10: - case GPCMD_READ_12: - switch(cdb[0]) { - case GPCMD_READ_6: - dev->sector_len = cdb[4]; - if (dev->sector_len == 0) - dev->sector_len = 256; /* For READ (6) and WRITE (6), a length of 0 indicates a transfer of 256 sector. */ - dev->sector_pos = ((((uint32_t) cdb[1]) & 0x1f) << 16) | (((uint32_t) cdb[2]) << 8) | ((uint32_t) cdb[3]); - break; - case GPCMD_READ_10: - dev->sector_len = (cdb[7] << 8) | cdb[8]; - dev->sector_pos = (cdb[2] << 24) | (cdb[3] << 16) | (cdb[4] << 8) | cdb[5]; - break; - case GPCMD_READ_12: - dev->sector_len = (((uint32_t) cdb[6]) << 24) | (((uint32_t) cdb[7]) << 16) | (((uint32_t) cdb[8]) << 8) | ((uint32_t) cdb[9]); - dev->sector_pos = (((uint32_t) cdb[2]) << 24) | (((uint32_t) cdb[3]) << 16) | (((uint32_t) cdb[4]) << 8) | ((uint32_t) cdb[5]); - break; - } + case GPCMD_READ_6: + case GPCMD_READ_10: + case GPCMD_READ_12: + scsi_disk_set_phase(dev, SCSI_PHASE_DATA_IN); + alloc_length = 512; - if ((dev->sector_pos > last_sector)/* || ((dev->sector_pos + dev->sector_len - 1) > last_sector)*/) { - scsi_disk_lba_out_of_range(dev); - return; - } + switch (cdb[0]) { + case GPCMD_READ_6: + dev->sector_len = cdb[4]; + /* + For READ (6) and WRITE (6), a length of 0 indicates a + transfer of 256 sectors. + */ + if (dev->sector_len == 0) + dev->sector_len = 256; + dev->sector_pos = ((((uint32_t) cdb[1]) & 0x1f) << 16) | + (((uint32_t) cdb[2]) << 8) | ((uint32_t) cdb[3]); + break; + case GPCMD_READ_10: + dev->sector_len = (cdb[7] << 8) | cdb[8]; + dev->sector_pos = (cdb[2] << 24) | (cdb[3] << 16) | (cdb[4] << 8) | cdb[5]; + break; + case GPCMD_READ_12: + dev->sector_len = (((uint32_t) cdb[6]) << 24) | (((uint32_t) cdb[7]) << 16) | + (((uint32_t) cdb[8]) << 8) | ((uint32_t) cdb[9]); + dev->sector_pos = (((uint32_t) cdb[2]) << 24) | (((uint32_t) cdb[3]) << 16) | + (((uint32_t) cdb[4]) << 8) | ((uint32_t) cdb[5]); + break; - if ((!dev->sector_len) || (*BufLen == 0)) { - scsi_disk_set_phase(dev, SCSI_PHASE_STATUS); - scsi_disk_log("SCSI HD %i: All done - callback set\n", dev); - dev->packet_status = PHASE_COMPLETE; - dev->callback = 20.0 * SCSI_TIME; - break; - } + default: + break; + } - max_len = dev->sector_len; - dev->requested_blocks = max_len; + if (dev->sector_pos > last_sector) { + scsi_disk_lba_out_of_range(dev); + return; + } - alloc_length = dev->packet_len = max_len << 9; - scsi_disk_buf_alloc(dev, dev->packet_len); - scsi_disk_set_buf_len(dev, BufLen, &alloc_length); - scsi_disk_set_phase(dev, SCSI_PHASE_DATA_IN); + if (!dev->sector_len) { + scsi_disk_set_phase(dev, SCSI_PHASE_STATUS); + scsi_disk_log("SCSI HD %i: All done - callback set\n", dev->id); + dev->packet_status = PHASE_COMPLETE; + dev->callback = 20.0 * SCSI_TIME; + scsi_disk_set_callback(dev); + break; + } - if ((dev->requested_blocks > 0) && (*BufLen > 0)) { - if (dev->packet_len > (uint32_t) *BufLen) - hdd_image_read(dev->id, dev->sector_pos, *BufLen >> 9, dev->temp_buffer); - else - hdd_image_read(dev->id, dev->sector_pos, dev->requested_blocks, dev->temp_buffer); - } + max_len = dev->sector_len; + /* + If we're reading all blocks in one go for DMA, why not also for + PIO, it should NOT matter anyway, this step should be identical + and only the way the read dat is transferred to the host should + be different. + */ + dev->requested_blocks = max_len; - if (dev->requested_blocks > 1) - scsi_disk_data_command_finish(dev, alloc_length, alloc_length / dev->requested_blocks, alloc_length, 0); - else - scsi_disk_data_command_finish(dev, alloc_length, alloc_length, alloc_length, 0); + dev->packet_len = max_len * alloc_length; + scsi_disk_buf_alloc(dev, dev->packet_len); - if (dev->packet_status != PHASE_COMPLETE) - ui_sb_update_icon(SB_HDD | dev->drv->bus, 1); - else - ui_sb_update_icon(SB_HDD | dev->drv->bus, 0); - return; + ret = scsi_disk_blocks(dev, &alloc_length, 1, 0); + if (ret <= 0) { + scsi_disk_set_phase(dev, SCSI_PHASE_STATUS); + dev->packet_status = PHASE_COMPLETE; + dev->callback = 20.0 * SCSI_TIME; + scsi_disk_set_callback(dev); + scsi_disk_buf_free(dev); + return; + } - case GPCMD_VERIFY_6: - case GPCMD_VERIFY_10: - case GPCMD_VERIFY_12: - if (!(cdb[1] & 2)) { - scsi_disk_set_phase(dev, SCSI_PHASE_STATUS); - scsi_disk_command_complete(dev); - break; - } - case GPCMD_WRITE_6: - case GPCMD_WRITE_10: - case GPCMD_WRITE_AND_VERIFY_10: - case GPCMD_WRITE_12: - case GPCMD_WRITE_AND_VERIFY_12: - switch(cdb[0]) - { - case GPCMD_VERIFY_6: - case GPCMD_WRITE_6: - dev->sector_len = cdb[4]; - if (dev->sector_len == 0) - dev->sector_len = 256; /* For READ (6) and WRITE (6), a length of 0 indicates a transfer of 256 sector. */ - dev->sector_pos = ((((uint32_t) cdb[1]) & 0x1f) << 16) | (((uint32_t) cdb[2]) << 8) | ((uint32_t) cdb[3]); - scsi_disk_log("SCSI HD %i: Length: %i, LBA: %i\n", dev->id, dev->sector_len, dev->sector_pos); - break; - case GPCMD_VERIFY_10: - case GPCMD_WRITE_10: - case GPCMD_WRITE_AND_VERIFY_10: - dev->sector_len = (cdb[7] << 8) | cdb[8]; - dev->sector_pos = (cdb[2] << 24) | (cdb[3] << 16) | (cdb[4] << 8) | cdb[5]; - scsi_disk_log("SCSI HD %i: Length: %i, LBA: %i\n", dev->id, dev->sector_len, dev->sector_pos); - break; - case GPCMD_VERIFY_12: - case GPCMD_WRITE_12: - case GPCMD_WRITE_AND_VERIFY_12: - dev->sector_len = (((uint32_t) cdb[6]) << 24) | (((uint32_t) cdb[7]) << 16) | (((uint32_t) cdb[8]) << 8) | ((uint32_t) cdb[9]); - dev->sector_pos = (((uint32_t) cdb[2]) << 24) | (((uint32_t) cdb[3]) << 16) | (((uint32_t) cdb[4]) << 8) | ((uint32_t) cdb[5]); - break; - } + dev->requested_blocks = max_len; + dev->packet_len = alloc_length; - if ((dev->sector_pos > last_sector)/* || - ((dev->sector_pos + dev->sector_len - 1) > last_sector)*/) { - scsi_disk_lba_out_of_range(dev); - return; - } + scsi_disk_set_buf_len(dev, BufLen, (int32_t *) &dev->packet_len); - if ((!dev->sector_len) || (*BufLen == 0)) { - scsi_disk_set_phase(dev, SCSI_PHASE_STATUS); - scsi_disk_log("SCSI HD %i: All done - callback set\n", dev->id); - dev->packet_status = PHASE_COMPLETE; - dev->callback = 20.0 * SCSI_TIME; - break; - } + scsi_disk_data_command_finish(dev, alloc_length, 512, alloc_length, 0); - max_len = dev->sector_len; - dev->requested_blocks = max_len; + ui_sb_update_icon(SB_HDD | dev->drv->bus, dev->packet_status != PHASE_COMPLETE); + return; - alloc_length = dev->packet_len = max_len << 9; - scsi_disk_buf_alloc(dev, dev->packet_len); + case GPCMD_VERIFY_6: + case GPCMD_VERIFY_10: + case GPCMD_VERIFY_12: + if (!(cdb[1] & 2)) { + scsi_disk_set_phase(dev, SCSI_PHASE_STATUS); + scsi_disk_command_complete(dev); + break; + } + fallthrough; + case GPCMD_WRITE_6: + case GPCMD_WRITE_10: + case GPCMD_WRITE_AND_VERIFY_10: + case GPCMD_WRITE_12: + case GPCMD_WRITE_AND_VERIFY_12: + scsi_disk_set_phase(dev, SCSI_PHASE_DATA_OUT); + alloc_length = 512; - scsi_disk_set_buf_len(dev, BufLen, &alloc_length); - scsi_disk_set_phase(dev, SCSI_PHASE_DATA_OUT); + switch (cdb[0]) { + case GPCMD_VERIFY_6: + case GPCMD_WRITE_6: + dev->sector_len = cdb[4]; + /* + For READ (6) and WRITE (6), a length of 0 indicates a + transfer of 256 sectors. + */ + if (dev->sector_len == 0) + dev->sector_len = 256; + dev->sector_pos = ((((uint32_t) cdb[1]) & 0x1f) << 16) | + (((uint32_t) cdb[2]) << 8) | ((uint32_t) cdb[3]); + scsi_disk_log("SCSI HD %i: Length: %i, LBA: %i\n", dev->id, + dev->sector_len, dev->sector_pos); + break; + case GPCMD_VERIFY_10: + case GPCMD_WRITE_10: + case GPCMD_WRITE_AND_VERIFY_10: + dev->sector_len = (cdb[7] << 8) | cdb[8]; + dev->sector_pos = (cdb[2] << 24) | (cdb[3] << 16) | (cdb[4] << 8) | cdb[5]; + scsi_disk_log("SCSI HD %i: Length: %i, LBA: %i\n", dev->id, + dev->sector_len, dev->sector_pos); + break; + case GPCMD_VERIFY_12: + case GPCMD_WRITE_12: + case GPCMD_WRITE_AND_VERIFY_12: + dev->sector_len = (((uint32_t) cdb[6]) << 24) | (((uint32_t) cdb[7]) << 16) | + (((uint32_t) cdb[8]) << 8) | ((uint32_t) cdb[9]); + dev->sector_pos = (((uint32_t) cdb[2]) << 24) | (((uint32_t) cdb[3]) << 16) | + (((uint32_t) cdb[4]) << 8) | ((uint32_t) cdb[5]); + break; - if (dev->requested_blocks > 1) - scsi_disk_data_command_finish(dev, alloc_length, alloc_length / dev->requested_blocks, alloc_length, 1); - else - scsi_disk_data_command_finish(dev, alloc_length, alloc_length, alloc_length, 1); + default: + break; + } - if (dev->packet_status != PHASE_COMPLETE) - ui_sb_update_icon(SB_HDD | dev->drv->bus, 1); - else - ui_sb_update_icon(SB_HDD | dev->drv->bus, 0); - return; + if (dev->sector_pos > last_sector) { + scsi_disk_lba_out_of_range(dev); + return; + } - case GPCMD_WRITE_SAME_10: - scsi_disk_set_phase(dev, SCSI_PHASE_DATA_OUT); - alloc_length = 512; + if (!dev->sector_len) { + scsi_disk_set_phase(dev, SCSI_PHASE_STATUS); + scsi_disk_log("SCSI HD %i: All done - callback set\n", dev->id); + dev->packet_status = PHASE_COMPLETE; + dev->callback = 20.0 * SCSI_TIME; + scsi_disk_set_callback(dev); + break; + } - if ((cdb[1] & 6) == 6) { - scsi_disk_invalid_field(dev); - return; - } + max_len = dev->sector_len; + /* + If we're writing all blocks in one go for DMA, why not also for + PIO, it should NOT matter anyway, this step should be identical + and only the way the read dat is transferred to the host should + be different. + */ + dev->requested_blocks = max_len; - dev->sector_len = (cdb[7] << 8) | cdb[8]; - dev->sector_pos = (cdb[2] << 24) | (cdb[3] << 16) | (cdb[4] << 8) | cdb[5]; + dev->packet_len = max_len * alloc_length; + scsi_disk_buf_alloc(dev, dev->packet_len); - if ((dev->sector_pos > last_sector)/* || - ((dev->sector_pos + dev->sector_len - 1) > last_sector)*/) { - scsi_disk_lba_out_of_range(dev); - return; - } + dev->requested_blocks = max_len; + dev->packet_len = max_len << 9; - if ((!dev->sector_len) || (*BufLen == 0)) { - scsi_disk_set_phase(dev, SCSI_PHASE_STATUS); - scsi_disk_log("SCSI HD %i: All done - callback set\n", dev->id); - dev->packet_status = PHASE_COMPLETE; - dev->callback = 20.0 * SCSI_TIME; - break; - } + scsi_disk_set_buf_len(dev, BufLen, (int32_t *) &dev->packet_len); - scsi_disk_buf_alloc(dev, alloc_length); - scsi_disk_set_buf_len(dev, BufLen, &alloc_length); + scsi_disk_data_command_finish(dev, dev->packet_len, 512, dev->packet_len, 1); - max_len = 1; - dev->requested_blocks = 1; + ui_sb_update_icon(SB_HDD | dev->drv->bus, dev->packet_status != PHASE_COMPLETE); + return; - scsi_disk_set_phase(dev, SCSI_PHASE_DATA_OUT); + case GPCMD_WRITE_SAME_10: + alloc_length = 512; - scsi_disk_data_command_finish(dev, 512, 512, alloc_length, 1); + if ((cdb[1] & 6) == 6) { + scsi_disk_invalid_field(dev); + return; + } - if (dev->packet_status != PHASE_COMPLETE) - ui_sb_update_icon(SB_HDD | dev->drv->bus, 1); - else - ui_sb_update_icon(SB_HDD | dev->drv->bus, 0); - return; + dev->sector_len = (cdb[7] << 8) | cdb[8]; + dev->sector_pos = (cdb[2] << 24) | (cdb[3] << 16) | (cdb[4] << 8) | cdb[5]; - case GPCMD_MODE_SENSE_6: - case GPCMD_MODE_SENSE_10: - scsi_disk_set_phase(dev, SCSI_PHASE_DATA_IN); + if (dev->sector_pos > last_sector) { + scsi_disk_lba_out_of_range(dev); + return; + } - block_desc = ((cdb[1] >> 3) & 1) ? 0 : 1; + if (!dev->sector_len) { + scsi_disk_set_phase(dev, SCSI_PHASE_STATUS); + scsi_disk_log("SCSI HD %i: All done - callback set\n", dev->id); + dev->packet_status = PHASE_COMPLETE; + dev->callback = 20.0 * SCSI_TIME; + scsi_disk_set_callback(dev); + break; + } - if (cdb[0] == GPCMD_MODE_SENSE_6) { - len = cdb[4]; - scsi_disk_buf_alloc(dev, 256); - } else { - len = (cdb[8] | (cdb[7] << 8)); - scsi_disk_buf_alloc(dev, 65536); - } + scsi_disk_buf_alloc(dev, alloc_length); + scsi_disk_set_buf_len(dev, BufLen, (int32_t *) &dev->packet_len); - memset(dev->temp_buffer, 0, len); - alloc_length = len; + max_len = 1; + dev->requested_blocks = 1; - if (cdb[0] == GPCMD_MODE_SENSE_6) { - len = scsi_disk_mode_sense(dev, dev->temp_buffer, 4, cdb[2], block_desc); - if (len > alloc_length) - len = alloc_length; - dev->temp_buffer[0] = len - 1; - dev->temp_buffer[1] = 0; - if (block_desc) - dev->temp_buffer[3] = 8; - } else { - len = scsi_disk_mode_sense(dev, dev->temp_buffer, 8, cdb[2], block_desc); - if (len > alloc_length) - len = alloc_length; - dev->temp_buffer[0] = (len - 2) >> 8; - dev->temp_buffer[1] = (len - 2) & 255; - dev->temp_buffer[2] = 0; - if (block_desc) { - dev->temp_buffer[6] = 0; - dev->temp_buffer[7] = 8; - } - } + dev->packet_len = alloc_length; - if (len > alloc_length) - len = alloc_length; - else if (len < alloc_length) - alloc_length = len; + scsi_disk_set_phase(dev, SCSI_PHASE_DATA_OUT); - scsi_disk_set_buf_len(dev, BufLen, &alloc_length); - scsi_disk_log("SCSI HDD %i: Reading mode page: %02X...\n", dev->id, cdb[2]); + scsi_disk_data_command_finish(dev, 512, 512, alloc_length, 1); - scsi_disk_data_command_finish(dev, len, len, alloc_length, 0); - return; + ui_sb_update_icon(SB_HDD | dev->drv->bus, dev->packet_status != PHASE_COMPLETE); + return; - case GPCMD_MODE_SELECT_6: - case GPCMD_MODE_SELECT_10: - scsi_disk_set_phase(dev, SCSI_PHASE_DATA_OUT); + case GPCMD_MODE_SENSE_6: + case GPCMD_MODE_SENSE_10: + scsi_disk_set_phase(dev, SCSI_PHASE_DATA_IN); - if (cdb[0] == GPCMD_MODE_SELECT_6) { - len = cdb[4]; - scsi_disk_buf_alloc(dev, 256); - } else { - len = (cdb[7] << 8) | cdb[8]; - scsi_disk_buf_alloc(dev, 65536); - } + if (dev->drv->bus == HDD_BUS_SCSI) + block_desc = ((cdb[1] >> 3) & 1) ? 0 : 1; + else + block_desc = 0; - scsi_disk_set_buf_len(dev, BufLen, &len); - dev->total_length = len; - dev->do_page_save = cdb[1] & 1; - scsi_disk_data_command_finish(dev, len, len, len, 1); - return; + if (cdb[0] == GPCMD_MODE_SENSE_6) { + len = cdb[4]; + scsi_disk_buf_alloc(dev, 256); + } else { + len = (cdb[8] | (cdb[7] << 8)); + scsi_disk_buf_alloc(dev, 65536); + } - case GPCMD_INQUIRY: - max_len = cdb[3]; - max_len <<= 8; - max_len |= cdb[4]; + memset(dev->temp_buffer, 0, len); + alloc_length = len; - if ((!max_len) || (*BufLen == 0)) { - scsi_disk_set_phase(dev, SCSI_PHASE_STATUS); - /* scsi_disk_log("SCSI HD %i: All done - callback set\n", dev->id); */ - dev->packet_status = PHASE_COMPLETE; - dev->callback = 20.0 * SCSI_TIME; - break; - } + if (cdb[0] == GPCMD_MODE_SENSE_6) { + len = scsi_disk_mode_sense(dev, dev->temp_buffer, 4, cdb[2], block_desc); + if (len > alloc_length) + len = alloc_length; + dev->temp_buffer[0] = len - 1; + dev->temp_buffer[1] = 0; + if (block_desc) + dev->temp_buffer[3] = 8; + } else { + len = scsi_disk_mode_sense(dev, dev->temp_buffer, 8, cdb[2], block_desc); + if (len > alloc_length) + len = alloc_length; + dev->temp_buffer[0] = (len - 2) >> 8; + dev->temp_buffer[1] = (len - 2) & 255; + dev->temp_buffer[2] = 0; + if (block_desc) { + dev->temp_buffer[6] = 0; + dev->temp_buffer[7] = 8; + } + } - scsi_disk_buf_alloc(dev, 65536); + if (len > alloc_length) + len = alloc_length; + else if (len < alloc_length) + alloc_length = len; - if (cdb[1] & 1) { - preamble_len = 4; - size_idx = 3; + scsi_disk_set_buf_len(dev, BufLen, &alloc_length); + scsi_disk_log("SCSI HDD %i: Reading mode page: %02X...\n", dev->id, cdb[2]); - dev->temp_buffer[idx++] = 05; - dev->temp_buffer[idx++] = cdb[2]; - dev->temp_buffer[idx++] = 0; + scsi_disk_data_command_finish(dev, len, len, alloc_length, 0); + return; - idx++; + case GPCMD_MODE_SELECT_6: + case GPCMD_MODE_SELECT_10: + scsi_disk_set_phase(dev, SCSI_PHASE_DATA_OUT); - switch (cdb[2]) { - case 0x00: - dev->temp_buffer[idx++] = 0x00; - dev->temp_buffer[idx++] = 0x83; - break; - case 0x83: - if (idx + 24 > max_len) { - scsi_disk_buf_free(dev); - scsi_disk_data_phase_error(dev); - return; - } + if (cdb[0] == GPCMD_MODE_SELECT_6) { + len = cdb[4]; + scsi_disk_buf_alloc(dev, 256); + } else { + len = (cdb[7] << 8) | cdb[8]; + scsi_disk_buf_alloc(dev, 65536); + } - dev->temp_buffer[idx++] = 0x02; - dev->temp_buffer[idx++] = 0x00; - dev->temp_buffer[idx++] = 0x00; - dev->temp_buffer[idx++] = 20; - ide_padstr8(dev->temp_buffer + idx, 20, "53R141"); /* Serial */ - idx += 20; + scsi_disk_set_buf_len(dev, BufLen, &len); + dev->total_length = len; + dev->do_page_save = cdb[1] & 1; + scsi_disk_data_command_finish(dev, len, len, len, 1); + return; - if (idx + 72 > cdb[4]) - goto atapi_out; - dev->temp_buffer[idx++] = 0x02; - dev->temp_buffer[idx++] = 0x01; - dev->temp_buffer[idx++] = 0x00; - dev->temp_buffer[idx++] = 68; - ide_padstr8(dev->temp_buffer + idx, 8, EMU_NAME); /* Vendor */ - idx += 8; - ide_padstr8(dev->temp_buffer + idx, 40, device_identify_ex); /* Product */ - idx += 40; - ide_padstr8(dev->temp_buffer + idx, 20, "53R141"); /* Product */ - idx += 20; - break; - default: - scsi_disk_log("INQUIRY: Invalid page: %02X\n", cdb[2]); - scsi_disk_invalid_field(dev); - scsi_disk_buf_free(dev); - return; - } - } else { - preamble_len = 5; - size_idx = 4; + case GPCMD_INQUIRY: + max_len = cdb[3]; + max_len <<= 8; + max_len |= cdb[4]; - memset(dev->temp_buffer, 0, 8); - dev->temp_buffer[0] = 0; /*SCSI HD*/ - dev->temp_buffer[1] = 0; /*Fixed*/ - dev->temp_buffer[2] = 0x02; /*SCSI-2 compliant*/ - dev->temp_buffer[3] = 0x02; - dev->temp_buffer[4] = 31; - dev->temp_buffer[6] = 1; /* 16-bit transfers supported */ - dev->temp_buffer[7] = 0x20; /* Wide bus supported */ + if ((!max_len) || (*BufLen == 0)) { + scsi_disk_set_phase(dev, SCSI_PHASE_STATUS); + /* scsi_disk_log("SCSI HD %i: All done - callback set\n", dev->id); */ + dev->packet_status = PHASE_COMPLETE; + dev->callback = 20.0 * SCSI_TIME; + break; + } - ide_padstr8(dev->temp_buffer + 8, 8, EMU_NAME); /* Vendor */ - ide_padstr8(dev->temp_buffer + 16, 16, device_identify); /* Product */ - ide_padstr8(dev->temp_buffer + 32, 4, EMU_VERSION_EX); /* Revision */ - idx = 36; + scsi_disk_buf_alloc(dev, 65536); - if (max_len == 96) { - dev->temp_buffer[4] = 91; - idx = 96; - } - } + if (cdb[1] & 1) { + preamble_len = 4; + size_idx = 3; + + dev->temp_buffer[idx++] = 05; + dev->temp_buffer[idx++] = cdb[2]; + dev->temp_buffer[idx++] = 0; + + idx++; + + switch (cdb[2]) { + case 0x00: + dev->temp_buffer[idx++] = 0x00; + dev->temp_buffer[idx++] = 0x83; + break; + case 0x83: + if (idx + 24 > max_len) { + scsi_disk_buf_free(dev); + scsi_disk_data_phase_error(dev); + return; + } + + dev->temp_buffer[idx++] = 0x02; + dev->temp_buffer[idx++] = 0x00; + dev->temp_buffer[idx++] = 0x00; + dev->temp_buffer[idx++] = 20; + ide_padstr8(dev->temp_buffer + idx, 20, "53R141"); /* Serial */ + idx += 20; + + if (idx + 72 > cdb[4]) + goto atapi_out; + dev->temp_buffer[idx++] = 0x02; + dev->temp_buffer[idx++] = 0x01; + dev->temp_buffer[idx++] = 0x00; + dev->temp_buffer[idx++] = 68; + ide_padstr8(dev->temp_buffer + idx, 8, EMU_NAME); /* Vendor */ + idx += 8; + ide_padstr8(dev->temp_buffer + idx, 40, device_identify_ex); /* Product */ + idx += 40; + ide_padstr8(dev->temp_buffer + idx, 20, "53R141"); /* Product */ + idx += 20; + break; + default: + scsi_disk_log("INQUIRY: Invalid page: %02X\n", cdb[2]); + scsi_disk_invalid_field(dev); + scsi_disk_buf_free(dev); + return; + } + } else { + preamble_len = 5; + size_idx = 4; + + memset(dev->temp_buffer, 0, 8); + dev->temp_buffer[0] = 0; /*SCSI HD*/ + dev->temp_buffer[1] = 0; /*Fixed*/ + dev->temp_buffer[2] = (dev->drv->bus == HDD_BUS_SCSI) ? 0x02 : 0x00; /*SCSI-2 compliant*/ + dev->temp_buffer[3] = (dev->drv->bus == HDD_BUS_SCSI) ? 0x02 : 0x21; + dev->temp_buffer[4] = 31; + dev->temp_buffer[6] = 1; /* 16-bit transfers supported */ + dev->temp_buffer[7] = 0x20; /* Wide bus supported */ + + ide_padstr8(dev->temp_buffer + 8, 8, EMU_NAME); /* Vendor */ + ide_padstr8(dev->temp_buffer + 16, 16, device_identify); /* Product */ + ide_padstr8(dev->temp_buffer + 32, 4, EMU_VERSION_EX); /* Revision */ + idx = 36; + + if (max_len == 96) { + dev->temp_buffer[4] = 91; + idx = 96; + } + } atapi_out: - dev->temp_buffer[size_idx] = idx - preamble_len; - len=idx; + dev->temp_buffer[size_idx] = idx - preamble_len; + len = idx; - if (len > max_len) - len = max_len; + if (len > max_len) + len = max_len; - scsi_disk_set_buf_len(dev, BufLen, &len); + scsi_disk_set_buf_len(dev, BufLen, &len); - if (len > *BufLen) - len = *BufLen; + if (len > *BufLen) + len = *BufLen; - scsi_disk_set_phase(dev, SCSI_PHASE_DATA_IN); - scsi_disk_data_command_finish(dev, len, len, max_len, 0); - break; + scsi_disk_set_phase(dev, SCSI_PHASE_DATA_IN); + scsi_disk_data_command_finish(dev, len, len, max_len, 0); + break; - case GPCMD_PREVENT_REMOVAL: - scsi_disk_set_phase(dev, SCSI_PHASE_STATUS); - scsi_disk_command_complete(dev); - break; + case GPCMD_PREVENT_REMOVAL: + scsi_disk_set_phase(dev, SCSI_PHASE_STATUS); + scsi_disk_command_complete(dev); + break; - case GPCMD_SEEK_6: - case GPCMD_SEEK_10: - switch(cdb[0]) { - case GPCMD_SEEK_6: - pos = (cdb[2] << 8) | cdb[3]; - break; - case GPCMD_SEEK_10: - pos = (cdb[2] << 24) | (cdb[3]<<16) | (cdb[4]<<8) | cdb[5]; - break; - } - scsi_disk_seek(dev, pos); + case GPCMD_SEEK_6: + case GPCMD_SEEK_10: + switch (cdb[0]) { + case GPCMD_SEEK_6: + pos = (cdb[2] << 8) | cdb[3]; + break; + case GPCMD_SEEK_10: + pos = (cdb[2] << 24) | (cdb[3] << 16) | (cdb[4] << 8) | cdb[5]; + break; - scsi_disk_set_phase(dev, SCSI_PHASE_STATUS); - scsi_disk_command_complete(dev); - break; + default: + break; + } + scsi_disk_seek(dev, pos); - case GPCMD_READ_CDROM_CAPACITY: - scsi_disk_buf_alloc(dev, 8); + scsi_disk_set_phase(dev, SCSI_PHASE_STATUS); + scsi_disk_command_complete(dev); + break; - max_len = hdd_image_get_last_sector(dev->id); - memset(dev->temp_buffer, 0, 8); - dev->temp_buffer[0] = (max_len >> 24) & 0xff; - dev->temp_buffer[1] = (max_len >> 16) & 0xff; - dev->temp_buffer[2] = (max_len >> 8) & 0xff; - dev->temp_buffer[3] = max_len & 0xff; - dev->temp_buffer[6] = 2; - len = 8; + case GPCMD_READ_CDROM_CAPACITY: + scsi_disk_buf_alloc(dev, 8); - scsi_disk_set_buf_len(dev, BufLen, &len); + max_len = hdd_image_get_last_sector(dev->id); + memset(dev->temp_buffer, 0, 8); + dev->temp_buffer[0] = (max_len >> 24) & 0xff; + dev->temp_buffer[1] = (max_len >> 16) & 0xff; + dev->temp_buffer[2] = (max_len >> 8) & 0xff; + dev->temp_buffer[3] = max_len & 0xff; + dev->temp_buffer[6] = 2; + len = 8; - scsi_disk_set_phase(dev, SCSI_PHASE_DATA_IN); - scsi_disk_data_command_finish(dev, len, len, len, 0); - break; + scsi_disk_set_buf_len(dev, BufLen, &len); - default: - scsi_disk_illegal_opcode(dev); - break; + scsi_disk_set_phase(dev, SCSI_PHASE_DATA_IN); + scsi_disk_data_command_finish(dev, len, len, len, 0); + break; + + default: + scsi_disk_illegal_opcode(dev); + break; } - /* scsi_disk_log("SCSI HD %i: Phase: %02X, request length: %i\n", dev->id, dev->phase, dev->request_length); */ -} + /* scsi_disk_log("SCSI HD %i: Phase: %02X, request length: %i\n", dev->id, dev->tf->phase, + dev->tf->request_length); */ + if ((dev->packet_status == PHASE_COMPLETE) || (dev->packet_status == PHASE_ERROR)) + scsi_disk_buf_free(dev); +} static void scsi_disk_command_stop(scsi_common_t *sc) @@ -1071,233 +1416,379 @@ scsi_disk_command_stop(scsi_common_t *sc) scsi_disk_buf_free(dev); } - static uint8_t scsi_disk_phase_data_out(scsi_common_t *sc) { - scsi_disk_t *dev = (scsi_disk_t *) sc; - uint8_t scsi_bus = (dev->drv->scsi_id >> 4) & 0x0f; - uint8_t scsi_id = dev->drv->scsi_id & 0x0f; - int i; - int32_t *BufLen = &scsi_devices[scsi_bus][scsi_id].buffer_length; - uint32_t last_sector = hdd_image_get_last_sector(dev->id); - uint32_t c, h, s, last_to_write = 0; - uint16_t block_desc_len, pos; - uint16_t param_list_len; - uint8_t hdr_len, val, old_val, ch, error = 0; - uint8_t page, page_len; + scsi_disk_t *dev = (scsi_disk_t *) sc; + uint8_t scsi_bus = (dev->drv->scsi_id >> 4) & 0x0f; + uint8_t scsi_id = dev->drv->scsi_id & 0x0f; + int i; + const int32_t *BufLen = &scsi_devices[scsi_bus][scsi_id].buffer_length; + uint32_t last_sector = hdd_image_get_last_sector(dev->id); + uint32_t c; + uint32_t h; + uint32_t s; + int len = 0; + uint32_t last_to_write = 0; + uint16_t block_desc_len; + uint16_t pos; + uint16_t param_list_len; + uint8_t hdr_len; + uint8_t val; + uint8_t old_val; + uint8_t ch; + uint8_t error = 0; + uint8_t page; + uint8_t page_len; if (!*BufLen) { - scsi_disk_set_phase(dev, SCSI_PHASE_STATUS); + scsi_disk_set_phase(dev, SCSI_PHASE_STATUS); - return 1; + return 1; } switch (dev->current_cdb[0]) { - case GPCMD_VERIFY_6: - case GPCMD_VERIFY_10: - case GPCMD_VERIFY_12: - break; - case GPCMD_WRITE_6: - case GPCMD_WRITE_10: - case GPCMD_WRITE_AND_VERIFY_10: - case GPCMD_WRITE_12: - case GPCMD_WRITE_AND_VERIFY_12: - if ((dev->requested_blocks > 0) && (*BufLen > 0)) { - if (dev->packet_len > (uint32_t) *BufLen) - hdd_image_write(dev->id, dev->sector_pos, *BufLen >> 9, dev->temp_buffer); - else - hdd_image_write(dev->id, dev->sector_pos, dev->requested_blocks, dev->temp_buffer); - } - break; - case GPCMD_WRITE_SAME_10: - if (!dev->current_cdb[7] && !dev->current_cdb[8]) - last_to_write = last_sector; - else - last_to_write = dev->sector_pos + dev->sector_len - 1; + case GPCMD_VERIFY_6: + case GPCMD_VERIFY_10: + case GPCMD_VERIFY_12: + break; + case GPCMD_WRITE_6: + case GPCMD_WRITE_10: + case GPCMD_WRITE_AND_VERIFY_10: + case GPCMD_WRITE_12: + case GPCMD_WRITE_AND_VERIFY_12: + if (dev->requested_blocks > 0) + scsi_disk_blocks(dev, &len, 1, 1); + break; + case GPCMD_WRITE_SAME_10: + if (!dev->current_cdb[7] && !dev->current_cdb[8]) + last_to_write = last_sector; + else + last_to_write = dev->sector_pos + dev->sector_len - 1; - for (i = dev->sector_pos; i <= (int) last_to_write; i++) { - if (dev->current_cdb[1] & 2) { - dev->temp_buffer[0] = (i >> 24) & 0xff; - dev->temp_buffer[1] = (i >> 16) & 0xff; - dev->temp_buffer[2] = (i >> 8) & 0xff; - dev->temp_buffer[3] = i & 0xff; - } else if (dev->current_cdb[1] & 4) { - s = (i % dev->drv->spt); - h = ((i - s) / dev->drv->spt) % dev->drv->hpc; - c = ((i - s) / dev->drv->spt) / dev->drv->hpc; - dev->temp_buffer[0] = (c >> 16) & 0xff; - dev->temp_buffer[1] = (c >> 8) & 0xff; - dev->temp_buffer[2] = c & 0xff; - dev->temp_buffer[3] = h & 0xff; - dev->temp_buffer[4] = (s >> 24) & 0xff; - dev->temp_buffer[5] = (s >> 16) & 0xff; - dev->temp_buffer[6] = (s >> 8) & 0xff; - dev->temp_buffer[7] = s & 0xff; - } - hdd_image_write(dev->id, i, 1, dev->temp_buffer); - } - break; - case GPCMD_MODE_SELECT_6: - case GPCMD_MODE_SELECT_10: - if (dev->current_cdb[0] == GPCMD_MODE_SELECT_10) { - hdr_len = 8; - param_list_len = dev->current_cdb[7]; - param_list_len <<= 8; - param_list_len |= dev->current_cdb[8]; - } else { - hdr_len = 4; - param_list_len = dev->current_cdb[4]; - } + for (i = dev->sector_pos; i <= (int) last_to_write; i++) { + if (dev->current_cdb[1] & 2) { + dev->temp_buffer[0] = (i >> 24) & 0xff; + dev->temp_buffer[1] = (i >> 16) & 0xff; + dev->temp_buffer[2] = (i >> 8) & 0xff; + dev->temp_buffer[3] = i & 0xff; + } else if (dev->current_cdb[1] & 4) { + s = (i % dev->drv->spt); + h = ((i - s) / dev->drv->spt) % dev->drv->hpc; + c = ((i - s) / dev->drv->spt) / dev->drv->hpc; + dev->temp_buffer[0] = (c >> 16) & 0xff; + dev->temp_buffer[1] = (c >> 8) & 0xff; + dev->temp_buffer[2] = c & 0xff; + dev->temp_buffer[3] = h & 0xff; + dev->temp_buffer[4] = (s >> 24) & 0xff; + dev->temp_buffer[5] = (s >> 16) & 0xff; + dev->temp_buffer[6] = (s >> 8) & 0xff; + dev->temp_buffer[7] = s & 0xff; + } + hdd_image_write(dev->id, i, 1, dev->temp_buffer); + } + break; + case GPCMD_MODE_SELECT_6: + case GPCMD_MODE_SELECT_10: + if (dev->current_cdb[0] == GPCMD_MODE_SELECT_10) { + hdr_len = 8; + param_list_len = dev->current_cdb[7]; + param_list_len <<= 8; + param_list_len |= dev->current_cdb[8]; + } else { + hdr_len = 4; + param_list_len = dev->current_cdb[4]; + } - if (dev->current_cdb[0] == GPCMD_MODE_SELECT_6) { - block_desc_len = dev->temp_buffer[2]; - block_desc_len <<= 8; - block_desc_len |= dev->temp_buffer[3]; - } else { - block_desc_len = dev->temp_buffer[6]; - block_desc_len <<= 8; - block_desc_len |= dev->temp_buffer[7]; - } + if (dev->drv->bus == HDD_BUS_SCSI) { + if (dev->current_cdb[0] == GPCMD_MODE_SELECT_6) { + block_desc_len = dev->temp_buffer[2]; + block_desc_len <<= 8; + block_desc_len |= dev->temp_buffer[3]; + } else { + block_desc_len = dev->temp_buffer[6]; + block_desc_len <<= 8; + block_desc_len |= dev->temp_buffer[7]; + } + } else + block_desc_len = 0; - pos = hdr_len + block_desc_len; + pos = hdr_len + block_desc_len; - while(1) { - if (pos >= param_list_len) { - scsi_disk_log("SCSI HD %i: Buffer has only block descriptor\n", dev->id); - break; - } + while (1) { + if (pos >= param_list_len) { + scsi_disk_log("SCSI HD %i: Buffer has only block descriptor\n", dev->id); + break; + } - page = dev->temp_buffer[pos] & 0x3F; - page_len = dev->temp_buffer[pos + 1]; + page = dev->temp_buffer[pos] & 0x3F; + page_len = dev->temp_buffer[pos + 1]; - pos += 2; + pos += 2; - if (!(scsi_disk_mode_sense_page_flags & (1LL << ((uint64_t) page)))) - error |= 1; - else { - for (i = 0; i < page_len; i++) { - ch = scsi_disk_mode_sense_pages_changeable.pages[page][i + 2]; - val = dev->temp_buffer[pos + i]; - old_val = dev->ms_pages_saved.pages[page][i + 2]; - if (val != old_val) { - if (ch) - dev->ms_pages_saved.pages[page][i + 2] = val; - else - error |= 1; - } - } - } + if (!(scsi_disk_mode_sense_page_flags & (1LL << ((uint64_t) page)))) + error |= 1; + else { + for (i = 0; i < page_len; i++) { + ch = scsi_disk_mode_sense_pages_changeable.pages[page][i + 2]; + val = dev->temp_buffer[pos + i]; + old_val = dev->ms_pages_saved.pages[page][i + 2]; + if (val != old_val) { + if (ch) + dev->ms_pages_saved.pages[page][i + 2] = val; + else + error |= 1; + } + } + } - pos += page_len; + pos += page_len; - val = scsi_disk_mode_sense_pages_default.pages[page][0] & 0x80; - if (dev->do_page_save && val) - scsi_disk_mode_sense_save(dev); + val = scsi_disk_mode_sense_pages_default.pages[page][0] & 0x80; + if (dev->do_page_save && val) + scsi_disk_mode_sense_save(dev); - if (pos >= dev->total_length) - break; - } + if (pos >= dev->total_length) + break; + } - if (error) { - scsi_disk_buf_free(dev); - scsi_disk_invalid_field_pl(dev); - } - break; - default: - fatal("SCSI HDD %i: Bad Command for phase 2 (%02X)\n", dev->id, dev->current_cdb[0]); - break; + if (error) { + scsi_disk_buf_free(dev); + scsi_disk_invalid_field_pl(dev); + } + break; + default: + fatal("SCSI HDD %i: Bad Command for phase 2 (%02X)\n", dev->id, dev->current_cdb[0]); + break; } scsi_disk_command_stop((scsi_common_t *) dev); return 1; } +static int +scsi_disk_get_max(int ide_has_dma, int type) +{ + int ret; + + switch (type) { + case TYPE_PIO: + ret = ide_has_dma ? 4 : 0; + break; + case TYPE_SDMA: + ret = ide_has_dma ? 2 : -1; + break; + case TYPE_MDMA: + ret = ide_has_dma ? 2 : -1; + break; + case TYPE_UDMA: + ret = ide_has_dma ? 5 : -1; + break; + default: + ret = -1; + break; + } + + return ret; +} + +static int +scsi_disk_get_timings(int ide_has_dma, int type) +{ + int ret; + + switch (type) { + case TIMINGS_DMA: + ret = ide_has_dma ? 120 : 0; + break; + case TIMINGS_PIO: + ret = ide_has_dma ? 120 : 0; + break; + case TIMINGS_PIO_FC: + ret = 0; + break; + default: + ret = 0; + break; + } + + return ret; +} + +/** + * Fill in ide->buffer with the output of the "IDENTIFY PACKET DEVICE" command + */ +static void +scsi_disk_identify(ide_t *ide, int ide_has_dma) +{ + const scsi_disk_t *dev; + char device_identify[9] = { '8', '6', 'B', '_', 'H', 'D', '0', '0', 0 }; + + dev = (scsi_disk_t *) ide->sc; + + device_identify[7] = dev->id + 0x30; + scsi_disk_log("ATAPI Identify: %s\n", device_identify); + + /* ATAPI device, direct-access device, non-removable media, accelerated DRQ */ + ide->buffer[0] = 0x8000 | (0 << 8) | 0x00 | (2 << 5); + ide_padstr((char *) (ide->buffer + 10), "", 20); /* Serial Number */ + + ide_padstr((char *) (ide->buffer + 23), EMU_VERSION_EX, 8); /* Firmware */ + ide_padstr((char *) (ide->buffer + 27), device_identify, 40); /* Model */ + + ide->buffer[49] = 0x200; /* LBA supported */ + ide->buffer[126] = 0xfffe; /* Interpret zero byte count limit as maximum length */ + + if (ide_has_dma) { + ide->buffer[71] = 30; + ide->buffer[72] = 30; + ide->buffer[80] = 0x7e; /*ATA-1 to ATA-6 supported*/ + ide->buffer[81] = 0x19; /*ATA-6 revision 3a supported*/ + } +} void scsi_disk_hard_reset(void) { - int c; - scsi_disk_t *dev; + scsi_disk_t *dev; scsi_device_t *sd; - uint8_t scsi_bus, scsi_id; + ide_t *id; + uint8_t scsi_bus; + uint8_t scsi_id; + uint8_t valid = 0; - for (c = 0; c < HDD_NUM; c++) { - if (hdd[c].bus == HDD_BUS_SCSI) { - scsi_disk_log("SCSI disk hard_reset drive=%d\n", c); + for (uint8_t c = 0; c < HDD_NUM; c++) { + valid = 0; + if (hdd[c].bus == HDD_BUS_SCSI) { + scsi_disk_log("SCSI disk hard_reset drive=%d\n", c); - scsi_bus = (hdd[c].scsi_id >> 4) & 0x0f; - scsi_id = hdd[c].scsi_id & 0x0f; + scsi_bus = (hdd[c].scsi_id >> 4) & 0x0f; + scsi_id = hdd[c].scsi_id & 0x0f; - /* Make sure to ignore any SCSI disk that has an out of range SCSI bus. */ - if (scsi_bus >= SCSI_BUS_MAX) - continue; + /* Make sure to ignore any SCSI disk that has an out of range SCSI bus. */ + if (scsi_bus >= SCSI_BUS_MAX) + continue; - /* Make sure to ignore any SCSI disk that has an out of range ID. */ - if (scsi_id >= SCSI_ID_MAX) - continue; + /* Make sure to ignore any SCSI disk that has an out of range ID. */ + if (scsi_id >= SCSI_ID_MAX) + continue; - /* Make sure to ignore any SCSI disk whose image file name is empty. */ - if (strlen(hdd[c].fn) == 0) - continue; + /* Make sure to ignore any SCSI disk whose image file name is empty. */ + if (strlen(hdd[c].fn) == 0) + continue; - /* Make sure to ignore any SCSI disk whose image fails to load. */ - if (! hdd_image_load(c)) - continue; + /* Make sure to ignore any SCSI disk whose image fails to load. */ + if (!hdd_image_load(c)) + continue; - if (!hdd[c].priv) { - hdd[c].priv = (scsi_disk_t *) malloc(sizeof(scsi_disk_t)); - memset(hdd[c].priv, 0, sizeof(scsi_disk_t)); - } + valid = 1; - dev = (scsi_disk_t *) hdd[c].priv; + hdd_preset_apply(c); - /* SCSI disk, attach to the SCSI bus. */ - sd = &scsi_devices[scsi_bus][scsi_id]; + if (!hdd[c].priv) + hdd[c].priv = (scsi_disk_t *) calloc(1, sizeof(scsi_disk_t)); - sd->sc = (scsi_common_t *) dev; - sd->command = scsi_disk_command; - sd->request_sense = scsi_disk_request_sense_for_scsi; - sd->reset = scsi_disk_reset; - sd->phase_data_out = scsi_disk_phase_data_out; - sd->command_stop = scsi_disk_command_stop; - sd->type = SCSI_FIXED_DISK; + dev = (scsi_disk_t *) hdd[c].priv; - dev->id = c; - dev->drv = &hdd[c]; + if (!dev->tf) + dev->tf = (ide_tf_t *) calloc(1, sizeof(ide_tf_t)); - dev->cur_lun = SCSI_LUN_USE_CDB; + /* SCSI disk, attach to the SCSI bus. */ + sd = &scsi_devices[scsi_bus][scsi_id]; - scsi_disk_mode_sense_load(dev); + sd->sc = (scsi_common_t *) dev; + sd->command = scsi_disk_command; + sd->request_sense = scsi_disk_request_sense_for_scsi; + sd->reset = scsi_disk_reset; + sd->phase_data_out = scsi_disk_phase_data_out; + sd->command_stop = scsi_disk_command_stop; + sd->type = SCSI_FIXED_DISK; - scsi_disk_log("SCSI disk %i attached to SCSI ID %i\n", c, hdd[c].scsi_id); - } + scsi_disk_log("SCSI disk %i attached to SCSI ID %i\n", c, hdd[c].scsi_id); + } else if (hdd[c].bus == HDD_BUS_ATAPI) { + /* Make sure to ignore any SCSI disk whose image file name is empty. */ + if (strlen(hdd[c].fn) == 0) + continue; + + /* Make sure to ignore any SCSI disk whose image fails to load. */ + /* ATAPI hard disk, attach to the IDE bus. */ + id = ide_get_drive(hdd[c].ide_channel); + /* If the IDE channel is initialized, we attach to it, + otherwise, we do nothing - it's going to be a drive + that's not attached to anything. */ + if (id) { + if (!hdd_image_load(c)) + continue; + + valid = 1; + + hdd_preset_apply(c); + + if (!hdd[c].priv) + hdd[c].priv = (scsi_disk_t *) calloc(1, sizeof(scsi_disk_t)); + + dev = (scsi_disk_t *) hdd[c].priv; + + id->sc = (scsi_common_t *) dev; + dev->tf = id->tf; + IDE_ATAPI_IS_EARLY = 0; + id->get_max = scsi_disk_get_max; + id->get_timings = scsi_disk_get_timings; + id->identify = scsi_disk_identify; + id->stop = NULL; + id->packet_command = scsi_disk_command; + id->device_reset = scsi_disk_reset; + id->phase_data_out = scsi_disk_phase_data_out; + id->command_stop = scsi_disk_command_stop; + id->bus_master_error = scsi_disk_bus_master_error; + id->interrupt_drq = 0; + + ide_atapi_attach(id); + } + + scsi_disk_log("ATAPI hard disk drive %i attached to IDE channel %i\n", c, hdd[c].ide_channel); + } + + if (valid) { + dev->id = c; + dev->drv = &hdd[c]; + + dev->cur_lun = SCSI_LUN_USE_CDB; + + scsi_disk_init(dev); + + scsi_disk_mode_sense_load(dev); + } } } - void scsi_disk_close(void) { scsi_disk_t *dev; - int c; - uint8_t scsi_bus, scsi_id; + uint8_t scsi_bus; + uint8_t scsi_id; - for (c = 0; c < HDD_NUM; c++) { - if (hdd[c].bus == HDD_BUS_SCSI) { - scsi_bus = (hdd[c].scsi_id >> 4) & 0x0f; - scsi_id = hdd[c].scsi_id & 0x0f; + for (uint8_t c = 0; c < HDD_NUM; c++) { + if ((hdd[c].bus == HDD_BUS_SCSI) || (hdd[c].bus == HDD_BUS_ATAPI)) { + if (hdd[c].bus == HDD_BUS_SCSI) { + scsi_bus = (hdd[c].scsi_id >> 4) & 0x0f; + scsi_id = hdd[c].scsi_id & 0x0f; - memset(&scsi_devices[scsi_bus][scsi_id], 0x00, sizeof(scsi_device_t)); + memset(&scsi_devices[scsi_bus][scsi_id], 0x00, sizeof(scsi_device_t)); + } - hdd_image_close(c); + hdd_image_close(c); - dev = hdd[c].priv; + dev = hdd[c].priv; - if (dev) { - free(dev); - hdd[c].priv = NULL; - } - } + if (dev) { + if (dev->tf) + free(dev->tf); + + free(dev); + hdd[c].priv = NULL; + } + } } } diff --git a/src/scsi/scsi_ncr5380.c b/src/scsi/scsi_ncr5380.c index abedb885c..285c65c80 100644 --- a/src/scsi/scsi_ncr5380.c +++ b/src/scsi/scsi_ncr5380.c @@ -1,23 +1,23 @@ /* - * 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. + * 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. + * This file is part of the 86Box distribution. * - * Implementation of the NCR 5380 series of SCSI Host Adapters - * made by NCR. These controllers were designed for the ISA bus. + * Implementation of the NCR 5380 series of SCSI Host Adapters + * made by NCR. These controllers were designed for the ISA bus. * * * - * Authors: Sarah Walker, - * TheCollector1995, - * Fred N. van Kempen, + * Authors: Sarah Walker, + * TheCollector1995, + * Fred N. van Kempen, * - * Copyright 2017-2019 Sarah Walker. - * Copyright 2017-2019 TheCollector1995. - * Copyright 2017-2019 Fred N. van Kempen. + * Copyright 2017-2019 Sarah Walker. + * Copyright 2017-2019 TheCollector1995. + * Copyright 2017-2019 Fred N. van Kempen. */ #include #include @@ -42,158 +42,169 @@ #include <86box/scsi_device.h> #include <86box/scsi_ncr5380.h> +#define LCS6821N_ROM "roms/scsi/ncr5380/Longshine LCS-6821N - BIOS version 1.04.bin" +#define RT1000B_810R_ROM "roms/scsi/ncr5380/Rancho_RT1000_RTBios_version_8.10R.bin" +#define RT1000B_820R_ROM "roms/scsi/ncr5380/RTBIOS82.ROM" +#define T130B_ROM "roms/scsi/ncr5380/trantor_t130b_bios_v2.14.bin" +#define T128_ROM "roms/scsi/ncr5380/trantor_t128_bios_v1.12.bin" +#define COREL_LS2000_ROM "roms/scsi/ncr5380/Corel LS2000 - BIOS ROM - Ver 1.65.bin" -#define LCS6821N_ROM "roms/scsi/ncr5380/Longshine LCS-6821N - BIOS version 1.04.bin" -#define RT1000B_810R_ROM "roms/scsi/ncr5380/Rancho_RT1000_RTBios_version_8.10R.bin" -#define RT1000B_820R_ROM "roms/scsi/ncr5380/RTBIOS82.ROM" -#define T130B_ROM "roms/scsi/ncr5380/trantor_t130b_bios_v2.14.bin" -#define T128_ROM "roms/scsi/ncr5380/trantor_t128_bios_v1.12.bin" +#define NCR_CURDATA 0 /* current SCSI data (read only) */ +#define NCR_OUTDATA 0 /* output data (write only) */ +#define NCR_INITCOMMAND 1 /* initiator command (read/write) */ +#define NCR_MODE 2 /* mode (read/write) */ +#define NCR_TARGETCMD 3 /* target command (read/write) */ +#define NCR_SELENABLE 4 /* select enable (write only) */ +#define NCR_BUSSTATUS 4 /* bus status (read only) */ +#define NCR_STARTDMA 5 /* start DMA send (write only) */ +#define NCR_BUSANDSTAT 5 /* bus and status (read only) */ +#define NCR_DMATARGET 6 /* DMA target (write only) */ +#define NCR_INPUTDATA 6 /* input data (read only) */ +#define NCR_DMAINIRECV 7 /* DMA initiator receive (write only) */ +#define NCR_RESETPARITY 7 /* reset parity/interrupt (read only) */ +#define ICR_DBP 0x01 +#define ICR_ATN 0x02 +#define ICR_SEL 0x04 +#define ICR_BSY 0x08 +#define ICR_ACK 0x10 +#define ICR_ARB_LOST 0x20 +#define ICR_ARB_IN_PROGRESS 0x40 -#define NCR_CURDATA 0 /* current SCSI data (read only) */ -#define NCR_OUTDATA 0 /* output data (write only) */ -#define NCR_INITCOMMAND 1 /* initiator command (read/write) */ -#define NCR_MODE 2 /* mode (read/write) */ -#define NCR_TARGETCMD 3 /* target command (read/write) */ -#define NCR_SELENABLE 4 /* select enable (write only) */ -#define NCR_BUSSTATUS 4 /* bus status (read only) */ -#define NCR_STARTDMA 5 /* start DMA send (write only) */ -#define NCR_BUSANDSTAT 5 /* bus and status (read only) */ -#define NCR_DMATARGET 6 /* DMA target (write only) */ -#define NCR_INPUTDATA 6 /* input data (read only) */ -#define NCR_DMAINIRECV 7 /* DMA initiator receive (write only) */ -#define NCR_RESETPARITY 7 /* reset parity/interrupt (read only) */ +#define MODE_ARBITRATE 0x01 +#define MODE_DMA 0x02 +#define MODE_MONITOR_BUSY 0x04 +#define MODE_ENA_EOP_INT 0x08 -#define ICR_DBP 0x01 -#define ICR_ATN 0x02 -#define ICR_SEL 0x04 -#define ICR_BSY 0x08 -#define ICR_ACK 0x10 -#define ICR_ARB_LOST 0x20 -#define ICR_ARB_IN_PROGRESS 0x40 +#define STATUS_ACK 0x01 +#define STATUS_BUSY_ERROR 0x04 +#define STATUS_PHASE_MATCH 0x08 +#define STATUS_INT 0x10 +#define STATUS_DRQ 0x40 +#define STATUS_END_OF_DMA 0x80 -#define MODE_ARBITRATE 0x01 -#define MODE_DMA 0x02 -#define MODE_MONITOR_BUSY 0x04 -#define MODE_ENA_EOP_INT 0x08 +#define TCR_IO 0x01 +#define TCR_CD 0x02 +#define TCR_MSG 0x04 +#define TCR_REQ 0x08 +#define TCR_LAST_BYTE_SENT 0x80 -#define STATUS_ACK 0x01 -#define STATUS_BUSY_ERROR 0x04 -#define STATUS_PHASE_MATCH 0x08 -#define STATUS_INT 0x10 -#define STATUS_DRQ 0x40 -#define STATUS_END_OF_DMA 0x80 - -#define TCR_IO 0x01 -#define TCR_CD 0x02 -#define TCR_MSG 0x04 -#define TCR_REQ 0x08 -#define TCR_LAST_BYTE_SENT 0x80 - -#define CTRL_DATA_DIR 0x40 -#define STATUS_BUFFER_NOT_READY 0x04 +#define CTRL_DATA_DIR 0x40 +#define STATUS_BUFFER_NOT_READY 0x04 #define STATUS_53C80_ACCESSIBLE 0x80 -typedef struct { - uint8_t icr, mode, tcr, data_wait; - uint8_t isr, output_data, target_id, tx_data; - uint8_t msglun; +typedef struct ncr_t { + uint8_t icr; + uint8_t mode; + uint8_t tcr; + uint8_t data_wait; + uint8_t isr; + uint8_t output_data; + uint8_t target_id; + uint8_t tx_data; + uint8_t msglun; - uint8_t command[20]; - uint8_t msgout[4]; - int msgout_pos; - int is_msgout; + uint8_t command[20]; + uint8_t msgout[4]; + int msgout_pos; + int is_msgout; - int dma_mode, cur_bus, bus_in, new_phase; - int state, clear_req, wait_data, wait_complete; - int command_pos, data_pos; + int dma_mode; + int cur_bus; + int bus_in; + int new_phase; + int state; + int clear_req; + int wait_data; + int wait_complete; + int command_pos; + int data_pos; } ncr_t; -typedef struct { - uint8_t ctrl; - uint8_t status; - uint8_t buffer[512]; - uint8_t ext_ram[0x80]; - uint8_t block_count; - - int block_loaded; - int pos, host_pos; - - int bios_enabled; +typedef struct t128_t { + uint8_t ctrl; + uint8_t status; + uint8_t buffer[512]; + uint8_t ext_ram[0x80]; + uint8_t block_count; + + int block_loaded; + int pos, host_pos; + + int bios_enabled; } t128_t; -typedef struct { - ncr_t ncr; - t128_t t128; +typedef struct ncr5380_t { + ncr_t ncr; + t128_t t128; - const char *name; + const char *name; - uint8_t buffer[128]; - uint8_t int_ram[0x40], ext_ram[0x600]; + uint8_t buffer[128]; + uint8_t int_ram[0x40]; + uint8_t ext_ram[0x600]; - uint32_t rom_addr; - uint16_t base; + uint32_t rom_addr; + uint16_t base; - int8_t irq; - int8_t type; - int8_t bios_ver; - uint8_t block_count; - uint8_t status_ctrl; - uint8_t bus, pad; + int8_t irq; + int8_t type; + int8_t bios_ver; + uint8_t block_count; + uint8_t status_ctrl; + uint8_t bus, pad; - rom_t bios_rom; + rom_t bios_rom; mem_mapping_t mapping; - int block_count_loaded; + int block_count_loaded; - int buffer_pos; - int buffer_host_pos; + int buffer_pos; + int buffer_host_pos; - int dma_enabled; + int dma_enabled; - pc_timer_t timer; - double period; + pc_timer_t timer; + double period; - int ncr_busy; + int ncr_busy; + uint8_t pos_regs[8]; } ncr5380_t; -#define STATE_IDLE 0 -#define STATE_COMMAND 1 -#define STATE_DATAIN 2 -#define STATE_DATAOUT 3 -#define STATE_STATUS 4 -#define STATE_MESSAGEIN 5 -#define STATE_SELECT 6 -#define STATE_MESSAGEOUT 7 -#define STATE_MESSAGE_ID 8 +#define STATE_IDLE 0 +#define STATE_COMMAND 1 +#define STATE_DATAIN 2 +#define STATE_DATAOUT 3 +#define STATE_STATUS 4 +#define STATE_MESSAGEIN 5 +#define STATE_SELECT 6 +#define STATE_MESSAGEOUT 7 +#define STATE_MESSAGE_ID 8 -#define DMA_IDLE 0 -#define DMA_SEND 1 +#define DMA_IDLE 0 +#define DMA_SEND 1 #define DMA_INITIATOR_RECEIVE 2 -static int cmd_len[8] = {6, 10, 10, 6, 16, 12, 6, 6}; - +static int cmd_len[8] = { 6, 10, 10, 6, 16, 12, 6, 6 }; #ifdef ENABLE_NCR5380_LOG int ncr5380_do_log = ENABLE_NCR5380_LOG; - static void ncr_log(const char *fmt, ...) { va_list ap; if (ncr5380_do_log) { - va_start(ap, fmt); - pclog_ex(fmt, ap); - va_end(ap); + va_start(ap, fmt); + pclog_ex(fmt, ap); + va_end(ap); } } #else -#define ncr_log(fmt, ...) +# define ncr_log(fmt, ...) #endif - #define SET_BUS_STATE(ncr, state) ncr->cur_bus = (ncr->cur_bus & ~(SCSI_PHASE_MESSAGE_IN)) | (state & (SCSI_PHASE_MESSAGE_IN)) static void @@ -209,37 +220,36 @@ static void ncr_irq(ncr5380_t *ncr_dev, ncr_t *ncr, int set_irq) { if (set_irq) { - ncr->isr |= STATUS_INT; - picint(1 << ncr_dev->irq); + ncr->isr |= STATUS_INT; + picint(1 << ncr_dev->irq); } else { - ncr->isr &= ~STATUS_INT; - picintc(1 << ncr_dev->irq); + ncr->isr &= ~STATUS_INT; + picintc(1 << ncr_dev->irq); } } static int get_dev_id(uint8_t data) { - int c; - - for (c = 0; c < SCSI_ID_MAX; c++) { - if (data & (1 << c)) return(c); + for (uint8_t c = 0; c < SCSI_ID_MAX; c++) { + if (data & (1 << c)) + return c; } - return(-1); + return -1; } -static int +static int getmsglen(uint8_t *msgp, int len) { - uint8_t msg = msgp[0]; - if (msg == 0 || (msg >= 0x02 && msg <= 0x1f) ||msg >= 0x80) - return 1; - if (msg >= 0x20 && msg <= 0x2f) - return 2; - if (len < 2) - return 3; - return msgp[1]; + uint8_t msg = msgp[0]; + if (msg == 0 || (msg >= 0x02 && msg <= 0x1f) || msg >= 0x80) + return 1; + if (msg >= 0x20 && msg <= 0x2f) + return 2; + if (len < 2) + return 3; + return msgp[1]; } static void @@ -247,11 +257,11 @@ ncr_reset(ncr5380_t *ncr_dev, ncr_t *ncr) { memset(ncr, 0x00, sizeof(ncr_t)); ncr_log("NCR reset\n"); - + timer_stop(&ncr_dev->timer); - + for (int i = 0; i < 8; i++) - scsi_device_reset(&scsi_devices[ncr_dev->bus][i]); + scsi_device_reset(&scsi_devices[ncr_dev->bus][i]); ncr_irq(ncr_dev, ncr, 0); } @@ -260,898 +270,948 @@ static void ncr_timer_on(ncr5380_t *ncr_dev, ncr_t *ncr, int callback) { double p = ncr_dev->period; - + if (ncr->data_wait & 2) - ncr->data_wait &= ~2; - - if (callback) { - if (ncr_dev->type == 3) - p *= 512.0; - else - p *= 128.0; - } + ncr->data_wait &= ~2; - p += 1.0; - - ncr_log("P = %lf, command = %02x, callback = %i, period = %lf, t128 pos = %i\n", p, ncr->command[0], callback, ncr_dev->period, ncr_dev->t128.host_pos); - timer_on_auto(&ncr_dev->timer, p); + if (callback) { + if (ncr_dev->type == 3) + p *= 512.0; + else + p *= 128.0; + } + + p += 1.0; + + ncr_log("P = %lf, command = %02x, callback = %i, period = %lf, t128 pos = %i\n", p, ncr->command[0], callback, ncr_dev->period, ncr_dev->t128.host_pos); + timer_on_auto(&ncr_dev->timer, p); } - static uint32_t get_bus_host(ncr_t *ncr) { uint32_t bus_host = 0; if (ncr->icr & ICR_DBP) - bus_host |= BUS_DBP; + bus_host |= BUS_DBP; if (ncr->icr & ICR_SEL) - bus_host |= BUS_SEL; + bus_host |= BUS_SEL; if (ncr->tcr & TCR_IO) - bus_host |= BUS_IO; + bus_host |= BUS_IO; if (ncr->tcr & TCR_CD) - bus_host |= BUS_CD; + bus_host |= BUS_CD; if (ncr->tcr & TCR_MSG) - bus_host |= BUS_MSG; + bus_host |= BUS_MSG; if (ncr->tcr & TCR_REQ) - bus_host |= BUS_REQ; + bus_host |= BUS_REQ; if (ncr->icr & ICR_BSY) - bus_host |= BUS_BSY; + bus_host |= BUS_BSY; if (ncr->icr & ICR_ATN) - bus_host |= BUS_ATN; + bus_host |= BUS_ATN; if (ncr->icr & ICR_ACK) - bus_host |= BUS_ACK; + bus_host |= BUS_ACK; if (ncr->mode & MODE_ARBITRATE) - bus_host |= BUS_ARB; + bus_host |= BUS_ARB; - return(bus_host | BUS_SETDATA(ncr->output_data)); + return (bus_host | BUS_SETDATA(ncr->output_data)); } - static void ncr_bus_read(ncr5380_t *ncr_dev) { - ncr_t *ncr = &ncr_dev->ncr; - scsi_device_t *dev; - int phase; + ncr_t *ncr = &ncr_dev->ncr; + const scsi_device_t *dev; + int phase; /*Wait processes to handle bus requests*/ if (ncr->clear_req) { - ncr->clear_req--; - if (!ncr->clear_req) { - ncr_log("Prelude to command data\n"); - SET_BUS_STATE(ncr, ncr->new_phase); - ncr->cur_bus |= BUS_REQ; - } + ncr->clear_req--; + if (!ncr->clear_req) { + ncr_log("Prelude to command data\n"); + SET_BUS_STATE(ncr, ncr->new_phase); + ncr->cur_bus |= BUS_REQ; + } } if (ncr->wait_data) { - ncr->wait_data--; - if (!ncr->wait_data) { - dev = &scsi_devices[ncr_dev->bus][ncr->target_id]; - SET_BUS_STATE(ncr, ncr->new_phase); - phase = (ncr->cur_bus & SCSI_PHASE_MESSAGE_IN); + ncr->wait_data--; + if (!ncr->wait_data) { + dev = &scsi_devices[ncr_dev->bus][ncr->target_id]; + SET_BUS_STATE(ncr, ncr->new_phase); + phase = (ncr->cur_bus & SCSI_PHASE_MESSAGE_IN); - if (phase == SCSI_PHASE_DATA_IN) { - ncr->tx_data = dev->sc->temp_buffer[ncr->data_pos++]; - ncr->state = STATE_DATAIN; - ncr->cur_bus = (ncr->cur_bus & ~BUS_DATAMASK) | BUS_SETDATA(ncr->tx_data) | BUS_DBP; - } else if (phase == SCSI_PHASE_DATA_OUT) { - if (ncr->new_phase & BUS_IDLE) { - ncr->state = STATE_IDLE; - ncr->cur_bus &= ~BUS_BSY; - } else - ncr->state = STATE_DATAOUT; - } else if (phase == SCSI_PHASE_STATUS) { - ncr->cur_bus |= BUS_REQ; - ncr->state = STATE_STATUS; - ncr->cur_bus = (ncr->cur_bus & ~BUS_DATAMASK) | BUS_SETDATA(dev->status) | BUS_DBP; - } else if (phase == SCSI_PHASE_MESSAGE_IN) { - ncr->state = STATE_MESSAGEIN; - ncr->cur_bus = (ncr->cur_bus & ~BUS_DATAMASK) | BUS_SETDATA(0) | BUS_DBP; - } else if (phase == SCSI_PHASE_MESSAGE_OUT) { - ncr->cur_bus |= BUS_REQ; - ncr->state = STATE_MESSAGEOUT; - ncr->cur_bus = (ncr->cur_bus & ~BUS_DATAMASK) | BUS_SETDATA(ncr->target_id >> 5) | BUS_DBP; - } - } + if (phase == SCSI_PHASE_DATA_IN) { + ncr->tx_data = dev->sc->temp_buffer[ncr->data_pos++]; + ncr->state = STATE_DATAIN; + ncr->cur_bus = (ncr->cur_bus & ~BUS_DATAMASK) | BUS_SETDATA(ncr->tx_data) | BUS_DBP; + } else if (phase == SCSI_PHASE_DATA_OUT) { + if (ncr->new_phase & BUS_IDLE) { + ncr->state = STATE_IDLE; + ncr->cur_bus &= ~BUS_BSY; + } else + ncr->state = STATE_DATAOUT; + } else if (phase == SCSI_PHASE_STATUS) { + ncr->cur_bus |= BUS_REQ; + ncr->state = STATE_STATUS; + ncr->cur_bus = (ncr->cur_bus & ~BUS_DATAMASK) | BUS_SETDATA(dev->status) | BUS_DBP; + } else if (phase == SCSI_PHASE_MESSAGE_IN) { + ncr->state = STATE_MESSAGEIN; + ncr->cur_bus = (ncr->cur_bus & ~BUS_DATAMASK) | BUS_SETDATA(0) | BUS_DBP; + } else if (phase == SCSI_PHASE_MESSAGE_OUT) { + ncr->cur_bus |= BUS_REQ; + ncr->state = STATE_MESSAGEOUT; + ncr->cur_bus = (ncr->cur_bus & ~BUS_DATAMASK) | BUS_SETDATA(ncr->target_id >> 5) | BUS_DBP; + } + } } if (ncr->wait_complete) { - ncr->wait_complete--; - if (!ncr->wait_complete) - ncr->cur_bus |= BUS_REQ; + ncr->wait_complete--; + if (!ncr->wait_complete) + ncr->cur_bus |= BUS_REQ; } } - static void ncr_bus_update(void *priv, int bus) { - ncr5380_t *ncr_dev = (ncr5380_t *)priv; - ncr_t *ncr = &ncr_dev->ncr; - scsi_device_t *dev = &scsi_devices[ncr_dev->bus][ncr->target_id]; - double p; - uint8_t sel_data; - int msglen; + ncr5380_t *ncr_dev = (ncr5380_t *) priv; + ncr_t *ncr = &ncr_dev->ncr; + scsi_device_t *dev = &scsi_devices[ncr_dev->bus][ncr->target_id]; + double p; + uint8_t sel_data; + int msglen; /*Start the SCSI command layer, which will also make the timings*/ if (bus & BUS_ARB) - ncr->state = STATE_IDLE; + ncr->state = STATE_IDLE; ncr_log("State = %i\n", ncr->state); switch (ncr->state) { - case STATE_IDLE: - ncr->clear_req = ncr->wait_data = ncr->wait_complete = 0; - if ((bus & BUS_SEL) && !(bus & BUS_BSY)) { - ncr_log("Selection phase\n"); - sel_data = BUS_GETDATA(bus); + case STATE_IDLE: + ncr->clear_req = ncr->wait_data = ncr->wait_complete = 0; + if ((bus & BUS_SEL) && !(bus & BUS_BSY)) { + ncr_log("Selection phase\n"); + sel_data = BUS_GETDATA(bus); - ncr->target_id = get_dev_id(sel_data); + ncr->target_id = get_dev_id(sel_data); - ncr_log("Select - target ID = %i\n", ncr->target_id); + ncr_log("Select - target ID = %i\n", ncr->target_id); - /*Once the device has been found and selected, mark it as busy*/ - if ((ncr->target_id != (uint8_t)-1) && scsi_device_present(&scsi_devices[ncr_dev->bus][ncr->target_id])) { - ncr->cur_bus |= BUS_BSY; - ncr->state = STATE_SELECT; - } else { - ncr_log("Device not found at ID %i, Current Bus BSY=%02x\n", ncr->target_id, ncr->cur_bus); - ncr->cur_bus = 0; - } - } - break; - case STATE_SELECT: - if (!(bus & BUS_SEL)) { - if (!(bus & BUS_ATN)) { - if ((ncr->target_id != (uint8_t)-1) && scsi_device_present(&scsi_devices[ncr_dev->bus][ncr->target_id])) { - ncr_log("Device found at ID %i, Current Bus BSY=%02x\n", ncr->target_id, ncr->cur_bus); - ncr->state = STATE_COMMAND; - ncr->cur_bus = BUS_BSY | BUS_REQ; - ncr_log("CurBus BSY|REQ=%02x\n", ncr->cur_bus); - ncr->command_pos = 0; - SET_BUS_STATE(ncr, SCSI_PHASE_COMMAND); - } else { - ncr->state = STATE_IDLE; - ncr->cur_bus = 0; - } - } else { - ncr_log("Set to SCSI Message Out\n"); - ncr->new_phase = SCSI_PHASE_MESSAGE_OUT; - ncr->wait_data = 4; - ncr->msgout_pos = 0; - ncr->is_msgout = 1; - } - } - break; - case STATE_COMMAND: - if ((bus & BUS_ACK) && !(ncr->bus_in & BUS_ACK)) { - /*Write command byte to the output data register*/ - ncr->command[ncr->command_pos++] = BUS_GETDATA(bus); - ncr->clear_req = 3; - ncr->new_phase = ncr->cur_bus & SCSI_PHASE_MESSAGE_IN; - ncr->cur_bus &= ~BUS_REQ; + /*Once the device has been found and selected, mark it as busy*/ + if ((ncr->target_id != (uint8_t) -1) && scsi_device_present(&scsi_devices[ncr_dev->bus][ncr->target_id])) { + ncr->cur_bus |= BUS_BSY; + ncr->state = STATE_SELECT; + } else { + ncr_log("Device not found at ID %i, Current Bus BSY=%02x\n", ncr->target_id, ncr->cur_bus); + ncr->cur_bus = 0; + } + } + break; + case STATE_SELECT: + if (!(bus & BUS_SEL)) { + if (!(bus & BUS_ATN)) { + if ((ncr->target_id != (uint8_t) -1) && scsi_device_present(&scsi_devices[ncr_dev->bus][ncr->target_id])) { + ncr_log("Device found at ID %i, Current Bus BSY=%02x\n", ncr->target_id, ncr->cur_bus); + ncr->state = STATE_COMMAND; + ncr->cur_bus = BUS_BSY | BUS_REQ; + ncr_log("CurBus BSY|REQ=%02x\n", ncr->cur_bus); + ncr->command_pos = 0; + SET_BUS_STATE(ncr, SCSI_PHASE_COMMAND); + } else { + ncr->state = STATE_IDLE; + ncr->cur_bus = 0; + } + } else { + ncr_log("Set to SCSI Message Out\n"); + ncr->new_phase = SCSI_PHASE_MESSAGE_OUT; + ncr->wait_data = 4; + ncr->msgout_pos = 0; + ncr->is_msgout = 1; + } + } + break; + case STATE_COMMAND: + if ((bus & BUS_ACK) && !(ncr->bus_in & BUS_ACK)) { + /*Write command byte to the output data register*/ + ncr->command[ncr->command_pos++] = BUS_GETDATA(bus); + ncr->clear_req = 3; + ncr->new_phase = ncr->cur_bus & SCSI_PHASE_MESSAGE_IN; + ncr->cur_bus &= ~BUS_REQ; - ncr_log("Command pos=%i, output data=%02x\n", ncr->command_pos, BUS_GETDATA(bus)); + ncr_log("Command pos=%i, output data=%02x\n", ncr->command_pos, BUS_GETDATA(bus)); - if (ncr->command_pos == cmd_len[(ncr->command[0] >> 5) & 7]) { - if (ncr->is_msgout) { - ncr->is_msgout = 0; - // ncr->command[1] = (ncr->command[1] & 0x1f) | (ncr->msglun << 5); - } + if (ncr->command_pos == cmd_len[(ncr->command[0] >> 5) & 7]) { + if (ncr->is_msgout) { + ncr->is_msgout = 0; +#if 0 + ncr->command[1] = (ncr->command[1] & 0x1f) | (ncr->msglun << 5); +#endif + } - /*Reset data position to default*/ - ncr->data_pos = 0; + /*Reset data position to default*/ + ncr->data_pos = 0; - dev = &scsi_devices[ncr_dev->bus][ncr->target_id]; + dev = &scsi_devices[ncr_dev->bus][ncr->target_id]; - ncr_log("SCSI Command 0x%02X for ID %d, status code=%02x\n", ncr->command[0], ncr->target_id, dev->status); - dev->buffer_length = -1; - scsi_device_command_phase0(dev, ncr->command); - ncr_log("SCSI ID %i: Command %02X: Buffer Length %i, SCSI Phase %02X\n", ncr->target_id, ncr->command[0], dev->buffer_length, dev->phase); + ncr_log("SCSI Command 0x%02X for ID %d, status code=%02x\n", ncr->command[0], ncr->target_id, dev->status); + dev->buffer_length = -1; + scsi_device_command_phase0(dev, ncr->command); + ncr_log("SCSI ID %i: Command %02X: Buffer Length %i, SCSI Phase %02X\n", ncr->target_id, ncr->command[0], dev->buffer_length, dev->phase); - ncr_dev->period = 1.0; - ncr->wait_data = 4; - ncr->data_wait = 0; + ncr_dev->period = 1.0; + ncr->wait_data = 4; + ncr->data_wait = 0; - if (dev->status == SCSI_STATUS_OK) { - /*If the SCSI phase is Data In or Data Out, allocate the SCSI buffer based on the transfer length of the command*/ - if (dev->buffer_length && (dev->phase == SCSI_PHASE_DATA_IN || dev->phase == SCSI_PHASE_DATA_OUT)) { - p = scsi_device_get_callback(dev); - if (p <= 0.0) { - ncr_dev->period = 0.2; - } else { - ncr_dev->period = p / ((double) dev->buffer_length); - } - ncr->data_wait |= 2; - ncr_log("SCSI ID %i: command 0x%02x for p = %lf, update = %lf, len = %i\n", ncr->target_id, ncr->command[0], p, ncr_dev->period, dev->buffer_length); - } - } - ncr->new_phase = dev->phase; - } - } - break; - case STATE_DATAIN: - dev = &scsi_devices[ncr_dev->bus][ncr->target_id]; - if ((bus & BUS_ACK) && !(ncr->bus_in & BUS_ACK)) { - if (ncr->data_pos >= dev->buffer_length) { - ncr->cur_bus &= ~BUS_REQ; - scsi_device_command_phase1(dev); - ncr->new_phase = SCSI_PHASE_STATUS; - ncr->wait_data = 4; - ncr->wait_complete = 8; - } else { - ncr->tx_data = dev->sc->temp_buffer[ncr->data_pos++]; - ncr->cur_bus = (ncr->cur_bus & ~BUS_DATAMASK) | BUS_SETDATA(ncr->tx_data) | BUS_DBP | BUS_REQ; - if (ncr->data_wait & 2) - ncr->data_wait &= ~2; - if (ncr->dma_mode == DMA_IDLE) { /*If a data in command that is not read 6/10 has been issued*/ - ncr->data_wait |= 1; - ncr_log("DMA mode idle in\n"); - timer_on_auto(&ncr_dev->timer, ncr_dev->period); - } else - ncr->clear_req = 3; - ncr->cur_bus &= ~BUS_REQ; - ncr->new_phase = SCSI_PHASE_DATA_IN; - } - } - break; - case STATE_DATAOUT: - dev = &scsi_devices[ncr_dev->bus][ncr->target_id]; - if ((bus & BUS_ACK) && !(ncr->bus_in & BUS_ACK)) { - dev->sc->temp_buffer[ncr->data_pos++] = BUS_GETDATA(bus); + if (dev->status == SCSI_STATUS_OK) { + /*If the SCSI phase is Data In or Data Out, allocate the SCSI buffer based on the transfer length of the command*/ + if (dev->buffer_length && (dev->phase == SCSI_PHASE_DATA_IN || dev->phase == SCSI_PHASE_DATA_OUT)) { + p = scsi_device_get_callback(dev); + if (p <= 0.0) { + ncr_dev->period = 0.2; + } else { + ncr_dev->period = p / ((double) dev->buffer_length); + } + ncr->data_wait |= 2; + ncr_log("SCSI ID %i: command 0x%02x for p = %lf, update = %lf, len = %i\n", ncr->target_id, ncr->command[0], p, ncr_dev->period, dev->buffer_length); + } + } + ncr->new_phase = dev->phase; + } + } + break; + case STATE_DATAIN: + dev = &scsi_devices[ncr_dev->bus][ncr->target_id]; + if ((bus & BUS_ACK) && !(ncr->bus_in & BUS_ACK)) { + if (ncr->data_pos >= dev->buffer_length) { + ncr->cur_bus &= ~BUS_REQ; + scsi_device_command_phase1(dev); + ncr->new_phase = SCSI_PHASE_STATUS; + ncr->wait_data = 4; + ncr->wait_complete = 8; + } else { + ncr->tx_data = dev->sc->temp_buffer[ncr->data_pos++]; + ncr->cur_bus = (ncr->cur_bus & ~BUS_DATAMASK) | BUS_SETDATA(ncr->tx_data) | BUS_DBP | BUS_REQ; + if (ncr->data_wait & 2) + ncr->data_wait &= ~2; + if (ncr->dma_mode == DMA_IDLE) { /*If a data in command that is not read 6/10 has been issued*/ + ncr->data_wait |= 1; + ncr_log("DMA mode idle in\n"); + timer_on_auto(&ncr_dev->timer, ncr_dev->period); + } else + ncr->clear_req = 3; + ncr->cur_bus &= ~BUS_REQ; + ncr->new_phase = SCSI_PHASE_DATA_IN; + } + } + break; + case STATE_DATAOUT: + dev = &scsi_devices[ncr_dev->bus][ncr->target_id]; + if ((bus & BUS_ACK) && !(ncr->bus_in & BUS_ACK)) { + dev->sc->temp_buffer[ncr->data_pos++] = BUS_GETDATA(bus); - if (ncr->data_pos >= dev->buffer_length) { - ncr->cur_bus &= ~BUS_REQ; - scsi_device_command_phase1(dev); - ncr->new_phase = SCSI_PHASE_STATUS; - ncr->wait_data = 4; - ncr->wait_complete = 8; - } else { - /*More data is to be transferred, place a request*/ - if (ncr->dma_mode == DMA_IDLE) { /*If a data out command that is not write 6/10 has been issued*/ - ncr->data_wait |= 1; - ncr_log("DMA mode idle out\n"); - timer_on_auto(&ncr_dev->timer, ncr_dev->period); - } else { - ncr->clear_req = 3; - } - ncr->cur_bus &= ~BUS_REQ; - ncr_log("CurBus ~REQ_DataOut=%02x\n", ncr->cur_bus); - } - } - break; - case STATE_STATUS: - if ((bus & BUS_ACK) && !(ncr->bus_in & BUS_ACK)) { - /*All transfers done, wait until next transfer*/ - scsi_device_identify(&scsi_devices[ncr_dev->bus][ncr->target_id], SCSI_LUN_USE_CDB); - ncr->cur_bus &= ~BUS_REQ; - ncr->new_phase = SCSI_PHASE_MESSAGE_IN; - ncr->wait_data = 4; - ncr->wait_complete = 8; - } - break; - case STATE_MESSAGEIN: - if ((bus & BUS_ACK) && !(ncr->bus_in & BUS_ACK)) { - ncr->cur_bus &= ~BUS_REQ; - ncr->new_phase = BUS_IDLE; - ncr->wait_data = 4; - } - break; - case STATE_MESSAGEOUT: - ncr_log("Ack on MSGOUT = %02x\n", (bus & BUS_ACK)); - if ((bus & BUS_ACK) && !(ncr->bus_in & BUS_ACK)) { - ncr->msgout[ncr->msgout_pos++] = BUS_GETDATA(bus); - msglen = getmsglen(ncr->msgout, ncr->msgout_pos); - if (ncr->msgout_pos >= msglen) { - if ((ncr->msgout[0] & (0x80 | 0x20)) == 0x80) - ncr->msglun = ncr->msgout[0] & 7; - ncr->cur_bus &= ~BUS_REQ; - ncr->state = STATE_MESSAGE_ID; - } - } - break; - case STATE_MESSAGE_ID: - if ((ncr->target_id != (uint8_t)-1) && scsi_device_present(&scsi_devices[ncr_dev->bus][ncr->target_id])) { - ncr_log("Device found at ID %i on MSGOUT, Current Bus BSY=%02x\n", ncr->target_id, ncr->cur_bus); - scsi_device_identify(&scsi_devices[ncr_dev->bus][ncr->target_id], ncr->msglun); - ncr->state = STATE_COMMAND; - ncr->cur_bus = BUS_BSY | BUS_REQ; - ncr_log("CurBus BSY|REQ=%02x\n", ncr->cur_bus); - ncr->command_pos = 0; - SET_BUS_STATE(ncr, SCSI_PHASE_COMMAND); - } - break; + if (ncr->data_pos >= dev->buffer_length) { + ncr->cur_bus &= ~BUS_REQ; + scsi_device_command_phase1(dev); + ncr->new_phase = SCSI_PHASE_STATUS; + ncr->wait_data = 4; + ncr->wait_complete = 8; + } else { + /*More data is to be transferred, place a request*/ + if (ncr->dma_mode == DMA_IDLE) { /*If a data out command that is not write 6/10 has been issued*/ + ncr->data_wait |= 1; + ncr_log("DMA mode idle out\n"); + timer_on_auto(&ncr_dev->timer, ncr_dev->period); + } else { + ncr->clear_req = 3; + } + ncr->cur_bus &= ~BUS_REQ; + ncr_log("CurBus ~REQ_DataOut=%02x\n", ncr->cur_bus); + } + } + break; + case STATE_STATUS: + if ((bus & BUS_ACK) && !(ncr->bus_in & BUS_ACK)) { + /*All transfers done, wait until next transfer*/ + scsi_device_identify(&scsi_devices[ncr_dev->bus][ncr->target_id], SCSI_LUN_USE_CDB); + ncr->cur_bus &= ~BUS_REQ; + ncr->new_phase = SCSI_PHASE_MESSAGE_IN; + ncr->wait_data = 4; + ncr->wait_complete = 8; + } + break; + case STATE_MESSAGEIN: + if ((bus & BUS_ACK) && !(ncr->bus_in & BUS_ACK)) { + ncr->cur_bus &= ~BUS_REQ; + ncr->new_phase = BUS_IDLE; + ncr->wait_data = 4; + } + break; + case STATE_MESSAGEOUT: + ncr_log("Ack on MSGOUT = %02x\n", (bus & BUS_ACK)); + if ((bus & BUS_ACK) && !(ncr->bus_in & BUS_ACK)) { + ncr->msgout[ncr->msgout_pos++] = BUS_GETDATA(bus); + msglen = getmsglen(ncr->msgout, ncr->msgout_pos); + if (ncr->msgout_pos >= msglen) { + if ((ncr->msgout[0] & (0x80 | 0x20)) == 0x80) + ncr->msglun = ncr->msgout[0] & 7; + ncr->cur_bus &= ~BUS_REQ; + ncr->state = STATE_MESSAGE_ID; + } + } + break; + case STATE_MESSAGE_ID: + if ((ncr->target_id != (uint8_t) -1) && scsi_device_present(&scsi_devices[ncr_dev->bus][ncr->target_id])) { + ncr_log("Device found at ID %i on MSGOUT, Current Bus BSY=%02x\n", ncr->target_id, ncr->cur_bus); + scsi_device_identify(&scsi_devices[ncr_dev->bus][ncr->target_id], ncr->msglun); + ncr->state = STATE_COMMAND; + ncr->cur_bus = BUS_BSY | BUS_REQ; + ncr_log("CurBus BSY|REQ=%02x\n", ncr->cur_bus); + ncr->command_pos = 0; + SET_BUS_STATE(ncr, SCSI_PHASE_COMMAND); + } + break; + + default: + break; } ncr->bus_in = bus; } - -static void +static void ncr_write(uint16_t port, uint8_t val, void *priv) { - ncr5380_t *ncr_dev = (ncr5380_t *)priv; - ncr_t *ncr = &ncr_dev->ncr; - scsi_device_t *dev = &scsi_devices[ncr_dev->bus][ncr->target_id]; - int bus_host = 0; + ncr5380_t *ncr_dev = (ncr5380_t *) priv; + ncr_t *ncr = &ncr_dev->ncr; + const scsi_device_t *dev = &scsi_devices[ncr_dev->bus][ncr->target_id]; + int bus_host = 0; - ncr_log("NCR5380 write(%04x,%02x)\n",port & 7,val); + ncr_log("NCR5380 write(%04x,%02x)\n", port & 7, val); switch (port & 7) { - case 0: /* Output data register */ - ncr_log("Write: Output data register, val = %02x\n", val); - ncr->output_data = val; - break; + case 0: /* Output data register */ + ncr_log("Write: Output data register, val = %02x\n", val); + ncr->output_data = val; + break; - case 1: /* Initiator Command Register */ - ncr_log("Write: Initiator command register\n"); - if ((val & 0x80) && !(ncr->icr & 0x80)) { - ncr_log("Resetting the 5380\n"); - ncr_reset(ncr_dev, &ncr_dev->ncr); - } - ncr->icr = val; - break; + case 1: /* Initiator Command Register */ + ncr_log("Write: Initiator command register\n"); + if ((val & 0x80) && !(ncr->icr & 0x80)) { + ncr_log("Resetting the 5380\n"); + ncr_reset(ncr_dev, &ncr_dev->ncr); + } + ncr->icr = val; + break; - case 2: /* Mode register */ - ncr_log("Write: Mode register, val=%02x\n", val & MODE_DMA); - if ((val & MODE_ARBITRATE) && !(ncr->mode & MODE_ARBITRATE)) { - ncr->icr &= ~ICR_ARB_LOST; - ncr->icr |= ICR_ARB_IN_PROGRESS; - } + case 2: /* Mode register */ + ncr_log("Write: Mode register, val=%02x.\n", val); + if ((val & MODE_ARBITRATE) && !(ncr->mode & MODE_ARBITRATE)) { + ncr->icr &= ~ICR_ARB_LOST; + ncr->icr |= ICR_ARB_IN_PROGRESS; + } - ncr->mode = val; - - if (ncr_dev->type == 3) { - /*Don't stop the timer until it finishes the transfer*/ - if (ncr_dev->t128.block_loaded && (ncr->mode & MODE_DMA)) { - ncr_log("Continuing DMA mode\n"); - ncr_timer_on(ncr_dev, ncr, 0); - } + ncr->mode = val; - /*When a pseudo-DMA transfer has completed (Send or Initiator Receive), mark it as complete and idle the status*/ - if (!ncr_dev->t128.block_loaded && !(ncr->mode & MODE_DMA)) { - ncr_log("No DMA mode\n"); - ncr->tcr &= ~TCR_LAST_BYTE_SENT; - ncr->isr &= ~STATUS_END_OF_DMA; - ncr->dma_mode = DMA_IDLE; - } - } else { - /*Don't stop the timer until it finishes the transfer*/ - if (ncr_dev->block_count_loaded && (ncr->mode & MODE_DMA) && !timer_is_enabled(&ncr_dev->timer)) { - ncr_log("Continuing DMA mode\n"); - ncr_timer_on(ncr_dev, ncr, 0); - } - - /*When a pseudo-DMA transfer has completed (Send or Initiator Receive), mark it as complete and idle the status*/ - if (!ncr_dev->block_count_loaded && !(ncr->mode & MODE_DMA)) { - ncr_log("No DMA mode\n"); - ncr->tcr &= ~TCR_LAST_BYTE_SENT; - ncr->isr &= ~STATUS_END_OF_DMA; - ncr->dma_mode = DMA_IDLE; - } - } - break; + if (ncr_dev->type == 3) { + /*Don't stop the timer until it finishes the transfer*/ + if (ncr_dev->t128.block_loaded && (ncr->mode & MODE_DMA)) { + ncr_log("Continuing DMA mode\n"); + ncr_timer_on(ncr_dev, ncr, 0); + } - case 3: /* Target Command Register */ - ncr_log("Write: Target Command register\n"); - ncr->tcr = val; - break; + /*When a pseudo-DMA transfer has completed (Send or Initiator Receive), mark it as complete and idle the status*/ + if (!ncr_dev->t128.block_loaded && !(ncr->mode & MODE_DMA)) { + ncr_log("No DMA mode\n"); + ncr->tcr &= ~TCR_LAST_BYTE_SENT; + ncr->isr &= ~STATUS_END_OF_DMA; + ncr->dma_mode = DMA_IDLE; + } + } else { + /*Don't stop the timer until it finishes the transfer*/ + if (ncr_dev->block_count_loaded && (ncr->mode & MODE_DMA) && + !timer_is_on(&ncr_dev->timer)) { + ncr_log("Continuing DMA mode\n"); + ncr_timer_on(ncr_dev, ncr, 0); + } - case 4: /* Select Enable Register */ - ncr_log("Write: Select Enable register\n"); - break; - - case 5: /* start DMA Send */ - ncr_log("Write: start DMA send register\n"); - /*a Write 6/10 has occurred, start the timer when the block count is loaded*/ - ncr->dma_mode = DMA_SEND; - if (ncr_dev->type == 3) { - memset(ncr_dev->t128.buffer, 0, MIN(512, dev->buffer_length)); - - ncr_log("DMA send timer start, enabled? = %i\n", timer_is_enabled(&ncr_dev->timer)); - ncr_dev->t128.block_count = dev->buffer_length >> 9; - ncr_dev->t128.block_loaded = 1; + /*When a pseudo-DMA transfer has completed (Send or Initiator Receive), mark it as complete and idle the status*/ + if (!ncr_dev->block_count_loaded && !(ncr->mode & MODE_DMA)) { + ncr_log("No DMA mode\n"); + ncr->tcr &= ~TCR_LAST_BYTE_SENT; + ncr->isr &= ~STATUS_END_OF_DMA; + ncr->dma_mode = DMA_IDLE; + } + } + break; - ncr_dev->t128.host_pos = 0; - ncr_dev->t128.status |= 0x04; - } else { - if ((ncr->mode & MODE_DMA) && !timer_is_enabled(&ncr_dev->timer)) { - memset(ncr_dev->buffer, 0, MIN(128, dev->buffer_length)); - - ncr_log("DMA send timer on\n"); - ncr_timer_on(ncr_dev, ncr, 0); - } - } - break; + case 3: /* Target Command Register */ + ncr_log("Write: Target Command register\n"); + ncr->tcr = val; + break; - case 7: /* start DMA Initiator Receive */ - ncr_log("Write: start DMA initiator receive register, dma? = %02x\n", ncr->mode & MODE_DMA); - /*a Read 6/10 has occurred, start the timer when the block count is loaded*/ - ncr->dma_mode = DMA_INITIATOR_RECEIVE; - if (ncr_dev->type == 3) { - ncr_log("DMA receive timer start, enabled? = %i, cdb[0] = %02x\n", timer_is_enabled(&ncr_dev->timer), ncr->command[0]); - memset(ncr_dev->t128.buffer, 0, MIN(512, dev->buffer_length)); - - ncr_dev->t128.block_count = dev->buffer_length >> 9; + case 4: /* Select Enable Register */ + ncr_log("Write: Select Enable register\n"); + break; - if (dev->buffer_length < 512) - ncr_dev->t128.block_count = 1; - - ncr_dev->t128.block_loaded = 1; + case 5: /* start DMA Send */ + ncr_log("Write: start DMA send register\n"); + /*a Write 6/10 has occurred, start the timer when the block count is loaded*/ + ncr->dma_mode = DMA_SEND; + if (ncr_dev->type == 3) { + if (dev->buffer_length > 0) { + memset(ncr_dev->t128.buffer, 0, MIN(512, dev->buffer_length)); - ncr_dev->t128.host_pos = MIN(512, dev->buffer_length); - ncr_dev->t128.status |= 0x04; - timer_on_auto(&ncr_dev->timer, 0.02); - } else { - if ((ncr->mode & MODE_DMA) && !timer_is_enabled(&ncr_dev->timer)) { - memset(ncr_dev->buffer, 0, MIN(128, dev->buffer_length)); - - ncr_log("DMA receive timer start\n"); - ncr_timer_on(ncr_dev, ncr, 0); - } - } - break; + ncr_log("DMA send timer start, enabled? = %i\n", timer_is_on(&ncr_dev->timer)); + ncr_dev->t128.block_count = dev->buffer_length >> 9; + ncr_dev->t128.block_loaded = 1; - default: - ncr_log("NCR5380: bad write %04x %02x\n", port, val); - break; + ncr_dev->t128.host_pos = 0; + ncr_dev->t128.status |= 0x04; + } + } else { + if ((ncr->mode & MODE_DMA) && !timer_is_on(&ncr_dev->timer)) { + memset(ncr_dev->buffer, 0, MIN(128, dev->buffer_length)); + + ncr_log("DMA send timer on\n"); + ncr_timer_on(ncr_dev, ncr, 0); + } + } + break; + + case 7: /* start DMA Initiator Receive */ + ncr_log("Write: start DMA initiator receive register, dma? = %02x\n", ncr->mode & MODE_DMA); + /*a Read 6/10 has occurred, start the timer when the block count is loaded*/ + ncr->dma_mode = DMA_INITIATOR_RECEIVE; + if (ncr_dev->type == 3) { + ncr_log("DMA receive timer start, enabled? = %i, cdb[0] = %02x, buflen = %i\n", + timer_is_on(&ncr_dev->timer), ncr->command[0], dev->buffer_length); + if (dev->buffer_length > 0) { + memset(ncr_dev->t128.buffer, 0, MIN(512, dev->buffer_length)); + + ncr_dev->t128.block_count = dev->buffer_length >> 9; + + if (dev->buffer_length < 512) + ncr_dev->t128.block_count = 1; + + ncr_dev->t128.block_loaded = 1; + + ncr_dev->t128.host_pos = MIN(512, dev->buffer_length); + ncr_dev->t128.status |= 0x04; + timer_on_auto(&ncr_dev->timer, 0.02); + } + } else { + if ((ncr->mode & MODE_DMA) && !timer_is_on(&ncr_dev->timer)) { + memset(ncr_dev->buffer, 0, MIN(128, dev->buffer_length)); + + ncr_log("DMA receive timer start\n"); + ncr_timer_on(ncr_dev, ncr, 0); + } + } + break; + + default: + ncr_log("NCR5380: bad write %04x %02x\n", port, val); + break; } - - if (ncr->dma_mode == DMA_IDLE || ncr_dev->type == 0 || ncr_dev->type == 3) { - bus_host = get_bus_host(ncr); - ncr_bus_update(priv, bus_host); + + if (ncr->dma_mode == DMA_IDLE || ncr_dev->type == 0 || ncr_dev->type >= 3) { + bus_host = get_bus_host(ncr); + ncr_bus_update(priv, bus_host); } } - -static uint8_t +static uint8_t ncr_read(uint16_t port, void *priv) { - ncr5380_t *ncr_dev = (ncr5380_t *)priv; - ncr_t *ncr = &ncr_dev->ncr; - uint8_t ret = 0xff; - int bus, bus_state; + ncr5380_t *ncr_dev = (ncr5380_t *) priv; + ncr_t *ncr = &ncr_dev->ncr; + uint8_t ret = 0xff; + int bus; + int bus_state; switch (port & 7) { - case 0: /* Current SCSI data */ - ncr_log("Read: Current SCSI data register\n"); - if (ncr->icr & ICR_DBP) { - /*Return the data from the output register if on data bus phase from ICR*/ - ncr_log("Data Bus Phase, ret = %02x\n", ncr->output_data); - ret = ncr->output_data; - } else { - /*Return the data from the SCSI bus*/ - ncr_bus_read(ncr_dev); - ncr_log("NCR GetData=%02x\n", BUS_GETDATA(ncr->cur_bus)); - ret = BUS_GETDATA(ncr->cur_bus); - } - break; + case 0: /* Current SCSI data */ + ncr_log("Read: Current SCSI data register\n"); + if (ncr->icr & ICR_DBP) { + /*Return the data from the output register if on data bus phase from ICR*/ + ncr_log("Data Bus Phase, ret = %02x\n", ncr->output_data); + ret = ncr->output_data; + } else { + /*Return the data from the SCSI bus*/ + ncr_bus_read(ncr_dev); + ncr_log("NCR GetData=%02x\n", BUS_GETDATA(ncr->cur_bus)); + ret = BUS_GETDATA(ncr->cur_bus); + } + break; - case 1: /* Initiator Command Register */ - ncr_log("Read: Initiator Command register, NCR ICR Read=%02x\n", ncr->icr); - ret = ncr->icr; - break; + case 1: /* Initiator Command Register */ + ncr_log("Read: Initiator Command register, NCR ICR Read=%02x\n", ncr->icr); + ret = ncr->icr; + break; - case 2: /* Mode register */ - ncr_log("Read: Mode register\n"); - ret = ncr->mode; - break; + case 2: /* Mode register */ + ncr_log("Read: Mode register = %02x.\n", ncr->mode); + ret = ncr->mode; + break; - case 3: /* Target Command Register */ - ncr_log("Read: Target Command register, NCR target stat=%02x\n", ncr->tcr); - ret = ncr->tcr; - break; + case 3: /* Target Command Register */ + ncr_log("Read: Target Command register, NCR target stat=%02x\n", ncr->tcr); + ret = ncr->tcr; + break; - case 4: /* Current SCSI Bus status */ - ncr_log("Read: SCSI bus status register\n"); - ret = 0; - ncr_bus_read(ncr_dev); - ncr_log("NCR cur bus stat=%02x\n", ncr->cur_bus & 0xff); - ret |= (ncr->cur_bus & 0xff); - break; + case 4: /* Current SCSI Bus status */ + ncr_log("Read: SCSI bus status register\n"); + ret = 0; + ncr_bus_read(ncr_dev); + ncr_log("NCR cur bus stat=%02x\n", ncr->cur_bus & 0xff); + ret |= (ncr->cur_bus & 0xff); + if (ncr->icr & ICR_SEL) + ret |= BUS_SEL; + if (ncr->icr & ICR_BSY) + ret |= BUS_BSY; + break; - case 5: /* Bus and Status register */ - ncr_log("Read: Bus and Status register\n"); - ret = 0; + case 5: /* Bus and Status register */ + ncr_log("Read: Bus and Status register\n"); + ret = 0; - bus = get_bus_host(ncr); - ncr_log("Get host from Interrupt\n"); - - /*Check if the phase in process matches with TCR's*/ - if ((bus & SCSI_PHASE_MESSAGE_IN) == (ncr->cur_bus & SCSI_PHASE_MESSAGE_IN)) { - ncr_log("Phase match\n"); - ret |= STATUS_PHASE_MATCH; - } + bus = get_bus_host(ncr); + ncr_log("Get host from Interrupt\n"); - ncr_bus_read(ncr_dev); - bus = ncr->cur_bus; + /*Check if the phase in process matches with TCR's*/ + if ((bus & SCSI_PHASE_MESSAGE_IN) == (ncr->cur_bus & SCSI_PHASE_MESSAGE_IN)) { + ncr_log("Phase match\n"); + ret |= STATUS_PHASE_MATCH; + } - if (bus & BUS_ACK) - ret |= STATUS_ACK; - if (bus & BUS_ATN) - ret |= 0x02; - - if ((bus & BUS_REQ) && (ncr->mode & MODE_DMA)) { - ncr_log("Entering DMA mode\n"); - ret |= STATUS_DRQ; - - bus_state = 0; - - if (bus & BUS_IO) - bus_state |= TCR_IO; - if (bus & BUS_CD) - bus_state |= TCR_CD; - if (bus & BUS_MSG) - bus_state |= TCR_MSG; - if ((ncr->tcr & 7) != bus_state) { - ncr_irq(ncr_dev, ncr, 1); - ncr_log("IRQ issued\n"); - } - } - if (!(bus & BUS_BSY) && (ncr->mode & MODE_MONITOR_BUSY)) { - ncr_log("Busy error\n"); - ret |= STATUS_BUSY_ERROR; - } - ret |= (ncr->isr & (STATUS_INT | STATUS_END_OF_DMA)); - break; + ncr_bus_read(ncr_dev); + bus = ncr->cur_bus; - case 6: - ret = ncr->tx_data; - break; + if ((bus & BUS_ACK) || (ncr->icr & ICR_ACK)) + ret |= STATUS_ACK; + if ((bus & BUS_ATN) || (ncr->icr & ICR_ATN)) + ret |= 0x02; - case 7: /* reset Parity/Interrupt */ - ncr->isr &= ~(STATUS_BUSY_ERROR | 0x20); - ncr_irq(ncr_dev, ncr, 0); - ncr_log("Reset Interrupt\n"); - break; + if ((bus & BUS_REQ) && (ncr->mode & MODE_DMA)) { + ncr_log("Entering DMA mode\n"); + ret |= STATUS_DRQ; - default: - ncr_log("NCR5380: bad read %04x\n", port); - break; + bus_state = 0; + + if (bus & BUS_IO) + bus_state |= TCR_IO; + if (bus & BUS_CD) + bus_state |= TCR_CD; + if (bus & BUS_MSG) + bus_state |= TCR_MSG; + if ((ncr->tcr & 7) != bus_state) { + ncr_irq(ncr_dev, ncr, 1); + ncr_log("IRQ issued\n"); + } + } + if (!(bus & BUS_BSY) && (ncr->mode & MODE_MONITOR_BUSY)) { + ncr_log("Busy error\n"); + ret |= STATUS_BUSY_ERROR; + } + ret |= (ncr->isr & (STATUS_INT | STATUS_END_OF_DMA)); + break; + + case 6: + ret = ncr->tx_data; + break; + + case 7: /* reset Parity/Interrupt */ + ncr->isr &= ~(STATUS_BUSY_ERROR | 0x20); + ncr_irq(ncr_dev, ncr, 0); + ncr_log("Reset Interrupt\n"); + break; + + default: + ncr_log("NCR5380: bad read %04x\n", port); + break; } ncr_log("NCR5380 read(%04x)=%02x\n", port & 7, ret); - return(ret); + return ret; } - /* Memory-mapped I/O READ handler. */ -static uint8_t +static uint8_t memio_read(uint32_t addr, void *priv) { - ncr5380_t *ncr_dev = (ncr5380_t *)priv; - ncr_t *ncr = &ncr_dev->ncr; - scsi_device_t *dev = &scsi_devices[ncr_dev->bus][ncr->target_id]; - uint8_t ret = 0xff; - + ncr5380_t *ncr_dev = (ncr5380_t *) priv; + ncr_t *ncr = &ncr_dev->ncr; + const scsi_device_t *dev = &scsi_devices[ncr_dev->bus][ncr->target_id]; + uint8_t ret = 0xff; + addr &= 0x3fff; if (addr < 0x2000) - ret = ncr_dev->bios_rom.rom[addr & 0x1fff]; + ret = ncr_dev->bios_rom.rom[addr & 0x1fff]; else if (addr < 0x3800) - ret = 0xff; + ret = 0xff; else if (addr >= 0x3a00) - ret = ncr_dev->ext_ram[addr - 0x3a00]; - else switch (addr & 0x3f80) { - case 0x3800: + ret = ncr_dev->ext_ram[addr - 0x3a00]; + else + switch (addr & 0x3f80) { + case 0x3800: #if ENABLE_NCR5380_LOG - ncr_log("Read intRAM %02x %02x\n", addr & 0x3f, ncr_dev->int_ram[addr & 0x3f]); + ncr_log("Read intRAM %02x %02x\n", addr & 0x3f, ncr_dev->int_ram[addr & 0x3f]); #endif - ret = ncr_dev->int_ram[addr & 0x3f]; - break; + ret = ncr_dev->int_ram[addr & 0x3f]; + break; - case 0x3880: + case 0x3880: #if ENABLE_NCR5380_LOG - ncr_log("Read 53c80 %04x\n", addr); + ncr_log("Read 53c80 %04x\n", addr); #endif - ret = ncr_read(addr, ncr_dev); - break; - - case 0x3900: - if (ncr_dev->buffer_host_pos >= MIN(128, dev->buffer_length) || !(ncr_dev->status_ctrl & CTRL_DATA_DIR)) { - ret = 0xff; - } else { - ret = ncr_dev->buffer[ncr_dev->buffer_host_pos++]; + ret = ncr_read(addr, ncr_dev); + break; - if (ncr_dev->buffer_host_pos == MIN(128, dev->buffer_length)) { - ncr_dev->status_ctrl |= STATUS_BUFFER_NOT_READY; - ncr_log("Transfer busy read, status = %02x\n", ncr_dev->status_ctrl); - } - } - break; + case 0x3900: + if (ncr_dev->buffer_host_pos >= MIN(128, dev->buffer_length) || !(ncr_dev->status_ctrl & CTRL_DATA_DIR)) { + ret = 0xff; + } else { + ret = ncr_dev->buffer[ncr_dev->buffer_host_pos++]; - case 0x3980: - switch (addr) { - case 0x3980: /* status */ - ret = ncr_dev->status_ctrl; - ncr_log("NCR status ctrl read=%02x\n", ncr_dev->status_ctrl & STATUS_BUFFER_NOT_READY); - if (!ncr_dev->ncr_busy) - ret |= STATUS_53C80_ACCESSIBLE; - break; + if (ncr_dev->buffer_host_pos == MIN(128, dev->buffer_length)) { + ncr_dev->status_ctrl |= STATUS_BUFFER_NOT_READY; + ncr_log("Transfer busy read, status = %02x\n", ncr_dev->status_ctrl); + } + } + break; - case 0x3981: /* block counter register*/ - ret = ncr_dev->block_count; - break; + case 0x3980: + switch (addr) { + case 0x3980: /* status */ + ret = ncr_dev->status_ctrl; + ncr_log("NCR status ctrl read=%02x\n", ncr_dev->status_ctrl & STATUS_BUFFER_NOT_READY); + if (!ncr_dev->ncr_busy) + ret |= STATUS_53C80_ACCESSIBLE; + if (ncr->mode & 0x30) { /*Parity bits*/ + if (!(ncr->mode & MODE_DMA)) { /*This is to avoid RTBios 8.10R BIOS problems with the hard disk and detection.*/ + ret |= 0x01; /*If the parity bits are set, bit 0 of the 53c400 status port should be set as well.*/ + ncr->mode = 0; /*Required by RTASPI10.SYS otherwise it won't initialize.*/ + } + } + ncr_log("NCR 53c400 status = %02x.\n", ret); + break; - case 0x3982: /* switch register read */ - ret = 0xff; - break; + case 0x3981: /* block counter register*/ + ret = ncr_dev->block_count; + break; - case 0x3983: - ret = 0xff; - break; - } - break; - } + case 0x3982: /* switch register read */ + ret = 0xff; + break; + + case 0x3983: + ret = 0xff; + break; + + default: + break; + } + break; + + default: + break; + } #if ENABLE_NCR5380_LOG if (addr >= 0x3880) - ncr_log("memio_read(%08x)=%02x\n", addr, ret); + ncr_log("memio_read(%08x)=%02x\n", addr, ret); #endif - return(ret); + return ret; } - /* Memory-mapped I/O WRITE handler. */ -static void +static void memio_write(uint32_t addr, uint8_t val, void *priv) { - ncr5380_t *ncr_dev = (ncr5380_t *)priv; - ncr_t *ncr = &ncr_dev->ncr; - scsi_device_t *dev = &scsi_devices[ncr_dev->bus][ncr->target_id]; - + ncr5380_t *ncr_dev = (ncr5380_t *) priv; + ncr_t *ncr = &ncr_dev->ncr; + const scsi_device_t *dev = &scsi_devices[ncr_dev->bus][ncr->target_id]; + addr &= 0x3fff; - ncr_log("memio_write(%08x,%02x) %i %02x\n", addr, val, ncr_dev->buffer_host_pos, ncr_dev->status_ctrl); - if (addr >= 0x3a00) - ncr_dev->ext_ram[addr - 0x3a00] = val; - else switch (addr & 0x3f80) { - case 0x3800: - ncr_dev->int_ram[addr & 0x3f] = val; - break; + ncr_dev->ext_ram[addr - 0x3a00] = val; + else + switch (addr & 0x3f80) { + case 0x3800: + ncr_dev->int_ram[addr & 0x3f] = val; + break; - case 0x3880: - ncr_write(addr, val, ncr_dev); - break; - - case 0x3900: - if (!(ncr_dev->status_ctrl & CTRL_DATA_DIR) && ncr_dev->buffer_host_pos < MIN(128, dev->buffer_length)) { - ncr_dev->buffer[ncr_dev->buffer_host_pos++] = val; + case 0x3880: + ncr_write(addr, val, ncr_dev); + break; - ncr_log("Write host pos = %i, val = %02x\n", ncr_dev->buffer_host_pos, val); + case 0x3900: + if (!(ncr_dev->status_ctrl & CTRL_DATA_DIR) && ncr_dev->buffer_host_pos < MIN(128, dev->buffer_length)) { + ncr_dev->buffer[ncr_dev->buffer_host_pos++] = val; - if (ncr_dev->buffer_host_pos == MIN(128, dev->buffer_length)) { - ncr_dev->status_ctrl |= STATUS_BUFFER_NOT_READY; - ncr_dev->ncr_busy = 1; - } - } - break; + ncr_log("Write host pos = %i, val = %02x\n", ncr_dev->buffer_host_pos, val); - case 0x3980: - switch (addr) { - case 0x3980: /* Control */ - if ((val & CTRL_DATA_DIR) && !(ncr_dev->status_ctrl & CTRL_DATA_DIR)) { - ncr_dev->buffer_host_pos = MIN(128, dev->buffer_length); - ncr_dev->status_ctrl |= STATUS_BUFFER_NOT_READY; - } - else if (!(val & CTRL_DATA_DIR) && (ncr_dev->status_ctrl & CTRL_DATA_DIR)) { - ncr_dev->buffer_host_pos = 0; - ncr_dev->status_ctrl &= ~STATUS_BUFFER_NOT_READY; - } - ncr_dev->status_ctrl = (ncr_dev->status_ctrl & 0x87) | (val & 0x78); - break; + if (ncr_dev->buffer_host_pos == MIN(128, dev->buffer_length)) { + ncr_dev->status_ctrl |= STATUS_BUFFER_NOT_READY; + ncr_dev->ncr_busy = 1; + } + } + break; - case 0x3981: /* block counter register */ - ncr_log("Write block counter register: val=%d, dma mode = %i, period = %lf\n", val, ncr->dma_mode, ncr_dev->period); - ncr_dev->block_count = val; - ncr_dev->block_count_loaded = 1; + case 0x3980: + switch (addr) { + case 0x3980: /* Control */ + ncr_log("NCR 53c400 control = %02x, mode = %02x.\n", val, ncr->mode); + if ((val & CTRL_DATA_DIR) && !(ncr_dev->status_ctrl & CTRL_DATA_DIR)) { + ncr_dev->buffer_host_pos = MIN(128, dev->buffer_length); + ncr_dev->status_ctrl |= STATUS_BUFFER_NOT_READY; + } else if (!(val & CTRL_DATA_DIR) && (ncr_dev->status_ctrl & CTRL_DATA_DIR)) { + ncr_dev->buffer_host_pos = 0; + ncr_dev->status_ctrl &= ~STATUS_BUFFER_NOT_READY; + } + ncr_dev->status_ctrl = (ncr_dev->status_ctrl & 0x87) | (val & 0x78); + break; - if (ncr->mode & MODE_DMA) - ncr_timer_on(ncr_dev, ncr, 0); - - if (ncr_dev->status_ctrl & CTRL_DATA_DIR) { - ncr_dev->buffer_host_pos = MIN(128, dev->buffer_length); - ncr_dev->status_ctrl |= STATUS_BUFFER_NOT_READY; - } else { - ncr_dev->buffer_host_pos = 0; - ncr_dev->status_ctrl &= ~STATUS_BUFFER_NOT_READY; - } - break; - } - break; - } + case 0x3981: /* block counter register */ + ncr_log("Write block counter register: val=%d, dma mode = %i, period = %lf\n", val, ncr->dma_mode, ncr_dev->period); + ncr_dev->block_count = val; + ncr_dev->block_count_loaded = 1; + + if (ncr->mode & MODE_DMA) + ncr_timer_on(ncr_dev, ncr, 0); + + if (ncr_dev->status_ctrl & CTRL_DATA_DIR) { + ncr_dev->buffer_host_pos = MIN(128, dev->buffer_length); + ncr_dev->status_ctrl |= STATUS_BUFFER_NOT_READY; + } else { + ncr_dev->buffer_host_pos = 0; + ncr_dev->status_ctrl &= ~STATUS_BUFFER_NOT_READY; + } + break; + + default: + break; + } + break; + + default: + break; + } } - /* Memory-mapped I/O READ handler for the Trantor T130B. */ -static uint8_t +static uint8_t t130b_read(uint32_t addr, void *priv) { - ncr5380_t *ncr_dev = (ncr5380_t *)priv; - uint8_t ret = 0xff; + const ncr5380_t *ncr_dev = (ncr5380_t *) priv; + uint8_t ret = 0xff; addr &= 0x3fff; if (addr < 0x1800) - ret = ncr_dev->bios_rom.rom[addr & 0x1fff]; + ret = ncr_dev->bios_rom.rom[addr & 0x1fff]; else if (addr >= 0x1800 && addr < 0x1880) - ret = ncr_dev->ext_ram[addr & 0x7f]; + ret = ncr_dev->ext_ram[addr & 0x7f]; ncr_log("MEM: Reading %02X from %08X\n", ret, addr); - return(ret); + return ret; } - /* Memory-mapped I/O WRITE handler for the Trantor T130B. */ -static void +static void t130b_write(uint32_t addr, uint8_t val, void *priv) { - ncr5380_t *ncr_dev = (ncr5380_t *)priv; + ncr5380_t *ncr_dev = (ncr5380_t *) priv; addr &= 0x3fff; ncr_log("MEM: Writing %02X to %08X\n", val, addr); if (addr >= 0x1800 && addr < 0x1880) - ncr_dev->ext_ram[addr & 0x7f] = val; + ncr_dev->ext_ram[addr & 0x7f] = val; } - -static uint8_t +static uint8_t t130b_in(uint16_t port, void *priv) { - ncr5380_t *ncr_dev = (ncr5380_t *)priv; - uint8_t ret = 0xff; + ncr5380_t *ncr_dev = (ncr5380_t *) priv; + uint8_t ret = 0xff; switch (port & 0x0f) { - case 0x00: case 0x01: case 0x02: case 0x03: - ret = memio_read((port & 7) | 0x3980, ncr_dev); - break; + case 0x00: + case 0x01: + case 0x02: + case 0x03: + ret = memio_read((port & 7) | 0x3980, ncr_dev); + break; - case 0x04: case 0x05: - ret = memio_read(0x3900, ncr_dev); - break; - - case 0x08: case 0x09: case 0x0a: case 0x0b: - case 0x0c: case 0x0d: case 0x0e: case 0x0f: - ret = ncr_read(port, ncr_dev); - break; + case 0x04: + case 0x05: + ret = memio_read(0x3900, ncr_dev); + break; + + case 0x08: + case 0x09: + case 0x0a: + case 0x0b: + case 0x0c: + case 0x0d: + case 0x0e: + case 0x0f: + ret = ncr_read(port, ncr_dev); + break; + + default: + break; } ncr_log("I/O: Reading %02X from %04X\n", ret, port); - return(ret); + return ret; } - -static void +static void t130b_out(uint16_t port, uint8_t val, void *priv) { - ncr5380_t *ncr_dev = (ncr5380_t *)priv; + ncr5380_t *ncr_dev = (ncr5380_t *) priv; ncr_log("I/O: Writing %02X to %04X\n", val, port); switch (port & 0x0f) { - case 0x00: case 0x01: case 0x02: case 0x03: - memio_write((port & 7) | 0x3980, val, ncr_dev); - break; + case 0x00: + case 0x01: + case 0x02: + case 0x03: + memio_write((port & 7) | 0x3980, val, ncr_dev); + break; - case 0x04: case 0x05: - memio_write(0x3900, val, ncr_dev); - break; - - case 0x08: case 0x09: case 0x0a: case 0x0b: - case 0x0c: case 0x0d: case 0x0e: case 0x0f: - ncr_write(port, val, ncr_dev); - break; + case 0x04: + case 0x05: + memio_write(0x3900, val, ncr_dev); + break; + + case 0x08: + case 0x09: + case 0x0a: + case 0x0b: + case 0x0c: + case 0x0d: + case 0x0e: + case 0x0f: + ncr_write(port, val, ncr_dev); + break; + + default: + break; } } static void ncr_dma_send(ncr5380_t *ncr_dev, ncr_t *ncr, scsi_device_t *dev) { - int bus, c = 0; + int bus; uint8_t data; - - if (scsi_device_get_callback(dev) > 0.0) - ncr_timer_on(ncr_dev, ncr, 1); - else - ncr_timer_on(ncr_dev, ncr, 0); - for (c = 0; c < 10; c++) { - ncr_bus_read(ncr_dev); - if (ncr->cur_bus & BUS_REQ) - break; + if (scsi_device_get_callback(dev) > 0.0) + ncr_timer_on(ncr_dev, ncr, 1); + else + ncr_timer_on(ncr_dev, ncr, 0); + + for (uint8_t c = 0; c < 10; c++) { + ncr_bus_read(ncr_dev); + if (ncr->cur_bus & BUS_REQ) + break; } /* Data ready. */ - if (ncr_dev->type == 3) { - data = ncr_dev->t128.buffer[ncr_dev->t128.pos]; - } else - data = ncr_dev->buffer[ncr_dev->buffer_pos]; + if (ncr_dev->type == 3) + data = ncr_dev->t128.buffer[ncr_dev->t128.pos]; + else + data = ncr_dev->buffer[ncr_dev->buffer_pos]; bus = get_bus_host(ncr) & ~BUS_DATAMASK; bus |= BUS_SETDATA(data); ncr_bus_update(ncr_dev, bus | BUS_ACK); ncr_bus_update(ncr_dev, bus & ~BUS_ACK); - if (ncr_dev->type == 3) { - ncr_dev->t128.pos++; - ncr_log("Buffer pos for writing = %d, data = %02x\n", ncr_dev->t128.pos, data); + if (ncr_dev->type == 3) { + ncr_dev->t128.pos++; + ncr_log("Buffer pos for writing = %d, data = %02x\n", ncr_dev->t128.pos, data); - if (ncr_dev->t128.pos == MIN(512, dev->buffer_length)) { - ncr_dev->t128.pos = 0; - ncr_dev->t128.host_pos = 0; - ncr_dev->t128.status &= ~0x02; - ncr_dev->t128.block_count = (ncr_dev->t128.block_count - 1) & 0xff; - ncr_log("Remaining blocks to be written=%d\n", ncr_dev->t128.block_count); - if (!ncr_dev->t128.block_count) { - ncr_dev->t128.block_loaded = 0; - ncr_log("IO End of write transfer\n"); - ncr->tcr |= TCR_LAST_BYTE_SENT; - ncr->isr |= STATUS_END_OF_DMA; - timer_stop(&ncr_dev->timer); - if (ncr->mode & MODE_ENA_EOP_INT) { - ncr_log("NCR write irq\n"); - ncr_irq(ncr_dev, ncr, 1); - } - } - return; - } - } else { - ncr_dev->buffer_pos++; - ncr_log("Buffer pos for writing = %d\n", ncr_dev->buffer_pos); + if (ncr_dev->t128.pos == MIN(512, dev->buffer_length)) { + ncr_dev->t128.pos = 0; + ncr_dev->t128.host_pos = 0; + ncr_dev->t128.status &= ~0x02; + ncr_dev->t128.block_count = (ncr_dev->t128.block_count - 1) & 0xff; + ncr_log("Remaining blocks to be written=%d\n", ncr_dev->t128.block_count); + if (!ncr_dev->t128.block_count) { + ncr_dev->t128.block_loaded = 0; + ncr_log("IO End of write transfer\n"); + ncr->tcr |= TCR_LAST_BYTE_SENT; + ncr->isr |= STATUS_END_OF_DMA; + timer_stop(&ncr_dev->timer); + if (ncr->mode & MODE_ENA_EOP_INT) { + ncr_log("NCR write irq\n"); + ncr_irq(ncr_dev, ncr, 1); + } + } + return; + } + } else { + ncr_dev->buffer_pos++; + ncr_log("Buffer pos for writing = %d\n", ncr_dev->buffer_pos); - if (ncr_dev->buffer_pos == MIN(128, dev->buffer_length)) { - ncr_dev->buffer_pos = 0; - ncr_dev->buffer_host_pos = 0; - ncr_dev->status_ctrl &= ~STATUS_BUFFER_NOT_READY; - ncr_dev->ncr_busy = 0; - ncr_dev->block_count = (ncr_dev->block_count - 1) & 0xff; - ncr_log("Remaining blocks to be written=%d\n", ncr_dev->block_count); - if (!ncr_dev->block_count) { - ncr_dev->block_count_loaded = 0; - ncr_log("IO End of write transfer\n"); - ncr->tcr |= TCR_LAST_BYTE_SENT; - ncr->isr |= STATUS_END_OF_DMA; - timer_stop(&ncr_dev->timer); - if (ncr->mode & MODE_ENA_EOP_INT) { - ncr_log("NCR write irq\n"); - ncr_irq(ncr_dev, ncr, 1); - } - } - return; - } - } + if (ncr_dev->buffer_pos == MIN(128, dev->buffer_length)) { + ncr_dev->buffer_pos = 0; + ncr_dev->buffer_host_pos = 0; + ncr_dev->status_ctrl &= ~STATUS_BUFFER_NOT_READY; + ncr_dev->ncr_busy = 0; + ncr_dev->block_count = (ncr_dev->block_count - 1) & 0xff; + ncr_log("Remaining blocks to be written=%d\n", ncr_dev->block_count); + if (!ncr_dev->block_count) { + ncr_dev->block_count_loaded = 0; + ncr_log("IO End of write transfer\n"); + ncr->tcr |= TCR_LAST_BYTE_SENT; + ncr->isr |= STATUS_END_OF_DMA; + timer_stop(&ncr_dev->timer); + if (ncr->mode & MODE_ENA_EOP_INT) { + ncr_log("NCR write irq\n"); + ncr_irq(ncr_dev, ncr, 1); + } + } + return; + } + } ncr_dma_send(ncr_dev, ncr, dev); } static void ncr_dma_initiator_receive(ncr5380_t *ncr_dev, ncr_t *ncr, scsi_device_t *dev) { - int bus, c = 0; + int bus; uint8_t temp; - if (scsi_device_get_callback(dev) > 0.0) { - ncr_timer_on(ncr_dev, ncr, 1); - } else { - ncr_timer_on(ncr_dev, ncr, 0); - } - - for (c = 0; c < 10; c++) { - ncr_bus_read(ncr_dev); - if (ncr->cur_bus & BUS_REQ) - break; + if (scsi_device_get_callback(dev) > 0.0) { + ncr_timer_on(ncr_dev, ncr, 1); + } else { + ncr_timer_on(ncr_dev, ncr, 0); + } + + for (uint8_t c = 0; c < 10; c++) { + ncr_bus_read(ncr_dev); + if (ncr->cur_bus & BUS_REQ) + break; } /* Data ready. */ @@ -1162,273 +1222,314 @@ ncr_dma_initiator_receive(ncr5380_t *ncr_dev, ncr_t *ncr, scsi_device_t *dev) ncr_bus_update(ncr_dev, bus | BUS_ACK); ncr_bus_update(ncr_dev, bus & ~BUS_ACK); - - if (ncr_dev->type == 3) { - ncr_dev->t128.buffer[ncr_dev->t128.pos++] = temp; - ncr_log("Buffer pos for reading = %d, temp = %02x\n", ncr_dev->t128.pos, temp); - if (ncr_dev->t128.pos == MIN(512, dev->buffer_length)) { - ncr_dev->t128.pos = 0; - ncr_dev->t128.host_pos = 0; - ncr_dev->t128.status &= ~0x02; - ncr_dev->t128.block_count = (ncr_dev->t128.block_count - 1) & 0xff; - ncr_log("Remaining blocks to be read=%d, status=%02x, len=%i, cdb[0] = %02x\n", ncr_dev->t128.block_count, ncr_dev->t128.status, dev->buffer_length, ncr->command[0]); - if (!ncr_dev->t128.block_count) { - ncr_dev->t128.block_loaded = 0; - ncr_log("IO End of read transfer\n"); - ncr->isr |= STATUS_END_OF_DMA; - timer_stop(&ncr_dev->timer); - if (ncr->mode & MODE_ENA_EOP_INT) { - ncr_log("NCR read irq\n"); - ncr_irq(ncr_dev, ncr, 1); - } - } - return; - } - } else { - ncr_dev->buffer[ncr_dev->buffer_pos++] = temp; - ncr_log("Buffer pos for reading = %d\n", ncr_dev->buffer_pos); - - if (ncr_dev->buffer_pos == MIN(128, dev->buffer_length)) { - ncr_dev->buffer_pos = 0; - ncr_dev->buffer_host_pos = 0; - ncr_dev->status_ctrl &= ~STATUS_BUFFER_NOT_READY; - ncr_dev->block_count = (ncr_dev->block_count - 1) & 0xff; - ncr_log("Remaining blocks to be read=%d\n", ncr_dev->block_count); - if (!ncr_dev->block_count) { - ncr_dev->block_count_loaded = 0; - ncr_log("IO End of read transfer\n"); - ncr->isr |= STATUS_END_OF_DMA; - timer_stop(&ncr_dev->timer); - if (ncr->mode & MODE_ENA_EOP_INT) { - ncr_log("NCR read irq\n"); - ncr_irq(ncr_dev, ncr, 1); - } - } - return; - } - } + if (ncr_dev->type == 3) { + ncr_dev->t128.buffer[ncr_dev->t128.pos++] = temp; + ncr_log("Buffer pos for reading = %d, temp = %02x\n", ncr_dev->t128.pos, temp); + + if (ncr_dev->t128.pos == MIN(512, dev->buffer_length)) { + ncr_dev->t128.pos = 0; + ncr_dev->t128.host_pos = 0; + ncr_dev->t128.status &= ~0x02; + ncr_dev->t128.block_count = (ncr_dev->t128.block_count - 1) & 0xff; + ncr_log("Remaining blocks to be read=%d, status=%02x, len=%i, cdb[0] = %02x\n", ncr_dev->t128.block_count, ncr_dev->t128.status, dev->buffer_length, ncr->command[0]); + if (!ncr_dev->t128.block_count) { + ncr_dev->t128.block_loaded = 0; + ncr_log("IO End of read transfer\n"); + ncr->isr |= STATUS_END_OF_DMA; + timer_stop(&ncr_dev->timer); + if (ncr->mode & MODE_ENA_EOP_INT) { + ncr_log("NCR read irq\n"); + ncr_irq(ncr_dev, ncr, 1); + } + } + return; + } + } else { + ncr_dev->buffer[ncr_dev->buffer_pos++] = temp; + ncr_log("Buffer pos for reading = %d\n", ncr_dev->buffer_pos); + + if (ncr_dev->buffer_pos == MIN(128, dev->buffer_length)) { + ncr_dev->buffer_pos = 0; + ncr_dev->buffer_host_pos = 0; + ncr_dev->status_ctrl &= ~STATUS_BUFFER_NOT_READY; + ncr_dev->block_count = (ncr_dev->block_count - 1) & 0xff; + ncr_log("Remaining blocks to be read=%d\n", ncr_dev->block_count); + if (!ncr_dev->block_count) { + ncr_dev->block_count_loaded = 0; + ncr_log("IO End of read transfer\n"); + ncr->isr |= STATUS_END_OF_DMA; + timer_stop(&ncr_dev->timer); + if (ncr->mode & MODE_ENA_EOP_INT) { + ncr_log("NCR read irq\n"); + ncr_irq(ncr_dev, ncr, 1); + } + } + return; + } + } ncr_dma_initiator_receive(ncr_dev, ncr, dev); } static void ncr_callback(void *priv) { - ncr5380_t *ncr_dev = (ncr5380_t *)priv; - ncr_t *ncr = &ncr_dev->ncr; - scsi_device_t *dev = &scsi_devices[ncr_dev->bus][ncr->target_id]; + ncr5380_t *ncr_dev = (ncr5380_t *) priv; + ncr_t *ncr = &ncr_dev->ncr; + scsi_device_t *dev = &scsi_devices[ncr_dev->bus][ncr->target_id]; - if (ncr_dev->type == 3) { - ncr_log("DMA Callback, load = %i\n", ncr_dev->t128.block_loaded); - if (ncr->dma_mode != DMA_IDLE && (ncr->mode & MODE_DMA) && ncr_dev->t128.block_loaded) { - ncr_log("Timer on! Host POS = %i, status = %02x, DMA mode = %i, Period = %lf\n", ncr_dev->t128.host_pos, ncr_dev->t128.status, ncr->dma_mode, scsi_device_get_callback(dev)); - if (ncr_dev->t128.host_pos == MIN(512, dev->buffer_length) && ncr_dev->t128.block_count) { - ncr_dev->t128.status |= 0x04; - } - ncr_timer_on(ncr_dev, ncr, 0); - } - } else { - ncr_log("DMA mode=%d, status ctrl = %02x\n", ncr->dma_mode, ncr_dev->status_ctrl); - if (ncr->dma_mode != DMA_IDLE && (ncr->mode & MODE_DMA) && ncr_dev->block_count_loaded) { - ncr_timer_on(ncr_dev, ncr, 0); - } - } - - if (ncr->data_wait & 1) { - ncr->clear_req = 3; - ncr->data_wait &= ~1; - if (ncr->dma_mode == DMA_IDLE) { - return; - } + if (ncr_dev->type == 3) { + ncr_log("DMA Callback, load = %i\n", ncr_dev->t128.block_loaded); + if (ncr->dma_mode != DMA_IDLE && (ncr->mode & MODE_DMA) && ncr_dev->t128.block_loaded) { + ncr_log("Timer on! Host POS = %i, status = %02x, DMA mode = %i, Period = %lf\n", ncr_dev->t128.host_pos, ncr_dev->t128.status, ncr->dma_mode, scsi_device_get_callback(dev)); + if (ncr_dev->t128.host_pos == MIN(512, dev->buffer_length) && ncr_dev->t128.block_count) { + ncr_dev->t128.status |= 0x04; + } + ncr_timer_on(ncr_dev, ncr, 0); + } + } else { + ncr_log("DMA mode=%d, status ctrl = %02x\n", ncr->dma_mode, ncr_dev->status_ctrl); + if (ncr->dma_mode != DMA_IDLE && (ncr->mode & MODE_DMA) && ncr_dev->block_count_loaded) { + ncr_timer_on(ncr_dev, ncr, 0); + } } - switch(ncr->dma_mode) { - case DMA_SEND: - if (ncr_dev->type != 3) { - if (ncr_dev->status_ctrl & CTRL_DATA_DIR) { - ncr_log("DMA_SEND with DMA direction set wrong\n"); - break; - } - - if (!(ncr_dev->status_ctrl & STATUS_BUFFER_NOT_READY)) { - ncr_log("Write buffer status ready\n"); - break; - } + if (ncr->data_wait & 1) { + ncr->clear_req = 3; + ncr->data_wait &= ~1; + if (ncr->dma_mode == DMA_IDLE) { + return; + } + } - if (!ncr_dev->block_count_loaded) - break; - } else { - if (!(ncr_dev->t128.status & 0x04)) { - ncr_log("Write status busy\n"); - break; - } - - if (!ncr_dev->t128.block_loaded) { - ncr_log("Write block not loaded\n"); - break; - } + switch (ncr->dma_mode) { + case DMA_SEND: + if (ncr_dev->type != 3) { + if (ncr_dev->status_ctrl & CTRL_DATA_DIR) { + ncr_log("DMA_SEND with DMA direction set wrong\n"); + break; + } - if (ncr_dev->t128.host_pos < MIN(512, dev->buffer_length)) - break; - } - ncr_dma_send(ncr_dev, ncr, dev); - break; + if (!(ncr_dev->status_ctrl & STATUS_BUFFER_NOT_READY)) { + ncr_log("Write buffer status ready\n"); + break; + } - case DMA_INITIATOR_RECEIVE: - if (ncr_dev->type != 3) { - if (!(ncr_dev->status_ctrl & CTRL_DATA_DIR)) { - ncr_log("DMA_INITIATOR_RECEIVE with DMA direction set wrong\n"); - break; - } + if (!ncr_dev->block_count_loaded) + break; + } else { + if (!(ncr_dev->t128.status & 0x04)) { + ncr_log("Write status busy\n"); + break; + } - if (!(ncr_dev->status_ctrl & STATUS_BUFFER_NOT_READY)) { - ncr_log("Read buffer status ready\n"); - break; - } + if (!ncr_dev->t128.block_loaded) { + ncr_log("Write block not loaded\n"); + break; + } - if (!ncr_dev->block_count_loaded) - break; - } else { - if (!(ncr_dev->t128.status & 0x04)) { - ncr_log("Read status busy, block count = %i, host pos = %i\n", ncr_dev->t128.block_count, ncr_dev->t128.host_pos); - break; - } - - if (!ncr_dev->t128.block_loaded) { - ncr_log("Read block not loaded\n"); - break; - } - - if (ncr_dev->t128.host_pos < MIN(512, dev->buffer_length)) - break; - } - ncr_dma_initiator_receive(ncr_dev, ncr, dev); - break; + if (ncr_dev->t128.host_pos < MIN(512, dev->buffer_length)) + break; + } + ncr_dma_send(ncr_dev, ncr, dev); + break; + + case DMA_INITIATOR_RECEIVE: + if (ncr_dev->type != 3) { + if (!(ncr_dev->status_ctrl & CTRL_DATA_DIR)) { + ncr_log("DMA_INITIATOR_RECEIVE with DMA direction set wrong\n"); + break; + } + + if (!(ncr_dev->status_ctrl & STATUS_BUFFER_NOT_READY)) { + ncr_log("Read buffer status ready\n"); + break; + } + + if (!ncr_dev->block_count_loaded) + break; + } else { + if (!(ncr_dev->t128.status & 0x04)) { + ncr_log("Read status busy, block count = %i, host pos = %i\n", ncr_dev->t128.block_count, ncr_dev->t128.host_pos); + break; + } + + if (!ncr_dev->t128.block_loaded) { + ncr_log("Read block not loaded\n"); + break; + } + + if (ncr_dev->t128.host_pos < MIN(512, dev->buffer_length)) + break; + } + ncr_dma_initiator_receive(ncr_dev, ncr, dev); + break; + + default: + break; } ncr_bus_read(ncr_dev); if (!(ncr->cur_bus & BUS_BSY) && (ncr->mode & MODE_MONITOR_BUSY)) { - ncr_log("Updating DMA\n"); - ncr->mode &= ~MODE_DMA; - ncr->dma_mode = DMA_IDLE; - timer_on_auto(&ncr_dev->timer, 10.0); + ncr_log("Updating DMA\n"); + ncr->mode &= ~MODE_DMA; + ncr->dma_mode = DMA_IDLE; + timer_on_auto(&ncr_dev->timer, 10.0); } } -static uint8_t +static uint8_t t128_read(uint32_t addr, void *priv) { - ncr5380_t *ncr_dev = (ncr5380_t *)priv; - ncr_t *ncr = &ncr_dev->ncr; - scsi_device_t *dev = &scsi_devices[ncr_dev->bus][ncr->target_id]; - uint8_t ret = 0xff; + ncr5380_t *ncr_dev = (ncr5380_t *) priv; + const ncr_t *ncr = &ncr_dev->ncr; + scsi_device_t *dev = &scsi_devices[ncr_dev->bus][ncr->target_id]; + uint8_t ret = 0xff; addr &= 0x3fff; - if (addr >= 0 && addr < 0x1800) - ret = ncr_dev->bios_rom.rom[addr & 0x1fff]; - else if (addr >= 0x1800 && addr < 0x1880) - ret = ncr_dev->t128.ext_ram[addr & 0x7f]; - else if (addr >= 0x1c00 && addr < 0x1c20) { - ret = ncr_dev->t128.ctrl; - } else if (addr >= 0x1c20 && addr < 0x1c40) { - ret = ncr_dev->t128.status; - ncr_log("T128 status read = %02x, cur bus = %02x, req = %02x, dma = %02x\n", ret, ncr->cur_bus, ncr->cur_bus & BUS_REQ, ncr->mode & MODE_DMA); - } else if (addr >= 0x1d00 && addr < 0x1e00) { - if (addr >= 0x1d00 && addr < 0x1d20) - ret = ncr_read(0, ncr_dev); - else if (addr >= 0x1d20 && addr < 0x1d40) - ret = ncr_read(1, ncr_dev); - else if (addr >= 0x1d40 && addr < 0x1d60) - ret = ncr_read(2, ncr_dev); - else if (addr >= 0x1d60 && addr < 0x1d80) - ret = ncr_read(3, ncr_dev); - else if (addr >= 0x1d80 && addr < 0x1da0) - ret = ncr_read(4, ncr_dev); - else if (addr >= 0x1da0 && addr < 0x1dc0) - ret = ncr_read(5, ncr_dev); - else if (addr >= 0x1dc0 && addr < 0x1de0) - ret = ncr_read(6, ncr_dev); - else if (addr >= 0x1de0 && addr < 0x1e00) - ret = ncr_read(7, ncr_dev); - } else if (addr >= 0x1e00 && addr < 0x2000) { - if (ncr_dev->t128.host_pos >= MIN(512, dev->buffer_length) || ncr->dma_mode != DMA_INITIATOR_RECEIVE) { - ret = 0xff; - } else { - ret = ncr_dev->t128.buffer[ncr_dev->t128.host_pos++]; + if (ncr_dev->t128.bios_enabled && (addr >= 0) && (addr < 0x1800)) + ret = ncr_dev->bios_rom.rom[addr & 0x1fff]; + else if ((addr >= 0x1800) && (addr < 0x1880)) + ret = ncr_dev->t128.ext_ram[addr & 0x7f]; + else if ((addr >= 0x1c00) && (addr < 0x1c20)) + ret = ncr_dev->t128.ctrl; + else if ((addr >= 0x1c20) && (addr < 0x1c40)) { + ret = ncr_dev->t128.status; + ncr_log("T128 status read = %02x, cur bus = %02x, req = %02x, dma = %02x\n", + ret, ncr->cur_bus, ncr->cur_bus & BUS_REQ, ncr->mode & MODE_DMA); + } else if ((addr >= 0x1d00) && (addr < 0x1e00)) + ret = ncr_read((addr - 0x1d00) >> 5, ncr_dev); + else if (addr >= 0x1e00 && addr < 0x2000) { + if ((ncr_dev->t128.host_pos >= MIN(512, dev->buffer_length)) || + (ncr->dma_mode != DMA_INITIATOR_RECEIVE)) + ret = 0xff; + else { + ret = ncr_dev->t128.buffer[ncr_dev->t128.host_pos++]; - ncr_log("Read transfer, addr = %i, pos = %i\n", addr & 0x1ff, ncr_dev->t128.host_pos); - - if (ncr_dev->t128.host_pos == MIN(512, dev->buffer_length)) { - ncr_dev->t128.status &= ~0x04; - ncr_log("Transfer busy read, status = %02x, period = %lf\n", ncr_dev->t128.status, ncr_dev->period); - if (ncr_dev->period == 0.2 || ncr_dev->period == 0.02) - timer_on_auto(&ncr_dev->timer, 40.2); - } else if (ncr_dev->t128.host_pos < MIN(512, dev->buffer_length) && scsi_device_get_callback(dev) > 100.0) - cycles += 100; /*Needed to avoid timer de-syncing with transfers.*/ - } - } - - return(ret); + ncr_log("Read transfer, addr = %i, pos = %i\n", addr & 0x1ff, + ncr_dev->t128.host_pos); + + if (ncr_dev->t128.host_pos == MIN(512, dev->buffer_length)) { + ncr_dev->t128.status &= ~0x04; + ncr_log("Transfer busy read, status = %02x, period = %lf\n", + ncr_dev->t128.status, ncr_dev->period); + if (ncr_dev->period == 0.2 || ncr_dev->period == 0.02) + timer_on_auto(&ncr_dev->timer, 40.2); + } else if ((ncr_dev->t128.host_pos < MIN(512, dev->buffer_length)) && + (scsi_device_get_callback(dev) > 100.0)) + cycles += 100; /*Needed to avoid timer de-syncing with transfers.*/ + } + } + + return ret; } -static void +static void t128_write(uint32_t addr, uint8_t val, void *priv) { - ncr5380_t *ncr_dev = (ncr5380_t *)priv; - ncr_t *ncr = &ncr_dev->ncr; - scsi_device_t *dev = &scsi_devices[ncr_dev->bus][ncr->target_id]; - + ncr5380_t *ncr_dev = (ncr5380_t *) priv; + const ncr_t *ncr = &ncr_dev->ncr; + const scsi_device_t *dev = &scsi_devices[ncr_dev->bus][ncr->target_id]; + addr &= 0x3fff; - if (addr >= 0x1800 && addr < 0x1880) - ncr_dev->t128.ext_ram[addr & 0x7f] = val; - else if (addr >= 0x1c00 && addr < 0x1c20) { - if ((val & 0x02) && !(ncr_dev->t128.ctrl & 0x02)) { - ncr_dev->t128.status |= 0x02; - ncr_log("Timer fired\n"); - } - ncr_dev->t128.ctrl = val; - ncr_log("T128 ctrl write = %02x\n", val); - } else if (addr >= 0x1d00 && addr < 0x1e00) { - if (addr >= 0x1d00 && addr < 0x1d20) - ncr_write(0, val, ncr_dev); - else if (addr >= 0x1d20 && addr < 0x1d40) - ncr_write(1, val, ncr_dev); - else if (addr >= 0x1d40 && addr < 0x1d60) - ncr_write(2, val, ncr_dev); - else if (addr >= 0x1d60 && addr < 0x1d80) - ncr_write(3, val, ncr_dev); - else if (addr >= 0x1d80 && addr < 0x1da0) - ncr_write(4, val, ncr_dev); - else if (addr >= 0x1da0 && addr < 0x1dc0) - ncr_write(5, val, ncr_dev); - else if (addr >= 0x1dc0 && addr < 0x1de0) - ncr_write(6, val, ncr_dev); - else if (addr >= 0x1de0 && addr < 0x1e00) - ncr_write(7, val, ncr_dev); - } else if (addr >= 0x1e00 && addr < 0x2000) { - if (ncr_dev->t128.host_pos < MIN(512, dev->buffer_length) && ncr->dma_mode == DMA_SEND) { - ncr_dev->t128.buffer[ncr_dev->t128.host_pos] = val; - ncr_dev->t128.host_pos++; + if ((addr >= 0x1800) && (addr < 0x1880)) + ncr_dev->t128.ext_ram[addr & 0x7f] = val; + else if ((addr >= 0x1c00) && (addr < 0x1c20)) { + if ((val & 0x02) && !(ncr_dev->t128.ctrl & 0x02)) { + ncr_dev->t128.status |= 0x02; + ncr_log("Timer fired\n"); + } + ncr_dev->t128.ctrl = val; + ncr_log("T128 ctrl write = %02x\n", val); + } else if ((addr >= 0x1d00) && (addr < 0x1e00)) + ncr_write((addr - 0x1d00) >> 5, val, ncr_dev); + else if ((addr >= 0x1e00) && (addr < 0x2000)) { + if ((ncr_dev->t128.host_pos < MIN(512, dev->buffer_length)) && + (ncr->dma_mode == DMA_SEND)) { + ncr_dev->t128.buffer[ncr_dev->t128.host_pos] = val; + ncr_dev->t128.host_pos++; - ncr_log("Write transfer, addr = %i, pos = %i, val = %02x\n", addr & 0x1ff, ncr_dev->t128.host_pos, val); + ncr_log("Write transfer, addr = %i, pos = %i, val = %02x\n", + addr & 0x1ff, ncr_dev->t128.host_pos, val); - if (ncr_dev->t128.host_pos == MIN(512, dev->buffer_length)) { - ncr_dev->t128.status &= ~0x04; - ncr_log("Transfer busy write, status = %02x\n", ncr_dev->t128.status); - timer_on_auto(&ncr_dev->timer, 0.02); - } - } else - ncr_log("Write PDMA addr = %i, val = %02x\n", addr & 0x1ff, val); - } + if (ncr_dev->t128.host_pos == MIN(512, dev->buffer_length)) { + ncr_dev->t128.status &= ~0x04; + ncr_log("Transfer busy write, status = %02x\n", ncr_dev->t128.status); + timer_on_auto(&ncr_dev->timer, 0.02); + } + } else + ncr_log("Write PDMA addr = %i, val = %02x\n", addr & 0x1ff, val); + } +} + +static uint8_t +rt1000b_mc_read(int port, void *priv) +{ + const ncr5380_t *ncr_dev = (ncr5380_t *) priv; + + return (ncr_dev->pos_regs[port & 7]); +} + +static void +rt1000b_mc_write(int port, uint8_t val, void *priv) +{ + ncr5380_t *ncr_dev = (ncr5380_t *) priv; + + /* MCA does not write registers below 0x0100. */ + if (port < 0x0102) + return; + + mem_mapping_disable(&ncr_dev->bios_rom.mapping); + mem_mapping_disable(&ncr_dev->mapping); + + /* Save the MCA register value. */ + ncr_dev->pos_regs[port & 7] = val; + + if (ncr_dev->pos_regs[2] & 1) { + switch (ncr_dev->pos_regs[2] & 0xe0) { + case 0: + ncr_dev->rom_addr = 0xd4000; + break; + case 0x20: + ncr_dev->rom_addr = 0xd0000; + break; + case 0x40: + ncr_dev->rom_addr = 0xcc000; + break; + case 0x60: + ncr_dev->rom_addr = 0xc8000; + break; + case 0xc0: + ncr_dev->rom_addr = 0xdc000; + break; + case 0xe0: + ncr_dev->rom_addr = 0xd8000; + break; + + default: + break; + } + + mem_mapping_set_addr(&ncr_dev->bios_rom.mapping, ncr_dev->rom_addr, 0x4000); + mem_mapping_set_addr(&ncr_dev->mapping, ncr_dev->rom_addr, 0x4000); + } +} + +static uint8_t +rt1000b_mc_feedb(void *priv) +{ + const ncr5380_t *ncr_dev = (ncr5380_t *) priv; + + return ncr_dev->pos_regs[2] & 1; } static void * ncr_init(const device_t *info) { - char *fn = NULL; - char temp[128]; - ncr5380_t *ncr_dev; + const char *fn = NULL; + char temp[128]; + ncr5380_t *ncr_dev; ncr_dev = malloc(sizeof(ncr5380_t)); memset(ncr_dev, 0x00, sizeof(ncr5380_t)); @@ -1437,396 +1538,466 @@ ncr_init(const device_t *info) ncr_dev->bus = scsi_get_bus(); - switch(ncr_dev->type) { - case 0: /* Longshine LCS6821N */ - ncr_dev->rom_addr = device_get_config_hex20("bios_addr"); - ncr_dev->irq = device_get_config_int("irq"); - rom_init(&ncr_dev->bios_rom, LCS6821N_ROM, - ncr_dev->rom_addr, 0x4000, 0x3fff, 0, MEM_MAPPING_EXTERNAL); + switch (ncr_dev->type) { + case 0: /* Longshine LCS6821N */ + ncr_dev->rom_addr = device_get_config_hex20("bios_addr"); + ncr_dev->irq = device_get_config_int("irq"); + rom_init(&ncr_dev->bios_rom, LCS6821N_ROM, + ncr_dev->rom_addr, 0x4000, 0x3fff, 0, MEM_MAPPING_EXTERNAL); - mem_mapping_add(&ncr_dev->mapping, ncr_dev->rom_addr, 0x4000, - memio_read, NULL, NULL, - memio_write, NULL, NULL, - ncr_dev->bios_rom.rom, MEM_MAPPING_EXTERNAL, ncr_dev); - break; + mem_mapping_add(&ncr_dev->mapping, ncr_dev->rom_addr, 0x4000, + memio_read, NULL, NULL, + memio_write, NULL, NULL, + ncr_dev->bios_rom.rom, MEM_MAPPING_EXTERNAL, ncr_dev); + break; - case 1: /* Rancho RT1000B */ - ncr_dev->rom_addr = device_get_config_hex20("bios_addr"); - ncr_dev->irq = device_get_config_int("irq"); - ncr_dev->bios_ver = device_get_config_int("bios_ver"); - - if (ncr_dev->bios_ver == 1) - fn = RT1000B_820R_ROM; - else - fn = RT1000B_810R_ROM; - - rom_init(&ncr_dev->bios_rom, fn, - ncr_dev->rom_addr, 0x4000, 0x3fff, 0, MEM_MAPPING_EXTERNAL); + case 1: /* Rancho RT1000B/MC */ + ncr_dev->rom_addr = device_get_config_hex20("bios_addr"); + ncr_dev->irq = device_get_config_int("irq"); + ncr_dev->bios_ver = device_get_config_int("bios_ver"); + if (info->flags & DEVICE_MCA) { + ncr_dev->rom_addr = 0xd8000; + ncr_dev->bios_ver = 1; + } - mem_mapping_add(&ncr_dev->mapping, ncr_dev->rom_addr, 0x4000, - memio_read, NULL, NULL, - memio_write, NULL, NULL, - ncr_dev->bios_rom.rom, MEM_MAPPING_EXTERNAL, ncr_dev); - break; + switch (ncr_dev->bios_ver) { + case 0: + fn = RT1000B_810R_ROM; + break; + case 1: + fn = RT1000B_820R_ROM; + break; + } - case 2: /* Trantor T130B */ - ncr_dev->rom_addr = device_get_config_hex20("bios_addr"); - ncr_dev->base = device_get_config_hex16("base"); - ncr_dev->irq = device_get_config_int("irq"); + rom_init(&ncr_dev->bios_rom, fn, + ncr_dev->rom_addr, 0x4000, 0x3fff, 0, MEM_MAPPING_EXTERNAL); - if (ncr_dev->rom_addr > 0x00000) { - rom_init(&ncr_dev->bios_rom, T130B_ROM, - ncr_dev->rom_addr, 0x4000, 0x3fff, 0, MEM_MAPPING_EXTERNAL); + if (info->flags & DEVICE_MCA) { + mem_mapping_add(&ncr_dev->mapping, 0, 0, + memio_read, NULL, NULL, + memio_write, NULL, NULL, + ncr_dev->bios_rom.rom, MEM_MAPPING_EXTERNAL, ncr_dev); + ncr_dev->pos_regs[0] = 0x8d; + ncr_dev->pos_regs[1] = 0x70; + mca_add(rt1000b_mc_read, rt1000b_mc_write, rt1000b_mc_feedb, NULL, ncr_dev); + } else { + mem_mapping_add(&ncr_dev->mapping, ncr_dev->rom_addr, 0x4000, + memio_read, NULL, NULL, + memio_write, NULL, NULL, + ncr_dev->bios_rom.rom, MEM_MAPPING_EXTERNAL, ncr_dev); + } + break; - mem_mapping_add(&ncr_dev->mapping, ncr_dev->rom_addr, 0x4000, - t130b_read, NULL, NULL, - t130b_write, NULL, NULL, - ncr_dev->bios_rom.rom, MEM_MAPPING_EXTERNAL, ncr_dev); - } + case 2: /* Trantor T130B */ + ncr_dev->rom_addr = device_get_config_hex20("bios_addr"); + ncr_dev->base = device_get_config_hex16("base"); + ncr_dev->irq = device_get_config_int("irq"); - io_sethandler(ncr_dev->base, 16, - t130b_in,NULL,NULL, t130b_out,NULL,NULL, ncr_dev); - break; + if (ncr_dev->rom_addr > 0x00000) { + rom_init(&ncr_dev->bios_rom, T130B_ROM, + ncr_dev->rom_addr, 0x4000, 0x3fff, 0, MEM_MAPPING_EXTERNAL); - case 3: /* Trantor T128 */ - ncr_dev->rom_addr = device_get_config_hex20("bios_addr"); - ncr_dev->irq = device_get_config_int("irq"); - ncr_dev->t128.bios_enabled = device_get_config_int("boot"); - - if (ncr_dev->t128.bios_enabled) - rom_init(&ncr_dev->bios_rom, T128_ROM, - ncr_dev->rom_addr, 0x4000, 0x3fff, 0, MEM_MAPPING_EXTERNAL); + mem_mapping_add(&ncr_dev->mapping, ncr_dev->rom_addr, 0x4000, + t130b_read, NULL, NULL, + t130b_write, NULL, NULL, + ncr_dev->bios_rom.rom, MEM_MAPPING_EXTERNAL, ncr_dev); + } - mem_mapping_add(&ncr_dev->mapping, ncr_dev->rom_addr, 0x4000, - t128_read, NULL, NULL, - t128_write, NULL, NULL, - ncr_dev->bios_rom.rom, MEM_MAPPING_EXTERNAL, ncr_dev); - break; + io_sethandler(ncr_dev->base, 16, + t130b_in, NULL, NULL, t130b_out, NULL, NULL, ncr_dev); + break; + + case 3: /* Trantor T128 */ + ncr_dev->rom_addr = device_get_config_hex20("bios_addr"); + ncr_dev->irq = device_get_config_int("irq"); + ncr_dev->t128.bios_enabled = device_get_config_int("boot"); + + if (ncr_dev->t128.bios_enabled) + rom_init(&ncr_dev->bios_rom, T128_ROM, + ncr_dev->rom_addr, 0x4000, 0x3fff, 0, MEM_MAPPING_EXTERNAL); + + mem_mapping_add(&ncr_dev->mapping, ncr_dev->rom_addr, 0x4000, + t128_read, NULL, NULL, + t128_write, NULL, NULL, + ncr_dev->bios_rom.rom, MEM_MAPPING_EXTERNAL, ncr_dev); + break; + + case 4: /* Corel LS2000 */ + ncr_dev->rom_addr = device_get_config_hex20("bios_addr"); + ncr_dev->irq = device_get_config_int("irq"); + rom_init(&ncr_dev->bios_rom, COREL_LS2000_ROM, + ncr_dev->rom_addr, 0x4000, 0x3fff, 0, MEM_MAPPING_EXTERNAL); + + mem_mapping_add(&ncr_dev->mapping, ncr_dev->rom_addr, 0x4000, + memio_read, NULL, NULL, + memio_write, NULL, NULL, + ncr_dev->bios_rom.rom, MEM_MAPPING_EXTERNAL, ncr_dev); + break; + + default: + break; } sprintf(temp, "%s: BIOS=%05X", ncr_dev->name, ncr_dev->rom_addr); if (ncr_dev->base != 0) - sprintf(&temp[strlen(temp)], " I/O=%04x", ncr_dev->base); + sprintf(&temp[strlen(temp)], " I/O=%04x", ncr_dev->base); if (ncr_dev->irq != 0) - sprintf(&temp[strlen(temp)], " IRQ=%d", ncr_dev->irq); + sprintf(&temp[strlen(temp)], " IRQ=%d", ncr_dev->irq); ncr_log("%s\n", temp); ncr_reset(ncr_dev, &ncr_dev->ncr); - if (ncr_dev->type < 3) { - ncr_dev->status_ctrl = STATUS_BUFFER_NOT_READY; - ncr_dev->buffer_host_pos = 128; - } else { - ncr_dev->t128.status = 0x04; - ncr_dev->t128.host_pos = 512; - - if (!ncr_dev->t128.bios_enabled) - ncr_dev->t128.status |= 0x80; - } - timer_add(&ncr_dev->timer, ncr_callback, ncr_dev, 0); + if ((ncr_dev->type < 3) || (ncr_dev->type == 4)) { + ncr_dev->status_ctrl = STATUS_BUFFER_NOT_READY; + ncr_dev->buffer_host_pos = 128; + } else { + ncr_dev->t128.status = 0x04; + ncr_dev->t128.host_pos = 512; - return(ncr_dev); + if (!ncr_dev->t128.bios_enabled) + ncr_dev->t128.status |= 0x80; + } + timer_add(&ncr_dev->timer, ncr_callback, ncr_dev, 0); + + scsi_bus_set_speed(ncr_dev->bus, 5000000.0); + + return ncr_dev; } - -static void +static void ncr_close(void *priv) { - ncr5380_t *ncr_dev = (ncr5380_t *)priv; + ncr5380_t *ncr_dev = (ncr5380_t *) priv; if (ncr_dev) { - /* Tell the timer to terminate. */ - timer_stop(&ncr_dev->timer); + /* Tell the timer to terminate. */ + timer_stop(&ncr_dev->timer); - free(ncr_dev); - ncr_dev = NULL; + free(ncr_dev); + ncr_dev = NULL; } } - static int lcs6821n_available(void) { - return(rom_present(LCS6821N_ROM)); + return (rom_present(LCS6821N_ROM)); } - static int rt1000b_available(void) { - return(rom_present(RT1000B_820R_ROM) && rom_present(RT1000B_810R_ROM)); + return (rom_present(RT1000B_820R_ROM) && rom_present(RT1000B_810R_ROM)); +} + +static int +rt1000b_820_available(void) +{ + return (rom_present(RT1000B_820R_ROM)); } static int t130b_available(void) { - return(rom_present(T130B_ROM)); + return (rom_present(T130B_ROM)); } static int t128_available(void) { - return(rom_present(T128_ROM)); + return (rom_present(T128_ROM)); } -static const device_config_t ncr5380_mmio_config[] = { - { - "bios_addr", "BIOS Address", CONFIG_HEX20, "", 0xD8000, "", { 0 }, - { - { - "C800H", 0xc8000 - }, - { - "CC00H", 0xcc000 - }, - { - "D800H", 0xd8000 - }, - { - "DC00H", 0xdc000 - }, - { - "" - } - }, +static int +corel_ls2000_available(void) +{ + return (rom_present(COREL_LS2000_ROM)); +} +// clang-format off +static const device_config_t ncr5380_mmio_config[] = { + { + .name = "bios_addr", + .description = "BIOS Address", + .type = CONFIG_HEX20, + .default_string = "", + .default_int = 0xD8000, + .file_filter = "", + .spinner = { 0 }, + .selection = { + { .description = "C800H", .value = 0xc8000 }, + { .description = "CC00H", .value = 0xcc000 }, + { .description = "D000H", .value = 0xd0000 }, + { .description = "D400H", .value = 0xd4000 }, + { .description = "D800H", .value = 0xd8000 }, + { .description = "DC00H", .value = 0xdc000 }, + { .description = "" } }, - { - "irq", "IRQ", CONFIG_SELECTION, "", 5, "", { 0 }, - { - { - "IRQ 3", 3 - }, - { - "IRQ 5", 5 - }, - { - "IRQ 7", 7 - }, - { - "" - } - }, + }, + { + .name = "irq", + .description = "IRQ", + .type = CONFIG_SELECTION, + .default_string = "", + .default_int = 5, + .file_filter = "", + .spinner = { 0 }, + .selection = { + { .description = "IRQ 3", .value = 3 }, + { .description = "IRQ 5", .value = 5 }, + { .description = "IRQ 7", .value = 7 }, + { .description = "" } }, - { - "", "", -1 - } + }, + { .name = "", .description = "", .type = CONFIG_END } }; static const device_config_t rancho_config[] = { - { - "bios_addr", "BIOS Address", CONFIG_HEX20, "", 0xD8000, "", { 0 }, - { - { - "C800H", 0xc8000 - }, - { - "CC00H", 0xcc000 - }, - { - "D800H", 0xd8000 - }, - { - "DC00H", 0xdc000 - }, - { - "" - } - }, + { + .name = "bios_addr", + .description = "BIOS Address", + .type = CONFIG_HEX20, + .default_string = "", + .default_int = 0xD8000, + .file_filter = "", + .spinner = { 0 }, + .selection = { + { .description = "C800H", .value = 0xc8000 }, + { .description = "CC00H", .value = 0xcc000 }, + { .description = "D000H", .value = 0xd0000 }, + { .description = "D400H", .value = 0xd4000 }, + { .description = "D800H", .value = 0xd8000 }, + { .description = "DC00H", .value = 0xdc000 }, + { .description = "" } + }, + }, + { + .name = "irq", + .description = "IRQ", + .type = CONFIG_SELECTION, + .default_string = "", + .default_int = 5, + .file_filter = "", + .spinner = { 0 }, + .selection = { + { .description = "IRQ 3", .value = 3 }, + { .description = "IRQ 5", .value = 5 }, + { .description = "IRQ 7", .value = 7 }, + { .description = "" } + }, + }, + { + .name = "bios_ver", + .description = "BIOS Version", + .type = CONFIG_SELECTION, + .default_string = "", + .default_int = 1, + .file_filter = "", + .spinner = { 0 }, + .selection = { + { .description = "8.20R", .value = 1 }, + { .description = "8.10R", .value = 0 }, + { .description = "" } + }, + }, + { .name = "", .description = "", .type = CONFIG_END } +}; +static const device_config_t rancho_mc_config[] = { + { + .name = "irq", + .description = "IRQ", + .type = CONFIG_SELECTION, + .default_string = "", + .default_int = 5, + .file_filter = "", + .spinner = { 0 }, + .selection = { + { .description = "IRQ 3", .value = 3 }, + { .description = "IRQ 5", .value = 5 }, + { .description = "IRQ 7", .value = 7 }, + { .description = "" } }, - { - "irq", "IRQ", CONFIG_SELECTION, "", 5, "", { 0 }, - { - { - "IRQ 3", 3 - }, - { - "IRQ 5", 5 - }, - { - "IRQ 7", 7 - }, - { - "" - } - }, - }, - { - "bios_ver", "BIOS Version", CONFIG_SELECTION, "", 1, "", { 0 }, - { - { - "8.20R", 1 - }, - { - "8.10R", 0 - }, - { - "" - } - }, - }, - { - "", "", -1 - } + }, + { .name = "", .description = "", .type = CONFIG_END } }; static const device_config_t t130b_config[] = { - { - "bios_addr", "BIOS Address", CONFIG_HEX20, "", 0xD8000, "", { 0 }, - { - { - "Disabled", 0 - }, - { - "C800H", 0xc8000 - }, - { - "CC00H", 0xcc000 - }, - { - "D800H", 0xd8000 - }, - { - "DC00H", 0xdc000 - }, - { - "" - } - }, + { + .name = "bios_addr", + .description = "BIOS Address", + .type = CONFIG_HEX20, + .default_string = "", + .default_int = 0xD8000, + .file_filter = "", + .spinner = { 0 }, + .selection = { + { .description = "Disabled", .value = 0 }, + { .description = "C800H", .value = 0xc8000 }, + { .description = "CC00H", .value = 0xcc000 }, + { .description = "D800H", .value = 0xd8000 }, + { .description = "DC00H", .value = 0xdc000 }, + { .description = "" } }, - { - "base", "Address", CONFIG_HEX16, "", 0x0350, "", { 0 }, - { - { - "240H", 0x0240 - }, - { - "250H", 0x0250 - }, - { - "340H", 0x0340 - }, - { - "350H", 0x0350 - }, - { - "" - } - }, + }, + { + .name = "base", + .description = "Address", + .type = CONFIG_HEX16, + .default_string = "", + .default_int = 0x0350, + .file_filter = "", + .spinner = { 0 }, + .selection = { + { .description = "240H", .value = 0x0240 }, + { .description = "250H", .value = 0x0250 }, + { .description = "340H", .value = 0x0340 }, + { .description = "350H", .value = 0x0350 }, + { .description = "" } }, - { - "irq", "IRQ", CONFIG_SELECTION, "", 5, "", { 0 }, - { - { - "IRQ 3", 3 - }, - { - "IRQ 5", 5 - }, - { - "IRQ 7", 7 - }, - { - "" - } - }, + }, + { + .name = "irq", + .description = "IRQ", + .type = CONFIG_SELECTION, + .default_string = "", + .default_int = 5, + .file_filter = "", + .spinner = { 0 }, + .selection = { + { .description = "IRQ 3", .value = 3 }, + { .description = "IRQ 5", .value = 5 }, + { .description = "IRQ 7", .value = 7 }, + { .description = "" } }, - { - "", "", -1 - } + }, + { .name = "", .description = "", .type = CONFIG_END } }; - static const device_config_t t128_config[] = { - { - "bios_addr", "BIOS Address", CONFIG_HEX20, "", 0xD8000, "", { 0 }, - { - { - "C800H", 0xc8000 - }, - { - "CC00H", 0xcc000 - }, - { - "D800H", 0xd8000 - }, - { - "DC00H", 0xdc000 - }, - { - "" - } - }, + { + .name = "bios_addr", + .description = "BIOS Address", + .type = CONFIG_HEX20, + .default_string = "", + .default_int = 0xD8000, + .file_filter = "", + .spinner = { 0 }, + .selection = { + { .description = "C800H", .value = 0xc8000 }, + { .description = "CC00H", .value = 0xcc000 }, + { .description = "D000H", .value = 0xd0000 }, + { .description = "D400H", .value = 0xd4000 }, + { .description = "D800H", .value = 0xd8000 }, + { .description = "DC00H", .value = 0xdc000 }, + { .description = "" } }, - { - "irq", "IRQ", CONFIG_SELECTION, "", 5, "", { 0 }, - { - { - "IRQ 3", 3 - }, - { - "IRQ 5", 5 - }, - { - "IRQ 7", 7 - }, - { - "" - } - }, + }, + { + .name = "irq", + .description = "IRQ", + .type = CONFIG_SELECTION, + .default_string = "", + .default_int = 5, + .file_filter = "", + .spinner ={ 0 }, + .selection = { + { .description = "IRQ 3", .value = 3 }, + { .description = "IRQ 5", .value = 5 }, + { .description = "IRQ 7", .value = 7 }, + { .description = "" } }, - { - "boot", "Enable Boot ROM", CONFIG_BINARY, "", 1 - }, - { - "", "", -1 - } + }, + { + .name = "boot", + .description = "Enable Boot ROM", + .type = CONFIG_BINARY, + .default_string = "", + .default_int = 1 + }, + { .name = "", .description = "", .type = CONFIG_END } +}; +// clang-format on + +const device_t scsi_lcs6821n_device = { + .name = "Longshine LCS-6821N", + .internal_name = "lcs6821n", + .flags = DEVICE_ISA, + .local = 0, + .init = ncr_init, + .close = ncr_close, + .reset = NULL, + { .available = lcs6821n_available }, + .speed_changed = NULL, + .force_redraw = NULL, + .config = ncr5380_mmio_config }; -const device_t scsi_lcs6821n_device = -{ - "Longshine LCS-6821N", - "lcs6821n", - DEVICE_ISA, - 0, - ncr_init, ncr_close, NULL, - { lcs6821n_available }, - NULL, NULL, - ncr5380_mmio_config +const device_t scsi_rt1000b_device = { + .name = "Rancho RT1000B", + .internal_name = "rt1000b", + .flags = DEVICE_ISA, + .local = 1, + .init = ncr_init, + .close = ncr_close, + .reset = NULL, + { .available = rt1000b_available }, + .speed_changed = NULL, + .force_redraw = NULL, + .config = rancho_config }; -const device_t scsi_rt1000b_device = -{ - "Rancho RT1000B", - "rt1000b", - DEVICE_ISA, - 1, - ncr_init, ncr_close, NULL, - { rt1000b_available }, - NULL, NULL, - rancho_config +const device_t scsi_rt1000mc_device = { + .name = "Rancho RT1000B-MC", + .internal_name = "rt1000mc", + .flags = DEVICE_MCA, + .local = 1, + .init = ncr_init, + .close = ncr_close, + .reset = NULL, + { .available = rt1000b_820_available }, + .speed_changed = NULL, + .force_redraw = NULL, + .config = rancho_mc_config }; -const device_t scsi_t130b_device = -{ - "Trantor T130B", - "t130b", - DEVICE_ISA, - 2, - ncr_init, ncr_close, NULL, - { t130b_available }, - NULL, NULL, - t130b_config +const device_t scsi_t130b_device = { + .name = "Trantor T130B", + .internal_name = "t130b", + .flags = DEVICE_ISA, + .local = 2, + .init = ncr_init, + .close = ncr_close, + .reset = NULL, + { .available = t130b_available }, + .speed_changed = NULL, + .force_redraw = NULL, + .config = t130b_config }; -const device_t scsi_t128_device = -{ - "Trantor T128", - "t128", - DEVICE_ISA, - 3, - ncr_init, ncr_close, NULL, - { t128_available }, - NULL, NULL, - t128_config +const device_t scsi_t128_device = { + .name = "Trantor T128", + .internal_name = "t128", + .flags = DEVICE_ISA, + .local = 3, + .init = ncr_init, + .close = ncr_close, + .reset = NULL, + { .available = t128_available }, + .speed_changed = NULL, + .force_redraw = NULL, + .config = t128_config +}; + +const device_t scsi_ls2000_device = { + .name = "Corel LS2000", + .internal_name = "ls2000", + .flags = DEVICE_ISA, + .local = 4, + .init = ncr_init, + .close = ncr_close, + .reset = NULL, + { .available = corel_ls2000_available }, + .speed_changed = NULL, + .force_redraw = NULL, + .config = ncr5380_mmio_config }; diff --git a/src/scsi/scsi_ncr53c8xx.c b/src/scsi/scsi_ncr53c8xx.c index fe7ebb558..42925338d 100644 --- a/src/scsi/scsi_ncr53c8xx.c +++ b/src/scsi/scsi_ncr53c8xx.c @@ -1,25 +1,25 @@ /* - * 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. + * 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. + * This file is part of the 86Box distribution. * - * Implementation of the NCR 53C810 and 53C875 SCSI Host - * Adapters made by NCR and later Symbios and LSI. These - * controllers were designed for the PCI bus. + * Implementation of the NCR 53C810 and 53C875 SCSI Host + * Adapters made by NCR and later Symbios and LSI. These + * controllers were designed for the PCI bus. * * * - * Authors: Paul Brook (QEMU) - * Artyom Tarasenko (QEMU) - * TheCollector1995, - * Miran Grca, + * Authors: Paul Brook (QEMU) + * Artyom Tarasenko (QEMU) + * TheCollector1995, + * Miran Grca, * - * Copyright 2006-2018 Paul Brook. - * Copyright 2009-2018 Artyom Tarasenko. - * Copyright 2017,2018 Miran Grca. + * Copyright 2006-2018 Paul Brook. + * Copyright 2009-2018 Artyom Tarasenko. + * Copyright 2017-2018 Miran Grca. */ #include #include @@ -45,190 +45,188 @@ #include <86box/scsi_device.h> #include <86box/scsi_ncr53c8xx.h> +#define NCR53C8XX_SDMS3_ROM "roms/scsi/ncr53c8xx/NCR307.BIN" +#define SYM53C8XX_SDMS4_ROM "roms/scsi/ncr53c8xx/8xx_64.rom" -#define NCR53C8XX_SDMS3_ROM "roms/scsi/ncr53c8xx/NCR307.BIN" -#define SYM53C8XX_SDMS4_ROM "roms/scsi/ncr53c8xx/8xx_64.rom" +#define HA_ID 7 -#define HA_ID 7 +#define CHIP_810 0x01 +#define CHIP_820 0x02 +#define CHIP_825 0x03 +#define CHIP_815 0x04 +#define CHIP_810AP 0x05 +#define CHIP_860 0x06 +#define CHIP_895 0x0c +#define CHIP_875 0x0f +#define CHIP_895A 0x12 +#define CHIP_875A 0x13 +#define CHIP_875J 0x8f -#define CHIP_810 0x01 -#define CHIP_820 0x02 -#define CHIP_825 0x03 -#define CHIP_815 0x04 -#define CHIP_810AP 0x05 -#define CHIP_860 0x06 -#define CHIP_895 0x0c -#define CHIP_875 0x0f -#define CHIP_895A 0x12 -#define CHIP_875A 0x13 -#define CHIP_875J 0x8f +#define NCR_SCNTL0_TRG 0x01 +#define NCR_SCNTL0_AAP 0x02 +#define NCR_SCNTL0_EPC 0x08 +#define NCR_SCNTL0_WATN 0x10 +#define NCR_SCNTL0_START 0x20 -#define NCR_SCNTL0_TRG 0x01 -#define NCR_SCNTL0_AAP 0x02 -#define NCR_SCNTL0_EPC 0x08 -#define NCR_SCNTL0_WATN 0x10 -#define NCR_SCNTL0_START 0x20 +#define NCR_SCNTL1_SST 0x01 +#define NCR_SCNTL1_IARB 0x02 +#define NCR_SCNTL1_AESP 0x04 +#define NCR_SCNTL1_RST 0x08 +#define NCR_SCNTL1_CON 0x10 +#define NCR_SCNTL1_DHP 0x20 +#define NCR_SCNTL1_ADB 0x40 +#define NCR_SCNTL1_EXC 0x80 -#define NCR_SCNTL1_SST 0x01 -#define NCR_SCNTL1_IARB 0x02 -#define NCR_SCNTL1_AESP 0x04 -#define NCR_SCNTL1_RST 0x08 -#define NCR_SCNTL1_CON 0x10 -#define NCR_SCNTL1_DHP 0x20 -#define NCR_SCNTL1_ADB 0x40 -#define NCR_SCNTL1_EXC 0x80 +#define NCR_SCNTL2_WSR 0x01 +#define NCR_SCNTL2_VUE0 0x02 +#define NCR_SCNTL2_VUE1 0x04 +#define NCR_SCNTL2_WSS 0x08 +#define NCR_SCNTL2_SLPHBEN 0x10 +#define NCR_SCNTL2_SLPMD 0x20 +#define NCR_SCNTL2_CHM 0x40 +#define NCR_SCNTL2_SDU 0x80 -#define NCR_SCNTL2_WSR 0x01 -#define NCR_SCNTL2_VUE0 0x02 -#define NCR_SCNTL2_VUE1 0x04 -#define NCR_SCNTL2_WSS 0x08 -#define NCR_SCNTL2_SLPHBEN 0x10 -#define NCR_SCNTL2_SLPMD 0x20 -#define NCR_SCNTL2_CHM 0x40 -#define NCR_SCNTL2_SDU 0x80 +#define NCR_ISTAT_DIP 0x01 +#define NCR_ISTAT_SIP 0x02 +#define NCR_ISTAT_INTF 0x04 +#define NCR_ISTAT_CON 0x08 +#define NCR_ISTAT_SEM 0x10 +#define NCR_ISTAT_SIGP 0x20 +#define NCR_ISTAT_SRST 0x40 +#define NCR_ISTAT_ABRT 0x80 -#define NCR_ISTAT_DIP 0x01 -#define NCR_ISTAT_SIP 0x02 -#define NCR_ISTAT_INTF 0x04 -#define NCR_ISTAT_CON 0x08 -#define NCR_ISTAT_SEM 0x10 -#define NCR_ISTAT_SIGP 0x20 -#define NCR_ISTAT_SRST 0x40 -#define NCR_ISTAT_ABRT 0x80 +#define NCR_SSTAT0_SDP0 0x01 +#define NCR_SSTAT0_RST 0x02 +#define NCR_SSTAT0_WOA 0x04 +#define NCR_SSTAT0_LOA 0x08 +#define NCR_SSTAT0_AIP 0x10 +#define NCR_SSTAT0_OLF 0x20 +#define NCR_SSTAT0_ORF 0x40 +#define NCR_SSTAT0_ILF 0x80 -#define NCR_SSTAT0_SDP0 0x01 -#define NCR_SSTAT0_RST 0x02 -#define NCR_SSTAT0_WOA 0x04 -#define NCR_SSTAT0_LOA 0x08 -#define NCR_SSTAT0_AIP 0x10 -#define NCR_SSTAT0_OLF 0x20 -#define NCR_SSTAT0_ORF 0x40 -#define NCR_SSTAT0_ILF 0x80 +#define NCR_SIST0_PAR 0x01 +#define NCR_SIST0_RST 0x02 +#define NCR_SIST0_UDC 0x04 +#define NCR_SIST0_SGE 0x08 +#define NCR_SIST0_RSL 0x10 +#define NCR_SIST0_SEL 0x20 +#define NCR_SIST0_CMP 0x40 +#define NCR_SIST0_MA 0x80 -#define NCR_SIST0_PAR 0x01 -#define NCR_SIST0_RST 0x02 -#define NCR_SIST0_UDC 0x04 -#define NCR_SIST0_SGE 0x08 -#define NCR_SIST0_RSL 0x10 -#define NCR_SIST0_SEL 0x20 -#define NCR_SIST0_CMP 0x40 -#define NCR_SIST0_MA 0x80 +#define NCR_SIST1_HTH 0x01 +#define NCR_SIST1_GEN 0x02 +#define NCR_SIST1_STO 0x04 +#define NCR_SIST1_SBMC 0x10 -#define NCR_SIST1_HTH 0x01 -#define NCR_SIST1_GEN 0x02 -#define NCR_SIST1_STO 0x04 -#define NCR_SIST1_SBMC 0x10 +#define NCR_SOCL_IO 0x01 +#define NCR_SOCL_CD 0x02 +#define NCR_SOCL_MSG 0x04 +#define NCR_SOCL_ATN 0x08 +#define NCR_SOCL_SEL 0x10 +#define NCR_SOCL_BSY 0x20 +#define NCR_SOCL_ACK 0x40 +#define NCR_SOCL_REQ 0x80 -#define NCR_SOCL_IO 0x01 -#define NCR_SOCL_CD 0x02 -#define NCR_SOCL_MSG 0x04 -#define NCR_SOCL_ATN 0x08 -#define NCR_SOCL_SEL 0x10 -#define NCR_SOCL_BSY 0x20 -#define NCR_SOCL_ACK 0x40 -#define NCR_SOCL_REQ 0x80 +#define NCR_DSTAT_IID 0x01 +#define NCR_DSTAT_SIR 0x04 +#define NCR_DSTAT_SSI 0x08 +#define NCR_DSTAT_ABRT 0x10 +#define NCR_DSTAT_BF 0x20 +#define NCR_DSTAT_MDPE 0x40 +#define NCR_DSTAT_DFE 0x80 -#define NCR_DSTAT_IID 0x01 -#define NCR_DSTAT_SIR 0x04 -#define NCR_DSTAT_SSI 0x08 -#define NCR_DSTAT_ABRT 0x10 -#define NCR_DSTAT_BF 0x20 -#define NCR_DSTAT_MDPE 0x40 -#define NCR_DSTAT_DFE 0x80 +#define NCR_DCNTL_COM 0x01 +#define NCR_DCNTL_IRQD 0x02 +#define NCR_DCNTL_STD 0x04 +#define NCR_DCNTL_IRQM 0x08 +#define NCR_DCNTL_SSM 0x10 +#define NCR_DCNTL_PFEN 0x20 +#define NCR_DCNTL_PFF 0x40 +#define NCR_DCNTL_CLSE 0x80 -#define NCR_DCNTL_COM 0x01 -#define NCR_DCNTL_IRQD 0x02 -#define NCR_DCNTL_STD 0x04 -#define NCR_DCNTL_IRQM 0x08 -#define NCR_DCNTL_SSM 0x10 -#define NCR_DCNTL_PFEN 0x20 -#define NCR_DCNTL_PFF 0x40 -#define NCR_DCNTL_CLSE 0x80 +#define NCR_DMODE_MAN 0x01 +#define NCR_DMODE_BOF 0x02 +#define NCR_DMODE_ERMP 0x04 +#define NCR_DMODE_ERL 0x08 +#define NCR_DMODE_DIOM 0x10 +#define NCR_DMODE_SIOM 0x20 -#define NCR_DMODE_MAN 0x01 -#define NCR_DMODE_BOF 0x02 -#define NCR_DMODE_ERMP 0x04 -#define NCR_DMODE_ERL 0x08 -#define NCR_DMODE_DIOM 0x10 -#define NCR_DMODE_SIOM 0x20 +#define NCR_CTEST2_DACK 0x01 +#define NCR_CTEST2_DREQ 0x02 +#define NCR_CTEST2_TEOP 0x04 +#define NCR_CTEST2_PCICIE 0x08 +#define NCR_CTEST2_CM 0x10 +#define NCR_CTEST2_CIO 0x20 +#define NCR_CTEST2_SIGP 0x40 +#define NCR_CTEST2_DDIR 0x80 -#define NCR_CTEST2_DACK 0x01 -#define NCR_CTEST2_DREQ 0x02 -#define NCR_CTEST2_TEOP 0x04 -#define NCR_CTEST2_PCICIE 0x08 -#define NCR_CTEST2_CM 0x10 -#define NCR_CTEST2_CIO 0x20 -#define NCR_CTEST2_SIGP 0x40 -#define NCR_CTEST2_DDIR 0x80 - -#define NCR_CTEST5_BL2 0x04 -#define NCR_CTEST5_DDIR 0x08 -#define NCR_CTEST5_MASR 0x10 -#define NCR_CTEST5_DFSN 0x20 -#define NCR_CTEST5_BBCK 0x40 -#define NCR_CTEST5_ADCK 0x80 +#define NCR_CTEST5_BL2 0x04 +#define NCR_CTEST5_DDIR 0x08 +#define NCR_CTEST5_MASR 0x10 +#define NCR_CTEST5_DFSN 0x20 +#define NCR_CTEST5_BBCK 0x40 +#define NCR_CTEST5_ADCK 0x80 /* Enable Response to Reselection */ -#define NCR_SCID_RRE 0x60 +#define NCR_SCID_RRE 0x60 -#define PHASE_DO 0 -#define PHASE_DI 1 -#define PHASE_CMD 2 -#define PHASE_ST 3 -#define PHASE_MO 6 -#define PHASE_MI 7 -#define PHASE_MASK 7 +#define PHASE_DO 0 +#define PHASE_DI 1 +#define PHASE_CMD 2 +#define PHASE_ST 3 +#define PHASE_MO 6 +#define PHASE_MI 7 +#define PHASE_MASK 7 /* Maximum length of MSG IN data. */ #define NCR_MAX_MSGIN_LEN 8 /* Flag set if this is a tagged command. */ -#define NCR_TAG_VALID (1 << 16) +#define NCR_TAG_VALID (1 << 16) -#define NCR_NVRAM_SIZE 2048 -#define NCR_BUF_SIZE 4096 +#define NCR_NVRAM_SIZE 2048 +#define NCR_BUF_SIZE 4096 typedef struct ncr53c8xx_request { uint32_t tag; uint32_t dma_len; uint8_t *dma_buf; uint32_t pending; - int out; + int out; } ncr53c8xx_request; -typedef enum -{ - SCSI_STATE_SEND_COMMAND, - SCSI_STATE_READ_DATA, - SCSI_STATE_WRITE_DATA, - SCSI_STATE_READ_STATUS, - SCSI_STATE_READ_MESSAGE, - SCSI_STATE_WRITE_MESSAGE +typedef enum { + SCSI_STATE_SEND_COMMAND, + SCSI_STATE_READ_DATA, + SCSI_STATE_WRITE_DATA, + SCSI_STATE_READ_STATUS, + SCSI_STATE_READ_MESSAGE, + SCSI_STATE_WRITE_MESSAGE } scsi_state_t; -typedef struct { - char *nvr_path; - uint8_t pci_slot; - uint8_t chip, wide; - int has_bios; - int BIOSBase; - rom_t bios; - int PCIBase; - int MMIOBase; +typedef struct ncr53c8xx_t { + char *nvr_path; + uint8_t pci_slot; + uint8_t chip, wide; + int has_bios; + int BIOSBase; + rom_t bios; + int PCIBase; + int MMIOBase; mem_mapping_t mmio_mapping; - int RAMBase; + int RAMBase; mem_mapping_t ram_mapping; int carry; /* ??? Should this be an a visible register somewhere? */ int status; /* Action to take at the end of a MSG IN phase. 0 = COMMAND, 1 = disconnect, 2 = DATA OUT, 3 = DATA IN. */ - int msg_action; - int msg_len; + int msg_action; + int msg_len; uint8_t msg[NCR_MAX_MSGIN_LEN]; uint8_t nvram[NCR_NVRAM_SIZE]; /* 24C16 EEPROM (16 Kbit) */ - void *i2c, *eeprom; - uint8_t ram[NCR_BUF_SIZE]; /* NCR 53C875 RAM (4 KB) */ + void *i2c, *eeprom; + uint8_t ram[NCR_BUF_SIZE]; /* NCR 53C875 RAM (4 KB) */ /* 0 if SCRIPTS are running or stopped. * 1 if a Wait Reselect instruction has been issued. * 2 if processing DMA from ncr53c8xx_execute_script. @@ -236,6 +234,7 @@ typedef struct { int waiting; uint8_t current_lun; + uint8_t irq_state; uint8_t istat; uint8_t dcmd; @@ -282,28 +281,35 @@ typedef struct { uint8_t gpcntl; uint8_t last_command; - int command_complete; + int command_complete; ncr53c8xx_request *current; int irq; - + uint32_t dsa; uint32_t temp; uint32_t dnad; uint32_t dbc; uint32_t dsp; uint32_t dsps; - uint32_t scratcha, scratchb, scratchc, scratchd; - uint32_t scratche, scratchf, scratchg, scratchh; - uint32_t scratchi, scratchj; - int last_level; - void *hba_private; + uint32_t scratcha; + uint32_t scratchb; + uint32_t scratchc; + uint32_t scratchd; + uint32_t scratche; + uint32_t scratchf; + uint32_t scratchg; + uint32_t scratchh; + uint32_t scratchi; + uint32_t scratchj; + int last_level; + void *hba_private; uint32_t buffer_pos; - int32_t temp_buf_len; + int32_t temp_buf_len; uint8_t sstop; - uint8_t regop; + uint8_t regop; uint32_t adder; uint32_t bios_mask; @@ -317,30 +323,26 @@ typedef struct { #endif } ncr53c8xx_t; - #ifdef ENABLE_NCR53C8XX_LOG int ncr53c8xx_do_log = ENABLE_NCR53C8XX_LOG; - static void ncr53c8xx_log(const char *fmt, ...) { va_list ap; if (ncr53c8xx_do_log) { - va_start(ap, fmt); - pclog_ex(fmt, ap); - va_end(ap); + va_start(ap, fmt); + pclog_ex(fmt, ap); + va_end(ap); } } #else -#define ncr53c8xx_log(fmt, ...) +# define ncr53c8xx_log(fmt, ...) #endif - -static uint8_t ncr53c8xx_reg_readb(ncr53c8xx_t *dev, uint32_t offset); -static void ncr53c8xx_reg_writeb(ncr53c8xx_t *dev, uint32_t offset, uint8_t val); - +static uint8_t ncr53c8xx_reg_readb(ncr53c8xx_t *dev, uint32_t offset); +static void ncr53c8xx_reg_writeb(ncr53c8xx_t *dev, uint32_t offset, uint8_t val); static __inline int32_t sextract32(uint32_t value, int start, int length) @@ -348,17 +350,15 @@ sextract32(uint32_t value, int start, int length) /* Note that this implementation relies on right shift of signed * integers being an arithmetic shift. */ - return ((int32_t)(value << (32 - length - start))) >> (32 - length); + return ((int32_t) (value << (32 - length - start))) >> (32 - length); } - static __inline int ncr53c8xx_irq_on_rsl(ncr53c8xx_t *dev) { return (dev->sien0 & NCR_SIST0_RSL) && (dev->scid & NCR_SCID_RRE); } - static void ncr53c8xx_soft_reset(ncr53c8xx_t *dev) { @@ -370,151 +370,142 @@ ncr53c8xx_soft_reset(ncr53c8xx_t *dev) dev->carry = 0; dev->msg_action = 0; - dev->msg_len = 0; - dev->waiting = 0; - dev->dsa = 0; - dev->dnad = 0; - dev->dbc = 0; - dev->temp = 0; - dev->scratcha = 0; - dev->scratchb = 0; - dev->scratchc = 0; - dev->scratchd = 0; - dev->scratche = 0; - dev->scratchf = 0; - dev->scratchg = 0; - dev->scratchh = 0; - dev->scratchi = 0; - dev->scratchj = 0; - dev->istat = 0; - dev->dcmd = 0x40; - dev->dstat = NCR_DSTAT_DFE; - dev->dien = 0; - dev->sist0 = 0; - dev->sist1 = 0; - dev->sien0 = 0; - dev->sien1 = 0; - dev->mbox0 = 0; - dev->mbox1 = 0; - dev->dfifo = 0; - dev->ctest2 = NCR_CTEST2_DACK; - dev->ctest3 = 0; - dev->ctest4 = 0; - dev->ctest5 = 0; - dev->dsp = 0; - dev->dsps = 0; - dev->dmode = 0; - dev->dcntl = 0; - dev->scntl0 = 0xc0; - dev->scntl1 = 0; - dev->scntl2 = 0; + dev->msg_len = 0; + dev->waiting = 0; + dev->dsa = 0; + dev->dnad = 0; + dev->dbc = 0; + dev->temp = 0; + dev->scratcha = 0; + dev->scratchb = 0; + dev->scratchc = 0; + dev->scratchd = 0; + dev->scratche = 0; + dev->scratchf = 0; + dev->scratchg = 0; + dev->scratchh = 0; + dev->scratchi = 0; + dev->scratchj = 0; + dev->istat = 0; + dev->dcmd = 0x40; + dev->dstat = NCR_DSTAT_DFE; + dev->dien = 0; + dev->sist0 = 0; + dev->sist1 = 0; + dev->sien0 = 0; + dev->sien1 = 0; + dev->mbox0 = 0; + dev->mbox1 = 0; + dev->dfifo = 0; + dev->ctest2 = NCR_CTEST2_DACK; + dev->ctest3 = 0; + dev->ctest4 = 0; + dev->ctest5 = 0; + dev->dsp = 0; + dev->dsps = 0; + dev->dmode = 0; + dev->dcntl = 0; + dev->scntl0 = 0xc0; + dev->scntl1 = 0; + dev->scntl2 = 0; if (dev->wide) - dev->scntl3 = 8; + dev->scntl3 = 8; else - dev->scntl3 = 0; - dev->sstat0 = 0; - dev->sstat1 = 0; - dev->scid = HA_ID; - dev->sxfer = 0; - dev->socl = 0; - dev->sdid = 0; - dev->ssid = 0; - dev->stest1 = 0; - dev->stest2 = 0; - dev->stest3 = 0; - dev->sidl0 = 0; - dev->sidl1 = 0; - dev->stime0 = 0; - dev->stime0 = 1; - dev->respid0 = 0x80; - dev->respid1 = 0x00; - dev->sbr = 0; + dev->scntl3 = 0; + dev->sstat0 = 0; + dev->sstat1 = 0; + dev->scid = HA_ID; + dev->sxfer = 0; + dev->socl = 0; + dev->sdid = 0; + dev->ssid = 0; + dev->stest1 = 0; + dev->stest2 = 0; + dev->stest3 = 0; + dev->sidl0 = 0; + dev->sidl1 = 0; + dev->stime0 = 0; + dev->stime0 = 1; + dev->respid0 = 0x80; + dev->respid1 = 0x00; + dev->sbr = 0; dev->last_level = 0; - dev->gpreg = 0; - dev->slpar = 0; - dev->sstop = 1; - dev->gpcntl = 0x03; + dev->gpreg = 0; + dev->slpar = 0; + dev->sstop = 1; + dev->gpcntl = 0x03; if (dev->wide) { - /* This *IS* a wide SCSI controller, so reset all SCSI - devices. */ - for (i = 0; i < 16; i++) { + /* This *IS* a wide SCSI controller, so reset all SCSI + devices. */ + for (i = 0; i < 16; i++) { #ifdef USE_WDTR - dev->tr_set[i] = 0; + dev->tr_set[i] = 0; #endif - scsi_device_reset(&scsi_devices[dev->bus][i]); - } + scsi_device_reset(&scsi_devices[dev->bus][i]); + } } else { - /* This is *NOT* a wide SCSI controller, so do not touch - SCSI devices with ID's >= 8. */ - for (i = 0; i < 8; i++) { + /* This is *NOT* a wide SCSI controller, so do not touch + SCSI devices with ID's >= 8. */ + for (i = 0; i < 8; i++) { #ifdef USE_WDTR - dev->tr_set[i] = 0; + dev->tr_set[i] = 0; #endif - scsi_device_reset(&scsi_devices[dev->bus][i]); - } + scsi_device_reset(&scsi_devices[dev->bus][i]); + } } } - static void ncr53c8xx_read(ncr53c8xx_t *dev, uint32_t addr, uint8_t *buf, uint32_t len) { - uint32_t i = 0; + ncr53c8xx_log("ncr53c8xx_read(): %08X-%08X, length %i\n", addr, (addr + len - 1), len); - ncr53c8xx_log("ncr53c8xx_read(): %08X-%08X, length %i\n", addr, (addr + len - 1), len); - - if (dev->dmode & NCR_DMODE_SIOM) { - ncr53c8xx_log("NCR 810: Reading from I/O address %04X\n", (uint16_t) addr); - for (i = 0; i < len; i++) - buf[i] = inb((uint16_t) (addr + i)); - } else { - ncr53c8xx_log("NCR 810: Reading from memory address %08X\n", addr); - dma_bm_read(addr, buf, len, 4); - } + if (dev->dmode & NCR_DMODE_SIOM) { + ncr53c8xx_log("NCR 810: Reading from I/O address %04X\n", (uint16_t) addr); + for (uint32_t i = 0; i < len; i++) + buf[i] = inb((uint16_t) (addr + i)); + } else { + ncr53c8xx_log("NCR 810: Reading from memory address %08X\n", addr); + dma_bm_read(addr, buf, len, 4); + } } - static void ncr53c8xx_write(ncr53c8xx_t *dev, uint32_t addr, uint8_t *buf, uint32_t len) { - uint32_t i = 0; + ncr53c8xx_log("ncr53c8xx_write(): %08X-%08X, length %i\n", addr, (addr + len - 1), len); - ncr53c8xx_log("ncr53c8xx_write(): %08X-%08X, length %i\n", addr, (addr + len - 1), len); - - if (dev->dmode & NCR_DMODE_DIOM) { - ncr53c8xx_log("NCR 810: Writing to I/O address %04X\n", (uint16_t) addr); - for (i = 0; i < len; i++) - outb((uint16_t) (addr + i), buf[i]); - } else { - ncr53c8xx_log("NCR 810: Writing to memory address %08X\n", addr); - dma_bm_write(addr, buf, len, 4); - } -} - - -static __inline uint32_t -read_dword(ncr53c8xx_t *dev, uint32_t addr) -{ - uint32_t buf; - ncr53c8xx_log("Reading the next DWORD from memory (%08X)...\n", addr); - dma_bm_read(addr, (uint8_t *)&buf, 4, 4); - return buf; -} - - -static -void do_irq(ncr53c8xx_t *dev, int level) -{ - if (level) { - pci_set_irq(dev->pci_slot, PCI_INTA); - ncr53c8xx_log("Raising IRQ...\n"); + if (dev->dmode & NCR_DMODE_DIOM) { + ncr53c8xx_log("NCR 810: Writing to I/O address %04X\n", (uint16_t) addr); + for (uint32_t i = 0; i < len; i++) + outb((uint16_t) (addr + i), buf[i]); } else { - pci_clear_irq(dev->pci_slot, PCI_INTA); - ncr53c8xx_log("Lowering IRQ...\n"); + ncr53c8xx_log("NCR 810: Writing to memory address %08X\n", addr); + dma_bm_write(addr, buf, len, 4); } } +static __inline uint32_t +read_dword(UNUSED(ncr53c8xx_t *dev), uint32_t addr) +{ + uint32_t buf; + ncr53c8xx_log("Reading the next DWORD from memory (%08X)...\n", addr); + dma_bm_read(addr, (uint8_t *) &buf, 4, 4); + return buf; +} + +static void +do_irq(ncr53c8xx_t *dev, int level) +{ + if (level) { + pci_set_irq(dev->pci_slot, PCI_INTA, &dev->irq_state); + ncr53c8xx_log("Raising IRQ...\n"); + } else { + pci_clear_irq(dev->pci_slot, PCI_INTA, &dev->irq_state); + ncr53c8xx_log("Lowering IRQ...\n"); + } +} static void ncr53c8xx_update_irq(ncr53c8xx_t *dev) @@ -544,15 +535,18 @@ ncr53c8xx_update_irq(ncr53c8xx_t *dev) level = 1; } +#ifdef STATE_KEEPING if (level != dev->last_level) { +#endif ncr53c8xx_log("Update IRQ level %d dstat %02x sist %02x%02x\n", - level, dev->dstat, dev->sist1, dev->sist0); + level, dev->dstat, dev->sist1, dev->sist0); dev->last_level = level; - do_irq(dev, level); /* Only do something with the IRQ if the new level differs from the previous one. */ + do_irq(dev, level); /* Only do something with the IRQ if the new level differs from the previous one. */ +#ifdef STATE_KEEPING } +#endif } - /* Stop SCRIPTS execution and raise a SCSI interrupt. */ static void ncr53c8xx_script_scsi_interrupt(ncr53c8xx_t *dev, int stat0, int stat1) @@ -561,7 +555,7 @@ ncr53c8xx_script_scsi_interrupt(ncr53c8xx_t *dev, int stat0, int stat1) uint32_t mask1; ncr53c8xx_log("SCSI Interrupt 0x%02x%02x prev 0x%02x%02x\n", - stat1, stat0, dev->sist1, dev->sist0); + stat1, stat0, dev->sist1, dev->sist0); dev->sist0 |= stat0; dev->sist1 |= stat1; /* Stop processor on fatal or unmasked interrupt. As a special hack @@ -571,14 +565,13 @@ ncr53c8xx_script_scsi_interrupt(ncr53c8xx_t *dev, int stat0, int stat1) mask1 = dev->sien1 | ~(NCR_SIST1_GEN | NCR_SIST1_HTH); mask1 &= ~NCR_SIST1_STO; if ((dev->sist0 & mask0) || (dev->sist1 & mask1)) { - ncr53c8xx_log("NCR 810: IRQ-mandated stop\n"); - dev->sstop = 1; - timer_stop(&dev->timer); + ncr53c8xx_log("NCR 810: IRQ-mandated stop\n"); + dev->sstop = 1; + timer_stop(&dev->timer); } ncr53c8xx_update_irq(dev); } - /* Stop SCRIPTS execution and raise a DMA interrupt. */ static void ncr53c8xx_script_dma_interrupt(ncr53c8xx_t *dev, int stat) @@ -590,16 +583,14 @@ ncr53c8xx_script_dma_interrupt(ncr53c8xx_t *dev, int stat) timer_stop(&dev->timer); } - static __inline void ncr53c8xx_set_phase(ncr53c8xx_t *dev, int phase) { dev->sstat1 = (dev->sstat1 & ~PHASE_MASK) | phase; } - static void -ncr53c8xx_bad_phase(ncr53c8xx_t *dev, int out, int new_phase) +ncr53c8xx_bad_phase(ncr53c8xx_t *dev, UNUSED(int out), int new_phase) { /* Trigger a phase mismatch. */ ncr53c8xx_log("Phase mismatch interrupt\n"); @@ -609,7 +600,6 @@ ncr53c8xx_bad_phase(ncr53c8xx_t *dev, int out, int new_phase) ncr53c8xx_set_phase(dev, new_phase); } - static void ncr53c8xx_disconnect(ncr53c8xx_t *dev) { @@ -619,65 +609,63 @@ ncr53c8xx_disconnect(ncr53c8xx_t *dev) dev->scntl1 &= ~NCR_SCNTL1_CON; dev->sstat1 &= ~PHASE_MASK; - if (dev->dcmd & 0x01) /* Select with ATN */ - dev->sstat1 |= 0x07; + if (dev->dcmd & 0x01) /* Select with ATN */ + dev->sstat1 |= 0x07; scsi_device_identify(sd, SCSI_LUN_USE_CDB); } - static void -ncr53c8xx_bad_selection(ncr53c8xx_t *dev, uint32_t id) +ncr53c8xx_bad_selection(ncr53c8xx_t *dev, UNUSED(uint32_t id)) { ncr53c8xx_log("Selected absent target %d\n", id); ncr53c8xx_script_scsi_interrupt(dev, 0, NCR_SIST1_STO); ncr53c8xx_disconnect(dev); } - /* Callback to indicate that the SCSI layer has completed a command. */ static void ncr53c8xx_command_complete(void *priv, uint32_t status) { - ncr53c8xx_t *dev = (ncr53c8xx_t *)priv; - int out; - + ncr53c8xx_t *dev = (ncr53c8xx_t *) priv; + int out; + out = (dev->sstat1 & PHASE_MASK) == PHASE_DO; - ncr53c8xx_log("(ID=%02i LUN=%02i) SCSI Command 0x%02x: Command complete status=%d\n", dev->current->tag, dev->current_lun, dev->last_command, (int)status); - dev->status = status; - dev->command_complete = 2; + ncr53c8xx_log("(ID=%02i LUN=%02i) SCSI Command 0x%02x: Command complete status=%d\n", dev->current->tag, dev->current_lun, dev->last_command, (int) status); + dev->status = status; + dev->command_complete = 2; if (dev->waiting && dev->dbc != 0) { - /* Raise phase mismatch for short transfers. */ - ncr53c8xx_bad_phase(dev, out, PHASE_ST); + /* Raise phase mismatch for short transfers. */ + ncr53c8xx_bad_phase(dev, out, PHASE_ST); } else - ncr53c8xx_set_phase(dev, PHASE_ST); + ncr53c8xx_set_phase(dev, PHASE_ST); dev->sstop = 0; } - static void ncr53c8xx_do_dma(ncr53c8xx_t *dev, int out, uint8_t id) { - uint32_t addr, tdbc; - int count; + uint32_t addr; + uint32_t tdbc; + int count; scsi_device_t *sd = &scsi_devices[dev->bus][id]; - if ((!scsi_device_present(sd))) { - ncr53c8xx_log("(ID=%02i LUN=%02i) SCSI Command 0x%02x: Device not present when attempting to do DMA\n", id, dev->current_lun, dev->last_command); - return; + if (!scsi_device_present(sd)) { + ncr53c8xx_log("(ID=%02i LUN=%02i) SCSI Command 0x%02x: Device not present when attempting to do DMA\n", id, dev->current_lun, dev->last_command); + return; } - + if (!dev->current->dma_len) { - /* Wait until data is available. */ - ncr53c8xx_log("(ID=%02i LUN=%02i) SCSI Command 0x%02x: DMA no data available\n", id, dev->current_lun, dev->last_command); - return; + /* Wait until data is available. */ + ncr53c8xx_log("(ID=%02i LUN=%02i) SCSI Command 0x%02x: DMA no data available\n", id, dev->current_lun, dev->last_command); + return; } /* Make sure count is never bigger than buffer_length. */ count = tdbc = dev->dbc; if (count > dev->temp_buf_len) - count = dev->temp_buf_len; + count = dev->temp_buf_len; addr = dev->dnad; @@ -686,45 +674,43 @@ ncr53c8xx_do_dma(ncr53c8xx_t *dev, int out, uint8_t id) dev->dbc -= count; if (out) - ncr53c8xx_read(dev, addr, sd->sc->temp_buffer + dev->buffer_pos, count); + ncr53c8xx_read(dev, addr, sd->sc->temp_buffer + dev->buffer_pos, count); else { #ifdef ENABLE_NCR53C8XX_LOG - if (!dev->buffer_pos) - ncr53c8xx_log("(ID=%02i LUN=%02i) SCSI Command 0x%02x: SCSI Command Phase 1 on PHASE_DI\n", id, dev->current_lun, dev->last_command); + if (!dev->buffer_pos) + ncr53c8xx_log("(ID=%02i LUN=%02i) SCSI Command 0x%02x: SCSI Command Phase 1 on PHASE_DI\n", id, dev->current_lun, dev->last_command); #endif - ncr53c8xx_write(dev, addr, sd->sc->temp_buffer + dev->buffer_pos, count); + ncr53c8xx_write(dev, addr, sd->sc->temp_buffer + dev->buffer_pos, count); } dev->temp_buf_len -= count; dev->buffer_pos += count; if (dev->temp_buf_len <= 0) { - scsi_device_command_phase1(&scsi_devices[dev->bus][id]); + scsi_device_command_phase1(&scsi_devices[dev->bus][id]); #ifdef ENABLE_NCR53C8XX_LOG - if (out) - ncr53c8xx_log("(ID=%02i LUN=%02i) SCSI Command 0x%02x: SCSI Command Phase 1 on PHASE_DO\n", id, dev->current_lun, dev->last_command); + if (out) + ncr53c8xx_log("(ID=%02i LUN=%02i) SCSI Command 0x%02x: SCSI Command Phase 1 on PHASE_DO\n", id, dev->current_lun, dev->last_command); #endif - ncr53c8xx_command_complete(dev, sd->status); + ncr53c8xx_command_complete(dev, sd->status); } else { - ncr53c8xx_log("(ID=%02i LUN=%02i) SCSI Command 0x%02x: Resume SCRIPTS\n", id, dev->current_lun, dev->last_command); - dev->sstop = 0; + ncr53c8xx_log("(ID=%02i LUN=%02i) SCSI Command 0x%02x: Resume SCRIPTS\n", id, dev->current_lun, dev->last_command); + dev->sstop = 0; } } - /* Queue a byte for a MSG IN phase. */ static void ncr53c8xx_add_msg_byte(ncr53c8xx_t *dev, uint8_t data) { if (dev->msg_len >= NCR_MAX_MSGIN_LEN) - ncr53c8xx_log("MSG IN data too long\n"); + ncr53c8xx_log("MSG IN data too long\n"); else { - ncr53c8xx_log("MSG IN 0x%02x\n", data); - dev->msg[dev->msg_len++] = data; + ncr53c8xx_log("MSG IN 0x%02x\n", data); + dev->msg[dev->msg_len++] = data; } } - static void ncr53c8xx_timer_on(ncr53c8xx_t *dev, scsi_device_t *sd, double p) { @@ -736,30 +722,29 @@ ncr53c8xx_timer_on(ncr53c8xx_t *dev, scsi_device_t *sd, double p) timer_on_auto(&dev->timer, period + 40.0); } - static int ncr53c8xx_do_command(ncr53c8xx_t *dev, uint8_t id) { scsi_device_t *sd; - uint8_t buf[12]; + uint8_t buf[12]; memset(buf, 0, 12); dma_bm_read(dev->dnad, buf, MIN(12, dev->dbc), 4); if (dev->dbc > 12) { - ncr53c8xx_log("(ID=%02i LUN=%02i) SCSI Command 0x%02x: CDB length %i too big\n", id, dev->current_lun, buf[0], dev->dbc); - dev->dbc = 12; + ncr53c8xx_log("(ID=%02i LUN=%02i) SCSI Command 0x%02x: CDB length %i too big\n", id, dev->current_lun, buf[0], dev->dbc); + dev->dbc = 12; } - dev->sfbr = buf[0]; + dev->sfbr = buf[0]; dev->command_complete = 0; sd = &scsi_devices[dev->bus][id]; if (!scsi_device_present(sd) || (dev->current_lun > 0)) { - ncr53c8xx_log("(ID=%02i LUN=%02i) SCSI Command 0x%02x: Bad Selection\n", id, dev->current_lun, buf[0]); - ncr53c8xx_bad_selection(dev, id); - return 0; + ncr53c8xx_log("(ID=%02i LUN=%02i) SCSI Command 0x%02x: Bad Selection\n", id, dev->current_lun, buf[0]); + ncr53c8xx_bad_selection(dev, id); + return 0; } - - dev->current = (ncr53c8xx_request*)malloc(sizeof(ncr53c8xx_request)); + + dev->current = (ncr53c8xx_request *) malloc(sizeof(ncr53c8xx_request)); dev->current->tag = id; sd->buffer_length = -1; @@ -769,47 +754,46 @@ ncr53c8xx_do_command(ncr53c8xx_t *dev, uint8_t id) /* Make sure bits 5-7 of the CDB have the correct LUN. */ if ((buf[1] & 0xe0) != (dev->current_lun << 5)) - buf[1] = (buf[1] & 0x1f) | (dev->current_lun << 5); + buf[1] = (buf[1] & 0x1f) | (dev->current_lun << 5); scsi_device_command_phase0(&scsi_devices[dev->bus][dev->current->tag], buf); - dev->hba_private = (void *)dev->current; + dev->hba_private = (void *) dev->current; - dev->waiting = 0; + dev->waiting = 0; dev->buffer_pos = 0; dev->temp_buf_len = sd->buffer_length; if (sd->buffer_length > 0) { - /* This should be set to the underlying device's buffer by command phase 0. */ - dev->current->dma_len = sd->buffer_length; + /* This should be set to the underlying device's buffer by command phase 0. */ + dev->current->dma_len = sd->buffer_length; } if ((sd->phase == SCSI_PHASE_DATA_IN) && (sd->buffer_length > 0)) { - ncr53c8xx_log("(ID=%02i LUN=%02i) SCSI Command 0x%02x: PHASE_DI\n", id, dev->current_lun, buf[0]); - ncr53c8xx_set_phase(dev, PHASE_DI); - ncr53c8xx_timer_on(dev, sd, scsi_device_get_callback(&scsi_devices[dev->bus][dev->current->tag])); - return 1; + ncr53c8xx_log("(ID=%02i LUN=%02i) SCSI Command 0x%02x: PHASE_DI\n", id, dev->current_lun, buf[0]); + ncr53c8xx_set_phase(dev, PHASE_DI); + ncr53c8xx_timer_on(dev, sd, scsi_device_get_callback(&scsi_devices[dev->bus][dev->current->tag])); + return 1; } else if ((sd->phase == SCSI_PHASE_DATA_OUT) && (sd->buffer_length > 0)) { - ncr53c8xx_log("(ID=%02i LUN=%02i) SCSI Command 0x%02x: PHASE_DO\n", id, buf[0]); - ncr53c8xx_set_phase(dev, PHASE_DO); - ncr53c8xx_timer_on(dev, sd, scsi_device_get_callback(&scsi_devices[dev->bus][dev->current->tag])); - return 1; + ncr53c8xx_log("(ID=%02i LUN=%02i) SCSI Command 0x%02x: PHASE_DO\n", id, buf[0]); + ncr53c8xx_set_phase(dev, PHASE_DO); + ncr53c8xx_timer_on(dev, sd, scsi_device_get_callback(&scsi_devices[dev->bus][dev->current->tag])); + return 1; } else { - ncr53c8xx_command_complete(dev, sd->status); - return 0; + ncr53c8xx_command_complete(dev, sd->status); + return 0; } } - static void ncr53c8xx_do_status(ncr53c8xx_t *dev) { uint8_t status; ncr53c8xx_log("Get status len=%d status=%d\n", dev->dbc, dev->status); if (dev->dbc != 1) - ncr53c8xx_log("Bad Status move\n"); - dev->dbc = 1; - status = dev->status; + ncr53c8xx_log("Bad Status move\n"); + dev->dbc = 1; + status = dev->status; dev->sfbr = status; ncr53c8xx_write(dev, dev->dnad, &status, 1); ncr53c8xx_set_phase(dev, PHASE_MI); @@ -817,7 +801,6 @@ ncr53c8xx_do_status(ncr53c8xx_t *dev) ncr53c8xx_add_msg_byte(dev, 0); /* COMMAND COMPLETE */ } - #ifdef USE_WDTR static void ncr53c8xx_do_wdtr(ncr53c8xx_t *dev, int exponent) @@ -825,55 +808,53 @@ ncr53c8xx_do_wdtr(ncr53c8xx_t *dev, int exponent) ncr53c8xx_log("Target-initiated WDTR (%08X)\n", dev); ncr53c8xx_set_phase(dev, PHASE_MI); dev->msg_action = 4; - ncr53c8xx_add_msg_byte(dev, 0x01); /* EXTENDED MESSAGE */ - ncr53c8xx_add_msg_byte(dev, 0x02); /* EXTENDED MESSAGE LENGTH */ - ncr53c8xx_add_msg_byte(dev, 0x03); /* WIDE DATA TRANSFER REQUEST */ - ncr53c8xx_add_msg_byte(dev, exponent); /* TRANSFER WIDTH EXPONENT (16-bit) */ + ncr53c8xx_add_msg_byte(dev, 0x01); /* EXTENDED MESSAGE */ + ncr53c8xx_add_msg_byte(dev, 0x02); /* EXTENDED MESSAGE LENGTH */ + ncr53c8xx_add_msg_byte(dev, 0x03); /* WIDE DATA TRANSFER REQUEST */ + ncr53c8xx_add_msg_byte(dev, exponent); /* TRANSFER WIDTH EXPONENT (16-bit) */ } #endif - static void ncr53c8xx_do_msgin(ncr53c8xx_t *dev) { uint32_t len; ncr53c8xx_log("Message in len=%d/%d\n", dev->dbc, dev->msg_len); dev->sfbr = dev->msg[0]; - len = dev->msg_len; + len = dev->msg_len; if (len > dev->dbc) - len = dev->dbc; + len = dev->dbc; ncr53c8xx_write(dev, dev->dnad, dev->msg, len); /* Linux drivers rely on the last byte being in the SIDL. */ dev->sidl0 = dev->msg[len - 1]; dev->msg_len -= len; if (dev->msg_len) - memmove(dev->msg, dev->msg + len, dev->msg_len); - else { - /* ??? Check if ATN (not yet implemented) is asserted and maybe - switch to PHASE_MO. */ - switch (dev->msg_action) { - case 0: - ncr53c8xx_set_phase(dev, PHASE_CMD); - break; - case 1: - ncr53c8xx_disconnect(dev); - break; - case 2: - ncr53c8xx_set_phase(dev, PHASE_DO); - break; - case 3: - ncr53c8xx_set_phase(dev, PHASE_DI); - break; - case 4: - ncr53c8xx_set_phase(dev, PHASE_MO); - break; - default: - abort(); - } + memmove(dev->msg, dev->msg + len, dev->msg_len); + else { + /* ??? Check if ATN (not yet implemented) is asserted and maybe + switch to PHASE_MO. */ + switch (dev->msg_action) { + case 0: + ncr53c8xx_set_phase(dev, PHASE_CMD); + break; + case 1: + ncr53c8xx_disconnect(dev); + break; + case 2: + ncr53c8xx_set_phase(dev, PHASE_DO); + break; + case 3: + ncr53c8xx_set_phase(dev, PHASE_DI); + break; + case 4: + ncr53c8xx_set_phase(dev, PHASE_MO); + break; + default: + abort(); + } } } - /* Read the next byte during a MSGOUT phase. */ static uint8_t ncr53c8xx_get_msgbyte(ncr53c8xx_t *dev) @@ -885,18 +866,16 @@ ncr53c8xx_get_msgbyte(ncr53c8xx_t *dev) return data; } - /* Skip the next n bytes during a MSGOUT phase. */ static void ncr53c8xx_skip_msgbytes(ncr53c8xx_t *dev, unsigned int n) { dev->dnad += n; - dev->dbc -= n; + dev->dbc -= n; } - static void -ncr53c8xx_bad_message(ncr53c8xx_t *dev, uint8_t msg) +ncr53c8xx_bad_message(ncr53c8xx_t *dev, UNUSED(uint8_t msg)) { ncr53c8xx_log("Unimplemented message 0x%02x\n", msg); ncr53c8xx_set_phase(dev, PHASE_MI); @@ -904,523 +883,535 @@ ncr53c8xx_bad_message(ncr53c8xx_t *dev, uint8_t msg) dev->msg_action = 0; } - static void ncr53c8xx_do_msgout(ncr53c8xx_t *dev, uint8_t id) { - uint8_t msg; - int len, arg; -#ifdef ENABLE_NCR53C8XX_LOG - uint32_t current_tag; -#endif + uint8_t msg; + int len; + int arg; scsi_device_t *sd; sd = &scsi_devices[dev->bus][id]; -#ifdef ENABLE_NCR53C8XX_LOG - current_tag = id; -#endif - ncr53c8xx_log("MSG out len=%d\n", dev->dbc); while (dev->dbc) { - msg = ncr53c8xx_get_msgbyte(dev); - dev->sfbr = msg; + msg = ncr53c8xx_get_msgbyte(dev); + dev->sfbr = msg; - switch (msg) { - case 0x04: - ncr53c8xx_log("MSG: Disconnect\n"); - ncr53c8xx_disconnect(dev); - break; - case 0x08: - ncr53c8xx_log("MSG: No Operation\n"); - ncr53c8xx_set_phase(dev, PHASE_CMD); - break; - case 0x01: - len = ncr53c8xx_get_msgbyte(dev); - msg = ncr53c8xx_get_msgbyte(dev); - arg = ncr53c8xx_get_msgbyte(dev); - (void) len; /* avoid a warning about unused variable*/ - ncr53c8xx_log("Extended message 0x%x (len %d)\n", msg, len); - switch (msg) { - case 1: - ncr53c8xx_log("SDTR (ignored)\n"); - ncr53c8xx_skip_msgbytes(dev, 1); - break; - case 3: - ncr53c8xx_log("WDTR (ignored)\n"); + switch (msg) { + case 0x04: + ncr53c8xx_log("MSG: Disconnect\n"); + ncr53c8xx_disconnect(dev); + break; + case 0x08: + ncr53c8xx_log("MSG: No Operation\n"); + ncr53c8xx_set_phase(dev, PHASE_CMD); + break; + case 0x01: + len = ncr53c8xx_get_msgbyte(dev); + msg = ncr53c8xx_get_msgbyte(dev); + arg = ncr53c8xx_get_msgbyte(dev); + (void) len; /* avoid a warning about unused variable*/ + ncr53c8xx_log("Extended message 0x%x (len %d)\n", msg, len); + switch (msg) { + case 1: + ncr53c8xx_log("SDTR (ignored)\n"); + ncr53c8xx_skip_msgbytes(dev, 1); + break; + case 3: + ncr53c8xx_log("WDTR (ignored)\n"); #ifdef USE_WDTR - dev->tr_set[dev->sdid] = 1; + dev->tr_set[dev->sdid] = 1; #endif - if (arg > 0x01) { - ncr53c8xx_bad_message(dev, msg); - return; - } - ncr53c8xx_set_phase(dev, PHASE_CMD); - break; - case 5: - ncr53c8xx_log("PPR (ignored)\n"); - ncr53c8xx_skip_msgbytes(dev, 4); - break; - default: - ncr53c8xx_bad_message(dev, msg); - return; - } - break; - case 0x20: /* SIMPLE queue */ - id |= ncr53c8xx_get_msgbyte(dev) | NCR_TAG_VALID; - ncr53c8xx_log("SIMPLE queue tag=0x%x\n", id & 0xff); - break; - case 0x21: /* HEAD of queue */ - ncr53c8xx_log("HEAD queue not implemented\n"); - id |= ncr53c8xx_get_msgbyte(dev) | NCR_TAG_VALID; - break; - case 0x22: /* ORDERED queue */ - ncr53c8xx_log("ORDERED queue not implemented\n"); - id |= ncr53c8xx_get_msgbyte(dev) | NCR_TAG_VALID; - break; - case 0x0d: - /* The ABORT TAG message clears the current I/O process only. */ - ncr53c8xx_log("MSG: Abort Tag\n"); - scsi_device_command_stop(sd); - ncr53c8xx_disconnect(dev); - break; - case 0x0c: - /* BUS DEVICE RESET message, reset wide transfer request. */ + if (arg > 0x01) { + ncr53c8xx_bad_message(dev, msg); + return; + } + ncr53c8xx_set_phase(dev, PHASE_CMD); + break; + case 5: + ncr53c8xx_log("PPR (ignored)\n"); + ncr53c8xx_skip_msgbytes(dev, 4); + break; + default: + ncr53c8xx_bad_message(dev, msg); + return; + } + break; + case 0x20: /* SIMPLE queue */ + id |= ncr53c8xx_get_msgbyte(dev) | NCR_TAG_VALID; + ncr53c8xx_log("SIMPLE queue tag=0x%x\n", id & 0xff); + break; + case 0x21: /* HEAD of queue */ + ncr53c8xx_log("HEAD queue not implemented\n"); + id |= ncr53c8xx_get_msgbyte(dev) | NCR_TAG_VALID; + break; + case 0x22: /* ORDERED queue */ + ncr53c8xx_log("ORDERED queue not implemented\n"); + id |= ncr53c8xx_get_msgbyte(dev) | NCR_TAG_VALID; + break; + case 0x0d: + /* The ABORT TAG message clears the current I/O process only. */ + ncr53c8xx_log("MSG: Abort Tag\n"); + scsi_device_command_stop(sd); + ncr53c8xx_disconnect(dev); + break; + case 0x0c: + /* BUS DEVICE RESET message, reset wide transfer request. */ #ifdef USE_WDTR - dev->tr_set[dev->sdid] = 0; + dev->tr_set[dev->sdid] = 0; #endif - /* FALLTHROUGH */ - case 0x06: - case 0x0e: - /* clear the current I/O process */ - scsi_device_command_stop(sd); - ncr53c8xx_disconnect(dev); - break; - default: - if ((msg & 0x80) == 0) { - ncr53c8xx_bad_message(dev, msg); - return; - } else { - /* 0x80 to 0xff are IDENTIFY messages. */ - ncr53c8xx_log("MSG: Identify\n"); - dev->current_lun = msg & 7; - scsi_device_identify(sd, msg & 7); - ncr53c8xx_log("Select LUN %d\n", dev->current_lun); + /* FALLTHROUGH */ + case 0x06: + case 0x0e: + /* clear the current I/O process */ + scsi_device_command_stop(sd); + ncr53c8xx_disconnect(dev); + break; + default: + if ((msg & 0x80) == 0) { + ncr53c8xx_bad_message(dev, msg); + return; + } else { + /* 0x80 to 0xff are IDENTIFY messages. */ + ncr53c8xx_log("MSG: Identify\n"); + dev->current_lun = msg & 7; + scsi_device_identify(sd, msg & 7); + ncr53c8xx_log("Select LUN %d\n", dev->current_lun); #ifdef USE_WDTR - if ((dev->chip == CHIP_875) && !dev->tr_set[dev->sdid]) - ncr53c8xx_do_wdtr(dev, 0x01); - else + if ((dev->chip == CHIP_875) && !dev->tr_set[dev->sdid]) + ncr53c8xx_do_wdtr(dev, 0x01); + else #endif - ncr53c8xx_set_phase(dev, PHASE_CMD); - } - break; - } + ncr53c8xx_set_phase(dev, PHASE_CMD); + } + break; + } } } - static void ncr53c8xx_memcpy(ncr53c8xx_t *dev, uint32_t dest, uint32_t src, int count) { - int n; + int n; uint8_t buf[NCR_BUF_SIZE]; ncr53c8xx_log("memcpy dest 0x%08x src 0x%08x count %d\n", dest, src, count); while (count) { - n = (count > NCR_BUF_SIZE) ? NCR_BUF_SIZE : count; - ncr53c8xx_read(dev, src, buf, n); - ncr53c8xx_write(dev, dest, buf, n); - src += n; - dest += n; - count -= n; + n = (count > NCR_BUF_SIZE) ? NCR_BUF_SIZE : count; + ncr53c8xx_read(dev, src, buf, n); + ncr53c8xx_write(dev, dest, buf, n); + src += n; + dest += n; + count -= n; } } - static void ncr53c8xx_process_script(ncr53c8xx_t *dev) { - uint32_t insn, addr, id, buf[2], dest; - int opcode, insn_processed = 0, reg, operator, cond, jmp, n, i, c; - int32_t offset; - uint8_t op0, op1, data8, mask, data[7]; -#ifdef ENABLE_NCR53C8XX_LOG - uint8_t *pp; -#endif + uint32_t insn; + uint32_t addr; + uint32_t id; + uint32_t buf[2]; + uint32_t dest; + int opcode; + int insn_processed = 0; + int reg; + int operator; + int cond; + int jmp; + int n; + int i; + int c; + int32_t offset; + uint8_t op0; + uint8_t op1; + uint8_t data8; + uint8_t mask; + uint8_t data[7]; dev->sstop = 0; again: insn_processed++; insn = read_dword(dev, dev->dsp); if (!insn) { - /* If we receive an empty opcode increment the DSP by 4 bytes - instead of 8 and execute the next opcode at that location */ - dev->dsp += 4; - if (insn_processed < 100) - goto again; - else { - timer_on_auto(&dev->timer, 10.0); - return; - } + /* If we receive an empty opcode increment the DSP by 4 bytes + instead of 8 and execute the next opcode at that location */ + dev->dsp += 4; + if (insn_processed < 100) + goto again; + else { + timer_on_auto(&dev->timer, 10.0); + return; + } } addr = read_dword(dev, dev->dsp + 4); ncr53c8xx_log("SCRIPTS dsp=%08x opcode %08x arg %08x\n", dev->dsp, insn, addr); dev->dsps = addr; dev->dcmd = insn >> 24; dev->dsp += 8; - + switch (insn >> 30) { - case 0: /* Block move. */ - ncr53c8xx_log("00: Block move\n"); - if (dev->sist1 & NCR_SIST1_STO) { - ncr53c8xx_log("Delayed select timeout\n"); - dev->sstop = 1; - break; - } - ncr53c8xx_log("Block Move DBC=%d\n", dev->dbc); - dev->dbc = insn & 0xffffff; - ncr53c8xx_log("Block Move DBC=%d now\n", dev->dbc); - /* ??? Set ESA. */ - if (insn & (1 << 29)) { - /* Indirect addressing. */ - /* Should this respect SIOM? */ - addr = read_dword(dev, addr); - ncr53c8xx_log("Indirect Block Move address: %08X\n", addr); - } else if (insn & (1 << 28)) { - /* Table indirect addressing. */ + case 0: /* Block move. */ + ncr53c8xx_log("00: Block move\n"); + if (dev->sist1 & NCR_SIST1_STO) { + ncr53c8xx_log("Delayed select timeout\n"); + dev->sstop = 1; + break; + } + ncr53c8xx_log("Block Move DBC=%d\n", dev->dbc); + dev->dbc = insn & 0xffffff; + ncr53c8xx_log("Block Move DBC=%d now\n", dev->dbc); + /* ??? Set ESA. */ + if (insn & (1 << 29)) { + /* Indirect addressing. */ + /* Should this respect SIOM? */ + addr = read_dword(dev, addr); + ncr53c8xx_log("Indirect Block Move address: %08X\n", addr); + } else if (insn & (1 << 28)) { + /* Table indirect addressing. */ - /* 32-bit Table indirect */ - offset = sextract32(addr, 0, 24); - dma_bm_read(dev->dsa + offset, (uint8_t *)buf, 8, 4); - /* byte count is stored in bits 0:23 only */ - dev->dbc = buf[0] & 0xffffff; - addr = buf[1]; + /* 32-bit Table indirect */ + offset = sextract32(addr, 0, 24); + dma_bm_read(dev->dsa + offset, (uint8_t *) buf, 8, 4); + /* byte count is stored in bits 0:23 only */ + dev->dbc = buf[0] & 0xffffff; + addr = buf[1]; - /* 40-bit DMA, upper addr bits [39:32] stored in first DWORD of - * table, bits [31:24] */ - } - if ((dev->sstat1 & PHASE_MASK) != ((insn >> 24) & 7)) { - ncr53c8xx_log("Wrong phase got %d expected %d\n", - dev->sstat1 & PHASE_MASK, (insn >> 24) & 7); - ncr53c8xx_script_scsi_interrupt(dev, NCR_SIST0_MA, 0); - break; - } - dev->dnad = addr; - switch (dev->sstat1 & 0x7) { - case PHASE_DO: - ncr53c8xx_log("Data Out Phase\n"); - dev->waiting = 0; - ncr53c8xx_do_dma(dev, 1, dev->sdid); - break; - case PHASE_DI: - ncr53c8xx_log("Data In Phase\n"); - dev->waiting = 0; - ncr53c8xx_do_dma(dev, 0, dev->sdid); - break; - case PHASE_CMD: - ncr53c8xx_log("Command Phase\n"); - c = ncr53c8xx_do_command(dev, dev->sdid); + /* 40-bit DMA, upper addr bits [39:32] stored in first DWORD of + * table, bits [31:24] */ + } + if ((dev->sstat1 & PHASE_MASK) != ((insn >> 24) & 7)) { + ncr53c8xx_log("Wrong phase got %d expected %d\n", + dev->sstat1 & PHASE_MASK, (insn >> 24) & 7); + ncr53c8xx_script_scsi_interrupt(dev, NCR_SIST0_MA, 0); + break; + } + dev->dnad = addr; + switch (dev->sstat1 & 0x7) { + case PHASE_DO: + ncr53c8xx_log("Data Out Phase\n"); + dev->waiting = 0; + ncr53c8xx_do_dma(dev, 1, dev->sdid); + break; + case PHASE_DI: + ncr53c8xx_log("Data In Phase\n"); + dev->waiting = 0; + ncr53c8xx_do_dma(dev, 0, dev->sdid); + break; + case PHASE_CMD: + ncr53c8xx_log("Command Phase\n"); + c = ncr53c8xx_do_command(dev, dev->sdid); - if (!c || dev->sstop || dev->waiting || ((dev->sstat1 & 0x7) == PHASE_ST)) - break; + if (!c || dev->sstop || dev->waiting || ((dev->sstat1 & 0x7) == PHASE_ST)) + break; - dev->dfifo = dev->dbc & 0xff; - dev->ctest5 = (dev->ctest5 & 0xfc) | ((dev->dbc >> 8) & 3); + dev->dfifo = dev->dbc & 0xff; + dev->ctest5 = (dev->ctest5 & 0xfc) | ((dev->dbc >> 8) & 3); - if (dev->dcntl & NCR_DCNTL_SSM) - ncr53c8xx_script_dma_interrupt(dev, NCR_DSTAT_SSI); - return; - case PHASE_ST: - ncr53c8xx_log("Status Phase\n"); - ncr53c8xx_do_status(dev); - break; - case PHASE_MO: - ncr53c8xx_log("MSG Out Phase\n"); - ncr53c8xx_do_msgout(dev, dev->sdid); - break; - case PHASE_MI: - ncr53c8xx_log("MSG In Phase\n"); - ncr53c8xx_do_msgin(dev); - break; - default: - ncr53c8xx_log("Unimplemented phase %d\n", dev->sstat1 & PHASE_MASK); - } - dev->dfifo = dev->dbc & 0xff; - dev->ctest5 = (dev->ctest5 & 0xfc) | ((dev->dbc >> 8) & 3); - break; + if (dev->dcntl & NCR_DCNTL_SSM) + ncr53c8xx_script_dma_interrupt(dev, NCR_DSTAT_SSI); + return; + case PHASE_ST: + ncr53c8xx_log("Status Phase\n"); + ncr53c8xx_do_status(dev); + break; + case PHASE_MO: + ncr53c8xx_log("MSG Out Phase\n"); + ncr53c8xx_do_msgout(dev, dev->sdid); + break; + case PHASE_MI: + ncr53c8xx_log("MSG In Phase\n"); + ncr53c8xx_do_msgin(dev); + break; + default: + ncr53c8xx_log("Unimplemented phase %d\n", dev->sstat1 & PHASE_MASK); + } + dev->dfifo = dev->dbc & 0xff; + dev->ctest5 = (dev->ctest5 & 0xfc) | ((dev->dbc >> 8) & 3); + break; - case 1: /* IO or Read/Write instruction. */ - ncr53c8xx_log("01: I/O or Read/Write instruction\n"); - opcode = (insn >> 27) & 7; - if (opcode < 5) { - if (insn & (1 << 25)) - id = read_dword(dev, dev->dsa + sextract32(insn, 0, 24)); - else - id = insn; - id = (id >> 16) & 0xf; - if (insn & (1 << 26)) - addr = dev->dsp + sextract32(addr, 0, 24); - dev->dnad = addr; - switch (opcode) { - case 0: /* Select */ - dev->sdid = id; - if (dev->scntl1 & NCR_SCNTL1_CON) { - ncr53c8xx_log("Already reselected, jumping to alternative address\n"); - dev->dsp = dev->dnad; - break; - } - dev->sstat0 |= NCR_SSTAT0_WOA; - dev->scntl1 &= ~NCR_SCNTL1_IARB; - if (!scsi_device_present(&scsi_devices[dev->bus][id])) { - ncr53c8xx_bad_selection(dev, id); - break; - } - ncr53c8xx_log("Selected target %d%s\n", - id, insn & (1 << 24) ? " ATN" : ""); - dev->scntl1 |= NCR_SCNTL1_CON; - if (insn & (1 << 24)) - dev->socl |= NCR_SOCL_ATN; - ncr53c8xx_set_phase(dev, PHASE_MO); - dev->waiting = 0; - break; - case 1: /* Disconnect */ - ncr53c8xx_log("Wait Disconnect\n"); - dev->scntl1 &= ~NCR_SCNTL1_CON; - break; - case 2: /* Wait Reselect */ - ncr53c8xx_log("Wait Reselect\n"); - if (dev->istat & NCR_ISTAT_SIGP) - dev->dsp = dev->dnad; /* If SIGP is set, this command causes an immediate jump to DNAD. */ - else { - if (!ncr53c8xx_irq_on_rsl(dev)) - dev->waiting = 1; - } - break; - case 3: /* Set */ - ncr53c8xx_log("Set%s%s%s%s\n", insn & (1 << 3) ? " ATN" : "", - insn & (1 << 6) ? " ACK" : "", - insn & (1 << 9) ? " TM" : "", - insn & (1 << 10) ? " CC" : ""); - if (insn & (1 << 3)) { - dev->socl |= NCR_SOCL_ATN; - ncr53c8xx_set_phase(dev, PHASE_MO); - } - if (insn & (1 << 9)) - ncr53c8xx_log("Target mode not implemented\n"); - if (insn & (1 << 10)) - dev->carry = 1; - break; - case 4: /* Clear */ - ncr53c8xx_log("Clear%s%s%s%s\n", insn & (1 << 3) ? " ATN" : "", - insn & (1 << 6) ? " ACK" : "", - insn & (1 << 9) ? " TM" : "", - insn & (1 << 10) ? " CC" : ""); - if (insn & (1 << 3)) - dev->socl &= ~NCR_SOCL_ATN; - if (insn & (1 << 10)) - dev->carry = 0; - break; - } - } else { - reg = ((insn >> 16) & 0x7f) | (insn & 0x80); - data8 = (insn >> 8) & 0xff; - opcode = (insn >> 27) & 7; - operator = (insn >> 24) & 7; - op0 = op1 = 0; - switch (opcode) { - case 5: /* From SFBR */ - op0 = dev->sfbr; - op1 = data8; - break; - case 6: /* To SFBR */ - if (operator) - op0 = ncr53c8xx_reg_readb(dev, reg); - op1 = data8; - break; - case 7: /* Read-modify-write */ - if (operator) - op0 = ncr53c8xx_reg_readb(dev, reg); - if (insn & (1 << 23)) - op1 = dev->sfbr; - else - op1 = data8; - break; - } + case 1: /* IO or Read/Write instruction. */ + ncr53c8xx_log("01: I/O or Read/Write instruction\n"); + opcode = (insn >> 27) & 7; + if (opcode < 5) { + if (insn & (1 << 25)) + id = read_dword(dev, dev->dsa + sextract32(insn, 0, 24)); + else + id = insn; + id = (id >> 16) & 0xf; + if (insn & (1 << 26)) + addr = dev->dsp + sextract32(addr, 0, 24); + dev->dnad = addr; + switch (opcode) { + case 0: /* Select */ + dev->sdid = id; + if (dev->scntl1 & NCR_SCNTL1_CON) { + ncr53c8xx_log("Already reselected, jumping to alternative address\n"); + dev->dsp = dev->dnad; + break; + } + dev->sstat0 |= NCR_SSTAT0_WOA; + dev->scntl1 &= ~NCR_SCNTL1_IARB; + if (!scsi_device_present(&scsi_devices[dev->bus][id])) { + ncr53c8xx_bad_selection(dev, id); + break; + } + ncr53c8xx_log("Selected target %d%s\n", + id, insn & (1 << 24) ? " ATN" : ""); + dev->scntl1 |= NCR_SCNTL1_CON; + if (insn & (1 << 24)) + dev->socl |= NCR_SOCL_ATN; + ncr53c8xx_set_phase(dev, PHASE_MO); + dev->waiting = 0; + break; + case 1: /* Disconnect */ + ncr53c8xx_log("Wait Disconnect\n"); + dev->scntl1 &= ~NCR_SCNTL1_CON; + break; + case 2: /* Wait Reselect */ + ncr53c8xx_log("Wait Reselect\n"); + if (dev->istat & NCR_ISTAT_SIGP) + dev->dsp = dev->dnad; /* If SIGP is set, this command causes an immediate jump to DNAD. */ + else { + if (!ncr53c8xx_irq_on_rsl(dev)) + dev->waiting = 1; + } + break; + case 3: /* Set */ + ncr53c8xx_log("Set%s%s%s%s\n", insn & (1 << 3) ? " ATN" : "", + insn & (1 << 6) ? " ACK" : "", + insn & (1 << 9) ? " TM" : "", + insn & (1 << 10) ? " CC" : ""); + if (insn & (1 << 3)) { + dev->socl |= NCR_SOCL_ATN; + ncr53c8xx_set_phase(dev, PHASE_MO); + } + if (insn & (1 << 9)) + ncr53c8xx_log("Target mode not implemented\n"); + if (insn & (1 << 10)) + dev->carry = 1; + break; + case 4: /* Clear */ + ncr53c8xx_log("Clear%s%s%s%s\n", insn & (1 << 3) ? " ATN" : "", + insn & (1 << 6) ? " ACK" : "", + insn & (1 << 9) ? " TM" : "", + insn & (1 << 10) ? " CC" : ""); + if (insn & (1 << 3)) + dev->socl &= ~NCR_SOCL_ATN; + if (insn & (1 << 10)) + dev->carry = 0; + break; - switch (operator) { - case 0: /* move */ - op0 = op1; - break; - case 1: /* Shift left */ - op1 = op0 >> 7; - op0 = (op0 << 1) | dev->carry; - dev->carry = op1; - break; - case 2: /* OR */ - op0 |= op1; - break; - case 3: /* XOR */ - op0 ^= op1; - break; - case 4: /* AND */ - op0 &= op1; - break; - case 5: /* SHR */ - op1 = op0 & 1; - op0 = (op0 >> 1) | (dev->carry << 7); - dev->carry = op1; - break; - case 6: /* ADD */ - op0 += op1; - dev->carry = op0 < op1; - break; - case 7: /* ADC */ - op0 += op1 + dev->carry; - if (dev->carry) - dev->carry = op0 <= op1; - else - dev->carry = op0 < op1; - break; - } + default: + break; + } + } else { + reg = ((insn >> 16) & 0x7f) | (insn & 0x80); + data8 = (insn >> 8) & 0xff; + opcode = (insn >> 27) & 7; + operator=(insn >> 24) & 7; + op0 = op1 = 0; + switch (opcode) { + case 5: /* From SFBR */ + op0 = dev->sfbr; + op1 = data8; + break; + case 6: /* To SFBR */ + if (operator) + op0 = ncr53c8xx_reg_readb(dev, reg); + op1 = data8; + break; + case 7: /* Read-modify-write */ + if (operator) + op0 = ncr53c8xx_reg_readb(dev, reg); + if (insn & (1 << 23)) + op1 = dev->sfbr; + else + op1 = data8; + break; - switch (opcode) { - case 5: /* From SFBR */ - case 7: /* Read-modify-write */ - ncr53c8xx_reg_writeb(dev, reg, op0); - break; - case 6: /* To SFBR */ - dev->sfbr = op0; - break; - } - } - break; + default: + break; + } - case 2: /* Transfer Control. */ - ncr53c8xx_log("02: Transfer Control\n"); - if ((insn & 0x002e0000) == 0) { - ncr53c8xx_log("NOP\n"); - break; - } - if (dev->sist1 & NCR_SIST1_STO) { - ncr53c8xx_log("Delayed select timeout\n"); - dev->sstop = 1; - break; - } - cond = jmp = (insn & (1 << 19)) != 0; - if (cond == jmp && (insn & (1 << 21))) { - ncr53c8xx_log("Compare carry %d\n", dev->carry == jmp); - cond = dev->carry != 0; - } - if (cond == jmp && (insn & (1 << 17))) { - ncr53c8xx_log("Compare phase %d %c= %d\n", (dev->sstat1 & PHASE_MASK), - jmp ? '=' : '!', ((insn >> 24) & 7)); - cond = (dev->sstat1 & PHASE_MASK) == ((insn >> 24) & 7); - } - if (cond == jmp && (insn & (1 << 18))) { - mask = (~insn >> 8) & 0xff; - ncr53c8xx_log("Compare data 0x%x & 0x%x %c= 0x%x\n", dev->sfbr, mask, - jmp ? '=' : '!', insn & mask); - cond = (dev->sfbr & mask) == (insn & mask); - } - if (cond == jmp) { - if (insn & (1 << 23)) { - /* Relative address. */ - addr = dev->dsp + sextract32(addr, 0, 24); - } - switch ((insn >> 27) & 7) { - case 0: /* Jump */ - ncr53c8xx_log("Jump to 0x%08x\n", addr); - dev->adder = addr; - dev->dsp = addr; - break; - case 1: /* Call */ - ncr53c8xx_log("Call 0x%08x\n", addr); - dev->temp = dev->dsp; - dev->dsp = addr; - break; - case 2: /* Return */ - ncr53c8xx_log("Return to 0x%08x\n", dev->temp); - dev->dsp = dev->temp; - break; - case 3: /* Interrupt */ - ncr53c8xx_log("Interrupt 0x%08x\n", dev->dsps); - if ((insn & (1 << 20)) != 0) { - dev->istat |= NCR_ISTAT_INTF; - ncr53c8xx_update_irq(dev); - } else - ncr53c8xx_script_dma_interrupt(dev, NCR_DSTAT_SIR); - break; - default: - ncr53c8xx_log("Illegal transfer control\n"); - ncr53c8xx_script_dma_interrupt(dev, NCR_DSTAT_IID); - break; - } - } else - ncr53c8xx_log("Control condition failed\n"); - break; + switch (operator) { + case 0: /* move */ + op0 = op1; + break; + case 1: /* Shift left */ + op1 = op0 >> 7; + op0 = (op0 << 1) | dev->carry; + dev->carry = op1; + break; + case 2: /* OR */ + op0 |= op1; + break; + case 3: /* XOR */ + op0 ^= op1; + break; + case 4: /* AND */ + op0 &= op1; + break; + case 5: /* SHR */ + op1 = op0 & 1; + op0 = (op0 >> 1) | (dev->carry << 7); + dev->carry = op1; + break; + case 6: /* ADD */ + op0 += op1; + dev->carry = op0 < op1; + break; + case 7: /* ADC */ + op0 += op1 + dev->carry; + if (dev->carry) + dev->carry = op0 <= op1; + else + dev->carry = op0 < op1; + break; - case 3: - ncr53c8xx_log("00: Memory move\n"); - if ((insn & (1 << 29)) == 0) { - /* Memory move. */ - /* ??? The docs imply the destination address is loaded into - the TEMP register. However the Linux drivers rely on - the value being presrved. */ - dest = read_dword(dev, dev->dsp); - dev->dsp += 4; - ncr53c8xx_memcpy(dev, dest, addr, insn & 0xffffff); - } else { -#ifdef ENABLE_NCR53C8XX_LOG - pp = data; -#endif + default: + break; + } - if (insn & (1 << 28)) - addr = dev->dsa + sextract32(addr, 0, 24); - n = (insn & 7); - reg = (insn >> 16) & 0xff; - if (insn & (1 << 24)) { - dma_bm_read(addr, data, n, 4); - for (i = 0; i < n; i++) - ncr53c8xx_reg_writeb(dev, reg + i, data[i]); - } else { - ncr53c8xx_log("Store reg 0x%x size %d addr 0x%08x\n", reg, n, addr); - for (i = 0; i < n; i++) - data[i] = ncr53c8xx_reg_readb(dev, reg + i); - dma_bm_write(addr, data, n, 4); - } - } - break; + switch (opcode) { + case 5: /* From SFBR */ + case 7: /* Read-modify-write */ + ncr53c8xx_reg_writeb(dev, reg, op0); + break; + case 6: /* To SFBR */ + dev->sfbr = op0; + break; - default: - ncr53c8xx_log("%02X: Unknown command\n", (uint8_t) (insn >> 30)); + default: + break; + } + } + break; + + case 2: /* Transfer Control. */ + ncr53c8xx_log("02: Transfer Control\n"); + if ((insn & 0x002e0000) == 0) { + ncr53c8xx_log("NOP\n"); + break; + } + if (dev->sist1 & NCR_SIST1_STO) { + ncr53c8xx_log("Delayed select timeout\n"); + dev->sstop = 1; + break; + } + cond = jmp = (insn & (1 << 19)) != 0; + if (cond == jmp && (insn & (1 << 21))) { + ncr53c8xx_log("Compare carry %d\n", dev->carry == jmp); + cond = dev->carry != 0; + } + if (cond == jmp && (insn & (1 << 17))) { + ncr53c8xx_log("Compare phase %d %c= %d\n", (dev->sstat1 & PHASE_MASK), + jmp ? '=' : '!', ((insn >> 24) & 7)); + cond = (dev->sstat1 & PHASE_MASK) == ((insn >> 24) & 7); + } + if (cond == jmp && (insn & (1 << 18))) { + mask = (~insn >> 8) & 0xff; + ncr53c8xx_log("Compare data 0x%x & 0x%x %c= 0x%x\n", dev->sfbr, mask, + jmp ? '=' : '!', insn & mask); + cond = (dev->sfbr & mask) == (insn & mask); + } + if (cond == jmp) { + if (insn & (1 << 23)) { + /* Relative address. */ + addr = dev->dsp + sextract32(addr, 0, 24); + } + switch ((insn >> 27) & 7) { + case 0: /* Jump */ + ncr53c8xx_log("Jump to 0x%08x\n", addr); + dev->adder = addr; + dev->dsp = addr; + break; + case 1: /* Call */ + ncr53c8xx_log("Call 0x%08x\n", addr); + dev->temp = dev->dsp; + dev->dsp = addr; + break; + case 2: /* Return */ + ncr53c8xx_log("Return to 0x%08x\n", dev->temp); + dev->dsp = dev->temp; + break; + case 3: /* Interrupt */ + ncr53c8xx_log("Interrupt 0x%08x\n", dev->dsps); + if ((insn & (1 << 20)) != 0) { + dev->istat |= NCR_ISTAT_INTF; + ncr53c8xx_update_irq(dev); + } else + ncr53c8xx_script_dma_interrupt(dev, NCR_DSTAT_SIR); + break; + default: + ncr53c8xx_log("Illegal transfer control\n"); + ncr53c8xx_script_dma_interrupt(dev, NCR_DSTAT_IID); + break; + } + } else + ncr53c8xx_log("Control condition failed\n"); + break; + + case 3: + ncr53c8xx_log("00: Memory move\n"); + if ((insn & (1 << 29)) == 0) { + /* Memory move. */ + /* ??? The docs imply the destination address is loaded into + the TEMP register. However the Linux drivers rely on + the value being presrved. */ + dest = read_dword(dev, dev->dsp); + dev->dsp += 4; + ncr53c8xx_memcpy(dev, dest, addr, insn & 0xffffff); + } else { + if (insn & (1 << 28)) + addr = dev->dsa + sextract32(addr, 0, 24); + n = (insn & 7); + reg = (insn >> 16) & 0xff; + if (insn & (1 << 24)) { + dma_bm_read(addr, data, n, 4); + for (i = 0; i < n; i++) + ncr53c8xx_reg_writeb(dev, reg + i, data[i]); + } else { + ncr53c8xx_log("Store reg 0x%x size %d addr 0x%08x\n", reg, n, addr); + for (i = 0; i < n; i++) + data[i] = ncr53c8xx_reg_readb(dev, reg + i); + dma_bm_write(addr, data, n, 4); + } + } + break; + + default: + ncr53c8xx_log("%02X: Unknown command\n", (uint8_t) (insn >> 30)); } ncr53c8xx_log("instructions processed %i\n", insn_processed); if (insn_processed > 10000 && !dev->waiting) { - /* Some windows drivers make the device spin waiting for a memory - location to change. If we have been executed a lot of code then - assume this is the case and force an unexpected device disconnect. - This is apparently sufficient to beat the drivers into submission. - */ - ncr53c8xx_log("Some windows drivers make the device spin...\n"); - if (!(dev->sien0 & NCR_SIST0_UDC)) - ncr53c8xx_log("inf. loop with UDC masked\n"); - ncr53c8xx_script_scsi_interrupt(dev, NCR_SIST0_UDC, 0); - ncr53c8xx_disconnect(dev); + /* Some windows drivers make the device spin waiting for a memory + location to change. If we have been executed a lot of code then + assume this is the case and force an unexpected device disconnect. + This is apparently sufficient to beat the drivers into submission. + */ + ncr53c8xx_log("Some windows drivers make the device spin...\n"); + if (!(dev->sien0 & NCR_SIST0_UDC)) + ncr53c8xx_log("inf. loop with UDC masked\n"); + ncr53c8xx_script_scsi_interrupt(dev, NCR_SIST0_UDC, 0); + ncr53c8xx_disconnect(dev); } else if (!dev->sstop && !dev->waiting) { - if (dev->dcntl & NCR_DCNTL_SSM) { - ncr53c8xx_log("NCR 810: SCRIPTS: Single-step mode\n"); - ncr53c8xx_script_dma_interrupt(dev, NCR_DSTAT_SSI); - } else { - ncr53c8xx_log("NCR 810: SCRIPTS: Normal mode\n"); - if (insn_processed < 100) - goto again; - } + if (dev->dcntl & NCR_DCNTL_SSM) { + ncr53c8xx_log("NCR 810: SCRIPTS: Single-step mode\n"); + ncr53c8xx_script_dma_interrupt(dev, NCR_DSTAT_SSI); + } else { + ncr53c8xx_log("NCR 810: SCRIPTS: Normal mode\n"); + if (insn_processed < 100) + goto again; + } } else { - if (dev->sstop) - ncr53c8xx_log("NCR 810: SCRIPTS: Stopped\n"); - if (dev->waiting) - ncr53c8xx_log("NCR 810: SCRIPTS: Waiting\n"); + if (dev->sstop) + ncr53c8xx_log("NCR 810: SCRIPTS: Stopped\n"); + if (dev->waiting) + ncr53c8xx_log("NCR 810: SCRIPTS: Waiting\n"); } timer_on_auto(&dev->timer, 40.0); @@ -1428,7 +1419,6 @@ again: ncr53c8xx_log("SCRIPTS execution stopped\n"); } - static void ncr53c8xx_execute_script(ncr53c8xx_t *dev) { @@ -1436,55 +1426,73 @@ ncr53c8xx_execute_script(ncr53c8xx_t *dev) timer_on_auto(&dev->timer, 40.0); } - static void -ncr53c8xx_callback(void *p) +ncr53c8xx_callback(void *priv) { - ncr53c8xx_t *dev = (ncr53c8xx_t *) p; + ncr53c8xx_t *dev = (ncr53c8xx_t *) priv; if (!dev->sstop) { - if (dev->waiting) - timer_on_auto(&dev->timer, 40.0); - else - ncr53c8xx_process_script(dev); + if (dev->waiting) + timer_on_auto(&dev->timer, 40.0); + else + ncr53c8xx_process_script(dev); } if (dev->sstop) - timer_stop(&dev->timer); + timer_stop(&dev->timer); } - static void ncr53c8xx_eeprom(ncr53c8xx_t *dev, uint8_t save) { - FILE *f; + FILE *fp; - f = nvr_fopen(dev->nvr_path, save ? "wb": "rb"); - if (f) { - if (save) - fwrite(&dev->nvram, sizeof(dev->nvram), 1, f); - else - fread(&dev->nvram, sizeof(dev->nvram), 1, f); - fclose(f); + fp = nvr_fopen(dev->nvr_path, save ? "wb" : "rb"); + if (fp) { + if (save) + fwrite(&dev->nvram, sizeof(dev->nvram), 1, fp); + else + (void) !fread(&dev->nvram, sizeof(dev->nvram), 1, fp); + fclose(fp); } } - static void ncr53c8xx_reg_writeb(ncr53c8xx_t *dev, uint32_t offset, uint8_t val) { uint8_t tmp = 0; #define CASE_SET_REG24(name, addr) \ - case addr : dev->name &= 0xffffff00; dev->name |= val; break; \ - case addr + 1: dev->name &= 0xffff00ff; dev->name |= val << 8; break; \ - case addr + 2: dev->name &= 0xff00ffff; dev->name |= val << 16; break; + case addr: \ + dev->name &= 0xffffff00; \ + dev->name |= val; \ + break; \ + case addr + 1: \ + dev->name &= 0xffff00ff; \ + dev->name |= val << 8; \ + break; \ + case addr + 2: \ + dev->name &= 0xff00ffff; \ + dev->name |= val << 16; \ + break; #define CASE_SET_REG32(name, addr) \ - case addr : dev->name &= 0xffffff00; dev->name |= val; break; \ - case addr + 1: dev->name &= 0xffff00ff; dev->name |= val << 8; break; \ - case addr + 2: dev->name &= 0xff00ffff; dev->name |= val << 16; break; \ - case addr + 3: dev->name &= 0x00ffffff; dev->name |= val << 24; break; + case addr: \ + dev->name &= 0xffffff00; \ + dev->name |= val; \ + break; \ + case addr + 1: \ + dev->name &= 0xffff00ff; \ + dev->name |= val << 8; \ + break; \ + case addr + 2: \ + dev->name &= 0xff00ffff; \ + dev->name |= val << 16; \ + break; \ + case addr + 3: \ + dev->name &= 0x00ffffff; \ + dev->name |= val << 24; \ + break; #ifdef DEBUG_NCR_REG ncr53c8xx_log("Write reg %02x = %02x\n", offset, val); @@ -1493,493 +1501,512 @@ ncr53c8xx_reg_writeb(ncr53c8xx_t *dev, uint32_t offset, uint8_t val) dev->regop = 1; switch (offset) { - case 0x00: /* SCNTL0 */ - dev->scntl0 = val; - if (val & NCR_SCNTL0_START) { - /* Looks like this (turn on bit 4 of SSTAT0 to mark arbitration in progress) - is enough to make BIOS v4.x happy. */ - ncr53c8xx_log("NCR 810: Selecting SCSI ID %i\n", dev->sdid); - dev->sstat0 |= 0x10; - } - break; - case 0x01: /* SCNTL1 */ - dev->scntl1 = val & ~NCR_SCNTL1_SST; - if (val & NCR_SCNTL1_IARB) { - ncr53c8xx_log("Arbitration lost\n"); - dev->sstat0 |= 0x08; - dev->waiting = 0; - } - if (val & NCR_SCNTL1_RST) { - if (!(dev->sstat0 & NCR_SSTAT0_RST)) { - dev->sstat0 |= NCR_SSTAT0_RST; - ncr53c8xx_script_scsi_interrupt(dev, NCR_SIST0_RST, 0); - } - } else - dev->sstat0 &= ~NCR_SSTAT0_RST; - break; - case 0x02: /* SCNTL2 */ - val &= ~(NCR_SCNTL2_WSR | NCR_SCNTL2_WSS); - dev->scntl2 = val; - break; - case 0x03: /* SCNTL3 */ - dev->scntl3 = val; - break; - case 0x04: /* SCID */ - dev->scid = val; - break; - case 0x05: /* SXFER */ - dev->sxfer = val; - break; - case 0x06: /* SDID */ - if ((dev->ssid & 0x80) && (val & 0xf) != (dev->ssid & 0xf)) - ncr53c8xx_log("Destination ID does not match SSID\n"); - dev->sdid = val & 0xf; - break; - case 0x07: /* GPREG */ - ncr53c8xx_log("NCR 810: GPREG write %02X\n", val); - dev->gpreg = val; - i2c_gpio_set(dev->i2c, (dev->gpreg & 0x02) || ((dev->gpcntl & 0x82) == 0x02), (dev->gpreg & 0x01) || ((dev->gpcntl & 0x41) == 0x01)); - break; - case 0x08: /* SFBR */ - /* The CPU is not allowed to write to this register. However the - SCRIPTS register move instructions are. */ - dev->sfbr = val; - break; - case 0x09: /* SOCL */ - ncr53c8xx_log("NCR 810: SOCL write %02X\n", val); - dev->socl = val; - break; - case 0x0a: case 0x0b: - /* Openserver writes to these readonly registers on startup */ - return; - case 0x0c: case 0x0d: case 0x0e: case 0x0f: - /* Linux writes to these readonly registers on startup. */ - return; - CASE_SET_REG32(dsa, 0x10) - case 0x14: /* ISTAT */ - ncr53c8xx_log("ISTAT write: %02X\n", val); - tmp = dev->istat; - dev->istat = (dev->istat & 0x0f) | (val & 0xf0); - if ((val & NCR_ISTAT_ABRT) && !(val & NCR_ISTAT_SRST)) - ncr53c8xx_script_dma_interrupt(dev, NCR_DSTAT_ABRT); - if (val & NCR_ISTAT_INTF) { - dev->istat &= ~NCR_ISTAT_INTF; - ncr53c8xx_update_irq(dev); - } + case 0x00: /* SCNTL0 */ + dev->scntl0 = val; + if (val & NCR_SCNTL0_START) { + /* Looks like this (turn on bit 4 of SSTAT0 to mark arbitration in progress) + is enough to make BIOS v4.x happy. */ + ncr53c8xx_log("NCR 810: Selecting SCSI ID %i\n", dev->sdid); + dev->sstat0 |= 0x10; + } + break; + case 0x01: /* SCNTL1 */ + dev->scntl1 = val & ~NCR_SCNTL1_SST; + if (val & NCR_SCNTL1_IARB) { + ncr53c8xx_log("Arbitration lost\n"); + dev->sstat0 |= 0x08; + dev->waiting = 0; + } + if (val & NCR_SCNTL1_RST) { + if (!(dev->sstat0 & NCR_SSTAT0_RST)) { + dev->sstat0 |= NCR_SSTAT0_RST; + ncr53c8xx_script_scsi_interrupt(dev, NCR_SIST0_RST, 0); + } + } else + dev->sstat0 &= ~NCR_SSTAT0_RST; + break; + case 0x02: /* SCNTL2 */ + val &= ~(NCR_SCNTL2_WSR | NCR_SCNTL2_WSS); + dev->scntl2 = val; + break; + case 0x03: /* SCNTL3 */ + dev->scntl3 = val; + break; + case 0x04: /* SCID */ + dev->scid = val; + break; + case 0x05: /* SXFER */ + dev->sxfer = val; + break; + case 0x06: /* SDID */ + if ((dev->ssid & 0x80) && (val & 0xf) != (dev->ssid & 0xf)) + ncr53c8xx_log("Destination ID does not match SSID\n"); + dev->sdid = val & 0xf; + break; + case 0x07: /* GPREG */ + ncr53c8xx_log("NCR 810: GPREG write %02X\n", val); + dev->gpreg = val; + i2c_gpio_set(dev->i2c, (dev->gpreg & 0x02) || ((dev->gpcntl & 0x82) == 0x02), (dev->gpreg & 0x01) || ((dev->gpcntl & 0x41) == 0x01)); + break; + case 0x08: /* SFBR */ + /* The CPU is not allowed to write to this register. However the + SCRIPTS register move instructions are. */ + dev->sfbr = val; + break; + case 0x09: /* SOCL */ + ncr53c8xx_log("NCR 810: SOCL write %02X\n", val); + dev->socl = val; + break; + case 0x0a: + case 0x0b: + /* Openserver writes to these readonly registers on startup */ + return; + case 0x0c: + case 0x0d: + case 0x0e: + case 0x0f: + /* Linux writes to these readonly registers on startup. */ + return; + CASE_SET_REG32(dsa, 0x10) + case 0x14: /* ISTAT */ + ncr53c8xx_log("ISTAT write: %02X\n", val); + tmp = dev->istat; + dev->istat = (dev->istat & 0x0f) | (val & 0xf0); + if ((val & NCR_ISTAT_ABRT) && !(val & NCR_ISTAT_SRST)) + ncr53c8xx_script_dma_interrupt(dev, NCR_DSTAT_ABRT); + if (val & NCR_ISTAT_INTF) { + dev->istat &= ~NCR_ISTAT_INTF; + ncr53c8xx_update_irq(dev); + } - if ((dev->waiting == 1) && (val & NCR_ISTAT_SIGP)) { - ncr53c8xx_log("Woken by SIGP\n"); - dev->waiting = 0; - dev->dsp = dev->dnad; - /* ncr53c8xx_execute_script(dev); */ - } - if ((val & NCR_ISTAT_SRST) && !(tmp & NCR_ISTAT_SRST)) { - ncr53c8xx_soft_reset(dev); - ncr53c8xx_update_irq(dev); - dev->istat = 0; - } - break; - case 0x16: /* MBOX0 */ - dev->mbox0 = val; - break; - case 0x17: /* MBOX1 */ - dev->mbox1 = val; - break; - case 0x18: /* CTEST0 */ - /* nothing to do */ - break; - case 0x19: /* CTEST1 */ - /* nothing to do */ - break; - case 0x1a: /* CTEST2 */ - dev->ctest2 = val & NCR_CTEST2_PCICIE; - break; - case 0x1b: /* CTEST3 */ - dev->ctest3 = val & 0x0f; - break; - CASE_SET_REG32(temp, 0x1c) - case 0x21: /* CTEST4 */ - if (val & 7) - ncr53c8xx_log("Unimplemented CTEST4-FBL 0x%x\n", val); - dev->ctest4 = val; - break; - case 0x22: /* CTEST5 */ - if (val & (NCR_CTEST5_ADCK | NCR_CTEST5_BBCK)) - ncr53c8xx_log("CTEST5 DMA increment not implemented\n"); - dev->ctest5 = val; - break; - CASE_SET_REG24(dbc, 0x24) - CASE_SET_REG32(dnad, 0x28) - case 0x2c: /* DSP[0:7] */ - dev->dsp &= 0xffffff00; - dev->dsp |= val; - break; - case 0x2d: /* DSP[8:15] */ - dev->dsp &= 0xffff00ff; - dev->dsp |= val << 8; - break; - case 0x2e: /* DSP[16:23] */ - dev->dsp &= 0xff00ffff; - dev->dsp |= val << 16; - break; - case 0x2f: /* DSP[24:31] */ - dev->dsp &= 0x00ffffff; - dev->dsp |= val << 24; - if (!(dev->dmode & NCR_DMODE_MAN) && dev->sstop) - ncr53c8xx_execute_script(dev); - break; - CASE_SET_REG32(dsps, 0x30) - CASE_SET_REG32(scratcha, 0x34) - case 0x38: /* DMODE */ - dev->dmode = val; - break; - case 0x39: /* DIEN */ - ncr53c8xx_log("DIEN write: %02X\n", val); - dev->dien = val; - ncr53c8xx_update_irq(dev); - break; - case 0x3a: /* SBR */ - dev->sbr = val; - break; - case 0x3b: /* DCNTL */ - dev->dcntl = val & ~(NCR_DCNTL_PFF | NCR_DCNTL_STD); - if ((val & NCR_DCNTL_STD) && dev->sstop) - ncr53c8xx_execute_script(dev); - break; - case 0x40: /* SIEN0 */ - dev->sien0 = val; - ncr53c8xx_update_irq(dev); - break; - case 0x41: /* SIEN1 */ - dev->sien1 = val; - ncr53c8xx_update_irq(dev); - break; - case 0x47: /* GPCNTL */ - ncr53c8xx_log("GPCNTL write: %02X\n", val); - dev->gpcntl = val; - break; - case 0x48: /* STIME0 */ - dev->stime0 = val; - break; - case 0x49: /* STIME1 */ - if (val & 0xf) { - ncr53c8xx_log("General purpose timer not implemented\n"); - /* ??? Raising the interrupt immediately seems to be sufficient - to keep the FreeBSD driver happy. */ - ncr53c8xx_script_scsi_interrupt(dev, 0, NCR_SIST1_GEN); - } - break; - case 0x4a: /* RESPID0 */ - dev->respid0 = val; - break; - case 0x4b: /* RESPID1 */ - if (dev->wide) - dev->respid1 = val; - break; - case 0x4d: /* STEST1 */ - dev->stest1 = val; - break; - case 0x4e: /* STEST2 */ - if (val & 1) - ncr53c8xx_log("Low level mode not implemented\n"); - dev->stest2 = val; - break; - case 0x4f: /* STEST3 */ - if (val & 0x41) - ncr53c8xx_log("SCSI FIFO test mode not implemented\n"); - dev->stest3 = val; - break; - case 0x54: - case 0x55: - break; - CASE_SET_REG32(scratchb, 0x5c) - CASE_SET_REG32(scratchc, 0x60) - CASE_SET_REG32(scratchd, 0x64) - CASE_SET_REG32(scratche, 0x68) - CASE_SET_REG32(scratchf, 0x6c) - CASE_SET_REG32(scratchg, 0x70) - CASE_SET_REG32(scratchh, 0x74) - CASE_SET_REG32(scratchi, 0x78) - CASE_SET_REG32(scratchj, 0x7c) - default: - ncr53c8xx_log("Unhandled writeb 0x%x = 0x%x\n", offset, val); + if ((dev->waiting == 1) && (val & NCR_ISTAT_SIGP)) { + ncr53c8xx_log("Woken by SIGP\n"); + dev->waiting = 0; + dev->dsp = dev->dnad; +#if 0 + ncr53c8xx_execute_script(dev); +#endif + } + if ((val & NCR_ISTAT_SRST) && !(tmp & NCR_ISTAT_SRST)) { + ncr53c8xx_soft_reset(dev); + ncr53c8xx_update_irq(dev); + dev->istat = 0; + } + break; + case 0x16: /* MBOX0 */ + dev->mbox0 = val; + break; + case 0x17: /* MBOX1 */ + dev->mbox1 = val; + break; + case 0x18: /* CTEST0 */ + /* nothing to do */ + break; + case 0x19: /* CTEST1 */ + /* nothing to do */ + break; + case 0x1a: /* CTEST2 */ + dev->ctest2 = val & NCR_CTEST2_PCICIE; + break; + case 0x1b: /* CTEST3 */ + dev->ctest3 = val & 0x0f; + break; + CASE_SET_REG32(temp, 0x1c) + case 0x21: /* CTEST4 */ + if (val & 7) + ncr53c8xx_log("Unimplemented CTEST4-FBL 0x%x\n", val); + dev->ctest4 = val; + break; + case 0x22: /* CTEST5 */ + if (val & (NCR_CTEST5_ADCK | NCR_CTEST5_BBCK)) + ncr53c8xx_log("CTEST5 DMA increment not implemented\n"); + dev->ctest5 = val; + break; + CASE_SET_REG24(dbc, 0x24) + CASE_SET_REG32(dnad, 0x28) + case 0x2c: /* DSP[0:7] */ + dev->dsp &= 0xffffff00; + dev->dsp |= val; + break; + case 0x2d: /* DSP[8:15] */ + dev->dsp &= 0xffff00ff; + dev->dsp |= val << 8; + break; + case 0x2e: /* DSP[16:23] */ + dev->dsp &= 0xff00ffff; + dev->dsp |= val << 16; + break; + case 0x2f: /* DSP[24:31] */ + dev->dsp &= 0x00ffffff; + dev->dsp |= val << 24; + if (!(dev->dmode & NCR_DMODE_MAN) && dev->sstop) + ncr53c8xx_execute_script(dev); + break; + CASE_SET_REG32(dsps, 0x30) + CASE_SET_REG32(scratcha, 0x34) + case 0x38: /* DMODE */ + dev->dmode = val; + break; + case 0x39: /* DIEN */ + ncr53c8xx_log("DIEN write: %02X\n", val); + dev->dien = val; + ncr53c8xx_update_irq(dev); + break; + case 0x3a: /* SBR */ + dev->sbr = val; + break; + case 0x3b: /* DCNTL */ + dev->dcntl = val & ~(NCR_DCNTL_PFF | NCR_DCNTL_STD); + if ((val & NCR_DCNTL_STD) && dev->sstop) + ncr53c8xx_execute_script(dev); + break; + case 0x40: /* SIEN0 */ + dev->sien0 = val; + ncr53c8xx_update_irq(dev); + break; + case 0x41: /* SIEN1 */ + dev->sien1 = val; + ncr53c8xx_update_irq(dev); + break; + case 0x47: /* GPCNTL */ + ncr53c8xx_log("GPCNTL write: %02X\n", val); + dev->gpcntl = val; + break; + case 0x48: /* STIME0 */ + dev->stime0 = val; + break; + case 0x49: /* STIME1 */ + if (val & 0xf) { + ncr53c8xx_log("General purpose timer not implemented\n"); + /* ??? Raising the interrupt immediately seems to be sufficient + to keep the FreeBSD driver happy. */ + ncr53c8xx_script_scsi_interrupt(dev, 0, NCR_SIST1_GEN); + } + break; + case 0x4a: /* RESPID0 */ + dev->respid0 = val; + break; + case 0x4b: /* RESPID1 */ + if (dev->wide) + dev->respid1 = val; + break; + case 0x4d: /* STEST1 */ + dev->stest1 = val; + break; + case 0x4e: /* STEST2 */ + if (val & 1) + ncr53c8xx_log("Low level mode not implemented\n"); + dev->stest2 = val; + break; + case 0x4f: /* STEST3 */ + if (val & 0x41) + ncr53c8xx_log("SCSI FIFO test mode not implemented\n"); + dev->stest3 = val; + break; + case 0x54: + case 0x55: + break; + CASE_SET_REG32(scratchb, 0x5c) + CASE_SET_REG32(scratchc, 0x60) + CASE_SET_REG32(scratchd, 0x64) + CASE_SET_REG32(scratche, 0x68) + CASE_SET_REG32(scratchf, 0x6c) + CASE_SET_REG32(scratchg, 0x70) + CASE_SET_REG32(scratchh, 0x74) + CASE_SET_REG32(scratchi, 0x78) + CASE_SET_REG32(scratchj, 0x7c) + default: + ncr53c8xx_log("Unhandled writeb 0x%x = 0x%x\n", offset, val); } #undef CASE_SET_REG24 #undef CASE_SET_REG32 } - static uint8_t ncr53c8xx_reg_readb(ncr53c8xx_t *dev, uint32_t offset) { uint8_t tmp; -#define CASE_GET_REG24(name, addr) \ - case addr: return dev->name & 0xff; \ - case addr + 1: return (dev->name >> 8) & 0xff; \ - case addr + 2: return (dev->name >> 16) & 0xff; +#define CASE_GET_REG24(name, addr) \ + case addr: \ + return dev->name & 0xff; \ + case addr + 1: \ + return (dev->name >> 8) & 0xff; \ + case addr + 2: \ + return (dev->name >> 16) & 0xff; -#define CASE_GET_REG32(name, addr) \ - case addr: return dev->name & 0xff; \ - case addr + 1: return (dev->name >> 8) & 0xff; \ - case addr + 2: return (dev->name >> 16) & 0xff; \ - case addr + 3: return (dev->name >> 24) & 0xff; +#define CASE_GET_REG32(name, addr) \ + case addr: \ + return dev->name & 0xff; \ + case addr + 1: \ + return (dev->name >> 8) & 0xff; \ + case addr + 2: \ + return (dev->name >> 16) & 0xff; \ + case addr + 3: \ + return (dev->name >> 24) & 0xff; -#define CASE_GET_REG32_COND(name, addr) \ - case addr: if (dev->wide) \ - return dev->name & 0xff; \ - else \ - return 0x00; \ - case addr + 1: if (dev->wide) \ - return (dev->name >> 8) & 0xff; \ - else \ - return 0x00; \ - case addr + 2: if (dev->wide) \ - return (dev->name >> 16) & 0xff; \ - else \ - return 0x00; \ - case addr + 3: if (dev->wide) \ - return (dev->name >> 24) & 0xff; \ - else \ - return 0x00; +#define CASE_GET_REG32_COND(name, addr) \ + case addr: \ + if (dev->wide) \ + return dev->name & 0xff; \ + else \ + return 0x00; \ + case addr + 1: \ + if (dev->wide) \ + return (dev->name >> 8) & 0xff; \ + else \ + return 0x00; \ + case addr + 2: \ + if (dev->wide) \ + return (dev->name >> 16) & 0xff; \ + else \ + return 0x00; \ + case addr + 3: \ + if (dev->wide) \ + return (dev->name >> 24) & 0xff; \ + else \ + return 0x00; dev->regop = 1; switch (offset) { - case 0x00: /* SCNTL0 */ - ncr53c8xx_log("NCR 810: Read SCNTL0 %02X\n", dev->scntl0); - return dev->scntl0; - case 0x01: /* SCNTL1 */ - ncr53c8xx_log("NCR 810: Read SCNTL1 %02X\n", dev->scntl1); - return dev->scntl1; - case 0x02: /* SCNTL2 */ - ncr53c8xx_log("NCR 810: Read SCNTL2 %02X\n", dev->scntl2); - return dev->scntl2; - case 0x03: /* SCNTL3 */ - ncr53c8xx_log("NCR 810: Read SCNTL3 %02X\n", dev->scntl3); - return dev->scntl3; - case 0x04: /* SCID */ - ncr53c8xx_log("NCR 810: Read SCID %02X\n", dev->scid); - return dev->scid & ~0x40; - case 0x05: /* SXFER */ - ncr53c8xx_log("NCR 810: Read SXFER %02X\n", dev->sxfer); - return dev->sxfer; - case 0x06: /* SDID */ - ncr53c8xx_log("NCR 810: Read SDID %02X\n", dev->sdid); - return dev->sdid; - case 0x07: /* GPREG */ - tmp = (dev->gpreg & (dev->gpcntl ^ 0x1f)) & 0x1f; - if ((dev->gpcntl & 0x41) == 0x01) { - tmp &= 0xfe; - if (i2c_gpio_get_sda(dev->i2c)) - tmp |= 0x01; - } - if ((dev->gpcntl & 0x82) == 0x02) { - tmp &= 0xfd; - if (i2c_gpio_get_scl(dev->i2c)) - tmp |= 0x02; - } + case 0x00: /* SCNTL0 */ + ncr53c8xx_log("NCR 810: Read SCNTL0 %02X\n", dev->scntl0); + return dev->scntl0; + case 0x01: /* SCNTL1 */ + ncr53c8xx_log("NCR 810: Read SCNTL1 %02X\n", dev->scntl1); + return dev->scntl1; + case 0x02: /* SCNTL2 */ + ncr53c8xx_log("NCR 810: Read SCNTL2 %02X\n", dev->scntl2); + return dev->scntl2; + case 0x03: /* SCNTL3 */ + ncr53c8xx_log("NCR 810: Read SCNTL3 %02X\n", dev->scntl3); + return dev->scntl3; + case 0x04: /* SCID */ + ncr53c8xx_log("NCR 810: Read SCID %02X\n", dev->scid); + return dev->scid & ~0x40; + case 0x05: /* SXFER */ + ncr53c8xx_log("NCR 810: Read SXFER %02X\n", dev->sxfer); + return dev->sxfer; + case 0x06: /* SDID */ + ncr53c8xx_log("NCR 810: Read SDID %02X\n", dev->sdid); + return dev->sdid; + case 0x07: /* GPREG */ + tmp = (dev->gpreg & (dev->gpcntl ^ 0x1f)) & 0x1f; + if ((dev->gpcntl & 0x41) == 0x01) { + tmp &= 0xfe; + if (i2c_gpio_get_sda(dev->i2c)) + tmp |= 0x01; + } + if ((dev->gpcntl & 0x82) == 0x02) { + tmp &= 0xfd; + if (i2c_gpio_get_scl(dev->i2c)) + tmp |= 0x02; + } - ncr53c8xx_log("NCR 810: Read GPREG %02X\n", tmp); - return tmp; - case 0x08: /* Revision ID */ - ncr53c8xx_log("NCR 810: Read REVID 00\n"); - return 0x00; - case 0xa: /* SSID */ - ncr53c8xx_log("NCR 810: Read SSID %02X\n", dev->ssid); - return dev->ssid; - case 0xb: /* SBCL */ - /* Bit 7 = REQ (SREQ/ status) - Bit 6 = ACK (SACK/ status) - Bit 5 = BSY (SBSY/ status) - Bit 4 = SEL (SSEL/ status) - Bit 3 = ATN (SATN/ status) - Bit 2 = MSG (SMSG/ status) - Bit 1 = C/D (SC_D/ status) - Bit 0 = I/O (SI_O/ status) */ - tmp = (dev->sstat1 & 7); - ncr53c8xx_log("NCR 810: Read SBCL %02X\n", tmp); - return tmp; /* For now, return the MSG, C/D, and I/O bits from SSTAT1. */ - case 0xc: /* DSTAT */ - tmp = dev->dstat | NCR_DSTAT_DFE; - if ((dev->istat & NCR_ISTAT_INTF) == 0) - dev->dstat = 0; - ncr53c8xx_update_irq(dev); - ncr53c8xx_log("NCR 810: Read DSTAT %02X\n", tmp); - return tmp; - case 0x0d: /* SSTAT0 */ - ncr53c8xx_log("NCR 810: Read SSTAT0 %02X\n", dev->sstat0); - return dev->sstat0; - case 0x0e: /* SSTAT1 */ - ncr53c8xx_log("NCR 810: Read SSTAT1 %02X\n", dev->sstat1); - return dev->sstat1; - case 0x0f: /* SSTAT2 */ - ncr53c8xx_log("NCR 810: Read SSTAT2 %02X\n", dev->scntl1 & NCR_SCNTL1_CON ? 0 : 2); - return dev->scntl1 & NCR_SCNTL1_CON ? 0 : 2; - CASE_GET_REG32(dsa, 0x10) - case 0x14: /* ISTAT */ - ncr53c8xx_log("NCR 810: Read ISTAT %02X\n", dev->istat); - tmp = dev->istat; - return tmp; - case 0x16: /* MBOX0 */ - if (dev->wide) - return 0x00; - ncr53c8xx_log("NCR 810: Read MBOX0 %02X\n", dev->mbox0); - return dev->mbox0; - case 0x17: /* MBOX1 */ - if (dev->wide) - return 0x00; - ncr53c8xx_log("NCR 810: Read MBOX1 %02X\n", dev->mbox1); - return dev->mbox1; - case 0x18: /* CTEST0 */ - ncr53c8xx_log("NCR 810: Read CTEST0 FF\n"); - return 0xff; - case 0x19: /* CTEST1 */ - ncr53c8xx_log("NCR 810: Read CTEST1 F0\n"); - return 0xf0; /* dma fifo empty */ - case 0x1a: /* CTEST2 */ - tmp = dev->ctest2 | NCR_CTEST2_DACK | NCR_CTEST2_CM; - if (dev->istat & NCR_ISTAT_SIGP) { - dev->istat &= ~NCR_ISTAT_SIGP; - tmp |= NCR_CTEST2_SIGP; - } - ncr53c8xx_log("NCR 810: Read CTEST2 %02X\n", tmp); - return tmp; - case 0x1b: /* CTEST3 */ - ncr53c8xx_log("NCR 810: Read CTEST3 %02X\n", - (dev->ctest3 & (0x08 | 0x02 | 0x01)) | ((dev->chip_rev & 0x0f) << 4)); - return (dev->ctest3 & (0x08 | 0x02 | 0x01)) | ((dev->chip_rev & 0x0f) << 4); - CASE_GET_REG32(temp, 0x1c) - case 0x20: /* DFIFO */ - ncr53c8xx_log("NCR 810: Read DFIFO 00\n"); - return 0; - case 0x21: /* CTEST4 */ - ncr53c8xx_log("NCR 810: Read CTEST4 %02X\n", dev->ctest4); - return dev->ctest4; - case 0x22: /* CTEST5 */ - ncr53c8xx_log("NCR 810: Read CTEST5 %02X\n", dev->ctest5); - return dev->ctest5; - case 0x23: /* CTEST6 */ - ncr53c8xx_log("NCR 810: Read CTEST6 00\n"); - return 0; - CASE_GET_REG24(dbc, 0x24) - case 0x27: /* DCMD */ - ncr53c8xx_log("NCR 810: Read DCMD %02X\n", dev->dcmd); - return dev->dcmd; - CASE_GET_REG32(dnad, 0x28) - CASE_GET_REG32(dsp, 0x2c) - CASE_GET_REG32(dsps, 0x30) - CASE_GET_REG32(scratcha, 0x34) - case 0x38: /* DMODE */ - ncr53c8xx_log("NCR 810: Read DMODE %02X\n", dev->dmode); - return dev->dmode; - case 0x39: /* DIEN */ - ncr53c8xx_log("NCR 810: Read DIEN %02X\n", dev->dien); - return dev->dien; - case 0x3a: /* SBR */ - ncr53c8xx_log("NCR 810: Read SBR %02X\n", dev->sbr); - return dev->sbr; - case 0x3b: /* DCNTL */ - ncr53c8xx_log("NCR 810: Read DCNTL %02X\n", dev->dcntl); - return dev->dcntl; - CASE_GET_REG32(adder, 0x3c) /* ADDER Output (Debug of relative jump address) */ - case 0x40: /* SIEN0 */ - ncr53c8xx_log("NCR 810: Read SIEN0 %02X\n", dev->sien0); - return dev->sien0; - case 0x41: /* SIEN1 */ - ncr53c8xx_log("NCR 810: Read SIEN1 %02X\n", dev->sien1); - return dev->sien1; - case 0x42: /* SIST0 */ - tmp = dev->sist0; - dev->sist0 = 0x00; - ncr53c8xx_update_irq(dev); - ncr53c8xx_log("NCR 810: Read SIST0 %02X\n", tmp); - return tmp; - case 0x43: /* SIST1 */ - tmp = dev->sist1; - dev->sist1 = 0x00; - ncr53c8xx_update_irq(dev); - ncr53c8xx_log("NCR 810: Read SIST1 %02X\n", tmp); - return tmp; - case 0x44: /* SLPAR */ - if (!dev->wide) - return 0x00; - ncr53c8xx_log("NCR 810: Read SLPAR %02X\n", dev->stime0); - return dev->slpar; - case 0x45: /* SWIDE */ - if (!dev->wide) - return 0x00; - ncr53c8xx_log("NCR 810: Read SWIDE %02X\n", dev->stime0); - return dev->swide; - case 0x46: /* MACNTL */ - ncr53c8xx_log("NCR 810: Read MACNTL 4F\n"); - return 0x4f; - case 0x47: /* GPCNTL */ - ncr53c8xx_log("NCR 810: Read GPCNTL %02X\n", dev->gpcntl); - return dev->gpcntl; - case 0x48: /* STIME0 */ - ncr53c8xx_log("NCR 810: Read STIME0 %02X\n", dev->stime0); - return dev->stime0; - case 0x4a: /* RESPID0 */ - if (dev->wide) { - ncr53c8xx_log("NCR 810: Read RESPID0 %02X\n", dev->respid0); - } else { - ncr53c8xx_log("NCR 810: Read RESPID %02X\n", dev->respid0); - } - return dev->respid0; - case 0x4b: /* RESPID1 */ - if (!dev->wide) - return 0x00; - ncr53c8xx_log("NCR 810: Read RESPID1 %02X\n", dev->respid1); - return dev->respid1; - case 0x4c: /* STEST0 */ - ncr53c8xx_log("NCR 810: Read STEST0 %02X\n", dev->stest1); - return 0x00; - case 0x4d: /* STEST1 */ - ncr53c8xx_log("NCR 810: Read STEST1 %02X\n", dev->stest1); - return dev->stest1; - case 0x4e: /* STEST2 */ - ncr53c8xx_log("NCR 810: Read STEST2 %02X\n", dev->stest2); - return dev->stest2; - case 0x4f: /* STEST3 */ - ncr53c8xx_log("NCR 810: Read STEST3 %02X\n", dev->stest3); - return dev->stest3; - case 0x50: /* SIDL0 */ - /* This is needed by the linux drivers. We currently only update it - during the MSG IN phase. */ - if (dev->wide) { - ncr53c8xx_log("NCR 810: Read SIDL0 %02X\n", dev->sidl0); - } else { - ncr53c8xx_log("NCR 810: Read SIDL %02X\n", dev->sidl0); - } - return dev->sidl0; - case 0x51: /* SIDL1 */ - if (!dev->wide) - return 0x00; - ncr53c8xx_log("NCR 810: Read SIDL1 %02X\n", dev->sidl1); - return dev->sidl1; - case 0x52: /* STEST4 */ - ncr53c8xx_log("NCR 810: Read STEST4 E0\n"); - return 0xe0; - case 0x58: /* SBDL */ - /* Some drivers peek at the data bus during the MSG IN phase. */ - if ((dev->sstat1 & PHASE_MASK) == PHASE_MI) { - ncr53c8xx_log("NCR 810: Read SBDL %02X\n", dev->msg[0]); - return dev->msg[0]; - } - ncr53c8xx_log("NCR 810: Read SBDL 00\n"); - return 0; - case 0x59: /* SBDL high */ - ncr53c8xx_log("NCR 810: Read SBDLH 00\n"); - return 0; - CASE_GET_REG32(scratchb, 0x5c) - CASE_GET_REG32_COND(scratchc, 0x60) - CASE_GET_REG32_COND(scratchd, 0x64) - CASE_GET_REG32_COND(scratche, 0x68) - CASE_GET_REG32_COND(scratchf, 0x6c) - CASE_GET_REG32_COND(scratchg, 0x70) - CASE_GET_REG32_COND(scratchh, 0x74) - CASE_GET_REG32_COND(scratchi, 0x78) - CASE_GET_REG32_COND(scratchj, 0x7c) + ncr53c8xx_log("NCR 810: Read GPREG %02X\n", tmp); + return tmp; + case 0x08: /* Revision ID */ + ncr53c8xx_log("NCR 810: Read REVID 00\n"); + return 0x00; + case 0xa: /* SSID */ + ncr53c8xx_log("NCR 810: Read SSID %02X\n", dev->ssid); + return dev->ssid; + case 0xb: /* SBCL */ + /* Bit 7 = REQ (SREQ/ status) + Bit 6 = ACK (SACK/ status) + Bit 5 = BSY (SBSY/ status) + Bit 4 = SEL (SSEL/ status) + Bit 3 = ATN (SATN/ status) + Bit 2 = MSG (SMSG/ status) + Bit 1 = C/D (SC_D/ status) + Bit 0 = I/O (SI_O/ status) */ + tmp = (dev->sstat1 & 7); + ncr53c8xx_log("NCR 810: Read SBCL %02X\n", tmp); + return tmp; /* For now, return the MSG, C/D, and I/O bits from SSTAT1. */ + case 0xc: /* DSTAT */ + tmp = dev->dstat | NCR_DSTAT_DFE; + if ((dev->istat & NCR_ISTAT_INTF) == 0) + dev->dstat = 0; + ncr53c8xx_update_irq(dev); + ncr53c8xx_log("NCR 810: Read DSTAT %02X\n", tmp); + return tmp; + case 0x0d: /* SSTAT0 */ + ncr53c8xx_log("NCR 810: Read SSTAT0 %02X\n", dev->sstat0); + return dev->sstat0; + case 0x0e: /* SSTAT1 */ + ncr53c8xx_log("NCR 810: Read SSTAT1 %02X\n", dev->sstat1); + return dev->sstat1; + case 0x0f: /* SSTAT2 */ + ncr53c8xx_log("NCR 810: Read SSTAT2 %02X\n", dev->scntl1 & NCR_SCNTL1_CON ? 0 : 2); + return dev->scntl1 & NCR_SCNTL1_CON ? 0 : 2; + CASE_GET_REG32(dsa, 0x10) + case 0x14: /* ISTAT */ + ncr53c8xx_log("NCR 810: Read ISTAT %02X\n", dev->istat); + tmp = dev->istat; + return tmp; + case 0x16: /* MBOX0 */ + if (dev->wide) + return 0x00; + ncr53c8xx_log("NCR 810: Read MBOX0 %02X\n", dev->mbox0); + return dev->mbox0; + case 0x17: /* MBOX1 */ + if (dev->wide) + return 0x00; + ncr53c8xx_log("NCR 810: Read MBOX1 %02X\n", dev->mbox1); + return dev->mbox1; + case 0x18: /* CTEST0 */ + ncr53c8xx_log("NCR 810: Read CTEST0 FF\n"); + return 0xff; + case 0x19: /* CTEST1 */ + ncr53c8xx_log("NCR 810: Read CTEST1 F0\n"); + return 0xf0; /* dma fifo empty */ + case 0x1a: /* CTEST2 */ + tmp = dev->ctest2 | NCR_CTEST2_DACK | NCR_CTEST2_CM; + if (dev->istat & NCR_ISTAT_SIGP) { + dev->istat &= ~NCR_ISTAT_SIGP; + tmp |= NCR_CTEST2_SIGP; + } + ncr53c8xx_log("NCR 810: Read CTEST2 %02X\n", tmp); + return tmp; + case 0x1b: /* CTEST3 */ + ncr53c8xx_log("NCR 810: Read CTEST3 %02X\n", + (dev->ctest3 & (0x08 | 0x02 | 0x01)) | ((dev->chip_rev & 0x0f) << 4)); + return (dev->ctest3 & (0x08 | 0x02 | 0x01)) | ((dev->chip_rev & 0x0f) << 4); + CASE_GET_REG32(temp, 0x1c) + case 0x20: /* DFIFO */ + ncr53c8xx_log("NCR 810: Read DFIFO 00\n"); + return 0; + case 0x21: /* CTEST4 */ + ncr53c8xx_log("NCR 810: Read CTEST4 %02X\n", dev->ctest4); + return dev->ctest4; + case 0x22: /* CTEST5 */ + ncr53c8xx_log("NCR 810: Read CTEST5 %02X\n", dev->ctest5); + return dev->ctest5; + case 0x23: /* CTEST6 */ + ncr53c8xx_log("NCR 810: Read CTEST6 00\n"); + return 0; + CASE_GET_REG24(dbc, 0x24) + case 0x27: /* DCMD */ + ncr53c8xx_log("NCR 810: Read DCMD %02X\n", dev->dcmd); + return dev->dcmd; + CASE_GET_REG32(dnad, 0x28) + CASE_GET_REG32(dsp, 0x2c) + CASE_GET_REG32(dsps, 0x30) + CASE_GET_REG32(scratcha, 0x34) + case 0x38: /* DMODE */ + ncr53c8xx_log("NCR 810: Read DMODE %02X\n", dev->dmode); + return dev->dmode; + case 0x39: /* DIEN */ + ncr53c8xx_log("NCR 810: Read DIEN %02X\n", dev->dien); + return dev->dien; + case 0x3a: /* SBR */ + ncr53c8xx_log("NCR 810: Read SBR %02X\n", dev->sbr); + return dev->sbr; + case 0x3b: /* DCNTL */ + ncr53c8xx_log("NCR 810: Read DCNTL %02X\n", dev->dcntl); + return dev->dcntl; + CASE_GET_REG32(adder, 0x3c) /* ADDER Output (Debug of relative jump address) */ + case 0x40: /* SIEN0 */ + ncr53c8xx_log("NCR 810: Read SIEN0 %02X\n", dev->sien0); + return dev->sien0; + case 0x41: /* SIEN1 */ + ncr53c8xx_log("NCR 810: Read SIEN1 %02X\n", dev->sien1); + return dev->sien1; + case 0x42: /* SIST0 */ + tmp = dev->sist0; + dev->sist0 = 0x00; + ncr53c8xx_update_irq(dev); + ncr53c8xx_log("NCR 810: Read SIST0 %02X\n", tmp); + return tmp; + case 0x43: /* SIST1 */ + tmp = dev->sist1; + dev->sist1 = 0x00; + ncr53c8xx_update_irq(dev); + ncr53c8xx_log("NCR 810: Read SIST1 %02X\n", tmp); + return tmp; + case 0x44: /* SLPAR */ + if (!dev->wide) + return 0x00; + ncr53c8xx_log("NCR 810: Read SLPAR %02X\n", dev->stime0); + return dev->slpar; + case 0x45: /* SWIDE */ + if (!dev->wide) + return 0x00; + ncr53c8xx_log("NCR 810: Read SWIDE %02X\n", dev->stime0); + return dev->swide; + case 0x46: /* MACNTL */ + ncr53c8xx_log("NCR 810: Read MACNTL 4F\n"); + return 0x4f; + case 0x47: /* GPCNTL */ + ncr53c8xx_log("NCR 810: Read GPCNTL %02X\n", dev->gpcntl); + return dev->gpcntl; + case 0x48: /* STIME0 */ + ncr53c8xx_log("NCR 810: Read STIME0 %02X\n", dev->stime0); + return dev->stime0; + case 0x4a: /* RESPID0 */ + if (dev->wide) { + ncr53c8xx_log("NCR 810: Read RESPID0 %02X\n", dev->respid0); + } else { + ncr53c8xx_log("NCR 810: Read RESPID %02X\n", dev->respid0); + } + return dev->respid0; + case 0x4b: /* RESPID1 */ + if (!dev->wide) + return 0x00; + ncr53c8xx_log("NCR 810: Read RESPID1 %02X\n", dev->respid1); + return dev->respid1; + case 0x4c: /* STEST0 */ + ncr53c8xx_log("NCR 810: Read STEST0 %02X\n", dev->stest1); + return 0x00; + case 0x4d: /* STEST1 */ + ncr53c8xx_log("NCR 810: Read STEST1 %02X\n", dev->stest1); + return dev->stest1; + case 0x4e: /* STEST2 */ + ncr53c8xx_log("NCR 810: Read STEST2 %02X\n", dev->stest2); + return dev->stest2; + case 0x4f: /* STEST3 */ + ncr53c8xx_log("NCR 810: Read STEST3 %02X\n", dev->stest3); + return dev->stest3; + case 0x50: /* SIDL0 */ + /* This is needed by the linux drivers. We currently only update it + during the MSG IN phase. */ + if (dev->wide) { + ncr53c8xx_log("NCR 810: Read SIDL0 %02X\n", dev->sidl0); + } else { + ncr53c8xx_log("NCR 810: Read SIDL %02X\n", dev->sidl0); + } + return dev->sidl0; + case 0x51: /* SIDL1 */ + if (!dev->wide) + return 0x00; + ncr53c8xx_log("NCR 810: Read SIDL1 %02X\n", dev->sidl1); + return dev->sidl1; + case 0x52: /* STEST4 */ + ncr53c8xx_log("NCR 810: Read STEST4 E0\n"); + return 0xe0; + case 0x58: /* SBDL */ + /* Some drivers peek at the data bus during the MSG IN phase. */ + if ((dev->sstat1 & PHASE_MASK) == PHASE_MI) { + ncr53c8xx_log("NCR 810: Read SBDL %02X\n", dev->msg[0]); + return dev->msg[0]; + } + ncr53c8xx_log("NCR 810: Read SBDL 00\n"); + return 0; + case 0x59: /* SBDL high */ + ncr53c8xx_log("NCR 810: Read SBDLH 00\n"); + return 0; + CASE_GET_REG32(scratchb, 0x5c) + CASE_GET_REG32_COND(scratchc, 0x60) + CASE_GET_REG32_COND(scratchd, 0x64) + CASE_GET_REG32_COND(scratche, 0x68) + CASE_GET_REG32_COND(scratchf, 0x6c) + CASE_GET_REG32_COND(scratchg, 0x70) + CASE_GET_REG32_COND(scratchh, 0x74) + CASE_GET_REG32_COND(scratchi, 0x78) + CASE_GET_REG32_COND(scratchj, 0x7c) + + default: + break; } ncr53c8xx_log("readb 0x%x\n", offset); return 0; @@ -1988,34 +2015,32 @@ ncr53c8xx_reg_readb(ncr53c8xx_t *dev, uint32_t offset) #undef CASE_GET_REG32 } - static uint8_t -ncr53c8xx_io_readb(uint16_t addr, void *p) +ncr53c8xx_io_readb(uint16_t addr, void *priv) { - ncr53c8xx_t *dev = (ncr53c8xx_t *)p; + ncr53c8xx_t *dev = (ncr53c8xx_t *) priv; + return ncr53c8xx_reg_readb(dev, addr & 0xff); } - static uint16_t -ncr53c8xx_io_readw(uint16_t addr, void *p) +ncr53c8xx_io_readw(uint16_t addr, void *priv) { - ncr53c8xx_t *dev = (ncr53c8xx_t *)p; - uint16_t val; - + ncr53c8xx_t *dev = (ncr53c8xx_t *) priv; + uint16_t val; + addr &= 0xff; val = ncr53c8xx_reg_readb(dev, addr); val |= ncr53c8xx_reg_readb(dev, addr + 1) << 8; return val; } - static uint32_t -ncr53c8xx_io_readl(uint16_t addr, void *p) +ncr53c8xx_io_readl(uint16_t addr, void *priv) { - ncr53c8xx_t *dev = (ncr53c8xx_t *)p; - uint32_t val; - + ncr53c8xx_t *dev = (ncr53c8xx_t *) priv; + uint32_t val; + addr &= 0xff; val = ncr53c8xx_reg_readb(dev, addr); val |= ncr53c8xx_reg_readb(dev, addr + 1) << 8; @@ -2024,61 +2049,28 @@ ncr53c8xx_io_readl(uint16_t addr, void *p) return val; } - static void -ncr53c8xx_io_writeb(uint16_t addr, uint8_t val, void *p) +ncr53c8xx_io_writeb(uint16_t addr, uint8_t val, void *priv) { - ncr53c8xx_t *dev = (ncr53c8xx_t *)p; - ncr53c8xx_reg_writeb(dev, addr & 0xff, val); -} - - -static void -ncr53c8xx_io_writew(uint16_t addr, uint16_t val, void *p) -{ - ncr53c8xx_t *dev = (ncr53c8xx_t *)p; - addr &= 0xff; - ncr53c8xx_reg_writeb(dev, addr, val & 0xff); - ncr53c8xx_reg_writeb(dev, addr + 1, (val >> 8) & 0xff); -} - - -static void -ncr53c8xx_io_writel(uint16_t addr, uint32_t val, void *p) -{ - ncr53c8xx_t *dev = (ncr53c8xx_t *)p; - addr &= 0xff; - ncr53c8xx_reg_writeb(dev, addr, val & 0xff); - ncr53c8xx_reg_writeb(dev, addr + 1, (val >> 8) & 0xff); - ncr53c8xx_reg_writeb(dev, addr + 2, (val >> 16) & 0xff); - ncr53c8xx_reg_writeb(dev, addr + 3, (val >> 24) & 0xff); -} - - -static void -ncr53c8xx_mmio_writeb(uint32_t addr, uint8_t val, void *p) -{ - ncr53c8xx_t *dev = (ncr53c8xx_t *)p; + ncr53c8xx_t *dev = (ncr53c8xx_t *) priv; ncr53c8xx_reg_writeb(dev, addr & 0xff, val); } - static void -ncr53c8xx_mmio_writew(uint32_t addr, uint16_t val, void *p) +ncr53c8xx_io_writew(uint16_t addr, uint16_t val, void *priv) { - ncr53c8xx_t *dev = (ncr53c8xx_t *)p; + ncr53c8xx_t *dev = (ncr53c8xx_t *) priv; addr &= 0xff; ncr53c8xx_reg_writeb(dev, addr, val & 0xff); ncr53c8xx_reg_writeb(dev, addr + 1, (val >> 8) & 0xff); } - static void -ncr53c8xx_mmio_writel(uint32_t addr, uint32_t val, void *p) +ncr53c8xx_io_writel(uint16_t addr, uint32_t val, void *priv) { - ncr53c8xx_t *dev = (ncr53c8xx_t *)p; + ncr53c8xx_t *dev = (ncr53c8xx_t *) priv; addr &= 0xff; ncr53c8xx_reg_writeb(dev, addr, val & 0xff); @@ -2087,21 +2079,49 @@ ncr53c8xx_mmio_writel(uint32_t addr, uint32_t val, void *p) ncr53c8xx_reg_writeb(dev, addr + 3, (val >> 24) & 0xff); } +static void +ncr53c8xx_mmio_writeb(uint32_t addr, uint8_t val, void *priv) +{ + ncr53c8xx_t *dev = (ncr53c8xx_t *) priv; + + ncr53c8xx_reg_writeb(dev, addr & 0xff, val); +} + +static void +ncr53c8xx_mmio_writew(uint32_t addr, uint16_t val, void *priv) +{ + ncr53c8xx_t *dev = (ncr53c8xx_t *) priv; + + addr &= 0xff; + ncr53c8xx_reg_writeb(dev, addr, val & 0xff); + ncr53c8xx_reg_writeb(dev, addr + 1, (val >> 8) & 0xff); +} + +static void +ncr53c8xx_mmio_writel(uint32_t addr, uint32_t val, void *priv) +{ + ncr53c8xx_t *dev = (ncr53c8xx_t *) priv; + + addr &= 0xff; + ncr53c8xx_reg_writeb(dev, addr, val & 0xff); + ncr53c8xx_reg_writeb(dev, addr + 1, (val >> 8) & 0xff); + ncr53c8xx_reg_writeb(dev, addr + 2, (val >> 16) & 0xff); + ncr53c8xx_reg_writeb(dev, addr + 3, (val >> 24) & 0xff); +} static uint8_t -ncr53c8xx_mmio_readb(uint32_t addr, void *p) +ncr53c8xx_mmio_readb(uint32_t addr, void *priv) { - ncr53c8xx_t *dev = (ncr53c8xx_t *)p; + ncr53c8xx_t *dev = (ncr53c8xx_t *) priv; return ncr53c8xx_reg_readb(dev, addr & 0xff); } - static uint16_t -ncr53c8xx_mmio_readw(uint32_t addr, void *p) +ncr53c8xx_mmio_readw(uint32_t addr, void *priv) { - ncr53c8xx_t *dev = (ncr53c8xx_t *)p; - uint16_t val; + ncr53c8xx_t *dev = (ncr53c8xx_t *) priv; + uint16_t val; addr &= 0xff; val = ncr53c8xx_reg_readb(dev, addr); @@ -2109,404 +2129,398 @@ ncr53c8xx_mmio_readw(uint32_t addr, void *p) return val; } - static uint32_t -ncr53c8xx_mmio_readl(uint32_t addr, void *p) +ncr53c8xx_mmio_readl(uint32_t addr, void *priv) { - ncr53c8xx_t *dev = (ncr53c8xx_t *)p; - uint32_t val; + ncr53c8xx_t *dev = (ncr53c8xx_t *) priv; + uint32_t val; addr &= 0xff; val = ncr53c8xx_reg_readb(dev, addr); val |= ncr53c8xx_reg_readb(dev, addr + 1) << 8; val |= ncr53c8xx_reg_readb(dev, addr + 2) << 16; - val |= ncr53c8xx_reg_readb(dev, addr + 3) << 24; + val |= ncr53c8xx_reg_readb(dev, addr + 3) << 24; return val; } - static void -ncr53c8xx_ram_writeb(uint32_t addr, uint8_t val, void *p) +ncr53c8xx_ram_writeb(uint32_t addr, uint8_t val, void *priv) { - ncr53c8xx_t *dev = (ncr53c8xx_t *)p; + ncr53c8xx_t *dev = (ncr53c8xx_t *) priv; dev->ram[addr & 0x0fff] = val; } - static void -ncr53c8xx_ram_writew(uint32_t addr, uint16_t val, void *p) +ncr53c8xx_ram_writew(uint32_t addr, uint16_t val, void *priv) { - ncr53c8xx_ram_writeb(addr, val & 0xff, p); - ncr53c8xx_ram_writeb(addr + 1, (val >> 8) & 0xff, p); + ncr53c8xx_ram_writeb(addr, val & 0xff, priv); + ncr53c8xx_ram_writeb(addr + 1, (val >> 8) & 0xff, priv); } - static void -ncr53c8xx_ram_writel(uint32_t addr, uint32_t val, void *p) +ncr53c8xx_ram_writel(uint32_t addr, uint32_t val, void *priv) { - ncr53c8xx_ram_writeb(addr, val & 0xff, p); - ncr53c8xx_ram_writeb(addr + 1, (val >> 8) & 0xff, p); - ncr53c8xx_ram_writeb(addr + 2, (val >> 16) & 0xff, p); - ncr53c8xx_ram_writeb(addr + 3, (val >> 24) & 0xff, p); + ncr53c8xx_ram_writeb(addr, val & 0xff, priv); + ncr53c8xx_ram_writeb(addr + 1, (val >> 8) & 0xff, priv); + ncr53c8xx_ram_writeb(addr + 2, (val >> 16) & 0xff, priv); + ncr53c8xx_ram_writeb(addr + 3, (val >> 24) & 0xff, priv); } - static uint8_t -ncr53c8xx_ram_readb(uint32_t addr, void *p) +ncr53c8xx_ram_readb(uint32_t addr, void *priv) { - ncr53c8xx_t *dev = (ncr53c8xx_t *)p; + const ncr53c8xx_t *dev = (ncr53c8xx_t *) priv; return dev->ram[addr & 0x0fff]; } - static uint16_t -ncr53c8xx_ram_readw(uint32_t addr, void *p) +ncr53c8xx_ram_readw(uint32_t addr, void *priv) { uint16_t val; - val = ncr53c8xx_ram_readb(addr, p); - val |= ncr53c8xx_ram_readb(addr + 1, p) << 8; + val = ncr53c8xx_ram_readb(addr, priv); + val |= ncr53c8xx_ram_readb(addr + 1, priv) << 8; return val; } - static uint32_t -ncr53c8xx_ram_readl(uint32_t addr, void *p) +ncr53c8xx_ram_readl(uint32_t addr, void *priv) { uint32_t val; - val = ncr53c8xx_ram_readb(addr, p); - val |= ncr53c8xx_ram_readb(addr + 1, p) << 8; - val |= ncr53c8xx_ram_readb(addr + 2, p) << 16; - val |= ncr53c8xx_ram_readb(addr + 3, p) << 24; + val = ncr53c8xx_ram_readb(addr, priv); + val |= ncr53c8xx_ram_readb(addr + 1, priv) << 8; + val |= ncr53c8xx_ram_readb(addr + 2, priv) << 16; + val |= ncr53c8xx_ram_readb(addr + 3, priv) << 24; return val; } - static void ncr53c8xx_io_set(ncr53c8xx_t *dev, uint32_t base, uint16_t len) { ncr53c8xx_log("NCR53c8xx: [PCI] Setting I/O handler at %04X\n", base); io_sethandler(base, len, - ncr53c8xx_io_readb, ncr53c8xx_io_readw, ncr53c8xx_io_readl, - ncr53c8xx_io_writeb, ncr53c8xx_io_writew, ncr53c8xx_io_writel, dev); + ncr53c8xx_io_readb, ncr53c8xx_io_readw, ncr53c8xx_io_readl, + ncr53c8xx_io_writeb, ncr53c8xx_io_writew, ncr53c8xx_io_writel, dev); } - static void ncr53c8xx_io_remove(ncr53c8xx_t *dev, uint32_t base, uint16_t len) { ncr53c8xx_log("NCR53c8xx: Removing I/O handler at %04X\n", base); io_removehandler(base, len, - ncr53c8xx_io_readb, ncr53c8xx_io_readw, ncr53c8xx_io_readl, + ncr53c8xx_io_readb, ncr53c8xx_io_readw, ncr53c8xx_io_readl, ncr53c8xx_io_writeb, ncr53c8xx_io_writew, ncr53c8xx_io_writel, dev); } - static void ncr53c8xx_mem_init(ncr53c8xx_t *dev, uint32_t addr) { mem_mapping_add(&dev->mmio_mapping, addr, 0x100, - ncr53c8xx_mmio_readb, ncr53c8xx_mmio_readw, ncr53c8xx_mmio_readl, - ncr53c8xx_mmio_writeb, ncr53c8xx_mmio_writew, ncr53c8xx_mmio_writel, - NULL, MEM_MAPPING_EXTERNAL, dev); + ncr53c8xx_mmio_readb, ncr53c8xx_mmio_readw, ncr53c8xx_mmio_readl, + ncr53c8xx_mmio_writeb, ncr53c8xx_mmio_writew, ncr53c8xx_mmio_writel, + NULL, MEM_MAPPING_EXTERNAL, dev); } - static void ncr53c8xx_ram_init(ncr53c8xx_t *dev, uint32_t addr) { mem_mapping_add(&dev->ram_mapping, addr, 0x1000, - ncr53c8xx_ram_readb, ncr53c8xx_ram_readw, ncr53c8xx_ram_readl, - ncr53c8xx_ram_writeb, ncr53c8xx_ram_writew, ncr53c8xx_ram_writel, - NULL, MEM_MAPPING_EXTERNAL, dev); + ncr53c8xx_ram_readb, ncr53c8xx_ram_readw, ncr53c8xx_ram_readl, + ncr53c8xx_ram_writeb, ncr53c8xx_ram_writew, ncr53c8xx_ram_writel, + NULL, MEM_MAPPING_EXTERNAL, dev); } - static void ncr53c8xx_mem_set_addr(ncr53c8xx_t *dev, uint32_t base) { mem_mapping_set_addr(&dev->mmio_mapping, base, 0x100); } - static void ncr53c8xx_ram_set_addr(ncr53c8xx_t *dev, uint32_t base) { mem_mapping_set_addr(&dev->ram_mapping, base, 0x1000); } - static void ncr53c8xx_bios_set_addr(ncr53c8xx_t *dev, uint32_t base) { if (dev->has_bios == 2) - mem_mapping_set_addr(&dev->bios.mapping, base, 0x10000); + mem_mapping_set_addr(&dev->bios.mapping, base, 0x10000); else if (dev->has_bios == 1) - mem_mapping_set_addr(&dev->bios.mapping, base, 0x04000); + mem_mapping_set_addr(&dev->bios.mapping, base, 0x04000); } - static void ncr53c8xx_mem_disable(ncr53c8xx_t *dev) { mem_mapping_disable(&dev->mmio_mapping); } - static void ncr53c8xx_ram_disable(ncr53c8xx_t *dev) { mem_mapping_disable(&dev->ram_mapping); } - static void ncr53c8xx_bios_disable(ncr53c8xx_t *dev) { mem_mapping_disable(&dev->bios.mapping); } - -uint8_t ncr53c8xx_pci_regs[256]; -bar_t ncr53c8xx_pci_bar[4]; - +uint8_t ncr53c8xx_pci_regs[256]; +bar_t ncr53c8xx_pci_bar[4]; static uint8_t -ncr53c8xx_pci_read(int func, int addr, void *p) +ncr53c8xx_pci_read(UNUSED(int func), int addr, void *priv) { - ncr53c8xx_t *dev = (ncr53c8xx_t *)p; + ncr53c8xx_t *dev = (ncr53c8xx_t *) priv; ncr53c8xx_log("NCR53c8xx: Reading register %02X\n", addr & 0xff); if ((addr >= 0x80) && (addr <= 0xFF)) - return ncr53c8xx_reg_readb(dev, addr & 0x7F); + return ncr53c8xx_reg_readb(dev, addr & 0x7F); switch (addr) { - case 0x00: - return 0x00; - case 0x01: - return 0x10; - case 0x02: - return dev->chip; - case 0x03: - return 0x00; - case 0x04: - return ncr53c8xx_pci_regs[0x04] & 0x57; /*Respond to IO and memory accesses*/ - case 0x05: - return ncr53c8xx_pci_regs[0x05] & 0x01; - case 0x07: - return 2; - case 0x08: - return dev->chip_rev; /*Revision ID*/ - case 0x09: - return 0; /*Programming interface*/ - case 0x0A: - return 0; /*devubclass*/ - case 0x0B: - return 1; /*Class code*/ - case 0x0C: - case 0x0D: - return ncr53c8xx_pci_regs[addr]; - case 0x0E: - return 0; /*Header type */ - case 0x10: - return 1; /*I/O space*/ - case 0x11: - return ncr53c8xx_pci_bar[0].addr_regs[1]; - case 0x12: - return ncr53c8xx_pci_bar[0].addr_regs[2]; - case 0x13: - return ncr53c8xx_pci_bar[0].addr_regs[3]; - case 0x14: - return 0; /*Memory space*/ - case 0x15: - return ncr53c8xx_pci_bar[1].addr_regs[1]; - case 0x16: - return ncr53c8xx_pci_bar[1].addr_regs[2]; - case 0x17: - return ncr53c8xx_pci_bar[1].addr_regs[3]; - case 0x18: - return 0; /*Memory space*/ - case 0x19: - if (!dev->wide) - return 0; - return ncr53c8xx_pci_bar[2].addr_regs[1]; - case 0x1A: - if (!dev->wide) - return 0; - return ncr53c8xx_pci_bar[2].addr_regs[2]; - case 0x1B: - if (!dev->wide) - return 0; - return ncr53c8xx_pci_bar[2].addr_regs[3]; - case 0x2C: - return 0x00; - case 0x2D: - if (dev->wide) - return 0; - return 0x10; - case 0x2E: - if (dev->wide) - return 0; - return 0x01; - case 0x2F: - return 0x00; - case 0x30: - return ncr53c8xx_pci_bar[3].addr_regs[0] & 0x01; - case 0x31: - return ncr53c8xx_pci_bar[3].addr_regs[1]; - case 0x32: - return ncr53c8xx_pci_bar[3].addr_regs[2]; - case 0x33: - return ncr53c8xx_pci_bar[3].addr_regs[3]; - case 0x3C: - return dev->irq; - case 0x3D: - return PCI_INTA; - case 0x3E: - return 0x11; - case 0x3F: - return 0x40; + case 0x00: + return 0x00; + case 0x01: + return 0x10; + case 0x02: + return dev->chip; + case 0x03: + return 0x00; + case 0x04: + return ncr53c8xx_pci_regs[0x04] & 0x57; /*Respond to IO and memory accesses*/ + case 0x05: + return ncr53c8xx_pci_regs[0x05] & 0x01; + case 0x07: + return 2; + case 0x08: + return dev->chip_rev; /*Revision ID*/ + case 0x09: + return 0; /*Programming interface*/ + case 0x0A: + return 0; /*devubclass*/ + case 0x0B: + return 1; /*Class code*/ + case 0x0C: + case 0x0D: + return ncr53c8xx_pci_regs[addr]; + case 0x0E: + return 0; /*Header type */ + case 0x10: + return 1; /*I/O space*/ + case 0x11: + return ncr53c8xx_pci_bar[0].addr_regs[1]; + case 0x12: + return ncr53c8xx_pci_bar[0].addr_regs[2]; + case 0x13: + return ncr53c8xx_pci_bar[0].addr_regs[3]; + case 0x14: + return 0; /*Memory space*/ + case 0x15: + return ncr53c8xx_pci_bar[1].addr_regs[1]; + case 0x16: + return ncr53c8xx_pci_bar[1].addr_regs[2]; + case 0x17: + return ncr53c8xx_pci_bar[1].addr_regs[3]; + case 0x18: + return 0; /*Memory space*/ + case 0x19: + if (!dev->wide) + return 0; + return ncr53c8xx_pci_bar[2].addr_regs[1]; + case 0x1A: + if (!dev->wide) + return 0; + return ncr53c8xx_pci_bar[2].addr_regs[2]; + case 0x1B: + if (!dev->wide) + return 0; + return ncr53c8xx_pci_bar[2].addr_regs[3]; + case 0x2C: + return 0x00; + case 0x2D: + if (dev->wide) + return 0; + return 0x10; + case 0x2E: + if (dev->wide) + return 0; + return 0x01; + case 0x2F: + return 0x00; + case 0x30: + return ncr53c8xx_pci_bar[3].addr_regs[0] & 0x01; + case 0x31: + return ncr53c8xx_pci_bar[3].addr_regs[1]; + case 0x32: + return ncr53c8xx_pci_bar[3].addr_regs[2]; + case 0x33: + return ncr53c8xx_pci_bar[3].addr_regs[3]; + case 0x3C: + return dev->irq; + case 0x3D: + return PCI_INTA; + case 0x3E: + return 0x11; + case 0x3F: + return 0x40; + + default: + break; } - return(0); + return 0; } - static void -ncr53c8xx_pci_write(int func, int addr, uint8_t val, void *p) +ncr53c8xx_pci_write(UNUSED(int func), int addr, uint8_t val, void *priv) { - ncr53c8xx_t *dev = (ncr53c8xx_t *)p; - uint8_t valxor; + ncr53c8xx_t *dev = (ncr53c8xx_t *) priv; + uint8_t valxor; ncr53c8xx_log("NCR53c8xx: Write value %02X to register %02X\n", val, addr & 0xff); if ((addr >= 0x80) && (addr <= 0xFF)) { - ncr53c8xx_reg_writeb(dev, addr & 0x7F, val); - return; + ncr53c8xx_reg_writeb(dev, addr & 0x7F, val); + return; } - switch (addr) - { - case 0x04: - valxor = (val & 0x57) ^ ncr53c8xx_pci_regs[addr]; - if (valxor & PCI_COMMAND_IO) { - ncr53c8xx_io_remove(dev, dev->PCIBase, 0x0100); - if ((dev->PCIBase != 0) && (val & PCI_COMMAND_IO)) - ncr53c8xx_io_set(dev, dev->PCIBase, 0x0100); - } - if (valxor & PCI_COMMAND_MEM) { - ncr53c8xx_mem_disable(dev); - if ((dev->MMIOBase != 0) && (val & PCI_COMMAND_MEM)) - ncr53c8xx_mem_set_addr(dev, dev->MMIOBase); - if (dev->wide) { - ncr53c8xx_ram_disable(dev); - if ((dev->RAMBase != 0) && (val & PCI_COMMAND_MEM)) - ncr53c8xx_ram_set_addr(dev, dev->RAMBase); - } - } - ncr53c8xx_pci_regs[addr] = val & 0x57; - break; + switch (addr) { + case 0x04: + valxor = (val & 0x57) ^ ncr53c8xx_pci_regs[addr]; + if (valxor & PCI_COMMAND_IO) { + ncr53c8xx_io_remove(dev, dev->PCIBase, 0x0100); + if ((dev->PCIBase != 0) && (val & PCI_COMMAND_IO)) + ncr53c8xx_io_set(dev, dev->PCIBase, 0x0100); + } + if (valxor & PCI_COMMAND_MEM) { + ncr53c8xx_mem_disable(dev); + if ((dev->MMIOBase != 0) && (val & PCI_COMMAND_MEM)) + ncr53c8xx_mem_set_addr(dev, dev->MMIOBase); + if (dev->wide) { + ncr53c8xx_ram_disable(dev); + if ((dev->RAMBase != 0) && (val & PCI_COMMAND_MEM)) + ncr53c8xx_ram_set_addr(dev, dev->RAMBase); + } + } + ncr53c8xx_pci_regs[addr] = val & 0x57; + break; - case 0x05: - ncr53c8xx_pci_regs[addr] = val & 0x01; - break; + case 0x05: + ncr53c8xx_pci_regs[addr] = val & 0x01; + break; - case 0x0C: - case 0x0D: - ncr53c8xx_pci_regs[addr] = val; - break; + case 0x0C: + case 0x0D: + ncr53c8xx_pci_regs[addr] = val; + break; - case 0x10: case 0x11: case 0x12: case 0x13: - /* I/O Base set. */ - /* First, remove the old I/O. */ - ncr53c8xx_io_remove(dev, dev->PCIBase, 0x0100); - /* Then let's set the PCI regs. */ - ncr53c8xx_pci_bar[0].addr_regs[addr & 3] = val; - /* Then let's calculate the new I/O base. */ - ncr53c8xx_pci_bar[0].addr &= 0xff00; - dev->PCIBase = ncr53c8xx_pci_bar[0].addr; - /* Log the new base. */ - ncr53c8xx_log("NCR53c8xx: New I/O base is %04X\n" , dev->PCIBase); - /* We're done, so get out of the here. */ - if (ncr53c8xx_pci_regs[4] & PCI_COMMAND_IO) { - if (dev->PCIBase != 0) { - ncr53c8xx_io_set(dev, dev->PCIBase, 0x0100); - } - } - return; + case 0x10: + case 0x11: + case 0x12: + case 0x13: + /* I/O Base set. */ + /* First, remove the old I/O. */ + ncr53c8xx_io_remove(dev, dev->PCIBase, 0x0100); + /* Then let's set the PCI regs. */ + ncr53c8xx_pci_bar[0].addr_regs[addr & 3] = val; + /* Then let's calculate the new I/O base. */ + ncr53c8xx_pci_bar[0].addr &= 0xff00; + dev->PCIBase = ncr53c8xx_pci_bar[0].addr; + /* Log the new base. */ + ncr53c8xx_log("NCR53c8xx: New I/O base is %04X\n", dev->PCIBase); + /* We're done, so get out of the here. */ + if (ncr53c8xx_pci_regs[4] & PCI_COMMAND_IO) { + if (dev->PCIBase != 0) { + ncr53c8xx_io_set(dev, dev->PCIBase, 0x0100); + } + } + return; - case 0x15: case 0x16: case 0x17: - /* MMIO Base set. */ - /* First, remove the old I/O. */ - ncr53c8xx_mem_disable(dev); - /* Then let's set the PCI regs. */ - ncr53c8xx_pci_bar[1].addr_regs[addr & 3] = val; - /* Then let's calculate the new I/O base. */ - ncr53c8xx_pci_bar[1].addr &= 0xffffc000; - dev->MMIOBase = ncr53c8xx_pci_bar[1].addr & 0xffffc000; - /* Log the new base. */ - ncr53c8xx_log("NCR53c8xx: New MMIO base is %08X\n" , dev->MMIOBase); - /* We're done, so get out of the here. */ - if (ncr53c8xx_pci_regs[4] & PCI_COMMAND_MEM) { - if (dev->MMIOBase != 0) - ncr53c8xx_mem_set_addr(dev, dev->MMIOBase); - } - return; + case 0x15: + case 0x16: + case 0x17: + /* MMIO Base set. */ + /* First, remove the old I/O. */ + ncr53c8xx_mem_disable(dev); + /* Then let's set the PCI regs. */ + ncr53c8xx_pci_bar[1].addr_regs[addr & 3] = val; + /* Then let's calculate the new I/O base. */ + ncr53c8xx_pci_bar[1].addr &= 0xffffc000; + dev->MMIOBase = ncr53c8xx_pci_bar[1].addr & 0xffffc000; + /* Log the new base. */ + ncr53c8xx_log("NCR53c8xx: New MMIO base is %08X\n", dev->MMIOBase); + /* We're done, so get out of the here. */ + if (ncr53c8xx_pci_regs[4] & PCI_COMMAND_MEM) { + if (dev->MMIOBase != 0) + ncr53c8xx_mem_set_addr(dev, dev->MMIOBase); + } + return; - case 0x19: case 0x1A: case 0x1B: - if (!dev->wide) - return; - /* RAM Base set. */ - /* First, remove the old I/O. */ - ncr53c8xx_ram_disable(dev); - /* Then let's set the PCI regs. */ - ncr53c8xx_pci_bar[2].addr_regs[addr & 3] = val; - /* Then let's calculate the new I/O base. */ - ncr53c8xx_pci_bar[2].addr &= 0xfffff000; - dev->RAMBase = ncr53c8xx_pci_bar[2].addr & 0xfffff000; - /* Log the new base. */ - ncr53c8xx_log("NCR53c8xx: New RAM base is %08X\n" , dev->RAMBase); - /* We're done, so get out of the here. */ - if (ncr53c8xx_pci_regs[4] & PCI_COMMAND_MEM) { - if (dev->RAMBase != 0) - ncr53c8xx_ram_set_addr(dev, dev->RAMBase); - } - return; + case 0x19: + case 0x1A: + case 0x1B: + if (!dev->wide) + return; + /* RAM Base set. */ + /* First, remove the old I/O. */ + ncr53c8xx_ram_disable(dev); + /* Then let's set the PCI regs. */ + ncr53c8xx_pci_bar[2].addr_regs[addr & 3] = val; + /* Then let's calculate the new I/O base. */ + ncr53c8xx_pci_bar[2].addr &= 0xfffff000; + dev->RAMBase = ncr53c8xx_pci_bar[2].addr & 0xfffff000; + /* Log the new base. */ + ncr53c8xx_log("NCR53c8xx: New RAM base is %08X\n", dev->RAMBase); + /* We're done, so get out of the here. */ + if (ncr53c8xx_pci_regs[4] & PCI_COMMAND_MEM) { + if (dev->RAMBase != 0) + ncr53c8xx_ram_set_addr(dev, dev->RAMBase); + } + return; - case 0x30: case 0x31: case 0x32: case 0x33: - if (dev->has_bios == 0) - return; - /* BIOS Base set. */ - /* First, remove the old I/O. */ - ncr53c8xx_bios_disable(dev); - /* Then let's set the PCI regs. */ - ncr53c8xx_pci_bar[3].addr_regs[addr & 3] = val; - /* Then let's calculate the new I/O base. */ - ncr53c8xx_pci_bar[3].addr &= (dev->bios_mask | 0x00000001); - dev->BIOSBase = ncr53c8xx_pci_bar[3].addr & dev->bios_mask; - ncr53c8xx_log("BIOS BAR: %08X\n", dev->BIOSBase | ncr53c8xx_pci_bar[3].addr_regs[0]); - /* Log the new base. */ - ncr53c8xx_log("NCR53c8xx: New BIOS base is %08X\n" , dev->BIOSBase); - /* We're done, so get out of the here. */ - if (ncr53c8xx_pci_bar[3].addr_regs[0] & 0x01) - ncr53c8xx_bios_set_addr(dev, dev->BIOSBase); - return; + case 0x30: + case 0x31: + case 0x32: + case 0x33: + if (dev->has_bios == 0) + return; + /* BIOS Base set. */ + /* First, remove the old I/O. */ + ncr53c8xx_bios_disable(dev); + /* Then let's set the PCI regs. */ + ncr53c8xx_pci_bar[3].addr_regs[addr & 3] = val; + /* Then let's calculate the new I/O base. */ + ncr53c8xx_pci_bar[3].addr &= (dev->bios_mask | 0x00000001); + dev->BIOSBase = ncr53c8xx_pci_bar[3].addr & dev->bios_mask; + ncr53c8xx_log("BIOS BAR: %08X\n", dev->BIOSBase | ncr53c8xx_pci_bar[3].addr_regs[0]); + /* Log the new base. */ + ncr53c8xx_log("NCR53c8xx: New BIOS base is %08X\n", dev->BIOSBase); + /* We're done, so get out of the here. */ + if (ncr53c8xx_pci_bar[3].addr_regs[0] & 0x01) + ncr53c8xx_bios_set_addr(dev, dev->BIOSBase); + return; - case 0x3C: - ncr53c8xx_pci_regs[addr] = val; - dev->irq = val; - return; + case 0x3C: + ncr53c8xx_pci_regs[addr] = val; + dev->irq = val; + return; + + default: + break; } } - static void * ncr53c8xx_init(const device_t *info) { @@ -2518,72 +2532,72 @@ ncr53c8xx_init(const device_t *info) dev->bus = scsi_get_bus(); dev->chip_rev = 0; - dev->chip = info->local & 0xff; + dev->chip = info->local & 0xff; if ((dev->chip != CHIP_810) && (dev->chip != CHIP_820) && !(info->local & 0x8000)) { - dev->has_bios = device_get_config_int("bios"); + dev->has_bios = device_get_config_int("bios"); - /* We have to auto-patch the BIOS to have the correct PCI Device ID, because for some reason, they all ship with - the PCI Device ID set to that of the NCR 53c825, but for a machine BIOS to load the SCSI BIOS correctly, the - PCI Device ID in the BIOS' PCIR block must match the one returned in the PCI registers. */ - if (dev->has_bios == 2) { - rom_init(&dev->bios, SYM53C8XX_SDMS4_ROM, 0xd0000, 0x10000, 0xffff, 0, MEM_MAPPING_EXTERNAL); - ncr53c8xx_log("BIOS v4.19: Old BIOS CHIP ID: %02X, old BIOS checksum: %02X\n", dev->bios.rom[0x0022], dev->bios.rom[0xffff]); - dev->bios.rom[0xffff] += (dev->bios.rom[0x0022] - dev->chip); - dev->bios.rom[0x0022] = dev->chip; - ncr53c8xx_log("BIOS v4.19: New BIOS CHIP ID: %02X, old BIOS checksum: %02X\n", dev->bios.rom[0x0022], dev->bios.rom[0xffff]); - } else if (dev->has_bios == 1) { - rom_init(&dev->bios, NCR53C8XX_SDMS3_ROM, 0xc8000, 0x4000, 0x3fff, 0, MEM_MAPPING_EXTERNAL); - ncr53c8xx_log("BIOS v3.07: Old BIOS CHIP ID: %02X, old BIOS checksum: %02X\n", dev->bios.rom[0x3fcb], dev->bios.rom[0x3fff]); - dev->bios.rom[0x3fff] += (dev->bios.rom[0x3fcb] - dev->chip); - dev->bios.rom[0x3fcb] = dev->chip; - ncr53c8xx_log("BIOS v3.07: New BIOS CHIP ID: %02X, old BIOS checksum: %02X\n", dev->bios.rom[0x3fcb], dev->bios.rom[0x3fff]); - } + /* We have to auto-patch the BIOS to have the correct PCI Device ID, because for some reason, they all ship with + the PCI Device ID set to that of the NCR 53c825, but for a machine BIOS to load the SCSI BIOS correctly, the + PCI Device ID in the BIOS' PCIR block must match the one returned in the PCI registers. */ + if (dev->has_bios == 2) { + rom_init(&dev->bios, SYM53C8XX_SDMS4_ROM, 0xd0000, 0x10000, 0xffff, 0, MEM_MAPPING_EXTERNAL); + ncr53c8xx_log("BIOS v4.19: Old BIOS CHIP ID: %02X, old BIOS checksum: %02X\n", dev->bios.rom[0x0022], dev->bios.rom[0xffff]); + dev->bios.rom[0xffff] += (dev->bios.rom[0x0022] - dev->chip); + dev->bios.rom[0x0022] = dev->chip; + ncr53c8xx_log("BIOS v4.19: New BIOS CHIP ID: %02X, old BIOS checksum: %02X\n", dev->bios.rom[0x0022], dev->bios.rom[0xffff]); + } else if (dev->has_bios == 1) { + rom_init(&dev->bios, NCR53C8XX_SDMS3_ROM, 0xc8000, 0x4000, 0x3fff, 0, MEM_MAPPING_EXTERNAL); + ncr53c8xx_log("BIOS v3.07: Old BIOS CHIP ID: %02X, old BIOS checksum: %02X\n", dev->bios.rom[0x3fcb], dev->bios.rom[0x3fff]); + dev->bios.rom[0x3fff] += (dev->bios.rom[0x3fcb] - dev->chip); + dev->bios.rom[0x3fcb] = dev->chip; + ncr53c8xx_log("BIOS v3.07: New BIOS CHIP ID: %02X, old BIOS checksum: %02X\n", dev->bios.rom[0x3fcb], dev->bios.rom[0x3fff]); + } } else - dev->has_bios = 0; + dev->has_bios = 0; if (info->local & 0x8000) - dev->pci_slot = pci_add_card(PCI_ADD_SCSI, ncr53c8xx_pci_read, ncr53c8xx_pci_write, dev); + pci_add_card(PCI_ADD_SCSI, ncr53c8xx_pci_read, ncr53c8xx_pci_write, dev, &dev->pci_slot); else - dev->pci_slot = pci_add_card(PCI_ADD_NORMAL, ncr53c8xx_pci_read, ncr53c8xx_pci_write, dev); + pci_add_card(PCI_ADD_NORMAL, ncr53c8xx_pci_read, ncr53c8xx_pci_write, dev, &dev->pci_slot); if (dev->chip == CHIP_875) { - dev->chip_rev = 0x04; - dev->nvr_path = "ncr53c875.nvr"; - dev->wide = 1; + dev->chip_rev = 0x04; + dev->nvr_path = "ncr53c875.nvr"; + dev->wide = 1; } else if (dev->chip == CHIP_860) { - dev->chip_rev = 0x04; - dev->nvr_path = "ncr53c860.nvr"; - dev->wide = 1; + dev->chip_rev = 0x04; + dev->nvr_path = "ncr53c860.nvr"; + dev->wide = 1; } else if (dev->chip == CHIP_820) { - dev->nvr_path = "ncr53c820.nvr"; - dev->wide = 1; + dev->nvr_path = "ncr53c820.nvr"; + dev->wide = 1; } else if (dev->chip == CHIP_825) { - dev->chip_rev = 0x26; - dev->nvr_path = "ncr53c825a.nvr"; - dev->wide = 1; + dev->chip_rev = 0x26; + dev->nvr_path = "ncr53c825a.nvr"; + dev->wide = 1; } else if (dev->chip == CHIP_810) { - dev->nvr_path = "ncr53c810.nvr"; - dev->wide = 0; + dev->nvr_path = "ncr53c810.nvr"; + dev->wide = 0; } else if (dev->chip == CHIP_815) { - dev->chip_rev = 0x04; - dev->nvr_path = "ncr53c815.nvr"; - dev->wide = 0; + dev->chip_rev = 0x04; + dev->nvr_path = "ncr53c815.nvr"; + dev->wide = 0; } ncr53c8xx_pci_bar[0].addr_regs[0] = 1; - ncr53c8xx_pci_bar[1].addr_regs[0] = 0; - ncr53c8xx_pci_regs[0x04] = 3; + ncr53c8xx_pci_bar[1].addr_regs[0] = 0; + ncr53c8xx_pci_regs[0x04] = 3; if (dev->has_bios == 2) { - ncr53c8xx_pci_bar[3].addr = 0xffff0000; - dev->bios_mask = 0xffff0000; + ncr53c8xx_pci_bar[3].addr = 0xffff0000; + dev->bios_mask = 0xffff0000; } else if (dev->has_bios == 1) { - ncr53c8xx_pci_bar[3].addr = 0xffffc000; - dev->bios_mask = 0xffffc000; + ncr53c8xx_pci_bar[3].addr = 0xffffc000; + dev->bios_mask = 0xffffc000; } else { - ncr53c8xx_pci_bar[3].addr = 0x00000000; - dev->bios_mask = 0x00000000; + ncr53c8xx_pci_bar[3].addr = 0x00000000; + dev->bios_mask = 0x00000000; } ncr53c8xx_mem_init(dev, 0x0fffff00); @@ -2592,14 +2606,14 @@ ncr53c8xx_init(const device_t *info) ncr53c8xx_pci_bar[2].addr_regs[0] = 0; if (dev->wide) { - ncr53c8xx_ram_init(dev, 0x0ffff000); - ncr53c8xx_ram_disable(dev); + ncr53c8xx_ram_init(dev, 0x0ffff000); + ncr53c8xx_ram_disable(dev); } - - if (dev->has_bios) - ncr53c8xx_bios_disable(dev); - dev->i2c = i2c_gpio_init("nvr_ncr53c8xx"); + if (dev->has_bios) + ncr53c8xx_bios_disable(dev); + + dev->i2c = i2c_gpio_init("nvr_ncr53c8xx"); dev->eeprom = i2c_eeprom_init(i2c_gpio_get_bus(dev->i2c), 0x50, dev->nvram, sizeof(dev->nvram), 1); /* Load the serial EEPROM. */ @@ -2609,127 +2623,146 @@ ncr53c8xx_init(const device_t *info) timer_add(&dev->timer, ncr53c8xx_callback, dev, 0); - return(dev); + scsi_bus_set_speed(dev->bus, 10000000.0); + + return dev; } - -static void +static void ncr53c8xx_close(void *priv) { - ncr53c8xx_t *dev = (ncr53c8xx_t *)priv; + ncr53c8xx_t *dev = (ncr53c8xx_t *) priv; if (dev) { - if (dev->eeprom) - i2c_eeprom_close(dev->eeprom); + if (dev->eeprom) + i2c_eeprom_close(dev->eeprom); - if (dev->i2c) - i2c_gpio_close(dev->i2c); + if (dev->i2c) + i2c_gpio_close(dev->i2c); - /* Save the serial EEPROM. */ - ncr53c8xx_eeprom(dev, 1); + /* Save the serial EEPROM. */ + ncr53c8xx_eeprom(dev, 1); - free(dev); - dev = NULL; + free(dev); + dev = NULL; } } static const device_config_t ncr53c8xx_pci_config[] = { - { - "bios", "BIOS", CONFIG_SELECTION, "", 1, "", { 0 }, - { - { - "SDMS 4.x BIOS", 2 - }, - { - "SDMS 3.x BIOS", 1 - }, - { - "Disable BIOS", 0 - }, - { - "" - } - }, + // clang-format off + { + .name = "bios", + .description = "BIOS", + .type = CONFIG_SELECTION, + .default_string = "", + .default_int = 1, + .file_filter = "", + .spinner = { 0 }, + .selection = { + { .description = "SDMS 4.x BIOS", .value = 2 }, + { .description = "SDMS 3.x BIOS", .value = 1 }, + { .description = "Disable BIOS", .value = 0 }, + { .description = "" } }, - { - "", "", -1 - } + }, + { .name = "", .description = "", .type = CONFIG_END } + // clang-format on }; - -const device_t ncr53c810_pci_device = -{ - "NCR 53c810", - "ncr53c810", - DEVICE_PCI, - CHIP_810, - ncr53c8xx_init, ncr53c8xx_close, NULL, - { NULL }, NULL, NULL, - NULL +const device_t ncr53c810_pci_device = { + .name = "NCR 53c810", + .internal_name = "ncr53c810", + .flags = DEVICE_PCI, + .local = CHIP_810, + .init = ncr53c8xx_init, + .close = ncr53c8xx_close, + .reset = NULL, + { .available = NULL }, + .speed_changed = NULL, + .force_redraw = NULL, + .config = NULL }; -const device_t ncr53c810_onboard_pci_device = -{ - "NCR 53c810 On-Board", - "ncr53c810_onboard", - DEVICE_PCI, - 0x8001, - ncr53c8xx_init, ncr53c8xx_close, NULL, - { NULL }, NULL, NULL, - NULL +const device_t ncr53c810_onboard_pci_device = { + .name = "NCR 53c810 On-Board", + .internal_name = "ncr53c810_onboard", + .flags = DEVICE_PCI, + .local = 0x8001, + .init = ncr53c8xx_init, + .close = ncr53c8xx_close, + .reset = NULL, + { .available = NULL }, + .speed_changed = NULL, + .force_redraw = NULL, + .config = NULL }; -const device_t ncr53c815_pci_device = -{ - "NCR 53c815", - "ncr53c815", - DEVICE_PCI, - CHIP_815, - ncr53c8xx_init, ncr53c8xx_close, NULL, - { NULL }, NULL, NULL, +const device_t ncr53c815_pci_device = { + .name = "NCR 53c815", + .internal_name = "ncr53c815", + .flags = DEVICE_PCI, + .local = CHIP_815, + .init = ncr53c8xx_init, + .close = ncr53c8xx_close, + .reset = NULL, + { .available = NULL }, + .speed_changed = NULL, + .force_redraw = NULL, ncr53c8xx_pci_config }; -const device_t ncr53c820_pci_device = -{ - "NCR 53c820", - "ncr53c820", - DEVICE_PCI, - CHIP_820, - ncr53c8xx_init, ncr53c8xx_close, NULL, - { NULL }, NULL, NULL, - NULL +const device_t ncr53c820_pci_device = { + .name = "NCR 53c820", + .internal_name = "ncr53c820", + .flags = DEVICE_PCI, + .local = CHIP_820, + .init = ncr53c8xx_init, + .close = ncr53c8xx_close, + .reset = NULL, + { .available = NULL }, + .speed_changed = NULL, + .force_redraw = NULL, + .config = NULL }; -const device_t ncr53c825a_pci_device = -{ - "NCR 53c825A", - "ncr53c825a", - DEVICE_PCI, - CHIP_825, - ncr53c8xx_init, ncr53c8xx_close, NULL, - { NULL }, NULL, NULL, - ncr53c8xx_pci_config +const device_t ncr53c825a_pci_device = { + .name = "NCR 53c825A", + .internal_name = "ncr53c825a", + .flags = DEVICE_PCI, + .local = CHIP_825, + .init = ncr53c8xx_init, + .close = ncr53c8xx_close, + .reset = NULL, + { .available = NULL }, + .speed_changed = NULL, + .force_redraw = NULL, + .config = ncr53c8xx_pci_config }; -const device_t ncr53c860_pci_device = -{ - "NCR 53c860", - "ncr53c860", - DEVICE_PCI, - CHIP_860, - ncr53c8xx_init, ncr53c8xx_close, NULL, - { NULL }, NULL, NULL, - ncr53c8xx_pci_config +const device_t ncr53c860_pci_device = { + .name = "NCR 53c860", + .internal_name = "ncr53c860", + .flags = DEVICE_PCI, + .local = CHIP_860, + .init = ncr53c8xx_init, + .close = ncr53c8xx_close, + .reset = NULL, + { .available = NULL }, + .speed_changed = NULL, + .force_redraw = NULL, + .config = ncr53c8xx_pci_config }; -const device_t ncr53c875_pci_device = -{ - "NCR 53c875", - "ncr53c875", - DEVICE_PCI, - CHIP_875, - ncr53c8xx_init, ncr53c8xx_close, NULL, - { NULL }, NULL, NULL, - ncr53c8xx_pci_config +const device_t ncr53c875_pci_device = { + .name = "NCR 53c875", + .internal_name = "ncr53c875", + .flags = DEVICE_PCI, + .local = CHIP_875, + .init = ncr53c8xx_init, + .close = ncr53c8xx_close, + .reset = NULL, + { .available = NULL }, + .speed_changed = NULL, + .force_redraw = NULL, + .config = ncr53c8xx_pci_config }; diff --git a/src/scsi/scsi_pcscsi.c b/src/scsi/scsi_pcscsi.c index cd0b7e426..7bf06b1c0 100644 --- a/src/scsi/scsi_pcscsi.c +++ b/src/scsi/scsi_pcscsi.c @@ -1,25 +1,24 @@ /* - * 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. + * 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. + * This file is part of the 86Box distribution. * - * Implementation of the Tekram DC-390 SCSI and related MCA - * controllers using the NCR 53c9x series of chips. + * Implementation of the Tekram DC-390 SCSI and related MCA + * controllers using the NCR 53c9x series of chips. * * * + * Authors: Fabrice Bellard (QEMU) + * Herve Poussineau (QEMU) + * TheCollector1995, + * Miran Grca, * - * Authors: Fabrice Bellard (QEMU) - * Herve Poussineau (QEMU) - * TheCollector1995, - * Miran Grca, - * - * Copyright 2005-2018 Fabrice Bellard. - * Copyright 2012-2018 Herve Poussineau. - * Copyright 2017,2018 Miran Grca. + * Copyright 2005-2018 Fabrice Bellard. + * Copyright 2012-2018 Herve Poussineau. + * Copyright 2017-2018 Miran Grca. */ #include #include @@ -47,98 +46,98 @@ #include <86box/vid_ati_eeprom.h> #include <86box/fifo8.h> -#define DC390_ROM "roms/scsi/esp_pci/INT13.BIN" +#define DC390_ROM "roms/scsi/esp_pci/INT13.BIN" -#define ESP_REGS 16 -#define ESP_FIFO_SZ 16 -#define ESP_CMDFIFO_SZ 32 +#define ESP_REGS 16 +#define ESP_FIFO_SZ 16 +#define ESP_CMDFIFO_SZ 32 -#define ESP_TCLO 0x0 -#define ESP_TCMID 0x1 -#define ESP_FIFO 0x2 -#define ESP_CMD 0x3 -#define ESP_RSTAT 0x4 -#define ESP_WBUSID 0x4 -#define ESP_RINTR 0x5 -#define ESP_WSEL 0x5 -#define ESP_RSEQ 0x6 -#define ESP_WSYNTP 0x6 -#define ESP_RFLAGS 0x7 -#define ESP_WSYNO 0x7 -#define ESP_CFG1 0x8 -#define ESP_RRES1 0x9 -#define ESP_WCCF 0x9 -#define ESP_RRES2 0xa -#define ESP_WTEST 0xa -#define ESP_CFG2 0xb -#define ESP_CFG3 0xc -#define ESP_RES3 0xd -#define ESP_TCHI 0xe -#define ESP_RES4 0xf +#define ESP_TCLO 0x0 +#define ESP_TCMID 0x1 +#define ESP_FIFO 0x2 +#define ESP_CMD 0x3 +#define ESP_RSTAT 0x4 +#define ESP_WBUSID 0x4 +#define ESP_RINTR 0x5 +#define ESP_WSEL 0x5 +#define ESP_RSEQ 0x6 +#define ESP_WSYNTP 0x6 +#define ESP_RFLAGS 0x7 +#define ESP_WSYNO 0x7 +#define ESP_CFG1 0x8 +#define ESP_RRES1 0x9 +#define ESP_WCCF 0x9 +#define ESP_RRES2 0xa +#define ESP_WTEST 0xa +#define ESP_CFG2 0xb +#define ESP_CFG3 0xc +#define ESP_RES3 0xd +#define ESP_TCHI 0xe +#define ESP_RES4 0xf -#define CMD_DMA 0x80 -#define CMD_CMD 0x7f +#define CMD_DMA 0x80 +#define CMD_CMD 0x7f -#define CMD_NOP 0x00 -#define CMD_FLUSH 0x01 -#define CMD_RESET 0x02 -#define CMD_BUSRESET 0x03 -#define CMD_TI 0x10 -#define CMD_ICCS 0x11 -#define CMD_MSGACC 0x12 -#define CMD_PAD 0x18 -#define CMD_SATN 0x1a -#define CMD_RSTATN 0x1b -#define CMD_SEL 0x41 -#define CMD_SELATN 0x42 -#define CMD_SELATNS 0x43 -#define CMD_ENSEL 0x44 -#define CMD_DISSEL 0x45 +#define CMD_NOP 0x00 +#define CMD_FLUSH 0x01 +#define CMD_RESET 0x02 +#define CMD_BUSRESET 0x03 +#define CMD_TI 0x10 +#define CMD_ICCS 0x11 +#define CMD_MSGACC 0x12 +#define CMD_PAD 0x18 +#define CMD_SATN 0x1a +#define CMD_RSTATN 0x1b +#define CMD_SEL 0x41 +#define CMD_SELATN 0x42 +#define CMD_SELATNS 0x43 +#define CMD_ENSEL 0x44 +#define CMD_DISSEL 0x45 -#define STAT_DO 0x00 -#define STAT_DI 0x01 -#define STAT_CD 0x02 -#define STAT_ST 0x03 -#define STAT_MO 0x06 -#define STAT_MI 0x07 -#define STAT_PIO_MASK 0x06 +#define STAT_DO 0x00 +#define STAT_DI 0x01 +#define STAT_CD 0x02 +#define STAT_ST 0x03 +#define STAT_MO 0x06 +#define STAT_MI 0x07 +#define STAT_PIO_MASK 0x06 -#define STAT_TC 0x10 -#define STAT_PE 0x20 -#define STAT_GE 0x40 -#define STAT_INT 0x80 +#define STAT_TC 0x10 +#define STAT_PE 0x20 +#define STAT_GE 0x40 +#define STAT_INT 0x80 -#define BUSID_DID 0x07 +#define BUSID_DID 0x07 -#define INTR_FC 0x08 -#define INTR_BS 0x10 -#define INTR_DC 0x20 -#define INTR_RST 0x80 +#define INTR_FC 0x08 +#define INTR_BS 0x10 +#define INTR_DC 0x20 +#define INTR_RST 0x80 -#define SEQ_0 0x0 -#define SEQ_MO 0x1 -#define SEQ_CD 0x4 +#define SEQ_0 0x0 +#define SEQ_MO 0x1 +#define SEQ_CD 0x4 -#define CFG1_RESREPT 0x40 +#define CFG1_RESREPT 0x40 -#define TCHI_FAS100A 0x04 -#define TCHI_AM53C974 0x12 +#define TCHI_FAS100A 0x04 +#define TCHI_AM53C974 0x12 -#define DMA_CMD 0x0 -#define DMA_STC 0x1 -#define DMA_SPA 0x2 -#define DMA_WBC 0x3 -#define DMA_WAC 0x4 -#define DMA_STAT 0x5 -#define DMA_SMDLA 0x6 -#define DMA_WMAC 0x7 +#define DMA_CMD 0x0 +#define DMA_STC 0x1 +#define DMA_SPA 0x2 +#define DMA_WBC 0x3 +#define DMA_WAC 0x4 +#define DMA_STAT 0x5 +#define DMA_SMDLA 0x6 +#define DMA_WMAC 0x7 -#define DMA_CMD_MASK 0x03 -#define DMA_CMD_DIAG 0x04 -#define DMA_CMD_MDL 0x10 -#define DMA_CMD_INTE_P 0x20 -#define DMA_CMD_INTE_D 0x40 -#define DMA_CMD_DIR 0x80 +#define DMA_CMD_MASK 0x03 +#define DMA_CMD_DIAG 0x04 +#define DMA_CMD_MDL 0x10 +#define DMA_CMD_INTE_P 0x20 +#define DMA_CMD_INTE_D 0x40 +#define DMA_CMD_DIR 0x80 #define DMA_STAT_PWDN 0x01 #define DMA_STAT_ERROR 0x02 @@ -147,38 +146,38 @@ #define DMA_STAT_SCSIINT 0x10 #define DMA_STAT_BCMBLT 0x20 -#define SBAC_STATUS (1 << 24) -#define SBAC_PABTEN (1 << 25) +#define SBAC_STATUS (1 << 24) +#define SBAC_PABTEN (1 << 25) -typedef struct { +typedef struct esp_t { mem_mapping_t mmio_mapping; - mem_mapping_t ram_mapping; - char *nvr_path; - uint8_t pci_slot; - int has_bios; - int BIOSBase; - int MMIOBase; - rom_t bios; - ati_eeprom_t eeprom; - int PCIBase; + mem_mapping_t ram_mapping; + char *nvr_path; + uint8_t pci_slot; + int has_bios; + int BIOSBase; + int MMIOBase; + rom_t bios; + ati_eeprom_t eeprom; + int PCIBase; - uint8_t rregs[ESP_REGS]; - uint8_t wregs[ESP_REGS]; - int irq; - int tchi_written; + uint8_t rregs[ESP_REGS]; + uint8_t wregs[ESP_REGS]; + int irq; + int tchi_written; uint32_t ti_size; uint32_t status; uint32_t dma; - Fifo8 fifo; - uint8_t bus; - uint8_t id, lun; - Fifo8 cmdfifo; + Fifo8 fifo; + uint8_t bus; + uint8_t id, lun; + Fifo8 cmdfifo; uint32_t do_cmd; - uint8_t cmdfifo_cdb_offset; + uint8_t cmdfifo_cdb_offset; int32_t xfer_counter; - int dma_enabled; - + int dma_enabled; + uint32_t buffer_pos; uint32_t dma_regs[8]; uint32_t sbac; @@ -186,42 +185,41 @@ typedef struct { double period; pc_timer_t timer; - - int mca; - uint16_t Base; - uint8_t HostID, DmaChannel; - - struct - { - uint8_t mode; - uint8_t status; - int pos; - } dma_86c01; - - uint8_t pos_regs[8]; + + int mca; + uint16_t Base; + uint8_t HostID; + uint8_t DmaChannel; + + struct { + uint8_t mode; + uint8_t status; + int pos; + } dma_86c01; + + uint8_t irq_state; + uint8_t pos_regs[8]; } esp_t; #define READ_FROM_DEVICE 1 #define WRITE_TO_DEVICE 0 - #ifdef ENABLE_ESP_LOG int esp_do_log = ENABLE_ESP_LOG; - static void esp_log(const char *fmt, ...) { va_list ap; if (esp_do_log) { - va_start(ap, fmt); - pclog_ex(fmt, ap); - va_end(ap); + va_start(ap, fmt); + pclog_ex(fmt, ap); + va_end(ap); } } #else -#define esp_log(fmt, ...) +# define esp_log(fmt, ...) #endif static void esp_dma_enable(esp_t *dev, int level); @@ -238,42 +236,42 @@ static void handle_ti(void *priv); static void esp_irq(esp_t *dev, int level) { - if (dev->mca) { - if (level) { - picint(1 << dev->irq); - dev->dma_86c01.status |= 0x01; - esp_log("Raising IRQ...\n"); - } else { - picintc(1 << dev->irq); - dev->dma_86c01.status &= ~0x01; - esp_log("Lowering IRQ...\n"); - } - } else { - if (level) { - pci_set_irq(dev->pci_slot, PCI_INTA); - esp_log("Raising IRQ...\n"); - } else { - pci_clear_irq(dev->pci_slot, PCI_INTA); - esp_log("Lowering IRQ...\n"); - } - } + if (dev->mca) { + if (level) { + picint(1 << dev->irq); + dev->dma_86c01.status |= 0x01; + esp_log("Raising IRQ...\n"); + } else { + picintc(1 << dev->irq); + dev->dma_86c01.status &= ~0x01; + esp_log("Lowering IRQ...\n"); + } + } else { + if (level) { + pci_set_irq(dev->pci_slot, PCI_INTA, &dev->irq_state); + esp_log("Raising IRQ...\n"); + } else { + pci_clear_irq(dev->pci_slot, PCI_INTA, &dev->irq_state); + esp_log("Lowering IRQ...\n"); + } + } } static void esp_raise_irq(esp_t *dev) { - if (!(dev->rregs[ESP_RSTAT] & STAT_INT)) { - dev->rregs[ESP_RSTAT] |= STAT_INT; - esp_irq(dev, 1); + if (!(dev->rregs[ESP_RSTAT] & STAT_INT)) { + dev->rregs[ESP_RSTAT] |= STAT_INT; + esp_irq(dev, 1); } } static void esp_lower_irq(esp_t *dev) { - if (dev->rregs[ESP_RSTAT] & STAT_INT) { - dev->rregs[ESP_RSTAT] &= ~STAT_INT; - esp_irq(dev, 0); + if (dev->rregs[ESP_RSTAT] & STAT_INT) { + dev->rregs[ESP_RSTAT] &= ~STAT_INT; + esp_irq(dev, 0); } } @@ -301,7 +299,7 @@ static uint32_t esp_fifo_pop_buf(Fifo8 *fifo, uint8_t *dest, int maxlen) { const uint8_t *buf; - uint32_t n; + uint32_t n; if (maxlen == 0) { return 0; @@ -330,9 +328,9 @@ esp_get_tc(esp_t *dev) static void esp_set_tc(esp_t *dev, uint32_t dmalen) { - dev->rregs[ESP_TCLO] = dmalen; + dev->rregs[ESP_TCLO] = dmalen; dev->rregs[ESP_TCMID] = dmalen >> 8; - dev->rregs[ESP_TCHI] = dmalen >> 16; + dev->rregs[ESP_TCHI] = dmalen >> 16; } static uint32_t @@ -351,10 +349,10 @@ static void esp_dma_done(esp_t *dev) { dev->rregs[ESP_RSTAT] |= STAT_TC; - dev->rregs[ESP_RINTR] = INTR_BS; - dev->rregs[ESP_RSEQ] = 0; + dev->rregs[ESP_RINTR] = INTR_BS; + dev->rregs[ESP_RSEQ] = 0; dev->rregs[ESP_RFLAGS] = 0; - esp_set_tc(dev, 0); + esp_set_tc(dev, 0); esp_log("ESP DMA Finished\n"); esp_raise_irq(dev); } @@ -362,29 +360,32 @@ esp_dma_done(esp_t *dev) static uint32_t esp_get_cmd(esp_t *dev, uint32_t maxlen) { - uint8_t buf[ESP_CMDFIFO_SZ]; - uint32_t dmalen, n; - + uint8_t buf[ESP_CMDFIFO_SZ]; + uint32_t dmalen; + uint32_t n; + dev->id = dev->wregs[ESP_WBUSID] & BUSID_DID; if (dev->dma) { dmalen = MIN(esp_get_tc(dev), maxlen); - esp_log("ESP Get data, dmalen = %d\n", dmalen); - if (dmalen == 0) - return 0; - if (dev->mca) { - while (dev->dma_86c01.pos < dmalen) { - int val = dma_channel_read(dev->DmaChannel); - buf[dev->dma_86c01.pos++] = val & 0xff; - } - dev->dma_86c01.pos = 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); - } + esp_log("ESP Get data, dmalen = %d\n", dmalen); + if (dmalen == 0) + return 0; + if (dev->mca) { + dma_set_drq(dev->DmaChannel, 1); + while (dev->dma_86c01.pos < dmalen) { + int val = dma_channel_read(dev->DmaChannel); + buf[dev->dma_86c01.pos++] = val & 0xff; + } + dev->dma_86c01.pos = 0; + 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); } else { dmalen = MIN(fifo8_num_used(&dev->fifo), maxlen); - esp_log("ESP Get command, dmalen = %i\n", dmalen); + esp_log("ESP Get command, dmalen = %i\n", dmalen); if (dmalen == 0) { return 0; } @@ -394,7 +395,7 @@ esp_get_cmd(esp_t *dev, uint32_t maxlen) } dev->ti_size = 0; - fifo8_reset(&dev->fifo); + fifo8_reset(&dev->fifo); dev->rregs[ESP_RINTR] |= INTR_FC; dev->rregs[ESP_RSEQ] = SEQ_CD; @@ -405,129 +406,130 @@ esp_get_cmd(esp_t *dev, uint32_t maxlen) static void esp_do_command_phase(esp_t *dev) { - uint32_t cmdlen; - uint8_t buf[ESP_CMDFIFO_SZ]; + uint32_t cmdlen; + uint8_t buf[ESP_CMDFIFO_SZ]; scsi_device_t *sd; sd = &scsi_devices[dev->bus][dev->id]; - - sd->buffer_length = -1; - - cmdlen = fifo8_num_used(&dev->cmdfifo); - if (!cmdlen) - return; - - esp_fifo_pop_buf(&dev->cmdfifo, buf, cmdlen); - - for (int i = 0; i < cmdlen; i++) - esp_log("CDB[%i] = %02x\n", i, buf[i]); + + sd->buffer_length = -1; + + cmdlen = fifo8_num_used(&dev->cmdfifo); + if (!cmdlen) + return; + + esp_fifo_pop_buf(&dev->cmdfifo, buf, cmdlen); + + for (int i = 0; i < cmdlen; i++) + esp_log("CDB[%i] = %02x\n", i, buf[i]); scsi_device_command_phase0(sd, buf); - - dev->buffer_pos = 0; - dev->ti_size = sd->buffer_length; + + dev->buffer_pos = 0; + dev->ti_size = sd->buffer_length; dev->xfer_counter = sd->buffer_length; esp_log("ESP SCSI Command = 0x%02x, ID = %d, LUN = %d, len = %d\n", buf[0], dev->id, dev->lun, sd->buffer_length); - fifo8_reset(&dev->cmdfifo); + fifo8_reset(&dev->cmdfifo); if (sd->buffer_length > 0) { - /* This should be set to the underlying device's buffer by command phase 0. */ - dev->rregs[ESP_RSTAT] = STAT_TC; - dev->rregs[ESP_RSEQ] = SEQ_CD; + /* This should be set to the underlying device's buffer by command phase 0. */ + dev->rregs[ESP_RSTAT] = STAT_TC; + dev->rregs[ESP_RSEQ] = SEQ_CD; - if (sd->phase == SCSI_PHASE_DATA_IN) { - dev->rregs[ESP_RSTAT] |= STAT_DI; - esp_log("ESP Data In\n"); - esp_timer_on(dev, sd, scsi_device_get_callback(sd)); - } else if (sd->phase == SCSI_PHASE_DATA_OUT) { - dev->rregs[ESP_RSTAT] |= STAT_DO; - esp_log("ESP Data Out\n"); - dev->ti_size = -sd->buffer_length; - esp_timer_on(dev, sd, scsi_device_get_callback(sd)); - } - esp_log("ESP SCSI Start reading/writing\n"); - esp_do_dma(dev, sd); + if (sd->phase == SCSI_PHASE_DATA_IN) { + dev->rregs[ESP_RSTAT] |= STAT_DI; + esp_log("ESP Data In\n"); + esp_timer_on(dev, sd, scsi_device_get_callback(sd)); + } else if (sd->phase == SCSI_PHASE_DATA_OUT) { + dev->rregs[ESP_RSTAT] |= STAT_DO; + esp_log("ESP Data Out\n"); + dev->ti_size = -sd->buffer_length; + esp_timer_on(dev, sd, scsi_device_get_callback(sd)); + } + esp_log("ESP SCSI Start reading/writing\n"); + esp_do_dma(dev, sd); } else { - esp_log("ESP SCSI Command with no length\n"); - if (dev->mca) { - if (buf[0] == 0x43) { - dev->rregs[ESP_RSTAT] = STAT_DI | STAT_TC; - dev->rregs[ESP_RSEQ] = SEQ_CD; - esp_do_dma(dev, sd); - } else - esp_command_complete(dev, sd->status); - } else - esp_pci_command_complete(dev, sd->status); + esp_log("ESP SCSI Command with no length\n"); + if (dev->mca) { + if (buf[0] == 0x43) { + dev->rregs[ESP_RSTAT] = STAT_DI | STAT_TC; + dev->rregs[ESP_RSEQ] = SEQ_CD; + esp_do_dma(dev, sd); + } else + esp_command_complete(dev, sd->status); + } else + esp_pci_command_complete(dev, sd->status); } - + scsi_device_identify(sd, SCSI_LUN_USE_CDB); - - dev->rregs[ESP_RINTR] |= INTR_BS | INTR_FC; - esp_raise_irq(dev); + + dev->rregs[ESP_RINTR] |= INTR_BS | INTR_FC; + esp_raise_irq(dev); } static void esp_do_message_phase(esp_t *dev) { - int len; - uint8_t message; - - if (dev->cmdfifo_cdb_offset) { - message = esp_fifo_pop(&dev->cmdfifo); - - dev->lun = message & 7; - dev->cmdfifo_cdb_offset--; - - if (scsi_device_present(&scsi_devices[dev->bus][dev->id]) && (dev->lun > 0)) { - /* We only support LUN 0 */ - esp_log("LUN = %i\n", dev->lun); - dev->rregs[ESP_RSTAT] = 0; - dev->rregs[ESP_RINTR] = INTR_DC; - dev->rregs[ESP_RSEQ] = SEQ_0; - esp_raise_irq(dev); - fifo8_reset(&dev->cmdfifo); - return; - } - - scsi_device_identify(&scsi_devices[dev->bus][dev->id], dev->lun); - } - - esp_log("CDB offset = %i\n", dev->cmdfifo_cdb_offset); + int len; + uint8_t message; - if (dev->cmdfifo_cdb_offset) { - len = MIN(dev->cmdfifo_cdb_offset, fifo8_num_used(&dev->cmdfifo)); + if (dev->cmdfifo_cdb_offset) { + message = esp_fifo_pop(&dev->cmdfifo); + + dev->lun = message & 7; + dev->cmdfifo_cdb_offset--; + + if (scsi_device_present(&scsi_devices[dev->bus][dev->id]) && (dev->lun > 0)) { + /* We only support LUN 0 */ + esp_log("LUN = %i\n", dev->lun); + dev->rregs[ESP_RSTAT] = 0; + dev->rregs[ESP_RINTR] = INTR_DC; + dev->rregs[ESP_RSEQ] = SEQ_0; + esp_raise_irq(dev); + fifo8_reset(&dev->cmdfifo); + return; + } + + scsi_device_identify(&scsi_devices[dev->bus][dev->id], dev->lun); + } + + esp_log("CDB offset = %i\n", dev->cmdfifo_cdb_offset); + + if (dev->cmdfifo_cdb_offset) { + len = MIN(dev->cmdfifo_cdb_offset, fifo8_num_used(&dev->cmdfifo)); esp_fifo_pop_buf(&dev->cmdfifo, NULL, len); dev->cmdfifo_cdb_offset = 0; - } + } } static void esp_do_cmd(esp_t *dev) { - esp_do_message_phase(dev); - if (dev->cmdfifo_cdb_offset == 0) - esp_do_command_phase(dev); + esp_do_message_phase(dev); + if (dev->cmdfifo_cdb_offset == 0) + esp_do_command_phase(dev); } static void esp_dma_enable(esp_t *dev, int level) { if (level) { - esp_log("ESP DMA Enabled\n"); - dev->dma_enabled = 1; - dev->dma_86c01.status |= 0x02; - if ((dev->rregs[ESP_CMD] & CMD_CMD) != CMD_TI) { - timer_on_auto(&dev->timer, 40.0); - } else { - esp_log("Period = %lf\n", dev->period); - timer_on_auto(&dev->timer, dev->period); - } + esp_log("ESP DMA Enabled\n"); + dev->dma_enabled = 1; + dev->dma_86c01.status |= 0x02; + timer_stop(&dev->timer); + if (((dev->rregs[ESP_CMD] & CMD_CMD) != CMD_TI) && ((dev->rregs[ESP_CMD] & CMD_CMD) != CMD_PAD)) { + timer_on_auto(&dev->timer, 40.0); + } else { + esp_log("Period = %lf\n", dev->period); + timer_on_auto(&dev->timer, dev->period); + } } else { - esp_log("ESP DMA Disabled\n"); - dev->dma_enabled = 0; - dev->dma_86c01.status &= ~0x02; + esp_log("ESP DMA Disabled\n"); + dev->dma_enabled = 0; + dev->dma_86c01.status &= ~0x02; } } @@ -537,13 +539,15 @@ esp_hard_reset(esp_t *dev) memset(dev->rregs, 0, ESP_REGS); memset(dev->wregs, 0, ESP_REGS); dev->tchi_written = 0; - dev->ti_size = 0; + dev->ti_size = 0; fifo8_reset(&dev->fifo); - fifo8_reset(&dev->cmdfifo); - dev->dma = 0; - dev->do_cmd = 0; + fifo8_reset(&dev->cmdfifo); + dev->dma = 0; + 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); } @@ -555,257 +559,261 @@ esp_do_nodma(esp_t *dev, scsi_device_t *sd) esp_log("ESP SCSI Actual FIFO len = %d\n", dev->xfer_counter); if (dev->do_cmd) { - esp_log("ESP Command on FIFO\n"); - dev->ti_size = 0; - - if ((dev->rregs[ESP_RSTAT] & 7) == STAT_CD) { - if (dev->cmdfifo_cdb_offset == fifo8_num_used(&dev->cmdfifo)) { - esp_log("CDB offset = %i used return\n", dev->cmdfifo_cdb_offset); - return; - } - - dev->do_cmd = 0; - 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); + esp_log("ESP Command on FIFO\n"); + dev->ti_size = 0; - dev->rregs[ESP_RSTAT] = STAT_TC | STAT_CD; - dev->rregs[ESP_RSEQ] = SEQ_CD; - dev->rregs[ESP_RINTR] |= INTR_BS; - esp_raise_irq(dev); - } - return; + if ((dev->rregs[ESP_RSTAT] & 7) == STAT_CD) { + if (dev->cmdfifo_cdb_offset == fifo8_num_used(&dev->cmdfifo)) { + esp_log("CDB offset = %i used return\n", dev->cmdfifo_cdb_offset); + return; + } + + dev->do_cmd = 0; + 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; + dev->rregs[ESP_RSEQ] = SEQ_CD; + dev->rregs[ESP_RINTR] |= INTR_BS; + esp_raise_irq(dev); + } + return; } if (dev->xfer_counter == 0) { - /* Wait until data is available. */ - esp_log("(ID=%02i LUN=%02i): FIFO no data available\n", dev->id, dev->lun); - return; + /* Wait until data is available. */ + esp_log("(ID=%02i LUN=%02i): FIFO no data available\n", dev->id, dev->lun); + return; } esp_log("ESP FIFO = %d, buffer length = %d\n", dev->xfer_counter, sd->buffer_length); if (sd->phase == SCSI_PHASE_DATA_IN) { - if (fifo8_is_empty(&dev->fifo)) { - fifo8_push(&dev->fifo, sd->sc->temp_buffer[dev->buffer_pos]); - dev->buffer_pos++; - dev->ti_size--; - dev->xfer_counter--; - } + if (fifo8_is_empty(&dev->fifo)) { + fifo8_push(&dev->fifo, sd->sc->temp_buffer[dev->buffer_pos]); + dev->buffer_pos++; + dev->ti_size--; + dev->xfer_counter--; + } } else if (sd->phase == SCSI_PHASE_DATA_OUT) { count = MIN(fifo8_num_used(&dev->fifo), ESP_FIFO_SZ); esp_fifo_pop_buf(&dev->fifo, sd->sc->temp_buffer + dev->buffer_pos, count); - dev->buffer_pos += count; - dev->ti_size += count; - dev->xfer_counter -= count; + dev->buffer_pos += count; + dev->ti_size += count; + dev->xfer_counter -= count; } - + esp_log("ESP FIFO Transfer bytes = %d\n", dev->xfer_counter); if (dev->xfer_counter <= 0) { - if (sd->phase == SCSI_PHASE_DATA_OUT) { - if (dev->ti_size < 0) { - esp_log("ESP FIFO Keep writing\n"); - esp_do_nodma(dev, sd); - } else { - esp_log("ESP FIFO Write finished\n"); - scsi_device_command_phase1(sd); - if (dev->mca) { - esp_command_complete(dev, sd->status); - } else - esp_pci_command_complete(dev, sd->status); - } - } else if (sd->phase == SCSI_PHASE_DATA_IN) { - /* If there is still data to be read from the device then - complete the DMA operation immediately. Otherwise defer - until the scsi layer has completed. */ - if (dev->ti_size <= 0) { - esp_log("ESP FIFO Read finished\n"); - scsi_device_command_phase1(sd); - if (dev->mca) { - esp_command_complete(dev, sd->status); - } else - esp_pci_command_complete(dev, sd->status); - } else { - esp_log("ESP FIFO Keep reading\n"); - esp_do_nodma(dev, sd); - } - } + if (sd->phase == SCSI_PHASE_DATA_OUT) { + if (dev->ti_size < 0) { + esp_log("ESP FIFO Keep writing\n"); + esp_do_nodma(dev, sd); + } else { + esp_log("ESP FIFO Write finished\n"); + scsi_device_command_phase1(sd); + if (dev->mca) { + esp_command_complete(dev, sd->status); + } else + esp_pci_command_complete(dev, sd->status); + } + } else if (sd->phase == SCSI_PHASE_DATA_IN) { + /* If there is still data to be read from the device then + complete the DMA operation immediately. Otherwise defer + until the scsi layer has completed. */ + if (dev->ti_size <= 0) { + esp_log("ESP FIFO Read finished\n"); + scsi_device_command_phase1(sd); + if (dev->mca) { + esp_command_complete(dev, sd->status); + } else + esp_pci_command_complete(dev, sd->status); + } else { + esp_log("ESP FIFO Keep reading\n"); + esp_do_nodma(dev, sd); + } + } } else { - /* Partially filled a scsi buffer. Complete immediately. */ - esp_log("ESP SCSI Partially filled the FIFO buffer\n"); - dev->rregs[ESP_RINTR] |= INTR_BS; - esp_raise_irq(dev); + /* Partially filled a scsi buffer. Complete immediately. */ + esp_log("ESP SCSI Partially filled the FIFO buffer\n"); + dev->rregs[ESP_RINTR] |= INTR_BS; + esp_raise_irq(dev); } } - static void esp_do_dma(esp_t *dev, scsi_device_t *sd) { - uint8_t buf[ESP_CMDFIFO_SZ]; + uint8_t buf[ESP_CMDFIFO_SZ]; uint32_t tdbc; - int count; + int count; esp_log("ESP SCSI Actual DMA len = %d\n", esp_get_tc(dev)); if (!scsi_device_present(sd)) { - esp_log("ESP SCSI no devices on ID %d, LUN %d\n", dev->id, dev->lun); + esp_log("ESP SCSI no devices on ID %d, LUN %d\n", dev->id, dev->lun); /* No such drive */ dev->rregs[ESP_RSTAT] = 0; dev->rregs[ESP_RINTR] = INTR_DC; - dev->rregs[ESP_RSEQ] = SEQ_0; - esp_raise_irq(dev); - fifo8_reset(&dev->cmdfifo); - return; + dev->rregs[ESP_RSEQ] = SEQ_0; + esp_raise_irq(dev); + fifo8_reset(&dev->cmdfifo); + return; } else { - esp_log("ESP SCSI device found on ID %d, LUN %d\n", dev->id, dev->lun); + esp_log("ESP SCSI device found on ID %d, LUN %d\n", dev->id, dev->lun); } - + count = tdbc = esp_get_tc(dev); - - if (dev->mca) { /*See the comment in the esp_do_busid_cmd() function.*/ - if (sd->buffer_length < 0) { - if (dev->dma_enabled) - goto done; - else - goto partial; - } - } + + if (dev->mca) { + if (sd->buffer_length < 0) { + if (dev->dma_enabled) + goto done; + else + goto partial; + } + } if (dev->do_cmd) { - esp_log("ESP Command on DMA\n"); - count = MIN(count, fifo8_num_free(&dev->cmdfifo)); - if (dev->mca) { - while (dev->dma_86c01.pos < count) { - dma_channel_write(dev->DmaChannel, buf[dev->dma_86c01.pos]); - dev->dma_86c01.pos++; - } - dev->dma_86c01.pos = 0; - } else - esp_pci_dma_memory_rw(dev, buf, count, READ_FROM_DEVICE); - fifo8_push_all(&dev->cmdfifo, buf, count); - dev->ti_size = 0; - - if ((dev->rregs[ESP_RSTAT] & 7) == STAT_CD) { - if (dev->cmdfifo_cdb_offset == fifo8_num_used(&dev->cmdfifo)) - return; - - dev->do_cmd = 0; - esp_do_cmd(dev); - } else { - dev->cmdfifo_cdb_offset = fifo8_num_used(&dev->cmdfifo); + esp_log("ESP Command on DMA\n"); + count = MIN(count, fifo8_num_free(&dev->cmdfifo)); + if (dev->mca) { + dma_set_drq(dev->DmaChannel, 1); + while (dev->dma_86c01.pos < count) { + dma_channel_write(dev->DmaChannel, buf[dev->dma_86c01.pos]); + dev->dma_86c01.pos++; + } + dev->dma_86c01.pos = 0; + dma_set_drq(dev->DmaChannel, 0); + } else + esp_pci_dma_memory_rw(dev, buf, count, READ_FROM_DEVICE); + fifo8_push_all(&dev->cmdfifo, buf, count); + dev->ti_size = 0; - dev->rregs[ESP_RSTAT] = STAT_TC | STAT_CD; - dev->rregs[ESP_RSEQ] = SEQ_CD; - dev->rregs[ESP_RINTR] |= INTR_BS; - esp_raise_irq(dev); - } - return; + if ((dev->rregs[ESP_RSTAT] & 7) == STAT_CD) { + if (dev->cmdfifo_cdb_offset == fifo8_num_used(&dev->cmdfifo)) + return; + + dev->do_cmd = 0; + esp_do_cmd(dev); + } else { + dev->cmdfifo_cdb_offset = fifo8_num_used(&dev->cmdfifo); + + dev->rregs[ESP_RSTAT] = STAT_TC | STAT_CD; + dev->rregs[ESP_RSEQ] = SEQ_CD; + dev->rregs[ESP_RINTR] |= INTR_BS; + esp_raise_irq(dev); + } + return; } if (dev->xfer_counter == 0) { - /* Wait until data is available. */ - esp_log("(ID=%02i LUN=%02i): DMA no data available\n", dev->id, dev->lun); - return; + /* Wait until data is available. */ + esp_log("(ID=%02i LUN=%02i): DMA no data available\n", dev->id, dev->lun); + 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) - count = dev->xfer_counter; + count = dev->xfer_counter; if (sd->phase == SCSI_PHASE_DATA_IN) { - esp_log("ESP SCSI Read, dma cnt = %i, ti size = %i, positive len = %i\n", esp_get_tc(dev), dev->ti_size, count); - if (dev->mca) { - while (dev->dma_86c01.pos < count) { - dma_channel_write(dev->DmaChannel, sd->sc->temp_buffer[dev->buffer_pos + dev->dma_86c01.pos]); - esp_log("ESP SCSI DMA read for 53C90: pos = %i, val = %02x\n", dev->dma_86c01.pos, sd->sc->temp_buffer[dev->buffer_pos + dev->dma_86c01.pos]); - dev->dma_86c01.pos++; - } - dev->dma_86c01.pos = 0; - } else { - esp_pci_dma_memory_rw(dev, sd->sc->temp_buffer + dev->buffer_pos, count, READ_FROM_DEVICE); - } + esp_log("ESP SCSI Read, dma cnt = %i, ti size = %i, positive len = %i\n", esp_get_tc(dev), dev->ti_size, count); + if (dev->mca) { + dma_set_drq(dev->DmaChannel, 1); + while (dev->dma_86c01.pos < count) { + dma_channel_write(dev->DmaChannel, sd->sc->temp_buffer[dev->buffer_pos + dev->dma_86c01.pos]); + esp_log("ESP SCSI DMA read for 53C90: pos = %i, val = %02x\n", dev->dma_86c01.pos, sd->sc->temp_buffer[dev->buffer_pos + dev->dma_86c01.pos]); + dev->dma_86c01.pos++; + } + dev->dma_86c01.pos = 0; + dma_set_drq(dev->DmaChannel, 0); + } else { + esp_pci_dma_memory_rw(dev, sd->sc->temp_buffer + dev->buffer_pos, count, READ_FROM_DEVICE); + } } else if (sd->phase == SCSI_PHASE_DATA_OUT) { - esp_log("ESP SCSI Write, negative len = %i, ti size = %i, dma cnt = %i\n", count, -dev->ti_size, esp_get_tc(dev)); - if (dev->mca) { - while (dev->dma_86c01.pos < count) { - int val = dma_channel_read(dev->DmaChannel); - esp_log("ESP SCSI DMA write for 53C90: pos = %i, val = %02x\n", dev->dma_86c01.pos, val & 0xff); - sd->sc->temp_buffer[dev->buffer_pos + dev->dma_86c01.pos] = val & 0xff; - dev->dma_86c01.pos++; - } - dev->dma_86c01.pos = 0; - } else - esp_pci_dma_memory_rw(dev, sd->sc->temp_buffer + dev->buffer_pos, count, WRITE_TO_DEVICE); + esp_log("ESP SCSI Write, negative len = %i, ti size = %i, dma cnt = %i\n", count, -dev->ti_size, esp_get_tc(dev)); + if (dev->mca) { + dma_set_drq(dev->DmaChannel, 1); + while (dev->dma_86c01.pos < count) { + int val = dma_channel_read(dev->DmaChannel); + esp_log("ESP SCSI DMA write for 53C90: pos = %i, val = %02x\n", dev->dma_86c01.pos, val & 0xff); + sd->sc->temp_buffer[dev->buffer_pos + dev->dma_86c01.pos] = val & 0xff; + dev->dma_86c01.pos++; + } + dma_set_drq(dev->DmaChannel, 0); + dev->dma_86c01.pos = 0; + } else + esp_pci_dma_memory_rw(dev, sd->sc->temp_buffer + dev->buffer_pos, count, WRITE_TO_DEVICE); } - esp_set_tc(dev, esp_get_tc(dev) - count); + esp_set_tc(dev, esp_get_tc(dev) - count); dev->buffer_pos += count; dev->xfer_counter -= count; if (sd->phase == SCSI_PHASE_DATA_IN) { - dev->ti_size -= count; + dev->ti_size -= count; } else if (sd->phase == SCSI_PHASE_DATA_OUT) { - dev->ti_size += count; + dev->ti_size += count; } - + esp_log("ESP SCSI Transfer bytes = %d\n", dev->xfer_counter); if (dev->xfer_counter <= 0) { - if (sd->phase == SCSI_PHASE_DATA_OUT) { - if (dev->ti_size < 0) { - esp_log("ESP SCSI Keep writing\n"); - esp_do_dma(dev, sd); - } else { - esp_log("ESP SCSI Write finished\n"); - scsi_device_command_phase1(sd); - if (dev->mca) { - esp_command_complete(dev, sd->status); - } else - esp_pci_command_complete(dev, sd->status); - } - } else if (sd->phase == SCSI_PHASE_DATA_IN) { - /* If there is still data to be read from the device then - complete the DMA operation immediately. Otherwise defer - until the scsi layer has completed. */ - if (dev->ti_size <= 0) { + if (sd->phase == SCSI_PHASE_DATA_OUT) { + if (dev->ti_size < 0) { + esp_log("ESP SCSI Keep writing\n"); + esp_do_dma(dev, sd); + } else { + esp_log("ESP SCSI Write finished\n"); + scsi_device_command_phase1(sd); + if (dev->mca) { + esp_command_complete(dev, sd->status); + } else + esp_pci_command_complete(dev, sd->status); + } + } else if (sd->phase == SCSI_PHASE_DATA_IN) { + /* If there is still data to be read from the device then + complete the DMA operation immediately. Otherwise defer + until the scsi layer has completed. */ + if (dev->ti_size <= 0) { done: - esp_log("ESP SCSI Read finished\n"); - scsi_device_command_phase1(sd); - if (dev->mca) { - esp_command_complete(dev, sd->status); - } else - esp_pci_command_complete(dev, sd->status); - } else { - esp_log("ESP SCSI Keep reading\n"); - esp_do_dma(dev, sd); - } - } + esp_log("ESP SCSI Read finished\n"); + scsi_device_command_phase1(sd); + if (dev->mca) { + esp_command_complete(dev, sd->status); + } else + esp_pci_command_complete(dev, sd->status); + } else { + esp_log("ESP SCSI Keep reading\n"); + esp_do_dma(dev, sd); + } + } } else { - /* Partially filled a scsi buffer. Complete immediately. */ -partial: - esp_log("ESP SCSI Partially filled the SCSI buffer\n"); - esp_dma_done(dev); + /* Partially filled a scsi buffer. Complete immediately. */ +partial: + esp_log("ESP SCSI Partially filled the SCSI buffer\n"); + esp_dma_done(dev); } } - static void esp_report_command_complete(esp_t *dev, uint32_t status) { esp_log("ESP Command complete\n"); - - dev->ti_size = 0; - dev->status = status; + + dev->ti_size = 0; + dev->status = status; dev->rregs[ESP_RSTAT] = STAT_TC | STAT_ST; - esp_dma_done(dev); + esp_dma_done(dev); } /* Callback to indicate that the SCSI layer has completed a command. */ static void esp_command_complete(void *priv, uint32_t status) { - esp_t *dev = (esp_t *)priv; + esp_t *dev = (esp_t *) priv; esp_report_command_complete(dev, status); } @@ -813,8 +821,8 @@ esp_command_complete(void *priv, uint32_t status) static void esp_pci_command_complete(void *priv, uint32_t status) { - esp_t *dev = (esp_t *)priv; - + esp_t *dev = (esp_t *) priv; + esp_command_complete(dev, status); dev->dma_regs[DMA_WBC] = 0; dev->dma_regs[DMA_STAT] |= DMA_STAT_DONE; @@ -823,379 +831,391 @@ esp_pci_command_complete(void *priv, uint32_t status) static void esp_timer_on(esp_t *dev, scsi_device_t *sd, double p) { - if (dev->mca) { - /* Normal SCSI: 5000000 bytes per second */ - dev->period = (p > 0.0) ? p : (((double) sd->buffer_length) * 0.2); - } else { - /* Fast SCSI: 10000000 bytes per second */ - dev->period = (p > 0.0) ? p : (((double) sd->buffer_length) * 0.1); - } + if (dev->mca) { + /* Normal SCSI: 5000000 bytes per second */ + dev->period = (p > 0.0) ? p : (((double) sd->buffer_length) * 0.2); + } else { + /* Fast SCSI: 10000000 bytes per second */ + dev->period = (p > 0.0) ? p : (((double) sd->buffer_length) * 0.1); + } - timer_on_auto(&dev->timer, dev->period + 40.0); + timer_on_auto(&dev->timer, dev->period + 40.0); } static void handle_ti(void *priv) { - esp_t *dev = (esp_t *)priv; - scsi_device_t *sd = &scsi_devices[dev->bus][dev->id]; + esp_t *dev = (esp_t *) priv; + scsi_device_t *sd = &scsi_devices[dev->bus][dev->id]; if (dev->dma) { - esp_log("ESP Handle TI, do data, minlen = %i\n", esp_get_tc(dev)); - esp_do_dma(dev, sd); + esp_log("ESP Handle TI, do data, minlen = %i\n", esp_get_tc(dev)); + esp_do_dma(dev, sd); } else { - esp_log("ESP Handle TI, do nodma, minlen = %i\n", dev->xfer_counter); - esp_do_nodma(dev, sd); + esp_log("ESP Handle TI, do nodma, minlen = %i\n", dev->xfer_counter); + esp_do_nodma(dev, sd); } } static void handle_s_without_atn(void *priv) { - esp_t *dev = (esp_t *)priv; - int len; + esp_t *dev = (esp_t *) priv; + int len; len = esp_get_cmd(dev, ESP_CMDFIFO_SZ); esp_log("ESP SEL w/o ATN len = %d, id = %d\n", len, dev->id); if (len > 0) { - dev->cmdfifo_cdb_offset = 0; - dev->do_cmd = 0; - esp_do_cmd(dev); + dev->cmdfifo_cdb_offset = 0; + dev->do_cmd = 0; + esp_do_cmd(dev); } else if (len == 0) { - dev->do_cmd = 1; + dev->do_cmd = 1; /* Target present, but no cmd yet - switch to command phase */ - dev->rregs[ESP_RSEQ] = SEQ_CD; + dev->rregs[ESP_RSEQ] = SEQ_CD; dev->rregs[ESP_RSTAT] = STAT_CD; - } + } } static void handle_satn(void *priv) { - esp_t *dev = (esp_t *)priv; - int len; + esp_t *dev = (esp_t *) priv; + int len; len = esp_get_cmd(dev, ESP_CMDFIFO_SZ); esp_log("ESP SEL with ATN len = %d, id = %d\n", len, dev->id); if (len > 0) { - dev->cmdfifo_cdb_offset = 1; - dev->do_cmd = 0; - esp_do_cmd(dev); + dev->cmdfifo_cdb_offset = 1; + dev->do_cmd = 0; + esp_do_cmd(dev); } else if (len == 0) { - dev->do_cmd = 1; - /* Target present, but no cmd yet - switch to command phase */ - dev->rregs[ESP_RSEQ] = SEQ_CD; - dev->rregs[ESP_RSTAT] = STAT_CD; - } + dev->do_cmd = 1; + /* Target present, but no cmd yet - switch to command phase */ + dev->rregs[ESP_RSEQ] = SEQ_CD; + dev->rregs[ESP_RSTAT] = STAT_CD; + } } static void handle_satn_stop(void *priv) { - esp_t *dev = (esp_t *)priv; - int cmdlen; + esp_t *dev = (esp_t *) priv; + int cmdlen; cmdlen = esp_get_cmd(dev, 1); if (cmdlen > 0) { - dev->do_cmd = 1; - dev->cmdfifo_cdb_offset = 1; - dev->rregs[ESP_RSTAT] = STAT_MO; - dev->rregs[ESP_RINTR] = INTR_BS | INTR_FC; - dev->rregs[ESP_RSEQ] = SEQ_MO; - esp_log("ESP SCSI Command len = %d, raising IRQ\n", cmdlen); - esp_raise_irq(dev); + dev->do_cmd = 1; + dev->cmdfifo_cdb_offset = 1; + dev->rregs[ESP_RSTAT] = STAT_MO; + dev->rregs[ESP_RINTR] = INTR_BS | INTR_FC; + dev->rregs[ESP_RSEQ] = SEQ_MO; + esp_log("ESP SCSI Command len = %d, raising IRQ\n", cmdlen); + esp_raise_irq(dev); } else if (cmdlen == 0) { - dev->do_cmd = 1; - /* Target present, switch to message out phase */ - dev->rregs[ESP_RSEQ] = SEQ_MO; - dev->rregs[ESP_RSTAT] = STAT_MO; - } + dev->do_cmd = 1; + /* Target present, switch to message out phase */ + dev->rregs[ESP_RSEQ] = SEQ_MO; + dev->rregs[ESP_RSTAT] = STAT_MO; + } } static void esp_write_response(esp_t *dev) { - uint8_t buf[2]; - + uint8_t buf[2]; + buf[0] = dev->status; buf[1] = 0; + esp_log("esp_write_response(): %02X %02X\n", buf[0], buf[1]); if (dev->dma) { - if (dev->mca) { - while (dev->dma_86c01.pos < 2) { - int val = dma_channel_read(dev->DmaChannel); - buf[dev->dma_86c01.pos++] = val & 0xff; - } - dev->dma_86c01.pos = 0; - } else - esp_pci_dma_memory_rw(dev, buf, 2, WRITE_TO_DEVICE); - dev->rregs[ESP_RSTAT] = STAT_TC | STAT_ST; - dev->rregs[ESP_RINTR] = INTR_BS | INTR_FC; - dev->rregs[ESP_RSEQ] = SEQ_CD; + if (dev->mca) { + dma_set_drq(dev->DmaChannel, 1); + while (dev->dma_86c01.pos < 2) { + int val = dma_channel_read(dev->DmaChannel); + buf[dev->dma_86c01.pos++] = val & 0xff; + } + dev->dma_86c01.pos = 0; + dma_set_drq(dev->DmaChannel, 0); + } else + esp_pci_dma_memory_rw(dev, buf, 2, WRITE_TO_DEVICE); + dev->rregs[ESP_RSTAT] = STAT_TC | STAT_ST; + dev->rregs[ESP_RINTR] = INTR_BS | INTR_FC; + dev->rregs[ESP_RSEQ] = SEQ_CD; } else { - fifo8_reset(&dev->fifo); - fifo8_push_all(&dev->fifo, buf, 2); - dev->rregs[ESP_RFLAGS] = 2; + fifo8_reset(&dev->fifo); + fifo8_push_all(&dev->fifo, buf, 2); + dev->rregs[ESP_RFLAGS] = 2; } esp_log("ESP SCSI ICCS IRQ\n"); esp_raise_irq(dev); } static void -esp_callback(void *p) +esp_callback(void *priv) { - esp_t *dev = (esp_t *) p; + esp_t *dev = (esp_t *) priv; - if (dev->dma_enabled || dev->do_cmd) { - if ((dev->rregs[ESP_CMD] & CMD_CMD) == CMD_TI) { - esp_log("ESP SCSI Handle TI Callback\n"); - handle_ti(dev); - } + if (dev->dma_enabled || dev->do_cmd || ((dev->rregs[ESP_CMD] & CMD_CMD) == CMD_PAD)) { + if ((dev->rregs[ESP_CMD] & CMD_CMD) == CMD_TI) { + esp_log("ESP SCSI Handle TI Callback\n"); + handle_ti(dev); + } else if ((dev->rregs[ESP_CMD] & CMD_CMD) == CMD_PAD) { + esp_log("ESP SCSI Handle PAD Callback\n"); + handle_ti(dev); + } } - - esp_log("ESP DMA activated = %d, CMD activated = %d\n", dev->dma_enabled, dev->do_cmd); + + esp_log("ESP DMA activated = %d, CMD activated = %d\n", dev->dma_enabled, dev->do_cmd); } static uint32_t esp_reg_read(esp_t *dev, uint32_t saddr) { - uint32_t ret; + uint32_t ret; switch (saddr) { - case ESP_FIFO: - if ((dev->rregs[ESP_RSTAT] & 7) == STAT_DI) { - if (dev->ti_size) { - esp_log("TI size FIFO = %i\n", dev->ti_size); - esp_do_nodma(dev, &scsi_devices[dev->bus][dev->id]); - } else { - /* - * The last byte of a non-DMA transfer has been read out - * of the FIFO so switch to status phase - */ - dev->rregs[ESP_RSTAT] = STAT_TC | STAT_ST; - } - } - - dev->rregs[ESP_FIFO] = esp_fifo_pop(&dev->fifo); - ret = dev->rregs[ESP_FIFO]; - break; - case ESP_RINTR: - /* Clear sequence step, interrupt register and all status bits - except TC */ - ret = dev->rregs[ESP_RINTR]; - dev->rregs[ESP_RINTR] = 0; - dev->rregs[ESP_RSTAT] &= ~STAT_TC; - esp_log("ESP SCSI Clear sequence step\n"); - esp_lower_irq(dev); - esp_log("ESP RINTR read old val = %02x\n", ret); - break; - case ESP_TCHI: - /* Return the unique id if the value has never been written */ - if (!dev->tchi_written && !dev->mca) { - esp_log("ESP TCHI read id 0x12\n"); - ret = TCHI_AM53C974; - } else - ret = dev->rregs[saddr]; - break; - case ESP_RFLAGS: - ret = fifo8_num_used(&dev->fifo); - break; - default: - ret = dev->rregs[saddr]; - break; - + case ESP_FIFO: + if ((dev->rregs[ESP_RSTAT] & 7) == STAT_DI) { + if (dev->ti_size) { + esp_log("TI size FIFO = %i\n", dev->ti_size); + esp_do_nodma(dev, &scsi_devices[dev->bus][dev->id]); + } else { + /* + * The last byte of a non-DMA transfer has been read out + * of the FIFO so switch to status phase + */ + dev->rregs[ESP_RSTAT] = STAT_TC | STAT_ST; + } + } + + dev->rregs[ESP_FIFO] = esp_fifo_pop(&dev->fifo); + ret = dev->rregs[ESP_FIFO]; + break; + case ESP_RINTR: + /* Clear sequence step, interrupt register and all status bits + except TC */ + ret = dev->rregs[ESP_RINTR]; + dev->rregs[ESP_RINTR] = 0; + dev->rregs[ESP_RSTAT] &= ~STAT_TC; + esp_log("ESP SCSI Clear sequence step\n"); + esp_lower_irq(dev); + esp_log("ESP RINTR read old val = %02x\n", ret); + break; + case ESP_TCHI: + /* Return the unique id if the value has never been written */ + if (!dev->tchi_written && !dev->mca) { + esp_log("ESP TCHI read id 0x12\n"); + ret = TCHI_AM53C974; + } else + ret = dev->rregs[saddr]; + break; + case ESP_RFLAGS: + ret = fifo8_num_used(&dev->fifo); + break; + default: + ret = dev->rregs[saddr]; + break; } esp_log("Read reg %02x = %02x\n", saddr, ret); return ret; } - static void esp_reg_write(esp_t *dev, uint32_t saddr, uint32_t val) { esp_log("Write reg %02x = %02x\n", saddr, val); switch (saddr) { - case ESP_TCHI: - dev->tchi_written = 1; - /* fall through */ - case ESP_TCLO: - case ESP_TCMID: - esp_log("Transfer count regs %02x = %i\n", saddr, val); - dev->rregs[ESP_RSTAT] &= ~STAT_TC; - break; - case ESP_FIFO: - if (dev->do_cmd) { - esp_fifo_push(&dev->cmdfifo, val); - esp_log("ESP CmdVal = %02x\n", val); - /* - * If any unexpected message out/command phase data is - * transferred using non-DMA, raise the interrupt - */ - if (dev->rregs[ESP_CMD] == CMD_TI) { - dev->rregs[ESP_RINTR] |= INTR_BS; - esp_raise_irq(dev); + case ESP_TCHI: + dev->tchi_written = 1; + fallthrough; + case ESP_TCLO: + case ESP_TCMID: + esp_log("Transfer count regs %02x = %i\n", saddr, val); + dev->rregs[ESP_RSTAT] &= ~STAT_TC; + break; + case ESP_FIFO: + if (dev->do_cmd) { + esp_fifo_push(&dev->cmdfifo, val); + esp_log("ESP CmdVal = %02x\n", val); + /* + * If any unexpected message out/command phase data is + * transferred using non-DMA, raise the interrupt + */ + if (dev->rregs[ESP_CMD] == CMD_TI) { + dev->rregs[ESP_RINTR] |= INTR_BS; + esp_raise_irq(dev); + } + } else { + esp_fifo_push(&dev->fifo, val); + esp_log("ESP fifoval = %02x\n", val); } - } else { - esp_fifo_push(&dev->fifo, val); - esp_log("ESP fifoval = %02x\n", val); - } - break; - case ESP_CMD: - dev->rregs[saddr] = val; + break; + case ESP_CMD: + dev->rregs[saddr] = val; - if (val & CMD_DMA) { - dev->dma = 1; - /* Reload DMA counter. */ - esp_set_tc(dev, esp_get_stc(dev)); - if (dev->mca) - esp_dma_enable(dev, 1); - } else { - dev->dma = 0; - esp_log("ESP Command not for DMA\n"); - if (dev->mca) - esp_dma_enable(dev, 0); - } - esp_log("[%04X:%08X]: ESP Command = %02x, DMA ena1 = %d, DMA ena2 = %d\n", CS, cpu_state.pc, val & (CMD_CMD|CMD_DMA), dev->dma, dev->dma_enabled); - switch (val & CMD_CMD) { - case CMD_NOP: - break; - case CMD_FLUSH: - fifo8_reset(&dev->fifo); - timer_on_auto(&dev->timer, 10.0); - break; - case CMD_RESET: - if (dev->mca) { - esp_lower_irq(dev); - esp_hard_reset(dev); - } else - esp_pci_soft_reset(dev); - break; - case CMD_BUSRESET: - if (!(dev->wregs[ESP_CFG1] & CFG1_RESREPT)) { - dev->rregs[ESP_RINTR] |= INTR_RST; - esp_log("ESP Bus Reset with IRQ\n"); - esp_raise_irq(dev); - } - break; - case CMD_TI: - break; - case CMD_SEL: - handle_s_without_atn(dev); - break; - case CMD_SELATN: - handle_satn(dev); - break; - case CMD_SELATNS: - handle_satn_stop(dev); - break; - case CMD_ICCS: - esp_write_response(dev); - dev->rregs[ESP_RINTR] |= INTR_FC; - dev->rregs[ESP_RSTAT] |= STAT_MI; - break; - case CMD_MSGACC: - dev->rregs[ESP_RINTR] |= INTR_DC; - dev->rregs[ESP_RSEQ] = 0; - dev->rregs[ESP_RFLAGS] = 0; - esp_log("ESP SCSI MSGACC IRQ\n"); - esp_raise_irq(dev); - break; - case CMD_PAD: - dev->rregs[ESP_RSTAT] = STAT_TC; - dev->rregs[ESP_RINTR] |= INTR_FC; - dev->rregs[ESP_RSEQ] = 0; - esp_log("ESP Transfer Pad\n"); - break; - case CMD_SATN: - case CMD_RSTATN: - break; - case CMD_ENSEL: - dev->rregs[ESP_RINTR] = 0; - esp_log("ESP Enable Selection, do cmd = %d\n", dev->do_cmd); - break; - case CMD_DISSEL: - dev->rregs[ESP_RINTR] = 0; - esp_log("ESP Disable Selection\n"); - esp_raise_irq(dev); - break; - } - break; - case ESP_WBUSID: - case ESP_WSEL: - case ESP_WSYNTP: - case ESP_WSYNO: - break; - case ESP_CFG1: - case ESP_CFG2: - case ESP_CFG3: - case ESP_RES3: - case ESP_RES4: - dev->rregs[saddr] = val; - break; - case ESP_WCCF: - case ESP_WTEST: - break; - default: - esp_log("Unhandled writeb 0x%x = 0x%x\n", saddr, val); - break; + if (val & CMD_DMA) { + dev->dma = 1; + /* Reload DMA counter. */ + esp_set_tc(dev, esp_get_stc(dev)); + if (dev->mca) + esp_dma_enable(dev, 1); + } else { + dev->dma = 0; + esp_log("ESP Command not for DMA\n"); + if (dev->mca) + esp_dma_enable(dev, 0); + } + esp_log("[%04X:%08X]: ESP Command = %02x, DMA ena1 = %d, DMA ena2 = %d\n", CS, cpu_state.pc, val & (CMD_CMD | CMD_DMA), dev->dma, dev->dma_enabled); + switch (val & CMD_CMD) { + case CMD_NOP: + break; + case CMD_FLUSH: + fifo8_reset(&dev->fifo); + timer_on_auto(&dev->timer, 10.0); + break; + case CMD_RESET: + if (dev->mca) { + esp_lower_irq(dev); + esp_hard_reset(dev); + } else + 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"); + esp_raise_irq(dev); + } + break; + case CMD_TI: + esp_log("val = %02X\n", val); + break; + case CMD_SEL: + handle_s_without_atn(dev); + break; + case CMD_SELATN: + handle_satn(dev); + break; + case CMD_SELATNS: + handle_satn_stop(dev); + break; + case CMD_ICCS: + esp_write_response(dev); + dev->rregs[ESP_RINTR] |= INTR_FC; + dev->rregs[ESP_RSTAT] |= STAT_MI; + break; + case CMD_MSGACC: + dev->rregs[ESP_RINTR] |= INTR_DC; + dev->rregs[ESP_RSEQ] = 0; + dev->rregs[ESP_RFLAGS] = 0; + esp_log("ESP SCSI MSGACC IRQ\n"); + esp_raise_irq(dev); + break; + case CMD_PAD: + esp_log("val = %02X\n", val); + timer_stop(&dev->timer); + timer_on_auto(&dev->timer, dev->period); + esp_log("ESP Transfer Pad\n"); + break; + case CMD_SATN: + case CMD_RSTATN: + break; + case CMD_ENSEL: + dev->rregs[ESP_RINTR] = 0; + esp_log("ESP Enable Selection, do cmd = %d\n", dev->do_cmd); + break; + case CMD_DISSEL: + dev->rregs[ESP_RINTR] = 0; + esp_log("ESP Disable Selection\n"); + esp_raise_irq(dev); + break; + + default: + break; + } + break; + case ESP_WBUSID: + case ESP_WSEL: + case ESP_WSYNTP: + case ESP_WSYNO: + break; + case ESP_CFG1: + case ESP_CFG2: + case ESP_CFG3: + case ESP_RES3: + case ESP_RES4: + dev->rregs[saddr] = val; + break; + case ESP_WCCF: + case ESP_WTEST: + break; + default: + esp_log("Unhandled writeb 0x%x = 0x%x\n", saddr, val); + break; } dev->wregs[saddr] = val; } - static void esp_pci_dma_memory_rw(esp_t *dev, uint8_t *buf, uint32_t len, int dir) { int expected_dir; - if (dev->dma_regs[DMA_CMD] & DMA_CMD_DIR) - expected_dir = READ_FROM_DEVICE; - else - expected_dir = WRITE_TO_DEVICE; + if (dev->dma_regs[DMA_CMD] & DMA_CMD_DIR) + expected_dir = READ_FROM_DEVICE; + else + expected_dir = WRITE_TO_DEVICE; - esp_log("ESP DMA WBC = %d, addr = %06x, expected direction = %d, dir = %i\n", dev->dma_regs[DMA_WBC], dev->dma_regs[DMA_SPA], expected_dir, dir); + esp_log("ESP DMA WBC = %d, addr = %06x, expected direction = %d, dir = %i\n", dev->dma_regs[DMA_WBC], dev->dma_regs[DMA_SPA], expected_dir, dir); - if (dir != expected_dir) { - esp_log("ESP unexpected direction\n"); - return; - } + if (dir != expected_dir) { + esp_log("ESP unexpected direction\n"); + return; + } - if (dev->dma_regs[DMA_WBC] < len) - len = dev->dma_regs[DMA_WBC]; + if (dev->dma_regs[DMA_WBC] < len) + len = dev->dma_regs[DMA_WBC]; - if (expected_dir) { - dma_bm_write(dev->dma_regs[DMA_SPA], buf, len, 4); - } else { - dma_bm_read(dev->dma_regs[DMA_SPA], buf, len, 4); - } + if (expected_dir) { + dma_bm_write(dev->dma_regs[DMA_SPA], buf, len, 4); + } else { + dma_bm_read(dev->dma_regs[DMA_SPA], buf, len, 4); + } + esp_log("DMA: Address = %08X, Length = %08X (%02X %02X %02X %02X -> %02X %02X %02X %02X)\n", dev->dma_regs[DMA_SPA], len, + ram[dev->dma_regs[DMA_SPA]], ram[dev->dma_regs[DMA_SPA] + 1], ram[dev->dma_regs[DMA_SPA] + 2], ram[dev->dma_regs[DMA_SPA] + 3], + buf[0], buf[1], buf[2], buf[3]); - /* update status registers */ - dev->dma_regs[DMA_WBC] -= len; - dev->dma_regs[DMA_WAC] += len; - if (dev->dma_regs[DMA_WBC] == 0) - dev->dma_regs[DMA_STAT] |= DMA_STAT_DONE; -} + /* update status registers */ + dev->dma_regs[DMA_WBC] -= len; + dev->dma_regs[DMA_WAC] += len; + if (dev->dma_regs[DMA_WBC] == 0) + dev->dma_regs[DMA_STAT] |= DMA_STAT_DONE; +} static uint32_t -esp_pci_dma_read(esp_t *dev, uint16_t saddr) +esp_pci_dma_read(esp_t *dev, uint16_t saddr) { uint32_t ret; - + ret = dev->dma_regs[saddr]; - + if (saddr == DMA_STAT) { - if (dev->rregs[ESP_RSTAT] & STAT_INT) { - ret |= DMA_STAT_SCSIINT; - esp_log("ESP PCI DMA Read SCSI interrupt issued\n"); - } + if (dev->rregs[ESP_RSTAT] & STAT_INT) { + ret |= DMA_STAT_SCSIINT; + esp_log("ESP PCI DMA Read SCSI interrupt issued\n"); + } if (!(dev->sbac & SBAC_STATUS)) { - dev->dma_regs[DMA_STAT] &= ~(DMA_STAT_ERROR | DMA_STAT_ABORT | - DMA_STAT_DONE); - esp_log("ESP PCI DMA Read done cleared\n"); - } + dev->dma_regs[DMA_STAT] &= ~(DMA_STAT_ERROR | DMA_STAT_ABORT | DMA_STAT_DONE); + esp_log("ESP PCI DMA Read done cleared\n"); + } } - + esp_log("ESP PCI DMA Read regs addr = %04x, temp = %06x\n", saddr, ret); return ret; } @@ -1203,46 +1223,49 @@ esp_pci_dma_read(esp_t *dev, uint16_t saddr) static void esp_pci_dma_write(esp_t *dev, uint16_t saddr, uint32_t val) { - uint32_t mask; - + uint32_t mask; + switch (saddr) { - case DMA_CMD: - dev->dma_regs[saddr] = val; - esp_log("ESP PCI DMA Write CMD = %02x\n", val & DMA_CMD_MASK); - switch (val & DMA_CMD_MASK) { - case 0: /*IDLE*/ - esp_dma_enable(dev, 0); - break; - case 1: /*BLAST*/ - break; - case 2: /*ABORT*/ - scsi_device_command_stop(&scsi_devices[dev->bus][dev->id]); - break; - case 3: /*START*/ - dev->dma_regs[DMA_WBC] = dev->dma_regs[DMA_STC]; - dev->dma_regs[DMA_WAC] = dev->dma_regs[DMA_SPA]; - dev->dma_regs[DMA_WMAC] = dev->dma_regs[DMA_SMDLA]; - dev->dma_regs[DMA_STAT] &= ~(DMA_STAT_BCMBLT | DMA_STAT_SCSIINT | - DMA_STAT_DONE | DMA_STAT_ABORT | - DMA_STAT_ERROR | DMA_STAT_PWDN); - esp_dma_enable(dev, 1); - break; - default: /* can't happen */ - abort(); - } - break; - case DMA_STC: - case DMA_SPA: - case DMA_SMDLA: - dev->dma_regs[saddr] = val; - break; - case DMA_STAT: - if (dev->sbac & SBAC_STATUS) { - /* clear some bits on write */ - mask = DMA_STAT_ERROR | DMA_STAT_ABORT | DMA_STAT_DONE; - dev->dma_regs[DMA_STAT] &= ~(val & mask); - } - break; + case DMA_CMD: + dev->dma_regs[saddr] = val; + esp_log("ESP PCI DMA Write CMD = %02x\n", val & DMA_CMD_MASK); + switch (val & DMA_CMD_MASK) { + case 0: /*IDLE*/ + esp_dma_enable(dev, 0); + esp_log("PCI DMA disable\n"); + break; + case 1: /*BLAST*/ + break; + case 2: /*ABORT*/ + scsi_device_command_stop(&scsi_devices[dev->bus][dev->id]); + break; + case 3: /*START*/ + dev->dma_regs[DMA_WBC] = dev->dma_regs[DMA_STC]; + dev->dma_regs[DMA_WAC] = dev->dma_regs[DMA_SPA]; + dev->dma_regs[DMA_WMAC] = dev->dma_regs[DMA_SMDLA]; + dev->dma_regs[DMA_STAT] &= ~(DMA_STAT_BCMBLT | DMA_STAT_SCSIINT | DMA_STAT_DONE | DMA_STAT_ABORT | DMA_STAT_ERROR | DMA_STAT_PWDN); + esp_dma_enable(dev, 1); + esp_log("PCI DMA enable\n"); + break; + default: /* can't happen */ + abort(); + } + break; + case DMA_STC: + case DMA_SPA: + case DMA_SMDLA: + dev->dma_regs[saddr] = val; + break; + case DMA_STAT: + if (dev->sbac & SBAC_STATUS) { + /* clear some bits on write */ + mask = DMA_STAT_ERROR | DMA_STAT_ABORT | DMA_STAT_DONE; + dev->dma_regs[DMA_STAT] &= ~(val & mask); + } + break; + + default: + break; } } @@ -1250,6 +1273,7 @@ static void esp_pci_soft_reset(esp_t *dev) { esp_irq(dev, 0); + dev->rregs[ESP_RSTAT] &= ~STAT_INT; esp_pci_hard_reset(dev); } @@ -1258,51 +1282,52 @@ esp_pci_hard_reset(esp_t *dev) { esp_hard_reset(dev); dev->dma_regs[DMA_CMD] &= ~(DMA_CMD_DIR | DMA_CMD_INTE_D | DMA_CMD_INTE_P - | DMA_CMD_MDL | DMA_CMD_DIAG | DMA_CMD_MASK); + | DMA_CMD_MDL | DMA_CMD_DIAG | DMA_CMD_MASK); dev->dma_regs[DMA_WBC] &= ~0xffff; dev->dma_regs[DMA_WAC] = 0xffffffff; dev->dma_regs[DMA_STAT] &= ~(DMA_STAT_BCMBLT | DMA_STAT_SCSIINT - | DMA_STAT_DONE | DMA_STAT_ABORT - | DMA_STAT_ERROR); + | DMA_STAT_DONE | DMA_STAT_ABORT + | DMA_STAT_ERROR); dev->dma_regs[DMA_WMAC] = 0xfffffffd; } static uint32_t -esp_io_pci_read(esp_t *dev, uint32_t addr, unsigned int size) +esp_io_pci_read(esp_t *dev, uint32_t addr, unsigned int size) { uint32_t ret; - + addr &= 0x7f; - + if (addr < 0x40) { - /* SCSI core reg */ - ret = esp_reg_read(dev, addr >> 2); + /* SCSI core reg */ + ret = esp_reg_read(dev, addr >> 2); } else if (addr < 0x60) { - /* PCI DMA CCB */ - ret = esp_pci_dma_read(dev, (addr - 0x40) >> 2); - esp_log("ESP PCI DMA CCB read addr = %02x, ret = %02x\n", (addr - 0x40) >> 2, ret); + /* PCI DMA CCB */ + ret = esp_pci_dma_read(dev, (addr - 0x40) >> 2); + esp_log("ESP PCI DMA CCB read addr = %02x, ret = %02x\n", (addr - 0x40) >> 2, ret); } else if (addr == 0x70) { - /* DMA SCSI Bus and control */ - ret = dev->sbac; - esp_log("ESP PCI SBAC read = %02x\n", ret); + /* DMA SCSI Bus and control */ + ret = dev->sbac; + esp_log("ESP PCI SBAC read = %02x\n", ret); } else { - /* Invalid region */ - ret = 0; + /* Invalid region */ + ret = 0; } - + /* give only requested data */ ret >>= (addr & 3) * 8; - ret &= ~(~(uint64_t)0 << (8 * size)); - + ret &= ~(~(uint64_t) 0 << (8 * size)); + esp_log("ESP PCI I/O read: addr = %02x, val = %02x\n", addr, ret); return ret; } static void -esp_io_pci_write(esp_t *dev, uint32_t addr, uint32_t val, unsigned int size) -{ - uint32_t current, mask; - int shift; +esp_io_pci_write(esp_t *dev, uint32_t addr, uint32_t val, unsigned int size) +{ + uint32_t current; + uint32_t mask; + int shift; addr &= 0x7f; @@ -1319,7 +1344,7 @@ esp_io_pci_write(esp_t *dev, uint32_t addr, uint32_t val, unsigned int size) } shift = (4 - size) * 8; - mask = (~(uint32_t)0 << shift) >> shift; + mask = (~(uint32_t) 0 << shift) >> shift; shift = ((4 - (addr & 3)) & 3) * 8; val <<= shift; @@ -1331,57 +1356,61 @@ esp_io_pci_write(esp_t *dev, uint32_t addr, uint32_t val, unsigned int size) esp_log("ESP PCI I/O write: addr = %02x, val = %02x\n", addr, val); if (addr < 0x40) { - /* SCSI core reg */ - esp_reg_write(dev, addr >> 2, val); + /* SCSI core reg */ + esp_reg_write(dev, addr >> 2, val); } else if (addr < 0x60) { - /* PCI DMA CCB */ - esp_pci_dma_write(dev, (addr - 0x40) >> 2, val); + /* PCI DMA CCB */ + esp_pci_dma_write(dev, (addr - 0x40) >> 2, val); } else if (addr == 0x70) { - /* DMA SCSI Bus and control */ - dev->sbac = val; + /* DMA SCSI Bus and control */ + dev->sbac = val; } } - static void -esp_pci_io_writeb(uint16_t addr, uint8_t val, void *p) +esp_pci_io_writeb(uint16_t addr, uint8_t val, void *priv) { - esp_t *dev = (esp_t *)p; + esp_t *dev = (esp_t *) priv; + esp_io_pci_write(dev, addr, val, 1); } static void -esp_pci_io_writew(uint16_t addr, uint16_t val, void *p) +esp_pci_io_writew(uint16_t addr, uint16_t val, void *priv) { - esp_t *dev = (esp_t *)p; + esp_t *dev = (esp_t *) priv; + esp_io_pci_write(dev, addr, val, 2); } static void -esp_pci_io_writel(uint16_t addr, uint32_t val, void *p) +esp_pci_io_writel(uint16_t addr, uint32_t val, void *priv) { - esp_t *dev = (esp_t *)p; + esp_t *dev = (esp_t *) priv; esp_io_pci_write(dev, addr, val, 4); } static uint8_t -esp_pci_io_readb(uint16_t addr, void *p) +esp_pci_io_readb(uint16_t addr, void *priv) { - esp_t *dev = (esp_t *)p; + esp_t *dev = (esp_t *) priv; + return esp_io_pci_read(dev, addr, 1); } static uint16_t -esp_pci_io_readw(uint16_t addr, void *p) +esp_pci_io_readw(uint16_t addr, void *priv) { - esp_t *dev = (esp_t *)p; + esp_t *dev = (esp_t *) priv; + return esp_io_pci_read(dev, addr, 2); } static uint32_t -esp_pci_io_readl(uint16_t addr, void *p) +esp_pci_io_readl(uint16_t addr, void *priv) { - esp_t *dev = (esp_t *)p; + esp_t *dev = (esp_t *) priv; + return esp_io_pci_read(dev, addr, 4); } @@ -1390,18 +1419,17 @@ esp_io_set(esp_t *dev, uint32_t base, uint16_t len) { esp_log("ESP: [PCI] Setting I/O handler at %04X\n", base); io_sethandler(base, len, - esp_pci_io_readb, esp_pci_io_readw, esp_pci_io_readl, - esp_pci_io_writeb, esp_pci_io_writew, esp_pci_io_writel, dev); + esp_pci_io_readb, esp_pci_io_readw, esp_pci_io_readl, + esp_pci_io_writeb, esp_pci_io_writew, esp_pci_io_writel, dev); } - static void esp_io_remove(esp_t *dev, uint32_t base, uint16_t len) { esp_log("ESP: [PCI] Removing I/O handler at %04X\n", base); io_removehandler(base, len, - esp_pci_io_readb, esp_pci_io_readw, esp_pci_io_readl, - esp_pci_io_writeb, esp_pci_io_writew, esp_pci_io_writel, dev); + esp_pci_io_readb, esp_pci_io_readw, esp_pci_io_readl, + esp_pci_io_writeb, esp_pci_io_writew, esp_pci_io_writel, dev); } static void @@ -1416,15 +1444,15 @@ esp_bios_disable(esp_t *dev) mem_mapping_disable(&dev->bios.mapping); } -#define EE_ADAPT_SCSI_ID 64 -#define EE_MODE2 65 -#define EE_DELAY 66 -#define EE_TAG_CMD_NUM 67 -#define EE_ADAPT_OPTIONS 68 -#define EE_BOOT_SCSI_ID 69 -#define EE_BOOT_SCSI_LUN 70 -#define EE_CHKSUM1 126 -#define EE_CHKSUM2 127 +#define EE_ADAPT_SCSI_ID 64 +#define EE_MODE2 65 +#define EE_DELAY 66 +#define EE_TAG_CMD_NUM 67 +#define EE_ADAPT_OPTIONS 68 +#define EE_BOOT_SCSI_ID 69 +#define EE_BOOT_SCSI_LUN 70 +#define EE_CHKSUM1 126 +#define EE_CHKSUM2 127 #define EE_ADAPT_OPTION_F6_F8_AT_BOOT 0x01 #define EE_ADAPT_OPTION_BOOT_FROM_CDROM 0x02 @@ -1435,339 +1463,367 @@ esp_bios_disable(esp_t *dev) static void dc390_save_eeprom(esp_t *dev) { - FILE *f = nvr_fopen(dev->nvr_path, "wb"); - if (!f) return; - fwrite(dev->eeprom.data, 1, 128, f); - fclose(f); + FILE *fp = nvr_fopen(dev->nvr_path, "wb"); + if (!fp) + return; + fwrite(dev->eeprom.data, 1, 128, fp); + fclose(fp); } static void dc390_write_eeprom(esp_t *dev, int ena, int clk, int dat) { - /*Actual EEPROM is the same as the one used by the ATI cards, the 93cxx series.*/ - ati_eeprom_t *eeprom = &dev->eeprom; - uint8_t tick = eeprom->count; - uint8_t eedo = eeprom->out; - uint16_t address = eeprom->address; - uint8_t command = eeprom->opcode; - - esp_log("EEPROM CS=%02x,SK=%02x,DI=%02x,DO=%02x,tick=%d\n", - ena, clk, dat, eedo, tick); - - if (!eeprom->oldena && ena) { - esp_log("EEPROM Start chip select cycle\n"); - tick = 0; - command = 0; - address = 0; - } else if (eeprom->oldena && !ena) { - if (!eeprom->wp) { - uint8_t subcommand = address >> 4; - if (command == 0 && subcommand == 2) { - esp_log("EEPROM Erase All\n"); - for (address = 0; address < 64; address++) - eeprom->data[address] = 0xffff; - dc390_save_eeprom(dev); - } else if (command == 3) { - esp_log("EEPROM Erase Word\n"); - eeprom->data[address] = 0xffff; - dc390_save_eeprom(dev); - } else if (tick >= 26) { - if (command == 1) { - esp_log("EEPROM Write Word\n"); - eeprom->data[address] &= eeprom->dat; - dc390_save_eeprom(dev); - } else if (command == 0 && subcommand == 1) { - esp_log("EEPROM Write All\n"); - for (address = 0; address < 64; address++) - eeprom->data[address] &= eeprom->dat; - dc390_save_eeprom(dev); - } - } - } - eedo = 1; - esp_log("EEPROM DO read\n"); - } else if (ena && !eeprom->oldclk && clk) { - if (tick == 0) { - if (dat == 0) { - esp_log("EEPROM Got correct 1st start bit, waiting for 2nd start bit (1)\n"); - tick++; - } else { - esp_log("EEPROM Wrong 1st start bit (is 1, should be 0)\n"); - tick = 2; - } - } else if (tick == 1) { - if (dat != 0) { - esp_log("EEPROM Got correct 2nd start bit, getting command + address\n"); - tick++; - } else { - esp_log("EEPROM 1st start bit is longer than needed\n"); - } - } else if (tick < 4) { - tick++; - command <<= 1; - if (dat) - command += 1; - } else if (tick < 10) { - tick++; - address = (address << 1) | dat; - if (tick == 10) { - esp_log("EEPROM command = %02x, address = %02x (val = %04x)\n", command, - address, eeprom->data[address]); - if (command == 2) - eedo = 0; - address = address % 64; - if (command == 0) { - switch (address >> 4) { - case 0: - esp_log("EEPROM Write disable command\n"); - eeprom->wp = 1; - break; - case 1: - esp_log("EEPROM Write all command\n"); - break; - case 2: - esp_log("EEPROM Erase all command\n"); - break; - case 3: - esp_log("EEPROM Write enable command\n"); - eeprom->wp = 0; - break; - } - } else { - esp_log("EEPROM Read, write or erase word\n"); - eeprom->dat = eeprom->data[address]; - } - } - } else if (tick < 26) { - tick++; - if (command == 2) { - esp_log("EEPROM Read Word\n"); - eedo = ((eeprom->dat & 0x8000) != 0); - } - eeprom->dat <<= 1; - eeprom->dat += dat; - } else { - esp_log("EEPROM Additional unneeded tick, not processed\n"); - } - } - - eeprom->count = tick; - eeprom->oldena = ena; - eeprom->oldclk = clk; - eeprom->out = eedo; - eeprom->address = address; - eeprom->opcode = command; - esp_log("EEPROM EEDO = %d\n", eeprom->out); + /*Actual EEPROM is the same as the one used by the ATI cards, the 93cxx series.*/ + ati_eeprom_t *eeprom = &dev->eeprom; + uint8_t tick = eeprom->count; + uint8_t eedo = eeprom->out; + uint16_t address = eeprom->address; + uint8_t command = eeprom->opcode; + + esp_log("EEPROM CS=%02x,SK=%02x,DI=%02x,DO=%02x,tick=%d\n", + ena, clk, dat, eedo, tick); + + if (!eeprom->oldena && ena) { + esp_log("EEPROM Start chip select cycle\n"); + tick = 0; + command = 0; + address = 0; + } else if (eeprom->oldena && !ena) { + if (!eeprom->wp) { + uint8_t subcommand = address >> 4; + if (command == 0 && subcommand == 2) { + esp_log("EEPROM Erase All\n"); + for (address = 0; address < 64; address++) + eeprom->data[address] = 0xffff; + dc390_save_eeprom(dev); + } else if (command == 3) { + esp_log("EEPROM Erase Word\n"); + eeprom->data[address] = 0xffff; + dc390_save_eeprom(dev); + } else if (tick >= 26) { + if (command == 1) { + esp_log("EEPROM Write Word\n"); + eeprom->data[address] &= eeprom->dat; + dc390_save_eeprom(dev); + } else if (command == 0 && subcommand == 1) { + esp_log("EEPROM Write All\n"); + for (address = 0; address < 64; address++) + eeprom->data[address] &= eeprom->dat; + dc390_save_eeprom(dev); + } + } + } + eedo = 1; + esp_log("EEPROM DO read\n"); + } else if (ena && !eeprom->oldclk && clk) { + if (tick == 0) { + if (dat == 0) { + esp_log("EEPROM Got correct 1st start bit, waiting for 2nd start bit (1)\n"); + tick++; + } else { + esp_log("EEPROM Wrong 1st start bit (is 1, should be 0)\n"); + tick = 2; + } + } else if (tick == 1) { + if (dat != 0) { + esp_log("EEPROM Got correct 2nd start bit, getting command + address\n"); + tick++; + } else { + esp_log("EEPROM 1st start bit is longer than needed\n"); + } + } else if (tick < 4) { + tick++; + command <<= 1; + if (dat) + command += 1; + } else if (tick < 10) { + tick++; + address = (address << 1) | dat; + if (tick == 10) { + esp_log("EEPROM command = %02x, address = %02x (val = %04x)\n", command, + address, eeprom->data[address]); + if (command == 2) + eedo = 0; + address = address % 64; + if (command == 0) { + switch (address >> 4) { + case 0: + esp_log("EEPROM Write disable command\n"); + eeprom->wp = 1; + break; + case 1: + esp_log("EEPROM Write all command\n"); + break; + case 2: + esp_log("EEPROM Erase all command\n"); + break; + case 3: + esp_log("EEPROM Write enable command\n"); + eeprom->wp = 0; + break; + + default: + break; + } + } else { + esp_log("EEPROM Read, write or erase word\n"); + eeprom->dat = eeprom->data[address]; + } + } + } else if (tick < 26) { + tick++; + if (command == 2) { + esp_log("EEPROM Read Word\n"); + eedo = ((eeprom->dat & 0x8000) != 0); + } + eeprom->dat <<= 1; + eeprom->dat += dat; + } else { + esp_log("EEPROM Additional unneeded tick, not processed\n"); + } + } + + eeprom->count = tick; + eeprom->oldena = ena; + eeprom->oldclk = clk; + eeprom->out = eedo; + eeprom->address = address; + eeprom->opcode = command; + esp_log("EEPROM EEDO = %d\n", eeprom->out); } static void dc390_load_eeprom(esp_t *dev) { ati_eeprom_t *eeprom = &dev->eeprom; - uint8_t *nvr = (uint8_t *)eeprom->data; - int i; - uint16_t checksum = 0; - FILE *f; + uint8_t *nvr = (uint8_t *) eeprom->data; + int i; + uint16_t checksum = 0; + FILE *fp; eeprom->out = 1; - f = nvr_fopen(dev->nvr_path, "rb"); - if (f) { - esp_log("EEPROM Load\n"); - if (fread(nvr, 1, 128, f) != 128) - fatal("dc390_eeprom_load(): Error reading data\n"); - fclose(f); + fp = nvr_fopen(dev->nvr_path, "rb"); + if (fp) { + esp_log("EEPROM Load\n"); + if (fread(nvr, 1, 128, fp) != 128) + fatal("dc390_eeprom_load(): Error reading data\n"); + fclose(fp); } else { - for (i = 0; i < 16; i++) { - nvr[i * 2] = 0x57; - nvr[i * 2 + 1] = 0x00; - } - - esp_log("EEPROM Defaults\n"); - - nvr[EE_ADAPT_SCSI_ID] = 7; - nvr[EE_MODE2] = 0x0f; - nvr[EE_TAG_CMD_NUM] = 0x04; - nvr[EE_ADAPT_OPTIONS] = EE_ADAPT_OPTION_F6_F8_AT_BOOT | - EE_ADAPT_OPTION_BOOT_FROM_CDROM | - EE_ADAPT_OPTION_INT13; - for (i = 0; i < EE_CHKSUM1; i += 2) { - checksum += ((nvr[i] & 0xff) | (nvr[i + 1] << 8)); - esp_log("Checksum calc = %04x, nvr = %02x\n", checksum, nvr[i]); - } - - checksum = 0x1234 - checksum; - nvr[EE_CHKSUM1] = checksum & 0xff; - nvr[EE_CHKSUM2] = checksum >> 8; - esp_log("EEPROM Checksum = %04x\n", checksum); - } + for (i = 0; i < 16; i++) { + nvr[i * 2] = 0x57; + nvr[i * 2 + 1] = 0x00; + } + + esp_log("EEPROM Defaults\n"); + + nvr[EE_ADAPT_SCSI_ID] = 7; + nvr[EE_MODE2] = 0x0f; + nvr[EE_TAG_CMD_NUM] = 0x04; + nvr[EE_ADAPT_OPTIONS] = EE_ADAPT_OPTION_F6_F8_AT_BOOT | EE_ADAPT_OPTION_BOOT_FROM_CDROM | EE_ADAPT_OPTION_INT13; + for (i = 0; i < EE_CHKSUM1; i += 2) { + checksum += ((nvr[i] & 0xff) | (nvr[i + 1] << 8)); + esp_log("Checksum calc = %04x, nvr = %02x\n", checksum, nvr[i]); + } + + checksum = 0x1234 - checksum; + nvr[EE_CHKSUM1] = checksum & 0xff; + nvr[EE_CHKSUM2] = checksum >> 8; + esp_log("EEPROM Checksum = %04x\n", checksum); + } } -uint8_t esp_pci_regs[256]; -bar_t esp_pci_bar[2]; - +uint8_t esp_pci_regs[256]; +bar_t esp_pci_bar[2]; static uint8_t -esp_pci_read(int func, int addr, void *p) +esp_pci_read(UNUSED(int func), int addr, void *priv) { - esp_t *dev = (esp_t *)p; + esp_t *dev = (esp_t *) priv; - //esp_log("ESP PCI: Reading register %02X\n", addr & 0xff); + // esp_log("ESP PCI: Reading register %02X\n", addr & 0xff); switch (addr) { - case 0x00: - //esp_log("ESP PCI: Read DO line = %02x\n", dev->eeprom.out); - if (!dev->has_bios) - return 0x22; - else { - if (dev->eeprom.out) - return 0x22; - else { - dev->eeprom.out = 1; - return 2; - } - } - break; - case 0x01: - return 0x10; - case 0x02: - return 0x20; - case 0x03: - return 0x20; - case 0x04: - return esp_pci_regs[0x04] & 3; /*Respond to IO*/ - case 0x07: - return 2; - case 0x08: - return 0; /*Revision ID*/ - case 0x09: - return 0; /*Programming interface*/ - case 0x0A: - return 0; /*devubclass*/ - case 0x0B: - return 1; /*Class code*/ - case 0x0E: - return 0; /*Header type */ - case 0x10: - return 1; /*I/O space*/ - case 0x11: - return esp_pci_bar[0].addr_regs[1]; - case 0x12: - return esp_pci_bar[0].addr_regs[2]; - case 0x13: - return esp_pci_bar[0].addr_regs[3]; - case 0x30: - if (!dev->has_bios) - return 0; - return esp_pci_bar[1].addr_regs[0]; - case 0x31: - if (!dev->has_bios) - return 0; - return esp_pci_bar[1].addr_regs[1]; - case 0x32: - if (!dev->has_bios) - return 0; - return esp_pci_bar[1].addr_regs[2]; - case 0x33: - if (!dev->has_bios) - return 0; - return esp_pci_bar[1].addr_regs[3]; - case 0x3C: - return dev->irq; - case 0x3D: - return PCI_INTA; + case 0x00: + // esp_log("ESP PCI: Read DO line = %02x\n", dev->eeprom.out); + if (!dev->has_bios) + return 0x22; + else { + if (dev->eeprom.out) + return 0x22; + else { + dev->eeprom.out = 1; + return 2; + } + } + case 0x01: + return 0x10; + case 0x02: + return 0x20; + case 0x03: + return 0x20; + case 0x04: + return esp_pci_regs[0x04] | 0x80; /*Respond to IO*/ + case 0x05: + return esp_pci_regs[0x05]; + case 0x07: + return esp_pci_regs[0x07] | 0x02; + case 0x08: + return 0; /*Revision ID*/ + case 0x09: + return 0; /*Programming interface*/ + case 0x0A: + return 0; /*devubclass*/ + case 0x0B: + return 1; /*Class code*/ + case 0x0E: + return 0; /*Header type */ + case 0x10: + return (esp_pci_bar[0].addr_regs[0] & 0x80) | 0x01; /*I/O space*/ + case 0x11: + return esp_pci_bar[0].addr_regs[1]; + case 0x12: + return esp_pci_bar[0].addr_regs[2]; + case 0x13: + return esp_pci_bar[0].addr_regs[3]; + case 0x30: + if (!dev->has_bios) + return 0; + return esp_pci_bar[1].addr_regs[0]; + case 0x31: + if (!dev->has_bios) + return 0; + return esp_pci_bar[1].addr_regs[1]; + case 0x32: + if (!dev->has_bios) + return 0; + return esp_pci_bar[1].addr_regs[2]; + case 0x33: + if (!dev->has_bios) + return 0; + return esp_pci_bar[1].addr_regs[3]; + case 0x3C: + return dev->irq; + case 0x3D: + return PCI_INTA; - case 0x40 ... 0x4f: - return esp_pci_regs[addr]; + case 0x40 ... 0x4f: + return esp_pci_regs[addr]; + + default: + break; } - return(0); + return 0; } - static void -esp_pci_write(int func, int addr, uint8_t val, void *p) +esp_pci_write(UNUSED(int func), int addr, uint8_t val, void *priv) { - esp_t *dev = (esp_t *)p; + esp_t *dev = (esp_t *) priv; uint8_t valxor; - int eesk; - int eedi; + int eesk; + int eedi; - //esp_log("ESP PCI: Write value %02X to register %02X\n", val, addr); + // esp_log("ESP PCI: Write value %02X to register %02X\n", val, addr); if ((addr >= 0x80) && (addr <= 0xFF)) { - if (addr == 0x80) { - eesk = val & 0x80 ? 1 : 0; - eedi = val & 0x40 ? 1 : 0; - dc390_write_eeprom(dev, 1, eesk, eedi); - } else if (addr == 0xc0) - dc390_write_eeprom(dev, 0, 0, 0); - //esp_log("ESP PCI: Write value %02X to register %02X\n", val, addr); - return; + if (addr == 0x80) { + eesk = val & 0x80 ? 1 : 0; + eedi = val & 0x40 ? 1 : 0; + dc390_write_eeprom(dev, 1, eesk, eedi); + } else if (addr == 0xc0) + dc390_write_eeprom(dev, 0, 0, 0); + // esp_log("ESP PCI: Write value %02X to register %02X\n", val, addr); + return; } switch (addr) { - case 0x04: - valxor = (val & 3) ^ esp_pci_regs[addr]; - if (valxor & PCI_COMMAND_IO) { - esp_io_remove(dev, dev->PCIBase, 0x80); - if ((dev->PCIBase != 0) && (val & PCI_COMMAND_IO)) - esp_io_set(dev, dev->PCIBase, 0x80); - } - esp_pci_regs[addr] = val & 3; - break; + case 0x04: + valxor = (val & 3) ^ esp_pci_regs[addr]; + if (valxor & PCI_COMMAND_IO) { + esp_io_remove(dev, dev->PCIBase, 0x80); + if ((val & PCI_COMMAND_IO) && (dev->PCIBase != 0)) + esp_io_set(dev, dev->PCIBase, 0x80); + } + if (dev->has_bios && (valxor & PCI_COMMAND_MEM)) { + esp_bios_disable(dev); + if ((val & PCI_COMMAND_MEM) && (esp_pci_bar[1].addr & 0x00000001)) + esp_bios_set_addr(dev, dev->BIOSBase); + } + if (dev->has_bios) + esp_pci_regs[addr] = val & 0x47; + else + esp_pci_regs[addr] = val & 0x45; + break; + case 0x05: + esp_pci_regs[addr] = val & 0x01; + break; - case 0x10: case 0x11: case 0x12: case 0x13: - /* I/O Base set. */ - /* First, remove the old I/O. */ - esp_io_remove(dev, dev->PCIBase, 0x80); - /* Then let's set the PCI regs. */ - esp_pci_bar[0].addr_regs[addr & 3] = val; - /* Then let's calculate the new I/O base. */ - esp_pci_bar[0].addr &= 0xff00; - dev->PCIBase = esp_pci_bar[0].addr; - /* Log the new base. */ - //esp_log("ESP PCI: New I/O base is %04X\n" , dev->PCIBase); - /* We're done, so get out of the here. */ - if (esp_pci_regs[4] & PCI_COMMAND_IO) { - if (dev->PCIBase != 0) { - esp_io_set(dev, dev->PCIBase, 0x80); - } - } - return; + case 0x07: + esp_pci_regs[addr] &= ~(val & 0xf9); + break; - case 0x30: case 0x31: case 0x32: case 0x33: - if (!dev->has_bios) - return; - /* BIOS Base set. */ - /* First, remove the old I/O. */ - esp_bios_disable(dev); - /* Then let's set the PCI regs. */ - esp_pci_bar[1].addr_regs[addr & 3] = val; - /* Then let's calculate the new I/O base. */ - esp_pci_bar[1].addr &= 0xfff80001; - dev->BIOSBase = esp_pci_bar[1].addr & 0xfff80000; - /* Log the new base. */ - //esp_log("ESP PCI: New BIOS base is %08X\n" , dev->BIOSBase); - /* We're done, so get out of the here. */ - if (esp_pci_bar[1].addr & 0x00000001) - esp_bios_set_addr(dev, dev->BIOSBase); - return; + case 0x10: + case 0x11: + case 0x12: + case 0x13: + /* I/O Base set. */ + /* First, remove the old I/O. */ + esp_io_remove(dev, dev->PCIBase, 0x80); + /* Then let's set the PCI regs. */ + esp_pci_bar[0].addr_regs[addr & 3] = val; + /* Then let's calculate the new I/O base. */ + esp_pci_bar[0].addr &= 0xff80; + dev->PCIBase = esp_pci_bar[0].addr; + /* Log the new base. */ + // esp_log("ESP PCI: New I/O base is %04X\n" , dev->PCIBase); + /* We're done, so get out of the here. */ + if (esp_pci_regs[4] & PCI_COMMAND_IO) { + if (dev->PCIBase != 0) { + esp_io_set(dev, dev->PCIBase, 0x80); + } + } + return; - case 0x3C: - esp_pci_regs[addr] = val; - dev->irq = val; - esp_log("ESP IRQ now: %i\n", val); - return; - - case 0x40 ... 0x4f: - esp_pci_regs[addr] = val; - return; + case 0x30: + case 0x31: + case 0x32: + case 0x33: + if (!dev->has_bios) + return; + /* BIOS Base set. */ + /* First, remove the old I/O. */ + esp_bios_disable(dev); + /* Then let's set the PCI regs. */ + esp_pci_bar[1].addr_regs[addr & 3] = val; + /* Then let's calculate the new I/O base. */ + esp_pci_bar[1].addr &= 0xffff0001; + dev->BIOSBase = esp_pci_bar[1].addr & 0xffff0000; + /* Log the new base. */ + // esp_log("ESP PCI: New BIOS base is %08X\n" , dev->BIOSBase); + /* We're done, so get out of the here. */ + if ((esp_pci_regs[0x04] & PCI_COMMAND_MEM) && (esp_pci_bar[1].addr & 0x00000001)) + esp_bios_set_addr(dev, dev->BIOSBase); + return; + + case 0x3c: + esp_pci_regs[addr] = val; + dev->irq = val; + esp_log("ESP IRQ now: %i\n", val); + return; + + case 0x40 ... 0x4f: + esp_pci_regs[addr] = val; + return; + + default: + break; } } static void * -dc390_init(const device_t *info) +dc390_init(UNUSED(const device_t *info)) { esp_t *dev; @@ -1775,155 +1831,162 @@ dc390_init(const device_t *info) memset(dev, 0x00, sizeof(esp_t)); dev->bus = scsi_get_bus(); - - dev->mca = 0; - + + dev->mca = 0; + fifo8_create(&dev->fifo, ESP_FIFO_SZ); - fifo8_create(&dev->cmdfifo, ESP_CMDFIFO_SZ); - - dev->PCIBase = 0; + fifo8_create(&dev->cmdfifo, ESP_CMDFIFO_SZ); + + dev->PCIBase = 0; dev->MMIOBase = 0; - dev->pci_slot = pci_add_card(PCI_ADD_NORMAL, esp_pci_read, esp_pci_write, dev); + pci_add_card(PCI_ADD_NORMAL, esp_pci_read, esp_pci_write, dev, &dev->pci_slot); esp_pci_bar[0].addr_regs[0] = 1; - esp_pci_regs[0x04] = 3; + esp_pci_regs[0x04] = 3; dev->has_bios = device_get_config_int("bios"); - if (dev->has_bios) - rom_init(&dev->bios, DC390_ROM, 0xc8000, 0x8000, 0x7fff, 0, MEM_MAPPING_EXTERNAL); + if (dev->has_bios) { + dev->BIOSBase = 0xd0000; + rom_init(&dev->bios, DC390_ROM, 0xd0000, 0x8000, 0x7fff, 0, MEM_MAPPING_EXTERNAL); + } /* Enable our BIOS space in PCI, if needed. */ if (dev->has_bios) { - esp_pci_bar[1].addr = 0xfff80000; + esp_pci_bar[1].addr = 0xffff0000; } else { - esp_pci_bar[1].addr = 0; + esp_pci_bar[1].addr = 0; } if (dev->has_bios) - esp_bios_disable(dev); + esp_bios_disable(dev); - dev->nvr_path = "dc390.nvr"; + dev->nvr_path = "dc390.nvr"; - /* Load the serial EEPROM. */ - dc390_load_eeprom(dev); + /* Load the serial EEPROM. */ + dc390_load_eeprom(dev); esp_pci_hard_reset(dev); timer_add(&dev->timer, esp_callback, dev, 0); - return(dev); + scsi_bus_set_speed(dev->bus, 10000000.0); + + return dev; } static uint16_t ncr53c90_in(uint16_t port, void *priv) { - esp_t *dev = (esp_t *)priv; + esp_t *dev = (esp_t *) priv; uint16_t ret = 0; - - port &= 0x1f; - - if (port >= 0x10) - ret = esp_reg_read(dev, port - 0x10); - else { - switch (port) { - case 0x02: - ret = dev->dma_86c01.mode; - break; - - case 0x0c: - ret = dev->dma_86c01.status; - break; - } - } - - esp_log("[%04X:%08X]: NCR53c90 DMA read port = %02x, ret = %02x\n", CS, cpu_state.pc, port, ret); - - return ret; + + port &= 0x1f; + + if (port >= 0x10) + ret = esp_reg_read(dev, port - 0x10); + else { + switch (port) { + case 0x02: + ret = dev->dma_86c01.mode; + break; + + case 0x0c: + ret = dev->dma_86c01.status; + break; + + default: + break; + } + } + + esp_log("[%04X:%08X]: NCR53c90 DMA read port = %02x, ret = %02x\n", CS, cpu_state.pc, port, ret); + + return ret; } static uint8_t ncr53c90_inb(uint16_t port, void *priv) { - return ncr53c90_in(port, priv); + return ncr53c90_in(port, priv); } static uint16_t ncr53c90_inw(uint16_t port, void *priv) { - return (ncr53c90_in(port, priv) & 0xff) | (ncr53c90_in(port + 1, priv) << 8); + return (ncr53c90_in(port, priv) & 0xff) | (ncr53c90_in(port + 1, priv) << 8); } static void ncr53c90_out(uint16_t port, uint16_t val, void *priv) { - esp_t *dev = (esp_t *)priv; + esp_t *dev = (esp_t *) priv; - port &= 0x1f; + port &= 0x1f; - esp_log("[%04X:%08X]: NCR53c90 DMA write port = %02x, val = %02x\n", CS, cpu_state.pc, port, val); + esp_log("[%04X:%08X]: NCR53c90 DMA write port = %02x, val = %02x\n", CS, cpu_state.pc, port, val); - if (port >= 0x10) - esp_reg_write(dev, port - 0x10, val); - else { - if (port == 0x02) { - dev->dma_86c01.mode = (val & 0x40); - } - } + if (port >= 0x10) + esp_reg_write(dev, port - 0x10, val); + else { + if (port == 0x02) { + dev->dma_86c01.mode = (val & 0x40); + } + } } static void ncr53c90_outb(uint16_t port, uint8_t val, void *priv) { - ncr53c90_out(port, val, priv); + ncr53c90_out(port, val, priv); } static void ncr53c90_outw(uint16_t port, uint16_t val, void *priv) { - ncr53c90_out(port, val & 0xff, priv); - ncr53c90_out(port + 1, val >> 8, priv); + ncr53c90_out(port, val & 0xff, priv); + ncr53c90_out(port + 1, val >> 8, priv); } static uint8_t ncr53c90_mca_read(int port, void *priv) { - esp_t *dev = (esp_t *)priv; + const esp_t *dev = (esp_t *) priv; - return(dev->pos_regs[port & 7]); + return (dev->pos_regs[port & 7]); } - static void ncr53c90_mca_write(int port, uint8_t val, void *priv) { - esp_t *dev = (esp_t *)priv; - static const uint16_t ncrmca_iobase[] = { - 0, 0x240, 0x340, 0x400, 0x420, 0x3240, 0x8240, 0xa240 - }; + esp_t *dev = (esp_t *) priv; + static const uint16_t ncrmca_iobase[] = { + 0, 0x240, 0x340, 0x400, 0x420, 0x3240, 0x8240, 0xa240 + }; /* MCA does not write registers below 0x0100. */ - if (port < 0x0102) return; + if (port < 0x0102) + return; /* Save the MCA register value. */ dev->pos_regs[port & 7] = val; /* This is always necessary so that the old handler doesn't remain. */ - if (dev->Base != 0) { - io_removehandler(dev->Base, 0x20, - ncr53c90_inb, ncr53c90_inw, NULL, - ncr53c90_outb, ncr53c90_outw, NULL, dev); - } + if (dev->Base != 0) { + io_removehandler(dev->Base, 0x20, + ncr53c90_inb, ncr53c90_inw, NULL, + ncr53c90_outb, ncr53c90_outw, NULL, dev); + } /* Get the new assigned I/O base address. */ dev->Base = ncrmca_iobase[(dev->pos_regs[2] & 0x0e) >> 1]; /* Save the new IRQ and DMA channel values. */ dev->irq = 3 + (2 * ((dev->pos_regs[2] & 0x30) >> 4)); - if (dev->irq == 9) - dev->irq = 2; - - dev->DmaChannel = dev->pos_regs[3] & 0x0f; + if (dev->irq == 9) + dev->irq = 2; + + dev->DmaChannel = dev->pos_regs[3] & 0x0f; /* * Get misc SCSI config stuff. For now, we are only @@ -1933,33 +1996,31 @@ ncr53c90_mca_write(int port, uint8_t val, void *priv) /* Initialize the device if fully configured. */ if (dev->pos_regs[2] & 0x01) { - if (dev->Base != 0) { - /* Card enabled; register (new) I/O handler. */ - io_sethandler(dev->Base, 0x20, - ncr53c90_inb, ncr53c90_inw, NULL, - ncr53c90_outb, ncr53c90_outw, NULL, dev); + if (dev->Base != 0) { + /* Card enabled; register (new) I/O handler. */ + io_sethandler(dev->Base, 0x20, + ncr53c90_inb, ncr53c90_inw, NULL, + ncr53c90_outb, ncr53c90_outw, NULL, dev); - esp_hard_reset(dev); - } + esp_hard_reset(dev); + } - /* Say hello. */ - esp_log("NCR 53c90: I/O=%04x, IRQ=%d, DMA=%d, HOST ID %i\n", - dev->Base, dev->irq, dev->DmaChannel, dev->HostID); + /* Say hello. */ + esp_log("NCR 53c90: I/O=%04x, IRQ=%d, DMA=%d, HOST ID %i\n", + dev->Base, dev->irq, dev->DmaChannel, dev->HostID); } } - static uint8_t ncr53c90_mca_feedb(void *priv) { - esp_t *dev = (esp_t *)priv; + const esp_t *dev = (esp_t *) priv; return (dev->pos_regs[2] & 0x01); } - static void * -ncr53c90_mca_init(const device_t *info) +ncr53c90_mca_init(UNUSED(const device_t *info)) { esp_t *dev; @@ -1967,66 +2028,76 @@ ncr53c90_mca_init(const device_t *info) memset(dev, 0x00, sizeof(esp_t)); dev->bus = scsi_get_bus(); - - dev->mca = 1; + + dev->mca = 1; fifo8_create(&dev->fifo, ESP_FIFO_SZ); fifo8_create(&dev->cmdfifo, ESP_CMDFIFO_SZ); - dev->pos_regs[0] = 0x4d; /* MCA board ID */ - dev->pos_regs[1] = 0x7f; - mca_add(ncr53c90_mca_read, ncr53c90_mca_write, ncr53c90_mca_feedb, NULL, dev); + dev->pos_regs[0] = 0x4d; /* MCA board ID */ + dev->pos_regs[1] = 0x7f; + mca_add(ncr53c90_mca_read, ncr53c90_mca_write, ncr53c90_mca_feedb, NULL, dev); esp_hard_reset(dev); timer_add(&dev->timer, esp_callback, dev, 0); - return(dev); + scsi_bus_set_speed(dev->bus, 5000000.0); + + return dev; } -static void +static void esp_close(void *priv) { - esp_t *dev = (esp_t *)priv; + esp_t *dev = (esp_t *) priv; if (dev) { - fifo8_destroy(&dev->fifo); - fifo8_destroy(&dev->cmdfifo); - - free(dev); - dev = NULL; + fifo8_destroy(&dev->fifo); + fifo8_destroy(&dev->cmdfifo); + + free(dev); + dev = NULL; } } - static const device_config_t bios_enable_config[] = { - { - "bios", "Enable BIOS", CONFIG_BINARY, "", 0 - }, - { - "", "", -1 - } + // clang-format off + { + .name = "bios", + .description = "Enable BIOS", + .type = CONFIG_BINARY, + .default_string = "", + .default_int = 0 + }, + { .name = "", .description = "", .type = CONFIG_END } + // clang-format on }; - -const device_t dc390_pci_device = -{ - "Tekram DC-390 PCI", - "dc390", - DEVICE_PCI, - 0, - dc390_init, esp_close, NULL, - { NULL }, NULL, NULL, - bios_enable_config +const device_t dc390_pci_device = { + .name = "Tekram DC-390 PCI", + .internal_name = "dc390", + .flags = DEVICE_PCI, + .local = 0, + .init = dc390_init, + .close = esp_close, + .reset = NULL, + { .available = NULL }, + .speed_changed = NULL, + .force_redraw = NULL, + .config = bios_enable_config }; -const device_t ncr53c90_mca_device = -{ - "NCR 53c90 MCA", - "ncr53c90", - DEVICE_MCA, - 0, - ncr53c90_mca_init, esp_close, NULL, - { NULL }, NULL, NULL, - NULL +const device_t ncr53c90_mca_device = { + .name = "NCR 53c90 MCA", + .internal_name = "ncr53c90", + .flags = DEVICE_MCA, + .local = 0, + .init = ncr53c90_mca_init, + .close = esp_close, + .reset = NULL, + { .available = NULL }, + .speed_changed = NULL, + .force_redraw = NULL, + .config = NULL }; diff --git a/src/scsi/scsi_spock.c b/src/scsi/scsi_spock.c index 548cacf96..ba2817fe3 100644 --- a/src/scsi/scsi_spock.c +++ b/src/scsi/scsi_spock.c @@ -1,21 +1,21 @@ /* - * 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. + * 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. + * This file is part of the 86Box distribution. * - * Implementation of the IBM PS/2 SCSI controller with - * cache for MCA only. + * Implementation of the IBM PS/2 SCSI controller with + * cache for MCA only. * * * - * Authors: Sarah Walker, - * TheCollector1995, + * Authors: Sarah Walker, + * TheCollector1995, * - * Copyright 2020 Sarah Walker. - * Copyright 2020 TheCollector1995. + * Copyright 2020 Sarah Walker. + * Copyright 2020 TheCollector1995. */ #include #include @@ -40,161 +40,162 @@ #include <86box/scsi_device.h> #include <86box/scsi_spock.h> -#define SPOCK_U68_1990_ROM "roms/scsi/ibm/64f4376.bin" -#define SPOCK_U69_1990_ROM "roms/scsi/ibm/64f4377.bin" +#define SPOCK_U68_1990_ROM "roms/scsi/ibm/64f4376.bin" +#define SPOCK_U69_1990_ROM "roms/scsi/ibm/64f4377.bin" -#define SPOCK_U68_1991_ROM "roms/scsi/ibm/92F2244.U68" -#define SPOCK_U69_1991_ROM "roms/scsi/ibm/92F2245.U69" +#define SPOCK_U68_1991_ROM "roms/scsi/ibm/92F2244.U68" +#define SPOCK_U69_1991_ROM "roms/scsi/ibm/92F2245.U69" -#define SPOCK_TIME (20) +#define SPOCK_TIME (20) -typedef enum -{ - SCSI_STATE_IDLE, - SCSI_STATE_SELECT, - SCSI_STATE_SEND_COMMAND, - SCSI_STATE_END_PHASE +typedef enum { + SCSI_STATE_IDLE, + SCSI_STATE_SELECT, + SCSI_STATE_SEND_COMMAND, + SCSI_STATE_END_PHASE } scsi_state_t; -#pragma pack(push,1) +#pragma pack(push, 1) typedef struct { - uint16_t pos; - uint16_t pos1; - uint16_t pos2; - uint16_t pos3; - uint16_t pos4; - uint16_t pos5; - uint16_t pos6; - uint16_t pos7; - uint16_t pos8; + uint16_t pos; + uint16_t pos1; + uint16_t pos2; + uint16_t pos3; + uint16_t pos4; + uint16_t pos5; + uint16_t pos6; + uint16_t pos7; + uint16_t pos8; } get_pos_info_t; typedef struct { - uint16_t scb_status; - uint16_t retry_count; - uint32_t residual_byte_count; - uint32_t sg_list_element_addr; - uint16_t device_dep_status_len; - uint16_t cmd_status; - uint16_t error; - uint16_t reserved; - uint16_t cache_info_status; - uint32_t scb_addr; + uint16_t scb_status; + uint16_t retry_count; + uint32_t residual_byte_count; + uint32_t sg_list_element_addr; + uint16_t device_dep_status_len; + uint16_t cmd_status; + uint16_t error; + uint16_t reserved; + uint16_t cache_info_status; + uint32_t scb_addr; } get_complete_stat_t; typedef struct { - uint32_t sys_buf_addr; - uint32_t sys_buf_byte_count; + uint32_t sys_buf_addr; + uint32_t sys_buf_byte_count; } SGE; typedef struct { - uint16_t command; - uint16_t enable; - uint32_t lba_addr; - SGE sge; - uint32_t term_status_block_addr; - uint32_t scb_chain_addr; - uint16_t block_count; - uint16_t block_length; + uint16_t command; + uint16_t enable; + uint32_t lba_addr; + SGE sge; + uint32_t term_status_block_addr; + uint32_t scb_chain_addr; + uint16_t block_count; + uint16_t block_length; } scb_t; #pragma pack(pop) typedef struct { - rom_t bios_rom; - - int bios_ver; - int irq, irq_inactive; - - uint8_t pos_regs[8]; + rom_t bios_rom; - uint8_t basic_ctrl; - uint32_t command; - - uint8_t attention, - attention_pending; - int attention_wait; - - uint8_t cir[4], - cir_pending[4]; + int bios_ver; + int irq, irq_inactive; - uint8_t irq_status; - - uint32_t scb_addr; - - uint8_t status; + uint8_t pos_regs[8]; - get_complete_stat_t get_complete_stat; - get_pos_info_t get_pos_info; + uint8_t basic_ctrl; + uint32_t command; - scb_t scb; - int adapter_reset; - int scb_id; - int adapter_id; + uint8_t attention, + attention_pending; + int attention_wait; - int cmd_status; - int cir_status; + uint8_t cir[4], + cir_pending[4]; - uint8_t pacing; + uint8_t irq_status; - uint8_t buf[0x600]; + uint32_t scb_addr; - struct { - int phys_id; - int lun_id; - } dev_id[SCSI_ID_MAX]; + uint8_t status; - uint8_t last_status, bus; - uint8_t cdb[12]; - int cdb_len; - int cdb_id; - uint32_t data_ptr, data_len; - uint8_t temp_cdb[12]; + get_complete_stat_t get_complete_stat; + get_pos_info_t get_pos_info; - int irq_requests[SCSI_ID_MAX]; + scb_t scb; + int scb_id; + int adapter_id; + int assign; + int present[8]; - pc_timer_t callback_timer; - - int cmd_timer; - - int scb_state; - int in_reset; - int in_invalid; + int cmd_status; + int cir_status; - uint64_t temp_period; - double media_period; - - scsi_state_t scsi_state; + uint8_t pacing; + uint8_t irq_state; + uint8_t buf[0x600]; + + struct { + int phys_id; + int lun_id; + } dev_id[SCSI_ID_MAX]; + + uint8_t last_status, bus; + uint8_t cdb[12]; + int cdb_len; + int cdb_id; + uint32_t data_ptr, data_len; + uint8_t temp_cdb[12]; + + int irq_requests[SCSI_ID_MAX]; + + pc_timer_t callback_timer; + + int cmd_timer; + + int scb_state; + int in_reset; + int in_invalid; + int spock_16bit; + + uint64_t temp_period; + double media_period; + + scsi_state_t scsi_state; } spock_t; -#define CTRL_RESET (1 << 7) -#define CTRL_DMA_ENA (1 << 1) -#define CTRL_IRQ_ENA (1 << 0) +#define CTRL_RESET (1 << 7) +#define CTRL_DMA_ENA (1 << 1) +#define CTRL_IRQ_ENA (1 << 0) -#define STATUS_CMD_FULL (1 << 3) -#define STATUS_CMD_EMPTY (1 << 2) -#define STATUS_IRQ (1 << 1) -#define STATUS_BUSY (1 << 0) +#define STATUS_CMD_FULL (1 << 3) +#define STATUS_CMD_EMPTY (1 << 2) +#define STATUS_IRQ (1 << 1) +#define STATUS_BUSY (1 << 0) -#define ENABLE_PT (1 << 12) +#define ENABLE_PT (1 << 12) -#define CMD_MASK 0xff3f -#define CMD_ASSIGN 0x040e -#define CMD_DEVICE_INQUIRY 0x1c0b -#define CMD_DMA_PACING_CONTROL 0x040d -#define CMD_FEATURE_CONTROL 0x040c -#define CMD_GET_POS_INFO 0x1c0a -#define CMD_INVALID_412 0x0412 -#define CMD_GET_COMPLETE_STATUS 0x1c07 -#define CMD_FORMAT_UNIT 0x1c16 -#define CMD_READ_DATA 0x1c01 -#define CMD_READ_DEVICE_CAPACITY 0x1c09 -#define CMD_REQUEST_SENSE 0x1c08 -#define CMD_RESET 0x0400 -#define CMD_SEND_OTHER_SCSI 0x241f -#define CMD_UNKNOWN_1C10 0x1c10 -#define CMD_UNKNOWN_1C11 0x1c11 -#define CMD_WRITE_DATA 0x1c02 -#define CMD_VERIFY 0x1c03 +#define CMD_MASK 0xff3f +#define CMD_ASSIGN 0x040e +#define CMD_DEVICE_INQUIRY 0x1c0b +#define CMD_DMA_PACING_CONTROL 0x040d +#define CMD_FEATURE_CONTROL 0x040c +#define CMD_GET_POS_INFO 0x1c0a +#define CMD_INVALID_412 0x0412 +#define CMD_GET_COMPLETE_STATUS 0x1c07 +#define CMD_FORMAT_UNIT 0x1c16 +#define CMD_READ_DATA 0x1c01 +#define CMD_READ_DEVICE_CAPACITY 0x1c09 +#define CMD_REQUEST_SENSE 0x1c08 +#define CMD_RESET 0x0400 +#define CMD_SEND_OTHER_SCSI 0x241f +#define CMD_UNKNOWN_1C10 0x1c10 +#define CMD_UNKNOWN_1C11 0x1c11 +#define CMD_WRITE_DATA 0x1c02 +#define CMD_VERIFY 0x1c03 #define IRQ_TYPE_NONE 0x0 #define IRQ_TYPE_SCB_COMPLETE 0x1 @@ -206,984 +207,1040 @@ typedef struct { #define IRQ_TYPE_SW_SEQ_ERROR 0xf #define IRQ_TYPE_RESET_COMPLETE 0x10 - #ifdef ENABLE_SPOCK_LOG int spock_do_log = ENABLE_SPOCK_LOG; - static void spock_log(const char *fmt, ...) { va_list ap; if (spock_do_log) { - va_start(ap, fmt); - pclog_ex(fmt, ap); - va_end(ap); + va_start(ap, fmt); + pclog_ex(fmt, ap); + va_end(ap); } } #else -#define spock_log(fmt, ...) +# define spock_log(fmt, ...) #endif static void spock_rethink_irqs(spock_t *scsi) { - int irq_pending = 0; - int c; + int irq_pending = 0; - if (!scsi->irq_status) { - for (c = 0; c < SCSI_ID_MAX; c++) { - if (scsi->irq_requests[c] != IRQ_TYPE_NONE) { - /* Found IRQ */ - scsi->irq_status = c | (scsi->irq_requests[c] << 4); - spock_log("Found IRQ: status = %02x\n", scsi->irq_status); - scsi->status |= STATUS_IRQ; - irq_pending = 1; - break; - } - } - } else + if (!scsi->irq_status) { + for (uint8_t c = 0; c < SCSI_ID_MAX; c++) { + if (scsi->irq_requests[c] != IRQ_TYPE_NONE) { + /* Found IRQ */ + scsi->irq_status = c | (scsi->irq_requests[c] << 4); + spock_log("Found IRQ: status = %02x\n", scsi->irq_status); + scsi->status |= STATUS_IRQ; irq_pending = 1; - - if (scsi->basic_ctrl & CTRL_IRQ_ENA) { - if (irq_pending) { - spock_log("IRQ issued\n"); - scsi->irq_inactive = 0; - picint(1 << scsi->irq); - } else { - /* No IRQs pending, clear IRQ state */ - spock_log("IRQ cleared\n"); - scsi->irq_status = 0; - scsi->irq_inactive = 1; - scsi->status &= ~STATUS_IRQ; - picintc(1 << scsi->irq); - } - } else { - spock_log("IRQ disabled\n"); - picintc(1 << scsi->irq); + break; + } } + } else + irq_pending = 1; + + if (scsi->basic_ctrl & CTRL_IRQ_ENA) { + if (irq_pending) { + spock_log("IRQ issued\n"); + scsi->irq_inactive = 0; + picint(1 << scsi->irq); + } else { + /* No IRQs pending, clear IRQ state */ + spock_log("IRQ cleared\n"); + scsi->irq_status = 0; + scsi->irq_inactive = 1; + scsi->status &= ~STATUS_IRQ; + picintc(1 << scsi->irq); + } + } else { + spock_log("IRQ disabled\n"); + picintc(1 << scsi->irq); + } } -static __inline void +static __inline void spock_set_irq(spock_t *scsi, int id, int type) { - spock_log("spock_set_irq id=%i type=%x %02x\n", id, type, scsi->irq_status); - scsi->irq_requests[id] = type; - if (!scsi->irq_status) /* Don't change IRQ status if one is currently being processed */ - spock_rethink_irqs(scsi); + spock_log("spock_set_irq id=%i type=%x %02x\n", id, type, scsi->irq_status); + scsi->irq_requests[id] = type; + if (!scsi->irq_status) /* Don't change IRQ status if one is currently being processed */ + spock_rethink_irqs(scsi); } -static __inline void +static __inline void spock_clear_irq(spock_t *scsi, int id) { - spock_log("spock_clear_irq id=%i\n", id); - scsi->irq_requests[id] = IRQ_TYPE_NONE; - spock_rethink_irqs(scsi); + spock_log("spock_clear_irq id=%i\n", id); + scsi->irq_requests[id] = IRQ_TYPE_NONE; + spock_rethink_irqs(scsi); } static void spock_add_to_period(spock_t *scsi, int TransferLength) { - scsi->temp_period += (uint64_t) TransferLength; + scsi->temp_period += (uint64_t) TransferLength; } static void -spock_write(uint16_t port, uint8_t val, void *p) +spock_write(uint16_t port, uint8_t val, void *priv) { - spock_t *scsi = (spock_t *)p; + spock_t *scsi = (spock_t *) priv; - spock_log("spock_write: port=%04x val=%02x %04x:%04x\n", port, val, CS, cpu_state.pc); - - switch (port & 7) { - case 0: case 1: case 2: case 3: /*Command Interface Register*/ - scsi->cir_pending[port & 3] = val; - if (port & 2) - scsi->cir_status |= 2; - else - scsi->cir_status |= 1; - break; + spock_log("spock_write: port=%04x val=%02x %04x:%04x\n", port, val, CS, cpu_state.pc); - case 4: /*Attention Register*/ - scsi->attention_pending = val; - scsi->attention_wait = 2; - scsi->status |= STATUS_BUSY; - break; - - case 5: /*Basic Control Register*/ - if ((scsi->basic_ctrl & CTRL_RESET) && !(val & CTRL_RESET)) { - spock_log("Spock: SCSI reset and busy\n"); - scsi->in_reset = 1; - scsi->cmd_timer = SPOCK_TIME * 2; - scsi->status |= STATUS_BUSY; - } - scsi->basic_ctrl = val; - spock_rethink_irqs(scsi); - break; - } + switch (port & 7) { + case 0: + case 1: + case 2: + case 3: /*Command Interface Register*/ + scsi->cir_pending[port & 3] = val; + if (port & 2) + scsi->cir_status |= 2; + else + scsi->cir_status |= 1; + break; + + case 4: /*Attention Register*/ + scsi->attention_pending = val; + scsi->attention_wait = 2; + scsi->status |= STATUS_BUSY; + break; + + case 5: /*Basic Control Register*/ + if ((scsi->basic_ctrl & CTRL_RESET) && !(val & CTRL_RESET)) { + spock_log("Spock: SCSI reset and busy\n"); + scsi->in_reset = 1; + scsi->cmd_timer = SPOCK_TIME * 2; + scsi->status |= STATUS_BUSY; + } + scsi->basic_ctrl = val; + spock_rethink_irqs(scsi); + break; + + default: + break; + } } static void -spock_writew(uint16_t port, uint16_t val, void *p) +spock_writew(uint16_t port, uint16_t val, void *priv) { - spock_t *scsi = (spock_t *)p; + spock_t *scsi = (spock_t *) priv; - switch (port & 7) { - case 0: /*Command Interface Register*/ - scsi->cir_pending[0] = val & 0xff; - scsi->cir_pending[1] = val >> 8; - scsi->cir_status |= 1; - break; - case 2: /*Command Interface Register*/ - scsi->cir_pending[2] = val & 0xff; - scsi->cir_pending[3] = val >> 8; - scsi->cir_status |= 2; - break; - } + switch (port & 7) { + case 0: /*Command Interface Register*/ + scsi->cir_pending[0] = val & 0xff; + scsi->cir_pending[1] = val >> 8; + scsi->cir_status |= 1; + break; + case 2: /*Command Interface Register*/ + scsi->cir_pending[2] = val & 0xff; + scsi->cir_pending[3] = val >> 8; + scsi->cir_status |= 2; + break; - spock_log("spock_writew: port=%04x val=%04x\n", port, val); + default: + break; + } + + spock_log("spock_writew: port=%04x val=%04x\n", port, val); } - static uint8_t -spock_read(uint16_t port, void *p) +spock_read(uint16_t port, void *priv) { - spock_t *scsi = (spock_t *)p; - uint8_t temp = 0xff; - - switch (port & 7) { - case 0: case 1: case 2: case 3: /*Command Interface Register*/ - temp = scsi->cir_pending[port & 3]; - break; + const spock_t *scsi = (spock_t *) priv; + uint8_t temp = 0xff; - case 4: /*Attention Register*/ - temp = scsi->attention_pending; - break; - case 5: /*Basic Control Register*/ - temp = scsi->basic_ctrl; - break; - case 6: /*IRQ status*/ - temp = scsi->irq_status; - break; - case 7: /*Basic Status Register*/ - temp = scsi->status; - spock_log("Cir Status=%d\n", scsi->cir_status); - if (scsi->cir_status == 0) { - spock_log("Status Cmd Empty\n"); - temp |= STATUS_CMD_EMPTY; - } - else if (scsi->cir_status == 3) { - spock_log("Status Cmd Full\n"); - temp |= STATUS_CMD_FULL; - } - break; - } - - spock_log("spock_read: port=%04x val=%02x %04x(%05x):%04x %02x\n", port, temp, CS, cs, cpu_state.pc, BH); - return temp; + switch (port & 7) { + case 0: + case 1: + case 2: + case 3: /*Command Interface Register*/ + temp = scsi->cir_pending[port & 3]; + break; + + case 4: /*Attention Register*/ + temp = scsi->attention_pending; + break; + case 5: /*Basic Control Register*/ + temp = scsi->basic_ctrl; + break; + case 6: /*IRQ status*/ + temp = scsi->irq_status; + break; + case 7: /*Basic Status Register*/ + temp = scsi->status; + spock_log("Cir Status=%d\n", scsi->cir_status); + if (scsi->cir_status == 0) { + spock_log("Status Cmd Empty\n"); + temp |= STATUS_CMD_EMPTY; + } else if (scsi->cir_status == 3) { + spock_log("Status Cmd Full\n"); + temp |= STATUS_CMD_FULL; + } + break; + + default: + break; + } + + spock_log("spock_read: port=%04x val=%02x %04x(%05x):%04x.\n", port, temp, CS, cs, cpu_state.pc); + return temp; } static uint16_t -spock_readw(uint16_t port, void *p) +spock_readw(uint16_t port, void *priv) { - spock_t *scsi = (spock_t *)p; - uint16_t temp = 0xffff; + const spock_t *scsi = (spock_t *) priv; + uint16_t temp = 0xffff; - switch (port & 7) { - case 0: /*Command Interface Register*/ - temp = scsi->cir_pending[0] | (scsi->cir_pending[1] << 8); - break; - case 2: /*Command Interface Register*/ - temp = scsi->cir_pending[2] | (scsi->cir_pending[3] << 8); - break; - } - - spock_log("spock_readw: port=%04x val=%04x\n", port, temp); - return temp; + switch (port & 7) { + case 0: /*Command Interface Register*/ + temp = scsi->cir_pending[0] | (scsi->cir_pending[1] << 8); + break; + case 2: /*Command Interface Register*/ + temp = scsi->cir_pending[2] | (scsi->cir_pending[3] << 8); + break; + + default: + break; + } + + spock_log("spock_readw: port=%04x val=%04x\n", port, temp); + return temp; } static void spock_rd_sge(spock_t *scsi, uint32_t Address, SGE *SG) { - dma_bm_read(Address, (uint8_t *)SG, sizeof(SGE), 2); - spock_add_to_period(scsi, sizeof(SGE)); + dma_bm_read(Address, (uint8_t *) SG, sizeof(SGE), 2); + spock_add_to_period(scsi, sizeof(SGE)); } static int spock_get_len(spock_t *scsi, scb_t *scb) { - uint32_t DataToTransfer = 0, i = 0; + uint32_t DataToTransfer = 0; - spock_log("Data Buffer write: length %d, pointer 0x%04X\n", - scsi->data_len, scsi->data_ptr); + spock_log("Data Buffer write: length %d, pointer 0x%04X\n", + scsi->data_len, scsi->data_ptr); - if (!scsi->data_len) - return(0); + if (!scsi->data_len) + return 0; - if (scb->enable & ENABLE_PT) { - for (i = 0; i < scsi->data_len; i += 8) { - spock_rd_sge(scsi, scsi->data_ptr + i, &scb->sge); - - DataToTransfer += scb->sge.sys_buf_byte_count; - } - return(DataToTransfer); - } else { - return(scsi->data_len); - } + if (scb->enable & ENABLE_PT) { + for (uint32_t i = 0; i < scsi->data_len; i += 8) { + spock_rd_sge(scsi, scsi->data_ptr + i, &scb->sge); + + DataToTransfer += scb->sge.sys_buf_byte_count; + } + return DataToTransfer; + } else { + return (scsi->data_len); + } } static void spock_process_imm_cmd(spock_t *scsi) { - int i; - int adapter_id, phys_id, lun_id; - - switch (scsi->command & CMD_MASK) { - case CMD_ASSIGN: - adapter_id = (scsi->command >> 16) & 15; - phys_id = (scsi->command >> 20) & 7; - lun_id = (scsi->command >> 24) & 7; - - if (adapter_id == 15) { - if (phys_id == 7) /*Device 15 always adapter*/ - spock_set_irq(scsi, scsi->attention & 0x0f, IRQ_TYPE_IMM_CMD_COMPLETE); - else /*Can not re-assign device 15 (always adapter)*/ - spock_set_irq(scsi, scsi->attention & 0x0f, IRQ_TYPE_COMMAND_FAIL); - } else { - if (scsi->command & (1 << 23)) { - spock_log("Assign: adapter id=%d\n", adapter_id); - scsi->dev_id[adapter_id].phys_id = -1; - spock_set_irq(scsi, scsi->attention & 0x0f, IRQ_TYPE_IMM_CMD_COMPLETE); - } else { - if (phys_id != scsi->adapter_id) { - scsi->dev_id[adapter_id].phys_id = phys_id; - scsi->dev_id[adapter_id].lun_id = lun_id; - spock_log("Assign: adapter dev=%x scsi ID=%i LUN=%i\n", adapter_id, scsi->dev_id[adapter_id].phys_id, scsi->dev_id[adapter_id].lun_id); - spock_set_irq(scsi, scsi->attention & 0x0f, IRQ_TYPE_IMM_CMD_COMPLETE); - } else { /*Can not assign adapter*/ - spock_log("Assign: PUN=%d, cannot assign adapter\n", phys_id); - spock_set_irq(scsi, scsi->attention & 0x0f, IRQ_TYPE_COMMAND_FAIL); - } - } - } - break; + int i; + int j = 0; + int adapter_id; + int phys_id; + int lun_id; - case CMD_DMA_PACING_CONTROL: - scsi->pacing = scsi->cir[2]; - spock_log("Pacing control: %i\n", scsi->pacing); - spock_set_irq(scsi, scsi->attention & 0x0f, IRQ_TYPE_IMM_CMD_COMPLETE); - break; + scsi->assign = 0; - case CMD_FEATURE_CONTROL: - spock_log("Feature control: timeout=%is d-rate=%i\n", (scsi->command >> 16) & 0x1fff, scsi->command >> 29); - spock_set_irq(scsi, scsi->attention & 0x0f, IRQ_TYPE_IMM_CMD_COMPLETE); - break; + switch (scsi->command & CMD_MASK) { + case CMD_ASSIGN: + scsi->assign = 1; + adapter_id = (scsi->command >> 16) & 15; + phys_id = (scsi->command >> 20) & 7; + lun_id = (scsi->command >> 24) & 7; + if (adapter_id == 15) { + if (phys_id == 7) /*Device 15 always adapter*/ + spock_set_irq(scsi, scsi->attention & 0x0f, IRQ_TYPE_IMM_CMD_COMPLETE); + else /*Can not re-assign device 15 (always adapter)*/ + spock_set_irq(scsi, scsi->attention & 0x0f, IRQ_TYPE_COMMAND_FAIL); + } else { + if (scsi->command & (1 << 23)) { + spock_log("Assign: adapter id=%d\n", adapter_id); + scsi->dev_id[adapter_id].phys_id = -1; + spock_set_irq(scsi, scsi->attention & 0x0f, IRQ_TYPE_IMM_CMD_COMPLETE); + } else { + if (phys_id != scsi->adapter_id) { + scsi->dev_id[adapter_id].phys_id = phys_id; + scsi->dev_id[adapter_id].lun_id = lun_id; + spock_log("Assign: adapter dev=%x scsi ID=%i LUN=%i.\n", adapter_id, scsi->dev_id[adapter_id].phys_id, scsi->dev_id[adapter_id].lun_id); + spock_set_irq(scsi, scsi->attention & 0x0f, IRQ_TYPE_IMM_CMD_COMPLETE); + } else { /*Can not assign adapter*/ + spock_log("Assign: PUN=%d, cannot assign adapter.\n", phys_id); + spock_set_irq(scsi, scsi->attention & 0x0f, IRQ_TYPE_COMMAND_FAIL); + } + } + } + break; + case CMD_DMA_PACING_CONTROL: + scsi->pacing = scsi->cir[2]; + spock_log("Pacing control: %i\n", scsi->pacing); + spock_set_irq(scsi, scsi->attention & 0x0f, IRQ_TYPE_IMM_CMD_COMPLETE); + break; + case CMD_FEATURE_CONTROL: + spock_log("Feature control: timeout=%is d-rate=%i\n", (scsi->command >> 16) & 0x1fff, scsi->command >> 29); + spock_set_irq(scsi, scsi->attention & 0x0f, IRQ_TYPE_IMM_CMD_COMPLETE); + break; + case CMD_INVALID_412: + spock_log("Invalid 412\n"); + spock_set_irq(scsi, scsi->attention & 0x0f, IRQ_TYPE_IMM_CMD_COMPLETE); + break; + case CMD_RESET: + spock_log("Reset Command, attention = %d.\n", scsi->attention & 0x0f); + if ((scsi->attention & 0x0f) == 0x0f) { /*Adapter reset*/ + for (i = 0; i < 8; i++) { + scsi_device_reset(&scsi_devices[scsi->bus][i]); + } - case CMD_INVALID_412: - spock_log("Invalid 412\n"); - spock_set_irq(scsi, scsi->attention & 0x0f, IRQ_TYPE_IMM_CMD_COMPLETE); - break; + for (i = 6; i > -1; i--) { + if (scsi_device_present(&scsi_devices[scsi->bus][i])) { + spock_log("Adapter Reset, SCSI reset present devices=%d, phys ID=%d, type=%04x.\n", j, scsi->dev_id[i].phys_id, scsi_devices[scsi->bus][i].type); + scsi->present[j] = i; + j++; + } else { + spock_log("Adapter Reset, SCSI reset not present devices=%d, phys ID=%d, type=%04x.\n", j, scsi->dev_id[i].phys_id, scsi_devices[scsi->bus][i].type); + } + } - case CMD_RESET: - spock_log("Reset Command\n"); - if ((scsi->attention & 0x0f) == 0x0f) { /*Adapter reset*/ - for (i = 0; i < 8; i++) - scsi_device_reset(&scsi_devices[scsi->bus][i]); - spock_log("Adapter Reset\n"); - - if (!scsi->adapter_reset && scsi->bios_ver) /*The early 1990 bios must have its boot drive - set to ID 6 according https://www.ardent-tool.com/IBM_SCSI/SCSI-A.html */ - scsi->adapter_reset = 1; - else - scsi->adapter_reset = 0; - - scsi->scb_state = 0; - } - spock_set_irq(scsi, scsi->attention & 0x0f, IRQ_TYPE_IMM_CMD_COMPLETE); - break; + scsi->scb_state = 0; + } - default: - fatal("scsi_callback: Bad command %02x\n", scsi->command); - break; - } + spock_set_irq(scsi, scsi->attention & 0x0f, IRQ_TYPE_IMM_CMD_COMPLETE); + break; + + default: + fatal("scsi_callback: Bad command %02x\n", scsi->command); + break; + } } static void spock_execute_cmd(spock_t *scsi, scb_t *scb) { - int c; - int old_scb_state; + int c; + int j = 0; + int old_scb_state; - if (scsi->in_reset) { - spock_log("Reset type = %d\n", scsi->in_reset); + if (scsi->in_reset) { + spock_log("Reset type = %d\n", scsi->in_reset); - scsi->status &= ~STATUS_BUSY; - scsi->irq_status = 0; + scsi->status &= ~STATUS_BUSY; + scsi->irq_status = 0; - for (c = 0; c < SCSI_ID_MAX; c++) - spock_clear_irq(scsi, c); + for (c = 0; c < SCSI_ID_MAX; c++) + spock_clear_irq(scsi, c); - if (scsi->in_reset == 1) { - scsi->basic_ctrl |= CTRL_IRQ_ENA; - spock_set_irq(scsi, 0xf, IRQ_TYPE_RESET_COMPLETE); - } else - spock_set_irq(scsi, 0xf, IRQ_TYPE_RESET_COMPLETE); + if (scsi->in_reset == 1) { + scsi->basic_ctrl |= CTRL_IRQ_ENA; + } - /*Reset device mappings*/ - for (c = 0; c < 7; c++) { - scsi->dev_id[c].phys_id = c; - scsi->dev_id[c].lun_id = 0; - } - for (; c < (SCSI_ID_MAX-1); c++) - scsi->dev_id[c].phys_id = -1; + spock_set_irq(scsi, 0x0f, IRQ_TYPE_RESET_COMPLETE); - scsi->in_reset = 0; - return; - } - - if (scsi->in_invalid) { - spock_log("Invalid command\n"); - spock_set_irq(scsi, scsi->attention & 0x0f, IRQ_TYPE_COMMAND_ERROR); - scsi->in_invalid = 0; - return; - } - - spock_log("SCB State = %d\n", scsi->scb_state); - - do - { - old_scb_state = scsi->scb_state; - - switch (scsi->scb_state) { - case 0: /* Idle */ - break; - - case 1: /* Select */ - if (scsi->dev_id[scsi->scb_id].phys_id == -1) { - uint16_t term_stat_block_addr7 = (0xe << 8) | 0; - uint16_t term_stat_block_addr8 = (0xa << 8) | 0; + /*Reset device mappings*/ + for (c = 0; c < 7; c++) { + scsi->dev_id[c].phys_id = c; + scsi->dev_id[c].lun_id = 0; + } + for (; c < (SCSI_ID_MAX - 1); c++) + scsi->dev_id[c].phys_id = -1; - spock_log("Start failed, SCB ID = %d\n", scsi->scb_id); - spock_set_irq(scsi, scsi->scb_id, IRQ_TYPE_COMMAND_FAIL); - scsi->scb_state = 0; - dma_bm_write(scb->term_status_block_addr + 0x7*2, (uint8_t *)&term_stat_block_addr7, 2, 2); - dma_bm_write(scb->term_status_block_addr + 0x8*2, (uint8_t *)&term_stat_block_addr8, 2, 2); - break; - } - - dma_bm_read(scsi->scb_addr, (uint8_t *)&scb->command, 2, 2); - dma_bm_read(scsi->scb_addr + 2, (uint8_t *)&scb->enable, 2, 2); - dma_bm_read(scsi->scb_addr + 4, (uint8_t *)&scb->lba_addr, 4, 2); - dma_bm_read(scsi->scb_addr + 8, (uint8_t *)&scb->sge.sys_buf_addr, 4, 2); - dma_bm_read(scsi->scb_addr + 12, (uint8_t *)&scb->sge.sys_buf_byte_count, 4, 2); - dma_bm_read(scsi->scb_addr + 16, (uint8_t *)&scb->term_status_block_addr, 4, 2); - dma_bm_read(scsi->scb_addr + 20, (uint8_t *)&scb->scb_chain_addr, 4, 2); - dma_bm_read(scsi->scb_addr + 24, (uint8_t *)&scb->block_count, 2, 2); - dma_bm_read(scsi->scb_addr + 26, (uint8_t *)&scb->block_length, 2, 2); + scsi->in_reset = 0; - spock_log("SCB : \n" - " Command = %04x\n" - " Enable = %04x\n" - " LBA addr = %08x\n" - " System buffer addr = %08x\n" - " System buffer byte count = %08x\n" - " Terminate status block addr = %08x\n" - " SCB chain address = %08x\n" - " Block count = %04x\n" - " Block length = %04x\n" - " SCB id = %d\n", - scb->command, scb->enable, scb->lba_addr, - scb->sge.sys_buf_addr, scb->sge.sys_buf_byte_count, - scb->term_status_block_addr, scb->scb_chain_addr, - scb->block_count, scb->block_length, scsi->scb_id); - - switch (scb->command & CMD_MASK) { - case CMD_GET_COMPLETE_STATUS: - { - spock_log("Get Complete Status\n"); - get_complete_stat_t *get_complete_stat = &scsi->get_complete_stat; - - get_complete_stat->scb_status = 0x201; - get_complete_stat->retry_count = 0; - get_complete_stat->residual_byte_count = 0; - get_complete_stat->sg_list_element_addr = 0; - get_complete_stat->device_dep_status_len = 0x0c; - get_complete_stat->cmd_status = scsi->cmd_status << 8; - get_complete_stat->error = 0; - get_complete_stat->reserved = 0; - get_complete_stat->cache_info_status = 0; - get_complete_stat->scb_addr = scsi->scb_addr; + for (c = 6; c > -1; c--) { + if (scsi_device_present(&scsi_devices[scsi->bus][c])) { + spock_log("Reset, SCSI reset present devices=%d, phys ID=%d, type=%04x.\n", j, scsi->dev_id[c].phys_id, scsi_devices[scsi->bus][c].type); + scsi->present[j] = c; + j++; + } else { + spock_log("Reset, SCSI reset not present devices=%d, phys ID=%d, type=%04x.\n", j, scsi->dev_id[c].phys_id, scsi_devices[scsi->bus][c].type); + } + } + return; + } - dma_bm_write(scb->sge.sys_buf_addr, (uint8_t *)&get_complete_stat->scb_status, 2, 2); - dma_bm_write(scb->sge.sys_buf_addr + 2, (uint8_t *)&get_complete_stat->retry_count, 2, 2); - dma_bm_write(scb->sge.sys_buf_addr + 4, (uint8_t *)&get_complete_stat->residual_byte_count, 4, 2); - dma_bm_write(scb->sge.sys_buf_addr + 8, (uint8_t *)&get_complete_stat->sg_list_element_addr, 4, 2); - dma_bm_write(scb->sge.sys_buf_addr + 12, (uint8_t *)&get_complete_stat->device_dep_status_len, 2, 2); - dma_bm_write(scb->sge.sys_buf_addr + 14, (uint8_t *)&get_complete_stat->cmd_status, 2, 2); - dma_bm_write(scb->sge.sys_buf_addr + 16, (uint8_t *)&get_complete_stat->error, 2, 2); - dma_bm_write(scb->sge.sys_buf_addr + 18, (uint8_t *)&get_complete_stat->reserved, 2, 2); - dma_bm_write(scb->sge.sys_buf_addr + 20, (uint8_t *)&get_complete_stat->cache_info_status, 2, 2); - dma_bm_write(scb->sge.sys_buf_addr + 22, (uint8_t *)&get_complete_stat->scb_addr, 4, 2); - scsi->scb_state = 3; - } - break; + if (scsi->in_invalid) { + spock_log("Invalid command\n"); + spock_set_irq(scsi, scsi->attention & 0x0f, IRQ_TYPE_COMMAND_ERROR); + scsi->in_invalid = 0; + return; + } - case CMD_UNKNOWN_1C10: - spock_log("Unknown 1C10\n"); - dma_bm_read(scb->sge.sys_buf_addr, scsi->buf, scb->sge.sys_buf_byte_count, 2); - scsi->scb_state = 3; - break; + spock_log("SCB State = %d\n", scsi->scb_state); - case CMD_UNKNOWN_1C11: - spock_log("Unknown 1C11\n"); - dma_bm_write(scb->sge.sys_buf_addr, scsi->buf, scb->sge.sys_buf_byte_count, 2); - scsi->scb_state = 3; - break; + do { + old_scb_state = scsi->scb_state; - case CMD_GET_POS_INFO: - { - spock_log("Get POS Info\n"); - get_pos_info_t *get_pos_info = &scsi->get_pos_info; - - get_pos_info->pos = 0x8eff; - get_pos_info->pos1 = scsi->pos_regs[3] | (scsi->pos_regs[2] << 8); - get_pos_info->pos2 = 0x0e | (scsi->pos_regs[4] << 8); - get_pos_info->pos3 = 1 << 12; - get_pos_info->pos4 = (7 << 8) | 8; - get_pos_info->pos5 = (16 << 8) | scsi->pacing; - get_pos_info->pos6 = (30 << 8) | 1; - get_pos_info->pos7 = 0; - get_pos_info->pos8 = 0; - - dma_bm_write(scb->sge.sys_buf_addr, (uint8_t *)&get_pos_info->pos, 2, 2); - dma_bm_write(scb->sge.sys_buf_addr + 2, (uint8_t *)&get_pos_info->pos1, 2, 2); - dma_bm_write(scb->sge.sys_buf_addr + 4, (uint8_t *)&get_pos_info->pos2, 2, 2); - dma_bm_write(scb->sge.sys_buf_addr + 6, (uint8_t *)&get_pos_info->pos3, 2, 2); - dma_bm_write(scb->sge.sys_buf_addr + 8, (uint8_t *)&get_pos_info->pos4, 2, 2); - dma_bm_write(scb->sge.sys_buf_addr + 10, (uint8_t *)&get_pos_info->pos5, 2, 2); - dma_bm_write(scb->sge.sys_buf_addr + 12, (uint8_t *)&get_pos_info->pos6, 2, 2); - dma_bm_write(scb->sge.sys_buf_addr + 14, (uint8_t *)&get_pos_info->pos7, 2, 2); - dma_bm_write(scb->sge.sys_buf_addr + 16, (uint8_t *)&get_pos_info->pos8, 2, 2); - scsi->scb_state = 3; - } - break; + switch (scsi->scb_state) { + case 0: /* Idle */ + break; - case CMD_DEVICE_INQUIRY: - if (scsi->adapter_reset) { - scsi->cdb_id = scsi->scb_id; - } else { - scsi->cdb_id = scsi->dev_id[scsi->scb_id].phys_id; - } - spock_log("Device Inquiry, ID=%d\n", scsi->cdb_id); - scsi->cdb[0] = GPCMD_INQUIRY; - scsi->cdb[1] = scsi->dev_id[scsi->scb_id].lun_id << 5; /*LUN*/ - scsi->cdb[2] = 0; /*Page code*/ - scsi->cdb[3] = 0; - scsi->cdb[4] = scb->sge.sys_buf_byte_count; /*Allocation length*/ - scsi->cdb[5] = 0; /*Control*/ - scsi->cdb_len = 6; - scsi->data_ptr = scb->sge.sys_buf_addr; - scsi->data_len = scb->sge.sys_buf_byte_count; - scsi->scsi_state = SCSI_STATE_SELECT; - scsi->scb_state = 2; - return; + case 1: /* Select */ + if (scsi->dev_id[scsi->scb_id].phys_id == -1) { + uint16_t term_stat_block_addr7 = (0xe << 8) | 0; + uint16_t term_stat_block_addr8 = (0xa << 8) | 0; - case CMD_SEND_OTHER_SCSI: - if (scsi->adapter_reset) { - scsi->cdb_id = scsi->scb_id; - } else { - scsi->cdb_id = scsi->dev_id[scsi->scb_id].phys_id; - } - spock_log("Send Other SCSI, ID=%d\n", scsi->cdb_id); - dma_bm_read(scsi->scb_addr + 0x18, scsi->cdb, 12, 2); - scsi->cdb[1] = (scsi->cdb[1] & 0x1f) | (scsi->dev_id[scsi->scb_id].lun_id << 5); /*Patch correct LUN into command*/ - scsi->cdb_len = (scb->lba_addr & 0xff) ? (scb->lba_addr & 0xff) : 6; - scsi->scsi_state = SCSI_STATE_SELECT; - scsi->scb_state = 2; - return; + spock_log("Start failed, SCB ID = %d\n", scsi->scb_id); + spock_set_irq(scsi, scsi->scb_id, IRQ_TYPE_COMMAND_FAIL); + scsi->scb_state = 0; + dma_bm_write(scb->term_status_block_addr + 0x7 * 2, (uint8_t *) &term_stat_block_addr7, 2, 2); + dma_bm_write(scb->term_status_block_addr + 0x8 * 2, (uint8_t *) &term_stat_block_addr8, 2, 2); + break; + } - case CMD_READ_DEVICE_CAPACITY: - if (scsi->adapter_reset) - scsi->cdb_id = scsi->scb_id; - else - scsi->cdb_id = scsi->dev_id[scsi->scb_id].phys_id; - spock_log("Device Capacity, ID=%d\n", scsi->cdb_id); - scsi->cdb[0] = GPCMD_READ_CDROM_CAPACITY; - scsi->cdb[1] = scsi->dev_id[scsi->scb_id].lun_id << 5; /*LUN*/ - scsi->cdb[2] = 0; /*LBA*/ - scsi->cdb[3] = 0; - scsi->cdb[4] = 0; - scsi->cdb[5] = 0; - scsi->cdb[6] = 0; /*Reserved*/ - scsi->cdb[7] = 0; - scsi->cdb[8] = 0; - scsi->cdb[9] = 0; /*Control*/ - scsi->cdb_len = 10; - scsi->scsi_state = SCSI_STATE_SELECT; - scsi->scb_state = 2; - return; + dma_bm_read(scsi->scb_addr, (uint8_t *) &scb->command, 2, 2); + dma_bm_read(scsi->scb_addr + 2, (uint8_t *) &scb->enable, 2, 2); + dma_bm_read(scsi->scb_addr + 4, (uint8_t *) &scb->lba_addr, 4, 2); + dma_bm_read(scsi->scb_addr + 8, (uint8_t *) &scb->sge.sys_buf_addr, 4, 2); + dma_bm_read(scsi->scb_addr + 12, (uint8_t *) &scb->sge.sys_buf_byte_count, 4, 2); + dma_bm_read(scsi->scb_addr + 16, (uint8_t *) &scb->term_status_block_addr, 4, 2); + dma_bm_read(scsi->scb_addr + 20, (uint8_t *) &scb->scb_chain_addr, 4, 2); + dma_bm_read(scsi->scb_addr + 24, (uint8_t *) &scb->block_count, 2, 2); + dma_bm_read(scsi->scb_addr + 26, (uint8_t *) &scb->block_length, 2, 2); - case CMD_READ_DATA: - spock_log("Device Read Data\n"); - scsi->cdb[0] = GPCMD_READ_10; - scsi->cdb[1] = scsi->dev_id[scsi->scb_id].lun_id << 5; /*LUN*/ - scsi->cdb[2] = (scb->lba_addr >> 24) & 0xff; /*LBA*/ - scsi->cdb[3] = (scb->lba_addr >> 16) & 0xff; - scsi->cdb[4] = (scb->lba_addr >> 8) & 0xff; - scsi->cdb[5] = scb->lba_addr & 0xff; - scsi->cdb[6] = 0; /*Reserved*/ - scsi->cdb[7] = (scb->block_count >> 8) & 0xff; - scsi->cdb[8] = scb->block_count & 0xff; - scsi->cdb[9] = 0; /*Control*/ - scsi->cdb_len = 10; - scsi->cdb_id = scsi->dev_id[scsi->scb_id].phys_id; - scsi->scsi_state = SCSI_STATE_SELECT; - scsi->scb_state = 2; - return; + spock_log("SCB : \n" + " Command = %04x\n" + " Enable = %04x\n" + " LBA addr = %08x\n" + " System buffer addr = %08x\n" + " System buffer byte count = %08x\n" + " Terminate status block addr = %08x\n" + " SCB chain address = %08x\n" + " Block count = %04x\n" + " Block length = %04x\n" + " SCB id = %d, Phys id = %d, Spock CMD = %08x, CMD Mask = %02x.\n", + scb->command, scb->enable, scb->lba_addr, + scb->sge.sys_buf_addr, scb->sge.sys_buf_byte_count, + scb->term_status_block_addr, scb->scb_chain_addr, + scb->block_count, scb->block_length, scsi->scb_id, scsi->dev_id[scsi->scb_id].phys_id, scsi->command, scb->command & 0xc0); - case CMD_WRITE_DATA: - spock_log("Device Write Data\n"); - scsi->cdb[0] = GPCMD_WRITE_10; - scsi->cdb[1] = scsi->dev_id[scsi->scb_id].lun_id << 5; /*LUN*/ - scsi->cdb[2] = (scb->lba_addr >> 24) & 0xff; /*LBA*/ - scsi->cdb[3] = (scb->lba_addr >> 16) & 0xff; - scsi->cdb[4] = (scb->lba_addr >> 8) & 0xff; - scsi->cdb[5] = scb->lba_addr & 0xff; - scsi->cdb[6] = 0; /*Reserved*/ - scsi->cdb[7] = (scb->block_count >> 8) & 0xff; - scsi->cdb[8] = scb->block_count & 0xff; - scsi->cdb[9] = 0; /*Control*/ - scsi->cdb_len = 10; - scsi->cdb_id = scsi->dev_id[scsi->scb_id].phys_id; - scsi->scsi_state = SCSI_STATE_SELECT; - scsi->scb_state = 2; - return; - - case CMD_VERIFY: - spock_log("Device Verify\n"); - scsi->cdb[0] = GPCMD_VERIFY_10; - scsi->cdb[1] = scsi->dev_id[scsi->scb_id].lun_id << 5; /*LUN*/ - scsi->cdb[2] = (scb->lba_addr >> 24) & 0xff; /*LBA*/ - scsi->cdb[3] = (scb->lba_addr >> 16) & 0xff; - scsi->cdb[4] = (scb->lba_addr >> 8) & 0xff; - scsi->cdb[5] = scb->lba_addr & 0xff; - scsi->cdb[6] = 0; /*Reserved*/ - scsi->cdb[7] = (scb->block_count >> 8) & 0xff; - scsi->cdb[8] = scb->block_count & 0xff; - scsi->cdb[9] = 0; /*Control*/ - scsi->cdb_len = 10; - scsi->cdb_id = scsi->dev_id[scsi->scb_id].phys_id; - scsi->data_len = 0; - scsi->scsi_state = SCSI_STATE_SELECT; - scsi->scb_state = 2; - return; - - case CMD_REQUEST_SENSE: - if (scsi->adapter_reset) - scsi->cdb_id = scsi->scb_id; - else - scsi->cdb_id = scsi->dev_id[scsi->scb_id].phys_id; - spock_log("Device Request Sense, ID=%d\n", scsi->cdb_id); - scsi->cdb[0] = GPCMD_REQUEST_SENSE; - scsi->cdb[1] = scsi->dev_id[scsi->scb_id].lun_id << 5; /*LUN*/ - scsi->cdb[2] = 0; - scsi->cdb[3] = 0; - scsi->cdb[4] = scb->sge.sys_buf_byte_count; /*Allocation length*/ - scsi->cdb[5] = 0; - scsi->cdb_len = 6; - scsi->scsi_state = SCSI_STATE_SELECT; - scsi->scb_state = 2; - return; - } - break; - - case 2: /* Wait */ - if (scsi->scsi_state == SCSI_STATE_IDLE && scsi_device_present(&scsi_devices[scsi->bus][scsi->cdb_id])) { - if (scsi->last_status == SCSI_STATUS_OK) { - scsi->scb_state = 3; - spock_log("Status is Good on device ID %d, timer = %i\n", scsi->cdb_id, scsi->cmd_timer); - } else if (scsi->last_status == SCSI_STATUS_CHECK_CONDITION) { - uint16_t term_stat_block_addr7 = (0xc << 8) | 2; - uint16_t term_stat_block_addr8 = 0x20; - uint16_t term_stat_block_addrb = scsi->scb_addr & 0xffff; - uint16_t term_stat_block_addrc = scsi->scb_addr >> 16; - - spock_set_irq(scsi, scsi->scb_id, IRQ_TYPE_COMMAND_FAIL); - scsi->scb_state = 0; - spock_log("Status Check Condition on device ID %d\n", scsi->cdb_id); - dma_bm_write(scb->term_status_block_addr + 0x7*2, (uint8_t *)&term_stat_block_addr7, 2, 2); - dma_bm_write(scb->term_status_block_addr + 0x8*2, (uint8_t *)&term_stat_block_addr8, 2, 2); - dma_bm_write(scb->term_status_block_addr + 0xb*2, (uint8_t *)&term_stat_block_addrb, 2, 2); - dma_bm_write(scb->term_status_block_addr + 0xc*2, (uint8_t *)&term_stat_block_addrc, 2, 2); - } - } else if (scsi->scsi_state == SCSI_STATE_IDLE && !scsi_device_present(&scsi_devices[scsi->bus][scsi->cdb_id])) { - uint16_t term_stat_block_addr7 = (0xc << 8) | 2; - uint16_t term_stat_block_addr8 = 0x10; - spock_set_irq(scsi, scsi->scb_id, IRQ_TYPE_COMMAND_FAIL); - scsi->scb_state = 0; - dma_bm_write(scb->term_status_block_addr + 0x7*2, (uint8_t *)&term_stat_block_addr7, 2, 2); - dma_bm_write(scb->term_status_block_addr + 0x8*2, (uint8_t *)&term_stat_block_addr8, 2, 2); - } - break; - - case 3: /* Complete */ - if (scb->enable & 1) { - scsi->scb_state = 1; - scsi->scb_addr = scb->scb_chain_addr; - spock_log("Next SCB - %08x\n", scsi->scb_addr); - } else { - spock_set_irq(scsi, scsi->scb_id, IRQ_TYPE_SCB_COMPLETE); - scsi->scb_state = 0; - spock_log("Complete SCB\n"); - } - break; - } - } while (scsi->scb_state != old_scb_state); + switch (scb->command & CMD_MASK) { + case CMD_GET_COMPLETE_STATUS: + { + spock_log("Get Complete Status\n"); + get_complete_stat_t *get_complete_stat = &scsi->get_complete_stat; + + get_complete_stat->scb_status = 0x201; + get_complete_stat->retry_count = 0; + get_complete_stat->residual_byte_count = 0; + get_complete_stat->sg_list_element_addr = 0; + get_complete_stat->device_dep_status_len = 0x0c; + get_complete_stat->cmd_status = scsi->cmd_status << 8; + get_complete_stat->error = 0; + get_complete_stat->reserved = 0; + get_complete_stat->cache_info_status = 0; + get_complete_stat->scb_addr = scsi->scb_addr; + + dma_bm_write(scb->sge.sys_buf_addr, (uint8_t *) &get_complete_stat->scb_status, 2, 2); + dma_bm_write(scb->sge.sys_buf_addr + 2, (uint8_t *) &get_complete_stat->retry_count, 2, 2); + dma_bm_write(scb->sge.sys_buf_addr + 4, (uint8_t *) &get_complete_stat->residual_byte_count, 4, 2); + dma_bm_write(scb->sge.sys_buf_addr + 8, (uint8_t *) &get_complete_stat->sg_list_element_addr, 4, 2); + dma_bm_write(scb->sge.sys_buf_addr + 12, (uint8_t *) &get_complete_stat->device_dep_status_len, 2, 2); + dma_bm_write(scb->sge.sys_buf_addr + 14, (uint8_t *) &get_complete_stat->cmd_status, 2, 2); + dma_bm_write(scb->sge.sys_buf_addr + 16, (uint8_t *) &get_complete_stat->error, 2, 2); + dma_bm_write(scb->sge.sys_buf_addr + 18, (uint8_t *) &get_complete_stat->reserved, 2, 2); + dma_bm_write(scb->sge.sys_buf_addr + 20, (uint8_t *) &get_complete_stat->cache_info_status, 2, 2); + dma_bm_write(scb->sge.sys_buf_addr + 22, (uint8_t *) &get_complete_stat->scb_addr, 4, 2); + scsi->scb_state = 3; + } + break; + + case CMD_UNKNOWN_1C10: + spock_log("Unknown 1C10\n"); + dma_bm_read(scb->sge.sys_buf_addr, scsi->buf, scb->sge.sys_buf_byte_count, 2); + scsi->scb_state = 3; + break; + + case CMD_UNKNOWN_1C11: + spock_log("Unknown 1C11\n"); + dma_bm_write(scb->sge.sys_buf_addr, scsi->buf, scb->sge.sys_buf_byte_count, 2); + scsi->scb_state = 3; + break; + + case CMD_GET_POS_INFO: + { + spock_log("Get POS Info\n"); + get_pos_info_t *get_pos_info = &scsi->get_pos_info; + + get_pos_info->pos = scsi->spock_16bit ? 0x8efe : 0x8eff; + get_pos_info->pos1 = scsi->pos_regs[3] | (scsi->pos_regs[2] << 8); + get_pos_info->pos2 = scsi->irq | (scsi->pos_regs[4] << 8); + get_pos_info->pos3 = 1 << 12; + get_pos_info->pos4 = (7 << 8) | 8; + get_pos_info->pos5 = (16 << 8) | scsi->pacing; + get_pos_info->pos6 = (30 << 8) | 1; + get_pos_info->pos7 = 0; + get_pos_info->pos8 = 0; + + dma_bm_write(scb->sge.sys_buf_addr, (uint8_t *) &get_pos_info->pos, 2, 2); + dma_bm_write(scb->sge.sys_buf_addr + 2, (uint8_t *) &get_pos_info->pos1, 2, 2); + dma_bm_write(scb->sge.sys_buf_addr + 4, (uint8_t *) &get_pos_info->pos2, 2, 2); + dma_bm_write(scb->sge.sys_buf_addr + 6, (uint8_t *) &get_pos_info->pos3, 2, 2); + dma_bm_write(scb->sge.sys_buf_addr + 8, (uint8_t *) &get_pos_info->pos4, 2, 2); + dma_bm_write(scb->sge.sys_buf_addr + 10, (uint8_t *) &get_pos_info->pos5, 2, 2); + dma_bm_write(scb->sge.sys_buf_addr + 12, (uint8_t *) &get_pos_info->pos6, 2, 2); + dma_bm_write(scb->sge.sys_buf_addr + 14, (uint8_t *) &get_pos_info->pos7, 2, 2); + dma_bm_write(scb->sge.sys_buf_addr + 16, (uint8_t *) &get_pos_info->pos8, 2, 2); + scsi->scb_state = 3; + } + break; + + case CMD_DEVICE_INQUIRY: + scsi->cdb_id = scsi->assign ? scsi->dev_id[scsi->scb_id].phys_id : scsi->present[scsi->scb_id]; + spock_log("Device Inquiry, ID=%d\n", scsi->cdb_id); + scsi->cdb[0] = GPCMD_INQUIRY; + scsi->cdb[1] = scsi->dev_id[scsi->scb_id].lun_id << 5; /*LUN*/ + scsi->cdb[2] = 0; /*Page code*/ + scsi->cdb[3] = 0; + scsi->cdb[4] = scb->sge.sys_buf_byte_count; /*Allocation length*/ + scsi->cdb[5] = 0; /*Control*/ + scsi->cdb_len = 6; + scsi->data_ptr = scb->sge.sys_buf_addr; + scsi->data_len = scb->sge.sys_buf_byte_count; + scsi->scsi_state = SCSI_STATE_SELECT; + scsi->scb_state = 2; + return; + + case CMD_SEND_OTHER_SCSI: + scsi->cdb_id = scsi->assign ? scsi->dev_id[scsi->scb_id].phys_id : scsi->present[scsi->scb_id]; + dma_bm_read(scsi->scb_addr + 0x18, scsi->cdb, 12, 2); + spock_log("Send Other SCSI, SCB ID=%d, PHYS ID=%d, CDB[0]=%02x, CDB_ID=%d\n", scsi->scb_id, scsi->dev_id[scsi->scb_id].phys_id, scsi->cdb[0], scsi->cdb_id); + scsi->cdb[1] = (scsi->cdb[1] & 0x1f) | (scsi->dev_id[scsi->scb_id].lun_id << 5); /*Patch correct LUN into command*/ + scsi->cdb_len = (scb->lba_addr & 0xff) ? (scb->lba_addr & 0xff) : 6; + scsi->scsi_state = SCSI_STATE_SELECT; + scsi->scb_state = 2; + return; + + case CMD_READ_DEVICE_CAPACITY: + scsi->cdb_id = scsi->assign ? scsi->dev_id[scsi->scb_id].phys_id : scsi->present[scsi->scb_id]; + spock_log("Device Capacity, SCB ID=%d, PHYS ID=%d\n", scsi->scb_id, scsi->dev_id[scsi->scb_id].phys_id); + scsi->cdb[0] = GPCMD_READ_CDROM_CAPACITY; + scsi->cdb[1] = scsi->dev_id[scsi->scb_id].lun_id << 5; /*LUN*/ + scsi->cdb[2] = 0; /*LBA*/ + scsi->cdb[3] = 0; + scsi->cdb[4] = 0; + scsi->cdb[5] = 0; + scsi->cdb[6] = 0; /*Reserved*/ + scsi->cdb[7] = 0; + scsi->cdb[8] = 0; + scsi->cdb[9] = 0; /*Control*/ + scsi->cdb_len = 10; + scsi->scsi_state = SCSI_STATE_SELECT; + scsi->scb_state = 2; + return; + + case CMD_READ_DATA: + scsi->cdb_id = scsi->assign ? scsi->dev_id[scsi->scb_id].phys_id : scsi->present[scsi->scb_id]; + spock_log("Device Read Data, SCB ID=%d, PHYS ID=%d\n", scsi->scb_id, scsi->dev_id[scsi->scb_id].phys_id); + scsi->cdb[0] = GPCMD_READ_10; + scsi->cdb[1] = scsi->dev_id[scsi->scb_id].lun_id << 5; /*LUN*/ + scsi->cdb[2] = (scb->lba_addr >> 24) & 0xff; /*LBA*/ + scsi->cdb[3] = (scb->lba_addr >> 16) & 0xff; + scsi->cdb[4] = (scb->lba_addr >> 8) & 0xff; + scsi->cdb[5] = scb->lba_addr & 0xff; + scsi->cdb[6] = 0; /*Reserved*/ + scsi->cdb[7] = (scb->block_count >> 8) & 0xff; + scsi->cdb[8] = scb->block_count & 0xff; + scsi->cdb[9] = 0; /*Control*/ + scsi->cdb_len = 10; + scsi->scsi_state = SCSI_STATE_SELECT; + scsi->scb_state = 2; + return; + + case CMD_WRITE_DATA: + scsi->cdb_id = scsi->assign ? scsi->dev_id[scsi->scb_id].phys_id : scsi->present[scsi->scb_id]; + spock_log("Device Write Data\n"); + scsi->cdb[0] = GPCMD_WRITE_10; + scsi->cdb[1] = scsi->dev_id[scsi->scb_id].lun_id << 5; /*LUN*/ + scsi->cdb[2] = (scb->lba_addr >> 24) & 0xff; /*LBA*/ + scsi->cdb[3] = (scb->lba_addr >> 16) & 0xff; + scsi->cdb[4] = (scb->lba_addr >> 8) & 0xff; + scsi->cdb[5] = scb->lba_addr & 0xff; + scsi->cdb[6] = 0; /*Reserved*/ + scsi->cdb[7] = (scb->block_count >> 8) & 0xff; + scsi->cdb[8] = scb->block_count & 0xff; + scsi->cdb[9] = 0; /*Control*/ + scsi->cdb_len = 10; + scsi->scsi_state = SCSI_STATE_SELECT; + scsi->scb_state = 2; + return; + + case CMD_VERIFY: + scsi->cdb_id = scsi->assign ? scsi->dev_id[scsi->scb_id].phys_id : scsi->present[scsi->scb_id]; + spock_log("Device Verify\n"); + scsi->cdb[0] = GPCMD_VERIFY_10; + scsi->cdb[1] = scsi->dev_id[scsi->scb_id].lun_id << 5; /*LUN*/ + scsi->cdb[2] = (scb->lba_addr >> 24) & 0xff; /*LBA*/ + scsi->cdb[3] = (scb->lba_addr >> 16) & 0xff; + scsi->cdb[4] = (scb->lba_addr >> 8) & 0xff; + scsi->cdb[5] = scb->lba_addr & 0xff; + scsi->cdb[6] = 0; /*Reserved*/ + scsi->cdb[7] = (scb->block_count >> 8) & 0xff; + scsi->cdb[8] = scb->block_count & 0xff; + scsi->cdb[9] = 0; /*Control*/ + scsi->cdb_len = 10; + scsi->data_len = 0; + scsi->scsi_state = SCSI_STATE_SELECT; + scsi->scb_state = 2; + return; + + case CMD_REQUEST_SENSE: + scsi->cdb_id = scsi->assign ? scsi->dev_id[scsi->scb_id].phys_id : scsi->present[scsi->scb_id]; + spock_log("Device Request Sense, ID=%d\n", scsi->cdb_id); + scsi->cdb[0] = GPCMD_REQUEST_SENSE; + scsi->cdb[1] = scsi->dev_id[scsi->scb_id].lun_id << 5; /*LUN*/ + scsi->cdb[2] = 0; + scsi->cdb[3] = 0; + scsi->cdb[4] = scb->sge.sys_buf_byte_count; /*Allocation length*/ + scsi->cdb[5] = 0; + scsi->cdb_len = 6; + scsi->scsi_state = SCSI_STATE_SELECT; + scsi->scb_state = 2; + return; + + default: + break; + } + break; + + case 2: /* Wait */ + if (scsi->scsi_state == SCSI_STATE_IDLE) { + if (scsi_device_present(&scsi_devices[scsi->bus][scsi->cdb_id])) { + if (scsi->last_status == SCSI_STATUS_OK) { + scsi->scb_state = 3; + spock_log("Status is Good on device ID %d, cdb id = %d.\n", scsi->scb_id, scsi->cdb_id); + } else if (scsi->last_status == SCSI_STATUS_CHECK_CONDITION) { + uint16_t term_stat_block_addr7 = (0xc << 8) | 2; + uint16_t term_stat_block_addr8 = 0x20; + uint16_t term_stat_block_addrb = scsi->scb_addr & 0xffff; + uint16_t term_stat_block_addrc = scsi->scb_addr >> 16; + + spock_set_irq(scsi, scsi->scb_id, IRQ_TYPE_COMMAND_FAIL); + scsi->scb_state = 0; + spock_log("Status Check Condition on device ID %d, cdb id = %d.\n", scsi->attention & 0x0f, scsi->cdb_id); + dma_bm_write(scb->term_status_block_addr + 0x7 * 2, (uint8_t *) &term_stat_block_addr7, 2, 2); + dma_bm_write(scb->term_status_block_addr + 0x8 * 2, (uint8_t *) &term_stat_block_addr8, 2, 2); + dma_bm_write(scb->term_status_block_addr + 0xb * 2, (uint8_t *) &term_stat_block_addrb, 2, 2); + dma_bm_write(scb->term_status_block_addr + 0xc * 2, (uint8_t *) &term_stat_block_addrc, 2, 2); + } + } else { + uint16_t term_stat_block_addr7 = (0xc << 8) | 2; + uint16_t term_stat_block_addr8 = 0x10; + spock_set_irq(scsi, scsi->scb_id, IRQ_TYPE_COMMAND_FAIL); + scsi->scb_state = 0; + spock_log("Status Check Condition on device ID %d on no device\n", scsi->scb_id); + dma_bm_write(scb->term_status_block_addr + 0x7 * 2, (uint8_t *) &term_stat_block_addr7, 2, 2); + dma_bm_write(scb->term_status_block_addr + 0x8 * 2, (uint8_t *) &term_stat_block_addr8, 2, 2); + } + } + break; + + case 3: /* Complete */ + if (scb->enable & 1) { + scsi->scb_state = 1; + scsi->scb_addr = scb->scb_chain_addr; + spock_log("Next SCB - %08x\n", scsi->scb_addr); + } else { + spock_set_irq(scsi, scsi->scb_id, IRQ_TYPE_SCB_COMPLETE); + scsi->scb_state = 0; + spock_log("Complete SCB ID = %d.\n", scsi->attention & 0x0f); + } + break; + + default: + break; + } + } while (scsi->scb_state != old_scb_state); } static void spock_process_scsi(spock_t *scsi, scb_t *scb) { - int c; - double p; - scsi_device_t *sd; + double p; + scsi_device_t *sd; - switch (scsi->scsi_state) { - case SCSI_STATE_IDLE: - break; - - case SCSI_STATE_SELECT: - spock_log("Selecting ID %d\n", scsi->cdb_id); - if ((scsi->cdb_id != (uint8_t)-1) && scsi_device_present(&scsi_devices[scsi->bus][scsi->cdb_id])) { - scsi->scsi_state = SCSI_STATE_SEND_COMMAND; - spock_log("Device selected at ID %i\n", scsi->cdb_id); - } else { - spock_log("Device selection failed at ID %i\n", scsi->cdb_id); - scsi->scsi_state = SCSI_STATE_IDLE; - if (!scsi->cmd_timer) { - spock_log("Callback to reset\n"); - scsi->cmd_timer = 1; - } - spock_add_to_period(scsi, 1); - } - break; + switch (scsi->scsi_state) { + case SCSI_STATE_IDLE: + break; - case SCSI_STATE_SEND_COMMAND: - sd = &scsi_devices[scsi->bus][scsi->cdb_id]; - memset(scsi->temp_cdb, 0x00, 12); + case SCSI_STATE_SELECT: + spock_log("Selecting ID %d, SCB ID %d, LUN %d, adapter id = %d.\n", scsi->cdb_id, scsi->scb_id, scsi->dev_id[scsi->scb_id].lun_id, scsi->attention); + if ((scsi->cdb_id != (uint8_t) -1) && scsi_device_present(&scsi_devices[scsi->bus][scsi->cdb_id])) { + scsi->scsi_state = SCSI_STATE_SEND_COMMAND; + spock_log("Device selected at ID %i.\n", scsi->cdb_id); + } else { + spock_log("Device selection failed at ID %i.\n", scsi->cdb_id); + scsi->scsi_state = SCSI_STATE_IDLE; + if (!scsi->cmd_timer) { + spock_log("Callback to reset\n"); + scsi->cmd_timer = 1; + } + spock_add_to_period(scsi, 1); + } + break; - if (scsi->cdb_len < 12) { - memcpy(scsi->temp_cdb, scsi->cdb, - scsi->cdb_len); - spock_add_to_period(scsi, scsi->cdb_len); - } else { - memcpy(scsi->temp_cdb, scsi->cdb, - 12); - spock_add_to_period(scsi, 12); - } - - scsi->data_ptr = scb->sge.sys_buf_addr; - scsi->data_len = scb->sge.sys_buf_byte_count; - - if (scb->enable & 0x400) - sd->buffer_length = -1; - else - sd->buffer_length = spock_get_len(scsi, scb); - - scsi_device_command_phase0(sd, scsi->temp_cdb); - spock_log("SCSI ID %i: Current CDB[0] = %02x, LUN = %i, data len = %i, max len = %i, phase val = %02x\n", scsi->cdb_id, scsi->temp_cdb[0], scsi->temp_cdb[1] >> 5, sd->buffer_length, spock_get_len(scsi, scb), sd->phase); - - if (sd->phase != SCSI_PHASE_STATUS && sd->buffer_length > 0) { - p = scsi_device_get_callback(sd); - if (p <= 0.0) - spock_add_to_period(scsi, sd->buffer_length); - else - scsi->media_period += p; - - if (scb->enable & ENABLE_PT) { - int32_t buflen = sd->buffer_length; - int sg_pos = 0; - uint32_t DataTx = 0; - uint32_t Address; - - if (scb->sge.sys_buf_byte_count > 0) { - for (c = 0; c < scsi->data_len; c += 8) { - spock_rd_sge(scsi, scsi->data_ptr + c, &scb->sge); - - Address = scb->sge.sys_buf_addr; - DataTx = MIN((int) scb->sge.sys_buf_byte_count, buflen); - - if ((sd->phase == SCSI_PHASE_DATA_IN) && DataTx) { - spock_log("Writing S/G segment %i: length %i, pointer %08X\n", c, DataTx, Address); - dma_bm_write(Address, &sd->sc->temp_buffer[sg_pos], DataTx, 2); - } else if ((sd->phase == SCSI_PHASE_DATA_OUT) && DataTx) { - spock_log("Reading S/G segment %i: length %i, pointer %08X\n", c, DataTx, Address); - dma_bm_read(Address, &sd->sc->temp_buffer[sg_pos], DataTx, 2); - } - - sg_pos += scb->sge.sys_buf_byte_count; - buflen -= scb->sge.sys_buf_byte_count; - - if (buflen < 0) - buflen = 0; - } - } - } else { - spock_log("Normal Transfer\n"); - if (sd->phase == SCSI_PHASE_DATA_IN) { - dma_bm_write(scsi->data_ptr, sd->sc->temp_buffer, MIN(sd->buffer_length, (int)scsi->data_len), 2); - } else if (sd->phase == SCSI_PHASE_DATA_OUT) - dma_bm_read(scsi->data_ptr, sd->sc->temp_buffer, MIN(sd->buffer_length, (int)scsi->data_len), 2); - } + case SCSI_STATE_SEND_COMMAND: + sd = &scsi_devices[scsi->bus][scsi->cdb_id]; + memset(scsi->temp_cdb, 0x00, 12); - scsi_device_command_phase1(sd); - } - scsi->last_status = sd->status; - scsi->scsi_state = SCSI_STATE_END_PHASE; - break; + if (scsi->cdb_len < 12) { + memcpy(scsi->temp_cdb, scsi->cdb, + scsi->cdb_len); + spock_add_to_period(scsi, scsi->cdb_len); + } else { + memcpy(scsi->temp_cdb, scsi->cdb, + 12); + spock_add_to_period(scsi, 12); + } - case SCSI_STATE_END_PHASE: - scsi->scsi_state = SCSI_STATE_IDLE; + scsi->data_ptr = scb->sge.sys_buf_addr; + scsi->data_len = scb->sge.sys_buf_byte_count; - spock_log("State to idle, cmd timer %d\n", scsi->cmd_timer); - if (!scsi->cmd_timer) { - scsi->cmd_timer = 1; - } - spock_add_to_period(scsi, 1); - break; - } + if (scb->enable & 0x400) + sd->buffer_length = -1; + else + sd->buffer_length = spock_get_len(scsi, scb); + + scsi_device_command_phase0(sd, scsi->temp_cdb); + spock_log("SCSI ID %i: Current CDB[0] = %02x, LUN = %i, data len = %i, max len = %i, phase val = %02x\n", scsi->cdb_id, scsi->temp_cdb[0], scsi->temp_cdb[1] >> 5, sd->buffer_length, spock_get_len(scsi, scb), sd->phase); + + if ((sd->phase != SCSI_PHASE_STATUS) && (sd->buffer_length > 0)) { + p = scsi_device_get_callback(sd); + if (p <= 0.0) + spock_add_to_period(scsi, sd->buffer_length); + else + scsi->media_period += p; + + if (scb->enable & ENABLE_PT) { + int32_t buflen = sd->buffer_length; + int sg_pos = 0; + uint32_t DataTx = 0; + uint32_t Address; + + if (scb->sge.sys_buf_byte_count > 0) { + for (uint32_t c = 0; c < scsi->data_len; c += 8) { + spock_rd_sge(scsi, scsi->data_ptr + c, &scb->sge); + + Address = scb->sge.sys_buf_addr; + DataTx = MIN((int) scb->sge.sys_buf_byte_count, buflen); + + if ((sd->phase == SCSI_PHASE_DATA_IN) && DataTx) { + spock_log("Writing S/G segment %i: length %i, pointer %08X\n", c, DataTx, Address); + dma_bm_write(Address, &sd->sc->temp_buffer[sg_pos], DataTx, 2); + } else if ((sd->phase == SCSI_PHASE_DATA_OUT) && DataTx) { + spock_log("Reading S/G segment %i: length %i, pointer %08X\n", c, DataTx, Address); + dma_bm_read(Address, &sd->sc->temp_buffer[sg_pos], DataTx, 2); + } + + sg_pos += scb->sge.sys_buf_byte_count; + buflen -= scb->sge.sys_buf_byte_count; + + if (buflen < 0) + buflen = 0; + } + } + } else { + spock_log("Normal Transfer\n"); + if (sd->phase == SCSI_PHASE_DATA_IN) { + dma_bm_write(scsi->data_ptr, sd->sc->temp_buffer, MIN(sd->buffer_length, (int) scsi->data_len), 2); + } else if (sd->phase == SCSI_PHASE_DATA_OUT) + dma_bm_read(scsi->data_ptr, sd->sc->temp_buffer, MIN(sd->buffer_length, (int) scsi->data_len), 2); + } + + scsi_device_command_phase1(sd); + } + scsi->last_status = sd->status; + scsi->scsi_state = SCSI_STATE_END_PHASE; + break; + + case SCSI_STATE_END_PHASE: + scsi->scsi_state = SCSI_STATE_IDLE; + + spock_log("State to idle, cmd timer %d\n", scsi->cmd_timer); + if (!scsi->cmd_timer) + scsi->cmd_timer = 1; + + spock_add_to_period(scsi, 1); + break; + } } static void spock_callback(void *priv) { - double period; - spock_t *scsi = (spock_t *)priv; - scb_t *scb = &scsi->scb; + double period; + spock_t *scsi = (spock_t *) priv; + scb_t *scb = &scsi->scb; - scsi->temp_period = 0; - scsi->media_period = 0.0; + scsi->temp_period = 0; + scsi->media_period = 0.0; - if (scsi->cmd_timer) { - scsi->cmd_timer--; - if (!scsi->cmd_timer) { - spock_execute_cmd(scsi, scb); - } - } + if (scsi->cmd_timer) { + scsi->cmd_timer--; + if (!scsi->cmd_timer) { + spock_execute_cmd(scsi, scb); + } + } - if (scsi->attention_wait && - (scsi->scb_state == 0 || (scsi->attention_pending & 0xf0) == 0xe0)) { - scsi->attention_wait--; - if (!scsi->attention_wait) { - scsi->attention = scsi->attention_pending; - scsi->status &= ~STATUS_BUSY; - scsi->cir[0] = scsi->cir_pending[0]; - scsi->cir[1] = scsi->cir_pending[1]; - scsi->cir[2] = scsi->cir_pending[2]; - scsi->cir[3] = scsi->cir_pending[3]; - scsi->cir_status = 0; - - switch (scsi->attention >> 4) { - case 1: /*Immediate command*/ - scsi->cmd_status = 0x0a; - scsi->command = scsi->cir[0] | (scsi->cir[1] << 8) | (scsi->cir[2] << 16) | (scsi->cir[3] << 24); - switch (scsi->command & CMD_MASK) { - case CMD_ASSIGN: - case CMD_DMA_PACING_CONTROL: - case CMD_FEATURE_CONTROL: - case CMD_INVALID_412: - case CMD_RESET: - spock_process_imm_cmd(scsi); - break; - } - break; - - case 3: case 4: case 0x0f: /*Start SCB*/ - scsi->cmd_status = 1; - scsi->scb_addr = scsi->cir[0] | (scsi->cir[1] << 8) | (scsi->cir[2] << 16) | (scsi->cir[3] << 24); - scsi->scb_id = scsi->attention & 0x0f; - scsi->cmd_timer = SPOCK_TIME * 2; - spock_log("Start SCB at ID = %d\n", scsi->scb_id); - scsi->scb_state = 1; - break; - - case 5: /*Invalid*/ - case 0x0a: /*Invalid*/ - scsi->in_invalid = 1; - scsi->cmd_timer = SPOCK_TIME * 2; - break; + if (scsi->attention_wait && (scsi->scb_state == 0 || (scsi->attention_pending & 0xf0) == 0xe0)) { + scsi->attention_wait--; + if (!scsi->attention_wait) { + scsi->attention = scsi->attention_pending; + scsi->status &= ~STATUS_BUSY; + scsi->cir[0] = scsi->cir_pending[0]; + scsi->cir[1] = scsi->cir_pending[1]; + scsi->cir[2] = scsi->cir_pending[2]; + scsi->cir[3] = scsi->cir_pending[3]; + scsi->cir_status = 0; - case 0x0e: /*EOI*/ - scsi->irq_status = 0; - spock_clear_irq(scsi, scsi->attention & 0xf); - break; - } - } - } + spock_log("SCSI attention = %02x.\n", scsi->attention_pending); + switch (scsi->attention >> 4) { + case 1: /*Immediate command*/ + scsi->cmd_status = 0x0a; + scsi->command = scsi->cir[0] | (scsi->cir[1] << 8) | (scsi->cir[2] << 16) | (scsi->cir[3] << 24); + switch (scsi->command & CMD_MASK) { + case CMD_ASSIGN: + case CMD_DMA_PACING_CONTROL: + case CMD_FEATURE_CONTROL: + case CMD_INVALID_412: + case CMD_RESET: + spock_process_imm_cmd(scsi); + break; - spock_process_scsi(scsi, scb); - - period = 0.2 * ((double) scsi->temp_period); - timer_on(&scsi->callback_timer, (scsi->media_period + period + 10.0), 0); - spock_log("Temporary period: %lf us (%" PRIi64 " periods)\n", scsi->callback_timer.period, scsi->temp_period); + default: + break; + } + break; + + case 3: + case 4: + case 0x0f: /*Start SCB*/ + scsi->cmd_status = 1; + scsi->scb_addr = scsi->cir[0] | (scsi->cir[1] << 8) | (scsi->cir[2] << 16) | (scsi->cir[3] << 24); + scsi->scb_id = scsi->attention & 0x0f; + scsi->cmd_timer = SPOCK_TIME * 2; + spock_log("Start SCB at ID = %d, attention = %02x\n", scsi->scb_id, scsi->attention >> 4); + scsi->scb_state = 1; + break; + + case 5: /*Invalid*/ + case 0x0a: /*Invalid*/ + scsi->in_invalid = 1; + scsi->cmd_timer = SPOCK_TIME * 2; + break; + + case 0x0e: /*EOI*/ + scsi->irq_status = 0; + spock_clear_irq(scsi, scsi->attention & 0x0f); + break; + + default: + break; + } + } + } + + spock_process_scsi(scsi, scb); + + period = 0.2 * ((double) scsi->temp_period); + timer_on_auto(&scsi->callback_timer, (scsi->media_period + period + 10.0)); + spock_log("Temporary period: %lf us (%" PRIi64 " periods), media period = %lf\n", scsi->callback_timer.period, scsi->temp_period, scsi->media_period); } -static void +static void spock_mca_write(int port, uint8_t val, void *priv) { - spock_t *scsi = (spock_t *)priv; + spock_t *scsi = (spock_t *) priv; - if (port < 0x102) - return; + if (port < 0x102) + return; - io_removehandler((((scsi->pos_regs[2] >> 1) & 7) * 8) + 0x3540, 0x0008, spock_read, spock_readw, NULL, spock_write, spock_writew, NULL, scsi); - mem_mapping_disable(&scsi->bios_rom.mapping); - - scsi->pos_regs[port & 7] = val; + io_removehandler((((scsi->pos_regs[2] >> 1) & 7) * 8) + 0x3540, 0x0008, spock_read, spock_readw, NULL, spock_write, spock_writew, NULL, scsi); + mem_mapping_disable(&scsi->bios_rom.mapping); - scsi->adapter_id = (scsi->pos_regs[3] & 0xe0) >> 5; + scsi->pos_regs[port & 7] = val; - if (scsi->pos_regs[2] & 1) { - io_sethandler((((scsi->pos_regs[2] >> 1) & 7) * 8) + 0x3540, 0x0008, spock_read, spock_readw, NULL, spock_write, spock_writew, NULL, scsi); - if ((scsi->pos_regs[2] >> 4) == 0x0f) - mem_mapping_disable(&scsi->bios_rom.mapping); - else { - mem_mapping_set_addr(&scsi->bios_rom.mapping, ((scsi->pos_regs[2] >> 4) * 0x2000) + 0xc0000, 0x8000); - } + scsi->adapter_id = (scsi->pos_regs[3] & 0xe0) >> 5; + + if (scsi->pos_regs[2] & 1) { + io_sethandler((((scsi->pos_regs[2] >> 1) & 7) * 8) + 0x3540, 0x0008, spock_read, spock_readw, NULL, spock_write, spock_writew, NULL, scsi); + if ((scsi->pos_regs[2] & 0xf0) != 0xf0) { + mem_mapping_set_addr(&scsi->bios_rom.mapping, ((scsi->pos_regs[2] >> 4) * 0x2000) + 0xc0000, 0x8000); + mem_mapping_enable(&scsi->bios_rom.mapping); } + } + spock_log("[%04X:%08X]: POS Write Port = %x, val = %02x, rom addr = %05x\n", CS, cpu_state.pc, port & 7, val, ((scsi->pos_regs[2] >> 4) * 0x2000) + 0xc0000); } -static uint8_t +static uint8_t spock_mca_read(int port, void *priv) { - spock_t *scsi = (spock_t *)priv; + const spock_t *scsi = (spock_t *) priv; - return scsi->pos_regs[port & 7]; + spock_log("[%04X:%08X]: POS Read Port = %x, val = %02x\n", CS, cpu_state.pc, + port & 7, scsi->pos_regs[port & 7]); + return scsi->pos_regs[port & 7]; } static uint8_t spock_mca_feedb(void *priv) { - spock_t *scsi = (spock_t *)priv; + const spock_t *scsi = (spock_t *) priv; - return (scsi->pos_regs[2] & 0x01); + return (scsi->pos_regs[2] & 0x01); } static void spock_mca_reset(void *priv) { - spock_t *scsi = (spock_t *)priv; - int i; - - scsi->in_reset = 2; - scsi->cmd_timer = SPOCK_TIME * 50; - scsi->status = STATUS_BUSY; - scsi->scsi_state = SCSI_STATE_IDLE; - scsi->scb_state = 0; - scsi->in_invalid = 0; - scsi->attention_wait = 0; - scsi->basic_ctrl = 0; + spock_t *scsi = (spock_t *) priv; - /* Reset all devices on controller reset. */ - for (i = 0; i < 8; i++) - scsi_device_reset(&scsi_devices[scsi->bus][i]); - - scsi->adapter_reset = 0; + scsi->in_reset = 2; + scsi->cmd_timer = SPOCK_TIME * 50; + scsi->status = STATUS_BUSY; + scsi->scsi_state = SCSI_STATE_IDLE; + scsi->scb_state = 0; + scsi->in_invalid = 0; + scsi->attention_wait = 0; + scsi->basic_ctrl = 0; + + /* Reset all devices on controller reset. */ + for (uint8_t i = 0; i < 8; i++) { + scsi_device_reset(&scsi_devices[scsi->bus][i]); + scsi->present[i] = 0; + } + + spock_log("Reset.\n"); + mem_mapping_disable(&scsi->bios_rom.mapping); + spock_mca_write(0x102, 0, scsi); } static void * spock_init(const device_t *info) { - int c; - spock_t *scsi = malloc(sizeof(spock_t)); - memset(scsi, 0x00, sizeof(spock_t)); + spock_t *scsi = malloc(sizeof(spock_t)); + memset(scsi, 0x00, sizeof(spock_t)); - scsi->bus = scsi_get_bus(); + scsi->bus = scsi_get_bus(); - scsi->irq = 14; - - scsi->bios_ver = device_get_config_int("bios_ver"); - - switch (scsi->bios_ver) { - case 1: - rom_init_interleaved(&scsi->bios_rom, SPOCK_U68_1991_ROM, SPOCK_U69_1991_ROM, - 0xc8000, 0x8000, 0x7fff, 0x4000, MEM_MAPPING_EXTERNAL); - break; - case 0: - rom_init_interleaved(&scsi->bios_rom, SPOCK_U68_1990_ROM, SPOCK_U69_1990_ROM, - 0xc8000, 0x8000, 0x7fff, 0x4000, MEM_MAPPING_EXTERNAL); - break; - } + scsi->irq = 14; - mem_mapping_disable(&scsi->bios_rom.mapping); + scsi->bios_ver = device_get_config_int("bios_ver"); + scsi->spock_16bit = info->local & 0xff; - scsi->pos_regs[0] = 0xff; - scsi->pos_regs[1] = 0x8e; - mca_add(spock_mca_read, spock_mca_write, spock_mca_feedb, spock_mca_reset, scsi); + switch (scsi->bios_ver) { + case 0: + rom_init_interleaved(&scsi->bios_rom, SPOCK_U68_1990_ROM, SPOCK_U69_1990_ROM, + 0xc8000, 0x8000, 0x7fff, 0x4000, MEM_MAPPING_EXTERNAL); + break; + case 1: + rom_init_interleaved(&scsi->bios_rom, SPOCK_U68_1991_ROM, SPOCK_U69_1991_ROM, + 0xc8000, 0x8000, 0x7fff, 0x4000, MEM_MAPPING_EXTERNAL); + break; - scsi->in_reset = 2; - scsi->cmd_timer = SPOCK_TIME * 50; - scsi->status = STATUS_BUSY; + default: + break; + } + mem_mapping_disable(&scsi->bios_rom.mapping); - for (c = 0; c < (SCSI_ID_MAX-1); c++) { - scsi->dev_id[c].phys_id = -1; - } - - scsi->dev_id[SCSI_ID_MAX-1].phys_id = scsi->adapter_id; + scsi->pos_regs[0] = scsi->spock_16bit ? 0xfe : 0xff; + scsi->pos_regs[1] = 0x8e; + mca_add(spock_mca_read, spock_mca_write, spock_mca_feedb, spock_mca_reset, scsi); - timer_add(&scsi->callback_timer, spock_callback, scsi, 1); - scsi->callback_timer.period = 10.0; - timer_set_delay_u64(&scsi->callback_timer, (uint64_t) (scsi->callback_timer.period * ((double) TIMER_USEC))); - - return scsi; + scsi->in_reset = 2; + scsi->cmd_timer = SPOCK_TIME * 50; + scsi->status = STATUS_BUSY; + + for (uint8_t c = 0; c < (SCSI_ID_MAX - 1); c++) + scsi->dev_id[c].phys_id = -1; + + scsi->dev_id[SCSI_ID_MAX - 1].phys_id = scsi->adapter_id; + + timer_add(&scsi->callback_timer, spock_callback, scsi, 1); + scsi->callback_timer.period = 10.0; + + timer_set_delay_u64(&scsi->callback_timer, + (uint64_t) (scsi->callback_timer.period * ((double) TIMER_USEC))); + + scsi_bus_set_speed(scsi->bus, 5000000.0); + + return scsi; } -static void -spock_close(void *p) +static void +spock_close(void *priv) { - spock_t *scsi = (spock_t *)p; - - if (scsi) { - free(scsi); - scsi = NULL; - } + spock_t *scsi = (spock_t *) priv; + + if (scsi) { + free(scsi); + scsi = NULL; + } } -static int +static int spock_available(void) { - return rom_present(SPOCK_U68_1991_ROM) && rom_present(SPOCK_U69_1991_ROM) && - rom_present(SPOCK_U68_1990_ROM) && rom_present(SPOCK_U69_1990_ROM); + return rom_present(SPOCK_U68_1991_ROM) && rom_present(SPOCK_U69_1991_ROM) && rom_present(SPOCK_U68_1990_ROM) && rom_present(SPOCK_U69_1990_ROM); } static const device_config_t spock_rom_config[] = { - { - "bios_ver", "BIOS Version", CONFIG_SELECTION, "", 1, "", { 0 }, - { - { - "1991 BIOS (>1GB)", 1 - }, - { - "1990 BIOS", 0 - }, - { - "" - } - }, + // clang-format off + { + .name = "bios_ver", + .description = "BIOS Version", + .type = CONFIG_SELECTION, + .default_string = "", + .default_int = 1, + .file_filter = "", + .spinner = { 0 }, + .selection = { + { .description = "1991 BIOS (>1GB)", .value = 1 }, + { .description = "1990 BIOS", .value = 0 }, + { .description = "" } }, - { - "", "", -1 - } + }, + { .name = "", .description = "", .type = CONFIG_END } + // clang-format on }; -const device_t spock_device = -{ - "IBM PS/2 SCSI Adapter (Spock)", - "spock", - DEVICE_MCA, - 0, - spock_init, spock_close, NULL, - { spock_available }, - NULL, NULL, - spock_rom_config +const device_t spock_device = { + .name = "IBM PS/2 SCSI Adapter (Spock)", + .internal_name = "spock", + .flags = DEVICE_MCA, + .local = 0, + .init = spock_init, + .close = spock_close, + .reset = NULL, + { .available = spock_available }, + .speed_changed = NULL, + .force_redraw = NULL, + .config = spock_rom_config +}; + +const device_t tribble_device = { + .name = "IBM PS/2 SCSI Adapter (Tribble)", + .internal_name = "tribble", + .flags = DEVICE_MCA, + .local = 1, + .init = spock_init, + .close = spock_close, + .reset = NULL, + { .available = spock_available }, + .speed_changed = NULL, + .force_redraw = NULL, + .config = spock_rom_config }; diff --git a/src/scsi/scsi_x54x.c b/src/scsi/scsi_x54x.c index c8dd945f5..6876e4385 100644 --- a/src/scsi/scsi_x54x.c +++ b/src/scsi/scsi_x54x.c @@ -1,24 +1,24 @@ /* - * 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. + * 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. + * This file is part of the 86Box distribution. * - * Implementation of the code common to the AHA-154x series of - * SCSI Host Adapters made by Adaptec, Inc. and the BusLogic - * series of SCSI Host Adapters made by Mylex. - * These controllers were designed for various buses. + * Implementation of the code common to the AHA-154x series of + * SCSI Host Adapters made by Adaptec, Inc. and the BusLogic + * series of SCSI Host Adapters made by Mylex. + * These controllers were designed for various buses. * * * - * Authors: TheCollector1995, - * Miran Grca, - * Fred N. van Kempen, + * Authors: TheCollector1995, + * Miran Grca, + * Fred N. van Kempen, * - * Copyright 2016-2018 Miran Grca. - * Copyright 2017,2018 Fred N. van Kempen. + * Copyright 2016-2018 Miran Grca. + * Copyright 2017-2018 Fred N. van Kempen. */ #include #include @@ -47,33 +47,28 @@ #include <86box/scsi_aha154x.h> #include <86box/scsi_x54x.h> +#define X54X_RESET_DURATION_US UINT64_C(50000) -#define X54X_RESET_DURATION_US UINT64_C(50000) - - -static void x54x_cmd_callback(void *priv); - +static void x54x_cmd_callback(void *priv); #ifdef ENABLE_X54X_LOG int x54x_do_log = ENABLE_X54X_LOG; - static void x54x_log(const char *fmt, ...) { va_list ap; if (x54x_do_log) { - va_start(ap, fmt); - pclog_ex(fmt, ap); - va_end(ap); + va_start(ap, fmt); + pclog_ex(fmt, ap); + va_end(ap); } } #else -#define x54x_log(fmt, ...) +# define x54x_log(fmt, ...) #endif - static void x54x_irq(x54x_t *dev, int set) { @@ -81,178 +76,180 @@ x54x_irq(x54x_t *dev, int set) int irq; if (dev->ven_get_irq) - irq = dev->ven_get_irq(dev); - else - irq = dev->Irq; + irq = dev->ven_get_irq(dev); + else + irq = dev->Irq; if (dev->card_bus & DEVICE_PCI) { - x54x_log("PCI IRQ: %02X, PCI_INTA\n", dev->pci_slot); + x54x_log("PCI IRQ: %02X, PCI_INTA\n", dev->pci_slot); if (set) - pci_set_irq(dev->pci_slot, PCI_INTA); - else - pci_clear_irq(dev->pci_slot, PCI_INTA); + pci_set_irq(dev->pci_slot, PCI_INTA, &dev->irq_state); + else + pci_clear_irq(dev->pci_slot, PCI_INTA, &dev->irq_state); } else { - x54x_log("%sing IRQ %i\n", set ? "Rais" : "Lower", irq); + x54x_log("%sing IRQ %i\n", set ? "Rais" : "Lower", irq); - if (set) { - if (dev->interrupt_type) - int_type = dev->interrupt_type(dev); + if (dev->interrupt_type) + int_type = dev->interrupt_type(dev); - if (int_type) - picintlevel(1 << irq); - else - picint(1 << irq); - } else - picintc(1 << irq); + if (set) { + if (int_type) + picintlevel(1 << irq, &dev->irq_state); + else + picint(1 << irq); + } else { + if (int_type) + picintclevel(1 << irq, &dev->irq_state); + else + picintc(1 << irq); + } } } - static void raise_irq(x54x_t *dev, int suppress, uint8_t Interrupt) { if (Interrupt & (INTR_MBIF | INTR_MBOA)) { - x54x_log("%s: RaiseInterrupt(): Interrupt=%02X %s\n", - dev->name, Interrupt, (! (dev->Interrupt & INTR_HACC)) ? "Immediate" : "Pending"); - if (! (dev->Interrupt & INTR_HACC)) { - dev->Interrupt |= Interrupt; /* Report now. */ - } else { - dev->PendingInterrupt |= Interrupt; /* Report later. */ - } + x54x_log("%s: RaiseInterrupt(): Interrupt=%02X %s\n", + dev->name, Interrupt, (!(dev->Interrupt & INTR_HACC)) ? "Immediate" : "Pending"); + if (!(dev->Interrupt & INTR_HACC)) { + dev->Interrupt |= Interrupt; /* Report now. */ + } else { + dev->PendingInterrupt |= Interrupt; /* Report later. */ + } } else if (Interrupt & INTR_HACC) { - if (dev->Interrupt == 0 || dev->Interrupt == (INTR_ANY | INTR_HACC)) { - x54x_log("%s: RaiseInterrupt(): Interrupt=%02X\n", - dev->name, dev->Interrupt); - } - dev->Interrupt |= Interrupt; + if (dev->Interrupt == 0 || dev->Interrupt == (INTR_ANY | INTR_HACC)) { + x54x_log("%s: RaiseInterrupt(): Interrupt=%02X\n", + dev->name, dev->Interrupt); + } + dev->Interrupt |= Interrupt; } else { - x54x_log("%s: RaiseInterrupt(): Invalid interrupt state!\n", dev->name); + x54x_log("%s: RaiseInterrupt(): Invalid interrupt state!\n", dev->name); } dev->Interrupt |= INTR_ANY; if (dev->IrqEnabled && !suppress) - x54x_irq(dev, 1); + x54x_irq(dev, 1); } - static void clear_irq(x54x_t *dev) { dev->Interrupt = 0; x54x_log("%s: lowering IRQ %i (stat 0x%02x)\n", - dev->name, dev->Irq, dev->Interrupt); + dev->name, dev->Irq, dev->Interrupt); x54x_irq(dev, 0); if (dev->PendingInterrupt) { - x54x_log("%s: Raising Interrupt 0x%02X (Pending)\n", - dev->name, dev->Interrupt); - if (dev->MailboxOutInterrupts || !(dev->Interrupt & INTR_MBOA)) { - raise_irq(dev, 0, dev->PendingInterrupt); - } - dev->PendingInterrupt = 0; + x54x_log("%s: Raising Interrupt 0x%02X (Pending)\n", + dev->name, dev->Interrupt); + if (dev->MailboxOutInterrupts || !(dev->Interrupt & INTR_MBOA)) { + raise_irq(dev, 0, dev->PendingInterrupt); + } + dev->PendingInterrupt = 0; } } - static void target_check(x54x_t *dev, uint8_t id) { - if (! scsi_device_valid(&scsi_devices[dev->bus][id])) - fatal("BIOS INT13 device on ID %02i has disappeared\n", id); + if (!scsi_device_valid(&scsi_devices[dev->bus][id])) + fatal("BIOS INT13 device on ID %02i has disappeared\n", id); } - static uint8_t completion_code(uint8_t *sense) { uint8_t ret = 0xff; switch (sense[12]) { - case ASC_NONE: - ret = 0x00; - break; + case ASC_NONE: + ret = 0x00; + break; - case ASC_ILLEGAL_OPCODE: - case ASC_INV_FIELD_IN_CMD_PACKET: - case ASC_INV_FIELD_IN_PARAMETER_LIST: - case ASC_DATA_PHASE_ERROR: - ret = 0x01; - break; + case ASC_ILLEGAL_OPCODE: + case ASC_INV_FIELD_IN_CMD_PACKET: + case ASC_INV_FIELD_IN_PARAMETER_LIST: + case ASC_DATA_PHASE_ERROR: + ret = 0x01; + break; - case 0x12: - case ASC_LBA_OUT_OF_RANGE: - ret = 0x02; - break; + case 0x12: + case ASC_LBA_OUT_OF_RANGE: + ret = 0x02; + break; - case ASC_WRITE_PROTECTED: - ret = 0x03; - break; + case ASC_WRITE_PROTECTED: + ret = 0x03; + break; - case 0x14: - case 0x16: - ret = 0x04; - break; + case 0x14: + case 0x16: + ret = 0x04; + break; - case ASC_INCOMPATIBLE_FORMAT: - case ASC_ILLEGAL_MODE_FOR_THIS_TRACK: - ret = 0x0c; - break; + case ASC_INCOMPATIBLE_FORMAT: + case ASC_ILLEGAL_MODE_FOR_THIS_TRACK: + ret = 0x0c; + break; - case 0x10: - case 0x11: - ret = 0x10; - break; + case 0x10: + case 0x11: + ret = 0x10; + break; - case 0x17: - case 0x18: - ret = 0x11; - break; + case 0x17: + case 0x18: + ret = 0x11; + break; - case 0x01: - case 0x03: - case 0x05: - case 0x06: - case 0x07: - case 0x08: - case 0x09: - case 0x1B: - case 0x1C: - case 0x1D: - case 0x40: - case 0x41: - case 0x42: - case 0x43: - case 0x44: - case 0x45: - case 0x46: - case 0x47: - case 0x48: - case 0x49: - ret = 0x20; - break; + case 0x01: + case 0x03: + case 0x05: + case 0x06: + case 0x07: + case 0x08: + case 0x09: + case 0x1B: + case 0x1C: + case 0x1D: + case 0x40: + case 0x41: + case 0x42: + case 0x43: + case 0x44: + case 0x45: + case 0x46: + case 0x47: + case 0x48: + case 0x49: + ret = 0x20; + break; - case 0x15: - case 0x02: - ret = 0x40; - break; + case 0x15: + case 0x02: + ret = 0x40; + break; - case 0x25: - ret = 0x80; - break; + case 0x25: + ret = 0x80; + break; - case ASC_NOT_READY: - case ASC_MEDIUM_MAY_HAVE_CHANGED: - case 0x29: - case ASC_CAPACITY_DATA_CHANGED: - case ASC_MEDIUM_NOT_PRESENT: - ret = 0xaa; - break; - }; + case ASC_NOT_READY: + case ASC_MEDIUM_MAY_HAVE_CHANGED: + case 0x29: + case ASC_CAPACITY_DATA_CHANGED: + case ASC_MEDIUM_NOT_PRESENT: + ret = 0xaa; + break; - return(ret); + default: + break; + } + + return ret; } - static uint8_t x54x_bios_scsi_command(scsi_device_t *dev, uint8_t *cdb, uint8_t *buf, int len, uint32_t addr, int transfer_size) { @@ -261,25 +258,25 @@ x54x_bios_scsi_command(scsi_device_t *dev, uint8_t *cdb, uint8_t *buf, int len, scsi_device_command_phase0(dev, cdb); if (dev->phase == SCSI_PHASE_STATUS) - return(completion_code(scsi_device_sense(dev))); + return (completion_code(scsi_device_sense(dev))); if (len > 0) { - if (dev->buffer_length == -1) { - fatal("Buffer length -1 when doing SCSI DMA\n"); - return(0xff); - } + if (dev->buffer_length == -1) { + fatal("Buffer length -1 when doing SCSI DMA\n"); + return 0xff; + } - if (dev->phase == SCSI_PHASE_DATA_IN) { - if (buf) - memcpy(buf, dev->sc->temp_buffer, dev->buffer_length); - else - dma_bm_write(addr, dev->sc->temp_buffer, dev->buffer_length, transfer_size); - } else if (dev->phase == SCSI_PHASE_DATA_OUT) { - if (buf) - memcpy(dev->sc->temp_buffer, buf, dev->buffer_length); - else - dma_bm_read(addr, dev->sc->temp_buffer, dev->buffer_length, transfer_size); - } + if (dev->phase == SCSI_PHASE_DATA_IN) { + if (buf) + memcpy(buf, dev->sc->temp_buffer, dev->buffer_length); + else + dma_bm_write(addr, dev->sc->temp_buffer, dev->buffer_length, transfer_size); + } else if (dev->phase == SCSI_PHASE_DATA_OUT) { + if (buf) + memcpy(dev->sc->temp_buffer, buf, dev->buffer_length); + else + dma_bm_read(addr, dev->sc->temp_buffer, dev->buffer_length, transfer_size); + } } scsi_device_command_phase1(dev); @@ -287,12 +284,11 @@ x54x_bios_scsi_command(scsi_device_t *dev, uint8_t *cdb, uint8_t *buf, int len, return (completion_code(scsi_device_sense(dev))); } - static uint8_t x54x_bios_read_capacity(scsi_device_t *sd, uint8_t *buf, int transfer_size) { uint8_t *cdb; - uint8_t ret; + uint8_t ret; cdb = (uint8_t *) malloc(12); memset(cdb, 0, 12); @@ -303,15 +299,14 @@ x54x_bios_read_capacity(scsi_device_t *sd, uint8_t *buf, int transfer_size) free(cdb); - return(ret); + return ret; } - static uint8_t x54x_bios_inquiry(scsi_device_t *sd, uint8_t *buf, int transfer_size) { uint8_t *cdb; - uint8_t ret; + uint8_t ret; cdb = (uint8_t *) malloc(12); memset(cdb, 0, 12); @@ -323,234 +318,232 @@ x54x_bios_inquiry(scsi_device_t *sd, uint8_t *buf, int transfer_size) free(cdb); - return(ret); + return ret; } - static uint8_t x54x_bios_command_08(scsi_device_t *sd, uint8_t *buffer, int transfer_size) { uint8_t *rcbuf; - uint8_t ret; - int i; + uint8_t ret; + int i; memset(buffer, 0x00, 6); rcbuf = (uint8_t *) malloc(8); - ret = x54x_bios_read_capacity(sd, rcbuf, transfer_size); + ret = x54x_bios_read_capacity(sd, rcbuf, transfer_size); if (ret) { - free(rcbuf); - return(ret); - } + free(rcbuf); + return ret; + } memset(buffer, 0x00, 6); - for (i=0; i<4; i++) - buffer[i] = rcbuf[i]; - for (i=4; i<6; i++) - buffer[i] = rcbuf[(i + 2) ^ 1]; + for (i = 0; i < 4; i++) + buffer[i] = rcbuf[i]; + for (i = 4; i < 6; i++) + buffer[i] = rcbuf[(i + 2) ^ 1]; x54x_log("BIOS Command 0x08: %02X %02X %02X %02X %02X %02X\n", - buffer[0], buffer[1], buffer[2], buffer[3], buffer[4], buffer[5]); + buffer[0], buffer[1], buffer[2], buffer[3], buffer[4], buffer[5]); free(rcbuf); - return(0); + return 0; } - static int x54x_bios_command_15(scsi_device_t *sd, uint8_t *buffer, int transfer_size) { - uint8_t *inqbuf, *rcbuf; - uint8_t ret; - int i; + uint8_t *inqbuf; + uint8_t *rcbuf; + uint8_t ret; memset(buffer, 0x00, 6); inqbuf = (uint8_t *) malloc(36); - ret = x54x_bios_inquiry(sd, inqbuf, transfer_size); + ret = x54x_bios_inquiry(sd, inqbuf, transfer_size); if (ret) { - free(inqbuf); - return(ret); + free(inqbuf); + return ret; } buffer[4] = inqbuf[0]; buffer[5] = inqbuf[1]; rcbuf = (uint8_t *) malloc(8); - ret = x54x_bios_read_capacity(sd, rcbuf, transfer_size); + ret = x54x_bios_read_capacity(sd, rcbuf, transfer_size); if (ret) { - free(rcbuf); - free(inqbuf); - return(ret); - } + free(rcbuf); + free(inqbuf); + return ret; + } - for (i = 0; i < 4; i++) - buffer[i] = rcbuf[i]; + for (uint8_t i = 0; i < 4; i++) + buffer[i] = rcbuf[i]; x54x_log("BIOS Command 0x15: %02X %02X %02X %02X %02X %02X\n", - buffer[0], buffer[1], buffer[2], buffer[3], buffer[4], buffer[5]); + buffer[0], buffer[1], buffer[2], buffer[3], buffer[4], buffer[5]); free(rcbuf); free(inqbuf); - return(0); + return 0; } - /* This returns the completion code. */ static uint8_t x54x_bios_command(x54x_t *x54x, uint8_t max_id, BIOSCMD *cmd, int8_t islba) { - const int bios_cmd_to_scsi[18] = { 0, 0, GPCMD_READ_10, GPCMD_WRITE_10, GPCMD_VERIFY_10, 0, 0, - GPCMD_FORMAT_UNIT, 0, 0, 0, 0, GPCMD_SEEK_10, 0, 0, 0, - GPCMD_TEST_UNIT_READY, GPCMD_REZERO_UNIT }; - uint8_t cdb[12] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }; - uint8_t *buf; - scsi_device_t *dev = NULL; - uint32_t dma_address = 0; - uint32_t lba; - int sector_len = cmd->secount; - uint8_t ret = 0x00; + const int bios_cmd_to_scsi[18] = { 0, 0, GPCMD_READ_10, GPCMD_WRITE_10, GPCMD_VERIFY_10, 0, 0, + GPCMD_FORMAT_UNIT, 0, 0, 0, 0, GPCMD_SEEK_10, 0, 0, 0, + GPCMD_TEST_UNIT_READY, GPCMD_REZERO_UNIT }; + uint8_t cdb[12] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }; + uint8_t *buf; + scsi_device_t *dev = NULL; + uint32_t dma_address = 0; + uint32_t lba; + int sector_len = cmd->secount; + uint8_t ret = 0x00; if (islba) - lba = lba32_blk(cmd); - else - lba = (cmd->u.chs.cyl << 9) + (cmd->u.chs.head << 5) + cmd->u.chs.sec; + lba = lba32_blk(cmd); + else + lba = (cmd->u.chs.cyl << 9) + (cmd->u.chs.head << 5) + cmd->u.chs.sec; x54x_log("BIOS Command = 0x%02X\n", cmd->command); if (cmd->id > max_id) { - x54x_log("BIOS Target ID %i or LUN %i are above maximum\n", - cmd->id, cmd->lun); - ret = 0x80; + x54x_log("BIOS Target ID %i or LUN %i are above maximum\n", + cmd->id, cmd->lun); + ret = 0x80; } if (cmd->lun) { - x54x_log("BIOS Target LUN is not 0\n"); - ret = 0x80; + x54x_log("BIOS Target LUN is not 0\n"); + ret = 0x80; } if (!ret) { - /* Get pointer to selected device. */ - dev = &scsi_devices[x54x->bus][cmd->id]; - dev->buffer_length = 0; + /* Get pointer to selected device. */ + dev = &scsi_devices[x54x->bus][cmd->id]; + dev->buffer_length = 0; - if (! scsi_device_present(dev)) { - x54x_log("BIOS Target ID %i has no device attached\n", cmd->id); - ret = 0x80; - } else { - scsi_device_identify(dev, 0xff); + if (!scsi_device_present(dev)) { + x54x_log("BIOS Target ID %i has no device attached\n", cmd->id); + ret = 0x80; + } else { + scsi_device_identify(dev, 0xff); - if ((dev->type == SCSI_REMOVABLE_CDROM) && !(x54x->flags & X54X_CDROM_BOOT)) { - x54x_log("BIOS Target ID %i is CD-ROM on unsupported BIOS\n", cmd->id); - return(0x80); - } else { - dma_address = ADDR_TO_U32(cmd->dma_address); + if ((dev->type == SCSI_REMOVABLE_CDROM) && !(x54x->flags & X54X_CDROM_BOOT)) { + x54x_log("BIOS Target ID %i is CD-ROM on unsupported BIOS\n", cmd->id); + return 0x80; + } else { + dma_address = ADDR_TO_U32(cmd->dma_address); - x54x_log("BIOS Data Buffer write: length %d, pointer 0x%04X\n", - sector_len, dma_address); - } - } + x54x_log("BIOS Data Buffer write: length %d, pointer 0x%04X\n", + sector_len, dma_address); + } + } } - if (!ret) switch(cmd->command) { - case 0x00: /* Reset Disk System, in practice it's a nop */ - ret = 0x00; - break; + if (!ret) + switch (cmd->command) { + case 0x00: /* Reset Disk System, in practice it's a nop */ + ret = 0x00; + break; - case 0x01: /* Read Status of Last Operation */ - target_check(x54x, cmd->id); + case 0x01: /* Read Status of Last Operation */ + target_check(x54x, cmd->id); - /* - * Assuming 14 bytes because that is the default - * length for SCSI sense, and no command-specific - * indication is given. - */ - if (sector_len > 0) { - x54x_log("BIOS DMA: Reading 14 bytes at %08X\n", - dma_address); - dma_bm_write(dma_address, scsi_device_sense(dev), 14, x54x->transfer_size); - } + /* + * Assuming 14 bytes because that is the default + * length for SCSI sense, and no command-specific + * indication is given. + */ + if (sector_len > 0) { + x54x_log("BIOS DMA: Reading 14 bytes at %08X\n", + dma_address); + dma_bm_write(dma_address, scsi_device_sense(dev), 14, x54x->transfer_size); + } - return(0); - break; + return 0; + break; - case 0x02: /* Read Desired Sectors to Memory */ - case 0x03: /* Write Desired Sectors from Memory */ - case 0x04: /* Verify Desired Sectors */ - case 0x0c: /* Seek */ - target_check(x54x, cmd->id); + case 0x02: /* Read Desired Sectors to Memory */ + case 0x03: /* Write Desired Sectors from Memory */ + case 0x04: /* Verify Desired Sectors */ + case 0x0c: /* Seek */ + target_check(x54x, cmd->id); - cdb[0] = bios_cmd_to_scsi[cmd->command]; - cdb[1] = (cmd->lun & 7) << 5; - cdb[2] = (lba >> 24) & 0xff; - cdb[3] = (lba >> 16) & 0xff; - cdb[4] = (lba >> 8) & 0xff; - cdb[5] = lba & 0xff; - if (cmd->command != 0x0c) - cdb[8] = sector_len; + cdb[0] = bios_cmd_to_scsi[cmd->command]; + cdb[1] = (cmd->lun & 7) << 5; + cdb[2] = (lba >> 24) & 0xff; + cdb[3] = (lba >> 16) & 0xff; + cdb[4] = (lba >> 8) & 0xff; + cdb[5] = lba & 0xff; + if (cmd->command != 0x0c) + cdb[8] = sector_len; - ret = x54x_bios_scsi_command(dev, cdb, NULL, sector_len, dma_address, x54x->transfer_size); - if (cmd->command == 0x0c) - ret = !!ret; - break; + ret = x54x_bios_scsi_command(dev, cdb, NULL, sector_len, dma_address, x54x->transfer_size); + if (cmd->command == 0x0c) + ret = !!ret; + break; - default: - x54x_log("BIOS: Unimplemented command: %02X\n", cmd->command); - case 0x05: /* Format Track, invalid since SCSI has no tracks */ - case 0x0a: /* ???? */ - case 0x0b: /* ???? */ - case 0x12: /* ???? */ - case 0x13: /* ???? */ -//FIXME: add a longer delay here --FvK - ret = 0x01; - break; + default: + x54x_log("BIOS: Unimplemented command: %02X\n", cmd->command); + fallthrough; + case 0x05: /* Format Track, invalid since SCSI has no tracks */ + case 0x0a: /* ???? */ + case 0x0b: /* ???? */ + case 0x12: /* ???? */ + case 0x13: /* ???? */ + // FIXME: add a longer delay here --FvK + ret = 0x01; + break; - case 0x06: /* Identify SCSI Devices, in practice it's a nop */ - case 0x09: /* Initialize Drive Pair Characteristics, in practice it's a nop */ - case 0x0d: /* Alternate Disk Reset, in practice it's a nop */ - case 0x0e: /* Read Sector Buffer */ - case 0x0f: /* Write Sector Buffer */ - case 0x14: /* Controller Diagnostic */ -//FIXME: add a longer delay here --FvK - ret = 0x00; - break; + case 0x06: /* Identify SCSI Devices, in practice it's a nop */ + case 0x09: /* Initialize Drive Pair Characteristics, in practice it's a nop */ + case 0x0d: /* Alternate Disk Reset, in practice it's a nop */ + case 0x0e: /* Read Sector Buffer */ + case 0x0f: /* Write Sector Buffer */ + case 0x14: /* Controller Diagnostic */ + // FIXME: add a longer delay here --FvK + ret = 0x00; + break; - case 0x07: /* Format Unit */ - case 0x10: /* Test Drive Ready */ - case 0x11: /* Recalibrate */ - target_check(x54x, cmd->id); + case 0x07: /* Format Unit */ + case 0x10: /* Test Drive Ready */ + case 0x11: /* Recalibrate */ + target_check(x54x, cmd->id); - cdb[0] = bios_cmd_to_scsi[cmd->command]; - cdb[1] = (cmd->lun & 7) << 5; + cdb[0] = bios_cmd_to_scsi[cmd->command]; + cdb[1] = (cmd->lun & 7) << 5; - ret = x54x_bios_scsi_command(dev, cdb, NULL, sector_len, dma_address, x54x->transfer_size); - break; + ret = x54x_bios_scsi_command(dev, cdb, NULL, sector_len, dma_address, x54x->transfer_size); + break; - case 0x08: /* Read Drive Parameters */ - case 0x15: /* Read DASD Type */ - target_check(x54x, cmd->id); + case 0x08: /* Read Drive Parameters */ + case 0x15: /* Read DASD Type */ + target_check(x54x, cmd->id); - dev->buffer_length = 6; + dev->buffer_length = 6; - buf = (uint8_t *) malloc(6); - if (cmd->command == 0x08) - ret = x54x_bios_command_08(dev, buf, x54x->transfer_size); - else - ret = x54x_bios_command_15(dev, buf, x54x->transfer_size); + buf = (uint8_t *) malloc(6); + if (cmd->command == 0x08) + ret = x54x_bios_command_08(dev, buf, x54x->transfer_size); + else + ret = x54x_bios_command_15(dev, buf, x54x->transfer_size); - x54x_log("BIOS DMA: Reading 6 bytes at %08X\n", dma_address); - dma_bm_write(dma_address, buf, 4, x54x->transfer_size); - free(buf); + x54x_log("BIOS DMA: Reading 6 bytes at %08X\n", dma_address); + dma_bm_write(dma_address, buf, 4, x54x->transfer_size); + free(buf); + + break; + } - break; - } - x54x_log("BIOS Request %02X complete: %02X\n", cmd->command, ret); - return(ret); + return ret; } - static void x54x_cmd_done(x54x_t *dev, int suppress) { @@ -560,49 +553,46 @@ x54x_cmd_done(x54x_t *dev, int suppress) dev->Status |= STAT_IDLE; if (dev->ven_cmd_is_fast) { - fast = dev->ven_cmd_is_fast(dev); + fast = dev->ven_cmd_is_fast(dev); } if ((dev->Command != CMD_START_SCSI) || fast) { - dev->Status &= ~STAT_DFULL; - x54x_log("%s: Raising IRQ %i\n", dev->name, dev->Irq); - raise_irq(dev, suppress, INTR_HACC); + dev->Status &= ~STAT_DFULL; + x54x_log("%s: Raising IRQ %i\n", dev->name, dev->Irq); + raise_irq(dev, suppress, INTR_HACC); } - dev->Command = 0xff; + dev->Command = 0xff; dev->CmdParam = 0; } - static void x54x_add_to_period(x54x_t *dev, int TransferLength) { dev->temp_period += (uint64_t) TransferLength; } - static void x54x_mbi_setup(x54x_t *dev, uint32_t CCBPointer, CCBU *CmdBlock, - uint8_t HostStatus, uint8_t TargetStatus, uint8_t mbcc) + uint8_t HostStatus, uint8_t TargetStatus, uint8_t mbcc) { Req_t *req = &dev->Req; req->CCBPointer = CCBPointer; memcpy(&(req->CmdBlock), CmdBlock, sizeof(CCB32)); - req->Is24bit = !!(dev->flags & X54X_MBX_24BIT); - req->HostStatus = HostStatus; - req->TargetStatus = TargetStatus; + req->Is24bit = !!(dev->flags & X54X_MBX_24BIT); + req->HostStatus = HostStatus; + req->TargetStatus = TargetStatus; req->MailboxCompletionCode = mbcc; x54x_log("Mailbox in setup\n"); } - static void x54x_ccb(x54x_t *dev) { - Req_t *req = &dev->Req; - uint8_t bytes[4] = { 0, 0, 0, 0}; + const Req_t *req = &dev->Req; + uint8_t bytes[4] = { 0, 0, 0, 0 }; /* Rewrite the CCB up to the CDB. */ x54x_log("CCB completion code and statuses rewritten (pointer %08X)\n", req->CCBPointer); @@ -614,341 +604,329 @@ x54x_ccb(x54x_t *dev) x54x_add_to_period(dev, 3); if (dev->MailboxOutInterrupts) - dev->ToRaise = INTR_MBOA | INTR_ANY; - else - dev->ToRaise = 0; + dev->ToRaise = INTR_MBOA | INTR_ANY; + else + dev->ToRaise = 0; } - static void x54x_mbi(x54x_t *dev) -{ +{ Req_t *req = &dev->Req; -// uint32_t CCBPointer = req->CCBPointer; - addr24 CCBPointer; - CCBU *CmdBlock = &(req->CmdBlock); - uint8_t HostStatus = req->HostStatus; - uint8_t TargetStatus = req->TargetStatus; - uint32_t MailboxCompletionCode = req->MailboxCompletionCode; - uint32_t Incoming; - uint8_t bytes[4] = { 0, 0, 0, 0 }; +#if 0 + uint32_t CCBPointer = req->CCBPointer; +#endif + addr24_t CCBPointer; + CCBU *CmdBlock = &(req->CmdBlock); + uint8_t HostStatus = req->HostStatus; + uint8_t TargetStatus = req->TargetStatus; + uint32_t MailboxCompletionCode = req->MailboxCompletionCode; + uint32_t Incoming; + uint8_t bytes[4] = { 0, 0, 0, 0 }; Incoming = dev->MailboxInAddr + (dev->MailboxInPosCur * ((dev->flags & X54X_MBX_24BIT) ? sizeof(Mailbox_t) : sizeof(Mailbox32_t))); if (MailboxCompletionCode != MBI_NOT_FOUND) { - CmdBlock->common.HostStatus = HostStatus; - CmdBlock->common.TargetStatus = TargetStatus; + CmdBlock->common.HostStatus = HostStatus; + CmdBlock->common.TargetStatus = TargetStatus; - /* Rewrite the CCB up to the CDB. */ - x54x_log("CCB statuses rewritten (pointer %08X)\n", req->CCBPointer); - dma_bm_read(req->CCBPointer + 0x000C, (uint8_t *) bytes, 4, dev->transfer_size); - bytes[2] = req->HostStatus; - bytes[3] = req->TargetStatus; - dma_bm_write(req->CCBPointer + 0x000C, (uint8_t *) bytes, 4, dev->transfer_size); - x54x_add_to_period(dev, 2); + /* Rewrite the CCB up to the CDB. */ + x54x_log("CCB statuses rewritten (pointer %08X)\n", req->CCBPointer); + dma_bm_read(req->CCBPointer + 0x000C, (uint8_t *) bytes, 4, dev->transfer_size); + bytes[2] = req->HostStatus; + bytes[3] = req->TargetStatus; + dma_bm_write(req->CCBPointer + 0x000C, (uint8_t *) bytes, 4, dev->transfer_size); + x54x_add_to_period(dev, 2); } else { - x54x_log("Mailbox not found!\n"); + x54x_log("Mailbox not found!\n"); } - x54x_log("Host Status 0x%02X, Target Status 0x%02X\n",HostStatus,TargetStatus); + x54x_log("Host Status 0x%02X, Target Status 0x%02X\n", HostStatus, TargetStatus); if (dev->flags & X54X_MBX_24BIT) { - U32_TO_ADDR(CCBPointer, req->CCBPointer); - x54x_log("Mailbox 24-bit: Status=0x%02X, CCB at 0x%04X\n", req->MailboxCompletionCode, CCBPointer); - bytes[0] = req->MailboxCompletionCode; - memcpy(&(bytes[1]), (uint8_t *)&CCBPointer, 3); - dma_bm_write(Incoming, (uint8_t *) bytes, 4, dev->transfer_size); - x54x_add_to_period(dev, 4); - x54x_log("%i bytes of 24-bit mailbox written to: %08X\n", sizeof(Mailbox_t), Incoming); + U32_TO_ADDR(CCBPointer, req->CCBPointer); + x54x_log("Mailbox 24-bit: Status=0x%02X, CCB at 0x%04X\n", req->MailboxCompletionCode, CCBPointer); + bytes[0] = req->MailboxCompletionCode; + memcpy(&(bytes[1]), (uint8_t *) &CCBPointer, 3); + dma_bm_write(Incoming, (uint8_t *) bytes, 4, dev->transfer_size); + x54x_add_to_period(dev, 4); + x54x_log("%i bytes of 24-bit mailbox written to: %08X\n", sizeof(Mailbox_t), Incoming); } else { - x54x_log("Mailbox 32-bit: Status=0x%02X, CCB at 0x%04X\n", req->MailboxCompletionCode, CCBPointer); - dma_bm_write(Incoming, (uint8_t *)&(req->CCBPointer), 4, dev->transfer_size); - dma_bm_read(Incoming + 4, (uint8_t *) bytes, 4, dev->transfer_size); - bytes[0] = req->HostStatus; - bytes[1] = req->TargetStatus; - bytes[3] = req->MailboxCompletionCode; - dma_bm_write(Incoming + 4, (uint8_t *) bytes, 4, dev->transfer_size); - x54x_add_to_period(dev, 7); - x54x_log("%i bytes of 32-bit mailbox written to: %08X\n", sizeof(Mailbox32_t), Incoming); + x54x_log("Mailbox 32-bit: Status=0x%02X, CCB at 0x%04X\n", req->MailboxCompletionCode, CCBPointer); + dma_bm_write(Incoming, (uint8_t *) &(req->CCBPointer), 4, dev->transfer_size); + dma_bm_read(Incoming + 4, (uint8_t *) bytes, 4, dev->transfer_size); + bytes[0] = req->HostStatus; + bytes[1] = req->TargetStatus; + bytes[3] = req->MailboxCompletionCode; + dma_bm_write(Incoming + 4, (uint8_t *) bytes, 4, dev->transfer_size); + x54x_add_to_period(dev, 7); + x54x_log("%i bytes of 32-bit mailbox written to: %08X\n", sizeof(Mailbox32_t), Incoming); } dev->MailboxInPosCur++; if (dev->MailboxInPosCur >= dev->MailboxCount) - dev->MailboxInPosCur = 0; + dev->MailboxInPosCur = 0; dev->ToRaise = INTR_MBIF | INTR_ANY; if (dev->MailboxOutInterrupts) - dev->ToRaise |= INTR_MBOA; + dev->ToRaise |= INTR_MBOA; } - static void x54x_rd_sge(x54x_t *dev, int Is24bit, uint32_t Address, SGE32 *SG) { - SGE SGE24; + SGE SGE24; uint8_t bytes[8]; if (Is24bit) { - if (dev->transfer_size == 4) { - /* 32-bit device, do this to make the transfer divisible by 4 bytes. */ - dma_bm_read(Address, (uint8_t *) bytes, 8, dev->transfer_size); - memcpy((uint8_t *)&SGE24, bytes, sizeof(SGE)); - } else { - /* 16-bit device, special handling not needed. */ - dma_bm_read(Address, (uint8_t *)&SGE24, 8, dev->transfer_size); - } - x54x_add_to_period(dev, sizeof(SGE)); + if (dev->transfer_size == 4) { + /* 32-bit device, do this to make the transfer divisible by 4 bytes. */ + dma_bm_read(Address, (uint8_t *) bytes, 8, dev->transfer_size); + memcpy((uint8_t *) &SGE24, bytes, sizeof(SGE)); + } else { + /* 16-bit device, special handling not needed. */ + dma_bm_read(Address, (uint8_t *) &SGE24, 6, dev->transfer_size); + } + x54x_add_to_period(dev, sizeof(SGE)); - /* Convert the 24-bit entries into 32-bit entries. */ - x54x_log("Read S/G block: %06X, %06X\n", SGE24.Segment, SGE24.SegmentPointer); - SG->Segment = ADDR_TO_U32(SGE24.Segment); - SG->SegmentPointer = ADDR_TO_U32(SGE24.SegmentPointer); + /* Convert the 24-bit entries into 32-bit entries. */ + x54x_log("Read S/G block: %06X, %06X\n", SGE24.Segment, SGE24.SegmentPointer); + SG->Segment = ADDR_TO_U32(SGE24.Segment); + SG->SegmentPointer = ADDR_TO_U32(SGE24.SegmentPointer); } else { - dma_bm_read(Address, (uint8_t *)SG, sizeof(SGE32), dev->transfer_size); - x54x_add_to_period(dev, sizeof(SGE32)); + dma_bm_read(Address, (uint8_t *) SG, sizeof(SGE32), dev->transfer_size); + x54x_add_to_period(dev, sizeof(SGE32)); } } - static int x54x_get_length(x54x_t *dev, Req_t *req, int Is24bit) { - uint32_t DataPointer, DataLength; + uint32_t DataPointer; + uint32_t DataLength; uint32_t SGEntryLength = (Is24bit ? sizeof(SGE) : sizeof(SGE32)); - SGE32 SGBuffer; - uint32_t DataToTransfer = 0, i = 0; + SGE32 SGBuffer; + uint32_t DataToTransfer = 0; if (Is24bit) { - DataPointer = ADDR_TO_U32(req->CmdBlock.old.DataPointer); - DataLength = ADDR_TO_U32(req->CmdBlock.old.DataLength); - x54x_log("Data length: %08X\n", req->CmdBlock.old.DataLength); + DataPointer = ADDR_TO_U32(req->CmdBlock.old.DataPointer); + DataLength = ADDR_TO_U32(req->CmdBlock.old.DataLength); + x54x_log("Data length: %08X\n", req->CmdBlock.old.DataLength); } else { - DataPointer = req->CmdBlock.new.DataPointer; - DataLength = req->CmdBlock.new.DataLength; + DataPointer = req->CmdBlock.new.DataPointer; + DataLength = req->CmdBlock.new.DataLength; } x54x_log("Data Buffer write: length %d, pointer 0x%04X\n", - DataLength, DataPointer); + DataLength, DataPointer); if (!DataLength) - return(0); + return 0; if (req->CmdBlock.common.ControlByte != 0x03) { - if (req->CmdBlock.common.Opcode == SCATTER_GATHER_COMMAND || - req->CmdBlock.common.Opcode == SCATTER_GATHER_COMMAND_RES) { - for (i = 0; i < DataLength; i += SGEntryLength) { - x54x_rd_sge(dev, Is24bit, DataPointer + i, &SGBuffer); + if (req->CmdBlock.common.Opcode == SCATTER_GATHER_COMMAND || req->CmdBlock.common.Opcode == SCATTER_GATHER_COMMAND_RES) { + for (uint32_t i = 0; i < DataLength; i += SGEntryLength) { + x54x_rd_sge(dev, Is24bit, DataPointer + i, &SGBuffer); - DataToTransfer += SGBuffer.Segment; - } - return(DataToTransfer); - } else if (req->CmdBlock.common.Opcode == SCSI_INITIATOR_COMMAND || - req->CmdBlock.common.Opcode == SCSI_INITIATOR_COMMAND_RES) { - return(DataLength); - } else { - return(0); - } + DataToTransfer += SGBuffer.Segment; + } + return DataToTransfer; + } else if (req->CmdBlock.common.Opcode == SCSI_INITIATOR_COMMAND || req->CmdBlock.common.Opcode == SCSI_INITIATOR_COMMAND_RES) { + return DataLength; + } else { + return 0; + } } else { - return(0); + return 0; } } - static void x54x_set_residue(x54x_t *dev, Req_t *req, int32_t TransferLength) { uint32_t Residue = 0; - addr24 Residue24; - int32_t BufLen = scsi_devices[dev->bus][req->TargetID].buffer_length; - uint8_t bytes[4] = { 0, 0, 0, 0 }; + addr24_t Residue24; + int32_t BufLen = scsi_devices[dev->bus][req->TargetID].buffer_length; + uint8_t bytes[4] = { 0, 0, 0, 0 }; - if ((req->CmdBlock.common.Opcode == SCSI_INITIATOR_COMMAND_RES) || - (req->CmdBlock.common.Opcode == SCATTER_GATHER_COMMAND_RES)) { + if ((req->CmdBlock.common.Opcode == SCSI_INITIATOR_COMMAND_RES) || (req->CmdBlock.common.Opcode == SCATTER_GATHER_COMMAND_RES)) { - if ((TransferLength > 0) && (req->CmdBlock.common.ControlByte < 0x03)) { - TransferLength -= BufLen; - if (TransferLength > 0) - Residue = TransferLength; - } + if ((TransferLength > 0) && (req->CmdBlock.common.ControlByte < 0x03)) { + TransferLength -= BufLen; + if (TransferLength > 0) + Residue = TransferLength; + } - if (req->Is24bit) { - U32_TO_ADDR(Residue24, Residue); - dma_bm_read(req->CCBPointer + 0x0004, (uint8_t *) bytes, 4, dev->transfer_size); - memcpy((uint8_t *) bytes, (uint8_t *)&Residue24, 3); - dma_bm_write(req->CCBPointer + 0x0004, (uint8_t *) bytes, 4, dev->transfer_size); - x54x_add_to_period(dev, 3); - x54x_log("24-bit Residual data length for reading: %d\n", Residue); - } else { - dma_bm_write(req->CCBPointer + 0x0004, (uint8_t *)&Residue, 4, dev->transfer_size); - x54x_add_to_period(dev, 4); - x54x_log("32-bit Residual data length for reading: %d\n", Residue); - } + if (req->Is24bit) { + U32_TO_ADDR(Residue24, Residue); + dma_bm_read(req->CCBPointer + 0x0004, (uint8_t *) bytes, 4, dev->transfer_size); + memcpy((uint8_t *) bytes, (uint8_t *) &Residue24, 3); + dma_bm_write(req->CCBPointer + 0x0004, (uint8_t *) bytes, 4, dev->transfer_size); + x54x_add_to_period(dev, 3); + x54x_log("24-bit Residual data length for reading: %d\n", Residue); + } else { + dma_bm_write(req->CCBPointer + 0x0004, (uint8_t *) &Residue, 4, dev->transfer_size); + x54x_add_to_period(dev, 4); + x54x_log("32-bit Residual data length for reading: %d\n", Residue); + } } } - static void x54x_buf_dma_transfer(x54x_t *dev, Req_t *req, int Is24bit, int TransferLength, int dir) { - uint32_t DataPointer, DataLength; + uint32_t DataPointer; + uint32_t DataLength; uint32_t SGEntryLength = (Is24bit ? sizeof(SGE) : sizeof(SGE32)); - uint32_t Address, i; - int32_t BufLen = scsi_devices[dev->bus][req->TargetID].buffer_length; - uint8_t read_from_host = (dir && ((req->CmdBlock.common.ControlByte == CCB_DATA_XFER_OUT) || (req->CmdBlock.common.ControlByte == 0x00))); - uint8_t write_to_host = (!dir && ((req->CmdBlock.common.ControlByte == CCB_DATA_XFER_IN) || (req->CmdBlock.common.ControlByte == 0x00))); - int sg_pos = 0; - SGE32 SGBuffer; + uint32_t Address; + int32_t BufLen = scsi_devices[dev->bus][req->TargetID].buffer_length; + uint8_t read_from_host = (dir && ((req->CmdBlock.common.ControlByte == CCB_DATA_XFER_OUT) || (req->CmdBlock.common.ControlByte == 0x00))); + uint8_t write_to_host = (!dir && ((req->CmdBlock.common.ControlByte == CCB_DATA_XFER_IN) || (req->CmdBlock.common.ControlByte == 0x00))); + int sg_pos = 0; + SGE32 SGBuffer; uint32_t DataToTransfer = 0; if (Is24bit) { - DataPointer = ADDR_TO_U32(req->CmdBlock.old.DataPointer); - DataLength = ADDR_TO_U32(req->CmdBlock.old.DataLength); + DataPointer = ADDR_TO_U32(req->CmdBlock.old.DataPointer); + DataLength = ADDR_TO_U32(req->CmdBlock.old.DataLength); } else { - DataPointer = req->CmdBlock.new.DataPointer; - DataLength = req->CmdBlock.new.DataLength; + DataPointer = req->CmdBlock.new.DataPointer; + DataLength = req->CmdBlock.new.DataLength; } x54x_log("Data Buffer %s: length %d (%u), pointer 0x%04X\n", - dir ? "write" : "read", BufLen, DataLength, DataPointer); + dir ? "write" : "read", BufLen, DataLength, DataPointer); if ((req->CmdBlock.common.ControlByte != 0x03) && TransferLength && BufLen) { - if ((req->CmdBlock.common.Opcode == SCATTER_GATHER_COMMAND) || - (req->CmdBlock.common.Opcode == SCATTER_GATHER_COMMAND_RES)) { + if ((req->CmdBlock.common.Opcode == SCATTER_GATHER_COMMAND) || (req->CmdBlock.common.Opcode == SCATTER_GATHER_COMMAND_RES)) { - /* If the control byte is 0x00, it means that the transfer direction is set up by the SCSI command without - checking its length, so do this procedure for both no read/write commands. */ - if ((DataLength > 0) && (req->CmdBlock.common.ControlByte < 0x03)) { - for (i = 0; i < DataLength; i += SGEntryLength) { - x54x_rd_sge(dev, Is24bit, DataPointer + i, &SGBuffer); + /* If the control byte is 0x00, it means that the transfer direction is set up by the SCSI command without + checking its length, so do this procedure for both no read/write commands. */ + if ((DataLength > 0) && (req->CmdBlock.common.ControlByte < 0x03)) { + for (uint32_t i = 0; i < DataLength; i += SGEntryLength) { + x54x_rd_sge(dev, Is24bit, DataPointer + i, &SGBuffer); - Address = SGBuffer.SegmentPointer; - DataToTransfer = MIN((int) SGBuffer.Segment, BufLen); + Address = SGBuffer.SegmentPointer; + DataToTransfer = MIN((int) SGBuffer.Segment, BufLen); - if (read_from_host && DataToTransfer) { - x54x_log("Reading S/G segment %i: length %i, pointer %08X\n", i, DataToTransfer, Address); - dma_bm_read(Address, &(scsi_devices[dev->bus][req->TargetID].sc->temp_buffer[sg_pos]), DataToTransfer, dev->transfer_size); - } - else if (write_to_host && DataToTransfer) { - x54x_log("Writing S/G segment %i: length %i, pointer %08X\n", i, DataToTransfer, Address); - dma_bm_write(Address, &(scsi_devices[dev->bus][req->TargetID].sc->temp_buffer[sg_pos]), DataToTransfer, dev->transfer_size); - } - else - x54x_log("No action on S/G segment %i: length %i, pointer %08X\n", i, DataToTransfer, Address); + if (read_from_host && DataToTransfer) { + x54x_log("Reading S/G segment %i: length %i, pointer %08X\n", i, DataToTransfer, Address); + dma_bm_read(Address, &(scsi_devices[dev->bus][req->TargetID].sc->temp_buffer[sg_pos]), DataToTransfer, dev->transfer_size); + } else if (write_to_host && DataToTransfer) { + x54x_log("Writing S/G segment %i: length %i, pointer %08X\n", i, DataToTransfer, Address); + dma_bm_write(Address, &(scsi_devices[dev->bus][req->TargetID].sc->temp_buffer[sg_pos]), DataToTransfer, dev->transfer_size); + } else + x54x_log("No action on S/G segment %i: length %i, pointer %08X\n", i, DataToTransfer, Address); - sg_pos += SGBuffer.Segment; + sg_pos += SGBuffer.Segment; - BufLen -= SGBuffer.Segment; - if (BufLen < 0) - BufLen = 0; + BufLen -= SGBuffer.Segment; + if (BufLen < 0) + BufLen = 0; - x54x_log("After S/G segment done: %i, %i\n", sg_pos, BufLen); - } - } - } else if ((req->CmdBlock.common.Opcode == SCSI_INITIATOR_COMMAND) || - (req->CmdBlock.common.Opcode == SCSI_INITIATOR_COMMAND_RES)) { - Address = DataPointer; + x54x_log("After S/G segment done: %i, %i\n", sg_pos, BufLen); + } + } + } else if ((req->CmdBlock.common.Opcode == SCSI_INITIATOR_COMMAND) || (req->CmdBlock.common.Opcode == SCSI_INITIATOR_COMMAND_RES)) { + Address = DataPointer; - if ((DataLength > 0) && (BufLen > 0) && (req->CmdBlock.common.ControlByte < 0x03)) { - if (read_from_host) - dma_bm_read(Address, scsi_devices[dev->bus][req->TargetID].sc->temp_buffer, MIN(BufLen, (int) DataLength), dev->transfer_size); - else if (write_to_host) - dma_bm_write(Address, scsi_devices[dev->bus][req->TargetID].sc->temp_buffer, MIN(BufLen, (int) DataLength), dev->transfer_size); - } - } + if ((DataLength > 0) && (BufLen > 0) && (req->CmdBlock.common.ControlByte < 0x03)) { + if (read_from_host) + dma_bm_read(Address, scsi_devices[dev->bus][req->TargetID].sc->temp_buffer, MIN(BufLen, (int) DataLength), dev->transfer_size); + else if (write_to_host) + dma_bm_write(Address, scsi_devices[dev->bus][req->TargetID].sc->temp_buffer, MIN(BufLen, (int) DataLength), dev->transfer_size); + } + } } } - static uint8_t ConvertSenseLength(uint8_t RequestSenseLength) { x54x_log("Unconverted Request Sense length %i\n", RequestSenseLength); if (RequestSenseLength == 0) - RequestSenseLength = 14; + RequestSenseLength = 14; else if (RequestSenseLength == 1) - RequestSenseLength = 0; + RequestSenseLength = 0; x54x_log("Request Sense length %i\n", RequestSenseLength); - return(RequestSenseLength); + return RequestSenseLength; } - uint32_t SenseBufferPointer(Req_t *req) { uint32_t SenseBufferAddress; if (req->Is24bit) { - SenseBufferAddress = req->CCBPointer; - SenseBufferAddress += req->CmdBlock.common.CdbLength + 18; + SenseBufferAddress = req->CCBPointer; + SenseBufferAddress += req->CmdBlock.common.CdbLength + 18; } else { - SenseBufferAddress = req->CmdBlock.new.SensePointer; + SenseBufferAddress = req->CmdBlock.new.SensePointer; } - return(SenseBufferAddress); + return SenseBufferAddress; } - static void SenseBufferFree(x54x_t *dev, Req_t *req, int Copy) { - uint8_t SenseLength = ConvertSenseLength(req->CmdBlock.common.RequestSenseLength); + uint8_t SenseLength = ConvertSenseLength(req->CmdBlock.common.RequestSenseLength); uint32_t SenseBufferAddress; - uint8_t temp_sense[256]; + uint8_t temp_sense[256]; if (SenseLength && Copy) { scsi_device_request_sense(&scsi_devices[dev->bus][req->TargetID], temp_sense, SenseLength); - /* - * The sense address, in 32-bit mode, is located in the - * Sense Pointer of the CCB, but in 24-bit mode, it is - * located at the end of the Command Descriptor Block. - */ - SenseBufferAddress = SenseBufferPointer(req); + /* + * The sense address, in 32-bit mode, is located in the + * Sense Pointer of the CCB, but in 24-bit mode, it is + * located at the end of the Command Descriptor Block. + */ + SenseBufferAddress = SenseBufferPointer(req); - x54x_log("Request Sense address: %02X\n", SenseBufferAddress); + x54x_log("Request Sense address: %02X\n", SenseBufferAddress); - x54x_log("SenseBufferFree(): Writing %i bytes at %08X\n", - SenseLength, SenseBufferAddress); - dma_bm_write(SenseBufferAddress, temp_sense, SenseLength, dev->transfer_size); - x54x_add_to_period(dev, SenseLength); - x54x_log("Sense data written to buffer: %02X %02X %02X\n", - temp_sense[2], temp_sense[12], temp_sense[13]); + x54x_log("SenseBufferFree(): Writing %i bytes at %08X\n", + SenseLength, SenseBufferAddress); + dma_bm_write(SenseBufferAddress, temp_sense, SenseLength, dev->transfer_size); + x54x_add_to_period(dev, SenseLength); + x54x_log("Sense data written to buffer: %02X %02X %02X\n", + temp_sense[2], temp_sense[12], temp_sense[13]); } } - static void x54x_scsi_cmd(x54x_t *dev) { - Req_t *req = &dev->Req; - uint8_t bit24 = !!req->Is24bit; - uint32_t i, target_cdb_len = 12; + Req_t *req = &dev->Req; + uint8_t bit24 = !!req->Is24bit; + uint32_t target_cdb_len = 12; scsi_device_t *sd; sd = &scsi_devices[dev->bus][req->TargetID]; - target_cdb_len = 12; + target_cdb_len = 12; dev->target_data_len = x54x_get_length(dev, req, bit24); if (!scsi_device_valid(sd)) - fatal("SCSI target on %02i has disappeared\n", req->TargetID); + fatal("SCSI target on %02i has disappeared\n", req->TargetID); x54x_log("dev->target_data_len = %i\n", dev->target_data_len); x54x_log("SCSI command being executed on ID %i, LUN %i\n", req->TargetID, req->LUN); x54x_log("SCSI CDB[0]=0x%02X\n", req->CmdBlock.common.Cdb[0]); - for (i=1; iCmdBlock.common.CdbLength; i++) - x54x_log("SCSI CDB[%i]=%i\n", i, req->CmdBlock.common.Cdb[i]); + for (uint8_t i = 1; i < req->CmdBlock.common.CdbLength; i++) + x54x_log("SCSI CDB[%i]=%i\n", i, req->CmdBlock.common.Cdb[i]); memset(dev->temp_cdb, 0x00, target_cdb_len); if (req->CmdBlock.common.CdbLength <= target_cdb_len) { - memcpy(dev->temp_cdb, req->CmdBlock.common.Cdb, - req->CmdBlock.common.CdbLength); - x54x_add_to_period(dev, req->CmdBlock.common.CdbLength); + memcpy(dev->temp_cdb, req->CmdBlock.common.Cdb, + req->CmdBlock.common.CdbLength); + x54x_add_to_period(dev, req->CmdBlock.common.CdbLength); } else { - memcpy(dev->temp_cdb, req->CmdBlock.common.Cdb, target_cdb_len); - x54x_add_to_period(dev, target_cdb_len); + memcpy(dev->temp_cdb, req->CmdBlock.common.Cdb, target_cdb_len); + x54x_add_to_period(dev, target_cdb_len); } dev->Residue = 0; @@ -961,86 +939,83 @@ x54x_scsi_cmd(x54x_t *dev) x54x_log("Control byte: %02X\n", (req->CmdBlock.common.ControlByte == 0x03)); if (dev->scsi_cmd_phase == SCSI_PHASE_STATUS) - dev->callback_sub_phase = 3; + dev->callback_sub_phase = 3; else - dev->callback_sub_phase = 2; + dev->callback_sub_phase = 2; x54x_log("scsi_devices[%02i][%02i].Status = %02X\n", dev->bus, req->TargetID, sd->status); } - static void x54x_scsi_cmd_phase1(x54x_t *dev) { - Req_t *req = &dev->Req; - double p; - uint8_t bit24 = !!req->Is24bit; + Req_t *req = &dev->Req; + double p; + uint8_t bit24 = !!req->Is24bit; scsi_device_t *sd; sd = &scsi_devices[dev->bus][req->TargetID]; if (dev->scsi_cmd_phase != SCSI_PHASE_STATUS) { - if ((dev->temp_cdb[0] != 0x03) || (req->CmdBlock.common.ControlByte != 0x03)) { - p = scsi_device_get_callback(sd); - if (p <= 0.0) - x54x_add_to_period(dev, sd->buffer_length); - else - dev->media_period += p; - x54x_buf_dma_transfer(dev, req, bit24, dev->target_data_len, (dev->scsi_cmd_phase == SCSI_PHASE_DATA_OUT)); - scsi_device_command_phase1(sd); - } + if ((dev->temp_cdb[0] != 0x03) || (req->CmdBlock.common.ControlByte != 0x03)) { + p = scsi_device_get_callback(sd); + if (p <= 0.0) + x54x_add_to_period(dev, sd->buffer_length); + else + dev->media_period += p; + x54x_buf_dma_transfer(dev, req, bit24, dev->target_data_len, (dev->scsi_cmd_phase == SCSI_PHASE_DATA_OUT)); + scsi_device_command_phase1(sd); + } } dev->callback_sub_phase = 3; - x54x_log("scsi_devices[%02xi][%02i].Status = %02X\n", x54x->bus, req->TargetID, sd->status); + x54x_log("scsi_devices[%02xi][%02i].Status = %02X\n", dev->bus, req->TargetID, sd->status); } - static void x54x_request_sense(x54x_t *dev) { - Req_t *req = &dev->Req; - uint32_t SenseBufferAddress; + Req_t *req = &dev->Req; + uint32_t SenseBufferAddress; scsi_device_t *sd; sd = &scsi_devices[dev->bus][req->TargetID]; if (dev->scsi_cmd_phase != SCSI_PHASE_STATUS) { - if ((dev->temp_cdb[0] == 0x03) && (req->CmdBlock.common.ControlByte == 0x03)) { - /* Request sense in non-data mode - sense goes to sense buffer. */ - sd->buffer_length = ConvertSenseLength(req->CmdBlock.common.RequestSenseLength); - if ((sd->status != SCSI_STATUS_OK) && (sd->buffer_length > 0)) { - SenseBufferAddress = SenseBufferPointer(req); - dma_bm_write(SenseBufferAddress, scsi_devices[dev->bus][req->TargetID].sc->temp_buffer, sd->buffer_length, dev->transfer_size); - x54x_add_to_period(dev, sd->buffer_length); - } - scsi_device_command_phase1(sd); - } else - SenseBufferFree(dev, req, (sd->status != SCSI_STATUS_OK)); + if ((dev->temp_cdb[0] == 0x03) && (req->CmdBlock.common.ControlByte == 0x03)) { + /* Request sense in non-data mode - sense goes to sense buffer. */ + sd->buffer_length = ConvertSenseLength(req->CmdBlock.common.RequestSenseLength); + if ((sd->status != SCSI_STATUS_OK) && (sd->buffer_length > 0)) { + SenseBufferAddress = SenseBufferPointer(req); + dma_bm_write(SenseBufferAddress, scsi_devices[dev->bus][req->TargetID].sc->temp_buffer, sd->buffer_length, dev->transfer_size); + x54x_add_to_period(dev, sd->buffer_length); + } + scsi_device_command_phase1(sd); + } else + SenseBufferFree(dev, req, (sd->status != SCSI_STATUS_OK)); } else - SenseBufferFree(dev, req, (sd->status != SCSI_STATUS_OK)); + SenseBufferFree(dev, req, (sd->status != SCSI_STATUS_OK)); x54x_set_residue(dev, req, dev->target_data_len); x54x_log("Request complete\n"); if (sd->status == SCSI_STATUS_OK) { - x54x_mbi_setup(dev, req->CCBPointer, &req->CmdBlock, - CCB_COMPLETE, SCSI_STATUS_OK, MBI_SUCCESS); + x54x_mbi_setup(dev, req->CCBPointer, &req->CmdBlock, + CCB_COMPLETE, SCSI_STATUS_OK, MBI_SUCCESS); } else if (sd->status == SCSI_STATUS_CHECK_CONDITION) { - x54x_mbi_setup(dev, req->CCBPointer, &req->CmdBlock, - CCB_COMPLETE, SCSI_STATUS_CHECK_CONDITION, MBI_ERROR); + x54x_mbi_setup(dev, req->CCBPointer, &req->CmdBlock, + CCB_COMPLETE, SCSI_STATUS_CHECK_CONDITION, MBI_ERROR); } dev->callback_sub_phase = 4; x54x_log("scsi_devices[%02i][%02i].Status = %02X\n", dev->bus, req->TargetID, sd->status); } - static void x54x_mbo_free(x54x_t *dev) { - uint8_t CmdStatus = MBO_FREE; + uint8_t CmdStatus = MBO_FREE; uint32_t CodeOffset = 0; CodeOffset = (dev->flags & X54X_MBX_24BIT) ? 0 : 7; @@ -1049,11 +1024,10 @@ x54x_mbo_free(x54x_t *dev) dma_bm_write(dev->Outgoing + CodeOffset, &CmdStatus, 1, dev->transfer_size); } - static void x54x_notify(x54x_t *dev) { - Req_t *req = &dev->Req; + const Req_t *req = &dev->Req; scsi_device_t *sd; sd = &scsi_devices[dev->bus][req->TargetID]; @@ -1061,41 +1035,41 @@ x54x_notify(x54x_t *dev) x54x_mbo_free(dev); if (dev->MailboxIsBIOS) - x54x_ccb(dev); + x54x_ccb(dev); else - x54x_mbi(dev); + x54x_mbi(dev); /* Make sure to restore device to non-IDENTIFY'd state as we disconnect. */ if (sd->type != SCSI_NONE) - scsi_device_identify(sd, SCSI_LUN_USE_CDB); + scsi_device_identify(sd, SCSI_LUN_USE_CDB); } - static void -x54x_req_setup(x54x_t *dev, uint32_t CCBPointer, Mailbox32_t *Mailbox32) -{ - Req_t *req = &dev->Req; - uint8_t id, lun; +x54x_req_setup(x54x_t *dev, uint32_t CCBPointer, UNUSED(Mailbox32_t *Mailbox32)) +{ + Req_t *req = &dev->Req; + uint8_t id; + uint8_t lun; scsi_device_t *sd; /* Fetch data from the Command Control Block. */ - dma_bm_read(CCBPointer, (uint8_t *)&req->CmdBlock, sizeof(CCB32), dev->transfer_size); + dma_bm_read(CCBPointer, (uint8_t *) &req->CmdBlock, sizeof(CCB32), dev->transfer_size); x54x_add_to_period(dev, sizeof(CCB32)); - req->Is24bit = !!(dev->flags & X54X_MBX_24BIT); + req->Is24bit = !!(dev->flags & X54X_MBX_24BIT); req->CCBPointer = CCBPointer; - req->TargetID = req->Is24bit ? req->CmdBlock.old.Id : req->CmdBlock.new.Id; - req->LUN = req->Is24bit ? req->CmdBlock.old.Lun : req->CmdBlock.new.Lun; + req->TargetID = req->Is24bit ? req->CmdBlock.old.Id : req->CmdBlock.new.Id; + req->LUN = req->Is24bit ? req->CmdBlock.old.Lun : req->CmdBlock.new.Lun; - id = req->TargetID; - sd = &scsi_devices[dev->bus][id]; + id = req->TargetID; + sd = &scsi_devices[dev->bus][id]; lun = req->LUN; if ((id > dev->max_id) || (lun > 7)) { - x54x_log("SCSI Target ID %i or LUN %i is not valid\n",id,lun); - x54x_mbi_setup(dev, CCBPointer, &req->CmdBlock, - CCB_SELECTION_TIMEOUT, SCSI_STATUS_OK, MBI_ERROR); - dev->callback_sub_phase = 4; - return; + x54x_log("SCSI Target ID %i or LUN %i is not valid\n", id, lun); + x54x_mbi_setup(dev, CCBPointer, &req->CmdBlock, + CCB_SELECTION_TIMEOUT, SCSI_STATUS_OK, MBI_ERROR); + dev->callback_sub_phase = 4; + return; } x54x_log("Scanning SCSI Target ID %i\n", id); @@ -1103,120 +1077,118 @@ x54x_req_setup(x54x_t *dev, uint32_t CCBPointer, Mailbox32_t *Mailbox32) sd->status = SCSI_STATUS_OK; if (!scsi_device_present(sd) || (lun > 0)) { - x54x_log("SCSI Target ID %i and LUN %i have no device attached\n",id,lun); - x54x_mbi_setup(dev, CCBPointer, &req->CmdBlock, - CCB_SELECTION_TIMEOUT, SCSI_STATUS_OK, MBI_ERROR); - dev->callback_sub_phase = 4; + x54x_log("SCSI Target ID %i and LUN %i have no device attached\n", id, lun); + x54x_mbi_setup(dev, CCBPointer, &req->CmdBlock, + CCB_SELECTION_TIMEOUT, SCSI_STATUS_OK, MBI_ERROR); + dev->callback_sub_phase = 4; } else { - x54x_log("SCSI Target ID %i detected and working\n", id); - scsi_device_identify(sd, lun); + x54x_log("SCSI Target ID %i detected and working\n", id); + scsi_device_identify(sd, lun); - x54x_log("Transfer Control %02X\n", req->CmdBlock.common.ControlByte); - x54x_log("CDB Length %i\n", req->CmdBlock.common.CdbLength); - x54x_log("CCB Opcode %x\n", req->CmdBlock.common.Opcode); - if ((req->CmdBlock.common.Opcode > 0x04) && (req->CmdBlock.common.Opcode != 0x81)) { - x54x_log("Invalid opcode: %02X\n", - req->CmdBlock.common.ControlByte); - x54x_mbi_setup(dev, CCBPointer, &req->CmdBlock, CCB_INVALID_OP_CODE, SCSI_STATUS_OK, MBI_ERROR); - dev->callback_sub_phase = 4; - return; - } - if (req->CmdBlock.common.Opcode == 0x81) { - x54x_log("Bus reset opcode\n"); - scsi_device_reset(sd); - x54x_mbi_setup(dev, req->CCBPointer, &req->CmdBlock, - CCB_COMPLETE, SCSI_STATUS_OK, MBI_SUCCESS); - dev->callback_sub_phase = 4; - return; - } + x54x_log("Transfer Control %02X\n", req->CmdBlock.common.ControlByte); + x54x_log("CDB Length %i\n", req->CmdBlock.common.CdbLength); + x54x_log("CCB Opcode %x\n", req->CmdBlock.common.Opcode); + if ((req->CmdBlock.common.Opcode > 0x04) && (req->CmdBlock.common.Opcode != 0x81)) { + x54x_log("Invalid opcode: %02X\n", + req->CmdBlock.common.ControlByte); + x54x_mbi_setup(dev, CCBPointer, &req->CmdBlock, CCB_INVALID_OP_CODE, SCSI_STATUS_OK, MBI_ERROR); + dev->callback_sub_phase = 4; + return; + } + if (req->CmdBlock.common.Opcode == 0x81) { + x54x_log("Bus reset opcode\n"); + scsi_device_reset(sd); + x54x_mbi_setup(dev, req->CCBPointer, &req->CmdBlock, + CCB_COMPLETE, SCSI_STATUS_OK, MBI_SUCCESS); + dev->callback_sub_phase = 4; + return; + } - dev->callback_sub_phase = 1; + dev->callback_sub_phase = 1; } } - static void x54x_req_abort(x54x_t *dev, uint32_t CCBPointer) { CCBU CmdBlock; /* Fetch data from the Command Control Block. */ - dma_bm_read(CCBPointer, (uint8_t *)&CmdBlock, sizeof(CCB32), dev->transfer_size); + dma_bm_read(CCBPointer, (uint8_t *) &CmdBlock, sizeof(CCB32), dev->transfer_size); x54x_add_to_period(dev, sizeof(CCB32)); x54x_mbi_setup(dev, CCBPointer, &CmdBlock, - 0x26, SCSI_STATUS_OK, MBI_NOT_FOUND); + 0x26, SCSI_STATUS_OK, MBI_NOT_FOUND); dev->callback_sub_phase = 4; } - static uint32_t x54x_mbo(x54x_t *dev, Mailbox32_t *Mailbox32) -{ +{ Mailbox_t MailboxOut; - uint32_t Outgoing; - uint32_t ccbp; - uint32_t Addr; - uint32_t Cur; + uint32_t Outgoing; + uint32_t ccbp; + uint32_t Addr; + uint32_t Cur; if (dev->MailboxIsBIOS) { - Addr = dev->BIOSMailboxOutAddr; - Cur = dev->BIOSMailboxOutPosCur; + Addr = dev->BIOSMailboxOutAddr; + Cur = dev->BIOSMailboxOutPosCur; } else { - Addr = dev->MailboxOutAddr; - Cur = dev->MailboxOutPosCur; + Addr = dev->MailboxOutAddr; + Cur = dev->MailboxOutPosCur; } if (dev->flags & X54X_MBX_24BIT) { - Outgoing = Addr + (Cur * sizeof(Mailbox_t)); - dma_bm_read(Outgoing, (uint8_t *)&MailboxOut, sizeof(Mailbox_t), dev->transfer_size); - x54x_add_to_period(dev, sizeof(Mailbox_t)); + Outgoing = Addr + (Cur * sizeof(Mailbox_t)); + dma_bm_read(Outgoing, (uint8_t *) &MailboxOut, sizeof(Mailbox_t), dev->transfer_size); + x54x_add_to_period(dev, sizeof(Mailbox_t)); - ccbp = *(uint32_t *) &MailboxOut; - Mailbox32->CCBPointer = (ccbp >> 24) | ((ccbp >> 8) & 0xff00) | ((ccbp << 8) & 0xff0000); - Mailbox32->u.out.ActionCode = MailboxOut.CmdStatus; + ccbp = *(uint32_t *) &MailboxOut; + Mailbox32->CCBPointer = (ccbp >> 24) | ((ccbp >> 8) & 0xff00) | ((ccbp << 8) & 0xff0000); + Mailbox32->u.out.ActionCode = MailboxOut.CmdStatus; } else { - Outgoing = Addr + (Cur * sizeof(Mailbox32_t)); + Outgoing = Addr + (Cur * sizeof(Mailbox32_t)); - dma_bm_read(Outgoing, (uint8_t *)Mailbox32, sizeof(Mailbox32_t), dev->transfer_size); - x54x_add_to_period(dev, sizeof(Mailbox32_t)); + dma_bm_read(Outgoing, (uint8_t *) Mailbox32, sizeof(Mailbox32_t), dev->transfer_size); + x54x_add_to_period(dev, sizeof(Mailbox32_t)); } - return(Outgoing); + return Outgoing; } - uint8_t x54x_mbo_process(x54x_t *dev) { Mailbox32_t mb32; - dev->ToRaise = 0; + dev->ToRaise = 0; dev->Outgoing = x54x_mbo(dev, &mb32); if (mb32.u.out.ActionCode == MBO_START) { - x54x_log("Start Mailbox Command\n"); - x54x_req_setup(dev, mb32.CCBPointer, &mb32); + x54x_log("Start Mailbox Command\n"); + x54x_req_setup(dev, mb32.CCBPointer, &mb32); } else if (!dev->MailboxIsBIOS && (mb32.u.out.ActionCode == MBO_ABORT)) { - x54x_log("Abort Mailbox Command\n"); - x54x_req_abort(dev, mb32.CCBPointer); - } /* else { - x54x_log("Invalid action code: %02X\n", mb32.u.out.ActionCode); - } */ - - if ((mb32.u.out.ActionCode == MBO_START) || (!dev->MailboxIsBIOS && (mb32.u.out.ActionCode == MBO_ABORT))) { - /* We got the mailbox, decrease the number of pending requests. */ - if (dev->MailboxIsBIOS) - dev->BIOSMailboxReq--; - else - dev->MailboxReq--; - - return(1); + x54x_log("Abort Mailbox Command\n"); + x54x_req_abort(dev, mb32.CCBPointer); +#if 0 + } else { + x54x_log("Invalid action code: %02X\n", mb32.u.out.ActionCode); +#endif } - return(0); -} + if ((mb32.u.out.ActionCode == MBO_START) || (!dev->MailboxIsBIOS && (mb32.u.out.ActionCode == MBO_ABORT))) { + /* We got the mailbox, decrease the number of pending requests. */ + if (dev->MailboxIsBIOS) + dev->BIOSMailboxReq--; + else + dev->MailboxReq--; + return 1; + } + + return 0; +} static void x54x_do_mail(x54x_t *dev) @@ -1226,707 +1198,700 @@ x54x_do_mail(x54x_t *dev) dev->MailboxIsBIOS = 0; if (dev->is_aggressive_mode) { - aggressive = dev->is_aggressive_mode(dev); - x54x_log("Processing mailboxes in %s mode...\n", aggressive ? "aggressive" : "strict"); - }/* else { - x54x_log("Defaulting to process mailboxes in %s mode...\n", aggressive ? "aggressive" : "strict"); - }*/ + aggressive = dev->is_aggressive_mode(dev); + x54x_log("Processing mailboxes in %s mode...\n", aggressive ? "aggressive" : "strict"); + } /* else { + x54x_log("Defaulting to process mailboxes in %s mode...\n", aggressive ? "aggressive" : "strict"); + }*/ if (!dev->MailboxCount) { - x54x_log("x54x_do_mail(): No Mailboxes\n"); - return; + x54x_log("x54x_do_mail(): No Mailboxes\n"); + return; } if (aggressive) { - /* Search for a filled mailbox - stop if we have scanned all mailboxes. */ - for (dev->MailboxOutPosCur = 0; dev->MailboxOutPosCur < dev->MailboxCount; dev->MailboxOutPosCur++) { - if (x54x_mbo_process(dev)) - break; - } + /* Search for a filled mailbox - stop if we have scanned all mailboxes. */ + for (dev->MailboxOutPosCur = 0; dev->MailboxOutPosCur < dev->MailboxCount; dev->MailboxOutPosCur++) { + if (x54x_mbo_process(dev)) + break; + } } else { - /* Strict round robin mode - only process the current mailbox and advance the pointer if successful. */ - if (x54x_mbo_process(dev)) { - dev->MailboxOutPosCur++; - dev->MailboxOutPosCur %= dev->MailboxCount; - } + /* Strict round robin mode - only process the current mailbox and advance the pointer if successful. */ + if (x54x_mbo_process(dev)) { + dev->MailboxOutPosCur++; + dev->MailboxOutPosCur %= dev->MailboxCount; + } } } - static void x54x_cmd_done(x54x_t *dev, int suppress); - static void x54x_cmd_callback(void *priv) { - double period; + double period; x54x_t *dev = (x54x_t *) priv; - int mailboxes_present, bios_mailboxes_present; + int mailboxes_present; + int bios_mailboxes_present; - mailboxes_present = (!(dev->Status & STAT_INIT) && dev->MailboxInit && dev->MailboxReq); + mailboxes_present = (!(dev->Status & STAT_INIT) && dev->MailboxInit && dev->MailboxReq); bios_mailboxes_present = (dev->ven_callback && dev->BIOSMailboxInit && dev->BIOSMailboxReq); - dev->temp_period = 0; + dev->temp_period = 0; dev->media_period = 0.0; switch (dev->callback_sub_phase) { - case 0: - /* Sub-phase 0 - Look for mailbox. */ - if ((dev->callback_phase == 0) && mailboxes_present) - x54x_do_mail(dev); - else if ((dev->callback_phase == 1) && bios_mailboxes_present) - dev->ven_callback(dev); + case 0: + /* Sub-phase 0 - Look for mailbox. */ + if ((dev->callback_phase == 0) && mailboxes_present) + x54x_do_mail(dev); + else if ((dev->callback_phase == 1) && bios_mailboxes_present) + dev->ven_callback(dev); - if (dev->ven_callback && (dev->callback_sub_phase == 0)) - dev->callback_phase ^= 1; - break; - case 1: - /* Sub-phase 1 - Do SCSI command phase 0. */ - x54x_log("%s: Callback: Process SCSI request\n", dev->name); - x54x_scsi_cmd(dev); - break; - case 2: - /* Sub-phase 2 - Do SCSI command phase 1. */ - x54x_log("%s: Callback: Process SCSI request\n", dev->name); - x54x_scsi_cmd_phase1(dev); - break; - case 3: - /* Sub-phase 3 - Request sense. */ - x54x_log("%s: Callback: Process SCSI request\n", dev->name); - x54x_request_sense(dev); - break; - case 4: - /* Sub-phase 4 - Notify. */ - x54x_log("%s: Callback: Send incoming mailbox\n", dev->name); - x54x_notify(dev); + if (dev->ven_callback && (dev->callback_sub_phase == 0)) + dev->callback_phase ^= 1; + break; + case 1: + /* Sub-phase 1 - Do SCSI command phase 0. */ + x54x_log("%s: Callback: Process SCSI request\n", dev->name); + x54x_scsi_cmd(dev); + break; + case 2: + /* Sub-phase 2 - Do SCSI command phase 1. */ + x54x_log("%s: Callback: Process SCSI request\n", dev->name); + x54x_scsi_cmd_phase1(dev); + break; + case 3: + /* Sub-phase 3 - Request sense. */ + x54x_log("%s: Callback: Process SCSI request\n", dev->name); + x54x_request_sense(dev); + break; + case 4: + /* Sub-phase 4 - Notify. */ + x54x_log("%s: Callback: Send incoming mailbox\n", dev->name); + x54x_notify(dev); - /* Go back to lookup phase. */ - dev->callback_sub_phase = 0; + /* Go back to lookup phase. */ + dev->callback_sub_phase = 0; - /* Toggle normal/BIOS mailbox - only has an effect if both types of mailboxes - have been initialized. */ - if (dev->ven_callback) - dev->callback_phase ^= 1; + /* Toggle normal/BIOS mailbox - only has an effect if both types of mailboxes + have been initialized. */ + if (dev->ven_callback) + dev->callback_phase ^= 1; - /* Add to period and raise the IRQ if needed. */ - x54x_add_to_period(dev, 1); + /* Add to period and raise the IRQ if needed. */ + x54x_add_to_period(dev, 1); - if (dev->ToRaise) - raise_irq(dev, 0, dev->ToRaise); - break; - default: - x54x_log("Invalid sub-phase: %02X\n", dev->callback_sub_phase); - break; + if (dev->ToRaise) + raise_irq(dev, 0, dev->ToRaise); + break; + default: + x54x_log("Invalid sub-phase: %02X\n", dev->callback_sub_phase); + break; } period = (1000000.0 / dev->ha_bps) * ((double) dev->temp_period); - timer_on(&dev->timer, dev->media_period + period + 10.0, 0); - // x54x_log("Temporary period: %lf us (%" PRIi64 " periods)\n", dev->timer.period, dev->temp_period); + timer_on_auto(&dev->timer, dev->media_period + period + 10.0); +#if 0 + x54x_log("Temporary period: %lf us (%" PRIi64 " periods)\n", dev->timer.period, dev->temp_period); +#endif } - static uint8_t x54x_in(uint16_t port, void *priv) { - x54x_t *dev = (x54x_t *)priv; + x54x_t *dev = (x54x_t *) priv; uint8_t ret; switch (port & 3) { - case 0: - default: - ret = dev->Status; - break; + default: + case 0: + ret = dev->Status; + break; - case 1: - ret = dev->DataBuf[dev->DataReply]; - if (dev->DataReplyLeft) { - dev->DataReply++; - dev->DataReplyLeft--; - if (! dev->DataReplyLeft) - x54x_cmd_done(dev, 0); - } - break; + case 1: + ret = dev->DataBuf[dev->DataReply]; + if (dev->DataReplyLeft) { + dev->DataReply++; + dev->DataReplyLeft--; + if (!dev->DataReplyLeft) + x54x_cmd_done(dev, 0); + } + break; - case 2: - if (dev->flags & X54X_INT_GEOM_WRITABLE) - ret = dev->Interrupt; - else - ret = dev->Interrupt & ~0x70; - break; + case 2: + if (dev->flags & X54X_INT_GEOM_WRITABLE) + ret = dev->Interrupt; + else + ret = dev->Interrupt & ~0x70; + break; - case 3: - /* Bits according to ASPI4DOS.SYS v3.36: - 0 Not checked - 1 Must be 0 - 2 Must be 0-0-0-1 - 3 Must be 0 - 4 Must be 0-1-0-0 - 5 Must be 0 - 6 Not checked - 7 Not checked - */ - if (dev->flags & X54X_INT_GEOM_WRITABLE) - ret = dev->Geometry; - else { - switch(dev->Geometry) { - case 0: default: ret = 'A'; break; - case 1: ret = 'D'; break; - case 2: ret = 'A'; break; - case 3: ret = 'P'; break; - } - ret ^= 1; - dev->Geometry++; - dev->Geometry &= 0x03; - break; - } - break; + case 3: + /* Bits according to ASPI4DOS.SYS v3.36: + 0 Not checked + 1 Must be 0 + 2 Must be 0-0-0-1 + 3 Must be 0 + 4 Must be 0-1-0-0 + 5 Must be 0 + 6 Not checked + 7 Not checked + */ + if (dev->flags & X54X_INT_GEOM_WRITABLE) + ret = dev->Geometry; + else { + if (dev->flags & X54X_HAS_SIGNATURE) { + switch (dev->Geometry) { + default: + case 0: + ret = 'A'; + break; + case 1: + ret = 'D'; + break; + case 2: + ret = 'A'; + break; + case 3: + ret = 'P'; + break; + } + ret ^= 1; + dev->Geometry++; + dev->Geometry &= 0x03; + } else + ret = 0xff; + break; + } + break; } #ifdef ENABLE_X54X_LOG if (port == 0x0332) - x54x_log("x54x_in(): %04X, %02X, %08X\n", port, ret, dev->DataReplyLeft); + x54x_log("x54x_in(): %04X, %02X, %08X\n", port, ret, dev->DataReplyLeft); else - x54x_log("x54x_in(): %04X, %02X\n", port, ret); + x54x_log("x54x_in(): %04X, %02X\n", port, ret); #endif - return(ret); + return ret; } - static uint16_t x54x_inw(uint16_t port, void *priv) { - return((uint16_t) x54x_in(port, priv)); + return ((uint16_t) x54x_in(port, priv)); } - static uint32_t x54x_inl(uint16_t port, void *priv) { - return((uint32_t) x54x_in(port, priv)); + return ((uint32_t) x54x_in(port, priv)); } - static uint8_t x54x_readb(uint32_t port, void *priv) { - return(x54x_in(port & 3, priv)); + return (x54x_in(port & 3, priv)); } - static uint16_t x54x_readw(uint32_t port, void *priv) { - return(x54x_inw(port & 3, priv)); + return (x54x_inw(port & 3, priv)); } - static uint32_t x54x_readl(uint32_t port, void *priv) { - return(x54x_inl(port & 3, priv)); + return (x54x_inl(port & 3, priv)); } - static void x54x_reset_poll(void *priv) { - x54x_t *dev = (x54x_t *)priv; + x54x_t *dev = (x54x_t *) priv; dev->Status = STAT_INIT | STAT_IDLE; } - static void x54x_reset(x54x_t *dev) { - int i; - clear_irq(dev); + dev->irq_state = 0; if (dev->flags & X54X_INT_GEOM_WRITABLE) - dev->Geometry = 0x80; + dev->Geometry = 0x90; else - dev->Geometry = 0x00; - dev->callback_phase = 0; + dev->Geometry = 0x00; + dev->callback_phase = 0; dev->callback_sub_phase = 0; timer_stop(&dev->timer); timer_set_delay_u64(&dev->timer, (uint64_t) (dev->timer.period * ((double) TIMER_USEC))); - dev->Command = 0xFF; - dev->CmdParam = 0; + dev->Command = 0xFF; + dev->CmdParam = 0; dev->CmdParamLeft = 0; dev->flags |= X54X_MBX_24BIT; - dev->MailboxInPosCur = 0; + dev->MailboxInPosCur = 0; dev->MailboxOutInterrupts = 0; - dev->PendingInterrupt = 0; - dev->IrqEnabled = 1; - dev->MailboxCount = 0; - dev->MailboxOutPosCur = 0; + dev->PendingInterrupt = 0; + dev->IrqEnabled = 1; + dev->MailboxCount = 0; + dev->MailboxOutPosCur = 0; /* Reset all devices on controller reset. */ - for (i = 0; i < 16; i++) - scsi_device_reset(&scsi_devices[dev->bus][i]); + for (uint8_t i = 0; i < 16; i++) + scsi_device_reset(&scsi_devices[dev->bus][i]); if (dev->ven_reset) - dev->ven_reset(dev); + dev->ven_reset(dev); } - void x54x_reset_ctrl(x54x_t *dev, uint8_t Reset) { /* Say hello! */ x54x_log("%s %s (IO=0x%04X, IRQ=%d, DMA=%d, BIOS @%05lX) ID=%d\n", - dev->vendor, dev->name, dev->Base, dev->Irq, dev->DmaChannel, - dev->rom_addr, dev->HostID); + dev->vendor, dev->name, dev->Base, dev->Irq, dev->DmaChannel, + dev->rom_addr, dev->HostID); x54x_reset(dev); if (Reset) { - dev->Status = STAT_STST; - timer_set_delay_u64(&dev->ResetCB, X54X_RESET_DURATION_US * TIMER_USEC); + dev->Status = STAT_STST; + timer_set_delay_u64(&dev->ResetCB, X54X_RESET_DURATION_US * TIMER_USEC); } else - dev->Status = STAT_INIT | STAT_IDLE; + dev->Status = STAT_INIT | STAT_IDLE; } - static void x54x_out(uint16_t port, uint8_t val, void *priv) { ReplyInquireSetupInformation *ReplyISI; - x54x_t *dev = (x54x_t *)priv; - MailboxInit_t *mbi; - int i = 0; - BIOSCMD *cmd; - uint16_t cyl = 0; - int suppress = 0; - uint32_t FIFOBuf; - uint8_t reset; - addr24 Address; - uint8_t host_id = dev->HostID; - uint8_t irq = 0; + x54x_t *dev = (x54x_t *) priv; + const MailboxInit_t *mbi; + int i = 0; + BIOSCMD *cmd; + uint16_t cyl = 0; + int suppress = 0; + uint32_t FIFOBuf; + uint8_t reset; + addr24_t Address; + uint8_t host_id = dev->HostID; + uint8_t irq = 0; x54x_log("%s: Write Port 0x%02X, Value %02X\n", dev->name, port, val); switch (port & 3) { - case 0: - if ((val & CTRL_HRST) || (val & CTRL_SRST)) { - reset = (val & CTRL_HRST); - x54x_log("Reset completed = %x\n", reset); - x54x_reset_ctrl(dev, reset); - x54x_log("Controller reset\n"); - break; - } + case 0: + if ((val & CTRL_HRST) || (val & CTRL_SRST)) { + reset = (val & CTRL_HRST); + x54x_log("Reset completed = %x\n", reset); + x54x_reset_ctrl(dev, reset); + x54x_log("Controller reset\n"); + break; + } - if (val & CTRL_SCRST) { - /* Reset all devices on SCSI bus reset. */ - for (i = 0; i < 16; i++) - scsi_device_reset(&scsi_devices[dev->bus][i]); - } + if (val & CTRL_SCRST) { + /* Reset all devices on SCSI bus reset. */ + for (i = 0; i < 16; i++) + scsi_device_reset(&scsi_devices[dev->bus][i]); + } - if (val & CTRL_IRST) { - clear_irq(dev); - x54x_log("Interrupt reset\n"); - } - break; + if (val & CTRL_IRST) { + clear_irq(dev); + x54x_log("Interrupt reset\n"); + } + break; - case 1: - /* Fast path for the mailbox execution command. */ - if ((val == CMD_START_SCSI) && (dev->Command == 0xff)) { - dev->MailboxReq++; - x54x_log("Start SCSI command\n"); - return; - } - if (dev->ven_fast_cmds) { - if (dev->Command == 0xff) { - if (dev->ven_fast_cmds(dev, val)) - return; - } - } + case 1: + /* Fast path for the mailbox execution command. */ + if ((val == CMD_START_SCSI) && (dev->Command == 0xff)) { + dev->MailboxReq++; + x54x_log("Start SCSI command\n"); + return; + } + if (dev->ven_fast_cmds) { + if (dev->Command == 0xff) { + if (dev->ven_fast_cmds(dev, val)) + return; + } + } - if (dev->Command == 0xff) { - dev->Command = val; - dev->CmdParam = 0; - dev->CmdParamLeft = 0; + if (dev->Command == 0xff) { + dev->Command = val; + dev->CmdParam = 0; + dev->CmdParamLeft = 0; - dev->Status &= ~(STAT_INVCMD | STAT_IDLE); - x54x_log("%s: Operation Code 0x%02X\n", dev->name, val); - switch (dev->Command) { - case CMD_MBINIT: - dev->CmdParamLeft = sizeof(MailboxInit_t); - break; + dev->Status &= ~(STAT_INVCMD | STAT_IDLE); + x54x_log("%s: Operation Code 0x%02X\n", dev->name, val); + switch (dev->Command) { + case CMD_MBINIT: + dev->CmdParamLeft = sizeof(MailboxInit_t); + break; - case CMD_BIOSCMD: - dev->CmdParamLeft = 10; - break; + case CMD_BIOSCMD: + dev->CmdParamLeft = 10; + break; - case CMD_EMBOI: - case CMD_BUSON_TIME: - case CMD_BUSOFF_TIME: - case CMD_DMASPEED: - case CMD_RETSETUP: - case CMD_ECHO: - case CMD_OPTIONS: - dev->CmdParamLeft = 1; - break; + case CMD_EMBOI: + case CMD_BUSON_TIME: + case CMD_BUSOFF_TIME: + case CMD_DMASPEED: + case CMD_RETSETUP: + case CMD_ECHO: + case CMD_OPTIONS: + dev->CmdParamLeft = 1; + break; - case CMD_SELTIMEOUT: - dev->CmdParamLeft = 4; - break; + case CMD_SELTIMEOUT: + dev->CmdParamLeft = 4; + break; - case CMD_WRITE_CH2: - case CMD_READ_CH2: - dev->CmdParamLeft = 3; - break; + case CMD_WRITE_CH2: + case CMD_READ_CH2: + dev->CmdParamLeft = 3; + break; - default: - if (dev->get_ven_param_len) - dev->CmdParamLeft = dev->get_ven_param_len(dev); - break; - } - } else { - dev->CmdBuf[dev->CmdParam] = val; - dev->CmdParam++; - dev->CmdParamLeft--; + default: + if (dev->get_ven_param_len) + dev->CmdParamLeft = dev->get_ven_param_len(dev); + break; + } + } else { + dev->CmdBuf[dev->CmdParam] = val; + dev->CmdParam++; + dev->CmdParamLeft--; - if (dev->ven_cmd_phase1) - dev->ven_cmd_phase1(dev); - } - - if (! dev->CmdParamLeft) { - x54x_log("Running Operation Code 0x%02X\n", dev->Command); - switch (dev->Command) { - case CMD_NOP: /* No Operation */ - dev->DataReplyLeft = 0; - break; + if (dev->ven_cmd_phase1) + dev->ven_cmd_phase1(dev); + } - case CMD_MBINIT: /* mailbox initialization */ - dev->flags |= X54X_MBX_24BIT; + if (!dev->CmdParamLeft) { + x54x_log("Running Operation Code 0x%02X\n", dev->Command); + switch (dev->Command) { + case CMD_NOP: /* No Operation */ + dev->DataReplyLeft = 0; + break; - mbi = (MailboxInit_t *)dev->CmdBuf; + case CMD_MBINIT: /* mailbox initialization */ + dev->flags |= X54X_MBX_24BIT; - dev->MailboxInit = 1; - dev->MailboxCount = mbi->Count; - dev->MailboxOutAddr = ADDR_TO_U32(mbi->Address); - dev->MailboxInAddr = dev->MailboxOutAddr + (dev->MailboxCount * sizeof(Mailbox_t)); + mbi = (MailboxInit_t *) dev->CmdBuf; - x54x_log("Initialize Mailbox: MBO=0x%08lx, MBI=0x%08lx, %d entries at 0x%08lx\n", - dev->MailboxOutAddr, - dev->MailboxInAddr, - mbi->Count, - ADDR_TO_U32(mbi->Address)); + dev->MailboxInit = 1; + dev->MailboxCount = mbi->Count; + dev->MailboxOutAddr = ADDR_TO_U32(mbi->Address); + dev->MailboxInAddr = dev->MailboxOutAddr + (dev->MailboxCount * sizeof(Mailbox_t)); - dev->Status &= ~STAT_INIT; - dev->DataReplyLeft = 0; - x54x_log("Mailbox init: "); - break; + x54x_log("Initialize Mailbox: MBO=0x%08lx, MBI=0x%08lx, %d entries at 0x%08lx\n", + dev->MailboxOutAddr, + dev->MailboxInAddr, + mbi->Count, + ADDR_TO_U32(mbi->Address)); - case CMD_BIOSCMD: /* execute BIOS */ - cmd = (BIOSCMD *)dev->CmdBuf; - if (!(dev->flags & X54X_LBA_BIOS)) { - /* 1640 uses LBA. */ - cyl = ((cmd->u.chs.cyl & 0xff) << 8) | ((cmd->u.chs.cyl >> 8) & 0xff); - cmd->u.chs.cyl = cyl; - } - if (dev->flags & X54X_LBA_BIOS) { - /* 1640 uses LBA. */ - x54x_log("BIOS LBA=%06lx (%lu)\n", - lba32_blk(cmd), - lba32_blk(cmd)); - } else { - cmd->u.chs.head &= 0xf; - cmd->u.chs.sec &= 0x1f; - x54x_log("BIOS CHS=%04X/%02X%02X\n", - cmd->u.chs.cyl, - cmd->u.chs.head, - cmd->u.chs.sec); - } - dev->DataBuf[0] = x54x_bios_command(dev, dev->max_id, cmd, !!(dev->flags & X54X_LBA_BIOS)); - x54x_log("BIOS Completion/Status Code %x\n", dev->DataBuf[0]); - dev->DataReplyLeft = 1; - break; + dev->Status &= ~STAT_INIT; + dev->DataReplyLeft = 0; + x54x_log("Mailbox init: "); + break; - case CMD_INQUIRY: /* Inquiry */ - memcpy(dev->DataBuf, dev->fw_rev, 4); - x54x_log("Adapter inquiry: %c %c %c %c\n", dev->fw_rev[0], dev->fw_rev[1], dev->fw_rev[2], dev->fw_rev[3]); - dev->DataReplyLeft = 4; - break; + case CMD_BIOSCMD: /* execute BIOS */ + cmd = (BIOSCMD *) dev->CmdBuf; + if (!(dev->flags & X54X_LBA_BIOS)) { + /* 1640 uses LBA. */ + cyl = ((cmd->u.chs.cyl & 0xff) << 8) | ((cmd->u.chs.cyl >> 8) & 0xff); + cmd->u.chs.cyl = cyl; + } + if (dev->flags & X54X_LBA_BIOS) { + /* 1640 uses LBA. */ + x54x_log("BIOS LBA=%06lx (%lu)\n", + lba32_blk(cmd), + lba32_blk(cmd)); + } else { + cmd->u.chs.head &= 0xf; + cmd->u.chs.sec &= 0x1f; + x54x_log("BIOS CHS=%04X/%02X%02X\n", + cmd->u.chs.cyl, + cmd->u.chs.head, + cmd->u.chs.sec); + } + dev->DataBuf[0] = x54x_bios_command(dev, dev->max_id, cmd, !!(dev->flags & X54X_LBA_BIOS)); + x54x_log("BIOS Completion/Status Code %x\n", dev->DataBuf[0]); + dev->DataReplyLeft = 1; + break; - case CMD_EMBOI: /* enable MBO Interrupt */ - if (dev->CmdBuf[0] <= 1) { - dev->MailboxOutInterrupts = dev->CmdBuf[0]; - x54x_log("Mailbox out interrupts: %s\n", dev->MailboxOutInterrupts ? "ON" : "OFF"); - suppress = 1; - } else { - dev->Status |= STAT_INVCMD; - } - dev->DataReplyLeft = 0; - break; + case CMD_INQUIRY: /* Inquiry */ + memcpy(dev->DataBuf, dev->fw_rev, 4); + x54x_log("Adapter inquiry: %c %c %c %c\n", dev->fw_rev[0], dev->fw_rev[1], dev->fw_rev[2], dev->fw_rev[3]); + dev->DataReplyLeft = 4; + break; - case CMD_SELTIMEOUT: /* Selection Time-out */ - dev->DataReplyLeft = 0; - break; + case CMD_EMBOI: /* enable MBO Interrupt */ + if (dev->CmdBuf[0] <= 1) { + dev->MailboxOutInterrupts = dev->CmdBuf[0]; + x54x_log("Mailbox out interrupts: %s\n", dev->MailboxOutInterrupts ? "ON" : "OFF"); + suppress = 1; + } else { + dev->Status |= STAT_INVCMD; + } + dev->DataReplyLeft = 0; + break; - case CMD_BUSON_TIME: /* bus-on time */ - dev->BusOnTime = dev->CmdBuf[0]; - dev->DataReplyLeft = 0; - x54x_log("Bus-on time: %d\n", dev->CmdBuf[0]); - break; + case CMD_SELTIMEOUT: /* Selection Time-out */ + dev->DataReplyLeft = 0; + break; - case CMD_BUSOFF_TIME: /* bus-off time */ - dev->BusOffTime = dev->CmdBuf[0]; - dev->DataReplyLeft = 0; - x54x_log("Bus-off time: %d\n", dev->CmdBuf[0]); - break; + case CMD_BUSON_TIME: /* bus-on time */ + dev->BusOnTime = dev->CmdBuf[0]; + dev->DataReplyLeft = 0; + x54x_log("Bus-on time: %d\n", dev->CmdBuf[0]); + break; - case CMD_DMASPEED: /* DMA Transfer Rate */ - dev->ATBusSpeed = dev->CmdBuf[0]; - dev->DataReplyLeft = 0; - x54x_log("DMA transfer rate: %02X\n", dev->CmdBuf[0]); - break; + case CMD_BUSOFF_TIME: /* bus-off time */ + dev->BusOffTime = dev->CmdBuf[0]; + dev->DataReplyLeft = 0; + x54x_log("Bus-off time: %d\n", dev->CmdBuf[0]); + break; - case CMD_RETDEVS: /* return Installed Devices */ - memset(dev->DataBuf, 0x00, 8); + case CMD_DMASPEED: /* DMA Transfer Rate */ + dev->ATBusSpeed = dev->CmdBuf[0]; + dev->DataReplyLeft = 0; + x54x_log("DMA transfer rate: %02X\n", dev->CmdBuf[0]); + break; - if (dev->ven_get_host_id) - host_id = dev->ven_get_host_id(dev); + case CMD_RETDEVS: /* return Installed Devices */ + memset(dev->DataBuf, 0x00, 8); - for (i=0; i<8; i++) { - dev->DataBuf[i] = 0x00; + if (dev->ven_get_host_id) + host_id = dev->ven_get_host_id(dev); - /* Skip the HA .. */ - if (i == host_id) continue; + for (i = 0; i < 8; i++) { + dev->DataBuf[i] = 0x00; - /* TODO: Query device for LUN's. */ - if (scsi_device_present(&scsi_devices[dev->bus][i])) - dev->DataBuf[i] |= 1; - } - dev->DataReplyLeft = i; - break; + /* Skip the HA .. */ + if (i == host_id) + continue; - case CMD_RETCONF: /* return Configuration */ - if (dev->ven_get_dma) - dev->DataBuf[0] = (1 << dev->ven_get_dma(dev)); - else - dev->DataBuf[0] = (1 << dev->DmaChannel); + /* TODO: Query device for LUN's. */ + if (scsi_device_present(&scsi_devices[dev->bus][i])) + dev->DataBuf[i] |= 1; + } + dev->DataReplyLeft = i; + break; - if (dev->ven_get_irq) - irq = dev->ven_get_irq(dev); - else - irq = dev->Irq; + case CMD_RETCONF: /* return Configuration */ + if (dev->ven_get_dma) + dev->DataBuf[0] = (1 << dev->ven_get_dma(dev)); + else + dev->DataBuf[0] = (1 << dev->DmaChannel); - if (irq >= 9) - dev->DataBuf[1]=(1<<(irq-9)); - else - dev->DataBuf[1]=0; - if (dev->ven_get_host_id) - dev->DataBuf[2] = dev->ven_get_host_id(dev); - else - dev->DataBuf[2] = dev->HostID; - x54x_log("Configuration data: %02X %02X %02X\n", dev->DataBuf[0], dev->DataBuf[1], dev->DataBuf[2]); - dev->DataReplyLeft = 3; - break; + if (dev->ven_get_irq) + irq = dev->ven_get_irq(dev); + else + irq = dev->Irq; - case CMD_RETSETUP: /* return Setup */ - ReplyISI = (ReplyInquireSetupInformation *)dev->DataBuf; - memset(ReplyISI, 0x00, sizeof(ReplyInquireSetupInformation)); + if (irq >= 9) + dev->DataBuf[1] = (1 << (irq - 9)); + else + dev->DataBuf[1] = 0; + if (dev->ven_get_host_id) + dev->DataBuf[2] = dev->ven_get_host_id(dev); + else + dev->DataBuf[2] = dev->HostID; + x54x_log("Configuration data: %02X %02X %02X\n", dev->DataBuf[0], dev->DataBuf[1], dev->DataBuf[2]); + dev->DataReplyLeft = 3; + break; - ReplyISI->uBusTransferRate = dev->ATBusSpeed; - ReplyISI->uPreemptTimeOnBus = dev->BusOnTime; - ReplyISI->uTimeOffBus = dev->BusOffTime; - ReplyISI->cMailbox = dev->MailboxCount; - U32_TO_ADDR(ReplyISI->MailboxAddress, dev->MailboxOutAddr); + case CMD_RETSETUP: /* return Setup */ + ReplyISI = (ReplyInquireSetupInformation *) dev->DataBuf; + memset(ReplyISI, 0x00, sizeof(ReplyInquireSetupInformation)); - if (dev->get_ven_data) - dev->get_ven_data(dev); + ReplyISI->uBusTransferRate = dev->ATBusSpeed; + ReplyISI->uPreemptTimeOnBus = dev->BusOnTime; + ReplyISI->uTimeOffBus = dev->BusOffTime; + ReplyISI->cMailbox = dev->MailboxCount; + U32_TO_ADDR(ReplyISI->MailboxAddress, dev->MailboxOutAddr); - dev->DataReplyLeft = dev->CmdBuf[0]; - x54x_log("Return Setup Information: %d (length: %i)\n", dev->CmdBuf[0], sizeof(ReplyInquireSetupInformation)); - break; + if (dev->get_ven_data) + dev->get_ven_data(dev); - case CMD_ECHO: /* ECHO data */ - dev->DataBuf[0] = dev->CmdBuf[0]; - dev->DataReplyLeft = 1; - break; + dev->DataReplyLeft = dev->CmdBuf[0]; + x54x_log("Return Setup Information: %d (length: %i)\n", dev->CmdBuf[0], sizeof(ReplyInquireSetupInformation)); + break; - case CMD_WRITE_CH2: /* write channel 2 buffer */ - dev->DataReplyLeft = 0; - Address.hi = dev->CmdBuf[0]; - Address.mid = dev->CmdBuf[1]; - Address.lo = dev->CmdBuf[2]; - FIFOBuf = ADDR_TO_U32(Address); - x54x_log("Adaptec LocalRAM: Reading 64 bytes at %08X\n", FIFOBuf); - dma_bm_read(FIFOBuf, dev->dma_buffer, 64, dev->transfer_size); - break; + case CMD_ECHO: /* ECHO data */ + dev->DataBuf[0] = dev->CmdBuf[0]; + dev->DataReplyLeft = 1; + break; - case CMD_READ_CH2: /* write channel 2 buffer */ - dev->DataReplyLeft = 0; - Address.hi = dev->CmdBuf[0]; - Address.mid = dev->CmdBuf[1]; - Address.lo = dev->CmdBuf[2]; - FIFOBuf = ADDR_TO_U32(Address); - x54x_log("Adaptec LocalRAM: Writing 64 bytes at %08X\n", FIFOBuf); - dma_bm_write(FIFOBuf, dev->dma_buffer, 64, dev->transfer_size); - break; + case CMD_WRITE_CH2: /* write channel 2 buffer */ + dev->DataReplyLeft = 0; + Address.hi = dev->CmdBuf[0]; + Address.mid = dev->CmdBuf[1]; + Address.lo = dev->CmdBuf[2]; + FIFOBuf = ADDR_TO_U32(Address); + x54x_log("Adaptec LocalRAM: Reading 64 bytes at %08X\n", FIFOBuf); + dma_bm_read(FIFOBuf, dev->dma_buffer, 64, dev->transfer_size); + break; - case CMD_OPTIONS: /* Set adapter options */ - if (dev->CmdParam == 1) - dev->CmdParamLeft = dev->CmdBuf[0]; - dev->DataReplyLeft = 0; - break; + case CMD_READ_CH2: /* write channel 2 buffer */ + dev->DataReplyLeft = 0; + Address.hi = dev->CmdBuf[0]; + Address.mid = dev->CmdBuf[1]; + Address.lo = dev->CmdBuf[2]; + FIFOBuf = ADDR_TO_U32(Address); + x54x_log("Adaptec LocalRAM: Writing 64 bytes at %08X\n", FIFOBuf); + dma_bm_write(FIFOBuf, dev->dma_buffer, 64, dev->transfer_size); + break; - default: - if (dev->ven_cmds) - suppress = dev->ven_cmds(dev); - else { - dev->DataReplyLeft = 0; - dev->Status |= STAT_INVCMD; - } - break; - } - } + case CMD_OPTIONS: /* Set adapter options */ + if (dev->CmdParam == 1) + dev->CmdParamLeft = dev->CmdBuf[0]; + dev->DataReplyLeft = 0; + break; - if (dev->DataReplyLeft) - dev->Status |= STAT_DFULL; - else if (!dev->CmdParamLeft) - x54x_cmd_done(dev, suppress); - break; + default: + if (dev->ven_cmds) + suppress = dev->ven_cmds(dev); + else { + dev->DataReplyLeft = 0; + dev->Status |= STAT_INVCMD; + } + break; + } + } - case 2: - if (dev->flags & X54X_INT_GEOM_WRITABLE) - dev->Interrupt = val; - break; + if (dev->DataReplyLeft) + dev->Status |= STAT_DFULL; + else if (!dev->CmdParamLeft) + x54x_cmd_done(dev, suppress); + break; - case 3: - if (dev->flags & X54X_INT_GEOM_WRITABLE) - dev->Geometry = val; - break; + case 2: + if (dev->flags & X54X_INT_GEOM_WRITABLE) + dev->Interrupt = val; + break; + + case 3: + if (dev->flags & X54X_INT_GEOM_WRITABLE) + dev->Geometry = val; + break; + + default: + break; } } - static void x54x_outw(uint16_t port, uint16_t val, void *priv) { x54x_out(port, val & 0xFF, priv); } - static void x54x_outl(uint16_t port, uint32_t val, void *priv) { x54x_out(port, val & 0xFF, priv); } - static void x54x_writeb(uint32_t port, uint8_t val, void *priv) { x54x_out(port & 3, val, priv); } - static void x54x_writew(uint32_t port, uint16_t val, void *priv) { x54x_outw(port & 3, val, priv); } - static void x54x_writel(uint32_t port, uint32_t val, void *priv) { x54x_outl(port & 3, val, priv); } - static int x54x_is_32bit(x54x_t *dev) { int bit32 = 0; if (dev->card_bus & DEVICE_PCI) - bit32 = 1; + bit32 = 1; else if ((dev->card_bus & DEVICE_MCA) && (dev->flags & X54X_32BIT)) - bit32 = 1; + bit32 = 1; return bit32; } - void x54x_io_set(x54x_t *dev, uint32_t base, uint8_t len) { if (x54x_is_32bit(dev)) { - x54x_log("x54x: [PCI] Setting I/O handler at %04X\n", base); - io_sethandler(base, len, - x54x_in, x54x_inw, x54x_inl, + x54x_log("x54x: [PCI] Setting I/O handler at %04X\n", base); + io_sethandler(base, len, + x54x_in, x54x_inw, x54x_inl, x54x_out, x54x_outw, x54x_outl, dev); } else { - x54x_log("x54x: [ISA] Setting I/O handler at %04X\n", base); - io_sethandler(base, len, - x54x_in, x54x_inw, NULL, + x54x_log("x54x: [ISA] Setting I/O handler at %04X\n", base); + io_sethandler(base, len, + x54x_in, x54x_inw, NULL, x54x_out, x54x_outw, NULL, dev); } } - void x54x_io_remove(x54x_t *dev, uint32_t base, uint8_t len) { x54x_log("x54x: Removing I/O handler at %04X\n", base); if (x54x_is_32bit(dev)) { - io_removehandler(base, len, - x54x_in, x54x_inw, x54x_inl, - x54x_out, x54x_outw, x54x_outl, dev); + io_removehandler(base, len, + x54x_in, x54x_inw, x54x_inl, + x54x_out, x54x_outw, x54x_outl, dev); } else { - io_removehandler(base, len, - x54x_in, x54x_inw, NULL, - x54x_out, x54x_outw, NULL, dev); + io_removehandler(base, len, + x54x_in, x54x_inw, NULL, + x54x_out, x54x_outw, NULL, dev); } } - void x54x_mem_init(x54x_t *dev, uint32_t addr) { if (x54x_is_32bit(dev)) { - mem_mapping_add(&dev->mmio_mapping, addr, 0x20, - x54x_readb, x54x_readw, x54x_readl, - x54x_writeb, x54x_writew, x54x_writel, - NULL, MEM_MAPPING_EXTERNAL, dev); + mem_mapping_add(&dev->mmio_mapping, addr, 0x20, + x54x_readb, x54x_readw, x54x_readl, + x54x_writeb, x54x_writew, x54x_writel, + NULL, MEM_MAPPING_EXTERNAL, dev); } else { - mem_mapping_add(&dev->mmio_mapping, addr, 0x20, - x54x_readb, x54x_readw, NULL, - x54x_writeb, x54x_writew, NULL, - NULL, MEM_MAPPING_EXTERNAL, dev); + mem_mapping_add(&dev->mmio_mapping, addr, 0x20, + x54x_readb, x54x_readw, NULL, + x54x_writeb, x54x_writew, NULL, + NULL, MEM_MAPPING_EXTERNAL, dev); } } - void x54x_mem_enable(x54x_t *dev) { mem_mapping_enable(&dev->mmio_mapping); } - void x54x_mem_set_addr(x54x_t *dev, uint32_t base) { mem_mapping_set_addr(&dev->mmio_mapping, base, 0x20); } - void x54x_mem_disable(x54x_t *dev) { mem_mapping_disable(&dev->mmio_mapping); } - /* General initialization routine for all boards. */ void * x54x_init(const device_t *info) @@ -1935,59 +1900,58 @@ x54x_init(const device_t *info) /* Allocate control block and set up basic stuff. */ dev = malloc(sizeof(x54x_t)); - if (dev == NULL) return(dev); + if (dev == NULL) + return dev; memset(dev, 0x00, sizeof(x54x_t)); dev->type = info->local; - dev->card_bus = info->flags; + dev->card_bus = info->flags; dev->callback_phase = 0; - + timer_add(&dev->ResetCB, x54x_reset_poll, dev, 0); timer_add(&dev->timer, x54x_cmd_callback, dev, 1); dev->timer.period = 10.0; timer_set_delay_u64(&dev->timer, (uint64_t) (dev->timer.period * ((double) TIMER_USEC))); - if (x54x_is_32bit(dev)) - dev->transfer_size = 4; - else - dev->transfer_size = 2; + if (x54x_is_32bit(dev)) + dev->transfer_size = 4; + else + dev->transfer_size = 2; - return(dev); + return dev; } - void x54x_close(void *priv) { - x54x_t *dev = (x54x_t *)priv; + x54x_t *dev = (x54x_t *) priv; if (dev) { - /* Tell the timer to terminate. */ - timer_stop(&dev->timer); + /* Tell the timer to terminate. */ + timer_stop(&dev->timer); - /* Also terminate the reset callback timer. */ - timer_disable(&dev->ResetCB); + /* Also terminate the reset callback timer. */ + timer_disable(&dev->ResetCB); - dev->MailboxInit = dev->BIOSMailboxInit = 0; - dev->MailboxCount = dev->BIOSMailboxCount = 0; - dev->MailboxReq = dev->BIOSMailboxReq = 0; + dev->MailboxInit = dev->BIOSMailboxInit = 0; + dev->MailboxCount = dev->BIOSMailboxCount = 0; + dev->MailboxReq = dev->BIOSMailboxReq = 0; - if (dev->ven_data) - free(dev->ven_data); + if (dev->ven_data) + free(dev->ven_data); - if (dev->nvr != NULL) - free(dev->nvr); + if (dev->nvr != NULL) + free(dev->nvr); - free(dev); - dev = NULL; + free(dev); + dev = NULL; } } - void x54x_device_reset(void *priv) { - x54x_t *dev = (x54x_t *)priv; + x54x_t *dev = (x54x_t *) priv; x54x_reset_ctrl(dev, 1); diff --git a/src/sio/CMakeLists.txt b/src/sio/CMakeLists.txt index 482c2c2d6..15411d3e6 100644 --- a/src/sio/CMakeLists.txt +++ b/src/sio/CMakeLists.txt @@ -1,20 +1,20 @@ # -# 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. +# 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. +# This file is part of the 86Box distribution. # -# CMake build script. +# CMake build script. # -# Authors: David HrdliÄka, +# Authors: David HrdliÄka, # -# Copyright 2020,2021 David HrdliÄka. +# Copyright 2020-2021 David HrdliÄka. # -add_library(sio OBJECT sio_acc3221.c sio_f82c710.c sio_82091aa.c sio_fdc37c6xx.c - sio_fdc37c67x.c sio_fdc37c669.c sio_fdc37c93x.c sio_fdc37m60x.c +add_library(sio OBJECT sio_acc3221.c sio_ali5123.c sio_f82c710.c sio_82091aa.c + sio_fdc37c6xx.c sio_fdc37c67x.c sio_fdc37c669.c sio_fdc37c93x.c sio_fdc37m60x.c sio_it8661f.c sio_pc87306.c sio_pc87307.c sio_pc87309.c sio_pc87310.c sio_pc87311.c sio_pc87332.c sio_prime3b.c sio_prime3c.c @@ -23,4 +23,4 @@ add_library(sio OBJECT sio_acc3221.c sio_f82c710.c sio_82091aa.c sio_fdc37c6xx.c if(SIO_DETECT) target_sources(sio PRIVATE sio_detect.c) -endif() \ No newline at end of file +endif() diff --git a/src/sio/sio_82091aa.c b/src/sio/sio_82091aa.c index f266f0a40..cbe89c682 100644 --- a/src/sio/sio_82091aa.c +++ b/src/sio/sio_82091aa.c @@ -1,17 +1,18 @@ /* - * 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. + * 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. + * This file is part of the 86Box distribution. * - * Emulation of the Intel 82019AA Super I/O chip. + * Emulation of the Intel 82091AA Super I/O chip. * * * - * Author: Miran Grca, - * Copyright 2020 Miran Grca. + * Authors: Miran Grca, + * + * Copyright 2020 Miran Grca. */ #include #include @@ -34,186 +35,194 @@ #include <86box/fdc.h> #include <86box/sio.h> - -typedef struct { - uint8_t cur_reg, has_ide, - regs[81]; - uint16_t base_address; - fdc_t * fdc; - serial_t * uart[2]; +typedef struct i82091aa_t { + uint8_t cur_reg; + uint8_t has_ide; + uint8_t regs[81]; + uint16_t base_address; + fdc_t *fdc; + serial_t *uart[2]; } i82091aa_t; - static void fdc_handler(i82091aa_t *dev) { fdc_remove(dev->fdc); if (dev->regs[0x10] & 0x01) - fdc_set_base(dev->fdc, (dev->regs[0x10] & 0x02) ? 0x0370 : 0x03f0); + fdc_set_base(dev->fdc, (dev->regs[0x10] & 0x02) ? FDC_SECONDARY_ADDR : FDC_PRIMARY_ADDR); } - static void lpt1_handler(i82091aa_t *dev) { - uint16_t lpt_port = 0x378; + uint16_t lpt_port = LPT1_ADDR; lpt1_remove(); switch ((dev->regs[0x20] >> 1) & 0x03) { - case 0x00: - lpt_port = 0x378; - break; - case 1: - lpt_port = 0x278; - break; - case 2: - lpt_port = 0x3bc; - break; - case 3: - lpt_port = 0x000; - break; + case 0x00: + lpt_port = LPT1_ADDR; + break; + case 1: + lpt_port = LPT2_ADDR; + break; + case 2: + lpt_port = LPT_MDA_ADDR; + break; + case 3: + lpt_port = 0x000; + break; + + default: + break; } if ((dev->regs[0x20] & 0x01) && lpt_port) - lpt1_init(lpt_port); + lpt1_init(lpt_port); - lpt1_irq((dev->regs[0x20] & 0x08) ? 7 : 5); + lpt1_irq((dev->regs[0x20] & 0x08) ? LPT1_IRQ : LPT2_IRQ); } - static void serial_handler(i82091aa_t *dev, int uart) { - int reg = (0x30 + (uart << 4)); - uint16_t uart_port = 0x3f8; + int reg = (0x30 + (uart << 4)); + uint16_t uart_port = COM1_ADDR; serial_remove(dev->uart[uart]); switch ((dev->regs[reg] >> 1) & 0x07) { - case 0x00: - uart_port = 0x3f8; - break; - case 0x01: - uart_port = 0x2f8; - break; - case 0x02: - uart_port = 0x220; - break; - case 0x03: - uart_port = 0x228; - break; - case 0x04: - uart_port = 0x238; - break; - case 0x05: - uart_port = 0x2e8; - break; - case 0x06: - uart_port = 0x338; - break; - case 0x07: - uart_port = 0x3e8; - break; + case 0x00: + uart_port = COM1_ADDR; + break; + case 0x01: + uart_port = COM2_ADDR; + break; + case 0x02: + uart_port = 0x220; + break; + case 0x03: + uart_port = 0x228; + break; + case 0x04: + uart_port = 0x238; + break; + case 0x05: + uart_port = COM4_ADDR; + break; + case 0x06: + uart_port = 0x338; + break; + case 0x07: + uart_port = COM3_ADDR; + break; + + default: + break; } if (dev->regs[reg] & 0x01) - serial_setup(dev->uart[uart], uart_port, (dev->regs[reg] & 0x10) ? 4 : 3); + serial_setup(dev->uart[uart], uart_port, (dev->regs[reg] & 0x10) ? COM1_IRQ : COM2_IRQ); } - static void ide_handler(i82091aa_t *dev) { - ide_sec_disable(); - ide_set_base(1, (dev->regs[0x50] & 0x02) ? 0x170 : 0x1f0); - ide_set_side(1, (dev->regs[0x50] & 0x02) ? 0x376 : 0x3f6); - if (dev->regs[0x50] & 0x01) - ide_sec_enable(); -} + int board = dev->has_ide - 1; + ide_remove_handlers(board); + ide_set_base(board, (dev->regs[0x50] & 0x02) ? 0x170 : 0x1f0); + ide_set_side(board, (dev->regs[0x50] & 0x02) ? 0x376 : 0x3f6); + if (dev->regs[0x50] & 0x01) + ide_set_handlers(board); +} static void i82091aa_write(uint16_t port, uint8_t val, void *priv) { i82091aa_t *dev = (i82091aa_t *) priv; - uint8_t index, valxor; - uint8_t uart = (dev->cur_reg >> 4) - 0x03; - uint8_t *reg = &(dev->regs[dev->cur_reg]); + uint8_t index; + uint8_t valxor = 0; + uint8_t uart = (dev->cur_reg >> 4) - 0x03; + uint8_t *reg = &(dev->regs[dev->cur_reg]); index = (port & 1) ? 0 : 1; if (index) { - dev->cur_reg = val; - return; + dev->cur_reg = val; + return; } else if (dev->cur_reg < 0x51) - valxor = val ^ *reg; + valxor = val ^ *reg; else if (dev->cur_reg >= 0x51) - return; + return; - switch(dev->cur_reg) { - case 0x02: - *reg = (*reg & 0x78) | (val & 0x01); - break; - case 0x03: - *reg = (val & 0xf8); - break; - case 0x10: - *reg = (val & 0x83); - if (valxor & 0x03) - fdc_handler(dev); - break; - case 0x11: - *reg = (val & 0x0f); - if ((valxor & 0x04) && (val & 0x04)) - fdc_reset(dev->fdc); - break; - case 0x20: - *reg = (val & 0xef); - if (valxor & 0x07) - lpt1_handler(dev); - break; - case 0x21: - *reg = (val & 0x2f); - break; - case 0x30: case 0x40: - *reg = (val & 0x9f); - if (valxor & 0x1f) - serial_handler(dev, uart); - if (valxor & 0x80) - serial_set_clock_src(dev->uart[uart], (val & 0x80) ? 2000000.0 : (24000000.0 / 13.0)); - break; - case 0x31: case 0x41: - *reg = (val & 0x1f); - if ((valxor & 0x04) && (val & 0x04)) - serial_reset_port(dev->uart[uart]); - break; - case 0x50: - *reg = (val & 0x07); - if (dev->has_ide && (valxor & 0x03)) - ide_handler(dev); - break; + switch (dev->cur_reg) { + case 0x02: + *reg = (*reg & 0x78) | (val & 0x01); + break; + case 0x03: + *reg = (val & 0xf8); + break; + case 0x10: + *reg = (val & 0x83); + if (valxor & 0x03) + fdc_handler(dev); + break; + case 0x11: + *reg = (val & 0x0f); + if ((valxor & 0x04) && (val & 0x04)) + fdc_reset(dev->fdc); + break; + case 0x20: + *reg = (val & 0xef); + if (valxor & 0x07) + lpt1_handler(dev); + break; + case 0x21: + *reg = (val & 0x2f); + break; + case 0x30: + case 0x40: + *reg = (val & 0x9f); + if (valxor & 0x1f) + serial_handler(dev, uart); + if (valxor & 0x80) + serial_set_clock_src(dev->uart[uart], (val & 0x80) ? 2000000.0 : (24000000.0 / 13.0)); + break; + case 0x31: + case 0x41: + *reg = (val & 0x1f); + if ((valxor & 0x04) && (val & 0x04)) + serial_reset_port(dev->uart[uart]); + break; + case 0x50: + *reg = (val & 0x07); + if (dev->has_ide && (valxor & 0x03)) + ide_handler(dev); + break; + + default: + break; } } - uint8_t i82091aa_read(uint16_t port, void *priv) { - i82091aa_t *dev = (i82091aa_t *) priv; - uint8_t ret = 0xff, index; + const i82091aa_t *dev = (i82091aa_t *) priv; + uint8_t ret = 0xff; + uint8_t index; index = (port & 1) ? 0 : 1; if (index) - ret = dev->cur_reg; + ret = dev->cur_reg; else if (dev->cur_reg < 0x51) - ret = dev->regs[dev->cur_reg]; + ret = dev->regs[dev->cur_reg]; return ret; } - void i82091aa_reset(i82091aa_t *dev) { @@ -222,7 +231,7 @@ i82091aa_reset(i82091aa_t *dev) dev->regs[0x00] = 0xa0; dev->regs[0x10] = 0x01; dev->regs[0x31] = dev->regs[0x41] = 0x02; - dev->regs[0x50] = 0x01; + dev->regs[0x50] = 0x01; fdc_reset(dev->fdc); @@ -234,10 +243,9 @@ i82091aa_reset(i82091aa_t *dev) serial_set_clock_src(dev->uart[1], (24000000.0 / 13.0)); if (dev->has_ide) - ide_handler(dev); + ide_handler(dev); } - static void i82091aa_close(void *priv) { @@ -246,7 +254,6 @@ i82091aa_close(void *priv) free(dev); } - static void * i82091aa_init(const device_t *info) { @@ -258,52 +265,75 @@ i82091aa_init(const device_t *info) dev->uart[0] = device_add_inst(&ns16550_device, 1); dev->uart[1] = device_add_inst(&ns16550_device, 2); - dev->has_ide = !!(info->local & 0x200); + dev->has_ide = (info->local >> 9) & 0x03; i82091aa_reset(dev); dev->regs[0x02] = info->local & 0xff; if (info->local & 0x08) - dev->base_address = (info->local & 0x100) ? 0x0398 : 0x0024; + dev->base_address = (info->local & 0x100) ? 0x0398 : 0x0024; else - dev->base_address = (info->local & 0x100) ? 0x026e : 0x0022; + dev->base_address = (info->local & 0x100) ? 0x026e : 0x0022; io_sethandler(dev->base_address, 0x0002, - i82091aa_read, NULL, NULL, i82091aa_write, NULL, NULL, dev); + i82091aa_read, NULL, NULL, i82091aa_write, NULL, NULL, dev); return dev; } - const device_t i82091aa_device = { - "Intel 82091AA Super I/O", - "i82091aa", - 0, - 0x40, - i82091aa_init, i82091aa_close, NULL, - { NULL }, NULL, NULL, - NULL + .name = "Intel 82091AA Super I/O", + .internal_name = "i82091aa", + .flags = 0, + .local = 0x40, + .init = i82091aa_init, + .close = i82091aa_close, + .reset = NULL, + { .available = NULL }, + .speed_changed = NULL, + .force_redraw = NULL, + .config = NULL }; - const device_t i82091aa_398_device = { - "Intel 82091AA Super I/O (Port 398h)", - "i82091aa_398", - 0, - 0x148, - i82091aa_init, i82091aa_close, NULL, - { NULL }, NULL, NULL, - NULL + .name = "Intel 82091AA Super I/O (Port 398h)", + .internal_name = "i82091aa_398", + .flags = 0, + .local = 0x148, + .init = i82091aa_init, + .close = i82091aa_close, + .reset = NULL, + { .available = NULL }, + .speed_changed = NULL, + .force_redraw = NULL, + .config = NULL }; +const device_t i82091aa_ide_pri_device = { + .name = "Intel 82091AA Super I/O (With Primary IDE)", + .internal_name = "i82091aa_ide", + .flags = 0, + .local = 0x240, + .init = i82091aa_init, + .close = i82091aa_close, + .reset = NULL, + { .available = NULL }, + .speed_changed = NULL, + .force_redraw = NULL, + .config = NULL +}; const device_t i82091aa_ide_device = { - "Intel 82091AA Super I/O (With IDE)", - "i82091aa_ide", - 0, - 0x240, - i82091aa_init, i82091aa_close, NULL, - { NULL }, NULL, NULL, - NULL + .name = "Intel 82091AA Super I/O (With IDE)", + .internal_name = "i82091aa_ide", + .flags = 0, + .local = 0x440, + .init = i82091aa_init, + .close = i82091aa_close, + .reset = NULL, + { .available = NULL }, + .speed_changed = NULL, + .force_redraw = NULL, + .config = NULL }; diff --git a/src/sio/sio_acc3221.c b/src/sio/sio_acc3221.c index 17536690c..275d9ae2e 100644 --- a/src/sio/sio_acc3221.c +++ b/src/sio/sio_acc3221.c @@ -1,18 +1,18 @@ /* - * 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. + * 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. + * This file is part of the 86Box distribution. * - * Implementation of the ACC 3221-SP Super I/O Chip. + * Implementation of the ACC 3221-SP Super I/O Chip. * * * - * Authors: Sarah Walker, + * Authors: Sarah Walker, * - * Copyright 2019 Sarah Walker. + * Copyright 2019 Sarah Walker. */ #include #include @@ -31,144 +31,143 @@ #include <86box/fdd.h> #include <86box/fdc.h> #include <86box/sio.h> +#include <86box/plat_unused.h> -typedef struct acc3221_t -{ - int reg_idx; - uint8_t regs[256]; - fdc_t * fdc; - serial_t * uart[2]; +typedef struct acc3221_t { + int reg_idx; + uint8_t regs[256]; + fdc_t *fdc; + serial_t *uart[2]; } acc3221_t; - /* Configuration Register Index, BE (R/W): - Bit Function - 7 PIRQ 5 polarity. - 1 = active high, default - 0 = active low - 6 PIRQ 7 polarity. - 1 = active high, default - 0 = active low - 5 Primary Parallel Port Extended Mode - 0 = Compatible mode, default - 1 = Extended/Bidirectional mode. - 4 Primary Parallel Port Disable - 1 = Disable, 0 = Enable - Power Up Default is set by pin 120 - (3221-DP)/pin 96 (3221-SP) - 3 Primary Parallel Port Power Down - 1 = Power Down, default = 0 - 2** Secondary Parallel Port Extended - Mode - 0 = Compatible mode, default - 1 = Extended/Bidirectional mode. - 1** Secondary Parallel Port Disable - 1 = Disable, 0 = Enable - Power Up Default is set by pin 77 - (3221-DP) - 0** Secondary Parallel Port Power Down - 1 = Power Down - 0 = Enable, default + Bit Function + 7 PIRQ 5 polarity. + 1 = active high, default + 0 = active low + 6 PIRQ 7 polarity. + 1 = active high, default + 0 = active low + 5 Primary Parallel Port Extended Mode + 0 = Compatible mode, default + 1 = Extended/Bidirectional mode. + 4 Primary Parallel Port Disable + 1 = Disable, 0 = Enable + Power Up Default is set by pin 120 + (3221-DP)/pin 96 (3221-SP) + 3 Primary Parallel Port Power Down + 1 = Power Down, default = 0 + 2** Secondary Parallel Port Extended + Mode + 0 = Compatible mode, default + 1 = Extended/Bidirectional mode. + 1** Secondary Parallel Port Disable + 1 = Disable, 0 = Enable + Power Up Default is set by pin 77 + (3221-DP) + 0** Secondary Parallel Port Power Down + 1 = Power Down + 0 = Enable, default Note: Power Up not applicable to 3221-EP. */ #define REG_BE_LPT1_DISABLE (3 << 3) -#define REG_BE_LPT2_DISABLE (3 << 0) /* 3221-DP/EP only */ +#define REG_BE_LPT2_DISABLE (3 << 0) /* 3221-DP/EP only */ /* Configuration Register Index, BF (R/W): - Bit Function - 7-0 The 8 most significant address bits of - the primary parallel port (A9-2) - Default 9E (LPT2, at 278-27B) */ + Bit Function + 7-0 The 8 most significant address bits of + the primary parallel port (A9-2) + Default 9E (LPT2, at 278-27B) */ /* Configuration Register Index, DA (R/W)**: - Bit Function - 7-0 The 8 most significant address bits of - the secondary parallel port (A9-2) - Default DE (LPT1, at 378-37B) */ + Bit Function + 7-0 The 8 most significant address bits of + the secondary parallel port (A9-2) + Default DE (LPT1, at 378-37B) */ /* Configuration Register Index, DB (R/W): - Bit Function - 7 SIRQ4 polarity. - 1 = active high; default - 0 = active low - 6 SIRQ3 polarity. - 1 = active high; default - 0 = active low - 5 SXTAL clock off. 1 = SCLK off, - 0 = SCKL on, default - 4 Primary serial port disable - 1 = Disable, 0 = Enable - Power Up default is set by pin 116 - (3221-DP)/pin 93 (3221-SP) - 3 Primary serial port power down - 1 = Power down, 0 = Enable - Power Up default is set by pin 116 - (3221-DP)/pin 93 (3221-SP) - 2 Reserved - 1 Secondary serial port disable - 1 = Disable, 0 = Enable - Power Up default is set by pin 121 - (3221-DP)/pin 97 (3221-SP) - 0 Secondary serial port power down - 1 = Power down, 0 = Enable - Power Up default is set by pin 121 - (3221-DP)/pin 97 (3221-SP) + Bit Function + 7 SIRQ4 polarity. + 1 = active high; default + 0 = active low + 6 SIRQ3 polarity. + 1 = active high; default + 0 = active low + 5 SXTAL clock off. 1 = SCLK off, + 0 = SCKL on, default + 4 Primary serial port disable + 1 = Disable, 0 = Enable + Power Up default is set by pin 116 + (3221-DP)/pin 93 (3221-SP) + 3 Primary serial port power down + 1 = Power down, 0 = Enable + Power Up default is set by pin 116 + (3221-DP)/pin 93 (3221-SP) + 2 Reserved + 1 Secondary serial port disable + 1 = Disable, 0 = Enable + Power Up default is set by pin 121 + (3221-DP)/pin 97 (3221-SP) + 0 Secondary serial port power down + 1 = Power down, 0 = Enable + Power Up default is set by pin 121 + (3221-DP)/pin 97 (3221-SP) Note: Power Up not applicable to 3221-EP. */ #define REG_DB_SERIAL1_DISABLE (3 << 3) #define REG_DB_SERIAL2_DISABLE (3 << 0) /* Configuration Register Index, DC (R/W): - Bit Function - 7-1 The MSB of the Primary Serial Port - Address (bits A9-3). - Default = 7F (COM1, at 3F8-3FF). - 0 When this bit is set to 1, bit A2 of - primary parallel port is decoded. - Default is 0. */ + Bit Function + 7-1 The MSB of the Primary Serial Port + Address (bits A9-3). + Default = 7F (COM1, at 3F8-3FF). + 0 When this bit is set to 1, bit A2 of + primary parallel port is decoded. + Default is 0. */ /* Configuration Register Index, DD (R/W): - Bit Function - 7-1 The MSB of the Secondary Serial Port - Address (bits A9-3). - Default = 5F (COM2, at 2F8-2FF). - 0** When this bit is set to 1, bit A2 of - secondary parallel port is decoded. - Default is 0. */ + Bit Function + 7-1 The MSB of the Secondary Serial Port + Address (bits A9-3). + Default = 5F (COM2, at 2F8-2FF). + 0** When this bit is set to 1, bit A2 of + secondary parallel port is decoded. + Default is 0. */ /* Configuration Register Index, DE (R/W): - Bit Function - 7-6 SIRQ3 source - b7 b6 - 0 0 Disabled, tri-stated - 0 1 Disabled, tri-stated** - 1 0 Primary serial port - 1 1 Secondary serial port, - default - 5-4 SIRQ4 source - b5 b4 - 0 0 Disabled, tri-stated - 0 1 Disabled, tri-stated** - 1 0 Primary serial port, - default - 1 1 Secondary serial port + Bit Function + 7-6 SIRQ3 source + b7 b6 + 0 0 Disabled, tri-stated + 0 1 Disabled, tri-stated** + 1 0 Primary serial port + 1 1 Secondary serial port, + default + 5-4 SIRQ4 source + b5 b4 + 0 0 Disabled, tri-stated + 0 1 Disabled, tri-stated** + 1 0 Primary serial port, + default + 1 1 Secondary serial port - 3-2** PIRQ7 source - b3 b2 - 0 0 Diabled, tri-stated, - default - 0 1 Primary serial port - 1 0 Primary parallel port - 1 1 Secondary parallel - port + 3-2** PIRQ7 source + b3 b2 + 0 0 Diabled, tri-stated, + default + 0 1 Primary serial port + 1 0 Primary parallel port + 1 1 Secondary parallel + port Note: Bits 3-2 are reserved in 3221-SP. - 1-0 PIRQ5 source - b1 b0 - 0 0 Disabled, tri-stated - 0 1 Secondary serial port - 1 0 Primary parallel port, - default - 1 1 Secondary parallel - port** */ + 1-0 PIRQ5 source + b1 b0 + 0 0 Disabled, tri-stated + 0 1 Secondary serial port + 1 0 Primary parallel port, + default + 1 1 Secondary parallel + port** */ #define REG_DE_SIRQ3_SOURCE (3 << 6) #define REG_DE_SIRQ3_SERIAL1 (1 << 6) #define REG_DE_SIRQ3_SERIAL2 (3 << 6) @@ -185,132 +184,130 @@ typedef struct acc3221_t #define REG_DE_PIRQ5_LPT2 (3 << 0) /* Configuration Register Index, DF (R/W)**: - Bit Function - 7-6 Reserved - 5 RTC interface disable - 1 = /RTCCS disabled - 0 = /RTCCS enabled, default - 4 Disable Modem Select - 1 = Moden CS disabled, default - 0 = Modem CS enabled + Bit Function + 7-6 Reserved + 5 RTC interface disable + 1 = /RTCCS disabled + 0 = /RTCCS enabled, default + 4 Disable Modem Select + 1 = Moden CS disabled, default + 0 = Modem CS enabled 3-2 - b3 b2 - 1 1 Reserved - 1 0 Modem port address - = 3E8-3EF (default) - 0 1 Modem port address: - 2F8-2FF - 0 0 Modem port address: - 3F8-3FF + b3 b2 + 1 1 Reserved + 1 0 Modem port address + = 3E8-3EF (default) + 0 1 Modem port address: + 2F8-2FF + 0 0 Modem port address: + 3F8-3FF 1-0 - b1 b0 - 1 1 Reserved - 1 0 Mode 2, EISA Mode - 0 1 Mode 1, AT BUS, - 0 0 Mode 0, Two parallel - ports, default */ + b1 b0 + 1 1 Reserved + 1 0 Mode 2, EISA Mode + 0 1 Mode 1, AT BUS, + 0 0 Mode 0, Two parallel + ports, default */ /* Configuration Register Index, FA (R/W)**: - Bit Function - 7 General purpose I/O register, Bit 7 - 6 General purpose I/O register, Bit 6 - 5 General purpose I/O register, Bit 5 - 4 General purpose I/O register, Bit 4 - 3 General purpose I/O register, Bit 3 - 2 General purpose I/O register, Bit 2 - 1 General purpose I/O register, Bit 1 - 0 General purpose I/O register, Bit 0 */ + Bit Function + 7 General purpose I/O register, Bit 7 + 6 General purpose I/O register, Bit 6 + 5 General purpose I/O register, Bit 5 + 4 General purpose I/O register, Bit 4 + 3 General purpose I/O register, Bit 3 + 2 General purpose I/O register, Bit 2 + 1 General purpose I/O register, Bit 1 + 0 General purpose I/O register, Bit 0 */ /* Configuration Register Index, FB (R/W)**: - Bit Function - 7 Reserved - 6** 0/2 EXG (Read Only) - In mode 1 and mode 2 - operation, when the third - floppy drive is installed, pin - EXTFDD should be pulled - high to enable the third floppy - drive or be pulled low to - disable the third floppy drive. - 1 = Third floppy drive enabled - 0 = Third floppy drive disabled - 5** EXTFDD (Read Only) - In mode 1 and mode 2 - operation, when the third - floppy drive is installed and - pin 0/2 EXG is pulled high, - the third floppy drive becomes - the bootable drive (drive 0). - When pi 0/2 EXG is pulled low, - the third floppy drive acts as - drive 2. - 1 = Third floppy drive as drive 0 (bootable) - 0 = Third floppy drive as drive 2 - 4** MS - In mode 1 and mode 2, t his bit is to - control the output pin MS to support a - special 3 1/2", 1.2M drive. When this - bit is set to high (1), the MS pin sends - a low signal. When this bit is set to - low (0), the MS pin sends a high - signal to support a 3 1/2", 1.2M drive. - 3 FDC, Clock disable - 0 = enable, default - 1 = disable - 2 Reserved - 1 FDC disable - 0 = enable, 1= disable - Power Upd efault set by pin 117 (3221- - DP)/pin 94 (3221-SP) - 0 FDC address - 0 = Primary, default - 1 = Secondary + Bit Function + 7 Reserved + 6** 0/2 EXG (Read Only) + In mode 1 and mode 2 + operation, when the third + floppy drive is installed, pin + EXTFDD should be pulled + high to enable the third floppy + drive or be pulled low to + disable the third floppy drive. + 1 = Third floppy drive enabled + 0 = Third floppy drive disabled + 5** EXTFDD (Read Only) + In mode 1 and mode 2 + operation, when the third + floppy drive is installed and + pin 0/2 EXG is pulled high, + the third floppy drive becomes + the bootable drive (drive 0). + When pi 0/2 EXG is pulled low, + the third floppy drive acts as + drive 2. + 1 = Third floppy drive as drive 0 (bootable) + 0 = Third floppy drive as drive 2 + 4** MS + In mode 1 and mode 2, t his bit is to + control the output pin MS to support a + special 3 1/2", 1.2M drive. When this + bit is set to high (1), the MS pin sends + a low signal. When this bit is set to + low (0), the MS pin sends a high + signal to support a 3 1/2", 1.2M drive. + 3 FDC, Clock disable + 0 = enable, default + 1 = disable + 2 Reserved + 1 FDC disable + 0 = enable, 1= disable + Power Upd efault set by pin 117 (3221- + DP)/pin 94 (3221-SP) + 0 FDC address + 0 = Primary, default + 1 = Secondary Note: Bits 6-4 are reserved in 3221-SP. */ #define REG_FB_FDC_DISABLE (1 << 1) /* Configuration Register Index, FB (R/W)**: - Bit Function - 7** Disable general chip select 1 - 1 = disable, default - 0 = enable - 6** Disable general chip select 2 - 1 = disable, default - 0 = enable - 5** Enable SA2 decoding for general chip - select 1 - 1 = enable - 0 = disable, default - 4** Enable SA2 decoding for general chip - select 2 - 1 = enable - 0 = disable, default - 3 Reserved - 2 IDE XT selected - 0 = IDE AT interface, default - 1 = IDE XT interface - 1 IDE disable, 1 = IDE disable - 0 = IDE enable - Power Up default set by pin 13 (3221- - DP)/pin 13 (3221-SP) - 0 Secondary IDE - 1 = secondary - 0 = primary, default + Bit Function + 7** Disable general chip select 1 + 1 = disable, default + 0 = enable + 6** Disable general chip select 2 + 1 = disable, default + 0 = enable + 5** Enable SA2 decoding for general chip + select 1 + 1 = enable + 0 = disable, default + 4** Enable SA2 decoding for general chip + select 2 + 1 = enable + 0 = disable, default + 3 Reserved + 2 IDE XT selected + 0 = IDE AT interface, default + 1 = IDE XT interface + 1 IDE disable, 1 = IDE disable + 0 = IDE enable + Power Up default set by pin 13 (3221- + DP)/pin 13 (3221-SP) + 0 Secondary IDE + 1 = secondary + 0 = primary, default Note: Bits 6-4 are reserved in 3221-SP. */ #define REG_FE_IDE_DISABLE (1 << 1) - static void acc3221_lpt_handle(acc3221_t *dev) { lpt1_remove(); if (!(dev->regs[0xbe] & REG_BE_LPT1_DISABLE)) - lpt1_init(dev->regs[0xbf] << 2); + lpt1_init(dev->regs[0xbf] << 2); } - static void acc3221_serial1_handler(acc3221_t *dev) { @@ -319,16 +316,15 @@ acc3221_serial1_handler(acc3221_t *dev) serial_remove(dev->uart[0]); if (!(dev->regs[0xdb] & REG_DB_SERIAL1_DISABLE)) { - com_addr = ((dev->regs[0xdc] & 0xfe) << 2); + com_addr = ((dev->regs[0xdc] & 0xfe) << 2); - if ((dev->regs[0xde] & REG_DE_SIRQ3_SOURCE) == REG_DE_SIRQ3_SERIAL1) - serial_setup(dev->uart[0], com_addr, 3); - else if ((dev->regs[0xde] & REG_DE_SIRQ4_SOURCE) == REG_DE_SIRQ4_SERIAL1) - serial_setup(dev->uart[0], com_addr, 4); + if ((dev->regs[0xde] & REG_DE_SIRQ3_SOURCE) == REG_DE_SIRQ3_SERIAL1) + serial_setup(dev->uart[0], com_addr, 3); + else if ((dev->regs[0xde] & REG_DE_SIRQ4_SOURCE) == REG_DE_SIRQ4_SERIAL1) + serial_setup(dev->uart[0], com_addr, 4); } } - static void acc3221_serial2_handler(acc3221_t *dev) { @@ -337,112 +333,112 @@ acc3221_serial2_handler(acc3221_t *dev) serial_remove(dev->uart[1]); if (!(dev->regs[0xdb] & REG_DB_SERIAL2_DISABLE)) { - com_addr = ((dev->regs[0xdd] & 0xfe) << 2); + com_addr = ((dev->regs[0xdd] & 0xfe) << 2); - if ((dev->regs[0xde] & REG_DE_SIRQ3_SOURCE) == REG_DE_SIRQ3_SERIAL2) - serial_setup(dev->uart[1], com_addr, 3); - else if ((dev->regs[0xde] & REG_DE_SIRQ4_SOURCE) == REG_DE_SIRQ4_SERIAL2) - serial_setup(dev->uart[1], com_addr, 4); - else if ((dev->regs[0xde] & REG_DE_PIRQ5_SOURCE) == REG_DE_PIRQ5_SERIAL2) - serial_setup(dev->uart[1], com_addr, 5); + if ((dev->regs[0xde] & REG_DE_SIRQ3_SOURCE) == REG_DE_SIRQ3_SERIAL2) + serial_setup(dev->uart[1], com_addr, 3); + else if ((dev->regs[0xde] & REG_DE_SIRQ4_SOURCE) == REG_DE_SIRQ4_SERIAL2) + serial_setup(dev->uart[1], com_addr, 4); + else if ((dev->regs[0xde] & REG_DE_PIRQ5_SOURCE) == REG_DE_PIRQ5_SERIAL2) + serial_setup(dev->uart[1], com_addr, 5); } } - -static void -acc3221_write(uint16_t addr, uint8_t val, void *p) +static void +acc3221_write(uint16_t addr, uint8_t val, void *priv) { - acc3221_t *dev = (acc3221_t *)p; - uint8_t old; + acc3221_t *dev = (acc3221_t *) priv; + uint8_t old; if (!(addr & 1)) - dev->reg_idx = val; + dev->reg_idx = val; else { - old = dev->regs[dev->reg_idx]; - dev->regs[dev->reg_idx] = val; + old = dev->regs[dev->reg_idx]; + dev->regs[dev->reg_idx] = val; - switch (dev->reg_idx) { - case 0xbe: - if ((old ^ val) & REG_BE_LPT1_DISABLE) - acc3221_lpt_handle(dev); - break; + switch (dev->reg_idx) { + case 0xbe: + if ((old ^ val) & REG_BE_LPT1_DISABLE) + acc3221_lpt_handle(dev); + break; - case 0xbf: - if (old != val) - acc3221_lpt_handle(dev); - break; + case 0xbf: + if (old != val) + acc3221_lpt_handle(dev); + break; - case 0xdb: - if ((old ^ val) & REG_DB_SERIAL2_DISABLE) - acc3221_serial2_handler(dev); - if ((old ^ val) & REG_DB_SERIAL1_DISABLE) - acc3221_serial1_handler(dev); - break; + case 0xdb: + if ((old ^ val) & REG_DB_SERIAL2_DISABLE) + acc3221_serial2_handler(dev); + if ((old ^ val) & REG_DB_SERIAL1_DISABLE) + acc3221_serial1_handler(dev); + break; - case 0xdc: - if (old != val) - acc3221_serial1_handler(dev); - break; + case 0xdc: + if (old != val) + acc3221_serial1_handler(dev); + break; - case 0xdd: - if (old != val) - acc3221_serial2_handler(dev); - break; + case 0xdd: + if (old != val) + acc3221_serial2_handler(dev); + break; - case 0xde: - if ((old ^ val) & (REG_DE_SIRQ3_SOURCE | REG_DE_SIRQ4_SOURCE)) { - acc3221_serial2_handler(dev); - acc3221_serial1_handler(dev); - } - break; + case 0xde: + if ((old ^ val) & (REG_DE_SIRQ3_SOURCE | REG_DE_SIRQ4_SOURCE)) { + acc3221_serial2_handler(dev); + acc3221_serial1_handler(dev); + } + break; - case 0xfb: - if ((old ^ val) & REG_FB_FDC_DISABLE) { - fdc_remove(dev->fdc); - if (!(dev->regs[0xfb] & REG_FB_FDC_DISABLE)) - fdc_set_base(dev->fdc, 0x03f0); - } - break; + case 0xfb: + if ((old ^ val) & REG_FB_FDC_DISABLE) { + fdc_remove(dev->fdc); + if (!(dev->regs[0xfb] & REG_FB_FDC_DISABLE)) + fdc_set_base(dev->fdc, FDC_PRIMARY_ADDR); + } + break; - case 0xfe: - if ((old ^ val) & REG_FE_IDE_DISABLE) { - ide_pri_disable(); - if (!(dev->regs[0xfe] & REG_FE_IDE_DISABLE)) - ide_pri_enable(); - } - break; - } + case 0xfe: + if ((old ^ val) & REG_FE_IDE_DISABLE) { + ide_pri_disable(); + if (!(dev->regs[0xfe] & REG_FE_IDE_DISABLE)) + ide_pri_enable(); + } + break; + + default: + break; + } } } - -static uint8_t -acc3221_read(uint16_t addr, void *p) +static uint8_t +acc3221_read(uint16_t addr, void *priv) { - acc3221_t *dev = (acc3221_t *)p; + const acc3221_t *dev = (acc3221_t *) priv; if (!(addr & 1)) - return dev->reg_idx; + return dev->reg_idx; if (dev->reg_idx < 0xbc) - return 0xff; + return 0xff; return dev->regs[dev->reg_idx]; } - static void acc3221_reset(acc3221_t *dev) { serial_remove(dev->uart[0]); - serial_setup(dev->uart[0], SERIAL1_ADDR, SERIAL1_IRQ); + serial_setup(dev->uart[0], COM1_ADDR, COM1_IRQ); serial_remove(dev->uart[1]); - serial_setup(dev->uart[1], SERIAL2_ADDR, SERIAL2_IRQ); - + serial_setup(dev->uart[1], COM2_ADDR, COM2_IRQ); + lpt1_remove(); - lpt1_init(0x378); - lpt1_irq(7); + lpt1_init(LPT1_ADDR); + lpt1_irq(LPT1_IRQ); fdc_reset(dev->fdc); } @@ -455,9 +451,8 @@ acc3221_close(void *priv) free(dev); } - static void * -acc3221_init(const device_t *info) +acc3221_init(UNUSED(const device_t *info)) { acc3221_t *dev = (acc3221_t *) malloc(sizeof(acc3221_t)); memset(dev, 0, sizeof(acc3221_t)); @@ -465,22 +460,25 @@ acc3221_init(const device_t *info) dev->fdc = device_add(&fdc_at_device); dev->uart[0] = device_add_inst(&ns16450_device, 1); - dev->uart[1] = device_add_inst(&ns16450_device, 2); + dev->uart[1] = device_add_inst(&ns16450_device, 2); - io_sethandler(0x00f2, 0x0002, acc3221_read, NULL, NULL, acc3221_write, NULL, NULL, dev); + io_sethandler(0x00f2, 0x0002, acc3221_read, NULL, NULL, acc3221_write, NULL, NULL, dev); acc3221_reset(dev); return dev; } - const device_t acc3221_device = { - "ACC 3221-SP Super I/O", - "acc3221", - 0, - 0, - acc3221_init, acc3221_close, NULL, - { NULL }, NULL, NULL, - NULL + .name = "ACC 3221-SP Super I/O", + .internal_name = "acc3221", + .flags = 0, + .local = 0, + .init = acc3221_init, + .close = acc3221_close, + .reset = NULL, + { .available = NULL }, + .speed_changed = NULL, + .force_redraw = NULL, + .config = NULL }; diff --git a/src/sio/sio_ali5123.c b/src/sio/sio_ali5123.c new file mode 100644 index 000000000..78c585c11 --- /dev/null +++ b/src/sio/sio_ali5123.c @@ -0,0 +1,499 @@ +/* + * 86Box A hypervisor and IBM PC system emulator that specializes in + * running old operating systems and software designed for IBM + * PC systems and compatibles from 1981 through fairly recent + * system designs based on the PCI bus. + * + * This file is part of the 86Box distribution. + * + * Implementation of the ALi M5123/1543C Super I/O Chip. + * + * + * + * Authors: Miran Grca, + * + * Copyright 2016-2018 Miran Grca. + */ +#include +#include +#include +#include +#include +#include <86box/86box.h> +#include <86box/io.h> +#include <86box/timer.h> +#include <86box/device.h> +#include <86box/pic.h> +#include <86box/pci.h> +#include <86box/keyboard.h> +#include <86box/lpt.h> +#include <86box/serial.h> +#include <86box/hdc.h> +#include <86box/hdc_ide.h> +#include <86box/fdd.h> +#include <86box/fdc.h> +#include "cpu.h" +#include <86box/sio.h> + +#define AB_RST 0x80 + +typedef struct ali5123_t { + uint8_t chip_id; + uint8_t is_apm; + uint8_t tries; + uint8_t regs[48]; + uint8_t ld_regs[13][256]; + int locked; + int cur_reg; + fdc_t *fdc; + serial_t *uart[3]; +} ali5123_t; + +static void ali5123_write(uint16_t port, uint8_t val, void *priv); +static uint8_t ali5123_read(uint16_t port, void *priv); + +static uint16_t +make_port(ali5123_t *dev, uint8_t ld) +{ + uint16_t r0 = dev->ld_regs[ld][0x60]; + uint16_t r1 = dev->ld_regs[ld][0x61]; + + uint16_t p = (r0 << 8) + r1; + + return p; +} + +static void +ali5123_fdc_handler(ali5123_t *dev) +{ + uint16_t ld_port = 0; + uint8_t global_enable = !(dev->regs[0x22] & (1 << 0)); + uint8_t local_enable = !!dev->ld_regs[0][0x30]; + + fdc_remove(dev->fdc); + if (global_enable && local_enable) { + ld_port = make_port(dev, 0) & 0xFFF8; + if ((ld_port >= 0x0100) && (ld_port <= 0x0FF8)) + fdc_set_base(dev->fdc, ld_port); + } +} + +static void +ali5123_lpt_handler(ali5123_t *dev) +{ + uint16_t ld_port = 0; + uint8_t global_enable = !(dev->regs[0x22] & (1 << 3)); + uint8_t local_enable = !!dev->ld_regs[3][0x30]; + uint8_t lpt_irq = dev->ld_regs[3][0x70]; + + if (lpt_irq > 15) + lpt_irq = 0xff; + + lpt1_remove(); + if (global_enable && local_enable) { + ld_port = make_port(dev, 3) & 0xFFFC; + if ((ld_port >= 0x0100) && (ld_port <= 0x0FFC)) + lpt1_init(ld_port); + } + lpt1_irq(lpt_irq); +} + +static void +ali5123_serial_handler(ali5123_t *dev, int uart) +{ + uint8_t uart_nos[2][3]= { { 4, 5, 0xb }, { 4, 0xb, 5 } }; + uint16_t ld_port = 0; + uint8_t uart_no = uart_nos[!!(dev->regs[0x2d] & 0x20)][uart]; + uint8_t global_enable = !(dev->regs[0x22] & (1 << (4 + uart))); + uint8_t local_enable = !!dev->ld_regs[uart_no][0x30]; + uint8_t mask = (uart == 1) ? 0x04 : 0x05; + + serial_remove(dev->uart[uart]); + if (global_enable && local_enable) { + ld_port = make_port(dev, uart_no) & 0xFFF8; + if ((ld_port >= 0x0100) && (ld_port <= 0x0FF8)) + serial_setup(dev->uart[uart], ld_port, dev->ld_regs[uart_no][0x70]); + } + + switch (dev->ld_regs[uart_no][0xf0] & mask) { + case 0x00: + serial_set_clock_src(dev->uart[uart], 1843200.0); + break; + case 0x04: + serial_set_clock_src(dev->uart[uart], 8000000.0); + break; + case 0x01: + case 0x05: + serial_set_clock_src(dev->uart[uart], 2000000.0); + break; + + default: + break; + } +} + +static void +ali5123_reset(ali5123_t *dev) +{ + memset(dev->regs, 0, 48); + + dev->regs[0x20] = 0x43; + dev->regs[0x21] = 0x15; + dev->regs[0x2d] = 0x20; + + for (uint8_t i = 0; i < 13; i++) + memset(dev->ld_regs[i], 0, 256); + + /* Logical device 0: FDD */ + dev->ld_regs[0][0x60] = 3; + dev->ld_regs[0][0x61] = 0xf0; + dev->ld_regs[0][0x70] = 6; + dev->ld_regs[0][0x74] = 2; + dev->ld_regs[0][0xf0] = 0x08; + dev->ld_regs[0][0xf2] = 0xff; + + /* Logical device 3: Parallel Port */ + dev->ld_regs[3][0x60] = 3; + dev->ld_regs[3][0x61] = 0x78; + dev->ld_regs[3][0x70] = 5; + dev->ld_regs[3][0x74] = 4; + dev->ld_regs[3][0xf0] = 0x8c; + dev->ld_regs[3][0xf1] = 0x85; + + /* Logical device 4: Serial Port 1 */ + dev->ld_regs[4][0x60] = 3; + dev->ld_regs[4][0x61] = 0xf8; + dev->ld_regs[4][0x70] = 4; + dev->ld_regs[4][0xf2] = 0x0c; + serial_setup(dev->uart[0], COM1_ADDR, dev->ld_regs[4][0x70]); + + /* Logical device 5: Serial Port 2 - HP like module */ + dev->ld_regs[5][0x60] = 3; + dev->ld_regs[5][0x61] = 0xe8; + dev->ld_regs[5][0x70] = 9; + dev->ld_regs[5][0xf0] = 0x80; + dev->ld_regs[4][0xf2] = 0x0c; + serial_setup(dev->uart[1], 0x03e8, dev->ld_regs[5][0x70]); + + /* Logical device 7: Keyboard */ + dev->ld_regs[7][0x30] = 1; + dev->ld_regs[7][0x70] = 1; + /* TODO: Register F0 bit 6: 0 = PS/2, 1 = AT */ + + /* Logical device B: Serial Port 2 - HP like module */ + dev->ld_regs[0x0b][0x60] = 2; + dev->ld_regs[0x0b][0x61] = 0xf8; + dev->ld_regs[0x0b][0x70] = 3; + dev->ld_regs[0x0b][0xf0] = 0x00; + dev->ld_regs[0x0b][0xf2] = 0x0c; + serial_setup(dev->uart[2], COM2_ADDR, dev->ld_regs[0x0b][0x70]); + + /* Logical device C: Hotkey */ + dev->ld_regs[0x0c][0xf0] = 0x35; + dev->ld_regs[0x0c][0xf1] = 0x14; + dev->ld_regs[0x0c][0xf2] = 0x11; + dev->ld_regs[0x0c][0xf3] = 0x71; + dev->ld_regs[0x0c][0xf4] = 0x42; + + ali5123_lpt_handler(dev); + ali5123_serial_handler(dev, 0); + ali5123_serial_handler(dev, 1); + ali5123_serial_handler(dev, 2); + + fdc_reset(dev->fdc); + ali5123_fdc_handler(dev); + + dev->locked = 0; +} + +static void +ali5123_write(uint16_t port, uint8_t val, void *priv) +{ + ali5123_t *dev = (ali5123_t *) priv; + uint8_t index = (port & 1) ? 0 : 1; + uint8_t valxor = 0x00; + uint8_t cur_ld = dev->regs[7]; + + if (index) { + if (((val == 0x51) && (!dev->tries) && (!dev->locked)) || ((val == 0x23) && (dev->tries) && (!dev->locked))) { + if (dev->tries) { + dev->locked = 1; + fdc_3f1_enable(dev->fdc, 0); + dev->tries = 0; + } else + dev->tries++; + } else { + if (dev->locked) { + if (val == 0xbb) { + dev->locked = 0; + fdc_3f1_enable(dev->fdc, 1); + return; + } + dev->cur_reg = val; + } else { + if (dev->tries) + dev->tries = 0; + } + } + return; + } else { + if (dev->locked) { + if (dev->cur_reg < 48) { + valxor = val ^ dev->regs[dev->cur_reg]; + if ((val >= 0x1f) && (val <= 0x21)) + return; + dev->regs[dev->cur_reg] = val; + } else { + valxor = val ^ dev->ld_regs[cur_ld][dev->cur_reg]; + if (((dev->cur_reg & 0xf0) == 0x70) && (cur_ld < 4)) + return; + /* Block writes to some logical devices. */ + if (cur_ld > 0x0c) + return; + else + switch (cur_ld) { + case 0x01: + case 0x02: + case 0x06: + case 0x08 ... 0x0a: + return; + case 0x07: + if (dev->cur_reg == 0xf0) + val &= 0xbf; + break; + + default: + break; + } + dev->ld_regs[cur_ld][dev->cur_reg] = val; + } + } else + return; + } + + if (dev->cur_reg < 48) { + switch (dev->cur_reg) { + case 0x02: + if (val & 0x01) + ali5123_reset(dev); + dev->regs[0x02] = 0x00; + break; + case 0x22: + if (valxor & 0x01) + ali5123_fdc_handler(dev); + if (valxor & 0x08) + ali5123_lpt_handler(dev); + if (valxor & 0x10) + ali5123_serial_handler(dev, 0); + if (valxor & 0x20) + ali5123_serial_handler(dev, 1); + if (valxor & 0x40) + ali5123_serial_handler(dev, 2); + break; + case 0x2d: + if (valxor & 0x20) { + ali5123_serial_handler(dev, 1); + ali5123_serial_handler(dev, 2); + } + break; + + default: + break; + } + + return; + } + + cur_ld = dev->regs[7]; + switch (cur_ld) { + case 0: + /* FDD */ + switch (dev->cur_reg) { + case 0x30: + case 0x60: + case 0x61: + if ((dev->cur_reg == 0x30) && (val & 0x01)) + dev->regs[0x22] &= ~0x01; + if (valxor) + ali5123_fdc_handler(dev); + break; + case 0xf0: + if (valxor & 0x08) + fdc_update_enh_mode(dev->fdc, !(val & 0x08)); + if (valxor & 0x10) + fdc_set_swap(dev->fdc, (val & 0x10) >> 4); + break; + case 0xf1: + if (valxor & 0xc) + fdc_update_densel_force(dev->fdc, (val & 0xc) >> 2); + break; + case 0xf4: + if (valxor & 0x08) + fdc_update_drvrate(dev->fdc, 0, (val & 0x08) >> 3); + break; + case 0xf5: + if (valxor & 0x08) + fdc_update_drvrate(dev->fdc, 1, (val & 0x08) >> 3); + break; + case 0xf6: + if (valxor & 0x08) + fdc_update_drvrate(dev->fdc, 2, (val & 0x08) >> 3); + break; + case 0xf7: + if (valxor & 0x08) + fdc_update_drvrate(dev->fdc, 3, (val & 0x08) >> 3); + break; + + default: + break; + } + break; + case 3: + /* Parallel port */ + switch (dev->cur_reg) { + case 0x30: + case 0x60: + case 0x61: + case 0x70: + if ((dev->cur_reg == 0x30) && (val & 0x01)) + dev->regs[0x22] &= ~0x08; + if (valxor) + ali5123_lpt_handler(dev); + break; + + default: + break; + } + break; + case 4: + /* Serial port 1 */ + switch (dev->cur_reg) { + case 0x30: + case 0x60: + case 0x61: + case 0x70: + case 0xf0: + if ((dev->cur_reg == 0x30) && (val & 0x01)) + dev->regs[0x22] &= ~0x10; + if (valxor) + ali5123_serial_handler(dev, 0); + break; + + default: + break; + } + break; + case 5: + /* Serial port 2 - HP like module */ + switch (dev->cur_reg) { + case 0x30: + case 0x60: + case 0x61: + case 0x70: + case 0xf0: + if ((dev->cur_reg == 0x30) && (val & 0x01)) + dev->regs[0x22] &= ~((dev->regs[0x2d] & 0x20) ? 0x40 : 0x20); + if (valxor) + ali5123_serial_handler(dev, (dev->regs[0x2d] & 0x20) ? 2 : 1); + break; + + default: + break; + } + break; + case 0x0b: + /* Serial port 3 */ + switch (dev->cur_reg) { + case 0x30: + case 0x60: + case 0x61: + case 0x70: + case 0xf0: + if ((dev->cur_reg == 0x30) && (val & 0x01)) + dev->regs[0x22] &= ~((dev->regs[0x2d] & 0x20) ? 0x20 : 0x40); + if (valxor) + ali5123_serial_handler(dev, (dev->regs[0x2d] & 0x20) ? 1 : 2); + break; + + default: + break; + } + break; + + default: + break; + } +} + +static uint8_t +ali5123_read(uint16_t port, void *priv) +{ + const ali5123_t *dev = (ali5123_t *) priv; + uint8_t index = (port & 1) ? 0 : 1; + uint8_t ret = 0xff; + uint8_t cur_ld; + + if (dev->locked) { + if (index) + ret = dev->cur_reg; + else { + if (dev->cur_reg < 0x30) { + if (dev->cur_reg == 0x20) + ret = dev->chip_id; + else + ret = dev->regs[dev->cur_reg]; + } else { + cur_ld = dev->regs[7]; + ret = dev->ld_regs[cur_ld][dev->cur_reg]; + } + } + } + + return ret; +} + +static void +ali5123_close(void *priv) +{ + ali5123_t *dev = (ali5123_t *) priv; + + free(dev); +} + +static void * +ali5123_init(const device_t *info) +{ + ali5123_t *dev = (ali5123_t *) malloc(sizeof(ali5123_t)); + memset(dev, 0, sizeof(ali5123_t)); + + dev->fdc = device_add(&fdc_at_ali_device); + + dev->uart[0] = device_add_inst(&ns16550_device, 1); + dev->uart[1] = device_add_inst(&ns16550_device, 2); + dev->uart[2] = device_add_inst(&ns16550_device, 3); + + dev->chip_id = info->local & 0xff; + + ali5123_reset(dev); + + io_sethandler(FDC_PRIMARY_ADDR, 0x0002, + ali5123_read, NULL, NULL, ali5123_write, NULL, NULL, dev); + + device_add(&keyboard_ps2_ali_pci_device); + + return dev; +} + +const device_t ali5123_device = { + .name = "ALi M5123/M1543C Super I/O", + .internal_name = "ali5123", + .flags = 0, + .local = 0x40, + .init = ali5123_init, + .close = ali5123_close, + .reset = NULL, + { .available = NULL }, + .speed_changed = NULL, + .force_redraw = NULL, + .config = NULL +}; diff --git a/src/sio/sio_detect.c b/src/sio/sio_detect.c index 5daa13fcd..38faf3c2c 100644 --- a/src/sio/sio_detect.c +++ b/src/sio/sio_detect.c @@ -1,18 +1,18 @@ /* - * 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. + * 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. + * This file is part of the 86Box distribution. * - * Super I/O chip detection code. + * Super I/O chip detection code. * * * - * Authors: Miran Grca, + * Authors: Miran Grca, * - * Copyright 2016-2018 Miran Grca. + * Copyright 2016-2018 Miran Grca. */ #include #include @@ -26,13 +26,12 @@ #include <86box/fdd.h> #include <86box/fdc.h> #include <86box/sio.h> +#include <86box/plat_unused.h> - -typedef struct { +typedef struct sio_detect_t { uint8_t regs[2]; } sio_detect_t; - static void sio_detect_write(uint16_t port, uint8_t val, void *priv) { @@ -45,18 +44,16 @@ sio_detect_write(uint16_t port, uint8_t val, void *priv) return; } - static uint8_t sio_detect_read(uint16_t port, void *priv) { - sio_detect_t *dev = (sio_detect_t *) priv; + const sio_detect_t *dev = (sio_detect_t *) priv; pclog("sio_detect_read : port=%04x = %02X\n", port, dev->regs[port & 1]); return 0xff /*dev->regs[port & 1]*/; } - static void sio_detect_close(void *priv) { @@ -65,9 +62,8 @@ sio_detect_close(void *priv) free(dev); } - static void * -sio_detect_init(const device_t *info) +sio_detect_init(UNUSED(const device_t *info)) { sio_detect_t *dev = (sio_detect_t *) malloc(sizeof(sio_detect_t)); memset(dev, 0, sizeof(sio_detect_t)); @@ -75,44 +71,47 @@ sio_detect_init(const device_t *info) device_add(&fdc_at_smc_device); io_sethandler(0x0022, 0x0006, - sio_detect_read, NULL, NULL, sio_detect_write, NULL, NULL, dev); + sio_detect_read, NULL, NULL, sio_detect_write, NULL, NULL, dev); io_sethandler(0x002e, 0x0002, - sio_detect_read, NULL, NULL, sio_detect_write, NULL, NULL, dev); + sio_detect_read, NULL, NULL, sio_detect_write, NULL, NULL, dev); io_sethandler(0x0044, 0x0004, - sio_detect_read, NULL, NULL, sio_detect_write, NULL, NULL, dev); + sio_detect_read, NULL, NULL, sio_detect_write, NULL, NULL, dev); io_sethandler(0x004e, 0x0002, - sio_detect_read, NULL, NULL, sio_detect_write, NULL, NULL, dev); + sio_detect_read, NULL, NULL, sio_detect_write, NULL, NULL, dev); io_sethandler(0x0108, 0x0002, - sio_detect_read, NULL, NULL, sio_detect_write, NULL, NULL, dev); + sio_detect_read, NULL, NULL, sio_detect_write, NULL, NULL, dev); io_sethandler(0x015c, 0x0002, - sio_detect_read, NULL, NULL, sio_detect_write, NULL, NULL, dev); + sio_detect_read, NULL, NULL, sio_detect_write, NULL, NULL, dev); io_sethandler(0x0250, 0x0003, - sio_detect_read, NULL, NULL, sio_detect_write, NULL, NULL, dev); + sio_detect_read, NULL, NULL, sio_detect_write, NULL, NULL, dev); io_sethandler(0x026e, 0x0002, - sio_detect_read, NULL, NULL, sio_detect_write, NULL, NULL, dev); + sio_detect_read, NULL, NULL, sio_detect_write, NULL, NULL, dev); io_sethandler(0x0279, 0x0001, - sio_detect_read, NULL, NULL, sio_detect_write, NULL, NULL, dev); - io_sethandler(0x0370, 0x0002, - sio_detect_read, NULL, NULL, sio_detect_write, NULL, NULL, dev); + sio_detect_read, NULL, NULL, sio_detect_write, NULL, NULL, dev); + io_sethandler(FDC_SECONDARY_ADDR, 0x0002, + sio_detect_read, NULL, NULL, sio_detect_write, NULL, NULL, dev); io_sethandler(0x0398, 0x0002, - sio_detect_read, NULL, NULL, sio_detect_write, NULL, NULL, dev); + sio_detect_read, NULL, NULL, sio_detect_write, NULL, NULL, dev); io_sethandler(0x03e3, 0x0001, - sio_detect_read, NULL, NULL, sio_detect_write, NULL, NULL, dev); - io_sethandler(0x03f0, 0x0002, - sio_detect_read, NULL, NULL, sio_detect_write, NULL, NULL, dev); + sio_detect_read, NULL, NULL, sio_detect_write, NULL, NULL, dev); + io_sethandler(FDC_PRIMARY_ADDR, 0x0002, + sio_detect_read, NULL, NULL, sio_detect_write, NULL, NULL, dev); io_sethandler(0x0a79, 0x0001, - sio_detect_read, NULL, NULL, sio_detect_write, NULL, NULL, dev); + sio_detect_read, NULL, NULL, sio_detect_write, NULL, NULL, dev); return dev; } - const device_t sio_detect_device = { - "Super I/O Detection Helper", - "sio_detect", - 0, - 0, - sio_detect_init, sio_detect_close, NULL, - { NULL }, NULL, NULL, - NULL + .name = "Super I/O Detection Helper", + .internal_name = "sio_detect", + .flags = 0, + .local = 0, + .init = sio_detect_init, + .close = sio_detect_close, + .reset = NULL, + { .available = NULL }, + .speed_changed = NULL, + .force_redraw = NULL, + .config = NULL }; diff --git a/src/sio/sio_f82c710.c b/src/sio/sio_f82c710.c index feb623a10..d4afb11da 100644 --- a/src/sio/sio_f82c710.c +++ b/src/sio/sio_f82c710.c @@ -1,28 +1,28 @@ /* - * 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. + * 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. + * This file is part of the 86Box distribution. * - * Implementation of the Chips & Technologies F82C710 Universal Peripheral - * Controller (UPC) and 82C606 CHIPSpak Multifunction Controller. + * Implementation of the Chips & Technologies F82C710 Universal Peripheral + * Controller (UPC) and 82C606 CHIPSpak Multifunction Controller. * - * Relevant literature: + * Relevant literature: * - * [1] Chips and Technologies, Inc., - * 82C605/82C606 CHIPSpak/CHIPSport MULTIFUNCTION CONTROLLERS, - * PRELIMINARY Data Sheet, Revision 1, May 1987. - * + * [1] Chips and Technologies, Inc., + * 82C605/82C606 CHIPSpak/CHIPSport MULTIFUNCTION CONTROLLERS, + * PRELIMINARY Data Sheet, Revision 1, May 1987. + * * - * Authors: Sarah Walker, - * Eluan Costa Miranda - * Lubomir Rintel * - * Copyright 2020 Sarah Walker. - * Copyright 2020 Eluan Costa Miranda. - * Copyright 2021 Lubomir Rintel. + * + * Authors: Eluan Costa Miranda + * Lubomir Rintel + * + * Copyright 2020 Eluan Costa Miranda. + * Copyright 2021 Lubomir Rintel. */ #include #include @@ -43,27 +43,42 @@ #include <86box/nvr.h> #include <86box/sio.h> - -typedef struct upc_t -{ - uint32_t local; - int configuration_state; /* state of algorithm to enter configuration mode */ - int configuration_mode; - uint16_t cri_addr; /* cri = configuration index register, addr is even */ - uint16_t cap_addr; /* cap = configuration access port, addr is odd and is cri_addr + 1 */ - uint8_t cri; /* currently indexed register */ - uint8_t last_write; +typedef struct upc_t { + uint32_t local; + int configuration_state; /* state of algorithm to enter configuration mode */ + int configuration_mode; + uint16_t cri_addr; /* cri = configuration index register, addr is even */ + uint16_t cap_addr; /* cap = configuration access port, addr is odd and is cri_addr + 1 */ + uint8_t cri; /* currently indexed register */ + uint8_t last_write; /* these regs are not affected by reset */ - uint8_t regs[15]; /* there are 16 indexes, but there is no need to store the last one which is: R = cri_addr / 4, W = exit config mode */ - fdc_t * fdc; - nvr_t * nvr; - void * gameport; - serial_t * uart[2]; + uint8_t regs[15]; /* there are 16 indexes, but there is no need to store the last one which is: R = cri_addr / 4, W = exit config mode */ + fdc_t *fdc; + nvr_t *nvr; + void *gameport; + serial_t *uart[2]; } upc_t; +#ifdef ENABLE_F82C710_LOG +int f82c710_do_log = ENABLE_F82C710_LOG; -static void +static void +f82c710_log(const char *fmt, ...) +{ + va_list ap; + + if (f82c710_do_log) { + va_start(ap, fmt); + pclog_ex(fmt, ap); + va_end(ap); + } +} +#else +# define f82c710_log(fmt, ...) +#endif + +static void f82c710_update_ports(upc_t *dev, int set) { uint16_t com_addr = 0; @@ -77,40 +92,39 @@ f82c710_update_ports(upc_t *dev, int set) ide_pri_disable(); if (!set) - return; + return; if (dev->regs[0] & 4) { - com_addr = dev->regs[4] * 4; - if (com_addr == SERIAL1_ADDR) - serial_setup(dev->uart[0], com_addr, 4); - else if (com_addr == SERIAL2_ADDR) - serial_setup(dev->uart[1], com_addr, 3); + com_addr = dev->regs[4] * 4; + if (com_addr == COM1_ADDR) + serial_setup(dev->uart[0], com_addr, COM1_IRQ); + else if (com_addr == COM2_ADDR) + serial_setup(dev->uart[1], com_addr, COM2_IRQ); } if (dev->regs[0] & 8) { - lpt_addr = dev->regs[6] * 4; - lpt1_init(lpt_addr); - if ((lpt_addr == 0x378) || (lpt_addr == 0x3bc)) - lpt1_irq(7); - else if (lpt_addr == 0x278) - lpt1_irq(5); + lpt_addr = dev->regs[6] * 4; + lpt1_init(lpt_addr); + if ((lpt_addr == LPT1_ADDR) || (lpt_addr == LPT_MDA_ADDR)) + lpt1_irq(LPT1_IRQ); + else if (lpt_addr == LPT2_ADDR) + lpt1_irq(LPT2_IRQ); } if (dev->regs[12] & 0x80) - ide_pri_enable(); + ide_pri_enable(); if (dev->regs[12] & 0x20) - fdc_set_base(dev->fdc, 0x03f0); + fdc_set_base(dev->fdc, FDC_PRIMARY_ADDR); } - static void f82c606_update_ports(upc_t *dev, int set) { uint8_t uart1_int = 0xff; uint8_t uart2_int = 0xff; - uint8_t lpt1_int = 0xff; - int nvr_int = -1; + uint8_t lpt1_int = 0xff; + int nvr_int = -1; serial_remove(dev->uart[0]); serial_remove(dev->uart[1]); @@ -123,149 +137,182 @@ f82c606_update_ports(upc_t *dev, int set) gameport_remap(dev->gameport, 0); if (!set) - return; + return; switch (dev->regs[8] & 0xc0) { - case 0x40: nvr_int = 3; break; - case 0x80: uart1_int = 3; break; - case 0xc0: uart2_int = 3; break; + case 0x40: + nvr_int = 3; + break; + case 0x80: + uart1_int = COM2_IRQ; + break; + case 0xc0: + uart2_int = COM2_IRQ; + break; + + default: + break; } switch (dev->regs[8] & 0x30) { - case 0x10: nvr_int = 4; break; - case 0x20: uart1_int = 4; break; - case 0x30: uart2_int = 4; break; + case 0x10: + nvr_int = 4; + break; + case 0x20: + uart1_int = COM1_IRQ; + break; + case 0x30: + uart2_int = COM1_IRQ; + break; + + default: + break; } switch (dev->regs[8] & 0x0c) { - case 0x04: nvr_int = 5; break; - case 0x08: uart1_int = 5; break; - case 0x0c: lpt1_int = 5; break; + case 0x04: + nvr_int = 5; + break; + case 0x08: + uart1_int = 5; + break; + case 0x0c: + lpt1_int = LPT2_IRQ; + break; + + default: + break; } switch (dev->regs[8] & 0x03) { - case 0x01: nvr_int = 7; break; - case 0x02: uart2_int = 7; break; - case 0x03: lpt1_int = 7; break; + case 0x01: + nvr_int = 7; + break; + case 0x02: + uart2_int = 7; + break; + case 0x03: + lpt1_int = LPT1_IRQ; + break; + + default: + break; } if (dev->regs[0] & 1) { - gameport_remap(dev->gameport, ((uint16_t) dev->regs[7]) << 2); - pclog("Game port at %04X\n", ((uint16_t) dev->regs[7]) << 2); + gameport_remap(dev->gameport, ((uint16_t) dev->regs[7]) << 2); + f82c710_log("Game port at %04X\n", ((uint16_t) dev->regs[7]) << 2); } if (dev->regs[0] & 2) { - serial_setup(dev->uart[0], ((uint16_t) dev->regs[4]) << 2, uart1_int); - pclog("UART 1 at %04X, IRQ %i\n", ((uint16_t) dev->regs[4]) << 2, uart1_int); + serial_setup(dev->uart[0], ((uint16_t) dev->regs[4]) << 2, uart1_int); + f82c710_log("UART 1 at %04X, IRQ %i\n", ((uint16_t) dev->regs[4]) << 2, uart1_int); } if (dev->regs[0] & 4) { - serial_setup(dev->uart[1], ((uint16_t) dev->regs[5]) << 2, uart2_int); - pclog("UART 2 at %04X, IRQ %i\n", ((uint16_t) dev->regs[5]) << 2, uart2_int); + serial_setup(dev->uart[1], ((uint16_t) dev->regs[5]) << 2, uart2_int); + f82c710_log("UART 2 at %04X, IRQ %i\n", ((uint16_t) dev->regs[5]) << 2, uart2_int); } if (dev->regs[0] & 8) { - lpt1_init(((uint16_t) dev->regs[6]) << 2); - lpt1_irq(lpt1_int); - pclog("LPT1 at %04X, IRQ %i\n", ((uint16_t) dev->regs[6]) << 2, lpt1_int); + lpt1_init(((uint16_t) dev->regs[6]) << 2); + lpt1_irq(lpt1_int); + f82c710_log("LPT1 at %04X, IRQ %i\n", ((uint16_t) dev->regs[6]) << 2, lpt1_int); } nvr_at_handler(1, ((uint16_t) dev->regs[3]) << 2, dev->nvr); nvr_irq_set(nvr_int, dev->nvr); - pclog("RTC at %04X, IRQ %i\n", ((uint16_t) dev->regs[3]) << 2, nvr_int); + f82c710_log("RTC at %04X, IRQ %i\n", ((uint16_t) dev->regs[3]) << 2, nvr_int); } - -static uint8_t +static uint8_t f82c710_config_read(uint16_t port, void *priv) { - upc_t *dev = (upc_t *) priv; - uint8_t temp = 0xff; + const upc_t *dev = (upc_t *) priv; + uint8_t temp = 0xff; if (dev->configuration_mode) { - if (port == dev->cri_addr) { - temp = dev->cri; - } else if (port == dev->cap_addr) { - if (dev->cri == 0xf) - temp = dev->cri_addr / 4; - else - temp = dev->regs[dev->cri]; - } + if (port == dev->cri_addr) { + temp = dev->cri; + } else if (port == dev->cap_addr) { + if (dev->cri == 0xf) + temp = dev->cri_addr / 4; + else + temp = dev->regs[dev->cri]; + } } return temp; } - -static void +static void f82c710_config_write(uint16_t port, uint8_t val, void *priv) { - upc_t *dev = (upc_t *) priv; - int configuration_state_event = 0; + upc_t *dev = (upc_t *) priv; + int configuration_state_event = 0; switch (port) { - case 0x2fa: - if ((dev->configuration_state == 0) && (val != 0x00) && (val != 0xff) && (dev->local == 606)) { - configuration_state_event = 1; - dev->last_write = val; - } else if ((dev->configuration_state == 0) && (val == 0x55) && (dev->local == 710)) - configuration_state_event = 1; - else if (dev->configuration_state == 4) { - if ((val | dev->last_write) == 0xff) { - dev->cri_addr = ((uint16_t) dev->last_write) << 2; - dev->cap_addr = dev->cri_addr + 1; - dev->configuration_mode = 1; - if (dev->local == 606) - f82c606_update_ports(dev, 0); - else if (dev->local == 710) - f82c710_update_ports(dev, 0); - /* TODO: is the value of cri reset here or when exiting configuration mode? */ - io_sethandler(dev->cri_addr, 0x0002, f82c710_config_read, NULL, NULL, f82c710_config_write, NULL, NULL, dev); - } else - dev->configuration_mode = 0; - } - break; - case 0x3fa: - if ((dev->configuration_state == 1) && ((val | dev->last_write) == 0xff) && (dev->local == 606)) - configuration_state_event = 1; - else if ((dev->configuration_state == 1) && (val == 0xaa) && (dev->local == 710)) - configuration_state_event = 1; - else if ((dev->configuration_state == 2) && (val == 0x36)) - configuration_state_event = 1; - else if (dev->configuration_state == 3) { - dev->last_write = val; - configuration_state_event = 1; - } - break; - default: - break; + case 0x2fa: + if ((dev->configuration_state == 0) && (val != 0x00) && (val != 0xff) && (dev->local == 606)) { + configuration_state_event = 1; + dev->last_write = val; + } else if ((dev->configuration_state == 0) && (val == 0x55) && (dev->local == 710)) + configuration_state_event = 1; + else if (dev->configuration_state == 4) { + if ((val | dev->last_write) == 0xff) { + dev->cri_addr = ((uint16_t) dev->last_write) << 2; + dev->cap_addr = dev->cri_addr + 1; + dev->configuration_mode = 1; + if (dev->local == 606) + f82c606_update_ports(dev, 0); + else if (dev->local == 710) + f82c710_update_ports(dev, 0); + /* TODO: is the value of cri reset here or when exiting configuration mode? */ + io_sethandler(dev->cri_addr, 0x0002, f82c710_config_read, NULL, NULL, f82c710_config_write, NULL, NULL, dev); + } else + dev->configuration_mode = 0; + } + break; + case 0x3fa: + if ((dev->configuration_state == 1) && ((val | dev->last_write) == 0xff) && (dev->local == 606)) + configuration_state_event = 1; + else if ((dev->configuration_state == 1) && (val == 0xaa) && (dev->local == 710)) + configuration_state_event = 1; + else if ((dev->configuration_state == 2) && (val == 0x36)) + configuration_state_event = 1; + else if (dev->configuration_state == 3) { + dev->last_write = val; + configuration_state_event = 1; + } + break; + default: + break; } if (dev->configuration_mode) { - if (port == dev->cri_addr) { - dev->cri = val & 0xf; - } else if (port == dev->cap_addr) { - if (dev->cri == 0xf) { - dev->configuration_mode = 0; - io_removehandler(dev->cri_addr, 0x0002, f82c710_config_read, NULL, NULL, f82c710_config_write, NULL, NULL, dev); - /* TODO: any benefit in updating at each register write instead of when exiting config mode? */ - if (dev->local == 606) - f82c606_update_ports(dev, 1); - else if (dev->local == 710) - f82c710_update_ports(dev, 1); - } else - dev->regs[dev->cri] = val; - } + if (port == dev->cri_addr) { + dev->cri = val & 0xf; + } else if (port == dev->cap_addr) { + if (dev->cri == 0xf) { + dev->configuration_mode = 0; + io_removehandler(dev->cri_addr, 0x0002, f82c710_config_read, NULL, NULL, f82c710_config_write, NULL, NULL, dev); + /* TODO: any benefit in updating at each register write instead of when exiting config mode? */ + if (dev->local == 606) + f82c606_update_ports(dev, 1); + else if (dev->local == 710) + f82c710_update_ports(dev, 1); + } else + dev->regs[dev->cri] = val; + } } /* TODO: is the state only reset when accessing 0x2fa and 0x3fa wrongly? */ if ((port == 0x2fa || port == 0x3fa) && configuration_state_event) - dev->configuration_state++; + dev->configuration_state++; else - dev->configuration_state = 0; + dev->configuration_state = 0; } - static void f82c710_reset(void *priv) { @@ -273,40 +320,39 @@ f82c710_reset(void *priv) /* Set power-on defaults. */ if (dev->local == 606) { - dev->regs[0] = 0x00; /* Enable */ - dev->regs[1] = 0x00; /* Configuration Register */ - dev->regs[2] = 0x00; /* Ext Baud Rate Select */ - dev->regs[3] = 0xb0; /* RTC Base */ - dev->regs[4] = 0xfe; /* UART1 Base */ - dev->regs[5] = 0xbe; /* UART2 Base */ - dev->regs[6] = 0x9e; /* Parallel Base */ - dev->regs[7] = 0x80; /* Game Base */ - dev->regs[8] = 0xec; /* Interrupt Select */ + dev->regs[0] = 0x00; /* Enable */ + dev->regs[1] = 0x00; /* Configuration Register */ + dev->regs[2] = 0x00; /* Ext Baud Rate Select */ + dev->regs[3] = 0xb0; /* RTC Base */ + dev->regs[4] = 0xfe; /* UART1 Base */ + dev->regs[5] = 0xbe; /* UART2 Base */ + dev->regs[6] = 0x9e; /* Parallel Base */ + dev->regs[7] = 0x80; /* Game Base */ + dev->regs[8] = 0xec; /* Interrupt Select */ } else if (dev->local == 710) { - dev->regs[0] = 0x0c; - dev->regs[1] = 0x00; - dev->regs[2] = 0x00; - dev->regs[3] = 0x00; - dev->regs[4] = 0xfe; - dev->regs[5] = 0x00; - dev->regs[6] = 0x9e; - dev->regs[7] = 0x00; - dev->regs[8] = 0x00; - dev->regs[9] = 0xb0; - dev->regs[10] = 0x00; - dev->regs[11] = 0x00; - dev->regs[12] = 0xa0; - dev->regs[13] = 0x00; - dev->regs[14] = 0x00; + dev->regs[0] = 0x0c; + dev->regs[1] = 0x00; + dev->regs[2] = 0x00; + dev->regs[3] = 0x00; + dev->regs[4] = 0xfe; + dev->regs[5] = 0x00; + dev->regs[6] = 0x9e; + dev->regs[7] = 0x00; + dev->regs[8] = 0x00; + dev->regs[9] = 0xb0; + dev->regs[10] = 0x00; + dev->regs[11] = 0x00; + dev->regs[12] = 0xa0; + dev->regs[13] = 0x00; + dev->regs[14] = 0x00; } if (dev->local == 606) - f82c606_update_ports(dev, 1); + f82c606_update_ports(dev, 1); else if (dev->local == 710) - f82c710_update_ports(dev, 1); + f82c710_update_ports(dev, 1); } - static void f82c710_close(void *priv) { @@ -315,7 +361,6 @@ f82c710_close(void *priv) free(dev); } - static void * f82c710_init(const device_t *info) { @@ -324,13 +369,13 @@ f82c710_init(const device_t *info) dev->local = info->local; if (dev->local == 606) { - dev->nvr = device_add(&at_nvr_old_device); - dev->gameport = gameport_add(&gameport_sio_device); + dev->nvr = device_add(&at_nvr_old_device); + dev->gameport = gameport_add(&gameport_sio_device); } else if (dev->local == 710) - dev->fdc = device_add(&fdc_at_device); + dev->fdc = device_add(&fdc_at_device); dev->uart[0] = device_add_inst(&ns16450_device, 1); - dev->uart[1] = device_add_inst(&ns16450_device, 2); + dev->uart[1] = device_add_inst(&ns16450_device, 2); io_sethandler(0x02fa, 0x0001, NULL, NULL, NULL, f82c710_config_write, NULL, NULL, dev); io_sethandler(0x03fa, 0x0001, NULL, NULL, NULL, f82c710_config_write, NULL, NULL, dev); @@ -340,23 +385,30 @@ f82c710_init(const device_t *info) return dev; } - const device_t f82c606_device = { - "82C606 CHIPSpak Multifunction Controller", - "f82c606", - 0, - 606, - f82c710_init, f82c710_close, f82c710_reset, - { NULL }, NULL, NULL, - NULL + .name = "82C606 CHIPSpak Multifunction Controller", + .internal_name = "f82c606", + .flags = 0, + .local = 606, + .init = f82c710_init, + .close = f82c710_close, + .reset = f82c710_reset, + { .available = NULL }, + .speed_changed = NULL, + .force_redraw = NULL, + .config = NULL }; const device_t f82c710_device = { - "F82C710 UPC Super I/O", - "f82c710", - 0, - 710, - f82c710_init, f82c710_close, f82c710_reset, - { NULL }, NULL, NULL, - NULL + .name = "F82C710 UPC Super I/O", + .internal_name = "f82c710", + .flags = 0, + .local = 710, + .init = f82c710_init, + .close = f82c710_close, + .reset = f82c710_reset, + { .available = NULL }, + .speed_changed = NULL, + .force_redraw = NULL, + .config = NULL }; diff --git a/src/sio/sio_fdc37c669.c b/src/sio/sio_fdc37c669.c index a365f0ede..b2c8933c6 100644 --- a/src/sio/sio_fdc37c669.c +++ b/src/sio/sio_fdc37c669.c @@ -1,17 +1,18 @@ /* - * 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. + * 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. + * This file is part of the 86Box distribution. * - * Implementation of the SMC FDC37C669 Super I/O Chip. + * Implementation of the SMC FDC37C669 Super I/O Chip. * * * - * Author: Miran Grca, - * Copyright 2016-2018 Miran Grca. + * Authors: Miran Grca, + * + * Copyright 2016-2018 Miran Grca. */ #include #include @@ -31,225 +32,227 @@ #include <86box/fdc.h> #include <86box/sio.h> - -typedef struct { - uint8_t id, tries, - regs[42]; - int locked, rw_locked, - cur_reg; - fdc_t *fdc; +typedef struct fdc37c669_t { + uint8_t id; + uint8_t tries; + uint8_t regs[42]; + int locked; + int rw_locked; + int cur_reg; + fdc_t *fdc; serial_t *uart[2]; } fdc37c669_t; - -static int next_id = 0; - +static int next_id = 0; static uint16_t make_port(fdc37c669_t *dev, uint8_t reg) { - uint16_t p = 0; + uint16_t p = 0; uint16_t mask = 0; - switch(reg) { - case 0x20: - case 0x21: - case 0x22: - mask = 0xfc; - break; - case 0x23: - mask = 0xff; - break; - case 0x24: - case 0x25: - mask = 0xfe; - break; + switch (reg) { + case 0x20: + case 0x21: + case 0x22: + mask = 0xfc; + break; + case 0x23: + mask = 0xff; + break; + case 0x24: + case 0x25: + mask = 0xfe; + break; + + default: + break; } p = ((uint16_t) (dev->regs[reg] & mask)) << 2; if (reg == 0x22) - p |= 6; + p |= 6; return p; } - static void fdc37c669_write(uint16_t port, uint8_t val, void *priv) { - fdc37c669_t *dev = (fdc37c669_t *) priv; - uint8_t index = (port & 1) ? 0 : 1; - uint8_t valxor = 0; - uint8_t max = 42; + fdc37c669_t *dev = (fdc37c669_t *) priv; + uint8_t index = (port & 1) ? 0 : 1; + uint8_t valxor = 0; + uint8_t max = 42; if (index) { - if ((val == 0x55) && !dev->locked) { - if (dev->tries) { - dev->locked = 1; - dev->tries = 0; - } else - dev->tries++; - } else { - if (dev->locked) { - if (val < max) - dev->cur_reg = val; - if (val == 0xaa) - dev->locked = 0; - } else { - if (dev->tries) - dev->tries = 0; - } - } - return; + if ((val == 0x55) && !dev->locked) { + if (dev->tries) { + dev->locked = 1; + dev->tries = 0; + } else + dev->tries++; + } else { + if (dev->locked) { + if (val < max) + dev->cur_reg = val; + if (val == 0xaa) + dev->locked = 0; + } else { + if (dev->tries) + dev->tries = 0; + } + } + return; } else { - if (dev->locked) { - if ((dev->cur_reg < 0x18) && (dev->rw_locked)) - return; - if ((dev->cur_reg >= 0x26) && (dev->cur_reg <= 0x27)) - return; - if (dev->cur_reg == 0x29) - return; - valxor = val ^ dev->regs[dev->cur_reg]; - dev->regs[dev->cur_reg] = val; - } else - return; + if (dev->locked) { + if ((dev->cur_reg < 0x18) && (dev->rw_locked)) + return; + if ((dev->cur_reg >= 0x26) && (dev->cur_reg <= 0x27)) + return; + if (dev->cur_reg == 0x29) + return; + valxor = val ^ dev->regs[dev->cur_reg]; + dev->regs[dev->cur_reg] = val; + } else + return; } - switch(dev->cur_reg) { - case 0: - if (!dev->id && (valxor & 8)) { - fdc_remove(dev->fdc); - if ((dev->regs[0] & 8) && (dev->regs[0x20] & 0xc0)) - fdc_set_base(dev->fdc, make_port(dev, 0x20)); - } - break; - case 1: - if (valxor & 4) { - if (dev->id) { - lpt2_remove(); - if ((dev->regs[1] & 4) && (dev->regs[0x23] >= 0x40)) - lpt2_init(make_port(dev, 0x23)); - } else { - lpt1_remove(); - if ((dev->regs[1] & 4) && (dev->regs[0x23] >= 0x40)) - lpt1_init(make_port(dev, 0x23)); - } - } - if (valxor & 7) - dev->rw_locked = (val & 8) ? 0 : 1; - break; - case 2: - if (valxor & 8) { - serial_remove(dev->uart[0]); - if ((dev->regs[2] & 8) && (dev->regs[0x24] >= 0x40)) - serial_setup(dev->uart[0], make_port(dev, 0x24), (dev->regs[0x28] & 0xf0) >> 4); - } - if (valxor & 0x80) { - serial_remove(dev->uart[1]); - if ((dev->regs[2] & 0x80) && (dev->regs[0x25] >= 0x40)) - serial_setup(dev->uart[1], make_port(dev, 0x25), dev->regs[0x28] & 0x0f); - } - break; - case 3: - if (!dev->id && (valxor & 2)) - fdc_update_enh_mode(dev->fdc, (val & 2) ? 1 : 0); - break; - case 5: - if (!dev->id && (valxor & 0x18)) - fdc_update_densel_force(dev->fdc, (val & 0x18) >> 3); - if (!dev->id && (valxor & 0x20)) - fdc_set_swap(dev->fdc, (val & 0x20) >> 5); - break; - case 0xB: - if (!dev->id && (valxor & 3)) - fdc_update_rwc(dev->fdc, 0, val & 3); - if (!dev->id && (valxor & 0xC)) - fdc_update_rwc(dev->fdc, 1, (val & 0xC) >> 2); - break; - case 0x20: - if (!dev->id && (valxor & 0xfc)) { - fdc_remove(dev->fdc); - if ((dev->regs[0] & 8) && (dev->regs[0x20] & 0xc0)) - fdc_set_base(dev->fdc, make_port(dev, 0x20)); - } - break; - case 0x23: - if (valxor) { - if (dev->id) { - lpt2_remove(); - if ((dev->regs[1] & 4) && (dev->regs[0x23] >= 0x40)) - lpt2_init(make_port(dev, 0x23)); - } else { - lpt1_remove(); - if ((dev->regs[1] & 4) && (dev->regs[0x23] >= 0x40)) - lpt1_init(make_port(dev, 0x23)); - } - } - break; - case 0x24: - if (valxor & 0xfe) { - serial_remove(dev->uart[0]); - if ((dev->regs[2] & 8) && (dev->regs[0x24] >= 0x40)) - serial_setup(dev->uart[0], make_port(dev, 0x24), (dev->regs[0x28] & 0xf0) >> 4); - } - break; - case 0x25: - if (valxor & 0xfe) { - serial_remove(dev->uart[1]); - if ((dev->regs[2] & 0x80) && (dev->regs[0x25] >= 0x40)) - serial_setup(dev->uart[1], make_port(dev, 0x25), dev->regs[0x28] & 0x0f); - } - break; - case 0x27: - if (valxor & 0xf) { - if (dev->id) - lpt2_irq(val & 0xf); - else - lpt1_irq(val & 0xf); - } - break; - case 0x28: - if (valxor & 0xf) { - serial_remove(dev->uart[1]); - if ((dev->regs[2] & 0x80) && (dev->regs[0x25] >= 0x40)) - serial_setup(dev->uart[1], make_port(dev, 0x25), dev->regs[0x28] & 0x0f); - } - if (valxor & 0xf0) { - serial_remove(dev->uart[0]); - if ((dev->regs[2] & 8) && (dev->regs[0x24] >= 0x40)) - serial_setup(dev->uart[0], make_port(dev, 0x24), (dev->regs[0x28] & 0xf0) >> 4); - } - break; + switch (dev->cur_reg) { + case 0: + if (!dev->id && (valxor & 8)) { + fdc_remove(dev->fdc); + if ((dev->regs[0] & 8) && (dev->regs[0x20] & 0xc0)) + fdc_set_base(dev->fdc, make_port(dev, 0x20)); + } + break; + case 1: + if (valxor & 4) { + if (dev->id) { + lpt2_remove(); + if ((dev->regs[1] & 4) && (dev->regs[0x23] >= 0x40)) + lpt2_init(make_port(dev, 0x23)); + } else { + lpt1_remove(); + if ((dev->regs[1] & 4) && (dev->regs[0x23] >= 0x40)) + lpt1_init(make_port(dev, 0x23)); + } + } + if (valxor & 7) + dev->rw_locked = (val & 8) ? 0 : 1; + break; + case 2: + if (valxor & 8) { + serial_remove(dev->uart[0]); + if ((dev->regs[2] & 8) && (dev->regs[0x24] >= 0x40)) + serial_setup(dev->uart[0], make_port(dev, 0x24), (dev->regs[0x28] & 0xf0) >> 4); + } + if (valxor & 0x80) { + serial_remove(dev->uart[1]); + if ((dev->regs[2] & 0x80) && (dev->regs[0x25] >= 0x40)) + serial_setup(dev->uart[1], make_port(dev, 0x25), dev->regs[0x28] & 0x0f); + } + break; + case 3: + if (!dev->id && (valxor & 2)) + fdc_update_enh_mode(dev->fdc, (val & 2) ? 1 : 0); + break; + case 5: + if (!dev->id && (valxor & 0x18)) + fdc_update_densel_force(dev->fdc, (val & 0x18) >> 3); + if (!dev->id && (valxor & 0x20)) + fdc_set_swap(dev->fdc, (val & 0x20) >> 5); + break; + case 0xB: + if (!dev->id && (valxor & 3)) + fdc_update_rwc(dev->fdc, 0, val & 3); + if (!dev->id && (valxor & 0xC)) + fdc_update_rwc(dev->fdc, 1, (val & 0xC) >> 2); + break; + case 0x20: + if (!dev->id && (valxor & 0xfc)) { + fdc_remove(dev->fdc); + if ((dev->regs[0] & 8) && (dev->regs[0x20] & 0xc0)) + fdc_set_base(dev->fdc, make_port(dev, 0x20)); + } + break; + case 0x23: + if (valxor) { + if (dev->id) { + lpt2_remove(); + if ((dev->regs[1] & 4) && (dev->regs[0x23] >= 0x40)) + lpt2_init(make_port(dev, 0x23)); + } else { + lpt1_remove(); + if ((dev->regs[1] & 4) && (dev->regs[0x23] >= 0x40)) + lpt1_init(make_port(dev, 0x23)); + } + } + break; + case 0x24: + if (valxor & 0xfe) { + serial_remove(dev->uart[0]); + if ((dev->regs[2] & 8) && (dev->regs[0x24] >= 0x40)) + serial_setup(dev->uart[0], make_port(dev, 0x24), (dev->regs[0x28] & 0xf0) >> 4); + } + break; + case 0x25: + if (valxor & 0xfe) { + serial_remove(dev->uart[1]); + if ((dev->regs[2] & 0x80) && (dev->regs[0x25] >= 0x40)) + serial_setup(dev->uart[1], make_port(dev, 0x25), dev->regs[0x28] & 0x0f); + } + break; + case 0x27: + if (valxor & 0xf) { + if (dev->id) + lpt2_irq(val & 0xf); + else + lpt1_irq(val & 0xf); + } + break; + case 0x28: + if (valxor & 0xf) { + serial_remove(dev->uart[1]); + if ((dev->regs[2] & 0x80) && (dev->regs[0x25] >= 0x40)) + serial_setup(dev->uart[1], make_port(dev, 0x25), dev->regs[0x28] & 0x0f); + } + if (valxor & 0xf0) { + serial_remove(dev->uart[0]); + if ((dev->regs[2] & 8) && (dev->regs[0x24] >= 0x40)) + serial_setup(dev->uart[0], make_port(dev, 0x24), (dev->regs[0x28] & 0xf0) >> 4); + } + break; + + default: + break; } } - static uint8_t fdc37c669_read(uint16_t port, void *priv) { - fdc37c669_t *dev = (fdc37c669_t *) priv; - uint8_t index = (port & 1) ? 0 : 1; - uint8_t ret = 0xff; + const fdc37c669_t *dev = (fdc37c669_t *) priv; + uint8_t index = (port & 1) ? 0 : 1; + uint8_t ret = 0xff; if (dev->locked) { - if (index) - ret = dev->cur_reg; - else if ((dev->cur_reg >= 0x18) || !dev->rw_locked) - ret = dev->regs[dev->cur_reg]; + if (index) + ret = dev->cur_reg; + else if ((dev->cur_reg >= 0x18) || !dev->rw_locked) + ret = dev->regs[dev->cur_reg]; } return ret; } - static void fdc37c669_reset(fdc37c669_t *dev) { serial_remove(dev->uart[0]); - serial_setup(dev->uart[0], SERIAL1_ADDR, SERIAL1_IRQ); + serial_setup(dev->uart[0], COM1_ADDR, COM1_IRQ); serial_remove(dev->uart[1]); - serial_setup(dev->uart[1], SERIAL2_ADDR, SERIAL2_IRQ); + serial_setup(dev->uart[1], COM2_ADDR, COM2_IRQ); memset(dev->regs, 0, 42); dev->regs[0x00] = 0x28; @@ -259,38 +262,37 @@ fdc37c669_reset(fdc37c669_t *dev) dev->regs[0x06] = 0xff; dev->regs[0x0d] = 0x03; dev->regs[0x0e] = 0x02; - dev->regs[0x1e] = 0x80; /* Gameport controller. */ - dev->regs[0x20] = (0x3f0 >> 2) & 0xfc; + dev->regs[0x1e] = 0x80; /* Gameport controller. */ + dev->regs[0x20] = (FDC_PRIMARY_ADDR >> 2) & 0xfc; dev->regs[0x21] = (0x1f0 >> 2) & 0xfc; dev->regs[0x22] = ((0x3f6 >> 2) & 0xfc) | 1; if (dev->id == 1) { - dev->regs[0x23] = (0x278 >> 2); + dev->regs[0x23] = (LPT2_ADDR >> 2); - lpt2_remove(); - lpt2_init(0x278); + lpt2_remove(); + lpt2_init(LPT2_ADDR); - dev->regs[0x24] = (SERIAL3_ADDR >> 2) & 0xfe; - dev->regs[0x25] = (SERIAL4_ADDR >> 2) & 0xfe; + dev->regs[0x24] = (COM3_ADDR >> 2) & 0xfe; + dev->regs[0x25] = (COM4_ADDR >> 2) & 0xfe; } else { - fdc_reset(dev->fdc); + fdc_reset(dev->fdc); - lpt1_remove(); - lpt1_init(0x378); + lpt1_remove(); + lpt1_init(LPT1_ADDR); - dev->regs[0x23] = (0x378 >> 2); + dev->regs[0x23] = (LPT1_ADDR >> 2); - dev->regs[0x24] = (SERIAL1_ADDR >> 2) & 0xfe; - dev->regs[0x25] = (SERIAL2_ADDR >> 2) & 0xfe; + dev->regs[0x24] = (COM1_ADDR >> 2) & 0xfe; + dev->regs[0x25] = (COM2_ADDR >> 2) & 0xfe; } dev->regs[0x26] = (2 << 4) | 3; dev->regs[0x27] = (6 << 4) | (dev->id ? 5 : 7); dev->regs[0x28] = (4 << 4) | 3; - dev->locked = 0; + dev->locked = 0; dev->rw_locked = 0; } - static void fdc37c669_close(void *priv) { @@ -301,7 +303,6 @@ fdc37c669_close(void *priv) free(dev); } - static void * fdc37c669_init(const device_t *info) { @@ -311,13 +312,13 @@ fdc37c669_init(const device_t *info) dev->id = next_id; if (next_id != 1) - dev->fdc = device_add(&fdc_at_smc_device); + dev->fdc = device_add(&fdc_at_smc_device); dev->uart[0] = device_add_inst(&ns16550_device, (next_id << 1) + 1); dev->uart[1] = device_add_inst(&ns16550_device, (next_id << 1) + 2); - io_sethandler(info->local ? 0x370 : (next_id ? 0x370 : 0x3f0), 0x0002, - fdc37c669_read, NULL, NULL, fdc37c669_write, NULL, NULL, dev); + io_sethandler(info->local ? FDC_SECONDARY_ADDR : (next_id ? FDC_SECONDARY_ADDR : FDC_PRIMARY_ADDR), 0x0002, + fdc37c669_read, NULL, NULL, fdc37c669_write, NULL, NULL, dev); fdc37c669_reset(dev); @@ -326,24 +327,30 @@ fdc37c669_init(const device_t *info) return dev; } - const device_t fdc37c669_device = { - "SMC FDC37C669 Super I/O", - "fdc37c669", - 0, - 0, - fdc37c669_init, fdc37c669_close, NULL, - { NULL }, NULL, NULL, - NULL + .name = "SMC FDC37C669 Super I/O", + .internal_name = "fdc37c669", + .flags = 0, + .local = 0, + .init = fdc37c669_init, + .close = fdc37c669_close, + .reset = NULL, + { .available = NULL }, + .speed_changed = NULL, + .force_redraw = NULL, + .config = NULL }; - const device_t fdc37c669_370_device = { - "SMC FDC37C669 Super I/O (Port 370h)", - "fdc37c669_370", - 0, - 1, - fdc37c669_init, fdc37c669_close, NULL, - { NULL }, NULL, NULL, - NULL + .name = "SMC FDC37C669 Super I/O (Port 370h)", + .internal_name = "fdc37c669_370", + .flags = 0, + .local = 1, + .init = fdc37c669_init, + .close = fdc37c669_close, + .reset = NULL, + { .available = NULL }, + .speed_changed = NULL, + .force_redraw = NULL, + .config = NULL }; diff --git a/src/sio/sio_fdc37c67x.c b/src/sio/sio_fdc37c67x.c index 727390535..871f3b1c8 100644 --- a/src/sio/sio_fdc37c67x.c +++ b/src/sio/sio_fdc37c67x.c @@ -1,17 +1,18 @@ /* - * 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. + * 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. + * This file is part of the 86Box distribution. * - * Implementation of the SMC FDC37C67X Super I/O Chip. + * Implementation of the SMC FDC37C67X Super I/O Chip. * * * - * Author: Miran Grca, - * Copyright 2016-2018 Miran Grca. + * Authors: Miran Grca, + * + * Copyright 2016-2018 Miran Grca. */ #include #include @@ -32,29 +33,29 @@ #include <86box/fdc.h> #include "cpu.h" #include <86box/sio.h> +#include <86box/plat_unused.h> +#define AB_RST 0x80 -#define AB_RST 0x80 - - -typedef struct { - uint8_t chip_id, is_apm, - tries, - gpio_regs[2], auxio_reg, - regs[48], - ld_regs[11][256]; - uint16_t gpio_base, /* Set to EA */ - auxio_base, sio_base; - int locked, - cur_reg; - fdc_t *fdc; +typedef struct fdc37c67x_t { + uint8_t chip_id; + uint8_t is_apm; + uint8_t tries; + uint8_t gpio_regs[2]; + uint8_t auxio_reg; + uint8_t regs[48]; + uint8_t ld_regs[11][256]; + uint16_t gpio_base; /* Set to EA */ + uint16_t auxio_base; + uint16_t sio_base; + int locked; + int cur_reg; + fdc_t *fdc; serial_t *uart[2]; } fdc37c67x_t; - -static void fdc37c67x_write(uint16_t port, uint8_t val, void *priv); -static uint8_t fdc37c67x_read(uint16_t port, void *priv); - +static void fdc37c67x_write(uint16_t port, uint8_t val, void *priv); +static uint8_t fdc37c67x_read(uint16_t port, void *priv); static uint16_t make_port(fdc37c67x_t *dev, uint8_t ld) @@ -67,168 +68,160 @@ make_port(fdc37c67x_t *dev, uint8_t ld) return p; } - static uint8_t -fdc37c67x_auxio_read(uint16_t port, void *priv) +fdc37c67x_auxio_read(UNUSED(uint16_t port), void *priv) { - fdc37c67x_t *dev = (fdc37c67x_t *) priv; + const fdc37c67x_t *dev = (fdc37c67x_t *) priv; return dev->auxio_reg; } - static void -fdc37c67x_auxio_write(uint16_t port, uint8_t val, void *priv) +fdc37c67x_auxio_write(UNUSED(uint16_t port), uint8_t val, void *priv) { fdc37c67x_t *dev = (fdc37c67x_t *) priv; dev->auxio_reg = val; } - static uint8_t fdc37c67x_gpio_read(uint16_t port, void *priv) { - fdc37c67x_t *dev = (fdc37c67x_t *) priv; - uint8_t ret = 0xff; + const fdc37c67x_t *dev = (fdc37c67x_t *) priv; + uint8_t ret = 0xff; ret = dev->gpio_regs[port & 1]; return ret; } - static void fdc37c67x_gpio_write(uint16_t port, uint8_t val, void *priv) { fdc37c67x_t *dev = (fdc37c67x_t *) priv; if (!(port & 1)) - dev->gpio_regs[0] = (dev->gpio_regs[0] & 0xfc) | (val & 0x03); + dev->gpio_regs[0] = (dev->gpio_regs[0] & 0xfc) | (val & 0x03); } - static void fdc37c67x_fdc_handler(fdc37c67x_t *dev) { - uint16_t ld_port = 0; - uint8_t global_enable = !!(dev->regs[0x22] & (1 << 0)); - uint8_t local_enable = !!dev->ld_regs[0][0x30]; + uint16_t ld_port = 0; + uint8_t global_enable = !!(dev->regs[0x22] & (1 << 0)); + uint8_t local_enable = !!dev->ld_regs[0][0x30]; fdc_remove(dev->fdc); if (global_enable && local_enable) { - ld_port = make_port(dev, 0) & 0xFFF8; - if ((ld_port >= 0x0100) && (ld_port <= 0x0FF8)) - fdc_set_base(dev->fdc, ld_port); + ld_port = make_port(dev, 0) & 0xFFF8; + if ((ld_port >= 0x0100) && (ld_port <= 0x0FF8)) + fdc_set_base(dev->fdc, ld_port); } } - static void fdc37c67x_lpt_handler(fdc37c67x_t *dev) { - uint16_t ld_port = 0; - uint8_t global_enable = !!(dev->regs[0x22] & (1 << 3)); - uint8_t local_enable = !!dev->ld_regs[3][0x30]; - uint8_t lpt_irq = dev->ld_regs[3][0x70]; + uint16_t ld_port = 0; + uint8_t global_enable = !!(dev->regs[0x22] & (1 << 3)); + uint8_t local_enable = !!dev->ld_regs[3][0x30]; + uint8_t lpt_irq = dev->ld_regs[3][0x70]; if (lpt_irq > 15) - lpt_irq = 0xff; + lpt_irq = 0xff; lpt1_remove(); if (global_enable && local_enable) { - ld_port = make_port(dev, 3) & 0xFFFC; - if ((ld_port >= 0x0100) && (ld_port <= 0x0FFC)) - lpt1_init(ld_port); + ld_port = make_port(dev, 3) & 0xFFFC; + if ((ld_port >= 0x0100) && (ld_port <= 0x0FFC)) + lpt1_init(ld_port); } lpt1_irq(lpt_irq); } - static void fdc37c67x_serial_handler(fdc37c67x_t *dev, int uart) { - uint16_t ld_port = 0; - uint8_t uart_no = 4 + uart; - uint8_t global_enable = !!(dev->regs[0x22] & (1 << uart_no)); - uint8_t local_enable = !!dev->ld_regs[uart_no][0x30]; + uint16_t ld_port = 0; + uint8_t uart_no = 4 + uart; + uint8_t global_enable = !!(dev->regs[0x22] & (1 << uart_no)); + uint8_t local_enable = !!dev->ld_regs[uart_no][0x30]; serial_remove(dev->uart[uart]); if (global_enable && local_enable) { - ld_port = make_port(dev, uart_no) & 0xFFF8; - if ((ld_port >= 0x0100) && (ld_port <= 0x0FF8)) - serial_setup(dev->uart[uart], ld_port, dev->ld_regs[uart_no][0x70]); + ld_port = make_port(dev, uart_no) & 0xFFF8; + if ((ld_port >= 0x0100) && (ld_port <= 0x0FF8)) + serial_setup(dev->uart[uart], ld_port, dev->ld_regs[uart_no][0x70]); } } - static void fdc37c67x_auxio_handler(fdc37c67x_t *dev) { - uint16_t ld_port = 0; - uint8_t local_enable = !!dev->ld_regs[8][0x30]; + uint16_t ld_port = 0; + uint8_t local_enable = !!dev->ld_regs[8][0x30]; io_removehandler(dev->auxio_base, 0x0001, - fdc37c67x_auxio_read, NULL, NULL, fdc37c67x_auxio_write, NULL, NULL, dev); + fdc37c67x_auxio_read, NULL, NULL, fdc37c67x_auxio_write, NULL, NULL, dev); if (local_enable) { - dev->auxio_base = ld_port = make_port(dev, 8); - if ((ld_port >= 0x0100) && (ld_port <= 0x0FFF)) - io_sethandler(dev->auxio_base, 0x0001, - fdc37c67x_auxio_read, NULL, NULL, fdc37c67x_auxio_write, NULL, NULL, dev); + dev->auxio_base = ld_port = make_port(dev, 8); + if ((ld_port >= 0x0100) && (ld_port <= 0x0FFF)) + io_sethandler(dev->auxio_base, 0x0001, + fdc37c67x_auxio_read, NULL, NULL, fdc37c67x_auxio_write, NULL, NULL, dev); } } - static void -fdc37c67x_sio_handler(fdc37c67x_t *dev) +fdc37c67x_sio_handler(UNUSED(fdc37c67x_t *dev)) { #if 0 if (dev->sio_base) { - io_removehandler(dev->sio_base, 0x0002, - fdc37c67x_read, NULL, NULL, fdc37c67x_write, NULL, NULL, dev); + io_removehandler(dev->sio_base, 0x0002, + fdc37c67x_read, NULL, NULL, fdc37c67x_write, NULL, NULL, dev); } dev->sio_base = (((uint16_t) dev->regs[0x27]) << 8) | dev->regs[0x26]; if (dev->sio_base) { - io_sethandler(dev->sio_base, 0x0002, - fdc37c67x_read, NULL, NULL, fdc37c67x_write, NULL, NULL, dev); + io_sethandler(dev->sio_base, 0x0002, + fdc37c67x_read, NULL, NULL, fdc37c67x_write, NULL, NULL, dev); } #endif } - static void fdc37c67x_gpio_handler(fdc37c67x_t *dev) { uint16_t ld_port = 0; - uint8_t local_enable; + uint8_t local_enable; local_enable = !!(dev->regs[0x03] & 0x80); io_removehandler(dev->gpio_base, 0x0002, - fdc37c67x_gpio_read, NULL, NULL, fdc37c67x_gpio_write, NULL, NULL, dev); + fdc37c67x_gpio_read, NULL, NULL, fdc37c67x_gpio_write, NULL, NULL, dev); if (local_enable) { - switch (dev->regs[0x03] & 0x03) { - case 0: - ld_port = 0xe0; - break; - case 1: - ld_port = 0xe2; - break; - case 2: - ld_port = 0xe4; - break; - case 3: - ld_port = 0xea; /* Default */ - break; - } - dev->gpio_base = ld_port; - if (ld_port > 0x0000) - io_sethandler(dev->gpio_base, 0x0002, - fdc37c67x_gpio_read, NULL, NULL, fdc37c67x_gpio_write, NULL, NULL, dev); + switch (dev->regs[0x03] & 0x03) { + case 0: + ld_port = 0xe0; + break; + case 1: + ld_port = 0xe2; + break; + case 2: + ld_port = 0xe4; + break; + case 3: + ld_port = 0xea; /* Default */ + break; + + default: + break; + } + dev->gpio_base = ld_port; + if (ld_port > 0x0000) + io_sethandler(dev->gpio_base, 0x0002, + fdc37c67x_gpio_read, NULL, NULL, fdc37c67x_gpio_write, NULL, NULL, dev); } } - static void fdc37c67x_smi_handler(fdc37c67x_t *dev) { @@ -243,258 +236,280 @@ fdc37c67x_smi_handler(fdc37c67x_t *dev) pic_set_smi_irq_mask(10, dev->ld_regs[8][0xb5] & 0x80); } - static void fdc37c67x_write(uint16_t port, uint8_t val, void *priv) { - fdc37c67x_t *dev = (fdc37c67x_t *) priv; - uint8_t index = (port & 1) ? 0 : 1; - uint8_t valxor = 0x00, keep = 0x00; + fdc37c67x_t *dev = (fdc37c67x_t *) priv; + uint8_t index = (port & 1) ? 0 : 1; + uint8_t valxor = 0x00; + uint8_t keep = 0x00; if (index) { - if ((val == 0x55) && !dev->locked) { - if (dev->tries) { - dev->locked = 1; - fdc_3f1_enable(dev->fdc, 0); - dev->tries = 0; - } else - dev->tries++; - } else { - if (dev->locked) { - if (val == 0xaa) { - dev->locked = 0; - fdc_3f1_enable(dev->fdc, 1); - return; - } - dev->cur_reg = val; - } else { - if (dev->tries) - dev->tries = 0; - } - } - return; + if ((val == 0x55) && !dev->locked) { + if (dev->tries) { + dev->locked = 1; + fdc_3f1_enable(dev->fdc, 0); + dev->tries = 0; + } else + dev->tries++; + } else { + if (dev->locked) { + if (val == 0xaa) { + dev->locked = 0; + fdc_3f1_enable(dev->fdc, 1); + return; + } + dev->cur_reg = val; + } else { + if (dev->tries) + dev->tries = 0; + } + } + return; } else { - if (dev->locked) { - if (dev->cur_reg < 48) { - valxor = val ^ dev->regs[dev->cur_reg]; - if ((val == 0x20) || (val == 0x21)) - return; - dev->regs[dev->cur_reg] = val; - } else { - valxor = val ^ dev->ld_regs[dev->regs[7]][dev->cur_reg]; - if (((dev->cur_reg & 0xF0) == 0x70) && (dev->regs[7] < 4)) - return; - /* Block writes to some logical devices. */ - if (dev->regs[7] > 0x0a) - return; - else switch (dev->regs[7]) { - case 0x01: - case 0x02: - case 0x07: - return; - } - dev->ld_regs[dev->regs[7]][dev->cur_reg] = val | keep; - } - } else - return; + if (dev->locked) { + if (dev->cur_reg < 48) { + valxor = val ^ dev->regs[dev->cur_reg]; + if ((val == 0x20) || (val == 0x21)) + return; + dev->regs[dev->cur_reg] = val; + } else { + valxor = val ^ dev->ld_regs[dev->regs[7]][dev->cur_reg]; + if (((dev->cur_reg & 0xF0) == 0x70) && (dev->regs[7] < 4)) + return; + /* Block writes to some logical devices. */ + if (dev->regs[7] > 0x0a) + return; + else + switch (dev->regs[7]) { + case 0x01: + case 0x02: + case 0x07: + return; + + default: + break; + } + dev->ld_regs[dev->regs[7]][dev->cur_reg] = val | keep; + } + } else + return; } if (dev->cur_reg < 48) { - switch(dev->cur_reg) { - case 0x03: - if (valxor & 0x83) - fdc37c67x_gpio_handler(dev); - dev->regs[0x03] &= 0x83; - break; - case 0x22: - if (valxor & 0x01) - fdc37c67x_fdc_handler(dev); - if (valxor & 0x08) - fdc37c67x_lpt_handler(dev); - if (valxor & 0x10) - fdc37c67x_serial_handler(dev, 0); - if (valxor & 0x20) - fdc37c67x_serial_handler(dev, 1); - break; - case 0x26: case 0x27: - fdc37c67x_sio_handler(dev); - } + switch (dev->cur_reg) { + case 0x03: + if (valxor & 0x83) + fdc37c67x_gpio_handler(dev); + dev->regs[0x03] &= 0x83; + break; + case 0x22: + if (valxor & 0x01) + fdc37c67x_fdc_handler(dev); + if (valxor & 0x08) + fdc37c67x_lpt_handler(dev); + if (valxor & 0x10) + fdc37c67x_serial_handler(dev, 0); + if (valxor & 0x20) + fdc37c67x_serial_handler(dev, 1); + break; + case 0x26: + case 0x27: + fdc37c67x_sio_handler(dev); + break; - return; + default: + break; + } + + return; } - switch(dev->regs[7]) { - case 0: - /* FDD */ - switch(dev->cur_reg) { - case 0x30: - case 0x60: - case 0x61: - if ((dev->cur_reg == 0x30) && (val & 0x01)) - dev->regs[0x22] |= 0x01; - if (valxor) - fdc37c67x_fdc_handler(dev); - break; - case 0xF0: - if (valxor & 0x01) - fdc_update_enh_mode(dev->fdc, val & 0x01); - if (valxor & 0x10) - fdc_set_swap(dev->fdc, (val & 0x10) >> 4); - break; - case 0xF1: - if (valxor & 0xC) - fdc_update_densel_force(dev->fdc, (val & 0xc) >> 2); - break; - case 0xF2: - if (valxor & 0xC0) - fdc_update_rwc(dev->fdc, 3, (val & 0xc0) >> 6); - if (valxor & 0x30) - fdc_update_rwc(dev->fdc, 2, (val & 0x30) >> 4); - if (valxor & 0x0C) - fdc_update_rwc(dev->fdc, 1, (val & 0x0c) >> 2); - if (valxor & 0x03) - fdc_update_rwc(dev->fdc, 0, (val & 0x03)); - break; - case 0xF4: - if (valxor & 0x18) - fdc_update_drvrate(dev->fdc, 0, (val & 0x18) >> 3); - break; - case 0xF5: - if (valxor & 0x18) - fdc_update_drvrate(dev->fdc, 1, (val & 0x18) >> 3); - break; - case 0xF6: - if (valxor & 0x18) - fdc_update_drvrate(dev->fdc, 2, (val & 0x18) >> 3); - break; - case 0xF7: - if (valxor & 0x18) - fdc_update_drvrate(dev->fdc, 3, (val & 0x18) >> 3); - break; - } - break; - case 3: - /* Parallel port */ - switch(dev->cur_reg) { - case 0x30: - case 0x60: - case 0x61: - case 0x70: - if ((dev->cur_reg == 0x30) && (val & 0x01)) - dev->regs[0x22] |= 0x08; - if (valxor) - fdc37c67x_lpt_handler(dev); - if (dev->cur_reg == 0x70) - fdc37c67x_smi_handler(dev); - break; - } - break; - case 4: - /* Serial port 1 */ - switch(dev->cur_reg) { - case 0x30: - case 0x60: - case 0x61: - case 0x70: - if ((dev->cur_reg == 0x30) && (val & 0x01)) - dev->regs[0x22] |= 0x10; - if (valxor) - fdc37c67x_serial_handler(dev, 0); - if (dev->cur_reg == 0x70) - fdc37c67x_smi_handler(dev); - break; - } - break; - case 5: - /* Serial port 2 */ - switch(dev->cur_reg) { - case 0x30: - case 0x60: - case 0x61: - case 0x70: - if ((dev->cur_reg == 0x30) && (val & 0x01)) - dev->regs[0x22] |= 0x20; - if (valxor) - fdc37c67x_serial_handler(dev, 1); - if (dev->cur_reg == 0x70) - fdc37c67x_smi_handler(dev); - break; - } - break; - case 8: - /* Auxiliary I/O */ - switch(dev->cur_reg) { - case 0x30: - case 0x60: - case 0x61: - case 0x70: - if (valxor) - fdc37c67x_auxio_handler(dev); - break; - case 0xb4: - case 0xb5: - fdc37c67x_smi_handler(dev); - break; - } - break; + switch (dev->regs[7]) { + case 0: + /* FDD */ + switch (dev->cur_reg) { + case 0x30: + case 0x60: + case 0x61: + if ((dev->cur_reg == 0x30) && (val & 0x01)) + dev->regs[0x22] |= 0x01; + if (valxor) + fdc37c67x_fdc_handler(dev); + break; + case 0xF0: + if (valxor & 0x01) + fdc_update_enh_mode(dev->fdc, val & 0x01); + if (valxor & 0x10) + fdc_set_swap(dev->fdc, (val & 0x10) >> 4); + break; + case 0xF1: + if (valxor & 0xC) + fdc_update_densel_force(dev->fdc, (val & 0xc) >> 2); + break; + case 0xF2: + if (valxor & 0xC0) + fdc_update_rwc(dev->fdc, 3, (val & 0xc0) >> 6); + if (valxor & 0x30) + fdc_update_rwc(dev->fdc, 2, (val & 0x30) >> 4); + if (valxor & 0x0C) + fdc_update_rwc(dev->fdc, 1, (val & 0x0c) >> 2); + if (valxor & 0x03) + fdc_update_rwc(dev->fdc, 0, (val & 0x03)); + break; + case 0xF4: + if (valxor & 0x18) + fdc_update_drvrate(dev->fdc, 0, (val & 0x18) >> 3); + break; + case 0xF5: + if (valxor & 0x18) + fdc_update_drvrate(dev->fdc, 1, (val & 0x18) >> 3); + break; + case 0xF6: + if (valxor & 0x18) + fdc_update_drvrate(dev->fdc, 2, (val & 0x18) >> 3); + break; + case 0xF7: + if (valxor & 0x18) + fdc_update_drvrate(dev->fdc, 3, (val & 0x18) >> 3); + break; + + default: + break; + } + break; + case 3: + /* Parallel port */ + switch (dev->cur_reg) { + case 0x30: + case 0x60: + case 0x61: + case 0x70: + if ((dev->cur_reg == 0x30) && (val & 0x01)) + dev->regs[0x22] |= 0x08; + if (valxor) + fdc37c67x_lpt_handler(dev); + if (dev->cur_reg == 0x70) + fdc37c67x_smi_handler(dev); + break; + + default: + break; + } + break; + case 4: + /* Serial port 1 */ + switch (dev->cur_reg) { + case 0x30: + case 0x60: + case 0x61: + case 0x70: + if ((dev->cur_reg == 0x30) && (val & 0x01)) + dev->regs[0x22] |= 0x10; + if (valxor) + fdc37c67x_serial_handler(dev, 0); + if (dev->cur_reg == 0x70) + fdc37c67x_smi_handler(dev); + break; + + default: + break; + } + break; + case 5: + /* Serial port 2 */ + switch (dev->cur_reg) { + case 0x30: + case 0x60: + case 0x61: + case 0x70: + if ((dev->cur_reg == 0x30) && (val & 0x01)) + dev->regs[0x22] |= 0x20; + if (valxor) + fdc37c67x_serial_handler(dev, 1); + if (dev->cur_reg == 0x70) + fdc37c67x_smi_handler(dev); + break; + + default: + break; + } + break; + case 8: + /* Auxiliary I/O */ + switch (dev->cur_reg) { + case 0x30: + case 0x60: + case 0x61: + case 0x70: + if (valxor) + fdc37c67x_auxio_handler(dev); + break; + case 0xb4: + case 0xb5: + fdc37c67x_smi_handler(dev); + break; + + default: + break; + } + break; + + default: + break; } } - static uint8_t fdc37c67x_read(uint16_t port, void *priv) { - fdc37c67x_t *dev = (fdc37c67x_t *) priv; - uint8_t index = (port & 1) ? 0 : 1; - uint8_t ret = 0xff; - uint16_t smi_stat = pic_get_smi_irq_status(); - int f_irq = dev->ld_regs[0][0x70]; - int p_irq = dev->ld_regs[3][0x70]; - int s1_irq = dev->ld_regs[4][0x70]; - int s2_irq = dev->ld_regs[5][0x70]; + fdc37c67x_t *dev = (fdc37c67x_t *) priv; + uint8_t index = (port & 1) ? 0 : 1; + uint8_t ret = 0xff; + uint16_t smi_stat = pic_get_smi_irq_status(); + int f_irq = dev->ld_regs[0][0x70]; + int p_irq = dev->ld_regs[3][0x70]; + int s1_irq = dev->ld_regs[4][0x70]; + int s2_irq = dev->ld_regs[5][0x70]; if (dev->locked) { - if (index) - ret = dev->cur_reg; - else { - if (dev->cur_reg < 0x30) { - if (dev->cur_reg == 0x20) - ret = dev->chip_id; - else - ret = dev->regs[dev->cur_reg]; - } else { - if ((dev->regs[7] == 0) && (dev->cur_reg == 0xF2)) { - ret = (fdc_get_rwc(dev->fdc, 0) | (fdc_get_rwc(dev->fdc, 1) << 2) | - (fdc_get_rwc(dev->fdc, 2) << 4) | (fdc_get_rwc(dev->fdc, 3) << 6)); - } else - ret = dev->ld_regs[dev->regs[7]][dev->cur_reg]; + if (index) + ret = dev->cur_reg; + else { + if (dev->cur_reg < 0x30) { + if (dev->cur_reg == 0x20) + ret = dev->chip_id; + else + ret = dev->regs[dev->cur_reg]; + } else { + if ((dev->regs[7] == 0) && (dev->cur_reg == 0xF2)) { + ret = (fdc_get_rwc(dev->fdc, 0) | (fdc_get_rwc(dev->fdc, 1) << 2) | (fdc_get_rwc(dev->fdc, 2) << 4) | (fdc_get_rwc(dev->fdc, 3) << 6)); + } else + ret = dev->ld_regs[dev->regs[7]][dev->cur_reg]; - /* TODO: 8042 P1.2 SMI#. */ - if ((dev->regs[7] == 8) && (dev->cur_reg == 0xb6)) { - ret = dev->ld_regs[dev->regs[7]][dev->cur_reg] & 0xe1; - ret |= ((!!(smi_stat & (1 << p_irq))) << 1); - ret |= ((!!(smi_stat & (1 << s2_irq))) << 2); - ret |= ((!!(smi_stat & (1 << s1_irq))) << 3); - ret |= ((!!(smi_stat & (1 << f_irq))) << 4); - } else if ((dev->regs[7] == 8) && (dev->cur_reg == 0xb7)) { - ret = dev->ld_regs[dev->regs[7]][dev->cur_reg] & 0xec; - ret |= ((!!(smi_stat & (1 << 12))) << 0); - ret |= ((!!(smi_stat & (1 << 1))) << 1); - ret |= ((!!(smi_stat & (1 << 10))) << 4); - } - } - } + /* TODO: 8042 P1.2 SMI#. */ + if ((dev->regs[7] == 8) && (dev->cur_reg == 0xb6)) { + ret = dev->ld_regs[dev->regs[7]][dev->cur_reg] & 0xe1; + ret |= ((!!(smi_stat & (1 << p_irq))) << 1); + ret |= ((!!(smi_stat & (1 << s2_irq))) << 2); + ret |= ((!!(smi_stat & (1 << s1_irq))) << 3); + ret |= ((!!(smi_stat & (1 << f_irq))) << 4); + } else if ((dev->regs[7] == 8) && (dev->cur_reg == 0xb7)) { + ret = dev->ld_regs[dev->regs[7]][dev->cur_reg] & 0xec; + ret |= ((!!(smi_stat & (1 << 12))) << 0); + ret |= ((!!(smi_stat & (1 << 1))) << 1); + ret |= ((!!(smi_stat & (1 << 10))) << 4); + } + } + } } return ret; } - static void fdc37c67x_reset(fdc37c67x_t *dev) { - int i = 0; - memset(dev->regs, 0, 48); dev->regs[0x03] = 0x03; @@ -504,8 +519,8 @@ fdc37c67x_reset(fdc37c67x_t *dev) dev->regs[0x26] = 0xf0; dev->regs[0x27] = 0x03; - for (i = 0; i < 11; i++) - memset(dev->ld_regs[i], 0, 256); + for (uint8_t i = 0; i < 11; i++) + memset(dev->ld_regs[i], 0, 256); /* Logical device 0: FDD */ dev->ld_regs[0][0x30] = 1; @@ -530,7 +545,7 @@ fdc37c67x_reset(fdc37c67x_t *dev) dev->ld_regs[4][0x61] = 0xf8; dev->ld_regs[4][0x70] = 4; dev->ld_regs[4][0xf0] = 3; - serial_setup(dev->uart[0], 0x3f8, dev->ld_regs[4][0x70]); + serial_setup(dev->uart[0], COM1_ADDR, dev->ld_regs[4][0x70]); /* Logical device 5: Serial Port 2 */ dev->ld_regs[5][0x30] = 1; @@ -540,7 +555,7 @@ fdc37c67x_reset(fdc37c67x_t *dev) dev->ld_regs[5][0x74] = 4; dev->ld_regs[5][0xf1] = 2; dev->ld_regs[5][0xf2] = 3; - serial_setup(dev->uart[1], 0x2f8, dev->ld_regs[5][0x70]); + serial_setup(dev->uart[1], COM2_ADDR, dev->ld_regs[5][0x70]); /* Logical device 7: Keyboard */ dev->ld_regs[7][0x30] = 1; @@ -565,7 +580,6 @@ fdc37c67x_reset(fdc37c67x_t *dev) dev->locked = 0; } - static void fdc37c67x_close(void *priv) { @@ -574,7 +588,6 @@ fdc37c67x_close(void *priv) free(dev); } - static void * fdc37c67x_init(const device_t *info) { @@ -589,26 +602,31 @@ fdc37c67x_init(const device_t *info) dev->chip_id = info->local & 0xff; dev->gpio_regs[0] = 0xff; - // dev->gpio_regs[1] = (info->local == 0x0030) ? 0xff : 0xfd; +#if 0 + dev->gpio_regs[1] = (info->local == 0x0030) ? 0xff : 0xfd; +#endif dev->gpio_regs[1] = (dev->chip_id == 0x30) ? 0xff : 0xfd; fdc37c67x_reset(dev); - io_sethandler(0x370, 0x0002, - fdc37c67x_read, NULL, NULL, fdc37c67x_write, NULL, NULL, dev); - io_sethandler(0x3f0, 0x0002, - fdc37c67x_read, NULL, NULL, fdc37c67x_write, NULL, NULL, dev); + io_sethandler(FDC_SECONDARY_ADDR, 0x0002, + fdc37c67x_read, NULL, NULL, fdc37c67x_write, NULL, NULL, dev); + io_sethandler(FDC_PRIMARY_ADDR, 0x0002, + fdc37c67x_read, NULL, NULL, fdc37c67x_write, NULL, NULL, dev); return dev; } - const device_t fdc37c67x_device = { - "SMC FDC37C67X Super I/O", - "fdc37c67x", - 0, - 0x40, - fdc37c67x_init, fdc37c67x_close, NULL, - { NULL }, NULL, NULL, - NULL + .name = "SMC FDC37C67X Super I/O", + .internal_name = "fdc37c67x", + .flags = 0, + .local = 0x40, + .init = fdc37c67x_init, + .close = fdc37c67x_close, + .reset = NULL, + { .available = NULL }, + .speed_changed = NULL, + .force_redraw = NULL, + .config = NULL }; diff --git a/src/sio/sio_fdc37c6xx.c b/src/sio/sio_fdc37c6xx.c index 89b90d332..23fcd2fb3 100644 --- a/src/sio/sio_fdc37c6xx.c +++ b/src/sio/sio_fdc37c6xx.c @@ -1,21 +1,19 @@ /* - * 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. + * 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. + * This file is part of the 86Box distribution. * - * Implementation of the SMC FDC37C663 and FDC37C665 Super - * I/O Chips. + * Implementation of the SMC FDC37C663 and FDC37C665 Super + * I/O Chips. * * * - * Authors: Sarah Walker, - * Miran Grca, + * Authors: Miran Grca, * - * Copyright 2008-2020 Sarah Walker. - * Copyright 2016-2020 Miran Grca. + * Copyright 2016-2020 Miran Grca. */ #include #include @@ -35,207 +33,212 @@ #include <86box/fdc.h> #include <86box/sio.h> - -typedef struct { - uint8_t max_reg, chip_id, - tries, has_ide, - regs[16]; - int cur_reg, - com3_addr, com4_addr; - fdc_t *fdc; +typedef struct fdc37c6xx_t { + uint8_t max_reg; + uint8_t chip_id; + uint8_t tries; + uint8_t has_ide; + uint8_t regs[16]; + int cur_reg; + int com3_addr; + int com4_addr; + fdc_t *fdc; serial_t *uart[2]; } fdc37c6xx_t; - static void set_com34_addr(fdc37c6xx_t *dev) { switch (dev->regs[1] & 0x60) { - case 0x00: - dev->com3_addr = 0x338; - dev->com4_addr = 0x238; - break; - case 0x20: - dev->com3_addr = 0x3e8; - dev->com4_addr = 0x2e8; - break; - case 0x40: - dev->com3_addr = 0x3e8; - dev->com4_addr = 0x2e0; - break; - case 0x60: - dev->com3_addr = 0x220; - dev->com4_addr = 0x228; - break; + case 0x00: + dev->com3_addr = 0x338; + dev->com4_addr = 0x238; + break; + case 0x20: + dev->com3_addr = COM3_ADDR; + dev->com4_addr = COM4_ADDR; + break; + case 0x40: + dev->com3_addr = COM3_ADDR; + dev->com4_addr = 0x2e0; + break; + case 0x60: + dev->com3_addr = 0x220; + dev->com4_addr = 0x228; + break; + + default: + break; } } - static void set_serial_addr(fdc37c6xx_t *dev, int port) { - uint8_t shift = (port << 2); - double clock_src = 24000000.0 / 13.0; + uint8_t shift = (port << 2); + double clock_src = 24000000.0 / 13.0; if (dev->regs[4] & (1 << (4 + port))) - clock_src = 24000000.0 / 12.0; + clock_src = 24000000.0 / 12.0; serial_remove(dev->uart[port]); if (dev->regs[2] & (4 << shift)) { - switch ((dev->regs[2] >> shift) & 3) { - case 0: - serial_setup(dev->uart[port], SERIAL1_ADDR, SERIAL1_IRQ); - break; - case 1: - serial_setup(dev->uart[port], SERIAL2_ADDR, SERIAL2_IRQ); - break; - case 2: - serial_setup(dev->uart[port], dev->com3_addr, 4); - break; - case 3: - serial_setup(dev->uart[port], dev->com4_addr, 3); - break; - } + switch ((dev->regs[2] >> shift) & 3) { + case 0: + serial_setup(dev->uart[port], COM1_ADDR, COM1_IRQ); + break; + case 1: + serial_setup(dev->uart[port], COM2_ADDR, COM2_IRQ); + break; + case 2: + serial_setup(dev->uart[port], dev->com3_addr, COM3_IRQ); + break; + case 3: + serial_setup(dev->uart[port], dev->com4_addr, COM4_IRQ); + break; + + default: + break; + } } serial_set_clock_src(dev->uart[port], clock_src); } - static void lpt1_handler(fdc37c6xx_t *dev) { lpt1_remove(); switch (dev->regs[1] & 3) { - case 1: - lpt1_init(0x3bc); - lpt1_irq(7); - break; - case 2: - lpt1_init(0x378); - lpt1_irq(7 /*5*/); - break; - case 3: - lpt1_init(0x278); - lpt1_irq(7 /*5*/); - break; + case 1: + lpt1_init(LPT_MDA_ADDR); + lpt1_irq(7); + break; + case 2: + lpt1_init(LPT1_ADDR); + lpt1_irq(7 /*5*/); + break; + case 3: + lpt1_init(LPT2_ADDR); + lpt1_irq(7 /*5*/); + break; + + default: + break; } } - static void fdc_handler(fdc37c6xx_t *dev) { fdc_remove(dev->fdc); if (dev->regs[0] & 0x10) - fdc_set_base(dev->fdc, (dev->regs[5] & 0x01) ? 0x0370 : 0x03f0); + fdc_set_base(dev->fdc, (dev->regs[5] & 0x01) ? FDC_SECONDARY_ADDR : FDC_PRIMARY_ADDR); } - - static void ide_handler(fdc37c6xx_t *dev) { /* TODO: Make an ide_disable(channel) and ide_enable(channel) so we can simplify this. */ if (dev->has_ide == 2) { - ide_sec_disable(); - ide_set_base(1, (dev->regs[0x05] & 0x02) ? 0x170 : 0x1f0); - ide_set_side(1, (dev->regs[0x05] & 0x02) ? 0x376 : 0x3f6); - if (dev->regs[0x00] & 0x01) - ide_sec_enable(); + ide_sec_disable(); + ide_set_base(1, (dev->regs[0x05] & 0x02) ? 0x170 : 0x1f0); + ide_set_side(1, (dev->regs[0x05] & 0x02) ? 0x376 : 0x3f6); + if (dev->regs[0x00] & 0x01) + ide_sec_enable(); } else if (dev->has_ide == 1) { - ide_pri_disable(); - ide_set_base(0, (dev->regs[0x05] & 0x02) ? 0x170 : 0x1f0); - ide_set_side(0, (dev->regs[0x05] & 0x02) ? 0x376 : 0x3f6); - if (dev->regs[0x00] & 0x01) - ide_pri_enable(); + ide_pri_disable(); + ide_set_base(0, (dev->regs[0x05] & 0x02) ? 0x170 : 0x1f0); + ide_set_side(0, (dev->regs[0x05] & 0x02) ? 0x376 : 0x3f6); + if (dev->regs[0x00] & 0x01) + ide_pri_enable(); } } - static void fdc37c6xx_write(uint16_t port, uint8_t val, void *priv) { - fdc37c6xx_t *dev = (fdc37c6xx_t *) priv; - uint8_t valxor = 0; + fdc37c6xx_t *dev = (fdc37c6xx_t *) priv; + uint8_t valxor = 0; if (dev->tries == 2) { - if (port == 0x3f0) { - if (val == 0xaa) - dev->tries = 0; - else - dev->cur_reg = val; - } else { - if (dev->cur_reg > dev->max_reg) - return; + if (port == FDC_PRIMARY_ADDR) { + if (val == 0xaa) + dev->tries = 0; + else + dev->cur_reg = val; + } else { + if (dev->cur_reg > dev->max_reg) + return; - valxor = val ^ dev->regs[dev->cur_reg]; - dev->regs[dev->cur_reg] = val; + valxor = val ^ dev->regs[dev->cur_reg]; + dev->regs[dev->cur_reg] = val; - switch(dev->cur_reg) { - case 0: - if (dev->has_ide && (valxor & 0x01)) - ide_handler(dev); - if (valxor & 0x10) - fdc_handler(dev); - break; - case 1: - if (valxor & 3) - lpt1_handler(dev); - if (valxor & 0x60) { - set_com34_addr(dev); - set_serial_addr(dev, 0); - set_serial_addr(dev, 1); - } - break; - case 2: - if (valxor & 7) - set_serial_addr(dev, 0); - if (valxor & 0x70) - set_serial_addr(dev, 1); - break; - case 3: - if (valxor & 2) - fdc_update_enh_mode(dev->fdc, (dev->regs[3] & 2) ? 1 : 0); - break; - case 4: - if (valxor & 0x10) - set_serial_addr(dev, 0); - if (valxor & 0x20) - set_serial_addr(dev, 1); - break; - case 5: - if (valxor & 0x01) - fdc_handler(dev); - if (dev->has_ide && (valxor & 0x02)) - ide_handler(dev); - if (valxor & 0x18) - fdc_update_densel_force(dev->fdc, (dev->regs[5] & 0x18) >> 3); - if (valxor & 0x20) - fdc_set_swap(dev->fdc, (dev->regs[5] & 0x20) >> 5); - break; - } - } - } else if ((port == 0x3f0) && (val == 0x55)) - dev->tries++; + switch (dev->cur_reg) { + case 0: + if (dev->has_ide && (valxor & 0x01)) + ide_handler(dev); + if (valxor & 0x10) + fdc_handler(dev); + break; + case 1: + if (valxor & 3) + lpt1_handler(dev); + if (valxor & 0x60) { + set_com34_addr(dev); + set_serial_addr(dev, 0); + set_serial_addr(dev, 1); + } + break; + case 2: + if (valxor & 7) + set_serial_addr(dev, 0); + if (valxor & 0x70) + set_serial_addr(dev, 1); + break; + case 3: + if (valxor & 2) + fdc_update_enh_mode(dev->fdc, (dev->regs[3] & 2) ? 1 : 0); + break; + case 4: + if (valxor & 0x10) + set_serial_addr(dev, 0); + if (valxor & 0x20) + set_serial_addr(dev, 1); + break; + case 5: + if (valxor & 0x01) + fdc_handler(dev); + if (dev->has_ide && (valxor & 0x02)) + ide_handler(dev); + if (valxor & 0x18) + fdc_update_densel_force(dev->fdc, (dev->regs[5] & 0x18) >> 3); + if (valxor & 0x20) + fdc_set_swap(dev->fdc, (dev->regs[5] & 0x20) >> 5); + break; + + default: + break; + } + } + } else if ((port == FDC_PRIMARY_ADDR) && (val == 0x55)) + dev->tries++; } - static uint8_t fdc37c6xx_read(uint16_t port, void *priv) { - fdc37c6xx_t *dev = (fdc37c6xx_t *) priv; - uint8_t ret = 0x00; + const fdc37c6xx_t *dev = (fdc37c6xx_t *) priv; + uint8_t ret = 0xff; if (dev->tries == 2) { - if (port == 0x3f1) - ret = dev->regs[dev->cur_reg]; + if (port == 0x3f1) + ret = dev->regs[dev->cur_reg]; } return ret; } - static void fdc37c6xx_reset(fdc37c6xx_t *dev) { @@ -243,13 +246,13 @@ fdc37c6xx_reset(fdc37c6xx_t *dev) dev->com4_addr = 0x238; serial_remove(dev->uart[0]); - serial_setup(dev->uart[0], SERIAL1_ADDR, SERIAL1_IRQ); + serial_setup(dev->uart[0], COM1_ADDR, COM1_IRQ); serial_remove(dev->uart[1]); - serial_setup(dev->uart[1], SERIAL2_ADDR, SERIAL2_IRQ); + serial_setup(dev->uart[1], COM2_ADDR, COM2_IRQ); lpt1_remove(); - lpt1_init(0x378); + lpt1_init(LPT1_ADDR); fdc_reset(dev->fdc); fdc_remove(dev->fdc); @@ -258,18 +261,20 @@ fdc37c6xx_reset(fdc37c6xx_t *dev) memset(dev->regs, 0, 16); switch (dev->chip_id) { - case 0x63: case 0x65: - dev->max_reg = 0x0f; - dev->regs[0x0] = 0x3b; - break; - case 0x64: case 0x66: - dev->max_reg = 0x0f; - dev->regs[0x0] = 0x2b; - break; - default: - dev->max_reg = (dev->chip_id >= 0x61) ? 0x03 : 0x02; - dev->regs[0x0] = 0x3f; - break; + case 0x63: + case 0x65: + dev->max_reg = 0x0f; + dev->regs[0x0] = 0x3b; + break; + case 0x64: + case 0x66: + dev->max_reg = 0x0f; + dev->regs[0x0] = 0x2b; + break; + default: + dev->max_reg = (dev->chip_id >= 0x61) ? 0x03 : 0x02; + dev->regs[0x0] = 0x3f; + break; } dev->regs[0x1] = 0x9f; @@ -277,12 +282,12 @@ fdc37c6xx_reset(fdc37c6xx_t *dev) dev->regs[0x3] = 0x78; if (dev->chip_id >= 0x63) { - dev->regs[0x6] = 0xff; - dev->regs[0xd] = dev->chip_id; - if (dev->chip_id >= 0x65) - dev->regs[0xe] = 0x02; - else - dev->regs[0xe] = 0x01; + dev->regs[0x6] = 0xff; + dev->regs[0xd] = dev->chip_id; + if (dev->chip_id >= 0x65) + dev->regs[0xe] = 0x02; + else + dev->regs[0xe] = 0x01; } set_serial_addr(dev, 0); @@ -293,10 +298,9 @@ fdc37c6xx_reset(fdc37c6xx_t *dev) fdc_handler(dev); if (dev->has_ide) - ide_handler(dev); + ide_handler(dev); } - static void fdc37c6xx_close(void *priv) { @@ -305,7 +309,6 @@ fdc37c6xx_close(void *priv) free(dev); } - static void * fdc37c6xx_init(const device_t *info) { @@ -318,110 +321,159 @@ fdc37c6xx_init(const device_t *info) dev->has_ide = (info->local >> 8) & 0xff; if (dev->chip_id >= 0x63) { - dev->uart[0] = device_add_inst(&ns16550_device, 1); - dev->uart[1] = device_add_inst(&ns16550_device, 2); + dev->uart[0] = device_add_inst(&ns16550_device, 1); + dev->uart[1] = device_add_inst(&ns16550_device, 2); } else { - dev->uart[0] = device_add_inst(&ns16450_device, 1); - dev->uart[1] = device_add_inst(&ns16450_device, 2); + dev->uart[0] = device_add_inst(&ns16450_device, 1); + dev->uart[1] = device_add_inst(&ns16450_device, 2); } - io_sethandler(0x03f0, 0x0002, - fdc37c6xx_read, NULL, NULL, fdc37c6xx_write, NULL, NULL, dev); + io_sethandler(FDC_PRIMARY_ADDR, 0x0002, + fdc37c6xx_read, NULL, NULL, fdc37c6xx_write, NULL, NULL, dev); fdc37c6xx_reset(dev); return dev; } - /* The three appear to differ only in the chip ID, if I understood their datasheets correctly. */ const device_t fdc37c651_device = { - "SMC FDC37C651 Super I/O", - "fdc37c651", - 0, - 0x51, - fdc37c6xx_init, fdc37c6xx_close, NULL, - { NULL }, NULL, NULL, - NULL + .name = "SMC FDC37C651 Super I/O", + .internal_name = "fdc37c651", + .flags = 0, + .local = 0x51, + .init = fdc37c6xx_init, + .close = fdc37c6xx_close, + .reset = NULL, + { .available = NULL }, + .speed_changed = NULL, + .force_redraw = NULL, + .config = NULL }; const device_t fdc37c651_ide_device = { - "SMC FDC37C651 Super I/O (With IDE)", - "fdc37c651_ide", - 0, - 0x151, - fdc37c6xx_init, fdc37c6xx_close, NULL, - { NULL }, NULL, NULL, - NULL + .name = "SMC FDC37C651 Super I/O (With IDE)", + .internal_name = "fdc37c651_ide", + .flags = 0, + .local = 0x151, + .init = fdc37c6xx_init, + .close = fdc37c6xx_close, + .reset = NULL, + { .available = NULL }, + .speed_changed = NULL, + .force_redraw = NULL, + .config = NULL }; const device_t fdc37c661_device = { - "SMC FDC37C661 Super I/O", - "fdc37c661", - 0, - 0x61, - fdc37c6xx_init, fdc37c6xx_close, NULL, - { NULL }, NULL, NULL, - NULL + .name = "SMC FDC37C661 Super I/O", + .internal_name = "fdc37c661", + .flags = 0, + .local = 0x61, + .init = fdc37c6xx_init, + .close = fdc37c6xx_close, + .reset = NULL, + { .available = NULL }, + .speed_changed = NULL, + .force_redraw = NULL, + .config = NULL }; const device_t fdc37c661_ide_device = { - "SMC FDC37C661 Super I/O (With IDE)", - "fdc37c661_ide", - 0, - 0x161, - fdc37c6xx_init, fdc37c6xx_close, NULL, - { NULL }, NULL, NULL, - NULL + .name = "SMC FDC37C661 Super I/O (With IDE)", + .internal_name = "fdc37c661_ide", + .flags = 0, + .local = 0x161, + .init = fdc37c6xx_init, + .close = fdc37c6xx_close, + .reset = NULL, + { .available = NULL }, + .speed_changed = NULL, + .force_redraw = NULL, + .config = NULL }; const device_t fdc37c663_device = { - "SMC FDC37C663 Super I/O", - "fdc37c663", - 0, - 0x63, - fdc37c6xx_init, fdc37c6xx_close, NULL, - { NULL }, NULL, NULL, - NULL + .name = "SMC FDC37C663 Super I/O", + .internal_name = "fdc37c663", + .flags = 0, + .local = 0x63, + .init = fdc37c6xx_init, + .close = fdc37c6xx_close, + .reset = NULL, + { .available = NULL }, + .speed_changed = NULL, + .force_redraw = NULL, + .config = NULL }; const device_t fdc37c663_ide_device = { - "SMC FDC37C663 Super I/O (With IDE)", - "fdc37c663_ide", - 0, - 0x163, - fdc37c6xx_init, fdc37c6xx_close, NULL, - { NULL }, NULL, NULL, - NULL + .name = "SMC FDC37C663 Super I/O (With IDE)", + .internal_name = "fdc37c663_ide", + .flags = 0, + .local = 0x163, + .init = fdc37c6xx_init, + .close = fdc37c6xx_close, + .reset = NULL, + { .available = NULL }, + .speed_changed = NULL, + .force_redraw = NULL, + .config = NULL }; const device_t fdc37c665_device = { - "SMC FDC37C665 Super I/O", - "fdc37c665", - 0, - 0x65, - fdc37c6xx_init, fdc37c6xx_close, NULL, - { NULL }, NULL, NULL, - NULL + .name = "SMC FDC37C665 Super I/O", + .internal_name = "fdc37c665", + .flags = 0, + .local = 0x65, + .init = fdc37c6xx_init, + .close = fdc37c6xx_close, + .reset = NULL, + { .available = NULL }, + .speed_changed = NULL, + .force_redraw = NULL, + .config = NULL }; const device_t fdc37c665_ide_device = { - "SMC FDC37C665 Super I/O (With IDE)", - "fdc37c665_ide", - 0, - 0x265, - fdc37c6xx_init, fdc37c6xx_close, NULL, - { NULL }, NULL, NULL, - NULL + .name = "SMC FDC37C665 Super I/O (With IDE)", + .internal_name = "fdc37c665_ide", + .flags = 0, + .local = 0x265, + .init = fdc37c6xx_init, + .close = fdc37c6xx_close, + .reset = NULL, + { .available = NULL }, + .speed_changed = NULL, + .force_redraw = NULL, + .config = NULL +}; + +const device_t fdc37c665_ide_pri_device = { + .name = "SMC FDC37C665 Super I/O (With Primary IDE)", + .internal_name = "fdc37c665_ide_pri", + .flags = 0, + .local = 0x165, + .init = fdc37c6xx_init, + .close = fdc37c6xx_close, + .reset = NULL, + { .available = NULL }, + .speed_changed = NULL, + .force_redraw = NULL, + .config = NULL }; const device_t fdc37c666_device = { - "SMC FDC37C666 Super I/O", - "fdc37c666", - 0, - 0x66, - fdc37c6xx_init, fdc37c6xx_close, NULL, - { NULL }, NULL, NULL, - NULL + .name = "SMC FDC37C666 Super I/O", + .internal_name = "fdc37c666", + .flags = 0, + .local = 0x66, + .init = fdc37c6xx_init, + .close = fdc37c6xx_close, + .reset = NULL, + { .available = NULL }, + .speed_changed = NULL, + .force_redraw = NULL, + .config = NULL }; diff --git a/src/sio/sio_fdc37c93x.c b/src/sio/sio_fdc37c93x.c index 1747df076..4acbfeff5 100644 --- a/src/sio/sio_fdc37c93x.c +++ b/src/sio/sio_fdc37c93x.c @@ -1,18 +1,19 @@ /* - * 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. + * 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. + * This file is part of the 86Box distribution. * - * Implementation of the SMC FDC37C932FR and FDC37C935 Super - * I/O Chips. + * Implementation of the SMC FDC37C932FR and FDC37C935 Super + * I/O Chips. * * * - * Author: Miran Grca, - * Copyright 2016-2018 Miran Grca. + * Authors: Miran Grca, + * + * Copyright 2016-2018 Miran Grca. */ #include #include @@ -34,38 +35,39 @@ #include <86box/apm.h> #include <86box/acpi.h> #include <86box/sio.h> +#include <86box/plat_unused.h> +#define AB_RST 0x80 -#define AB_RST 0x80 - - -typedef struct { - uint8_t control; - uint8_t status; - uint8_t own_addr; - uint8_t data; - uint8_t clock; - uint16_t base; +typedef struct access_bus_t { + uint8_t control; + uint8_t status; + uint8_t own_addr; + uint8_t data; + uint8_t clock; + uint16_t base; } access_bus_t; -typedef struct { - uint8_t chip_id, is_apm, - tries, - gpio_regs[2], auxio_reg, - regs[48], - ld_regs[11][256]; - uint16_t gpio_base, /* Set to EA */ - auxio_base, nvr_sec_base; - int locked, - cur_reg; - fdc_t *fdc; - serial_t *uart[2]; +typedef struct fdc37c93x_t { + uint8_t chip_id; + uint8_t is_apm; + uint8_t tries; + uint8_t gpio_regs[2]; + uint8_t auxio_reg; + uint8_t regs[48]; + uint8_t ld_regs[11][256]; + uint16_t gpio_base; /* Set to EA */ + uint16_t auxio_base; + uint16_t nvr_sec_base; + int locked; + int cur_reg; + fdc_t *fdc; + serial_t *uart[2]; access_bus_t *access_bus; - nvr_t *nvr; - acpi_t *acpi; + nvr_t *nvr; + acpi_t *acpi; } fdc37c93x_t; - static uint16_t make_port(fdc37c93x_t *dev, uint8_t ld) { @@ -77,7 +79,6 @@ make_port(fdc37c93x_t *dev, uint8_t ld) return p; } - static uint16_t make_port_sec(fdc37c93x_t *dev, uint8_t ld) { @@ -89,101 +90,93 @@ make_port_sec(fdc37c93x_t *dev, uint8_t ld) return p; } - static uint8_t -fdc37c93x_auxio_read(uint16_t port, void *priv) +fdc37c93x_auxio_read(UNUSED(uint16_t port), void *priv) { - fdc37c93x_t *dev = (fdc37c93x_t *) priv; + const fdc37c93x_t *dev = (fdc37c93x_t *) priv; return dev->auxio_reg; } - static void -fdc37c93x_auxio_write(uint16_t port, uint8_t val, void *priv) +fdc37c93x_auxio_write(UNUSED(uint16_t port), uint8_t val, void *priv) { fdc37c93x_t *dev = (fdc37c93x_t *) priv; dev->auxio_reg = val; } - static uint8_t fdc37c93x_gpio_read(uint16_t port, void *priv) { - fdc37c93x_t *dev = (fdc37c93x_t *) priv; - uint8_t ret = 0xff; + const fdc37c93x_t *dev = (fdc37c93x_t *) priv; + uint8_t ret = 0xff; ret = dev->gpio_regs[port & 1]; return ret; } - static void fdc37c93x_gpio_write(uint16_t port, uint8_t val, void *priv) { fdc37c93x_t *dev = (fdc37c93x_t *) priv; if (!(port & 1)) - dev->gpio_regs[0] = (dev->gpio_regs[0] & 0xfc) | (val & 0x03); + dev->gpio_regs[0] = (dev->gpio_regs[0] & 0xfc) | (val & 0x03); } - static void fdc37c93x_fdc_handler(fdc37c93x_t *dev) { - uint16_t ld_port = 0; - uint8_t global_enable = !!(dev->regs[0x22] & (1 << 0)); - uint8_t local_enable = !!dev->ld_regs[0][0x30]; + uint16_t ld_port = 0; + uint8_t global_enable = !!(dev->regs[0x22] & (1 << 0)); + uint8_t local_enable = !!dev->ld_regs[0][0x30]; fdc_remove(dev->fdc); if (global_enable && local_enable) { - ld_port = make_port(dev, 0) & 0xFFF8; - if ((ld_port >= 0x0100) && (ld_port <= 0x0FF8)) - fdc_set_base(dev->fdc, ld_port); + ld_port = make_port(dev, 0) & 0xFFF8; + if ((ld_port >= 0x0100) && (ld_port <= 0x0FF8)) + fdc_set_base(dev->fdc, ld_port); } } - static void fdc37c93x_lpt_handler(fdc37c93x_t *dev) { - uint16_t ld_port = 0; - uint8_t global_enable = !!(dev->regs[0x22] & (1 << 3)); - uint8_t local_enable = !!dev->ld_regs[3][0x30]; - uint8_t lpt_irq = dev->ld_regs[3][0x70]; + uint16_t ld_port = 0; + uint8_t global_enable = !!(dev->regs[0x22] & (1 << 3)); + uint8_t local_enable = !!dev->ld_regs[3][0x30]; + uint8_t lpt_irq = dev->ld_regs[3][0x70]; if (lpt_irq > 15) - lpt_irq = 0xff; + lpt_irq = 0xff; lpt1_remove(); if (global_enable && local_enable) { - ld_port = make_port(dev, 3) & 0xFFFC; - if ((ld_port >= 0x0100) && (ld_port <= 0x0FFC)) - lpt1_init(ld_port); + ld_port = make_port(dev, 3) & 0xFFFC; + if ((ld_port >= 0x0100) && (ld_port <= 0x0FFC)) + lpt1_init(ld_port); } lpt1_irq(lpt_irq); } - static void fdc37c93x_serial_handler(fdc37c93x_t *dev, int uart) { - uint16_t ld_port = 0; - uint8_t uart_no = 4 + uart; - uint8_t global_enable = !!(dev->regs[0x22] & (1 << uart_no)); - uint8_t local_enable = !!dev->ld_regs[uart_no][0x30]; + uint16_t ld_port = 0; + uint8_t uart_no = 4 + uart; + uint8_t global_enable = !!(dev->regs[0x22] & (1 << uart_no)); + uint8_t local_enable = !!dev->ld_regs[uart_no][0x30]; serial_remove(dev->uart[uart]); if (global_enable && local_enable) { - ld_port = make_port(dev, uart_no) & 0xFFF8; - if ((ld_port >= 0x0100) && (ld_port <= 0x0FF8)) - serial_setup(dev->uart[uart], ld_port, dev->ld_regs[uart_no][0x70]); + ld_port = make_port(dev, uart_no) & 0xFFF8; + if ((ld_port >= 0x0100) && (ld_port <= 0x0FF8)) + serial_setup(dev->uart[uart], ld_port, dev->ld_regs[uart_no][0x70]); } } - static void fdc37c93x_nvr_pri_handler(fdc37c93x_t *dev) { @@ -191,503 +184,538 @@ fdc37c93x_nvr_pri_handler(fdc37c93x_t *dev) nvr_at_handler(0, 0x70, dev->nvr); if (local_enable) - nvr_at_handler(1, 0x70, dev->nvr); + nvr_at_handler(1, 0x70, dev->nvr); } - static void fdc37c93x_nvr_sec_handler(fdc37c93x_t *dev) { - uint16_t ld_port = 0; - uint8_t local_enable = !!dev->ld_regs[6][0x30]; + uint16_t ld_port = 0; + uint8_t local_enable = !!dev->ld_regs[6][0x30]; nvr_at_sec_handler(0, dev->nvr_sec_base, dev->nvr); if (local_enable) { - dev->nvr_sec_base = ld_port = make_port_sec(dev, 6) & 0xFFFE; - /* Datasheet erratum: First it says minimum address is 0x0100, but later implies that it's 0x0000 - and that default is 0x0070, same as (unrelocatable) primary NVR. */ - if (ld_port <= 0x0FFE) - nvr_at_sec_handler(1, dev->nvr_sec_base, dev->nvr); + dev->nvr_sec_base = ld_port = make_port_sec(dev, 6) & 0xFFFE; + /* Datasheet erratum: First it says minimum address is 0x0100, but later implies that it's 0x0000 + and that default is 0x0070, same as (unrelocatable) primary NVR. */ + if (ld_port <= 0x0FFE) + nvr_at_sec_handler(1, dev->nvr_sec_base, dev->nvr); } } - static void fdc37c93x_auxio_handler(fdc37c93x_t *dev) { - uint16_t ld_port = 0; - uint8_t local_enable = !!dev->ld_regs[8][0x30]; + uint16_t ld_port = 0; + uint8_t local_enable = !!dev->ld_regs[8][0x30]; io_removehandler(dev->auxio_base, 0x0001, - fdc37c93x_auxio_read, NULL, NULL, fdc37c93x_auxio_write, NULL, NULL, dev); + fdc37c93x_auxio_read, NULL, NULL, fdc37c93x_auxio_write, NULL, NULL, dev); if (local_enable) { - dev->auxio_base = ld_port = make_port(dev, 8); - if ((ld_port >= 0x0100) && (ld_port <= 0x0FFF)) - io_sethandler(dev->auxio_base, 0x0001, - fdc37c93x_auxio_read, NULL, NULL, fdc37c93x_auxio_write, NULL, NULL, dev); + dev->auxio_base = ld_port = make_port(dev, 8); + if ((ld_port >= 0x0100) && (ld_port <= 0x0FFF)) + io_sethandler(dev->auxio_base, 0x0001, + fdc37c93x_auxio_read, NULL, NULL, fdc37c93x_auxio_write, NULL, NULL, dev); } } - static void fdc37c93x_gpio_handler(fdc37c93x_t *dev) { uint16_t ld_port = 0; - uint8_t local_enable; + uint8_t local_enable; local_enable = !!(dev->regs[0x03] & 0x80); io_removehandler(dev->gpio_base, 0x0002, - fdc37c93x_gpio_read, NULL, NULL, fdc37c93x_gpio_write, NULL, NULL, dev); + fdc37c93x_gpio_read, NULL, NULL, fdc37c93x_gpio_write, NULL, NULL, dev); if (local_enable) { - switch (dev->regs[0x03] & 0x03) { - case 0: - ld_port = 0xe0; - break; - case 1: - ld_port = 0xe2; - break; - case 2: - ld_port = 0xe4; - break; - case 3: - ld_port = 0xea; /* Default */ - break; - } - dev->gpio_base = ld_port; - if (ld_port > 0x0000) - io_sethandler(dev->gpio_base, 0x0002, - fdc37c93x_gpio_read, NULL, NULL, fdc37c93x_gpio_write, NULL, NULL, dev); + switch (dev->regs[0x03] & 0x03) { + case 0: + ld_port = 0xe0; + break; + case 1: + ld_port = 0xe2; + break; + case 2: + ld_port = 0xe4; + break; + case 3: + ld_port = 0xea; /* Default */ + break; + + default: + break; + } + dev->gpio_base = ld_port; + if (ld_port > 0x0000) + io_sethandler(dev->gpio_base, 0x0002, + fdc37c93x_gpio_read, NULL, NULL, fdc37c93x_gpio_write, NULL, NULL, dev); } } - static uint8_t fdc37c93x_access_bus_read(uint16_t port, void *priv) { - access_bus_t *dev = (access_bus_t *) priv; - uint8_t ret = 0xff; + const access_bus_t *dev = (access_bus_t *) priv; + uint8_t ret = 0xff; - switch(port & 3) { - case 0: - ret = (dev->status & 0xBF); - break; - case 1: - ret = (dev->own_addr & 0x7F); - break; - case 2: - ret = dev->data; - break; - case 3: - ret = (dev->clock & 0x87); - break; + switch (port & 3) { + case 0: + ret = (dev->status & 0xBF); + break; + case 1: + ret = (dev->own_addr & 0x7F); + break; + case 2: + ret = dev->data; + break; + case 3: + ret = (dev->clock & 0x87); + break; + + default: + break; } return ret; } - static void fdc37c93x_access_bus_write(uint16_t port, uint8_t val, void *priv) { access_bus_t *dev = (access_bus_t *) priv; - switch(port & 3) { - case 0: - dev->control = (val & 0xCF); - break; - case 1: - dev->own_addr = (val & 0x7F); - break; - case 2: - dev->data = val; - break; - case 3: - dev->clock &= 0x80; - dev->clock |= (val & 0x07); - break; + switch (port & 3) { + case 0: + dev->control = (val & 0xCF); + break; + case 1: + dev->own_addr = (val & 0x7F); + break; + case 2: + dev->data = val; + break; + case 3: + dev->clock &= 0x80; + dev->clock |= (val & 0x07); + break; + + default: + break; } } - static void fdc37c93x_access_bus_handler(fdc37c93x_t *dev) { - uint16_t ld_port = 0; - uint8_t global_enable = !!(dev->regs[0x22] & (1 << 6)); - uint8_t local_enable = !!dev->ld_regs[9][0x30]; + uint16_t ld_port = 0; + uint8_t global_enable = !!(dev->regs[0x22] & (1 << 6)); + uint8_t local_enable = !!dev->ld_regs[9][0x30]; io_removehandler(dev->access_bus->base, 0x0004, - fdc37c93x_access_bus_read, NULL, NULL, fdc37c93x_access_bus_write, NULL, NULL, dev->access_bus); + fdc37c93x_access_bus_read, NULL, NULL, fdc37c93x_access_bus_write, NULL, NULL, dev->access_bus); if (global_enable && local_enable) { - dev->access_bus->base = ld_port = make_port(dev, 9); - if ((ld_port >= 0x0100) && (ld_port <= 0x0FFC)) - io_sethandler(dev->access_bus->base, 0x0004, - fdc37c93x_access_bus_read, NULL, NULL, fdc37c93x_access_bus_write, NULL, NULL, dev->access_bus); + dev->access_bus->base = ld_port = make_port(dev, 9); + if ((ld_port >= 0x0100) && (ld_port <= 0x0FFC)) + io_sethandler(dev->access_bus->base, 0x0004, + fdc37c93x_access_bus_read, NULL, NULL, fdc37c93x_access_bus_write, NULL, NULL, dev->access_bus); } } - static void fdc37c93x_acpi_handler(fdc37c93x_t *dev) { - uint16_t ld_port = 0; - uint8_t local_enable = !!dev->ld_regs[0x0a][0x30]; - uint8_t sci_irq = dev->ld_regs[0x0a][0x70]; + uint16_t ld_port = 0; + uint8_t local_enable = !!dev->ld_regs[0x0a][0x30]; + uint8_t sci_irq = dev->ld_regs[0x0a][0x70]; acpi_update_io_mapping(dev->acpi, 0x0000, local_enable); if (local_enable) { - ld_port = make_port(dev, 0x0a) & 0xFFF0; - if ((ld_port >= 0x0100) && (ld_port <= 0x0FF0)) - acpi_update_io_mapping(dev->acpi, ld_port, local_enable); + ld_port = make_port(dev, 0x0a) & 0xFFF0; + if ((ld_port >= 0x0100) && (ld_port <= 0x0FF0)) + acpi_update_io_mapping(dev->acpi, ld_port, local_enable); } acpi_update_aux_io_mapping(dev->acpi, 0x0000, local_enable); if (local_enable) { - ld_port = make_port_sec(dev, 0x0a) & 0xFFF8; - if ((ld_port >= 0x0100) && (ld_port <= 0x0FF8)) - acpi_update_aux_io_mapping(dev->acpi, ld_port, local_enable); + ld_port = make_port_sec(dev, 0x0a) & 0xFFF8; + if ((ld_port >= 0x0100) && (ld_port <= 0x0FF8)) + acpi_update_aux_io_mapping(dev->acpi, ld_port, local_enable); } acpi_set_irq_line(dev->acpi, sci_irq); } - static void fdc37c93x_write(uint16_t port, uint8_t val, void *priv) { - fdc37c93x_t *dev = (fdc37c93x_t *) priv; - uint8_t index = (port & 1) ? 0 : 1; - uint8_t valxor = 0x00, keep = 0x00; + fdc37c93x_t *dev = (fdc37c93x_t *) priv; + uint8_t index = (port & 1) ? 0 : 1; + uint8_t valxor = 0x00; + uint8_t keep = 0x00; /* Compaq Presario 4500: Unlock at FB, Register at EA, Data at EB, Lock at F9. */ if ((port == 0xea) || (port == 0xf9) || (port == 0xfb)) - index = 1; + index = 1; else if (port == 0xeb) - index = 0; + index = 0; if (index) { - if ((val == 0x55) && !dev->locked) { - if (dev->tries) { - dev->locked = 1; - fdc_3f1_enable(dev->fdc, 0); - dev->tries = 0; - } else - dev->tries++; - } else { - if (dev->locked) { - if (val == 0xaa) { - dev->locked = 0; - fdc_3f1_enable(dev->fdc, 1); - return; - } - dev->cur_reg = val; - } else { - if (dev->tries) - dev->tries = 0; - } - } - return; + if ((val == 0x55) && !dev->locked) { + if (dev->tries) { + dev->locked = 1; + fdc_3f1_enable(dev->fdc, 0); + dev->tries = 0; + } else + dev->tries++; + } else { + if (dev->locked) { + if (val == 0xaa) { + dev->locked = 0; + fdc_3f1_enable(dev->fdc, 1); + return; + } + dev->cur_reg = val; + } else { + if (dev->tries) + dev->tries = 0; + } + } + return; } else { - if (dev->locked) { - if (dev->cur_reg < 48) { - valxor = val ^ dev->regs[dev->cur_reg]; - if ((val == 0x20) || (val == 0x21)) - return; - dev->regs[dev->cur_reg] = val; - } else { - valxor = val ^ dev->ld_regs[dev->regs[7]][dev->cur_reg]; - if (((dev->cur_reg & 0xF0) == 0x70) && (dev->regs[7] < 4)) - return; - /* Block writes to some logical devices. */ - if (dev->regs[7] > 0x0a) - return; - else switch (dev->regs[7]) { - case 0x01: - case 0x02: - case 0x07: - return; - case 0x06: - if (dev->chip_id != 0x30) - return; - /* Bits 0 to 3 of logical device 6 (RTC) register F0h must stay set - once they are set. */ - else if (dev->cur_reg == 0xf0) - keep = dev->ld_regs[dev->regs[7]][dev->cur_reg] & 0x0f; - break; - case 0x09: - /* If we're on the FDC37C935, return as this is not a valid - logical device there. */ - if (!dev->is_apm && (dev->chip_id == 0x02)) - return; - break; - case 0x0a: - /* If we're not on the FDC37C931APM, return as this is not a - valid logical device there. */ - if (!dev->is_apm) - return; - break; - } - dev->ld_regs[dev->regs[7]][dev->cur_reg] = val | keep; - } - } else - return; + if (dev->locked) { + if (dev->cur_reg < 48) { + valxor = val ^ dev->regs[dev->cur_reg]; + if ((val == 0x20) || (val == 0x21)) + return; + dev->regs[dev->cur_reg] = val; + } else { + valxor = val ^ dev->ld_regs[dev->regs[7]][dev->cur_reg]; + if (((dev->cur_reg & 0xF0) == 0x70) && (dev->regs[7] < 4)) + return; + /* Block writes to some logical devices. */ + if (dev->regs[7] > 0x0a) + return; + else + switch (dev->regs[7]) { + case 0x01: + case 0x02: + case 0x07: + return; + case 0x06: + if (dev->chip_id != 0x30) + return; + /* Bits 0 to 3 of logical device 6 (RTC) register F0h must stay set + once they are set. */ + else if (dev->cur_reg == 0xf0) + keep = dev->ld_regs[dev->regs[7]][dev->cur_reg] & 0x0f; + break; + case 0x09: + /* If we're on the FDC37C935, return as this is not a valid + logical device there. */ + if (!dev->is_apm && (dev->chip_id == 0x02)) + return; + break; + case 0x0a: + /* If we're not on the FDC37C931APM, return as this is not a + valid logical device there. */ + if (!dev->is_apm) + return; + break; + + default: + break; + } + dev->ld_regs[dev->regs[7]][dev->cur_reg] = val | keep; + } + } else + return; } if (dev->cur_reg < 48) { - switch(dev->cur_reg) { - case 0x03: - if (valxor & 0x83) - fdc37c93x_gpio_handler(dev); - dev->regs[0x03] &= 0x83; - break; - case 0x22: - if (valxor & 0x01) - fdc37c93x_fdc_handler(dev); - if (valxor & 0x08) - fdc37c93x_lpt_handler(dev); - if (valxor & 0x10) - fdc37c93x_serial_handler(dev, 0); - if (valxor & 0x20) - fdc37c93x_serial_handler(dev, 1); - if ((valxor & 0x40) && (dev->chip_id != 0x02)) - fdc37c93x_access_bus_handler(dev); - break; - } + switch (dev->cur_reg) { + case 0x03: + if (valxor & 0x83) + fdc37c93x_gpio_handler(dev); + dev->regs[0x03] &= 0x83; + break; + case 0x22: + if (valxor & 0x01) + fdc37c93x_fdc_handler(dev); + if (valxor & 0x08) + fdc37c93x_lpt_handler(dev); + if (valxor & 0x10) + fdc37c93x_serial_handler(dev, 0); + if (valxor & 0x20) + fdc37c93x_serial_handler(dev, 1); + if ((valxor & 0x40) && (dev->chip_id != 0x02)) + fdc37c93x_access_bus_handler(dev); + break; - return; + default: + break; + } + + return; } - switch(dev->regs[7]) { - case 0: - /* FDD */ - switch(dev->cur_reg) { - case 0x30: - case 0x60: - case 0x61: - if ((dev->cur_reg == 0x30) && (val & 0x01)) - dev->regs[0x22] |= 0x01; - if (valxor) - fdc37c93x_fdc_handler(dev); - break; - case 0xF0: - if (valxor & 0x01) - fdc_update_enh_mode(dev->fdc, val & 0x01); - if (valxor & 0x10) - fdc_set_swap(dev->fdc, (val & 0x10) >> 4); - break; - case 0xF1: - if (valxor & 0xC) - fdc_update_densel_force(dev->fdc, (val & 0xc) >> 2); - break; - case 0xF2: - if (valxor & 0xC0) - fdc_update_rwc(dev->fdc, 3, (val & 0xc0) >> 6); - if (valxor & 0x30) - fdc_update_rwc(dev->fdc, 2, (val & 0x30) >> 4); - if (valxor & 0x0C) - fdc_update_rwc(dev->fdc, 1, (val & 0x0c) >> 2); - if (valxor & 0x03) - fdc_update_rwc(dev->fdc, 0, (val & 0x03)); - break; - case 0xF4: - if (valxor & 0x18) - fdc_update_drvrate(dev->fdc, 0, (val & 0x18) >> 3); - break; - case 0xF5: - if (valxor & 0x18) - fdc_update_drvrate(dev->fdc, 1, (val & 0x18) >> 3); - break; - case 0xF6: - if (valxor & 0x18) - fdc_update_drvrate(dev->fdc, 2, (val & 0x18) >> 3); - break; - case 0xF7: - if (valxor & 0x18) - fdc_update_drvrate(dev->fdc, 3, (val & 0x18) >> 3); - break; - } - break; - case 3: - /* Parallel port */ - switch(dev->cur_reg) { - case 0x30: - case 0x60: - case 0x61: - case 0x70: - if ((dev->cur_reg == 0x30) && (val & 0x01)) - dev->regs[0x22] |= 0x08; - if (valxor) - fdc37c93x_lpt_handler(dev); - break; - } - break; - case 4: - /* Serial port 1 */ - switch(dev->cur_reg) { - case 0x30: - case 0x60: - case 0x61: - case 0x70: - if ((dev->cur_reg == 0x30) && (val & 0x01)) - dev->regs[0x22] |= 0x10; - if (valxor) - fdc37c93x_serial_handler(dev, 0); - break; - } - break; - case 5: - /* Serial port 2 */ - switch(dev->cur_reg) { - case 0x30: - case 0x60: - case 0x61: - case 0x70: - if ((dev->cur_reg == 0x30) && (val & 0x01)) - dev->regs[0x22] |= 0x20; - if (valxor) - fdc37c93x_serial_handler(dev, 1); - break; - } - break; - case 6: - /* RTC/NVR */ - if (dev->chip_id != 0x30) - break; - switch(dev->cur_reg) { - case 0x30: - if (valxor) - fdc37c93x_nvr_pri_handler(dev); - case 0x62: - case 0x63: - if (valxor) - fdc37c93x_nvr_sec_handler(dev); - break; - case 0xf0: - if (valxor) { - nvr_lock_set(0x80, 0x20, !!(dev->ld_regs[6][dev->cur_reg] & 0x01), dev->nvr); - nvr_lock_set(0xa0, 0x20, !!(dev->ld_regs[6][dev->cur_reg] & 0x02), dev->nvr); - nvr_lock_set(0xc0, 0x20, !!(dev->ld_regs[6][dev->cur_reg] & 0x04), dev->nvr); - nvr_lock_set(0xe0, 0x20, !!(dev->ld_regs[6][dev->cur_reg] & 0x08), dev->nvr); - if (dev->ld_regs[6][dev->cur_reg] & 0x80) switch ((dev->ld_regs[6][dev->cur_reg] >> 4) & 0x07) { - case 0x00: - default: - nvr_bank_set(0, 0xff, dev->nvr); - nvr_bank_set(1, 1, dev->nvr); - break; - case 0x01: - nvr_bank_set(0, 0, dev->nvr); - nvr_bank_set(1, 1, dev->nvr); - break; - case 0x02: case 0x04: - nvr_bank_set(0, 0xff, dev->nvr); - nvr_bank_set(1, 0xff, dev->nvr); - break; - case 0x03: case 0x05: - nvr_bank_set(0, 0, dev->nvr); - nvr_bank_set(1, 0xff, dev->nvr); - break; - case 0x06: - nvr_bank_set(0, 0xff, dev->nvr); - nvr_bank_set(1, 2, dev->nvr); - break; - case 0x07: - nvr_bank_set(0, 0, dev->nvr); - nvr_bank_set(1, 2, dev->nvr); - break; - } else { - nvr_bank_set(0, 0, dev->nvr); - nvr_bank_set(1, 0xff, dev->nvr); - } - } - break; - } - break; - case 8: - /* Auxiliary I/O */ - switch(dev->cur_reg) { - case 0x30: - case 0x60: - case 0x61: - case 0x70: - if (valxor) - fdc37c93x_auxio_handler(dev); - break; - } - break; - case 9: - /* Access bus (FDC37C932FR and FDC37C931APM only) */ - switch(dev->cur_reg) { - case 0x30: - case 0x60: - case 0x61: - case 0x70: - if ((dev->cur_reg == 0x30) && (val & 0x01)) - dev->regs[0x22] |= 0x40; - if (valxor) - fdc37c93x_access_bus_handler(dev); - break; - } - break; - case 10: - /* Access bus (FDC37C931APM only) */ - switch(dev->cur_reg) { - case 0x30: - case 0x60: - case 0x61: - case 0x62: - case 0x63: - case 0x70: - if (valxor) - fdc37c93x_acpi_handler(dev); - break; - } - break; + switch (dev->regs[7]) { + case 0: + /* FDD */ + switch (dev->cur_reg) { + case 0x30: + case 0x60: + case 0x61: + if ((dev->cur_reg == 0x30) && (val & 0x01)) + dev->regs[0x22] |= 0x01; + if (valxor) + fdc37c93x_fdc_handler(dev); + break; + case 0xF0: + if (valxor & 0x01) + fdc_update_enh_mode(dev->fdc, val & 0x01); + if (valxor & 0x10) + fdc_set_swap(dev->fdc, (val & 0x10) >> 4); + break; + case 0xF1: + if (valxor & 0xC) + fdc_update_densel_force(dev->fdc, (val & 0xc) >> 2); + break; + case 0xF2: + if (valxor & 0xC0) + fdc_update_rwc(dev->fdc, 3, (val & 0xc0) >> 6); + if (valxor & 0x30) + fdc_update_rwc(dev->fdc, 2, (val & 0x30) >> 4); + if (valxor & 0x0C) + fdc_update_rwc(dev->fdc, 1, (val & 0x0c) >> 2); + if (valxor & 0x03) + fdc_update_rwc(dev->fdc, 0, (val & 0x03)); + break; + case 0xF4: + if (valxor & 0x18) + fdc_update_drvrate(dev->fdc, 0, (val & 0x18) >> 3); + break; + case 0xF5: + if (valxor & 0x18) + fdc_update_drvrate(dev->fdc, 1, (val & 0x18) >> 3); + break; + case 0xF6: + if (valxor & 0x18) + fdc_update_drvrate(dev->fdc, 2, (val & 0x18) >> 3); + break; + case 0xF7: + if (valxor & 0x18) + fdc_update_drvrate(dev->fdc, 3, (val & 0x18) >> 3); + break; + + default: + break; + } + break; + case 3: + /* Parallel port */ + switch (dev->cur_reg) { + case 0x30: + case 0x60: + case 0x61: + case 0x70: + if ((dev->cur_reg == 0x30) && (val & 0x01)) + dev->regs[0x22] |= 0x08; + if (valxor) + fdc37c93x_lpt_handler(dev); + break; + + default: + break; + } + break; + case 4: + /* Serial port 1 */ + switch (dev->cur_reg) { + case 0x30: + case 0x60: + case 0x61: + case 0x70: + if ((dev->cur_reg == 0x30) && (val & 0x01)) + dev->regs[0x22] |= 0x10; + if (valxor) + fdc37c93x_serial_handler(dev, 0); + break; + + default: + break; + } + break; + case 5: + /* Serial port 2 */ + switch (dev->cur_reg) { + case 0x30: + case 0x60: + case 0x61: + case 0x70: + if ((dev->cur_reg == 0x30) && (val & 0x01)) + dev->regs[0x22] |= 0x20; + if (valxor) + fdc37c93x_serial_handler(dev, 1); + break; + + default: + break; + } + break; + case 6: + /* RTC/NVR */ + if (dev->chip_id != 0x30) + break; + switch (dev->cur_reg) { + case 0x30: + if (valxor) + fdc37c93x_nvr_pri_handler(dev); + case 0x62: + case 0x63: + if (valxor) + fdc37c93x_nvr_sec_handler(dev); + break; + case 0xf0: + if (valxor) { + nvr_lock_set(0x80, 0x20, !!(dev->ld_regs[6][dev->cur_reg] & 0x01), dev->nvr); + nvr_lock_set(0xa0, 0x20, !!(dev->ld_regs[6][dev->cur_reg] & 0x02), dev->nvr); + nvr_lock_set(0xc0, 0x20, !!(dev->ld_regs[6][dev->cur_reg] & 0x04), dev->nvr); + nvr_lock_set(0xe0, 0x20, !!(dev->ld_regs[6][dev->cur_reg] & 0x08), dev->nvr); + if (dev->ld_regs[6][dev->cur_reg] & 0x80) + switch ((dev->ld_regs[6][dev->cur_reg] >> 4) & 0x07) { + default: + case 0x00: + nvr_bank_set(0, 0xff, dev->nvr); + nvr_bank_set(1, 1, dev->nvr); + break; + case 0x01: + nvr_bank_set(0, 0, dev->nvr); + nvr_bank_set(1, 1, dev->nvr); + break; + case 0x02: + case 0x04: + nvr_bank_set(0, 0xff, dev->nvr); + nvr_bank_set(1, 0xff, dev->nvr); + break; + case 0x03: + case 0x05: + nvr_bank_set(0, 0, dev->nvr); + nvr_bank_set(1, 0xff, dev->nvr); + break; + case 0x06: + nvr_bank_set(0, 0xff, dev->nvr); + nvr_bank_set(1, 2, dev->nvr); + break; + case 0x07: + nvr_bank_set(0, 0, dev->nvr); + nvr_bank_set(1, 2, dev->nvr); + break; + } + else { + nvr_bank_set(0, 0, dev->nvr); + nvr_bank_set(1, 0xff, dev->nvr); + } + } + break; + + default: + break; + } + break; + case 8: + /* Auxiliary I/O */ + switch (dev->cur_reg) { + case 0x30: + case 0x60: + case 0x61: + case 0x70: + if (valxor) + fdc37c93x_auxio_handler(dev); + break; + + default: + break; + } + break; + case 9: + /* Access bus (FDC37C932FR and FDC37C931APM only) */ + switch (dev->cur_reg) { + case 0x30: + case 0x60: + case 0x61: + case 0x70: + if ((dev->cur_reg == 0x30) && (val & 0x01)) + dev->regs[0x22] |= 0x40; + if (valxor) + fdc37c93x_access_bus_handler(dev); + break; + + default: + break; + } + break; + case 10: + /* Access bus (FDC37C931APM only) */ + switch (dev->cur_reg) { + case 0x30: + case 0x60: + case 0x61: + case 0x62: + case 0x63: + case 0x70: + if (valxor) + fdc37c93x_acpi_handler(dev); + break; + + default: + break; + } + break; + + default: + break; } } - static uint8_t fdc37c93x_read(uint16_t port, void *priv) { - fdc37c93x_t *dev = (fdc37c93x_t *) priv; - uint8_t index = (port & 1) ? 0 : 1; - uint8_t ret = 0xff; + fdc37c93x_t *dev = (fdc37c93x_t *) priv; + uint8_t index = (port & 1) ? 0 : 1; + uint8_t ret = 0xff; /* Compaq Presario 4500: Unlock at FB, Register at EA, Data at EB, Lock at F9. */ if ((port == 0xea) || (port == 0xf9) || (port == 0xfb)) - index = 1; + index = 1; else if (port == 0xeb) - index = 0; + index = 0; if (dev->locked) { - if (index) - ret = dev->cur_reg; - else { - if (dev->cur_reg < 0x30) { - if (dev->cur_reg == 0x20) - ret = dev->chip_id; - else - ret = dev->regs[dev->cur_reg]; - } else { - if ((dev->regs[7] == 0) && (dev->cur_reg == 0xF2)) { - ret = (fdc_get_rwc(dev->fdc, 0) | (fdc_get_rwc(dev->fdc, 1) << 2) | - (fdc_get_rwc(dev->fdc, 2) << 4) | (fdc_get_rwc(dev->fdc, 3) << 6)); - } else - ret = dev->ld_regs[dev->regs[7]][dev->cur_reg]; - } - } + if (index) + ret = dev->cur_reg; + else { + if (dev->cur_reg < 0x30) { + if (dev->cur_reg == 0x20) + ret = dev->chip_id; + else + ret = dev->regs[dev->cur_reg]; + } else { + if ((dev->regs[7] == 0) && (dev->cur_reg == 0xF2)) { + ret = (fdc_get_rwc(dev->fdc, 0) | (fdc_get_rwc(dev->fdc, 1) << 2) | (fdc_get_rwc(dev->fdc, 2) << 4) | (fdc_get_rwc(dev->fdc, 3) << 6)); + } else + ret = dev->ld_regs[dev->regs[7]][dev->cur_reg]; + } + } } return ret; } - static void fdc37c93x_reset(fdc37c93x_t *dev) { - int i = 0; - memset(dev->regs, 0, 48); dev->regs[0x03] = 0x03; @@ -698,8 +726,8 @@ fdc37c93x_reset(fdc37c93x_t *dev) dev->regs[0x26] = 0xF0; dev->regs[0x27] = 0x03; - for (i = 0; i < 11; i++) - memset(dev->ld_regs[i], 0, 256); + for (uint8_t i = 0; i < 11; i++) + memset(dev->ld_regs[i], 0, 256); /* Logical device 0: FDD */ dev->ld_regs[0][0x30] = 1; @@ -741,7 +769,7 @@ fdc37c93x_reset(fdc37c93x_t *dev) dev->ld_regs[4][0x61] = 0xf8; dev->ld_regs[4][0x70] = 4; dev->ld_regs[4][0xF0] = 3; - serial_setup(dev->uart[0], 0x3f8, dev->ld_regs[4][0x70]); + serial_setup(dev->uart[0], COM1_ADDR, dev->ld_regs[4][0x70]); /* Logical device 5: Serial Port 2 */ dev->ld_regs[5][0x30] = 1; @@ -751,7 +779,7 @@ fdc37c93x_reset(fdc37c93x_t *dev) dev->ld_regs[5][0x74] = 4; dev->ld_regs[5][0xF1] = 2; dev->ld_regs[5][0xF2] = 3; - serial_setup(dev->uart[1], 0x2f8, dev->ld_regs[5][0x70]); + serial_setup(dev->uart[1], COM2_ADDR, dev->ld_regs[5][0x70]); /* Logical device 6: RTC */ dev->ld_regs[6][0x30] = 1; @@ -775,24 +803,23 @@ fdc37c93x_reset(fdc37c93x_t *dev) fdc37c93x_serial_handler(dev, 1); fdc37c93x_auxio_handler(dev); if (dev->is_apm || (dev->chip_id == 0x03)) - fdc37c93x_access_bus_handler(dev); + fdc37c93x_access_bus_handler(dev); if (dev->is_apm) - fdc37c93x_acpi_handler(dev); + fdc37c93x_acpi_handler(dev); fdc_reset(dev->fdc); fdc37c93x_fdc_handler(dev); if (dev->chip_id == 0x30) { - fdc37c93x_nvr_pri_handler(dev); - fdc37c93x_nvr_sec_handler(dev); - nvr_bank_set(0, 0, dev->nvr); - nvr_bank_set(1, 0xff, dev->nvr); + fdc37c93x_nvr_pri_handler(dev); + fdc37c93x_nvr_sec_handler(dev); + nvr_bank_set(0, 0, dev->nvr); + nvr_bank_set(1, 0xff, dev->nvr); } dev->locked = 0; } - static void access_bus_close(void *priv) { @@ -801,9 +828,8 @@ access_bus_close(void *priv) free(dev); } - static void * -access_bus_init(const device_t *info) +access_bus_init(UNUSED(const device_t *info)) { access_bus_t *dev = (access_bus_t *) malloc(sizeof(access_bus_t)); memset(dev, 0, sizeof(access_bus_t)); @@ -811,18 +837,20 @@ access_bus_init(const device_t *info) return dev; } - static const device_t access_bus_device = { - "SMC FDC37C932FR ACCESS.bus", - "access_bus", - 0, - 0x03, - access_bus_init, access_bus_close, NULL, - { NULL }, NULL, NULL, - NULL + .name = "SMC FDC37C932FR ACCESS.bus", + .internal_name = "access_bus", + .flags = 0, + .local = 0x03, + .init = access_bus_init, + .close = access_bus_close, + .reset = NULL, + { .available = NULL }, + .speed_changed = NULL, + .force_redraw = NULL, + .config = NULL }; - static void fdc37c93x_close(void *priv) { @@ -831,11 +859,10 @@ fdc37c93x_close(void *priv) free(dev); } - static void * fdc37c93x_init(const device_t *info) { - int is_compaq; + int is_compaq; fdc37c93x_t *dev = (fdc37c93x_t *) malloc(sizeof(fdc37c93x_t)); memset(dev, 0, sizeof(fdc37c93x_t)); @@ -845,38 +872,40 @@ fdc37c93x_init(const device_t *info) dev->uart[1] = device_add_inst(&ns16550_device, 2); dev->chip_id = info->local & 0xff; - dev->is_apm = (info->local >> 8) & 0x01; - is_compaq = (info->local >> 8) & 0x02; + dev->is_apm = (info->local >> 8) & 0x01; + is_compaq = (info->local >> 8) & 0x02; dev->gpio_regs[0] = 0xff; - // dev->gpio_regs[1] = (info->local == 0x0030) ? 0xff : 0xfd; +#if 0 + dev->gpio_regs[1] = (info->local == 0x0030) ? 0xff : 0xfd; +#endif dev->gpio_regs[1] = (dev->chip_id == 0x30) ? 0xff : 0xfd; if (dev->chip_id == 0x30) { - dev->nvr = device_add(&at_nvr_device); + dev->nvr = device_add(&at_nvr_device); - nvr_bank_set(0, 0, dev->nvr); - nvr_bank_set(1, 0xff, dev->nvr); + nvr_bank_set(0, 0, dev->nvr); + nvr_bank_set(1, 0xff, dev->nvr); } if (dev->is_apm || (dev->chip_id == 0x03)) - dev->access_bus = device_add(&access_bus_device); + dev->access_bus = device_add(&access_bus_device); if (dev->is_apm) - dev->acpi = device_add(&acpi_smc_device); + dev->acpi = device_add(&acpi_smc_device); if (is_compaq) { - io_sethandler(0x0ea, 0x0002, - fdc37c93x_read, NULL, NULL, fdc37c93x_write, NULL, NULL, dev); - io_sethandler(0x0f9, 0x0001, - fdc37c93x_read, NULL, NULL, fdc37c93x_write, NULL, NULL, dev); - io_sethandler(0x0fb, 0x0001, - fdc37c93x_read, NULL, NULL, fdc37c93x_write, NULL, NULL, dev); + io_sethandler(0x0ea, 0x0002, + fdc37c93x_read, NULL, NULL, fdc37c93x_write, NULL, NULL, dev); + io_sethandler(0x0f9, 0x0001, + fdc37c93x_read, NULL, NULL, fdc37c93x_write, NULL, NULL, dev); + io_sethandler(0x0fb, 0x0001, + fdc37c93x_read, NULL, NULL, fdc37c93x_write, NULL, NULL, dev); } else { - io_sethandler(0x370, 0x0002, - fdc37c93x_read, NULL, NULL, fdc37c93x_write, NULL, NULL, dev); - io_sethandler(0x3f0, 0x0002, - fdc37c93x_read, NULL, NULL, fdc37c93x_write, NULL, NULL, dev); + io_sethandler(FDC_SECONDARY_ADDR, 0x0002, + fdc37c93x_read, NULL, NULL, fdc37c93x_write, NULL, NULL, dev); + io_sethandler(FDC_PRIMARY_ADDR, 0x0002, + fdc37c93x_read, NULL, NULL, fdc37c93x_write, NULL, NULL, dev); } fdc37c93x_reset(dev); @@ -884,53 +913,72 @@ fdc37c93x_init(const device_t *info) return dev; } - const device_t fdc37c931apm_device = { - "SMC FDC37C932QF Super I/O", - "fdc37c931apm", - 0, - 0x130, /* Share the same ID with the 932QF. */ - fdc37c93x_init, fdc37c93x_close, NULL, - { NULL }, NULL, NULL, - NULL + .name = "SMC FDC37C932QF Super I/O", + .internal_name = "fdc37c931apm", + .flags = 0, + .local = 0x130, /* Share the same ID with the 932QF. */ + .init = fdc37c93x_init, + .close = fdc37c93x_close, + .reset = NULL, + { .available = NULL }, + .speed_changed = NULL, + .force_redraw = NULL, + .config = NULL }; const device_t fdc37c931apm_compaq_device = { - "SMC FDC37C932QF Super I/O (Compaq Presario 4500)", - "fdc37c931apm_compaq", - 0, - 0x330, /* Share the same ID with the 932QF. */ - fdc37c93x_init, fdc37c93x_close, NULL, - { NULL }, NULL, NULL, - NULL + .name = "SMC FDC37C932QF Super I/O (Compaq Presario 4500)", + .internal_name = "fdc37c931apm_compaq", + .flags = 0, + .local = 0x330, /* Share the same ID with the 932QF. */ + .init = fdc37c93x_init, + .close = fdc37c93x_close, + .reset = NULL, + { .available = NULL }, + .speed_changed = NULL, + .force_redraw = NULL, + .config = NULL }; const device_t fdc37c932fr_device = { - "SMC FDC37C932FR Super I/O", - "fdc37c932fr", - 0, - 0x03, - fdc37c93x_init, fdc37c93x_close, NULL, - { NULL }, NULL, NULL, - NULL + .name = "SMC FDC37C932FR Super I/O", + .internal_name = "fdc37c932fr", + .flags = 0, + .local = 0x03, + .init = fdc37c93x_init, + .close = fdc37c93x_close, + .reset = NULL, + { .available = NULL }, + .speed_changed = NULL, + .force_redraw = NULL, + .config = NULL }; const device_t fdc37c932qf_device = { - "SMC FDC37C932QF Super I/O", - "fdc37c932qf", - 0, - 0x30, - fdc37c93x_init, fdc37c93x_close, NULL, - { NULL }, NULL, NULL, - NULL + .name = "SMC FDC37C932QF Super I/O", + .internal_name = "fdc37c932qf", + .flags = 0, + .local = 0x30, + .init = fdc37c93x_init, + .close = fdc37c93x_close, + .reset = NULL, + { .available = NULL }, + .speed_changed = NULL, + .force_redraw = NULL, + .config = NULL }; const device_t fdc37c935_device = { - "SMC FDC37C935 Super I/O", - "fdc37c935", - 0, - 0x02, - fdc37c93x_init, fdc37c93x_close, NULL, - { NULL }, NULL, NULL, - NULL + .name = "SMC FDC37C935 Super I/O", + .internal_name = "fdc37c935", + .flags = 0, + .local = 0x02, + .init = fdc37c93x_init, + .close = fdc37c93x_close, + .reset = NULL, + { .available = NULL }, + .speed_changed = NULL, + .force_redraw = NULL, + .config = NULL }; diff --git a/src/sio/sio_fdc37m60x.c b/src/sio/sio_fdc37m60x.c index 1b36ad996..38a163538 100644 --- a/src/sio/sio_fdc37m60x.c +++ b/src/sio/sio_fdc37m60x.c @@ -1,15 +1,18 @@ /* - * 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. + * 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. + * This file is part of the 86Box distribution. * - * Emulation of the SMSC FDC37M60x Super I/O + * Emulation of the SMSC FDC37M60x Super I/O * - * Authors: Tiseno100 - * Copyright 2020 Tiseno100 + * + * + * Authors: Tiseno100 + * + * Copyright 2020 Tiseno100 */ #include #include @@ -31,23 +34,21 @@ #include <86box/fdc.h> #include <86box/sio.h> -#define SIO_INDEX_PORT dev->sio_index_port -#define INDEX dev->index +#define SIO_INDEX_PORT dev->sio_index_port +#define INDEX dev->index /* Current Logical Device Number */ -#define CURRENT_LOGICAL_DEVICE dev->regs[0x07] +#define CURRENT_LOGICAL_DEVICE dev->regs[0x07] /* Global Device Configuration */ -#define ENABLED(ld) dev->device_regs[ld][0x30] -#define BASE_ADDRESS(ld) ((dev->device_regs[ld][0x60] << 8) | \ - (dev->device_regs[ld][0x61])) -#define IRQ(ld) dev->device_regs[ld][0x70] -#define DMA(ld) dev->device_regs[ld][0x74] +#define ENABLED(ld) dev->device_regs[ld][0x30] +#define BASE_ADDRESS(ld) ((dev->device_regs[ld][0x60] << 8) | (dev->device_regs[ld][0x61])) +#define IRQ(ld) dev->device_regs[ld][0x70] +#define DMA(ld) dev->device_regs[ld][0x74] /* Miscellaneous Chip Functionality */ -#define SOFT_RESET (val & 0x01) -#define POWER_CONTROL dev->regs[0x22] - +#define SOFT_RESET (val & 0x01) +#define POWER_CONTROL dev->regs[0x22] #ifdef ENABLE_FDC37M60X_LOG int fdc37m60x_do_log = ENABLE_FDC37M60X_LOG; @@ -57,117 +58,126 @@ fdc37m60x_log(const char *fmt, ...) { va_list ap; - if (fdc37m60x_do_log) - { + if (fdc37m60x_do_log) { va_start(ap, fmt); pclog_ex(fmt, ap); va_end(ap); } } #else -#define fdc37m60x_log(fmt, ...) +# define fdc37m60x_log(fmt, ...) #endif +typedef struct fdc37m60x_t { + uint8_t index; + uint8_t regs[256]; + uint8_t device_regs[10][256]; + uint8_t cfg_lock; + uint8_t ide_function; + uint16_t sio_index_port; -typedef struct -{ - uint8_t index, regs[256], device_regs[10][256], cfg_lock, ide_function; - uint16_t sio_index_port; - - fdc_t * fdc; - serial_t * uart[2]; + fdc_t *fdc; + serial_t *uart[2]; } fdc37m60x_t; - -static void fdc37m60x_fdc_handler(fdc37m60x_t *dev); -static void fdc37m60x_uart_handler(uint8_t num, fdc37m60x_t *dev); -static void fdc37m60x_lpt_handler(fdc37m60x_t *dev); -static void fdc37m60x_logical_device_handler(fdc37m60x_t *dev); -static void fdc37m60x_reset(void *priv); - +static void fdc37m60x_fdc_handler(fdc37m60x_t *dev); +static void fdc37m60x_uart_handler(uint8_t num, fdc37m60x_t *dev); +static void fdc37m60x_lpt_handler(fdc37m60x_t *dev); +static void fdc37m60x_logical_device_handler(fdc37m60x_t *dev); +static void fdc37m60x_reset(void *priv); static void fdc37m60x_write(uint16_t addr, uint8_t val, void *priv) { - fdc37m60x_t *dev = (fdc37m60x_t *)priv; + fdc37m60x_t *dev = (fdc37m60x_t *) priv; if (addr & 1) { - if (!dev->cfg_lock) { - switch (INDEX) { - /* Global Configuration */ - case 0x02: - dev->regs[INDEX] = val; - if (SOFT_RESET) - fdc37m60x_reset(dev); - break; + if (!dev->cfg_lock) { + switch (INDEX) { + /* Global Configuration */ + case 0x02: + dev->regs[INDEX] = val; + if (SOFT_RESET) + fdc37m60x_reset(dev); + break; - case 0x07: - CURRENT_LOGICAL_DEVICE = val; - break; + case 0x07: + CURRENT_LOGICAL_DEVICE = val; + break; - case 0x22: - POWER_CONTROL = val & 0x3f; - break; + case 0x22: + POWER_CONTROL = val & 0x3f; + break; - case 0x23: - dev->regs[INDEX] = val & 0x3f; - break; + case 0x23: + dev->regs[INDEX] = val & 0x3f; + break; - case 0x24: - dev->regs[INDEX] = val & 0x4e; - break; + case 0x24: + dev->regs[INDEX] = val & 0x4e; + break; - case 0x2b: case 0x2c: case 0x2d: case 0x2e: - case 0x2f: - dev->regs[INDEX] = val; - break; + case 0x2b: + case 0x2c: + case 0x2d: + case 0x2e: + case 0x2f: + dev->regs[INDEX] = val; + break; - /* Device Configuration */ - case 0x30: - case 0x60: case 0x61: - case 0x70: - case 0x74: - case 0xf0: case 0xf1: case 0xf2: case 0xf3: - case 0xf4: case 0xf5: case 0xf6: case 0xf7: - if (CURRENT_LOGICAL_DEVICE <= 0x81) /* Avoid Overflow */ - dev->device_regs[CURRENT_LOGICAL_DEVICE][INDEX] = (INDEX == 0x30) ? (val & 1) : val; - fdc37m60x_logical_device_handler(dev); - break; - } + /* Device Configuration */ + case 0x30: + case 0x60: + case 0x61: + case 0x70: + case 0x74: + case 0xf0: + case 0xf1: + case 0xf2: + case 0xf3: + case 0xf4: + case 0xf5: + case 0xf6: + case 0xf7: + if (CURRENT_LOGICAL_DEVICE <= 0x81) /* Avoid Overflow */ + dev->device_regs[CURRENT_LOGICAL_DEVICE][INDEX] = (INDEX == 0x30) ? (val & 1) : val; + fdc37m60x_logical_device_handler(dev); + break; + + default: + break; + } } } else { - /* Enter/Escape Configuration Mode */ - if (val == 0x55) - dev->cfg_lock = 0; - else if (!dev->cfg_lock && (val == 0xaa)) - dev->cfg_lock = 1; - else if (!dev->cfg_lock) - INDEX = val; + /* Enter/Escape Configuration Mode */ + if (val == 0x55) + dev->cfg_lock = 0; + else if (!dev->cfg_lock && (val == 0xaa)) + dev->cfg_lock = 1; + else if (!dev->cfg_lock) + INDEX = val; } } - static uint8_t fdc37m60x_read(uint16_t addr, void *priv) { - fdc37m60x_t *dev = (fdc37m60x_t *)priv; - uint8_t ret = 0xff; + const fdc37m60x_t *dev = (fdc37m60x_t *) priv; + uint8_t ret = 0xff; if (addr & 1) - ret = (INDEX >= 0x30) ? dev->device_regs[CURRENT_LOGICAL_DEVICE][INDEX] : dev->regs[INDEX]; + ret = (INDEX >= 0x30) ? dev->device_regs[CURRENT_LOGICAL_DEVICE][INDEX] : dev->regs[INDEX]; return ret; } - static void fdc37m60x_fdc_handler(fdc37m60x_t *dev) { fdc_remove(dev->fdc); - if (ENABLED(0) || (POWER_CONTROL & 0x01)) - { + if (ENABLED(0) || (POWER_CONTROL & 0x01)) { fdc_set_base(dev->fdc, BASE_ADDRESS(0)); fdc_set_irq(dev->fdc, IRQ(0) & 0xf); fdc_set_dma_ch(dev->fdc, DMA(0) & 0x07); @@ -189,70 +199,69 @@ fdc37m60x_fdc_handler(fdc37m60x_t *dev) fdc_update_drvrate(dev->fdc, 3, (dev->device_regs[0][0xf7] & 0x18) >> 3); } - static void fdc37m60x_uart_handler(uint8_t num, fdc37m60x_t *dev) { serial_remove(dev->uart[num & 1]); - if (ENABLED(4 + (num & 1)) || (POWER_CONTROL & (1 << (4 + (num & 1))))) - { + if (ENABLED(4 + (num & 1)) || (POWER_CONTROL & (1 << (4 + (num & 1))))) { serial_setup(dev->uart[num & 1], BASE_ADDRESS(4 + (num & 1)), IRQ(4 + (num & 1)) & 0xf); fdc37m60x_log("SMC60x-UART%d: BASE %04x IRQ %d\n", num & 1, BASE_ADDRESS(4 + (num & 1)), IRQ(4 + (num & 1)) & 0xf); } } - -void fdc37m60x_lpt_handler(fdc37m60x_t *dev) +void +fdc37m60x_lpt_handler(fdc37m60x_t *dev) { lpt1_remove(); if (ENABLED(3) || (POWER_CONTROL & 0x08)) { - lpt1_init(BASE_ADDRESS(3)); - lpt1_irq(IRQ(3) & 0xf); - fdc37m60x_log("SMC60x-LPT: BASE %04x IRQ %d\n", BASE_ADDRESS(3), IRQ(3) & 0xf); + lpt1_init(BASE_ADDRESS(3)); + lpt1_irq(IRQ(3) & 0xf); + fdc37m60x_log("SMC60x-LPT: BASE %04x IRQ %d\n", BASE_ADDRESS(3), IRQ(3) & 0xf); } } - -void fdc37m60x_logical_device_handler(fdc37m60x_t *dev) +void +fdc37m60x_logical_device_handler(fdc37m60x_t *dev) { /* Register 07h: - Device 0: FDC - Device 3: LPT - Device 4: UART1 - Device 5: UART2 + Device 0: FDC + Device 3: LPT + Device 4: UART1 + Device 5: UART2 */ switch (CURRENT_LOGICAL_DEVICE) { - case 0x00: - fdc37m60x_fdc_handler(dev); - break; + case 0x00: + fdc37m60x_fdc_handler(dev); + break; - case 0x03: - fdc37m60x_lpt_handler(dev); - break; + case 0x03: + fdc37m60x_lpt_handler(dev); + break; - case 0x04: - fdc37m60x_uart_handler(0, dev); - break; + case 0x04: + fdc37m60x_uart_handler(0, dev); + break; - case 0x05: - fdc37m60x_uart_handler(1, dev); - break; + case 0x05: + fdc37m60x_uart_handler(1, dev); + break; + + default: + break; } } - static void fdc37m60x_reset(void *priv) { fdc37m60x_t *dev = (fdc37m60x_t *) priv; - uint8_t i; memset(dev->regs, 0, sizeof(dev->regs)); - for (i = 0; i < 10; i++) - memset(dev->device_regs[i], 0, sizeof(dev->device_regs[i])); + for (uint8_t i = 0; i < 10; i++) + memset(dev->device_regs[i], 0, sizeof(dev->device_regs[i])); dev->regs[0x20] = 0x47; dev->regs[0x24] = 0x04; @@ -286,24 +295,22 @@ fdc37m60x_reset(void *priv) fdc37m60x_lpt_handler(dev); } - static void fdc37m60x_close(void *priv) { - fdc37m60x_t *dev = (fdc37m60x_t *)priv; + fdc37m60x_t *dev = (fdc37m60x_t *) priv; free(dev); } - static void * fdc37m60x_init(const device_t *info) { - fdc37m60x_t *dev = (fdc37m60x_t *)malloc(sizeof(fdc37m60x_t)); + fdc37m60x_t *dev = (fdc37m60x_t *) malloc(sizeof(fdc37m60x_t)); memset(dev, 0, sizeof(fdc37m60x_t)); SIO_INDEX_PORT = info->local; - dev->fdc = device_add(&fdc_at_smc_device); + dev->fdc = device_add(&fdc_at_smc_device); dev->uart[0] = device_add_inst(&ns16550_device, 1); dev->uart[1] = device_add_inst(&ns16550_device, 2); @@ -314,31 +321,30 @@ fdc37m60x_init(const device_t *info) return dev; } - const device_t fdc37m60x_device = { - "SMSC FDC37M60X", - "fdc37m60x", - 0, - 0x03f0, - fdc37m60x_init, - fdc37m60x_close, - NULL, - { NULL }, - NULL, - NULL, - NULL + .name = "SMSC FDC37M60X", + .internal_name = "fdc37m60x", + .flags = 0, + .local = FDC_PRIMARY_ADDR, + .init = fdc37m60x_init, + .close = fdc37m60x_close, + .reset = NULL, + { .available = NULL }, + .speed_changed = NULL, + .force_redraw = NULL, + .config = NULL }; const device_t fdc37m60x_370_device = { - "SMSC FDC37M60X with 10K Pull Up Resistor", - "fdc37m60x_370", - 0, - 0x0370, - fdc37m60x_init, - fdc37m60x_close, - NULL, - { NULL }, - NULL, - NULL, - NULL + .name = "SMSC FDC37M60X with 10K Pull Up Resistor", + .internal_name = "fdc37m60x_370", + .flags = 0, + .local = FDC_SECONDARY_ADDR, + .init = fdc37m60x_init, + .close = fdc37m60x_close, + .reset = NULL, + { .available = NULL }, + .speed_changed = NULL, + .force_redraw = NULL, + .config = NULL }; diff --git a/src/sio/sio_it8661f.c b/src/sio/sio_it8661f.c index 565feb72c..5367ffedf 100644 --- a/src/sio/sio_it8661f.c +++ b/src/sio/sio_it8661f.c @@ -1,18 +1,18 @@ /* - * 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. + * 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. + * This file is part of the 86Box distribution. * - * Implementation of the ITE IT8661F chipset. + * Implementation of the ITE IT8661F chipset. * - * Note: This Super I/O is partially incomplete and intended only for having the intended machine to function + * Note: This Super I/O is partially incomplete and intended only for having the intended machine to function * - * Authors: Tiseno100 + * Authors: Tiseno100 * - * Copyright 2021 Tiseno100 + * Copyright 2021 Tiseno100 * */ #include @@ -32,251 +32,256 @@ #include <86box/fdc.h> #include <86box/fdd_common.h> #include <86box/sio.h> - +#include <86box/plat_unused.h> #define LDN dev->regs[7] - -typedef struct -{ - fdc_t *fdc_controller; +typedef struct it8661f_t { + fdc_t *fdc_controller; serial_t *uart[2]; - uint8_t index, regs[256], device_regs[6][256]; - int unlocked, enumerator; + uint8_t index; + uint8_t regs[256]; + uint8_t device_regs[6][256]; + int unlocked; + int enumerator; } it8661f_t; +static uint8_t mb_pnp_key[32] = { 0x6a, 0xb5, 0xda, 0xed, 0xf6, 0xfb, 0x7d, 0xbe, 0xdf, 0x6f, 0x37, 0x1b, 0x0d, 0x86, 0xc3, 0x61, 0xb0, 0x58, 0x2c, 0x16, 0x8b, 0x45, 0xa2, 0xd1, 0xe8, 0x74, 0x3a, 0x9d, 0xce, 0xe7, 0x73, 0x39 }; -static uint8_t mb_pnp_key[32] = {0x6a, 0xb5, 0xda, 0xed, 0xf6, 0xfb, 0x7d, 0xbe, 0xdf, 0x6f, 0x37, 0x1b, 0x0d, 0x86, 0xc3, 0x61, 0xb0, 0x58, 0x2c, 0x16, 0x8b, 0x45, 0xa2, 0xd1, 0xe8, 0x74, 0x3a, 0x9d, 0xce, 0xe7, 0x73, 0x39}; - - -static void it8661f_reset(void *priv); - +static void it8661f_reset(void *priv); #ifdef ENABLE_IT8661_LOG int it8661_do_log = ENABLE_IT8661_LOG; - void it8661_log(const char *fmt, ...) { va_list ap; if (it8661_do_log) { - va_start(ap, fmt); - pclog_ex(fmt, ap); - va_end(ap); + va_start(ap, fmt); + pclog_ex(fmt, ap); + va_end(ap); } } #else -#define it8661_log(fmt, ...) +# define it8661_log(fmt, ...) #endif - static void it8661_fdc(uint16_t addr, uint8_t val, it8661f_t *dev) { fdc_remove(dev->fdc_controller); if (((addr == 0x30) && (val & 1)) || (dev->device_regs[0][0x30] & 1)) { - switch (addr) { - case 0x30: - dev->device_regs[0][addr] = val & 1; - break; + switch (addr) { + case 0x30: + dev->device_regs[0][addr] = val & 1; + break; - case 0x31: - dev->device_regs[0][addr] = val & 3; - if (val & 1) - dev->device_regs[0][addr] |= 0x55; - break; + case 0x31: + dev->device_regs[0][addr] = val & 3; + if (val & 1) + dev->device_regs[0][addr] |= 0x55; + break; - case 0x60: - case 0x61: - dev->device_regs[0][addr] = val & ((addr == 0x61) ? 0xff : 0xf8); - break; + case 0x60: + case 0x61: + dev->device_regs[0][addr] = val & ((addr == 0x61) ? 0xff : 0xf8); + break; - case 0x70: - dev->device_regs[0][addr] = val & 0x0f; - break; + case 0x70: + dev->device_regs[0][addr] = val & 0x0f; + break; - case 0x74: - dev->device_regs[0][addr] = val & 7; - break; + case 0x74: + dev->device_regs[0][addr] = val & 7; + break; - case 0xf0: - dev->device_regs[0][addr] = val & 0x0f; - break; - } + case 0xf0: + dev->device_regs[0][addr] = val & 0x0f; + break; - fdc_set_base(dev->fdc_controller, (dev->device_regs[0][0x60] << 8) | (dev->device_regs[0][0x61])); - fdc_set_irq(dev->fdc_controller, dev->device_regs[0][0x70] & 0x0f); - fdc_set_dma_ch(dev->fdc_controller, dev->device_regs[0][0x74] & 7); + default: + break; + } - if (dev->device_regs[0][0xf0] & 1) - fdc_writeprotect(dev->fdc_controller); + fdc_set_base(dev->fdc_controller, (dev->device_regs[0][0x60] << 8) | (dev->device_regs[0][0x61])); + fdc_set_irq(dev->fdc_controller, dev->device_regs[0][0x70] & 0x0f); + fdc_set_dma_ch(dev->fdc_controller, dev->device_regs[0][0x74] & 7); + + if (dev->device_regs[0][0xf0] & 1) + fdc_writeprotect(dev->fdc_controller); it8661_log("ITE 8661-FDC: BASE %04x IRQ %02x\n", (dev->device_regs[0][0x60] << 8) | (dev->device_regs[0][0x61]), - dev->device_regs[0][0x70] & 0x0f); + dev->device_regs[0][0x70] & 0x0f); } } - static void it8661_serial(int uart, uint16_t addr, uint8_t val, it8661f_t *dev) { serial_remove(dev->uart[uart]); if (((addr == 0x30) && (val & 1)) || (dev->device_regs[1 + uart][0x30] & 1)) { - switch (addr) { - case 0x30: - dev->device_regs[1 + uart][addr] = val & 1; - break; + switch (addr) { + case 0x30: + dev->device_regs[1 + uart][addr] = val & 1; + break; - case 0x60: - case 0x61: - dev->device_regs[1 + uart][addr] = val & ((addr == 0x61) ? 0xff : 0xf8); - break; + case 0x60: + case 0x61: + dev->device_regs[1 + uart][addr] = val & ((addr == 0x61) ? 0xff : 0xf8); + break; - case 0x70: - dev->device_regs[1 + uart][addr] = val & 0x0f; - break; + case 0x70: + dev->device_regs[1 + uart][addr] = val & 0x0f; + break; - case 0x74: - dev->device_regs[1 + uart][addr] = val & 7; - break; + case 0x74: + dev->device_regs[1 + uart][addr] = val & 7; + break; - case 0xf0: - dev->device_regs[1 + uart][addr] = val & 3; - break; - } + case 0xf0: + dev->device_regs[1 + uart][addr] = val & 3; + break; - serial_setup(dev->uart[uart], (dev->device_regs[1 + uart][0x60] << 8) | (dev->device_regs[1 + uart][0x61]), dev->device_regs[1 + uart][0x70] & 0x0f); + default: + break; + } - it8661_log("ITE 8661-UART%01x: BASE %04x IRQ %02x\n", 1 + (LDN % 1), - (dev->device_regs[1 + uart][0x60] << 8) | (dev->device_regs[1 + uart][0x61]), - dev->device_regs[1 + uart][0x70] & 0x0f); + serial_setup(dev->uart[uart], (dev->device_regs[1 + uart][0x60] << 8) | (dev->device_regs[1 + uart][0x61]), dev->device_regs[1 + uart][0x70] & 0x0f); + + it8661_log("ITE 8661-UART%01x: BASE %04x IRQ %02x\n", 1 + (LDN % 1), + (dev->device_regs[1 + uart][0x60] << 8) | (dev->device_regs[1 + uart][0x61]), + dev->device_regs[1 + uart][0x70] & 0x0f); } } - void it8661_lpt(uint16_t addr, uint8_t val, it8661f_t *dev) { lpt1_remove(); if (((addr == 0x30) && (val & 1)) || (dev->device_regs[3][0x30] & 1)) { - switch (addr) { - case 0x30: - dev->device_regs[3][addr] = val & 1; - break; + switch (addr) { + case 0x30: + dev->device_regs[3][addr] = val & 1; + break; - case 0x60: - case 0x61: - dev->device_regs[3][addr] = val & ((addr == 0x61) ? 0xff : 0xf8); - break; + case 0x60: + case 0x61: + dev->device_regs[3][addr] = val & ((addr == 0x61) ? 0xff : 0xf8); + break; - case 0x70: - dev->device_regs[3][addr] = val & 0x0f; - break; + case 0x70: + dev->device_regs[3][addr] = val & 0x0f; + break; - case 0x74: - dev->device_regs[3][addr] = val & 7; - break; + case 0x74: + dev->device_regs[3][addr] = val & 7; + break; - case 0xf0: - dev->device_regs[3][addr] = val & 3; - break; - } + case 0xf0: + dev->device_regs[3][addr] = val & 3; + break; - lpt1_init((dev->device_regs[3][0x60] << 8) | (dev->device_regs[3][0x61])); - lpt1_irq(dev->device_regs[3][0x70] & 0x0f); + default: + break; + } - it8661_log("ITE 8661-LPT: BASE %04x IRQ %02x\n", (dev->device_regs[3][0x60] << 8) | (dev->device_regs[3][0x61]), - dev->device_regs[3][0x70] & 0x0f); + lpt1_init((dev->device_regs[3][0x60] << 8) | (dev->device_regs[3][0x61])); + lpt1_irq(dev->device_regs[3][0x70] & 0x0f); + + it8661_log("ITE 8661-LPT: BASE %04x IRQ %02x\n", (dev->device_regs[3][0x60] << 8) | (dev->device_regs[3][0x61]), + dev->device_regs[3][0x70] & 0x0f); } } - void it8661_ldn(uint16_t addr, uint8_t val, it8661f_t *dev) { switch (LDN) { - case 0: - it8661_fdc(addr, val, dev); - break; - case 1: - case 2: - it8661_serial(LDN & 2, addr, val, dev); - break; - case 3: - it8661_lpt(addr, val, dev); - break; + case 0: + it8661_fdc(addr, val, dev); + break; + case 1: + case 2: + it8661_serial((LDN & 2) - 1, addr, val, dev); + break; + case 3: + it8661_lpt(addr, val, dev); + break; + + default: + break; } } - static void it8661f_write(uint16_t addr, uint8_t val, void *priv) { - it8661f_t *dev = (it8661f_t *)priv; + it8661f_t *dev = (it8661f_t *) priv; switch (addr) { - case 0x370: - if (!dev->unlocked) { - (val == mb_pnp_key[dev->enumerator]) ? dev->enumerator++ : (dev->enumerator = 0); - if (dev->enumerator == 31) { - dev->unlocked = 1; - it8661_log("ITE8661F: Unlocked!\n"); - } - } else - dev->index = val; - break; + case FDC_SECONDARY_ADDR: + if (!dev->unlocked) { + (val == mb_pnp_key[dev->enumerator]) ? dev->enumerator++ : (dev->enumerator = 0); + if (dev->enumerator == 31) { + dev->unlocked = 1; + it8661_log("ITE8661F: Unlocked!\n"); + } + } else + dev->index = val; + break; - case 0x371: - if (dev->unlocked) { - switch (dev->index) { - case 0x02: - dev->regs[dev->index] = val; - if (val & 1) - it8661f_reset(dev); - if (val & 2) - dev->unlocked = 0; - break; - case 0x07: - dev->regs[dev->index] = val; - break; - case 0x22: - dev->regs[dev->index] = val & 0x30; - break; - case 0x23: - dev->regs[dev->index] = val & 0x1f; - break; - default: - it8661_ldn(dev->index, val, dev); - break; - } - } - break; + case 0x371: + if (dev->unlocked) { + switch (dev->index) { + case 0x02: + dev->regs[dev->index] = val; + if (val & 1) + it8661f_reset(dev); + if (val & 2) + dev->unlocked = 0; + break; + case 0x07: + dev->regs[dev->index] = val; + break; + case 0x22: + dev->regs[dev->index] = val & 0x30; + break; + case 0x23: + dev->regs[dev->index] = val & 0x1f; + break; + default: + it8661_ldn(dev->index, val, dev); + break; + } + } + break; + + default: + break; } return; } - static uint8_t it8661f_read(uint16_t addr, void *priv) { - it8661f_t *dev = (it8661f_t *)priv; + const it8661f_t *dev = (it8661f_t *) priv; it8661_log("IT8661F:\n", addr, dev->regs[dev->index]); return (addr == 0xa79) ? dev->regs[dev->index] : 0xff; } - static void it8661f_reset(void *priv) { - it8661f_t *dev = (it8661f_t *)priv; + it8661f_t *dev = (it8661f_t *) priv; dev->regs[0x20] = 0x86; dev->regs[0x21] = 0x61; @@ -304,20 +309,18 @@ it8661f_reset(void *priv) dev->device_regs[3][0xf0] = 3; } - static void it8661f_close(void *priv) { - it8661f_t *dev = (it8661f_t *)priv; + it8661f_t *dev = (it8661f_t *) priv; free(dev); } - static void * -it8661f_init(const device_t *info) +it8661f_init(UNUSED(const device_t *info)) { - it8661f_t *dev = (it8661f_t *)malloc(sizeof(it8661f_t)); + it8661f_t *dev = (it8661f_t *) malloc(sizeof(it8661f_t)); memset(dev, 0, sizeof(it8661f_t)); dev->fdc_controller = device_add(&fdc_at_smc_device); @@ -326,26 +329,25 @@ it8661f_init(const device_t *info) dev->uart[0] = device_add_inst(&ns16550_device, 1); dev->uart[1] = device_add_inst(&ns16550_device, 2); - io_sethandler(0x0370, 0x0002, it8661f_read, NULL, NULL, it8661f_write, NULL, NULL, dev); + io_sethandler(FDC_SECONDARY_ADDR, 0x0002, it8661f_read, NULL, NULL, it8661f_write, NULL, NULL, dev); dev->enumerator = 0; - dev->unlocked = 0; + dev->unlocked = 0; it8661f_reset(dev); return dev; } - const device_t it8661f_device = { - "ITE IT8661F", - "it8661f", - 0, - 0, - it8661f_init, - it8661f_close, - NULL, - { NULL }, - NULL, - NULL, - NULL + .name = "ITE IT8661F", + .internal_name = "it8661f", + .flags = 0, + .local = 0, + .init = it8661f_init, + .close = it8661f_close, + .reset = NULL, + { .available = NULL }, + .speed_changed = NULL, + .force_redraw = NULL, + .config = NULL }; diff --git a/src/sio/sio_pc87306.c b/src/sio/sio_pc87306.c index 2b72e3de1..ab7f8597e 100644 --- a/src/sio/sio_pc87306.c +++ b/src/sio/sio_pc87306.c @@ -1,17 +1,18 @@ /* - * 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. + * 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. + * This file is part of the 86Box distribution. * - * Emulation of the NatSemi PC87306 Super I/O chip. + * Emulation of the NatSemi PC87306 Super I/O chip. * * * - * Author: Miran Grca, - * Copyright 2016-2018 Miran Grca. + * Authors: Miran Grca, + * + * Copyright 2016-2018 Miran Grca. */ #include #include @@ -33,330 +34,385 @@ #include <86box/fdd.h> #include <86box/fdc.h> #include <86box/sio.h> +#include <86box/plat_unused.h> +#include <86box/machine.h> - -typedef struct { - uint8_t tries, - regs[29], gpio[2]; - int cur_reg; - fdc_t *fdc; +typedef struct pc87306_t { + uint8_t tries; + uint8_t regs[29]; + uint8_t gpio[2]; + uint16_t gpioba; + int cur_reg; + fdc_t *fdc; serial_t *uart[2]; - nvr_t *nvr; + nvr_t *nvr; } pc87306_t; - static void pc87306_gpio_write(uint16_t port, uint8_t val, void *priv) { pc87306_t *dev = (pc87306_t *) priv; + uint32_t gpio = 0xffff0000; - dev->gpio[port & 1] = val; + dev->gpio[port & 0x0001] = val; + + if (port & 0x0001) { + gpio |= ((uint32_t) val) << 8; + gpio |= dev->gpio[0]; + } else { + gpio |= ((uint32_t) dev->gpio[1]) << 8; + gpio |= val; + } + + (void) machine_handle_gpio(1, gpio); } - uint8_t pc87306_gpio_read(uint16_t port, void *priv) { - pc87306_t *dev = (pc87306_t *) priv; + uint32_t ret = machine_handle_gpio(0, 0xffffffff); - return dev->gpio[port & 1]; + if (port & 0x0001) + ret = (ret >> 8) & 0xff; + else + ret &= 0xff; + + return ret; } - static void pc87306_gpio_remove(pc87306_t *dev) { - io_removehandler(dev->regs[0x0f] << 2, 0x0001, - pc87306_gpio_read, NULL, NULL, pc87306_gpio_write, NULL, NULL, dev); - io_removehandler((dev->regs[0x0f] << 2) + 1, 0x0001, - pc87306_gpio_read, NULL, NULL, pc87306_gpio_write, NULL, NULL, dev); + if (dev->gpioba != 0x0000) { + io_removehandler(dev->gpioba, 0x0001, + pc87306_gpio_read, NULL, NULL, pc87306_gpio_write, NULL, NULL, dev); + io_removehandler(dev->gpioba + 1, 0x0001, + pc87306_gpio_read, NULL, NULL, pc87306_gpio_write, NULL, NULL, dev); + } } - static void pc87306_gpio_init(pc87306_t *dev) { - if ((dev->regs[0x12]) & 0x10) - io_sethandler(dev->regs[0x0f] << 2, 0x0001, - pc87306_gpio_read, NULL, NULL, pc87306_gpio_write, NULL, NULL, dev); + dev->gpioba = ((uint16_t) dev->regs[0x0f]) << 2; - if ((dev->regs[0x12]) & 0x20) - io_sethandler((dev->regs[0x0f] << 2) + 1, 0x0001, - pc87306_gpio_read, NULL, NULL, pc87306_gpio_write, NULL, NULL, dev); + if (dev->gpioba != 0x0000) { + if ((dev->regs[0x12]) & 0x10) + io_sethandler(dev->gpioba, 0x0001, + pc87306_gpio_read, NULL, NULL, pc87306_gpio_write, NULL, NULL, dev); + + if ((dev->regs[0x12]) & 0x20) + io_sethandler(dev->gpioba + 1, 0x0001, + pc87306_gpio_read, NULL, NULL, pc87306_gpio_write, NULL, NULL, dev); + } } +static void +pc87306_gpio_handler(pc87306_t *dev) +{ + pc87306_gpio_remove(dev); + pc87306_gpio_init(dev); +} static void lpt1_handler(pc87306_t *dev) { - int temp; - uint16_t lptba, lpt_port = 0x378; - uint8_t lpt_irq = 5; + int temp; + uint16_t lptba; + uint16_t lpt_port = LPT1_ADDR; + uint8_t lpt_irq = LPT2_IRQ; - temp = dev->regs[0x01] & 3; + temp = dev->regs[0x01] & 3; lptba = ((uint16_t) dev->regs[0x19]) << 2; switch (temp) { - case 0: - lpt_port = 0x378; - lpt_irq = (dev->regs[0x02] & 0x08) ? 7 : 5; - break; - case 1: - if (dev->regs[0x1b] & 0x40) - lpt_port = lptba; - else - lpt_port = 0x3bc; - lpt_irq = 7; - break; - case 2: - lpt_port = 0x278; - lpt_irq = 5; - break; - case 3: - lpt_port = 0x000; - lpt_irq = 0xff; - break; + case 0: + lpt_port = LPT1_ADDR; + lpt_irq = (dev->regs[0x02] & 0x08) ? LPT1_IRQ : LPT2_IRQ; + break; + case 1: + if (dev->regs[0x1b] & 0x40) + lpt_port = lptba; + else + lpt_port = LPT_MDA_ADDR; + lpt_irq = LPT_MDA_IRQ; + break; + case 2: + lpt_port = LPT2_ADDR; + lpt_irq = LPT2_IRQ; + break; + case 3: + lpt_port = 0x000; + lpt_irq = 0xff; + break; + + default: + break; } if (dev->regs[0x1b] & 0x10) - lpt_irq = (dev->regs[0x1b] & 0x20) ? 7 : 5; + lpt_irq = (dev->regs[0x1b] & 0x20) ? 7 : 5; if (lpt_port) - lpt1_init(lpt_port); + lpt1_init(lpt_port); lpt1_irq(lpt_irq); } - static void serial_handler(pc87306_t *dev, int uart) { - int temp; - uint8_t fer_irq, pnp1_irq; - uint8_t fer_shift, pnp_shift; + int temp; + uint8_t fer_irq; + uint8_t pnp1_irq; + uint8_t fer_shift; + uint8_t pnp_shift; uint8_t irq; temp = (dev->regs[1] >> (2 << uart)) & 3; - fer_shift = 2 << uart; /* 2 for UART 1, 4 for UART 2 */ - pnp_shift = 2 + (uart << 2); /* 2 for UART 1, 6 for UART 2 */ + fer_shift = 2 << uart; /* 2 for UART 1, 4 for UART 2 */ + pnp_shift = 2 + (uart << 2); /* 2 for UART 1, 6 for UART 2 */ /* 0 = COM1 (IRQ 4), 1 = COM2 (IRQ 3), 2 = COM3 (IRQ 4), 3 = COM4 (IRQ 3) */ - fer_irq = ((dev->regs[1] >> fer_shift) & 1) ? 3 : 4; + fer_irq = ((dev->regs[1] >> fer_shift) & 1) ? 3 : 4; pnp1_irq = ((dev->regs[0x1c] >> pnp_shift) & 1) ? 4 : 3; irq = (dev->regs[0x1c] & 1) ? pnp1_irq : fer_irq; switch (temp) { - case 0: - serial_setup(dev->uart[uart], SERIAL1_ADDR, irq); - break; - case 1: - serial_setup(dev->uart[uart], SERIAL2_ADDR, irq); - break; - case 2: - switch ((dev->regs[1] >> 6) & 3) { - case 0: - serial_setup(dev->uart[uart], 0x3e8, irq); - break; - case 1: - serial_setup(dev->uart[uart], 0x338, irq); - break; - case 2: - serial_setup(dev->uart[uart], 0x2e8, irq); - break; - case 3: - serial_setup(dev->uart[uart], 0x220, irq); - break; - } - break; - case 3: - switch ((dev->regs[1] >> 6) & 3) { - case 0: - serial_setup(dev->uart[uart], 0x2e8, irq); - break; - case 1: - serial_setup(dev->uart[uart], 0x238, irq); - break; - case 2: - serial_setup(dev->uart[uart], 0x2e0, irq); - break; - case 3: - serial_setup(dev->uart[uart], 0x228, irq); - break; - } - break; + case 0: + serial_setup(dev->uart[uart], COM1_ADDR, irq); + break; + case 1: + serial_setup(dev->uart[uart], COM2_ADDR, irq); + break; + case 2: + switch ((dev->regs[1] >> 6) & 3) { + case 0: + serial_setup(dev->uart[uart], COM3_ADDR, irq); + break; + case 1: + serial_setup(dev->uart[uart], 0x338, irq); + break; + case 2: + serial_setup(dev->uart[uart], COM4_ADDR, irq); + break; + case 3: + serial_setup(dev->uart[uart], 0x220, irq); + break; + + default: + break; + } + break; + case 3: + switch ((dev->regs[1] >> 6) & 3) { + case 0: + serial_setup(dev->uart[uart], COM4_ADDR, irq); + break; + case 1: + serial_setup(dev->uart[uart], 0x238, irq); + break; + case 2: + serial_setup(dev->uart[uart], 0x2e0, irq); + break; + case 3: + serial_setup(dev->uart[uart], 0x228, irq); + break; + + default: + break; + } + break; + + default: + break; } } - static void pc87306_write(uint16_t port, uint8_t val, void *priv) { pc87306_t *dev = (pc87306_t *) priv; - uint8_t index, valxor; + uint8_t index; + uint8_t valxor; index = (port & 1) ? 0 : 1; if (index) { - dev->cur_reg = val & 0x1f; - dev->tries = 0; - return; + dev->cur_reg = val & 0x1f; + dev->tries = 0; + return; } else { - if (dev->tries) { - if ((dev->cur_reg == 0) && (val == 8)) - val = 0x4b; - valxor = val ^ dev->regs[dev->cur_reg]; - dev->tries = 0; - if ((dev->cur_reg <= 28) && (dev->cur_reg != 8)) { - if (dev->cur_reg == 0) - val &= 0x5f; - if (((dev->cur_reg == 0x0F) || (dev->cur_reg == 0x12)) && valxor) - pc87306_gpio_remove(dev); - dev->regs[dev->cur_reg] = val; - } else - return; - } else { - dev->tries++; - return; - } + if (dev->tries) { + if ((dev->cur_reg == 0) && (val == 8)) + val = 0x4b; + valxor = val ^ dev->regs[dev->cur_reg]; + dev->tries = 0; + if ((dev->cur_reg <= 28) && (dev->cur_reg != 8)) { + if (dev->cur_reg == 0) + val &= 0x5f; + dev->regs[dev->cur_reg] = val; + } else + return; + } else { + dev->tries++; + return; + } } - switch(dev->cur_reg) { - case 0: - if (valxor & 1) { - lpt1_remove(); - if ((val & 1) && !(dev->regs[2] & 1)) - lpt1_handler(dev); - } - if (valxor & 2) { - serial_remove(dev->uart[0]); - if ((val & 2) && !(dev->regs[2] & 1)) - serial_handler(dev, 0); - } - if (valxor & 4) { - serial_remove(dev->uart[1]); - if ((val & 4) && !(dev->regs[2] & 1)) - serial_handler(dev, 1); - } - if (valxor & 0x28) { - fdc_remove(dev->fdc); - if ((val & 8) && !(dev->regs[2] & 1)) - fdc_set_base(dev->fdc, (val & 0x20) ? 0x370 : 0x3f0); - } - break; - case 1: - if (valxor & 3) { - lpt1_remove(); - if ((dev->regs[0] & 1) && !(dev->regs[2] & 1)) - lpt1_handler(dev); - } - if (valxor & 0xcc) { - serial_remove(dev->uart[0]); - if ((dev->regs[0] & 2) && !(dev->regs[2] & 1)) - serial_handler(dev, 0); - } - if (valxor & 0xf0) { - serial_remove(dev->uart[1]); - if ((dev->regs[0] & 4) && !(dev->regs[2] & 1)) - serial_handler(dev, 1); - } - break; - case 2: - if (valxor & 1) { - lpt1_remove(); - serial_remove(dev->uart[0]); - serial_remove(dev->uart[1]); - fdc_remove(dev->fdc); + switch (dev->cur_reg) { + case 0x00: + if (valxor & 1) { + lpt1_remove(); + if ((val & 1) && !(dev->regs[2] & 1)) + lpt1_handler(dev); + } + if (valxor & 2) { + serial_remove(dev->uart[0]); + if ((val & 2) && !(dev->regs[2] & 1)) + serial_handler(dev, 0); + } + if (valxor & 4) { + serial_remove(dev->uart[1]); + if ((val & 4) && !(dev->regs[2] & 1)) + serial_handler(dev, 1); + } + if (valxor & 0x28) { + fdc_remove(dev->fdc); + if ((val & 8) && !(dev->regs[2] & 1)) + fdc_set_base(dev->fdc, (val & 0x20) ? FDC_SECONDARY_ADDR : FDC_PRIMARY_ADDR); + } + break; + case 0x01: + if (valxor & 3) { + lpt1_remove(); + if ((dev->regs[0] & 1) && !(dev->regs[2] & 1)) + lpt1_handler(dev); + } + if (valxor & 0xcc) { + serial_remove(dev->uart[0]); + if ((dev->regs[0] & 2) && !(dev->regs[2] & 1)) + serial_handler(dev, 0); + } + if (valxor & 0xf0) { + serial_remove(dev->uart[1]); + if ((dev->regs[0] & 4) && !(dev->regs[2] & 1)) + serial_handler(dev, 1); + } + break; + case 0x02: + if (valxor & 1) { + lpt1_remove(); + serial_remove(dev->uart[0]); + serial_remove(dev->uart[1]); + fdc_remove(dev->fdc); - if (!(val & 1)) { - if (dev->regs[0] & 1) - lpt1_handler(dev); - if (dev->regs[0] & 2) - serial_handler(dev, 0); - if (dev->regs[0] & 4) - serial_handler(dev, 1); - if (dev->regs[0] & 8) - fdc_set_base(dev->fdc, (dev->regs[0] & 0x20) ? 0x370 : 0x3f0); - } - } - if (valxor & 8) { - lpt1_remove(); - if ((dev->regs[0] & 1) && !(dev->regs[2] & 1)) - lpt1_handler(dev); - } - break; - case 9: - if (valxor & 0x44) { - fdc_update_enh_mode(dev->fdc, (val & 4) ? 1 : 0); - fdc_update_densel_polarity(dev->fdc, (val & 0x40) ? 1 : 0); - } - break; - case 0xF: - if (valxor) - pc87306_gpio_init(dev); - break; - case 0x12: - if (valxor & 0x30) - pc87306_gpio_init(dev); - break; - case 0x19: - if (valxor) { - lpt1_remove(); - if ((dev->regs[0] & 1) && !(dev->regs[2] & 1)) - lpt1_handler(dev); - } - break; - case 0x1B: - if (valxor & 0x70) { - lpt1_remove(); - if (!(val & 0x40)) - dev->regs[0x19] = 0xEF; - if ((dev->regs[0] & 1) && !(dev->regs[2] & 1)) - lpt1_handler(dev); - } - break; - case 0x1C: - if (valxor) { - serial_remove(dev->uart[0]); - serial_remove(dev->uart[1]); + if (!(val & 1)) { + if (dev->regs[0] & 1) + lpt1_handler(dev); + if (dev->regs[0] & 2) + serial_handler(dev, 0); + if (dev->regs[0] & 4) + serial_handler(dev, 1); + if (dev->regs[0] & 8) + fdc_set_base(dev->fdc, (dev->regs[0] & 0x20) ? FDC_SECONDARY_ADDR : FDC_PRIMARY_ADDR); + } + } + if (valxor & 8) { + lpt1_remove(); + if ((dev->regs[0] & 1) && !(dev->regs[2] & 1)) + lpt1_handler(dev); + } + break; + case 0x04: + if (valxor & 0x80) + nvr_lock_set(0x00, 256, !!(val & 0x80), dev->nvr); + break; + case 0x05: + if (valxor & 0x08) + nvr_at_handler(!!(val & 0x08), 0x0070, dev->nvr); + if (valxor & 0x20) + nvr_bank_set(0, !!(val & 0x20), dev->nvr); + break; + case 0x09: + if (valxor & 0x44) { + fdc_update_enh_mode(dev->fdc, (val & 4) ? 1 : 0); + fdc_update_densel_polarity(dev->fdc, (val & 0x40) ? 1 : 0); + } + break; + case 0x0f: + if (valxor) + pc87306_gpio_handler(dev); + break; + case 0x12: + if (valxor & 0x01) + nvr_wp_set(!!(val & 0x01), 0, dev->nvr); + if (valxor & 0x30) + pc87306_gpio_handler(dev); + break; + case 0x19: + if (valxor) { + lpt1_remove(); + if ((dev->regs[0] & 1) && !(dev->regs[2] & 1)) + lpt1_handler(dev); + } + break; + case 0x1B: + if (valxor & 0x70) { + lpt1_remove(); + if (!(val & 0x40)) + dev->regs[0x19] = 0xEF; + if ((dev->regs[0] & 1) && !(dev->regs[2] & 1)) + lpt1_handler(dev); + } + break; + case 0x1C: + if (valxor) { + serial_remove(dev->uart[0]); + serial_remove(dev->uart[1]); - if ((dev->regs[0] & 2) && !(dev->regs[2] & 1)) - serial_handler(dev, 0); - if ((dev->regs[0] & 4) && !(dev->regs[2] & 1)) - serial_handler(dev, 1); - } - break; + if ((dev->regs[0] & 2) && !(dev->regs[2] & 1)) + serial_handler(dev, 0); + if ((dev->regs[0] & 4) && !(dev->regs[2] & 1)) + serial_handler(dev, 1); + } + break; + + default: + break; } } - uint8_t pc87306_read(uint16_t port, void *priv) { pc87306_t *dev = (pc87306_t *) priv; - uint8_t ret = 0xff, index; + uint8_t ret = 0xff; + uint8_t index; index = (port & 1) ? 0 : 1; dev->tries = 0; if (index) - ret = dev->cur_reg & 0x1f; + ret = dev->cur_reg & 0x1f; else { - if (dev->cur_reg == 8) - ret = 0x70; - else if (dev->cur_reg < 28) - ret = dev->regs[dev->cur_reg]; + if (dev->cur_reg == 8) + ret = 0x70; + else if (dev->cur_reg < 28) + ret = dev->regs[dev->cur_reg]; } return ret; } - void -pc87306_reset(pc87306_t *dev) +pc87306_reset_common(void *priv) { + pc87306_t *dev = (pc87306_t *) priv; + memset(dev->regs, 0, 29); dev->regs[0x00] = 0x0B; @@ -370,12 +426,9 @@ pc87306_reset(pc87306_t *dev) dev->regs[0x12] = 0x30; dev->regs[0x19] = 0xEF; - dev->gpio[0] = 0xff; - dev->gpio[1] = 0xfb; - /* - 0 = 360 rpm @ 500 kbps for 3.5" - 1 = Default, 300 rpm @ 500,300,250,1000 kbps for 3.5" + 0 = 360 rpm @ 500 kbps for 3.5" + 1 = Default, 300 rpm @ 500, 300, 250, 1000 kbps for 3.5" */ lpt1_remove(); lpt1_handler(dev); @@ -385,8 +438,23 @@ pc87306_reset(pc87306_t *dev) serial_handler(dev, 1); fdc_reset(dev->fdc); pc87306_gpio_init(dev); + nvr_lock_set(0x00, 256, 0, dev->nvr); + nvr_at_handler(0, 0x0070, dev->nvr); + nvr_at_handler(1, 0x0070, dev->nvr); + nvr_bank_set(0, 0, dev->nvr); + nvr_wp_set(0, 0, dev->nvr); } +void +pc87306_reset(void *priv) +{ + pc87306_t *dev = (pc87306_t *) priv; + + pc87306_gpio_write(0x0000, 0xff, dev); + pc87306_gpio_write(0x0001, 0xff, dev); + + pc87306_reset_common(dev); +} static void pc87306_close(void *priv) @@ -396,9 +464,8 @@ pc87306_close(void *priv) free(dev); } - static void * -pc87306_init(const device_t *info) +pc87306_init(UNUSED(const device_t *info)) { pc87306_t *dev = (pc87306_t *) malloc(sizeof(pc87306_t)); memset(dev, 0, sizeof(pc87306_t)); @@ -408,23 +475,28 @@ pc87306_init(const device_t *info) dev->uart[0] = device_add_inst(&ns16550_device, 1); dev->uart[1] = device_add_inst(&ns16550_device, 2); - // dev->nvr = device_add(&piix4_nvr_device); + dev->nvr = device_add(&at_mb_nvr_device); - pc87306_reset(dev); + dev->gpio[0] = dev->gpio[1] = 0xff; + + pc87306_reset_common(dev); io_sethandler(0x02e, 0x0002, - pc87306_read, NULL, NULL, pc87306_write, NULL, NULL, dev); + pc87306_read, NULL, NULL, pc87306_write, NULL, NULL, dev); return dev; } - const device_t pc87306_device = { - "National Semiconductor PC87306 Super I/O", - "pc87306", - 0, - 0, - pc87306_init, pc87306_close, NULL, - { NULL }, NULL, NULL, - NULL + .name = "National Semiconductor PC87306 Super I/O", + .internal_name = "pc87306", + .flags = 0, + .local = 0, + .init = pc87306_init, + .close = pc87306_close, + .reset = pc87306_reset, + { .available = NULL }, + .speed_changed = NULL, + .force_redraw = NULL, + .config = NULL }; diff --git a/src/sio/sio_pc87307.c b/src/sio/sio_pc87307.c index 24432c670..63e19c03d 100644 --- a/src/sio/sio_pc87307.c +++ b/src/sio/sio_pc87307.c @@ -1,17 +1,18 @@ /* - * 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. + * 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. + * This file is part of the 86Box distribution. * - * Emulation of the NatSemi PC87307 Super I/O chip. + * Emulation of the NatSemi PC87307 Super I/O chip. * * * - * Author: Miran Grca, - * Copyright 2020 Miran Grca. + * Authors: Miran Grca, + * + * Copyright 2020 Miran Grca. */ #include #include @@ -34,70 +35,73 @@ #include <86box/fdc.h> #include <86box/sio.h> - -typedef struct { - uint8_t id, pm_idx, - regs[48], ld_regs[256][208], - pcregs[16], gpio[2][4], - pm[8]; - uint16_t gpio_base, gpio_base2, - pm_base; - int cur_reg; - fdc_t *fdc; +typedef struct pc87307_t { + uint8_t id; + uint8_t pm_idx; + uint8_t regs[48]; + uint8_t ld_regs[256][208]; + uint8_t pcregs[16]; + uint8_t gpio[2][4]; + uint8_t pm[8]; + uint16_t gpio_base; + uint16_t gpio_base2; + uint16_t pm_base; + int cur_reg; + fdc_t *fdc; serial_t *uart[2]; } pc87307_t; - -static void fdc_handler(pc87307_t *dev); -static void lpt1_handler(pc87307_t *dev); -static void serial_handler(pc87307_t *dev, int uart); - +static void fdc_handler(pc87307_t *dev); +static void lpt1_handler(pc87307_t *dev); +static void serial_handler(pc87307_t *dev, int uart); static void pc87307_gpio_write(uint16_t port, uint8_t val, void *priv) { - pc87307_t *dev = (pc87307_t *) priv; - uint8_t bank = ((port & 0xfffc) == dev->gpio_base2); + pc87307_t *dev = (pc87307_t *) priv; + uint8_t bank = ((port & 0xfffc) == dev->gpio_base2); dev->gpio[bank][port & 3] = val; } - uint8_t pc87307_gpio_read(uint16_t port, void *priv) { - pc87307_t *dev = (pc87307_t *) priv; - uint8_t pins = 0xff, bank = ((port & 0xfffc) == dev->gpio_base2); - uint8_t mask, ret = dev->gpio[bank][port & 0x0003]; + const pc87307_t *dev = (pc87307_t *) priv; + uint8_t pins = 0xff; + uint8_t bank = ((port & 0xfffc) == dev->gpio_base2); + uint8_t mask; + uint8_t ret = dev->gpio[bank][port & 0x0003]; switch (port & 0x0003) { - case 0x0000: - mask = dev->gpio[bank][0x0001]; - ret = (ret & mask) | (pins & ~mask); - break; + case 0x0000: + mask = dev->gpio[bank][0x0001]; + ret = (ret & mask) | (pins & ~mask); + break; + + default: + break; } return ret; } - static void pc87307_gpio_remove(pc87307_t *dev) { if (dev->gpio_base != 0xffff) { - io_removehandler(dev->gpio_base, 0x0002, - pc87307_gpio_read, NULL, NULL, pc87307_gpio_write, NULL, NULL, dev); - dev->gpio_base = 0xffff; + io_removehandler(dev->gpio_base, 0x0002, + pc87307_gpio_read, NULL, NULL, pc87307_gpio_write, NULL, NULL, dev); + dev->gpio_base = 0xffff; } if (dev->gpio_base2 != 0xffff) { - io_removehandler(dev->gpio_base2, 0x0002, - pc87307_gpio_read, NULL, NULL, pc87307_gpio_write, NULL, NULL, dev); - dev->gpio_base2 = 0xffff; + io_removehandler(dev->gpio_base2, 0x0002, + pc87307_gpio_read, NULL, NULL, pc87307_gpio_write, NULL, NULL, dev); + dev->gpio_base2 = 0xffff; } } - static void pc87307_gpio_init(pc87307_t *dev, int bank, uint16_t addr) { @@ -106,360 +110,378 @@ pc87307_gpio_init(pc87307_t *dev, int bank, uint16_t addr) *bank_base = addr; io_sethandler(*bank_base, 0x0002, - pc87307_gpio_read, NULL, NULL, pc87307_gpio_write, NULL, NULL, dev); + pc87307_gpio_read, NULL, NULL, pc87307_gpio_write, NULL, NULL, dev); } - static void pc87307_pm_write(uint16_t port, uint8_t val, void *priv) { pc87307_t *dev = (pc87307_t *) priv; if (port & 1) - dev->pm[dev->pm_idx] = val; + dev->pm[dev->pm_idx] = val; else { - dev->pm_idx = val & 0x07; - switch (dev->pm_idx) { - case 0x00: - fdc_handler(dev); - lpt1_handler(dev); - serial_handler(dev, 1); - serial_handler(dev, 0); - break; - } + dev->pm_idx = val & 0x07; + switch (dev->pm_idx) { + case 0x00: + fdc_handler(dev); + lpt1_handler(dev); + serial_handler(dev, 1); + serial_handler(dev, 0); + break; + + default: + break; + } } } - uint8_t pc87307_pm_read(uint16_t port, void *priv) { - pc87307_t *dev = (pc87307_t *) priv; + const pc87307_t *dev = (pc87307_t *) priv; if (port & 1) - return dev->pm[dev->pm_idx]; + return dev->pm[dev->pm_idx]; else - return dev->pm_idx; + return dev->pm_idx; } - static void pc87307_pm_remove(pc87307_t *dev) { if (dev->pm_base != 0xffff) { - io_removehandler(dev->pm_base, 0x0008, - pc87307_pm_read, NULL, NULL, pc87307_pm_write, NULL, NULL, dev); - dev->pm_base = 0xffff; + io_removehandler(dev->pm_base, 0x0008, + pc87307_pm_read, NULL, NULL, pc87307_pm_write, NULL, NULL, dev); + dev->pm_base = 0xffff; } } - static void pc87307_pm_init(pc87307_t *dev, uint16_t addr) { dev->pm_base = addr; io_sethandler(dev->pm_base, 0x0008, - pc87307_pm_read, NULL, NULL, pc87307_pm_write, NULL, NULL, dev); + pc87307_pm_read, NULL, NULL, pc87307_pm_write, NULL, NULL, dev); } - static void fdc_handler(pc87307_t *dev) { - uint8_t irq, active; + uint8_t irq; + uint8_t active; uint16_t addr; fdc_remove(dev->fdc); active = (dev->ld_regs[0x03][0x00] & 0x01) && (dev->pm[0x00] & 0x08); - addr = ((dev->ld_regs[0x03][0x30] << 8) | dev->ld_regs[0x03][0x31]) - 0x0002; - irq = (dev->ld_regs[0x03][0x40] & 0x0f); + addr = ((dev->ld_regs[0x03][0x30] << 8) | dev->ld_regs[0x03][0x31]) - 0x0002; + irq = (dev->ld_regs[0x03][0x40] & 0x0f); if (active && (addr <= 0xfff8)) { - fdc_set_base(dev->fdc, addr); - fdc_set_irq(dev->fdc, irq); + fdc_set_base(dev->fdc, addr); + fdc_set_irq(dev->fdc, irq); } } - static void lpt1_handler(pc87307_t *dev) { - uint8_t irq, active; + uint8_t irq; + uint8_t active; uint16_t addr; lpt1_remove(); active = (dev->ld_regs[0x04][0x00] & 0x01) && (dev->pm[0x00] & 0x10); - addr = (dev->ld_regs[0x04][0x30] << 8) | dev->ld_regs[0x04][0x31]; - irq = (dev->ld_regs[0x04][0x40] & 0x0f); + addr = (dev->ld_regs[0x04][0x30] << 8) | dev->ld_regs[0x04][0x31]; + irq = (dev->ld_regs[0x04][0x40] & 0x0f); if (active && (addr <= 0xfffc)) { - lpt1_init(addr); - lpt1_irq(irq); + lpt1_init(addr); + lpt1_irq(irq); } } - static void serial_handler(pc87307_t *dev, int uart) { - uint8_t irq, active; + uint8_t irq; + uint8_t active; uint16_t addr; serial_remove(dev->uart[uart]); active = (dev->ld_regs[0x06 - uart][0x00] & 0x01) && (dev->pm[0x00] & (1 << (6 - uart))); - addr = (dev->ld_regs[0x06 - uart][0x30] << 8) | dev->ld_regs[0x06 - uart][0x31]; - irq = (dev->ld_regs[0x06 - uart][0x40] & 0x0f); + addr = (dev->ld_regs[0x06 - uart][0x30] << 8) | dev->ld_regs[0x06 - uart][0x31]; + irq = (dev->ld_regs[0x06 - uart][0x40] & 0x0f); if (active && (addr <= 0xfff8)) - serial_setup(dev->uart[uart], addr, irq); + serial_setup(dev->uart[uart], addr, irq); } - static void gpio_handler(pc87307_t *dev) { - uint8_t active; + uint8_t active; uint16_t addr; pc87307_gpio_remove(dev); active = (dev->ld_regs[0x07][0x00] & 0x01); - addr = (dev->ld_regs[0x07][0x30] << 8) | dev->ld_regs[0x07][0x31]; + addr = (dev->ld_regs[0x07][0x30] << 8) | dev->ld_regs[0x07][0x31]; if (active) - pc87307_gpio_init(dev, 0, addr); + pc87307_gpio_init(dev, 0, addr); addr = (dev->ld_regs[0x07][0x32] << 8) | dev->ld_regs[0x07][0x33]; if (active) - pc87307_gpio_init(dev, 1, addr); + pc87307_gpio_init(dev, 1, addr); } - static void pm_handler(pc87307_t *dev) { - uint8_t active; + uint8_t active; uint16_t addr; pc87307_pm_remove(dev); active = (dev->ld_regs[0x08][0x00] & 0x01); - addr = (dev->ld_regs[0x08][0x30] << 8) | dev->ld_regs[0x08][0x31]; + addr = (dev->ld_regs[0x08][0x30] << 8) | dev->ld_regs[0x08][0x31]; if (active) - pc87307_pm_init(dev, addr); + pc87307_pm_init(dev, addr); } - static void pc87307_write(uint16_t port, uint8_t val, void *priv) { pc87307_t *dev = (pc87307_t *) priv; - uint8_t index; + uint8_t index; index = (port & 1) ? 0 : 1; if (index) { - dev->cur_reg = val; - return; + dev->cur_reg = val; + return; } else { - switch (dev->cur_reg) { - case 0x00: case 0x02: case 0x03: case 0x06: - case 0x07: case 0x21: - dev->regs[dev->cur_reg] = val; - break; - case 0x22: - dev->regs[dev->cur_reg] = val & 0x7f; - break; - case 0x23: - dev->regs[dev->cur_reg] = val & 0x0f; - break; - case 0x24: - dev->pcregs[dev->regs[0x23]] = val; - break; - default: - if (dev->cur_reg >= 0x30) { - if ((dev->regs[0x07] != 0x06) || !(dev->regs[0x21] & 0x10)) - dev->ld_regs[dev->regs[0x07]][dev->cur_reg - 0x30] = val; - } - break; - } + switch (dev->cur_reg) { + case 0x00: + case 0x02: + case 0x03: + case 0x06: + case 0x07: + case 0x21: + dev->regs[dev->cur_reg] = val; + break; + case 0x22: + dev->regs[dev->cur_reg] = val & 0x7f; + break; + case 0x23: + dev->regs[dev->cur_reg] = val & 0x0f; + break; + case 0x24: + dev->pcregs[dev->regs[0x23]] = val; + break; + default: + if (dev->cur_reg >= 0x30) { + if ((dev->regs[0x07] != 0x06) || !(dev->regs[0x21] & 0x10)) + dev->ld_regs[dev->regs[0x07]][dev->cur_reg - 0x30] = val; + } + break; + } } - switch(dev->cur_reg) { - case 0x30: - dev->ld_regs[dev->regs[0x07]][dev->cur_reg - 0x30] = val & 0x01; - switch (dev->regs[0x07]) { - case 0x03: - fdc_handler(dev); - break; - case 0x04: - lpt1_handler(dev); - break; - case 0x05: - serial_handler(dev, 1); - break; - case 0x06: - serial_handler(dev, 0); - break; - case 0x07: - gpio_handler(dev); - break; - case 0x08: - pm_handler(dev); - break; - } - break; - case 0x60: case 0x62: - dev->ld_regs[dev->regs[0x07]][dev->cur_reg - 0x30] = val & 0x07; - if ((dev->cur_reg == 0x62) && (dev->regs[0x07] != 0x07)) - break; - switch (dev->regs[0x07]) { - case 0x03: - fdc_handler(dev); - break; - case 0x04: - lpt1_handler(dev); - break; - case 0x05: - serial_handler(dev, 1); - break; - case 0x06: - serial_handler(dev, 0); - break; - case 0x07: - gpio_handler(dev); - break; - case 0x08: - pm_handler(dev); - break; - } - break; - case 0x61: - switch (dev->regs[0x07]) { - case 0x00: - dev->ld_regs[dev->regs[0x07]][dev->cur_reg - 0x30] = val & 0xfb; - break; - case 0x03: - dev->ld_regs[dev->regs[0x07]][dev->cur_reg - 0x30] = (val & 0xfa) | 0x02; - fdc_handler(dev); - break; - case 0x04: - dev->ld_regs[dev->regs[0x07]][dev->cur_reg - 0x30] = val & 0xfc; - lpt1_handler(dev); - break; - case 0x05: - dev->ld_regs[dev->regs[0x07]][dev->cur_reg - 0x30] = val & 0xf8; - serial_handler(dev, 1); - break; - case 0x06: - dev->ld_regs[dev->regs[0x07]][dev->cur_reg - 0x30] = val & 0xf8; - serial_handler(dev, 0); - break; - case 0x07: - dev->ld_regs[dev->regs[0x07]][dev->cur_reg - 0x30] = val & 0xf8; - gpio_handler(dev); - break; - case 0x08: - dev->ld_regs[dev->regs[0x07]][dev->cur_reg - 0x30] = val & 0xfe; - pm_handler(dev); - break; - } - break; - case 0x63: - if (dev->regs[0x07] == 0x00) - dev->ld_regs[dev->regs[0x07]][dev->cur_reg - 0x30] = (val & 0xfb) | 0x04; - else if (dev->regs[0x07] == 0x07) { - dev->ld_regs[dev->regs[0x07]][dev->cur_reg - 0x30] = val & 0xfe; - gpio_handler(dev); - } - break; - case 0x70: - case 0x74: case 0x75: - switch (dev->regs[0x07]) { - case 0x03: - fdc_handler(dev); - break; - case 0x04: - lpt1_handler(dev); - break; - case 0x05: - serial_handler(dev, 1); - break; - case 0x06: - serial_handler(dev, 0); - break; - case 0x07: - gpio_handler(dev); - break; - case 0x08: - pm_handler(dev); - break; - } - break; - case 0xf0: - switch (dev->regs[0x07]) { - case 0x00: - dev->ld_regs[dev->regs[0x07]][dev->cur_reg - 0x30] = val & 0xc1; - break; - case 0x03: - dev->ld_regs[dev->regs[0x07]][dev->cur_reg - 0x30] = val & 0xe1; - fdc_update_densel_polarity(dev->fdc, (val & 0x20) ? 1 : 0); - fdc_update_enh_mode(dev->fdc, (val & 0x40) ? 1 : 0); - break; - case 0x04: - dev->ld_regs[dev->regs[0x07]][dev->cur_reg - 0x30] = val & 0xf3; - lpt1_handler(dev); - break; - case 0x05: case 0x06: - dev->ld_regs[dev->regs[0x07]][dev->cur_reg - 0x30] = val & 0x87; - break; - } - break; - case 0xf1: - if (dev->regs[0x07] == 0x03) - dev->ld_regs[dev->regs[0x07]][dev->cur_reg - 0x30] = val & 0x0f; - break; + switch (dev->cur_reg) { + case 0x30: + dev->ld_regs[dev->regs[0x07]][dev->cur_reg - 0x30] = val & 0x01; + switch (dev->regs[0x07]) { + case 0x03: + fdc_handler(dev); + break; + case 0x04: + lpt1_handler(dev); + break; + case 0x05: + serial_handler(dev, 1); + break; + case 0x06: + serial_handler(dev, 0); + break; + case 0x07: + gpio_handler(dev); + break; + case 0x08: + pm_handler(dev); + break; + + default: + break; + } + break; + case 0x60: + case 0x62: + dev->ld_regs[dev->regs[0x07]][dev->cur_reg - 0x30] = val & 0x07; + if ((dev->cur_reg == 0x62) && (dev->regs[0x07] != 0x07)) + break; + switch (dev->regs[0x07]) { + case 0x03: + fdc_handler(dev); + break; + case 0x04: + lpt1_handler(dev); + break; + case 0x05: + serial_handler(dev, 1); + break; + case 0x06: + serial_handler(dev, 0); + break; + case 0x07: + gpio_handler(dev); + break; + case 0x08: + pm_handler(dev); + break; + + default: + break; + } + break; + case 0x61: + switch (dev->regs[0x07]) { + case 0x00: + dev->ld_regs[dev->regs[0x07]][dev->cur_reg - 0x30] = val & 0xfb; + break; + case 0x03: + dev->ld_regs[dev->regs[0x07]][dev->cur_reg - 0x30] = (val & 0xfa) | 0x02; + fdc_handler(dev); + break; + case 0x04: + dev->ld_regs[dev->regs[0x07]][dev->cur_reg - 0x30] = val & 0xfc; + lpt1_handler(dev); + break; + case 0x05: + dev->ld_regs[dev->regs[0x07]][dev->cur_reg - 0x30] = val & 0xf8; + serial_handler(dev, 1); + break; + case 0x06: + dev->ld_regs[dev->regs[0x07]][dev->cur_reg - 0x30] = val & 0xf8; + serial_handler(dev, 0); + break; + case 0x07: + dev->ld_regs[dev->regs[0x07]][dev->cur_reg - 0x30] = val & 0xf8; + gpio_handler(dev); + break; + case 0x08: + dev->ld_regs[dev->regs[0x07]][dev->cur_reg - 0x30] = val & 0xfe; + pm_handler(dev); + break; + + default: + break; + } + break; + case 0x63: + if (dev->regs[0x07] == 0x00) + dev->ld_regs[dev->regs[0x07]][dev->cur_reg - 0x30] = (val & 0xfb) | 0x04; + else if (dev->regs[0x07] == 0x07) { + dev->ld_regs[dev->regs[0x07]][dev->cur_reg - 0x30] = val & 0xfe; + gpio_handler(dev); + } + break; + case 0x70: + case 0x74: + case 0x75: + switch (dev->regs[0x07]) { + case 0x03: + fdc_handler(dev); + break; + case 0x04: + lpt1_handler(dev); + break; + case 0x05: + serial_handler(dev, 1); + break; + case 0x06: + serial_handler(dev, 0); + break; + case 0x07: + gpio_handler(dev); + break; + case 0x08: + pm_handler(dev); + break; + + default: + break; + } + break; + case 0xf0: + switch (dev->regs[0x07]) { + case 0x00: + dev->ld_regs[dev->regs[0x07]][dev->cur_reg - 0x30] = val & 0xc1; + break; + case 0x03: + dev->ld_regs[dev->regs[0x07]][dev->cur_reg - 0x30] = val & 0xe1; + fdc_update_densel_polarity(dev->fdc, (val & 0x20) ? 1 : 0); + fdc_update_enh_mode(dev->fdc, (val & 0x40) ? 1 : 0); + break; + case 0x04: + dev->ld_regs[dev->regs[0x07]][dev->cur_reg - 0x30] = val & 0xf3; + lpt1_handler(dev); + break; + case 0x05: + case 0x06: + dev->ld_regs[dev->regs[0x07]][dev->cur_reg - 0x30] = val & 0x87; + break; + + default: + break; + } + break; + case 0xf1: + if (dev->regs[0x07] == 0x03) + dev->ld_regs[dev->regs[0x07]][dev->cur_reg - 0x30] = val & 0x0f; + break; + + default: + break; } } - uint8_t pc87307_read(uint16_t port, void *priv) { - pc87307_t *dev = (pc87307_t *) priv; - uint8_t ret = 0xff, index; + const pc87307_t *dev = (pc87307_t *) priv; + uint8_t ret = 0xff; + uint8_t index; index = (port & 1) ? 0 : 1; if (index) - ret = dev->cur_reg; + ret = dev->cur_reg; else { - if (dev->cur_reg >= 0x30) - ret = dev->ld_regs[dev->regs[0x07]][dev->cur_reg - 0x30]; - else if (dev->cur_reg == 0x24) - ret = dev->pcregs[dev->regs[0x23]]; - else - ret = dev->regs[dev->cur_reg]; + if (dev->cur_reg >= 0x30) + ret = dev->ld_regs[dev->regs[0x07]][dev->cur_reg - 0x30]; + else if (dev->cur_reg == 0x24) + ret = dev->pcregs[dev->regs[0x23]]; + else + ret = dev->regs[dev->cur_reg]; } return ret; } - void pc87307_reset(pc87307_t *dev) { - int i; - memset(dev->regs, 0x00, 0x30); - for (i = 0; i < 256; i++) - memset(dev->ld_regs[i], 0x00, 0xd0); + for (uint16_t i = 0; i < 256; i++) + memset(dev->ld_regs[i], 0x00, 0xd0); memset(dev->pcregs, 0x00, 0x10); memset(dev->gpio, 0xff, 0x08); memset(dev->pm, 0x00, 0x08); @@ -525,8 +547,10 @@ pc87307_reset(pc87307_t *dev) dev->ld_regs[0x08][0x44] = 0x04; dev->ld_regs[0x08][0x45] = 0x04; - // dev->gpio[0] = 0xff; - // dev->gpio[1] = 0xfb; +#if 0 + dev->gpio[0] = 0xff; + dev->gpio[1] = 0xfb; +#endif dev->gpio[0][0] = 0xff; dev->gpio[0][1] = 0x00; dev->gpio[0][2] = 0x00; @@ -544,8 +568,8 @@ pc87307_reset(pc87307_t *dev) dev->gpio_base = dev->pm_base = 0xffff; /* - 0 = 360 rpm @ 500 kbps for 3.5" - 1 = Default, 300 rpm @ 500,300,250,1000 kbps for 3.5" + 0 = 360 rpm @ 500 kbps for 3.5" + 1 = Default, 300 rpm @ 500, 300, 250, 1000 kbps for 3.5" */ lpt1_remove(); serial_remove(dev->uart[0]); @@ -553,7 +577,6 @@ pc87307_reset(pc87307_t *dev) fdc_reset(dev->fdc); } - static void pc87307_close(void *priv) { @@ -562,7 +585,6 @@ pc87307_close(void *priv) free(dev); } - static void * pc87307_init(const device_t *info) { @@ -579,57 +601,69 @@ pc87307_init(const device_t *info) pc87307_reset(dev); if (info->local & 0x100) { - io_sethandler(0x02e, 0x0002, - pc87307_read, NULL, NULL, pc87307_write, NULL, NULL, dev); + io_sethandler(0x02e, 0x0002, + pc87307_read, NULL, NULL, pc87307_write, NULL, NULL, dev); } if (info->local & 0x200) { - io_sethandler(0x15c, 0x0002, - pc87307_read, NULL, NULL, pc87307_write, NULL, NULL, dev); + io_sethandler(0x15c, 0x0002, + pc87307_read, NULL, NULL, pc87307_write, NULL, NULL, dev); } return dev; } - const device_t pc87307_device = { - "National Semiconductor PC87307 Super I/O", - "pc87307", - 0, - 0x1c0, - pc87307_init, pc87307_close, NULL, - { NULL }, NULL, NULL, - NULL + .name = "National Semiconductor PC87307 Super I/O", + .internal_name = "pc87307", + .flags = 0, + .local = 0x1c0, + .init = pc87307_init, + .close = pc87307_close, + .reset = NULL, + { .available = NULL }, + .speed_changed = NULL, + .force_redraw = NULL, + .config = NULL }; - const device_t pc87307_15c_device = { - "National Semiconductor PC87307 Super I/O (Port 15Ch)", - "pc87307_15c", - 0, - 0x2c0, - pc87307_init, pc87307_close, NULL, - { NULL }, NULL, NULL, - NULL + .name = "National Semiconductor PC87307 Super I/O (Port 15Ch)", + .internal_name = "pc87307_15c", + .flags = 0, + .local = 0x2c0, + .init = pc87307_init, + .close = pc87307_close, + .reset = NULL, + { .available = NULL }, + .speed_changed = NULL, + .force_redraw = NULL, + .config = NULL }; - const device_t pc87307_both_device = { - "National Semiconductor PC87307 Super I/O (Ports 2Eh and 15Ch)", - "pc87307_both", - 0, - 0x3c0, - pc87307_init, pc87307_close, NULL, - { NULL }, NULL, NULL, - NULL + .name = "National Semiconductor PC87307 Super I/O (Ports 2Eh and 15Ch)", + .internal_name = "pc87307_both", + .flags = 0, + .local = 0x3c0, + .init = pc87307_init, + .close = pc87307_close, + .reset = NULL, + { .available = NULL }, + .speed_changed = NULL, + .force_redraw = NULL, + .config = NULL }; - const device_t pc97307_device = { - "National Semiconductor PC97307 Super I/O", - "pc97307", - 0, - 0x1cf, - pc87307_init, pc87307_close, NULL, - { NULL }, NULL, NULL, - NULL + .name = "National Semiconductor PC97307 Super I/O", + .internal_name = "pc97307", + .flags = 0, + .local = 0x1cf, + .init = pc87307_init, + .close = pc87307_close, + .reset = NULL, + { .available = NULL }, + .speed_changed = NULL, + .force_redraw = NULL, + .config = NULL }; diff --git a/src/sio/sio_pc87309.c b/src/sio/sio_pc87309.c index ad214ff6a..d10cb3e0b 100644 --- a/src/sio/sio_pc87309.c +++ b/src/sio/sio_pc87309.c @@ -1,17 +1,18 @@ /* - * 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. + * 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. + * This file is part of the 86Box distribution. * - * Emulation of the NatSemi PC87309 Super I/O chip. + * Emulation of the NatSemi PC87309 Super I/O chip. * * * - * Author: Miran Grca, - * Copyright 2020 Miran Grca. + * Authors: Miran Grca, + * + * Copyright 2020 Miran Grca. */ #include #include @@ -34,22 +35,21 @@ #include <86box/fdc.h> #include <86box/sio.h> - -typedef struct { - uint8_t id, pm_idx, - regs[48], ld_regs[256][208], - pm[8]; - uint16_t pm_base; - int cur_reg; - fdc_t *fdc; +typedef struct pc87309_t { + uint8_t id; + uint8_t pm_idx; + uint8_t regs[48]; + uint8_t ld_regs[256][208]; + uint8_t pm[8]; + uint16_t pm_base; + int cur_reg; + fdc_t *fdc; serial_t *uart[2]; } pc87309_t; - -static void fdc_handler(pc87309_t *dev); -static void lpt1_handler(pc87309_t *dev); -static void serial_handler(pc87309_t *dev, int uart); - +static void fdc_handler(pc87309_t *dev); +static void lpt1_handler(pc87309_t *dev); +static void serial_handler(pc87309_t *dev, int uart); static void pc87309_pm_write(uint16_t port, uint8_t val, void *priv) @@ -57,304 +57,324 @@ pc87309_pm_write(uint16_t port, uint8_t val, void *priv) pc87309_t *dev = (pc87309_t *) priv; if (port & 1) { - dev->pm[dev->pm_idx] = val; + dev->pm[dev->pm_idx] = val; - switch (dev->pm_idx) { - case 0x00: - fdc_handler(dev); - lpt1_handler(dev); - serial_handler(dev, 1); - serial_handler(dev, 0); - break; - } + switch (dev->pm_idx) { + case 0x00: + fdc_handler(dev); + lpt1_handler(dev); + serial_handler(dev, 1); + serial_handler(dev, 0); + break; + + default: + break; + } } else - dev->pm_idx = val & 0x07; + dev->pm_idx = val & 0x07; } - uint8_t pc87309_pm_read(uint16_t port, void *priv) { - pc87309_t *dev = (pc87309_t *) priv; + const pc87309_t *dev = (pc87309_t *) priv; if (port & 1) - return dev->pm[dev->pm_idx]; + return dev->pm[dev->pm_idx]; else - return dev->pm_idx; + return dev->pm_idx; } - static void pc87309_pm_remove(pc87309_t *dev) { if (dev->pm_base != 0xffff) { - io_removehandler(dev->pm_base, 0x0008, - pc87309_pm_read, NULL, NULL, pc87309_pm_write, NULL, NULL, dev); - dev->pm_base = 0xffff; + io_removehandler(dev->pm_base, 0x0008, + pc87309_pm_read, NULL, NULL, pc87309_pm_write, NULL, NULL, dev); + dev->pm_base = 0xffff; } } - static void pc87309_pm_init(pc87309_t *dev, uint16_t addr) { dev->pm_base = addr; io_sethandler(dev->pm_base, 0x0008, - pc87309_pm_read, NULL, NULL, pc87309_pm_write, NULL, NULL, dev); + pc87309_pm_read, NULL, NULL, pc87309_pm_write, NULL, NULL, dev); } - static void fdc_handler(pc87309_t *dev) { - uint8_t irq, active; + uint8_t irq; + uint8_t active; uint16_t addr; fdc_remove(dev->fdc); active = (dev->ld_regs[0x00][0x00] & 0x01) && (dev->pm[0x00] & 0x08); - addr = ((dev->ld_regs[0x00][0x30] << 8) | dev->ld_regs[0x00][0x31]) - 0x0002; - irq = (dev->ld_regs[0x00][0x40] & 0x0f); + addr = ((dev->ld_regs[0x00][0x30] << 8) | dev->ld_regs[0x00][0x31]) - 0x0002; + irq = (dev->ld_regs[0x00][0x40] & 0x0f); if (active) { - fdc_set_base(dev->fdc, addr); - fdc_set_irq(dev->fdc, irq); + fdc_set_base(dev->fdc, addr); + fdc_set_irq(dev->fdc, irq); } } - static void lpt1_handler(pc87309_t *dev) { - uint8_t irq, active; + uint8_t irq; + uint8_t active; uint16_t addr; lpt1_remove(); active = (dev->ld_regs[0x01][0x00] & 0x01) && (dev->pm[0x00] & 0x10); - addr = (dev->ld_regs[0x01][0x30] << 8) | dev->ld_regs[0x01][0x31]; - irq = (dev->ld_regs[0x01][0x40] & 0x0f); + addr = (dev->ld_regs[0x01][0x30] << 8) | dev->ld_regs[0x01][0x31]; + irq = (dev->ld_regs[0x01][0x40] & 0x0f); if (active) { - lpt1_init(addr); - lpt1_irq(irq); + lpt1_init(addr); + lpt1_irq(irq); } } - static void serial_handler(pc87309_t *dev, int uart) { - uint8_t irq, active; + uint8_t irq; + uint8_t active; uint16_t addr; serial_remove(dev->uart[uart]); active = (dev->ld_regs[0x03 - uart][0x00] & 0x01) && (dev->pm[0x00] & (1 << (6 - uart))); - addr = (dev->ld_regs[0x03 - uart][0x30] << 8) | dev->ld_regs[0x03 - uart][0x31]; - irq = (dev->ld_regs[0x03 - uart][0x40] & 0x0f); + addr = (dev->ld_regs[0x03 - uart][0x30] << 8) | dev->ld_regs[0x03 - uart][0x31]; + irq = (dev->ld_regs[0x03 - uart][0x40] & 0x0f); if (active) - serial_setup(dev->uart[uart], addr, irq); + serial_setup(dev->uart[uart], addr, irq); } - static void pm_handler(pc87309_t *dev) { - uint8_t active; + uint8_t active; uint16_t addr; pc87309_pm_remove(dev); active = (dev->ld_regs[0x04][0x00] & 0x01); - addr = (dev->ld_regs[0x04][0x30] << 8) | dev->ld_regs[0x04][0x31]; + addr = (dev->ld_regs[0x04][0x30] << 8) | dev->ld_regs[0x04][0x31]; if (active) - pc87309_pm_init(dev, addr); + pc87309_pm_init(dev, addr); } - static void pc87309_write(uint16_t port, uint8_t val, void *priv) { pc87309_t *dev = (pc87309_t *) priv; - uint8_t index; + uint8_t index; index = (port & 1) ? 0 : 1; if (index) { - dev->cur_reg = val; - return; + dev->cur_reg = val; + return; } else { - switch (dev->cur_reg) { - case 0x00: case 0x02: case 0x03: case 0x06: - case 0x07: case 0x21: - dev->regs[dev->cur_reg] = val; - break; - case 0x22: - dev->regs[dev->cur_reg] = val & 0x7f; - break; - default: - if (dev->cur_reg >= 0x30) { - if ((dev->regs[0x07] != 0x06) || !(dev->regs[0x21] & 0x10)) - dev->ld_regs[dev->regs[0x07]][dev->cur_reg - 0x30] = val; - } - break; - } + switch (dev->cur_reg) { + case 0x00: + case 0x02: + case 0x03: + case 0x06: + case 0x07: + case 0x21: + dev->regs[dev->cur_reg] = val; + break; + case 0x22: + dev->regs[dev->cur_reg] = val & 0x7f; + break; + default: + if (dev->cur_reg >= 0x30) { + if ((dev->regs[0x07] != 0x06) || !(dev->regs[0x21] & 0x10)) + dev->ld_regs[dev->regs[0x07]][dev->cur_reg - 0x30] = val; + } + break; + } } - switch(dev->cur_reg) { - case 0x30: - dev->ld_regs[dev->regs[0x07]][dev->cur_reg - 0x30] = val & 0x01; - switch (dev->regs[0x07]) { - case 0x00: - fdc_handler(dev); - break; - case 0x01: - lpt1_handler(dev); - break; - case 0x02: - serial_handler(dev, 1); - break; - case 0x03: - serial_handler(dev, 0); - break; - case 0x04: - pm_handler(dev); - break; - } - break; - case 0x60: case 0x62: - dev->ld_regs[dev->regs[0x07]][dev->cur_reg - 0x30] = val & 0x07; - if (dev->cur_reg == 0x62) - break; - switch (dev->regs[0x07]) { - case 0x00: - fdc_handler(dev); - break; - case 0x01: - lpt1_handler(dev); - break; - case 0x02: - serial_handler(dev, 1); - break; - case 0x03: - serial_handler(dev, 0); - break; - case 0x04: - pm_handler(dev); - break; - } - break; - case 0x63: - if (dev->regs[0x07] == 0x06) - dev->ld_regs[dev->regs[0x07]][dev->cur_reg - 0x30] = (val & 0xf8) | 0x04; - break; - case 0x61: - switch (dev->regs[0x07]) { - case 0x00: - dev->ld_regs[dev->regs[0x07]][dev->cur_reg - 0x30] = (val & 0xfa) | 0x02; - fdc_handler(dev); - break; - case 0x01: - dev->ld_regs[dev->regs[0x07]][dev->cur_reg - 0x30] = val & 0xfc; - lpt1_handler(dev); - break; - case 0x02: - dev->ld_regs[dev->regs[0x07]][dev->cur_reg - 0x30] = val & 0xf8; - serial_handler(dev, 1); - break; - case 0x03: - dev->ld_regs[dev->regs[0x07]][dev->cur_reg - 0x30] = val & 0xf8; - serial_handler(dev, 0); - break; - case 0x04: - dev->ld_regs[dev->regs[0x07]][dev->cur_reg - 0x30] = val & 0xfe; - pm_handler(dev); - break; - case 0x06: - dev->ld_regs[dev->regs[0x07]][dev->cur_reg - 0x30] = val & 0xf8; - break; - } - break; - case 0x70: - case 0x74: case 0x75: - switch (dev->regs[0x07]) { - case 0x00: - fdc_handler(dev); - break; - case 0x01: - lpt1_handler(dev); - break; - case 0x02: - serial_handler(dev, 1); - break; - case 0x03: - serial_handler(dev, 0); - break; - case 0x04: - pm_handler(dev); - break; - } - break; - case 0xf0: - switch (dev->regs[0x07]) { - case 0x00: - dev->ld_regs[dev->regs[0x07]][dev->cur_reg - 0x30] = val & 0xe1; - fdc_update_densel_polarity(dev->fdc, (val & 0x20) ? 1 : 0); - fdc_update_enh_mode(dev->fdc, (val & 0x40) ? 1 : 0); - break; - case 0x01: - dev->ld_regs[dev->regs[0x07]][dev->cur_reg - 0x30] = val & 0xf3; - lpt1_handler(dev); - break; - case 0x02: case 0x03: - dev->ld_regs[dev->regs[0x07]][dev->cur_reg - 0x30] = val & 0x87; - break; - case 0x06: - dev->ld_regs[dev->regs[0x07]][dev->cur_reg - 0x30] = val & 0xc1; - break; - } - break; - case 0xf1: - if (dev->regs[0x07] == 0x00) - dev->ld_regs[dev->regs[0x07]][dev->cur_reg - 0x30] = val & 0x0f; - break; + switch (dev->cur_reg) { + case 0x30: + dev->ld_regs[dev->regs[0x07]][dev->cur_reg - 0x30] = val & 0x01; + switch (dev->regs[0x07]) { + case 0x00: + fdc_handler(dev); + break; + case 0x01: + lpt1_handler(dev); + break; + case 0x02: + serial_handler(dev, 1); + break; + case 0x03: + serial_handler(dev, 0); + break; + case 0x04: + pm_handler(dev); + break; + + default: + break; + } + break; + case 0x60: + case 0x62: + dev->ld_regs[dev->regs[0x07]][dev->cur_reg - 0x30] = val & 0x07; + if (dev->cur_reg == 0x62) + break; + switch (dev->regs[0x07]) { + case 0x00: + fdc_handler(dev); + break; + case 0x01: + lpt1_handler(dev); + break; + case 0x02: + serial_handler(dev, 1); + break; + case 0x03: + serial_handler(dev, 0); + break; + case 0x04: + pm_handler(dev); + break; + + default: + break; + } + break; + case 0x63: + if (dev->regs[0x07] == 0x06) + dev->ld_regs[dev->regs[0x07]][dev->cur_reg - 0x30] = (val & 0xf8) | 0x04; + break; + case 0x61: + switch (dev->regs[0x07]) { + case 0x00: + dev->ld_regs[dev->regs[0x07]][dev->cur_reg - 0x30] = (val & 0xfa) | 0x02; + fdc_handler(dev); + break; + case 0x01: + dev->ld_regs[dev->regs[0x07]][dev->cur_reg - 0x30] = val & 0xfc; + lpt1_handler(dev); + break; + case 0x02: + dev->ld_regs[dev->regs[0x07]][dev->cur_reg - 0x30] = val & 0xf8; + serial_handler(dev, 1); + break; + case 0x03: + dev->ld_regs[dev->regs[0x07]][dev->cur_reg - 0x30] = val & 0xf8; + serial_handler(dev, 0); + break; + case 0x04: + dev->ld_regs[dev->regs[0x07]][dev->cur_reg - 0x30] = val & 0xfe; + pm_handler(dev); + break; + case 0x06: + dev->ld_regs[dev->regs[0x07]][dev->cur_reg - 0x30] = val & 0xf8; + break; + + default: + break; + } + break; + case 0x70: + case 0x74: + case 0x75: + switch (dev->regs[0x07]) { + case 0x00: + fdc_handler(dev); + break; + case 0x01: + lpt1_handler(dev); + break; + case 0x02: + serial_handler(dev, 1); + break; + case 0x03: + serial_handler(dev, 0); + break; + case 0x04: + pm_handler(dev); + break; + + default: + break; + } + break; + case 0xf0: + switch (dev->regs[0x07]) { + case 0x00: + dev->ld_regs[dev->regs[0x07]][dev->cur_reg - 0x30] = val & 0xe1; + fdc_update_densel_polarity(dev->fdc, (val & 0x20) ? 1 : 0); + fdc_update_enh_mode(dev->fdc, (val & 0x40) ? 1 : 0); + break; + case 0x01: + dev->ld_regs[dev->regs[0x07]][dev->cur_reg - 0x30] = val & 0xf3; + lpt1_handler(dev); + break; + case 0x02: + case 0x03: + dev->ld_regs[dev->regs[0x07]][dev->cur_reg - 0x30] = val & 0x87; + break; + case 0x06: + dev->ld_regs[dev->regs[0x07]][dev->cur_reg - 0x30] = val & 0xc1; + break; + + default: + break; + } + break; + case 0xf1: + if (dev->regs[0x07] == 0x00) + dev->ld_regs[dev->regs[0x07]][dev->cur_reg - 0x30] = val & 0x0f; + break; + + default: + break; } } - uint8_t pc87309_read(uint16_t port, void *priv) { - pc87309_t *dev = (pc87309_t *) priv; - uint8_t ret = 0xff, index; + const pc87309_t *dev = (pc87309_t *) priv; + uint8_t ret = 0xff; + uint8_t index; index = (port & 1) ? 0 : 1; if (index) - ret = dev->cur_reg & 0x1f; + ret = dev->cur_reg & 0x1f; else { - if (dev->cur_reg >= 0x30) - ret = dev->ld_regs[dev->regs[0x07]][dev->cur_reg - 0x30]; - else - ret = dev->regs[dev->cur_reg]; + if (dev->cur_reg >= 0x30) + ret = dev->ld_regs[dev->regs[0x07]][dev->cur_reg - 0x30]; + else + ret = dev->regs[dev->cur_reg]; } return ret; } - void pc87309_reset(pc87309_t *dev) { - int i; - memset(dev->regs, 0x00, 0x30); - for (i = 0; i < 256; i++) - memset(dev->ld_regs[i], 0x00, 0xd0); + for (uint16_t i = 0; i < 256; i++) + memset(dev->ld_regs[i], 0x00, 0xd0); memset(dev->pm, 0x00, 0x08); dev->regs[0x20] = dev->id; @@ -426,8 +446,8 @@ pc87309_reset(pc87309_t *dev) dev->pm_base = 0xffff; /* - 0 = 360 rpm @ 500 kbps for 3.5" - 1 = Default, 300 rpm @ 500,300,250,1000 kbps for 3.5" + 0 = 360 rpm @ 500 kbps for 3.5" + 1 = Default, 300 rpm @ 500, 300, 250, 1000 kbps for 3.5" */ lpt1_remove(); serial_remove(dev->uart[0]); @@ -435,7 +455,6 @@ pc87309_reset(pc87309_t *dev) fdc_reset(dev->fdc); } - static void pc87309_close(void *priv) { @@ -444,7 +463,6 @@ pc87309_close(void *priv) free(dev); } - static void * pc87309_init(const device_t *info) { @@ -461,34 +479,40 @@ pc87309_init(const device_t *info) pc87309_reset(dev); if (info->local & 0x100) { - io_sethandler(0x15c, 0x0002, - pc87309_read, NULL, NULL, pc87309_write, NULL, NULL, dev); + io_sethandler(0x15c, 0x0002, + pc87309_read, NULL, NULL, pc87309_write, NULL, NULL, dev); } else { - io_sethandler(0x02e, 0x0002, - pc87309_read, NULL, NULL, pc87309_write, NULL, NULL, dev); + io_sethandler(0x02e, 0x0002, + pc87309_read, NULL, NULL, pc87309_write, NULL, NULL, dev); } return dev; } - const device_t pc87309_device = { - "National Semiconductor PC87309 Super I/O", - "pc87309", - 0, - 0xe0, - pc87309_init, pc87309_close, NULL, - { NULL }, NULL, NULL, - NULL + .name = "National Semiconductor PC87309 Super I/O", + .internal_name = "pc87309", + .flags = 0, + .local = 0xe0, + .init = pc87309_init, + .close = pc87309_close, + .reset = NULL, + { .available = NULL }, + .speed_changed = NULL, + .force_redraw = NULL, + .config = NULL }; - const device_t pc87309_15c_device = { - "National Semiconductor PC87309 Super I/O (Port 15Ch)", - "pc87309_15c", - 0, - 0x1e0, - pc87309_init, pc87309_close, NULL, - { NULL }, NULL, NULL, - NULL + .name = "National Semiconductor PC87309 Super I/O (Port 15Ch)", + .internal_name = "pc87309_15c", + .flags = 0, + .local = 0x1e0, + .init = pc87309_init, + .close = pc87309_close, + .reset = NULL, + { .available = NULL }, + .speed_changed = NULL, + .force_redraw = NULL, + .config = NULL }; diff --git a/src/sio/sio_pc87310.c b/src/sio/sio_pc87310.c index 424a9524b..d567bd4d5 100644 --- a/src/sio/sio_pc87310.c +++ b/src/sio/sio_pc87310.c @@ -1,22 +1,22 @@ /* - * 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. + * 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. + * This file is part of the 86Box distribution. * - * Emulation of the NatSemi PC87310 Super I/O chip. + * Emulation of the NatSemi PC87310 Super I/O chip. * * * - * Author: Miran Grca, - * Tiseno100 - * EngiNerd - * - * Copyright 2020 Miran Grca. - * Copyright 2020 Tiseno100 - * Copyright 2021 EngiNerd. + * Authors: Miran Grca, + * Tiseno100 + * EngiNerd + * + * Copyright 2020 Miran Grca. + * Copyright 2020 Tiseno100 + * Copyright 2021 EngiNerd. */ #include #include @@ -40,41 +40,42 @@ #include <86box/fdd.h> #include <86box/fdc.h> #include <86box/sio.h> +#include <86box/plat_unused.h> #define HAS_IDE_FUNCTIONALITY dev->ide_function #ifdef ENABLE_PC87310_LOG int pc87310_do_log = ENABLE_PC87310_LOG; + static void pc87310_log(const char *fmt, ...) { va_list ap; - if (pc87310_do_log) - { + if (pc87310_do_log) { va_start(ap, fmt); pclog_ex(fmt, ap); va_end(ap); } } #else -#define pc87310_log(fmt, ...) +# define pc87310_log(fmt, ...) #endif -typedef struct { - uint8_t tries, ide_function, - reg; - fdc_t *fdc; +typedef struct pc87310_t { + uint8_t tries; + uint8_t ide_function; + uint8_t reg; + fdc_t *fdc; serial_t *uart[2]; } pc87310_t; - static void lpt1_handler(pc87310_t *dev) { - int temp; - uint16_t lpt_port = 0x378; - uint8_t lpt_irq = 7; + int temp; + uint16_t lpt_port = LPT1_ADDR; + uint8_t lpt_irq = LPT1_IRQ; /* bits 0-1: * 00 378h @@ -85,28 +86,30 @@ lpt1_handler(pc87310_t *dev) temp = dev->reg & 3; switch (temp) { - case 0: - lpt_port = 0x378; - break; - case 1: - lpt_port = 0x3bc; - break; - case 2: - lpt_port = 0x278; - break; - case 3: - lpt_port = 0x000; - lpt_irq = 0xff; - break; + case 0: + lpt_port = LPT1_ADDR; + break; + case 1: + lpt_port = LPT_MDA_ADDR; + break; + case 2: + lpt_port = LPT2_ADDR; + break; + case 3: + lpt_port = 0x000; + lpt_irq = 0xff; + break; + + default: + break; } if (lpt_port) - lpt1_init(lpt_port); + lpt1_init(lpt_port); lpt1_irq(lpt_irq); } - static void serial_handler(pc87310_t *dev, int uart) { @@ -117,37 +120,36 @@ serial_handler(pc87310_t *dev, int uart) */ temp = (dev->reg >> (2 + uart)) & 1; - //current serial port is enabled - if (!temp){ - //configure serial port as COM2 + // current serial port is enabled + if (!temp) { + // configure serial port as COM2 if (((dev->reg >> 4) & 1) ^ uart) - serial_setup(dev->uart[uart], 0x2f8, 3); + serial_setup(dev->uart[uart], COM2_ADDR, COM2_IRQ); // configure serial port as COM1 else - serial_setup(dev->uart[uart], 0x3f8, 4); + serial_setup(dev->uart[uart], COM1_ADDR, COM1_IRQ); } } - static void -pc87310_write(uint16_t port, uint8_t val, void *priv) +pc87310_write(UNUSED(uint16_t port), uint8_t val, void *priv) { pc87310_t *dev = (pc87310_t *) priv; - uint8_t valxor; + uint8_t valxor; // second write to config register - if (dev->tries) { - valxor = val ^ dev->reg; - dev->tries = 0; - dev->reg = val; - // first write to config register + if (dev->tries) { + valxor = val ^ dev->reg; + dev->tries = 0; + dev->reg = val; + // first write to config register } else { - dev->tries++; - return; - } + dev->tries++; + return; + } pc87310_log("SIO: written %01X\n", val); - + /* reconfigure parallel port */ if (valxor & 0x03) { lpt1_remove(); @@ -185,37 +187,35 @@ pc87310_write(uint16_t port, uint8_t val, void *priv) /* bit 6: 1 disable fdc */ if (!(val & 0x40)) { pc87310_log("SIO: FDC enabled\n"); - fdc_set_base(dev->fdc, 0x3f0); + fdc_set_base(dev->fdc, FDC_PRIMARY_ADDR); } } return; } - uint8_t -pc87310_read(uint16_t port, void *priv) +pc87310_read(UNUSED(uint16_t port), void *priv) { pc87310_t *dev = (pc87310_t *) priv; - uint8_t ret = 0xff; + uint8_t ret = 0xff; dev->tries = 0; ret = dev->reg; pc87310_log("SIO: read %01X\n", ret); - + return ret; } - void pc87310_reset(pc87310_t *dev) { - dev->reg = 0x0; + dev->reg = 0x0; dev->tries = 0; /* - 0 = 360 rpm @ 500 kbps for 3.5" - 1 = Default, 300 rpm @ 500,300,250,1000 kbps for 3.5" + 0 = 360 rpm @ 500 kbps for 3.5" + 1 = Default, 300 rpm @ 500, 300, 250, 1000 kbps for 3.5" */ lpt1_remove(); lpt1_handler(dev); @@ -224,10 +224,11 @@ pc87310_reset(pc87310_t *dev) serial_handler(dev, 0); serial_handler(dev, 1); fdc_reset(dev->fdc); - //ide_pri_enable(); +#if 0 + ide_pri_enable(); +#endif } - static void pc87310_close(void *priv) { @@ -236,7 +237,6 @@ pc87310_close(void *priv) free(dev); } - static void * pc87310_init(const device_t *info) { @@ -247,7 +247,7 @@ pc87310_init(const device_t *info) HAS_IDE_FUNCTIONALITY = info->local; dev->fdc = device_add(&fdc_at_nsc_device); - + dev->uart[0] = device_add_inst(&ns16550_device, 1); dev->uart[1] = device_add_inst(&ns16550_device, 2); @@ -257,29 +257,35 @@ pc87310_init(const device_t *info) pc87310_reset(dev); io_sethandler(0x3f3, 0x0001, - pc87310_read, NULL, NULL, pc87310_write, NULL, NULL, dev); - + pc87310_read, NULL, NULL, pc87310_write, NULL, NULL, dev); return dev; } - const device_t pc87310_device = { - "National Semiconductor PC87310 Super I/O", - "pc87310", - 0, - 0, - pc87310_init, pc87310_close, NULL, - { NULL }, NULL, NULL, - NULL + .name = "National Semiconductor PC87310 Super I/O", + .internal_name = "pc87310", + .flags = 0, + .local = 0, + .init = pc87310_init, + .close = pc87310_close, + .reset = NULL, + { .available = NULL }, + .speed_changed = NULL, + .force_redraw = NULL, + .config = NULL }; const device_t pc87310_ide_device = { - "National Semiconductor PC87310 Super I/O with IDE functionality", - "pc87310_ide", - 0, - 1, - pc87310_init, pc87310_close, NULL, - { NULL }, NULL, NULL, - NULL -}; \ No newline at end of file + .name = "National Semiconductor PC87310 Super I/O with IDE functionality", + .internal_name = "pc87310_ide", + .flags = 0, + .local = 1, + .init = pc87310_init, + .close = pc87310_close, + .reset = NULL, + { .available = NULL }, + .speed_changed = NULL, + .force_redraw = NULL, + .config = NULL +}; diff --git a/src/sio/sio_pc87311.c b/src/sio/sio_pc87311.c index 6406c766d..9740753d1 100644 --- a/src/sio/sio_pc87311.c +++ b/src/sio/sio_pc87311.c @@ -1,15 +1,18 @@ /* - * 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. + * 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. + * This file is part of the 86Box distribution. * - * Emulation of the National Semiconductor PC87311 Super I/O + * Emulation of the National Semiconductor PC87311 Super I/O * - * Authors: Tiseno100 - * Copyright 2020 Tiseno100 + * + * + * Authors: Tiseno100 + * + * Copyright 2020 Tiseno100 */ #include #include @@ -29,43 +32,47 @@ #include <86box/fdd.h> #include <86box/fdc.h> #include <86box/sio.h> +#include <86box/plat_unused.h> #define HAS_IDE_FUNCTIONALITY dev->ide_function /* Basic Functionalities */ -#define FUNCTION_ENABLE dev->regs[0x00] +#define FUNCTION_ENABLE dev->regs[0x00] #define FUNCTION_ADDRESS dev->regs[0x01] -#define POWER_TEST dev->regs[0x02] +#define POWER_TEST dev->regs[0x02] /* Base Addresses */ -#define LPT_BA (FUNCTION_ADDRESS & 0x03) +#define LPT_BA (FUNCTION_ADDRESS & 0x03) #define UART1_BA ((FUNCTION_ADDRESS >> 2) & 0x03) #define UART2_BA ((FUNCTION_ADDRESS >> 4) & 0x03) -#define COM_BA ((FUNCTION_ADDRESS >> 6) & 0x03) +#define COM_BA ((FUNCTION_ADDRESS >> 6) & 0x03) #ifdef ENABLE_PC87311_LOG int pc87311_do_log = ENABLE_PC87311_LOG; + static void pc87311_log(const char *fmt, ...) { va_list ap; - if (pc87311_do_log) - { + if (pc87311_do_log) { va_start(ap, fmt); pclog_ex(fmt, ap); va_end(ap); } } #else -#define pc87311_log(fmt, ...) +# define pc87311_log(fmt, ...) #endif -typedef struct -{ - uint8_t index, regs[256], cfg_lock, ide_function; - uint16_t base, irq; - fdc_t *fdc_controller; +typedef struct pc87311_t { + uint8_t index; + uint8_t regs[256]; + uint8_t cfg_lock; + uint8_t ide_function; + uint16_t base; + uint16_t irq; + fdc_t *fdc_controller; serial_t *uart[2]; } pc87311_t; @@ -79,135 +86,147 @@ void pc87311_enable(pc87311_t *dev); static void pc87311_write(uint16_t addr, uint8_t val, void *priv) { - pc87311_t *dev = (pc87311_t *)priv; + pc87311_t *dev = (pc87311_t *) priv; - switch (addr) - { - case 0x398: - case 0x26e: - dev->index = val; - break; + switch (addr) { + case 0x398: + case 0x26e: + dev->index = val; + break; - case 0x399: - case 0x26f: - switch (dev->index) - { - case 0x00: - FUNCTION_ENABLE = val; + case 0x399: + case 0x26f: + switch (dev->index) { + case 0x00: + FUNCTION_ENABLE = val; + break; + case 0x01: + FUNCTION_ADDRESS = val; + break; + case 0x02: + POWER_TEST = val; + break; + + default: + break; + } break; - case 0x01: - FUNCTION_ADDRESS = val; + + default: break; - case 0x02: - POWER_TEST = val; - break; - } - break; } pc87311_enable(dev); } static uint8_t -pc87311_read(uint16_t addr, void *priv) +pc87311_read(UNUSED(uint16_t addr), void *priv) { - pc87311_t *dev = (pc87311_t *)priv; + const pc87311_t *dev = (pc87311_t *) priv; return dev->regs[dev->index]; } -void pc87311_fdc_handler(pc87311_t *dev) +void +pc87311_fdc_handler(pc87311_t *dev) { fdc_remove(dev->fdc_controller); - fdc_set_base(dev->fdc_controller, (FUNCTION_ENABLE & 0x20) ? 0x0370 : 0x03f0); - pc87311_log("PC87311-FDC: BASE %04x\n", (FUNCTION_ENABLE & 0x20) ? 0x0370 : 0x03f0); + fdc_set_base(dev->fdc_controller, (FUNCTION_ENABLE & 0x20) ? FDC_SECONDARY_ADDR : FDC_PRIMARY_ADDR); + pc87311_log("PC87311-FDC: BASE %04x\n", (FUNCTION_ENABLE & 0x20) ? FDC_SECONDARY_ADDR : FDC_PRIMARY_ADDR); } -uint16_t com3(pc87311_t *dev) +uint16_t +com3(pc87311_t *dev) { - switch (COM_BA) - { - case 0: - return 0x03e8; - case 1: - return 0x0338; - case 2: - return 0x02e8; - case 3: - return 0x0220; - default: - return 0x03e8; + switch (COM_BA) { + case 0: + return COM3_ADDR; + case 1: + return 0x0338; + case 2: + return COM4_ADDR; + case 3: + return 0x0220; + default: + return COM3_ADDR; } } -uint16_t com4(pc87311_t *dev) +uint16_t +com4(pc87311_t *dev) { - switch (COM_BA) - { - case 0: - return 0x02e8; - case 1: - return 0x0238; - case 2: - return 0x02e0; - case 3: - return 0x0228; - default: - return 0x02e8; + switch (COM_BA) { + case 0: + return COM4_ADDR; + case 1: + return 0x0238; + case 2: + return 0x02e0; + case 3: + return 0x0228; + default: + return COM4_ADDR; } } -void pc87311_uart_handler(uint8_t num, pc87311_t *dev) +void +pc87311_uart_handler(uint8_t num, pc87311_t *dev) { serial_remove(dev->uart[num & 1]); - switch (!(num & 1) ? UART1_BA : UART2_BA) - { - case 0: - dev->base = 0x03f8; - dev->irq = 4; - break; - case 1: - dev->base = 0x02f8; - dev->irq = 3; - break; - case 2: - dev->base = com3(dev); - dev->irq = 4; - break; - case 3: - dev->base = com4(dev); - dev->irq = 3; - break; + switch (!(num & 1) ? UART1_BA : UART2_BA) { + case 0: + dev->base = COM1_ADDR; + dev->irq = COM1_IRQ; + break; + case 1: + dev->base = COM2_ADDR; + dev->irq = COM2_IRQ; + break; + case 2: + dev->base = com3(dev); + dev->irq = COM3_IRQ; + break; + case 3: + dev->base = com4(dev); + dev->irq = COM4_IRQ; + break; + + default: + break; } serial_setup(dev->uart[num & 1], dev->base, dev->irq); pc87311_log("PC87311-UART%01x: BASE %04x IRQ %01x\n", num & 1, dev->base, dev->irq); } -void pc87311_lpt_handler(pc87311_t *dev) +void +pc87311_lpt_handler(pc87311_t *dev) { lpt1_remove(); - switch (LPT_BA) - { - case 0: - dev->base = 0x0378; - dev->irq = (POWER_TEST & 0x08) ? 7 : 5; - break; - case 1: - dev->base = 0x03bc; - dev->irq = 7; - break; - case 2: - dev->base = 0x0278; - dev->irq = 5; - break; + switch (LPT_BA) { + case 0: + dev->base = LPT1_ADDR; + dev->irq = (POWER_TEST & 0x08) ? LPT1_IRQ : LPT2_IRQ; + break; + case 1: + dev->base = LPT_MDA_ADDR; + dev->irq = LPT_MDA_IRQ; + break; + case 2: + dev->base = LPT2_ADDR; + dev->irq = LPT2_IRQ; + break; + + default: + break; } lpt1_init(dev->base); lpt1_irq(dev->irq); pc87311_log("PC87311-LPT: BASE %04x IRQ %01x\n", dev->base, dev->irq); } -void pc87311_ide_handler(pc87311_t *dev) +void +pc87311_ide_handler(pc87311_t *dev) { ide_pri_disable(); ide_sec_disable(); @@ -216,8 +235,7 @@ void pc87311_ide_handler(pc87311_t *dev) ide_set_side(0, 0x3f6); ide_pri_enable(); - if (FUNCTION_ENABLE & 0x80) - { + if (FUNCTION_ENABLE & 0x80) { ide_set_base(1, 0x170); ide_set_side(1, 0x376); ide_sec_enable(); @@ -225,7 +243,8 @@ void pc87311_ide_handler(pc87311_t *dev) pc87311_log("PC87311-IDE: PRI %01x SEC %01x\n", (FUNCTION_ENABLE >> 6) & 1, (FUNCTION_ENABLE >> 7) & 1); } -void pc87311_enable(pc87311_t *dev) +void +pc87311_enable(pc87311_t *dev) { (FUNCTION_ENABLE & 0x01) ? pc87311_lpt_handler(dev) : lpt1_remove(); (FUNCTION_ENABLE & 0x02) ? pc87311_uart_handler(0, dev) : serial_remove(dev->uart[0]); @@ -233,8 +252,7 @@ void pc87311_enable(pc87311_t *dev) (FUNCTION_ENABLE & 0x08) ? pc87311_fdc_handler(dev) : fdc_remove(dev->fdc_controller); if (FUNCTION_ENABLE & 0x20) pc87311_fdc_handler(dev); - if (HAS_IDE_FUNCTIONALITY) - { + if (HAS_IDE_FUNCTIONALITY) { (FUNCTION_ENABLE & 0x40) ? pc87311_ide_handler(dev) : ide_pri_disable(); (FUNCTION_ADDRESS & 0x80) ? pc87311_ide_handler(dev) : ide_sec_disable(); } @@ -243,7 +261,7 @@ void pc87311_enable(pc87311_t *dev) static void pc87311_close(void *priv) { - pc87311_t *dev = (pc87311_t *)priv; + pc87311_t *dev = (pc87311_t *) priv; free(dev); } @@ -251,15 +269,15 @@ pc87311_close(void *priv) static void * pc87311_init(const device_t *info) { - pc87311_t *dev = (pc87311_t *)malloc(sizeof(pc87311_t)); + pc87311_t *dev = (pc87311_t *) malloc(sizeof(pc87311_t)); memset(dev, 0, sizeof(pc87311_t)); /* Avoid conflicting with machines that make no use of the PC87311 Internal IDE */ HAS_IDE_FUNCTIONALITY = info->local; dev->fdc_controller = device_add(&fdc_at_nsc_device); - dev->uart[0] = device_add_inst(&ns16450_device, 1); - dev->uart[1] = device_add_inst(&ns16450_device, 2); + dev->uart[0] = device_add_inst(&ns16450_device, 1); + dev->uart[1] = device_add_inst(&ns16450_device, 2); if (HAS_IDE_FUNCTIONALITY) device_add(&ide_isa_2ch_device); @@ -273,27 +291,29 @@ pc87311_init(const device_t *info) } const device_t pc87311_device = { - "National Semiconductor PC87311", - "pc87311", - 0, - 0, - pc87311_init, - pc87311_close, - NULL, - {NULL}, - NULL, - NULL, - NULL}; + .name = "National Semiconductor PC87311", + .internal_name = "pc87311", + .flags = 0, + .local = 0, + .init = pc87311_init, + .close = pc87311_close, + .reset = NULL, + { .available = NULL }, + .speed_changed = NULL, + .force_redraw = NULL, + .config = NULL +}; const device_t pc87311_ide_device = { - "National Semiconductor PC87311 with IDE functionality", - "pc87311_ide", - 0, - 1, - pc87311_init, - pc87311_close, - NULL, - {NULL}, - NULL, - NULL, - NULL}; + .name = "National Semiconductor PC87311 with IDE functionality", + .internal_name = "pc87311_ide", + .flags = 0, + .local = 1, + .init = pc87311_init, + .close = pc87311_close, + .reset = NULL, + { .available = NULL }, + .speed_changed = NULL, + .force_redraw = NULL, + .config = NULL +}; diff --git a/src/sio/sio_pc87332.c b/src/sio/sio_pc87332.c index ea185abce..5cbf9f694 100644 --- a/src/sio/sio_pc87332.c +++ b/src/sio/sio_pc87332.c @@ -1,17 +1,18 @@ /* - * 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. + * 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. + * This file is part of the 86Box distribution. * - * Emulation of the NatSemi PC87332 Super I/O chip. + * Emulation of the NatSemi PC87332 Super I/O chip. * * * - * Author: Miran Grca, - * Copyright 2020 Miran Grca. + * Authors: Miran Grca, + * + * Copyright 2020 Miran Grca. */ #include #include @@ -34,51 +35,53 @@ #include <86box/fdc.h> #include <86box/sio.h> - -typedef struct { - uint8_t tries, has_ide, - fdc_on, regs[15]; - int cur_reg; - fdc_t *fdc; +typedef struct pc87332_t { + uint8_t tries; + uint8_t has_ide; + uint8_t fdc_on; + uint8_t regs[15]; + int cur_reg; + fdc_t *fdc; serial_t *uart[2]; } pc87332_t; - static void lpt1_handler(pc87332_t *dev) { - int temp; - uint16_t lpt_port = 0x378; - uint8_t lpt_irq = 5; + int temp; + uint16_t lpt_port = LPT1_ADDR; + uint8_t lpt_irq = LPT2_IRQ; temp = dev->regs[0x01] & 3; switch (temp) { - case 0: - lpt_port = 0x378; - lpt_irq = (dev->regs[0x02] & 0x08) ? 7 : 5; - break; - case 1: - lpt_port = 0x3bc; - lpt_irq = 7; - break; - case 2: - lpt_port = 0x278; - lpt_irq = 5; - break; - case 3: - lpt_port = 0x000; - lpt_irq = 0xff; - break; + case 0: + lpt_port = LPT1_ADDR; + lpt_irq = (dev->regs[0x02] & 0x08) ? LPT1_IRQ : LPT2_IRQ; + break; + case 1: + lpt_port = LPT_MDA_ADDR; + lpt_irq = LPT_MDA_IRQ; + break; + case 2: + lpt_port = LPT2_ADDR; + lpt_irq = LPT2_IRQ; + break; + case 3: + lpt_port = 0x000; + lpt_irq = 0xff; + break; + + default: + break; } if (lpt_port) - lpt1_init(lpt_port); + lpt1_init(lpt_port); lpt1_irq(lpt_irq); } - static void serial_handler(pc87332_t *dev, int uart) { @@ -87,187 +90,197 @@ serial_handler(pc87332_t *dev, int uart) temp = (dev->regs[1] >> (2 << uart)) & 3; switch (temp) { - case 0: - serial_setup(dev->uart[uart], SERIAL1_ADDR, 4); - break; - case 1: - serial_setup(dev->uart[uart], SERIAL2_ADDR, 3); - break; - case 2: - switch ((dev->regs[1] >> 6) & 3) { - case 0: - serial_setup(dev->uart[uart], 0x3e8, 4); - break; - case 1: - serial_setup(dev->uart[uart], 0x338, 4); - break; - case 2: - serial_setup(dev->uart[uart], 0x2e8, 4); - break; - case 3: - serial_setup(dev->uart[uart], 0x220, 4); - break; - } - break; - case 3: - switch ((dev->regs[1] >> 6) & 3) { - case 0: - serial_setup(dev->uart[uart], 0x2e8, 3); - break; - case 1: - serial_setup(dev->uart[uart], 0x238, 3); - break; - case 2: - serial_setup(dev->uart[uart], 0x2e0, 3); - break; - case 3: - serial_setup(dev->uart[uart], 0x228, 3); - break; - } - break; + case 0: + serial_setup(dev->uart[uart], COM1_ADDR, 4); + break; + case 1: + serial_setup(dev->uart[uart], COM2_ADDR, 3); + break; + case 2: + switch ((dev->regs[1] >> 6) & 3) { + case 0: + serial_setup(dev->uart[uart], COM3_ADDR, COM3_IRQ); + break; + case 1: + serial_setup(dev->uart[uart], 0x338, COM3_IRQ); + break; + case 2: + serial_setup(dev->uart[uart], COM4_ADDR, COM3_IRQ); + break; + case 3: + serial_setup(dev->uart[uart], 0x220, COM3_IRQ); + break; + + default: + break; + } + break; + case 3: + switch ((dev->regs[1] >> 6) & 3) { + case 0: + serial_setup(dev->uart[uart], COM4_ADDR, COM4_IRQ); + break; + case 1: + serial_setup(dev->uart[uart], 0x238, COM4_IRQ); + break; + case 2: + serial_setup(dev->uart[uart], 0x2e0, COM4_IRQ); + break; + case 3: + serial_setup(dev->uart[uart], 0x228, COM4_IRQ); + break; + + default: + break; + } + break; + + default: + break; } } - static void ide_handler(pc87332_t *dev) { /* TODO: Make an ide_disable(channel) and ide_enable(channel) so we can simplify this. */ if (dev->has_ide == 2) { - ide_sec_disable(); - ide_set_base(1, (dev->regs[0x00] & 0x80) ? 0x170 : 0x1f0); - ide_set_side(1, (dev->regs[0x00] & 0x80) ? 0x376 : 0x3f6); - if (dev->regs[0x00] & 0x40) - ide_sec_enable(); + ide_sec_disable(); + ide_set_base(1, (dev->regs[0x00] & 0x80) ? 0x170 : 0x1f0); + ide_set_side(1, (dev->regs[0x00] & 0x80) ? 0x376 : 0x3f6); + if (dev->regs[0x00] & 0x40) + ide_sec_enable(); } else if (dev->has_ide == 1) { - ide_pri_disable(); - ide_set_base(0, (dev->regs[0x00] & 0x80) ? 0x170 : 0x1f0); - ide_set_side(0, (dev->regs[0x00] & 0x80) ? 0x376 : 0x3f6); - if (dev->regs[0x00] & 0x40) - ide_pri_enable(); + ide_pri_disable(); + ide_set_base(0, (dev->regs[0x00] & 0x80) ? 0x170 : 0x1f0); + ide_set_side(0, (dev->regs[0x00] & 0x80) ? 0x376 : 0x3f6); + if (dev->regs[0x00] & 0x40) + ide_pri_enable(); } } - static void pc87332_write(uint16_t port, uint8_t val, void *priv) { pc87332_t *dev = (pc87332_t *) priv; - uint8_t index, valxor; + uint8_t index; + uint8_t valxor; index = (port & 1) ? 0 : 1; if (index) { - dev->cur_reg = val & 0x1f; - dev->tries = 0; - return; + dev->cur_reg = val & 0x1f; + dev->tries = 0; + return; } else { - if (dev->tries) { - valxor = val ^ dev->regs[dev->cur_reg]; - dev->tries = 0; - if ((dev->cur_reg <= 14) && (dev->cur_reg != 8)) - dev->regs[dev->cur_reg] = val; - else - return; - } else { - dev->tries++; - return; - } + if (dev->tries) { + valxor = val ^ dev->regs[dev->cur_reg]; + dev->tries = 0; + if ((dev->cur_reg <= 14) && (dev->cur_reg != 8)) + dev->regs[dev->cur_reg] = val; + else + return; + } else { + dev->tries++; + return; + } } - switch(dev->cur_reg) { - case 0: - if (valxor & 1) { - lpt1_remove(); - if ((val & 1) && !(dev->regs[2] & 1)) - lpt1_handler(dev); - } - if (valxor & 2) { - serial_remove(dev->uart[0]); - if ((val & 2) && !(dev->regs[2] & 1)) - serial_handler(dev, 0); - } - if (valxor & 4) { - serial_remove(dev->uart[1]); - if ((val & 4) && !(dev->regs[2] & 1)) - serial_handler(dev, 1); - } - if (valxor & 0x28) { - fdc_remove(dev->fdc); - if ((val & 8) && !(dev->regs[2] & 1)) - fdc_set_base(dev->fdc, (val & 0x20) ? 0x370 : 0x3f0); - } - if (dev->has_ide && (valxor & 0xc0)) - ide_handler(dev); - break; - case 1: - if (valxor & 3) { - lpt1_remove(); - if ((dev->regs[0] & 1) && !(dev->regs[2] & 1)) - lpt1_handler(dev); - } - if (valxor & 0xcc) { - serial_remove(dev->uart[0]); - if ((dev->regs[0] & 2) && !(dev->regs[2] & 1)) - serial_handler(dev, 0); - } - if (valxor & 0xf0) { - serial_remove(dev->uart[1]); - if ((dev->regs[0] & 4) && !(dev->regs[2] & 1)) - serial_handler(dev, 1); - } - break; - case 2: - if (valxor & 1) { - lpt1_remove(); - serial_remove(dev->uart[0]); - serial_remove(dev->uart[1]); - fdc_remove(dev->fdc); + switch (dev->cur_reg) { + case 0: + if (valxor & 1) { + lpt1_remove(); + if ((val & 1) && !(dev->regs[2] & 1)) + lpt1_handler(dev); + } + if (valxor & 2) { + serial_remove(dev->uart[0]); + if ((val & 2) && !(dev->regs[2] & 1)) + serial_handler(dev, 0); + } + if (valxor & 4) { + serial_remove(dev->uart[1]); + if ((val & 4) && !(dev->regs[2] & 1)) + serial_handler(dev, 1); + } + if (valxor & 0x28) { + fdc_remove(dev->fdc); + if ((val & 8) && !(dev->regs[2] & 1)) + fdc_set_base(dev->fdc, (val & 0x20) ? FDC_SECONDARY_ADDR : FDC_PRIMARY_ADDR); + } + if (dev->has_ide && (valxor & 0xc0)) + ide_handler(dev); + break; + case 1: + if (valxor & 3) { + lpt1_remove(); + if ((dev->regs[0] & 1) && !(dev->regs[2] & 1)) + lpt1_handler(dev); + } + if (valxor & 0xcc) { + serial_remove(dev->uart[0]); + if ((dev->regs[0] & 2) && !(dev->regs[2] & 1)) + serial_handler(dev, 0); + } + if (valxor & 0xf0) { + serial_remove(dev->uart[1]); + if ((dev->regs[0] & 4) && !(dev->regs[2] & 1)) + serial_handler(dev, 1); + } + break; + case 2: + if (valxor & 1) { + lpt1_remove(); + serial_remove(dev->uart[0]); + serial_remove(dev->uart[1]); + fdc_remove(dev->fdc); - if (!(val & 1)) { - if (dev->regs[0] & 1) - lpt1_handler(dev); - if (dev->regs[0] & 2) - serial_handler(dev, 0); - if (dev->regs[0] & 4) - serial_handler(dev, 1); - if (dev->regs[0] & 8) - fdc_set_base(dev->fdc, (dev->regs[0] & 0x20) ? 0x370 : 0x3f0); - } - } - if (valxor & 8) { - lpt1_remove(); - if ((dev->regs[0] & 1) && !(dev->regs[2] & 1)) - lpt1_handler(dev); - } - break; + if (!(val & 1)) { + if (dev->regs[0] & 1) + lpt1_handler(dev); + if (dev->regs[0] & 2) + serial_handler(dev, 0); + if (dev->regs[0] & 4) + serial_handler(dev, 1); + if (dev->regs[0] & 8) + fdc_set_base(dev->fdc, (dev->regs[0] & 0x20) ? FDC_SECONDARY_ADDR : FDC_PRIMARY_ADDR); + } + } + if (valxor & 8) { + lpt1_remove(); + if ((dev->regs[0] & 1) && !(dev->regs[2] & 1)) + lpt1_handler(dev); + } + break; + + default: + break; } } - uint8_t pc87332_read(uint16_t port, void *priv) { pc87332_t *dev = (pc87332_t *) priv; - uint8_t ret = 0xff, index; + uint8_t ret = 0xff; + uint8_t index; index = (port & 1) ? 0 : 1; dev->tries = 0; if (index) - ret = dev->cur_reg & 0x1f; + ret = dev->cur_reg & 0x1f; else { - if (dev->cur_reg == 8) - ret = 0x10; - else if (dev->cur_reg < 14) - ret = dev->regs[dev->cur_reg]; + if (dev->cur_reg == 8) + ret = 0x10; + else if (dev->cur_reg < 14) + ret = dev->regs[dev->cur_reg]; } return ret; } - void pc87332_reset(pc87332_t *dev) { @@ -275,15 +288,15 @@ pc87332_reset(pc87332_t *dev) dev->regs[0x00] = dev->fdc_on ? 0x4f : 0x07; if (dev->has_ide == 2) - dev->regs[0x00] |= 0x80; + dev->regs[0x00] |= 0x80; dev->regs[0x01] = 0x10; dev->regs[0x03] = 0x01; dev->regs[0x05] = 0x0D; dev->regs[0x08] = 0x70; /* - 0 = 360 rpm @ 500 kbps for 3.5" - 1 = Default, 300 rpm @ 500,300,250,1000 kbps for 3.5" + 0 = 360 rpm @ 500 kbps for 3.5" + 1 = Default, 300 rpm @ 500, 300, 250, 1000 kbps for 3.5" */ lpt1_remove(); lpt1_handler(dev); @@ -293,13 +306,12 @@ pc87332_reset(pc87332_t *dev) serial_handler(dev, 1); fdc_reset(dev->fdc); if (!dev->fdc_on) - fdc_remove(dev->fdc); + fdc_remove(dev->fdc); if (dev->has_ide) - ide_handler(dev); + ide_handler(dev); } - static void pc87332_close(void *priv) { @@ -308,7 +320,6 @@ pc87332_close(void *priv) free(dev); } - static void * pc87332_init(const device_t *info) { @@ -321,71 +332,86 @@ pc87332_init(const device_t *info) dev->uart[1] = device_add_inst(&ns16550_device, 2); dev->has_ide = (info->local >> 8) & 0xff; - dev->fdc_on = (info->local >> 16) & 0xff; + dev->fdc_on = (info->local >> 16) & 0xff; pc87332_reset(dev); - if ((info->local & 0xff) == (0x01)) { - io_sethandler(0x398, 0x0002, - pc87332_read, NULL, NULL, pc87332_write, NULL, NULL, dev); + if ((info->local & 0xff) == 0x01) { + io_sethandler(0x398, 0x0002, + pc87332_read, NULL, NULL, pc87332_write, NULL, NULL, dev); } else { - io_sethandler(0x02e, 0x0002, - pc87332_read, NULL, NULL, pc87332_write, NULL, NULL, dev); + io_sethandler(0x02e, 0x0002, + pc87332_read, NULL, NULL, pc87332_write, NULL, NULL, dev); } return dev; } - const device_t pc87332_device = { - "National Semiconductor PC87332 Super I/O", - "pc87332", - 0, - 0x00, - pc87332_init, pc87332_close, NULL, - { NULL }, NULL, NULL, - NULL + .name = "National Semiconductor PC87332 Super I/O", + .internal_name = "pc87332", + .flags = 0, + .local = 0x00, + .init = pc87332_init, + .close = pc87332_close, + .reset = NULL, + { .available = NULL }, + .speed_changed = NULL, + .force_redraw = NULL, + .config = NULL }; - const device_t pc87332_398_device = { - "National Semiconductor PC87332 Super I/O (Port 398h)", - "pc87332_398", - 0, - 0x01, - pc87332_init, pc87332_close, NULL, - { NULL }, NULL, NULL, - NULL + .name = "National Semiconductor PC87332 Super I/O (Port 398h)", + .internal_name = "pc87332_398", + .flags = 0, + .local = 0x01, + .init = pc87332_init, + .close = pc87332_close, + .reset = NULL, + { .available = NULL }, + .speed_changed = NULL, + .force_redraw = NULL, + .config = NULL }; - const device_t pc87332_398_ide_device = { - "National Semiconductor PC87332 Super I/O (Port 398h) (With IDE)", - "pc87332_398_ide", - 0, - 0x101, - pc87332_init, pc87332_close, NULL, - { NULL }, NULL, NULL, - NULL + .name = "National Semiconductor PC87332 Super I/O (Port 398h) (With IDE)", + .internal_name = "pc87332_398_ide", + .flags = 0, + .local = 0x101, + .init = pc87332_init, + .close = pc87332_close, + .reset = NULL, + { .available = NULL }, + .speed_changed = NULL, + .force_redraw = NULL, + .config = NULL }; - const device_t pc87332_398_ide_sec_device = { - "National Semiconductor PC87332 Super I/O (Port 398h) (With Secondary IDE)", - "pc87332_398_ide_sec", - 0, - 0x201, - pc87332_init, pc87332_close, NULL, - { NULL }, NULL, NULL, - NULL + .name = "National Semiconductor PC87332 Super I/O (Port 398h) (With Secondary IDE)", + .internal_name = "pc87332_398_ide_sec", + .flags = 0, + .local = 0x201, + .init = pc87332_init, + .close = pc87332_close, + .reset = NULL, + { .available = NULL }, + .speed_changed = NULL, + .force_redraw = NULL, + .config = NULL }; - const device_t pc87332_398_ide_fdcon_device = { - "National Semiconductor PC87332 Super I/O (Port 398h) (With IDE and FDC on)", - "pc87332_398_ide_fdcon", - 0, - 0x10101, - pc87332_init, pc87332_close, NULL, - { NULL }, NULL, NULL, - NULL + .name = "National Semiconductor PC87332 Super I/O (Port 398h) (With IDE and FDC on)", + .internal_name = "pc87332_398_ide_fdcon", + .flags = 0, + .local = 0x10101, + .init = pc87332_init, + .close = pc87332_close, + .reset = NULL, + { .available = NULL }, + .speed_changed = NULL, + .force_redraw = NULL, + .config = NULL }; diff --git a/src/sio/sio_prime3b.c b/src/sio/sio_prime3b.c index 9e71f3124..c93630516 100644 --- a/src/sio/sio_prime3b.c +++ b/src/sio/sio_prime3b.c @@ -1,15 +1,18 @@ /* - * 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. + * 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. + * This file is part of the 86Box distribution. * - * Emulation of the Goldstar Prime3B Super I/O + * Emulation of the Goldstar Prime3B Super I/O * - * Authors: Tiseno100 - * Copyright 2021 Tiseno100 + * + * + * Authors: Tiseno100 + * + * Copyright 2021 Tiseno100 */ #include #include @@ -29,36 +32,40 @@ #include <86box/fdd.h> #include <86box/fdc.h> #include <86box/sio.h> +#include <86box/plat_unused.h> -#define FSR dev->regs[0xa0] -#define ASR dev->regs[0xa1] -#define PDR dev->regs[0xa2] +#define FSR dev->regs[0xa0] +#define ASR dev->regs[0xa1] +#define PDR dev->regs[0xa2] #define HAS_IDE_FUNCTIONALITY dev->ide_function #ifdef ENABLE_PRIME3B_LOG int prime3b_do_log = ENABLE_PRIME3B_LOG; + static void prime3b_log(const char *fmt, ...) { va_list ap; - if (prime3b_do_log) - { + if (prime3b_do_log) { va_start(ap, fmt); pclog_ex(fmt, ap); va_end(ap); } } #else -#define prime3b_log(fmt, ...) +# define prime3b_log(fmt, ...) #endif -typedef struct -{ - uint8_t index, regs[256], cfg_lock, ide_function; - uint16_t com3_addr, com4_addr; +typedef struct prime3b_t { + uint8_t index; + uint8_t regs[256]; + uint8_t cfg_lock; + uint8_t ide_function; + uint16_t com3_addr; + uint16_t com4_addr; - fdc_t *fdc_controller; + fdc_t *fdc_controller; serial_t *uart[2]; } prime3b_t; @@ -73,10 +80,9 @@ void prime3b_powerdown(prime3b_t *dev); static void prime3b_write(uint16_t addr, uint8_t val, void *priv) { - prime3b_t *dev = (prime3b_t *)priv; + prime3b_t *dev = (prime3b_t *) priv; - if (addr == 0x398) - { + if (addr == 0x398) { dev->index = val; /* Enter/Escape Configuration Mode */ @@ -84,102 +90,110 @@ prime3b_write(uint16_t addr, uint8_t val, void *priv) dev->cfg_lock = 0; else if (val == 0xcc) dev->cfg_lock = 1; - } - else if ((addr == 0x399) && !dev->cfg_lock) - { - switch (dev->index) - { - case 0xa0: /* Function Selection Register (FSR) */ - FSR = val; - prime3b_enable(dev); - break; - case 0xa1: /* Address Selection Register (ASR) */ - ASR = val; - prime3b_enable(dev); - break; - case 0xa2: /* Power Down Register (PDR) */ - dev->regs[0xa2] = val; - break; - case 0xa3: /* Test Mode Register (TMR) */ - dev->regs[0xa3] = val; - break; - case 0xa4: /* Miscellaneous Function Register */ - dev->regs[0xa4] = val; - switch ((dev->regs[0xa4] >> 6) & 3) - { - case 0: - dev->com3_addr = 0x3e8; - dev->com4_addr = 0x2e8; + } else if ((addr == 0x399) && !dev->cfg_lock) { + switch (dev->index) { + case 0xa0: /* Function Selection Register (FSR) */ + FSR = val; + prime3b_enable(dev); break; - case 1: - dev->com3_addr = 0x338; - dev->com4_addr = 0x238; + case 0xa1: /* Address Selection Register (ASR) */ + ASR = val; + prime3b_enable(dev); break; - case 2: - dev->com3_addr = 0x2e8; - dev->com4_addr = 0x2e0; + case 0xa2: /* Power Down Register (PDR) */ + dev->regs[0xa2] = val; break; - case 3: - dev->com3_addr = 0x220; - dev->com4_addr = 0x228; + case 0xa3: /* Test Mode Register (TMR) */ + dev->regs[0xa3] = val; + break; + case 0xa4: /* Miscellaneous Function Register */ + dev->regs[0xa4] = val; + switch ((dev->regs[0xa4] >> 6) & 3) { + case 0: + dev->com3_addr = COM3_ADDR; + dev->com4_addr = COM4_ADDR; + break; + case 1: + dev->com3_addr = 0x338; + dev->com4_addr = 0x238; + break; + case 2: + dev->com3_addr = COM4_ADDR; + dev->com4_addr = 0x2e0; + break; + case 3: + dev->com3_addr = 0x220; + dev->com4_addr = 0x228; + break; + + default: + break; + } + break; + case 0xa5: /* ECP Register */ + dev->regs[0xa5] = val; + break; + + default: break; - } - break; - case 0xa5: /* ECP Register */ - dev->regs[0xa5] = val; - break; } } } static uint8_t -prime3b_read(uint16_t addr, void *priv) +prime3b_read(UNUSED(uint16_t addr), void *priv) { - prime3b_t *dev = (prime3b_t *)priv; + const prime3b_t *dev = (prime3b_t *) priv; return dev->regs[dev->index]; } -void prime3b_fdc_handler(prime3b_t *dev) +void +prime3b_fdc_handler(prime3b_t *dev) { - uint16_t fdc_base = !(ASR & 0x40) ? 0x3f0 : 0x370; + uint16_t fdc_base = !(ASR & 0x40) ? FDC_PRIMARY_ADDR : FDC_SECONDARY_ADDR; fdc_remove(dev->fdc_controller); fdc_set_base(dev->fdc_controller, fdc_base); prime3b_log("Prime3B-FDC: Enabled with base %03x\n", fdc_base); } -void prime3b_uart_handler(uint8_t num, prime3b_t *dev) +void +prime3b_uart_handler(uint8_t num, prime3b_t *dev) { uint16_t uart_base; if ((ASR >> (3 + 2 * num)) & 1) uart_base = !((ASR >> (2 + 2 * num)) & 1) ? dev->com3_addr : dev->com4_addr; else - uart_base = !((ASR >> (2 + 2 * num)) & 1) ? 0x3f8 : 0x2f8; + uart_base = !((ASR >> (2 + 2 * num)) & 1) ? COM1_ADDR : COM2_ADDR; serial_remove(dev->uart[num]); serial_setup(dev->uart[num], uart_base, 4 - num); prime3b_log("Prime3B-UART%d: Enabled with base %03x\n", num, uart_base); } -void prime3b_lpt_handler(prime3b_t *dev) +void +prime3b_lpt_handler(prime3b_t *dev) { - uint16_t lpt_base = (ASR & 2) ? 0x3bc : (!(ASR & 1) ? 0x378 : 0x278); + uint16_t lpt_base = (ASR & 2) ? LPT_MDA_ADDR : (!(ASR & 1) ? LPT1_ADDR : LPT2_ADDR); lpt1_remove(); lpt1_init(lpt_base); - lpt1_irq(7); + lpt1_irq(LPT1_IRQ); prime3b_log("Prime3B-LPT: Enabled with base %03x\n", lpt_base); } -void prime3b_ide_handler(prime3b_t *dev) +void +prime3b_ide_handler(prime3b_t *dev) { ide_pri_disable(); uint16_t ide_base = !(ASR & 0x80) ? 0x1f0 : 0x170; + uint16_t ide_side = ide_base + 0x206; ide_set_base(0, ide_base); - ide_set_side(0, ide_base + 0x206); - prime3b_log("Prime3B-IDE: Enabled with base %03x and side %03x\n", ide_base, ide_base + 0x206); + ide_set_side(0, ide_side); + prime3b_log("Prime3B-IDE: Enabled with base %03x and side %03x\n", ide_base, ide_side); } -void prime3b_enable(prime3b_t *dev) +void +prime3b_enable(prime3b_t *dev) { /* Simulate a device enable/disable scenario @@ -204,7 +218,8 @@ void prime3b_enable(prime3b_t *dev) (FSR & 0x20) ? prime3b_ide_handler(dev) : ide_pri_disable(); } -void prime3b_powerdown(prime3b_t *dev) +void +prime3b_powerdown(prime3b_t *dev) { /* Note: It can be done more efficiently for sure */ uint8_t old_base = PDR; @@ -234,7 +249,7 @@ void prime3b_powerdown(prime3b_t *dev) static void prime3b_close(void *priv) { - prime3b_t *dev = (prime3b_t *)priv; + prime3b_t *dev = (prime3b_t *) priv; free(dev); } @@ -242,7 +257,7 @@ prime3b_close(void *priv) static void * prime3b_init(const device_t *info) { - prime3b_t *dev = (prime3b_t *)malloc(sizeof(prime3b_t)); + prime3b_t *dev = (prime3b_t *) malloc(sizeof(prime3b_t)); memset(dev, 0, sizeof(prime3b_t)); /* Avoid conflicting with machines that make no use of the Prime3B Internal IDE */ @@ -251,13 +266,13 @@ prime3b_init(const device_t *info) dev->regs[0xa0] = 3; dev->fdc_controller = device_add(&fdc_at_device); - dev->uart[0] = device_add_inst(&ns16550_device, 1); - dev->uart[1] = device_add_inst(&ns16550_device, 2); + dev->uart[0] = device_add_inst(&ns16550_device, 1); + dev->uart[1] = device_add_inst(&ns16550_device, 2); if (HAS_IDE_FUNCTIONALITY) device_add(&ide_isa_device); - dev->com3_addr = 0x3e8; - dev->com4_addr = 0x2e8; + dev->com3_addr = COM3_ADDR; + dev->com4_addr = COM4_ADDR; fdc_reset(dev->fdc_controller); prime3b_enable(dev); @@ -268,27 +283,29 @@ prime3b_init(const device_t *info) } const device_t prime3b_device = { - "Goldstar Prime3B", - "prime3b", - 0, - 0, - prime3b_init, - prime3b_close, - NULL, - {NULL}, - NULL, - NULL, - NULL}; + .name = "Goldstar Prime3B", + .internal_name = "prime3b", + .flags = 0, + .local = 0, + .init = prime3b_init, + .close = prime3b_close, + .reset = NULL, + { .available = NULL }, + .speed_changed = NULL, + .force_redraw = NULL, + .config = NULL +}; const device_t prime3b_ide_device = { - "Goldstar Prime3B with IDE functionality", - "prime3b_ide", - 0, - 1, - prime3b_init, - prime3b_close, - NULL, - {NULL}, - NULL, - NULL, - NULL}; + .name = "Goldstar Prime3B with IDE functionality", + .internal_name = "prime3b_ide", + .flags = 0, + .local = 1, + .init = prime3b_init, + .close = prime3b_close, + .reset = NULL, + { .available = NULL }, + .speed_changed = NULL, + .force_redraw = NULL, + .config = NULL +}; diff --git a/src/sio/sio_prime3c.c b/src/sio/sio_prime3c.c index 1b4bde5d4..b19f861bf 100644 --- a/src/sio/sio_prime3c.c +++ b/src/sio/sio_prime3c.c @@ -1,15 +1,18 @@ /* - * 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. + * 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. + * This file is part of the 86Box distribution. * - * Emulation of the LG Prime3C Super I/O + * Emulation of the LG Prime3C Super I/O * - * Authors: Tiseno100 - * Copyright 2020 Tiseno100 + * + * + * Authors: Tiseno100 + * + * Copyright 2020 Tiseno100 */ #include #include @@ -29,33 +32,34 @@ #include <86box/fdd.h> #include <86box/fdc.h> #include <86box/sio.h> +#include <86box/plat_unused.h> #ifdef ENABLE_PRIME3C_LOG int prime3c_do_log = ENABLE_PRIME3C_LOG; + static void prime3c_log(const char *fmt, ...) { va_list ap; - if (prime3c_do_log) - { + if (prime3c_do_log) { va_start(ap, fmt); pclog_ex(fmt, ap); va_end(ap); } } #else -#define prime3c_log(fmt, ...) +# define prime3c_log(fmt, ...) #endif /* Function Select(Note on prime3c_enable) */ #define FUNCTION_SELECT dev->regs[0xc2] /* Base Address Registers */ -#define FDC_BASE_ADDRESS dev->regs[0xc3] -#define IDE_BASE_ADDRESS dev->regs[0xc4] -#define IDE_SIDE_ADDRESS dev->regs[0xc5] -#define LPT_BASE_ADDRESS dev->regs[0xc6] +#define FDC_BASE_ADDRESS dev->regs[0xc3] +#define IDE_BASE_ADDRESS dev->regs[0xc4] +#define IDE_SIDE_ADDRESS dev->regs[0xc5] +#define LPT_BASE_ADDRESS dev->regs[0xc6] #define UART1_BASE_ADDRESS dev->regs[0xc7] #define UART2_BASE_ADDRESS dev->regs[0xc8] @@ -72,11 +76,13 @@ prime3c_log(const char *fmt, ...) /* IDE functionality(Note on Init) */ #define HAS_IDE_FUNCTIONALITY dev->ide_function -typedef struct -{ - uint8_t index, regs[256], cfg_lock, ide_function; +typedef struct prime3c_t { + uint8_t index; + uint8_t regs[256]; + uint8_t cfg_lock; + uint8_t ide_function; - fdc_t *fdc_controller; + fdc_t *fdc_controller; serial_t *uart[2]; } prime3c_t; @@ -90,124 +96,127 @@ void prime3c_enable(prime3c_t *dev); static void prime3c_write(uint16_t addr, uint8_t val, void *priv) { - prime3c_t *dev = (prime3c_t *)priv; + prime3c_t *dev = (prime3c_t *) priv; - switch (addr) - { - case 0x398: - dev->index = val; + switch (addr) { + case 0x398: + dev->index = val; - /* Enter/Escape Configuration Mode */ - if (val == 0x33) - dev->cfg_lock = 0; - else if (val == 0x55) - dev->cfg_lock = 1; - break; + /* Enter/Escape Configuration Mode */ + if (val == 0x33) + dev->cfg_lock = 0; + else if (val == 0x55) + dev->cfg_lock = 1; + break; - case 0x399: - if (!dev->cfg_lock) - { - switch (dev->index) - { - case 0xc2: - FUNCTION_SELECT = val & 0xbf; - prime3c_enable(dev); - break; + case 0x399: + if (!dev->cfg_lock) { + switch (dev->index) { + case 0xc2: + FUNCTION_SELECT = val & 0xbf; + prime3c_enable(dev); + break; - case 0xc3: - FDC_BASE_ADDRESS = val & 0xfc; - prime3c_fdc_handler(dev); - break; + case 0xc3: + FDC_BASE_ADDRESS = val & 0xfc; + prime3c_fdc_handler(dev); + break; - case 0xc4: - IDE_BASE_ADDRESS = val & 0xfc; - if (HAS_IDE_FUNCTIONALITY) - prime3c_ide_handler(dev); - break; + case 0xc4: + IDE_BASE_ADDRESS = val & 0xfc; + if (HAS_IDE_FUNCTIONALITY) + prime3c_ide_handler(dev); + break; - case 0xc5: - IDE_SIDE_ADDRESS = (val & 0xfc) | 0x02; - if (HAS_IDE_FUNCTIONALITY) - prime3c_ide_handler(dev); - break; + case 0xc5: + IDE_SIDE_ADDRESS = (val & 0xfc) | 0x02; + if (HAS_IDE_FUNCTIONALITY) + prime3c_ide_handler(dev); + break; - case 0xc6: - LPT_BASE_ADDRESS = val; - break; + case 0xc6: + LPT_BASE_ADDRESS = val; + break; - case 0xc7: - UART1_BASE_ADDRESS = val & 0xfe; - prime3c_uart_handler(0, dev); - break; + case 0xc7: + UART1_BASE_ADDRESS = val & 0xfe; + prime3c_uart_handler(0, dev); + break; - case 0xc8: - UART2_BASE_ADDRESS = val & 0xfe; - prime3c_uart_handler(1, dev); - break; + case 0xc8: + UART2_BASE_ADDRESS = val & 0xfe; + prime3c_uart_handler(1, dev); + break; - case 0xc9: - FDC_LPT_DMA = val; - prime3c_fdc_handler(dev); - break; + case 0xc9: + FDC_LPT_DMA = val; + prime3c_fdc_handler(dev); + break; - case 0xca: - FDC_LPT_IRQ = val; - prime3c_fdc_handler(dev); - prime3c_lpt_handler(dev); - break; + case 0xca: + FDC_LPT_IRQ = val; + prime3c_fdc_handler(dev); + prime3c_lpt_handler(dev); + break; - case 0xcb: - UART_IRQ = val; - prime3c_uart_handler(0, dev); - prime3c_uart_handler(1, dev); - break; + case 0xcb: + UART_IRQ = val; + prime3c_uart_handler(0, dev); + prime3c_uart_handler(1, dev); + break; - case 0xcd: - case 0xce: - dev->regs[dev->index] = val; - break; + case 0xcd: + case 0xce: + dev->regs[dev->index] = val; + break; - case 0xcf: - dev->regs[dev->index] = val & 0x3f; - break; + case 0xcf: + dev->regs[dev->index] = val & 0x3f; + break; - case 0xd0: - dev->regs[dev->index] = val & 0xfc; - break; + case 0xd0: + dev->regs[dev->index] = val & 0xfc; + break; - case 0xd1: - dev->regs[dev->index] = val & 0x3f; - break; + case 0xd1: + dev->regs[dev->index] = val & 0x3f; + break; - case 0xd3: - dev->regs[dev->index] = val & 0x7c; - break; + case 0xd3: + dev->regs[dev->index] = val & 0x7c; + break; - case 0xd5: - case 0xd6: - case 0xd7: - case 0xd8: - dev->regs[dev->index] = val; - break; + case 0xd5: + case 0xd6: + case 0xd7: + case 0xd8: + dev->regs[dev->index] = val; + break; + + default: + break; + } } - } - break; + break; + + default: + break; } } static uint8_t -prime3c_read(uint16_t addr, void *priv) +prime3c_read(UNUSED(uint16_t addr), void *priv) { - prime3c_t *dev = (prime3c_t *)priv; + const prime3c_t *dev = (prime3c_t *) priv; return dev->regs[dev->index]; } -void prime3c_fdc_handler(prime3c_t *dev) +void +prime3c_fdc_handler(prime3c_t *dev) { fdc_remove(dev->fdc_controller); - if (FUNCTION_SELECT & 0x10) - { + if (FUNCTION_SELECT & 0x10) { fdc_set_base(dev->fdc_controller, FDC_BASE_ADDRESS << 2); fdc_set_irq(dev->fdc_controller, (FDC_LPT_IRQ >> 4) & 0xf); fdc_set_dma_ch(dev->fdc_controller, (FDC_LPT_DMA >> 4) & 0xf); @@ -216,21 +225,21 @@ void prime3c_fdc_handler(prime3c_t *dev) } } -void prime3c_uart_handler(uint8_t num, prime3c_t *dev) +void +prime3c_uart_handler(uint8_t num, prime3c_t *dev) { serial_remove(dev->uart[num & 1]); - if (FUNCTION_SELECT & (!(num & 1) ? 0x04 : 0x08)) - { + if (FUNCTION_SELECT & (!(num & 1) ? 0x04 : 0x08)) { serial_setup(dev->uart[num & 1], (!(num & 1) ? UART1_BASE_ADDRESS : UART2_BASE_ADDRESS) << 2, (UART_IRQ >> (!(num & 1) ? 4 : 0)) & 0xf); prime3c_log("Prime3C-UART%01x: BASE %04x IRQ %01x\n", num & 1, (!(num & 1) ? UART1_BASE_ADDRESS : UART2_BASE_ADDRESS) << 2, (UART_IRQ >> (!(num & 1) ? 4 : 0)) & 0xf); } } -void prime3c_lpt_handler(prime3c_t *dev) +void +prime3c_lpt_handler(prime3c_t *dev) { lpt1_remove(); - if (!(FUNCTION_SELECT & 0x03)) - { + if (!(FUNCTION_SELECT & 0x03)) { lpt1_init(LPT_BASE_ADDRESS << 2); lpt1_irq(FDC_LPT_IRQ & 0xf); @@ -238,11 +247,11 @@ void prime3c_lpt_handler(prime3c_t *dev) } } -void prime3c_ide_handler(prime3c_t *dev) +void +prime3c_ide_handler(prime3c_t *dev) { ide_pri_disable(); - if (FUNCTION_SELECT & 0x20) - { + if (FUNCTION_SELECT & 0x20) { ide_set_base(0, IDE_BASE_ADDRESS << 2); ide_set_side(0, IDE_SIDE_ADDRESS << 2); ide_pri_enable(); @@ -250,35 +259,36 @@ void prime3c_ide_handler(prime3c_t *dev) } } -void prime3c_enable(prime3c_t *dev) +void +prime3c_enable(prime3c_t *dev) { -/* -Simulate a device enable/disable scenario + /* + Simulate a device enable/disable scenario -Register C2: Function Select -Bit 7: Gameport -Bit 6: Reserved -Bit 5: IDE -Bit 4: FDC -Bit 3: UART 2 -Bit 2: UART 1 -Bit 1/0: PIO (0/0 Unidirectional , 0/1 ECP, 1/0 EPP, 1/1 Disabled) + Register C2: Function Select + Bit 7: Gameport + Bit 6: Reserved + Bit 5: IDE + Bit 4: FDC + Bit 3: UART 2 + Bit 2: UART 1 + Bit 1/0: PIO (0/0 Unidirectional , 0/1 ECP, 1/0 EPP, 1/1 Disabled) -Note: 86Box LPT is simplistic and can't do ECP or EPP. -*/ + Note: 86Box LPT is simplistic and can't do ECP or EPP. + */ -!(FUNCTION_SELECT & 0x03) ? prime3c_lpt_handler(dev) : lpt1_remove(); -(FUNCTION_SELECT & 0x04) ? prime3c_uart_handler(0, dev) : serial_remove(dev->uart[0]); -(FUNCTION_SELECT & 0x08) ? prime3c_uart_handler(1, dev) : serial_remove(dev->uart[1]); -(FUNCTION_SELECT & 0x10) ? prime3c_fdc_handler(dev) : fdc_remove(dev->fdc_controller); -if (HAS_IDE_FUNCTIONALITY) - (FUNCTION_SELECT & 0x20) ? prime3c_ide_handler(dev) : ide_pri_disable(); + !(FUNCTION_SELECT & 0x03) ? prime3c_lpt_handler(dev) : lpt1_remove(); + (FUNCTION_SELECT & 0x04) ? prime3c_uart_handler(0, dev) : serial_remove(dev->uart[0]); + (FUNCTION_SELECT & 0x08) ? prime3c_uart_handler(1, dev) : serial_remove(dev->uart[1]); + (FUNCTION_SELECT & 0x10) ? prime3c_fdc_handler(dev) : fdc_remove(dev->fdc_controller); + if (HAS_IDE_FUNCTIONALITY) + (FUNCTION_SELECT & 0x20) ? prime3c_ide_handler(dev) : ide_pri_disable(); } static void prime3c_close(void *priv) { - prime3c_t *dev = (prime3c_t *)priv; + prime3c_t *dev = (prime3c_t *) priv; free(dev); } @@ -286,7 +296,7 @@ prime3c_close(void *priv) static void * prime3c_init(const device_t *info) { - prime3c_t *dev = (prime3c_t *)malloc(sizeof(prime3c_t)); + prime3c_t *dev = (prime3c_t *) malloc(sizeof(prime3c_t)); memset(dev, 0, sizeof(prime3c_t)); /* Avoid conflicting with machines that make no use of the Prime3C Internal IDE */ @@ -300,8 +310,8 @@ prime3c_init(const device_t *info) dev->regs[0xd5] = 0x3c; dev->fdc_controller = device_add(&fdc_at_device); - dev->uart[0] = device_add_inst(&ns16550_device, 1); - dev->uart[1] = device_add_inst(&ns16550_device, 2); + dev->uart[0] = device_add_inst(&ns16550_device, 1); + dev->uart[1] = device_add_inst(&ns16550_device, 2); if (HAS_IDE_FUNCTIONALITY) device_add(&ide_isa_device); @@ -318,27 +328,29 @@ prime3c_init(const device_t *info) } const device_t prime3c_device = { - "Goldstar Prime3C", - "prime3c", - 0, - 0, - prime3c_init, - prime3c_close, - NULL, - {NULL}, - NULL, - NULL, - NULL}; + .name = "Goldstar Prime3C", + .internal_name = "prime3c", + .flags = 0, + .local = 0, + .init = prime3c_init, + .close = prime3c_close, + .reset = NULL, + { .available = NULL }, + .speed_changed = NULL, + .force_redraw = NULL, + .config = NULL +}; const device_t prime3c_ide_device = { - "Goldstar Prime3C with IDE functionality", - "prime3c_ide", - 0, - 1, - prime3c_init, - prime3c_close, - NULL, - {NULL}, - NULL, - NULL, - NULL}; + .name = "Goldstar Prime3C with IDE functionality", + .internal_name = "prime3c_ide", + .flags = 0, + .local = 1, + .init = prime3c_init, + .close = prime3c_close, + .reset = NULL, + { .available = NULL }, + .speed_changed = NULL, + .force_redraw = NULL, + .config = NULL +}; diff --git a/src/sio/sio_um8669f.c b/src/sio/sio_um8669f.c index aeef3a51e..2643e76f7 100644 --- a/src/sio/sio_um8669f.c +++ b/src/sio/sio_um8669f.c @@ -1,22 +1,22 @@ /* - * 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. + * 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. + * This file is part of the 86Box distribution. * - * Emulation of the UMC UM8669F Super I/O chip. + * Emulation of the UMC UM8669F Super I/O chip. * * * - * Authors: Sarah Walker, - * Miran Grca, - * RichardG, + * Authors: Sarah Walker, + * Miran Grca, + * RichardG, * - * Copyright 2008-2021 Sarah Walker. - * Copyright 2016-2021 Miran Grca. - * Copyright 2021 RichardG. + * Copyright 2008-2021 Sarah Walker. + * Copyright 2016-2021 Miran Grca. + * Copyright 2021 RichardG. */ #include #include @@ -37,163 +37,163 @@ #include <86box/gameport.h> #include <86box/sio.h> #include <86box/isapnp.h> +#include <86box/plat_unused.h> - -/* This ROM was reconstructed out of many assumptions, some of which based on the IT8671F. */ +/* Real chips don't have a PnP ROM and instead rely on the BIOS going in blind. + We create a fake ROM here (with values based on the IT8671F) to delegate + all the logical device register handling over to the ISAPnP subsystem. */ static uint8_t um8669f_pnp_rom[] = { 0x55, 0xa3, 0x86, 0x69, 0x00, 0x00, 0x00, 0x00, 0x00, /* UMC8669, dummy checksum (filled in by isapnp_add_card) */ - 0x0a, 0x10, 0x10, /* PnP version 1.0, vendor version 1.0 */ + 0x0a, 0x10, 0x10, /* PnP version 1.0, vendor version 1.0 */ - 0x15, 0x41, 0xd0, 0x07, 0x00, 0x01, /* logical device PNP0700, can participate in boot */ - 0x22, 0xfa, 0x1f, /* IRQ 1/3/4/5/6/7/8/9/10/11/12 */ - 0x2a, 0x0f, 0x0c, /* DMA 0/1/2/3, compatibility, no count by word, count by byte, is bus master, 8-bit only */ - 0x47, 0x00, 0x00, 0x01, 0xf8, 0x03, 0x08, 0x08, /* I/O 0x100-0x3F8, decodes 10-bit, 8-byte alignment, 8 addresses */ + 0x15, 0x41, 0xd0, 0x07, 0x00, 0x01, /* logical device PNP0700, can participate in boot */ + 0x22, 0xfa, 0x1f, /* IRQ 1/3/4/5/6/7/8/9/10/11/12 */ + 0x2a, 0x0f, 0x0c, /* DMA 0/1/2/3, compatibility, no count by word, count by byte, is bus master, 8-bit only */ + 0x47, 0x00, 0x00, 0x01, 0xf8, 0x03, 0x08, 0x08, /* I/O 0x100-0x3F8, decodes 10-bit, 8-byte alignment, 8 addresses */ - 0x15, 0x41, 0xd0, 0x05, 0x01, 0x01, /* logical device PNP0501, can participate in boot */ - 0x22, 0xfa, 0x1f, /* IRQ 1/3/4/5/6/7/8/9/10/11/12 */ - 0x47, 0x00, 0x00, 0x01, 0xf8, 0x03, 0x08, 0x08, /* I/O 0x100-0x3F8, decodes 10-bit, 8-byte alignment, 8 addresses */ + 0x15, 0x41, 0xd0, 0x05, 0x01, 0x01, /* logical device PNP0501, can participate in boot */ + 0x22, 0xfa, 0x1f, /* IRQ 1/3/4/5/6/7/8/9/10/11/12 */ + 0x47, 0x00, 0x00, 0x01, 0xf8, 0x03, 0x08, 0x08, /* I/O 0x100-0x3F8, decodes 10-bit, 8-byte alignment, 8 addresses */ - 0x15, 0x41, 0xd0, 0x05, 0x01, 0x01, /* logical device PNP0501, can participate in boot */ - 0x22, 0xfa, 0x1f, /* IRQ 1/3/4/5/6/7/8/9/10/11/12 */ - 0x47, 0x00, 0x00, 0x01, 0xf8, 0x03, 0x08, 0x08, /* I/O 0x100-0x3F8, decodes 10-bit, 8-byte alignment, 8 addresses */ + 0x15, 0x41, 0xd0, 0x05, 0x01, 0x01, /* logical device PNP0501, can participate in boot */ + 0x22, 0xfa, 0x1f, /* IRQ 1/3/4/5/6/7/8/9/10/11/12 */ + 0x47, 0x00, 0x00, 0x01, 0xf8, 0x03, 0x08, 0x08, /* I/O 0x100-0x3F8, decodes 10-bit, 8-byte alignment, 8 addresses */ - 0x15, 0x41, 0xd0, 0x04, 0x00, 0x01, /* logical device PNP0400, can participate in boot */ - 0x22, 0xfa, 0x1f, /* IRQ 1/3/4/5/6/7/8/9/10/11/12 */ - 0x47, 0x00, 0x00, 0x01, 0xf8, 0x03, 0x08, 0x08, /* I/O 0x100-0x3F8, decodes 10-bit, 8-byte alignment, 8 addresses */ + 0x15, 0x41, 0xd0, 0x04, 0x00, 0x01, /* logical device PNP0400, can participate in boot */ + 0x22, 0xfa, 0x1f, /* IRQ 1/3/4/5/6/7/8/9/10/11/12 */ + 0x47, 0x00, 0x00, 0x01, 0xf8, 0x03, 0x08, 0x08, /* I/O 0x100-0x3F8, decodes 10-bit, 8-byte alignment, 8 addresses */ - 0x15, 0x41, 0xd0, 0xff, 0xff, 0x00, /* logical device PNPFFFF (just a dummy to create a gap in LDNs) */ + 0x15, 0x41, 0xd0, 0xff, 0xff, 0x00, /* logical device PNPFFFF (dummy to create a gap in LDNs) */ - 0x15, 0x41, 0xd0, 0xb0, 0x2f, 0x01, /* logical device PNPB02F, can participate in boot */ - 0x47, 0x00, 0x00, 0x01, 0xf8, 0x03, 0x08, 0x08, /* I/O 0x100-0x3F8, decodes 10-bit, 8-byte alignment, 8 addresses */ + 0x15, 0x41, 0xd0, 0xb0, 0x2f, 0x01, /* logical device PNPB02F, can participate in boot */ + 0x47, 0x00, 0x00, 0x01, 0xf8, 0x03, 0x08, 0x08, /* I/O 0x100-0x3F8, decodes 10-bit, 8-byte alignment, 8 addresses */ 0x79, 0x00 /* end tag, dummy checksum (filled in by isapnp_add_card) */ }; static const isapnp_device_config_t um8669f_pnp_defaults[] = { { - .activate = 1, - .io = { { .base = 0x03f0 }, }, - .irq = { { .irq = 6 }, }, - .dma = { { .dma = 2 }, } + .activate = 1, + .io = { { .base = FDC_PRIMARY_ADDR }, }, + .irq = { { .irq = FDC_PRIMARY_IRQ }, }, + .dma = { { .dma = FDC_PRIMARY_DMA }, } }, { - .activate = 1, - .io = { { .base = 0x03f8 }, }, - .irq = { { .irq = 4 }, } + .activate = 1, + .io = { { .base = COM1_ADDR }, }, + .irq = { { .irq = COM1_IRQ }, } }, { - .activate = 1, - .io = { { .base = 0x02f8 }, }, - .irq = { { .irq = 3 }, } + .activate = 1, + .io = { { .base = COM2_ADDR }, }, + .irq = { { .irq = COM2_IRQ }, } }, { - .activate = 1, - .io = { { .base = 0x0378 }, }, - .irq = { { .irq = 7 }, } + .activate = 1, + .io = { { .base = LPT1_ADDR }, }, + .irq = { { .irq = LPT1_IRQ }, } }, { - .activate = 0 + .activate = 0 }, { - .activate = 0, - .io = { { .base = 0x200 }, } + .activate = 0, + .io = { { .base = 0x200 }, } } }; - #ifdef ENABLE_UM8669F_LOG int um8669f_do_log = ENABLE_UM8669F_LOG; - static void um8669f_log(const char *fmt, ...) { va_list ap; if (um8669f_do_log) { - va_start(ap, fmt); - pclog_ex(fmt, ap); - va_end(ap); + va_start(ap, fmt); + pclog_ex(fmt, ap); + va_end(ap); } } #else -#define um8669f_log(fmt, ...) +# define um8669f_log(fmt, ...) #endif +typedef struct um8669f_t { + uint8_t locked; + uint8_t cur_reg_108; + void *pnp_card; -typedef struct um8669f_t -{ - int locked, cur_reg_108; - void *pnp_card; - isapnp_device_config_t *pnp_config[5]; + uint8_t regs_108[256]; - uint8_t regs_108[256]; - - fdc_t *fdc; - serial_t *uart[2]; - void *gameport; + fdc_t *fdc; + serial_t *uart[2]; + void *gameport; } um8669f_t; - static void um8669f_pnp_config_changed(uint8_t ld, isapnp_device_config_t *config, void *priv) { if (ld > 5) { - um8669f_log("UM8669F: Unknown logical device %d\n", ld); - return; + um8669f_log("UM8669F: Unknown logical device %d\n", ld); + return; } um8669f_t *dev = (um8669f_t *) priv; switch (ld) { - case 0: - fdc_remove(dev->fdc); + case 0: + fdc_remove(dev->fdc); - if (config->activate) { - um8669f_log("UM8669F: FDC enabled at port %04X IRQ %d DMA %d\n", config->io[0].base, config->irq[0].irq, (config->dma[0].dma == ISAPNP_DMA_DISABLED) ? -1 : config->dma[0].dma); + if (config->activate) { + um8669f_log("UM8669F: FDC enabled at port %04X IRQ %d DMA %d\n", config->io[0].base, config->irq[0].irq, (config->dma[0].dma == ISAPNP_DMA_DISABLED) ? -1 : config->dma[0].dma); - if (config->io[0].base != ISAPNP_IO_DISABLED) - fdc_set_base(dev->fdc, config->io[0].base); + if (config->io[0].base != ISAPNP_IO_DISABLED) + fdc_set_base(dev->fdc, config->io[0].base); - fdc_set_irq(dev->fdc, config->irq[0].irq); - fdc_set_dma_ch(dev->fdc, (config->dma[0].dma == ISAPNP_DMA_DISABLED) ? -1 : config->dma[0].dma); - } else { - um8669f_log("UM8669F: FDC disabled\n"); - } + fdc_set_irq(dev->fdc, config->irq[0].irq); + fdc_set_dma_ch(dev->fdc, (config->dma[0].dma == ISAPNP_DMA_DISABLED) ? -1 : config->dma[0].dma); + } else { + um8669f_log("UM8669F: FDC disabled\n"); + } - break; + break; - case 1: - case 2: - serial_remove(dev->uart[ld - 1]); + case 1: + case 2: + serial_remove(dev->uart[ld - 1]); - if (config->activate && (config->io[0].base != ISAPNP_IO_DISABLED)) { - um8669f_log("UM8669F: UART %d enabled at port %04X IRQ %d\n", ld - 1, config->io[0].base, config->irq[0].irq); - serial_setup(dev->uart[ld - 1], config->io[0].base, config->irq[0].irq); - } else { - um8669f_log("UM8669F: UART %d disabled\n", ld - 1); - } + if (config->activate && (config->io[0].base != ISAPNP_IO_DISABLED)) { + um8669f_log("UM8669F: UART %d enabled at port %04X IRQ %d\n", ld - 1, config->io[0].base, config->irq[0].irq); + serial_setup(dev->uart[ld - 1], config->io[0].base, config->irq[0].irq); + } else { + um8669f_log("UM8669F: UART %d disabled\n", ld - 1); + } - break; + break; - case 3: - lpt1_remove(); + case 3: + lpt1_remove(); - if (config->activate && (config->io[0].base != ISAPNP_IO_DISABLED)) { - um8669f_log("UM8669F: LPT enabled at port %04X IRQ %d\n", config->io[0].base, config->irq[0].irq); - lpt1_init(config->io[0].base); - } else { - um8669f_log("UM8669F: LPT disabled\n"); - } + if (config->activate && (config->io[0].base != ISAPNP_IO_DISABLED)) { + um8669f_log("UM8669F: LPT enabled at port %04X IRQ %d\n", config->io[0].base, config->irq[0].irq); + lpt1_init(config->io[0].base); + } else { + um8669f_log("UM8669F: LPT disabled\n"); + } - break; + break; - case 5: - if (config->activate && (config->io[0].base != ISAPNP_IO_DISABLED)) { - um8669f_log("UM8669F: Game port enabled at port %04X\n", config->io[0].base); - gameport_remap(dev->gameport, config->io[0].base); - } else { - um8669f_log("UM8669F: Game port disabled\n"); - gameport_remap(dev->gameport, 0); - } + case 5: + if (config->activate && (config->io[0].base != ISAPNP_IO_DISABLED)) { + um8669f_log("UM8669F: Game port enabled at port %04X\n", config->io[0].base); + gameport_remap(dev->gameport, config->io[0].base); + } else { + um8669f_log("UM8669F: Game port disabled\n"); + gameport_remap(dev->gameport, 0); + } + break; + + default: + break; } } - void um8669f_write(uint16_t port, uint8_t val, void *priv) { @@ -202,37 +202,36 @@ um8669f_write(uint16_t port, uint8_t val, void *priv) um8669f_log("UM8669F: write(%04X, %02X)\n", port, val); if (dev->locked) { - if ((port == 0x108) && (val == 0xaa)) - dev->locked = 0; + if ((port == 0x108) && (val == 0xaa)) + dev->locked = 0; } else { - if (port == 0x108) { - if (val == 0x55) - dev->locked = 1; - else - dev->cur_reg_108 = val; - } else { - dev->regs_108[dev->cur_reg_108] = val; + if (port == 0x108) { + if (val == 0x55) + dev->locked = 1; + else + dev->cur_reg_108 = val; + } else { + dev->regs_108[dev->cur_reg_108] = val; - if (dev->cur_reg_108 == 0xc1) { - um8669f_log("UM8669F: ISAPnP %sabled\n", (val & 0x80) ? "en" : "dis"); - isapnp_enable_card(dev->pnp_card, (val & 0x80) ? ISAPNP_CARD_FORCE_CONFIG : ISAPNP_CARD_DISABLE); - } - } + if (dev->cur_reg_108 == 0xc1) { + um8669f_log("UM8669F: ISAPnP %sabled\n", (val & 0x80) ? "en" : "dis"); + isapnp_enable_card(dev->pnp_card, (val & 0x80) ? ISAPNP_CARD_FORCE_CONFIG : ISAPNP_CARD_DISABLE); + } + } } } - uint8_t um8669f_read(uint16_t port, void *priv) { - um8669f_t *dev = (um8669f_t *) priv; - uint8_t ret = 0xff; + const um8669f_t *dev = (um8669f_t *) priv; + uint8_t ret = 0xff; if (!dev->locked) { - if (port == 0x108) - ret = dev->cur_reg_108; /* ??? */ - else - ret = dev->regs_108[dev->cur_reg_108]; + if (port == 0x108) + ret = dev->cur_reg_108; /* ??? */ + else + ret = dev->regs_108[dev->cur_reg_108]; } um8669f_log("UM8669F: read(%04X) = %02X\n", port, ret); @@ -240,7 +239,6 @@ um8669f_read(uint16_t port, void *priv) return ret; } - void um8669f_reset(um8669f_t *dev) { @@ -261,7 +259,6 @@ um8669f_reset(um8669f_t *dev) isapnp_reset_card(dev->pnp_card); } - static void um8669f_close(void *priv) { @@ -272,9 +269,8 @@ um8669f_close(void *priv) free(dev); } - static void * -um8669f_init(const device_t *info) +um8669f_init(UNUSED(const device_t *info)) { um8669f_log("UM8669F: init()\n"); @@ -283,7 +279,7 @@ um8669f_init(const device_t *info) dev->pnp_card = isapnp_add_card(um8669f_pnp_rom, sizeof(um8669f_pnp_rom), um8669f_pnp_config_changed, NULL, NULL, NULL, dev); for (uint8_t i = 0; i < (sizeof(um8669f_pnp_defaults) / sizeof(isapnp_device_config_t)); i++) - isapnp_set_device_defaults(dev->pnp_card, i, &um8669f_pnp_defaults[i]); + isapnp_set_device_defaults(dev->pnp_card, i, &um8669f_pnp_defaults[i]); dev->fdc = device_add(&fdc_at_smc_device); @@ -293,20 +289,23 @@ um8669f_init(const device_t *info) dev->gameport = gameport_add(&gameport_sio_device); io_sethandler(0x0108, 0x0002, - um8669f_read, NULL, NULL, um8669f_write, NULL, NULL, dev); + um8669f_read, NULL, NULL, um8669f_write, NULL, NULL, dev); um8669f_reset(dev); return dev; } - const device_t um8669f_device = { - "UMC UM8669F Super I/O", - "um8669f", - 0, - 0, - um8669f_init, um8669f_close, NULL, - { NULL }, NULL, NULL, - NULL + .name = "UMC UM8669F Super I/O", + .internal_name = "um8669f", + .flags = 0, + .local = 0, + .init = um8669f_init, + .close = um8669f_close, + .reset = NULL, + { .available = NULL }, + .speed_changed = NULL, + .force_redraw = NULL, + .config = NULL }; diff --git a/src/sio/sio_vt82c686.c b/src/sio/sio_vt82c686.c index 3f6229f15..f22af07df 100644 --- a/src/sio/sio_vt82c686.c +++ b/src/sio/sio_vt82c686.c @@ -1,18 +1,18 @@ /* - * 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. + * 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. + * This file is part of the 86Box distribution. * - * Emulation of the VIA VT82C686A/B integrated Super I/O. + * Emulation of the VIA VT82C686A/B integrated Super I/O. * * * - * Author: RichardG, + * Authors: RichardG, * - * Copyright 2020 RichardG. + * Copyright 2020 RichardG. */ #include #include @@ -31,28 +31,32 @@ #include <86box/fdd.h> #include <86box/fdc.h> #include <86box/sio.h> +#include <86box/plat_unused.h> - -typedef struct { - uint8_t cur_reg, last_val, regs[25], - fdc_dma, fdc_irq, uart_irq[2], lpt_dma, lpt_irq; - fdc_t *fdc; - serial_t *uart[2]; +typedef struct vt82c686_t { + uint8_t cur_reg; + uint8_t last_val; + uint8_t regs[25]; + uint8_t fdc_dma; + uint8_t fdc_irq; + uint8_t uart_irq[2]; + uint8_t lpt_dma; + uint8_t lpt_irq; + fdc_t *fdc; + serial_t *uart[2]; } vt82c686_t; - static uint8_t get_lpt_length(vt82c686_t *dev) { uint8_t length = 4; /* non-EPP */ if ((dev->regs[0x02] & 0x03) == 0x02) - length = 8; /* EPP */ + length = 8; /* EPP */ return length; } - static void vt82c686_fdc_handler(vt82c686_t *dev) { @@ -60,48 +64,46 @@ vt82c686_fdc_handler(vt82c686_t *dev) fdc_remove(dev->fdc); - if (dev->regs[0x02] & 0x10) - fdc_set_base(dev->fdc, io_base); + if ((dev->regs[0x02] & 0x10) && !(dev->regs[0x0f] & 0x03)) + fdc_set_base(dev->fdc, io_base); fdc_set_dma_ch(dev->fdc, dev->fdc_dma); fdc_set_irq(dev->fdc, dev->fdc_irq); fdc_set_swap(dev->fdc, dev->regs[0x16] & 0x01); } - static void vt82c686_lpt_handler(vt82c686_t *dev) { - uint16_t io_mask, io_base = dev->regs[0x06] << 2; - int io_len = get_lpt_length(dev); + uint16_t io_mask; + uint16_t io_base = dev->regs[0x06] << 2; + int io_len = get_lpt_length(dev); io_base &= (0xff8 | io_len); io_mask = 0x3fc; /* non-EPP */ if (io_len == 8) - io_mask = 0x3f8; /* EPP */ + io_mask = 0x3f8; /* EPP */ lpt1_remove(); - if (((dev->regs[0x02] & 0x03) != 0x03) && (io_base >= 0x100) && (io_base <= io_mask)) - lpt1_init(io_base); + if (((dev->regs[0x02] & 0x03) != 0x03) && !(dev->regs[0x0f] & 0x11) && (io_base >= 0x100) && (io_base <= io_mask)) + lpt1_init(io_base); if (dev->lpt_irq) { - lpt1_irq(dev->lpt_irq); + lpt1_irq(dev->lpt_irq); } else { - lpt1_irq(0xff); + lpt1_irq(0xff); } } - static void vt82c686_serial_handler(vt82c686_t *dev, int uart) { serial_remove(dev->uart[uart]); - if (dev->regs[0x02] & (0x04 << uart)) - serial_setup(dev->uart[uart], dev->regs[0x07 + uart] << 2, dev->uart_irq[uart]); + if ((dev->regs[0x02] & (0x04 << uart)) && !(dev->regs[0x0f] & ((0x04 << uart) | 0x01))) + serial_setup(dev->uart[uart], dev->regs[0x07 + uart] << 2, dev->uart_irq[uart]); } - static void vt82c686_write(uint16_t port, uint8_t val, void *priv) { @@ -112,86 +114,94 @@ vt82c686_write(uint16_t port, uint8_t val, void *priv) /* Write current register index on port 0. */ if (!(port & 1)) { - dev->cur_reg = val; - return; + dev->cur_reg = val; + return; } /* NOTE: Registers are [0xE0:0xF8] but we store them as [0x00:0x18]. */ if ((dev->cur_reg < 0xe0) || (dev->cur_reg > 0xf8)) - return; + return; uint8_t reg = dev->cur_reg & 0x1f; /* Read-only registers. */ if ((reg < 0x02) || (reg == 0x0c)) - return; + return; /* Write current register value on port 1. */ dev->regs[reg] = val; /* Update device state. */ switch (reg) { - case 0x02: - dev->regs[reg] &= 0xbf; - vt82c686_lpt_handler(dev); - vt82c686_serial_handler(dev, 0); - vt82c686_serial_handler(dev, 1); - vt82c686_fdc_handler(dev); - break; + case 0x02: + dev->regs[reg] &= 0xbf; + vt82c686_lpt_handler(dev); + vt82c686_serial_handler(dev, 0); + vt82c686_serial_handler(dev, 1); + vt82c686_fdc_handler(dev); + break; - case 0x03: - dev->regs[reg] &= 0xfc; - vt82c686_fdc_handler(dev); - break; + case 0x03: + dev->regs[reg] &= 0xfc; + vt82c686_fdc_handler(dev); + break; - case 0x04: - dev->regs[reg] &= 0xfc; - break; + case 0x04: + dev->regs[reg] &= 0xfc; + break; - case 0x05: - dev->regs[reg] |= 0x03; - break; + case 0x05: + dev->regs[reg] |= 0x03; + break; - case 0x06: - vt82c686_lpt_handler(dev); - break; + case 0x06: + vt82c686_lpt_handler(dev); + break; - case 0x07: case 0x08: - dev->regs[reg] &= 0xfe; - vt82c686_serial_handler(dev, reg == 0x08); - break; + case 0x07: + case 0x08: + dev->regs[reg] &= 0xfe; + vt82c686_serial_handler(dev, reg == 0x08); + break; - case 0x0d: - dev->regs[reg] &= 0x0f; - break; + case 0x0d: + dev->regs[reg] &= 0x0f; + break; - case 0x0f: - dev->regs[reg] &= 0x7f; - break; + case 0x0f: + dev->regs[reg] &= 0x7f; + vt82c686_lpt_handler(dev); + vt82c686_serial_handler(dev, 0); + vt82c686_serial_handler(dev, 1); + vt82c686_fdc_handler(dev); + break; - case 0x10: - dev->regs[reg] &= 0xf4; - break; + case 0x10: + dev->regs[reg] &= 0xf4; + break; - case 0x11: - dev->regs[reg] &= 0x3f; - break; + case 0x11: + dev->regs[reg] &= 0x3f; + break; - case 0x13: - dev->regs[reg] &= 0xfb; - break; + case 0x13: + dev->regs[reg] &= 0xfb; + break; - case 0x14: case 0x17: - dev->regs[reg] &= 0xfe; - break; + case 0x14: + case 0x17: + dev->regs[reg] &= 0xfe; + break; - case 0x16: - dev->regs[reg] &= 0xf7; - vt82c686_fdc_handler(dev); - break; + case 0x16: + dev->regs[reg] &= 0xf7; + vt82c686_fdc_handler(dev); + break; + + default: + break; } } - static uint8_t vt82c686_read(uint16_t port, void *priv) { @@ -201,14 +211,13 @@ vt82c686_read(uint16_t port, void *priv) Real 686B echoes the last read/written value when reading from registers outside that range. */ if (!(port & 1)) - dev->last_val = dev->cur_reg; + dev->last_val = dev->cur_reg; else if ((dev->cur_reg >= 0xe0) && (dev->cur_reg <= 0xf8)) - dev->last_val = dev->regs[dev->cur_reg & 0x1f]; + dev->last_val = dev->regs[dev->cur_reg & 0x1f]; return dev->last_val; } - /* Writes to Super I/O-related configuration space registers of the VT82C686 PCI-ISA bridge are sent here by via_pipc.c */ void @@ -217,53 +226,48 @@ vt82c686_sio_write(uint8_t addr, uint8_t val, void *priv) vt82c686_t *dev = (vt82c686_t *) priv; switch (addr) { - case 0x50: - dev->fdc_dma = val & 0x03; - vt82c686_fdc_handler(dev); - dev->lpt_dma = (val >> 2) & 0x03; - vt82c686_lpt_handler(dev); - break; + case 0x50: + dev->fdc_dma = val & 0x03; + vt82c686_fdc_handler(dev); + dev->lpt_dma = (val >> 2) & 0x03; + vt82c686_lpt_handler(dev); + break; - case 0x51: - dev->fdc_irq = val & 0x0f; - vt82c686_fdc_handler(dev); - dev->lpt_irq = val >> 4; - vt82c686_lpt_handler(dev); - break; + case 0x51: + dev->fdc_irq = val & 0x0f; + vt82c686_fdc_handler(dev); + dev->lpt_irq = val >> 4; + vt82c686_lpt_handler(dev); + break; - case 0x52: - dev->uart_irq[0] = val & 0x0f; - vt82c686_serial_handler(dev, 0); - dev->uart_irq[1] = val >> 4; - vt82c686_serial_handler(dev, 1); - break; + case 0x52: + dev->uart_irq[0] = val & 0x0f; + vt82c686_serial_handler(dev, 0); + dev->uart_irq[1] = val >> 4; + vt82c686_serial_handler(dev, 1); + break; - case 0x85: - io_removehandler(0x3f0, 2, vt82c686_read, NULL, NULL, vt82c686_write, NULL, NULL, dev); - if (val & 0x02) - io_sethandler(0x3f0, 2, vt82c686_read, NULL, NULL, vt82c686_write, NULL, NULL, dev); - break; + case 0x85: + io_removehandler(FDC_PRIMARY_ADDR, 2, vt82c686_read, NULL, NULL, vt82c686_write, NULL, NULL, dev); + if (val & 0x02) + io_sethandler(FDC_PRIMARY_ADDR, 2, vt82c686_read, NULL, NULL, vt82c686_write, NULL, NULL, dev); + break; + + default: + break; } } - static void vt82c686_reset(vt82c686_t *dev) { - memset(dev->regs, 0, 20); + memset(dev->regs, 0, 21); dev->regs[0x00] = 0x3c; dev->regs[0x02] = 0x03; - dev->regs[0x03] = 0xfc; - dev->regs[0x06] = 0xde; - dev->regs[0x07] = 0xfe; - dev->regs[0x08] = 0xbe; fdc_reset(dev->fdc); - serial_setup(dev->uart[0], SERIAL1_ADDR, SERIAL1_IRQ); - serial_setup(dev->uart[1], SERIAL2_ADDR, SERIAL2_IRQ); - vt82c686_lpt_handler(dev); vt82c686_serial_handler(dev, 0); vt82c686_serial_handler(dev, 1); @@ -272,7 +276,6 @@ vt82c686_reset(vt82c686_t *dev) vt82c686_sio_write(0x85, 0x00, dev); } - static void vt82c686_close(void *priv) { @@ -281,14 +284,13 @@ vt82c686_close(void *priv) free(dev); } - static void * -vt82c686_init(const device_t *info) +vt82c686_init(UNUSED(const device_t *info)) { vt82c686_t *dev = (vt82c686_t *) malloc(sizeof(vt82c686_t)); memset(dev, 0, sizeof(vt82c686_t)); - dev->fdc = device_add(&fdc_at_smc_device); + dev->fdc = device_add(&fdc_at_smc_device); dev->fdc_dma = 2; dev->uart[0] = device_add_inst(&ns16550_device, 1); @@ -301,13 +303,16 @@ vt82c686_init(const device_t *info) return dev; } - const device_t via_vt82c686_sio_device = { - "VIA VT82C686 Integrated Super I/O", - "via_vt82c686_sio", - 0, - 0, - vt82c686_init, vt82c686_close, NULL, - { NULL }, NULL, NULL, - NULL + .name = "VIA VT82C686 Integrated Super I/O", + .internal_name = "via_vt82c686_sio", + .flags = 0, + .local = 0, + .init = vt82c686_init, + .close = vt82c686_close, + .reset = NULL, + { .available = NULL }, + .speed_changed = NULL, + .force_redraw = NULL, + .config = NULL }; diff --git a/src/sio/sio_w83787f.c b/src/sio/sio_w83787f.c index 5cd7017bc..33cfc6311 100644 --- a/src/sio/sio_w83787f.c +++ b/src/sio/sio_w83787f.c @@ -1,20 +1,20 @@ /* - * 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. + * 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. + * This file is part of the 86Box distribution. * - * Emulation of the Winbond W83787F/IF Super I/O Chip. + * Emulation of the Winbond W83787F/IF Super I/O Chip. * - * Winbond W83787F Super I/O Chip - * Used by the Award 430HX + * Winbond W83787F Super I/O Chip + * Used by the Award 430HX * * * - * Author: Miran Grca, - * Copyright 2020 Miran Grca. + * Authors: Miran Grca, + * Copyright 2020 Miran Grca. */ #include #include @@ -34,72 +34,74 @@ #include <86box/fdc.h> #include <86box/hdc.h> #include <86box/hdc_ide.h> +#include <86box/gameport.h> #include <86box/sio.h> #ifdef ENABLE_W83787_LOG int w83787_do_log = ENABLE_W83787_LOG; + static void w83787_log(const char *fmt, ...) { va_list ap; - if (w83787_do_log) - { + if (w83787_do_log) { va_start(ap, fmt); pclog_ex(fmt, ap); va_end(ap); } } #else -#define w83787_log(fmt, ...) +# define w83787_log(fmt, ...) #endif -#define FDDA_TYPE (dev->regs[7] & 3) -#define FDDB_TYPE ((dev->regs[7] >> 2) & 3) -#define FDDC_TYPE ((dev->regs[7] >> 4) & 3) -#define FDDD_TYPE ((dev->regs[7] >> 6) & 3) +#define FDDA_TYPE (dev->regs[7] & 3) +#define FDDB_TYPE ((dev->regs[7] >> 2) & 3) +#define FDDC_TYPE ((dev->regs[7] >> 4) & 3) +#define FDDD_TYPE ((dev->regs[7] >> 6) & 3) -#define FD_BOOT (dev->regs[8] & 3) -#define SWWP ((dev->regs[8] >> 4) & 1) -#define DISFDDWR ((dev->regs[8] >> 5) & 1) +#define FD_BOOT (dev->regs[8] & 3) +#define SWWP ((dev->regs[8] >> 4) & 1) +#define DISFDDWR ((dev->regs[8] >> 5) & 1) -#define EN3MODE ((dev->regs[9] >> 5) & 1) +#define EN3MODE ((dev->regs[9] >> 5) & 1) -#define DRV2EN_NEG (dev->regs[0xB] & 1) /* 0 = drive 2 installed */ -#define INVERTZ ((dev->regs[0xB] >> 1) & 1) /* 0 = invert DENSEL polarity */ -#define IDENT ((dev->regs[0xB] >> 3) & 1) +#define DRV2EN_NEG (dev->regs[0xB] & 1) /* 0 = drive 2 installed */ +#define INVERTZ ((dev->regs[0xB] >> 1) & 1) /* 0 = invert DENSEL polarity */ +#define IDENT ((dev->regs[0xB] >> 3) & 1) -#define HEFERE ((dev->regs[0xC] >> 5) & 1) +#define HEFERE ((dev->regs[0xC] >> 5) & 1) -#define HAS_IDE_FUNCTIONALITY dev->ide_function +#define HAS_IDE_FUNCTIONALITY dev->ide_function -typedef struct { - uint8_t tries, regs[42]; +typedef struct w83787f_t { + uint8_t tries; + uint8_t regs[42]; uint16_t reg_init; - int locked, rw_locked, - cur_reg, - key, ide_function, - ide_start; - fdc_t *fdc; + int locked; + int rw_locked; + int cur_reg; + int key; + int ide_function; + int ide_start; + fdc_t *fdc; serial_t *uart[2]; + void *gameport; } w83787f_t; - -static void w83787f_write(uint16_t port, uint8_t val, void *priv); -static uint8_t w83787f_read(uint16_t port, void *priv); - +static void w83787f_write(uint16_t port, uint8_t val, void *priv); +static uint8_t w83787f_read(uint16_t port, void *priv); static void w83787f_remap(w83787f_t *dev) { io_removehandler(0x250, 0x0004, - w83787f_read, NULL, NULL, w83787f_write, NULL, NULL, dev); + w83787f_read, NULL, NULL, w83787f_write, NULL, NULL, dev); io_sethandler(0x250, 0x0004, - w83787f_read, NULL, NULL, w83787f_write, NULL, NULL, dev); + w83787f_read, NULL, NULL, w83787f_write, NULL, NULL, dev); dev->key = 0x88 | HEFERE; } - #ifdef FIXME /* FIXME: Implement EPP (and ECP) parallel port modes. */ static uint8_t @@ -108,309 +110,326 @@ get_lpt_length(w83787f_t *dev) uint8_t length = 4; if (dev->regs[9] & 0x80) { - if (dev->regs[0] & 0x04) - length = 8; /* EPP mode. */ - if (dev->regs[0] & 0x08) - length |= 0x80; /* ECP mode. */ + if (dev->regs[0] & 0x04) + length = 8; /* EPP mode. */ + if (dev->regs[0] & 0x08) + length |= 0x80; /* ECP mode. */ } return length; } #endif - static void w83787f_serial_handler(w83787f_t *dev, int uart) { - int urs0 = !!(dev->regs[1] & (1 << uart)); - int urs1 = !!(dev->regs[1] & (4 << uart)); - int urs2 = !!(dev->regs[3] & (8 >> uart)); - int urs, irq = 4; - uint16_t addr = 0x3f8, enable = 1; + int urs0 = !!(dev->regs[1] & (1 << uart)); + int urs1 = !!(dev->regs[1] & (4 << uart)); + int urs2 = !!(dev->regs[3] & (8 >> uart)); + int urs; + int irq = COM1_IRQ; + uint16_t addr = COM1_ADDR; + uint16_t enable = 1; urs = (urs1 << 1) | urs0; if (urs2) { - addr = uart ? 0x3f8 : 0x2f8; - irq = uart ? 4 : 3; + addr = uart ? COM1_ADDR : COM2_ADDR; + irq = uart ? COM1_IRQ : COM2_IRQ; } else { - switch (urs) { - case 0: - addr = uart ? 0x3e8 : 0x2e8; - irq = uart ? 4 : 3; - break; - case 1: - addr = uart ? 0x2e8 : 0x3e8; - irq = uart ? 3 : 4; - break; - case 2: - addr = uart ? 0x2f8 : 0x3f8; - irq = uart ? 3 : 4; - break; - case 3: - default: - enable = 0; - break; - } + switch (urs) { + case 0: + addr = uart ? COM3_ADDR : COM4_ADDR; + irq = uart ? COM3_IRQ : COM4_IRQ; + break; + case 1: + addr = uart ? COM4_ADDR : COM3_ADDR; + irq = uart ? COM4_IRQ : COM3_IRQ; + break; + case 2: + addr = uart ? COM2_ADDR : COM1_ADDR; + irq = uart ? COM2_IRQ : COM1_IRQ; + break; + case 3: + default: + enable = 0; + break; + } } if (dev->regs[4] & (0x20 >> uart)) - enable = 0; + enable = 0; serial_remove(dev->uart[uart]); if (enable) - serial_setup(dev->uart[uart], addr, irq); + serial_setup(dev->uart[uart], addr, irq); } - static void w83787f_lpt_handler(w83787f_t *dev) { - int ptras = (dev->regs[1] >> 4) & 0x03; - int irq = 7; - uint16_t addr = 0x378, enable = 1; + int ptras = (dev->regs[1] >> 4) & 0x03; + int irq = LPT1_IRQ; + uint16_t addr = LPT1_ADDR; + uint16_t enable = 1; switch (ptras) { - case 0x00: - addr = 0x3bc; - irq = 7; - break; - case 0x01: - addr = 0x278; - irq = 5; - break; - case 0x02: - addr = 0x378; - irq = 7; - break; - case 0x03: - default: - enable = 0; - break; + case 0x00: + addr = LPT_MDA_ADDR; + irq = LPT_MDA_IRQ; + break; + case 0x01: + addr = LPT2_ADDR; + irq = LPT2_IRQ; + break; + case 0x02: + addr = LPT1_ADDR; + irq = LPT1_IRQ; + break; + case 0x03: + default: + enable = 0; + break; } if (dev->regs[4] & 0x80) - enable = 0; + enable = 0; lpt1_remove(); if (enable) { - lpt1_init(addr); - lpt1_irq(irq); + lpt1_init(addr); + lpt1_irq(irq); } } +static void +w83787f_gameport_handler(w83787f_t *dev) +{ + if (!(dev->regs[3] & 0x40) && !(dev->regs[4] & 0x40)) + gameport_remap(dev->gameport, 0x201); + else + gameport_remap(dev->gameport, 0); +} static void w83787f_fdc_handler(w83787f_t *dev) { fdc_remove(dev->fdc); if (!(dev->regs[0] & 0x20) && !(dev->regs[6] & 0x08)) - fdc_set_base(dev->fdc, (dev->regs[0] & 0x10) ? 0x03f0 : 0x0370); + fdc_set_base(dev->fdc, (dev->regs[0] & 0x10) ? FDC_PRIMARY_ADDR : FDC_SECONDARY_ADDR); } - static void w83787f_ide_handler(w83787f_t *dev) { if (dev->ide_function & 0x20) { - ide_sec_disable(); - if (!(dev->regs[0] & 0x80)) { - ide_set_base(1, (dev->regs[0] & 0x40) ? 0x1f0 : 0x170); - ide_set_side(1, (dev->regs[0] & 0x40) ? 0x3f6 : 0x376); - ide_sec_enable(); - } + ide_sec_disable(); + if (!(dev->regs[0] & 0x80)) { + ide_set_base(1, (dev->regs[0] & 0x40) ? 0x1f0 : 0x170); + ide_set_side(1, (dev->regs[0] & 0x40) ? 0x3f6 : 0x376); + ide_sec_enable(); + } } else { - ide_pri_disable(); - if (!(dev->regs[0] & 0x80)) { - ide_set_base(0, (dev->regs[0] & 0x40) ? 0x1f0 : 0x170); - ide_set_side(0, (dev->regs[0] & 0x40) ? 0x3f6 : 0x376); - ide_pri_enable(); - } + ide_pri_disable(); + if (!(dev->regs[0] & 0x80)) { + ide_set_base(0, (dev->regs[0] & 0x40) ? 0x1f0 : 0x170); + ide_set_side(0, (dev->regs[0] & 0x40) ? 0x3f6 : 0x376); + ide_pri_enable(); + } } } - static void w83787f_write(uint16_t port, uint8_t val, void *priv) { - w83787f_t *dev = (w83787f_t *) priv; - uint8_t valxor = 0; - uint8_t max = 0x15; + w83787f_t *dev = (w83787f_t *) priv; + uint8_t valxor = 0; + uint8_t max = 0x15; if (port == 0x250) { - if (val == dev->key) - dev->locked = 1; - else - dev->locked = 0; - return; + if (val == dev->key) + dev->locked = 1; + else + dev->locked = 0; + return; } else if (port == 0x251) { - if (val <= max) - dev->cur_reg = val; - return; + if (val <= max) + dev->cur_reg = val; + return; } else { - if (dev->locked) { - if (dev->rw_locked) - return; - if (dev->cur_reg == 6) - val &= 0xF3; - valxor = val ^ dev->regs[dev->cur_reg]; - dev->regs[dev->cur_reg] = val; - } else - return; + if (dev->locked) { + if (dev->rw_locked) + return; + if (dev->cur_reg == 6) + val &= 0xF3; + valxor = val ^ dev->regs[dev->cur_reg]; + dev->regs[dev->cur_reg] = val; + } else + return; } switch (dev->cur_reg) { - case 0: - w83787_log("REG 00: %02X\n", val); - if ((valxor & 0xc0) && (HAS_IDE_FUNCTIONALITY)) - w83787f_ide_handler(dev); - if (valxor & 0x30) - w83787f_fdc_handler(dev); - if (valxor & 0x0c) - w83787f_lpt_handler(dev); - break; - case 1: - if (valxor & 0x80) - fdc_set_swap(dev->fdc, (dev->regs[1] & 0x80) ? 1 : 0); - if (valxor & 0x30) - w83787f_lpt_handler(dev); - if (valxor & 0x0a) - w83787f_serial_handler(dev, 1); - if (valxor & 0x05) - w83787f_serial_handler(dev, 0); - break; - case 3: - if (valxor & 0x80) - w83787f_lpt_handler(dev); - if (valxor & 0x08) - w83787f_serial_handler(dev, 0); - if (valxor & 0x04) - w83787f_serial_handler(dev, 1); - break; - case 4: - if (valxor & 0x10) - w83787f_serial_handler(dev, 1); - if (valxor & 0x20) - w83787f_serial_handler(dev, 0); - if (valxor & 0x80) - w83787f_lpt_handler(dev); - break; - case 6: - if (valxor & 0x08) - w83787f_fdc_handler(dev); - break; - case 7: - if (valxor & 0x03) - fdc_update_rwc(dev->fdc, 0, FDDA_TYPE); - if (valxor & 0x0c) - fdc_update_rwc(dev->fdc, 1, FDDB_TYPE); - if (valxor & 0x30) - fdc_update_rwc(dev->fdc, 2, FDDC_TYPE); - if (valxor & 0xc0) - fdc_update_rwc(dev->fdc, 3, FDDD_TYPE); - break; - case 8: - if (valxor & 0x03) - fdc_update_boot_drive(dev->fdc, FD_BOOT); - if (valxor & 0x10) - fdc_set_swwp(dev->fdc, SWWP ? 1 : 0); - if (valxor & 0x20) - fdc_set_diswr(dev->fdc, DISFDDWR ? 1 : 0); - break; - case 9: - if (valxor & 0x20) - fdc_update_enh_mode(dev->fdc, EN3MODE ? 1 : 0); - if (valxor & 0x40) - dev->rw_locked = (val & 0x40) ? 1 : 0; - if (valxor & 0x80) - w83787f_lpt_handler(dev); - break; - case 0xB: - w83787_log("Writing %02X to CRB\n", val); - break; - case 0xC: - if (valxor & 0x20) - w83787f_remap(dev); - break; + case 0: + w83787_log("REG 00: %02X\n", val); + if ((valxor & 0xc0) && (HAS_IDE_FUNCTIONALITY)) + w83787f_ide_handler(dev); + if (valxor & 0x30) + w83787f_fdc_handler(dev); + if (valxor & 0x0c) + w83787f_lpt_handler(dev); + break; + case 1: + if (valxor & 0x80) + fdc_set_swap(dev->fdc, (dev->regs[1] & 0x80) ? 1 : 0); + if (valxor & 0x30) + w83787f_lpt_handler(dev); + if (valxor & 0x0a) + w83787f_serial_handler(dev, 1); + if (valxor & 0x05) + w83787f_serial_handler(dev, 0); + break; + case 3: + if (valxor & 0x80) + w83787f_lpt_handler(dev); + if (valxor & 0x40) + w83787f_gameport_handler(dev); + if (valxor & 0x08) + w83787f_serial_handler(dev, 0); + if (valxor & 0x04) + w83787f_serial_handler(dev, 1); + break; + case 4: + if (valxor & 0x10) + w83787f_serial_handler(dev, 1); + if (valxor & 0x20) + w83787f_serial_handler(dev, 0); + if (valxor & 0x80) + w83787f_lpt_handler(dev); + if (valxor & 0x40) + w83787f_gameport_handler(dev); + break; + case 6: + if (valxor & 0x08) + w83787f_fdc_handler(dev); + break; + case 7: + if (valxor & 0x03) + fdc_update_rwc(dev->fdc, 0, FDDA_TYPE); + if (valxor & 0x0c) + fdc_update_rwc(dev->fdc, 1, FDDB_TYPE); + if (valxor & 0x30) + fdc_update_rwc(dev->fdc, 2, FDDC_TYPE); + if (valxor & 0xc0) + fdc_update_rwc(dev->fdc, 3, FDDD_TYPE); + break; + case 8: + if (valxor & 0x03) + fdc_update_boot_drive(dev->fdc, FD_BOOT); + if (valxor & 0x10) + fdc_set_swwp(dev->fdc, SWWP ? 1 : 0); + if (valxor & 0x20) + fdc_set_diswr(dev->fdc, DISFDDWR ? 1 : 0); + break; + case 9: + if (valxor & 0x20) + fdc_update_enh_mode(dev->fdc, EN3MODE ? 1 : 0); + if (valxor & 0x40) + dev->rw_locked = (val & 0x40) ? 1 : 0; + if (valxor & 0x80) + w83787f_lpt_handler(dev); + break; + case 0xB: + w83787_log("Writing %02X to CRB\n", val); + break; + case 0xC: + if (valxor & 0x20) + w83787f_remap(dev); + break; + + default: + break; } } - static uint8_t w83787f_read(uint16_t port, void *priv) { w83787f_t *dev = (w83787f_t *) priv; - uint8_t ret = 0xff; + uint8_t ret = 0xff; if (dev->locked) { - if (port == 0x251) - ret = dev->cur_reg; - else if (port == 0x252) { - if (dev->cur_reg == 7) - ret = (fdc_get_rwc(dev->fdc, 0) | (fdc_get_rwc(dev->fdc, 1) << 2)); - else if (!dev->rw_locked) - ret = dev->regs[dev->cur_reg]; - } + if (port == 0x251) + ret = dev->cur_reg; + else if (port == 0x252) { + if (dev->cur_reg == 7) + ret = (fdc_get_rwc(dev->fdc, 0) | (fdc_get_rwc(dev->fdc, 1) << 2)); + else if (!dev->rw_locked) + ret = dev->regs[dev->cur_reg]; + } } return ret; } - static void w83787f_reset(w83787f_t *dev) { + uint16_t hefere = dev->reg_init & 0x0100; + lpt1_remove(); - lpt1_init(0x378); - lpt1_irq(7); + lpt1_init(LPT1_ADDR); + lpt1_irq(LPT1_IRQ); memset(dev->regs, 0, 0x2A); if (HAS_IDE_FUNCTIONALITY) { - if (dev->ide_function & 0x20) { - dev->regs[0x00] = 0x90; - ide_sec_disable(); - ide_set_base(1, 0x170); - ide_set_side(1, 0x376); - } else { - dev->regs[0x00] = 0xd0; - ide_pri_disable(); - ide_set_base(0, 0x1f0); - ide_set_side(0, 0x3f6); - } + if (dev->ide_function & 0x20) { + dev->regs[0x00] = 0x90; + ide_sec_disable(); + ide_set_base(1, 0x170); + ide_set_side(1, 0x376); + } else { + dev->regs[0x00] = 0xd0; + ide_pri_disable(); + ide_set_base(0, 0x1f0); + ide_set_side(0, 0x3f6); + } - if (dev->ide_start) { - dev->regs[0x00] &= 0x7f; - if (dev->ide_function & 0x20) - ide_sec_enable(); - else - ide_pri_enable(); - } + if (dev->ide_start) { + dev->regs[0x00] &= 0x7f; + if (dev->ide_function & 0x20) + ide_sec_enable(); + else + ide_pri_enable(); + } } else - dev->regs[0x00] = 0xd0; + dev->regs[0x00] = 0xd0; fdc_reset(dev->fdc); dev->regs[0x01] = 0x2C; - dev->regs[0x03] = 0x30; + dev->regs[0x03] = 0x70; dev->regs[0x07] = 0xF5; dev->regs[0x09] = dev->reg_init & 0xff; dev->regs[0x0a] = 0x1F; - dev->regs[0x0c] = 0x2C; + dev->regs[0x0c] = 0x0C | (hefere >> 3); dev->regs[0x0d] = 0xA3; - serial_setup(dev->uart[0], SERIAL1_ADDR, SERIAL1_IRQ); - serial_setup(dev->uart[1], SERIAL2_ADDR, SERIAL2_IRQ); + gameport_remap(dev->gameport, 0); - dev->key = 0x89; + serial_setup(dev->uart[0], COM1_ADDR, COM1_IRQ); + serial_setup(dev->uart[1], COM2_ADDR, COM2_IRQ); + + w83787f_lpt_handler(dev); + + dev->key = 0x88 | (hefere >> 8); w83787f_remap(dev); - dev->locked = 0; + dev->locked = 0; dev->rw_locked = 0; } - static void w83787f_close(void *priv) { @@ -419,7 +438,6 @@ w83787f_close(void *priv) free(dev); } - static void * w83787f_init(const device_t *info) { @@ -432,55 +450,86 @@ w83787f_init(const device_t *info) dev->uart[0] = device_add_inst(&ns16550_device, 1); dev->uart[1] = device_add_inst(&ns16550_device, 2); - + + dev->gameport = gameport_add(&gameport_sio_1io_device); + if ((dev->ide_function & 0x30) == 0x10) - device_add(&ide_isa_device); + device_add(&ide_isa_device); dev->ide_start = !!(info->local & 0x40); - dev->reg_init = info->local & 0x0f; + dev->reg_init = info->local & 0x010f; w83787f_reset(dev); return dev; } +const device_t w83787f_88h_device = { + .name = "Winbond W83787F/IF Super I/O", + .internal_name = "w83787f", + .flags = 0, + .local = 0x0009, + .init = w83787f_init, + .close = w83787f_close, + .reset = NULL, + { .available = NULL }, + .speed_changed = NULL, + .force_redraw = NULL, + .config = NULL +}; const device_t w83787f_device = { - "Winbond W83787F/IF Super I/O", - "w83787f", - 0, - 0x09, - w83787f_init, w83787f_close, NULL, - { NULL }, NULL, NULL, - NULL + .name = "Winbond W83787F/IF Super I/O", + .internal_name = "w83787f", + .flags = 0, + .local = 0x0109, + .init = w83787f_init, + .close = w83787f_close, + .reset = NULL, + { .available = NULL }, + .speed_changed = NULL, + .force_redraw = NULL, + .config = NULL }; const device_t w83787f_ide_device = { - "Winbond W83787F/IF Super I/O (With IDE)", - "w83787f_ide", - 0, - 0x19, - w83787f_init, w83787f_close, NULL, - { NULL }, NULL, NULL, - NULL + .name = "Winbond W83787F/IF Super I/O (With IDE)", + .internal_name = "w83787f_ide", + .flags = 0, + .local = 0x0119, + .init = w83787f_init, + .close = w83787f_close, + .reset = NULL, + { .available = NULL }, + .speed_changed = NULL, + .force_redraw = NULL, + .config = NULL }; const device_t w83787f_ide_en_device = { - "Winbond W83787F/IF Super I/O (With IDE Enabled)", - "w83787f_ide_en", - 0, - 0x59, - w83787f_init, w83787f_close, NULL, - { NULL }, NULL, NULL, - NULL + .name = "Winbond W83787F/IF Super I/O (With IDE Enabled)", + .internal_name = "w83787f_ide_en", + .flags = 0, + .local = 0x0159, + .init = w83787f_init, + .close = w83787f_close, + .reset = NULL, + { .available = NULL }, + .speed_changed = NULL, + .force_redraw = NULL, + .config = NULL }; const device_t w83787f_ide_sec_device = { - "Winbond W83787F/IF Super I/O (With Secondary IDE)", - "w83787f_ide_sec", - 0, - 0x39, - w83787f_init, w83787f_close, NULL, - { NULL }, NULL, NULL, - NULL + .name = "Winbond W83787F/IF Super I/O (With Secondary IDE)", + .internal_name = "w83787f_ide_sec", + .flags = 0, + .local = 0x0139, + .init = w83787f_init, + .close = w83787f_close, + .reset = NULL, + { .available = NULL }, + .speed_changed = NULL, + .force_redraw = NULL, + .config = NULL }; diff --git a/src/sio/sio_w83877f.c b/src/sio/sio_w83877f.c index d1433cb1f..8cbb82876 100644 --- a/src/sio/sio_w83877f.c +++ b/src/sio/sio_w83877f.c @@ -1,20 +1,20 @@ /* - * 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. + * 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. + * This file is part of the 86Box distribution. * - * Emulation of the Winbond W83877F Super I/O Chip. + * Emulation of the Winbond W83877F Super I/O Chip. * - * Winbond W83877F Super I/O Chip - * Used by the Award 430HX + * Winbond W83877F Super I/O Chip + * Used by the Award 430HX * * * - * Author: Miran Grca, - * Copyright 2016-2020 Miran Grca. + * Authors: Miran Grca, + * Copyright 2016-2020 Miran Grca. */ #include #include @@ -34,45 +34,44 @@ #include <86box/fdc.h> #include <86box/sio.h> +#define FDDA_TYPE (dev->regs[7] & 3) +#define FDDB_TYPE ((dev->regs[7] >> 2) & 3) +#define FDDC_TYPE ((dev->regs[7] >> 4) & 3) +#define FDDD_TYPE ((dev->regs[7] >> 6) & 3) -#define FDDA_TYPE (dev->regs[7] & 3) -#define FDDB_TYPE ((dev->regs[7] >> 2) & 3) -#define FDDC_TYPE ((dev->regs[7] >> 4) & 3) -#define FDDD_TYPE ((dev->regs[7] >> 6) & 3) +#define FD_BOOT (dev->regs[8] & 3) +#define SWWP ((dev->regs[8] >> 4) & 1) +#define DISFDDWR ((dev->regs[8] >> 5) & 1) -#define FD_BOOT (dev->regs[8] & 3) -#define SWWP ((dev->regs[8] >> 4) & 1) -#define DISFDDWR ((dev->regs[8] >> 5) & 1) +#define EN3MODE ((dev->regs[9] >> 5) & 1) -#define EN3MODE ((dev->regs[9] >> 5) & 1) +#define DRV2EN_NEG (dev->regs[0xB] & 1) /* 0 = drive 2 installed */ +#define INVERTZ ((dev->regs[0xB] >> 1) & 1) /* 0 = invert DENSEL polarity */ +#define IDENT ((dev->regs[0xB] >> 3) & 1) -#define DRV2EN_NEG (dev->regs[0xB] & 1) /* 0 = drive 2 installed */ -#define INVERTZ ((dev->regs[0xB] >> 1) & 1) /* 0 = invert DENSEL polarity */ -#define IDENT ((dev->regs[0xB] >> 3) & 1) +#define HEFERE ((dev->regs[0xC] >> 5) & 1) -#define HEFERE ((dev->regs[0xC] >> 5) & 1) +#define HEFRAS (dev->regs[0x16] & 1) -#define HEFRAS (dev->regs[0x16] & 1) +#define PRTIQS (dev->regs[0x27] & 0x0f) +#define ECPIRQ ((dev->regs[0x27] >> 5) & 0x07) -#define PRTIQS (dev->regs[0x27] & 0x0f) -#define ECPIRQ ((dev->regs[0x27] >> 5) & 0x07) - - -typedef struct { - uint8_t tries, regs[42]; - uint16_t reg_init; - int locked, rw_locked, - cur_reg, - base_address, key, - key_times; - fdc_t *fdc; +typedef struct w83877f_t { + uint8_t tries; + uint8_t regs[42]; + uint16_t reg_init; + int locked; + int rw_locked; + int cur_reg; + int base_address; + int key; + int key_times; + fdc_t *fdc; serial_t *uart[2]; } w83877f_t; - -static void w83877f_write(uint16_t port, uint8_t val, void *priv); -static uint8_t w83877f_read(uint16_t port, void *priv); - +static void w83877f_write(uint16_t port, uint8_t val, void *priv); +static uint8_t w83877f_read(uint16_t port, void *priv); static void w83877f_remap(w83877f_t *dev) @@ -80,83 +79,86 @@ w83877f_remap(w83877f_t *dev) uint8_t hefras = HEFRAS; io_removehandler(0x250, 0x0002, - w83877f_read, NULL, NULL, w83877f_write, NULL, NULL, dev); - io_removehandler(0x3f0, 0x0002, - w83877f_read, NULL, NULL, w83877f_write, NULL, NULL, dev); - dev->base_address = (hefras ? 0x3f0 : 0x250); + w83877f_read, NULL, NULL, w83877f_write, NULL, NULL, dev); + io_removehandler(FDC_PRIMARY_ADDR, 0x0002, + w83877f_read, NULL, NULL, w83877f_write, NULL, NULL, dev); + dev->base_address = (hefras ? FDC_PRIMARY_ADDR : 0x250); io_sethandler(dev->base_address, 0x0002, - w83877f_read, NULL, NULL, w83877f_write, NULL, NULL, dev); + w83877f_read, NULL, NULL, w83877f_write, NULL, NULL, dev); dev->key_times = hefras + 1; - dev->key = (hefras ? 0x86 : 0x88) | HEFERE; + dev->key = (hefras ? 0x86 : 0x88) | HEFERE; } - static uint8_t get_lpt_length(w83877f_t *dev) { uint8_t length = 4; if (dev->regs[9] & 0x80) { - if (dev->regs[0] & 0x04) - length = 8; /* EPP mode. */ - if (dev->regs[0] & 0x08) - length |= 0x80; /* ECP mode. */ + if (dev->regs[0] & 0x04) + length = 8; /* EPP mode. */ + if (dev->regs[0] & 0x08) + length |= 0x80; /* ECP mode. */ } return length; } - static uint16_t make_port(w83877f_t *dev, uint8_t reg) { uint16_t p = 0; - uint8_t l; + uint8_t l; switch (reg) { - case 0x20: - p = ((uint16_t) (dev->regs[reg] & 0xfc)) << 2; - p &= 0xFF0; - if ((p < 0x100) || (p > 0x3F0)) p = 0x3F0; - break; - case 0x23: - l = get_lpt_length(dev); - p = ((uint16_t) (dev->regs[reg] & 0xff)) << 2; - /* 8 ports in EPP mode, 4 in non-EPP mode. */ - if ((l & 0x0f) == 8) - p &= 0x3F8; - else - p &= 0x3FC; - if ((p < 0x100) || (p > 0x3FF)) p = 0x378; - /* In ECP mode, A10 is active. */ - if (l & 0x80) - p |= 0x400; - break; - case 0x24: - p = ((uint16_t) (dev->regs[reg] & 0xfe)) << 2; - p &= 0xFF8; - if ((p < 0x100) || (p > 0x3F8)) p = 0x3F8; - break; - case 0x25: - p = ((uint16_t) (dev->regs[reg] & 0xfe)) << 2; - p &= 0xFF8; - if ((p < 0x100) || (p > 0x3F8)) p = 0x2F8; - break; + case 0x20: + p = ((uint16_t) (dev->regs[reg] & 0xfc)) << 2; + p &= 0xFF0; + if ((p < 0x100) || (p > 0x3F0)) + p = 0x3F0; + break; + case 0x23: + l = get_lpt_length(dev); + p = ((uint16_t) (dev->regs[reg] & 0xff)) << 2; + /* 8 ports in EPP mode, 4 in non-EPP mode. */ + if ((l & 0x0f) == 8) + p &= 0x3F8; + else + p &= 0x3FC; + if ((p < 0x100) || (p > 0x3FF)) + p = LPT1_ADDR; + /* In ECP mode, A10 is active. */ + if (l & 0x80) + p |= 0x400; + break; + case 0x24: + p = ((uint16_t) (dev->regs[reg] & 0xfe)) << 2; + p &= 0xFF8; + if ((p < 0x100) || (p > 0x3F8)) + p = COM1_ADDR; + break; + case 0x25: + p = ((uint16_t) (dev->regs[reg] & 0xfe)) << 2; + p &= 0xFF8; + if ((p < 0x100) || (p > 0x3F8)) + p = COM2_ADDR; + break; + + default: + break; } return p; } - static void w83877f_fdc_handler(w83877f_t *dev) { fdc_remove(dev->fdc); if (!(dev->regs[6] & 0x08) && (dev->regs[0x20] & 0xc0)) - fdc_set_base(dev->fdc, 0x03f0); + fdc_set_base(dev->fdc, FDC_PRIMARY_ADDR); } - static void w83877f_lpt_handler(w83877f_t *dev) { @@ -165,230 +167,229 @@ w83877f_lpt_handler(w83877f_t *dev) lpt1_remove(); if (!(dev->regs[4] & 0x80) && (dev->regs[0x23] & 0xc0)) - lpt1_init(make_port(dev, 0x23)); + lpt1_init(make_port(dev, 0x23)); lpt_irq = 0xff; lpt_irq = lpt_irqs[ECPIRQ]; if (lpt_irq == 0) - lpt_irq = PRTIQS; + lpt_irq = PRTIQS; lpt1_irq(lpt_irq); } - static void w83877f_serial_handler(w83877f_t *dev, int uart) { - int reg_mask = uart ? 0x10 : 0x20; - int reg_id = uart ? 0x25 : 0x24; - int irq_mask = uart ? 0x0f : 0xf0; - int irq_shift = uart ? 0 : 4; + int reg_mask = uart ? 0x10 : 0x20; + int reg_id = uart ? 0x25 : 0x24; + int irq_mask = uart ? 0x0f : 0xf0; + int irq_shift = uart ? 0 : 4; double clock_src = 24000000.0 / 13.0; serial_remove(dev->uart[uart]); if (!(dev->regs[4] & reg_mask) && (dev->regs[reg_id] & 0xc0)) - serial_setup(dev->uart[uart], make_port(dev, reg_id), (dev->regs[0x28] & irq_mask) >> irq_shift); + serial_setup(dev->uart[uart], make_port(dev, reg_id), (dev->regs[0x28] & irq_mask) >> irq_shift); if (dev->regs[0x19] & (0x02 >> uart)) { - clock_src = 14769000.0; - } else if (dev->regs[0x03] & (0x02 >> uart)) { - clock_src = 24000000.0 / 12.0; + clock_src = 14769000.0; + } else if (dev->regs[0x03] & (0x02 >> uart)) { + clock_src = 24000000.0 / 12.0; } else { - clock_src = 24000000.0 / 13.0; + clock_src = 24000000.0 / 13.0; } serial_set_clock_src(dev->uart[uart], clock_src); } - static void w83877f_write(uint16_t port, uint8_t val, void *priv) { - w83877f_t *dev = (w83877f_t *) priv; - uint8_t valxor = 0; - uint8_t max = 0x2A; + w83877f_t *dev = (w83877f_t *) priv; + uint8_t valxor = 0; + uint8_t max = 0x2A; if (port == 0x250) { - if (val == dev->key) - dev->locked = 1; - else - dev->locked = 0; - return; + if (val == dev->key) + dev->locked = 1; + else + dev->locked = 0; + return; } else if (port == 0x251) { - if (val <= max) - dev->cur_reg = val; - return; - } else if (port == 0x03f0) { - if ((val == dev->key) && !dev->locked) { - if (dev->key_times == 2) { - if (dev->tries) { - dev->locked = 1; - dev->tries = 0; - } else - dev->tries++; - } else { - dev->locked = 1; - dev->tries = 0; - } - } else { - if (dev->locked) { - if (val < max) - dev->cur_reg = val; - if (val == 0xaa) - dev->locked = 0; - } else { - if (dev->tries) - dev->tries = 0; - } - } - return; + if (val <= max) + dev->cur_reg = val; + return; + } else if (port == FDC_PRIMARY_ADDR) { + if ((val == dev->key) && !dev->locked) { + if (dev->key_times == 2) { + if (dev->tries) { + dev->locked = 1; + dev->tries = 0; + } else + dev->tries++; + } else { + dev->locked = 1; + dev->tries = 0; + } + } else { + if (dev->locked) { + if (val < max) + dev->cur_reg = val; + if (val == 0xaa) + dev->locked = 0; + } else { + if (dev->tries) + dev->tries = 0; + } + } + return; } else if ((port == 0x252) || (port == 0x3f1)) { - if (dev->locked) { - if (dev->rw_locked) - return; - if ((dev->cur_reg >= 0x26) && (dev->cur_reg <= 0x27)) - return; - if (dev->cur_reg == 0x29) - return; - if (dev->cur_reg == 6) - val &= 0xF3; - valxor = val ^ dev->regs[dev->cur_reg]; - dev->regs[dev->cur_reg] = val; - } else - return; + if (dev->locked) { + if (dev->rw_locked) + return; + if ((dev->cur_reg >= 0x26) && (dev->cur_reg <= 0x27)) + return; + if (dev->cur_reg == 0x29) + return; + if (dev->cur_reg == 6) + val &= 0xF3; + valxor = val ^ dev->regs[dev->cur_reg]; + dev->regs[dev->cur_reg] = val; + } else + return; } switch (dev->cur_reg) { - case 0: - if (valxor & 0x0c) - w83877f_lpt_handler(dev); - break; - case 1: - if (valxor & 0x80) - fdc_set_swap(dev->fdc, (dev->regs[1] & 0x80) ? 1 : 0); - break; - case 3: - if (valxor & 0x02) - w83877f_serial_handler(dev, 0); - if (valxor & 0x01) - w83877f_serial_handler(dev, 1); - break; - case 4: - if (valxor & 0x10) - w83877f_serial_handler(dev, 1); - if (valxor & 0x20) - w83877f_serial_handler(dev, 0); - if (valxor & 0x80) - w83877f_lpt_handler(dev); - break; - case 6: - if (valxor & 0x08) - w83877f_fdc_handler(dev); - break; - case 7: - if (valxor & 0x03) - fdc_update_rwc(dev->fdc, 0, FDDA_TYPE); - if (valxor & 0x0c) - fdc_update_rwc(dev->fdc, 1, FDDB_TYPE); - if (valxor & 0x30) - fdc_update_rwc(dev->fdc, 2, FDDC_TYPE); - if (valxor & 0xc0) - fdc_update_rwc(dev->fdc, 3, FDDD_TYPE); - break; - case 8: - if (valxor & 0x03) - fdc_update_boot_drive(dev->fdc, FD_BOOT); - if (valxor & 0x10) - fdc_set_swwp(dev->fdc, SWWP ? 1 : 0); - if (valxor & 0x20) - fdc_set_diswr(dev->fdc, DISFDDWR ? 1 : 0); - break; - case 9: - if (valxor & 0x20) - fdc_update_enh_mode(dev->fdc, EN3MODE ? 1 : 0); - if (valxor & 0x40) - dev->rw_locked = (val & 0x40) ? 1 : 0; - if (valxor & 0x80) - w83877f_lpt_handler(dev); - break; - case 0xB: - if (valxor & 1) - fdc_update_drv2en(dev->fdc, DRV2EN_NEG ? 0 : 1); - if (valxor & 2) - fdc_update_densel_polarity(dev->fdc, INVERTZ ? 1 : 0); - break; - case 0xC: - if (valxor & 0x20) - w83877f_remap(dev); - break; - case 0x16: - if (valxor & 1) - w83877f_remap(dev); - break; - case 0x19: - if (valxor & 0x02) - w83877f_serial_handler(dev, 0); - if (valxor & 0x01) - w83877f_serial_handler(dev, 1); - break; - case 0x20: - if (valxor) - w83877f_fdc_handler(dev); - break; - case 0x23: - if (valxor) - w83877f_lpt_handler(dev); - break; - case 0x24: - if (valxor & 0xfe) - w83877f_serial_handler(dev, 0); - break; - case 0x25: - if (valxor & 0xfe) - w83877f_serial_handler(dev, 1); - break; - case 0x27: - if (valxor & 0xef) - w83877f_lpt_handler(dev); - break; - case 0x28: - if (valxor & 0xf) { - if ((dev->regs[0x28] & 0x0f) == 0) - dev->regs[0x28] |= 0x03; - w83877f_serial_handler(dev, 1); - } - if (valxor & 0xf0) { - if ((dev->regs[0x28] & 0xf0) == 0) - dev->regs[0x28] |= 0x40; - w83877f_serial_handler(dev, 0); - } - break; + case 0: + if (valxor & 0x0c) + w83877f_lpt_handler(dev); + break; + case 1: + if (valxor & 0x80) + fdc_set_swap(dev->fdc, (dev->regs[1] & 0x80) ? 1 : 0); + break; + case 3: + if (valxor & 0x02) + w83877f_serial_handler(dev, 0); + if (valxor & 0x01) + w83877f_serial_handler(dev, 1); + break; + case 4: + if (valxor & 0x10) + w83877f_serial_handler(dev, 1); + if (valxor & 0x20) + w83877f_serial_handler(dev, 0); + if (valxor & 0x80) + w83877f_lpt_handler(dev); + break; + case 6: + if (valxor & 0x08) + w83877f_fdc_handler(dev); + break; + case 7: + if (valxor & 0x03) + fdc_update_rwc(dev->fdc, 0, FDDA_TYPE); + if (valxor & 0x0c) + fdc_update_rwc(dev->fdc, 1, FDDB_TYPE); + if (valxor & 0x30) + fdc_update_rwc(dev->fdc, 2, FDDC_TYPE); + if (valxor & 0xc0) + fdc_update_rwc(dev->fdc, 3, FDDD_TYPE); + break; + case 8: + if (valxor & 0x03) + fdc_update_boot_drive(dev->fdc, FD_BOOT); + if (valxor & 0x10) + fdc_set_swwp(dev->fdc, SWWP ? 1 : 0); + if (valxor & 0x20) + fdc_set_diswr(dev->fdc, DISFDDWR ? 1 : 0); + break; + case 9: + if (valxor & 0x20) + fdc_update_enh_mode(dev->fdc, EN3MODE ? 1 : 0); + if (valxor & 0x40) + dev->rw_locked = (val & 0x40) ? 1 : 0; + if (valxor & 0x80) + w83877f_lpt_handler(dev); + break; + case 0xB: + if (valxor & 1) + fdc_update_drv2en(dev->fdc, DRV2EN_NEG ? 0 : 1); + if (valxor & 2) + fdc_update_densel_polarity(dev->fdc, INVERTZ ? 1 : 0); + break; + case 0xC: + if (valxor & 0x20) + w83877f_remap(dev); + break; + case 0x16: + if (valxor & 1) + w83877f_remap(dev); + break; + case 0x19: + if (valxor & 0x02) + w83877f_serial_handler(dev, 0); + if (valxor & 0x01) + w83877f_serial_handler(dev, 1); + break; + case 0x20: + if (valxor) + w83877f_fdc_handler(dev); + break; + case 0x23: + if (valxor) + w83877f_lpt_handler(dev); + break; + case 0x24: + if (valxor & 0xfe) + w83877f_serial_handler(dev, 0); + break; + case 0x25: + if (valxor & 0xfe) + w83877f_serial_handler(dev, 1); + break; + case 0x27: + if (valxor & 0xef) + w83877f_lpt_handler(dev); + break; + case 0x28: + if (valxor & 0xf) { + if ((dev->regs[0x28] & 0x0f) == 0) + dev->regs[0x28] |= 0x03; + w83877f_serial_handler(dev, 1); + } + if (valxor & 0xf0) { + if ((dev->regs[0x28] & 0xf0) == 0) + dev->regs[0x28] |= 0x40; + w83877f_serial_handler(dev, 0); + } + break; + + default: + break; } } - static uint8_t w83877f_read(uint16_t port, void *priv) { w83877f_t *dev = (w83877f_t *) priv; - uint8_t ret = 0xff; + uint8_t ret = 0xff; if (dev->locked) { - if ((port == 0x3f0) || (port == 0x251)) - ret = dev->cur_reg; - else if ((port == 0x3f1) || (port == 0x252)) { - if (dev->cur_reg == 7) - ret = (fdc_get_rwc(dev->fdc, 0) | (fdc_get_rwc(dev->fdc, 1) << 2) | (fdc_get_rwc(dev->fdc, 2) << 4) | (fdc_get_rwc(dev->fdc, 3) << 6)); - else if ((dev->cur_reg >= 0x18) || !dev->rw_locked) - ret = dev->regs[dev->cur_reg]; - } + if ((port == FDC_PRIMARY_ADDR) || (port == 0x251)) + ret = dev->cur_reg; + else if ((port == 0x3f1) || (port == 0x252)) { + if (dev->cur_reg == 7) + ret = (fdc_get_rwc(dev->fdc, 0) | (fdc_get_rwc(dev->fdc, 1) << 2) | (fdc_get_rwc(dev->fdc, 2) << 4) | (fdc_get_rwc(dev->fdc, 3) << 6)); + else if ((dev->cur_reg >= 0x18) || !dev->rw_locked) + ret = dev->regs[dev->cur_reg]; + } } return ret; } - static void w83877f_reset(w83877f_t *dev) { @@ -403,12 +404,12 @@ w83877f_reset(w83877f_t *dev) dev->regs[0x0d] = 0xA3; dev->regs[0x16] = dev->reg_init & 0xff; dev->regs[0x1e] = 0x81; - dev->regs[0x20] = (0x3f0 >> 2) & 0xfc; + dev->regs[0x20] = (FDC_PRIMARY_ADDR >> 2) & 0xfc; dev->regs[0x21] = (0x1f0 >> 2) & 0xfc; dev->regs[0x22] = ((0x3f6 >> 2) & 0xfc) | 1; - dev->regs[0x23] = (0x378 >> 2); - dev->regs[0x24] = (0x3f8 >> 2) & 0xfe; - dev->regs[0x25] = (0x2f8 >> 2) & 0xfe; + dev->regs[0x23] = (LPT1_ADDR >> 2); + dev->regs[0x24] = (COM1_ADDR >> 2) & 0xfe; + dev->regs[0x25] = (COM2_ADDR >> 2) & 0xfe; dev->regs[0x26] = (2 << 4) | 4; dev->regs[0x27] = (2 << 4) | 5; dev->regs[0x28] = (4 << 4) | 3; @@ -421,17 +422,16 @@ w83877f_reset(w83877f_t *dev) w83877f_serial_handler(dev, 0); w83877f_serial_handler(dev, 1); - dev->base_address = 0x3f0; - dev->key = 0x89; - dev->key_times = 1; + dev->base_address = FDC_PRIMARY_ADDR; + dev->key = 0x89; + dev->key_times = 1; w83877f_remap(dev); - dev->locked = 0; + dev->locked = 0; dev->rw_locked = 0; } - static void w83877f_close(void *priv) { @@ -440,7 +440,6 @@ w83877f_close(void *priv) free(dev); } - static void * w83877f_init(const device_t *info) { @@ -459,46 +458,58 @@ w83877f_init(const device_t *info) return dev; } - const device_t w83877f_device = { - "Winbond W83877F Super I/O", - "w83877f", - 0, - 0x0a05, - w83877f_init, w83877f_close, NULL, - { NULL }, NULL, NULL, - NULL + .name = "Winbond W83877F Super I/O", + .internal_name = "w83877f", + .flags = 0, + .local = 0x0a05, + .init = w83877f_init, + .close = w83877f_close, + .reset = NULL, + { .available = NULL }, + .speed_changed = NULL, + .force_redraw = NULL, + .config = NULL }; - const device_t w83877f_president_device = { - "Winbond W83877F Super I/O (President)", - "w83877f_president", - 0, - 0x0a04, - w83877f_init, w83877f_close, NULL, - { NULL }, NULL, NULL, - NULL + .name = "Winbond W83877F Super I/O (President)", + .internal_name = "w83877f_president", + .flags = 0, + .local = 0x0a04, + .init = w83877f_init, + .close = w83877f_close, + .reset = NULL, + { .available = NULL }, + .speed_changed = NULL, + .force_redraw = NULL, + .config = NULL }; - const device_t w83877tf_device = { - "Winbond W83877TF Super I/O", - "w83877tf", - 0, - 0x0c04, - w83877f_init, w83877f_close, NULL, - { NULL }, NULL, NULL, - NULL + .name = "Winbond W83877TF Super I/O", + .internal_name = "w83877tf", + .flags = 0, + .local = 0x0c04, + .init = w83877f_init, + .close = w83877f_close, + .reset = NULL, + { .available = NULL }, + .speed_changed = NULL, + .force_redraw = NULL, + .config = NULL }; - const device_t w83877tf_acorp_device = { - "Winbond W83877TF Super I/O", - "w83877tf_acorp", - 0, - 0x0c05, - w83877f_init, w83877f_close, NULL, - { NULL }, NULL, NULL, - NULL + .name = "Winbond W83877TF Super I/O", + .internal_name = "w83877tf_acorp", + .flags = 0, + .local = 0x0c05, + .init = w83877f_init, + .close = w83877f_close, + .reset = NULL, + { .available = NULL }, + .speed_changed = NULL, + .force_redraw = NULL, + .config = NULL }; diff --git a/src/sio/sio_w83977f.c b/src/sio/sio_w83977f.c index 66678d741..063f0ca69 100644 --- a/src/sio/sio_w83977f.c +++ b/src/sio/sio_w83977f.c @@ -1,20 +1,20 @@ /* - * 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. + * 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. + * This file is part of the 86Box distribution. * - * Emulation of the Winbond W83977F Super I/O Chip. + * Emulation of the Winbond W83977F Super I/O Chip. * - * Winbond W83977F Super I/O Chip - * Used by the Award 430TX + * Winbond W83977F Super I/O Chip + * Used by the Award 430TX * * * - * Author: Miran Grca, - * Copyright 2016-2020 Miran Grca. + * Authors: Miran Grca, + * Copyright 2016-2020 Miran Grca. */ #include #include @@ -34,348 +34,378 @@ #include <86box/fdc.h> #include <86box/sio.h> +#define HEFRAS (dev->regs[0x26] & 0x40) -#define HEFRAS (dev->regs[0x26] & 0x40) - - -typedef struct { - uint8_t id, tries, - regs[48], - dev_regs[256][208]; - int locked, rw_locked, - cur_reg, base_address, - type, hefras; - fdc_t *fdc; +typedef struct w83977f_t { + uint8_t id; + uint8_t tries; + uint8_t regs[48]; + uint8_t dev_regs[256][208]; + int locked; + int rw_locked; + int cur_reg; + int base_address; + int type; + int hefras; + fdc_t *fdc; serial_t *uart[2]; } w83977f_t; +static int next_id = 0; -static int next_id = 0; - - -static void w83977f_write(uint16_t port, uint8_t val, void *priv); -static uint8_t w83977f_read(uint16_t port, void *priv); - +static void w83977f_write(uint16_t port, uint8_t val, void *priv); +static uint8_t w83977f_read(uint16_t port, void *priv); static void w83977f_remap(w83977f_t *dev) { - io_removehandler(0x3f0, 0x0002, - w83977f_read, NULL, NULL, w83977f_write, NULL, NULL, dev); - io_removehandler(0x370, 0x0002, - w83977f_read, NULL, NULL, w83977f_write, NULL, NULL, dev); + io_removehandler(FDC_PRIMARY_ADDR, 0x0002, + w83977f_read, NULL, NULL, w83977f_write, NULL, NULL, dev); + io_removehandler(FDC_SECONDARY_ADDR, 0x0002, + w83977f_read, NULL, NULL, w83977f_write, NULL, NULL, dev); - dev->base_address = (HEFRAS ? 0x370 : 0x3f0); + dev->base_address = (HEFRAS ? FDC_SECONDARY_ADDR : FDC_PRIMARY_ADDR); io_sethandler(dev->base_address, 0x0002, - w83977f_read, NULL, NULL, w83977f_write, NULL, NULL, dev); + w83977f_read, NULL, NULL, w83977f_write, NULL, NULL, dev); } - static uint8_t get_lpt_length(w83977f_t *dev) { uint8_t length = 4; - if (((dev->dev_regs[1][0xc0] & 0x07) != 0x00) && ((dev->dev_regs[1][0xc0] & 0x07) != 0x02) && - ((dev->dev_regs[1][0xc0] & 0x07) != 0x04)) - length = 8; + if (((dev->dev_regs[1][0xc0] & 0x07) != 0x00) && ((dev->dev_regs[1][0xc0] & 0x07) != 0x02) && ((dev->dev_regs[1][0xc0] & 0x07) != 0x04)) + length = 8; return length; } - static void w83977f_fdc_handler(w83977f_t *dev) { uint16_t io_base = (dev->dev_regs[0][0x30] << 8) | dev->dev_regs[0][0x31]; if (dev->id == 1) - return; + return; fdc_remove(dev->fdc); if ((dev->dev_regs[0][0x00] & 0x01) && (dev->regs[0x22] & 0x01) && (io_base >= 0x100) && (io_base <= 0xff8)) - fdc_set_base(dev->fdc, io_base); + fdc_set_base(dev->fdc, io_base); fdc_set_irq(dev->fdc, dev->dev_regs[0][0x40] & 0x0f); } - static void w83977f_lpt_handler(w83977f_t *dev) { - uint16_t io_mask, io_base = (dev->dev_regs[1][0x30] << 8) | dev->dev_regs[1][0x31]; - int io_len = get_lpt_length(dev); + uint16_t io_mask; + uint16_t io_base = (dev->dev_regs[1][0x30] << 8) | dev->dev_regs[1][0x31]; + int io_len = get_lpt_length(dev); io_base &= (0xff8 | io_len); io_mask = 0xffc; if (io_len == 8) - io_mask = 0xff8; + io_mask = 0xff8; if (dev->id == 1) { - lpt2_remove(); + lpt2_remove(); - if ((dev->dev_regs[1][0x00] & 0x01) && (dev->regs[0x22] & 0x08) && (io_base >= 0x100) && (io_base <= io_mask)) - lpt2_init(io_base); + if ((dev->dev_regs[1][0x00] & 0x01) && (dev->regs[0x22] & 0x08) && (io_base >= 0x100) && (io_base <= io_mask)) + lpt2_init(io_base); - lpt2_irq(dev->dev_regs[1][0x40] & 0x0f); + lpt2_irq(dev->dev_regs[1][0x40] & 0x0f); } else { - lpt1_remove(); + lpt1_remove(); - if ((dev->dev_regs[1][0x00] & 0x01) && (dev->regs[0x22] & 0x08) && (io_base >= 0x100) && (io_base <= io_mask)) - lpt1_init(io_base); + if ((dev->dev_regs[1][0x00] & 0x01) && (dev->regs[0x22] & 0x08) && (io_base >= 0x100) && (io_base <= io_mask)) + lpt1_init(io_base); - lpt1_irq(dev->dev_regs[1][0x40] & 0x0f); + lpt1_irq(dev->dev_regs[1][0x40] & 0x0f); } } - static void w83977f_serial_handler(w83977f_t *dev, int uart) { - uint16_t io_base = (dev->dev_regs[2 + uart][0x30] << 8) | dev->dev_regs[2 + uart][0x31]; - double clock_src = 24000000.0 / 13.0; + uint16_t io_base = (dev->dev_regs[2 + uart][0x30] << 8) | dev->dev_regs[2 + uart][0x31]; + double clock_src = 24000000.0 / 13.0; serial_remove(dev->uart[uart]); if ((dev->dev_regs[2 + uart][0x00] & 0x01) && (dev->regs[0x22] & (0x10 << uart)) && (io_base >= 0x100) && (io_base <= 0xff8)) - serial_setup(dev->uart[uart], io_base, dev->dev_regs[2 + uart][0x40] & 0x0f); + serial_setup(dev->uart[uart], io_base, dev->dev_regs[2 + uart][0x40] & 0x0f); switch (dev->dev_regs[2 + uart][0xc0] & 0x03) { - case 0x00: - clock_src = 24000000.0 / 13.0; - break; - case 0x01: - clock_src = 24000000.0 / 12.0; - break; - case 0x02: - clock_src = 24000000.0 / 1.0; - break; - case 0x03: - clock_src = 24000000.0 / 1.625; - break; + case 0x00: + clock_src = 24000000.0 / 13.0; + break; + case 0x01: + clock_src = 24000000.0 / 12.0; + break; + case 0x02: + clock_src = 24000000.0 / 1.0; + break; + case 0x03: + clock_src = 24000000.0 / 1.625; + break; + + default: + break; } serial_set_clock_src(dev->uart[uart], clock_src); } - static void w83977f_write(uint16_t port, uint8_t val, void *priv) { - w83977f_t *dev = (w83977f_t *) priv; - uint8_t index = (port & 1) ? 0 : 1; - uint8_t valxor = 0; - uint8_t ld = dev->regs[7]; + w83977f_t *dev = (w83977f_t *) priv; + uint8_t index = (port & 1) ? 0 : 1; + uint8_t valxor = 0; + uint8_t ld = dev->regs[7]; if (index) { - if ((val == 0x87) && !dev->locked) { - if (dev->tries) { - dev->locked = 1; - dev->tries = 0; - } else - dev->tries++; - } else { - if (dev->locked) { - if (val == 0xaa) - dev->locked = 0; - else - dev->cur_reg = val; - } else { - if (dev->tries) - dev->tries = 0; - } - } - return; + if ((val == 0x87) && !dev->locked) { + if (dev->tries) { + dev->locked = 1; + dev->tries = 0; + } else + dev->tries++; + } else { + if (dev->locked) { + if (val == 0xaa) + dev->locked = 0; + else + dev->cur_reg = val; + } else { + if (dev->tries) + dev->tries = 0; + } + } + return; } else { - if (dev->locked) { - if (dev->rw_locked) - return; - if (dev->cur_reg >= 0x30) { - valxor = val ^ dev->dev_regs[ld][dev->cur_reg - 0x30]; - dev->dev_regs[ld][dev->cur_reg - 0x30] = val; - } else { - valxor = val ^ dev->regs[dev->cur_reg]; - dev->regs[dev->cur_reg] = val; - } - } else - return; + if (dev->locked) { + if (dev->rw_locked) + return; + if (dev->cur_reg >= 0x30) { + valxor = val ^ dev->dev_regs[ld][dev->cur_reg - 0x30]; + dev->dev_regs[ld][dev->cur_reg - 0x30] = val; + } else { + valxor = val ^ dev->regs[dev->cur_reg]; + dev->regs[dev->cur_reg] = val; + } + } else + return; } switch (dev->cur_reg) { - case 0x02: - /* if (valxor & 0x02) - softresetx86(); */ - break; - case 0x22: - if (valxor & 0x20) - w83977f_serial_handler(dev, 1); - if (valxor & 0x10) - w83977f_serial_handler(dev, 0); - if (valxor & 0x08) - w83977f_lpt_handler(dev); - if (valxor & 0x01) - w83977f_fdc_handler(dev); - break; - case 0x26: - if (valxor & 0x40) - w83977f_remap(dev); - if (valxor & 0x20) - dev->rw_locked = (val & 0x20) ? 1 : 0; - break; - case 0x30: - if (valxor & 0x01) switch (ld) { - case 0x00: - w83977f_fdc_handler(dev); - break; - case 0x01: - w83977f_lpt_handler(dev); - break; - case 0x02: case 0x03: - w83977f_serial_handler(dev, ld - 2); - break; - } - break; - case 0x60: case 0x61: - if (valxor & 0xff) switch (ld) { - case 0x00: - w83977f_fdc_handler(dev); - break; - case 0x01: - w83977f_lpt_handler(dev); - break; - case 0x02: case 0x03: - w83977f_serial_handler(dev, ld - 2); - break; - } - break; - case 0x70: - if (valxor & 0x0f) switch (ld) { - case 0x00: - w83977f_fdc_handler(dev); - break; - case 0x01: - w83977f_lpt_handler(dev); - break; - case 0x02: case 0x03: - w83977f_serial_handler(dev, ld - 2); - break; - } - break; - case 0xf0: - switch (ld) { - case 0x00: - if (dev->id == 1) - break; + case 0x02: +#if 0 + if (valxor & 0x02) + softresetx86(); +#endif + break; + case 0x22: + if (valxor & 0x20) + w83977f_serial_handler(dev, 1); + if (valxor & 0x10) + w83977f_serial_handler(dev, 0); + if (valxor & 0x08) + w83977f_lpt_handler(dev); + if (valxor & 0x01) + w83977f_fdc_handler(dev); + break; + case 0x26: + if (valxor & 0x40) + w83977f_remap(dev); + if (valxor & 0x20) + dev->rw_locked = (val & 0x20) ? 1 : 0; + break; + case 0x30: + if (valxor & 0x01) + switch (ld) { + case 0x00: + w83977f_fdc_handler(dev); + break; + case 0x01: + w83977f_lpt_handler(dev); + break; + case 0x02: + case 0x03: + w83977f_serial_handler(dev, ld - 2); + break; - if (!dev->id && (valxor & 0x20)) - fdc_update_drv2en(dev->fdc, (val & 0x20) ? 0 : 1); - if (!dev->id && (valxor & 0x10)) - fdc_set_swap(dev->fdc, (val & 0x10) ? 1 : 0); - if (!dev->id && (valxor & 0x01)) - fdc_update_enh_mode(dev->fdc, (val & 0x01) ? 1 : 0); - break; - case 0x01: - if (valxor & 0x07) - w83977f_lpt_handler(dev); - break; - case 0x02: case 0x03: - if (valxor & 0x03) - w83977f_serial_handler(dev, ld - 2); - break; - } - break; - case 0xf1: - switch (ld) { - case 0x00: - if (dev->id == 1) - break; + default: + break; + } + break; + case 0x60: + case 0x61: + if (valxor & 0xff) + switch (ld) { + case 0x00: + w83977f_fdc_handler(dev); + break; + case 0x01: + w83977f_lpt_handler(dev); + break; + case 0x02: + case 0x03: + w83977f_serial_handler(dev, ld - 2); + break; - if (!dev->id && (valxor & 0xc0)) - fdc_update_boot_drive(dev->fdc, (val & 0xc0) >> 6); - if (!dev->id && (valxor & 0x0c)) - fdc_update_densel_force(dev->fdc, (val & 0x0c) >> 2); - if (!dev->id && (valxor & 0x02)) - fdc_set_diswr(dev->fdc, (val & 0x02) ? 1 : 0); - if (!dev->id && (valxor & 0x01)) - fdc_set_swwp(dev->fdc, (val & 0x01) ? 1 : 0); - break; - } - break; - case 0xf2: - switch (ld) { - case 0x00: - if (dev->id == 1) - break; + default: + break; + } + break; + case 0x70: + if (valxor & 0x0f) + switch (ld) { + case 0x00: + w83977f_fdc_handler(dev); + break; + case 0x01: + w83977f_lpt_handler(dev); + break; + case 0x02: + case 0x03: + w83977f_serial_handler(dev, ld - 2); + break; - if (!dev->id && (valxor & 0xc0)) - fdc_update_rwc(dev->fdc, 3, (val & 0xc0) >> 6); - if (!dev->id && (valxor & 0x30)) - fdc_update_rwc(dev->fdc, 2, (val & 0x30) >> 4); - if (!dev->id && (valxor & 0x0c)) - fdc_update_rwc(dev->fdc, 1, (val & 0x0c) >> 2); - if (!dev->id && (valxor & 0x03)) - fdc_update_rwc(dev->fdc, 0, val & 0x03); - break; - } - break; - case 0xf4: case 0xf5: case 0xf6: case 0xf7: - switch (ld) { - case 0x00: - if (dev->id == 1) - break; + default: + break; + } + break; + case 0xf0: + switch (ld) { + case 0x00: + if (dev->id == 1) + break; - if (!dev->id && (valxor & 0x18)) - fdc_update_drvrate(dev->fdc, dev->cur_reg & 0x03, (val & 0x18) >> 3); - break; - } - break; + if (!dev->id && (valxor & 0x20)) + fdc_update_drv2en(dev->fdc, (val & 0x20) ? 0 : 1); + if (!dev->id && (valxor & 0x10)) + fdc_set_swap(dev->fdc, (val & 0x10) ? 1 : 0); + if (!dev->id && (valxor & 0x01)) + fdc_update_enh_mode(dev->fdc, (val & 0x01) ? 1 : 0); + break; + case 0x01: + if (valxor & 0x07) + w83977f_lpt_handler(dev); + break; + case 0x02: + case 0x03: + if (valxor & 0x03) + w83977f_serial_handler(dev, ld - 2); + break; + + default: + break; + } + break; + case 0xf1: + switch (ld) { + case 0x00: + if (dev->id == 1) + break; + + if (!dev->id && (valxor & 0xc0)) + fdc_update_boot_drive(dev->fdc, (val & 0xc0) >> 6); + if (!dev->id && (valxor & 0x0c)) + fdc_update_densel_force(dev->fdc, (val & 0x0c) >> 2); + if (!dev->id && (valxor & 0x02)) + fdc_set_diswr(dev->fdc, (val & 0x02) ? 1 : 0); + if (!dev->id && (valxor & 0x01)) + fdc_set_swwp(dev->fdc, (val & 0x01) ? 1 : 0); + break; + + default: + break; + } + break; + case 0xf2: + switch (ld) { + case 0x00: + if (dev->id == 1) + break; + + if (!dev->id && (valxor & 0xc0)) + fdc_update_rwc(dev->fdc, 3, (val & 0xc0) >> 6); + if (!dev->id && (valxor & 0x30)) + fdc_update_rwc(dev->fdc, 2, (val & 0x30) >> 4); + if (!dev->id && (valxor & 0x0c)) + fdc_update_rwc(dev->fdc, 1, (val & 0x0c) >> 2); + if (!dev->id && (valxor & 0x03)) + fdc_update_rwc(dev->fdc, 0, val & 0x03); + break; + + default: + break; + } + break; + case 0xf4: + case 0xf5: + case 0xf6: + case 0xf7: + switch (ld) { + case 0x00: + if (dev->id == 1) + break; + + if (!dev->id && (valxor & 0x18)) + fdc_update_drvrate(dev->fdc, dev->cur_reg & 0x03, (val & 0x18) >> 3); + break; + + default: + break; + } + break; + + default: + break; } } - static uint8_t w83977f_read(uint16_t port, void *priv) { - w83977f_t *dev = (w83977f_t *) priv; - uint8_t ret = 0xff; - uint8_t index = (port & 1) ? 0 : 1; - uint8_t ld = dev->regs[7]; + w83977f_t *dev = (w83977f_t *) priv; + uint8_t ret = 0xff; + uint8_t index = (port & 1) ? 0 : 1; + uint8_t ld = dev->regs[7]; if (dev->locked) { - if (index) - ret = dev->cur_reg; - else { - if (!dev->rw_locked) { - if (!dev->id && ((dev->cur_reg == 0xf2) && (ld == 0x00))) - ret = (fdc_get_rwc(dev->fdc, 0) | (fdc_get_rwc(dev->fdc, 1) << 2) | (fdc_get_rwc(dev->fdc, 2) << 4) | (fdc_get_rwc(dev->fdc, 3) << 6)); - else if (dev->cur_reg >= 0x30) - ret = dev->dev_regs[ld][dev->cur_reg - 0x30]; - else - ret = dev->regs[dev->cur_reg]; - } - } + if (index) + ret = dev->cur_reg; + else { + if (!dev->rw_locked) { + if (!dev->id && ((dev->cur_reg == 0xf2) && (ld == 0x00))) + ret = (fdc_get_rwc(dev->fdc, 0) | (fdc_get_rwc(dev->fdc, 1) << 2) | (fdc_get_rwc(dev->fdc, 2) << 4) | (fdc_get_rwc(dev->fdc, 3) << 6)); + else if (dev->cur_reg >= 0x30) + ret = dev->dev_regs[ld][dev->cur_reg - 0x30]; + else + ret = dev->regs[dev->cur_reg]; + } + } } return ret; } - static void w83977f_reset(w83977f_t *dev) { - int i; - memset(dev->regs, 0, 48); - for (i = 0; i < 256; i++) - memset(dev->dev_regs[i], 0, 208); + for (uint16_t i = 0; i < 256; i++) + memset(dev->dev_regs[i], 0, 208); if (dev->type < 2) { - dev->regs[0x20] = 0x97; - dev->regs[0x21] = dev->type ? 0x73 : 0x71; + dev->regs[0x20] = 0x97; + dev->regs[0x21] = dev->type ? 0x73 : 0x71; } else { - dev->regs[0x20] = 0x52; - dev->regs[0x21] = 0xf0; + dev->regs[0x20] = 0x52; + dev->regs[0x21] = 0xf0; } dev->regs[0x22] = 0xff; dev->regs[0x24] = dev->type ? 0x84 : 0xa4; @@ -385,137 +415,159 @@ w83977f_reset(w83977f_t *dev) /* Logical Device 0 (FDC) */ dev->dev_regs[0][0x00] = 0x01; if (!dev->type) - dev->dev_regs[0][0x01] = 0x02; + dev->dev_regs[0][0x01] = 0x02; if (next_id == 1) { - dev->dev_regs[0][0x30] = 0x03; dev->dev_regs[0][0x31] = 0x70; + dev->dev_regs[0][0x30] = 0x03; + dev->dev_regs[0][0x31] = 0x70; } else { - dev->dev_regs[0][0x30] = 0x03; dev->dev_regs[0][0x31] = 0xf0; + dev->dev_regs[0][0x30] = 0x03; + dev->dev_regs[0][0x31] = 0xf0; } dev->dev_regs[0][0x40] = 0x06; if (!dev->type) - dev->dev_regs[0][0x41] = 0x02; /* Read-only */ + dev->dev_regs[0][0x41] = 0x02; /* Read-only */ dev->dev_regs[0][0x44] = 0x02; dev->dev_regs[0][0xc0] = 0x0e; /* Logical Device 1 (Parallel Port) */ dev->dev_regs[1][0x00] = 0x01; if (!dev->type) - dev->dev_regs[1][0x01] = 0x02; + dev->dev_regs[1][0x01] = 0x02; if (next_id == 1) { - dev->dev_regs[1][0x30] = 0x02; dev->dev_regs[1][0x31] = 0x78; - dev->dev_regs[1][0x40] = 0x05; + dev->dev_regs[1][0x30] = 0x02; + dev->dev_regs[1][0x31] = 0x78; + dev->dev_regs[1][0x40] = 0x05; } else { - dev->dev_regs[1][0x30] = 0x03; dev->dev_regs[1][0x31] = 0x78; - dev->dev_regs[1][0x40] = 0x07; + dev->dev_regs[1][0x30] = 0x03; + dev->dev_regs[1][0x31] = 0x78; + dev->dev_regs[1][0x40] = 0x07; } if (!dev->type) - dev->dev_regs[1][0x41] = 0x01 /*0x02*/; /* Read-only */ + dev->dev_regs[1][0x41] = 0x01 /*0x02*/; /* Read-only */ dev->dev_regs[1][0x44] = 0x04; - dev->dev_regs[1][0xc0] = 0x3c; /* The datasheet says default is 3f, but also default is printer mode. */ + dev->dev_regs[1][0xc0] = 0x3c; /* The datasheet says default is 3f, but also default is printer mode. */ /* Logical Device 2 (UART A) */ dev->dev_regs[2][0x00] = 0x01; if (!dev->type) - dev->dev_regs[2][0x01] = 0x02; + dev->dev_regs[2][0x01] = 0x02; if (next_id == 1) { - dev->dev_regs[2][0x30] = 0x03; dev->dev_regs[2][0x31] = 0xe8; + dev->dev_regs[2][0x30] = 0x03; + dev->dev_regs[2][0x31] = 0xe8; } else { - dev->dev_regs[2][0x30] = 0x03; dev->dev_regs[2][0x31] = 0xf8; + dev->dev_regs[2][0x30] = 0x03; + dev->dev_regs[2][0x31] = 0xf8; } dev->dev_regs[2][0x40] = 0x04; if (!dev->type) - dev->dev_regs[2][0x41] = 0x02; /* Read-only */ + dev->dev_regs[2][0x41] = 0x02; /* Read-only */ /* Logical Device 3 (UART B) */ dev->dev_regs[3][0x00] = 0x01; if (!dev->type) - dev->dev_regs[3][0x01] = 0x02; + dev->dev_regs[3][0x01] = 0x02; if (next_id == 1) { - dev->dev_regs[3][0x30] = 0x02; dev->dev_regs[3][0x31] = 0xe8; + dev->dev_regs[3][0x30] = 0x02; + dev->dev_regs[3][0x31] = 0xe8; } else { - dev->dev_regs[3][0x30] = 0x02; dev->dev_regs[3][0x31] = 0xf8; + dev->dev_regs[3][0x30] = 0x02; + dev->dev_regs[3][0x31] = 0xf8; } dev->dev_regs[3][0x40] = 0x03; if (!dev->type) - dev->dev_regs[3][0x41] = 0x02; /* Read-only */ + dev->dev_regs[3][0x41] = 0x02; /* Read-only */ /* Logical Device 4 (RTC) */ if (!dev->type) { - dev->dev_regs[4][0x00] = 0x01; - dev->dev_regs[4][0x01] = 0x02; - dev->dev_regs[4][0x30] = 0x00; dev->dev_regs[4][0x31] = 0x70; - dev->dev_regs[4][0x40] = 0x08; - dev->dev_regs[4][0x41] = 0x02; /* Read-only */ + dev->dev_regs[4][0x00] = 0x01; + dev->dev_regs[4][0x01] = 0x02; + dev->dev_regs[4][0x30] = 0x00; + dev->dev_regs[4][0x31] = 0x70; + dev->dev_regs[4][0x40] = 0x08; + dev->dev_regs[4][0x41] = 0x02; /* Read-only */ } /* Logical Device 5 (KBC) */ dev->dev_regs[5][0x00] = 0x01; if (!dev->type) - dev->dev_regs[5][0x01] = 0x02; - dev->dev_regs[5][0x30] = 0x00; dev->dev_regs[5][0x31] = 0x60; - dev->dev_regs[5][0x32] = 0x00; dev->dev_regs[5][0x33] = 0x64; + dev->dev_regs[5][0x01] = 0x02; + dev->dev_regs[5][0x30] = 0x00; + dev->dev_regs[5][0x31] = 0x60; + dev->dev_regs[5][0x32] = 0x00; + dev->dev_regs[5][0x33] = 0x64; dev->dev_regs[5][0x40] = 0x01; if (!dev->type) - dev->dev_regs[5][0x41] = 0x02; /* Read-only */ + dev->dev_regs[5][0x41] = 0x02; /* Read-only */ dev->dev_regs[5][0x42] = 0x0c; if (!dev->type) - dev->dev_regs[5][0x43] = 0x02; /* Read-only? */ + dev->dev_regs[5][0x43] = 0x02; /* Read-only? */ dev->dev_regs[5][0xc0] = dev->type ? 0x83 : 0x40; /* Logical Device 6 (IR) = UART C */ if (!dev->type) { - dev->dev_regs[6][0x01] = 0x02; - dev->dev_regs[6][0x41] = 0x02; /* Read-only */ - dev->dev_regs[6][0x44] = 0x04; - dev->dev_regs[6][0x45] = 0x04; + dev->dev_regs[6][0x01] = 0x02; + dev->dev_regs[6][0x41] = 0x02; /* Read-only */ + dev->dev_regs[6][0x44] = 0x04; + dev->dev_regs[6][0x45] = 0x04; } /* Logical Device 7 (Auxiliary I/O Part I) */ if (!dev->type) - dev->dev_regs[7][0x01] = 0x02; + dev->dev_regs[7][0x01] = 0x02; if (!dev->type) - dev->dev_regs[7][0x41] = 0x02; /* Read-only */ + dev->dev_regs[7][0x41] = 0x02; /* Read-only */ if (!dev->type) - dev->dev_regs[7][0x43] = 0x02; /* Read-only? */ - dev->dev_regs[7][0xb0] = 0x01; dev->dev_regs[7][0xb1] = 0x01; - dev->dev_regs[7][0xb2] = 0x01; dev->dev_regs[7][0xb3] = 0x01; - dev->dev_regs[7][0xb4] = 0x01; dev->dev_regs[7][0xb5] = 0x01; + dev->dev_regs[7][0x43] = 0x02; /* Read-only? */ + dev->dev_regs[7][0xb0] = 0x01; + dev->dev_regs[7][0xb1] = 0x01; + dev->dev_regs[7][0xb2] = 0x01; + dev->dev_regs[7][0xb3] = 0x01; + dev->dev_regs[7][0xb4] = 0x01; + dev->dev_regs[7][0xb5] = 0x01; dev->dev_regs[7][0xb6] = 0x01; if (dev->type) - dev->dev_regs[7][0xb7] = 0x01; + dev->dev_regs[7][0xb7] = 0x01; /* Logical Device 8 (Auxiliary I/O Part II) */ if (!dev->type) - dev->dev_regs[8][0x01] = 0x02; + dev->dev_regs[8][0x01] = 0x02; if (!dev->type) - dev->dev_regs[8][0x41] = 0x02; /* Read-only */ + dev->dev_regs[8][0x41] = 0x02; /* Read-only */ if (!dev->type) - dev->dev_regs[8][0x43] = 0x02; /* Read-only? */ - dev->dev_regs[8][0xb8] = 0x01; dev->dev_regs[8][0xb9] = 0x01; - dev->dev_regs[8][0xba] = 0x01; dev->dev_regs[8][0xbb] = 0x01; - dev->dev_regs[8][0xbc] = 0x01; dev->dev_regs[8][0xbd] = 0x01; - dev->dev_regs[8][0xbe] = 0x01; dev->dev_regs[8][0xbf] = 0x01; + dev->dev_regs[8][0x43] = 0x02; /* Read-only? */ + dev->dev_regs[8][0xb8] = 0x01; + dev->dev_regs[8][0xb9] = 0x01; + dev->dev_regs[8][0xba] = 0x01; + dev->dev_regs[8][0xbb] = 0x01; + dev->dev_regs[8][0xbc] = 0x01; + dev->dev_regs[8][0xbd] = 0x01; + dev->dev_regs[8][0xbe] = 0x01; + dev->dev_regs[8][0xbf] = 0x01; /* Logical Device 9 (Auxiliary I/O Part III) */ if (dev->type) { - dev->dev_regs[9][0xb0] = 0x01; dev->dev_regs[9][0xb1] = 0x01; - dev->dev_regs[9][0xb2] = 0x01; dev->dev_regs[9][0xb3] = 0x01; - dev->dev_regs[9][0xb4] = 0x01; dev->dev_regs[9][0xb5] = 0x01; - dev->dev_regs[9][0xb6] = 0x01; dev->dev_regs[9][0xb7] = 0x01; + dev->dev_regs[9][0xb0] = 0x01; + dev->dev_regs[9][0xb1] = 0x01; + dev->dev_regs[9][0xb2] = 0x01; + dev->dev_regs[9][0xb3] = 0x01; + dev->dev_regs[9][0xb4] = 0x01; + dev->dev_regs[9][0xb5] = 0x01; + dev->dev_regs[9][0xb6] = 0x01; + dev->dev_regs[9][0xb7] = 0x01; - dev->dev_regs[10][0xc0] = 0x8f; + dev->dev_regs[10][0xc0] = 0x8f; } if (dev->id == 1) { - serial_setup(dev->uart[0], SERIAL3_ADDR, SERIAL3_IRQ); - serial_setup(dev->uart[1], SERIAL4_ADDR, SERIAL4_IRQ); + serial_setup(dev->uart[0], COM3_ADDR, COM3_IRQ); + serial_setup(dev->uart[1], COM4_ADDR, COM4_IRQ); } else { - fdc_reset(dev->fdc); + fdc_reset(dev->fdc); - serial_setup(dev->uart[0], SERIAL1_ADDR, SERIAL1_IRQ); - serial_setup(dev->uart[1], SERIAL2_ADDR, SERIAL2_IRQ); + serial_setup(dev->uart[0], COM1_ADDR, COM1_IRQ); + serial_setup(dev->uart[1], COM2_ADDR, COM2_IRQ); - w83977f_fdc_handler(dev); + w83977f_fdc_handler(dev); } w83977f_lpt_handler(dev); @@ -524,11 +576,10 @@ w83977f_reset(w83977f_t *dev) w83977f_remap(dev); - dev->locked = 0; + dev->locked = 0; dev->rw_locked = 0; } - static void w83977f_close(void *priv) { @@ -539,22 +590,21 @@ w83977f_close(void *priv) free(dev); } - static void * w83977f_init(const device_t *info) { w83977f_t *dev = (w83977f_t *) malloc(sizeof(w83977f_t)); memset(dev, 0, sizeof(w83977f_t)); - dev->type = info->local & 0x0f; + dev->type = info->local & 0x0f; dev->hefras = info->local & 0x40; dev->id = next_id; if (next_id == 1) - dev->hefras ^= 0x40; + dev->hefras ^= 0x40; else - dev->fdc = device_add(&fdc_at_smc_device); + dev->fdc = device_add(&fdc_at_smc_device); dev->uart[0] = device_add_inst(&ns16550_device, (next_id << 1) + 1); dev->uart[1] = device_add_inst(&ns16550_device, (next_id << 1) + 2); @@ -566,57 +616,72 @@ w83977f_init(const device_t *info) return dev; } - const device_t w83977f_device = { - "Winbond W83977F Super I/O", - "w83977f", - 0, - 0, - w83977f_init, w83977f_close, NULL, - { NULL }, NULL, NULL, - NULL + .name = "Winbond W83977F Super I/O", + .internal_name = "w83977f", + .flags = 0, + .local = 0, + .init = w83977f_init, + .close = w83977f_close, + .reset = NULL, + { .available = NULL }, + .speed_changed = NULL, + .force_redraw = NULL, + .config = NULL }; - const device_t w83977f_370_device = { - "Winbond W83977F Super I/O (Port 370h)", - "w83977f_370", - 0, - 0x40, - w83977f_init, w83977f_close, NULL, - { NULL }, NULL, NULL, - NULL + .name = "Winbond W83977F Super I/O (Port 370h)", + .internal_name = "w83977f_370", + .flags = 0, + .local = 0x40, + .init = w83977f_init, + .close = w83977f_close, + .reset = NULL, + { .available = NULL }, + .speed_changed = NULL, + .force_redraw = NULL, + .config = NULL }; - const device_t w83977tf_device = { - "Winbond W83977TF Super I/O", - "w83977tf", - 0, - 1, - w83977f_init, w83977f_close, NULL, - { NULL }, NULL, NULL, - NULL + .name = "Winbond W83977TF Super I/O", + .internal_name = "w83977tf", + .flags = 0, + .local = 1, + .init = w83977f_init, + .close = w83977f_close, + .reset = NULL, + { .available = NULL }, + .speed_changed = NULL, + .force_redraw = NULL, + .config = NULL }; - const device_t w83977ef_device = { - "Winbond W83977TF Super I/O", - "w83977ef", - 0, - 2, - w83977f_init, w83977f_close, NULL, - { NULL }, NULL, NULL, - NULL + .name = "Winbond W83977TF Super I/O", + .internal_name = "w83977ef", + .flags = 0, + .local = 2, + .init = w83977f_init, + .close = w83977f_close, + .reset = NULL, + { .available = NULL }, + .speed_changed = NULL, + .force_redraw = NULL, + .config = NULL }; - const device_t w83977ef_370_device = { - "Winbond W83977TF Super I/O (Port 370h)", - "w83977ef_370", - 0, - 0x42, - w83977f_init, w83977f_close, NULL, - { NULL }, NULL, NULL, - NULL + .name = "Winbond W83977TF Super I/O (Port 370h)", + .internal_name = "w83977ef_370", + .flags = 0, + .local = 0x42, + .init = w83977f_init, + .close = w83977f_close, + .reset = NULL, + { .available = NULL }, + .speed_changed = NULL, + .force_redraw = NULL, + .config = NULL }; diff --git a/src/sound/CMakeLists.txt b/src/sound/CMakeLists.txt index 8879b0378..ec4f8823b 100644 --- a/src/sound/CMakeLists.txt +++ b/src/sound/CMakeLists.txt @@ -1,30 +1,97 @@ # -# 86Box A hypervisor and IBM PC system emulator that specializes in -# running old operating systems and software designed for IBM -# PC systems and compatibles from 1981 through fairly recent -# system designs based on the PCI bus. +# 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. +# This file is part of the 86Box distribution. # -# CMake build script. +# CMake build script. # -# Authors: David HrdliÄka, +# Authors: David HrdliÄka, # -# Copyright 2020,2021 David HrdliÄka. +# Copyright 2020-2021 David HrdliÄka. # -add_library(snd OBJECT sound.c snd_opl.c snd_opl_nuked.c snd_resid.cc - midi.c midi_rtmidi.cpp snd_speaker.c snd_pssj.c snd_lpt_dac.c snd_ac97_codec.c snd_ac97_via.c +add_library(snd OBJECT sound.c snd_opl.c snd_opl_nuked.c snd_opl_ymfm.cpp snd_resid.cc + midi.c snd_speaker.c snd_pssj.c snd_lpt_dac.c snd_ac97_codec.c snd_ac97_via.c snd_lpt_dss.c snd_ps1.c snd_adlib.c snd_adlibgold.c snd_ad1848.c snd_audiopci.c - snd_azt2316a.c snd_cms.c snd_cs423x.c snd_gus.c snd_sb.c snd_sb_dsp.c - snd_emu8k.c snd_mpu401.c snd_sn76489.c snd_ssi2001.c snd_wss.c snd_ym7128.c) + snd_azt2316a.c snd_cms.c snd_cmi8x38.c snd_cs423x.c snd_gus.c snd_sb.c snd_sb_dsp.c + snd_emu8k.c snd_mpu401.c snd_sn76489.c snd_ssi2001.c snd_wss.c snd_ym7128.c + snd_optimc.c) if(OPENAL) - target_compile_definitions(snd PRIVATE USE_OPENAL) + if(VCPKG_TOOLCHAIN) + find_package(OpenAL CONFIG REQUIRED) + elseif(MINGW) + find_package(OpenAL MODULE REQUIRED) + else() + find_package(OpenAL REQUIRED) + endif() + + if(TARGET OpenAL::OpenAL) + target_link_libraries(86Box OpenAL::OpenAL) + else() + target_link_libraries(86Box ${OPENAL_LIBRARY}) + endif() + + include_directories(${OPENAL_INCLUDE_DIR}) + target_sources(snd PRIVATE openal.c) +else() + if(WIN32) + option(FAUDIO "Use FAudio instead of XAudio2" OFF) + endif() + + target_sources(snd PRIVATE xaudio2.c) + + if(NOT WIN32 OR FAUDIO) + find_package(PkgConfig REQUIRED) + + # Use FAudio, a reimplementation of XAudio2 + pkg_check_modules(FAUDIO IMPORTED_TARGET FAudio) + if(FAUDIO_FOUND) + target_link_libraries(86Box PkgConfig::FAUDIO) + else() + find_path(FAUDIO_INCLUDE_DIR NAMES "FAudio.h") + find_library(FAUDIO_LIBRARY FAudio) + + target_link_libraries(86Box ${FAUDIO_LIBRARY}) + endif() + + include_directories(${FAUDIO_INCLUDE_DIRS}) + + set_property(SOURCE xaudio2.c PROPERTY COMPILE_DEFINITIONS USE_FAUDIO) + endif() +endif() + +if(RTMIDI) + if(VCPKG_TOOLCHAIN) + # vcpkg includes a config file for rtmidi + find_package(RtMidi REQUIRED) + target_link_libraries(86Box RtMidi::rtmidi) + else() + find_package(PkgConfig REQUIRED) + pkg_check_modules(RTMIDI REQUIRED IMPORTED_TARGET rtmidi) + target_link_libraries(86Box PkgConfig::RTMIDI) + + if(WIN32) + target_link_libraries(PkgConfig::RTMIDI INTERFACE winmm) + endif() + endif() + + target_compile_definitions(snd PRIVATE USE_RTMIDI) + target_sources(snd PRIVATE midi_rtmidi.cpp) endif() if(FLUIDSYNTH) + find_package(PkgConfig REQUIRED) + pkg_check_modules(FLUIDSYNTH REQUIRED IMPORTED_TARGET fluidsynth) + target_link_libraries(86Box PkgConfig::FLUIDSYNTH) + if(STATIC_BUILD) + target_link_libraries(86Box -static ${FLUIDSYNTH_STATIC_LIBRARIES} -fopenmp) + endif() + target_compile_definitions(snd PRIVATE USE_FLUIDSYNTH) target_sources(snd PRIVATE midi_fluidsynth.c) endif() @@ -46,6 +113,9 @@ if(MUNT) endif() endif() +add_subdirectory(ymfm) +target_link_libraries(86Box ymfm) + if(PAS16) target_compile_definitions(snd PRIVATE USE_PAS16) target_sources(snd PRIVATE snd_pas16.c) @@ -55,9 +125,5 @@ if(GUSMAX) target_compile_definitions(snd PRIVATE USE_GUSMAX) endif() -if(TANDY_ISA) - target_compile_definitions(snd PRIVATE USE_TANDY_ISA) -endif() - add_subdirectory(resid-fp) -target_link_libraries(86Box resid-fp) \ No newline at end of file +target_link_libraries(86Box resid-fp) diff --git a/src/sound/midi.c b/src/sound/midi.c index 4ceb5fdb1..41f82801a 100644 --- a/src/sound/midi.c +++ b/src/sound/midi.c @@ -1,203 +1,213 @@ /* - * 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. + * 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. + * This file is part of the 86Box distribution. * - * MIDI device core module. + * MIDI device core module. * * * - * Authors: Sarah Walker, - * Miran Grca, - * Bit, - * DOSBox Team, + * Authors: Miran Grca, + * Bit, + * DOSBox Team, * - * Copyright 2008-2020 Sarah Walker. - * Copyright 2016-2020 Miran Grca. - * Copyright 2016-2020 Bit. - * Copyright 2008-2020 DOSBox Team. + * Copyright 2016-2020 Miran Grca. + * Copyright 2016-2020 Bit. + * Copyright 2008-2020 DOSBox Team. */ -#include #include -#include +#include #include +#include #include + #include <86box/86box.h> #include <86box/device.h> -#include <86box/plat.h> #include <86box/midi.h> +#include <86box/plat.h> +int midi_output_device_current = 0; +static int midi_output_device_last = 0; +int midi_input_device_current = 0; +static int midi_input_device_last = 0; -int midi_device_current = 0; -static int midi_device_last = 0; -int midi_input_device_current = 0; -static int midi_input_device_last = 0; +midi_t *midi_out = NULL; +midi_t *midi_in = NULL; -midi_t *midi = NULL, *midi_in = NULL; - -midi_in_handler_t *mih_first = NULL, *mih_last = NULL, - *mih_cur = NULL; +midi_in_handler_t *mih_first = NULL; +midi_in_handler_t *mih_last = NULL; +midi_in_handler_t *mih_cur = NULL; uint8_t MIDI_InSysexBuf[SYSEX_SIZE]; uint8_t MIDI_evt_len[256] = { - 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, /* 0x00 */ - 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, /* 0x10 */ - 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, /* 0x20 */ - 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, /* 0x30 */ - 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, /* 0x40 */ - 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, /* 0x50 */ - 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, /* 0x60 */ - 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, /* 0x70 */ + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0x00 */ + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0x10 */ + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0x20 */ + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0x30 */ + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0x40 */ + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0x50 */ + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0x60 */ + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0x70 */ - 3,3,3,3, 3,3,3,3, 3,3,3,3, 3,3,3,3, /* 0x80 */ - 3,3,3,3, 3,3,3,3, 3,3,3,3, 3,3,3,3, /* 0x90 */ - 3,3,3,3, 3,3,3,3, 3,3,3,3, 3,3,3,3, /* 0xa0 */ - 3,3,3,3, 3,3,3,3, 3,3,3,3, 3,3,3,3, /* 0xb0 */ + 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, /* 0x80 */ + 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, /* 0x90 */ + 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, /* 0xa0 */ + 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, /* 0xb0 */ - 2,2,2,2, 2,2,2,2, 2,2,2,2, 2,2,2,2, /* 0xc0 */ - 2,2,2,2, 2,2,2,2, 2,2,2,2, 2,2,2,2, /* 0xd0 */ + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, /* 0xc0 */ + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, /* 0xd0 */ - 3,3,3,3, 3,3,3,3, 3,3,3,3, 3,3,3,3, /* 0xe0 */ + 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, /* 0xe0 */ - 0,2,3,2, 0,0,1,0, 1,0,1,1, 1,0,1,0 /* 0xf0 */ + 0, 2, 3, 2, 0, 0, 1, 0, 1, 0, 1, 1, 1, 0, 1, 0 /* 0xf0 */ }; typedef struct { const device_t *device; -} MIDI_DEVICE, MIDI_IN_DEVICE; +} MIDI_OUT_DEVICE, MIDI_IN_DEVICE; -static const device_t midi_none_device = { - "None", - "none", - 0, 0, - NULL, NULL, NULL, - { NULL }, NULL, NULL, - NULL +static const device_t midi_out_none_device = { + .name = "None", + .internal_name = "none", + .flags = 0, + .local = 0, + .init = NULL, + .close = NULL, + .reset = NULL, + { .available = NULL }, + .speed_changed = NULL, + .force_redraw = NULL, + .config = NULL }; -static const MIDI_DEVICE devices[] = -{ - { &midi_none_device }, +static const MIDI_OUT_DEVICE devices[] = { + // clang-format off + { &midi_out_none_device }, #ifdef USE_FLUIDSYNTH - { &fluidsynth_device }, + { &fluidsynth_device }, #endif #ifdef USE_MUNT - { &mt32_device }, - { &cm32l_device }, + { &mt32_old_device }, + { &mt32_new_device }, + { &cm32l_device }, + { &cm32ln_device }, #endif - { &rtmidi_device }, - { NULL } +#ifdef USE_RTMIDI + { &rtmidi_output_device }, +#endif + { NULL } + // clang-format on }; static const device_t midi_in_none_device = { - "None", - "none", - 0, 0, - NULL, NULL, NULL, - { NULL }, NULL, NULL, - NULL + .name = "None", + .internal_name = "none", + .flags = 0, + .local = 0, + .init = NULL, + .close = NULL, + .reset = NULL, + { .available = NULL }, + .speed_changed = NULL, + .force_redraw = NULL, + .config = NULL }; -static const MIDI_IN_DEVICE midi_in_devices[] = -{ - { &midi_in_none_device }, - { &rtmidi_input_device }, - { NULL } +static const MIDI_IN_DEVICE midi_in_devices[] = { + // clang-format off + { &midi_in_none_device }, +#ifdef USE_RTMIDI + { &rtmidi_input_device }, +#endif + { NULL } + // clang-format on }; - int -midi_device_available(int card) +midi_out_device_available(int card) { if (devices[card].device) - return device_available(devices[card].device); + return device_available(devices[card].device); return 1; } - const device_t * -midi_device_getdevice(int card) +midi_out_device_getdevice(int card) { return devices[card].device; } - int -midi_device_has_config(int card) +midi_out_device_has_config(int card) { if (!devices[card].device) - return 0; + return 0; return devices[card].device->config ? 1 : 0; } - -char * -midi_device_get_internal_name(int card) +const char * +midi_out_device_get_internal_name(int card) { return device_get_internal_name(devices[card].device); } - int -midi_device_get_from_internal_name(char *s) +midi_out_device_get_from_internal_name(char *s) { int c = 0; while (devices[c].device != NULL) { - if (!strcmp(devices[c].device->internal_name, s)) - return c; - c++; + if (!strcmp(devices[c].device->internal_name, s)) + return c; + c++; } return 0; } - void -midi_device_init() +midi_out_device_init(void) { - if (devices[midi_device_current].device) - device_add(devices[midi_device_current].device); - midi_device_last = midi_device_current; -} - - -void -midi_init(midi_device_t* device) -{ - midi = (midi_t *) malloc(sizeof(midi_t)); - memset(midi, 0, sizeof(midi_t)); - - midi->m_out_device = device; + if ((midi_output_device_current > 0) && devices[midi_output_device_current].device) + device_add(devices[midi_output_device_current].device); + midi_output_device_last = midi_output_device_current; } void -midi_in_init(midi_device_t* device, midi_t **mididev) +midi_out_init(midi_device_t *device) { - *mididev = (midi_t *)malloc(sizeof(midi_t)); + midi_out = (midi_t *) malloc(sizeof(midi_t)); + memset(midi_out, 0, sizeof(midi_t)); + + midi_out->m_out_device = device; +} + +void +midi_in_init(midi_device_t *device, midi_t **mididev) +{ + *mididev = (midi_t *) malloc(sizeof(midi_t)); memset(*mididev, 0, sizeof(midi_t)); (*mididev)->m_in_device = device; } - void -midi_close(void) +midi_out_close(void) { - if (midi && midi->m_out_device) { - free(midi->m_out_device); - midi->m_out_device = NULL; + if (midi_out && midi_out->m_out_device) { + free(midi_out->m_out_device); + midi_out->m_out_device = NULL; } - if (midi) { - free(midi); - midi = NULL; + if (midi_out) { + free(midi_out); + midi_out = NULL; } } @@ -205,416 +215,397 @@ void midi_in_close(void) { if (midi_in && midi_in->m_in_device) { - free(midi_in->m_in_device); - midi_in->m_in_device = NULL; + free(midi_in->m_in_device); + midi_in->m_in_device = NULL; } if (midi_in) { - free(midi_in); - midi_in = NULL; + free(midi_in); + midi_in = NULL; } } - void midi_poll(void) { - if (midi && midi->m_out_device && midi->m_out_device->poll) - midi->m_out_device->poll(); + if (midi_out && midi_out->m_out_device && midi_out->m_out_device->poll) + midi_out->m_out_device->poll(); } - void play_msg(uint8_t *msg) { - if (midi->m_out_device->play_msg) - midi->m_out_device->play_msg(msg); + if (midi_out->m_out_device->play_msg) + midi_out->m_out_device->play_msg(msg); } - void play_sysex(uint8_t *sysex, unsigned int len) { - if (midi->m_out_device->play_sysex) - midi->m_out_device->play_sysex(sysex, len); + if (midi_out->m_out_device->play_sysex) + midi_out->m_out_device->play_sysex(sysex, len); } - int midi_in_device_available(int card) { if (midi_in_devices[card].device) - return device_available(midi_in_devices[card].device); + return device_available(midi_in_devices[card].device); return 1; } - const device_t * midi_in_device_getdevice(int card) { return midi_in_devices[card].device; } - int midi_in_device_has_config(int card) { if (!midi_in_devices[card].device) - return 0; + return 0; return midi_in_devices[card].device->config ? 1 : 0; } - -char * +const char * midi_in_device_get_internal_name(int card) { return device_get_internal_name(midi_in_devices[card].device); } - int midi_in_device_get_from_internal_name(char *s) { int c = 0; while (midi_in_devices[c].device != NULL) { - if (!strcmp(midi_in_devices[c].device->internal_name, s)) - return c; - c++; + if (!strcmp(midi_in_devices[c].device->internal_name, s)) + return c; + c++; } return 0; } - void -midi_in_device_init() +midi_in_device_init(void) { - if (midi_in_devices[midi_input_device_current].device) - device_add(midi_in_devices[midi_input_device_current].device); + if ((midi_input_device_current > 0) && midi_in_devices[midi_input_device_current].device) + device_add(midi_in_devices[midi_input_device_current].device); midi_input_device_last = midi_input_device_current; } - void midi_raw_out_rt_byte(uint8_t val) { if (!midi_in) - return; + return; if (!midi_in->midi_realtime) - return; + return; - if ((!midi_in->midi_clockout && (val == 0xf8))) - return; + if (!midi_in->midi_clockout && (val == 0xf8)) + return; midi_in->midi_cmd_r = val << 24; /* pclog("Play RT Byte msg\n"); */ - play_msg((uint8_t *)&midi_in->midi_cmd_r); + play_msg((uint8_t *) &midi_in->midi_cmd_r); } - void midi_raw_out_thru_rt_byte(uint8_t val) { if (midi_in && midi_in->thruchan) - midi_raw_out_rt_byte(val); + midi_raw_out_rt_byte(val); } - void midi_raw_out_byte(uint8_t val) { uint32_t passed_ticks; - if (!midi || !midi->m_out_device) - return; + if (!midi_out || !midi_out->m_out_device) + return; - if ((midi->m_out_device->write && midi->m_out_device->write(val))) - return; + if (midi_out->m_out_device->write && midi_out->m_out_device->write(val)) + return; - if (midi->midi_sysex_start) { - passed_ticks = plat_get_ticks() - midi->midi_sysex_start; - if (passed_ticks < midi->midi_sysex_delay) - plat_delay_ms(midi->midi_sysex_delay - passed_ticks); + if (midi_out->midi_sysex_start) { + passed_ticks = plat_get_ticks() - midi_out->midi_sysex_start; + if (passed_ticks < midi_out->midi_sysex_delay) + plat_delay_ms(midi_out->midi_sysex_delay - passed_ticks); } /* Test for a realtime MIDI message */ if (val >= 0xf8) { - midi->midi_rt_buf[0] = val; - play_msg(midi->midi_rt_buf); - return; + midi_out->midi_rt_buf[0] = val; + play_msg(midi_out->midi_rt_buf); + return; } /* Test for a active sysex transfer */ - if (midi->midi_status == 0xf0) { - if (!(val & 0x80)) { - if (midi->midi_pos < (SYSEX_SIZE-1)) - midi->midi_sysex_data[midi->midi_pos++] = val; - return; - } else { - midi->midi_sysex_data[midi->midi_pos++] = 0xf7; + if (midi_out->midi_status == 0xf0) { + if (!(val & 0x80)) { + if (midi_out->midi_pos < (SYSEX_SIZE - 1)) + midi_out->midi_sysex_data[midi_out->midi_pos++] = val; + return; + } else { + midi_out->midi_sysex_data[midi_out->midi_pos++] = 0xf7; - if ((midi->midi_sysex_start) && (midi->midi_pos >= 4) && (midi->midi_pos <= 9) && - (midi->midi_sysex_data[1] == 0x41) && (midi->midi_sysex_data[3] == 0x16)) { - /* pclog("MIDI: Skipping invalid MT-32 SysEx MIDI message\n"); */ - } else { - play_sysex(midi->midi_sysex_data, midi->midi_pos); - if (midi->midi_sysex_start) { - if (midi-> midi_sysex_data[5] == 0x7f) - midi->midi_sysex_delay = 290; /* All parameters reset */ - else if ((midi->midi_sysex_data[5] == 0x10) && (midi->midi_sysex_data[6] == 0x00) && - (midi->midi_sysex_data[7] == 0x04)) - midi->midi_sysex_delay = 145; /* Viking Child */ - else if ((midi->midi_sysex_data[5] == 0x10) && (midi->midi_sysex_data[6] == 0x00) && - (midi->midi_sysex_data[7] == 0x01)) - midi->midi_sysex_delay = 30; /* Dark Sun 1 */ - else - midi->midi_sysex_delay = (unsigned int) (((float) (midi->midi_pos) * 1.25f) * 1000.0f / 3125.0f) + 2; + if ((midi_out->midi_sysex_start) && (midi_out->midi_pos >= 4) && (midi_out->midi_pos <= 9) && (midi_out->midi_sysex_data[1] == 0x41) && (midi_out->midi_sysex_data[3] == 0x16)) { + /* pclog("MIDI: Skipping invalid MT-32 SysEx MIDI message\n"); */ + } else { + play_sysex(midi_out->midi_sysex_data, midi_out->midi_pos); + if (midi_out->midi_sysex_start) { + if (midi_out->midi_sysex_data[5] == 0x7f) + midi_out->midi_sysex_delay = 290; /* All parameters reset */ + else if ((midi_out->midi_sysex_data[5] == 0x10) && (midi_out->midi_sysex_data[6] == 0x00) && (midi_out->midi_sysex_data[7] == 0x04)) + midi_out->midi_sysex_delay = 145; /* Viking Child */ + else if ((midi_out->midi_sysex_data[5] == 0x10) && (midi_out->midi_sysex_data[6] == 0x00) && (midi_out->midi_sysex_data[7] == 0x01)) + midi_out->midi_sysex_delay = 30; /* Dark Sun 1 */ + else + midi_out->midi_sysex_delay = (unsigned int) (((float) (midi_out->midi_pos) * 1.25f) * 1000.0f / 3125.0f) + 2; - midi->midi_sysex_start = plat_get_ticks(); - } - } - } + midi_out->midi_sysex_start = plat_get_ticks(); + } + } + } } if (val & 0x80) { - midi->midi_status = val; - midi->midi_cmd_pos = 0; - midi->midi_cmd_len = MIDI_evt_len[val]; - if (midi->midi_status == 0xf0) { - midi->midi_sysex_data[0] = 0xf0; - midi->midi_pos = 1; - } + midi_out->midi_status = val; + midi_out->midi_cmd_pos = 0; + midi_out->midi_cmd_len = MIDI_evt_len[val]; + if (midi_out->midi_status == 0xf0) { + midi_out->midi_sysex_data[0] = 0xf0; + midi_out->midi_pos = 1; + } } - if (midi->midi_cmd_len) { - midi->midi_cmd_buf[midi->midi_cmd_pos++] = val; - if (midi->midi_cmd_pos >= midi->midi_cmd_len) { - play_msg(midi->midi_cmd_buf); - midi->midi_cmd_pos = 1; - } + if (midi_out->midi_cmd_len) { + midi_out->midi_cmd_buf[midi_out->midi_cmd_pos++] = val; + if (midi_out->midi_cmd_pos >= midi_out->midi_cmd_len) { + play_msg(midi_out->midi_cmd_buf); + midi_out->midi_cmd_pos = 1; + } } } - -void -midi_clear_buffer(void) -{ - if (!midi) - return; - - midi->midi_pos = 0; - midi->midi_status = 0x00; - midi->midi_cmd_pos = 0; - midi->midi_cmd_len = 0; -} - - void -midi_in_handler(int set, void (*msg)(void *p, uint8_t *msg, uint32_t len), int (*sysex)(void *p, uint8_t *buffer, uint32_t len, int abort), void *p) +midi_clear_buffer(void) { - midi_in_handler_t *temp = NULL, *next; + if (!midi_out) + return; - if (set) { - /* Add MIDI IN handler. */ - if ((mih_first == NULL) && (mih_last != NULL)) - fatal("Last MIDI IN handler present with no first MIDI IN handler\n"); - - if ((mih_first != NULL) && (mih_last == NULL)) - fatal("First MIDI IN handler present with no last MIDI IN handler\n"); - - temp = (midi_in_handler_t *) malloc(sizeof(midi_in_handler_t)); - memset(temp, 0, sizeof(midi_in_handler_t)); - temp->msg = msg; - temp->sysex = sysex; - temp->p = p; - - if (mih_last == NULL) - mih_first = mih_last = temp; - else { - temp->prev = mih_last; - mih_last = temp; - } - } else if ((mih_first != NULL) && (mih_last != NULL)) { - temp = mih_first; - - while(1) { - if (temp == NULL) - break; - - if ((temp->msg == msg) && (temp->sysex == sysex) && (temp->p == p)) { - if (temp->prev != NULL) - temp->prev->next = temp->next; - - if (temp->next != NULL) - temp->next->prev = temp->prev; - - next = temp->next; - - if (temp == mih_first) { - mih_first = NULL; - if (next == NULL) - mih_last = NULL; - } - - if (temp == mih_last) - mih_last = NULL; - - free(temp); - temp = next; - - if (next == NULL) - break; - } - } - } + midi_out->midi_pos = 0; + midi_out->midi_status = 0x00; + midi_out->midi_cmd_pos = 0; + midi_out->midi_cmd_len = 0; } +void +midi_in_handler(int set, void (*msg)(void *priv, uint8_t *msg, uint32_t len), int (*sysex)(void *priv, uint8_t *buffer, uint32_t len, int abort), void *priv) +{ + midi_in_handler_t *temp = NULL; + midi_in_handler_t *next; + + if (set) { + /* Add MIDI IN handler. */ + if ((mih_first == NULL) && (mih_last != NULL)) + fatal("Last MIDI IN handler present with no first MIDI IN handler\n"); + + if ((mih_first != NULL) && (mih_last == NULL)) + fatal("First MIDI IN handler present with no last MIDI IN handler\n"); + + temp = (midi_in_handler_t *) malloc(sizeof(midi_in_handler_t)); + memset(temp, 0, sizeof(midi_in_handler_t)); + temp->msg = msg; + temp->sysex = sysex; + temp->priv = priv; + + if (mih_last == NULL) + mih_first = mih_last = temp; + else { + temp->prev = mih_last; + mih_last = temp; + } + } else if ((mih_first != NULL) && (mih_last != NULL)) { + temp = mih_first; + + while (1) { + if (temp == NULL) + break; + + if ((temp->msg == msg) && (temp->sysex == sysex) && (temp->priv == priv)) { + if (temp->prev != NULL) + temp->prev->next = temp->next; + + if (temp->next != NULL) + temp->next->prev = temp->prev; + + next = temp->next; + + if (temp == mih_first) { + mih_first = NULL; + if (next == NULL) + mih_last = NULL; + } + + if (temp == mih_last) + mih_last = NULL; + + free(temp); + temp = next; + + if (next == NULL) + break; + } + } + } +} void midi_in_handlers_clear(void) { - midi_in_handler_t *temp = mih_first, *next; + midi_in_handler_t *temp = mih_first; + midi_in_handler_t *next; - while(1) { - if (temp == NULL) - break; + while (1) { + if (temp == NULL) + break; - next = temp->next; - free(temp); + next = temp->next; + free(temp); - temp = next; + temp = next; - if (next == NULL) - break; + if (next == NULL) + break; } mih_first = mih_last = NULL; } - void midi_in_msg(uint8_t *msg, uint32_t len) { midi_in_handler_t *temp = mih_first; - while(1) { - if (temp == NULL) - break; + while (1) { + if (temp == NULL) + break; - if (temp->msg) - temp->msg(temp->p, msg, len); + if (temp->msg) + temp->msg(temp->priv, msg, len); - temp = temp->next; + temp = temp->next; - if (temp == NULL) - break; + if (temp == NULL) + break; } } - static void midi_start_sysex(uint8_t *buffer, uint32_t len) { midi_in_handler_t *temp = mih_first; - while(1) { - if (temp == NULL) - break; + while (1) { + if (temp == NULL) + break; - temp->cnt = 5; - temp->buf = buffer; - temp->len = len; + temp->cnt = 5; + temp->buf = buffer; + temp->len = len; - temp = temp->next; + temp = temp->next; - if (temp == NULL) - break; + if (temp == NULL) + break; } } - /* Returns: - 0 = All handlers have returnd 0; - 1 = There are still handlers to go. */ + 0 = All handlers have returnd 0; + 1 = There are still handlers to go. */ static int midi_do_sysex(void) { midi_in_handler_t *temp = mih_first; - int ret, cnt_acc = 0; + int ret; + int cnt_acc = 0; - while(1) { - if (temp == NULL) - break; + while (1) { + if (temp == NULL) + break; - /* Do nothing if the handler has a zero count. */ - if ((temp->cnt > 0) || (temp->len > 0)) { - ret = 0; - if (temp->sysex) { - if (temp->cnt == 0) - ret = temp->sysex(temp->p, temp->buf, 0, 0); - else - ret = temp->sysex(temp->p, temp->buf, temp->len, 0); - } + /* Do nothing if the handler has a zero count. */ + if ((temp->cnt > 0) || (temp->len > 0)) { + ret = 0; + if (temp->sysex) { + if (temp->cnt == 0) + ret = temp->sysex(temp->priv, temp->buf, 0, 0); + else + ret = temp->sysex(temp->priv, temp->buf, temp->len, 0); + } - /* If count is 0 and length is 0, then this is just a finishing - call to temp->sysex(), so skip this entire block. */ - if (temp->cnt > 0) { - if (ret) { - /* Decrease or reset the counter. */ - if (temp->len == ret) - temp->cnt--; - else - temp->cnt = 5; + /* If count is 0 and length is 0, then this is just a finishing + call to temp->sysex(), so skip this entire block. */ + if (temp->cnt > 0) { + if (ret) { + /* Decrease or reset the counter. */ + if (temp->len == ret) + temp->cnt--; + else + temp->cnt = 5; - /* Advance the buffer pointer and remember the - remaining length. */ - temp->buf += (temp->len - ret); - temp->len = ret; - } else { - /* Set count to 0 so that this handler will be - ignored on the next interation. */ - temp->cnt = 0; + /* Advance the buffer pointer and remember the + remaining length. */ + temp->buf += (temp->len - ret); + temp->len = ret; + } else { + /* Set count to 0 so that this handler will be + ignored on the next interation. */ + temp->cnt = 0; - /* Reset the buffer pointer and length. */ - temp->buf = NULL; - temp->len = 0; - } + /* Reset the buffer pointer and length. */ + temp->buf = NULL; + temp->len = 0; + } - /* If the remaining count is above zero, add it to the - accumulator. */ - if (temp->cnt > 0) - cnt_acc |= temp->cnt; - } - } + /* If the remaining count is above zero, add it to the + accumulator. */ + if (temp->cnt > 0) + cnt_acc |= temp->cnt; + } + } - temp = temp->next; + temp = temp->next; - if (temp == NULL) - break; + if (temp == NULL) + break; } /* Return 0 if all handlers have returned 0 or all the counts are otherwise 0. */ if (cnt_acc == 0) - return 0; + return 0; else - return 1; + return 1; } - void midi_in_sysex(uint8_t *buffer, uint32_t len) { midi_start_sysex(buffer, len); while (1) { - /* This will return 0 if all theh handlers have either - timed out or otherwise indicated it is time to stop. */ - if (midi_do_sysex()) - plat_delay_ms(5); /* msec */ - else - break; + /* This will return 0 if all theh handlers have either + timed out or otherwise indicated it is time to stop. */ + if (midi_do_sysex()) + plat_delay_ms(5); /* msec */ + else + break; } } diff --git a/src/sound/midi_fluidsynth.c b/src/sound/midi_fluidsynth.c index ed3e2d535..08aefe16c 100644 --- a/src/sound/midi_fluidsynth.c +++ b/src/sound/midi_fluidsynth.c @@ -1,574 +1,502 @@ /* some code borrowed from scummvm */ #ifdef USE_FLUIDSYNTH -#include -#include -#include -#include -#include -#include <86box/86box.h> -#include <86box/config.h> -#include <86box/device.h> -#include <86box/plat.h> -#include <86box/plat_dynld.h> -#include <86box/ui.h> -#include <86box/midi.h> -#include <86box/sound.h> +# include +# include +# include +# include +# include +# ifdef __unix__ +# include +# endif +# define FLUIDSYNTH_NOT_A_DLL +# include +# include <86box/86box.h> +# include <86box/config.h> +# include <86box/device.h> +# include <86box/midi.h> +# include <86box/thread.h> +# include <86box/sound.h> +# include <86box/plat_unused.h> -#define FLUID_CHORUS_DEFAULT_N 3 -#define FLUID_CHORUS_DEFAULT_LEVEL 2.0f -#define FLUID_CHORUS_DEFAULT_SPEED 0.3f -#define FLUID_CHORUS_DEFAULT_DEPTH 8.0f -#define FLUID_CHORUS_DEFAULT_TYPE FLUID_CHORUS_MOD_SINE +# define RENDER_RATE 100 +# define BUFFER_SEGMENTS 10 -#define RENDER_RATE 100 -#define BUFFER_SEGMENTS 10 +/* Check the FluidSynth version to determine wheteher to use the older reverb/chorus + control functions that were deprecated in 2.2.0, or their newer replacements */ +# if (FLUIDSYNTH_VERSION_MAJOR < 2) || ((FLUIDSYNTH_VERSION_MAJOR == 2) && (FLUIDSYNTH_VERSION_MINOR < 2)) +# define USE_OLD_FLUIDSYNTH_API +# endif - -enum fluid_chorus_mod { - FLUID_CHORUS_MOD_SINE = 0, - FLUID_CHORUS_MOD_TRIANGLE = 1 -}; - -enum fluid_interp { - FLUID_INTERP_NONE = 0, - FLUID_INTERP_LINEAR = 1, - FLUID_INTERP_DEFAULT = 4, - FLUID_INTERP_4THORDER = 4, - FLUID_INTERP_7THORDER = 7, - FLUID_INTERP_HIGHEST = 7 -}; - - -#ifdef USE_OPENAL extern void givealbuffer_midi(void *buf, uint32_t size); extern void al_set_midi(int freq, int buf_size); -#endif -static void *fluidsynth_handle; /* handle to FluidSynth DLL */ +typedef struct fluidsynth { + fluid_settings_t *settings; + fluid_synth_t *synth; + int samplerate; + int sound_font; -/* Pointers to the real functions. */ -static void * (*f_new_fluid_settings)(void); -static void (*f_delete_fluid_settings)(void *settings); -static int (*f_fluid_settings_setnum)(void *settings, const char *name, double val); -static int (*f_fluid_settings_getnum)(void *settings, const char *name, double *val); -static void * (*f_new_fluid_synth)(void *settings); -static int (*f_delete_fluid_synth)(void *synth); -static int (*f_fluid_synth_noteon)(void *synth, int chan, int key, int vel); -static int (*f_fluid_synth_noteoff)(void *synth, int chan, int key); -static int (*f_fluid_synth_cc)(void *synth, int chan, int ctrl, int val); -static int (*f_fluid_synth_sysex)(void *synth, const char *data, int len, char *response, int *response_len, int *handled, int dryrun); -static int (*f_fluid_synth_pitch_bend)(void *synth, int chan, int val); -static int (*f_fluid_synth_program_change)(void *synth, int chan, int program); -static int (*f_fluid_synth_sfload)(void *synth, const char *filename, int reset_presets); -static int (*f_fluid_synth_set_interp_method)(void *synth, int chan, int interp_method); -static void (*f_fluid_synth_set_reverb)(void *synth, double roomsize, double damping, double width, double level); -static void (*f_fluid_synth_set_reverb_on)(void *synth, int on); -static void (*f_fluid_synth_set_chorus)(void *synth, int nr, double level, double speed, double depth_ms, int type); -static void (*f_fluid_synth_set_chorus_on)(void *synth, int on); -static int (*f_fluid_synth_write_s16)(void *synth, int len, void *lout, int loff, int lincr, void *rout, int roff, int rincr); -static int (*f_fluid_synth_write_float)(void *synth, int len, void *lout, int loff, int lincr, void *rout, int roff, int rincr); -static char* (*f_fluid_version_str)(void); -static dllimp_t fluidsynth_imports[] = { - { "new_fluid_settings", &f_new_fluid_settings }, - { "delete_fluid_settings", &f_delete_fluid_settings }, - { "fluid_settings_setnum", &f_fluid_settings_setnum }, - { "fluid_settings_getnum", &f_fluid_settings_getnum }, - { "new_fluid_synth", &f_new_fluid_synth }, - { "delete_fluid_synth", &f_delete_fluid_synth }, - { "fluid_synth_noteon", &f_fluid_synth_noteon }, - { "fluid_synth_noteoff", &f_fluid_synth_noteoff }, - { "fluid_synth_cc", &f_fluid_synth_cc }, - { "fluid_synth_sysex", &f_fluid_synth_sysex }, - { "fluid_synth_pitch_bend", &f_fluid_synth_pitch_bend }, - { "fluid_synth_program_change", &f_fluid_synth_program_change }, - { "fluid_synth_sfload", &f_fluid_synth_sfload }, - { "fluid_synth_set_interp_method", &f_fluid_synth_set_interp_method }, - { "fluid_synth_set_reverb", &f_fluid_synth_set_reverb }, - { "fluid_synth_set_reverb_on", &f_fluid_synth_set_reverb_on }, - { "fluid_synth_set_chorus", &f_fluid_synth_set_chorus }, - { "fluid_synth_set_chorus_on", &f_fluid_synth_set_chorus_on }, - { "fluid_synth_write_s16", &f_fluid_synth_write_s16 }, - { "fluid_synth_write_float", &f_fluid_synth_write_float }, - { "fluid_version_str", &f_fluid_version_str }, - { NULL, NULL }, -}; + thread_t *thread_h; + event_t *event, *start_event; + int buf_size; + float *buffer; + int16_t *buffer_int16; + int midi_pos; - -typedef struct fluidsynth -{ - void* settings; - void* synth; - int samplerate; - int sound_font; - - thread_t *thread_h; - event_t *event, *start_event; - int buf_size; - float* buffer; - int16_t* buffer_int16; - int midi_pos; - - int on; + int on; } fluidsynth_t; fluidsynth_t fsdev; -int fluidsynth_available(void) +int +fluidsynth_available(void) { - return 1; + return 1; } -void fluidsynth_poll(void) +void +fluidsynth_poll(void) { - fluidsynth_t* data = &fsdev; - data->midi_pos++; - if (data->midi_pos == 48000/RENDER_RATE) - { - data->midi_pos = 0; - thread_set_event(data->event); + fluidsynth_t *data = &fsdev; + data->midi_pos++; + if (data->midi_pos == SOUND_FREQ / RENDER_RATE) { + data->midi_pos = 0; + thread_set_event(data->event); + } +} + +static void +fluidsynth_thread(void *param) +{ + fluidsynth_t *data = (fluidsynth_t *) param; + int buf_pos = 0; + int buf_size = data->buf_size / BUFFER_SEGMENTS; + + thread_set_event(data->start_event); + + while (data->on) { + thread_wait_event(data->event, -1); + thread_reset_event(data->event); + + if (sound_is_float) { + float *buf = (float *) ((uint8_t *) data->buffer + buf_pos); + memset(buf, 0, buf_size); + if (data->synth) + fluid_synth_write_float(data->synth, buf_size / (2 * sizeof(float)), buf, 0, 2, buf, 1, 2); + buf_pos += buf_size; + if (buf_pos >= data->buf_size) { + givealbuffer_midi(data->buffer, data->buf_size / sizeof(float)); + buf_pos = 0; + } + } else { + int16_t *buf = (int16_t *) ((uint8_t *) data->buffer_int16 + buf_pos); + memset(buf, 0, buf_size); + if (data->synth) + fluid_synth_write_s16(data->synth, buf_size / (2 * sizeof(int16_t)), buf, 0, 2, buf, 1, 2); + buf_pos += buf_size; + if (buf_pos >= data->buf_size) { + givealbuffer_midi(data->buffer_int16, data->buf_size / sizeof(int16_t)); + buf_pos = 0; + } } + } } -static void fluidsynth_thread(void *param) +void +fluidsynth_msg(uint8_t *msg) { - fluidsynth_t* data = (fluidsynth_t*)param; - int buf_pos = 0; - int buf_size = data->buf_size / BUFFER_SEGMENTS; + fluidsynth_t *data = &fsdev; - thread_set_event(data->start_event); + uint32_t val = *((uint32_t *) msg); - while (data->on) - { - thread_wait_event(data->event, -1); - thread_reset_event(data->event); + uint32_t param2 = (uint8_t) ((val >> 16) & 0xFF); + uint32_t param1 = (uint8_t) ((val >> 8) & 0xFF); + uint8_t cmd = (uint8_t) (val & 0xF0); + uint8_t chan = (uint8_t) (val & 0x0F); - if (sound_is_float) - { - float *buf = (float*)((uint8_t*)data->buffer + buf_pos); - memset(buf, 0, buf_size); - if (data->synth) - f_fluid_synth_write_float(data->synth, buf_size/(2 * sizeof(float)), buf, 0, 2, buf, 1, 2); - buf_pos += buf_size; - if (buf_pos >= data->buf_size) - { -#ifdef USE_OPENAL - givealbuffer_midi(data->buffer, data->buf_size / sizeof(float)); -#endif - buf_pos = 0; - } - } - else - { - int16_t *buf = (int16_t*)((uint8_t*)data->buffer_int16 + buf_pos); - memset(buf, 0, buf_size); - if (data->synth) - f_fluid_synth_write_s16(data->synth, buf_size/(2 * sizeof(int16_t)), buf, 0, 2, buf, 1, 2); - buf_pos += buf_size; - if (buf_pos >= data->buf_size) - { -#ifdef USE_OPENAL - givealbuffer_midi(data->buffer_int16, data->buf_size / sizeof(int16_t)); -#endif - buf_pos = 0; - } - } - } -} - -void fluidsynth_msg(uint8_t *msg) -{ - fluidsynth_t* data = &fsdev; - - uint32_t val = *((uint32_t*)msg); - - uint32_t param2 = (uint8_t) ((val >> 16) & 0xFF); - uint32_t param1 = (uint8_t) ((val >> 8) & 0xFF); - uint8_t cmd = (uint8_t) (val & 0xF0); - uint8_t chan = (uint8_t) (val & 0x0F); - - switch (cmd) { - case 0x80: /* Note Off */ - f_fluid_synth_noteoff(data->synth, chan, param1); - break; - case 0x90: /* Note On */ - f_fluid_synth_noteon(data->synth, chan, param1, param2); - break; - case 0xA0: /* Aftertouch */ - break; - case 0xB0: /* Control Change */ - f_fluid_synth_cc(data->synth, chan, param1, param2); - break; - case 0xC0: /* Program Change */ - f_fluid_synth_program_change(data->synth, chan, param1); - break; - case 0xD0: /* Channel Pressure */ - break; - case 0xE0: /* Pitch Bend */ - f_fluid_synth_pitch_bend(data->synth, chan, (param2 << 7) | param1); - break; - case 0xF0: /* SysEx */ - break; + switch (cmd) { + case 0x80: /* Note Off */ + fluid_synth_noteoff(data->synth, chan, param1); + break; + case 0x90: /* Note On */ + fluid_synth_noteon(data->synth, chan, param1, param2); + break; + case 0xA0: /* Aftertouch */ + break; + case 0xB0: /* Control Change */ + fluid_synth_cc(data->synth, chan, param1, param2); + break; + case 0xC0: /* Program Change */ + fluid_synth_program_change(data->synth, chan, param1); + break; + case 0xD0: /* Channel Pressure */ + fluid_synth_channel_pressure(data->synth, chan, param1); + break; + case 0xE0: /* Pitch Bend */ + fluid_synth_pitch_bend(data->synth, chan, (param2 << 7) | param1); + break; + case 0xF0: /* SysEx */ + break; default: - break; - } + break; + } } -void fluidsynth_sysex(uint8_t* data, unsigned int len) +void +fluidsynth_sysex(uint8_t *data, unsigned int len) { - fluidsynth_t* d = &fsdev; + fluidsynth_t *d = &fsdev; - f_fluid_synth_sysex(d->synth, (const char *) data, len, 0, 0, 0, 0); + fluid_synth_sysex(d->synth, (const char *) data, len, 0, 0, 0, 0); } -void* fluidsynth_init(const device_t *info) +void * +fluidsynth_init(UNUSED(const device_t *info)) { - fluidsynth_t* data = &fsdev; - midi_device_t* dev; + fluidsynth_t *data = &fsdev; + midi_device_t *dev; - memset(data, 0, sizeof(fluidsynth_t)); + memset(data, 0, sizeof(fluidsynth_t)); - /* Try loading the DLL. */ -#ifdef _WIN32 -# if (!(defined __amd64__ || defined _M_X64 || defined __aarch64__ || defined _M_ARM64)) - fluidsynth_handle = dynld_module("libfluidsynth.dll", fluidsynth_imports); -# else - fluidsynth_handle = dynld_module("libfluidsynth64.dll", fluidsynth_imports); -# endif -#elif defined __APPLE__ - fluidsynth_handle = dynld_module("libfluidsynth.dylib", fluidsynth_imports); -#else - fluidsynth_handle = dynld_module("libfluidsynth.so.3", fluidsynth_imports); - if (fluidsynth_handle == NULL) - fluidsynth_handle = dynld_module("libfluidsynth.so.2", fluidsynth_imports); -#endif - if (fluidsynth_handle == NULL) - { - ui_msgbox_header(MBX_ERROR, (wchar_t *) IDS_2080, (wchar_t *) IDS_2133); - return NULL; - } + data->settings = new_fluid_settings(); - data->settings = f_new_fluid_settings(); + fluid_settings_setnum(data->settings, "synth.sample-rate", 44100); + fluid_settings_setnum(data->settings, "synth.gain", device_get_config_int("output_gain") / 100.0f); - f_fluid_settings_setnum(data->settings, "synth.sample-rate", 44100); - f_fluid_settings_setnum(data->settings, "synth.gain", device_get_config_int("output_gain")/100.0f); + data->synth = new_fluid_synth(data->settings); - data->synth = f_new_fluid_synth(data->settings); + const char *sound_font = device_get_config_string("sound_font"); +# ifdef __unix__ + if (!sound_font || sound_font[0] == 0) + sound_font = (access("/usr/share/sounds/sf2/FluidR3_GM.sf2", F_OK) == 0 ? "/usr/share/sounds/sf2/FluidR3_GM.sf2" : + (access("/usr/share/soundfonts/default.sf2", F_OK) == 0 ? "/usr/share/soundfonts/default.sf2" : "")); +# endif + data->sound_font = fluid_synth_sfload(data->synth, sound_font, 1); - char* sound_font = (char *) device_get_config_string("sound_font"); - data->sound_font = f_fluid_synth_sfload(data->synth, sound_font, 1); + if (device_get_config_int("chorus")) { +# ifndef USE_OLD_FLUIDSYNTH_API + fluid_synth_chorus_on(data->synth, -1, 1); +# else + fluid_synth_set_chorus_on(data->synth, 1); +# endif - if (device_get_config_int("chorus")) - { - f_fluid_synth_set_chorus_on(data->synth, 1); + int chorus_voices = device_get_config_int("chorus_voices"); + double chorus_level = device_get_config_int("chorus_level") / 100.0; + double chorus_speed = device_get_config_int("chorus_speed") / 100.0; + double chorus_depth = device_get_config_int("chorus_depth") / 10.0; - int chorus_voices = device_get_config_int("chorus_voices"); - double chorus_level = device_get_config_int("chorus_level") / 100.0; - double chorus_speed = device_get_config_int("chorus_speed") / 100.0; - double chorus_depth = device_get_config_int("chorus_depth") / 10.0; - - int chorus_waveform = FLUID_CHORUS_MOD_SINE; - if (device_get_config_int("chorus_waveform") == 0) - chorus_waveform = FLUID_CHORUS_MOD_SINE; - else - chorus_waveform = FLUID_CHORUS_MOD_TRIANGLE; - - f_fluid_synth_set_chorus(data->synth, chorus_voices, chorus_level, chorus_speed, chorus_depth, chorus_waveform); - } + int chorus_waveform = FLUID_CHORUS_MOD_SINE; + if (device_get_config_int("chorus_waveform") == 0) + chorus_waveform = FLUID_CHORUS_MOD_SINE; else - f_fluid_synth_set_chorus_on(data->synth, 0); + chorus_waveform = FLUID_CHORUS_MOD_TRIANGLE; - if (device_get_config_int("reverb")) - { - f_fluid_synth_set_reverb_on(data->synth, 1); +# ifndef USE_OLD_FLUIDSYNTH_API + fluid_synth_set_chorus_group_nr(data->synth, -1, chorus_voices); + fluid_synth_set_chorus_group_level(data->synth, -1, chorus_level); + fluid_synth_set_chorus_group_speed(data->synth, -1, chorus_speed); + fluid_synth_set_chorus_group_depth(data->synth, -1, chorus_depth); + fluid_synth_set_chorus_group_type(data->synth, -1, chorus_waveform); +# else + fluid_synth_set_chorus(data->synth, chorus_voices, chorus_level, chorus_speed, chorus_depth, chorus_waveform); +# endif + } else +# ifndef USE_OLD_FLUIDSYNTH_API + fluid_synth_chorus_on(data->synth, -1, 0); +# else + fluid_synth_set_chorus_on(data->synth, 0); +# endif - double reverb_room_size = device_get_config_int("reverb_room_size") / 100.0; - double reverb_damping = device_get_config_int("reverb_damping") / 100.0; - int reverb_width = device_get_config_int("reverb_width"); - double reverb_level = device_get_config_int("reverb_level") / 100.0; + if (device_get_config_int("reverb")) { +# ifndef USE_OLD_FLUIDSYNTH_API + fluid_synth_reverb_on(data->synth, -1, 1); +# else + fluid_synth_set_reverb_on(data->synth, 1); +# endif - f_fluid_synth_set_reverb(data->synth, reverb_room_size, reverb_damping, reverb_width, reverb_level); - } - else - f_fluid_synth_set_reverb_on(data->synth, 0); + double reverb_room_size = device_get_config_int("reverb_room_size") / 100.0; + double reverb_damping = device_get_config_int("reverb_damping") / 100.0; + double reverb_width = device_get_config_int("reverb_width") / 10.0; + double reverb_level = device_get_config_int("reverb_level") / 100.0; - int interpolation = device_get_config_int("interpolation"); - int fs_interpolation = FLUID_INTERP_4THORDER; +# ifndef USE_OLD_FLUIDSYNTH_API + fluid_synth_set_reverb_group_roomsize(data->synth, -1, reverb_room_size); + fluid_synth_set_reverb_group_damp(data->synth, -1, reverb_damping); + fluid_synth_set_reverb_group_width(data->synth, -1, reverb_width); + fluid_synth_set_reverb_group_level(data->synth, -1, reverb_level); +# else + fluid_synth_set_reverb(data->synth, reverb_room_size, reverb_damping, reverb_width, reverb_level); +# endif + } else +# ifndef USE_OLD_FLUIDSYNTH_API + fluid_synth_reverb_on(data->synth, -1, 0); +# else + fluid_synth_set_reverb_on(data->synth, 0); +# endif - if (interpolation == 0) - fs_interpolation = FLUID_INTERP_NONE; - else if (interpolation == 1) - fs_interpolation = FLUID_INTERP_LINEAR; - else if (interpolation == 2) - fs_interpolation = FLUID_INTERP_4THORDER; - else if (interpolation == 3) - fs_interpolation = FLUID_INTERP_7THORDER; + int interpolation = device_get_config_int("interpolation"); + int fs_interpolation = FLUID_INTERP_4THORDER; - f_fluid_synth_set_interp_method(data->synth, -1, fs_interpolation); + if (interpolation == 0) + fs_interpolation = FLUID_INTERP_NONE; + else if (interpolation == 1) + fs_interpolation = FLUID_INTERP_LINEAR; + else if (interpolation == 2) + fs_interpolation = FLUID_INTERP_4THORDER; + else if (interpolation == 3) + fs_interpolation = FLUID_INTERP_7THORDER; - double samplerate; - f_fluid_settings_getnum(data->settings, "synth.sample-rate", &samplerate); - data->samplerate = (int)samplerate; - if (sound_is_float) - { - data->buf_size = (data->samplerate/RENDER_RATE)*2*sizeof(float)*BUFFER_SEGMENTS; - data->buffer = malloc(data->buf_size); - data->buffer_int16 = NULL; - } - else - { - data->buf_size = (data->samplerate/RENDER_RATE)*2*sizeof(int16_t)*BUFFER_SEGMENTS; - data->buffer = NULL; - data->buffer_int16 = malloc(data->buf_size); - } + fluid_synth_set_interp_method(data->synth, -1, fs_interpolation); -#ifdef USE_OPENAL - al_set_midi(data->samplerate, data->buf_size); -#endif + double samplerate; + fluid_settings_getnum(data->settings, "synth.sample-rate", &samplerate); + data->samplerate = (int) samplerate; + if (sound_is_float) { + data->buf_size = (data->samplerate / RENDER_RATE) * 2 * sizeof(float) * BUFFER_SEGMENTS; + data->buffer = malloc(data->buf_size); + data->buffer_int16 = NULL; + } else { + data->buf_size = (data->samplerate / RENDER_RATE) * 2 * sizeof(int16_t) * BUFFER_SEGMENTS; + data->buffer = NULL; + data->buffer_int16 = malloc(data->buf_size); + } - dev = malloc(sizeof(midi_device_t)); - memset(dev, 0, sizeof(midi_device_t)); + al_set_midi(data->samplerate, data->buf_size); - dev->play_msg = fluidsynth_msg; - dev->play_sysex = fluidsynth_sysex; - dev->poll = fluidsynth_poll; + dev = malloc(sizeof(midi_device_t)); + memset(dev, 0, sizeof(midi_device_t)); - midi_init(dev); + dev->play_msg = fluidsynth_msg; + dev->play_sysex = fluidsynth_sysex; + dev->poll = fluidsynth_poll; - data->on = 1; + midi_out_init(dev); - data->start_event = thread_create_event(); + data->on = 1; - data->event = thread_create_event(); - data->thread_h = thread_create(fluidsynth_thread, data); + data->start_event = thread_create_event(); - thread_wait_event(data->start_event, -1); - thread_reset_event(data->start_event); + data->event = thread_create_event(); + data->thread_h = thread_create(fluidsynth_thread, data); - return dev; + thread_wait_event(data->start_event, -1); + thread_reset_event(data->start_event); + + return dev; } -void fluidsynth_close(void* p) +void +fluidsynth_close(void *priv) { - if (!p) return; + if (!priv) + return; - fluidsynth_t* data = &fsdev; + fluidsynth_t *data = &fsdev; - data->on = 0; - thread_set_event(data->event); - thread_wait(data->thread_h); + data->on = 0; + thread_set_event(data->event); + thread_wait(data->thread_h); - if (data->synth) { - f_delete_fluid_synth(data->synth); - data->synth = NULL; - } + if (data->synth) { + delete_fluid_synth(data->synth); + data->synth = NULL; + } - if (data->settings) { - f_delete_fluid_settings(data->settings); - data->settings = NULL; - } + if (data->settings) { + delete_fluid_settings(data->settings); + data->settings = NULL; + } - if (data->buffer) - { - free(data->buffer); - data->buffer = NULL; - } + if (data->buffer) { + free(data->buffer); + data->buffer = NULL; + } - if (data->buffer_int16) - { - free(data->buffer_int16); - data->buffer_int16 = NULL; - } - - /* Unload the DLL if possible. */ - if (fluidsynth_handle != NULL) - { - dynld_close(fluidsynth_handle); - fluidsynth_handle = NULL; - } + if (data->buffer_int16) { + free(data->buffer_int16); + data->buffer_int16 = NULL; + } } -static const device_config_t fluidsynth_config[] = -{ +static const device_config_t fluidsynth_config[] = { + // clang-format off + { + .name = "sound_font", + .description = "Sound Font", + .type = CONFIG_FNAME, + .default_string = "", + .file_filter = "SF2 Sound Fonts (*.sf2)|*.sf2" + }, + { + .name = "output_gain", + .description = "Output Gain", + .type = CONFIG_SPINNER, + .spinner = { - .name = "sound_font", - .description = "Sound Font", - .type = CONFIG_FNAME, - .default_string = "", - .file_filter = "SF2 Sound Fonts (*.sf2)|*.sf2" + .min = 0, + .max = 100 }, + .default_int = 100 + }, + { + .name = "chorus", + .description = "Chorus", + .type = CONFIG_BINARY, + .default_int = 1 + }, + { + .name = "chorus_voices", + .description = "Chorus Voices", + .type = CONFIG_SPINNER, + .spinner = { - .name = "output_gain", - .description = "Output Gain", - .type = CONFIG_SPINNER, - .spinner = - { - .min = 0, - .max = 100 - }, - .default_int = 100 + .min = 0, + .max = 99 }, + .default_int = 3 + }, + { + .name = "chorus_level", + .description = "Chorus Level", + .type = CONFIG_SPINNER, + .spinner = { - .name = "chorus", - .description = "Chorus", - .type = CONFIG_BINARY, - .default_int = 0 + .min = 0, + .max = 100 }, + .default_int = 20 + }, + { + .name = "chorus_speed", + .description = "Chorus Speed", + .type = CONFIG_SPINNER, + .spinner = { - .name = "chorus_voices", - .description = "Chorus Voices", - .type = CONFIG_SPINNER, - .spinner = - { - .min = 0, - .max = 99 - }, - .default_int = 3 + .min = 10, + .max = 500 }, + .default_int = 30 + }, + { + .name = "chorus_depth", + .description = "Chorus Depth", + .type = CONFIG_SPINNER, + .spinner = { - .name = "chorus_level", - .description = "Chorus Level", - .type = CONFIG_SPINNER, - .spinner = - { - .min = 0, - .max = 100 - }, - .default_int = 100 + .min = 0, + .max = 2560 }, + .default_int = 80 + }, + { + .name = "chorus_waveform", + .description = "Chorus Waveform", + .type = CONFIG_SELECTION, + .selection = { - .name = "chorus_speed", - .description = "Chorus Speed", - .type = CONFIG_SPINNER, - .spinner = - { - .min = 30, - .max = 500 - }, - .default_int = 30 + { + .description = "Sine", + .value = 0 + }, + { + .description = "Triangle", + .value = 1 + } }, + .default_int = 0 + }, + { + .name = "reverb", + .description = "Reverb", + .type = CONFIG_BINARY, + .default_int = 1 + }, + { + .name = "reverb_room_size", + .description = "Reverb Room Size", + .type = CONFIG_SPINNER, + .spinner = { - .name = "chorus_depth", - .description = "Chorus Depth", - .type = CONFIG_SPINNER, - .spinner = - { - .min = 0, - .max = 210 - }, - .default_int = 80 + .min = 0, + .max = 100 }, + .default_int = 20 + }, + { + .name = "reverb_damping", + .description = "Reverb Damping", + .type = CONFIG_SPINNER, + .spinner = { - .name = "chorus_waveform", - .description = "Chorus Waveform", - .type = CONFIG_SELECTION, - .selection = - { - { - .description = "Sine", - .value = 0 - }, - { - .description = "Triangle", - .value = 1 - } - }, - .default_int = 0 + .min = 0, + .max = 100 }, + .default_int = 0 + }, + { + .name = "reverb_width", + .description = "Reverb Width", + .type = CONFIG_SPINNER, + .spinner = { - .name = "reverb", - .description = "Reverb", - .type = CONFIG_BINARY, - .default_int = 0 + .min = 0, + .max = 1000 }, + .default_int = 5 + }, + { + .name = "reverb_level", + .description = "Reverb Level", + .type = CONFIG_SPINNER, + .spinner = { - .name = "reverb_room_size", - .description = "Reverb Room Size", - .type = CONFIG_SPINNER, - .spinner = - { - .min = 0, - .max = 120 - }, - .default_int = 20 + .min = 0, + .max = 100 }, + .default_int = 90 + }, + { + .name = "interpolation", + .description = "Interpolation Method", + .type = CONFIG_SELECTION, + .selection = { - .name = "reverb_damping", - .description = "Reverb Damping", - .type = CONFIG_SPINNER, - .spinner = - { - .min = 0, - .max = 100 - }, - .default_int = 0 + { + .description = "None", + .value = 0 + }, + { + .description = "Linear", + .value = 1 + }, + { + .description = "4th Order", + .value = 2 + }, + { + .description = "7th Order", + .value = 3 + } }, - { - .name = "reverb_width", - .description = "Reverb Width", - .type = CONFIG_SPINNER, - .spinner = - { - .min = 0, - .max = 100 - }, - .default_int = 1 - }, - { - .name = "reverb_level", - .description = "Reverb Level", - .type = CONFIG_SPINNER, - .spinner = - { - .min = 0, - .max = 100 - }, - .default_int = 90 - }, - { - .name = "interpolation", - .description = "Interpolation Method", - .type = CONFIG_SELECTION, - .selection = - { - { - .description = "None", - .value = 0 - }, - { - .description = "Linear", - .value = 1 - }, - { - .description = "4th Order", - .value = 2 - }, - { - .description = "7th Order", - .value = 3 - } - }, - .default_int = 2 - }, - { - .type = -1 - } + .default_int = 2 + }, + { .name = "", .description = "", .type = CONFIG_END } + // clang-format on }; -const device_t fluidsynth_device = -{ - "FluidSynth", - "fluidsynth", - 0, - 0, - fluidsynth_init, - fluidsynth_close, - NULL, - { fluidsynth_available }, - NULL, - NULL, - fluidsynth_config +const device_t fluidsynth_device = { + .name = "FluidSynth", + .internal_name = "fluidsynth", + .flags = 0, + .local = 0, + .init = fluidsynth_init, + .close = fluidsynth_close, + .reset = NULL, + { .available = fluidsynth_available }, + .speed_changed = NULL, + .force_redraw = NULL, + .config = fluidsynth_config }; - -#endif /*USE_FLUIDSYNTH*/ +#endif /*USE_FLUIDSYNTH*/ diff --git a/src/sound/midi_mt32.c b/src/sound/midi_mt32.c index 00c26b392..91d85e438 100644 --- a/src/sound/midi_mt32.c +++ b/src/sound/midi_mt32.c @@ -1,402 +1,476 @@ -#include #include -#include +#include #include +#include #include -#include + #include <86box/86box.h> #include <86box/device.h> #include <86box/mem.h> -#include <86box/rom.h> -#include <86box/plat.h> -#include <86box/ui.h> -#include <86box/sound.h> #include <86box/midi.h> +#include <86box/plat.h> +#include <86box/thread.h> +#include <86box/rom.h> +#include <86box/sound.h> +#include <86box/ui.h> +#include +#define MT32_OLD_CTRL_ROM "roms/sound/mt32/MT32_CONTROL.ROM" +#define MT32_OLD_PCM_ROM "roms/sound/mt32/MT32_PCM.ROM" +#define MT32_NEW_CTRL_ROM "roms/sound/mt32_new/MT32_CONTROL.ROM" +#define MT32_NEW_PCM_ROM "roms/sound/mt32_new/MT32_PCM.ROM" +#define CM32L_CTRL_ROM "roms/sound/cm32l/CM32L_CONTROL.ROM" +#define CM32L_PCM_ROM "roms/sound/cm32l/CM32L_PCM.ROM" +#define CM32LN_CTRL_ROM "roms/sound/cm32ln/CM32LN_CONTROL.ROM" +#define CM32LN_PCM_ROM "roms/sound/cm32ln/CM32LN_PCM.ROM" -#ifdef USE_OPENAL extern void givealbuffer_midi(void *buf, uint32_t size); extern void al_set_midi(int freq, int buf_size); -#endif -static void display_mt32_message(void *instance_data, const char *message); +static mt32emu_report_handler_version get_mt32_report_handler_version(mt32emu_report_handler_i i); +static void display_mt32_message(void *instance_data, const char *message); static const mt32emu_report_handler_i_v0 handler_mt32_v0 = { - /** Returns the actual interface version ID */ - NULL, //mt32emu_report_handler_version (*getVersionID)(mt32emu_report_handler_i i); + /** Returns the actual interface version ID */ + get_mt32_report_handler_version, // mt32emu_report_handler_version (*getVersionID)(mt32emu_report_handler_i i); - /** Callback for debug messages, in vprintf() format */ - NULL, //void (*printDebug)(void *instance_data, const char *fmt, va_list list); - /** Callbacks for reporting errors */ - NULL, //void (*onErrorControlROM)(void *instance_data); - NULL, //void (*onErrorPCMROM)(void *instance_data); - /** Callback for reporting about displaying a new custom message on LCD */ - display_mt32_message, //void (*showLCDMessage)(void *instance_data, const char *message); - /** Callback for reporting actual processing of a MIDI message */ - NULL, //void (*onMIDIMessagePlayed)(void *instance_data); - /** - * Callback for reporting an overflow of the input MIDI queue. - * Returns MT32EMU_BOOL_TRUE if a recovery action was taken - * and yet another attempt to enqueue the MIDI event is desired. - */ - NULL, //mt32emu_boolean (*onMIDIQueueOverflow)(void *instance_data); - /** - * Callback invoked when a System Realtime MIDI message is detected in functions - * mt32emu_parse_stream and mt32emu_play_short_message and the likes. - */ - NULL, //void (*onMIDISystemRealtime)(void *instance_data, mt32emu_bit8u system_realtime); - /** Callbacks for reporting system events */ - NULL, //void (*onDeviceReset)(void *instance_data); - NULL, //void (*onDeviceReconfig)(void *instance_data); - /** Callbacks for reporting changes of reverb settings */ - NULL, //void (*onNewReverbMode)(void *instance_data, mt32emu_bit8u mode); - NULL, //void (*onNewReverbTime)(void *instance_data, mt32emu_bit8u time); - NULL, //void (*onNewReverbLevel)(void *instance_data, mt32emu_bit8u level); - /** Callbacks for reporting various information */ - NULL, //void (*onPolyStateChanged)(void *instance_data, mt32emu_bit8u part_num); - NULL, //void (*onProgramChanged)(void *instance_data, mt32emu_bit8u part_num, const char *sound_group_name, const char *patch_name); + /** Callback for debug messages, in vprintf() format */ + NULL, // void (*printDebug)(void *instance_data, const char *fmt, va_list list); + /** Callbacks for reporting errors */ + NULL, // void (*onErrorControlROM)(void *instance_data); + NULL, // void (*onErrorPCMROM)(void *instance_data); + /** Callback for reporting about displaying a new custom message on LCD */ + display_mt32_message, // void (*showLCDMessage)(void *instance_data, const char *message); + /** Callback for reporting actual processing of a MIDI message */ + NULL, // void (*onMIDIMessagePlayed)(void *instance_data); + /** + * Callback for reporting an overflow of the input MIDI queue. + * Returns MT32EMU_BOOL_TRUE if a recovery action was taken + * and yet another attempt to enqueue the MIDI event is desired. + */ + NULL, // mt32emu_boolean (*onMIDIQueueOverflow)(void *instance_data); + /** + * Callback invoked when a System Realtime MIDI message is detected in functions + * mt32emu_parse_stream and mt32emu_play_short_message and the likes. + */ + NULL, // void (*onMIDISystemRealtime)(void *instance_data, mt32emu_bit8u system_realtime); + /** Callbacks for reporting system events */ + NULL, // void (*onDeviceReset)(void *instance_data); + NULL, // void (*onDeviceReconfig)(void *instance_data); + /** Callbacks for reporting changes of reverb settings */ + NULL, // void (*onNewReverbMode)(void *instance_data, mt32emu_bit8u mode); + NULL, // void (*onNewReverbTime)(void *instance_data, mt32emu_bit8u time); + NULL, // void (*onNewReverbLevel)(void *instance_data, mt32emu_bit8u level); + /** Callbacks for reporting various information */ + NULL, // void (*onPolyStateChanged)(void *instance_data, mt32emu_bit8u part_num); + NULL, // void (*onProgramChanged)(void *instance_data, mt32emu_bit8u part_num, const char *sound_group_name, const char *patch_name); }; -/** Alternate report handler for Roland CM-32L */ +/** Alternate report handler for Roland CM-32L/CM-32LN */ static const mt32emu_report_handler_i_v0 handler_cm32l_v0 = { - /** Returns the actual interface version ID */ - NULL, //mt32emu_report_handler_version (*getVersionID)(mt32emu_report_handler_i i); + /** Returns the actual interface version ID */ + get_mt32_report_handler_version, // mt32emu_report_handler_version (*getVersionID)(mt32emu_report_handler_i i); - /** Callback for debug messages, in vprintf() format */ - NULL, //void (*printDebug)(void *instance_data, const char *fmt, va_list list); - /** Callbacks for reporting errors */ - NULL, //void (*onErrorControlROM)(void *instance_data); - NULL, //void (*onErrorPCMROM)(void *instance_data); - /** Callback for reporting about displaying a new custom message on LCD */ - NULL, //void (*showLCDMessage)(void *instance_data, const char *message); - /** Callback for reporting actual processing of a MIDI message */ - NULL, //void (*onMIDIMessagePlayed)(void *instance_data); - /** - * Callback for reporting an overflow of the input MIDI queue. - * Returns MT32EMU_BOOL_TRUE if a recovery action was taken - * and yet another attempt to enqueue the MIDI event is desired. - */ - NULL, //mt32emu_boolean (*onMIDIQueueOverflow)(void *instance_data); - /** - * Callback invoked when a System Realtime MIDI message is detected in functions - * mt32emu_parse_stream and mt32emu_play_short_message and the likes. - */ - NULL, //void (*onMIDISystemRealtime)(void *instance_data, mt32emu_bit8u system_realtime); - /** Callbacks for reporting system events */ - NULL, //void (*onDeviceReset)(void *instance_data); - NULL, //void (*onDeviceReconfig)(void *instance_data); - /** Callbacks for reporting changes of reverb settings */ - NULL, //void (*onNewReverbMode)(void *instance_data, mt32emu_bit8u mode); - NULL, //void (*onNewReverbTime)(void *instance_data, mt32emu_bit8u time); - NULL, //void (*onNewReverbLevel)(void *instance_data, mt32emu_bit8u level); - /** Callbacks for reporting various information */ - NULL, //void (*onPolyStateChanged)(void *instance_data, mt32emu_bit8u part_num); - NULL, //void (*onProgramChanged)(void *instance_data, mt32emu_bit8u part_num, const char *sound_group_name, const char *patch_name); + /** Callback for debug messages, in vprintf() format */ + NULL, // void (*printDebug)(void *instance_data, const char *fmt, va_list list); + /** Callbacks for reporting errors */ + NULL, // void (*onErrorControlROM)(void *instance_data); + NULL, // void (*onErrorPCMROM)(void *instance_data); + /** Callback for reporting about displaying a new custom message on LCD */ + NULL, // void (*showLCDMessage)(void *instance_data, const char *message); + /** Callback for reporting actual processing of a MIDI message */ + NULL, // void (*onMIDIMessagePlayed)(void *instance_data); + /** + * Callback for reporting an overflow of the input MIDI queue. + * Returns MT32EMU_BOOL_TRUE if a recovery action was taken + * and yet another attempt to enqueue the MIDI event is desired. + */ + NULL, // mt32emu_boolean (*onMIDIQueueOverflow)(void *instance_data); + /** + * Callback invoked when a System Realtime MIDI message is detected in functions + * mt32emu_parse_stream and mt32emu_play_short_message and the likes. + */ + NULL, // void (*onMIDISystemRealtime)(void *instance_data, mt32emu_bit8u system_realtime); + /** Callbacks for reporting system events */ + NULL, // void (*onDeviceReset)(void *instance_data); + NULL, // void (*onDeviceReconfig)(void *instance_data); + /** Callbacks for reporting changes of reverb settings */ + NULL, // void (*onNewReverbMode)(void *instance_data, mt32emu_bit8u mode); + NULL, // void (*onNewReverbTime)(void *instance_data, mt32emu_bit8u time); + NULL, // void (*onNewReverbLevel)(void *instance_data, mt32emu_bit8u level); + /** Callbacks for reporting various information */ + NULL, // void (*onPolyStateChanged)(void *instance_data, mt32emu_bit8u part_num); + NULL, // void (*onProgramChanged)(void *instance_data, mt32emu_bit8u part_num, const char *sound_group_name, const char *patch_name); }; -static const mt32emu_report_handler_i handler_mt32 = { &handler_mt32_v0 }; +static const mt32emu_report_handler_i handler_mt32 = { &handler_mt32_v0 }; static const mt32emu_report_handler_i handler_cm32l = { &handler_cm32l_v0 }; -static mt32emu_context context = NULL; -static int roms_present[2] = {-1, -1}; +static mt32emu_context context = NULL; +static int roms_present[2] = { -1, -1 }; -mt32emu_return_code mt32_check(const char* func, mt32emu_return_code ret, mt32emu_return_code expected) +mt32emu_return_code +mt32_check(UNUSED(const char *func), mt32emu_return_code ret, mt32emu_return_code expected) { - if (ret != expected) - { - return 0; - } - return 1; + if (ret != expected) { + return 0; + } + return 1; } -int mt32_available() +int +mt32_old_available(void) { - if (roms_present[0] < 0) - roms_present[0] = (rom_present("roms/sound/mt32/MT32_CONTROL.ROM") && rom_present("roms/sound/mt32/MT32_PCM.ROM")); - return roms_present[0]; + if (roms_present[0] < 0) + roms_present[0] = (rom_present(MT32_OLD_CTRL_ROM) && rom_present(MT32_OLD_PCM_ROM)); + return roms_present[0]; } -int cm32l_available() +int +mt32_new_available(void) { - if (roms_present[1] < 0) - roms_present[1] = (rom_present("roms/sound/cm32l/CM32L_CONTROL.ROM") && rom_present("roms/sound/cm32l/CM32L_PCM.ROM")); - return roms_present[1]; + if (roms_present[0] < 0) + roms_present[0] = (rom_present(MT32_NEW_CTRL_ROM) && rom_present(MT32_NEW_PCM_ROM)); + return roms_present[0]; } -static thread_t *thread_h = NULL; -static event_t *event = NULL; -static event_t *start_event = NULL; -static int mt32_on = 0; +int +cm32l_available(void) +{ + if (roms_present[1] < 0) + roms_present[1] = (rom_present(CM32L_CTRL_ROM) && rom_present(CM32L_PCM_ROM)); + return roms_present[1]; +} -#define RENDER_RATE 100 +int +cm32ln_available(void) +{ + if (roms_present[1] < 0) + roms_present[1] = (rom_present(CM32LN_CTRL_ROM) && rom_present(CM32LN_PCM_ROM)); + return roms_present[1]; +} + +static thread_t *thread_h = NULL; +static event_t *event = NULL; +static event_t *start_event = NULL; +static int mt32_on = 0; + +#define RENDER_RATE 100 #define BUFFER_SEGMENTS 10 -static uint32_t samplerate = 44100; -static int buf_size = 0; -static float* buffer = NULL; -static int16_t* buffer_int16 = NULL; -static int midi_pos = 0; +static uint32_t samplerate = 44100; +static int buf_size = 0; +static float *buffer = NULL; +static int16_t *buffer_int16 = NULL; +static int midi_pos = 0; -static void display_mt32_message(void *instance_data, const char *message) +static mt32emu_report_handler_version +get_mt32_report_handler_version(UNUSED(mt32emu_report_handler_i i)) { - int sz = 0; - char* ui_msg = NULL; + return MT32EMU_REPORT_HANDLER_VERSION_0; +} - sz = snprintf(NULL, 0, "MT-32: %s", message); +static void +display_mt32_message(UNUSED(void *instance_data), const char *message) +{ + int sz = 0; + char *ui_msg = NULL; + + sz = snprintf(NULL, 0, "MT-32: %s", message); ui_msg = calloc(sz + 1, 1); - if (ui_msg) - { + if (ui_msg) { snprintf(ui_msg, sz, "MT-32: %s", message); ui_sb_mt32lcd(ui_msg); } } -void mt32_stream(float* stream, int len) +void +mt32_stream(float *stream, int len) { - if (context) mt32emu_render_float(context, stream, len); + if (context) + mt32emu_render_float(context, stream, len); } -void mt32_stream_int16(int16_t* stream, int len) +void +mt32_stream_int16(int16_t *stream, int len) { - if (context) mt32emu_render_bit16s(context, stream, len); + if (context) + mt32emu_render_bit16s(context, stream, len); } -void mt32_poll() +void +mt32_poll(void) { - midi_pos++; - if (midi_pos == 48000/RENDER_RATE) - { - midi_pos = 0; - thread_set_event(event); + midi_pos++; + if (midi_pos == SOUND_FREQ / RENDER_RATE) { + midi_pos = 0; + thread_set_event(event); + } +} + +static void +mt32_thread(UNUSED(void *param)) +{ + int buf_pos = 0; + int bsize = buf_size / BUFFER_SEGMENTS; + float *buf; + int16_t *buf16; + + thread_set_event(start_event); + + while (mt32_on) { + thread_wait_event(event, -1); + thread_reset_event(event); + + if (sound_is_float) { + buf = (float *) ((uint8_t *) buffer + buf_pos); + memset(buf, 0, bsize); + mt32_stream(buf, bsize / (2 * sizeof(float))); + buf_pos += bsize; + if (buf_pos >= buf_size) { + givealbuffer_midi(buffer, buf_size / sizeof(float)); + buf_pos = 0; + } + } else { + buf16 = (int16_t *) ((uint8_t *) buffer_int16 + buf_pos); + memset(buf16, 0, bsize); + mt32_stream_int16(buf16, bsize / (2 * sizeof(int16_t))); + buf_pos += bsize; + if (buf_pos >= buf_size) { + givealbuffer_midi(buffer_int16, buf_size / sizeof(int16_t)); + buf_pos = 0; + } } + } } -static void mt32_thread(void *param) +void +mt32_msg(uint8_t *val) { - int buf_pos = 0; - int bsize = buf_size / BUFFER_SEGMENTS; - float *buf; - int16_t *buf16; - - thread_set_event(start_event); - - while (mt32_on) - { - thread_wait_event(event, -1); - thread_reset_event(event); - - if (sound_is_float) - { - buf = (float *) ((uint8_t*)buffer + buf_pos); - memset(buf, 0, bsize); - mt32_stream(buf, bsize / (2 * sizeof(float))); - buf_pos += bsize; - if (buf_pos >= buf_size) - { -#ifdef USE_OPENAL - givealbuffer_midi(buffer, buf_size / sizeof(float)); -#endif - buf_pos = 0; - } - } - else - { - buf16 = (int16_t *) ((uint8_t*)buffer_int16 + buf_pos); - memset(buf16, 0, bsize); - mt32_stream_int16(buf16, bsize / (2 * sizeof(int16_t))); - buf_pos += bsize; - if (buf_pos >= buf_size) - { -#ifdef USE_OPENAL - givealbuffer_midi(buffer_int16, buf_size / sizeof(int16_t)); -#endif - buf_pos = 0; - } - } - } + if (context) + mt32_check("mt32emu_play_msg", mt32emu_play_msg(context, *(uint32_t *) val), MT32EMU_RC_OK); } -void mt32_msg(uint8_t* val) +void +mt32_sysex(uint8_t *data, unsigned int len) { - if (context) mt32_check("mt32emu_play_msg", mt32emu_play_msg(context, *(uint32_t*)val), MT32EMU_RC_OK); + if (context) + mt32_check("mt32emu_play_sysex", mt32emu_play_sysex(context, data, len), MT32EMU_RC_OK); } -void mt32_sysex(uint8_t* data, unsigned int len) +void * +mt32emu_init(char *control_rom, char *pcm_rom) { - if (context) mt32_check("mt32emu_play_sysex", mt32emu_play_sysex(context, data, len), MT32EMU_RC_OK); -} + midi_device_t *dev; + char fn[512]; -void* mt32emu_init(char *control_rom, char *pcm_rom) -{ - midi_device_t* dev; - char fn[512]; + context = mt32emu_create_context(strstr(control_rom, "MT32_CONTROL.ROM") ? handler_mt32 : handler_cm32l, NULL); - context = mt32emu_create_context(strstr(control_rom, "CM32L_CONTROL.ROM") ? handler_cm32l : handler_mt32, NULL); + if (!rom_getfile(control_rom, fn, 512)) + return 0; + if (!mt32_check("mt32emu_add_rom_file", mt32emu_add_rom_file(context, fn), MT32EMU_RC_ADDED_CONTROL_ROM)) + return 0; + if (!rom_getfile(pcm_rom, fn, 512)) + return 0; + if (!mt32_check("mt32emu_add_rom_file", mt32emu_add_rom_file(context, fn), MT32EMU_RC_ADDED_PCM_ROM)) + return 0; - if (!rom_getfile(control_rom, fn, 512)) return 0; - if (!mt32_check("mt32emu_add_rom_file", mt32emu_add_rom_file(context, fn), MT32EMU_RC_ADDED_CONTROL_ROM)) return 0; - if (!rom_getfile(pcm_rom, fn, 512)) return 0; - if (!mt32_check("mt32emu_add_rom_file", mt32emu_add_rom_file(context, fn), MT32EMU_RC_ADDED_PCM_ROM)) return 0; + if (!mt32_check("mt32emu_open_synth", mt32emu_open_synth(context), MT32EMU_RC_OK)) + return 0; - if (!mt32_check("mt32emu_open_synth", mt32emu_open_synth(context), MT32EMU_RC_OK)) return 0; - - samplerate = mt32emu_get_actual_stereo_output_samplerate(context); - /* buf_size = samplerate/RENDER_RATE*2; */ - if (sound_is_float) - { - buf_size = (samplerate/RENDER_RATE)*2*BUFFER_SEGMENTS*sizeof(float); - buffer = malloc(buf_size); - buffer_int16 = NULL; - } - else - { - buf_size = (samplerate/RENDER_RATE)*2*BUFFER_SEGMENTS*sizeof(int16_t); - buffer = NULL; - buffer_int16 = malloc(buf_size); - } - - mt32emu_set_output_gain(context, device_get_config_int("output_gain")/100.0f); - mt32emu_set_reverb_enabled(context, device_get_config_int("reverb")); - mt32emu_set_reverb_output_gain(context, device_get_config_int("reverb_output_gain")/100.0f); - mt32emu_set_reversed_stereo_enabled(context, device_get_config_int("reversed_stereo")); - mt32emu_set_nice_amp_ramp_enabled(context, device_get_config_int("nice_ramp")); - -#ifdef USE_OPENAL - al_set_midi(samplerate, buf_size); -#endif - - dev = malloc(sizeof(midi_device_t)); - memset(dev, 0, sizeof(midi_device_t)); - - dev->play_msg = mt32_msg; - dev->play_sysex = mt32_sysex; - dev->poll = mt32_poll; - - midi_init(dev); - - mt32_on = 1; - - start_event = thread_create_event(); - - event = thread_create_event(); - thread_h = thread_create(mt32_thread, 0); - - thread_wait_event(start_event, -1); - thread_reset_event(start_event); - - return dev; -} - -void *mt32_init(const device_t *info) -{ - return mt32emu_init("roms/sound/mt32/MT32_CONTROL.ROM", "roms/sound/mt32/MT32_PCM.ROM"); -} - -void *cm32l_init(const device_t *info) -{ - return mt32emu_init("roms/sound/cm32l/CM32L_CONTROL.ROM", "roms/sound/cm32l/CM32L_PCM.ROM"); -} - -void mt32_close(void* p) -{ - if (!p) return; - - mt32_on = 0; - thread_set_event(event); - thread_wait(thread_h); - - event = NULL; - start_event = NULL; - thread_h = NULL; - - if (context) { - mt32emu_close_synth(context); - mt32emu_free_context(context); - } - context = NULL; - - if (buffer) - free(buffer); - buffer = NULL; - - if (buffer_int16) - free(buffer_int16); + samplerate = mt32emu_get_actual_stereo_output_samplerate(context); + /* buf_size = samplerate/RENDER_RATE*2; */ + if (sound_is_float) { + buf_size = (samplerate / RENDER_RATE) * 2 * BUFFER_SEGMENTS * sizeof(float); + buffer = malloc(buf_size); buffer_int16 = NULL; + } else { + buf_size = (samplerate / RENDER_RATE) * 2 * BUFFER_SEGMENTS * sizeof(int16_t); + buffer = NULL; + buffer_int16 = malloc(buf_size); + } + + mt32emu_set_output_gain(context, device_get_config_int("output_gain") / 100.0f); + mt32emu_set_reverb_enabled(context, device_get_config_int("reverb")); + mt32emu_set_reverb_output_gain(context, device_get_config_int("reverb_output_gain") / 100.0f); + mt32emu_set_reversed_stereo_enabled(context, device_get_config_int("reversed_stereo")); + mt32emu_set_nice_amp_ramp_enabled(context, device_get_config_int("nice_ramp")); + + al_set_midi(samplerate, buf_size); + + dev = malloc(sizeof(midi_device_t)); + memset(dev, 0, sizeof(midi_device_t)); + + dev->play_msg = mt32_msg; + dev->play_sysex = mt32_sysex; + dev->poll = mt32_poll; + + midi_out_init(dev); + + mt32_on = 1; + + start_event = thread_create_event(); + + event = thread_create_event(); + thread_h = thread_create(mt32_thread, 0); + + thread_wait_event(start_event, -1); + thread_reset_event(start_event); + + return dev; } -static const device_config_t mt32_config[] = +void * +mt32_old_init(UNUSED(const device_t *info)) { - { - .name = "output_gain", - .description = "Output Gain", - .type = CONFIG_SPINNER, - .spinner = - { - .min = 0, - .max = 100 - }, - .default_int = 100 + return mt32emu_init(MT32_OLD_CTRL_ROM, MT32_OLD_PCM_ROM); +} + +void * +mt32_new_init(UNUSED(const device_t *info)) +{ + return mt32emu_init(MT32_NEW_CTRL_ROM, MT32_NEW_PCM_ROM); +} + +void * +cm32l_init(UNUSED(const device_t *info)) +{ + return mt32emu_init(CM32L_CTRL_ROM, CM32L_PCM_ROM); +} + +void * +cm32ln_init(UNUSED(const device_t *info)) +{ + return mt32emu_init(CM32LN_CTRL_ROM, CM32LN_PCM_ROM); +} + +void +mt32_close(void *priv) +{ + if (!priv) + return; + + mt32_on = 0; + thread_set_event(event); + thread_wait(thread_h); + + event = NULL; + start_event = NULL; + thread_h = NULL; + + if (context) { + mt32emu_close_synth(context); + mt32emu_free_context(context); + } + context = NULL; + + ui_sb_mt32lcd(""); + + if (buffer) + free(buffer); + buffer = NULL; + + if (buffer_int16) + free(buffer_int16); + buffer_int16 = NULL; +} + +static const device_config_t mt32_config[] = { + // clang-format off + { + .name = "output_gain", + .description = "Output Gain", + .type = CONFIG_SPINNER, + .spinner = { + .min = 0, + .max = 100 }, - { - .name = "reverb", - .description = "Reverb", - .type = CONFIG_BINARY, - .default_int = 1 + .default_int = 100 + }, + { + .name = "reverb", + .description = "Reverb", + .type = CONFIG_BINARY, + .default_int = 1 + }, + { + .name = "reverb_output_gain", + .description = "Reverb Output Gain", + .type = CONFIG_SPINNER, + .spinner = { + .min = 0, + .max = 100 }, - { - .name = "reverb_output_gain", - .description = "Reverb Output Gain", - .type = CONFIG_SPINNER, - .spinner = - { - .min = 0, - .max = 100 - }, - .default_int = 100 - }, - { - .name = "reversed_stereo", - .description = "Reversed stereo", - .type = CONFIG_BINARY, - .default_int = 0 - }, - { - .name = "nice_ramp", - .description = "Nice ramp", - .type = CONFIG_BINARY, - .default_int = 1 - }, - { - .type = -1 - } + .default_int = 100 + }, + { + .name = "reversed_stereo", + .description = "Reversed stereo", + .type = CONFIG_BINARY, + .default_int = 0 + }, + { + .name = "nice_ramp", + .description = "Nice ramp", + .type = CONFIG_BINARY, + .default_int = 1 + }, + { .name = "", .description = "", .type = CONFIG_END } + // clang-format on }; -const device_t mt32_device = -{ - "Roland MT-32 Emulation", - "mt32", - 0, - 0, - mt32_init, - mt32_close, - NULL, - { mt32_available }, - NULL, - NULL, - mt32_config +const device_t mt32_old_device = { + .name = "Roland MT-32 Emulation", + .internal_name = "mt32", + .flags = 0, + .local = 0, + .init = mt32_old_init, + .close = mt32_close, + .reset = NULL, + { .available = mt32_old_available }, + .speed_changed = NULL, + .force_redraw = NULL, + .config = mt32_config }; -const device_t cm32l_device = -{ - "Roland CM-32L Emulation", - "cm32l", - 0, - 0, - cm32l_init, - mt32_close, - NULL, - { cm32l_available }, - NULL, - NULL, - mt32_config +const device_t mt32_new_device = { + .name = "Roland MT-32 (New) Emulation", + .internal_name = "mt32", + .flags = 0, + .local = 0, + .init = mt32_new_init, + .close = mt32_close, + .reset = NULL, + { .available = mt32_new_available }, + .speed_changed = NULL, + .force_redraw = NULL, + .config = mt32_config +}; + +const device_t cm32l_device = { + .name = "Roland CM-32L Emulation", + .internal_name = "cm32l", + .flags = 0, + .local = 0, + .init = cm32l_init, + .close = mt32_close, + .reset = NULL, + { .available = cm32l_available }, + .speed_changed = NULL, + .force_redraw = NULL, + .config = mt32_config +}; + +const device_t cm32ln_device = { + .name = "Roland CM-32LN Emulation", + .internal_name = "cm32ln", + .flags = 0, + .local = 0, + .init = cm32ln_init, + .close = mt32_close, + .reset = NULL, + { .available = cm32ln_available }, + .speed_changed = NULL, + .force_redraw = NULL, + .config = mt32_config }; diff --git a/src/sound/midi_rtmidi.cpp b/src/sound/midi_rtmidi.cpp index 48877924c..72df8fd32 100644 --- a/src/sound/midi_rtmidi.cpp +++ b/src/sound/midi_rtmidi.cpp @@ -1,25 +1,26 @@ /* - * 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. + * 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. + * This file is part of the 86Box distribution. * - * MIDI backend implemented using the RtMidi library. + * MIDI backend implemented using the RtMidi library. * - * Author: Cacodemon345, - * Miran Grca, - * Copyright 2021 Cacodemon345. - * Copyright 2021 Miran Grca. + * Author: Cacodemon345, + * Miran Grca, + * Copyright 2021 Cacodemon345. + * Copyright 2021 Miran Grca. */ + #if defined __has_include -# if __has_include () -# include -# endif -# if __has_include () -# include -# endif +# if __has_include() +# include +# endif +# if __has_include() +# include +# endif #endif #include @@ -27,160 +28,160 @@ #include #include -extern "C" -{ +extern "C" { #include <86box/86box.h> #include <86box/device.h> #include <86box/midi.h> #include <86box/midi_rtmidi.h> +#include <86box/ini.h> #include <86box/config.h> +#include <86box/plat_unused.h> +// Disable c99-designator to avoid the warnings in rtmidi_*_device +#ifdef __clang__ +# if __has_warning("-Wc99-designator") +# pragma clang diagnostic push +# pragma clang diagnostic ignored "-Wc99-designator" +# endif +#endif -static RtMidiOut * midiout = nullptr; -static RtMidiIn * midiin = nullptr; -static int midi_out_id = 0, midi_in_id = 0; -static const int midi_lengths[8] = {3, 3, 3, 3, 2, 2, 3, 1}; - +static RtMidiOut *midiout = nullptr; +static RtMidiIn *midiin = nullptr; +static int midi_out_id = 0, midi_in_id = 0; +static const int midi_lengths[8] = { 3, 3, 3, 3, 2, 2, 3, 1 }; int -rtmidi_write(uint8_t val) +rtmidi_write(UNUSED(uint8_t val)) { return 0; } - void rtmidi_play_msg(uint8_t *msg) { if (midiout) - midiout->sendMessage(msg, midi_lengths[(msg[0] >> 4) & 7]); + midiout->sendMessage(msg, midi_lengths[(msg[0] >> 4) & 7]); } - void rtmidi_play_sysex(uint8_t *sysex, unsigned int len) { if (midiout) - midiout->sendMessage(sysex, len); + midiout->sendMessage(sysex, len); } - -void* -rtmidi_init(const device_t *info) +void * +rtmidi_output_init(UNUSED(const device_t *info)) { - midi_device_t* dev = (midi_device_t*)malloc(sizeof(midi_device_t)); + midi_device_t *dev = (midi_device_t *) malloc(sizeof(midi_device_t)); memset(dev, 0, sizeof(midi_device_t)); - dev->play_msg = rtmidi_play_msg; + dev->play_msg = rtmidi_play_msg; dev->play_sysex = rtmidi_play_sysex; - dev->write = rtmidi_write; + dev->write = rtmidi_write; try { - if (!midiout) midiout = new RtMidiOut; - } catch (RtMidiError& error) { - pclog("Failed to initialize MIDI output: %s\n", error.getMessage().c_str()); - return nullptr; + if (!midiout) + midiout = new RtMidiOut; + } catch (RtMidiError &error) { + pclog("Failed to initialize MIDI output: %s\n", error.getMessage().c_str()); + return nullptr; } - midi_out_id = config_get_int((char*)SYSTEM_MIDI_NAME, (char*)"midi", 0); + midi_out_id = config_get_int((char *) SYSTEM_MIDI_NAME, (char *) "midi", 0); try { - midiout->openPort(midi_out_id); - } catch (RtMidiError& error) { - pclog("Fallback to default MIDI output port: %s\n", error.getMessage().c_str()); + midiout->openPort(midi_out_id); + } catch (RtMidiError &error) { + pclog("Fallback to default MIDI output port: %s\n", error.getMessage().c_str()); - try { - midiout->openPort(0); - } catch (RtMidiError& error) { - pclog("Failed to initialize MIDI output: %s\n", error.getMessage().c_str()); - delete midiout; - midiout = nullptr; - return nullptr; - } + try { + midiout->openPort(0); + } catch (RtMidiError &error) { + pclog("Failed to initialize MIDI output: %s\n", error.getMessage().c_str()); + delete midiout; + midiout = nullptr; + return nullptr; + } } - midi_init(dev); + midi_out_init(dev); return dev; } - void -rtmidi_close(void *p) +rtmidi_output_close(UNUSED(void *priv)) { if (!midiout) - return; + return; midiout->closePort(); delete midiout; midiout = nullptr; - midi_close(); + midi_out_close(); } - int -rtmidi_get_num_devs(void) +rtmidi_out_get_num_devs(void) { if (!midiout) { - try { - midiout = new RtMidiOut; - } catch (RtMidiError& error) { - pclog("Failed to initialize MIDI output: %s\n", error.getMessage().c_str()); - } + try { + midiout = new RtMidiOut; + } catch (RtMidiError &error) { + pclog("Failed to initialize MIDI output: %s\n", error.getMessage().c_str()); + } } return midiout ? midiout->getPortCount() : 0; } - void -rtmidi_get_dev_name(int num, char *s) +rtmidi_out_get_dev_name(int num, char *s) { strcpy(s, midiout->getPortName(num).c_str()); } - void -rtmidi_input_callback(double timeStamp, std::vector *message, void *userData) +rtmidi_input_callback(UNUSED(double timeStamp), std::vector *message, UNUSED(void *userData)) { if (message->front() == 0xF0) midi_in_sysex(message->data(), message->size()); else - midi_in_msg(message->data(), message->size()); + midi_in_msg(message->data(), message->size()); } - -void* -rtmidi_input_init(const device_t *info) +void * +rtmidi_input_init(UNUSED(const device_t *info)) { - midi_device_t* dev = (midi_device_t*)malloc(sizeof(midi_device_t)); + midi_device_t *dev = (midi_device_t *) malloc(sizeof(midi_device_t)); memset(dev, 0, sizeof(midi_device_t)); try { - if (!midiin) - midiin = new RtMidiIn; - } catch (RtMidiError& error) { - pclog("Failed to initialize MIDI input: %s\n", error.getMessage().c_str()); - return nullptr; + if (!midiin) + midiin = new RtMidiIn; + } catch (RtMidiError &error) { + pclog("Failed to initialize MIDI input: %s\n", error.getMessage().c_str()); + return nullptr; } - midi_in_id = config_get_int((char*)MIDI_INPUT_NAME, (char*)"midi_input", 0); + midi_in_id = config_get_int((char *) MIDI_INPUT_NAME, (char *) "midi_input", 0); try { - midiin->openPort(midi_in_id); - } catch (RtMidiError& error) { - pclog("Fallback to default MIDI input port: %s\n", error.getMessage().c_str()); + midiin->openPort(midi_in_id); + } catch (RtMidiError &error) { + pclog("Fallback to default MIDI input port: %s\n", error.getMessage().c_str()); - try { - midiin->openPort(0); - } catch (RtMidiError& error) { - pclog("Failed to initialize MIDI input: %s\n", error.getMessage().c_str()); - delete midiin; - midiin = nullptr; - return nullptr; - } + try { + midiin->openPort(0); + } catch (RtMidiError &error) { + pclog("Failed to initialize MIDI input: %s\n", error.getMessage().c_str()); + delete midiin; + midiin = nullptr; + return nullptr; + } } midiin->setCallback(&rtmidi_input_callback); @@ -191,15 +192,14 @@ rtmidi_input_init(const device_t *info) midi_in_init(dev, &midi_in); midi_in->midi_realtime = device_get_config_int("realtime"); - midi_in->thruchan = device_get_config_int("thruchan"); + midi_in->thruchan = device_get_config_int("thruchan"); midi_in->midi_clockout = device_get_config_int("clockout"); return dev; } - void -rtmidi_input_close(void* p) +rtmidi_input_close(UNUSED(void *priv)) { midiin->cancelCallback(); midiin->closePort(); @@ -207,87 +207,108 @@ rtmidi_input_close(void* p) delete midiin; midiin = nullptr; - midi_close(); + midi_out_close(); } - int rtmidi_in_get_num_devs(void) { if (!midiin) { - try { - midiin = new RtMidiIn; - } catch (RtMidiError& error) { - pclog("Failed to initialize MIDI input: %s\n", error.getMessage().c_str()); - } + try { + midiin = new RtMidiIn; + } catch (RtMidiError &error) { + pclog("Failed to initialize MIDI input: %s\n", error.getMessage().c_str()); + } } return midiin ? midiin->getPortCount() : 0; } - void rtmidi_in_get_dev_name(int num, char *s) { strcpy(s, midiin->getPortName(num).c_str()); } -static const device_config_t system_midi_config[] = -{ +static const device_config_t system_midi_config[] = { + // clang-format off { - "midi", "MIDI out device", CONFIG_MIDI, "", 0 + .name = "midi", + .description = "MIDI out device", + .type = CONFIG_MIDI_OUT, + .default_string = "", + .default_int = 0 }, - { - "", "", -1 - } + { .name = "", .description = "", .type = CONFIG_END } + // clang-format on }; -static const device_config_t midi_input_config[] = -{ +static const device_config_t midi_input_config[] = { + // clang-format off { - "midi_input", "MIDI in device", CONFIG_MIDI_IN, "", 0 + .name = "midi_input", + .description = "MIDI in device", + .type = CONFIG_MIDI_IN, + .default_string = "", + .default_int = 0 }, { - "realtime", "MIDI Real time", CONFIG_BINARY, "", 0 + .name = "realtime", + .description = "MIDI Real time", + .type = CONFIG_BINARY, + .default_string = "", + .default_int = 0 }, { - "thruchan", "MIDI Thru", CONFIG_BINARY, "", 1 + .name = "thruchan", + .description = "MIDI Thru", + .type = CONFIG_BINARY, + .default_string = "", + .default_int = 1 }, { - "clockout", "MIDI Clockout", CONFIG_BINARY, "", 1 + .name = "clockout", + .description = "MIDI Clockout", + .type = CONFIG_BINARY, + .default_string = "", + .default_int = 1 }, - { - "", "", -1 - } + { .name = "", .description = "", .type = CONFIG_END } + // clang-format on }; -const device_t rtmidi_device = -{ - SYSTEM_MIDI_NAME, - SYSTEM_MIDI_INTERNAL_NAME, - 0, 0, - rtmidi_init, - rtmidi_close, - NULL, - { rtmidi_get_num_devs }, - NULL, - NULL, - system_midi_config +const device_t rtmidi_output_device = { + .name = SYSTEM_MIDI_NAME, + .internal_name = SYSTEM_MIDI_INTERNAL_NAME, + .flags = 0, + .local = 0, + .init = rtmidi_output_init, + .close = rtmidi_output_close, + .reset = NULL, + { .available = rtmidi_out_get_num_devs }, + .speed_changed = NULL, + .force_redraw = NULL, + .config = system_midi_config }; - -const device_t rtmidi_input_device = -{ - MIDI_INPUT_NAME, - MIDI_INPUT_INTERNAL_NAME, - 0, 0, - rtmidi_input_init, - rtmidi_input_close, - NULL, - { rtmidi_in_get_num_devs }, - NULL, - NULL, - midi_input_config +const device_t rtmidi_input_device = { + .name = MIDI_INPUT_NAME, + .internal_name = MIDI_INPUT_INTERNAL_NAME, + .flags = 0, + .local = 0, + .init = rtmidi_input_init, + .close = rtmidi_input_close, + .reset = NULL, + { .available = rtmidi_in_get_num_devs }, + .speed_changed = NULL, + .force_redraw = NULL, + .config = midi_input_config }; +#ifdef __clang__ +# if __has_warning("-Wc99-designator") +# pragma clang diagnostic pop +# endif +#endif + } diff --git a/src/sound/munt/Analog.cpp b/src/sound/munt/Analog.cpp index b14d824dd..41fb19b44 100644 --- a/src/sound/munt/Analog.cpp +++ b/src/sound/munt/Analog.cpp @@ -1,5 +1,5 @@ /* Copyright (C) 2003, 2004, 2005, 2006, 2008, 2009 Dean Beeler, Jerome Fisher - * Copyright (C) 2011-2020 Dean Beeler, Jerome Fisher, Sergey V. Mikayev + * Copyright (C) 2011-2022 Dean Beeler, Jerome Fisher, Sergey V. Mikayev * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by @@ -273,6 +273,8 @@ Analog *Analog::createAnalog(const AnalogOutputMode mode, const bool oldMT32Anal return new AnalogImpl(mode, oldMT32AnalogLPF); case RendererType_FLOAT: return new AnalogImpl(mode, oldMT32AnalogLPF); + default: + break; } return NULL; } diff --git a/src/sound/munt/Analog.h b/src/sound/munt/Analog.h index 244e4118f..62c092d9d 100644 --- a/src/sound/munt/Analog.h +++ b/src/sound/munt/Analog.h @@ -1,5 +1,5 @@ /* Copyright (C) 2003, 2004, 2005, 2006, 2008, 2009 Dean Beeler, Jerome Fisher - * Copyright (C) 2011-2020 Dean Beeler, Jerome Fisher, Sergey V. Mikayev + * Copyright (C) 2011-2022 Dean Beeler, Jerome Fisher, Sergey V. Mikayev * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by diff --git a/src/sound/munt/BReverbModel.cpp b/src/sound/munt/BReverbModel.cpp index 1eb6f7e56..05a2e4240 100644 --- a/src/sound/munt/BReverbModel.cpp +++ b/src/sound/munt/BReverbModel.cpp @@ -1,5 +1,5 @@ /* Copyright (C) 2003, 2004, 2005, 2006, 2008, 2009 Dean Beeler, Jerome Fisher - * Copyright (C) 2011-2020 Dean Beeler, Jerome Fisher, Sergey V. Mikayev + * Copyright (C) 2011-2022 Dean Beeler, Jerome Fisher, Sergey V. Mikayev * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by @@ -633,6 +633,8 @@ BReverbModel *BReverbModel::createBReverbModel(const ReverbMode mode, const bool return new BReverbModelImpl(mode, mt32CompatibleModel); case RendererType_FLOAT: return new BReverbModelImpl(mode, mt32CompatibleModel); + default: + break; } return NULL; } diff --git a/src/sound/munt/BReverbModel.h b/src/sound/munt/BReverbModel.h index ee2f838b2..ff34e9543 100644 --- a/src/sound/munt/BReverbModel.h +++ b/src/sound/munt/BReverbModel.h @@ -1,5 +1,5 @@ /* Copyright (C) 2003, 2004, 2005, 2006, 2008, 2009 Dean Beeler, Jerome Fisher - * Copyright (C) 2011-2020 Dean Beeler, Jerome Fisher, Sergey V. Mikayev + * Copyright (C) 2011-2022 Dean Beeler, Jerome Fisher, Sergey V. Mikayev * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by diff --git a/src/sound/munt/CMakeLists.txt b/src/sound/munt/CMakeLists.txt index 79ac7b2d9..d0438aa5b 100644 --- a/src/sound/munt/CMakeLists.txt +++ b/src/sound/munt/CMakeLists.txt @@ -1,19 +1,19 @@ # -# 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. +# 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. +# This file is part of the 86Box distribution. # -# CMake build script. +# CMake build script. # -# Authors: David HrdliÄka, +# Authors: David HrdliÄka, # -# Copyright 2020,2021 David HrdliÄka. +# Copyright 2020,2021 David HrdliÄka. # -add_library(mt32emu STATIC Analog.cpp BReverbModel.cpp File.cpp FileStream.cpp +add_library(mt32emu STATIC Analog.cpp BReverbModel.cpp Display.cpp File.cpp FileStream.cpp LA32Ramp.cpp LA32FloatWaveGenerator.cpp LA32WaveGenerator.cpp MidiStreamParser.cpp Part.cpp Partial.cpp PartialManager.cpp Poly.cpp ROMInfo.cpp SampleRateConverter.cpp @@ -22,5 +22,5 @@ add_library(mt32emu STATIC Analog.cpp BReverbModel.cpp File.cpp FileStream.cpp srchelper/srctools/src/LinearResampler.cpp srchelper/srctools/src/ResamplerModel.cpp srchelper/srctools/src/SincResampler.cpp - srchelper/InternalResampler.cpp Synth.cpp Tables.cpp TVA.cpp TVF.cpp + srchelper/InternalResampler.cpp Synth.cpp Tables.cpp TVA.cpp TVF.cpp TVP.cpp sha1/sha1.cpp c_interface/c_interface.cpp) \ No newline at end of file diff --git a/src/sound/munt/Display.cpp b/src/sound/munt/Display.cpp new file mode 100644 index 000000000..e04ea2cd1 --- /dev/null +++ b/src/sound/munt/Display.cpp @@ -0,0 +1,354 @@ +/* Copyright (C) 2003, 2004, 2005, 2006, 2008, 2009 Dean Beeler, Jerome Fisher + * Copyright (C) 2011-2022 Dean Beeler, Jerome Fisher, Sergey V. Mikayev + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 2.1 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this program. If not, see . + */ + +#include +#include + +#include "internals.h" + +#include "Display.h" +#include "Part.h" +#include "Structures.h" +#include "Synth.h" + +namespace MT32Emu { + +/* Details on the emulation model. + * + * There are four display modes emulated: + * - main (Master Volume), set upon startup after showing the welcoming banner; + * - program change notification; + * - custom display message received via a SysEx; + * - error banner (e.g. the MIDI message checksum error). + * Stuff like cursor blinking, patch selection mode, test mode, reaction to the front panel buttons, etc. is out of scope, as more + * convenient UI/UX solutions are likely desired in applications, if at all. + * + * Note, despite the LAPC and CM devices come without the LCD and the front panel buttons, the control ROM does support these, + * if connected to the main board. That's intended for running the test mode in a service centre, as documented. + * + * Within the aforementioned scope, the observable hardware behaviour differs noticeably, depending on the control ROM version. + * At least three milestones can be identified: + * - with MT-32 control ROM V1.06, custom messages are no longer shown unless the display is in the main (Master Volume) mode; + * - with MT-32 control ROM V2.04, new function introduced - Display Reset yet added many other changes (taking the full SysEx + * address into account when processing custom messages and special handling of the ASCII control characters are among them); + * all the second-gen devices, including LAPC-I and CM-32L, behave very similarly; + * - in the third-gen devices, the LCD support was partially cut down in the control ROM (basically, only the status + * of the test mode, the ROM version and the checksum warnings are shown) - it's not fun, so this is NOT emulated. + * + * Features of the old-gen units. + * - Any message with the first address byte 0x20 is processed and has some effect on the LCD. Messages with any other first + * address byte (e.g. starting with 0x21 or 0x1F7F7F with an overlap) are not considered display-relevant. + * - The second and the third address byte are largely irrelevant. Only presence of the second address byte makes an observable + * difference, not the data within. + * - Any string received in the custom message is normalised - all ASCII control characters are replaced with spaces, messages + * shorter than 20 bytes are filled up with spaces to the full supported length. However, should a timbre name contain an ASCII + * control character, it is displayed nevertheless, with zero meaning the end-of-string. + * - Special message 0x20 (of just 1 address byte) shows the contents of the custom message buffer with either the last received + * message or the empty buffer initially filled with spaces. See the note below about the priorities of the display modes. + * - Messages containing two or three bytes with just the address are considered empty and fill the custom message buffer with + * all spaces. The contents of the empty buffer is then shown, depending on the priority of the current display mode. + * - Timing: custom messages are shown until an external event occurs like pressing a front panel button, receiving a new custom + * message, program change, etc., and for indefinitely long otherwise. A program change notification is shown for about 1300 + * milliseconds; when the timer expires, the display returns to the main mode (irrespective to the current display mode). + * When an error occurs, the warning is shown for a limited time only, similarly to the program change notifications. + * - The earlier old-gen devices treat all display modes with equal priority, except the main mode, which has a lower one. This + * makes it possible e.g. to replace the error banner with a custom message or a program change notification, and so on. + * A slightly improved behaviour is observed since the control ROM V1.06, when custom messages were de-prioritised. But still, + * a program change beats an error banner even in the later models. + * + * Features of the second-gen units. + * - All three bytes in SysEx address are now relevant. + * - It is possible to replace individual characters in the custom message buffer which are addressed individually within + * the range 0x200000-0x200013. + * - Writes to higher addresses up to 0x20007F simply make the custom message buffer shown, with either the last received message + * or the empty buffer initially filled with spaces. + * - Writes to address 0x200100 trigger the Display Reset function which resets the display to the main (Master Volume) mode. + * Similarly, showing an error banner is ended. If a program change notification is shown, this function does nothing, however. + * - Writes to other addresses are not considered display-relevant, albeit writing a long string to lower addresses + * (e.g. 0x1F7F7F) that overlaps the display range does result in updating and showing the custom display message. + * - Writing a long string that covers the custom message buffer and address 0x200100 does both things, i.e. updates the buffer + * and triggers the Display Reset function. + * - While the display is not in a user interaction mode, custom messages and error banners have the highest display priority. + * As long as these are shown, program change notifications are suppressed. The display only leaves this mode when the Display + * Reset function is triggered or a front panel button is pressed. Notably, when the user enters the menu, all custom messages + * are ignored, including the Display Reset command, but error banners are shown nevertheless. + * - Sending cut down messages with partially specified address rather leads to undefined behaviour, except for a two-byte message + * 0x20 0x00 which consistently shows the content of the custom message buffer (if priority permits). Otherwise, the behaviour + * depends on the previously submitted address, e.g. the two-byte version of Display Reset may fail depending on the third byte + * of the previous message. One-byte message 0x20 seemingly does Display Reset yet writes a zero character to a position derived + * from the third byte of the preceding message. + * + * Some notes on the behaviour that is common to all hardware models. + * - The display is DM2011 with LSI SED1200D-0A. This unit supports 4 user-programmable characters stored in CGRAM, all 4 get + * loaded at startup. Character #0 is empty (with the cursor underline), #1 is the full block (used to mark active parts), + * #2 is the pipe character (identical to #124 from the CGROM) and #3 is a variation on "down arrow". During normal operation, + * those duplicated characters #2 and #124 are both used in different places and character #3 can only be made visible by adding + * it either to a custom timbre name or a custom message. Character #0 is probably never shown as this code has special meaning + * in the processing routines. For simplicity, we only use characters #124 and #1 in this model. + * - When the main mode is active, the current state of the first 5 parts and the rhythm part is represented by replacing the part + * symbol with the full rectangle character (#1 from the CGRAM). For voice parts, the rectangle is shown as long as at least one + * partial is playing in a non-releasing phase on that part. For the rhythm part, the rectangle blinks briefly when a new NoteOn + * message is received on that part (sometimes even when that actually produces no sound). + */ + +static const char MASTER_VOLUME_WITH_DELIMITER[] = "| 0"; +static const char MASTER_VOLUME_WITH_DELIMITER_AND_PREFIX[] = "|vol: 0"; +static const Bit8u RHYTHM_PART_CODE = 'R'; +static const Bit8u FIELD_DELIMITER = '|'; +static const Bit8u ACTIVE_PART_INDICATOR = 1; + +static const Bit32u DISPLAYED_VOICE_PARTS_COUNT = 5; +static const Bit32u SOUND_GROUP_NAME_WITH_DELIMITER_SIZE = 8; +static const Bit32u MASTER_VOLUME_WITH_DELIMITER_SIZE = sizeof(MASTER_VOLUME_WITH_DELIMITER) - 1; +static const Bit32u MASTER_VOLUME_WITH_DELIMITER_AND_PREFIX_SIZE = sizeof(MASTER_VOLUME_WITH_DELIMITER_AND_PREFIX) - 1; + +// This is the period to show those short blinks of MIDI MESSAGE LED and the rhythm part state. +// Two related countdowns are initialised to 8 and touched each 10 milliseconds by the software timer 0 interrupt handler. +static const Bit32u BLINK_TIME_MILLIS = 80; +static const Bit32u BLINK_TIME_FRAMES = BLINK_TIME_MILLIS * SAMPLE_RATE / 1000; + +// This is based on the (free-running) TIMER1 overflow interrupt. The timer is 16-bit and clocked at 500KHz. +// The message is displayed until 10 overflow interrupts occur. At the standard sample rate, it counts +// precisely as 41943.04 frame times. +static const Bit32u SCHEDULED_DISPLAY_MODE_RESET_FRAMES = 41943; + +/** + * Copies up to lengthLimit characters from possibly null-terminated source to destination. The character of destination located + * at the position of the null terminator (if any) in source and the rest of destination are left untouched. + */ +static void copyNullTerminatedString(Bit8u *destination, const Bit8u *source, Bit32u lengthLimit) { + for (Bit32u i = 0; i < lengthLimit; i++) { + Bit8u c = source[i]; + if (c == 0) break; + destination[i] = c; + } +} + +Display::Display(Synth &useSynth) : + synth(useSynth), + lastLEDState(), + lcdDirty(), + lcdUpdateSignalled(), + lastRhythmPartState(), + mode(Mode_STARTUP_MESSAGE), + midiMessagePlayedSinceLastReset(), + rhythmNotePlayedSinceLastReset() +{ + scheduleDisplayReset(); + const Bit8u *startupMessage = &synth.controlROMData[synth.controlROMMap->startupMessage]; + memcpy(displayBuffer, startupMessage, LCD_TEXT_SIZE); + memset(customMessageBuffer, ' ', LCD_TEXT_SIZE); + memset(voicePartStates, 0, sizeof voicePartStates); +} + +void Display::checkDisplayStateUpdated(bool &midiMessageLEDState, bool &midiMessageLEDUpdated, bool &lcdUpdated) { + midiMessageLEDState = midiMessagePlayedSinceLastReset; + maybeResetTimer(midiMessagePlayedSinceLastReset, midiMessageLEDResetTimestamp); + // Note, the LED represents activity of the voice parts only. + for (Bit32u partIndex = 0; !midiMessageLEDState && partIndex < 8; partIndex++) { + midiMessageLEDState = voicePartStates[partIndex]; + } + midiMessageLEDUpdated = lastLEDState != midiMessageLEDState; + lastLEDState = midiMessageLEDState; + + if (displayResetScheduled && shouldResetTimer(displayResetTimestamp)) setMainDisplayMode(); + + if (lastRhythmPartState != rhythmNotePlayedSinceLastReset && mode == Mode_MAIN) lcdDirty = true; + lastRhythmPartState = rhythmNotePlayedSinceLastReset; + maybeResetTimer(rhythmNotePlayedSinceLastReset, rhythmStateResetTimestamp); + + lcdUpdated = lcdDirty && !lcdUpdateSignalled; + if (lcdUpdated) lcdUpdateSignalled = true; +} + +bool Display::getDisplayState(char *targetBuffer, bool narrowLCD) { + if (lcdUpdateSignalled) { + lcdDirty = false; + lcdUpdateSignalled = false; + + switch (mode) { + case Mode_CUSTOM_MESSAGE: + if (synth.isDisplayOldMT32Compatible()) { + memcpy(displayBuffer, customMessageBuffer, LCD_TEXT_SIZE); + } else { + copyNullTerminatedString(displayBuffer, customMessageBuffer, LCD_TEXT_SIZE); + } + break; + case Mode_ERROR_MESSAGE: { + const Bit8u *sysexErrorMessage = &synth.controlROMData[synth.controlROMMap->sysexErrorMessage]; + memcpy(displayBuffer, sysexErrorMessage, LCD_TEXT_SIZE); + break; + } + case Mode_PROGRAM_CHANGE: { + Bit8u *writePosition = displayBuffer; + *writePosition++ = '1' + lastProgramChangePartIndex; + *writePosition++ = FIELD_DELIMITER; + if (narrowLCD) { + writePosition[TIMBRE_NAME_SIZE] = 0; + } else { + memcpy(writePosition, lastProgramChangeSoundGroupName, SOUND_GROUP_NAME_WITH_DELIMITER_SIZE); + writePosition += SOUND_GROUP_NAME_WITH_DELIMITER_SIZE; + } + copyNullTerminatedString(writePosition, lastProgramChangeTimbreName, TIMBRE_NAME_SIZE); + break; + } + case Mode_MAIN: { + Bit8u *writePosition = displayBuffer; + for (Bit32u partIndex = 0; partIndex < DISPLAYED_VOICE_PARTS_COUNT; partIndex++) { + *writePosition++ = voicePartStates[partIndex] ? ACTIVE_PART_INDICATOR : '1' + partIndex; + *writePosition++ = ' '; + } + *writePosition++ = lastRhythmPartState ? ACTIVE_PART_INDICATOR : RHYTHM_PART_CODE; + *writePosition++ = ' '; + if (narrowLCD) { + memcpy(writePosition, MASTER_VOLUME_WITH_DELIMITER, MASTER_VOLUME_WITH_DELIMITER_SIZE); + writePosition += MASTER_VOLUME_WITH_DELIMITER_SIZE; + *writePosition = 0; + } else { + memcpy(writePosition, MASTER_VOLUME_WITH_DELIMITER_AND_PREFIX, MASTER_VOLUME_WITH_DELIMITER_AND_PREFIX_SIZE); + writePosition += MASTER_VOLUME_WITH_DELIMITER_AND_PREFIX_SIZE; + } + Bit32u masterVol = synth.mt32ram.system.masterVol; + while (masterVol > 0) { + std::div_t result = std::div(masterVol, 10); + *--writePosition = '0' + result.rem; + masterVol = result.quot; + } + break; + } + default: + break; + } + } + + memcpy(targetBuffer, displayBuffer, LCD_TEXT_SIZE); + targetBuffer[LCD_TEXT_SIZE] = 0; + return lastLEDState; +} + +void Display::setMainDisplayMode() { + displayResetScheduled = false; + mode = Mode_MAIN; + lcdDirty = true; +} + +void Display::midiMessagePlayed() { + midiMessagePlayedSinceLastReset = true; + midiMessageLEDResetTimestamp = synth.renderedSampleCount + BLINK_TIME_FRAMES; +} + +void Display::rhythmNotePlayed() { + rhythmNotePlayedSinceLastReset = true; + rhythmStateResetTimestamp = synth.renderedSampleCount + BLINK_TIME_FRAMES; + midiMessagePlayed(); + if (synth.isDisplayOldMT32Compatible() && mode == Mode_CUSTOM_MESSAGE) setMainDisplayMode(); +} + +void Display::voicePartStateChanged(Bit8u partIndex, bool activated) { + if (mode == Mode_MAIN) lcdDirty = true; + voicePartStates[partIndex] = activated; + if (synth.isDisplayOldMT32Compatible() && mode == Mode_CUSTOM_MESSAGE) setMainDisplayMode(); +} + +void Display::masterVolumeChanged() { + if (mode == Mode_MAIN) lcdDirty = true; +} + +void Display::programChanged(Bit8u partIndex) { + if (!synth.isDisplayOldMT32Compatible() && (mode == Mode_CUSTOM_MESSAGE || mode == Mode_ERROR_MESSAGE)) return; + mode = Mode_PROGRAM_CHANGE; + lcdDirty = true; + scheduleDisplayReset(); + lastProgramChangePartIndex = partIndex; + const Part *part = synth.getPart(partIndex); + lastProgramChangeSoundGroupName = synth.getSoundGroupName(part); + memcpy(lastProgramChangeTimbreName, part->getCurrentInstr(), TIMBRE_NAME_SIZE); +} + +void Display::checksumErrorOccurred() { + if (mode != Mode_ERROR_MESSAGE) { + mode = Mode_ERROR_MESSAGE; + lcdDirty = true; + } + if (synth.isDisplayOldMT32Compatible()) { + scheduleDisplayReset(); + } else { + displayResetScheduled = false; + } +} + +bool Display::customDisplayMessageReceived(const Bit8u *message, Bit32u startIndex, Bit32u length) { + if (synth.isDisplayOldMT32Compatible()) { + for (Bit32u i = 0; i < LCD_TEXT_SIZE; i++) { + Bit8u c = i < length ? message[i] : ' '; + if (c < 32 || 127 < c) c = ' '; + customMessageBuffer[i] = c; + } + if (!synth.controlROMFeatures->quirkDisplayCustomMessagePriority + && (mode == Mode_PROGRAM_CHANGE || mode == Mode_ERROR_MESSAGE)) return false; + // Note, real devices keep the display reset timer running. + } else { + if (startIndex > 0x80) return false; + if (startIndex == 0x80) { + if (mode != Mode_PROGRAM_CHANGE) setMainDisplayMode(); + return false; + } + displayResetScheduled = false; + if (startIndex < LCD_TEXT_SIZE) { + if (length > LCD_TEXT_SIZE - startIndex) length = LCD_TEXT_SIZE - startIndex; + memcpy(customMessageBuffer + startIndex, message, length); + } + } + mode = Mode_CUSTOM_MESSAGE; + lcdDirty = true; + return true; +} + +void Display::displayControlMessageReceived(const Bit8u *messageBytes, Bit32u length) { + Bit8u emptyMessage[] = { 0 }; + if (synth.isDisplayOldMT32Compatible()) { + if (length == 1) { + customDisplayMessageReceived(customMessageBuffer, 0, LCD_TEXT_SIZE); + } else { + customDisplayMessageReceived(emptyMessage, 0, 0); + } + } else { + // Always assume the third byte to be zero for simplicity. + if (length == 2) { + customDisplayMessageReceived(emptyMessage, messageBytes[1] << 7, 0); + } else if (length == 1) { + customMessageBuffer[0] = 0; + customDisplayMessageReceived(emptyMessage, 0x80, 0); + } + } +} + +void Display::scheduleDisplayReset() { + displayResetTimestamp = synth.renderedSampleCount + SCHEDULED_DISPLAY_MODE_RESET_FRAMES; + displayResetScheduled = true; +} + +bool Display::shouldResetTimer(Bit32u scheduledResetTimestamp) { + // Deals with wrapping of renderedSampleCount. + return Bit32s(scheduledResetTimestamp - synth.renderedSampleCount) < 0; +} + +void Display::maybeResetTimer(bool &timerState, Bit32u scheduledResetTimestamp) { + if (timerState && shouldResetTimer(scheduledResetTimestamp)) timerState = false; +} + +} // namespace MT32Emu diff --git a/src/sound/munt/Display.h b/src/sound/munt/Display.h new file mode 100644 index 000000000..1802b0bd2 --- /dev/null +++ b/src/sound/munt/Display.h @@ -0,0 +1,91 @@ +/* Copyright (C) 2003, 2004, 2005, 2006, 2008, 2009 Dean Beeler, Jerome Fisher + * Copyright (C) 2011-2022 Dean Beeler, Jerome Fisher, Sergey V. Mikayev + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 2.1 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this program. If not, see . + */ + +#ifndef MT32EMU_DISPLAY_H +#define MT32EMU_DISPLAY_H + +#include "globals.h" +#include "Types.h" + +namespace MT32Emu { + +class Synth; + +/** Facilitates emulation of internal state of the MIDI MESSAGE LED and the MT-32 LCD. */ +class Display { +public: + static const unsigned int LCD_TEXT_SIZE = 20; + + enum Mode { + Mode_MAIN, // a.k.a. Master Volume + Mode_STARTUP_MESSAGE, + Mode_PROGRAM_CHANGE, + Mode_CUSTOM_MESSAGE, + Mode_ERROR_MESSAGE + }; + + Display(Synth &synth); + void checkDisplayStateUpdated(bool &midiMessageLEDState, bool &midiMessageLEDUpdated, bool &lcdUpdated); + /** Returns whether the MIDI MESSAGE LED is ON and fills the targetBuffer parameter. */ + bool getDisplayState(char *targetBuffer, bool narrowLCD); + void setMainDisplayMode(); + + void midiMessagePlayed(); + void rhythmNotePlayed(); + void voicePartStateChanged(Bit8u partIndex, bool activated); + void masterVolumeChanged(); + void programChanged(Bit8u partIndex); + void checksumErrorOccurred(); + bool customDisplayMessageReceived(const Bit8u *message, Bit32u startIndex, Bit32u length); + void displayControlMessageReceived(const Bit8u *messageBytes, Bit32u length); + +private: + typedef Bit8u DisplayBuffer[LCD_TEXT_SIZE]; + + static const unsigned int TIMBRE_NAME_SIZE = 10; + + Synth &synth; + + bool lastLEDState; + bool lcdDirty; + bool lcdUpdateSignalled; + bool lastRhythmPartState; + bool voicePartStates[8]; + + Bit8u lastProgramChangePartIndex; + const char *lastProgramChangeSoundGroupName; + Bit8u lastProgramChangeTimbreName[TIMBRE_NAME_SIZE]; + + Mode mode; + Bit32u displayResetTimestamp; + bool displayResetScheduled; + Bit32u midiMessageLEDResetTimestamp; + bool midiMessagePlayedSinceLastReset; + Bit32u rhythmStateResetTimestamp; + bool rhythmNotePlayedSinceLastReset; + + DisplayBuffer displayBuffer; + DisplayBuffer customMessageBuffer; + + void scheduleDisplayReset(); + bool shouldResetTimer(Bit32u scheduledResetTimestamp); + void maybeResetTimer(bool &timerState, Bit32u scheduledResetTimestamp); +}; + +} // namespace MT32Emu + +#endif // #ifndef MT32EMU_DISPLAY_H diff --git a/src/sound/munt/Enumerations.h b/src/sound/munt/Enumerations.h index 05a2b6f6d..3cbfdd4c8 100644 --- a/src/sound/munt/Enumerations.h +++ b/src/sound/munt/Enumerations.h @@ -1,5 +1,5 @@ /* Copyright (C) 2003, 2004, 2005, 2006, 2008, 2009 Dean Beeler, Jerome Fisher - * Copyright (C) 2011-2020 Dean Beeler, Jerome Fisher, Sergey V. Mikayev + * Copyright (C) 2011-2022 Dean Beeler, Jerome Fisher, Sergey V. Mikayev * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by diff --git a/src/sound/munt/File.cpp b/src/sound/munt/File.cpp index dbe226648..fb2febeb1 100644 --- a/src/sound/munt/File.cpp +++ b/src/sound/munt/File.cpp @@ -1,5 +1,5 @@ /* Copyright (C) 2003, 2004, 2005, 2006, 2008, 2009 Dean Beeler, Jerome Fisher - * Copyright (C) 2011-2020 Dean Beeler, Jerome Fisher, Sergey V. Mikayev + * Copyright (C) 2011-2022 Dean Beeler, Jerome Fisher, Sergey V. Mikayev * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by diff --git a/src/sound/munt/File.h b/src/sound/munt/File.h index a4b099fbb..2aa34b4c7 100644 --- a/src/sound/munt/File.h +++ b/src/sound/munt/File.h @@ -1,5 +1,5 @@ /* Copyright (C) 2003, 2004, 2005, 2006, 2008, 2009 Dean Beeler, Jerome Fisher - * Copyright (C) 2011-2020 Dean Beeler, Jerome Fisher, Sergey V. Mikayev + * Copyright (C) 2011-2022 Dean Beeler, Jerome Fisher, Sergey V. Mikayev * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by diff --git a/src/sound/munt/FileStream.cpp b/src/sound/munt/FileStream.cpp index 3fa1a3107..5e32c10d6 100644 --- a/src/sound/munt/FileStream.cpp +++ b/src/sound/munt/FileStream.cpp @@ -1,5 +1,5 @@ /* Copyright (C) 2003, 2004, 2005, 2006, 2008, 2009 Dean Beeler, Jerome Fisher - * Copyright (C) 2011-2020 Dean Beeler, Jerome Fisher, Sergey V. Mikayev + * Copyright (C) 2011-2022 Dean Beeler, Jerome Fisher, Sergey V. Mikayev * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by @@ -15,8 +15,8 @@ * along with this program. If not, see . */ -#ifdef MT32EMU_SHARED -#include +#if defined MT32EMU_SHARED && defined MT32EMU_INSTALL_DEFAULT_LOCALE +#include #endif #include "internals.h" @@ -25,13 +25,18 @@ namespace MT32Emu { +// This initialises C locale with the user-preferred system locale once facilitating access +// to ROM files with localised pathnames. This is only necessary in rare cases e.g. when building +// shared library statically linked with C runtime with old MS VC versions, so that the C locale +// set by the client application does not have effect, and thus such ROM files cannot be opened. static inline void configureSystemLocale() { -#ifdef MT32EMU_SHARED +#if defined MT32EMU_SHARED && defined MT32EMU_INSTALL_DEFAULT_LOCALE static bool configured = false; if (configured) return; configured = true; - std::locale::global(std::locale("")); + + setlocale(LC_ALL, ""); #endif } diff --git a/src/sound/munt/FileStream.h b/src/sound/munt/FileStream.h index 2279890b4..3b3976869 100644 --- a/src/sound/munt/FileStream.h +++ b/src/sound/munt/FileStream.h @@ -1,5 +1,5 @@ /* Copyright (C) 2003, 2004, 2005, 2006, 2008, 2009 Dean Beeler, Jerome Fisher - * Copyright (C) 2011-2020 Dean Beeler, Jerome Fisher, Sergey V. Mikayev + * Copyright (C) 2011-2022 Dean Beeler, Jerome Fisher, Sergey V. Mikayev * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by diff --git a/src/sound/munt/LA32FloatWaveGenerator.cpp b/src/sound/munt/LA32FloatWaveGenerator.cpp index 34ea1fbf4..7aea6c240 100644 --- a/src/sound/munt/LA32FloatWaveGenerator.cpp +++ b/src/sound/munt/LA32FloatWaveGenerator.cpp @@ -1,5 +1,5 @@ /* Copyright (C) 2003, 2004, 2005, 2006, 2008, 2009 Dean Beeler, Jerome Fisher - * Copyright (C) 2011-2020 Dean Beeler, Jerome Fisher, Sergey V. Mikayev + * Copyright (C) 2011-2022 Dean Beeler, Jerome Fisher, Sergey V. Mikayev * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by @@ -236,7 +236,7 @@ float LA32FloatWaveGenerator::generateNextSample(const Bit32u ampVal, const Bit1 relWavePos -= cosineLen + hLen; } - // To ensure the output wave has no breaks, two different windows are appied to the beginning and the ending of the resonance sine segment + // To ensure the output wave has no breaks, two different windows are applied to the beginning and the ending of the resonance sine segment if (relWavePos < 0.5f * cosineLen) { float syncSine = sin(FLOAT_PI * relWavePos / cosineLen); if (relWavePos < 0.0f) { diff --git a/src/sound/munt/LA32FloatWaveGenerator.h b/src/sound/munt/LA32FloatWaveGenerator.h index a21d68e2b..b34c1fa86 100644 --- a/src/sound/munt/LA32FloatWaveGenerator.h +++ b/src/sound/munt/LA32FloatWaveGenerator.h @@ -1,5 +1,5 @@ /* Copyright (C) 2003, 2004, 2005, 2006, 2008, 2009 Dean Beeler, Jerome Fisher - * Copyright (C) 2011-2020 Dean Beeler, Jerome Fisher, Sergey V. Mikayev + * Copyright (C) 2011-2022 Dean Beeler, Jerome Fisher, Sergey V. Mikayev * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by diff --git a/src/sound/munt/LA32Ramp.cpp b/src/sound/munt/LA32Ramp.cpp index 122ee05ac..cc61d8357 100644 --- a/src/sound/munt/LA32Ramp.cpp +++ b/src/sound/munt/LA32Ramp.cpp @@ -1,5 +1,5 @@ /* Copyright (C) 2003, 2004, 2005, 2006, 2008, 2009 Dean Beeler, Jerome Fisher - * Copyright (C) 2011-2020 Dean Beeler, Jerome Fisher, Sergey V. Mikayev + * Copyright (C) 2011-2022 Dean Beeler, Jerome Fisher, Sergey V. Mikayev * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by diff --git a/src/sound/munt/LA32Ramp.h b/src/sound/munt/LA32Ramp.h index 802b34aa4..178e16b60 100644 --- a/src/sound/munt/LA32Ramp.h +++ b/src/sound/munt/LA32Ramp.h @@ -1,5 +1,5 @@ /* Copyright (C) 2003, 2004, 2005, 2006, 2008, 2009 Dean Beeler, Jerome Fisher - * Copyright (C) 2011-2020 Dean Beeler, Jerome Fisher, Sergey V. Mikayev + * Copyright (C) 2011-2022 Dean Beeler, Jerome Fisher, Sergey V. Mikayev * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by diff --git a/src/sound/munt/LA32WaveGenerator.cpp b/src/sound/munt/LA32WaveGenerator.cpp index f4f7eeccb..cf1a34c9c 100644 --- a/src/sound/munt/LA32WaveGenerator.cpp +++ b/src/sound/munt/LA32WaveGenerator.cpp @@ -1,5 +1,5 @@ /* Copyright (C) 2003, 2004, 2005, 2006, 2008, 2009 Dean Beeler, Jerome Fisher - * Copyright (C) 2011-2020 Dean Beeler, Jerome Fisher, Sergey V. Mikayev + * Copyright (C) 2011-2022 Dean Beeler, Jerome Fisher, Sergey V. Mikayev * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by @@ -173,7 +173,7 @@ void LA32WaveGenerator::generateNextResonanceWaveLogSample() { // Unsure about resonanceSinePosition here. It's possible that dedicated counter & decrement are used. Although, cutoff is finely ramped, so maybe not. logSampleValue += resonanceAmpSubtraction + (((resonanceSinePosition >> 4) * decayFactor) >> 8); - // To ensure the output wave has no breaks, two different windows are appied to the beginning and the ending of the resonance sine segment + // To ensure the output wave has no breaks, two different windows are applied to the beginning and the ending of the resonance sine segment if (phase == POSITIVE_RISING_SINE_SEGMENT || phase == NEGATIVE_FALLING_SINE_SEGMENT) { // The window is synchronous sine here logSampleValue += Tables::getInstance().logsin9[(squareWavePosition >> 9) & 511] << 2; @@ -183,7 +183,7 @@ void LA32WaveGenerator::generateNextResonanceWaveLogSample() { } if (cutoffVal < MIDDLE_CUTOFF_VALUE) { - // For the cutoff values below the cutoff middle point, it seems the amp of the resonance wave is expotentially decayed + // For the cutoff values below the cutoff middle point, it seems the amp of the resonance wave is exponentially decayed logSampleValue += 31743 + ((MIDDLE_CUTOFF_VALUE - cutoffVal) >> 9); } else if (cutoffVal < RESONANCE_DECAY_THRESHOLD_CUTOFF_VALUE) { // For the cutoff values below this point, the amp of the resonance wave is sinusoidally decayed diff --git a/src/sound/munt/LA32WaveGenerator.h b/src/sound/munt/LA32WaveGenerator.h index d2d74f48d..71d909df8 100644 --- a/src/sound/munt/LA32WaveGenerator.h +++ b/src/sound/munt/LA32WaveGenerator.h @@ -1,5 +1,5 @@ /* Copyright (C) 2003, 2004, 2005, 2006, 2008, 2009 Dean Beeler, Jerome Fisher - * Copyright (C) 2011-2020 Dean Beeler, Jerome Fisher, Sergey V. Mikayev + * Copyright (C) 2011-2022 Dean Beeler, Jerome Fisher, Sergey V. Mikayev * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by diff --git a/src/sound/munt/MemoryRegion.h b/src/sound/munt/MemoryRegion.h index c8e85c7fb..1f224768c 100644 --- a/src/sound/munt/MemoryRegion.h +++ b/src/sound/munt/MemoryRegion.h @@ -1,5 +1,5 @@ /* Copyright (C) 2003, 2004, 2005, 2006, 2008, 2009 Dean Beeler, Jerome Fisher - * Copyright (C) 2011-2020 Dean Beeler, Jerome Fisher, Sergey V. Mikayev + * Copyright (C) 2011-2022 Dean Beeler, Jerome Fisher, Sergey V. Mikayev * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by @@ -120,7 +120,9 @@ public: }; class DisplayMemoryRegion : public MemoryRegion { public: - DisplayMemoryRegion(Synth *useSynth) : MemoryRegion(useSynth, NULL, NULL, MR_Display, MT32EMU_MEMADDR(0x200000), SYSEX_BUFFER_SIZE - 1, 1) {} + // Note, we set realMemory to NULL despite the real devices buffer inbound strings. However, it is impossible to retrieve them. + // This entrySize permits emulation of handling a 20-byte display message sent to an old-gen device at address 0x207F7F. + DisplayMemoryRegion(Synth *useSynth) : MemoryRegion(useSynth, NULL, NULL, MR_Display, MT32EMU_MEMADDR(0x200000), 0x4013, 1) {} }; class ResetMemoryRegion : public MemoryRegion { public: diff --git a/src/sound/munt/MidiEventQueue.h b/src/sound/munt/MidiEventQueue.h index 846f47c51..b458b8190 100644 --- a/src/sound/munt/MidiEventQueue.h +++ b/src/sound/munt/MidiEventQueue.h @@ -1,5 +1,5 @@ /* Copyright (C) 2003, 2004, 2005, 2006, 2008, 2009 Dean Beeler, Jerome Fisher - * Copyright (C) 2011-2020 Dean Beeler, Jerome Fisher, Sergey V. Mikayev + * Copyright (C) 2011-2022 Dean Beeler, Jerome Fisher, Sergey V. Mikayev * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by diff --git a/src/sound/munt/MidiStreamParser.cpp b/src/sound/munt/MidiStreamParser.cpp index e9fbf7690..f91a81828 100644 --- a/src/sound/munt/MidiStreamParser.cpp +++ b/src/sound/munt/MidiStreamParser.cpp @@ -1,5 +1,5 @@ /* Copyright (C) 2003, 2004, 2005, 2006, 2008, 2009 Dean Beeler, Jerome Fisher - * Copyright (C) 2011-2020 Dean Beeler, Jerome Fisher, Sergey V. Mikayev + * Copyright (C) 2011-2022 Dean Beeler, Jerome Fisher, Sergey V. Mikayev * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by @@ -191,7 +191,7 @@ Bit32u MidiStreamParserImpl::parseShortMessageDataBytes(const Bit8u stream[], Bi } else if (dataByte < 0xF8) { // Discard invalid bytes and start over char s[128]; - sprintf(s, "parseShortMessageDataBytes: Invalid short message: status %02x, expected length %i, actual %i -> ignored", *streamBuffer, shortMessageLength, streamBufferSize); + snprintf(s, sizeof(s), "parseShortMessageDataBytes: Invalid short message: status %02x, expected length %i, actual %i -> ignored", *streamBuffer, shortMessageLength, streamBufferSize); midiReporter.printDebug(s); streamBufferSize = 0; // Clear streamBuffer return parsedLength; diff --git a/src/sound/munt/MidiStreamParser.h b/src/sound/munt/MidiStreamParser.h index f26fe11b7..d3a76c8a0 100644 --- a/src/sound/munt/MidiStreamParser.h +++ b/src/sound/munt/MidiStreamParser.h @@ -1,5 +1,5 @@ /* Copyright (C) 2003, 2004, 2005, 2006, 2008, 2009 Dean Beeler, Jerome Fisher - * Copyright (C) 2011-2020 Dean Beeler, Jerome Fisher, Sergey V. Mikayev + * Copyright (C) 2011-2022 Dean Beeler, Jerome Fisher, Sergey V. Mikayev * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by diff --git a/src/sound/munt/Part.cpp b/src/sound/munt/Part.cpp index 465903a72..f536f2ab8 100644 --- a/src/sound/munt/Part.cpp +++ b/src/sound/munt/Part.cpp @@ -1,5 +1,5 @@ /* Copyright (C) 2003, 2004, 2005, 2006, 2008, 2009 Dean Beeler, Jerome Fisher - * Copyright (C) 2011-2020 Dean Beeler, Jerome Fisher, Sergey V. Mikayev + * Copyright (C) 2011-2022 Dean Beeler, Jerome Fisher, Sergey V. Mikayev * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by @@ -54,15 +54,17 @@ Part::Part(Synth *useSynth, unsigned int usePartNum) { // Nasty hack for rhythm timbreTemp = NULL; } else { - sprintf(name, "Part %d", partNum + 1); + snprintf(name, sizeof(name), "Part %d", partNum + 1); timbreTemp = &synth->mt32ram.timbreTemp[partNum]; } currentInstr[0] = 0; currentInstr[10] = 0; + volumeOverride = 255; modulation = 0; expression = 100; pitchBend = 0; activePartialCount = 0; + activeNonReleasingPolyCount = 0; memset(patchCache, 0, sizeof(patchCache)); } @@ -166,7 +168,7 @@ void Part::refresh() { patchCache[t].reverb = patchTemp->patch.reverbSwitch > 0; } memcpy(currentInstr, timbreTemp->common.name, 10); - synth->newTimbreSet(partNum, patchTemp->patch.timbreGroup, patchTemp->patch.timbreNum, currentInstr); + synth->newTimbreSet(partNum); updatePitchBenderRange(); } @@ -317,7 +319,21 @@ void Part::setVolume(unsigned int midiVolume) { } Bit8u Part::getVolume() const { - return patchTemp->outputLevel; + return volumeOverride <= 100 ? volumeOverride : patchTemp->outputLevel; +} + +void Part::setVolumeOverride(Bit8u volume) { + volumeOverride = volume; + // When volume is 0, we want the part to stop producing any sound at all. + // For that to achieve, we have to actually stop processing NoteOn MIDI messages; merely + // returning 0 volume is not enough - the output may still be generated at a very low level. + // But first, we have to stop all the currently playing polys. This behaviour may also help + // with performance issues, because parts muted this way barely consume CPU resources. + if (volume == 0) allSoundOff(); +} + +Bit8u Part::getVolumeOverride() const { + return volumeOverride; } Bit8u Part::getExpression() const { @@ -380,6 +396,7 @@ void RhythmPart::noteOn(unsigned int midiKey, unsigned int velocity) { synth->printDebug("%s: Attempted to play invalid key %d (velocity %d)", name, midiKey, velocity); return; } + synth->rhythmNotePlayed(); unsigned int key = midiKey; unsigned int drumNum = key - 24; int drumTimbreNum = rhythmTemp[drumNum].timbre; @@ -609,6 +626,27 @@ void Part::partialDeactivated(Poly *poly) { } } +void RhythmPart::polyStateChanged(PolyState, PolyState) {} + +void Part::polyStateChanged(PolyState oldState, PolyState newState) { + switch (newState) { + case POLY_Playing: + if (activeNonReleasingPolyCount++ == 0) synth->voicePartStateChanged(partNum, true); + break; + case POLY_Releasing: + case POLY_Inactive: + if (oldState == POLY_Playing || oldState == POLY_Held) { + if (--activeNonReleasingPolyCount == 0) synth->voicePartStateChanged(partNum, false); + } + break; + default: + break; + } +#ifdef MT32EMU_TRACE_POLY_STATE_CHANGES + synth->printDebug("Part %d: Changed poly state %d->%d, activeNonReleasingPolyCount=%d", partNum, oldState, newState, activeNonReleasingPolyCount); +#endif +} + PolyList::PolyList() : firstPoly(NULL), lastPoly(NULL) {} bool PolyList::isEmpty() const { diff --git a/src/sound/munt/Part.h b/src/sound/munt/Part.h index bc2e11416..d266efb7e 100644 --- a/src/sound/munt/Part.h +++ b/src/sound/munt/Part.h @@ -1,5 +1,5 @@ /* Copyright (C) 2003, 2004, 2005, 2006, 2008, 2009 Dean Beeler, Jerome Fisher - * Copyright (C) 2011-2020 Dean Beeler, Jerome Fisher, Sergey V. Mikayev + * Copyright (C) 2011-2022 Dean Beeler, Jerome Fisher, Sergey V. Mikayev * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by @@ -55,6 +55,7 @@ private: bool holdpedal; unsigned int activePartialCount; + unsigned int activeNonReleasingPolyCount; PatchCache patchCache[4]; PolyList activePolys; @@ -69,6 +70,8 @@ protected: MemParams::PatchTemp *patchTemp; char name[8]; // "Part 1".."Part 8", "Rhythm" char currentInstr[11]; + // Values outside the valid range 0..100 imply no override. + Bit8u volumeOverride; Bit8u modulation; Bit8u expression; Bit32s pitchBend; @@ -95,8 +98,10 @@ public: virtual void noteOff(unsigned int midiKey); void allNotesOff(); void allSoundOff(); - Bit8u getVolume() const; // Internal volume, 0-100, exposed for use by ExternalInterface - void setVolume(unsigned int midiVolume); + Bit8u getVolume() const; // Effective output level, valid range 0..100. + void setVolume(unsigned int midiVolume); // Valid range 0..127, as defined for MIDI controller 7. + Bit8u getVolumeOverride() const; + void setVolumeOverride(Bit8u volumeOverride); Bit8u getModulation() const; void setModulation(unsigned int midiModulation); Bit8u getExpression() const; @@ -122,6 +127,7 @@ public: // This should only be called by Poly void partialDeactivated(Poly *poly); + virtual void polyStateChanged(PolyState oldState, PolyState newState); // These are rather specialised, and should probably only be used by PartialManager bool abortFirstPoly(PolyState polyState); @@ -146,6 +152,7 @@ public: unsigned int getAbsTimbreNum() const; void setPan(unsigned int midiPan); void setProgram(unsigned int patchNum); + void polyStateChanged(PolyState oldState, PolyState newState); }; } // namespace MT32Emu diff --git a/src/sound/munt/Partial.cpp b/src/sound/munt/Partial.cpp index 877d93b45..2a4b21d9f 100644 --- a/src/sound/munt/Partial.cpp +++ b/src/sound/munt/Partial.cpp @@ -1,5 +1,5 @@ /* Copyright (C) 2003, 2004, 2005, 2006, 2008, 2009 Dean Beeler, Jerome Fisher - * Copyright (C) 2011-2020 Dean Beeler, Jerome Fisher, Sergey V. Mikayev + * Copyright (C) 2011-2022 Dean Beeler, Jerome Fisher, Sergey V. Mikayev * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by diff --git a/src/sound/munt/Partial.h b/src/sound/munt/Partial.h index 0c4355742..bfc6f6dca 100644 --- a/src/sound/munt/Partial.h +++ b/src/sound/munt/Partial.h @@ -1,5 +1,5 @@ /* Copyright (C) 2003, 2004, 2005, 2006, 2008, 2009 Dean Beeler, Jerome Fisher - * Copyright (C) 2011-2020 Dean Beeler, Jerome Fisher, Sergey V. Mikayev + * Copyright (C) 2011-2022 Dean Beeler, Jerome Fisher, Sergey V. Mikayev * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by diff --git a/src/sound/munt/PartialManager.cpp b/src/sound/munt/PartialManager.cpp index 508d5fa6c..609adaa74 100644 --- a/src/sound/munt/PartialManager.cpp +++ b/src/sound/munt/PartialManager.cpp @@ -1,5 +1,5 @@ /* Copyright (C) 2003, 2004, 2005, 2006, 2008, 2009 Dean Beeler, Jerome Fisher - * Copyright (C) 2011-2020 Dean Beeler, Jerome Fisher, Sergey V. Mikayev + * Copyright (C) 2011-2022 Dean Beeler, Jerome Fisher, Sergey V. Mikayev * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by diff --git a/src/sound/munt/PartialManager.h b/src/sound/munt/PartialManager.h index 6b59857cc..5c019effe 100644 --- a/src/sound/munt/PartialManager.h +++ b/src/sound/munt/PartialManager.h @@ -1,5 +1,5 @@ /* Copyright (C) 2003, 2004, 2005, 2006, 2008, 2009 Dean Beeler, Jerome Fisher - * Copyright (C) 2011-2020 Dean Beeler, Jerome Fisher, Sergey V. Mikayev + * Copyright (C) 2011-2022 Dean Beeler, Jerome Fisher, Sergey V. Mikayev * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by diff --git a/src/sound/munt/Poly.cpp b/src/sound/munt/Poly.cpp index f37e471d4..0306e51ff 100644 --- a/src/sound/munt/Poly.cpp +++ b/src/sound/munt/Poly.cpp @@ -1,5 +1,5 @@ /* Copyright (C) 2003, 2004, 2005, 2006, 2008, 2009 Dean Beeler, Jerome Fisher - * Copyright (C) 2011-2020 Dean Beeler, Jerome Fisher, Sergey V. Mikayev + * Copyright (C) 2011-2022 Dean Beeler, Jerome Fisher, Sergey V. Mikayev * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by @@ -53,7 +53,7 @@ void Poly::reset(unsigned int newKey, unsigned int newVelocity, bool newSustain, activePartialCount--; } } - state = POLY_Inactive; + setState(POLY_Inactive); } key = newKey; @@ -65,7 +65,7 @@ void Poly::reset(unsigned int newKey, unsigned int newVelocity, bool newSustain, partials[i] = newPartials[i]; if (newPartials[i] != NULL) { activePartialCount++; - state = POLY_Playing; + setState(POLY_Playing); } } } @@ -80,7 +80,7 @@ bool Poly::noteOff(bool pedalHeld) { if (state == POLY_Held) { return false; } - state = POLY_Held; + setState(POLY_Held); } else { startDecay(); } @@ -98,7 +98,7 @@ bool Poly::startDecay() { if (state == POLY_Inactive || state == POLY_Releasing) { return false; } - state = POLY_Releasing; + setState(POLY_Releasing); for (int t = 0; t < 4; t++) { Partial *partial = partials[t]; @@ -123,6 +123,13 @@ bool Poly::startAbort() { return true; } +void Poly::setState(PolyState newState) { + if (state == newState) return; + PolyState oldState = state; + state = newState; + part->polyStateChanged(oldState, newState); +} + void Poly::backupCacheToPartials(PatchCache cache[4]) { for (int partialNum = 0; partialNum < 4; partialNum++) { Partial *partial = partials[partialNum]; @@ -171,7 +178,7 @@ void Poly::partialDeactivated(Partial *partial) { } } if (activePartialCount == 0) { - state = POLY_Inactive; + setState(POLY_Inactive); if (part->getSynth()->abortingPoly == this) { part->getSynth()->abortingPoly = NULL; } diff --git a/src/sound/munt/Poly.h b/src/sound/munt/Poly.h index 5b7cc30e4..dd6def094 100644 --- a/src/sound/munt/Poly.h +++ b/src/sound/munt/Poly.h @@ -1,5 +1,5 @@ /* Copyright (C) 2003, 2004, 2005, 2006, 2008, 2009 Dean Beeler, Jerome Fisher - * Copyright (C) 2011-2020 Dean Beeler, Jerome Fisher, Sergey V. Mikayev + * Copyright (C) 2011-2022 Dean Beeler, Jerome Fisher, Sergey V. Mikayev * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by @@ -41,6 +41,8 @@ private: Poly *next; + void setState(PolyState state); + public: Poly(); void setPart(Part *usePart); diff --git a/src/sound/munt/ROMInfo.cpp b/src/sound/munt/ROMInfo.cpp index 308d3eb1e..0f58cd292 100644 --- a/src/sound/munt/ROMInfo.cpp +++ b/src/sound/munt/ROMInfo.cpp @@ -1,5 +1,5 @@ /* Copyright (C) 2003, 2004, 2005, 2006, 2008, 2009 Dean Beeler, Jerome Fisher - * Copyright (C) 2011-2020 Dean Beeler, Jerome Fisher, Sergey V. Mikayev + * Copyright (C) 2011-2022 Dean Beeler, Jerome Fisher, Sergey V. Mikayev * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by @@ -19,45 +19,164 @@ #include "internals.h" +#include "File.h" #include "ROMInfo.h" namespace MT32Emu { -static const ROMInfo *getKnownROMInfoFromList(Bit32u index) { - // Known ROMs - static const ROMInfo CTRL_MT32_V1_04 = {65536, "5a5cb5a77d7d55ee69657c2f870416daed52dea7", ROMInfo::Control, "ctrl_mt32_1_04", "MT-32 Control v1.04", ROMInfo::Full, NULL}; - static const ROMInfo CTRL_MT32_V1_05 = {65536, "e17a3a6d265bf1fa150312061134293d2b58288c", ROMInfo::Control, "ctrl_mt32_1_05", "MT-32 Control v1.05", ROMInfo::Full, NULL}; - static const ROMInfo CTRL_MT32_V1_06 = {65536, "a553481f4e2794c10cfe597fef154eef0d8257de", ROMInfo::Control, "ctrl_mt32_1_06", "MT-32 Control v1.06", ROMInfo::Full, NULL}; - static const ROMInfo CTRL_MT32_V1_07 = {65536, "b083518fffb7f66b03c23b7eb4f868e62dc5a987", ROMInfo::Control, "ctrl_mt32_1_07", "MT-32 Control v1.07", ROMInfo::Full, NULL}; - static const ROMInfo CTRL_MT32_BLUER = {65536, "7b8c2a5ddb42fd0732e2f22b3340dcf5360edf92", ROMInfo::Control, "ctrl_mt32_bluer", "MT-32 Control BlueRidge", ROMInfo::Full, NULL}; +namespace { +struct ROMInfoList { + const ROMInfo * const *romInfos; + const Bit32u itemCount; +}; + +struct ROMInfoLists { + ROMInfoList mt32_1_04; + ROMInfoList mt32_1_05; + ROMInfoList mt32_1_06; + ROMInfoList mt32_1_07; + ROMInfoList mt32_bluer; + ROMInfoList mt32_2_03; + ROMInfoList mt32_2_04; + ROMInfoList mt32_2_06; + ROMInfoList mt32_2_07; + ROMInfoList cm32l_1_00; + ROMInfoList cm32l_1_02; + ROMInfoList cm32ln_1_00; + ROMInfoList fullROMInfos; + ROMInfoList partialROMInfos; + ROMInfoList allROMInfos; +}; + +} + +#define _CALC_ARRAY_LENGTH(x) Bit32u(sizeof (x) / sizeof *(x) - 1) + +static const ROMInfoLists &getROMInfoLists() { + static ROMInfo CTRL_MT32_V1_04_A = {32768, "9cd4858014c4e8a9dff96053f784bfaac1092a2e", ROMInfo::Control, "ctrl_mt32_1_04_a", "MT-32 Control v1.04", ROMInfo::Mux0, NULL}; + static ROMInfo CTRL_MT32_V1_04_B = {32768, "fe8db469b5bfeb37edb269fd47e3ce6d91014652", ROMInfo::Control, "ctrl_mt32_1_04_b", "MT-32 Control v1.04", ROMInfo::Mux1, &CTRL_MT32_V1_04_A}; + static ROMInfo CTRL_MT32_V1_04 = {65536, "5a5cb5a77d7d55ee69657c2f870416daed52dea7", ROMInfo::Control, "ctrl_mt32_1_04", "MT-32 Control v1.04", ROMInfo::Full, NULL}; + static ROMInfo CTRL_MT32_V1_05_A = {32768, "57a09d80d2f7ca5b9734edbe9645e6e700f83701", ROMInfo::Control, "ctrl_mt32_1_05_a", "MT-32 Control v1.05", ROMInfo::Mux0, NULL}; + static ROMInfo CTRL_MT32_V1_05_B = {32768, "52e3c6666db9ef962591a8ee99be0cde17f3a6b6", ROMInfo::Control, "ctrl_mt32_1_05_b", "MT-32 Control v1.05", ROMInfo::Mux1, &CTRL_MT32_V1_05_A}; + static ROMInfo CTRL_MT32_V1_05 = {65536, "e17a3a6d265bf1fa150312061134293d2b58288c", ROMInfo::Control, "ctrl_mt32_1_05", "MT-32 Control v1.05", ROMInfo::Full, NULL}; + static ROMInfo CTRL_MT32_V1_06_A = {32768, "cc83bf23cee533097fb4c7e2c116e43b50ebacc8", ROMInfo::Control, "ctrl_mt32_1_06_a", "MT-32 Control v1.06", ROMInfo::Mux0, NULL}; + static ROMInfo CTRL_MT32_V1_06_B = {32768, "bf4f15666bc46679579498386704893b630c1171", ROMInfo::Control, "ctrl_mt32_1_06_b", "MT-32 Control v1.06", ROMInfo::Mux1, &CTRL_MT32_V1_06_A}; + static ROMInfo CTRL_MT32_V1_06 = {65536, "a553481f4e2794c10cfe597fef154eef0d8257de", ROMInfo::Control, "ctrl_mt32_1_06", "MT-32 Control v1.06", ROMInfo::Full, NULL}; + static ROMInfo CTRL_MT32_V1_07_A = {32768, "13f06b38f0d9e0fc050b6503ab777bb938603260", ROMInfo::Control, "ctrl_mt32_1_07_a", "MT-32 Control v1.07", ROMInfo::Mux0, NULL}; + static ROMInfo CTRL_MT32_V1_07_B = {32768, "c55e165487d71fa88bd8c5e9c083bc456c1a89aa", ROMInfo::Control, "ctrl_mt32_1_07_b", "MT-32 Control v1.07", ROMInfo::Mux1, &CTRL_MT32_V1_07_A}; + static ROMInfo CTRL_MT32_V1_07 = {65536, "b083518fffb7f66b03c23b7eb4f868e62dc5a987", ROMInfo::Control, "ctrl_mt32_1_07", "MT-32 Control v1.07", ROMInfo::Full, NULL}; + static ROMInfo CTRL_MT32_BLUER_A = {32768, "11a6ae5d8b6ee328b371af7f1e40b82125aa6b4d", ROMInfo::Control, "ctrl_mt32_bluer_a", "MT-32 Control BlueRidge", ROMInfo::Mux0, NULL}; + static ROMInfo CTRL_MT32_BLUER_B = {32768, "e0934320d7cbb5edfaa29e0d01ae835ef620085b", ROMInfo::Control, "ctrl_mt32_bluer_b", "MT-32 Control BlueRidge", ROMInfo::Mux1, &CTRL_MT32_BLUER_A}; + static ROMInfo CTRL_MT32_BLUER = {65536, "7b8c2a5ddb42fd0732e2f22b3340dcf5360edf92", ROMInfo::Control, "ctrl_mt32_bluer", "MT-32 Control BlueRidge", ROMInfo::Full, NULL}; + + static const ROMInfo CTRL_MT32_V2_03 = {131072, "5837064c9df4741a55f7c4d8787ac158dff2d3ce", ROMInfo::Control, "ctrl_mt32_2_03", "MT-32 Control v2.03", ROMInfo::Full, NULL}; static const ROMInfo CTRL_MT32_V2_04 = {131072, "2c16432b6c73dd2a3947cba950a0f4c19d6180eb", ROMInfo::Control, "ctrl_mt32_2_04", "MT-32 Control v2.04", ROMInfo::Full, NULL}; + static const ROMInfo CTRL_MT32_V2_06 = {131072, "2869cf4c235d671668cfcb62415e2ce8323ad4ed", ROMInfo::Control, "ctrl_mt32_2_06", "MT-32 Control v2.06", ROMInfo::Full, NULL}; + static const ROMInfo CTRL_MT32_V2_07 = {131072, "47b52adefedaec475c925e54340e37673c11707c", ROMInfo::Control, "ctrl_mt32_2_07", "MT-32 Control v2.07", ROMInfo::Full, NULL}; static const ROMInfo CTRL_CM32L_V1_00 = {65536, "73683d585cd6948cc19547942ca0e14a0319456d", ROMInfo::Control, "ctrl_cm32l_1_00", "CM-32L/LAPC-I Control v1.00", ROMInfo::Full, NULL}; static const ROMInfo CTRL_CM32L_V1_02 = {65536, "a439fbb390da38cada95a7cbb1d6ca199cd66ef8", ROMInfo::Control, "ctrl_cm32l_1_02", "CM-32L/LAPC-I Control v1.02", ROMInfo::Full, NULL}; + static const ROMInfo CTRL_CM32LN_V1_00 = {65536, "dc1c5b1b90a4646d00f7daf3679733c7badc7077", ROMInfo::Control, "ctrl_cm32ln_1_00", "CM-32LN/CM-500/LAPC-N Control v1.00", ROMInfo::Full, NULL}; - static const ROMInfo PCM_MT32 = {524288, "f6b1eebc4b2d200ec6d3d21d51325d5b48c60252", ROMInfo::PCM, "pcm_mt32", "MT-32 PCM ROM", ROMInfo::Full, NULL}; - static const ROMInfo PCM_CM32L = {1048576, "289cc298ad532b702461bfc738009d9ebe8025ea", ROMInfo::PCM, "pcm_cm32l", "CM-32L/CM-64/LAPC-I PCM ROM", ROMInfo::Full, NULL}; + static ROMInfo PCM_MT32_L = {262144, "3a1e19b0cd4036623fd1d1d11f5f25995585962b", ROMInfo::PCM, "pcm_mt32_l", "MT-32 PCM ROM", ROMInfo::FirstHalf, NULL}; + static ROMInfo PCM_MT32_H = {262144, "2cadb99d21a6a4a6f5b61b6218d16e9b43f61d01", ROMInfo::PCM, "pcm_mt32_h", "MT-32 PCM ROM", ROMInfo::SecondHalf, &PCM_MT32_L}; + static ROMInfo PCM_MT32 = {524288, "f6b1eebc4b2d200ec6d3d21d51325d5b48c60252", ROMInfo::PCM, "pcm_mt32", "MT-32 PCM ROM", ROMInfo::Full, NULL}; + // Alias of PCM_MT32 ROM, only useful for pairing with PCM_CM32L_H. + static ROMInfo PCM_CM32L_L = {524288, "f6b1eebc4b2d200ec6d3d21d51325d5b48c60252", ROMInfo::PCM, "pcm_cm32l_l", "CM-32L/CM-64/LAPC-I PCM ROM", ROMInfo::FirstHalf, NULL}; + static ROMInfo PCM_CM32L_H = {524288, "3ad889fde5db5b6437cbc2eb6e305312fec3df93", ROMInfo::PCM, "pcm_cm32l_h", "CM-32L/CM-64/LAPC-I PCM ROM", ROMInfo::SecondHalf, &PCM_CM32L_L}; + static ROMInfo PCM_CM32L = {1048576, "289cc298ad532b702461bfc738009d9ebe8025ea", ROMInfo::PCM, "pcm_cm32l", "CM-32L/CM-64/LAPC-I PCM ROM", ROMInfo::Full, NULL}; - static const ROMInfo * const ROM_INFOS[] = { + static const ROMInfo * const FULL_ROM_INFOS[] = { &CTRL_MT32_V1_04, &CTRL_MT32_V1_05, &CTRL_MT32_V1_06, &CTRL_MT32_V1_07, &CTRL_MT32_BLUER, + &CTRL_MT32_V2_03, &CTRL_MT32_V2_04, + &CTRL_MT32_V2_06, + &CTRL_MT32_V2_07, &CTRL_CM32L_V1_00, &CTRL_CM32L_V1_02, + &CTRL_CM32LN_V1_00, &PCM_MT32, &PCM_CM32L, - NULL}; + NULL + }; + static const ROMInfo * const PARTIAL_ROM_INFOS[] = { + &CTRL_MT32_V1_04_A, &CTRL_MT32_V1_04_B, + &CTRL_MT32_V1_05_A, &CTRL_MT32_V1_05_B, + &CTRL_MT32_V1_06_A, &CTRL_MT32_V1_06_B, + &CTRL_MT32_V1_07_A, &CTRL_MT32_V1_07_B, + &CTRL_MT32_BLUER_A, &CTRL_MT32_BLUER_B, + &PCM_MT32_L, &PCM_MT32_H, + &PCM_CM32L_L, &PCM_CM32L_H, + NULL + }; + static const ROMInfo *ALL_ROM_INFOS[_CALC_ARRAY_LENGTH(FULL_ROM_INFOS) + _CALC_ARRAY_LENGTH(PARTIAL_ROM_INFOS) + 1]; - return ROM_INFOS[index]; + if (CTRL_MT32_V1_04_A.pairROMInfo == NULL) { + CTRL_MT32_V1_04_A.pairROMInfo = &CTRL_MT32_V1_04_B; + CTRL_MT32_V1_05_A.pairROMInfo = &CTRL_MT32_V1_05_B; + CTRL_MT32_V1_06_A.pairROMInfo = &CTRL_MT32_V1_06_B; + CTRL_MT32_V1_07_A.pairROMInfo = &CTRL_MT32_V1_07_B; + CTRL_MT32_BLUER_A.pairROMInfo = &CTRL_MT32_BLUER_B; + PCM_MT32_L.pairROMInfo = &PCM_MT32_H; + PCM_CM32L_L.pairROMInfo = &PCM_CM32L_H; + + memcpy(&ALL_ROM_INFOS[0], FULL_ROM_INFOS, sizeof FULL_ROM_INFOS); + memcpy(&ALL_ROM_INFOS[_CALC_ARRAY_LENGTH(FULL_ROM_INFOS)], PARTIAL_ROM_INFOS, sizeof PARTIAL_ROM_INFOS); // Includes NULL terminator. + } + + static const ROMInfo * const MT32_V1_04_ROMS[] = {&CTRL_MT32_V1_04, &PCM_MT32, &CTRL_MT32_V1_04_A, &CTRL_MT32_V1_04_B, &PCM_MT32_L, &PCM_MT32_H, NULL}; + static const ROMInfo * const MT32_V1_05_ROMS[] = {&CTRL_MT32_V1_05, &PCM_MT32, &CTRL_MT32_V1_05_A, &CTRL_MT32_V1_05_B, &PCM_MT32_L, &PCM_MT32_H, NULL}; + static const ROMInfo * const MT32_V1_06_ROMS[] = {&CTRL_MT32_V1_06, &PCM_MT32, &CTRL_MT32_V1_06_A, &CTRL_MT32_V1_06_B, &PCM_MT32_L, &PCM_MT32_H, NULL}; + static const ROMInfo * const MT32_V1_07_ROMS[] = {&CTRL_MT32_V1_07, &PCM_MT32, &CTRL_MT32_V1_07_A, &CTRL_MT32_V1_07_B, &PCM_MT32_L, &PCM_MT32_H, NULL}; + static const ROMInfo * const MT32_BLUER_ROMS[] = {&CTRL_MT32_BLUER, &PCM_MT32, &CTRL_MT32_BLUER_A, &CTRL_MT32_BLUER_B, &PCM_MT32_L, &PCM_MT32_H, NULL}; + static const ROMInfo * const MT32_V2_03_ROMS[] = {&CTRL_MT32_V2_03, &PCM_MT32, &PCM_MT32_L, &PCM_MT32_H, NULL}; + static const ROMInfo * const MT32_V2_04_ROMS[] = {&CTRL_MT32_V2_04, &PCM_MT32, &PCM_MT32_L, &PCM_MT32_H, NULL}; + static const ROMInfo * const MT32_V2_06_ROMS[] = {&CTRL_MT32_V2_06, &PCM_MT32, &PCM_MT32_L, &PCM_MT32_H, NULL}; + static const ROMInfo * const MT32_V2_07_ROMS[] = {&CTRL_MT32_V2_07, &PCM_MT32, &PCM_MT32_L, &PCM_MT32_H, NULL}; + static const ROMInfo * const CM32L_V1_00_ROMS[] = {&CTRL_CM32L_V1_00, &PCM_CM32L, &PCM_CM32L_L, &PCM_CM32L_H, NULL}; + static const ROMInfo * const CM32L_V1_02_ROMS[] = {&CTRL_CM32L_V1_02, &PCM_CM32L, &PCM_CM32L_L, &PCM_CM32L_H, NULL}; + static const ROMInfo * const CM32LN_V1_00_ROMS[] = {&CTRL_CM32LN_V1_00, &PCM_CM32L, NULL}; + + static const ROMInfoLists romInfoLists = { + {MT32_V1_04_ROMS, _CALC_ARRAY_LENGTH(MT32_V1_04_ROMS)}, + {MT32_V1_05_ROMS, _CALC_ARRAY_LENGTH(MT32_V1_05_ROMS)}, + {MT32_V1_06_ROMS, _CALC_ARRAY_LENGTH(MT32_V1_06_ROMS)}, + {MT32_V1_07_ROMS, _CALC_ARRAY_LENGTH(MT32_V1_07_ROMS)}, + {MT32_BLUER_ROMS, _CALC_ARRAY_LENGTH(MT32_BLUER_ROMS)}, + {MT32_V2_03_ROMS, _CALC_ARRAY_LENGTH(MT32_V2_03_ROMS)}, + {MT32_V2_04_ROMS, _CALC_ARRAY_LENGTH(MT32_V2_04_ROMS)}, + {MT32_V2_06_ROMS, _CALC_ARRAY_LENGTH(MT32_V2_06_ROMS)}, + {MT32_V2_07_ROMS, _CALC_ARRAY_LENGTH(MT32_V2_07_ROMS)}, + {CM32L_V1_00_ROMS, _CALC_ARRAY_LENGTH(CM32L_V1_00_ROMS)}, + {CM32L_V1_02_ROMS, _CALC_ARRAY_LENGTH(CM32L_V1_02_ROMS)}, + {CM32LN_V1_00_ROMS, _CALC_ARRAY_LENGTH(CM32LN_V1_00_ROMS)}, + {FULL_ROM_INFOS, _CALC_ARRAY_LENGTH(FULL_ROM_INFOS)}, + {PARTIAL_ROM_INFOS, _CALC_ARRAY_LENGTH(PARTIAL_ROM_INFOS)}, + {ALL_ROM_INFOS, _CALC_ARRAY_LENGTH(ALL_ROM_INFOS)} + }; + return romInfoLists; } -const ROMInfo* ROMInfo::getROMInfo(File *file) { +static const ROMInfo * const *getKnownROMInfoList() { + return getROMInfoLists().allROMInfos.romInfos; +} + +static const ROMInfo *getKnownROMInfoFromList(Bit32u index) { + return getKnownROMInfoList()[index]; +} + +const ROMInfo *ROMInfo::getROMInfo(File *file) { + return getROMInfo(file, getKnownROMInfoList()); +} + +const ROMInfo *ROMInfo::getROMInfo(File *file, const ROMInfo * const *romInfos) { size_t fileSize = file->getSize(); - for (Bit32u i = 0; getKnownROMInfoFromList(i) != NULL; i++) { - const ROMInfo *romInfo = getKnownROMInfoFromList(i); + for (Bit32u i = 0; romInfos[i] != NULL; i++) { + const ROMInfo *romInfo = romInfos[i]; if (fileSize == romInfo->fileSize && !strcmp(file->getSHA1(), romInfo->sha1Digest)) { return romInfo; } @@ -69,17 +188,11 @@ void ROMInfo::freeROMInfo(const ROMInfo *romInfo) { (void) romInfo; } -static Bit32u getROMCount() { - Bit32u count; - for(count = 0; getKnownROMInfoFromList(count) != NULL; count++) { - } - return count; -} - -const ROMInfo** ROMInfo::getROMInfoList(Bit32u types, Bit32u pairTypes) { - const ROMInfo **romInfoList = new const ROMInfo*[getROMCount() + 1]; +const ROMInfo **ROMInfo::getROMInfoList(Bit32u types, Bit32u pairTypes) { + Bit32u romCount = getROMInfoLists().allROMInfos.itemCount; // Excludes the NULL terminator. + const ROMInfo **romInfoList = new const ROMInfo*[romCount + 1]; const ROMInfo **currentROMInList = romInfoList; - for (Bit32u i = 0; getKnownROMInfoFromList(i) != NULL; i++) { + for (Bit32u i = 0; i < romCount; i++) { const ROMInfo *romInfo = getKnownROMInfoFromList(i); if ((types & (1 << romInfo->type)) && (pairTypes & (1 << romInfo->pairType))) { *currentROMInList++ = romInfo; @@ -93,27 +206,157 @@ void ROMInfo::freeROMInfoList(const ROMInfo **romInfoList) { delete[] romInfoList; } -ROMImage::ROMImage(File *useFile) : file(useFile), romInfo(ROMInfo::getROMInfo(file)) +const ROMInfo * const *ROMInfo::getAllROMInfos(Bit32u *itemCount) { + if (itemCount != NULL) *itemCount = getROMInfoLists().allROMInfos.itemCount; + return getROMInfoLists().allROMInfos.romInfos; +} + +const ROMInfo * const *ROMInfo::getFullROMInfos(Bit32u *itemCount) { + if (itemCount != NULL) *itemCount = getROMInfoLists().fullROMInfos.itemCount; + return getROMInfoLists().fullROMInfos.romInfos; +} + +const ROMInfo * const *ROMInfo::getPartialROMInfos(Bit32u *itemCount) { + if (itemCount != NULL) *itemCount = getROMInfoLists().partialROMInfos.itemCount; + return getROMInfoLists().partialROMInfos.romInfos; +} + +const ROMImage *ROMImage::makeFullROMImage(Bit8u *data, size_t dataSize) { + return new ROMImage(new ArrayFile(data, dataSize), true, getKnownROMInfoList()); +} + +const ROMImage *ROMImage::appendImages(const ROMImage *romImageLow, const ROMImage *romImageHigh) { + const Bit8u *romDataLow = romImageLow->getFile()->getData(); + const Bit8u *romDataHigh = romImageHigh->getFile()->getData(); + size_t partSize = romImageLow->getFile()->getSize(); + Bit8u *data = new Bit8u[2 * partSize]; + memcpy(data, romDataLow, partSize); + memcpy(data + partSize, romDataHigh, partSize); + const ROMImage *romImageFull = makeFullROMImage(data, 2 * partSize); + if (romImageFull->getROMInfo() == NULL) { + freeROMImage(romImageFull); + return NULL; + } + return romImageFull; +} + +const ROMImage *ROMImage::interleaveImages(const ROMImage *romImageEven, const ROMImage *romImageOdd) { + const Bit8u *romDataEven = romImageEven->getFile()->getData(); + const Bit8u *romDataOdd = romImageOdd->getFile()->getData(); + size_t partSize = romImageEven->getFile()->getSize(); + Bit8u *data = new Bit8u[2 * partSize]; + Bit8u *writePtr = data; + for (size_t romDataIx = 0; romDataIx < partSize; romDataIx++) { + *(writePtr++) = romDataEven[romDataIx]; + *(writePtr++) = romDataOdd[romDataIx]; + } + const ROMImage *romImageFull = makeFullROMImage(data, 2 * partSize); + if (romImageFull->getROMInfo() == NULL) { + freeROMImage(romImageFull); + return NULL; + } + return romImageFull; +} + +ROMImage::ROMImage(File *useFile, bool useOwnFile, const ROMInfo * const *romInfos) : + file(useFile), ownFile(useOwnFile), romInfo(ROMInfo::getROMInfo(file, romInfos)) {} ROMImage::~ROMImage() { ROMInfo::freeROMInfo(romInfo); + if (ownFile) { + const Bit8u *data = file->getData(); + delete file; + delete[] data; + } } -const ROMImage* ROMImage::makeROMImage(File *file) { - return new ROMImage(file); +const ROMImage *ROMImage::makeROMImage(File *file) { + return new ROMImage(file, false, getKnownROMInfoList()); +} + +const ROMImage *ROMImage::makeROMImage(File *file, const ROMInfo * const *romInfos) { + return new ROMImage(file, false, romInfos); +} + +const ROMImage *ROMImage::makeROMImage(File *file1, File *file2) { + const ROMInfo * const *partialROMInfos = getROMInfoLists().partialROMInfos.romInfos; + const ROMImage *image1 = makeROMImage(file1, partialROMInfos); + const ROMImage *image2 = makeROMImage(file2, partialROMInfos); + const ROMImage *fullImage = image1->getROMInfo() == NULL || image2->getROMInfo() == NULL ? NULL : mergeROMImages(image1, image2); + freeROMImage(image1); + freeROMImage(image2); + return fullImage; } void ROMImage::freeROMImage(const ROMImage *romImage) { delete romImage; } -File* ROMImage::getFile() const { +const ROMImage *ROMImage::mergeROMImages(const ROMImage *romImage1, const ROMImage *romImage2) { + if (romImage1->romInfo->pairROMInfo != romImage2->romInfo) { + return NULL; + } + switch (romImage1->romInfo->pairType) { + case ROMInfo::FirstHalf: + return appendImages(romImage1, romImage2); + case ROMInfo::SecondHalf: + return appendImages(romImage2, romImage1); + case ROMInfo::Mux0: + return interleaveImages(romImage1, romImage2); + case ROMInfo::Mux1: + return interleaveImages(romImage2, romImage1); + default: + break; + } + return NULL; +} + +File *ROMImage::getFile() const { return file; } -const ROMInfo* ROMImage::getROMInfo() const { +bool ROMImage::isFileUserProvided() const { + return !ownFile; +} + +const ROMInfo *ROMImage::getROMInfo() const { return romInfo; } +const MachineConfiguration * const *MachineConfiguration::getAllMachineConfigurations(Bit32u *itemCount) { + static const ROMInfoLists &romInfoLists = getROMInfoLists(); + static const MachineConfiguration MT32_1_04 = MachineConfiguration("mt32_1_04", romInfoLists.mt32_1_04.romInfos, romInfoLists.mt32_1_04.itemCount); + static const MachineConfiguration MT32_1_05 = MachineConfiguration("mt32_1_05", romInfoLists.mt32_1_05.romInfos, romInfoLists.mt32_1_05.itemCount); + static const MachineConfiguration MT32_1_06 = MachineConfiguration("mt32_1_06", romInfoLists.mt32_1_06.romInfos, romInfoLists.mt32_1_06.itemCount); + static const MachineConfiguration MT32_1_07 = MachineConfiguration("mt32_1_07", romInfoLists.mt32_1_07.romInfos, romInfoLists.mt32_1_07.itemCount); + static const MachineConfiguration MT32_BLUER = MachineConfiguration("mt32_bluer", romInfoLists.mt32_bluer.romInfos, romInfoLists.mt32_bluer.itemCount); + static const MachineConfiguration MT32_2_03 = MachineConfiguration("mt32_2_03", romInfoLists.mt32_2_03.romInfos, romInfoLists.mt32_2_03.itemCount); + static const MachineConfiguration MT32_2_04 = MachineConfiguration("mt32_2_04", romInfoLists.mt32_2_04.romInfos, romInfoLists.mt32_2_04.itemCount); + static const MachineConfiguration MT32_2_06 = MachineConfiguration("mt32_2_06", romInfoLists.mt32_2_06.romInfos, romInfoLists.mt32_2_06.itemCount); + static const MachineConfiguration MT32_2_07 = MachineConfiguration("mt32_2_07", romInfoLists.mt32_2_07.romInfos, romInfoLists.mt32_2_07.itemCount); + static const MachineConfiguration CM32L_1_00 = MachineConfiguration("cm32l_1_00", romInfoLists.cm32l_1_00.romInfos, romInfoLists.cm32l_1_00.itemCount); + static const MachineConfiguration CM32L_1_02 = MachineConfiguration("cm32l_1_02", romInfoLists.cm32l_1_02.romInfos, romInfoLists.cm32l_1_02.itemCount); + static const MachineConfiguration CM32LN_1_00 = MachineConfiguration("cm32ln_1_00", romInfoLists.cm32ln_1_00.romInfos, romInfoLists.cm32ln_1_00.itemCount); + static const MachineConfiguration * const MACHINE_CONFIGURATIONS[] = { + &MT32_1_04, &MT32_1_05, &MT32_1_06, &MT32_1_07, &MT32_BLUER, &MT32_2_03, &MT32_2_04, &MT32_2_06, &MT32_2_07, &CM32L_1_00, &CM32L_1_02, &CM32LN_1_00, NULL + }; + + if (itemCount != NULL) *itemCount = _CALC_ARRAY_LENGTH(MACHINE_CONFIGURATIONS); + return MACHINE_CONFIGURATIONS; +} + +MachineConfiguration::MachineConfiguration(const char *useMachineID, const ROMInfo * const *useROMInfos, Bit32u useROMInfosCount) : + machineID(useMachineID), romInfos(useROMInfos), romInfosCount(useROMInfosCount) +{} + +const char *MachineConfiguration::getMachineID() const { + return machineID; +} + +const ROMInfo * const *MachineConfiguration::getCompatibleROMInfos(Bit32u *itemCount) const { + if (itemCount != NULL) *itemCount = romInfosCount; + return romInfos; +} + } // namespace MT32Emu diff --git a/src/sound/munt/ROMInfo.h b/src/sound/munt/ROMInfo.h index b695ba2a1..1580362f4 100644 --- a/src/sound/munt/ROMInfo.h +++ b/src/sound/munt/ROMInfo.h @@ -1,5 +1,5 @@ /* Copyright (C) 2003, 2004, 2005, 2006, 2008, 2009 Dean Beeler, Jerome Fisher - * Copyright (C) 2011-2020 Dean Beeler, Jerome Fisher, Sergey V. Mikayev + * Copyright (C) 2011-2022 Dean Beeler, Jerome Fisher, Sergey V. Mikayev * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by @@ -34,11 +34,28 @@ public: enum Type {PCM, Control, Reverb} type; const char *shortName; const char *description; - enum PairType {Full, FirstHalf, SecondHalf, Mux0, Mux1} pairType; - ROMInfo *pairROMInfo; + enum PairType { + // Complete ROM image ready to use with Synth. + Full, + // ROM image contains data that occupies lower addresses. Needs pairing before use. + FirstHalf, + // ROM image contains data that occupies higher addresses. Needs pairing before use. + SecondHalf, + // ROM image contains data that occupies even addresses. Needs pairing before use. + Mux0, + // ROM image contains data that occupies odd addresses. Needs pairing before use. + Mux1 + } pairType; + // NULL for Full images or a pointer to the corresponding other image for pairing. + const ROMInfo *pairROMInfo; - // Returns a ROMInfo struct by inspecting the size and the SHA1 hash - MT32EMU_EXPORT static const ROMInfo* getROMInfo(File *file); + // Returns a ROMInfo struct by inspecting the size and the SHA1 hash of the file + // among all the known ROMInfos. + MT32EMU_EXPORT static const ROMInfo *getROMInfo(File *file); + + // Returns a ROMInfo struct by inspecting the size and the SHA1 hash of the file + // among the ROMInfos listed in the NULL-terminated list romInfos. + MT32EMU_EXPORT_V(2.5) static const ROMInfo *getROMInfo(File *file, const ROMInfo * const *romInfos); // Currently no-op MT32EMU_EXPORT static void freeROMInfo(const ROMInfo *romInfo); @@ -46,33 +63,111 @@ public: // Allows retrieving a NULL-terminated list of ROMInfos for a range of types and pairTypes // (specified by bitmasks) // Useful for GUI/console app to output information on what ROMs it supports - MT32EMU_EXPORT static const ROMInfo** getROMInfoList(Bit32u types, Bit32u pairTypes); + // The caller must free the returned list with freeROMInfoList when finished. + MT32EMU_EXPORT static const ROMInfo **getROMInfoList(Bit32u types, Bit32u pairTypes); - // Frees the list of ROMInfos given + // Frees the list of ROMInfos given that has been created by getROMInfoList. MT32EMU_EXPORT static void freeROMInfoList(const ROMInfo **romInfos); + + // Returns an immutable NULL-terminated list of all (full and partial) supported ROMInfos. + // For convenience, this method also can fill the number of non-NULL items present in the list + // if a non-NULL value is provided in optional argument itemCount. + MT32EMU_EXPORT_V(2.5) static const ROMInfo * const *getAllROMInfos(Bit32u *itemCount = NULL); + // Returns an immutable NULL-terminated list of all supported full ROMInfos. + // For convenience, this method also can fill the number of non-NULL items present in the list + // if a non-NULL value is provided in optional argument itemCount. + MT32EMU_EXPORT_V(2.5) static const ROMInfo * const *getFullROMInfos(Bit32u *itemCount = NULL); + // Returns an immutable NULL-terminated list of all supported partial ROMInfos. + // For convenience, this method also can fill the number of non-NULL items present in the list + // if a non-NULL value is provided in optional argument itemCount. + MT32EMU_EXPORT_V(2.5) static const ROMInfo * const *getPartialROMInfos(Bit32u *itemCount = NULL); }; -// Synth::open() is to require a full control ROMImage and a full PCM ROMImage to work +// Synth::open() requires a full control ROMImage and a compatible full PCM ROMImage to work class ROMImage { -private: - File * const file; - const ROMInfo * const romInfo; - - ROMImage(File *file); - ~ROMImage(); - public: // Creates a ROMImage object given a ROMInfo and a File. Keeps a reference // to the File and ROMInfo given, which must be freed separately by the user - // after the ROMImage is freed - MT32EMU_EXPORT static const ROMImage* makeROMImage(File *file); + // after the ROMImage is freed. + // CAVEAT: This method always prefers full ROM images over partial ones. + // Because the lower half of CM-32L/CM-64/LAPC-I PCM ROM is essentially the full + // MT-32 PCM ROM, it is therefore aliased. In this case a partial image can only be + // created by the overridden method makeROMImage(File *, const ROMInfo * const *). + MT32EMU_EXPORT static const ROMImage *makeROMImage(File *file); + + // Same as the method above but only permits creation of a ROMImage if the file content + // matches one of the ROMs described in a NULL-terminated list romInfos. This list can be + // created using e.g. method ROMInfo::getROMInfoList. + MT32EMU_EXPORT_V(2.5) static const ROMImage *makeROMImage(File *file, const ROMInfo * const *romInfos); + + // Creates a ROMImage object given a couple of files that contain compatible partial ROM images. + // The files aren't referenced by the resulting ROMImage and may be freed anytime afterwards. + // The file in the resulting image will be automatically freed along with the ROMImage. + // If the given files contain incompatible partial images, NULL is returned. + MT32EMU_EXPORT_V(2.5) static const ROMImage *makeROMImage(File *file1, File *file2); // Must only be done after all Synths using the ROMImage are deleted MT32EMU_EXPORT static void freeROMImage(const ROMImage *romImage); + // Checks whether the given ROMImages are pairable and merges them into a full image, if possible. + // If the check fails, NULL is returned. + MT32EMU_EXPORT_V(2.5) static const ROMImage *mergeROMImages(const ROMImage *romImage1, const ROMImage *romImage2); + MT32EMU_EXPORT File *getFile() const; + + // Returns true in case this ROMImage is built with a user provided File that has to be deallocated separately. + // For a ROMImage created via merging two partial ROMImages, this method returns false. + MT32EMU_EXPORT_V(2.5) bool isFileUserProvided() const; MT32EMU_EXPORT const ROMInfo *getROMInfo() const; + +private: + static const ROMImage *makeFullROMImage(Bit8u *data, size_t dataSize); + static const ROMImage *appendImages(const ROMImage *romImageLow, const ROMImage *romImageHigh); + static const ROMImage *interleaveImages(const ROMImage *romImageEven, const ROMImage *romImageOdd); + + File * const file; + const bool ownFile; + const ROMInfo * const romInfo; + + ROMImage(File *file, bool ownFile, const ROMInfo * const *romInfos); + ~ROMImage(); + + // Make ROMIMage an identity class. + ROMImage(const ROMImage &); + ROMImage &operator=(const ROMImage &); +}; + +class MachineConfiguration { +public: + // Returns an immutable NULL-terminated list of all supported machine configurations. + // For convenience, this method also can fill the number of non-NULL items present in the list + // if a non-NULL value is provided in optional argument itemCount. + MT32EMU_EXPORT_V(2.5) static const MachineConfiguration * const *getAllMachineConfigurations(Bit32u *itemCount = NULL); + + // Returns a string identifier of this MachineConfiguration. + MT32EMU_EXPORT_V(2.5) const char *getMachineID() const; + + // Returns an immutable NULL-terminated list of ROMInfos that are compatible with this + // MachineConfiguration. That means the respective ROMImages can be successfully used together + // by the emulation engine. Calling ROMInfo::getROMInfo or ROMImage::makeROMImage with this list + // supplied enables identification of all files containing desired ROM images while filtering out + // any incompatible ones. + // For convenience, this method also can fill the number of non-NULL items present in the list + // if a non-NULL value is provided in optional argument itemCount. + MT32EMU_EXPORT_V(2.5) const ROMInfo * const *getCompatibleROMInfos(Bit32u *itemCount = NULL) const; + +private: + const char * const machineID; + const ROMInfo * const * const romInfos; + const Bit32u romInfosCount; + + MachineConfiguration(const char *machineID, const ROMInfo * const *romInfos, Bit32u romInfosCount); + + // Make MachineConfiguration an identity class. + MachineConfiguration(const MachineConfiguration &); + ~MachineConfiguration() {} + MachineConfiguration &operator=(const MachineConfiguration &); }; } // namespace MT32Emu diff --git a/src/sound/munt/SampleRateConverter.cpp b/src/sound/munt/SampleRateConverter.cpp index 9ae35e962..cce6f59fd 100644 --- a/src/sound/munt/SampleRateConverter.cpp +++ b/src/sound/munt/SampleRateConverter.cpp @@ -1,4 +1,4 @@ -/* Copyright (C) 2015-2020 Sergey V. Mikayev +/* Copyright (C) 2015-2022 Sergey V. Mikayev * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by diff --git a/src/sound/munt/SampleRateConverter.h b/src/sound/munt/SampleRateConverter.h index 96f3925e3..6831ff2a0 100644 --- a/src/sound/munt/SampleRateConverter.h +++ b/src/sound/munt/SampleRateConverter.h @@ -1,4 +1,4 @@ -/* Copyright (C) 2015-2020 Sergey V. Mikayev +/* Copyright (C) 2015-2022 Sergey V. Mikayev * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by diff --git a/src/sound/munt/SampleRateConverter_dummy.cpp b/src/sound/munt/SampleRateConverter_dummy.cpp deleted file mode 100644 index 09f491338..000000000 --- a/src/sound/munt/SampleRateConverter_dummy.cpp +++ /dev/null @@ -1,63 +0,0 @@ -/* Copyright (C) 2015-2017 Sergey V. Mikayev - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU Lesser General Public License as published by - * the Free Software Foundation, either version 2.1 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with this program. If not, see . - */ - -#include -#include -#include <86box/plat.h> -#include "SampleRateConverter.h" - -#include "Synth.h" - -using namespace MT32Emu; - -static inline void *createDelegate(UNUSED(Synth &synth), UNUSED(double targetSampleRate), UNUSED(SamplerateConversionQuality quality)) { - return 0; -} - -AnalogOutputMode SampleRateConverter::getBestAnalogOutputMode(UNUSED(double targetSampleRate)) { - return AnalogOutputMode_COARSE; -} - -SampleRateConverter::SampleRateConverter(Synth &useSynth, double targetSampleRate, SamplerateConversionQuality useQuality) : - synthInternalToTargetSampleRateRatio(SAMPLE_RATE / targetSampleRate), - useSynthDelegate(useSynth.getStereoOutputSampleRate() == targetSampleRate), - srcDelegate(useSynthDelegate ? &useSynth : createDelegate(useSynth, targetSampleRate, useQuality)) -{} - -SampleRateConverter::~SampleRateConverter() { -} - -void SampleRateConverter::getOutputSamples(float *buffer, unsigned int length) { - if (useSynthDelegate) { - static_cast(srcDelegate)->render(buffer, length); - return; - } -} - -void SampleRateConverter::getOutputSamples(Bit16s *outBuffer, unsigned int length) { - if (useSynthDelegate) { - static_cast(srcDelegate)->render(outBuffer, length); - return; - } -} - -double SampleRateConverter::convertOutputToSynthTimestamp(double outputTimestamp) const { - return outputTimestamp * synthInternalToTargetSampleRateRatio; -} - -double SampleRateConverter::convertSynthToOutputTimestamp(double synthTimestamp) const { - return synthTimestamp / synthInternalToTargetSampleRateRatio; -} diff --git a/src/sound/munt/Structures.h b/src/sound/munt/Structures.h index 8202c44b9..171033325 100644 --- a/src/sound/munt/Structures.h +++ b/src/sound/munt/Structures.h @@ -1,5 +1,5 @@ /* Copyright (C) 2003, 2004, 2005, 2006, 2008, 2009 Dean Beeler, Jerome Fisher - * Copyright (C) 2011-2020 Dean Beeler, Jerome Fisher, Sergey V. Mikayev + * Copyright (C) 2011-2022 Dean Beeler, Jerome Fisher, Sergey V. Mikayev * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by @@ -191,6 +191,9 @@ struct ControlROMFeatureSet { unsigned int quirkPanMult : 1; unsigned int quirkKeyShift : 1; unsigned int quirkTVFBaseCutoffLimit : 1; + unsigned int quirkFastPitchChanges : 1; + unsigned int quirkDisplayCustomMessagePriority : 1; + unsigned int oldMT32DisplayFeatures : 1; // Features below don't actually depend on control ROM version, which is used to identify hardware model unsigned int defaultReverbMT32Compatible : 1; @@ -221,6 +224,8 @@ struct ControlROMMap { Bit16u timbreMaxTable; // 72 bytes Bit16u soundGroupsTable; // 14 bytes each entry Bit16u soundGroupsCount; + Bit16u startupMessage; // 20 characters + NULL terminator + Bit16u sysexErrorMessage; // 20 characters + NULL terminator }; struct ControlROMPCMStruct { diff --git a/src/sound/munt/Synth.cpp b/src/sound/munt/Synth.cpp index d61ad44a6..0b81edb93 100644 --- a/src/sound/munt/Synth.cpp +++ b/src/sound/munt/Synth.cpp @@ -1,5 +1,5 @@ /* Copyright (C) 2003, 2004, 2005, 2006, 2008, 2009 Dean Beeler, Jerome Fisher - * Copyright (C) 2011-2020 Dean Beeler, Jerome Fisher, Sergey V. Mikayev + * Copyright (C) 2011-2022 Dean Beeler, Jerome Fisher, Sergey V. Mikayev * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by @@ -22,6 +22,7 @@ #include "Synth.h" #include "Analog.h" #include "BReverbModel.h" +#include "Display.h" #include "File.h" #include "MemoryRegion.h" #include "MidiEventQueue.h" @@ -41,19 +42,35 @@ namespace MT32Emu { // MIDI interface data transfer rate in samples. Used to simulate the transfer delay. static const double MIDI_DATA_TRANSFER_RATE = double(SAMPLE_RATE) / 31250.0 * 8.0; -// FIXME: there should be more specific feature sets for various MT-32 control ROM versions -static const ControlROMFeatureSet OLD_MT32_COMPATIBLE = { - true, // quirkBasePitchOverflow - true, // quirkPitchEnvelopeOverflow - true, // quirkRingModulationNoMix - true, // quirkTVAZeroEnvLevels - true, // quirkPanMult - true, // quirkKeyShift - true, // quirkTVFBaseCutoffLimit - true, // defaultReverbMT32Compatible - true // oldMT32AnalogLPF +static const ControlROMFeatureSet OLD_MT32_ELDER = { + true, // quirkBasePitchOverflow + true, // quirkPitchEnvelopeOverflow + true, // quirkRingModulationNoMix + true, // quirkTVAZeroEnvLevels + true, // quirkPanMult + true, // quirkKeyShift + true, // quirkTVFBaseCutoffLimit + false, // quirkFastPitchChanges + true, // quirkDisplayCustomMessagePriority + true, // oldMT32DisplayFeatures + true, // defaultReverbMT32Compatible + true // oldMT32AnalogLPF }; -static const ControlROMFeatureSet CM32L_COMPATIBLE = { +static const ControlROMFeatureSet OLD_MT32_LATER = { + true, // quirkBasePitchOverflow + true, // quirkPitchEnvelopeOverflow + true, // quirkRingModulationNoMix + true, // quirkTVAZeroEnvLevels + true, // quirkPanMult + true, // quirkKeyShift + true, // quirkTVFBaseCutoffLimit + false, // quirkFastPitchChanges + false, // quirkDisplayCustomMessagePriority + true, // oldMT32DisplayFeatures + true, // defaultReverbMT32Compatible + true // oldMT32AnalogLPF +}; +static const ControlROMFeatureSet NEW_MT32_COMPATIBLE = { false, // quirkBasePitchOverflow false, // quirkPitchEnvelopeOverflow false, // quirkRingModulationNoMix @@ -61,20 +78,41 @@ static const ControlROMFeatureSet CM32L_COMPATIBLE = { false, // quirkPanMult false, // quirkKeyShift false, // quirkTVFBaseCutoffLimit + false, // quirkFastPitchChanges + false, // quirkDisplayCustomMessagePriority + false, // oldMT32DisplayFeatures false, // defaultReverbMT32Compatible - false // oldMT32AnalogLPF + false // oldMT32AnalogLPF +}; +static const ControlROMFeatureSet CM32LN_COMPATIBLE = { + false, // quirkBasePitchOverflow + false, // quirkPitchEnvelopeOverflow + false, // quirkRingModulationNoMix + false, // quirkTVAZeroEnvLevels + false, // quirkPanMult + false, // quirkKeyShift + false, // quirkTVFBaseCutoffLimit + true, // quirkFastPitchChanges + false, // quirkDisplayCustomMessagePriority + false, // oldMT32DisplayFeatures + false, // defaultReverbMT32Compatible + false // oldMT32AnalogLPF }; -static const ControlROMMap ControlROMMaps[8] = { - // ID Features PCMmap PCMc tmbrA tmbrAO, tmbrAC tmbrB tmbrBO tmbrBC tmbrR trC rhythm rhyC rsrv panpot prog rhyMax patMax sysMax timMax sndGrp sGC - { "ctrl_mt32_1_04", OLD_MT32_COMPATIBLE, 0x3000, 128, 0x8000, 0x0000, false, 0xC000, 0x4000, false, 0x3200, 30, 0x73A6, 85, 0x57C7, 0x57E2, 0x57D0, 0x5252, 0x525E, 0x526E, 0x520A, 0x7064, 19 }, - { "ctrl_mt32_1_05", OLD_MT32_COMPATIBLE, 0x3000, 128, 0x8000, 0x0000, false, 0xC000, 0x4000, false, 0x3200, 30, 0x7414, 85, 0x57C7, 0x57E2, 0x57D0, 0x5252, 0x525E, 0x526E, 0x520A, 0x70CA, 19 }, - { "ctrl_mt32_1_06", OLD_MT32_COMPATIBLE, 0x3000, 128, 0x8000, 0x0000, false, 0xC000, 0x4000, false, 0x3200, 30, 0x7414, 85, 0x57D9, 0x57F4, 0x57E2, 0x5264, 0x5270, 0x5280, 0x521C, 0x70CA, 19 }, - { "ctrl_mt32_1_07", OLD_MT32_COMPATIBLE, 0x3000, 128, 0x8000, 0x0000, false, 0xC000, 0x4000, false, 0x3200, 30, 0x73fe, 85, 0x57B1, 0x57CC, 0x57BA, 0x523C, 0x5248, 0x5258, 0x51F4, 0x70B0, 19 }, // MT-32 revision 1 - {"ctrl_mt32_bluer", OLD_MT32_COMPATIBLE, 0x3000, 128, 0x8000, 0x0000, false, 0xC000, 0x4000, false, 0x3200, 30, 0x741C, 85, 0x57E5, 0x5800, 0x57EE, 0x5270, 0x527C, 0x528C, 0x5228, 0x70CE, 19 }, // MT-32 Blue Ridge mod - {"ctrl_mt32_2_04", CM32L_COMPATIBLE, 0x8100, 128, 0x8000, 0x8000, true, 0x8080, 0x8000, true, 0x8500, 30, 0x8580, 85, 0x4F5D, 0x4F78, 0x4F66, 0x4899, 0x489D, 0x48B6, 0x48CD, 0x5A58, 19 }, - {"ctrl_cm32l_1_00", CM32L_COMPATIBLE, 0x8100, 256, 0x8000, 0x8000, true, 0x8080, 0x8000, true, 0x8500, 64, 0x8580, 85, 0x4F65, 0x4F80, 0x4F6E, 0x48A1, 0x48A5, 0x48BE, 0x48D5, 0x5A6C, 19 }, - {"ctrl_cm32l_1_02", CM32L_COMPATIBLE, 0x8100, 256, 0x8000, 0x8000, true, 0x8080, 0x8000, true, 0x8500, 64, 0x8580, 85, 0x4F93, 0x4FAE, 0x4F9C, 0x48CB, 0x48CF, 0x48E8, 0x48FF, 0x5A96, 19 } // CM-32L +static const ControlROMMap ControlROMMaps[] = { + // ID Features PCMmap PCMc tmbrA tmbrAO, tmbrAC tmbrB tmbrBO tmbrBC tmbrR trC rhythm rhyC rsrv panpot prog rhyMax patMax sysMax timMax sndGrp sGC stMsg sErMsg + {"ctrl_mt32_1_04", OLD_MT32_ELDER, 0x3000, 128, 0x8000, 0x0000, false, 0xC000, 0x4000, false, 0x3200, 30, 0x73A6, 85, 0x57C7, 0x57E2, 0x57D0, 0x5252, 0x525E, 0x526E, 0x520A, 0x7064, 19, 0x217A, 0x4BB6}, + {"ctrl_mt32_1_05", OLD_MT32_ELDER, 0x3000, 128, 0x8000, 0x0000, false, 0xC000, 0x4000, false, 0x3200, 30, 0x7414, 85, 0x57C7, 0x57E2, 0x57D0, 0x5252, 0x525E, 0x526E, 0x520A, 0x70CA, 19, 0x217A, 0x4BB6}, + {"ctrl_mt32_1_06", OLD_MT32_LATER, 0x3000, 128, 0x8000, 0x0000, false, 0xC000, 0x4000, false, 0x3200, 30, 0x7414, 85, 0x57D9, 0x57F4, 0x57E2, 0x5264, 0x5270, 0x5280, 0x521C, 0x70CA, 19, 0x217A, 0x4BBA}, + {"ctrl_mt32_1_07", OLD_MT32_LATER, 0x3000, 128, 0x8000, 0x0000, false, 0xC000, 0x4000, false, 0x3200, 30, 0x73fe, 85, 0x57B1, 0x57CC, 0x57BA, 0x523C, 0x5248, 0x5258, 0x51F4, 0x70B0, 19, 0x217A, 0x4B92}, + {"ctrl_mt32_bluer", OLD_MT32_LATER, 0x3000, 128, 0x8000, 0x0000, false, 0xC000, 0x4000, false, 0x3200, 30, 0x741C, 85, 0x57E5, 0x5800, 0x57EE, 0x5270, 0x527C, 0x528C, 0x5228, 0x70CE, 19, 0x217A, 0x4BC6}, + {"ctrl_mt32_2_03", NEW_MT32_COMPATIBLE, 0x8100, 128, 0x8000, 0x8000, true, 0x8080, 0x8000, true, 0x8500, 64, 0x8580, 85, 0x4F49, 0x4F64, 0x4F52, 0x4885, 0x4889, 0x48A2, 0x48B9, 0x5A44, 19, 0x1EF0, 0x4066}, + {"ctrl_mt32_2_04", NEW_MT32_COMPATIBLE, 0x8100, 128, 0x8000, 0x8000, true, 0x8080, 0x8000, true, 0x8500, 64, 0x8580, 85, 0x4F5D, 0x4F78, 0x4F66, 0x4899, 0x489D, 0x48B6, 0x48CD, 0x5A58, 19, 0x1EF0, 0x406D}, + {"ctrl_mt32_2_06", NEW_MT32_COMPATIBLE, 0x8100, 128, 0x8000, 0x8000, true, 0x8080, 0x8000, true, 0x8500, 64, 0x8580, 85, 0x4F69, 0x4F84, 0x4F72, 0x48A5, 0x48A9, 0x48C2, 0x48D9, 0x5A64, 19, 0x1EF0, 0x4021}, + {"ctrl_mt32_2_07", NEW_MT32_COMPATIBLE, 0x8100, 128, 0x8000, 0x8000, true, 0x8080, 0x8000, true, 0x8500, 64, 0x8580, 85, 0x4F81, 0x4F9C, 0x4F8A, 0x48B9, 0x48BD, 0x48D6, 0x48ED, 0x5A78, 19, 0x1EE7, 0x4035}, + {"ctrl_cm32l_1_00", NEW_MT32_COMPATIBLE, 0x8100, 256, 0x8000, 0x8000, true, 0x8080, 0x8000, true, 0x8500, 64, 0x8580, 85, 0x4F65, 0x4F80, 0x4F6E, 0x48A1, 0x48A5, 0x48BE, 0x48D5, 0x5A6C, 19, 0x1EF0, 0x401D}, + {"ctrl_cm32l_1_02", NEW_MT32_COMPATIBLE, 0x8100, 256, 0x8000, 0x8000, true, 0x8080, 0x8000, true, 0x8500, 64, 0x8580, 85, 0x4F93, 0x4FAE, 0x4F9C, 0x48CB, 0x48CF, 0x48E8, 0x48FF, 0x5A96, 19, 0x1EE7, 0x4047}, + {"ctrl_cm32ln_1_00", CM32LN_COMPATIBLE, 0x8100, 256, 0x8000, 0x8000, true, 0x8080, 0x8000, true, 0x8500, 64, 0x8580, 85, 0x4EC7, 0x4EE2, 0x4ED0, 0x47FF, 0x4803, 0x481C, 0x4833, 0x55A2, 19, 0x1F59, 0x3F7C} // (Note that old MT-32 ROMs actually have 86 entries for rhythmTemp) }; @@ -138,6 +176,8 @@ protected: synth.renderedSampleCount += count; } + void updateDisplayState(); + public: Renderer(Synth &useSynth) : synth(useSynth) {} @@ -209,10 +249,16 @@ public: Bit32u midiEventQueueSize; Bit32u midiEventQueueSysexStorageBufferSize; + + Display *display; + bool oldMT32DisplayFeatures; + + ReportHandler2 defaultReportHandler; + ReportHandler2 *reportHandler2; }; Bit32u Synth::getLibraryVersionInt() { - return (MT32EMU_VERSION_MAJOR << 16) | (MT32EMU_VERSION_MINOR << 8) | (MT32EMU_VERSION_PATCH); + return MT32EMU_CURRENT_VERSION_INT; } const char *Synth::getLibraryVersionString() { @@ -244,13 +290,8 @@ Synth::Synth(ReportHandler *useReportHandler) : controlROMMap = NULL; controlROMFeatures = NULL; - if (useReportHandler == NULL) { - reportHandler = new ReportHandler; - isDefaultReportHandler = true; - } else { - reportHandler = useReportHandler; - isDefaultReportHandler = false; - } + reportHandler = useReportHandler != NULL ? useReportHandler : &extensions.defaultReportHandler; + extensions.reportHandler2 = &extensions.defaultReportHandler; extensions.preallocatedReverbMemory = false; for (int i = REVERB_MODE_ROOM; i <= REVERB_MODE_TAP_DELAY; i++) { @@ -289,18 +330,27 @@ Synth::Synth(ReportHandler *useReportHandler) : lastReceivedMIDIEventTimestamp = 0; memset(parts, 0, sizeof(parts)); renderedSampleCount = 0; + extensions.display = NULL; + extensions.oldMT32DisplayFeatures = false; } Synth::~Synth() { close(); // Make sure we're closed and everything is freed - if (isDefaultReportHandler) { - delete reportHandler; - } delete &mt32ram; delete &mt32default; delete &extensions; } +void Synth::setReportHandler2(ReportHandler2 *reportHandler2) { + if (reportHandler2 != NULL) { + reportHandler = reportHandler2; + extensions.reportHandler2 = reportHandler2; + } else { + reportHandler = &extensions.defaultReportHandler; + extensions.reportHandler2 = &extensions.defaultReportHandler; + } +} + void ReportHandler::showLCDMessage(const char *data) { printf("WRITE-LCD: %s\n", data); } @@ -310,26 +360,38 @@ void ReportHandler::printDebug(const char *fmt, va_list list) { printf("\n"); } -void Synth::newTimbreSet(Bit8u partNum, Bit8u timbreGroup, Bit8u timbreNumber, const char patchName[]) { - const char *soundGroupName; +void Synth::rhythmNotePlayed() const { + extensions.display->rhythmNotePlayed(); +} + +void Synth::voicePartStateChanged(Bit8u partNum, bool partActivated) const { + extensions.display->voicePartStateChanged(partNum, partActivated); +} + +void Synth::newTimbreSet(Bit8u partNum) const { + const Part *part = getPart(partNum); + reportHandler->onProgramChanged(partNum, getSoundGroupName(part), part->getCurrentInstr()); +} + +const char *Synth::getSoundGroupName(const Part *part) const { + const PatchParam &patch = part->getPatchTemp()->patch; + return getSoundGroupName(patch.timbreGroup, patch.timbreNum); +} + +const char *Synth::getSoundGroupName(Bit8u timbreGroup, Bit8u timbreNumber) const { switch (timbreGroup) { case 1: timbreNumber += 64; // Fall-through case 0: - soundGroupName = soundGroupNames[soundGroupIx[timbreNumber]]; - break; + return soundGroupNames[soundGroupIx[timbreNumber]]; case 2: - soundGroupName = soundGroupNames[controlROMMap->soundGroupsCount - 2]; - break; + return soundGroupNames[controlROMMap->soundGroupsCount - 2]; case 3: - soundGroupName = soundGroupNames[controlROMMap->soundGroupsCount - 1]; - break; + return soundGroupNames[controlROMMap->soundGroupsCount - 1]; default: - soundGroupName = NULL; - break; + return NULL; } - reportHandler->onProgramChanged(partNum, soundGroupName, patchName); } #define MT32EMU_PRINT_DEBUG \ @@ -450,6 +512,16 @@ float Synth::getReverbOutputGain() const { return reverbOutputGain; } +void Synth::setPartVolumeOverride(Bit8u partNumber, Bit8u volumeOverride) { + if (opened && partNumber < 9) { + parts[partNumber]->setVolumeOverride(volumeOverride); + } +} + +Bit8u Synth::getPartVolumeOverride(Bit8u partNumber) const { + return (!opened || partNumber > 8) ? 255 : parts[partNumber]->getVolumeOverride(); +} + void Synth::setReversedStereoEnabled(bool enabled) { reversedStereoEnabled = enabled; } @@ -542,7 +614,7 @@ bool Synth::loadPCMROM(const ROMImage &pcmROMImage) { int order[16] = {0, 9, 1, 2, 3, 4, 5, 6, 7, 10, 11, 12, 13, 14, 15, 8}; Bit16s log = 0; - for (int u = 0; u < 15; u++) { + for (int u = 0; u < 16; u++) { int bit; if (order[u] < 8) { bit = (s >> (7 - order[u])) & 0x1; @@ -717,6 +789,16 @@ bool Synth::open(const ROMImage &controlROMImage, const ROMImage &pcmROMImage, B return false; } + if (controlROMMap->timbreRCount == 30) { + // We must initialise all 64 rhythm timbres to avoid undefined behaviour. + // SEMI-CONFIRMED: Old-gen MT-32 units likely map timbres 30..59 to 0..29. + // Attempts to play rhythm timbres 60..63 exhibit undefined behaviour. + // We want to emulate the wrap around, so merely copy the entire set of standard + // timbres once more. The last 4 dangerous timbres are zeroed out. + memcpy(&mt32ram.timbres[222], &mt32ram.timbres[192], sizeof(*mt32ram.timbres) * 30); + memset(&mt32ram.timbres[252], 0, sizeof(*mt32ram.timbres) * 4); + } + #if MT32EMU_MONITOR_INIT printDebug("Initialising Timbre Bank M"); #endif @@ -838,6 +920,9 @@ bool Synth::open(const ROMImage &controlROMImage, const ROMImage &pcmROMImage, B return false; } + extensions.display = new Display(*this); + extensions.oldMT32DisplayFeatures = controlROMFeatures->oldMT32DisplayFeatures; + opened = true; activated = false; @@ -850,6 +935,9 @@ bool Synth::open(const ROMImage &controlROMImage, const ROMImage &pcmROMImage, B void Synth::dispose() { opened = false; + delete extensions.display; + extensions.display = NULL; + delete midiQueue; midiQueue = NULL; @@ -1064,7 +1152,7 @@ void Synth::playMsgOnPart(Bit8u part, Bit8u code, Bit8u note, Bit8u velocity) { if (velocity == 0) { // MIDI defines note-on with velocity 0 as being the same as note-off with velocity 40 parts[part]->noteOff(note); - } else { + } else if (parts[part]->getVolumeOverride() > 0) { parts[part]->noteOn(note, velocity); } break; @@ -1130,16 +1218,21 @@ void Synth::playMsgOnPart(Bit8u part, Bit8u code, Bit8u note, Bit8u velocity) { #endif return; } - + extensions.display->midiMessagePlayed(); break; case 0xC: // Program change //printDebug("Program change %01x", note); parts[part]->setProgram(note); + if (part < 8) { + extensions.display->midiMessagePlayed(); + extensions.display->programChanged(part); + } break; case 0xE: // Pitch bender bend = (velocity << 7) | (note); //printDebug("Pitch bender %02x", bend); parts[part]->setBend(bend); + extensions.display->midiMessagePlayed(); break; default: #if MT32EMU_MONITOR_MIDI > 0 @@ -1197,12 +1290,19 @@ void Synth::playSysexWithoutHeader(Bit8u device, Bit8u command, const Bit8u *sys printDebug("playSysexWithoutHeader: Message is not intended for this device ID (provided: %02x, expected: 0x10 or channel)", int(device)); return; } - // This is checked early in the real devices (before any sysex length checks or further processing) - // FIXME: Response to SYSEX_CMD_DAT reset with partials active (and in general) is untested. - if ((command == SYSEX_CMD_DT1 || command == SYSEX_CMD_DAT) && sysex[0] == 0x7F) { - reset(); + + // All models process the checksum before anything else and ignore messages lacking the checksum, or containing the checksum only. + if (len < 2) { + printDebug("playSysexWithoutHeader: Message is too short (%d bytes)!", len); return; } + Bit8u checksum = calcSysexChecksum(sysex, len - 1); + if (checksum != sysex[len - 1]) { + printDebug("playSysexWithoutHeader: Message checksum is incorrect (provided: %02x, expected: %02x)!", sysex[len - 1], checksum); + if (opened) extensions.display->checksumErrorOccurred(); + return; + } + len -= 1; // Exclude checksum if (command == SYSEX_CMD_EOD) { #if MT32EMU_MONITOR_SYSEX > 0 @@ -1210,16 +1310,6 @@ void Synth::playSysexWithoutHeader(Bit8u device, Bit8u command, const Bit8u *sys #endif return; } - if (len < 4) { - printDebug("playSysexWithoutHeader: Message is too short (%d bytes)!", len); - return; - } - Bit8u checksum = calcSysexChecksum(sysex, len - 1); - if (checksum != sysex[len - 1]) { - printDebug("playSysexWithoutHeader: Message checksum is incorrect (provided: %02x, expected: %02x)!", sysex[len - 1], checksum); - return; - } - len -= 1; // Exclude checksum switch (command) { case SYSEX_CMD_WSD: #if MT32EMU_MONITOR_SYSEX > 0 @@ -1259,12 +1349,34 @@ void Synth::readSysex(Bit8u /*device*/, const Bit8u * /*sysex*/, Bit32u /*len*/) } void Synth::writeSysex(Bit8u device, const Bit8u *sysex, Bit32u len) { - if (!opened) return; + if (!opened || len < 1) return; + + // This is checked early in the real devices (before any sysex length checks or further processing) + if (sysex[0] == 0x7F) { + if (!isDisplayOldMT32Compatible()) extensions.display->midiMessagePlayed(); + reset(); + return; + } + + extensions.display->midiMessagePlayed(); reportHandler->onMIDIMessagePlayed(); + + if (len < 3) { + // A short message of just 1 or 2 bytes may be written to the display area yet it may cause a user-visible effect, + // similarly to the reset area. + if (sysex[0] == 0x20) { + extensions.display->displayControlMessageReceived(sysex, len); + return; + } + printDebug("writeSysex: Message is too short (%d bytes)!", len); + return; + } + Bit32u addr = (sysex[0] << 16) | (sysex[1] << 8) | (sysex[2]); addr = MT32EMU_MEMADDR(addr); sysex += 3; len -= 3; + //printDebug("Sysex addr: 0x%06x", MT32EMU_SYSEXMEMADDR(addr)); // NOTE: Please keep both lower and upper bounds in each check, for ease of reading @@ -1345,6 +1457,7 @@ void Synth::writeSysexGlobal(Bit32u addr, const Bit8u *sysex, Bit32u len) { if (region == NULL) { printDebug("Sysex write to unrecognised address %06x, len %d", MT32EMU_SYSEXMEMADDR(addr), len); + // FIXME: Real devices may respond differently to a long SysEx that covers adjacent regions. break; } writeMemoryRegion(region, addr, region->getClampedLen(addr, len), sysex); @@ -1663,7 +1776,10 @@ void Synth::writeMemoryRegion(const MemoryRegion *region, Bit32u addr, Bit32u le } break; case MR_Display: - char buf[SYSEX_BUFFER_SIZE]; + if (len > Display::LCD_TEXT_SIZE) len = Display::LCD_TEXT_SIZE; + if (!extensions.display->customDisplayMessageReceived(data, off, len)) break; + // Holds zero-terminated string of the maximum length. + char buf[Display::LCD_TEXT_SIZE + 1]; memcpy(&buf, &data[0], len); buf[len] = 0; #if MT32EMU_MONITOR_SYSEX > 0 @@ -1674,6 +1790,8 @@ void Synth::writeMemoryRegion(const MemoryRegion *region, Bit32u addr, Bit32u le case MR_Reset: reset(); break; + default: + break; } } @@ -1767,6 +1885,10 @@ void Synth::refreshSystemChanAssign(Bit8u firstPart, Bit8u lastPart) { } void Synth::refreshSystemMasterVol() { + // Note, this should only occur when the user turns the volume knob. When the master volume is set via a SysEx, display + // doesn't actually update on all real devices. However, we anyway update the display, as we don't foresee a dedicated + // API for setting the master volume yet it's rather dubious that one really needs this quirk to be fairly emulated. + if (opened) extensions.display->masterVolumeChanged(); #if MT32EMU_MONITOR_SYSEX > 0 printDebug(" Master volume: %d", mt32ram.system.masterVol); #endif @@ -1816,6 +1938,32 @@ Bit32s Synth::getMasterTunePitchDelta() const { return extensions.masterTunePitchDelta; } +bool Synth::getDisplayState(char *targetBuffer, bool narrowLCD) const { + if (!opened) { + memset(targetBuffer, ' ', Display::LCD_TEXT_SIZE); + targetBuffer[Display::LCD_TEXT_SIZE] = 0; + return false; + } + return extensions.display->getDisplayState(targetBuffer, narrowLCD); +} + +void Synth::setMainDisplayMode() { + if (opened) extensions.display->setMainDisplayMode(); +} + + +void Synth::setDisplayCompatibility(bool oldMT32CompatibilityEnabled) { + extensions.oldMT32DisplayFeatures = oldMT32CompatibilityEnabled; +} + +bool Synth::isDisplayOldMT32Compatible() const { + return extensions.oldMT32DisplayFeatures; +} + +bool Synth::isDefaultDisplayOldMT32Compatible() const { + return opened && controlROMFeatures->oldMT32DisplayFeatures; +} + /** Defines an interface of a class that maintains storage of variable-sized data of SysEx messages. */ class MidiEventQueue::SysexDataStorage { public: @@ -1994,6 +2142,15 @@ Bit32u Synth::getStereoOutputSampleRate() const { return (analog == NULL) ? SAMPLE_RATE : analog->getOutputSampleRate(); } +void Renderer::updateDisplayState() { + bool midiMessageLEDState; + bool midiMessageLEDStateUpdated; + bool lcdUpdated; + synth.extensions.display->checkDisplayStateUpdated(midiMessageLEDState, midiMessageLEDStateUpdated, lcdUpdated); + if (midiMessageLEDStateUpdated) synth.extensions.reportHandler2->onMidiMessageLEDStateUpdated(midiMessageLEDState); + if (lcdUpdated) synth.extensions.reportHandler2->onLCDStateUpdated(); +} + template void RendererImpl::doRender(Sample *stereoStream, Bit32u len) { if (!isActivated()) { @@ -2002,6 +2159,7 @@ void RendererImpl::doRender(Sample *stereoStream, Bit32u len) { printDebug("RendererImpl: Invalid call to Analog::process()!\n"); } Synth::muteSampleBuffer(stereoStream, len << 1); + updateDisplayState(); return; } @@ -2358,6 +2516,7 @@ void RendererImpl::produceStreams(const DACOutputStreams &stream getPartialManager().clearAlreadyOutputed(); incRenderedSampleCount(len); + updateDisplayState(); } void Synth::printPartialUsage(Bit32u sampleOffset) { @@ -2468,6 +2627,26 @@ const char *Synth::getPatchName(Bit8u partNumber) const { return (!opened || partNumber > 8) ? NULL : parts[partNumber]->getCurrentInstr(); } +bool Synth::getSoundGroupName(char *soundGroupName, Bit8u timbreGroup, Bit8u timbreNumber) const { + if (!opened || 63 < timbreNumber) return false; + const char *foundGroupName = getSoundGroupName(timbreGroup, timbreNumber); + if (foundGroupName == NULL) return false; + memcpy(soundGroupName, foundGroupName, 7); + soundGroupName[7] = 0; + return true; +} + +bool Synth::getSoundName(char *soundName, Bit8u timbreGroup, Bit8u timbreNumber) const { + if (!opened || 3 < timbreGroup) return false; + Bit8u timbresInGroup = 3 == timbreGroup ? controlROMMap->timbreRCount : 64; + if (timbresInGroup <= timbreNumber) return false; + TimbreParam::CommonParam &timbreCommon = mt32ram.timbres[timbreGroup * 64 + timbreNumber].timbre.common; + if (timbreCommon.partialMute == 0) return false; + memcpy(soundName, timbreCommon.name, sizeof timbreCommon.name); + soundName[sizeof timbreCommon.name] = 0; + return true; +} + const Part *Synth::getPart(Bit8u partNum) const { if (partNum > 8) { return NULL; diff --git a/src/sound/munt/Synth.h b/src/sound/munt/Synth.h index 65f2656e6..0f88eb9f0 100644 --- a/src/sound/munt/Synth.h +++ b/src/sound/munt/Synth.h @@ -1,5 +1,5 @@ /* Copyright (C) 2003, 2004, 2005, 2006, 2008, 2009 Dean Beeler, Jerome Fisher - * Copyright (C) 2011-2020 Dean Beeler, Jerome Fisher, Sergey V. Mikayev + * Copyright (C) 2011-2022 Dean Beeler, Jerome Fisher, Sergey V. Mikayev * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by @@ -69,6 +69,9 @@ const Bit8u SYSEX_CMD_EOD = 0x45; // End of data const Bit8u SYSEX_CMD_ERR = 0x4E; // Communications error const Bit8u SYSEX_CMD_RJC = 0x4F; // Rejection +// This value isn't quite correct: the new-gen MT-32 control ROMs (ver. 2.XX) are twice as big. +// Nevertheless, this is still relevant for library internal usage because the higher half +// of those ROMs only contains the demo songs in all cases. const Bit32u CONTROL_ROM_SIZE = 64 * 1024; // Set of multiplexed output streams appeared at the DAC entrance. @@ -113,8 +116,21 @@ public: virtual void onProgramChanged(Bit8u /* partNum */, const char * /* soundGroupName */, const char * /* patchName */) {} }; +// Extends ReportHandler, so that the client may supply callbacks for reporting signals about updated display state. +class MT32EMU_EXPORT_V(2.6) ReportHandler2 : public ReportHandler { +public: + virtual ~ReportHandler2() {} + + // Invoked to signal about a change of the emulated LCD state. Use method Synth::getDisplayState to retrieve the actual data. + // This callback will not be invoked on further changes, until the client retrieves the LCD state. + virtual void onLCDStateUpdated() {} + // Invoked when the emulated MIDI MESSAGE LED changes state. The ledState parameter represents whether the LED is ON. + virtual void onMidiMessageLEDStateUpdated(bool /* ledState */) {} +}; + class Synth { friend class DefaultMidiStreamParser; +friend class Display; friend class MemoryRegion; friend class Part; friend class Partial; @@ -177,7 +193,7 @@ private: bool opened; bool activated; - bool isDefaultReportHandler; + bool isDefaultReportHandler; // No longer used, retained for binary compatibility only. ReportHandler *reportHandler; PartialManager *partialManager; @@ -227,7 +243,11 @@ private: void printPartialUsage(Bit32u sampleOffset = 0); - void newTimbreSet(Bit8u partNum, Bit8u timbreGroup, Bit8u timbreNumber, const char patchName[]); + void rhythmNotePlayed() const; + void voicePartStateChanged(Bit8u partNum, bool activated) const; + void newTimbreSet(Bit8u partNum) const; + const char *getSoundGroupName(const Part *part) const; + const char *getSoundGroupName(Bit8u timbreGroup, Bit8u timbreNumber) const; void printDebug(const char *fmt, ...); // partNum should be 0..7 for Part 1..8, or 8 for Rhythm @@ -290,9 +310,13 @@ public: MT32EMU_EXPORT explicit Synth(ReportHandler *useReportHandler = NULL); MT32EMU_EXPORT ~Synth(); + // Sets an implementation of ReportHandler2 interface for reporting various errors, information and debug messages. + // If the argument is NULL, the default implementation is installed as a fallback. + MT32EMU_EXPORT_V(2.6) void setReportHandler2(ReportHandler2 *reportHandler2); + // Used to initialise the MT-32. Must be called before any other function. - // Returns true if initialization was sucessful, otherwise returns false. - // controlROMImage and pcmROMImage represent Control and PCM ROM images for use by synth. + // Returns true if initialization was successful, otherwise returns false. + // controlROMImage and pcmROMImage represent full Control and PCM ROM images for use by synth. // usePartialCount sets the maximum number of partials playing simultaneously for this session (optional). // analogOutputMode sets the mode for emulation of analogue circuitry of the hardware units (optional). MT32EMU_EXPORT bool open(const ROMImage &controlROMImage, const ROMImage &pcmROMImage, Bit32u usePartialCount = DEFAULT_MAX_PARTIALS, AnalogOutputMode analogOutputMode = AnalogOutputMode_COARSE); @@ -391,7 +415,7 @@ public: MT32EMU_EXPORT bool isMT32ReverbCompatibilityMode() const; // Returns whether default reverb compatibility mode is the old MT-32 compatibility mode. MT32EMU_EXPORT bool isDefaultReverbMT32Compatible() const; - // If enabled, reverb buffers for all modes are keept around allocated all the time to avoid memory + // If enabled, reverb buffers for all modes are kept around allocated all the time to avoid memory // allocating/freeing in the rendering thread, which may be required for realtime operation. // Otherwise, reverb buffers that are not in use are deleted to save memory (the default behaviour). MT32EMU_EXPORT void preallocateReverbMemory(bool enabled); @@ -423,6 +447,22 @@ public: // Returns current output gain factor for reverb wet output channels. MT32EMU_EXPORT float getReverbOutputGain() const; + // Sets (or removes) an override for the current volume (output level) on a specific part. + // When the part volume is overridden, the MIDI controller Volume (7) on the MIDI channel this part is assigned to + // has no effect on the output level of this part. Similarly, the output level value set on this part via a SysEx that + // modifies the Patch temp structure is disregarded. + // To enable the override mode, argument volumeOverride should be in range 0..100, setting a value outside this range + // disables the previously set override, if any. + // Note: Setting volumeOverride to 0 mutes the part completely, meaning no sound is generated at all. + // This is unlike the behaviour of real devices - setting 0 volume on a part may leave it still producing + // sound at a very low level. + // Argument partNumber should be 0..7 for Part 1..8, or 8 for Rhythm. + MT32EMU_EXPORT_V(2.6) void setPartVolumeOverride(Bit8u partNumber, Bit8u volumeOverride); + // Returns the overridden volume previously set on a specific part; a value outside the range 0..100 means no override + // is currently in effect. + // Argument partNumber should be 0..7 for Part 1..8, or 8 for Rhythm. + MT32EMU_EXPORT_V(2.6) Bit8u getPartVolumeOverride(Bit8u partNumber) const; + // Swaps left and right output channels. MT32EMU_EXPORT void setReversedStereoEnabled(bool enabled); // Returns whether left and right output channels are swapped. @@ -529,10 +569,53 @@ public: // Returns name of the patch set on the specified part. // Argument partNumber should be 0..7 for Part 1..8, or 8 for Rhythm. + // The returned value is a null-terminated string which is guaranteed to remain valid until the next call to one of render methods. MT32EMU_EXPORT const char *getPatchName(Bit8u partNumber) const; + // Retrieves the name of the sound group the timbre identified by arguments timbreGroup and timbreNumber is associated with. + // Values 0-3 of timbreGroup correspond to the timbre banks GROUP A, GROUP B, MEMORY and RHYTHM. + // For all but the RHYTHM timbre bank, allowed values of timbreNumber are in range 0-63. The number of timbres + // contained in the RHYTHM bank depends on the used control ROM version. + // The argument soundGroupName must point to an array of at least 8 characters. The result is a null-terminated string. + // Returns whether the specified timbre has been found and the result written in soundGroupName. + MT32EMU_EXPORT_V(2.7) bool getSoundGroupName(char *soundGroupName, Bit8u timbreGroup, Bit8u timbreNumber) const; + // Retrieves the name of the timbre identified by arguments timbreGroup and timbreNumber. + // Values 0-3 of timbreGroup correspond to the timbre banks GROUP A, GROUP B, MEMORY and RHYTHM. + // For all but the RHYTHM timbre bank, allowed values of timbreNumber are in range 0-63. The number of timbres + // contained in the RHYTHM bank depends on the used control ROM version. + // The argument soundName must point to an array of at least 11 characters. The result is a null-terminated string. + // Returns whether the specified timbre has been found and the result written in soundName. + MT32EMU_EXPORT_V(2.7) bool getSoundName(char *soundName, Bit8u timbreGroup, Bit8u timbreNumber) const; + // Stores internal state of emulated synth into an array provided (as it would be acquired from hardware). MT32EMU_EXPORT void readMemory(Bit32u addr, Bit32u len, Bit8u *data); + + // Retrieves the current state of the emulated MT-32 display facilities. + // Typically, the state is updated during the rendering. When that happens, a related callback from ReportHandler2 is invoked. + // However, there might be no need to invoke this method after each update, e.g. when the render buffer is just a few milliseconds + // long. + // The argument targetBuffer must point to an array of at least 21 characters. The result is a null-terminated string. + // The optional argument narrowLCD enables a condensed representation of the displayed information in some cases. This is mainly + // intended to route the result to a hardware LCD that is only 16 characters wide. Automatic scrolling of longer strings + // is not supported. + // Returns whether the MIDI MESSAGE LED is ON and fills the targetBuffer parameter. + MT32EMU_EXPORT_V(2.6) bool getDisplayState(char *targetBuffer, bool narrowLCD = false) const; + + // Resets the emulated LCD to the main mode (Master Volume). This has the same effect as pressing the Master Volume button + // while the display shows some other message. Useful for the new-gen devices as those require a special Display Reset SysEx + // to return to the main mode e.g. from showing a custom display message or a checksum error. + MT32EMU_EXPORT_V(2.6) void setMainDisplayMode(); + + // Permits to select an arbitrary display emulation model that does not necessarily match the actual behaviour implemented + // in the control ROM version being used. + // Invoking this method with the argument set to true forces emulation of the old-gen MT-32 display features. + // Otherwise, emulation of the new-gen devices is enforced (these include CM-32L and LAPC-I as if these were connected to an LCD). + MT32EMU_EXPORT_V(2.6) void setDisplayCompatibility(bool oldMT32CompatibilityEnabled); + // Returns whether the currently configured features of the emulated display are compatible with the old-gen MT-32 devices. + MT32EMU_EXPORT_V(2.6) bool isDisplayOldMT32Compatible() const; + // Returns whether the emulated display features configured by default depending on the actual control ROM version + // are compatible with the old-gen MT-32 devices. + MT32EMU_EXPORT_V(2.6) bool isDefaultDisplayOldMT32Compatible() const; }; // class Synth } // namespace MT32Emu diff --git a/src/sound/munt/TVA.cpp b/src/sound/munt/TVA.cpp index a49ad0193..e3f76181f 100644 --- a/src/sound/munt/TVA.cpp +++ b/src/sound/munt/TVA.cpp @@ -1,5 +1,5 @@ /* Copyright (C) 2003, 2004, 2005, 2006, 2008, 2009 Dean Beeler, Jerome Fisher - * Copyright (C) 2011-2020 Dean Beeler, Jerome Fisher, Sergey V. Mikayev + * Copyright (C) 2011-2022 Dean Beeler, Jerome Fisher, Sergey V. Mikayev * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by @@ -99,7 +99,7 @@ static int calcVeloAmpSubtraction(Bit8u veloSensitivity, unsigned int velocity) return absVelocityMult - (velocityMult >> 8); // PORTABILITY NOTE: Assumes arithmetic shift } -static int calcBasicAmp(const Tables *tables, const Partial *partial, const MemParams::System *system, const TimbreParam::PartialParam *partialParam, const MemParams::PatchTemp *patchTemp, const MemParams::RhythmTemp *rhythmTemp, int biasAmpSubtraction, int veloAmpSubtraction, Bit8u expression, bool hasRingModQuirk) { +static int calcBasicAmp(const Tables *tables, const Partial *partial, const MemParams::System *system, const TimbreParam::PartialParam *partialParam, Bit8u partVolume, const MemParams::RhythmTemp *rhythmTemp, int biasAmpSubtraction, int veloAmpSubtraction, Bit8u expression, bool hasRingModQuirk) { int amp = 155; if (!(hasRingModQuirk ? partial->isRingModulatingNoMix() : partial->isRingModulatingSlave())) { @@ -107,7 +107,7 @@ static int calcBasicAmp(const Tables *tables, const Partial *partial, const MemP if (amp < 0) { return 0; } - amp -= tables->levelToAmpSubtraction[patchTemp->outputLevel]; + amp -= tables->levelToAmpSubtraction[partVolume]; if (amp < 0) { return 0; } @@ -154,7 +154,6 @@ static int calcKeyTimeSubtraction(Bit8u envTimeKeyfollow, int key) { void TVA::reset(const Part *newPart, const TimbreParam::PartialParam *newPartialParam, const MemParams::RhythmTemp *newRhythmTemp) { part = newPart; partialParam = newPartialParam; - patchTemp = newPart->getPatchTemp(); rhythmTemp = newRhythmTemp; playing = true; @@ -169,7 +168,7 @@ void TVA::reset(const Part *newPart, const TimbreParam::PartialParam *newPartial biasAmpSubtraction = calcBiasAmpSubtractions(partialParam, key); veloAmpSubtraction = calcVeloAmpSubtraction(partialParam->tva.veloSensitivity, velocity); - int newTarget = calcBasicAmp(tables, partial, system, partialParam, patchTemp, newRhythmTemp, biasAmpSubtraction, veloAmpSubtraction, part->getExpression(), partial->getSynth()->controlROMFeatures->quirkRingModulationNoMix); + int newTarget = calcBasicAmp(tables, partial, system, partialParam, part->getVolume(), newRhythmTemp, biasAmpSubtraction, veloAmpSubtraction, part->getExpression(), partial->getSynth()->controlROMFeatures->quirkRingModulationNoMix); int newPhase; if (partialParam->tva.envTime[0] == 0) { // Initially go to the TVA_PHASE_ATTACK target amp, and spend the next phase going from there to the TVA_PHASE_2 target amp @@ -221,7 +220,7 @@ void TVA::recalcSustain() { } // We're sustaining. Recalculate all the values const Tables *tables = &Tables::getInstance(); - int newTarget = calcBasicAmp(tables, partial, system, partialParam, patchTemp, rhythmTemp, biasAmpSubtraction, veloAmpSubtraction, part->getExpression(), partial->getSynth()->controlROMFeatures->quirkRingModulationNoMix); + int newTarget = calcBasicAmp(tables, partial, system, partialParam, part->getVolume(), rhythmTemp, biasAmpSubtraction, veloAmpSubtraction, part->getExpression(), partial->getSynth()->controlROMFeatures->quirkRingModulationNoMix); newTarget += partialParam->tva.envLevel[3]; // Although we're in TVA_PHASE_SUSTAIN at this point, we cannot be sure that there is no active ramp at the moment. @@ -271,10 +270,10 @@ void TVA::nextPhase() { } bool allLevelsZeroFromNowOn = false; - if (!partial->getSynth()->controlROMFeatures->quirkTVAZeroEnvLevels && partialParam->tva.envLevel[3] == 0) { + if (partialParam->tva.envLevel[3] == 0) { if (newPhase == TVA_PHASE_4) { allLevelsZeroFromNowOn = true; - } else if (partialParam->tva.envLevel[2] == 0) { + } else if (!partial->getSynth()->controlROMFeatures->quirkTVAZeroEnvLevels && partialParam->tva.envLevel[2] == 0) { if (newPhase == TVA_PHASE_3) { allLevelsZeroFromNowOn = true; } else if (partialParam->tva.envLevel[1] == 0) { @@ -294,7 +293,7 @@ void TVA::nextPhase() { int envPointIndex = phase; if (!allLevelsZeroFromNowOn) { - newTarget = calcBasicAmp(tables, partial, system, partialParam, patchTemp, rhythmTemp, biasAmpSubtraction, veloAmpSubtraction, part->getExpression(), partial->getSynth()->controlROMFeatures->quirkRingModulationNoMix); + newTarget = calcBasicAmp(tables, partial, system, partialParam, part->getVolume(), rhythmTemp, biasAmpSubtraction, veloAmpSubtraction, part->getExpression(), partial->getSynth()->controlROMFeatures->quirkRingModulationNoMix); if (newPhase == TVA_PHASE_SUSTAIN || newPhase == TVA_PHASE_RELEASE) { if (partialParam->tva.envLevel[3] == 0) { diff --git a/src/sound/munt/TVA.h b/src/sound/munt/TVA.h index de6e61017..415909be8 100644 --- a/src/sound/munt/TVA.h +++ b/src/sound/munt/TVA.h @@ -1,5 +1,5 @@ /* Copyright (C) 2003, 2004, 2005, 2006, 2008, 2009 Dean Beeler, Jerome Fisher - * Copyright (C) 2011-2020 Dean Beeler, Jerome Fisher, Sergey V. Mikayev + * Copyright (C) 2011-2022 Dean Beeler, Jerome Fisher, Sergey V. Mikayev * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by @@ -67,7 +67,6 @@ private: const Part *part; const TimbreParam::PartialParam *partialParam; - const MemParams::PatchTemp *patchTemp; const MemParams::RhythmTemp *rhythmTemp; bool playing; diff --git a/src/sound/munt/TVF.cpp b/src/sound/munt/TVF.cpp index 3d5f26049..47ce0a936 100644 --- a/src/sound/munt/TVF.cpp +++ b/src/sound/munt/TVF.cpp @@ -1,5 +1,5 @@ /* Copyright (C) 2003, 2004, 2005, 2006, 2008, 2009 Dean Beeler, Jerome Fisher - * Copyright (C) 2011-2020 Dean Beeler, Jerome Fisher, Sergey V. Mikayev + * Copyright (C) 2011-2022 Dean Beeler, Jerome Fisher, Sergey V. Mikayev * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by @@ -206,6 +206,8 @@ void TVF::nextPhase() { } startRamp((levelMult * partialParam->tvf.envLevel[3]) >> 8, 0, newPhase); return; + default: + break; } int envPointIndex = phase; diff --git a/src/sound/munt/TVF.h b/src/sound/munt/TVF.h index 149b1d09b..1b766e8ed 100644 --- a/src/sound/munt/TVF.h +++ b/src/sound/munt/TVF.h @@ -1,5 +1,5 @@ /* Copyright (C) 2003, 2004, 2005, 2006, 2008, 2009 Dean Beeler, Jerome Fisher - * Copyright (C) 2011-2020 Dean Beeler, Jerome Fisher, Sergey V. Mikayev + * Copyright (C) 2011-2022 Dean Beeler, Jerome Fisher, Sergey V. Mikayev * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by diff --git a/src/sound/munt/TVP.cpp b/src/sound/munt/TVP.cpp index 3d5f492fd..9921f3a4d 100644 --- a/src/sound/munt/TVP.cpp +++ b/src/sound/munt/TVP.cpp @@ -1,5 +1,5 @@ /* Copyright (C) 2003, 2004, 2005, 2006, 2008, 2009 Dean Beeler, Jerome Fisher - * Copyright (C) 2011-2020 Dean Beeler, Jerome Fisher, Sergey V. Mikayev + * Copyright (C) 2011-2022 Dean Beeler, Jerome Fisher, Sergey V. Mikayev * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by @@ -54,13 +54,32 @@ static Bit16u keyToPitchTable[] = { // We want to do processing 4000 times per second. FIXME: This is pretty arbitrary. static const int NOMINAL_PROCESS_TIMER_PERIOD_SAMPLES = SAMPLE_RATE / 4000; -// The timer runs at 500kHz. This is how much to increment it after 8 samples passes. -// We multiply by 8 to get rid of the fraction and deal with just integers. -static const int PROCESS_TIMER_INCREMENT_x8 = 8 * 500000 / SAMPLE_RATE; +// In all hardware units we emulate, the main clock frequency of the MCU is 12MHz. +// However, the MCU used in the 3rd-gen sound modules (like CM-500 and LAPC-N) +// is significantly faster. Importantly, the software timer also works faster, +// yet this fact has been seemingly missed. To be more specific, the software timer +// ticks each 8 "state times", and 1 state time equals to 3 clock periods +// for 8095 and 8098 but 2 clock periods for 80C198. That is, on MT-32 and CM-32L, +// the software timer tick rate is 12,000,000 / 3 / 8 = 500kHz, but on the 3rd-gen +// devices it's 12,000,000 / 2 / 8 = 750kHz instead. + +// For 1st- and 2nd-gen devices, the timer ticks at 500kHz. This is how much to increment +// timeElapsed once 16 samples passes. We multiply by 16 to get rid of the fraction +// and deal with just integers. +static const int PROCESS_TIMER_TICKS_PER_SAMPLE_X16_1N2_GEN = (500000 << 4) / SAMPLE_RATE; +// For 3rd-gen devices, the timer ticks at 750kHz. This is how much to increment +// timeElapsed once 16 samples passes. We multiply by 16 to get rid of the fraction +// and deal with just integers. +static const int PROCESS_TIMER_TICKS_PER_SAMPLE_X16_3_GEN = (750000 << 4) / SAMPLE_RATE; TVP::TVP(const Partial *usePartial) : - partial(usePartial), system(&usePartial->getSynth()->mt32ram.system) { -} + partial(usePartial), + system(&usePartial->getSynth()->mt32ram.system), + processTimerTicksPerSampleX16( + partial->getSynth()->controlROMFeatures->quirkFastPitchChanges + ? PROCESS_TIMER_TICKS_PER_SAMPLE_X16_3_GEN + : PROCESS_TIMER_TICKS_PER_SAMPLE_X16_1N2_GEN) +{} static Bit16s keyToPitch(unsigned int key) { // We're using a table to do: return round_to_nearest_or_even((key - 60) * (4096.0 / 12.0)) @@ -270,7 +289,7 @@ void TVP::setupPitchChange(int targetPitchOffset, Bit8u changeDuration) { pitchOffsetDelta = -pitchOffsetDelta; } // We want to maximise the number of bits of the Bit16s "pitchOffsetChangePerBigTick" we use in order to get the best possible precision later - Bit32u absPitchOffsetDelta = pitchOffsetDelta << 16; + Bit32u absPitchOffsetDelta = (pitchOffsetDelta & 0xFFFF) << 16; Bit8u normalisationShifts = normalise(absPitchOffsetDelta); // FIXME: Double-check: normalisationShifts is usually between 0 and 15 here, unless the delta is 0, in which case it's 31 absPitchOffsetDelta = absPitchOffsetDelta >> 1; // Make room for the sign bit @@ -301,7 +320,7 @@ void TVP::startDecay() { Bit16u TVP::nextPitch() { // We emulate MCU software timer using these counter and processTimerIncrement variables. - // The value of nominalProcessTimerPeriod approximates the period in samples + // The value of NOMINAL_PROCESS_TIMER_PERIOD_SAMPLES approximates the period in samples // between subsequent firings of the timer that normally occur. // However, accurate emulation is quite complicated because the timer is not guaranteed to fire in time. // This makes pitch variations on real unit non-deterministic and dependent on various factors. @@ -309,7 +328,7 @@ Bit16u TVP::nextPitch() { timeElapsed = (timeElapsed + processTimerIncrement) & 0x00FFFFFF; // This roughly emulates pitch deviations observed on real units when playing a single partial that uses TVP/LFO. counter = NOMINAL_PROCESS_TIMER_PERIOD_SAMPLES + (rand() & 3); - processTimerIncrement = (PROCESS_TIMER_INCREMENT_x8 * counter) >> 3; + processTimerIncrement = (processTimerTicksPerSampleX16 * counter) >> 4; process(); } counter--; @@ -337,13 +356,16 @@ void TVP::process() { return; } // FIXME: Write explanation for this stuff + // NOTE: Value of shifts may happily exceed the maximum of 31 specified for the 8095 MCU. + // We assume the device performs a shift with the rightmost 5 bits of the counter regardless of argument size, + // since shift instructions of any size have the same maximum. int rightShifts = shifts; if (rightShifts > 13) { rightShifts -= 13; - negativeBigTicksRemaining = negativeBigTicksRemaining >> rightShifts; // PORTABILITY NOTE: Assumes arithmetic shift + negativeBigTicksRemaining = negativeBigTicksRemaining >> (rightShifts & 0x1F); // PORTABILITY NOTE: Assumes arithmetic shift rightShifts = 13; } - int newResult = (negativeBigTicksRemaining * pitchOffsetChangePerBigTick) >> rightShifts; // PORTABILITY NOTE: Assumes arithmetic shift + int newResult = (negativeBigTicksRemaining * pitchOffsetChangePerBigTick) >> (rightShifts & 0x1F); // PORTABILITY NOTE: Assumes arithmetic shift newResult += targetPitchOffsetWithoutLFO + lfoPitchOffset; currentPitchOffset = newResult; updatePitch(); diff --git a/src/sound/munt/TVP.h b/src/sound/munt/TVP.h index c3dc314b4..61bd2033e 100644 --- a/src/sound/munt/TVP.h +++ b/src/sound/munt/TVP.h @@ -1,5 +1,5 @@ /* Copyright (C) 2003, 2004, 2005, 2006, 2008, 2009 Dean Beeler, Jerome Fisher - * Copyright (C) 2011-2020 Dean Beeler, Jerome Fisher, Sergey V. Mikayev + * Copyright (C) 2011-2022 Dean Beeler, Jerome Fisher, Sergey V. Mikayev * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by @@ -36,6 +36,7 @@ private: const TimbreParam::PartialParam *partialParam; const MemParams::PatchTemp *patchTemp; + const int processTimerTicksPerSampleX16; int processTimerIncrement; int counter; Bit32u timeElapsed; diff --git a/src/sound/munt/Tables.cpp b/src/sound/munt/Tables.cpp index 7fee467e8..dff042d20 100644 --- a/src/sound/munt/Tables.cpp +++ b/src/sound/munt/Tables.cpp @@ -1,5 +1,5 @@ /* Copyright (C) 2003, 2004, 2005, 2006, 2008, 2009 Dean Beeler, Jerome Fisher - * Copyright (C) 2011-2020 Dean Beeler, Jerome Fisher, Sergey V. Mikayev + * Copyright (C) 2011-2022 Dean Beeler, Jerome Fisher, Sergey V. Mikayev * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by diff --git a/src/sound/munt/Tables.h b/src/sound/munt/Tables.h index 790ee17b9..2f9053215 100644 --- a/src/sound/munt/Tables.h +++ b/src/sound/munt/Tables.h @@ -1,5 +1,5 @@ /* Copyright (C) 2003, 2004, 2005, 2006, 2008, 2009 Dean Beeler, Jerome Fisher - * Copyright (C) 2011-2020 Dean Beeler, Jerome Fisher, Sergey V. Mikayev + * Copyright (C) 2011-2022 Dean Beeler, Jerome Fisher, Sergey V. Mikayev * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by diff --git a/src/sound/munt/Types.h b/src/sound/munt/Types.h index 17c33e568..12e454750 100644 --- a/src/sound/munt/Types.h +++ b/src/sound/munt/Types.h @@ -1,5 +1,5 @@ /* Copyright (C) 2003, 2004, 2005, 2006, 2008, 2009 Dean Beeler, Jerome Fisher - * Copyright (C) 2011-2020 Dean Beeler, Jerome Fisher, Sergey V. Mikayev + * Copyright (C) 2011-2022 Dean Beeler, Jerome Fisher, Sergey V. Mikayev * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by diff --git a/src/sound/munt/VersionTagging.cpp b/src/sound/munt/VersionTagging.cpp new file mode 100644 index 000000000..0a3388f3b --- /dev/null +++ b/src/sound/munt/VersionTagging.cpp @@ -0,0 +1,32 @@ +/* Copyright (C) 2003, 2004, 2005, 2006, 2008, 2009 Dean Beeler, Jerome Fisher + * Copyright (C) 2011-2022 Dean Beeler, Jerome Fisher, Sergey V. Mikayev + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 2.1 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this program. If not, see . + */ + +#include "globals.h" + +extern "C" { +// Here's a list of all tagged minor library versions through global (potentially versioned) symbols. +// An application that's been linked with an older library version will be able to find a matching tag, +// while for an application linked with a newer library version there will be no match. + +MT32EMU_EXPORT_V(2.5) extern const volatile char mt32emu_2_5 = 0; +MT32EMU_EXPORT_V(2.6) extern const volatile char mt32emu_2_6 = 0; +MT32EMU_EXPORT_V(2.7) extern const volatile char mt32emu_2_7 = 0; + +#if MT32EMU_VERSION_MAJOR > 2 || MT32EMU_VERSION_MINOR > 7 +#error "Missing version tag definition for current library version" +#endif +} diff --git a/src/sound/munt/VersionTagging.h b/src/sound/munt/VersionTagging.h new file mode 100644 index 000000000..df211f3c0 --- /dev/null +++ b/src/sound/munt/VersionTagging.h @@ -0,0 +1,60 @@ +/* Copyright (C) 2003, 2004, 2005, 2006, 2008, 2009 Dean Beeler, Jerome Fisher + * Copyright (C) 2011-2022 Dean Beeler, Jerome Fisher, Sergey V. Mikayev + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 2.1 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this program. If not, see . + */ + +#ifndef MT32EMU_VERSION_TAG_H +#define MT32EMU_VERSION_TAG_H + +#include "globals.h" + +/* This is intended to implement a simple check of a shared library version in runtime. Sadly, per-symbol versioning + * is unavailable on many platforms, and even where it is, it's still not too easy to maintain for a C++ library. + * Therefore, the goal here is just to ensure that the client application quickly bails out when attempted to run + * with an older version of shared library, as well as to produce a more readable error message indicating a version mismatch + * rather than a report about some missing symbols with unreadable mangled names. + * This is an optional feature, since it adds some minor burden to both the library and client applications code, + * albeit it is ought to work on platforms that do not implement symbol versioning. + */ + +#define MT32EMU_REALLY_BUILD_VERSION_TAG(major, minor) mt32emu_ ## major ## _ ## minor +/* This macro expansion step permits resolution the actual version numbers. */ +#define MT32EMU_BUILD_VERSION_TAG(major, minor) MT32EMU_REALLY_BUILD_VERSION_TAG(major, minor) +#define MT32EMU_VERSION_TAG MT32EMU_BUILD_VERSION_TAG(MT32EMU_VERSION_MAJOR, MT32EMU_VERSION_MINOR) + +#if defined(__cplusplus) + +extern "C" { +MT32EMU_EXPORT extern const volatile char MT32EMU_VERSION_TAG; +} +// This pulls the external reference in yet prevents it from being optimised out. +static const volatile char mt32emu_version_tag = MT32EMU_VERSION_TAG; + +#else + +static void mt32emu_refer_version_tag(void) { + MT32EMU_EXPORT extern const volatile char MT32EMU_VERSION_TAG; + (void)MT32EMU_VERSION_TAG; +} + +static void (*const volatile mt32emu_refer_version_tag_ref)(void) = mt32emu_refer_version_tag; + +#endif + +#undef MT32EMU_REALLY_BUILD_VERSION_TAG +#undef MT32EMU_BUILD_VERSION_TAG +#undef MT32EMU_VERSION_TAG + +#endif diff --git a/src/sound/munt/c_interface/c_interface.cpp b/src/sound/munt/c_interface/c_interface.cpp index 48eb2824a..4c7706be8 100644 --- a/src/sound/munt/c_interface/c_interface.cpp +++ b/src/sound/munt/c_interface/c_interface.cpp @@ -1,5 +1,5 @@ /* Copyright (C) 2003, 2004, 2005, 2006, 2008, 2009 Dean Beeler, Jerome Fisher - * Copyright (C) 2011-2020 Dean Beeler, Jerome Fisher, Sergey V. Mikayev + * Copyright (C) 2011-2022 Dean Beeler, Jerome Fisher, Sergey V. Mikayev * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by @@ -15,6 +15,8 @@ * along with this program. If not, see . */ +#include + #include "../globals.h" #include "../Types.h" #include "../File.h" @@ -37,11 +39,11 @@ struct SamplerateConversionState { SampleRateConverter *src; }; -static mt32emu_service_version getSynthVersionID(mt32emu_service_i) { +static mt32emu_service_version MT32EMU_C_CALL getSynthVersionID(mt32emu_service_i) { return MT32EMU_SERVICE_VERSION_CURRENT; } -static const mt32emu_service_i_v3 SERVICE_VTABLE = { +static const mt32emu_service_i_v6 SERVICE_VTABLE = { getSynthVersionID, mt32emu_get_supported_report_handler_version, mt32emu_get_supported_midi_receiver_version, @@ -118,13 +120,29 @@ static const mt32emu_service_i_v3 SERVICE_VTABLE = { mt32emu_set_nice_partial_mixing_enabled, mt32emu_is_nice_partial_mixing_enabled, mt32emu_preallocate_reverb_memory, - mt32emu_configure_midi_event_queue_sysex_storage + mt32emu_configure_midi_event_queue_sysex_storage, + mt32emu_get_machine_ids, + mt32emu_get_rom_ids, + mt32emu_identify_rom_data, + mt32emu_identify_rom_file, + mt32emu_merge_and_add_rom_data, + mt32emu_merge_and_add_rom_files, + mt32emu_add_machine_rom_file, + mt32emu_get_display_state, + mt32emu_set_main_display_mode, + mt32emu_set_display_compatibility, + mt32emu_is_display_old_mt32_compatible, + mt32emu_is_default_display_old_mt32_compatible, + mt32emu_set_part_volume_override, + mt32emu_get_part_volume_override, + mt32emu_get_sound_group_name, + mt32emu_get_sound_name }; } // namespace MT32Emu struct mt32emu_data { - ReportHandler *reportHandler; + ReportHandler2 *reportHandler; Synth *synth; const ROMImage *controlROMImage; const ROMImage *pcmROMImage; @@ -138,16 +156,19 @@ struct mt32emu_data { namespace MT32Emu { -class DelegatingReportHandlerAdapter : public ReportHandler { +class DelegatingReportHandlerAdapter : public ReportHandler2 { public: DelegatingReportHandlerAdapter(mt32emu_report_handler_i useReportHandler, void *useInstanceData) : delegate(useReportHandler), instanceData(useInstanceData) {} -protected: +private: const mt32emu_report_handler_i delegate; void * const instanceData; -private: + bool isVersionLess(mt32emu_report_handler_version versionID) { + return delegate.v0->getVersionID(delegate) < versionID; + } + void printDebug(const char *fmt, va_list list) { if (delegate.v0->printDebug == NULL) { ReportHandler::printDebug(fmt, list); @@ -258,6 +279,22 @@ private: delegate.v0->onProgramChanged(instanceData, partNum, soundGroupName, patchName); } } + + void onLCDStateUpdated() { + if (isVersionLess(MT32EMU_REPORT_HANDLER_VERSION_1) || delegate.v1->onLCDStateUpdated == NULL) { + ReportHandler2::onLCDStateUpdated(); + } else { + delegate.v1->onLCDStateUpdated(instanceData); + } + } + + void onMidiMessageLEDStateUpdated(bool ledState) { + if (isVersionLess(MT32EMU_REPORT_HANDLER_VERSION_1) || delegate.v1->onMidiMessageLEDStateUpdated == NULL) { + ReportHandler2::onMidiMessageLEDStateUpdated(ledState); + } else { + delegate.v1->onMidiMessageLEDStateUpdated(instanceData, ledState ? MT32EMU_BOOL_TRUE : MT32EMU_BOOL_FALSE); + } + } }; class DelegatingMidiStreamParser : public DefaultMidiStreamParser { @@ -295,30 +332,130 @@ private: } }; -static mt32emu_return_code addROMFile(mt32emu_data *data, File *file) { - const ROMImage *image = ROMImage::makeROMImage(file); - const ROMInfo *info = image->getROMInfo(); - if (info == NULL) { - ROMImage::freeROMImage(image); +static void fillROMInfo(mt32emu_rom_info *rom_info, const ROMInfo *controlROMInfo, const ROMInfo *pcmROMInfo) { + if (controlROMInfo != NULL) { + rom_info->control_rom_id = controlROMInfo->shortName; + rom_info->control_rom_description = controlROMInfo->description; + rom_info->control_rom_sha1_digest = controlROMInfo->sha1Digest; + } else { + rom_info->control_rom_id = NULL; + rom_info->control_rom_description = NULL; + rom_info->control_rom_sha1_digest = NULL; + } + if (pcmROMInfo != NULL) { + rom_info->pcm_rom_id = pcmROMInfo->shortName; + rom_info->pcm_rom_description = pcmROMInfo->description; + rom_info->pcm_rom_sha1_digest = pcmROMInfo->sha1Digest; + } else { + rom_info->pcm_rom_id = NULL; + rom_info->pcm_rom_description = NULL; + rom_info->pcm_rom_sha1_digest = NULL; + } +} + +static const MachineConfiguration *findMachineConfiguration(const char *machine_id) { + Bit32u configurationCount; + const MachineConfiguration * const *configurations = MachineConfiguration::getAllMachineConfigurations(&configurationCount); + for (Bit32u i = 0; i < configurationCount; i++) { + if (!strcmp(configurations[i]->getMachineID(), machine_id)) return configurations[i]; + } + return NULL; +} + +static mt32emu_return_code identifyROM(mt32emu_rom_info *rom_info, File *romFile, const char *machineID) { + const ROMInfo *romInfo; + if (machineID == NULL) { + romInfo = ROMInfo::getROMInfo(romFile); + } else { + const MachineConfiguration *configuration = findMachineConfiguration(machineID); + if (configuration == NULL) { + fillROMInfo(rom_info, NULL, NULL); + return MT32EMU_RC_MACHINE_NOT_IDENTIFIED; + } + romInfo = ROMInfo::getROMInfo(romFile, configuration->getCompatibleROMInfos()); + } + if (romInfo == NULL) { + fillROMInfo(rom_info, NULL, NULL); return MT32EMU_RC_ROM_NOT_IDENTIFIED; } - if (info->type == ROMInfo::Control) { - if (data->controlROMImage != NULL) { - delete data->controlROMImage->getFile(); - ROMImage::freeROMImage(data->controlROMImage); - } - data->controlROMImage = image; - return MT32EMU_RC_ADDED_CONTROL_ROM; - } else if (info->type == ROMInfo::PCM) { - if (data->pcmROMImage != NULL) { - delete data->pcmROMImage->getFile(); - ROMImage::freeROMImage(data->pcmROMImage); - } - data->pcmROMImage = image; - return MT32EMU_RC_ADDED_PCM_ROM; + if (romInfo->type == ROMInfo::Control) fillROMInfo(rom_info, romInfo, NULL); + else if (romInfo->type == ROMInfo::PCM) fillROMInfo(rom_info, NULL, romInfo); + else fillROMInfo(rom_info, NULL, NULL); + return MT32EMU_RC_OK; +} + +static bool isROMInfoCompatible(const MachineConfiguration *machineConfiguration, const ROMInfo *romInfo) { + Bit32u romCount; + const ROMInfo * const *compatibleROMInfos = machineConfiguration->getCompatibleROMInfos(&romCount); + for (Bit32u i = 0; i < romCount; i++) { + if (romInfo == compatibleROMInfos[i]) return true; } - ROMImage::freeROMImage(image); - return MT32EMU_RC_OK; // No support for reverb ROM yet. + return false; +} + +static mt32emu_return_code replaceOrMergeROMImage(const ROMImage *&contextROMImage, const ROMImage *newROMImage, const MachineConfiguration *machineConfiguration, mt32emu_return_code addedFullROM, mt32emu_return_code addedPartialROM) { + if (contextROMImage != NULL) { + if (machineConfiguration != NULL) { + const ROMImage *mergedROMImage = ROMImage::mergeROMImages(contextROMImage, newROMImage); + if (mergedROMImage != NULL) { + if (newROMImage->isFileUserProvided()) delete newROMImage->getFile(); + ROMImage::freeROMImage(newROMImage); + if (contextROMImage->isFileUserProvided()) delete contextROMImage->getFile(); + ROMImage::freeROMImage(contextROMImage); + contextROMImage = mergedROMImage; + return addedFullROM; + } + if (newROMImage->getROMInfo() == contextROMImage->getROMInfo() + || (newROMImage->getROMInfo()->pairType != ROMInfo::Full + && isROMInfoCompatible(machineConfiguration, contextROMImage->getROMInfo()))) { + ROMImage::freeROMImage(newROMImage); + return MT32EMU_RC_OK; + } + } + if (contextROMImage->isFileUserProvided()) delete contextROMImage->getFile(); + ROMImage::freeROMImage(contextROMImage); + } + contextROMImage = newROMImage; + return newROMImage->getROMInfo()->pairType == ROMInfo::Full ? addedFullROM: addedPartialROM; +} + +static mt32emu_return_code addROMFiles(mt32emu_data *data, File *file1, File *file2 = NULL, const MachineConfiguration *machineConfiguration = NULL) { + const ROMImage *romImage; + if (machineConfiguration != NULL) { + romImage = ROMImage::makeROMImage(file1, machineConfiguration->getCompatibleROMInfos()); + } else { + romImage = file2 == NULL ? ROMImage::makeROMImage(file1, ROMInfo::getFullROMInfos()) : ROMImage::makeROMImage(file1, file2); + } + if (romImage == NULL) return MT32EMU_RC_ROMS_NOT_PAIRABLE; + const ROMInfo *info = romImage->getROMInfo(); + if (info == NULL) { + ROMImage::freeROMImage(romImage); + return MT32EMU_RC_ROM_NOT_IDENTIFIED; + } + switch (info->type) { + case ROMInfo::Control: + return replaceOrMergeROMImage(data->controlROMImage, romImage, machineConfiguration, MT32EMU_RC_ADDED_CONTROL_ROM, MT32EMU_RC_ADDED_PARTIAL_CONTROL_ROM); + case ROMInfo::PCM: + return replaceOrMergeROMImage(data->pcmROMImage, romImage, machineConfiguration, MT32EMU_RC_ADDED_PCM_ROM, MT32EMU_RC_ADDED_PARTIAL_PCM_ROM); + default: + ROMImage::freeROMImage(romImage); + return MT32EMU_RC_OK; // No support for reverb ROM yet. + } +} + +static mt32emu_return_code createFileStream(const char *filename, FileStream *&fileStream) { + mt32emu_return_code rc; + fileStream = new FileStream; + if (!fileStream->open(filename)) { + rc = MT32EMU_RC_FILE_NOT_FOUND; + } else if (fileStream->getSize() == 0) { + rc = MT32EMU_RC_FILE_NOT_LOADED; + } else { + return MT32EMU_RC_OK; + } + delete fileStream; + fileStream = NULL; + return rc; } } // namespace MT32Emu @@ -327,40 +464,92 @@ static mt32emu_return_code addROMFile(mt32emu_data *data, File *file) { extern "C" { -mt32emu_service_i mt32emu_get_service_i() { +mt32emu_service_i MT32EMU_C_CALL mt32emu_get_service_i() { mt32emu_service_i i; - i.v3 = &SERVICE_VTABLE; + i.v6 = &SERVICE_VTABLE; return i; } -mt32emu_report_handler_version mt32emu_get_supported_report_handler_version() { +mt32emu_report_handler_version MT32EMU_C_CALL mt32emu_get_supported_report_handler_version() { return MT32EMU_REPORT_HANDLER_VERSION_CURRENT; } -mt32emu_midi_receiver_version mt32emu_get_supported_midi_receiver_version() { +mt32emu_midi_receiver_version MT32EMU_C_CALL mt32emu_get_supported_midi_receiver_version() { return MT32EMU_MIDI_RECEIVER_VERSION_CURRENT; } -mt32emu_bit32u mt32emu_get_library_version_int() { +mt32emu_bit32u MT32EMU_C_CALL mt32emu_get_library_version_int() { return Synth::getLibraryVersionInt(); } -const char *mt32emu_get_library_version_string() { +const char * MT32EMU_C_CALL mt32emu_get_library_version_string() { return Synth::getLibraryVersionString(); } -mt32emu_bit32u mt32emu_get_stereo_output_samplerate(const mt32emu_analog_output_mode analog_output_mode) { +mt32emu_bit32u MT32EMU_C_CALL mt32emu_get_stereo_output_samplerate(const mt32emu_analog_output_mode analog_output_mode) { return Synth::getStereoOutputSampleRate(static_cast(analog_output_mode)); } -mt32emu_analog_output_mode mt32emu_get_best_analog_output_mode(const double target_samplerate) { +mt32emu_analog_output_mode MT32EMU_C_CALL mt32emu_get_best_analog_output_mode(const double target_samplerate) { return mt32emu_analog_output_mode(SampleRateConverter::getBestAnalogOutputMode(target_samplerate)); } -mt32emu_context mt32emu_create_context(mt32emu_report_handler_i report_handler, void *instance_data) { +size_t MT32EMU_C_CALL mt32emu_get_machine_ids(const char **machine_ids, size_t machine_ids_size) { + Bit32u configurationCount; + const MachineConfiguration * const *configurations = MachineConfiguration::getAllMachineConfigurations(&configurationCount); + if (machine_ids != NULL) { + for (Bit32u i = 0; i < machine_ids_size; i++) { + machine_ids[i] = i < configurationCount ? configurations[i]->getMachineID() : NULL; + } + } + return configurationCount; +} + +size_t MT32EMU_C_CALL mt32emu_get_rom_ids(const char **rom_ids, size_t rom_ids_size, const char *machine_id) { + const ROMInfo * const *romInfos; + Bit32u romCount; + if (machine_id != NULL) { + const MachineConfiguration *configuration = findMachineConfiguration(machine_id); + if (configuration != NULL) { + romInfos = configuration->getCompatibleROMInfos(&romCount); + } else { + romInfos = NULL; + romCount = 0U; + } + } else { + romInfos = ROMInfo::getAllROMInfos(&romCount); + } + if (rom_ids != NULL) { + for (size_t i = 0; i < rom_ids_size; i++) { + rom_ids[i] = i < romCount ? romInfos[i]->shortName : NULL; + } + } + return romCount; +} + +mt32emu_return_code MT32EMU_C_CALL mt32emu_identify_rom_data(mt32emu_rom_info *rom_info, const mt32emu_bit8u *data, size_t data_size, const char *machine_id) { + ArrayFile romFile = ArrayFile(data, data_size); + return identifyROM(rom_info, &romFile, machine_id); +} + +mt32emu_return_code MT32EMU_C_CALL mt32emu_identify_rom_file(mt32emu_rom_info *rom_info, const char *filename, const char *machine_id) { + FileStream *fs; + mt32emu_return_code rc = createFileStream(filename, fs); + if (fs == NULL) return rc; + rc = identifyROM(rom_info, fs, machine_id); + delete fs; + return rc; +} + +mt32emu_context MT32EMU_C_CALL mt32emu_create_context(mt32emu_report_handler_i report_handler, void *instance_data) { mt32emu_data *data = new mt32emu_data; - data->reportHandler = (report_handler.v0 != NULL) ? new DelegatingReportHandlerAdapter(report_handler, instance_data) : new ReportHandler; - data->synth = new Synth(data->reportHandler); + data->synth = new Synth; + if (report_handler.v0 != NULL) { + data->reportHandler = new DelegatingReportHandlerAdapter(report_handler, instance_data); + data->synth->setReportHandler2(data->reportHandler); + } else { + data->reportHandler = NULL; + } data->midiParser = new DefaultMidiStreamParser(*data->synth); data->controlROMImage = NULL; data->pcmROMImage = NULL; @@ -375,7 +564,7 @@ mt32emu_context mt32emu_create_context(mt32emu_report_handler_i report_handler, return data; } -void mt32emu_free_context(mt32emu_context data) { +void MT32EMU_C_CALL mt32emu_free_context(mt32emu_context data) { if (data == NULL) return; delete data->srcState->src; @@ -384,12 +573,12 @@ void mt32emu_free_context(mt32emu_context data) { data->srcState = NULL; if (data->controlROMImage != NULL) { - delete data->controlROMImage->getFile(); + if (data->controlROMImage->isFileUserProvided()) delete data->controlROMImage->getFile(); ROMImage::freeROMImage(data->controlROMImage); data->controlROMImage = NULL; } if (data->pcmROMImage != NULL) { - delete data->pcmROMImage->getFile(); + if (data->pcmROMImage->isFileUserProvided()) delete data->pcmROMImage->getFile(); ROMImage::freeROMImage(data->pcmROMImage); data->pcmROMImage = NULL; } @@ -402,76 +591,86 @@ void mt32emu_free_context(mt32emu_context data) { delete data; } -mt32emu_return_code mt32emu_add_rom_data(mt32emu_context context, const mt32emu_bit8u *data, size_t data_size, const mt32emu_sha1_digest *sha1_digest) { - if (sha1_digest == NULL) return addROMFile(context, new ArrayFile(data, data_size)); - return addROMFile(context, new ArrayFile(data, data_size, *sha1_digest)); +mt32emu_return_code MT32EMU_C_CALL mt32emu_add_rom_data(mt32emu_context context, const mt32emu_bit8u *data, size_t data_size, const mt32emu_sha1_digest *sha1_digest) { + if (sha1_digest == NULL) return addROMFiles(context, new ArrayFile(data, data_size)); + return addROMFiles(context, new ArrayFile(data, data_size, *sha1_digest)); } -mt32emu_return_code mt32emu_add_rom_file(mt32emu_context context, const char *filename) { - mt32emu_return_code rc = MT32EMU_RC_OK; - FileStream *fs = new FileStream; - if (fs->open(filename)) { - if (fs->getData() != NULL) { - rc = addROMFile(context, fs); - if (rc > 0) return rc; - } else { - rc = MT32EMU_RC_FILE_NOT_LOADED; - } - } else { - rc = MT32EMU_RC_FILE_NOT_FOUND; - } - delete fs; +mt32emu_return_code MT32EMU_C_CALL mt32emu_add_rom_file(mt32emu_context context, const char *filename) { + FileStream *fs; + mt32emu_return_code rc = createFileStream(filename, fs); + if (fs != NULL) rc = addROMFiles(context, fs); + if (rc <= MT32EMU_RC_OK) delete fs; return rc; } -void mt32emu_get_rom_info(mt32emu_const_context context, mt32emu_rom_info *rom_info) { - const ROMInfo *romInfo = context->controlROMImage == NULL ? NULL : context->controlROMImage->getROMInfo(); - if (romInfo != NULL) { - rom_info->control_rom_id = romInfo->shortName; - rom_info->control_rom_description = romInfo->description; - rom_info->control_rom_sha1_digest = romInfo->sha1Digest; - } else { - rom_info->control_rom_id = NULL; - rom_info->control_rom_description = NULL; - rom_info->control_rom_sha1_digest = NULL; - } - romInfo = context->pcmROMImage == NULL ? NULL : context->pcmROMImage->getROMInfo(); - if (romInfo != NULL) { - rom_info->pcm_rom_id = romInfo->shortName; - rom_info->pcm_rom_description = romInfo->description; - rom_info->pcm_rom_sha1_digest = romInfo->sha1Digest; - } else { - rom_info->pcm_rom_id = NULL; - rom_info->pcm_rom_description = NULL; - rom_info->pcm_rom_sha1_digest = NULL; - } +mt32emu_return_code MT32EMU_C_CALL mt32emu_merge_and_add_rom_data(mt32emu_context context, const mt32emu_bit8u *part1_data, size_t part1_data_size, const mt32emu_sha1_digest *part1_sha1_digest, const mt32emu_bit8u *part2_data, size_t part2_data_size, const mt32emu_sha1_digest *part2_sha1_digest) { + ArrayFile *file1 = part1_sha1_digest == NULL ? new ArrayFile(part1_data, part1_data_size) : new ArrayFile(part1_data, part1_data_size, *part1_sha1_digest); + ArrayFile *file2 = part2_sha1_digest == NULL ? new ArrayFile(part2_data, part2_data_size) : new ArrayFile(part2_data, part2_data_size, *part2_sha1_digest); + mt32emu_return_code rc = addROMFiles(context, file1, file2); + delete file1; + delete file2; + return rc; } -void mt32emu_set_partial_count(mt32emu_context context, const mt32emu_bit32u partial_count) { +mt32emu_return_code MT32EMU_C_CALL mt32emu_merge_and_add_rom_files(mt32emu_context context, const char *part1_filename, const char *part2_filename) { + FileStream *fs1; + mt32emu_return_code rc = createFileStream(part1_filename, fs1); + if (fs1 != NULL) { + FileStream *fs2; + rc = createFileStream(part2_filename, fs2); + if (fs2 != NULL) { + rc = addROMFiles(context, fs1, fs2); + delete fs2; + } + delete fs1; + } + return rc; +} + +mt32emu_return_code MT32EMU_C_CALL mt32emu_add_machine_rom_file(mt32emu_context context, const char *machine_id, const char *filename) { + const MachineConfiguration *machineConfiguration = findMachineConfiguration(machine_id); + if (machineConfiguration == NULL) return MT32EMU_RC_MACHINE_NOT_IDENTIFIED; + + FileStream *fs; + mt32emu_return_code rc = createFileStream(filename, fs); + if (fs == NULL) return rc; + rc = addROMFiles(context, fs, NULL, machineConfiguration); + if (rc <= MT32EMU_RC_OK) delete fs; + return rc; +} + +void MT32EMU_C_CALL mt32emu_get_rom_info(mt32emu_const_context context, mt32emu_rom_info *rom_info) { + const ROMInfo *controlROMInfo = context->controlROMImage == NULL ? NULL : context->controlROMImage->getROMInfo(); + const ROMInfo *pcmROMInfo = context->pcmROMImage == NULL ? NULL : context->pcmROMImage->getROMInfo(); + fillROMInfo(rom_info, controlROMInfo, pcmROMInfo); +} + +void MT32EMU_C_CALL mt32emu_set_partial_count(mt32emu_context context, const mt32emu_bit32u partial_count) { context->partialCount = partial_count; } -void mt32emu_set_analog_output_mode(mt32emu_context context, const mt32emu_analog_output_mode analog_output_mode) { +void MT32EMU_C_CALL mt32emu_set_analog_output_mode(mt32emu_context context, const mt32emu_analog_output_mode analog_output_mode) { context->analogOutputMode = static_cast(analog_output_mode); } -void mt32emu_set_stereo_output_samplerate(mt32emu_context context, const double samplerate) { +void MT32EMU_C_CALL mt32emu_set_stereo_output_samplerate(mt32emu_context context, const double samplerate) { context->srcState->outputSampleRate = SampleRateConverter::getSupportedOutputSampleRate(samplerate); } -void mt32emu_set_samplerate_conversion_quality(mt32emu_context context, const mt32emu_samplerate_conversion_quality quality) { +void MT32EMU_C_CALL mt32emu_set_samplerate_conversion_quality(mt32emu_context context, const mt32emu_samplerate_conversion_quality quality) { context->srcState->srcQuality = SamplerateConversionQuality(quality); } -void mt32emu_select_renderer_type(mt32emu_context context, const mt32emu_renderer_type renderer_type) { +void MT32EMU_C_CALL mt32emu_select_renderer_type(mt32emu_context context, const mt32emu_renderer_type renderer_type) { context->synth->selectRendererType(static_cast(renderer_type)); } -mt32emu_renderer_type mt32emu_get_selected_renderer_type(mt32emu_context context) { +mt32emu_renderer_type MT32EMU_C_CALL mt32emu_get_selected_renderer_type(mt32emu_context context) { return static_cast(context->synth->getSelectedRendererType()); } -mt32emu_return_code mt32emu_open_synth(mt32emu_const_context context) { +mt32emu_return_code MT32EMU_C_CALL mt32emu_open_synth(mt32emu_const_context context) { if ((context->controlROMImage == NULL) || (context->pcmROMImage == NULL)) { return MT32EMU_RC_MISSING_ROMS; } @@ -484,211 +683,219 @@ mt32emu_return_code mt32emu_open_synth(mt32emu_const_context context) { return MT32EMU_RC_OK; } -void mt32emu_close_synth(mt32emu_const_context context) { +void MT32EMU_C_CALL mt32emu_close_synth(mt32emu_const_context context) { context->synth->close(); delete context->srcState->src; context->srcState->src = NULL; } -mt32emu_boolean mt32emu_is_open(mt32emu_const_context context) { +mt32emu_boolean MT32EMU_C_CALL mt32emu_is_open(mt32emu_const_context context) { return context->synth->isOpen() ? MT32EMU_BOOL_TRUE : MT32EMU_BOOL_FALSE; } -mt32emu_bit32u mt32emu_get_actual_stereo_output_samplerate(mt32emu_const_context context) { +mt32emu_bit32u MT32EMU_C_CALL mt32emu_get_actual_stereo_output_samplerate(mt32emu_const_context context) { if (context->srcState->src == NULL) { return context->synth->getStereoOutputSampleRate(); } return mt32emu_bit32u(0.5 + context->srcState->src->convertSynthToOutputTimestamp(SAMPLE_RATE)); } -mt32emu_bit32u mt32emu_convert_output_to_synth_timestamp(mt32emu_const_context context, mt32emu_bit32u output_timestamp) { +mt32emu_bit32u MT32EMU_C_CALL mt32emu_convert_output_to_synth_timestamp(mt32emu_const_context context, mt32emu_bit32u output_timestamp) { if (context->srcState->src == NULL) { return output_timestamp; } return mt32emu_bit32u(0.5 + context->srcState->src->convertOutputToSynthTimestamp(output_timestamp)); } -mt32emu_bit32u mt32emu_convert_synth_to_output_timestamp(mt32emu_const_context context, mt32emu_bit32u synth_timestamp) { +mt32emu_bit32u MT32EMU_C_CALL mt32emu_convert_synth_to_output_timestamp(mt32emu_const_context context, mt32emu_bit32u synth_timestamp) { if (context->srcState->src == NULL) { return synth_timestamp; } return mt32emu_bit32u(0.5 + context->srcState->src->convertSynthToOutputTimestamp(synth_timestamp)); } -void mt32emu_flush_midi_queue(mt32emu_const_context context) { +void MT32EMU_C_CALL mt32emu_flush_midi_queue(mt32emu_const_context context) { context->synth->flushMIDIQueue(); } -mt32emu_bit32u mt32emu_set_midi_event_queue_size(mt32emu_const_context context, const mt32emu_bit32u queue_size) { +mt32emu_bit32u MT32EMU_C_CALL mt32emu_set_midi_event_queue_size(mt32emu_const_context context, const mt32emu_bit32u queue_size) { return context->synth->setMIDIEventQueueSize(queue_size); } -void mt32emu_configure_midi_event_queue_sysex_storage(mt32emu_const_context context, const mt32emu_bit32u storage_buffer_size) { - return context->synth->configureMIDIEventQueueSysexStorage(storage_buffer_size); +void MT32EMU_C_CALL mt32emu_configure_midi_event_queue_sysex_storage(mt32emu_const_context context, const mt32emu_bit32u storage_buffer_size) { + context->synth->configureMIDIEventQueueSysexStorage(storage_buffer_size); } -void mt32emu_set_midi_receiver(mt32emu_context context, mt32emu_midi_receiver_i midi_receiver, void *instance_data) { +void MT32EMU_C_CALL mt32emu_set_midi_receiver(mt32emu_context context, mt32emu_midi_receiver_i midi_receiver, void *instance_data) { delete context->midiParser; context->midiParser = (midi_receiver.v0 != NULL) ? new DelegatingMidiStreamParser(context, midi_receiver, instance_data) : new DefaultMidiStreamParser(*context->synth); } -mt32emu_bit32u mt32emu_get_internal_rendered_sample_count(mt32emu_const_context context) { +mt32emu_bit32u MT32EMU_C_CALL mt32emu_get_internal_rendered_sample_count(mt32emu_const_context context) { return context->synth->getInternalRenderedSampleCount(); } -void mt32emu_parse_stream(mt32emu_const_context context, const mt32emu_bit8u *stream, mt32emu_bit32u length) { +void MT32EMU_C_CALL mt32emu_parse_stream(mt32emu_const_context context, const mt32emu_bit8u *stream, mt32emu_bit32u length) { context->midiParser->resetTimestamp(); context->midiParser->parseStream(stream, length); } -void mt32emu_parse_stream_at(mt32emu_const_context context, const mt32emu_bit8u *stream, mt32emu_bit32u length, mt32emu_bit32u timestamp) { +void MT32EMU_C_CALL mt32emu_parse_stream_at(mt32emu_const_context context, const mt32emu_bit8u *stream, mt32emu_bit32u length, mt32emu_bit32u timestamp) { context->midiParser->setTimestamp(timestamp); context->midiParser->parseStream(stream, length); } -void mt32emu_play_short_message(mt32emu_const_context context, mt32emu_bit32u message) { +void MT32EMU_C_CALL mt32emu_play_short_message(mt32emu_const_context context, mt32emu_bit32u message) { context->midiParser->resetTimestamp(); context->midiParser->processShortMessage(message); } -void mt32emu_play_short_message_at(mt32emu_const_context context, mt32emu_bit32u message, mt32emu_bit32u timestamp) { +void MT32EMU_C_CALL mt32emu_play_short_message_at(mt32emu_const_context context, mt32emu_bit32u message, mt32emu_bit32u timestamp) { context->midiParser->setTimestamp(timestamp); context->midiParser->processShortMessage(message); } -mt32emu_return_code mt32emu_play_msg(mt32emu_const_context context, mt32emu_bit32u msg) { +mt32emu_return_code MT32EMU_C_CALL mt32emu_play_msg(mt32emu_const_context context, mt32emu_bit32u msg) { if (!context->synth->isOpen()) return MT32EMU_RC_NOT_OPENED; return (context->synth->playMsg(msg)) ? MT32EMU_RC_OK : MT32EMU_RC_QUEUE_FULL; } -mt32emu_return_code mt32emu_play_sysex(mt32emu_const_context context, const mt32emu_bit8u *sysex, mt32emu_bit32u len) { +mt32emu_return_code MT32EMU_C_CALL mt32emu_play_sysex(mt32emu_const_context context, const mt32emu_bit8u *sysex, mt32emu_bit32u len) { if (!context->synth->isOpen()) return MT32EMU_RC_NOT_OPENED; return (context->synth->playSysex(sysex, len)) ? MT32EMU_RC_OK : MT32EMU_RC_QUEUE_FULL; } -mt32emu_return_code mt32emu_play_msg_at(mt32emu_const_context context, mt32emu_bit32u msg, mt32emu_bit32u timestamp) { +mt32emu_return_code MT32EMU_C_CALL mt32emu_play_msg_at(mt32emu_const_context context, mt32emu_bit32u msg, mt32emu_bit32u timestamp) { if (!context->synth->isOpen()) return MT32EMU_RC_NOT_OPENED; return (context->synth->playMsg(msg, timestamp)) ? MT32EMU_RC_OK : MT32EMU_RC_QUEUE_FULL; } -mt32emu_return_code mt32emu_play_sysex_at(mt32emu_const_context context, const mt32emu_bit8u *sysex, mt32emu_bit32u len, mt32emu_bit32u timestamp) { +mt32emu_return_code MT32EMU_C_CALL mt32emu_play_sysex_at(mt32emu_const_context context, const mt32emu_bit8u *sysex, mt32emu_bit32u len, mt32emu_bit32u timestamp) { if (!context->synth->isOpen()) return MT32EMU_RC_NOT_OPENED; return (context->synth->playSysex(sysex, len, timestamp)) ? MT32EMU_RC_OK : MT32EMU_RC_QUEUE_FULL; } -void mt32emu_play_msg_now(mt32emu_const_context context, mt32emu_bit32u msg) { +void MT32EMU_C_CALL mt32emu_play_msg_now(mt32emu_const_context context, mt32emu_bit32u msg) { context->synth->playMsgNow(msg); } -void mt32emu_play_msg_on_part(mt32emu_const_context context, mt32emu_bit8u part, mt32emu_bit8u code, mt32emu_bit8u note, mt32emu_bit8u velocity) { +void MT32EMU_C_CALL mt32emu_play_msg_on_part(mt32emu_const_context context, mt32emu_bit8u part, mt32emu_bit8u code, mt32emu_bit8u note, mt32emu_bit8u velocity) { context->synth->playMsgOnPart(part, code, note, velocity); } -void mt32emu_play_sysex_now(mt32emu_const_context context, const mt32emu_bit8u *sysex, mt32emu_bit32u len) { +void MT32EMU_C_CALL mt32emu_play_sysex_now(mt32emu_const_context context, const mt32emu_bit8u *sysex, mt32emu_bit32u len) { context->synth->playSysexNow(sysex, len); } -void mt32emu_write_sysex(mt32emu_const_context context, mt32emu_bit8u channel, const mt32emu_bit8u *sysex, mt32emu_bit32u len) { +void MT32EMU_C_CALL mt32emu_write_sysex(mt32emu_const_context context, mt32emu_bit8u channel, const mt32emu_bit8u *sysex, mt32emu_bit32u len) { context->synth->writeSysex(channel, sysex, len); } -void mt32emu_set_reverb_enabled(mt32emu_const_context context, const mt32emu_boolean reverb_enabled) { +void MT32EMU_C_CALL mt32emu_set_reverb_enabled(mt32emu_const_context context, const mt32emu_boolean reverb_enabled) { context->synth->setReverbEnabled(reverb_enabled != MT32EMU_BOOL_FALSE); } -mt32emu_boolean mt32emu_is_reverb_enabled(mt32emu_const_context context) { +mt32emu_boolean MT32EMU_C_CALL mt32emu_is_reverb_enabled(mt32emu_const_context context) { return context->synth->isReverbEnabled() ? MT32EMU_BOOL_TRUE : MT32EMU_BOOL_FALSE; } -void mt32emu_set_reverb_overridden(mt32emu_const_context context, const mt32emu_boolean reverb_overridden) { +void MT32EMU_C_CALL mt32emu_set_reverb_overridden(mt32emu_const_context context, const mt32emu_boolean reverb_overridden) { context->synth->setReverbOverridden(reverb_overridden != MT32EMU_BOOL_FALSE); } -mt32emu_boolean mt32emu_is_reverb_overridden(mt32emu_const_context context) { +mt32emu_boolean MT32EMU_C_CALL mt32emu_is_reverb_overridden(mt32emu_const_context context) { return context->synth->isReverbOverridden() ? MT32EMU_BOOL_TRUE : MT32EMU_BOOL_FALSE; } -void mt32emu_set_reverb_compatibility_mode(mt32emu_const_context context, const mt32emu_boolean mt32_compatible_mode) { +void MT32EMU_C_CALL mt32emu_set_reverb_compatibility_mode(mt32emu_const_context context, const mt32emu_boolean mt32_compatible_mode) { context->synth->setReverbCompatibilityMode(mt32_compatible_mode != MT32EMU_BOOL_FALSE); } -mt32emu_boolean mt32emu_is_mt32_reverb_compatibility_mode(mt32emu_const_context context) { +mt32emu_boolean MT32EMU_C_CALL mt32emu_is_mt32_reverb_compatibility_mode(mt32emu_const_context context) { return context->synth->isMT32ReverbCompatibilityMode() ? MT32EMU_BOOL_TRUE : MT32EMU_BOOL_FALSE; } -mt32emu_boolean mt32emu_is_default_reverb_mt32_compatible(mt32emu_const_context context) { +mt32emu_boolean MT32EMU_C_CALL mt32emu_is_default_reverb_mt32_compatible(mt32emu_const_context context) { return context->synth->isDefaultReverbMT32Compatible() ? MT32EMU_BOOL_TRUE : MT32EMU_BOOL_FALSE; } -void mt32emu_preallocate_reverb_memory(mt32emu_const_context context, const mt32emu_boolean enabled) { - return context->synth->preallocateReverbMemory(enabled != MT32EMU_BOOL_FALSE); +void MT32EMU_C_CALL mt32emu_preallocate_reverb_memory(mt32emu_const_context context, const mt32emu_boolean enabled) { + context->synth->preallocateReverbMemory(enabled != MT32EMU_BOOL_FALSE); } -void mt32emu_set_dac_input_mode(mt32emu_const_context context, const mt32emu_dac_input_mode mode) { +void MT32EMU_C_CALL mt32emu_set_dac_input_mode(mt32emu_const_context context, const mt32emu_dac_input_mode mode) { context->synth->setDACInputMode(static_cast(mode)); } -mt32emu_dac_input_mode mt32emu_get_dac_input_mode(mt32emu_const_context context) { +mt32emu_dac_input_mode MT32EMU_C_CALL mt32emu_get_dac_input_mode(mt32emu_const_context context) { return static_cast(context->synth->getDACInputMode()); } -void mt32emu_set_midi_delay_mode(mt32emu_const_context context, const mt32emu_midi_delay_mode mode) { +void MT32EMU_C_CALL mt32emu_set_midi_delay_mode(mt32emu_const_context context, const mt32emu_midi_delay_mode mode) { context->synth->setMIDIDelayMode(static_cast(mode)); } -mt32emu_midi_delay_mode mt32emu_get_midi_delay_mode(mt32emu_const_context context) { +mt32emu_midi_delay_mode MT32EMU_C_CALL mt32emu_get_midi_delay_mode(mt32emu_const_context context) { return static_cast(context->synth->getMIDIDelayMode()); } -void mt32emu_set_output_gain(mt32emu_const_context context, float gain) { +void MT32EMU_C_CALL mt32emu_set_output_gain(mt32emu_const_context context, float gain) { context->synth->setOutputGain(gain); } -float mt32emu_get_output_gain(mt32emu_const_context context) { +float MT32EMU_C_CALL mt32emu_get_output_gain(mt32emu_const_context context) { return context->synth->getOutputGain(); } -void mt32emu_set_reverb_output_gain(mt32emu_const_context context, float gain) { +void MT32EMU_C_CALL mt32emu_set_reverb_output_gain(mt32emu_const_context context, float gain) { context->synth->setReverbOutputGain(gain); } -float mt32emu_get_reverb_output_gain(mt32emu_const_context context) { +float MT32EMU_C_CALL mt32emu_get_reverb_output_gain(mt32emu_const_context context) { return context->synth->getReverbOutputGain(); } -void mt32emu_set_reversed_stereo_enabled(mt32emu_const_context context, const mt32emu_boolean enabled) { +void MT32EMU_C_CALL mt32emu_set_part_volume_override(mt32emu_const_context context, mt32emu_bit8u part_number, mt32emu_bit8u volume_override) { + context->synth->setPartVolumeOverride(part_number, volume_override); +} + +mt32emu_bit8u MT32EMU_C_CALL mt32emu_get_part_volume_override(mt32emu_const_context context, mt32emu_bit8u part_number) { + return context->synth->getPartVolumeOverride(part_number); +} + +void MT32EMU_C_CALL mt32emu_set_reversed_stereo_enabled(mt32emu_const_context context, const mt32emu_boolean enabled) { context->synth->setReversedStereoEnabled(enabled != MT32EMU_BOOL_FALSE); } -mt32emu_boolean mt32emu_is_reversed_stereo_enabled(mt32emu_const_context context) { +mt32emu_boolean MT32EMU_C_CALL mt32emu_is_reversed_stereo_enabled(mt32emu_const_context context) { return context->synth->isReversedStereoEnabled() ? MT32EMU_BOOL_TRUE : MT32EMU_BOOL_FALSE; } -void mt32emu_set_nice_amp_ramp_enabled(mt32emu_const_context context, const mt32emu_boolean enabled) { +void MT32EMU_C_CALL mt32emu_set_nice_amp_ramp_enabled(mt32emu_const_context context, const mt32emu_boolean enabled) { context->synth->setNiceAmpRampEnabled(enabled != MT32EMU_BOOL_FALSE); } -mt32emu_boolean mt32emu_is_nice_amp_ramp_enabled(mt32emu_const_context context) { +mt32emu_boolean MT32EMU_C_CALL mt32emu_is_nice_amp_ramp_enabled(mt32emu_const_context context) { return context->synth->isNiceAmpRampEnabled() ? MT32EMU_BOOL_TRUE : MT32EMU_BOOL_FALSE; } -MT32EMU_EXPORT void mt32emu_set_nice_panning_enabled(mt32emu_const_context context, const mt32emu_boolean enabled) { +void MT32EMU_C_CALL mt32emu_set_nice_panning_enabled(mt32emu_const_context context, const mt32emu_boolean enabled) { context->synth->setNicePanningEnabled(enabled != MT32EMU_BOOL_FALSE); } -MT32EMU_EXPORT mt32emu_boolean mt32emu_is_nice_panning_enabled(mt32emu_const_context context) { +mt32emu_boolean MT32EMU_C_CALL mt32emu_is_nice_panning_enabled(mt32emu_const_context context) { return context->synth->isNicePanningEnabled() ? MT32EMU_BOOL_TRUE : MT32EMU_BOOL_FALSE; } -MT32EMU_EXPORT void mt32emu_set_nice_partial_mixing_enabled(mt32emu_const_context context, const mt32emu_boolean enabled) { +void MT32EMU_C_CALL mt32emu_set_nice_partial_mixing_enabled(mt32emu_const_context context, const mt32emu_boolean enabled) { context->synth->setNicePartialMixingEnabled(enabled != MT32EMU_BOOL_FALSE); } -MT32EMU_EXPORT mt32emu_boolean mt32emu_is_nice_partial_mixing_enabled(mt32emu_const_context context) { +mt32emu_boolean MT32EMU_C_CALL mt32emu_is_nice_partial_mixing_enabled(mt32emu_const_context context) { return context->synth->isNicePartialMixingEnabled() ? MT32EMU_BOOL_TRUE : MT32EMU_BOOL_FALSE; } -void mt32emu_render_bit16s(mt32emu_const_context context, mt32emu_bit16s *stream, mt32emu_bit32u len) { +void MT32EMU_C_CALL mt32emu_render_bit16s(mt32emu_const_context context, mt32emu_bit16s *stream, mt32emu_bit32u len) { if (context->srcState->src != NULL) { context->srcState->src->getOutputSamples(stream, len); } else { @@ -696,7 +903,7 @@ void mt32emu_render_bit16s(mt32emu_const_context context, mt32emu_bit16s *stream } } -void mt32emu_render_float(mt32emu_const_context context, float *stream, mt32emu_bit32u len) { +void MT32EMU_C_CALL mt32emu_render_float(mt32emu_const_context context, float *stream, mt32emu_bit32u len) { if (context->srcState->src != NULL) { context->srcState->src->getOutputSamples(stream, len); } else { @@ -704,44 +911,72 @@ void mt32emu_render_float(mt32emu_const_context context, float *stream, mt32emu_ } } -void mt32emu_render_bit16s_streams(mt32emu_const_context context, const mt32emu_dac_output_bit16s_streams *streams, mt32emu_bit32u len) { +void MT32EMU_C_CALL mt32emu_render_bit16s_streams(mt32emu_const_context context, const mt32emu_dac_output_bit16s_streams *streams, mt32emu_bit32u len) { context->synth->renderStreams(*reinterpret_cast *>(streams), len); } -void mt32emu_render_float_streams(mt32emu_const_context context, const mt32emu_dac_output_float_streams *streams, mt32emu_bit32u len) { +void MT32EMU_C_CALL mt32emu_render_float_streams(mt32emu_const_context context, const mt32emu_dac_output_float_streams *streams, mt32emu_bit32u len) { context->synth->renderStreams(*reinterpret_cast *>(streams), len); } -mt32emu_boolean mt32emu_has_active_partials(mt32emu_const_context context) { +mt32emu_boolean MT32EMU_C_CALL mt32emu_has_active_partials(mt32emu_const_context context) { return context->synth->hasActivePartials() ? MT32EMU_BOOL_TRUE : MT32EMU_BOOL_FALSE; } -mt32emu_boolean mt32emu_is_active(mt32emu_const_context context) { +mt32emu_boolean MT32EMU_C_CALL mt32emu_is_active(mt32emu_const_context context) { return context->synth->isActive() ? MT32EMU_BOOL_TRUE : MT32EMU_BOOL_FALSE; } -mt32emu_bit32u mt32emu_get_partial_count(mt32emu_const_context context) { +mt32emu_bit32u MT32EMU_C_CALL mt32emu_get_partial_count(mt32emu_const_context context) { return context->synth->getPartialCount(); } -mt32emu_bit32u mt32emu_get_part_states(mt32emu_const_context context) { +mt32emu_bit32u MT32EMU_C_CALL mt32emu_get_part_states(mt32emu_const_context context) { return context->synth->getPartStates(); } -void mt32emu_get_partial_states(mt32emu_const_context context, mt32emu_bit8u *partial_states) { +void MT32EMU_C_CALL mt32emu_get_partial_states(mt32emu_const_context context, mt32emu_bit8u *partial_states) { context->synth->getPartialStates(partial_states); } -mt32emu_bit32u mt32emu_get_playing_notes(mt32emu_const_context context, mt32emu_bit8u part_number, mt32emu_bit8u *keys, mt32emu_bit8u *velocities) { +mt32emu_bit32u MT32EMU_C_CALL mt32emu_get_playing_notes(mt32emu_const_context context, mt32emu_bit8u part_number, mt32emu_bit8u *keys, mt32emu_bit8u *velocities) { return context->synth->getPlayingNotes(part_number, keys, velocities); } -const char *mt32emu_get_patch_name(mt32emu_const_context context, mt32emu_bit8u part_number) { +const char * MT32EMU_C_CALL mt32emu_get_patch_name(mt32emu_const_context context, mt32emu_bit8u part_number) { return context->synth->getPatchName(part_number); } -void mt32emu_read_memory(mt32emu_const_context context, mt32emu_bit32u addr, mt32emu_bit32u len, mt32emu_bit8u *data) { +mt32emu_boolean MT32EMU_C_CALL mt32emu_get_sound_group_name(mt32emu_const_context context, char *sound_group_name, mt32emu_bit8u timbre_group, mt32emu_bit8u timbre_number) { + return context->synth->getSoundGroupName(sound_group_name, timbre_group, timbre_number) ? MT32EMU_BOOL_TRUE : MT32EMU_BOOL_FALSE; +} + +mt32emu_boolean MT32EMU_C_CALL mt32emu_get_sound_name(mt32emu_const_context context, char *sound_name, mt32emu_bit8u timbre_group, mt32emu_bit8u timbre_number) { + return context->synth->getSoundName(sound_name, timbre_group, timbre_number) ? MT32EMU_BOOL_TRUE : MT32EMU_BOOL_FALSE; +} + +void MT32EMU_C_CALL mt32emu_read_memory(mt32emu_const_context context, mt32emu_bit32u addr, mt32emu_bit32u len, mt32emu_bit8u *data) { context->synth->readMemory(addr, len, data); } +mt32emu_boolean MT32EMU_C_CALL mt32emu_get_display_state(mt32emu_const_context context, char *target_buffer, const mt32emu_boolean narrow_lcd) { + return context->synth->getDisplayState(target_buffer, narrow_lcd != MT32EMU_BOOL_FALSE) ? MT32EMU_BOOL_TRUE : MT32EMU_BOOL_FALSE; +} + +void MT32EMU_C_CALL mt32emu_set_main_display_mode(mt32emu_const_context context) { + context->synth->setMainDisplayMode(); +} + +void MT32EMU_C_CALL mt32emu_set_display_compatibility(mt32emu_const_context context, mt32emu_boolean old_mt32_compatibility_enabled) { + context->synth->setDisplayCompatibility(old_mt32_compatibility_enabled != MT32EMU_BOOL_FALSE); +} + +mt32emu_boolean MT32EMU_C_CALL mt32emu_is_display_old_mt32_compatible(mt32emu_const_context context) { + return context->synth->isDisplayOldMT32Compatible() ? MT32EMU_BOOL_TRUE : MT32EMU_BOOL_FALSE; +} + +mt32emu_boolean MT32EMU_C_CALL mt32emu_is_default_display_old_mt32_compatible(mt32emu_const_context context) { + return context->synth->isDefaultDisplayOldMT32Compatible() ? MT32EMU_BOOL_TRUE : MT32EMU_BOOL_FALSE; +} + } // extern "C" diff --git a/src/sound/munt/c_interface/c_interface.h b/src/sound/munt/c_interface/c_interface.h index 0924dcce5..5653c9051 100644 --- a/src/sound/munt/c_interface/c_interface.h +++ b/src/sound/munt/c_interface/c_interface.h @@ -1,5 +1,5 @@ /* Copyright (C) 2003, 2004, 2005, 2006, 2008, 2009 Dean Beeler, Jerome Fisher - * Copyright (C) 2011-2020 Dean Beeler, Jerome Fisher, Sergey V. Mikayev + * Copyright (C) 2011-2022 Dean Beeler, Jerome Fisher, Sergey V. Mikayev * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by @@ -24,7 +24,9 @@ #include "c_types.h" #undef MT32EMU_EXPORT +#undef MT32EMU_EXPORT_V #define MT32EMU_EXPORT MT32EMU_EXPORT_ATTRIBUTE +#define MT32EMU_EXPORT_V(symbol_version_tag) MT32EMU_EXPORT #ifdef __cplusplus extern "C" { @@ -35,24 +37,28 @@ extern "C" { /* === Interface handling === */ /** Returns mt32emu_service_i interface. */ -MT32EMU_EXPORT mt32emu_service_i mt32emu_get_service_i(void); +MT32EMU_EXPORT mt32emu_service_i MT32EMU_C_CALL mt32emu_get_service_i(void); #if MT32EMU_EXPORTS_TYPE == 2 #undef MT32EMU_EXPORT +#undef MT32EMU_EXPORT_V #define MT32EMU_EXPORT +#define MT32EMU_EXPORT_V(symbol_version_tag) MT32EMU_EXPORT #endif /** * Returns the version ID of mt32emu_report_handler_i interface the library has been compiled with. * This allows a client to fall-back gracefully instead of silently not receiving expected event reports. */ -MT32EMU_EXPORT mt32emu_report_handler_version mt32emu_get_supported_report_handler_version(void); +MT32EMU_EXPORT mt32emu_report_handler_version MT32EMU_C_CALL mt32emu_get_supported_report_handler_version(void); /** * Returns the version ID of mt32emu_midi_receiver_version_i interface the library has been compiled with. * This allows a client to fall-back gracefully instead of silently not receiving expected MIDI messages. */ -MT32EMU_EXPORT mt32emu_midi_receiver_version mt32emu_get_supported_midi_receiver_version(void); +MT32EMU_EXPORT mt32emu_midi_receiver_version MT32EMU_C_CALL mt32emu_get_supported_midi_receiver_version(void); + +/* === Utility === */ /** * Returns library version as an integer in format: 0x00MMmmpp, where: @@ -60,67 +66,149 @@ MT32EMU_EXPORT mt32emu_midi_receiver_version mt32emu_get_supported_midi_receiver * mm - minor version number * pp - patch number */ -MT32EMU_EXPORT mt32emu_bit32u mt32emu_get_library_version_int(void); +MT32EMU_EXPORT mt32emu_bit32u MT32EMU_C_CALL mt32emu_get_library_version_int(void); /** * Returns library version as a C-string in format: "MAJOR.MINOR.PATCH". */ -MT32EMU_EXPORT const char *mt32emu_get_library_version_string(void); +MT32EMU_EXPORT const char * MT32EMU_C_CALL mt32emu_get_library_version_string(void); /** * Returns output sample rate used in emulation of stereo analog circuitry of hardware units for particular analog_output_mode. * See comment for mt32emu_analog_output_mode. */ -MT32EMU_EXPORT mt32emu_bit32u mt32emu_get_stereo_output_samplerate(const mt32emu_analog_output_mode analog_output_mode); +MT32EMU_EXPORT mt32emu_bit32u MT32EMU_C_CALL mt32emu_get_stereo_output_samplerate(const mt32emu_analog_output_mode analog_output_mode); /** * Returns the value of analog_output_mode for which the output signal may retain its full frequency spectrum * at the sample rate specified by the target_samplerate argument. * See comment for mt32emu_analog_output_mode. */ -MT32EMU_EXPORT mt32emu_analog_output_mode mt32emu_get_best_analog_output_mode(const double target_samplerate); +MT32EMU_EXPORT mt32emu_analog_output_mode MT32EMU_C_CALL mt32emu_get_best_analog_output_mode(const double target_samplerate); + +/* === ROM handling === */ + +/** + * Retrieves a list of identifiers (as C-strings) of supported machines. Argument machine_ids points to the array of size + * machine_ids_size to be filled. + * Returns the number of identifiers available for retrieval. The size of the target array to be allocated can be found + * by passing NULL in argument machine_ids; argument machine_ids_size is ignored in this case. + */ +MT32EMU_EXPORT_V(2.5) size_t MT32EMU_C_CALL mt32emu_get_machine_ids(const char **machine_ids, size_t machine_ids_size); +/** + * Retrieves a list of identifiers (as C-strings) of supported ROM images. Argument rom_ids points to the array of size + * rom_ids_size to be filled. Optional argument machine_id can be used to indicate a specific machine to retrieve ROM identifiers + * for; if NULL, identifiers of all the ROM images supported by the emulation engine are retrieved. + * Returns the number of ROM identifiers available for retrieval. The size of the target array to be allocated can be found + * by passing NULL in argument rom_ids; argument rom_ids_size is ignored in this case. If argument machine_id contains + * an unrecognised value, 0 is returned. + */ +MT32EMU_EXPORT_V(2.5) size_t MT32EMU_C_CALL mt32emu_get_rom_ids(const char **rom_ids, size_t rom_ids_size, const char *machine_id); + +/** + * Identifies a ROM image the provided data array contains by its SHA1 digest. Optional argument machine_id can be used to indicate + * a specific machine to identify the ROM image for; if NULL, the ROM image is identified for any supported machine. + * A mt32emu_rom_info structure supplied in argument rom_info is filled in accordance with the provided ROM image; unused fields + * are filled with NULLs. If the content of the ROM image is not identified successfully (e.g. when the ROM image is incompatible + * with the specified machine), all fields of rom_info are filled with NULLs. + * Returns MT32EMU_RC_OK upon success or a negative error code otherwise. + */ +MT32EMU_EXPORT_V(2.5) mt32emu_return_code MT32EMU_C_CALL mt32emu_identify_rom_data(mt32emu_rom_info *rom_info, const mt32emu_bit8u *data, size_t data_size, const char *machine_id); +/** + * Loads the content of the file specified by argument filename and identifies a ROM image the file contains by its SHA1 digest. + * Optional argument machine_id can be used to indicate a specific machine to identify the ROM image for; if NULL, the ROM image + * is identified for any supported machine. + * A mt32emu_rom_info structure supplied in argument rom_info is filled in accordance with the provided ROM image; unused fields + * are filled with NULLs. If the content of the file is not identified successfully (e.g. when the ROM image is incompatible + * with the specified machine), all fields of rom_info are filled with NULLs. + * Returns MT32EMU_RC_OK upon success or a negative error code otherwise. + */ +MT32EMU_EXPORT_V(2.5) mt32emu_return_code MT32EMU_C_CALL mt32emu_identify_rom_file(mt32emu_rom_info *rom_info, const char *filename, const char *machine_id); /* == Context-dependent functions == */ /** Initialises a new emulation context and installs custom report handler if non-NULL. */ -MT32EMU_EXPORT mt32emu_context mt32emu_create_context(mt32emu_report_handler_i report_handler, void *instance_data); +MT32EMU_EXPORT mt32emu_context MT32EMU_C_CALL mt32emu_create_context(mt32emu_report_handler_i report_handler, void *instance_data); /** Closes and destroys emulation context. */ -MT32EMU_EXPORT void mt32emu_free_context(mt32emu_context context); +MT32EMU_EXPORT void MT32EMU_C_CALL mt32emu_free_context(mt32emu_context context); /** - * Adds new ROM identified by its SHA1 digest to the emulation context replacing previously added ROM of the same type if any. - * Argument sha1_digest can be NULL, in this case the digest will be computed using the actual ROM data. + * Adds a new full ROM data image identified by its SHA1 digest to the emulation context replacing previously added ROM of the same + * type if any. Argument sha1_digest can be NULL, in this case the digest will be computed using the actual ROM data. * If sha1_digest is set to non-NULL, it is assumed being correct and will not be recomputed. - * This function doesn't immediately change the state of already opened synth. Newly added ROM will take effect upon next call of mt32emu_open_synth(). + * The provided data array is NOT copied and used directly for efficiency. The caller should not deallocate it while the emulation + * context is referring to the ROM data. + * This function doesn't immediately change the state of already opened synth. Newly added ROM will take effect upon next call of + * mt32emu_open_synth(). * Returns positive value upon success. */ -MT32EMU_EXPORT mt32emu_return_code mt32emu_add_rom_data(mt32emu_context context, const mt32emu_bit8u *data, size_t data_size, const mt32emu_sha1_digest *sha1_digest); +MT32EMU_EXPORT mt32emu_return_code MT32EMU_C_CALL mt32emu_add_rom_data(mt32emu_context context, const mt32emu_bit8u *data, size_t data_size, const mt32emu_sha1_digest *sha1_digest); /** - * Loads a ROM file, identify it by SHA1 digest, and adds it to the emulation context replacing previously added ROM of the same type if any. - * This function doesn't immediately change the state of already opened synth. Newly added ROM will take effect upon next call of mt32emu_open_synth(). + * Loads a ROM file that contains a full ROM data image, identifies it by the SHA1 digest, and adds it to the emulation context + * replacing previously added ROM of the same type if any. + * This function doesn't immediately change the state of already opened synth. Newly added ROM will take effect upon next call of + * mt32emu_open_synth(). * Returns positive value upon success. */ -MT32EMU_EXPORT mt32emu_return_code mt32emu_add_rom_file(mt32emu_context context, const char *filename); +MT32EMU_EXPORT mt32emu_return_code MT32EMU_C_CALL mt32emu_add_rom_file(mt32emu_context context, const char *filename); + +/** + * Merges a pair of compatible ROM data image parts into a full image and adds it to the emulation context replacing previously + * added ROM of the same type if any. Each partial image is identified by its SHA1 digest. Arguments partN_sha1_digest can be NULL, + * in this case the digest will be computed using the actual ROM data. If a non-NULL SHA1 value is provided, it is assumed being + * correct and will not be recomputed. The provided data arrays may be deallocated as soon as the function completes. + * This function doesn't immediately change the state of already opened synth. Newly added ROM will take effect upon next call of + * mt32emu_open_synth(). + * Returns positive value upon success. + */ +MT32EMU_EXPORT_V(2.5) mt32emu_return_code MT32EMU_C_CALL mt32emu_merge_and_add_rom_data(mt32emu_context context, const mt32emu_bit8u *part1_data, size_t part1_data_size, const mt32emu_sha1_digest *part1_sha1_digest, const mt32emu_bit8u *part2_data, size_t part2_data_size, const mt32emu_sha1_digest *part2_sha1_digest); + +/** + * Loads a pair of files that contains compatible parts of a full ROM image, identifies them by the SHA1 digest, merges these + * parts into a full ROM image and adds it to the emulation context replacing previously added ROM of the same type if any. + * This function doesn't immediately change the state of already opened synth. Newly added ROM will take effect upon next call of + * mt32emu_open_synth(). + * Returns positive value upon success. + */ +MT32EMU_EXPORT_V(2.5) mt32emu_return_code MT32EMU_C_CALL mt32emu_merge_and_add_rom_files(mt32emu_context context, const char *part1_filename, const char *part2_filename); + +/** + * Loads a file that contains a ROM image of a specific machine, identifies it by the SHA1 digest, and adds it to the emulation + * context. The ROM image can only be identified successfully if it is compatible with the specified machine. + * Full and partial ROM images are supported and handled according to the following rules: + * - a file with any compatible ROM image is added if none (of the same type) exists in the emulation context; + * - a file with any compatible ROM image replaces any image of the same type that is incompatible with the specified machine; + * - a file with a full ROM image replaces the previously added partial ROM of the same type; + * - a file with a partial ROM image is merged with the previously added ROM image if pairable; + * - otherwise, the file is ignored. + * The described behaviour allows the caller application to traverse a directory with ROM files attempting to add each one in turn. + * As soon as both the full control and the full PCM ROM images are added and / or merged, the iteration can be stopped. + * This function doesn't immediately change the state of already opened synth. Newly added ROMs will take effect upon next call of + * mt32emu_open_synth(). + * Returns a positive value in case changes have been made, MT32EMU_RC_OK if the file has been ignored or a negative error code + * upon failure. + */ +MT32EMU_EXPORT_V(2.5) mt32emu_return_code MT32EMU_C_CALL mt32emu_add_machine_rom_file(mt32emu_context context, const char *machine_id, const char *filename); /** * Fills in mt32emu_rom_info structure with identifiers and descriptions of control and PCM ROM files identified and added to the synth context. * If one of the ROM files is not loaded and identified yet, NULL is returned in the corresponding fields of the mt32emu_rom_info structure. */ -MT32EMU_EXPORT void mt32emu_get_rom_info(mt32emu_const_context context, mt32emu_rom_info *rom_info); +MT32EMU_EXPORT void MT32EMU_C_CALL mt32emu_get_rom_info(mt32emu_const_context context, mt32emu_rom_info *rom_info); /** * Allows to override the default maximum number of partials playing simultaneously within the emulation session. * This function doesn't immediately change the state of already opened synth. Newly set value will take effect upon next call of mt32emu_open_synth(). */ -MT32EMU_EXPORT void mt32emu_set_partial_count(mt32emu_context context, const mt32emu_bit32u partial_count); +MT32EMU_EXPORT void MT32EMU_C_CALL mt32emu_set_partial_count(mt32emu_context context, const mt32emu_bit32u partial_count); /** * Allows to override the default mode for emulation of analogue circuitry of the hardware units within the emulation session. * This function doesn't immediately change the state of already opened synth. Newly set value will take effect upon next call of mt32emu_open_synth(). */ -MT32EMU_EXPORT void mt32emu_set_analog_output_mode(mt32emu_context context, const mt32emu_analog_output_mode analog_output_mode); +MT32EMU_EXPORT void MT32EMU_C_CALL mt32emu_set_analog_output_mode(mt32emu_context context, const mt32emu_analog_output_mode analog_output_mode); /** * Allows to convert the synthesiser output to any desired sample rate. The samplerate conversion @@ -131,7 +219,7 @@ MT32EMU_EXPORT void mt32emu_set_analog_output_mode(mt32emu_context context, cons * This function doesn't immediately change the state of already opened synth. * Newly set value will take effect upon next call of mt32emu_open_synth(). */ -MT32EMU_EXPORT void mt32emu_set_stereo_output_samplerate(mt32emu_context context, const double samplerate); +MT32EMU_EXPORT void MT32EMU_C_CALL mt32emu_set_stereo_output_samplerate(mt32emu_context context, const double samplerate); /** * Several samplerate conversion quality options are provided which allow to trade-off the conversion speed vs. @@ -140,66 +228,66 @@ MT32EMU_EXPORT void mt32emu_set_stereo_output_samplerate(mt32emu_context context * This function doesn't immediately change the state of already opened synth. * Newly set value will take effect upon next call of mt32emu_open_synth(). */ -MT32EMU_EXPORT void mt32emu_set_samplerate_conversion_quality(mt32emu_context context, const mt32emu_samplerate_conversion_quality quality); +MT32EMU_EXPORT void MT32EMU_C_CALL mt32emu_set_samplerate_conversion_quality(mt32emu_context context, const mt32emu_samplerate_conversion_quality quality); /** * Selects new type of the wave generator and renderer to be used during subsequent calls to mt32emu_open_synth(). * By default, MT32EMU_RT_BIT16S is selected. * See mt32emu_renderer_type for details. */ -MT32EMU_EXPORT void mt32emu_select_renderer_type(mt32emu_context context, const mt32emu_renderer_type renderer_type); +MT32EMU_EXPORT void MT32EMU_C_CALL mt32emu_select_renderer_type(mt32emu_context context, const mt32emu_renderer_type renderer_type); /** * Returns previously selected type of the wave generator and renderer. * See mt32emu_renderer_type for details. */ -MT32EMU_EXPORT mt32emu_renderer_type mt32emu_get_selected_renderer_type(mt32emu_context context); +MT32EMU_EXPORT mt32emu_renderer_type MT32EMU_C_CALL mt32emu_get_selected_renderer_type(mt32emu_context context); /** * Prepares the emulation context to receive MIDI messages and produce output audio data using aforehand added set of ROMs, * and optionally set the maximum partial count and the analog output mode. * Returns MT32EMU_RC_OK upon success. */ -MT32EMU_EXPORT mt32emu_return_code mt32emu_open_synth(mt32emu_const_context context); +MT32EMU_EXPORT mt32emu_return_code MT32EMU_C_CALL mt32emu_open_synth(mt32emu_const_context context); /** Closes the emulation context freeing allocated resources. Added ROMs remain unaffected and ready for reuse. */ -MT32EMU_EXPORT void mt32emu_close_synth(mt32emu_const_context context); +MT32EMU_EXPORT void MT32EMU_C_CALL mt32emu_close_synth(mt32emu_const_context context); /** Returns true if the synth is in completely initialized state, otherwise returns false. */ -MT32EMU_EXPORT mt32emu_boolean mt32emu_is_open(mt32emu_const_context context); +MT32EMU_EXPORT mt32emu_boolean MT32EMU_C_CALL mt32emu_is_open(mt32emu_const_context context); /** * Returns actual sample rate of the fully processed output stereo signal. * If samplerate conversion is used (i.e. when mt32emu_set_stereo_output_samplerate() has been invoked with a non-zero value), * the returned value is the desired output samplerate rounded down to the closest integer. - * Otherwise, the output samplerate is choosen depending on the emulation mode of stereo analog circuitry of hardware units. + * Otherwise, the output samplerate is chosen depending on the emulation mode of stereo analog circuitry of hardware units. * See comment for mt32emu_analog_output_mode for more info. */ -MT32EMU_EXPORT mt32emu_bit32u mt32emu_get_actual_stereo_output_samplerate(mt32emu_const_context context); +MT32EMU_EXPORT mt32emu_bit32u MT32EMU_C_CALL mt32emu_get_actual_stereo_output_samplerate(mt32emu_const_context context); /** * Returns the number of samples produced at the internal synth sample rate (32000 Hz) * that correspond to the given number of samples at the output sample rate. * Intended to facilitate audio time synchronisation. */ -MT32EMU_EXPORT mt32emu_bit32u mt32emu_convert_output_to_synth_timestamp(mt32emu_const_context context, mt32emu_bit32u output_timestamp); +MT32EMU_EXPORT mt32emu_bit32u MT32EMU_C_CALL mt32emu_convert_output_to_synth_timestamp(mt32emu_const_context context, mt32emu_bit32u output_timestamp); /** * Returns the number of samples produced at the output sample rate * that correspond to the given number of samples at the internal synth sample rate (32000 Hz). * Intended to facilitate audio time synchronisation. */ -MT32EMU_EXPORT mt32emu_bit32u mt32emu_convert_synth_to_output_timestamp(mt32emu_const_context context, mt32emu_bit32u synth_timestamp); +MT32EMU_EXPORT mt32emu_bit32u MT32EMU_C_CALL mt32emu_convert_synth_to_output_timestamp(mt32emu_const_context context, mt32emu_bit32u synth_timestamp); /** All the enqueued events are processed by the synth immediately. */ -MT32EMU_EXPORT void mt32emu_flush_midi_queue(mt32emu_const_context context); +MT32EMU_EXPORT void MT32EMU_C_CALL mt32emu_flush_midi_queue(mt32emu_const_context context); /** * Sets size of the internal MIDI event queue. The queue size is set to the minimum power of 2 that is greater or equal to the size specified. * The queue is flushed before reallocation. * Returns the actual queue size being used. */ -MT32EMU_EXPORT mt32emu_bit32u mt32emu_set_midi_event_queue_size(mt32emu_const_context context, const mt32emu_bit32u queue_size); +MT32EMU_EXPORT mt32emu_bit32u MT32EMU_C_CALL mt32emu_set_midi_event_queue_size(mt32emu_const_context context, const mt32emu_bit32u queue_size); /** * Configures the SysEx storage of the internal MIDI event queue. @@ -212,7 +300,7 @@ MT32EMU_EXPORT mt32emu_bit32u mt32emu_set_midi_event_queue_size(mt32emu_const_co * by a SysEx event, that has been processed and thus is no longer necessary, is disposed instantly. * Note, the queue is flushed and recreated in the process so that its size remains intact. */ -void mt32emu_configure_midi_event_queue_sysex_storage(mt32emu_const_context context, const mt32emu_bit32u storage_buffer_size); +MT32EMU_EXPORT void MT32EMU_C_CALL mt32emu_configure_midi_event_queue_sysex_storage(mt32emu_const_context context, const mt32emu_bit32u storage_buffer_size); /** * Installs custom MIDI receiver object intended for receiving MIDI messages generated by MIDI stream parser. @@ -220,13 +308,13 @@ void mt32emu_configure_midi_event_queue_sysex_storage(mt32emu_const_context cont * By default, parsed short MIDI messages and System Exclusive messages are sent to the synth input MIDI queue. * This function allows to override default behaviour. If midi_receiver argument is set to NULL, the default behaviour is restored. */ -MT32EMU_EXPORT void mt32emu_set_midi_receiver(mt32emu_context context, mt32emu_midi_receiver_i midi_receiver, void *instance_data); +MT32EMU_EXPORT void MT32EMU_C_CALL mt32emu_set_midi_receiver(mt32emu_context context, mt32emu_midi_receiver_i midi_receiver, void *instance_data); /** * Returns current value of the global counter of samples rendered since the synth was created (at the native sample rate 32000 Hz). * This method helps to compute accurate timestamp of a MIDI message to use with the methods below. */ -MT32EMU_EXPORT mt32emu_bit32u mt32emu_get_internal_rendered_sample_count(mt32emu_const_context context); +MT32EMU_EXPORT mt32emu_bit32u MT32EMU_C_CALL mt32emu_get_internal_rendered_sample_count(mt32emu_const_context context); /* Enqueues a MIDI event for subsequent playback. * The MIDI event will be processed not before the specified timestamp. @@ -243,7 +331,7 @@ MT32EMU_EXPORT mt32emu_bit32u mt32emu_get_internal_rendered_sample_count(mt32emu * When a System Realtime MIDI message is parsed, onMIDISystemRealtime callback is invoked. * NOTE: the total length of a SysEx message being fragmented shall not exceed MT32EMU_MAX_STREAM_BUFFER_SIZE (32768 bytes). */ -MT32EMU_EXPORT void mt32emu_parse_stream(mt32emu_const_context context, const mt32emu_bit8u *stream, mt32emu_bit32u length); +MT32EMU_EXPORT void MT32EMU_C_CALL mt32emu_parse_stream(mt32emu_const_context context, const mt32emu_bit8u *stream, mt32emu_bit32u length); /** * Parses a block of raw MIDI bytes and enqueues parsed MIDI messages to play at specified time. @@ -251,31 +339,31 @@ MT32EMU_EXPORT void mt32emu_parse_stream(mt32emu_const_context context, const mt * When a System Realtime MIDI message is parsed, onMIDISystemRealtime callback is invoked. * NOTE: the total length of a SysEx message being fragmented shall not exceed MT32EMU_MAX_STREAM_BUFFER_SIZE (32768 bytes). */ -MT32EMU_EXPORT void mt32emu_parse_stream_at(mt32emu_const_context context, const mt32emu_bit8u *stream, mt32emu_bit32u length, mt32emu_bit32u timestamp); +MT32EMU_EXPORT void MT32EMU_C_CALL mt32emu_parse_stream_at(mt32emu_const_context context, const mt32emu_bit8u *stream, mt32emu_bit32u length, mt32emu_bit32u timestamp); /** * Enqueues a single mt32emu_bit32u-encoded short MIDI message with full processing ASAP. * The short MIDI message may contain no status byte, the running status is used in this case. * When the argument is a System Realtime MIDI message, onMIDISystemRealtime callback is invoked. */ -MT32EMU_EXPORT void mt32emu_play_short_message(mt32emu_const_context context, mt32emu_bit32u message); +MT32EMU_EXPORT void MT32EMU_C_CALL mt32emu_play_short_message(mt32emu_const_context context, mt32emu_bit32u message); /** * Enqueues a single mt32emu_bit32u-encoded short MIDI message to play at specified time with full processing. * The short MIDI message may contain no status byte, the running status is used in this case. * When the argument is a System Realtime MIDI message, onMIDISystemRealtime callback is invoked. */ -MT32EMU_EXPORT void mt32emu_play_short_message_at(mt32emu_const_context context, mt32emu_bit32u message, mt32emu_bit32u timestamp); +MT32EMU_EXPORT void MT32EMU_C_CALL mt32emu_play_short_message_at(mt32emu_const_context context, mt32emu_bit32u message, mt32emu_bit32u timestamp); /** Enqueues a single short MIDI message to be processed ASAP. The message must contain a status byte. */ -MT32EMU_EXPORT mt32emu_return_code mt32emu_play_msg(mt32emu_const_context context, mt32emu_bit32u msg); +MT32EMU_EXPORT mt32emu_return_code MT32EMU_C_CALL mt32emu_play_msg(mt32emu_const_context context, mt32emu_bit32u msg); /** Enqueues a single well formed System Exclusive MIDI message to be processed ASAP. */ -MT32EMU_EXPORT mt32emu_return_code mt32emu_play_sysex(mt32emu_const_context context, const mt32emu_bit8u *sysex, mt32emu_bit32u len); +MT32EMU_EXPORT mt32emu_return_code MT32EMU_C_CALL mt32emu_play_sysex(mt32emu_const_context context, const mt32emu_bit8u *sysex, mt32emu_bit32u len); /** Enqueues a single short MIDI message to play at specified time. The message must contain a status byte. */ -MT32EMU_EXPORT mt32emu_return_code mt32emu_play_msg_at(mt32emu_const_context context, mt32emu_bit32u msg, mt32emu_bit32u timestamp); +MT32EMU_EXPORT mt32emu_return_code MT32EMU_C_CALL mt32emu_play_msg_at(mt32emu_const_context context, mt32emu_bit32u msg, mt32emu_bit32u timestamp); /** Enqueues a single well formed System Exclusive MIDI message to play at specified time. */ -MT32EMU_EXPORT mt32emu_return_code mt32emu_play_sysex_at(mt32emu_const_context context, const mt32emu_bit8u *sysex, mt32emu_bit32u len, mt32emu_bit32u timestamp); +MT32EMU_EXPORT mt32emu_return_code MT32EMU_C_CALL mt32emu_play_sysex_at(mt32emu_const_context context, const mt32emu_bit8u *sysex, mt32emu_bit32u len, mt32emu_bit32u timestamp); /* WARNING: * The methods below don't ensure minimum 1-sample delay between sequential MIDI events, @@ -287,73 +375,73 @@ MT32EMU_EXPORT mt32emu_return_code mt32emu_play_sysex_at(mt32emu_const_context c * Sends a short MIDI message to the synth for immediate playback. The message must contain a status byte. * See the WARNING above. */ -MT32EMU_EXPORT void mt32emu_play_msg_now(mt32emu_const_context context, mt32emu_bit32u msg); +MT32EMU_EXPORT void MT32EMU_C_CALL mt32emu_play_msg_now(mt32emu_const_context context, mt32emu_bit32u msg); /** * Sends unpacked short MIDI message to the synth for immediate playback. The message must contain a status byte. * See the WARNING above. */ -MT32EMU_EXPORT void mt32emu_play_msg_on_part(mt32emu_const_context context, mt32emu_bit8u part, mt32emu_bit8u code, mt32emu_bit8u note, mt32emu_bit8u velocity); +MT32EMU_EXPORT void MT32EMU_C_CALL mt32emu_play_msg_on_part(mt32emu_const_context context, mt32emu_bit8u part, mt32emu_bit8u code, mt32emu_bit8u note, mt32emu_bit8u velocity); /** * Sends a single well formed System Exclusive MIDI message for immediate processing. The length is in bytes. * See the WARNING above. */ -MT32EMU_EXPORT void mt32emu_play_sysex_now(mt32emu_const_context context, const mt32emu_bit8u *sysex, mt32emu_bit32u len); +MT32EMU_EXPORT void MT32EMU_C_CALL mt32emu_play_sysex_now(mt32emu_const_context context, const mt32emu_bit8u *sysex, mt32emu_bit32u len); /** * Sends inner body of a System Exclusive MIDI message for direct processing. The length is in bytes. * See the WARNING above. */ -MT32EMU_EXPORT void mt32emu_write_sysex(mt32emu_const_context context, mt32emu_bit8u channel, const mt32emu_bit8u *sysex, mt32emu_bit32u len); +MT32EMU_EXPORT void MT32EMU_C_CALL mt32emu_write_sysex(mt32emu_const_context context, mt32emu_bit8u channel, const mt32emu_bit8u *sysex, mt32emu_bit32u len); /** Allows to disable wet reverb output altogether. */ -MT32EMU_EXPORT void mt32emu_set_reverb_enabled(mt32emu_const_context context, const mt32emu_boolean reverb_enabled); +MT32EMU_EXPORT void MT32EMU_C_CALL mt32emu_set_reverb_enabled(mt32emu_const_context context, const mt32emu_boolean reverb_enabled); /** Returns whether wet reverb output is enabled. */ -MT32EMU_EXPORT mt32emu_boolean mt32emu_is_reverb_enabled(mt32emu_const_context context); +MT32EMU_EXPORT mt32emu_boolean MT32EMU_C_CALL mt32emu_is_reverb_enabled(mt32emu_const_context context); /** * Sets override reverb mode. In this mode, emulation ignores sysexes (or the related part of them) which control the reverb parameters. * This mode is in effect until it is turned off. When the synth is re-opened, the override mode is unchanged but the state * of the reverb model is reset to default. */ -MT32EMU_EXPORT void mt32emu_set_reverb_overridden(mt32emu_const_context context, const mt32emu_boolean reverb_overridden); +MT32EMU_EXPORT void MT32EMU_C_CALL mt32emu_set_reverb_overridden(mt32emu_const_context context, const mt32emu_boolean reverb_overridden); /** Returns whether reverb settings are overridden. */ -MT32EMU_EXPORT mt32emu_boolean mt32emu_is_reverb_overridden(mt32emu_const_context context); +MT32EMU_EXPORT mt32emu_boolean MT32EMU_C_CALL mt32emu_is_reverb_overridden(mt32emu_const_context context); /** * Forces reverb model compatibility mode. By default, the compatibility mode corresponds to the used control ROM version. * Invoking this method with the argument set to true forces emulation of old MT-32 reverb circuit. * When the argument is false, emulation of the reverb circuit used in new generation of MT-32 compatible modules is enforced * (these include CM-32L and LAPC-I). */ -MT32EMU_EXPORT void mt32emu_set_reverb_compatibility_mode(mt32emu_const_context context, const mt32emu_boolean mt32_compatible_mode); +MT32EMU_EXPORT void MT32EMU_C_CALL mt32emu_set_reverb_compatibility_mode(mt32emu_const_context context, const mt32emu_boolean mt32_compatible_mode); /** Returns whether reverb is in old MT-32 compatibility mode. */ -MT32EMU_EXPORT mt32emu_boolean mt32emu_is_mt32_reverb_compatibility_mode(mt32emu_const_context context); +MT32EMU_EXPORT mt32emu_boolean MT32EMU_C_CALL mt32emu_is_mt32_reverb_compatibility_mode(mt32emu_const_context context); /** Returns whether default reverb compatibility mode is the old MT-32 compatibility mode. */ -MT32EMU_EXPORT mt32emu_boolean mt32emu_is_default_reverb_mt32_compatible(mt32emu_const_context context); +MT32EMU_EXPORT mt32emu_boolean MT32EMU_C_CALL mt32emu_is_default_reverb_mt32_compatible(mt32emu_const_context context); /** - * If enabled, reverb buffers for all modes are keept around allocated all the time to avoid memory + * If enabled, reverb buffers for all modes are kept around allocated all the time to avoid memory * allocating/freeing in the rendering thread, which may be required for realtime operation. * Otherwise, reverb buffers that are not in use are deleted to save memory (the default behaviour). */ -MT32EMU_EXPORT void mt32emu_preallocate_reverb_memory(mt32emu_const_context context, const mt32emu_boolean enabled); +MT32EMU_EXPORT void MT32EMU_C_CALL mt32emu_preallocate_reverb_memory(mt32emu_const_context context, const mt32emu_boolean enabled); /** Sets new DAC input mode. See mt32emu_dac_input_mode for details. */ -MT32EMU_EXPORT void mt32emu_set_dac_input_mode(mt32emu_const_context context, const mt32emu_dac_input_mode mode); +MT32EMU_EXPORT void MT32EMU_C_CALL mt32emu_set_dac_input_mode(mt32emu_const_context context, const mt32emu_dac_input_mode mode); /** Returns current DAC input mode. See mt32emu_dac_input_mode for details. */ -MT32EMU_EXPORT mt32emu_dac_input_mode mt32emu_get_dac_input_mode(mt32emu_const_context context); +MT32EMU_EXPORT mt32emu_dac_input_mode MT32EMU_C_CALL mt32emu_get_dac_input_mode(mt32emu_const_context context); /** Sets new MIDI delay mode. See mt32emu_midi_delay_mode for details. */ -MT32EMU_EXPORT void mt32emu_set_midi_delay_mode(mt32emu_const_context context, const mt32emu_midi_delay_mode mode); +MT32EMU_EXPORT void MT32EMU_C_CALL mt32emu_set_midi_delay_mode(mt32emu_const_context context, const mt32emu_midi_delay_mode mode); /** Returns current MIDI delay mode. See mt32emu_midi_delay_mode for details. */ -MT32EMU_EXPORT mt32emu_midi_delay_mode mt32emu_get_midi_delay_mode(mt32emu_const_context context); +MT32EMU_EXPORT mt32emu_midi_delay_mode MT32EMU_C_CALL mt32emu_get_midi_delay_mode(mt32emu_const_context context); /** * Sets output gain factor for synth output channels. Applied to all output samples and unrelated with the synth's Master volume, * it rather corresponds to the gain of the output analog circuitry of the hardware units. However, together with mt32emu_set_reverb_output_gain() * it offers to the user a capability to control the gain of reverb and non-reverb output channels independently. */ -MT32EMU_EXPORT void mt32emu_set_output_gain(mt32emu_const_context context, float gain); +MT32EMU_EXPORT void MT32EMU_C_CALL mt32emu_set_output_gain(mt32emu_const_context context, float gain); /** Returns current output gain factor for synth output channels. */ -MT32EMU_EXPORT float mt32emu_get_output_gain(mt32emu_const_context context); +MT32EMU_EXPORT float MT32EMU_C_CALL mt32emu_get_output_gain(mt32emu_const_context context); /** * Sets output gain factor for the reverb wet output channels. It rather corresponds to the gain of the output @@ -365,14 +453,34 @@ MT32EMU_EXPORT float mt32emu_get_output_gain(mt32emu_const_context context); * there is a difference in the reverb analogue circuit, and the resulting output gain is 0.68 * of that for LA32 analogue output. This factor is applied to the reverb output gain. */ -MT32EMU_EXPORT void mt32emu_set_reverb_output_gain(mt32emu_const_context context, float gain); +MT32EMU_EXPORT void MT32EMU_C_CALL mt32emu_set_reverb_output_gain(mt32emu_const_context context, float gain); /** Returns current output gain factor for reverb wet output channels. */ -MT32EMU_EXPORT float mt32emu_get_reverb_output_gain(mt32emu_const_context context); +MT32EMU_EXPORT float MT32EMU_C_CALL mt32emu_get_reverb_output_gain(mt32emu_const_context context); + +/** + * Sets (or removes) an override for the current volume (output level) on a specific part. + * When the part volume is overridden, the MIDI controller Volume (7) on the MIDI channel this part is assigned to + * has no effect on the output level of this part. Similarly, the output level value set on this part via a SysEx that + * modifies the Patch temp structure is disregarded. + * To enable the override mode, argument volumeOverride should be in range 0..100, setting a value outside this range + * disables the previously set override, if any. + * Note: Setting volumeOverride to 0 mutes the part completely, meaning no sound is generated at all. + * This is unlike the behaviour of real devices - setting 0 volume on a part may leave it still producing + * sound at a very low level. + * Argument partNumber should be 0..7 for Part 1..8, or 8 for Rhythm. + */ +MT32EMU_EXPORT_V(2.6) void MT32EMU_C_CALL mt32emu_set_part_volume_override(mt32emu_const_context context, mt32emu_bit8u part_number, mt32emu_bit8u volume_override); +/** + * Returns the overridden volume previously set on a specific part; a value outside the range 0..100 means no override + * is currently in effect. + * Argument partNumber should be 0..7 for Part 1..8, or 8 for Rhythm. + */ +MT32EMU_EXPORT_V(2.6) mt32emu_bit8u MT32EMU_C_CALL mt32emu_get_part_volume_override(mt32emu_const_context context, mt32emu_bit8u part_number); /** Swaps left and right output channels. */ -MT32EMU_EXPORT void mt32emu_set_reversed_stereo_enabled(mt32emu_const_context context, const mt32emu_boolean enabled); +MT32EMU_EXPORT void MT32EMU_C_CALL mt32emu_set_reversed_stereo_enabled(mt32emu_const_context context, const mt32emu_boolean enabled); /** Returns whether left and right output channels are swapped. */ -MT32EMU_EXPORT mt32emu_boolean mt32emu_is_reversed_stereo_enabled(mt32emu_const_context context); +MT32EMU_EXPORT mt32emu_boolean MT32EMU_C_CALL mt32emu_is_reversed_stereo_enabled(mt32emu_const_context context); /** * Allows to toggle the NiceAmpRamp mode. @@ -382,9 +490,9 @@ MT32EMU_EXPORT mt32emu_boolean mt32emu_is_reversed_stereo_enabled(mt32emu_const_ * We also prefer the quality improvement over the emulation accuracy, * so this mode is enabled by default. */ -MT32EMU_EXPORT void mt32emu_set_nice_amp_ramp_enabled(mt32emu_const_context context, const mt32emu_boolean enabled); +MT32EMU_EXPORT void MT32EMU_C_CALL mt32emu_set_nice_amp_ramp_enabled(mt32emu_const_context context, const mt32emu_boolean enabled); /** Returns whether NiceAmpRamp mode is enabled. */ -MT32EMU_EXPORT mt32emu_boolean mt32emu_is_nice_amp_ramp_enabled(mt32emu_const_context context); +MT32EMU_EXPORT mt32emu_boolean MT32EMU_C_CALL mt32emu_is_nice_amp_ramp_enabled(mt32emu_const_context context); /** * Allows to toggle the NicePanning mode. @@ -395,9 +503,9 @@ MT32EMU_EXPORT mt32emu_boolean mt32emu_is_nice_amp_ramp_enabled(mt32emu_const_co * making it smoother thus sacrificing the emulation accuracy. * This mode is disabled by default. */ -MT32EMU_EXPORT void mt32emu_set_nice_panning_enabled(mt32emu_const_context context, const mt32emu_boolean enabled); +MT32EMU_EXPORT void MT32EMU_C_CALL mt32emu_set_nice_panning_enabled(mt32emu_const_context context, const mt32emu_boolean enabled); /** Returns whether NicePanning mode is enabled. */ -MT32EMU_EXPORT mt32emu_boolean mt32emu_is_nice_panning_enabled(mt32emu_const_context context); +MT32EMU_EXPORT mt32emu_boolean MT32EMU_C_CALL mt32emu_is_nice_panning_enabled(mt32emu_const_context context); /** * Allows to toggle the NicePartialMixing mode. @@ -409,9 +517,9 @@ MT32EMU_EXPORT mt32emu_boolean mt32emu_is_nice_panning_enabled(mt32emu_const_con * thus making the behaviour more predictable. * This mode is disabled by default. */ -MT32EMU_EXPORT void mt32emu_set_nice_partial_mixing_enabled(mt32emu_const_context context, const mt32emu_boolean enabled); +MT32EMU_EXPORT void MT32EMU_C_CALL mt32emu_set_nice_partial_mixing_enabled(mt32emu_const_context context, const mt32emu_boolean enabled); /** Returns whether NicePartialMixing mode is enabled. */ -MT32EMU_EXPORT mt32emu_boolean mt32emu_is_nice_partial_mixing_enabled(mt32emu_const_context context); +MT32EMU_EXPORT mt32emu_boolean MT32EMU_C_CALL mt32emu_is_nice_partial_mixing_enabled(mt32emu_const_context context); /** * Renders samples to the specified output stream as if they were sampled at the analog stereo output at the desired sample rate. @@ -419,9 +527,9 @@ MT32EMU_EXPORT mt32emu_boolean mt32emu_is_nice_partial_mixing_enabled(mt32emu_co * mode of analog circuitry emulation. See mt32emu_analog_output_mode. * The length is in frames, not bytes (in 16-bit stereo, one frame is 4 bytes). Uses NATIVE byte ordering. */ -MT32EMU_EXPORT void mt32emu_render_bit16s(mt32emu_const_context context, mt32emu_bit16s *stream, mt32emu_bit32u len); +MT32EMU_EXPORT void MT32EMU_C_CALL mt32emu_render_bit16s(mt32emu_const_context context, mt32emu_bit16s *stream, mt32emu_bit32u len); /** Same as above but outputs to a float stereo stream. */ -MT32EMU_EXPORT void mt32emu_render_float(mt32emu_const_context context, float *stream, mt32emu_bit32u len); +MT32EMU_EXPORT void MT32EMU_C_CALL mt32emu_render_float(mt32emu_const_context context, float *stream, mt32emu_bit32u len); /** * Renders samples to the specified output streams as if they appeared at the DAC entrance. @@ -429,25 +537,25 @@ MT32EMU_EXPORT void mt32emu_render_float(mt32emu_const_context context, float *s * NULL may be specified in place of any or all of the stream buffers to skip it. * The length is in samples, not bytes. Uses NATIVE byte ordering. */ -MT32EMU_EXPORT void mt32emu_render_bit16s_streams(mt32emu_const_context context, const mt32emu_dac_output_bit16s_streams *streams, mt32emu_bit32u len); +MT32EMU_EXPORT void MT32EMU_C_CALL mt32emu_render_bit16s_streams(mt32emu_const_context context, const mt32emu_dac_output_bit16s_streams *streams, mt32emu_bit32u len); /** Same as above but outputs to float streams. */ -MT32EMU_EXPORT void mt32emu_render_float_streams(mt32emu_const_context context, const mt32emu_dac_output_float_streams *streams, mt32emu_bit32u len); +MT32EMU_EXPORT void MT32EMU_C_CALL mt32emu_render_float_streams(mt32emu_const_context context, const mt32emu_dac_output_float_streams *streams, mt32emu_bit32u len); /** Returns true when there is at least one active partial, otherwise false. */ -MT32EMU_EXPORT mt32emu_boolean mt32emu_has_active_partials(mt32emu_const_context context); +MT32EMU_EXPORT mt32emu_boolean MT32EMU_C_CALL mt32emu_has_active_partials(mt32emu_const_context context); /** Returns true if mt32emu_has_active_partials() returns true, or reverb is (somewhat unreliably) detected as being active. */ -MT32EMU_EXPORT mt32emu_boolean mt32emu_is_active(mt32emu_const_context context); +MT32EMU_EXPORT mt32emu_boolean MT32EMU_C_CALL mt32emu_is_active(mt32emu_const_context context); /** Returns the maximum number of partials playing simultaneously. */ -MT32EMU_EXPORT mt32emu_bit32u mt32emu_get_partial_count(mt32emu_const_context context); +MT32EMU_EXPORT mt32emu_bit32u MT32EMU_C_CALL mt32emu_get_partial_count(mt32emu_const_context context); /** * Returns current states of all the parts as a bit set. The least significant bit corresponds to the state of part 1, * total of 9 bits hold the states of all the parts. If the returned bit for a part is set, there is at least one active * non-releasing partial playing on this part. This info is useful in emulating behaviour of LCD display of the hardware units. */ -MT32EMU_EXPORT mt32emu_bit32u mt32emu_get_part_states(mt32emu_const_context context); +MT32EMU_EXPORT mt32emu_bit32u MT32EMU_C_CALL mt32emu_get_part_states(mt32emu_const_context context); /** * Fills in current states of all the partials into the array provided. Each byte in the array holds states of 4 partials @@ -455,7 +563,7 @@ MT32EMU_EXPORT mt32emu_bit32u mt32emu_get_part_states(mt32emu_const_context cont * The array must be large enough to accommodate states of all the partials. * @see getPartialCount() */ -MT32EMU_EXPORT void mt32emu_get_partial_states(mt32emu_const_context context, mt32emu_bit8u *partial_states); +MT32EMU_EXPORT void MT32EMU_C_CALL mt32emu_get_partial_states(mt32emu_const_context context, mt32emu_bit8u *partial_states); /** * Fills in information about currently playing notes on the specified part into the arrays provided. The arrays must be large enough @@ -463,16 +571,71 @@ MT32EMU_EXPORT void mt32emu_get_partial_states(mt32emu_const_context context, mt * Argument partNumber should be 0..7 for Part 1..8, or 8 for Rhythm. * Returns the number of currently playing notes on the specified part. */ -MT32EMU_EXPORT mt32emu_bit32u mt32emu_get_playing_notes(mt32emu_const_context context, mt32emu_bit8u part_number, mt32emu_bit8u *keys, mt32emu_bit8u *velocities); +MT32EMU_EXPORT mt32emu_bit32u MT32EMU_C_CALL mt32emu_get_playing_notes(mt32emu_const_context context, mt32emu_bit8u part_number, mt32emu_bit8u *keys, mt32emu_bit8u *velocities); /** * Returns name of the patch set on the specified part. * Argument partNumber should be 0..7 for Part 1..8, or 8 for Rhythm. + * The returned value is a null-terminated string which is guaranteed to remain valid until the next call to one of functions + * that perform sample rendering or immediate SysEx processing (e.g. mt32emu_play_sysex_now). */ -MT32EMU_EXPORT const char *mt32emu_get_patch_name(mt32emu_const_context context, mt32emu_bit8u part_number); +MT32EMU_EXPORT const char * MT32EMU_C_CALL mt32emu_get_patch_name(mt32emu_const_context context, mt32emu_bit8u part_number); + +/** + * Retrieves the name of the sound group the timbre identified by arguments timbre_group and timbre_number is associated with. + * Values 0-3 of timbre_group correspond to the timbre banks GROUP A, GROUP B, MEMORY and RHYTHM. + * For all but the RHYTHM timbre bank, allowed values of timbre_number are in range 0-63. The number of timbres + * contained in the RHYTHM bank depends on the used control ROM version. + * The argument sound_group_name must point to an array of at least 8 characters. The result is a null-terminated string. + * Returns whether the specified timbre has been found and the result written in sound_group_name. + */ +MT32EMU_EXPORT_V(2.7) mt32emu_boolean MT32EMU_C_CALL mt32emu_get_sound_group_name(mt32emu_const_context context, char *sound_group_name, mt32emu_bit8u timbre_group, mt32emu_bit8u timbre_number); +/** + * Retrieves the name of the timbre identified by arguments timbre_group and timbre_number. + * Values 0-3 of timbre_group correspond to the timbre banks GROUP A, GROUP B, MEMORY and RHYTHM. + * For all but the RHYTHM timbre bank, allowed values of timbre_number are in range 0-63. The number of timbres + * contained in the RHYTHM bank depends on the used control ROM version. + * The argument sound_name must point to an array of at least 11 characters. The result is a null-terminated string. + * Returns whether the specified timbre has been found and the result written in sound_name. + */ +MT32EMU_EXPORT_V(2.7) mt32emu_boolean MT32EMU_C_CALL mt32emu_get_sound_name(mt32emu_const_context context, char *sound_name, mt32emu_bit8u timbreGroup, mt32emu_bit8u timbreNumber); /** Stores internal state of emulated synth into an array provided (as it would be acquired from hardware). */ -MT32EMU_EXPORT void mt32emu_read_memory(mt32emu_const_context context, mt32emu_bit32u addr, mt32emu_bit32u len, mt32emu_bit8u *data); +MT32EMU_EXPORT void MT32EMU_C_CALL mt32emu_read_memory(mt32emu_const_context context, mt32emu_bit32u addr, mt32emu_bit32u len, mt32emu_bit8u *data); + +/** + * Retrieves the current state of the emulated MT-32 display facilities. + * Typically, the state is updated during the rendering. When that happens, a related callback from mt32emu_report_handler_i_v1 + * is invoked. However, there might be no need to invoke this method after each update, e.g. when the render buffer is just + * a few milliseconds long. + * The argument target_buffer must point to an array of at least 21 characters. The result is a null-terminated string. + * The argument narrow_lcd enables a condensed representation of the displayed information in some cases. This is mainly intended + * to route the result to a hardware LCD that is only 16 characters wide. Automatic scrolling of longer strings is not supported. + * Returns whether the MIDI MESSAGE LED is ON and fills the target_buffer parameter. + */ +MT32EMU_EXPORT_V(2.6) mt32emu_boolean MT32EMU_C_CALL mt32emu_get_display_state(mt32emu_const_context context, char *target_buffer, const mt32emu_boolean narrow_lcd); + +/** + * Resets the emulated LCD to the main mode (Master Volume). This has the same effect as pressing the Master Volume button + * while the display shows some other message. Useful for the new-gen devices as those require a special Display Reset SysEx + * to return to the main mode e.g. from showing a custom display message or a checksum error. + */ +MT32EMU_EXPORT_V(2.6) void MT32EMU_C_CALL mt32emu_set_main_display_mode(mt32emu_const_context context); + +/** + * Permits to select an arbitrary display emulation model that does not necessarily match the actual behaviour implemented + * in the control ROM version being used. + * Invoking this method with the argument set to true forces emulation of the old-gen MT-32 display features. + * Otherwise, emulation of the new-gen devices is enforced (these include CM-32L and LAPC-I as if these were connected to an LCD). + */ +MT32EMU_EXPORT_V(2.6) void MT32EMU_C_CALL mt32emu_set_display_compatibility(mt32emu_const_context context, mt32emu_boolean old_mt32_compatibility_enabled); +/** Returns whether the currently configured features of the emulated display are compatible with the old-gen MT-32 devices. */ +MT32EMU_EXPORT_V(2.6) mt32emu_boolean MT32EMU_C_CALL mt32emu_is_display_old_mt32_compatible(mt32emu_const_context context); +/** + * Returns whether the emulated display features configured by default depending on the actual control ROM version + * are compatible with the old-gen MT-32 devices. + */ +MT32EMU_EXPORT_V(2.6) mt32emu_boolean MT32EMU_C_CALL mt32emu_is_default_display_old_mt32_compatible(mt32emu_const_context context); #ifdef __cplusplus } // extern "C" diff --git a/src/sound/munt/c_interface/c_types.h b/src/sound/munt/c_interface/c_types.h index 74bae8df4..8928bfeae 100644 --- a/src/sound/munt/c_interface/c_types.h +++ b/src/sound/munt/c_interface/c_types.h @@ -1,5 +1,5 @@ /* Copyright (C) 2003, 2004, 2005, 2006, 2008, 2009 Dean Beeler, Jerome Fisher - * Copyright (C) 2011-2020 Dean Beeler, Jerome Fisher, Sergey V. Mikayev + * Copyright (C) 2011-2022 Dean Beeler, Jerome Fisher, Sergey V. Mikayev * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by @@ -27,6 +27,12 @@ #include "../Enumerations.h" #undef MT32EMU_C_ENUMERATIONS +#ifdef _WIN32 +# define MT32EMU_C_CALL __cdecl +#else +# define MT32EMU_C_CALL +#endif + typedef unsigned int mt32emu_bit32u; typedef signed int mt32emu_bit32s; typedef unsigned short int mt32emu_bit16u; @@ -45,6 +51,8 @@ typedef enum { MT32EMU_RC_OK = 0, MT32EMU_RC_ADDED_CONTROL_ROM = 1, MT32EMU_RC_ADDED_PCM_ROM = 2, + MT32EMU_RC_ADDED_PARTIAL_CONTROL_ROM = 3, + MT32EMU_RC_ADDED_PARTIAL_PCM_ROM = 4, /* Definite error occurred. */ MT32EMU_RC_ROM_NOT_IDENTIFIED = -1, @@ -53,6 +61,8 @@ typedef enum { MT32EMU_RC_MISSING_ROMS = -4, MT32EMU_RC_NOT_OPENED = -5, MT32EMU_RC_QUEUE_FULL = -6, + MT32EMU_RC_ROMS_NOT_PAIRABLE = -7, + MT32EMU_RC_MACHINE_NOT_IDENTIFIED = -8, /* Undefined error occurred. */ MT32EMU_RC_FAILED = -100 @@ -107,7 +117,8 @@ typedef struct { /** Report handler interface versions */ typedef enum { MT32EMU_REPORT_HANDLER_VERSION_0 = 0, - MT32EMU_REPORT_HANDLER_VERSION_CURRENT = MT32EMU_REPORT_HANDLER_VERSION_0 + MT32EMU_REPORT_HANDLER_VERSION_1 = 1, + MT32EMU_REPORT_HANDLER_VERSION_CURRENT = MT32EMU_REPORT_HANDLER_VERSION_1 } mt32emu_report_handler_version; /** MIDI receiver interface versions */ @@ -122,7 +133,10 @@ typedef enum { MT32EMU_SERVICE_VERSION_1 = 1, MT32EMU_SERVICE_VERSION_2 = 2, MT32EMU_SERVICE_VERSION_3 = 3, - MT32EMU_SERVICE_VERSION_CURRENT = MT32EMU_SERVICE_VERSION_3 + MT32EMU_SERVICE_VERSION_4 = 4, + MT32EMU_SERVICE_VERSION_5 = 5, + MT32EMU_SERVICE_VERSION_6 = 6, + MT32EMU_SERVICE_VERSION_CURRENT = MT32EMU_SERVICE_VERSION_6 } mt32emu_service_version; /* === Report Handler Interface === */ @@ -130,42 +144,59 @@ typedef enum { typedef union mt32emu_report_handler_i mt32emu_report_handler_i; /** Interface for handling reported events (initial version) */ -typedef struct { - /** Returns the actual interface version ID */ - mt32emu_report_handler_version (*getVersionID)(mt32emu_report_handler_i i); - - /** Callback for debug messages, in vprintf() format */ - void (*printDebug)(void *instance_data, const char *fmt, va_list list); - /** Callbacks for reporting errors */ - void (*onErrorControlROM)(void *instance_data); - void (*onErrorPCMROM)(void *instance_data); - /** Callback for reporting about displaying a new custom message on LCD */ - void (*showLCDMessage)(void *instance_data, const char *message); - /** Callback for reporting actual processing of a MIDI message */ - void (*onMIDIMessagePlayed)(void *instance_data); +#define MT32EMU_REPORT_HANDLER_I_V0 \ + /** Returns the actual interface version ID */ \ + mt32emu_report_handler_version (MT32EMU_C_CALL *getVersionID)(mt32emu_report_handler_i i); \ +\ + /** Callback for debug messages, in vprintf() format */ \ + void (MT32EMU_C_CALL *printDebug)(void *instance_data, const char *fmt, va_list list); \ + /** Callbacks for reporting errors */ \ + void (MT32EMU_C_CALL *onErrorControlROM)(void *instance_data); \ + void (MT32EMU_C_CALL *onErrorPCMROM)(void *instance_data); \ + /** Callback for reporting about displaying a new custom message on LCD */ \ + void (MT32EMU_C_CALL *showLCDMessage)(void *instance_data, const char *message); \ + /** Callback for reporting actual processing of a MIDI message */ \ + void (MT32EMU_C_CALL *onMIDIMessagePlayed)(void *instance_data); \ /** * Callback for reporting an overflow of the input MIDI queue. * Returns MT32EMU_BOOL_TRUE if a recovery action was taken * and yet another attempt to enqueue the MIDI event is desired. - */ - mt32emu_boolean (*onMIDIQueueOverflow)(void *instance_data); + */ \ + mt32emu_boolean (MT32EMU_C_CALL *onMIDIQueueOverflow)(void *instance_data); \ /** * Callback invoked when a System Realtime MIDI message is detected in functions * mt32emu_parse_stream and mt32emu_play_short_message and the likes. - */ - void (*onMIDISystemRealtime)(void *instance_data, mt32emu_bit8u system_realtime); - /** Callbacks for reporting system events */ - void (*onDeviceReset)(void *instance_data); - void (*onDeviceReconfig)(void *instance_data); - /** Callbacks for reporting changes of reverb settings */ - void (*onNewReverbMode)(void *instance_data, mt32emu_bit8u mode); - void (*onNewReverbTime)(void *instance_data, mt32emu_bit8u time); - void (*onNewReverbLevel)(void *instance_data, mt32emu_bit8u level); - /** Callbacks for reporting various information */ - void (*onPolyStateChanged)(void *instance_data, mt32emu_bit8u part_num); - void (*onProgramChanged)(void *instance_data, mt32emu_bit8u part_num, const char *sound_group_name, const char *patch_name); + */ \ + void (MT32EMU_C_CALL *onMIDISystemRealtime)(void *instance_data, mt32emu_bit8u system_realtime); \ + /** Callbacks for reporting system events */ \ + void (MT32EMU_C_CALL *onDeviceReset)(void *instance_data); \ + void (MT32EMU_C_CALL *onDeviceReconfig)(void *instance_data); \ + /** Callbacks for reporting changes of reverb settings */ \ + void (MT32EMU_C_CALL *onNewReverbMode)(void *instance_data, mt32emu_bit8u mode); \ + void (MT32EMU_C_CALL *onNewReverbTime)(void *instance_data, mt32emu_bit8u time); \ + void (MT32EMU_C_CALL *onNewReverbLevel)(void *instance_data, mt32emu_bit8u level); \ + /** Callbacks for reporting various information */ \ + void (MT32EMU_C_CALL *onPolyStateChanged)(void *instance_data, mt32emu_bit8u part_num); \ + void (MT32EMU_C_CALL *onProgramChanged)(void *instance_data, mt32emu_bit8u part_num, const char *sound_group_name, const char *patch_name); + +#define MT32EMU_REPORT_HANDLER_I_V1 \ + /** + * Invoked to signal about a change of the emulated LCD state. Use mt32emu_get_display_state to retrieve the actual data. + * This callback will not be invoked on further changes, until the client retrieves the LCD state. + */ \ + void (MT32EMU_C_CALL *onLCDStateUpdated)(void *instance_data); \ + /** Invoked when the emulated MIDI MESSAGE LED changes state. The led_state parameter represents whether the LED is ON. */ \ + void (MT32EMU_C_CALL *onMidiMessageLEDStateUpdated)(void *instance_data, mt32emu_boolean led_state); + +typedef struct { + MT32EMU_REPORT_HANDLER_I_V0 } mt32emu_report_handler_i_v0; +typedef struct { + MT32EMU_REPORT_HANDLER_I_V0 + MT32EMU_REPORT_HANDLER_I_V1 +} mt32emu_report_handler_i_v1; + /** * Extensible interface for handling reported events. * Union intended to view an interface of any subsequent version as any parent interface not requiring a cast. @@ -173,8 +204,12 @@ typedef struct { */ union mt32emu_report_handler_i { const mt32emu_report_handler_i_v0 *v0; + const mt32emu_report_handler_i_v1 *v1; }; +#undef MT32EMU_REPORT_HANDLER_I_V0 +#undef MT32EMU_REPORT_HANDLER_I_V1 + /* === MIDI Receiver Interface === */ typedef union mt32emu_midi_receiver_i mt32emu_midi_receiver_i; @@ -182,16 +217,16 @@ typedef union mt32emu_midi_receiver_i mt32emu_midi_receiver_i; /** Interface for receiving MIDI messages generated by MIDI stream parser (initial version) */ typedef struct { /** Returns the actual interface version ID */ - mt32emu_midi_receiver_version (*getVersionID)(mt32emu_midi_receiver_i i); + mt32emu_midi_receiver_version (MT32EMU_C_CALL *getVersionID)(mt32emu_midi_receiver_i i); /** Invoked when a complete short MIDI message is parsed in the input MIDI stream. */ - void (*handleShortMessage)(void *instance_data, const mt32emu_bit32u message); + void (MT32EMU_C_CALL *handleShortMessage)(void *instance_data, const mt32emu_bit32u message); /** Invoked when a complete well-formed System Exclusive MIDI message is parsed in the input MIDI stream. */ - void (*handleSysex)(void *instance_data, const mt32emu_bit8u stream[], const mt32emu_bit32u length); + void (MT32EMU_C_CALL *handleSysex)(void *instance_data, const mt32emu_bit8u stream[], const mt32emu_bit32u length); /** Invoked when a System Realtime MIDI message is parsed in the input MIDI stream. */ - void (*handleSystemRealtimeMessage)(void *instance_data, const mt32emu_bit8u realtime); + void (MT32EMU_C_CALL *handleSystemRealtimeMessage)(void *instance_data, const mt32emu_bit8u realtime); } mt32emu_midi_receiver_i_v0; /** @@ -216,101 +251,124 @@ typedef union mt32emu_service_i mt32emu_service_i; */ #define MT32EMU_SERVICE_I_V0 \ /** Returns the actual interface version ID */ \ - mt32emu_service_version (*getVersionID)(mt32emu_service_i i); \ - mt32emu_report_handler_version (*getSupportedReportHandlerVersionID)(void); \ - mt32emu_midi_receiver_version (*getSupportedMIDIReceiverVersionID)(void); \ + mt32emu_service_version (MT32EMU_C_CALL *getVersionID)(mt32emu_service_i i); \ + mt32emu_report_handler_version (MT32EMU_C_CALL *getSupportedReportHandlerVersionID)(void); \ + mt32emu_midi_receiver_version (MT32EMU_C_CALL *getSupportedMIDIReceiverVersionID)(void); \ \ - mt32emu_bit32u (*getLibraryVersionInt)(void); \ - const char *(*getLibraryVersionString)(void); \ + mt32emu_bit32u (MT32EMU_C_CALL *getLibraryVersionInt)(void); \ + const char *(MT32EMU_C_CALL *getLibraryVersionString)(void); \ \ - mt32emu_bit32u (*getStereoOutputSamplerate)(const mt32emu_analog_output_mode analog_output_mode); \ + mt32emu_bit32u (MT32EMU_C_CALL *getStereoOutputSamplerate)(const mt32emu_analog_output_mode analog_output_mode); \ \ - mt32emu_context (*createContext)(mt32emu_report_handler_i report_handler, void *instance_data); \ - void (*freeContext)(mt32emu_context context); \ - mt32emu_return_code (*addROMData)(mt32emu_context context, const mt32emu_bit8u *data, size_t data_size, const mt32emu_sha1_digest *sha1_digest); \ - mt32emu_return_code (*addROMFile)(mt32emu_context context, const char *filename); \ - void (*getROMInfo)(mt32emu_const_context context, mt32emu_rom_info *rom_info); \ - void (*setPartialCount)(mt32emu_context context, const mt32emu_bit32u partial_count); \ - void (*setAnalogOutputMode)(mt32emu_context context, const mt32emu_analog_output_mode analog_output_mode); \ - mt32emu_return_code (*openSynth)(mt32emu_const_context context); \ - void (*closeSynth)(mt32emu_const_context context); \ - mt32emu_boolean (*isOpen)(mt32emu_const_context context); \ - mt32emu_bit32u (*getActualStereoOutputSamplerate)(mt32emu_const_context context); \ - void (*flushMIDIQueue)(mt32emu_const_context context); \ - mt32emu_bit32u (*setMIDIEventQueueSize)(mt32emu_const_context context, const mt32emu_bit32u queue_size); \ - void (*setMIDIReceiver)(mt32emu_context context, mt32emu_midi_receiver_i midi_receiver, void *instance_data); \ + mt32emu_context (MT32EMU_C_CALL *createContext)(mt32emu_report_handler_i report_handler, void *instance_data); \ + void (MT32EMU_C_CALL *freeContext)(mt32emu_context context); \ + mt32emu_return_code (MT32EMU_C_CALL *addROMData)(mt32emu_context context, const mt32emu_bit8u *data, size_t data_size, const mt32emu_sha1_digest *sha1_digest); \ + mt32emu_return_code (MT32EMU_C_CALL *addROMFile)(mt32emu_context context, const char *filename); \ + void (MT32EMU_C_CALL *getROMInfo)(mt32emu_const_context context, mt32emu_rom_info *rom_info); \ + void (MT32EMU_C_CALL *setPartialCount)(mt32emu_context context, const mt32emu_bit32u partial_count); \ + void (MT32EMU_C_CALL *setAnalogOutputMode)(mt32emu_context context, const mt32emu_analog_output_mode analog_output_mode); \ + mt32emu_return_code (MT32EMU_C_CALL *openSynth)(mt32emu_const_context context); \ + void (MT32EMU_C_CALL *closeSynth)(mt32emu_const_context context); \ + mt32emu_boolean (MT32EMU_C_CALL *isOpen)(mt32emu_const_context context); \ + mt32emu_bit32u (MT32EMU_C_CALL *getActualStereoOutputSamplerate)(mt32emu_const_context context); \ + void (MT32EMU_C_CALL *flushMIDIQueue)(mt32emu_const_context context); \ + mt32emu_bit32u (MT32EMU_C_CALL *setMIDIEventQueueSize)(mt32emu_const_context context, const mt32emu_bit32u queue_size); \ + void (MT32EMU_C_CALL *setMIDIReceiver)(mt32emu_context context, mt32emu_midi_receiver_i midi_receiver, void *instance_data); \ \ - void (*parseStream)(mt32emu_const_context context, const mt32emu_bit8u *stream, mt32emu_bit32u length); \ - void (*parseStream_At)(mt32emu_const_context context, const mt32emu_bit8u *stream, mt32emu_bit32u length, mt32emu_bit32u timestamp); \ - void (*playShortMessage)(mt32emu_const_context context, mt32emu_bit32u message); \ - void (*playShortMessageAt)(mt32emu_const_context context, mt32emu_bit32u message, mt32emu_bit32u timestamp); \ - mt32emu_return_code (*playMsg)(mt32emu_const_context context, mt32emu_bit32u msg); \ - mt32emu_return_code (*playSysex)(mt32emu_const_context context, const mt32emu_bit8u *sysex, mt32emu_bit32u len); \ - mt32emu_return_code (*playMsgAt)(mt32emu_const_context context, mt32emu_bit32u msg, mt32emu_bit32u timestamp); \ - mt32emu_return_code (*playSysexAt)(mt32emu_const_context context, const mt32emu_bit8u *sysex, mt32emu_bit32u len, mt32emu_bit32u timestamp); \ + void (MT32EMU_C_CALL *parseStream)(mt32emu_const_context context, const mt32emu_bit8u *stream, mt32emu_bit32u length); \ + void (MT32EMU_C_CALL *parseStream_At)(mt32emu_const_context context, const mt32emu_bit8u *stream, mt32emu_bit32u length, mt32emu_bit32u timestamp); \ + void (MT32EMU_C_CALL *playShortMessage)(mt32emu_const_context context, mt32emu_bit32u message); \ + void (MT32EMU_C_CALL *playShortMessageAt)(mt32emu_const_context context, mt32emu_bit32u message, mt32emu_bit32u timestamp); \ + mt32emu_return_code (MT32EMU_C_CALL *playMsg)(mt32emu_const_context context, mt32emu_bit32u msg); \ + mt32emu_return_code (MT32EMU_C_CALL *playSysex)(mt32emu_const_context context, const mt32emu_bit8u *sysex, mt32emu_bit32u len); \ + mt32emu_return_code (MT32EMU_C_CALL *playMsgAt)(mt32emu_const_context context, mt32emu_bit32u msg, mt32emu_bit32u timestamp); \ + mt32emu_return_code (MT32EMU_C_CALL *playSysexAt)(mt32emu_const_context context, const mt32emu_bit8u *sysex, mt32emu_bit32u len, mt32emu_bit32u timestamp); \ \ - void (*playMsgNow)(mt32emu_const_context context, mt32emu_bit32u msg); \ - void (*playMsgOnPart)(mt32emu_const_context context, mt32emu_bit8u part, mt32emu_bit8u code, mt32emu_bit8u note, mt32emu_bit8u velocity); \ - void (*playSysexNow)(mt32emu_const_context context, const mt32emu_bit8u *sysex, mt32emu_bit32u len); \ - void (*writeSysex)(mt32emu_const_context context, mt32emu_bit8u channel, const mt32emu_bit8u *sysex, mt32emu_bit32u len); \ + void (MT32EMU_C_CALL *playMsgNow)(mt32emu_const_context context, mt32emu_bit32u msg); \ + void (MT32EMU_C_CALL *playMsgOnPart)(mt32emu_const_context context, mt32emu_bit8u part, mt32emu_bit8u code, mt32emu_bit8u note, mt32emu_bit8u velocity); \ + void (MT32EMU_C_CALL *playSysexNow)(mt32emu_const_context context, const mt32emu_bit8u *sysex, mt32emu_bit32u len); \ + void (MT32EMU_C_CALL *writeSysex)(mt32emu_const_context context, mt32emu_bit8u channel, const mt32emu_bit8u *sysex, mt32emu_bit32u len); \ \ - void (*setReverbEnabled)(mt32emu_const_context context, const mt32emu_boolean reverb_enabled); \ - mt32emu_boolean (*isReverbEnabled)(mt32emu_const_context context); \ - void (*setReverbOverridden)(mt32emu_const_context context, const mt32emu_boolean reverb_overridden); \ - mt32emu_boolean (*isReverbOverridden)(mt32emu_const_context context); \ - void (*setReverbCompatibilityMode)(mt32emu_const_context context, const mt32emu_boolean mt32_compatible_mode); \ - mt32emu_boolean (*isMT32ReverbCompatibilityMode)(mt32emu_const_context context); \ - mt32emu_boolean (*isDefaultReverbMT32Compatible)(mt32emu_const_context context); \ + void (MT32EMU_C_CALL *setReverbEnabled)(mt32emu_const_context context, const mt32emu_boolean reverb_enabled); \ + mt32emu_boolean (MT32EMU_C_CALL *isReverbEnabled)(mt32emu_const_context context); \ + void (MT32EMU_C_CALL *setReverbOverridden)(mt32emu_const_context context, const mt32emu_boolean reverb_overridden); \ + mt32emu_boolean (MT32EMU_C_CALL *isReverbOverridden)(mt32emu_const_context context); \ + void (MT32EMU_C_CALL *setReverbCompatibilityMode)(mt32emu_const_context context, const mt32emu_boolean mt32_compatible_mode); \ + mt32emu_boolean (MT32EMU_C_CALL *isMT32ReverbCompatibilityMode)(mt32emu_const_context context); \ + mt32emu_boolean (MT32EMU_C_CALL *isDefaultReverbMT32Compatible)(mt32emu_const_context context); \ \ - void (*setDACInputMode)(mt32emu_const_context context, const mt32emu_dac_input_mode mode); \ - mt32emu_dac_input_mode (*getDACInputMode)(mt32emu_const_context context); \ + void (MT32EMU_C_CALL *setDACInputMode)(mt32emu_const_context context, const mt32emu_dac_input_mode mode); \ + mt32emu_dac_input_mode (MT32EMU_C_CALL *getDACInputMode)(mt32emu_const_context context); \ \ - void (*setMIDIDelayMode)(mt32emu_const_context context, const mt32emu_midi_delay_mode mode); \ - mt32emu_midi_delay_mode (*getMIDIDelayMode)(mt32emu_const_context context); \ + void (MT32EMU_C_CALL *setMIDIDelayMode)(mt32emu_const_context context, const mt32emu_midi_delay_mode mode); \ + mt32emu_midi_delay_mode (MT32EMU_C_CALL *getMIDIDelayMode)(mt32emu_const_context context); \ \ - void (*setOutputGain)(mt32emu_const_context context, float gain); \ - float (*getOutputGain)(mt32emu_const_context context); \ - void (*setReverbOutputGain)(mt32emu_const_context context, float gain); \ - float (*getReverbOutputGain)(mt32emu_const_context context); \ + void (MT32EMU_C_CALL *setOutputGain)(mt32emu_const_context context, float gain); \ + float (MT32EMU_C_CALL *getOutputGain)(mt32emu_const_context context); \ + void (MT32EMU_C_CALL *setReverbOutputGain)(mt32emu_const_context context, float gain); \ + float (MT32EMU_C_CALL *getReverbOutputGain)(mt32emu_const_context context); \ \ - void (*setReversedStereoEnabled)(mt32emu_const_context context, const mt32emu_boolean enabled); \ - mt32emu_boolean (*isReversedStereoEnabled)(mt32emu_const_context context); \ + void (MT32EMU_C_CALL *setReversedStereoEnabled)(mt32emu_const_context context, const mt32emu_boolean enabled); \ + mt32emu_boolean (MT32EMU_C_CALL *isReversedStereoEnabled)(mt32emu_const_context context); \ \ - void (*renderBit16s)(mt32emu_const_context context, mt32emu_bit16s *stream, mt32emu_bit32u len); \ - void (*renderFloat)(mt32emu_const_context context, float *stream, mt32emu_bit32u len); \ - void (*renderBit16sStreams)(mt32emu_const_context context, const mt32emu_dac_output_bit16s_streams *streams, mt32emu_bit32u len); \ - void (*renderFloatStreams)(mt32emu_const_context context, const mt32emu_dac_output_float_streams *streams, mt32emu_bit32u len); \ + void (MT32EMU_C_CALL *renderBit16s)(mt32emu_const_context context, mt32emu_bit16s *stream, mt32emu_bit32u len); \ + void (MT32EMU_C_CALL *renderFloat)(mt32emu_const_context context, float *stream, mt32emu_bit32u len); \ + void (MT32EMU_C_CALL *renderBit16sStreams)(mt32emu_const_context context, const mt32emu_dac_output_bit16s_streams *streams, mt32emu_bit32u len); \ + void (MT32EMU_C_CALL *renderFloatStreams)(mt32emu_const_context context, const mt32emu_dac_output_float_streams *streams, mt32emu_bit32u len); \ \ - mt32emu_boolean (*hasActivePartials)(mt32emu_const_context context); \ - mt32emu_boolean (*isActive)(mt32emu_const_context context); \ - mt32emu_bit32u (*getPartialCount)(mt32emu_const_context context); \ - mt32emu_bit32u (*getPartStates)(mt32emu_const_context context); \ - void (*getPartialStates)(mt32emu_const_context context, mt32emu_bit8u *partial_states); \ - mt32emu_bit32u (*getPlayingNotes)(mt32emu_const_context context, mt32emu_bit8u part_number, mt32emu_bit8u *keys, mt32emu_bit8u *velocities); \ - const char *(*getPatchName)(mt32emu_const_context context, mt32emu_bit8u part_number); \ - void (*readMemory)(mt32emu_const_context context, mt32emu_bit32u addr, mt32emu_bit32u len, mt32emu_bit8u *data); + mt32emu_boolean (MT32EMU_C_CALL *hasActivePartials)(mt32emu_const_context context); \ + mt32emu_boolean (MT32EMU_C_CALL *isActive)(mt32emu_const_context context); \ + mt32emu_bit32u (MT32EMU_C_CALL *getPartialCount)(mt32emu_const_context context); \ + mt32emu_bit32u (MT32EMU_C_CALL *getPartStates)(mt32emu_const_context context); \ + void (MT32EMU_C_CALL *getPartialStates)(mt32emu_const_context context, mt32emu_bit8u *partial_states); \ + mt32emu_bit32u (MT32EMU_C_CALL *getPlayingNotes)(mt32emu_const_context context, mt32emu_bit8u part_number, mt32emu_bit8u *keys, mt32emu_bit8u *velocities); \ + const char *(MT32EMU_C_CALL *getPatchName)(mt32emu_const_context context, mt32emu_bit8u part_number); \ + void (MT32EMU_C_CALL *readMemory)(mt32emu_const_context context, mt32emu_bit32u addr, mt32emu_bit32u len, mt32emu_bit8u *data); #define MT32EMU_SERVICE_I_V1 \ - mt32emu_analog_output_mode (*getBestAnalogOutputMode)(const double target_samplerate); \ - void (*setStereoOutputSampleRate)(mt32emu_context context, const double samplerate); \ - void (*setSamplerateConversionQuality)(mt32emu_context context, const mt32emu_samplerate_conversion_quality quality); \ - void (*selectRendererType)(mt32emu_context context, mt32emu_renderer_type renderer_type); \ - mt32emu_renderer_type (*getSelectedRendererType)(mt32emu_context context); \ - mt32emu_bit32u (*convertOutputToSynthTimestamp)(mt32emu_const_context context, mt32emu_bit32u output_timestamp); \ - mt32emu_bit32u (*convertSynthToOutputTimestamp)(mt32emu_const_context context, mt32emu_bit32u synth_timestamp); + mt32emu_analog_output_mode (MT32EMU_C_CALL *getBestAnalogOutputMode)(const double target_samplerate); \ + void (MT32EMU_C_CALL *setStereoOutputSampleRate)(mt32emu_context context, const double samplerate); \ + void (MT32EMU_C_CALL *setSamplerateConversionQuality)(mt32emu_context context, const mt32emu_samplerate_conversion_quality quality); \ + void (MT32EMU_C_CALL *selectRendererType)(mt32emu_context context, mt32emu_renderer_type renderer_type); \ + mt32emu_renderer_type (MT32EMU_C_CALL *getSelectedRendererType)(mt32emu_context context); \ + mt32emu_bit32u (MT32EMU_C_CALL *convertOutputToSynthTimestamp)(mt32emu_const_context context, mt32emu_bit32u output_timestamp); \ + mt32emu_bit32u (MT32EMU_C_CALL *convertSynthToOutputTimestamp)(mt32emu_const_context context, mt32emu_bit32u synth_timestamp); #define MT32EMU_SERVICE_I_V2 \ - mt32emu_bit32u (*getInternalRenderedSampleCount)(mt32emu_const_context context); \ - void (*setNiceAmpRampEnabled)(mt32emu_const_context context, const mt32emu_boolean enabled); \ - mt32emu_boolean (*isNiceAmpRampEnabled)(mt32emu_const_context context); + mt32emu_bit32u (MT32EMU_C_CALL *getInternalRenderedSampleCount)(mt32emu_const_context context); \ + void (MT32EMU_C_CALL *setNiceAmpRampEnabled)(mt32emu_const_context context, const mt32emu_boolean enabled); \ + mt32emu_boolean (MT32EMU_C_CALL *isNiceAmpRampEnabled)(mt32emu_const_context context); #define MT32EMU_SERVICE_I_V3 \ - void (*setNicePanningEnabled)(mt32emu_const_context context, const mt32emu_boolean enabled); \ - mt32emu_boolean (*isNicePanningEnabled)(mt32emu_const_context context); \ - void (*setNicePartialMixingEnabled)(mt32emu_const_context context, const mt32emu_boolean enabled); \ - mt32emu_boolean (*isNicePartialMixingEnabled)(mt32emu_const_context context); \ - void (*preallocateReverbMemory)(mt32emu_const_context context, const mt32emu_boolean enabled); \ - void (*configureMIDIEventQueueSysexStorage)(mt32emu_const_context context, const mt32emu_bit32u storage_buffer_size); + void (MT32EMU_C_CALL *setNicePanningEnabled)(mt32emu_const_context context, const mt32emu_boolean enabled); \ + mt32emu_boolean (MT32EMU_C_CALL *isNicePanningEnabled)(mt32emu_const_context context); \ + void (MT32EMU_C_CALL *setNicePartialMixingEnabled)(mt32emu_const_context context, const mt32emu_boolean enabled); \ + mt32emu_boolean (MT32EMU_C_CALL *isNicePartialMixingEnabled)(mt32emu_const_context context); \ + void (MT32EMU_C_CALL *preallocateReverbMemory)(mt32emu_const_context context, const mt32emu_boolean enabled); \ + void (MT32EMU_C_CALL *configureMIDIEventQueueSysexStorage)(mt32emu_const_context context, const mt32emu_bit32u storage_buffer_size); + +#define MT32EMU_SERVICE_I_V4 \ + size_t (MT32EMU_C_CALL *getMachineIDs)(const char **machine_ids, size_t machine_ids_size); \ + size_t (MT32EMU_C_CALL *getROMIDs)(const char **rom_ids, size_t rom_ids_size, const char *machine_id); \ + mt32emu_return_code (MT32EMU_C_CALL *identifyROMData)(mt32emu_rom_info *rom_info, const mt32emu_bit8u *data, size_t data_size, const char *machine_id); \ + mt32emu_return_code (MT32EMU_C_CALL *identifyROMFile)(mt32emu_rom_info *rom_info, const char *filename, const char *machine_id); \ +\ + mt32emu_return_code (MT32EMU_C_CALL *mergeAndAddROMData)(mt32emu_context context, const mt32emu_bit8u *part1_data, size_t part1_data_size, const mt32emu_sha1_digest *part1_sha1_digest, const mt32emu_bit8u *part2_data, size_t part2_data_size, const mt32emu_sha1_digest *part2_sha1_digest); \ + mt32emu_return_code (MT32EMU_C_CALL *mergeAndAddROMFiles)(mt32emu_context context, const char *part1_filename, const char *part2_filename); \ + mt32emu_return_code (MT32EMU_C_CALL *addMachineROMFile)(mt32emu_context context, const char *machine_id, const char *filename); + +#define MT32EMU_SERVICE_I_V5 \ + mt32emu_boolean (MT32EMU_C_CALL *getDisplayState)(mt32emu_const_context context, char *target_buffer, const mt32emu_boolean narrow_lcd); \ + void (MT32EMU_C_CALL *setMainDisplayMode)(mt32emu_const_context context); \ + void (MT32EMU_C_CALL *setDisplayCompatibility)(mt32emu_const_context context, mt32emu_boolean old_mt32_compatibility_enabled); \ + mt32emu_boolean (MT32EMU_C_CALL *isDisplayOldMT32Compatible)(mt32emu_const_context context); \ + mt32emu_boolean (MT32EMU_C_CALL *isDefaultDisplayOldMT32Compatible)(mt32emu_const_context context); \ + void (MT32EMU_C_CALL *setPartVolumeOverride)(mt32emu_const_context context, mt32emu_bit8u part_number, mt32emu_bit8u volume_override); \ + mt32emu_bit8u (MT32EMU_C_CALL *getPartVolumeOverride)(mt32emu_const_context context, mt32emu_bit8u part_number); + +#define MT32EMU_SERVICE_I_V6 \ + mt32emu_boolean (MT32EMU_C_CALL *getSoundGroupName)(mt32emu_const_context context, char *sound_group_name, mt32emu_bit8u timbre_group, mt32emu_bit8u timbre_number); \ + mt32emu_boolean (MT32EMU_C_CALL *getSoundName)(mt32emu_const_context context, char *sound_name, mt32emu_bit8u timbre_group, mt32emu_bit8u timbre_number); typedef struct { MT32EMU_SERVICE_I_V0 @@ -334,6 +392,33 @@ typedef struct { MT32EMU_SERVICE_I_V3 } mt32emu_service_i_v3; +typedef struct { + MT32EMU_SERVICE_I_V0 + MT32EMU_SERVICE_I_V1 + MT32EMU_SERVICE_I_V2 + MT32EMU_SERVICE_I_V3 + MT32EMU_SERVICE_I_V4 +} mt32emu_service_i_v4; + +typedef struct { + MT32EMU_SERVICE_I_V0 + MT32EMU_SERVICE_I_V1 + MT32EMU_SERVICE_I_V2 + MT32EMU_SERVICE_I_V3 + MT32EMU_SERVICE_I_V4 + MT32EMU_SERVICE_I_V5 +} mt32emu_service_i_v5; + +typedef struct { + MT32EMU_SERVICE_I_V0 + MT32EMU_SERVICE_I_V1 + MT32EMU_SERVICE_I_V2 + MT32EMU_SERVICE_I_V3 + MT32EMU_SERVICE_I_V4 + MT32EMU_SERVICE_I_V5 + MT32EMU_SERVICE_I_V6 +} mt32emu_service_i_v6; + /** * Extensible interface for all the library services. * Union intended to view an interface of any subsequent version as any parent interface not requiring a cast. @@ -344,11 +429,17 @@ union mt32emu_service_i { const mt32emu_service_i_v1 *v1; const mt32emu_service_i_v2 *v2; const mt32emu_service_i_v3 *v3; + const mt32emu_service_i_v4 *v4; + const mt32emu_service_i_v5 *v5; + const mt32emu_service_i_v6 *v6; }; #undef MT32EMU_SERVICE_I_V0 #undef MT32EMU_SERVICE_I_V1 #undef MT32EMU_SERVICE_I_V2 #undef MT32EMU_SERVICE_I_V3 +#undef MT32EMU_SERVICE_I_V4 +#undef MT32EMU_SERVICE_I_V5 +#undef MT32EMU_SERVICE_I_V6 #endif /* #ifndef MT32EMU_C_TYPES_H */ diff --git a/src/sound/munt/c_interface/cpp_interface.h b/src/sound/munt/c_interface/cpp_interface.h index 82fa44b2e..d22897b74 100644 --- a/src/sound/munt/c_interface/cpp_interface.h +++ b/src/sound/munt/c_interface/cpp_interface.h @@ -1,5 +1,5 @@ /* Copyright (C) 2003, 2004, 2005, 2006, 2008, 2009 Dean Beeler, Jerome Fisher - * Copyright (C) 2011-2020 Dean Beeler, Jerome Fisher, Sergey V. Mikayev + * Copyright (C) 2011-2022 Dean Beeler, Jerome Fisher, Sergey V. Mikayev * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by @@ -41,10 +41,17 @@ mt32emu_service_i mt32emu_get_service_i(); #define mt32emu_get_library_version_string i.v0->getLibraryVersionString #define mt32emu_get_stereo_output_samplerate i.v0->getStereoOutputSamplerate #define mt32emu_get_best_analog_output_mode iV1()->getBestAnalogOutputMode +#define mt32emu_get_machine_ids iV4()->getMachineIDs +#define mt32emu_get_rom_ids iV4()->getROMIDs +#define mt32emu_identify_rom_data iV4()->identifyROMData +#define mt32emu_identify_rom_file iV4()->identifyROMFile #define mt32emu_create_context i.v0->createContext #define mt32emu_free_context i.v0->freeContext #define mt32emu_add_rom_data i.v0->addROMData #define mt32emu_add_rom_file i.v0->addROMFile +#define mt32emu_merge_and_add_rom_data iV4()->mergeAndAddROMData +#define mt32emu_merge_and_add_rom_files iV4()->mergeAndAddROMFiles +#define mt32emu_add_machine_rom_file iV4()->addMachineROMFile #define mt32emu_get_rom_info i.v0->getROMInfo #define mt32emu_set_partial_count i.v0->setPartialCount #define mt32emu_set_analog_output_mode i.v0->setAnalogOutputMode @@ -91,6 +98,8 @@ mt32emu_service_i mt32emu_get_service_i(); #define mt32emu_get_output_gain i.v0->getOutputGain #define mt32emu_set_reverb_output_gain i.v0->setReverbOutputGain #define mt32emu_get_reverb_output_gain i.v0->getReverbOutputGain +#define mt32emu_set_part_volume_override iV5()->setPartVolumeOverride +#define mt32emu_get_part_volume_override iV5()->getPartVolumeOverride #define mt32emu_set_reversed_stereo_enabled i.v0->setReversedStereoEnabled #define mt32emu_is_reversed_stereo_enabled i.v0->isReversedStereoEnabled #define mt32emu_set_nice_amp_ramp_enabled iV2()->setNiceAmpRampEnabled @@ -110,7 +119,14 @@ mt32emu_service_i mt32emu_get_service_i(); #define mt32emu_get_partial_states i.v0->getPartialStates #define mt32emu_get_playing_notes i.v0->getPlayingNotes #define mt32emu_get_patch_name i.v0->getPatchName +#define mt32emu_get_sound_group_name iV6()->getSoundGroupName +#define mt32emu_get_sound_name iV6()->getSoundName #define mt32emu_read_memory i.v0->readMemory +#define mt32emu_get_display_state iV5()->getDisplayState +#define mt32emu_set_main_display_mode iV5()->setMainDisplayMode +#define mt32emu_set_display_compatibility iV5()->setDisplayCompatibility +#define mt32emu_is_display_old_mt32_compatible iV5()->isDisplayOldMT32Compatible +#define mt32emu_is_default_display_old_mt32_compatible iV5()->isDefaultDisplayOldMT32Compatible #else // #if MT32EMU_API_TYPE == 2 @@ -123,7 +139,7 @@ namespace MT32Emu { namespace CppInterfaceImpl { static const mt32emu_report_handler_i NULL_REPORT_HANDLER = { NULL }; -static mt32emu_report_handler_i getReportHandlerThunk(); +static mt32emu_report_handler_i getReportHandlerThunk(mt32emu_report_handler_version); static mt32emu_midi_receiver_i getMidiReceiverThunk(); } @@ -136,8 +152,8 @@ static mt32emu_midi_receiver_i getMidiReceiverThunk(); * See c_types.h and c_interface.h for description of the corresponding interface methods. */ -// Defines the interface for handling reported events. -// Corresponds to the current version of mt32emu_report_handler_i interface. +// Defines the interface for handling reported events (initial version). +// Corresponds to the mt32emu_report_handler_i_v0 interface. class IReportHandler { public: virtual void printDebug(const char *fmt, va_list list) = 0; @@ -159,6 +175,17 @@ protected: ~IReportHandler() {} }; +// Extends IReportHandler, so that the client may supply callbacks for reporting signals about updated display state. +// Corresponds to the mt32emu_report_handler_i_v1 interface. +class IReportHandlerV1 : public IReportHandler { +public: + virtual void onLCDStateUpdated() = 0; + virtual void onMidiMessageLEDStateUpdated(bool ledState) = 0; + +protected: + ~IReportHandlerV1() {} +}; + // Defines the interface for receiving MIDI messages generated by MIDI stream parser. // Corresponds to the current version of mt32emu_midi_receiver_i interface. class IMidiReceiver { @@ -196,14 +223,24 @@ public: Bit32u getStereoOutputSamplerate(const AnalogOutputMode analog_output_mode) { return mt32emu_get_stereo_output_samplerate(static_cast(analog_output_mode)); } AnalogOutputMode getBestAnalogOutputMode(const double target_samplerate) { return static_cast(mt32emu_get_best_analog_output_mode(target_samplerate)); } + size_t getMachineIDs(const char **machine_ids, size_t machine_ids_size) { return mt32emu_get_machine_ids(machine_ids, machine_ids_size); } + size_t getROMIDs(const char **rom_ids, size_t rom_ids_size, const char *machine_id) { return mt32emu_get_rom_ids(rom_ids, rom_ids_size, machine_id); } + mt32emu_return_code identifyROMData(mt32emu_rom_info *rom_info, const Bit8u *data, size_t data_size, const char *machine_id) { return mt32emu_identify_rom_data(rom_info, data, data_size, machine_id); } + mt32emu_return_code identifyROMFile(mt32emu_rom_info *rom_info, const char *filename, const char *machine_id) { return mt32emu_identify_rom_file(rom_info, filename, machine_id); } + // Context-dependent methods mt32emu_context getContext() { return c; } void createContext(mt32emu_report_handler_i report_handler = CppInterfaceImpl::NULL_REPORT_HANDLER, void *instance_data = NULL) { freeContext(); c = mt32emu_create_context(report_handler, instance_data); } - void createContext(IReportHandler &report_handler) { createContext(CppInterfaceImpl::getReportHandlerThunk(), &report_handler); } + void createContext(IReportHandler &report_handler) { createContext(CppInterfaceImpl::getReportHandlerThunk(MT32EMU_REPORT_HANDLER_VERSION_0), &report_handler); } + void createContext(IReportHandlerV1 &report_handler) { createContext(CppInterfaceImpl::getReportHandlerThunk(MT32EMU_REPORT_HANDLER_VERSION_1), &report_handler); } void freeContext() { if (c != NULL) { mt32emu_free_context(c); c = NULL; } } mt32emu_return_code addROMData(const Bit8u *data, size_t data_size, const mt32emu_sha1_digest *sha1_digest = NULL) { return mt32emu_add_rom_data(c, data, data_size, sha1_digest); } mt32emu_return_code addROMFile(const char *filename) { return mt32emu_add_rom_file(c, filename); } + mt32emu_return_code mergeAndAddROMData(const Bit8u *part1_data, size_t part1_data_size, const Bit8u *part2_data, size_t part2_data_size) { return mt32emu_merge_and_add_rom_data(c, part1_data, part1_data_size, NULL, part2_data, part2_data_size, NULL); } + mt32emu_return_code mergeAndAddROMData(const Bit8u *part1_data, size_t part1_data_size, const mt32emu_sha1_digest *part1_sha1_digest, const Bit8u *part2_data, size_t part2_data_size, const mt32emu_sha1_digest *part2_sha1_digest) { return mt32emu_merge_and_add_rom_data(c, part1_data, part1_data_size, part1_sha1_digest, part2_data, part2_data_size, part2_sha1_digest); } + mt32emu_return_code mergeAndAddROMFiles(const char *part1_filename, const char *part2_filename) { return mt32emu_merge_and_add_rom_files(c, part1_filename, part2_filename); } + mt32emu_return_code addMachineROMFile(const char *machine_id, const char *filename) { return mt32emu_add_machine_rom_file(c, machine_id, filename); } void getROMInfo(mt32emu_rom_info *rom_info) { mt32emu_get_rom_info(c, rom_info); } void setPartialCount(const Bit32u partial_count) { mt32emu_set_partial_count(c, partial_count); } void setAnalogOutputMode(const AnalogOutputMode analog_output_mode) { mt32emu_set_analog_output_mode(c, static_cast(analog_output_mode)); } @@ -258,6 +295,9 @@ public: void setReverbOutputGain(float gain) { mt32emu_set_reverb_output_gain(c, gain); } float getReverbOutputGain() { return mt32emu_get_reverb_output_gain(c); } + void setPartVolumeOverride(Bit8u part_number, Bit8u volume_override) { mt32emu_set_part_volume_override(c, part_number, volume_override); } + Bit8u getPartVolumeOverride(Bit8u part_number) { return mt32emu_get_part_volume_override(c, part_number); } + void setReversedStereoEnabled(const bool enabled) { mt32emu_set_reversed_stereo_enabled(c, enabled ? MT32EMU_BOOL_TRUE : MT32EMU_BOOL_FALSE); } bool isReversedStereoEnabled() { return mt32emu_is_reversed_stereo_enabled(c) != MT32EMU_BOOL_FALSE; } @@ -282,8 +322,17 @@ public: void getPartialStates(Bit8u *partial_states) { mt32emu_get_partial_states(c, partial_states); } Bit32u getPlayingNotes(Bit8u part_number, Bit8u *keys, Bit8u *velocities) { return mt32emu_get_playing_notes(c, part_number, keys, velocities); } const char *getPatchName(Bit8u part_number) { return mt32emu_get_patch_name(c, part_number); } + bool getSoundGroupName(char *soundGroupName, Bit8u timbreGroup, Bit8u timbreNumber) { return mt32emu_get_sound_group_name(c, soundGroupName, timbreGroup, timbreNumber) != MT32EMU_BOOL_FALSE; } + bool getSoundName(char *soundName, Bit8u timbreGroup, Bit8u timbreNumber) { return mt32emu_get_sound_name(c, soundName, timbreGroup, timbreNumber) != MT32EMU_BOOL_FALSE; } void readMemory(Bit32u addr, Bit32u len, Bit8u *data) { mt32emu_read_memory(c, addr, len, data); } + bool getDisplayState(char *target_buffer, const bool narrow_lcd) { return mt32emu_get_display_state(c, target_buffer, narrow_lcd ? MT32EMU_BOOL_TRUE : MT32EMU_BOOL_FALSE) != MT32EMU_BOOL_FALSE; } + void setMainDisplayMode() { mt32emu_set_main_display_mode(c); } + + void setDisplayCompatibility(const bool oldMT32CompatibilityEnabled) { mt32emu_set_display_compatibility(c, oldMT32CompatibilityEnabled ? MT32EMU_BOOL_TRUE : MT32EMU_BOOL_FALSE); } + bool isDisplayOldMT32Compatible() { return mt32emu_is_display_old_mt32_compatible(c) != MT32EMU_BOOL_FALSE; } + bool isDefaultDisplayOldMT32Compatible() { return mt32emu_is_default_display_old_mt32_compatible(c) != MT32EMU_BOOL_FALSE; } + private: #if MT32EMU_API_TYPE == 2 const mt32emu_service_i i; @@ -294,108 +343,137 @@ private: const mt32emu_service_i_v1 *iV1() { return (getVersionID() < MT32EMU_SERVICE_VERSION_1) ? NULL : i.v1; } const mt32emu_service_i_v2 *iV2() { return (getVersionID() < MT32EMU_SERVICE_VERSION_2) ? NULL : i.v2; } const mt32emu_service_i_v3 *iV3() { return (getVersionID() < MT32EMU_SERVICE_VERSION_3) ? NULL : i.v3; } + const mt32emu_service_i_v4 *iV4() { return (getVersionID() < MT32EMU_SERVICE_VERSION_4) ? NULL : i.v4; } + const mt32emu_service_i_v5 *iV5() { return (getVersionID() < MT32EMU_SERVICE_VERSION_5) ? NULL : i.v5; } + const mt32emu_service_i_v6 *iV6() { return (getVersionID() < MT32EMU_SERVICE_VERSION_6) ? NULL : i.v6; } #endif + + Service(const Service &); // prevent copy-construction + Service& operator=(const Service &); // prevent assignment }; namespace CppInterfaceImpl { -static mt32emu_report_handler_version getReportHandlerVersionID(mt32emu_report_handler_i) { - return MT32EMU_REPORT_HANDLER_VERSION_CURRENT; -} +static mt32emu_report_handler_version MT32EMU_C_CALL getReportHandlerVersionID(mt32emu_report_handler_i); -static void printDebug(void *instance_data, const char *fmt, va_list list) { +static void MT32EMU_C_CALL printDebug(void *instance_data, const char *fmt, va_list list) { static_cast(instance_data)->printDebug(fmt, list); } -static void onErrorControlROM(void *instance_data) { +static void MT32EMU_C_CALL onErrorControlROM(void *instance_data) { static_cast(instance_data)->onErrorControlROM(); } -static void onErrorPCMROM(void *instance_data) { +static void MT32EMU_C_CALL onErrorPCMROM(void *instance_data) { static_cast(instance_data)->onErrorPCMROM(); } -static void showLCDMessage(void *instance_data, const char *message) { +static void MT32EMU_C_CALL showLCDMessage(void *instance_data, const char *message) { static_cast(instance_data)->showLCDMessage(message); } -static void onMIDIMessagePlayed(void *instance_data) { +static void MT32EMU_C_CALL onMIDIMessagePlayed(void *instance_data) { static_cast(instance_data)->onMIDIMessagePlayed(); } -static mt32emu_boolean onMIDIQueueOverflow(void *instance_data) { +static mt32emu_boolean MT32EMU_C_CALL onMIDIQueueOverflow(void *instance_data) { return static_cast(instance_data)->onMIDIQueueOverflow() ? MT32EMU_BOOL_TRUE : MT32EMU_BOOL_FALSE; } -static void onMIDISystemRealtime(void *instance_data, mt32emu_bit8u system_realtime) { +static void MT32EMU_C_CALL onMIDISystemRealtime(void *instance_data, mt32emu_bit8u system_realtime) { static_cast(instance_data)->onMIDISystemRealtime(system_realtime); } -static void onDeviceReset(void *instance_data) { +static void MT32EMU_C_CALL onDeviceReset(void *instance_data) { static_cast(instance_data)->onDeviceReset(); } -static void onDeviceReconfig(void *instance_data) { +static void MT32EMU_C_CALL onDeviceReconfig(void *instance_data) { static_cast(instance_data)->onDeviceReconfig(); } -static void onNewReverbMode(void *instance_data, mt32emu_bit8u mode) { +static void MT32EMU_C_CALL onNewReverbMode(void *instance_data, mt32emu_bit8u mode) { static_cast(instance_data)->onNewReverbMode(mode); } -static void onNewReverbTime(void *instance_data, mt32emu_bit8u time) { +static void MT32EMU_C_CALL onNewReverbTime(void *instance_data, mt32emu_bit8u time) { static_cast(instance_data)->onNewReverbTime(time); } -static void onNewReverbLevel(void *instance_data, mt32emu_bit8u level) { +static void MT32EMU_C_CALL onNewReverbLevel(void *instance_data, mt32emu_bit8u level) { static_cast(instance_data)->onNewReverbLevel(level); } -static void onPolyStateChanged(void *instance_data, mt32emu_bit8u part_num) { +static void MT32EMU_C_CALL onPolyStateChanged(void *instance_data, mt32emu_bit8u part_num) { static_cast(instance_data)->onPolyStateChanged(part_num); } -static void onProgramChanged(void *instance_data, mt32emu_bit8u part_num, const char *sound_group_name, const char *patch_name) { +static void MT32EMU_C_CALL onProgramChanged(void *instance_data, mt32emu_bit8u part_num, const char *sound_group_name, const char *patch_name) { static_cast(instance_data)->onProgramChanged(part_num, sound_group_name, patch_name); } -static mt32emu_report_handler_i getReportHandlerThunk() { - static const mt32emu_report_handler_i_v0 REPORT_HANDLER_V0_THUNK = { - getReportHandlerVersionID, - printDebug, - onErrorControlROM, - onErrorPCMROM, - showLCDMessage, - onMIDIMessagePlayed, - onMIDIQueueOverflow, - onMIDISystemRealtime, - onDeviceReset, - onDeviceReconfig, - onNewReverbMode, - onNewReverbTime, - onNewReverbLevel, - onPolyStateChanged, - onProgramChanged - }; - - static const mt32emu_report_handler_i REPORT_HANDLER_THUNK = { &REPORT_HANDLER_V0_THUNK }; - - return REPORT_HANDLER_THUNK; +static void MT32EMU_C_CALL onLCDStateUpdated(void *instance_data) { + static_cast(instance_data)->onLCDStateUpdated(); } -static mt32emu_midi_receiver_version getMidiReceiverVersionID(mt32emu_midi_receiver_i) { +static void MT32EMU_C_CALL onMidiMessageLEDStateUpdated(void *instance_data, mt32emu_boolean led_state) { + static_cast(instance_data)->onMidiMessageLEDStateUpdated(led_state != MT32EMU_BOOL_FALSE); +} + +#define MT32EMU_REPORT_HANDLER_V0_THUNK \ + getReportHandlerVersionID, \ + printDebug, \ + onErrorControlROM, \ + onErrorPCMROM, \ + showLCDMessage, \ + onMIDIMessagePlayed, \ + onMIDIQueueOverflow, \ + onMIDISystemRealtime, \ + onDeviceReset, \ + onDeviceReconfig, \ + onNewReverbMode, \ + onNewReverbTime, \ + onNewReverbLevel, \ + onPolyStateChanged, \ + onProgramChanged + +static const mt32emu_report_handler_i_v0 REPORT_HANDLER_V0_THUNK = { + MT32EMU_REPORT_HANDLER_V0_THUNK +}; + +static const mt32emu_report_handler_i_v1 REPORT_HANDLER_V1_THUNK = { + MT32EMU_REPORT_HANDLER_V0_THUNK, + onLCDStateUpdated, + onMidiMessageLEDStateUpdated +}; + +#undef MT32EMU_REPORT_HANDLER_THUNK_V0 + +static mt32emu_report_handler_version MT32EMU_C_CALL getReportHandlerVersionID(mt32emu_report_handler_i thunk) { + if (thunk.v0 == &REPORT_HANDLER_V0_THUNK) return MT32EMU_REPORT_HANDLER_VERSION_0; + return MT32EMU_REPORT_HANDLER_VERSION_CURRENT; +} + +static mt32emu_report_handler_i getReportHandlerThunk(mt32emu_report_handler_version versionID) { + mt32emu_report_handler_i thunk; + if (versionID == MT32EMU_REPORT_HANDLER_VERSION_0) thunk.v0 = &REPORT_HANDLER_V0_THUNK; + else thunk.v1 = &REPORT_HANDLER_V1_THUNK; + return thunk; +} + +static mt32emu_midi_receiver_version MT32EMU_C_CALL getMidiReceiverVersionID(mt32emu_midi_receiver_i) { return MT32EMU_MIDI_RECEIVER_VERSION_CURRENT; } -static void handleShortMessage(void *instance_data, const mt32emu_bit32u message) { +static void MT32EMU_C_CALL handleShortMessage(void *instance_data, const mt32emu_bit32u message) { static_cast(instance_data)->handleShortMessage(message); } -static void handleSysex(void *instance_data, const mt32emu_bit8u stream[], const mt32emu_bit32u length) { +static void MT32EMU_C_CALL handleSysex(void *instance_data, const mt32emu_bit8u stream[], const mt32emu_bit32u length) { static_cast(instance_data)->handleSysex(stream, length); } -static void handleSystemRealtimeMessage(void *instance_data, const mt32emu_bit8u realtime) { +static void MT32EMU_C_CALL handleSystemRealtimeMessage(void *instance_data, const mt32emu_bit8u realtime) { static_cast(instance_data)->handleSystemRealtimeMessage(realtime); } @@ -424,10 +502,17 @@ static mt32emu_midi_receiver_i getMidiReceiverThunk() { #undef mt32emu_get_library_version_string #undef mt32emu_get_stereo_output_samplerate #undef mt32emu_get_best_analog_output_mode +#undef mt32emu_get_machine_ids +#undef mt32emu_get_rom_ids +#undef mt32emu_identify_rom_data +#undef mt32emu_identify_rom_file #undef mt32emu_create_context #undef mt32emu_free_context #undef mt32emu_add_rom_data #undef mt32emu_add_rom_file +#undef mt32emu_merge_and_add_rom_data +#undef mt32emu_merge_and_add_rom_files +#undef mt32emu_add_machine_rom_file #undef mt32emu_get_rom_info #undef mt32emu_set_partial_count #undef mt32emu_set_analog_output_mode @@ -493,7 +578,14 @@ static mt32emu_midi_receiver_i getMidiReceiverThunk() { #undef mt32emu_get_partial_states #undef mt32emu_get_playing_notes #undef mt32emu_get_patch_name +#undef mt32emu_get_sound_group_name +#undef mt32emu_get_sound_name #undef mt32emu_read_memory +#undef mt32emu_get_display_state +#undef mt32emu_set_main_display_mode +#undef mt32emu_set_display_compatibility +#undef mt32emu_is_display_old_mt32_compatible +#undef mt32emu_is_default_display_old_mt32_compatible #endif // #if MT32EMU_API_TYPE == 2 diff --git a/src/sound/munt/config.h b/src/sound/munt/config.h index e41d4664b..906c23d56 100644 --- a/src/sound/munt/config.h +++ b/src/sound/munt/config.h @@ -1,5 +1,5 @@ /* Copyright (C) 2003, 2004, 2005, 2006, 2008, 2009 Dean Beeler, Jerome Fisher - * Copyright (C) 2011-2017 Dean Beeler, Jerome Fisher, Sergey V. Mikayev + * Copyright (C) 2011-2022 Dean Beeler, Jerome Fisher, Sergey V. Mikayev * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by @@ -18,9 +18,9 @@ #ifndef MT32EMU_CONFIG_H #define MT32EMU_CONFIG_H -#define MT32EMU_VERSION "2.4.0" +#define MT32EMU_VERSION "2.7.0" #define MT32EMU_VERSION_MAJOR 2 -#define MT32EMU_VERSION_MINOR 4 +#define MT32EMU_VERSION_MINOR 7 #define MT32EMU_VERSION_PATCH 0 /* Library Exports Configuration diff --git a/src/sound/munt/config.h.in b/src/sound/munt/config.h.in index 48dfb0076..b120f407c 100644 --- a/src/sound/munt/config.h.in +++ b/src/sound/munt/config.h.in @@ -1,5 +1,5 @@ /* Copyright (C) 2003, 2004, 2005, 2006, 2008, 2009 Dean Beeler, Jerome Fisher - * Copyright (C) 2011-2020 Dean Beeler, Jerome Fisher, Sergey V. Mikayev + * Copyright (C) 2011-2022 Dean Beeler, Jerome Fisher, Sergey V. Mikayev * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by @@ -33,6 +33,35 @@ * is exported, and thus the client application may ONLY use MT32EMU_API_TYPE 2. * 3: All the available API types are provided by the library build. */ -#define MT32EMU_EXPORTS_TYPE @libmt32emu_EXPORTS_TYPE@ +#define MT32EMU_EXPORTS_TYPE @libmt32emu_EXPORTS_TYPE@ +/* Type of library build. + * + * For shared library builds, MT32EMU_SHARED is defined, so that compiler-specific attributes are assigned + * to all the exported symbols as appropriate. MT32EMU_SHARED is undefined for static library builds. + */ +@libmt32emu_SHARED_DEFINITION@ + +/* Whether the library is built as a shared object with a version tag to enable runtime version checks. */ +#define MT32EMU_WITH_VERSION_TAGGING @libmt32emu_RUNTIME_VERSION_CHECK@ + +/* Automatic runtime check of the shared library version in client applications. + * + * When the shared library is built with version tagging enabled, the client application may rely on an automatic + * version check that ensures forward compatibility. See VersionTagging.h for more info. + * 0: Disables the automatic runtime version check in the client application. Implied for static library builds + * and when version tagging is not used in a shared object. + * 1: Enables an automatic runtime version check in client applications that utilise low-level C++ API, + * i.e. when MT32EMU_API_TYPE 0. Client applications that rely on the C-compatible API are supposed + * to check the version of the shared object by other means (e.g. using versioned C symbols, etc.). + * 2: Enables an automatic runtime version check for C++ and C client applications. + */ +#if MT32EMU_WITH_VERSION_TAGGING +# ifndef MT32EMU_RUNTIME_VERSION_CHECK +# define MT32EMU_RUNTIME_VERSION_CHECK @libmt32emu_RUNTIME_VERSION_CHECK@ +# endif +#else +# undef MT32EMU_RUNTIME_VERSION_CHECK #endif + +#endif /* #ifndef MT32EMU_CONFIG_H */ diff --git a/src/sound/munt/globals.h b/src/sound/munt/globals.h index 243ff82ae..86ac1ca5b 100644 --- a/src/sound/munt/globals.h +++ b/src/sound/munt/globals.h @@ -1,5 +1,5 @@ /* Copyright (C) 2003, 2004, 2005, 2006, 2008, 2009 Dean Beeler, Jerome Fisher - * Copyright (C) 2011-2020 Dean Beeler, Jerome Fisher, Sergey V. Mikayev + * Copyright (C) 2011-2022 Dean Beeler, Jerome Fisher, Sergey V. Mikayev * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by @@ -20,27 +20,35 @@ #include "config.h" -/* Support for compiling shared library. */ +/* Support for compiling shared library. + * MT32EMU_SHARED and mt32emu_EXPORTS are defined when building a shared library. + * MT32EMU_SHARED should also be defined for Windows platforms that provides for a small performance benefit, + * and it _must_ be defined along with MT32EMU_RUNTIME_VERSION_CHECK when using MSVC. + */ #ifdef MT32EMU_SHARED -#if defined _WIN32 || defined __CYGWIN__ -#ifdef _MSC_VER -#ifdef mt32emu_EXPORTS -#define MT32EMU_EXPORT_ATTRIBUTE _declspec(dllexport) -#else /* #ifdef mt32emu_EXPORTS */ -#define MT32EMU_EXPORT_ATTRIBUTE _declspec(dllimport) -#endif /* #ifdef mt32emu_EXPORTS */ -#else /* #ifdef _MSC_VER */ -#ifdef mt32emu_EXPORTS -#define MT32EMU_EXPORT_ATTRIBUTE __attribute__ ((dllexport)) -#else /* #ifdef mt32emu_EXPORTS */ -#define MT32EMU_EXPORT_ATTRIBUTE __attribute__ ((dllimport)) -#endif /* #ifdef mt32emu_EXPORTS */ -#endif /* #ifdef _MSC_VER */ -#else /* #if defined _WIN32 || defined __CYGWIN__ */ -#define MT32EMU_EXPORT_ATTRIBUTE __attribute__ ((visibility("default"))) -#endif /* #if defined _WIN32 || defined __CYGWIN__ */ +# if defined _WIN32 || defined __CYGWIN__ || defined __OS2__ +# ifdef _MSC_VER +# ifdef mt32emu_EXPORTS +# define MT32EMU_EXPORT_ATTRIBUTE _declspec(dllexport) +# else /* #ifdef mt32emu_EXPORTS */ +# define MT32EMU_EXPORT_ATTRIBUTE _declspec(dllimport) +# endif /* #ifdef mt32emu_EXPORTS */ +# else /* #ifdef _MSC_VER */ +# ifdef mt32emu_EXPORTS +# define MT32EMU_EXPORT_ATTRIBUTE __attribute__ ((dllexport)) +# else /* #ifdef mt32emu_EXPORTS */ +# define MT32EMU_EXPORT_ATTRIBUTE __attribute__ ((dllimport)) +# endif /* #ifdef mt32emu_EXPORTS */ +# endif /* #ifdef _MSC_VER */ +# else /* #if defined _WIN32 || defined __CYGWIN__ || defined __OS2__ */ +# ifdef mt32emu_EXPORTS +# define MT32EMU_EXPORT_ATTRIBUTE __attribute__ ((visibility("default"))) +# else /* #ifdef mt32emu_EXPORTS */ +# define MT32EMU_EXPORT_ATTRIBUTE +# endif /* #ifdef mt32emu_EXPORTS */ +# endif /* #if defined _WIN32 || defined __CYGWIN__ || defined __OS2__ */ #else /* #ifdef MT32EMU_SHARED */ -#define MT32EMU_EXPORT_ATTRIBUTE +# define MT32EMU_EXPORT_ATTRIBUTE #endif /* #ifdef MT32EMU_SHARED */ #if MT32EMU_EXPORTS_TYPE == 1 || MT32EMU_EXPORTS_TYPE == 2 @@ -49,6 +57,33 @@ #define MT32EMU_EXPORT MT32EMU_EXPORT_ATTRIBUTE #endif +/* Facilitates easier tracking of the library version when an external symbol was introduced. + * Particularly useful for shared library builds on POSIX systems that support symbol versioning, + * so that the version map file can be generated automatically. + */ +#define MT32EMU_EXPORT_V(symbol_version_tag) MT32EMU_EXPORT + +/* Helpers for compile-time version checks */ + +/* Encodes the given version components to a single integer value to simplify further checks. */ +#define MT32EMU_VERSION_INT(major, minor, patch) ((major << 16) | (minor << 8) | patch) + +/* The version of this library build, as an integer. */ +#define MT32EMU_CURRENT_VERSION_INT MT32EMU_VERSION_INT(MT32EMU_VERSION_MAJOR, MT32EMU_VERSION_MINOR, MT32EMU_VERSION_PATCH) + +/* Compares the current library version with the given version components. Intended for feature checks. */ +#define MT32EMU_VERSION_ATLEAST(major, minor, patch) (MT32EMU_CURRENT_VERSION_INT >= MT32EMU_VERSION_INT(major, minor, patch)) + +/* Implements a simple version check that ensures full API compatibility of this library build + * with the application requirements. The latter can be derived from the versions of used public symbols. + * + * Note: This macro is intended for a quick compile-time check. To ensure compatibility of an application + * linked with a shared library, an automatic version check can be engaged with help of the build option + * libmt32emu_WITH_VERSION_TAGGING. For a fine-grained feature checking in run-time, see functions + * mt32emu_get_library_version_int and Synth::getLibraryVersionInt. + */ +#define MT32EMU_IS_COMPATIBLE(major, minor) (MT32EMU_VERSION_MAJOR == major && MT32EMU_VERSION_MINOR >= minor) + /* Useful constants */ /* Sample rate to use in mixing. With the progress of development, we've found way too many thing dependent. diff --git a/src/sound/munt/internals.h b/src/sound/munt/internals.h index 8a609546c..1b3ad0de2 100644 --- a/src/sound/munt/internals.h +++ b/src/sound/munt/internals.h @@ -1,5 +1,5 @@ /* Copyright (C) 2003, 2004, 2005, 2006, 2008, 2009 Dean Beeler, Jerome Fisher - * Copyright (C) 2011-2020 Dean Beeler, Jerome Fisher, Sergey V. Mikayev + * Copyright (C) 2011-2022 Dean Beeler, Jerome Fisher, Sergey V. Mikayev * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by diff --git a/src/sound/munt/mmath.h b/src/sound/munt/mmath.h index a66fad566..3164c7bfc 100644 --- a/src/sound/munt/mmath.h +++ b/src/sound/munt/mmath.h @@ -1,5 +1,5 @@ /* Copyright (C) 2003, 2004, 2005, 2006, 2008, 2009 Dean Beeler, Jerome Fisher - * Copyright (C) 2011-2020 Dean Beeler, Jerome Fisher, Sergey V. Mikayev + * Copyright (C) 2011-2022 Dean Beeler, Jerome Fisher, Sergey V. Mikayev * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by diff --git a/src/sound/munt/mt32emu.h b/src/sound/munt/mt32emu.h index cfb50fb28..571b25571 100644 --- a/src/sound/munt/mt32emu.h +++ b/src/sound/munt/mt32emu.h @@ -1,5 +1,5 @@ /* Copyright (C) 2003, 2004, 2005, 2006, 2008, 2009 Dean Beeler, Jerome Fisher - * Copyright (C) 2011-2020 Dean Beeler, Jerome Fisher, Sergey V. Mikayev + * Copyright (C) 2011-2022 Dean Beeler, Jerome Fisher, Sergey V. Mikayev * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by @@ -37,28 +37,23 @@ */ #ifdef MT32EMU_API_TYPE -#if MT32EMU_API_TYPE == 0 && (MT32EMU_EXPORTS_TYPE == 1 || MT32EMU_EXPORTS_TYPE == 2) -#error Incompatible setting MT32EMU_API_TYPE=0 -#elif MT32EMU_API_TYPE == 1 && (MT32EMU_EXPORTS_TYPE == 0 || MT32EMU_EXPORTS_TYPE == 2) -#error Incompatible setting MT32EMU_API_TYPE=1 -#elif MT32EMU_API_TYPE == 2 && (MT32EMU_EXPORTS_TYPE == 0) -#error Incompatible setting MT32EMU_API_TYPE=2 -#elif MT32EMU_API_TYPE == 3 && (MT32EMU_EXPORTS_TYPE == 0 || MT32EMU_EXPORTS_TYPE == 2) -#error Incompatible setting MT32EMU_API_TYPE=3 -#endif +# if MT32EMU_API_TYPE == 0 && (MT32EMU_EXPORTS_TYPE == 1 || MT32EMU_EXPORTS_TYPE == 2) +# error Incompatible setting MT32EMU_API_TYPE=0 +# elif MT32EMU_API_TYPE == 1 && (MT32EMU_EXPORTS_TYPE == 0 || MT32EMU_EXPORTS_TYPE == 2) +# error Incompatible setting MT32EMU_API_TYPE=1 +# elif MT32EMU_API_TYPE == 2 && (MT32EMU_EXPORTS_TYPE == 0) +# error Incompatible setting MT32EMU_API_TYPE=2 +# elif MT32EMU_API_TYPE == 3 && (MT32EMU_EXPORTS_TYPE == 0 || MT32EMU_EXPORTS_TYPE == 2) +# error Incompatible setting MT32EMU_API_TYPE=3 +# endif #else /* #ifdef MT32EMU_API_TYPE */ -#if 0 < MT32EMU_EXPORTS_TYPE && MT32EMU_EXPORTS_TYPE < 3 -#define MT32EMU_API_TYPE MT32EMU_EXPORTS_TYPE -#else -#define MT32EMU_API_TYPE 0 -#endif +# if 0 < MT32EMU_EXPORTS_TYPE && MT32EMU_EXPORTS_TYPE < 3 +# define MT32EMU_API_TYPE MT32EMU_EXPORTS_TYPE +# else +# define MT32EMU_API_TYPE 0 +# endif #endif /* #ifdef MT32EMU_API_TYPE */ -/* MT32EMU_SHARED should be defined when building shared library, especially for Windows platforms. */ -/* -#define MT32EMU_SHARED -*/ - #include "globals.h" #if !defined(__cplusplus) || MT32EMU_API_TYPE == 1 @@ -79,6 +74,14 @@ #include "MidiStreamParser.h" #include "SampleRateConverter.h" +#if MT32EMU_RUNTIME_VERSION_CHECK == 1 +#include "VersionTagging.h" +#endif + #endif /* #if !defined(__cplusplus) || MT32EMU_API_TYPE == 1 */ +#if MT32EMU_RUNTIME_VERSION_CHECK == 2 +#include "VersionTagging.h" +#endif + #endif /* #ifndef MT32EMU_MT32EMU_H */ diff --git a/src/sound/munt/srchelper/InternalResampler.cpp b/src/sound/munt/srchelper/InternalResampler.cpp index 56bd1ac05..4e6a5a748 100644 --- a/src/sound/munt/srchelper/InternalResampler.cpp +++ b/src/sound/munt/srchelper/InternalResampler.cpp @@ -1,4 +1,4 @@ -/* Copyright (C) 2015-2020 Sergey V. Mikayev +/* Copyright (C) 2015-2022 Sergey V. Mikayev * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by diff --git a/src/sound/munt/srchelper/InternalResampler.h b/src/sound/munt/srchelper/InternalResampler.h index cf08c8261..a80cc7dc4 100644 --- a/src/sound/munt/srchelper/InternalResampler.h +++ b/src/sound/munt/srchelper/InternalResampler.h @@ -1,4 +1,4 @@ -/* Copyright (C) 2015-2020 Sergey V. Mikayev +/* Copyright (C) 2015-2022 Sergey V. Mikayev * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by diff --git a/src/sound/munt/srchelper/SamplerateAdapter.cpp b/src/sound/munt/srchelper/SamplerateAdapter.cpp index 2a417ed2e..aeb695a2e 100644 --- a/src/sound/munt/srchelper/SamplerateAdapter.cpp +++ b/src/sound/munt/srchelper/SamplerateAdapter.cpp @@ -1,4 +1,4 @@ -/* Copyright (C) 2015-2020 Sergey V. Mikayev +/* Copyright (C) 2015-2022 Sergey V. Mikayev * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by diff --git a/src/sound/munt/srchelper/SamplerateAdapter.h b/src/sound/munt/srchelper/SamplerateAdapter.h index eed9799a9..6da9b64aa 100644 --- a/src/sound/munt/srchelper/SamplerateAdapter.h +++ b/src/sound/munt/srchelper/SamplerateAdapter.h @@ -1,4 +1,4 @@ -/* Copyright (C) 2015-2020 Sergey V. Mikayev +/* Copyright (C) 2015-2022 Sergey V. Mikayev * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by diff --git a/src/sound/munt/srchelper/SoxrAdapter.cpp b/src/sound/munt/srchelper/SoxrAdapter.cpp index a88c133ec..754f55d56 100644 --- a/src/sound/munt/srchelper/SoxrAdapter.cpp +++ b/src/sound/munt/srchelper/SoxrAdapter.cpp @@ -1,4 +1,4 @@ -/* Copyright (C) 2015-2020 Sergey V. Mikayev +/* Copyright (C) 2015-2022 Sergey V. Mikayev * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by diff --git a/src/sound/munt/srchelper/SoxrAdapter.h b/src/sound/munt/srchelper/SoxrAdapter.h index c6b9d3ade..2abcbdd8a 100644 --- a/src/sound/munt/srchelper/SoxrAdapter.h +++ b/src/sound/munt/srchelper/SoxrAdapter.h @@ -1,4 +1,4 @@ -/* Copyright (C) 2015-2020 Sergey V. Mikayev +/* Copyright (C) 2015-2022 Sergey V. Mikayev * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by diff --git a/src/sound/munt/srchelper/srctools/include/FIRResampler.h b/src/sound/munt/srchelper/srctools/include/FIRResampler.h index 9032131dc..b8e0be1bb 100644 --- a/src/sound/munt/srchelper/srctools/include/FIRResampler.h +++ b/src/sound/munt/srchelper/srctools/include/FIRResampler.h @@ -1,4 +1,4 @@ -/* Copyright (C) 2015-2020 Sergey V. Mikayev +/* Copyright (C) 2015-2022 Sergey V. Mikayev * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by diff --git a/src/sound/munt/srchelper/srctools/include/FloatSampleProvider.h b/src/sound/munt/srchelper/srctools/include/FloatSampleProvider.h index 4056db373..9b88bced6 100644 --- a/src/sound/munt/srchelper/srctools/include/FloatSampleProvider.h +++ b/src/sound/munt/srchelper/srctools/include/FloatSampleProvider.h @@ -1,4 +1,4 @@ -/* Copyright (C) 2015-2020 Sergey V. Mikayev +/* Copyright (C) 2015-2022 Sergey V. Mikayev * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by diff --git a/src/sound/munt/srchelper/srctools/include/IIR2xResampler.h b/src/sound/munt/srchelper/srctools/include/IIR2xResampler.h index ea150f9db..247d57568 100644 --- a/src/sound/munt/srchelper/srctools/include/IIR2xResampler.h +++ b/src/sound/munt/srchelper/srctools/include/IIR2xResampler.h @@ -1,4 +1,4 @@ -/* Copyright (C) 2015-2020 Sergey V. Mikayev +/* Copyright (C) 2015-2022 Sergey V. Mikayev * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by diff --git a/src/sound/munt/srchelper/srctools/include/LinearResampler.h b/src/sound/munt/srchelper/srctools/include/LinearResampler.h index 0e30ea2e9..a55f4ae67 100644 --- a/src/sound/munt/srchelper/srctools/include/LinearResampler.h +++ b/src/sound/munt/srchelper/srctools/include/LinearResampler.h @@ -1,4 +1,4 @@ -/* Copyright (C) 2015-2020 Sergey V. Mikayev +/* Copyright (C) 2015-2022 Sergey V. Mikayev * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by diff --git a/src/sound/munt/srchelper/srctools/include/ResamplerModel.h b/src/sound/munt/srchelper/srctools/include/ResamplerModel.h index b7a64f02e..622ccbb18 100644 --- a/src/sound/munt/srchelper/srctools/include/ResamplerModel.h +++ b/src/sound/munt/srchelper/srctools/include/ResamplerModel.h @@ -1,4 +1,4 @@ -/* Copyright (C) 2015-2020 Sergey V. Mikayev +/* Copyright (C) 2015-2022 Sergey V. Mikayev * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by diff --git a/src/sound/munt/srchelper/srctools/include/ResamplerStage.h b/src/sound/munt/srchelper/srctools/include/ResamplerStage.h index edd7678c1..2d8507037 100644 --- a/src/sound/munt/srchelper/srctools/include/ResamplerStage.h +++ b/src/sound/munt/srchelper/srctools/include/ResamplerStage.h @@ -1,4 +1,4 @@ -/* Copyright (C) 2015-2020 Sergey V. Mikayev +/* Copyright (C) 2015-2022 Sergey V. Mikayev * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by diff --git a/src/sound/munt/srchelper/srctools/include/SincResampler.h b/src/sound/munt/srchelper/srctools/include/SincResampler.h index bac844043..8db9f5bb9 100644 --- a/src/sound/munt/srchelper/srctools/include/SincResampler.h +++ b/src/sound/munt/srchelper/srctools/include/SincResampler.h @@ -1,4 +1,4 @@ -/* Copyright (C) 2015-2020 Sergey V. Mikayev +/* Copyright (C) 2015-2022 Sergey V. Mikayev * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by diff --git a/src/sound/munt/srchelper/srctools/src/FIRResampler.cpp b/src/sound/munt/srchelper/srctools/src/FIRResampler.cpp index b5ab5585c..0df8acd16 100644 --- a/src/sound/munt/srchelper/srctools/src/FIRResampler.cpp +++ b/src/sound/munt/srchelper/srctools/src/FIRResampler.cpp @@ -1,4 +1,4 @@ -/* Copyright (C) 2015-2020 Sergey V. Mikayev +/* Copyright (C) 2015-2022 Sergey V. Mikayev * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by diff --git a/src/sound/munt/srchelper/srctools/src/IIR2xResampler.cpp b/src/sound/munt/srchelper/srctools/src/IIR2xResampler.cpp index 98f7a3a5b..a09b48d9e 100644 --- a/src/sound/munt/srchelper/srctools/src/IIR2xResampler.cpp +++ b/src/sound/munt/srchelper/srctools/src/IIR2xResampler.cpp @@ -1,4 +1,4 @@ -/* Copyright (C) 2015-2020 Sergey V. Mikayev +/* Copyright (C) 2015-2022 Sergey V. Mikayev * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by diff --git a/src/sound/munt/srchelper/srctools/src/LinearResampler.cpp b/src/sound/munt/srchelper/srctools/src/LinearResampler.cpp index 1ca143a38..18224833b 100644 --- a/src/sound/munt/srchelper/srctools/src/LinearResampler.cpp +++ b/src/sound/munt/srchelper/srctools/src/LinearResampler.cpp @@ -1,4 +1,4 @@ -/* Copyright (C) 2015-2020 Sergey V. Mikayev +/* Copyright (C) 2015-2022 Sergey V. Mikayev * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by diff --git a/src/sound/munt/srchelper/srctools/src/ResamplerModel.cpp b/src/sound/munt/srchelper/srctools/src/ResamplerModel.cpp index 2a7f75822..504024629 100644 --- a/src/sound/munt/srchelper/srctools/src/ResamplerModel.cpp +++ b/src/sound/munt/srchelper/srctools/src/ResamplerModel.cpp @@ -1,4 +1,4 @@ -/* Copyright (C) 2015-2020 Sergey V. Mikayev +/* Copyright (C) 2015-2022 Sergey V. Mikayev * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by diff --git a/src/sound/munt/srchelper/srctools/src/SincResampler.cpp b/src/sound/munt/srchelper/srctools/src/SincResampler.cpp index 60a18256c..de9048093 100644 --- a/src/sound/munt/srchelper/srctools/src/SincResampler.cpp +++ b/src/sound/munt/srchelper/srctools/src/SincResampler.cpp @@ -1,4 +1,4 @@ -/* Copyright (C) 2015-2020 Sergey V. Mikayev +/* Copyright (C) 2015-2022 Sergey V. Mikayev * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by diff --git a/src/sound/openal.c b/src/sound/openal.c index 95619e79b..76656c66e 100644 --- a/src/sound/openal.c +++ b/src/sound/openal.c @@ -1,109 +1,106 @@ /* - * 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. + * 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. + * This file is part of the 86Box distribution. * - * Interface to the OpenAL sound processing library. + * Interface to the OpenAL sound processing library. * * * - * Authors: Sarah Walker, - * Miran Grca, + * Authors: Sarah Walker, + * Miran Grca, * - * Copyright 2008-2019 Sarah Walker. - * Copyright 2016-2019 Miran Grca. + * Copyright 2008-2019 Sarah Walker. + * Copyright 2016-2019 Miran Grca. */ #include -#include #include -#include +#include #include +#include #include -# undef AL_API -# undef ALC_API -# define AL_LIBTYPE_STATIC -# define ALC_LIBTYPE_STATIC -# include "AL/al.h" -# include "AL/alc.h" -# include "AL/alext.h" +#undef AL_API +#undef ALC_API +#define AL_LIBTYPE_STATIC +#define ALC_LIBTYPE_STATIC + +#include "AL/al.h" +#include "AL/alc.h" +#include "AL/alext.h" #include <86box/86box.h> -#include <86box/sound.h> #include <86box/midi.h> +#include <86box/sound.h> +#include <86box/plat_unused.h> +#define FREQ SOUND_FREQ +#define BUFLEN SOUNDBUFLEN -#define FREQ 48000 -#define BUFLEN SOUNDBUFLEN +ALuint buffers[4]; /* front and back buffers */ +ALuint buffers_cd[4]; /* front and back buffers */ +ALuint buffers_midi[4]; /* front and back buffers */ +static ALuint source[3]; /* audio source */ - -ALuint buffers[4]; /* front and back buffers */ -ALuint buffers_cd[4]; /* front and back buffers */ -ALuint buffers_midi[4]; /* front and back buffers */ -static ALuint source[3]; /* audio source */ - - -static int midi_freq = 44100; -static int midi_buf_size = 4410; -static int initialized = 0; -static int sources = 2; +static int midi_freq = 44100; +static int midi_buf_size = 4410; +static int initialized = 0; +static int sources = 2; static ALCcontext *Context; -static ALCdevice *Device; +static ALCdevice *Device; void al_set_midi(int freq, int buf_size) { - midi_freq = freq; + midi_freq = freq; midi_buf_size = buf_size; } - void closeal(void); -ALvoid alutInit(ALint *argc,ALbyte **argv) +ALvoid +alutInit(UNUSED(ALint *argc), UNUSED(ALbyte **argv)) { /* Open device */ - Device = alcOpenDevice((ALCchar *)""); + Device = alcOpenDevice((ALCchar *) ""); if (Device != NULL) { - /* Create context(s) */ - Context = alcCreateContext(Device, NULL); - if (Context != NULL) { - /* Set active context */ - alcMakeContextCurrent(Context); - } + /* Create context(s) */ + Context = alcCreateContext(Device, NULL); + if (Context != NULL) { + /* Set active context */ + alcMakeContextCurrent(Context); + } } } - ALvoid -alutExit(ALvoid) +alutExit(ALvoid) { if (Context != NULL) { - /* Disable context */ - alcMakeContextCurrent(NULL); + /* Disable context */ + alcMakeContextCurrent(NULL); - /* Release context(s) */ - alcDestroyContext(Context); + /* Release context(s) */ + alcDestroyContext(Context); - if (Device != NULL) { - /* Close device */ - alcCloseDevice(Device); - } + if (Device != NULL) { + /* Close device */ + alcCloseDevice(Device); + } } } - void closeal(void) { if (!initialized) - return; + return; alSourceStopv(sources, source); alDeleteSources(sources, source); if (sources == 3) - alDeleteBuffers(4, buffers_midi); + alDeleteBuffers(4, buffers_midi); alDeleteBuffers(4, buffers_cd); alDeleteBuffers(4, buffers); @@ -112,168 +109,166 @@ closeal(void) initialized = 0; } - void inital(void) { - float *buf = NULL, *cd_buf = NULL, *midi_buf = NULL; - int16_t *buf_int16 = NULL, *cd_buf_int16 = NULL, *midi_buf_int16 = NULL; - int c; + float *buf = NULL; + float *cd_buf = NULL; + float *midi_buf = NULL; + int16_t *buf_int16 = NULL; + int16_t *cd_buf_int16 = NULL; + int16_t *midi_buf_int16 = NULL; - char *mdn; - int init_midi = 0; + const char *mdn; + int init_midi = 0; if (initialized) - return; + return; alutInit(0, 0); atexit(closeal); - mdn = midi_device_get_internal_name(midi_device_current); + mdn = midi_out_device_get_internal_name(midi_output_device_current); if (strcmp(mdn, "none") && strcmp(mdn, SYSTEM_MIDI_INTERNAL_NAME)) - init_midi = 1; /* If the device is neither none, nor system MIDI, initialize the - MIDI buffer and source, otherwise, do not. */ + init_midi = 1; /* If the device is neither none, nor system MIDI, initialize the + MIDI buffer and source, otherwise, do not. */ sources = 2 + !!init_midi; if (sound_is_float) { - buf = (float *) malloc((BUFLEN << 1) * sizeof(float)); - cd_buf = (float *) malloc((CD_BUFLEN << 1) * sizeof(float)); - if (init_midi) - midi_buf = (float *) malloc(midi_buf_size * sizeof(float)); + buf = (float *) calloc((BUFLEN << 1), sizeof(float)); + cd_buf = (float *) calloc((CD_BUFLEN << 1), sizeof(float)); + if (init_midi) + midi_buf = (float *) calloc(midi_buf_size, sizeof(float)); } else { - buf_int16 = (int16_t *) malloc((BUFLEN << 1) * sizeof(int16_t)); - cd_buf_int16 = (int16_t *) malloc((CD_BUFLEN << 1) * sizeof(int16_t)); - if (init_midi) - midi_buf_int16 = (int16_t *) malloc(midi_buf_size * sizeof(int16_t)); + buf_int16 = (int16_t *) calloc((BUFLEN << 1), sizeof(int16_t)); + cd_buf_int16 = (int16_t *) calloc((CD_BUFLEN << 1), sizeof(int16_t)); + if (init_midi) + midi_buf_int16 = (int16_t *) calloc(midi_buf_size, sizeof(int16_t)); } alGenBuffers(4, buffers); alGenBuffers(4, buffers_cd); if (init_midi) - alGenBuffers(4, buffers_midi); + alGenBuffers(4, buffers_midi); if (init_midi) - alGenSources(3, source); + alGenSources(3, source); else - alGenSources(2, source); + alGenSources(2, source); - alSource3f(source[0], AL_POSITION, 0.0, 0.0, 0.0); - alSource3f(source[0], AL_VELOCITY, 0.0, 0.0, 0.0); - alSource3f(source[0], AL_DIRECTION, 0.0, 0.0, 0.0); - alSourcef (source[0], AL_ROLLOFF_FACTOR, 0.0 ); - alSourcei (source[0], AL_SOURCE_RELATIVE, AL_TRUE ); - alSource3f(source[1], AL_POSITION, 0.0, 0.0, 0.0); - alSource3f(source[1], AL_VELOCITY, 0.0, 0.0, 0.0); - alSource3f(source[1], AL_DIRECTION, 0.0, 0.0, 0.0); - alSourcef (source[1], AL_ROLLOFF_FACTOR, 0.0 ); - alSourcei (source[1], AL_SOURCE_RELATIVE, AL_TRUE ); + alSource3f(source[0], AL_POSITION, 0.0, 0.0, 0.0); + alSource3f(source[0], AL_VELOCITY, 0.0, 0.0, 0.0); + alSource3f(source[0], AL_DIRECTION, 0.0, 0.0, 0.0); + alSourcef(source[0], AL_ROLLOFF_FACTOR, 0.0); + alSourcei(source[0], AL_SOURCE_RELATIVE, AL_TRUE); + alSource3f(source[1], AL_POSITION, 0.0, 0.0, 0.0); + alSource3f(source[1], AL_VELOCITY, 0.0, 0.0, 0.0); + alSource3f(source[1], AL_DIRECTION, 0.0, 0.0, 0.0); + alSourcef(source[1], AL_ROLLOFF_FACTOR, 0.0); + alSourcei(source[1], AL_SOURCE_RELATIVE, AL_TRUE); if (init_midi) { - alSource3f(source[2], AL_POSITION, 0.0, 0.0, 0.0); - alSource3f(source[2], AL_VELOCITY, 0.0, 0.0, 0.0); - alSource3f(source[2], AL_DIRECTION, 0.0, 0.0, 0.0); - alSourcef (source[2], AL_ROLLOFF_FACTOR, 0.0 ); - alSourcei (source[2], AL_SOURCE_RELATIVE, AL_TRUE ); + alSource3f(source[2], AL_POSITION, 0.0, 0.0, 0.0); + alSource3f(source[2], AL_VELOCITY, 0.0, 0.0, 0.0); + alSource3f(source[2], AL_DIRECTION, 0.0, 0.0, 0.0); + alSourcef(source[2], AL_ROLLOFF_FACTOR, 0.0); + alSourcei(source[2], AL_SOURCE_RELATIVE, AL_TRUE); } if (sound_is_float) { - memset(buf,0,BUFLEN*2*sizeof(float)); - memset(cd_buf,0,BUFLEN*2*sizeof(float)); - if (init_midi) - memset(midi_buf,0,midi_buf_size*sizeof(float)); + memset(buf, 0, BUFLEN * 2 * sizeof(float)); + memset(cd_buf, 0, BUFLEN * 2 * sizeof(float)); + if (init_midi) + memset(midi_buf, 0, midi_buf_size * sizeof(float)); } else { - memset(buf_int16,0,BUFLEN*2*sizeof(int16_t)); - memset(cd_buf_int16,0,BUFLEN*2*sizeof(int16_t)); - if (init_midi) - memset(midi_buf_int16,0,midi_buf_size*sizeof(int16_t)); + memset(buf_int16, 0, BUFLEN * 2 * sizeof(int16_t)); + memset(cd_buf_int16, 0, BUFLEN * 2 * sizeof(int16_t)); + if (init_midi) + memset(midi_buf_int16, 0, midi_buf_size * sizeof(int16_t)); } - for (c=0; c<4; c++) { - if (sound_is_float) { - alBufferData(buffers[c], AL_FORMAT_STEREO_FLOAT32, buf, BUFLEN*2*sizeof(float), FREQ); - alBufferData(buffers_cd[c], AL_FORMAT_STEREO_FLOAT32, cd_buf, CD_BUFLEN*2*sizeof(float), CD_FREQ); - if (init_midi) - alBufferData(buffers_midi[c], AL_FORMAT_STEREO_FLOAT32, midi_buf, midi_buf_size*sizeof(float), midi_freq); - } else { - alBufferData(buffers[c], AL_FORMAT_STEREO16, buf_int16, BUFLEN*2*sizeof(int16_t), FREQ); - alBufferData(buffers_cd[c], AL_FORMAT_STEREO16, cd_buf_int16, CD_BUFLEN*2*sizeof(int16_t), CD_FREQ); - if (init_midi) - alBufferData(buffers_midi[c], AL_FORMAT_STEREO16, midi_buf_int16, midi_buf_size*sizeof(int16_t), midi_freq); - } + for (uint8_t c = 0; c < 4; c++) { + if (sound_is_float) { + alBufferData(buffers[c], AL_FORMAT_STEREO_FLOAT32, buf, BUFLEN * 2 * sizeof(float), FREQ); + alBufferData(buffers_cd[c], AL_FORMAT_STEREO_FLOAT32, cd_buf, CD_BUFLEN * 2 * sizeof(float), CD_FREQ); + if (init_midi) + alBufferData(buffers_midi[c], AL_FORMAT_STEREO_FLOAT32, midi_buf, midi_buf_size * sizeof(float), midi_freq); + } else { + alBufferData(buffers[c], AL_FORMAT_STEREO16, buf_int16, BUFLEN * 2 * sizeof(int16_t), FREQ); + alBufferData(buffers_cd[c], AL_FORMAT_STEREO16, cd_buf_int16, CD_BUFLEN * 2 * sizeof(int16_t), CD_FREQ); + if (init_midi) + alBufferData(buffers_midi[c], AL_FORMAT_STEREO16, midi_buf_int16, midi_buf_size * sizeof(int16_t), midi_freq); + } } alSourceQueueBuffers(source[0], 4, buffers); alSourceQueueBuffers(source[1], 4, buffers_cd); if (init_midi) - alSourceQueueBuffers(source[2], 4, buffers_midi); + alSourceQueueBuffers(source[2], 4, buffers_midi); alSourcePlay(source[0]); alSourcePlay(source[1]); if (init_midi) - alSourcePlay(source[2]); + alSourcePlay(source[2]); if (sound_is_float) { - if (init_midi) - free(midi_buf); - free(cd_buf); - free(buf); + if (init_midi) + free(midi_buf); + free(cd_buf); + free(buf); } else { - if (init_midi) - free(midi_buf_int16); - free(cd_buf_int16); - free(buf_int16); + if (init_midi) + free(midi_buf_int16); + free(cd_buf_int16); + free(buf_int16); } initialized = 1; } - void givealbuffer_common(void *buf, uint8_t src, int size, int freq) { - int processed; - int state; + int processed; + int state; ALuint buffer; double gain; if (!initialized) - return; + return; alGetSourcei(source[src], AL_SOURCE_STATE, &state); if (state == 0x1014) { - alSourcePlay(source[src]); + alSourcePlay(source[src]); } alGetSourcei(source[src], AL_BUFFERS_PROCESSED, &processed); if (processed >= 1) { - gain = pow(10.0, (double)sound_gain / 20.0); - alListenerf(AL_GAIN, gain); + gain = pow(10.0, (double) sound_gain / 20.0); + alListenerf(AL_GAIN, gain); - alSourceUnqueueBuffers(source[src], 1, &buffer); + alSourceUnqueueBuffers(source[src], 1, &buffer); - if (sound_is_float) - alBufferData(buffer, AL_FORMAT_STEREO_FLOAT32, buf, size * sizeof(float), freq); - else - alBufferData(buffer, AL_FORMAT_STEREO16, buf, size * sizeof(int16_t), freq); + if (sound_is_float) + alBufferData(buffer, AL_FORMAT_STEREO_FLOAT32, buf, size * sizeof(float), freq); + else + alBufferData(buffer, AL_FORMAT_STEREO16, buf, size * sizeof(int16_t), freq); - alSourceQueueBuffers(source[src], 1, &buffer); + alSourceQueueBuffers(source[src], 1, &buffer); } } - void givealbuffer(void *buf) { givealbuffer_common(buf, 0, BUFLEN << 1, FREQ); } - void givealbuffer_cd(void *buf) { givealbuffer_common(buf, 1, CD_BUFLEN << 1, CD_FREQ); } - void givealbuffer_midi(void *buf, uint32_t size) { diff --git a/src/sound/resid-fp/CMakeLists.txt b/src/sound/resid-fp/CMakeLists.txt index fb9b5396e..699fcae54 100644 --- a/src/sound/resid-fp/CMakeLists.txt +++ b/src/sound/resid-fp/CMakeLists.txt @@ -1,16 +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. +# 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. +# This file is part of the 86Box distribution. # -# CMake build script. +# CMake build script. # -# Authors: David HrdliÄka, +# Authors: David HrdliÄka, # -# Copyright 2020,2021 David HrdliÄka. +# Copyright 2020-2021 David HrdliÄka. # add_library(resid-fp STATIC convolve-sse.cc convolve.cc envelope.cc extfilt.cc diff --git a/src/sound/resid-fp/envelope.h b/src/sound/resid-fp/envelope.h index 556e71a47..af0764ccd 100644 --- a/src/sound/resid-fp/envelope.h +++ b/src/sound/resid-fp/envelope.h @@ -130,7 +130,7 @@ void EnvelopeGeneratorFP::clock() --envelope_counter &= 0xff; break; } - + // Check for change of exponential counter period. switch (envelope_counter) { case 0xff: diff --git a/src/sound/resid-fp/filter.h b/src/sound/resid-fp/filter.h index 13e6aa67e..9ca254564 100644 --- a/src/sound/resid-fp/filter.h +++ b/src/sound/resid-fp/filter.h @@ -57,7 +57,7 @@ // // SID filter // ---------- -// +// // ----------------------------------------------- // | | // | ---Rq-- | @@ -66,15 +66,15 @@ // | | | | // | | ---C---| ---C---| // | | | | | | -// | --R1-- ---R1-- |---Rs--| |---Rs--| +// | --R1-- ---R1-- |---Rs--| |---Rs--| // | | | | | | | | // ----R1--|-----[A>--|--R-----[A>--|--R-----[A>--| // | | | | // vi -----R1-- | | | -// +// // vhp vbp vlp -// -// +// +// // vi - input voltage // vhp - highpass output // vbp - bandpass output @@ -85,14 +85,14 @@ // R - NMOS FET voltage controlled resistor controlling cutoff frequency // Rs - shunt resitor // C - capacitor -// -// -// +// +// +// // SID integrator // -------------- -// +// // V+ -// +// // | // | // -----| @@ -114,7 +114,7 @@ // R1 V- // | // | -// +// // Vw // // ---------------------------------------------------------------------------- @@ -312,7 +312,7 @@ float FilterFP::clock(float voice1, else if (! voice3off) Vnf += voice3; ((filt & 8) ? Vi : Vnf) += ext_in; - + if (! enabled) return (Vnf - Vi) * volf; @@ -322,7 +322,7 @@ float FilterFP::clock(float voice1, Vf += Vbp; if (hp_bp_lp & 4) Vf += Vhp; - + if (model == MOS6581FP) { float diff1, diff2; @@ -345,7 +345,7 @@ float FilterFP::clock(float voice1, Vbp += (Vf + Vnf - Vbp) * distortion_cf_threshold; if (hp_bp_lp & 4) Vhp += (Vf + Vnf - Vhp) * distortion_cf_threshold; - + /* Simulating the exponential VCR that the FET block is... */ Vlp -= Vbp * type3_w0(Vbp, type3_fc_distortion_offset_bp); Vbp -= Vhp * type3_w0(Vhp, type3_fc_distortion_offset_hp) * outputleveldifference_bp_hp; @@ -354,7 +354,7 @@ float FilterFP::clock(float voice1, * discontinuity but a saturation effect... */ if (Vnf > 3.2e6f) Vnf = 3.2e6f; - + Vf += Vnf + Vlp * (outputleveldifference_lp_bp - 1.f); } else { /* On the 8580, BP appears mixed in phase with the rest. */ @@ -364,7 +364,7 @@ float FilterFP::clock(float voice1, Vf += Vnf; } - + return Vf * volf; } diff --git a/src/sound/resid-fp/sid.cc b/src/sound/resid-fp/sid.cc index 6f7544423..ad72d9d51 100644 --- a/src/sound/resid-fp/sid.cc +++ b/src/sound/resid-fp/sid.cc @@ -91,6 +91,7 @@ static int host_cpu_features_by_cpuid(void) return features; } +#if (RESID_USE_SSE==1) static int host_cpu_features(void) { static int features = 0; @@ -152,6 +153,7 @@ static int host_cpu_features(void) return 0; } #endif +#endif float SIDFP::kinked_dac(const int x, const float nonlinearity, const int max) { diff --git a/src/sound/resid-fp/sid.h b/src/sound/resid-fp/sid.h index 6dad2e0c4..5180898fb 100644 --- a/src/sound/resid-fp/sid.h +++ b/src/sound/resid-fp/sid.h @@ -47,7 +47,7 @@ public: void clock(); int clock(cycle_count& delta_t, short* buf, int n, int interleave = 1); void reset(); - + // Read/write registers. reg8 read(reg8 offset); void write(reg8 offset, reg8 value); @@ -73,7 +73,7 @@ public: EnvelopeGeneratorFP::State envelope_state[3]; bool hold_zero[3]; }; - + State read_state(); void write_state(const State& state); @@ -114,7 +114,7 @@ protected: int sample_index; int fir_N; int fir_RES; - + // Linear interpolation helper float sample_prev; diff --git a/src/sound/resid-fp/wave.h b/src/sound/resid-fp/wave.h index 07d229ba0..64684228b 100644 --- a/src/sound/resid-fp/wave.h +++ b/src/sound/resid-fp/wave.h @@ -269,7 +269,7 @@ reg12 WaveformGeneratorFP::outputN___() // in the output. The reason for this has not been determined. // // Example: -// +// // 1 1 // Bit # 1 0 9 8 7 6 5 4 3 2 1 0 // ----------------------- @@ -303,14 +303,14 @@ reg12 WaveformGeneratorFP::outputN___() // // Sawtooth+Triangle: // The sawtooth output is used to look up an OSC3 sample. -// +// // Pulse+Triangle: // The triangle output is right-shifted and used to look up an OSC3 sample. // The sample is output if the pulse output is on. // The reason for using the triangle output as the index is to handle ring // modulation. Only the first half of the sample is used, which should be OK // since the triangle waveform has half the resolution of the accumulator. -// +// // Pulse+Sawtooth: // The sawtooth output is used to look up an OSC3 sample. // The sample is output if the pulse output is on. @@ -318,7 +318,7 @@ reg12 WaveformGeneratorFP::outputN___() // Pulse+Sawtooth+Triangle: // The sawtooth output is used to look up an OSC3 sample. // The sample is output if the pulse output is on. -// +// RESID_INLINE reg12 WaveformGeneratorFP::output__ST() { diff --git a/src/sound/snd_ac97_codec.c b/src/sound/snd_ac97_codec.c index dbccb2c9f..d302db6ae 100644 --- a/src/sound/snd_ac97_codec.c +++ b/src/sound/snd_ac97_codec.c @@ -1,109 +1,118 @@ /* - * 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. + * 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. + * This file is part of the 86Box distribution. * - * AC'97 audio codec emulation. + * AC'97 audio codec emulation. * * * - * Authors: RichardG, + * Authors: RichardG, * - * Copyright 2021 RichardG. + * Copyright 2021 RichardG. */ #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/snd_ac97.h> - +#include <86box/plat_fallthrough.h> static const struct { - const uint32_t vendor_id, min_rate, max_rate, misc_flags; /* definitions for misc_flags in snd_ac97.h */ - const uint16_t reset_flags, extid_flags, /* definitions in snd_ac97.h */ - powerdown_mask; /* bits [7:0] => register 26 bits [15:8]; bits [11:8] => register 2A bits [14:11] */ - const ac97_vendor_reg_t *vendor_regs; /* bits [11:8] of index are the page number if applicable (registers [60:6F]) */ - const device_t *device; -} ac97_codecs[] = { - [AC97_CODEC_AD1881] = { - .vendor_id = AC97_VENDOR_ID('A', 'D', 'S', 0x40), - .min_rate = 7000, - .max_rate = 48000, - .misc_flags = AC97_MASTER_6B | AC97_MONOOUT | AC97_PCBEEP | AC97_PHONE | AC97_VIDEO | AC97_AUXIN | AC97_POP | AC97_MS | AC97_LPBK, - .reset_flags = (1 << AC97_3D_SHIFT), /* datasheet contradicts itself on AC97_HPOUT */ - .extid_flags = AC97_VRA, - .powerdown_mask = 0x0bf, - .vendor_regs = (const ac97_vendor_reg_t[]) {{0x74, 0x0000, 0xff07}, {0x76, 0x0404, 0xdde5}, {0x78, 48000, 0x0000}, {0x7a, 48000, 0x0000}, {0}}, - .device = &ad1881_device - }, - [AC97_CODEC_AK4540] = { - .vendor_id = AC97_VENDOR_ID('A', 'K', 'M', 0x00), - .misc_flags = AC97_MONOOUT | AC97_PCBEEP | AC97_PHONE | AC97_VIDEO | AC97_AUXIN | AC97_MS | AC97_LPBK, - .powerdown_mask = 0x01f, - .device = &ak4540_device - }, - [AC97_CODEC_ALC100] = { - .vendor_id = AC97_VENDOR_ID('A', 'L', 'C', 0x20), - .misc_flags = AC97_AUXOUT | AC97_MONOOUT | AC97_PCBEEP | AC97_PHONE | AC97_VIDEO | AC97_AUXIN | AC97_POP | AC97_MS | AC97_LPBK, - .reset_flags = (22 << AC97_3D_SHIFT), - .extid_flags = AC97_AMAP, - .powerdown_mask = 0x0bf, - .device = &alc100_device - }, - [AC97_CODEC_CS4297] = { - .vendor_id = AC97_VENDOR_ID('C', 'R', 'Y', 0x03), - .misc_flags = AC97_MASTER_6B | AC97_AUXOUT | AC97_AUXOUT_6B | AC97_MONOOUT | AC97_MONOOUT_6B | AC97_PCBEEP | AC97_PHONE | AC97_VIDEO | AC97_AUXIN | AC97_MS | AC97_LPBK, - .reset_flags = AC97_HPOUT | AC97_DAC_18B | AC97_ADC_18B, - .extid_flags = 0, - .powerdown_mask = 0x07f, - .vendor_regs = (const ac97_vendor_reg_t[]) {{0x5a, 0x0301, 0x0000}, {0}}, - .device = &cs4297_device - }, - [AC97_CODEC_CS4297A] = { - .vendor_id = AC97_VENDOR_ID('C', 'R', 'Y', 0x11), - .misc_flags = AC97_MASTER_6B | AC97_AUXOUT | AC97_MONOOUT | AC97_PCBEEP | AC97_PHONE | AC97_VIDEO | AC97_AUXIN | AC97_MS | AC97_LPBK, - .reset_flags = AC97_HPOUT | AC97_DAC_20B | AC97_ADC_18B | (6 << AC97_3D_SHIFT), - .extid_flags = AC97_AMAP, - .powerdown_mask = 0x0ff, - .vendor_regs = (const ac97_vendor_reg_t[]) {{0x5e, 0x0000, 0x01b0}, {0x60, 0x0023, 0x0001}, {0x68, 0x0000, 0xdfff}, {0}}, - .device = &cs4297a_device - }, - [AC97_CODEC_STAC9708] = { - .vendor_id = AC97_VENDOR_ID(0x83, 0x84, 0x76, 0x08), - .misc_flags = AC97_AUXOUT | AC97_MONOOUT | AC97_PCBEEP | AC97_PHONE | AC97_VIDEO | AC97_AUXIN | AC97_MS | AC97_LPBK, - .reset_flags = (26 << AC97_3D_SHIFT) | AC97_DAC_18B | AC97_ADC_18B, - .extid_flags = AC97_SDAC, - .powerdown_mask = 0x2ff, - .vendor_regs = (const ac97_vendor_reg_t []) {{0x6c, 0x0000, 0x0003}, {0x74, 0x0000, 0x0003}, {0}}, - .device = &stac9708_device - }, - [AC97_CODEC_STAC9721] = { - .vendor_id = AC97_VENDOR_ID(0x83, 0x84, 0x76, 0x09), - .misc_flags = AC97_AUXOUT | AC97_MONOOUT | AC97_PCBEEP | AC97_PHONE | AC97_VIDEO | AC97_AUXIN | AC97_MS | AC97_LPBK, - .reset_flags = (26 << AC97_3D_SHIFT) | AC97_DAC_18B | AC97_ADC_18B, - .extid_flags = AC97_AMAP, - .powerdown_mask = 0x0ff, - .vendor_regs = (const ac97_vendor_reg_t []) {{0x6c, 0x0000, 0x0000}, {0x6e, 0x0000, 0x0003}, {0x70, 0x0000, 0xffff}, {0x72, 0x0000, 0x0006}, {0x74, 0x0000, 0x0003}, {0x76, 0x0000, 0xffff}, {0x78, 0x0000, 0x3802}, {0}}, - .device = &stac9721_device - }, - [AC97_CODEC_WM9701A] = { - .vendor_id = AC97_VENDOR_ID('W', 'M', 'L', 0x00), - .misc_flags = AC97_AUXOUT | AC97_MONOOUT | AC97_PCBEEP | AC97_PHONE | AC97_VIDEO | AC97_AUXIN | AC97_MS | AC97_LPBK, - .reset_flags = AC97_DAC_18B | AC97_ADC_18B, - .extid_flags = 0, - .powerdown_mask = 0x03f, - .device = &wm9701a_device - } -}; + const device_t *device; + /* Definitions for *_flags and vendor_regs in snd_ac97.h */ + uint32_t min_rate; + uint32_t max_rate; + uint32_t misc_flags; + uint16_t reset_flags; + uint16_t extid_flags; + uint8_t pcsr_mask; /* register 26 bits [15:8] */ + uint8_t eascr_mask; /* register 2A bits [14:11] */ + + const ac97_vendor_reg_t *vendor_regs; +} ac97_codecs[] = { + // clang-format off + { + .device = &ad1881_device, + .min_rate = 7000, + .max_rate = 48000, + .misc_flags = AC97_MASTER_6B | AC97_MONOOUT | AC97_PCBEEP | AC97_PHONE | AC97_VIDEO | AC97_AUXIN | AC97_POP | AC97_MS | AC97_LPBK, + .reset_flags = (1 << AC97_3D_SHIFT), /* datasheet contradicts itself on AC97_HPOUT */ + .extid_flags = AC97_VRA, + .pcsr_mask = 0xbf, + .vendor_regs = (const ac97_vendor_reg_t[]) {{0, 0x74, 0x0000, 0xff07}, {0, 0x76, 0x0404, 0xdde5}, {0, 0x78, 48000, 0x0000}, {0, 0x7a, 48000, 0x0000}, {0}} + }, + { + .device = &ak4540_device, + .misc_flags = AC97_MONOOUT | AC97_PCBEEP | AC97_PHONE | AC97_VIDEO | AC97_AUXIN | AC97_MS | AC97_LPBK, + .pcsr_mask = 0x1f + }, + { + .device = &alc100_device, + .misc_flags = AC97_AUXOUT | AC97_MONOOUT | AC97_PCBEEP | AC97_PHONE | AC97_VIDEO | AC97_AUXIN | AC97_POP | AC97_MS | AC97_LPBK, + .reset_flags = (22 << AC97_3D_SHIFT), + .extid_flags = AC97_AMAP, + .pcsr_mask = 0xbf + }, + { + .device = &cs4297_device, + .misc_flags = AC97_MASTER_6B | AC97_AUXOUT | AC97_AUXOUT_6B | AC97_MONOOUT | AC97_MONOOUT_6B | AC97_PCBEEP | AC97_PHONE | AC97_VIDEO | AC97_AUXIN | AC97_MS | AC97_LPBK, + .reset_flags = AC97_HPOUT | AC97_DAC_18B | AC97_ADC_18B, + .extid_flags = 0, + .pcsr_mask = 0x7f, + .vendor_regs = (const ac97_vendor_reg_t[]) {{0, 0x5a, 0x0301, 0x0000}, {0}} + }, + { + .device = &cs4297a_device, + .misc_flags = AC97_MASTER_6B | AC97_AUXOUT | AC97_MONOOUT | AC97_PCBEEP | AC97_PHONE | AC97_VIDEO | AC97_AUXIN | AC97_MS | AC97_LPBK, + .reset_flags = AC97_HPOUT | AC97_DAC_20B | AC97_ADC_18B | (6 << AC97_3D_SHIFT), + .extid_flags = AC97_AMAP, + .pcsr_mask = 0xff, + .vendor_regs = (const ac97_vendor_reg_t[]) {{0, 0x5e, 0x0000, 0x01b0}, {0, 0x60, 0x0023, 0x0001}, {0, 0x68, 0x0000, 0xdfff}, {0}} + }, + { + .device = &stac9708_device, + .misc_flags = AC97_AUXOUT | AC97_MONOOUT | AC97_PCBEEP | AC97_PHONE | AC97_VIDEO | AC97_AUXIN | AC97_MS | AC97_LPBK, + .reset_flags = (26 << AC97_3D_SHIFT) | AC97_DAC_18B | AC97_ADC_18B, + .extid_flags = AC97_SDAC, + .pcsr_mask = 0xff, + .eascr_mask = 0x02, + .vendor_regs = (const ac97_vendor_reg_t[]) {{0, 0x6c, 0x0000, 0x0003}, {0, 0x74, 0x0000, 0x0003}, {0}} + }, + { + .device = &stac9721_device, + .misc_flags = AC97_AUXOUT | AC97_MONOOUT | AC97_PCBEEP | AC97_PHONE | AC97_VIDEO | AC97_AUXIN | AC97_MS | AC97_LPBK, + .reset_flags = (26 << AC97_3D_SHIFT) | AC97_DAC_18B | AC97_ADC_18B, + .extid_flags = AC97_AMAP, + .pcsr_mask = 0xff, + .vendor_regs = (const ac97_vendor_reg_t[]) {{0, 0x6c, 0x0000, 0x0000}, {0, 0x6e, 0x0000, 0x0003}, {0, 0x70, 0x0000, 0xffff}, {0, 0x72, 0x0000, 0x0006}, {0, 0x74, 0x0000, 0x0003}, {0, 0x76, 0x0000, 0xffff}, {0, 0x78, 0x0000, 0x3802}, {0}} + }, + { + .device = &tr28023_device, + .misc_flags = AC97_MASTER_6B | AC97_MONOOUT | AC97_MONOOUT_6B | AC97_PCBEEP | AC97_PHONE | AC97_POP | AC97_MS | AC97_LPBK, + .reset_flags = 0, + .extid_flags = 0, + .pcsr_mask = 0x3f + }, + { + .device = &wm9701a_device, + .misc_flags = AC97_AUXOUT | AC97_MONOOUT | AC97_PCBEEP | AC97_PHONE | AC97_VIDEO | AC97_AUXIN | AC97_MS | AC97_LPBK, + .reset_flags = AC97_DAC_18B | AC97_ADC_18B, + .extid_flags = 0, + .pcsr_mask = 0x3f + } + // clang-format on +}; #ifdef ENABLE_AC97_CODEC_LOG int ac97_codec_do_log = ENABLE_AC97_CODEC_LOG; @@ -114,27 +123,31 @@ ac97_codec_log(const char *fmt, ...) va_list ap; if (ac97_codec_do_log) { - va_start(ap, fmt); - pclog_ex(fmt, ap); - va_end(ap); + va_start(ap, fmt); + pclog_ex(fmt, ap); + va_end(ap); } } #else -#define ac97_codec_log(fmt, ...) +# define ac97_codec_log(fmt, ...) #endif static const int32_t codec_attn[] = { + // clang-format off 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 2, 2, 2, 3, 4, 5, 6, 8, 10, 12, 16, 20, 25, 32, 41, 51, 65, 82, 103, 130, 164, 206, 260, 327, 412, 519, 653, 822, 1036, 1304, 1641, 2067, 2602, 3276, 4125, 5192, 6537, 8230, 10362, 13044, 16422, 20674, 26027, 32767, - 41305, 52068, 65636, 82739, 104299, 131477, 165737, 208925 + 41305, 52068, 65636, 82739, 104299, 131477, 165737, 208925 + // clang-format on }; -ac97_codec_t **ac97_codec = NULL, **ac97_modem_codec = NULL; -int ac97_codec_count = 0, ac97_modem_codec_count = 0, - ac97_codec_id = 0, ac97_modem_codec_id = 0; - +ac97_codec_t **ac97_codec = NULL; +ac97_codec_t **ac97_modem_codec = NULL; +int ac97_codec_count = 0; +int ac97_modem_codec_count = 0; +int ac97_codec_id = 0; +int ac97_modem_codec_id = 0; uint16_t ac97_codec_readw(ac97_codec_t *dev, uint8_t reg) @@ -143,311 +156,312 @@ ac97_codec_readw(ac97_codec_t *dev, uint8_t reg) reg &= 0x7e; uint16_t ret = dev->regs[0x24 >> 1] & 0x000f; if ((ret > 0) && (reg >= 0x60) && (reg < 0x6f)) - ret = (ret <= dev->vendor_reg_page_max) ? dev->vendor_reg_pages[(ret << 3) | ((reg & 0x0e) >> 1)] : 0; + ret = (ret <= dev->vendor_reg_page_max) ? dev->vendor_reg_pages[(ret << 3) | ((reg & 0x0e) >> 1)] : 0; else - ret = dev->regs[reg >> 1]; + ret = dev->regs[reg >> 1]; ac97_codec_log("AC97 Codec %d: readw(%02X) = %04X\n", dev->codec_id, reg, ret); return ret; } - void ac97_codec_writew(ac97_codec_t *dev, uint8_t reg, uint16_t val) { ac97_codec_log("AC97 Codec %d: writew(%02X, %04X)\n", dev->codec_id, reg, val); reg &= 0x7e; - uint16_t i = 0, prev = dev->regs[reg >> 1]; - int j; + uint16_t i = 0; + uint16_t prev = dev->regs[reg >> 1]; + int j; switch (reg) { - case 0x00: /* Reset / ID code */ - ac97_codec_reset(dev); - return; + case 0x00: /* Reset / ID code */ + ac97_codec_reset(dev); + return; - case 0x02: /* Master Volume */ - val &= 0xbf3f; + case 0x02: /* Master Volume */ + val &= 0xbf3f; - /* Convert 1xxxxx to 011111 where unsupported, per specification. */ - if (!(dev->misc_flags & AC97_MASTER_6B)) { -clamp_5b: if (val & 0x2000) - val = (val & ~0x2000) | 0x1f00; -clamp_5b_r: if (val & 0x0020) - val = (val & ~0x0020) | 0x001f; - } - break; + /* Convert 1xxxxx to 011111 where unsupported, per specification. */ + if (!(ac97_codecs[dev->model].misc_flags & AC97_MASTER_6B)) { +clamp_5b: + if (val & 0x2000) + val = (val & ~0x2000) | 0x1f00; +clamp_5b_r: + if (val & 0x0020) + val = (val & ~0x0020) | 0x001f; + } + break; - case 0x04: /* Aux Out Volume */ - if (!(dev->misc_flags & AC97_AUXOUT)) - return; - val &= 0xbf3f; + case 0x04: /* Aux Out Volume */ + if (!(ac97_codecs[dev->model].misc_flags & AC97_AUXOUT)) + return; + val &= 0xbf3f; - /* Convert 1xxxxx to 011111 where unsupported, per specification. */ - if (!(dev->misc_flags & AC97_AUXOUT_6B)) - goto clamp_5b; - break; + /* Convert 1xxxxx to 011111 where unsupported, per specification. */ + if (!(ac97_codecs[dev->model].misc_flags & AC97_AUXOUT_6B)) + goto clamp_5b; + break; - case 0x06: /* Mono Out Volume */ - if (!(dev->misc_flags & AC97_MONOOUT)) - return; - val &= 0x803f; + case 0x06: /* Mono Out Volume */ + if (!(ac97_codecs[dev->model].misc_flags & AC97_MONOOUT)) + return; + val &= 0x803f; - /* Convert 1xxxxx to 011111 where unsupported, per specification. */ - if (!(dev->misc_flags & AC97_MONOOUT_6B)) - goto clamp_5b_r; - break; + /* Convert 1xxxxx to 011111 where unsupported, per specification. */ + if (!(ac97_codecs[dev->model].misc_flags & AC97_MONOOUT_6B)) + goto clamp_5b_r; + break; - case 0x08: /* Master Tone Control */ - if (!(dev->reset_flags & AC97_TONECTL)) - return; - val &= 0x0f0f; - break; + case 0x08: /* Master Tone Control */ + if (!(ac97_codecs[dev->model].reset_flags & AC97_TONECTL)) + return; + val &= 0x0f0f; + break; - case 0x0a: /* PC Beep Volume */ - if (dev->misc_flags & AC97_PCBEEP) - i |= 0x801e; - if (dev->misc_flags & AC97_PCBEEP_GEN) - i |= 0x1fe0; - val &= i; - break; + case 0x0a: /* PC Beep Volume */ + if (ac97_codecs[dev->model].misc_flags & AC97_PCBEEP) + i |= 0x801e; + if (ac97_codecs[dev->model].misc_flags & AC97_PCBEEP_GEN) + i |= 0x1fe0; + val &= i; + break; - case 0x0c: /* Phone Volume */ - if (!(dev->misc_flags & AC97_PHONE)) - return; - val &= 0x801f; - break; + case 0x0c: /* Phone Volume */ + if (!(ac97_codecs[dev->model].misc_flags & AC97_PHONE)) + return; + val &= 0x801f; + break; - case 0x0e: /* Mic Volume */ - val &= 0x805f; - break; + case 0x0e: /* Mic Volume */ + val &= 0x805f; + break; - case 0x10: /* Line In Volume */ - case 0x12: /* CD Volume */ - case 0x18: /* PCM Out Volume */ -line_gain: val &= 0x9f1f; - break; + case 0x10: /* Line In Volume */ + case 0x12: /* CD Volume */ + case 0x18: /* PCM Out Volume */ +line_gain: + val &= 0x9f1f; + break; - case 0x14: /* Video Volume */ - if (!(dev->misc_flags & AC97_VIDEO)) - return; - goto line_gain; + case 0x14: /* Video Volume */ + if (!(ac97_codecs[dev->model].misc_flags & AC97_VIDEO)) + return; + goto line_gain; - case 0x16: /* Aux In Volume */ - if (!(dev->misc_flags & AC97_AUXIN)) - return; - goto line_gain; + case 0x16: /* Aux In Volume */ + if (!(ac97_codecs[dev->model].misc_flags & AC97_AUXIN)) + return; + goto line_gain; - case 0x1a: /* Record Select Control */ - val &= 0x0707; - break; + case 0x1a: /* Record Select Control */ + val &= 0x0707; + break; - case 0x1c: /* Record Gain */ - val &= 0x8f0f; - break; + case 0x1c: /* Record Gain */ + val &= 0x8f0f; + break; - case 0x1e: /* Record Gain Mic */ - if (!(dev->reset_flags & AC97_MICPCM)) - return; - val &= 0x800f; - break; + case 0x1e: /* Record Gain Mic */ + if (!(ac97_codecs[dev->model].reset_flags & AC97_MICPCM)) + return; + val &= 0x800f; + break; - case 0x20: /* General Purpose */ - i = AC97_MIX | (dev->misc_flags & (AC97_POP | AC97_MS | AC97_LPBK)); - if (dev->reset_flags >> AC97_3D_SHIFT) - i |= AC97_3D; - if (dev->reset_flags & AC97_SIMSTEREO) - i |= AC97_ST; - if (dev->reset_flags & AC97_LOUDNESS) - i |= AC97_LD; - if (dev->extid_flags & AC97_DRA) - i |= AC97_DRSS_MASK; - val &= i; - break; + case 0x20: /* General Purpose */ + i = AC97_MIX | (ac97_codecs[dev->model].misc_flags & (AC97_POP | AC97_MS | AC97_LPBK)); + if (ac97_codecs[dev->model].reset_flags >> AC97_3D_SHIFT) + i |= AC97_3D; + if (ac97_codecs[dev->model].reset_flags & AC97_SIMSTEREO) + i |= AC97_ST; + if (ac97_codecs[dev->model].reset_flags & AC97_LOUDNESS) + i |= AC97_LD; + if (ac97_codecs[dev->model].extid_flags & AC97_DRA) + i |= AC97_DRSS_MASK; + val &= i; + break; - case 0x22: /* 3D Control */ - switch (dev->reset_flags >> AC97_3D_SHIFT) { - case 1: /* Analog Devices */ - case 6: /* Crystal */ - val &= 0x000f; - break; + case 0x22: /* 3D Control */ + switch (ac97_codecs[dev->model].reset_flags >> AC97_3D_SHIFT) { + case 1: /* Analog Devices */ + case 6: /* Crystal */ + val &= 0x000f; + break; - case 22: /* Avance Logic / Realtek */ - val &= 0x0003; - break; + case 22: /* Avance Logic / Realtek */ + val &= 0x0003; + break; - case 26: /* SigmaTel */ - i = 0x0003; - if (dev->extid_flags & AC97_SDAC) - i |= 0x000c; - val &= i; - break; + case 26: /* SigmaTel */ + i = 0x0003; + if (ac97_codecs[dev->model].extid_flags & AC97_SDAC) + i |= 0x000c; + val &= i; + break; - default: - return; - } - break; + default: + return; + } + break; - case 0x24: /* Audio Interrupt and Paging Mechanism */ - if ((dev->extid_flags & AC97_REV_MASK) < AC97_REV_2_3) - return; - val &= 0x000f; - break; + case 0x24: /* Audio Interrupt and Paging Mechanism */ + if ((ac97_codecs[dev->model].extid_flags & AC97_REV_MASK) < AC97_REV_2_3) + return; + val &= 0x000f; + break; - case 0x26: /* Powerdown Control/Status */ - i = dev->powerdown_mask << 8; - val = (val & i) | (prev & ~i); + case 0x26: /* Powerdown Control/Status */ + i = ac97_codecs[dev->model].pcsr_mask << 8; + val = (val & i) | (prev & ~i); - /* Update status bits to reflect powerdowns. */ - val = (val & ~0x000f) | (~(val >> 8) & 0x000f); - if (val & 0x0800) /* PR3 clears both ANL and REF */ - val &= ~0x0004; - break; + /* Update status bits to reflect powerdowns. */ + val = (val & ~0x000f) | (~(val >> 8) & 0x000f); + if (val & 0x0800) /* PR3 clears both ANL and REF */ + val &= ~0x0004; + break; - case 0x28: /* Extended Audio ID */ - if (dev->misc_flags & AC97_DSA) - i |= 0x0030; - val = (val & i) | (prev & ~i); - break; + case 0x28: /* Extended Audio ID */ + if (ac97_codecs[dev->model].misc_flags & AC97_DSA) + i |= 0x0030; + val = (val & i) | (prev & ~i); + break; - case 0x2a: /* Extended Audio Status/Control */ - i = dev->extid_flags & (AC97_VRA | AC97_DRA | AC97_SPDIF | AC97_VRM); - if (dev->extid_flags & AC97_SPDIF) - i |= AC97_SPSA_MASK << AC97_SPSA_SHIFT; - i |= (dev->powerdown_mask << 3) & 0x7800; /* multichannel powerdowns */ - val = (val & i) | (prev & ~i); + case 0x2a: /* Extended Audio Status/Control */ + i = ac97_codecs[dev->model].extid_flags & (AC97_VRA | AC97_DRA | AC97_SPDIF | AC97_VRM); + if (ac97_codecs[dev->model].extid_flags & AC97_SPDIF) + i |= AC97_SPSA_MASK << AC97_SPSA_SHIFT; + i |= (ac97_codecs[dev->model].eascr_mask << 11) & 0x7800; + val = (val & i) | (prev & ~i); - /* Reset DAC sample rates to 48 KHz (96 KHz with DRA) if VRA is being cleared. */ - if (!(val & AC97_VRA)) { - for (i = 0x2c; i <= 0x30; i += 2) - dev->regs[i >> 1] = 48000; - } + /* Reset DAC sample rates to 48 KHz (96 KHz with DRA) if VRA is being cleared. */ + if (!(val & AC97_VRA)) { + for (i = 0x2c; i <= 0x30; i += 2) + dev->regs[i >> 1] = 48000; + } - /* Reset ADC sample rates to 48 KHz if VRM is being cleared. */ - if (!(val & AC97_VRM)) { - for (i = 0x32; i <= 0x34; i += 2) - dev->regs[i >> 1] = 48000; - } - break; + /* Reset ADC sample rates to 48 KHz if VRM is being cleared. */ + if (!(val & AC97_VRM)) { + for (i = 0x32; i <= 0x34; i += 2) + dev->regs[i >> 1] = 48000; + } + break; - case 0x2c: /* PCM Front DAC Rate */ - case 0x32: /* PCM L/R ADC Rate */ -rate: /* Writable only if VRA/VRM is set. */ - i = (reg >= 0x32) ? AC97_VRM : AC97_VRA; - if (!(dev->extid_flags & i)) - return; + case 0x2c: /* PCM Front DAC Rate */ + case 0x32: /* PCM L/R ADC Rate */ +rate: /* Writable only if VRA/VRM is set. */ + i = (reg >= 0x32) ? AC97_VRM : AC97_VRA; + if (!(ac97_codecs[dev->model].extid_flags & i)) + return; - /* Limit to supported sample rate range. */ - if (val < dev->min_rate) - val = dev->min_rate; - else if (val > dev->max_rate) - val = dev->max_rate; - break; + /* Limit to supported sample rate range. */ + if (val < ac97_codecs[dev->model].min_rate) + val = ac97_codecs[dev->model].min_rate; + else if (val > ac97_codecs[dev->model].max_rate) + val = ac97_codecs[dev->model].max_rate; + break; - case 0x2e: /* PCM Surround DAC Rate */ - if (!(dev->extid_flags & AC97_SDAC)) - return; - goto rate; + case 0x2e: /* PCM Surround DAC Rate */ + if (!(ac97_codecs[dev->model].extid_flags & AC97_SDAC)) + return; + goto rate; - case 0x30: /* PCM LFE DAC Rate */ - if (!(dev->extid_flags & AC97_LDAC)) - return; - goto rate; + case 0x30: /* PCM LFE DAC Rate */ + if (!(ac97_codecs[dev->model].extid_flags & AC97_LDAC)) + return; + goto rate; - case 0x34: /* Mic ADC Rate */ - if (!(dev->reset_flags & AC97_MICPCM)) - return; - goto rate; + case 0x34: /* Mic ADC Rate */ + if (!(ac97_codecs[dev->model].reset_flags & AC97_MICPCM)) + return; + goto rate; - case 0x36: /* Center/LFE Volume */ - if (dev->extid_flags & AC97_LDAC) - i |= 0xbf00; - if (dev->extid_flags & AC97_CDAC) - i |= 0x00bf; - val &= i; + case 0x36: /* Center/LFE Volume */ + if (ac97_codecs[dev->model].extid_flags & AC97_LDAC) + i |= 0xbf00; + if (ac97_codecs[dev->model].extid_flags & AC97_CDAC) + i |= 0x00bf; + val &= i; - /* Convert 1xxxxx to 011111 where unsupported, per specification. */ - if (!(dev->misc_flags & AC97_LFE_6B) && (val & 0x2000)) - val = (val & ~0x2000) | 0x1f00; - if (!(dev->misc_flags & AC97_CENTER_6B)) - goto clamp_5b_r; - break; + /* Convert 1xxxxx to 011111 where unsupported, per specification. */ + if (!(ac97_codecs[dev->model].misc_flags & AC97_LFE_6B) && (val & 0x2000)) + val = (val & ~0x2000) | 0x1f00; + if (!(ac97_codecs[dev->model].misc_flags & AC97_CENTER_6B)) + goto clamp_5b_r; + break; - case 0x38: /* Surround Volume */ - if (!(dev->extid_flags & AC97_SDAC)) - return; - val &= 0xbfbf; + case 0x38: /* Surround Volume */ + if (!(ac97_codecs[dev->model].extid_flags & AC97_SDAC)) + return; + val &= 0xbfbf; - /* Convert 1xxxxx to 011111 where unsupported, per specification. */ - if (!(dev->misc_flags & AC97_SURR_6B)) - goto clamp_5b; - break; + /* Convert 1xxxxx to 011111 where unsupported, per specification. */ + if (!(ac97_codecs[dev->model].misc_flags & AC97_SURR_6B)) + goto clamp_5b; + break; - case 0x3a: /* S/PDIF Control */ - if (!(dev->extid_flags & AC97_SPDIF)) - return; - break; + case 0x3a: /* S/PDIF Control */ + if (!(ac97_codecs[dev->model].extid_flags & AC97_SPDIF)) + return; + break; - case 0x60 ... 0x6e: /* Extended */ - /* Get extended register page. */ - i = dev->regs[0x24 >> 1] & 0x000f; + case 0x60 ... 0x6e: /* Extended */ + /* Get extended register page. */ + i = dev->regs[0x24 >> 1] & 0x000f; - /* Redirect a write to page 1+ to the right array, part 1. */ - if (i > 0) { - /* Don't overflow the pages. */ - if (i > dev->vendor_reg_page_max) - return; + /* Redirect a write to page 1+ to the right array, part 1. */ + if (i > 0) { + /* Don't overflow the pages. */ + if (i > dev->vendor_reg_page_max) + return; - /* Get actual previous value. */ - prev = dev->vendor_reg_pages[(i << 3) | ((reg & 0x0e) >> 1)]; - } + /* Get actual previous value. */ + prev = dev->vendor_reg_pages[(i << 3) | ((reg & 0x0e) >> 1)]; + } + fallthrough; - i <<= 8; - /* fall-through */ + case 0x5a ... 0x5e: /* Vendor Reserved */ + case 0x70 ... 0x7a: + /* Stop if no vendor-specific registers are defined. */ + if (!ac97_codecs[dev->model].vendor_regs) + return; - case 0x5a ... 0x5e: /* Vendor Reserved */ - case 0x70 ... 0x7a: - /* Stop if no vendor-specific registers are defined. */ - if (!dev->vendor_regs) - return; + /* Look for a matching vendor-specific register. */ + for (j = 0; ac97_codecs[dev->model].vendor_regs[j].index; j++) { + /* If a match was found, inject written bits. */ + if ((ac97_codecs[dev->model].vendor_regs[j].page == i) && (ac97_codecs[dev->model].vendor_regs[j].index == reg)) { + val = (val & ac97_codecs[dev->model].vendor_regs[j].write_mask) | (prev & ~ac97_codecs[dev->model].vendor_regs[j].write_mask); + break; + } + } - /* Look for a matching vendor-specific register. */ - i |= reg; - for (j = 0; dev->vendor_regs[j].index; j++) { - /* If a match was found, inject written bits. */ - if (dev->vendor_regs[j].index == i) { - val = (val & dev->vendor_regs[j].write_mask) | (prev & ~dev->vendor_regs[j].write_mask); - break; - } - } + /* No match found. */ + if (!ac97_codecs[dev->model].vendor_regs[j].index) + return; - /* No match found. */ - if (!dev->vendor_regs[j].index) - return; + /* Redirect a write to page 1+ to the right array, part 2. */ + if (i > 0) { + dev->vendor_reg_pages[(i << 3) | ((reg & 0x0e) >> 1)] = val; + return; + } + break; - /* Redirect a write to page 1+ to the right array, part 2. */ - i >>= 8; - if (i > 0) { - dev->vendor_reg_pages[(i << 3) | ((reg & 0x0e) >> 1)] = val; - return; - } - break; + case 0x7c: /* Vendor ID1 */ + case 0x7e: /* Vendor ID2 */ + return; - case 0x7c: /* Vendor ID1 */ - case 0x7e: /* Vendor ID2 */ - return; + default: + break; } dev->regs[reg >> 1] = val; } - void ac97_codec_reset(void *priv) { ac97_codec_t *dev = (ac97_codec_t *) priv; - uint16_t i, j; + uint16_t i; ac97_codec_log("AC97 Codec %d: reset()\n", dev->codec_id); @@ -455,160 +469,158 @@ ac97_codec_reset(void *priv) /* Set default level and gain values. */ dev->regs[0x02 >> 1] = AC97_MUTE; - if (dev->misc_flags & AC97_AUXOUT) - dev->regs[0x04 >> 1] = AC97_MUTE; - if (dev->misc_flags & AC97_MONOOUT) - dev->regs[0x06 >> 1] = AC97_MUTE; - if (dev->misc_flags & AC97_PHONE) - dev->regs[0x0c >> 1] = AC97_MUTE | 0x0008; - dev->regs[0x0e >> 1] = AC97_MUTE | 0x0008; /* mic */ + if (ac97_codecs[dev->model].misc_flags & AC97_AUXOUT) + dev->regs[0x04 >> 1] = AC97_MUTE; + if (ac97_codecs[dev->model].misc_flags & AC97_MONOOUT) + dev->regs[0x06 >> 1] = AC97_MUTE; + if (ac97_codecs[dev->model].misc_flags & AC97_PHONE) + dev->regs[0x0c >> 1] = AC97_MUTE | 0x0008; + dev->regs[0x0e >> 1] = AC97_MUTE | 0x0008; /* mic */ dev->regs[0x10 >> 1] = dev->regs[0x12 >> 1] = dev->regs[0x18 >> 1] = AC97_MUTE | 0x0808; /* line in, CD, PCM out */ - if (dev->misc_flags & AC97_VIDEO) - dev->regs[0x14 >> 1] = AC97_MUTE | 0x0808; - if (dev->misc_flags & AC97_AUXIN) - dev->regs[0x14 >> 1] = AC97_MUTE | 0x0808; - dev->regs[0x1c >> 1] = AC97_MUTE; /* record gain */ - if (dev->reset_flags & AC97_MICPCM) - dev->regs[0x1e >> 1] = AC97_MUTE; /* mic record gain */ - if (dev->misc_flags & AC97_LDAC) - dev->regs[0x36 >> 1] = AC97_MUTE_L; - if (dev->misc_flags & AC97_CDAC) - dev->regs[0x36 >> 1] |= AC97_MUTE_R; - if (dev->misc_flags & AC97_SDAC) - dev->regs[0x38 >> 1] = AC97_MUTE_L | AC97_MUTE_R; + if (ac97_codecs[dev->model].misc_flags & AC97_VIDEO) + dev->regs[0x14 >> 1] = AC97_MUTE | 0x0808; + if (ac97_codecs[dev->model].misc_flags & AC97_AUXIN) + dev->regs[0x14 >> 1] = AC97_MUTE | 0x0808; + dev->regs[0x1c >> 1] = AC97_MUTE; /* record gain */ + if (ac97_codecs[dev->model].reset_flags & AC97_MICPCM) + dev->regs[0x1e >> 1] = AC97_MUTE; /* mic record gain */ + if (ac97_codecs[dev->model].misc_flags & AC97_LDAC) + dev->regs[0x36 >> 1] = AC97_MUTE_L; + if (ac97_codecs[dev->model].misc_flags & AC97_CDAC) + dev->regs[0x36 >> 1] |= AC97_MUTE_R; + if (ac97_codecs[dev->model].misc_flags & AC97_SDAC) + dev->regs[0x38 >> 1] = AC97_MUTE_L | AC97_MUTE_R; /* Set flags. */ - dev->regs[0x00 >> 1] = dev->reset_flags; - dev->regs[0x26 >> 1] = 0x000f; /* codec ready */ - dev->regs[0x28 >> 1] = (dev->codec_id << 14) | dev->extid_flags; + dev->regs[0x00 >> 1] = ac97_codecs[dev->model].reset_flags; + dev->regs[0x26 >> 1] = 0x000f; /* codec ready */ + dev->regs[0x28 >> 1] = (dev->codec_id << 14) | ac97_codecs[dev->model].extid_flags; ac97_codec_writew(dev, 0x2a, 0x0000); /* reset variable DAC/ADC sample rates */ - i = dev->extid_flags & (AC97_CDAC | AC97_SDAC | AC97_LDAC); + i = ac97_codecs[dev->model].extid_flags & (AC97_CDAC | AC97_SDAC | AC97_LDAC); dev->regs[0x2a >> 1] |= i | (i << 5); /* any additional DACs are ready but powered down */ - if (dev->extid_flags & AC97_SPDIF) - dev->regs[0x2a >> 1] |= AC97_SPCV; - if (dev->reset_flags & AC97_MICPCM) - dev->regs[0x2a >> 1] |= AC97_MADC | AC97_PRL; + if (ac97_codecs[dev->model].extid_flags & AC97_SPDIF) + dev->regs[0x2a >> 1] |= AC97_SPCV; + if (ac97_codecs[dev->model].reset_flags & AC97_MICPCM) + dev->regs[0x2a >> 1] |= AC97_MADC | AC97_PRL; /* Set vendor ID. */ - dev->regs[0x7c >> 1] = dev->vendor_id >> 16; - dev->regs[0x7e >> 1] = dev->vendor_id; + dev->regs[0x7c >> 1] = ac97_codecs[dev->model].device->local >> 16; + dev->regs[0x7e >> 1] = ac97_codecs[dev->model].device->local; /* Set vendor-specific registers. */ - if (dev->vendor_regs) { - for (j = 0; dev->vendor_regs[j].index; j++) { - i = (dev->vendor_regs[j].index >> 8) & 0x000f; - if (i > 0) - dev->vendor_reg_pages[(i << 3) | (dev->vendor_regs[j].index >> 1)] = dev->vendor_regs[j].value; - else - dev->regs[dev->vendor_regs[j].index >> 1] = dev->vendor_regs[j].value; - } + if (ac97_codecs[dev->model].vendor_regs) { + for (i = 0; ac97_codecs[dev->model].vendor_regs[i].index; i++) { + if (ac97_codecs[dev->model].vendor_regs[i].page > 0) + dev->vendor_reg_pages[(ac97_codecs[dev->model].vendor_regs[i].page << 3) | (ac97_codecs[dev->model].vendor_regs[i].index >> 1)] = ac97_codecs[dev->model].vendor_regs[i].value; + else + dev->regs[ac97_codecs[dev->model].vendor_regs[i].index >> 1] = ac97_codecs[dev->model].vendor_regs[i].value; + } } } - void ac97_codec_getattn(void *priv, uint8_t reg, int *l, int *r) { - ac97_codec_t *dev = (ac97_codec_t *) priv; - uint16_t val = dev->regs[reg >> 1]; + const ac97_codec_t *dev = (ac97_codec_t *) priv; + uint16_t val = dev->regs[reg >> 1]; /* Apply full mute and powerdowns. */ int full_mute = (reg < 0x36); - if ((full_mute && (val & AC97_MUTE)) || /* full mute */ - (dev->regs[0x26 >> 1] & 0x3e00) || /* DAC powerdown */ - ((reg == 0x38) && (dev->regs[0x2a >> 1] & AC97_PRJ))) { /* surround DAC powerdown */ - *l = 0; - *r = 0; + if ((full_mute && (val & AC97_MUTE)) || /* full mute */ + (dev->regs[0x26 >> 1] & 0x3e00) || /* DAC powerdown */ + ((reg == 0x38) && (dev->regs[0x2a >> 1] & AC97_PRJ))) { /* surround DAC powerdown */ + *l = 0; + *r = 0; } else { /* per-channel mute */ - /* Determine attenuation value. */ - uint8_t l_val = val >> 8, r_val = val; - if (reg <= 0x06) { /* 6-bit level */ - *l = codec_attn[0x3f - (l_val & 0x3f)]; - *r = codec_attn[0x3f - (r_val & 0x3f)]; - } else { /* 5-bit gain */ - *l = codec_attn[0x47 - (l_val & 0x1f)]; - *r = codec_attn[0x47 - (r_val & 0x1f)]; - } + /* Determine attenuation value. */ + uint8_t l_val = val >> 8; + uint8_t r_val = val; + if (reg <= 0x06) { /* 6-bit level */ + *l = codec_attn[0x3f - (l_val & 0x3f)]; + *r = codec_attn[0x3f - (r_val & 0x3f)]; + } else { /* 5-bit gain */ + *l = codec_attn[0x47 - (l_val & 0x1f)]; + *r = codec_attn[0x47 - (r_val & 0x1f)]; + } - /* Apply per-channel mute and center/LFE powerdowns where applicable. */ - if (!full_mute) { - if ((val & AC97_MUTE_L) || /* left mute */ - ((reg == 0x36) && (dev->regs[0x2a >> 1] & AC97_PRK))) /* LFE DAC powerdown */ - *l = 0; - if ((val & AC97_MUTE_R) || /* right mute */ - ((reg == 0x36) && (dev->regs[0x2a >> 1] & AC97_PRI))) /* center DAC powerdown */ - *r = 0; - } + /* Apply per-channel mute and center/LFE powerdowns where applicable. */ + if (!full_mute) { + if ((val & AC97_MUTE_L) || /* left mute */ + ((reg == 0x36) && (dev->regs[0x2a >> 1] & AC97_PRK))) /* LFE DAC powerdown */ + *l = 0; + if ((val & AC97_MUTE_R) || /* right mute */ + ((reg == 0x36) && (dev->regs[0x2a >> 1] & AC97_PRI))) /* center DAC powerdown */ + *r = 0; + } } ac97_codec_log("AC97 Codec %d: getattn(%02X) = %d %d\n", dev->codec_id, reg, *l, *r); } - uint32_t ac97_codec_getrate(void *priv, uint8_t reg) { - ac97_codec_t *dev = (ac97_codec_t *) priv; + const ac97_codec_t *dev = (ac97_codec_t *) priv; /* Get configured sample rate, which is always 48000 if VRA/VRM is not set. */ uint32_t ret = dev->regs[reg >> 1]; /* If this is the PCM DAC, double sample rate if DRA is set. */ if ((reg == 0x2c) && (dev->regs[0x2a >> 1] & AC97_DRA)) - ret <<= 1; + ret <<= 1; ac97_codec_log("AC97 Codec %d: getrate(%02X) = %d\n", dev->codec_id, reg, ret); return ret; } - static void * ac97_codec_init(const device_t *info) { ac97_codec_t *dev = malloc(sizeof(ac97_codec_t)); memset(dev, 0, sizeof(ac97_codec_t)); - dev->vendor_id = ac97_codecs[info->local].vendor_id; - dev->min_rate = ac97_codecs[info->local].min_rate; - dev->max_rate = ac97_codecs[info->local].max_rate; - dev->reset_flags = ac97_codecs[info->local].reset_flags; - dev->extid_flags = ac97_codecs[info->local].extid_flags; - dev->misc_flags = ac97_codecs[info->local].misc_flags; - dev->powerdown_mask = ac97_codecs[info->local].powerdown_mask; - dev->vendor_regs = ac97_codecs[info->local].vendor_regs; - ac97_codec_log("AC97 Codec %d: init(%c%c%c%02X)\n", ac97_codec_id, (dev->vendor_id >> 24) & 0xff, (dev->vendor_id >> 16) & 0xff, (dev->vendor_id >> 8) & 0xff, dev->vendor_id & 0xff); + for (; dev->model < (sizeof(ac97_codecs) / sizeof(ac97_codecs[0])); dev->model++) { + if (ac97_codecs[dev->model].device->local == info->local) + break; + } + if (dev->model >= (sizeof(ac97_codecs) / sizeof(ac97_codecs[0]))) { + fatal("AC97 Codec %d: Unknown ID %c%c%c%02X\n", ac97_codec_id, (uint32_t) ((info->local >> 24) & 0xff), (uint32_t) ((info->local >> 16) & 0xff), (uint32_t) ((info->local >> 8) & 0xff), (uint32_t) (info->local & 0xff)); + free(dev); + return NULL; + } + ac97_codec_log("AC97 Codec %d: init(%c%c%c%02X)\n", ac97_codec_id, + (ac97_codecs[dev->model].device->local >> 24) & 0xff, (ac97_codecs[dev->model].device->local >> 16) & 0xff, + (ac97_codecs[dev->model].device->local >> 8) & 0xff, ac97_codecs[dev->model].device->local & 0xff); /* Associate this codec to the current controller. */ if (!ac97_codec || (ac97_codec_count <= 0)) { - pclog("AC97 Codec %d: No controller to associate codec\n", ac97_codec_id); - return NULL; + pclog("AC97 Codec %d: No controller to associate codec\n", ac97_codec_id); + free(dev); + return NULL; } *ac97_codec = dev; if (--ac97_codec_count == 0) - ac97_codec = NULL; + ac97_codec = NULL; else - ac97_codec += sizeof(ac97_codec_t *); + ac97_codec += sizeof(ac97_codec_t *); dev->codec_id = ac97_codec_id++; /* Allocate vendor-specific register pages if required. */ - if (dev->vendor_regs) { - /* Get the highest vendor-specific register page number. */ - int i, j; - dev->vendor_reg_page_max = 0; - for (j = 0; dev->vendor_regs[j].index; j++) { - i = (dev->vendor_regs[j].index >> 8) & 0x000f; - if (i > dev->vendor_reg_page_max) - dev->vendor_reg_page_max = i; - } + if (ac97_codecs[dev->model].vendor_regs) { + /* Get the highest vendor-specific register page number. */ + for (uint16_t i = 0; ac97_codecs[dev->model].vendor_regs[i].index; i++) { + if (ac97_codecs[dev->model].vendor_regs[i].page > dev->vendor_reg_page_max) + dev->vendor_reg_page_max = ac97_codecs[dev->model].vendor_regs[i].page; + } - /* Allocate pages 1+. */ - if (dev->vendor_reg_page_max > 0) { - ac97_codec_log("AC97 Codec %d: Allocating %d vendor-specific register pages\n", dev->codec_id, dev->vendor_reg_page_max); - i = 16 * dev->vendor_reg_page_max; - dev->vendor_reg_pages = (uint16_t *) malloc(i); - memset(dev->vendor_reg_pages, 0, i); - } + /* Allocate pages 1+. */ + if (dev->vendor_reg_page_max > 0) { + ac97_codec_log("AC97 Codec %d: Allocating %d vendor-specific register pages\n", dev->codec_id, dev->vendor_reg_page_max); + int i = 16 * dev->vendor_reg_page_max; + dev->vendor_reg_pages = (uint16_t *) malloc(i); + memset(dev->vendor_reg_pages, 0, i); + } } /* Initialize codec registers. */ @@ -617,132 +629,152 @@ ac97_codec_init(const device_t *info) return dev; } - static void ac97_codec_close(void *priv) { ac97_codec_t *dev = (ac97_codec_t *) priv; if (!dev) - return; + return; ac97_codec_log("AC97 Codec %d: close()\n", dev->codec_id); if (dev->vendor_reg_pages) - free(dev->vendor_reg_pages); + free(dev->vendor_reg_pages); free(dev); } - const device_t * -ac97_codec_get(int model) +ac97_codec_get(uint32_t id) { - if ((model >= 0) && (model < (sizeof(ac97_codecs) / sizeof(ac97_codecs[0])))) - return ac97_codecs[model].device; - else - return &cs4297a_device; /* fallback */ + for (int i = 0; i < (sizeof(ac97_codecs) / sizeof(ac97_codecs[0])); i++) { + if (ac97_codecs[i].device->local == id) + return ac97_codecs[i].device; + } + return &tr28023_device; /* fallback */ } - -const device_t ad1881_device = -{ - "Analog Devices AD1881", - "ad1881", - DEVICE_AC97, - AC97_CODEC_AD1881, - ac97_codec_init, ac97_codec_close, ac97_codec_reset, - { NULL }, - NULL, - NULL, - NULL +const device_t ad1881_device = { + .name = "Analog Devices AD1881", + .internal_name = "ad1881", + .flags = DEVICE_AC97, + .local = AC97_CODEC_AD1881, + .init = ac97_codec_init, + .close = ac97_codec_close, + .reset = ac97_codec_reset, + { .available = NULL }, + .speed_changed = NULL, + .force_redraw = NULL, + .config = NULL }; -const device_t ak4540_device = -{ - "Asahi Kasei AK4540", - "ak4540", - DEVICE_AC97, - AC97_CODEC_AK4540, - ac97_codec_init, ac97_codec_close, ac97_codec_reset, - { NULL }, - NULL, - NULL, - NULL +const device_t ak4540_device = { + .name = "Asahi Kasei AK4540", + .internal_name = "ak4540", + .flags = DEVICE_AC97, + .local = AC97_CODEC_AK4540, + .init = ac97_codec_init, + .close = ac97_codec_close, + .reset = ac97_codec_reset, + { .available = NULL }, + .speed_changed = NULL, + .force_redraw = NULL, + .config = NULL }; -const device_t alc100_device = -{ - "Avance Logic ALC100", - "alc100", - DEVICE_AC97, - AC97_CODEC_ALC100, - ac97_codec_init, ac97_codec_close, ac97_codec_reset, - { NULL }, - NULL, - NULL, - NULL +const device_t alc100_device = { + .name = "Avance Logic ALC100", + .internal_name = "alc100", + .flags = DEVICE_AC97, + .local = AC97_CODEC_ALC100, + .init = ac97_codec_init, + .close = ac97_codec_close, + .reset = ac97_codec_reset, + { .available = NULL }, + .speed_changed = NULL, + .force_redraw = NULL, + .config = NULL }; -const device_t cs4297_device = -{ - "Crystal CS4297", - "cs4297", - DEVICE_AC97, - AC97_CODEC_CS4297, - ac97_codec_init, ac97_codec_close, ac97_codec_reset, - { NULL }, - NULL, - NULL, - NULL +const device_t cs4297_device = { + .name = "Crystal CS4297", + .internal_name = "cs4297", + .flags = DEVICE_AC97, + .local = AC97_CODEC_CS4297, + .init = ac97_codec_init, + .close = ac97_codec_close, + .reset = ac97_codec_reset, + { .available = NULL }, + .speed_changed = NULL, + .force_redraw = NULL, + .config = NULL }; -const device_t cs4297a_device = -{ - "Crystal CS4297A", - "cs4297a", - DEVICE_AC97, - AC97_CODEC_CS4297A, - ac97_codec_init, ac97_codec_close, ac97_codec_reset, - { NULL }, - NULL, - NULL, - NULL +const device_t cs4297a_device = { + .name = "Crystal CS4297A", + .internal_name = "cs4297a", + .flags = DEVICE_AC97, + .local = AC97_CODEC_CS4297A, + .init = ac97_codec_init, + .close = ac97_codec_close, + .reset = ac97_codec_reset, + { .available = NULL }, + .speed_changed = NULL, + .force_redraw = NULL, + .config = NULL }; -const device_t stac9708_device = -{ - "SigmaTel STAC9708", - "stac9708", - DEVICE_AC97, - AC97_CODEC_STAC9708, - ac97_codec_init, ac97_codec_close, ac97_codec_reset, - { NULL }, - NULL, - NULL, - NULL +const device_t stac9708_device = { + .name = "SigmaTel STAC9708", + .internal_name = "stac9708", + .flags = DEVICE_AC97, + .local = AC97_CODEC_STAC9708, + .init = ac97_codec_init, + .close = ac97_codec_close, + .reset = ac97_codec_reset, + { .available = NULL }, + .speed_changed = NULL, + .force_redraw = NULL, + .config = NULL }; -const device_t stac9721_device = -{ - "SigmaTel STAC9721", - "stac9721", - DEVICE_AC97, - AC97_CODEC_STAC9721, - ac97_codec_init, ac97_codec_close, ac97_codec_reset, - { NULL }, - NULL, - NULL, - NULL +const device_t stac9721_device = { + .name = "SigmaTel STAC9721", + .internal_name = "stac9721", + .flags = DEVICE_AC97, + .local = AC97_CODEC_STAC9721, + .init = ac97_codec_init, + .close = ac97_codec_close, + .reset = ac97_codec_reset, + { .available = NULL }, + .speed_changed = NULL, + .force_redraw = NULL, + .config = NULL }; -const device_t wm9701a_device = -{ - "Wolfson WM9701A", - "wm9701a", - DEVICE_AC97, - AC97_CODEC_WM9701A, - ac97_codec_init, ac97_codec_close, ac97_codec_reset, - { NULL }, - NULL, - NULL, - NULL +const device_t tr28023_device = { + .name = "TriTech TR28023 / Creative CT1297", + .internal_name = "tr28023", + .flags = DEVICE_AC97, + .local = AC97_CODEC_TR28023, + .init = ac97_codec_init, + .close = ac97_codec_close, + .reset = ac97_codec_reset, + { .available = NULL }, + .speed_changed = NULL, + .force_redraw = NULL, + .config = NULL +}; + +const device_t wm9701a_device = { + .name = "Wolfson WM9701A", + .internal_name = "wm9701a", + .flags = DEVICE_AC97, + .local = AC97_CODEC_WM9701A, + .init = ac97_codec_init, + .close = ac97_codec_close, + .reset = ac97_codec_reset, + { .available = NULL }, + .speed_changed = NULL, + .force_redraw = NULL, + .config = NULL }; diff --git a/src/sound/snd_ac97_via.c b/src/sound/snd_ac97_via.c index f1feaa99b..ceac42387 100644 --- a/src/sound/snd_ac97_via.c +++ b/src/sound/snd_ac97_via.c @@ -1,70 +1,91 @@ /* - * 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. + * 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. + * This file is part of the 86Box distribution. * - * VIA AC'97 audio controller emulation. + * VIA AC'97 audio controller emulation. * * * - * Authors: RichardG, + * Authors: RichardG, * - * Copyright 2021 RichardG. + * Copyright 2021 RichardG. */ #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/pic.h> -#include <86box/timer.h> #include <86box/pci.h> -#include <86box/sound.h> +#include <86box/pic.h> #include <86box/snd_ac97.h> +#include <86box/sound.h> +#include <86box/timer.h> +#include <86box/plat_unused.h> - -typedef struct { - uint8_t id, always_run; +typedef struct ac97_via_sgd_t { + uint8_t id; + uint8_t always_run; struct _ac97_via_ *dev; - uint32_t entry_ptr, sample_ptr, fifo_pos, fifo_end; - int32_t sample_count; - uint8_t entry_flags, fifo[32], restart; + uint32_t entry_ptr; + uint32_t sample_ptr; + uint32_t fifo_pos; + uint32_t fifo_end; + int32_t sample_count; + uint8_t entry_flags; + uint8_t fifo[32]; + uint8_t restart; - int16_t out_l, out_r; - int vol_l, vol_r, pos; - int32_t buffer[SOUNDBUFLEN * 2]; - uint64_t timer_latch; + int16_t out_l; + int16_t out_r; + int vol_l; + int vol_r; + int pos; + int32_t buffer[SOUNDBUFLEN * 2]; + uint64_t timer_latch; - pc_timer_t dma_timer, poll_timer; + pc_timer_t dma_timer; + pc_timer_t poll_timer; } ac97_via_sgd_t; typedef struct _ac97_via_ { - uint16_t audio_sgd_base, audio_codec_base, modem_sgd_base, modem_codec_base; - uint8_t sgd_regs[256], pcm_enabled: 1, fm_enabled: 1, vsr_enabled: 1; + uint16_t audio_sgd_base; + uint16_t audio_codec_base; + uint16_t modem_sgd_base; + uint16_t modem_codec_base; + uint8_t sgd_regs[256]; + uint8_t pcm_enabled : 1; + uint8_t fm_enabled : 1; + uint8_t vsr_enabled : 1; struct { - union { - uint8_t regs_codec[2][128]; - uint8_t regs_linear[256]; - }; + union { + uint8_t regs_codec[2][128]; + uint8_t regs_linear[256]; + }; } codec_shadow[2]; - int slot, irq_pin; + uint8_t pci_slot; + uint8_t irq_state; + int irq_pin; - ac97_codec_t *codec[2][2]; + ac97_codec_t *codec[2][2]; ac97_via_sgd_t sgd[6]; - int master_vol_l, master_vol_r, cd_vol_l, cd_vol_r; + int master_vol_l; + int master_vol_r; + int cd_vol_l; + int cd_vol_r; } ac97_via_t; - #ifdef ENABLE_AC97_VIA_LOG int ac97_via_do_log = ENABLE_AC97_VIA_LOG; @@ -74,21 +95,19 @@ ac97_via_log(const char *fmt, ...) va_list ap; if (ac97_via_do_log) { - va_start(ap, fmt); - pclog_ex(fmt, ap); - va_end(ap); + va_start(ap, fmt); + pclog_ex(fmt, ap); + va_end(ap); } } #else -#define ac97_via_log(fmt, ...) +# define ac97_via_log(fmt, ...) #endif - -static void ac97_via_sgd_process(void *priv); -static void ac97_via_update_codec(ac97_via_t *dev); -static void ac97_via_speed_changed(void *priv); -static void ac97_via_filter_cd_audio(int channel, double *buffer, void *priv); - +static void ac97_via_sgd_process(void *priv); +static void ac97_via_update_codec(ac97_via_t *dev); +static void ac97_via_speed_changed(void *priv); +static void ac97_via_filter_cd_audio(int channel, double *buffer, void *priv); void ac97_via_set_slot(void *priv, int slot, int irq_pin) @@ -97,21 +116,20 @@ ac97_via_set_slot(void *priv, int slot, int irq_pin) ac97_via_log("AC97 VIA: set_slot(%d, %d)\n", slot, irq_pin); - dev->slot = slot; - dev->irq_pin = irq_pin; + dev->pci_slot = slot; + dev->irq_pin = irq_pin; } - uint8_t ac97_via_read_status(void *priv, uint8_t modem) { - ac97_via_t *dev = (ac97_via_t *) priv; - uint8_t ret = 0x00; + const ac97_via_t *dev = (ac97_via_t *) priv; + uint8_t ret = 0x00; /* Flag each codec as ready if present. */ for (uint8_t i = 0; i <= 1; i++) { - if (dev->codec[modem][i]) - ret |= 0x01 << (i << 1); + if (dev->codec[modem][i]) + ret |= 0x01 << (i << 1); } ac97_via_log("AC97 VIA %d: read_status() = %02X\n", modem, ret); @@ -119,63 +137,60 @@ ac97_via_read_status(void *priv, uint8_t modem) return ret; } - void ac97_via_write_control(void *priv, uint8_t modem, uint8_t val) { ac97_via_t *dev = (ac97_via_t *) priv; - uint8_t i; + uint8_t i; ac97_via_log("AC97 VIA %d: write_control(%02X)\n", modem, val); /* Reset codecs if requested. */ if (!(val & 0x40)) { - for (i = 0; i <= 1; i++) { - if (dev->codec[modem][i]) - ac97_codec_reset(dev->codec[modem][i]); - } + for (i = 0; i <= 1; i++) { + if (dev->codec[modem][i]) + ac97_codec_reset(dev->codec[modem][i]); + } } if (!modem) { - /* Set the variable sample rate flag. */ - dev->vsr_enabled = (val & 0xf8) == 0xc8; + /* Set the variable sample rate flag. */ + dev->vsr_enabled = (val & 0xf8) == 0xc8; - /* Start or stop PCM playback. */ - i = (val & 0xf4) == 0xc4; - if (i && !dev->pcm_enabled) - timer_advance_u64(&dev->sgd[0].poll_timer, dev->sgd[0].timer_latch); - dev->pcm_enabled = i; + /* Start or stop PCM playback. */ + i = (val & 0xf4) == 0xc4; + if (i && !dev->pcm_enabled) + timer_advance_u64(&dev->sgd[0].poll_timer, dev->sgd[0].timer_latch); + dev->pcm_enabled = i; - /* Start or stop FM playback. */ - i = (val & 0xf2) == 0xc2; - if (i && !dev->fm_enabled) - timer_advance_u64(&dev->sgd[2].poll_timer, dev->sgd[2].timer_latch); - dev->fm_enabled = i; + /* Start or stop FM playback. */ + i = (val & 0xf2) == 0xc2; + if (i && !dev->fm_enabled) + timer_advance_u64(&dev->sgd[2].poll_timer, dev->sgd[2].timer_latch); + dev->fm_enabled = i; - /* Update primary audio codec state. */ - if (dev->codec[0][0]) - ac97_via_update_codec(dev); + /* Update primary audio codec state. */ + if (dev->codec[0][0]) + ac97_via_update_codec(dev); } } - static void ac97_via_update_irqs(ac97_via_t *dev) { /* Check interrupt flags in all SGDs. */ for (uint8_t i = 0x00; i < ((sizeof(dev->sgd) / sizeof(dev->sgd[0])) << 4); i += 0x10) { - /* Stop immediately if any flag is set. Doing it this way optimizes - rising edges for the playback SGD (0 - first to be checked). */ - if (dev->sgd_regs[i] & (dev->sgd_regs[i | 0x2] & 0x03)) { - pci_set_irq(dev->slot, dev->irq_pin); - return; - } + /* Stop immediately if any flag is set. Doing it this way optimizes + rising edges for the playback SGD (0 - first to be checked). */ + if (dev->sgd_regs[i] & (dev->sgd_regs[i | 0x2] & 0x03)) { + pci_set_irq(dev->pci_slot, dev->irq_pin, &dev->irq_state); + return; + } } - pci_clear_irq(dev->slot, dev->irq_pin); + pci_clear_irq(dev->pci_slot, dev->irq_pin, &dev->irq_state); } - static void ac97_via_update_codec(ac97_via_t *dev) { @@ -185,17 +200,17 @@ ac97_via_update_codec(ac97_via_t *dev) /* Update volumes according to codec registers. */ ac97_codec_getattn(codec, 0x02, &dev->master_vol_l, &dev->master_vol_r); ac97_codec_getattn(codec, 0x18, &dev->sgd[0].vol_l, &dev->sgd[0].vol_r); + ac97_codec_getattn(codec, 0x18, &dev->sgd[2].vol_l, &dev->sgd[2].vol_r); /* VIAFMTSR sets Master, CD and PCM volumes to 0 dB */ ac97_codec_getattn(codec, 0x12, &dev->cd_vol_l, &dev->cd_vol_r); /* Update sample rate according to codec registers and the variable sample rate flag. */ ac97_via_speed_changed(dev); } - uint8_t ac97_via_sgd_read(uint16_t addr, void *priv) { - ac97_via_t *dev = (ac97_via_t *) priv; + const ac97_via_t *dev = (ac97_via_t *) priv; #ifdef ENABLE_AC97_VIA_LOG uint8_t modem = (addr & 0xff00) == dev->modem_sgd_base; #endif @@ -203,83 +218,83 @@ ac97_via_sgd_read(uint16_t addr, void *priv) uint8_t ret; if (!(addr & 0x80)) { - /* Process SGD channel registers. */ - switch (addr & 0xf) { - case 0x4: - ret = dev->sgd[addr >> 4].entry_ptr; - break; + /* Process SGD channel registers. */ + switch (addr & 0xf) { + case 0x4: + ret = dev->sgd[addr >> 4].entry_ptr; + break; - case 0x5: - ret = dev->sgd[addr >> 4].entry_ptr >> 8; - break; + case 0x5: + ret = dev->sgd[addr >> 4].entry_ptr >> 8; + break; - case 0x6: - ret = dev->sgd[addr >> 4].entry_ptr >> 16; - break; + case 0x6: + ret = dev->sgd[addr >> 4].entry_ptr >> 16; + break; - case 0x7: - ret = dev->sgd[addr >> 4].entry_ptr >> 24; - break; + case 0x7: + ret = dev->sgd[addr >> 4].entry_ptr >> 24; + break; - case 0xc: - ret = dev->sgd[addr >> 4].sample_count; - break; + case 0xc: + ret = dev->sgd[addr >> 4].sample_count; + break; - case 0xd: - ret = dev->sgd[addr >> 4].sample_count >> 8; - break; + case 0xd: + ret = dev->sgd[addr >> 4].sample_count >> 8; + break; - case 0xe: - ret = dev->sgd[addr >> 4].sample_count >> 16; - break; + case 0xe: + ret = dev->sgd[addr >> 4].sample_count >> 16; + break; - default: - ret = dev->sgd_regs[addr]; - break; - } + default: + ret = dev->sgd_regs[addr]; + break; + } } else { - /* Process regular registers. */ - switch (addr) { - case 0x84: - ret = (dev->sgd_regs[0x00] & 0x01); - ret |= (dev->sgd_regs[0x10] & 0x01) << 1; - ret |= (dev->sgd_regs[0x20] & 0x01) << 2; + /* Process regular registers. */ + switch (addr) { + case 0x84: + ret = (dev->sgd_regs[0x00] & 0x01); + ret |= (dev->sgd_regs[0x10] & 0x01) << 1; + ret |= (dev->sgd_regs[0x20] & 0x01) << 2; - ret |= (dev->sgd_regs[0x00] & 0x02) << 3; - ret |= (dev->sgd_regs[0x10] & 0x02) << 4; - ret |= (dev->sgd_regs[0x20] & 0x02) << 5; - break; + ret |= (dev->sgd_regs[0x00] & 0x02) << 3; + ret |= (dev->sgd_regs[0x10] & 0x02) << 4; + ret |= (dev->sgd_regs[0x20] & 0x02) << 5; + break; - case 0x85: - ret = (dev->sgd_regs[0x00] & 0x04) >> 2; - ret |= (dev->sgd_regs[0x10] & 0x04) >> 1; - ret |= (dev->sgd_regs[0x20] & 0x04); + case 0x85: + ret = (dev->sgd_regs[0x00] & 0x04) >> 2; + ret |= (dev->sgd_regs[0x10] & 0x04) >> 1; + ret |= (dev->sgd_regs[0x20] & 0x04); - ret |= (dev->sgd_regs[0x00] & 0x80) >> 3; - ret |= (dev->sgd_regs[0x10] & 0x80) >> 2; - ret |= (dev->sgd_regs[0x20] & 0x80) >> 1; - break; + ret |= (dev->sgd_regs[0x00] & 0x80) >> 3; + ret |= (dev->sgd_regs[0x10] & 0x80) >> 2; + ret |= (dev->sgd_regs[0x20] & 0x80) >> 1; + break; - case 0x86: - ret = (dev->sgd_regs[0x40] & 0x01); - ret |= (dev->sgd_regs[0x50] & 0x01) << 1; + case 0x86: + ret = (dev->sgd_regs[0x40] & 0x01); + ret |= (dev->sgd_regs[0x50] & 0x01) << 1; - ret |= (dev->sgd_regs[0x40] & 0x02) << 3; - ret |= (dev->sgd_regs[0x50] & 0x02) << 4; - break; + ret |= (dev->sgd_regs[0x40] & 0x02) << 3; + ret |= (dev->sgd_regs[0x50] & 0x02) << 4; + break; - case 0x87: - ret = (dev->sgd_regs[0x40] & 0x04) >> 2; - ret |= (dev->sgd_regs[0x50] & 0x04) >> 1; + case 0x87: + ret = (dev->sgd_regs[0x40] & 0x04) >> 2; + ret |= (dev->sgd_regs[0x50] & 0x04) >> 1; - ret |= (dev->sgd_regs[0x40] & 0x80) >> 3; - ret |= (dev->sgd_regs[0x50] & 0x80) >> 2; - break; + ret |= (dev->sgd_regs[0x40] & 0x80) >> 3; + ret |= (dev->sgd_regs[0x50] & 0x80) >> 2; + break; - default: - ret = dev->sgd_regs[addr]; - break; - } + default: + ret = dev->sgd_regs[addr]; + break; + } } ac97_via_log("AC97 VIA %d: sgd_read(%02X) = %02X\n", modem, addr, ret); @@ -287,12 +302,12 @@ ac97_via_sgd_read(uint16_t addr, void *priv) return ret; } - void ac97_via_sgd_write(uint16_t addr, uint8_t val, void *priv) { - ac97_via_t *dev = (ac97_via_t *) priv; - uint8_t modem = (addr & 0xff00) == dev->modem_sgd_base, i; + ac97_via_t *dev = (ac97_via_t *) priv; + uint8_t modem = (addr & 0xff00) == dev->modem_sgd_base; + uint8_t i; ac97_codec_t *codec; addr &= 0xff; @@ -300,163 +315,165 @@ ac97_via_sgd_write(uint16_t addr, uint8_t val, void *priv) /* Check function-specific read only registers. */ if ((addr >= (modem ? 0x00 : 0x40)) && (addr < (modem ? 0x40 : 0x60))) - return; + return; if (addr >= (modem ? 0x90 : 0x88)) - return; + return; if (!(addr & 0x80)) { - /* Process SGD channel registers. */ - switch (addr & 0xf) { - case 0x0: - /* Clear RWC status bits. */ - dev->sgd_regs[addr] &= ~(val & 0x07); + /* Process SGD channel registers. */ + switch (addr & 0xf) { + case 0x0: + /* Clear RWC status bits. */ + dev->sgd_regs[addr] &= ~(val & 0x07); - /* Update status interrupts. */ - ac97_via_update_irqs(dev); + /* Update status interrupts. */ + ac97_via_update_irqs(dev); - return; + return; - case 0x1: - /* Start SGD if requested. */ - if (val & 0x80) { - if (dev->sgd_regs[addr & 0xf0] & 0x80) { - /* Queue SGD trigger if already running. */ - dev->sgd_regs[addr & 0xf0] |= 0x08; - } else { - /* Start SGD immediately. */ - dev->sgd_regs[addr & 0xf0] |= 0x80; - dev->sgd_regs[addr & 0xf0] &= ~0x44; + case 0x1: + /* Start SGD if requested. */ + if (val & 0x80) { + if (dev->sgd_regs[addr & 0xf0] & 0x80) { + /* Queue SGD trigger if already running. */ + dev->sgd_regs[addr & 0xf0] |= 0x08; + } else { + /* Start SGD immediately. */ + dev->sgd_regs[addr & 0xf0] = (dev->sgd_regs[addr & 0xf0] & ~0x47) | 0x80; - /* Start at the specified entry pointer. */ - dev->sgd[addr >> 4].sample_ptr = 0; - dev->sgd[addr >> 4].entry_ptr = *((uint32_t *) &dev->sgd_regs[(addr & 0xf0) | 0x4]) & 0xfffffffe; - dev->sgd[addr >> 4].restart = 1; + /* Start at the specified entry pointer. */ + dev->sgd[addr >> 4].entry_ptr = *((uint32_t *) &dev->sgd_regs[(addr & 0xf0) | 0x4]) & 0xfffffffe; + dev->sgd[addr >> 4].restart = 2; - /* Start the actual SGD process. */ - ac97_via_sgd_process(&dev->sgd[addr >> 4]); - } - } - /* Stop SGD if requested. */ - if (val & 0x40) - dev->sgd_regs[addr & 0xf0] &= ~0x88; + /* Start the actual SGD process. */ + ac97_via_sgd_process(&dev->sgd[addr >> 4]); + } + } + /* Stop SGD if requested. */ + if (val & 0x40) + dev->sgd_regs[addr & 0xf0] &= ~0x88; - val &= 0x08; + val &= 0x08; - /* (Un)pause SGD if requested. */ - if (val & 0x08) - dev->sgd_regs[addr & 0xf0] |= 0x40; - else - dev->sgd_regs[addr & 0xf0] &= ~0x40; + /* (Un)pause SGD if requested. */ + if (val & 0x08) + dev->sgd_regs[addr & 0xf0] |= 0x40; + else + dev->sgd_regs[addr & 0xf0] &= ~0x40; - break; + break; - case 0x2: - if (addr & 0x10) - val &= 0xf3; - break; + case 0x2: + if (addr & 0x10) + val &= 0xf3; + break; - case 0x3: case 0x8 ... 0xf: - /* Read-only registers. */ - return; - } + case 0x3: + case 0x8 ... 0xf: + /* Read-only registers. */ + return; + + default: + break; + } } else { - /* Process regular registers. */ - switch (addr) { - case 0x30 ... 0x3f: - case 0x60 ... 0x7f: - case 0x84 ... 0x87: - /* Read-only registers. */ - return; + /* Process regular registers. */ + switch (addr) { + case 0x30 ... 0x3f: + case 0x60 ... 0x7f: + case 0x84 ... 0x87: + /* Read-only registers. */ + return; - case 0x82: - /* Determine the selected codec. */ - i = !!(dev->sgd_regs[0x83] & 0x40); - codec = dev->codec[modem][i]; + case 0x82: + /* Determine the selected codec. */ + i = !!(dev->sgd_regs[0x83] & 0x40); + codec = dev->codec[modem][i]; - /* Keep value in register if this codec is not present. */ - if (codec) { - /* Read from or write to codec. */ - if (val & 0x80) { - if (val & 1) { /* return 0x0000 on unaligned reads (real 686B behavior) */ - dev->sgd_regs[0x80] = dev->sgd_regs[0x81] = 0x00; - } else { - *((uint16_t *) &dev->codec_shadow[modem].regs_codec[i][val & 0x7f]) = *((uint16_t *) &dev->sgd_regs[0x80]) = - ac97_codec_readw(codec, val); - } + /* Keep value in register if this codec is not present. */ + if (codec) { + /* Read from or write to codec. */ + if (val & 0x80) { + if (val & 1) { /* return 0x0000 on unaligned reads (real 686B behavior) */ + dev->sgd_regs[0x80] = dev->sgd_regs[0x81] = 0x00; + } else { + *((uint16_t *) &dev->codec_shadow[modem].regs_codec[i][val & 0x7f]) = *((uint16_t *) &dev->sgd_regs[0x80]) = ac97_codec_readw(codec, val); + } - /* Flag data/status/index for this codec as valid. */ - dev->sgd_regs[0x83] |= 0x02 << (i << 1); - } else if (!(val & 1)) { /* do nothing on unaligned writes */ - ac97_codec_writew(codec, val, - *((uint16_t *) &dev->codec_shadow[modem].regs_codec[i][val & 0x7f]) = *((uint16_t *) &dev->sgd_regs[0x80])); + /* Flag data/status/index for this codec as valid. */ + dev->sgd_regs[0x83] |= 0x02 << (i << 1); + } else if (!(val & 1)) { /* do nothing on unaligned writes */ + ac97_codec_writew(codec, val, + *((uint16_t *) &dev->codec_shadow[modem].regs_codec[i][val & 0x7f]) = *((uint16_t *) &dev->sgd_regs[0x80])); - /* Update primary audio codec state if that codec was written to. */ - if (!modem && !i) { - ac97_via_update_codec(dev); + /* Update primary audio codec state if that codec was written to. */ + if (!modem && !i) { + ac97_via_update_codec(dev); - /* Set up CD audio filter if CD volume was written to. Setting it - up at init prevents CD audio from working on other cards, but - this works as the CD channel is muted by default per AC97 spec. */ - if (val == 0x12) - sound_set_cd_audio_filter(ac97_via_filter_cd_audio, dev); - } - } - } + /* Set up CD audio filter if CD volume was written to. Setting it + up at init prevents CD audio from working on other cards, but + this works as the CD channel is muted by default per AC97 spec. */ + if (val == 0x12) + sound_set_cd_audio_filter(ac97_via_filter_cd_audio, dev); + } + } + } - break; + break; - case 0x83: - /* Clear RWC status bits. */ + case 0x83: + /* Clear RWC status bits. */ #if 0 /* race condition with Linux accessing a register and clearing status bits on the same dword write */ - val = (dev->sgd_regs[addr] & ~(val & 0x0a)) | (val & 0xc0); + val = (dev->sgd_regs[addr] & ~(val & 0x0a)) | (val & 0xc0); #else - val = dev->sgd_regs[addr] | (val & 0xc0); + val = dev->sgd_regs[addr] | (val & 0xc0); #endif - break; - } + break; + + default: + break; + } } dev->sgd_regs[addr] = val; } - void ac97_via_remap_audio_sgd(void *priv, uint16_t new_io_base, uint8_t enable) { ac97_via_t *dev = (ac97_via_t *) priv; if (dev->audio_sgd_base) - io_removehandler(dev->audio_sgd_base, 256, ac97_via_sgd_read, NULL, NULL, ac97_via_sgd_write, NULL, NULL, dev); + io_removehandler(dev->audio_sgd_base, 256, ac97_via_sgd_read, NULL, NULL, ac97_via_sgd_write, NULL, NULL, dev); dev->audio_sgd_base = new_io_base; if (dev->audio_sgd_base && enable) - io_sethandler(dev->audio_sgd_base, 256, ac97_via_sgd_read, NULL, NULL, ac97_via_sgd_write, NULL, NULL, dev); + io_sethandler(dev->audio_sgd_base, 256, ac97_via_sgd_read, NULL, NULL, ac97_via_sgd_write, NULL, NULL, dev); } - void ac97_via_remap_modem_sgd(void *priv, uint16_t new_io_base, uint8_t enable) { ac97_via_t *dev = (ac97_via_t *) priv; if (dev->modem_sgd_base) - io_removehandler(dev->modem_sgd_base, 256, ac97_via_sgd_read, NULL, NULL, ac97_via_sgd_write, NULL, NULL, dev); + io_removehandler(dev->modem_sgd_base, 256, ac97_via_sgd_read, NULL, NULL, ac97_via_sgd_write, NULL, NULL, dev); dev->modem_sgd_base = new_io_base; if (dev->modem_sgd_base && enable) - io_sethandler(dev->modem_sgd_base, 256, ac97_via_sgd_read, NULL, NULL, ac97_via_sgd_write, NULL, NULL, dev); + io_sethandler(dev->modem_sgd_base, 256, ac97_via_sgd_read, NULL, NULL, ac97_via_sgd_write, NULL, NULL, dev); } - uint8_t ac97_via_codec_read(uint16_t addr, void *priv) { - ac97_via_t *dev = (ac97_via_t *) priv; - uint8_t modem = (addr & 0xff00) == dev->modem_codec_base; + const ac97_via_t *dev = (ac97_via_t *) priv; + uint8_t modem = (addr & 0xff00) == dev->modem_codec_base; + uint8_t ret = 0xff; + addr &= 0xff; - uint8_t ret = 0xff; ret = dev->codec_shadow[modem].regs_linear[addr]; @@ -465,12 +482,11 @@ ac97_via_codec_read(uint16_t addr, void *priv) return ret; } - void ac97_via_codec_write(uint16_t addr, uint8_t val, void *priv) { - ac97_via_t *dev = (ac97_via_t *) priv; - uint8_t modem = (addr & 0xff00) == dev->modem_codec_base; + ac97_via_t *dev = (ac97_via_t *) priv; + uint8_t modem = (addr & 0xff00) == dev->modem_codec_base; addr &= 0xff; ac97_via_log("AC97 VIA %d: codec_write(%02X, %02X)\n", modem, addr, val); @@ -479,239 +495,234 @@ ac97_via_codec_write(uint16_t addr, uint8_t val, void *priv) dev->codec_shadow[modem].regs_linear[addr] = val; } - void ac97_via_remap_audio_codec(void *priv, uint16_t new_io_base, uint8_t enable) { ac97_via_t *dev = (ac97_via_t *) priv; if (dev->audio_codec_base) - io_removehandler(dev->audio_codec_base, 256, ac97_via_codec_read, NULL, NULL, ac97_via_codec_write, NULL, NULL, dev); + io_removehandler(dev->audio_codec_base, 256, ac97_via_codec_read, NULL, NULL, ac97_via_codec_write, NULL, NULL, dev); dev->audio_codec_base = new_io_base; if (dev->audio_codec_base && enable) - io_sethandler(dev->audio_codec_base, 256, ac97_via_codec_read, NULL, NULL, ac97_via_codec_write, NULL, NULL, dev); + io_sethandler(dev->audio_codec_base, 256, ac97_via_codec_read, NULL, NULL, ac97_via_codec_write, NULL, NULL, dev); } - void ac97_via_remap_modem_codec(void *priv, uint16_t new_io_base, uint8_t enable) { ac97_via_t *dev = (ac97_via_t *) priv; if (dev->modem_codec_base) - io_removehandler(dev->modem_codec_base, 256, ac97_via_codec_read, NULL, NULL, ac97_via_codec_write, NULL, NULL, dev); + io_removehandler(dev->modem_codec_base, 256, ac97_via_codec_read, NULL, NULL, ac97_via_codec_write, NULL, NULL, dev); dev->modem_codec_base = new_io_base; if (dev->modem_codec_base && enable) - io_sethandler(dev->modem_codec_base, 256, ac97_via_codec_read, NULL, NULL, ac97_via_codec_write, NULL, NULL, dev); + io_sethandler(dev->modem_codec_base, 256, ac97_via_codec_read, NULL, NULL, ac97_via_codec_write, NULL, NULL, dev); } - static void ac97_via_update_stereo(ac97_via_t *dev, ac97_via_sgd_t *sgd) { - int32_t l = (((sgd->out_l * sgd->vol_l) >> 15) * dev->master_vol_l) >> 15, - r = (((sgd->out_r * sgd->vol_r) >> 15) * dev->master_vol_r) >> 15; + int32_t l = (((sgd->out_l * sgd->vol_l) >> 15) * dev->master_vol_l) >> 15; + int32_t r = (((sgd->out_r * sgd->vol_r) >> 15) * dev->master_vol_r) >> 15; if (l < -32768) - l = -32768; + l = -32768; else if (l > 32767) - l = 32767; + l = 32767; if (r < -32768) - r = -32768; + r = -32768; else if (r > 32767) - r = 32767; + r = 32767; for (; sgd->pos < sound_pos_global; sgd->pos++) { - sgd->buffer[sgd->pos*2] = l; - sgd->buffer[sgd->pos*2 + 1] = r; + sgd->buffer[sgd->pos * 2] = l; + sgd->buffer[sgd->pos * 2 + 1] = r; } } - static void ac97_via_sgd_process(void *priv) { ac97_via_sgd_t *sgd = (ac97_via_sgd_t *) priv; - ac97_via_t *dev = sgd->dev; + ac97_via_t *dev = sgd->dev; /* Stop if this SGD is not active. */ uint8_t sgd_status = dev->sgd_regs[sgd->id] & 0xc4; if (!(sgd_status & 0x80)) - return; + return; /* Schedule next run. */ timer_on_auto(&sgd->dma_timer, 10.0); /* Process SGD if it's active, and the FIFO has room or is disabled. */ - if ((sgd_status == 0x80) && (sgd->always_run || ((sgd->fifo_end - sgd->fifo_pos) <= (sizeof(sgd->fifo) - 4)))) { - /* Move on to the next block if no entry is present. */ - if (sgd->restart) { - sgd->restart = 0; + if (((sgd_status & 0xc7) == 0x80) && (sgd->always_run || ((sgd->fifo_end - sgd->fifo_pos) <= (sizeof(sgd->fifo) - 4)))) { + /* Move on to the next block if no entry is present. */ + if (sgd->restart) { + /* (Re)load entry pointer if required. */ + if (sgd->restart & 2) + sgd->entry_ptr = *((uint32_t *) &dev->sgd_regs[sgd->id | 0x4]) & 0xfffffffe; /* TODO: probe real hardware - does "even addr" actually mean dword aligned? */ + sgd->restart = 0; - /* Start at first entry if no pointer is present. */ - if (!sgd->entry_ptr) - sgd->entry_ptr = *((uint32_t *) &dev->sgd_regs[sgd->id | 0x4]) & 0xfffffffe; - - /* Read entry. */ - sgd->sample_ptr = mem_readl_phys(sgd->entry_ptr); - sgd->entry_ptr += 4; - sgd->sample_count = mem_readl_phys(sgd->entry_ptr); - sgd->entry_ptr += 4; + /* Read entry. */ + sgd->sample_ptr = mem_readl_phys(sgd->entry_ptr); + sgd->entry_ptr += 4; + sgd->sample_count = mem_readl_phys(sgd->entry_ptr); + sgd->entry_ptr += 4; #ifdef ENABLE_AC97_VIA_LOG - if (((sgd->sample_ptr == 0xffffffff) && (sgd->sample_count == 0xffffffff)) || - ((sgd->sample_ptr == 0x00000000) && (sgd->sample_count == 0x00000000))) - fatal("AC97 VIA: Invalid SGD %d entry %08X%08X at %08X\n", sgd->id >> 4, - sgd->sample_ptr, sgd->sample_count, sgd->entry_ptr - 8); + if (((sgd->sample_ptr == 0xffffffff) && (sgd->sample_count == 0xffffffff)) || ((sgd->sample_ptr == 0x00000000) && (sgd->sample_count == 0x00000000))) + fatal("AC97 VIA: Invalid SGD %d entry %08X%08X at %08X\n", sgd->id >> 4, + sgd->sample_ptr, sgd->sample_count, sgd->entry_ptr - 8); #endif - /* Extract flags from the most significant byte. */ - sgd->entry_flags = sgd->sample_count >> 24; - sgd->sample_count &= 0xffffff; + /* Extract flags from the most significant byte. */ + sgd->entry_flags = sgd->sample_count >> 24; + sgd->sample_count &= 0xffffff; - ac97_via_log("AC97 VIA: Starting SGD %d block at %08X start %08X len %06X flags %02X\n", sgd->id >> 4, - sgd->entry_ptr - 8, sgd->sample_ptr, sgd->sample_count, sgd->entry_flags); - } + ac97_via_log("AC97 VIA: Starting SGD %d block at %08X start %08X len %06X flags %02X\n", sgd->id >> 4, + sgd->entry_ptr - 8, sgd->sample_ptr, sgd->sample_count, sgd->entry_flags); + } - if (sgd->id & 0x10) { - /* Write channel: read data from FIFO. */ - mem_writel_phys(sgd->sample_ptr, *((uint32_t *) &sgd->fifo[sgd->fifo_end & (sizeof(sgd->fifo) - 1)])); - } else { - /* Read channel: write data to FIFO. */ - *((uint32_t *) &sgd->fifo[sgd->fifo_end & (sizeof(sgd->fifo) - 1)]) = mem_readl_phys(sgd->sample_ptr); - } - sgd->fifo_end += 4; - sgd->sample_ptr += 4; - sgd->sample_count -= 4; + if (sgd->id & 0x10) { + /* Write channel: read data from FIFO. */ + mem_writel_phys(sgd->sample_ptr, *((uint32_t *) &sgd->fifo[sgd->fifo_end & (sizeof(sgd->fifo) - 1)])); + } else { + /* Read channel: write data to FIFO. */ + *((uint32_t *) &sgd->fifo[sgd->fifo_end & (sizeof(sgd->fifo) - 1)]) = mem_readl_phys(sgd->sample_ptr); + } + sgd->fifo_end += 4; + sgd->sample_ptr += 4; + sgd->sample_count -= 4; - /* Check if we've hit the end of this block. */ - if (sgd->sample_count <= 0) { - ac97_via_log("AC97 VIA: Ending SGD %d block", sgd->id >> 4); + /* Check if we've hit the end of this block. */ + if (sgd->sample_count <= 0) { + ac97_via_log("AC97 VIA: Ending SGD %d block", sgd->id >> 4); - if (sgd->entry_flags & 0x20) { - ac97_via_log(" with STOP"); + /* Move on to the next block on the next run, unless overridden below. */ + sgd->restart = 1; - /* Raise STOP to pause SGD. */ - dev->sgd_regs[sgd->id] |= 0x04; - } + if (sgd->entry_flags & 0x20) { + ac97_via_log(" with STOP"); - if (sgd->entry_flags & 0x40) { - ac97_via_log(" with FLAG"); + /* Raise STOP to pause SGD. */ + dev->sgd_regs[sgd->id] |= 0x04; + } - /* Raise FLAG and STOP. */ - dev->sgd_regs[sgd->id] |= 0x05; + if (sgd->entry_flags & 0x40) { + ac97_via_log(" with FLAG"); + + /* Raise FLAG to pause SGD. */ + dev->sgd_regs[sgd->id] |= 0x01; #ifdef ENABLE_AC97_VIA_LOG - if (dev->sgd_regs[sgd->id | 0x2] & 0x01) - ac97_via_log(" interrupt"); + if (dev->sgd_regs[sgd->id | 0x2] & 0x01) + ac97_via_log(" interrupt"); #endif - } + } - if (sgd->entry_flags & 0x80) { - ac97_via_log(" with EOL"); + if (sgd->entry_flags & 0x80) { + ac97_via_log(" with EOL"); - /* Raise EOL. */ - dev->sgd_regs[sgd->id] |= 0x02; + /* Raise EOL. */ + dev->sgd_regs[sgd->id] |= 0x02; #ifdef ENABLE_AC97_VIA_LOG - if (dev->sgd_regs[sgd->id | 0x2] & 0x02) - ac97_via_log(" interrupt"); + if (dev->sgd_regs[sgd->id | 0x2] & 0x02) + ac97_via_log(" interrupt"); #endif - /* Restart SGD if a trigger is queued or auto-start is enabled. */ - if ((dev->sgd_regs[sgd->id] & 0x08) || (dev->sgd_regs[sgd->id | 0x2] & 0x80)) { - ac97_via_log(" restart"); + /* Restart SGD if a trigger is queued or auto-start is enabled. */ + if ((dev->sgd_regs[sgd->id] & 0x08) || (dev->sgd_regs[sgd->id | 0x2] & 0x80)) { + ac97_via_log(" restart"); - /* Un-queue trigger. */ - dev->sgd_regs[sgd->id] &= ~0x08; + /* Un-queue trigger. */ + dev->sgd_regs[sgd->id] &= ~0x08; - /* Go back to the starting block. */ - sgd->entry_ptr = 0; /* ugly, but Windows XP plays too fast if the pointer is reloaded now */ - } else { - ac97_via_log(" finish"); + /* Go back to the starting block on the next run. */ + sgd->restart = 2; + } else { + ac97_via_log(" finish"); - /* Terminate SGD. */ - dev->sgd_regs[sgd->id] &= ~0x80; - } - } - ac97_via_log("\n"); + /* Terminate SGD. */ + dev->sgd_regs[sgd->id] &= ~0x80; + } + } + ac97_via_log("\n"); - /* Fire any requested status interrupts. */ - ac97_via_update_irqs(dev); - - /* Move on to a new block on the next run. */ - sgd->restart = 1; - } + /* Fire any requested status interrupts. */ + ac97_via_update_irqs(dev); + } } } - static void ac97_via_poll_stereo(void *priv) { - ac97_via_t *dev = (ac97_via_t *) priv; + ac97_via_t *dev = (ac97_via_t *) priv; ac97_via_sgd_t *sgd = &dev->sgd[0]; /* Audio Read */ /* Schedule next run if PCM playback is enabled. */ if (dev->pcm_enabled) - timer_advance_u64(&sgd->poll_timer, sgd->timer_latch); + timer_advance_u64(&sgd->poll_timer, sgd->timer_latch); /* Update stereo audio buffer. */ ac97_via_update_stereo(dev, sgd); /* Feed next sample from the FIFO. */ switch (dev->sgd_regs[sgd->id | 0x2] & 0x30) { - case 0x00: /* Mono, 8-bit PCM */ - if ((sgd->fifo_end - sgd->fifo_pos) >= 1) { - sgd->out_l = sgd->out_r = (sgd->fifo[sgd->fifo_pos++ & (sizeof(sgd->fifo) - 1)] ^ 0x80) << 8; - return; - } - break; + case 0x00: /* Mono, 8-bit PCM */ + if ((sgd->fifo_end - sgd->fifo_pos) >= 1) { + sgd->out_l = sgd->out_r = (sgd->fifo[sgd->fifo_pos++ & (sizeof(sgd->fifo) - 1)] ^ 0x80) << 8; + return; + } + break; - case 0x10: /* Stereo, 8-bit PCM */ - if ((sgd->fifo_end - sgd->fifo_pos) >= 2) { - sgd->out_l = (sgd->fifo[sgd->fifo_pos++ & (sizeof(sgd->fifo) - 1)] ^ 0x80) << 8; - sgd->out_r = (sgd->fifo[sgd->fifo_pos++ & (sizeof(sgd->fifo) - 1)] ^ 0x80) << 8; - return; - } - break; + case 0x10: /* Stereo, 8-bit PCM */ + if ((sgd->fifo_end - sgd->fifo_pos) >= 2) { + sgd->out_l = (sgd->fifo[sgd->fifo_pos++ & (sizeof(sgd->fifo) - 1)] ^ 0x80) << 8; + sgd->out_r = (sgd->fifo[sgd->fifo_pos++ & (sizeof(sgd->fifo) - 1)] ^ 0x80) << 8; + return; + } + break; - case 0x20: /* Mono, 16-bit PCM */ - if ((sgd->fifo_end - sgd->fifo_pos) >= 2) { - sgd->out_l = sgd->out_r = *((uint16_t *) &sgd->fifo[sgd->fifo_pos & (sizeof(sgd->fifo) - 1)]); - sgd->fifo_pos += 2; - return; - } - break; + case 0x20: /* Mono, 16-bit PCM */ + if ((sgd->fifo_end - sgd->fifo_pos) >= 2) { + sgd->out_l = sgd->out_r = *((uint16_t *) &sgd->fifo[sgd->fifo_pos & (sizeof(sgd->fifo) - 1)]); + sgd->fifo_pos += 2; + return; + } + break; - case 0x30: /* Stereo, 16-bit PCM */ - if ((sgd->fifo_end - sgd->fifo_pos) >= 4) { - sgd->out_l = *((uint16_t *) &sgd->fifo[sgd->fifo_pos & (sizeof(sgd->fifo) - 1)]); - sgd->fifo_pos += 2; - sgd->out_r = *((uint16_t *) &sgd->fifo[sgd->fifo_pos & (sizeof(sgd->fifo) - 1)]); - sgd->fifo_pos += 2; - return; - } - break; + case 0x30: /* Stereo, 16-bit PCM */ + if ((sgd->fifo_end - sgd->fifo_pos) >= 4) { + sgd->out_l = *((uint16_t *) &sgd->fifo[sgd->fifo_pos & (sizeof(sgd->fifo) - 1)]); + sgd->fifo_pos += 2; + sgd->out_r = *((uint16_t *) &sgd->fifo[sgd->fifo_pos & (sizeof(sgd->fifo) - 1)]); + sgd->fifo_pos += 2; + return; + } + break; + + default: + break; } /* Feed silence if the FIFO is empty. */ sgd->out_l = sgd->out_r = 0; } - static void ac97_via_poll_fm(void *priv) { - ac97_via_t *dev = (ac97_via_t *) priv; + ac97_via_t *dev = (ac97_via_t *) priv; ac97_via_sgd_t *sgd = &dev->sgd[2]; /* FM Read */ /* Schedule next run if FM playback is enabled. */ if (dev->fm_enabled) - timer_advance_u64(&sgd->poll_timer, sgd->timer_latch); + timer_advance_u64(&sgd->poll_timer, sgd->timer_latch); /* Update FM audio buffer. */ ac97_via_update_stereo(dev, sgd); @@ -719,18 +730,17 @@ ac97_via_poll_fm(void *priv) /* Feed next sample from the FIFO. The data format is not documented, but it probes as 16-bit stereo at 24 KHz. */ if ((sgd->fifo_end - sgd->fifo_pos) >= 4) { - sgd->out_l = *((uint16_t *) &sgd->fifo[sgd->fifo_pos & (sizeof(sgd->fifo) - 1)]); - sgd->fifo_pos += 2; - sgd->out_r = *((uint16_t *) &sgd->fifo[sgd->fifo_pos & (sizeof(sgd->fifo) - 1)]); - sgd->fifo_pos += 2; - return; + sgd->out_l = *((uint16_t *) &sgd->fifo[sgd->fifo_pos & (sizeof(sgd->fifo) - 1)]); + sgd->fifo_pos += 2; + sgd->out_r = *((uint16_t *) &sgd->fifo[sgd->fifo_pos & (sizeof(sgd->fifo) - 1)]); + sgd->fifo_pos += 2; + return; } /* Feed silence if the FIFO is empty. */ sgd->out_l = sgd->out_r = 0; } - static void ac97_via_get_buffer(int32_t *buffer, int len, void *priv) { @@ -740,44 +750,42 @@ ac97_via_get_buffer(int32_t *buffer, int len, void *priv) ac97_via_update_stereo(dev, &dev->sgd[2]); for (int c = 0; c < len * 2; c++) { - buffer[c] += dev->sgd[0].buffer[c] / 2; - buffer[c] += dev->sgd[2].buffer[c] / 2; + buffer[c] += dev->sgd[0].buffer[c] / 2; + buffer[c] += dev->sgd[2].buffer[c] / 2; } dev->sgd[0].pos = dev->sgd[2].pos = 0; } - static void ac97_via_filter_cd_audio(int channel, double *buffer, void *priv) { - ac97_via_t *dev = (ac97_via_t *) priv; - double c, volume = channel ? dev->cd_vol_r : dev->cd_vol_l; + const ac97_via_t *dev = (ac97_via_t *) priv; + double c; + double volume = channel ? dev->cd_vol_r : dev->cd_vol_l; - c = ((*buffer) * volume) / 65536.0; + c = ((*buffer) * volume) / 65536.0; *buffer = c; } - static void ac97_via_speed_changed(void *priv) { ac97_via_t *dev = (ac97_via_t *) priv; - double freq; + double freq; /* Get variable sample rate if enabled. */ if (dev->vsr_enabled && dev->codec[0][0]) - freq = ac97_codec_getrate(dev->codec[0][0], 0x2c); + freq = ac97_codec_getrate(dev->codec[0][0], 0x2c); else - freq = 48000.0; + freq = (double) SOUND_FREQ; dev->sgd[0].timer_latch = (uint64_t) ((double) TIMER_USEC * (1000000.0 / freq)); - dev->sgd[2].timer_latch = (uint64_t) ((double) TIMER_USEC * (1000000.0 / 24000.0)); + dev->sgd[2].timer_latch = (uint64_t) ((double) TIMER_USEC * (1000000.0 / 24000.0)); /* FM operates at a fixed 24 KHz */ } - static void * -ac97_via_init(const device_t *info) +ac97_via_init(UNUSED(const device_t *info)) { ac97_via_t *dev = malloc(sizeof(ac97_via_t)); memset(dev, 0, sizeof(ac97_via_t)); @@ -785,25 +793,21 @@ ac97_via_init(const device_t *info) ac97_via_log("AC97 VIA: init()\n"); /* Set up codecs. */ - ac97_codec = &dev->codec[0][0]; + ac97_codec = &dev->codec[0][0]; ac97_modem_codec = &dev->codec[1][0]; ac97_codec_count = ac97_modem_codec_count = sizeof(dev->codec[0]) / sizeof(dev->codec[0][0]); ac97_codec_id = ac97_modem_codec_id = 0; /* Set up SGD channels. */ for (uint8_t i = 0; i < (sizeof(dev->sgd) / sizeof(dev->sgd[0])); i++) { - dev->sgd[i].id = i << 4; - dev->sgd[i].dev = dev; + dev->sgd[i].id = i << 4; + dev->sgd[i].dev = dev; - /* Disable the FIFO on SGDs we don't care about. */ - if ((i != 0) && (i != 2)) - dev->sgd[i].always_run = 1; + /* Disable the FIFO on SGDs we don't care about. */ + if ((i != 0) && (i != 2)) + dev->sgd[i].always_run = 1; - /* No volume control on FM SGD that I know of. */ - if (i == 2) - dev->sgd[i].vol_l = dev->sgd[i].vol_r = 32767; - - timer_add(&dev->sgd[i].dma_timer, ac97_via_sgd_process, &dev->sgd[i], 0); + timer_add(&dev->sgd[i].dma_timer, ac97_via_sgd_process, &dev->sgd[i], 0); } /* Set up playback pollers. */ @@ -817,7 +821,6 @@ ac97_via_init(const device_t *info) return dev; } - static void ac97_via_close(void *priv) { @@ -828,16 +831,16 @@ ac97_via_close(void *priv) free(dev); } - -const device_t ac97_via_device = -{ - "VIA VT82C686 Integrated AC97 Controller", - "ac97_via", - DEVICE_PCI, - 0, - ac97_via_init, ac97_via_close, NULL, - { NULL }, - ac97_via_speed_changed, - NULL, - NULL +const device_t ac97_via_device = { + .name = "VIA VT82C686 Integrated AC97 Controller", + .internal_name = "ac97_via", + .flags = DEVICE_PCI, + .local = 0, + .init = ac97_via_init, + .close = ac97_via_close, + .reset = NULL, + { .available = NULL }, + .speed_changed = ac97_via_speed_changed, + .force_redraw = NULL, + .config = NULL }; diff --git a/src/sound/snd_ad1848.c b/src/sound/snd_ad1848.c index ff4c0be83..d2a05fd6f 100644 --- a/src/sound/snd_ad1848.c +++ b/src/sound/snd_ad1848.c @@ -1,43 +1,46 @@ /* - * 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. + * 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. + * This file is part of the 86Box distribution. * - * AD1848 / CS4248 / CS4231 (Windows Sound System) codec emulation. + * AD1848 / CS4248 / CS4231 (Windows Sound System) codec emulation. * * * - * Authors: Sarah Walker, - * TheCollector1995, - * RichardG, + * Authors: Sarah Walker, + * TheCollector1995, + * RichardG, * - * Copyright 2008-2020 Sarah Walker. - * Copyright 2018-2020 TheCollector1995. - * Copyright 2021 RichardG. + * Copyright 2008-2020 Sarah Walker. + * Copyright 2018-2020 TheCollector1995. + * Copyright 2021-2022 RichardG. */ -#include +#include #include +#include #include #include -#include + #include <86box/86box.h> #include <86box/dma.h> #include <86box/pic.h> #include <86box/timer.h> #include <86box/sound.h> #include <86box/snd_ad1848.h> +#include <86box/plat_fallthrough.h> +#define CS4231 0x80 +#define CS4236 0x03 -#define CS4231 0x80 -#define CS4236 0x03 - - -static int ad1848_vols_7bits[128]; -static double ad1848_vols_5bits_aux_gain[32]; +static int ad1848_vols_7bits[128]; +static double ad1848_vols_5bits_aux_gain[32]; +/* Borrowed from snd_sb_dsp */ +extern int8_t scaleMap4[64]; +extern uint8_t adjustMap4[64]; void ad1848_setirq(ad1848_t *ad1848, int irq) @@ -45,326 +48,461 @@ ad1848_setirq(ad1848_t *ad1848, int irq) ad1848->irq = irq; } - void -ad1848_setdma(ad1848_t *ad1848, int dma) +ad1848_setdma(ad1848_t *ad1848, int newdma) { - ad1848->dma = dma; + ad1848->dma = newdma; } - void ad1848_updatevolmask(ad1848_t *ad1848) { - if ((ad1848->type == AD1848_TYPE_CS4236) && ((ad1848->xregs[4] & 0x10) || ad1848->wten)) - ad1848->wave_vol_mask = 0x3f; + if ((ad1848->type >= AD1848_TYPE_CS4235) && ((ad1848->xregs[4] & 0x10) || ad1848->wten)) + ad1848->wave_vol_mask = 0x3f; else - ad1848->wave_vol_mask = 0x7f; + ad1848->wave_vol_mask = 0x7f; } - 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_CS4236) { - if (ad1848->xregs[11] & 0x20) { - freq = 16934400LL; - switch (ad1848->xregs[13]) { - case 1: freq /= 353; break; - case 2: freq /= 529; break; - case 3: freq /= 617; break; - case 4: freq /= 1058; break; - case 5: freq /= 1764; break; - case 6: freq /= 2117; break; - case 7: freq /= 2558; break; - default: freq /= 16 * MAX(ad1848->xregs[13], 21); break; - } - set = 1; - } else if (ad1848->regs[22] & 0x80) { - freq = (ad1848->regs[22] & 1) ? 33868800LL : 49152000LL; - set = (ad1848->regs[22] >> 1) & 0x3f; - switch (ad1848->regs[10] & 0x30) { - case 0x00: freq /= 128 * set; break; - case 0x10: freq /= 64 * set; break; - case 0x20: freq /= 256 * set; break; - } - set = 1; - } + if (ad1848->type >= AD1848_TYPE_CS4235) { + if (ad1848->xregs[11] & 0x20) { + freq = 16934400LL; + switch (ad1848->xregs[13]) { + case 1: + freq /= 353; + break; + case 2: + freq /= 529; + break; + case 3: + freq /= 617; + break; + case 4: + freq /= 1058; + break; + case 5: + freq /= 1764; + break; + case 6: + freq /= 2117; + break; + case 7: + freq /= 2558; + break; + default: + freq /= 16 * MAX(ad1848->xregs[13], 21); + break; + } + set = 1; + } else if (ad1848->regs[22] & 0x80) { + freq = (ad1848->regs[22] & 1) ? 33868800LL : 49152000LL; + set = (ad1848->regs[22] >> 1) & 0x3f; + switch (ad1848->regs[10] & 0x30) { + case 0x00: + freq /= 128 * set; + break; + case 0x10: + freq /= 64 * set; + break; + case 0x20: + freq /= 256 * set; + break; + + default: + break; + } + set = 1; + } } if (!set) { - freq = (ad1848->regs[8] & 1) ? 16934400LL : 24576000LL; - switch ((ad1848->regs[8] >> 1) & 7) { - case 0: freq /= 3072; break; - case 1: freq /= 1536; break; - case 2: freq /= 896; break; - case 3: freq /= 768; break; - case 4: freq /= 448; break; - case 5: freq /= 384; break; - case 6: freq /= 512; break; - case 7: freq /= 2560; break; - } + freq = (ad1848->regs[8] & 1) ? 16934400LL : 24576000LL; + switch ((ad1848->regs[8] >> 1) & 7) { + case 0: + freq /= 3072; + break; + case 1: + freq /= 1536; + break; + case 2: + freq /= 896; + break; + case 3: + freq /= 768; + break; + case 4: + freq /= 448; + break; + case 5: + freq /= 384; + break; + case 6: + freq /= 512; + break; + case 7: + freq /= 2560; + break; + + default: + break; + } } - ad1848->freq = freq; + ad1848->freq = freq; ad1848->timer_latch = (uint64_t) ((double) TIMER_USEC * (1000000.0 / (double) ad1848->freq)); } - uint8_t ad1848_read(uint16_t addr, void *priv) { ad1848_t *ad1848 = (ad1848_t *) priv; - uint8_t ret = 0xff; + uint8_t ret = 0xff; switch (addr & 3) { - case 0: /* Index */ - ret = ad1848->index | ad1848->trd | ad1848->mce; - break; + case 0: /* Index */ + ret = ad1848->index | ad1848->trd | ad1848->mce; + break; - case 1: - ret = ad1848->regs[ad1848->index]; - switch (ad1848->index) { - case 11: - ret ^= 0x20; - ad1848->regs[ad1848->index] = ret; - break; + case 1: + ret = ad1848->regs[ad1848->index]; + switch (ad1848->index) { + case 11: + ret ^= 0x20; + ad1848->regs[ad1848->index] = ret; + break; - case 18: case 19: - if (ad1848->type == AD1848_TYPE_CS4236) { - if ((ad1848->xregs[4] & 0x14) == 0x14) /* FM remapping */ - ret = ad1848->xregs[ad1848->index - 12]; /* real FM volume on registers 6 and 7 */ - else if (ad1848->wten && !(ad1848->xregs[4] & 0x08)) /* wavetable remapping */ - ret = ad1848->xregs[ad1848->index - 2]; /* real wavetable volume on registers 16 and 17 */ - } - break; + case 18: + case 19: + if (ad1848->type >= AD1848_TYPE_CS4235) { + if ((ad1848->xregs[4] & 0x14) == 0x14) /* FM remapping */ + ret = ad1848->xregs[ad1848->index - 12]; /* real FM volume on registers 6 and 7 */ + else if (ad1848->wten && !(ad1848->xregs[4] & 0x08)) /* wavetable remapping */ + ret = ad1848->xregs[ad1848->index - 2]; /* real wavetable volume on registers 16 and 17 */ + } + break; - case 23: - if ((ad1848->type == AD1848_TYPE_CS4236) && (ad1848->regs[23] & 0x08)) { - if ((ad1848->xindex & 0xfe) == 0x00) /* remapped line volume */ - ret = ad1848->regs[18 + ad1848->xindex]; - else - ret = ad1848->xregs[ad1848->xindex]; - } - break; - } - break; + case 20: + case 21: + /* Backdoor to the Control/RAM registers on CS4235. */ + if ((ad1848->type == AD1848_TYPE_CS4235) && (ad1848->xregs[18] & 0x80)) + ret = ad1848->cram_read(ad1848->index - 15, ad1848->cram_priv); + break; - case 2: - ret = ad1848->status; - break; + case 23: + if ((ad1848->type >= AD1848_TYPE_CS4235) && (ad1848->regs[23] & 0x08)) { + if ((ad1848->xindex & 0xfe) == 0x00) /* remapped line volume */ + ret = ad1848->regs[18 + ad1848->xindex]; + else + ret = ad1848->xregs[ad1848->xindex]; + } + break; + + default: + break; + } + break; + + case 2: + ret = ad1848->status; + break; + + default: + break; } return ret; } - void ad1848_write(uint16_t addr, uint8_t val, void *priv) { ad1848_t *ad1848 = (ad1848_t *) priv; - uint8_t temp = 0, updatefreq = 0; + uint8_t temp = 0; + uint8_t updatefreq = 0; switch (addr & 3) { - case 0: /* Index */ - if ((ad1848->regs[12] & 0x40) && (ad1848->type >= AD1848_TYPE_CS4231)) - ad1848->index = val & 0x1f; /* cs4231a extended mode enabled */ - else - ad1848->index = val & 0x0f; /* ad1848/cs4248 mode TODO: some variants/clones DO NOT mirror, just ignore the writes? */ - if (ad1848->type == AD1848_TYPE_CS4236) - ad1848->regs[23] &= ~0x08; /* clear XRAE */ - ad1848->trd = val & 0x20; - ad1848->mce = val & 0x40; - break; + case 0: /* Index */ + if ((ad1848->regs[12] & 0x40) && (ad1848->type >= AD1848_TYPE_CS4231)) + ad1848->index = val & 0x1f; /* cs4231a extended mode enabled */ + else + ad1848->index = val & 0x0f; /* ad1848/cs4248 mode TODO: some variants/clones DO NOT mirror, just ignore the writes? */ + if (ad1848->type >= AD1848_TYPE_CS4235) + ad1848->regs[23] &= ~0x08; /* clear XRAE */ + ad1848->trd = val & 0x20; + ad1848->mce = val & 0x40; + break; - case 1: - switch (ad1848->index) { - case 10: - if (ad1848->type != AD1848_TYPE_CS4236) - break; - /* fall-through */ + case 1: + switch (ad1848->index) { + case 10: + if (ad1848->type < AD1848_TYPE_CS4235) + break; + fallthrough; - case 8: - updatefreq = 1; - break; - - case 9: - if (!ad1848->enable && (val & 0x41) == 0x01) { - if (ad1848->timer_latch) - timer_set_delay_u64(&ad1848->timer_count, ad1848->timer_latch); - else - timer_set_delay_u64(&ad1848->timer_count, TIMER_USEC); - } - ad1848->enable = ((val & 0x41) == 0x01); - if (!ad1848->enable) { - timer_disable(&ad1848->timer_count); - ad1848->out_l = ad1848->out_r = 0; - } - break; + case 8: + updatefreq = 1; + break; - case 11: - return; - - case 12: - if (ad1848->type != AD1848_TYPE_DEFAULT) - ad1848->regs[12] = ((ad1848->regs[12] & 0x0f) + (val & 0xf0)) | 0x80; - return; + case 9: + if (!ad1848->enable && (val & 0x41) == 0x01) { + ad1848->adpcm_pos = 0; + if (ad1848->timer_latch) + timer_set_delay_u64(&ad1848->timer_count, ad1848->timer_latch); + else + timer_set_delay_u64(&ad1848->timer_count, TIMER_USEC); + } + ad1848->enable = ((val & 0x41) == 0x01); + if (!ad1848->enable) { + timer_disable(&ad1848->timer_count); + ad1848->out_l = ad1848->out_r = 0; + } + break; - case 14: - ad1848->count = ad1848->regs[15] | (val << 8); - break; + case 11: + return; - case 17: - if (ad1848->type >= AD1848_TYPE_CS4231) /* enable additional data formats on modes 2 and 3 */ - ad1848->fmt_mask = (val & 0x40) ? 0xf0 : 0x70; - break; + case 12: + if (ad1848->type != AD1848_TYPE_DEFAULT) + ad1848->regs[12] = ((ad1848->regs[12] & 0x0f) + (val & 0xf0)) | 0x80; + return; - case 18: case 19: - if (ad1848->type == AD1848_TYPE_CS4236) { - if ((ad1848->xregs[4] & 0x14) == 0x14) { /* FM remapping */ - ad1848->xregs[ad1848->index - 12] = val; /* real FM volume on extended registers 6 and 7 */ - temp = 1; + case 14: + ad1848->count = ad1848->regs[15] | (val << 8); + break; - if (ad1848->index == 18) { - if (val & 0x80) - ad1848->fm_vol_l = 0; - else - ad1848->fm_vol_l = ad1848_vols_7bits[val & 0x3f]; - } else { - if (val & 0x80) - ad1848->fm_vol_r = 0; - else - ad1848->fm_vol_r = ad1848_vols_7bits[val & 0x3f]; - } - } - if (ad1848->wten && !(ad1848->xregs[4] & 0x08)) { /* wavetable remapping */ - ad1848->xregs[ad1848->index - 2] = val; /* real wavetable volume on extended registers 16 and 17 */ - temp = 1; - } + case 17: + /* Enable additional data formats on modes 2 and 3 where supported. */ + if ((ad1848->type == AD1848_TYPE_CS4231) || (ad1848->type == AD1848_TYPE_CS4236)) + ad1848->fmt_mask = (val & 0x40) ? 0xf0 : 0x70; + break; - /* Stop here if any remapping is enabled. */ - if (temp) - return; + case 18: + case 19: + if (ad1848->type >= AD1848_TYPE_CS4235) { + if ((ad1848->xregs[4] & 0x14) == 0x14) { /* FM remapping */ + ad1848->xregs[ad1848->index - 12] = val; /* real FM volume on extended registers 6 and 7 */ + temp = 1; - /* HACK: the Windows 9x driver's "Synth" control writes to this - register with no remapping, even if internal FM is enabled. */ - if (ad1848->index == 18) { - if (val & 0x80) - ad1848->fm_vol_l = 0; - else - ad1848->fm_vol_l = (int) ad1848_vols_5bits_aux_gain[val & 0x1f]; - } else { - if (val & 0x80) - ad1848->fm_vol_r = 0; - else - ad1848->fm_vol_r = (int) ad1848_vols_5bits_aux_gain[val & 0x1f]; - } - } - break; + if (ad1848->index == 18) { + if (val & 0x80) + ad1848->fm_vol_l = 0; + else + ad1848->fm_vol_l = ad1848_vols_7bits[val & 0x3f]; + } else { + if (val & 0x80) + ad1848->fm_vol_r = 0; + else + ad1848->fm_vol_r = ad1848_vols_7bits[val & 0x3f]; + } + } + if (ad1848->wten && !(ad1848->xregs[4] & 0x08)) { /* wavetable remapping */ + ad1848->xregs[ad1848->index - 2] = val; /* real wavetable volume on extended registers 16 and 17 */ + temp = 1; + } - case 22: - updatefreq = 1; - break; + /* Stop here if any remapping is enabled. */ + if (temp) + return; - case 23: - if ((ad1848->type == AD1848_TYPE_CS4236) && ((ad1848->regs[12] & 0x60) == 0x60)) { - if (!(ad1848->regs[23] & 0x08)) { /* existing (not new) XRAE is clear */ - ad1848->xindex = ((val & 0x04) << 2) | (val >> 4); - break; - } + /* HACK: the Windows 9x driver's "Synth" control writes to this + register with no remapping, even if internal FM is enabled. */ + if (ad1848->index == 18) { + if (val & 0x80) + ad1848->fm_vol_l = 0; + else + ad1848->fm_vol_l = (int) ad1848_vols_5bits_aux_gain[val & 0x1f]; + } else { + if (val & 0x80) + ad1848->fm_vol_r = 0; + else + ad1848->fm_vol_r = (int) ad1848_vols_5bits_aux_gain[val & 0x1f]; + } + } + break; - switch (ad1848->xindex) { - case 0: case 1: /* remapped line volume */ - ad1848->regs[18 + ad1848->xindex] = val; - return; + case 20: + case 21: + /* Backdoor to the Control/RAM registers on CS4235. */ + if ((ad1848->type == AD1848_TYPE_CS4235) && (ad1848->xregs[18] & 0x80)) { + ad1848->cram_write(ad1848->index - 15, val, ad1848->cram_priv); + val = ad1848->regs[ad1848->index]; + } + break; - case 6: - if (val & 0x80) - ad1848->fm_vol_l = 0; - else - ad1848->fm_vol_l = ad1848_vols_7bits[val & 0x3f]; - break; + case 22: + updatefreq = 1; + break; - case 7: - if (val & 0x80) - ad1848->fm_vol_r = 0; - else - ad1848->fm_vol_r = ad1848_vols_7bits[val & 0x3f]; - break; + case 23: + if ((ad1848->type >= AD1848_TYPE_CS4235) && ((ad1848->regs[12] & 0x60) == 0x60)) { + if (!(ad1848->regs[23] & 0x08)) { /* existing (not new) XRAE is clear */ + ad1848->xindex = ((val & 0x04) << 2) | (val >> 4); + break; + } - case 11: case 13: - updatefreq = 1; - break; + switch (ad1848->xindex) { + case 0: + case 1: /* remapped line volume */ + ad1848->regs[18 + ad1848->xindex] = val; + return; - case 25: - return; - } - ad1848->xregs[ad1848->xindex] = val; + case 6: + if (val & 0x80) + ad1848->fm_vol_l = 0; + else + ad1848->fm_vol_l = ad1848_vols_7bits[val & 0x3f]; + break; - if (updatefreq) - ad1848_updatefreq(ad1848); + case 7: + if (val & 0x80) + ad1848->fm_vol_r = 0; + else + ad1848->fm_vol_r = ad1848_vols_7bits[val & 0x3f]; + break; - return; - } - break; + case 11: + case 13: + updatefreq = 1; + break; - case 24: - val = ad1848->regs[24] & ((val & 0x70) | 0x0f); - if (!(val & 0x70)) { - ad1848->status &= 0xfe; - picintc(1 << ad1848->irq); - } - break; + case 25: + return; - case 25: - return; - } - ad1848->regs[ad1848->index] = val; + default: + break; + } + ad1848->xregs[ad1848->xindex] = val; - if (updatefreq) - ad1848_updatefreq(ad1848); + if (updatefreq) + ad1848_updatefreq(ad1848); - if ((ad1848->type == AD1848_TYPE_CS4231) || (ad1848->type == AD1848_TYPE_CS4236)) { /* TODO: configure CD volume for CS4248/AD1848 too */ - temp = (ad1848->type == AD1848_TYPE_CS4231) ? 18 : 4; - if (ad1848->regs[temp] & 0x80) - ad1848->cd_vol_l = 0; - else - ad1848->cd_vol_l = ad1848_vols_5bits_aux_gain[ad1848->regs[temp] & 0x1f]; - temp++; - if (ad1848->regs[temp] & 0x80) - ad1848->cd_vol_r = 0; - else - ad1848->cd_vol_r = ad1848_vols_5bits_aux_gain[ad1848->regs[temp] & 0x1f]; - } - break; + return; + } + break; - case 2: - ad1848->status &= 0xfe; - ad1848->regs[24] &= 0x0f; - break; + case 24: + val = ad1848->regs[24] & ((val & 0x70) | 0x0f); + if (!(val & 0x70)) { + ad1848->status &= 0xfe; + picintc(1 << ad1848->irq); + } + break; + + case 25: + return; + case 27: + if (ad1848->type != AD1848_TYPE_DEFAULT) + return; + break; + + default: + break; + } + ad1848->regs[ad1848->index] = val; + + if (updatefreq) + ad1848_updatefreq(ad1848); + + temp = (ad1848->type < AD1848_TYPE_CS4231) ? 2 : ((ad1848->type == AD1848_TYPE_CS4231) ? 18 : 4); + if (ad1848->regs[temp] & 0x80) + ad1848->cd_vol_l = 0; + else + ad1848->cd_vol_l = ad1848_vols_5bits_aux_gain[ad1848->regs[temp] & 0x1f]; + temp++; + if (ad1848->regs[temp] & 0x80) + ad1848->cd_vol_r = 0; + else + ad1848->cd_vol_r = ad1848_vols_5bits_aux_gain[ad1848->regs[temp] & 0x1f]; + + break; + + case 2: + ad1848->status &= 0xfe; + ad1848->regs[24] &= 0x0f; + break; + + default: + break; } } - void ad1848_speed_changed(ad1848_t *ad1848) { ad1848->timer_latch = (uint64_t) ((double) TIMER_USEC * (1000000.0 / (double) ad1848->freq)); } - void ad1848_update(ad1848_t *ad1848) { for (; ad1848->pos < sound_pos_global; ad1848->pos++) { - ad1848->buffer[ad1848->pos*2] = ad1848->out_l; - ad1848->buffer[ad1848->pos*2 + 1] = ad1848->out_r; + ad1848->buffer[ad1848->pos * 2] = ad1848->out_l; + ad1848->buffer[ad1848->pos * 2 + 1] = ad1848->out_r; } } +static int16_t +ad1848_process_mulaw(uint8_t byte) +{ + byte = ~byte; + int16_t dec = ((byte & 0x0f) << 3) + 0x84; + dec <<= (byte & 0x70) >> 4; + return (byte & 0x80) ? (0x84 - dec) : (dec - 0x84); +} + +static int16_t +ad1848_process_alaw(uint8_t byte) +{ + byte ^= 0x55; + int16_t dec = (byte & 0x0f) << 4; + int seg = (byte & 0x70) >> 4; + switch (seg) { + case 0: + dec |= 0x8; + break; + + case 1: + dec |= 0x108; + break; + + default: + dec |= 0x108; + dec <<= seg - 1; + break; + } + return (byte & 0x80) ? dec : -dec; +} + +static int16_t +ad1848_process_adpcm(ad1848_t *ad1848) +{ + int temp; + if (ad1848->adpcm_pos++ & 1) { + temp = (ad1848->adpcm_data & 0x0f) + ad1848->adpcm_step; + } else { + ad1848->adpcm_data = dma_channel_read(ad1848->dma); + temp = (ad1848->adpcm_data >> 4) + ad1848->adpcm_step; + } + if (temp < 0) + temp = 0; + else if (temp > 63) + temp = 63; + + ad1848->adpcm_ref += scaleMap4[temp]; + if (ad1848->adpcm_ref > 0xff) + ad1848->adpcm_ref = 0xff; + else if (ad1848->adpcm_ref < 0x00) + ad1848->adpcm_ref = 0x00; + + ad1848->adpcm_step = (ad1848->adpcm_step + adjustMap4[temp]) & 0xff; + + return (ad1848->adpcm_ref ^ 0x80) << 8; +} static void ad1848_poll(void *priv) @@ -372,144 +510,196 @@ ad1848_poll(void *priv) ad1848_t *ad1848 = (ad1848_t *) priv; if (ad1848->timer_latch) - timer_advance_u64(&ad1848->timer_count, ad1848->timer_latch); + timer_advance_u64(&ad1848->timer_count, ad1848->timer_latch); else - timer_advance_u64(&ad1848->timer_count, TIMER_USEC * 1000); + timer_advance_u64(&ad1848->timer_count, TIMER_USEC * 1000); ad1848_update(ad1848); if (ad1848->enable) { - int32_t temp; + int32_t temp; - switch (ad1848->regs[8] & ad1848->fmt_mask) { - case 0x00: /* Mono, 8-bit PCM */ - ad1848->out_l = ad1848->out_r = (dma_channel_read(ad1848->dma) ^ 0x80) * 256; - break; + switch (ad1848->regs[8] & ad1848->fmt_mask) { + case 0x00: /* Mono, 8-bit PCM */ + ad1848->out_l = ad1848->out_r = (dma_channel_read(ad1848->dma) ^ 0x80) << 8; + break; - case 0x10: /* Stereo, 8-bit PCM */ - ad1848->out_l = (dma_channel_read(ad1848->dma) ^ 0x80) * 256; - ad1848->out_r = (dma_channel_read(ad1848->dma) ^ 0x80) * 256; - break; - - case 0x40: /* Mono, 16-bit PCM little endian */ - temp = dma_channel_read(ad1848->dma); - ad1848->out_l = ad1848->out_r = (dma_channel_read(ad1848->dma) << 8) | temp; - break; + case 0x10: /* Stereo, 8-bit PCM */ + ad1848->out_l = (dma_channel_read(ad1848->dma) ^ 0x80) << 8; + ad1848->out_r = (dma_channel_read(ad1848->dma) ^ 0x80) << 8; + break; - case 0x50: /* Stereo, 16-bit PCM little endian */ - temp = dma_channel_read(ad1848->dma); - ad1848->out_l = (dma_channel_read(ad1848->dma) << 8) | temp; - temp = dma_channel_read(ad1848->dma); - ad1848->out_r = (dma_channel_read(ad1848->dma) << 8) | temp; - break; + case 0x20: /* Mono, 8-bit Mu-Law */ + ad1848->out_l = ad1848->out_r = ad1848_process_mulaw(dma_channel_read(ad1848->dma)); + break; - case 0xc0: /* Mono, 16-bit PCM big endian */ - temp = dma_channel_read(ad1848->dma); - ad1848->out_l = ad1848->out_r = dma_channel_read(ad1848->dma) | (temp << 8); - break; + case 0x30: /* Stereo, 8-bit Mu-Law */ + ad1848->out_l = ad1848_process_mulaw(dma_channel_read(ad1848->dma)); + ad1848->out_r = ad1848_process_mulaw(dma_channel_read(ad1848->dma)); + break; - case 0xd0: /* Stereo, 16-bit PCM big endian */ - temp = dma_channel_read(ad1848->dma); - ad1848->out_l = dma_channel_read(ad1848->dma) | (temp << 8); - temp = dma_channel_read(ad1848->dma); - ad1848->out_r = dma_channel_read(ad1848->dma) | (temp << 8); - break; - } + case 0x40: /* Mono, 16-bit PCM little endian */ + temp = dma_channel_read(ad1848->dma); + ad1848->out_l = ad1848->out_r = (dma_channel_read(ad1848->dma) << 8) | temp; + break; - if (ad1848->regs[6] & 0x80) - ad1848->out_l = 0; - else - ad1848->out_l = (ad1848->out_l * ad1848_vols_7bits[ad1848->regs[6] & ad1848->wave_vol_mask]) >> 16; + case 0x50: /* Stereo, 16-bit PCM little endian */ + temp = dma_channel_read(ad1848->dma); + ad1848->out_l = (dma_channel_read(ad1848->dma) << 8) | temp; + temp = dma_channel_read(ad1848->dma); + ad1848->out_r = (dma_channel_read(ad1848->dma) << 8) | temp; + break; - if (ad1848->regs[7] & 0x80) - ad1848->out_r = 0; - else - ad1848->out_r = (ad1848->out_r * ad1848_vols_7bits[ad1848->regs[7] & ad1848->wave_vol_mask]) >> 16; + case 0x60: /* Mono, 8-bit A-Law */ + ad1848->out_l = ad1848->out_r = ad1848_process_alaw(dma_channel_read(ad1848->dma)); + break; - if (ad1848->count < 0) { - ad1848->count = ad1848->regs[15] | (ad1848->regs[14] << 8); - if (!(ad1848->status & 0x01)) { - ad1848->status |= 0x01; - ad1848->regs[24] |= 0x10; - if (ad1848->regs[10] & 2) - picint(1 << ad1848->irq); - } - } + case 0x70: /* Stereo, 8-bit A-Law */ + ad1848->out_l = ad1848_process_alaw(dma_channel_read(ad1848->dma)); + ad1848->out_r = ad1848_process_alaw(dma_channel_read(ad1848->dma)); + break; - ad1848->count--; + /* 0x80 and 0x90 reserved */ + + case 0xa0: /* Mono, 4-bit ADPCM */ + ad1848->out_l = ad1848->out_r = ad1848_process_adpcm(ad1848); + break; + + case 0xb0: /* Stereo, 4-bit ADPCM */ + ad1848->out_l = ad1848_process_adpcm(ad1848); + ad1848->out_r = ad1848_process_adpcm(ad1848); + break; + + case 0xc0: /* Mono, 16-bit PCM big endian */ + temp = dma_channel_read(ad1848->dma); + ad1848->out_l = ad1848->out_r = dma_channel_read(ad1848->dma) | (temp << 8); + break; + + case 0xd0: /* Stereo, 16-bit PCM big endian */ + temp = dma_channel_read(ad1848->dma); + ad1848->out_l = dma_channel_read(ad1848->dma) | (temp << 8); + temp = dma_channel_read(ad1848->dma); + ad1848->out_r = dma_channel_read(ad1848->dma) | (temp << 8); + break; + + /* 0xe0 and 0xf0 reserved */ + + default: + break; + } + + if (ad1848->regs[6] & 0x80) + ad1848->out_l = 0; + else + ad1848->out_l = (ad1848->out_l * ad1848_vols_7bits[ad1848->regs[6] & ad1848->wave_vol_mask]) >> 16; + + if (ad1848->regs[7] & 0x80) + ad1848->out_r = 0; + else + ad1848->out_r = (ad1848->out_r * ad1848_vols_7bits[ad1848->regs[7] & ad1848->wave_vol_mask]) >> 16; + + if (ad1848->count < 0) { + ad1848->count = ad1848->regs[15] | (ad1848->regs[14] << 8); + ad1848->adpcm_pos = 0; + if (!(ad1848->status & 0x01)) { + ad1848->status |= 0x01; + ad1848->regs[24] |= 0x10; + if (ad1848->regs[10] & 2) + picint(1 << ad1848->irq); + } + } + + if (!(ad1848->adpcm_pos & 7)) /* ADPCM counts down every 4 bytes */ + ad1848->count--; } else { - ad1848->out_l = ad1848->out_r = 0; - ad1848->cd_vol_l = ad1848->cd_vol_r = 0; + ad1848->out_l = ad1848->out_r = 0; + ad1848->cd_vol_l = ad1848->cd_vol_r = 0; } } - void ad1848_filter_cd_audio(int channel, double *buffer, void *priv) { - ad1848_t *ad1848 = (ad1848_t *) priv; - double c; - double volume = channel ? ad1848->cd_vol_r : ad1848->cd_vol_l; + const ad1848_t *ad1848 = (ad1848_t *) priv; + double c; + double volume = channel ? ad1848->cd_vol_r : ad1848->cd_vol_l; - c = ((*buffer) * volume) / 65536.0; + c = ((*buffer) * volume) / 65536.0; *buffer = c; } +void +ad1848_filter_aux2(void *priv, double *out_l, double *out_r) +{ + const ad1848_t *ad1848 = (ad1848_t *) priv; + + if (ad1848->regs[4] & 0x80) { + *out_l = 0.0; + } else { + *out_l = ((*out_l) * ad1848_vols_5bits_aux_gain[ad1848->regs[4] & 0x1f]) / 65536.0; + } + + if (ad1848->regs[5] & 0x80) { + *out_r = 0.0; + } else { + *out_r = ((*out_r) * ad1848_vols_5bits_aux_gain[ad1848->regs[5] & 0x1f]) / 65536.0; + } +} void ad1848_init(ad1848_t *ad1848, uint8_t type) { uint8_t c; - double attenuation; + double attenuation; ad1848->status = 0xcc; ad1848->index = ad1848->trd = 0; - ad1848->mce = 0x40; - ad1848->wten = 0; + ad1848->mce = 0x40; + ad1848->wten = 0; ad1848->regs[0] = ad1848->regs[1] = 0; ad1848->regs[2] = ad1848->regs[3] = 0x80; /* Line-in */ ad1848->regs[4] = ad1848->regs[5] = 0x80; ad1848->regs[6] = ad1848->regs[7] = 0x80; /* Left/right Output */ - ad1848->regs[8] = 0; - ad1848->regs[9] = 0x08; + ad1848->regs[8] = 0; + ad1848->regs[9] = 0x08; ad1848->regs[10] = ad1848->regs[11] = 0; - if ((type == AD1848_TYPE_CS4248) || (type == AD1848_TYPE_CS4231) || (type == AD1848_TYPE_CS4236)) - ad1848->regs[12] = 0x8a; + if ((type == AD1848_TYPE_CS4248) || (type == AD1848_TYPE_CS4231) || (type >= AD1848_TYPE_CS4235)) + ad1848->regs[12] = 0x8a; else - ad1848->regs[12] = 0xa; + ad1848->regs[12] = 0xa; ad1848->regs[13] = 0; ad1848->regs[14] = ad1848->regs[15] = 0; if (type == AD1848_TYPE_CS4231) { - ad1848->regs[16] = ad1848->regs[17] = 0; - ad1848->regs[18] = ad1848->regs[19] = 0x88; - ad1848->regs[22] = 0x80; - ad1848->regs[24] = 0; - ad1848->regs[25] = CS4231; - ad1848->regs[26] = 0x80; - ad1848->regs[29] = 0x80; - } else if (type == AD1848_TYPE_CS4236) { - ad1848->regs[16] = ad1848->regs[17] = 0; - ad1848->regs[18] = ad1848->regs[19] = 0; - ad1848->regs[20] = ad1848->regs[21] = 0; - ad1848->regs[22] = ad1848->regs[23] = 0; - ad1848->regs[24] = 0; - ad1848->regs[25] = CS4236; - ad1848->regs[26] = 0xa0; - ad1848->regs[27] = ad1848->regs[29] = 0; - ad1848->regs[30] = ad1848->regs[31] = 0; + ad1848->regs[16] = ad1848->regs[17] = 0; + ad1848->regs[18] = ad1848->regs[19] = 0x88; + ad1848->regs[22] = 0x80; + ad1848->regs[24] = 0; + ad1848->regs[25] = CS4231; + ad1848->regs[26] = 0x80; + ad1848->regs[29] = 0x80; + } else if (type >= AD1848_TYPE_CS4235) { + ad1848->regs[16] = ad1848->regs[17] = 0; + ad1848->regs[18] = ad1848->regs[19] = 0; + ad1848->regs[20] = ad1848->regs[21] = 0; + ad1848->regs[22] = ad1848->regs[23] = 0; + ad1848->regs[24] = 0; + ad1848->regs[25] = CS4236; + ad1848->regs[26] = 0xa0; + ad1848->regs[27] = ad1848->regs[29] = 0; + ad1848->regs[30] = ad1848->regs[31] = 0; - ad1848->xregs[0] = ad1848->xregs[1] = 0xe8; - ad1848->xregs[2] = ad1848->xregs[3] = 0xcf; - ad1848->xregs[4] = 0x84; - ad1848->xregs[5] = 0; - ad1848->xregs[6] = ad1848->xregs[7] = 0x80; - ad1848->xregs[8] = ad1848->xregs[9] = 0; - ad1848->xregs[10] = 0x3f; - ad1848->xregs[11] = 0xc0; - ad1848->xregs[14] = ad1848->xregs[15] = 0; - ad1848->xregs[16] = ad1848->xregs[17] = 0; + ad1848->xregs[0] = ad1848->xregs[1] = 0xe8; + ad1848->xregs[2] = ad1848->xregs[3] = 0xcf; + ad1848->xregs[4] = 0x84; + ad1848->xregs[5] = 0; + ad1848->xregs[6] = ad1848->xregs[7] = 0x80; + ad1848->xregs[8] = ad1848->xregs[9] = 0; + ad1848->xregs[10] = 0x3f; + ad1848->xregs[11] = 0xc0; + ad1848->xregs[14] = ad1848->xregs[15] = 0; + ad1848->xregs[16] = ad1848->xregs[17] = 0; } ad1848_updatefreq(ad1848); @@ -517,37 +707,52 @@ ad1848_init(ad1848_t *ad1848, uint8_t type) ad1848->out_l = ad1848->out_r = 0; ad1848->fm_vol_l = ad1848->fm_vol_r = 65536; ad1848_updatevolmask(ad1848); - ad1848->fmt_mask = 0x70; + if (type == AD1848_TYPE_CS4235) + ad1848->fmt_mask = 0x50; + else + ad1848->fmt_mask = 0x70; for (c = 0; c < 128; c++) { - attenuation = 0.0; - if (c & 0x40) { - if (c < 72) attenuation = (c - 72) * -1.5; - } else { - if (c & 0x01) attenuation -= 1.5; - if (c & 0x02) attenuation -= 3.0; - if (c & 0x04) attenuation -= 6.0; - if (c & 0x08) attenuation -= 12.0; - if (c & 0x10) attenuation -= 24.0; - if (c & 0x20) attenuation -= 48.0; - } + attenuation = 0.0; + if (c & 0x40) { + if (c < 72) + attenuation = (c - 72) * -1.5; + } else { + if (c & 0x01) + attenuation -= 1.5; + if (c & 0x02) + attenuation -= 3.0; + if (c & 0x04) + attenuation -= 6.0; + if (c & 0x08) + attenuation -= 12.0; + if (c & 0x10) + attenuation -= 24.0; + if (c & 0x20) + attenuation -= 48.0; + } - attenuation = pow(10, attenuation / 10); + attenuation = pow(10, attenuation / 10); - ad1848_vols_7bits[c] = (int) (attenuation * 65536); + ad1848_vols_7bits[c] = (int) (attenuation * 65536); } for (c = 0; c < 32; c++) { - attenuation = 12.0; - if (c & 0x01) attenuation -= 1.5; - if (c & 0x02) attenuation -= 3.0; - if (c & 0x04) attenuation -= 6.0; - if (c & 0x08) attenuation -= 12.0; - if (c & 0x10) attenuation -= 24.0; + attenuation = 12.0; + if (c & 0x01) + attenuation -= 1.5; + if (c & 0x02) + attenuation -= 3.0; + if (c & 0x04) + attenuation -= 6.0; + if (c & 0x08) + attenuation -= 12.0; + if (c & 0x10) + attenuation -= 24.0; - attenuation = pow(10, attenuation / 10); + attenuation = pow(10, attenuation / 10); - ad1848_vols_5bits_aux_gain[c] = (attenuation * 65536); + ad1848_vols_5bits_aux_gain[c] = (attenuation * 65536); } ad1848->type = type; @@ -555,5 +760,5 @@ ad1848_init(ad1848_t *ad1848, uint8_t type) timer_add(&ad1848->timer_count, ad1848_poll, ad1848, 0); if ((ad1848->type != AD1848_TYPE_DEFAULT) && (ad1848->type != AD1848_TYPE_CS4248)) - sound_set_cd_audio_filter(ad1848_filter_cd_audio, ad1848); + sound_set_cd_audio_filter(ad1848_filter_cd_audio, ad1848); } diff --git a/src/sound/snd_adlib.c b/src/sound/snd_adlib.c index ca6916ad8..5d0d7c7aa 100644 --- a/src/sound/snd_adlib.c +++ b/src/sound/snd_adlib.c @@ -1,147 +1,172 @@ #include #include #include -#include #include +#include #include #define HAVE_STDARG_H -#include <86box/86box.h> -#include <86box/io.h> -#include <86box/timer.h> -#include <86box/mca.h> -#include <86box/device.h> -#include <86box/sound.h> -#include <86box/snd_opl.h> +#include <86box/86box.h> +#include <86box/device.h> +#include <86box/io.h> +#include <86box/mca.h> +#include <86box/sound.h> +#include <86box/timer.h> +#include <86box/snd_opl.h> +#include <86box/plat_unused.h> #ifdef ENABLE_ADLIB_LOG int adlib_do_log = ENABLE_ADLIB_LOG; - static void adlib_log(const char *fmt, ...) { va_list ap; if (adlib_do_log) { - va_start(ap, fmt); - pclog_ex(fmt, ap); - va_end(ap); + va_start(ap, fmt); + pclog_ex(fmt, ap); + va_end(ap); } } #else -#define adlib_log(fmt, ...) +# define adlib_log(fmt, ...) #endif +typedef struct adlib_t { + fm_drv_t opl; -typedef struct adlib_t -{ - opl_t opl; - - uint8_t pos_regs[8]; + uint8_t pos_regs[8]; } adlib_t; - -static void adlib_get_buffer(int32_t *buffer, int len, void *p) +static void +adlib_get_buffer(int32_t *buffer, int len, void *priv) { - adlib_t *adlib = (adlib_t *)p; - int c; + adlib_t *adlib = (adlib_t *) priv; - opl2_update(&adlib->opl); - - for (c = 0; c < len * 2; c++) - buffer[c] += (int32_t)adlib->opl.buffer[c]; + const int32_t *opl_buf = adlib->opl.update(adlib->opl.priv); - adlib->opl.pos = 0; + for (int c = 0; c < len * 2; c++) + buffer[c] += opl_buf[c]; + + adlib->opl.reset_buffer(adlib->opl.priv); } -uint8_t adlib_mca_read(int port, void *p) +uint8_t +adlib_mca_read(int port, void *priv) { - adlib_t *adlib = (adlib_t *)p; - - adlib_log("adlib_mca_read: port=%04x\n", port); - - return adlib->pos_regs[port & 7]; + const adlib_t *adlib = (adlib_t *) priv; + + adlib_log("adlib_mca_read: port=%04x\n", port); + + return adlib->pos_regs[port & 7]; } -void adlib_mca_write(int port, uint8_t val, void *p) +void +adlib_mca_write(int port, uint8_t val, void *priv) { - adlib_t *adlib = (adlib_t *)p; + adlib_t *adlib = (adlib_t *) priv; - if (port < 0x102) - return; - - adlib_log("adlib_mca_write: port=%04x val=%02x\n", port, val); - - switch (port) - { - case 0x102: - if ((adlib->pos_regs[2] & 1) && !(val & 1)) - io_removehandler(0x0388, 0x0002, opl2_read, NULL, NULL, opl2_write, NULL, NULL, &adlib->opl); - if (!(adlib->pos_regs[2] & 1) && (val & 1)) - io_sethandler(0x0388, 0x0002, opl2_read, NULL, NULL, opl2_write, NULL, NULL, &adlib->opl); - break; - } - adlib->pos_regs[port & 7] = val; + if (port < 0x102) + return; + + adlib_log("adlib_mca_write: port=%04x val=%02x\n", port, val); + + switch (port) { + case 0x102: + if ((adlib->pos_regs[2] & 1) && !(val & 1)) + io_removehandler(0x0388, 0x0002, + adlib->opl.read, NULL, NULL, + adlib->opl.write, NULL, NULL, + adlib->opl.priv); + if (!(adlib->pos_regs[2] & 1) && (val & 1)) + io_sethandler(0x0388, 0x0002, + adlib->opl.read, NULL, NULL, + adlib->opl.write, NULL, NULL, + adlib->opl.priv); + break; + + default: + break; + } + adlib->pos_regs[port & 7] = val; } -uint8_t adlib_mca_feedb(void *p) +uint8_t +adlib_mca_feedb(void *priv) { - adlib_t *adlib = (adlib_t *)p; + const adlib_t *adlib = (adlib_t *) priv; - return (adlib->pos_regs[2] & 1); + return (adlib->pos_regs[2] & 1); } - -void *adlib_init(const device_t *info) +void * +adlib_init(UNUSED(const device_t *info)) { - adlib_t *adlib = malloc(sizeof(adlib_t)); - memset(adlib, 0, sizeof(adlib_t)); - - adlib_log("adlib_init\n"); - opl2_init(&adlib->opl); - io_sethandler(0x0388, 0x0002, opl2_read, NULL, NULL, opl2_write, NULL, NULL, &adlib->opl); - sound_add_handler(adlib_get_buffer, adlib); - return adlib; + adlib_t *adlib = malloc(sizeof(adlib_t)); + memset(adlib, 0, sizeof(adlib_t)); + + adlib_log("adlib_init\n"); + fm_driver_get(FM_YM3812, &adlib->opl); + io_sethandler(0x0388, 0x0002, + adlib->opl.read, NULL, NULL, + adlib->opl.write, NULL, NULL, + adlib->opl.priv); + sound_add_handler(adlib_get_buffer, adlib); + return adlib; } -void *adlib_mca_init(const device_t *info) +void * +adlib_mca_init(const device_t *info) { - adlib_t *adlib = adlib_init(info); - - io_removehandler(0x0388, 0x0002, opl2_read, NULL, NULL, opl2_write, NULL, NULL, &adlib->opl); - mca_add(adlib_mca_read, adlib_mca_write, adlib_mca_feedb, NULL, adlib); - adlib->pos_regs[0] = 0xd7; - adlib->pos_regs[1] = 0x70; + adlib_t *adlib = adlib_init(info); - return adlib; + io_removehandler(0x0388, 0x0002, + adlib->opl.read, NULL, NULL, + adlib->opl.write, NULL, NULL, + adlib->opl.priv); + mca_add(adlib_mca_read, + adlib_mca_write, + adlib_mca_feedb, + NULL, + adlib); + adlib->pos_regs[0] = 0xd7; + adlib->pos_regs[1] = 0x70; + + return adlib; } -void adlib_close(void *p) +void +adlib_close(void *priv) { - adlib_t *adlib = (adlib_t *)p; - - free(adlib); + adlib_t *adlib = (adlib_t *) priv; + free(adlib); } -const device_t adlib_device = -{ - "AdLib", - "adlib", - DEVICE_ISA, - 0, - adlib_init, adlib_close, NULL, - { NULL }, NULL, NULL, - NULL +const device_t adlib_device = { + .name = "AdLib", + .internal_name = "adlib", + .flags = DEVICE_ISA, + .local = 0, + .init = adlib_init, + .close = adlib_close, + .reset = NULL, + { .available = NULL }, + .speed_changed = NULL, + .force_redraw = NULL, + .config = NULL }; -const device_t adlib_mca_device = -{ - "AdLib (MCA)", - "adlib_mca", - DEVICE_MCA, - 0, - adlib_init, adlib_close, NULL, - { NULL }, NULL, NULL, - NULL +const device_t adlib_mca_device = { + .name = "AdLib (MCA)", + .internal_name = "adlib_mca", + .flags = DEVICE_MCA, + .local = 0, + .init = adlib_mca_init, + .close = adlib_close, + .reset = NULL, + { .available = NULL }, + .speed_changed = NULL, + .force_redraw = NULL, + .config = NULL }; diff --git a/src/sound/snd_adlibgold.c b/src/sound/snd_adlibgold.c index 1c43adf0c..71cbbcaa6 100644 --- a/src/sound/snd_adlibgold.c +++ b/src/sound/snd_adlibgold.c @@ -1,1036 +1,1167 @@ -#include #include -#include +#include #include +#include #include + #include <86box/86box.h> -#include <86box/io.h> -#include <86box/timer.h> -#include <86box/dma.h> -#include <86box/pic.h> #include <86box/device.h> -#include <86box/gameport.h> -#include <86box/nvr.h> -#include <86box/sound.h> +#include <86box/dma.h> #include <86box/filters.h> +#include <86box/gameport.h> +#include <86box/io.h> #include <86box/midi.h> +#include <86box/timer.h> +#include <86box/nvr.h> +#include <86box/pic.h> +#include <86box/sound.h> #include <86box/snd_opl.h> #include <86box/snd_ym7128.h> +#include <86box/plat_unused.h> +typedef struct adgold_t { + int adgold_irq_status; + int irq; + int dma; -typedef struct adgold_t -{ - int adgold_irq_status; + uint8_t adgold_eeprom[0x1a]; - uint8_t adgold_eeprom[0x1a]; + uint8_t adgold_status; + int adgold_38x_state; + int adgold_38x_addr; + uint8_t adgold_38x_regs[0x1a]; - uint8_t adgold_status; - int adgold_38x_state, adgold_38x_addr; - uint8_t adgold_38x_regs[0x1a]; + int adgold_mma_addr; + uint8_t adgold_mma_regs[2][0xe]; - int adgold_mma_addr; - uint8_t adgold_mma_regs[2][0xe]; + int adgold_mma_enable[2]; + uint8_t adgold_mma_fifo[2][256]; + int adgold_mma_fifo_start[2]; + int adgold_mma_fifo_end[2]; + uint8_t adgold_mma_status; - int adgold_mma_enable[2]; - uint8_t adgold_mma_fifo[2][256]; - int adgold_mma_fifo_start[2], adgold_mma_fifo_end[2]; - uint8_t adgold_mma_status; + int16_t adgold_mma_out[2]; + int adgold_mma_intpos[2]; - int16_t adgold_mma_out[2]; - int adgold_mma_intpos[2]; + pc_timer_t adgold_mma_timer_count; - pc_timer_t adgold_mma_timer_count; + uint8_t adgold_midi_ctrl; + uint8_t midi_queue[16]; + int midi_r; + int midi_w; + int uart_in; + int uart_out; + int sysex; - uint8_t adgold_midi_ctrl, midi_queue[16]; - int midi_r, midi_w; - int uart_in, uart_out, sysex; + struct { + int timer0_latch; + int timer0_count; + int timerbase_latch; + int timerbase_count; + int timer1_latch; + int timer1_count; + int timer2_latch; + int timer2_count; + int timer2_read; - struct - { - int timer0_latch, timer0_count; - int timerbase_latch, timerbase_count; - int timer1_latch, timer1_count; - int timer2_latch, timer2_count, timer2_read; - - int voice_count[2], voice_latch[2]; - } adgold_mma; + int voice_count[2]; + int voice_latch[2]; + } adgold_mma; - opl_t opl; - ym7128_t ym7128; + fm_drv_t opl; + ym7128_t ym7128; - int fm_vol_l, fm_vol_r; - int samp_vol_l, samp_vol_r; - int aux_vol_l, aux_vol_r; - int vol_l, vol_r; - int treble, bass; + int fm_vol_l; + int fm_vol_r; + int samp_vol_l; + int samp_vol_r; + int aux_vol_l; + int aux_vol_r; + int vol_l; + int vol_r; + int treble; + int bass; - int16_t opl_buffer[SOUNDBUFLEN * 2]; - int16_t mma_buffer[2][SOUNDBUFLEN]; + int16_t opl_buffer[SOUNDBUFLEN * 2]; + int16_t mma_buffer[2][SOUNDBUFLEN]; - int pos; + int pos; - int gameport_enabled; + int gameport_enabled; - int surround_enabled; + int surround_enabled; } adgold_t; static int attenuation[0x40]; -static int bass_attenuation[0x10] = -{ - (int)(1.995 * 16384), /*12 dB - filter output is at +6 dB so we use 6 dB here*/ - (int)(1.995 * 16384), - (int)(1.995 * 16384), - (int)(1.413 * 16384), /*9 dB*/ - (int)(1 * 16384), /*6 dB*/ - (int)(0.708 * 16384), /*3 dB*/ - (int)(0 * 16384), /*0 dB*/ - (int)(0.708 * 16384), /*3 dB*/ - (int)(1 * 16384), /*6 dB*/ - (int)(1.413 * 16384), /*9 dB*/ - (int)(1.995 * 16384), /*12 dB*/ - (int)(2.819 * 16384), /*15 dB*/ - (int)(2.819 * 16384), - (int)(2.819 * 16384), - (int)(2.819 * 16384), - (int)(2.819 * 16384) +static int bass_attenuation[0x10] = { + (int) (1.995 * 16384), /*12 dB - filter output is at +6 dB so we use 6 dB here*/ + (int) (1.995 * 16384), + (int) (1.995 * 16384), + (int) (1.413 * 16384), /*9 dB*/ + (int) (1 * 16384), /*6 dB*/ + (int) (0.708 * 16384), /*3 dB*/ + (int) (0 * 16384), /*0 dB*/ + (int) (0.708 * 16384), /*3 dB*/ + (int) (1 * 16384), /*6 dB*/ + (int) (1.413 * 16384), /*9 dB*/ + (int) (1.995 * 16384), /*12 dB*/ + (int) (2.819 * 16384), /*15 dB*/ + (int) (2.819 * 16384), + (int) (2.819 * 16384), + (int) (2.819 * 16384), + (int) (2.819 * 16384) }; -static int bass_cut[6] = -{ - (int)(0.126 * 16384), /*-12 dB*/ - (int)(0.126 * 16384), /*-12 dB*/ - (int)(0.126 * 16384), /*-12 dB*/ - (int)(0.178 * 16384), /*-9 dB*/ - (int)(0.251 * 16384), /*-6 dB*/ - (int)(0.354 * 16384) /*-3 dB - filter output is at +6 dB*/ +static int bass_cut[6] = { + (int) (0.126 * 16384), /*-12 dB*/ + (int) (0.126 * 16384), /*-12 dB*/ + (int) (0.126 * 16384), /*-12 dB*/ + (int) (0.178 * 16384), /*-9 dB*/ + (int) (0.251 * 16384), /*-6 dB*/ + (int) (0.354 * 16384) /*-3 dB - filter output is at +6 dB*/ }; -static int treble_attenuation[0x10] = -{ - (int)(1.995 * 16384), /*12 dB - filter output is at +6 dB so we use 6 dB here*/ - (int)(1.995 * 16384), - (int)(1.995 * 16384), - (int)(1.413 * 16384), /*9 dB*/ - (int)(1 * 16384), /*6 dB*/ - (int)(0.708 * 16384), /*3 dB*/ - (int)(0 * 16384), /*0 dB*/ - (int)(0.708 * 16384), /*3 dB*/ - (int)(1 * 16384), /*6 dB*/ - (int)(1.413 * 16384), /*9 dB*/ - (int)(1.995 * 16384), /*12 dB*/ - (int)(1.995 * 16384), - (int)(1.995 * 16384), - (int)(1.995 * 16384), - (int)(1.995 * 16384), - (int)(1.995 * 16384) +static int treble_attenuation[0x10] = { + (int) (1.995 * 16384), /*12 dB - filter output is at +6 dB so we use 6 dB here*/ + (int) (1.995 * 16384), + (int) (1.995 * 16384), + (int) (1.413 * 16384), /*9 dB*/ + (int) (1 * 16384), /*6 dB*/ + (int) (0.708 * 16384), /*3 dB*/ + (int) (0 * 16384), /*0 dB*/ + (int) (0.708 * 16384), /*3 dB*/ + (int) (1 * 16384), /*6 dB*/ + (int) (1.413 * 16384), /*9 dB*/ + (int) (1.995 * 16384), /*12 dB*/ + (int) (1.995 * 16384), + (int) (1.995 * 16384), + (int) (1.995 * 16384), + (int) (1.995 * 16384), + (int) (1.995 * 16384) }; -static int treble_cut[6] = -{ - (int)(0.126 * 16384), /*-12 dB*/ - (int)(0.126 * 16384), /*-12 dB*/ - (int)(0.126 * 16384), /*-12 dB*/ - (int)(0.178 * 16384), /*-9 dB*/ - (int)(0.251 * 16384), /*-6 dB*/ - (int)(0.354 * 16384) /*-3 dB - filter output is at +6 dB*/ +static int treble_cut[6] = { + (int) (0.126 * 16384), /*-12 dB*/ + (int) (0.126 * 16384), /*-12 dB*/ + (int) (0.126 * 16384), /*-12 dB*/ + (int) (0.178 * 16384), /*-9 dB*/ + (int) (0.251 * 16384), /*-6 dB*/ + (int) (0.354 * 16384) /*-3 dB - filter output is at +6 dB*/ }; -void adgold_timer_poll(); +void adgold_timer_poll(void *priv); void adgold_update(adgold_t *adgold); -void adgold_update_irq_status(adgold_t *adgold) +void +adgold_update_irq_status(adgold_t *adgold) { - uint8_t temp = 0xf; + uint8_t temp = 0xf; - if (!(adgold->adgold_mma_regs[0][8] & 0x10) && (adgold->adgold_mma_status & 0x10)) /*Timer 0*/ - temp &= ~2; - if (!(adgold->adgold_mma_regs[0][8] & 0x20) && (adgold->adgold_mma_status & 0x20)) /*Timer 1*/ - temp &= ~2; - if (!(adgold->adgold_mma_regs[0][8] & 0x40) && (adgold->adgold_mma_status & 0x40)) /*Timer 2*/ - temp &= ~2; - if (!(adgold->adgold_mma_regs[0][0xd] & 0x01) && (adgold->adgold_mma_status & 0x04)) - temp &= ~2; - if (!(adgold->adgold_mma_regs[0][0xd] & 0x04) && (adgold->adgold_mma_status & 0x08)) - temp &= ~2; - if (!(adgold->adgold_mma_regs[0][0xd] & 0x10) && (adgold->adgold_mma_status & 0x80)) - temp &= ~2; - if ((adgold->adgold_mma_status & 0x01) && !(adgold->adgold_mma_regs[0][0xc] & 2)) - temp &= ~2; - if ((adgold->adgold_mma_status & 0x02) && !(adgold->adgold_mma_regs[1][0xc] & 2)) - temp &= ~2; - adgold->adgold_status = temp; - - if ((adgold->adgold_status ^ 0xf) && !adgold->adgold_irq_status) - { - picint(0x80); - } - - adgold->adgold_irq_status = adgold->adgold_status ^ 0xf; + if (!(adgold->adgold_mma_regs[0][8] & 0x10) && (adgold->adgold_mma_status & 0x10)) /*Timer 0*/ + temp &= ~2; + if (!(adgold->adgold_mma_regs[0][8] & 0x20) && (adgold->adgold_mma_status & 0x20)) /*Timer 1*/ + temp &= ~2; + if (!(adgold->adgold_mma_regs[0][8] & 0x40) && (adgold->adgold_mma_status & 0x40)) /*Timer 2*/ + temp &= ~2; + if (!(adgold->adgold_mma_regs[0][0xd] & 0x01) && (adgold->adgold_mma_status & 0x04)) + temp &= ~2; + if (!(adgold->adgold_mma_regs[0][0xd] & 0x04) && (adgold->adgold_mma_status & 0x08)) + temp &= ~2; + if (!(adgold->adgold_mma_regs[0][0xd] & 0x10) && (adgold->adgold_mma_status & 0x80)) + temp &= ~2; + if ((adgold->adgold_mma_status & 0x01) && !(adgold->adgold_mma_regs[0][0xc] & 2)) + temp &= ~2; + if ((adgold->adgold_mma_status & 0x02) && !(adgold->adgold_mma_regs[1][0xc] & 2)) + temp &= ~2; + adgold->adgold_status = temp; + + if ((adgold->adgold_status ^ 0xf) && !adgold->adgold_irq_status) { + picint(1 << adgold->irq); + } + + adgold->adgold_irq_status = adgold->adgold_status ^ 0xf; } -void adgold_getsamp_dma(adgold_t *adgold, int channel) +int +adgold_getsamp_dma(adgold_t *adgold, int channel) { - int temp; + int temp; + dma_set_drq(adgold->dma, 1); - if ((adgold->adgold_mma_regs[channel][0xc] & 0x60) && (((adgold->adgold_mma_fifo_end[channel] - adgold->adgold_mma_fifo_start[channel]) & 255) >= 127)) - return; + if ((adgold->adgold_mma_regs[channel][0xc] & 0x60) && (((adgold->adgold_mma_fifo_end[channel] - adgold->adgold_mma_fifo_start[channel]) & 255) >= 127)) + return 2; - temp = dma_channel_read(1); - if (temp == DMA_NODATA) return; + temp = dma_channel_read(adgold->dma); + if (temp == DMA_NODATA) { + return 1; + } + adgold->adgold_mma_fifo[channel][adgold->adgold_mma_fifo_end[channel]] = temp; + adgold->adgold_mma_fifo_end[channel] = (adgold->adgold_mma_fifo_end[channel] + 1) & 255; + if (adgold->adgold_mma_regs[channel][0xc] & 0x60) { + temp = dma_channel_read(adgold->dma); adgold->adgold_mma_fifo[channel][adgold->adgold_mma_fifo_end[channel]] = temp; - adgold->adgold_mma_fifo_end[channel] = (adgold->adgold_mma_fifo_end[channel] + 1) & 255; - if (adgold->adgold_mma_regs[channel][0xc] & 0x60) - { - temp = dma_channel_read(1); - adgold->adgold_mma_fifo[channel][adgold->adgold_mma_fifo_end[channel]] = temp; - adgold->adgold_mma_fifo_end[channel] = (adgold->adgold_mma_fifo_end[channel] + 1) & 255; - } - if (((adgold->adgold_mma_fifo_end[channel] - adgold->adgold_mma_fifo_start[channel]) & 255) >= adgold->adgold_mma_intpos[channel]) - { - adgold->adgold_mma_status &= ~(0x01 << channel); - adgold_update_irq_status(adgold); - } + adgold->adgold_mma_fifo_end[channel] = (adgold->adgold_mma_fifo_end[channel] + 1) & 255; + } + if (((adgold->adgold_mma_fifo_end[channel] - adgold->adgold_mma_fifo_start[channel]) & 255) >= adgold->adgold_mma_intpos[channel]) { + adgold->adgold_mma_status &= ~(0x01 << channel); + adgold_update_irq_status(adgold); + dma_set_drq(adgold->dma, 0); + } + + return 0; } -void adgold_write(uint16_t addr, uint8_t val, void *p) +void +adgold_write(uint16_t addr, uint8_t val, void *priv) { - adgold_t *adgold = (adgold_t *)p; - switch (addr & 7) - { - case 0: case 1: - opl3_write(addr, val, &adgold->opl); - break; + adgold_t *adgold = (adgold_t *) priv; + switch (addr & 7) { + case 0: + case 1: + adgold->opl.write(addr, val, adgold->opl.priv); + break; - case 2: - if (val == 0xff) - { - adgold->adgold_38x_state = 1; - return; - } - if (val == 0xfe) - { - adgold->adgold_38x_state = 0; - return; - } - if (adgold->adgold_38x_state) /*Write to control chip*/ - adgold->adgold_38x_addr = val; - else - opl3_write(addr, val, &adgold->opl); - break; - case 3: - if (adgold->adgold_38x_state) - { - if (adgold->adgold_38x_addr >= 0x19) break; - switch (adgold->adgold_38x_addr) - { - case 0x00: /*Control/ID*/ - if (val & 1) - memcpy(adgold->adgold_38x_regs, adgold->adgold_eeprom, 0x1a); - if (val & 2) - memcpy(adgold->adgold_eeprom, adgold->adgold_38x_regs, 0x1a); - break; - - case 0x04: /*Final output volume left*/ - adgold->adgold_38x_regs[0x04] = val; - adgold->vol_l = attenuation[val & 0x3f]; - break; - case 0x05: /*Final output volume right*/ - adgold->adgold_38x_regs[0x05] = val; - adgold->vol_r = attenuation[val & 0x3f]; - break; - case 0x06: /*Bass*/ - adgold->adgold_38x_regs[0x06] = val; - adgold->bass = val & 0xf; - break; - case 0x07: /*Treble*/ - adgold->adgold_38x_regs[0x07] = val; - adgold->treble = val & 0xf; - break; - - case 0x09: /*FM volume left*/ - adgold->adgold_38x_regs[0x09] = val; - adgold->fm_vol_l = (int)(int8_t)(val - 128); - break; - case 0x0a: /*FM volume right*/ - adgold->adgold_38x_regs[0x0a] = val; - adgold->fm_vol_r = (int)(int8_t)(val - 128); - break; - case 0x0b: /*Sample volume left*/ - adgold->adgold_38x_regs[0x0b] = val; - adgold->samp_vol_l = (int)(int8_t)(val - 128); - break; - case 0x0c: /*Sample volume right*/ - adgold->adgold_38x_regs[0x0c] = val; - adgold->samp_vol_r = (int)(int8_t)(val - 128); - break; - case 0x0d: /*Aux volume left*/ - adgold->adgold_38x_regs[0x0d] = val; - adgold->aux_vol_l = (int)(int8_t)(val - 128); - break; - case 0x0e: /*Aux volume right*/ - adgold->adgold_38x_regs[0x0e] = val; - adgold->aux_vol_r = (int)(int8_t)(val - 128); - break; - - case 0x18: /*Surround*/ - adgold->adgold_38x_regs[0x18] = val; - ym7128_write(&adgold->ym7128, val); - break; - - default: - adgold->adgold_38x_regs[adgold->adgold_38x_addr] = val; - break; - } - } - else - opl3_write(addr, val, &adgold->opl); - break; - case 4: case 6: - adgold->adgold_mma_addr = val; - break; - case 5: - if (adgold->adgold_mma_addr >= 0xf) break; - switch (adgold->adgold_mma_addr) - { - case 0x2: - adgold->adgold_mma.timer0_latch = (adgold->adgold_mma.timer0_latch & 0xff00) | val; - break; - case 0x3: - adgold->adgold_mma.timer0_latch = (adgold->adgold_mma.timer0_latch & 0xff) | (val << 8); - break; - case 0x4: - adgold->adgold_mma.timerbase_latch = (adgold->adgold_mma.timerbase_latch & 0xf00) | val; - break; - case 0x5: - adgold->adgold_mma.timerbase_latch = (adgold->adgold_mma.timerbase_latch & 0xff) | ((val & 0xf) << 8); - adgold->adgold_mma.timer1_latch = val >> 4; - break; - case 0x6: - adgold->adgold_mma.timer2_latch = (adgold->adgold_mma.timer2_latch & 0xff00) | val; - break; - case 0x7: - adgold->adgold_mma.timer2_latch = (adgold->adgold_mma.timer2_latch & 0xff) | (val << 8); + case 2: + if (val == 0xff) { + adgold->adgold_38x_state = 1; + return; + } + if (val == 0xfe) { + adgold->adgold_38x_state = 0; + return; + } + if (adgold->adgold_38x_state) /*Write to control chip*/ + adgold->adgold_38x_addr = val; + else + adgold->opl.write(addr, val, adgold->opl.priv); + break; + case 3: + if (adgold->adgold_38x_state) { + if (adgold->adgold_38x_addr >= 0x19) + break; + switch (adgold->adgold_38x_addr) { + case 0x00: /*Control/ID*/ + if (val & 1) + memcpy(adgold->adgold_38x_regs, adgold->adgold_eeprom, 0x1a); + if (val & 2) + memcpy(adgold->adgold_eeprom, adgold->adgold_38x_regs, 0x1a); break; - case 0x8: - if ((val & 1) && !(adgold->adgold_mma_regs[0][8] & 1)) /*Reload timer 0*/ - adgold->adgold_mma.timer0_count = adgold->adgold_mma.timer0_latch; - - if ((val & 2) && !(adgold->adgold_mma_regs[0][8] & 2)) /*Reload timer 1*/ - adgold->adgold_mma.timer1_count = adgold->adgold_mma.timer1_latch; - - if ((val & 4) && !(adgold->adgold_mma_regs[0][8] & 4)) /*Reload timer 2*/ - adgold->adgold_mma.timer2_count = adgold->adgold_mma.timer2_latch; - - if ((val & 8) && !(adgold->adgold_mma_regs[0][8] & 8)) /*Reload base timer*/ - adgold->adgold_mma.timerbase_count = adgold->adgold_mma.timerbase_latch; + case 0x04: /*Final output volume left*/ + adgold->adgold_38x_regs[0x04] = val; + adgold->vol_l = attenuation[val & 0x3f]; + break; + case 0x05: /*Final output volume right*/ + adgold->adgold_38x_regs[0x05] = val; + adgold->vol_r = attenuation[val & 0x3f]; + break; + case 0x06: /*Bass*/ + adgold->adgold_38x_regs[0x06] = val; + adgold->bass = val & 0xf; + break; + case 0x07: /*Treble*/ + adgold->adgold_38x_regs[0x07] = val; + adgold->treble = val & 0xf; break; - case 0x9: - switch (val & 0x18) - { - case 0x00: adgold->adgold_mma.voice_latch[0] = 12; break; /*44100 Hz*/ - case 0x08: adgold->adgold_mma.voice_latch[0] = 24; break; /*22050 Hz*/ - case 0x10: adgold->adgold_mma.voice_latch[0] = 48; break; /*11025 Hz*/ - case 0x18: adgold->adgold_mma.voice_latch[0] = 72; break; /* 7350 Hz*/ - } - if (val & 0x80) - { - adgold->adgold_mma_enable[0] = 0; - adgold->adgold_mma_fifo_end[0] = adgold->adgold_mma_fifo_start[0] = 0; - adgold->adgold_mma_status &= ~0x01; - adgold_update_irq_status(adgold); - } - if ((val & 0x01)) /*Start playback*/ - { - if (!(adgold->adgold_mma_regs[0][0x9] & 1)) - adgold->adgold_mma.voice_count[0] = adgold->adgold_mma.voice_latch[0]; - - if (adgold->adgold_mma_regs[0][0xc] & 1) - { - if (adgold->adgold_mma_regs[0][0xc] & 0x80) - { - adgold->adgold_mma_enable[1] = 1; - adgold->adgold_mma.voice_count[1] = adgold->adgold_mma.voice_latch[1]; - - while (((adgold->adgold_mma_fifo_end[0] - adgold->adgold_mma_fifo_start[0]) & 255) < 128) - { - adgold_getsamp_dma(adgold, 0); - adgold_getsamp_dma(adgold, 1); - } - if (((adgold->adgold_mma_fifo_end[0] - adgold->adgold_mma_fifo_start[0]) & 255) >= adgold->adgold_mma_intpos[0]) - { - adgold->adgold_mma_status &= ~0x01; - adgold_update_irq_status(adgold); - } - if (((adgold->adgold_mma_fifo_end[1] - adgold->adgold_mma_fifo_start[1]) & 255) >= adgold->adgold_mma_intpos[1]) - { - adgold->adgold_mma_status &= ~0x02; - adgold_update_irq_status(adgold); - } - } - else - { - while (((adgold->adgold_mma_fifo_end[0] - adgold->adgold_mma_fifo_start[0]) & 255) < 128) - { - adgold_getsamp_dma(adgold, 0); - } - if (((adgold->adgold_mma_fifo_end[0] - adgold->adgold_mma_fifo_start[0]) & 255) >= adgold->adgold_mma_intpos[0]) - { - adgold->adgold_mma_status &= ~0x01; - adgold_update_irq_status(adgold); - } - } - } - } - adgold->adgold_mma_enable[0] = val & 0x01; + case 0x09: /*FM volume left*/ + adgold->adgold_38x_regs[0x09] = val; + adgold->fm_vol_l = (int) (int8_t) (val - 128); + break; + case 0x0a: /*FM volume right*/ + adgold->adgold_38x_regs[0x0a] = val; + adgold->fm_vol_r = (int) (int8_t) (val - 128); + break; + case 0x0b: /*Sample volume left*/ + adgold->adgold_38x_regs[0x0b] = val; + adgold->samp_vol_l = (int) (int8_t) (val - 128); + break; + case 0x0c: /*Sample volume right*/ + adgold->adgold_38x_regs[0x0c] = val; + adgold->samp_vol_r = (int) (int8_t) (val - 128); + break; + case 0x0d: /*Aux volume left*/ + adgold->adgold_38x_regs[0x0d] = val; + adgold->aux_vol_l = (int) (int8_t) (val - 128); + break; + case 0x0e: /*Aux volume right*/ + adgold->adgold_38x_regs[0x0e] = val; + adgold->aux_vol_r = (int) (int8_t) (val - 128); break; - case 0xb: - if (((adgold->adgold_mma_fifo_end[0] - adgold->adgold_mma_fifo_start[0]) & 255) < 128) - { - adgold->adgold_mma_fifo[0][adgold->adgold_mma_fifo_end[0]] = val; - adgold->adgold_mma_fifo_end[0] = (adgold->adgold_mma_fifo_end[0] + 1) & 255; - if (((adgold->adgold_mma_fifo_end[0] - adgold->adgold_mma_fifo_start[0]) & 255) >= adgold->adgold_mma_intpos[0]) - { - adgold->adgold_mma_status &= ~0x01; - adgold_update_irq_status(adgold); - } - } + case 0x18: /*Surround*/ + adgold->adgold_38x_regs[0x18] = val; + ym7128_write(&adgold->ym7128, val); break; - case 0xc: - adgold->adgold_mma_intpos[0] = (7 - ((val >> 2) & 7)) * 8; - break; - - case 0xd: - adgold->adgold_midi_ctrl = val & 0x3f; - - if ((adgold->adgold_midi_ctrl & 0x0f) != 0x0f) { - if ((adgold->adgold_midi_ctrl & 0x0f) == 0x00) { - adgold->uart_out = 0; - adgold->uart_in = 0; - adgold->midi_w = 0; - adgold->midi_r = 0; - adgold->adgold_mma_status &= ~0x8c; - } else { - if (adgold->adgold_midi_ctrl & 0x01) - adgold->uart_in = 1; - if (adgold->adgold_midi_ctrl & 0x04) - adgold->uart_out = 1; - if (adgold->adgold_midi_ctrl & 0x02) { - adgold->uart_in = 0; - adgold->midi_w = 0; - adgold->midi_r = 0; - } - if (adgold->adgold_midi_ctrl & 0x08) - adgold->uart_out = 0; - adgold->adgold_mma_status &= ~0x80; - } - } else - adgold->adgold_mma_status &= ~0x8c; - - adgold_update_irq_status(adgold); - break; - - case 0xe: - if (adgold->uart_out) { - midi_raw_out_byte(val); - - adgold->adgold_mma_status &= ~0x08; - adgold_update_irq_status(adgold); - } - break; - } - adgold->adgold_mma_regs[0][adgold->adgold_mma_addr] = val; - break; - case 7: - if (adgold->adgold_mma_addr >= 0xe) break; - switch (adgold->adgold_mma_addr) - { - case 0x9: - adgold_update(adgold); - switch (val & 0x18) - { - case 0x00: adgold->adgold_mma.voice_latch[1] = 12; break; /*44100 Hz*/ - case 0x08: adgold->adgold_mma.voice_latch[1] = 24; break; /*22050 Hz*/ - case 0x10: adgold->adgold_mma.voice_latch[1] = 48; break; /*11025 Hz*/ - case 0x18: adgold->adgold_mma.voice_latch[1] = 72; break; /* 7350 Hz*/ - } - if (val & 0x80) - { - adgold->adgold_mma_enable[1] = 0; - adgold->adgold_mma_fifo_end[1] = adgold->adgold_mma_fifo_start[1] = 0; - adgold->adgold_mma_status &= ~0x02; - adgold_update_irq_status(adgold); - } - if ((val & 0x01)) /*Start playback*/ - { - if (!(adgold->adgold_mma_regs[1][0x9] & 1)) - adgold->adgold_mma.voice_count[1] = adgold->adgold_mma.voice_latch[1]; - - if (adgold->adgold_mma_regs[1][0xc] & 1) - { - while (((adgold->adgold_mma_fifo_end[1] - adgold->adgold_mma_fifo_start[1]) & 255) < 128) - { - adgold_getsamp_dma(adgold, 1); - } - } - } - adgold->adgold_mma_enable[1] = val & 0x01; - break; - - case 0xb: - if (((adgold->adgold_mma_fifo_end[1] - adgold->adgold_mma_fifo_start[1]) & 255) < 128) - { - adgold->adgold_mma_fifo[1][adgold->adgold_mma_fifo_end[1]] = val; - adgold->adgold_mma_fifo_end[1] = (adgold->adgold_mma_fifo_end[1] + 1) & 255; - if (((adgold->adgold_mma_fifo_end[1] - adgold->adgold_mma_fifo_start[1]) & 255) >= adgold->adgold_mma_intpos[1]) - { - adgold->adgold_mma_status &= ~0x02; - adgold_update_irq_status(adgold); - } - } - break; - - case 0xc: - adgold->adgold_mma_intpos[1] = (7 - ((val >> 2) & 7)) * 8; + default: + adgold->adgold_38x_regs[adgold->adgold_38x_addr] = val; break; } - adgold->adgold_mma_regs[1][adgold->adgold_mma_addr] = val; + } else + adgold->opl.write(addr, val, adgold->opl.priv); + break; + case 4: + case 6: + adgold->adgold_mma_addr = val; + break; + case 5: + if (adgold->adgold_mma_addr >= 0xf) break; - } -} + switch (adgold->adgold_mma_addr) { + case 0x2: + adgold->adgold_mma.timer0_latch = (adgold->adgold_mma.timer0_latch & 0xff00) | val; + break; + case 0x3: + adgold->adgold_mma.timer0_latch = (adgold->adgold_mma.timer0_latch & 0xff) | (val << 8); + break; + case 0x4: + adgold->adgold_mma.timerbase_latch = (adgold->adgold_mma.timerbase_latch & 0xf00) | val; + break; + case 0x5: + adgold->adgold_mma.timerbase_latch = (adgold->adgold_mma.timerbase_latch & 0xff) | ((val & 0xf) << 8); + adgold->adgold_mma.timer1_latch = val >> 4; + break; + case 0x6: + adgold->adgold_mma.timer2_latch = (adgold->adgold_mma.timer2_latch & 0xff00) | val; + break; + case 0x7: + adgold->adgold_mma.timer2_latch = (adgold->adgold_mma.timer2_latch & 0xff) | (val << 8); + break; -uint8_t adgold_read(uint16_t addr, void *p) -{ - adgold_t *adgold = (adgold_t *)p; - uint8_t temp = 0; + case 0x8: + if ((val & 1) && !(adgold->adgold_mma_regs[0][8] & 1)) /*Reload timer 0*/ + adgold->adgold_mma.timer0_count = adgold->adgold_mma.timer0_latch; - switch (addr & 7) - { - case 0: case 1: - temp = opl3_read(addr, &adgold->opl); - break; - - case 2: - if (adgold->adgold_38x_state) /*Read from control chip*/ - temp = adgold->adgold_status; - else - temp = opl3_read(addr, &adgold->opl); - break; + if ((val & 2) && !(adgold->adgold_mma_regs[0][8] & 2)) /*Reload timer 1*/ + adgold->adgold_mma.timer1_count = adgold->adgold_mma.timer1_latch; - case 3: - if (adgold->adgold_38x_state) - { - if (adgold->adgold_38x_addr >= 0x19) temp = 0xff; - switch (adgold->adgold_38x_addr) - { - case 0x00: /*Control/ID*/ - if (adgold->surround_enabled) - temp = 0x51; /*8-bit ISA, surround module, no telephone/CD-ROM*/ - else - temp = 0x71; /*8-bit ISA, no telephone/surround/CD-ROM*/ - break; - - default: - temp = adgold->adgold_38x_regs[adgold->adgold_38x_addr]; - } - } - else - temp = opl3_read(addr, &adgold->opl); - break; + if ((val & 4) && !(adgold->adgold_mma_regs[0][8] & 4)) /*Reload timer 2*/ + adgold->adgold_mma.timer2_count = adgold->adgold_mma.timer2_latch; + + if ((val & 8) && !(adgold->adgold_mma_regs[0][8] & 8)) /*Reload base timer*/ + adgold->adgold_mma.timerbase_count = adgold->adgold_mma.timerbase_latch; + break; + + case 0x9: + switch (val & 0x18) { + case 0x00: + adgold->adgold_mma.voice_latch[0] = 12; + break; /*44100 Hz*/ + case 0x08: + adgold->adgold_mma.voice_latch[0] = 24; + break; /*22050 Hz*/ + case 0x10: + adgold->adgold_mma.voice_latch[0] = 48; + break; /*11025 Hz*/ + case 0x18: + adgold->adgold_mma.voice_latch[0] = 72; + break; /* 7350 Hz*/ - case 4: case 6: - temp = adgold->adgold_mma_status; - adgold->adgold_mma_status &= ~0xf3; /*JUKEGOLD expects timer status flags to auto-clear*/ - adgold_update_irq_status(adgold); - break; - case 5: - if (adgold->adgold_mma_addr >= 0xf) temp = 0xff; - switch (adgold->adgold_mma_addr) - { - case 6: /*Timer 2 low*/ - adgold->adgold_mma.timer2_read = adgold->adgold_mma.timer2_count; - adgold->adgold_mma_status |= 0x40; - temp = adgold->adgold_mma.timer2_read & 0xff; - break; - case 7: /*Timer 2 high*/ - temp = adgold->adgold_mma.timer2_read >> 8; - break; - - case 0xe: - temp = 0; - if (adgold->uart_in) { - temp = adgold->midi_queue[adgold->midi_r]; - if (adgold->midi_r != adgold->midi_w) { - adgold->midi_r++; - adgold->midi_r &= 0x0f; - } - adgold->adgold_mma_status &= ~0x04; - adgold_update_irq_status(adgold); - } - break; - default: - temp = adgold->adgold_mma_regs[0][adgold->adgold_mma_addr]; - break; - } - break; - case 7: - if (adgold->adgold_mma_addr >= 0xf) - temp = 0xff; - else - temp = adgold->adgold_mma_regs[1][adgold->adgold_mma_addr]; - break; - } - return temp; -} - -void adgold_update(adgold_t *adgold) -{ - for (; adgold->pos < sound_pos_global; adgold->pos++) - { - adgold->mma_buffer[0][adgold->pos] = adgold->mma_buffer[1][adgold->pos] = 0; - - if (adgold->adgold_mma_regs[0][9] & 0x20) - adgold->mma_buffer[0][adgold->pos] += adgold->adgold_mma_out[0] / 2; - if (adgold->adgold_mma_regs[0][9] & 0x40) - adgold->mma_buffer[1][adgold->pos] += adgold->adgold_mma_out[0] / 2; - - if (adgold->adgold_mma_regs[1][9] & 0x20) - adgold->mma_buffer[0][adgold->pos] += adgold->adgold_mma_out[1] / 2; - if (adgold->adgold_mma_regs[1][9] & 0x40) - adgold->mma_buffer[1][adgold->pos] += adgold->adgold_mma_out[1] / 2; - } -} - -void adgold_mma_poll(adgold_t *adgold, int channel) -{ - int16_t dat; - - adgold_update(adgold); - - if (adgold->adgold_mma_fifo_start[channel] != adgold->adgold_mma_fifo_end[channel]) - { - switch (adgold->adgold_mma_regs[channel][0xc] & 0x60) - { - case 0x00: /*8-bit*/ - dat = adgold->adgold_mma_fifo[channel][adgold->adgold_mma_fifo_start[channel]] * 256; - adgold->adgold_mma_out[channel] = dat; - adgold->adgold_mma_fifo_start[channel] = (adgold->adgold_mma_fifo_start[channel] + 1) & 255; - break; - - case 0x40: /*12-bit sensible format*/ - if (((adgold->adgold_mma_fifo_end[channel] - adgold->adgold_mma_fifo_start[channel]) & 255) < 2) - return; - - dat = adgold->adgold_mma_fifo[channel][adgold->adgold_mma_fifo_start[channel]] & 0xf0; - adgold->adgold_mma_fifo_start[channel] = (adgold->adgold_mma_fifo_start[channel] + 1) & 255; - dat |= (adgold->adgold_mma_fifo[channel][adgold->adgold_mma_fifo_start[channel]] << 8); - adgold->adgold_mma_fifo_start[channel] = (adgold->adgold_mma_fifo_start[channel] + 1) & 255; - adgold->adgold_mma_out[channel] = dat; - break; - } - - if (adgold->adgold_mma_regs[channel][0xc] & 1) - { - adgold_getsamp_dma(adgold, channel); - } - if (((adgold->adgold_mma_fifo_end[channel] - adgold->adgold_mma_fifo_start[channel]) & 255) < adgold->adgold_mma_intpos[channel] && !(adgold->adgold_mma_status & 0x01)) - { - adgold->adgold_mma_status |= 1 << channel; + break; + } + if (val & 0x80) { + adgold->adgold_mma_enable[0] = 0; + adgold->adgold_mma_fifo_end[0] = adgold->adgold_mma_fifo_start[0] = 0; + adgold->adgold_mma_status &= ~0x01; adgold_update_irq_status(adgold); - } - } - if (adgold->adgold_mma_fifo_start[channel] == adgold->adgold_mma_fifo_end[channel]) - { - adgold->adgold_mma_enable[channel] = 0; - } + dma_set_drq(adgold->dma, 0); + } + if (val & 0x01) /*Start playback*/ + { + if (!(adgold->adgold_mma_regs[0][0x9] & 1)) + adgold->adgold_mma.voice_count[0] = adgold->adgold_mma.voice_latch[0]; + + if (adgold->adgold_mma_regs[0][0xc] & 1) { + if (adgold->adgold_mma_regs[0][0xc] & 0x80) { + adgold->adgold_mma_enable[1] = 1; + adgold->adgold_mma.voice_count[1] = adgold->adgold_mma.voice_latch[1]; + + while (((adgold->adgold_mma_fifo_end[0] - adgold->adgold_mma_fifo_start[0]) & 255) < 128) { + if (adgold_getsamp_dma(adgold, 0)) { + adgold->adgold_mma_fifo_end[0] = 0; + adgold->adgold_mma_fifo_start[0] = 0; + break; + } + if (adgold_getsamp_dma(adgold, 1)) { + adgold->adgold_mma_fifo_end[1] = 0; + adgold->adgold_mma_fifo_start[1] = 0; + break; + } + } + if (((adgold->adgold_mma_fifo_end[0] - adgold->adgold_mma_fifo_start[0]) & 255) >= adgold->adgold_mma_intpos[0]) { + adgold->adgold_mma_status &= ~0x01; + adgold_update_irq_status(adgold); + dma_set_drq(adgold->dma, 0); + } + if (((adgold->adgold_mma_fifo_end[1] - adgold->adgold_mma_fifo_start[1]) & 255) >= adgold->adgold_mma_intpos[1]) { + adgold->adgold_mma_status &= ~0x02; + adgold_update_irq_status(adgold); + dma_set_drq(adgold->dma, 0); + } + } else { + while (((adgold->adgold_mma_fifo_end[0] - adgold->adgold_mma_fifo_start[0]) & 255) < 128) { + if (adgold_getsamp_dma(adgold, 0)) { + adgold->adgold_mma_fifo_end[0] = 0; + adgold->adgold_mma_fifo_start[0] = 0; + break; + } + } + if (((adgold->adgold_mma_fifo_end[0] - adgold->adgold_mma_fifo_start[0]) & 255) >= adgold->adgold_mma_intpos[0]) { + adgold->adgold_mma_status &= ~0x01; + adgold_update_irq_status(adgold); + dma_set_drq(adgold->dma, 0); + } + } + } + } + adgold->adgold_mma_enable[0] = val & 0x01; + break; + + case 0xb: + if (((adgold->adgold_mma_fifo_end[0] - adgold->adgold_mma_fifo_start[0]) & 255) < 128) { + adgold->adgold_mma_fifo[0][adgold->adgold_mma_fifo_end[0]] = val; + adgold->adgold_mma_fifo_end[0] = (adgold->adgold_mma_fifo_end[0] + 1) & 255; + if (((adgold->adgold_mma_fifo_end[0] - adgold->adgold_mma_fifo_start[0]) & 255) >= adgold->adgold_mma_intpos[0]) { + adgold->adgold_mma_status &= ~0x01; + adgold_update_irq_status(adgold); + dma_set_drq(adgold->dma, 0); + } + } + break; + + case 0xc: + adgold->adgold_mma_intpos[0] = (7 - ((val >> 2) & 7)) * 8; + break; + + case 0xd: + adgold->adgold_midi_ctrl = val & 0x3f; + + if ((adgold->adgold_midi_ctrl & 0x0f) != 0x0f) { + if ((adgold->adgold_midi_ctrl & 0x0f) == 0x00) { + adgold->uart_out = 0; + adgold->uart_in = 0; + adgold->midi_w = 0; + adgold->midi_r = 0; + adgold->adgold_mma_status &= ~0x8c; + } else { + if (adgold->adgold_midi_ctrl & 0x01) + adgold->uart_in = 1; + if (adgold->adgold_midi_ctrl & 0x04) + adgold->uart_out = 1; + if (adgold->adgold_midi_ctrl & 0x02) { + adgold->uart_in = 0; + adgold->midi_w = 0; + adgold->midi_r = 0; + } + if (adgold->adgold_midi_ctrl & 0x08) + adgold->uart_out = 0; + adgold->adgold_mma_status &= ~0x80; + } + } else + adgold->adgold_mma_status &= ~0x8c; + + adgold_update_irq_status(adgold); + break; + + case 0xe: + if (adgold->uart_out) { + midi_raw_out_byte(val); + + adgold->adgold_mma_status &= ~0x08; + adgold_update_irq_status(adgold); + } + break; + + default: + break; + } + adgold->adgold_mma_regs[0][adgold->adgold_mma_addr] = val; + break; + case 7: + if (adgold->adgold_mma_addr >= 0xe) + break; + switch (adgold->adgold_mma_addr) { + case 0x9: + adgold_update(adgold); + switch (val & 0x18) { + case 0x00: + adgold->adgold_mma.voice_latch[1] = 12; + break; /*44100 Hz*/ + case 0x08: + adgold->adgold_mma.voice_latch[1] = 24; + break; /*22050 Hz*/ + case 0x10: + adgold->adgold_mma.voice_latch[1] = 48; + break; /*11025 Hz*/ + case 0x18: + adgold->adgold_mma.voice_latch[1] = 72; + break; /* 7350 Hz*/ + + default: + break; + } + if (val & 0x80) { + adgold->adgold_mma_enable[1] = 0; + adgold->adgold_mma_fifo_end[1] = adgold->adgold_mma_fifo_start[1] = 0; + adgold->adgold_mma_status &= ~0x02; + adgold_update_irq_status(adgold); + dma_set_drq(adgold->dma, 0); + } + if (val & 0x01) /*Start playback*/ + { + if (!(adgold->adgold_mma_regs[1][0x9] & 1)) + adgold->adgold_mma.voice_count[1] = adgold->adgold_mma.voice_latch[1]; + + if (adgold->adgold_mma_regs[1][0xc] & 1) { + while (((adgold->adgold_mma_fifo_end[1] - adgold->adgold_mma_fifo_start[1]) & 255) < 128) { + if (adgold_getsamp_dma(adgold, 1)) { + adgold->adgold_mma_fifo_end[1] = 0; + adgold->adgold_mma_fifo_start[1] = 0; + break; + } + } + } + } + adgold->adgold_mma_enable[1] = val & 0x01; + break; + + case 0xb: + if (((adgold->adgold_mma_fifo_end[1] - adgold->adgold_mma_fifo_start[1]) & 255) < 128) { + adgold->adgold_mma_fifo[1][adgold->adgold_mma_fifo_end[1]] = val; + adgold->adgold_mma_fifo_end[1] = (adgold->adgold_mma_fifo_end[1] + 1) & 255; + if (((adgold->adgold_mma_fifo_end[1] - adgold->adgold_mma_fifo_start[1]) & 255) >= adgold->adgold_mma_intpos[1]) { + adgold->adgold_mma_status &= ~0x02; + adgold_update_irq_status(adgold); + dma_set_drq(adgold->dma, 0); + } + } + break; + + case 0xc: + adgold->adgold_mma_intpos[1] = (7 - ((val >> 2) & 7)) * 8; + break; + + default: + break; + } + adgold->adgold_mma_regs[1][adgold->adgold_mma_addr] = val; + break; + + default: + break; + } } -void adgold_timer_poll(void *p) +uint8_t +adgold_read(uint16_t addr, void *priv) { - adgold_t *adgold = (adgold_t *)p; + adgold_t *adgold = (adgold_t *) priv; + uint8_t temp = 0; - timer_advance_u64(&adgold->adgold_mma_timer_count, (uint64_t)((double)TIMER_USEC * 1.88964)); + switch (addr & 7) { + case 0: + case 1: + temp = adgold->opl.read(addr, adgold->opl.priv); + break; - if (adgold->adgold_midi_ctrl & 0x3f) { - if ((adgold->adgold_midi_ctrl & 0x3f) != 0x3f) { - if (adgold->uart_out) - adgold->adgold_mma_status |= 0x08; - if (adgold->adgold_midi_ctrl & 0x10) - adgold->adgold_mma_status |= 0x80; - } - adgold_update_irq_status(adgold); - } - - if (adgold->adgold_mma_regs[0][8] & 0x01) /*Timer 0*/ - { - adgold->adgold_mma.timer0_count--; - if (!adgold->adgold_mma.timer0_count) - { - adgold->adgold_mma.timer0_count = adgold->adgold_mma.timer0_latch; - adgold->adgold_mma_status |= 0x10; - adgold_update_irq_status(adgold); - } - } - if (adgold->adgold_mma_regs[0][8] & 0x08) /*Base timer*/ - { - adgold->adgold_mma.timerbase_count--; - if (!adgold->adgold_mma.timerbase_count) - { - adgold->adgold_mma.timerbase_count = adgold->adgold_mma.timerbase_latch; - if (adgold->adgold_mma_regs[0][8] & 0x02) /*Timer 1*/ - { - adgold->adgold_mma.timer1_count--; - if (!adgold->adgold_mma.timer1_count) - { - adgold->adgold_mma.timer1_count = adgold->adgold_mma.timer1_latch; - adgold->adgold_mma_status |= 0x20; - adgold_update_irq_status(adgold); - } - } - if (adgold->adgold_mma_regs[0][8] & 0x04) /*Timer 2*/ - { - adgold->adgold_mma.timer2_count--; - if (!adgold->adgold_mma.timer2_count) - { - adgold->adgold_mma.timer2_count = adgold->adgold_mma.timer2_latch; - adgold->adgold_mma_status |= 0x40; - adgold_update_irq_status(adgold); - } - } - } - } + case 2: + if (adgold->adgold_38x_state) /*Read from control chip*/ + temp = adgold->adgold_status; + else + temp = adgold->opl.read(addr, adgold->opl.priv); + break; - if (adgold->adgold_mma_enable[0]) - { - adgold->adgold_mma.voice_count[0]--; - if (!adgold->adgold_mma.voice_count[0]) - { - adgold->adgold_mma.voice_count[0] = adgold->adgold_mma.voice_latch[0]; - adgold_mma_poll(adgold, 0); - } - } - if (adgold->adgold_mma_enable[1]) - { - adgold->adgold_mma.voice_count[1]--; - if (!adgold->adgold_mma.voice_count[1]) - { - adgold->adgold_mma.voice_count[1] = adgold->adgold_mma.voice_latch[1]; - adgold_mma_poll(adgold, 1); - } - } + case 3: + if (adgold->adgold_38x_state) { + if (adgold->adgold_38x_addr >= 0x19) + temp = 0xff; + switch (adgold->adgold_38x_addr) { + case 0x00: /*Control/ID*/ + if (adgold->surround_enabled) + temp = 0x51; /*8-bit ISA, surround module, no telephone/CD-ROM*/ + else + temp = 0x71; /*8-bit ISA, no telephone/surround/CD-ROM*/ + break; + + default: + temp = adgold->adgold_38x_regs[adgold->adgold_38x_addr]; + break; + } + } else + temp = adgold->opl.read(addr, adgold->opl.priv); + break; + + case 4: + case 6: + 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) + temp = 0xff; + switch (adgold->adgold_mma_addr) { + case 6: /*Timer 2 low*/ + adgold->adgold_mma.timer2_read = adgold->adgold_mma.timer2_count; + adgold->adgold_mma_status |= 0x40; + temp = adgold->adgold_mma.timer2_read & 0xff; + break; + case 7: /*Timer 2 high*/ + temp = adgold->adgold_mma.timer2_read >> 8; + break; + + case 0xe: + temp = 0; + if (adgold->uart_in) { + temp = adgold->midi_queue[adgold->midi_r]; + if (adgold->midi_r != adgold->midi_w) { + adgold->midi_r++; + adgold->midi_r &= 0x0f; + } + adgold->adgold_mma_status &= ~0x04; + adgold_update_irq_status(adgold); + } + break; + + default: + temp = adgold->adgold_mma_regs[0][adgold->adgold_mma_addr]; + break; + } + break; + case 7: + if (adgold->adgold_mma_addr >= 0xf) + temp = 0xff; + else + temp = adgold->adgold_mma_regs[1][adgold->adgold_mma_addr]; + break; + + default: + break; + } + return temp; } -static void adgold_get_buffer(int32_t *buffer, int len, void *p) +void +adgold_update(adgold_t *adgold) { - adgold_t *adgold = (adgold_t *)p; - int16_t* adgold_buffer = malloc(sizeof(int16_t) * len * 2); - if (adgold_buffer == NULL) fatal("adgold_buffer = NULL"); + for (; adgold->pos < sound_pos_global; adgold->pos++) { + adgold->mma_buffer[0][adgold->pos] = adgold->mma_buffer[1][adgold->pos] = 0; - int c; + if (adgold->adgold_mma_regs[0][9] & 0x20) + adgold->mma_buffer[0][adgold->pos] += adgold->adgold_mma_out[0] / 2; + if (adgold->adgold_mma_regs[0][9] & 0x40) + adgold->mma_buffer[1][adgold->pos] += adgold->adgold_mma_out[0] / 2; - opl3_update(&adgold->opl); - adgold_update(adgold); - - for (c = 0; c < len * 2; c += 2) - { - adgold_buffer[c] = ((adgold->opl.buffer[c] * adgold->fm_vol_l) >> 7) / 2; - adgold_buffer[c] += ((adgold->mma_buffer[0][c >> 1] * adgold->samp_vol_l) >> 7) / 4; - adgold_buffer[c+1] = ((adgold->opl.buffer[c+1] * adgold->fm_vol_r) >> 7) / 2; - adgold_buffer[c+1] += ((adgold->mma_buffer[1][c >> 1] * adgold->samp_vol_r) >> 7) / 4; - } + if (adgold->adgold_mma_regs[1][9] & 0x20) + adgold->mma_buffer[0][adgold->pos] += adgold->adgold_mma_out[1] / 2; + if (adgold->adgold_mma_regs[1][9] & 0x40) + adgold->mma_buffer[1][adgold->pos] += adgold->adgold_mma_out[1] / 2; + } +} - if (adgold->surround_enabled) - ym7128_apply(&adgold->ym7128, adgold_buffer, len); +void +adgold_mma_poll(adgold_t *adgold, int channel) +{ + int16_t dat; - switch (adgold->adgold_38x_regs[0x8] & 6) - { - case 0: - for (c = 0; c < len * 2; c++) - adgold_buffer[c] = 0; + adgold_update(adgold); + + if (adgold->adgold_mma_fifo_start[channel] != adgold->adgold_mma_fifo_end[channel]) { + switch (adgold->adgold_mma_regs[channel][0xc] & 0x60) { + case 0x00: /*8-bit*/ + dat = adgold->adgold_mma_fifo[channel][adgold->adgold_mma_fifo_start[channel]] * 256; + adgold->adgold_mma_out[channel] = dat; + adgold->adgold_mma_fifo_start[channel] = (adgold->adgold_mma_fifo_start[channel] + 1) & 255; break; - case 2: /*Left channel only*/ - for (c = 0; c < len * 2; c += 2) - adgold_buffer[c+1] = adgold_buffer[c]; + + case 0x40: /*12-bit sensible format*/ + if (((adgold->adgold_mma_fifo_end[channel] - adgold->adgold_mma_fifo_start[channel]) & 255) < 2) + return; + + dat = adgold->adgold_mma_fifo[channel][adgold->adgold_mma_fifo_start[channel]] & 0xf0; + adgold->adgold_mma_fifo_start[channel] = (adgold->adgold_mma_fifo_start[channel] + 1) & 255; + dat |= (adgold->adgold_mma_fifo[channel][adgold->adgold_mma_fifo_start[channel]] << 8); + adgold->adgold_mma_fifo_start[channel] = (adgold->adgold_mma_fifo_start[channel] + 1) & 255; + adgold->adgold_mma_out[channel] = dat; break; - case 4: /*Right channel only*/ - for (c = 0; c < len * 2; c += 2) - adgold_buffer[c] = adgold_buffer[c+1]; - break; - case 6: /*Left and right channels*/ + + default: break; } - switch (adgold->adgold_38x_regs[0x8] & 0x18) - { - case 0x00: /*Forced mono*/ - for (c = 0; c < len * 2; c += 2) - adgold_buffer[c] = adgold_buffer[c+1] = ((int32_t)adgold_buffer[c] + (int32_t)adgold_buffer[c+1]) / 2; - break; - case 0x08: /*Linear stereo*/ - break; - case 0x10: /*Pseudo stereo*/ - /*Filter left channel, leave right channel unchanged*/ - /*Filter cutoff is largely a guess*/ - for (c = 0; c < len * 2; c += 2) - adgold_buffer[c] += adgold_pseudo_stereo_iir(adgold_buffer[c]); - break; - case 0x18: /*Spatial stereo*/ - /*Quite probably wrong, I only have the diagram in the TDA8425 datasheet - and a very vague understanding of how op-amps work to go on*/ - for (c = 0; c < len * 2; c += 2) - { - int16_t l = adgold_buffer[c]; - int16_t r = adgold_buffer[c+1]; - - adgold_buffer[c] += (r / 3) + ((l * 2) / 3); - adgold_buffer[c+1] += (l / 3) + ((r * 2) / 3); + if (adgold->adgold_mma_regs[channel][0xc] & 1) { + if (adgold_getsamp_dma(adgold, channel)) { + adgold->adgold_mma_fifo_end[channel] = 0; + adgold->adgold_mma_fifo_start[channel] = 0; + return; + } + } + if (((adgold->adgold_mma_fifo_end[channel] - adgold->adgold_mma_fifo_start[channel]) & 255) < adgold->adgold_mma_intpos[channel] && !(adgold->adgold_mma_status & 0x01)) { + adgold->adgold_mma_status |= (1 << channel); + adgold_update_irq_status(adgold); + } + } + if (adgold->adgold_mma_fifo_start[channel] == adgold->adgold_mma_fifo_end[channel]) { + adgold->adgold_mma_enable[channel] = 0; + } +} + +void +adgold_timer_poll(void *priv) +{ + adgold_t *adgold = (adgold_t *) priv; + + /*A small timer period will result in hangs.*/ + timer_advance_u64(&adgold->adgold_mma_timer_count, (uint64_t) ((double) TIMER_USEC * 1.88964)); + + if (adgold->adgold_midi_ctrl & 0x3f) { + if ((adgold->adgold_midi_ctrl & 0x3f) != 0x3f) { + if (adgold->uart_out) + adgold->adgold_mma_status |= 0x08; + if (adgold->adgold_midi_ctrl & 0x10) + adgold->adgold_mma_status |= 0x80; + } + adgold_update_irq_status(adgold); + } + + if (adgold->adgold_mma_regs[0][8] & 0x01) /*Timer 0*/ + { + adgold->adgold_mma.timer0_count--; + if (!adgold->adgold_mma.timer0_count) { + adgold->adgold_mma.timer0_count = adgold->adgold_mma.timer0_latch; + adgold->adgold_mma_status |= 0x10; + adgold_update_irq_status(adgold); + } + } + if (adgold->adgold_mma_regs[0][8] & 0x08) /*Base timer*/ + { + adgold->adgold_mma.timerbase_count--; + if (!adgold->adgold_mma.timerbase_count) { + adgold->adgold_mma.timerbase_count = adgold->adgold_mma.timerbase_latch; + if (adgold->adgold_mma_regs[0][8] & 0x02) /*Timer 1*/ + { + adgold->adgold_mma.timer1_count--; + if (!adgold->adgold_mma.timer1_count) { + adgold->adgold_mma.timer1_count = adgold->adgold_mma.timer1_latch; + adgold->adgold_mma_status |= 0x20; + adgold_update_irq_status(adgold); } - break; + } + if (adgold->adgold_mma_regs[0][8] & 0x04) /*Timer 2*/ + { + adgold->adgold_mma.timer2_count--; + if (!adgold->adgold_mma.timer2_count) { + adgold->adgold_mma.timer2_count = adgold->adgold_mma.timer2_latch; + adgold->adgold_mma_status |= 0x40; + adgold_update_irq_status(adgold); + } + } } + } - for (c = 0; c < len * 2; c += 2) - { - int32_t temp, lowpass, highpass; - - /*Output is deliberately halved to avoid clipping*/ - temp = ((int32_t)adgold_buffer[c] * adgold->vol_l) >> 17; - lowpass = adgold_lowpass_iir(0, temp); - highpass = adgold_highpass_iir(0, temp); - if (adgold->bass > 6) - temp += (lowpass * bass_attenuation[adgold->bass]) >> 14; - else if (adgold->bass < 6) - temp = highpass + ((temp * bass_cut[adgold->bass]) >> 14); - if (adgold->treble > 6) - temp += (highpass * treble_attenuation[adgold->treble]) >> 14; - else if (adgold->treble < 6) - temp = lowpass + ((temp * treble_cut[adgold->treble]) >> 14); - if (temp < -32768) - temp = -32768; - if (temp > 32767) - temp = 32767; - buffer[c] += temp; - - temp = ((int32_t)adgold_buffer[c+1] * adgold->vol_r) >> 17; - lowpass = adgold_lowpass_iir(1, temp); - highpass = adgold_highpass_iir(1, temp); - if (adgold->bass > 6) - temp += (lowpass * bass_attenuation[adgold->bass]) >> 14; - else if (adgold->bass < 6) - temp = highpass + ((temp * bass_cut[adgold->bass]) >> 14); - if (adgold->treble > 6) - temp += (highpass * treble_attenuation[adgold->treble]) >> 14; - else if (adgold->treble < 6) - temp = lowpass + ((temp * treble_cut[adgold->treble]) >> 14); - if (temp < -32768) - temp = -32768; - if (temp > 32767) - temp = 32767; - buffer[c+1] += temp; + if (adgold->adgold_mma_enable[0]) { + adgold->adgold_mma.voice_count[0]--; + if (!adgold->adgold_mma.voice_count[0]) { + adgold->adgold_mma.voice_count[0] = adgold->adgold_mma.voice_latch[0]; + adgold_mma_poll(adgold, 0); } - - adgold->opl.pos = 0; - adgold->pos = 0; - - free(adgold_buffer); + } + if (adgold->adgold_mma_enable[1]) { + adgold->adgold_mma.voice_count[1]--; + if (!adgold->adgold_mma.voice_count[1]) { + adgold->adgold_mma.voice_count[1] = adgold->adgold_mma.voice_latch[1]; + adgold_mma_poll(adgold, 1); + } + } } static void -adgold_filter_cd_audio(int channel, double *buffer, void *p) +adgold_get_buffer(int32_t *buffer, int len, void *priv) { - adgold_t *adgold = (adgold_t *)p; - double c; - int aux = channel ? adgold->aux_vol_r : adgold->aux_vol_l; - int vol = channel ? adgold->vol_r : adgold->vol_l; + adgold_t *adgold = (adgold_t *) priv; + int16_t *adgold_buffer = malloc(sizeof(int16_t) * len * 2); + if (adgold_buffer == NULL) + fatal("adgold_buffer = NULL"); - c = ((((*buffer) * aux) / 4096.0) * vol) / 4096.0; + int c; + + const int32_t *opl_buf = adgold->opl.update(adgold->opl.priv); + adgold_update(adgold); + + for (c = 0; c < len * 2; c += 2) { + adgold_buffer[c] = ((opl_buf[c] * adgold->fm_vol_l) >> 7) / 2; + adgold_buffer[c] += ((adgold->mma_buffer[0][c >> 1] * adgold->samp_vol_l) >> 7) / 4; + adgold_buffer[c + 1] = ((opl_buf[c + 1] * adgold->fm_vol_r) >> 7) / 2; + adgold_buffer[c + 1] += ((adgold->mma_buffer[1][c >> 1] * adgold->samp_vol_r) >> 7) / 4; + } + + if (adgold->surround_enabled) + ym7128_apply(&adgold->ym7128, adgold_buffer, len); + + switch (adgold->adgold_38x_regs[0x8] & 6) { + case 0: + for (c = 0; c < len * 2; c++) + adgold_buffer[c] = 0; + break; + case 2: /*Left channel only*/ + for (c = 0; c < len * 2; c += 2) + adgold_buffer[c + 1] = adgold_buffer[c]; + break; + case 4: /*Right channel only*/ + for (c = 0; c < len * 2; c += 2) + adgold_buffer[c] = adgold_buffer[c + 1]; + break; + case 6: /*Left and right channels*/ + break; + + default: + break; + } + + switch (adgold->adgold_38x_regs[0x8] & 0x18) { + case 0x00: /*Forced mono*/ + for (c = 0; c < len * 2; c += 2) + adgold_buffer[c] = adgold_buffer[c + 1] = ((int32_t) adgold_buffer[c] + (int32_t) adgold_buffer[c + 1]) / 2; + break; + case 0x08: /*Linear stereo*/ + break; + case 0x10: /*Pseudo stereo*/ + /*Filter left channel, leave right channel unchanged*/ + /*Filter cutoff is largely a guess*/ + for (c = 0; c < len * 2; c += 2) + adgold_buffer[c] += adgold_pseudo_stereo_iir(adgold_buffer[c]); + break; + case 0x18: /*Spatial stereo*/ + /*Quite probably wrong, I only have the diagram in the TDA8425 datasheet + and a very vague understanding of how op-amps work to go on*/ + for (c = 0; c < len * 2; c += 2) { + int16_t l = adgold_buffer[c]; + int16_t r = adgold_buffer[c + 1]; + + adgold_buffer[c] += (r / 3) + ((l * 2) / 3); + adgold_buffer[c + 1] += (l / 3) + ((r * 2) / 3); + } + break; + + default: + break; + } + + for (c = 0; c < len * 2; c += 2) { + int32_t temp; + int32_t lowpass; + int32_t highpass; + + /*Output is deliberately halved to avoid clipping*/ + temp = ((int32_t) adgold_buffer[c] * adgold->vol_l) >> 17; + lowpass = adgold_lowpass_iir(0, temp); + highpass = adgold_highpass_iir(0, temp); + if (adgold->bass > 6) + temp += (lowpass * bass_attenuation[adgold->bass]) >> 14; + else if (adgold->bass < 6) + temp = highpass + ((temp * bass_cut[adgold->bass]) >> 14); + if (adgold->treble > 6) + temp += (highpass * treble_attenuation[adgold->treble]) >> 14; + else if (adgold->treble < 6) + temp = lowpass + ((temp * treble_cut[adgold->treble]) >> 14); + if (temp < -32768) + temp = -32768; + if (temp > 32767) + temp = 32767; + buffer[c] += temp; + + temp = ((int32_t) adgold_buffer[c + 1] * adgold->vol_r) >> 17; + lowpass = adgold_lowpass_iir(1, temp); + highpass = adgold_highpass_iir(1, temp); + if (adgold->bass > 6) + temp += (lowpass * bass_attenuation[adgold->bass]) >> 14; + else if (adgold->bass < 6) + temp = highpass + ((temp * bass_cut[adgold->bass]) >> 14); + if (adgold->treble > 6) + temp += (highpass * treble_attenuation[adgold->treble]) >> 14; + else if (adgold->treble < 6) + temp = lowpass + ((temp * treble_cut[adgold->treble]) >> 14); + if (temp < -32768) + temp = -32768; + if (temp > 32767) + temp = 32767; + buffer[c + 1] += temp; + } + + adgold->opl.reset_buffer(adgold->opl.priv); + adgold->pos = 0; + + free(adgold_buffer); +} + +static void +adgold_filter_cd_audio(int channel, double *buffer, void *priv) +{ + const adgold_t *adgold = (adgold_t *) priv; + double c; + int aux = channel ? adgold->aux_vol_r : adgold->aux_vol_l; + int vol = channel ? adgold->vol_r : adgold->vol_l; + + c = ((((*buffer) * aux) / 4096.0) * vol) / 4096.0; *buffer = c; } - -static void adgold_input_msg(void *p, uint8_t *msg, uint32_t len) +static void +adgold_input_msg(void *priv, uint8_t *msg, uint32_t len) { - adgold_t *adgold = (adgold_t *)p; - uint8_t i; + adgold_t *adgold = (adgold_t *) priv; - if (adgold->sysex) - return; + if (adgold->sysex) + return; - if (adgold->uart_in) { - adgold->adgold_mma_status |= 0x04; + if (adgold->uart_in) { + adgold->adgold_mma_status |= 0x04; - for (i=0; i < len; i++) { - adgold->midi_queue[adgold->midi_w++] = msg[i]; - adgold->midi_w &= 0x0f; - } - - adgold_update_irq_status(adgold); - } -} - -static int adgold_input_sysex(void *p, uint8_t *buffer, uint32_t len, int abort) -{ - adgold_t *adgold = (adgold_t *)p; - uint32_t i; - - if (abort) { - adgold->sysex = 0; - return 0; - } - adgold->sysex = 1; - for (i=0;imidi_r == adgold->midi_w) - return (len-i); - adgold->midi_queue[adgold->midi_w++] = buffer[i]; - adgold->midi_w &= 0x0f; - } - adgold->sysex = 0; - return 0; -} - - -void *adgold_init(const device_t *info) -{ - FILE *f; - int c; - double out; - adgold_t *adgold = malloc(sizeof(adgold_t)); - memset(adgold, 0, sizeof(adgold_t)); - - adgold->surround_enabled = device_get_config_int("surround"); - - adgold->gameport_enabled = device_get_config_int("gameport"); - - opl3_init(&adgold->opl); - if (adgold->surround_enabled) - ym7128_init(&adgold->ym7128); - - out = 65536.0; /*Main volume control ranges from +6 dB to -64 dB in 2 dB steps, then remaining settings are -80 dB (effectively 0)*/ - for (c = 0x3f; c >= 0x1c; c--) - { - attenuation[c] = (int)out; - out /= 1.25963; /*2 dB steps*/ - } - for (; c >= 0; c--) - attenuation[c] = 0; - - adgold->adgold_eeprom[0x00] = 0x00; - adgold->adgold_eeprom[0x01] = 0x00; - adgold->adgold_eeprom[0x02] = 0x7f; - adgold->adgold_eeprom[0x03] = 0x7f; - adgold->adgold_eeprom[0x04] = 0xf8; /* vol_l */ - adgold->adgold_eeprom[0x05] = 0xf8; /* vol_r */ - adgold->adgold_eeprom[0x06] = 0xf6; /* bass */ - adgold->adgold_eeprom[0x07] = 0xf6; /* treble */ - adgold->adgold_eeprom[0x08] = 0xce; - adgold->adgold_eeprom[0x09] = 0xff; /* fm_vol_l */ - adgold->adgold_eeprom[0x0a] = 0xff; /* fm_vol_r */ - adgold->adgold_eeprom[0x0b] = 0xff; /* samp_vol_l */ - adgold->adgold_eeprom[0x0c] = 0xff; /* samp_vol_r */ - adgold->adgold_eeprom[0x0d] = 0xff; /* aux_vol_l */ - adgold->adgold_eeprom[0x0e] = 0xff; /* aux_vol_r */ - adgold->adgold_eeprom[0x0f] = 0xff; - adgold->adgold_eeprom[0x10] = 0xff; - adgold->adgold_eeprom[0x11] = 0x20; - adgold->adgold_eeprom[0x12] = 0x00; - adgold->adgold_eeprom[0x13] = 0x0b; /* IRQ 1, DMA1 */ - adgold->adgold_eeprom[0x14] = 0x00; /* DMA2 */ - adgold->adgold_eeprom[0x15] = 0x71; /* Port */ - adgold->adgold_eeprom[0x16] = 0x00; - adgold->adgold_eeprom[0x17] = 0x68; - adgold->adgold_eeprom[0x18] = 0x00; /* Surround */ - adgold->adgold_eeprom[0x19] = 0x00; - - f = nvr_fopen("adgold.bin", "rb"); - if (f) - { - if (fread(adgold->adgold_eeprom, 1, 0x1a, f) != 0x1a) - fatal("adgold_init(): Error reading data\n"); - fclose(f); + for (uint32_t i = 0; i < len; i++) { + adgold->midi_queue[adgold->midi_w++] = msg[i]; + adgold->midi_w &= 0x0f; } - adgold->adgold_status = 0xf; - adgold->adgold_38x_addr = 0; - adgold->adgold_eeprom[0x13] = 3 | (1 << 3); /*IRQ 7, DMA 1*/ -// adgold->adgold_eeprom[0x14] = 3 << 4; /*DMA 3 - Double check this */ - adgold->adgold_eeprom[0x14] = 0x00; /*DMA ?*/ - adgold->adgold_eeprom[0x15] = 0x388 / 8; /*Present at 388-38f*/ - 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]; - adgold->bass = adgold->adgold_eeprom[0x06] & 0xf; - adgold->treble = adgold->adgold_eeprom[0x07] & 0xf; - adgold->fm_vol_l = (int)(int8_t)(adgold->adgold_eeprom[0x09] - 128); - adgold->fm_vol_r = (int)(int8_t)(adgold->adgold_eeprom[0x0a] - 128); - adgold->samp_vol_l = (int)(int8_t)(adgold->adgold_eeprom[0x0b] - 128); - adgold->samp_vol_r = (int)(int8_t)(adgold->adgold_eeprom[0x0c] - 128); - adgold->aux_vol_l = (int)(int8_t)(adgold->adgold_eeprom[0x0d] - 128); - adgold->aux_vol_r = (int)(int8_t)(adgold->adgold_eeprom[0x0e] - 128); + adgold_update_irq_status(adgold); + } +} - adgold->adgold_mma_enable[0] = 0; - adgold->adgold_mma_fifo_start[0] = adgold->adgold_mma_fifo_end[0] = 0; +static int +adgold_input_sysex(void *priv, uint8_t *buffer, uint32_t len, int abort) +{ + adgold_t *adgold = (adgold_t *) priv; - /*388/389 are handled by adlib_init*/ - io_sethandler(0x0388, 0x0008, adgold_read, NULL, NULL, adgold_write, NULL, NULL, adgold); + if (abort) { + adgold->sysex = 0; + return 0; + } + adgold->sysex = 1; + for (uint32_t i = 0; i < len; i++) { + if (adgold->midi_r == adgold->midi_w) + return (len - i); + adgold->midi_queue[adgold->midi_w++] = buffer[i]; + adgold->midi_w &= 0x0f; + } + adgold->sysex = 0; + return 0; +} - if (adgold->gameport_enabled) +void * +adgold_init(UNUSED(const device_t *info)) +{ + FILE *fp; + int c; + double out; + adgold_t *adgold = malloc(sizeof(adgold_t)); + memset(adgold, 0, sizeof(adgold_t)); + + adgold->dma = device_get_config_int("dma"); + adgold->irq = device_get_config_int("irq"); + adgold->surround_enabled = device_get_config_int("surround"); + adgold->gameport_enabled = device_get_config_int("gameport"); + + fm_driver_get(FM_YMF262, &adgold->opl); + if (adgold->surround_enabled) + ym7128_init(&adgold->ym7128); + + out = 65536.0; /*Main volume control ranges from +6 dB to -64 dB in 2 dB steps, then remaining settings are -80 dB (effectively 0)*/ + for (c = 0x3f; c >= 0x1c; c--) { + attenuation[c] = (int) out; + out /= 1.25963; /*2 dB steps*/ + } + for (; c >= 0; c--) + attenuation[c] = 0; + + adgold->adgold_eeprom[0x00] = 0x00; + adgold->adgold_eeprom[0x01] = 0x00; + adgold->adgold_eeprom[0x02] = 0x7f; + adgold->adgold_eeprom[0x03] = 0x7f; + adgold->adgold_eeprom[0x04] = 0xf8; /* vol_l */ + adgold->adgold_eeprom[0x05] = 0xf8; /* vol_r */ + adgold->adgold_eeprom[0x06] = 0xf6; /* bass */ + adgold->adgold_eeprom[0x07] = 0xf6; /* treble */ + adgold->adgold_eeprom[0x08] = 0xce; + adgold->adgold_eeprom[0x09] = 0xff; /* fm_vol_l */ + adgold->adgold_eeprom[0x0a] = 0xff; /* fm_vol_r */ + adgold->adgold_eeprom[0x0b] = 0xff; /* samp_vol_l */ + adgold->adgold_eeprom[0x0c] = 0xff; /* samp_vol_r */ + adgold->adgold_eeprom[0x0d] = 0xff; /* aux_vol_l */ + adgold->adgold_eeprom[0x0e] = 0xff; /* aux_vol_r */ + adgold->adgold_eeprom[0x0f] = 0xff; + adgold->adgold_eeprom[0x10] = 0xff; + adgold->adgold_eeprom[0x11] = 0x20; + adgold->adgold_eeprom[0x12] = 0x00; + 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; + adgold->adgold_eeprom[0x17] = 0x68; + adgold->adgold_eeprom[0x18] = 0x00; /* Surround */ + adgold->adgold_eeprom[0x19] = 0x00; + + fp = nvr_fopen("adgold.bin", "rb"); + if (fp) { + if (fread(adgold->adgold_eeprom, 1, 0x1a, fp) != 0x1a) + fatal("adgold_init(): Error reading data\n"); + fclose(fp); + } + + adgold->adgold_status = 0xf; + adgold->adgold_38x_addr = 0; + switch (adgold->irq) { + case 3: + adgold->adgold_eeprom[0x13] |= 0x00; + break; + case 4: + adgold->adgold_eeprom[0x13] |= 0x01; + break; + case 5: + adgold->adgold_eeprom[0x13] |= 0x02; + break; + case 7: + adgold->adgold_eeprom[0x13] |= 0x03; + break; + + default: + 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]; + adgold->bass = adgold->adgold_eeprom[0x06] & 0xf; + adgold->treble = adgold->adgold_eeprom[0x07] & 0xf; + adgold->fm_vol_l = (int) (int8_t) (adgold->adgold_eeprom[0x09] - 128); + adgold->fm_vol_r = (int) (int8_t) (adgold->adgold_eeprom[0x0a] - 128); + adgold->samp_vol_l = (int) (int8_t) (adgold->adgold_eeprom[0x0b] - 128); + adgold->samp_vol_r = (int) (int8_t) (adgold->adgold_eeprom[0x0c] - 128); + adgold->aux_vol_l = (int) (int8_t) (adgold->adgold_eeprom[0x0d] - 128); + adgold->aux_vol_r = (int) (int8_t) (adgold->adgold_eeprom[0x0e] - 128); + + adgold->adgold_mma_enable[0] = 0; + adgold->adgold_mma_fifo_start[0] = adgold->adgold_mma_fifo_end[0] = 0; + + /*388/389 are handled by adlib_init*/ + io_sethandler(0x0388, 0x0008, adgold_read, NULL, NULL, adgold_write, NULL, NULL, adgold); + + if (adgold->gameport_enabled) gameport_remap(gameport_add(&gameport_201_device), 0x201); - timer_add(&adgold->adgold_mma_timer_count, adgold_timer_poll, adgold, 1); + timer_add(&adgold->adgold_mma_timer_count, adgold_timer_poll, adgold, 1); - sound_add_handler(adgold_get_buffer, adgold); - sound_set_cd_audio_filter(adgold_filter_cd_audio, adgold); + sound_add_handler(adgold_get_buffer, adgold); + sound_set_cd_audio_filter(adgold_filter_cd_audio, adgold); - if (device_get_config_int("receive_input")) - midi_in_handler(1, adgold_input_msg, adgold_input_sysex, adgold); + if (device_get_config_int("receive_input")) + midi_in_handler(1, adgold_input_msg, adgold_input_sysex, adgold); - return adgold; + return adgold; } -void adgold_close(void *p) +void +adgold_close(void *priv) { - FILE *f; - adgold_t *adgold = (adgold_t *)p; + FILE *fp; + adgold_t *adgold = (adgold_t *) priv; - f = nvr_fopen("adgold.bin", "wb"); - if (f) - { - fwrite(adgold->adgold_eeprom, 0x1a, 1, f); - fclose(f); - } + fp = nvr_fopen("adgold.bin", "wb"); + if (fp) { + fwrite(adgold->adgold_eeprom, 0x1a, 1, fp); + fclose(fp); + } - free(adgold); + free(adgold); } -static const device_config_t adgold_config[] = -{ - { - "gameport", "Enable Game port", CONFIG_BINARY, "", 1 - }, - { - "surround", "Surround module", CONFIG_BINARY, "", 1 - }, - { - "receive_input", "Receive input (MIDI)", CONFIG_BINARY, "", 1 - }, - { - "", "", -1 +static const device_config_t adgold_config[] = { + // clang-format off + { + .name = "irq", + .description = "IRQ", + .type = CONFIG_SELECTION, + .default_string = "", + .default_int = 7, + .file_filter = "", + .spinner = { 0 }, + .selection = { + { + .description = "IRQ 3", + .value = 3 + }, + { + .description = "IRQ 4", + .value = 4 + }, + { + .description = "IRQ 5", + .value = 5 + }, + { + .description = "IRQ 7", + .value = 7 + }, + { .description = "" } } + }, + { + .name = "dma", + .description = "Low DMA channel", + .type = CONFIG_SELECTION, + .default_string = "", + .default_int = 1, + .file_filter = "", + .spinner = { 0 }, + .selection = { + { + .description = "DMA 1", + .value = 1 + }, + { + .description = "DMA 3", + .value = 3 + }, + { .description = "" } + } + }, + { + .name = "gameport", + .description = "Enable Game port", + .type = CONFIG_BINARY, + .default_string = "", + .default_int = 1 + }, + { + .name = "surround", + .description = "Surround module", + .type = CONFIG_BINARY, + .default_string = "", + .default_int = 1 + }, + { + .name = "receive_input", + .description = "Receive input (MIDI)", + .type = CONFIG_BINARY, + .default_string = "", + .default_int = 1 + }, + { .name = "", .description = "", .type = CONFIG_END } + // clang-format on }; -const device_t adgold_device = -{ - "AdLib Gold", - "adlibgold", - DEVICE_ISA, 0, - adgold_init, - adgold_close, - NULL, - { NULL }, - NULL, - NULL, - adgold_config +const device_t adgold_device = { + .name = "AdLib Gold", + .internal_name = "adlibgold", + .flags = DEVICE_ISA, + .local = 0, + .init = adgold_init, + .close = adgold_close, + .reset = NULL, + { .available = NULL }, + .speed_changed = NULL, + .force_redraw = NULL, + .config = adgold_config }; diff --git a/src/sound/snd_audiopci.c b/src/sound/snd_audiopci.c index 6e88d401b..1405d8769 100644 --- a/src/sound/snd_audiopci.c +++ b/src/sound/snd_audiopci.c @@ -1,178 +1,193 @@ /* - * 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. + * 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. + * This file is part of the 86Box distribution. * - * Ensoniq AudioPCI (ES1371) emulation. + * Ensoniq AudioPCI (ES1371) emulation. * * * - * Authors: Sarah Walker, - * RichardG, - * Miran Grca, + * Authors: Sarah Walker, + * RichardG, + * Miran Grca, * - * Copyright 2008-2021 Sarah Walker. - * Copyright 2021 RichardG. - * Copyright 2021 Miran Grca. + * Copyright 2008-2021 Sarah Walker. + * Copyright 2021 RichardG. + * Copyright 2021 Miran Grca. */ -#include +#include #include +#include #include #include -#include #define _USE_MATH_DEFINES #include #define HAVE_STDARG_H + #include <86box/86box.h> #include <86box/device.h> #include <86box/gameport.h> #include <86box/io.h> -#include <86box/nmi.h> #include <86box/mem.h> -#include <86box/pci.h> -#include <86box/timer.h> -#include <86box/sound.h> #include <86box/midi.h> +#include <86box/nmi.h> +#include <86box/pci.h> #include <86box/snd_ac97.h> +#include <86box/sound.h> +#include <86box/timer.h> +#include <86box/plat_unused.h> - -#define N 16 +#define N 16 #define ES1371_NCoef 91 - static float low_fir_es1371_coef[ES1371_NCoef]; +typedef struct es1371_t { + uint8_t pci_command; + uint8_t pci_serr; -typedef struct { - uint8_t pci_command, pci_serr; + uint32_t base_addr; - uint32_t base_addr; + uint8_t int_line; + uint8_t irq_state; - uint8_t int_line; + uint16_t pmcsr; - uint16_t pmcsr; + uint32_t int_ctrl; + uint32_t int_status; + uint32_t legacy_ctrl; + void *gameport; - uint32_t int_ctrl, int_status, - legacy_ctrl; - void * gameport; + int mem_page; - int mem_page; + uint32_t si_cr; - uint32_t si_cr; + uint32_t sr_cir; + uint16_t sr_ram[128]; - uint32_t sr_cir; - uint16_t sr_ram[128]; + uint8_t uart_data; + uint8_t uart_ctrl; + uint8_t uart_status; + uint8_t uart_res; + uint32_t uart_fifo[8]; + uint8_t read_fifo_pos; + uint8_t write_fifo_pos; - uint8_t uart_data, uart_ctrl, - uart_status, uart_res; - uint32_t uart_fifo[8]; - uint8_t read_fifo_pos, write_fifo_pos; - - ac97_codec_t * codec; - uint32_t codec_ctrl; + ac97_codec_t *codec; + uint32_t codec_ctrl; struct { - uint32_t addr, addr_latch; - uint16_t count, size; + uint32_t addr; + uint32_t addr_latch; + uint16_t count; + uint16_t size; - uint16_t samp_ct; - int curr_samp_ct; + uint16_t samp_ct; + int curr_samp_ct; - pc_timer_t timer; - uint64_t latch; + pc_timer_t timer; + uint64_t latch; - uint32_t vf, ac; + uint32_t vf; + uint32_t ac; - int16_t buffer_l[64], buffer_r[64]; - int buffer_pos, buffer_pos_end; + int16_t buffer_l[64]; + int16_t buffer_r[64]; + int buffer_pos; + int buffer_pos_end; - int filtered_l[32], filtered_r[32]; - int f_pos; + int filtered_l[32]; + int filtered_r[32]; + int f_pos; - int16_t out_l, out_r; + int16_t out_l; + int16_t out_r; - int32_t vol_l, vol_r; + int32_t vol_l; + int32_t vol_r; } dac[2], adc; - int64_t dac_latch, dac_time; + int64_t dac_latch; + int64_t dac_time; - int master_vol_l, master_vol_r, - pcm_vol_l, pcm_vol_r, - cd_vol_l, cd_vol_r; + int master_vol_l; + int master_vol_r; + int pcm_vol_l; + int pcm_vol_r; + int cd_vol_l; + int cd_vol_r; - int card; + uint8_t pci_slot; - int pos; - int16_t buffer[SOUNDBUFLEN * 2]; + int pos; + int16_t buffer[SOUNDBUFLEN * 2]; - int type; + int type; } es1371_t; +#define LEGACY_SB_ADDR (1 << 29) +#define LEGACY_SSCAPE_ADDR_SHIFT 27 +#define LEGACY_CODEC_ADDR_SHIFT 25 +#define LEGACY_FORCE_IRQ (1 << 24) +#define LEGACY_CAPTURE_SLAVE_DMA (1 << 23) +#define LEGACY_CAPTURE_SLAVE_PIC (1 << 22) +#define LEGACY_CAPTURE_MASTER_DMA (1 << 21) +#define LEGACY_CAPTURE_MASTER_PIC (1 << 20) +#define LEGACY_CAPTURE_ADLIB (1 << 19) +#define LEGACY_CAPTURE_SB (1 << 18) +#define LEGACY_CAPTURE_CODEC (1 << 17) +#define LEGACY_CAPTURE_SSCAPE (1 << 16) +#define LEGACY_EVENT_SSCAPE (0 << 8) +#define LEGACY_EVENT_CODEC (1 << 8) +#define LEGACY_EVENT_SB (2 << 8) +#define LEGACY_EVENT_ADLIB (3 << 8) +#define LEGACY_EVENT_MASTER_PIC (4 << 8) +#define LEGACY_EVENT_MASTER_DMA (5 << 8) +#define LEGACY_EVENT_SLAVE_PIC (6 << 8) +#define LEGACY_EVENT_SLAVE_DMA (7 << 8) +#define LEGACY_EVENT_MASK (7 << 8) +#define LEGACY_EVENT_ADDR_SHIFT 3 +#define LEGACY_EVENT_ADDR_MASK (0x1f << 3) +#define LEGACY_EVENT_TYPE_RW (1 << 2) +#define LEGACY_INT (1 << 0) -#define LEGACY_SB_ADDR (1<<29) -#define LEGACY_SSCAPE_ADDR_SHIFT 27 -#define LEGACY_CODEC_ADDR_SHIFT 25 -#define LEGACY_FORCE_IRQ (1<<24) -#define LEGACY_CAPTURE_SLAVE_DMA (1<<23) -#define LEGACY_CAPTURE_SLAVE_PIC (1<<22) -#define LEGACY_CAPTURE_MASTER_DMA (1<<21) -#define LEGACY_CAPTURE_MASTER_PIC (1<<20) -#define LEGACY_CAPTURE_ADLIB (1<<19) -#define LEGACY_CAPTURE_SB (1<<18) -#define LEGACY_CAPTURE_CODEC (1<<17) -#define LEGACY_CAPTURE_SSCAPE (1<<16) -#define LEGACY_EVENT_SSCAPE (0<<8) -#define LEGACY_EVENT_CODEC (1<<8) -#define LEGACY_EVENT_SB (2<<8) -#define LEGACY_EVENT_ADLIB (3<<8) -#define LEGACY_EVENT_MASTER_PIC (4<<8) -#define LEGACY_EVENT_MASTER_DMA (5<<8) -#define LEGACY_EVENT_SLAVE_PIC (6<<8) -#define LEGACY_EVENT_SLAVE_DMA (7<<8) -#define LEGACY_EVENT_MASK (7<<8) -#define LEGACY_EVENT_ADDR_SHIFT 3 -#define LEGACY_EVENT_ADDR_MASK (0x1f<<3) -#define LEGACY_EVENT_TYPE_RW (1<<2) -#define LEGACY_INT (1<<0) +#define SRC_RAM_WE (1 << 24) -#define SRC_RAM_WE (1<<24) +#define CODEC_READ (1 << 23) +#define CODEC_READY (1 << 31) -#define CODEC_READ (1<<23) -#define CODEC_READY (1<<31) +#define INT_DAC1_EN (1 << 6) +#define INT_DAC2_EN (1 << 5) +#define INT_UART_EN (1 << 3) -#define INT_DAC1_EN (1<<6) -#define INT_DAC2_EN (1<<5) -#define INT_UART_EN (1<<3) +#define SI_P2_PAUSE (1 << 12) +#define SI_P1_PAUSE (1 << 11) +#define SI_P2_INTR_EN (1 << 9) +#define SI_P1_INTR_EN (1 << 8) -#define SI_P2_PAUSE (1<<12) -#define SI_P1_PAUSE (1<<11) -#define SI_P2_INTR_EN (1<<9) -#define SI_P1_INTR_EN (1<<8) +#define INT_STATUS_INTR (1 << 31) +#define INT_STATUS_UART (1 << 3) +#define INT_STATUS_DAC1 (1 << 2) +#define INT_STATUS_DAC2 (1 << 1) -#define INT_STATUS_INTR (1<<31) -#define INT_STATUS_UART (1<<3) -#define INT_STATUS_DAC1 (1<<2) -#define INT_STATUS_DAC2 (1<<1) +#define UART_CTRL_RXINTEN (1 << 7) +#define UART_CTRL_TXINTEN (3 << 5) -#define UART_CTRL_RXINTEN (1<<7) -#define UART_CTRL_TXINTEN (3<<5) +#define UART_STATUS_RXINT (1 << 7) +#define UART_STATUS_TXINT (1 << 2) +#define UART_STATUS_TXRDY (1 << 1) +#define UART_STATUS_RXRDY (1 << 0) -#define UART_STATUS_RXINT (1<<7) -#define UART_STATUS_TXINT (1<<2) -#define UART_STATUS_TXRDY (1<<1) -#define UART_STATUS_RXRDY (1<<0) - -#define UART_FIFO_BYTE_VALID 0x00000100 - -#define FORMAT_MONO_8 0 -#define FORMAT_STEREO_8 1 -#define FORMAT_MONO_16 2 -#define FORMAT_STEREO_16 3 +#define UART_FIFO_BYTE_VALID 0x00000100 +#define FORMAT_MONO_8 0 +#define FORMAT_STEREO_8 1 +#define FORMAT_MONO_16 2 +#define FORMAT_STEREO_16 3 static void es1371_fetch(es1371_t *dev, int dac_nr); static void update_legacy(es1371_t *dev, uint32_t old_legacy_ctrl); @@ -180,151 +195,138 @@ static void update_legacy(es1371_t *dev, uint32_t old_legacy_ctrl); #ifdef ENABLE_AUDIOPCI_LOG int audiopci_do_log = ENABLE_AUDIOPCI_LOG; - static void audiopci_log(const char *fmt, ...) { va_list ap; if (audiopci_do_log) { - va_start(ap, fmt); - pclog_ex(fmt, ap); - va_end(ap); + va_start(ap, fmt); + pclog_ex(fmt, ap); + va_end(ap); } } #else -#define audiopci_log(fmt, ...) +# define audiopci_log(fmt, ...) #endif - static void es1371_update_irqs(es1371_t *dev) { int irq = 0; if ((dev->int_status & INT_STATUS_DAC1) && (dev->si_cr & SI_P1_INTR_EN)) - irq = 1; + irq = 1; if ((dev->int_status & INT_STATUS_DAC2) && (dev->si_cr & SI_P2_INTR_EN)) - irq = 1; + irq = 1; dev->int_status &= ~INT_STATUS_UART; if ((dev->uart_status & UART_STATUS_TXINT) || (dev->uart_status & UART_STATUS_RXINT)) { - dev->int_status |= INT_STATUS_UART; - irq = 1; + dev->int_status |= INT_STATUS_UART; + irq = 1; } if (irq) - dev->int_status |= INT_STATUS_INTR; + dev->int_status |= INT_STATUS_INTR; else - dev->int_status &= ~INT_STATUS_INTR; + dev->int_status &= ~INT_STATUS_INTR; if (dev->legacy_ctrl & LEGACY_FORCE_IRQ) - irq = 1; + irq = 1; if (irq) - pci_set_irq(dev->card, PCI_INTA); + pci_set_irq(dev->pci_slot, PCI_INTA, &dev->irq_state); else - pci_clear_irq(dev->card, PCI_INTA); + pci_clear_irq(dev->pci_slot, PCI_INTA, &dev->irq_state); } - static void es1371_update_tx_irq(es1371_t *dev) { dev->uart_status &= ~UART_STATUS_TXINT; if (((dev->uart_ctrl & UART_CTRL_TXINTEN) == 0x20) && (dev->uart_status & UART_STATUS_TXRDY)) - dev->uart_status |= UART_STATUS_TXINT; + dev->uart_status |= UART_STATUS_TXINT; es1371_update_irqs(dev); } - static void es1371_set_tx_irq(es1371_t *dev, int set) { dev->uart_status &= ~UART_STATUS_TXRDY; if (set) - dev->uart_status |= UART_STATUS_TXRDY; + dev->uart_status |= UART_STATUS_TXRDY; es1371_update_tx_irq(dev); } - static void es1371_update_rx_irq(es1371_t *dev) { dev->uart_status &= ~UART_STATUS_RXINT; if ((dev->uart_ctrl & UART_CTRL_RXINTEN) && (dev->uart_status & UART_STATUS_RXRDY)) - dev->uart_status |= UART_STATUS_RXINT; + dev->uart_status |= UART_STATUS_RXINT; es1371_update_irqs(dev); } - static void es1371_set_rx_irq(es1371_t *dev, int set) { dev->uart_status &= ~UART_STATUS_RXRDY; if (set) - dev->uart_status |= UART_STATUS_RXRDY; + dev->uart_status |= UART_STATUS_RXRDY; es1371_update_rx_irq(dev); } - static void es1371_scan_fifo(es1371_t *dev) { if (dev->read_fifo_pos != dev->write_fifo_pos) { - dev->uart_data = dev->uart_fifo[dev->read_fifo_pos]; - dev->read_fifo_pos = (dev->read_fifo_pos + 1) & 7; + dev->uart_data = dev->uart_fifo[dev->read_fifo_pos]; + dev->read_fifo_pos = (dev->read_fifo_pos + 1) & 7; - es1371_set_rx_irq(dev, 1); + es1371_set_rx_irq(dev, 1); } else - es1371_set_rx_irq(dev, 0); + es1371_set_rx_irq(dev, 0); } - static void es1371_write_fifo(es1371_t *dev, uint8_t val) { if (dev->write_fifo_pos < 8) { - dev->uart_fifo[dev->write_fifo_pos] = val | UART_FIFO_BYTE_VALID; - dev->write_fifo_pos = (dev->write_fifo_pos + 1) & 7; + dev->uart_fifo[dev->write_fifo_pos] = val | UART_FIFO_BYTE_VALID; + dev->write_fifo_pos = (dev->write_fifo_pos + 1) & 7; } } - static void es1371_reset_fifo(es1371_t *dev) { - int i; - - for (i = 0; i < 8; i++) - dev->uart_fifo[i] = 0x00000000; + for (uint8_t i = 0; i < 8; i++) + dev->uart_fifo[i] = 0x00000000; dev->read_fifo_pos = dev->write_fifo_pos = 0; es1371_set_rx_irq(dev, 0); } - static void -es1371_reset(void *p) +es1371_reset(void *priv) { - es1371_t *dev = (es1371_t *) p; - int i; + es1371_t *dev = (es1371_t *) priv; nmi = 0; /* Interrupt/Chip Select Control Register, Address 00H Addressable as byte, word, longword */ - dev->int_ctrl = 0xfc0f0000; + dev->int_ctrl = 0xfcff0000; /* Interrupt/Chip Select Control Register, Address 00H Addressable as longword only */ @@ -332,7 +334,7 @@ es1371_reset(void *p) /* UART Status Register, Address 09H Addressable as byte only */ - dev->uart_status = 0x00; + dev->uart_status = 0xff; /* UART Control Register, Address 09H Addressable as byte only */ @@ -340,15 +342,15 @@ es1371_reset(void *p) /* UART Reserved Register, Address 0AH Addressable as byte only */ - dev->uart_res = 0x00; + dev->uart_res = 0xff; /* Memory Page Register, Address 0CH Addressable as byte, word, longword */ - dev->mem_page = 0x00; + dev->mem_page = 0xf0; /* FIXME: hardware reads 0xfffffff0 */ /* Sample Rate Converter Interface Register, Address 10H Addressable as longword only */ - dev->sr_cir = 0x00000000; + dev->sr_cir = 0x00470000; /* CODEC Write Register, Address 14H Addressable as longword only */ @@ -356,7 +358,7 @@ es1371_reset(void *p) /* Legacy Control/Status Register, Address 18H Addressable as byte, word, longword */ - dev->legacy_ctrl = 0x0000f800; + dev->legacy_ctrl = 0x0000f801; /* Serial Interface Control Register, Address 20H Addressable as byte, word, longword */ @@ -364,17 +366,17 @@ es1371_reset(void *p) /* DAC1 Channel Sample Count Register, Address 24H Addressable as word, longword */ - dev->dac[0].samp_ct = 0x00000000; + dev->dac[0].samp_ct = 0x00000000; /* FIXME: hardware reads 0x00010000 */ dev->dac[0].curr_samp_ct = 0x00000000; /* DAC2 Channel Sample Count Register, Address 28H Addressable as word, longword */ - dev->dac[1].samp_ct = 0x00000000; + dev->dac[1].samp_ct = 0x00000000; /* FIXME: hardware reads 0x00010000 */ dev->dac[1].curr_samp_ct = 0x00000000; /* ADC Channel Sample Count Register, Address 2CH Addressable as word, longword */ - dev->adc.samp_ct = 0x00000000; + dev->adc.samp_ct = 0x00000000; /* FIXME: hardware reads 0x00010000 */ dev->adc.curr_samp_ct = 0x00000000; /* DAC1 Frame Register 1, Address 30H, Memory Page 1100b @@ -383,7 +385,7 @@ es1371_reset(void *p) /* DAC1 Frame Register 2, Address 34H, Memory Page 1100b Addressable as longword only */ - dev->dac[0].size = 0x00000000; + dev->dac[0].size = 0x00000000; dev->dac[0].count = 0x00000000; /* DAC2 Frame Register 1, Address 38H, Memory Page 1100b @@ -392,7 +394,7 @@ es1371_reset(void *p) /* DAC2 Frame Register 2, Address 3CH, Memory Page 1100b Addressable as longword only */ - dev->dac[1].size = 0x00000000; + dev->dac[1].size = 0x00000000; dev->dac[1].count = 0x00000000; /* ADC Frame Register 1, Address 30H, Memory Page 1101b @@ -401,13 +403,13 @@ es1371_reset(void *p) /* ADC Frame Register 2, Address 34H, Memory Page 1101b Addressable as longword only */ - dev->adc.size = 0x00000000; + dev->adc.size = 0x00000000; dev->adc.count = 0x00000000; /* UART FIFO Register, Address 30H, 34H, 38H, 3CH, Memory Page 1110b, 1111b Addressable as longword only */ - for (i = 0; i < 8; i++) - dev->uart_fifo[i] = 0xffff0000; + for (uint8_t i = 0; i < 8; i++) + dev->uart_fifo[i] = 0xffff0000; /* Reset the UART TX. */ es1371_set_tx_irq(dev, 0); @@ -419,1405 +421,1481 @@ es1371_reset(void *p) es1371_update_irqs(dev); } - static uint32_t es1371_read_frame_reg(es1371_t *dev, int frame, int page) { uint32_t ret = 0xffffffff; switch (frame) { - case 0x30: - switch (page) { - /* DAC1 Frame Register 1, Address 30H, Memory Page 1100b - Addressable as longword only */ - case 0xc: - ret = dev->dac[0].addr_latch; - break; - /* ADC Frame Register 1, Address 30H, Memory Page 1101b - Addressable as longword only */ - case 0xd: - ret = dev->adc.addr_latch; - break; - /* UART FIFO Register, Address 30H, 34H, 38H, 3CH, Memory Page 1110b, 1111b - Addressable as longword only */ - case 0xe: case 0xf: - audiopci_log("[30:%02X] ret = dev->uart_fifo[%02X] = %08X\n", page, - ((page & 0x01) << 2) + ((frame >> 2) & 0x03), - dev->uart_fifo[((page & 0x01) << 2) + ((frame >> 2) & 0x03)]); - ret = dev->uart_fifo[((page & 0x01) << 2) + ((frame >> 2) & 0x03)]; - break; - } - break; - case 0x34: - switch (page) { - /* DAC1 Frame Register 2, Address 34H, Memory Page 1100b - Addressable as longword only */ - case 0xc: - ret = dev->dac[0].size | (dev->dac[0].count << 16); - break; - /* ADC Frame Register 2, Address 34H, Memory Page 1101b - Addressable as longword only */ - case 0xd: - ret = dev->adc.size | (dev->adc.count << 16); - break; - /* UART FIFO Register, Address 30H, 34H, 38H, 3CH, Memory Page 1110b, 1111b - Addressable as longword only */ - case 0xe: case 0xf: - audiopci_log("[34:%02X] ret = dev->uart_fifo[%02X] = %08X\n", page, - ((page & 0x01) << 2) + ((frame >> 2) & 0x03), - dev->uart_fifo[((page & 0x01) << 2) + ((frame >> 2) & 0x03)]); - ret = dev->uart_fifo[((page & 0x01) << 2) + ((frame >> 2) & 0x03)]; - break; - } - break; - case 0x38: - switch (page) { - /* DAC2 Frame Register 1, Address 38H, Memory Page 1100b - Addressable as longword only */ - case 0xc: - ret = dev->dac[1].addr_latch; - break; - /* UART FIFO Register, Address 30H, 34H, 38H, 3CH, Memory Page 1110b, 1111b - Addressable as longword only */ - case 0xe: case 0xf: - audiopci_log("[38:%02X] ret = dev->uart_fifo[%02X] = %08X\n", page, - ((page & 0x01) << 2) + ((frame >> 2) & 0x03), - dev->uart_fifo[((page & 0x01) << 2) + ((frame >> 2) & 0x03)]); - ret = dev->uart_fifo[((page & 0x01) << 2) + ((frame >> 2) & 0x03)]; - break; - } - break; - case 0x3c: - switch (page) { - /* DAC2 Frame Register 2, Address 3CH, Memory Page 1100b - Addressable as longword only */ - case 0xc: - ret = dev->dac[1].size | (dev->dac[1].count << 16); - break; - /* UART FIFO Register, Address 30H, 34H, 38H, 3CH, Memory Page 1110b, 1111b - Addressable as longword only */ - case 0xe: case 0xf: - audiopci_log("[3C:%02X] ret = dev->uart_fifo[%02X] = %08X\n", page, - ((page & 0x01) << 2) + ((frame >> 2) & 0x03), - dev->uart_fifo[((page & 0x01) << 2) + ((frame >> 2) & 0x03)]); - ret = dev->uart_fifo[((page & 0x01) << 2) + ((frame >> 2) & 0x03)]; - break; - } - break; + case 0x30: + switch (page) { + /* DAC1 Frame Register 1, Address 30H, Memory Page 1100b + Addressable as longword only */ + case 0xc: + ret = dev->dac[0].addr_latch; + break; + /* ADC Frame Register 1, Address 30H, Memory Page 1101b + Addressable as longword only */ + case 0xd: + ret = dev->adc.addr_latch; + break; + /* UART FIFO Register, Address 30H, 34H, 38H, 3CH, Memory Page 1110b, 1111b + Addressable as longword only */ + case 0xe: + case 0xf: + audiopci_log("[30:%02X] ret = dev->uart_fifo[%02X] = %08X\n", page, + ((page & 0x01) << 2) + ((frame >> 2) & 0x03), + dev->uart_fifo[((page & 0x01) << 2) + ((frame >> 2) & 0x03)]); + ret = dev->uart_fifo[((page & 0x01) << 2) + ((frame >> 2) & 0x03)]; + break; + + default: + break; + } + break; + case 0x34: + switch (page) { + /* DAC1 Frame Register 2, Address 34H, Memory Page 1100b + Addressable as longword only */ + case 0xc: + ret = dev->dac[0].size | (dev->dac[0].count << 16); + break; + /* ADC Frame Register 2, Address 34H, Memory Page 1101b + Addressable as longword only */ + case 0xd: + ret = dev->adc.size | (dev->adc.count << 16); + break; + /* UART FIFO Register, Address 30H, 34H, 38H, 3CH, Memory Page 1110b, 1111b + Addressable as longword only */ + case 0xe: + case 0xf: + audiopci_log("[34:%02X] ret = dev->uart_fifo[%02X] = %08X\n", page, + ((page & 0x01) << 2) + ((frame >> 2) & 0x03), + dev->uart_fifo[((page & 0x01) << 2) + ((frame >> 2) & 0x03)]); + ret = dev->uart_fifo[((page & 0x01) << 2) + ((frame >> 2) & 0x03)]; + break; + + default: + break; + } + break; + case 0x38: + switch (page) { + /* DAC2 Frame Register 1, Address 38H, Memory Page 1100b + Addressable as longword only */ + case 0xc: + ret = dev->dac[1].addr_latch; + break; + /* UART FIFO Register, Address 30H, 34H, 38H, 3CH, Memory Page 1110b, 1111b + Addressable as longword only */ + case 0xe: + case 0xf: + audiopci_log("[38:%02X] ret = dev->uart_fifo[%02X] = %08X\n", page, + ((page & 0x01) << 2) + ((frame >> 2) & 0x03), + dev->uart_fifo[((page & 0x01) << 2) + ((frame >> 2) & 0x03)]); + ret = dev->uart_fifo[((page & 0x01) << 2) + ((frame >> 2) & 0x03)]; + break; + + default: + break; + } + break; + case 0x3c: + switch (page) { + /* DAC2 Frame Register 2, Address 3CH, Memory Page 1100b + Addressable as longword only */ + case 0xc: + ret = dev->dac[1].size | (dev->dac[1].count << 16); + break; + /* UART FIFO Register, Address 30H, 34H, 38H, 3CH, Memory Page 1110b, 1111b + Addressable as longword only */ + case 0xe: + case 0xf: + audiopci_log("[3C:%02X] ret = dev->uart_fifo[%02X] = %08X\n", page, + ((page & 0x01) << 2) + ((frame >> 2) & 0x03), + dev->uart_fifo[((page & 0x01) << 2) + ((frame >> 2) & 0x03)]); + ret = dev->uart_fifo[((page & 0x01) << 2) + ((frame >> 2) & 0x03)]; + break; + + default: + break; + } + break; + + default: + break; } - if (page == 0x0e || page == 0x0f) { - audiopci_log("Read frame = %02x, page = %02x, uart fifo valid = %02x, temp = %03x\n", frame, page, dev->valid, ret); - } - return ret; } - static void es1371_write_frame_reg(es1371_t *dev, int frame, int page, uint32_t val) { switch (frame) { - case 0x30: - switch (page) { - /* DAC1 Frame Register 1, Address 30H, Memory Page 1100b - Addressable as longword only */ - case 0xc: - dev->dac[0].addr_latch = val; - break; - /* ADC Frame Register 1, Address 30H, Memory Page 1101b - Addressable as longword only */ - case 0xd: - dev->adc.addr_latch = val; - break; - /* UART FIFO Register, Address 30H, 34H, 38H, 3CH, Memory Page 1110b, 1111b - Addressable as longword only */ - case 0xe: case 0xf: - audiopci_log("[30:%02X] dev->uart_fifo[%02X] = %08X\n", page, - ((page & 0x01) << 2) + ((frame >> 2) & 0x03), val); - dev->uart_fifo[((page & 0x01) << 2) + ((frame >> 2) & 0x03)] = val; - break; - } - break; - case 0x34: - switch (page) { - /* DAC1 Frame Register 2, Address 34H, Memory Page 1100b - Addressable as longword only */ - case 0xc: - dev->dac[0].size = val & 0xffff; - dev->dac[0].count = val >> 16; - break; - /* ADC Frame Register 2, Address 34H, Memory Page 1101b - Addressable as longword only */ - case 0xd: - dev->adc.size = val & 0xffff; - dev->adc.count = val >> 16; - break; - /* UART FIFO Register, Address 30H, 34H, 38H, 3CH, Memory Page 1110b, 1111b - Addressable as longword only */ - case 0xe: case 0xf: - audiopci_log("[34:%02X] dev->uart_fifo[%02X] = %08X\n", page, - ((page & 0x01) << 2) + ((frame >> 2) & 0x03), val); - dev->uart_fifo[((page & 0x01) << 2) + ((frame >> 2) & 0x03)] = val; - break; - } - break; - case 0x38: - switch (page) { - /* DAC2 Frame Register 1, Address 38H, Memory Page 1100b - Addressable as longword only */ - case 0xc: - dev->dac[1].addr_latch = val; - break; - /* UART FIFO Register, Address 30H, 34H, 38H, 3CH, Memory Page 1110b, 1111b - Addressable as longword only */ - case 0xe: case 0xf: - audiopci_log("[38:%02X] dev->uart_fifo[%02X] = %08X\n", page, - ((page & 0x01) << 2) + ((frame >> 2) & 0x03), val); - dev->uart_fifo[((page & 0x01) << 2) + ((frame >> 2) & 0x03)] = val; - break; - } - break; - case 0x3c: - switch (page) { - /* DAC2 Frame Register 2, Address 3CH, Memory Page 1100b - Addressable as longword only */ - case 0xc: - dev->dac[1].size = val & 0xffff; - dev->dac[1].count = val >> 16; - break; - /* UART FIFO Register, Address 30H, 34H, 38H, 3CH, Memory Page 1110b, 1111b - Addressable as longword only */ - case 0xe: case 0xf: - audiopci_log("[3C:%02X] dev->uart_fifo[%02X] = %08X\n", page, - ((page & 0x01) << 2) + ((frame >> 2) & 0x03), val); - dev->uart_fifo[((page & 0x01) << 2) + ((frame >> 2) & 0x03)] = val; - break; - } - break; + case 0x30: + switch (page) { + /* DAC1 Frame Register 1, Address 30H, Memory Page 1100b + Addressable as longword only */ + case 0xc: + dev->dac[0].addr_latch = val; + break; + /* ADC Frame Register 1, Address 30H, Memory Page 1101b + Addressable as longword only */ + case 0xd: + dev->adc.addr_latch = val; + break; + /* UART FIFO Register, Address 30H, 34H, 38H, 3CH, Memory Page 1110b, 1111b + Addressable as longword only */ + case 0xe: + case 0xf: + audiopci_log("[30:%02X] dev->uart_fifo[%02X] = %08X\n", page, + ((page & 0x01) << 2) + ((frame >> 2) & 0x03), val); + dev->uart_fifo[((page & 0x01) << 2) + ((frame >> 2) & 0x03)] = val; + break; + + default: + break; + } + break; + case 0x34: + switch (page) { + /* DAC1 Frame Register 2, Address 34H, Memory Page 1100b + Addressable as longword only */ + case 0xc: + dev->dac[0].size = val & 0xffff; + dev->dac[0].count = val >> 16; + break; + /* ADC Frame Register 2, Address 34H, Memory Page 1101b + Addressable as longword only */ + case 0xd: + dev->adc.size = val & 0xffff; + dev->adc.count = val >> 16; + break; + /* UART FIFO Register, Address 30H, 34H, 38H, 3CH, Memory Page 1110b, 1111b + Addressable as longword only */ + case 0xe: + case 0xf: + audiopci_log("[34:%02X] dev->uart_fifo[%02X] = %08X\n", page, + ((page & 0x01) << 2) + ((frame >> 2) & 0x03), val); + dev->uart_fifo[((page & 0x01) << 2) + ((frame >> 2) & 0x03)] = val; + break; + + default: + break; + } + break; + case 0x38: + switch (page) { + /* DAC2 Frame Register 1, Address 38H, Memory Page 1100b + Addressable as longword only */ + case 0xc: + dev->dac[1].addr_latch = val; + break; + /* UART FIFO Register, Address 30H, 34H, 38H, 3CH, Memory Page 1110b, 1111b + Addressable as longword only */ + case 0xe: + case 0xf: + audiopci_log("[38:%02X] dev->uart_fifo[%02X] = %08X\n", page, + ((page & 0x01) << 2) + ((frame >> 2) & 0x03), val); + dev->uart_fifo[((page & 0x01) << 2) + ((frame >> 2) & 0x03)] = val; + break; + + default: + break; + } + break; + case 0x3c: + switch (page) { + /* DAC2 Frame Register 2, Address 3CH, Memory Page 1100b + Addressable as longword only */ + case 0xc: + dev->dac[1].size = val & 0xffff; + dev->dac[1].count = val >> 16; + break; + /* UART FIFO Register, Address 30H, 34H, 38H, 3CH, Memory Page 1110b, 1111b + Addressable as longword only */ + case 0xe: + case 0xf: + audiopci_log("[3C:%02X] dev->uart_fifo[%02X] = %08X\n", page, + ((page & 0x01) << 2) + ((frame >> 2) & 0x03), val); + dev->uart_fifo[((page & 0x01) << 2) + ((frame >> 2) & 0x03)] = val; + break; + + default: + break; + } + break; + + default: + break; } if (page == 0x0e || page == 0x0f) { - audiopci_log("Write frame = %02x, page = %02x, uart fifo = %08x, val = %02x\n", frame, page, dev->uart_fifo, val); + audiopci_log("Write frame = %02x, page = %02x, uart fifo = %08x, val = %02x\n", frame, page, dev->uart_fifo, val); } } - static uint8_t -es1371_inb(uint16_t port, void *p) +es1371_inb(uint16_t port, void *priv) { - es1371_t *dev = (es1371_t *) p; - uint8_t ret = 0xff; + es1371_t *dev = (es1371_t *) priv; + uint8_t ret = 0xff; switch (port & 0x3f) { - /* Interrupt/Chip Select Control Register, Address 00H - Addressable as byte, word, longword */ - case 0x00: - ret = dev->int_ctrl & 0xff; - break; - case 0x01: - ret = (dev->int_ctrl >> 8) & 0xff; - break; - case 0x02: - ret = (dev->int_ctrl >> 16) & 0x0f; - break; - case 0x03: - ret = ((dev->int_ctrl >> 24) & 0x03) | 0xfc; - break; + /* Interrupt/Chip Select Control Register, Address 00H + Addressable as byte, word, longword */ + case 0x00: + ret = dev->int_ctrl & 0xff; + break; + case 0x01: + ret = (dev->int_ctrl >> 8) & 0xff; + break; + case 0x02: + ret = (dev->int_ctrl >> 16) & 0x0f; + break; + case 0x03: + ret = ((dev->int_ctrl >> 24) & 0x03) | 0xfc; + break; - /* Interrupt/Chip Select Status Register, Address 04H - Addressable as longword only, but PCem implements byte access, which - must be for a reason */ - case 0x04: - ret = dev->int_status & 0xff; - audiopci_log("[R] STATUS 0- 7 = %02X\n", ret); - break; - case 0x05: - ret = (dev->int_status >> 8) & 0xff; - audiopci_log("[R] STATUS 8-15 = %02X\n", ret); - break; - case 0x06: - ret = (dev->int_status >> 16) & 0x0f; - audiopci_log("[R] STATUS 16-23 = %02X\n", ret); - break; - case 0x07: - ret = ((dev->int_status >> 24) & 0x03) | 0xfc; - audiopci_log("[R] STATUS 24-31 = %02X\n", ret); - break; + /* Interrupt/Chip Select Status Register, Address 04H + Addressable as longword only, but PCem implements byte access, which + must be for a reason */ + case 0x04: + ret = dev->int_status & 0xff; + audiopci_log("[R] STATUS 0- 7 = %02X\n", ret); + break; + case 0x05: + ret = (dev->int_status >> 8) & 0xff; + audiopci_log("[R] STATUS 8-15 = %02X\n", ret); + break; + case 0x06: + ret = (dev->int_status >> 16) & 0xff; + audiopci_log("[R] STATUS 16-23 = %02X\n", ret); + break; + case 0x07: + ret = (dev->int_status >> 24) & 0xff; + audiopci_log("[R] STATUS 24-31 = %02X\n", ret); + break; - /* UART Data Register, Address 08H - Addressable as byte only */ - case 0x08: - ret = dev->uart_data; - es1371_set_rx_irq(dev, 0); - audiopci_log("[R] UART DATA = %02X\n", ret); - break; + /* UART Data Register, Address 08H + Addressable as byte only */ + case 0x08: + ret = dev->uart_data; + es1371_set_rx_irq(dev, 0); + audiopci_log("[R] UART DATA = %02X\n", ret); + break; - /* UART Status Register, Address 09H - Addressable as byte only */ - case 0x09: - ret = dev->uart_status & 0x87; - audiopci_log("ES1371 UART Status = %02x\n", dev->uart_status); - break; + /* UART Status Register, Address 09H + Addressable as byte only */ + case 0x09: + ret = dev->uart_status & 0x87; + audiopci_log("ES1371 UART Status = %02x\n", dev->uart_status); + break; - /* UART Reserved Register, Address 0AH - Addressable as byte only */ - case 0x0a: - ret = dev->uart_res & 0x01; - audiopci_log("[R] UART RES = %02X\n", ret); - break; + /* UART Reserved Register, Address 0AH + Addressable as byte only */ + case 0x0a: + ret = dev->uart_res & 0x01; + audiopci_log("[R] UART RES = %02X\n", ret); + break; - /* Memory Page Register, Address 0CH - Addressable as byte, word, longword */ - case 0x0c: - ret = dev->mem_page; - break; - case 0x0d ... 0x0e: - ret = 0x00; - break; - - /* Legacy Control/Status Register, Address 18H - Addressable as byte, word, longword */ - case 0x18: - ret = dev->legacy_ctrl & 0xfd; - break; - case 0x19: - ret = ((dev->legacy_ctrl >> 8) & 0x07) | 0xf8; - break; - case 0x1a: - ret = dev->legacy_ctrl >> 16; - break; - case 0x1b: - ret = dev->legacy_ctrl >> 24; - break; + /* Memory Page Register, Address 0CH + Addressable as byte, word, longword */ + case 0x0c: + ret = dev->mem_page; + break; + case 0x0d ... 0x0e: + ret = 0x00; + break; - /* Serial Interface Control Register, Address 20H - Addressable as byte, word, longword */ - case 0x20: - ret = dev->si_cr & 0xff; - break; - case 0x21: - ret = dev->si_cr >> 8; - break; - case 0x22: - ret = (dev->si_cr >> 16) | 0x80; - break; - case 0x23: - ret = 0xff; - break; - - default: - audiopci_log("Bad es1371_inb: port=%04x\n", port); + /* Legacy Control/Status Register, Address 18H + Addressable as byte, word, longword */ + case 0x18: + ret = dev->legacy_ctrl & 0xfd; + break; + case 0x19: + ret = ((dev->legacy_ctrl >> 8) & 0x07) | 0xf8; + break; + case 0x1a: + ret = dev->legacy_ctrl >> 16; + break; + case 0x1b: + ret = dev->legacy_ctrl >> 24; + break; + + /* Serial Interface Control Register, Address 20H + Addressable as byte, word, longword */ + case 0x20: + ret = dev->si_cr & 0xff; + break; + case 0x21: + ret = dev->si_cr >> 8; + break; + case 0x22: + ret = (dev->si_cr >> 16) | 0x80; + break; + case 0x23: + ret = 0xff; + break; + + default: + audiopci_log("Bad es1371_inb: port=%04x\n", port); } audiopci_log("es1371_inb: port=%04x ret=%02x\n", port, ret); return ret; } - static uint16_t -es1371_inw(uint16_t port, void *p) +es1371_inw(uint16_t port, void *priv) { - es1371_t *dev = (es1371_t *) p; - uint16_t ret = 0xffff; + es1371_t *dev = (es1371_t *) priv; + uint16_t ret = 0xffff; switch (port & 0x3e) { - /* Interrupt/Chip Select Control Register, Address 00H - Addressable as byte, word, longword */ - case 0x00: - ret = dev->int_ctrl & 0xffff; - break; - case 0x02: - ret = ((dev->int_ctrl >> 16) & 0x030f) | 0xfc00; - break; + /* Interrupt/Chip Select Control Register, Address 00H + Addressable as byte, word, longword */ + case 0x00: + ret = dev->int_ctrl & 0xffff; + break; + case 0x02: + ret = ((dev->int_ctrl >> 16) & 0x030f) | 0xfc00; + break; - /* Memory Page Register, Address 0CH - Addressable as byte, word, longword */ - case 0x0c: - ret = dev->mem_page; - break; - case 0x0e: - ret = 0x0000; - break; + /* Memory Page Register, Address 0CH + Addressable as byte, word, longword */ + case 0x0c: + ret = dev->mem_page; + break; + case 0x0e: + ret = 0x0000; + break; - /* Legacy Control/Status Register, Address 18H - Addressable as byte, word, longword */ - case 0x18: - ret = (dev->legacy_ctrl & 0x07fd) | 0xf800; - break; - case 0x1a: - ret = dev->legacy_ctrl >> 16; - break; + /* Legacy Control/Status Register, Address 18H + Addressable as byte, word, longword */ + case 0x18: + ret = (dev->legacy_ctrl & 0x07fd) | 0xf800; + break; + case 0x1a: + ret = dev->legacy_ctrl >> 16; + break; - /* Serial Interface Control Register, Address 20H - Addressable as byte, word, longword */ - case 0x20: - ret = dev->si_cr & 0xffff; - break; - case 0x22: - ret = (dev->si_cr >> 16) | 0xff80; - break; + /* Serial Interface Control Register, Address 20H + Addressable as byte, word, longword */ + case 0x20: + ret = dev->si_cr & 0xffff; + break; + case 0x22: + ret = (dev->si_cr >> 16) | 0xff80; + break; - /* DAC1 Channel Sample Count Register, Address 24H - Addressable as word, longword */ - case 0x24: - ret = dev->dac[0].samp_ct; - break; - case 0x26: - ret = dev->dac[0].curr_samp_ct; - break; + /* DAC1 Channel Sample Count Register, Address 24H + Addressable as word, longword */ + case 0x24: + ret = dev->dac[0].samp_ct; + break; + case 0x26: + ret = dev->dac[0].curr_samp_ct; + break; - /* DAC2 Channel Sample Count Register, Address 28H - Addressable as word, longword */ - case 0x28: - ret = dev->dac[1].samp_ct; - break; - case 0x2a: - ret = dev->dac[1].curr_samp_ct; - break; + /* DAC2 Channel Sample Count Register, Address 28H + Addressable as word, longword */ + case 0x28: + ret = dev->dac[1].samp_ct; + break; + case 0x2a: + ret = dev->dac[1].curr_samp_ct; + break; - /* ADC Channel Sample Count Register, Address 2CH - Addressable as word, longword */ - case 0x2c: - ret = dev->adc.samp_ct; - break; - case 0x2e: - ret = dev->adc.curr_samp_ct; - break; + /* ADC Channel Sample Count Register, Address 2CH + Addressable as word, longword */ + case 0x2c: + ret = dev->adc.samp_ct; + break; + case 0x2e: + ret = dev->adc.curr_samp_ct; + break; - case 0x30: case 0x34: case 0x38: case 0x3c: - ret = es1371_read_frame_reg(dev, port & 0x3c, dev->mem_page) & 0xffff; - break; - case 0x32: case 0x36: case 0x3a: case 0x3e: - ret = es1371_read_frame_reg(dev, port & 0x3c, dev->mem_page) >> 16; - break; + case 0x30: + case 0x34: + case 0x38: + case 0x3c: + ret = es1371_read_frame_reg(dev, port & 0x3c, dev->mem_page) & 0xffff; + break; + case 0x32: + case 0x36: + case 0x3a: + case 0x3e: + ret = es1371_read_frame_reg(dev, port & 0x3c, dev->mem_page) >> 16; + break; + + default: + break; } - audiopci_log("es1371_inw: port=%04x ret=%04x\n", port, ret); + audiopci_log("es1371_inw: port=%04x ret=%04x\n", port, ret); return ret; } - static uint32_t -es1371_inl(uint16_t port, void *p) +es1371_inl(uint16_t port, void *priv) { - es1371_t *dev = (es1371_t *) p; - uint32_t ret = 0xffffffff; + es1371_t *dev = (es1371_t *) priv; + uint32_t ret = 0xffffffff; switch (port & 0x3c) { - /* Interrupt/Chip Select Control Register, Address 00H - Addressable as byte, word, longword */ - case 0x00: - ret = (dev->int_ctrl & 0x030fffff) | 0xfc000000; - break; + /* Interrupt/Chip Select Control Register, Address 00H + Addressable as byte, word, longword */ + case 0x00: + ret = (dev->int_ctrl & 0x030fffff) | 0xfc000000; + break; - /* Interrupt/Chip Select Status Register, Address 04H - Addressable as longword only */ - case 0x04: - ret = dev->int_status; - audiopci_log("[R] STATUS = %08X\n", ret); - break; + /* Interrupt/Chip Select Status Register, Address 04H + Addressable as longword only */ + case 0x04: + ret = dev->int_status; + audiopci_log("[R] STATUS = %08X\n", ret); + break; - /* Memory Page Register, Address 0CH - Addressable as byte, word, longword */ - case 0x0c: - ret = dev->mem_page; - break; + /* Memory Page Register, Address 0CH + Addressable as byte, word, longword */ + case 0x0c: + ret = dev->mem_page; + break; - /* Sample Rate Converter Interface Register, Address 10H - Addressable as longword only */ - case 0x10: - ret = dev->sr_cir & ~0xffff; - ret |= dev->sr_ram[dev->sr_cir >> 25]; - break; - - /* CODEC Read Register, Address 14H - Addressable as longword only */ - case 0x14: - ret = dev->codec_ctrl | CODEC_READY; - break; + /* Sample Rate Converter Interface Register, Address 10H + Addressable as longword only */ + case 0x10: + ret = dev->sr_cir & ~0xffff; + ret |= dev->sr_ram[dev->sr_cir >> 25]; + break; - /* Legacy Control/Status Register, Address 18H - Addressable as byte, word, longword */ - case 0x18: - ret = (dev->legacy_ctrl & 0xffff07fd) | 0x0000f800; - break; + /* CODEC Read Register, Address 14H + Addressable as longword only */ + case 0x14: + ret = dev->codec_ctrl | CODEC_READY; + break; - /* Serial Interface Control Register, Address 20H - Addressable as byte, word, longword */ - case 0x20: - ret = dev->si_cr | 0xff800000; - break; + /* Legacy Control/Status Register, Address 18H + Addressable as byte, word, longword */ + case 0x18: + ret = (dev->legacy_ctrl & 0xffff07fd) | 0x0000f800; + break; - /* DAC1 Channel Sample Count Register, Address 24H - Addressable as word, longword */ - case 0x24: - ret = dev->dac[0].samp_ct | (((uint32_t) dev->dac[0].curr_samp_ct) << 16); - break; + /* Serial Interface Control Register, Address 20H + Addressable as byte, word, longword */ + case 0x20: + ret = dev->si_cr | 0xff800000; + break; - /* DAC2 Channel Sample Count Register, Address 28H - Addressable as word, longword */ - case 0x28: - ret = dev->dac[1].samp_ct | (((uint32_t) dev->dac[1].curr_samp_ct) << 16); - break; + /* DAC1 Channel Sample Count Register, Address 24H + Addressable as word, longword */ + case 0x24: + ret = dev->dac[0].samp_ct | (((uint32_t) dev->dac[0].curr_samp_ct) << 16); + break; - /* ADC Channel Sample Count Register, Address 2CH - Addressable as word, longword */ - case 0x2c: - ret = dev->adc.samp_ct | (((uint32_t) dev->adc.curr_samp_ct) << 16); - break; + /* DAC2 Channel Sample Count Register, Address 28H + Addressable as word, longword */ + case 0x28: + ret = dev->dac[1].samp_ct | (((uint32_t) dev->dac[1].curr_samp_ct) << 16); + break; - case 0x30: case 0x34: case 0x38: case 0x3c: - ret = es1371_read_frame_reg(dev, port & 0x3c, dev->mem_page); - break; + /* ADC Channel Sample Count Register, Address 2CH + Addressable as word, longword */ + case 0x2c: + ret = dev->adc.samp_ct | (((uint32_t) dev->adc.curr_samp_ct) << 16); + break; + + case 0x30: + case 0x34: + case 0x38: + case 0x3c: + ret = es1371_read_frame_reg(dev, port & 0x3c, dev->mem_page); + break; + + default: + break; } audiopci_log("es1371_inl: port=%04x ret=%08x\n", port, ret); return ret; } - static void -es1371_outb(uint16_t port, uint8_t val, void *p) +es1371_outb(uint16_t port, uint8_t val, void *priv) { - es1371_t *dev = (es1371_t *)p; - uint32_t old_legacy_ctrl; + es1371_t *dev = (es1371_t *) priv; + uint32_t old_legacy_ctrl; audiopci_log("es1371_outb: port=%04x val=%02x\n", port, val); switch (port & 0x3f) { - /* Interrupt/Chip Select Control Register, Address 00H - Addressable as byte, word, longword */ - case 0x00: - if (!(dev->int_ctrl & INT_DAC1_EN) && (val & INT_DAC1_EN)) { - dev->dac[0].addr = dev->dac[0].addr_latch; - dev->dac[0].buffer_pos = 0; - dev->dac[0].buffer_pos_end = 0; - es1371_fetch(dev, 0); - } - if (!(dev->int_ctrl & INT_DAC2_EN) && (val & INT_DAC2_EN)) { - dev->dac[1].addr = dev->dac[1].addr_latch; - dev->dac[1].buffer_pos = 0; - dev->dac[1].buffer_pos_end = 0; - es1371_fetch(dev, 1); - } - dev->int_ctrl = (dev->int_ctrl & 0xffffff00) | val; - break; - case 0x01: - dev->int_ctrl = (dev->int_ctrl & 0xffff00ff) | (val << 8); - break; - case 0x02: - dev->int_ctrl = (dev->int_ctrl & 0xff00ffff) | (val << 16); - break; - case 0x03: - dev->int_ctrl = (dev->int_ctrl & 0x00ffffff) | (val << 24); - gameport_remap(dev->gameport, 0x200 | ((val & 0x03) << 3)); - break; + /* Interrupt/Chip Select Control Register, Address 00H + Addressable as byte, word, longword */ + case 0x00: + if (!(dev->int_ctrl & INT_DAC1_EN) && (val & INT_DAC1_EN)) { + dev->dac[0].addr = dev->dac[0].addr_latch; + dev->dac[0].buffer_pos = 0; + dev->dac[0].buffer_pos_end = 0; + es1371_fetch(dev, 0); + } + if (!(dev->int_ctrl & INT_DAC2_EN) && (val & INT_DAC2_EN)) { + dev->dac[1].addr = dev->dac[1].addr_latch; + dev->dac[1].buffer_pos = 0; + dev->dac[1].buffer_pos_end = 0; + es1371_fetch(dev, 1); + } + dev->int_ctrl = (dev->int_ctrl & 0xffffff00) | val; + break; + case 0x01: + dev->int_ctrl = (dev->int_ctrl & 0xffff00ff) | (val << 8); + break; + case 0x02: + dev->int_ctrl = (dev->int_ctrl & 0xff00ffff) | (val << 16); + break; + case 0x03: + dev->int_ctrl = (dev->int_ctrl & 0x00ffffff) | (val << 24); + gameport_remap(dev->gameport, 0x200 | ((val & 0x03) << 3)); + break; - /* UART Data Register, Address 08H - Addressable as byte only */ - case 0x08: - audiopci_log("MIDI data = %02x\n", val); - /* TX does not use FIFO. */ - midi_raw_out_byte(val); - es1371_set_tx_irq(dev, 1); - break; + /* UART Data Register, Address 08H + Addressable as byte only */ + case 0x08: + audiopci_log("MIDI data = %02x\n", val); + /* TX does not use FIFO. */ + midi_raw_out_byte(val); + es1371_set_tx_irq(dev, 1); + break; - /* UART Control Register, Address 09H - Addressable as byte only */ - case 0x09: - audiopci_log("[W] UART CTRL = %02X\n", val); - dev->uart_ctrl = val & 0xe3; - - if ((val & 0x03) == 0x03) { - /* Reset TX */ - es1371_set_tx_irq(dev, 1); + /* UART Control Register, Address 09H + Addressable as byte only */ + case 0x09: + audiopci_log("[W] UART CTRL = %02X\n", val); + dev->uart_ctrl = val & 0xe3; - /* Software reset */ - es1371_reset_fifo(dev); - } else { - es1371_set_tx_irq(dev, 1); + if ((val & 0x03) == 0x03) { + /* Reset TX */ + es1371_set_tx_irq(dev, 1); - es1371_update_tx_irq(dev); - es1371_update_rx_irq(dev); - } - break; + /* Software reset */ + es1371_reset_fifo(dev); + } else { + es1371_set_tx_irq(dev, 1); - /* UART Reserved Register, Address 0AH - Addressable as byte only */ - case 0x0a: - audiopci_log("[W] UART RES = %02X\n", val); - dev->uart_res = val & 0x01; - break; + es1371_update_tx_irq(dev); + es1371_update_rx_irq(dev); + } + break; - /* Memory Page Register, Address 0CH - Addressable as byte, word, longword */ - case 0x0c: - dev->mem_page = val & 0xf; - break; - case 0x0d ... 0x0f: - break; + /* UART Reserved Register, Address 0AH + Addressable as byte only */ + case 0x0a: + audiopci_log("[W] UART RES = %02X\n", val); + dev->uart_res = val & 0x01; + break; - /* Legacy Control/Status Register, Address 18H - Addressable as byte, word, longword */ - case 0x18: - dev->legacy_ctrl |= LEGACY_INT; - break; - case 0x1a: - old_legacy_ctrl = dev->legacy_ctrl; - dev->legacy_ctrl = (dev->legacy_ctrl & 0xff00ffff) | (val << 16); - update_legacy(dev, old_legacy_ctrl); - break; - case 0x1b: - old_legacy_ctrl = dev->legacy_ctrl; - dev->legacy_ctrl = (dev->legacy_ctrl & 0x00ffffff) | (val << 24); - es1371_update_irqs(dev); - update_legacy(dev, old_legacy_ctrl); - break; + /* Memory Page Register, Address 0CH + Addressable as byte, word, longword */ + case 0x0c: + dev->mem_page = val & 0xf; + break; + case 0x0d ... 0x0f: + break; - /* Serial Interface Control Register, Address 20H - Addressable as byte, word, longword */ - case 0x20: - dev->si_cr = (dev->si_cr & 0xffffff00) | val; - break; - case 0x21: - dev->si_cr = (dev->si_cr & 0xffff00ff) | (val << 8); - if (!(dev->si_cr & SI_P1_INTR_EN)) - dev->int_status &= ~INT_STATUS_DAC1; - if (!(dev->si_cr & SI_P2_INTR_EN)) - dev->int_status &= ~INT_STATUS_DAC2; - es1371_update_irqs(dev); - break; - case 0x22: - dev->si_cr = (dev->si_cr & 0xff80ffff) | ((val & 0x7f) << 16); - break; + /* Legacy Control/Status Register, Address 18H + Addressable as byte, word, longword */ + case 0x18: + dev->legacy_ctrl |= LEGACY_INT; + break; + case 0x1a: + old_legacy_ctrl = dev->legacy_ctrl; + dev->legacy_ctrl = (dev->legacy_ctrl & 0xff00ffff) | (val << 16); + update_legacy(dev, old_legacy_ctrl); + break; + case 0x1b: + old_legacy_ctrl = dev->legacy_ctrl; + dev->legacy_ctrl = (dev->legacy_ctrl & 0x00ffffff) | (val << 24); + es1371_update_irqs(dev); + update_legacy(dev, old_legacy_ctrl); + break; - default: - audiopci_log("Bad es1371_outb: port=%04x val=%02x\n", port, val); + /* Serial Interface Control Register, Address 20H + Addressable as byte, word, longword */ + case 0x20: + dev->si_cr = (dev->si_cr & 0xffffff00) | val; + break; + case 0x21: + dev->si_cr = (dev->si_cr & 0xffff00ff) | (val << 8); + if (!(dev->si_cr & SI_P1_INTR_EN)) + dev->int_status &= ~INT_STATUS_DAC1; + if (!(dev->si_cr & SI_P2_INTR_EN)) + dev->int_status &= ~INT_STATUS_DAC2; + es1371_update_irqs(dev); + break; + case 0x22: + dev->si_cr = (dev->si_cr & 0xff80ffff) | ((val & 0x7f) << 16); + break; + + default: + audiopci_log("Bad es1371_outb: port=%04x val=%02x\n", port, val); } } - static void -es1371_outw(uint16_t port, uint16_t val, void *p) +es1371_outw(uint16_t port, uint16_t val, void *priv) { - es1371_t *dev = (es1371_t *)p; - uint32_t old_legacy_ctrl; + es1371_t *dev = (es1371_t *) priv; + uint32_t old_legacy_ctrl; switch (port & 0x3f) { - /* Interrupt/Chip Select Control Register, Address 00H - Addressable as byte, word, longword */ - case 0x00: - if (!(dev->int_ctrl & INT_DAC1_EN) && (val & INT_DAC1_EN)) { - dev->dac[0].addr = dev->dac[0].addr_latch; - dev->dac[0].buffer_pos = 0; - dev->dac[0].buffer_pos_end = 0; - es1371_fetch(dev, 0); - } - if (!(dev->int_ctrl & INT_DAC2_EN) && (val & INT_DAC2_EN)) { - dev->dac[1].addr = dev->dac[1].addr_latch; - dev->dac[1].buffer_pos = 0; - dev->dac[1].buffer_pos_end = 0; - es1371_fetch(dev, 1); - } - dev->int_ctrl = (dev->int_ctrl & 0xffff0000) | val; - break; - case 0x02: - dev->int_ctrl = (dev->int_ctrl & 0x0000ffff) | (val << 16); - gameport_remap(dev->gameport, 0x200 | ((val & 0x0300) >> 5)); - break; + /* Interrupt/Chip Select Control Register, Address 00H + Addressable as byte, word, longword */ + case 0x00: + if (!(dev->int_ctrl & INT_DAC1_EN) && (val & INT_DAC1_EN)) { + dev->dac[0].addr = dev->dac[0].addr_latch; + dev->dac[0].buffer_pos = 0; + dev->dac[0].buffer_pos_end = 0; + es1371_fetch(dev, 0); + } + if (!(dev->int_ctrl & INT_DAC2_EN) && (val & INT_DAC2_EN)) { + dev->dac[1].addr = dev->dac[1].addr_latch; + dev->dac[1].buffer_pos = 0; + dev->dac[1].buffer_pos_end = 0; + es1371_fetch(dev, 1); + } + dev->int_ctrl = (dev->int_ctrl & 0xffff0000) | val; + break; + case 0x02: + dev->int_ctrl = (dev->int_ctrl & 0x0000ffff) | (val << 16); + gameport_remap(dev->gameport, 0x200 | ((val & 0x0300) >> 5)); + break; - /* Memory Page Register, Address 0CH - Addressable as byte, word, longword */ - case 0x0c: - dev->mem_page = val & 0xf; - break; - case 0x0e: - break; + /* Memory Page Register, Address 0CH + Addressable as byte, word, longword */ + case 0x0c: + dev->mem_page = val & 0xf; + break; + case 0x0e: + break; - /* Legacy Control/Status Register, Address 18H - Addressable as byte, word, longword */ - case 0x18: - dev->legacy_ctrl |= LEGACY_INT; - break; - case 0x1a: - old_legacy_ctrl = dev->legacy_ctrl; - dev->legacy_ctrl = (dev->legacy_ctrl & 0x0000ffff) | (val << 16); - es1371_update_irqs(dev); - update_legacy(dev, old_legacy_ctrl); - break; + /* Legacy Control/Status Register, Address 18H + Addressable as byte, word, longword */ + case 0x18: + dev->legacy_ctrl |= LEGACY_INT; + break; + case 0x1a: + old_legacy_ctrl = dev->legacy_ctrl; + dev->legacy_ctrl = (dev->legacy_ctrl & 0x0000ffff) | (val << 16); + es1371_update_irqs(dev); + update_legacy(dev, old_legacy_ctrl); + break; - /* Serial Interface Control Register, Address 20H - Addressable as byte, word, longword */ - case 0x20: - dev->si_cr = (dev->si_cr & 0xffff0000) | val; - if (!(dev->si_cr & SI_P1_INTR_EN)) - dev->int_status &= ~INT_STATUS_DAC1; - if (!(dev->si_cr & SI_P2_INTR_EN)) - dev->int_status &= ~INT_STATUS_DAC2; - es1371_update_irqs(dev); - break; - case 0x22: - dev->si_cr = (dev->si_cr & 0xff80ffff) | ((val & 0x007f) << 16); - break; + /* Serial Interface Control Register, Address 20H + Addressable as byte, word, longword */ + case 0x20: + dev->si_cr = (dev->si_cr & 0xffff0000) | val; + if (!(dev->si_cr & SI_P1_INTR_EN)) + dev->int_status &= ~INT_STATUS_DAC1; + if (!(dev->si_cr & SI_P2_INTR_EN)) + dev->int_status &= ~INT_STATUS_DAC2; + es1371_update_irqs(dev); + break; + case 0x22: + dev->si_cr = (dev->si_cr & 0xff80ffff) | ((val & 0x007f) << 16); + break; - /* DAC1 Channel Sample Count Register, Address 24H - Addressable as word, longword */ - case 0x24: - dev->dac[0].samp_ct = val; - break; + /* DAC1 Channel Sample Count Register, Address 24H + Addressable as word, longword */ + case 0x24: + dev->dac[0].samp_ct = val; + break; - /* DAC2 Channel Sample Count Register, Address 28H - Addressable as word, longword */ - case 0x28: - dev->dac[1].samp_ct = val; - break; + /* DAC2 Channel Sample Count Register, Address 28H + Addressable as word, longword */ + case 0x28: + dev->dac[1].samp_ct = val; + break; - /* ADC Channel Sample Count Register, Address 2CH - Addressable as word, longword */ - case 0x2c: - dev->adc.samp_ct = val; - break; + /* ADC Channel Sample Count Register, Address 2CH + Addressable as word, longword */ + case 0x2c: + dev->adc.samp_ct = val; + break; + + default: + break; } } - static void -es1371_outl(uint16_t port, uint32_t val, void *p) +es1371_outl(uint16_t port, uint32_t val, void *priv) { - es1371_t *dev = (es1371_t *)p; - uint32_t old_legacy_ctrl; + es1371_t *dev = (es1371_t *) priv; + uint32_t old_legacy_ctrl; audiopci_log("es1371_outl: port=%04x val=%08x\n", port, val); switch (port & 0x3f) { - /* Interrupt/Chip Select Control Register, Address 00H - Addressable as byte, word, longword */ - case 0x00: - if (!(dev->int_ctrl & INT_DAC1_EN) && (val & INT_DAC1_EN)) { - dev->dac[0].addr = dev->dac[0].addr_latch; - dev->dac[0].buffer_pos = 0; - dev->dac[0].buffer_pos_end = 0; - es1371_fetch(dev, 0); - } - if (!(dev->int_ctrl & INT_DAC2_EN) && (val & INT_DAC2_EN)) { - dev->dac[1].addr = dev->dac[1].addr_latch; - dev->dac[1].buffer_pos = 0; - dev->dac[1].buffer_pos_end = 0; - es1371_fetch(dev, 1); - } - dev->int_ctrl = val; - gameport_remap(dev->gameport, 0x200 | ((val & 0x03000000) >> 21)); - break; + /* Interrupt/Chip Select Control Register, Address 00H + Addressable as byte, word, longword */ + case 0x00: + if (!(dev->int_ctrl & INT_DAC1_EN) && (val & INT_DAC1_EN)) { + dev->dac[0].addr = dev->dac[0].addr_latch; + dev->dac[0].buffer_pos = 0; + dev->dac[0].buffer_pos_end = 0; + es1371_fetch(dev, 0); + } + if (!(dev->int_ctrl & INT_DAC2_EN) && (val & INT_DAC2_EN)) { + dev->dac[1].addr = dev->dac[1].addr_latch; + dev->dac[1].buffer_pos = 0; + dev->dac[1].buffer_pos_end = 0; + es1371_fetch(dev, 1); + } + dev->int_ctrl = val; + gameport_remap(dev->gameport, 0x200 | ((val & 0x03000000) >> 21)); + break; - /* Interrupt/Chip Select Status Register, Address 04H - Addressable as longword only */ - case 0x04: - audiopci_log("[W] STATUS = %08X\n", val); - break; + /* Interrupt/Chip Select Status Register, Address 04H + Addressable as longword only */ + case 0x04: + audiopci_log("[W] STATUS = %08X\n", val); + break; - /* Memory Page Register, Address 0CH - Addressable as byte, word, longword */ - case 0x0c: - dev->mem_page = val & 0xf; - break; + /* Memory Page Register, Address 0CH + Addressable as byte, word, longword */ + case 0x0c: + dev->mem_page = val & 0xf; + break; - /* Sample Rate Converter Interface Register, Address 10H - Addressable as longword only */ - case 0x10: - dev->sr_cir = val & 0xfff8ffff; /*Bits 16 to 18 are undefined*/ - if (dev->sr_cir & SRC_RAM_WE) { - dev->sr_ram[dev->sr_cir >> 25] = val & 0xffff; - switch (dev->sr_cir >> 25) { - case 0x71: - dev->dac[0].vf = (dev->dac[0].vf & ~0x1f8000) | ((val & 0xfc00) << 5); - dev->dac[0].ac = (dev->dac[0].ac & ~0x7f8000) | ((val & 0x00ff) << 15); - dev->dac[0].f_pos = 0; - break; - case 0x72: - dev->dac[0].ac = (dev->dac[0].ac & ~0x7fff) | (val & 0x7fff); - break; - case 0x73: - dev->dac[0].vf = (dev->dac[0].vf & ~0x7fff) | (val & 0x7fff); - break; + /* Sample Rate Converter Interface Register, Address 10H + Addressable as longword only */ + case 0x10: + dev->sr_cir = val & 0xfff8ffff; /*Bits 16 to 18 are undefined*/ + if (dev->sr_cir & SRC_RAM_WE) { + dev->sr_ram[dev->sr_cir >> 25] = val & 0xffff; + switch (dev->sr_cir >> 25) { + case 0x71: + dev->dac[0].vf = (dev->dac[0].vf & ~0x1f8000) | ((val & 0xfc00) << 5); + dev->dac[0].ac = (dev->dac[0].ac & ~0x7f8000) | ((val & 0x00ff) << 15); + dev->dac[0].f_pos = 0; + break; + case 0x72: + dev->dac[0].ac = (dev->dac[0].ac & ~0x7fff) | (val & 0x7fff); + break; + case 0x73: + dev->dac[0].vf = (dev->dac[0].vf & ~0x7fff) | (val & 0x7fff); + break; - case 0x75: - dev->dac[1].vf = (dev->dac[1].vf & ~0x1f8000) | ((val & 0xfc00) << 5); - dev->dac[1].ac = (dev->dac[1].ac & ~0x7f8000) | ((val & 0x00ff) << 15); - dev->dac[1].f_pos = 0; - break; - case 0x76: - dev->dac[1].ac = (dev->dac[1].ac & ~0x7fff) | (val & 0x7fff); - break; - case 0x77: - dev->dac[1].vf = (dev->dac[1].vf & ~0x7fff) | (val & 0x7fff); - break; + case 0x75: + dev->dac[1].vf = (dev->dac[1].vf & ~0x1f8000) | ((val & 0xfc00) << 5); + dev->dac[1].ac = (dev->dac[1].ac & ~0x7f8000) | ((val & 0x00ff) << 15); + dev->dac[1].f_pos = 0; + break; + case 0x76: + dev->dac[1].ac = (dev->dac[1].ac & ~0x7fff) | (val & 0x7fff); + break; + case 0x77: + dev->dac[1].vf = (dev->dac[1].vf & ~0x7fff) | (val & 0x7fff); + break; - case 0x7c: - dev->dac[0].vol_l = (int32_t)(int16_t)(val & 0xffff); - break; - case 0x7d: - dev->dac[0].vol_r = (int32_t)(int16_t)(val & 0xffff); - break; - case 0x7e: - dev->dac[1].vol_l = (int32_t)(int16_t)(val & 0xffff); - break; - case 0x7f: - dev->dac[1].vol_r = (int32_t)(int16_t)(val & 0xffff); - break; - } - } - break; + case 0x7c: + dev->dac[0].vol_l = (int32_t) (int16_t) (val & 0xffff); + break; + case 0x7d: + dev->dac[0].vol_r = (int32_t) (int16_t) (val & 0xffff); + break; + case 0x7e: + dev->dac[1].vol_l = (int32_t) (int16_t) (val & 0xffff); + break; + case 0x7f: + dev->dac[1].vol_r = (int32_t) (int16_t) (val & 0xffff); + break; - /* CODEC Write Register, Address 14H - Addressable as longword only */ - case 0x14: - if (val & CODEC_READ) { - dev->codec_ctrl &= 0x00ff0000; - dev->codec_ctrl |= ac97_codec_readw(dev->codec, val >> 16); - } else { - dev->codec_ctrl = val & 0x00ffffff; - ac97_codec_writew(dev->codec, val >> 16, val); + default: + break; + } + } + break; - ac97_codec_getattn(dev->codec, 0x02, &dev->master_vol_l, &dev->master_vol_r); - ac97_codec_getattn(dev->codec, 0x18, &dev->pcm_vol_l, &dev->pcm_vol_r); - ac97_codec_getattn(dev->codec, 0x12, &dev->cd_vol_l, &dev->cd_vol_r); - } - break; + /* CODEC Write Register, Address 14H + Addressable as longword only */ + case 0x14: + if (val & CODEC_READ) { + dev->codec_ctrl &= 0x00ff0000; + dev->codec_ctrl |= ac97_codec_readw(dev->codec, val >> 16); + } else { + dev->codec_ctrl = val & 0x00ffffff; + ac97_codec_writew(dev->codec, val >> 16, val); - /* Legacy Control/Status Register, Address 18H - Addressable as byte, word, longword */ - case 0x18: - old_legacy_ctrl = dev->legacy_ctrl; - dev->legacy_ctrl = (dev->legacy_ctrl & 0x0000ffff) | (val & 0xffff0000); - dev->legacy_ctrl |= LEGACY_INT; - es1371_update_irqs(dev); - update_legacy(dev, old_legacy_ctrl); - break; + ac97_codec_getattn(dev->codec, 0x02, &dev->master_vol_l, &dev->master_vol_r); + ac97_codec_getattn(dev->codec, 0x18, &dev->pcm_vol_l, &dev->pcm_vol_r); + ac97_codec_getattn(dev->codec, 0x12, &dev->cd_vol_l, &dev->cd_vol_r); + } + break; - /* Serial Interface Control Register, Address 20H - Addressable as byte, word, longword */ - case 0x20: - dev->si_cr = (val & 0x007fffff) | 0xff800000; - if (!(dev->si_cr & SI_P1_INTR_EN)) - dev->int_status &= ~INT_STATUS_DAC1; - if (!(dev->si_cr & SI_P2_INTR_EN)) - dev->int_status &= ~INT_STATUS_DAC2; - es1371_update_irqs(dev); - break; + /* Legacy Control/Status Register, Address 18H + Addressable as byte, word, longword */ + case 0x18: + old_legacy_ctrl = dev->legacy_ctrl; + dev->legacy_ctrl = (dev->legacy_ctrl & 0x0000ffff) | (val & 0xffff0000); + dev->legacy_ctrl |= LEGACY_INT; + es1371_update_irqs(dev); + update_legacy(dev, old_legacy_ctrl); + break; - /* DAC1 Channel Sample Count Register, Address 24H - Addressable as word, longword */ - case 0x24: - dev->dac[0].samp_ct = val & 0xffff; - break; + /* Serial Interface Control Register, Address 20H + Addressable as byte, word, longword */ + case 0x20: + dev->si_cr = (val & 0x007fffff) | 0xff800000; + if (!(dev->si_cr & SI_P1_INTR_EN)) + dev->int_status &= ~INT_STATUS_DAC1; + if (!(dev->si_cr & SI_P2_INTR_EN)) + dev->int_status &= ~INT_STATUS_DAC2; + es1371_update_irqs(dev); + break; - /* DAC2 Channel Sample Count Register, Address 28H - Addressable as word, longword */ - case 0x28: - dev->dac[1].samp_ct = val & 0xffff; - break; + /* DAC1 Channel Sample Count Register, Address 24H + Addressable as word, longword */ + case 0x24: + dev->dac[0].samp_ct = val & 0xffff; + break; - /* ADC Channel Sample Count Register, Address 2CH - Addressable as word, longword */ - case 0x2c: - dev->adc.samp_ct = val & 0xffff; - break; + /* DAC2 Channel Sample Count Register, Address 28H + Addressable as word, longword */ + case 0x28: + dev->dac[1].samp_ct = val & 0xffff; + break; - case 0x30: case 0x34: case 0x38: case 0x3c: - es1371_write_frame_reg(dev, port & 0x3c, dev->mem_page, val); - break; + /* ADC Channel Sample Count Register, Address 2CH + Addressable as word, longword */ + case 0x2c: + dev->adc.samp_ct = val & 0xffff; + break; + + case 0x30: + case 0x34: + case 0x38: + case 0x3c: + es1371_write_frame_reg(dev, port & 0x3c, dev->mem_page, val); + break; + + default: + break; } } - static void capture_event(es1371_t *dev, int type, int rw, uint16_t port) { dev->legacy_ctrl &= ~(LEGACY_EVENT_MASK | LEGACY_EVENT_ADDR_MASK); dev->legacy_ctrl |= type; - if (rw) - dev->legacy_ctrl |= LEGACY_EVENT_TYPE_RW; + if (rw) + dev->legacy_ctrl |= LEGACY_EVENT_TYPE_RW; else - dev->legacy_ctrl &= ~LEGACY_EVENT_TYPE_RW; + dev->legacy_ctrl &= ~LEGACY_EVENT_TYPE_RW; dev->legacy_ctrl |= ((port << LEGACY_EVENT_ADDR_SHIFT) & LEGACY_EVENT_ADDR_MASK); dev->legacy_ctrl &= ~LEGACY_INT; - nmi = 1; + nmi_raise(); } - static void -capture_write_sscape(uint16_t port, uint8_t val, void *p) +capture_write_sscape(uint16_t port, UNUSED(uint8_t val), void *priv) { - capture_event(p, LEGACY_EVENT_SSCAPE, 1, port); + capture_event(priv, LEGACY_EVENT_SSCAPE, 1, port); } - static void -capture_write_codec(uint16_t port, uint8_t val, void *p) +capture_write_codec(uint16_t port, UNUSED(uint8_t val), void *priv) { - capture_event(p, LEGACY_EVENT_CODEC, 1, port); + capture_event(priv, LEGACY_EVENT_CODEC, 1, port); } - static void -capture_write_sb(uint16_t port, uint8_t val, void *p) +capture_write_sb(uint16_t port, UNUSED(uint8_t val), void *priv) { - capture_event(p, LEGACY_EVENT_SB, 1, port); + capture_event(priv, LEGACY_EVENT_SB, 1, port); } - static void -capture_write_adlib(uint16_t port, uint8_t val, void *p) +capture_write_adlib(uint16_t port, UNUSED(uint8_t val), void *priv) { - capture_event(p, LEGACY_EVENT_ADLIB, 1, port); + capture_event(priv, LEGACY_EVENT_ADLIB, 1, port); } - static void -capture_write_master_pic(uint16_t port, uint8_t val, void *p) +capture_write_master_pic(uint16_t port, UNUSED(uint8_t val), void *priv) { - capture_event(p, LEGACY_EVENT_MASTER_PIC, 1, port); + capture_event(priv, LEGACY_EVENT_MASTER_PIC, 1, port); } - static void -capture_write_master_dma(uint16_t port, uint8_t val, void *p) +capture_write_master_dma(uint16_t port, UNUSED(uint8_t val), void *priv) { - capture_event(p, LEGACY_EVENT_MASTER_DMA, 1, port); + capture_event(priv, LEGACY_EVENT_MASTER_DMA, 1, port); } - static void -capture_write_slave_pic(uint16_t port, uint8_t val, void *p) +capture_write_slave_pic(uint16_t port, UNUSED(uint8_t val), void *priv) { - capture_event(p, LEGACY_EVENT_SLAVE_PIC, 1, port); + capture_event(priv, LEGACY_EVENT_SLAVE_PIC, 1, port); } - static void -capture_write_slave_dma(uint16_t port, uint8_t val, void *p) +capture_write_slave_dma(uint16_t port, UNUSED(uint8_t val), void *priv) { - capture_event(p, LEGACY_EVENT_SLAVE_DMA, 1, port); + capture_event(priv, LEGACY_EVENT_SLAVE_DMA, 1, port); } - static uint8_t -capture_read_sscape(uint16_t port, void *p) +capture_read_sscape(uint16_t port, void *priv) { - capture_event(p, LEGACY_EVENT_SSCAPE, 0, port); + capture_event(priv, LEGACY_EVENT_SSCAPE, 0, port); return 0xff; } - static uint8_t -capture_read_codec(uint16_t port, void *p) +capture_read_codec(uint16_t port, void *priv) { - capture_event(p, LEGACY_EVENT_CODEC, 0, port); + capture_event(priv, LEGACY_EVENT_CODEC, 0, port); return 0xff; } - static uint8_t -capture_read_sb(uint16_t port, void *p) +capture_read_sb(uint16_t port, void *priv) { - capture_event(p, LEGACY_EVENT_SB, 0, port); + capture_event(priv, LEGACY_EVENT_SB, 0, port); return 0xff; } - static uint8_t -capture_read_adlib(uint16_t port, void *p) +capture_read_adlib(uint16_t port, void *priv) { - capture_event(p, LEGACY_EVENT_ADLIB, 0, port); + capture_event(priv, LEGACY_EVENT_ADLIB, 0, port); return 0xff; } - static uint8_t -capture_read_master_pic(uint16_t port, void *p) +capture_read_master_pic(uint16_t port, void *priv) { - capture_event(p, LEGACY_EVENT_MASTER_PIC, 0, port); + capture_event(priv, LEGACY_EVENT_MASTER_PIC, 0, port); return 0xff; } - static uint8_t -capture_read_master_dma(uint16_t port, void *p) +capture_read_master_dma(uint16_t port, void *priv) { - capture_event(p, LEGACY_EVENT_MASTER_DMA, 0, port); + capture_event(priv, LEGACY_EVENT_MASTER_DMA, 0, port); return 0xff; } - static uint8_t -capture_read_slave_pic(uint16_t port, void *p) +capture_read_slave_pic(uint16_t port, void *priv) { - capture_event(p, LEGACY_EVENT_SLAVE_PIC, 0, port); + capture_event(priv, LEGACY_EVENT_SLAVE_PIC, 0, port); return 0xff; } - static uint8_t -capture_read_slave_dma(uint16_t port, void *p) +capture_read_slave_dma(uint16_t port, void *priv) { - capture_event(p, LEGACY_EVENT_SLAVE_DMA, 0, port); + capture_event(priv, LEGACY_EVENT_SLAVE_DMA, 0, port); return 0xff; } - static void update_legacy(es1371_t *dev, uint32_t old_legacy_ctrl) { if (old_legacy_ctrl & LEGACY_CAPTURE_SSCAPE) { - switch ((old_legacy_ctrl >> LEGACY_SSCAPE_ADDR_SHIFT) & 3) { - case 0: - io_removehandler(0x0320, 0x0008, - capture_read_sscape, NULL, NULL, - capture_write_sscape, NULL, NULL, dev); - break; - case 1: - io_removehandler(0x0330, 0x0008, - capture_read_sscape, NULL, NULL, - capture_write_sscape, NULL, NULL, dev); - break; - case 2: - io_removehandler(0x0340, 0x0008, - capture_read_sscape, NULL ,NULL, - capture_write_sscape, NULL, NULL, dev); - break; - case 3: - io_removehandler(0x0350, 0x0008, - capture_read_sscape, NULL, NULL, - capture_write_sscape, NULL, NULL, dev); - break; - } + switch ((old_legacy_ctrl >> LEGACY_SSCAPE_ADDR_SHIFT) & 3) { + case 0: + io_removehandler(0x0320, 0x0008, + capture_read_sscape, NULL, NULL, + capture_write_sscape, NULL, NULL, dev); + break; + case 1: + io_removehandler(0x0330, 0x0008, + capture_read_sscape, NULL, NULL, + capture_write_sscape, NULL, NULL, dev); + break; + case 2: + io_removehandler(0x0340, 0x0008, + capture_read_sscape, NULL, NULL, + capture_write_sscape, NULL, NULL, dev); + break; + case 3: + io_removehandler(0x0350, 0x0008, + capture_read_sscape, NULL, NULL, + capture_write_sscape, NULL, NULL, dev); + break; + + default: + break; + } } if (old_legacy_ctrl & LEGACY_CAPTURE_CODEC) { - switch ((old_legacy_ctrl >> LEGACY_CODEC_ADDR_SHIFT) & 3) { - case 0: - io_removehandler(0x0530, 0x0008, - capture_read_codec, NULL, NULL, - capture_write_codec, NULL, NULL, dev); - break; - case 2: - io_removehandler(0x0e80, 0x0008, - capture_read_codec, NULL, NULL, - capture_write_codec,NULL,NULL, dev); - break; - case 3: - io_removehandler(0x0f40, 0x0008, - capture_read_codec, NULL, NULL, - capture_write_codec, NULL, NULL, dev); - break; - } + switch ((old_legacy_ctrl >> LEGACY_CODEC_ADDR_SHIFT) & 3) { + case 0: + io_removehandler(0x0530, 0x0008, + capture_read_codec, NULL, NULL, + capture_write_codec, NULL, NULL, dev); + break; + case 2: + io_removehandler(0x0e80, 0x0008, + capture_read_codec, NULL, NULL, + capture_write_codec, NULL, NULL, dev); + break; + case 3: + io_removehandler(0x0f40, 0x0008, + capture_read_codec, NULL, NULL, + capture_write_codec, NULL, NULL, dev); + break; + + default: + break; + } } if (old_legacy_ctrl & LEGACY_CAPTURE_SB) { - if (!(old_legacy_ctrl & LEGACY_SB_ADDR)) { - io_removehandler(0x0220, 0x0010, - capture_read_sb, NULL, NULL, - capture_write_sb, NULL, NULL, dev); - } else { - io_removehandler(0x0240, 0x0010, - capture_read_sb, NULL, NULL, - capture_write_sb, NULL, NULL, dev); - } + if (!(old_legacy_ctrl & LEGACY_SB_ADDR)) { + io_removehandler(0x0220, 0x0010, + capture_read_sb, NULL, NULL, + capture_write_sb, NULL, NULL, dev); + } else { + io_removehandler(0x0240, 0x0010, + capture_read_sb, NULL, NULL, + capture_write_sb, NULL, NULL, dev); + } } if (old_legacy_ctrl & LEGACY_CAPTURE_ADLIB) { - io_removehandler(0x0388, 0x0004, - capture_read_adlib, NULL, NULL, - capture_write_adlib, NULL, NULL, dev); + io_removehandler(0x0388, 0x0004, + capture_read_adlib, NULL, NULL, + capture_write_adlib, NULL, NULL, dev); } if (old_legacy_ctrl & LEGACY_CAPTURE_MASTER_PIC) { - io_removehandler(0x0020, 0x0002, - capture_read_master_pic, NULL, NULL, - capture_write_master_pic,NULL,NULL, dev); + io_removehandler(0x0020, 0x0002, + capture_read_master_pic, NULL, NULL, + capture_write_master_pic, NULL, NULL, dev); } if (old_legacy_ctrl & LEGACY_CAPTURE_MASTER_DMA) { - io_removehandler(0x0000, 0x0010, - capture_read_master_dma, NULL, NULL, - capture_write_master_dma, NULL, NULL, dev); + io_removehandler(0x0000, 0x0010, + capture_read_master_dma, NULL, NULL, + capture_write_master_dma, NULL, NULL, dev); } if (old_legacy_ctrl & LEGACY_CAPTURE_SLAVE_PIC) { - io_removehandler(0x00a0, 0x0002, - capture_read_slave_pic, NULL, NULL, - capture_write_slave_pic, NULL, NULL, dev); + io_removehandler(0x00a0, 0x0002, + capture_read_slave_pic, NULL, NULL, + capture_write_slave_pic, NULL, NULL, dev); } if (old_legacy_ctrl & LEGACY_CAPTURE_SLAVE_DMA) { - io_removehandler(0x00c0, 0x0020, - capture_read_slave_dma, NULL, NULL, - capture_write_slave_dma, NULL, NULL, dev); + io_removehandler(0x00c0, 0x0020, + capture_read_slave_dma, NULL, NULL, + capture_write_slave_dma, NULL, NULL, dev); } if (dev->legacy_ctrl & LEGACY_CAPTURE_SSCAPE) { - switch ((dev->legacy_ctrl >> LEGACY_SSCAPE_ADDR_SHIFT) & 3) { - case 0: - io_sethandler(0x0320, 0x0008, - capture_read_sscape, NULL, NULL, - capture_write_sscape, NULL, NULL, dev); - break; - case 1: - io_sethandler(0x0330, 0x0008, - capture_read_sscape, NULL, NULL, - capture_write_sscape, NULL, NULL, dev); - break; - case 2: - io_sethandler(0x0340, 0x0008, - capture_read_sscape, NULL, NULL, - capture_write_sscape, NULL, NULL, dev); - break; - case 3: - io_sethandler(0x0350, 0x0008, - capture_read_sscape, NULL, NULL, - capture_write_sscape, NULL, NULL, dev); - break; - } + switch ((dev->legacy_ctrl >> LEGACY_SSCAPE_ADDR_SHIFT) & 3) { + case 0: + io_sethandler(0x0320, 0x0008, + capture_read_sscape, NULL, NULL, + capture_write_sscape, NULL, NULL, dev); + break; + case 1: + io_sethandler(0x0330, 0x0008, + capture_read_sscape, NULL, NULL, + capture_write_sscape, NULL, NULL, dev); + break; + case 2: + io_sethandler(0x0340, 0x0008, + capture_read_sscape, NULL, NULL, + capture_write_sscape, NULL, NULL, dev); + break; + case 3: + io_sethandler(0x0350, 0x0008, + capture_read_sscape, NULL, NULL, + capture_write_sscape, NULL, NULL, dev); + break; + + default: + break; + } } if (dev->legacy_ctrl & LEGACY_CAPTURE_CODEC) { - switch ((dev->legacy_ctrl >> LEGACY_CODEC_ADDR_SHIFT) & 3) { - case 0: - io_sethandler(0x0530, 0x0008, - capture_read_codec, NULL, NULL, - capture_write_codec, NULL, NULL, dev); - break; - case 2: - io_sethandler(0x0e80, 0x0008, - capture_read_codec, NULL, NULL, - capture_write_codec, NULL, NULL, dev); - break; - case 3: - io_sethandler(0x0f40, 0x0008, - capture_read_codec, NULL, NULL, - capture_write_codec, NULL, NULL, dev); - break; - } + switch ((dev->legacy_ctrl >> LEGACY_CODEC_ADDR_SHIFT) & 3) { + case 0: + io_sethandler(0x0530, 0x0008, + capture_read_codec, NULL, NULL, + capture_write_codec, NULL, NULL, dev); + break; + case 2: + io_sethandler(0x0e80, 0x0008, + capture_read_codec, NULL, NULL, + capture_write_codec, NULL, NULL, dev); + break; + case 3: + io_sethandler(0x0f40, 0x0008, + capture_read_codec, NULL, NULL, + capture_write_codec, NULL, NULL, dev); + break; + + default: + break; + } } if (dev->legacy_ctrl & LEGACY_CAPTURE_SB) { - if (!(dev->legacy_ctrl & LEGACY_SB_ADDR)) { - io_sethandler(0x0220, 0x0010, - capture_read_sb, NULL, NULL, - capture_write_sb, NULL, NULL, dev); - } else { - io_sethandler(0x0240, 0x0010, - capture_read_sb, NULL, NULL, - capture_write_sb, NULL, NULL, dev); - } + if (!(dev->legacy_ctrl & LEGACY_SB_ADDR)) { + io_sethandler(0x0220, 0x0010, + capture_read_sb, NULL, NULL, + capture_write_sb, NULL, NULL, dev); + } else { + io_sethandler(0x0240, 0x0010, + capture_read_sb, NULL, NULL, + capture_write_sb, NULL, NULL, dev); + } } if (dev->legacy_ctrl & LEGACY_CAPTURE_ADLIB) { - io_sethandler(0x0388, 0x0004, - capture_read_adlib, NULL, NULL, - capture_write_adlib, NULL, NULL, dev); + io_sethandler(0x0388, 0x0004, + capture_read_adlib, NULL, NULL, + capture_write_adlib, NULL, NULL, dev); } if (dev->legacy_ctrl & LEGACY_CAPTURE_MASTER_PIC) { - io_sethandler(0x0020, 0x0002, - capture_read_master_pic, NULL, NULL, - capture_write_master_pic, NULL, NULL, dev); + io_sethandler(0x0020, 0x0002, + capture_read_master_pic, NULL, NULL, + capture_write_master_pic, NULL, NULL, dev); } if (dev->legacy_ctrl & LEGACY_CAPTURE_MASTER_DMA) { - io_sethandler(0x0000, 0x0010, - capture_read_master_dma, NULL, NULL, - capture_write_master_dma, NULL, NULL, dev); + io_sethandler(0x0000, 0x0010, + capture_read_master_dma, NULL, NULL, + capture_write_master_dma, NULL, NULL, dev); } if (dev->legacy_ctrl & LEGACY_CAPTURE_SLAVE_PIC) { - io_sethandler(0x00a0, 0x0002, - capture_read_slave_pic, NULL, NULL, - capture_write_slave_pic, NULL, NULL, dev); + io_sethandler(0x00a0, 0x0002, + capture_read_slave_pic, NULL, NULL, + capture_write_slave_pic, NULL, NULL, dev); } if (dev->legacy_ctrl & LEGACY_CAPTURE_SLAVE_DMA) { - io_sethandler(0x00c0, 0x0020, - capture_read_slave_dma, NULL, NULL, - capture_write_slave_dma, NULL, NULL, dev); + io_sethandler(0x00c0, 0x0020, + capture_read_slave_dma, NULL, NULL, + capture_write_slave_dma, NULL, NULL, dev); } } - static uint8_t -es1371_pci_read(int func, int addr, void *p) +es1371_pci_read(int func, int addr, void *priv) { - es1371_t *dev = (es1371_t *)p; + const es1371_t *dev = (es1371_t *) priv; if (func > 0) - return 0xff; + return 0xff; if ((addr > 0x3f) && ((addr < 0xdc) || (addr > 0xe1))) - return 0x00; + return 0x00; switch (addr) { - case 0x00: return 0x74; /* Ensoniq */ - case 0x01: return 0x12; + case 0x00: + return 0x74; /* Ensoniq */ + case 0x01: + return 0x12; - case 0x02: return 0x71; /* ES1371 */ - case 0x03: return 0x13; + case 0x02: + return 0x71; /* ES1371 */ + case 0x03: + return 0x13; - case 0x04: return dev->pci_command; - case 0x05: return dev->pci_serr; + case 0x04: + return dev->pci_command; + case 0x05: + return dev->pci_serr; - case 0x06: return 0x10; /* Supports ACPI */ - case 0x07: return 0x00; + case 0x06: + return 0x10; /* Supports ACPI */ + case 0x07: + return 0x00; - case 0x08: return 0x08; /* Revision ID - 0x02 (datasheet, VMware) has issues with the 2001 Creative WDM driver */ - case 0x09: return 0x00; /* Multimedia audio device */ - case 0x0a: return 0x01; - case 0x0b: return 0x04; + case 0x08: + return 0x02; /* Revision ID - 0x02 is actual Ensoniq-branded ES1371 */ + case 0x09: + return 0x00; /* Multimedia audio device */ + case 0x0a: + return 0x01; + case 0x0b: + return 0x04; - case 0x10: return 0x01 | (dev->base_addr & 0xc0); /* memBaseAddr */ - case 0x11: return dev->base_addr >> 8; - case 0x12: return dev->base_addr >> 16; - case 0x13: return dev->base_addr >> 24; + case 0x10: + return 0x01 | (dev->base_addr & 0xc0); /* memBaseAddr */ + case 0x11: + return dev->base_addr >> 8; + case 0x12: + return dev->base_addr >> 16; + case 0x13: + return dev->base_addr >> 24; - case 0x2c: return 0x74; /* Subsystem vendor ID */ - case 0x2d: return 0x12; - case 0x2e: return 0x71; - case 0x2f: return 0x13; + case 0x2c: + return 0x74; /* Subsystem vendor ID */ + case 0x2d: + return 0x12; + case 0x2e: + return 0x71; + case 0x2f: + return 0x13; - case 0x34: return 0xdc; /* Capabilites pointer */ + case 0x34: + return 0xdc; /* Capabilites pointer */ - case 0x3c: return dev->int_line; - case 0x3d: return 0x01; /* INTA */ + case 0x3c: + return dev->int_line; + case 0x3d: + return 0x01; /* INTA */ - case 0x3e: return 0xc; /* Minimum grant */ - case 0x3f: return 0x80; /* Maximum latency */ + case 0x3e: + return 0xc; /* Minimum grant */ + case 0x3f: + return 0x80; /* Maximum latency */ - case 0xdc: return 0x01; /* Capabilities identifier */ - case 0xdd: return 0x00; /* Next item pointer */ - case 0xde: return 0x31; /* Power management capabilities */ - case 0xdf: return 0x6c; + case 0xdc: + return 0x01; /* Capabilities identifier */ + case 0xdd: + return 0x00; /* Next item pointer */ + case 0xde: + return 0x31; /* Power management capabilities */ + case 0xdf: + return 0x6c; - case 0xe0: return dev->pmcsr & 0xff; - case 0xe1: return dev->pmcsr >> 8; + case 0xe0: + return dev->pmcsr & 0xff; + case 0xe1: + return dev->pmcsr >> 8; + + default: + break; } return 0x00; } - static void es1371_io_set(es1371_t *dev, int set) { if (dev->pci_command & PCI_COMMAND_IO) { - io_handler(set, dev->base_addr, 0x0040, - es1371_inb, es1371_inw, es1371_inl, - es1371_outb, es1371_outw, es1371_outl, dev); + io_handler(set, dev->base_addr, 0x0040, + es1371_inb, es1371_inw, es1371_inl, + es1371_outb, es1371_outw, es1371_outl, dev); } } - static void -es1371_pci_write(int func, int addr, uint8_t val, void *p) +es1371_pci_write(int func, int addr, uint8_t val, void *priv) { - es1371_t *dev = (es1371_t *)p; + es1371_t *dev = (es1371_t *) priv; if (func) - return; + return; switch (addr) { - case 0x04: - es1371_io_set(dev, 0); - dev->pci_command = val & 0x05; - es1371_io_set(dev, 1); - break; - case 0x05: - dev->pci_serr = val & 1; - break; + case 0x04: + es1371_io_set(dev, 0); + dev->pci_command = val & 0x05; + es1371_io_set(dev, 1); + break; + case 0x05: + dev->pci_serr = val & 1; + break; - case 0x10: - es1371_io_set(dev, 0); - dev->base_addr = (dev->base_addr & 0xffffff00) | (val & 0xc0); - es1371_io_set(dev, 1); - break; - case 0x11: - es1371_io_set(dev, 0); - dev->base_addr = (dev->base_addr & 0xffff00c0) | (val << 8); - es1371_io_set(dev, 1); - break; - case 0x12: - dev->base_addr = (dev->base_addr & 0xff00ffc0) | (val << 16); - break; - case 0x13: - dev->base_addr = (dev->base_addr & 0x00ffffc0) | (val << 24); - break; + case 0x10: + es1371_io_set(dev, 0); + dev->base_addr = (dev->base_addr & 0xffffff00) | (val & 0xc0); + es1371_io_set(dev, 1); + break; + case 0x11: + es1371_io_set(dev, 0); + dev->base_addr = (dev->base_addr & 0xffff00c0) | (val << 8); + es1371_io_set(dev, 1); + break; + case 0x12: + dev->base_addr = (dev->base_addr & 0xff00ffc0) | (val << 16); + break; + case 0x13: + dev->base_addr = (dev->base_addr & 0x00ffffc0) | (val << 24); + break; - case 0x3c: - dev->int_line = val; - break; + case 0x3c: + dev->int_line = val; + break; - case 0xe0: - dev->pmcsr = (dev->pmcsr & 0xff00) | (val & 0x03); - break; - case 0xe1: - dev->pmcsr = (dev->pmcsr & 0x00ff) | ((val & 0x01) << 8); - break; + case 0xe0: + dev->pmcsr = (dev->pmcsr & 0xff00) | (val & 0x03); + break; + case 0xe1: + dev->pmcsr = (dev->pmcsr & 0x00ff) | ((val & 0x01) << 8); + break; + + default: + break; } } - static void es1371_fetch(es1371_t *dev, int dac_nr) { if (dev->si_cr & (dac_nr ? SI_P2_PAUSE : SI_P1_PAUSE)) - return; + return; int format = dac_nr ? ((dev->si_cr >> 2) & 3) : (dev->si_cr & 3); - int pos = dev->dac[dac_nr].buffer_pos & 63; + int pos = dev->dac[dac_nr].buffer_pos & 63; int c; switch (format) { - case FORMAT_MONO_8: - for (c = 0; c < 32; c += 4) { - dev->dac[dac_nr].buffer_l[(pos+c) & 63] = dev->dac[dac_nr].buffer_r[(pos+c) & 63] = - (mem_readb_phys(dev->dac[dac_nr].addr) ^ 0x80) << 8; - dev->dac[dac_nr].buffer_l[(pos+c+1) & 63] = dev->dac[dac_nr].buffer_r[(pos+c+1) & 63] = - (mem_readb_phys(dev->dac[dac_nr].addr+1) ^ 0x80) << 8; - dev->dac[dac_nr].buffer_l[(pos+c+2) & 63] = dev->dac[dac_nr].buffer_r[(pos+c+2) & 63] = - (mem_readb_phys(dev->dac[dac_nr].addr+2) ^ 0x80) << 8; - dev->dac[dac_nr].buffer_l[(pos+c+3) & 63] = dev->dac[dac_nr].buffer_r[(pos+c+3) & 63] = - (mem_readb_phys(dev->dac[dac_nr].addr+3) ^ 0x80) << 8; - dev->dac[dac_nr].addr += 4; + case FORMAT_MONO_8: + for (c = 0; c < 32; c += 4) { + dev->dac[dac_nr].buffer_l[(pos + c) & 63] = dev->dac[dac_nr].buffer_r[(pos + c) & 63] = (mem_readb_phys(dev->dac[dac_nr].addr) ^ 0x80) << 8; + dev->dac[dac_nr].buffer_l[(pos + c + 1) & 63] = dev->dac[dac_nr].buffer_r[(pos + c + 1) & 63] = (mem_readb_phys(dev->dac[dac_nr].addr + 1) ^ 0x80) << 8; + dev->dac[dac_nr].buffer_l[(pos + c + 2) & 63] = dev->dac[dac_nr].buffer_r[(pos + c + 2) & 63] = (mem_readb_phys(dev->dac[dac_nr].addr + 2) ^ 0x80) << 8; + dev->dac[dac_nr].buffer_l[(pos + c + 3) & 63] = dev->dac[dac_nr].buffer_r[(pos + c + 3) & 63] = (mem_readb_phys(dev->dac[dac_nr].addr + 3) ^ 0x80) << 8; + dev->dac[dac_nr].addr += 4; - dev->dac[dac_nr].buffer_pos_end += 4; - dev->dac[dac_nr].count++; + dev->dac[dac_nr].buffer_pos_end += 4; + dev->dac[dac_nr].count++; - if (dev->dac[dac_nr].count > dev->dac[dac_nr].size) { - dev->dac[dac_nr].count = 0; - dev->dac[dac_nr].addr = dev->dac[dac_nr].addr_latch; - break; - } - } - break; + if (dev->dac[dac_nr].count > dev->dac[dac_nr].size) { + dev->dac[dac_nr].count = 0; + dev->dac[dac_nr].addr = dev->dac[dac_nr].addr_latch; + break; + } + } + break; - case FORMAT_STEREO_8: - for (c = 0; c < 16; c += 2) { - dev->dac[dac_nr].buffer_l[(pos+c) & 63] = (mem_readb_phys(dev->dac[dac_nr].addr) ^ 0x80) << 8; - dev->dac[dac_nr].buffer_r[(pos+c) & 63] = (mem_readb_phys(dev->dac[dac_nr].addr + 1) ^ 0x80) << 8; - dev->dac[dac_nr].buffer_l[(pos+c+1) & 63] = (mem_readb_phys(dev->dac[dac_nr].addr + 2) ^ 0x80) << 8; - dev->dac[dac_nr].buffer_r[(pos+c+1) & 63] = (mem_readb_phys(dev->dac[dac_nr].addr + 3) ^ 0x80) << 8; - dev->dac[dac_nr].addr += 4; + case FORMAT_STEREO_8: + for (c = 0; c < 16; c += 2) { + dev->dac[dac_nr].buffer_l[(pos + c) & 63] = (mem_readb_phys(dev->dac[dac_nr].addr) ^ 0x80) << 8; + dev->dac[dac_nr].buffer_r[(pos + c) & 63] = (mem_readb_phys(dev->dac[dac_nr].addr + 1) ^ 0x80) << 8; + dev->dac[dac_nr].buffer_l[(pos + c + 1) & 63] = (mem_readb_phys(dev->dac[dac_nr].addr + 2) ^ 0x80) << 8; + dev->dac[dac_nr].buffer_r[(pos + c + 1) & 63] = (mem_readb_phys(dev->dac[dac_nr].addr + 3) ^ 0x80) << 8; + dev->dac[dac_nr].addr += 4; - dev->dac[dac_nr].buffer_pos_end += 2; - dev->dac[dac_nr].count++; + dev->dac[dac_nr].buffer_pos_end += 2; + dev->dac[dac_nr].count++; - if (dev->dac[dac_nr].count > dev->dac[dac_nr].size) { - dev->dac[dac_nr].count = 0; - dev->dac[dac_nr].addr = dev->dac[dac_nr].addr_latch; - break; - } - } - break; + if (dev->dac[dac_nr].count > dev->dac[dac_nr].size) { + dev->dac[dac_nr].count = 0; + dev->dac[dac_nr].addr = dev->dac[dac_nr].addr_latch; + break; + } + } + break; - case FORMAT_MONO_16: - for (c = 0; c < 16; c += 2) { - dev->dac[dac_nr].buffer_l[(pos+c) & 63] = dev->dac[dac_nr].buffer_r[(pos+c) & 63] = - mem_readw_phys(dev->dac[dac_nr].addr); - dev->dac[dac_nr].buffer_l[(pos+c+1) & 63] = dev->dac[dac_nr].buffer_r[(pos+c+1) & 63] = - mem_readw_phys(dev->dac[dac_nr].addr + 2); - dev->dac[dac_nr].addr += 4; + case FORMAT_MONO_16: + for (c = 0; c < 16; c += 2) { + dev->dac[dac_nr].buffer_l[(pos + c) & 63] = dev->dac[dac_nr].buffer_r[(pos + c) & 63] = mem_readw_phys(dev->dac[dac_nr].addr); + dev->dac[dac_nr].buffer_l[(pos + c + 1) & 63] = dev->dac[dac_nr].buffer_r[(pos + c + 1) & 63] = mem_readw_phys(dev->dac[dac_nr].addr + 2); + dev->dac[dac_nr].addr += 4; - dev->dac[dac_nr].buffer_pos_end += 2; - dev->dac[dac_nr].count++; + dev->dac[dac_nr].buffer_pos_end += 2; + dev->dac[dac_nr].count++; - if (dev->dac[dac_nr].count > dev->dac[dac_nr].size) { - dev->dac[dac_nr].count = 0; - dev->dac[dac_nr].addr = dev->dac[dac_nr].addr_latch; - break; - } - } - break; + if (dev->dac[dac_nr].count > dev->dac[dac_nr].size) { + dev->dac[dac_nr].count = 0; + dev->dac[dac_nr].addr = dev->dac[dac_nr].addr_latch; + break; + } + } + break; - case FORMAT_STEREO_16: - for (c = 0; c < 4; c++) { - dev->dac[dac_nr].buffer_l[(pos+c) & 63] = mem_readw_phys(dev->dac[dac_nr].addr); - dev->dac[dac_nr].buffer_r[(pos+c) & 63] = mem_readw_phys(dev->dac[dac_nr].addr + 2); - dev->dac[dac_nr].addr += 4; + case FORMAT_STEREO_16: + for (c = 0; c < 4; c++) { + dev->dac[dac_nr].buffer_l[(pos + c) & 63] = mem_readw_phys(dev->dac[dac_nr].addr); + dev->dac[dac_nr].buffer_r[(pos + c) & 63] = mem_readw_phys(dev->dac[dac_nr].addr + 2); + dev->dac[dac_nr].addr += 4; - dev->dac[dac_nr].buffer_pos_end++; - dev->dac[dac_nr].count++; + dev->dac[dac_nr].buffer_pos_end++; + dev->dac[dac_nr].count++; - if (dev->dac[dac_nr].count > dev->dac[dac_nr].size) { - dev->dac[dac_nr].count = 0; - dev->dac[dac_nr].addr = dev->dac[dac_nr].addr_latch; - break; - } - } - break; + if (dev->dac[dac_nr].count > dev->dac[dac_nr].size) { + dev->dac[dac_nr].count = 0; + dev->dac[dac_nr].addr = dev->dac[dac_nr].addr_latch; + break; + } + } + break; + + default: + break; } } - static inline float low_fir_es1371(int dac_nr, int i, float NewSample) { - static float x[2][2][128]; //input samples - static int x_pos[2] = {0, 0}; - float out = 0.0; - int read_pos, n_coef; - int pos = x_pos[dac_nr]; + static float x[2][2][128]; // input samples + static int x_pos[2] = { 0, 0 }; + float out = 0.0; + int read_pos; + int n_coef; + int pos = x_pos[dac_nr]; x[dac_nr][i][pos] = NewSample; /* Since only 1/16th of input samples are non-zero, only filter those that are valid.*/ read_pos = (pos + 15) & (127 & ~15); - n_coef = (16 - pos) & 15; + n_coef = (16 - pos) & 15; while (n_coef < ES1371_NCoef) { - out += low_fir_es1371_coef[n_coef] * x[dac_nr][i][read_pos]; - read_pos = (read_pos + 16) & (127 & ~15); - n_coef += 16; + out += low_fir_es1371_coef[n_coef] * x[dac_nr][i][read_pos]; + read_pos = (read_pos + 16) & (127 & ~15); + n_coef += 16; } if (i == 1) { - x_pos[dac_nr] = (x_pos[dac_nr] + 1) & 127; - if (x_pos[dac_nr] > 127) - x_pos[dac_nr] = 0; + x_pos[dac_nr] = (x_pos[dac_nr] + 1) & 127; + if (x_pos[dac_nr] > 127) + x_pos[dac_nr] = 0; } return out; } - static void es1371_next_sample_filtered(es1371_t *dev, int dac_nr, int out_idx) { - int out_l, out_r; - int c; + int out_l; + int out_r; if ((dev->dac[dac_nr].buffer_pos - dev->dac[dac_nr].buffer_pos_end) >= 0) - es1371_fetch(dev, dac_nr); + es1371_fetch(dev, dac_nr); out_l = dev->dac[dac_nr].buffer_l[dev->dac[dac_nr].buffer_pos & 63]; out_r = dev->dac[dac_nr].buffer_r[dev->dac[dac_nr].buffer_pos & 63]; - dev->dac[dac_nr].filtered_l[out_idx] = (int)low_fir_es1371(dac_nr, 0, (float)out_l); - dev->dac[dac_nr].filtered_r[out_idx] = (int)low_fir_es1371(dac_nr, 1, (float)out_r); + dev->dac[dac_nr].filtered_l[out_idx] = (int) low_fir_es1371(dac_nr, 0, (float) out_l); + dev->dac[dac_nr].filtered_r[out_idx] = (int) low_fir_es1371(dac_nr, 1, (float) out_r); - for (c = 1; c < 16; c++) { - dev->dac[dac_nr].filtered_l[out_idx+c] = (int)low_fir_es1371(dac_nr, 0, 0); - dev->dac[dac_nr].filtered_r[out_idx+c] = (int)low_fir_es1371(dac_nr, 1, 0); + for (uint8_t c = 1; c < 16; c++) { + dev->dac[dac_nr].filtered_l[out_idx + c] = (int) low_fir_es1371(dac_nr, 0, 0); + dev->dac[dac_nr].filtered_r[out_idx + c] = (int) low_fir_es1371(dac_nr, 1, 0); } dev->dac[dac_nr].buffer_pos++; } - static void es1371_update(es1371_t *dev) { - int32_t l, r; + int32_t l; + int32_t r; l = (dev->dac[0].out_l * dev->dac[0].vol_l) >> 12; l += ((dev->dac[1].out_l * dev->dac[1].vol_l) >> 12); @@ -1831,180 +1909,176 @@ es1371_update(es1371_t *dev) r = (((r * dev->pcm_vol_r) >> 15) * dev->master_vol_r) >> 15; if (l < -32768) - l = -32768; + l = -32768; else if (l > 32767) - l = 32767; + l = 32767; if (r < -32768) - r = -32768; + r = -32768; else if (r > 32767) - r = 32767; + r = 32767; - for (; dev->pos < sound_pos_global; dev->pos++) { - dev->buffer[dev->pos*2] = l; - dev->buffer[dev->pos*2 + 1] = r; + for (; dev->pos < sound_pos_global; dev->pos++) { + dev->buffer[dev->pos * 2] = l; + dev->buffer[dev->pos * 2 + 1] = r; } } - static void -es1371_poll(void *p) +es1371_poll(void *priv) { - es1371_t *dev = (es1371_t *)p; - int frac, idx, samp1_l, samp1_r, samp2_l, samp2_r; + es1371_t *dev = (es1371_t *) priv; + int frac; + int idx; + int samp1_l; + int samp1_r; + int samp2_l; + int samp2_r; timer_advance_u64(&dev->dac[1].timer, dev->dac[1].latch); es1371_scan_fifo(dev); - es1371_update(dev); + es1371_update(dev); if (dev->int_ctrl & INT_DAC1_EN) { - frac = dev->dac[0].ac & 0x7fff; - idx = dev->dac[0].ac >> 15; - samp1_l = dev->dac[0].filtered_l[idx]; - samp1_r = dev->dac[0].filtered_r[idx]; - samp2_l = dev->dac[0].filtered_l[(idx + 1) & 31]; - samp2_r = dev->dac[0].filtered_r[(idx + 1) & 31]; + frac = dev->dac[0].ac & 0x7fff; + idx = dev->dac[0].ac >> 15; + samp1_l = dev->dac[0].filtered_l[idx]; + samp1_r = dev->dac[0].filtered_r[idx]; + samp2_l = dev->dac[0].filtered_l[(idx + 1) & 31]; + samp2_r = dev->dac[0].filtered_r[(idx + 1) & 31]; - dev->dac[0].out_l = ((samp1_l * (0x8000 - frac)) + (samp2_l * frac)) >> 15; - dev->dac[0].out_r = ((samp1_r * (0x8000 - frac)) + (samp2_r * frac)) >> 15; - dev->dac[0].ac += dev->dac[0].vf; - dev->dac[0].ac &= ((32 << 15) - 1); - if ((dev->dac[0].ac >> (15+4)) != dev->dac[0].f_pos) { - es1371_next_sample_filtered(dev, 0, dev->dac[0].f_pos ? 16 : 0); - dev->dac[0].f_pos = (dev->dac[0].f_pos + 1) & 1; + dev->dac[0].out_l = ((samp1_l * (0x8000 - frac)) + (samp2_l * frac)) >> 15; + dev->dac[0].out_r = ((samp1_r * (0x8000 - frac)) + (samp2_r * frac)) >> 15; + dev->dac[0].ac += dev->dac[0].vf; + dev->dac[0].ac &= ((32 << 15) - 1); + if ((dev->dac[0].ac >> (15 + 4)) != dev->dac[0].f_pos) { + es1371_next_sample_filtered(dev, 0, dev->dac[0].f_pos ? 16 : 0); + dev->dac[0].f_pos = (dev->dac[0].f_pos + 1) & 1; - dev->dac[0].curr_samp_ct--; - if (dev->dac[0].curr_samp_ct < 0) { - dev->int_status |= INT_STATUS_DAC1; - es1371_update_irqs(dev); - dev->dac[0].curr_samp_ct = dev->dac[0].samp_ct; - } - } + dev->dac[0].curr_samp_ct--; + if (dev->dac[0].curr_samp_ct < 0) { + dev->int_status |= INT_STATUS_DAC1; + es1371_update_irqs(dev); + dev->dac[0].curr_samp_ct = dev->dac[0].samp_ct; + } + } } if (dev->int_ctrl & INT_DAC2_EN) { - frac = dev->dac[1].ac & 0x7fff; - idx = dev->dac[1].ac >> 15; - samp1_l = dev->dac[1].filtered_l[idx]; - samp1_r = dev->dac[1].filtered_r[idx]; - samp2_l = dev->dac[1].filtered_l[(idx + 1) & 31]; - samp2_r = dev->dac[1].filtered_r[(idx + 1) & 31]; + frac = dev->dac[1].ac & 0x7fff; + idx = dev->dac[1].ac >> 15; + samp1_l = dev->dac[1].filtered_l[idx]; + samp1_r = dev->dac[1].filtered_r[idx]; + samp2_l = dev->dac[1].filtered_l[(idx + 1) & 31]; + samp2_r = dev->dac[1].filtered_r[(idx + 1) & 31]; - dev->dac[1].out_l = ((samp1_l * (0x8000 - frac)) + (samp2_l * frac)) >> 15; - dev->dac[1].out_r = ((samp1_r * (0x8000 - frac)) + (samp2_r * frac)) >> 15; - dev->dac[1].ac += dev->dac[1].vf; - dev->dac[1].ac &= ((32 << 15) - 1); - if ((dev->dac[1].ac >> (15+4)) != dev->dac[1].f_pos) { - es1371_next_sample_filtered(dev, 1, dev->dac[1].f_pos ? 16 : 0); - dev->dac[1].f_pos = (dev->dac[1].f_pos + 1) & 1; + dev->dac[1].out_l = ((samp1_l * (0x8000 - frac)) + (samp2_l * frac)) >> 15; + dev->dac[1].out_r = ((samp1_r * (0x8000 - frac)) + (samp2_r * frac)) >> 15; + dev->dac[1].ac += dev->dac[1].vf; + dev->dac[1].ac &= ((32 << 15) - 1); + if ((dev->dac[1].ac >> (15 + 4)) != dev->dac[1].f_pos) { + es1371_next_sample_filtered(dev, 1, dev->dac[1].f_pos ? 16 : 0); + dev->dac[1].f_pos = (dev->dac[1].f_pos + 1) & 1; - dev->dac[1].curr_samp_ct--; - if (dev->dac[1].curr_samp_ct < 0) { - dev->int_status |= INT_STATUS_DAC2; - es1371_update_irqs(dev); - dev->dac[1].curr_samp_ct = dev->dac[1].samp_ct; - } - } + dev->dac[1].curr_samp_ct--; + if (dev->dac[1].curr_samp_ct < 0) { + dev->int_status |= INT_STATUS_DAC2; + es1371_update_irqs(dev); + dev->dac[1].curr_samp_ct = dev->dac[1].samp_ct; + } + } } } - static void -es1371_get_buffer(int32_t *buffer, int len, void *p) +es1371_get_buffer(int32_t *buffer, int len, void *priv) { - es1371_t *dev = (es1371_t *)p; - int c; + es1371_t *dev = (es1371_t *) priv; es1371_update(dev); - for (c = 0; c < len * 2; c++) - buffer[c] += (dev->buffer[c] / 2); + for (int c = 0; c < len * 2; c++) + buffer[c] += (dev->buffer[c] / 2); dev->pos = 0; } - static void -es1371_filter_cd_audio(int channel, double *buffer, void *p) +es1371_filter_cd_audio(int channel, double *buffer, void *priv) { - es1371_t *dev = (es1371_t *)p; - double c; - int cd = channel ? dev->cd_vol_r : dev->cd_vol_l; - int master = channel ? dev->master_vol_r : dev->master_vol_l; + const es1371_t *dev = (es1371_t *) priv; + double c; + int cd = channel ? dev->cd_vol_r : dev->cd_vol_l; + int master = channel ? dev->master_vol_r : dev->master_vol_l; - c = ((((*buffer) * cd) / 65536.0) * master) / 65536.0; + c = ((((*buffer) * cd) / 65536.0) * master) / 65536.0; *buffer = c; } - -static inline -double sinc(double x) +static inline double +sinc(double x) { return sin(M_PI * x) / (M_PI * x); } - static void generate_es1371_filter(void) { /* Cutoff frequency = 1 / 32 */ float fC = 1.0 / 32.0; float gain; - int n; + int n; for (n = 0; n < ES1371_NCoef; n++) { - /* Blackman window */ - double w = 0.42 - (0.5 * cos((2.0*n*M_PI)/(double)(ES1371_NCoef-1))) + (0.08 * cos((4.0*n*M_PI)/(double)(ES1371_NCoef-1))); - /* Sinc filter */ - double h = sinc(2.0 * fC * ((double)n - ((double)(ES1371_NCoef-1) / 2.0))); + /* Blackman window */ + double w = 0.42 - (0.5 * cos((2.0 * n * M_PI) / (double) (ES1371_NCoef - 1))) + (0.08 * cos((4.0 * n * M_PI) / (double) (ES1371_NCoef - 1))); + /* Sinc filter */ + double h = sinc(2.0 * fC * ((double) n - ((double) (ES1371_NCoef - 1) / 2.0))); - /* Create windowed-sinc filter */ - low_fir_es1371_coef[n] = w * h; + /* Create windowed-sinc filter */ + low_fir_es1371_coef[n] = w * h; } low_fir_es1371_coef[(ES1371_NCoef - 1) / 2] = 1.0; gain = 0.0; for (n = 0; n < ES1371_NCoef; n++) - gain += low_fir_es1371_coef[n] / (float)N; + gain += low_fir_es1371_coef[n] / (float) N; - gain /= 0.95; + gain /= 0.65; /* Normalise filter, to produce unity gain */ for (n = 0; n < ES1371_NCoef; n++) - low_fir_es1371_coef[n] /= gain; + low_fir_es1371_coef[n] /= gain; } - static void -es1371_input_msg(void *p, uint8_t *msg, uint32_t len) +es1371_input_msg(void *priv, uint8_t *msg, uint32_t len) { - es1371_t *dev = (es1371_t *)p; - uint8_t i; + es1371_t *dev = (es1371_t *) priv; - for (i = 0; i < len; i++) - es1371_write_fifo(dev, msg[i]); + for (uint32_t i = 0; i < len; i++) + es1371_write_fifo(dev, msg[i]); } - static int -es1371_input_sysex(void *p, uint8_t *buffer, uint32_t len, int abort) +es1371_input_sysex(void *priv, uint8_t *buffer, uint32_t len, int abort) { - es1371_t *dev = (es1371_t *)p; - uint32_t i = -1; + es1371_t *dev = (es1371_t *) priv; + uint32_t i = -1; audiopci_log("Abort = %i\n", abort); if (dev->uart_status & UART_STATUS_RXRDY) - abort = 1; + abort = 1; if (!abort) { - for (i = 0; i < len; i++) { - es1371_write_fifo(dev, buffer[i]); - if (dev->uart_status & UART_STATUS_RXRDY) - break; - } + for (i = 0; i < len; i++) { + es1371_write_fifo(dev, buffer[i]); + if (dev->uart_status & UART_STATUS_RXRDY) + break; + } } /* The last sent position is in i. Return 7 - i. */ @@ -2012,7 +2086,6 @@ es1371_input_sysex(void *p, uint8_t *buffer, uint32_t len, int abort) return 7 - i; } - static void * es1371_init(const device_t *info) { @@ -2020,7 +2093,7 @@ es1371_init(const device_t *info) memset(dev, 0x00, sizeof(es1371_t)); if (device_get_config_int("receive_input")) - midi_in_handler(1, es1371_input_msg, es1371_input_sysex, dev); + midi_in_handler(1, es1371_input_msg, es1371_input_sysex, dev); sound_add_handler(es1371_get_buffer, dev); sound_set_cd_audio_filter(es1371_filter_cd_audio, dev); @@ -2028,104 +2101,107 @@ es1371_init(const device_t *info) dev->gameport = gameport_add(&gameport_pnp_device); gameport_remap(dev->gameport, 0x200); - dev->card = pci_add_card(info->local ? PCI_ADD_SOUND : PCI_ADD_NORMAL, es1371_pci_read, es1371_pci_write, dev); + pci_add_card(info->local ? PCI_ADD_SOUND : PCI_ADD_NORMAL, es1371_pci_read, es1371_pci_write, dev, &dev->pci_slot); - timer_add(&dev->dac[1].timer, es1371_poll, dev, 1); + timer_add(&dev->dac[1].timer, es1371_poll, dev, 1); generate_es1371_filter(); - ac97_codec = &dev->codec; + ac97_codec = &dev->codec; ac97_codec_count = 1; - ac97_codec_id = 0; + ac97_codec_id = 0; /* Let the machine decide the codec on onboard implementations. */ if (!info->local) - device_add(ac97_codec_get(device_get_config_int("codec"))); + device_add(ac97_codec_get(device_get_config_int("codec"))); es1371_reset(dev); return dev; } - static void -es1371_close(void *p) +es1371_close(void *priv) { - es1371_t *dev = (es1371_t *) p; + es1371_t *dev = (es1371_t *) priv; free(dev); } - static void -es1371_speed_changed(void *p) +es1371_speed_changed(void *priv) { - es1371_t *dev = (es1371_t *)p; + es1371_t *dev = (es1371_t *) priv; - dev->dac[1].latch = (uint64_t)((double)TIMER_USEC * (1000000.0 / 48000.0)); + dev->dac[1].latch = (uint64_t) ((double) TIMER_USEC * (1000000.0 / (double) SOUND_FREQ)); } - -static const device_config_t es1371_config[] = -{ +static const device_config_t es1371_config[] = { + // clang-format off { - .name = "codec", - .description = "CODEC", - .type = CONFIG_SELECTION, - .selection = { - { - .description = "Asahi Kasei AK4540", - .value = AC97_CODEC_AK4540 - }, { - .description = "Crystal CS4297", - .value = AC97_CODEC_CS4297 - }, { - .description = "Crystal CS4297A", - .value = AC97_CODEC_CS4297A - }, { - .description = "SigmaTel STAC9708", - .value = AC97_CODEC_STAC9708 - }, { - .description = "SigmaTel STAC9721", - .value = AC97_CODEC_STAC9721 - } - }, - .default_int = AC97_CODEC_CS4297A - }, - { - "receive_input", "Receive input (MIDI)", CONFIG_BINARY, "", 1 - }, - { - "", "", -1 - } + .name = "codec", + .description = "Codec", + .type = CONFIG_SELECTION, + .selection = { + { + .description = "Asahi Kasei AK4540", + .value = AC97_CODEC_AK4540 + }, + { + .description = "TriTech TR28023 / Creative CT1297", + .value = AC97_CODEC_TR28023 + }, + { .description = "" } + }, + .default_int = AC97_CODEC_TR28023 + }, + { + .name = "receive_input", + .description = "Receive input (MIDI)", + .type = CONFIG_BINARY, + .default_string = "", + .default_int = 1 + }, + { .name = "", .description = "", .type = CONFIG_END } + // clang-format on }; - -const device_t es1371_device = -{ - "Ensoniq AudioPCI (ES1371)", - "es1371", - DEVICE_PCI, - 0, - es1371_init, - es1371_close, - es1371_reset, - { NULL }, - es1371_speed_changed, - NULL, - es1371_config +static const device_config_t es1371_onboard_config[] = { + // clang-format off + { + .name = "receive_input", + .description = "Receive input (MIDI)", + .type = CONFIG_BINARY, + .default_string = "", + .default_int = 1 + }, + { .name = "", .description = "", .type = CONFIG_END } + // clang-format on }; -const device_t es1371_onboard_device = -{ - "Ensoniq AudioPCI (ES1371) (On-Board)", - "es1371_onboard", - DEVICE_PCI, - 1, - es1371_init, - es1371_close, - es1371_reset, - { NULL }, - es1371_speed_changed, - NULL, - NULL +const device_t es1371_device = { + .name = "Ensoniq AudioPCI (ES1371)", + .internal_name = "es1371", + .flags = DEVICE_PCI, + .local = 0, + .init = es1371_init, + .close = es1371_close, + .reset = es1371_reset, + { .available = NULL }, + .speed_changed = es1371_speed_changed, + .force_redraw = NULL, + .config = es1371_config +}; + +const device_t es1371_onboard_device = { + .name = "Ensoniq AudioPCI (ES1371) (On-Board)", + .internal_name = "es1371_onboard", + .flags = DEVICE_PCI, + .local = 1, + .init = es1371_init, + .close = es1371_close, + .reset = es1371_reset, + { .available = NULL }, + .speed_changed = es1371_speed_changed, + .force_redraw = NULL, + .config = es1371_onboard_config }; diff --git a/src/sound/snd_azt2316a.c b/src/sound/snd_azt2316a.c index fd8bf6555..80d668599 100644 --- a/src/sound/snd_azt2316a.c +++ b/src/sound/snd_azt2316a.c @@ -130,25 +130,27 @@ * are probably due to this. */ +#include #include -#include #include -#include +#include #include +#include #include -#include #define HAVE_STDARG_H + #include <86box/86box.h> -#include <86box/io.h> -#include <86box/timer.h> -#include <86box/pic.h> -#include <86box/nvr.h> #include <86box/device.h> -#include <86box/sound.h> +#include <86box/io.h> #include <86box/midi.h> +#include <86box/timer.h> +#include <86box/nvr.h> +#include <86box/pic.h> +#include <86box/sound.h> #include <86box/snd_ad1848.h> #include <86box/snd_azt2316a.h> #include <86box/snd_sb.h> +#include <86box/plat_unused.h> /*530, 11, 3 - 530=23*/ /*530, 11, 1 - 530=22*/ @@ -161,1328 +163,1444 @@ /*e80, 11, 1 - 530=22*/ /*f40, 11, 1 - 530=22*/ +static int azt2316a_wss_dma[4] = { 0, 0, 1, 3 }; +static int azt2316a_wss_irq[8] = { 5, 7, 9, 10, 11, 12, 14, 15 }; /* W95 only uses 7-10, others may be wrong */ +#if 0 +static uint16_t azt2316a_wss_addr[4] = {0x530, 0x604, 0xe80, 0xf40}; +#endif -static int azt2316a_wss_dma[4] = {0, 0, 1, 3}; -static int azt2316a_wss_irq[8] = {5, 7, 9, 10, 11, 12, 14, 15}; /* W95 only uses 7-10, others may be wrong */ -//static uint16_t azt2316a_wss_addr[4] = {0x530, 0x604, 0xe80, 0xf40}; +typedef struct azt2316a_t { + int type; + int wss_interrupt_after_config; -typedef struct azt2316a_t -{ - int type; - int wss_interrupt_after_config; + uint8_t wss_config; - uint8_t wss_config; + uint16_t cur_addr; + uint16_t cur_wss_addr; + uint16_t cur_mpu401_addr; - uint16_t cur_addr, cur_wss_addr, cur_mpu401_addr; + int cur_irq, cur_dma; + int cur_wss_enabled; + int cur_wss_irq; + int cur_wss_dma; + int cur_mpu401_irq; + int cur_mpu401_enabled; - int cur_irq, cur_dma; - int cur_wss_enabled, cur_wss_irq, cur_wss_dma; - int cur_mpu401_irq; - int cur_mpu401_enabled; + uint32_t config_word; + uint32_t config_word_unlocked; - uint32_t config_word; - uint32_t config_word_unlocked; + uint8_t cur_mode; - uint8_t cur_mode; + ad1848_t ad1848; + mpu_t *mpu; - ad1848_t ad1848; - mpu_t *mpu; - - sb_t *sb; + sb_t *sb; } azt2316a_t; -static uint8_t -azt2316a_wss_read(uint16_t addr, void *p) +static uint8_t +azt2316a_wss_read(uint16_t addr, void *priv) { - azt2316a_t *azt2316a = (azt2316a_t *)p; - uint8_t temp; + const azt2316a_t *azt2316a = (azt2316a_t *) priv; + uint8_t temp; - /* TODO: when windows is initializing, writing 0x48, 0x58 and 0x60 to - 0x530 makes reading from 0x533 return 0x44, but writing 0x50 - makes this return 0x04. Why? */ - if (addr & 1) - temp = 4 | (azt2316a->wss_config & 0x40); - else - temp = 4 | (azt2316a->wss_config & 0xC0); + /* TODO: when windows is initializing, writing 0x48, 0x58 and 0x60 to + 0x530 makes reading from 0x533 return 0x44, but writing 0x50 + makes this return 0x04. Why? */ + if (addr & 1) + temp = 4 | (azt2316a->wss_config & 0x40); + else + temp = 4 | (azt2316a->wss_config & 0xC0); - return temp; -} - -static void -azt2316a_wss_write(uint16_t addr, uint8_t val, void *p) + return temp; +} + +static void +azt2316a_wss_write(UNUSED(uint16_t addr), uint8_t val, void *priv) { - azt2316a_t *azt2316a = (azt2316a_t *)p; - int interrupt = 0; + azt2316a_t *azt2316a = (azt2316a_t *) priv; + int interrupt = 0; - if (azt2316a->wss_interrupt_after_config) { - if ((azt2316a->wss_config & 0x40) && !(val & 0x40)) { // TODO: is this the right edge? - interrupt = 1; - } - } + if (azt2316a->wss_interrupt_after_config) { + if ((azt2316a->wss_config & 0x40) && !(val & 0x40)) { // TODO: is this the right edge? + interrupt = 1; + } + } - azt2316a->wss_config = val; - azt2316a->cur_wss_dma = azt2316a_wss_dma[val & 3]; - azt2316a->cur_wss_irq = azt2316a_wss_irq[(val >> 3) & 7]; - ad1848_setdma(&azt2316a->ad1848, azt2316a_wss_dma[val & 3]); - ad1848_setirq(&azt2316a->ad1848, azt2316a_wss_irq[(val >> 3) & 7]); - - if (interrupt) - picint(1 << azt2316a->cur_wss_irq); + azt2316a->wss_config = val; + azt2316a->cur_wss_dma = azt2316a_wss_dma[val & 3]; + azt2316a->cur_wss_irq = azt2316a_wss_irq[(val >> 3) & 7]; + ad1848_setdma(&azt2316a->ad1848, azt2316a_wss_dma[val & 3]); + ad1848_setirq(&azt2316a->ad1848, azt2316a_wss_irq[(val >> 3) & 7]); + + if (interrupt) + picint(1 << azt2316a->cur_wss_irq); } /* generate a config word based on current settings */ -static void -azt1605_create_config_word(void *p) +static void +azt1605_create_config_word(void *priv) { - azt2316a_t *azt2316a = (azt2316a_t *)p; - uint32_t temp = 0; + azt2316a_t *azt2316a = (azt2316a_t *) priv; + uint32_t temp = 0; - /* not implemented / hardcoded */ - uint8_t game_enable = 1; - uint8_t cd_type = 0; /* TODO: see if the cd-rom was originally connected there on the real machines emulated by 86Box (Packard Bell Legend 100CD, Itautec Infoway Multimidia, etc) */ - uint8_t cd_dma8 = -1; - uint8_t cd_irq = 0; + /* not implemented / hardcoded */ + uint8_t game_enable = 1; + uint8_t cd_type = 0; /* TODO: see if the cd-rom was originally connected there on the real machines emulated by 86Box (Packard Bell Legend 100CD, Itautec Infoway Multimidia, etc) */ + uint8_t cd_dma8 = -1; + uint8_t cd_irq = 0; - switch (azt2316a->cur_addr) { - case 0x220: - /* do nothing - temp += 0 << 0; */ - break; - case 0x240: - temp += 1 << 0; - break; -/* - case 0x260: // TODO: INVALID? - temp += 2 << 0; - break; - case 0x280: // TODO: INVALID? - temp += 3 << 0; - break; -*/ - } + switch (azt2316a->cur_addr) { + case 0x220: + // do nothing +#if 0 + temp += 0 << 0; +#endif + break; + case 0x240: + temp += 1 << 0; + break; +#if 0 + case 0x260: // TODO: INVALID? + temp += 2 << 0; + break; + case 0x280: // TODO: INVALID? + temp += 3 << 0; + break; +#endif + default: + break; + } - switch (azt2316a->cur_irq) { - case 9: - temp += 1 << 8; - break; - case 3: - temp += 1 << 9; - break; - case 5: - temp += 1 << 10; - break; - case 7: - temp += 1 << 11; - break; - } - - switch (azt2316a->cur_wss_addr) { - case 0x530: - /* do nothing - temp += 0 << 16; */ - break; - case 0x604: - temp += 1 << 16; - break; - case 0xE80: - temp += 2 << 16; - break; - case 0xF40: - temp += 3 << 16; - break; - } - - if (azt2316a->cur_wss_enabled) - temp += 1 << 18; - - if (game_enable) - temp += 1 << 4; - - switch (azt2316a->cur_mpu401_addr) { - case 0x300: - /* do nothing - temp += 0 << 2; */ - break; - case 0x330: - temp += 1 << 2; - break; - } - - if (azt2316a->cur_mpu401_enabled) - temp += 1 << 3; - - switch (cd_type) { - case 0: /* disabled - do nothing - temp += 0 << 5; */ - break; - case 1: // panasonic - temp += 1 << 5; - break; - case 2: // mitsumi/sony/aztech - temp += 2 << 5; - break; - case 3: // all enabled - temp += 3 << 5; - break; - case 4: // unused - temp += 4 << 5; - break; - case 5: // unused - temp += 5 << 5; - break; - case 6: // unused - temp += 6 << 5; - break; - case 7: // unused - temp += 7 << 5; - break; - } - - switch (cd_dma8) { - case 0xFF: /* -1 - do nothing - temp += 0 << 22;*/ - break; - case 0: - temp += 1 << 22; - break; - case 1: - temp += 2 << 22; - break; - case 3: - temp += 3 << 22; - break; - } - - switch (azt2316a->cur_mpu401_irq) { - case 9: - temp += 1 << 12; - break; - case 3: - temp += 1 << 13; - break; - case 5: - temp += 1 << 14; - break; - case 7: - temp += 1 << 15; - break; - } - - switch (cd_irq) { - case 0: // disabled - // do nothing - break; - case 11: - temp += 1 << 19; - break; - case 12: - temp += 1 << 20; - break; - case 15: - temp += 1 << 21; - break; - } - - azt2316a->config_word = temp; -} - -static void -azt2316a_create_config_word(void *p) -{ - azt2316a_t *azt2316a = (azt2316a_t *)p; - uint32_t temp = 0; - - /* not implemented / hardcoded */ - uint8_t game_enable = 1; - uint16_t cd_addr = 0x310; - uint8_t cd_type = 0; /* TODO: see if the cd-rom was originally connected there on the real machines emulated by 86Box (Packard Bell Legend 100CD, Itautec Infoway Multimidia, etc) */ - uint8_t cd_dma8 = -1; - uint8_t cd_dma16 = -1; - uint8_t cd_irq = 15; - - if (azt2316a->type == SB_SUBTYPE_CLONE_AZT1605_0X0C) { - azt1605_create_config_word(p); - return; - } - - switch (azt2316a->cur_addr) { - case 0x220: - /* do nothing - temp += 0 << 0; */ - break; - case 0x240: - temp += 1 << 0; - break; -/* - case 0x260: // TODO: INVALID? - temp += 2 << 0; - break; - case 0x280: // TODO: INVALID? - temp += 3 << 0; - break; -*/ - } - - switch (azt2316a->cur_irq) { - case 9: - temp += 1 << 2; - break; - case 5: - temp += 1 << 3; - break; - case 7: - temp += 1 << 4; - break; - case 10: - temp += 1 << 5; - break; - } - - switch (azt2316a->cur_dma) { -/* - // TODO: INVALID? - case 0xFF: // -1 - // do nothing - //temp += 0 << 6; - break; -*/ - case 0: - temp += 1 << 6; - break; - case 1: - temp += 2 << 6; - break; - case 3: - temp += 3 << 6; - break; - } - - switch (azt2316a->cur_wss_addr) - { - case 0x530: - // do nothing - //temp += 0 << 8; - break; - case 0x604: - temp += 1 << 8; - break; - case 0xE80: - temp += 2 << 8; - break; - case 0xF40: - temp += 3 << 8; - break; - } - if (azt2316a->cur_wss_enabled) + switch (azt2316a->cur_irq) { + case 9: + temp += 1 << 8; + break; + case 3: + temp += 1 << 9; + break; + case 5: temp += 1 << 10; - if (game_enable) + break; + case 7: temp += 1 << 11; - switch (azt2316a->cur_mpu401_addr) - { - case 0x300: - // do nothing - //temp += 0 << 12; + break; + + default: + break; + } + + switch (azt2316a->cur_wss_addr) { + case 0x530: + // do nothing +#if 0 + temp += 0 << 16; +#endif + break; + case 0x604: + temp += 1 << 16; + break; + case 0xE80: + temp += 2 << 16; + break; + case 0xF40: + temp += 3 << 16; + break; + + default: + break; + } + + if (azt2316a->cur_wss_enabled) + temp += 1 << 18; + + if (game_enable) + temp += 1 << 4; + + switch (azt2316a->cur_mpu401_addr) { + case 0x300: + // do nothing +#if 0 + temp += 0 << 2; +#endif + break; + case 0x330: + temp += 1 << 2; + break; + + default: + break; + } + + if (azt2316a->cur_mpu401_enabled) + temp += 1 << 3; + + switch (cd_type) { + case 0: /* disabled + do nothing + temp += 0 << 5; */ + break; + case 1: // panasonic + temp += 1 << 5; + break; + case 2: // mitsumi/sony/aztech + temp += 2 << 5; + break; + case 3: // all enabled + temp += 3 << 5; + break; + case 4: // unused + temp += 4 << 5; + break; + case 5: // unused + temp += 5 << 5; + break; + case 6: // unused + temp += 6 << 5; + break; + case 7: // unused + temp += 7 << 5; + break; + + default: + break; + } + + switch (cd_dma8) { + case 0xFF: /* -1 + do nothing + temp += 0 << 22;*/ + break; + case 0: + temp += 1 << 22; + break; + case 1: + temp += 2 << 22; + break; + case 3: + temp += 3 << 22; + break; + + default: + break; + } + + switch (azt2316a->cur_mpu401_irq) { + case 9: + temp += 1 << 12; + break; + case 3: + temp += 1 << 13; + break; + case 5: + temp += 1 << 14; + break; + case 7: + temp += 1 << 15; + break; + + default: + break; + } + + switch (cd_irq) { + case 0: // disabled + // do nothing + break; + case 11: + temp += 1 << 19; + break; + case 12: + temp += 1 << 20; + break; + case 15: + temp += 1 << 21; + break; + + default: + break; + } + + azt2316a->config_word = temp; +} + +static void +azt2316a_create_config_word(void *priv) +{ + azt2316a_t *azt2316a = (azt2316a_t *) priv; + uint32_t temp = 0; + + /* not implemented / hardcoded */ + uint8_t game_enable = 1; + uint16_t cd_addr = 0x310; + uint8_t cd_type = 0; /* TODO: see if the cd-rom was originally connected there on the real machines emulated by 86Box (Packard Bell Legend 100CD, Itautec Infoway Multimidia, etc) */ + uint8_t cd_dma8 = -1; + uint8_t cd_dma16 = -1; + uint8_t cd_irq = 15; + + if (azt2316a->type == SB_SUBTYPE_CLONE_AZT1605_0X0C) { + azt1605_create_config_word(priv); + return; + } + + switch (azt2316a->cur_addr) { + case 0x220: + // do nothing +#if 0 + temp += 0 << 0; +#endif + break; + case 0x240: + temp += 1 << 0; + break; +#if 0 + case 0x260: // TODO: INVALID? + temp += 2 << 0; + break; + case 0x280: // TODO: INVALID? + temp += 3 << 0; + break; +#endif + default: + break; + } + + switch (azt2316a->cur_irq) { + case 9: + temp += 1 << 2; + break; + case 5: + temp += 1 << 3; + break; + case 7: + temp += 1 << 4; + break; + case 10: + temp += 1 << 5; + break; + + default: + break; + } + + switch (azt2316a->cur_dma) { +#if 0 + // TODO: INVALID? + case 0xFF: // -1 + // do nothing + //temp += 0 << 6; + break; +#endif + case 0: + temp += 1 << 6; + break; + case 1: + temp += 2 << 6; + break; + case 3: + temp += 3 << 6; + break; + + default: + break; + } + + switch (azt2316a->cur_wss_addr) { + case 0x530: + // do nothing +#if 0 + temp += 0 << 8; +#endif + break; + case 0x604: + temp += 1 << 8; + break; + case 0xE80: + temp += 2 << 8; + break; + case 0xF40: + temp += 3 << 8; + break; + + default: + break; + } + if (azt2316a->cur_wss_enabled) + temp += 1 << 10; + if (game_enable) + temp += 1 << 11; + switch (azt2316a->cur_mpu401_addr) { + case 0x300: + // do nothing +#if 0 + temp += 0 << 12; +#endif + break; + case 0x330: + temp += 1 << 12; + break; + + default: + break; + } + + if (azt2316a->cur_mpu401_enabled) + temp += 1 << 13; + + switch (cd_addr) { + case 0x310: + // do nothing +#if 0 + temp += 0 << 14; +#endif + break; + case 0x320: + temp += 1 << 14; + break; + case 0x340: + temp += 2 << 14; + break; + case 0x350: + temp += 3 << 14; + break; + + default: + break; + } + switch (cd_type) { + case 0: /* disabled */ + // do nothing +#if 0 + temp += 0 << 16; */ +#endif + break; + case 1: /* panasonic */ + temp += 1 << 16; + break; + case 2: /* sony */ + temp += 2 << 16; + break; + case 3: /* mitsumi */ + temp += 3 << 16; + break; + case 4: /* aztech */ + temp += 4 << 16; + break; + case 5: /* unused */ + temp += 5 << 16; + break; + case 6: /* unused */ + temp += 6 << 16; + break; + case 7: /* unused */ + temp += 7 << 16; + break; + + default: + break; + } + + switch (cd_dma8) { + case 0xFF: /* -1 + do nothing + temp += 0 << 20; */ + break; + case 0: + temp += 1 << 20; + break; +#if 0 + case 1: // TODO: INVALID? + temp += 2 << 20; + break; +#endif + case 3: + temp += 3 << 20; + break; + + default: + break; + } + + switch (cd_dma16) { + case 0xFF: /* -1 + do nothing + temp += 0 << 22; */ + break; + case 5: + temp += 1 << 22; + break; + case 6: + temp += 2 << 22; + break; + case 7: + temp += 3 << 22; + break; + + default: + break; + } + + switch (azt2316a->cur_mpu401_irq) { + case 9: + temp += 1 << 24; + break; + case 5: + temp += 1 << 25; + break; + case 7: + temp += 1 << 26; + break; + case 10: + temp += 1 << 27; + break; + + default: + break; + } + + switch (cd_irq) { + case 5: + temp += 1 << 28; + break; + case 11: + temp += 1 << 29; + break; + case 12: + temp += 1 << 30; + break; + case 15: + temp += 1 << 31; + break; + + default: + break; + } + + azt2316a->config_word = temp; +} + +static uint8_t +azt2316a_config_read(uint16_t addr, void *priv) +{ + const azt2316a_t *azt2316a = (azt2316a_t *) priv; + uint8_t temp = 0; + + /* Some WSS config here + config change enable bit + (setting bit 7 and writing back) */ + + if (addr == (azt2316a->cur_addr + 0x404)) { + /* TODO: what is the real meaning of the read value? + I got a mention of bit 0x10 for WSS from disassembling the source + code of the driver, and when playing with the I/O ports on real + hardware after doing some configuration, but didn't dig into it. + Bit 0x08 seems to be a busy flag and generates a timeout + (continuous re-reading when initializing windows 98) */ + temp = azt2316a->cur_mode ? 0x07 : 0x0F; + if (azt2316a->config_word_unlocked) { + temp |= 0x80; + } + } else { + // Rest of config. These are documented in the Linux driver. + switch (addr & 0x3) { + case 0: + temp = azt2316a->config_word & 0xFF; break; - case 0x330: - temp += 1 << 12; + case 1: + temp = (azt2316a->config_word >> 8); + break; + case 2: + temp = (azt2316a->config_word >> 16); + break; + case 3: + temp = (azt2316a->config_word >> 24); + break; + + default: break; } - - if (azt2316a->cur_mpu401_enabled) - temp += 1 << 13; - - switch (cd_addr) { - case 0x310: - // do nothing - //temp += 0 << 14; - break; - case 0x320: - temp += 1 << 14; - break; - case 0x340: - temp += 2 << 14; - break; - case 0x350: - temp += 3 << 14; - break; - } - switch (cd_type) { - case 0: /* disabled - do nothing - temp += 0 << 16; */ - break; - case 1: /* panasonic */ - temp += 1 << 16; - break; - case 2: /* sony */ - temp += 2 << 16; - break; - case 3: /* mitsumi */ - temp += 3 << 16; - break; - case 4: /* aztech */ - temp += 4 << 16; - break; - case 5: /* unused */ - temp += 5 << 16; - break; - case 6: /* unused */ - temp += 6 << 16; - break; - case 7: /* unused */ - temp += 7 << 16; - break; - } - - switch (cd_dma8) { - case 0xFF: /* -1 - do nothing - temp += 0 << 20; */ - break; - case 0: - temp += 1 << 20; - break; -/* - case 1: // TODO: INVALID? - temp += 2 << 20; - break; -*/ - case 3: - temp += 3 << 20; - break; - } - - switch (cd_dma16) { - case 0xFF: /* -1 - do nothing - temp += 0 << 22; */ - break; - case 5: - temp += 1 << 22; - break; - case 6: - temp += 2 << 22; - break; - case 7: - temp += 3 << 22; - break; - } - - switch (azt2316a->cur_mpu401_irq) { - case 9: - temp += 1 << 24; - break; - case 5: - temp += 1 << 25; - break; - case 7: - temp += 1 << 26; - break; - case 10: - temp += 1 << 27; - break; - } - - switch (cd_irq) { - case 5: - temp += 1 << 28; - break; - case 11: - temp += 1 << 29; - break; - case 12: - temp += 1 << 30; - break; - case 15: - temp += 1 << 31; - break; - } + } - azt2316a->config_word = temp; + return temp; } -static uint8_t -azt2316a_config_read(uint16_t addr, void *p) +static void +azt1605_config_write(uint16_t addr, uint8_t val, void *priv) { - azt2316a_t *azt2316a = (azt2316a_t *)p; - uint8_t temp = 0; + azt2316a_t *azt2316a = (azt2316a_t *) priv; + uint8_t temp; - /* Some WSS config here + config change enable bit - (setting bit 7 and writing back) */ - - if (addr == (azt2316a->cur_addr + 0x404)) { - /* TODO: what is the real meaning of the read value? - I got a mention of bit 0x10 for WSS from disassembling the source - code of the driver, and when playing with the I/O ports on real - hardware after doing some configuration, but didn't dig into it. - Bit 0x08 seems to be a busy flag and generates a timeout - (continuous re-reading when initializing windows 98) */ - temp = azt2316a->cur_mode ? 0x07 : 0x0F; - if (azt2316a->config_word_unlocked) { - temp |= 0x80; - } - } else { - // Rest of config. These are documented in the Linux driver. - switch (addr & 0x3) - { - case 0: - temp = azt2316a->config_word & 0xFF; - break; - case 1: - temp = (azt2316a->config_word >> 8); - break; - case 2: - temp = (azt2316a->config_word >> 16); - break; - case 3: - temp = (azt2316a->config_word >> 24); - break; - } + if (addr == (azt2316a->cur_addr + 0x404)) { + if (val & 0x80) + azt2316a->config_word_unlocked = 1; + else + azt2316a->config_word_unlocked = 0; + } else if (azt2316a->config_word_unlocked) { + if (val == 0xFF) { /* TODO: check if this still happens on eeprom.sys after having more complete emulation! */ + return; } + switch (addr & 3) { + case 0: + azt2316a->config_word = (azt2316a->config_word & 0xFFFFFF00) | val; - return temp; -} - - -static void -azt1605_config_write(uint16_t addr, uint8_t val, void *p) -{ - azt2316a_t *azt2316a = (azt2316a_t *)p; - uint8_t temp; - - if (addr == (azt2316a->cur_addr + 0x404)) { - if (val & 0x80) - azt2316a->config_word_unlocked = 1; + temp = val & 3; + if (temp == 0) + azt2316a->cur_addr = 0x220; + else if (temp == 1) + azt2316a->cur_addr = 0x240; +#if 0 + else if (temp == 2) + azt2316a->cur_addr = 0x260; // TODO: INVALID + else if (temp == 3) + azt2316a->cur_addr = 0x280; // TODO: INVALID +#endif + if (val & 0x4) + azt2316a->cur_mpu401_addr = 0x330; else - azt2316a->config_word_unlocked = 0; - } else if (azt2316a->config_word_unlocked) { - if (val == 0xFF) { /* TODO: check if this still happens on eeprom.sys after having more complete emulation! */ - return; - } - switch (addr & 3) { - case 0: - azt2316a->config_word = (azt2316a->config_word & 0xFFFFFF00) | val; + azt2316a->cur_mpu401_addr = 0x300; - temp = val & 3; - if (temp == 0) - azt2316a->cur_addr = 0x220; - else if (temp == 1) - azt2316a->cur_addr = 0x240; -/* - else if (temp == 2) - azt2316a->cur_addr = 0x260; // TODO: INVALID - else if (temp == 3) - azt2316a->cur_addr = 0x280; // TODO: INVALID -*/ - if (val & 0x4) - azt2316a->cur_mpu401_addr = 0x330; - else - azt2316a->cur_mpu401_addr = 0x300; - - if (val & 0x8) - azt2316a->cur_mpu401_enabled = 1; - else - azt2316a->cur_mpu401_enabled = 0; - break; - case 1: - azt2316a->config_word = (azt2316a->config_word & 0xFFFF00FF) | (val << 8); + if (val & 0x8) + azt2316a->cur_mpu401_enabled = 1; + else + azt2316a->cur_mpu401_enabled = 0; + break; + case 1: + azt2316a->config_word = (azt2316a->config_word & 0xFFFF00FF) | (val << 8); - if (val & 0x1) - azt2316a->cur_irq = 9; - else if (val & 0x2) - azt2316a->cur_irq = 3; - else if (val & 0x4) - azt2316a->cur_irq = 5; - else if (val & 0x8) - azt2316a->cur_irq = 7; - /* else undefined? */ + if (val & 0x1) + azt2316a->cur_irq = 9; + else if (val & 0x2) + azt2316a->cur_irq = 3; + else if (val & 0x4) + azt2316a->cur_irq = 5; + else if (val & 0x8) + azt2316a->cur_irq = 7; + /* else undefined? */ - if (val & 0x10) - azt2316a->cur_mpu401_irq = 9; - else if (val & 0x20) - azt2316a->cur_mpu401_irq = 3; - else if (val & 0x40) - azt2316a->cur_mpu401_irq = 5; - else if (val & 0x80) - azt2316a->cur_mpu401_irq = 7; - /* else undefined? */ - break; - case 2: - azt2316a->config_word = (azt2316a->config_word & 0xFF00FFFF) | (val << 16); + if (val & 0x10) + azt2316a->cur_mpu401_irq = 9; + else if (val & 0x20) + azt2316a->cur_mpu401_irq = 3; + else if (val & 0x40) + azt2316a->cur_mpu401_irq = 5; + else if (val & 0x80) + azt2316a->cur_mpu401_irq = 7; + /* else undefined? */ + break; + case 2: + azt2316a->config_word = (azt2316a->config_word & 0xFF00FFFF) | (val << 16); - io_removehandler(azt2316a->cur_wss_addr, 0x0004, azt2316a_wss_read, NULL, NULL, azt2316a_wss_write, NULL, NULL, azt2316a); - io_removehandler(azt2316a->cur_wss_addr + 0x0004, 0x0004, ad1848_read, NULL, NULL, ad1848_write, NULL, NULL, &azt2316a->ad1848); + io_removehandler(azt2316a->cur_wss_addr, 0x0004, azt2316a_wss_read, NULL, NULL, azt2316a_wss_write, NULL, NULL, azt2316a); + io_removehandler(azt2316a->cur_wss_addr + 0x0004, 0x0004, ad1848_read, NULL, NULL, ad1848_write, NULL, NULL, &azt2316a->ad1848); - temp = val & 0x3; - if (temp == 0) - azt2316a->cur_wss_addr = 0x530; - else if (temp == 1) - azt2316a->cur_wss_addr = 0x604; - else if (temp == 2) - azt2316a->cur_wss_addr = 0xE80; - else if (temp == 3) - azt2316a->cur_wss_addr = 0xF40; + temp = val & 0x3; + if (temp == 0) + azt2316a->cur_wss_addr = 0x530; + else if (temp == 1) + azt2316a->cur_wss_addr = 0x604; + else if (temp == 2) + azt2316a->cur_wss_addr = 0xE80; + else if (temp == 3) + azt2316a->cur_wss_addr = 0xF40; - io_sethandler(azt2316a->cur_wss_addr, 0x0004, azt2316a_wss_read, NULL, NULL, azt2316a_wss_write, NULL, NULL, azt2316a); - io_sethandler(azt2316a->cur_wss_addr + 0x0004, 0x0004, ad1848_read, NULL, NULL, ad1848_write, NULL, NULL, &azt2316a->ad1848); + io_sethandler(azt2316a->cur_wss_addr, 0x0004, azt2316a_wss_read, NULL, NULL, azt2316a_wss_write, NULL, NULL, azt2316a); + io_sethandler(azt2316a->cur_wss_addr + 0x0004, 0x0004, ad1848_read, NULL, NULL, ad1848_write, NULL, NULL, &azt2316a->ad1848); - /* no actual effect */ - if (val & 0x4) - azt2316a->cur_wss_enabled = 1; - else - azt2316a->cur_wss_enabled = 0; - break; - case 3: - break; - } - /* update sbprov2 configs */ - sb_dsp_setaddr(&azt2316a->sb->dsp, azt2316a->cur_addr); - sb_dsp_setirq(&azt2316a->sb->dsp, azt2316a->cur_irq); - sb_dsp_setdma8(&azt2316a->sb->dsp, azt2316a->cur_dma); - - mpu401_change_addr(azt2316a->mpu, azt2316a->cur_mpu401_addr); - mpu401_setirq(azt2316a->mpu, azt2316a->cur_mpu401_irq); + /* no actual effect */ + if (val & 0x4) + azt2316a->cur_wss_enabled = 1; + else + azt2316a->cur_wss_enabled = 0; + break; + case 3: + break; + + default: + break; } + /* update sbprov2 configs */ + sb_dsp_setaddr(&azt2316a->sb->dsp, azt2316a->cur_addr); + sb_dsp_setirq(&azt2316a->sb->dsp, azt2316a->cur_irq); + sb_dsp_setdma8(&azt2316a->sb->dsp, azt2316a->cur_dma); + + mpu401_change_addr(azt2316a->mpu, azt2316a->cur_mpu401_addr); + mpu401_setirq(azt2316a->mpu, azt2316a->cur_mpu401_irq); + } } -static void -azt2316a_config_write(uint16_t addr, uint8_t val, void *p) +static void +azt2316a_config_write(uint16_t addr, uint8_t val, void *priv) { - azt2316a_t *azt2316a = (azt2316a_t *)p; - uint8_t temp; + azt2316a_t *azt2316a = (azt2316a_t *) priv; + uint8_t temp; - if (azt2316a->type == SB_SUBTYPE_CLONE_AZT1605_0X0C) { - azt1605_config_write(addr, val, azt2316a); - return; - } + if (azt2316a->type == SB_SUBTYPE_CLONE_AZT1605_0X0C) { + azt1605_config_write(addr, val, azt2316a); + return; + } - if (addr == (azt2316a->cur_addr + 0x404)) { - if (val & 0x80) - azt2316a->config_word_unlocked = 1; + if (addr == (azt2316a->cur_addr + 0x404)) { + if (val & 0x80) + azt2316a->config_word_unlocked = 1; + else + azt2316a->config_word_unlocked = 0; + } else if (azt2316a->config_word_unlocked) { + if (val == 0xFF) // TODO: check if this still happens on eeprom.sys after having more complete emulation! + return; + switch (addr & 3) { + case 0: + azt2316a->config_word = (azt2316a->config_word & 0xFFFFFF00) | val; + temp = val & 3; + + if (temp == 0) + azt2316a->cur_addr = 0x220; + else if (temp == 1) + azt2316a->cur_addr = 0x240; + + if (val & 0x4) + azt2316a->cur_irq = 9; + else if (val & 0x8) + azt2316a->cur_irq = 5; + else if (val & 0x10) + azt2316a->cur_irq = 7; + else if (val & 0x20) + azt2316a->cur_irq = 10; + + temp = (val >> 6) & 3; + if (temp == 1) + azt2316a->cur_dma = 0; + else if (temp == 2) + azt2316a->cur_dma = 1; + else if (temp == 3) + azt2316a->cur_dma = 3; + break; + case 1: + azt2316a->config_word = (azt2316a->config_word & 0xFFFF00FF) | (val << 8); + + io_removehandler(azt2316a->cur_wss_addr, 0x0004, azt2316a_wss_read, NULL, NULL, azt2316a_wss_write, NULL, NULL, azt2316a); + io_removehandler(azt2316a->cur_wss_addr + 0x0004, 0x0004, ad1848_read, NULL, NULL, ad1848_write, NULL, NULL, &azt2316a->ad1848); + + temp = val & 0x3; + if (temp == 0) + azt2316a->cur_wss_addr = 0x530; + else if (temp == 1) + azt2316a->cur_wss_addr = 0x604; + else if (temp == 2) + azt2316a->cur_wss_addr = 0xE80; + else if (temp == 3) + azt2316a->cur_wss_addr = 0xF40; + + io_sethandler(azt2316a->cur_wss_addr, 0x0004, azt2316a_wss_read, NULL, NULL, azt2316a_wss_write, NULL, NULL, azt2316a); + io_sethandler(azt2316a->cur_wss_addr + 0x0004, 0x0004, ad1848_read, NULL, NULL, ad1848_write, NULL, NULL, &azt2316a->ad1848); + + /* no actual effect */ + if (val & 0x4) + azt2316a->cur_wss_enabled = 1; else - azt2316a->config_word_unlocked = 0; - } else if (azt2316a->config_word_unlocked) { - if (val == 0xFF) // TODO: check if this still happens on eeprom.sys after having more complete emulation! - return; - switch (addr & 3) { - case 0: - azt2316a->config_word = (azt2316a->config_word & 0xFFFFFF00) | val; - temp = val & 3; - - if (temp == 0) - azt2316a->cur_addr = 0x220; - else if (temp == 1) - azt2316a->cur_addr = 0x240; + azt2316a->cur_wss_enabled = 0; - if (val & 0x4) - azt2316a->cur_irq = 9; - else if (val & 0x8) - azt2316a->cur_irq = 5; - else if (val & 0x10) - azt2316a->cur_irq = 7; - else if (val & 0x20) - azt2316a->cur_irq = 10; + if (val & 0x10) + azt2316a->cur_mpu401_addr = 0x330; + else + azt2316a->cur_mpu401_addr = 0x300; - temp = (val >> 6) & 3; - if (temp == 1) - azt2316a->cur_dma = 0; - else if (temp == 2) - azt2316a->cur_dma = 1; - else if (temp == 3) - azt2316a->cur_dma = 3; - break; - case 1: - azt2316a->config_word = (azt2316a->config_word & 0xFFFF00FF) | (val << 8); - - io_removehandler(azt2316a->cur_wss_addr, 0x0004, azt2316a_wss_read, NULL, NULL, azt2316a_wss_write, NULL, NULL, azt2316a); - io_removehandler(azt2316a->cur_wss_addr + 0x0004, 0x0004, ad1848_read, NULL, NULL, ad1848_write, NULL, NULL, &azt2316a->ad1848); + if (val & 0x20) + azt2316a->cur_mpu401_enabled = 1; + else + azt2316a->cur_mpu401_enabled = 0; + break; + case 2: + azt2316a->config_word = (azt2316a->config_word & 0xFF00FFFF) | (val << 16); + break; + case 3: + azt2316a->config_word = (azt2316a->config_word & 0x00FFFFFF) | (val << 24); - temp = val & 0x3; - if (temp == 0) - azt2316a->cur_wss_addr = 0x530; - else if (temp == 1) - azt2316a->cur_wss_addr = 0x604; - else if (temp == 2) - azt2316a->cur_wss_addr = 0xE80; - else if (temp == 3) - azt2316a->cur_wss_addr = 0xF40; + if (val & 0x1) + azt2316a->cur_mpu401_irq = 9; + else if (val & 0x2) + azt2316a->cur_mpu401_irq = 5; + else if (val & 0x4) + azt2316a->cur_mpu401_irq = 7; + else if (val & 0x8) + azt2316a->cur_mpu401_irq = 10; + /* else undefined? */ + break; - io_sethandler(azt2316a->cur_wss_addr, 0x0004, azt2316a_wss_read, NULL, NULL, azt2316a_wss_write, NULL, NULL, azt2316a); - io_sethandler(azt2316a->cur_wss_addr + 0x0004, 0x0004, ad1848_read, NULL, NULL, ad1848_write, NULL, NULL, &azt2316a->ad1848); - - /* no actual effect */ - if (val & 0x4) - azt2316a->cur_wss_enabled = 1; - else - azt2316a->cur_wss_enabled = 0; - - if (val & 0x10) - azt2316a->cur_mpu401_addr = 0x330; - else - azt2316a->cur_mpu401_addr = 0x300; - - if (val & 0x20) - azt2316a->cur_mpu401_enabled = 1; - else - azt2316a->cur_mpu401_enabled = 0; - break; - case 2: - azt2316a->config_word = (azt2316a->config_word & 0xFF00FFFF) | (val << 16); - break; - case 3: - azt2316a->config_word = (azt2316a->config_word & 0x00FFFFFF) | (val << 24); - - if (val & 0x1) - azt2316a->cur_mpu401_irq = 9; - else if (val & 0x2) - azt2316a->cur_mpu401_irq = 5; - else if (val & 0x4) - azt2316a->cur_mpu401_irq = 7; - else if (val & 0x8) - azt2316a->cur_mpu401_irq = 10; - /* else undefined? */ - break; - } - /* update sbprov2 configs */ - sb_dsp_setaddr(&azt2316a->sb->dsp, azt2316a->cur_addr); - sb_dsp_setirq(&azt2316a->sb->dsp, azt2316a->cur_irq); - sb_dsp_setdma8(&azt2316a->sb->dsp, azt2316a->cur_dma); - - mpu401_change_addr(azt2316a->mpu, azt2316a->cur_mpu401_addr); - mpu401_setirq(azt2316a->mpu, azt2316a->cur_mpu401_irq); + default: + break; } + /* update sbprov2 configs */ + sb_dsp_setaddr(&azt2316a->sb->dsp, azt2316a->cur_addr); + sb_dsp_setirq(&azt2316a->sb->dsp, azt2316a->cur_irq); + sb_dsp_setdma8(&azt2316a->sb->dsp, azt2316a->cur_dma); + + mpu401_change_addr(azt2316a->mpu, azt2316a->cur_mpu401_addr); + mpu401_setirq(azt2316a->mpu, azt2316a->cur_mpu401_irq); + } } /* How it behaves when one or another is activated may affect games auto-detecting (and will also use more of the limited system resources!) */ -void -azt2316a_enable_wss(uint8_t enable, void *p) +void +azt2316a_enable_wss(uint8_t enable, void *priv) { - azt2316a_t *azt2316a = (azt2316a_t *)p; + azt2316a_t *azt2316a = (azt2316a_t *) priv; - if (enable) - azt2316a->cur_mode = 1; - else - azt2316a->cur_mode = 0; + if (enable) + azt2316a->cur_mode = 1; + else + azt2316a->cur_mode = 0; } -static void -azt2316a_get_buffer(int32_t *buffer, int len, void *p) +static void +azt2316a_get_buffer(int32_t *buffer, int len, void *priv) { - azt2316a_t *azt2316a = (azt2316a_t *)p; - int c; + azt2316a_t *azt2316a = (azt2316a_t *) priv; - /* wss part */ - ad1848_update(&azt2316a->ad1848); - for (c = 0; c < len * 2; c++) - buffer[c] += (azt2316a->ad1848.buffer[c] / 2); + /* wss part */ + ad1848_update(&azt2316a->ad1848); + for (int c = 0; c < len * 2; c++) + buffer[c] += (azt2316a->ad1848.buffer[c] / 2); - azt2316a->ad1848.pos = 0; + azt2316a->ad1848.pos = 0; - /* sbprov2 part */ - sb_get_buffer_sbpro(buffer, len, azt2316a->sb); + /* sbprov2 part */ + sb_get_buffer_sbpro(buffer, len, azt2316a->sb); } static void * azt_init(const device_t *info) { - FILE *f; - char *fn = NULL; - int i; - int loaded_from_eeprom = 0; - uint16_t addr_setting; - uint8_t read_eeprom[AZTECH_EEPROM_SIZE]; - azt2316a_t *azt2316a = malloc(sizeof(azt2316a_t)); - memset(azt2316a, 0, sizeof(azt2316a_t)); - - azt2316a->type = info->local; - - if (azt2316a->type == SB_SUBTYPE_CLONE_AZT1605_0X0C) { - fn = "azt1605.nvr"; - } else if (azt2316a->type == SB_SUBTYPE_CLONE_AZT2316A_0X11) { - fn = "azt2316a.nvr"; - } + FILE *fp; + char *fn = NULL; + int i; + int loaded_from_eeprom = 0; + uint16_t addr_setting; + uint8_t read_eeprom[AZTECH_EEPROM_SIZE]; + azt2316a_t *azt2316a = malloc(sizeof(azt2316a_t)); + memset(azt2316a, 0, sizeof(azt2316a_t)); - /* config */ - f = nvr_fopen(fn, "rb"); - if (f) { - uint8_t checksum = 0x7f; - uint8_t saved_checksum; - size_t res; - - res = fread(read_eeprom, AZTECH_EEPROM_SIZE, 1, f); - for (i = 0; i < AZTECH_EEPROM_SIZE; i++) - checksum += read_eeprom[i]; - - res = fread(&saved_checksum, sizeof(saved_checksum), 1, f); - (void)res; + azt2316a->type = info->local; - fclose(f); - - if (checksum == saved_checksum) - loaded_from_eeprom = 1; + if (azt2316a->type == SB_SUBTYPE_CLONE_AZT1605_0X0C) { + fn = "azt1605.nvr"; + } else if (azt2316a->type == SB_SUBTYPE_CLONE_AZT2316A_0X11) { + fn = "azt2316a.nvr"; + } + + /* config */ + fp = nvr_fopen(fn, "rb"); + if (fp) { + uint8_t checksum = 0x7f; + uint8_t saved_checksum; + size_t res; + + res = fread(read_eeprom, AZTECH_EEPROM_SIZE, 1, fp); + for (i = 0; i < AZTECH_EEPROM_SIZE; i++) + checksum += read_eeprom[i]; + + res = fread(&saved_checksum, sizeof(saved_checksum), 1, fp); + (void) res; + + fclose(fp); + + if (checksum == saved_checksum) + loaded_from_eeprom = 1; + } + + if (!loaded_from_eeprom) { + if (azt2316a->type == SB_SUBTYPE_CLONE_AZT2316A_0X11) { + read_eeprom[0] = 0x00; + read_eeprom[1] = 0x00; + read_eeprom[2] = 0x00; + read_eeprom[3] = 0x00; + read_eeprom[4] = 0x00; + read_eeprom[5] = 0x00; + read_eeprom[6] = 0x00; + read_eeprom[7] = 0x00; + read_eeprom[8] = 0x00; + read_eeprom[9] = 0x00; + read_eeprom[10] = 0x00; + read_eeprom[11] = 0x88; + read_eeprom[12] = 0xbc; + read_eeprom[13] = 0x00; + read_eeprom[14] = 0x01; + read_eeprom[15] = 0x00; + } else if (azt2316a->type == SB_SUBTYPE_CLONE_AZT1605_0X0C) { + read_eeprom[0] = 0x80; + read_eeprom[1] = 0x80; + read_eeprom[2] = 0x9F; + read_eeprom[3] = 0x13; + read_eeprom[4] = 0x16; + read_eeprom[5] = 0x13; + read_eeprom[6] = 0x00; + read_eeprom[7] = 0x00; + read_eeprom[8] = 0x16; + read_eeprom[9] = 0x0B; + read_eeprom[10] = 0x06; + read_eeprom[11] = 0x01; + read_eeprom[12] = 0x1C; + read_eeprom[13] = 0x14; + read_eeprom[14] = 0x04; + read_eeprom[15] = 0x1C; } - - if (!loaded_from_eeprom) { - if (azt2316a->type == SB_SUBTYPE_CLONE_AZT2316A_0X11) { - read_eeprom[0] = 0x00; - read_eeprom[1] = 0x00; - read_eeprom[2] = 0x00; - read_eeprom[3] = 0x00; - read_eeprom[4] = 0x00; - read_eeprom[5] = 0x00; - read_eeprom[6] = 0x00; - read_eeprom[7] = 0x00; - read_eeprom[8] = 0x00; - read_eeprom[9] = 0x00; - read_eeprom[10] = 0x00; - read_eeprom[11] = 0x88; - read_eeprom[12] = 0xbc; - read_eeprom[13] = 0x00; - read_eeprom[14] = 0x01; - read_eeprom[15] = 0x00; - } else if (azt2316a->type == SB_SUBTYPE_CLONE_AZT1605_0X0C) { - read_eeprom[0] = 0x80; - read_eeprom[1] = 0x80; - read_eeprom[2] = 0x9F; - read_eeprom[3] = 0x13; - read_eeprom[4] = 0x16; - read_eeprom[5] = 0x13; - read_eeprom[6] = 0x00; - read_eeprom[7] = 0x00; - read_eeprom[8] = 0x16; - read_eeprom[9] = 0x0B; - read_eeprom[10] = 0x06; - read_eeprom[11] = 0x01; - read_eeprom[12] = 0x1C; - read_eeprom[13] = 0x14; - read_eeprom[14] = 0x04; - read_eeprom[15] = 0x1C; - } - } + } - if (azt2316a->type == SB_SUBTYPE_CLONE_AZT2316A_0X11) { - azt2316a->config_word = read_eeprom[11] | (read_eeprom[12] << 8) | (read_eeprom[13] << 16) | (read_eeprom[14] << 24); + if (azt2316a->type == SB_SUBTYPE_CLONE_AZT2316A_0X11) { + azt2316a->config_word = read_eeprom[11] | (read_eeprom[12] << 8) | (read_eeprom[13] << 16) | (read_eeprom[14] << 24); - switch (azt2316a->config_word & (3 << 0)) { - case 0: - azt2316a->cur_addr = 0x220; - break; - case 1: - azt2316a->cur_addr = 0x240; - break; - default: - fatal("AZT2316A: invalid sb addr in config word %08X\n", azt2316a->config_word); - } - - if (azt2316a->config_word & (1 << 2)) - azt2316a->cur_irq = 9; - else if (azt2316a->config_word & (1 << 3)) - azt2316a->cur_irq = 5; - else if (azt2316a->config_word & (1 << 4)) - azt2316a->cur_irq = 7; - else if (azt2316a->config_word & (1 << 5)) - azt2316a->cur_irq = 10; - else - fatal("AZT2316A: invalid sb irq in config word %08X\n", azt2316a->config_word); - - switch (azt2316a->config_word & (3 << 6)) { - case 1 << 6: - azt2316a->cur_dma = 0; - break; - case 2 << 6: - azt2316a->cur_dma = 1; - break; - case 3 << 6: - azt2316a->cur_dma = 3; - break; - default: - fatal("AZT2316A: invalid sb dma in config word %08X\n", azt2316a->config_word); - } - - switch (azt2316a->config_word & (3 << 8)) { - case 0: - azt2316a->cur_wss_addr = 0x530; - break; - case 1 << 8: - azt2316a->cur_wss_addr = 0x604; - break; - case 2 << 8: - azt2316a->cur_wss_addr = 0xE80; - break; - case 3 << 8: - azt2316a->cur_wss_addr = 0xF40; - break; - default: - fatal("AZT2316A: invalid wss addr in config word %08X\n", azt2316a->config_word); - } - - if (azt2316a->config_word & (1 << 10)) - azt2316a->cur_wss_enabled = 1; - else - azt2316a->cur_wss_enabled = 0; - - if (azt2316a->config_word & (1 << 12)) - azt2316a->cur_mpu401_addr = 0x330; - else - azt2316a->cur_mpu401_addr = 0x300; - - if (azt2316a->config_word & (1 << 13)) - azt2316a->cur_mpu401_enabled = 1; - else - azt2316a->cur_mpu401_enabled = 0; - - if (azt2316a->config_word & (1 << 24)) - azt2316a->cur_mpu401_irq = 9; - else if (azt2316a->config_word & (1 << 25)) - azt2316a->cur_mpu401_irq = 5; - else if (azt2316a->config_word & (1 << 26)) - azt2316a->cur_mpu401_irq = 7; - else if (azt2316a->config_word & (1 << 27)) - azt2316a->cur_mpu401_irq = 10; - else - fatal("AZT2316A: invalid mpu401 irq in config word %08X\n", azt2316a->config_word); - - /* these are not present on the EEPROM */ - azt2316a->cur_wss_irq = device_get_config_int("wss_irq"); - azt2316a->cur_wss_dma = device_get_config_int("wss_dma"); - azt2316a->cur_mode = 0; - } else if (azt2316a->type == SB_SUBTYPE_CLONE_AZT1605_0X0C) { - azt2316a->config_word = read_eeprom[12] + (read_eeprom[13] << 8) + (read_eeprom[14] << 16); - - switch (azt2316a->config_word & (3 << 0)) { - case 0: - azt2316a->cur_addr = 0x220; - break; - case 1: - azt2316a->cur_addr = 0x240; - break; - default: - fatal("AZT1605: invalid sb addr in config word %08X\n", azt2316a->config_word); - } - - if (azt2316a->config_word & (1 << 2)) - azt2316a->cur_mpu401_addr = 0x330; - else - azt2316a->cur_mpu401_addr = 0x300; - - if (azt2316a->config_word & (1 << 3)) - azt2316a->cur_mpu401_enabled = 1; - else - azt2316a->cur_mpu401_enabled = 0; - - if (azt2316a->config_word & (1 << 8)) - azt2316a->cur_irq = 9; - else if (azt2316a->config_word & (1 << 9)) - azt2316a->cur_irq = 3; - else if (azt2316a->config_word & (1 << 10)) - azt2316a->cur_irq = 5; - else if (azt2316a->config_word & (1 << 11)) - azt2316a->cur_irq = 7; - else - fatal("AZT1605: invalid sb irq in config word %08X\n", azt2316a->config_word); - - if (azt2316a->config_word & (1 << 12)) - azt2316a->cur_mpu401_irq = 9; - else if (azt2316a->config_word & (1 << 13)) - azt2316a->cur_mpu401_irq = 3; - else if (azt2316a->config_word & (1 << 14)) - azt2316a->cur_mpu401_irq = 5; - else if (azt2316a->config_word & (1 << 15)) - azt2316a->cur_mpu401_irq = 7; - else - fatal("AZT1605: invalid mpu401 irq in config word %08X\n", azt2316a->config_word); - - switch (azt2316a->config_word & (3 << 16)) { - case 0: - azt2316a->cur_wss_addr = 0x530; - break; - case 1 << 16: - azt2316a->cur_wss_addr = 0x604; - break; - case 2 << 16: - azt2316a->cur_wss_addr = 0xE80; - break; - case 3 << 16: - azt2316a->cur_wss_addr = 0xF40; - break; - default: - fatal("AZT1605: invalid wss addr in config word %08X\n", azt2316a->config_word); - } - - if (azt2316a->config_word & (1 << 18)) - azt2316a->cur_wss_enabled = 1; - else - azt2316a->cur_wss_enabled = 0; - - // these are not present on the EEPROM - azt2316a->cur_dma = device_get_config_int("sb_dma8"); // TODO: investigate TSR to make this work with it - there is no software configurable DMA8? - azt2316a->cur_wss_irq = device_get_config_int("wss_irq"); - azt2316a->cur_wss_dma = device_get_config_int("wss_dma"); - azt2316a->cur_mode = 0; - } - - addr_setting = device_get_config_hex16("addr"); - if (addr_setting) - azt2316a->cur_addr = addr_setting; - - azt2316a->wss_interrupt_after_config = device_get_config_int("wss_interrupt_after_config"); - - /* wss part */ - ad1848_init(&azt2316a->ad1848, device_get_config_int("codec")); - - ad1848_setirq(&azt2316a->ad1848, azt2316a->cur_wss_irq); - ad1848_setdma(&azt2316a->ad1848, azt2316a->cur_wss_dma); - - io_sethandler(azt2316a->cur_addr + 0x0400, 0x0040, azt2316a_config_read, NULL, NULL, azt2316a_config_write, NULL, NULL, azt2316a); - io_sethandler(azt2316a->cur_wss_addr, 0x0004, azt2316a_wss_read, NULL, NULL, azt2316a_wss_write, NULL, NULL, azt2316a); - io_sethandler(azt2316a->cur_wss_addr + 0x0004, 0x0004, ad1848_read, NULL, NULL, ad1848_write, NULL, NULL, &azt2316a->ad1848); - - /* sbprov2 part */ - /*sbpro port mappings. 220h or 240h. - 2x0 to 2x3 -> FM chip (18 voices) - 2x4 to 2x5 -> Mixer interface - 2x6, 2xA, 2xC, 2xE -> DSP chip - 2x8, 2x9, 388 and 389 FM chip (9 voices).*/ - azt2316a->sb = malloc(sizeof(sb_t)); - memset(azt2316a->sb, 0, sizeof(sb_t)); - - azt2316a->sb->opl_enabled = device_get_config_int("opl"); - - for (i = 0; i < AZTECH_EEPROM_SIZE; i++) - azt2316a->sb->dsp.azt_eeprom[i] = read_eeprom[i]; - - if (azt2316a->sb->opl_enabled) - opl3_init(&azt2316a->sb->opl); - - sb_dsp_init(&azt2316a->sb->dsp, SBPRO2, azt2316a->type, azt2316a); - sb_dsp_setaddr(&azt2316a->sb->dsp, azt2316a->cur_addr); - sb_dsp_setirq(&azt2316a->sb->dsp, azt2316a->cur_irq); - sb_dsp_setdma8(&azt2316a->sb->dsp, azt2316a->cur_dma); - sb_ct1345_mixer_reset(azt2316a->sb); - /* DSP I/O handler is activated in sb_dsp_setaddr */ - if (azt2316a->sb->opl_enabled) { - io_sethandler(azt2316a->cur_addr+0, 0x0004, opl3_read, NULL, NULL, opl3_write, NULL, NULL, &azt2316a->sb->opl); - io_sethandler(azt2316a->cur_addr+8, 0x0002, opl3_read, NULL, NULL, opl3_write, NULL, NULL, &azt2316a->sb->opl); - io_sethandler(0x0388, 0x0004, opl3_read, NULL, NULL, opl3_write, NULL, NULL, &azt2316a->sb->opl); + switch (azt2316a->config_word & (3 << 0)) { + case 0: + azt2316a->cur_addr = 0x220; + break; + case 1: + azt2316a->cur_addr = 0x240; + break; + default: + fatal("AZT2316A: invalid sb addr in config word %08X\n", azt2316a->config_word); } - - io_sethandler(azt2316a->cur_addr+4, 0x0002, sb_ct1345_mixer_read, NULL, NULL, sb_ct1345_mixer_write, NULL, NULL, azt2316a->sb); - azt2316a_create_config_word(azt2316a); - sound_add_handler(azt2316a_get_buffer, azt2316a); - sound_set_cd_audio_filter(sbpro_filter_cd_audio, azt2316a->sb); + if (azt2316a->config_word & (1 << 2)) + azt2316a->cur_irq = 9; + else if (azt2316a->config_word & (1 << 3)) + azt2316a->cur_irq = 5; + else if (azt2316a->config_word & (1 << 4)) + azt2316a->cur_irq = 7; + else if (azt2316a->config_word & (1 << 5)) + azt2316a->cur_irq = 10; + else + fatal("AZT2316A: invalid sb irq in config word %08X\n", azt2316a->config_word); - if (azt2316a->cur_mpu401_enabled) { - azt2316a->mpu = (mpu_t *) malloc(sizeof(mpu_t)); - memset(azt2316a->mpu, 0, sizeof(mpu_t)); - mpu401_init(azt2316a->mpu, azt2316a->cur_mpu401_addr, azt2316a->cur_mpu401_irq, M_UART, device_get_config_int("receive_input401")); - } else - azt2316a->mpu = NULL; + switch (azt2316a->config_word & (3 << 6)) { + case 1 << 6: + azt2316a->cur_dma = 0; + break; + case 2 << 6: + azt2316a->cur_dma = 1; + break; + case 3 << 6: + azt2316a->cur_dma = 3; + break; + default: + fatal("AZT2316A: invalid sb dma in config word %08X\n", azt2316a->config_word); + } - if (device_get_config_int("receive_input")) - midi_in_handler(1, sb_dsp_input_msg, sb_dsp_input_sysex, &azt2316a->sb->dsp); + switch (azt2316a->config_word & (3 << 8)) { + case 0: + azt2316a->cur_wss_addr = 0x530; + break; + case 1 << 8: + azt2316a->cur_wss_addr = 0x604; + break; + case 2 << 8: + azt2316a->cur_wss_addr = 0xE80; + break; + case 3 << 8: + azt2316a->cur_wss_addr = 0xF40; + break; + default: + fatal("AZT2316A: invalid wss addr in config word %08X\n", azt2316a->config_word); + } - return azt2316a; + if (azt2316a->config_word & (1 << 10)) + azt2316a->cur_wss_enabled = 1; + else + azt2316a->cur_wss_enabled = 0; + + if (azt2316a->config_word & (1 << 12)) + azt2316a->cur_mpu401_addr = 0x330; + else + azt2316a->cur_mpu401_addr = 0x300; + + if (azt2316a->config_word & (1 << 13)) + azt2316a->cur_mpu401_enabled = 1; + else + azt2316a->cur_mpu401_enabled = 0; + + if (azt2316a->config_word & (1 << 24)) + azt2316a->cur_mpu401_irq = 9; + else if (azt2316a->config_word & (1 << 25)) + azt2316a->cur_mpu401_irq = 5; + else if (azt2316a->config_word & (1 << 26)) + azt2316a->cur_mpu401_irq = 7; + else if (azt2316a->config_word & (1 << 27)) + azt2316a->cur_mpu401_irq = 10; + else + fatal("AZT2316A: invalid mpu401 irq in config word %08X\n", azt2316a->config_word); + + /* these are not present on the EEPROM */ + azt2316a->cur_wss_irq = device_get_config_int("wss_irq"); + azt2316a->cur_wss_dma = device_get_config_int("wss_dma"); + azt2316a->cur_mode = 0; + } else if (azt2316a->type == SB_SUBTYPE_CLONE_AZT1605_0X0C) { + azt2316a->config_word = read_eeprom[12] + (read_eeprom[13] << 8) + (read_eeprom[14] << 16); + + switch (azt2316a->config_word & (3 << 0)) { + case 0: + azt2316a->cur_addr = 0x220; + break; + case 1: + azt2316a->cur_addr = 0x240; + break; + default: + fatal("AZT1605: invalid sb addr in config word %08X\n", azt2316a->config_word); + } + + if (azt2316a->config_word & (1 << 2)) + azt2316a->cur_mpu401_addr = 0x330; + else + azt2316a->cur_mpu401_addr = 0x300; + + if (azt2316a->config_word & (1 << 3)) + azt2316a->cur_mpu401_enabled = 1; + else + azt2316a->cur_mpu401_enabled = 0; + + if (azt2316a->config_word & (1 << 8)) + azt2316a->cur_irq = 9; + else if (azt2316a->config_word & (1 << 9)) + azt2316a->cur_irq = 3; + else if (azt2316a->config_word & (1 << 10)) + azt2316a->cur_irq = 5; + else if (azt2316a->config_word & (1 << 11)) + azt2316a->cur_irq = 7; + else + fatal("AZT1605: invalid sb irq in config word %08X\n", azt2316a->config_word); + + if (azt2316a->config_word & (1 << 12)) + azt2316a->cur_mpu401_irq = 9; + else if (azt2316a->config_word & (1 << 13)) + azt2316a->cur_mpu401_irq = 3; + else if (azt2316a->config_word & (1 << 14)) + azt2316a->cur_mpu401_irq = 5; + else if (azt2316a->config_word & (1 << 15)) + azt2316a->cur_mpu401_irq = 7; + else + fatal("AZT1605: invalid mpu401 irq in config word %08X\n", azt2316a->config_word); + + switch (azt2316a->config_word & (3 << 16)) { + case 0: + azt2316a->cur_wss_addr = 0x530; + break; + case 1 << 16: + azt2316a->cur_wss_addr = 0x604; + break; + case 2 << 16: + azt2316a->cur_wss_addr = 0xE80; + break; + case 3 << 16: + azt2316a->cur_wss_addr = 0xF40; + break; + default: + fatal("AZT1605: invalid wss addr in config word %08X\n", azt2316a->config_word); + } + + if (azt2316a->config_word & (1 << 18)) + azt2316a->cur_wss_enabled = 1; + else + azt2316a->cur_wss_enabled = 0; + + // these are not present on the EEPROM + azt2316a->cur_dma = device_get_config_int("sb_dma8"); // TODO: investigate TSR to make this work with it - there is no software configurable DMA8? + azt2316a->cur_wss_irq = device_get_config_int("wss_irq"); + azt2316a->cur_wss_dma = device_get_config_int("wss_dma"); + azt2316a->cur_mode = 0; + } + + addr_setting = device_get_config_hex16("addr"); + if (addr_setting) + azt2316a->cur_addr = addr_setting; + + azt2316a->wss_interrupt_after_config = device_get_config_int("wss_interrupt_after_config"); + + /* wss part */ + ad1848_init(&azt2316a->ad1848, device_get_config_int("codec")); + + ad1848_setirq(&azt2316a->ad1848, azt2316a->cur_wss_irq); + ad1848_setdma(&azt2316a->ad1848, azt2316a->cur_wss_dma); + + io_sethandler(azt2316a->cur_addr + 0x0400, 0x0040, azt2316a_config_read, NULL, NULL, azt2316a_config_write, NULL, NULL, azt2316a); + io_sethandler(azt2316a->cur_wss_addr, 0x0004, azt2316a_wss_read, NULL, NULL, azt2316a_wss_write, NULL, NULL, azt2316a); + io_sethandler(azt2316a->cur_wss_addr + 0x0004, 0x0004, ad1848_read, NULL, NULL, ad1848_write, NULL, NULL, &azt2316a->ad1848); + + /* sbprov2 part */ + /*sbpro port mappings. 220h or 240h. + 2x0 to 2x3 -> FM chip (18 voices) + 2x4 to 2x5 -> Mixer interface + 2x6, 2xA, 2xC, 2xE -> DSP chip + 2x8, 2x9, 388 and 389 FM chip (9 voices).*/ + azt2316a->sb = malloc(sizeof(sb_t)); + memset(azt2316a->sb, 0, sizeof(sb_t)); + + azt2316a->sb->opl_enabled = device_get_config_int("opl"); + + for (i = 0; i < AZTECH_EEPROM_SIZE; i++) + azt2316a->sb->dsp.azt_eeprom[i] = read_eeprom[i]; + + if (azt2316a->sb->opl_enabled) + fm_driver_get(FM_YMF262, &azt2316a->sb->opl); + + sb_dsp_init(&azt2316a->sb->dsp, SBPRO2, azt2316a->type, azt2316a); + sb_dsp_setaddr(&azt2316a->sb->dsp, azt2316a->cur_addr); + sb_dsp_setirq(&azt2316a->sb->dsp, azt2316a->cur_irq); + sb_dsp_setdma8(&azt2316a->sb->dsp, azt2316a->cur_dma); + sb_ct1345_mixer_reset(azt2316a->sb); + /* DSP I/O handler is activated in sb_dsp_setaddr */ + if (azt2316a->sb->opl_enabled) { + io_sethandler(azt2316a->cur_addr + 0, 0x0004, azt2316a->sb->opl.read, NULL, NULL, azt2316a->sb->opl.write, NULL, NULL, azt2316a->sb->opl.priv); + io_sethandler(azt2316a->cur_addr + 8, 0x0002, azt2316a->sb->opl.read, NULL, NULL, azt2316a->sb->opl.write, NULL, NULL, azt2316a->sb->opl.priv); + io_sethandler(0x0388, 0x0004, azt2316a->sb->opl.read, NULL, NULL, azt2316a->sb->opl.write, NULL, NULL, azt2316a->sb->opl.priv); + } + + io_sethandler(azt2316a->cur_addr + 4, 0x0002, sb_ct1345_mixer_read, NULL, NULL, sb_ct1345_mixer_write, NULL, NULL, azt2316a->sb); + + azt2316a_create_config_word(azt2316a); + sound_add_handler(azt2316a_get_buffer, azt2316a); + sound_set_cd_audio_filter(sbpro_filter_cd_audio, azt2316a->sb); + + if (azt2316a->cur_mpu401_enabled) { + azt2316a->mpu = (mpu_t *) malloc(sizeof(mpu_t)); + memset(azt2316a->mpu, 0, sizeof(mpu_t)); + mpu401_init(azt2316a->mpu, azt2316a->cur_mpu401_addr, azt2316a->cur_mpu401_irq, M_UART, device_get_config_int("receive_input401")); + } else + azt2316a->mpu = NULL; + + if (device_get_config_int("receive_input")) + midi_in_handler(1, sb_dsp_input_msg, sb_dsp_input_sysex, &azt2316a->sb->dsp); + + return azt2316a; } -static void -azt_close(void *p) +static void +azt_close(void *priv) { - azt2316a_t *azt2316a = (azt2316a_t *)p; - char *fn = NULL; - FILE *f; - uint8_t checksum = 0x7f; - int i; + azt2316a_t *azt2316a = (azt2316a_t *) priv; + char *fn = NULL; + FILE *fp; + uint8_t checksum = 0x7f; - if (azt2316a->type == SB_SUBTYPE_CLONE_AZT1605_0X0C) { - fn = "azt1605.nvr"; - } else if (azt2316a->type == SB_SUBTYPE_CLONE_AZT2316A_0X11) { - fn = "azt2316a.nvr"; - } + if (azt2316a->type == SB_SUBTYPE_CLONE_AZT1605_0X0C) { + fn = "azt1605.nvr"; + } else if (azt2316a->type == SB_SUBTYPE_CLONE_AZT2316A_0X11) { + fn = "azt2316a.nvr"; + } - /* always save to eeprom (recover from bad values) */ - f = nvr_fopen(fn, "wb"); - if (f) { - for (i = 0; i < AZTECH_EEPROM_SIZE; i++) - checksum += azt2316a->sb->dsp.azt_eeprom[i]; - fwrite(azt2316a->sb->dsp.azt_eeprom, AZTECH_EEPROM_SIZE, 1, f); + /* always save to eeprom (recover from bad values) */ + fp = nvr_fopen(fn, "wb"); + if (fp) { + for (uint8_t i = 0; i < AZTECH_EEPROM_SIZE; i++) + checksum += azt2316a->sb->dsp.azt_eeprom[i]; + fwrite(azt2316a->sb->dsp.azt_eeprom, AZTECH_EEPROM_SIZE, 1, fp); - // TODO: confirm any models saving mixer settings to EEPROM and implement reading back - // TODO: should remember to save wss duplex setting if 86Box has voice recording implemented in the future? Also, default azt2316a->wss_config - // TODO: azt2316a->cur_mode is not saved to EEPROM? - fwrite(&checksum, sizeof(checksum), 1, f); + // TODO: confirm any models saving mixer settings to EEPROM and implement reading back + // TODO: should remember to save wss duplex setting if 86Box has voice recording implemented in the future? Also, default azt2316a->wss_config + // TODO: azt2316a->cur_mode is not saved to EEPROM? + fwrite(&checksum, sizeof(checksum), 1, fp); - fclose(f); - } + fclose(fp); + } - sb_close(azt2316a->sb); + sb_close(azt2316a->sb); - free(azt2316a); + free(azt2316a->mpu); + free(azt2316a); } -static void -azt_speed_changed(void *p) +static void +azt_speed_changed(void *priv) { - azt2316a_t *azt2316a = (azt2316a_t *)p; + azt2316a_t *azt2316a = (azt2316a_t *) priv; - ad1848_speed_changed(&azt2316a->ad1848); - sb_speed_changed(azt2316a->sb); + ad1848_speed_changed(&azt2316a->ad1848); + sb_speed_changed(azt2316a->sb); } -static const device_config_t azt1605_config[] = -{ - { - .name = "codec", - .description = "CODEC", - .type = CONFIG_SELECTION, - .selection = - { - { - .description = "CS4248", - .value = AD1848_TYPE_CS4248 - }, - { - .description = "CS4231", - .value = AD1848_TYPE_CS4231 - }, - }, - .default_int = AD1848_TYPE_CS4248 +static const device_config_t azt1605_config[] = { + // clang-format off + { + .name = "codec", + .description = "CODEC", + .type = CONFIG_SELECTION, + .selection = { + { + .description = "CS4248", + .value = AD1848_TYPE_CS4248 + }, + { + .description = "CS4231", + .value = AD1848_TYPE_CS4231 + }, }, - { - .name = "wss_interrupt_after_config", - .description = "Raise CODEC interrupt on CODEC setup (needed by some drivers)", - .type = CONFIG_BINARY, - .default_int = 0 - }, - { - "addr", "SB Address", CONFIG_HEX16, "", 0, "", { 0 }, - { - { - "0x220", 0x220 - }, - { - "0x240", 0x240 - }, - { - "Use EEPROM setting", 0 - }, - { - "" - } - } - }, - { - .name = "sb_dma8", - .description = "SB low DMA", - .type = CONFIG_SELECTION, - .selection = - { - { - .description = "DMA 0", - .value = 0 - }, - { - .description = "DMA 1", - .value = 1 - }, - { - .description = "DMA 3", - .value = 3 - }, - { - .description = "" - } - }, - .default_int = 1 - }, - { - .name = "wss_irq", - .description = "WSS IRQ", - .type = CONFIG_SELECTION, - .selection = - { - { - .description = "IRQ 11", - .value = 11 - }, - { - .description = "IRQ 10", - .value = 10 - }, - { - .description = "IRQ 7", - .value = 7 - }, - { - .description = "" - } - }, - .default_int = 10 - }, - { - .name = "wss_dma", - .description = "WSS DMA", - .type = CONFIG_SELECTION, - .selection = - { - { - .description = "DMA 0", - .value = 0 - }, - { - .description = "DMA 1", - .value = 1 - }, - { - .description = "DMA 3", - .value = 3 - }, - { - .description = "" - } - }, - .default_int = 0 - }, - { - "opl", "Enable OPL", CONFIG_BINARY, "", 1 - }, - { - "receive_input", "Receive input (SB MIDI)", CONFIG_BINARY, "", 1 - }, - { - "receive_input401", "Receive input (MPU-401)", CONFIG_BINARY, "", 0 - }, - { - "", "", -1 + .default_int = AD1848_TYPE_CS4248 + }, + { + .name = "wss_interrupt_after_config", + .description = "Raise CODEC interrupt on CODEC setup (needed by some drivers)", + .type = CONFIG_BINARY, + .default_int = 0 + }, + { + .name = "addr", + .description = "SB Address", + .type = CONFIG_HEX16, + .default_string = "", + .default_int = 0, + .file_filter = "", + .spinner = { 0 }, + .selection = { + { + .description = "0x220", + .value = 0x220 + }, + { + .description = "0x240", + .value = 0x240 + }, + { + .description = "Use EEPROM setting", + .value = 0 + }, + { + .description = "" + } } -}; - -static const device_config_t azt2316a_config[] = -{ + }, + { + .name = "sb_dma8", + .description = "SB low DMA", + .type = CONFIG_SELECTION, + .selection = { + { + .description = "DMA 0", + .value = 0 + }, + { + .description = "DMA 1", + .value = 1 + }, + { + .description = "DMA 3", + .value = 3 + }, + { + .description = "" + } + }, + .default_int = 1 + }, + { + .name = "wss_irq", + .description = "WSS IRQ", + .type = CONFIG_SELECTION, + .selection = { + { + .description = "IRQ 11", + .value = 11 + }, + { + .description = "IRQ 10", + .value = 10 + }, + { + .description = "IRQ 7", + .value = 7 + }, + { + .description = "" + } + }, + .default_int = 10 + }, { - .name = "codec", - .description = "CODEC", - .type = CONFIG_SELECTION, - .selection = + .name = "wss_dma", + .description = "WSS DMA", + .type = CONFIG_SELECTION, + .selection = { { - { - .description = "CS4248", - .value = AD1848_TYPE_CS4248 - }, - { - .description = "CS4231", - .value = AD1848_TYPE_CS4231 - }, + .description = "DMA 0", + .value = 0 }, - .default_int = AD1848_TYPE_CS4248 - }, - { - .name = "wss_interrupt_after_config", - .description = "Raise CODEC interrupt on CODEC setup (needed by some drivers)", - .type = CONFIG_BINARY, - .default_int = 0 - }, - { - "addr", "SB Address", CONFIG_HEX16, "", 0, "", { 0 }, { - { - "0x220", 0x220 - }, - { - "0x240", 0x240 - }, - { - "Use EEPROM setting", 0 - }, - { - "" - } + .description = "DMA 1", + .value = 1 + }, + { + .description = "DMA 3", + .value = 3 + }, + { + .description = "" } + }, + .default_int = 0 }, - { - .name = "wss_irq", - .description = "WSS IRQ", - .type = CONFIG_SELECTION, - .selection = - { - { - .description = "IRQ 11", - .value = 11 - }, - { - .description = "IRQ 10", - .value = 10 - }, - { - .description = "IRQ 7", - .value = 7 - }, - { - .description = "" - } - }, - .default_int = 10 + { + .name = "opl", + .description = "Enable OPL", + .type = CONFIG_BINARY, + .default_string = "", + .default_int = 1 + }, + { + .name = "receive_input", + .description = "Receive input (SB MIDI)", + .type = CONFIG_BINARY, + .default_string = "", + .default_int = 1 + }, + { + .name = "receive_input401", + .description = "Receive input (MPU-401)", + .type = CONFIG_BINARY, + .default_string = "", + .default_int = 0 + }, + { .name = "", .description = "", .type = CONFIG_END } + // clang-format on +}; + +static const device_config_t azt2316a_config[] = { + // clang-format off + { + .name = "codec", + .description = "CODEC", + .type = CONFIG_SELECTION, + .selection = { + { + .description = "CS4248", + .value = AD1848_TYPE_CS4248 + }, + { + .description = "CS4231", + .value = AD1848_TYPE_CS4231 + }, }, - { - .name = "wss_dma", - .description = "WSS DMA", - .type = CONFIG_SELECTION, - .selection = - { - { - .description = "DMA 0", - .value = 0 - }, - { - .description = "DMA 1", - .value = 1 - }, - { - .description = "DMA 3", - .value = 3 - }, - { - .description = "" - } - }, - .default_int = 0 - }, - { - "opl", "Enable OPL", CONFIG_BINARY, "", 1 - }, - { - "receive_input", "Receive input (SB MIDI)", CONFIG_BINARY, "", 1 - }, - { - "receive_input401", "Receive input (MPU-401)", CONFIG_BINARY, "", 0 - }, - { - "", "", -1 + .default_int = AD1848_TYPE_CS4248 + }, + { + .name = "wss_interrupt_after_config", + .description = "Raise CODEC interrupt on CODEC setup (needed by some drivers)", + .type = CONFIG_BINARY, + .default_int = 0 + }, + { + .name = "addr", + .description = "SB Address", + .type = CONFIG_HEX16, + .default_string = "", + .default_int = 0, + .file_filter = "", + .spinner = { 0 }, + .selection = { + { + .description = "0x220", + .value = 0x220 + }, + { + .description = "0x240", + .value = 0x240 + }, + { + .description = "Use EEPROM setting", + .value = 0 + }, + { + .description = "" + } } + }, + { + .name = "wss_irq", + .description = "WSS IRQ", + .type = CONFIG_SELECTION, + .selection = { + { + .description = "IRQ 11", + .value = 11 + }, + { + .description = "IRQ 10", + .value = 10 + }, + { + .description = "IRQ 7", + .value = 7 + }, + { + .description = "" + } + }, + .default_int = 10 + }, + { + .name = "wss_dma", + .description = "WSS DMA", + .type = CONFIG_SELECTION, + .selection = { + { + .description = "DMA 0", + .value = 0 + }, + { + .description = "DMA 1", + .value = 1 + }, + { + .description = "DMA 3", + .value = 3 + }, + { + .description = "" + } + }, + .default_int = 0 + }, + { + .name = "opl", + .description = "Enable OPL", + .type = CONFIG_BINARY, + .default_string = "", + .default_int = 1 + }, + { + .name = "receive_input", + .description = "Receive input (SB MIDI)", + .type = CONFIG_BINARY, + .default_string = "", + .default_int = 1 + }, + { + .name = "receive_input401", + .description = "Receive input (MPU-401)", + .type = CONFIG_BINARY, + .default_string = "", + .default_int = 0 + }, + { .name = "", .description = "", .type = CONFIG_END } + // clang-format on }; -const device_t azt2316a_device = -{ - "Aztech Sound Galaxy Pro 16 AB (Washington)", - "azt2316a", - DEVICE_ISA | DEVICE_AT, - SB_SUBTYPE_CLONE_AZT2316A_0X11, - azt_init, azt_close, NULL, { NULL }, - azt_speed_changed, - NULL, - azt2316a_config +const device_t azt2316a_device = { + .name = "Aztech Sound Galaxy Pro 16 AB (Washington)", + .internal_name = "azt2316a", + .flags = DEVICE_ISA | DEVICE_AT, + .local = SB_SUBTYPE_CLONE_AZT2316A_0X11, + .init = azt_init, + .close = azt_close, + .reset = NULL, + { .available = NULL }, + .speed_changed = azt_speed_changed, + .force_redraw = NULL, + .config = azt2316a_config }; -const device_t azt1605_device = -{ - "Aztech Sound Galaxy Nova 16 Extra (Clinton)", - "azt1605", - DEVICE_ISA | DEVICE_AT, - SB_SUBTYPE_CLONE_AZT1605_0X0C, - azt_init, azt_close, NULL, { NULL }, - azt_speed_changed, - NULL, - azt1605_config +const device_t azt1605_device = { + .name = "Aztech Sound Galaxy Nova 16 Extra (Clinton)", + .internal_name = "azt1605", + .flags = DEVICE_ISA | DEVICE_AT, + .local = SB_SUBTYPE_CLONE_AZT1605_0X0C, + .init = azt_init, + .close = azt_close, + .reset = NULL, + { .available = NULL }, + .speed_changed = azt_speed_changed, + .force_redraw = NULL, + .config = azt1605_config }; diff --git a/src/sound/snd_cmi8x38.c b/src/sound/snd_cmi8x38.c new file mode 100644 index 000000000..359563b99 --- /dev/null +++ b/src/sound/snd_cmi8x38.c @@ -0,0 +1,1597 @@ +/* + * 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. + * + * C-Media CMI8x38 PCI audio controller emulation. + * + * + * + * Authors: RichardG, + * + * Copyright 2022 RichardG. + */ +#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/pic.h> +#include <86box/timer.h> +#include <86box/dma.h> +#include <86box/pci.h> +#include <86box/sound.h> +#include <86box/snd_sb.h> +#include <86box/snd_sb_dsp.h> +#include <86box/gameport.h> +#include <86box/nmi.h> +#include <86box/ui.h> +#include <86box/plat_fallthrough.h> +#include <86box/plat_unused.h> + +enum { + /* [23:16] = reg 0F [7:0] (reg 0C [31:24]) + [13] = onboard flag + [12:8] = reg 0B [4:0] (reg 08 [28:24]) + [7:0] = PCI device ID [7:0] */ + CMEDIA_CMI8338 = 0x000000, + CMEDIA_CMI8738_4CH = 0x040011, /* chip version 039 with 4-channel output */ + CMEDIA_CMI8738_6CH = 0x080011 /* chip version 055 with 6-channel output */ +}; + +enum { + TRAP_DMA = 0, + TRAP_PIC, + TRAP_OPL, + TRAP_MPU, + TRAP_MAX +}; + +typedef struct cmi8x38_dma_t { + uint8_t id; + uint8_t reg; + uint8_t always_run; + uint8_t playback_enabled; + uint8_t channels; + struct _cmi8x38_ *dev; + + uint32_t sample_ptr; + uint32_t fifo_pos; + uint32_t fifo_end; + int32_t frame_count_dma; + int32_t frame_count_fragment; + int32_t sample_count_out; + uint8_t fifo[256]; + uint8_t restart; + + int16_t out_fl; + int16_t out_fr; + int16_t out_rl; + int16_t out_rr; + int16_t out_c; + int16_t out_lfe; + int vol_l; + int vol_r; + int pos; + int32_t buffer[SOUNDBUFLEN * 2]; + uint64_t timer_latch; + double dma_latch; + + pc_timer_t dma_timer; + pc_timer_t poll_timer; +} cmi8x38_dma_t; + +typedef struct _cmi8x38_ { + uint32_t type; + uint16_t io_base; + uint16_t sb_base; + uint16_t opl_base; + uint16_t mpu_base; + uint8_t pci_regs[256]; + uint8_t io_regs[256]; + uint8_t pci_slot; + uint8_t irq_state; + + sb_t *sb; + void *gameport; + void *io_traps[TRAP_MAX]; + + cmi8x38_dma_t dma[2]; + uint16_t tdma_base_addr; + uint16_t tdma_base_count; + int tdma_8; + int tdma_16; + int tdma_mask; + int prev_mask; + int tdma_irq_mask; + + int master_vol_l; + int master_vol_r; + int cd_vol_l; + int cd_vol_r; +} cmi8x38_t; + +#ifdef ENABLE_CMI8X38_LOG +int cmi8x38_do_log = ENABLE_CMI8X38_LOG; + +static void +cmi8x38_log(const char *fmt, ...) +{ + va_list ap; + + if (cmi8x38_do_log) { + va_start(ap, fmt); + pclog_ex(fmt, ap); + va_end(ap); + } +} +#else +# define cmi8x38_log(fmt, ...) +#endif + +static const double freqs[] = { 5512.0, 11025.0, 22050.0, 44100.0, 8000.0, 16000.0, 32000.0, 48000.0 }; +static const uint16_t opl_ports_cmi8738[] = { 0x388, 0x3c8, 0x3e0, 0x3e8 }; + +static void cmi8x38_dma_process(void *priv); +static void cmi8x38_speed_changed(void *priv); + +static void +cmi8x38_update_irqs(cmi8x38_t *dev) +{ + /* Calculate and use the INTR flag. */ + if (*((uint32_t *) &dev->io_regs[0x10]) & 0x0401c003) { + dev->io_regs[0x13] |= 0x80; + pci_set_irq(dev->pci_slot, PCI_INTA, &dev->irq_state); + cmi8x38_log("CMI8x38: Raising IRQ\n"); + } else { + dev->io_regs[0x13] &= ~0x80; + pci_clear_irq(dev->pci_slot, PCI_INTA, &dev->irq_state); + } +} + +static void +cmi8x38_mpu_irq_update(void *priv, int set) +{ + cmi8x38_t *dev = (cmi8x38_t *) priv; + if (set) + dev->io_regs[0x12] |= 0x01; + else + dev->io_regs[0x12] &= ~0x01; + cmi8x38_update_irqs(dev); +} + +static int +cmi8x38_mpu_irq_pending(void *priv) +{ + const cmi8x38_t *dev = (cmi8x38_t *) priv; + + return dev->io_regs[0x12] & 0x01; +} + +static void +cmi8x38_sb_irq_update(void *priv, int set) +{ + cmi8x38_t *dev = (cmi8x38_t *) priv; + /* Interrupt flag shared with the first DMA channel. Combining SB and + PCI DMA is undefined; the VxD driver disables SB if PCI is in use. */ + if (set) + dev->io_regs[0x10] |= 0x01; + else + dev->io_regs[0x10] &= ~0x01; + cmi8x38_update_irqs(dev); +} + +static int +cmi8x38_sb_dma_post(cmi8x38_t *dev, uint16_t *addr, uint16_t *count, int channel) +{ + /* Increment address and decrement count. */ + *addr += 1; + *count -= 1; + + /* Copy TDMA registers to DMA on CMI8738+. Everything so far suggests that + those chips use PCI bus mastering to directly write to the DMA registers. */ +#if 0 /* TSRs don't set ENWR8237, except for the patched C3DPCI - does that bit have no effect? */ + if ((dev->type != CMEDIA_CMI8338) && (dev->io_regs[0x17] & 0x10)) +#else + if (dev->type != CMEDIA_CMI8338) +#endif + { + if (channel & 4) + dma[channel].ab = (dma[channel].ab & 0xfffe0000) | ((*addr) << 1); + else + dma[channel].ab = (dma[channel].ab & 0xffff0000) | *addr; + dma[channel].ac = dma[channel].ab; + dma[channel].cc = dma[channel].cb = *count; + } + + /* Check TDMA position update interrupt if enabled. */ + if (dev->io_regs[0x0e] & 0x04) { + /* Nothing uses this; I assume it goes by the SB DSP sample counter (forwards instead of backwards). */ + int origlength = (channel & 4) ? dev->sb->dsp.sb_16_origlength : dev->sb->dsp.sb_8_origlength; + int length = (channel & 4) ? dev->sb->dsp.sb_16_length : dev->sb->dsp.sb_8_length; + if ((origlength != length) && (((origlength - length) & dev->tdma_irq_mask) == 0)) { /* skip initial sample */ + /* Fire the interrupt. */ + dev->io_regs[0x11] |= (channel & 4) ? 0x40 : 0x80; + cmi8x38_update_irqs(dev); + } + } + + /* Handle end of DMA. */ + if (*count == 0xffff) { + if (dma[channel].mode & 0x10) { /* auto-init */ + /* Restart TDMA. */ + *addr = dev->tdma_base_addr; + *count = dev->tdma_base_count; + cmi8x38_log("CMI8x38: Restarting TDMA on DMA %d with addr %08X count %04X\n", + channel, + (channel & 4) ? ((dma[channel].ab & 0xfffe0000) | ((*addr) << 1)) : ((dma[channel].ab & 0xffff0000) | *addr), + *count); + } else { + /* Mask TDMA. */ + dev->tdma_mask |= 1 << channel; + } + + /* Set the mysterious LHBTOG bit, assuming it corresponds + to the 8237 channel status bit. Nothing reads it. */ + dev->io_regs[0x10] |= 0x40; + + return DMA_OVER; + } + return 0; +} + +static int +cmi8x38_sb_dma_readb(void *priv) +{ + cmi8x38_t *dev = (cmi8x38_t *) priv; + + /* Stop if the DMA channel is invalid or if TDMA is masked. */ + int channel = dev->tdma_8; + if ((channel < 0) || (dev->tdma_mask & (1 << channel))) + return DMA_NODATA; + + /* Get 16-bit address and count registers. */ + uint16_t *addr = (uint16_t *) &dev->io_regs[0x1c]; + uint16_t *count = (uint16_t *) &dev->io_regs[0x1e]; + + /* Read data. */ + int ret = mem_readb_phys((dma[channel].ab & 0xffff0000) | *addr); + + /* Handle address, count and end. */ + ret |= cmi8x38_sb_dma_post(dev, addr, count, channel); + + return ret; +} + +static int +cmi8x38_sb_dma_readw(void *priv) +{ + cmi8x38_t *dev = (cmi8x38_t *) priv; + + /* Stop if the DMA channel is invalid or if TDMA is masked. */ + int channel = dev->tdma_16; + if ((channel < 0) || (dev->tdma_mask & (1 << channel))) + return DMA_NODATA; + + /* Get 16-bit address and count registers. */ + uint16_t *addr = (uint16_t *) &dev->io_regs[0x1c]; + uint16_t *count = (uint16_t *) &dev->io_regs[0x1e]; + + /* Read data. */ + int ret = mem_readw_phys((dma[channel].ab & 0xfffe0000) | ((*addr) << 1)); + + /* Handle address, count and end. */ + ret |= cmi8x38_sb_dma_post(dev, addr, count, channel); + + return ret; +} + +static int +cmi8x38_sb_dma_writeb(void *priv, uint8_t val) +{ + cmi8x38_t *dev = (cmi8x38_t *) priv; + + /* Stop if the DMA channel is invalid or if TDMA is masked. */ + int channel = dev->tdma_8; + if ((channel < 0) || (dev->tdma_mask & (1 << channel))) + return 1; + + /* Get 16-bit address and count registers. */ + uint16_t *addr = (uint16_t *) &dev->io_regs[0x1c]; + uint16_t *count = (uint16_t *) &dev->io_regs[0x1e]; + + /* Write data. */ + mem_writeb_phys((dma[channel].ab & 0xffff0000) | *addr, val); + + /* Handle address, count and end. */ + cmi8x38_sb_dma_post(dev, addr, count, channel); + + return 0; +} + +static int +cmi8x38_sb_dma_writew(void *priv, uint16_t val) +{ + cmi8x38_t *dev = (cmi8x38_t *) priv; + + /* Stop if the DMA channel is invalid or if TDMA is masked. */ + int channel = dev->tdma_16; + if ((channel < 0) || (dev->tdma_mask & (1 << channel))) + return 1; + + /* Get 16-bit address and count registers. */ + uint16_t *addr = (uint16_t *) &dev->io_regs[0x1c]; + uint16_t *count = (uint16_t *) &dev->io_regs[0x1e]; + + /* Write data. */ + mem_writew_phys((dma[channel].ab & 0xfffe0000) | ((*addr) << 1), val); + + /* Handle address, count and end. */ + cmi8x38_sb_dma_post(dev, addr, count, channel); + + return 0; +} + +static void +cmi8x38_dma_write(uint16_t addr, UNUSED(uint8_t val), void *priv) +{ + cmi8x38_t *dev = (cmi8x38_t *) priv; + + /* Stop if DMA channel auto-detection is disabled. This is required for the CMI8338 TSR, + which disables auto-detection while copying the TDMA address/count to the SB DMA channel, + so that those writes don't loop back to the DMA register snoop mechanism implemented here. */ + if (!(dev->io_regs[0x27] & 0x01)) + return; + + /* Stop if this is not a TDMA channel. Also set or + clear the high channel flag while we're here. */ + int channel; + if (addr < 0x08) { + channel = addr >> 1; + if (channel != dev->tdma_8) + return; + dev->io_regs[0x10] &= ~0x20; + } else { + channel = 4 | ((addr >> 2) & 3); + if (channel != dev->tdma_16) + return; + dev->io_regs[0x10] |= 0x20; + } + + /* Write base address and count. */ + uint16_t *daddr = (uint16_t *) &dev->io_regs[0x1c]; + uint16_t *count = (uint16_t *) &dev->io_regs[0x1e]; + *daddr = dev->tdma_base_addr = dma[channel].ab >> !!(channel & 4); + *count = dev->tdma_base_count = dma[channel].cb; + cmi8x38_log("CMI8x38: Starting TDMA on DMA %d with addr %08X count %04X\n", + channel, + (channel & 4) ? ((dma[channel].ab & 0xfffe0000) | ((*daddr) << 1)) : ((dma[channel].ab & 0xffff0000) | *daddr), + *count); + + /* Clear the mysterious LHBTOG bit, assuming it corresponds + to the 8237 channel status bit. Nothing reads it. */ + dev->io_regs[0x10] &= ~0x40; +} + +static void +cmi8x38_dma_mask_write(UNUSED(uint16_t addr), UNUSED(uint8_t val), void *priv) +{ + cmi8x38_t *dev = (cmi8x38_t *) priv; + + /* See comment on dma_write above. */ + if (!(dev->io_regs[0x27] & 0x01)) + return; + + /* Unmask TDMA on DMA unmasking edge. */ + if ((dev->tdma_8 >= 0) && (dev->prev_mask & (1 << dev->tdma_8)) && !(dma_m & (1 << dev->tdma_8))) + dev->tdma_mask &= ~(1 << dev->tdma_8); + else if ((dev->tdma_16 >= 0) && (dev->prev_mask & (1 << dev->tdma_16)) && !(dma_m & (1 << dev->tdma_16))) + dev->tdma_mask &= ~(1 << dev->tdma_16); + dev->prev_mask = dma_m; +} + +static void +cmi8338_io_trap(UNUSED(int size), uint16_t addr, uint8_t write, uint8_t val, void *priv) +{ + cmi8x38_t *dev = (cmi8x38_t *) priv; + +#ifdef ENABLE_CMI8X38_LOG + if (write) + cmi8x38_log("CMI8x38: cmi8338_io_trap(%04X, %02X)\n", addr, val); + else + cmi8x38_log("CMI8x38: cmi8338_io_trap(%04X)\n", addr); +#endif + + /* Weird offsets, it's best to just treat the register as a big dword. */ + uint32_t *lcs = (uint32_t *) &dev->io_regs[0x14]; + *lcs &= ~0x0003dff0; + *lcs |= (addr & 0x0f) << 14; + if (write) + *lcs |= 0x1000 | (val << 4); + + /* Raise NMI. */ + nmi = 1; +} + +static uint8_t +cmi8x38_sb_mixer_read(uint16_t addr, void *priv) +{ + cmi8x38_t *dev = (cmi8x38_t *) priv; + const sb_ct1745_mixer_t *mixer = &dev->sb->mixer_sb16; + uint8_t ret = sb_ct1745_mixer_read(addr, dev->sb); + + if (addr & 1) { + if ((mixer->index == 0x0e) || (mixer->index >= 0xf0)) + ret = mixer->regs[mixer->index]; + cmi8x38_log("CMI8x38: sb_mixer_read(1, %02X) = %02X\n", mixer->index, ret); + } else { + cmi8x38_log("CMI8x38: sb_mixer_read(0) = %02X\n", ret); + } + + return ret; +} + +static void +cmi8x38_sb_mixer_write(uint16_t addr, uint8_t val, void *priv) +{ + cmi8x38_t *dev = (cmi8x38_t *) priv; + sb_ct1745_mixer_t *mixer = &dev->sb->mixer_sb16; + + /* Our clone mixer has a few differences. */ + if (addr & 1) { + cmi8x38_log("CMI8x38: sb_mixer_write(1, %02X, %02X)\n", mixer->index, val); + + switch (mixer->index) { + /* Reset interleaved stereo flag for SBPro mode. */ + case 0x00: + mixer->regs[0x0e] = 0x00; + break; + + /* No dynamic MPU port assignment. */ + case 0x84: + return; + + /* Some extended registers beyond those accepted by the CT1745. */ + case 0xf0: + if (dev->type == CMEDIA_CMI8338) + val &= 0xfe; + mixer->regs[mixer->index] = val; + return; + + case 0xf8 ... 0xff: + if (dev->type == CMEDIA_CMI8338) + mixer->regs[mixer->index] = val; + fallthrough; + + case 0xf1 ... 0xf7: + return; + + default: + break; + } + + sb_ct1745_mixer_write(addr, val, dev->sb); + + /* No [3F:47] controls. */ + mixer->input_gain_L = 0; + mixer->input_gain_R = 0; + mixer->output_gain_L = 1.0; + mixer->output_gain_R = 1.0; + mixer->bass_l = 8; + mixer->bass_r = 8; + mixer->treble_l = 8; + mixer->treble_r = 8; + + /* Check interleaved stereo flag for SBPro mode. */ + if ((mixer->index == 0x00) || (mixer->index == 0x0e)) + sb_dsp_set_stereo(&dev->sb->dsp, mixer->regs[0x0e] & 2); + + /* Set TDMA channels if auto-detection is enabled. */ + if ((dev->io_regs[0x27] & 0x01) && (mixer->index == 0x81)) { + dev->tdma_8 = dev->sb->dsp.sb_8_dmanum; + if (dev->sb->dsp.sb_type >= SB16) + dev->tdma_16 = dev->sb->dsp.sb_16_dmanum; + } + } else { + cmi8x38_log("CMI8x38: sb_mixer_write(0, %02X)\n", val); + sb_ct1745_mixer_write(addr, val, dev->sb); + } +} + +static void +cmi8x38_remap_sb(cmi8x38_t *dev) +{ + if (dev->sb_base) { + io_removehandler(dev->sb_base, 0x0004, dev->sb->opl.read, NULL, NULL, + dev->sb->opl.write, NULL, NULL, dev->sb->opl.priv); + io_removehandler(dev->sb_base + 8, 0x0002, dev->sb->opl.read, NULL, NULL, + dev->sb->opl.write, NULL, NULL, dev->sb->opl.priv); + io_removehandler(dev->sb_base + 4, 0x0002, cmi8x38_sb_mixer_read, NULL, NULL, + cmi8x38_sb_mixer_write, NULL, NULL, dev); + + sb_dsp_setaddr(&dev->sb->dsp, 0); + } + + dev->sb_base = 0x220; + if (dev->type == CMEDIA_CMI8338) + dev->sb_base += (dev->io_regs[0x17] & 0x80) >> 2; + else + dev->sb_base += (dev->io_regs[0x17] & 0x0c) << 3; + if (!(dev->io_regs[0x04] & 0x08)) + dev->sb_base = 0; + cmi8x38_log("CMI8x38: remap_sb(%04X)\n", dev->sb_base); + + if (dev->sb_base) { + io_sethandler(dev->sb_base, 0x0004, dev->sb->opl.read, NULL, NULL, + dev->sb->opl.write, NULL, NULL, dev->sb->opl.priv); + io_sethandler(dev->sb_base + 8, 0x0002, dev->sb->opl.read, NULL, NULL, + dev->sb->opl.write, NULL, NULL, dev->sb->opl.priv); + io_sethandler(dev->sb_base + 4, 0x0002, cmi8x38_sb_mixer_read, NULL, NULL, + cmi8x38_sb_mixer_write, NULL, NULL, dev); + + sb_dsp_setaddr(&dev->sb->dsp, dev->sb_base); + } +} + +static void +cmi8x38_remap_opl(cmi8x38_t *dev) +{ + if (dev->opl_base) { + io_removehandler(dev->opl_base, 0x0004, dev->sb->opl.read, NULL, NULL, + dev->sb->opl.write, NULL, NULL, dev->sb->opl.priv); + } + + dev->opl_base = (dev->type == CMEDIA_CMI8338) ? 0x388 : opl_ports_cmi8738[dev->io_regs[0x17] & 0x03]; + io_trap_remap(dev->io_traps[TRAP_OPL], (dev->io_regs[0x04] & 0x01) && (dev->io_regs[0x16] & 0x80), dev->opl_base, 4); + if (!(dev->io_regs[0x1a] & 0x08)) + dev->opl_base = 0; + + cmi8x38_log("CMI8x38: remap_opl(%04X)\n", dev->opl_base); + + if (dev->opl_base) { + io_sethandler(dev->opl_base, 0x0004, dev->sb->opl.read, NULL, NULL, + dev->sb->opl.write, NULL, NULL, dev->sb->opl.priv); + } +} + +static void +cmi8x38_remap_mpu(cmi8x38_t *dev) +{ + if (dev->mpu_base) + mpu401_change_addr(dev->sb->mpu, 0); + + /* The CMI8338 datasheet's port range of [300:330] is + inaccurate. Drivers expect [330:300] like CMI8738. */ + dev->mpu_base = 0x330 - ((dev->io_regs[0x17] & 0x60) >> 1); + io_trap_remap(dev->io_traps[TRAP_MPU], (dev->io_regs[0x04] & 0x01) && (dev->io_regs[0x16] & 0x20), dev->mpu_base, 2); + if (!(dev->io_regs[0x04] & 0x04)) + dev->mpu_base = 0; + + cmi8x38_log("CMI8x38: remap_mpu(%04X)\n", dev->mpu_base); + + if (dev->mpu_base) + mpu401_change_addr(dev->sb->mpu, dev->mpu_base); +} + +static void +cmi8x38_remap_traps(cmi8x38_t *dev) +{ + cmi8x38_remap_opl(dev); + cmi8x38_remap_mpu(dev); + io_trap_remap(dev->io_traps[TRAP_DMA], (dev->io_regs[0x04] & 0x01) && (dev->io_regs[0x17] & 0x02), 0x0000, 16); + io_trap_remap(dev->io_traps[TRAP_PIC], (dev->io_regs[0x04] & 0x01) && (dev->io_regs[0x17] & 0x01), 0x0020, 2); +} + +static void +cmi8x38_start_playback(cmi8x38_t *dev) +{ + uint8_t i; + uint8_t val = dev->io_regs[0x00]; + + i = !(val & 0x01); + if (!dev->dma[0].playback_enabled && i) + timer_set_delay_u64(&dev->dma[0].poll_timer, dev->dma[0].timer_latch); + dev->dma[0].playback_enabled = i; + + i = !(val & 0x02); + if (!dev->dma[1].playback_enabled && i) + timer_set_delay_u64(&dev->dma[1].poll_timer, dev->dma[1].timer_latch); + dev->dma[1].playback_enabled = i; +} + +static uint8_t +cmi8x38_read(uint16_t addr, void *priv) +{ + cmi8x38_t *dev = (cmi8x38_t *) priv; + addr &= 0xff; + uint8_t ret; + + switch (addr) { + case 0x22: + case 0x23: + ret = cmi8x38_sb_mixer_read(addr ^ 1, dev); + break; + + case 0x40 ... 0x4f: + if (dev->type == CMEDIA_CMI8338) + goto io_reg; + else + ret = mpu401_read(addr, dev->sb->mpu); + break; + + case 0x50 ... 0x5f: + if (dev->type == CMEDIA_CMI8338) + goto io_reg; + else + ret = dev->sb->opl.read(addr, dev->sb->opl.priv); + break; + + case 0x80: + case 0x88: + ret = dev->dma[(addr & 0x78) >> 3].sample_ptr; + break; + + case 0x81: + case 0x89: + ret = dev->dma[(addr & 0x78) >> 3].sample_ptr >> 8; + break; + + case 0x82: + case 0x8a: + ret = dev->dma[(addr & 0x78) >> 3].sample_ptr >> 16; + break; + + case 0x83: + case 0x8b: + ret = dev->dma[(addr & 0x78) >> 3].sample_ptr >> 24; + break; + + case 0x84: + case 0x8c: + ret = dev->dma[(addr & 0x78) >> 3].frame_count_dma; + break; + + case 0x85: + case 0x8d: + ret = dev->dma[(addr & 0x78) >> 3].frame_count_dma >> 8; + break; + + case 0x86: + case 0x8e: + ret = dev->dma[(addr & 0x78) >> 3].sample_count_out >> 2; + break; + + case 0x87: + case 0x8f: + ret = dev->dma[(addr & 0x78) >> 3].sample_count_out >> 10; + break; + + default: +io_reg: + ret = dev->io_regs[addr]; + break; + } + + cmi8x38_log("CMI8x38: read(%02X) = %02X\n", addr, ret); + return ret; +} + +static void +cmi8x38_write(uint16_t addr, uint8_t val, void *priv) +{ + cmi8x38_t *dev = (cmi8x38_t *) priv; + addr &= 0xff; + cmi8x38_log("CMI8x38: write(%02X, %02X)\n", addr, val); + + switch (addr) { + case 0x00: + val &= 0x0f; + + /* Don't care about recording DMA. */ + dev->dma[0].always_run = val & 0x01; + dev->dma[1].always_run = val & 0x02; + + /* Start playback if requested. */ + dev->io_regs[addr] = val; + cmi8x38_start_playback(dev); + break; + + case 0x02: + /* Reset or start DMA channels if requested. */ + dev->io_regs[addr] = val & 0x03; + for (int i = 0; i < (sizeof(dev->dma) / sizeof(dev->dma[0])); i++) { + if (val & (0x04 << i)) { + /* Reset DMA channel. */ + val &= ~(0x01 << i); + dev->io_regs[0x10] &= ~(0x01 << i); /* clear interrupt */ + + /* Reset Sound Blaster as well when resetting channel 0. */ + if ((i == 0) && (dev->sb->dsp.sb_8_enable || dev->sb->dsp.sb_16_enable || dev->sb->dsp.sb_irq8 || dev->sb->dsp.sb_irq16)) + dev->sb->dsp.sb_8_enable = dev->sb->dsp.sb_16_enable = dev->sb->dsp.sb_irq8 = dev->sb->dsp.sb_irq16 = 0; + } else if (val & (0x01 << i)) { + /* Start DMA channel. */ + cmi8x38_log("CMI8x38: DMA %d trigger\n", i); + dev->dma[i].restart = 1; + cmi8x38_dma_process(&dev->dma[i]); + } + } + + /* Clear reset bits. */ + val &= 0x03; + + /* Start playback along with DMA channels. */ + if (val & 0x03) + cmi8x38_start_playback(dev); + + /* Update interrupts. */ + dev->io_regs[addr] = val; + cmi8x38_update_irqs(dev); + break; + + case 0x04: + /* Enable or disable the game port. */ + gameport_remap(dev->gameport, (val & 0x02) ? 0x200 : 0); + + /* Enable or disable the legacy devices. */ + dev->io_regs[addr] = val; + cmi8x38_remap_sb(dev); + /* remap_mpu called by remap_traps */ + + /* Enable or disable I/O traps. */ + cmi8x38_remap_traps(dev); + break; + + case 0x05: + dev->io_regs[addr] = val; + cmi8x38_speed_changed(dev); + break; + + case 0x08: + if (dev->type == CMEDIA_CMI8338) + val &= 0x0f; + break; + + case 0x09: + if (dev->type == CMEDIA_CMI8338) + return; + + /* Update sample rate. */ + dev->io_regs[addr] = val; + cmi8x38_speed_changed(dev); + break; + + case 0x0a: + case 0x0b: + if (dev->type == CMEDIA_CMI8338) + return; + else + val &= 0xe0; + + if (addr == 0x0a) { + /* Set PCI latency timer if requested. */ + dev->pci_regs[0x0d] = (val & 0x80) ? 0x48 : 0x20; /* clearing SETLAT48 is undefined */ + } else { + /* Update channel count. */ + dev->io_regs[addr] = val; + cmi8x38_speed_changed(dev); + } + break; + + case 0x0e: + val &= 0x07; + + /* Clear interrupts. */ + dev->io_regs[0x10] &= val | 0xfc; + if (!(val & 0x04)) + dev->io_regs[0x11] &= ~0xc0; + cmi8x38_update_irqs(dev); + break; + + case 0x15: + if (dev->type == CMEDIA_CMI8338) + return; + else + val &= 0xf0; + + /* Update channel count. */ + dev->io_regs[addr] = val; + cmi8x38_speed_changed(dev); + break; + + case 0x16: + if (dev->type == CMEDIA_CMI8338) { + val &= 0xa0; + + /* Enable or disable I/O traps. */ + dev->io_regs[addr] = val; + cmi8x38_remap_traps(dev); + } + break; + + case 0x17: + if (dev->type == CMEDIA_CMI8338) { + val &= 0xf3; + + /* Force IRQ if requested. Clearing this bit is undefined. */ + if (val & 0x10) + pci_set_irq(dev->pci_slot, PCI_INTA, &dev->irq_state); + else if ((dev->io_regs[0x17] & 0x10) && !(val & 0x10)) + pci_clear_irq(dev->pci_slot, PCI_INTA, &dev->irq_state); + + /* Enable or disable I/O traps. */ + dev->io_regs[addr] = val; + cmi8x38_remap_traps(dev); + } + + /* Remap the legacy devices. */ + dev->io_regs[addr] = val; + cmi8x38_remap_sb(dev); + cmi8x38_remap_mpu(dev); + break; + + case 0x18: + if (dev->type == CMEDIA_CMI8338) + val &= 0x0f; + else + val &= 0xdf; + + /* Update the TDMA position update interrupt's sample interval. */ + dev->tdma_irq_mask = 2047 >> ((val >> 2) & 3); + break; + + case 0x19: + if (dev->type == CMEDIA_CMI8338) + return; + else + val &= 0xe0; + break; + + case 0x1a: + val &= 0xfd; + + /* Enable or disable the OPL. */ + dev->io_regs[addr] = val; + cmi8x38_remap_opl(dev); + break; + + case 0x1b: + if (dev->type == CMEDIA_CMI8338) + val &= 0xf0; + else + val &= 0xd7; + break; + + case 0x20: + /* ??? */ + break; + + case 0x21: + if (dev->type == CMEDIA_CMI8338) + val &= 0xf7; + else + val &= 0x07; + + /* Enable or disable SBPro channel swapping. */ + dev->sb->dsp.sbleftright_default = !!(val & 0x02); + + /* Enable or disable SB16 mode. */ + dev->sb->dsp.sb_type = (val & 0x01) ? SBPRO2 : SB16; + break; + + case 0x22: + case 0x23: + cmi8x38_sb_mixer_write(addr ^ 1, val, dev); + return; + + case 0x24: + if (dev->type == CMEDIA_CMI8338) + val &= 0xcf; + break; + + case 0x27: + if (dev->type == CMEDIA_CMI8338) + val &= 0x03; + else + val &= 0x27; + break; + + case 0x40 ... 0x4f: + if (dev->type != CMEDIA_CMI8338) + mpu401_write(addr, val, dev->sb->mpu); + return; + + case 0x50 ... 0x5f: + if (dev->type != CMEDIA_CMI8338) + dev->sb->opl.write(addr, val, dev->sb->opl.priv); + return; + + case 0x92: + if (dev->type == CMEDIA_CMI8338) + return; + else + val &= 0x1f; + break; + + case 0x93: + if (dev->type == CMEDIA_CMI8338) + return; + else + val &= 0x10; + break; + + case 0x25: + case 0x26: + case 0x70: + case 0x71: + case 0x80 ... 0x8f: + break; + + default: + return; + } + + dev->io_regs[addr] = val; +} + +static void +cmi8x38_remap(cmi8x38_t *dev) +{ + if (dev->io_base) + io_removehandler(dev->io_base, 256, cmi8x38_read, NULL, NULL, cmi8x38_write, NULL, NULL, dev); + + dev->io_base = (dev->pci_regs[0x04] & 0x01) ? (dev->pci_regs[0x11] << 8) : 0; + cmi8x38_log("CMI8x38: remap(%04X)\n", dev->io_base); + + if (dev->io_base) + io_sethandler(dev->io_base, 256, cmi8x38_read, NULL, NULL, cmi8x38_write, NULL, NULL, dev); +} + +static uint8_t +cmi8x38_pci_read(int func, int addr, void *priv) +{ + const cmi8x38_t *dev = (cmi8x38_t *) priv; + uint8_t ret = 0xff; + + if (!func) { + ret = dev->pci_regs[addr]; + cmi8x38_log("CMI8x38: pci_read(%02X) = %02X\n", addr, ret); + } + + return ret; +} + +static void +cmi8x38_pci_write(int func, int addr, uint8_t val, void *priv) +{ + cmi8x38_t *dev = (cmi8x38_t *) priv; + + if (func) + return; + + cmi8x38_log("CMI8x38: pci_write(%02X, %02X)\n", addr, val); + + switch (addr) { + case 0x04: + val &= 0x05; + + /* Enable or disable the I/O BAR. */ + dev->pci_regs[addr] = val; + cmi8x38_remap(dev); + break; + + case 0x05: + val &= 0x01; + break; + + case 0x11: + /* Remap the I/O BAR. */ + dev->pci_regs[addr] = val; + cmi8x38_remap(dev); + break; + + case 0x2c: + case 0x2d: + case 0x2e: + case 0x2f: + if (!(dev->io_regs[0x1a] & 0x01)) + return; + break; + + case 0x40: + if (dev->type == CMEDIA_CMI8338) + val &= 0x0f; + else + return; + break; + + case 0x0c: + case 0x0d: + case 0x3c: + break; + + default: + return; + } + + dev->pci_regs[addr] = val; +} + +static void +cmi8x38_update(cmi8x38_t *dev, cmi8x38_dma_t *dma) +{ + const sb_ct1745_mixer_t *mixer = &dev->sb->mixer_sb16; + int32_t l = (dma->out_fl * mixer->voice_l) * mixer->master_l; + int32_t r = (dma->out_fr * mixer->voice_r) * mixer->master_r; + + for (; dma->pos < sound_pos_global; dma->pos++) { + dma->buffer[dma->pos * 2] = l; + dma->buffer[dma->pos * 2 + 1] = r; + } +} + +static void +cmi8x38_dma_process(void *priv) +{ + cmi8x38_dma_t *dma = (cmi8x38_dma_t *) priv; + cmi8x38_t *dev = dma->dev; + + /* Stop if this DMA channel is not active. */ + uint8_t dma_bit = 0x01 << dma->id; + if (!(dev->io_regs[0x02] & dma_bit)) { + cmi8x38_log("CMI8x38: Stopping DMA %d due to inactive channel (%02X)\n", dma->id, dev->io_regs[0x02]); + return; + } + + /* Schedule next run. */ + timer_on_auto(&dma->dma_timer, dma->dma_latch); + + /* Process DMA if it's active, and the FIFO has room or is disabled. */ + uint8_t dma_status = dev->io_regs[0x00] >> dma->id; + if (!(dma_status & 0x04) && (dma->always_run || ((dma->fifo_end - dma->fifo_pos) <= (sizeof(dma->fifo) - 4)))) { + /* Start DMA if requested. */ + if (dma->restart) { + /* Set up base address and counters. + Nothing reads sample_count_out; it's implemented as an assumption. */ + dma->restart = 0; + dma->sample_ptr = *((uint32_t *) &dev->io_regs[dma->reg]); + dma->frame_count_dma = dma->sample_count_out = *((uint16_t *) &dev->io_regs[dma->reg | 0x4]) + 1; + dma->frame_count_fragment = *((uint16_t *) &dev->io_regs[dma->reg | 0x6]) + 1; + + cmi8x38_log("CMI8x38: Starting DMA %d at %08X (count %04X fragment %04X)\n", dma->id, dma->sample_ptr, dma->frame_count_dma, dma->frame_count_fragment); + } + + if (dma_status & 0x01) { + /* Write channel: read data from FIFO. */ + mem_writel_phys(dma->sample_ptr, *((uint32_t *) &dma->fifo[dma->fifo_end & (sizeof(dma->fifo) - 1)])); + } else { + /* Read channel: write data to FIFO. */ + *((uint32_t *) &dma->fifo[dma->fifo_end & (sizeof(dma->fifo) - 1)]) = mem_readl_phys(dma->sample_ptr); + } + dma->fifo_end += 4; + dma->sample_ptr += 4; + + /* Check if the fragment size was reached. */ + if (--dma->frame_count_fragment <= 0) { + /* Reset fragment counter. */ + dma->frame_count_fragment = *((uint16_t *) &dev->io_regs[dma->reg | 0x6]) + 1; +#ifdef ENABLE_CMI8X38_LOG + if (dma->frame_count_fragment > 1) /* avoid log spam if fragment counting is unused, like on the newer WDM drivers (cmudax3) */ + cmi8x38_log("CMI8x38: DMA %d fragment size reached at %04X frames left", dma->id, dma->frame_count_dma - 1); +#endif + /* Fire interrupt if requested. */ + if (dev->io_regs[0x0e] & dma_bit) { +#ifdef ENABLE_CMI8X38_LOG + if (dma->frame_count_fragment > 1) + cmi8x38_log(", firing interrupt\n"); +#endif + /* Set channel interrupt flag. */ + dev->io_regs[0x10] |= dma_bit; + + /* Fire interrupt. */ + cmi8x38_update_irqs(dev); + } else { +#ifdef ENABLE_CMI8X38_LOG + if (dma->frame_count_fragment > 1) + cmi8x38_log("\n"); +#endif + } + } + + /* Check if the buffer's end was reached. */ + if (--dma->frame_count_dma <= 0) { + dma->frame_count_dma = 0; + cmi8x38_log("CMI8x38: DMA %d end reached, restarting\n", dma->id); + + /* Restart DMA on the next run. */ + dma->restart = 1; + } + } +} + +static void +cmi8x38_poll(void *priv) +{ + cmi8x38_dma_t *dma = (cmi8x38_dma_t *) priv; + cmi8x38_t *dev = dma->dev; + int16_t *out_l; + int16_t *out_r; + int16_t *out_ol; + int16_t *out_or; /* o = opposite */ + + /* Schedule next run if playback is enabled. */ + if (dma->playback_enabled) + timer_advance_u64(&dma->poll_timer, dma->timer_latch); + + /* Update audio buffer. */ + cmi8x38_update(dev, dma); + + /* Swap stereo pair if this is the rear DMA channel according to ENDBDAC and XCHGDAC. */ + if ((dev->io_regs[0x1a] & 0x80) && (!!(dev->io_regs[0x1a] & 0x40) ^ dma->id)) { + out_l = &dma->out_rl; + out_r = &dma->out_rr; + out_ol = &dma->out_fl; + out_or = &dma->out_fr; + } else { + out_l = &dma->out_fl; + out_r = &dma->out_fr; + out_ol = &dma->out_rl; + out_or = &dma->out_rr; + } + *out_ol = *out_or = dma->out_c = dma->out_lfe = 0; + + /* Feed next sample from the FIFO. */ + switch ((dev->io_regs[0x08] >> (dma->id << 1)) & 0x03) { + case 0x00: /* Mono, 8-bit PCM */ + if ((dma->fifo_end - dma->fifo_pos) >= 1) { + *out_l = *out_r = (dma->fifo[dma->fifo_pos++ & (sizeof(dma->fifo) - 1)] ^ 0x80) << 8; + dma->sample_count_out--; + goto n4spk3d; + } + break; + + case 0x01: /* Stereo, 8-bit PCM */ + if ((dma->fifo_end - dma->fifo_pos) >= 2) { + *out_l = (dma->fifo[dma->fifo_pos++ & (sizeof(dma->fifo) - 1)] ^ 0x80) << 8; + *out_r = (dma->fifo[dma->fifo_pos++ & (sizeof(dma->fifo) - 1)] ^ 0x80) << 8; + dma->sample_count_out -= 2; + goto n4spk3d; + } + break; + + case 0x02: /* Mono, 16-bit PCM */ + if ((dma->fifo_end - dma->fifo_pos) >= 2) { + *out_l = *out_r = *((uint16_t *) &dma->fifo[dma->fifo_pos & (sizeof(dma->fifo) - 1)]); + dma->fifo_pos += 2; + dma->sample_count_out -= 2; + goto n4spk3d; + } + break; + + case 0x03: /* Stereo, 16-bit PCM, with multi-channel capability */ + switch (dma->channels) { + case 2: + if ((dma->fifo_end - dma->fifo_pos) >= 4) { + *out_l = *((uint16_t *) &dma->fifo[dma->fifo_pos & (sizeof(dma->fifo) - 1)]); + dma->fifo_pos += 2; + *out_r = *((uint16_t *) &dma->fifo[dma->fifo_pos & (sizeof(dma->fifo) - 1)]); + dma->fifo_pos += 2; + dma->sample_count_out -= 4; + goto n4spk3d; + } + break; + + case 4: + if ((dma->fifo_end - dma->fifo_pos) >= 8) { + dma->out_fl = *((uint16_t *) &dma->fifo[dma->fifo_pos & (sizeof(dma->fifo) - 1)]); + dma->fifo_pos += 2; + dma->out_fr = *((uint16_t *) &dma->fifo[dma->fifo_pos & (sizeof(dma->fifo) - 1)]); + dma->fifo_pos += 2; + dma->out_rl = *((uint16_t *) &dma->fifo[dma->fifo_pos & (sizeof(dma->fifo) - 1)]); + dma->fifo_pos += 2; + dma->out_rr = *((uint16_t *) &dma->fifo[dma->fifo_pos & (sizeof(dma->fifo) - 1)]); + dma->fifo_pos += 2; + dma->sample_count_out -= 8; + return; + } + break; + + case 5: /* not supported by WDM and Linux drivers; channel layout assumed */ + if ((dma->fifo_end - dma->fifo_pos) >= 10) { + dma->out_fl = *((uint16_t *) &dma->fifo[dma->fifo_pos & (sizeof(dma->fifo) - 1)]); + dma->fifo_pos += 2; + dma->out_fr = *((uint16_t *) &dma->fifo[dma->fifo_pos & (sizeof(dma->fifo) - 1)]); + dma->fifo_pos += 2; + dma->out_rl = *((uint16_t *) &dma->fifo[dma->fifo_pos & (sizeof(dma->fifo) - 1)]); + dma->fifo_pos += 2; + dma->out_rr = *((uint16_t *) &dma->fifo[dma->fifo_pos & (sizeof(dma->fifo) - 1)]); + dma->fifo_pos += 2; + dma->out_c = *((uint16_t *) &dma->fifo[dma->fifo_pos & (sizeof(dma->fifo) - 1)]); + dma->fifo_pos += 2; + dma->sample_count_out -= 10; + return; + } + break; + + case 6: + if ((dma->fifo_end - dma->fifo_pos) >= 12) { + dma->out_fl = *((uint16_t *) &dma->fifo[dma->fifo_pos & (sizeof(dma->fifo) - 1)]); + dma->fifo_pos += 2; + dma->out_fr = *((uint16_t *) &dma->fifo[dma->fifo_pos & (sizeof(dma->fifo) - 1)]); + dma->fifo_pos += 2; + dma->out_rl = *((uint16_t *) &dma->fifo[dma->fifo_pos & (sizeof(dma->fifo) - 1)]); + dma->fifo_pos += 2; + dma->out_rr = *((uint16_t *) &dma->fifo[dma->fifo_pos & (sizeof(dma->fifo) - 1)]); + dma->fifo_pos += 2; + dma->out_c = *((uint16_t *) &dma->fifo[dma->fifo_pos & (sizeof(dma->fifo) - 1)]); + dma->fifo_pos += 2; + dma->out_lfe = *((uint16_t *) &dma->fifo[dma->fifo_pos & (sizeof(dma->fifo) - 1)]); + dma->fifo_pos += 2; + dma->sample_count_out -= 12; + return; + } + break; + + default: + break; + } + break; + + default: + break; + } + + /* Feed silence if the FIFO is empty. */ + *out_l = *out_r = 0; + + /* Stop playback if DMA is disabled. */ + if ((*((uint32_t *) &dev->io_regs[0x00]) & (0x00010001 << dma->id)) != (0x00010000 << dma->id)) { + cmi8x38_log("CMI8x38: Stopping playback of DMA channel %d\n", dma->id); + dma->playback_enabled = 0; + } + + return; +n4spk3d: + /* Mirror front and rear channels if requested. */ + if (dev->io_regs[0x1b] & 0x04) { + *out_ol = *out_l; + *out_or = *out_r; + } +} + +static void +cmi8x38_get_buffer(int32_t *buffer, int len, void *priv) +{ + cmi8x38_t *dev = (cmi8x38_t *) priv; + + /* Update wave playback channels. */ + cmi8x38_update(dev, &dev->dma[0]); + cmi8x38_update(dev, &dev->dma[1]); + + /* Apply wave mute. */ + if (!(dev->io_regs[0x24] & 0x40)) { + /* Fill buffer. */ + for (int c = 0; c < len * 2; c++) { + buffer[c] += dev->dma[0].buffer[c]; + buffer[c] += dev->dma[1].buffer[c]; + } + } + + dev->dma[0].pos = dev->dma[1].pos = 0; +} + +static void +cmi8x38_speed_changed(void *priv) +{ + cmi8x38_t *dev = (cmi8x38_t *) priv; + double freq; + uint8_t dsr = dev->io_regs[0x09]; + uint8_t freqreg = dev->io_regs[0x05] >> 2; + uint8_t chfmt45 = dev->io_regs[0x0b]; + uint8_t chfmt6 = dev->io_regs[0x15]; + +#ifdef ENABLE_CMI8X38_LOG + char buf[256]; + sprintf(buf, "%02X-%02X-%02X-%02X", dsr, freqreg, chfmt45, chfmt6); +#endif + + /* CMI8338 claims the frequency controls are for DAC (playback) and ADC (recording) + respectively, while CMI8738 claims they're for channel 0 and channel 1. The Linux + driver just assumes the latter definition, so that's what we're going to use here. */ + for (int i = 0; i < (sizeof(dev->dma) / sizeof(dev->dma[0])); i++) { + /* More confusion. The Linux driver implies the sample rate doubling + bits take precedence over any configured sample rate. 128K with both + doubling bits set is also supported there, but that's for newer chips. */ + switch (dsr & 0x03) { + case 0x01: + freq = 88200.0; + break; + case 0x02: + freq = 96000.0; + break; +#if 0 + case 0x03: + freq = 128000.0; + break; +#endif + default: + freq = freqs[freqreg & 0x07]; + break; + } + + /* Set polling timer period. */ + freq = 1000000.0 / freq; + dev->dma[i].timer_latch = (uint64_t) ((double) TIMER_USEC * freq); + + /* Calculate channel count and set DMA timer period. */ + if ((dev->type == CMEDIA_CMI8338) || (i == 0)) { /* multi-channel requires channel 1 */ +stereo: + dev->dma[i].channels = 2; + } else { + if (chfmt45 & 0x80) + dev->dma[i].channels = (chfmt6 & 0x80) ? 6 : 5; + else if (chfmt45 & 0x20) + dev->dma[i].channels = 4; + else + goto stereo; + } + dev->dma[i].dma_latch = freq / dev->dma[i].channels; /* frequency / approximately(dwords * 2) */ + + /* Shift sample rate configuration registers. */ +#ifdef ENABLE_CMI8X38_LOG + sprintf(&buf[strlen(buf)], " %d:%X-%X-%.0f-%dC", i, dsr & 0x03, freqreg & 0x07, 1000000.0 / freq, dev->dma[i].channels); +#endif + dsr >>= 2; + freqreg >>= 3; + } + +#ifdef ENABLE_CMI8X38_LOG + if (cmi8x38_do_log) + ui_sb_bugui(buf); +#endif +} + +static void +cmi8x38_reset(void *priv) +{ + cmi8x38_t *dev = (cmi8x38_t *) priv; + + /* Reset PCI configuration registers. */ + memset(dev->pci_regs, 0, sizeof(dev->pci_regs)); + dev->pci_regs[0x00] = 0xf6; + dev->pci_regs[0x01] = 0x13; + dev->pci_regs[0x02] = dev->type; + dev->pci_regs[0x03] = 0x01; + dev->pci_regs[0x06] = (dev->type == CMEDIA_CMI8338) ? 0x80 : 0x10; + dev->pci_regs[0x07] = 0x02; + dev->pci_regs[0x08] = 0x10; + dev->pci_regs[0x0a] = 0x01; + dev->pci_regs[0x0b] = 0x04; + dev->pci_regs[0x0d] = 0x20; + dev->pci_regs[0x10] = 0x01; + dev->pci_regs[0x2c] = 0xf6; + dev->pci_regs[0x2d] = 0x13; + if (dev->type == CMEDIA_CMI8338) { + dev->pci_regs[0x2e] = 0xff; + dev->pci_regs[0x2f] = 0xff; + } else { + dev->pci_regs[0x2e] = dev->type; + dev->pci_regs[0x2f] = 0x01; + dev->pci_regs[0x34] = 0x40; + } + dev->pci_regs[0x3d] = 0x01; + dev->pci_regs[0x3e] = 0x02; + dev->pci_regs[0x3f] = 0x18; + + /* Reset I/O space registers. */ + memset(dev->io_regs, 0, sizeof(dev->io_regs)); + dev->io_regs[0x0b] = (dev->type >> 8) & 0x1f; + dev->io_regs[0x0f] = dev->type >> 16; + dev->tdma_irq_mask = 2047; + + /* Reset I/O mappings. */ + cmi8x38_remap(dev); + cmi8x38_remap_sb(dev); + /* remap_mpu and remap_opl called by remap_traps */ + cmi8x38_remap_traps(dev); + + /* Reset DMA channels. */ + for (int i = 0; i < (sizeof(dev->dma) / sizeof(dev->dma[0])); i++) { + dev->dma[i].playback_enabled = 0; + dev->dma[i].fifo_pos = dev->dma[i].fifo_end = 0; + memset(dev->dma[i].fifo, 0, sizeof(dev->dma[i].fifo)); + } + + /* Reset TDMA channel. */ + dev->tdma_8 = 1; + dev->tdma_16 = 5; + dev->tdma_mask = 0; + + /* Reset Sound Blaster 16 mixer. */ + sb_ct1745_mixer_reset(dev->sb); +} + +static void * +cmi8x38_init(const device_t *info) +{ + cmi8x38_t *dev = malloc(sizeof(cmi8x38_t)); + memset(dev, 0, sizeof(cmi8x38_t)); + + /* Set the chip type. */ + if ((info->local == CMEDIA_CMI8738_6CH) && !device_get_config_int("six_channel")) + dev->type = CMEDIA_CMI8738_4CH; + else + dev->type = info->local; + cmi8x38_log("CMI8x38: init(%06X)\n", dev->type); + + /* Initialize Sound Blaster 16. */ + dev->sb = device_add_inst(device_get_config_int("receive_input") ? &sb_16_compat_device : &sb_16_compat_nompu_device, 1); + dev->sb->opl_enabled = 1; /* let snd_sb.c handle the OPL3 */ + dev->sb->mixer_sb16.output_filter = 0; /* no output filtering */ + + /* Initialize legacy interrupt and DMA handlers. */ + mpu401_irq_attach(dev->sb->mpu, cmi8x38_mpu_irq_update, cmi8x38_mpu_irq_pending, dev); + sb_dsp_irq_attach(&dev->sb->dsp, cmi8x38_sb_irq_update, dev); + sb_dsp_dma_attach(&dev->sb->dsp, cmi8x38_sb_dma_readb, cmi8x38_sb_dma_readw, cmi8x38_sb_dma_writeb, cmi8x38_sb_dma_writew, dev); + io_sethandler(0x00, 8, NULL, NULL, NULL, cmi8x38_dma_write, NULL, NULL, dev); + io_sethandler(0x08, 8, NULL, NULL, NULL, cmi8x38_dma_mask_write, NULL, NULL, dev); + io_sethandler(0xc0, 16, NULL, NULL, NULL, cmi8x38_dma_write, NULL, NULL, dev); + io_sethandler(0xd0, 16, NULL, NULL, NULL, cmi8x38_dma_mask_write, NULL, NULL, dev); + + /* Initialize DMA channels. */ + for (int i = 0; i < (sizeof(dev->dma) / sizeof(dev->dma[0])); i++) { + dev->dma[i].id = i; + dev->dma[i].reg = 0x80 + (8 * i); + dev->dma[i].dev = dev; + + timer_add(&dev->dma[i].dma_timer, cmi8x38_dma_process, &dev->dma[i], 0); + timer_add(&dev->dma[i].poll_timer, cmi8x38_poll, &dev->dma[i], 0); + } + cmi8x38_speed_changed(dev); + + /* Initialize playback handler and CD audio filter. */ + sound_add_handler(cmi8x38_get_buffer, dev); + sound_set_cd_audio_filter(sb16_awe32_filter_cd_audio, dev->sb); + + /* Initialize game port. */ + dev->gameport = gameport_add(&gameport_pnp_device); + + /* Initialize I/O traps. */ + if (dev->type == CMEDIA_CMI8338) { + dev->io_traps[TRAP_DMA] = io_trap_add(cmi8338_io_trap, dev); + dev->io_traps[TRAP_PIC] = io_trap_add(cmi8338_io_trap, dev); + dev->io_traps[TRAP_OPL] = io_trap_add(cmi8338_io_trap, dev); + dev->io_traps[TRAP_MPU] = io_trap_add(cmi8338_io_trap, dev); + } + + /* Add PCI card. */ + pci_add_card((info->local & (1 << 13)) ? PCI_ADD_SOUND : PCI_ADD_NORMAL, cmi8x38_pci_read, cmi8x38_pci_write, dev, &dev->pci_slot); + + /* Perform initial reset. */ + cmi8x38_reset(dev); + + return dev; +} + +static void +cmi8x38_close(void *priv) +{ + cmi8x38_t *dev = (cmi8x38_t *) priv; + + cmi8x38_log("CMI8x38: close()\n"); + + for (int i = 0; i < TRAP_MAX; i++) + io_trap_remove(dev->io_traps[i]); + + free(dev); +} + +static const device_config_t cmi8x38_config[] = { + // clang-format off + { + .name = "receive_input", + .description = "Receive input (MPU-401)", + .type = CONFIG_BINARY, + .default_string = "", + .default_int = 1 + }, + { .name = "", .description = "", .type = CONFIG_END } + // clang-format on +}; + +static const device_config_t cmi8738_config[] = { + // clang-format off + { + .name = "six_channel", + .description = "6CH variant (6-channel)", + .type = CONFIG_BINARY, + .default_string = "", + .default_int = 1 + }, + { + .name = "receive_input", + .description = "Receive input (MPU-401)", + .type = CONFIG_BINARY, + .default_string = "", + .default_int = 1 + }, + { .name = "", .description = "", .type = CONFIG_END } + // clang-format on +}; + +const device_t cmi8338_device = { + .name = "C-Media CMI8338", + .internal_name = "cmi8338", + .flags = DEVICE_PCI, + .local = CMEDIA_CMI8338, + .init = cmi8x38_init, + .close = cmi8x38_close, + .reset = cmi8x38_reset, + { .available = NULL }, + .speed_changed = cmi8x38_speed_changed, + .force_redraw = NULL, + .config = cmi8x38_config +}; + +const device_t cmi8338_onboard_device = { + .name = "C-Media CMI8338 (On-Board)", + .internal_name = "cmi8338_onboard", + .flags = DEVICE_PCI, + .local = CMEDIA_CMI8338 | (1 << 13), + .init = cmi8x38_init, + .close = cmi8x38_close, + .reset = cmi8x38_reset, + { .available = NULL }, + .speed_changed = cmi8x38_speed_changed, + .force_redraw = NULL, + .config = cmi8x38_config +}; + +const device_t cmi8738_device = { + .name = "C-Media CMI8738", + .internal_name = "cmi8738", + .flags = DEVICE_PCI, + .local = CMEDIA_CMI8738_6CH, + .init = cmi8x38_init, + .close = cmi8x38_close, + .reset = cmi8x38_reset, + { .available = NULL }, + .speed_changed = cmi8x38_speed_changed, + .force_redraw = NULL, + .config = cmi8738_config +}; + +const device_t cmi8738_onboard_device = { + .name = "C-Media CMI8738 (On-Board)", + .internal_name = "cmi8738_onboard", + .flags = DEVICE_PCI, + .local = CMEDIA_CMI8738_4CH | (1 << 13), + .init = cmi8x38_init, + .close = cmi8x38_close, + .reset = cmi8x38_reset, + { .available = NULL }, + .speed_changed = cmi8x38_speed_changed, + .force_redraw = NULL, + .config = cmi8x38_config +}; + +const device_t cmi8738_6ch_onboard_device = { + .name = "C-Media CMI8738-6CH (On-Board)", + .internal_name = "cmi8738_6ch_onboard", + .flags = DEVICE_PCI, + .local = CMEDIA_CMI8738_6CH | (1 << 13), + .init = cmi8x38_init, + .close = cmi8x38_close, + .reset = cmi8x38_reset, + { .available = NULL }, + .speed_changed = cmi8x38_speed_changed, + .force_redraw = NULL, + .config = cmi8x38_config +}; diff --git a/src/sound/snd_cms.c b/src/sound/snd_cms.c index b0f979849..d33eba83a 100644 --- a/src/sound/snd_cms.c +++ b/src/sound/snd_cms.c @@ -1,215 +1,256 @@ #include #include #include -#include #include +#include #include #define HAVE_STDARG_H #include <86box/86box.h> -#include <86box/io.h> #include <86box/device.h> -#include <86box/sound.h> +#include <86box/io.h> #include <86box/snd_cms.h> +#include <86box/sound.h> +#include <86box/plat_unused.h> - -void cms_update(cms_t *cms) +void +cms_update(cms_t *cms) { - for (; cms->pos < sound_pos_global; cms->pos++) - { - int c, d; - int16_t out_l = 0, out_r = 0; + for (; cms->pos < sound_pos_global; cms->pos++) { + int16_t out_l = 0; + int16_t out_r = 0; - for (c = 0; c < 4; c++) - { - switch (cms->noisetype[c >> 1][c & 1]) - { - case 0: cms->noisefreq[c >> 1][c & 1] = MASTER_CLOCK/256; break; - case 1: cms->noisefreq[c >> 1][c & 1] = MASTER_CLOCK/512; break; - case 2: cms->noisefreq[c >> 1][c & 1] = MASTER_CLOCK/1024; break; - case 3: cms->noisefreq[c >> 1][c & 1] = cms->freq[c >> 1][(c & 1) * 3]; break; - } - } - for (c = 0; c < 2; c ++) - { - if (cms->regs[c][0x1C] & 1) - { - for (d = 0; d < 6; d++) - { - if (cms->regs[c][0x14] & (1 << d)) - { - if (cms->stat[c][d]) out_l += (cms->vol[c][d][0] * 90); - if (cms->stat[c][d]) out_r += (cms->vol[c][d][1] * 90); - cms->count[c][d] += cms->freq[c][d]; - if (cms->count[c][d] >= 24000) - { - cms->count[c][d] -= 24000; - cms->stat[c][d] ^= 1; - } - } - else if (cms->regs[c][0x15] & (1 << d)) - { - if (cms->noise[c][d / 3] & 1) out_l += (cms->vol[c][d][0] * 90); - if (cms->noise[c][d / 3] & 1) out_r += (cms->vol[c][d][0] * 90); - } - } - for (d = 0; d < 2; d++) - { - cms->noisecount[c][d] += cms->noisefreq[c][d]; - while (cms->noisecount[c][d] >= 24000) - { - cms->noisecount[c][d] -= 24000; - cms->noise[c][d] <<= 1; - if (!(((cms->noise[c][d] & 0x4000) >> 8) ^ (cms->noise[c][d] & 0x40))) - cms->noise[c][d] |= 1; - } - } - } - } - cms->buffer[(cms->pos << 1)] = out_l; - cms->buffer[(cms->pos << 1) + 1] = out_r; - } -} - -void cms_get_buffer(int32_t *buffer, int len, void *p) -{ - cms_t *cms = (cms_t *)p; - - int c; - - cms_update(cms); - - for (c = 0; c < len * 2; c++) - buffer[c] += cms->buffer[c]; - - cms->pos = 0; -} - -void cms_write(uint16_t addr, uint8_t val, void *p) -{ - cms_t *cms = (cms_t *)p; - int voice; - int chip = (addr & 2) >> 1; - - switch (addr & 0xf) - { + for (uint8_t c = 0; c < 4; c++) { + switch (cms->noisetype[c >> 1][c & 1]) { + case 0: + cms->noisefreq[c >> 1][c & 1] = MASTER_CLOCK / 256; + break; case 1: - cms->addrs[0] = val & 31; - break; + cms->noisefreq[c >> 1][c & 1] = MASTER_CLOCK / 512; + break; + case 2: + cms->noisefreq[c >> 1][c & 1] = MASTER_CLOCK / 1024; + break; case 3: - cms->addrs[1] = val & 31; - break; - - case 0: case 2: - cms_update(cms); - cms->regs[chip][cms->addrs[chip] & 31] = val; - switch (cms->addrs[chip] & 31) - { - case 0x00: case 0x01: case 0x02: /*Volume*/ - case 0x03: case 0x04: case 0x05: - voice = cms->addrs[chip] & 7; - cms->vol[chip][voice][0] = val & 0xf; - cms->vol[chip][voice][1] = val >> 4; - break; - case 0x08: case 0x09: case 0x0A: /*Frequency*/ - case 0x0B: case 0x0C: case 0x0D: - voice = cms->addrs[chip] & 7; - cms->latch[chip][voice] = (cms->latch[chip][voice] & 0x700) | val; - cms->freq[chip][voice] = (MASTER_CLOCK/512 << (cms->latch[chip][voice] >> 8)) / (511 - (cms->latch[chip][voice] & 255)); - break; - case 0x10: case 0x11: case 0x12: /*Octave*/ - voice = (cms->addrs[chip] & 3) << 1; - cms->latch[chip][voice] = (cms->latch[chip][voice] & 0xFF) | ((val & 7) << 8); - cms->latch[chip][voice + 1] = (cms->latch[chip][voice + 1] & 0xFF) | ((val & 0x70) << 4); - cms->freq[chip][voice] = (MASTER_CLOCK/512 << (cms->latch[chip][voice] >> 8)) / (511 - (cms->latch[chip][voice] & 255)); - cms->freq[chip][voice + 1] = (MASTER_CLOCK/512 << (cms->latch[chip][voice + 1] >> 8)) / (511 - (cms->latch[chip][voice + 1] & 255)); - break; - case 0x16: /*Noise*/ - cms->noisetype[chip][0] = val & 3; - cms->noisetype[chip][1] = (val >> 4) & 3; - break; - } - break; - case 0x6: case 0x7: - cms->latched_data = val; - break; + cms->noisefreq[c >> 1][c & 1] = cms->freq[c >> 1][(c & 1) * 3]; + break; + + default: + break; + } } -} - -uint8_t cms_read(uint16_t addr, void *p) -{ - cms_t *cms = (cms_t *)p; - - switch (addr & 0xf) - { - case 0x1: - return cms->addrs[0]; - case 0x3: - return cms->addrs[1]; - case 0x4: - return 0x7f; - case 0xa: case 0xb: - return cms->latched_data; - } - return 0xff; -} - -void *cms_init(const device_t *info) -{ - cms_t *cms = malloc(sizeof(cms_t)); - memset(cms, 0, sizeof(cms_t)); - - uint16_t addr = device_get_config_hex16("base"); - io_sethandler(addr, 0x0010, cms_read, NULL, NULL, cms_write, NULL, NULL, cms); - sound_add_handler(cms_get_buffer, cms); - return cms; -} - -void cms_close(void *p) -{ - cms_t *cms = (cms_t *)p; - - free(cms); -} - -static const device_config_t cms_config[] = -{ - { - "base", "Address", CONFIG_HEX16, "", 0x220, "", { 0 }, - { - { - "0x210", 0x210 - }, - { - "0x220", 0x220 - }, - { - "0x230", 0x230 - }, - { - "0x240", 0x240 - }, - { - "0x250", 0x250 - }, - { - "0x260", 0x260 - }, - { - "" + for (uint8_t c = 0; c < 2; c++) { + if (cms->regs[c][0x1C] & 1) { + for (uint8_t d = 0; d < 6; d++) { + if (cms->regs[c][0x14] & (1 << d)) { + if (cms->stat[c][d]) + out_l += (cms->vol[c][d][0] * 90); + if (cms->stat[c][d]) + out_r += (cms->vol[c][d][1] * 90); + cms->count[c][d] += cms->freq[c][d]; + if (cms->count[c][d] >= 24000) { + cms->count[c][d] -= 24000; + cms->stat[c][d] ^= 1; } + } else if (cms->regs[c][0x15] & (1 << d)) { + if (cms->noise[c][d / 3] & 1) + out_l += (cms->vol[c][d][0] * 90); + if (cms->noise[c][d / 3] & 1) + out_r += (cms->vol[c][d][0] * 90); + } } - }, - { - "", "", -1 + for (uint8_t d = 0; d < 2; d++) { + cms->noisecount[c][d] += cms->noisefreq[c][d]; + while (cms->noisecount[c][d] >= 24000) { + cms->noisecount[c][d] -= 24000; + cms->noise[c][d] <<= 1; + if (!(((cms->noise[c][d] & 0x4000) >> 8) ^ (cms->noise[c][d] & 0x40))) + cms->noise[c][d] |= 1; + } + } + } } + cms->buffer[cms->pos << 1] = out_l; + cms->buffer[(cms->pos << 1) + 1] = out_r; + } +} + +void +cms_get_buffer(int32_t *buffer, int len, void *priv) +{ + cms_t *cms = (cms_t *) priv; + + cms_update(cms); + + for (int c = 0; c < len * 2; c++) + buffer[c] += cms->buffer[c]; + + cms->pos = 0; +} + +void +cms_write(uint16_t addr, uint8_t val, void *priv) +{ + cms_t *cms = (cms_t *) priv; + int voice; + int chip = (addr & 2) >> 1; + + switch (addr & 0xf) { + case 1: + cms->addrs[0] = val & 31; + break; + case 3: + cms->addrs[1] = val & 31; + break; + + case 0: + case 2: + cms_update(cms); + cms->regs[chip][cms->addrs[chip] & 31] = val; + switch (cms->addrs[chip] & 31) { + case 0x00: + case 0x01: + case 0x02: /*Volume*/ + case 0x03: + case 0x04: + case 0x05: + voice = cms->addrs[chip] & 7; + cms->vol[chip][voice][0] = val & 0xf; + cms->vol[chip][voice][1] = val >> 4; + break; + case 0x08: + case 0x09: + case 0x0A: /*Frequency*/ + case 0x0B: + case 0x0C: + case 0x0D: + voice = cms->addrs[chip] & 7; + cms->latch[chip][voice] = (cms->latch[chip][voice] & 0x700) | val; + cms->freq[chip][voice] = (MASTER_CLOCK / 512 << (cms->latch[chip][voice] >> 8)) / (511 - (cms->latch[chip][voice] & 255)); + break; + case 0x10: + case 0x11: + case 0x12: /*Octave*/ + voice = (cms->addrs[chip] & 3) << 1; + cms->latch[chip][voice] = (cms->latch[chip][voice] & 0xFF) | ((val & 7) << 8); + cms->latch[chip][voice + 1] = (cms->latch[chip][voice + 1] & 0xFF) | ((val & 0x70) << 4); + cms->freq[chip][voice] = (MASTER_CLOCK / 512 << (cms->latch[chip][voice] >> 8)) / (511 - (cms->latch[chip][voice] & 255)); + cms->freq[chip][voice + 1] = (MASTER_CLOCK / 512 << (cms->latch[chip][voice + 1] >> 8)) / (511 - (cms->latch[chip][voice + 1] & 255)); + break; + case 0x16: /*Noise*/ + cms->noisetype[chip][0] = val & 3; + cms->noisetype[chip][1] = (val >> 4) & 3; + break; + + default: + break; + } + break; + case 0x6: + case 0x7: + cms->latched_data = val; + break; + + default: + break; + } +} + +uint8_t +cms_read(uint16_t addr, void *priv) +{ + const cms_t *cms = (cms_t *) priv; + + switch (addr & 0xf) { + case 0x1: + return cms->addrs[0]; + case 0x3: + return cms->addrs[1]; + case 0x4: + return 0x7f; + case 0xa: + case 0xb: + return cms->latched_data; + + default: + break; + } + return 0xff; +} + +void * +cms_init(UNUSED(const device_t *info)) +{ + cms_t *cms = malloc(sizeof(cms_t)); + memset(cms, 0, sizeof(cms_t)); + + uint16_t addr = device_get_config_hex16("base"); + io_sethandler(addr, 0x0010, cms_read, NULL, NULL, cms_write, NULL, NULL, cms); + sound_add_handler(cms_get_buffer, cms); + return cms; +} + +void +cms_close(void *priv) +{ + cms_t *cms = (cms_t *) priv; + + free(cms); +} + +static const device_config_t cms_config[] = { + // clang-format off + { + .name = "base", + .description = "Address", + .type = CONFIG_HEX16, + .default_string = "", + .default_int = 0x220, + .file_filter = "", + .spinner = { 0 }, + .selection = { + { + .description = "0x210", + .value = 0x210 + }, + { + .description = "0x220", + .value = 0x220 + }, + { + .description = "0x230", + .value = 0x230 + }, + { + .description = "0x240", + .value = 0x240 + }, + { + .description = "0x250", + .value = 0x250 + }, + { + .description = "0x260", + .value = 0x260 + }, + { + .description = "" + } + } + }, + { .name = "", .description = "", .type = CONFIG_END } + // clang-format on }; -const device_t cms_device = -{ - "Creative Music System / Game Blaster", - "cms", - DEVICE_ISA, 0, - cms_init, cms_close, NULL, - { NULL }, NULL, NULL, - cms_config +const device_t cms_device = { + .name = "Creative Music System / Game Blaster", + .internal_name = "cms", + .flags = DEVICE_ISA, + .local = 0, + .init = cms_init, + .close = cms_close, + .reset = NULL, + { .available = NULL }, + .speed_changed = NULL, + .force_redraw = NULL, + .config = cms_config }; diff --git a/src/sound/snd_cs423x.c b/src/sound/snd_cs423x.c index d159182e4..fad1d76b9 100644 --- a/src/sound/snd_cs423x.c +++ b/src/sound/snd_cs423x.c @@ -1,43 +1,48 @@ /* - * 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. + * 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. + * This file is part of the 86Box distribution. * - * Crystal CS423x (SBPro/WSS compatible sound chips) emulation. + * Crystal CS423x (SBPro/WSS compatible sound chips) emulation. * * * - * Authors: RichardG, + * Authors: RichardG, * - * Copyright 2021 RichardG. + * Copyright 2021-2022 RichardG. */ -#include -#include -#include -#include -#include #include +#include +#include +#include +#include +#include + #include <86box/86box.h> -#include <86box/io.h> -#include <86box/timer.h> -#include <86box/pic.h> -#include <86box/dma.h> #include <86box/device.h> +#include <86box/dma.h> #include <86box/gameport.h> #include <86box/i2c.h> +#include <86box/io.h> #include <86box/isapnp.h> -#include <86box/sound.h> #include <86box/midi.h> +#include <86box/timer.h> +#include <86box/nvr.h> +#include <86box/pic.h> +#include <86box/sound.h> #include <86box/snd_ad1848.h> #include <86box/snd_opl.h> #include <86box/snd_sb.h> -#include <86box/nvr.h> +#include <86box/plat_fallthrough.h> +#include <86box/plat_unused.h> +#define CRYSTAL_NOEEPROM 0x100 enum { + CRYSTAL_CS4235 = 0xdd, CRYSTAL_CS4236B = 0xcb, CRYSTAL_CS4237B = 0xc8, CRYSTAL_CS4238B = 0xc9 @@ -49,12 +54,12 @@ enum { CRYSTAL_SLAM_BYTE2 = 3 }; - static const uint8_t slam_init_key[32] = { 0x96, 0x35, 0x9A, 0xCD, 0xE6, 0xF3, 0x79, 0xBC, - 0x5E, 0xAF, 0x57, 0x2B, 0x15, 0x8A, 0xC5, 0xE2, - 0xF1, 0xF8, 0x7C, 0x3E, 0x9F, 0x4F, 0x27, 0x13, - 0x09, 0x84, 0x42, 0xA1, 0xD0, 0x68, 0x34, 0x1A }; -static const uint8_t cs4236b_eeprom[] = { + 0x5E, 0xAF, 0x57, 0x2B, 0x15, 0x8A, 0xC5, 0xE2, + 0xF1, 0xF8, 0x7C, 0x3E, 0x9F, 0x4F, 0x27, 0x13, + 0x09, 0x84, 0x42, 0xA1, 0xD0, 0x68, 0x34, 0x1A }; +static const uint8_t cs4236b_eeprom[] = { + // clang-format off /* Chip configuration */ 0x55, 0xbb, /* magic */ 0x00, 0x00, /* length */ @@ -69,615 +74,655 @@ static const uint8_t cs4236b_eeprom[] = { 0x10, 0x03, /* DMA routing */ /* PnP resources */ - 0x0e, 0x63, 0x42, 0x36, 0x00, 0x00, 0x00, 0x00, 0x00, /* CSC4236, dummy checksum (filled in by isapnp_add_card) */ + 0x0e, 0x63, 0x42, 0x35, 0x00, 0x00, 0x00, 0x00, 0x00, /* CSC4236, dummy checksum (filled in by isapnp_add_card) */ 0x0a, 0x10, 0x01, /* PnP version 1.0, vendor version 0.1 */ 0x82, 0x0e, 0x00, 'C', 'r', 'y', 's', 't', 'a', 'l', ' ', 'C', 'o', 'd', 'e' ,'c', 0x00, /* ANSI identifier */ 0x15, 0x0e, 0x63, 0x00, 0x00, 0x00, /* logical device CSC0000 */ - 0x82, 0x07, 0x00, 'W', 'S', 'S', '/', 'S', 'B', 0x00, /* ANSI identifier */ - 0x31, 0x00, /* start dependent functions, preferred */ - 0x2a, 0x02, 0x28, /* DMA 1, type A, no count by word, count by byte, not bus master, 8-bit only */ - 0x2a, 0x09, 0x28, /* DMA 0/3, type A, no count by word, count by byte, not bus master, 8-bit only */ - 0x22, 0x20, 0x00, /* IRQ 5 */ - 0x47, 0x01, 0x34, 0x05, 0x34, 0x05, 0x04, 0x04, /* I/O 0x534, decodes 16-bit, 4-byte alignment, 4 addresses */ - 0x47, 0x01, 0x88, 0x03, 0x88, 0x03, 0x08, 0x04, /* I/O 0x388, decodes 16-bit, 8-byte alignment, 4 addresses */ - 0x47, 0x01, 0x20, 0x02, 0x20, 0x02, 0x20, 0x10, /* I/O 0x220, decodes 16-bit, 32-byte alignment, 16 addresses */ - 0x31, 0x01, /* start dependent functions, acceptable */ - 0x2a, 0x0a, 0x28, /* DMA 1/3, type A, no count by word, count by byte, not bus master, 8-bit only */ - 0x2a, 0x0b, 0x28, /* DMA 0/1/3, type A, no count by word, count by byte, not bus master, 8-bit only */ - 0x22, 0xa0, 0x9a, /* IRQ 5/7/9/11/12/15 */ - 0x47, 0x01, 0x34, 0x05, 0xfc, 0x0f, 0x04, 0x04, /* I/O 0x534-0xFFC, decodes 16-bit, 4-byte alignment, 4 addresses */ - 0x47, 0x01, 0x88, 0x03, 0x88, 0x03, 0x08, 0x04, /* I/O 0x388, decodes 16-bit, 8-byte alignment, 4 addresses */ - 0x47, 0x01, 0x20, 0x02, 0x60, 0x02, 0x20, 0x10, /* I/O 0x220-0x260, decodes 16-bit, 32-byte alignment, 16 addresses */ - 0x31, 0x02, /* start dependent functions, sub-optimal */ - 0x2a, 0x0b, 0x28, /* DMA 0/1/3, type A, no count by word, count by byte, not bus master, 8-bit only */ - 0x22, 0xa0, 0x9a, /* IRQ 5/7/9/11/12/15 */ - 0x47, 0x01, 0x34, 0x05, 0xfc, 0x0f, 0x04, 0x04, /* I/O 0x534-0xFFC, decodes 16-bit, 4-byte alignment, 4 addresses */ - 0x47, 0x01, 0x88, 0x03, 0xf8, 0x03, 0x08, 0x04, /* I/O 0x388-0x3F8, decodes 16-bit, 8-byte alignment, 4 addresses */ - 0x47, 0x01, 0x20, 0x02, 0x00, 0x03, 0x20, 0x10, /* I/O 0x220-0x300, decodes 16-bit, 32-byte alignment, 16 addresses */ - 0x38, /* end dependent functions */ + 0x82, 0x07, 0x00, 'W', 'S', 'S', '/', 'S', 'B', 0x00, /* ANSI identifier */ + 0x31, 0x00, /* start dependent functions, preferred */ + 0x2a, 0x02, 0x28, /* DMA 1, type A, no count by word, count by byte, not bus master, 8-bit only */ + 0x2a, 0x09, 0x28, /* DMA 0/3, type A, no count by word, count by byte, not bus master, 8-bit only */ + 0x22, 0x20, 0x00, /* IRQ 5 */ + 0x47, 0x01, 0x34, 0x05, 0x34, 0x05, 0x04, 0x04, /* I/O 0x534, decodes 16-bit, 4-byte alignment, 4 addresses */ + 0x47, 0x01, 0x88, 0x03, 0x88, 0x03, 0x08, 0x04, /* I/O 0x388, decodes 16-bit, 8-byte alignment, 4 addresses */ + 0x47, 0x01, 0x20, 0x02, 0x20, 0x02, 0x20, 0x10, /* I/O 0x220, decodes 16-bit, 32-byte alignment, 16 addresses */ + 0x31, 0x01, /* start dependent functions, acceptable */ + 0x2a, 0x0a, 0x28, /* DMA 1/3, type A, no count by word, count by byte, not bus master, 8-bit only */ + 0x2a, 0x0b, 0x28, /* DMA 0/1/3, type A, no count by word, count by byte, not bus master, 8-bit only */ + 0x22, 0xa0, 0x9a, /* IRQ 5/7/9/11/12/15 */ + 0x47, 0x01, 0x34, 0x05, 0xfc, 0x0f, 0x04, 0x04, /* I/O 0x534-0xFFC, decodes 16-bit, 4-byte alignment, 4 addresses */ + 0x47, 0x01, 0x88, 0x03, 0x88, 0x03, 0x08, 0x04, /* I/O 0x388, decodes 16-bit, 8-byte alignment, 4 addresses */ + 0x47, 0x01, 0x20, 0x02, 0x60, 0x02, 0x20, 0x10, /* I/O 0x220-0x260, decodes 16-bit, 32-byte alignment, 16 addresses */ + 0x31, 0x02, /* start dependent functions, sub-optimal */ + 0x2a, 0x0b, 0x28, /* DMA 0/1/3, type A, no count by word, count by byte, not bus master, 8-bit only */ + 0x22, 0xa0, 0x9a, /* IRQ 5/7/9/11/12/15 */ + 0x47, 0x01, 0x34, 0x05, 0xfc, 0x0f, 0x04, 0x04, /* I/O 0x534-0xFFC, decodes 16-bit, 4-byte alignment, 4 addresses */ + 0x47, 0x01, 0x88, 0x03, 0xf8, 0x03, 0x08, 0x04, /* I/O 0x388-0x3F8, decodes 16-bit, 8-byte alignment, 4 addresses */ + 0x47, 0x01, 0x20, 0x02, 0x00, 0x03, 0x20, 0x10, /* I/O 0x220-0x300, decodes 16-bit, 32-byte alignment, 16 addresses */ + 0x38, /* end dependent functions */ 0x15, 0x0e, 0x63, 0x00, 0x01, 0x00, /* logical device CSC0001 */ - 0x82, 0x05, 0x00, 'G', 'A', 'M', 'E', 0x00, /* ANSI identifier */ - 0x31, 0x00, /* start dependent functions, preferred */ - 0x47, 0x01, 0x00, 0x02, 0x00, 0x02, 0x08, 0x08, /* I/O 0x200, decodes 16-bit, 8-byte alignment, 8 addresses */ - 0x31, 0x01, /* start dependent functions, acceptable */ - 0x47, 0x01, 0x08, 0x02, 0x08, 0x02, 0x08, 0x08, /* I/O 0x208, decodes 16-bit, 8-byte alignment, 8 addresses */ - 0x38, /* end dependent functions */ + 0x82, 0x05, 0x00, 'G', 'A', 'M', 'E', 0x00, /* ANSI identifier */ + 0x31, 0x00, /* start dependent functions, preferred */ + 0x47, 0x01, 0x00, 0x02, 0x00, 0x02, 0x08, 0x08, /* I/O 0x200, decodes 16-bit, 8-byte alignment, 8 addresses */ + 0x31, 0x01, /* start dependent functions, acceptable */ + 0x47, 0x01, 0x08, 0x02, 0x08, 0x02, 0x08, 0x08, /* I/O 0x208, decodes 16-bit, 8-byte alignment, 8 addresses */ + 0x38, /* end dependent functions */ 0x15, 0x0e, 0x63, 0x00, 0x10, 0x00, /* logical device CSC0010 */ - 0x82, 0x05, 0x00, 'C', 'T', 'R', 'L', 0x00, /* ANSI identifier */ - 0x47, 0x01, 0x20, 0x01, 0xf8, 0x0f, 0x08, 0x08, /* I/O 0x120-0xFF8, decodes 16-bit, 8-byte alignment, 8 addresses */ + 0x82, 0x05, 0x00, 'C', 'T', 'R', 'L', 0x00, /* ANSI identifier */ + 0x47, 0x01, 0x20, 0x01, 0xf8, 0x0f, 0x08, 0x08, /* I/O 0x120-0xFF8, decodes 16-bit, 8-byte alignment, 8 addresses */ 0x15, 0x0e, 0x63, 0x00, 0x03, 0x00, /* logical device CSC0003 */ - 0x82, 0x04, 0x00, 'M', 'P', 'U', 0x00, /* ANSI identifier */ - 0x31, 0x00, /* start dependent functions, preferred */ - 0x22, 0x00, 0x02, /* IRQ 9 */ - 0x47, 0x01, 0x30, 0x03, 0x30, 0x03, 0x08, 0x02, /* I/O 0x330, decodes 16-bit, 8-byte alignment, 2 addresses */ - 0x31, 0x01, /* start dependent functions, acceptable */ - 0x22, 0x00, 0x9a, /* IRQ 9/11/12/15 */ - 0x47, 0x01, 0x30, 0x03, 0x60, 0x03, 0x08, 0x02, /* I/O 0x330-0x360, decodes 16-bit, 8-byte alignment, 2 addresses */ - 0x31, 0x02, /* start dependent functions, sub-optimal */ - 0x47, 0x01, 0x30, 0x03, 0xe0, 0x03, 0x08, 0x02, /* I/O 0x330-0x3E0, decodes 16-bit, 8-byte alignment, 2 addresses */ - 0x38, /* end dependent functions */ + 0x82, 0x04, 0x00, 'M', 'P', 'U', 0x00, /* ANSI identifier */ + 0x31, 0x00, /* start dependent functions, preferred */ + 0x22, 0x00, 0x02, /* IRQ 9 */ + 0x47, 0x01, 0x30, 0x03, 0x30, 0x03, 0x08, 0x02, /* I/O 0x330, decodes 16-bit, 8-byte alignment, 2 addresses */ + 0x31, 0x01, /* start dependent functions, acceptable */ + 0x22, 0x00, 0x9a, /* IRQ 9/11/12/15 */ + 0x47, 0x01, 0x30, 0x03, 0x60, 0x03, 0x08, 0x02, /* I/O 0x330-0x360, decodes 16-bit, 8-byte alignment, 2 addresses */ + 0x31, 0x02, /* start dependent functions, sub-optimal */ + 0x47, 0x01, 0x30, 0x03, 0xe0, 0x03, 0x08, 0x02, /* I/O 0x330-0x3E0, decodes 16-bit, 8-byte alignment, 2 addresses */ + 0x38, /* end dependent functions */ 0x79, 0x00 /* end tag, dummy checksum (filled in by isapnp_add_card) */ + // clang-format on }; +typedef struct cs423x_t { + void *pnp_card; + ad1848_t ad1848; + sb_t *sb; + void *gameport; + void *i2c; + void *eeprom; -typedef struct cs423x_t -{ - void *pnp_card; - ad1848_t ad1848; - sb_t *sb; - void *gameport; - void *i2c, *eeprom; + uint16_t wss_base; + uint16_t opl_base; + uint16_t sb_base; + uint16_t ctrl_base; + uint16_t ram_addr; + uint16_t eeprom_size : 11; + uint16_t pnp_offset; + uint8_t type; + uint8_t ad1848_type; + uint8_t regs[8]; + uint8_t indirect_regs[16]; + uint8_t eeprom_data[2048]; + uint8_t ram_data[65536]; + uint8_t ram_dl : 2; + uint8_t opl_wss : 1; + char *nvr_path; - uint16_t wss_base, opl_base, sb_base, ctrl_base, ram_addr, eeprom_size: 11, pnp_offset; - uint8_t type, ad1848_type, regs[8], indirect_regs[16], - eeprom_data[2048], ram_data[65536], ram_dl: 2, opl_wss: 1; - char *nvr_path; - - uint8_t pnp_enable: 1, key_pos: 5, slam_enable: 1, slam_state: 2, slam_ld, slam_reg; + uint8_t pnp_enable : 1; + uint8_t key_pos : 5; + uint8_t slam_enable : 1; + uint8_t slam_state : 2; + uint8_t slam_ld; + uint8_t slam_reg; isapnp_device_config_t *slam_config; } cs423x_t; - -static void cs423x_slam_enable(cs423x_t *dev, uint8_t enable); -static void cs423x_pnp_enable(cs423x_t *dev, uint8_t update_rom, uint8_t update_hwconfig); -static void cs423x_pnp_config_changed(uint8_t ld, isapnp_device_config_t *config, void *priv); - +static void cs423x_slam_enable(cs423x_t *dev, uint8_t enable); +static void cs423x_pnp_enable(cs423x_t *dev, uint8_t update_rom, uint8_t update_hwconfig); +static void cs423x_pnp_config_changed(uint8_t ld, isapnp_device_config_t *config, void *priv); static void cs423x_nvram(cs423x_t *dev, uint8_t save) { - FILE *f = nvr_fopen(dev->nvr_path, save ? "wb" : "rb"); - if (f) { - if (save) - fwrite(dev->eeprom_data, sizeof(dev->eeprom_data), 1, f); - else - fread(dev->eeprom_data, sizeof(dev->eeprom_data), 1, f); - fclose(f); + FILE *fp = nvr_fopen(dev->nvr_path, save ? "wb" : "rb"); + if (fp) { + if (save) + fwrite(dev->eeprom_data, sizeof(dev->eeprom_data), 1, fp); + else + (void) !fread(dev->eeprom_data, sizeof(dev->eeprom_data), 1, fp); + fclose(fp); } } - static uint8_t cs423x_read(uint16_t addr, void *priv) { cs423x_t *dev = (cs423x_t *) priv; - uint8_t reg = addr & 7; - uint8_t ret = dev->regs[reg]; + uint8_t reg = addr & 7; + uint8_t ret = dev->regs[reg]; switch (reg) { - case 1: /* EEPROM Interface */ - ret &= ~0x04; - if ((dev->regs[1] & 0x04) && i2c_gpio_get_sda(dev->i2c)) - ret |= 0x04; - break; + case 1: /* EEPROM Interface */ + ret &= ~0x04; + if ((dev->regs[1] & 0x04) && i2c_gpio_get_sda(dev->i2c)) + ret |= 0x04; + break; - case 4: /* Control Indirect Data Register */ - ret = dev->indirect_regs[dev->regs[3]]; - break; + case 4: /* Control Indirect Data Register */ + ret = dev->indirect_regs[dev->regs[3]]; + break; - case 5: /* Control/RAM Access */ - /* Reading RAM is undocumented; the Windows drivers do so. */ - if (dev->ram_dl == 3) - ret = dev->ram_data[dev->ram_addr++]; - break; + case 5: /* Control/RAM Access */ + /* Reading RAM is undocumented; the Windows drivers do so. */ + if (dev->ram_dl == 3) + ret = dev->ram_data[dev->ram_addr++]; + break; - case 7: /* Global Status */ - /* Context switching: take active context and interrupt flag, then clear interrupt flag. */ - ret &= 0xc0; - dev->regs[7] &= 0x80; + case 7: /* Global Status */ + /* Context switching: take active context and interrupt flag, then clear interrupt flag. */ + ret &= 0xc0; + dev->regs[7] &= 0x80; - if (dev->sb->mpu->state.irq_pending) /* MPU interrupt */ - ret |= 0x08; - if (dev->ad1848.status & 0x01) /* WSS interrupt */ - ret |= 0x10; - if (dev->sb->dsp.sb_irq8 || dev->sb->dsp.sb_irq16 || dev->sb->dsp.sb_irq401) /* SBPro interrupt */ - ret |= 0x20; + if (dev->sb->mpu->state.irq_pending) /* MPU interrupt */ + ret |= 0x08; + if (dev->ad1848.status & 0x01) /* WSS interrupt */ + ret |= 0x10; + if (dev->sb->dsp.sb_irq8 || dev->sb->dsp.sb_irq16 || dev->sb->dsp.sb_irq401) /* SBPro interrupt */ + ret |= 0x20; - break; + break; + + default: + break; } return ret; } - static void cs423x_write(uint16_t addr, uint8_t val, void *priv) { cs423x_t *dev = (cs423x_t *) priv; - uint8_t reg = addr & 0x07; + uint8_t reg = addr & 0x07; switch (reg) { - case 1: /* EEPROM Interface */ - if (val & 0x04) - i2c_gpio_set(dev->i2c, val & 0x01, val & 0x02); - break; + case 1: /* EEPROM Interface */ + if (val & 0x04) + i2c_gpio_set(dev->i2c, val & 0x01, val & 0x02); + break; - case 3: /* Control Indirect Access Register */ - val &= 0x0f; - break; + case 3: /* Control Indirect Access Register */ + val &= 0x0f; + break; - case 4: /* Control Indirect Data Register */ - switch (dev->regs[3] & 0x0f) { - case 0: /* WSS Master Control */ - if (val & 0x80) - ad1848_init(&dev->ad1848, dev->ad1848_type); - val = 0x00; - break; + case 4: /* Control Indirect Data Register */ + switch (dev->regs[3] & 0x0f) { + case 0: /* WSS Master Control */ + if (val & 0x80) + ad1848_init(&dev->ad1848, dev->ad1848_type); + val = 0x00; + break; - case 1: /* Version / Chip ID */ - case 7: /* Reserved */ - case 9 ... 15: /* unspecified */ - return; + case 1: /* Version / Chip ID */ + case 7: /* Reserved */ + case 9 ... 15: /* unspecified */ + return; - case 2: /* 3D Space and {Center|Volume} */ - case 6: /* Upper Channel Status */ - if (dev->type < CRYSTAL_CS4237B) - return; - break; + case 2: /* 3D Space and {Center|Volume} */ + case 6: /* Upper Channel Status */ + if (dev->type < CRYSTAL_CS4237B) + return; + break; - case 3: /* 3D Enable */ - if (dev->type < CRYSTAL_CS4237B) - return; - val &= 0xe0; - break; + case 3: /* 3D Enable */ + if (dev->type < CRYSTAL_CS4237B) + return; + val &= 0xe0; + break; - case 4: /* Consumer Serial Port Enable */ - if (dev->type < CRYSTAL_CS4237B) - return; - val &= 0xf0; - break; + case 4: /* Consumer Serial Port Enable */ + if (dev->type < CRYSTAL_CS4237B) + return; + val &= 0xf0; + break; - case 5: /* Lower Channel Status */ - if (dev->type < CRYSTAL_CS4237B) - return; - val &= 0xfe; - break; + case 5: /* Lower Channel Status */ + if (dev->type < CRYSTAL_CS4237B) + return; + val &= 0xfe; + break; - case 8: /* CS9236 Wavetable Control */ - val &= 0x0f; - cs423x_pnp_enable(dev, 0, 0); + case 8: /* CS9236 Wavetable Control */ + val &= 0x0f; + cs423x_pnp_enable(dev, 0, 0); - /* Update WTEN state on the WSS codec. */ - dev->ad1848.wten = !!(val & 0x08); - ad1848_updatevolmask(&dev->ad1848); - break; - } - dev->indirect_regs[dev->regs[3]] = val; - break; + /* Update WTEN state on the WSS codec. */ + dev->ad1848.wten = !!(val & 0x08); + ad1848_updatevolmask(&dev->ad1848); + break; - case 5: /* Control/RAM Access */ - switch (dev->ram_dl) { - case 0: /* commands */ - switch (val) { - case 0x55: /* Disable PnP Key */ - dev->pnp_enable = 0; - /* fall-through */ + default: + break; + } + dev->indirect_regs[dev->regs[3]] = val; + break; - case 0x5a: /* Update Hardware Configuration Data */ - cs423x_pnp_enable(dev, 0, 1); - break; + case 5: /* Control/RAM Access */ + switch (dev->ram_dl) { + case 0: /* commands */ + switch (val) { + case 0x55: /* Disable PnP Key */ + dev->pnp_enable = 0; + fallthrough; - case 0x56: /* Disable Crystal Key */ - cs423x_slam_enable(dev, 0); - break; + case 0x5a: /* Update Hardware Configuration Data */ + cs423x_pnp_enable(dev, 0, 1); + break; - case 0x57: /* Jump to ROM */ - break; + case 0x56: /* Disable Crystal Key */ + cs423x_slam_enable(dev, 0); + break; - case 0xaa: /* Download RAM */ - dev->ram_dl = 1; - break; - } - break; + case 0x57: /* Jump to ROM */ + break; - case 1: /* low address byte */ - dev->ram_addr = val; - dev->ram_dl++; - break; + case 0xaa: /* Download RAM */ + dev->ram_dl = 1; + break; - case 2: /* high address byte */ - dev->ram_addr |= (val << 8); - dev->ram_dl++; - break; + default: + break; + } + break; - case 3: /* data */ - dev->ram_data[dev->ram_addr++] = val; - break; - } - break; + case 1: /* low address byte */ + dev->ram_addr = val; + dev->ram_dl++; + break; - case 6: /* RAM Access End */ - if (!val) { - dev->ram_dl = 0; + case 2: /* high address byte */ + dev->ram_addr |= (val << 8); + dev->ram_dl++; + break; - /* Update PnP state and resource data. */ - cs423x_pnp_enable(dev, 1, 0); - } - break; + case 3: /* data */ + dev->ram_data[dev->ram_addr++] = val; + break; - case 7: /* Global Status */ - return; + default: + break; + } + break; + + case 6: /* RAM Access End */ + /* TriGem Delhi-III BIOS writes undocumented value 0x40 instead of 0x00. */ + if ((val == 0x00) || (val == 0x40)) { + dev->ram_dl = 0; + + /* Update PnP state and resource data. */ + cs423x_pnp_enable(dev, 1, 0); + } + break; + + case 7: /* Global Status */ + return; + + default: + break; } dev->regs[reg] = val; } - static void -cs423x_slam_write(uint16_t addr, uint8_t val, void *priv) +cs423x_slam_write(UNUSED(uint16_t addr), uint8_t val, void *priv) { cs423x_t *dev = (cs423x_t *) priv; - uint8_t idx; + uint8_t idx; switch (dev->slam_state) { - case CRYSTAL_SLAM_NONE: - /* Not in SLAM: read and compare Crystal key. */ - if (val == slam_init_key[dev->key_pos]) { - dev->key_pos++; - /* Was the key successfully written? */ - if (!dev->key_pos) { - /* Discard any pending logical device configuration, just to be safe. */ - if (dev->slam_config) { - free(dev->slam_config); - dev->slam_config = NULL; - } + case CRYSTAL_SLAM_NONE: + /* Not in SLAM: read and compare Crystal key. */ + if (val == slam_init_key[dev->key_pos]) { + dev->key_pos++; + /* Was the key successfully written? */ + if (!dev->key_pos) { + /* Discard any pending logical device configuration, just to be safe. */ + if (dev->slam_config) { + free(dev->slam_config); + dev->slam_config = NULL; + } - /* Enter SLAM. */ - dev->slam_state = CRYSTAL_SLAM_INDEX; - } - } else { - dev->key_pos = 0; - } - break; + /* Enter SLAM. */ + dev->slam_state = CRYSTAL_SLAM_INDEX; + } + } else { + dev->key_pos = 0; + } + break; - case CRYSTAL_SLAM_INDEX: - /* Write register index. */ - dev->slam_reg = val; - dev->slam_state = CRYSTAL_SLAM_BYTE1; - break; + case CRYSTAL_SLAM_INDEX: + /* Intercept the Activate Audio Device command. */ + if (val == 0x79) { + /* Apply the last logical device's configuration. */ + if (dev->slam_config) { + cs423x_pnp_config_changed(dev->slam_ld, dev->slam_config, dev); + free(dev->slam_config); + dev->slam_config = NULL; + } - case CRYSTAL_SLAM_BYTE1: - case CRYSTAL_SLAM_BYTE2: - /* Write register value: two bytes for I/O ports, single byte otherwise. */ - switch (dev->slam_reg) { - case 0x06: /* Card Select Number */ - isapnp_set_csn(dev->pnp_card, val); - break; + /* Exit out of SLAM. */ + dev->slam_state = CRYSTAL_SLAM_NONE; + break; + } - case 0x15: /* Logical Device ID */ - /* Apply the previous logical device's configuration, and reuse its config structure. */ - if (dev->slam_config) - cs423x_pnp_config_changed(dev->slam_ld, dev->slam_config, dev); - else - dev->slam_config = (isapnp_device_config_t *) malloc(sizeof(isapnp_device_config_t)); + /* Write register index. */ + dev->slam_reg = val; + dev->slam_state = CRYSTAL_SLAM_BYTE1; + break; - /* Start new logical device. */ - memset(dev->slam_config, 0, sizeof(isapnp_device_config_t)); - dev->slam_ld = val; - break; + case CRYSTAL_SLAM_BYTE1: + case CRYSTAL_SLAM_BYTE2: + /* Write register value: two bytes for I/O ports, single byte otherwise. */ + switch (dev->slam_reg) { + case 0x06: /* Card Select Number */ + isapnp_set_csn(dev->pnp_card, val); + break; - case 0x47: /* I/O Port Base Address 0 */ - case 0x48: /* I/O Port Base Address 1 */ - case 0x42: /* I/O Port Base Address 2 */ - idx = (dev->slam_reg == 0x42) ? 2 : (dev->slam_reg - 0x47); - if (dev->slam_state == CRYSTAL_SLAM_BYTE1) { - /* Set high byte, or ignore it if no logical device is selected. */ - if (dev->slam_config) - dev->slam_config->io[idx].base = val << 8; + case 0x15: /* Logical Device ID */ + /* Apply the previous logical device's configuration, and reuse its config structure. */ + if (dev->slam_config) + cs423x_pnp_config_changed(dev->slam_ld, dev->slam_config, dev); + else + dev->slam_config = (isapnp_device_config_t *) malloc(sizeof(isapnp_device_config_t)); - /* Prepare for the second (low byte) write. */ - dev->slam_state = CRYSTAL_SLAM_BYTE2; - return; - } else if (dev->slam_config) { - /* Set low byte, or ignore it if no logical device is selected. */ - dev->slam_config->io[idx].base |= val; - } - break; + /* Start new logical device. */ + memset(dev->slam_config, 0, sizeof(isapnp_device_config_t)); + dev->slam_ld = val; + break; - case 0x22: /* Interrupt Select 0 */ - case 0x27: /* Interrupt Select 1 */ - /* Stop if no logical device is selected. */ - if (!dev->slam_config) - break; + case 0x47: /* I/O Port Base Address 0 */ + case 0x48: /* I/O Port Base Address 1 */ + case 0x42: /* I/O Port Base Address 2 */ + idx = (dev->slam_reg == 0x42) ? 2 : (dev->slam_reg - 0x47); + if (dev->slam_state == CRYSTAL_SLAM_BYTE1) { + /* Set high byte, or ignore it if no logical device is selected. */ + if (dev->slam_config) + dev->slam_config->io[idx].base = val << 8; - /* Set IRQ value. */ - idx = (dev->slam_reg == 0x22) ? 0 : 1; - dev->slam_config->irq[idx].irq = val & 15; - break; + /* Prepare for the second (low byte) write. */ + dev->slam_state = CRYSTAL_SLAM_BYTE2; + return; + } else if (dev->slam_config) { + /* Set low byte, or ignore it if no logical device is selected. */ + dev->slam_config->io[idx].base |= val; + } + break; - case 0x2a: /* DMA Select 0 */ - case 0x25: /* DMA Select 1 */ - /* Stop if no logical device is selected. */ - if (!dev->slam_config) - break; + case 0x22: /* Interrupt Select 0 */ + case 0x27: /* Interrupt Select 1 */ + /* Stop if no logical device is selected. */ + if (!dev->slam_config) + break; - /* Set DMA value. */ - idx = (dev->slam_reg == 0x2a) ? 0 : 1; - dev->slam_config->dma[idx].dma = val & 7; - break; + /* Set IRQ value. */ + idx = (dev->slam_reg == 0x22) ? 0 : 1; + dev->slam_config->irq[idx].irq = val & 15; + break; - case 0x33: /* Activate Device */ - /* Stop if no logical device is selected. */ - if (!dev->slam_config) - break; + case 0x2a: /* DMA Select 0 */ + case 0x25: /* DMA Select 1 */ + /* Stop if no logical device is selected. */ + if (!dev->slam_config) + break; - /* Activate or deactivate the device. */ - dev->slam_config->activate = val & 0x01; - break; + /* Set DMA value. */ + idx = (dev->slam_reg == 0x2a) ? 0 : 1; + dev->slam_config->dma[idx].dma = val & 7; + break; - case 0x79: /* activate chip */ - /* Apply the last logical device's configuration. */ - if (dev->slam_config) { - cs423x_pnp_config_changed(dev->slam_ld, dev->slam_config, dev); - free(dev->slam_config); - dev->slam_config = NULL; - } + case 0x33: /* Activate Device */ + /* Stop if no logical device is selected. */ + if (!dev->slam_config) + break; - /* Exit out of SLAM. */ - dev->slam_state = CRYSTAL_SLAM_NONE; - break; - } + /* Activate or deactivate the device. */ + dev->slam_config->activate = val & 0x01; + break; - /* Prepare for the next register, unless a two-byte read returns above. */ - dev->slam_state = CRYSTAL_SLAM_INDEX; - break; + default: + break; + } + + /* Prepare for the next register, unless a two-byte read returns above. */ + dev->slam_state = CRYSTAL_SLAM_INDEX; + break; + + default: + break; } } - static void cs423x_slam_enable(cs423x_t *dev, uint8_t enable) { /* Disable SLAM. */ if (dev->slam_enable) { - dev->slam_state = CRYSTAL_SLAM_NONE; - dev->slam_enable = 0; - io_removehandler(0x279, 1, NULL, NULL, NULL, cs423x_slam_write, NULL, NULL, dev); + dev->slam_state = CRYSTAL_SLAM_NONE; + dev->slam_enable = 0; + io_removehandler(0x279, 1, NULL, NULL, NULL, cs423x_slam_write, NULL, NULL, dev); } /* Enable SLAM if the CKD bit is not set. */ if (enable && !(dev->ram_data[0x4002] & 0x10)) { - dev->slam_enable = 1; - io_sethandler(0x279, 1, NULL, NULL, NULL, cs423x_slam_write, NULL, NULL, dev); + dev->slam_enable = 1; + io_sethandler(0x279, 1, NULL, NULL, NULL, cs423x_slam_write, NULL, NULL, dev); } } - static void -cs423x_ctxswitch_write(uint16_t addr, uint8_t val, void *priv) +cs423x_ctxswitch_write(uint16_t addr, UNUSED(uint8_t val), void *priv) { - cs423x_t *dev = (cs423x_t *) priv; - uint8_t ctx = (dev->regs[7] & 0x80), - enable_opl = (dev->ad1848.xregs[4] & 0x10) && !(dev->indirect_regs[2] & 0x85); + cs423x_t *dev = (cs423x_t *) priv; + uint8_t ctx = (dev->regs[7] & 0x80); + uint8_t enable_opl = (dev->ad1848.xregs[4] & 0x10) && !(dev->indirect_regs[2] & 0x85); /* Check if a context switch (WSS=1 <-> SBPro=0) occurred through the address being written. */ if ((dev->regs[7] & 0x80) ? ((addr & 0xfff0) == dev->sb_base) : ((addr & 0xfffc) == dev->wss_base)) { - /* Flip context bit. */ - dev->regs[7] ^= 0x80; - ctx ^= 0x80; + /* Flip context bit. */ + dev->regs[7] ^= 0x80; + ctx ^= 0x80; - /* Update CD audio filter. - FIXME: not thread-safe: filter function TOCTTOU in sound_cd_thread! */ - sound_set_cd_audio_filter(NULL, NULL); - if (ctx) /* WSS */ - sound_set_cd_audio_filter(ad1848_filter_cd_audio, &dev->ad1848); - else /* SBPro */ - sound_set_cd_audio_filter(sbpro_filter_cd_audio, dev->sb); + /* Update CD audio filter. + FIXME: not thread-safe: filter function TOCTTOU in sound_cd_thread! */ + sound_set_cd_audio_filter(NULL, NULL); + if (ctx) /* WSS */ + sound_set_cd_audio_filter(ad1848_filter_cd_audio, &dev->ad1848); + else /* SBPro */ + sound_set_cd_audio_filter(sbpro_filter_cd_audio, dev->sb); - /* Fire a context switch interrupt if enabled. */ - if ((dev->regs[0] & 0x20) && (dev->ad1848.irq > 0)) { - dev->regs[7] |= 0x40; /* set interrupt flag */ - picint(1 << dev->ad1848.irq); /* control device shares IRQ with WSS and SBPro */ - } + /* Fire a context switch interrupt if enabled. */ + if ((dev->regs[0] & 0x20) && (dev->ad1848.irq > 0)) { + dev->regs[7] |= 0x40; /* set interrupt flag */ + picint(1 << dev->ad1848.irq); /* control device shares IRQ with WSS and SBPro */ + } } /* Update OPL ownership and state regardless of context switch, to trap writes to other registers which may disable the OPL. */ dev->sb->opl_enabled = !ctx && enable_opl; - dev->opl_wss = ctx && enable_opl; + dev->opl_wss = ctx && enable_opl; } - static void cs423x_get_buffer(int32_t *buffer, int len, void *priv) { - cs423x_t *dev = (cs423x_t *) priv; - int c, opl_wss = dev->opl_wss; + cs423x_t *dev = (cs423x_t *) priv; + int opl_wss = dev->opl_wss; + const int32_t *opl_buf = NULL; /* Output audio from the WSS codec, and also the OPL if we're in charge of it. */ ad1848_update(&dev->ad1848); if (opl_wss) - opl3_update(&dev->sb->opl); + opl_buf = dev->sb->opl.update(dev->sb->opl.priv); /* Don't output anything if the analog section is powered down. */ if (!(dev->indirect_regs[2] & 0xa4)) { - for (c = 0; c < len * 2; c += 2) { - if (opl_wss) { - buffer[c] += (dev->sb->opl.buffer[c] * dev->ad1848.fm_vol_l) >> 16; - buffer[c + 1] += (dev->sb->opl.buffer[c + 1] * dev->ad1848.fm_vol_r) >> 16; - } + for (int c = 0; c < len * 2; c += 2) { + if (opl_wss) { + buffer[c] += (opl_buf[c] * dev->ad1848.fm_vol_l) >> 16; + buffer[c + 1] += (opl_buf[c + 1] * dev->ad1848.fm_vol_r) >> 16; + } - buffer[c] += dev->ad1848.buffer[c] / 2; - buffer[c + 1] += dev->ad1848.buffer[c + 1] / 2; - } + buffer[c] += dev->ad1848.buffer[c] / 2; + buffer[c + 1] += dev->ad1848.buffer[c + 1] / 2; + } } dev->ad1848.pos = 0; if (opl_wss) - dev->sb->opl.pos = 0; + dev->sb->opl.reset_buffer(dev->sb->opl.priv); } - static void cs423x_pnp_enable(cs423x_t *dev, uint8_t update_rom, uint8_t update_hwconfig) { if (dev->pnp_card) { - /* Update PnP resource data if requested. */ - if (update_rom) - isapnp_update_card_rom(dev->pnp_card, &dev->ram_data[dev->pnp_offset], 384); + /* Update PnP resource data if requested. */ + if (update_rom) + isapnp_update_card_rom(dev->pnp_card, &dev->ram_data[dev->pnp_offset], 384); - /* Hide PnP card if the PKD bit is set, or if PnP was disabled by command 0x55. */ - if ((dev->ram_data[0x4002] & 0x20) || !dev->pnp_enable) - isapnp_enable_card(dev->pnp_card, ISAPNP_CARD_DISABLE); - else - isapnp_enable_card(dev->pnp_card, ISAPNP_CARD_ENABLE); + /* Disable PnP key if the PKD bit is set, or if it was disabled by command 0x55. */ + /* But wait! The TriGem Delhi-III BIOS sends command 0x55, and its behavior doesn't + line up with real hardware (still listed in the POST summary and seen by software). + Disable the PnP key disabling mechanism until someone figures something out. */ +#if 0 + isapnp_enable_card(dev->pnp_card, ((dev->ram_data[0x4002] & 0x20) || !dev->pnp_enable) ? ISAPNP_CARD_NO_KEY : ISAPNP_CARD_ENABLE); +#endif + if ((dev->ram_data[0x4002] & 0x20) || !dev->pnp_enable) + pclog("CS423x: Attempted to disable PnP key\n"); } /* Update some register bits based on the config data in RAM if requested. */ if (update_hwconfig) { - /* Update WTEN. */ - if (dev->ram_data[0x4003] & 0x08) { - dev->indirect_regs[8] |= 0x08; - dev->ad1848.wten = 1; - } else { - dev->indirect_regs[8] &= ~0x08; - dev->ad1848.wten = 0; - } + /* Update WTEN. */ + if (dev->ram_data[0x4003] & 0x08) { + dev->indirect_regs[8] |= 0x08; + dev->ad1848.wten = 1; + } else { + dev->indirect_regs[8] &= ~0x08; + dev->ad1848.wten = 0; + } - /* Update SPS. */ - if (dev->ram_data[0x4003] & 0x04) - dev->indirect_regs[8] |= 0x04; - else - dev->indirect_regs[8] &= ~0x04; + /* Update SPS. */ + if (dev->type != CRYSTAL_CS4235) { + if (dev->ram_data[0x4003] & 0x04) + dev->indirect_regs[8] |= 0x04; + else + dev->indirect_regs[8] &= ~0x04; + } - /* Update IFM. */ - if (dev->ram_data[0x4003] & 0x80) - dev->ad1848.xregs[4] |= 0x10; - else - dev->ad1848.xregs[4] &= ~0x10; + /* Update IFM. */ + if (dev->ram_data[0x4003] & 0x80) + dev->ad1848.xregs[4] |= 0x10; + else + dev->ad1848.xregs[4] &= ~0x10; - /* Inform WSS codec of the changes. */ - ad1848_updatevolmask(&dev->ad1848); + /* Inform WSS codec of the changes. */ + ad1848_updatevolmask(&dev->ad1848); } } - static void cs423x_pnp_config_changed(uint8_t ld, isapnp_device_config_t *config, void *priv) { cs423x_t *dev = (cs423x_t *) priv; switch (ld) { - case 0: /* WSS, OPL3 and SBPro */ - if (dev->wss_base) { - io_removehandler(dev->wss_base, 4, ad1848_read, NULL, NULL, ad1848_write, NULL, NULL, &dev->ad1848); - io_removehandler(dev->wss_base, 4, NULL, NULL, NULL, cs423x_ctxswitch_write, NULL, NULL, dev); - dev->wss_base = 0; - } + case 0: /* WSS, OPL3 and SBPro */ + if (dev->wss_base) { + io_removehandler(dev->wss_base, 4, ad1848_read, NULL, NULL, ad1848_write, NULL, NULL, &dev->ad1848); + io_removehandler(dev->wss_base, 4, NULL, NULL, NULL, cs423x_ctxswitch_write, NULL, NULL, dev); + dev->wss_base = 0; + } - if (dev->opl_base) { - io_removehandler(dev->opl_base, 4, opl3_read, NULL, NULL, opl3_write, NULL, NULL, &dev->sb->opl); - dev->opl_base = 0; - } + if (dev->opl_base) { + io_removehandler(dev->opl_base, 4, dev->sb->opl.read, NULL, NULL, dev->sb->opl.write, NULL, NULL, dev->sb->opl.priv); + dev->opl_base = 0; + } - if (dev->sb_base) { - sb_dsp_setaddr(&dev->sb->dsp, 0); - io_removehandler(dev->sb_base, 4, opl3_read, NULL, NULL, opl3_write, NULL, NULL, &dev->sb->opl); - io_removehandler(dev->sb_base + 8, 2, opl3_read, NULL, NULL, opl3_write, NULL, NULL, &dev->sb->opl); - io_removehandler(dev->sb_base + 4, 2, sb_ct1345_mixer_read, NULL, NULL, sb_ct1345_mixer_write, NULL, NULL, dev->sb); - io_removehandler(dev->sb_base, 16, NULL, NULL, NULL, cs423x_ctxswitch_write, NULL, NULL, dev); - dev->sb_base = 0; - } + if (dev->sb_base) { + sb_dsp_setaddr(&dev->sb->dsp, 0); + io_removehandler(dev->sb_base, 4, dev->sb->opl.read, NULL, NULL, dev->sb->opl.write, NULL, NULL, dev->sb->opl.priv); + io_removehandler(dev->sb_base + 8, 2, dev->sb->opl.read, NULL, NULL, dev->sb->opl.write, NULL, NULL, dev->sb->opl.priv); + io_removehandler(dev->sb_base + 4, 2, sb_ct1345_mixer_read, NULL, NULL, sb_ct1345_mixer_write, NULL, NULL, dev->sb); + io_removehandler(dev->sb_base, 16, NULL, NULL, NULL, cs423x_ctxswitch_write, NULL, NULL, dev); + dev->sb_base = 0; + } - ad1848_setirq(&dev->ad1848, 0); - sb_dsp_setirq(&dev->sb->dsp, 0); + ad1848_setirq(&dev->ad1848, 0); + sb_dsp_setirq(&dev->sb->dsp, 0); - ad1848_setdma(&dev->ad1848, 0); - sb_dsp_setdma8(&dev->sb->dsp, 0); + ad1848_setdma(&dev->ad1848, 0); + sb_dsp_setdma8(&dev->sb->dsp, 0); - if (config->activate) { - if (config->io[0].base != ISAPNP_IO_DISABLED) { - dev->wss_base = config->io[0].base; - io_sethandler(dev->wss_base, 4, ad1848_read, NULL, NULL, ad1848_write, NULL, NULL, &dev->ad1848); - io_sethandler(dev->wss_base, 4, NULL, NULL, NULL, cs423x_ctxswitch_write, NULL, NULL, dev); - } + if (config->activate) { + if (config->io[0].base != ISAPNP_IO_DISABLED) { + dev->wss_base = config->io[0].base; + io_sethandler(dev->wss_base, 4, ad1848_read, NULL, NULL, ad1848_write, NULL, NULL, &dev->ad1848); + io_sethandler(dev->wss_base, 4, NULL, NULL, NULL, cs423x_ctxswitch_write, NULL, NULL, dev); + } - if (config->io[1].base != ISAPNP_IO_DISABLED) { - dev->opl_base = config->io[1].base; - io_sethandler(dev->opl_base, 4, opl3_read, NULL, NULL, opl3_write, NULL, NULL, &dev->sb->opl); - } + if (config->io[1].base != ISAPNP_IO_DISABLED) { + dev->opl_base = config->io[1].base; + io_sethandler(dev->opl_base, 4, dev->sb->opl.read, NULL, NULL, dev->sb->opl.write, NULL, NULL, dev->sb->opl.priv); + } - if (config->io[2].base != ISAPNP_IO_DISABLED) { - dev->sb_base = config->io[2].base; - sb_dsp_setaddr(&dev->sb->dsp, dev->sb_base); - io_sethandler(dev->sb_base, 4, opl3_read, NULL, NULL, opl3_write, NULL, NULL, &dev->sb->opl); - io_sethandler(dev->sb_base + 8, 2, opl3_read, NULL, NULL, opl3_write, NULL, NULL, &dev->sb->opl); - io_sethandler(dev->sb_base + 4, 2, sb_ct1345_mixer_read, NULL, NULL, sb_ct1345_mixer_write, NULL, NULL, dev->sb); - io_sethandler(dev->sb_base, 16, NULL, NULL, NULL, cs423x_ctxswitch_write, NULL, NULL, dev); - } + if (config->io[2].base != ISAPNP_IO_DISABLED) { + dev->sb_base = config->io[2].base; + sb_dsp_setaddr(&dev->sb->dsp, dev->sb_base); + io_sethandler(dev->sb_base, 4, dev->sb->opl.read, NULL, NULL, dev->sb->opl.write, NULL, NULL, dev->sb->opl.priv); + io_sethandler(dev->sb_base + 8, 2, dev->sb->opl.read, NULL, NULL, dev->sb->opl.write, NULL, NULL, dev->sb->opl.priv); + io_sethandler(dev->sb_base + 4, 2, sb_ct1345_mixer_read, NULL, NULL, sb_ct1345_mixer_write, NULL, NULL, dev->sb); + io_sethandler(dev->sb_base, 16, NULL, NULL, NULL, cs423x_ctxswitch_write, NULL, NULL, dev); + } - if (config->irq[0].irq != ISAPNP_IRQ_DISABLED) { - ad1848_setirq(&dev->ad1848, config->irq[0].irq); - sb_dsp_setirq(&dev->sb->dsp, config->irq[0].irq); - } + if (config->irq[0].irq != ISAPNP_IRQ_DISABLED) { + ad1848_setirq(&dev->ad1848, config->irq[0].irq); + sb_dsp_setirq(&dev->sb->dsp, config->irq[0].irq); + } - if (config->dma[0].dma != ISAPNP_DMA_DISABLED) { - ad1848_setdma(&dev->ad1848, config->dma[0].dma); - sb_dsp_setdma8(&dev->sb->dsp, config->dma[0].dma); - } - } - break; + if (config->dma[0].dma != ISAPNP_DMA_DISABLED) { + ad1848_setdma(&dev->ad1848, config->dma[0].dma); + sb_dsp_setdma8(&dev->sb->dsp, config->dma[0].dma); + } + } + break; - case 1: /* Game Port */ - if (dev->gameport) - gameport_remap(dev->gameport, (config->activate && (config->io[0].base != ISAPNP_IO_DISABLED)) ? config->io[0].base : 0); - break; + case 1: /* Game Port */ + if (dev->gameport) + gameport_remap(dev->gameport, (config->activate && (config->io[0].base != ISAPNP_IO_DISABLED)) ? config->io[0].base : 0); + break; - case 2: /* Control Registers */ - if (dev->ctrl_base) { - io_removehandler(dev->ctrl_base, 8, cs423x_read, NULL, NULL, cs423x_write, NULL, NULL, dev); - dev->ctrl_base = 0; - } + case 2: /* Control Registers */ + if (dev->ctrl_base) { + io_removehandler(dev->ctrl_base, 8, cs423x_read, NULL, NULL, cs423x_write, NULL, NULL, dev); + dev->ctrl_base = 0; + } - if (config->activate && (config->io[0].base != ISAPNP_IO_DISABLED)) { - dev->ctrl_base = config->io[0].base; - io_sethandler(dev->ctrl_base, 8, cs423x_read, NULL, NULL, cs423x_write, NULL, NULL, dev); - } + if (config->activate && (config->io[0].base != ISAPNP_IO_DISABLED)) { + dev->ctrl_base = config->io[0].base; + io_sethandler(dev->ctrl_base, 8, cs423x_read, NULL, NULL, cs423x_write, NULL, NULL, dev); + } - break; + break; - case 3: /* MPU-401 */ - mpu401_change_addr(dev->sb->mpu, 0); - mpu401_setirq(dev->sb->mpu, 0); + case 3: /* MPU-401 */ + mpu401_change_addr(dev->sb->mpu, 0); + mpu401_setirq(dev->sb->mpu, 0); - if (config->activate) { - if (config->io[0].base != ISAPNP_IO_DISABLED) - mpu401_change_addr(dev->sb->mpu, config->io[0].base); + if (config->activate) { + if (config->io[0].base != ISAPNP_IO_DISABLED) + mpu401_change_addr(dev->sb->mpu, config->io[0].base); - if (config->irq[0].irq != ISAPNP_IRQ_DISABLED) - mpu401_setirq(dev->sb->mpu, config->irq[0].irq); - } + if (config->irq[0].irq != ISAPNP_IRQ_DISABLED) + mpu401_setirq(dev->sb->mpu, config->irq[0].irq); + } - break; + break; + + default: + break; } } - static void cs423x_reset(void *priv) { @@ -687,11 +732,11 @@ cs423x_reset(void *priv) memset(dev->ram_data, 0, sizeof(dev->ram_data)); if (dev->eeprom) { - /* Load EEPROM data to RAM. */ - memcpy(&dev->ram_data[0x4000], &dev->eeprom_data[4], MIN(384, ((dev->eeprom_data[2] << 8) | dev->eeprom_data[3]) - 4)); + /* Load EEPROM data to RAM. */ + memcpy(&dev->ram_data[0x4000], &dev->eeprom_data[4], MIN(384, ((dev->eeprom_data[2] << 8) | dev->eeprom_data[3]) - 4)); - /* Save EEPROM contents to file. */ - cs423x_nvram(dev, 1); + /* Save EEPROM contents to file. */ + cs423x_nvram(dev, 1); } /* Reset registers. */ @@ -700,7 +745,7 @@ cs423x_reset(void *priv) memset(dev->indirect_regs, 0, sizeof(dev->indirect_regs)); dev->indirect_regs[1] = dev->type; if (dev->type == CRYSTAL_CS4238B) - dev->indirect_regs[2] = 0x20; + dev->indirect_regs[2] = 0x20; /* Reset WSS codec. */ ad1848_init(&dev->ad1848, dev->ad1848_type); @@ -708,14 +753,13 @@ cs423x_reset(void *priv) /* Reset PnP resource data, state and logical devices. */ dev->pnp_enable = 1; cs423x_pnp_enable(dev, 1, 1); - if (dev->pnp_card) - isapnp_reset_card(dev->pnp_card); + if (dev->pnp_card && dev->sb) + isapnp_reset_card(dev->pnp_card); /* Reset SLAM. */ cs423x_slam_enable(dev, 1); } - static void * cs423x_init(const device_t *info) { @@ -723,50 +767,66 @@ cs423x_init(const device_t *info) memset(dev, 0, sizeof(cs423x_t)); /* Initialize model-specific data. */ - dev->type = info->local; + dev->type = info->local & 0xff; switch (dev->type) { - case CRYSTAL_CS4236B: - case CRYSTAL_CS4237B: - case CRYSTAL_CS4238B: - /* Same WSS codec and EEPROM structure. */ - dev->ad1848_type = AD1848_TYPE_CS4236; - dev->pnp_offset = 0x4013; + case CRYSTAL_CS4235: + case CRYSTAL_CS4236B: + case CRYSTAL_CS4237B: + case CRYSTAL_CS4238B: + /* Same WSS codec and EEPROM structure. */ + dev->ad1848_type = (dev->type == CRYSTAL_CS4235) ? AD1848_TYPE_CS4235 : AD1848_TYPE_CS4236; + dev->pnp_offset = 0x4013; - /* Different Chip Version and ID registers, which shouldn't be reset by ad1848_init */ - dev->ad1848.xregs[25] = dev->type; + /* Different Chip Version and ID registers, which shouldn't be reset by ad1848_init */ + dev->ad1848.xregs[25] = dev->type; - /* Load EEPROM contents from template. */ - memcpy(dev->eeprom_data, cs4236b_eeprom, sizeof(cs4236b_eeprom)); + if (!(info->local & CRYSTAL_NOEEPROM)) { + /* Load EEPROM contents from template. */ + memcpy(dev->eeprom_data, cs4236b_eeprom, sizeof(cs4236b_eeprom)); - /* Set content size. */ - dev->eeprom_data[2] = sizeof(cs4236b_eeprom) >> 8; - dev->eeprom_data[3] = sizeof(cs4236b_eeprom) & 0xff; + /* Set content size. */ + dev->eeprom_data[2] = sizeof(cs4236b_eeprom) >> 8; + dev->eeprom_data[3] = sizeof(cs4236b_eeprom) & 0xff; - /* Set PnP card ID and EEPROM file name. */ - switch (dev->type) { - case CRYSTAL_CS4236B: - dev->nvr_path = "cs4236b.nvr"; - break; + /* Set PnP card ID and EEPROM file name. */ + switch (dev->type) { + case CRYSTAL_CS4235: + dev->eeprom_data[8] = 0x05; + dev->eeprom_data[16] = 0x08; + dev->eeprom_data[26] = 0x25; + dev->nvr_path = "cs4235.nvr"; + break; - case CRYSTAL_CS4237B: - dev->eeprom_data[26] = 0x37; - dev->nvr_path = "cs4237b.nvr"; - break; + case CRYSTAL_CS4236B: + dev->nvr_path = "cs4236b.nvr"; + break; - case CRYSTAL_CS4238B: - dev->eeprom_data[26] = 0x38; - dev->nvr_path = "cs4238b.nvr"; - break; - } + case CRYSTAL_CS4237B: + dev->eeprom_data[26] = 0x37; + dev->nvr_path = "cs4237b.nvr"; + break; - /* Load EEPROM contents from file if present. */ - cs423x_nvram(dev, 0); + case CRYSTAL_CS4238B: + dev->eeprom_data[26] = 0x38; + dev->nvr_path = "cs4238b.nvr"; + break; - /* Initialize game port. The '7B and '8B game port only responds to 6 I/O ports; the remaining - 2 ports are reserved on those chips, and probably connected to the Digital Assist feature. */ - dev->gameport = gameport_add((dev->type == CRYSTAL_CS4236B) ? &gameport_pnp_device : &gameport_pnp_6io_device); + default: + break; + } - break; + /* Load EEPROM contents from file if present. */ + cs423x_nvram(dev, 0); + } + + /* Initialize game port. The '7B and '8B game port only responds to 6 I/O ports; the remaining + 2 ports are reserved on those chips, and probably connected to the Digital Assist feature. */ + dev->gameport = gameport_add(((dev->type == CRYSTAL_CS4235) || (dev->type == CRYSTAL_CS4236B)) ? &gameport_pnp_device : &gameport_pnp_6io_device); + + break; + + default: + break; } /* Initialize I2C bus for the EEPROM. */ @@ -774,23 +834,27 @@ cs423x_init(const device_t *info) /* Initialize I2C EEPROM if the contents are valid. */ if ((dev->eeprom_data[0] == 0x55) && (dev->eeprom_data[1] == 0xbb)) - dev->eeprom = i2c_eeprom_init(i2c_gpio_get_bus(dev->i2c), 0x50, dev->eeprom_data, sizeof(dev->eeprom_data), 1); + dev->eeprom = i2c_eeprom_init(i2c_gpio_get_bus(dev->i2c), 0x50, dev->eeprom_data, sizeof(dev->eeprom_data), 1); /* Initialize ISAPnP. */ dev->pnp_card = isapnp_add_card(NULL, 0, cs423x_pnp_config_changed, NULL, NULL, NULL, dev); /* Initialize SBPro codec. The WSS codec is initialized later by cs423x_reset */ - dev->sb = device_add(&sb_pro_compat_device); + dev->sb = device_add_inst(&sb_pro_compat_device, 1); sound_set_cd_audio_filter(sbpro_filter_cd_audio, dev->sb); /* CD audio filter for the default context */ /* Initialize RAM, registers and WSS codec. */ cs423x_reset(dev); sound_add_handler(cs423x_get_buffer, dev); + /* Add Control/RAM backdoor handlers for CS4235. */ + dev->ad1848.cram_priv = dev; + dev->ad1848.cram_read = cs423x_read; + dev->ad1848.cram_write = cs423x_write; + return dev; } - static void cs423x_close(void *priv) { @@ -798,8 +862,8 @@ cs423x_close(void *priv) /* Save EEPROM contents to file. */ if (dev->eeprom) { - cs423x_nvram(dev, 1); - i2c_eeprom_close(dev->eeprom); + cs423x_nvram(dev, 1); + i2c_eeprom_close(dev->eeprom); } i2c_gpio_close(dev->i2c); @@ -807,7 +871,6 @@ cs423x_close(void *priv) free(dev); } - static void cs423x_speed_changed(void *priv) { @@ -816,42 +879,72 @@ cs423x_speed_changed(void *priv) ad1848_speed_changed(&dev->ad1848); } - -const device_t cs4236b_device = -{ - "Crystal CS4236B", - "cs4236b", - DEVICE_ISA | DEVICE_AT, - CRYSTAL_CS4236B, - cs423x_init, cs423x_close, cs423x_reset, - { NULL }, - cs423x_speed_changed, - NULL, - NULL +const device_t cs4235_device = { + .name = "Crystal CS4235", + .internal_name = "cs4235", + .flags = DEVICE_ISA | DEVICE_AT, + .local = CRYSTAL_CS4235, + .init = cs423x_init, + .close = cs423x_close, + .reset = cs423x_reset, + { .available = NULL }, + .speed_changed = cs423x_speed_changed, + .force_redraw = NULL, + .config = NULL }; -const device_t cs4237b_device = -{ - "Crystal CS4237B", - "cs4237b", - DEVICE_ISA | DEVICE_AT, - CRYSTAL_CS4237B, - cs423x_init, cs423x_close, cs423x_reset, - { NULL }, - cs423x_speed_changed, - NULL, - NULL +const device_t cs4235_onboard_device = { + .name = "Crystal CS4235 (On-Board)", + .internal_name = "cs4235_onboard", + .flags = DEVICE_ISA | DEVICE_AT, + .local = CRYSTAL_CS4235 | CRYSTAL_NOEEPROM, + .init = cs423x_init, + .close = cs423x_close, + .reset = cs423x_reset, + { .available = NULL }, + .speed_changed = cs423x_speed_changed, + .force_redraw = NULL, + .config = NULL }; -const device_t cs4238b_device = -{ - "Crystal CS4238B", - "cs4238b", - DEVICE_ISA | DEVICE_AT, - CRYSTAL_CS4238B, - cs423x_init, cs423x_close, cs423x_reset, - { NULL }, - cs423x_speed_changed, - NULL, - NULL +const device_t cs4236b_device = { + .name = "Crystal CS4236B", + .internal_name = "cs4236b", + .flags = DEVICE_ISA | DEVICE_AT, + .local = CRYSTAL_CS4236B, + .init = cs423x_init, + .close = cs423x_close, + .reset = cs423x_reset, + { .available = NULL }, + .speed_changed = cs423x_speed_changed, + .force_redraw = NULL, + .config = NULL +}; + +const device_t cs4237b_device = { + .name = "Crystal CS4237B", + .internal_name = "cs4237b", + .flags = DEVICE_ISA | DEVICE_AT, + .local = CRYSTAL_CS4237B, + .init = cs423x_init, + .close = cs423x_close, + .reset = cs423x_reset, + { .available = NULL }, + .speed_changed = cs423x_speed_changed, + .force_redraw = NULL, + .config = NULL +}; + +const device_t cs4238b_device = { + .name = "Crystal CS4238B", + .internal_name = "cs4238b", + .flags = DEVICE_ISA | DEVICE_AT, + .local = CRYSTAL_CS4238B, + .init = cs423x_init, + .close = cs423x_close, + .reset = cs423x_reset, + { .available = NULL }, + .speed_changed = cs423x_speed_changed, + .force_redraw = NULL, + .config = NULL }; diff --git a/src/sound/snd_emu8k.c b/src/sound/snd_emu8k.c index 8f324cfaa..22435c065 100644 --- a/src/sound/snd_emu8k.c +++ b/src/sound/snd_emu8k.c @@ -1,120 +1,129 @@ #include #include -#include #include -#include +#include #include +#include #include #define _USE_MATH_DEFINES #include #define HAVE_STDARG_H + #include <86box/86box.h> #include <86box/device.h> #include <86box/io.h> #include <86box/mem.h> #include <86box/rom.h> -#include <86box/timer.h> #include <86box/sound.h> #include <86box/snd_emu8k.h> - +#include <86box/timer.h> +#include <86box/plat_unused.h> #if !defined FILTER_INITIAL && !defined FILTER_MOOG && !defined FILTER_CONSTANT -//#define FILTER_INITIAL -#define FILTER_MOOG -//#define FILTER_CONSTANT +#if 0 +#define FILTER_INITIAL +#endif +# define FILTER_MOOG +#if 0 +#define FILTER_CONSTANT +#endif #endif #if !defined RESAMPLER_LINEAR && !defined RESAMPLER_CUBIC -//#define RESAMPLER_LINEAR -#define RESAMPLER_CUBIC +#if 0 +#define RESAMPLER_LINEAR +#endif +# define RESAMPLER_CUBIC #endif -//#define EMU8K_DEBUG_REGISTERS +#if 0 +#define EMU8K_DEBUG_REGISTERS +#endif -char *PORT_NAMES[][8] = -{ - /* Data 0 ( 0x620/0x622) */ - { "AWE_CPF", - "AWE_PTRX", - "AWE_CVCF", - "AWE_VTFT", - "Unk-620-4", - "Unk-620-5", - "AWE_PSST", - "AWE_CSL", - }, - /* Data 1 0xA20 */ - { "AWE_CCCA", - 0, - /* - "AWE_HWCF4" - "AWE_HWCF5" - "AWE_HWCF6" - "AWE_HWCF7" - "AWE_SMALR" - "AWE_SMARR" - "AWE_SMALW" - "AWE_SMARW" - "AWE_SMLD" - "AWE_SMRD" - "AWE_WC" - "AWE_HWCF1" - "AWE_HWCF2" - "AWE_HWCF3" - */ - 0,//"AWE_INIT1", - 0,//"AWE_INIT3", - "AWE_ENVVOL", - "AWE_DCYSUSV", - "AWE_ENVVAL", - "AWE_DCYSUS", - }, - /* Data 2 0xA22 */ - { "AWE_CCCA", - 0, - 0,//"AWE_INIT2", - 0,//"AWE_INIT4", - "AWE_ATKHLDV", - "AWE_LFO1VAL", - "AWE_ATKHLD", - "AWE_LFO2VAL", - }, - /* Data 3 0xE20 */ - { "AWE_IP", - "AWE_IFATN", - "AWE_PEFE", - "AWE_FMMOD", - "AWE_TREMFRQ", - "AWE_FM2FRQ2", - 0, - 0, - }, +char *PORT_NAMES[][8] = { + /* Data 0 ( 0x620/0x622) */ + { + "AWE_CPF", + "AWE_PTRX", + "AWE_CVCF", + "AWE_VTFT", + "Unk-620-4", + "Unk-620-5", + "AWE_PSST", + "AWE_CSL", + }, + /* Data 1 0xA20 */ + { + "AWE_CCCA", + 0, + /* + "AWE_HWCF4" + "AWE_HWCF5" + "AWE_HWCF6" + "AWE_HWCF7" + "AWE_SMALR" + "AWE_SMARR" + "AWE_SMALW" + "AWE_SMARW" + "AWE_SMLD" + "AWE_SMRD" + "AWE_WC" + "AWE_HWCF1" + "AWE_HWCF2" + "AWE_HWCF3" + */ + 0, //"AWE_INIT1", + 0, //"AWE_INIT3", + "AWE_ENVVOL", + "AWE_DCYSUSV", + "AWE_ENVVAL", + "AWE_DCYSUS", + }, + /* Data 2 0xA22 */ + { + "AWE_CCCA", + 0, + 0, //"AWE_INIT2", + 0, //"AWE_INIT4", + "AWE_ATKHLDV", + "AWE_LFO1VAL", + "AWE_ATKHLD", + "AWE_LFO2VAL", + }, + /* Data 3 0xE20 */ + { + "AWE_IP", + "AWE_IFATN", + "AWE_PEFE", + "AWE_FMMOD", + "AWE_TREMFRQ", + "AWE_FM2FRQ2", + 0, + 0, + }, }; -enum -{ - ENV_STOPPED = 0, - ENV_DELAY = 1, - ENV_ATTACK = 2, - ENV_HOLD = 3, - //ENV_DECAY = 4, - ENV_SUSTAIN = 5, - //ENV_RELEASE = 6, - ENV_RAMP_DOWN = 7, - ENV_RAMP_UP = 8 +enum { + ENV_STOPPED = 0, + ENV_DELAY = 1, + ENV_ATTACK = 2, + ENV_HOLD = 3, + // ENV_DECAY = 4, + ENV_SUSTAIN = 5, + // ENV_RELEASE = 6, + ENV_RAMP_DOWN = 7, + ENV_RAMP_UP = 8 }; - static int random_helper = 0; -int dmareadbit = 0; -int dmawritebit = 0; - +int dmareadbit = 0; +int dmawritebit = 0; /* cubic and linear tables resolution. Note: higher than 10 does not improve the result. */ #define CUBIC_RESOLUTION_LOG 10 -#define CUBIC_RESOLUTION (1<> 15 to move back to +/-1 range). */ static int32_t lfotable[65536]; @@ -177,8 +189,7 @@ static int64_t lfofreqtospeed[256]; /* LFO used for the chorus. a sine wave.(signed 16bits with 32768 max int. >> 15 to move back to +/-1 range). */ static double chortable[65536]; -static const int REV_BUFSIZE_STEP=242; - +static const int REV_BUFSIZE_STEP = 242; /* These lines come from the awe32faq, describing the NRPN control for the initial filter * where it describes a linear increment filter instead of an octave-incremented one. @@ -188,9 +199,9 @@ static const int REV_BUFSIZE_STEP=242; * Filter cutoff from 100Hz to 8000Hz * This table comes from the awe32faq, describing the NRPN control for the filter Q. - * I don't know if is meant to be interpreted as the actual measured output of the + * I don't know if is meant to be interpreted as the actual measured output of the * filter or what. Especially, I don't understand the "low" and "high" ranges. - * What is otherwise documented is that the Q ranges from 0dB to 24dB and the attenuation + * What is otherwise documented is that the Q ranges from 0dB to 24dB and the attenuation * is half of the Q ( i.e. for 12dB Q, attenuate the input signal with -6dB) Coeff Low Fc(Hz)Low Q(dB)High Fc(kHz)High Q(dB)DC Attenuation(dB) * 0 92 5 Flat Flat -0.0 @@ -211,2197 +222,2174 @@ Coeff Low Fc(Hz)Low Q(dB)High Fc(kHz)High Q(dB)DC Attenuation(dB) * 15 100 28 7.0 18 -11.0 * * Attenuation as above, codified in amplitude.*/ -static int32_t filter_atten[16] = -{ +static int32_t filter_atten[16] = { 65536, 61869, 57079, 53269, 49145, 44820, 40877, 34792, 32845, 30653, 28607, - 26392, 24630, 22463, 20487, 18470 + 26392, 24630, 22463, 20487, 18470 }; /*Coefficients for the filters for a defined Q and cutoff.*/ static int32_t filt_coeffs[16][256][3]; -#define READ16_SWITCH(addr, var) switch ((addr) & 2) \ - { \ - case 0: ret = (var) & 0xffff; break; \ - case 2: ret = ((var) >> 16) & 0xffff; break; \ - } - -#define WRITE16_SWITCH(addr, var, val) switch ((addr) & 2) \ - { \ - case 0: var = (var & 0xffff0000) | (val); break; \ - case 2: var = (var & 0x0000ffff) | ((val) << 16); break; \ - } +#define READ16_SWITCH(addr, var) \ + switch ((addr) &2) { \ + case 0: \ + ret = (var) &0xffff; \ + break; \ + case 2: \ + ret = ((var) >> 16) & 0xffff; \ + break; \ + } + +#define WRITE16_SWITCH(addr, var, val) \ + switch ((addr) &2) { \ + case 0: \ + var = (var & 0xffff0000) | (val); \ + break; \ + case 2: \ + var = (var & 0x0000ffff) | ((val) << 16); \ + break; \ + } #ifdef EMU8K_DEBUG_REGISTERS -uint32_t dw_value = 0; -uint32_t last_read = 0; -uint32_t last_write = 0; +uint32_t dw_value = 0; +uint32_t last_read = 0; +uint32_t last_write = 0; uint32_t rep_count_r = 0; uint32_t rep_count_w = 0; -# define READ16(addr, var) READ16_SWITCH(addr, var) \ - { \ - const char *name=0; \ - switch(addr&0xF02) \ - { \ - case 0x600: case 0x602: \ - name = PORT_NAMES[0][emu8k->cur_reg]; \ - break; \ - case 0xA00: \ - name = PORT_NAMES[1][emu8k->cur_reg]; \ - break; \ - case 0xA02: \ - name = PORT_NAMES[2][emu8k->cur_reg]; \ - break; \ - } \ - if (name == 0) \ - { \ - /*emu8k_log("EMU8K READ %04X-%02X(%d): %04X\n",addr,(emu8k->cur_reg)<<5|emu8k->cur_voice, emu8k->cur_voice,ret);*/ \ - } \ - else \ - { \ - emu8k_log("EMU8K READ %s(%d) (%d): %04X\n",name, (addr&0x2), emu8k->cur_voice, ret); \ - }\ - } -# define WRITE16(addr, var, val) WRITE16_SWITCH(addr, var, val) \ - { \ - const char *name=0; \ - switch(addr&0xF02) \ - { \ - case 0x600: case 0x602: \ - name = PORT_NAMES[0][emu8k->cur_reg]; \ - break; \ - case 0xA00: \ - name = PORT_NAMES[1][emu8k->cur_reg]; \ - break; \ - case 0xA02: \ - name = PORT_NAMES[2][emu8k->cur_reg]; \ - break; \ - } \ - if (name == 0) \ - { \ - /*emu8k_log("EMU8K WRITE %04X-%02X(%d): %04X\n",addr,(emu8k->cur_reg)<<5|emu8k->cur_voice,emu8k->cur_voice, val);*/ \ - } \ - else \ - { \ - emu8k_log("EMU8K WRITE %s(%d) (%d): %04X\n",name, (addr&0x2), emu8k->cur_voice,val); \ - }\ - } +# define READ16(addr, var) \ + READ16_SWITCH(addr, var) \ + { \ + const char *name = 0; \ + switch (addr & 0xF02) { \ + case 0x600: \ + case 0x602: \ + name = PORT_NAMES[0][emu8k->cur_reg]; \ + break; \ + case 0xA00: \ + name = PORT_NAMES[1][emu8k->cur_reg]; \ + break; \ + case 0xA02: \ + name = PORT_NAMES[2][emu8k->cur_reg]; \ + break; \ + } \ + if (name == 0) { \ + /*emu8k_log("EMU8K READ %04X-%02X(%d): %04X\n",addr,(emu8k->cur_reg)<<5|emu8k->cur_voice, emu8k->cur_voice,ret);*/ \ + } else { \ + emu8k_log("EMU8K READ %s(%d) (%d): %04X\n", name, (addr & 0x2), emu8k->cur_voice, ret); \ + } \ + } +# define WRITE16(addr, var, val) \ + WRITE16_SWITCH(addr, var, val) \ + { \ + const char *name = 0; \ + switch (addr & 0xF02) { \ + case 0x600: \ + case 0x602: \ + name = PORT_NAMES[0][emu8k->cur_reg]; \ + break; \ + case 0xA00: \ + name = PORT_NAMES[1][emu8k->cur_reg]; \ + break; \ + case 0xA02: \ + name = PORT_NAMES[2][emu8k->cur_reg]; \ + break; \ + } \ + if (name == 0) { \ + /*emu8k_log("EMU8K WRITE %04X-%02X(%d): %04X\n",addr,(emu8k->cur_reg)<<5|emu8k->cur_voice,emu8k->cur_voice, val);*/ \ + } else { \ + emu8k_log("EMU8K WRITE %s(%d) (%d): %04X\n", name, (addr & 0x2), emu8k->cur_voice, val); \ + } \ + } #else -# define READ16(addr, var) READ16_SWITCH(addr, var) -# define WRITE16(addr, var, val) WRITE16_SWITCH(addr, var, val) -#endif //EMU8K_DEBUG_REGISTERS - +# define READ16(addr, var) READ16_SWITCH(addr, var) +# define WRITE16(addr, var, val) WRITE16_SWITCH(addr, var, val) +#endif // EMU8K_DEBUG_REGISTERS #ifdef ENABLE_EMU8K_LOG int emu8k_do_log = ENABLE_EMU8K_LOG; - static void emu8k_log(const char *fmt, ...) { va_list ap; if (emu8k_do_log) { - va_start(ap, fmt); - pclog_ex(fmt, ap); - va_end(ap); + va_start(ap, fmt); + pclog_ex(fmt, ap); + va_end(ap); } } #else -#define emu8k_log(fmt, ...) +# define emu8k_log(fmt, ...) #endif - -static inline int16_t EMU8K_READ(emu8k_t *emu8k, uint32_t addr) +static inline int16_t +EMU8K_READ(emu8k_t *emu8k, uint32_t addr) { - const register emu8k_mem_pointers_t addrmem = {{addr}}; - return emu8k->ram_pointers[addrmem.hb_address][addrmem.lw_address]; + const register emu8k_mem_pointers_t addrmem = { { addr } }; + return emu8k->ram_pointers[addrmem.hb_address][addrmem.lw_address]; } #if NOTUSED -static inline int16_t EMU8K_READ_INTERP_LINEAR(emu8k_t *emu8k, uint32_t int_addr, uint16_t fract) +static inline int16_t +EMU8K_READ_INTERP_LINEAR(emu8k_t *emu8k, uint32_t int_addr, uint16_t fract) { - /* The interpolation in AWE32 used a so-called patented 3-point interpolation - * ( I guess some sort of spline having one point before and one point after). - * Also, it has the consequence that the playback is delayed by one sample. - * I simulate the "one sample later" than the address with addr+1 and addr+2 - * instead of +0 and +1 */ - int16_t dat1 = EMU8K_READ(emu8k, int_addr+1); - int32_t dat2 = EMU8K_READ(emu8k, int_addr+2); - dat1 += ((dat2-(int32_t)dat1)* fract) >> 16; - return dat1; + /* The interpolation in AWE32 used a so-called patented 3-point interpolation + * ( I guess some sort of spline having one point before and one point after). + * Also, it has the consequence that the playback is delayed by one sample. + * I simulate the "one sample later" than the address with addr+1 and addr+2 + * instead of +0 and +1 */ + int16_t dat1 = EMU8K_READ(emu8k, int_addr + 1); + int32_t dat2 = EMU8K_READ(emu8k, int_addr + 2); + dat1 += ((dat2 - (int32_t) dat1) * fract) >> 16; + return dat1; } #endif -static inline int32_t EMU8K_READ_INTERP_CUBIC(emu8k_t *emu8k, uint32_t int_addr, uint16_t fract) +static inline int32_t +EMU8K_READ_INTERP_CUBIC(emu8k_t *emu8k, uint32_t int_addr, uint16_t fract) { - /*Since there are four floats in the table for each fraction, the position is 16byte aligned. */ - fract >>= 16-CUBIC_RESOLUTION_LOG; - fract <<=2; + /*Since there are four floats in the table for each fraction, the position is 16byte aligned. */ + fract >>= 16 - CUBIC_RESOLUTION_LOG; + fract <<= 2; - /* TODO: I still have to verify how this works, but I think that - * the card could use two oscillators (usually 31 and 32) where it would - * be writing the OPL3 output, and to which, chorus and reverb could be applied to get - * those effects for OPL3 sounds.*/ -// if ((addr & EMU8K_FM_MEM_ADDRESS) == EMU8K_FM_MEM_ADDRESS) {} + /* TODO: I still have to verify how this works, but I think that + * the card could use two oscillators (usually 31 and 32) where it would + * be writing the OPL3 output, and to which, chorus and reverb could be applied to get + * those effects for OPL3 sounds.*/ +#if 0 + if ((addr & EMU8K_FM_MEM_ADDRESS) == EMU8K_FM_MEM_ADDRESS) {} +#endif - /* This is cubic interpolation. - * Not the same than 3-point interpolation, but a better approximation than linear - * interpolation. - * Also, it takes into account the "Note that the actual audio location is the point - * 1 word higher than this value due to interpolation offset". - * That's why the pointers are 0, 1, 2, 3 and not -1, 0, 1, 2 */ - int32_t dat2 = EMU8K_READ(emu8k, int_addr+1); - const float *table = &cubic_table[fract]; - const int32_t dat1 = EMU8K_READ(emu8k, int_addr); - const int32_t dat3 = EMU8K_READ(emu8k, int_addr+2); - const int32_t dat4 = EMU8K_READ(emu8k, int_addr+3); - /* Note: I've ended using float for the table values to avoid some cases of integer overflow. */ - dat2 = dat1*table[0] + dat2*table[1] + dat3*table[2] + dat4*table[3]; - return dat2; + /* This is cubic interpolation. + * Not the same than 3-point interpolation, but a better approximation than linear + * interpolation. + * Also, it takes into account the "Note that the actual audio location is the point + * 1 word higher than this value due to interpolation offset". + * That's why the pointers are 0, 1, 2, 3 and not -1, 0, 1, 2 */ + int32_t dat2 = EMU8K_READ(emu8k, int_addr + 1); + const float *table = &cubic_table[fract]; + const int32_t dat1 = EMU8K_READ(emu8k, int_addr); + const int32_t dat3 = EMU8K_READ(emu8k, int_addr + 2); + const int32_t dat4 = EMU8K_READ(emu8k, int_addr + 3); + /* Note: I've ended using float for the table values to avoid some cases of integer overflow. */ + dat2 = dat1 * table[0] + dat2 * table[1] + dat3 * table[2] + dat4 * table[3]; + return dat2; } -static inline void EMU8K_WRITE(emu8k_t *emu8k, uint32_t addr, uint16_t val) +static inline void +EMU8K_WRITE(emu8k_t *emu8k, uint32_t addr, uint16_t val) { - addr &= EMU8K_MEM_ADDRESS_MASK; - if ( !emu8k->ram || addr < EMU8K_RAM_MEM_START || addr >= EMU8K_FM_MEM_ADDRESS ) - return; + addr &= EMU8K_MEM_ADDRESS_MASK; + if (!emu8k->ram || addr < EMU8K_RAM_MEM_START || addr >= EMU8K_FM_MEM_ADDRESS) + return; - /* It looks like if an application writes to a memory part outside of the available - * amount on the card, it wraps, and opencubicplayer uses that to detect the amount - * of memory, as opposed to simply check at the address that it has just tried to write. */ - while (addr >= emu8k->ram_end_addr) - addr -= emu8k->ram_end_addr - EMU8K_RAM_MEM_START; + /* It looks like if an application writes to a memory part outside of the available + * amount on the card, it wraps, and opencubicplayer uses that to detect the amount + * of memory, as opposed to simply check at the address that it has just tried to write. */ + while (addr >= emu8k->ram_end_addr) + addr -= emu8k->ram_end_addr - EMU8K_RAM_MEM_START; - emu8k->ram[addr - EMU8K_RAM_MEM_START] = val; + emu8k->ram[addr - EMU8K_RAM_MEM_START] = val; } -uint16_t emu8k_inw(uint16_t addr, void *p) +uint16_t +emu8k_inw(uint16_t addr, void *priv) { - emu8k_t *emu8k = (emu8k_t *)p; - uint16_t ret = 0xffff; - + emu8k_t *emu8k = (emu8k_t *) priv; + uint16_t ret = 0xffff; + #ifdef EMU8K_DEBUG_REGISTERS - if (addr == 0xE22) - { - emu8k_log("EMU8K READ POINTER: %d\n", - ((0x80 | ((random_helper + 1) & 0x1F)) << 8) | (emu8k->cur_reg << 5) | emu8k->cur_voice); + if (addr == 0xE22) { + emu8k_log("EMU8K READ POINTER: %d\n", + ((0x80 | ((random_helper + 1) & 0x1F)) << 8) | (emu8k->cur_reg << 5) | emu8k->cur_voice); + } else if ((addr & 0xF00) == 0x600) { + /* These are automatically reported by READ16 */ + if (rep_count_r > 1) { + emu8k_log("EMU8K ...... for %d times\n", rep_count_r); + rep_count_r = 0; } - else if ((addr&0xF00) == 0x600) - { - /* These are automatically reported by READ16 */ - if (rep_count_r>1) - { - emu8k_log("EMU8K ...... for %d times\n", rep_count_r); - rep_count_r=0; + last_read = 0; + } else if ((addr & 0xF00) == 0xA00 && emu8k->cur_reg == 0) { + /* These are automatically reported by READ16 */ + if (rep_count_r > 1) { + emu8k_log("EMU8K ...... for %d times\n", rep_count_r); + rep_count_r = 0; + } + last_read = 0; + } else if ((addr & 0xF00) == 0xA00 && emu8k->cur_reg == 1) { + uint32_t tmpz = ((addr & 0xF00) << 16) | (emu8k->cur_reg << 5); + if (tmpz != last_read) { + if (rep_count_r > 1) { + emu8k_log("EMU8K ...... for %d times\n", rep_count_r); + rep_count_r = 0; + } + last_read = tmpz; + emu8k_log("EMU8K READ RAM I/O or configuration or clock \n"); + } + // emu8k_log("EMU8K READ %04X-%02X(%d/%d)\n",addr,(emu8k->cur_reg)<<5|emu8k->cur_voice, emu8k->cur_reg, emu8k->cur_voice); + } else if ((addr & 0xF00) == 0xA00 && (emu8k->cur_reg == 2 || emu8k->cur_reg == 3)) { + uint32_t tmpz = ((addr & 0xF00) << 16); + if (tmpz != last_read) { + if (rep_count_r > 1) { + emu8k_log("EMU8K ...... for %d times\n", rep_count_r); + rep_count_r = 0; + } + last_read = tmpz; + emu8k_log("EMU8K READ INIT \n"); + } + // emu8k_log("EMU8K READ %04X-%02X(%d/%d)\n",addr,(emu8k->cur_reg)<<5|emu8k->cur_voice, emu8k->cur_reg, emu8k->cur_voice); + } else { + uint32_t tmpz = (addr << 16) | (emu8k->cur_reg << 5) | emu8k->cur_voice; + if (tmpz != last_read) { + char *name = 0; + uint16_t val = 0xBAAD; + if (addr == 0xA20) { + name = PORT_NAMES[1][emu8k->cur_reg]; + switch (emu8k->cur_reg) { + case 2: + val = emu8k->init1[emu8k->cur_voice]; + break; + case 3: + val = emu8k->init3[emu8k->cur_voice]; + break; + case 4: + val = emu8k->voice[emu8k->cur_voice].envvol; + break; + case 5: + val = emu8k->voice[emu8k->cur_voice].dcysusv; + break; + case 6: + val = emu8k->voice[emu8k->cur_voice].envval; + break; + case 7: + val = emu8k->voice[emu8k->cur_voice].dcysus; + break; } - last_read=0; - } - else if ((addr&0xF00) == 0xA00 && emu8k->cur_reg == 0) - { - /* These are automatically reported by READ16 */ - if (rep_count_r>1) - { - emu8k_log("EMU8K ...... for %d times\n", rep_count_r); - rep_count_r=0; + } else if (addr == 0xA22) { + name = PORT_NAMES[2][emu8k->cur_reg]; + switch (emu8k->cur_reg) { + case 2: + val = emu8k->init2[emu8k->cur_voice]; + break; + case 3: + val = emu8k->init4[emu8k->cur_voice]; + break; + case 4: + val = emu8k->voice[emu8k->cur_voice].atkhldv; + break; + case 5: + val = emu8k->voice[emu8k->cur_voice].lfo1val; + break; + case 6: + val = emu8k->voice[emu8k->cur_voice].atkhld; + break; + case 7: + val = emu8k->voice[emu8k->cur_voice].lfo2val; + break; } - last_read=0; - } - else if ((addr&0xF00) == 0xA00 && emu8k->cur_reg == 1) - { - uint32_t tmpz = ((addr&0xF00) << 16)|(emu8k->cur_reg<<5); - if (tmpz != last_read) - { - if (rep_count_r>1) - { - emu8k_log("EMU8K ...... for %d times\n", rep_count_r); - rep_count_r=0; - } - last_read=tmpz; - emu8k_log("EMU8K READ RAM I/O or configuration or clock \n"); + } else if (addr == 0xE20) { + name = PORT_NAMES[3][emu8k->cur_reg]; + switch (emu8k->cur_reg) { + case 0: + val = emu8k->voice[emu8k->cur_voice].ip; + break; + case 1: + val = emu8k->voice[emu8k->cur_voice].ifatn; + break; + case 2: + val = emu8k->voice[emu8k->cur_voice].pefe; + break; + case 3: + val = emu8k->voice[emu8k->cur_voice].fmmod; + break; + case 4: + val = emu8k->voice[emu8k->cur_voice].tremfrq; + break; + case 5: + val = emu8k->voice[emu8k->cur_voice].fm2frq2; + break; + case 6: + val = 0xffff; + break; + case 7: + val = 0x1c | ((emu8k->id & 0x0002) ? 0xff02 : 0); + break; } - //emu8k_log("EMU8K READ %04X-%02X(%d/%d)\n",addr,(emu8k->cur_reg)<<5|emu8k->cur_voice, emu8k->cur_reg, emu8k->cur_voice); - } - else if ((addr&0xF00) == 0xA00 && (emu8k->cur_reg == 2 || emu8k->cur_reg == 3)) - { - uint32_t tmpz = ((addr&0xF00) << 16); - if (tmpz != last_read) - { - if (rep_count_r>1) - { - emu8k_log("EMU8K ...... for %d times\n", rep_count_r); - rep_count_r=0; - } - last_read=tmpz; - emu8k_log("EMU8K READ INIT \n"); - } - //emu8k_log("EMU8K READ %04X-%02X(%d/%d)\n",addr,(emu8k->cur_reg)<<5|emu8k->cur_voice, emu8k->cur_reg, emu8k->cur_voice); - } - else - { - uint32_t tmpz = (addr << 16)|(emu8k->cur_reg<<5)| emu8k->cur_voice; - if (tmpz != last_read) - { - char* name = 0; - uint16_t val = 0xBAAD; - if (addr == 0xA20) - { - name = PORT_NAMES[1][emu8k->cur_reg]; - switch (emu8k->cur_reg) - { - case 2: val = emu8k->init1[emu8k->cur_voice]; break; - case 3: val = emu8k->init3[emu8k->cur_voice]; break; - case 4: val = emu8k->voice[emu8k->cur_voice].envvol; break; - case 5: val = emu8k->voice[emu8k->cur_voice].dcysusv; break; - case 6: val = emu8k->voice[emu8k->cur_voice].envval; break; - case 7: val = emu8k->voice[emu8k->cur_voice].dcysus; break; - } - } - else if (addr == 0xA22) - { - name = PORT_NAMES[2][emu8k->cur_reg]; - switch (emu8k->cur_reg) - { - case 2: val = emu8k->init2[emu8k->cur_voice]; break; - case 3: val = emu8k->init4[emu8k->cur_voice]; break; - case 4: val = emu8k->voice[emu8k->cur_voice].atkhldv; break; - case 5: val = emu8k->voice[emu8k->cur_voice].lfo1val; break; - case 6: val = emu8k->voice[emu8k->cur_voice].atkhld; break; - case 7: val = emu8k->voice[emu8k->cur_voice].lfo2val; break; - } - } - else if (addr == 0xE20) - { - name = PORT_NAMES[3][emu8k->cur_reg]; - switch (emu8k->cur_reg) - { - case 0: val = emu8k->voice[emu8k->cur_voice].ip; break; - case 1: val = emu8k->voice[emu8k->cur_voice].ifatn; break; - case 2: val = emu8k->voice[emu8k->cur_voice].pefe; break; - case 3: val = emu8k->voice[emu8k->cur_voice].fmmod; break; - case 4: val = emu8k->voice[emu8k->cur_voice].tremfrq; break; - case 5: val = emu8k->voice[emu8k->cur_voice].fm2frq2;break; - case 6: val = 0xffff; break; - case 7: val = 0x1c | ((emu8k->id & 0x0002) ? 0xff02 : 0); break; - } - } - if (rep_count_r>1) - { - emu8k_log("EMU8K ...... for %d times\n", rep_count_r); - } - if (name == 0) - { - emu8k_log("EMU8K READ %04X-%02X(%d/%d): %04X\n",addr,(emu8k->cur_reg)<<5|emu8k->cur_voice, emu8k->cur_reg, emu8k->cur_voice,val); - } - else - { - emu8k_log("EMU8K READ %s (%d): %04X\n",name,emu8k->cur_voice, val); - } + } + if (rep_count_r > 1) { + emu8k_log("EMU8K ...... for %d times\n", rep_count_r); + } + if (name == 0) { + emu8k_log("EMU8K READ %04X-%02X(%d/%d): %04X\n", addr, (emu8k->cur_reg) << 5 | emu8k->cur_voice, emu8k->cur_reg, emu8k->cur_voice, val); + } else { + emu8k_log("EMU8K READ %s (%d): %04X\n", name, emu8k->cur_voice, val); + } - rep_count_r=0; - last_read=tmpz; - } - rep_count_r++; + rep_count_r = 0; + last_read = tmpz; } + rep_count_r++; + } #endif // EMU8K_DEBUG_REGISTERS + switch (addr & 0xF02) { + case 0x600: + case 0x602: /*Data0. also known as BLASTER+0x400 and EMU+0x000 */ + switch (emu8k->cur_reg) { + case 0: + READ16(addr, emu8k->voice[emu8k->cur_voice].cpf); + return ret; - switch (addr & 0xF02) - { - case 0x600: case 0x602: /*Data0. also known as BLASTER+0x400 and EMU+0x000 */ - switch (emu8k->cur_reg) - { - case 0: - READ16(addr, emu8k->voice[emu8k->cur_voice].cpf); - return ret; - - case 1: - READ16(addr, emu8k->voice[emu8k->cur_voice].ptrx); - return ret; - - case 2: - READ16(addr, emu8k->voice[emu8k->cur_voice].cvcf); - return ret; - - case 3: - READ16(addr, emu8k->voice[emu8k->cur_voice].vtft); - return ret; - - case 4: - READ16(addr, emu8k->voice[emu8k->cur_voice].unknown_data0_4); - return ret; + case 1: + READ16(addr, emu8k->voice[emu8k->cur_voice].ptrx); + return ret; - case 5: - READ16(addr, emu8k->voice[emu8k->cur_voice].unknown_data0_5); - return ret; - - case 6: - READ16(addr, emu8k->voice[emu8k->cur_voice].psst); - return ret; - - case 7: - READ16(addr, emu8k->voice[emu8k->cur_voice].csl); - return ret; - } - break; + case 2: + READ16(addr, emu8k->voice[emu8k->cur_voice].cvcf); + return ret; - case 0xA00: /*Data1. also known as BLASTER+0x800 and EMU+0x400 */ - switch (emu8k->cur_reg) - { - case 0: - READ16(addr, emu8k->voice[emu8k->cur_voice].ccca); - return ret; + case 3: + READ16(addr, emu8k->voice[emu8k->cur_voice].vtft); + return ret; - case 1: - switch (emu8k->cur_voice) - { - case 9: - READ16(addr, emu8k->hwcf4); - return ret; - case 10: - READ16(addr, emu8k->hwcf5); - return ret; - /* Actually, these two might be command words rather than registers, or some LFO position/buffer reset.*/ - case 13: - READ16(addr, emu8k->hwcf6); - return ret; - case 14: - READ16(addr, emu8k->hwcf7); - return ret; - - case 20: - READ16(addr, emu8k->smalr); - return ret; - case 21: - READ16(addr, emu8k->smarr); - return ret; - case 22: - READ16(addr, emu8k->smalw); - return ret; - case 23: - READ16(addr, emu8k->smarw); - return ret; - - case 26: - { - uint16_t val = emu8k->smld_buffer; - emu8k->smld_buffer = EMU8K_READ(emu8k, emu8k->smalr); - emu8k->smalr = (emu8k->smalr+1) & EMU8K_MEM_ADDRESS_MASK; - return val; - } + case 4: + READ16(addr, emu8k->voice[emu8k->cur_voice].unknown_data0_4); + return ret; - /*The EMU8000 PGM describes the return values of these registers as 'a VLSI error'*/ - case 29: /*Configuration Word 1*/ - return (emu8k->hwcf1 & 0xfe) | (emu8k->hwcf3 & 0x01); - case 30: /*Configuration Word 2*/ - return ((emu8k->hwcf2 >> 4) & 0x0e) | (emu8k->hwcf1 & 0x01) | ((emu8k->hwcf3 & 0x02) ? 0x10 : 0) | ((emu8k->hwcf3 & 0x04) ? 0x40 : 0) - | ((emu8k->hwcf3 & 0x08) ? 0x20 : 0) | ((emu8k->hwcf3 & 0x10) ? 0x80 : 0); - case 31: /*Configuration Word 3*/ - return emu8k->hwcf2 & 0x1f; - } - break; + case 5: + READ16(addr, emu8k->voice[emu8k->cur_voice].unknown_data0_5); + return ret; - case 2: - return emu8k->init1[emu8k->cur_voice]; - - case 3: - return emu8k->init3[emu8k->cur_voice]; - - case 4: - return emu8k->voice[emu8k->cur_voice].envvol; + case 6: + READ16(addr, emu8k->voice[emu8k->cur_voice].psst); + return ret; - case 5: - return emu8k->voice[emu8k->cur_voice].dcysusv; - - case 6: - return emu8k->voice[emu8k->cur_voice].envval; + case 7: + READ16(addr, emu8k->voice[emu8k->cur_voice].csl); + return ret; - case 7: - return emu8k->voice[emu8k->cur_voice].dcysus; - } - break; + default: + break; + } + break; - case 0xA02: /*Data2. also known as BLASTER+0x802 and EMU+0x402 */ - switch (emu8k->cur_reg) - { - case 0: - READ16(addr, emu8k->voice[emu8k->cur_voice].ccca); - return ret; + case 0xA00: /*Data1. also known as BLASTER+0x800 and EMU+0x400 */ + switch (emu8k->cur_reg) { + case 0: + READ16(addr, emu8k->voice[emu8k->cur_voice].ccca); + return ret; - case 1: - switch (emu8k->cur_voice) - { - case 9: - READ16(addr, emu8k->hwcf4); - return ret; - case 10: - READ16(addr, emu8k->hwcf5); - return ret; - /* Actually, these two might be command words rather than registers, or some LFO position/buffer reset. */ - case 13: - READ16(addr, emu8k->hwcf6); - return ret; - case 14: - READ16(addr, emu8k->hwcf7); - return ret; + case 1: + switch (emu8k->cur_voice) { + case 9: + READ16(addr, emu8k->hwcf4); + return ret; + case 10: + READ16(addr, emu8k->hwcf5); + return ret; + /* Actually, these two might be command words rather than registers, or some LFO position/buffer reset.*/ + case 13: + READ16(addr, emu8k->hwcf6); + return ret; + case 14: + READ16(addr, emu8k->hwcf7); + return ret; - /* Simulating empty/full bits by unsetting it once read. */ - case 20: - READ16(addr, emu8k->smalr|dmareadbit); - /* xor with itself to set to zero faster. */ - dmareadbit^=dmareadbit; - return ret; - case 21: - READ16(addr, emu8k->smarr|dmareadbit); - /* xor with itself to set to zero faster.*/ - dmareadbit^=dmareadbit; - return ret; - case 22: - READ16(addr, emu8k->smalw|dmawritebit); - /*xor with itself to set to zero faster.*/ - dmawritebit^=dmawritebit; - return ret; - case 23: - READ16(addr, emu8k->smarw|dmawritebit); - /*xor with itself to set to zero faster.*/ - dmawritebit^=dmawritebit; - return ret; - - case 26: - { - uint16_t val = emu8k->smrd_buffer; - emu8k->smrd_buffer = EMU8K_READ(emu8k, emu8k->smarr); - emu8k->smarr = (emu8k->smarr+1) & EMU8K_MEM_ADDRESS_MASK; - return val; - } - /*TODO: We need to improve the precision of this clock, since - it is used by programs to wait. Not critical, but should help reduce - the amount of calls and wait time */ - case 27: /*Sample Counter ( 44Khz clock) */ - return emu8k->wc; - } - break; + case 20: + READ16(addr, emu8k->smalr); + return ret; + case 21: + READ16(addr, emu8k->smarr); + return ret; + case 22: + READ16(addr, emu8k->smalw); + return ret; + case 23: + READ16(addr, emu8k->smarw); + return ret; - case 2: - return emu8k->init2[emu8k->cur_voice]; + case 26: + { + uint16_t val = emu8k->smld_buffer; + emu8k->smld_buffer = EMU8K_READ(emu8k, emu8k->smalr); + emu8k->smalr = (emu8k->smalr + 1) & EMU8K_MEM_ADDRESS_MASK; + return val; + } - case 3: - return emu8k->init4[emu8k->cur_voice]; - - case 4: - return emu8k->voice[emu8k->cur_voice].atkhldv; + /*The EMU8000 PGM describes the return values of these registers as 'a VLSI error'*/ + case 29: /*Configuration Word 1*/ + return (emu8k->hwcf1 & 0xfe) | (emu8k->hwcf3 & 0x01); + case 30: /*Configuration Word 2*/ + return ((emu8k->hwcf2 >> 4) & 0x0e) | (emu8k->hwcf1 & 0x01) | ((emu8k->hwcf3 & 0x02) ? 0x10 : 0) | ((emu8k->hwcf3 & 0x04) ? 0x40 : 0) + | ((emu8k->hwcf3 & 0x08) ? 0x20 : 0) | ((emu8k->hwcf3 & 0x10) ? 0x80 : 0); + case 31: /*Configuration Word 3*/ + return emu8k->hwcf2 & 0x1f; - case 5: - return emu8k->voice[emu8k->cur_voice].lfo1val; + default: + break; + } + break; - case 6: - return emu8k->voice[emu8k->cur_voice].atkhld; + case 2: + return emu8k->init1[emu8k->cur_voice]; - case 7: - return emu8k->voice[emu8k->cur_voice].lfo2val; - } - break; - - case 0xE00: /*Data3. also known as BLASTER+0xC00 and EMU+0x800 */ - switch (emu8k->cur_reg) - { - case 0: - return emu8k->voice[emu8k->cur_voice].ip; + case 3: + return emu8k->init3[emu8k->cur_voice]; - case 1: - return emu8k->voice[emu8k->cur_voice].ifatn; + case 4: + return emu8k->voice[emu8k->cur_voice].envvol; - case 2: - return emu8k->voice[emu8k->cur_voice].pefe; + case 5: + return emu8k->voice[emu8k->cur_voice].dcysusv; - case 3: - return emu8k->voice[emu8k->cur_voice].fmmod; + case 6: + return emu8k->voice[emu8k->cur_voice].envval; - case 4: - return emu8k->voice[emu8k->cur_voice].tremfrq; + case 7: + return emu8k->voice[emu8k->cur_voice].dcysus; - case 5: - return emu8k->voice[emu8k->cur_voice].fm2frq2; + default: + break; + } + break; - case 6: - return 0xffff; - - case 7: /*ID?*/ - return 0x1c | ((emu8k->id & 0x0002) ? 0xff02 : 0); - } - break; + case 0xA02: /*Data2. also known as BLASTER+0x802 and EMU+0x402 */ + switch (emu8k->cur_reg) { + case 0: + READ16(addr, emu8k->voice[emu8k->cur_voice].ccca); + return ret; - case 0xE02: /* Pointer. also known as BLASTER+0xC02 and EMU+0x802 */ - /* LS five bits = channel number, next 3 bits = register number - * and MS 8 bits = VLSI test register. - * Impulse tracker tests the non variability of the LS byte that it has set, and the variability - * of the MS byte to determine that it really is an AWE32. - * cubic player has a similar code, where it waits until value & 0x1000 is nonzero, and then waits again until it changes to zero.*/ - random_helper = (random_helper + 1) & 0x1F; - return ((0x80 | random_helper) << 8) | (emu8k->cur_reg << 5) | emu8k->cur_voice; - } - emu8k_log("EMU8K READ : Unknown register read: %04X-%02X(%d/%d) \n", addr, (emu8k->cur_reg << 5) | emu8k->cur_voice, emu8k->cur_reg, emu8k->cur_voice); - return 0xffff; + case 1: + switch (emu8k->cur_voice) { + case 9: + READ16(addr, emu8k->hwcf4); + return ret; + case 10: + READ16(addr, emu8k->hwcf5); + return ret; + /* Actually, these two might be command words rather than registers, or some LFO position/buffer reset. */ + case 13: + READ16(addr, emu8k->hwcf6); + return ret; + case 14: + READ16(addr, emu8k->hwcf7); + return ret; + + /* Simulating empty/full bits by unsetting it once read. */ + case 20: + READ16(addr, emu8k->smalr | dmareadbit); + /* xor with itself to set to zero faster. */ + dmareadbit ^= dmareadbit; + return ret; + case 21: + READ16(addr, emu8k->smarr | dmareadbit); + /* xor with itself to set to zero faster.*/ + dmareadbit ^= dmareadbit; + return ret; + case 22: + READ16(addr, emu8k->smalw | dmawritebit); + /*xor with itself to set to zero faster.*/ + dmawritebit ^= dmawritebit; + return ret; + case 23: + READ16(addr, emu8k->smarw | dmawritebit); + /*xor with itself to set to zero faster.*/ + dmawritebit ^= dmawritebit; + return ret; + + case 26: + { + uint16_t val = emu8k->smrd_buffer; + emu8k->smrd_buffer = EMU8K_READ(emu8k, emu8k->smarr); + emu8k->smarr = (emu8k->smarr + 1) & EMU8K_MEM_ADDRESS_MASK; + return val; + } + /*TODO: We need to improve the precision of this clock, since + it is used by programs to wait. Not critical, but should help reduce + the amount of calls and wait time */ + case 27: /*Sample Counter ( 44Khz clock) */ + return emu8k->wc; + + default: + break; + } + break; + + case 2: + return emu8k->init2[emu8k->cur_voice]; + + case 3: + return emu8k->init4[emu8k->cur_voice]; + + case 4: + return emu8k->voice[emu8k->cur_voice].atkhldv; + + case 5: + return emu8k->voice[emu8k->cur_voice].lfo1val; + + case 6: + return emu8k->voice[emu8k->cur_voice].atkhld; + + case 7: + return emu8k->voice[emu8k->cur_voice].lfo2val; + + default: + break; + } + break; + + case 0xE00: /*Data3. also known as BLASTER+0xC00 and EMU+0x800 */ + switch (emu8k->cur_reg) { + case 0: + return emu8k->voice[emu8k->cur_voice].ip; + + case 1: + return emu8k->voice[emu8k->cur_voice].ifatn; + + case 2: + return emu8k->voice[emu8k->cur_voice].pefe; + + case 3: + return emu8k->voice[emu8k->cur_voice].fmmod; + + case 4: + return emu8k->voice[emu8k->cur_voice].tremfrq; + + case 5: + return emu8k->voice[emu8k->cur_voice].fm2frq2; + + case 6: + return 0xffff; + + case 7: /*ID?*/ + return 0x1c | ((emu8k->id & 0x0002) ? 0xff02 : 0); + + default: + break; + } + break; + + case 0xE02: /* Pointer. also known as BLASTER+0xC02 and EMU+0x802 */ + /* LS five bits = channel number, next 3 bits = register number + * and MS 8 bits = VLSI test register. + * Impulse tracker tests the non variability of the LS byte that it has set, and the variability + * of the MS byte to determine that it really is an AWE32. + * cubic player has a similar code, where it waits until value & 0x1000 is nonzero, and then waits again until it changes to zero.*/ + random_helper = (random_helper + 1) & 0x1F; + return ((0x80 | random_helper) << 8) | (emu8k->cur_reg << 5) | emu8k->cur_voice; + + default: + break; + } + emu8k_log("EMU8K READ : Unknown register read: %04X-%02X(%d/%d) \n", addr, (emu8k->cur_reg << 5) | emu8k->cur_voice, emu8k->cur_reg, emu8k->cur_voice); + return 0xffff; } -void emu8k_outw(uint16_t addr, uint16_t val, void *p) +void +emu8k_outw(uint16_t addr, uint16_t val, void *priv) { - emu8k_t *emu8k = (emu8k_t *)p; + emu8k_t *emu8k = (emu8k_t *) priv; - /*TODO: I would like to not call this here, but i found it was needed or else cubic player would not finish opening (take a looot more of time than usual). - * Basically, being here means that the audio is generated in the emulation thread, instead of the audio thread.*/ - emu8k_update(emu8k); + /*TODO: I would like to not call this here, but i found it was needed or else cubic player would not finish opening (take a looot more of time than usual). + * Basically, being here means that the audio is generated in the emulation thread, instead of the audio thread.*/ + emu8k_update(emu8k); #ifdef EMU8K_DEBUG_REGISTERS - if (addr == 0xE22) - { - //emu8k_log("EMU8K WRITE POINTER: %d\n", val); + if (addr == 0xE22) { + // emu8k_log("EMU8K WRITE POINTER: %d\n", val); + } else if ((addr & 0xF00) == 0x600) { + /* These are automatically reported by WRITE16 */ + if (rep_count_w > 1) { + emu8k_log("EMU8K ...... for %d times\n", rep_count_w); + rep_count_w = 0; } - else if ((addr&0xF00) == 0x600) - { - /* These are automatically reported by WRITE16 */ - if (rep_count_w>1) - { - emu8k_log("EMU8K ...... for %d times\n", rep_count_w); - rep_count_w=0; - } - last_write=0; + last_write = 0; + } else if ((addr & 0xF00) == 0xA00 && emu8k->cur_reg == 0) { + /* These are automatically reported by WRITE16 */ + if (rep_count_w > 1) { + emu8k_log("EMU8K ...... for %d times\n", rep_count_w); + rep_count_w = 0; } - else if ((addr&0xF00) == 0xA00 && emu8k->cur_reg == 0) - { - /* These are automatically reported by WRITE16 */ - if (rep_count_w>1) - { - emu8k_log("EMU8K ...... for %d times\n", rep_count_w); - rep_count_w=0; - } - last_write=0; + last_write = 0; + } else if ((addr & 0xF00) == 0xA00 && emu8k->cur_reg == 1) { + uint32_t tmpz = ((addr & 0xF00) << 16) | (emu8k->cur_reg << 5); + if (tmpz != last_write) { + if (rep_count_w > 1) { + emu8k_log("EMU8K ...... for %d times\n", rep_count_w); + rep_count_w = 0; + } + last_write = tmpz; + emu8k_log("EMU8K WRITE RAM I/O or configuration \n"); } - else if ((addr&0xF00) == 0xA00 && emu8k->cur_reg == 1) - { - uint32_t tmpz = ((addr&0xF00) << 16)|(emu8k->cur_reg<<5); - if (tmpz != last_write) - { - if (rep_count_w>1) - { - emu8k_log("EMU8K ...... for %d times\n", rep_count_w); - rep_count_w=0; - } - last_write=tmpz; - emu8k_log("EMU8K WRITE RAM I/O or configuration \n"); - } - //emu8k_log("EMU8K WRITE %04X-%02X(%d/%d): %04X\n",addr,(emu8k->cur_reg)<<5|emu8k->cur_voice,emu8k->cur_reg,emu8k->cur_voice, val); + // emu8k_log("EMU8K WRITE %04X-%02X(%d/%d): %04X\n",addr,(emu8k->cur_reg)<<5|emu8k->cur_voice,emu8k->cur_reg,emu8k->cur_voice, val); + } else if ((addr & 0xF00) == 0xA00 && (emu8k->cur_reg == 2 || emu8k->cur_reg == 3)) { + uint32_t tmpz = ((addr & 0xF00) << 16); + if (tmpz != last_write) { + if (rep_count_w > 1) { + emu8k_log("EMU8K ...... for %d times\n", rep_count_w); + rep_count_w = 0; + } + last_write = tmpz; + emu8k_log("EMU8K WRITE INIT \n"); } - else if ((addr&0xF00) == 0xA00 && (emu8k->cur_reg == 2 || emu8k->cur_reg == 3)) - { - uint32_t tmpz = ((addr&0xF00) << 16); - if (tmpz != last_write) - { - if (rep_count_w>1) - { - emu8k_log("EMU8K ...... for %d times\n", rep_count_w); - rep_count_w=0; - } - last_write=tmpz; - emu8k_log("EMU8K WRITE INIT \n"); - } - //emu8k_log("EMU8K WRITE %04X-%02X(%d/%d): %04X\n",addr,(emu8k->cur_reg)<<5|emu8k->cur_voice,emu8k->cur_reg,emu8k->cur_voice, val); - } - else if (addr != 0xE22) - { - uint32_t tmpz = (addr << 16)|(emu8k->cur_reg<<5)| emu8k->cur_voice; - //if (tmpz != last_write) - if(1) - { - char* name = 0; - if (addr == 0xA20) - { - name = PORT_NAMES[1][emu8k->cur_reg]; - } - else if (addr == 0xA22) - { - name = PORT_NAMES[2][emu8k->cur_reg]; - } - else if (addr == 0xE20) - { - name = PORT_NAMES[3][emu8k->cur_reg]; - } + // emu8k_log("EMU8K WRITE %04X-%02X(%d/%d): %04X\n",addr,(emu8k->cur_reg)<<5|emu8k->cur_voice,emu8k->cur_reg,emu8k->cur_voice, val); + } else if (addr != 0xE22) { + uint32_t tmpz = (addr << 16) | (emu8k->cur_reg << 5) | emu8k->cur_voice; + // if (tmpz != last_write) + if (1) { + char *name = 0; + if (addr == 0xA20) { + name = PORT_NAMES[1][emu8k->cur_reg]; + } else if (addr == 0xA22) { + name = PORT_NAMES[2][emu8k->cur_reg]; + } else if (addr == 0xE20) { + name = PORT_NAMES[3][emu8k->cur_reg]; + } - if (rep_count_w>1) - { - emu8k_log("EMU8K ...... for %d times\n", rep_count_w); - } - if (name == 0) - { - emu8k_log("EMU8K WRITE %04X-%02X(%d/%d): %04X\n",addr,(emu8k->cur_reg)<<5|emu8k->cur_voice,emu8k->cur_reg,emu8k->cur_voice, val); - } - else - { - emu8k_log("EMU8K WRITE %s (%d): %04X\n",name,emu8k->cur_voice, val); - } - - rep_count_w=0; - last_write=tmpz; - } - rep_count_w++; + if (rep_count_w > 1) { + emu8k_log("EMU8K ...... for %d times\n", rep_count_w); + } + if (name == 0) { + emu8k_log("EMU8K WRITE %04X-%02X(%d/%d): %04X\n", addr, (emu8k->cur_reg) << 5 | emu8k->cur_voice, emu8k->cur_reg, emu8k->cur_voice, val); + } else { + emu8k_log("EMU8K WRITE %s (%d): %04X\n", name, emu8k->cur_voice, val); + } + + rep_count_w = 0; + last_write = tmpz; } -#endif //EMU8K_DEBUG_REGISTERS + rep_count_w++; + } +#endif // EMU8K_DEBUG_REGISTERS + switch (addr & 0xF02) { + case 0x600: + case 0x602: /*Data0. also known as BLASTER+0x400 and EMU+0x000 */ + switch (emu8k->cur_reg) { + case 0: + /* The docs says that this value is constantly updating, and it should have no actual effect. Actions should be done over ptrx */ + WRITE16(addr, emu8k->voice[emu8k->cur_voice].cpf, val); + return; - switch (addr & 0xF02) - { - case 0x600: case 0x602: /*Data0. also known as BLASTER+0x400 and EMU+0x000 */ - switch (emu8k->cur_reg) - { - case 0: - /* The docs says that this value is constantly updating, and it should have no actual effect. Actions should be done over ptrx */ - WRITE16(addr, emu8k->voice[emu8k->cur_voice].cpf, val); - return; - - case 1: - WRITE16(addr, emu8k->voice[emu8k->cur_voice].ptrx, val); - return; - - case 2: - /* The docs says that this value is constantly updating, and it should have no actual effect. Actions should be done over vtft */ - WRITE16(addr, emu8k->voice[emu8k->cur_voice].cvcf, val); - return; - - case 3: - WRITE16(addr, emu8k->voice[emu8k->cur_voice].vtft, val); - return; - - case 4: - WRITE16(addr, emu8k->voice[emu8k->cur_voice].unknown_data0_4, val); - return; + case 1: + WRITE16(addr, emu8k->voice[emu8k->cur_voice].ptrx, val); + return; - case 5: - WRITE16(addr, emu8k->voice[emu8k->cur_voice].unknown_data0_5, val); - return; - - case 6: - { - emu8k_voice_t *emu_voice = &emu8k->voice[emu8k->cur_voice]; - WRITE16(addr, emu_voice->psst, val); - /* TODO: Should we update only on MSB update, or this could be used as some sort of hack by applications? */ - emu_voice->loop_start.int_address = emu_voice->psst & EMU8K_MEM_ADDRESS_MASK; - if (addr & 2) - { - emu_voice->vol_l = emu_voice->psst_pan; - emu_voice->vol_r = 255 - (emu_voice->psst_pan); - } - } - return; - - case 7: - WRITE16(addr, emu8k->voice[emu8k->cur_voice].csl, val); + case 2: + /* The docs says that this value is constantly updating, and it should have no actual effect. Actions should be done over vtft */ + WRITE16(addr, emu8k->voice[emu8k->cur_voice].cvcf, val); + return; + + case 3: + WRITE16(addr, emu8k->voice[emu8k->cur_voice].vtft, val); + return; + + case 4: + WRITE16(addr, emu8k->voice[emu8k->cur_voice].unknown_data0_4, val); + return; + + case 5: + WRITE16(addr, emu8k->voice[emu8k->cur_voice].unknown_data0_5, val); + return; + + case 6: + { + emu8k_voice_t *emu_voice = &emu8k->voice[emu8k->cur_voice]; + WRITE16(addr, emu_voice->psst, val); /* TODO: Should we update only on MSB update, or this could be used as some sort of hack by applications? */ - emu8k->voice[emu8k->cur_voice].loop_end.int_address = emu8k->voice[emu8k->cur_voice].csl & EMU8K_MEM_ADDRESS_MASK; - return; - } - break; - - case 0xA00: /*Data1. also known as BLASTER+0x800 and EMU+0x400 */ - switch (emu8k->cur_reg) - { - case 0: - WRITE16(addr, emu8k->voice[emu8k->cur_voice].ccca, val); - /* TODO: Should we update only on MSB update, or this could be used as some sort of hack by applications? */ - emu8k->voice[emu8k->cur_voice].addr.int_address = emu8k->voice[emu8k->cur_voice].ccca & EMU8K_MEM_ADDRESS_MASK; - return; - - case 1: - switch (emu8k->cur_voice) - { - case 9: - WRITE16(addr, emu8k->hwcf4, val); - return; - case 10: - WRITE16(addr, emu8k->hwcf5, val); - return; - /* Actually, these two might be command words rather than registers, or some LFO position/buffer reset. */ - case 13: - WRITE16(addr, emu8k->hwcf6, val); - return; - case 14: - WRITE16(addr, emu8k->hwcf7, val); - return; - - case 20: - WRITE16(addr, emu8k->smalr, val); - return; - case 21: - WRITE16(addr, emu8k->smarr, val); - return; - case 22: - WRITE16(addr, emu8k->smalw, val); - return; - case 23: - WRITE16(addr, emu8k->smarw, val); - return; - - case 26: - EMU8K_WRITE(emu8k, emu8k->smalw, val); - emu8k->smalw = (emu8k->smalw+1) & EMU8K_MEM_ADDRESS_MASK; - return; - - case 29: - emu8k->hwcf1 = val; - return; - case 30: - emu8k->hwcf2 = val; - return; - case 31: - emu8k->hwcf3 = val; - return; + emu_voice->loop_start.int_address = emu_voice->psst & EMU8K_MEM_ADDRESS_MASK; + if (addr & 2) { + emu_voice->vol_l = emu_voice->psst_pan; + emu_voice->vol_r = 255 - (emu_voice->psst_pan); } - break; + } + return; - case 2: - emu8k->init1[emu8k->cur_voice] = val; - /* Skip if in first/second initialization step */ - if (emu8k->init1[0] != 0x03FF) - { - switch(emu8k->cur_voice) + case 7: + WRITE16(addr, emu8k->voice[emu8k->cur_voice].csl, val); + /* TODO: Should we update only on MSB update, or this could be used as some sort of hack by applications? */ + emu8k->voice[emu8k->cur_voice].loop_end.int_address = emu8k->voice[emu8k->cur_voice].csl & EMU8K_MEM_ADDRESS_MASK; + return; + + default: + break; + } + break; + + case 0xA00: /*Data1. also known as BLASTER+0x800 and EMU+0x400 */ + switch (emu8k->cur_reg) { + case 0: + WRITE16(addr, emu8k->voice[emu8k->cur_voice].ccca, val); + /* TODO: Should we update only on MSB update, or this could be used as some sort of hack by applications? */ + emu8k->voice[emu8k->cur_voice].addr.int_address = emu8k->voice[emu8k->cur_voice].ccca & EMU8K_MEM_ADDRESS_MASK; + return; + + case 1: + switch (emu8k->cur_voice) { + case 9: + WRITE16(addr, emu8k->hwcf4, val); + return; + case 10: + WRITE16(addr, emu8k->hwcf5, val); + return; + /* Actually, these two might be command words rather than registers, or some LFO position/buffer reset. */ + case 13: + WRITE16(addr, emu8k->hwcf6, val); + return; + case 14: + WRITE16(addr, emu8k->hwcf7, val); + return; + + case 20: + WRITE16(addr, emu8k->smalr, val); + return; + case 21: + WRITE16(addr, emu8k->smarr, val); + return; + case 22: + WRITE16(addr, emu8k->smalw, val); + return; + case 23: + WRITE16(addr, emu8k->smarw, val); + return; + + case 26: + EMU8K_WRITE(emu8k, emu8k->smalw, val); + emu8k->smalw = (emu8k->smalw + 1) & EMU8K_MEM_ADDRESS_MASK; + return; + + case 29: + emu8k->hwcf1 = val; + return; + case 30: + emu8k->hwcf2 = val; + return; + case 31: + emu8k->hwcf3 = val; + return; + + default: + break; + } + break; + + case 2: + emu8k->init1[emu8k->cur_voice] = val; + /* Skip if in first/second initialization step */ + if (emu8k->init1[0] != 0x03FF) { + switch (emu8k->cur_voice) { + case 0x3: + emu8k->reverb_engine.out_mix = val & 0xFF; + break; + case 0x5: { - case 0x3: emu8k->reverb_engine.out_mix = val&0xFF; - break; - case 0x5: - { - int c; - for (c=0;c<8;c++) - { - emu8k->reverb_engine.allpass[c].feedback=(val&0xFF)/((float)0xFF); - } - } - break; - case 0x7: emu8k->reverb_engine.link_return_type = (val==0x8474)? 1:0; - break; - case 0xF: emu8k->reverb_engine.reflections[0].output_gain = ((val&0xF0)>>4)/15.0; - break; - case 0x17: emu8k->reverb_engine.reflections[1].output_gain = ((val&0xF0)>>4)/15.0; - break; - case 0x1F: emu8k->reverb_engine.reflections[2].output_gain = ((val&0xF0)>>4)/15.0; - break; - case 0x9: emu8k->reverb_engine.reflections[0].feedback = (val&0xF)/15.0; - break; - case 0xB: //emu8k->reverb_engine.reflections[0].feedback_r = (val&0xF)/15.0; - break; - case 0x11:emu8k->reverb_engine.reflections[1].feedback = (val&0xF)/15.0; - break; - case 0x13: //emu8k->reverb_engine.reflections[1].feedback_r = (val&0xF)/15.0; - break; - case 0x19: emu8k->reverb_engine.reflections[2].feedback = (val&0xF)/15.0; - break; - case 0x1B: //emu8k->reverb_engine.reflections[2].feedback_r = (val&0xF)/15.0; - break; + for (uint8_t c = 0; c < 8; c++) { + emu8k->reverb_engine.allpass[c].feedback = (val & 0xFF) / ((float) 0xFF); + } } - } - return; - - case 3: - emu8k->init3[emu8k->cur_voice] = val; - /* Skip if in first/second initialization step */ - if (emu8k->init1[0] != 0x03FF) - { - switch(emu8k->cur_voice) - { - case 9: - emu8k->chorus_engine.feedback = (val&0xFF); - break; - case 12: - /* Limiting this to a sane value given our buffer. */ - emu8k->chorus_engine.delay_samples_central = (val&0x1FFF); - break; - - case 1: emu8k->reverb_engine.refl_in_amp = val&0xFF; - break; - case 3: //emu8k->reverb_engine.refl_in_amp_r = val&0xFF; - break; - } - } - return; - - case 4: - emu8k->voice[emu8k->cur_voice].envvol = val; - emu8k->voice[emu8k->cur_voice].vol_envelope.delay_samples = ENVVOL_TO_EMU_SAMPLES(val); - return; - - case 5: - { - emu8k->voice[emu8k->cur_voice].dcysusv = val; - emu8k_envelope_t * const vol_env = &emu8k->voice[emu8k->cur_voice].vol_envelope; - int old_on=emu8k->voice[emu8k->cur_voice].env_engine_on; - emu8k->voice[emu8k->cur_voice].env_engine_on = DCYSUSV_GENERATOR_ENGINE_ON(val); - - if (emu8k->voice[emu8k->cur_voice].env_engine_on && - old_on != emu8k->voice[emu8k->cur_voice].env_engine_on) - { - if (emu8k->hwcf3 != 0x04) - { - /* This is a hack for some programs like Doom or cubic player 1.7 that don't initialize - the hwcfg and init registers (doom does not init the card at all. only tests the cfg registers) */ - emu8k->hwcf3 = 0x04; - } - - //reset lfos. - emu8k->voice[emu8k->cur_voice].lfo1_count.addr = 0; - emu8k->voice[emu8k->cur_voice].lfo2_count.addr = 0; - // Trigger envelopes - if (ATKHLDV_TRIGGER(emu8k->voice[emu8k->cur_voice].atkhldv)) - { - vol_env->value_amp_hz = 0; - if (vol_env->delay_samples) - { - vol_env->state = ENV_DELAY; - } - else if (vol_env->attack_amount_amp_hz == 0) - { - vol_env->state = ENV_STOPPED; - } - else - { - vol_env->state = ENV_ATTACK; - /* TODO: Verify if "never attack" means eternal mute, - * or it means skip attack, go to hold". - if (vol_env->attack_amount == 0) - { - vol_env->value = (1 << 21); - vol_env->state = ENV_HOLD; - }*/ - } - } - - if (ATKHLD_TRIGGER(emu8k->voice[emu8k->cur_voice].atkhld)) - { - emu8k_envelope_t* const mod_env = &emu8k->voice[emu8k->cur_voice].mod_envelope; - mod_env->value_amp_hz = 0; - mod_env->value_db_oct = 0; - if (mod_env->delay_samples) - { - mod_env->state = ENV_DELAY; - } - else if (mod_env->attack_amount_amp_hz == 0) - { - mod_env->state = ENV_STOPPED; - } - else - { - mod_env->state = ENV_ATTACK; - /* TODO: Verify if "never attack" means eternal start, - * or it means skip attack, go to hold". - if (mod_env->attack_amount == 0) - { - mod_env->value = (1 << 21); - mod_env->state = ENV_HOLD; - }*/ - } - } - } - - - /* Converting the input in dBs to envelope value range. */ - vol_env->sustain_value_db_oct = DCYSUSV_SUS_TO_ENV_RANGE(DCYSUSV_SUSVALUE_GET(val)); - vol_env->ramp_amount_db_oct = env_decay_to_dbs_or_oct[DCYSUSV_DECAYRELEASE_GET(val)]; - if (DCYSUSV_IS_RELEASE(val)) - { - if (vol_env->state == ENV_DELAY || vol_env->state == ENV_ATTACK || vol_env->state == ENV_HOLD) - { - vol_env->value_db_oct = env_vol_amplitude_to_db[vol_env->value_amp_hz >> 5] << 5; - if (vol_env->value_db_oct > (1 << 21)) - vol_env->value_db_oct = 1 << 21; - } - - vol_env->state = (vol_env->value_db_oct >= vol_env->sustain_value_db_oct) ? ENV_RAMP_DOWN : ENV_RAMP_UP; - } - } - return; - - case 6: - emu8k->voice[emu8k->cur_voice].envval = val; - emu8k->voice[emu8k->cur_voice].mod_envelope.delay_samples = ENVVAL_TO_EMU_SAMPLES(val); - return; - - case 7: - { - //TODO: Look for a bug on delay (first trigger it works, next trigger it doesn't) - emu8k->voice[emu8k->cur_voice].dcysus = val; - emu8k_envelope_t* const mod_env = &emu8k->voice[emu8k->cur_voice].mod_envelope; - /* Converting the input in octaves to envelope value range. */ - mod_env->sustain_value_db_oct = DCYSUS_SUS_TO_ENV_RANGE(DCYSUS_SUSVALUE_GET(val)); - mod_env->ramp_amount_db_oct = env_decay_to_dbs_or_oct[DCYSUS_DECAYRELEASE_GET(val)]; - if (DCYSUS_IS_RELEASE(val)) - { - if (mod_env->state == ENV_DELAY || mod_env->state == ENV_ATTACK || mod_env->state == ENV_HOLD) - { - mod_env->value_db_oct = env_mod_hertz_to_octave[mod_env->value_amp_hz >> 9] << 9; - if (mod_env->value_db_oct >= (1 << 21)) - mod_env->value_db_oct = (1 << 21)-1; - } - - mod_env->state = (mod_env->value_db_oct >= mod_env->sustain_value_db_oct) ? ENV_RAMP_DOWN : ENV_RAMP_UP; - } - } - return; - } - break; - - case 0xA02: /*Data2. also known as BLASTER+0x802 and EMU+0x402 */ - switch (emu8k->cur_reg) - { - case 0: - { - emu8k_voice_t *emu_voice = &emu8k->voice[emu8k->cur_voice]; - WRITE16(addr, emu_voice->ccca, val); - emu_voice->addr.int_address = emu_voice->ccca & EMU8K_MEM_ADDRESS_MASK; - uint32_t paramq = CCCA_FILTQ_GET(emu_voice->ccca); - emu_voice->filt_att = filter_atten[paramq]; - emu_voice->filterq_idx = paramq; - } - return; - - case 1: - switch (emu8k->cur_voice) - { - case 9: - WRITE16(addr, emu8k->hwcf4, val); - /* Skip if in first/second initialization step */ - if (emu8k->init1[0] != 0x03FF) - { - /*(1/256th of a 44Khz sample) */ - /* clip the value to a reasonable value given our buffer */ - int32_t tmp = emu8k->hwcf4&0x1FFFFF; - emu8k->chorus_engine.delay_offset_samples_right = ((double)tmp)/256.0; - } - return; - case 10: - WRITE16(addr, emu8k->hwcf5, val); - /* Skip if in first/second initialization step */ - if (emu8k->init1[0] != 0x03FF) - { - /* The scale of this value is unknown. I've taken it as milliHz. - * Another interpretation could be periods. (and so, Hz = 1/period)*/ - double osc_speed = emu8k->hwcf5;//*1.316; -#if 1 // milliHz - /*milliHz to lfotable samples.*/ - osc_speed *= 65.536/44100.0; -#elif 0 //periods - /* 44.1Khz ticks to lfotable samples.*/ - osc_speed = 65.536/osc_speed; + break; + case 0x7: + emu8k->reverb_engine.link_return_type = (val == 0x8474) ? 1 : 0; + break; + case 0xF: + emu8k->reverb_engine.reflections[0].output_gain = ((val & 0xF0) >> 4) / 15.0; + break; + case 0x17: + emu8k->reverb_engine.reflections[1].output_gain = ((val & 0xF0) >> 4) / 15.0; + break; + case 0x1F: + emu8k->reverb_engine.reflections[2].output_gain = ((val & 0xF0) >> 4) / 15.0; + break; + case 0x9: + emu8k->reverb_engine.reflections[0].feedback = (val & 0xF) / 15.0; + break; + case 0xB: +#if 0 + emu8k->reverb_engine.reflections[0].feedback_r = (val&0xF)/15.0; #endif - /*left shift 32bits for 32.32 fixed.point*/ - osc_speed *= 65536.0*65536.0; - emu8k->chorus_engine.lfo_inc.addr = (uint64_t)osc_speed; + break; + case 0x11: + emu8k->reverb_engine.reflections[1].feedback = (val & 0xF) / 15.0; + break; + case 0x13: +#if 0 + emu8k->reverb_engine.reflections[1].feedback_r = (val&0xF)/15.0; +#endif + break; + case 0x19: + emu8k->reverb_engine.reflections[2].feedback = (val & 0xF) / 15.0; + break; + case 0x1B: +#if 0 + emu8k->reverb_engine.reflections[2].feedback_r = (val&0xF)/15.0; +#endif + break; + + default: + break; + } + } + return; + + case 3: + emu8k->init3[emu8k->cur_voice] = val; + /* Skip if in first/second initialization step */ + if (emu8k->init1[0] != 0x03FF) { + switch (emu8k->cur_voice) { + case 9: + emu8k->chorus_engine.feedback = (val & 0xFF); + break; + case 12: + /* Limiting this to a sane value given our buffer. */ + emu8k->chorus_engine.delay_samples_central = (val & 0x1FFF); + break; + + case 1: + emu8k->reverb_engine.refl_in_amp = val & 0xFF; + break; + case 3: +#if 0 + emu8k->reverb_engine.refl_in_amp_r = val&0xFF; +#endif + break; + + default: + break; + } + } + return; + + case 4: + emu8k->voice[emu8k->cur_voice].envvol = val; + emu8k->voice[emu8k->cur_voice].vol_envelope.delay_samples = ENVVOL_TO_EMU_SAMPLES(val); + return; + + case 5: + { + emu8k->voice[emu8k->cur_voice].dcysusv = val; + emu8k_envelope_t *const vol_env = &emu8k->voice[emu8k->cur_voice].vol_envelope; + int old_on = emu8k->voice[emu8k->cur_voice].env_engine_on; + emu8k->voice[emu8k->cur_voice].env_engine_on = DCYSUSV_GENERATOR_ENGINE_ON(val); + + if (emu8k->voice[emu8k->cur_voice].env_engine_on && old_on != emu8k->voice[emu8k->cur_voice].env_engine_on) { + if (emu8k->hwcf3 != 0x04) { + /* This is a hack for some programs like Doom or cubic player 1.7 that don't initialize + the hwcfg and init registers (doom does not init the card at all. only tests the cfg registers) */ + emu8k->hwcf3 = 0x04; + } + + // reset lfos. + emu8k->voice[emu8k->cur_voice].lfo1_count.addr = 0; + emu8k->voice[emu8k->cur_voice].lfo2_count.addr = 0; + // Trigger envelopes + if (ATKHLDV_TRIGGER(emu8k->voice[emu8k->cur_voice].atkhldv)) { + vol_env->value_amp_hz = 0; + if (vol_env->delay_samples) { + vol_env->state = ENV_DELAY; + } else if (vol_env->attack_amount_amp_hz == 0) { + vol_env->state = ENV_STOPPED; + } else { + vol_env->state = ENV_ATTACK; + /* TODO: Verify if "never attack" means eternal mute, + * or it means skip attack, go to hold". + if (vol_env->attack_amount == 0) + { + vol_env->value = (1 << 21); + vol_env->state = ENV_HOLD; + }*/ } - return; - /* Actually, these two might be command words rather than registers, or some LFO position/buffer reset.*/ - case 13: - WRITE16(addr, emu8k->hwcf6, val); - return; - case 14: - WRITE16(addr, emu8k->hwcf7, val); - return; + } - case 20: /*Top 8 bits are for Empty (MT) bit or non-addressable.*/ - WRITE16(addr, emu8k->smalr, val&0xFF); - dmareadbit=0x8000; - return; - case 21: /*Top 8 bits are for Empty (MT) bit or non-addressable.*/ - WRITE16(addr, emu8k->smarr, val&0xFF); - dmareadbit=0x8000; - return; - case 22: /*Top 8 bits are for full bit or non-addressable.*/ - WRITE16(addr, emu8k->smalw, val&0xFF); - return; - case 23: /*Top 8 bits are for full bit or non-addressable.*/ - WRITE16(addr, emu8k->smarw, val&0xFF); - return; + if (ATKHLD_TRIGGER(emu8k->voice[emu8k->cur_voice].atkhld)) { + emu8k_envelope_t *const mod_env = &emu8k->voice[emu8k->cur_voice].mod_envelope; + mod_env->value_amp_hz = 0; + mod_env->value_db_oct = 0; + if (mod_env->delay_samples) { + mod_env->state = ENV_DELAY; + } else if (mod_env->attack_amount_amp_hz == 0) { + mod_env->state = ENV_STOPPED; + } else { + mod_env->state = ENV_ATTACK; + /* TODO: Verify if "never attack" means eternal start, + * or it means skip attack, go to hold". + if (mod_env->attack_amount == 0) + { + mod_env->value = (1 << 21); + mod_env->state = ENV_HOLD; + }*/ + } + } + } - case 26: - dmawritebit=0x8000; - EMU8K_WRITE(emu8k, emu8k->smarw, val); - emu8k->smarw++; - return; + /* Converting the input in dBs to envelope value range. */ + vol_env->sustain_value_db_oct = DCYSUSV_SUS_TO_ENV_RANGE(DCYSUSV_SUSVALUE_GET(val)); + vol_env->ramp_amount_db_oct = env_decay_to_dbs_or_oct[DCYSUSV_DECAYRELEASE_GET(val)]; + if (DCYSUSV_IS_RELEASE(val)) { + if (vol_env->state == ENV_DELAY || vol_env->state == ENV_ATTACK || vol_env->state == ENV_HOLD) { + vol_env->value_db_oct = env_vol_amplitude_to_db[vol_env->value_amp_hz >> 5] << 5; + if (vol_env->value_db_oct > (1 << 21)) + vol_env->value_db_oct = 1 << 21; + } + + vol_env->state = (vol_env->value_db_oct >= vol_env->sustain_value_db_oct) ? ENV_RAMP_DOWN : ENV_RAMP_UP; + } + } + return; + + case 6: + emu8k->voice[emu8k->cur_voice].envval = val; + emu8k->voice[emu8k->cur_voice].mod_envelope.delay_samples = ENVVAL_TO_EMU_SAMPLES(val); + return; + + case 7: + { + // TODO: Look for a bug on delay (first trigger it works, next trigger it doesn't) + emu8k->voice[emu8k->cur_voice].dcysus = val; + emu8k_envelope_t *const mod_env = &emu8k->voice[emu8k->cur_voice].mod_envelope; + /* Converting the input in octaves to envelope value range. */ + mod_env->sustain_value_db_oct = DCYSUS_SUS_TO_ENV_RANGE(DCYSUS_SUSVALUE_GET(val)); + mod_env->ramp_amount_db_oct = env_decay_to_dbs_or_oct[DCYSUS_DECAYRELEASE_GET(val)]; + if (DCYSUS_IS_RELEASE(val)) { + if (mod_env->state == ENV_DELAY || mod_env->state == ENV_ATTACK || mod_env->state == ENV_HOLD) { + mod_env->value_db_oct = env_mod_hertz_to_octave[mod_env->value_amp_hz >> 9] << 9; + if (mod_env->value_db_oct >= (1 << 21)) + mod_env->value_db_oct = (1 << 21) - 1; + } + + mod_env->state = (mod_env->value_db_oct >= mod_env->sustain_value_db_oct) ? ENV_RAMP_DOWN : ENV_RAMP_UP; + } + } + return; + + default: + break; + } + break; + + case 0xA02: /*Data2. also known as BLASTER+0x802 and EMU+0x402 */ + switch (emu8k->cur_reg) { + case 0: + { + emu8k_voice_t *emu_voice = &emu8k->voice[emu8k->cur_voice]; + WRITE16(addr, emu_voice->ccca, val); + emu_voice->addr.int_address = emu_voice->ccca & EMU8K_MEM_ADDRESS_MASK; + uint32_t paramq = CCCA_FILTQ_GET(emu_voice->ccca); + emu_voice->filt_att = filter_atten[paramq]; + emu_voice->filterq_idx = paramq; + } + return; + + case 1: + switch (emu8k->cur_voice) { + case 9: + WRITE16(addr, emu8k->hwcf4, val); + /* Skip if in first/second initialization step */ + if (emu8k->init1[0] != 0x03FF) { + /*(1/256th of a 44Khz sample) */ + /* clip the value to a reasonable value given our buffer */ + int32_t tmp = emu8k->hwcf4 & 0x1FFFFF; + emu8k->chorus_engine.delay_offset_samples_right = ((double) tmp) / 256.0; + } + return; + case 10: + WRITE16(addr, emu8k->hwcf5, val); + /* Skip if in first/second initialization step */ + if (emu8k->init1[0] != 0x03FF) { + /* The scale of this value is unknown. I've taken it as milliHz. + * Another interpretation could be periods. (and so, Hz = 1/period)*/ + double osc_speed = emu8k->hwcf5; //*1.316; +#if 1 // milliHz + /*milliHz to lfotable samples.*/ + osc_speed *= 65.536 / 44100.0; +#elif 0 // periods + /* 44.1Khz ticks to lfotable samples.*/ + osc_speed = 65.536 / osc_speed; +#endif + /*left shift 32bits for 32.32 fixed.point*/ + osc_speed *= 65536.0 * 65536.0; + emu8k->chorus_engine.lfo_inc.addr = (uint64_t) osc_speed; + } + return; + /* Actually, these two might be command words rather than registers, or some LFO position/buffer reset.*/ + case 13: + WRITE16(addr, emu8k->hwcf6, val); + return; + case 14: + WRITE16(addr, emu8k->hwcf7, val); + return; + + case 20: /*Top 8 bits are for Empty (MT) bit or non-addressable.*/ + WRITE16(addr, emu8k->smalr, val & 0xFF); + dmareadbit = 0x8000; + return; + case 21: /*Top 8 bits are for Empty (MT) bit or non-addressable.*/ + WRITE16(addr, emu8k->smarr, val & 0xFF); + dmareadbit = 0x8000; + return; + case 22: /*Top 8 bits are for full bit or non-addressable.*/ + WRITE16(addr, emu8k->smalw, val & 0xFF); + return; + case 23: /*Top 8 bits are for full bit or non-addressable.*/ + WRITE16(addr, emu8k->smarw, val & 0xFF); + return; + + case 26: + dmawritebit = 0x8000; + EMU8K_WRITE(emu8k, emu8k->smarw, val); + emu8k->smarw++; + return; + + default: + break; + } + break; + + case 2: + emu8k->init2[emu8k->cur_voice] = val; + /* Skip if in first/second initialization step */ + if (emu8k->init1[0] != 0x03FF) { + switch (emu8k->cur_voice) { + case 0x14: + { + int multip = ((val & 0xF00) >> 8) + 18; + emu8k->reverb_engine.reflections[5].bufsize = multip * REV_BUFSIZE_STEP; + emu8k->reverb_engine.tailL.bufsize = (multip + 1) * REV_BUFSIZE_STEP; + if (emu8k->reverb_engine.link_return_type == 0) { + emu8k->reverb_engine.tailR.bufsize = (multip + 1) * REV_BUFSIZE_STEP; + } + } + break; + case 0x16: + if (emu8k->reverb_engine.link_return_type == 1) { + int multip = ((val & 0xF00) >> 8) + 18; + emu8k->reverb_engine.tailR.bufsize = (multip + 1) * REV_BUFSIZE_STEP; + } + break; + case 0x7: + emu8k->reverb_engine.reflections[3].output_gain = ((val & 0xF0) >> 4) / 15.0; + break; + case 0xf: + emu8k->reverb_engine.reflections[4].output_gain = ((val & 0xF0) >> 4) / 15.0; + break; + case 0x17: + emu8k->reverb_engine.reflections[5].output_gain = ((val & 0xF0) >> 4) / 15.0; + break; + case 0x1d: + { + for (uint8_t c = 0; c < 6; c++) { + emu8k->reverb_engine.reflections[c].damp1 = (val & 0xFF) / 255.0; + emu8k->reverb_engine.reflections[c].damp2 = (0xFF - (val & 0xFF)) / 255.0; + emu8k->reverb_engine.reflections[c].filterstore = 0; + } + emu8k->reverb_engine.damper.damp1 = (val & 0xFF) / 255.0; + emu8k->reverb_engine.damper.damp2 = (0xFF - (val & 0xFF)) / 255.0; + emu8k->reverb_engine.damper.filterstore = 0; + } + break; + case 0x1f: /* filter r */ + break; + case 0x1: + emu8k->reverb_engine.reflections[3].feedback = (val & 0xF) / 15.0; + break; + case 0x3: +#if 0 + emu8k->reverb_engine.reflections[3].feedback_r = (val&0xF)/15.0; +#endif + break; + case 0x9: + emu8k->reverb_engine.reflections[4].feedback = (val & 0xF) / 15.0; + break; + case 0xb: +#if 0 + emu8k->reverb_engine.reflections[4].feedback_r = (val&0xF)/15.0; +#endif + break; + case 0x11: + emu8k->reverb_engine.reflections[5].feedback = (val & 0xF) / 15.0; + break; + case 0x13: +#if 0 + emu8k->reverb_engine.reflections[5].feedback_r = (val&0xF)/15.0; +#endif + break; + + default: + break; + } + } + return; + + case 3: + emu8k->init4[emu8k->cur_voice] = val; + /* Skip if in first/second initialization step */ + if (emu8k->init1[0] != 0x03FF) { + switch (emu8k->cur_voice) { + case 0x3: + { + int32_t samples = ((val & 0xFF) * emu8k->chorus_engine.delay_samples_central) >> 8; + emu8k->chorus_engine.lfodepth_multip = samples; + } + break; + + case 0x1F: + emu8k->reverb_engine.link_return_amp = val & 0xFF; + break; + + default: + break; + } + } + return; + + case 4: + { + emu8k->voice[emu8k->cur_voice].atkhldv = val; + emu8k_envelope_t *const vol_env = &emu8k->voice[emu8k->cur_voice].vol_envelope; + vol_env->attack_samples = env_attack_to_samples[ATKHLDV_ATTACK(val)]; + if (vol_env->attack_samples == 0) { + vol_env->attack_amount_amp_hz = 0; + } else { + /* Linear amplitude increase each sample. */ + vol_env->attack_amount_amp_hz = (1 << 21) / vol_env->attack_samples; + } + vol_env->hold_samples = ATKHLDV_HOLD_TO_EMU_SAMPLES(val); + if (ATKHLDV_TRIGGER(val) && emu8k->voice[emu8k->cur_voice].env_engine_on) { + /*TODO: I assume that "envelope trigger" is the same as new note + * (since changing the IP can be done when modulating pitch too) */ + emu8k->voice[emu8k->cur_voice].lfo1_count.addr = 0; + emu8k->voice[emu8k->cur_voice].lfo2_count.addr = 0; + + vol_env->value_amp_hz = 0; + if (vol_env->delay_samples) { + vol_env->state = ENV_DELAY; + } else if (vol_env->attack_amount_amp_hz == 0) { + vol_env->state = ENV_STOPPED; + } else { + vol_env->state = ENV_ATTACK; + /* TODO: Verify if "never attack" means eternal mute, + * or it means skip attack, go to hold". + if (vol_env->attack_amount == 0) + { + vol_env->value = (1 << 21); + vol_env->state = ENV_HOLD; + }*/ + } + } + } + return; + + case 5: + emu8k->voice[emu8k->cur_voice].lfo1val = val; + /* TODO: verify if this is set once, or set every time. */ + emu8k->voice[emu8k->cur_voice].lfo1_delay_samples = LFOxVAL_TO_EMU_SAMPLES(val); + return; + + case 6: + { + emu8k->voice[emu8k->cur_voice].atkhld = val; + emu8k_envelope_t *const mod_env = &emu8k->voice[emu8k->cur_voice].mod_envelope; + mod_env->attack_samples = env_attack_to_samples[ATKHLD_ATTACK(val)]; + if (mod_env->attack_samples == 0) { + mod_env->attack_amount_amp_hz = 0; + } else { + /* Linear amplitude increase each sample. */ + mod_env->attack_amount_amp_hz = (1 << 21) / mod_env->attack_samples; + } + mod_env->hold_samples = ATKHLD_HOLD_TO_EMU_SAMPLES(val); + if (ATKHLD_TRIGGER(val) && emu8k->voice[emu8k->cur_voice].env_engine_on) { + mod_env->value_amp_hz = 0; + mod_env->value_db_oct = 0; + if (mod_env->delay_samples) { + mod_env->state = ENV_DELAY; + } else if (mod_env->attack_amount_amp_hz == 0) { + mod_env->state = ENV_STOPPED; + } else { + mod_env->state = ENV_ATTACK; + /* TODO: Verify if "never attack" means eternal start, + * or it means skip attack, go to hold". + if (mod_env->attack_amount == 0) + { + mod_env->value = (1 << 21); + mod_env->state = ENV_HOLD; + }*/ + } + } + } + return; + + case 7: + emu8k->voice[emu8k->cur_voice].lfo2val = val; + emu8k->voice[emu8k->cur_voice].lfo2_delay_samples = LFOxVAL_TO_EMU_SAMPLES(val); + + return; + + default: + break; + } + break; + + case 0xE00: /*Data3. also known as BLASTER+0xC00 and EMU+0x800 */ + switch (emu8k->cur_reg) { + case 0: + emu8k->voice[emu8k->cur_voice].ip = val; + emu8k->voice[emu8k->cur_voice].ptrx_pit_target = freqtable[val] >> 18; + return; + + case 1: + { + emu8k_voice_t *const the_voice = &emu8k->voice[emu8k->cur_voice]; + if ((val & 0xFF) == 0 && the_voice->cvcf_curr_volume == 0 && the_voice->vtft_vol_target == 0 + && the_voice->dcysusv == 0x80 && the_voice->ip == 0) { + // Patch to avoid some clicking noises with Impulse tracker or other software that sets + // different values to 0 to set noteoff, but here, 0 means no attenuation = full volume. + return; + } + the_voice->ifatn = val; + the_voice->initial_att = (((int32_t) the_voice->ifatn_attenuation << 21) / 0xFF); + the_voice->vtft_vol_target = attentable[the_voice->ifatn_attenuation]; + + the_voice->initial_filter = (((int32_t) the_voice->ifatn_init_filter << 21) / 0xFF); + if (the_voice->ifatn_init_filter == 0xFF) { + the_voice->vtft_filter_target = 0xFFFF; + } else { + the_voice->vtft_filter_target = the_voice->initial_filter >> 5; + } + } + return; + + case 2: + { + emu8k_voice_t *const the_voice = &emu8k->voice[emu8k->cur_voice]; + the_voice->pefe = val; + + int divider = (the_voice->pefe_modenv_filter_height < 0) ? 0x80 : 0x7F; + the_voice->fixed_modenv_filter_height = ((int32_t) the_voice->pefe_modenv_filter_height) * 0x4000 / divider; + + divider = (the_voice->pefe_modenv_pitch_height < 0) ? 0x80 : 0x7F; + the_voice->fixed_modenv_pitch_height = ((int32_t) the_voice->pefe_modenv_pitch_height) * 0x4000 / divider; + } + return; + + case 3: + { + emu8k_voice_t *const the_voice = &emu8k->voice[emu8k->cur_voice]; + the_voice->fmmod = val; + + int divider = (the_voice->fmmod_lfo1_filt_mod < 0) ? 0x80 : 0x7F; + the_voice->fixed_lfo1_filt_mod = ((int32_t) the_voice->fmmod_lfo1_filt_mod) * 0x4000 / divider; + + divider = (the_voice->fmmod_lfo1_vibrato < 0) ? 0x80 : 0x7F; + the_voice->fixed_lfo1_vibrato = ((int32_t) the_voice->fmmod_lfo1_vibrato) * 0x4000 / divider; + } + return; + + case 4: + { + emu8k_voice_t *const the_voice = &emu8k->voice[emu8k->cur_voice]; + the_voice->tremfrq = val; + the_voice->lfo1_speed = lfofreqtospeed[the_voice->tremfrq_lfo1_freq]; + + int divider = (the_voice->tremfrq_lfo1_tremolo < 0) ? 0x80 : 0x7F; + the_voice->fixed_lfo1_tremolo = ((int32_t) the_voice->tremfrq_lfo1_tremolo) * 0x4000 / divider; + } + return; + + case 5: + { + emu8k_voice_t *const the_voice = &emu8k->voice[emu8k->cur_voice]; + the_voice->fm2frq2 = val; + the_voice->lfo2_speed = lfofreqtospeed[the_voice->fm2frq2_lfo2_freq]; + + int divider = (the_voice->fm2frq2_lfo2_vibrato < 0) ? 0x80 : 0x7F; + the_voice->fixed_lfo2_vibrato = ((int32_t) the_voice->fm2frq2_lfo2_vibrato) * 0x4000 / divider; + } + return; + + case 7: /*ID? I believe that this allows applications to know if the emu is in use by another application */ + emu8k->id = val; + return; + + default: + break; + } + break; + + case 0xE02: /* Pointer. also known as BLASTER+0xC02 and EMU+0x802 */ + emu8k->cur_voice = (val & 31); + emu8k->cur_reg = ((val >> 5) & 7); + return; + + default: + break; + } + emu8k_log("EMU8K WRITE: Unknown register write: %04X-%02X(%d/%d): %04X \n", addr, (emu8k->cur_reg) << 5 | emu8k->cur_voice, + emu8k->cur_reg, emu8k->cur_voice, val); +} + +uint8_t +emu8k_inb(uint16_t addr, void *priv) +{ + /* Reading a single byte is a feature that at least Impulse tracker uses, + * but only on detection code and not for odd addresses.*/ + if (addr & 1) + return emu8k_inw(addr & ~1, priv) >> 1; + return emu8k_inw(addr, priv) & 0xff; +} + +void +emu8k_outb(uint16_t addr, uint8_t val, void *priv) +{ + /* TODO: AWE32 docs says that you cannot write in bytes, but if + * an app were to use this implementation, the content of the LS Byte would be lost.*/ + if (addr & 1) + emu8k_outw(addr & ~1, val << 8, priv); + else + emu8k_outw(addr, val, priv); +} + +/* TODO: This is not a correct emulation, just a workalike implementation. */ +void +emu8k_work_chorus(int32_t *inbuf, int32_t *outbuf, emu8k_chorus_eng_t *engine, int count) +{ + for (int pos = 0; pos < count; pos++) { + double lfo_inter1 = chortable[engine->lfo_pos.int_address]; +#if 0 + double lfo_inter2 = chortable[(engine->lfo_pos.int_address+1)&0xFFFF]; +#endif + + double offset_lfo = lfo_inter1; //= lfo_inter1 + ((lfo_inter2-lfo_inter1)*engine->lfo_pos.fract_address/65536.0); + offset_lfo *= engine->lfodepth_multip; + + /* Work left */ + double readdouble = (double) engine->write - (double) engine->delay_samples_central - offset_lfo; + int read = (int32_t) floor(readdouble); + int fraction_part = (readdouble - (double) read) * 65536.0; + int next_value = read + 1; + if (read < 0) { + read += EMU8K_LFOCHORUS_SIZE; + if (next_value < 0) + next_value += EMU8K_LFOCHORUS_SIZE; + } else if (next_value >= EMU8K_LFOCHORUS_SIZE) { + next_value -= EMU8K_LFOCHORUS_SIZE; + if (read >= EMU8K_LFOCHORUS_SIZE) + read -= EMU8K_LFOCHORUS_SIZE; + } + int32_t dat1 = engine->chorus_left_buffer[read]; + int32_t dat2 = engine->chorus_left_buffer[next_value]; + dat1 += ((dat2 - dat1) * fraction_part) >> 16; + + engine->chorus_left_buffer[engine->write] = *inbuf + ((dat1 * engine->feedback) >> 8); + + /* Work right */ + readdouble = (double) engine->write - (double) engine->delay_samples_central - engine->delay_offset_samples_right - offset_lfo; + read = (int32_t) floor(readdouble); + next_value = read + 1; + if (read < 0) { + read += EMU8K_LFOCHORUS_SIZE; + if (next_value < 0) + next_value += EMU8K_LFOCHORUS_SIZE; + } else if (next_value >= EMU8K_LFOCHORUS_SIZE) { + next_value -= EMU8K_LFOCHORUS_SIZE; + if (read >= EMU8K_LFOCHORUS_SIZE) + read -= EMU8K_LFOCHORUS_SIZE; + } + int32_t dat3 = engine->chorus_right_buffer[read]; + int32_t dat4 = engine->chorus_right_buffer[next_value]; + dat3 += ((dat4 - dat3) * fraction_part) >> 16; + + engine->chorus_right_buffer[engine->write] = *inbuf + ((dat3 * engine->feedback) >> 8); + + ++engine->write; + engine->write %= EMU8K_LFOCHORUS_SIZE; + engine->lfo_pos.addr += engine->lfo_inc.addr; + engine->lfo_pos.int_address &= 0xFFFF; + + (*outbuf++) += dat1; + (*outbuf++) += dat3; + inbuf++; + } +} + +int32_t +emu8k_reverb_comb_work(emu8k_reverb_combfilter_t *comb, int32_t in) +{ + + int32_t bufin; + /* get echo */ + int32_t output = comb->reflection[comb->read_pos]; + /* apply lowpass */ + comb->filterstore = (output * comb->damp2) + (comb->filterstore * comb->damp1); + /* appply feedback */ + bufin = in - (comb->filterstore * comb->feedback); + /* store new value in delayed buffer */ + comb->reflection[comb->read_pos] = bufin; + + if (++comb->read_pos >= comb->bufsize) + comb->read_pos = 0; + + return output * comb->output_gain; +} + +int32_t +emu8k_reverb_diffuser_work(emu8k_reverb_combfilter_t *comb, int32_t in) +{ + + int32_t bufout = comb->reflection[comb->read_pos]; + /*diffuse*/ + int32_t bufin = -in + (bufout * comb->feedback); + int32_t output = bufout - (bufin * comb->feedback); + /* store new value in delayed buffer */ + comb->reflection[comb->read_pos] = bufin; + + if (++comb->read_pos >= comb->bufsize) + comb->read_pos = 0; + + return output; +} + +int32_t +emu8k_reverb_tail_work(emu8k_reverb_combfilter_t *comb, emu8k_reverb_combfilter_t *allpasses, int32_t in) +{ + int32_t output = comb->reflection[comb->read_pos]; + /* store new value in delayed buffer */ + comb->reflection[comb->read_pos] = in; + +#if 0 + output = emu8k_reverb_allpass_work(&allpasses[0],output); +#endif + output = emu8k_reverb_diffuser_work(&allpasses[1], output); + output = emu8k_reverb_diffuser_work(&allpasses[2], output); +#if 0 + output = emu8k_reverb_allpass_work(&allpasses[3],output); +#endif + + if (++comb->read_pos >= comb->bufsize) + comb->read_pos = 0; + + return output; +} +int32_t +emu8k_reverb_damper_work(emu8k_reverb_combfilter_t *comb, int32_t in) +{ + /* apply lowpass */ + comb->filterstore = (in * comb->damp2) + (comb->filterstore * comb->damp1); + return comb->filterstore; +} + +/* TODO: This is not a correct emulation, just a workalike implementation. */ +void +emu8k_work_reverb(int32_t *inbuf, int32_t *outbuf, emu8k_reverb_eng_t *engine, int count) +{ + int pos; + if (engine->link_return_type) { + for (pos = 0; pos < count; pos++) { + int32_t dat1; + int32_t dat2; + int32_t in; + int32_t in2; + in = emu8k_reverb_damper_work(&engine->damper, inbuf[pos]); + in2 = (in * engine->refl_in_amp) >> 8; + dat2 = emu8k_reverb_comb_work(&engine->reflections[0], in2); + dat2 += emu8k_reverb_comb_work(&engine->reflections[1], in2); + dat1 = emu8k_reverb_comb_work(&engine->reflections[2], in2); + dat2 += emu8k_reverb_comb_work(&engine->reflections[3], in2); + dat1 += emu8k_reverb_comb_work(&engine->reflections[4], in2); + dat2 += emu8k_reverb_comb_work(&engine->reflections[5], in2); + + dat1 += (emu8k_reverb_tail_work(&engine->tailL, &engine->allpass[0], in + dat1) * engine->link_return_amp) >> 8; + dat2 += (emu8k_reverb_tail_work(&engine->tailR, &engine->allpass[4], in + dat2) * engine->link_return_amp) >> 8; + + (*outbuf++) += (dat1 * engine->out_mix) >> 8; + (*outbuf++) += (dat2 * engine->out_mix) >> 8; + } + } else { + for (pos = 0; pos < count; pos++) { + int32_t dat1; + int32_t dat2; + int32_t in; + int32_t in2; + in = emu8k_reverb_damper_work(&engine->damper, inbuf[pos]); + in2 = (in * engine->refl_in_amp) >> 8; + dat1 = emu8k_reverb_comb_work(&engine->reflections[0], in2); + dat1 += emu8k_reverb_comb_work(&engine->reflections[1], in2); + dat1 += emu8k_reverb_comb_work(&engine->reflections[2], in2); + dat1 += emu8k_reverb_comb_work(&engine->reflections[3], in2); + dat1 += emu8k_reverb_comb_work(&engine->reflections[4], in2); + dat1 += emu8k_reverb_comb_work(&engine->reflections[5], in2); + dat2 = dat1; + + dat1 += (emu8k_reverb_tail_work(&engine->tailL, &engine->allpass[0], in + dat1) * engine->link_return_amp) >> 8; + dat2 += (emu8k_reverb_tail_work(&engine->tailR, &engine->allpass[4], in + dat2) * engine->link_return_amp) >> 8; + + (*outbuf++) += (dat1 * engine->out_mix) >> 8; + (*outbuf++) += (dat2 * engine->out_mix) >> 8; + } + } +} +void +emu8k_work_eq(UNUSED(int32_t *inoutbuf), UNUSED(int count)) +{ + // TODO: Work EQ over buf +} + +int32_t +emu8k_vol_slide(emu8k_slide_t *slide, int32_t target) +{ + if (slide->last < target) { + slide->last += 0x400; + if (slide->last > target) + slide->last = target; + } else if (slide->last > target) { + slide->last -= 0x400; + if (slide->last < target) + slide->last = target; + } + return slide->last; +} + +#if 0 +int32_t old_pitch[32] = { 0 }; +int32_t old_cut[32] = { 0 }; +int32_t old_vol[32] = { 0 }; +#endif +void +emu8k_update(emu8k_t *emu8k) +{ + int new_pos = (sound_pos_global * FREQ_44100) / SOUND_FREQ; + if (emu8k->pos >= new_pos) + return; + + int32_t *buf; + emu8k_voice_t *emu_voice; + int pos; + + /* Clean the buffers since we will accumulate into them. */ + buf = &emu8k->buffer[emu8k->pos * 2]; + memset(buf, 0, 2 * (new_pos - emu8k->pos) * sizeof(emu8k->buffer[0])); + memset(&emu8k->chorus_in_buffer[emu8k->pos], 0, (new_pos - emu8k->pos) * sizeof(emu8k->chorus_in_buffer[0])); + memset(&emu8k->reverb_in_buffer[emu8k->pos], 0, (new_pos - emu8k->pos) * sizeof(emu8k->reverb_in_buffer[0])); + + /* Voices section */ + for (uint8_t c = 0; c < 32; c++) { + emu_voice = &emu8k->voice[c]; + buf = &emu8k->buffer[emu8k->pos * 2]; + + for (pos = emu8k->pos; pos < new_pos; pos++) { + int32_t dat; + + if (emu_voice->cvcf_curr_volume) { + /* Waveform oscillator */ +#ifdef RESAMPLER_LINEAR + dat = EMU8K_READ_INTERP_LINEAR(emu8k, emu_voice->addr.int_address, + emu_voice->addr.fract_address); + +#elif defined RESAMPLER_CUBIC + dat = EMU8K_READ_INTERP_CUBIC(emu8k, emu_voice->addr.int_address, + emu_voice->addr.fract_address); +#endif + + /* Filter section */ + if (emu_voice->filterq_idx || emu_voice->cvcf_curr_filt_ctoff != 0xFFFF) { + int cutoff = emu_voice->cvcf_curr_filt_ctoff >> 8; + const int64_t coef0 = filt_coeffs[emu_voice->filterq_idx][cutoff][0]; + const int64_t coef1 = filt_coeffs[emu_voice->filterq_idx][cutoff][1]; + const int64_t coef2 = filt_coeffs[emu_voice->filterq_idx][cutoff][2]; +/* clip at twice the range */ +#define ClipBuffer(buf) (buf < -16777216) ? -16777216 : (buf > 16777216) ? 16777216 \ + : buf + +#ifdef FILTER_INITIAL +# define NOOP(x) (void) x; + NOOP(coef1) + /* Apply expected attenuation. (FILTER_MOOG does it implicitly, but this one doesn't). + * Work in 24bits. */ + dat = (dat * emu_voice->filt_att) >> 8; + + int64_t vhp = ((-emu_voice->filt_buffer[0] * coef2) >> 24) - emu_voice->filt_buffer[1] - dat; + emu_voice->filt_buffer[1] += (emu_voice->filt_buffer[0] * coef0) >> 24; + emu_voice->filt_buffer[0] += (vhp * coef0) >> 24; + dat = (int32_t) (emu_voice->filt_buffer[1] >> 8); + if (dat > 32767) { + dat = 32767; + } else if (dat < -32768) { + dat = -32768; + } + +#elif defined FILTER_MOOG + + /*move to 24bits*/ + dat <<= 8; + + dat -= (coef2 * emu_voice->filt_buffer[4]) >> 24; /*feedback*/ + int64_t t1 = emu_voice->filt_buffer[1]; + emu_voice->filt_buffer[1] = ((dat + emu_voice->filt_buffer[0]) * coef0 - emu_voice->filt_buffer[1] * coef1) >> 24; + emu_voice->filt_buffer[1] = ClipBuffer(emu_voice->filt_buffer[1]); + + int64_t t2 = emu_voice->filt_buffer[2]; + emu_voice->filt_buffer[2] = ((emu_voice->filt_buffer[1] + t1) * coef0 - emu_voice->filt_buffer[2] * coef1) >> 24; + emu_voice->filt_buffer[2] = ClipBuffer(emu_voice->filt_buffer[2]); + + int64_t t3 = emu_voice->filt_buffer[3]; + emu_voice->filt_buffer[3] = ((emu_voice->filt_buffer[2] + t2) * coef0 - emu_voice->filt_buffer[3] * coef1) >> 24; + emu_voice->filt_buffer[3] = ClipBuffer(emu_voice->filt_buffer[3]); + + emu_voice->filt_buffer[4] = ((emu_voice->filt_buffer[3] + t3) * coef0 - emu_voice->filt_buffer[4] * coef1) >> 24; + emu_voice->filt_buffer[4] = ClipBuffer(emu_voice->filt_buffer[4]); + + emu_voice->filt_buffer[0] = ClipBuffer(dat); + + dat = (int32_t) (emu_voice->filt_buffer[4] >> 8); + if (dat > 32767) { + dat = 32767; + } else if (dat < -32768) { + dat = -32768; + } + +#elif defined FILTER_CONSTANT + + /* Apply expected attenuation. (FILTER_MOOG does it implicitly, but this one is constant gain). + * Also stay at 24bits.*/ + dat = (dat * emu_voice->filt_att) >> 8; + + emu_voice->filt_buffer[0] = (coef1 * emu_voice->filt_buffer[0] + + coef0 * (dat + ((coef2 * (emu_voice->filt_buffer[0] - emu_voice->filt_buffer[1])) >> 24))) + >> 24; + emu_voice->filt_buffer[1] = (coef1 * emu_voice->filt_buffer[1] + + coef0 * emu_voice->filt_buffer[0]) + >> 24; + + emu_voice->filt_buffer[0] = ClipBuffer(emu_voice->filt_buffer[0]); + emu_voice->filt_buffer[1] = ClipBuffer(emu_voice->filt_buffer[1]); + + dat = (int32_t) (emu_voice->filt_buffer[1] >> 8); + if (dat > 32767) { + dat = 32767; + } else if (dat < -32768) { + dat = -32768; + } + +#endif + } + if ((emu8k->hwcf3 & 0x04) && !CCCA_DMA_ACTIVE(emu_voice->ccca)) { + /*volume and pan*/ + dat = (dat * emu_voice->cvcf_curr_volume) >> 16; + + (*buf++) += (dat * emu_voice->vol_l) >> 8; + (*buf++) += (dat * emu_voice->vol_r) >> 8; + + /* Effects section */ + if (emu_voice->ptrx_revb_send > 0) { + emu8k->reverb_in_buffer[pos] += (dat * emu_voice->ptrx_revb_send) >> 8; + } + if (emu_voice->csl_chor_send > 0) { + emu8k->chorus_in_buffer[pos] += (dat * emu_voice->csl_chor_send) >> 8; + } + } + } + + if (emu_voice->env_engine_on) { + int32_t attenuation = emu_voice->initial_att; + int32_t filtercut = emu_voice->initial_filter; + int32_t currentpitch = emu_voice->ip; + /* run envelopes */ + emu8k_envelope_t *volenv = &emu_voice->vol_envelope; + switch (volenv->state) { + case ENV_DELAY: + volenv->delay_samples--; + if (volenv->delay_samples <= 0) { + volenv->state = ENV_ATTACK; + volenv->delay_samples = 0; + } + attenuation = 0x1FFFFF; + break; + + case ENV_ATTACK: + /* Attack amount is in linear amplitude */ + volenv->value_amp_hz += volenv->attack_amount_amp_hz; + if (volenv->value_amp_hz >= (1 << 21)) { + volenv->value_amp_hz = 1 << 21; + volenv->value_db_oct = 0; + if (volenv->hold_samples) { + volenv->state = ENV_HOLD; + } else { + /* RAMP_UP since db value is inverted and it is 0 at this point. */ + volenv->state = ENV_RAMP_UP; + } + } + attenuation += env_vol_amplitude_to_db[volenv->value_amp_hz >> 5] << 5; + break; + + case ENV_HOLD: + volenv->hold_samples--; + if (volenv->hold_samples <= 0) { + volenv->state = ENV_RAMP_UP; + } + attenuation += volenv->value_db_oct; + break; + + case ENV_RAMP_DOWN: + /* Decay/release amount is in fraction of dBs and is always positive */ + volenv->value_db_oct -= volenv->ramp_amount_db_oct; + if (volenv->value_db_oct <= volenv->sustain_value_db_oct) { + volenv->value_db_oct = volenv->sustain_value_db_oct; + volenv->state = ENV_SUSTAIN; + } + attenuation += volenv->value_db_oct; + break; + + case ENV_RAMP_UP: + /* Decay/release amount is in fraction of dBs and is always positive */ + volenv->value_db_oct += volenv->ramp_amount_db_oct; + if (volenv->value_db_oct >= volenv->sustain_value_db_oct) { + volenv->value_db_oct = volenv->sustain_value_db_oct; + volenv->state = ENV_SUSTAIN; + } + attenuation += volenv->value_db_oct; + break; + + case ENV_SUSTAIN: + attenuation += volenv->value_db_oct; + break; + + case ENV_STOPPED: + attenuation = 0x1FFFFF; + break; + + default: + break; + } + + emu8k_envelope_t *modenv = &emu_voice->mod_envelope; + switch (modenv->state) { + case ENV_DELAY: + modenv->delay_samples--; + if (modenv->delay_samples <= 0) { + modenv->state = ENV_ATTACK; + modenv->delay_samples = 0; } break; - case 2: - emu8k->init2[emu8k->cur_voice] = val; - /* Skip if in first/second initialization step */ - if (emu8k->init1[0] != 0x03FF) - { - switch(emu8k->cur_voice) - { - case 0x14: - { - int multip = ((val&0xF00)>>8)+18; - emu8k->reverb_engine.reflections[5].bufsize = multip*REV_BUFSIZE_STEP; - emu8k->reverb_engine.tailL.bufsize = (multip+1)*REV_BUFSIZE_STEP; - if ( emu8k->reverb_engine.link_return_type == 0) - { - emu8k->reverb_engine.tailR.bufsize = (multip+1)*REV_BUFSIZE_STEP; - } - } - break; - case 0x16: - if ( emu8k->reverb_engine.link_return_type == 1) - { - int multip = ((val&0xF00)>>8)+18; - emu8k->reverb_engine.tailR.bufsize = (multip+1)*REV_BUFSIZE_STEP; - } - break; - case 0x7: emu8k->reverb_engine.reflections[3].output_gain = ((val&0xF0)>>4)/15.0; - break; - case 0xf: emu8k->reverb_engine.reflections[4].output_gain = ((val&0xF0)>>4)/15.0; - break; - case 0x17: emu8k->reverb_engine.reflections[5].output_gain = ((val&0xF0)>>4)/15.0; - break; - case 0x1d: - { - int c; - for (c=0;c<6;c++) - { - emu8k->reverb_engine.reflections[c].damp1=(val&0xFF)/255.0; - emu8k->reverb_engine.reflections[c].damp2=(0xFF-(val&0xFF))/255.0; - emu8k->reverb_engine.reflections[c].filterstore=0; - } - emu8k->reverb_engine.damper.damp1=(val&0xFF)/255.0; - emu8k->reverb_engine.damper.damp2=(0xFF-(val&0xFF))/255.0; - emu8k->reverb_engine.damper.filterstore=0; - } - break; - case 0x1f: /* filter r */ - break; - case 0x1: emu8k->reverb_engine.reflections[3].feedback = (val&0xF)/15.0; - break; - case 0x3: //emu8k->reverb_engine.reflections[3].feedback_r = (val&0xF)/15.0; - break; - case 0x9: emu8k->reverb_engine.reflections[4].feedback = (val&0xF)/15.0; - break; - case 0xb: //emu8k->reverb_engine.reflections[4].feedback_r = (val&0xF)/15.0; - break; - case 0x11: emu8k->reverb_engine.reflections[5].feedback = (val&0xF)/15.0; - break; - case 0x13: //emu8k->reverb_engine.reflections[5].feedback_r = (val&0xF)/15.0; - break; - } + case ENV_ATTACK: + /* Attack amount is in linear amplitude */ + modenv->value_amp_hz += modenv->attack_amount_amp_hz; + modenv->value_db_oct = env_mod_hertz_to_octave[modenv->value_amp_hz >> 5] << 5; + if (modenv->value_amp_hz >= (1 << 21)) { + modenv->value_amp_hz = 1 << 21; + modenv->value_db_oct = 1 << 21; + if (modenv->hold_samples) { + modenv->state = ENV_HOLD; + } else { + modenv->state = ENV_RAMP_DOWN; + } } - return; + break; - case 3: - emu8k->init4[emu8k->cur_voice] = val; - /* Skip if in first/second initialization step */ - if (emu8k->init1[0] != 0x03FF) - { - switch(emu8k->cur_voice) - { - case 0x3: - { - int32_t samples = ((val&0xFF)*emu8k->chorus_engine.delay_samples_central) >> 8; - emu8k->chorus_engine.lfodepth_multip = samples; - - } - break; - - case 0x1F: - emu8k->reverb_engine.link_return_amp = val&0xFF; - break; - } + case ENV_HOLD: + modenv->hold_samples--; + if (modenv->hold_samples <= 0) { + modenv->state = ENV_RAMP_UP; } - return ; + break; - case 4: - { - emu8k->voice[emu8k->cur_voice].atkhldv = val; - emu8k_envelope_t* const vol_env = &emu8k->voice[emu8k->cur_voice].vol_envelope; - vol_env->attack_samples = env_attack_to_samples[ATKHLDV_ATTACK(val)]; - if (vol_env->attack_samples == 0) - { - vol_env->attack_amount_amp_hz = 0; - } - else - { - /* Linear amplitude increase each sample. */ - vol_env->attack_amount_amp_hz = (1<<21) / vol_env->attack_samples; - } - vol_env->hold_samples = ATKHLDV_HOLD_TO_EMU_SAMPLES(val); - if (ATKHLDV_TRIGGER(val) && emu8k->voice[emu8k->cur_voice].env_engine_on) - { - /*TODO: I assume that "envelope trigger" is the same as new note - * (since changing the IP can be done when modulating pitch too) */ - emu8k->voice[emu8k->cur_voice].lfo1_count.addr = 0; - emu8k->voice[emu8k->cur_voice].lfo2_count.addr = 0; - - vol_env->value_amp_hz = 0; - if (vol_env->delay_samples) - { - vol_env->state = ENV_DELAY; - } - else if (vol_env->attack_amount_amp_hz == 0) - { - vol_env->state = ENV_STOPPED; - } - else - { - vol_env->state = ENV_ATTACK; - /* TODO: Verify if "never attack" means eternal mute, - * or it means skip attack, go to hold". - if (vol_env->attack_amount == 0) - { - vol_env->value = (1 << 21); - vol_env->state = ENV_HOLD; - }*/ - } - } + case ENV_RAMP_DOWN: + /* Decay/release amount is in fraction of octave and is always positive */ + modenv->value_db_oct -= modenv->ramp_amount_db_oct; + if (modenv->value_db_oct <= modenv->sustain_value_db_oct) { + modenv->value_db_oct = modenv->sustain_value_db_oct; + modenv->state = ENV_SUSTAIN; } - return; - - case 5: - emu8k->voice[emu8k->cur_voice].lfo1val = val; - /* TODO: verify if this is set once, or set every time. */ - emu8k->voice[emu8k->cur_voice].lfo1_delay_samples = LFOxVAL_TO_EMU_SAMPLES(val); - return; + break; - case 6: - { - emu8k->voice[emu8k->cur_voice].atkhld = val; - emu8k_envelope_t* const mod_env = &emu8k->voice[emu8k->cur_voice].mod_envelope; - mod_env->attack_samples = env_attack_to_samples[ATKHLD_ATTACK(val)]; - if (mod_env->attack_samples == 0) - { - mod_env->attack_amount_amp_hz = 0; - } - else - { - /* Linear amplitude increase each sample. */ - mod_env->attack_amount_amp_hz = (1<<21) / mod_env->attack_samples; - } - mod_env->hold_samples = ATKHLD_HOLD_TO_EMU_SAMPLES(val); - if (ATKHLD_TRIGGER(val) && emu8k->voice[emu8k->cur_voice].env_engine_on) - { - mod_env->value_amp_hz = 0; - mod_env->value_db_oct = 0; - if (mod_env->delay_samples) - { - mod_env->state = ENV_DELAY; - } - else if (mod_env->attack_amount_amp_hz == 0) - { - mod_env->state = ENV_STOPPED; - } - else - { - mod_env->state = ENV_ATTACK; - /* TODO: Verify if "never attack" means eternal start, - * or it means skip attack, go to hold". - if (mod_env->attack_amount == 0) - { - mod_env->value = (1 << 21); - mod_env->state = ENV_HOLD; - }*/ - } - } + case ENV_RAMP_UP: + /* Decay/release amount is in fraction of octave and is always positive */ + modenv->value_db_oct += modenv->ramp_amount_db_oct; + if (modenv->value_db_oct >= modenv->sustain_value_db_oct) { + modenv->value_db_oct = modenv->sustain_value_db_oct; + modenv->state = ENV_SUSTAIN; } - return; - - case 7: - emu8k->voice[emu8k->cur_voice].lfo2val = val; - emu8k->voice[emu8k->cur_voice].lfo2_delay_samples = LFOxVAL_TO_EMU_SAMPLES(val); + break; - return; + default: + break; } - break; - - case 0xE00: /*Data3. also known as BLASTER+0xC00 and EMU+0x800 */ - switch (emu8k->cur_reg) - { - case 0: - emu8k->voice[emu8k->cur_voice].ip = val; - emu8k->voice[emu8k->cur_voice].ptrx_pit_target = freqtable[val] >> 18; - return; - - case 1: - { - emu8k_voice_t * const the_voice = &emu8k->voice[emu8k->cur_voice]; - if ((val&0xFF) == 0 && the_voice->cvcf_curr_volume == 0 && the_voice->vtft_vol_target == 0 - && the_voice->dcysusv == 0x80 && the_voice->ip == 0) - { - // Patch to avoid some clicking noises with Impulse tracker or other software that sets - // different values to 0 to set noteoff, but here, 0 means no attenuation = full volume. - return; - } - the_voice->ifatn = val; - the_voice->initial_att = (((int32_t)the_voice->ifatn_attenuation <<21)/0xFF); - the_voice->vtft_vol_target = attentable[the_voice->ifatn_attenuation]; - - the_voice->initial_filter = (((int32_t)the_voice->ifatn_init_filter <<21)/0xFF); - if (the_voice->ifatn_init_filter==0xFF) - { - the_voice->vtft_filter_target = 0xFFFF; - } - else - { - the_voice->vtft_filter_target = the_voice->initial_filter >> 5; - } - } - return; - case 2: - { - emu8k_voice_t * const the_voice = &emu8k->voice[emu8k->cur_voice]; - the_voice->pefe = val; - - int divider = (the_voice->pefe_modenv_filter_height < 0) ? 0x80 : 0x7F; - the_voice->fixed_modenv_filter_height = ((int32_t)the_voice->pefe_modenv_filter_height)*0x4000/divider; - - divider = (the_voice->pefe_modenv_pitch_height < 0) ? 0x80 : 0x7F; - the_voice->fixed_modenv_pitch_height = ((int32_t)the_voice->pefe_modenv_pitch_height)*0x4000/divider; - } - return; - - case 3: - { - emu8k_voice_t * const the_voice = &emu8k->voice[emu8k->cur_voice]; - the_voice->fmmod = val; - - int divider = (the_voice->fmmod_lfo1_filt_mod < 0) ? 0x80 : 0x7F; - the_voice->fixed_lfo1_filt_mod = ((int32_t)the_voice->fmmod_lfo1_filt_mod)*0x4000/divider; - - divider = (the_voice->fmmod_lfo1_vibrato < 0) ? 0x80 : 0x7F; - the_voice->fixed_lfo1_vibrato = ((int32_t)the_voice->fmmod_lfo1_vibrato)*0x4000/divider; - } - return; - - case 4: - { - emu8k_voice_t * const the_voice = &emu8k->voice[emu8k->cur_voice]; - the_voice->tremfrq = val; - the_voice->lfo1_speed = lfofreqtospeed[the_voice->tremfrq_lfo1_freq]; - - int divider = (the_voice->tremfrq_lfo1_tremolo < 0) ? 0x80 : 0x7F; - the_voice->fixed_lfo1_tremolo = ((int32_t)the_voice->tremfrq_lfo1_tremolo)*0x4000/divider; - } - return; - - case 5: - { - emu8k_voice_t * const the_voice = &emu8k->voice[emu8k->cur_voice]; - the_voice->fm2frq2 = val; - the_voice->lfo2_speed = lfofreqtospeed[the_voice->fm2frq2_lfo2_freq]; - - int divider = (the_voice->fm2frq2_lfo2_vibrato < 0) ? 0x80 : 0x7F; - the_voice->fixed_lfo2_vibrato = ((int32_t)the_voice->fm2frq2_lfo2_vibrato)*0x4000/divider; - } - return; - - case 7: /*ID? I believe that this allows applications to know if the emu is in use by another application */ - emu8k->id = val; - return; + /* run lfos */ + if (emu_voice->lfo1_delay_samples) { + emu_voice->lfo1_delay_samples--; + } else { + emu_voice->lfo1_count.addr += emu_voice->lfo1_speed; + emu_voice->lfo1_count.int_address &= 0xFFFF; } - break; - - case 0xE02: /* Pointer. also known as BLASTER+0xC02 and EMU+0x802 */ - emu8k->cur_voice = (val & 31); - emu8k->cur_reg = ((val >> 5) & 7); - return; - } - emu8k_log("EMU8K WRITE: Unknown register write: %04X-%02X(%d/%d): %04X \n", addr, (emu8k->cur_reg)<<5|emu8k->cur_voice, - emu8k->cur_reg,emu8k->cur_voice, val); - -} - -uint8_t emu8k_inb(uint16_t addr, void *p) -{ - /* Reading a single byte is a feature that at least Impulse tracker uses, - * but only on detection code and not for odd addresses.*/ - if (addr & 1) - return emu8k_inw(addr & ~1, p) >> 1; - return emu8k_inw(addr, p) & 0xff; -} - -void emu8k_outb(uint16_t addr, uint8_t val, void *p) -{ - /* TODO: AWE32 docs says that you cannot write in bytes, but if - * an app were to use this implementation, the content of the LS Byte would be lost.*/ - if (addr & 1) - emu8k_outw(addr & ~1, val << 8, p); - else - emu8k_outw(addr, val, p); -} - -/* TODO: This is not a correct emulation, just a workalike implementation. */ -void emu8k_work_chorus(int32_t *inbuf, int32_t *outbuf, emu8k_chorus_eng_t *engine, int count) -{ - int pos; - for (pos = 0; pos < count; pos++) - { - double lfo_inter1 = chortable[engine->lfo_pos.int_address]; - // double lfo_inter2 = chortable[(engine->lfo_pos.int_address+1)&0xFFFF]; - - double offset_lfo =lfo_inter1; //= lfo_inter1 + ((lfo_inter2-lfo_inter1)*engine->lfo_pos.fract_address/65536.0); - offset_lfo *= engine->lfodepth_multip; - - /* Work left */ - double readdouble = (double)engine->write - (double)engine->delay_samples_central - offset_lfo; - int read = (int32_t)floor(readdouble); - int fraction_part = (readdouble - (double)read)*65536.0; - int next_value = read + 1; - if(read < 0) - { - read += EMU8K_LFOCHORUS_SIZE; - if(next_value < 0) next_value += EMU8K_LFOCHORUS_SIZE; + if (emu_voice->lfo2_delay_samples) { + emu_voice->lfo2_delay_samples--; + } else { + emu_voice->lfo2_count.addr += emu_voice->lfo2_speed; + emu_voice->lfo2_count.int_address &= 0xFFFF; } - else if(next_value >= EMU8K_LFOCHORUS_SIZE) - { - next_value -= EMU8K_LFOCHORUS_SIZE; - if(read >= EMU8K_LFOCHORUS_SIZE) read -= EMU8K_LFOCHORUS_SIZE; + + if (emu_voice->fixed_modenv_pitch_height) { + /* modenv range 1<<21, pitch height range 1<<14 desired range 0x1000 (+/-one octave) */ + currentpitch += ((modenv->value_db_oct >> 9) * emu_voice->fixed_modenv_pitch_height) >> 14; } - int32_t dat1 = engine->chorus_left_buffer[read]; - int32_t dat2 = engine->chorus_left_buffer[next_value]; - dat1 += ((dat2-dat1)* fraction_part) >> 16; - - engine->chorus_left_buffer[engine->write] = *inbuf + ((dat1 * engine->feedback)>>8); - - - /* Work right */ - readdouble = (double)engine->write - (double)engine->delay_samples_central - engine->delay_offset_samples_right - offset_lfo; - read = (int32_t)floor(readdouble); - next_value = read + 1; - if(read < 0) - { - read += EMU8K_LFOCHORUS_SIZE; - if(next_value < 0) next_value += EMU8K_LFOCHORUS_SIZE; + + if (emu_voice->fixed_lfo1_vibrato) { + /* table range 1<<15, pitch mod range 1<<14 desired range 0x1000 (+/-one octave) */ + int32_t lfo1_vibrato = (lfotable[emu_voice->lfo1_count.int_address] * emu_voice->fixed_lfo1_vibrato) >> 17; + currentpitch += lfo1_vibrato; } - else if(next_value >= EMU8K_LFOCHORUS_SIZE) - { - next_value -= EMU8K_LFOCHORUS_SIZE; - if(read >= EMU8K_LFOCHORUS_SIZE) read -= EMU8K_LFOCHORUS_SIZE; + if (emu_voice->fixed_lfo2_vibrato) { + /* table range 1<<15, pitch mod range 1<<14 desired range 0x1000 (+/-one octave) */ + int32_t lfo2_vibrato = (lfotable[emu_voice->lfo2_count.int_address] * emu_voice->fixed_lfo2_vibrato) >> 17; + currentpitch += lfo2_vibrato; } - int32_t dat3 = engine->chorus_right_buffer[read]; - int32_t dat4 = engine->chorus_right_buffer[next_value]; - dat3 += ((dat4-dat3)* fraction_part) >> 16; - - engine->chorus_right_buffer[engine->write] = *inbuf + ((dat3 * engine->feedback)>>8); - - ++engine->write; - engine->write %= EMU8K_LFOCHORUS_SIZE; - engine->lfo_pos.addr +=engine->lfo_inc.addr; - engine->lfo_pos.int_address &= 0xFFFF; - (*outbuf++) += dat1; - (*outbuf++) += dat3; - inbuf++; - } - -} - -int32_t emu8k_reverb_comb_work(emu8k_reverb_combfilter_t* comb, int32_t in) -{ - - int32_t bufin; - /* get echo */ - int32_t output = comb->reflection[comb->read_pos]; - /* apply lowpass */ - comb->filterstore = (output*comb->damp2) + (comb->filterstore*comb->damp1); - /* appply feedback */ - bufin = in - (comb->filterstore*comb->feedback); - /* store new value in delayed buffer */ - comb->reflection[comb->read_pos] = bufin; - - if(++comb->read_pos>=comb->bufsize) comb->read_pos = 0; - - return output*comb->output_gain; -} - -int32_t emu8k_reverb_diffuser_work(emu8k_reverb_combfilter_t* comb, int32_t in) -{ - - int32_t bufout = comb->reflection[comb->read_pos]; - /*diffuse*/ - int32_t bufin = -in + (bufout*comb->feedback); - int32_t output = bufout - (bufin*comb->feedback); - /* store new value in delayed buffer */ - comb->reflection[comb->read_pos] = bufin; - - if(++comb->read_pos>=comb->bufsize) comb->read_pos = 0; - - return output; -} - -int32_t emu8k_reverb_tail_work(emu8k_reverb_combfilter_t* comb, emu8k_reverb_combfilter_t* allpasses, int32_t in) -{ - int32_t output = comb->reflection[comb->read_pos]; - /* store new value in delayed buffer */ - comb->reflection[comb->read_pos] = in; - - //output = emu8k_reverb_allpass_work(&allpasses[0],output); - output = emu8k_reverb_diffuser_work(&allpasses[1],output); - output = emu8k_reverb_diffuser_work(&allpasses[2],output); - //output = emu8k_reverb_allpass_work(&allpasses[3],output); - - if(++comb->read_pos>=comb->bufsize) comb->read_pos = 0; - - return output; -} -int32_t emu8k_reverb_damper_work(emu8k_reverb_combfilter_t* comb, int32_t in) -{ - /* apply lowpass */ - comb->filterstore = (in*comb->damp2) + (comb->filterstore*comb->damp1); - return comb->filterstore; -} - -/* TODO: This is not a correct emulation, just a workalike implementation. */ -void emu8k_work_reverb(int32_t *inbuf, int32_t *outbuf, emu8k_reverb_eng_t *engine, int count) -{ - int pos; - if (engine->link_return_type) - { - for (pos = 0; pos < count; pos++) - { - int32_t dat1, dat2, in, in2; - in = emu8k_reverb_damper_work(&engine->damper, inbuf[pos]); - in2 = (in * engine->refl_in_amp) >> 8; - dat2 = emu8k_reverb_comb_work(&engine->reflections[0], in2); - dat2 += emu8k_reverb_comb_work(&engine->reflections[1], in2); - dat1 = emu8k_reverb_comb_work(&engine->reflections[2], in2); - dat2 += emu8k_reverb_comb_work(&engine->reflections[3], in2); - dat1 += emu8k_reverb_comb_work(&engine->reflections[4], in2); - dat2 += emu8k_reverb_comb_work(&engine->reflections[5], in2); - - dat1 += (emu8k_reverb_tail_work(&engine->tailL,&engine->allpass[0], in+dat1)*engine->link_return_amp) >> 8; - dat2 += (emu8k_reverb_tail_work(&engine->tailR,&engine->allpass[4], in+dat2)*engine->link_return_amp) >> 8; - - (*outbuf++) += (dat1 * engine->out_mix) >> 8; - (*outbuf++) += (dat2 * engine->out_mix) >> 8; + if (emu_voice->fixed_modenv_filter_height) { + /* modenv range 1<<21, pitch height range 1<<14 desired range 0x200000 (+/-full filter range) */ + filtercut += ((modenv->value_db_oct >> 9) * emu_voice->fixed_modenv_filter_height) >> 5; } - } - else - { - for (pos = 0; pos < count; pos++) - { - int32_t dat1, dat2, in, in2; - in = emu8k_reverb_damper_work(&engine->damper, inbuf[pos]); - in2 = (in * engine->refl_in_amp) >> 8; - dat1 = emu8k_reverb_comb_work(&engine->reflections[0], in2); - dat1 += emu8k_reverb_comb_work(&engine->reflections[1], in2); - dat1 += emu8k_reverb_comb_work(&engine->reflections[2], in2); - dat1 += emu8k_reverb_comb_work(&engine->reflections[3], in2); - dat1 += emu8k_reverb_comb_work(&engine->reflections[4], in2); - dat1 += emu8k_reverb_comb_work(&engine->reflections[5], in2); - dat2 = dat1; - - dat1 += (emu8k_reverb_tail_work(&engine->tailL,&engine->allpass[0], in+dat1)*engine->link_return_amp) >> 8; - dat2 += (emu8k_reverb_tail_work(&engine->tailR,&engine->allpass[4], in+dat2)*engine->link_return_amp) >> 8; - - (*outbuf++) += (dat1 * engine->out_mix) >> 8; - (*outbuf++) += (dat2 * engine->out_mix) >> 8; + + if (emu_voice->fixed_lfo1_filt_mod) { + /* table range 1<<15, pitch mod range 1<<14 desired range 0x100000 (+/-three octaves) */ + int32_t lfo1_filtmod = (lfotable[emu_voice->lfo1_count.int_address] * emu_voice->fixed_lfo1_filt_mod) >> 9; + filtercut += lfo1_filtmod; } - } -} -void emu8k_work_eq(int32_t *inoutbuf, int count) -{ - // TODO: Work EQ over buf -} - -int32_t emu8k_vol_slide(emu8k_slide_t* slide, int32_t target) -{ - if (slide->last < target) - { - slide->last+=0x400; - if (slide->last > target) slide->last = target; - } - else if (slide->last > target) - { - slide->last-=0x400; - if (slide->last < target) slide->last = target; - } - return slide->last; -} - -//int32_t old_pitch[32]={0}; -//int32_t old_cut[32]={0}; -//int32_t old_vol[32]={0}; -void emu8k_update(emu8k_t *emu8k) -{ - int new_pos = (sound_pos_global * 44100) / 48000; - if (emu8k->pos >= new_pos) - return; - - int32_t *buf; - emu8k_voice_t* emu_voice; - int pos; - int c; - - /* Clean the buffers since we will accumulate into them. */ - buf = &emu8k->buffer[emu8k->pos*2]; - memset(buf, 0, 2*(new_pos-emu8k->pos)*sizeof(emu8k->buffer[0])); - memset(&emu8k->chorus_in_buffer[emu8k->pos], 0, (new_pos-emu8k->pos)*sizeof(emu8k->chorus_in_buffer[0])); - memset(&emu8k->reverb_in_buffer[emu8k->pos], 0, (new_pos-emu8k->pos)*sizeof(emu8k->reverb_in_buffer[0])); - - /* Voices section */ - for (c = 0; c < 32; c++) - { - emu_voice = &emu8k->voice[c]; - buf = &emu8k->buffer[emu8k->pos*2]; - - for (pos = emu8k->pos; pos < new_pos; pos++) - { - int32_t dat; - - if (emu_voice->cvcf_curr_volume) - { - /* Waveform oscillator */ - #ifdef RESAMPLER_LINEAR - dat = EMU8K_READ_INTERP_LINEAR(emu8k, emu_voice->addr.int_address, - emu_voice->addr.fract_address); - - #elif defined RESAMPLER_CUBIC - dat = EMU8K_READ_INTERP_CUBIC(emu8k, emu_voice->addr.int_address, - emu_voice->addr.fract_address); - #endif - - /* Filter section */ - if (emu_voice->filterq_idx || emu_voice->cvcf_curr_filt_ctoff != 0xFFFF ) - { - int cutoff = emu_voice->cvcf_curr_filt_ctoff >> 8; - const int64_t coef0 = filt_coeffs[emu_voice->filterq_idx][cutoff][0]; - const int64_t coef1 = filt_coeffs[emu_voice->filterq_idx][cutoff][1]; - const int64_t coef2 = filt_coeffs[emu_voice->filterq_idx][cutoff][2]; - /* clip at twice the range */ - #define ClipBuffer(buf) (buf < -16777216) ? -16777216 : (buf > 16777216) ? 16777216 : buf - - #ifdef FILTER_INITIAL - #define NOOP(x) (void)x; - NOOP(coef1) - /* Apply expected attenuation. (FILTER_MOOG does it implicitly, but this one doesn't). - * Work in 24bits. */ - dat = (dat * emu_voice->filt_att) >> 8; - - int64_t vhp = ((-emu_voice->filt_buffer[0] * coef2) >> 24) - emu_voice->filt_buffer[1] - dat; - emu_voice->filt_buffer[1] += (emu_voice->filt_buffer[0] * coef0) >> 24; - emu_voice->filt_buffer[0] += (vhp * coef0) >> 24; - dat = (int32_t)(emu_voice->filt_buffer[1] >> 8); - if (dat > 32767) { dat = 32767; } - else if (dat < -32768) { dat = -32768; } - - #elif defined FILTER_MOOG - - /*move to 24bits*/ - dat <<= 8; - - dat -= (coef2 * emu_voice->filt_buffer[4]) >> 24; /*feedback*/ - int64_t t1 = emu_voice->filt_buffer[1]; - emu_voice->filt_buffer[1] = ((dat + emu_voice->filt_buffer[0]) * coef0 - emu_voice->filt_buffer[1] * coef1) >> 24; - emu_voice->filt_buffer[1] = ClipBuffer(emu_voice->filt_buffer[1]); - - int64_t t2 = emu_voice->filt_buffer[2]; - emu_voice->filt_buffer[2] = ((emu_voice->filt_buffer[1] + t1) * coef0 - emu_voice->filt_buffer[2] * coef1) >> 24; - emu_voice->filt_buffer[2] = ClipBuffer(emu_voice->filt_buffer[2]); - - int64_t t3 = emu_voice->filt_buffer[3]; - emu_voice->filt_buffer[3] = ((emu_voice->filt_buffer[2] + t2) * coef0 - emu_voice->filt_buffer[3] * coef1) >> 24; - emu_voice->filt_buffer[3] = ClipBuffer(emu_voice->filt_buffer[3]); - - emu_voice->filt_buffer[4] = ((emu_voice->filt_buffer[3] + t3) * coef0 - emu_voice->filt_buffer[4] * coef1) >> 24; - emu_voice->filt_buffer[4] = ClipBuffer(emu_voice->filt_buffer[4]); - - emu_voice->filt_buffer[0] = ClipBuffer(dat); - - dat = (int32_t)(emu_voice->filt_buffer[4] >> 8); - if (dat > 32767) { dat = 32767; } - else if (dat < -32768) { dat = -32768; } - - #elif defined FILTER_CONSTANT - - /* Apply expected attenuation. (FILTER_MOOG does it implicitly, but this one is constant gain). - * Also stay at 24bits.*/ - dat = (dat * emu_voice->filt_att) >> 8; - - emu_voice->filt_buffer[0] = (coef1 * emu_voice->filt_buffer[0] - + coef0 * (dat + - ((coef2 * (emu_voice->filt_buffer[0] - emu_voice->filt_buffer[1]))>>24)) - ) >> 24; - emu_voice->filt_buffer[1] = (coef1 * emu_voice->filt_buffer[1] - + coef0 * emu_voice->filt_buffer[0]) >> 24; - - emu_voice->filt_buffer[0] = ClipBuffer(emu_voice->filt_buffer[0]); - emu_voice->filt_buffer[1] = ClipBuffer(emu_voice->filt_buffer[1]); - - dat = (int32_t)(emu_voice->filt_buffer[1] >> 8); - if (dat > 32767) { dat = 32767; } - else if (dat < -32768) { dat = -32768; } - - #endif - - } - if (( emu8k->hwcf3 & 0x04) && !CCCA_DMA_ACTIVE(emu_voice->ccca)) - { - /*volume and pan*/ - dat = (dat * emu_voice->cvcf_curr_volume) >> 16; - - (*buf++) += (dat * emu_voice->vol_l) >> 8; - (*buf++) += (dat * emu_voice->vol_r) >> 8; - - /* Effects section */ - if (emu_voice->ptrx_revb_send > 0) - { - emu8k->reverb_in_buffer[pos]+=(dat*emu_voice->ptrx_revb_send) >> 8; - } - if (emu_voice->csl_chor_send > 0) - { - emu8k->chorus_in_buffer[pos]+=(dat*emu_voice->csl_chor_send) >> 8; - } - } - } - - if ( emu_voice->env_engine_on) - { - int32_t attenuation = emu_voice->initial_att; - int32_t filtercut = emu_voice->initial_filter; - int32_t currentpitch = emu_voice->ip; - /* run envelopes */ - emu8k_envelope_t *volenv = &emu_voice->vol_envelope; - switch (volenv->state) - { - case ENV_DELAY: - volenv->delay_samples--; - if (volenv->delay_samples <=0) - { - volenv->state=ENV_ATTACK; - volenv->delay_samples=0; - } - attenuation = 0x1FFFFF; - break; - - case ENV_ATTACK: - /* Attack amount is in linear amplitude */ - volenv->value_amp_hz += volenv->attack_amount_amp_hz; - if (volenv->value_amp_hz >= (1 << 21)) - { - volenv->value_amp_hz = 1 << 21; - volenv->value_db_oct = 0; - if (volenv->hold_samples) - { - volenv->state = ENV_HOLD; - } - else - { - /* RAMP_UP since db value is inverted and it is 0 at this point. */ - volenv->state = ENV_RAMP_UP; - } - } - attenuation += env_vol_amplitude_to_db[volenv->value_amp_hz >> 5] << 5; - break; - - case ENV_HOLD: - volenv->hold_samples--; - if (volenv->hold_samples <=0) - { - volenv->state=ENV_RAMP_UP; - } - attenuation += volenv->value_db_oct; - break; - - case ENV_RAMP_DOWN: - /* Decay/release amount is in fraction of dBs and is always positive */ - volenv->value_db_oct -= volenv->ramp_amount_db_oct; - if (volenv->value_db_oct <= volenv->sustain_value_db_oct) - { - volenv->value_db_oct = volenv->sustain_value_db_oct; - volenv->state = ENV_SUSTAIN; - } - attenuation += volenv->value_db_oct; - break; - - case ENV_RAMP_UP: - /* Decay/release amount is in fraction of dBs and is always positive */ - volenv->value_db_oct += volenv->ramp_amount_db_oct; - if (volenv->value_db_oct >= volenv->sustain_value_db_oct) - { - volenv->value_db_oct = volenv->sustain_value_db_oct; - volenv->state = ENV_SUSTAIN; - } - attenuation += volenv->value_db_oct; - break; - - case ENV_SUSTAIN: - attenuation += volenv->value_db_oct; - break; - - case ENV_STOPPED: - attenuation = 0x1FFFFF; - break; - } - - emu8k_envelope_t *modenv = &emu_voice->mod_envelope; - switch (modenv->state) - { - case ENV_DELAY: - modenv->delay_samples--; - if (modenv->delay_samples <=0) - { - modenv->state=ENV_ATTACK; - modenv->delay_samples=0; - } - break; - - case ENV_ATTACK: - /* Attack amount is in linear amplitude */ - modenv->value_amp_hz += modenv->attack_amount_amp_hz; - modenv->value_db_oct = env_mod_hertz_to_octave[modenv->value_amp_hz >> 5] << 5; - if (modenv->value_amp_hz >= (1 << 21)) - { - modenv->value_amp_hz = 1 << 21; - modenv->value_db_oct = 1 << 21; - if (modenv->hold_samples) - { - modenv->state = ENV_HOLD; - } - else - { - modenv->state = ENV_RAMP_DOWN; - } - } - break; - - case ENV_HOLD: - modenv->hold_samples--; - if (modenv->hold_samples <=0) - { - modenv->state=ENV_RAMP_UP; - } - break; - - case ENV_RAMP_DOWN: - /* Decay/release amount is in fraction of octave and is always positive */ - modenv->value_db_oct -= modenv->ramp_amount_db_oct; - if (modenv->value_db_oct <= modenv->sustain_value_db_oct) - { - modenv->value_db_oct = modenv->sustain_value_db_oct; - modenv->state = ENV_SUSTAIN; - } - break; - - case ENV_RAMP_UP: - /* Decay/release amount is in fraction of octave and is always positive */ - modenv->value_db_oct += modenv->ramp_amount_db_oct; - if (modenv->value_db_oct >= modenv->sustain_value_db_oct) - { - modenv->value_db_oct = modenv->sustain_value_db_oct; - modenv->state = ENV_SUSTAIN; - } - break; - } - - /* run lfos */ - if (emu_voice->lfo1_delay_samples) - { - emu_voice->lfo1_delay_samples--; - } - else - { - emu_voice->lfo1_count.addr += emu_voice->lfo1_speed; - emu_voice->lfo1_count.int_address &= 0xFFFF; - } - if (emu_voice->lfo2_delay_samples) - { - emu_voice->lfo2_delay_samples--; - } - else - { - emu_voice->lfo2_count.addr += emu_voice->lfo2_speed; - emu_voice->lfo2_count.int_address &= 0xFFFF; - } - - - if (emu_voice->fixed_modenv_pitch_height) - { - /* modenv range 1<<21, pitch height range 1<<14 desired range 0x1000 (+/-one octave) */ - currentpitch += ((modenv->value_db_oct>>9)*emu_voice->fixed_modenv_pitch_height) >> 14; - } - - if (emu_voice->fixed_lfo1_vibrato) - { - /* table range 1<<15, pitch mod range 1<<14 desired range 0x1000 (+/-one octave) */ - int32_t lfo1_vibrato = (lfotable[emu_voice->lfo1_count.int_address]*emu_voice->fixed_lfo1_vibrato) >> 17; - currentpitch += lfo1_vibrato; - } - if (emu_voice->fixed_lfo2_vibrato) - { - /* table range 1<<15, pitch mod range 1<<14 desired range 0x1000 (+/-one octave) */ - int32_t lfo2_vibrato = (lfotable[emu_voice->lfo2_count.int_address]*emu_voice->fixed_lfo2_vibrato) >> 17; - currentpitch += lfo2_vibrato; - } - - if (emu_voice->fixed_modenv_filter_height) - { - /* modenv range 1<<21, pitch height range 1<<14 desired range 0x200000 (+/-full filter range) */ - filtercut += ((modenv->value_db_oct>>9)*emu_voice->fixed_modenv_filter_height) >> 5; - } - - if (emu_voice->fixed_lfo1_filt_mod) - { - /* table range 1<<15, pitch mod range 1<<14 desired range 0x100000 (+/-three octaves) */ - int32_t lfo1_filtmod = (lfotable[emu_voice->lfo1_count.int_address]*emu_voice->fixed_lfo1_filt_mod) >> 9; - filtercut += lfo1_filtmod; - } - - if (emu_voice->fixed_lfo1_tremolo) - { - /* table range 1<<15, pitch mod range 1<<14 desired range 0x40000 (+/-12dBs). */ - int32_t lfo1_tremolo = (lfotable[emu_voice->lfo1_count.int_address]*emu_voice->fixed_lfo1_tremolo) >> 11; - attenuation += lfo1_tremolo; - } - - if (currentpitch > 0xFFFF) currentpitch = 0xFFFF; - if (currentpitch < 0) currentpitch = 0; - if (attenuation > 0x1FFFFF) attenuation = 0x1FFFFF; - if (attenuation < 0) attenuation = 0; - if (filtercut > 0x1FFFFF) filtercut = 0x1FFFFF; - if (filtercut < 0) filtercut = 0; - - emu_voice->vtft_vol_target = env_vol_db_to_vol_target[attenuation >> 5]; - emu_voice->vtft_filter_target = filtercut >> 5; - emu_voice->ptrx_pit_target = freqtable[currentpitch]>>18; - - } -/* -I've recopilated these sentences to get an idea of how to loop - -- Set its PSST register and its CLS register to zero to cause no loops to occur. --Setting the Loop Start Offset and the Loop End Offset to the same value, will cause the oscillator to loop the entire memory. - --Setting the PlayPosition greater than the Loop End Offset, will cause the oscillator to play in reverse, back to the Loop End Offset. - It's pretty neat, but appears to be uncontrollable (the rate at which the samples are played in reverse). - --Note that due to interpolator offset, the actual loop point is one greater than the start address --Note that due to interpolator offset, the actual loop point will end at an address one greater than the loop address --Note that the actual audio location is the point 1 word higher than this value due to interpolation offset --In programs that use the awe, they generally set the loop address as "loopaddress -1" to compensate for the above. -(Note: I am already using address+1 in the interpolators so these things are already as they should.) -*/ - emu_voice->addr.addr += ((uint64_t)emu_voice->cpf_curr_pitch) << 18; - if (emu_voice->addr.addr >= emu_voice->loop_end.addr) - { - emu_voice->addr.int_address -= (emu_voice->loop_end.int_address - emu_voice->loop_start.int_address); - emu_voice->addr.int_address &= EMU8K_MEM_ADDRESS_MASK; - } - - /* TODO: How and when are the target and current values updated */ - emu_voice->cpf_curr_pitch = emu_voice->ptrx_pit_target; - emu_voice->cvcf_curr_volume = emu8k_vol_slide(&emu_voice->volumeslide,emu_voice->vtft_vol_target); - emu_voice->cvcf_curr_filt_ctoff = emu_voice->vtft_filter_target; + if (emu_voice->fixed_lfo1_tremolo) { + /* table range 1<<15, pitch mod range 1<<14 desired range 0x40000 (+/-12dBs). */ + int32_t lfo1_tremolo = (lfotable[emu_voice->lfo1_count.int_address] * emu_voice->fixed_lfo1_tremolo) >> 11; + attenuation += lfo1_tremolo; } - - /* Update EMU voice registers. */ - emu_voice->ccca = (((uint32_t)emu_voice->ccca_qcontrol) << 24) | emu_voice->addr.int_address; - emu_voice->cpf_curr_frac_addr = emu_voice->addr.fract_address; - //if ( emu_voice->cvcf_curr_volume != old_vol[c]) { - // pclog("EMUVOL (%d):%d\n", c, emu_voice->cvcf_curr_volume); - // old_vol[c]=emu_voice->cvcf_curr_volume; - //} - //pclog("EMUFILT :%d\n", emu_voice->cvcf_curr_filt_ctoff); + if (currentpitch > 0xFFFF) + currentpitch = 0xFFFF; + if (currentpitch < 0) + currentpitch = 0; + if (attenuation > 0x1FFFFF) + attenuation = 0x1FFFFF; + if (attenuation < 0) + attenuation = 0; + if (filtercut > 0x1FFFFF) + filtercut = 0x1FFFFF; + if (filtercut < 0) + filtercut = 0; + + emu_voice->vtft_vol_target = env_vol_db_to_vol_target[attenuation >> 5]; + emu_voice->vtft_filter_target = filtercut >> 5; + emu_voice->ptrx_pit_target = freqtable[currentpitch] >> 18; + } + /* + I've recopilated these sentences to get an idea of how to loop + + - Set its PSST register and its CLS register to zero to cause no loops to occur. + -Setting the Loop Start Offset and the Loop End Offset to the same value, will cause the oscillator to loop the entire memory. + + -Setting the PlayPosition greater than the Loop End Offset, will cause the oscillator to play in reverse, back to the Loop End Offset. + It's pretty neat, but appears to be uncontrollable (the rate at which the samples are played in reverse). + + -Note that due to interpolator offset, the actual loop point is one greater than the start address + -Note that due to interpolator offset, the actual loop point will end at an address one greater than the loop address + -Note that the actual audio location is the point 1 word higher than this value due to interpolation offset + -In programs that use the awe, they generally set the loop address as "loopaddress -1" to compensate for the above. + (Note: I am already using address+1 in the interpolators so these things are already as they should.) + */ + emu_voice->addr.addr += ((uint64_t) emu_voice->cpf_curr_pitch) << 18; + if (emu_voice->addr.addr >= emu_voice->loop_end.addr) { + emu_voice->addr.int_address -= (emu_voice->loop_end.int_address - emu_voice->loop_start.int_address); + emu_voice->addr.int_address &= EMU8K_MEM_ADDRESS_MASK; + } + + /* TODO: How and when are the target and current values updated */ + emu_voice->cpf_curr_pitch = emu_voice->ptrx_pit_target; + emu_voice->cvcf_curr_volume = emu8k_vol_slide(&emu_voice->volumeslide, emu_voice->vtft_vol_target); + emu_voice->cvcf_curr_filt_ctoff = emu_voice->vtft_filter_target; } - - buf = &emu8k->buffer[emu8k->pos*2]; - emu8k_work_reverb(&emu8k->reverb_in_buffer[emu8k->pos], buf, &emu8k->reverb_engine, new_pos-emu8k->pos); - emu8k_work_chorus(&emu8k->chorus_in_buffer[emu8k->pos], buf, &emu8k->chorus_engine, new_pos-emu8k->pos); - emu8k_work_eq(buf, new_pos-emu8k->pos); - - // Clip signal - for (pos = emu8k->pos; pos < new_pos; pos++) - { - if (buf[0] < -32768) - buf[0] = -32768; - else if (buf[0] > 32767) - buf[0] = 32767; - - if (buf[1] < -32768) - buf[1] = -32768; - else if (buf[1] > 32767) - buf[1] = 32767; + /* Update EMU voice registers. */ + emu_voice->ccca = (((uint32_t) emu_voice->ccca_qcontrol) << 24) | emu_voice->addr.int_address; + emu_voice->cpf_curr_frac_addr = emu_voice->addr.fract_address; - buf += 2; +#if 0 + if (emu_voice->cvcf_curr_volume != old_vol[c]) { + pclog("EMUVOL (%d):%d\n", c, emu_voice->cvcf_curr_volume); + old_vol[c]=emu_voice->cvcf_curr_volume; } + pclog("EMUFILT :%d\n", emu_voice->cvcf_curr_filt_ctoff); +#endif + } - /* Update EMU clock. */ - emu8k->wc += (new_pos - emu8k->pos); - - emu8k->pos = new_pos; + buf = &emu8k->buffer[emu8k->pos * 2]; + emu8k_work_reverb(&emu8k->reverb_in_buffer[emu8k->pos], buf, &emu8k->reverb_engine, new_pos - emu8k->pos); + emu8k_work_chorus(&emu8k->chorus_in_buffer[emu8k->pos], buf, &emu8k->chorus_engine, new_pos - emu8k->pos); + emu8k_work_eq(buf, new_pos - emu8k->pos); + + // Clip signal + for (pos = emu8k->pos; pos < new_pos; pos++) { + if (buf[0] < -32768) + buf[0] = -32768; + else if (buf[0] > 32767) + buf[0] = 32767; + + if (buf[1] < -32768) + buf[1] = -32768; + else if (buf[1] > 32767) + buf[1] = 32767; + + buf += 2; + } + + /* Update EMU clock. */ + emu8k->wc += (new_pos - emu8k->pos); + + emu8k->pos = new_pos; } void emu8k_change_addr(emu8k_t *emu8k, uint16_t emu_addr) { - if (emu8k->addr) { - io_removehandler(emu8k->addr, 0x0004, emu8k_inb, emu8k_inw, NULL, emu8k_outb, emu8k_outw, NULL, emu8k); - io_removehandler(emu8k->addr+0x400, 0x0004, emu8k_inb, emu8k_inw, NULL, emu8k_outb, emu8k_outw, NULL, emu8k); - io_removehandler(emu8k->addr+0x800, 0x0004, emu8k_inb, emu8k_inw, NULL, emu8k_outb, emu8k_outw, NULL, emu8k); - emu8k->addr = 0; - } - if (emu_addr) { - emu8k->addr = emu_addr; - io_sethandler(emu8k->addr, 0x0004, emu8k_inb, emu8k_inw, NULL, emu8k_outb, emu8k_outw, NULL, emu8k); - io_sethandler(emu8k->addr+0x400, 0x0004, emu8k_inb, emu8k_inw, NULL, emu8k_outb, emu8k_outw, NULL, emu8k); - io_sethandler(emu8k->addr+0x800, 0x0004, emu8k_inb, emu8k_inw, NULL, emu8k_outb, emu8k_outw, NULL, emu8k); - } + if (emu8k->addr) { + io_removehandler(emu8k->addr, 0x0004, emu8k_inb, emu8k_inw, NULL, emu8k_outb, emu8k_outw, NULL, emu8k); + io_removehandler(emu8k->addr + 0x400, 0x0004, emu8k_inb, emu8k_inw, NULL, emu8k_outb, emu8k_outw, NULL, emu8k); + io_removehandler(emu8k->addr + 0x800, 0x0004, emu8k_inb, emu8k_inw, NULL, emu8k_outb, emu8k_outw, NULL, emu8k); + emu8k->addr = 0; + } + if (emu_addr) { + emu8k->addr = emu_addr; + io_sethandler(emu8k->addr, 0x0004, emu8k_inb, emu8k_inw, NULL, emu8k_outb, emu8k_outw, NULL, emu8k); + io_sethandler(emu8k->addr + 0x400, 0x0004, emu8k_inb, emu8k_inw, NULL, emu8k_outb, emu8k_outw, NULL, emu8k); + io_sethandler(emu8k->addr + 0x800, 0x0004, emu8k_inb, emu8k_inw, NULL, emu8k_outb, emu8k_outw, NULL, emu8k); + } } /* onboard_ram in kilobytes */ -void emu8k_init(emu8k_t *emu8k, uint16_t emu_addr, int onboard_ram) +void +emu8k_init(emu8k_t *emu8k, uint16_t emu_addr, int onboard_ram) { - uint32_t const BLOCK_SIZE_WORDS = 0x10000; - FILE *f; - int c; - double out; - - f = rom_fopen("roms/sound/awe32.raw", "rb"); - if (!f) - fatal("AWE32.RAW not found\n"); - - emu8k->rom = malloc(1024 * 1024); - if (fread(emu8k->rom, 1, 1048576, f) != 1048576) - fatal("emu8k_init(): Error reading data\n"); - fclose(f); - /*AWE-DUMP creates ROM images offset by 2 bytes, so if we detect this - then correct it*/ - if (emu8k->rom[3] == 0x314d && emu8k->rom[4] == 0x474d) - { - memmove(&emu8k->rom[0], &emu8k->rom[1], (1024 * 1024) - 2); - emu8k->rom[0x7ffff] = 0; - } + uint32_t const BLOCK_SIZE_WORDS = 0x10000; + FILE *fp; + int c; + double out; - emu8k->empty = malloc(2*BLOCK_SIZE_WORDS); - memset(emu8k->empty, 0, 2*BLOCK_SIZE_WORDS); + fp = rom_fopen("roms/sound/creative/awe32.raw", "rb"); + if (!fp) + fatal("AWE32.RAW not found\n"); - int j=0; - for (;j<0x8;j++) - { - emu8k->ram_pointers[j]=emu8k->rom+(j*BLOCK_SIZE_WORDS); - } - for (;j<0x20;j++) - { - emu8k->ram_pointers[j]=emu8k->empty; - } + emu8k->rom = malloc(1024 * 1024); + if (fread(emu8k->rom, 1, 1048576, fp) != 1048576) + fatal("emu8k_init(): Error reading data\n"); + fclose(fp); + /*AWE-DUMP creates ROM images offset by 2 bytes, so if we detect this + then correct it*/ + if (emu8k->rom[3] == 0x314d && emu8k->rom[4] == 0x474d) { + memmove(&emu8k->rom[0], &emu8k->rom[1], (1024 * 1024) - 2); + emu8k->rom[0x7ffff] = 0; + } - if (onboard_ram) - { - /*Clip to 28MB, since that's the max that we can address. */ - if (onboard_ram > 0x7000) onboard_ram = 0x7000; - emu8k->ram = malloc(onboard_ram * 1024); - memset(emu8k->ram, 0, onboard_ram * 1024); - const int i_end=onboard_ram>>7; - int i=0; - for(;iram_pointers[j]=emu8k->ram+(i*BLOCK_SIZE_WORDS); - } - emu8k->ram_end_addr = EMU8K_RAM_MEM_START + (onboard_ram<<9); + emu8k->empty = malloc(2 * BLOCK_SIZE_WORDS); + memset(emu8k->empty, 0, 2 * BLOCK_SIZE_WORDS); + + int j = 0; + for (; j < 0x8; j++) { + emu8k->ram_pointers[j] = emu8k->rom + (j * BLOCK_SIZE_WORDS); + } + for (; j < 0x20; j++) { + emu8k->ram_pointers[j] = emu8k->empty; + } + + if (onboard_ram) { + /*Clip to 28MB, since that's the max that we can address. */ + if (onboard_ram > 0x7000) + onboard_ram = 0x7000; + emu8k->ram = malloc(onboard_ram * 1024); + memset(emu8k->ram, 0, onboard_ram * 1024); + const int i_end = onboard_ram >> 7; + int i = 0; + for (; i < i_end; i++, j++) { + emu8k->ram_pointers[j] = emu8k->ram + (i * BLOCK_SIZE_WORDS); } + emu8k->ram_end_addr = EMU8K_RAM_MEM_START + (onboard_ram << 9); + } else { + emu8k->ram = 0; + emu8k->ram_end_addr = EMU8K_RAM_MEM_START; + } + for (; j < 0x100; j++) { + emu8k->ram_pointers[j] = emu8k->empty; + } + + emu8k_change_addr(emu8k, emu_addr); + + /*Create frequency table. (Convert initial pitch register value to a linear speed change) + * The input is encoded such as 0xe000 is center note (no pitch shift) + * and from then on , changing up or down 0x1000 (4096) increments/decrements an octave. + * Note that this is in reference to the 44.1Khz clock that the channels play at. + * The 65536 * 65536 is in order to left-shift the 32bit value to a 64bit value as a 32.32 fixed point. + */ + for (c = 0; c < 0x10000; c++) { + freqtable[c] = (uint64_t) (exp2((double) (c - 0xe000) / 4096.0) * 65536.0 * 65536.0); + } + /* Shortcut: minimum pitch equals stopped. I don't really know if this is true, but it's better + * since some programs set the pitch to 0 for unused channels. */ + freqtable[0] = 0; + + /* starting at 65535 because it is used for "volume target" register conversion. */ + out = 65535.0; + for (c = 0; c < 256; c++) { + attentable[c] = (int32_t) out; + out /= sqrt(1.09018); /*0.375 dB steps*/ + } + /* Shortcut: max attenuation is silent, not -96dB. */ + attentable[255] = 0; + + /* Note: these two tables have "db" inverted: 0 dB is max volume, 65535 "db" (-96.32dBFS) is silence. + * Important: Using 65535 as max output value because this is intended to be used with the volume target register! */ + out = 65535.0; + for (c = 0; c < 0x10000; c++) { +#if 0 + double db = -(c*6.0205999/65535.0)*16.0; + out = powf(10.f,db/20.f) * 65536.0; +#endif + env_vol_db_to_vol_target[c] = (int32_t) out; + /* calculated from the 65536th root of 65536 */ + out /= 1.00016923970; + } + /* Shortcut: max attenuation is silent, not -96dB. */ + env_vol_db_to_vol_target[0x10000 - 1] = 0; + /* One more position to accept max value being 65536. */ + env_vol_db_to_vol_target[0x10000] = 0; + + for (c = 1; c < 0x10000; c++) { + out = -680.32142884264 * 20.0 * log10(((double) c) / 65535.0); + env_vol_amplitude_to_db[c] = (int32_t) out; + } + /*Shortcut: max attenuation is silent, not -96dB.*/ + env_vol_amplitude_to_db[0] = 65535; + /* One more position to accept max value being 65536. */ + env_vol_amplitude_to_db[0x10000] = 0; + + for (c = 1; c < 0x10000; c++) { + out = log2((((double) c) / 0x10000) + 1.0) * 65536.0; + env_mod_hertz_to_octave[c] = (int32_t) out; + } + /*No hertz change, no octave change. */ + env_mod_hertz_to_octave[0] = 0; + /* One more position to accept max value being 65536. */ + env_mod_hertz_to_octave[0x10000] = 65536; + + /* This formula comes from vince vu/judge dredd's awe32p10 and corresponds to what the freebsd/linux AWE32 driver has. */ + float millis; + for (c = 0; c < 128; c++) { + if (c == 0) + millis = 0; /* This means never attack. */ + else if (c < 32) + millis = 11878.0 / c; else - { - emu8k->ram = 0; - emu8k->ram_end_addr = EMU8K_RAM_MEM_START; - } - for (;j < 0x100;j++) - { - emu8k->ram_pointers[j]=emu8k->empty; - - } + millis = 360 * exp((c - 32) / (16.0 / log(1.0 / 2.0))); - emu8k_change_addr(emu8k, emu_addr); + env_attack_to_samples[c] = 44.1 * millis; + /* This is an alternate formula with linear increments, but probably incorrect: + * millis = (256+4096*(0x7F-c)) */ + } - /*Create frequency table. (Convert initial pitch register value to a linear speed change) - * The input is encoded such as 0xe000 is center note (no pitch shift) - * and from then on , changing up or down 0x1000 (4096) increments/decrements an octave. - * Note that this is in reference to the 44.1Khz clock that the channels play at. - * The 65536 * 65536 is in order to left-shift the 32bit value to a 64bit value as a 32.32 fixed point. - */ - for (c = 0; c < 0x10000; c++) - { - freqtable[c] = (uint64_t)(exp2((double)(c - 0xe000) / 4096.0) * 65536.0 * 65536.0); - } - /* Shortcut: minimum pitch equals stopped. I don't really know if this is true, but it's better - * since some programs set the pitch to 0 for unused channels. */ - freqtable[0] = 0; + /* The LFOs use a triangular waveform starting at zero and going 1/-1/1/-1. + * This table is stored in signed 16bits precision, with a period of 65536 samples */ + for (c = 0; c < 65536; c++) { + int d = (c + 16384) & 65535; + if (d >= 32768) + lfotable[c] = 32768 + ((32768 - d) * 2); + else + lfotable[c] = (d * 2) - 32768; + } + /* The 65536 * 65536 is in order to left-shift the 32bit value to a 64bit value as a 32.32 fixed point. */ + out = 0.01; + for (c = 0; c < 256; c++) { + lfofreqtospeed[c] = (uint64_t) (out * 65536.0 / 44100.0 * 65536.0 * 65536.0); + out += 0.042; + } - /* starting at 65535 because it is used for "volume target" register conversion. */ - out = 65535.0; - for (c = 0; c < 256; c++) - { - attentable[c] = (int32_t)out; - out /= sqrt(1.09018); /*0.375 dB steps*/ - } - /* Shortcut: max attenuation is silent, not -96dB. */ - attentable[255]=0; - - /* Note: these two tables have "db" inverted: 0 dB is max volume, 65535 "db" (-96.32dBFS) is silence. - * Important: Using 65535 as max output value because this is intended to be used with the volume target register! */ - out = 65535.0; - for (c = 0; c < 0x10000; c++) - { - //double db = -(c*6.0205999/65535.0)*16.0; - //out = powf(10.f,db/20.f) * 65536.0; - env_vol_db_to_vol_target[c] = (int32_t)out; - /* calculated from the 65536th root of 65536 */ - out /= 1.00016923970; - } - /* Shortcut: max attenuation is silent, not -96dB. */ - env_vol_db_to_vol_target[0x10000-1]=0; - /* One more position to accept max value being 65536. */ - env_vol_db_to_vol_target[0x10000]=0; + for (c = 0; c < 65536; c++) { + chortable[c] = sin(c * M_PI / 32768.0); + } - for (c = 1; c < 0x10000; c++) - { - out = -680.32142884264* 20.0 * log10(((double)c)/65535.0); - env_vol_amplitude_to_db[c] = (int32_t)out; - } - /*Shortcut: max attenuation is silent, not -96dB.*/ - env_vol_amplitude_to_db[0]=65535; - /* One more position to accept max value being 65536. */ - env_vol_amplitude_to_db[0x10000]=0; - - - for (c = 1; c < 0x10000; c++) - { - out = log2((((double)c)/0x10000)+1.0) *65536.0; - env_mod_hertz_to_octave[c] = (int32_t)out; - } - /*No hertz change, no octave change. */ - env_mod_hertz_to_octave[0]=0; - /* One more position to accept max value being 65536. */ - env_mod_hertz_to_octave[0x10000]=65536; - - - /* This formula comes from vince vu/judge dredd's awe32p10 and corresponds to what the freebsd/linux AWE32 driver has. */ - float millis; - for (c=0;c<128;c++) - { - if (c==0) - millis = 0; /* This means never attack. */ - else if (c < 32) - millis = 11878.0/c; - else - millis = 360*exp((c - 32) / (16.0/log(1.0/2.0))); - - env_attack_to_samples[c] = 44.1*millis; - /* This is an alternate formula with linear increments, but probably incorrect: - * millis = (256+4096*(0x7F-c)) */ - } - - /* The LFOs use a triangular waveform starting at zero and going 1/-1/1/-1. - * This table is stored in signed 16bits precision, with a period of 65536 samples */ - for (c = 0; c < 65536; c++) - { - int d = (c + 16384) & 65535; - if (d >= 32768) - lfotable[c] = 32768 + ((32768 - d)*2); - else - lfotable[c] = (d*2) - 32768; - } - /* The 65536 * 65536 is in order to left-shift the 32bit value to a 64bit value as a 32.32 fixed point. */ - out = 0.01; - for (c = 0; c < 256; c++) - { - lfofreqtospeed[c] = (uint64_t)(out *65536.0/44100.0 * 65536.0 * 65536.0); - out += 0.042; - } - - for (c = 0; c < 65536; c++) - { - chortable[c] = sin(c*M_PI/32768.0); - } - - - /* Filter coefficients tables. Note: Values are multiplied by *16777216 to left shift 24 bits. (i.e. 8.24 fixed point) */ - int qidx; - for (qidx = 0; qidx < 16; qidx++) - { - out = 125.0; /* Start at 125Hz */ - for (c = 0; c < 256; c++) - { + /* Filter coefficients tables. Note: Values are multiplied by *16777216 to left shift 24 bits. (i.e. 8.24 fixed point) */ + for (uint8_t qidx = 0; qidx < 16; qidx++) { + out = 125.0; /* Start at 125Hz */ + for (c = 0; c < 256; c++) { #ifdef FILTER_INITIAL - float w0 = sin(2.0*M_PI*out / 44100.0); - /* The value 102.5f has been selected a bit randomly. Pretends to reach 0.2929 at w0 = 1.0 */ - float q = (qidx / 102.5f) * (1.0 + 1.0 / w0); - /* Limit max value. Else it would be 470. */ - if (q > 200) q=200; - filt_coeffs[qidx][c][0] = (int32_t)(w0 * 16777216.0); - filt_coeffs[qidx][c][1] = 16777216.0; - filt_coeffs[qidx][c][2] = (int32_t)((1.0f / (0.7071f + q)) * 16777216.0); -#elif defined FILTER_MOOG - float w0 = sin(2.0*M_PI*out / 44100.0); - float q_factor = 1.0f - w0; - float p = w0 + 0.8f * w0 * q_factor; - float f = p + p - 1.0f; - float resonance = (1.0-pow(2.0,-qidx*24.0/90.0))*0.8; - float q = resonance * (1.0f + 0.5f * q_factor * (w0 + 5.6f * q_factor * q_factor)); - filt_coeffs[qidx][c][0] = (int32_t)(p * 16777216.0); - filt_coeffs[qidx][c][1] = (int32_t)(f * 16777216.0); - filt_coeffs[qidx][c][2] = (int32_t)(q * 16777216.0); + float w0 = sin(2.0 * M_PI * out / 44100.0); + /* The value 102.5f has been selected a bit randomly. Pretends to reach 0.2929 at w0 = 1.0 */ + float q = (qidx / 102.5f) * (1.0 + 1.0 / w0); + /* Limit max value. Else it would be 470. */ + if (q > 200) + q = 200; + filt_coeffs[qidx][c][0] = (int32_t) (w0 * 16777216.0); + filt_coeffs[qidx][c][1] = 16777216.0; + filt_coeffs[qidx][c][2] = (int32_t) ((1.0f / (0.7071f + q)) * 16777216.0); +#elif defined FILTER_MOOG + float w0 = sin(2.0 * M_PI * out / 44100.0); + float q_factor = 1.0f - w0; + float p = w0 + 0.8f * w0 * q_factor; + float f = p + p - 1.0f; + float resonance = (1.0 - pow(2.0, -qidx * 24.0 / 90.0)) * 0.8; + float q = resonance * (1.0f + 0.5f * q_factor * (w0 + 5.6f * q_factor * q_factor)); + filt_coeffs[qidx][c][0] = (int32_t) (p * 16777216.0); + filt_coeffs[qidx][c][1] = (int32_t) (f * 16777216.0); + filt_coeffs[qidx][c][2] = (int32_t) (q * 16777216.0); #elif defined FILTER_CONSTANT - float q = (1.0-pow(2.0,-qidx*24.0/90.0))*0.8; - float coef0 = sin(2.0*M_PI*out / 44100.0); - float coef1 = 1.0 - coef0; - float coef2 = q * (1.0 + 1.0 / coef1); - filt_coeffs[qidx][c][0] = (int32_t)(coef0 * 16777216.0); - filt_coeffs[qidx][c][1] = (int32_t)(coef1 * 16777216.0); - filt_coeffs[qidx][c][2] = (int32_t)(coef2 * 16777216.0); -#endif //FILTER_TYPE - /* 42.66 divisions per octave (the doc says quarter seminotes which is 48, but then it would be almost an octave less) */ - out *= 1.016378315; - /* 42 divisions. This moves the max frequency to 8.5Khz.*/ - //out *= 1.0166404394; - /* This is a linear increment method, that corresponds to the NRPN table, but contradicts the EMU8KPRM doc: */ - //out = 100.0 + (c+1.0)*31.25; //31.25Hz steps */ - } + float q = (1.0 - pow(2.0, -qidx * 24.0 / 90.0)) * 0.8; + float coef0 = sin(2.0 * M_PI * out / 44100.0); + float coef1 = 1.0 - coef0; + float coef2 = q * (1.0 + 1.0 / coef1); + filt_coeffs[qidx][c][0] = (int32_t) (coef0 * 16777216.0); + filt_coeffs[qidx][c][1] = (int32_t) (coef1 * 16777216.0); + filt_coeffs[qidx][c][2] = (int32_t) (coef2 * 16777216.0); +#endif // FILTER_TYPE + /* 42.66 divisions per octave (the doc says quarter seminotes which is 48, but then it would be almost an octave less) */ + out *= 1.016378315; + /* 42 divisions. This moves the max frequency to 8.5Khz.*/ + // out *= 1.0166404394; + /* This is a linear increment method, that corresponds to the NRPN table, but contradicts the EMU8KPRM doc: */ + // out = 100.0 + (c+1.0)*31.25; //31.25Hz steps */ } - /* NOTE! read_pos and buffer content is implicitly initialized to zero by the sb_t structure memset on sb_awe32_init() */ - emu8k->reverb_engine.reflections[0].bufsize=2*REV_BUFSIZE_STEP; - emu8k->reverb_engine.reflections[1].bufsize=4*REV_BUFSIZE_STEP; - emu8k->reverb_engine.reflections[2].bufsize=8*REV_BUFSIZE_STEP; - emu8k->reverb_engine.reflections[3].bufsize=13*REV_BUFSIZE_STEP; - emu8k->reverb_engine.reflections[4].bufsize=19*REV_BUFSIZE_STEP; - emu8k->reverb_engine.reflections[5].bufsize=26*REV_BUFSIZE_STEP; + } + /* NOTE! read_pos and buffer content is implicitly initialized to zero by the sb_t structure memset on sb_awe32_init() */ + emu8k->reverb_engine.reflections[0].bufsize = 2 * REV_BUFSIZE_STEP; + emu8k->reverb_engine.reflections[1].bufsize = 4 * REV_BUFSIZE_STEP; + emu8k->reverb_engine.reflections[2].bufsize = 8 * REV_BUFSIZE_STEP; + emu8k->reverb_engine.reflections[3].bufsize = 13 * REV_BUFSIZE_STEP; + emu8k->reverb_engine.reflections[4].bufsize = 19 * REV_BUFSIZE_STEP; + emu8k->reverb_engine.reflections[5].bufsize = 26 * REV_BUFSIZE_STEP; - /*This is a bit random.*/ - for (c=0;c<4;c++) - { - emu8k->reverb_engine.allpass[3-c].feedback=0.5; - emu8k->reverb_engine.allpass[3-c].bufsize=(4*c)*REV_BUFSIZE_STEP+55; - emu8k->reverb_engine.allpass[7-c].feedback=0.5; - emu8k->reverb_engine.allpass[7-c].bufsize=(4*c)*REV_BUFSIZE_STEP+55; - } - + /*This is a bit random.*/ + for (c = 0; c < 4; c++) { + emu8k->reverb_engine.allpass[3 - c].feedback = 0.5; + emu8k->reverb_engine.allpass[3 - c].bufsize = (4 * c) * REV_BUFSIZE_STEP + 55; + emu8k->reverb_engine.allpass[7 - c].feedback = 0.5; + emu8k->reverb_engine.allpass[7 - c].bufsize = (4 * c) * REV_BUFSIZE_STEP + 55; + } - - /* Cubic Resampling ( 4point cubic spline) */ - double const resdouble = 1.0/(double)CUBIC_RESOLUTION; - for (c = 0; c < CUBIC_RESOLUTION; c++) - { - double x = (double)c * resdouble; - /* Cubic resolution is made of four table, but I've put them all in one table to optimize memory access. */ - cubic_table[c*4] = (-0.5 * x * x * x + x * x - 0.5 * x) ; - cubic_table[c*4+1] = ( 1.5 * x * x * x - 2.5 * x * x + 1.0) ; - cubic_table[c*4+2] = (-1.5 * x * x * x + 2.0 * x * x + 0.5 * x) ; - cubic_table[c*4+3] = ( 0.5 * x * x * x - 0.5 * x * x) ; - } - /* Even when the documentation says that this has to be written by applications to initialize the card, - * several applications and drivers ( aweman on windows, linux oss driver..) read it to detect an AWE card. */ - emu8k->hwcf1 = 0x59; - emu8k->hwcf2 = 0x20; - /* Initial state is muted. 0x04 is unmuted. */ - emu8k->hwcf3 = 0x00; + /* Cubic Resampling ( 4point cubic spline) */ + double const resdouble = 1.0 / (double) CUBIC_RESOLUTION; + for (c = 0; c < CUBIC_RESOLUTION; c++) { + double x = (double) c * resdouble; + /* Cubic resolution is made of four table, but I've put them all in one table to optimize memory access. */ + cubic_table[c * 4] = (-0.5 * x * x * x + x * x - 0.5 * x); + cubic_table[c * 4 + 1] = (1.5 * x * x * x - 2.5 * x * x + 1.0); + cubic_table[c * 4 + 2] = (-1.5 * x * x * x + 2.0 * x * x + 0.5 * x); + cubic_table[c * 4 + 3] = (0.5 * x * x * x - 0.5 * x * x); + } + /* Even when the documentation says that this has to be written by applications to initialize the card, + * several applications and drivers ( aweman on windows, linux oss driver..) read it to detect an AWE card. */ + emu8k->hwcf1 = 0x59; + emu8k->hwcf2 = 0x20; + /* Initial state is muted. 0x04 is unmuted. */ + emu8k->hwcf3 = 0x00; } -void emu8k_close(emu8k_t *emu8k) +void +emu8k_close(emu8k_t *emu8k) { - free(emu8k->rom); - free(emu8k->ram); + free(emu8k->rom); + free(emu8k->ram); } - diff --git a/src/sound/snd_gus.c b/src/sound/snd_gus.c index a20d7fd50..d0af5c564 100644 --- a/src/sound/snd_gus.c +++ b/src/sound/snd_gus.c @@ -1,1326 +1,1539 @@ #include #include #include -#include #include +#include #include #define HAVE_STDARG_H -#include <86box/86box.h> -#include <86box/io.h> -#include <86box/nmi.h> -#include <86box/pic.h> -#include <86box/dma.h> -#include <86box/timer.h> -#include <86box/device.h> -#include <86box/sound.h> -#include <86box/midi.h> -#include <86box/snd_ad1848.h> #include -enum -{ - MIDI_INT_RECEIVE = 0x01, - MIDI_INT_TRANSMIT = 0x02, - MIDI_INT_MASTER = 0x80 +#include <86box/86box.h> +#include <86box/device.h> +#include <86box/dma.h> +#include <86box/io.h> +#include <86box/midi.h> +#include <86box/nmi.h> +#include <86box/pic.h> +#include <86box/sound.h> +#include <86box/timer.h> +#if defined(DEV_BRANCH) && defined(USE_GUSMAX) +# include <86box/snd_ad1848.h> +#endif +#include <86box/plat_fallthrough.h> +#include <86box/plat_unused.h> + +enum { + MIDI_INT_RECEIVE = 0x01, + MIDI_INT_TRANSMIT = 0x02, + MIDI_INT_MASTER = 0x80 }; -enum -{ - MIDI_CTRL_TRANSMIT_MASK = 0x60, - MIDI_CTRL_TRANSMIT = 0x20, - MIDI_CTRL_RECEIVE = 0x80 +enum { + MIDI_CTRL_TRANSMIT_MASK = 0x60, + MIDI_CTRL_TRANSMIT = 0x20, + MIDI_CTRL_RECEIVE = 0x80 }; -enum -{ - GUS_INT_MIDI_TRANSMIT = 0x01, - GUS_INT_MIDI_RECEIVE = 0x02 +enum { + GUS_INT_MIDI_TRANSMIT = 0x01, + GUS_INT_MIDI_RECEIVE = 0x02 }; -enum -{ - GUS_TIMER_CTRL_AUTO = 0x01 +enum { + GUS_TIMER_CTRL_AUTO = 0x01 }; -enum -{ - GUS_CLASSIC = 0, - GUS_MAX = 1, +enum { + GUS_CLASSIC = 0, + GUS_MAX = 1, }; -typedef struct gus_t -{ - int reset; - - int global; - uint32_t addr,dmaaddr; - int voice; - uint32_t start[32],end[32],cur[32]; - uint32_t startx[32],endx[32],curx[32]; - int rstart[32],rend[32]; - int rcur[32]; - uint16_t freq[32]; - uint16_t rfreq[32]; - uint8_t ctrl[32]; - uint8_t rctrl[32]; - int curvol[32]; - int pan_l[32], pan_r[32]; - int t1on,t2on; - uint8_t tctrl; - uint16_t t1,t2,t1l,t2l; - uint8_t irqstatus,irqstatus2; - uint8_t adcommand; - int waveirqs[32],rampirqs[32]; - int voices; - uint8_t dmactrl; +typedef struct gus_t { + int reset; - int32_t out_l, out_r; - - int16_t buffer[2][SOUNDBUFLEN]; - int pos; - - pc_timer_t samp_timer; - uint64_t samp_latch; - - uint8_t *ram; - uint32_t gus_end_ram; - - int irqnext; - - pc_timer_t timer_1, timer_2; - - int irq, dma, irq_midi; - uint16_t base; - int latch_enable; - - uint8_t sb_2xa, sb_2xc, sb_2xe; - uint8_t sb_ctrl; - int sb_nmi; - - uint8_t reg_ctrl; - - uint8_t ad_status, ad_data; - uint8_t ad_timer_ctrl; - - uint8_t midi_ctrl, midi_status, midi_queue[64], midi_data; - int midi_r, midi_w; - int uart_in, uart_out, sysex; - - uint8_t gp1, gp2; - uint16_t gp1_addr, gp2_addr; - - uint8_t usrr; + int global; + uint32_t addr; + uint32_t dmaaddr; + int voice; + uint32_t start[32]; + uint32_t end[32]; + uint32_t cur[32]; + uint32_t startx[32]; + uint32_t endx[32]; + uint32_t curx[32]; + int rstart[32]; + int rend[32]; + int rcur[32]; + uint16_t freq[32]; + uint16_t rfreq[32]; + uint8_t ctrl[32]; + uint8_t rctrl[32]; + int curvol[32]; + int pan_l[32]; + int pan_r[32]; + int t1on; + int t2on; + uint8_t tctrl; + uint16_t t1; + uint16_t t2; + uint16_t t1l; + uint16_t t2l; + uint8_t irqstatus; + uint8_t irqstatus2; + uint8_t adcommand; + int waveirqs[32]; + int rampirqs[32]; + int voices; + uint8_t dmactrl; - uint8_t max_ctrl; + int32_t out_l; + int32_t out_r; + + int16_t buffer[2][SOUNDBUFLEN]; + int pos; + + pc_timer_t samp_timer; + uint64_t samp_latch; + + uint8_t *ram; + uint32_t gus_end_ram; + + int irqnext; + + uint8_t irq_state; + uint8_t midi_irq_state; + + pc_timer_t timer_1; + pc_timer_t timer_2; + + uint8_t type; + + int irq; + int dma; + int irq_midi; + int dma2; + uint16_t base; + int latch_enable; + + uint8_t sb_2xa; + uint8_t sb_2xc; + uint8_t sb_2xe; + uint8_t sb_ctrl; + int sb_nmi; + + uint8_t reg_ctrl; + + uint8_t ad_status; + uint8_t ad_data; + uint8_t ad_timer_ctrl; + + uint8_t midi_ctrl; + uint8_t midi_status; + uint8_t midi_queue[64]; + uint8_t midi_data; + int midi_r; + int midi_w; + int uart_in; + int uart_out; + int sysex; + + uint8_t gp1; + uint8_t gp2; + uint16_t gp1_addr; + uint16_t gp2_addr; + + uint8_t usrr; #if defined(DEV_BRANCH) && defined(USE_GUSMAX) - ad1848_t ad1848; + uint8_t max_ctrl; + + ad1848_t ad1848; #endif } gus_t; -static int gus_gf1_irqs[8] = {-1, 2, 5, 3, 7, 11, 12, 15}; -static int gus_midi_irqs[8] = {-1, 2, 5, 3, 7, 11, 12, 15}; -static int gus_dmas[8] = {-1, 1, 3, 5, 6, 7, -1, -1}; +static int gus_gf1_irqs[8] = { -1, 2, 5, 3, 7, 11, 12, 15 }; +static int gus_midi_irqs[8] = { -1, 2, 5, 3, 7, 11, 12, 15 }; +static int gus_dmas[8] = { -1, 1, 3, 5, 6, 7, -1, -1 }; -int gusfreqs[]= -{ - 44100,41160,38587,36317,34300,32494,30870,29400,28063,26843,25725,24696, - 23746,22866,22050,21289,20580,19916,19293 +int gusfreqs[] = { + 44100, 41160, 38587, 36317, 34300, 32494, 30870, 29400, 28063, 26843, 25725, 24696, + 23746, 22866, 22050, 21289, 20580, 19916, 19293 }; double vol16bit[4096]; -void gus_update_int_status(gus_t *gus) +void +gus_update_int_status(gus_t *gus) { - int c; - int irq_pending = 0; - int midi_irq_pending = 0; + int irq_pending = 0; + int midi_irq_pending = 0; + int intr_pending = 0; + int midi_intr_pending = 0; - gus->irqstatus&=~0x60; - gus->irqstatus2=0xE0; - for (c=0;c<32;c++) - { - if (gus->waveirqs[c]) - { - gus->irqstatus2=0x60|c; - if (gus->rampirqs[c]) - gus->irqstatus2 |= 0x80; - gus->irqstatus|=0x20; - irq_pending = 1; - break; - } - if (gus->rampirqs[c]) - { - gus->irqstatus2=0xA0|c; - gus->irqstatus|=0x40; - irq_pending = 1; - break; - } + gus->irqstatus &= ~0x60; + gus->irqstatus2 = 0xE0; + for (uint8_t c = 0; c < 32; c++) { + if (gus->waveirqs[c]) { + gus->irqstatus2 = 0x60 | c; + if (gus->rampirqs[c]) + gus->irqstatus2 |= 0x80; + gus->irqstatus |= 0x20; + irq_pending = 1; + break; } - if ((gus->tctrl & 4) && (gus->irqstatus & 0x04)) - irq_pending = 1; /*Timer 1 interrupt pending*/ - if ((gus->tctrl & 8) && (gus->irqstatus & 0x08)) - irq_pending = 1; /*Timer 2 interrupt pending*/ - if ((gus->irqstatus & 0x80) && (gus->dmactrl & 0x20)) - irq_pending = 1; /*DMA TC interrupt pending*/ - - midi_irq_pending = gus->midi_status & MIDI_INT_MASTER; - - if (gus->irq == gus->irq_midi && gus->irq != -1) - { - if (irq_pending || midi_irq_pending) - picintlevel(1 << gus->irq); - else - picintc(1 << gus->irq); + if (gus->rampirqs[c]) { + gus->irqstatus2 = 0xA0 | c; + gus->irqstatus |= 0x40; + irq_pending = 1; + break; } + } + if ((gus->tctrl & 4) && (gus->irqstatus & 0x04)) + irq_pending = 1; /*Timer 1 interrupt pending*/ + if ((gus->tctrl & 8) && (gus->irqstatus & 0x08)) + irq_pending = 1; /*Timer 2 interrupt pending*/ + if ((gus->irqstatus & 0x80) && (gus->dmactrl & 0x20)) + irq_pending = 1; /*DMA TC interrupt pending*/ + + midi_irq_pending = gus->midi_status & MIDI_INT_MASTER; + + if (gus->irq == gus->irq_midi) { + if (irq_pending || midi_irq_pending) + intr_pending = 1; else - { - if (gus->irq != -1) - { - if (irq_pending) - picintlevel(1 << gus->irq); - else - picintc(1 << gus->irq); - } - if (gus->irq_midi != -1) - { - if (midi_irq_pending) - picintlevel(1 << gus->irq_midi); - else - picintc(1 << gus->irq_midi); - } - } + intr_pending = 0; + } else { + if (irq_pending) + intr_pending = 1; + else + intr_pending = 0; + + if (midi_irq_pending) + midi_intr_pending = 1; + else + midi_intr_pending = 0; + } + + if (gus->irq != -1) { + if (intr_pending) + picint(1 << gus->irq); + else + picintc(1 << gus->irq); + } + + if ((gus->irq_midi != -1) && (gus->irq_midi != gus->irq)) { + if (midi_intr_pending) + picint(1 << gus->irq_midi); + else + picintc(1 << gus->irq_midi); + } } -void gus_midi_update_int_status(gus_t *gus) +void +gus_midi_update_int_status(gus_t *gus) { - gus->midi_status &= ~MIDI_INT_MASTER; - if ((gus->midi_ctrl & MIDI_CTRL_TRANSMIT_MASK) == MIDI_CTRL_TRANSMIT && (gus->midi_status & MIDI_INT_TRANSMIT)) - { - gus->midi_status |= MIDI_INT_MASTER; - gus->irqstatus |= GUS_INT_MIDI_TRANSMIT; - } - else - gus->irqstatus &= ~GUS_INT_MIDI_TRANSMIT; - - if ((gus->midi_ctrl & MIDI_CTRL_RECEIVE) && (gus->midi_status & MIDI_INT_RECEIVE)) - { - gus->midi_status |= MIDI_INT_MASTER; - gus->irqstatus |= GUS_INT_MIDI_RECEIVE; - } - else - gus->irqstatus &= ~GUS_INT_MIDI_RECEIVE; + gus->midi_status &= ~MIDI_INT_MASTER; + if ((gus->midi_ctrl & MIDI_CTRL_TRANSMIT_MASK) == MIDI_CTRL_TRANSMIT && (gus->midi_status & MIDI_INT_TRANSMIT)) { + gus->midi_status |= MIDI_INT_MASTER; + gus->irqstatus |= GUS_INT_MIDI_TRANSMIT; + } else + gus->irqstatus &= ~GUS_INT_MIDI_TRANSMIT; + if ((gus->midi_ctrl & MIDI_CTRL_RECEIVE) && (gus->midi_status & MIDI_INT_RECEIVE)) { + gus->midi_status |= MIDI_INT_MASTER; + gus->irqstatus |= GUS_INT_MIDI_RECEIVE; + } else + gus->irqstatus &= ~GUS_INT_MIDI_RECEIVE; + + gus_update_int_status(gus); +} + +void +writegus(uint16_t addr, uint8_t val, void *priv) +{ + gus_t *gus = (gus_t *) priv; + int c; + int d; + int old; + uint16_t port; +#if defined(DEV_BRANCH) && defined(USE_GUSMAX) + uint16_t csioport; +#endif + + if ((addr == 0x388) || (addr == 0x389)) + port = addr; + else + port = addr & 0xf0f; + + switch (port) { + case 0x300: /*MIDI control*/ + old = gus->midi_ctrl; + gus->midi_ctrl = val; + gus->uart_out = 1; + + if ((val & 3) == 3) { /*Master reset*/ + gus->uart_in = 0; + gus->midi_status = 0; + gus->midi_r = 0; + gus->midi_w = 0; + } else if ((old & 3) == 3) { + gus->midi_status |= MIDI_INT_TRANSMIT; + } else if (gus->midi_ctrl & MIDI_CTRL_RECEIVE) { + gus->uart_in = 1; + } + gus_midi_update_int_status(gus); + break; + case 0x301: /*MIDI data*/ + gus->midi_data = val; + if (gus->uart_out) { + midi_raw_out_byte(val); + } + if (gus->latch_enable & 0x20) { + gus->midi_status |= MIDI_INT_RECEIVE; + } else + gus->midi_status |= MIDI_INT_TRANSMIT; + break; + case 0x302: /*Voice select*/ + gus->voice = val & 31; + break; + case 0x303: /*Global select*/ + gus->global = val; + break; + case 0x304: /*Global low*/ + switch (gus->global) { + case 0: /*Voice control*/ + gus->ctrl[gus->voice] = val; + break; + case 1: /*Frequency control*/ + gus->freq[gus->voice] = (gus->freq[gus->voice] & 0xFF00) | val; + break; + case 2: /*Start addr high*/ + gus->startx[gus->voice] = (gus->startx[gus->voice] & 0xF807F) | (val << 7); + gus->start[gus->voice] = (gus->start[gus->voice] & 0x1F00FFFF) | (val << 16); + break; + case 3: /*Start addr low*/ + gus->start[gus->voice] = (gus->start[gus->voice] & 0x1FFFFF00) | val; + break; + case 4: /*End addr high*/ + gus->endx[gus->voice] = (gus->endx[gus->voice] & 0xF807F) | (val << 7); + gus->end[gus->voice] = (gus->end[gus->voice] & 0x1F00FFFF) | (val << 16); + break; + case 5: /*End addr low*/ + gus->end[gus->voice] = (gus->end[gus->voice] & 0x1FFFFF00) | val; + break; + + case 6: /*Ramp frequency*/ + gus->rfreq[gus->voice] = (int) ((double) ((val & 63) * 512) / (double) (1 << (3 * (val >> 6)))); + break; + + case 9: /*Current volume*/ + gus->curvol[gus->voice] = gus->rcur[gus->voice] = (gus->rcur[gus->voice] & ~(0xff << 6)) | (val << 6); + break; + + case 0xA: /*Current addr high*/ + gus->cur[gus->voice] = (gus->cur[gus->voice] & 0x1F00FFFF) | (val << 16); + gus->curx[gus->voice] = (gus->curx[gus->voice] & 0xF807F00) | ((val << 7) << 8); + break; + case 0xB: /*Current addr low*/ + gus->cur[gus->voice] = (gus->cur[gus->voice] & 0x1FFFFF00) | val; + break; + + case 0x42: /*DMA address low*/ + gus->dmaaddr = (gus->dmaaddr & 0xFF000) | (val << 4); + break; + + case 0x43: /*Address low*/ + gus->addr = (gus->addr & 0xFFF00) | val; + break; + case 0x45: /*Timer control*/ + gus->tctrl = val; + gus_update_int_status(gus); + break; + + default: + break; + } + break; + case 0x305: /*Global high*/ + switch (gus->global) { + case 0: /*Voice control*/ + gus->ctrl[gus->voice] = val & 0x7f; + + old = gus->waveirqs[gus->voice]; + gus->waveirqs[gus->voice] = ((val & 0xa0) == 0xa0) ? 1 : 0; + if (gus->waveirqs[gus->voice] != old) + gus_update_int_status(gus); + break; + case 1: /*Frequency control*/ + gus->freq[gus->voice] = (gus->freq[gus->voice] & 0xFF) | (val << 8); + break; + case 2: /*Start addr high*/ + gus->startx[gus->voice] = (gus->startx[gus->voice] & 0x07FFF) | (val << 15); + gus->start[gus->voice] = (gus->start[gus->voice] & 0x00FFFFFF) | ((val & 0x1F) << 24); + break; + case 3: /*Start addr low*/ + gus->startx[gus->voice] = (gus->startx[gus->voice] & 0xFFF80) | (val & 0x7F); + gus->start[gus->voice] = (gus->start[gus->voice] & 0x1FFF00FF) | (val << 8); + break; + case 4: /*End addr high*/ + gus->endx[gus->voice] = (gus->endx[gus->voice] & 0x07FFF) | (val << 15); + gus->end[gus->voice] = (gus->end[gus->voice] & 0x00FFFFFF) | ((val & 0x1F) << 24); + break; + case 5: /*End addr low*/ + gus->endx[gus->voice] = (gus->endx[gus->voice] & 0xFFF80) | (val & 0x7F); + gus->end[gus->voice] = (gus->end[gus->voice] & 0x1FFF00FF) | (val << 8); + break; + + case 6: /*Ramp frequency*/ + gus->rfreq[gus->voice] = (int) ((double) ((val & 63) * (1 << 10)) / (double) (1 << (3 * (val >> 6)))); + break; + case 7: /*Ramp start*/ + gus->rstart[gus->voice] = val << 14; + break; + case 8: /*Ramp end*/ + gus->rend[gus->voice] = val << 14; + break; + case 9: /*Current volume*/ + gus->curvol[gus->voice] = gus->rcur[gus->voice] = (gus->rcur[gus->voice] & ~(0xff << 14)) | (val << 14); + break; + + case 0xA: /*Current addr high*/ + gus->cur[gus->voice] = (gus->cur[gus->voice] & 0x00FFFFFF) | ((val & 0x1F) << 24); + gus->curx[gus->voice] = (gus->curx[gus->voice] & 0x07FFF00) | ((val << 15) << 8); + break; + case 0xB: /*Current addr low*/ + gus->cur[gus->voice] = (gus->cur[gus->voice] & 0x1FFF00FF) | (val << 8); + gus->curx[gus->voice] = (gus->curx[gus->voice] & 0xFFF8000) | ((val & 0x7F) << 8); + break; + case 0xC: /*Pan*/ + gus->pan_l[gus->voice] = 15 - (val & 0xf); + gus->pan_r[gus->voice] = (val & 0xf); + break; + case 0xD: /*Ramp control*/ + old = gus->rampirqs[gus->voice]; + gus->rctrl[gus->voice] = val & 0x7F; + gus->rampirqs[gus->voice] = ((val & 0xa0) == 0xa0) ? 1 : 0; + if (gus->rampirqs[gus->voice] != old) + gus_update_int_status(gus); + break; + + case 0xE: + gus->voices = (val & 63) + 1; + if (gus->voices > 32) + gus->voices = 32; + if (gus->voices < 14) + gus->voices = 14; + gus->global = val; + if (gus->voices < 14) + gus->samp_latch = (uint64_t) (TIMER_USEC * (1000000.0 / 44100.0)); + else + gus->samp_latch = (uint64_t) (TIMER_USEC * + (1000000.0 / gusfreqs[gus->voices - 14])); + break; + + case 0x41: /*DMA*/ + if (val & 1 && gus->dma != -1) { + if (val & 2) { + c = 0; + while (c < 65536) { + int dma_result; + if (val & 0x04) { + uint32_t gus_addr = (gus->dmaaddr & 0xc0000) | + ((gus->dmaaddr & 0x1ffff) << 1); + + if (gus_addr < gus->gus_end_ram) + d = gus->ram[gus_addr]; + else + d = 0x00; + + if ((gus_addr + 1) < gus->gus_end_ram) + d |= (gus->ram[gus_addr + 1] << 8); + + if (val & 0x80) + d ^= 0x8080; + dma_result = dma_channel_write(gus->dma, d); + if (dma_result == DMA_NODATA) + break; + } else { + if (gus->dmaaddr < gus->gus_end_ram) + d = gus->ram[gus->dmaaddr]; + else + d = 0x00; + + if (val & 0x80) + d ^= 0x80; + dma_result = dma_channel_write(gus->dma, d); + if (dma_result == DMA_NODATA) + break; + } + gus->dmaaddr++; + gus->dmaaddr &= 0xfffff; + c++; + if (dma_result & DMA_OVER) + break; + } + gus->dmactrl = val & ~0x40; + gus->irqnext = 1; + } else { + c = 0; + while (c < 65536) { + d = dma_channel_read(gus->dma); + if (d == DMA_NODATA) + break; + if (val & 0x04) { + uint32_t gus_addr = (gus->dmaaddr & 0xc0000) | + ((gus->dmaaddr & 0x1ffff) << 1); + if (val & 0x80) + d ^= 0x8080; + + if (gus_addr < gus->gus_end_ram) + gus->ram[gus_addr] = d & 0xff; + + if ((gus_addr + 1) < gus->gus_end_ram) + gus->ram[gus_addr + 1] = (d >> 8) & 0xff; + } else { + if (val & 0x80) + d ^= 0x80; + + if (gus->dmaaddr < gus->gus_end_ram) + gus->ram[gus->dmaaddr] = d; + } + gus->dmaaddr++; + gus->dmaaddr &= 0xfffff; + c++; + if (d & DMA_OVER) + break; + } + gus->dmactrl = val & ~0x40; + gus->irqnext = 1; + } + } + break; + + case 0x42: /*DMA address low*/ + gus->dmaaddr = (gus->dmaaddr & 0xFF0) | (val << 12); + break; + + case 0x43: /*Address low*/ + gus->addr = (gus->addr & 0xf00ff) | (val << 8); + break; + case 0x44: /*Address high*/ + gus->addr = (gus->addr & 0x0ffff) | ((val << 16) & 0xf0000); + break; + case 0x45: /*Timer control*/ + if (!(val & 4)) + gus->irqstatus &= ~4; + if (!(val & 8)) + gus->irqstatus &= ~8; + if (!(val & 0x20)) + gus->ad_status &= ~0x18; + if (!(val & 0x02)) + gus->ad_status &= ~0x01; + gus->tctrl = val; + gus->sb_ctrl = val; + gus_update_int_status(gus); + break; + case 0x46: /*Timer 1*/ + gus->t1 = gus->t1l = val; + gus->t1on = 1; + break; + case 0x47: /*Timer 2*/ + gus->t2 = gus->t2l = val; + gus->t2on = 1; + break; + + case 0x4c: /*Reset*/ + gus->reset = val; + break; + + default: + break; + } + break; + case 0x307: /*DRAM access*/ + if (gus->addr < gus->gus_end_ram) + gus->ram[gus->addr] = val; + gus->addr &= 0xfffff; + break; + case 0x208: + case 0x388: + gus->adcommand = val; + break; + + case 0x389: + if ((gus->tctrl & GUS_TIMER_CTRL_AUTO) || gus->adcommand != 4) { + gus->ad_data = val; + gus->ad_status |= 0x01; + if (gus->sb_ctrl & 0x02) { + if (gus->sb_nmi) + nmi_raise(); + else if (gus->irq != -1) + picint(1 << gus->irq); + } + } else if (!(gus->tctrl & GUS_TIMER_CTRL_AUTO) && gus->adcommand == 4) { + if (val & 0x80) { + gus->ad_status &= ~0x60; + } else { + gus->ad_timer_ctrl = val; + + if (val & 0x01) + gus->t1on = 1; + else + gus->t1 = gus->t1l; + + if (val & 0x02) + gus->t2on = 1; + else + gus->t2 = gus->t2l; + } + } + break; + + case 0x200: + gus->latch_enable = val; + break; + + case 0x20b: + switch (gus->reg_ctrl & 0x07) { + case 0: + if (gus->latch_enable & 0x40) { + gus->irq = gus_gf1_irqs[val & 7]; + + if (val & 0x40) { + if (gus->irq == -1) + gus->irq = gus->irq_midi = gus_gf1_irqs[(val >> 3) & 7]; + else + gus->irq_midi = gus->irq; + } else + gus->irq_midi = gus_midi_irqs[(val >> 3) & 7]; +#if defined(DEV_BRANCH) && defined(USE_GUSMAX) + if (gus->type == GUS_MAX) + ad1848_setirq(&gus->ad1848, gus->irq); +#endif + + gus->sb_nmi = val & 0x80; + } else { + gus->dma = gus_dmas[val & 7]; + + if (val & 0x40) { + if (gus->dma == -1) + gus->dma = gus->dma2 = gus_dmas[(val >> 3) & 7]; + else + gus->dma2 = gus->dma; + } else + gus->dma2 = gus_dmas[(val >> 3) & 7]; +#if defined(DEV_BRANCH) && defined(USE_GUSMAX) + if (gus->type == GUS_MAX) + ad1848_setdma(&gus->ad1848, gus->dma2); +#endif + } + break; + case 1: + gus->gp1 = val; + break; + case 2: + gus->gp2 = val; + break; + case 3: + gus->gp1_addr = val; + break; + case 4: + gus->gp2_addr = val; + break; + case 5: + gus->usrr = 0; + break; + case 6: + break; + + default: + break; + } + break; + + case 0x206: + gus->ad_status |= 0x08; + if (gus->sb_ctrl & 0x20) { + if (gus->sb_nmi) + nmi_raise(); + else if (gus->irq != -1) + picint(1 << gus->irq); + } + break; + case 0x20a: + gus->sb_2xa = val; + break; + case 0x20c: + gus->ad_status |= 0x10; + if (gus->sb_ctrl & 0x20) { + if (gus->sb_nmi) + nmi_raise(); + else if (gus->irq != -1) + picint(1 << gus->irq); + } + fallthrough; + case 0x20d: + gus->sb_2xc = val; + break; + case 0x20e: + gus->sb_2xe = val; + break; + case 0x20f: + gus->reg_ctrl = val; + break; + case 0x306: + case 0x706: +#if defined(DEV_BRANCH) && defined(USE_GUSMAX) + if (gus->type == GUS_MAX) { + if (gus->dma >= 4) + val |= 0x10; + if (gus->dma2 >= 4) + val |= 0x20; + gus->max_ctrl = (val >> 6) & 1; + if (val & 0x40) { + if ((val & 0xF) != ((addr >> 4) & 0xF)) { + csioport = 0x30c | ((addr >> 4) & 0xf); + io_removehandler(csioport, 4, + ad1848_read, NULL, NULL, + ad1848_write, NULL, NULL, &gus->ad1848); + csioport = 0x30c | ((val & 0xf) << 4); + io_sethandler(csioport, 4, + ad1848_read, NULL, NULL, + ad1848_write, NULL, NULL, &gus->ad1848); + } + } + } +#endif + break; + + default: + break; + } +} + +uint8_t +readgus(uint16_t addr, void *priv) +{ + gus_t *gus = (gus_t *) priv; + uint8_t val = 0xff; + uint16_t port; + + if ((addr == 0x388) || (addr == 0x389)) + port = addr; + else + port = addr & 0xf0f; + + switch (port) { + case 0x300: /*MIDI status*/ + val = gus->midi_status; + break; + + case 0x301: /*MIDI data*/ + val = 0; + if (gus->uart_in) { + if ((gus->midi_data == 0xaa) && (gus->midi_ctrl & MIDI_CTRL_RECEIVE)) /*Handle master reset*/ + val = gus->midi_data; + else { + val = gus->midi_queue[gus->midi_r]; + if (gus->midi_r != gus->midi_w) { + gus->midi_r++; + gus->midi_r &= 63; + } + } + gus->midi_status &= ~MIDI_INT_RECEIVE; + gus_midi_update_int_status(gus); + } + break; + + case 0x200: + return 0; + + case 0x206: /*IRQ status*/ + val = gus->irqstatus & ~0x10; + if (gus->ad_status & 0x19) + val |= 0x10; + return val; + + case 0x20F: +#if defined(DEV_BRANCH) && defined(USE_GUSMAX) + if (gus->type == GUS_MAX) + val = 0x02; + else +#endif + val = 0x00; + break; + + case 0x302: + return gus->voice; + + case 0x303: + return gus->global; + + case 0x304: /*Global low*/ + switch (gus->global) { + case 0x82: /*Start addr high*/ + return gus->start[gus->voice] >> 16; + case 0x83: /*Start addr low*/ + return gus->start[gus->voice] & 0xFF; + + case 0x89: /*Current volume*/ + return gus->rcur[gus->voice] >> 6; + case 0x8A: /*Current addr high*/ + return gus->cur[gus->voice] >> 16; + case 0x8B: /*Current addr low*/ + return gus->cur[gus->voice] & 0xFF; + + case 0x8F: /*IRQ status*/ + val = gus->irqstatus2; + gus->rampirqs[gus->irqstatus2 & 0x1F] = 0; + gus->waveirqs[gus->irqstatus2 & 0x1F] = 0; + gus_update_int_status(gus); + return val; + + case 0x00: + case 0x01: + case 0x02: + case 0x03: + case 0x04: + case 0x05: + case 0x06: + case 0x07: + case 0x08: + case 0x09: + case 0x0a: + case 0x0b: + case 0x0c: + case 0x0d: + case 0x0e: + case 0x0f: + val = 0xff; + break; + + default: + break; + } + break; + case 0x305: /*Global high*/ + switch (gus->global) { + case 0x80: /*Voice control*/ + return gus->ctrl[gus->voice] | (gus->waveirqs[gus->voice] ? 0x80 : 0); + + case 0x82: /*Start addr high*/ + return gus->start[gus->voice] >> 24; + case 0x83: /*Start addr low*/ + return gus->start[gus->voice] >> 8; + + case 0x89: /*Current volume*/ + return gus->rcur[gus->voice] >> 14; + + case 0x8A: /*Current addr high*/ + return gus->cur[gus->voice] >> 24; + case 0x8B: /*Current addr low*/ + return gus->cur[gus->voice] >> 8; + + case 0x8C: /*Pan*/ + return gus->pan_r[gus->voice]; + + case 0x8D: + return gus->rctrl[gus->voice] | (gus->rampirqs[gus->voice] ? 0x80 : 0); + + case 0x8F: /*IRQ status*/ + val = gus->irqstatus2; + gus->rampirqs[gus->irqstatus2 & 0x1F] = 0; + gus->waveirqs[gus->irqstatus2 & 0x1F] = 0; + gus_update_int_status(gus); + return val; + + case 0x41: /*DMA control*/ + val = gus->dmactrl | ((gus->irqstatus & 0x80) ? 0x40 : 0); + gus->irqstatus &= ~0x80; + return val; + case 0x45: /*Timer control*/ + return gus->tctrl; + case 0x49: /*Sampling control*/ + return 0; + + case 0x00: + case 0x01: + case 0x02: + case 0x03: + case 0x04: + case 0x05: + case 0x06: + case 0x07: + case 0x08: + case 0x09: + case 0x0a: + case 0x0b: + case 0x0c: + case 0x0d: + case 0x0e: + case 0x0f: + val = 0xff; + break; + + default: + break; + } + break; + case 0x306: + case 0x706: +#if defined(DEV_BRANCH) && defined(USE_GUSMAX) + if (gus->type == GUS_MAX) + val = 0x0a; /* GUS MAX */ + else +#endif + val = 0xff; /*Pre 3.7 - no mixer*/ + break; + + case 0x307: /*DRAM access*/ + gus->addr &= 0xfffff; + if (gus->addr < gus->gus_end_ram) + val = gus->ram[gus->addr]; + else + val = 0; + return val; + case 0x309: + return 0; + + case 0x20b: + switch (gus->reg_ctrl & 0x07) { + case 1: + val = gus->gp1; + break; + case 2: + val = gus->gp2; + break; + case 3: + val = gus->gp1_addr; + break; + case 4: + val = gus->gp2_addr; + break; + + default: + break; + } + break; + + case 0x20c: + val = gus->sb_2xc; + if (gus->reg_ctrl & 0x20) + gus->sb_2xc &= 0x80; + break; + case 0x20e: + return gus->sb_2xe; + + case 0x208: + case 0x388: + if (gus->tctrl & GUS_TIMER_CTRL_AUTO) + val = gus->sb_2xa; + else { + val = gus->ad_status & ~(gus->ad_timer_ctrl & 0x60); + if (val & 0x60) + val |= 0x80; + } + break; + + case 0x209: + gus->ad_status &= ~0x01; +#ifdef OLD_NMI_BEHAVIOR + nmi = 0; +#endif + fallthrough; + case 0x389: + val = gus->ad_data; + break; + + case 0x20A: + val = gus->adcommand; + break; + + default: + break; + } + return val; +} + +void +gus_poll_timer_1(void *priv) +{ + gus_t *gus = (gus_t *) priv; + + timer_advance_u64(&gus->timer_1, (uint64_t) (TIMER_USEC * 80)); + if (gus->t1on) { + gus->t1++; + if (gus->t1 > 0xFF) { + gus->t1 = gus->t1l; + gus->ad_status |= 0x40; + if (gus->tctrl & 4) { + gus->ad_status |= 0x04; + gus->irqstatus |= 0x04; + } + } + } + if (gus->irqnext) { + gus->irqnext = 0; + gus->irqstatus |= 0x80; + } + + gus_midi_update_int_status(gus); + gus_update_int_status(gus); +} + +void +gus_poll_timer_2(void *priv) +{ + gus_t *gus = (gus_t *) priv; + + timer_advance_u64(&gus->timer_2, (uint64_t) (TIMER_USEC * 320)); + if (gus->t2on) { + gus->t2++; + if (gus->t2 > 0xFF) { + gus->t2 = gus->t2l; + gus->ad_status |= 0x20; + if (gus->tctrl & 8) { + gus->ad_status |= 0x02; + gus->irqstatus |= 0x08; + } + } + } + if (gus->irqnext) { + gus->irqnext = 0; + gus->irqstatus |= 0x80; + } + gus_update_int_status(gus); +} + +static void +gus_update(gus_t *gus) +{ + for (; gus->pos < sound_pos_global; gus->pos++) { + if (gus->out_l < -32768) + gus->buffer[0][gus->pos] = -32768; + else if (gus->out_l > 32767) + gus->buffer[0][gus->pos] = 32767; + else + gus->buffer[0][gus->pos] = gus->out_l; + if (gus->out_r < -32768) + gus->buffer[1][gus->pos] = -32768; + else if (gus->out_r > 32767) + gus->buffer[1][gus->pos] = 32767; + else + gus->buffer[1][gus->pos] = gus->out_r; + } +} + +void +gus_poll_wave(void *priv) +{ + gus_t *gus = (gus_t *) priv; + uint32_t addr; + int16_t v; + int32_t vl; + int update_irqs = 0; + + gus_update(gus); + + timer_advance_u64(&gus->samp_timer, gus->samp_latch); + + gus->out_l = gus->out_r = 0; + + if ((gus->reset & 3) != 3) + return; + for (uint8_t d = 0; d < 32; d++) { + if (!(gus->ctrl[d] & 3)) { + if (gus->ctrl[d] & 4) { + addr = gus->cur[d] >> 9; + addr = (addr & 0xC0000) | ((addr << 1) & 0x3FFFE); + if (!(gus->freq[d] >> 10)) { + /* Interpolate */ + if (((addr + 1) & 0xfffff) < gus->gus_end_ram) + vl = (int16_t) (int8_t) ((gus->ram[(addr + 1) & 0xfffff] ^ 0x80) - 0x80) * + (511 - (gus->cur[d] & 511)); + else + vl = 0; + + if (((addr + 3) & 0xfffff) < gus->gus_end_ram) + vl += (int16_t) (int8_t) ((gus->ram[(addr + 3) & 0xfffff] ^ 0x80) - 0x80) * + (gus->cur[d] & 511); + + v = vl >> 9; + } else if (((addr + 1) & 0xfffff) < gus->gus_end_ram) + v = (int16_t) (int8_t) ((gus->ram[(addr + 1) & 0xfffff] ^ 0x80) - 0x80); + else + v = 0x0000; + } else { + if (!(gus->freq[d] >> 10)) { + /* Interpolate */ + if (((gus->cur[d] >> 9) & 0xfffff) < gus->gus_end_ram) + vl = ((int8_t) ((gus->ram[(gus->cur[d] >> 9) & 0xfffff] ^ 0x80) - 0x80)) * + (511 - (gus->cur[d] & 511)); + else + vl = 0; + + if ((((gus->cur[d] >> 9) + 1) & 0xfffff) < gus->gus_end_ram) + vl += ((int8_t) ((gus->ram[((gus->cur[d] >> 9) + 1) & 0xfffff] ^ 0x80) - 0x80)) * + (gus->cur[d] & 511); + + v = vl >> 9; + } else if (((gus->cur[d] >> 9) & 0xfffff) < gus->gus_end_ram) + v = (int16_t) (int8_t) ((gus->ram[(gus->cur[d] >> 9) & 0xfffff] ^ 0x80) - 0x80); + else + v = 0x0000; + } + + if ((gus->rcur[d] >> 14) > 4095) + v = (int16_t) (float) (v) *24.0 * vol16bit[4095]; + else + v = (int16_t) (float) (v) *24.0 * vol16bit[(gus->rcur[d] >> 10) & 4095]; + + gus->out_l += (v * gus->pan_l[d]) / 7; + gus->out_r += (v * gus->pan_r[d]) / 7; + + if (gus->ctrl[d] & 0x40) { + gus->cur[d] -= (gus->freq[d] >> 1); + if (gus->cur[d] <= gus->start[d]) { + int diff = gus->start[d] - gus->cur[d]; + + if (gus->ctrl[d] & 8) { + if (gus->ctrl[d] & 0x10) + gus->ctrl[d] ^= 0x40; + gus->cur[d] = (gus->ctrl[d] & 0x40) ? (gus->end[d] - diff) : (gus->start[d] + diff); + } else if (!(gus->rctrl[d] & 4)) { + gus->ctrl[d] |= 1; + gus->cur[d] = (gus->ctrl[d] & 0x40) ? gus->end[d] : gus->start[d]; + } + + if ((gus->ctrl[d] & 0x20) && !gus->waveirqs[d]) { + gus->waveirqs[d] = 1; + update_irqs = 1; + } + } + } else { + gus->cur[d] += (gus->freq[d] >> 1); + + if (gus->cur[d] >= gus->end[d]) { + int diff = gus->cur[d] - gus->end[d]; + + if (gus->ctrl[d] & 8) { + if (gus->ctrl[d] & 0x10) + gus->ctrl[d] ^= 0x40; + gus->cur[d] = (gus->ctrl[d] & 0x40) ? (gus->end[d] - diff) : (gus->start[d] + diff); + } else if (!(gus->rctrl[d] & 4)) { + gus->ctrl[d] |= 1; + gus->cur[d] = (gus->ctrl[d] & 0x40) ? gus->end[d] : gus->start[d]; + } + + if ((gus->ctrl[d] & 0x20) && !gus->waveirqs[d]) { + gus->waveirqs[d] = 1; + update_irqs = 1; + } + } + } + } + if (!(gus->rctrl[d] & 3)) { + if (gus->rctrl[d] & 0x40) { + gus->rcur[d] -= gus->rfreq[d]; + if (gus->rcur[d] <= gus->rstart[d]) { + int diff = gus->rstart[d] - gus->rcur[d]; + if (!(gus->rctrl[d] & 8)) { + gus->rctrl[d] |= 1; + gus->rcur[d] = (gus->rctrl[d] & 0x40) ? gus->rstart[d] : gus->rend[d]; + } else { + if (gus->rctrl[d] & 0x10) + gus->rctrl[d] ^= 0x40; + gus->rcur[d] = (gus->rctrl[d] & 0x40) ? (gus->rend[d] - diff) : (gus->rstart[d] + diff); + } + + if ((gus->rctrl[d] & 0x20) && !gus->rampirqs[d]) { + gus->rampirqs[d] = 1; + update_irqs = 1; + } + } + } else { + gus->rcur[d] += gus->rfreq[d]; + if (gus->rcur[d] >= gus->rend[d]) { + int diff = gus->rcur[d] - gus->rend[d]; + if (!(gus->rctrl[d] & 8)) { + gus->rctrl[d] |= 1; + gus->rcur[d] = (gus->rctrl[d] & 0x40) ? gus->rstart[d] : gus->rend[d]; + } else { + if (gus->rctrl[d] & 0x10) + gus->rctrl[d] ^= 0x40; + gus->rcur[d] = (gus->rctrl[d] & 0x40) ? (gus->rend[d] - diff) : (gus->rstart[d] + diff); + } + + if ((gus->rctrl[d] & 0x20) && !gus->rampirqs[d]) { + gus->rampirqs[d] = 1; + update_irqs = 1; + } + } + } + } + } + + if (update_irqs) gus_update_int_status(gus); } -void writegus(uint16_t addr, uint8_t val, void *p) +static void +gus_get_buffer(int32_t *buffer, int len, void *priv) { - gus_t *gus = (gus_t *)p; - int c, d; - int old; - uint16_t port; + gus_t *gus = (gus_t *) priv; + #if defined(DEV_BRANCH) && defined(USE_GUSMAX) - uint16_t csioport; + if ((gus->type == GUS_MAX) && (gus->max_ctrl)) + ad1848_update(&gus->ad1848); #endif - - if ((addr == 0x388) || (addr == 0x389)) - port = addr; - else - port = addr & 0xf0f; - - switch (port) - { - case 0x300: /*MIDI control*/ - old = gus->midi_ctrl; - gus->midi_ctrl = val; - gus->uart_out = 1; - - if ((val & 3) == 3) { /*Master reset*/ - gus->uart_in = 0; - gus->midi_status = 0; - gus->midi_r = 0; - gus->midi_w = 0; - } else if ((old & 3) == 3) { - gus->midi_status |= MIDI_INT_TRANSMIT; - } else if (gus->midi_ctrl & MIDI_CTRL_RECEIVE) { - gus->uart_in = 1; - } - gus_midi_update_int_status(gus); - break; - case 0x301: /*MIDI data*/ - gus->midi_data = val; - if (gus->uart_out) { - midi_raw_out_byte(val); - } - if (gus->latch_enable & 0x20) { - gus->midi_status |= MIDI_INT_RECEIVE; - } else - gus->midi_status |= MIDI_INT_TRANSMIT; - break; - case 0x302: /*Voice select*/ - gus->voice=val&31; - break; - case 0x303: /*Global select*/ - gus->global=val; - break; - case 0x304: /*Global low*/ - switch (gus->global) - { - case 0: /*Voice control*/ - gus->ctrl[gus->voice]=val; - break; - case 1: /*Frequency control*/ - gus->freq[gus->voice]=(gus->freq[gus->voice]&0xFF00)|val; - break; - case 2: /*Start addr high*/ - gus->startx[gus->voice]=(gus->startx[gus->voice]&0xF807F)|(val<<7); - gus->start[gus->voice]=(gus->start[gus->voice]&0x1F00FFFF)|(val<<16); - break; - case 3: /*Start addr low*/ - gus->start[gus->voice]=(gus->start[gus->voice]&0x1FFFFF00)|val; - break; - case 4: /*End addr high*/ - gus->endx[gus->voice]=(gus->endx[gus->voice]&0xF807F)|(val<<7); - gus->end[gus->voice]=(gus->end[gus->voice]&0x1F00FFFF)|(val<<16); - break; - case 5: /*End addr low*/ - gus->end[gus->voice]=(gus->end[gus->voice]&0x1FFFFF00)|val; - break; + gus_update(gus); - case 6: /*Ramp frequency*/ - gus->rfreq[gus->voice] = (int)( (double)((val & 63)*512)/(double)(1 << (3*(val >> 6)))); - break; - - case 9: /*Current volume*/ - gus->curvol[gus->voice] = gus->rcur[gus->voice] = (gus->rcur[gus->voice] & ~(0xff << 6)) | (val << 6); - break; - - case 0xA: /*Current addr high*/ - gus->cur[gus->voice]=(gus->cur[gus->voice]&0x1F00FFFF)|(val<<16); -gus->curx[gus->voice]=(gus->curx[gus->voice]&0xF807F00)|((val<<7)<<8); - break; - case 0xB: /*Current addr low*/ - gus->cur[gus->voice]=(gus->cur[gus->voice]&0x1FFFFF00)|val; - break; - - case 0x42: /*DMA address low*/ - gus->dmaaddr=(gus->dmaaddr&0xFF000)|(val<<4); - break; - - case 0x43: /*Address low*/ - gus->addr=(gus->addr&0xFFF00)|val; - break; - case 0x45: /*Timer control*/ - gus->tctrl=val; - gus_update_int_status(gus); - break; - } - break; - case 0x305: /*Global high*/ - switch (gus->global) - { - case 0: /*Voice control*/ - gus->ctrl[gus->voice] = val & 0x7f; - - old = gus->waveirqs[gus->voice]; - gus->waveirqs[gus->voice] = ((val & 0xa0) == 0xa0) ? 1 : 0; - if (gus->waveirqs[gus->voice] != old) - gus_update_int_status(gus); - break; - case 1: /*Frequency control*/ - gus->freq[gus->voice]=(gus->freq[gus->voice]&0xFF)|(val<<8); - break; - case 2: /*Start addr high*/ - gus->startx[gus->voice]=(gus->startx[gus->voice]&0x07FFF)|(val<<15); - gus->start[gus->voice]=(gus->start[gus->voice]&0x00FFFFFF)|((val&0x1F)<<24); - break; - case 3: /*Start addr low*/ - gus->startx[gus->voice]=(gus->startx[gus->voice]&0xFFF80)|(val&0x7F); - gus->start[gus->voice]=(gus->start[gus->voice]&0x1FFF00FF)|(val<<8); - break; - case 4: /*End addr high*/ - gus->endx[gus->voice]=(gus->endx[gus->voice]&0x07FFF)|(val<<15); - gus->end[gus->voice]=(gus->end[gus->voice]&0x00FFFFFF)|((val&0x1F)<<24); - break; - case 5: /*End addr low*/ - gus->endx[gus->voice]=(gus->endx[gus->voice]&0xFFF80)|(val&0x7F); - gus->end[gus->voice]=(gus->end[gus->voice]&0x1FFF00FF)|(val<<8); - break; - - case 6: /*Ramp frequency*/ - gus->rfreq[gus->voice] = (int)( (double)((val & 63) * (1 << 10))/(double)(1 << (3 * (val >> 6)))); - break; - case 7: /*Ramp start*/ - gus->rstart[gus->voice] = val << 14; - break; - case 8: /*Ramp end*/ - gus->rend[gus->voice] = val << 14; - break; - case 9: /*Current volume*/ - gus->curvol[gus->voice] = gus->rcur[gus->voice] = (gus->rcur[gus->voice] & ~(0xff << 14)) | (val << 14); - break; - - case 0xA: /*Current addr high*/ - gus->cur[gus->voice]=(gus->cur[gus->voice]&0x00FFFFFF)|((val&0x1F)<<24); - gus->curx[gus->voice]=(gus->curx[gus->voice]&0x07FFF00)|((val<<15)<<8); - break; - case 0xB: /*Current addr low*/ - gus->cur[gus->voice]=(gus->cur[gus->voice]&0x1FFF00FF)|(val<<8); -gus->curx[gus->voice]=(gus->curx[gus->voice]&0xFFF8000)|((val&0x7F)<<8); - break; - case 0xC: /*Pan*/ - gus->pan_l[gus->voice] = 15 - (val & 0xf); - gus->pan_r[gus->voice] = (val & 0xf); - break; - case 0xD: /*Ramp control*/ - old = gus->rampirqs[gus->voice]; - gus->rctrl[gus->voice] = val & 0x7F; - gus->rampirqs[gus->voice] = ((val & 0xa0) == 0xa0) ? 1 : 0; - if (gus->rampirqs[gus->voice] != old) - gus_update_int_status(gus); - break; - - case 0xE: - gus->voices=(val&63)+1; - if (gus->voices>32) gus->voices=32; - if (gus->voices<14) gus->voices=14; - gus->global=val; - if (gus->voices < 14) - gus->samp_latch = (uint64_t)(TIMER_USEC * (1000000.0 / 44100.0)); - else - gus->samp_latch = (uint64_t)(TIMER_USEC * (1000000.0 / gusfreqs[gus->voices - 14])); - break; - - case 0x41: /*DMA*/ - if (val&1 && gus->dma != -1) - { - if (val & 2) - { - c=0; - while (c<65536) - { - int dma_result; - if (val & 0x04) - { - uint32_t gus_addr = (gus->dmaaddr & 0xc0000) | ((gus->dmaaddr & 0x1ffff) << 1); - d = gus->ram[gus_addr] | (gus->ram[gus_addr + 1] << 8); - if (val & 0x80) - d ^= 0x8080; - dma_result = dma_channel_write(gus->dma, d); - if (dma_result == DMA_NODATA) - break; - } - else - { - d = gus->ram[gus->dmaaddr]; - if (val & 0x80) - d ^= 0x80; - dma_result = dma_channel_write(gus->dma, d); - if (dma_result == DMA_NODATA) - break; - } - gus->dmaaddr++; - gus->dmaaddr &= 0xFFFFF; - c++; - if (dma_result & DMA_OVER) - break; - } - gus->dmactrl=val&~0x40; - gus->irqnext=1; - } - else - { - c=0; - while (c<65536) - { - d = dma_channel_read(gus->dma); - if (d == DMA_NODATA) - break; - if (val & 0x04) - { - uint32_t gus_addr = (gus->dmaaddr & 0xc0000) | ((gus->dmaaddr & 0x1ffff) << 1); - if (val & 0x80) - d ^= 0x8080; - gus->ram[gus_addr] = d & 0xff; - gus->ram[gus_addr +1] = (d >> 8) & 0xff; - } - else - { - if (val & 0x80) - d ^= 0x80; - gus->ram[gus->dmaaddr] = d; - } - gus->dmaaddr++; - gus->dmaaddr &= 0xFFFFF; - c++; - if (d & DMA_OVER) - break; - } - gus->dmactrl=val&~0x40; - gus->irqnext=1; - } - } - break; - - case 0x42: /*DMA address low*/ - gus->dmaaddr=(gus->dmaaddr&0xFF0)|(val<<12); - break; - - case 0x43: /*Address low*/ - gus->addr=(gus->addr&0xF00FF)|(val<<8); - break; - case 0x44: /*Address high*/ - gus->addr=(gus->addr&0xFFFF)|((val<<16)&0xF0000); - break; - case 0x45: /*Timer control*/ - if (!(val&4)) gus->irqstatus&=~4; - if (!(val&8)) gus->irqstatus&=~8; - if (!(val & 0x20)) - { - gus->ad_status &= ~0x18; - nmi = 0; - } - if (!(val & 0x02)) - { - gus->ad_status &= ~0x01; - nmi = 0; - } - gus->tctrl=val; - gus->sb_ctrl = val; - gus_update_int_status(gus); - break; - case 0x46: /*Timer 1*/ - gus->t1 = gus->t1l = val; - gus->t1on = 1; - break; - case 0x47: /*Timer 2*/ - gus->t2 = gus->t2l = val; - gus->t2on = 1; - break; - - case 0x4c: /*Reset*/ - gus->reset = val; - break; - } - break; - case 0x307: /*DRAM access*/ - if (gus->addr < gus->gus_end_ram) - gus->ram[gus->addr]=val; - gus->addr&=0xFFFFF; - break; - case 0x208: case 0x388: - gus->adcommand = val; - break; - - case 0x389: - if ((gus->tctrl & GUS_TIMER_CTRL_AUTO) || gus->adcommand != 4) - { - gus->ad_data = val; - gus->ad_status |= 0x01; - if (gus->sb_ctrl & 0x02) - { - if (gus->sb_nmi) - nmi = 1; - else if (gus->irq != -1) - picint(1 << gus->irq); - } - } - else if (!(gus->tctrl & GUS_TIMER_CTRL_AUTO) && gus->adcommand == 4) - { - if (val & 0x80) - { - gus->ad_status &= ~0x60; - } - else - { - gus->ad_timer_ctrl = val; - - if (val & 0x01) - gus->t1on = 1; - else - gus->t1 = gus->t1l; - - if (val & 0x02) - gus->t2on = 1; - else - gus->t2 = gus->t2l; - } - } - break; - - case 0x200: - gus->latch_enable = val; - break; - - case 0x20b: - switch (gus->reg_ctrl & 0x07) - { - case 0: - if (gus->latch_enable & 0x40) { - gus->irq = gus_gf1_irqs[val & 7]; - - if (val & 0x40) - { - if (gus->irq == -1) - gus->irq = gus->irq_midi = gus_gf1_irqs[(val >> 3) & 7]; - else - gus->irq_midi = gus->irq; - } - else - gus->irq_midi = gus_midi_irqs[(val >> 3) & 7]; -#if defined(DEV_BRANCH) && defined(USE_GUSMAX) - ad1848_setirq(&gus->ad1848, gus->irq); + for (int c = 0; c < len * 2; c++) { +#if defined(DEV_BRANCH) && defined(USE_GUSMAX) + if ((gus->type == GUS_MAX) && (gus->max_ctrl)) + buffer[c] += (int32_t) (gus->ad1848.buffer[c] / 2); #endif - - gus->sb_nmi = val & 0x80; - } else { - gus->dma = gus_dmas[val & 7]; + buffer[c] += (int32_t) gus->buffer[c & 1][c >> 1]; + } + #if defined(DEV_BRANCH) && defined(USE_GUSMAX) - ad1848_setdma(&gus->ad1848, gus->dma); -#endif - } - break; - case 1: - gus->gp1 = val; - break; - case 2: - gus->gp2 = val; - break; - case 3: - gus->gp1_addr = val; - break; - case 4: - gus->gp2_addr = val; - break; - case 5: - gus->usrr = 0; - break; - case 6: - break; - } - break; - - case 0x206: - gus->ad_status |= 0x08; - if (gus->sb_ctrl & 0x20) - { - if (gus->sb_nmi) - nmi = 1; - else if (gus->irq != -1) - picint(1 << gus->irq); - } - break; - case 0x20a: - gus->sb_2xa = val; - break; - case 0x20c: - gus->ad_status |= 0x10; - if (gus->sb_ctrl & 0x20) - { - if (gus->sb_nmi) - nmi = 1; - else if (gus->irq != -1) - picint(1 << gus->irq); - } - /*FALLTHROUGH*/ - case 0x20d: - gus->sb_2xc = val; - break; - case 0x20e: - gus->sb_2xe = val; - break; - case 0x20f: - gus->reg_ctrl = val; - break; - case 0x306: case 0x706: - if (gus->dma >= 4) - val |= 0x30; - gus->max_ctrl = (val >> 6) & 1; -#if defined(DEV_BRANCH) && defined(USE_GUSMAX) - if (val & 0x40) { - if ((val & 0xF) != ((addr >> 4) & 0xF)) { - csioport = 0x30c | ((addr >> 4) & 0xf); - io_removehandler(csioport, 4, - ad1848_read,NULL,NULL, - ad1848_write,NULL,NULL,&gus->ad1848); - csioport = 0x30c | ((val & 0xf) << 4); - io_sethandler(csioport, 4, - ad1848_read,NULL,NULL, - ad1848_write,NULL,NULL, &gus->ad1848); - } - } + if ((gus->type == GUS_MAX) && (gus->max_ctrl)) + gus->ad1848.pos = 0; #endif - break; - } + gus->pos = 0; } - -uint8_t readgus(uint16_t addr, void *p) +static void +gus_input_msg(void *priv, uint8_t *msg, uint32_t len) { - gus_t *gus = (gus_t *)p; - uint8_t val = 0xff; - uint16_t port; - - if ((addr == 0x388) || (addr == 0x389)) - port = addr; - else - port = addr & 0xf0f; - - switch (port) - { - case 0x300: /*MIDI status*/ - val = gus->midi_status; - break; + gus_t *gus = (gus_t *) priv; - case 0x301: /*MIDI data*/ - val = 0; - if (gus->uart_in) { - if ((gus->midi_data == 0xaa) && (gus->midi_ctrl & MIDI_CTRL_RECEIVE)) /*Handle master reset*/ - val = gus->midi_data; - else { - val = gus->midi_queue[gus->midi_r]; - if (gus->midi_r != gus->midi_w) { - gus->midi_r++; - gus->midi_r &= 63; - } - } - gus->midi_status &= ~MIDI_INT_RECEIVE; - gus_midi_update_int_status(gus); - } - break; - - case 0x200: - return 0; - - case 0x206: /*IRQ status*/ - val = gus->irqstatus & ~0x10; - if (gus->ad_status & 0x19) - val |= 0x10; - return val; + if (gus->sysex) + return; - case 0x20F: - if (gus->max_ctrl) - val = 0x02; - else - val = 0x00; - break; - - case 0x302: - return gus->voice; - - case 0x303: - return gus->global; - - case 0x304: /*Global low*/ - switch (gus->global) - { - case 0x82: /*Start addr high*/ - return gus->start[gus->voice]>>16; - case 0x83: /*Start addr low*/ - return gus->start[gus->voice]&0xFF; - - case 0x89: /*Current volume*/ - return gus->rcur[gus->voice]>>6; - case 0x8A: /*Current addr high*/ - return gus->cur[gus->voice]>>16; - case 0x8B: /*Current addr low*/ - return gus->cur[gus->voice]&0xFF; - - case 0x8F: /*IRQ status*/ - val=gus->irqstatus2; - gus->rampirqs[gus->irqstatus2&0x1F]=0; - gus->waveirqs[gus->irqstatus2&0x1F]=0; - gus_update_int_status(gus); - return val; - - case 0x00: case 0x01: case 0x02: case 0x03: - case 0x04: case 0x05: case 0x06: case 0x07: - case 0x08: case 0x09: case 0x0a: case 0x0b: - case 0x0c: case 0x0d: case 0x0e: case 0x0f: - val = 0xff; - break; - } - break; - case 0x305: /*Global high*/ - switch (gus->global) - { - case 0x80: /*Voice control*/ - return gus->ctrl[gus->voice]|(gus->waveirqs[gus->voice]?0x80:0); - - case 0x82: /*Start addr high*/ - return gus->start[gus->voice]>>24; - case 0x83: /*Start addr low*/ - return gus->start[gus->voice]>>8; - - case 0x89: /*Current volume*/ - return gus->rcur[gus->voice]>>14; - - case 0x8A: /*Current addr high*/ - return gus->cur[gus->voice]>>24; - case 0x8B: /*Current addr low*/ - return gus->cur[gus->voice]>>8; - - case 0x8C: /*Pan*/ - return gus->pan_r[gus->voice]; - - case 0x8D: - return gus->rctrl[gus->voice]|(gus->rampirqs[gus->voice]?0x80:0); - - case 0x8F: /*IRQ status*/ - val=gus->irqstatus2; - gus->rampirqs[gus->irqstatus2&0x1F]=0; - gus->waveirqs[gus->irqstatus2&0x1F]=0; - gus_update_int_status(gus); - return val; - - case 0x41: /*DMA control*/ - val=gus->dmactrl|((gus->irqstatus&0x80)?0x40:0); - gus->irqstatus&=~0x80; - return val; - case 0x45: /*Timer control*/ - return gus->tctrl; - case 0x49: /*Sampling control*/ - return 0; - - case 0x00: case 0x01: case 0x02: case 0x03: - case 0x04: case 0x05: case 0x06: case 0x07: - case 0x08: case 0x09: case 0x0a: case 0x0b: - case 0x0c: case 0x0d: case 0x0e: case 0x0f: - val = 0xff; - break; - } - break; - case 0x306: case 0x706: - if (gus->max_ctrl) - val = 0x0a; /* GUS MAX */ - else - val = 0xff; /*Pre 3.7 - no mixer*/ - break; - - break; - case 0x307: /*DRAM access*/ - val=gus->ram[gus->addr]; - gus->addr&=0xFFFFF; - if (gus->addr < gus->gus_end_ram) - val = gus->ram[gus->addr]; - else - val = 0; - return val; - case 0x309: return 0; - - case 0x20b: - switch (gus->reg_ctrl & 0x07) - { - case 1: - val = gus->gp1; - break; - case 2: - val = gus->gp2; - break; - case 3: - val = gus->gp1_addr; - break; - case 4: - val = gus->gp2_addr; - break; - } - break; - - case 0x20c: - val = gus->sb_2xc; - if (gus->reg_ctrl & 0x20) - gus->sb_2xc &= 0x80; - break; - case 0x20e: - return gus->sb_2xe; - - case 0x208: case 0x388: - if (gus->tctrl & GUS_TIMER_CTRL_AUTO) - val = gus->sb_2xa; - else - { - val = gus->ad_status & ~(gus->ad_timer_ctrl & 0x60); - if (val & 0x60) - val |= 0x80; - } - break; - - case 0x209: - gus->ad_status &= ~0x01; - nmi = 0; - /*FALLTHROUGH*/ - case 0x389: - val = gus->ad_data; - break; - - case 0x20A: - val = gus->adcommand; - break; + if (gus->uart_in) { + gus->midi_status |= MIDI_INT_RECEIVE; + for (uint32_t i = 0; i < len; i++) { + gus->midi_queue[gus->midi_w++] = msg[i]; + gus->midi_w &= 63; } - return val; + + gus_midi_update_int_status(gus); + } } -void gus_poll_timer_1(void *p) +static int +gus_input_sysex(void *priv, uint8_t *buffer, uint32_t len, int abort) { - gus_t *gus = (gus_t *)p; - - timer_advance_u64(&gus->timer_1, (uint64_t)(TIMER_USEC * 80)); - if (gus->t1on) - { - gus->t1++; - if (gus->t1 > 0xFF) - { - gus->t1=gus->t1l; - gus->ad_status |= 0x40; - if (gus->tctrl&4) - { - gus->ad_status |= 0x04; - gus->irqstatus |= 0x04; - } - } - } - if (gus->irqnext) - { - gus->irqnext=0; - gus->irqstatus|=0x80; - } + gus_t *gus = (gus_t *) priv; - gus_midi_update_int_status(gus); - gus_update_int_status(gus); + if (abort) { + gus->sysex = 0; + return 0; + } + gus->sysex = 1; + for (uint32_t i = 0; i < len; i++) { + if (gus->midi_r == gus->midi_w) + return (len - i); + gus->midi_queue[gus->midi_w++] = buffer[i]; + gus->midi_w &= 63; + } + gus->sysex = 0; + return 0; } -void gus_poll_timer_2(void *p) +static void +gus_reset(void *priv) { - gus_t *gus = (gus_t *)p; - - timer_advance_u64(&gus->timer_2, (uint64_t)(TIMER_USEC * 320)); - if (gus->t2on) - { - gus->t2++; - if (gus->t2 > 0xFF) - { - gus->t2=gus->t2l; - gus->ad_status |= 0x20; - if (gus->tctrl&8) - { - gus->ad_status |= 0x02; - gus->irqstatus |= 0x08; - } - } - } - if (gus->irqnext) - { - gus->irqnext=0; - gus->irqstatus|=0x80; - } - gus_update_int_status(gus); -} + gus_t *gus = (gus_t *) priv; + int c; + double out = 1.0; -static void gus_update(gus_t *gus) -{ - for (; gus->pos < sound_pos_global; gus->pos++) - { - if (gus->out_l < -32768) - gus->buffer[0][gus->pos] = -32768; - else if (gus->out_l > 32767) - gus->buffer[0][gus->pos] = 32767; - else - gus->buffer[0][gus->pos] = gus->out_l; - if (gus->out_r < -32768) - gus->buffer[1][gus->pos] = -32768; - else if (gus->out_r > 32767) - gus->buffer[1][gus->pos] = 32767; - else - gus->buffer[1][gus->pos] = gus->out_r; - } -} + if (gus == NULL) + return; -void gus_poll_wave(void *p) -{ - gus_t *gus = (gus_t *)p; - uint32_t addr; - int d; - int16_t v; - int32_t vl; - int update_irqs = 0; - - gus_update(gus); - - timer_advance_u64(&gus->samp_timer, gus->samp_latch); - - gus->out_l = gus->out_r = 0; + memset(gus->ram, 0x00, (gus->gus_end_ram)); - if ((gus->reset & 3) != 3) - return; - for (d=0;d<32;d++) - { - if (!(gus->ctrl[d] & 3)) - { - if (gus->ctrl[d] & 4) - { - addr = gus->cur[d] >> 9; - addr = (addr & 0xC0000) | ((addr << 1) & 0x3FFFE); - if (!(gus->freq[d] >> 10)) /*Interpolate*/ - { - vl = (int16_t)(int8_t)((gus->ram[(addr + 1) & 0xFFFFF] ^ 0x80) - 0x80) * (511 - (gus->cur[d] & 511)); - vl += (int16_t)(int8_t)((gus->ram[(addr + 3) & 0xFFFFF] ^ 0x80) - 0x80) * (gus->cur[d] & 511); - v = vl >> 9; - } - else - v = (int16_t)(int8_t)((gus->ram[(addr + 1) & 0xFFFFF] ^ 0x80) - 0x80); - } - else - { - if (!(gus->freq[d] >> 10)) /*Interpolate*/ - { - vl = ((int8_t)((gus->ram[(gus->cur[d] >> 9) & 0xFFFFF] ^ 0x80) - 0x80)) * (511 - (gus->cur[d] & 511)); - vl += ((int8_t)((gus->ram[((gus->cur[d] >> 9) + 1) & 0xFFFFF] ^ 0x80) - 0x80)) * (gus->cur[d] & 511); - v = vl >> 9; - } - else - v = (int16_t)(int8_t)((gus->ram[(gus->cur[d] >> 9) & 0xFFFFF] ^ 0x80) - 0x80); - } + for (c = 0; c < 32; c++) { + gus->ctrl[c] = 1; + gus->rctrl[c] = 1; + gus->rfreq[c] = 63 * 512; + } - if ((gus->rcur[d] >> 14) > 4095) v = (int16_t)(float)(v) * 24.0 * vol16bit[4095]; - else v = (int16_t)(float)(v) * 24.0 * vol16bit[(gus->rcur[d]>>10) & 4095]; + for (c = 4095; c >= 0; c--) { + vol16bit[c] = out; + out /= 1.002709201; /* 0.0235 dB Steps */ + } - gus->out_l += (v * gus->pan_l[d]) / 7; - gus->out_r += (v * gus->pan_r[d]) / 7; + gus->voices = 14; - if (gus->ctrl[d]&0x40) - { - gus->cur[d] -= (gus->freq[d] >> 1); - if (gus->cur[d] <= gus->start[d]) - { - int diff = gus->start[d] - gus->cur[d]; + gus->samp_latch = (uint64_t) (TIMER_USEC * (1000000.0 / 44100.0)); - if (gus->ctrl[d]&8) - { - if (gus->ctrl[d]&0x10) gus->ctrl[d]^=0x40; - gus->cur[d] = (gus->ctrl[d] & 0x40) ? (gus->end[d] - diff) : (gus->start[d] + diff); - } - else if (!(gus->rctrl[d]&4)) - { - gus->ctrl[d] |= 1; - gus->cur[d] = (gus->ctrl[d] & 0x40) ? gus->end[d] : gus->start[d]; - } - - if ((gus->ctrl[d] & 0x20) && !gus->waveirqs[d]) - { - gus->waveirqs[d] = 1; - update_irqs = 1; - } - } - } - else - { - gus->cur[d] += (gus->freq[d] >> 1); + gus->t1l = gus->t2l = 0xff; - if (gus->cur[d] >= gus->end[d]) - { - int diff = gus->cur[d] - gus->end[d]; + gus->global = 0; + gus->addr = 0; + gus->dmaaddr = 0; + gus->voice = 0; + memset(gus->start, 0x00, 32 * sizeof(uint32_t)); + memset(gus->end, 0x00, 32 * sizeof(uint32_t)); + memset(gus->cur, 0x00, 32 * sizeof(uint32_t)); + memset(gus->startx, 0x00, 32 * sizeof(uint32_t)); + memset(gus->endx, 0x00, 32 * sizeof(uint32_t)); + memset(gus->curx, 0x00, 32 * sizeof(uint32_t)); + memset(gus->rstart, 0x00, 32 * sizeof(int)); + memset(gus->rend, 0x00, 32 * sizeof(int)); + memset(gus->rcur, 0x00, 32 * sizeof(int)); + memset(gus->freq, 0x00, 32 * sizeof(uint16_t)); + memset(gus->curvol, 0x00, 32 * sizeof(int)); + memset(gus->pan_l, 0x00, 32 * sizeof(int)); + memset(gus->pan_r, 0x00, 32 * sizeof(int)); + gus->t1on = 0; + gus->t2on = 0; + gus->tctrl = 0; + gus->t1 = 0; + gus->t2 = 0; + gus->irqstatus = 0; + gus->irqstatus2 = 0; + gus->adcommand = 0; + memset(gus->waveirqs, 0x00, 32 * sizeof(int)); + memset(gus->rampirqs, 0x00, 32 * sizeof(int)); + gus->dmactrl = 0; - if (gus->ctrl[d]&8) - { - if (gus->ctrl[d]&0x10) gus->ctrl[d]^=0x40; - gus->cur[d] = (gus->ctrl[d] & 0x40) ? (gus->end[d] - diff) : (gus->start[d] + diff); - } - else if (!(gus->rctrl[d]&4)) - { - gus->ctrl[d] |= 1; - gus->cur[d] = (gus->ctrl[d] & 0x40) ? gus->end[d] : gus->start[d]; - } + gus->uart_out = 1; - if ((gus->ctrl[d] & 0x20) && !gus->waveirqs[d]) - { - gus->waveirqs[d] = 1; - update_irqs = 1; - } - } - } - } - if (!(gus->rctrl[d] & 3)) - { - if (gus->rctrl[d] & 0x40) - { - gus->rcur[d] -= gus->rfreq[d]; - if (gus->rcur[d] <= gus->rstart[d]) - { - int diff = gus->rstart[d] - gus->rcur[d]; - if (!(gus->rctrl[d] & 8)) - { - gus->rctrl[d] |= 1; - gus->rcur[d] = (gus->rctrl[d] & 0x40) ? gus->rstart[d] : gus->rend[d]; - } - else - { - if (gus->rctrl[d] & 0x10) gus->rctrl[d] ^= 0x40; - gus->rcur[d] = (gus->rctrl[d] & 0x40) ? (gus->rend[d] - diff) : (gus->rstart[d] + diff); - } + gus->sb_2xa = 0; + gus->sb_2xc = 0; + gus->sb_2xe = 0; + gus->sb_ctrl = 0; + gus->sb_nmi = 0; - if ((gus->rctrl[d] & 0x20) && !gus->rampirqs[d]) - { - gus->rampirqs[d] = 1; - update_irqs = 1; - } - } - } - else - { - gus->rcur[d] += gus->rfreq[d]; - if (gus->rcur[d] >= gus->rend[d]) - { - int diff = gus->rcur[d] - gus->rend[d]; - if (!(gus->rctrl[d] & 8)) - { - gus->rctrl[d] |= 1; - gus->rcur[d] = (gus->rctrl[d] & 0x40) ? gus->rstart[d] : gus->rend[d]; - } - else - { - if (gus->rctrl[d] & 0x10) gus->rctrl[d] ^= 0x40; - gus->rcur[d] = (gus->rctrl[d] & 0x40) ? (gus->rend[d] - diff) : (gus->rstart[d] + diff); - } + gus->reg_ctrl = 0; - if ((gus->rctrl[d] & 0x20) && !gus->rampirqs[d]) - { - gus->rampirqs[d] = 1; - update_irqs = 1; - } - } - } - } - } + gus->ad_status = 0; + gus->ad_data = 0; + gus->ad_timer_ctrl = 0; - if (update_irqs) - gus_update_int_status(gus); -} + gus->midi_ctrl = 0; + gus->midi_status = 0; + memset(gus->midi_queue, 0x00, 64 * sizeof(uint8_t)); + gus->midi_data = 0; + gus->midi_r = 0; + gus->midi_w = 0; + gus->uart_in = 0; + gus->uart_out = 0; + gus->sysex = 0; -static void gus_get_buffer(int32_t *buffer, int len, void *p) -{ - gus_t *gus = (gus_t *)p; - int c; + gus->gp1 = 0; + gus->gp2 = 0; + gus->gp1_addr = 0; + gus->gp2_addr = 0; -#if defined(DEV_BRANCH) && defined(USE_GUSMAX) - if (gus->max_ctrl) - ad1848_update(&gus->ad1848); -#endif - gus_update(gus); - - for (c = 0; c < len * 2; c++) - { -#if defined(DEV_BRANCH) && defined(USE_GUSMAX) - if (gus->max_ctrl) - buffer[c] += (int32_t)(gus->ad1848.buffer[c] / 2); -#endif - buffer[c] += (int32_t)gus->buffer[c & 1][c >> 1]; - } - -#if defined(DEV_BRANCH) && defined(USE_GUSMAX) - if (gus->max_ctrl) - gus->ad1848.pos = 0; -#endif - gus->pos = 0; -} - -static void gus_input_msg(void *p, uint8_t *msg, uint32_t len) -{ - gus_t *gus = (gus_t *)p; - uint8_t i; - - if (gus->sysex) - return; - - if (gus->uart_in) { - gus->midi_status |= MIDI_INT_RECEIVE; - - for (i=0; i < len; i++) { - gus->midi_queue[gus->midi_w++] = msg[i]; - gus->midi_w &= 63; - } - - gus_midi_update_int_status(gus); - } -} - -static int gus_input_sysex(void *p, uint8_t *buffer, uint32_t len, int abort) -{ - gus_t *gus = (gus_t *)p; - uint32_t i; - - if (abort) { - gus->sysex = 0; - return 0; - } - gus->sysex = 1; - for (i=0;imidi_r == gus->midi_w) - return (len-i); - gus->midi_queue[gus->midi_w++] = buffer[i]; - gus->midi_w &= 63; - } - gus->sysex = 0; - return 0; -} - -void *gus_init(const device_t *info) -{ - int c; - double out = 1.0; - uint8_t gus_ram = device_get_config_int("gus_ram"); - gus_t *gus = malloc(sizeof(gus_t)); - memset(gus, 0, sizeof(gus_t)); - - gus->gus_end_ram = 1 << (18 + gus_ram); - gus->ram = (uint8_t *)malloc(gus->gus_end_ram); - memset(gus->ram, 0x00, (gus->gus_end_ram)); - - for (c=0;c<32;c++) - { - gus->ctrl[c]=1; - gus->rctrl[c]=1; - gus->rfreq[c]=63*512; - } - - for (c=4095;c>=0;c--) { - vol16bit[c]=out; - out/=1.002709201; /* 0.0235 dB Steps */ - } - - gus->voices=14; - - gus->samp_latch = (uint64_t)(TIMER_USEC * (1000000.0 / 44100.0)); - - gus->t1l = gus->t2l = 0xff; - - gus->uart_out = 1; - - gus->base = device_get_config_hex16("base"); - - io_sethandler(gus->base, 0x0010, readgus, NULL, NULL, writegus, NULL, NULL, gus); - io_sethandler(0x0100+gus->base, 0x0010, readgus, NULL, NULL, writegus, NULL, NULL, gus); - io_sethandler(0x0506+gus->base, 0x0001, readgus, NULL, NULL, writegus, NULL, NULL, gus); - io_sethandler(0x0388, 0x0002, readgus, NULL, NULL, writegus, NULL, NULL, gus); + gus->usrr = 0; #if defined(DEV_BRANCH) && defined(USE_GUSMAX) - ad1848_init(&gus->ad1848, AD1848_TYPE_CS4231); - ad1848_setirq(&gus->ad1848, 5); - ad1848_setdma(&gus->ad1848, 3); - io_sethandler(0x10C+gus->base, 4, - ad1848_read,NULL,NULL, ad1848_write,NULL,NULL, &gus->ad1848); + gus->max_ctrl = 0; #endif - timer_add(&gus->samp_timer, gus_poll_wave, gus, 1); - timer_add(&gus->timer_1, gus_poll_timer_1, gus, 1); - timer_add(&gus->timer_2, gus_poll_timer_2, gus, 1); + gus->irq_state = 0; + gus->midi_irq_state = 0; - sound_add_handler(gus_get_buffer, gus); - - if (device_get_config_int("receive_input")) - midi_in_handler(1, gus_input_msg, gus_input_sysex, gus); - - return gus; + gus_update_int_status(gus); } -void gus_close(void *p) +void * +gus_init(UNUSED(const device_t *info)) { - gus_t *gus = (gus_t *)p; - - free(gus->ram); - free(gus); -} + int c; + double out = 1.0; + uint8_t gus_ram = device_get_config_int("gus_ram"); + gus_t *gus = malloc(sizeof(gus_t)); + memset(gus, 0x00, sizeof(gus_t)); -void gus_speed_changed(void *p) -{ - gus_t *gus = (gus_t *)p; + gus->gus_end_ram = 1 << (18 + gus_ram); + gus->ram = (uint8_t *) malloc(gus->gus_end_ram); + memset(gus->ram, 0x00, (gus->gus_end_ram)); - if (gus->voices < 14) - gus->samp_latch = (uint64_t)(TIMER_USEC * (1000000.0 / 44100.0)); - else - gus->samp_latch = (uint64_t)(TIMER_USEC * (1000000.0 / gusfreqs[gus->voices - 14])); + for (c = 0; c < 32; c++) { + gus->ctrl[c] = 1; + gus->rctrl[c] = 1; + gus->rfreq[c] = 63 * 512; + } + + for (c = 4095; c >= 0; c--) { + vol16bit[c] = out; + out /= 1.002709201; /* 0.0235 dB Steps */ + } + + gus->voices = 14; + + gus->samp_latch = (uint64_t) (TIMER_USEC * (1000000.0 / 44100.0)); + + gus->t1l = gus->t2l = 0xff; + + gus->uart_out = 1; + + gus->type = device_get_config_int("type"); + + gus->base = device_get_config_hex16("base"); + + io_sethandler(gus->base, 0x0010, readgus, NULL, NULL, writegus, NULL, NULL, gus); + io_sethandler(0x0100 + gus->base, 0x0010, readgus, NULL, NULL, writegus, NULL, NULL, gus); + io_sethandler(0x0506 + gus->base, 0x0001, readgus, NULL, NULL, writegus, NULL, NULL, gus); + io_sethandler(0x0388, 0x0002, readgus, NULL, NULL, writegus, NULL, NULL, gus); #if defined(DEV_BRANCH) && defined(USE_GUSMAX) - if (gus->max_ctrl) - ad1848_speed_changed(&gus->ad1848); + if (gus->type == GUS_MAX) { + ad1848_init(&gus->ad1848, AD1848_TYPE_CS4231); + ad1848_setirq(&gus->ad1848, 5); + ad1848_setdma(&gus->ad1848, 3); + io_sethandler(0x10C + gus->base, 4, + ad1848_read, NULL, NULL, ad1848_write, NULL, NULL, &gus->ad1848); + } +#endif + + timer_add(&gus->samp_timer, gus_poll_wave, gus, 1); + timer_add(&gus->timer_1, gus_poll_timer_1, gus, 1); + timer_add(&gus->timer_2, gus_poll_timer_2, gus, 1); + + sound_add_handler(gus_get_buffer, gus); + + if (device_get_config_int("receive_input")) + midi_in_handler(1, gus_input_msg, gus_input_sysex, gus); + + return gus; +} + +void +gus_close(void *priv) +{ + gus_t *gus = (gus_t *) priv; + + free(gus->ram); + free(gus); +} + +void +gus_speed_changed(void *priv) +{ + gus_t *gus = (gus_t *) priv; + + if (gus->voices < 14) + gus->samp_latch = (uint64_t) (TIMER_USEC * (1000000.0 / 44100.0)); + else + gus->samp_latch = (uint64_t) (TIMER_USEC * (1000000.0 / gusfreqs[gus->voices - 14])); + +#if defined(DEV_BRANCH) && defined(USE_GUSMAX) + if ((gus->type == GUS_MAX) && (gus->max_ctrl)) + ad1848_speed_changed(&gus->ad1848); #endif } static const device_config_t gus_config[] = { - { - "type", "GUS type", CONFIG_SELECTION, "", 0, "", { 0 }, - { - { - "Classic", GUS_CLASSIC - }, + // clang-format off + { + .name = "type", + .description = "GUS type", + .type = CONFIG_SELECTION, + .default_string = "", + .default_int = 0, + .file_filter = "", + .spinner = { 0 }, + .selection = { + { + .description = "Classic", + .value = GUS_CLASSIC + }, #if defined(DEV_BRANCH) && defined(USE_GUSMAX) - { - "MAX", GUS_MAX - }, + { + .description = "MAX", + .value = GUS_MAX + }, #endif - { - NULL - } - }, - }, - { - "base", "Address", CONFIG_HEX16, "", 0x220, "", { 0 }, - { - { - "210H", 0x210 - }, - { - "220H", 0x220 - }, - { - "230H", 0x230 - }, - { - "240H", 0x240 - }, - { - "250H", 0x250 - }, - { - "260H", 0x260 - }, - }, - }, - { - "gus_ram", "Onboard RAM", CONFIG_SELECTION, "", 0, "", { 0 }, - { - { - "256 KB", 0 - }, - { - "512 KB", 1 - }, - { - "1 MB", 2 - }, - { - NULL - } - } - }, - { - "receive_input", "Receive input (SB MIDI)", CONFIG_BINARY, "", 1 - }, - { - "", "", -1 - } + { NULL } + }, + }, + { + .name = "base", + .description = "Address", + .type = CONFIG_HEX16, + .default_string = "", + .default_int = 0x220, + .file_filter = "", + .spinner = { 0 }, + .selection = { + { + .description = "210H", + .value = 0x210 + }, + { + .description = "220H", + .value = 0x220 + }, + { + .description = "230H", + .value = 0x230 + }, + { + .description = "240H", + .value = 0x240 + }, + { + .description = "250H", + .value = 0x250 + }, + { + .description = "260H", + .value = 0x260 + }, + }, + }, + { + .name = "gus_ram", + "Onboard RAM", + .type = CONFIG_SELECTION, + .default_string = "", + .default_int = 0, + .file_filter = "", + .spinner = { 0 }, + .selection = { + { + .description = "256 KB", + .value = 0 + }, + { + .description = "512 KB", + .value = 1 + }, + { + .description = "1 MB", + .value = 2 + }, + { NULL } + } + }, + { + .name = "receive_input", + .description = "Receive input (SB MIDI)", + .type = CONFIG_BINARY, + .default_string = "", + .default_int = 1 + }, + { .name = "", .description = "", .type = CONFIG_END } +// clang-format off }; -const device_t gus_device = -{ - "Gravis UltraSound", - "gus", - DEVICE_ISA | DEVICE_AT, - 0, - gus_init, gus_close, NULL, - { NULL }, - gus_speed_changed, - NULL, - gus_config +const device_t gus_device = { + .name = "Gravis UltraSound", + .internal_name = "gus", + .flags = DEVICE_ISA | DEVICE_AT, + .local = 0, + .init = gus_init, + .close = gus_close, + .reset = gus_reset, + { .available = NULL }, + .speed_changed = gus_speed_changed, + .force_redraw = NULL, + .config = gus_config }; diff --git a/src/sound/snd_lpt_dac.c b/src/sound/snd_lpt_dac.c index 5781a9880..8fb526f14 100644 --- a/src/sound/snd_lpt_dac.c +++ b/src/sound/snd_lpt_dac.c @@ -1,129 +1,134 @@ -#include #include -#include +#include #include +#include #include -#include <86box/86box.h> + #include "cpu.h" -#include <86box/machine.h> -#include <86box/lpt.h> -#include <86box/timer.h> -#include <86box/sound.h> +#include <86box/86box.h> #include <86box/filters.h> +#include <86box/lpt.h> +#include <86box/machine.h> +#include <86box/sound.h> +#include <86box/timer.h> +#include <86box/plat_unused.h> -typedef struct lpt_dac_t -{ - void *lpt; +typedef struct lpt_dac_t { + void *lpt; - uint8_t dac_val_l, dac_val_r; - - int is_stereo; - int channel; - - int16_t buffer[2][SOUNDBUFLEN]; - int pos; + uint8_t dac_val_l; + uint8_t dac_val_r; + + int is_stereo; + int channel; + + int16_t buffer[2][SOUNDBUFLEN]; + int pos; } lpt_dac_t; -static void dac_update(lpt_dac_t *lpt_dac) +static void +dac_update(lpt_dac_t *lpt_dac) { - for (; lpt_dac->pos < sound_pos_global; lpt_dac->pos++) - { - lpt_dac->buffer[0][lpt_dac->pos] = (int8_t)(lpt_dac->dac_val_l ^ 0x80) * 0x40; - lpt_dac->buffer[1][lpt_dac->pos] = (int8_t)(lpt_dac->dac_val_r ^ 0x80) * 0x40; - } + for (; lpt_dac->pos < sound_pos_global; lpt_dac->pos++) { + lpt_dac->buffer[0][lpt_dac->pos] = (int8_t) (lpt_dac->dac_val_l ^ 0x80) * 0x40; + lpt_dac->buffer[1][lpt_dac->pos] = (int8_t) (lpt_dac->dac_val_r ^ 0x80) * 0x40; + } } - -static void dac_write_data(uint8_t val, void *p) +static void +dac_write_data(uint8_t val, void *priv) { - lpt_dac_t *lpt_dac = (lpt_dac_t *)p; + lpt_dac_t *lpt_dac = (lpt_dac_t *) priv; - if (lpt_dac->is_stereo) - { - if (lpt_dac->channel) - lpt_dac->dac_val_r = val; - else - lpt_dac->dac_val_l = val; - } - else - lpt_dac->dac_val_l = lpt_dac->dac_val_r = val; - dac_update(lpt_dac); + if (lpt_dac->is_stereo) { + if (lpt_dac->channel) + lpt_dac->dac_val_r = val; + else + lpt_dac->dac_val_l = val; + } else + lpt_dac->dac_val_l = lpt_dac->dac_val_r = val; + dac_update(lpt_dac); } -static void dac_write_ctrl(uint8_t val, void *p) +static void +dac_write_ctrl(uint8_t val, void *priv) { - lpt_dac_t *lpt_dac = (lpt_dac_t *)p; + lpt_dac_t *lpt_dac = (lpt_dac_t *) priv; - if (lpt_dac->is_stereo) - lpt_dac->channel = val & 0x01; + if (lpt_dac->is_stereo) + lpt_dac->channel = val & 0x01; } -static uint8_t dac_read_status(void *p) +static uint8_t +dac_read_status(UNUSED(void *priv)) { - return 0x0f; + return 0x0f; } - -static void dac_get_buffer(int32_t *buffer, int len, void *p) +static void +dac_get_buffer(int32_t *buffer, int len, void *priv) { - lpt_dac_t *lpt_dac = (lpt_dac_t *)p; - int c; - - dac_update(lpt_dac); - - for (c = 0; c < len; c++) - { - buffer[c*2] += dac_iir(0, lpt_dac->buffer[0][c]); - buffer[c*2 + 1] += dac_iir(1, lpt_dac->buffer[1][c]); - } - lpt_dac->pos = 0; + lpt_dac_t *lpt_dac = (lpt_dac_t *) priv; + + dac_update(lpt_dac); + + for (int c = 0; c < len; c++) { + buffer[c * 2] += dac_iir(0, lpt_dac->buffer[0][c]); + buffer[c * 2 + 1] += dac_iir(1, lpt_dac->buffer[1][c]); + } + lpt_dac->pos = 0; } -static void *dac_init(void *lpt) +static void * +dac_init(void *lpt) { - lpt_dac_t *lpt_dac = malloc(sizeof(lpt_dac_t)); - memset(lpt_dac, 0, sizeof(lpt_dac_t)); + lpt_dac_t *lpt_dac = malloc(sizeof(lpt_dac_t)); + memset(lpt_dac, 0, sizeof(lpt_dac_t)); - lpt_dac->lpt = lpt; + lpt_dac->lpt = lpt; - sound_add_handler(dac_get_buffer, lpt_dac); - - return lpt_dac; -} -static void *dac_stereo_init(void *lpt) -{ - lpt_dac_t *lpt_dac = dac_init(lpt); - - lpt_dac->is_stereo = 1; - - return lpt_dac; -} -static void dac_close(void *p) -{ - lpt_dac_t *lpt_dac = (lpt_dac_t *)p; - - free(lpt_dac); + sound_add_handler(dac_get_buffer, lpt_dac); + + return lpt_dac; } -const lpt_device_t lpt_dac_device = +static void * +dac_stereo_init(void *lpt) { - "LPT DAC / Covox Speech Thing", - dac_init, - dac_close, - dac_write_data, - dac_write_ctrl, - NULL, - dac_read_status, - NULL + lpt_dac_t *lpt_dac = dac_init(lpt); + + lpt_dac->is_stereo = 1; + + return lpt_dac; +} +static void +dac_close(void *priv) +{ + lpt_dac_t *lpt_dac = (lpt_dac_t *) priv; + + free(lpt_dac); +} + +const lpt_device_t lpt_dac_device = { + .name = "LPT DAC / Covox Speech Thing", + .internal_name = "lpt_dac", + .init = dac_init, + .close = dac_close, + .write_data = dac_write_data, + .write_ctrl = dac_write_ctrl, + .read_data = NULL, + .read_status = dac_read_status, + .read_ctrl = NULL }; -const lpt_device_t lpt_dac_stereo_device = -{ - "Stereo LPT DAC", - dac_stereo_init, - dac_close, - dac_write_data, - dac_write_ctrl, - NULL, - dac_read_status, - NULL + +const lpt_device_t lpt_dac_stereo_device = { + .name = "Stereo LPT DAC", + .internal_name = "lpt_dac_stereo", + .init = dac_stereo_init, + .close = dac_close, + .write_data = dac_write_data, + .write_ctrl = dac_write_ctrl, + .read_data = NULL, + .read_status = dac_read_status, + .read_ctrl = NULL }; diff --git a/src/sound/snd_lpt_dss.c b/src/sound/snd_lpt_dss.c index 3c735298c..bd794fffb 100644 --- a/src/sound/snd_lpt_dss.c +++ b/src/sound/snd_lpt_dss.c @@ -1,141 +1,146 @@ -#include #include -#include +#include #include +#include #include -#include <86box/86box.h> + #include "cpu.h" -#include <86box/machine.h> -#include <86box/timer.h> -#include <86box/lpt.h> -#include <86box/sound.h> +#include <86box/86box.h> #include <86box/filters.h> +#include <86box/lpt.h> +#include <86box/machine.h> +#include <86box/sound.h> +#include <86box/timer.h> +#include <86box/plat_unused.h> -typedef struct dss_t -{ - void *lpt; +typedef struct dss_t { + void *lpt; - uint8_t fifo[16]; - int read_idx, write_idx; - - uint8_t dac_val, - status; - - pc_timer_t timer; - - int16_t buffer[SOUNDBUFLEN]; - int pos; + uint8_t fifo[16]; + int read_idx; + int write_idx; + + uint8_t dac_val; + uint8_t status; + + pc_timer_t timer; + + int16_t buffer[SOUNDBUFLEN]; + int pos; } dss_t; -static void dss_update(dss_t *dss) +static void +dss_update(dss_t *dss) { - for (; dss->pos < sound_pos_global; dss->pos++) - dss->buffer[dss->pos] = (int8_t)(dss->dac_val ^ 0x80) * 0x40; + for (; dss->pos < sound_pos_global; dss->pos++) + dss->buffer[dss->pos] = (int8_t) (dss->dac_val ^ 0x80) * 0x40; } - -static void dss_update_status(dss_t *dss) +static void +dss_update_status(dss_t *dss) { - uint8_t old = dss->status; + uint8_t old = dss->status; - dss->status &= ~0x40; + dss->status &= ~0x40; - if ((dss->write_idx - dss->read_idx) >= 16) - dss->status |= 0x40; + if ((dss->write_idx - dss->read_idx) >= 16) + dss->status |= 0x40; - if ((old & 0x40) && !(dss->status & 0x40)) - lpt_irq(dss->lpt, 1); + if ((old & 0x40) && !(dss->status & 0x40)) + lpt_irq(dss->lpt, 1); } - -static void dss_write_data(uint8_t val, void *p) +static void +dss_write_data(uint8_t val, void *priv) { - dss_t *dss = (dss_t *)p; + dss_t *dss = (dss_t *) priv; - if ((dss->write_idx - dss->read_idx) < 16) - { - dss->fifo[dss->write_idx & 15] = val; - dss->write_idx++; - dss_update_status(dss); - } + if ((dss->write_idx - dss->read_idx) < 16) { + dss->fifo[dss->write_idx & 15] = val; + dss->write_idx++; + dss_update_status(dss); + } } -static void dss_write_ctrl(uint8_t val, void *p) +static void +dss_write_ctrl(UNUSED(uint8_t val), UNUSED(void *priv)) { + // } -static uint8_t dss_read_status(void *p) +static uint8_t +dss_read_status(void *priv) { - dss_t *dss = (dss_t *)p; + const dss_t *dss = (dss_t *) priv; - return dss->status | 0x0f; + return dss->status | 0x0f; } - -static void dss_get_buffer(int32_t *buffer, int len, void *p) +static void +dss_get_buffer(int32_t *buffer, int len, void *priv) { - dss_t *dss = (dss_t *)p; - int c; - int16_t val; - float fval; - - dss_update(dss); - - for (c = 0; c < len*2; c += 2) - { - fval = dss_iir((float)dss->buffer[c >> 1]); - val = (float) fval; - - buffer[c] += val; - buffer[c+1] += val; - } + dss_t *dss = (dss_t *) priv; + int16_t val; + float fval; - dss->pos = 0; + dss_update(dss); + + for (int c = 0; c < len * 2; c += 2) { + fval = dss_iir((float) dss->buffer[c >> 1]); + val = fval; + + buffer[c] += val; + buffer[c + 1] += val; + } + + dss->pos = 0; } -static void dss_callback(void *p) +static void +dss_callback(void *priv) { - dss_t *dss = (dss_t *)p; + dss_t *dss = (dss_t *) priv; - dss_update(dss); + dss_update(dss); - if ((dss->write_idx - dss->read_idx) > 0) - { - dss->dac_val = dss->fifo[dss->read_idx & 15]; - dss->read_idx++; - dss_update_status(dss); - } + if ((dss->write_idx - dss->read_idx) > 0) { + dss->dac_val = dss->fifo[dss->read_idx & 15]; + dss->read_idx++; + dss_update_status(dss); + } - timer_advance_u64(&dss->timer, (TIMER_USEC * (1000000.0 / 7000.0))); + timer_advance_u64(&dss->timer, (TIMER_USEC * (1000000.0 / 7000.0))); } -static void *dss_init(void *lpt) +static void * +dss_init(void *lpt) { - dss_t *dss = malloc(sizeof(dss_t)); - memset(dss, 0, sizeof(dss_t)); + dss_t *dss = malloc(sizeof(dss_t)); + memset(dss, 0, sizeof(dss_t)); - dss->lpt = lpt; + dss->lpt = lpt; - sound_add_handler(dss_get_buffer, dss); - timer_add(&dss->timer, dss_callback, dss, 1); + sound_add_handler(dss_get_buffer, dss); + timer_add(&dss->timer, dss_callback, dss, 1); - return dss; + return dss; } -static void dss_close(void *p) +static void +dss_close(void *priv) { - dss_t *dss = (dss_t *)p; - - free(dss); + dss_t *dss = (dss_t *) priv; + + free(dss); } -const lpt_device_t dss_device = -{ - "Disney Sound Source", - dss_init, - dss_close, - dss_write_data, - dss_write_ctrl, - NULL, - dss_read_status, - NULL +const lpt_device_t dss_device = { + .name = "Disney Sound Source", + .internal_name = "dss", + .init = dss_init, + .close = dss_close, + .write_data = dss_write_data, + .write_ctrl = dss_write_ctrl, + .read_data = NULL, + .read_status = dss_read_status, + .read_ctrl = NULL }; diff --git a/src/sound/snd_mpu401.c b/src/sound/snd_mpu401.c index 7183195d6..a8c9d3e3c 100644 --- a/src/sound/snd_mpu401.c +++ b/src/sound/snd_mpu401.c @@ -1,1386 +1,1421 @@ /* - * 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. + * 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. + * This file is part of the 86Box distribution. * - * Roland MPU-401 emulation. + * Roland MPU-401 emulation. * * * - * Authors: Sarah Walker, - * DOSBox Team, - * Miran Grca, - * TheCollector1995, + * Authors: DOSBox Team, + * Miran Grca, + * TheCollector1995, * - * Copyright 2008-2020 Sarah Walker. - * Copyright 2008-2020 DOSBox Team. - * Copyright 2016-2020 Miran Grca. + * Copyright 2008-2020 DOSBox Team. + * Copyright 2016-2020 Miran Grca. + * Copyright 2016-2020 TheCollector1995. */ +#include #include #include #include -#include #include -#include +#include #include #define HAVE_STDARG_H + #include <86box/86box.h> #include <86box/device.h> -#include <86box/plat.h> #include <86box/io.h> #include <86box/machine.h> #include <86box/mca.h> -#include <86box/pic.h> -#include <86box/timer.h> -#include <86box/sound.h> -#include <86box/snd_mpu401.h> #include <86box/midi.h> +#include <86box/pic.h> +#include <86box/plat.h> +#include <86box/timer.h> +#include <86box/snd_mpu401.h> +#include <86box/sound.h> +#include <86box/plat_unused.h> - -static uint32_t MPUClockBase[8] = {48,72,96,120,144,168,192}; -static uint8_t cth_data[16] = {0,0,0,0,1,0,0,0,1,0,1,0,1,1,1,0}; - +static uint32_t MPUClockBase[8] = { 48, 72, 96, 120, 144, 168, 192 }; +static uint8_t cth_data[16] = { 0, 0, 0, 0, 1, 0, 0, 0, 1, 0, 1, 0, 1, 1, 1, 0 }; enum { STATUS_OUTPUT_NOT_READY = 0x40, STATUS_INPUT_NOT_READY = 0x80 }; - int mpu401_standalone_enable = 0; - static void MPU401_WriteCommand(mpu_t *mpu, uint8_t val); static void MPU401_IntelligentOut(mpu_t *mpu, uint8_t track); static void MPU401_EOIHandler(void *priv); -static void MPU401_EOIHandlerDispatch(void *p); +static void MPU401_EOIHandlerDispatch(void *priv); static void MPU401_NotesOff(mpu_t *mpu, int i); - #ifdef ENABLE_MPU401_LOG int mpu401_do_log = ENABLE_MPU401_LOG; - static void mpu401_log(const char *fmt, ...) { va_list ap; if (mpu401_do_log) { - va_start(ap, fmt); - pclog_ex(fmt, ap); - va_end(ap); + va_start(ap, fmt); + pclog_ex(fmt, ap); + va_end(ap); } } #else -#define mpu401_log(fmt, ...) +# define mpu401_log(fmt, ...) #endif - static void MPU401_ReCalcClock(mpu_t *mpu) { - int32_t maxtempo = 240, mintempo = 16; + int32_t mintempo = 16; + int32_t maxtempo = 240; int32_t freq; if (mpu->clock.timebase < 72) { - maxtempo = 240; - mintempo = 32; + maxtempo = 240; + mintempo = 32; } else if (mpu->clock.timebase < 120) { - maxtempo = 240; - mintempo = 16; + maxtempo = 240; + mintempo = 16; } else if (mpu->clock.timebase < 168) { - maxtempo = 208; - mintempo = 8; + maxtempo = 208; + mintempo = 8; } else { - maxtempo = 179; - mintempo = 8; + maxtempo = 179; + mintempo = 8; } - mpu->clock.freq = ((uint32_t)(mpu->clock.tempo * 2 * mpu->clock.tempo_rel)) >> 6; - mpu->clock.freq = mpu->clock.timebase * (mpu->clock.freq < (mintempo * 2) ? mintempo : - ((mpu->clock.freq / 2) < maxtempo ? (mpu->clock.freq / 2) : maxtempo)); + mpu->clock.freq = ((uint32_t) (mpu->clock.tempo * 2 * mpu->clock.tempo_rel)) >> 6; + mpu->clock.freq = mpu->clock.timebase * (mpu->clock.freq < (mintempo * 2) ? mintempo : ((mpu->clock.freq / 2) < maxtempo ? (mpu->clock.freq / 2) : maxtempo)); if (mpu->state.sync_in) { - freq = (int32_t)((float)(mpu->clock.freq) * mpu->clock.freq_mod); - if ((freq > (mpu->clock.timebase * mintempo)) && (freq < (mpu->clock.timebase * maxtempo))) - mpu->clock.freq = freq; - } + freq = (int32_t) ((float) (mpu->clock.freq) * mpu->clock.freq_mod); + if ((freq > (mpu->clock.timebase * mintempo)) && (freq < (mpu->clock.timebase * maxtempo))) + mpu->clock.freq = freq; + } } +static void +MPU401_ReStartClock(mpu_t *mpu) +{ + if (mpu->clock.active) { + timer_disable(&mpu->mpu401_event_callback); + timer_set_delay_u64(&mpu->mpu401_event_callback, (MPU401_TIMECONSTANT / mpu->clock.freq) * 1000 * TIMER_USEC); + } +} static void MPU401_StartClock(mpu_t *mpu) { + mpu401_log("MPU401_StartClock(): %i, %i, %i, %i\n", mpu->clock.active, mpu->state.clock_to_host, + mpu->state.playing, (mpu->state.rec == M_RECON)); if (mpu->clock.active) - return; - if (!(mpu->state.clock_to_host || mpu->state.playing || (mpu->state.rec == M_RECON))) - return; + return; + if (mpu->state.clock_to_host || mpu->state.playing || (mpu->state.rec == M_RECON)) + return; mpu->clock.active = 1; timer_set_delay_u64(&mpu->mpu401_event_callback, (MPU401_TIMECONSTANT / mpu->clock.freq) * 1000 * TIMER_USEC); } - static void MPU401_StopClock(mpu_t *mpu) { - if (mpu->state.clock_to_host || mpu->state.playing || (mpu->state.rec == M_RECON)) - return; + if (!mpu->state.clock_to_host && !mpu->state.playing && (mpu->state.rec == M_RECOFF)) + return; mpu->clock.active = 0; timer_disable(&mpu->mpu401_event_callback); } - static void MPU401_RunClock(mpu_t *mpu) { if (!mpu->clock.active) { - timer_disable(&mpu->mpu401_event_callback); - return; + timer_disable(&mpu->mpu401_event_callback); + return; } - timer_set_delay_u64(&mpu->mpu401_event_callback, (MPU401_TIMECONSTANT / mpu->clock.freq) * 1000 * TIMER_USEC); - mpu401_log("Next event after %i us (time constant: %i)\n", (uint64_t) ((MPU401_TIMECONSTANT/mpu->clock.freq) * 1000 * TIMER_USEC), (int) MPU401_TIMECONSTANT); + timer_advance_u64(&mpu->mpu401_event_callback, (MPU401_TIMECONSTANT / mpu->clock.freq) * 1000 * TIMER_USEC); +#if 0 + mpu401_log("Next event after %" PRIu64 " us (time constant: %i)\n", (uint64_t) ((MPU401_TIMECONSTANT / mpu->clock.freq) * 1000 * TIMER_USEC), (int) MPU401_TIMECONSTANT); +#endif } - static void -MPU401_QueueByteEx(mpu_t *mpu, uint8_t data, int irq) +MPU401_QueueByteEx(mpu_t *mpu, uint8_t data, UNUSED(int irq)) { if (mpu->state.block_ack) { - mpu->state.block_ack = 0; - return; + mpu->state.block_ack = 0; + return; } if (mpu->queue_used == 0) { - if (mpu->ext_irq_update) - mpu->ext_irq_update(mpu->priv, 1); - else { - mpu->state.irq_pending = 1; - picint(1 << mpu->irq); - } + if (mpu->ext_irq_update) + mpu->ext_irq_update(mpu->priv, 1); + else { + mpu->state.irq_pending = 1; + picint(1 << mpu->irq); + } } if (mpu->queue_used < MPU401_QUEUE) { - int pos = mpu->queue_used+mpu->queue_pos; + int pos = mpu->queue_used + mpu->queue_pos; - if (mpu->queue_pos >= MPU401_QUEUE) - mpu->queue_pos -= MPU401_QUEUE; - if (pos>=MPU401_QUEUE) - pos-=MPU401_QUEUE; + if (mpu->queue_pos >= MPU401_QUEUE) + mpu->queue_pos -= MPU401_QUEUE; + if (pos >= MPU401_QUEUE) + pos -= MPU401_QUEUE; - mpu->queue_used++; - mpu->queue[pos] = data; + mpu->queue_used++; + mpu->queue[pos] = data; } } - static void -MPU401_QueueByte(mpu_t *mpu, uint8_t data) +MPU401_QueueByte(mpu_t *mpu, uint8_t data) { MPU401_QueueByteEx(mpu, data, 1); } - static int MPU401_IRQPending(mpu_t *mpu) { int irq_pending; if (mpu->ext_irq_pending) - irq_pending = mpu->ext_irq_pending(mpu->priv); + irq_pending = mpu->ext_irq_pending(mpu->priv); else - irq_pending = mpu->state.irq_pending; + irq_pending = mpu->state.irq_pending; return irq_pending; } - static void -MPU401_RecQueueBuffer(mpu_t *mpu, uint8_t *buf, uint32_t len, int block) +MPU401_RecQueueBuffer(mpu_t *mpu, uint8_t *buf, uint32_t len, UNUSED(int block)) { uint32_t cnt = 0; - int pos; + int pos; while (cnt < len) { - if (mpu->rec_queue_used < MPU401_INPUT_QUEUE) { - pos = mpu->rec_queue_used + mpu->rec_queue_pos; - if (pos >= MPU401_INPUT_QUEUE) - pos -= MPU401_INPUT_QUEUE; - mpu->rec_queue[pos] = buf[cnt]; - mpu->rec_queue_used++; - if ((!mpu->state.sysex_in_finished) && (buf[cnt] == MSG_EOX)) { - /* finish sysex */ - mpu->state.sysex_in_finished = 1; - break; - } - cnt++; - } + if (mpu->rec_queue_used < MPU401_INPUT_QUEUE) { + pos = mpu->rec_queue_used + mpu->rec_queue_pos; + if (pos >= MPU401_INPUT_QUEUE) + pos -= MPU401_INPUT_QUEUE; + mpu->rec_queue[pos] = buf[cnt]; + mpu->rec_queue_used++; + if ((!mpu->state.sysex_in_finished) && (buf[cnt] == MSG_EOX)) { + /* finish sysex */ + mpu->state.sysex_in_finished = 1; + break; + } + cnt++; + } } if (mpu->queue_used == 0) { - if (mpu->state.rec_copy || MPU401_IRQPending(mpu)) { - if (MPU401_IRQPending(mpu)) { - if (mpu->ext_irq_update) - mpu->ext_irq_update(mpu->priv, 0); - else { - mpu->state.irq_pending = 0; - picintc(1 << mpu->irq); - } - } - return; - } - mpu->state.rec_copy = 1; - if (mpu->rec_queue_pos >= MPU401_INPUT_QUEUE) - mpu->rec_queue_pos -= MPU401_INPUT_QUEUE; - MPU401_QueueByte(mpu, mpu->rec_queue[mpu->rec_queue_pos]); - mpu->rec_queue_used--; - mpu->rec_queue_pos++; + if (mpu->state.rec_copy || MPU401_IRQPending(mpu)) { + if (MPU401_IRQPending(mpu)) { + if (mpu->ext_irq_update) + mpu->ext_irq_update(mpu->priv, 0); + else { + mpu->state.irq_pending = 0; + picintc(1 << mpu->irq); + } + } + return; + } + mpu->state.rec_copy = 1; + if (mpu->rec_queue_pos >= MPU401_INPUT_QUEUE) + mpu->rec_queue_pos -= MPU401_INPUT_QUEUE; + MPU401_QueueByte(mpu, mpu->rec_queue[mpu->rec_queue_pos]); + mpu->rec_queue_used--; + mpu->rec_queue_pos++; } } - static void -MPU401_ClrQueue(mpu_t *mpu) +MPU401_ClrQueue(mpu_t *mpu) { - mpu->queue_used = 0; - mpu->queue_pos = 0; - mpu->rec_queue_used = 0; - mpu->rec_queue_pos = 0; + mpu->queue_used = 0; + mpu->queue_pos = 0; + mpu->rec_queue_used = 0; + mpu->rec_queue_pos = 0; mpu->state.sysex_in_finished = 1; if (mpu->ext_irq_update) - mpu->ext_irq_update(mpu->priv, 0); + mpu->ext_irq_update(mpu->priv, 0); else { - mpu->state.irq_pending = 0; - picintc(1 << mpu->irq); + mpu->state.irq_pending = 0; + picintc(1 << mpu->irq); } } - static void -MPU401_Reset(mpu_t *mpu) +MPU401_Reset(mpu_t *mpu) { uint8_t i; #ifdef DOSBOX_CODE if (mpu->mode == M_INTELLIGENT) { - if (mpu->ext_irq_update) - mpu->ext_irq_update(mpu->priv, 0); - else { - mpu->state.irq_pending = 0; - picintc(1 << mpu->irq); - } + if (mpu->ext_irq_update) + mpu->ext_irq_update(mpu->priv, 0); + else { + mpu->state.irq_pending = 0; + picintc(1 << mpu->irq); + } } #else if (mpu->ext_irq_update) - mpu->ext_irq_update(mpu->priv, 0); + mpu->ext_irq_update(mpu->priv, 0); else { - mpu->state.irq_pending = 0; - picintc(1 << mpu->irq); + mpu->state.irq_pending = 0; + picintc(1 << mpu->irq); } #endif - mpu->mode = M_INTELLIGENT; - mpu->midi_thru = 0; - mpu->state.rec = M_RECOFF; + mpu->mode = M_INTELLIGENT; + mpu->midi_thru = 0; + mpu->state.rec = M_RECOFF; mpu->state.eoi_scheduled = 0; - mpu->state.wsd = 0; - mpu->state.wsm = 0; - mpu->state.conductor = 0; - mpu->state.cond_req = 0; - mpu->state.cond_set = 0; - mpu->state.playing = 0; - mpu->state.run_irq = 0; - mpu->state.cmask = 0xff; + mpu->state.wsd = 0; + mpu->state.wsm = 0; + mpu->state.conductor = 0; + mpu->state.cond_req = 0; + mpu->state.cond_set = 0; + mpu->state.playing = 0; + mpu->state.run_irq = 0; + mpu->state.cmask = 0xff; mpu->state.amask = mpu->state.tmask = 0; - mpu->state.midi_mask = 0xffff; - mpu->state.command_byte = 0; - mpu->state.block_ack = 0; + mpu->state.midi_mask = 0xffff; + mpu->state.command_byte = 0; + mpu->state.block_ack = 0; mpu->clock.tempo = mpu->clock.old_tempo = 100; mpu->clock.timebase = mpu->clock.old_timebase = 120; mpu->clock.tempo_rel = mpu->clock.old_tempo_rel = 0x40; - mpu->clock.freq_mod = 1.0; - mpu->clock.tempo_grad = 0; + mpu->clock.freq_mod = 1.0; + mpu->clock.tempo_grad = 0; MPU401_StopClock(mpu); MPU401_ReCalcClock(mpu); for (i = 0; i < 4; i++) - mpu->clock.cth_rate[i] = 60; + mpu->clock.cth_rate[i] = 60; - mpu->clock.cth_counter = 0; - mpu->clock.midimetro = 12; - mpu->clock.metromeas = 8; + mpu->clock.cth_counter = 0; + mpu->clock.midimetro = 12; + mpu->clock.metromeas = 8; mpu->filter.rec_measure_end = 1; - mpu->filter.rt_out = 1; - mpu->filter.rt_affection = 1; + mpu->filter.rt_out = 1; + mpu->filter.rt_affection = 1; mpu->filter.allnotesoff_out = 1; - mpu->filter.all_thru = 1; - mpu->filter.midi_thru = 1; + mpu->filter.all_thru = 1; + mpu->filter.midi_thru = 1; mpu->filter.commonmsgs_thru = 1; /* Reset channel reference and input tables. */ for (i = 0; i < 4; i++) { - mpu->chanref[i].on = 1; - mpu->chanref[i].chan = i; - mpu->ch_toref[i] = i; + mpu->chanref[i].on = 1; + mpu->chanref[i].chan = i; + mpu->ch_toref[i] = i; } for (i = 0; i < 16; i++) { - mpu->inputref[i].on = 1; - mpu->inputref[i].chan = i; - if (i > 3) - mpu->ch_toref[i] = 4; /* Dummy reftable. */ + mpu->inputref[i].on = 1; + mpu->inputref[i].chan = i; + if (i > 3) + mpu->ch_toref[i] = 4; /* Dummy reftable. */ } MPU401_ClrQueue(mpu); mpu->state.data_onoff = -1; - mpu->state.req_mask = 0; - mpu->condbuf.counter = 0; - mpu->condbuf.type = T_OVERFLOW; + mpu->state.req_mask = 0; + mpu->condbuf.counter = 0; + mpu->condbuf.type = T_OVERFLOW; for (i = 0; i < 8; i++) { - mpu->playbuf[i].type = T_OVERFLOW; - mpu->playbuf[i].counter = 0; + mpu->playbuf[i].type = T_OVERFLOW; + mpu->playbuf[i].counter = 0; } /* Clear MIDI buffers, terminate notes. */ midi_clear_buffer(); for (i = 0xb0; i <= 0xbf; i++) { - midi_raw_out_byte(i); - midi_raw_out_byte(0x7b); - midi_raw_out_byte(0); + midi_raw_out_byte(i); + midi_raw_out_byte(0x7b); + midi_raw_out_byte(0); } } - static void -MPU401_ResetDone(void *priv) +MPU401_ResetDone(void *priv) { - mpu_t *mpu = (mpu_t *)priv; + mpu_t *mpu = (mpu_t *) priv; mpu401_log("MPU-401 reset callback\n"); timer_disable(&mpu->mpu401_reset_callback); mpu->state.reset = 0; - + if (mpu->state.cmd_pending) { - MPU401_WriteCommand(mpu, mpu->state.cmd_pending - 1); - mpu->state.cmd_pending = 0; + MPU401_WriteCommand(mpu, mpu->state.cmd_pending - 1); + mpu->state.cmd_pending = 0; } } - static void MPU401_WriteCommand(mpu_t *mpu, uint8_t val) -{ - uint8_t i, j, was_uart, recmsg[3]; +{ + uint8_t i; + uint8_t j; + uint8_t was_uart; + uint8_t recmsg[3]; if (mpu->state.reset) - mpu->state.cmd_pending = val + 1; + mpu->state.cmd_pending = val + 1; /* The only command recognized in UART mode is 0xFF: Reset and return to Intelligent mode. */ if ((val != 0xff) && (mpu->mode == M_UART)) - return; + return; /* In Intelligent mode, UART-only variants of the MPU-401 only support commands 0x3F and 0xFF. */ if (!mpu->intelligent && (val != 0x3f) && (val != 0xff)) - return; + return; /* Hack: Enable midi through after the first mpu401 command is written. */ mpu->midi_thru = 1; if (val <= 0x2f) { /* Sequencer state */ - int send_prchg = 0; - if ((val & 0xf) < 0xc) { - switch (val & 3) { /* MIDI realtime messages */ - case 1: - mpu->state.last_rtcmd = 0xfc; - if (mpu->filter.rt_out) - midi_raw_out_rt_byte(0xfc); - mpu->clock.meas_old = mpu->clock.measure_counter; - mpu->clock.cth_old = mpu->clock.cth_counter; - break; - case 2: - mpu->state.last_rtcmd = 0xfa; - if (mpu->filter.rt_out) - midi_raw_out_rt_byte(0xfb); - mpu->clock.measure_counter = mpu->clock.meas_old = 0; - mpu->clock.cth_counter = mpu->clock.cth_old = 0; - break; - case 3: - mpu->state.last_rtcmd = 0xfc; - if (mpu->filter.rt_out) - midi_raw_out_rt_byte(0xfa); - mpu->clock.measure_counter = mpu->clock.meas_old; - mpu->clock.cth_counter = mpu->clock.cth_old; - break; - } - switch (val & 0xc) { /* Playing */ - case 0x4: /* Stop */ - mpu->state.playing = 0; - MPU401_StopClock(mpu); - for (i = 0; i < 16; i++) - MPU401_NotesOff(mpu, i); - mpu->filter.prchg_mask = 0; - break; - case 0x8: /* Start */ - mpu->state.playing = 1; - MPU401_StartClock(mpu); - break; - } - switch (val & 0x30) { /* Recording */ - case 0: /* check if it waited for MIDI RT command */ - if (((val & 3) < 2) || !mpu->filter.rt_affection || (mpu->state.rec != M_RECSTB)) - break; - mpu->state.rec = M_RECON; - MPU401_StartClock(mpu); - if (mpu->filter.prchg_mask) - send_prchg = 1; - break; - case 0x10: /* Stop */ - mpu->state.rec = M_RECOFF; - MPU401_StopClock(mpu); - MPU401_QueueByte(mpu, MSG_MPU_ACK); - MPU401_QueueByte(mpu, mpu->clock.rec_counter); - MPU401_QueueByte(mpu, MSG_MPU_END); - mpu->filter.prchg_mask = 0; - mpu->clock.rec_counter = 0; - return; - case 0x20: /* Start */ - if (!(mpu->state.rec == M_RECON)) { - mpu->clock.rec_counter = 0; - mpu->state.rec = M_RECSTB; - } - if ((mpu->state.last_rtcmd == 0xfa) || (mpu->state.last_rtcmd == 0xfb)) { - mpu->clock.rec_counter = 0; - mpu->state.rec = M_RECON; - if (mpu->filter.prchg_mask) - send_prchg = 1; - MPU401_StartClock(mpu); - } - break; - } - } - MPU401_QueueByte(mpu, MSG_MPU_ACK); - /* record counter hack: needed by Prism, but sent only on cmd 0x20/0x26 (or breaks Ballade) */ - uint8_t rec_cnt = mpu->clock.rec_counter; - if (((val == 0x20) || (val == 0x26)) && (mpu->state.rec == M_RECON)) - MPU401_RecQueueBuffer(mpu, &rec_cnt, 1, 0); - - if (send_prchg) { - for (i = 0; i < 16; i++) { - if (mpu->filter.prchg_mask & (1 << i)) { - recmsg[0] = mpu->clock.rec_counter; - recmsg[1] = 0xc0 | i; - recmsg[2] = mpu->filter.prchg_buf[i]; - MPU401_RecQueueBuffer(mpu, recmsg, 3, 0); - mpu->filter.prchg_mask &= ~(1 << i); - } - } - } - } else if ((val >= 0xa0) && (val <= 0xa7)) /* Request play counter */ - MPU401_QueueByte(mpu, mpu->playbuf[val & 7].counter); - else if ((val >= 0xd0) && (val <= 0xd7)) { /* Send data */ - mpu->state.old_track = mpu->state.track; - mpu->state.track= val & 7; - mpu->state.wsd = 1; - mpu->state.wsm = 0; - mpu->state.wsd_start = 1; - } else if ((val < 0x80) && (val >= 0x40)) { /* Set reference table channel */ - mpu->chanref[(val >> 4) - 4].on = 1; - mpu->chanref[(val >> 4) - 4].chan = val & 0x0f; - mpu->chanref[(val >> 4) - 4].trmask = 0; - for (i = 0; i < 4; i++) - mpu->chanref[(val >> 4) - 4].key[i] = 0; - for (i = 0; i < 16; i++) { - if (mpu->ch_toref[i] == ((val >> 4) - 4)) - mpu->ch_toref[i] = 4; - } - mpu->ch_toref[val & 0x0f] = (val >> 4) - 4; - } else switch (val) { - case 0x30: /* Configuration 0x30 - 0x39 */ - mpu->filter.allnotesoff_out = 0; - break; - case 0x32: - mpu->filter.rt_out = 0; - break; - case 0x33: - mpu->filter.all_thru = 0; - mpu->filter.commonmsgs_thru = 0; - mpu->filter.midi_thru = 0; - for (i = 0; i < 16; i++) { - mpu->inputref[i].on = 0; - for (j = 0; j < 4; j++) - mpu->inputref[i].key[j] = 0; - } - break; - case 0x34: - mpu->filter.timing_in_stop = 1; - break; - case 0x35: - mpu->filter.modemsgs_in = 1; - break; - case 0x37: - mpu->filter.sysex_thru = 1; - break; - case 0x38: - mpu->filter.commonmsgs_in = 1; - break; - case 0x39: - mpu->filter.rt_in = 1; - break; - case 0x3f: /* UART mode */ - mpu401_log("MPU-401: Set UART mode %X\n",val); - MPU401_QueueByte(mpu, MSG_MPU_ACK); - mpu->mode = M_UART; - return; - case 0x80: /* Internal clock */ - if (mpu->clock.active && mpu->state.sync_in) { - timer_set_delay_u64(&mpu->mpu401_event_callback, (MPU401_TIMECONSTANT / mpu->clock.freq) * 1000 * TIMER_USEC); - mpu->clock.freq_mod = 1.0; - } - mpu->state.sync_in = 0; - break; - case 0x81: /* Sync to tape signal */ - case 0x82: /* Sync to MIDI */ - mpu->clock.ticks_in = 0; - mpu->state.sync_in = 1; - break; - case 0x86: case 0x87: /* Bender */ - mpu->filter.bender_in = !!(val & 1); - break; - case 0x88: case 0x89: /* MIDI through */ - mpu->filter.midi_thru = !!(val & 1); - for (i = 0; i < 16; i++) { - mpu->inputref[i].on = mpu->filter.midi_thru; - if (!(val & 1)) { - for (j = 0; j < 4; j++) - mpu->inputref[i].key[j] = 0; - } - } - break; - case 0x8a: case 0x8b: /* Data in stop */ - mpu->filter.data_in_stop = !!(val & 1); - break; - case 0x8c: case 0x8d: /* Send measure end */ - mpu->filter.rec_measure_end = !!(val & 1); - break; - case 0x8e: case 0x8f: /* Conductor */ - mpu->state.cond_set = !!(val & 1); - break; - case 0x90: case 0x91: /* Realtime affection */ - mpu->filter.rt_affection = !!(val & 1); - break; - case 0x94: /* Clock to host */ - mpu->state.clock_to_host = 0; - MPU401_StopClock(mpu); - break; - case 0x95: - mpu->state.clock_to_host = 1; - MPU401_StartClock(mpu); - break; - case 0x96: case 0x97: /* Sysex input allow */ - mpu->filter.sysex_in = !!(val & 1); - if (val & 1) - mpu->filter.sysex_thru = 0; - break; - case 0x98: case 0x99: case 0x9a: case 0x9b: /* Reference tables on/off */ - case 0x9c: case 0x9d: case 0x9e: case 0x9f: - mpu->chanref[(val - 0x98) / 2].on = !!(val & 1); - break; - /* Commands 0xa# returning data */ - case 0xab: /* Request and clear recording counter */ - MPU401_QueueByte(mpu, MSG_MPU_ACK); - MPU401_QueueByte(mpu, 0); - return; - case 0xac: /* Request version */ - MPU401_QueueByte(mpu, MSG_MPU_ACK); - MPU401_QueueByte(mpu, MPU401_VERSION); - return; - case 0xad: /* Request revision */ - MPU401_QueueByte(mpu, MSG_MPU_ACK); - MPU401_QueueByte(mpu, MPU401_REVISION); - return; - case 0xaf: /* Request tempo */ - MPU401_QueueByte(mpu, MSG_MPU_ACK); - MPU401_QueueByte(mpu, mpu->clock.tempo); - return; - case 0xb1: /* Reset relative tempo */ - mpu->clock.old_tempo_rel = mpu->clock.tempo_rel; - mpu->clock.tempo_rel = 0x40; - break; - case 0xb8: /* Clear play counters */ - mpu->state.last_rtcmd = 0; - for (i = 0; i < 8; i++) { - mpu->playbuf[i].counter = 0; - mpu->playbuf[i].type = T_OVERFLOW; - } - mpu->condbuf.counter = 0; - mpu->condbuf.type = T_OVERFLOW; - mpu->state.amask = mpu->state.tmask; - mpu->state.conductor = mpu->state.cond_set; - mpu->clock.cth_counter = mpu->clock.cth_old = 0; - mpu->clock.measure_counter = mpu->clock.meas_old = 0; - break; - case 0xb9: /* Clear play map */ - for (i = 0; i < 16; i++) - MPU401_NotesOff(mpu, i); - for (i = 0; i < 8; i++) { - mpu->playbuf[i].counter = 0; - mpu->playbuf[i].type = T_OVERFLOW; - } - mpu->state.last_rtcmd = 0; - mpu->clock.cth_counter = mpu->clock.cth_old = 0; - mpu->clock.measure_counter = mpu->clock.meas_old = 0; - break; - case 0xba: /* Clear record counter */ - mpu->clock.rec_counter = 0; - break; - case 0xc2: case 0xc3: case 0xc4: /* Internal timebase */ - case 0xc5: case 0xc6: case 0xc7: case 0xc8: - mpu->clock.timebase = MPUClockBase[val-0xc2]; - MPU401_ReCalcClock(mpu); - break; - case 0xdf: /* Send system message */ - mpu->state.wsd = 0; - mpu->state.wsm = 1; - mpu->state.wsd_start = 1; - break; - /* Commands with data byte */ - case 0xe0: case 0xe1: case 0xe2: case 0xe4: case 0xe6: - case 0xe7: case 0xec: case 0xed: case 0xee: case 0xef: - mpu->state.command_byte = val; - break; - case 0xff: /* Reset MPU-401 */ - mpu401_log("MPU-401: Reset %X\n", val); - timer_set_delay_u64(&mpu->mpu401_reset_callback, MPU401_RESETBUSY * 33LL * TIMER_USEC); - mpu->state.reset = 1; - was_uart = (mpu->mode == M_UART); - MPU401_Reset(mpu); - if (was_uart) - return; - break; + int send_prchg = 0; + if ((val & 0xf) < 0xc) { + switch (val & 3) { /* MIDI realtime messages */ + case 1: + mpu->state.last_rtcmd = 0xfc; + if (mpu->filter.rt_out) + midi_raw_out_rt_byte(0xfc); + mpu->clock.meas_old = mpu->clock.measure_counter; + mpu->clock.cth_old = mpu->clock.cth_counter; + break; + case 2: + mpu->state.last_rtcmd = 0xfa; + if (mpu->filter.rt_out) + midi_raw_out_rt_byte(0xfb); + mpu->clock.measure_counter = mpu->clock.meas_old = 0; + mpu->clock.cth_counter = mpu->clock.cth_old = 0; + break; + case 3: + mpu->state.last_rtcmd = 0xfc; + if (mpu->filter.rt_out) + midi_raw_out_rt_byte(0xfa); + mpu->clock.measure_counter = mpu->clock.meas_old; + mpu->clock.cth_counter = mpu->clock.cth_old; + break; - /* default: - mpu401_log("MPU-401:Unhandled command %X",val); */ - } + default: + break; + } + switch (val & 0xc) { /* Playing */ + case 0x4: /* Stop */ + MPU401_StopClock(mpu); + mpu->state.playing = 0; + for (i = 0; i < 16; i++) + MPU401_NotesOff(mpu, i); + mpu->filter.prchg_mask = 0; + break; + case 0x8: /* Start */ + MPU401_StartClock(mpu); + mpu->state.playing = 1; + MPU401_ClrQueue(mpu); + break; + + default: + break; + } + switch (val & 0x30) { /* Recording */ + case 0: /* check if it waited for MIDI RT command */ + if (((val & 3) < 2) || !mpu->filter.rt_affection || (mpu->state.rec != M_RECSTB)) + break; + MPU401_StartClock(mpu); + mpu->state.rec = M_RECON; + if (mpu->filter.prchg_mask) + send_prchg = 1; + break; + case 0x10: /* Stop */ + MPU401_StopClock(mpu); + mpu->state.rec = M_RECOFF; + MPU401_QueueByte(mpu, MSG_MPU_ACK); + MPU401_QueueByte(mpu, mpu->clock.rec_counter); + MPU401_QueueByte(mpu, MSG_MPU_END); + mpu->filter.prchg_mask = 0; + mpu->clock.rec_counter = 0; + return; + case 0x20: /* Start */ + if (!(mpu->state.rec == M_RECON)) { + mpu->clock.rec_counter = 0; + mpu->state.rec = M_RECSTB; + } + if ((mpu->state.last_rtcmd == 0xfa) || (mpu->state.last_rtcmd == 0xfb)) { + mpu->clock.rec_counter = 0; + mpu->state.rec = M_RECON; + if (mpu->filter.prchg_mask) + send_prchg = 1; + MPU401_StartClock(mpu); + } + break; + + default: + break; + } + } + MPU401_QueueByte(mpu, MSG_MPU_ACK); + /* record counter hack: needed by Prism, but sent only on cmd 0x20/0x26 (or breaks Ballade) */ + uint8_t rec_cnt = mpu->clock.rec_counter; + if (((val == 0x20) || (val == 0x26)) && (mpu->state.rec == M_RECON)) + MPU401_RecQueueBuffer(mpu, &rec_cnt, 1, 0); + + if (send_prchg) { + for (i = 0; i < 16; i++) { + if (mpu->filter.prchg_mask & (1 << i)) { + recmsg[0] = mpu->clock.rec_counter; + recmsg[1] = 0xc0 | i; + recmsg[2] = mpu->filter.prchg_buf[i]; + MPU401_RecQueueBuffer(mpu, recmsg, 3, 0); + mpu->filter.prchg_mask &= ~(1 << i); + } + } + } + } else if ((val >= 0xa0) && (val <= 0xa7)) /* Request play counter */ + MPU401_QueueByte(mpu, mpu->playbuf[val & 7].counter); + else if ((val >= 0xd0) && (val <= 0xd7)) { /* Send data */ + mpu->state.old_track = mpu->state.track; + mpu->state.track = val & 7; + mpu->state.wsd = 1; + mpu->state.wsm = 0; + mpu->state.wsd_start = 1; + } else if ((val < 0x80) && (val >= 0x40)) { /* Set reference table channel */ + mpu->chanref[(val >> 4) - 4].on = 1; + mpu->chanref[(val >> 4) - 4].chan = val & 0x0f; + mpu->chanref[(val >> 4) - 4].trmask = 0; + for (i = 0; i < 4; i++) + mpu->chanref[(val >> 4) - 4].key[i] = 0; + for (i = 0; i < 16; i++) { + if (mpu->ch_toref[i] == ((val >> 4) - 4)) + mpu->ch_toref[i] = 4; + } + mpu->ch_toref[val & 0x0f] = (val >> 4) - 4; + } else + switch (val) { + case 0x30: /* Configuration 0x30 - 0x39 */ + mpu->filter.allnotesoff_out = 0; + break; + case 0x32: + mpu->filter.rt_out = 0; + break; + case 0x33: + mpu->filter.all_thru = 0; + mpu->filter.commonmsgs_thru = 0; + mpu->filter.midi_thru = 0; + for (i = 0; i < 16; i++) { + mpu->inputref[i].on = 0; + for (j = 0; j < 4; j++) + mpu->inputref[i].key[j] = 0; + } + break; + case 0x34: + mpu->filter.timing_in_stop = 1; + break; + case 0x35: + mpu->filter.modemsgs_in = 1; + break; + case 0x37: + mpu->filter.sysex_thru = 1; + break; + case 0x38: + mpu->filter.commonmsgs_in = 1; + break; + case 0x39: + mpu->filter.rt_in = 1; + break; + case 0x3f: /* UART mode */ + mpu401_log("MPU-401: Set UART mode %X\n", val); + MPU401_QueueByte(mpu, MSG_MPU_ACK); + mpu->mode = M_UART; + return; + case 0x80: /* Internal clock */ + if (mpu->clock.active && mpu->state.sync_in) { + timer_set_delay_u64(&mpu->mpu401_event_callback, (MPU401_TIMECONSTANT / mpu->clock.freq) * 1000 * TIMER_USEC); + mpu->clock.freq_mod = 1.0; + } + mpu->state.sync_in = 0; + break; + case 0x81: /* Sync to tape signal */ + case 0x82: /* Sync to MIDI */ + mpu->clock.ticks_in = 0; + mpu->state.sync_in = 1; + break; + case 0x86: + case 0x87: /* Bender */ + mpu->filter.bender_in = !!(val & 1); + break; + case 0x88: + case 0x89: /* MIDI through */ + mpu->filter.midi_thru = !!(val & 1); + for (i = 0; i < 16; i++) { + mpu->inputref[i].on = mpu->filter.midi_thru; + if (!(val & 1)) { + for (j = 0; j < 4; j++) + mpu->inputref[i].key[j] = 0; + } + } + break; + case 0x8a: + case 0x8b: /* Data in stop */ + mpu->filter.data_in_stop = !!(val & 1); + break; + case 0x8c: + case 0x8d: /* Send measure end */ + mpu->filter.rec_measure_end = !!(val & 1); + break; + case 0x8e: + case 0x8f: /* Conductor */ + mpu->state.cond_set = !!(val & 1); + break; + case 0x90: + case 0x91: /* Realtime affection */ + mpu->filter.rt_affection = !!(val & 1); + break; + case 0x94: /* Clock to host */ + MPU401_StopClock(mpu); + mpu->state.clock_to_host = 0; + break; + case 0x95: + MPU401_StartClock(mpu); + mpu->state.clock_to_host = 1; + break; + case 0x96: + case 0x97: /* Sysex input allow */ + mpu->filter.sysex_in = !!(val & 1); + if (val & 1) + mpu->filter.sysex_thru = 0; + break; + case 0x98: + case 0x99: + case 0x9a: + case 0x9b: /* Reference tables on/off */ + case 0x9c: + case 0x9d: + case 0x9e: + case 0x9f: + mpu->chanref[(val - 0x98) / 2].on = !!(val & 1); + break; + /* Commands 0xa# returning data */ + case 0xab: /* Request and clear recording counter */ + MPU401_QueueByte(mpu, MSG_MPU_ACK); + MPU401_QueueByte(mpu, 0); + return; + case 0xac: /* Request version */ + MPU401_QueueByte(mpu, MSG_MPU_ACK); + MPU401_QueueByte(mpu, MPU401_VERSION); + return; + case 0xad: /* Request revision */ + MPU401_QueueByte(mpu, MSG_MPU_ACK); + MPU401_QueueByte(mpu, MPU401_REVISION); + return; + case 0xaf: /* Request tempo */ + MPU401_QueueByte(mpu, MSG_MPU_ACK); + MPU401_QueueByte(mpu, mpu->clock.tempo); + return; + case 0xb1: /* Reset relative tempo */ + mpu->clock.old_tempo_rel = mpu->clock.tempo_rel; + mpu->clock.tempo_rel = 0x40; + break; + case 0xb8: /* Clear play counters */ + mpu->state.last_rtcmd = 0; + for (i = 0; i < 8; i++) { + mpu->playbuf[i].counter = 0; + mpu->playbuf[i].type = T_OVERFLOW; + } + mpu->condbuf.counter = 0; + mpu->condbuf.type = T_OVERFLOW; + mpu->state.amask = mpu->state.tmask; + mpu->state.conductor = mpu->state.cond_set; + mpu->clock.cth_counter = mpu->clock.cth_old = 0; + mpu->clock.measure_counter = mpu->clock.meas_old = 0; + break; + case 0xb9: /* Clear play map */ + for (i = 0; i < 16; i++) + MPU401_NotesOff(mpu, i); + for (i = 0; i < 8; i++) { + mpu->playbuf[i].counter = 0; + mpu->playbuf[i].type = T_OVERFLOW; + } + mpu->state.last_rtcmd = 0; + mpu->clock.cth_counter = mpu->clock.cth_old = 0; + mpu->clock.measure_counter = mpu->clock.meas_old = 0; + break; + case 0xba: /* Clear record counter */ + mpu->clock.rec_counter = 0; + break; + case 0xc2: + case 0xc3: + case 0xc4: /* Internal timebase */ + case 0xc5: + case 0xc6: + case 0xc7: + case 0xc8: + mpu->clock.timebase = MPUClockBase[val - 0xc2]; + MPU401_ReCalcClock(mpu); + MPU401_ReStartClock(mpu); + break; + case 0xdf: /* Send system message */ + mpu->state.wsd = 0; + mpu->state.wsm = 1; + mpu->state.wsd_start = 1; + break; + /* Commands with data byte */ + case 0xe0: + case 0xe1: + case 0xe2: + case 0xe4: + case 0xe6: + case 0xe7: + case 0xec: + case 0xed: + case 0xee: + case 0xef: + mpu->state.command_byte = val; + break; + case 0xff: /* Reset MPU-401 */ + mpu401_log("MPU-401: Reset %X\n", val); + timer_set_delay_u64(&mpu->mpu401_reset_callback, MPU401_RESETBUSY * 33LL * TIMER_USEC); + mpu->state.reset = 1; + was_uart = (mpu->mode == M_UART); + MPU401_Reset(mpu); + if (was_uart) + return; + break; + + default: +#if 0 + mpu401_log("MPU-401:Unhandled command %X",val); +#endif + break; + } MPU401_QueueByte(mpu, MSG_MPU_ACK); } - static void -MPU401_WriteData(mpu_t *mpu, uint8_t val) +MPU401_WriteData(mpu_t *mpu, uint8_t val) { - static int length, cnt; - uint8_t i; + static int length; + static int cnt; #ifdef DOSBOX_CODE if (mpu->mode == M_UART) { - midi_raw_out_byte(val); - return; + midi_raw_out_byte(val); + return; } if (!mpu->intelligent) { - mpu->state.command_byte = 0; - return; + mpu->state.command_byte = 0; + return; } #else if (!mpu->intelligent || (mpu->mode == M_UART)) { - midi_raw_out_byte(val); - return; + midi_raw_out_byte(val); + return; } #endif - - switch (mpu->state.command_byte) { /* 0xe# command data */ - case 0x00: - break; - case 0xe0: /* Set tempo */ - mpu->state.command_byte = 0; - if (mpu->clock.tempo < 8) - mpu->clock.tempo = 8; - else if (mpu->clock.tempo > 250) - mpu->clock.tempo = 250; - else - mpu->clock.tempo = val; - MPU401_ReCalcClock(mpu); - return; - case 0xe1: /* Set relative tempo */ - mpu->state.command_byte = 0; - mpu->clock.old_tempo_rel = mpu->clock.tempo_rel; - mpu->clock.tempo_rel = val; - MPU401_ReCalcClock(mpu); - return; - case 0xe2: /* Set gradation for relative tempo */ - mpu->clock.tempo_grad = val; - MPU401_ReCalcClock(mpu); - return; - case 0xe4: /* Set MIDI clocks for metronome ticks */ - mpu->state.command_byte = 0; - mpu->clock.midimetro = val; - return; - case 0xe6: /* Set metronome ticks per measure */ - mpu->state.command_byte = 0; - mpu->clock.metromeas = val; - return; - case 0xe7: /* Set internal clock to host interval */ - mpu->state.command_byte = 0; - if (!val) - val = 64; - for (i = 0; i < 4; i++) - mpu->clock.cth_rate[i] = (val >> 2) + cth_data[(val & 3) * 4 + i]; - mpu->clock.cth_mode = 0; - return; - case 0xec: /* Set active track mask */ - mpu->state.command_byte = 0; - mpu->state.tmask = val; - return; - case 0xed: /* Set play counter mask */ - mpu->state.command_byte = 0; - mpu->state.cmask = val; - return; - case 0xee: /* Set 1-8 MIDI channel mask */ - mpu->state.command_byte = 0; - mpu->state.midi_mask &= 0xff00; - mpu->state.midi_mask |= val; - return; - case 0xef: /* Set 9-16 MIDI channel mask */ - mpu->state.command_byte = 0; - mpu->state.midi_mask &= 0x00ff; - mpu->state.midi_mask |= ((uint16_t) val) << 8; - return; - default: - mpu->state.command_byte = 0; - return; + switch (mpu->state.command_byte) { /* 0xe# command data */ + case 0x00: + break; + case 0xe0: /* Set tempo */ + mpu->state.command_byte = 0; + if (mpu->clock.tempo < 8) + mpu->clock.tempo = 8; + else if (mpu->clock.tempo > 250) + mpu->clock.tempo = 250; + else + mpu->clock.tempo = val; + MPU401_ReCalcClock(mpu); + MPU401_ReStartClock(mpu); + return; + case 0xe1: /* Set relative tempo */ + mpu->state.command_byte = 0; + mpu->clock.old_tempo_rel = mpu->clock.tempo_rel; + mpu->clock.tempo_rel = val; + MPU401_ReCalcClock(mpu); + MPU401_ReStartClock(mpu); + return; + case 0xe2: /* Set gradation for relative tempo */ + mpu->clock.tempo_grad = val; + MPU401_ReCalcClock(mpu); + MPU401_ReStartClock(mpu); + return; + case 0xe4: /* Set MIDI clocks for metronome ticks */ + mpu->state.command_byte = 0; + mpu->clock.midimetro = val; + return; + case 0xe6: /* Set metronome ticks per measure */ + mpu->state.command_byte = 0; + mpu->clock.metromeas = val; + return; + case 0xe7: /* Set internal clock to host interval */ + mpu->state.command_byte = 0; + if (!val) + val = 64; + for (uint8_t i = 0; i < 4; i++) + mpu->clock.cth_rate[i] = (val >> 2) + cth_data[(val & 3) * 4 + i]; + mpu->clock.cth_mode = 0; + return; + case 0xec: /* Set active track mask */ + mpu->state.command_byte = 0; + mpu->state.tmask = val; + return; + case 0xed: /* Set play counter mask */ + mpu->state.command_byte = 0; + mpu->state.cmask = val; + return; + case 0xee: /* Set 1-8 MIDI channel mask */ + mpu->state.command_byte = 0; + mpu->state.midi_mask &= 0xff00; + mpu->state.midi_mask |= val; + return; + case 0xef: /* Set 9-16 MIDI channel mask */ + mpu->state.command_byte = 0; + mpu->state.midi_mask &= 0x00ff; + mpu->state.midi_mask |= ((uint16_t) val) << 8; + return; + + default: + mpu->state.command_byte = 0; + return; } if (mpu->state.wsd && !mpu->state.track_req && !mpu->state.cond_req) { - /* Directly send MIDI message */ - if (mpu->state.wsd_start) { - mpu->state.wsd_start = 0; - cnt = 0; - switch (val & 0xf0) { - case 0xc0: case 0xd0: - length = mpu->playbuf[mpu->state.track].length = 2; - mpu->playbuf[mpu->state.track].type = T_MIDI_NORM; - break; - case 0x80: case 0x90: case 0xa0: case 0xb0:case 0xe0: - length = mpu->playbuf[mpu->state.track].length = 3; - mpu->playbuf[mpu->state.track].type = T_MIDI_NORM; - break; + /* Directly send MIDI message */ + if (mpu->state.wsd_start) { + mpu->state.wsd_start = 0; + cnt = 0; + switch (val & 0xf0) { + case 0xc0: + case 0xd0: + length = mpu->playbuf[mpu->state.track].length = 2; + mpu->playbuf[mpu->state.track].type = T_MIDI_NORM; + break; + case 0x80: + case 0x90: + case 0xa0: + case 0xb0: + case 0xe0: + length = mpu->playbuf[mpu->state.track].length = 3; + mpu->playbuf[mpu->state.track].type = T_MIDI_NORM; + break; - case 0xf0: - /* mpu401_log("MPU-401:Illegal WSD byte\n"); */ - mpu->state.wsd = 0; - mpu->state.track = mpu->state.old_track; - return; + case 0xf0: +#if 0 + mpu401_log("MPU-401:Illegal WSD byte\n"); +#endif + mpu->state.wsd = 0; + mpu->state.track = mpu->state.old_track; + return; - default: /* MIDI with running status */ - cnt++; - length = mpu->playbuf[mpu->state.track].length; - mpu->playbuf[mpu->state.track].type = T_MIDI_NORM; - } - } + default: /* MIDI with running status */ + cnt++; + length = mpu->playbuf[mpu->state.track].length; + mpu->playbuf[mpu->state.track].type = T_MIDI_NORM; + } + } - if (cnt < length) { - mpu->playbuf[mpu->state.track].value[cnt] = val; - cnt++; - } + if (cnt < length) { + mpu->playbuf[mpu->state.track].value[cnt] = val; + cnt++; + } - if (cnt == length) { - MPU401_IntelligentOut(mpu, mpu->state.track); - mpu->state.wsd = 0; - mpu->state.track = mpu->state.old_track; - } + if (cnt == length) { + MPU401_IntelligentOut(mpu, mpu->state.track); + mpu->state.wsd = 0; + mpu->state.track = mpu->state.old_track; + } - return; + return; } - if (mpu->state.wsm && !mpu->state.track_req && !mpu->state.cond_req) { /* Send system message */ - if (mpu->state.wsd_start) { - mpu->state.wsd_start = 0; - cnt = 0; - switch (val) { - case 0xf2: - length = 3; - break; + if (mpu->state.wsm && !mpu->state.track_req && !mpu->state.cond_req) { /* Send system message */ + if (mpu->state.wsd_start) { + mpu->state.wsd_start = 0; + cnt = 0; + switch (val) { + case 0xf2: + length = 3; + break; - case 0xf3: - length = 2; - break; + case 0xf3: + length = 2; + break; - case 0xf6: - length = 1; - break; + case 0xf6: + length = 1; + break; - case 0xf0: - length = 0; - break; + case 0xf0: + length = 0; + break; - default: - mpu->state.wsm = 0; - return; - } - } else if (val & 0x80) { - midi_raw_out_byte(MSG_EOX); - mpu->state.wsm = 0; - return; - } + default: + mpu->state.wsm = 0; + return; + } + } else if (val & 0x80) { + midi_raw_out_byte(MSG_EOX); + mpu->state.wsm = 0; + return; + } - if (!length || (cnt < length)) { - midi_raw_out_byte(val); - cnt++; - } + if (!length || (cnt < length)) { + midi_raw_out_byte(val); + cnt++; + } - if (cnt == length) - mpu->state.wsm = 0; + if (cnt == length) + mpu->state.wsm = 0; - return; + return; } if (mpu->state.cond_req) { - /* Command */ - switch (mpu->state.data_onoff) { - case -1: - return; - case 0: /* Timing byte */ - mpu->condbuf.length = 0; - if (val < 0xf0) - mpu->state.data_onoff++; - else { - mpu->state.cond_req = 0; - mpu->state.data_onoff = -1; - MPU401_EOIHandlerDispatch(mpu); - break; - } - mpu->state.send_now = !val ? 1 : 0; - mpu->condbuf.counter = val; - break; - case 1: /* Command byte #1 */ - mpu->condbuf.type = T_COMMAND; - if ((val == 0xf8) || (val == 0xf9) || (val == 0xfc)) - mpu->condbuf.type = T_OVERFLOW; - mpu->condbuf.value[mpu->condbuf.length] = val; - mpu->condbuf.length++; - if ((val & 0xf0) != 0xe0) { /*no cmd data byte*/ - MPU401_EOIHandler(mpu); - mpu->state.data_onoff = -1; - mpu->state.cond_req = 0; - } else - mpu->state.data_onoff++; - break; + /* Command */ + switch (mpu->state.data_onoff) { + case -1: + return; + case 0: /* Timing byte */ + mpu->condbuf.length = 0; + if (val < 0xf0) + mpu->state.data_onoff++; + else { + mpu->state.cond_req = 0; + mpu->state.data_onoff = -1; + MPU401_EOIHandlerDispatch(mpu); + break; + } + mpu->state.send_now = !val ? 1 : 0; + mpu->condbuf.counter = val; + break; + case 1: /* Command byte #1 */ + mpu->condbuf.type = T_COMMAND; + if ((val == 0xf8) || (val == 0xf9) || (val == 0xfc)) + mpu->condbuf.type = T_OVERFLOW; + mpu->condbuf.value[mpu->condbuf.length] = val; + mpu->condbuf.length++; + if ((val & 0xf0) != 0xe0) { /*no cmd data byte*/ + MPU401_EOIHandler(mpu); + mpu->state.data_onoff = -1; + mpu->state.cond_req = 0; + } else + mpu->state.data_onoff++; + break; - case 2:/* Command byte #2 */ - mpu->condbuf.value[mpu->condbuf.length]=val; - mpu->condbuf.length++; - MPU401_EOIHandler(mpu); - mpu->state.data_onoff = -1; - mpu->state.cond_req = 0; - break; - } - return; + case 2: /* Command byte #2 */ + mpu->condbuf.value[mpu->condbuf.length] = val; + mpu->condbuf.length++; + MPU401_EOIHandler(mpu); + mpu->state.data_onoff = -1; + mpu->state.cond_req = 0; + break; + + default: + break; + } + return; } switch (mpu->state.data_onoff) { - /* Data */ - case -1: - break; - case 0: /* Timing byte */ - if (val < 0xf0) - mpu->state.data_onoff++; - else { - mpu->state.data_onoff = -1; - MPU401_EOIHandlerDispatch(mpu); - mpu->state.track_req = 0; - return; - } - mpu->state.send_now = !val ? 1 : 0; - mpu->playbuf[mpu->state.track].counter = val; - break; - case 1: /* MIDI */ - cnt = 0; - mpu->state.data_onoff++; - switch (val & 0xf0) { - case 0xc0: case 0xd0: /* MIDI Message */ - length = mpu->playbuf[mpu->state.track].length = 2; - mpu->playbuf[mpu->state.track].type = T_MIDI_NORM; - break; - case 0x80: case 0x90: case 0xa0: case 0xb0: case 0xe0: - length = mpu->playbuf[mpu->state.track].length = 3; - mpu->playbuf[mpu->state.track].type = T_MIDI_NORM; - break; - case 0xf0: /* System message or mark */ - mpu->playbuf[mpu->state.track].sys_val = val; - if (val > 0xf7) { - mpu->playbuf[mpu->state.track].type = T_MARK; - if (val == 0xf9) - mpu->clock.measure_counter = 0; - } else { - /* mpu401_log("MPU-401:Illegal message"); */ - mpu->playbuf[mpu->state.track].type = T_OVERFLOW; - } - mpu->state.data_onoff = -1; - MPU401_EOIHandler(mpu); - mpu->state.track_req = 0; - return; - default: /* MIDI with running status */ - cnt++; - length = mpu->playbuf[mpu->state.track].length; - mpu->playbuf[mpu->state.track].type = T_MIDI_NORM; - break; - } - break; - case 2: - if (cnt < length) { - mpu->playbuf[mpu->state.track].value[cnt] = val; - cnt++; - } - if (cnt == length) { - mpu->state.data_onoff = -1; - mpu->state.track_req = 0; - MPU401_EOIHandler(mpu); - } - break; + /* Data */ + case -1: + break; + case 0: /* Timing byte */ + if (val < 0xf0) + mpu->state.data_onoff++; + else { + mpu->state.data_onoff = -1; + MPU401_EOIHandlerDispatch(mpu); + mpu->state.track_req = 0; + return; + } + mpu->state.send_now = !val ? 1 : 0; + mpu->playbuf[mpu->state.track].counter = val; + break; + case 1: /* MIDI */ + cnt = 0; + mpu->state.data_onoff++; + switch (val & 0xf0) { + case 0xc0: + case 0xd0: /* MIDI Message */ + length = mpu->playbuf[mpu->state.track].length = 2; + mpu->playbuf[mpu->state.track].type = T_MIDI_NORM; + break; + case 0x80: + case 0x90: + case 0xa0: + case 0xb0: + case 0xe0: + length = mpu->playbuf[mpu->state.track].length = 3; + mpu->playbuf[mpu->state.track].type = T_MIDI_NORM; + break; + case 0xf0: /* System message or mark */ + mpu->playbuf[mpu->state.track].sys_val = val; + if (val > 0xf7) { + mpu->playbuf[mpu->state.track].type = T_MARK; + if (val == 0xf9) + mpu->clock.measure_counter = 0; + } else { +#if 0 + mpu401_log("MPU-401:Illegal message"); +#endif + mpu->playbuf[mpu->state.track].type = T_OVERFLOW; + } + mpu->state.data_onoff = -1; + MPU401_EOIHandler(mpu); + mpu->state.track_req = 0; + return; + default: /* MIDI with running status */ + cnt++; + length = mpu->playbuf[mpu->state.track].length; + mpu->playbuf[mpu->state.track].type = T_MIDI_NORM; + break; + } + break; + case 2: + if (cnt < length) { + mpu->playbuf[mpu->state.track].value[cnt] = val; + cnt++; + } + if (cnt == length) { + mpu->state.data_onoff = -1; + mpu->state.track_req = 0; + MPU401_EOIHandler(mpu); + } + break; + + default: + break; } - - return; + + return; } - static void -MPU401_IntelligentOut(mpu_t *mpu, uint8_t track) +MPU401_IntelligentOut(mpu_t *mpu, uint8_t track) { - uint8_t chan, chrefnum, key, msg; - int send, retrigger; - uint8_t i; + uint8_t chan; + uint8_t chrefnum; + uint8_t key; + uint8_t msg; + int send; + int retrigger; switch (mpu->playbuf[track].type) { - case T_OVERFLOW: - break; + case T_OVERFLOW: + break; - case T_MARK: - if (mpu->playbuf[track].sys_val == 0xfc) { - midi_raw_out_rt_byte(mpu->playbuf[track].sys_val); - mpu->state.amask&=~(1<playbuf[track].sys_val == 0xfc) { + midi_raw_out_rt_byte(mpu->playbuf[track].sys_val); + mpu->state.amask &= ~(1 << track); + } + break; - case T_MIDI_NORM: - chan = mpu->playbuf[track].value[0] & 0xf; - key = mpu->playbuf[track].value[1] & 0x7f; - chrefnum = mpu->ch_toref[chan]; - send = 1; - retrigger = 0; - switch (msg = mpu->playbuf[track].value[0] & 0xf0) { - case 0x80: /* note off */ - if (mpu->inputref[chan].on && (mpu->inputref[chan].M_GETKEY)) - send = 0; - if (mpu->chanref[chrefnum].on && (!(mpu->chanref[chrefnum].M_GETKEY))) - send = 0; - mpu->chanref[chrefnum].M_DELKEY; - break; - case 0x90: /* note on */ - if (mpu->inputref[chan].on && (mpu->inputref[chan].M_GETKEY)) - retrigger = 1; - if (mpu->chanref[chrefnum].on && (!(mpu->chanref[chrefnum].M_GETKEY))) - retrigger = 1; - mpu->chanref[chrefnum].M_SETKEY; - break; - case 0xb0: - if (mpu->playbuf[track].value[1] == 123) { /* All notes off */ - MPU401_NotesOff(mpu, mpu->playbuf[track].value[0] & 0xf); - return; - } - break; - } - if (retrigger) { - midi_raw_out_byte(0x80 | chan); - midi_raw_out_byte(key); - midi_raw_out_byte(0); - } - if (send) { - for (i = 0; i < mpu->playbuf[track].length; i++) - midi_raw_out_byte(mpu->playbuf[track].value[i]); - } - break; - - default: - break; + case T_MIDI_NORM: + chan = mpu->playbuf[track].value[0] & 0xf; + key = mpu->playbuf[track].value[1] & 0x7f; + chrefnum = mpu->ch_toref[chan]; + send = 1; + retrigger = 0; + switch (msg = mpu->playbuf[track].value[0] & 0xf0) { + case 0x80: /* note off */ + if (mpu->inputref[chan].on && (mpu->inputref[chan].M_GETKEY)) + send = 0; + if (mpu->chanref[chrefnum].on && (!(mpu->chanref[chrefnum].M_GETKEY))) + send = 0; + mpu->chanref[chrefnum].M_DELKEY; + break; + case 0x90: /* note on */ + if (mpu->inputref[chan].on && (mpu->inputref[chan].M_GETKEY)) + retrigger = 1; + if (mpu->chanref[chrefnum].on && (!(mpu->chanref[chrefnum].M_GETKEY))) + retrigger = 1; + mpu->chanref[chrefnum].M_SETKEY; + break; + case 0xb0: + if (mpu->playbuf[track].value[1] == 123) { /* All notes off */ + MPU401_NotesOff(mpu, mpu->playbuf[track].value[0] & 0xf); + return; + } + break; + + default: + break; + } + if (retrigger) { + midi_raw_out_byte(0x80 | chan); + midi_raw_out_byte(key); + midi_raw_out_byte(0); + } + if (send) { + for (uint8_t i = 0; i < mpu->playbuf[track].length; i++) + midi_raw_out_byte(mpu->playbuf[track].value[i]); + } + break; + + default: + break; } } - static void -UpdateTrack(mpu_t *mpu, uint8_t track) +UpdateTrack(mpu_t *mpu, uint8_t track) { MPU401_IntelligentOut(mpu, track); - if (mpu->state.amask&(1<playbuf[track].type = T_OVERFLOW; - mpu->playbuf[track].counter = 0xf0; - mpu->state.req_mask |= (1 << track); + if (mpu->state.amask & (1 << track)) { + mpu->playbuf[track].type = T_OVERFLOW; + mpu->playbuf[track].counter = 0xf0; + mpu->state.req_mask |= (1 << track); } else { - if ((mpu->state.amask == 0) && !mpu->state.conductor) - mpu->state.req_mask |= (1 << 12); + if ((mpu->state.amask == 0) && !mpu->state.conductor) + mpu->state.req_mask |= (1 << 12); } } - -#if 0 -static void -UpdateConductor(mpu_t *mpu) -{ - if (mpu->condbuf.value[0] == 0xfc) { - mpu->condbuf.value[0] = 0; - mpu->state.conductor = 0; - mpu->state.req_mask &= ~(1 << 9); - if (mpu->state.amask == 0) - mpu->state.req_mask |= (1 << 12); - return; - } - - mpu->condbuf.vlength = 0; - mpu->condbuf.counter = 0xf0; - mpu->state.req_mask |= (1 << 9); -} -#endif - - /* Updates counters and requests new data on "End of Input" */ static void MPU401_EOIHandler(void *priv) { - mpu_t *mpu = (mpu_t *)priv; + mpu_t *mpu = (mpu_t *) priv; uint8_t i; mpu401_log("MPU-401 end of input callback\n"); - + timer_disable(&mpu->mpu401_eoi_callback); mpu->state.eoi_scheduled = 0; if (mpu->state.send_now) { - mpu->state.send_now = 0; - if (mpu->state.cond_req) { - mpu->condbuf.counter = 0xf0; - mpu->state.req_mask |= (1 << 9); - } else UpdateTrack(mpu, mpu->state.track); + mpu->state.send_now = 0; + if (mpu->state.cond_req) { + mpu->condbuf.counter = 0xf0; + mpu->state.req_mask |= (1 << 9); + } else + UpdateTrack(mpu, mpu->state.track); } - if (mpu->state.rec_copy || !mpu->state.sysex_in_finished) - return; + if (mpu->state.rec_copy || !mpu->state.sysex_in_finished) + return; + + if (!mpu->state.req_mask || !mpu->clock.active) + return; if (mpu->ext_irq_update) - mpu->ext_irq_update(mpu->priv, 0); + mpu->ext_irq_update(mpu->priv, 0); else { - mpu->state.irq_pending = 0; - picintc(1 << mpu->irq); + mpu->state.irq_pending = 0; } - if (!(mpu->state.req_mask && mpu->clock.active)) - return; - i = 0; do { - if (mpu->state.req_mask & (1 << i)) { - MPU401_QueueByte(mpu, 0xf0 + i); - mpu->state.req_mask &= ~(1 << i); - break; - } + if (mpu->state.req_mask & (1 << i)) { + MPU401_QueueByte(mpu, 0xf0 + i); + mpu->state.req_mask &= ~(1 << i); + break; + } } while ((i++) < 16); } - static void -MPU401_EOIHandlerDispatch(void *priv) +MPU401_EOIHandlerDispatch(void *priv) { - mpu_t *mpu = (mpu_t *)priv; + mpu_t *mpu = (mpu_t *) priv; mpu401_log("EOI handler dispatch\n"); if (mpu->state.send_now) { - mpu->state.eoi_scheduled = 1; - timer_advance_u64(&mpu->mpu401_eoi_callback, 60LL * TIMER_USEC); /* Possibly a bit longer */ - } else if (!mpu->state.eoi_scheduled) - MPU401_EOIHandler(mpu); + mpu->state.eoi_scheduled = 1; + timer_advance_u64(&mpu->mpu401_eoi_callback, 60LL * TIMER_USEC); /* Possibly a bit longer */ + } else if (!mpu->state.eoi_scheduled) + MPU401_EOIHandler(mpu); } - static void -imf_write(uint16_t addr, uint8_t val, void *priv) +imf_write(UNUSED(uint16_t addr), UNUSED(uint8_t val), UNUSED(void *priv)) { mpu401_log("IMF:Wr %4X,%X\n", addr, val); } - void MPU401_ReadRaiseIRQ(mpu_t *mpu) { /* Clear IRQ. */ if (mpu->ext_irq_update) - mpu->ext_irq_update(mpu->priv, 0); + mpu->ext_irq_update(mpu->priv, 0); else { - mpu->state.irq_pending = 0; - picintc(1 << mpu->irq); + mpu->state.irq_pending = 0; + picintc(1 << mpu->irq); } if (mpu->queue_used) { - /* Bytes remaining in queue, raise IRQ again. */ - if (mpu->ext_irq_update) - mpu->ext_irq_update(mpu->priv, 1); - else { - mpu->state.irq_pending = 1; - picint(1 << mpu->irq); - } + /* Bytes remaining in queue, raise IRQ again. */ + if (mpu->ext_irq_update) + mpu->ext_irq_update(mpu->priv, 1); + else { + mpu->state.irq_pending = 1; + picint(1 << mpu->irq); + } } } - uint8_t MPU401_ReadData(mpu_t *mpu) { uint8_t ret; - + ret = MSG_MPU_ACK; if (mpu->queue_used) { - if (mpu->queue_pos >= MPU401_QUEUE) - mpu->queue_pos -= MPU401_QUEUE; - ret = mpu->queue[mpu->queue_pos]; - mpu->queue_pos++; - mpu->queue_used--; + if (mpu->queue_pos >= MPU401_QUEUE) + mpu->queue_pos -= MPU401_QUEUE; + ret = mpu->queue[mpu->queue_pos]; + mpu->queue_pos++; + mpu->queue_used--; } /* Shouldn't this check mpu->mode? */ #ifdef DOSBOX_CODE if (mpu->mode == M_UART) { - MPU401_ReadRaiseIRQ(mpu); - return ret; + MPU401_ReadRaiseIRQ(mpu); + return ret; } #else if (!mpu->intelligent || (mpu->mode == M_UART)) { - MPU401_ReadRaiseIRQ(mpu); - return ret; + MPU401_ReadRaiseIRQ(mpu); + return ret; } #endif if (mpu->state.rec_copy && !mpu->rec_queue_used) { - mpu->state.rec_copy = 0; - MPU401_EOIHandler(mpu); - return ret; + mpu->state.rec_copy = 0; + MPU401_EOIHandler(mpu); + return ret; } /* Copy from recording buffer. */ if (!mpu->queue_used && mpu->rec_queue_used) { - mpu->state.rec_copy = 1; - if (mpu->rec_queue_pos >= MPU401_INPUT_QUEUE) - mpu->rec_queue_pos -= MPU401_INPUT_QUEUE; - MPU401_QueueByte(mpu, mpu->rec_queue[mpu->rec_queue_pos]); - mpu->rec_queue_pos++; - mpu->rec_queue_used--; + mpu->state.rec_copy = 1; + if (mpu->rec_queue_pos >= MPU401_INPUT_QUEUE) + mpu->rec_queue_pos -= MPU401_INPUT_QUEUE; + MPU401_QueueByte(mpu, mpu->rec_queue[mpu->rec_queue_pos]); + mpu->rec_queue_pos++; + mpu->rec_queue_used--; } MPU401_ReadRaiseIRQ(mpu); if ((ret >= 0xf0) && (ret <= 0xf7)) { - /* MIDI data request */ - mpu->state.track = ret & 7; - mpu->state.data_onoff = 0; - mpu->state.cond_req = 0; - mpu->state.track_req = 1; + /* MIDI data request */ + mpu->state.track = ret & 7; + mpu->state.data_onoff = 0; + mpu->state.cond_req = 0; + mpu->state.track_req = 1; } if (ret == MSG_MPU_COMMAND_REQ) { - mpu->state.data_onoff = 0; - mpu->state.cond_req = 1; - if (mpu->condbuf.type != T_OVERFLOW) { - mpu->state.block_ack = 1; - MPU401_WriteCommand(mpu, mpu->condbuf.value[0]); - if (mpu->state.command_byte) - MPU401_WriteData(mpu, mpu->condbuf.value[1]); - mpu->condbuf.type = T_OVERFLOW; - } + mpu->state.data_onoff = 0; + mpu->state.cond_req = 1; + if (mpu->condbuf.type != T_OVERFLOW) { + mpu->state.block_ack = 1; + MPU401_WriteCommand(mpu, mpu->condbuf.value[0]); + if (mpu->state.command_byte) + MPU401_WriteData(mpu, mpu->condbuf.value[1]); + mpu->condbuf.type = T_OVERFLOW; + } } if ((ret == MSG_MPU_END) || (ret == MSG_MPU_CLOCK) || (ret == MSG_MPU_ACK) || (ret == MSG_MPU_OVERFLOW)) - MPU401_EOIHandlerDispatch(mpu); + MPU401_EOIHandlerDispatch(mpu); return ret; } - -static void +void mpu401_write(uint16_t addr, uint8_t val, void *priv) { - mpu_t *mpu = (mpu_t *)priv; - + mpu_t *mpu = (mpu_t *) priv; + /* mpu401_log("MPU401 Write Port %04X, val %x\n", addr, val); */ switch (addr & 1) { - case 0: /*Data*/ - MPU401_WriteData(mpu, val); - mpu401_log("Write Data (0x330) %X\n", val); - break; + case 0: /*Data*/ + MPU401_WriteData(mpu, val); + mpu401_log("Write Data (0x330) %X\n", val); + break; - case 1: /*Command*/ - MPU401_WriteCommand(mpu, val); - mpu401_log("Write Command (0x331) %x\n", val); - break; + case 1: /*Command*/ + MPU401_WriteCommand(mpu, val); + mpu401_log("Write Command (0x331) %x\n", val); + break; + + default: + break; } } - -static uint8_t +uint8_t mpu401_read(uint16_t addr, void *priv) { - mpu_t *mpu = (mpu_t *)priv; + mpu_t *mpu = (mpu_t *) priv; uint8_t ret = 0; - switch (addr & 1) { - case 0: /* Read Data */ - ret = MPU401_ReadData(mpu); - mpu401_log("Read Data (0x330) %X\n", ret); - break; + switch (addr & 1) { + case 0: /* Read Data */ + ret = MPU401_ReadData(mpu); + mpu401_log("Read Data (0x330) %X\n", ret); + break; - case 1: /* Read Status */ - if (mpu->state.cmd_pending) - ret = STATUS_OUTPUT_NOT_READY; - if (!mpu->queue_used) - ret = STATUS_INPUT_NOT_READY; - ret |= 0x3f; + case 1: /* Read Status */ + if (mpu->state.cmd_pending) + ret = STATUS_OUTPUT_NOT_READY; + if (!mpu->queue_used) + ret = STATUS_INPUT_NOT_READY; + ret |= 0x3f; - mpu401_log("Read Status (0x331) %x\n", ret); - break; + mpu401_log("Read Status (0x331) %x\n", ret); + break; + + default: + break; } /* mpu401_log("MPU401 Read Port %04X, ret %x\n", addr, ret); */ - return(ret); + return ret; } - static void -MPU401_Event(void *priv) +MPU401_Event(void *priv) { - mpu_t *mpu = (mpu_t *)priv; - uint8_t i; - int max_meascnt; + mpu_t *mpu = (mpu_t *) priv; + int max_meascnt; mpu401_log("MPU-401 event callback\n"); #ifdef DOSBOX_CODE if (mpu->mode == M_UART) { - timer_disable(&mpu->mpu401_event_callback); - return; + timer_disable(&mpu->mpu401_event_callback); + return; } #else if (!mpu->intelligent || (mpu->mode == M_UART)) { - timer_disable(&mpu->mpu401_event_callback); - return; + timer_disable(&mpu->mpu401_event_callback); + return; } #endif if (MPU401_IRQPending(mpu)) - goto next_event; + goto next_event; if (mpu->state.playing) { - for (i = 0; i < 8; i++) { - /* Decrease counters. */ - if (mpu->state.amask & (1 << i)) { - mpu->playbuf[i].counter--; - if (mpu->playbuf[i].counter <= 0) - UpdateTrack(mpu, i); - } - } + for (uint8_t i = 0; i < 8; i++) { + /* Decrease counters. */ + if (mpu->state.amask & (1 << i)) { + mpu->playbuf[i].counter--; + if (mpu->playbuf[i].counter <= 0) + UpdateTrack(mpu, i); + } + } - if (mpu->state.conductor) { - mpu->condbuf.counter--; - if (mpu->condbuf.counter <= 0) { - mpu->condbuf.counter = 0xf0; - mpu->state.req_mask |= (1 << 9); - } - } + if (mpu->state.conductor) { + mpu->condbuf.counter--; + if (mpu->condbuf.counter <= 0) { + mpu->condbuf.counter = 0xf0; + mpu->state.req_mask |= (1 << 9); + } + } } if (mpu->state.clock_to_host) { - mpu->clock.cth_counter++; - if (mpu->clock.cth_counter >= mpu->clock.cth_rate[mpu->clock.cth_mode]) { - mpu->clock.cth_counter = 0; - mpu->clock.cth_mode++; - mpu->clock.cth_mode %= 4; - mpu->state.req_mask |= (1 << 13); - } + mpu->clock.cth_counter++; + if (mpu->clock.cth_counter >= mpu->clock.cth_rate[mpu->clock.cth_mode]) { + mpu->clock.cth_counter = 0; + mpu->clock.cth_mode++; + mpu->clock.cth_mode %= 4; + mpu->state.req_mask |= (1 << 13); + } } if (mpu->state.rec == M_RECON) { - /* Recording. */ - mpu->clock.rec_counter++; - if (mpu->clock.rec_counter>=240) { - mpu->clock.rec_counter=0; - mpu->state.req_mask|=(1<<8); - } + /* Recording. */ + mpu->clock.rec_counter++; + if (mpu->clock.rec_counter >= 240) { + mpu->clock.rec_counter = 0; + mpu->state.req_mask |= (1 << 8); + } } if (mpu->state.playing || (mpu->state.rec == M_RECON)) { - max_meascnt = (mpu->clock.timebase * mpu->clock.midimetro * mpu->clock.metromeas) / 24; - if (max_meascnt != 0) { - /* Measure end. */ - if (++mpu->clock.measure_counter >= max_meascnt) { - if (mpu->filter.rt_out) - midi_raw_out_rt_byte(0xf8); - mpu->clock.measure_counter = 0; - if (mpu->filter.rec_measure_end && (mpu->state.rec == M_RECON)) - mpu->state.req_mask |= (1 << 12); - } - } + max_meascnt = (mpu->clock.timebase * mpu->clock.midimetro * mpu->clock.metromeas) / 24; + if (max_meascnt != 0) { + /* Measure end. */ + if (++mpu->clock.measure_counter >= max_meascnt) { + if (mpu->filter.rt_out) + midi_raw_out_rt_byte(0xf8); + mpu->clock.measure_counter = 0; + if (mpu->filter.rec_measure_end && (mpu->state.rec == M_RECON)) + mpu->state.req_mask |= (1 << 12); + } + } } - if (MPU401_IRQPending(mpu) && mpu->state.req_mask) - MPU401_EOIHandler(mpu); + if (!MPU401_IRQPending(mpu) && mpu->state.req_mask) + MPU401_EOIHandler(mpu); next_event: MPU401_RunClock(mpu); if (mpu->state.sync_in) - mpu->clock.ticks_in++; + mpu->clock.ticks_in++; } - -static void -MPU401_NotesOff(mpu_t *mpu, int i) +static void +MPU401_NotesOff(mpu_t *mpu, int i) { - int j; - uint8_t key; - - if (mpu->filter.allnotesoff_out && !(mpu->inputref[i].on && - (mpu->inputref[i].key[0] | mpu->inputref[i].key[1] | - mpu->inputref[i].key[2] | mpu->inputref[i].key[3]))) { - for (j=0;j<4;j++) - mpu->chanref[mpu->ch_toref[i]].key[j]=0; - midi_raw_out_byte(0xb0 | i); - midi_raw_out_byte(123); - midi_raw_out_byte(0); + if (mpu->filter.allnotesoff_out && !(mpu->inputref[i].on && (mpu->inputref[i].key[0] | mpu->inputref[i].key[1] | mpu->inputref[i].key[2] | mpu->inputref[i].key[3]))) { + for (uint8_t j = 0; j < 4; j++) + mpu->chanref[mpu->ch_toref[i]].key[j] = 0; + midi_raw_out_byte(0xb0 | i); + midi_raw_out_byte(123); + midi_raw_out_byte(0); } else if (mpu->chanref[mpu->ch_toref[i]].on) { - for (key = 0; key < 128; key++) { - if ((mpu->chanref[mpu->ch_toref[i]].M_GETKEY) && - !(mpu->inputref[i].on && (mpu->inputref[i].M_GETKEY))) { - midi_raw_out_byte(0x80|i); - midi_raw_out_byte(key); - midi_raw_out_byte(0); - } - mpu->chanref[mpu->ch_toref[i]].M_DELKEY; - } + for (uint8_t key = 0; key < 128; key++) { + if ((mpu->chanref[mpu->ch_toref[i]].M_GETKEY) && !(mpu->inputref[i].on && (mpu->inputref[i].M_GETKEY))) { + midi_raw_out_byte(0x80 | i); + midi_raw_out_byte(key); + midi_raw_out_byte(0); + } + mpu->chanref[mpu->ch_toref[i]].M_DELKEY; + } } } - /*Input handler for SysEx */ int -MPU401_InputSysex(void *p, uint8_t *buffer, uint32_t len, int abort) +MPU401_InputSysex(void *priv, uint8_t *buffer, uint32_t len, int abort) { - mpu_t *mpu = (mpu_t *)p; - int i; + mpu_t *mpu = (mpu_t *) priv; + int i; uint8_t val_ff = 0xff; mpu401_log("MPU401 Input Sysex\n"); @@ -1390,63 +1425,67 @@ MPU401_InputSysex(void *p, uint8_t *buffer, uint32_t len, int abort) #else if (!mpu->intelligent || mpu->mode == M_UART) { #endif - /* UART mode input. */ - for (i = 0; i < len; i++) - MPU401_QueueByte(mpu, buffer[i]); - return 0; + /* UART mode input. */ + for (i = 0; i < len; i++) + MPU401_QueueByte(mpu, buffer[i]); + return 0; } if (mpu->filter.sysex_in) { - if (abort) { - mpu->state.sysex_in_finished=1; - mpu->rec_queue_used=0;/*reset also the input queue*/ - return 0; - } - if (mpu->state.sysex_in_finished) { - if (mpu->rec_queue_used>=MPU401_INPUT_QUEUE) - return len; - MPU401_RecQueueBuffer(mpu, &val_ff, 1, 1); - mpu->state.sysex_in_finished=0; - mpu->clock.rec_counter=0; - } - if (mpu->rec_queue_used>=MPU401_INPUT_QUEUE) - return len; - int available = MPU401_INPUT_QUEUE - mpu->rec_queue_used; + if (abort) { + mpu->state.sysex_in_finished = 1; + mpu->rec_queue_used = 0; /*reset also the input queue*/ + return 0; + } + if (mpu->state.sysex_in_finished) { + if (mpu->rec_queue_used >= MPU401_INPUT_QUEUE) + return len; + MPU401_RecQueueBuffer(mpu, &val_ff, 1, 1); + mpu->state.sysex_in_finished = 0; + mpu->clock.rec_counter = 0; + } + if (mpu->rec_queue_used >= MPU401_INPUT_QUEUE) + return len; + int available = MPU401_INPUT_QUEUE - mpu->rec_queue_used; - if (available >= len) { - MPU401_RecQueueBuffer(mpu, buffer, len, 1); - return 0; - } else { - MPU401_RecQueueBuffer(mpu,buffer, available, 1); - if (mpu->state.sysex_in_finished) - return 0; - return (len - available); - } + if (available >= len) { + MPU401_RecQueueBuffer(mpu, buffer, len, 1); + return 0; + } else { + MPU401_RecQueueBuffer(mpu, buffer, available, 1); + if (mpu->state.sysex_in_finished) + return 0; + return (len - available); + } } else if (mpu->filter.sysex_thru && mpu->midi_thru) { - midi_raw_out_byte(0xf0); - for (i = 0; i < len; i++) - midi_raw_out_byte(*(buffer+i)); + midi_raw_out_byte(0xf0); + for (i = 0; i < len; i++) + midi_raw_out_byte(*(buffer + i)); } return 0; } - /*Input handler for MIDI*/ void -MPU401_InputMsg(void *p, uint8_t *msg, uint32_t len) +MPU401_InputMsg(void *priv, uint8_t *msg, uint32_t len) { - mpu_t *mpu = (mpu_t *)p; - int i, tick; + mpu_t *mpu = (mpu_t *) priv; + int i; + int tick; static uint8_t old_msg = 0; - uint8_t key; - uint8_t recdata[2], recmsg[4]; - int send = 1, send_thru = 0; - int retrigger_thru = 0, chan, chrefnum; + uint8_t key; + uint8_t recdata[2]; + uint8_t recmsg[4]; + int send = 1; + int send_thru = 0; + int retrigger_thru = 0; + int chan; + int chrefnum; /* Abort if sysex transfer is in progress. */ if (!mpu->state.sysex_in_finished) { - mpu401_log("SYSEX in progress\n"); - return; + mpu401_log("SYSEX in progress\n"); + return; } mpu401_log("MPU401 Input Msg\n"); @@ -1456,202 +1495,213 @@ MPU401_InputMsg(void *p, uint8_t *msg, uint32_t len) #else if (mpu->intelligent && (mpu->mode == M_INTELLIGENT)) { #endif - if (msg[0] < 0x80) { - /* Expand running status */ - msg[2] = msg[1]; - msg[1] = msg[0]; - msg[0] = old_msg; - } - old_msg = msg[0]; - chan = msg[0] & 0xf; - chrefnum = mpu->ch_toref[chan]; - key = msg[1] & 0x7f; - if (msg[0] < 0xf0) { - /* If non-system msg. */ - if (!(mpu->state.midi_mask & (1 << chan)) && mpu->filter.all_thru) - send_thru = 1; - else if (mpu->filter.midi_thru) - send_thru = 1; - switch (msg[0] & 0xf0) { - case 0x80: /* Note off. */ - if (send_thru) { - if (mpu->chanref[chrefnum].on && (mpu->chanref[chrefnum].M_GETKEY)) - send_thru = 0; - if (!mpu->filter.midi_thru) - break; - if (!(mpu->inputref[chan].M_GETKEY)) - send_thru = 0; - mpu->inputref[chan].M_DELKEY; - } - break; - case 0x90: /* Note on. */ - if (send_thru) { - if (mpu->chanref[chrefnum].on && (mpu->chanref[chrefnum].M_GETKEY)) - retrigger_thru = 1; - if (!mpu->filter.midi_thru) - break; - if (mpu->inputref[chan].M_GETKEY) - retrigger_thru = 1; - mpu->inputref[chan].M_SETKEY; - } - break; - case 0xb0: - if (msg[1] >= 120) { - send_thru = 0; - if (msg[1] == 123) { - /* All notes off. */ - for (key = 0; key < 128; key++) { - if (!(mpu->chanref[chrefnum].on && (mpu->chanref[chrefnum].M_GETKEY))) { - if (mpu->inputref[chan].on && mpu->inputref[chan].M_GETKEY) { - midi_raw_out_byte(0x80 | chan); - midi_raw_out_byte(key); - midi_raw_out_byte(0); - } - mpu->inputref[chan].M_DELKEY; - } - } - } - break; - } - } - } - if ((msg[0] >= 0xf0) || (mpu->state.midi_mask & (1 << chan))) { - switch (msg[0] & 0xf0) { - case 0xa0: /* Aftertouch. */ - if (!mpu->filter.bender_in) - send = 0; - break; - case 0xb0: /* Control change. */ - if (!mpu->filter.bender_in && (msg[1] < 64)) - send = 0; - if (msg[1] >= 120) { - if (mpu->filter.modemsgs_in) - send = 1; - } - break; - case 0xc0: /* Program change. */ - if ((mpu->state.rec != M_RECON) && !mpu->filter.data_in_stop) { - mpu->filter.prchg_buf[chan] = msg[1]; - mpu->filter.prchg_mask |= 1 << chan; - } - break; - case 0xd0: /* Ch pressure. */ - case 0xe0: /* Pitch wheel. */ - if (!mpu->filter.bender_in) - send = 0; - break; - case 0xf0: /* System message. */ - if (msg[0] == 0xf8) { - send = 0; - if (mpu->clock.active && mpu->state.sync_in) { - send = 0; /* Don't pass to host in this mode? */ - tick = mpu->clock.timebase / 24; - if (mpu->clock.ticks_in != tick) { - if (!mpu->clock.ticks_in || (mpu->clock.ticks_in > (tick * 2))) - mpu->clock.freq_mod *= 2.0; - else { - if (ABS(mpu->clock.ticks_in-tick) == 1) - mpu->clock.freq_mod /= mpu->clock.ticks_in / (float) (tick * 2); - else - mpu->clock.freq_mod /= mpu->clock.ticks_in / (float) (tick); - } - MPU401_ReCalcClock(mpu); - } - mpu->clock.ticks_in = 0; - } - } else if (msg[0] > 0xf8) { /* Realtime. */ - if (!(mpu->filter.rt_in && (msg[0] <= 0xfc) && (msg[0] >= 0xfa))) { - recdata[0] = 0xff; - recdata[1] = msg[0]; - MPU401_RecQueueBuffer(mpu, recdata, 2, 1); - send = 0; - } - } else { /* Common or system. */ - send = 0; - if ((msg[0] == 0xf2) || (msg[0] == 0xf3) || (msg[0] == 0xf6)) { - if (mpu->filter.commonmsgs_in) - send = 1; - if (mpu->filter.commonmsgs_thru) - for (i = 0; i < len; i++) - midi_raw_out_byte(msg[i]); - } - } - if (send) { - recmsg[0] = 0xff; - recmsg[1] = msg[0]; - recmsg[2] = msg[1]; - recmsg[3] = msg[2]; - MPU401_RecQueueBuffer(mpu, recmsg, len + 1, 1); - } - if (mpu->filter.rt_affection) { - switch(msg[0]) { - case 0xf2: case 0xf3: - mpu->state.block_ack = 1; - MPU401_WriteCommand(mpu, 0xb8); /* Clear play counters. */ - break; - case 0xfa: - mpu->state.block_ack = 1; - MPU401_WriteCommand(mpu, 0xa); /* Start, play. */ - if (mpu->filter.rt_out) - midi_raw_out_rt_byte(msg[0]); - break; - case 0xfb: - mpu->state.block_ack = 1; - MPU401_WriteCommand(mpu, 0xb); /* Continue, play. */ - if (mpu->filter.rt_out) - midi_raw_out_rt_byte(msg[0]); - break; - case 0xfc: - mpu->state.block_ack = 1; - MPU401_WriteCommand(mpu, 0xd) ;/* Stop: Play, rec, midi */ - if (mpu->filter.rt_out) - midi_raw_out_rt_byte(msg[0]); - break; - } - return; - } - } - } - if (send_thru && mpu->midi_thru) { - if (retrigger_thru) { - midi_raw_out_byte(0x80 | (msg[0] & 0xf)); - midi_raw_out_byte(msg[1]); - midi_raw_out_byte(msg[2]); - } - for (i = 0; i < len; i++) - midi_raw_out_byte(msg[i]); - } - if (send) { - if (mpu->state.rec == M_RECON) { - recmsg[0] = mpu->clock.rec_counter; - recmsg[1] = msg[0]; - recmsg[2] = msg[1]; - recmsg[3] = msg[2]; - MPU401_RecQueueBuffer(mpu, recmsg, len + 1, 1); - mpu->clock.rec_counter = 0; - } - else if (mpu->filter.data_in_stop) { - if (mpu->filter.timing_in_stop) { - recmsg[0] = 0; - recmsg[1] = msg[0]; - recmsg[2] = msg[1]; - recmsg[3] = msg[2]; - MPU401_RecQueueBuffer(mpu, recmsg, len + 1, 1); - } else { - recmsg[0] = msg[0]; - recmsg[1] = msg[1]; - recmsg[2] = msg[2]; - recmsg[3] = 0; - MPU401_RecQueueBuffer(mpu, recmsg, len, 1); - } - } - } - return; + if (msg[0] < 0x80) { + /* Expand running status */ + msg[2] = msg[1]; + msg[1] = msg[0]; + msg[0] = old_msg; + } + old_msg = msg[0]; + chan = msg[0] & 0xf; + chrefnum = mpu->ch_toref[chan]; + key = msg[1] & 0x7f; + if (msg[0] < 0xf0) { + /* If non-system msg. */ + if (!(mpu->state.midi_mask & (1 << chan)) && mpu->filter.all_thru) + send_thru = 1; + else if (mpu->filter.midi_thru) + send_thru = 1; + switch (msg[0] & 0xf0) { + case 0x80: /* Note off. */ + if (send_thru) { + if (mpu->chanref[chrefnum].on && (mpu->chanref[chrefnum].M_GETKEY)) + send_thru = 0; + if (!mpu->filter.midi_thru) + break; + if (!(mpu->inputref[chan].M_GETKEY)) + send_thru = 0; + mpu->inputref[chan].M_DELKEY; + } + break; + case 0x90: /* Note on. */ + if (send_thru) { + if (mpu->chanref[chrefnum].on && (mpu->chanref[chrefnum].M_GETKEY)) + retrigger_thru = 1; + if (!mpu->filter.midi_thru) + break; + if (mpu->inputref[chan].M_GETKEY) + retrigger_thru = 1; + mpu->inputref[chan].M_SETKEY; + } + break; + case 0xb0: + if (msg[1] >= 120) { + send_thru = 0; + if (msg[1] == 123) { + /* All notes off. */ + for (key = 0; key < 128; key++) { + if (!(mpu->chanref[chrefnum].on && (mpu->chanref[chrefnum].M_GETKEY))) { + if (mpu->inputref[chan].on && mpu->inputref[chan].M_GETKEY) { + midi_raw_out_byte(0x80 | chan); + midi_raw_out_byte(key); + midi_raw_out_byte(0); + } + mpu->inputref[chan].M_DELKEY; + } + } + } + } + break; + + default: + break; + } + } + if ((msg[0] >= 0xf0) || (mpu->state.midi_mask & (1 << chan))) { + switch (msg[0] & 0xf0) { + case 0xa0: /* Aftertouch. */ + if (!mpu->filter.bender_in) + send = 0; + break; + case 0xb0: /* Control change. */ + if (!mpu->filter.bender_in && (msg[1] < 64)) + send = 0; + if (msg[1] >= 120) { + if (mpu->filter.modemsgs_in) + send = 1; + } + break; + case 0xc0: /* Program change. */ + if ((mpu->state.rec != M_RECON) && !mpu->filter.data_in_stop) { + mpu->filter.prchg_buf[chan] = msg[1]; + mpu->filter.prchg_mask |= 1 << chan; + } + break; + case 0xd0: /* Ch pressure. */ + case 0xe0: /* Pitch wheel. */ + if (!mpu->filter.bender_in) + send = 0; + break; + case 0xf0: /* System message. */ + if (msg[0] == 0xf8) { + send = 0; + if (mpu->clock.active && mpu->state.sync_in) { + send = 0; /* Don't pass to host in this mode? */ + tick = mpu->clock.timebase / 24; + if (mpu->clock.ticks_in != tick) { + if (!mpu->clock.ticks_in || (mpu->clock.ticks_in > (tick * 2))) + mpu->clock.freq_mod *= 2.0; + else { + if (ABS(mpu->clock.ticks_in - tick) == 1) + mpu->clock.freq_mod /= mpu->clock.ticks_in / (float) (tick * 2); + else + mpu->clock.freq_mod /= mpu->clock.ticks_in / (float) (tick); + } + MPU401_ReCalcClock(mpu); + MPU401_ReStartClock(mpu); + } + mpu->clock.ticks_in = 0; + } + } else if (msg[0] > 0xf8) { /* Realtime. */ + if (!(mpu->filter.rt_in && (msg[0] <= 0xfc) && (msg[0] >= 0xfa))) { + recdata[0] = 0xff; + recdata[1] = msg[0]; + MPU401_RecQueueBuffer(mpu, recdata, 2, 1); + send = 0; + } + } else { /* Common or system. */ + send = 0; + if ((msg[0] == 0xf2) || (msg[0] == 0xf3) || (msg[0] == 0xf6)) { + if (mpu->filter.commonmsgs_in) + send = 1; + if (mpu->filter.commonmsgs_thru) + for (i = 0; i < len; i++) + midi_raw_out_byte(msg[i]); + } + } + if (send) { + recmsg[0] = 0xff; + recmsg[1] = msg[0]; + recmsg[2] = msg[1]; + recmsg[3] = msg[2]; + MPU401_RecQueueBuffer(mpu, recmsg, len + 1, 1); + } + if (mpu->filter.rt_affection) { + switch (msg[0]) { + case 0xf2: + case 0xf3: + mpu->state.block_ack = 1; + MPU401_WriteCommand(mpu, 0xb8); /* Clear play counters. */ + break; + case 0xfa: + mpu->state.block_ack = 1; + MPU401_WriteCommand(mpu, 0xa); /* Start, play. */ + if (mpu->filter.rt_out) + midi_raw_out_rt_byte(msg[0]); + break; + case 0xfb: + mpu->state.block_ack = 1; + MPU401_WriteCommand(mpu, 0xb); /* Continue, play. */ + if (mpu->filter.rt_out) + midi_raw_out_rt_byte(msg[0]); + break; + case 0xfc: + mpu->state.block_ack = 1; + MPU401_WriteCommand(mpu, 0xd); /* Stop: Play, rec, midi */ + if (mpu->filter.rt_out) + midi_raw_out_rt_byte(msg[0]); + break; + + default: + break; + } + return; + } + break; + + default: + break; + } + } + if (send_thru && mpu->midi_thru) { + if (retrigger_thru) { + midi_raw_out_byte(0x80 | (msg[0] & 0xf)); + midi_raw_out_byte(msg[1]); + midi_raw_out_byte(msg[2]); + } + for (i = 0; i < len; i++) + midi_raw_out_byte(msg[i]); + } + if (send) { + if (mpu->state.rec == M_RECON) { + recmsg[0] = mpu->clock.rec_counter; + recmsg[1] = msg[0]; + recmsg[2] = msg[1]; + recmsg[3] = msg[2]; + MPU401_RecQueueBuffer(mpu, recmsg, len + 1, 1); + mpu->clock.rec_counter = 0; + } else if (mpu->filter.data_in_stop) { + if (mpu->filter.timing_in_stop) { + recmsg[0] = 0; + recmsg[1] = msg[0]; + recmsg[2] = msg[1]; + recmsg[3] = msg[2]; + MPU401_RecQueueBuffer(mpu, recmsg, len + 1, 1); + } else { + recmsg[0] = msg[0]; + recmsg[1] = msg[1]; + recmsg[2] = msg[2]; + recmsg[3] = 0; + MPU401_RecQueueBuffer(mpu, recmsg, len, 1); + } + } + } + return; } /* UART mode input. */ for (i = 0; i < len; i++) - MPU401_QueueByte(mpu, msg[i]); + MPU401_QueueByte(mpu, msg[i]); } void @@ -1664,39 +1714,38 @@ void mpu401_change_addr(mpu_t *mpu, uint16_t addr) { if (mpu == NULL) - return; + return; if (mpu->addr) - io_removehandler(mpu->addr, 2, - mpu401_read, NULL, NULL, mpu401_write, NULL, NULL, mpu); + io_removehandler(mpu->addr, 2, + mpu401_read, NULL, NULL, mpu401_write, NULL, NULL, mpu); mpu->addr = addr; if (mpu->addr) - io_sethandler(mpu->addr, 2, - mpu401_read, NULL, NULL, mpu401_write, NULL, NULL, mpu); + io_sethandler(mpu->addr, 2, + mpu401_read, NULL, NULL, mpu401_write, NULL, NULL, mpu); } - void mpu401_init(mpu_t *mpu, uint16_t addr, int irq, int mode, int receive_input) { - mpu->status = STATUS_INPUT_NOT_READY; - mpu->irq = irq; + mpu->status = STATUS_INPUT_NOT_READY; + mpu->irq = irq; mpu->queue_used = 0; - mpu->queue_pos = 0; - mpu->mode = M_UART; - mpu->addr = addr; + mpu->queue_pos = 0; + mpu->mode = M_UART; + mpu->addr = addr; /* Expalantion: - MPU-401 starting in intelligent mode = Full MPU-401 intelligent mode capability; - MPU-401 starting in UART mode = Reduced MPU-401 intelligent mode capability seen on the Sound Blaster 16/AWE32, - only supporting commands 3F (set UART mode) and FF (reset). */ + MPU-401 starting in intelligent mode = Full MPU-401 intelligent mode capability; + MPU-401 starting in UART mode = Reduced MPU-401 intelligent mode capability seen on the Sound Blaster 16/AWE32, + only supporting commands 3F (set UART mode) and FF (reset). */ mpu->intelligent = (mode == M_INTELLIGENT) ? 1 : 0; mpu401_log("Starting as %s (mode is %s)\n", mpu->intelligent ? "INTELLIGENT" : "UART", (mode == M_INTELLIGENT) ? "INTELLIGENT" : "UART"); if (mpu->addr) - io_sethandler(mpu->addr, 2, - mpu401_read, NULL, NULL, mpu401_write, NULL, NULL, mpu); + io_sethandler(mpu->addr, 2, + mpu401_read, NULL, NULL, mpu401_write, NULL, NULL, mpu); io_sethandler(0x2A20, 16, - NULL, NULL, NULL, imf_write, NULL, NULL, mpu); + NULL, NULL, NULL, imf_write, NULL, NULL, mpu); timer_add(&mpu->mpu401_event_callback, MPU401_Event, mpu, 0); timer_add(&mpu->mpu401_eoi_callback, MPU401_EOIHandler, mpu, 0); timer_add(&mpu->mpu401_reset_callback, MPU401_ResetDone, mpu, 0); @@ -1704,40 +1753,37 @@ mpu401_init(mpu_t *mpu, uint16_t addr, int irq, int mode, int receive_input) MPU401_Reset(mpu); if (receive_input) - midi_in_handler(1, MPU401_InputMsg, MPU401_InputSysex, mpu); + midi_in_handler(1, MPU401_InputMsg, MPU401_InputSysex, mpu); } - void mpu401_device_add(void) { if (!mpu401_standalone_enable) - return; + return; if (machine_has_bus(machine, MACHINE_BUS_MCA)) - device_add(&mpu401_mca_device); + device_add(&mpu401_mca_device); else - device_add(&mpu401_device); + device_add(&mpu401_device); } - static uint8_t -mpu401_mca_read(int port, void *p) +mpu401_mca_read(int port, void *priv) { - mpu_t *mpu = (mpu_t *)p; + const mpu_t *mpu = (mpu_t *) priv; return mpu->pos_regs[port & 7]; } - static void -mpu401_mca_write(int port, uint8_t val, void *p) +mpu401_mca_write(int port, uint8_t val, void *priv) { - mpu_t *mpu = (mpu_t *)p; + mpu_t *mpu = (mpu_t *) priv; uint16_t addr; if (port < 0x102) - return; + return; addr = (mpu->pos_regs[2] & 2) ? 0x0330 : 0x1330; @@ -1746,38 +1792,35 @@ mpu401_mca_write(int port, uint8_t val, void *p) mpu->pos_regs[port] = val; if (port == 2) { - io_removehandler(addr, 2, - mpu401_read, NULL, NULL, mpu401_write, NULL, NULL, mpu); + io_removehandler(addr, 2, + mpu401_read, NULL, NULL, mpu401_write, NULL, NULL, mpu); - addr = (mpu->pos_regs[2] & 2) ? 0x1330 : 0x0330; + addr = (mpu->pos_regs[2] & 2) ? 0x1330 : 0x0330; - io_sethandler(addr, 2, - mpu401_read, NULL, NULL, mpu401_write, NULL, NULL, mpu); + io_sethandler(addr, 2, + mpu401_read, NULL, NULL, mpu401_write, NULL, NULL, mpu); } } - static uint8_t -mpu401_mca_feedb(void *p) +mpu401_mca_feedb(UNUSED(void *priv)) { return 1; } - void mpu401_irq_attach(mpu_t *mpu, void (*ext_irq_update)(void *priv, int set), int (*ext_irq_pending)(void *priv), void *priv) { - mpu->ext_irq_update = ext_irq_update; + mpu->ext_irq_update = ext_irq_update; mpu->ext_irq_pending = ext_irq_pending; - mpu->priv = priv; + mpu->priv = priv; } - static void * mpu401_standalone_init(const device_t *info) { - mpu_t *mpu; - int irq; + mpu_t *mpu; + int irq; uint16_t base; mpu = malloc(sizeof(mpu_t)); @@ -1786,138 +1829,211 @@ mpu401_standalone_init(const device_t *info) mpu401_log("mpu_init\n"); if (info->flags & DEVICE_MCA) { - mca_add(mpu401_mca_read, mpu401_mca_write, mpu401_mca_feedb, NULL, mpu); - mpu->pos_regs[0] = 0x0F; - mpu->pos_regs[1] = 0x6C; - base = 0; /* Tell mpu401_init() that this is the MCA variant. */ - irq = 2; /* According to @6c0f.adf, the IRQ is fixed to 2. */ + mca_add(mpu401_mca_read, mpu401_mca_write, mpu401_mca_feedb, NULL, mpu); + mpu->pos_regs[0] = 0x0F; + mpu->pos_regs[1] = 0x6C; + base = 0; /* Tell mpu401_init() that this is the MCA variant. */ + /* According to @6c0f.adf, the IRQ is supposed to be fixed to 2. + This is only true for earlier models. Later ones have selectable IRQ. */ + irq = device_get_config_int("irq"); } else { - base = device_get_config_hex16("base"); - irq = device_get_config_int("irq"); + base = device_get_config_hex16("base"); + irq = device_get_config_int("irq"); } mpu401_init(mpu, base, irq, M_INTELLIGENT, device_get_config_int("receive_input")); - - return(mpu); -} + return mpu; +} static void mpu401_standalone_close(void *priv) { - mpu_t *mpu = (mpu_t *)priv; + mpu_t *mpu = (mpu_t *) priv; free(mpu); } - -static const device_config_t mpu401_standalone_config[] = -{ - { - "base", "MPU-401 Address", CONFIG_HEX16, "", 0x330, "", { 0 }, - { - { - "0x220", 0x220 - }, - { - "0x230", 0x230 - }, - { - "0x240", 0x240 - }, - { - "0x250", 0x250 - }, - { - "0x300", 0x300 - }, - { - "0x320", 0x320 - }, - { - "0x330", 0x330 - }, - { - "0x340", 0x340 - }, - { - "0x350", 0x350 - }, - { - "" - } - } - }, - { - "irq", "MPU-401 IRQ", CONFIG_SELECTION, "", 2, "", { 0 }, - { - { - "IRQ 2", 2 - }, - { - "IRQ 3", 3 - }, - { - "IRQ 4", 4 - }, - { - "IRQ 5", 5 - }, - { - "IRQ 6", 6 - }, - { - "IRQ 7", 7 - }, - { - "" - } - } - }, - { - .name = "receive_input", - .description = "Receive input", - .type = CONFIG_BINARY, - .default_int = 1 - }, - { - "", "", -1 +static const device_config_t mpu401_standalone_config[] = { + // clang-format off + { + .name = "base", + .description = "MPU-401 Address", + .type = CONFIG_HEX16, + .default_string = "", + .default_int = 0x330, + .file_filter = "", + .spinner = { 0 }, + .selection = { + { + .description = "0x220", + .value = 0x220 + }, + { + .description = "0x230", + .value = 0x230 + }, + { + .description = "0x240", + .value = 0x240 + }, + { + .description = "0x250", + .value = 0x250 + }, + { + .description = "0x300", + .value = 0x300 + }, + { + .description = "0x320", + .value = 0x320 + }, + { + .description = "0x330", + .value = 0x330 + }, + { + .description = "0x332", + .value = 0x332 + }, + { + .description = "0x334", + .value = 0x334 + }, + { + .description = "0x336", + .value = 0x336 + }, + { + .description = "0x340", + .value = 0x340 + }, + { + .description = "0x350", + .value = 0x350 + }, + { .description = "" } } + }, + { + .name = "irq", + .description = "MPU-401 IRQ", + .type = CONFIG_SELECTION, + .default_string = "", + .default_int = 2, + .file_filter = "", + .spinner = { 0 }, + .selection = { + { + .description = "IRQ 2", + .value = 2 + }, + { + .description = "IRQ 3", + .value = 3 + }, + { + .description = "IRQ 4", + .value = 4 + }, + { + .description = "IRQ 5", + .value = 5 + }, + { + .description = "IRQ 6", + .value = 6 + }, + { + .description = "IRQ 7", + .value = 7 + }, + { .description = "" } + } + }, + { + .name = "receive_input", + .description = "Receive input", + .type = CONFIG_BINARY, + .default_int = 1 + }, + { .name = "", .description = "", .type = CONFIG_END } + // clang-format on }; - -static const device_config_t mpu401_standalone_mca_config[] = -{ - { - .name = "receive_input", - .description = "Receive input", - .type = CONFIG_BINARY, - .default_int = 1 - }, - { - "", "", -1 +static const device_config_t mpu401_standalone_mca_config[] = { + // clang-format off + { + .name = "irq", + .description = "MPU-401 IRQ", + .type = CONFIG_SELECTION, + .default_string = "", + .default_int = 9, + .file_filter = "", + .spinner = { 0 }, + .selection = { + { + .description = "IRQ 3", + .value = 3 + }, + { + .description = "IRQ 4", + .value = 4 + }, + { + .description = "IRQ 5", + .value = 5 + }, + { + .description = "IRQ 6", + .value = 6 + }, + { + .description = "IRQ 7", + .value = 7 + }, + { + .description = "IRQ 9", + .value = 9 + }, + { .description = "" } } + }, + { + .name = "receive_input", + .description = "Receive input", + .type = CONFIG_BINARY, + .default_int = 1 + }, + { .name = "", .description = "", .type = CONFIG_END } + // clang-format on }; - const device_t mpu401_device = { - "Roland MPU-IPC-T", - "mpu401", - DEVICE_ISA, 0, - mpu401_standalone_init, mpu401_standalone_close, NULL, - { NULL }, - NULL, - NULL, - mpu401_standalone_config + .name = "Roland MPU-IPC-T", + .internal_name = "mpu401", + .flags = DEVICE_ISA, + .local = 0, + .init = mpu401_standalone_init, + .close = mpu401_standalone_close, + .reset = NULL, + { .available = NULL }, + .speed_changed = NULL, + .force_redraw = NULL, + .config = mpu401_standalone_config }; const device_t mpu401_mca_device = { - "Roland MPU-IMC", - "mpu401_mca", - DEVICE_MCA, 0, - mpu401_standalone_init, mpu401_standalone_close, NULL, - { NULL }, - NULL, - NULL, - mpu401_standalone_mca_config + .name = "Roland MPU-IMC", + .internal_name = "mpu401_mca", + .flags = DEVICE_MCA, + .local = 0, + .init = mpu401_standalone_init, + .close = mpu401_standalone_close, + .reset = NULL, + { .available = NULL }, + .speed_changed = NULL, + .force_redraw = NULL, + .config = mpu401_standalone_mca_config }; diff --git a/src/sound/snd_opl.c b/src/sound/snd_opl.c index 6cd31f608..21cc66f04 100644 --- a/src/sound/snd_opl.c +++ b/src/sound/snd_opl.c @@ -1,22 +1,22 @@ /* - * 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. + * 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. + * This file is part of the 86Box distribution. * - * Interface to the actual OPL emulator. + * Interface to the actual OPL emulator. * - * TODO: Finish re-working this into a device_t, which requires a - * poll-like function for "update" so the sound card can call - * that and get a buffer-full of sample data. + * TODO: Finish re-working this into a device_t, which requires a + * poll-like function for "update" so the sound card can call + * that and get a buffer-full of sample data. * - * Authors: Fred N. van Kempen, - * Miran Grca, + * Authors: Fred N. van Kempen, + * Miran Grca, * - * Copyright 2017-2020 Fred N. van Kempen. - * Copyright 2016-2020 Miran Grca. + * Copyright 2017-2020 Fred N. van Kempen. + * Copyright 2016-2020 Miran Grca. */ #include #include @@ -25,307 +25,53 @@ #include #include #define HAVE_STDARG_H -#include <86box/86box.h> -#include <86box/timer.h> + #include "cpu.h" +#include <86box/86box.h> +#include <86box/device.h> #include <86box/io.h> #include <86box/sound.h> #include <86box/snd_opl.h> -#include <86box/snd_opl_nuked.h> - - -enum { - FLAG_CYCLES = 0x02, - FLAG_OPL3 = 0x01 -}; - -enum { - STAT_TMR_OVER = 0x60, - STAT_TMR1_OVER = 0x40, - STAT_TMR2_OVER = 0x20, - STAT_TMR_ANY = 0x80 -}; - -enum { - CTRL_RESET = 0x80, - CTRL_TMR_MASK = 0x60, - CTRL_TMR1_MASK = 0x40, - CTRL_TMR2_MASK = 0x20, - CTRL_TMR2_START = 0x02, - CTRL_TMR1_START = 0x01 -}; - - -#ifdef ENABLE_OPL_LOG -int opl_do_log = ENABLE_OPL_LOG; - - -static void -opl_log(const char *fmt, ...) -{ - va_list ap; - - if (opl_do_log) { - va_start(ap, fmt); - pclog_ex(fmt, ap); - va_end(ap); - } -} -#else -#define opl_log(fmt, ...) -#endif - - -static void -timer_tick(opl_t *dev, int tmr) -{ - dev->timer_cur_count[tmr] = (dev->timer_cur_count[tmr] + 1) & 0xff; - - opl_log("Ticking timer %i, count now %02X...\n", tmr, dev->timer_cur_count[tmr]); - - if (dev->timer_cur_count[tmr] == 0x00) { - dev->status |= ((STAT_TMR1_OVER >> tmr) & ~dev->timer_ctrl); - dev->timer_cur_count[tmr] = dev->timer_count[tmr]; - - opl_log("Count wrapped around to zero, reloading timer %i (%02X), status = %02X...\n", tmr, (STAT_TMR1_OVER >> tmr), dev->status); - } - - timer_on_auto(&dev->timers[tmr], (tmr == 1) ? 320.0 : 80.0); -} - - -static void -timer_control(opl_t *dev, int tmr, int start) -{ - timer_on_auto(&dev->timers[tmr], 0.0); - - if (start) { - opl_log("Loading timer %i count: %02X = %02X\n", tmr, dev->timer_cur_count[tmr], dev->timer_count[tmr]); - dev->timer_cur_count[tmr] = dev->timer_count[tmr]; - if (dev->flags & FLAG_OPL3) - timer_tick(dev, tmr); /* Per the YMF 262 datasheet, OPL3 starts counting immediately, unlike OPL2. */ - else - timer_on_auto(&dev->timers[tmr], (tmr == 1) ? 320.0 : 80.0); - } else { - opl_log("Timer %i stopped\n", tmr); - if (tmr == 1) { - dev->status &= ~STAT_TMR2_OVER; - } else - dev->status &= ~STAT_TMR1_OVER; - } -} - - -static void -timer_1(void *priv) -{ - opl_t *dev = (opl_t *)priv; - - timer_tick(dev, 0); -} - - -static void -timer_2(void *priv) -{ - opl_t *dev = (opl_t *)priv; - - timer_tick(dev, 1); -} - - -static uint8_t -opl_read(opl_t *dev, uint16_t port) -{ - uint8_t ret = 0xff; - - if ((port & 0x0003) == 0x0000) { - ret = dev->status; - if (dev->status & STAT_TMR_OVER) - ret |= STAT_TMR_ANY; - } - - opl_log("OPL statret = %02x, status = %02x\n", ret, dev->status); - - return ret; -} - - -static void -opl_write(opl_t *dev, uint16_t port, uint8_t val) -{ - if ((port & 0x0001) == 0x0001) { - nuked_write_reg_buffered(dev->opl, dev->port, val); - - switch (dev->port) { - case 0x02: /* Timer 1 */ - dev->timer_count[0] = val; - opl_log("Timer 0 count now: %i\n", dev->timer_count[0]); - break; - - case 0x03: /* Timer 2 */ - dev->timer_count[1] = val; - opl_log("Timer 1 count now: %i\n", dev->timer_count[1]); - break; - - case 0x04: /* Timer control */ - if (val & CTRL_RESET) { - opl_log("Resetting timer status...\n"); - dev->status &= ~STAT_TMR_OVER; - } else { - dev->timer_ctrl = val; - timer_control(dev, 0, val & CTRL_TMR1_START); - timer_control(dev, 1, val & CTRL_TMR2_START); - opl_log("Status mask now %02X (val = %02X)\n", (val & ~CTRL_TMR_MASK) & CTRL_TMR_MASK, val); - } - break; - } - } else { - dev->port = nuked_write_addr(dev->opl, port, val) & 0x01ff; - - if (!(dev->flags & FLAG_OPL3)) - dev->port &= 0x00ff; - } -} - - -void -opl_set_do_cycles(opl_t *dev, int8_t do_cycles) -{ - if (do_cycles) - dev->flags |= FLAG_CYCLES; - else - dev->flags &= ~FLAG_CYCLES; -} - - -static void -opl_init(opl_t *dev, int is_opl3) -{ - memset(dev, 0x00, sizeof(opl_t)); - - dev->flags = FLAG_CYCLES; - if (is_opl3) - dev->flags |= FLAG_OPL3; - else - dev->status = 0x06; - - /* Create a NukedOPL object. */ - dev->opl = nuked_init(48000); - - timer_add(&dev->timers[0], timer_1, dev, 0); - timer_add(&dev->timers[1], timer_2, dev, 0); -} - - -void -opl_close(opl_t *dev) -{ - /* Release the NukedOPL object. */ - if (dev->opl) { - nuked_close(dev->opl); - dev->opl = NULL; - } -} +static uint32_t fm_dev_inst[FM_DRV_MAX][FM_MAX]; uint8_t -opl2_read(uint16_t port, void *priv) +fm_driver_get(int chip_id, fm_drv_t *drv) { - opl_t *dev = (opl_t *)priv; + switch (chip_id) { + case FM_YM3812: + if (fm_driver == FM_DRV_NUKED) { + *drv = nuked_opl_drv; + drv->priv = device_add_inst(&ym3812_nuked_device, fm_dev_inst[fm_driver][chip_id]++); + } else { + *drv = ymfm_drv; + drv->priv = device_add_inst(&ym3812_ymfm_device, fm_dev_inst[fm_driver][chip_id]++); + } + break; - if (dev->flags & FLAG_CYCLES) - cycles -= ((int) (isa_timing * 8)); + case FM_YMF262: + if (fm_driver == FM_DRV_NUKED) { + *drv = nuked_opl_drv; + drv->priv = device_add_inst(&ymf262_nuked_device, fm_dev_inst[fm_driver][chip_id]++); + } else { + *drv = ymfm_drv; + drv->priv = device_add_inst(&ymf262_ymfm_device, fm_dev_inst[fm_driver][chip_id]++); + } + break; - opl2_update(dev); - opl_log("OPL2 port read = %04x\n", port); - - return(opl_read(dev, port)); -} + case FM_YMF289B: + *drv = ymfm_drv; + drv->priv = device_add_inst(&ymf289b_ymfm_device, fm_dev_inst[fm_driver][chip_id]++); + break; + case FM_YMF278B: + *drv = ymfm_drv; + drv->priv = device_add_inst(&ymf278b_ymfm_device, fm_dev_inst[fm_driver][chip_id]++); + break; -void -opl2_write(uint16_t port, uint8_t val, void *priv) -{ - opl_t *dev = (opl_t *)priv; - - opl2_update(dev); - - opl_log("OPL2 port write = %04x\n", port); - opl_write(dev, port, val); -} - - -void -opl2_init(opl_t *dev) -{ - opl_init(dev, 0); -} - - -void -opl2_update(opl_t *dev) -{ - if (dev->pos >= sound_pos_global) { - return; - } - - nuked_generate_stream(dev->opl, - &dev->buffer[dev->pos * 2], - sound_pos_global - dev->pos); - - for (; dev->pos < sound_pos_global; dev->pos++) { - dev->buffer[dev->pos * 2] /= 2; - dev->buffer[(dev->pos * 2) + 1] = dev->buffer[dev->pos * 2]; + default: + return 0; } -} - -uint8_t -opl3_read(uint16_t port, void *priv) -{ - opl_t *dev = (opl_t *)priv; - - if (dev->flags & FLAG_CYCLES) - cycles -= ((int)(isa_timing * 8)); - - opl3_update(dev); - - return(opl_read(dev, port)); -} - - -void -opl3_write(uint16_t port, uint8_t val, void *priv) -{ - opl_t *dev = (opl_t *)priv; - - opl3_update(dev); - - opl_write(dev, port, val); -} - - -void -opl3_init(opl_t *dev) -{ - opl_init(dev, 1); -} - - -/* API to sound interface. */ -void -opl3_update(opl_t *dev) -{ - if (dev->pos >= sound_pos_global) - return; - - nuked_generate_stream(dev->opl, - &dev->buffer[dev->pos * 2], - sound_pos_global - dev->pos); - - for (; dev->pos < sound_pos_global; dev->pos++) { - dev->buffer[dev->pos * 2] /= 2; - dev->buffer[(dev->pos * 2) + 1] /= 2; - } -} + return 1; +}; diff --git a/src/sound/snd_opl_nuked.c b/src/sound/snd_opl_nuked.c index 5bde0d2dd..6ed697bf3 100644 --- a/src/sound/snd_opl_nuked.c +++ b/src/sound/snd_opl_nuked.c @@ -1,61 +1,66 @@ /* - * 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. + * 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. + * This file is part of the 86Box distribution. * - * Nuked OPL3 emulator. + * Nuked OPL3 emulator. * - * Thanks: - * MAME Development Team(Jarek Burczynski, Tatsuyuki Satoh): - * Feedback and Rhythm part calculation information. - * forums.submarine.org.uk(carbon14, opl3): - * Tremolo and phase generator calculation information. - * OPLx decapsulated(Matthew Gambrell, Olli Niemitalo): - * OPL2 ROMs. - * siliconpr0n.org(John McMaster, digshadow): - * YMF262 and VRC VII decaps and die shots. + * Thanks: + * MAME Development Team(Jarek Burczynski, Tatsuyuki Satoh): + * Feedback and Rhythm part calculation information. + * forums.submarine.org.uk(carbon14, opl3): + * Tremolo and phase generator calculation information. + * OPLx decapsulated(Matthew Gambrell, Olli Niemitalo): + * OPL2 ROMs. + * siliconpr0n.org(John McMaster, digshadow): + * YMF262 and VRC VII decaps and die shots. * - * Version: 1.8.0 + * Version: 1.8.0 * - * Translation from C++ into C done by Miran Grca. + * Translation from C++ into C done by Miran Grca. * - * **TODO** The OPL3 is a stereo chip, and, thus, always generates - * a two-sample stream of data, for the L and R channels, - * in that order. The OPL2, however, is mono. What should - * we generate for that? + * **TODO** The OPL3 is a stereo chip, and, thus, always generates + * a two-sample stream of data, for the L and R channels, + * in that order. The OPL2, however, is mono. What should + * we generate for that? * - * Version: @(#)snd_opl_nuked.c 1.0.5 2020/07/16 + * Version: @(#)snd_opl_nuked.c 1.0.5 2020/07/16 * - * Authors: Fred N. van Kempen, - * Miran Grca, - * Alexey Khokholov (Nuke.YKT) + * Authors: Fred N. van Kempen, + * Miran Grca, + * Alexey Khokholov (Nuke.YKT) * - * Copyright 2017-2020 Fred N. van Kempen. - * Copyright 2016-2020 Miran Grca. - * Copyright 2013-2018 Alexey Khokholov (Nuke.YKT) + * Copyright 2017-2020 Fred N. van Kempen. + * Copyright 2016-2020 Miran Grca. + * Copyright 2013-2018 Alexey Khokholov (Nuke.YKT) */ +#include #include #include #include #include + +#define HAVE_STDARG_H #include <86box/86box.h> -#include <86box/timer.h> -#include <86box/sound.h> #include <86box/snd_opl_nuked.h> +#include <86box/sound.h> +#include <86box/timer.h> +#include <86box/device.h> +#include <86box/snd_opl.h> +#define WRBUF_SIZE 1024 +#define WRBUF_DELAY 1 +#define RSM_FRAC 10 -#define WRBUF_SIZE 1024 -#define WRBUF_DELAY 1 -#define RSM_FRAC 10 - +#define OPL_FREQ FREQ_48000 // Channel types enum { - ch_2op = 0, - ch_4op = 1, + ch_2op = 0, + ch_4op = 1, ch_4op2 = 2, ch_drum = 3 }; @@ -67,110 +72,164 @@ enum { }; enum envelope_gen_num { - envelope_gen_num_attack = 0, - envelope_gen_num_decay = 1, + envelope_gen_num_attack = 0, + envelope_gen_num_decay = 1, envelope_gen_num_sustain = 2, envelope_gen_num_release = 3 }; - struct chan; struct chip; typedef struct slot { - struct chan *chan; - struct chip *dev; - int16_t out; - int16_t fbmod; - int16_t *mod; - int16_t prout; - int16_t eg_rout; - int16_t eg_out; - uint8_t eg_inc; - uint8_t eg_gen; - uint8_t eg_rate; - uint8_t eg_ksl; - uint8_t *trem; - uint8_t reg_vib; - uint8_t reg_type; - uint8_t reg_ksr; - uint8_t reg_mult; - uint8_t reg_ksl; - uint8_t reg_tl; - uint8_t reg_ar; - uint8_t reg_dr; - uint8_t reg_sl; - uint8_t reg_rr; - uint8_t reg_wf; - uint8_t key; - uint32_t pg_reset; - uint32_t pg_phase; - uint16_t pg_phase_out; - uint8_t slot_num; + struct chan *chan; + struct chip *dev; + int16_t out; + int16_t fbmod; + int16_t *mod; + int16_t prout; + int16_t eg_rout; + int16_t eg_out; + uint8_t eg_inc; + uint8_t eg_gen; + uint8_t eg_rate; + uint8_t eg_ksl; + uint8_t *trem; + uint8_t reg_vib; + uint8_t reg_type; + uint8_t reg_ksr; + uint8_t reg_mult; + uint8_t reg_ksl; + uint8_t reg_tl; + uint8_t reg_ar; + uint8_t reg_dr; + uint8_t reg_sl; + uint8_t reg_rr; + uint8_t reg_wf; + uint8_t key; + uint32_t pg_reset; + uint32_t pg_phase; + uint16_t pg_phase_out; + uint8_t slot_num; } slot_t; typedef struct chan { - slot_t *slots[2]; - struct chan *pair; - struct chip *dev; - int16_t *out[4]; - uint8_t chtype; - uint16_t f_num; - uint8_t block; - uint8_t fb; - uint8_t con; - uint8_t alg; - uint8_t ksv; - uint16_t cha, - chb; - uint8_t ch_num; + slot_t *slots[2]; + struct chan *pair; + struct chip *dev; + int16_t *out[4]; + uint8_t chtype; + uint16_t f_num; + uint8_t block; + uint8_t fb; + uint8_t con; + uint8_t alg; + uint8_t ksv; + uint16_t cha; + uint16_t chb; + uint8_t ch_num; } chan_t; typedef struct wrbuf { - uint64_t time; - uint16_t reg; - uint8_t data; + uint64_t time; + uint16_t reg; + uint8_t data; } wrbuf_t; typedef struct chip { - chan_t chan[18]; - slot_t slot[36]; - uint16_t timer; - uint64_t eg_timer; - uint8_t eg_timerrem; - uint8_t eg_state; - uint8_t eg_add; - uint8_t newm; - uint8_t nts; - uint8_t rhy; - uint8_t vibpos; - uint8_t vibshift; - uint8_t tremolo; - uint8_t tremolopos; - uint8_t tremoloshift; - uint32_t noise; - int16_t zeromod; - int32_t mixbuff[2]; - uint8_t rm_hh_bit2; - uint8_t rm_hh_bit3; - uint8_t rm_hh_bit7; - uint8_t rm_hh_bit8; - uint8_t rm_tc_bit3; - uint8_t rm_tc_bit5; + chan_t chan[18]; + slot_t slot[36]; + uint16_t timer; + uint64_t eg_timer; + uint8_t eg_timerrem; + uint8_t eg_state; + uint8_t eg_add; + uint8_t newm; + uint8_t nts; + uint8_t rhy; + uint8_t vibpos; + uint8_t vibshift; + uint8_t tremolo; + uint8_t tremolopos; + uint8_t tremoloshift; + uint32_t noise; + int16_t zeromod; + int32_t mixbuff[2]; + uint8_t rm_hh_bit2; + uint8_t rm_hh_bit3; + uint8_t rm_hh_bit7; + uint8_t rm_hh_bit8; + uint8_t rm_tc_bit3; + uint8_t rm_tc_bit5; - //OPL3L - int32_t rateratio; - int32_t samplecnt; - int32_t oldsamples[2]; - int32_t samples[2]; + // OPL3L + int32_t rateratio; + int32_t samplecnt; + int32_t oldsamples[2]; + int32_t samples[2]; - uint64_t wrbuf_samplecnt; - uint32_t wrbuf_cur; - uint32_t wrbuf_last; - uint64_t wrbuf_lasttime; - wrbuf_t wrbuf[WRBUF_SIZE]; + uint64_t wrbuf_samplecnt; + uint32_t wrbuf_cur; + uint32_t wrbuf_last; + uint64_t wrbuf_lasttime; + wrbuf_t wrbuf[WRBUF_SIZE]; } nuked_t; +typedef struct { + nuked_t opl; + int8_t flags; + int8_t pad; + + uint16_t port; + uint8_t status; + uint8_t timer_ctrl; + uint16_t timer_count[2]; + uint16_t timer_cur_count[2]; + + pc_timer_t timers[2]; + + int pos; + int32_t buffer[SOUNDBUFLEN * 2]; +} nuked_drv_t; + +enum { + FLAG_CYCLES = 0x02, + FLAG_OPL3 = 0x01 +}; + +enum { + STAT_TMR_OVER = 0x60, + STAT_TMR1_OVER = 0x40, + STAT_TMR2_OVER = 0x20, + STAT_TMR_ANY = 0x80 +}; + +enum { + CTRL_RESET = 0x80, + CTRL_TMR_MASK = 0x60, + CTRL_TMR1_MASK = 0x40, + CTRL_TMR2_MASK = 0x20, + CTRL_TMR2_START = 0x02, + CTRL_TMR1_START = 0x01 +}; + +#ifdef ENABLE_OPL_LOG +int nuked_do_log = ENABLE_OPL_LOG; + +static void +nuked_log(const char *fmt, ...) +{ + va_list ap; + + if (nuked_do_log) { + va_start(ap, fmt); + pclog_ex(fmt, ap); + va_end(ap); + } +} +#else +# define nuked_log(fmt, ...) +#endif // logsin table static const uint16_t logsinrom[256] = { @@ -262,10 +321,10 @@ static const uint8_t kslshift[4] = { // envelope generator constants static const uint8_t eg_incstep[4][4] = { - { 0, 0, 0, 0 }, - { 1, 0, 0, 0 }, - { 1, 0, 1, 0 }, - { 1, 1, 1, 0 } + {0, 0, 0, 0}, + { 1, 0, 0, 0}, + { 1, 0, 1, 0}, + { 1, 1, 1, 0} }; // address decoding @@ -279,20 +338,18 @@ static const uint8_t ch_slot[18] = { }; // Envelope generator -typedef int16_t(*env_sinfunc)(uint16_t phase, uint16_t envelope); -typedef void(*env_genfunc)(slot_t *slot); - +typedef int16_t (*env_sinfunc)(uint16_t phase, uint16_t envelope); +typedef void (*env_genfunc)(slot_t *slot); static int16_t env_calc_exp(uint32_t level) { if (level > 0x1fff) - level = 0x1fff; + level = 0x1fff; - return((exprom[level & 0xff] << 1) >> (level >> 8)); + return ((exprom[level & 0xff] << 1) >> (level >> 8)); } - static int16_t env_calc_sin0(uint16_t phase, uint16_t env) { @@ -302,17 +359,16 @@ env_calc_sin0(uint16_t phase, uint16_t env) phase &= 0x3ff; if (phase & 0x0200) - neg = 0xffff; + neg = 0xffff; if (phase & 0x0100) - out = logsinrom[(phase & 0xff) ^ 0xff]; + out = logsinrom[(phase & 0xff) ^ 0xff]; else - out = logsinrom[phase & 0xff]; + out = logsinrom[phase & 0xff]; - return(env_calc_exp(out + (env << 3)) ^ neg); + return (env_calc_exp(out + (env << 3)) ^ neg); } - static int16_t env_calc_sin1(uint16_t phase, uint16_t env) { @@ -321,16 +377,15 @@ env_calc_sin1(uint16_t phase, uint16_t env) phase &= 0x3ff; if (phase & 0x0200) - out = 0x1000; + out = 0x1000; else if (phase & 0x0100) - out = logsinrom[(phase & 0xff) ^ 0xff]; + out = logsinrom[(phase & 0xff) ^ 0xff]; else - out = logsinrom[phase & 0xff]; + out = logsinrom[phase & 0xff]; - return(env_calc_exp(out + (env << 3))); + return (env_calc_exp(out + (env << 3))); } - static int16_t env_calc_sin2(uint16_t phase, uint16_t env) { @@ -339,14 +394,13 @@ env_calc_sin2(uint16_t phase, uint16_t env) phase &= 0x03ff; if (phase & 0x0100) - out = logsinrom[(phase & 0xff) ^ 0xff]; + out = logsinrom[(phase & 0xff) ^ 0xff]; else - out = logsinrom[phase & 0xff]; + out = logsinrom[phase & 0xff]; - return(env_calc_exp(out + (env << 3))); + return (env_calc_exp(out + (env << 3))); } - static int16_t env_calc_sin3(uint16_t phase, uint16_t env) { @@ -355,14 +409,13 @@ env_calc_sin3(uint16_t phase, uint16_t env) phase &= 0x03ff; if (phase & 0x0100) - out = 0x1000; + out = 0x1000; else - out = logsinrom[phase & 0xff]; + out = logsinrom[phase & 0xff]; - return(env_calc_exp(out + (env << 3))); + return (env_calc_exp(out + (env << 3))); } - static int16_t env_calc_sin4(uint16_t phase, uint16_t env) { @@ -372,19 +425,18 @@ env_calc_sin4(uint16_t phase, uint16_t env) phase &= 0x03ff; if ((phase & 0x0300) == 0x0100) - neg = 0xffff; + neg = 0xffff; if (phase & 0x0200) - out = 0x1000; + out = 0x1000; else if (phase & 0x80) - out = logsinrom[((phase ^ 0xff) << 1) & 0xff]; + out = logsinrom[((phase ^ 0xff) << 1) & 0xff]; else - out = logsinrom[(phase << 1) & 0xff]; + out = logsinrom[(phase << 1) & 0xff]; - return(env_calc_exp(out + (env << 3)) ^ neg); + return (env_calc_exp(out + (env << 3)) ^ neg); } - static int16_t env_calc_sin5(uint16_t phase, uint16_t env) { @@ -393,16 +445,15 @@ env_calc_sin5(uint16_t phase, uint16_t env) phase &= 0x03ff; if (phase & 0x0200) - out = 0x1000; + out = 0x1000; else if (phase & 0x80) - out = logsinrom[((phase ^ 0xff) << 1) & 0xff]; + out = logsinrom[((phase ^ 0xff) << 1) & 0xff]; else - out = logsinrom[(phase << 1) & 0xff]; + out = logsinrom[(phase << 1) & 0xff]; - return(env_calc_exp(out + (env << 3))); + return (env_calc_exp(out + (env << 3))); } - static int16_t env_calc_sin6(uint16_t phase, uint16_t env) { @@ -411,12 +462,11 @@ env_calc_sin6(uint16_t phase, uint16_t env) phase &= 0x03ff; if (phase & 0x0200) - neg = 0xffff; + neg = 0xffff; - return(env_calc_exp(env << 3) ^ neg); + return (env_calc_exp(env << 3) ^ neg); } - static int16_t env_calc_sin7(uint16_t phase, uint16_t env) { @@ -426,16 +476,15 @@ env_calc_sin7(uint16_t phase, uint16_t env) phase &= 0x03ff; if (phase & 0x0200) { - neg = 0xffff; - phase = (phase & 0x01ff) ^ 0x01ff; + neg = 0xffff; + phase = (phase & 0x01ff) ^ 0x01ff; } out = phase << 3; - return(env_calc_exp(out + (env << 3)) ^ neg); + return (env_calc_exp(out + (env << 3)) ^ neg); } - static const env_sinfunc env_sin[8] = { env_calc_sin0, env_calc_sin1, @@ -447,233 +496,233 @@ static const env_sinfunc env_sin[8] = { env_calc_sin7 }; - static void env_update_ksl(slot_t *slot) { - int16_t ksl = (kslrom[slot->chan->f_num >> 6] << 2) - - ((0x08 - slot->chan->block) << 5); + int16_t ksl = (kslrom[slot->chan->f_num >> 6] << 2) - ((0x08 - slot->chan->block) << 5); if (ksl < 0) - ksl = 0; + ksl = 0; - slot->eg_ksl = (uint8_t)ksl; + slot->eg_ksl = (uint8_t) ksl; } - static void env_calc(slot_t *slot) { - uint8_t nonzero; - uint8_t rate; - uint8_t rate_hi; - uint8_t rate_lo; - uint8_t reg_rate = 0; - uint8_t ks; - uint8_t eg_shift, shift; + uint8_t nonzero; + uint8_t rate; + uint8_t rate_hi; + uint8_t rate_lo; + uint8_t reg_rate = 0; + uint8_t ks; + uint8_t eg_shift; + uint8_t shift; uint16_t eg_rout; - int16_t eg_inc; - uint8_t eg_off; - uint8_t reset = 0; + int16_t eg_inc; + uint8_t eg_off; + uint8_t reset = 0; - slot->eg_out = slot->eg_rout + (slot->reg_tl << 2) + - (slot->eg_ksl >> kslshift[slot->reg_ksl]) + *slot->trem; + slot->eg_out = slot->eg_rout + (slot->reg_tl << 2) + (slot->eg_ksl >> kslshift[slot->reg_ksl]) + *slot->trem; if (slot->key && slot->eg_gen == envelope_gen_num_release) { - reset = 1; - reg_rate = slot->reg_ar; - } else switch (slot->eg_gen) { - case envelope_gen_num_attack: - reg_rate = slot->reg_ar; - break; + reset = 1; + reg_rate = slot->reg_ar; + } else + switch (slot->eg_gen) { + case envelope_gen_num_attack: + reg_rate = slot->reg_ar; + break; - case envelope_gen_num_decay: - reg_rate = slot->reg_dr; - break; + case envelope_gen_num_decay: + reg_rate = slot->reg_dr; + break; - case envelope_gen_num_sustain: - if (! slot->reg_type) - reg_rate = slot->reg_rr; - break; + case envelope_gen_num_sustain: + if (!slot->reg_type) + reg_rate = slot->reg_rr; + break; - case envelope_gen_num_release: - reg_rate = slot->reg_rr; - break; - } + case envelope_gen_num_release: + reg_rate = slot->reg_rr; + break; + + default: + break; + } slot->pg_reset = reset; - ks = slot->chan->ksv >> ((slot->reg_ksr ^ 1) << 1); - nonzero = (reg_rate != 0); - rate = ks + (reg_rate << 2); - rate_hi = rate >> 2; - rate_lo = rate & 0x03; + ks = slot->chan->ksv >> ((slot->reg_ksr ^ 1) << 1); + nonzero = (reg_rate != 0); + rate = ks + (reg_rate << 2); + rate_hi = rate >> 2; + rate_lo = rate & 0x03; if (rate_hi & 0x10) - rate_hi = 0x0f; + rate_hi = 0x0f; eg_shift = rate_hi + slot->dev->eg_add; - shift = 0; + shift = 0; if (nonzero) { - if (rate_hi < 12) { - if (slot->dev->eg_state) switch (eg_shift) { - case 12: - shift = 1; - break; + if (rate_hi < 12) { + if (slot->dev->eg_state) + switch (eg_shift) { + case 12: + shift = 1; + break; - case 13: - shift = (rate_lo >> 1) & 0x01; - break; + case 13: + shift = (rate_lo >> 1) & 0x01; + break; - case 14: - shift = rate_lo & 0x01; - break; + case 14: + shift = rate_lo & 0x01; + break; - default: - break; - } - } else { - shift = (rate_hi & 0x03) + eg_incstep[rate_lo][slot->dev->timer & 0x03]; - if (shift & 0x04) - shift = 0x03; - if (! shift) - shift = slot->dev->eg_state; - } + default: + break; + } + } else { + shift = (rate_hi & 0x03) + eg_incstep[rate_lo][slot->dev->timer & 0x03]; + if (shift & 0x04) + shift = 0x03; + if (!shift) + shift = slot->dev->eg_state; + } } eg_rout = slot->eg_rout; - eg_inc = 0; - eg_off = 0; + eg_inc = 0; + eg_off = 0; // Instant attack if (reset && rate_hi == 0x0f) - eg_rout = 0x00; + eg_rout = 0x00; // Envelope off if ((slot->eg_rout & 0x1f8) == 0x1f8) - eg_off = 1; + eg_off = 1; if (slot->eg_gen != envelope_gen_num_attack && !reset && eg_off) - eg_rout = 0x1ff; + eg_rout = 0x1ff; switch (slot->eg_gen) { - case envelope_gen_num_attack: - if (! slot->eg_rout) - slot->eg_gen = envelope_gen_num_decay; - else if (slot->key && shift > 0 && rate_hi != 0x0f) - eg_inc = ((~slot->eg_rout) << shift) >> 4; - break; + case envelope_gen_num_attack: + if (!slot->eg_rout) + slot->eg_gen = envelope_gen_num_decay; + else if (slot->key && shift > 0 && rate_hi != 0x0f) + eg_inc = ((~slot->eg_rout) << shift) >> 4; + break; - case envelope_gen_num_decay: - if ((slot->eg_rout >> 4) == slot->reg_sl) - slot->eg_gen = envelope_gen_num_sustain; - else if (!eg_off && !reset && shift > 0) - eg_inc = 1 << (shift - 1); - break; + case envelope_gen_num_decay: + if ((slot->eg_rout >> 4) == slot->reg_sl) + slot->eg_gen = envelope_gen_num_sustain; + else if (!eg_off && !reset && shift > 0) + eg_inc = 1 << (shift - 1); + break; - case envelope_gen_num_sustain: - case envelope_gen_num_release: - if (!eg_off && !reset && shift > 0) - eg_inc = 1 << (shift - 1); - break; + case envelope_gen_num_sustain: + case envelope_gen_num_release: + if (!eg_off && !reset && shift > 0) + eg_inc = 1 << (shift - 1); + break; + + default: + break; } slot->eg_rout = (eg_rout + eg_inc) & 0x1ff; // Key off if (reset) - slot->eg_gen = envelope_gen_num_attack; + slot->eg_gen = envelope_gen_num_attack; - if (! slot->key) - slot->eg_gen = envelope_gen_num_release; + if (!slot->key) + slot->eg_gen = envelope_gen_num_release; } - static void env_key_on(slot_t *slot, uint8_t type) { slot->key |= type; } - static void env_key_off(slot_t *slot, uint8_t type) { slot->key &= ~type; } - static void phase_generate(slot_t *slot) { uint16_t f_num; uint32_t basefreq; - uint8_t rm_xor, n_bit; + uint8_t rm_xor; + uint8_t n_bit; uint32_t noise; uint16_t phase; - int8_t range; - uint8_t vibpos; + int8_t range; + uint8_t vibpos; nuked_t *dev; - dev = slot->dev; + dev = slot->dev; f_num = slot->chan->f_num; if (slot->reg_vib) { - range = (f_num >> 7) & 7; - vibpos = dev->vibpos; + range = (f_num >> 7) & 7; + vibpos = dev->vibpos; - if (! (vibpos & 3)) - range = 0; - else if (vibpos & 1) - range >>= 1; - range >>= dev->vibshift; + if (!(vibpos & 3)) + range = 0; + else if (vibpos & 1) + range >>= 1; + range >>= dev->vibshift; - if (vibpos & 4) - range = -range; - f_num += range; + if (vibpos & 4) + range = -range; + f_num += range; } basefreq = (f_num << slot->chan->block) >> 1; - phase = (uint16_t)(slot->pg_phase >> 9); + phase = (uint16_t) (slot->pg_phase >> 9); if (slot->pg_reset) - slot->pg_phase = 0; + slot->pg_phase = 0; slot->pg_phase += (basefreq * mt[slot->reg_mult]) >> 1; // Rhythm mode - noise = dev->noise; + noise = dev->noise; slot->pg_phase_out = phase; - if (slot->slot_num == 13) { // hh - dev->rm_hh_bit2 = (phase >> 2) & 1; - dev->rm_hh_bit3 = (phase >> 3) & 1; - dev->rm_hh_bit7 = (phase >> 7) & 1; - dev->rm_hh_bit8 = (phase >> 8) & 1; + if (slot->slot_num == 13) { // hh + dev->rm_hh_bit2 = (phase >> 2) & 1; + dev->rm_hh_bit3 = (phase >> 3) & 1; + dev->rm_hh_bit7 = (phase >> 7) & 1; + dev->rm_hh_bit8 = (phase >> 8) & 1; } - if (slot->slot_num == 17 && (dev->rhy & 0x20)) { // tc - dev->rm_tc_bit3 = (phase >> 3) & 1; - dev->rm_tc_bit5 = (phase >> 5) & 1; + if (slot->slot_num == 17 && (dev->rhy & 0x20)) { // tc + dev->rm_tc_bit3 = (phase >> 3) & 1; + dev->rm_tc_bit5 = (phase >> 5) & 1; } if (dev->rhy & 0x20) { - rm_xor = (dev->rm_hh_bit2 ^ dev->rm_hh_bit7) | - (dev->rm_hh_bit3 ^ dev->rm_tc_bit5) | - (dev->rm_tc_bit3 ^ dev->rm_tc_bit5); + rm_xor = (dev->rm_hh_bit2 ^ dev->rm_hh_bit7) | (dev->rm_hh_bit3 ^ dev->rm_tc_bit5) | (dev->rm_tc_bit3 ^ dev->rm_tc_bit5); - switch (slot->slot_num) { - case 13: // hh - slot->pg_phase_out = rm_xor << 9; - if (rm_xor ^ (noise & 1)) - slot->pg_phase_out |= 0xd0; - else - slot->pg_phase_out |= 0x34; - break; + switch (slot->slot_num) { + case 13: // hh + slot->pg_phase_out = rm_xor << 9; + if (rm_xor ^ (noise & 1)) + slot->pg_phase_out |= 0xd0; + else + slot->pg_phase_out |= 0x34; + break; - case 16: // sd - slot->pg_phase_out = (dev->rm_hh_bit8 << 9) | - ((dev->rm_hh_bit8 ^ (noise & 1)) << 8); - break; + case 16: // sd + slot->pg_phase_out = (dev->rm_hh_bit8 << 9) | ((dev->rm_hh_bit8 ^ (noise & 1)) << 8); + break; - case 17: // tc - slot->pg_phase_out = (rm_xor << 9) | 0x80; - break; + case 17: // tc + slot->pg_phase_out = (rm_xor << 9) | 0x80; + break; - default: - break; - } + default: + break; + } } n_bit = ((noise >> 14) ^ noise) & 0x01; @@ -681,32 +730,29 @@ phase_generate(slot_t *slot) dev->noise = (noise >> 1) | (n_bit << 22); } - static void slot_write_20(slot_t *slot, uint8_t data) { if ((data >> 7) & 0x01) - slot->trem = &slot->dev->tremolo; + slot->trem = &slot->dev->tremolo; else - slot->trem = (uint8_t*)&slot->dev->zeromod; + slot->trem = (uint8_t *) &slot->dev->zeromod; - slot->reg_vib = (data >> 6) & 0x01; + slot->reg_vib = (data >> 6) & 0x01; slot->reg_type = (data >> 5) & 0x01; - slot->reg_ksr = (data >> 4) & 0x01; + slot->reg_ksr = (data >> 4) & 0x01; slot->reg_mult = data & 0x0f; } - static void slot_write_40(slot_t *slot, uint8_t data) { slot->reg_ksl = (data >> 6) & 0x03; - slot->reg_tl = data & 0x3f; + slot->reg_tl = data & 0x3f; env_update_ksl(slot); } - static void slot_write_60(slot_t *slot, uint8_t data) { @@ -714,689 +760,901 @@ slot_write_60(slot_t *slot, uint8_t data) slot->reg_dr = data & 0x0f; } - static void slot_write_80(slot_t *slot, uint8_t data) { slot->reg_sl = (data >> 4) & 0x0f; if (slot->reg_sl == 0x0f) - slot->reg_sl = 0x1f; + slot->reg_sl = 0x1f; slot->reg_rr = data & 0x0f; } - static void slot_write_e0(slot_t *slot, uint8_t data) { slot->reg_wf = data & 0x07; if (slot->dev->newm == 0x00) - slot->reg_wf &= 0x03; + slot->reg_wf &= 0x03; } - static void slot_generate(slot_t *slot) { slot->out = env_sin[slot->reg_wf](slot->pg_phase_out + *slot->mod, - slot->eg_out); + slot->eg_out); } - static void slot_calc_fb(slot_t *slot) { if (slot->chan->fb != 0x00) - slot->fbmod = (slot->prout + slot->out) >> (0x09 - slot->chan->fb); + slot->fbmod = (slot->prout + slot->out) >> (0x09 - slot->chan->fb); else - slot->fbmod = 0; + slot->fbmod = 0; slot->prout = slot->out; } - static void channel_setup_alg(chan_t *ch) { if (ch->chtype == ch_drum) { - if (ch->ch_num == 7 || ch->ch_num == 8) { - ch->slots[0]->mod = &ch->dev->zeromod; - ch->slots[1]->mod = &ch->dev->zeromod; - return; - } + if (ch->ch_num == 7 || ch->ch_num == 8) { + ch->slots[0]->mod = &ch->dev->zeromod; + ch->slots[1]->mod = &ch->dev->zeromod; + return; + } - switch (ch->alg & 0x01) { - case 0x00: - ch->slots[0]->mod = &ch->slots[0]->fbmod; - ch->slots[1]->mod = &ch->slots[0]->out; - break; + switch (ch->alg & 0x01) { + case 0x00: + ch->slots[0]->mod = &ch->slots[0]->fbmod; + ch->slots[1]->mod = &ch->slots[0]->out; + break; - case 0x01: - ch->slots[0]->mod = &ch->slots[0]->fbmod; - ch->slots[1]->mod = &ch->dev->zeromod; - break; - } - return; + case 0x01: + ch->slots[0]->mod = &ch->slots[0]->fbmod; + ch->slots[1]->mod = &ch->dev->zeromod; + break; + + default: + break; + } + return; } if (ch->alg & 0x08) - return; + return; if (ch->alg & 0x04) { - ch->pair->out[0] = &ch->dev->zeromod; - ch->pair->out[1] = &ch->dev->zeromod; - ch->pair->out[2] = &ch->dev->zeromod; - ch->pair->out[3] = &ch->dev->zeromod; + ch->pair->out[0] = &ch->dev->zeromod; + ch->pair->out[1] = &ch->dev->zeromod; + ch->pair->out[2] = &ch->dev->zeromod; + ch->pair->out[3] = &ch->dev->zeromod; - switch (ch->alg & 0x03) { - case 0x00: - ch->pair->slots[0]->mod = &ch->pair->slots[0]->fbmod; - ch->pair->slots[1]->mod = &ch->pair->slots[0]->out; - ch->slots[0]->mod = &ch->pair->slots[1]->out; - ch->slots[1]->mod = &ch->slots[0]->out; - ch->out[0] = &ch->slots[1]->out; - ch->out[1] = &ch->dev->zeromod; - ch->out[2] = &ch->dev->zeromod; - ch->out[3] = &ch->dev->zeromod; - break; + switch (ch->alg & 0x03) { + case 0x00: + ch->pair->slots[0]->mod = &ch->pair->slots[0]->fbmod; + ch->pair->slots[1]->mod = &ch->pair->slots[0]->out; + ch->slots[0]->mod = &ch->pair->slots[1]->out; + ch->slots[1]->mod = &ch->slots[0]->out; + ch->out[0] = &ch->slots[1]->out; + ch->out[1] = &ch->dev->zeromod; + ch->out[2] = &ch->dev->zeromod; + ch->out[3] = &ch->dev->zeromod; + break; - case 0x01: - ch->pair->slots[0]->mod = &ch->pair->slots[0]->fbmod; - ch->pair->slots[1]->mod = &ch->pair->slots[0]->out; - ch->slots[0]->mod = &ch->dev->zeromod; - ch->slots[1]->mod = &ch->slots[0]->out; - ch->out[0] = &ch->pair->slots[1]->out; - ch->out[1] = &ch->slots[1]->out; - ch->out[2] = &ch->dev->zeromod; - ch->out[3] = &ch->dev->zeromod; - break; + case 0x01: + ch->pair->slots[0]->mod = &ch->pair->slots[0]->fbmod; + ch->pair->slots[1]->mod = &ch->pair->slots[0]->out; + ch->slots[0]->mod = &ch->dev->zeromod; + ch->slots[1]->mod = &ch->slots[0]->out; + ch->out[0] = &ch->pair->slots[1]->out; + ch->out[1] = &ch->slots[1]->out; + ch->out[2] = &ch->dev->zeromod; + ch->out[3] = &ch->dev->zeromod; + break; - case 0x02: - ch->pair->slots[0]->mod = &ch->pair->slots[0]->fbmod; - ch->pair->slots[1]->mod = &ch->dev->zeromod; - ch->slots[0]->mod = &ch->pair->slots[1]->out; - ch->slots[1]->mod = &ch->slots[0]->out; - ch->out[0] = &ch->pair->slots[0]->out; - ch->out[1] = &ch->slots[1]->out; - ch->out[2] = &ch->dev->zeromod; - ch->out[3] = &ch->dev->zeromod; - break; + case 0x02: + ch->pair->slots[0]->mod = &ch->pair->slots[0]->fbmod; + ch->pair->slots[1]->mod = &ch->dev->zeromod; + ch->slots[0]->mod = &ch->pair->slots[1]->out; + ch->slots[1]->mod = &ch->slots[0]->out; + ch->out[0] = &ch->pair->slots[0]->out; + ch->out[1] = &ch->slots[1]->out; + ch->out[2] = &ch->dev->zeromod; + ch->out[3] = &ch->dev->zeromod; + break; - case 0x03: - ch->pair->slots[0]->mod = &ch->pair->slots[0]->fbmod; - ch->pair->slots[1]->mod = &ch->dev->zeromod; - ch->slots[0]->mod = &ch->pair->slots[1]->out; - ch->slots[1]->mod = &ch->dev->zeromod; - ch->out[0] = &ch->pair->slots[0]->out; - ch->out[1] = &ch->slots[0]->out; - ch->out[2] = &ch->slots[1]->out; - ch->out[3] = &ch->dev->zeromod; - break; - } - } else switch (ch->alg & 0x01) { - case 0x00: - ch->slots[0]->mod = &ch->slots[0]->fbmod; - ch->slots[1]->mod = &ch->slots[0]->out; - ch->out[0] = &ch->slots[1]->out; - ch->out[1] = &ch->dev->zeromod; - ch->out[2] = &ch->dev->zeromod; - ch->out[3] = &ch->dev->zeromod; - break; + case 0x03: + ch->pair->slots[0]->mod = &ch->pair->slots[0]->fbmod; + ch->pair->slots[1]->mod = &ch->dev->zeromod; + ch->slots[0]->mod = &ch->pair->slots[1]->out; + ch->slots[1]->mod = &ch->dev->zeromod; + ch->out[0] = &ch->pair->slots[0]->out; + ch->out[1] = &ch->slots[0]->out; + ch->out[2] = &ch->slots[1]->out; + ch->out[3] = &ch->dev->zeromod; + break; - case 0x01: - ch->slots[0]->mod = &ch->slots[0]->fbmod; - ch->slots[1]->mod = &ch->dev->zeromod; - ch->out[0] = &ch->slots[0]->out; - ch->out[1] = &ch->slots[1]->out; - ch->out[2] = &ch->dev->zeromod; - ch->out[3] = &ch->dev->zeromod; - break; - } + default: + break; + } + } else + switch (ch->alg & 0x01) { + case 0x00: + ch->slots[0]->mod = &ch->slots[0]->fbmod; + ch->slots[1]->mod = &ch->slots[0]->out; + ch->out[0] = &ch->slots[1]->out; + ch->out[1] = &ch->dev->zeromod; + ch->out[2] = &ch->dev->zeromod; + ch->out[3] = &ch->dev->zeromod; + break; + + case 0x01: + ch->slots[0]->mod = &ch->slots[0]->fbmod; + ch->slots[1]->mod = &ch->dev->zeromod; + ch->out[0] = &ch->slots[0]->out; + ch->out[1] = &ch->slots[1]->out; + ch->out[2] = &ch->dev->zeromod; + ch->out[3] = &ch->dev->zeromod; + break; + + default: + break; + } } - static void channel_update_rhythm(nuked_t *dev, uint8_t data) { - chan_t *ch6, *ch7, *ch8; + chan_t *ch6; + chan_t *ch7; + chan_t *ch8; uint8_t chnum; dev->rhy = data & 0x3f; if (dev->rhy & 0x20) { - ch6 = &dev->chan[6]; - ch7 = &dev->chan[7]; - ch8 = &dev->chan[8]; - ch6->out[0] = &ch6->slots[1]->out; - ch6->out[1] = &ch6->slots[1]->out; - ch6->out[2] = &dev->zeromod; - ch6->out[3] = &dev->zeromod; - ch7->out[0] = &ch7->slots[0]->out; - ch7->out[1] = &ch7->slots[0]->out; - ch7->out[2] = &ch7->slots[1]->out; - ch7->out[3] = &ch7->slots[1]->out; - ch8->out[0] = &ch8->slots[0]->out; - ch8->out[1] = &ch8->slots[0]->out; - ch8->out[2] = &ch8->slots[1]->out; - ch8->out[3] = &ch8->slots[1]->out; + ch6 = &dev->chan[6]; + ch7 = &dev->chan[7]; + ch8 = &dev->chan[8]; + ch6->out[0] = &ch6->slots[1]->out; + ch6->out[1] = &ch6->slots[1]->out; + ch6->out[2] = &dev->zeromod; + ch6->out[3] = &dev->zeromod; + ch7->out[0] = &ch7->slots[0]->out; + ch7->out[1] = &ch7->slots[0]->out; + ch7->out[2] = &ch7->slots[1]->out; + ch7->out[3] = &ch7->slots[1]->out; + ch8->out[0] = &ch8->slots[0]->out; + ch8->out[1] = &ch8->slots[0]->out; + ch8->out[2] = &ch8->slots[1]->out; + ch8->out[3] = &ch8->slots[1]->out; - for (chnum = 6; chnum < 9; chnum++) - dev->chan[chnum].chtype = ch_drum; + for (chnum = 6; chnum < 9; chnum++) + dev->chan[chnum].chtype = ch_drum; - channel_setup_alg(ch6); - channel_setup_alg(ch7); - channel_setup_alg(ch8); + channel_setup_alg(ch6); + channel_setup_alg(ch7); + channel_setup_alg(ch8); - // hh - if (dev->rhy & 0x01) - env_key_on(ch7->slots[0], egk_drum); - else - env_key_off(ch7->slots[0], egk_drum); + // hh + if (dev->rhy & 0x01) + env_key_on(ch7->slots[0], egk_drum); + else + env_key_off(ch7->slots[0], egk_drum); - // tc - if (dev->rhy & 0x02) - env_key_on(ch8->slots[1], egk_drum); - else - env_key_off(ch8->slots[1], egk_drum); + // tc + if (dev->rhy & 0x02) + env_key_on(ch8->slots[1], egk_drum); + else + env_key_off(ch8->slots[1], egk_drum); - // tom - if (dev->rhy & 0x04) - env_key_on(ch8->slots[0], egk_drum); - else - env_key_off(ch8->slots[0], egk_drum); + // tom + if (dev->rhy & 0x04) + env_key_on(ch8->slots[0], egk_drum); + else + env_key_off(ch8->slots[0], egk_drum); - // sd - if (dev->rhy & 0x08) - env_key_on(ch7->slots[1], egk_drum); - else - env_key_off(ch7->slots[1], egk_drum); + // sd + if (dev->rhy & 0x08) + env_key_on(ch7->slots[1], egk_drum); + else + env_key_off(ch7->slots[1], egk_drum); - // bd - if (dev->rhy & 0x10) { - env_key_on(ch6->slots[0], egk_drum); - env_key_on(ch6->slots[1], egk_drum); - } else { - env_key_off(ch6->slots[0], egk_drum); - env_key_off(ch6->slots[1], egk_drum); - } + // bd + if (dev->rhy & 0x10) { + env_key_on(ch6->slots[0], egk_drum); + env_key_on(ch6->slots[1], egk_drum); + } else { + env_key_off(ch6->slots[0], egk_drum); + env_key_off(ch6->slots[1], egk_drum); + } } else { - for (chnum = 6; chnum < 9; chnum++) { - dev->chan[chnum].chtype = ch_2op; + for (chnum = 6; chnum < 9; chnum++) { + dev->chan[chnum].chtype = ch_2op; - channel_setup_alg(&dev->chan[chnum]); - env_key_off(dev->chan[chnum].slots[0], egk_drum); - env_key_off(dev->chan[chnum].slots[1], egk_drum); - } + channel_setup_alg(&dev->chan[chnum]); + env_key_off(dev->chan[chnum].slots[0], egk_drum); + env_key_off(dev->chan[chnum].slots[1], egk_drum); + } } } - static void channel_write_a0(chan_t *ch, uint8_t data) { if (ch->dev->newm && ch->chtype == ch_4op2) - return; + return; ch->f_num = (ch->f_num & 0x300) | data; - ch->ksv = (ch->block << 1) | ((ch->f_num >> (0x09 - ch->dev->nts)) & 0x01); + ch->ksv = (ch->block << 1) | ((ch->f_num >> (0x09 - ch->dev->nts)) & 0x01); env_update_ksl(ch->slots[0]); env_update_ksl(ch->slots[1]); if (ch->dev->newm && ch->chtype == ch_4op) { - ch->pair->f_num = ch->f_num; - ch->pair->ksv = ch->ksv; + ch->pair->f_num = ch->f_num; + ch->pair->ksv = ch->ksv; - env_update_ksl(ch->pair->slots[0]); - env_update_ksl(ch->pair->slots[1]); + env_update_ksl(ch->pair->slots[0]); + env_update_ksl(ch->pair->slots[1]); } } - static void channel_write_b0(chan_t *ch, uint8_t data) { if (ch->dev->newm && ch->chtype == ch_4op2) - return; + return; ch->f_num = (ch->f_num & 0xff) | ((data & 0x03) << 8); ch->block = (data >> 2) & 0x07; - ch->ksv = (ch->block << 1) | ((ch->f_num >> (0x09 - ch->dev->nts)) & 0x01); + ch->ksv = (ch->block << 1) | ((ch->f_num >> (0x09 - ch->dev->nts)) & 0x01); env_update_ksl(ch->slots[0]); env_update_ksl(ch->slots[1]); if (ch->dev->newm && ch->chtype == ch_4op) { - ch->pair->f_num = ch->f_num; - ch->pair->block = ch->block; - ch->pair->ksv = ch->ksv; + ch->pair->f_num = ch->f_num; + ch->pair->block = ch->block; + ch->pair->ksv = ch->ksv; - env_update_ksl(ch->pair->slots[0]); - env_update_ksl(ch->pair->slots[1]); + env_update_ksl(ch->pair->slots[0]); + env_update_ksl(ch->pair->slots[1]); } } - static void channel_write_c0(chan_t *ch, uint8_t data) { - ch->fb = (data & 0x0e) >> 1; + ch->fb = (data & 0x0e) >> 1; ch->con = data & 0x01; ch->alg = ch->con; if (ch->dev->newm) { - if (ch->chtype == ch_4op) { - ch->pair->alg = 0x04 | (ch->con << 1) | ch->pair->con; - ch->alg = 0x08; - channel_setup_alg(ch->pair); - } else if (ch->chtype == ch_4op2) { - ch->alg = 0x04 | (ch->pair->con << 1) | ch->con; - ch->pair->alg = 0x08; - channel_setup_alg(ch); - } else - channel_setup_alg(ch); + if (ch->chtype == ch_4op) { + ch->pair->alg = 0x04 | (ch->con << 1) | ch->pair->con; + ch->alg = 0x08; + channel_setup_alg(ch->pair); + } else if (ch->chtype == ch_4op2) { + ch->alg = 0x04 | (ch->pair->con << 1) | ch->con; + ch->pair->alg = 0x08; + channel_setup_alg(ch); + } else + channel_setup_alg(ch); } else - channel_setup_alg(ch); + channel_setup_alg(ch); if (ch->dev->newm) { - ch->cha = ((data >> 4) & 0x01) ? ~0 : 0; - ch->chb = ((data >> 5) & 0x01) ? ~0 : 0; + ch->cha = ((data >> 4) & 0x01) ? ~0 : 0; + ch->chb = ((data >> 5) & 0x01) ? ~0 : 0; } else - ch->cha = ch->chb = (uint16_t)~0; + ch->cha = ch->chb = (uint16_t) ~0; } - static void channel_key_on(chan_t *ch) { if (ch->dev->newm) { - if (ch->chtype == ch_4op) { - env_key_on(ch->slots[0], egk_norm); - env_key_on(ch->slots[1], egk_norm); - env_key_on(ch->pair->slots[0], egk_norm); - env_key_on(ch->pair->slots[1], egk_norm); - } else if (ch->chtype == ch_2op || ch->chtype == ch_drum) { - env_key_on(ch->slots[0], egk_norm); - env_key_on(ch->slots[1], egk_norm); - } + if (ch->chtype == ch_4op) { + env_key_on(ch->slots[0], egk_norm); + env_key_on(ch->slots[1], egk_norm); + env_key_on(ch->pair->slots[0], egk_norm); + env_key_on(ch->pair->slots[1], egk_norm); + } else if (ch->chtype == ch_2op || ch->chtype == ch_drum) { + env_key_on(ch->slots[0], egk_norm); + env_key_on(ch->slots[1], egk_norm); + } } else { - env_key_on(ch->slots[0], egk_norm); - env_key_on(ch->slots[1], egk_norm); + env_key_on(ch->slots[0], egk_norm); + env_key_on(ch->slots[1], egk_norm); } } - static void channel_key_off(chan_t *ch) { if (ch->dev->newm) { - if (ch->chtype == ch_4op) { - env_key_off(ch->slots[0], egk_norm); - env_key_off(ch->slots[1], egk_norm); - env_key_off(ch->pair->slots[0], egk_norm); - env_key_off(ch->pair->slots[1], egk_norm); - } else if (ch->chtype == ch_2op || ch->chtype == ch_drum) { - env_key_off(ch->slots[0], egk_norm); - env_key_off(ch->slots[1], egk_norm); - } + if (ch->chtype == ch_4op) { + env_key_off(ch->slots[0], egk_norm); + env_key_off(ch->slots[1], egk_norm); + env_key_off(ch->pair->slots[0], egk_norm); + env_key_off(ch->pair->slots[1], egk_norm); + } else if (ch->chtype == ch_2op || ch->chtype == ch_drum) { + env_key_off(ch->slots[0], egk_norm); + env_key_off(ch->slots[1], egk_norm); + } } else { - env_key_off(ch->slots[0], egk_norm); - env_key_off(ch->slots[1], egk_norm); + env_key_off(ch->slots[0], egk_norm); + env_key_off(ch->slots[1], egk_norm); } } - static void channel_set_4op(nuked_t *dev, uint8_t data) { uint8_t chnum; - uint8_t bit; - for (bit = 0; bit < 6; bit++) { - chnum = bit; + for (uint8_t bit = 0; bit < 6; bit++) { + chnum = bit; - if (bit >= 3) - chnum += 9 - 3; + if (bit >= 3) + chnum += 9 - 3; - if ((data >> bit) & 0x01) { - dev->chan[chnum].chtype = ch_4op; - dev->chan[chnum + 3].chtype = ch_4op2; - } else { - dev->chan[chnum].chtype = ch_2op; - dev->chan[chnum + 3].chtype = ch_2op; - } + if ((data >> bit) & 0x01) { + dev->chan[chnum].chtype = ch_4op; + dev->chan[chnum + 3].chtype = ch_4op2; + } else { + dev->chan[chnum].chtype = ch_2op; + dev->chan[chnum + 3].chtype = ch_2op; + } } } - uint16_t -nuked_write_addr(void *priv, uint16_t port, uint8_t val) +nuked_write_addr(void *priv, uint16_t port, uint8_t val) { - nuked_t *dev = (nuked_t *)priv; + const nuked_t *dev = (nuked_t *) priv; uint16_t addr; addr = val; if ((port & 0x0002) && ((addr == 0x0005) || dev->newm)) - addr |= 0x0100; + addr |= 0x0100; - return(addr); + return addr; } - void nuked_write_reg(void *priv, uint16_t reg, uint8_t val) { - nuked_t *dev = (nuked_t *)priv; - uint8_t high = (reg >> 8) & 0x01; - uint8_t regm = reg & 0xff; + nuked_t *dev = (nuked_t *) priv; + uint8_t high = (reg >> 8) & 0x01; + uint8_t regm = reg & 0xff; switch (regm & 0xf0) { - case 0x00: - if (high) switch (regm & 0x0f) { - case 0x04: - channel_set_4op(dev, val); - break; + case 0x00: + if (high) + switch (regm & 0x0f) { + case 0x04: + channel_set_4op(dev, val); + break; - case 0x05: - dev->newm = val & 0x01; - break; - } else switch (regm & 0x0f) { - case 0x08: - dev->nts = (val >> 6) & 0x01; - break; - } - break; + case 0x05: + dev->newm = val & 0x01; + break; - case 0x20: - case 0x30: - if (ad_slot[regm & 0x1f] >= 0) - slot_write_20(&dev->slot[18 * high + ad_slot[regm & 0x1f]], val); - break; + default: + break; + } + else + switch (regm & 0x0f) { + case 0x08: + dev->nts = (val >> 6) & 0x01; + break; - case 0x40: - case 0x50: - if (ad_slot[regm & 0x1f] >= 0) - slot_write_40(&dev->slot[18 * high + ad_slot[regm & 0x1f]], val); - break; + default: + break; + } + break; - case 0x60: - case 0x70: - if (ad_slot[regm & 0x1f] >= 0) - slot_write_60(&dev->slot[18 * high + ad_slot[regm & 0x1f]], val); - break; + case 0x20: + case 0x30: + if (ad_slot[regm & 0x1f] >= 0) + slot_write_20(&dev->slot[18 * high + ad_slot[regm & 0x1f]], val); + break; - case 0x80: - case 0x90: - if (ad_slot[regm & 0x1f] >= 0) - slot_write_80(&dev->slot[18 * high + ad_slot[regm & 0x1f]], val); - break; + case 0x40: + case 0x50: + if (ad_slot[regm & 0x1f] >= 0) + slot_write_40(&dev->slot[18 * high + ad_slot[regm & 0x1f]], val); + break; - case 0xa0: - if ((regm & 0x0f) < 9) - channel_write_a0(&dev->chan[9 * high + (regm & 0x0f)], val); - break; + case 0x60: + case 0x70: + if (ad_slot[regm & 0x1f] >= 0) + slot_write_60(&dev->slot[18 * high + ad_slot[regm & 0x1f]], val); + break; - case 0xb0: - if (regm == 0xbd && !high) { - dev->tremoloshift = (((val >> 7) ^ 1) << 1) + 2; - dev->vibshift = ((val >> 6) & 0x01) ^ 1; - channel_update_rhythm(dev, val); - } else if ((regm & 0x0f) < 9) { - channel_write_b0(&dev->chan[9 * high + (regm & 0x0f)], val); + case 0x80: + case 0x90: + if (ad_slot[regm & 0x1f] >= 0) + slot_write_80(&dev->slot[18 * high + ad_slot[regm & 0x1f]], val); + break; - if (val & 0x20) - channel_key_on(&dev->chan[9 * high + (regm & 0x0f)]); - else - channel_key_off(&dev->chan[9 * high + (regm & 0x0f)]); - } - break; + case 0xa0: + if ((regm & 0x0f) < 9) + channel_write_a0(&dev->chan[9 * high + (regm & 0x0f)], val); + break; - case 0xc0: - if ((regm & 0x0f) < 9) - channel_write_c0(&dev->chan[9 * high + (regm & 0x0f)], val); - break; + case 0xb0: + if (regm == 0xbd && !high) { + dev->tremoloshift = (((val >> 7) ^ 1) << 1) + 2; + dev->vibshift = ((val >> 6) & 0x01) ^ 1; + channel_update_rhythm(dev, val); + } else if ((regm & 0x0f) < 9) { + channel_write_b0(&dev->chan[9 * high + (regm & 0x0f)], val); - case 0xe0: - case 0xf0: - if (ad_slot[regm & 0x1f] >= 0) - slot_write_e0(&dev->slot[18 * high + ad_slot[regm & 0x1f]], val); - break; + if (val & 0x20) + channel_key_on(&dev->chan[9 * high + (regm & 0x0f)]); + else + channel_key_off(&dev->chan[9 * high + (regm & 0x0f)]); + } + break; + case 0xc0: + if ((regm & 0x0f) < 9) + channel_write_c0(&dev->chan[9 * high + (regm & 0x0f)], val); + break; + + case 0xe0: + case 0xf0: + if (ad_slot[regm & 0x1f] >= 0) + slot_write_e0(&dev->slot[18 * high + ad_slot[regm & 0x1f]], val); + break; + + default: + break; } } - void nuked_write_reg_buffered(void *priv, uint16_t reg, uint8_t val) { - nuked_t *dev = (nuked_t *)priv; - uint64_t time1, time2; + nuked_t *dev = (nuked_t *) priv; + uint64_t time1; + uint64_t time2; if (dev->wrbuf[dev->wrbuf_last].reg & 0x0200) { - nuked_write_reg(dev, dev->wrbuf[dev->wrbuf_last].reg & 0x01ff, - dev->wrbuf[dev->wrbuf_last].data); + nuked_write_reg(dev, dev->wrbuf[dev->wrbuf_last].reg & 0x01ff, + dev->wrbuf[dev->wrbuf_last].data); - dev->wrbuf_cur = (dev->wrbuf_last + 1) % WRBUF_SIZE; - dev->wrbuf_samplecnt = dev->wrbuf[dev->wrbuf_last].time; + dev->wrbuf_cur = (dev->wrbuf_last + 1) % WRBUF_SIZE; + dev->wrbuf_samplecnt = dev->wrbuf[dev->wrbuf_last].time; } - dev->wrbuf[dev->wrbuf_last].reg = reg | 0x0200; + dev->wrbuf[dev->wrbuf_last].reg = reg | 0x0200; dev->wrbuf[dev->wrbuf_last].data = val; - time1 = dev->wrbuf_lasttime + WRBUF_DELAY; - time2 = dev->wrbuf_samplecnt; + time1 = dev->wrbuf_lasttime + WRBUF_DELAY; + time2 = dev->wrbuf_samplecnt; if (time1 < time2) - time1 = time2; + time1 = time2; dev->wrbuf[dev->wrbuf_last].time = time1; - dev->wrbuf_lasttime = time1; - dev->wrbuf_last = (dev->wrbuf_last + 1) % WRBUF_SIZE; + dev->wrbuf_lasttime = time1; + dev->wrbuf_last = (dev->wrbuf_last + 1) % WRBUF_SIZE; } - void nuked_generate(void *priv, int32_t *bufp) { - nuked_t *dev = (nuked_t *)priv; - int16_t accm, shift = 0; - uint8_t i, j; + nuked_t *dev = (nuked_t *) priv; + int16_t accm; + int16_t shift = 0; + uint8_t i; + uint8_t j; bufp[1] = dev->mixbuff[1]; for (i = 0; i < 15; i++) { - slot_calc_fb(&dev->slot[i]); - env_calc(&dev->slot[i]); - phase_generate(&dev->slot[i]); - slot_generate(&dev->slot[i]); + slot_calc_fb(&dev->slot[i]); + env_calc(&dev->slot[i]); + phase_generate(&dev->slot[i]); + slot_generate(&dev->slot[i]); } dev->mixbuff[0] = 0; for (i = 0; i < 18; i++) { - accm = 0; + accm = 0; - for (j = 0; j < 4; j++) - accm += *dev->chan[i].out[j]; + for (j = 0; j < 4; j++) + accm += *dev->chan[i].out[j]; - dev->mixbuff[0] += (int16_t)(accm & dev->chan[i].cha); + dev->mixbuff[0] += (int16_t) (accm & dev->chan[i].cha); } for (i = 15; i < 18; i++) { - slot_calc_fb(&dev->slot[i]); - env_calc(&dev->slot[i]); - phase_generate(&dev->slot[i]); - slot_generate(&dev->slot[i]); + slot_calc_fb(&dev->slot[i]); + env_calc(&dev->slot[i]); + phase_generate(&dev->slot[i]); + slot_generate(&dev->slot[i]); } bufp[0] = dev->mixbuff[0]; for (i = 18; i < 33; i++) { - slot_calc_fb(&dev->slot[i]); - env_calc(&dev->slot[i]); - phase_generate(&dev->slot[i]); - slot_generate(&dev->slot[i]); + slot_calc_fb(&dev->slot[i]); + env_calc(&dev->slot[i]); + phase_generate(&dev->slot[i]); + slot_generate(&dev->slot[i]); } dev->mixbuff[1] = 0; for (i = 0; i < 18; i++) { - accm = 0; + accm = 0; - for (j = 0; j < 4; j++) - accm += *dev->chan[i].out[j]; + for (j = 0; j < 4; j++) + accm += *dev->chan[i].out[j]; - dev->mixbuff[1] += (int16_t)(accm & dev->chan[i].chb); + dev->mixbuff[1] += (int16_t) (accm & dev->chan[i].chb); } for (i = 33; i < 36; i++) { - slot_calc_fb(&dev->slot[i]); - env_calc(&dev->slot[i]); - phase_generate(&dev->slot[i]); - slot_generate(&dev->slot[i]); + slot_calc_fb(&dev->slot[i]); + env_calc(&dev->slot[i]); + phase_generate(&dev->slot[i]); + slot_generate(&dev->slot[i]); } if ((dev->timer & 0x3f) == 0x3f) - dev->tremolopos = (dev->tremolopos + 1) % 210; + dev->tremolopos = (dev->tremolopos + 1) % 210; if (dev->tremolopos < 105) - dev->tremolo = dev->tremolopos >> dev->tremoloshift; + dev->tremolo = dev->tremolopos >> dev->tremoloshift; else - dev->tremolo = (210 - dev->tremolopos) >> dev->tremoloshift; + dev->tremolo = (210 - dev->tremolopos) >> dev->tremoloshift; if ((dev->timer & 0x03ff) == 0x03ff) - dev->vibpos = (dev->vibpos + 1) & 7; + dev->vibpos = (dev->vibpos + 1) & 7; dev->timer++; dev->eg_add = 0; if (dev->eg_timer) { - while (shift < 36 && ((dev->eg_timer >> shift) & 1) == 0) - shift++; + while (shift < 36 && ((dev->eg_timer >> shift) & 1) == 0) + shift++; - if (shift > 12) - dev->eg_add = 0; - else - dev->eg_add = shift + 1; + if (shift > 12) + dev->eg_add = 0; + else + dev->eg_add = shift + 1; } if (dev->eg_timerrem || dev->eg_state) { - if (dev->eg_timer == 0xfffffffff) { - dev->eg_timer = 0; - dev->eg_timerrem = 1; - } else { - dev->eg_timer++; - dev->eg_timerrem = 0; - } + if (dev->eg_timer == 0xfffffffff) { + dev->eg_timer = 0; + dev->eg_timerrem = 1; + } else { + dev->eg_timer++; + dev->eg_timerrem = 0; + } } dev->eg_state ^= 1; while (dev->wrbuf[dev->wrbuf_cur].time <= dev->wrbuf_samplecnt) { - if (! (dev->wrbuf[dev->wrbuf_cur].reg & 0x200)) - break; + if (!(dev->wrbuf[dev->wrbuf_cur].reg & 0x200)) + break; - dev->wrbuf[dev->wrbuf_cur].reg &= 0x01ff; + dev->wrbuf[dev->wrbuf_cur].reg &= 0x01ff; - nuked_write_reg(dev, dev->wrbuf[dev->wrbuf_cur].reg, - dev->wrbuf[dev->wrbuf_cur].data); + nuked_write_reg(dev, dev->wrbuf[dev->wrbuf_cur].reg, + dev->wrbuf[dev->wrbuf_cur].data); - dev->wrbuf_cur = (dev->wrbuf_cur + 1) % WRBUF_SIZE; + dev->wrbuf_cur = (dev->wrbuf_cur + 1) % WRBUF_SIZE; } dev->wrbuf_samplecnt++; } - void -nuked_generate_resampled(void *priv, int32_t *bufp) +nuked_generate_resampled(nuked_t *dev, int32_t *bufp) { - nuked_t *dev = (nuked_t *)priv; - while (dev->samplecnt >= dev->rateratio) { - dev->oldsamples[0] = dev->samples[0]; - dev->oldsamples[1] = dev->samples[1]; - nuked_generate(dev, dev->samples); - dev->samplecnt -= dev->rateratio; + dev->oldsamples[0] = dev->samples[0]; + dev->oldsamples[1] = dev->samples[1]; + nuked_generate(dev, dev->samples); + dev->samplecnt -= dev->rateratio; } - bufp[0] = (int32_t)((dev->oldsamples[0] * (dev->rateratio - dev->samplecnt) - + dev->samples[0] * dev->samplecnt) / dev->rateratio); - bufp[1] = (int32_t)((dev->oldsamples[1] * (dev->rateratio - dev->samplecnt) - + dev->samples[1] * dev->samplecnt) / dev->rateratio); + bufp[0] = (int32_t) ((dev->oldsamples[0] * (dev->rateratio - dev->samplecnt) + + dev->samples[0] * dev->samplecnt) + / dev->rateratio); + bufp[1] = (int32_t) ((dev->oldsamples[1] * (dev->rateratio - dev->samplecnt) + + dev->samples[1] * dev->samplecnt) + / dev->rateratio); dev->samplecnt += 1 << RSM_FRAC; } - void -nuked_generate_stream(void *priv, int32_t *sndptr, uint32_t num) +nuked_generate_stream(nuked_t *dev, int32_t *sndptr, uint32_t num) { - nuked_t *dev = (nuked_t *)priv; - uint32_t i; - - for (i = 0; i < num; i++) { - nuked_generate_resampled(dev, sndptr); - sndptr += 2; + for (uint32_t i = 0; i < num; i++) { + nuked_generate_resampled(dev, sndptr); + sndptr += 2; } } - -void * -nuked_init(uint32_t samplerate) +void +nuked_init(nuked_t *dev, uint32_t samplerate) { - nuked_t *dev; uint8_t i; - dev = (nuked_t *)malloc(sizeof(nuked_t)); memset(dev, 0x00, sizeof(nuked_t)); for (i = 0; i < 36; i++) { - dev->slot[i].dev = dev; - dev->slot[i].mod = &dev->zeromod; - dev->slot[i].eg_rout = 0x01ff; - dev->slot[i].eg_out = 0x01ff; - dev->slot[i].eg_gen = envelope_gen_num_release; - dev->slot[i].trem = (uint8_t*)&dev->zeromod; - dev->slot[i].slot_num = i; + dev->slot[i].dev = dev; + dev->slot[i].mod = &dev->zeromod; + dev->slot[i].eg_rout = 0x01ff; + dev->slot[i].eg_out = 0x01ff; + dev->slot[i].eg_gen = envelope_gen_num_release; + dev->slot[i].trem = (uint8_t *) &dev->zeromod; + dev->slot[i].slot_num = i; } for (i = 0; i < 18; i++) { - dev->chan[i].slots[0] = &dev->slot[ch_slot[i]]; - dev->chan[i].slots[1] = &dev->slot[ch_slot[i] + 3]; - dev->slot[ch_slot[i]].chan = &dev->chan[i]; - dev->slot[ch_slot[i] + 3].chan = &dev->chan[i]; + dev->chan[i].slots[0] = &dev->slot[ch_slot[i]]; + dev->chan[i].slots[1] = &dev->slot[ch_slot[i] + 3]; + dev->slot[ch_slot[i]].chan = &dev->chan[i]; + dev->slot[ch_slot[i] + 3].chan = &dev->chan[i]; - if ((i % 9) < 3) - dev->chan[i].pair = &dev->chan[i + 3]; - else if ((i % 9) < 6) - dev->chan[i].pair = &dev->chan[i - 3]; + if ((i % 9) < 3) + dev->chan[i].pair = &dev->chan[i + 3]; + else if ((i % 9) < 6) + dev->chan[i].pair = &dev->chan[i - 3]; - dev->chan[i].dev = dev; - dev->chan[i].out[0] = &dev->zeromod; - dev->chan[i].out[1] = &dev->zeromod; - dev->chan[i].out[2] = &dev->zeromod; - dev->chan[i].out[3] = &dev->zeromod; - dev->chan[i].chtype = ch_2op; - dev->chan[i].cha = 0xffff; - dev->chan[i].chb = 0xffff; - dev->chan[i].ch_num = i; + dev->chan[i].dev = dev; + dev->chan[i].out[0] = &dev->zeromod; + dev->chan[i].out[1] = &dev->zeromod; + dev->chan[i].out[2] = &dev->zeromod; + dev->chan[i].out[3] = &dev->zeromod; + dev->chan[i].chtype = ch_2op; + dev->chan[i].cha = 0xffff; + dev->chan[i].chb = 0xffff; + dev->chan[i].ch_num = i; - channel_setup_alg(&dev->chan[i]); + channel_setup_alg(&dev->chan[i]); } - dev->noise = 1; - dev->rateratio = (samplerate << RSM_FRAC) / 49716; + dev->noise = 1; + dev->rateratio = (samplerate << RSM_FRAC) / 49716; dev->tremoloshift = 4; - dev->vibshift = 1; - - return(dev); + dev->vibshift = 1; } - -void -nuked_close(void *priv) +static void +nuked_timer_tick(nuked_drv_t *dev, int tmr) { - nuked_t *dev = (nuked_t *)priv; + dev->timer_cur_count[tmr] = (dev->timer_cur_count[tmr] + 1) & 0xff; + nuked_log("Ticking timer %i, count now %02X...\n", tmr, dev->timer_cur_count[tmr]); + + if (dev->timer_cur_count[tmr] == 0x00) { + dev->status |= ((STAT_TMR1_OVER >> tmr) & ~dev->timer_ctrl); + dev->timer_cur_count[tmr] = dev->timer_count[tmr]; + + nuked_log("Count wrapped around to zero, reloading timer %i (%02X), status = %02X...\n", tmr, (STAT_TMR1_OVER >> tmr), dev->status); + } + + timer_on_auto(&dev->timers[tmr], (tmr == 1) ? 320.0 : 80.0); +} + +static void +nuked_timer_control(nuked_drv_t *dev, int tmr, int start) +{ + timer_on_auto(&dev->timers[tmr], 0.0); + + if (start) { + nuked_log("Loading timer %i count: %02X = %02X\n", tmr, dev->timer_cur_count[tmr], dev->timer_count[tmr]); + dev->timer_cur_count[tmr] = dev->timer_count[tmr]; + if (dev->flags & FLAG_OPL3) + nuked_timer_tick(dev, tmr); /* Per the YMF 262 datasheet, OPL3 starts counting immediately, unlike OPL2. */ + else + timer_on_auto(&dev->timers[tmr], (tmr == 1) ? 320.0 : 80.0); + } else { + nuked_log("Timer %i stopped\n", tmr); + if (tmr == 1) { + dev->status &= ~STAT_TMR2_OVER; + } else + dev->status &= ~STAT_TMR1_OVER; + } +} + +static void +nuked_timer_1(void *priv) +{ + nuked_drv_t *dev = (nuked_drv_t *) priv; + + nuked_timer_tick(dev, 0); +} + +static void +nuked_timer_2(void *priv) +{ + nuked_drv_t *dev = (nuked_drv_t *) priv; + + nuked_timer_tick(dev, 1); +} + +static void +nuked_drv_set_do_cycles(void *priv, int8_t do_cycles) +{ + nuked_drv_t *dev = (nuked_drv_t *) priv; + + if (do_cycles) + dev->flags |= FLAG_CYCLES; + else + dev->flags &= ~FLAG_CYCLES; +} + +static void * +nuked_drv_init(const device_t *info) +{ + nuked_drv_t *dev = (nuked_drv_t *) calloc(1, sizeof(nuked_drv_t)); + dev->flags = FLAG_CYCLES; + if (info->local == FM_YMF262) + dev->flags |= FLAG_OPL3; + else + dev->status = 0x06; + + /* Initialize the NukedOPL object. */ + nuked_init(&dev->opl, OPL_FREQ); + + timer_add(&dev->timers[0], nuked_timer_1, dev, 0); + timer_add(&dev->timers[1], nuked_timer_2, dev, 0); + + return dev; +} + +static void +nuked_drv_close(void *priv) +{ + nuked_drv_t *dev = (nuked_drv_t *) priv; free(dev); } + +static int32_t * +nuked_drv_update(void *priv) +{ + nuked_drv_t *dev = (nuked_drv_t *) priv; + + if (dev->pos >= sound_pos_global) + return dev->buffer; + + nuked_generate_stream(&dev->opl, + &dev->buffer[dev->pos * 2], + sound_pos_global - dev->pos); + + for (; dev->pos < sound_pos_global; dev->pos++) { + dev->buffer[dev->pos * 2] /= 2; + dev->buffer[(dev->pos * 2) + 1] /= 2; + } + + return dev->buffer; +} + +static uint8_t +nuked_drv_read(uint16_t port, void *priv) +{ + nuked_drv_t *dev = (nuked_drv_t *) priv; + + if (dev->flags & FLAG_CYCLES) + cycles -= ((int) (isa_timing * 8)); + + nuked_drv_update(dev); + + uint8_t ret = 0xff; + + if ((port & 0x0003) == 0x0000) { + ret = dev->status; + if (dev->status & STAT_TMR_OVER) + ret |= STAT_TMR_ANY; + } + + nuked_log("OPL statret = %02x, status = %02x\n", ret, dev->status); + + return ret; +} + +static void +nuked_drv_write(uint16_t port, uint8_t val, void *priv) +{ + nuked_drv_t *dev = (nuked_drv_t *) priv; + nuked_drv_update(dev); + + if ((port & 0x0001) == 0x0001) { + nuked_write_reg_buffered(&dev->opl, dev->port, val); + + switch (dev->port) { + case 0x02: /* Timer 1 */ + dev->timer_count[0] = val; + nuked_log("Timer 0 count now: %i\n", dev->timer_count[0]); + break; + + case 0x03: /* Timer 2 */ + dev->timer_count[1] = val; + nuked_log("Timer 1 count now: %i\n", dev->timer_count[1]); + break; + + case 0x04: /* Timer control */ + if (val & CTRL_RESET) { + nuked_log("Resetting timer status...\n"); + dev->status &= ~STAT_TMR_OVER; + } else { + dev->timer_ctrl = val; + nuked_timer_control(dev, 0, val & CTRL_TMR1_START); + nuked_timer_control(dev, 1, val & CTRL_TMR2_START); + nuked_log("Status mask now %02X (val = %02X)\n", (val & ~CTRL_TMR_MASK) & CTRL_TMR_MASK, val); + } + break; + + default: + break; + } + } else { + dev->port = nuked_write_addr(&dev->opl, port, val) & 0x01ff; + + if (!(dev->flags & FLAG_OPL3)) + dev->port &= 0x00ff; + } +} + +static void +nuked_drv_reset_buffer(void *priv) +{ + nuked_drv_t *dev = (nuked_drv_t *) priv; + + dev->pos = 0; +} + +const device_t ym3812_nuked_device = { + .name = "Yamaha YM3812 OPL2 (NUKED)", + .internal_name = "ym3812_nuked", + .flags = 0, + .local = FM_YM3812, + .init = nuked_drv_init, + .close = nuked_drv_close, + .reset = NULL, + { .available = NULL }, + .speed_changed = NULL, + .force_redraw = NULL, + .config = NULL +}; + +const device_t ymf262_nuked_device = { + .name = "Yamaha YMF262 OPL3 (NUKED)", + .internal_name = "ymf262_nuked", + .flags = 0, + .local = FM_YMF262, + .init = nuked_drv_init, + .close = nuked_drv_close, + .reset = NULL, + { .available = NULL }, + .speed_changed = NULL, + .force_redraw = NULL, + .config = NULL +}; + +const fm_drv_t nuked_opl_drv = { + &nuked_drv_read, + &nuked_drv_write, + &nuked_drv_update, + &nuked_drv_reset_buffer, + &nuked_drv_set_do_cycles, + NULL, +}; \ No newline at end of file diff --git a/src/sound/snd_opl_ymfm.cpp b/src/sound/snd_opl_ymfm.cpp new file mode 100644 index 000000000..a8867e6ed --- /dev/null +++ b/src/sound/snd_opl_ymfm.cpp @@ -0,0 +1,473 @@ +/* + * 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. + * + * Interface to the YMFM emulator. + * + * + * Authors: Adrien Moulin, + * + * Copyright 2022 Adrien Moulin. + */ +#include +#include +#include +#include +#include +#include "ymfm/ymfm_opl.h" + +extern "C" { +#define HAVE_STDARG_H +#include <86box/86box.h> +#include <86box/timer.h> +#include <86box/device.h> +#include <86box/sound.h> +#include <86box/snd_opl.h> +#include <86box/mem.h> +#include <86box/rom.h> +#include <86box/plat_unused.h> + +// Disable c99-designator to avoid the warnings in *_ymfm_device +#ifdef __clang__ +# if __has_warning("-Wc99-designator") +# pragma clang diagnostic push +# pragma clang diagnostic ignored "-Wc99-designator" +# endif +#endif + +} + +#define RSM_FRAC 10 + +#define OPL_FREQ FREQ_48000 + +enum { + FLAG_CYCLES = (1 << 0) +}; + +class YMFMChipBase { +public: + YMFMChipBase(UNUSED(uint32_t clock), fm_type type, UNUSED(uint32_t samplerate)) + : m_buf_pos(0) + , m_flags(0) + , m_type(type) + { + memset(m_buffer, 0, sizeof(m_buffer)); + } + + virtual ~YMFMChipBase() + { + } + + fm_type type() const { return m_type; } + int8_t flags() const { return m_flags; } + void set_do_cycles(int8_t do_cycles) { do_cycles ? m_flags |= FLAG_CYCLES : m_flags &= ~FLAG_CYCLES; } + int32_t *buffer() const { return (int32_t *) m_buffer; } + void reset_buffer() { m_buf_pos = 0; } + + virtual uint32_t sample_rate() const = 0; + + virtual void write(uint16_t addr, uint8_t data) = 0; + virtual void generate(int32_t *data, uint32_t num_samples) = 0; + virtual void generate_resampled(int32_t *data, uint32_t num_samples) = 0; + virtual int32_t *update() = 0; + virtual uint8_t read(uint16_t addr) = 0; + virtual void set_clock(uint32_t clock) = 0; + +protected: + int32_t m_buffer[SOUNDBUFLEN * 2]; + int m_buf_pos; + int8_t m_flags; + fm_type m_type; +}; + +template +class YMFMChip : public YMFMChipBase, public ymfm::ymfm_interface { +public: + YMFMChip(uint32_t clock, fm_type type, uint32_t samplerate) + : YMFMChipBase(clock, type, samplerate) + , m_chip(*this) + , m_clock(clock) + , m_samplerate(samplerate) + , m_samplecnt(0) + { + memset(m_samples, 0, sizeof(m_samples)); + memset(m_oldsamples, 0, sizeof(m_oldsamples)); + m_rateratio = (samplerate << RSM_FRAC) / m_chip.sample_rate(m_clock); + m_clock_us = 1000000.0 / (double) m_clock; + m_subtract[0] = 80.0; + m_subtract[1] = 320.0; + m_type = type; + + if (m_type == FM_YMF278B) { + if (rom_load_linear("roms/sound/yamaha/yrw801.rom", 0, 0x200000, 0, m_yrw801) == 0) { + fatal("YRW801 ROM image \"roms/sound/yamaha/yrw801.rom\" not found\n"); + } + } + + timer_add(&m_timers[0], YMFMChip::timer1, this, 0); + timer_add(&m_timers[1], YMFMChip::timer2, this, 0); + } + + virtual uint32_t sample_rate() const override + { + return m_chip.sample_rate(m_clock); + } + + virtual void ymfm_set_timer(uint32_t tnum, int32_t duration_in_clocks) override + { + if (tnum > 1) + return; + + m_duration_in_clocks[tnum] = duration_in_clocks; + pc_timer_t *timer = &m_timers[tnum]; + if (duration_in_clocks < 0) + timer_stop(timer); + else { + double period = m_clock_us * duration_in_clocks; + if (period < m_subtract[tnum]) + m_engine->engine_timer_expired(tnum); + else + timer_on_auto(timer, period); + } + } + + virtual void set_clock(uint32_t clock) override + { + m_clock = clock; + m_clock_us = 1000000.0 / (double) m_clock; + m_rateratio = (m_samplerate << RSM_FRAC) / m_chip.sample_rate(m_clock); + + ymfm_set_timer(0, m_duration_in_clocks[0]); + ymfm_set_timer(1, m_duration_in_clocks[1]); + } + + virtual void generate(int32_t *data, uint32_t num_samples) override + { + for (uint32_t i = 0; i < num_samples; i++) { + m_chip.generate(&m_output); + if ((m_type == FM_YMF278B) && (sizeof(m_output.data) > (4 * sizeof(int32_t)))) { + if (ChipType::OUTPUTS == 1) { + *data++ = m_output.data[4]; + *data++ = m_output.data[4]; + } else { + *data++ = m_output.data[4]; + *data++ = m_output.data[5]; + } + } else if (ChipType::OUTPUTS == 1) { + *data++ = m_output.data[0]; + *data++ = m_output.data[0]; + } else { + *data++ = m_output.data[0]; + *data++ = m_output.data[1 % ChipType::OUTPUTS]; + } + } + } + + virtual void generate_resampled(int32_t *data, uint32_t num_samples) override + { + for (uint32_t i = 0; i < num_samples; i++) { + while (m_samplecnt >= m_rateratio) { + m_oldsamples[0] = m_samples[0]; + m_oldsamples[1] = m_samples[1]; + m_chip.generate(&m_output); + if ((m_type == FM_YMF278B) && (sizeof(m_output.data) > (4 * sizeof(int32_t)))) { + if (ChipType::OUTPUTS == 1) { + m_samples[0] = m_output.data[4]; + m_samples[1] = m_output.data[4]; + } else { + m_samples[0] = m_output.data[4]; + m_samples[1] = m_output.data[5]; + } + } else if (ChipType::OUTPUTS == 1) { + m_samples[0] = m_output.data[0]; + m_samples[1] = m_output.data[0]; + } else { + m_samples[0] = m_output.data[0]; + m_samples[1] = m_output.data[1 % ChipType::OUTPUTS]; + } + m_samplecnt -= m_rateratio; + } + + *data++ = ((int32_t) ((m_oldsamples[0] * (m_rateratio - m_samplecnt) + + m_samples[0] * m_samplecnt) + / m_rateratio)); + *data++ = ((int32_t) ((m_oldsamples[1] * (m_rateratio - m_samplecnt) + + m_samples[1] * m_samplecnt) + / m_rateratio)); + + m_samplecnt += 1 << RSM_FRAC; + } + } + + virtual int32_t *update() override + { + if (m_buf_pos >= sound_pos_global) + return m_buffer; + + generate_resampled(&m_buffer[m_buf_pos * 2], sound_pos_global - m_buf_pos); + + for (; m_buf_pos < sound_pos_global; m_buf_pos++) { + m_buffer[m_buf_pos * 2] /= 2; + m_buffer[(m_buf_pos * 2) + 1] /= 2; + } + + return m_buffer; + } + + virtual void write(uint16_t addr, uint8_t data) override + { + m_chip.write(addr, data); + } + + virtual uint8_t read(uint16_t addr) override + { + return m_chip.read(addr); + } + + virtual uint32_t get_special_flags(void) override + { + return ((m_type == FM_YMF262) || (m_type == FM_YMF289B) || (m_type == FM_YMF278B)) ? 0x8000 : 0x0000; + } + + static void timer1(void *priv) + { + YMFMChip *drv = (YMFMChip *) priv; + drv->m_engine->engine_timer_expired(0); + } + + static void timer2(void *priv) + { + YMFMChip *drv = (YMFMChip *) priv; + drv->m_engine->engine_timer_expired(1); + } + + virtual uint8_t ymfm_external_read(ymfm::access_class type, uint32_t address) override + { + if (type == ymfm::access_class::ACCESS_PCM && address < 0x200000) { + return m_yrw801[address]; + } + return 0xFF; + } + +private: + ChipType m_chip; + uint32_t m_clock; + double m_clock_us; + double m_subtract[2]; + typename ChipType::output_data m_output; + pc_timer_t m_timers[2]; + int32_t m_duration_in_clocks[2]; // Needed for clock switches. + uint32_t m_samplerate; + + // YRW801-M wavetable ROM. + uint8_t m_yrw801[0x200000]; + + // Resampling + int32_t m_rateratio; + int32_t m_samplecnt; + int32_t m_oldsamples[2]; + int32_t m_samples[2]; +}; + +extern "C" { +#include +#include +#include +#include +#include +#include +#define HAVE_STDARG_H + +#include "cpu.h" +#include <86box/86box.h> +#include <86box/io.h> +#include <86box/snd_opl.h> + +#ifdef ENABLE_OPL_LOG +int ymfm_do_log = ENABLE_OPL_LOG; + +static void +ymfm_log(const char *fmt, ...) +{ + va_list ap; + + if (ymfm_do_log) { + va_start(ap, fmt); + pclog_ex(fmt, ap); + va_end(ap); + } +} +#else +# define ymfm_log(fmt, ...) +#endif + +static void * +ymfm_drv_init(const device_t *info) +{ + YMFMChipBase *fm; + + switch (info->local) { + default: + case FM_YM3812: + fm = (YMFMChipBase *) new YMFMChip(3579545, FM_YM3812, OPL_FREQ); + break; + + case FM_YMF262: + fm = (YMFMChipBase *) new YMFMChip(14318181, FM_YMF262, OPL_FREQ); + break; + + case FM_YMF289B: + /* According to the datasheet, we should be using 33868800, but YMFM appears + to cheat and does it using the same values as the YMF262. */ + fm = (YMFMChipBase *) new YMFMChip(14318181, FM_YMF289B, OPL_FREQ); + break; + + case FM_YMF278B: + fm = (YMFMChipBase *) new YMFMChip(33868800, FM_YMF278B, OPL_FREQ); + break; + } + + fm->set_do_cycles(1); + + return fm; +} + +static void +ymfm_drv_close(void *priv) +{ + YMFMChipBase *drv = (YMFMChipBase *) priv; + + if (drv != NULL) + delete drv; +} + +static uint8_t +ymfm_drv_read(uint16_t port, void *priv) +{ + YMFMChipBase *drv = (YMFMChipBase *) priv; + + if ((port == 0x380) || (port == 0x381)) + port |= 4; + + /* Point to register read port. */ + if (drv->flags() & FLAG_CYCLES) + cycles -= ((int) (isa_timing * 8)); + + uint8_t ret = drv->read(port); + drv->update(); + + ymfm_log("YMFM read port %04x, status = %02x\n", port, ret); + return ret; +} + +static void +ymfm_drv_write(uint16_t port, uint8_t val, void *priv) +{ + YMFMChipBase *drv = (YMFMChipBase *) priv; + ymfm_log("YMFM write port %04x value = %02x\n", port, val); + if ((port == 0x380) || (port == 0x381)) + port |= 4; + drv->write(port, val); + drv->update(); +} + +static int32_t * +ymfm_drv_update(void *priv) +{ + YMFMChipBase *drv = (YMFMChipBase *) priv; + + return drv->update(); +} + +static void +ymfm_drv_reset_buffer(void *priv) +{ + YMFMChipBase *drv = (YMFMChipBase *) priv; + + drv->reset_buffer(); +} + +static void +ymfm_drv_set_do_cycles(void *priv, int8_t do_cycles) +{ + YMFMChipBase *drv = (YMFMChipBase *) priv; + drv->set_do_cycles(do_cycles); +} + +const device_t ym3812_ymfm_device = { + .name = "Yamaha YM3812 OPL2 (YMFM)", + .internal_name = "ym3812_ymfm", + .flags = 0, + .local = FM_YM3812, + .init = ymfm_drv_init, + .close = ymfm_drv_close, + .reset = NULL, + { .available = NULL }, + .speed_changed = NULL, + .force_redraw = NULL, + .config = NULL +}; + +const device_t ymf262_ymfm_device = { + .name = "Yamaha YMF262 OPL3 (YMFM)", + .internal_name = "ymf262_ymfm", + .flags = 0, + .local = FM_YMF262, + .init = ymfm_drv_init, + .close = ymfm_drv_close, + .reset = NULL, + { .available = NULL }, + .speed_changed = NULL, + .force_redraw = NULL, + .config = NULL +}; + +const device_t ymf289b_ymfm_device = { + .name = "Yamaha YMF289B OPL3-L (YMFM)", + .internal_name = "ymf289b_ymfm", + .flags = 0, + .local = FM_YMF289B, + .init = ymfm_drv_init, + .close = ymfm_drv_close, + .reset = NULL, + { .available = NULL }, + .speed_changed = NULL, + .force_redraw = NULL, + .config = NULL +}; + +const device_t ymf278b_ymfm_device = { + .name = "Yamaha YMF278B OPL4 (YMFM)", + .internal_name = "ymf278b_ymfm", + .flags = 0, + .local = FM_YMF278B, + .init = ymfm_drv_init, + .close = ymfm_drv_close, + .reset = NULL, + { .available = NULL }, + .speed_changed = NULL, + .force_redraw = NULL, + .config = NULL +}; + +const fm_drv_t ymfm_drv { + &ymfm_drv_read, + &ymfm_drv_write, + &ymfm_drv_update, + &ymfm_drv_reset_buffer, + &ymfm_drv_set_do_cycles, + NULL, +}; + +#ifdef __clang__ +# if __has_warning("-Wc99-designator") +# pragma clang diagnostic pop +# endif +#endif + +} diff --git a/src/sound/snd_optimc.c b/src/sound/snd_optimc.c new file mode 100644 index 000000000..d7afca382 --- /dev/null +++ b/src/sound/snd_optimc.c @@ -0,0 +1,497 @@ +/* + * 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. + * + * OPTi MediaCHIPS 82C929A (also known as OPTi MAD16 Pro) audio controller emulation. + * + * + * + * Authors: Cacodemon345 + * Eluan Costa Miranda + * + * Copyright 2022 Cacodemon345. + * Copyright 2020 Eluan Costa Miranda. + */ + +#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/midi.h> +#include <86box/timer.h> +#include <86box/pic.h> +#include <86box/sound.h> +#include <86box/gameport.h> +#include <86box/snd_ad1848.h> +#include <86box/snd_sb.h> +#include <86box/mem.h> +#include <86box/rom.h> +#include <86box/plat_unused.h> + +static int optimc_wss_dma[4] = { 0, 0, 1, 3 }; +static int optimc_wss_irq[8] = { 5, 7, 9, 10, 11, 12, 14, 15 }; + +enum optimc_local_flags { + OPTIMC_CS4231 = 0x100, + OPTIMC_OPL4 = 0x200, +}; + +typedef struct optimc_t { + uint8_t type; + uint8_t fm_type; + + uint8_t wss_config; + uint8_t reg_enabled; + + uint16_t cur_addr; + uint16_t cur_wss_addr; + uint16_t cur_mpu401_addr; + + int cur_irq; + int cur_dma; + int cur_wss_enabled; + int cur_wss_irq; + int cur_wss_dma; + int cur_mpu401_irq; + int cur_mpu401_enabled; + void *gameport; + + uint8_t cur_mode; + + ad1848_t ad1848; + mpu_t *mpu; + + sb_t *sb; + uint8_t regs[6]; +} optimc_t, opti_82c929a_t; + +static void +optimc_filter_opl(void *priv, double *out_l, double *out_r) +{ + optimc_t *optimc = (optimc_t *) priv; + + if (optimc->cur_wss_enabled) { + *out_l /= optimc->sb->mixer_sbpro.fm_l; + *out_r /= optimc->sb->mixer_sbpro.fm_r; + ad1848_filter_aux2((void *) &optimc->ad1848, out_l, out_r); + } +} + +static uint8_t +optimc_wss_read(UNUSED(uint16_t addr), void *priv) +{ + const optimc_t *optimc = (optimc_t *) priv; + + if (!(optimc->regs[4] & 0x10) && optimc->cur_mode == 0) + return 0xFF; + + return 4 | (optimc->wss_config & 0x40); +} + +static void +optimc_wss_write(UNUSED(uint16_t addr), uint8_t val, void *priv) +{ + optimc_t *optimc = (optimc_t *) priv; + + if (!(optimc->regs[4] & 0x10) && optimc->cur_mode == 0) + return; + optimc->wss_config = val; + ad1848_setdma(&optimc->ad1848, optimc_wss_dma[val & 3]); + ad1848_setirq(&optimc->ad1848, optimc_wss_irq[(val >> 3) & 7]); +} + +static void +optimc_get_buffer(int32_t *buffer, int len, void *priv) +{ + optimc_t *optimc = (optimc_t *) priv; + + if (optimc->regs[3] & 0x4) + return; + + /* wss part */ + ad1848_update(&optimc->ad1848); + for (int c = 0; c < len * 2; c++) + buffer[c] += (optimc->ad1848.buffer[c] / 2); + + optimc->ad1848.pos = 0; + + /* sbprov2 part */ + sb_get_buffer_sbpro(buffer, len, optimc->sb); +} + +static void +optimc_remove_opl(optimc_t *optimc) +{ + io_removehandler(optimc->cur_addr + 0, 0x0004, optimc->sb->opl.read, NULL, NULL, optimc->sb->opl.write, NULL, NULL, optimc->sb->opl.priv); + io_removehandler(optimc->cur_addr + 8, 0x0002, optimc->sb->opl.read, NULL, NULL, optimc->sb->opl.write, NULL, NULL, optimc->sb->opl.priv); + io_removehandler(0x0388, 0x0004, optimc->sb->opl.read, NULL, NULL, optimc->sb->opl.write, NULL, NULL, optimc->sb->opl.priv); +} + +static void +optimc_add_opl(optimc_t *optimc) +{ + /* DSP I/O handler is activated in sb_dsp_setaddr */ + io_sethandler(optimc->cur_addr + 0, 0x0004, optimc->sb->opl.read, NULL, NULL, optimc->sb->opl.write, NULL, NULL, optimc->sb->opl.priv); + io_sethandler(optimc->cur_addr + 8, 0x0002, optimc->sb->opl.read, NULL, NULL, optimc->sb->opl.write, NULL, NULL, optimc->sb->opl.priv); + io_sethandler(0x0388, 0x0004, optimc->sb->opl.read, NULL, NULL, optimc->sb->opl.write, NULL, NULL, optimc->sb->opl.priv); +} + +static void +optimc_reg_write(uint16_t addr, uint8_t val, void *priv) +{ + optimc_t *optimc = (optimc_t *) priv; + uint16_t idx = addr - 0xF8D; + uint8_t old = optimc->regs[idx]; + static uint8_t reg_enable_phase = 0; + + if (optimc->reg_enabled) { + switch (idx) { + case 0: /* MC1 */ + optimc->regs[0] = val; + if (val != old) { + optimc->cur_mode = optimc->cur_wss_enabled = !!(val & 0x80); + + sound_set_cd_audio_filter(NULL, NULL); + if (optimc->cur_wss_enabled) /* WSS */ + sound_set_cd_audio_filter(ad1848_filter_cd_audio, &optimc->ad1848); + else /* SBPro */ + sound_set_cd_audio_filter(sbpro_filter_cd_audio, optimc->sb); + + io_removehandler(optimc->cur_wss_addr, 0x0004, optimc_wss_read, NULL, NULL, optimc_wss_write, NULL, NULL, optimc); + io_removehandler(optimc->cur_wss_addr + 0x0004, 0x0004, ad1848_read, NULL, NULL, ad1848_write, NULL, NULL, &optimc->ad1848); + switch ((val >> 4) & 0x3) { + case 0: /* WSBase = 0x530 */ + optimc->cur_wss_addr = 0x530; + break; + case 1: /* WSBase = 0xE80 */ + optimc->cur_wss_addr = 0xE80; + break; + case 2: /* WSBase = 0xF40 */ + optimc->cur_wss_addr = 0xF40; + break; + case 3: /* WSBase = 0x604 */ + optimc->cur_wss_addr = 0x604; + break; + + default: + break; + } + io_sethandler(optimc->cur_wss_addr, 0x0004, optimc_wss_read, NULL, NULL, optimc_wss_write, NULL, NULL, optimc); + io_sethandler(optimc->cur_wss_addr + 0x0004, 0x0004, ad1848_read, NULL, NULL, ad1848_write, NULL, NULL, &optimc->ad1848); + + gameport_remap(optimc->gameport, (optimc->regs[0] & 0x1) ? 0x00 : 0x200); + } + break; + case 1: /* MC2 */ + optimc->regs[1] = val; + break; + case 2: /* MC3 */ + if (val == optimc->type) + break; + optimc->regs[2] = val; + if (old != val) { + io_removehandler(optimc->cur_addr + 4, 0x0002, sb_ct1345_mixer_read, NULL, NULL, sb_ct1345_mixer_write, NULL, NULL, optimc->sb); + optimc_remove_opl(optimc); + optimc->cur_addr = (val & 0x4) ? 0x240 : 0x220; + switch ((val >> 4) & 0x3) { + case 0: + optimc->cur_dma = 1; + break; + case 1: + optimc->cur_dma = 0; + break; + case 2: + default: + optimc->cur_dma = 3; + break; + } + switch ((val >> 6) & 0x3) { + case 0: + optimc->cur_irq = 7; + break; + case 1: + optimc->cur_irq = 10; + break; + case 2: + default: + optimc->cur_irq = 5; + break; + } + sb_dsp_setaddr(&optimc->sb->dsp, optimc->cur_addr); + sb_dsp_setirq(&optimc->sb->dsp, optimc->cur_irq); + sb_dsp_setdma8(&optimc->sb->dsp, optimc->cur_dma); + optimc_add_opl(optimc); + io_sethandler(optimc->cur_addr + 4, 0x0002, sb_ct1345_mixer_read, NULL, NULL, sb_ct1345_mixer_write, NULL, NULL, optimc->sb); + } + break; + case 3: /* MC4 */ + optimc->regs[3] = val; + break; + case 4: /* MC5 */ + optimc->regs[4] = val; + break; + case 5: /* MC6 */ + optimc->regs[5] = val; + if (old != val) { + switch ((val >> 3) & 0x3) { + case 0: + optimc->cur_mpu401_irq = 9; + break; + case 1: + optimc->cur_mpu401_irq = 10; + break; + case 2: + optimc->cur_mpu401_irq = 5; + break; + case 3: + optimc->cur_mpu401_irq = 7; + break; + + default: + break; + } + switch ((val >> 5) & 0x3) { + case 0: + optimc->cur_mpu401_addr = 0x330; + break; + case 1: + optimc->cur_mpu401_addr = 0x320; + break; + case 2: + optimc->cur_mpu401_addr = 0x310; + break; + case 3: + optimc->cur_mpu401_addr = 0x300; + break; + + default: + break; + } + mpu401_change_addr(optimc->mpu, optimc->cur_mpu401_addr); + mpu401_setirq(optimc->mpu, optimc->cur_mpu401_irq); + } + break; + + default: + break; + } + } + if (optimc->reg_enabled) + optimc->reg_enabled = 0; + if ((addr == 0xF8F) && ((val == optimc->type) || (val == 0x00))) { + if ((addr == 0xF8F) && (val == optimc->type) && !optimc->reg_enabled) + optimc->reg_enabled = 1; + if (reg_enable_phase) { + switch (reg_enable_phase) { + case 1: + if (val == optimc->type) { + reg_enable_phase++; + } + break; + case 2: + if (val == 0x00) { + reg_enable_phase++; + } + break; + case 3: + if (val == optimc->type) { + optimc->regs[2] = 0x2; + reg_enable_phase = 1; + } + break; + + default: + break; + } + } else + reg_enable_phase = 1; + return; + } +} + +static uint8_t +optimc_reg_read(uint16_t addr, void *priv) +{ + optimc_t *optimc = (optimc_t *) priv; + uint8_t temp = 0xFF; + + if (optimc->reg_enabled) { + switch (addr - 0xF8D) { + case 0: /* MC1 */ + case 1: /* MC2 */ + case 3: /* MC4 */ + case 4: /* MC5 */ + case 5: /* MC6 */ + temp = optimc->regs[addr - 0xF8D]; + break; + case 2: /* MC3 */ + temp = (optimc->regs[2] & ~0x3) | 0x2; + break; + + default: + break; + } + optimc->reg_enabled = 0; + } + return temp; +} + +static void * +optimc_init(const device_t *info) +{ + optimc_t *optimc = calloc(1, sizeof(optimc_t)); + + optimc->type = info->local & 0xFF; + + optimc->cur_wss_addr = 0x530; + optimc->cur_mode = 0; + optimc->cur_addr = 0x220; + optimc->cur_irq = 5; + optimc->cur_wss_enabled = 0; + optimc->cur_dma = 1; + optimc->cur_mpu401_irq = 9; + optimc->cur_mpu401_addr = 0x330; + optimc->cur_mpu401_enabled = 1; + + optimc->regs[0] = 0x00; + optimc->regs[1] = 0x03; + optimc->regs[2] = 0x00; + optimc->regs[3] = 0x00; + optimc->regs[4] = 0x3F; + optimc->regs[5] = 0x83; + + optimc->gameport = gameport_add(&gameport_pnp_device); + gameport_remap(optimc->gameport, (optimc->regs[0] & 0x1) ? 0x00 : 0x200); + + if (info->local & 0x100) + ad1848_init(&optimc->ad1848, AD1848_TYPE_CS4231); + else + ad1848_init(&optimc->ad1848, AD1848_TYPE_DEFAULT); + + ad1848_setirq(&optimc->ad1848, optimc->cur_wss_irq); + ad1848_setdma(&optimc->ad1848, optimc->cur_wss_dma); + + io_sethandler(0xF8D, 6, optimc_reg_read, NULL, NULL, optimc_reg_write, NULL, NULL, optimc); + + io_sethandler(optimc->cur_wss_addr, 0x0004, optimc_wss_read, NULL, NULL, optimc_wss_write, NULL, NULL, optimc); + io_sethandler(optimc->cur_wss_addr + 0x0004, 0x0004, ad1848_read, NULL, NULL, ad1848_write, NULL, NULL, &optimc->ad1848); + + optimc->sb = calloc(1, sizeof(sb_t)); + optimc->sb->opl_enabled = 1; + + sb_dsp_init(&optimc->sb->dsp, SBPRO2, SB_SUBTYPE_DEFAULT, optimc); + sb_dsp_setaddr(&optimc->sb->dsp, optimc->cur_addr); + sb_dsp_setirq(&optimc->sb->dsp, optimc->cur_irq); + sb_dsp_setdma8(&optimc->sb->dsp, optimc->cur_dma); + sb_ct1345_mixer_reset(optimc->sb); + + optimc->sb->opl_mixer = optimc; + optimc->sb->opl_mix = optimc_filter_opl; + + optimc->fm_type = (info->local & OPTIMC_OPL4) ? FM_YMF278B : FM_YMF262; + fm_driver_get(optimc->fm_type, &optimc->sb->opl); + io_sethandler(optimc->cur_addr + 0, 0x0004, optimc->sb->opl.read, NULL, NULL, optimc->sb->opl.write, NULL, NULL, optimc->sb->opl.priv); + io_sethandler(optimc->cur_addr + 8, 0x0002, optimc->sb->opl.read, NULL, NULL, optimc->sb->opl.write, NULL, NULL, optimc->sb->opl.priv); + io_sethandler(0x0388, 0x0004, optimc->sb->opl.read, NULL, NULL, optimc->sb->opl.write, NULL, NULL, optimc->sb->opl.priv); + if (optimc->fm_type == FM_YMF278B) + io_sethandler(0x380, 2, optimc->sb->opl.read, NULL, NULL, optimc->sb->opl.write, NULL, NULL, optimc->sb->opl.priv); + + io_sethandler(optimc->cur_addr + 4, 0x0002, sb_ct1345_mixer_read, NULL, NULL, sb_ct1345_mixer_write, NULL, NULL, optimc->sb); + + sound_add_handler(optimc_get_buffer, optimc); + sound_set_cd_audio_filter(sbpro_filter_cd_audio, optimc->sb); /* CD audio filter for the default context */ + + optimc->mpu = (mpu_t *) malloc(sizeof(mpu_t)); + memset(optimc->mpu, 0, sizeof(mpu_t)); + mpu401_init(optimc->mpu, optimc->cur_mpu401_addr, optimc->cur_mpu401_irq, M_UART, device_get_config_int("receive_input401")); + + if (device_get_config_int("receive_input")) + midi_in_handler(1, sb_dsp_input_msg, sb_dsp_input_sysex, &optimc->sb->dsp); + + return optimc; +} + +static void +optimc_close(void *priv) +{ + optimc_t *optimc = (optimc_t *) priv; + + sb_close(optimc->sb); + free(optimc->mpu); + free(priv); +} + +static void +optimc_speed_changed(void *priv) +{ + optimc_t *optimc = (optimc_t *) priv; + + ad1848_speed_changed(&optimc->ad1848); + sb_speed_changed(optimc->sb); +} + +static int +mirosound_pcm10_available(void) +{ + return rom_present("roms/sound/yamaha/yrw801.rom"); +} + +static const device_config_t optimc_config[] = { + // clang-format off + { + .name = "receive_input", + .description = "Receive input (SB MIDI)", + .type = CONFIG_BINARY, + .default_string = "", + .default_int = 1 + }, + { + .name = "receive_input401", + .description = "Receive input (MPU-401)", + .type = CONFIG_BINARY, + .default_string = "", + .default_int = 0 + }, + { .name = "", .description = "", .type = CONFIG_END } + // clang-format on +}; + +const device_t acermagic_s20_device = { + .name = "AcerMagic S20", + .internal_name = "acermagic_s20", + .flags = DEVICE_ISA | DEVICE_AT, + .local = 0xE3 | OPTIMC_CS4231, + .init = optimc_init, + .close = optimc_close, + .reset = NULL, + { .available = NULL }, + .speed_changed = optimc_speed_changed, + .force_redraw = NULL, + .config = optimc_config +}; + +const device_t mirosound_pcm10_device = { + .name = "miroSOUND PCM10", + .internal_name = "mirosound_pcm10", + .flags = DEVICE_ISA | DEVICE_AT, + .local = 0xE3 | OPTIMC_OPL4, + .init = optimc_init, + .close = optimc_close, + .reset = NULL, + { .available = mirosound_pcm10_available }, + .speed_changed = optimc_speed_changed, + .force_redraw = NULL, + .config = optimc_config +}; diff --git a/src/sound/snd_pas16.c b/src/sound/snd_pas16.c index 65a0026fb..674acfcbb 100644 --- a/src/sound/snd_pas16.c +++ b/src/sound/snd_pas16.c @@ -1,768 +1,783 @@ #include #include #include -#include #include +#include #include #define HAVE_STDARG_H -#include <86box/86box.h> + #include "cpu.h" +#include <86box/86box.h> +#include <86box/device.h> +#include <86box/dma.h> +#include <86box/filters.h> #include <86box/io.h> #include <86box/pic.h> #include <86box/timer.h> #include <86box/pit.h> -#include <86box/dma.h> -#include <86box/device.h> -#include <86box/sound.h> -#include <86box/filters.h> #include <86box/snd_mpu401.h> +#include <86box/sound.h> #include <86box/snd_opl.h> #include <86box/snd_sb.h> #include <86box/snd_sb_dsp.h> - +#include <86box/plat_unused.h> /* Original PAS uses 2 x OPL2 PIT - sample rate/count LMC835N/LMC1982 - mixer YM3802 - MIDI Control System - + 9A01 - IO base base >> 2 - + All below + IO base B89 - interrupt status / clear bit 2 - sample rate bit 3 - PCM bit 4 - MIDI - + B88 - Audio mixer control register - + B8A - Audio filter control bit 5 - mute? - + B8B - interrupt mask / board ID bits 5-7 - board ID (read only on PAS16) F88 - PCM data (low) - + F89 - PCM data (high) - + F8A - PCM control? bit 4 - input/output select (1 = output) bit 5 - mono/stereo select bit 6 - PCM enable - + 1388-138b - PIT clocked at 1193180 Hz 1388 - sample rate 1389 - sample count - - 178b - + + 178b - 2789 - board revision - + 8389 - bit 2 - 8/16 bit - + BF88 - wait states - + EF8B - bit 3 - 16 bits okay ? - - F388 - + + F388 - bit 6 - joystick enable - + F389 - bits 0-2 - DMA - + F38A - bits 0-3 - IRQ F788 - bit 1 - SB emulation bit 0 - MPU401 emulation - + F789 - SB base addr bits 0-3 - addr bits 4-7 - + FB8A - SB IRQ/DMA bits 3-5 - IRQ bits 6-7 - DMA - + FF88 - board model 3 = PAS16 */ -typedef struct pas16_t -{ - uint16_t base; - - int irq, dma; - - uint8_t audiofilt; - - uint8_t audio_mixer; - - uint8_t compat, compat_base; - - uint8_t enhancedscsi; - - uint8_t io_conf_1, io_conf_2, io_conf_3, io_conf_4; - - uint8_t irq_stat, irq_ena; - - uint8_t pcm_ctrl; - uint16_t pcm_dat; +typedef struct pas16_t { + uint16_t base; - uint16_t pcm_dat_l, pcm_dat_r; - - uint8_t sb_irqdma; - - int stereo_lr; - - uint8_t sys_conf_1, sys_conf_2, sys_conf_3, sys_conf_4; - - struct - { - uint32_t l[3]; - int64_t c[3]; - pc_timer_t timer[3]; - uint8_t m[3]; - uint8_t ctrl, ctrls[2]; - int wp, rm[3], wm[3]; - uint16_t rl[3]; - int thit[3]; - int delay[3]; - int rereadlatch[3]; - int64_t enable[3]; - } pit; + int irq; + int dma; - opl_t opl; - sb_dsp_t dsp; + uint8_t audiofilt; - int16_t pcm_buffer[2][SOUNDBUFLEN]; + uint8_t audio_mixer; - int pos; + uint8_t compat; + uint8_t compat_base; + + uint8_t enhancedscsi; + + uint8_t io_conf_1; + uint8_t io_conf_2; + uint8_t io_conf_3; + uint8_t io_conf_4; + + uint8_t irq_stat; + uint8_t irq_ena; + + uint8_t pcm_ctrl; + uint16_t pcm_dat; + + uint16_t pcm_dat_l; + uint16_t pcm_dat_r; + + uint8_t sb_irqdma; + + int stereo_lr; + + uint8_t sys_conf_1; + uint8_t sys_conf_2; + uint8_t sys_conf_3; + uint8_t sys_conf_4; + + struct { + uint32_t l[3]; + int64_t c[3]; + pc_timer_t timer[3]; + uint8_t m[3]; + uint8_t ctrl; + uint8_t ctrls[2]; + int wp; + int rm[3]; + int wm[3]; + uint16_t rl[3]; + int thit[3]; + int delay[3]; + int rereadlatch[3]; + int64_t enable[3]; + } pit; + + fm_drv_t opl; + sb_dsp_t dsp; + + int16_t pcm_buffer[2][SOUNDBUFLEN]; + + int pos; } pas16_t; static uint8_t pas16_pit_in(uint16_t port, void *priv); -static void pas16_pit_out(uint16_t port, uint8_t val, void *priv); -static void pas16_update(pas16_t *pas16); +static void pas16_pit_out(uint16_t port, uint8_t val, void *priv); +static void pas16_update(pas16_t *pas16); -static int pas16_dmas[8] = {4, 1, 2, 3, 0, 5, 6, 7}; -static int pas16_irqs[16] = {0, 2, 3, 4, 5, 6, 7, 10, 11, 12, 14, 15, 0, 0, 0, 0}; -static int pas16_sb_irqs[8] = {0, 2, 3, 5, 7, 10, 11, 12}; -static int pas16_sb_dmas[8] = {0, 1, 2, 3}; +static int pas16_dmas[8] = { 4, 1, 2, 3, 0, 5, 6, 7 }; +static int pas16_irqs[16] = { 0, 2, 3, 4, 5, 6, 7, 10, 11, 12, 14, 15, 0, 0, 0, 0 }; +static int pas16_sb_irqs[8] = { 0, 2, 3, 5, 7, 10, 11, 12 }; +static int pas16_sb_dmas[8] = { 0, 1, 2, 3 }; -enum -{ - PAS16_INT_SAMP = 0x04, - PAS16_INT_PCM = 0x08 +enum { + PAS16_INT_SAMP = 0x04, + PAS16_INT_PCM = 0x08 }; -enum -{ - PAS16_PCM_MONO = 0x20, - PAS16_PCM_ENA = 0x40 +enum { + PAS16_PCM_MONO = 0x20, + PAS16_PCM_ENA = 0x40 }; -enum -{ - PAS16_SC2_16BIT = 0x04, - PAS16_SC2_MSBINV = 0x10 +enum { + PAS16_SC2_16BIT = 0x04, + PAS16_SC2_MSBINV = 0x10 }; -enum -{ - PAS16_FILT_MUTE = 0x20 +enum { + PAS16_FILT_MUTE = 0x20 }; - #ifdef ENABLE_PAS16_LOG int pas16_do_log = ENABLE_PAS16_LOG; - static void pas16_log(const char *fmt, ...) { va_list ap; if (pas16_do_log) { - va_start(ap, fmt); - pclog_ex(fmt, ap); - va_end(ap); + va_start(ap, fmt); + pclog_ex(fmt, ap); + va_end(ap); } } #else -#define pas16_log(fmt, ...) +# define pas16_log(fmt, ...) #endif - -static uint8_t pas16_in(uint16_t port, void *p) +static uint8_t +pas16_in(uint16_t port, void *priv) { - pas16_t *pas16 = (pas16_t *)p; - uint8_t temp = 0xff; - switch ((port - pas16->base) + 0x388) - { - case 0x388: case 0x389: case 0x38a: case 0x38b: - temp = opl3_read((port - pas16->base) + 0x388, &pas16->opl); - break; - - case 0xb88: - temp = pas16->audio_mixer; - break; - - case 0xb89: - temp = pas16->irq_stat; - break; - - case 0xb8a: - temp = pas16->audiofilt; - break; - - case 0xb8b: - temp = (pas16->irq_ena & ~0xe0) | 0x20; - break; - - case 0xf8a: - temp = pas16->pcm_ctrl; - break; - - case 0x1388: case 0x1389: case 0x138a: case 0x138b: - temp = pas16_pit_in(port, pas16); - break; + pas16_t *pas16 = (pas16_t *) priv; + uint8_t temp = 0xff; + switch ((port - pas16->base) + 0x388) { + case 0x388: + case 0x389: + case 0x38a: + case 0x38b: + temp = pas16->opl.read((port - pas16->base) + 0x388, pas16->opl.priv); + break; - case 0x2789: /*Board revision*/ - temp = 0; - break; - - case 0x7f89: - temp = pas16->enhancedscsi & ~1; - break; - - case 0x8388: - temp = pas16->sys_conf_1; - break; - case 0x8389: - temp = pas16->sys_conf_2; - break; - case 0x838b: - temp = pas16->sys_conf_3; - break; - case 0x838c: - temp = pas16->sys_conf_4; - break; - - case 0xef8b: - temp = 0x0c; - break; + case 0xb88: + temp = pas16->audio_mixer; + break; - case 0xf388: - temp = pas16->io_conf_1; - break; - case 0xf389: - temp = pas16->io_conf_2; - break; - case 0xf38b: - temp = pas16->io_conf_3; - break; - case 0xf38c: - temp = pas16->io_conf_4; - break; + case 0xb89: + temp = pas16->irq_stat; + break; - case 0xf788: - temp = pas16->compat; - break; - case 0xf789: - temp = pas16->compat_base; - break; - - case 0xfb8a: - temp = pas16->sb_irqdma; - break; + case 0xb8a: + temp = pas16->audiofilt; + break; - case 0xff88: /*Board model*/ - temp = 4; /*PAS16*/ - break; - case 0xff8b: /*Master mode read*/ - temp = 0x20 | 0x10 | 0x01; /*AT bus, XT/AT timing*/ - break; - } - pas16_log("pas16_in : port %04X return %02X %04X:%04X\n", port, temp, CS,cpu_state.pc); - return temp; + case 0xb8b: + temp = (pas16->irq_ena & ~0xe0) | 0x20; + break; + + case 0xf8a: + temp = pas16->pcm_ctrl; + break; + + case 0x1388: + case 0x1389: + case 0x138a: + case 0x138b: + temp = pas16_pit_in(port, pas16); + break; + + case 0x2789: /*Board revision*/ + temp = 0; + break; + + case 0x7f89: + temp = pas16->enhancedscsi & ~1; + break; + + case 0x8388: + temp = pas16->sys_conf_1; + break; + case 0x8389: + temp = pas16->sys_conf_2; + break; + case 0x838b: + temp = pas16->sys_conf_3; + break; + case 0x838c: + temp = pas16->sys_conf_4; + break; + + case 0xef8b: + temp = 0x0c; + break; + + case 0xf388: + temp = pas16->io_conf_1; + break; + case 0xf389: + temp = pas16->io_conf_2; + break; + case 0xf38b: + temp = pas16->io_conf_3; + break; + case 0xf38c: + temp = pas16->io_conf_4; + break; + + case 0xf788: + temp = pas16->compat; + break; + case 0xf789: + temp = pas16->compat_base; + break; + + case 0xfb8a: + temp = pas16->sb_irqdma; + break; + + case 0xff88: /*Board model*/ + temp = 4; /*PAS16*/ + break; + case 0xff8b: /*Master mode read*/ + temp = 0x20 | 0x10 | 0x01; /*AT bus, XT/AT timing*/ + break; + + default: + break; + } + pas16_log("pas16_in : port %04X return %02X %04X:%04X\n", port, temp, CS, cpu_state.pc); + return temp; } -static void pas16_out(uint16_t port, uint8_t val, void *p) +static void +pas16_out(uint16_t port, uint8_t val, void *priv) { - pas16_t *pas16 = (pas16_t *)p; - pas16_log("pas16_out : port %04X val %02X %04X:%04X\n", port, val, CS,cpu_state.pc); - switch ((port - pas16->base) + 0x388) - { - case 0x388: case 0x389: case 0x38a: case 0x38b: - opl3_write((port - pas16->base) + 0x388, val, &pas16->opl); - break; - - case 0xb88: - pas16->audio_mixer = val; - break; + pas16_t *pas16 = (pas16_t *) priv; + pas16_log("pas16_out : port %04X val %02X %04X:%04X\n", port, val, CS, cpu_state.pc); + switch ((port - pas16->base) + 0x388) { + case 0x388: + case 0x389: + case 0x38a: + case 0x38b: + pas16->opl.write((port - pas16->base) + 0x388, val, pas16->opl.priv); + break; - case 0xb89: - pas16->irq_stat &= ~val; - break; + case 0xb88: + pas16->audio_mixer = val; + break; - case 0xb8a: - pas16_update(pas16); - pas16->audiofilt = val; - break; + case 0xb89: + pas16->irq_stat &= ~val; + break; - case 0xb8b: - pas16->irq_ena = val; - break; + case 0xb8a: + pas16_update(pas16); + pas16->audiofilt = val; + break; - case 0xf88: - pas16_update(pas16); - pas16->pcm_dat = (pas16->pcm_dat & 0xff00) | val; - break; - case 0xf89: - pas16_update(pas16); - pas16->pcm_dat = (pas16->pcm_dat & 0x00ff) | (val << 8); - break; - case 0xf8a: - if ((val & PAS16_PCM_ENA) && !(pas16->pcm_ctrl & PAS16_PCM_ENA)) /*Guess*/ - pas16->stereo_lr = 0; - pas16->pcm_ctrl = val; - break; - - case 0x1388: case 0x1389: case 0x138a: case 0x138b: - pas16_pit_out(port, val, pas16); - break; + case 0xb8b: + pas16->irq_ena = val; + break; - case 0x7f89: - pas16->enhancedscsi = val; - break; + case 0xf88: + pas16_update(pas16); + pas16->pcm_dat = (pas16->pcm_dat & 0xff00) | val; + break; + case 0xf89: + pas16_update(pas16); + pas16->pcm_dat = (pas16->pcm_dat & 0x00ff) | (val << 8); + break; + case 0xf8a: + if ((val & PAS16_PCM_ENA) && !(pas16->pcm_ctrl & PAS16_PCM_ENA)) /*Guess*/ + pas16->stereo_lr = 0; + pas16->pcm_ctrl = val; + break; - case 0x8388: - pas16->sys_conf_1 = val; - break; - case 0x8389: - pas16->sys_conf_2 = val; - break; - case 0x838a: - pas16->sys_conf_3 = val; - break; - case 0x838b: - pas16->sys_conf_4 = val; - break; + case 0x1388: + case 0x1389: + case 0x138a: + case 0x138b: + pas16_pit_out(port, val, pas16); + break; - case 0xf388: - pas16->io_conf_1 = val; - break; - case 0xf389: - pas16->io_conf_2 = val; - pas16->dma = pas16_dmas[val & 0x7]; - pas16_log("pas16_out : set PAS DMA %i\n", pas16->dma); - break; - case 0xf38a: - pas16->io_conf_3 = val; - pas16->irq = pas16_irqs[val & 0xf]; - pas16_log("pas16_out : set PAS IRQ %i\n", pas16->irq); - break; - case 0xf38b: - pas16->io_conf_4 = val; - break; + case 0x7f89: + pas16->enhancedscsi = val; + break; + + case 0x8388: + pas16->sys_conf_1 = val; + break; + case 0x8389: + pas16->sys_conf_2 = val; + break; + case 0x838a: + pas16->sys_conf_3 = val; + break; + case 0x838b: + pas16->sys_conf_4 = val; + break; + + case 0xf388: + pas16->io_conf_1 = val; + break; + case 0xf389: + pas16->io_conf_2 = val; + pas16->dma = pas16_dmas[val & 0x7]; + pas16_log("pas16_out : set PAS DMA %i\n", pas16->dma); + break; + case 0xf38a: + pas16->io_conf_3 = val; + pas16->irq = pas16_irqs[val & 0xf]; + pas16_log("pas16_out : set PAS IRQ %i\n", pas16->irq); + break; + case 0xf38b: + pas16->io_conf_4 = val; + break; + + case 0xf788: + pas16->compat = val; + if (pas16->compat & 0x02) + sb_dsp_setaddr(&pas16->dsp, ((pas16->compat_base & 0xf) << 4) | 0x200); + else + sb_dsp_setaddr(&pas16->dsp, 0); + break; + case 0xf789: + pas16->compat_base = val; + if (pas16->compat & 0x02) + sb_dsp_setaddr(&pas16->dsp, ((pas16->compat_base & 0xf) << 4) | 0x200); + break; + + case 0xfb8a: + pas16->sb_irqdma = val; + sb_dsp_setirq(&pas16->dsp, pas16_sb_irqs[(val >> 3) & 7]); + sb_dsp_setdma8(&pas16->dsp, pas16_sb_dmas[(val >> 6) & 3]); + pas16_log("pas16_out : set SB IRQ %i DMA %i\n", pas16_sb_irqs[(val >> 3) & 7], pas16_sb_dmas[(val >> 6) & 3]); + break; + + default: + pas16_log("pas16_out : unknown %04X\n", port); + } +#if 0 + if (cpu_state.pc == 0x80048CF3) { + if (output) + fatal("here\n"); + output = 3; + } +#endif +} + +static void +pas16_pit_out(uint16_t port, uint8_t val, void *priv) +{ + pas16_t *pas16 = (pas16_t *) priv; + int t; + switch (port & 3) { + case 3: /*CTRL*/ + if ((val & 0xC0) == 0xC0) { + if (!(val & 0x20)) { + if (val & 2) + pas16->pit.rl[0] = timer_get_remaining_u64(&pas16->pit.timer[0]) / PITCONST; + if (val & 4) + pas16->pit.rl[1] = pas16->pit.c[1]; + if (val & 8) + pas16->pit.rl[2] = pas16->pit.c[2]; + } + return; + } + t = val >> 6; + pas16->pit.ctrls[t] = pas16->pit.ctrl = val; + if (t == 3) { + printf("Bad PIT reg select\n"); + return; + } + if (!(pas16->pit.ctrl & 0x30)) { + if (!t) + pas16->pit.rl[t] = timer_get_remaining_u64(&pas16->pit.timer[t]) / PITCONST; + else { + pas16->pit.rl[t] = pas16->pit.c[t]; + if (pas16->pit.c[t] < 0) + pas16->pit.rl[t] = 0; + } + pas16->pit.ctrl |= 0x30; + pas16->pit.rereadlatch[t] = 0; + pas16->pit.rm[t] = 3; + } else { + pas16->pit.rm[t] = pas16->pit.wm[t] = (pas16->pit.ctrl >> 4) & 3; + pas16->pit.m[t] = (val >> 1) & 7; + if (pas16->pit.m[t] > 5) + pas16->pit.m[t] &= 3; + if (!pas16->pit.rm[t]) { + pas16->pit.rm[t] = 3; + if (!t) + pas16->pit.rl[t] = timer_get_remaining_u64(&pas16->pit.timer[t]) / PITCONST; + else + pas16->pit.rl[t] = pas16->pit.c[t]; + } + pas16->pit.rereadlatch[t] = 1; + } + pas16->pit.wp = 0; + pas16->pit.thit[t] = 0; + break; + case 0: + case 1: + case 2: /*Timers*/ + t = port & 3; + switch (pas16->pit.wm[t]) { + case 1: + pas16->pit.l[t] = val; + pas16->pit.thit[t] = 0; + pas16->pit.c[t] = pas16->pit.l[t]; + if (!t) + timer_set_delay_u64(&pas16->pit.timer[t], pas16->pit.c[t] * PITCONST); + pas16->pit.enable[t] = 1; + break; + case 2: + pas16->pit.l[t] = val << 8; + pas16->pit.thit[t] = 0; + pas16->pit.c[t] = pas16->pit.l[t]; + if (!t) + timer_set_delay_u64(&pas16->pit.timer[t], pas16->pit.c[t] * PITCONST); + pas16->pit.enable[t] = 1; + break; + case 0: + pas16->pit.l[t] &= 0xFF; + pas16->pit.l[t] |= (val << 8); + pas16->pit.c[t] = pas16->pit.l[t]; + if (!t) + timer_set_delay_u64(&pas16->pit.timer[t], pas16->pit.c[t] * PITCONST); + pas16->pit.thit[t] = 0; + pas16->pit.wm[t] = 3; + pas16->pit.enable[t] = 1; + break; + case 3: + pas16->pit.l[t] &= 0xFF00; + pas16->pit.l[t] |= val; + pas16->pit.wm[t] = 0; + break; - case 0xf788: - pas16->compat = val; - if (pas16->compat & 0x02) - sb_dsp_setaddr(&pas16->dsp, ((pas16->compat_base & 0xf) << 4) | 0x200); - else - sb_dsp_setaddr(&pas16->dsp, 0); - break; - case 0xf789: - pas16->compat_base = val; - if (pas16->compat & 0x02) - sb_dsp_setaddr(&pas16->dsp, ((pas16->compat_base & 0xf) << 4) | 0x200); - break; - - case 0xfb8a: - pas16->sb_irqdma = val; - sb_dsp_setirq(&pas16->dsp, pas16_sb_irqs[(val >> 3) & 7]); - sb_dsp_setdma8(&pas16->dsp, pas16_sb_dmas[(val >> 6) & 3]); - pas16_log("pas16_out : set SB IRQ %i DMA %i\n", pas16_sb_irqs[(val >> 3) & 7], pas16_sb_dmas[(val >> 6) & 3]); - break; - default: - pas16_log("pas16_out : unknown %04X\n", port); - } - if (cpu_state.pc == 0x80048CF3) - { - if (output) - fatal("here\n"); - output = 3; - } + break; + } + if (!pas16->pit.l[t]) { + pas16->pit.l[t] |= 0x10000; + pas16->pit.c[t] = pas16->pit.l[t]; + if (!t) + timer_set_delay_u64(&pas16->pit.timer[t], pas16->pit.c[t] * PITCONST); + } + break; + + default: + break; + } } -static void pas16_pit_out(uint16_t port, uint8_t val, void *p) +static uint8_t +pas16_pit_in(uint16_t port, void *priv) { - pas16_t *pas16 = (pas16_t *)p; - int t; - switch (port & 3) - { - case 3: /*CTRL*/ - if ((val & 0xC0) == 0xC0) - { - if (!(val & 0x20)) - { - if (val & 2) pas16->pit.rl[0] = timer_get_remaining_u64(&pas16->pit.timer[0]) / PITCONST;; - if (val & 4) pas16->pit.rl[1] = pas16->pit.c[1]; - if (val & 8) pas16->pit.rl[2] = pas16->pit.c[2]; - } - return; + pas16_t *pas16 = (pas16_t *) priv; + uint8_t temp = 0xff; + int t = port & 3; + switch (port & 3) { + case 0: + case 1: + case 2: /*Timers*/ + if (pas16->pit.rereadlatch[t]) { + pas16->pit.rereadlatch[t] = 0; + if (!t) { + pas16->pit.rl[t] = timer_get_remaining_u64(&pas16->pit.timer[t]) / PITCONST; + if ((timer_get_remaining_u64(&pas16->pit.timer[t]) / PITCONST) > 65536) + pas16->pit.rl[t] = 0xFFFF; + } else { + pas16->pit.rl[t] = pas16->pit.c[t]; + if (pas16->pit.c[t] > 65536) + pas16->pit.rl[t] = 0xFFFF; } - t = val >> 6; - pas16->pit.ctrls[t] = pas16->pit.ctrl = val; - if (t == 3) - { - printf("Bad PIT reg select\n"); - return; - } - if (!(pas16->pit.ctrl & 0x30)) - { - if (!t) - pas16->pit.rl[t] = timer_get_remaining_u64(&pas16->pit.timer[t]) / PITCONST; - else - { - pas16->pit.rl[t] = pas16->pit.c[t]; - if (pas16->pit.c[t] < 0) - pas16->pit.rl[t] = 0; - } - pas16->pit.ctrl |= 0x30; - pas16->pit.rereadlatch[t] = 0; - pas16->pit.rm[t] = 3; - } - else - { - pas16->pit.rm[t] = pas16->pit.wm[t] = (pas16->pit.ctrl >> 4) & 3; - pas16->pit.m[t] = (val >> 1) & 7; - if (pas16->pit.m[t] > 5) - pas16->pit.m[t] &= 3; - if (!pas16->pit.rm[t]) - { - pas16->pit.rm[t] = 3; - if (!t) - pas16->pit.rl[t] = timer_get_remaining_u64(&pas16->pit.timer[t]) / PITCONST; - else - pas16->pit.rl[t] = pas16->pit.c[t]; - } - pas16->pit.rereadlatch[t] = 1; - } - pas16->pit.wp = 0; - pas16->pit.thit[t] = 0; - break; - case 0: case 1: case 2: /*Timers*/ - t = port & 3; - switch (pas16->pit.wm[t]) - { - case 1: - pas16->pit.l[t] = val; - pas16->pit.thit[t] = 0; - pas16->pit.c[t] = pas16->pit.l[t]; - if (!t) - timer_set_delay_u64(&pas16->pit.timer[t], pas16->pit.c[t] * PITCONST); - pas16->pit.enable[t] = 1; - break; - case 2: - pas16->pit.l[t] = val << 8; - pas16->pit.thit[t] = 0; - pas16->pit.c[t] = pas16->pit.l[t]; - if (!t) - timer_set_delay_u64(&pas16->pit.timer[t], pas16->pit.c[t] * PITCONST); - pas16->pit.enable[t] = 1; - break; - case 0: - pas16->pit.l[t] &= 0xFF; - pas16->pit.l[t] |= (val << 8); - pas16->pit.c[t] = pas16->pit.l[t]; - if (!t) - timer_set_delay_u64(&pas16->pit.timer[t], pas16->pit.c[t] * PITCONST); - pas16->pit.thit[t] = 0; - pas16->pit.wm[t] = 3; - pas16->pit.enable[t] = 1; - break; - case 3: - pas16->pit.l[t] &= 0xFF00; - pas16->pit.l[t] |= val; - pas16->pit.wm[t] = 0; - break; - } - if (!pas16->pit.l[t]) - { - pas16->pit.l[t] |= 0x10000; - pas16->pit.c[t] = pas16->pit.l[t]; - if (!t) - timer_set_delay_u64(&pas16->pit.timer[t], pas16->pit.c[t] * PITCONST); - } - break; - } + } + switch (pas16->pit.rm[t]) { + case 0: + temp = pas16->pit.rl[t] >> 8; + pas16->pit.rm[t] = 3; + pas16->pit.rereadlatch[t] = 1; + break; + case 1: + temp = (pas16->pit.rl[t]) & 0xFF; + pas16->pit.rereadlatch[t] = 1; + break; + case 2: + temp = (pas16->pit.rl[t]) >> 8; + pas16->pit.rereadlatch[t] = 1; + break; + case 3: + temp = (pas16->pit.rl[t]) & 0xFF; + if (pas16->pit.m[t] & 0x80) + pas16->pit.m[t] &= 7; + else + pas16->pit.rm[t] = 0; + break; + + default: + break; + } + break; + case 3: /*Control*/ + temp = pas16->pit.ctrl; + break; + + default: + break; + } + return temp; } -static uint8_t pas16_pit_in(uint16_t port, void *p) +static uint8_t +pas16_readdma(pas16_t *pas16) { - pas16_t *pas16 = (pas16_t *)p; - uint8_t temp = 0xff; - int t = port & 3; - switch (port & 3) - { - case 0: case 1: case 2: /*Timers*/ - if (pas16->pit.rereadlatch[t]) - { - pas16->pit.rereadlatch[t] = 0; - if (!t) - { - pas16->pit.rl[t] = timer_get_remaining_u64(&pas16->pit.timer[t]) / PITCONST; - if ((timer_get_remaining_u64(&pas16->pit.timer[t]) / PITCONST) > 65536) - pas16->pit.rl[t] = 0xFFFF; - } - else - { - pas16->pit.rl[t] = pas16->pit.c[t]; - if (pas16->pit.c[t] > 65536) - pas16->pit.rl[t] = 0xFFFF; - } - } - switch (pas16->pit.rm[t]) - { - case 0: - temp = pas16->pit.rl[t] >> 8; - pas16->pit.rm[t] = 3; - pas16->pit.rereadlatch[t] = 1; - break; - case 1: - temp = (pas16->pit.rl[t]) & 0xFF; - pas16->pit.rereadlatch[t] = 1; - break; - case 2: - temp = (pas16->pit.rl[t]) >> 8; - pas16->pit.rereadlatch[t] = 1; - break; - case 3: - temp = (pas16->pit.rl[t]) & 0xFF; - if (pas16->pit.m[t] & 0x80) pas16->pit.m[t] &= 7; - else pas16->pit.rm[t] = 0; - break; - } - break; - case 3: /*Control*/ - temp = pas16->pit.ctrl; - break; - } - return temp; + return dma_channel_read(pas16->dma); } -static uint8_t pas16_readdma(pas16_t *pas16) +static void +pas16_pcm_poll(void *priv) { - return dma_channel_read(pas16->dma); -} + pas16_t *pas16 = (pas16_t *) priv; -static void pas16_pcm_poll(void *p) -{ - pas16_t *pas16 = (pas16_t *)p; - - pas16_update(pas16); - if (pas16->pit.m[0] & 2) - { - if (pas16->pit.l[0]) - timer_advance_u64(&pas16->pit.timer[0], pas16->pit.l[0] * PITCONST); - else - timer_advance_u64(&pas16->pit.timer[0], 0x10000 * PITCONST); - } + pas16_update(pas16); + if (pas16->pit.m[0] & 2) { + if (pas16->pit.l[0]) + timer_advance_u64(&pas16->pit.timer[0], pas16->pit.l[0] * PITCONST); else - { - pas16->pit.enable[0] = 0; - } + timer_advance_u64(&pas16->pit.timer[0], 0x10000 * PITCONST); + } else { + pas16->pit.enable[0] = 0; + } - pas16->irq_stat |= PAS16_INT_SAMP; - if (pas16->irq_ena & PAS16_INT_SAMP) + pas16->irq_stat |= PAS16_INT_SAMP; + if (pas16->irq_ena & PAS16_INT_SAMP) + picint(1 << pas16->irq); + + /*Update sample rate counter*/ + if (pas16->pit.enable[1]) { + if (pas16->pcm_ctrl & PAS16_PCM_ENA) { + uint16_t temp; + + if (pas16->sys_conf_2 & PAS16_SC2_16BIT) { + temp = pas16_readdma(pas16) << 8; + temp |= pas16_readdma(pas16); + } else + temp = (pas16_readdma(pas16) ^ 0x80) << 8; + + if (pas16->sys_conf_2 & PAS16_SC2_MSBINV) + temp ^= 0x8000; + if (pas16->pcm_ctrl & PAS16_PCM_MONO) + pas16->pcm_dat_l = pas16->pcm_dat_r = temp; + else { + if (pas16->stereo_lr) + pas16->pcm_dat_r = temp; + else + pas16->pcm_dat_l = temp; + + pas16->stereo_lr = !pas16->stereo_lr; + } + } + if (pas16->sys_conf_2 & PAS16_SC2_16BIT) + pas16->pit.c[1] -= 2; + else + pas16->pit.c[1]--; + if (pas16->pit.c[1] == 0) { + if (pas16->pit.m[1] & 2) { + if (pas16->pit.l[1]) + pas16->pit.c[1] += pas16->pit.l[1]; + else + pas16->pit.c[1] += 0x10000; + } else { + pas16->pit.c[1] = -1; + pas16->pit.enable[1] = 0; + } + + pas16->irq_stat |= PAS16_INT_PCM; + if (pas16->irq_ena & PAS16_INT_PCM) { + pas16_log("pas16_pcm_poll : cause IRQ %i %02X\n", pas16->irq, 1 << pas16->irq); picint(1 << pas16->irq); - - /*Update sample rate counter*/ - if (pas16->pit.enable[1]) - { - if (pas16->pcm_ctrl & PAS16_PCM_ENA) - { - uint16_t temp; - - if (pas16->sys_conf_2 & PAS16_SC2_16BIT) - { - temp = pas16_readdma(pas16) << 8; - temp |= pas16_readdma(pas16); - } - else - temp = (pas16_readdma(pas16) ^ 0x80) << 8; - - if (pas16->sys_conf_2 & PAS16_SC2_MSBINV) - temp ^= 0x8000; - if (pas16->pcm_ctrl & PAS16_PCM_MONO) - pas16->pcm_dat_l = pas16->pcm_dat_r = temp; - else - { - if (pas16->stereo_lr) - pas16->pcm_dat_r = temp; - else - pas16->pcm_dat_l = temp; - - pas16->stereo_lr = !pas16->stereo_lr; - } - } - if (pas16->sys_conf_2 & PAS16_SC2_16BIT) - pas16->pit.c[1] -= 2; - else - pas16->pit.c[1]--; - if (pas16->pit.c[1] == 0) - { - if (pas16->pit.m[1] & 2) - { - if (pas16->pit.l[1]) - pas16->pit.c[1] += pas16->pit.l[1]; - else - pas16->pit.c[1] += 0x10000; - } - else - { - pas16->pit.c[1] = -1; - pas16->pit.enable[1] = 0; - } - - pas16->irq_stat |= PAS16_INT_PCM; - if (pas16->irq_ena & PAS16_INT_PCM) - { - pas16_log("pas16_pcm_poll : cause IRQ %i %02X\n", pas16->irq, 1 << pas16->irq); - picint(1 << pas16->irq); - } - } + } } + } } -static void pas16_out_base(uint16_t port, uint8_t val, void *p) +static void +pas16_out_base(UNUSED(uint16_t port), uint8_t val, void *priv) { - pas16_t *pas16 = (pas16_t *)p; + pas16_t *pas16 = (pas16_t *) priv; - io_removehandler((pas16->base - 0x388) + 0x0388, 0x0004, pas16_in, NULL, NULL, pas16_out, NULL, NULL, pas16); - io_removehandler((pas16->base - 0x388) + 0x0788, 0x0004, pas16_in, NULL, NULL, pas16_out, NULL, NULL, pas16); - io_removehandler((pas16->base - 0x388) + 0x0b88, 0x0004, pas16_in, NULL, NULL, pas16_out, NULL, NULL, pas16); - io_removehandler((pas16->base - 0x388) + 0x0f88, 0x0004, pas16_in, NULL, NULL, pas16_out, NULL, NULL, pas16); - io_removehandler((pas16->base - 0x388) + 0x1388, 0x0004, pas16_in, NULL, NULL, pas16_out, NULL, NULL, pas16); - io_removehandler((pas16->base - 0x388) + 0x1788, 0x0004, pas16_in, NULL, NULL, pas16_out, NULL, NULL, pas16); - io_removehandler((pas16->base - 0x388) + 0x2788, 0x0004, pas16_in, NULL, NULL, pas16_out, NULL, NULL, pas16); - io_removehandler((pas16->base - 0x388) + 0x7f88, 0x0004, pas16_in, NULL, NULL, pas16_out, NULL, NULL, pas16); - io_removehandler((pas16->base - 0x388) + 0x8388, 0x0004, pas16_in, NULL, NULL, pas16_out, NULL, NULL, pas16); - io_removehandler((pas16->base - 0x388) + 0xbf88, 0x0004, pas16_in, NULL, NULL, pas16_out, NULL, NULL, pas16); - io_removehandler((pas16->base - 0x388) + 0xe388, 0x0004, pas16_in, NULL, NULL, pas16_out, NULL, NULL, pas16); - io_removehandler((pas16->base - 0x388) + 0xe788, 0x0004, pas16_in, NULL, NULL, pas16_out, NULL, NULL, pas16); - io_removehandler((pas16->base - 0x388) + 0xeb88, 0x0004, pas16_in, NULL, NULL, pas16_out, NULL, NULL, pas16); - io_removehandler((pas16->base - 0x388) + 0xef88, 0x0004, pas16_in, NULL, NULL, pas16_out, NULL, NULL, pas16); - io_removehandler((pas16->base - 0x388) + 0xf388, 0x0004, pas16_in, NULL, NULL, pas16_out, NULL, NULL, pas16); - io_removehandler((pas16->base - 0x388) + 0xf788, 0x0004, pas16_in, NULL, NULL, pas16_out, NULL, NULL, pas16); - io_removehandler((pas16->base - 0x388) + 0xfb88, 0x0004, pas16_in, NULL, NULL, pas16_out, NULL, NULL, pas16); - io_removehandler((pas16->base - 0x388) + 0xff88, 0x0004, pas16_in, NULL, NULL, pas16_out, NULL, NULL, pas16); - - pas16->base = val << 2; - pas16_log("pas16_write_base : PAS16 base now at %04X\n", pas16->base); + io_removehandler((pas16->base - 0x388) + 0x0388, 0x0004, pas16_in, NULL, NULL, pas16_out, NULL, NULL, pas16); + io_removehandler((pas16->base - 0x388) + 0x0788, 0x0004, pas16_in, NULL, NULL, pas16_out, NULL, NULL, pas16); + io_removehandler((pas16->base - 0x388) + 0x0b88, 0x0004, pas16_in, NULL, NULL, pas16_out, NULL, NULL, pas16); + io_removehandler((pas16->base - 0x388) + 0x0f88, 0x0004, pas16_in, NULL, NULL, pas16_out, NULL, NULL, pas16); + io_removehandler((pas16->base - 0x388) + 0x1388, 0x0004, pas16_in, NULL, NULL, pas16_out, NULL, NULL, pas16); + io_removehandler((pas16->base - 0x388) + 0x1788, 0x0004, pas16_in, NULL, NULL, pas16_out, NULL, NULL, pas16); + io_removehandler((pas16->base - 0x388) + 0x2788, 0x0004, pas16_in, NULL, NULL, pas16_out, NULL, NULL, pas16); + io_removehandler((pas16->base - 0x388) + 0x7f88, 0x0004, pas16_in, NULL, NULL, pas16_out, NULL, NULL, pas16); + io_removehandler((pas16->base - 0x388) + 0x8388, 0x0004, pas16_in, NULL, NULL, pas16_out, NULL, NULL, pas16); + io_removehandler((pas16->base - 0x388) + 0xbf88, 0x0004, pas16_in, NULL, NULL, pas16_out, NULL, NULL, pas16); + io_removehandler((pas16->base - 0x388) + 0xe388, 0x0004, pas16_in, NULL, NULL, pas16_out, NULL, NULL, pas16); + io_removehandler((pas16->base - 0x388) + 0xe788, 0x0004, pas16_in, NULL, NULL, pas16_out, NULL, NULL, pas16); + io_removehandler((pas16->base - 0x388) + 0xeb88, 0x0004, pas16_in, NULL, NULL, pas16_out, NULL, NULL, pas16); + io_removehandler((pas16->base - 0x388) + 0xef88, 0x0004, pas16_in, NULL, NULL, pas16_out, NULL, NULL, pas16); + io_removehandler((pas16->base - 0x388) + 0xf388, 0x0004, pas16_in, NULL, NULL, pas16_out, NULL, NULL, pas16); + io_removehandler((pas16->base - 0x388) + 0xf788, 0x0004, pas16_in, NULL, NULL, pas16_out, NULL, NULL, pas16); + io_removehandler((pas16->base - 0x388) + 0xfb88, 0x0004, pas16_in, NULL, NULL, pas16_out, NULL, NULL, pas16); + io_removehandler((pas16->base - 0x388) + 0xff88, 0x0004, pas16_in, NULL, NULL, pas16_out, NULL, NULL, pas16); - io_sethandler((pas16->base - 0x388) + 0x0388, 0x0004, pas16_in, NULL, NULL, pas16_out, NULL, NULL, pas16); - io_sethandler((pas16->base - 0x388) + 0x0788, 0x0004, pas16_in, NULL, NULL, pas16_out, NULL, NULL, pas16); - io_sethandler((pas16->base - 0x388) + 0x0b88, 0x0004, pas16_in, NULL, NULL, pas16_out, NULL, NULL, pas16); - io_sethandler((pas16->base - 0x388) + 0x0f88, 0x0004, pas16_in, NULL, NULL, pas16_out, NULL, NULL, pas16); - io_sethandler((pas16->base - 0x388) + 0x1388, 0x0004, pas16_in, NULL, NULL, pas16_out, NULL, NULL, pas16); - io_sethandler((pas16->base - 0x388) + 0x1788, 0x0004, pas16_in, NULL, NULL, pas16_out, NULL, NULL, pas16); - io_sethandler((pas16->base - 0x388) + 0x2788, 0x0004, pas16_in, NULL, NULL, pas16_out, NULL, NULL, pas16); - io_sethandler((pas16->base - 0x388) + 0x7f88, 0x0004, pas16_in, NULL, NULL, pas16_out, NULL, NULL, pas16); - io_sethandler((pas16->base - 0x388) + 0x8388, 0x0004, pas16_in, NULL, NULL, pas16_out, NULL, NULL, pas16); - io_sethandler((pas16->base - 0x388) + 0xbf88, 0x0004, pas16_in, NULL, NULL, pas16_out, NULL, NULL, pas16); - io_sethandler((pas16->base - 0x388) + 0xe388, 0x0004, pas16_in, NULL, NULL, pas16_out, NULL, NULL, pas16); - io_sethandler((pas16->base - 0x388) + 0xe788, 0x0004, pas16_in, NULL, NULL, pas16_out, NULL, NULL, pas16); - io_sethandler((pas16->base - 0x388) + 0xeb88, 0x0004, pas16_in, NULL, NULL, pas16_out, NULL, NULL, pas16); - io_sethandler((pas16->base - 0x388) + 0xef88, 0x0004, pas16_in, NULL, NULL, pas16_out, NULL, NULL, pas16); - io_sethandler((pas16->base - 0x388) + 0xf388, 0x0004, pas16_in, NULL, NULL, pas16_out, NULL, NULL, pas16); - io_sethandler((pas16->base - 0x388) + 0xf788, 0x0004, pas16_in, NULL, NULL, pas16_out, NULL, NULL, pas16); - io_sethandler((pas16->base - 0x388) + 0xfb88, 0x0004, pas16_in, NULL, NULL, pas16_out, NULL, NULL, pas16); - io_sethandler((pas16->base - 0x388) + 0xff88, 0x0004, pas16_in, NULL, NULL, pas16_out, NULL, NULL, pas16); + pas16->base = val << 2; + pas16_log("pas16_write_base : PAS16 base now at %04X\n", pas16->base); + + io_sethandler((pas16->base - 0x388) + 0x0388, 0x0004, pas16_in, NULL, NULL, pas16_out, NULL, NULL, pas16); + io_sethandler((pas16->base - 0x388) + 0x0788, 0x0004, pas16_in, NULL, NULL, pas16_out, NULL, NULL, pas16); + io_sethandler((pas16->base - 0x388) + 0x0b88, 0x0004, pas16_in, NULL, NULL, pas16_out, NULL, NULL, pas16); + io_sethandler((pas16->base - 0x388) + 0x0f88, 0x0004, pas16_in, NULL, NULL, pas16_out, NULL, NULL, pas16); + io_sethandler((pas16->base - 0x388) + 0x1388, 0x0004, pas16_in, NULL, NULL, pas16_out, NULL, NULL, pas16); + io_sethandler((pas16->base - 0x388) + 0x1788, 0x0004, pas16_in, NULL, NULL, pas16_out, NULL, NULL, pas16); + io_sethandler((pas16->base - 0x388) + 0x2788, 0x0004, pas16_in, NULL, NULL, pas16_out, NULL, NULL, pas16); + io_sethandler((pas16->base - 0x388) + 0x7f88, 0x0004, pas16_in, NULL, NULL, pas16_out, NULL, NULL, pas16); + io_sethandler((pas16->base - 0x388) + 0x8388, 0x0004, pas16_in, NULL, NULL, pas16_out, NULL, NULL, pas16); + io_sethandler((pas16->base - 0x388) + 0xbf88, 0x0004, pas16_in, NULL, NULL, pas16_out, NULL, NULL, pas16); + io_sethandler((pas16->base - 0x388) + 0xe388, 0x0004, pas16_in, NULL, NULL, pas16_out, NULL, NULL, pas16); + io_sethandler((pas16->base - 0x388) + 0xe788, 0x0004, pas16_in, NULL, NULL, pas16_out, NULL, NULL, pas16); + io_sethandler((pas16->base - 0x388) + 0xeb88, 0x0004, pas16_in, NULL, NULL, pas16_out, NULL, NULL, pas16); + io_sethandler((pas16->base - 0x388) + 0xef88, 0x0004, pas16_in, NULL, NULL, pas16_out, NULL, NULL, pas16); + io_sethandler((pas16->base - 0x388) + 0xf388, 0x0004, pas16_in, NULL, NULL, pas16_out, NULL, NULL, pas16); + io_sethandler((pas16->base - 0x388) + 0xf788, 0x0004, pas16_in, NULL, NULL, pas16_out, NULL, NULL, pas16); + io_sethandler((pas16->base - 0x388) + 0xfb88, 0x0004, pas16_in, NULL, NULL, pas16_out, NULL, NULL, pas16); + io_sethandler((pas16->base - 0x388) + 0xff88, 0x0004, pas16_in, NULL, NULL, pas16_out, NULL, NULL, pas16); } - -static void pas16_update(pas16_t *pas16) +static void +pas16_update(pas16_t *pas16) { - if (!(pas16->audiofilt & PAS16_FILT_MUTE)) - { - for (; pas16->pos < sound_pos_global; pas16->pos++) - { - pas16->pcm_buffer[0][pas16->pos] = 0; - pas16->pcm_buffer[1][pas16->pos] = 0; - } + if (!(pas16->audiofilt & PAS16_FILT_MUTE)) { + for (; pas16->pos < sound_pos_global; pas16->pos++) { + pas16->pcm_buffer[0][pas16->pos] = 0; + pas16->pcm_buffer[1][pas16->pos] = 0; } - else - { - for (; pas16->pos < sound_pos_global; pas16->pos++) - { - pas16->pcm_buffer[0][pas16->pos] = (int16_t)pas16->pcm_dat_l; - pas16->pcm_buffer[1][pas16->pos] = (int16_t)pas16->pcm_dat_r; - } + } else { + for (; pas16->pos < sound_pos_global; pas16->pos++) { + pas16->pcm_buffer[0][pas16->pos] = (int16_t) pas16->pcm_dat_l; + pas16->pcm_buffer[1][pas16->pos] = (int16_t) pas16->pcm_dat_r; } + } } -void pas16_get_buffer(int32_t *buffer, int len, void *p) +void +pas16_get_buffer(int32_t *buffer, int len, void *priv) { - pas16_t *pas16 = (pas16_t *)p; - int c; + pas16_t *pas16 = (pas16_t *) priv; - opl3_update(&pas16->opl); - sb_dsp_update(&pas16->dsp); - pas16_update(pas16); - for (c = 0; c < len * 2; c++) - { - buffer[c] += pas16->opl.buffer[c]; - buffer[c] += (int16_t)(sb_iir(c & 1, (float)pas16->dsp.buffer[c]) / 1.3) / 2; - buffer[c] += (pas16->pcm_buffer[c & 1][c >> 1] / 2); - } + const int32_t *opl_buf = pas16->opl.update(pas16->opl.priv); + sb_dsp_update(&pas16->dsp); + pas16_update(pas16); + for (int c = 0; c < len * 2; c++) { + buffer[c] += opl_buf[c]; + buffer[c] += (int16_t) (sb_iir(0, c & 1, (double) pas16->dsp.buffer[c]) / 1.3) / 2; + buffer[c] += (pas16->pcm_buffer[c & 1][c >> 1] / 2); + } - pas16->pos = 0; - pas16->opl.pos = 0; - pas16->dsp.pos = 0; + pas16->pos = 0; + pas16->opl.reset_buffer(pas16->opl.priv); + pas16->dsp.pos = 0; } - -static void *pas16_init(const device_t *info) +static void * +pas16_init(UNUSED(const device_t *info)) { - pas16_t *pas16 = malloc(sizeof(pas16_t)); - memset(pas16, 0, sizeof(pas16_t)); + pas16_t *pas16 = malloc(sizeof(pas16_t)); + memset(pas16, 0, sizeof(pas16_t)); - opl3_init(&pas16->opl); - sb_dsp_init(&pas16->dsp, SB2, SB_SUBTYPE_DEFAULT, pas16); + fm_driver_get(FM_YMF262, &pas16->opl); + sb_dsp_init(&pas16->dsp, SB2, SB_SUBTYPE_DEFAULT, pas16); - io_sethandler(0x9a01, 0x0001, NULL, NULL, NULL, pas16_out_base, NULL, NULL, pas16); - - timer_add(&pas16->pit.timer[0], pas16_pcm_poll, pas16, 0); - - sound_add_handler(pas16_get_buffer, pas16); - - return pas16; + io_sethandler(0x9a01, 0x0001, NULL, NULL, NULL, pas16_out_base, NULL, NULL, pas16); + + timer_add(&pas16->pit.timer[0], pas16_pcm_poll, pas16, 0); + + sound_add_handler(pas16_get_buffer, pas16); + + return pas16; } -static void pas16_close(void *p) +static void +pas16_close(void *priv) { - pas16_t *pas16 = (pas16_t *)p; - - free(pas16); + pas16_t *pas16 = (pas16_t *) priv; + + free(pas16); } -const device_t pas16_device = -{ - "Pro Audio Spectrum 16", - "pas16", - DEVICE_ISA | DEVICE_NOT_WORKING, - 0, - pas16_init, pas16_close, NULL, - { NULL }, NULL, NULL, - NULL +const device_t pas16_device = { + .name = "Pro Audio Spectrum 16", + .internal_name = "pas16", + .flags = DEVICE_ISA, + .local = 0, + .init = pas16_init, + .close = pas16_close, + .reset = NULL, + { .available = NULL }, + .speed_changed = NULL, + .force_redraw = NULL, + .config = NULL }; diff --git a/src/sound/snd_ps1.c b/src/sound/snd_ps1.c index dbca48e79..60b4515f8 100644 --- a/src/sound/snd_ps1.c +++ b/src/sound/snd_ps1.c @@ -1,34 +1,36 @@ #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/pic.h> -#include <86box/timer.h> -#include <86box/device.h> #include <86box/sound.h> #include <86box/snd_sn76489.h> +#include <86box/timer.h> +#include <86box/plat_unused.h> - -typedef struct { - sn76489_t sn76489; - uint8_t status, ctrl; - uint64_t timer_latch; +typedef struct ps1snd_t { + sn76489_t sn76489; + uint8_t status; + uint8_t ctrl; + uint64_t timer_latch; pc_timer_t timer_count; - int timer_enable; - uint8_t fifo[2048]; - int fifo_read_idx, fifo_write_idx; - int fifo_threshold; - uint8_t dac_val; - int16_t buffer[SOUNDBUFLEN]; - int pos; + int timer_enable; + uint8_t fifo[2048]; + int fifo_read_idx; + int fifo_write_idx; + int fifo_threshold; + uint8_t dac_val; + int16_t buffer[SOUNDBUFLEN]; + int pos; } ps1snd_t; - static void ps1snd_update_irq_status(ps1snd_t *snd) { @@ -38,96 +40,99 @@ ps1snd_update_irq_status(ps1snd_t *snd) picintc(1 << 7); } - static uint8_t ps1snd_read(uint16_t port, void *priv) { - ps1snd_t *ps1snd = (ps1snd_t *)priv; - uint8_t ret = 0xff; + ps1snd_t *ps1snd = (ps1snd_t *) priv; + uint8_t ret = 0xff; switch (port & 7) { - case 0: /* ADC data */ - ps1snd->status &= ~0x10; - ps1snd_update_irq_status(ps1snd); - ret = 0; - break; + case 0: /* ADC data */ + ps1snd->status &= ~0x10; + ps1snd_update_irq_status(ps1snd); + ret = 0; + break; - case 2: /* status */ - ret = ps1snd->status; - ret |= (ps1snd->ctrl & 0x01); - if ((ps1snd->fifo_write_idx - ps1snd->fifo_read_idx) >= 2048) - ret |= 0x08; /* FIFO full */ - if (ps1snd->fifo_read_idx == ps1snd->fifo_write_idx) - ret |= 0x04; /* FIFO empty */ - break; + case 2: /* status */ + ret = ps1snd->status; + ret |= (ps1snd->ctrl & 0x01); + if ((ps1snd->fifo_write_idx - ps1snd->fifo_read_idx) >= 2048) + ret |= 0x08; /* FIFO full */ + if (ps1snd->fifo_read_idx == ps1snd->fifo_write_idx) + ret |= 0x04; /* FIFO empty */ + break; - case 3: /* FIFO timer */ - /* - * The PS/1 Technical Reference says this should return - * thecurrent value, but the PS/1 BIOS and Stunt Island - * expect it not to change. - */ - ret = ps1snd->timer_latch; - break; + case 3: /* FIFO timer */ + /* + * The PS/1 Technical Reference says this should return + * thecurrent value, but the PS/1 BIOS and Stunt Island + * expect it not to change. + */ + ret = ps1snd->timer_latch; + break; - case 4: - case 5: - case 6: - case 7: - ret = 0; + case 4: + case 5: + case 6: + case 7: + ret = 0; + break; + + default: + break; } - return(ret); + return ret; } - static void ps1snd_write(uint16_t port, uint8_t val, void *priv) { - ps1snd_t *ps1snd = (ps1snd_t *)priv; + ps1snd_t *ps1snd = (ps1snd_t *) priv; switch (port & 7) { - case 0: /* DAC output */ - if ((ps1snd->fifo_write_idx - ps1snd->fifo_read_idx) < 2048) { - ps1snd->fifo[ps1snd->fifo_write_idx & 2047] = val; - ps1snd->fifo_write_idx++; - } - break; + case 0: /* DAC output */ + if ((ps1snd->fifo_write_idx - ps1snd->fifo_read_idx) < 2048) { + ps1snd->fifo[ps1snd->fifo_write_idx & 2047] = val; + ps1snd->fifo_write_idx++; + } + break; - case 2: /* control */ - ps1snd->ctrl = val; - if (! (val & 0x02)) - ps1snd->status &= ~0x02; - ps1snd_update_irq_status(ps1snd); - break; + case 2: /* control */ + ps1snd->ctrl = val; + if (!(val & 0x02)) + ps1snd->status &= ~0x02; + ps1snd_update_irq_status(ps1snd); + break; - case 3: /* timer reload value */ - ps1snd->timer_latch = val; - if (val) - timer_set_delay_u64(&ps1snd->timer_count, ((0xff-val) * TIMER_USEC)); - else - timer_disable(&ps1snd->timer_count); - break; + case 3: /* timer reload value */ + ps1snd->timer_latch = val; + if (val) + timer_set_delay_u64(&ps1snd->timer_count, ((0xff - val) * TIMER_USEC)); + else + timer_disable(&ps1snd->timer_count); + break; - case 4: /* almost empty */ - ps1snd->fifo_threshold = val * 4; - break; + case 4: /* almost empty */ + ps1snd->fifo_threshold = val * 4; + break; + + default: + break; } } - static void ps1snd_update(ps1snd_t *ps1snd) { - for (; ps1snd->pos < sound_pos_global; ps1snd->pos++) - ps1snd->buffer[ps1snd->pos] = (int8_t)(ps1snd->dac_val ^ 0x80) * 0x20; + for (; ps1snd->pos < sound_pos_global; ps1snd->pos++) + ps1snd->buffer[ps1snd->pos] = (int8_t) (ps1snd->dac_val ^ 0x80) * 0x20; } - static void ps1snd_callback(void *priv) { - ps1snd_t *ps1snd = (ps1snd_t *)priv; + ps1snd_t *ps1snd = (ps1snd_t *) priv; ps1snd_update(ps1snd); @@ -145,58 +150,61 @@ ps1snd_callback(void *priv) timer_advance_u64(&ps1snd->timer_count, ps1snd->timer_latch * TIMER_USEC); } - static void ps1snd_get_buffer(int32_t *buffer, int len, void *priv) { - ps1snd_t *ps1snd = (ps1snd_t *)priv; - int c; + ps1snd_t *ps1snd = (ps1snd_t *) priv; ps1snd_update(ps1snd); - for (c = 0; c < len * 2; c++) + for (int c = 0; c < len * 2; c++) buffer[c] += ps1snd->buffer[c >> 1]; ps1snd->pos = 0; } - static void * -ps1snd_init(const device_t *info) +ps1snd_init(UNUSED(const device_t *info)) { ps1snd_t *ps1snd = malloc(sizeof(ps1snd_t)); memset(ps1snd, 0x00, sizeof(ps1snd_t)); sn76489_init(&ps1snd->sn76489, 0x0205, 0x0001, SN76496, 4000000); - io_sethandler(0x0200, 1, ps1snd_read,NULL,NULL, ps1snd_write,NULL,NULL, ps1snd); - io_sethandler(0x0202, 6, ps1snd_read,NULL,NULL, ps1snd_write,NULL,NULL, ps1snd); + io_sethandler(0x0200, 1, + ps1snd_read, NULL, NULL, + ps1snd_write, NULL, NULL, + ps1snd); + io_sethandler(0x0202, 6, + ps1snd_read, NULL, NULL, + ps1snd_write, NULL, NULL, + ps1snd); timer_add(&ps1snd->timer_count, ps1snd_callback, ps1snd, 0); sound_add_handler(ps1snd_get_buffer, ps1snd); - return(ps1snd); + return ps1snd; } - static void ps1snd_close(void *priv) { - ps1snd_t *ps1snd = (ps1snd_t *)priv; + ps1snd_t *ps1snd = (ps1snd_t *) priv; free(ps1snd); } - const device_t ps1snd_device = { - "IBM PS/1 Audio Card", - "ps1snd", - 0, 0, - ps1snd_init, ps1snd_close, - NULL, - { NULL }, - NULL, - NULL, - NULL + .name = "IBM PS/1 Audio Card", + .internal_name = "ps1snd", + .flags = 0, + .local = 0, + .init = ps1snd_init, + .close = ps1snd_close, + .reset = NULL, + { .available = NULL }, + .speed_changed = NULL, + .force_redraw = NULL, + .config = NULL }; diff --git a/src/sound/snd_pssj.c b/src/sound/snd_pssj.c index cd5f274fe..1e6f48ae3 100644 --- a/src/sound/snd_pssj.c +++ b/src/sound/snd_pssj.c @@ -1,55 +1,56 @@ -#include #include -#include +#include #include +#include #include + #include <86box/86box.h> -#include <86box/io.h> -#include <86box/dma.h> -#include <86box/pic.h> -#include <86box/timer.h> #include <86box/device.h> +#include <86box/dma.h> +#include <86box/io.h> +#include <86box/pic.h> #include <86box/sound.h> #include <86box/snd_sn76489.h> +#include <86box/timer.h> +#include <86box/plat_unused.h> - -typedef struct pssj_t -{ +typedef struct pssj_t { sn76489_t sn76489; - uint8_t ctrl; - uint8_t wave; - uint8_t dac_val; + uint8_t ctrl; + uint8_t wave; + uint8_t dac_val; uint16_t freq; - int amplitude; - - int irq; + int amplitude; + + int irq; pc_timer_t timer_count; - int enable; - + int enable; + int wave_pos; int pulse_width; int16_t buffer[SOUNDBUFLEN]; - int pos; + int pos; } pssj_t; -static void pssj_update_irq(pssj_t *pssj) +static void +pssj_update_irq(pssj_t *pssj) { if (pssj->irq && (pssj->ctrl & 0x10) && (pssj->ctrl & 0x08)) picint(1 << 7); } -static void pssj_write(uint16_t port, uint8_t val, void *p) +static void +pssj_write(uint16_t port, uint8_t val, void *priv) { - pssj_t *pssj = (pssj_t *)p; - - switch (port & 3) - { + pssj_t *pssj = (pssj_t *) priv; + + switch (port & 3) { case 0: pssj->ctrl = val; if (!pssj->enable && ((val & 4) && (pssj->ctrl & 3))) - timer_set_delay_u64(&pssj->timer_count, (TIMER_USEC * (1000000.0 / 3579545.0) * (double)(pssj->freq ? pssj->freq : 0x400))); + timer_set_delay_u64(&pssj->timer_count, (TIMER_USEC * (1000000.0 / 3579545.0) * (double) (pssj->freq ? pssj->freq : 0x400))); pssj->enable = (val & 4) && (pssj->ctrl & 3); if (!pssj->enable) timer_disable(&pssj->timer_count); @@ -59,37 +60,41 @@ static void pssj_write(uint16_t port, uint8_t val, void *p) pssj_update_irq(pssj); break; case 1: - switch (pssj->ctrl & 3) - { + switch (pssj->ctrl & 3) { case 1: /*Sound channel*/ - pssj->wave = val; + pssj->wave = val; pssj->pulse_width = val & 7; break; case 3: /*Direct DAC*/ pssj->dac_val = val; break; + + default: + break; } break; case 2: pssj->freq = (pssj->freq & 0xf00) | val; break; case 3: - pssj->freq = (pssj->freq & 0x0ff) | ((val & 0xf) << 8); + pssj->freq = (pssj->freq & 0x0ff) | ((val & 0xf) << 8); pssj->amplitude = val >> 4; break; - } -} -static uint8_t pssj_read(uint16_t port, void *p) -{ - pssj_t *pssj = (pssj_t *)p; - switch (port & 3) - { + default: + break; + } +} +static uint8_t +pssj_read(uint16_t port, void *priv) +{ + const pssj_t *pssj = (pssj_t *) priv; + + switch (port & 3) { case 0: return (pssj->ctrl & ~0x88) | (pssj->irq ? 8 : 0); case 1: - switch (pssj->ctrl & 3) - { + switch (pssj->ctrl & 3) { case 0: /*Joystick*/ return 0; case 1: /*Sound channel*/ @@ -98,6 +103,9 @@ static uint8_t pssj_read(uint16_t port, void *p) return 0x80; case 3: /*Direct DAC*/ return pssj->dac_val; + + default: + break; } break; case 2: @@ -111,47 +119,39 @@ static uint8_t pssj_read(uint16_t port, void *p) return 0xff; } -static void pssj_update(pssj_t *pssj) +static void +pssj_update(pssj_t *pssj) { - for (; pssj->pos < sound_pos_global; pssj->pos++) - pssj->buffer[pssj->pos] = (((int8_t)(pssj->dac_val ^ 0x80) * 0x20) * pssj->amplitude) / 15; + for (; pssj->pos < sound_pos_global; pssj->pos++) + pssj->buffer[pssj->pos] = (((int8_t) (pssj->dac_val ^ 0x80) * 0x20) * pssj->amplitude) / 15; } -static void pssj_callback(void *p) +static void +pssj_callback(void *priv) { - pssj_t *pssj = (pssj_t *)p; - int data; - + pssj_t *pssj = (pssj_t *) priv; + int data; + pssj_update(pssj); - if (pssj->ctrl & 2) - { - if ((pssj->ctrl & 3) == 3) - { + if (pssj->ctrl & 2) { + if ((pssj->ctrl & 3) == 3) { data = dma_channel_read(1); - if (data != DMA_NODATA) - { + if (data != DMA_NODATA) { pssj->dac_val = data & 0xff; } - } - else - { + } else { data = dma_channel_write(1, 0x80); } - if ((data & DMA_OVER) && data != DMA_NODATA) - { - if (pssj->ctrl & 0x08) - { + if ((data & DMA_OVER) && data != DMA_NODATA) { + if (pssj->ctrl & 0x08) { pssj->irq = 1; pssj_update_irq(pssj); } - } - } - else - { - switch (pssj->wave & 0xc0) - { + } + } else { + switch (pssj->wave & 0xc0) { case 0x00: /*Pulse*/ pssj->dac_val = (pssj->wave_pos > (pssj->pulse_width << 1)) ? 0xff : 0; break; @@ -167,27 +167,31 @@ static void pssj_callback(void *p) case 0xc0: pssj->dac_val = 0x80; break; + + default: + break; } pssj->wave_pos = (pssj->wave_pos + 1) & 31; } - timer_advance_u64(&pssj->timer_count, (TIMER_USEC * (1000000.0 / 3579545.0) * (double)(pssj->freq ? pssj->freq : 0x400))); + timer_advance_u64(&pssj->timer_count, (TIMER_USEC * (1000000.0 / 3579545.0) * (double) (pssj->freq ? pssj->freq : 0x400))); } -static void pssj_get_buffer(int32_t *buffer, int len, void *p) +static void +pssj_get_buffer(int32_t *buffer, int len, void *priv) { - pssj_t *pssj = (pssj_t *)p; - int c; + pssj_t *pssj = (pssj_t *) priv; pssj_update(pssj); - for (c = 0; c < len * 2; c++) + for (int c = 0; c < len * 2; c++) buffer[c] += pssj->buffer[c >> 1]; pssj->pos = 0; } -void *pssj_init(const device_t *info) +void * +pssj_init(UNUSED(const device_t *info)) { pssj_t *pssj = malloc(sizeof(pssj_t)); memset(pssj, 0, sizeof(pssj_t)); @@ -201,7 +205,8 @@ void *pssj_init(const device_t *info) return pssj; } -void *pssj_1e0_init(const device_t *info) +void * +pssj_1e0_init(UNUSED(const device_t *info)) { pssj_t *pssj = malloc(sizeof(pssj_t)); memset(pssj, 0, sizeof(pssj_t)); @@ -215,98 +220,111 @@ void *pssj_1e0_init(const device_t *info) return pssj; } -#if defined(DEV_BRANCH) && defined(USE_TANDY_ISA) -void *pssj_isa_init(const device_t *info) +void * +pssj_isa_init(UNUSED(const device_t *info)) { pssj_t *pssj = malloc(sizeof(pssj_t)); memset(pssj, 0, sizeof(pssj_t)); - sn76489_init(&pssj->sn76489, 0x00c0, 0x0004, PSSJ, 3579545); - uint16_t addr = device_get_config_hex16("base"); - io_sethandler(addr, 0x0004, pssj_read, NULL, NULL, pssj_write, NULL, NULL, pssj); + sn76489_init(&pssj->sn76489, addr, 0x0004, PSSJ, 3579545); + + io_sethandler(addr + 0x04, 0x0004, pssj_read, NULL, NULL, pssj_write, NULL, NULL, pssj); timer_add(&pssj->timer_count, pssj_callback, pssj, pssj->enable); sound_add_handler(pssj_get_buffer, pssj); return pssj; } -#endif -void pssj_close(void *p) +void +pssj_close(void *priv) { - pssj_t *pssj = (pssj_t *)p; + pssj_t *pssj = (pssj_t *) priv; - free(pssj); + free(pssj); } -#if defined(DEV_BRANCH) && defined(USE_TANDY_ISA) -static const device_config_t pssj_isa_config[] = -{ +static const device_config_t pssj_isa_config[] = { + // clang-format off { - "base", "Address", CONFIG_HEX16, "", 0x2C0, "", { 0 }, - { + .name = "base", + .description = "Address", + .type = CONFIG_HEX16, + .default_string = "", + .default_int = 0x2C0, + .file_filter = "", + .spinner = { 0 }, + .selection = { { - "0xC0", 0xC0 + .description = "0x0C0", + .value = 0x0C0 }, { - "0x1E0", 0x1E0 + .description = "0x0E0", + .value = 0x0E0 }, { - "0x2C0", 0x2C0 + .description = "0x1C0", + .value = 0x1C0 }, { - "" - } + .description = "0x1E0", + .value = 0x1E0 + }, + { + .description = "0x2C0", + .value = 0x2C0 + }, + { + .description = "0x2E0", + .value = 0x2E0 + }, + { .description = "" } } }, - { - "", "", -1 - } -}; -#endif - -const device_t pssj_device = -{ - "Tandy PSSJ", - "pssj", - 0, - 0, - pssj_init, - pssj_close, - NULL, - { NULL }, - NULL, - NULL + { .name = "", .description = "", .type = CONFIG_END } + // clang-format on }; -const device_t pssj_1e0_device = -{ - "Tandy PSSJ (port 1e0h)", - "pssj_1e0", - 0, - 0, - pssj_1e0_init, - pssj_close, - NULL, - { NULL }, - NULL, - NULL +const device_t pssj_device = { + .name = "Tandy PSSJ", + .internal_name = "pssj", + .flags = 0, + .local = 0, + .init = pssj_init, + .close = pssj_close, + .reset = NULL, + { .available = NULL }, + .speed_changed = NULL, + .force_redraw = NULL, + .config = NULL }; -#if defined(DEV_BRANCH) && defined(USE_TANDY_ISA) -const device_t pssj_isa_device = -{ - "Tandy PSSJ Clone", - "pssj_isa", - DEVICE_ISA, - 0, - pssj_isa_init, - pssj_close, - NULL, - { NULL }, - NULL, - NULL, - pssj_isa_config +const device_t pssj_1e0_device = { + .name = "Tandy PSSJ (port 1e0h)", + .internal_name = "pssj_1e0", + .flags = 0, + .local = 0, + .init = pssj_1e0_init, + .close = pssj_close, + .reset = NULL, + { .available = NULL }, + .speed_changed = NULL, + .force_redraw = NULL, + .config = NULL +}; + +const device_t pssj_isa_device = { + .name = "Tandy PSSJ Clone", + .internal_name = "pssj_isa", + .flags = DEVICE_ISA, + .local = 0, + .init = pssj_isa_init, + .close = pssj_close, + .reset = NULL, + { .available = NULL }, + .speed_changed = NULL, + .force_redraw = NULL, + .config = pssj_isa_config }; -#endif diff --git a/src/sound/snd_resid.cc b/src/sound/snd_resid.cc index 5ca5f6804..94bbcd591 100644 --- a/src/sound/snd_resid.cc +++ b/src/sound/snd_resid.cc @@ -1,112 +1,134 @@ -#include -#include #include +#include #include +#include + #include "resid-fp/sid.h" #include <86box/plat.h> #include <86box/snd_resid.h> +#define RESID_FREQ 48000 -typedef struct psid_t -{ - /* resid sid implementation */ - SIDFP *sid; - int16_t last_sample; +typedef struct psid_t { + /* resid sid implementation */ + SIDFP *sid; + int16_t last_sample; } psid_t; - psid_t *psid; - -void *sid_init(void) +void * +sid_init(void) { -// psid_t *psid; - int c; - sampling_method method=SAMPLE_INTERPOLATE; - float cycles_per_sec = 14318180.0 / 16.0; - - psid = new psid_t; -// psid = (psid_t *)malloc(sizeof(sound_t)); - psid->sid = new SIDFP; - - psid->sid->set_chip_model(MOS8580FP); - - psid->sid->set_voice_nonlinearity(1.0f); - psid->sid->get_filter().set_distortion_properties(0.f, 0.f, 0.f); - psid->sid->get_filter().set_type4_properties(6.55f, 20.0f); +#if 0 + psid_t *psid; +#endif + sampling_method method = SAMPLE_INTERPOLATE; + float cycles_per_sec = 14318180.0 / 16.0; - psid->sid->enable_filter(true); - psid->sid->enable_external_filter(true); + psid = new psid_t; +#if 0 + psid = (psid_t *)malloc(sizeof(sound_t)); +#endif + psid->sid = new SIDFP; - psid->sid->reset(); - - for (c=0;c<32;c++) - psid->sid->write(c,0); - - if (!psid->sid->set_sampling_parameters((float)cycles_per_sec, method, - (float)48000, 0.9*48000.0/2.0)) - { - // printf("reSID failed!\n"); - } + psid->sid->set_chip_model(MOS8580FP); - psid->sid->set_chip_model(MOS6581FP); - psid->sid->set_voice_nonlinearity(0.96f); - psid->sid->get_filter().set_distortion_properties(3.7e-3f, 2048.f, 1.2e-4f); + psid->sid->set_voice_nonlinearity(1.0f); + psid->sid->get_filter().set_distortion_properties(0.f, 0.f, 0.f); + psid->sid->get_filter().set_type4_properties(6.55f, 20.0f); - psid->sid->input(0); - psid->sid->get_filter().set_type3_properties(1.33e6f, 2.2e9f, 1.0056f, 7e3f); + psid->sid->enable_filter(true); + psid->sid->enable_external_filter(true); - return (void *)psid; + psid->sid->reset(); + + for (uint8_t c = 0; c < 32; c++) + psid->sid->write(c, 0); + + if (!psid->sid->set_sampling_parameters(cycles_per_sec, method, + (float) RESID_FREQ, 0.9 * (float) RESID_FREQ / 2.0)) { +#if 0 + printf("reSID failed!\n"); +#endif + } + + psid->sid->set_chip_model(MOS6581FP); + psid->sid->set_voice_nonlinearity(0.96f); + psid->sid->get_filter().set_distortion_properties(3.7e-3f, 2048.f, 1.2e-4f); + + psid->sid->input(0); + psid->sid->get_filter().set_type3_properties(1.33e6f, 2.2e9f, 1.0056f, 7e3f); + + return (void *) psid; } -void sid_close(UNUSED(void *p)) +void +sid_close(UNUSED(void *priv)) { -// psid_t *psid = (psid_t *)p; - delete psid->sid; -// free(psid); +#if 0 + psid_t *psid = (psid_t *) priv; +#endif + delete psid->sid; +#if 0 + free(psid); +#endif } -void sid_reset(UNUSED(void *p)) +void +sid_reset(UNUSED(void *priv)) { -// psid_t *psid = (psid_t *)p; - int c; - - psid->sid->reset(); +#if 0 + psid_t *psid = (psid_t *) priv; +#endif - for (c = 0; c < 32; c++) - psid->sid->write(c, 0); + psid->sid->reset(); + + for (uint8_t c = 0; c < 32; c++) + psid->sid->write(c, 0); } - -uint8_t sid_read(uint16_t addr, UNUSED(void *p)) +uint8_t +sid_read(uint16_t addr, UNUSED(void *priv)) { -// psid_t *psid = (psid_t *)p; - - return psid->sid->read(addr & 0x1f); -// return 0xFF; +#if 0 + psid_t *psid = (psid_t *) priv; +#endif + + return psid->sid->read(addr & 0x1f); +#if 0 + return 0xFF; +#endif } -void sid_write(uint16_t addr, uint8_t val, UNUSED(void *p)) +void +sid_write(uint16_t addr, uint8_t val, UNUSED(void *priv)) { -// psid_t *psid = (psid_t *)p; - - psid->sid->write(addr & 0x1f,val); +#if 0 + psid_t *psid = (psid_t *) priv; +#endif + + psid->sid->write(addr & 0x1f, val); } -#define CLOCK_DELTA(n) (int)(((14318180.0 * n) / 16.0) / 48000.0) +#define CLOCK_DELTA(n) (int) (((14318180.0 * n) / 16.0) / (float) RESID_FREQ) -static void fillbuf2(int& count, int16_t *buf, int len) +static void +fillbuf2(int &count, int16_t *buf, int len) { - int c; - c = psid->sid->clock(count, buf, len, 1); - if (!c) - *buf = psid->last_sample; - psid->last_sample = *buf; + int c; + c = psid->sid->clock(count, buf, len, 1); + if (!c) + *buf = psid->last_sample; + psid->last_sample = *buf; } -void sid_fillbuf(int16_t *buf, int len, UNUSED(void *p)) +void +sid_fillbuf(int16_t *buf, int len, UNUSED(void *priv)) { -// psid_t *psid = (psid_t *)p; - int x = CLOCK_DELTA(len); - - fillbuf2(x, buf, len); +#if 0 + psid_t *psid = (psid_t *) priv; +#endif + int x = CLOCK_DELTA(len); + + fillbuf2(x, buf, len); } diff --git a/src/sound/snd_sb.c b/src/sound/snd_sb.c index fd0e0a929..5f1aeb261 100644 --- a/src/sound/snd_sb.c +++ b/src/sound/snd_sb.c @@ -1,456 +1,467 @@ /* - * 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. + * 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. + * This file is part of the 86Box distribution. * - * Sound Blaster emulation. + * Sound Blaster emulation. * * * - * Authors: Sarah Walker, - * Miran Grca, - * TheCollector1995, + * Authors: Sarah Walker, + * Miran Grca, + * TheCollector1995, * - * Copyright 2008-2020 Sarah Walker. - * Copyright 2016-2020 Miran Grca. + * Copyright 2008-2020 Sarah Walker. + * Copyright 2016-2020 Miran Grca. */ #include #include #include -#include #include +#include #include #define HAVE_STDARG_H + #include <86box/86box.h> +#include <86box/device.h> +#include <86box/filters.h> +#include <86box/gameport.h> +#include <86box/hdc.h> +#include <86box/isapnp.h> +#include <86box/hdc_ide.h> #include <86box/io.h> -#include <86box/timer.h> #include <86box/mca.h> #include <86box/mem.h> -#include <86box/rom.h> -#include <86box/device.h> -#include <86box/gameport.h> -#include <86box/pic.h> -#include <86box/sound.h> #include <86box/midi.h> -#include <86box/filters.h> -#include <86box/isapnp.h> +#include <86box/pic.h> +#include <86box/rom.h> +#include <86box/sound.h> +#include <86box/timer.h> #include <86box/snd_sb.h> -#include <86box/hdc.h> -#include <86box/hdc_ide.h> - +#include <86box/plat_unused.h> /* 0 to 7 -> -14dB to 0dB i 2dB steps. 8 to 15 -> 0 to +14dB in 2dB steps. - Note that for positive dB values, this is not amplitude, it is amplitude-1. */ -static const double sb_bass_treble_4bits[]= { - 0.199526231, 0.25, 0.316227766, 0.398107170, 0.5, 0.63095734, 0.794328234, 1, + Note that for positive dB values, this is not amplitude, it is amplitude - 1. */ +static const double sb_bass_treble_4bits[] = { + 0.199526231, 0.25, 0.316227766, 0.398107170, 0.5, 0.63095734, 0.794328234, 1, 0, 0.25892541, 0.584893192, 1, 1.511886431, 2.16227766, 3, 4.011872336 }; -/* Attenuation tables for the mixer. Max volume = 32767 in order to give 6dB of +/* Attenuation tables for the mixer. Max volume = 32767 in order to give 6dB of * headroom and avoid integer overflow */ -static const double sb_att_2dbstep_5bits[]= -{ +// clang-format off +static const double sb_att_2dbstep_5bits[] = { 25.0, 32.0, 41.0, 51.0, 65.0, 82.0, 103.0, 130.0, 164.0, 206.0, 260.0, 327.0, 412.0, 519.0, 653.0, 822.0, 1036.0, 1304.0, 1641.0, 2067.0, 2602.0, 3276.0, 4125.0, 5192.0, 6537.0, 8230.0, 10362.0, 13044.0, 16422.0, 20674.0, 26027.0, 32767.0 }; -static const double sb_att_4dbstep_3bits[]= -{ +static const double sb_att_4dbstep_3bits[] = { 164.0, 2067.0, 3276.0, 5193.0, 8230.0, 13045.0, 20675.0, 32767.0 }; -static const double sb_att_7dbstep_2bits[]= -{ +static const double sb_att_7dbstep_2bits[] = { 164.0, 6537.0, 14637.0, 32767.0 }; +// clang-format on - -static const uint16_t sb_mcv_addr[8] = {0x200, 0x210, 0x220, 0x230, 0x240, 0x250, 0x260, 0x270}; -static const int sb_pro_mcv_irqs[4] = {7, 5, 3, 3}; - +static const uint16_t sb_mcv_addr[8] = { 0x200, 0x210, 0x220, 0x230, 0x240, 0x250, 0x260, 0x270 }; +static const int sb_pro_mcv_irqs[4] = { 7, 5, 3, 3 }; /* Each card in the SB16 family has a million variants, and it shows in the large variety of device IDs for the PnP models. This ROM was reconstructed in a best-effort basis around a pnpdump output log found in a forum. */ static uint8_t sb_16_pnp_rom[] = { + // clang-format off 0x0e, 0x8c, 0x00, 0x24, 0x00, 0x00, 0x00, 0x00, 0x00, /* CTL0024, dummy checksum (filled in by isapnp_add_card) */ 0x0a, 0x10, 0x10, /* PnP version 1.0, vendor version 1.0 */ 0x82, 0x11, 0x00, 'C', 'r', 'e', 'a', 't', 'i', 'v', 'e', ' ', 'S', 'B', '1', '6', ' ', 'P', 'n', 'P', /* ANSI identifier */ 0x16, 0x0e, 0x8c, 0x00, 0x31, 0x00, 0x65, /* logical device CTL0031, supports vendor-specific registers 0x39/0x3A/0x3D/0x3F */ - 0x82, 0x05, 0x00, 'A', 'u', 'd', 'i', 'o', /* ANSI identifier */ - 0x31, 0x00, /* start dependent functions, preferred */ - 0x22, 0x20, 0x00, /* IRQ 5 */ - 0x2a, 0x02, 0x08, /* DMA 1, compatibility, no count by word, count by byte, not bus master, 8-bit only */ - 0x2a, 0x20, 0x12, /* DMA 5, compatibility, count by word, no count by byte, not bus master, 16-bit only */ - 0x47, 0x01, 0x20, 0x02, 0x20, 0x02, 0x01, 0x10, /* I/O 0x220, decodes 16-bit, 1-byte alignment, 16 addresses */ - 0x47, 0x01, 0x30, 0x03, 0x30, 0x03, 0x01, 0x02, /* I/O 0x330, decodes 16-bit, 1-byte alignment, 2 addresses */ - 0x47, 0x01, 0x88, 0x03, 0x88, 0x03, 0x01, 0x04, /* I/O 0x388, decodes 16-bit, 1-byte alignment, 4 addresses */ - 0x31, 0x01, /* start dependent functions, acceptable */ - 0x22, 0xa0, 0x04, /* IRQ 5/7/10 */ - 0x2a, 0x0b, 0x08, /* DMA 0/1/3, compatibility, no count by word, count by byte, not bus master, 8-bit only */ - 0x2a, 0xe0, 0x12, /* DMA 5/6/7, compatibility, count by word, no count by byte, not bus master, 16-bit only */ - 0x47, 0x01, 0x20, 0x02, 0x80, 0x02, 0x20, 0x10, /* I/O 0x220-0x280, decodes 16-bit, 32-byte alignment, 16 addresses */ - 0x47, 0x01, 0x00, 0x03, 0x30, 0x03, 0x30, 0x02, /* I/O 0x300-0x330, decodes 16-bit, 48-byte alignment, 2 addresses */ - 0x47, 0x01, 0x88, 0x03, 0x88, 0x03, 0x01, 0x04, /* I/O 0x388, decodes 16-bit, 1-byte alignment, 4 addresses */ - 0x31, 0x01, /* start dependent functions, acceptable */ - 0x22, 0xa0, 0x04, /* IRQ 5/7/10 */ - 0x2a, 0x0b, 0x08, /* DMA 0/1/3, compatibility, no count by word, count by byte, not bus master, 8-bit only */ - 0x2a, 0xe0, 0x12, /* DMA 5/6/7, compatibility, count by word, no count by byte, not bus master, 16-bit only */ - 0x47, 0x01, 0x20, 0x02, 0x80, 0x02, 0x20, 0x10, /* I/O 0x220-0x280, decodes 16-bit, 32-byte alignment, 16 addresses */ - 0x47, 0x01, 0x00, 0x03, 0x30, 0x03, 0x30, 0x02, /* I/O 0x300-0x330, decodes 16-bit, 48-byte alignment, 2 addresses */ - 0x31, 0x02, /* start dependent functions, functional */ - 0x22, 0xa0, 0x04, /* IRQ 5/7/10 */ - 0x2a, 0x0b, 0x08, /* DMA 0/1/3, compatibility, no count by word, count by byte, not bus master, 8-bit only */ - 0x2a, 0xe0, 0x12, /* DMA 5/6/7, compatibility, count by word, no count by byte, not bus master, 16-bit only */ - 0x47, 0x01, 0x20, 0x02, 0x80, 0x02, 0x20, 0x10, /* I/O 0x220-0x280, decodes 16-bit, 32-byte alignment, 16 addresses */ - 0x31, 0x02, /* start dependent functions, functional */ - 0x22, 0xa0, 0x04, /* IRQ 5/7/10 */ - 0x2a, 0x0b, 0x08, /* DMA 0/1/3, compatibility, no count by word, count by byte, not bus master, 8-bit only */ - 0x47, 0x01, 0x20, 0x02, 0x80, 0x02, 0x20, 0x10, /* I/O 0x220-0x280, decodes 16-bit, 32-byte alignment, 16 addresses */ - 0x47, 0x01, 0x00, 0x03, 0x30, 0x03, 0x30, 0x02, /* I/O 0x300-0x330, decodes 16-bit, 48-byte alignment, 2 addresses */ - 0x47, 0x01, 0x88, 0x03, 0x88, 0x03, 0x01, 0x04, /* I/O 0x388, decodes 16-bit, 1-byte alignment, 4 addresses */ - 0x31, 0x02, /* start dependent functions, functional */ - 0x22, 0xa0, 0x04, /* IRQ 5/7/10 */ - 0x2a, 0x0b, 0x08, /* DMA 0/1/3, compatibility, no count by word, count by byte, not bus master, 8-bit only */ - 0x47, 0x01, 0x20, 0x02, 0x80, 0x02, 0x20, 0x10, /* I/O 0x220-0x280, decodes 16-bit, 32-byte alignment, 16 addresses */ - 0x47, 0x01, 0x00, 0x03, 0x30, 0x03, 0x30, 0x02, /* I/O 0x300-0x330, decodes 16-bit, 48-byte alignment, 2 addresses */ - 0x31, 0x02, /* start dependent functions, functional */ - 0x22, 0xa0, 0x04, /* IRQ 5/7/10 */ - 0x2a, 0x0b, 0x08, /* DMA 0/1/3, compatibility, no count by word, count by byte, not bus master, 8-bit only */ - 0x47, 0x01, 0x20, 0x02, 0x80, 0x02, 0x20, 0x10, /* I/O 0x220-0x280, decodes 16-bit, 32-byte alignment, 16 addresses */ - 0x38, /* end dependent functions */ + 0x82, 0x05, 0x00, 'A', 'u', 'd', 'i', 'o', /* ANSI identifier */ + 0x31, 0x00, /* start dependent functions, preferred */ + 0x22, 0x20, 0x00, /* IRQ 5 */ + 0x2a, 0x02, 0x08, /* DMA 1, compatibility, no count by word, count by byte, not bus master, 8-bit only */ + 0x2a, 0x20, 0x12, /* DMA 5, compatibility, count by word, no count by byte, not bus master, 16-bit only */ + 0x47, 0x01, 0x20, 0x02, 0x20, 0x02, 0x01, 0x10, /* I/O 0x220, decodes 16-bit, 1-byte alignment, 16 addresses */ + 0x47, 0x01, 0x30, 0x03, 0x30, 0x03, 0x01, 0x02, /* I/O 0x330, decodes 16-bit, 1-byte alignment, 2 addresses */ + 0x47, 0x01, 0x88, 0x03, 0x88, 0x03, 0x01, 0x04, /* I/O 0x388, decodes 16-bit, 1-byte alignment, 4 addresses */ + 0x31, 0x01, /* start dependent functions, acceptable */ + 0x22, 0xa0, 0x04, /* IRQ 5/7/10 */ + 0x2a, 0x0b, 0x08, /* DMA 0/1/3, compatibility, no count by word, count by byte, not bus master, 8-bit only */ + 0x2a, 0xe0, 0x12, /* DMA 5/6/7, compatibility, count by word, no count by byte, not bus master, 16-bit only */ + 0x47, 0x01, 0x20, 0x02, 0x80, 0x02, 0x20, 0x10, /* I/O 0x220-0x280, decodes 16-bit, 32-byte alignment, 16 addresses */ + 0x47, 0x01, 0x00, 0x03, 0x30, 0x03, 0x30, 0x02, /* I/O 0x300-0x330, decodes 16-bit, 48-byte alignment, 2 addresses */ + 0x47, 0x01, 0x88, 0x03, 0x88, 0x03, 0x01, 0x04, /* I/O 0x388, decodes 16-bit, 1-byte alignment, 4 addresses */ + 0x31, 0x01, /* start dependent functions, acceptable */ + 0x22, 0xa0, 0x04, /* IRQ 5/7/10 */ + 0x2a, 0x0b, 0x08, /* DMA 0/1/3, compatibility, no count by word, count by byte, not bus master, 8-bit only */ + 0x2a, 0xe0, 0x12, /* DMA 5/6/7, compatibility, count by word, no count by byte, not bus master, 16-bit only */ + 0x47, 0x01, 0x20, 0x02, 0x80, 0x02, 0x20, 0x10, /* I/O 0x220-0x280, decodes 16-bit, 32-byte alignment, 16 addresses */ + 0x47, 0x01, 0x00, 0x03, 0x30, 0x03, 0x30, 0x02, /* I/O 0x300-0x330, decodes 16-bit, 48-byte alignment, 2 addresses */ + 0x31, 0x02, /* start dependent functions, functional */ + 0x22, 0xa0, 0x04, /* IRQ 5/7/10 */ + 0x2a, 0x0b, 0x08, /* DMA 0/1/3, compatibility, no count by word, count by byte, not bus master, 8-bit only */ + 0x2a, 0xe0, 0x12, /* DMA 5/6/7, compatibility, count by word, no count by byte, not bus master, 16-bit only */ + 0x47, 0x01, 0x20, 0x02, 0x80, 0x02, 0x20, 0x10, /* I/O 0x220-0x280, decodes 16-bit, 32-byte alignment, 16 addresses */ + 0x31, 0x02, /* start dependent functions, functional */ + 0x22, 0xa0, 0x04, /* IRQ 5/7/10 */ + 0x2a, 0x0b, 0x08, /* DMA 0/1/3, compatibility, no count by word, count by byte, not bus master, 8-bit only */ + 0x47, 0x01, 0x20, 0x02, 0x80, 0x02, 0x20, 0x10, /* I/O 0x220-0x280, decodes 16-bit, 32-byte alignment, 16 addresses */ + 0x47, 0x01, 0x00, 0x03, 0x30, 0x03, 0x30, 0x02, /* I/O 0x300-0x330, decodes 16-bit, 48-byte alignment, 2 addresses */ + 0x47, 0x01, 0x88, 0x03, 0x88, 0x03, 0x01, 0x04, /* I/O 0x388, decodes 16-bit, 1-byte alignment, 4 addresses */ + 0x31, 0x02, /* start dependent functions, functional */ + 0x22, 0xa0, 0x04, /* IRQ 5/7/10 */ + 0x2a, 0x0b, 0x08, /* DMA 0/1/3, compatibility, no count by word, count by byte, not bus master, 8-bit only */ + 0x47, 0x01, 0x20, 0x02, 0x80, 0x02, 0x20, 0x10, /* I/O 0x220-0x280, decodes 16-bit, 32-byte alignment, 16 addresses */ + 0x47, 0x01, 0x00, 0x03, 0x30, 0x03, 0x30, 0x02, /* I/O 0x300-0x330, decodes 16-bit, 48-byte alignment, 2 addresses */ + 0x31, 0x02, /* start dependent functions, functional */ + 0x22, 0xa0, 0x04, /* IRQ 5/7/10 */ + 0x2a, 0x0b, 0x08, /* DMA 0/1/3, compatibility, no count by word, count by byte, not bus master, 8-bit only */ + 0x47, 0x01, 0x20, 0x02, 0x80, 0x02, 0x20, 0x10, /* I/O 0x220-0x280, decodes 16-bit, 32-byte alignment, 16 addresses */ + 0x38, /* end dependent functions */ 0x16, 0x0e, 0x8c, 0x20, 0x11, 0x00, 0x5a, /* logical device CTL2011, supports vendor-specific registers 0x39/0x3B/0x3C/0x3E */ - 0x1c, 0x41, 0xd0, 0x06, 0x00, /* compatible device PNP0600 */ - 0x82, 0x03, 0x00, 'I', 'D', 'E', /* ANSI identifier */ - 0x31, 0x00, /* start dependent functions, preferred */ - 0x22, 0x00, 0x04, /* IRQ 10 */ - 0x47, 0x01, 0x68, 0x01, 0x68, 0x01, 0x01, 0x08, /* I/O 0x168, decodes 16-bit, 1-byte alignment, 8 addresses */ - 0x47, 0x01, 0x6e, 0x03, 0x6e, 0x03, 0x01, 0x02, /* I/O 0x36E, decodes 16-bit, 1-byte alignment, 2 addresses */ - 0x31, 0x01, /* start dependent functions, acceptable */ - 0x22, 0x00, 0x08, /* IRQ 11 */ - 0x47, 0x01, 0xe8, 0x01, 0xe8, 0x01, 0x01, 0x08, /* I/O 0x1E8, decodes 16-bit, 1-byte alignment, 8 addresses */ - 0x47, 0x01, 0xee, 0x03, 0xee, 0x03, 0x01, 0x02, /* I/O 0x3EE, decodes 16-bit, 1-byte alignment, 2 addresses */ - 0x31, 0x01, /* start dependent functions, acceptable */ - 0x22, 0x00, 0x8c, /* IRQ 10/11/15 */ - 0x47, 0x01, 0x00, 0x01, 0xf8, 0x01, 0x08, 0x08, /* I/O 0x100-0x1F8, decodes 16-bit, 8-byte alignment, 8 addresses */ - 0x47, 0x01, 0x00, 0x03, 0xfe, 0x03, 0x02, 0x02, /* I/O 0x300-0x3FE, decodes 16-bit, 2-byte alignment, 2 addresses */ - 0x31, 0x02, /* start dependent functions, functional */ - 0x22, 0x00, 0x80, /* IRQ 15 */ - 0x47, 0x01, 0x70, 0x01, 0x70, 0x01, 0x01, 0x08, /* I/O 0x170, decodes 16-bit, 1-byte alignment, 8 addresses */ - 0x47, 0x01, 0x76, 0x03, 0x76, 0x03, 0x01, 0x02, /* I/O 0x376, decodes 16-bit, 1-byte alignment, 1 addresses */ - 0x38, /* end dependent functions */ + 0x1c, 0x41, 0xd0, 0x06, 0x00, /* compatible device PNP0600 */ + 0x82, 0x03, 0x00, 'I', 'D', 'E', /* ANSI identifier */ + 0x31, 0x00, /* start dependent functions, preferred */ + 0x22, 0x00, 0x04, /* IRQ 10 */ + 0x47, 0x01, 0x68, 0x01, 0x68, 0x01, 0x01, 0x08, /* I/O 0x168, decodes 16-bit, 1-byte alignment, 8 addresses */ + 0x47, 0x01, 0x6e, 0x03, 0x6e, 0x03, 0x01, 0x02, /* I/O 0x36E, decodes 16-bit, 1-byte alignment, 2 addresses */ + 0x31, 0x01, /* start dependent functions, acceptable */ + 0x22, 0x00, 0x08, /* IRQ 11 */ + 0x47, 0x01, 0xe8, 0x01, 0xe8, 0x01, 0x01, 0x08, /* I/O 0x1E8, decodes 16-bit, 1-byte alignment, 8 addresses */ + 0x47, 0x01, 0xee, 0x03, 0xee, 0x03, 0x01, 0x02, /* I/O 0x3EE, decodes 16-bit, 1-byte alignment, 2 addresses */ + 0x31, 0x01, /* start dependent functions, acceptable */ + 0x22, 0x00, 0x8c, /* IRQ 10/11/15 */ + 0x47, 0x01, 0x00, 0x01, 0xf8, 0x01, 0x08, 0x08, /* I/O 0x100-0x1F8, decodes 16-bit, 8-byte alignment, 8 addresses */ + 0x47, 0x01, 0x00, 0x03, 0xfe, 0x03, 0x02, 0x02, /* I/O 0x300-0x3FE, decodes 16-bit, 2-byte alignment, 2 addresses */ + 0x31, 0x02, /* start dependent functions, functional */ + 0x22, 0x00, 0x80, /* IRQ 15 */ + 0x47, 0x01, 0x70, 0x01, 0x70, 0x01, 0x01, 0x08, /* I/O 0x170, decodes 16-bit, 1-byte alignment, 8 addresses */ + 0x47, 0x01, 0x76, 0x03, 0x76, 0x03, 0x01, 0x02, /* I/O 0x376, decodes 16-bit, 1-byte alignment, 1 addresses */ + 0x38, /* end dependent functions */ 0x16, 0x41, 0xd0, 0xff, 0xff, 0x00, 0xda, /* logical device PNPFFFF, supports vendor-specific registers 0x38/0x39/0x3B/0x3C/0x3E */ - 0x82, 0x08, 0x00, 'R', 'e', 's', 'e', 'r', 'v', 'e', 'd', /* ANSI identifier */ - 0x47, 0x01, 0x00, 0x01, 0xf8, 0x03, 0x08, 0x01, /* I/O 0x100-0x3F8, decodes 16-bit, 8-byte alignment, 1 address */ + 0x82, 0x08, 0x00, 'R', 'e', 's', 'e', 'r', 'v', 'e', 'd', /* ANSI identifier */ + 0x47, 0x01, 0x00, 0x01, 0xf8, 0x03, 0x08, 0x01, /* I/O 0x100-0x3F8, decodes 16-bit, 8-byte alignment, 1 address */ 0x15, 0x0e, 0x8c, 0x70, 0x01, 0x00, /* logical device CTL7001 */ - 0x1c, 0x41, 0xd0, 0xb0, 0x2f, /* compatible device PNPB02F */ - 0x82, 0x04, 0x00, 'G', 'a', 'm', 'e', /* ANSI identifier */ - 0x47, 0x01, 0x00, 0x02, 0x00, 0x02, 0x01, 0x08, /* I/O 0x200, decodes 16-bit, 1-byte alignment, 8 addresses */ + 0x1c, 0x41, 0xd0, 0xb0, 0x2f, /* compatible device PNPB02F */ + 0x82, 0x04, 0x00, 'G', 'a', 'm', 'e', /* ANSI identifier */ + 0x47, 0x01, 0x00, 0x02, 0x00, 0x02, 0x01, 0x08, /* I/O 0x200, decodes 16-bit, 1-byte alignment, 8 addresses */ 0x79, 0x00 /* end tag, dummy checksum (filled in by isapnp_add_card) */ + // clang-format on }; - #ifdef ENABLE_SB_LOG int sb_do_log = ENABLE_SB_LOG; - static void sb_log(const char *fmt, ...) { va_list ap; if (sb_do_log) { - va_start(ap, fmt); - pclog_ex(fmt, ap); - va_end(ap); + va_start(ap, fmt); + pclog_ex(fmt, ap); + va_end(ap); } } #else -#define sb_log(fmt, ...) +# define sb_log(fmt, ...) #endif - /* SB 1, 1.5, MCV, and 2 do not have a mixer, so signal is hardwired. */ static void -sb_get_buffer_sb2(int32_t *buffer, int len, void *p) +sb_get_buffer_sb2(int32_t *buffer, int len, void *priv) { - sb_t *sb = (sb_t *) p; - sb_ct1335_mixer_t *mixer = &sb->mixer_sb2; - int c; - double out_mono = 0.0, out_l = 0.0, out_r = 0.0; + sb_t *sb = (sb_t *) priv; + const sb_ct1335_mixer_t *mixer = &sb->mixer_sb2; + double out_mono = 0.0; + double out_l = 0.0; + double out_r = 0.0; + const int32_t *opl_buf = NULL; if (sb->opl_enabled) - opl2_update(&sb->opl); + opl_buf = sb->opl.update(sb->opl.priv); sb_dsp_update(&sb->dsp); if (sb->cms_enabled) - cms_update(&sb->cms); + cms_update(&sb->cms); - for (c = 0; c < len * 2; c += 2) { - out_mono = 0.0; - out_l = 0.0; - out_r = 0.0; + for (int c = 0; c < len * 2; c += 2) { + out_mono = 0.0; + out_l = 0.0; + out_r = 0.0; - if (sb->opl_enabled) - out_mono = ((double) sb->opl.buffer[c]) * 0.7171630859375; + if (sb->opl_enabled) + out_mono = ((double) opl_buf[c]) * 0.7171630859375; - if (sb->cms_enabled) { - out_l += sb->cms.buffer[c]; - out_r += sb->cms.buffer[c + 1]; - } - out_l += out_mono; - out_r += out_mono; + if (sb->cms_enabled) { + out_l += sb->cms.buffer[c]; + out_r += sb->cms.buffer[c + 1]; + } + out_l += out_mono; + out_r += out_mono; - if (((sb->opl_enabled) || (sb->cms_enabled)) && sb->mixer_enabled) { - out_l *= mixer->fm; - out_r *= mixer->fm; - } + if (((sb->opl_enabled) || (sb->cms_enabled)) && sb->mixer_enabled) { + out_l *= mixer->fm; + out_r *= mixer->fm; + } - /* TODO: Recording: I assume it has direct mic and line in like SB2. - It is unclear from the docs if it has a filter, but it probably does. */ - /* TODO: Recording: Mic and line In with AGC. */ - if (sb->mixer_enabled) - out_mono = (sb_iir(0, 0, (double) sb->dsp.buffer[c]) * mixer->voice) / 3.9; - else - out_mono = (((sb_iir(0, 0, (double) sb->dsp.buffer[c]) / 1.3) * 65536.0) / 3.0) / 65536.0; - out_l += out_mono; - out_r += out_mono; + /* TODO: Recording: I assume it has direct mic and line in like SB2. + It is unclear from the docs if it has a filter, but it probably does. */ + /* TODO: Recording: Mic and line In with AGC. */ + if (sb->mixer_enabled) + out_mono = (sb_iir(0, 0, (double) sb->dsp.buffer[c]) * mixer->voice) / 3.9; + else + out_mono = (((sb_iir(0, 0, (double) sb->dsp.buffer[c]) / 1.3) * 65536.0) / 3.0) / 65536.0; + out_l += out_mono; + out_r += out_mono; - if (sb->mixer_enabled) { - out_l *= mixer->master; - out_r *= mixer->master; - } + if (sb->mixer_enabled) { + out_l *= mixer->master; + out_r *= mixer->master; + } - buffer[c] += (int32_t) out_l; - buffer[c + 1] += (int32_t) out_r; + buffer[c] += (int32_t) out_l; + buffer[c + 1] += (int32_t) out_r; } sb->pos = 0; if (sb->opl_enabled) - sb->opl.pos = 0; + sb->opl.reset_buffer(sb->opl.priv); sb->dsp.pos = 0; if (sb->cms_enabled) - sb->cms.pos = 0; + sb->cms.pos = 0; } - static void -sb2_filter_cd_audio(int channel, double *buffer, void *p) +sb2_filter_cd_audio(UNUSED(int channel), double *buffer, void *priv) { - sb_t *sb = (sb_t *)p; - sb_ct1335_mixer_t *mixer = &sb->mixer_sb2; - double c; + const sb_t *sb = (sb_t *) priv; + const sb_ct1335_mixer_t *mixer = &sb->mixer_sb2; + double c; if (sb->mixer_enabled) { - c = ((sb_iir(1, 0, *buffer) / 1.3) * mixer->cd) / 3.0; - *buffer = c * mixer->master; + c = ((sb_iir(1, 0, *buffer) / 1.3) * mixer->cd) / 3.0; + *buffer = c * mixer->master; } else { - c = (((sb_iir(1, 0, ((double) *buffer)) / 1.3) * 65536) / 3.0) / 65536.0; - *buffer = c; + c = (((sb_iir(1, 0, (*buffer)) / 1.3) * 65536) / 3.0) / 65536.0; + *buffer = c; } } - void -sb_get_buffer_sbpro(int32_t *buffer, int len, void *p) +sb_get_buffer_sbpro(int32_t *buffer, int len, void *priv) { - sb_t *sb = (sb_t *)p; - sb_ct1345_mixer_t *mixer = &sb->mixer_sbpro; - int c; - double out_l = 0.0, out_r = 0.0; + sb_t *sb = (sb_t *) priv; + const sb_ct1345_mixer_t *mixer = &sb->mixer_sbpro; + double out_l = 0.0; + double out_r = 0.0; + const int32_t *opl_buf = NULL; + const int32_t *opl2_buf = NULL; if (sb->opl_enabled) { - if (sb->dsp.sb_type == SBPRO) { - opl2_update(&sb->opl); - opl2_update(&sb->opl2); - } else - opl3_update(&sb->opl); + if (sb->dsp.sb_type == SBPRO) { + opl_buf = sb->opl.update(sb->opl.priv); + opl2_buf = sb->opl2.update(sb->opl2.priv); + } else + opl_buf = sb->opl.update(sb->opl.priv); } sb_dsp_update(&sb->dsp); - for (c = 0; c < len * 2; c += 2) { - out_l = 0.0, out_r = 0.0; + for (int c = 0; c < len * 2; c += 2) { + out_l = 0.0; + out_r = 0.0; - if (sb->opl_enabled) { - if (sb->dsp.sb_type == SBPRO) { - /* Two chips for LEFT and RIGHT channels. - Each chip stores data into the LEFT channel only (no sample alternating.) */ - out_l = (((double) sb->opl.buffer [c ]) * mixer->fm_l) * 0.7171630859375; - out_r = (((double) sb->opl2.buffer[c ]) * mixer->fm_r) * 0.7171630859375; - } else { - out_l = (((double) sb->opl.buffer[c ]) * mixer->fm_l) * 0.7171630859375; - out_r = (((double) sb->opl.buffer[c + 1]) * mixer->fm_r) * 0.7171630859375; - } - } + if (sb->opl_enabled) { + if (sb->dsp.sb_type == SBPRO) { + /* Two chips for LEFT and RIGHT channels. + Each chip stores data into the LEFT channel only (no sample alternating.) */ + out_l = (((double) opl_buf[c]) * mixer->fm_l) * 0.7171630859375; + out_r = (((double) opl2_buf[c]) * mixer->fm_r) * 0.7171630859375; + } else { + out_l = (((double) opl_buf[c]) * mixer->fm_l) * 0.7171630859375; + out_r = (((double) opl_buf[c + 1]) * mixer->fm_r) * 0.7171630859375; + if (sb->opl_mix && sb->opl_mixer) { + sb->opl_mix(sb->opl_mixer, &out_l, &out_r); + } + } + } - /* TODO: Implement the stereo switch on the mixer instead of on the dsp? */ - if (mixer->output_filter) { - out_l += (sb_iir(0, 0, (double) sb->dsp.buffer[c]) * mixer->voice_l) / 3.9; - out_r += (sb_iir(0, 1, (double) sb->dsp.buffer[c + 1]) * mixer->voice_r) / 3.9; - } else { - out_l += (sb->dsp.buffer[c] * mixer->voice_l) / 3.0; - out_r += (sb->dsp.buffer[c + 1] * mixer->voice_r) / 3.0; - } - /* TODO: recording CD, Mic with AGC or line in. Note: mic volume does not affect recording. */ + /* TODO: Implement the stereo switch on the mixer instead of on the dsp? */ + if (mixer->output_filter) { + out_l += (sb_iir(0, 0, (double) sb->dsp.buffer[c]) * mixer->voice_l) / 3.9; + out_r += (sb_iir(0, 1, (double) sb->dsp.buffer[c + 1]) * mixer->voice_r) / 3.9; + } else { + out_l += (sb->dsp.buffer[c] * mixer->voice_l) / 3.0; + out_r += (sb->dsp.buffer[c + 1] * mixer->voice_r) / 3.0; + } - out_l *= mixer->master_l; - out_r *= mixer->master_r; + /* TODO: recording CD, Mic with AGC or line in. Note: mic volume does not affect recording. */ + out_l *= mixer->master_l; + out_r *= mixer->master_r; - buffer[c] += (int32_t) out_l; - buffer[c + 1] += (int32_t) out_r; + buffer[c] += (int32_t) out_l; + buffer[c + 1] += (int32_t) out_r; } sb->pos = 0; if (sb->opl_enabled) { - sb->opl.pos = 0; - if (sb->dsp.sb_type != SBPRO) - sb->opl2.pos = 0; + sb->opl.reset_buffer(sb->opl.priv); + if (sb->dsp.sb_type == SBPRO) + sb->opl2.reset_buffer(sb->opl2.priv); } sb->dsp.pos = 0; } - void -sbpro_filter_cd_audio(int channel, double *buffer, void *p) +sbpro_filter_cd_audio(int channel, double *buffer, void *priv) { - sb_t *sb = (sb_t *)p; - sb_ct1345_mixer_t *mixer = &sb->mixer_sbpro; - double c; - double cd = channel ? mixer->cd_r : mixer->cd_l; - double master = channel ? mixer->master_r : mixer->master_l; + const sb_t *sb = (sb_t *) priv; + const sb_ct1345_mixer_t *mixer = &sb->mixer_sbpro; + double c; + double cd = channel ? mixer->cd_r : mixer->cd_l; + double master = channel ? mixer->master_r : mixer->master_l; if (mixer->output_filter) - c = (sb_iir(1, channel, *buffer) * cd) / 3.9; + c = (sb_iir(1, channel, *buffer) * cd) / 3.9; else - c = (*buffer * cd) / 3.0; + c = (*buffer * cd) / 3.0; *buffer = c * master; } - static void -sb_get_buffer_sb16_awe32(int32_t *buffer, int len, void *p) +sb_get_buffer_sb16_awe32(int32_t *buffer, int len, void *priv) { - sb_t *sb = (sb_t *)p; - sb_ct1745_mixer_t *mixer = &sb->mixer_sb16; - int c, dsp_rec_pos = sb->dsp.record_pos_write; - int c_emu8k, c_record; - int32_t in_l, in_r; - double out_l = 0.0, out_r = 0.0; - double bass_treble; + sb_t *sb = (sb_t *) priv; + const sb_ct1745_mixer_t *mixer = &sb->mixer_sb16; + int dsp_rec_pos = sb->dsp.record_pos_write; + int c_emu8k = 0; + int c_record; + int32_t in_l; + int32_t in_r; + double out_l = 0.0; + double out_r = 0.0; + double bass_treble; + const int32_t *opl_buf = NULL; if (sb->opl_enabled) - opl3_update(&sb->opl); + opl_buf = sb->opl.update(sb->opl.priv); if (sb->dsp.sb_type > SB16) - emu8k_update(&sb->emu8k); + emu8k_update(&sb->emu8k); sb_dsp_update(&sb->dsp); - for (c = 0; c < len * 2; c += 2) { - out_l = 0.0, out_r = 0.0; + for (int c = 0; c < len * 2; c += 2) { + out_l = 0.0; + out_r = 0.0; - if (sb->dsp.sb_type > SB16) - c_emu8k = ((((c / 2) * 44100) / 48000) * 2); + if (sb->dsp.sb_type > SB16) + c_emu8k = ((((c / 2) * FREQ_44100) / SOUND_FREQ) * 2); - if (sb->opl_enabled) { - out_l = ((double) sb->opl.buffer[c ]) * mixer->fm_l * 0.7171630859375; - out_r = ((double) sb->opl.buffer[c + 1]) * mixer->fm_r * 0.7171630859375; - } + if (sb->opl_enabled) { + out_l = ((double) opl_buf[c]) * mixer->fm_l * 0.7171630859375; + out_r = ((double) opl_buf[c + 1]) * mixer->fm_r * 0.7171630859375; + } - if (sb->dsp.sb_type > SB16) { - out_l += (((double) sb->emu8k.buffer[c_emu8k]) * mixer->fm_l); - out_r += (((double) sb->emu8k.buffer[c_emu8k + 1]) * mixer->fm_r); - } + if (sb->dsp.sb_type > SB16) { + out_l += (((double) sb->emu8k.buffer[c_emu8k]) * mixer->fm_l); + out_r += (((double) sb->emu8k.buffer[c_emu8k + 1]) * mixer->fm_r); + } - /* TODO: Multi-recording mic with agc/+20db, CD, and line in with channel inversion */ - in_l = (mixer->input_selector_left & INPUT_MIDI_L) ? ((int32_t) out_l) : - 0 + (mixer->input_selector_left & INPUT_MIDI_R) ? ((int32_t) out_r) : 0; - in_r = (mixer->input_selector_right & INPUT_MIDI_L) ? ((int32_t) out_l) : - 0 + (mixer->input_selector_right & INPUT_MIDI_R) ? ((int32_t) out_r) : 0; + /* TODO: Multi-recording mic with agc/+20db, CD, and line in with channel inversion */ + in_l = (mixer->input_selector_left & INPUT_MIDI_L) ? ((int32_t) out_l) : 0 + (mixer->input_selector_left & INPUT_MIDI_R) ? ((int32_t) out_r) + : 0; + in_r = (mixer->input_selector_right & INPUT_MIDI_L) ? ((int32_t) out_l) : 0 + (mixer->input_selector_right & INPUT_MIDI_R) ? ((int32_t) out_r) + : 0; - /* We divide by 3 to get the volume down to normal. */ - out_l += (low_fir_sb16(0, 0, (double) sb->dsp.buffer[c]) * mixer->voice_l) / 3.0; - out_r += (low_fir_sb16(0, 1, (double) sb->dsp.buffer[c + 1]) * mixer->voice_r) / 3.0; + if (mixer->output_filter) { + /* We divide by 3 to get the volume down to normal. */ + out_l += (low_fir_sb16(0, 0, (double) sb->dsp.buffer[c]) * mixer->voice_l) / 3.0; + out_r += (low_fir_sb16(0, 1, (double) sb->dsp.buffer[c + 1]) * mixer->voice_r) / 3.0; + } else { + out_l += (((double) sb->dsp.buffer[c]) * mixer->voice_l) / 3.0; + out_r += (((double) sb->dsp.buffer[c + 1]) * mixer->voice_r) / 3.0; + } - out_l *= mixer->master_l; - out_r *= mixer->master_r; + out_l *= mixer->master_l; + out_r *= mixer->master_r; - /* This is not exactly how one does bass/treble controls, but the end result is like it. - A better implementation would reduce the CPU usage. */ - if (mixer->bass_l != 8) { - bass_treble = sb_bass_treble_4bits[mixer->bass_l]; + /* This is not exactly how one does bass/treble controls, but the end result is like it. + A better implementation would reduce the CPU usage. */ + if (mixer->bass_l != 8) { + bass_treble = sb_bass_treble_4bits[mixer->bass_l]; - if (mixer->bass_l > 8) - out_l += (low_iir(0, 0, out_l) * bass_treble); - else if (mixer->bass_l < 8) - out_l = ((out_l) * bass_treble + low_cut_iir(0, 0, out_l) * (1.0 - bass_treble)); - } + if (mixer->bass_l > 8) + out_l += (low_iir(0, 0, out_l) * bass_treble); + else if (mixer->bass_l < 8) + out_l = (out_l *bass_treble + low_cut_iir(0, 0, out_l) * (1.0 - bass_treble)); + } - if (mixer->bass_r != 8) { - bass_treble = sb_bass_treble_4bits[mixer->bass_r]; + if (mixer->bass_r != 8) { + bass_treble = sb_bass_treble_4bits[mixer->bass_r]; - if (mixer->bass_r > 8) - out_r += (low_iir(0, 1, out_r) * bass_treble); - else if (mixer->bass_r < 8) - out_r = ((out_r) * bass_treble + low_cut_iir(0, 1, out_r) * (1.0 - bass_treble)); - } + if (mixer->bass_r > 8) + out_r += (low_iir(0, 1, out_r) * bass_treble); + else if (mixer->bass_r < 8) + out_r = (out_r *bass_treble + low_cut_iir(0, 1, out_r) * (1.0 - bass_treble)); + } - if (mixer->treble_l != 8) { - bass_treble = sb_bass_treble_4bits[mixer->treble_l]; + if (mixer->treble_l != 8) { + bass_treble = sb_bass_treble_4bits[mixer->treble_l]; - if (mixer->treble_l > 8) - out_l += (high_iir(0, 0, out_l) * bass_treble); - else if (mixer->treble_l < 8) - out_l = ((out_l) * bass_treble + high_cut_iir(0, 0, out_l) * (1.0 - bass_treble)); - } + if (mixer->treble_l > 8) + out_l += (high_iir(0, 0, out_l) * bass_treble); + else if (mixer->treble_l < 8) + out_l = (out_l *bass_treble + high_cut_iir(0, 0, out_l) * (1.0 - bass_treble)); + } - if (mixer->treble_r != 8) { - bass_treble = sb_bass_treble_4bits[mixer->treble_r]; + if (mixer->treble_r != 8) { + bass_treble = sb_bass_treble_4bits[mixer->treble_r]; - if (mixer->treble_r > 8) - out_r += (high_iir(0, 1, out_r) * bass_treble); - else if (mixer->treble_r < 8) - out_r = ((out_l) * bass_treble + high_cut_iir(0, 1, out_r) * (1.0 - bass_treble)); - } + if (mixer->treble_r > 8) + out_r += (high_iir(0, 1, out_r) * bass_treble); + else if (mixer->treble_r < 8) + out_r = (out_l *bass_treble + high_cut_iir(0, 1, out_r) * (1.0 - bass_treble)); + } - if (sb->dsp.sb_enable_i) { - c_record = dsp_rec_pos + ((c * sb->dsp.sb_freq) / 48000); - in_l <<= mixer->input_gain_L; - in_r <<= mixer->input_gain_R; + if (sb->dsp.sb_enable_i) { + c_record = dsp_rec_pos + ((c * sb->dsp.sb_freq) / SOUND_FREQ); + in_l <<= mixer->input_gain_L; + in_r <<= mixer->input_gain_R; - /* Clip signal */ - if (in_l < -32768) - in_l = -32768; - else if (in_l > 32767) - in_l = 32767; + /* Clip signal */ + if (in_l < -32768) + in_l = -32768; + else if (in_l > 32767) + in_l = 32767; - if (in_r < -32768) - in_r = -32768; - else if (in_r > 32767) - in_r = 32767; + if (in_r < -32768) + in_r = -32768; + else if (in_r > 32767) + in_r = 32767; - sb->dsp.record_buffer[c_record & 0xffff] = in_l; - sb->dsp.record_buffer[(c_record+1) & 0xffff] = in_r; - } + sb->dsp.record_buffer[c_record & 0xffff] = in_l; + sb->dsp.record_buffer[(c_record + 1) & 0xffff] = in_r; + } - buffer[c] += (int32_t) (out_l * mixer->output_gain_L); - buffer[c + 1] += (int32_t) (out_r * mixer->output_gain_R); + buffer[c] += (int32_t) (out_l * mixer->output_gain_L); + buffer[c + 1] += (int32_t) (out_r * mixer->output_gain_R); } sb->dsp.record_pos_write += ((len * sb->dsp.sb_freq) / 24000); @@ -459,552 +470,719 @@ sb_get_buffer_sb16_awe32(int32_t *buffer, int len, void *p) sb->pos = 0; if (sb->opl_enabled) - sb->opl.pos = 0; + sb->opl.reset_buffer(sb->opl.priv); sb->dsp.pos = 0; if (sb->dsp.sb_type > SB16) - sb->emu8k.pos = 0; + sb->emu8k.pos = 0; } - -static void -sb16_awe32_filter_cd_audio(int channel, double *buffer, void *p) +void +sb16_awe32_filter_cd_audio(int channel, double *buffer, void *priv) { - sb_t *sb = (sb_t *)p; - sb_ct1745_mixer_t *mixer = &sb->mixer_sb16; - double c; - double cd = channel ? mixer->cd_r : mixer->cd_l /* / 3.0 */; - double master = channel ? mixer->master_r : mixer->master_l; - int32_t bass = channel ? mixer->bass_r : mixer->bass_l; - int32_t treble = channel ? mixer->treble_r : mixer->treble_l; - double bass_treble; - double output_gain = (channel ? mixer->output_gain_R : mixer->output_gain_L); + const sb_t *sb = (sb_t *) priv; + const sb_ct1745_mixer_t *mixer = &sb->mixer_sb16; + double c; + double cd = channel ? mixer->cd_r : mixer->cd_l /* / 3.0 */; + double master = channel ? mixer->master_r : mixer->master_l; + int32_t bass = channel ? mixer->bass_r : mixer->bass_l; + int32_t treble = channel ? mixer->treble_r : mixer->treble_l; + double bass_treble; + double output_gain = (channel ? mixer->output_gain_R : mixer->output_gain_L); - c = (low_fir_sb16(1, channel, *buffer) * cd) / 3.0; + if (mixer->output_filter) + c = (low_fir_sb16(1, channel, *buffer) * cd) / 3.0; + else + c = ((*buffer) * cd) / 3.0; c *= master; /* This is not exactly how one does bass/treble controls, but the end result is like it. A better implementation would reduce the CPU usage. */ if (bass != 8) { - bass_treble = sb_bass_treble_4bits[bass]; + bass_treble = sb_bass_treble_4bits[bass]; - if (bass > 8) - c += (low_iir(1, channel, c) * bass_treble); - else if (bass < 8) - c = (c * bass_treble + low_cut_iir(1, channel, c) * (1.0 - bass_treble)); + if (bass > 8) + c += (low_iir(1, channel, c) * bass_treble); + else if (bass < 8) + c = (c * bass_treble + low_cut_iir(1, channel, c) * (1.0 - bass_treble)); } if (treble != 8) { - bass_treble = sb_bass_treble_4bits[treble]; + bass_treble = sb_bass_treble_4bits[treble]; - if (treble > 8) - c += (high_iir(1, channel, c) * bass_treble); - else if (treble < 8) - c = (c * bass_treble + high_cut_iir(1, channel, c) * (1.0 - bass_treble)); + if (treble > 8) + c += (high_iir(1, channel, c) * bass_treble); + else if (treble < 8) + c = (c * bass_treble + high_cut_iir(1, channel, c) * (1.0 - bass_treble)); } *buffer = c * output_gain; } +void +sb16_awe32_filter_pc_speaker(int channel, double *buffer, void *priv) +{ + const sb_t *sb = (sb_t *) priv; + const sb_ct1745_mixer_t *mixer = &sb->mixer_sb16; + double c; + double spk = mixer->speaker; + double master = channel ? mixer->master_r : mixer->master_l; + int32_t bass = channel ? mixer->bass_r : mixer->bass_l; + int32_t treble = channel ? mixer->treble_r : mixer->treble_l; + double bass_treble; + double output_gain = (channel ? mixer->output_gain_R : mixer->output_gain_L); + + if (mixer->output_filter) + c = (low_fir_sb16(2, channel, *buffer) * spk) / 3.0; + else + c = ((*buffer) * spk) / 3.0; + c *= master; + + /* This is not exactly how one does bass/treble controls, but the end result is like it. + A better implementation would reduce the CPU usage. */ + if (bass != 8) { + bass_treble = sb_bass_treble_4bits[bass]; + + if (bass > 8) + c += (low_iir(2, channel, c) * bass_treble); + else if (bass < 8) + c = (c * bass_treble + low_cut_iir(1, channel, c) * (1.0 - bass_treble)); + } + + if (treble != 8) { + bass_treble = sb_bass_treble_4bits[treble]; + + if (treble > 8) + c += (high_iir(2, channel, c) * bass_treble); + else if (treble < 8) + c = (c * bass_treble + high_cut_iir(1, channel, c) * (1.0 - bass_treble)); + } + + *buffer = c * output_gain; +} void -sb_ct1335_mixer_write(uint16_t addr, uint8_t val, void *p) +sb_ct1335_mixer_write(uint16_t addr, uint8_t val, void *priv) { - sb_t *sb = (sb_t *)p; + sb_t *sb = (sb_t *) priv; sb_ct1335_mixer_t *mixer = &sb->mixer_sb2; if (!(addr & 1)) { - mixer->index = val; - mixer->regs[0x01] = val; + mixer->index = val; + mixer->regs[0x01] = val; } else { - if (mixer->index == 0) { - /* Reset */ - mixer->regs[0x02] = mixer->regs[0x06] = 0x08; - mixer->regs[0x08] = 0x00; - /* Changed default from -46dB to 0dB*/ - mixer->regs[0x0a] = 0x06; - } else { - mixer->regs[mixer->index] = val; - switch (mixer->index) { - case 0x00: case 0x02: case 0x06: case 0x08: case 0x0a: - break; + if (mixer->index == 0) { + /* Reset */ + mixer->regs[0x02] = mixer->regs[0x06] = 0x08; + mixer->regs[0x08] = 0x00; + /* Changed default from -46dB to 0dB*/ + mixer->regs[0x0a] = 0x06; + } else { + mixer->regs[mixer->index] = val; + switch (mixer->index) { + case 0x00: + case 0x02: + case 0x06: + case 0x08: + case 0x0a: + break; - default: - sb_log("sb_ct1335: Unknown register WRITE: %02X\t%02X\n", mixer->index, mixer->regs[mixer->index]); - break; - } - } + default: + sb_log("sb_ct1335: Unknown register WRITE: %02X\t%02X\n", mixer->index, mixer->regs[mixer->index]); + break; + } + } - mixer->master = sb_att_4dbstep_3bits[(mixer->regs[0x02] >> 1) & 0x7] / 32768.0; - mixer->fm = sb_att_4dbstep_3bits[(mixer->regs[0x06] >> 1) & 0x7] / 32768.0; - mixer->cd = sb_att_4dbstep_3bits[(mixer->regs[0x08] >> 1) & 0x7] / 32768.0; - mixer->voice = sb_att_7dbstep_2bits[(mixer->regs[0x0a] >> 1) & 0x3] / 32768.0; + mixer->master = sb_att_4dbstep_3bits[(mixer->regs[0x02] >> 1) & 0x7] / 32768.0; + mixer->fm = sb_att_4dbstep_3bits[(mixer->regs[0x06] >> 1) & 0x7] / 32768.0; + mixer->cd = sb_att_4dbstep_3bits[(mixer->regs[0x08] >> 1) & 0x7] / 32768.0; + mixer->voice = sb_att_7dbstep_2bits[(mixer->regs[0x0a] >> 1) & 0x3] / 32768.0; } } - uint8_t -sb_ct1335_mixer_read(uint16_t addr, void *p) +sb_ct1335_mixer_read(uint16_t addr, void *priv) { - sb_t *sb = (sb_t *)p; - sb_ct1335_mixer_t *mixer = &sb->mixer_sb2; + const sb_t *sb = (sb_t *) priv; + const sb_ct1335_mixer_t *mixer = &sb->mixer_sb2; if (!(addr & 1)) - return mixer->index; + return mixer->index; switch (mixer->index) { - case 0x00: case 0x02: case 0x06: case 0x08: case 0x0A: - return mixer->regs[mixer->index]; - default: - sb_log("sb_ct1335: Unknown register READ: %02X\t%02X\n", mixer->index, mixer->regs[mixer->index]); - break; + case 0x00: + case 0x02: + case 0x06: + case 0x08: + case 0x0A: + return mixer->regs[mixer->index]; + default: + sb_log("sb_ct1335: Unknown register READ: %02X\t%02X\n", mixer->index, mixer->regs[mixer->index]); + break; } return 0xff; } - void -sb_ct1335_mixer_reset(sb_t* sb) +sb_ct1335_mixer_reset(sb_t *sb) { sb_ct1335_mixer_write(0x254, 0, sb); sb_ct1335_mixer_write(0x255, 0, sb); } - void -sb_ct1345_mixer_write(uint16_t addr, uint8_t val, void *p) +sb_ct1345_mixer_write(uint16_t addr, uint8_t val, void *priv) { - sb_t *sb = (sb_t *)p; + sb_t *sb = (sb_t *) priv; sb_ct1345_mixer_t *mixer = &sb->mixer_sbpro; if (!(addr & 1)) { - mixer->index = val; - mixer->regs[0x01] = val; + mixer->index = val; + mixer->regs[0x01] = val; } else { - if (mixer->index == 0) { - /* Reset */ - mixer->regs[0x0a] = mixer->regs[0x0c] = 0x00; - mixer->regs[0x0e] = 0x00; - /* Changed default from -11dB to 0dB */ - mixer->regs[0x04] = mixer->regs[0x22] = 0xee; - mixer->regs[0x26] = mixer->regs[0x28] = 0xee; - mixer->regs[0x2e] = 0x00; - sb_dsp_set_stereo(&sb->dsp, mixer->regs[0x0e] & 2); - } else { - mixer->regs[mixer->index] = val; + if (mixer->index == 0) { + /* Reset */ + mixer->regs[0x0a] = mixer->regs[0x0c] = 0x00; + mixer->regs[0x0e] = 0x00; + /* Changed default from -11dB to 0dB */ + mixer->regs[0x04] = mixer->regs[0x22] = 0xee; + mixer->regs[0x26] = mixer->regs[0x28] = 0xee; + mixer->regs[0x2e] = 0x00; + sb_dsp_set_stereo(&sb->dsp, mixer->regs[0x0e] & 2); + } else { + mixer->regs[mixer->index] = val; - switch (mixer->index) { - /* Compatibility: chain registers 0x02 and 0x22 as well as 0x06 and 0x26 */ - case 0x02: case 0x06: case 0x08: - mixer->regs[mixer->index + 0x20] = ((val & 0xe) << 4) | (val&0xe); - break; + switch (mixer->index) { + /* Compatibility: chain registers 0x02 and 0x22 as well as 0x06 and 0x26 */ + case 0x02: + case 0x06: + case 0x08: + mixer->regs[mixer->index + 0x20] = ((val & 0xe) << 4) | (val & 0xe); + break; - case 0x22: case 0x26: case 0x28: - mixer->regs[mixer->index - 0x20] = (val & 0xe); - break; + case 0x22: + case 0x26: + case 0x28: + mixer->regs[mixer->index - 0x20] = (val & 0xe); + break; - /* More compatibility: - SoundBlaster Pro selects register 020h for 030h, 022h for 032h, - 026h for 036h, and 028h for 038h. */ - case 0x30: case 0x32: case 0x36: case 0x38: - mixer->regs[mixer->index - 0x10] = (val & 0xee); - break; + /* More compatibility: + SoundBlaster Pro selects register 020h for 030h, 022h for 032h, + 026h for 036h, and 028h for 038h. */ + case 0x30: + case 0x32: + case 0x36: + case 0x38: + mixer->regs[mixer->index - 0x10] = (val & 0xee); + break; - case 0x00: case 0x04: case 0x0a: case 0x0c: case 0x0e: - case 0x2e: - break; + case 0x00: + case 0x04: + case 0x0a: + case 0x0c: + case 0x0e: + case 0x2e: + break; - default: - sb_log("sb_ct1345: Unknown register WRITE: %02X\t%02X\n", mixer->index, mixer->regs[mixer->index]); - break; - } - } + default: + sb_log("sb_ct1345: Unknown register WRITE: %02X\t%02X\n", mixer->index, mixer->regs[mixer->index]); + break; + } + } - mixer->voice_l = sb_att_4dbstep_3bits[(mixer->regs[0x04] >> 5) & 0x7] / 32768.0; - mixer->voice_r = sb_att_4dbstep_3bits[(mixer->regs[0x04] >> 1) & 0x7] / 32768.0; - mixer->master_l = sb_att_4dbstep_3bits[(mixer->regs[0x22] >> 5) & 0x7] / 32768.0; - mixer->master_r = sb_att_4dbstep_3bits[(mixer->regs[0x22] >> 1) & 0x7] / 32768.0; - mixer->fm_l = sb_att_4dbstep_3bits[(mixer->regs[0x26] >> 5) & 0x7] / 32768.0; - mixer->fm_r = sb_att_4dbstep_3bits[(mixer->regs[0x26] >> 1) & 0x7] / 32768.0; - mixer->cd_l = sb_att_4dbstep_3bits[(mixer->regs[0x28] >> 5) & 0x7] / 32768.0; - mixer->cd_r = sb_att_4dbstep_3bits[(mixer->regs[0x28] >> 1) & 0x7] / 32768.0; - mixer->line_l = sb_att_4dbstep_3bits[(mixer->regs[0x2e] >> 5) & 0x7] / 32768.0; - mixer->line_r = sb_att_4dbstep_3bits[(mixer->regs[0x2e] >> 1) & 0x7] / 32768.0; + mixer->voice_l = sb_att_4dbstep_3bits[(mixer->regs[0x04] >> 5) & 0x7] / 32768.0; + mixer->voice_r = sb_att_4dbstep_3bits[(mixer->regs[0x04] >> 1) & 0x7] / 32768.0; + mixer->master_l = sb_att_4dbstep_3bits[(mixer->regs[0x22] >> 5) & 0x7] / 32768.0; + mixer->master_r = sb_att_4dbstep_3bits[(mixer->regs[0x22] >> 1) & 0x7] / 32768.0; + mixer->fm_l = sb_att_4dbstep_3bits[(mixer->regs[0x26] >> 5) & 0x7] / 32768.0; + mixer->fm_r = sb_att_4dbstep_3bits[(mixer->regs[0x26] >> 1) & 0x7] / 32768.0; + mixer->cd_l = sb_att_4dbstep_3bits[(mixer->regs[0x28] >> 5) & 0x7] / 32768.0; + mixer->cd_r = sb_att_4dbstep_3bits[(mixer->regs[0x28] >> 1) & 0x7] / 32768.0; + mixer->line_l = sb_att_4dbstep_3bits[(mixer->regs[0x2e] >> 5) & 0x7] / 32768.0; + mixer->line_r = sb_att_4dbstep_3bits[(mixer->regs[0x2e] >> 1) & 0x7] / 32768.0; - mixer->mic = sb_att_7dbstep_2bits[(mixer->regs[0x0a] >> 1) & 0x3] / 32768.0; + mixer->mic = sb_att_7dbstep_2bits[(mixer->regs[0x0a] >> 1) & 0x3] / 32768.0; - mixer->output_filter = !(mixer->regs[0xe] & 0x20); - mixer->input_filter = !(mixer->regs[0xc] & 0x20); - mixer->in_filter_freq = ((mixer->regs[0xc] & 0x8) == 0) ? 3200 : 8800; - mixer->stereo = mixer->regs[0xe] & 2; - if (mixer->index == 0xe) - sb_dsp_set_stereo(&sb->dsp, val & 2); + mixer->output_filter = !(mixer->regs[0xe] & 0x20); + mixer->input_filter = !(mixer->regs[0xc] & 0x20); + mixer->in_filter_freq = ((mixer->regs[0xc] & 0x8) == 0) ? 3200 : 8800; + mixer->stereo = mixer->regs[0xe] & 2; + if (mixer->index == 0xe) + sb_dsp_set_stereo(&sb->dsp, val & 2); - switch ((mixer->regs[0xc] & 6)) { - case 2: - mixer->input_selector = INPUT_CD_L | INPUT_CD_R; - break; - case 6: - mixer->input_selector = INPUT_LINE_L | INPUT_LINE_R; - break; - default: - mixer->input_selector = INPUT_MIC; - break; - } + switch (mixer->regs[0xc] & 6) { + case 2: + mixer->input_selector = INPUT_CD_L | INPUT_CD_R; + break; + case 6: + mixer->input_selector = INPUT_LINE_L | INPUT_LINE_R; + break; + default: + mixer->input_selector = INPUT_MIC; + break; + } - /* TODO: pcspeaker volume? Or is it not worth? */ + /* TODO: pcspeaker volume? Or is it not worth? */ } } - uint8_t -sb_ct1345_mixer_read(uint16_t addr, void *p) +sb_ct1345_mixer_read(uint16_t addr, void *priv) { - sb_t *sb = (sb_t *)p; - sb_ct1345_mixer_t *mixer = &sb->mixer_sbpro; + const sb_t *sb = (sb_t *) priv; + const sb_ct1345_mixer_t *mixer = &sb->mixer_sbpro; if (!(addr & 1)) - return mixer->index; + return mixer->index; switch (mixer->index) { - case 0x00: case 0x04: case 0x0a: case 0x0c: case 0x0e: - case 0x22: case 0x26: case 0x28: case 0x2e: case 0x02: case 0x06: - case 0x30: case 0x32: case 0x36: case 0x38: - return mixer->regs[mixer->index]; + case 0x00: + case 0x04: + case 0x0a: + case 0x0c: + case 0x0e: + case 0x22: + case 0x26: + case 0x28: + case 0x2e: + case 0x02: + case 0x06: + case 0x30: + case 0x32: + case 0x36: + case 0x38: + return mixer->regs[mixer->index]; - default: - sb_log("sb_ct1345: Unknown register READ: %02X\t%02X\n", mixer->index, mixer->regs[mixer->index]); - break; + default: + sb_log("sb_ct1345: Unknown register READ: %02X\t%02X\n", mixer->index, mixer->regs[mixer->index]); + break; } return 0xff; } - void -sb_ct1345_mixer_reset(sb_t* sb) +sb_ct1345_mixer_reset(sb_t *sb) { sb_ct1345_mixer_write(4, 0, sb); sb_ct1345_mixer_write(5, 0, sb); } - -static void -sb_ct1745_mixer_write(uint16_t addr, uint8_t val, void *p) +void +sb_ct1745_mixer_write(uint16_t addr, uint8_t val, void *priv) { - sb_t *sb = (sb_t *) p; + sb_t *sb = (sb_t *) priv; sb_ct1745_mixer_t *mixer = &sb->mixer_sb16; if (!(addr & 1)) - mixer->index = val; + mixer->index = val; else { - /* DESCRIPTION: - Contains previously selected register value. Mixer Data Register value. - NOTES: - SoundBlaster 16 sets bit 7 if previous mixer index invalid. - Status bytes initially 080h on startup for all but level bytes (SB16). */ + /* DESCRIPTION: + Contains previously selected register value. Mixer Data Register value. + NOTES: + SoundBlaster 16 sets bit 7 if previous mixer index invalid. + Status bytes initially 080h on startup for all but level bytes (SB16). */ - if (mixer->index == 0) { - /* Reset: Changed defaults from -14dB to 0dB */ + sb_log("CT1745: [W] %02X = %02X\n", mixer->index, val); - mixer->regs[0x30] = mixer->regs[0x31] = 0xf8; - mixer->regs[0x32] = mixer->regs[0x33] = 0xf8; - mixer->regs[0x34] = mixer->regs[0x35] = 0xf8; - mixer->regs[0x36] = mixer->regs[0x37] = 0xf8; - mixer->regs[0x38] = mixer->regs[0x39] = 0x00; + if (mixer->index == 0) { + /* Reset: Changed defaults from -14dB to 0dB */ - mixer->regs[0x3a] = mixer->regs[0x3b] = 0x00; + mixer->regs[0x30] = mixer->regs[0x31] = 0xf8; + mixer->regs[0x32] = mixer->regs[0x33] = 0xf8; + mixer->regs[0x34] = mixer->regs[0x35] = 0xf8; + mixer->regs[0x36] = mixer->regs[0x37] = 0xf8; + mixer->regs[0x38] = mixer->regs[0x39] = 0x00; - mixer->regs[0x3c] = (OUTPUT_MIC | OUTPUT_CD_R | OUTPUT_CD_L | OUTPUT_LINE_R | OUTPUT_LINE_L); - mixer->regs[0x3d] = (INPUT_MIC | INPUT_CD_L | INPUT_LINE_L | INPUT_MIDI_L); - mixer->regs[0x3e] = (INPUT_MIC | INPUT_CD_R | INPUT_LINE_R | INPUT_MIDI_R); + mixer->regs[0x3a] = mixer->regs[0x3b] = 0x00; - mixer->regs[0x3f] = mixer->regs[0x40] = 0x00; - mixer->regs[0x41] = mixer->regs[0x42] = 0x00; + mixer->regs[0x3c] = (OUTPUT_MIC | OUTPUT_CD_R | OUTPUT_CD_L | OUTPUT_LINE_R | OUTPUT_LINE_L); + mixer->regs[0x3d] = (INPUT_MIC | INPUT_CD_L | INPUT_LINE_L | INPUT_MIDI_L); + mixer->regs[0x3e] = (INPUT_MIC | INPUT_CD_R | INPUT_LINE_R | INPUT_MIDI_R); - mixer->regs[0x44] = mixer->regs[0x45] = 0x80; - mixer->regs[0x46] = mixer->regs[0x47] = 0x80; + mixer->regs[0x3f] = mixer->regs[0x40] = 0x00; + mixer->regs[0x41] = mixer->regs[0x42] = 0x00; - mixer->regs[0x43] = 0x00; + mixer->regs[0x44] = mixer->regs[0x45] = 0x80; + mixer->regs[0x46] = mixer->regs[0x47] = 0x80; - mixer->regs[0x83] = 0xff; - sb->dsp.sb_irqm8 = 0; - sb->dsp.sb_irqm16 = 0; - sb->dsp.sb_irqm401 = 0; - } else - mixer->regs[mixer->index] = val; + /* 0x43 = Mic AGC (Automatic Gain Control?) according to Linux's sb.h. + NSC LM4560 datasheet: Bit 0: 1 = Enable, 0 = Disable; + Another source says this: Bit 0: 0 = AGC on (default), 1 = Fixed gain of 20 dB. */ + mixer->regs[0x43] = 0x00; - switch (mixer->index) { - /* SB1/2 compatibility? */ - case 0x02: - mixer->regs[0x30] = ((mixer->regs[0x02] & 0xf) << 4) | 0x8; - mixer->regs[0x31] = ((mixer->regs[0x02] & 0xf) << 4) | 0x8; - break; - case 0x06: - mixer->regs[0x34] = ((mixer->regs[0x06] & 0xf) << 4) | 0x8; - mixer->regs[0x35] = ((mixer->regs[0x06] & 0xf) << 4) | 0x8; - break; - case 0x08: - mixer->regs[0x36] = ((mixer->regs[0x08] & 0xf) << 4) | 0x8; - mixer->regs[0x37] = ((mixer->regs[0x08] & 0xf) << 4) | 0x8; - break; - /* SBPro compatibility. Copy values to sb16 registers. */ - case 0x22: - mixer->regs[0x30] = (mixer->regs[0x22] & 0xf0) | 0x8; - mixer->regs[0x31] = ((mixer->regs[0x22] & 0xf) << 4) | 0x8; - break; - case 0x04: - mixer->regs[0x32] = (mixer->regs[0x04] & 0xf0) | 0x8; - mixer->regs[0x33] = ((mixer->regs[0x04] & 0xf) << 4) | 0x8; - break; - case 0x26: - mixer->regs[0x34] = (mixer->regs[0x26] & 0xf0) | 0x8; - mixer->regs[0x35] = ((mixer->regs[0x26] & 0xf) << 4) | 0x8; - break; - case 0x28: - mixer->regs[0x36] = (mixer->regs[0x28] & 0xf0) | 0x8; - mixer->regs[0x37] = ((mixer->regs[0x28] & 0xf) << 4) | 0x8; - break; - case 0x0A: - mixer->regs[0x3a] = (mixer->regs[0x0a] << 5) | 0x18; - break; - case 0x2e: - mixer->regs[0x38] = (mixer->regs[0x2e] & 0xf0) | 0x8; - mixer->regs[0x39] = ((mixer->regs[0x2e] & 0xf) << 4) | 0x8; - break; + mixer->regs[0x49] = mixer->regs[0x4a] = 0x80; - /* (DSP 4.xx feature): - The Interrupt Setup register, addressed as register 80h on the Mixer register map, - is used to configure or determine the Interrupt request line. - The DMA setup register, addressed as register 81h on the Mixer register map, is - used to configure or determine the DMA channels. + mixer->regs[0x83] = 0xff; + sb->dsp.sb_irqm8 = 0; + sb->dsp.sb_irqm16 = 0; + sb->dsp.sb_irqm401 = 0; - Note: Registers 80h and 81h are Read-only for PnP boards. */ - case 0x80: - if (val & 0x01) - sb_dsp_setirq(&sb->dsp, 2); - if (val & 0x02) - sb_dsp_setirq(&sb->dsp, 5); - if (val & 0x04) - sb_dsp_setirq(&sb->dsp, 7); - if (val & 0x08) - sb_dsp_setirq(&sb->dsp, 10); - break; + mixer->regs[0xfd] = 0x10; + mixer->regs[0xfe] = 0x06; - case 0x81: - /* The documentation is confusing. sounds as if multple dma8 channels could - be set. */ - if (val & 0x01) - sb_dsp_setdma8(&sb->dsp, 0); - if (val & 0x02) - sb_dsp_setdma8(&sb->dsp, 1); - if (val & 0x08) - sb_dsp_setdma8(&sb->dsp, 3); - if (val & 0x20) - sb_dsp_setdma16(&sb->dsp, 5); - if (val & 0x40) - sb_dsp_setdma16(&sb->dsp, 6); - if (val & 0x80) - sb_dsp_setdma16(&sb->dsp, 7); - break; + mixer->regs[0xff] = sb->dsp.sb_16_dma_supported ? 0x05 : 0x03; - case 0x83: - /* Interrupt mask. */ - sb_update_mask(&sb->dsp, !(val & 0x01), !(val & 0x02), !(val & 0x04)); - break; + sb_dsp_setdma16_enabled(&sb->dsp, 0x01); + sb_dsp_setdma16_translate(&sb->dsp, mixer->regs[0xff] & 0x02); + } else + mixer->regs[mixer->index] = val; - case 0x84: - /* MPU Control register, per the Linux source code. */ - if (sb->mpu != NULL) { - if ((val & 0x06) == 0x00) - mpu401_change_addr(sb->mpu, 0x330); - else if ((val & 0x06) == 0x04) - mpu401_change_addr(sb->mpu, 0x300); - else if ((val & 0x06) == 0x02) - mpu401_change_addr(sb->mpu, 0); - } - break; - } + switch (mixer->index) { + /* SB1/2 compatibility? */ + case 0x02: + mixer->regs[0x30] = ((mixer->regs[0x02] & 0xf) << 4) | 0x8; + mixer->regs[0x31] = ((mixer->regs[0x02] & 0xf) << 4) | 0x8; + break; + case 0x06: + mixer->regs[0x34] = ((mixer->regs[0x06] & 0xf) << 4) | 0x8; + mixer->regs[0x35] = ((mixer->regs[0x06] & 0xf) << 4) | 0x8; + break; + case 0x08: + mixer->regs[0x36] = ((mixer->regs[0x08] & 0xf) << 4) | 0x8; + mixer->regs[0x37] = ((mixer->regs[0x08] & 0xf) << 4) | 0x8; + break; + /* SBPro compatibility. Copy values to sb16 registers. */ + case 0x22: + mixer->regs[0x30] = (mixer->regs[0x22] & 0xf0) | 0x8; + mixer->regs[0x31] = ((mixer->regs[0x22] & 0xf) << 4) | 0x8; + break; + case 0x04: + mixer->regs[0x32] = (mixer->regs[0x04] & 0xf0) | 0x8; + mixer->regs[0x33] = ((mixer->regs[0x04] & 0xf) << 4) | 0x8; + break; + case 0x26: + mixer->regs[0x34] = (mixer->regs[0x26] & 0xf0) | 0x8; + mixer->regs[0x35] = ((mixer->regs[0x26] & 0xf) << 4) | 0x8; + break; + case 0x28: + mixer->regs[0x36] = (mixer->regs[0x28] & 0xf0) | 0x8; + mixer->regs[0x37] = ((mixer->regs[0x28] & 0xf) << 4) | 0x8; + break; + case 0x0A: + mixer->regs[0x3a] = (mixer->regs[0x0a] << 5) | 0x18; + break; + case 0x2e: + mixer->regs[0x38] = (mixer->regs[0x2e] & 0xf0) | 0x8; + mixer->regs[0x39] = ((mixer->regs[0x2e] & 0xf) << 4) | 0x8; + break; - mixer->output_selector = mixer->regs[0x3c]; - mixer->input_selector_left = mixer->regs[0x3d]; - mixer->input_selector_right = mixer->regs[0x3e]; + /* (DSP 4.xx feature): + The Interrupt Setup register, addressed as register 80h on the Mixer register map, + is used to configure or determine the Interrupt request line. + The DMA setup register, addressed as register 81h on the Mixer register map, is + used to configure or determine the DMA channels. - mixer->master_l = sb_att_2dbstep_5bits[mixer->regs[0x30] >> 3] / 32768.0; - mixer->master_r = sb_att_2dbstep_5bits[mixer->regs[0x31] >> 3] / 32768.0; - mixer->voice_l = sb_att_2dbstep_5bits[mixer->regs[0x32] >> 3] / 32768.0; - mixer->voice_r = sb_att_2dbstep_5bits[mixer->regs[0x33] >> 3] / 32768.0; - mixer->fm_l = sb_att_2dbstep_5bits[mixer->regs[0x34] >> 3] / 32768.0; - mixer->fm_r = sb_att_2dbstep_5bits[mixer->regs[0x35] >> 3] / 32768.0; - mixer->cd_l = (mixer->output_selector & OUTPUT_CD_L) ? (sb_att_2dbstep_5bits[mixer->regs[0x36] >> 3] / 32768.0): 0.0; - mixer->cd_r = (mixer->output_selector & OUTPUT_CD_R) ? (sb_att_2dbstep_5bits[mixer->regs[0x37] >> 3] / 32768.0) : 0.0; - mixer->line_l = (mixer->output_selector & OUTPUT_LINE_L) ? (sb_att_2dbstep_5bits[mixer->regs[0x38] >> 3] / 32768.0) : 0.0; - mixer->line_r = (mixer->output_selector & OUTPUT_LINE_R) ? (sb_att_2dbstep_5bits[mixer->regs[0x39] >> 3] / 32768.0) : 0.0; + Note: Registers 80h and 81h are Read-only for PnP boards. */ + case 0x80: + if (!sb->pnp) { + if (val & 0x01) + sb_dsp_setirq(&sb->dsp, 2); + if (val & 0x02) + sb_dsp_setirq(&sb->dsp, 5); + if (val & 0x04) + sb_dsp_setirq(&sb->dsp, 7); + if (val & 0x08) + sb_dsp_setirq(&sb->dsp, 10); + } + break; - mixer->mic = sb_att_2dbstep_5bits[mixer->regs[0x3a] >> 3] / 32768.0; - mixer->speaker = sb_att_2dbstep_5bits[mixer->regs[0x3b] * 3 + 22] / 32768.0; + case 0x81: + /* The documentation is confusing. sounds as if multple dma8 channels could + be set. */ + if (!sb->pnp) { + if (val & 0x01) + sb_dsp_setdma8(&sb->dsp, 0); + else if (val & 0x02) + sb_dsp_setdma8(&sb->dsp, 1); + else if (val & 0x08) + sb_dsp_setdma8(&sb->dsp, 3); - mixer->input_gain_L = (mixer->regs[0x3f] >> 6); - mixer->input_gain_R = (mixer->regs[0x40] >> 6); - mixer->output_gain_L = (double) (1 << (mixer->regs[0x41] >> 6)); - mixer->output_gain_R = (double) (1 << (mixer->regs[0x42] >> 6)); + sb_dsp_setdma16(&sb->dsp, 4); + if (val & 0x20) + sb_dsp_setdma16(&sb->dsp, 5); + else if (val & 0x40) + sb_dsp_setdma16(&sb->dsp, 6); + else if (val & 0x80) + sb_dsp_setdma16(&sb->dsp, 7); + } + break; - mixer->bass_l = mixer->regs[0x46] >> 4; - mixer->bass_r = mixer->regs[0x47] >> 4; - mixer->treble_l = mixer->regs[0x44] >> 4; - mixer->treble_r = mixer->regs[0x45] >> 4; + case 0x83: + /* Interrupt mask. */ + sb_update_mask(&sb->dsp, !(val & 0x01), !(val & 0x02), !(val & 0x04)); + break; - /* TODO: PC Speaker volume, with "output_selector" check? or better not? */ - sb_log("sb_ct1745: Received register WRITE: %02X\t%02X\n", mixer->index, mixer->regs[mixer->index]); + case 0x84: + /* MPU Control register, per the Linux source code. */ + /* Bits 2-1: MPU-401 address: + 0, 0 = 330h; + 0, 1 = Disabled; + 1, 0 = 300h; + 1, 1 = ???? (Reserved?) + Bit 0: Gameport address: + 0, 0 = 200-207h; + 0, 1 = Disabled + */ + if (!sb->pnp) { + if (sb->mpu != NULL) { + if ((val & 0x06) == 0x00) + mpu401_change_addr(sb->mpu, 0x330); + else if ((val & 0x06) == 0x04) + mpu401_change_addr(sb->mpu, 0x300); + else if ((val & 0x06) == 0x02) + mpu401_change_addr(sb->mpu, 0); + } + sb->gameport_addr = 0; + gameport_remap(sb->gameport, 0); + if (!(val & 0x01)) { + sb->gameport_addr = 0x200; + gameport_remap(sb->gameport, 0x200); + } + } + break; + + case 0xff: + if (sb->dsp.sb_type > SBAWE32) { + /* + Bit 5: High DMA channel enabled (0 = yes, 1 = no); + Bit 2: ????; + Bit 1: ???? (16-bit to 8-bit translation?); + Bit 0: ???? + Seen values: 20, 05, 04, 03 + */ + sb_dsp_setdma16_enabled(&sb->dsp, !(val & 0x20)); +#ifdef TOGGLABLE_TRANSLATION + sb_dsp_setdma16_translate(&sb->dsp, val & 0x02); +#endif + } + break; + + default: + break; + } + + mixer->output_selector = mixer->regs[0x3c]; + mixer->input_selector_left = mixer->regs[0x3d]; + mixer->input_selector_right = mixer->regs[0x3e]; + + mixer->master_l = sb_att_2dbstep_5bits[mixer->regs[0x30] >> 3] / 32768.0; + mixer->master_r = sb_att_2dbstep_5bits[mixer->regs[0x31] >> 3] / 32768.0; + mixer->voice_l = sb_att_2dbstep_5bits[mixer->regs[0x32] >> 3] / 32768.0; + mixer->voice_r = sb_att_2dbstep_5bits[mixer->regs[0x33] >> 3] / 32768.0; + mixer->fm_l = sb_att_2dbstep_5bits[mixer->regs[0x34] >> 3] / 32768.0; + mixer->fm_r = sb_att_2dbstep_5bits[mixer->regs[0x35] >> 3] / 32768.0; + mixer->cd_l = (mixer->output_selector & OUTPUT_CD_L) ? (sb_att_2dbstep_5bits[mixer->regs[0x36] >> 3] / 32768.0) : 0.0; + mixer->cd_r = (mixer->output_selector & OUTPUT_CD_R) ? (sb_att_2dbstep_5bits[mixer->regs[0x37] >> 3] / 32768.0) : 0.0; + mixer->line_l = (mixer->output_selector & OUTPUT_LINE_L) ? (sb_att_2dbstep_5bits[mixer->regs[0x38] >> 3] / 32768.0) : 0.0; + mixer->line_r = (mixer->output_selector & OUTPUT_LINE_R) ? (sb_att_2dbstep_5bits[mixer->regs[0x39] >> 3] / 32768.0) : 0.0; + + mixer->mic = sb_att_2dbstep_5bits[mixer->regs[0x3a] >> 3] / 32768.0; + mixer->speaker = sb_att_2dbstep_5bits[mixer->regs[0x3b] * 3 + 22] / 32768.0; + + mixer->input_gain_L = (mixer->regs[0x3f] >> 6); + mixer->input_gain_R = (mixer->regs[0x40] >> 6); + mixer->output_gain_L = (double) (1 << (mixer->regs[0x41] >> 6)); + mixer->output_gain_R = (double) (1 << (mixer->regs[0x42] >> 6)); + + mixer->bass_l = mixer->regs[0x46] >> 4; + mixer->bass_r = mixer->regs[0x47] >> 4; + mixer->treble_l = mixer->regs[0x44] >> 4; + mixer->treble_r = mixer->regs[0x45] >> 4; + + /* TODO: PC Speaker volume, with "output_selector" check? or better not? */ + sb_log("sb_ct1745: Received register WRITE: %02X\t%02X\n", mixer->index, mixer->regs[mixer->index]); } } - -static uint8_t -sb_ct1745_mixer_read(uint16_t addr, void *p) +uint8_t +sb_ct1745_mixer_read(uint16_t addr, void *priv) { - sb_t *sb = (sb_t *) p; - sb_ct1745_mixer_t *mixer = &sb->mixer_sb16; - uint8_t temp, ret = 0xff; + const sb_t *sb = (sb_t *) priv; + const sb_ct1745_mixer_t *mixer = &sb->mixer_sb16; + uint8_t temp; + uint8_t ret = 0xff; if (!(addr & 1)) - ret = mixer->index; + ret = mixer->index; sb_log("sb_ct1745: received register READ: %02X\t%02X\n", mixer->index, mixer->regs[mixer->index]); if ((mixer->index >= 0x30) && (mixer->index <= 0x47)) - ret = mixer->regs[mixer->index]; - else switch (mixer->index) { - case 0x00: - ret = mixer->regs[mixer->index]; - break; + ret = mixer->regs[mixer->index]; + else { + switch (mixer->index) { + case 0x00: + ret = mixer->regs[mixer->index]; + break; - /*SB Pro compatibility*/ - case 0x04: - ret = ((mixer->regs[0x33] >> 4) & 0x0f) | (mixer->regs[0x32] & 0xf0); - break; - case 0x0a: - ret = (mixer->regs[0x3a] >> 5); - break; - case 0x02: - ret = ((mixer->regs[0x30] >> 4) & 0x0f); - break; - case 0x06: - ret = ((mixer->regs[0x34] >> 4) & 0x0f); - break; - case 0x08: - ret = ((mixer->regs[0x36] >> 4) & 0x0f); - break; - case 0x0e: - ret = 0x02; - break; - case 0x22: - ret = ((mixer->regs[0x31] >> 4) & 0x0f) | (mixer->regs[0x30] & 0xf0); - break; - case 0x26: - ret = ((mixer->regs[0x35] >> 4) & 0x0f) | (mixer->regs[0x34] & 0xf0); - break; - case 0x28: - ret = ((mixer->regs[0x37] >> 4) & 0x0f) | (mixer->regs[0x36] & 0xf0); - break; - case 0x2e: - ret = ((mixer->regs[0x39] >> 4) & 0x0f) | (mixer->regs[0x38] & 0xf0); - break; + /*SB Pro compatibility*/ + case 0x04: + ret = ((mixer->regs[0x33] >> 4) & 0x0f) | (mixer->regs[0x32] & 0xf0); + break; + case 0x0a: + ret = (mixer->regs[0x3a] >> 5); + break; + case 0x02: + ret = ((mixer->regs[0x30] >> 4) & 0x0f); + break; + case 0x06: + ret = ((mixer->regs[0x34] >> 4) & 0x0f); + break; + case 0x08: + ret = ((mixer->regs[0x36] >> 4) & 0x0f); + break; + case 0x0e: + ret = 0x02; + break; + case 0x22: + ret = ((mixer->regs[0x31] >> 4) & 0x0f) | (mixer->regs[0x30] & 0xf0); + break; + case 0x26: + ret = ((mixer->regs[0x35] >> 4) & 0x0f) | (mixer->regs[0x34] & 0xf0); + break; + case 0x28: + ret = ((mixer->regs[0x37] >> 4) & 0x0f) | (mixer->regs[0x36] & 0xf0); + break; + case 0x2e: + ret = ((mixer->regs[0x39] >> 4) & 0x0f) | (mixer->regs[0x38] & 0xf0); + break; - case 0x48: - /* Undocumented. The Creative Windows Mixer calls this after calling 3C (input selector), - even when writing. - Also, the version I have (5.17), does not use the MIDI.L/R input selectors, it uses - the volume to mute (Affecting the output, obviously). */ - ret = mixer->regs[mixer->index]; - break; + case 0x48: + /* Undocumented. The Creative Windows Mixer calls this after calling 3C (input selector), + even when writing. + Also, the version I have (5.17), does not use the MIDI.L/R input selectors, it uses + the volume to mute (Affecting the output, obviously). */ + ret = mixer->regs[mixer->index]; + break; - case 0x80: - /* TODO: Unaffected by mixer reset or soft reboot. - Enabling multiple bits enables multiple IRQs. */ + case 0x80: + /* TODO: Unaffected by mixer reset or soft reboot. + Enabling multiple bits enables multiple IRQs. */ - switch (sb->dsp.sb_irqnum) { - case 2: ret = 1; break; - case 5: ret = 2; break; - case 7: ret = 4; break; - case 10: ret = 8; break; - } - break; + switch (sb->dsp.sb_irqnum) { + case 2: + ret = 1; + break; + case 5: + ret = 2; + break; + case 7: + ret = 4; + break; + case 10: + ret = 8; + break; - case 0x81: - /* TODO: Unaffected by mixer reset or soft reboot. - Enabling multiple 8 or 16-bit DMA bits enables multiple DMA channels. - Disabling all 8-bit DMA channel bits disables 8-bit DMA requests, - including translated 16-bit DMA requests. - Disabling all 16-bit DMA channel bits enables translation of 16-bit DMA - requests to 8-bit ones, using the selected 8-bit DMA channel. */ + default: + break; + } + break; - ret = 0; - switch (sb->dsp.sb_8_dmanum) { - case 0: ret |= 1; break; - case 1: ret |= 2; break; - case 3: ret |= 8; break; - } - switch (sb->dsp.sb_16_dmanum) { - case 5: ret |= 0x20; break; - case 6: ret |= 0x40; break; - case 7: ret |= 0x80; break; - } - break; + case 0x81: + /* TODO: Unaffected by mixer reset or soft reboot. + Enabling multiple 8 or 16-bit DMA bits enables multiple DMA channels. + Disabling all 8-bit DMA channel bits disables 8-bit DMA requests, + including translated 16-bit DMA requests. + Disabling all 16-bit DMA channel bits enables translation of 16-bit DMA + requests to 8-bit ones, using the selected 8-bit DMA channel. */ - case 0x82: - /* The Interrupt status register, addressed as register 82h on the Mixer register map, - is used by the ISR to determine whether the interrupt is meant for it or for some other ISR, - in which case it should chain to the previous routine. */ - /* 0 = none, 1 = digital 8bit or SBMIDI, 2 = digital 16bit, 4 = MPU-401 */ - /* 0x02000 DSP v4.04, 0x4000 DSP v4.05, 0x8000 DSP v4.12. - I haven't seen this making any difference, but I'm keeping it for now. */ - /* If QEMU is any indication, then the values are actually 0x20, 0x40, and 0x80. */ - temp = ((sb->dsp.sb_irq8) ? 1 : 0) | ((sb->dsp.sb_irq16) ? 2 : 0) | - ((sb->dsp.sb_irq401) ? 4 : 0) | 0x40; - ret = temp; - break; + ret = 0; + switch (sb->dsp.sb_8_dmanum) { + case 0: + ret |= 1; + break; + case 1: + ret |= 2; + break; + case 3: + ret |= 8; + break; - case 0x83: - /* Interrupt mask. */ - ret = mixer->regs[mixer->index]; - break; + default: + break; + } + switch (sb->dsp.sb_16_dmanum) { + case 5: + ret |= 0x20; + break; + case 6: + ret |= 0x40; + break; + case 7: + ret |= 0x80; + break; + } + break; - case 0x84: - /* MPU Control. */ - if (sb->mpu == NULL) - ret = 0x02; - else { - if (sb->mpu->addr == 0x330) - ret = 0x00; - else if (sb->mpu->addr == 0x300) - ret = 0x04; - else if (sb->mpu->addr == 0) - ret = 0x02; - else - ret = 0x06; /* Should never happen. */ - } - break; + case 0x82: + /* The Interrupt status register, addressed as register 82h on the Mixer register map, + is used by the ISR to determine whether the interrupt is meant for it or for some + other ISR, in which case it should chain to the previous routine. */ + /* 0 = none, 1 = digital 8bit or SBMIDI, 2 = digital 16bit, 4 = MPU-401 */ + /* 0x02000 DSP v4.04, 0x4000 DSP v4.05, 0x8000 DSP v4.12. + I haven't seen this making any difference, but I'm keeping it for now. */ + /* If QEMU is any indication, then the values are actually 0x20, 0x40, and 0x80. */ + /* http://the.earth.li/~tfm/oldpage/sb_mixer.html - 0x10, 0x20, 0x80. */ + temp = ((sb->dsp.sb_irq8) ? 1 : 0) | ((sb->dsp.sb_irq16) ? 2 : 0) | + ((sb->dsp.sb_irq401) ? 4 : 0); + if (sb->dsp.sb_type >= SBAWE32) + ret = temp | 0x80; + else + ret = temp | 0x40; + break; - case 0x90: - /* 3D Enhancement switch. */ - ret = mixer->regs[mixer->index]; - break; + case 0x83: + /* Interrupt mask. */ + ret = mixer->regs[mixer->index]; + break; - /* TODO: creative drivers read and write on 0xFE and 0xFF. not sure what they are supposed to be. */ - case 0xfd: - ret = 16; - break; + case 0x84: + /* MPU Control. */ + if (sb->mpu == NULL) + ret = 0x02; + else { + if (sb->mpu->addr == 0x330) + ret = 0x00; + else if (sb->mpu->addr == 0x300) + ret = 0x04; + else if (sb->mpu->addr == 0) + ret = 0x02; + else + ret = 0x06; /* Should never happen. */ + } + if (!sb->gameport_addr) + ret |= 0x01; + break; - case 0xfe: - ret = 6; - break; + case 0x49: /* Undocumented register used by some Creative drivers. */ + case 0x4a: /* Undocumented register used by some Creative drivers. */ + case 0x8c: /* Undocumented register used by some Creative drivers. */ + case 0x8e: /* Undocumented register used by some Creative drivers. */ + case 0x90: /* 3D Enhancement switch. */ + case 0xfd: /* Undocumented register used by some Creative drivers. */ + case 0xfe: /* Undocumented register used by some Creative drivers. */ + ret = mixer->regs[mixer->index]; + break; - default: - sb_log("sb_ct1745: Unknown register READ: %02X\t%02X\n", mixer->index, mixer->regs[mixer->index]); - break; + case 0xff: /* Undocumented register used by some Creative drivers. + This and the upper bits of 0x82 seem to affect the + playback volume: + - Register FF = FF: Volume playback normal. + - Register FF = Not FF: Volume playback low unless + bit 6 of 82h is set. */ + if (sb->dsp.sb_type > SBAWE32) + ret = mixer->regs[mixer->index]; + break; + + default: + sb_log("sb_ct1745: Unknown register READ: %02X\t%02X\n", mixer->index, mixer->regs[mixer->index]); + break; + } + + sb_log("CT1745: [R] %02X = %02X\n", mixer->index, ret); } sb_log("CT1745: read REG%02X: %02X\n", mixer->index, ret); @@ -1012,46 +1190,44 @@ sb_ct1745_mixer_read(uint16_t addr, void *p) return ret; } - -static void -sb_ct1745_mixer_reset(sb_t* sb) +void +sb_ct1745_mixer_reset(sb_t *sb) { sb_ct1745_mixer_write(4, 0, sb); sb_ct1745_mixer_write(5, 0, sb); - - sb->mixer_sb16.regs[0xfd] = 16; - sb->mixer_sb16.regs[0xfe] = 6; } - uint8_t -sb_mcv_read(int port, void *p) +sb_mcv_read(int port, void *priv) { - sb_t *sb = (sb_t *)p; + const sb_t *sb = (sb_t *) priv; sb_log("sb_mcv_read: port=%04x\n", port); return sb->pos_regs[port & 7]; } - void -sb_mcv_write(int port, uint8_t val, void *p) +sb_mcv_write(int port, uint8_t val, void *priv) { uint16_t addr; - sb_t *sb = (sb_t *)p; + sb_t *sb = (sb_t *) priv; if (port < 0x102) - return; + return; sb_log("sb_mcv_write: port=%04x val=%02x\n", port, val); addr = sb_mcv_addr[sb->pos_regs[4] & 7]; if (sb->opl_enabled) { - io_removehandler(addr + 8, 0x0002, opl2_read, NULL, NULL, - opl2_write, NULL, NULL, &sb->opl); - io_removehandler(0x0388, 0x0002, opl2_read, NULL, NULL, - opl2_write, NULL, NULL, &sb->opl); + io_removehandler(addr + 8, 0x0002, + sb->opl.read, NULL, NULL, + sb->opl.write, NULL, NULL, + sb->opl.priv); + io_removehandler(0x0388, 0x0002, + sb->opl.read, NULL, NULL, + sb->opl.write, NULL, NULL, + sb->opl.priv); } /* DSP I/O handler is activated in sb_dsp_setaddr */ sb_dsp_setaddr(&sb->dsp, 0); @@ -1059,174 +1235,418 @@ sb_mcv_write(int port, uint8_t val, void *p) sb->pos_regs[port & 7] = val; if (sb->pos_regs[2] & 1) { - addr = sb_mcv_addr[sb->pos_regs[4] & 7]; + addr = sb_mcv_addr[sb->pos_regs[4] & 7]; - if (sb->opl_enabled) { - io_sethandler(addr + 8, 0x0002, opl2_read, NULL, NULL, - opl2_write, NULL, NULL, &sb->opl); - io_sethandler(0x0388, 0x0002, opl2_read, NULL, NULL, - opl2_write, NULL, NULL, &sb->opl); - } - /* DSP I/O handler is activated in sb_dsp_setaddr */ - sb_dsp_setaddr(&sb->dsp, addr); + if (sb->opl_enabled) { + io_sethandler(addr + 8, 0x0002, + sb->opl.read, NULL, NULL, + sb->opl.write, NULL, NULL, + sb->opl.priv); + io_sethandler(0x0388, 0x0002, + sb->opl.read, NULL, NULL, + sb->opl.write, NULL, NULL, + sb->opl.priv); + } + /* DSP I/O handler is activated in sb_dsp_setaddr */ + sb_dsp_setaddr(&sb->dsp, addr); } } - uint8_t -sb_mcv_feedb(void *p) +sb_mcv_feedb(void *priv) { - sb_t *sb = (sb_t *)p; + const sb_t *sb = (sb_t *) priv; return (sb->pos_regs[2] & 1); } - static uint8_t -sb_pro_mcv_read(int port, void *p) +sb_pro_mcv_read(int port, void *priv) { - sb_t *sb = (sb_t *)p; - uint8_t ret = sb->pos_regs[port & 7]; + const sb_t *sb = (sb_t *) priv; + uint8_t ret = sb->pos_regs[port & 7]; sb_log("sb_pro_mcv_read: port=%04x ret=%02x\n", port, ret); return ret; } - static void -sb_pro_mcv_write(int port, uint8_t val, void *p) +sb_pro_mcv_write(int port, uint8_t val, void *priv) { uint16_t addr; - sb_t *sb = (sb_t *)p; + sb_t *sb = (sb_t *) priv; if (port < 0x102) - return; + return; sb_log("sb_pro_mcv_write: port=%04x val=%02x\n", port, val); addr = (sb->pos_regs[2] & 0x20) ? 0x220 : 0x240; - io_removehandler(addr, 0x0004, opl3_read, NULL, NULL, - opl3_write, NULL, NULL, &sb->opl); - io_removehandler(addr + 8, 0x0002, opl3_read, NULL, NULL, - opl3_write, NULL, NULL, &sb->opl); - io_removehandler(0x0388, 0x0004, opl3_read, NULL, NULL, - opl3_write, NULL, NULL, &sb->opl); - io_removehandler(addr + 4, 0x0002, sb_ct1345_mixer_read, NULL, NULL, - sb_ct1345_mixer_write, NULL, NULL, sb); + io_removehandler(addr, 0x0004, + sb->opl.read, NULL, NULL, + sb->opl.write, NULL, NULL, + sb->opl.priv); + io_removehandler(addr + 8, 0x0002, + sb->opl.read, NULL, NULL, + sb->opl.write, NULL, NULL, + sb->opl.priv); + io_removehandler(0x0388, 0x0004, + sb->opl.read, NULL, NULL, + sb->opl.write, NULL, NULL, + sb->opl.priv); + io_removehandler(addr + 4, 0x0002, + sb_ct1345_mixer_read, NULL, NULL, + sb_ct1345_mixer_write, NULL, NULL, + sb); /* DSP I/O handler is activated in sb_dsp_setaddr */ sb_dsp_setaddr(&sb->dsp, 0); sb->pos_regs[port & 7] = val; if (sb->pos_regs[2] & 1) { - addr = (sb->pos_regs[2] & 0x20) ? 0x220 : 0x240; + addr = (sb->pos_regs[2] & 0x20) ? 0x220 : 0x240; - io_sethandler(addr, 0x0004, opl3_read, NULL, NULL, - opl3_write, NULL, NULL, &sb->opl); - io_sethandler(addr + 8, 0x0002, opl3_read, NULL, NULL, - opl3_write, NULL, NULL, &sb->opl); - io_sethandler(0x0388, 0x0004, opl3_read, NULL, NULL, - opl3_write, NULL, NULL, &sb->opl); - io_sethandler(addr + 4, 0x0002, sb_ct1345_mixer_read, NULL, NULL, - sb_ct1345_mixer_write, NULL, NULL, sb); - /* DSP I/O handler is activated in sb_dsp_setaddr */ - sb_dsp_setaddr(&sb->dsp, addr); + io_sethandler(addr, 0x0004, + sb->opl.read, NULL, NULL, + sb->opl.write, NULL, NULL, + sb->opl.priv); + io_sethandler(addr + 8, 0x0002, + sb->opl.read, NULL, NULL, + sb->opl.write, NULL, NULL, + sb->opl.priv); + io_sethandler(0x0388, 0x0004, + sb->opl.read, NULL, NULL, + sb->opl.write, NULL, NULL, sb->opl.priv); + io_sethandler(addr + 4, 0x0002, + sb_ct1345_mixer_read, NULL, NULL, + sb_ct1345_mixer_write, NULL, NULL, + sb); + /* DSP I/O handler is activated in sb_dsp_setaddr */ + sb_dsp_setaddr(&sb->dsp, addr); } sb_dsp_setirq(&sb->dsp, sb_pro_mcv_irqs[(sb->pos_regs[5] >> 4) & 3]); sb_dsp_setdma8(&sb->dsp, sb->pos_regs[4] & 3); } +static uint8_t +sb_16_reply_mca_read(int port, void *priv) +{ + const sb_t *sb = (sb_t *) priv; + uint8_t ret = sb->pos_regs[port & 7]; + + sb_log("sb_16_reply_mca_read: port=%04x ret=%02x\n", port, ret); + + return ret; +} + +static void +sb_16_reply_mca_write(int port, uint8_t val, void *priv) +{ + uint16_t addr; + uint16_t mpu401_addr; + int low_dma; + int high_dma; + sb_t *sb = (sb_t *) priv; + + if (port < 0x102) + return; + + sb_log("sb_16_reply_mca_write: port=%04x val=%02x\n", port, val); + + switch (sb->pos_regs[2] & 0xc4) { + case 4: + addr = 0x220; + break; + case 0x44: + addr = 0x240; + break; + case 0x84: + addr = 0x260; + break; + case 0xc4: + addr = 0x280; + break; + case 0: + default: + addr = 0; + break; + } + + if (addr) { + io_removehandler(addr, 0x0004, + sb->opl.read, NULL, NULL, + sb->opl.write, NULL, NULL, + sb->opl.priv); + io_removehandler(addr + 8, 0x0002, + sb->opl.read, NULL, NULL, + sb->opl.write, NULL, NULL, + sb->opl.priv); + io_removehandler(0x0388, 0x0004, + sb->opl.read, NULL, NULL, + sb->opl.write, NULL, NULL, + sb->opl.priv); + io_removehandler(addr + 4, 0x0002, + sb_ct1745_mixer_read, NULL, NULL, + sb_ct1745_mixer_write, NULL, NULL, + sb); + } + + /* DSP I/O handler is activated in sb_dsp_setaddr */ + sb_dsp_setaddr(&sb->dsp, 0); + mpu401_change_addr(sb->mpu, 0); + gameport_remap(sb->gameport, 0); + + sb->pos_regs[port & 7] = val; + + if (sb->pos_regs[2] & 1) { + switch (sb->pos_regs[2] & 0xc4) { + case 4: + addr = 0x220; + break; + case 0x44: + addr = 0x240; + break; + case 0x84: + addr = 0x260; + break; + case 0xc4: + addr = 0x280; + break; + case 0: + default: + addr = 0; + break; + } + switch (sb->pos_regs[2] & 0x18) { + case 8: + mpu401_addr = 0x330; + break; + case 0x18: + mpu401_addr = 0x300; + break; + case 0: + default: + mpu401_addr = 0; + break; + } + + if (addr) { + io_sethandler(addr, 0x0004, + sb->opl.read, NULL, NULL, + sb->opl.write, NULL, NULL, + sb->opl.priv); + io_sethandler(addr + 8, 0x0002, + sb->opl.read, NULL, NULL, + sb->opl.write, NULL, NULL, + sb->opl.priv); + io_sethandler(0x0388, 0x0004, + sb->opl.read, NULL, NULL, + sb->opl.write, NULL, NULL, sb->opl.priv); + io_sethandler(addr + 4, 0x0002, + sb_ct1745_mixer_read, NULL, NULL, + sb_ct1745_mixer_write, NULL, NULL, + sb); + } + + /* DSP I/O handler is activated in sb_dsp_setaddr */ + sb_dsp_setaddr(&sb->dsp, addr); + mpu401_change_addr(sb->mpu, mpu401_addr); + gameport_remap(sb->gameport, (sb->pos_regs[2] & 0x20) ? 0x200 : 0); + } + + switch (sb->pos_regs[4] & 0x60) { + case 0x20: + sb_dsp_setirq(&sb->dsp, 5); + break; + case 0x40: + sb_dsp_setirq(&sb->dsp, 7); + break; + case 0x60: + sb_dsp_setirq(&sb->dsp, 10); + break; + + default: + break; + } + + low_dma = sb->pos_regs[3] & 3; + high_dma = (sb->pos_regs[3] >> 4) & 7; + if (!high_dma) + high_dma = low_dma; + + sb_dsp_setdma8(&sb->dsp, low_dma); + sb_dsp_setdma16(&sb->dsp, high_dma); +} + +void +sb_vibra16s_onboard_relocate_base(uint16_t new_addr, void *priv) +{ + sb_t *sb = (sb_t *) priv; + uint16_t addr = sb->dsp.sb_addr; + + io_removehandler(addr, 0x0004, + sb->opl.read, NULL, NULL, + sb->opl.write, NULL, NULL, + sb->opl.priv); + io_removehandler(addr + 8, 0x0002, + sb->opl.read, NULL, NULL, + sb->opl.write, NULL, NULL, + sb->opl.priv); + io_removehandler(addr + 4, 0x0002, + sb_ct1745_mixer_read, NULL, NULL, + sb_ct1745_mixer_write, NULL, NULL, + sb); + + sb_dsp_setaddr(&sb->dsp, 0); + + addr = new_addr; + + io_sethandler(addr, 0x0004, + sb->opl.read, NULL, NULL, + sb->opl.write, NULL, NULL, + sb->opl.priv); + io_sethandler(addr + 8, 0x0002, + sb->opl.read, NULL, NULL, + sb->opl.write, NULL, NULL, + sb->opl.priv); + io_sethandler(addr + 4, 0x0002, + sb_ct1745_mixer_read, NULL, NULL, + sb_ct1745_mixer_write, NULL, NULL, + sb); + + sb_dsp_setaddr(&sb->dsp, addr); +} static void sb_16_pnp_config_changed(uint8_t ld, isapnp_device_config_t *config, void *priv) { - sb_t *sb = (sb_t *) priv; + sb_t *sb = (sb_t *) priv; uint16_t addr = sb->dsp.sb_addr; - uint8_t val; + uint8_t val; switch (ld) { - case 0: /* Audio */ - io_removehandler(addr, 0x0004, opl3_read, NULL, NULL, - opl3_write, NULL, NULL, &sb->opl); - io_removehandler(addr + 8, 0x0002, opl3_read, NULL, NULL, - opl3_write, NULL, NULL, &sb->opl); - io_removehandler(addr + 4, 0x0002, sb_ct1745_mixer_read, NULL, NULL, - sb_ct1745_mixer_write, NULL, NULL, sb); + case 0: /* Audio */ + io_removehandler(addr, 0x0004, + sb->opl.read, NULL, NULL, + sb->opl.write, NULL, NULL, + sb->opl.priv); + io_removehandler(addr + 8, 0x0002, + sb->opl.read, NULL, NULL, + sb->opl.write, NULL, NULL, + sb->opl.priv); + io_removehandler(addr + 4, 0x0002, + sb_ct1745_mixer_read, NULL, NULL, + sb_ct1745_mixer_write, NULL, NULL, + sb); - addr = sb->opl_pnp_addr; - if (addr) { - sb->opl_pnp_addr = 0; - io_removehandler(addr, 0x0004, opl3_read, NULL, NULL, - opl3_write, NULL, NULL, &sb->opl); - } + addr = sb->opl_pnp_addr; + if (addr) { + sb->opl_pnp_addr = 0; + io_removehandler(addr, 0x0004, + sb->opl.read, NULL, NULL, + sb->opl.write, NULL, NULL, + sb->opl.priv); + } - sb_dsp_setaddr(&sb->dsp, 0); - sb_dsp_setirq(&sb->dsp, 0); - sb_dsp_setdma8(&sb->dsp, ISAPNP_DMA_DISABLED); - sb_dsp_setdma16(&sb->dsp, ISAPNP_DMA_DISABLED); + sb_dsp_setaddr(&sb->dsp, 0); + sb_dsp_setirq(&sb->dsp, 0); + sb_dsp_setdma8(&sb->dsp, ISAPNP_DMA_DISABLED); + sb_dsp_setdma16(&sb->dsp, ISAPNP_DMA_DISABLED); - mpu401_change_addr(sb->mpu, 0); + mpu401_change_addr(sb->mpu, 0); - if (config->activate) { - addr = config->io[0].base; - if (addr != ISAPNP_IO_DISABLED) { - io_sethandler(addr, 0x0004, opl3_read, NULL, NULL, - opl3_write, NULL, NULL, &sb->opl); - io_sethandler(addr + 8, 0x0002, opl3_read, NULL, NULL, - opl3_write, NULL, NULL, &sb->opl); - io_sethandler(addr + 4, 0x0002, sb_ct1745_mixer_read, NULL, NULL, - sb_ct1745_mixer_write, NULL, NULL, sb); + if (config->activate) { + addr = config->io[0].base; + if (addr != ISAPNP_IO_DISABLED) { + io_sethandler(addr, 0x0004, + sb->opl.read, NULL, NULL, + sb->opl.write, NULL, NULL, + sb->opl.priv); + io_sethandler(addr + 8, 0x0002, + sb->opl.read, NULL, NULL, + sb->opl.write, NULL, NULL, + sb->opl.priv); + io_sethandler(addr + 4, 0x0002, + sb_ct1745_mixer_read, NULL, NULL, + sb_ct1745_mixer_write, NULL, NULL, + sb); - sb_dsp_setaddr(&sb->dsp, addr); - } + sb_dsp_setaddr(&sb->dsp, addr); + } - addr = config->io[1].base; - if (addr != ISAPNP_IO_DISABLED) - mpu401_change_addr(sb->mpu, addr); + addr = config->io[1].base; + if (addr != ISAPNP_IO_DISABLED) + mpu401_change_addr(sb->mpu, addr); - addr = config->io[2].base; - if (addr != ISAPNP_IO_DISABLED) { - sb->opl_pnp_addr = addr; - io_sethandler(addr, 0x0004, opl3_read, NULL, NULL, - opl3_write, NULL, NULL, &sb->opl); - } + addr = config->io[2].base; + if (addr != ISAPNP_IO_DISABLED) { + sb->opl_pnp_addr = addr; + io_sethandler(addr, 0x0004, + sb->opl.read, NULL, NULL, + sb->opl.write, NULL, NULL, + sb->opl.priv); + } - val = config->irq[0].irq; - if (val != ISAPNP_IRQ_DISABLED) - sb_dsp_setirq(&sb->dsp, val); + val = config->irq[0].irq; + if (val != ISAPNP_IRQ_DISABLED) + sb_dsp_setirq(&sb->dsp, val); - val = config->dma[0].dma; - if (val != ISAPNP_DMA_DISABLED) - sb_dsp_setdma8(&sb->dsp, val); + val = config->dma[0].dma; + if (val != ISAPNP_DMA_DISABLED) + sb_dsp_setdma8(&sb->dsp, val); - val = config->dma[1].dma; - if (val != ISAPNP_DMA_DISABLED) - sb_dsp_setdma16(&sb->dsp, val); - } + val = config->dma[1].dma; + sb_dsp_setdma16_enabled(&sb->dsp, val != ISAPNP_DMA_DISABLED); + sb_dsp_setdma16_translate(&sb->dsp, val < ISAPNP_DMA_DISABLED); + if (val != ISAPNP_DMA_DISABLED) { + if (sb->dsp.sb_16_dma_supported) + sb_dsp_setdma16(&sb->dsp, val); + else + sb_dsp_setdma16_8(&sb->dsp, val); + } + } - break; + break; - case 1: /* IDE */ - ide_pnp_config_changed(0, config, (void *) 2); - break; + case 1: /* IDE */ + ide_pnp_config_changed(0, config, (void *) 3); + break; - case 2: /* Reserved (16) / WaveTable (32+) */ - if (sb->dsp.sb_type > SB16) - emu8k_change_addr(&sb->emu8k, (config->activate && (config->io[0].base != ISAPNP_IO_DISABLED)) ? config->io[0].base : 0); - break; + case 2: /* Reserved (16) / WaveTable (32+) */ + if (sb->dsp.sb_type > SB16) + emu8k_change_addr(&sb->emu8k, (config->activate && (config->io[0].base != ISAPNP_IO_DISABLED)) ? config->io[0].base : 0); + break; - case 3: /* Game */ - gameport_remap(sb->gameport, (config->activate && (config->io[0].base != ISAPNP_IO_DISABLED)) ? config->io[0].base : 0); - break; + case 3: /* Game */ + gameport_remap(sb->gameport, (config->activate && (config->io[0].base != ISAPNP_IO_DISABLED)) ? config->io[0].base : 0); + break; - case 4: /* StereoEnhance (32) */ - break; + case 4: /* StereoEnhance (32) */ + break; + + default: + break; } } +static void +sb_vibra16_pnp_config_changed(uint8_t ld, isapnp_device_config_t *config, void *priv) +{ + sb_t *sb = (sb_t *) priv; + + switch (ld) { + case 0: /* Audio */ + case 1: /* Game */ + sb_16_pnp_config_changed(ld * 3, config, sb); + break; + + default: + break; + } +} static void sb_awe32_pnp_config_changed(uint8_t ld, isapnp_device_config_t *config, void *priv) @@ -1234,51 +1654,55 @@ sb_awe32_pnp_config_changed(uint8_t ld, isapnp_device_config_t *config, void *pr sb_t *sb = (sb_t *) priv; switch (ld) { - case 0: /* Audio */ - case 1: /* IDE */ - sb_16_pnp_config_changed(ld, config, sb); - break; + case 0: /* Audio */ + case 1: /* IDE */ + sb_16_pnp_config_changed(ld, config, sb); + break; - case 2: /* Game */ - case 3: /* WaveTable */ - sb_16_pnp_config_changed(ld ^ 1, config, sb); - break; + case 2: /* Game */ + case 3: /* WaveTable */ + sb_16_pnp_config_changed(ld ^ 1, config, sb); + break; + + default: + break; } } - static void sb_awe64_gold_pnp_config_changed(uint8_t ld, isapnp_device_config_t *config, void *priv) { sb_t *sb = (sb_t *) priv; switch (ld) { - case 0: /* Audio */ - case 2: /* WaveTable */ - sb_16_pnp_config_changed(ld, config, sb); - break; + case 0: /* Audio */ + case 2: /* WaveTable */ + sb_16_pnp_config_changed(ld, config, sb); + break; - case 1: /* Game */ - sb_16_pnp_config_changed(3, config, sb); - break; + case 1: /* Game */ + sb_16_pnp_config_changed(3, config, sb); + break; + + default: + break; } } - void * -sb_1_init(const device_t *info) +sb_1_init(UNUSED(const device_t *info)) { /* SB1/2 port mappings, 210h to 260h in 10h steps 2x0 to 2x3 -> CMS chip 2x6, 2xA, 2xC, 2xE -> DSP chip 2x8, 2x9, 388 and 389 FM chip */ - sb_t *sb = malloc(sizeof(sb_t)); + sb_t *sb = malloc(sizeof(sb_t)); uint16_t addr = device_get_config_hex16("base"); memset(sb, 0, sizeof(sb_t)); sb->opl_enabled = device_get_config_int("opl"); if (sb->opl_enabled) - opl2_init(&sb->opl); + fm_driver_get(FM_YM3812, &sb->opl); sb_dsp_init(&sb->dsp, SB1, SB_SUBTYPE_DEFAULT, sb); sb_dsp_setaddr(&sb->dsp, addr); @@ -1286,41 +1710,47 @@ sb_1_init(const device_t *info) sb_dsp_setdma8(&sb->dsp, device_get_config_int("dma")); /* DSP I/O handler is activated in sb_dsp_setaddr */ if (sb->opl_enabled) { - io_sethandler(addr + 8, 0x0002, opl2_read, NULL, NULL, - opl2_write, NULL, NULL, &sb->opl); - io_sethandler(0x0388, 0x0002, opl2_read, NULL, NULL, - opl2_write, NULL, NULL, &sb->opl); + io_sethandler(addr + 8, 0x0002, + sb->opl.read, NULL, NULL, + sb->opl.write, NULL, NULL, + sb->opl.priv); + io_sethandler(0x0388, 0x0002, + sb->opl.read, NULL, NULL, + sb->opl.write, NULL, NULL, + sb->opl.priv); } sb->cms_enabled = 1; memset(&sb->cms, 0, sizeof(cms_t)); - io_sethandler(addr, 0x0004, cms_read, NULL, NULL, cms_write, NULL, NULL, &sb->cms); + io_sethandler(addr, 0x0004, + cms_read, NULL, NULL, + cms_write, NULL, NULL, + &sb->cms); sb->mixer_enabled = 0; sound_add_handler(sb_get_buffer_sb2, sb); sound_set_cd_audio_filter(sb2_filter_cd_audio, sb); if (device_get_config_int("receive_input")) - midi_in_handler(1, sb_dsp_input_msg, sb_dsp_input_sysex, &sb->dsp); + midi_in_handler(1, sb_dsp_input_msg, sb_dsp_input_sysex, &sb->dsp); return sb; } - void * -sb_15_init(const device_t *info) +sb_15_init(UNUSED(const device_t *info)) { /* SB1/2 port mappings, 210h to 260h in 10h steps 2x0 to 2x3 -> CMS chip 2x6, 2xA, 2xC, 2xE -> DSP chip 2x8, 2x9, 388 and 389 FM chip */ - sb_t *sb = malloc(sizeof(sb_t)); + sb_t *sb = malloc(sizeof(sb_t)); uint16_t addr = device_get_config_hex16("base"); memset(sb, 0, sizeof(sb_t)); sb->opl_enabled = device_get_config_int("opl"); if (sb->opl_enabled) - opl2_init(&sb->opl); + fm_driver_get(FM_YM3812, &sb->opl); sb_dsp_init(&sb->dsp, SB15, SB_SUBTYPE_DEFAULT, sb); sb_dsp_setaddr(&sb->dsp, addr); @@ -1328,16 +1758,23 @@ sb_15_init(const device_t *info) sb_dsp_setdma8(&sb->dsp, device_get_config_int("dma")); /* DSP I/O handler is activated in sb_dsp_setaddr */ if (sb->opl_enabled) { - io_sethandler(addr + 8, 0x0002, opl2_read, NULL, NULL, - opl2_write, NULL, NULL, &sb->opl); - io_sethandler(0x0388, 0x0002, opl2_read, NULL, NULL, - opl2_write, NULL, NULL, &sb->opl); + io_sethandler(addr + 8, 0x0002, + sb->opl.read, NULL, NULL, + sb->opl.write, NULL, NULL, + sb->opl.priv); + io_sethandler(0x0388, 0x0002, + sb->opl.read, NULL, NULL, + sb->opl.write, NULL, NULL, + sb->opl.priv); } sb->cms_enabled = device_get_config_int("cms"); if (sb->cms_enabled) { - memset(&sb->cms, 0, sizeof(cms_t)); - io_sethandler(addr, 0x0004, cms_read, NULL, NULL, cms_write, NULL, NULL, &sb->cms); + memset(&sb->cms, 0, sizeof(cms_t)); + io_sethandler(addr, 0x0004, + cms_read, NULL, NULL, + cms_write, NULL, NULL, + &sb->cms); } sb->mixer_enabled = 0; @@ -1345,14 +1782,13 @@ sb_15_init(const device_t *info) sound_set_cd_audio_filter(sb2_filter_cd_audio, sb); if (device_get_config_int("receive_input")) - midi_in_handler(1, sb_dsp_input_msg, sb_dsp_input_sysex, &sb->dsp); + midi_in_handler(1, sb_dsp_input_msg, sb_dsp_input_sysex, &sb->dsp); return sb; } - void * -sb_mcv_init(const device_t *info) +sb_mcv_init(UNUSED(const device_t *info)) { /* SB1/2 port mappings, 210h to 260h in 10h steps 2x6, 2xA, 2xC, 2xE -> DSP chip @@ -1362,7 +1798,7 @@ sb_mcv_init(const device_t *info) sb->opl_enabled = device_get_config_int("opl"); if (sb->opl_enabled) - opl2_init(&sb->opl); + fm_driver_get(FM_YM3812, &sb->opl); sb_dsp_init(&sb->dsp, SB15, SB_SUBTYPE_DEFAULT, sb); sb_dsp_setaddr(&sb->dsp, 0); @@ -1379,14 +1815,13 @@ sb_mcv_init(const device_t *info) sb->pos_regs[1] = 0x50; if (device_get_config_int("receive_input")) - midi_in_handler(1, sb_dsp_input_msg, sb_dsp_input_sysex, &sb->dsp); + midi_in_handler(1, sb_dsp_input_msg, sb_dsp_input_sysex, &sb->dsp); return sb; } - void * -sb_2_init(const device_t *info) +sb_2_init(UNUSED(const device_t *info)) { /* SB2 port mappings, 220h or 240h. 2x0 to 2x3 -> CMS chip @@ -1400,81 +1835,89 @@ sb_2_init(const device_t *info) This mirror may also exist on SB 1.5 & MCV, however I am unable to test this. It shouldn't exist on SB 1.0 as the CMS chips are always present there. Syndicate requires this mirror for music to play.*/ - sb_t *sb = malloc(sizeof(sb_t)); - uint16_t addr = device_get_config_hex16("base"); + sb_t *sb = malloc(sizeof(sb_t)); + uint16_t addr = device_get_config_hex16("base"); uint16_t mixer_addr = device_get_config_int("mixaddr"); memset(sb, 0, sizeof(sb_t)); sb->opl_enabled = device_get_config_int("opl"); if (sb->opl_enabled) - opl2_init(&sb->opl); + fm_driver_get(FM_YM3812, &sb->opl); sb_dsp_init(&sb->dsp, SB2, SB_SUBTYPE_DEFAULT, sb); sb_dsp_setaddr(&sb->dsp, addr); sb_dsp_setirq(&sb->dsp, device_get_config_int("irq")); sb_dsp_setdma8(&sb->dsp, device_get_config_int("dma")); if (mixer_addr > 0x000) - sb_ct1335_mixer_reset(sb); + sb_ct1335_mixer_reset(sb); sb->cms_enabled = device_get_config_int("cms"); /* DSP I/O handler is activated in sb_dsp_setaddr */ if (sb->opl_enabled) { - if (!sb->cms_enabled) { - io_sethandler(addr, 0x0002, opl2_read, NULL, NULL, - opl2_write, NULL, NULL, &sb->opl); - } - io_sethandler(addr + 8, 0x0002, opl2_read, NULL, NULL, - opl2_write, NULL, NULL, &sb->opl); - io_sethandler(0x0388, 0x0002, opl2_read, NULL, NULL, - opl2_write, NULL, NULL, &sb->opl); + if (!sb->cms_enabled) { + io_sethandler(addr, 0x0002, + sb->opl.read, NULL, NULL, + sb->opl.write, NULL, NULL, + sb->opl.priv); + } + io_sethandler(addr + 8, 0x0002, + sb->opl.read, NULL, NULL, + sb->opl.write, NULL, NULL, + sb->opl.priv); + io_sethandler(0x0388, 0x0002, + sb->opl.read, NULL, NULL, + sb->opl.write, NULL, NULL, + sb->opl.priv); } if (sb->cms_enabled) { - memset(&sb->cms, 0, sizeof(cms_t)); - io_sethandler(addr, 0x0004, cms_read, NULL, NULL, cms_write, NULL, NULL, &sb->cms); + memset(&sb->cms, 0, sizeof(cms_t)); + io_sethandler(addr, 0x0004, + cms_read, NULL, NULL, + cms_write, NULL, NULL, + &sb->cms); } if (mixer_addr > 0x000) { - sb->mixer_enabled = 1; - io_sethandler(mixer_addr + 4, 0x0002, sb_ct1335_mixer_read, NULL, NULL, - sb_ct1335_mixer_write, NULL, NULL, sb); + sb->mixer_enabled = 1; + io_sethandler(mixer_addr + 4, 0x0002, + sb_ct1335_mixer_read, NULL, NULL, + sb_ct1335_mixer_write, NULL, NULL, + sb); } else - sb->mixer_enabled = 0; + sb->mixer_enabled = 0; sound_add_handler(sb_get_buffer_sb2, sb); sound_set_cd_audio_filter(sb2_filter_cd_audio, sb); if (device_get_config_int("receive_input")) - midi_in_handler(1, sb_dsp_input_msg, sb_dsp_input_sysex, &sb->dsp); + midi_in_handler(1, sb_dsp_input_msg, sb_dsp_input_sysex, &sb->dsp); return sb; } - static uint8_t sb_pro_v1_opl_read(uint16_t port, void *priv) { - sb_t *sb = (sb_t *)priv; + sb_t *sb = (sb_t *) priv; cycles -= ((int) (isa_timing * 8)); - (void)opl2_read(port, &sb->opl2); // read, but ignore - return(opl2_read(port, &sb->opl)); + (void) sb->opl2.read(port, sb->opl2.priv); // read, but ignore + return (sb->opl.read(port, sb->opl.priv)); } - static void sb_pro_v1_opl_write(uint16_t port, uint8_t val, void *priv) { - sb_t *sb = (sb_t *)priv; + sb_t *sb = (sb_t *) priv; - opl2_write(port, val, &sb->opl); - opl2_write(port, val, &sb->opl2); + sb->opl.write(port, val, sb->opl.priv); + sb->opl2.write(port, val, sb->opl2.priv); } - static void * -sb_pro_v1_init(const device_t *info) +sb_pro_v1_init(UNUSED(const device_t *info)) { /* SB Pro port mappings, 220h or 240h. 2x0 to 2x3 -> FM chip, Left and Right (9*2 voices) @@ -1482,16 +1925,16 @@ sb_pro_v1_init(const device_t *info) 2x6, 2xA, 2xC, 2xE -> DSP chip 2x8, 2x9, 388 and 389 FM chip (9 voices) 2x0+10 to 2x0+13 CDROM interface. */ - sb_t *sb = malloc(sizeof(sb_t)); + sb_t *sb = malloc(sizeof(sb_t)); uint16_t addr = device_get_config_hex16("base"); memset(sb, 0, sizeof(sb_t)); sb->opl_enabled = device_get_config_int("opl"); if (sb->opl_enabled) { - opl2_init(&sb->opl); - opl_set_do_cycles(&sb->opl, 0); - opl2_init(&sb->opl2); - opl_set_do_cycles(&sb->opl2, 0); + fm_driver_get(FM_YM3812, &sb->opl); + sb->opl.set_do_cycles(sb->opl.priv, 0); + fm_driver_get(FM_YM3812, &sb->opl2); + sb->opl2.set_do_cycles(sb->opl2.priv, 0); } sb_dsp_init(&sb->dsp, SBPRO, SB_SUBTYPE_DEFAULT, sb); @@ -1501,31 +1944,40 @@ sb_pro_v1_init(const device_t *info) sb_ct1345_mixer_reset(sb); /* DSP I/O handler is activated in sb_dsp_setaddr */ if (sb->opl_enabled) { - io_sethandler(addr, 0x0002, opl2_read, NULL, NULL, - opl2_write, NULL, NULL, &sb->opl); - io_sethandler(addr + 2, 0x0002, opl2_read, NULL, NULL, - opl2_write, NULL, NULL, &sb->opl2); - io_sethandler(addr + 8, 0x0002, sb_pro_v1_opl_read, NULL, NULL, - sb_pro_v1_opl_write, NULL, NULL, sb); - io_sethandler(0x0388, 0x0002, sb_pro_v1_opl_read, NULL, NULL, - sb_pro_v1_opl_write, NULL, NULL, sb); + io_sethandler(addr, 0x0002, + sb->opl.read, NULL, NULL, + sb->opl.write, NULL, NULL, + sb->opl.priv); + io_sethandler(addr + 2, 0x0002, + sb->opl2.read, NULL, NULL, + sb->opl2.write, NULL, NULL, + sb->opl2.priv); + io_sethandler(addr + 8, 0x0002, + sb_pro_v1_opl_read, NULL, NULL, + sb_pro_v1_opl_write, NULL, NULL, + sb); + io_sethandler(0x0388, 0x0002, + sb_pro_v1_opl_read, NULL, NULL, + sb_pro_v1_opl_write, NULL, NULL, + sb); } sb->mixer_enabled = 1; - io_sethandler(addr + 4, 0x0002, sb_ct1345_mixer_read, NULL, NULL, - sb_ct1345_mixer_write, NULL, NULL, sb); + io_sethandler(addr + 4, 0x0002, + sb_ct1345_mixer_read, NULL, NULL, + sb_ct1345_mixer_write, NULL, NULL, + sb); sound_add_handler(sb_get_buffer_sbpro, sb); sound_set_cd_audio_filter(sbpro_filter_cd_audio, sb); if (device_get_config_int("receive_input")) - midi_in_handler(1, sb_dsp_input_msg, sb_dsp_input_sysex, &sb->dsp); + midi_in_handler(1, sb_dsp_input_msg, sb_dsp_input_sysex, &sb->dsp); return sb; } - static void * -sb_pro_v2_init(const device_t *info) +sb_pro_v2_init(UNUSED(const device_t *info)) { /* SB Pro 2 port mappings, 220h or 240h. 2x0 to 2x3 -> FM chip (18 voices) @@ -1533,13 +1985,13 @@ sb_pro_v2_init(const device_t *info) 2x6, 2xA, 2xC, 2xE -> DSP chip 2x8, 2x9, 388 and 389 FM chip (9 voices) 2x0+10 to 2x0+13 CDROM interface. */ - sb_t *sb = malloc(sizeof(sb_t)); + sb_t *sb = malloc(sizeof(sb_t)); uint16_t addr = device_get_config_hex16("base"); memset(sb, 0, sizeof(sb_t)); sb->opl_enabled = device_get_config_int("opl"); if (sb->opl_enabled) - opl3_init(&sb->opl); + fm_driver_get(FM_YMF262, &sb->opl); sb_dsp_init(&sb->dsp, SBPRO2, SB_SUBTYPE_DEFAULT, sb); sb_dsp_setaddr(&sb->dsp, addr); @@ -1548,29 +2000,36 @@ sb_pro_v2_init(const device_t *info) sb_ct1345_mixer_reset(sb); /* DSP I/O handler is activated in sb_dsp_setaddr */ if (sb->opl_enabled) { - io_sethandler(addr, 0x0004, opl3_read, NULL, NULL, - opl3_write, NULL, NULL, &sb->opl); - io_sethandler(addr + 8, 0x0002, opl3_read, NULL, NULL, - opl3_write, NULL, NULL, &sb->opl); - io_sethandler(0x0388, 0x0004, opl3_read, NULL, NULL, - opl3_write, NULL, NULL, &sb->opl); + io_sethandler(addr, 0x0004, + sb->opl.read, NULL, NULL, + sb->opl.write, NULL, NULL, + sb->opl.priv); + io_sethandler(addr + 8, 0x0002, + sb->opl.read, NULL, NULL, + sb->opl.write, NULL, NULL, + sb->opl.priv); + io_sethandler(0x0388, 0x0004, + sb->opl.read, NULL, NULL, + sb->opl.write, NULL, NULL, + sb->opl.priv); } sb->mixer_enabled = 1; - io_sethandler(addr + 4, 0x0002, sb_ct1345_mixer_read, NULL, NULL, - sb_ct1345_mixer_write, NULL, NULL, sb); + io_sethandler(addr + 4, 0x0002, + sb_ct1345_mixer_read, NULL, NULL, + sb_ct1345_mixer_write, NULL, NULL, + sb); sound_add_handler(sb_get_buffer_sbpro, sb); sound_set_cd_audio_filter(sbpro_filter_cd_audio, sb); if (device_get_config_int("receive_input")) - midi_in_handler(1, sb_dsp_input_msg, sb_dsp_input_sysex, &sb->dsp); + midi_in_handler(1, sb_dsp_input_msg, sb_dsp_input_sysex, &sb->dsp); return sb; } - static void * -sb_pro_mcv_init(const device_t *info) +sb_pro_mcv_init(UNUSED(const device_t *info)) { /* SB Pro MCV port mappings, 220h or 240h. 2x0 to 2x3 -> FM chip, Left and Right (18 voices) @@ -1581,7 +2040,7 @@ sb_pro_mcv_init(const device_t *info) memset(sb, 0, sizeof(sb_t)); sb->opl_enabled = 1; - opl3_init(&sb->opl); + fm_driver_get(FM_YMF262, &sb->opl); sb_dsp_init(&sb->dsp, SBPRO2, SB_SUBTYPE_DEFAULT, sb); sb_ct1345_mixer_reset(sb); @@ -1596,23 +2055,22 @@ sb_pro_mcv_init(const device_t *info) sb->pos_regs[1] = 0x51; if (device_get_config_int("receive_input")) - midi_in_handler(1, sb_dsp_input_msg, sb_dsp_input_sysex, &sb->dsp); + midi_in_handler(1, sb_dsp_input_msg, sb_dsp_input_sysex, &sb->dsp); return sb; } - static void * -sb_pro_compat_init(const device_t *info) +sb_pro_compat_init(UNUSED(const device_t *info)) { sb_t *sb = malloc(sizeof(sb_t)); memset(sb, 0, sizeof(sb_t)); - opl3_init(&sb->opl); + fm_driver_get(FM_YMF262, &sb->opl); sb_dsp_init(&sb->dsp, SBPRO2, SB_SUBTYPE_DEFAULT, sb); sb_ct1345_mixer_reset(sb); - + sb->mixer_enabled = 1; sound_add_handler(sb_get_buffer_sbpro, sb); @@ -1624,72 +2082,89 @@ sb_pro_compat_init(const device_t *info) return sb; } - static void * -sb_16_init(const device_t *info) +sb_16_init(UNUSED(const device_t *info)) { - sb_t *sb = malloc(sizeof(sb_t)); - uint16_t addr = device_get_config_hex16("base"); + sb_t *sb = malloc(sizeof(sb_t)); + uint16_t addr = device_get_config_hex16("base"); uint16_t mpu_addr = device_get_config_hex16("base401"); memset(sb, 0x00, sizeof(sb_t)); sb->opl_enabled = device_get_config_int("opl"); if (sb->opl_enabled) - opl3_init(&sb->opl); + fm_driver_get(info->local, &sb->opl); - sb_dsp_init(&sb->dsp, SB16, SB_SUBTYPE_DEFAULT, sb); + sb_dsp_init(&sb->dsp, (info->local == FM_YMF289B) ? SBAWE32PNP : SB16, SB_SUBTYPE_DEFAULT, sb); sb_dsp_setaddr(&sb->dsp, addr); sb_dsp_setirq(&sb->dsp, device_get_config_int("irq")); sb_dsp_setdma8(&sb->dsp, device_get_config_int("dma")); sb_dsp_setdma16(&sb->dsp, device_get_config_int("dma16")); + sb_dsp_setdma16_supported(&sb->dsp, 1); + sb_dsp_setdma16_enabled(&sb->dsp, 1); sb_ct1745_mixer_reset(sb); if (sb->opl_enabled) { - io_sethandler(addr, 0x0004, opl3_read, NULL, NULL, - opl3_write, NULL, NULL, &sb->opl); - io_sethandler(addr + 8, 0x0002, opl3_read, NULL, NULL, - opl3_write, NULL, NULL, &sb->opl); - io_sethandler(0x0388, 0x0004, opl3_read, NULL, NULL, - opl3_write, NULL, NULL, &sb->opl); + io_sethandler(addr, 0x0004, + sb->opl.read, NULL, NULL, + sb->opl.write, NULL, NULL, + sb->opl.priv); + io_sethandler(addr + 8, 0x0002, + sb->opl.read, NULL, NULL, + sb->opl.write, NULL, NULL, + sb->opl.priv); + io_sethandler(0x0388, 0x0004, + sb->opl.read, NULL, NULL, + sb->opl.write, NULL, NULL, + sb->opl.priv); } - sb->mixer_enabled = 1; - io_sethandler(addr + 4, 0x0002, sb_ct1745_mixer_read, NULL, NULL, - sb_ct1745_mixer_write, NULL, NULL, sb); + sb->mixer_enabled = 1; + sb->mixer_sb16.output_filter = 1; + io_sethandler(addr + 4, 0x0002, sb_ct1745_mixer_read, NULL, NULL, + sb_ct1745_mixer_write, NULL, NULL, sb); sound_add_handler(sb_get_buffer_sb16_awe32, sb); sound_set_cd_audio_filter(sb16_awe32_filter_cd_audio, sb); + if (device_get_config_int("control_pc_speaker")) + sound_set_pc_speaker_filter(sb16_awe32_filter_pc_speaker, sb); if (mpu_addr) { - sb->mpu = (mpu_t *) malloc(sizeof(mpu_t)); - memset(sb->mpu, 0, sizeof(mpu_t)); - mpu401_init(sb->mpu, device_get_config_hex16("base401"), device_get_config_int("irq"), M_UART, device_get_config_int("receive_input401")); + sb->mpu = (mpu_t *) malloc(sizeof(mpu_t)); + memset(sb->mpu, 0, sizeof(mpu_t)); + mpu401_init(sb->mpu, device_get_config_hex16("base401"), device_get_config_int("irq"), M_UART, device_get_config_int("receive_input401")); } else - sb->mpu = NULL; + sb->mpu = NULL; sb_dsp_set_mpu(&sb->dsp, sb->mpu); if (device_get_config_int("receive_input")) - midi_in_handler(1, sb_dsp_input_msg, sb_dsp_input_sysex, &sb->dsp); + midi_in_handler(1, sb_dsp_input_msg, sb_dsp_input_sysex, &sb->dsp); + + sb->gameport = gameport_add(&gameport_pnp_device); + sb->gameport_addr = 0x200; return sb; } - static void * -sb_16_pnp_init(const device_t *info) +sb_16_reply_mca_init(UNUSED(const device_t *info)) { sb_t *sb = malloc(sizeof(sb_t)); memset(sb, 0x00, sizeof(sb_t)); sb->opl_enabled = 1; - opl3_init(&sb->opl); + fm_driver_get(FM_YMF262, &sb->opl); sb_dsp_init(&sb->dsp, SB16, SB_SUBTYPE_DEFAULT, sb); + sb_dsp_setdma16_supported(&sb->dsp, 1); + sb_dsp_setdma16_enabled(&sb->dsp, 1); sb_ct1745_mixer_reset(sb); - sb->mixer_enabled = 1; + sb->mixer_enabled = 1; + sb->mixer_sb16.output_filter = 1; sound_add_handler(sb_get_buffer_sb16_awe32, sb); sound_set_cd_audio_filter(sb16_awe32_filter_cd_audio, sb); + if (device_get_config_int("control_pc_speaker")) + sound_set_pc_speaker_filter(sb16_awe32_filter_pc_speaker, sb); sb->mpu = (mpu_t *) malloc(sizeof(mpu_t)); memset(sb->mpu, 0, sizeof(mpu_t)); @@ -1697,131 +2172,317 @@ sb_16_pnp_init(const device_t *info) sb_dsp_set_mpu(&sb->dsp, sb->mpu); if (device_get_config_int("receive_input")) - midi_in_handler(1, sb_dsp_input_msg, sb_dsp_input_sysex, &sb->dsp); + midi_in_handler(1, sb_dsp_input_msg, sb_dsp_input_sysex, &sb->dsp); - sb->gameport = gameport_add(&gameport_pnp_device); + sb->gameport = gameport_add(&gameport_device); - device_add(&ide_ter_pnp_device); + /* I/O handlers activated in sb_pro_mcv_write */ + mca_add(sb_16_reply_mca_read, sb_16_reply_mca_write, sb_mcv_feedb, NULL, sb); + sb->pos_regs[0] = 0x38; + sb->pos_regs[1] = 0x51; - isapnp_add_card(sb_16_pnp_rom, sizeof(sb_16_pnp_rom), sb_16_pnp_config_changed, NULL, NULL, NULL, sb); + sb->gameport_addr = 0x200; return sb; } - -static int -sb_awe32_available() -{ - return rom_present("roms/sound/awe32.raw"); -} - - -static int -sb_32_pnp_available() -{ - return sb_awe32_available() && rom_present("roms/sound/CT3600 PnP.BIN"); -} - - -static int -sb_awe32_pnp_available() -{ - return sb_awe32_available() && rom_present("roms/sound/CT3980 PnP.BIN"); -} - - -static int -sb_awe64_value_available() -{ - return sb_awe32_available() && rom_present("roms/sound/CT4520 PnP.BIN"); -} - - -static int -sb_awe64_available() -{ - return sb_awe32_available() && rom_present("roms/sound/CT4520 PnP.BIN"); -} - - -static int -sb_awe64_gold_available() -{ - return sb_awe32_available() && rom_present("roms/sound/CT4540 PnP.BIN"); -} - - static void * -sb_awe32_init(const device_t *info) +sb_16_pnp_init(UNUSED(const device_t *info)) { sb_t *sb = malloc(sizeof(sb_t)); - uint16_t addr = device_get_config_hex16("base"); - uint16_t mpu_addr = device_get_config_hex16("base401"); - uint16_t emu_addr = device_get_config_hex16("emu_base"); - int onboard_ram = device_get_config_int("onboard_ram"); + memset(sb, 0x00, sizeof(sb_t)); + + sb->pnp = 1; + + sb->opl_enabled = 1; + fm_driver_get(FM_YMF262, &sb->opl); + + sb_dsp_init(&sb->dsp, SB16, SB_SUBTYPE_DEFAULT, sb); + sb_dsp_setdma16_supported(&sb->dsp, 1); + sb_ct1745_mixer_reset(sb); + + sb->mixer_enabled = 1; + sb->mixer_sb16.output_filter = 1; + sound_add_handler(sb_get_buffer_sb16_awe32, sb); + sound_set_cd_audio_filter(sb16_awe32_filter_cd_audio, sb); + if (device_get_config_int("control_pc_speaker")) + sound_set_pc_speaker_filter(sb16_awe32_filter_pc_speaker, sb); + + sb->mpu = (mpu_t *) malloc(sizeof(mpu_t)); + memset(sb->mpu, 0, sizeof(mpu_t)); + mpu401_init(sb->mpu, 0, 0, M_UART, device_get_config_int("receive_input401")); + sb_dsp_set_mpu(&sb->dsp, sb->mpu); + + if (device_get_config_int("receive_input")) + midi_in_handler(1, sb_dsp_input_msg, sb_dsp_input_sysex, &sb->dsp); + + sb->gameport = gameport_add(&gameport_pnp_device); + + device_add(&ide_qua_pnp_device); + + isapnp_add_card(sb_16_pnp_rom, sizeof(sb_16_pnp_rom), sb_16_pnp_config_changed, NULL, NULL, NULL, sb); + + sb_dsp_setaddr(&sb->dsp, 0); + sb_dsp_setirq(&sb->dsp, 0); + sb_dsp_setdma8(&sb->dsp, ISAPNP_DMA_DISABLED); + sb_dsp_setdma16(&sb->dsp, ISAPNP_DMA_DISABLED); + + mpu401_change_addr(sb->mpu, 0); + ide_remove_handlers(3); + + sb->gameport_addr = 0; + gameport_remap(sb->gameport, 0); + + return sb; +} + +static int +sb_vibra16xv_available(void) +{ + return rom_present("roms/sound/creative/CT4170 PnP.BIN"); +} + +static int +sb_vibra16c_available(void) +{ + return rom_present("roms/sound/creative/CT4180 PnP.BIN"); +} + +static void * +sb_vibra16_pnp_init(UNUSED(const device_t *info)) +{ + sb_t *sb = malloc(sizeof(sb_t)); + memset(sb, 0x00, sizeof(sb_t)); + + sb->pnp = 1; + + sb->opl_enabled = 1; + fm_driver_get(FM_YMF262, &sb->opl); + + sb_dsp_init(&sb->dsp, (info->local == 0) ? SBAWE64 : SBAWE32PNP, SB_SUBTYPE_DEFAULT, sb); + /* The ViBRA 16XV does 16-bit DMA through 8-bit DMA. */ + sb_dsp_setdma16_supported(&sb->dsp, info->local != 0); + sb_ct1745_mixer_reset(sb); + + sb->mixer_enabled = 1; + sb->mixer_sb16.output_filter = 1; + sound_add_handler(sb_get_buffer_sb16_awe32, sb); + sound_set_cd_audio_filter(sb16_awe32_filter_cd_audio, sb); + if (device_get_config_int("control_pc_speaker")) + sound_set_pc_speaker_filter(sb16_awe32_filter_pc_speaker, sb); + + sb->mpu = (mpu_t *) malloc(sizeof(mpu_t)); + memset(sb->mpu, 0, sizeof(mpu_t)); + mpu401_init(sb->mpu, 0, 0, M_UART, device_get_config_int("receive_input401")); + sb_dsp_set_mpu(&sb->dsp, sb->mpu); + + if (device_get_config_int("receive_input")) + midi_in_handler(1, sb_dsp_input_msg, sb_dsp_input_sysex, &sb->dsp); + + sb->gameport = gameport_add(&gameport_pnp_device); + + const char *pnp_rom_file = NULL; + switch (info->local) { + case 0: + pnp_rom_file = "roms/sound/creative/CT4170 PnP.BIN"; + break; + + case 1: + pnp_rom_file = "roms/sound/creative/CT4180 PnP.BIN"; + break; + + default: + break; + } + + uint8_t *pnp_rom = NULL; + if (pnp_rom_file) { + FILE *fp = rom_fopen(pnp_rom_file, "rb"); + if (fp) { + if (fread(sb->pnp_rom, 1, 512, fp) == 512) + pnp_rom = sb->pnp_rom; + fclose(fp); + } + } + + switch (info->local) { + case 0: + case 1: + isapnp_add_card(pnp_rom, sizeof(sb->pnp_rom), sb_vibra16_pnp_config_changed, + NULL, NULL, NULL, sb); + break; + + default: + break; + } + + sb_dsp_setaddr(&sb->dsp, 0); + sb_dsp_setirq(&sb->dsp, 0); + sb_dsp_setdma8(&sb->dsp, ISAPNP_DMA_DISABLED); + sb_dsp_setdma16(&sb->dsp, ISAPNP_DMA_DISABLED); + + mpu401_change_addr(sb->mpu, 0); + + sb->gameport_addr = 0; + gameport_remap(sb->gameport, 0); + + return sb; +} + +static void * +sb_16_compat_init(const device_t *info) +{ + sb_t *sb = malloc(sizeof(sb_t)); + memset(sb, 0, sizeof(sb_t)); + + fm_driver_get(FM_YMF262, &sb->opl); + + sb_dsp_init(&sb->dsp, SB16, SB_SUBTYPE_DEFAULT, sb); + sb_dsp_setdma16_supported(&sb->dsp, 1); + sb_dsp_setdma16_enabled(&sb->dsp, 1); + sb_ct1745_mixer_reset(sb); + + sb->mixer_enabled = 1; + sound_add_handler(sb_get_buffer_sb16_awe32, sb); + + sb->mpu = (mpu_t *) malloc(sizeof(mpu_t)); + memset(sb->mpu, 0, sizeof(mpu_t)); + mpu401_init(sb->mpu, 0, 0, M_UART, info->local); + sb_dsp_set_mpu(&sb->dsp, sb->mpu); + + sb->gameport = gameport_add(&gameport_pnp_device); + sb->gameport_addr = 0x200; + + return sb; +} + +static int +sb_awe32_available(void) +{ + return rom_present("roms/sound/creative/awe32.raw"); +} + +static int +sb_32_pnp_available(void) +{ + return sb_awe32_available() && rom_present("roms/sound/creative/CT3600 PnP.BIN"); +} + +static int +sb_awe32_pnp_available(void) +{ + return sb_awe32_available() && rom_present("roms/sound/creative/CT3980 PnP.BIN"); +} + +static int +sb_awe64_value_available(void) +{ + return sb_awe32_available() && rom_present("roms/sound/creative/CT4520 PnP.BIN"); +} + +static int +sb_awe64_available(void) +{ + return sb_awe32_available() && rom_present("roms/sound/creative/CT4520 PnP.BIN"); +} + +static int +sb_awe64_gold_available(void) +{ + return sb_awe32_available() && rom_present("roms/sound/creative/CT4540 PnP.BIN"); +} + +static void * +sb_awe32_init(UNUSED(const device_t *info)) +{ + sb_t *sb = malloc(sizeof(sb_t)); + uint16_t addr = device_get_config_hex16("base"); + uint16_t mpu_addr = device_get_config_hex16("base401"); + uint16_t emu_addr = device_get_config_hex16("emu_base"); + int onboard_ram = device_get_config_int("onboard_ram"); memset(sb, 0x00, sizeof(sb_t)); sb->opl_enabled = device_get_config_int("opl"); if (sb->opl_enabled) - opl3_init(&sb->opl); + fm_driver_get(FM_YMF262, &sb->opl); sb_dsp_init(&sb->dsp, SBAWE32, SB_SUBTYPE_DEFAULT, sb); sb_dsp_setaddr(&sb->dsp, addr); sb_dsp_setirq(&sb->dsp, device_get_config_int("irq")); sb_dsp_setdma8(&sb->dsp, device_get_config_int("dma")); sb_dsp_setdma16(&sb->dsp, device_get_config_int("dma16")); + sb_dsp_setdma16_supported(&sb->dsp, 1); + sb_dsp_setdma16_enabled(&sb->dsp, 1); sb_ct1745_mixer_reset(sb); if (sb->opl_enabled) { - io_sethandler(addr, 0x0004, opl3_read, NULL, NULL, - opl3_write, NULL, NULL, &sb->opl); - io_sethandler(addr + 8, 0x0002, opl3_read, NULL, NULL, - opl3_write, NULL, NULL, &sb->opl); - io_sethandler(0x0388, 0x0004, opl3_read, NULL, NULL, - opl3_write, NULL, NULL, &sb->opl); + io_sethandler(addr, 0x0004, + sb->opl.read, NULL, NULL, + sb->opl.write, NULL, NULL, + sb->opl.priv); + io_sethandler(addr + 8, 0x0002, + sb->opl.read, NULL, NULL, + sb->opl.write, NULL, NULL, + sb->opl.priv); + io_sethandler(0x0388, 0x0004, + sb->opl.read, NULL, NULL, + sb->opl.write, NULL, NULL, + sb->opl.priv); } - sb->mixer_enabled = 1; - io_sethandler(addr + 4, 0x0002, sb_ct1745_mixer_read, NULL, NULL, - sb_ct1745_mixer_write, NULL, NULL, sb); + sb->mixer_enabled = 1; + sb->mixer_sb16.output_filter = 1; + io_sethandler(addr + 4, 0x0002, sb_ct1745_mixer_read, NULL, NULL, + sb_ct1745_mixer_write, NULL, NULL, sb); sound_add_handler(sb_get_buffer_sb16_awe32, sb); sound_set_cd_audio_filter(sb16_awe32_filter_cd_audio, sb); + if (device_get_config_int("control_pc_speaker")) + sound_set_pc_speaker_filter(sb16_awe32_filter_pc_speaker, sb); if (mpu_addr) { - sb->mpu = (mpu_t *) malloc(sizeof(mpu_t)); - memset(sb->mpu, 0, sizeof(mpu_t)); - mpu401_init(sb->mpu, device_get_config_hex16("base401"), device_get_config_int("irq"), M_UART, device_get_config_int("receive_input401")); + sb->mpu = (mpu_t *) malloc(sizeof(mpu_t)); + memset(sb->mpu, 0, sizeof(mpu_t)); + mpu401_init(sb->mpu, device_get_config_hex16("base401"), device_get_config_int("irq"), M_UART, device_get_config_int("receive_input401")); } else - sb->mpu = NULL; + sb->mpu = NULL; sb_dsp_set_mpu(&sb->dsp, sb->mpu); emu8k_init(&sb->emu8k, emu_addr, onboard_ram); if (device_get_config_int("receive_input")) - midi_in_handler(1, sb_dsp_input_msg, sb_dsp_input_sysex, &sb->dsp); + midi_in_handler(1, sb_dsp_input_msg, sb_dsp_input_sysex, &sb->dsp); + + sb->gameport = gameport_add(&gameport_pnp_device); + sb->gameport_addr = 0x200; return sb; } - static void * sb_awe32_pnp_init(const device_t *info) { - sb_t *sb = malloc(sizeof(sb_t)); - int onboard_ram = device_get_config_int("onboard_ram"); + sb_t *sb = malloc(sizeof(sb_t)); + int onboard_ram = device_get_config_int("onboard_ram"); memset(sb, 0x00, sizeof(sb_t)); - sb->opl_enabled = 1; - opl3_init(&sb->opl); + sb->pnp = 1; - sb_dsp_init(&sb->dsp, ((info->local == 2) || (info->local == 3) || (info->local == 4)) ? SBAWE64 : SBAWE32, SB_SUBTYPE_DEFAULT, sb); + sb->opl_enabled = 1; + fm_driver_get(FM_YMF262, &sb->opl); + + sb_dsp_init(&sb->dsp, ((info->local == 2) || (info->local == 3) || (info->local == 4)) ? + SBAWE64 : SBAWE32PNP, SB_SUBTYPE_DEFAULT, sb); + sb_dsp_setdma16_supported(&sb->dsp, 1); sb_ct1745_mixer_reset(sb); - sb->mixer_enabled = 1; + sb->mixer_enabled = 1; + sb->mixer_sb16.output_filter = 1; sound_add_handler(sb_get_buffer_sb16_awe32, sb); sound_set_cd_audio_filter(sb16_awe32_filter_cd_audio, sb); + if (device_get_config_int("control_pc_speaker")) + sound_set_pc_speaker_filter(sb16_awe32_filter_pc_speaker, sb); sb->mpu = (mpu_t *) malloc(sizeof(mpu_t)); memset(sb->mpu, 0, sizeof(mpu_t)); @@ -1831,1120 +2492,1685 @@ sb_awe32_pnp_init(const device_t *info) emu8k_init(&sb->emu8k, 0, onboard_ram); if (device_get_config_int("receive_input")) - midi_in_handler(1, sb_dsp_input_msg, sb_dsp_input_sysex, &sb->dsp); + midi_in_handler(1, sb_dsp_input_msg, sb_dsp_input_sysex, &sb->dsp); sb->gameport = gameport_add(&gameport_pnp_device); if ((info->local != 2) && (info->local != 3) && (info->local != 4)) - device_add(&ide_ter_pnp_device); + device_add(&ide_qua_pnp_device); - char *pnp_rom_file = NULL; + const char *pnp_rom_file = NULL; switch (info->local) { - case 0: - pnp_rom_file = "roms/sound/CT3600 PnP.BIN"; - break; + case 0: + pnp_rom_file = "roms/sound/creative/CT3600 PnP.BIN"; + break; - case 1: - pnp_rom_file = "roms/sound/CT3980 PnP.BIN"; - break; + case 1: + pnp_rom_file = "roms/sound/creative/CT3980 PnP.BIN"; + break; - case 2: case 3: - pnp_rom_file = "roms/sound/CT4520 PnP.BIN"; - break; + case 2: + case 3: + pnp_rom_file = "roms/sound/creative/CT4520 PnP.BIN"; + break; - case 4: - pnp_rom_file = "roms/sound/CT4540 PnP.BIN"; - break; + case 4: + pnp_rom_file = "roms/sound/creative/CT4540 PnP.BIN"; + break; + + default: + break; } uint8_t *pnp_rom = NULL; if (pnp_rom_file) { - FILE *f = rom_fopen(pnp_rom_file, "rb"); - if (f) { - if (fread(sb->pnp_rom, 1, 512, f) == 512) - pnp_rom = sb->pnp_rom; - fclose(f); - } + FILE *fp = rom_fopen(pnp_rom_file, "rb"); + if (fp) { + if (fread(sb->pnp_rom, 1, 512, fp) == 512) + pnp_rom = sb->pnp_rom; + fclose(fp); + } } switch (info->local) { - case 0: - isapnp_add_card(pnp_rom, sizeof(sb->pnp_rom), sb_16_pnp_config_changed, NULL, NULL, NULL, sb); - break; + case 0: + isapnp_add_card(pnp_rom, sizeof(sb->pnp_rom), sb_16_pnp_config_changed, NULL, NULL, NULL, sb); + break; - case 1: - isapnp_add_card(pnp_rom, sizeof(sb->pnp_rom), sb_awe32_pnp_config_changed, NULL, NULL, NULL, sb); - break; + case 1: + isapnp_add_card(pnp_rom, sizeof(sb->pnp_rom), sb_awe32_pnp_config_changed, NULL, NULL, NULL, sb); + break; - case 2: case 3: case 4: - isapnp_add_card(pnp_rom, sizeof(sb->pnp_rom), sb_awe64_gold_pnp_config_changed, NULL, NULL, NULL, sb); - break; + case 2: + case 3: + case 4: + isapnp_add_card(pnp_rom, sizeof(sb->pnp_rom), sb_awe64_gold_pnp_config_changed, NULL, NULL, NULL, sb); + break; + + default: + break; } + sb_dsp_setaddr(&sb->dsp, 0); + sb_dsp_setirq(&sb->dsp, 0); + sb_dsp_setdma8(&sb->dsp, ISAPNP_DMA_DISABLED); + sb_dsp_setdma16(&sb->dsp, ISAPNP_DMA_DISABLED); + + mpu401_change_addr(sb->mpu, 0); + if ((info->local != 2) && (info->local != 3) && (info->local != 4)) + ide_remove_handlers(3); + + emu8k_change_addr(&sb->emu8k, 0); + + sb->gameport_addr = 0; + + gameport_remap(sb->gameport, 0); + return sb; } - void -sb_close(void *p) +sb_close(void *priv) { - sb_t *sb = (sb_t *)p; + sb_t *sb = (sb_t *) priv; sb_dsp_close(&sb->dsp); free(sb); } - static void -sb_awe32_close(void *p) +sb_awe32_close(void *priv) { - sb_t *sb = (sb_t *)p; + sb_t *sb = (sb_t *) priv; emu8k_close(&sb->emu8k); sb_close(sb); } - void -sb_speed_changed(void *p) +sb_speed_changed(void *priv) { - sb_t *sb = (sb_t *)p; + sb_t *sb = (sb_t *) priv; sb_dsp_speed_changed(&sb->dsp); } - -static const device_config_t sb_config[] = -{ - { - "base", "Address", CONFIG_HEX16, "", 0x220, "", { 0 }, - { - { - "0x210", 0x210 - }, - { - "0x220", 0x220 - }, - { - "0x230", 0x230 - }, - { - "0x240", 0x240 - }, - { - "0x250", 0x250 - }, - { - "0x260", 0x260 - }, - { - "" - } - } - }, - { - "irq", "IRQ", CONFIG_SELECTION, "", 7, "", { 0 }, - { - { - "IRQ 2", 2 - }, - { - "IRQ 3", 3 - }, - { - "IRQ 5", 5 - }, - { - "IRQ 7", 7 - }, - { - "" - } - } - }, - { - "dma", "DMA", CONFIG_SELECTION, "", 1, "", { 0 }, - { - { - "DMA 1", 1 - }, - { - "DMA 3", 3 - }, - { - "" - } - } - }, - { - "opl", "Enable OPL", CONFIG_BINARY, "", 1 - }, - { - "receive_input", "Receive input (SB MIDI)", CONFIG_BINARY, "", 1 - }, - { - "", "", -1 +// clang-format off +static const device_config_t sb_config[] = { + { + .name = "base", + .description = "Address", + .type = CONFIG_HEX16, + .default_string = "", + .default_int = 0x220, + .file_filter = "", + .spinner = { 0 }, + .selection = { + { + .description = "0x210", + .value = 0x210 + }, + { + .description = "0x220", + .value = 0x220 + }, + { + .description = "0x230", + .value = 0x230 + }, + { + .description = "0x240", + .value = 0x240 + }, + { + .description = "0x250", + .value = 0x250 + }, + { + .description = "0x260", + .value = 0x260 }, + { .description = "" } } -}; - - -static const device_config_t sb15_config[] = -{ - { - "base", "Address", CONFIG_HEX16, "", 0x220, "", { 0 }, - { - { - "0x210", 0x210 - }, - { - "0x220", 0x220 - }, - { - "0x230", 0x230 - }, - { - "0x240", 0x240 - }, - { - "0x250", 0x250 - }, - { - "0x260", 0x260 - }, - { - "" - } - } - }, - { - "irq", "IRQ", CONFIG_SELECTION, "", 7, "", { 0 }, - { - { - "IRQ 2", 2 - }, - { - "IRQ 3", 3 - }, - { - "IRQ 5", 5 - }, - { - "IRQ 7", 7 - }, - { - "" - } - } - }, - { - "dma", "DMA", CONFIG_SELECTION, "", 1, "", { 0 }, - { - { - "DMA 1", 1 - }, - { - "DMA 3", 3 - }, - { - "" - } - } - }, - { - "opl", "Enable OPL", CONFIG_BINARY, "", 1 - }, - { - "cms", "Enable CMS", CONFIG_BINARY, "", 0 - }, - { - "receive_input", "Receive input (SB MIDI)", CONFIG_BINARY, "", 1 - }, - { - "", "", -1 + }, + { + .name = "irq", + .description = "IRQ", + .type = CONFIG_SELECTION, + .default_string = "", + .default_int = 7, + .file_filter = "", + .spinner = { 0 }, + .selection = { + { + .description = "IRQ 2", + .value = 2 + }, + { + .description = "IRQ 3", + .value = 3 + }, + { + .description = "IRQ 5", + .value = 5 + }, + { + .description = "IRQ 7", + .value = 7 + }, + { .description = "" } } -}; - - -static const device_config_t sb2_config[] = -{ - { - "base", "Address", CONFIG_HEX16, "", 0x220, "", { 0 }, - { - { - "0x220", 0x220 - }, - { - "0x240", 0x240 - }, - { - "0x260", 0x260 - }, - { - "" - } - } - }, - { - "mixaddr", "Mixer", CONFIG_HEX16, "", 0, "", { 0 }, - { - { - "Disabled", 0 - }, - { - "0x220", 0x220 - }, - { - "0x240", 0x240 - }, - { - "0x250", 0x250 - }, - { - "0x260", 0x260 - }, - { - "" - } - } - }, - { - "irq", "IRQ", CONFIG_SELECTION, "", 5, "", { 0 }, - { - { - "IRQ 2", 2 - }, - { - "IRQ 3", 3 - }, - { - "IRQ 5", 5 - }, - { - "IRQ 7", 7 - }, - { - "" - } - } - }, - { - "dma", "DMA", CONFIG_SELECTION, "", 1, "", { 0 }, - { - { - "DMA 1", 1 - }, - { - "DMA 3", 3 - }, - { - "" - } - } - }, - { - "opl", "Enable OPL", CONFIG_BINARY, "", 1 - }, - { - "cms", "Enable CMS", CONFIG_BINARY, "", 0 - }, - { - "receive_input", "Receive input (SB MIDI)", CONFIG_BINARY, "", 1 - }, - { - "", "", -1 + }, + { + .name = "dma", + .description = "DMA", + .type = CONFIG_SELECTION, + .default_string = "", + .default_int = 1, + .file_filter = "", + .spinner = { 0 }, + .selection = { + { + .description = "DMA 1", + .value = 1 + }, + { + .description = "DMA 3", + .value = 3 + }, + { "" } } + }, + { + .name = "opl", + .description = "Enable OPL", + .type = CONFIG_BINARY, + .default_string = "", + .default_int = 1 + }, + { + .name = "receive_input", + .description = "Receive input (SB MIDI)", + .type = CONFIG_BINARY, + .default_string = "", + .default_int = 1 + }, + { .name = "", .description = "", .type = CONFIG_END } }; -static const device_config_t sb_mcv_config[] = -{ - { - "irq", "IRQ", CONFIG_SELECTION, "", 7, "", { 0 }, - { - { - "IRQ 2", 2 - }, - { - "IRQ 3", 3 - }, - { - "IRQ 5", 5 - }, - { - "IRQ 7", 7 - }, - { - "" - } - } - }, - { - "dma", "DMA", CONFIG_SELECTION, "", 1, "", { 0 }, - { - { - "DMA 1", 1 - }, - { - "DMA 3", 3 - }, - { - "" - } - } - }, - { - "opl", "Enable OPL", CONFIG_BINARY, "", 1 - }, - { - "receive_input", "Receive input (SB MIDI)", CONFIG_BINARY, "", 1 - }, - { - "", "", -1 +static const device_config_t sb15_config[] = { + { + .name = "base", + .description = "Address", + .type = CONFIG_HEX16, + .default_string = "", + .default_int = 0x220, + .file_filter = "", + .spinner = { 0 }, + .selection = { + { + .description = "0x210", + .value = 0x210 + }, + { + .description = "0x220", + .value = 0x220 + }, + { + .description = "0x230", + .value = 0x230 + }, + { + .description = "0x240", + .value = 0x240 + }, + { + .description = "0x250", + .value = 0x250 + }, + { + .description = "0x260", + .value = 0x260 + }, + { + .description = "" } } -}; - -static const device_config_t sb_pro_config[] = -{ - { - "base", "Address", CONFIG_HEX16, "", 0x220, "", { 0 }, - { - { - "0x220", 0x220 - }, - { - "0x240", 0x240 - }, - { - "" - } - } - }, - { - "irq", "IRQ", CONFIG_SELECTION, "", 7, "", { 0 }, - { - { - "IRQ 2", 2 - }, - { - "IRQ 5", 5 - }, - { - "IRQ 7", 7 - }, - { - "IRQ 10", 10 - }, - { - "" - } - } - }, - { - "dma", "DMA", CONFIG_SELECTION, "", 1, "", { 0 }, - { - { - "DMA 0", 0 - }, - { - "DMA 1", 1 - }, - { - "DMA 3", 3 - }, - { - "" - } - } - }, - { - "opl", "Enable OPL", CONFIG_BINARY, "", 1 - }, - { - "receive_input", "Receive input (SB MIDI)", CONFIG_BINARY, "", 1 - }, - { - "", "", -1 + }, + { + .name = "irq", + .description = "IRQ", + .type = CONFIG_SELECTION, + .default_string = "", + .default_int = 7, + .file_filter = "", + .spinner = { 0 }, + .selection = { + { + .description = "IRQ 2", + .value = 2 + }, + { + .description = "IRQ 3", + .value = 3 + }, + { + .description = "IRQ 5", + .value = 5 + }, + { + .description = "IRQ 7", + .value = 7 + }, + { .description = "" } } -}; - -static const device_config_t sb_16_config[] = -{ - { - "base", "Address", CONFIG_HEX16, "", 0x220, "", { 0 }, - { - { - "0x220", 0x220 - }, - { - "0x240", 0x240 - }, - { - "0x260", 0x260 - }, - { - "0x280", 0x280 - }, - { - "" - } - } - }, - { - "base401", "MPU-401 Address", CONFIG_HEX16, "", 0x330, "", { 0 }, - { - { - "Disabled", 0 - }, - { - "0x300", 0x300 - }, - { - "0x330", 0x330 - }, - { - "" - } - } - }, - { - "irq", "IRQ", CONFIG_SELECTION, "", 5, "", { 0 }, - { - { - "IRQ 2", 2 - }, - { - "IRQ 5", 5 - }, - { - "IRQ 7", 7 - }, - { - "IRQ 10", 10 - }, - { - "" - } - } - }, - { - "dma", "Low DMA channel", CONFIG_SELECTION, "", 1, "", { 0 }, - { - { - "DMA 0", 0 - }, - { - "DMA 1", 1 - }, - { - "DMA 3", 3 - }, - { - "" - } - } - }, - { - "dma16", "High DMA channel", CONFIG_SELECTION, "", 5, "", { 0 }, - { - { - "DMA 5", 5 - }, - { - "DMA 6", 6 - }, - { - "DMA 7", 7 - }, - { - "" - } - } - }, - { - "opl", "Enable OPL", CONFIG_BINARY, "", 1 - }, - { - "receive_input", "Receive input (SB MIDI)", CONFIG_BINARY, "", 1 - }, - { - "receive_input401", "Receive input (MPU-401)", CONFIG_BINARY, "", 0 - }, - { - "", "", -1 + }, + { + .name = "dma", + .description = "DMA", + .type = CONFIG_SELECTION, + .default_string = "", + .default_int = 1, + .file_filter = "", + .spinner = { 0 }, + .selection = { + { + .description = "DMA 1", + .value = 1 + }, + { + .description = "DMA 3", + .value = 3 + }, + { .description = "" } } + }, + { + .name = "opl", + .description = "Enable OPL", + .type = CONFIG_BINARY, + .default_string = "", + .default_int = 1 + }, + { + .name = "cms", + .description = "Enable CMS", + .type = CONFIG_BINARY, + .default_string = "", + .default_int = 0 + }, + { + .name = "receive_input", + .description = "Receive input (SB MIDI)", + .type = CONFIG_BINARY, + .default_string = "", + .default_int = 1 + }, + { .name = "", .description = "", .type = CONFIG_END } }; -static const device_config_t sb_16_pnp_config[] = -{ - { - "receive_input", "Receive input (SB MIDI)", CONFIG_BINARY, "", 1 - }, - { - "receive_input401", "Receive input (MPU-401)", CONFIG_BINARY, "", 0 - }, - { - "", "", -1 +static const device_config_t sb2_config[] = { + { + .name = "base", + .description = "Address", + .type = CONFIG_HEX16, + .default_string = "", + .default_int = 0x220, + .file_filter = "", + .spinner = { 0 }, + .selection = { + { + .description = "0x220", + .value = 0x220 + }, + { + .description = "0x240", + .value = 0x240 + }, + { + .description = "0x260", + .value = 0x260 + }, + { .description = "" } } -}; - -static const device_config_t sb_32_pnp_config[] = -{ - { - "onboard_ram", "Onboard RAM", CONFIG_SELECTION, "", 0, "", { 0 }, - { - { - "None", 0 - }, - { - "512 KB", 512 - }, - { - "2 MB", 2048 - }, - { - "8 MB", 8192 - }, - { - "28 MB", 28*1024 - }, - { - "" - } - } - }, - { - "receive_input", "Receive input (SB MIDI)", CONFIG_BINARY, "", 1 - }, - { - "receive_input401", "Receive input (MPU-401)", CONFIG_BINARY, "", 0 - }, - { - "", "", -1 + }, + { + .name = "mixaddr", + .description = "Mixer", + .type = CONFIG_HEX16, + .default_string = "", + .default_int = 0, + .file_filter = "", + .spinner = { 0 }, + .selection = { + { + .description = "Disabled", + .value = 0 + }, + { + .description = "0x220", + .value = 0x220 + }, + { + .description = "0x240", + .value = 0x240 + }, + { + .description = "0x250", + .value = 0x250 + }, + { + .description = "0x260", + .value = 0x260 + }, + { .description = "" } } -}; - -static const device_config_t sb_awe32_config[] = -{ - { - "base", "Address", CONFIG_HEX16, "", 0x220, "", { 0 }, - { - { - "0x220", 0x220 - }, - { - "0x240", 0x240 - }, - { - "0x260", 0x260 - }, - { - "0x280", 0x280 - }, - { - "" - } - } - }, - { - "emu_base", "EMU8000 Address", CONFIG_HEX16, "", 0x620, "", { 0 }, - { - { - "0x620", 0x620 - }, - { - "0x640", 0x640 - }, - { - "0x660", 0x660 - }, - { - "0x680", 0x680 - }, - { - .description = "" - } - } - }, - { - "base401", "MPU-401 Address", CONFIG_HEX16, "", 0x330, "", { 0 }, - { - { - "Disabled", 0 - }, - { - "0x300", 0x300 - }, - { - "0x330", 0x330 - }, - { - "" - } - } - }, - { - "irq", "IRQ", CONFIG_SELECTION, "", 5, "", { 0 }, - { - { - "IRQ 2", 2 - }, - { - "IRQ 5", 5 - }, - { - "IRQ 7", 7 - }, - { - "IRQ 10", 10 - }, - { - "" - } - } - }, - { - "dma", "Low DMA channel", CONFIG_SELECTION, "", 1, "", { 0 }, - { - { - "DMA 0", 0 - }, - { - "DMA 1", 1 - }, - { - "DMA 3", 3 - }, - { - "" - } - } - }, - { - "dma16", "High DMA channel", CONFIG_SELECTION, "", 5, "", { 0 }, - { - { - "DMA 5", 5 - }, - { - "DMA 6", 6 - }, - { - "DMA 7", 7 - }, - { - "" - } - } - }, - { - "onboard_ram", "Onboard RAM", CONFIG_SELECTION, "", 512, "", { 0 }, - { - { - "None", 0 - }, - { - "512 KB", 512 - }, - { - "2 MB", 2048 - }, - { - "8 MB", 8192 - }, - { - "28 MB", 28*1024 - }, - { - "" - } - } - }, - { - "opl", "Enable OPL", CONFIG_BINARY, "", 1 - }, - { - "receive_input", "Receive input (SB MIDI)", CONFIG_BINARY, "", 1 - }, - { - "receive_input401", "Receive input (MPU-401)", CONFIG_BINARY, "", 0 - }, - { - "", "", -1 + }, + { + .name = "irq", + .description = "IRQ", + .type = CONFIG_SELECTION, + .default_string = "", + .default_int = 5, + .file_filter = "", + .spinner = { 0 }, + .selection = { + { + .description = "IRQ 2", + .value = 2 + }, + { + .description = "IRQ 3", + .value = 3 + }, + { + .description = "IRQ 5", + .value = 5 + }, + { + .description = "IRQ 7", + .value = 7 + }, + { .description = "" } } -}; - -static const device_config_t sb_awe32_pnp_config[] = -{ - { - "onboard_ram", "Onboard RAM", CONFIG_SELECTION, "", 512, "", { 0 }, - { - { - "None", 0 - }, - { - "512 KB", 512 - }, - { - "2 MB", 2048 - }, - { - "8 MB", 8192 - }, - { - "28 MB", 28*1024 - }, - { - "" - } - } - }, - { - "receive_input", "Receive input (SB MIDI)", CONFIG_BINARY, "", 1 - }, - { - "receive_input401", "Receive input (MPU-401)", CONFIG_BINARY, "", 0 - }, - { - "", "", -1 + }, + { + .name = "dma", + .description = "DMA", + .type = CONFIG_SELECTION, + .default_string = "", + .default_int = 1, + .file_filter = "", + .spinner = { 0 }, + .selection = { + { + .description = "DMA 1", + .value = 1 + }, + { + .description = "DMA 3", + .value = 3 + }, + { .description = "" } } + }, + { + .name = "opl", + .description = "Enable OPL", + .type = CONFIG_BINARY, + .default_string = "", + .default_int = 1 + }, + { + .name = "cms", + .description = "Enable CMS", + .type = CONFIG_BINARY, + .default_string = "", + .default_int = 0 + }, + { + .name = "receive_input", + .description = "Receive input (SB MIDI)", + .type = CONFIG_BINARY, + .default_string = "", + .default_int = 1 + }, + { .name = "", .description = "", .type = CONFIG_END } }; -static const device_config_t sb_awe64_value_config[] = -{ - { - "onboard_ram", "Onboard RAM", CONFIG_SELECTION, "", 512, "", { 0 }, - { - { - "512 KB", 512 - }, - { - "1 MB", 1024 - }, - { - "2 MB", 2048 - }, - { - "4 MB", 4096 - }, - { - "8 MB", 8192 - }, - { - "12 MB", 12288 - }, - { - "16 MB", 16384 - }, - { - "20 MB", 20480 - }, - { - "24 MB", 24576 - }, - { - "28 MB", 28672 - }, - { - "" - } - } - }, - { - "receive_input", "Receive input (SB MIDI)", CONFIG_BINARY, "", 1 - }, - { - "receive_input401", "Receive input (MPU-401)", CONFIG_BINARY, "", 0 - }, - { - "", "", -1 +static const device_config_t sb_mcv_config[] = { + { + .name = "irq", + .description = "IRQ", + .type = CONFIG_SELECTION, + .default_string = "", + .default_int = 7, + .file_filter = "", + .spinner = { 0 }, + .selection = { + { + .description = "IRQ 2", + .value = 2 + }, + { + .description = "IRQ 3", + .value = 3 + }, + { + .description = "IRQ 5", + .value = 5 + }, + { + .description = "IRQ 7", + .value = 7 + }, + { .description = "" } } -}; - -static const device_config_t sb_awe64_config[] = -{ - { - "onboard_ram", "Onboard RAM", CONFIG_SELECTION, "", 1024, "", { 0 }, - { - { - "1 MB", 1024 - }, - { - "2 MB", 2048 - }, - { - "4 MB", 4096 - }, - { - "8 MB", 8192 - }, - { - "12 MB", 12288 - }, - { - "16 MB", 16384 - }, - { - "20 MB", 20480 - }, - { - "24 MB", 24576 - }, - { - "28 MB", 28672 - }, - { - "" - } - } - }, - { - "receive_input", "Receive input (SB MIDI)", CONFIG_BINARY, "", 1 - }, - { - "receive_input401", "Receive input (MPU-401)", CONFIG_BINARY, "", 0 - }, - { - "", "", -1 + }, + { + .name = "dma", + .description = "DMA", + .type = CONFIG_SELECTION, + .default_string = "", + .default_int = 1, + .file_filter = "", + .spinner = { 0 }, + .selection = { + { + .description = "DMA 1", + .value = 1 + }, + { + .description = "DMA 3", + .value = 3 + }, + { .description = "" } } + }, + { + .name = "opl", + .description = "Enable OPL", + .type = CONFIG_BINARY, + .default_string = "", + .default_int = 1 + }, + { + .name = "receive_input", + .description = "Receive input (SB MIDI)", + .type = CONFIG_BINARY, + .default_string = "", + .default_int = 1 + }, + { .name = "", .description = "", .type = CONFIG_END } }; -static const device_config_t sb_awe64_gold_config[] = -{ - { - "onboard_ram", "Onboard RAM", CONFIG_SELECTION, "", 4096, "", { 0 }, - { - { - "4 MB", 4096 - }, - { - "8 MB", 8192 - }, - { - "12 MB", 12288 - }, - { - "16 MB", 16384 - }, - { - "20 MB", 20480 - }, - { - "24 MB", 24576 - }, - { - "28 MB", 28672 - }, - { - "" - } - } - }, - { - "receive_input", "Receive input (SB MIDI)", CONFIG_BINARY, "", 1 - }, - { - "receive_input401", "Receive input (MPU-401)", CONFIG_BINARY, "", 0 - }, - { - "", "", -1 +static const device_config_t sb_pro_config[] = { + { + .name = "base", + .description = "Address", + .type = CONFIG_HEX16, + .default_string = "", + .default_int = 0x220, + .file_filter = "", + .spinner = { 0 }, + .selection = { + { + .description = "0x220", + .value = 0x220 + }, + { + .description = "0x240", + .value = 0x240 + }, + { .description = "" } } + }, + { + .name = "irq", + .description = "IRQ", + .type = CONFIG_SELECTION, + .default_string = "", + .default_int = 7, + .file_filter = "", + .spinner = { 0 }, + .selection = { + { + .description = "IRQ 2", + .value = 2 + }, + { + .description = "IRQ 5", + .value = 5 + }, + { + .description = "IRQ 7", + .value = 7 + }, + { + .description = "IRQ 10", + .value = 10 + }, + { .description = "" } + } + }, + { + .name = "dma", + .description = "DMA", + .type = CONFIG_SELECTION, + .default_string = "", + .default_int = 1, + .file_filter = "", + .spinner = { 0 }, + .selection = { + { + .description = "DMA 0", + .value = 0 + }, + { + .description = "DMA 1", + .value = 1 + }, + { + .description = "DMA 3", + .value = 3 + }, + { .description = "" } + } + }, + { + .name = "opl", + .description = "Enable OPL", + .type = CONFIG_BINARY, + .default_string = "", + .default_int = 1 + }, + { + .name = "receive_input", + .description = "Receive input (SB MIDI)", + .type = CONFIG_BINARY, + .default_string = "", + .default_int = 1 + }, + { .name = "", .description = "", .type = CONFIG_END } }; -const device_t sb_1_device = -{ - "Sound Blaster v1.0", - "sb", - DEVICE_ISA, - 0, - sb_1_init, sb_close, NULL, { NULL }, - sb_speed_changed, - NULL, - sb_config +static const device_config_t sb_pro_mcv_config[] = { + { + .name = "receive_input", + .description = "Receive input (SB MIDI)", + .type = CONFIG_BINARY, + .default_string = "", + .default_int = 1 + }, + { .name = "", .description = "", .type = CONFIG_END } }; -const device_t sb_15_device = -{ - "Sound Blaster v1.5", - "sb1.5", - DEVICE_ISA, - 0, - sb_15_init, sb_close, NULL, { NULL }, - sb_speed_changed, - NULL, - sb15_config +static const device_config_t sb_16_config[] = { + { + .name = "base", + .description = "Address", + .type = CONFIG_HEX16, + .default_string = "", + .default_int = 0x220, + .file_filter = "", + .spinner = { 0 }, + .selection = { + { + .description = "0x220", + .value = 0x220 + }, + { + .description = "0x240", + .value = 0x240 + }, + { + .description = "0x260", + .value = 0x260 + }, + { + .description = "0x280", + .value = 0x280 + }, + { .description = "" } + } + }, + { + .name = "base401", + .description = "MPU-401 Address", + .type = CONFIG_HEX16, + .default_string = "", + .default_int = 0x330, + .file_filter = "", + .spinner = { 0 }, + .selection = { + { + .description = "Disabled", + .value = 0 + }, + { + .description = "0x300", + .value = 0x300 + }, + { + .description = "0x330", + .value = 0x330 + }, + { .description = "" } + } + }, + { + .name = "irq", + .description = "IRQ", + .type = CONFIG_SELECTION, + .default_string = "", + .default_int = 5, + .file_filter = "", + .spinner = { 0 }, + .selection = { + { + .description = "IRQ 2", + .value = 2 + }, + { + .description = "IRQ 5", + .value = 5 + }, + { + .description = "IRQ 7", + .value = 7 + }, + { + .description = "IRQ 10", + .value = 10 + }, + { .description = "" } + } + }, + { + .name = "dma", + .description = "Low DMA channel", + .type = CONFIG_SELECTION, + .default_string = "", + .default_int = 1, + .file_filter = "", + .spinner = { 0 }, + .selection = { + { + .description = "DMA 0", + .value = 0 + }, + { + .description = "DMA 1", + .value = 1 + }, + { + .description = "DMA 3", + .value = 3 + }, + { .description = "" } + } + }, + { + .name = "dma16", + .description = "High DMA channel", + .type = CONFIG_SELECTION, + .default_string = "", + .default_int = 5, + .file_filter = "", + .spinner = { 0 }, + .selection = { + { + .description = "DMA 5", + .value = 5 + }, + { + .description = "DMA 6", + .value = 6 + }, + { + .description = "DMA 7", + .value = 7 + }, + { .description = "" } + } + }, + { + .name = "opl", + .description = "Enable OPL", + .type = CONFIG_BINARY, + .default_string = "", + .default_int = 1 + }, + { + .name = "control_pc_speaker", + .description = "Control PC speaker", + .type = CONFIG_BINARY, + .default_string = "", + .default_int = 0 + }, + { + .name = "receive_input", + .description = "Receive input (SB MIDI)", + .type = CONFIG_BINARY, + .default_string = "", + .default_int = 1 + }, + { + .name = "receive_input401", + .description = "Receive input (MPU-401)", + .type = CONFIG_BINARY, + .default_string = "", + .default_int = 0 + }, + { .name = "", .description = "", .type = CONFIG_END } }; -const device_t sb_mcv_device = -{ - "Sound Blaster MCV", - "sbmcv", - DEVICE_MCA, - 0, - sb_mcv_init, sb_close, NULL, { NULL }, - sb_speed_changed, - NULL, - sb_mcv_config +static const device_config_t sb_16_pnp_config[] = { + { + .name = "control_pc_speaker", + .description = "Control PC speaker", + .type = CONFIG_BINARY, + .default_string = "", + .default_int = 0 + }, + { + .name = "receive_input", + .description = "Receive input (SB MIDI)", + .type = CONFIG_BINARY, + .default_string = "", + .default_int = 1 + }, + { + .name = "receive_input401", + .description = "Receive input (MPU-401)", + .type = CONFIG_BINARY, + .default_string = "", + .default_int = 0 + }, + { .name = "", .description = "", .type = CONFIG_END } }; -const device_t sb_2_device = -{ - "Sound Blaster v2.0", - "sb2.0", - DEVICE_ISA, - 0, - sb_2_init, sb_close, NULL, { NULL }, - sb_speed_changed, - NULL, - sb2_config +static const device_config_t sb_32_pnp_config[] = { + { + .name = "onboard_ram", + .description = "Onboard RAM", + .type = CONFIG_SELECTION, + .default_string = "", + .default_int = 0, + .file_filter = "", + .spinner = { 0 }, + .selection = { + { + .description = "None", + .value = 0 + }, + { + .description = "512 KB", + .value = 512 + }, + { + .description = "2 MB", + .value = 2048 + }, + { + .description = "8 MB", + .value = 8192 + }, + { + .description = "28 MB", + .value = 28672 + }, + { .description = "" } + } + }, + { + .name = "control_pc_speaker", + .description = "Control PC speaker", + .type = CONFIG_BINARY, + .default_string = "", + .default_int = 0 + }, + { + .name = "receive_input", + .description = "Receive input (SB MIDI)", + .type = CONFIG_BINARY, + .default_string = "", + .default_int = 1 + }, + { + .name = "receive_input401", + .description = "Receive input (MPU-401)", + .type = CONFIG_BINARY, + .default_string = "", + .default_int = 0 + }, + { .name = "", .description = "", .type = CONFIG_END } }; -const device_t sb_pro_v1_device = -{ - "Sound Blaster Pro v1", - "sbprov1", - DEVICE_ISA, - 0, - sb_pro_v1_init, sb_close, NULL, { NULL }, - sb_speed_changed, - NULL, - sb_pro_config +static const device_config_t sb_awe32_config[] = { + { + .name = "base", + .description = "Address", + .type = CONFIG_HEX16, + .default_string = "", + .default_int = 0x220, + .file_filter = "", + .spinner = { 0 }, + .selection = { + { + .description = "0x220", + .value = 0x220 + }, + { + .description = "0x240", + .value = 0x240 + }, + { + .description = "0x260", + .value = 0x260 + }, + { + .description = "0x280", + .value = 0x280 + }, + { .description = "" } + } + }, + { + .name = "emu_base", + .description = "EMU8000 Address", + .type = CONFIG_HEX16, + .default_string = "", + .default_int = 0x620, + .file_filter = "", + .spinner = { 0 }, + .selection = { + { + .description = "0x620", + .value = 0x620 + }, + { + .description = "0x640", + .value = 0x640 + }, + { + .description = "0x660", + .value = 0x660 + }, + { + .description = "0x680", + .value = 0x680 + }, + { .description = ""} + } + }, + { + .name = "base401", + .description = "MPU-401 Address", + .type = CONFIG_HEX16, + .default_string = "", + .default_int = 0x330, + .file_filter = "", + .spinner = { 0 }, + .selection = { + { + .description = "Disabled", + .value = 0 + }, + { + .description = "0x300", + .value = 0x300 + }, + { + .description = "0x330", + .value = 0x330 + }, + { .description = "" } + } + }, + { + .name = "irq", + .description = "IRQ", + .type = CONFIG_SELECTION, + .default_string = "", + .default_int = 5, + .file_filter = "", + .spinner = { 0 }, + .selection = { + { + .description = "IRQ 2", + .value = 2 + }, + { + .description = "IRQ 5", + .value = 5 + }, + { + .description = "IRQ 7", + .value = 7 + }, + { + .description = "IRQ 10", + .value = 10 + }, + { .description = "" } + } + }, + { + .name = "dma", + .description = "Low DMA channel", + .type = CONFIG_SELECTION, + .default_string = "", + .default_int = 1, + .file_filter = "", + .spinner = { 0 }, + .selection = { + { + .description = "DMA 0", + .value = 0 + }, + { + .description = "DMA 1", + .value = 1 + }, + { + .description = "DMA 3", + .value = 3 + }, + { .description = "" } + } + }, + { + .name = "dma16", + .description = "High DMA channel", + .type = CONFIG_SELECTION, + .default_string = "", + .default_int = 5, + .file_filter = "", + .spinner = { 0 }, + .selection = { + { + .description = "DMA 5", + .value = 5 + }, + { + .description = "DMA 6", + .value = 6 + }, + { + .description = "DMA 7", + .value = 7 + }, + { .description = "" } + } + }, + { + .name = "onboard_ram", + .description = "Onboard RAM", + .type = CONFIG_SELECTION, + .default_string = "", + .default_int = 512, + .file_filter = "", + .spinner = { 0 }, + .selection = { + { + .description = "None", + .value = 0 + }, + { + .description = "512 KB", + .value = 512 + }, + { + .description = "2 MB", + .value = 2048 + }, + { + .description = "8 MB", + .value = 8192 + }, + { + .description = "28 MB", + .value = 28672 + }, + { "" } + } + }, + { + .name = "opl", + .description = "Enable OPL", + .type = CONFIG_BINARY, + .default_string = "", + .default_int = 1 + }, + { + .name = "control_pc_speaker", + .description = "Control PC speaker", + .type = CONFIG_BINARY, + .default_string = "", + .default_int = 0 + }, + { + .name = "receive_input", + .description = "Receive input (SB MIDI)", + .type = CONFIG_BINARY, + .default_string = "", + .default_int = 1 + }, + { + .name = "receive_input401", + .description = "Receive input (MPU-401)", + .type = CONFIG_BINARY, + .default_string = "", + .default_int = 0 + }, + { .name = "", .description = "", .type = CONFIG_END } }; -const device_t sb_pro_v2_device = -{ - "Sound Blaster Pro v2", - "sbprov2", - DEVICE_ISA, - 0, - sb_pro_v2_init, sb_close, NULL, { NULL }, - sb_speed_changed, - NULL, - sb_pro_config +static const device_config_t sb_awe32_pnp_config[] = { + { + .name = "onboard_ram", + .description = "Onboard RAM", + .type = CONFIG_SELECTION, + .default_string = "", + .default_int = 512, + .file_filter = "", + .spinner = { 0 }, + .selection = { + { + .description = "None", + .value = 0 + }, + { + .description = "512 KB", + .value = 512 + }, + { + .description = "2 MB", + .value = 2048 + }, + { + .description = "8 MB", + .value = 8192 + }, + { + .description = "28 MB", + .value = 28672 + }, + { .description = "" } + } + }, + { + .name = "control_pc_speaker", + .description = "Control PC speaker", + .type = CONFIG_BINARY, + .default_string = "", + .default_int = 0 + }, + { + .name = "receive_input", + .description = "Receive input (SB MIDI)", + .type = CONFIG_BINARY, + .default_string = "", + .default_int = 1 + }, + { + .name = "receive_input401", + .description = "Receive input (MPU-401)", + .type = CONFIG_BINARY, + .default_string = "", + .default_int = 0 + }, + { .name = "", .description = "", .type = CONFIG_END } }; -const device_t sb_pro_mcv_device = -{ - "Sound Blaster Pro MCV", - "sbpromcv", - DEVICE_MCA, - 0, - sb_pro_mcv_init, sb_close, NULL, { NULL }, - sb_speed_changed, - NULL, - NULL +static const device_config_t sb_awe64_value_config[] = { + { + .name = "onboard_ram", + .description = "Onboard RAM", + .type = CONFIG_SELECTION, + .default_string = "", + .default_int = 512, + .file_filter = "", + .spinner = { 0 }, + .selection = { + { + .description = "512 KB", + .value = 512 + }, + { + .description = "1 MB", + .value = 1024 + }, + { + .description = "2 MB", + .value = 2048 + }, + { + .description = "4 MB", + .value = 4096 + }, + { + .description = "8 MB", + .value = 8192 + }, + { + .description = "12 MB", + .value = 12288 + }, + { + .description = "16 MB", + .value = 16384 + }, + { + .description = "20 MB", + .value = 20480 + }, + { + .description = "24 MB", + .value = 24576 + }, + { + .description = "28 MB", + .value = 28672 + }, + { .description = "" } + } + }, + { + .name = "control_pc_speaker", + .description = "Control PC speaker", + .type = CONFIG_BINARY, + .default_string = "", + .default_int = 0 + }, + { + .name = "receive_input", + .description = "Receive input (SB MIDI)", + .type = CONFIG_BINARY, + .default_string = "", + .default_int = 1 + }, + { + .name = "receive_input401", + .description = "Receive input (MPU-401)", + .type = CONFIG_BINARY, + .default_string = "", + .default_int = 0 + }, + { .name = "", .description = "", .type = CONFIG_END } }; -const device_t sb_pro_compat_device = -{ - "Sound Blaster Pro (Compatibility)", - "sbpro_compat", - DEVICE_ISA | DEVICE_AT, - 0, - sb_pro_compat_init, sb_close, NULL, { NULL }, - sb_speed_changed, - NULL, - NULL +static const device_config_t sb_awe64_config[] = { + { + .name = "onboard_ram", + .description = "Onboard RAM", + .type = CONFIG_SELECTION, + .default_string = "", + .default_int = 1024, + .file_filter = "", + .spinner = { 0 }, + .selection = { + { + .description = "1 MB", + .value = 1024 + }, + { + .description = "2 MB", + .value = 2048 + }, + { + .description = "4 MB", + .value = 4096 + }, + { + .description = "8 MB", + .value = 8192 + }, + { + .description = "12 MB", + .value = 12288 + }, + { + .description = "16 MB", + .value = 16384 + }, + { + .description = "20 MB", + .value = 20480 + }, + { + .description = "24 MB", + .value = 24576 + }, + { + .description = "28 MB", + .value = 28672 + }, + { .description = "" } + } + }, + { + .name = "control_pc_speaker", + .description = "Control PC speaker", + .type = CONFIG_BINARY, + .default_string = "", + .default_int = 0 + }, + { + .name = "receive_input", + .description = "Receive input (SB MIDI)", + .type = CONFIG_BINARY, + .default_string = "", + .default_int = 1 + }, + { + .name = "receive_input401", + .description = "Receive input (MPU-401)", + .type = CONFIG_BINARY, + .default_string = "", + .default_int = 0 + }, + { .name = "", .description = "", .type = CONFIG_END } }; -const device_t sb_16_device = -{ - "Sound Blaster 16", - "sb16", - DEVICE_ISA | DEVICE_AT, - 0, - sb_16_init, sb_close, NULL, { NULL }, - sb_speed_changed, - NULL, - sb_16_config +static const device_config_t sb_awe64_gold_config[] = { + { + .name = "onboard_ram", + .description = "Onboard RAM", + .type = CONFIG_SELECTION, + .default_string = "", + .default_int = 4096, + .file_filter = "", + .spinner = { 0 }, + .selection = { + { + .description = "4 MB", + .value = 4096 + }, + { + .description = "8 MB", + .value = 8192 + }, + { + .description = "12 MB", + .value = 12288 + }, + { + .description = "16 MB", + .value = 16384 + }, + { + .description = "20 MB", + .value = 20480 + }, + { + .description = "24 MB", + .value = 24576 + }, + { + .description = "28 MB", + .value = 28672 + }, + { .description = "" } + } + }, + { + .name = "control_pc_speaker", + .description = "Control PC speaker", + .type = CONFIG_BINARY, + .default_string = "", + .default_int = 0 + }, + { + .name = "receive_input", + .description = "Receive input (SB MIDI)", + .type = CONFIG_BINARY, + .default_string = "", + .default_int = 1 + }, + { + .name = "receive_input401", + .description = "Receive input (MPU-401)", + .type = CONFIG_BINARY, + .default_string = "", + .default_int = 0 + }, + { .name = "", .description = "", .type = CONFIG_END } +}; +// clang-format on + +const device_t sb_1_device = { + .name = "Sound Blaster v1.0", + .internal_name = "sb", + .flags = DEVICE_ISA, + .local = 0, + .init = sb_1_init, + .close = sb_close, + .reset = NULL, + { .available = NULL }, + .speed_changed = sb_speed_changed, + .force_redraw = NULL, + .config = sb_config }; -const device_t sb_16_pnp_device = -{ - "Sound Blaster 16 PnP", - "sb16_pnp", - DEVICE_ISA | DEVICE_AT, - 0, - sb_16_pnp_init, sb_close, NULL, { NULL }, - sb_speed_changed, - NULL, - sb_16_pnp_config +const device_t sb_15_device = { + .name = "Sound Blaster v1.5", + .internal_name = "sb1.5", + .flags = DEVICE_ISA, + .local = 0, + .init = sb_15_init, + .close = sb_close, + .reset = NULL, + { .available = NULL }, + .speed_changed = sb_speed_changed, + .force_redraw = NULL, + .config = sb15_config }; -const device_t sb_32_pnp_device = -{ - "Sound Blaster 32 PnP", - "sb32_pnp", - DEVICE_ISA | DEVICE_AT, - 0, - sb_awe32_pnp_init, sb_awe32_close, NULL, - { sb_32_pnp_available }, - sb_speed_changed, - NULL, - sb_32_pnp_config +const device_t sb_mcv_device = { + .name = "Sound Blaster MCV", + .internal_name = "sbmcv", + .flags = DEVICE_MCA, + .local = 0, + .init = sb_mcv_init, + .close = sb_close, + .reset = NULL, + { .available = NULL }, + .speed_changed = sb_speed_changed, + .force_redraw = NULL, + .config = sb_mcv_config }; - -const device_t sb_awe32_device = -{ - "Sound Blaster AWE32", - "sbawe32", - DEVICE_ISA | DEVICE_AT, - 0, - sb_awe32_init, sb_awe32_close, NULL, - { sb_awe32_available }, - sb_speed_changed, - NULL, - sb_awe32_config +const device_t sb_2_device = { + .name = "Sound Blaster v2.0", + .internal_name = "sb2.0", + .flags = DEVICE_ISA, + .local = 0, + .init = sb_2_init, + .close = sb_close, + .reset = NULL, + { .available = NULL }, + .speed_changed = sb_speed_changed, + .force_redraw = NULL, + .config = sb2_config }; -const device_t sb_awe32_pnp_device = -{ - "Sound Blaster AWE32 PnP", - "sbawe32_pnp", - DEVICE_ISA | DEVICE_AT, - 1, - sb_awe32_pnp_init, sb_awe32_close, NULL, - { sb_awe32_pnp_available }, - sb_speed_changed, - NULL, - sb_awe32_pnp_config +const device_t sb_pro_v1_device = { + .name = "Sound Blaster Pro v1", + .internal_name = "sbprov1", + .flags = DEVICE_ISA, + .local = 0, + .init = sb_pro_v1_init, + .close = sb_close, + .reset = NULL, + { .available = NULL }, + .speed_changed = sb_speed_changed, + .force_redraw = NULL, + .config = sb_pro_config }; -const device_t sb_awe64_value_device = -{ - "Sound Blaster AWE64 Value", - "sbawe64_value", - DEVICE_ISA | DEVICE_AT, - 2, - sb_awe32_pnp_init, sb_awe32_close, NULL, - { sb_awe64_value_available }, - sb_speed_changed, - NULL, - sb_awe64_value_config +const device_t sb_pro_v2_device = { + .name = "Sound Blaster Pro v2", + .internal_name = "sbprov2", + .flags = DEVICE_ISA, + .local = 0, + .init = sb_pro_v2_init, + .close = sb_close, + .reset = NULL, + { .available = NULL }, + .speed_changed = sb_speed_changed, + .force_redraw = NULL, + .config = sb_pro_config }; -const device_t sb_awe64_device = -{ - "Sound Blaster AWE64", - "sbawe64", - DEVICE_ISA | DEVICE_AT, - 3, - sb_awe32_pnp_init, sb_awe32_close, NULL, - { sb_awe64_available }, - sb_speed_changed, - NULL, - sb_awe64_config +const device_t sb_pro_mcv_device = { + .name = "Sound Blaster Pro MCV", + .internal_name = "sbpromcv", + .flags = DEVICE_MCA, + .local = 0, + .init = sb_pro_mcv_init, + .close = sb_close, + .reset = NULL, + { .available = NULL }, + .speed_changed = sb_speed_changed, + .force_redraw = NULL, + .config = sb_pro_mcv_config }; -const device_t sb_awe64_gold_device = -{ - "Sound Blaster AWE64 Gold", - "sbawe64_gold", - DEVICE_ISA | DEVICE_AT, - 4, - sb_awe32_pnp_init, sb_awe32_close, NULL, - { sb_awe64_gold_available }, - sb_speed_changed, - NULL, - sb_awe64_gold_config +const device_t sb_pro_compat_device = { + .name = "Sound Blaster Pro (Compatibility)", + .internal_name = "sbpro_compat", + .flags = DEVICE_ISA | DEVICE_AT, + .local = 0, + .init = sb_pro_compat_init, + .close = sb_close, + .reset = NULL, + { .available = NULL }, + .speed_changed = sb_speed_changed, + .force_redraw = NULL, + .config = NULL +}; + +const device_t sb_16_device = { + .name = "Sound Blaster 16", + .internal_name = "sb16", + .flags = DEVICE_ISA | DEVICE_AT, + .local = FM_YMF262, + .init = sb_16_init, + .close = sb_close, + .reset = NULL, + { .available = NULL }, + .speed_changed = sb_speed_changed, + .force_redraw = NULL, + .config = sb_16_config +}; + +const device_t sb_vibra16s_onboard_device = { + .name = "Sound Blaster ViBRA 16S (On-Board)", + .internal_name = "sb_vibra16s_onboard", + .flags = DEVICE_ISA | DEVICE_AT, + .local = FM_YMF289B, + .init = sb_16_init, + .close = sb_close, + .reset = NULL, + { .available = NULL }, + .speed_changed = sb_speed_changed, + .force_redraw = NULL, + .config = sb_16_config +}; + +const device_t sb_vibra16s_device = { + .name = "Sound Blaster ViBRA 16S", + .internal_name = "sb_vibra16s", + .flags = DEVICE_ISA | DEVICE_AT, + .local = FM_YMF289B, + .init = sb_16_init, + .close = sb_close, + .reset = NULL, + { .available = NULL }, + .speed_changed = sb_speed_changed, + .force_redraw = NULL, + .config = sb_16_config +}; + +const device_t sb_vibra16xv_device = { + .name = "Sound Blaster ViBRA 16XV", + .internal_name = "sb_vibra16xv", + .flags = DEVICE_ISA | DEVICE_AT, + .local = 0, + .init = sb_vibra16_pnp_init, + .close = sb_close, + .reset = NULL, + { .available = sb_vibra16xv_available }, + .speed_changed = sb_speed_changed, + .force_redraw = NULL, + .config = sb_16_pnp_config +}; + +const device_t sb_vibra16c_onboard_device = { + .name = "Sound Blaster ViBRA 16C (On-Board)", + .internal_name = "sb_vibra16c_onboard", + .flags = DEVICE_ISA | DEVICE_AT, + .local = 1, + .init = sb_vibra16_pnp_init, + .close = sb_close, + .reset = NULL, + { .available = sb_vibra16c_available }, + .speed_changed = sb_speed_changed, + .force_redraw = NULL, + .config = sb_16_pnp_config +}; + +const device_t sb_vibra16c_device = { + .name = "Sound Blaster ViBRA 16C", + .internal_name = "sb_vibra16c", + .flags = DEVICE_ISA | DEVICE_AT, + .local = 1, + .init = sb_vibra16_pnp_init, + .close = sb_close, + .reset = NULL, + { .available = sb_vibra16c_available }, + .speed_changed = sb_speed_changed, + .force_redraw = NULL, + .config = sb_16_pnp_config +}; + +const device_t sb_16_reply_mca_device = { + .name = "Sound Blaster 16 Reply MCA", + .internal_name = "sb16_reply_mca", + .flags = DEVICE_MCA, + .local = 0, + .init = sb_16_reply_mca_init, + .close = sb_close, + .reset = NULL, + { .available = NULL }, + .speed_changed = sb_speed_changed, + .force_redraw = NULL, + .config = sb_16_pnp_config +}; + +const device_t sb_16_pnp_device = { + .name = "Sound Blaster 16 PnP", + .internal_name = "sb16_pnp", + .flags = DEVICE_ISA | DEVICE_AT, + .local = 0, + .init = sb_16_pnp_init, + .close = sb_close, + .reset = NULL, + { .available = NULL }, + .speed_changed = sb_speed_changed, + .force_redraw = NULL, + .config = sb_16_pnp_config +}; + +const device_t sb_16_compat_device = { + .name = "Sound Blaster 16 (Compatibility)", + .internal_name = "sb16_compat", + .flags = DEVICE_ISA | DEVICE_AT, + .local = 1, + .init = sb_16_compat_init, + .close = sb_close, + .reset = NULL, + { .available = NULL }, + .speed_changed = sb_speed_changed, + .force_redraw = NULL, + .config = NULL +}; + +const device_t sb_16_compat_nompu_device = { + .name = "Sound Blaster 16 (Compatibility - MPU-401 Off)", + .internal_name = "sb16_compat", + .flags = DEVICE_ISA | DEVICE_AT, + .local = 0, + .init = sb_16_compat_init, + .close = sb_close, + .reset = NULL, + { .available = NULL }, + .speed_changed = sb_speed_changed, + .force_redraw = NULL, + .config = NULL +}; + +const device_t sb_32_pnp_device = { + .name = "Sound Blaster 32 PnP", + .internal_name = "sb32_pnp", + .flags = DEVICE_ISA | DEVICE_AT, + .local = 0, + .init = sb_awe32_pnp_init, + .close = sb_awe32_close, + .reset = NULL, + { .available = sb_32_pnp_available }, + .speed_changed = sb_speed_changed, + .force_redraw = NULL, + .config = sb_32_pnp_config +}; + +const device_t sb_awe32_device = { + .name = "Sound Blaster AWE32", + .internal_name = "sbawe32", + .flags = DEVICE_ISA | DEVICE_AT, + .local = 0, + .init = sb_awe32_init, + .close = sb_awe32_close, + .reset = NULL, + { .available = sb_awe32_available }, + .speed_changed = sb_speed_changed, + .force_redraw = NULL, + .config = sb_awe32_config +}; + +const device_t sb_awe32_pnp_device = { + .name = "Sound Blaster AWE32 PnP", + .internal_name = "sbawe32_pnp", + .flags = DEVICE_ISA | DEVICE_AT, + .local = 1, + .init = sb_awe32_pnp_init, + .close = sb_awe32_close, + .reset = NULL, + { .available = sb_awe32_pnp_available }, + .speed_changed = sb_speed_changed, + .force_redraw = NULL, + .config = sb_awe32_pnp_config +}; + +const device_t sb_awe64_value_device = { + .name = "Sound Blaster AWE64 Value", + .internal_name = "sbawe64_value", + .flags = DEVICE_ISA | DEVICE_AT, + .local = 2, + .init = sb_awe32_pnp_init, + .close = sb_awe32_close, + .reset = NULL, + { .available = sb_awe64_value_available }, + .speed_changed = sb_speed_changed, + .force_redraw = NULL, + .config = sb_awe64_value_config +}; + +const device_t sb_awe64_device = { + .name = "Sound Blaster AWE64", + .internal_name = "sbawe64", + .flags = DEVICE_ISA | DEVICE_AT, + .local = 3, + .init = sb_awe32_pnp_init, + .close = sb_awe32_close, + .reset = NULL, + { .available = sb_awe64_available }, + .speed_changed = sb_speed_changed, + .force_redraw = NULL, + .config = sb_awe64_config +}; + +const device_t sb_awe64_gold_device = { + .name = "Sound Blaster AWE64 Gold", + .internal_name = "sbawe64_gold", + .flags = DEVICE_ISA | DEVICE_AT, + .local = 4, + .init = sb_awe32_pnp_init, + .close = sb_awe32_close, + .reset = NULL, + { .available = sb_awe64_gold_available }, + .speed_changed = sb_speed_changed, + .force_redraw = NULL, + .config = sb_awe64_gold_config }; diff --git a/src/sound/snd_sb_dsp.c b/src/sound/snd_sb_dsp.c index f2797431b..6fc7815ab 100644 --- a/src/sound/snd_sb_dsp.c +++ b/src/sound/snd_sb_dsp.c @@ -9,95 +9,93 @@ #include #include #include -#include #include +#include #include #define HAVE_STDARG_H + #include <86box/86box.h> -#include <86box/io.h> -#include <86box/pic.h> -#include <86box/dma.h> -#include <86box/timer.h> #include <86box/device.h> +#include <86box/dma.h> #include <86box/filters.h> -#include <86box/sound.h> +#include <86box/io.h> #include <86box/midi.h> -#include <86box/sound.h> +#include <86box/pic.h> #include <86box/snd_azt2316a.h> +#include <86box/sound.h> +#include <86box/timer.h> #include <86box/snd_sb.h> +#include <86box/plat_fallthrough.h> +#include <86box/plat_unused.h> - -#define ADPCM_4 1 -#define ADPCM_26 2 -#define ADPCM_2 3 +#define ADPCM_4 1 +#define ADPCM_26 2 +#define ADPCM_2 3 /*The recording safety margin is intended for uneven "len" calls to the get_buffer mixer calls on sound_sb*/ #define SB_DSP_REC_SAFEFTY_MARGIN 4096 -void pollsb(void *p); -void sb_poll_i(void *p); +void pollsb(void *priv); +void sb_poll_i(void *priv); static int sbe2dat[4][9] = { - { 0x01, -0x02, -0x04, 0x08, -0x10, 0x20, 0x40, -0x80, -106 }, - { -0x01, 0x02, -0x04, 0x08, 0x10, -0x20, 0x40, -0x80, 165 }, - { -0x01, 0x02, 0x04, -0x08, 0x10, -0x20, -0x40, 0x80, -151 }, - { 0x01, -0x02, 0x04, -0x08, -0x10, 0x20, -0x40, 0x80, 90 } + {0x01, -0x02, -0x04, 0x08, -0x10, 0x20, 0x40, -0x80, -106}, + { -0x01, 0x02, -0x04, 0x08, 0x10, -0x20, 0x40, -0x80, 165 }, + { -0x01, 0x02, 0x04, -0x08, 0x10, -0x20, -0x40, 0x80, -151}, + { 0x01, -0x02, 0x04, -0x08, -0x10, 0x20, -0x40, 0x80, 90 } }; -static int sb_commands[256]= -{ - -1, 2,-1, 0, 1, 2,-1, 0, 1,-1,-1,-1,-1,-1, 2, 1, - 1,-1,-1,-1, 2,-1, 2, 2,-1,-1,-1,-1, 0,-1,-1, 0, - 0,-1,-1,-1, 2,-1,-1,-1,-1,-1,-1,-1, 0,-1,-1,-1, - -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, - 1, 2, 2,-1,-1,-1,-1,-1, 2,-1,-1,-1,-1,-1,-1,-1, - -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, - -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, - -1,-1,-1,-1, 2, 2, 2, 2,-1,-1,-1,-1,-1, 0,-1, 0, - 2, 2,-1,-1,-1,-1,-1,-1, 2, 2,-1,-1,-1,-1,-1,-1, - 0,-1,-1,-1,-1,-1,-1,-1, 0,-1,-1,-1,-1,-1,-1,-1, - -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, - 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, - 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, - 0, 0,-1, 0, 0, 0, 0,-1, 0, 0, 0,-1,-1,-1,-1,-1, - 1, 0, 1, 0, 1,-1,-1, 0, 0,-1,-1,-1,-1,-1,-1,-1, - -1,-1, 0, 0,-1,-1,-1,-1,-1, 1, 2,-1,-1,-1,-1, 0 +static int sb_commands[256] = { + -1, 2, -1, 0, 1, 2, -1, 0, 1, -1, -1, -1, -1, -1, 2, 1, + 1, -1, -1, -1, 2, -1, 2, 2, -1, -1, -1, -1, 0, -1, -1, 0, + 0, -1, -1, -1, 2, -1, -1, -1, -1, -1, -1, -1, 0, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + 1, 2, 2, -1, -1, -1, -1, -1, 2, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, 2, 2, 2, 2, -1, -1, -1, -1, -1, 0, -1, 0, + 2, 2, -1, -1, -1, -1, -1, -1, 2, 2, -1, -1, -1, -1, -1, -1, + 0, -1, -1, -1, -1, -1, -1, -1, 0, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, + 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, + 0, 0, -1, 0, 0, 0, 0, -1, 0, 0, 0, -1, -1, -1, -1, -1, + 1, 0, 1, 0, 1, -1, -1, 0, 0, -1, -1, -1, -1, -1, -1, -1, + -1, -1, 0, 0, -1, -1, -1, -1, -1, 1, 2, -1, -1, -1, -1, 0 }; - -char sb16_copyright[] = "COPYRIGHT (C) CREATIVE TECHNOLOGY LTD, 1992."; -uint16_t sb_dsp_versions[] = {0, 0, 0x105, 0x200, 0x201, 0x300, 0x302, 0x405, 0x40d, 0x410}; - +char sb16_copyright[] = "COPYRIGHT (C) CREATIVE TECHNOLOGY LTD, 1992."; +uint16_t sb_dsp_versions[] = { 0, 0, 0x105, 0x200, 0x201, 0x300, 0x302, 0x405, 0x40c, 0x40d, 0x410 }; /*These tables were 'borrowed' from DOSBox*/ int8_t scaleMap4[64] = { - 0, 1, 2, 3, 4, 5, 6, 7, 0, -1, -2, -3, -4, -5, -6, -7, - 1, 3, 5, 7, 9, 11, 13, 15, -1, -3, -5, -7, -9, -11, -13, -15, - 2, 6, 10, 14, 18, 22, 26, 30, -2, -6, -10, -14, -18, -22, -26, -30, + 0, 1, 2, 3, 4, 5, 6, 7, 0, -1, -2, -3, -4, -5, -6, -7, + 1, 3, 5, 7, 9, 11, 13, 15, -1, -3, -5, -7, -9, -11, -13, -15, + 2, 6, 10, 14, 18, 22, 26, 30, -2, -6, -10, -14, -18, -22, -26, -30, 4, 12, 20, 28, 36, 44, 52, 60, -4, -12, -20, -28, -36, -44, -52, -60 }; uint8_t adjustMap4[64] = { - 0, 0, 0, 0, 0, 16, 16, 16, - 0, 0, 0, 0, 0, 16, 16, 16, + 0, 0, 0, 0, 0, 16, 16, 16, + 0, 0, 0, 0, 0, 16, 16, 16, 240, 0, 0, 0, 0, 16, 16, 16, 240, 0, 0, 0, 0, 16, 16, 16, 240, 0, 0, 0, 0, 16, 16, 16, 240, 0, 0, 0, 0, 16, 16, 16, - 240, 0, 0, 0, 0, 0, 0, 0, - 240, 0, 0, 0, 0, 0, 0, 0 + 240, 0, 0, 0, 0, 0, 0, 0, + 240, 0, 0, 0, 0, 0, 0, 0 }; int8_t scaleMap26[40] = { - 0, 1, 2, 3, 0, -1, -2, -3, - 1, 3, 5, 7, -1, -3, -5, -7, - 2, 6, 10, 14, -2, -6, -10, -14, + 0, 1, 2, 3, 0, -1, -2, -3, + 1, 3, 5, 7, -1, -3, -5, -7, + 2, 6, 10, 14, -2, -6, -10, -14, 4, 12, 20, 28, -4, -12, -20, -28, 5, 15, 25, 35, -5, -15, -25, -35 }; uint8_t adjustMap26[40] = { - 0, 0, 0, 8, 0, 0, 0, 8, + 0, 0, 0, 8, 0, 0, 0, 8, 248, 0, 0, 8, 248, 0, 0, 8, 248, 0, 0, 8, 248, 0, 0, 8, 248, 0, 0, 8, 248, 0, 0, 8, @@ -105,41 +103,38 @@ uint8_t adjustMap26[40] = { }; int8_t scaleMap2[24] = { - 0, 1, 0, -1, 1, 3, -1, -3, - 2, 6, -2, -6, 4, 12, -4, -12, + 0, 1, 0, -1, 1, 3, -1, -3, + 2, 6, -2, -6, 4, 12, -4, -12, 8, 24, -8, -24, 6, 48, -16, -48 }; uint8_t adjustMap2[24] = { - 0, 4, 0, 4, + 0, 4, 0, 4, 252, 4, 252, 4, 252, 4, 252, 4, 252, 4, 252, 4, 252, 4, 252, 4, 252, 0, 252, 0 }; -double low_fir_sb16_coef[2][SB16_NCoef]; - +double low_fir_sb16_coef[3][SB16_NCoef]; #ifdef ENABLE_SB_DSP_LOG int sb_dsp_do_log = ENABLE_SB_DSP_LOG; - static void sb_dsp_log(const char *fmt, ...) { va_list ap; if (sb_dsp_do_log) { - va_start(ap, fmt); - pclog_ex(fmt, ap); - va_end(ap); + va_start(ap, fmt); + pclog_ex(fmt, ap); + va_end(ap); } } #else -#define sb_dsp_log(fmt, ...) +# define sb_dsp_log(fmt, ...) #endif - static __inline double sinc(double x) { @@ -150,32 +145,42 @@ static void recalc_sb16_filter(int c, int playback_freq) { /* Cutoff frequency = playback / 2 */ - int n; - double w, h; - double fC = ((double) playback_freq) / 96000.0; + int n; + double w; + double h; + double fC = ((double) playback_freq) / (double) FREQ_96000; double gain; for (n = 0; n < SB16_NCoef; n++) { - /* Blackman window */ - w = 0.42 - (0.5 * cos((2.0*n*M_PI)/(double)(SB16_NCoef-1))) + (0.08 * cos((4.0*n*M_PI)/(double)(SB16_NCoef-1))); - /* Sinc filter */ - h = sinc(2.0 * fC * ((double)n - ((double)(SB16_NCoef-1) / 2.0))); + /* Blackman window */ + w = 0.42 - (0.5 * cos((2.0 * n * M_PI) / (double) (SB16_NCoef - 1))) + (0.08 * cos((4.0 * n * M_PI) / (double) (SB16_NCoef - 1))); + /* Sinc filter */ + h = sinc(2.0 * fC * ((double) n - ((double) (SB16_NCoef - 1) / 2.0))); - /* Create windowed-sinc filter */ - low_fir_sb16_coef[c][n] = w * h; + /* Create windowed-sinc filter */ + low_fir_sb16_coef[c][n] = w * h; } low_fir_sb16_coef[c][(SB16_NCoef - 1) / 2] = 1.0; gain = 0.0; for (n = 0; n < SB16_NCoef; n++) - gain += low_fir_sb16_coef[c][n]; + gain += low_fir_sb16_coef[c][n]; /* Normalise filter, to produce unity gain */ for (n = 0; n < SB16_NCoef; n++) - low_fir_sb16_coef[c][n] /= gain; + low_fir_sb16_coef[c][n] /= gain; } +static void +sb_irq_update_pic(void *priv, int set) +{ + const sb_dsp_t *dsp = (sb_dsp_t *) priv; + if (set) + picint(1 << dsp->sb_irqnum); + else + picintc(1 << dsp->sb_irqnum); +} void sb_update_mask(sb_dsp_t *dsp, int irqm8, int irqm16, int irqm401) @@ -183,62 +188,58 @@ sb_update_mask(sb_dsp_t *dsp, int irqm8, int irqm16, int irqm401) int clear = 0; if (!dsp->sb_irqm8 && irqm8) - clear |= 1; + clear |= 1; dsp->sb_irqm8 = irqm8; if (!dsp->sb_irqm16 && irqm16) - clear |= 1; + clear |= 1; dsp->sb_irqm16 = irqm16; if (!dsp->sb_irqm401 && irqm401) - clear |= 1; + clear |= 1; dsp->sb_irqm401 = irqm401; if (clear) - picintc(1 << dsp->sb_irqnum); + dsp->irq_update(dsp->irq_priv, 0); } - void sb_update_status(sb_dsp_t *dsp, int bit, int set) { int masked = 0; switch (bit) { - case 0: - default: - dsp->sb_irq8 = set; - masked = dsp->sb_irqm8; - break; - case 1: - dsp->sb_irq16 = set; - masked = dsp->sb_irqm16; - break; - case 2: - dsp->sb_irq401 = set; - masked = dsp->sb_irqm401; - break; + default: + case 0: + dsp->sb_irq8 = set; + masked = dsp->sb_irqm8; + break; + case 1: + dsp->sb_irq16 = set; + masked = dsp->sb_irqm16; + break; + case 2: + dsp->sb_irq401 = set; + masked = dsp->sb_irqm401; + break; } if (set && !masked) - picint(1 << dsp->sb_irqnum); + dsp->irq_update(dsp->irq_priv, 1); else if (!set) - picintc(1 << dsp->sb_irqnum); + dsp->irq_update(dsp->irq_priv, 0); } - void sb_irq(sb_dsp_t *dsp, int irq8) { sb_update_status(dsp, !irq8, 1); } - void sb_irqc(sb_dsp_t *dsp, int irq8) { sb_update_status(dsp, !irq8, 0); } - static void sb_dsp_irq_update(void *priv, int set) { @@ -247,26 +248,23 @@ sb_dsp_irq_update(void *priv, int set) sb_update_status(dsp, 2, set); } - static int sb_dsp_irq_pending(void *priv) { - sb_dsp_t *dsp = (sb_dsp_t *) priv; + const sb_dsp_t *dsp = (sb_dsp_t *) priv; return dsp->sb_irq401; } - void sb_dsp_set_mpu(sb_dsp_t *dsp, mpu_t *mpu) { dsp->mpu = mpu; if (mpu != NULL) - mpu401_irq_attach(mpu, sb_dsp_irq_update, sb_dsp_irq_pending, dsp); + mpu401_irq_attach(mpu, sb_dsp_irq_update, sb_dsp_irq_pending, dsp); } - void sb_dsp_reset(sb_dsp_t *dsp) { @@ -277,74 +275,68 @@ sb_dsp_reset(sb_dsp_t *dsp) dsp->sb_command = 0; - dsp->sb_8_length = 0xffff; + dsp->sb_8_length = 0xffff; dsp->sb_8_autolen = 0xffff; - dsp->sb_irq8 = 0; - dsp->sb_irq16 = 0; - dsp->sb_irq401 = 0; + dsp->sb_irq8 = 0; + dsp->sb_irq16 = 0; + dsp->sb_irq401 = 0; dsp->sb_16_pause = 0; dsp->sb_read_wp = dsp->sb_read_rp = 0; - dsp->sb_data_stat = -1; - dsp->sb_speaker = 0; - dsp->sb_pausetime = -1LL; - dsp->sbe2 = 0xAA; - dsp->sbe2count = 0; + dsp->sb_data_stat = -1; + dsp->sb_speaker = 0; + dsp->sb_pausetime = -1LL; + dsp->sbe2 = 0xAA; + dsp->sbe2count = 0; dsp->sbreset = 0; - dsp->record_pos_read = 0; + dsp->record_pos_read = 0; dsp->record_pos_write = SB_DSP_REC_SAFEFTY_MARGIN; - picintc(1 << dsp->sb_irqnum); + dsp->irq_update(dsp->irq_priv, 0); dsp->asp_data_len = 0; } - void sb_doreset(sb_dsp_t *dsp) { - int c; - sb_dsp_reset(dsp); - if (IS_AZTECH(dsp)) { - sb_commands[8] = 1; - sb_commands[9] = 1; + sb_commands[8] = 1; + sb_commands[9] = 1; } else { - if (dsp->sb_type >= SB16) - sb_commands[8] = 1; - else - sb_commands[8] = -1; + if (dsp->sb_type >= SB16) + sb_commands[8] = 1; + else + sb_commands[8] = -1; } - dsp->sb_asp_mode = 0; + dsp->sb_asp_mode = 0; dsp->sb_asp_ram_index = 0; - for (c = 0; c < 256; c++) - dsp->sb_asp_regs[c] = 0; + for (uint16_t c = 0; c < 256; c++) + dsp->sb_asp_regs[c] = 0; dsp->sb_asp_regs[5] = 0x01; dsp->sb_asp_regs[9] = 0xf8; } - void sb_dsp_speed_changed(sb_dsp_t *dsp) { if (dsp->sb_timeo < 256) - dsp->sblatcho = TIMER_USEC * (256 - dsp->sb_timeo); + dsp->sblatcho = TIMER_USEC * (256 - dsp->sb_timeo); else - dsp->sblatcho = (uint64_t)(TIMER_USEC * (1000000.0f / (float)(dsp->sb_timeo - 256))); + dsp->sblatcho = (uint64_t) (TIMER_USEC * (1000000.0f / (float) (dsp->sb_timeo - 256))); if (dsp->sb_timei < 256) - dsp->sblatchi = TIMER_USEC * (256 - dsp->sb_timei); + dsp->sblatchi = TIMER_USEC * (256 - dsp->sb_timei); else - dsp->sblatchi = (uint64_t)(TIMER_USEC * (1000000.0f / (float)(dsp->sb_timei - 256))); + dsp->sblatchi = (uint64_t) (TIMER_USEC * (1000000.0f / (float) (dsp->sb_timei - 256))); } - void sb_add_data(sb_dsp_t *dsp, uint8_t v) { @@ -352,749 +344,879 @@ sb_add_data(sb_dsp_t *dsp, uint8_t v) dsp->sb_read_wp &= 0xff; } - void sb_start_dma(sb_dsp_t *dsp, int dma8, int autoinit, uint8_t format, int len) { dsp->sb_pausetime = -1; if (dma8) { - dsp->sb_8_length = len; - dsp->sb_8_format = format; - dsp->sb_8_autoinit = autoinit; - dsp->sb_8_pause = 0; - dsp->sb_8_enable = 1; + dsp->sb_8_length = dsp->sb_8_origlength = len; + dsp->sb_8_format = format; + dsp->sb_8_autoinit = autoinit; + dsp->sb_8_pause = 0; + dsp->sb_8_enable = 1; - if (dsp->sb_16_enable && dsp->sb_16_output) - dsp->sb_16_enable = 0; - dsp->sb_8_output = 1; - if (!timer_is_enabled(&dsp->output_timer)) - timer_set_delay_u64(&dsp->output_timer, dsp->sblatcho); - dsp->sbleftright = 0; - dsp->sbdacpos = 0; + if (dsp->sb_16_enable && dsp->sb_16_output) + dsp->sb_16_enable = 0; + dsp->sb_8_output = 1; + if (!timer_is_enabled(&dsp->output_timer)) + timer_set_delay_u64(&dsp->output_timer, dsp->sblatcho); + dsp->sbleftright = dsp->sbleftright_default; + dsp->sbdacpos = 0; } else { - dsp->sb_16_length = len; - dsp->sb_16_format = format; - dsp->sb_16_autoinit = autoinit; - dsp->sb_16_pause = 0; - dsp->sb_16_enable = 1; - if (dsp->sb_8_enable && dsp->sb_8_output) dsp->sb_8_enable = 0; - dsp->sb_16_output = 1; - if (!timer_is_enabled(&dsp->output_timer)) - timer_set_delay_u64(&dsp->output_timer, dsp->sblatcho); + dsp->sb_16_length = dsp->sb_16_origlength = len; + dsp->sb_16_format = format; + dsp->sb_16_autoinit = autoinit; + dsp->sb_16_pause = 0; + dsp->sb_16_enable = 1; + if (dsp->sb_8_enable && dsp->sb_8_output) + dsp->sb_8_enable = 0; + dsp->sb_16_output = 1; + if (!timer_is_enabled(&dsp->output_timer)) + timer_set_delay_u64(&dsp->output_timer, dsp->sblatcho); } } - void sb_start_dma_i(sb_dsp_t *dsp, int dma8, int autoinit, uint8_t format, int len) { if (dma8) { - dsp->sb_8_length = len; - dsp->sb_8_format = format; - dsp->sb_8_autoinit = autoinit; - dsp->sb_8_pause = 0; - dsp->sb_8_enable = 1; - if (dsp->sb_16_enable && !dsp->sb_16_output) - dsp->sb_16_enable = 0; - dsp->sb_8_output = 0; - if (!timer_is_enabled(&dsp->input_timer)) - timer_set_delay_u64(&dsp->input_timer, dsp->sblatchi); + dsp->sb_8_length = dsp->sb_8_origlength = len; + dsp->sb_8_format = format; + dsp->sb_8_autoinit = autoinit; + dsp->sb_8_pause = 0; + dsp->sb_8_enable = 1; + if (dsp->sb_16_enable && !dsp->sb_16_output) + dsp->sb_16_enable = 0; + dsp->sb_8_output = 0; + if (!timer_is_enabled(&dsp->input_timer)) + timer_set_delay_u64(&dsp->input_timer, dsp->sblatchi); } else { - dsp->sb_16_length = len; - dsp->sb_16_format = format; - dsp->sb_16_autoinit = autoinit; - dsp->sb_16_pause = 0; - dsp->sb_16_enable = 1; - if (dsp->sb_8_enable && !dsp->sb_8_output) - dsp->sb_8_enable = 0; - dsp->sb_16_output = 0; - if (!timer_is_enabled(&dsp->input_timer)) - timer_set_delay_u64(&dsp->input_timer, dsp->sblatchi); + dsp->sb_16_length = dsp->sb_16_origlength = len; + dsp->sb_16_format = format; + dsp->sb_16_autoinit = autoinit; + dsp->sb_16_pause = 0; + dsp->sb_16_enable = 1; + if (dsp->sb_8_enable && !dsp->sb_8_output) + dsp->sb_8_enable = 0; + dsp->sb_16_output = 0; + if (!timer_is_enabled(&dsp->input_timer)) + timer_set_delay_u64(&dsp->input_timer, dsp->sblatchi); } - memset(dsp->record_buffer,0,sizeof(dsp->record_buffer)); + memset(dsp->record_buffer, 0, sizeof(dsp->record_buffer)); } - int -sb_8_read_dma(sb_dsp_t *dsp) +sb_8_read_dma(void *priv) { + const sb_dsp_t *dsp = (sb_dsp_t *) priv; + return dma_channel_read(dsp->sb_8_dmanum); } - -void -sb_8_write_dma(sb_dsp_t *dsp, uint8_t val) +int +sb_8_write_dma(void *priv, uint8_t val) { - dma_channel_write(dsp->sb_8_dmanum, val); + const sb_dsp_t *dsp = (sb_dsp_t *) priv; + + return dma_channel_write(dsp->sb_8_dmanum, val) == DMA_NODATA; } +/* + Supported High DMA Translation Channel + ---------------------------------------------------- + 0 0 0 First 8-bit + 0 0 1 First 8-bit + 0 1 0 Second 8-bit + 0 1 1 Second 8-bit + 1 0 0 First 8-bit + 1 0 1 First 8-bit + 1 1 0 16-bit + 1 1 1 Second 8-bit + */ +int +sb_16_read_dma(void *priv) +{ + const sb_dsp_t *dsp = (sb_dsp_t *) priv; + int temp, ret = 0; + int dma_flags, dma_ch = dsp->sb_16_dmanum; + + if (dsp->sb_16_dma_enabled && dsp->sb_16_dma_supported && !dsp->sb_16_dma_translate) + ret = dma_channel_read(dma_ch); + else { + if (dsp->sb_16_dma_enabled) { + /* High DMA channel enabled, either translation is enabled or + 16-bit transfers are not supported. */ + if (dsp->sb_16_dma_translate || !dsp->sb_16_dma_supported) + dma_ch = dsp->sb_16_8_dmanum; + } else + /* High DMA channel disabled, always use the first 8-bit channel. */ + dma_ch = dsp->sb_8_dmanum; + temp = dma_channel_read(dma_ch); + ret = temp; + if ((temp != DMA_NODATA) && !(temp & DMA_OVER)) { + temp = dma_channel_read(dma_ch); + if (temp == DMA_NODATA) + ret = DMA_NODATA; + else { + dma_flags = temp & DMA_OVER; + temp &= ~DMA_OVER; + ret |= (temp << 8) | dma_flags; + } + } + } + + return ret; +} int -sb_16_read_dma(sb_dsp_t *dsp) +sb_16_write_dma(void *priv, uint16_t val) { - return dma_channel_read(dsp->sb_16_dmanum); + const sb_dsp_t *dsp = (sb_dsp_t *) priv; + int temp, ret = 0; + int dma_ch = dsp->sb_16_dmanum; + + if (dsp->sb_16_dma_enabled && dsp->sb_16_dma_supported && !dsp->sb_16_dma_translate) + ret = dma_channel_write(dma_ch, val) == DMA_NODATA; + else { + if (dsp->sb_16_dma_enabled) { + /* High DMA channel enabled, either translation is enabled or + 16-bit transfers are not supported. */ + if (dsp->sb_16_dma_translate || !dsp->sb_16_dma_supported) + dma_ch = dsp->sb_16_8_dmanum; + } else + /* High DMA channel disabled, always use the first 8-bit channel. */ + dma_ch = dsp->sb_8_dmanum; + temp = dma_channel_write(dma_ch, val & 0xff); + ret = temp; + if ((temp != DMA_NODATA) && (temp != DMA_OVER)) { + temp = dma_channel_write(dma_ch, val >> 8); + ret = temp; + } + } + + return ret; } - -int -sb_16_write_dma(sb_dsp_t *dsp, uint16_t val) -{ - int ret = dma_channel_write(dsp->sb_16_dmanum, val); - - return (ret == DMA_NODATA); -} - - void sb_dsp_setirq(sb_dsp_t *dsp, int irq) { + sb_dsp_log("IRQ now: %i\n", irq); dsp->sb_irqnum = irq; } - void sb_dsp_setdma8(sb_dsp_t *dsp, int dma) { + sb_dsp_log("8-bit DMA now: %i\n", dma); dsp->sb_8_dmanum = dma; } - void sb_dsp_setdma16(sb_dsp_t *dsp, int dma) { + sb_dsp_log("16-bit DMA now: %i\n", dma); dsp->sb_16_dmanum = dma; } +void +sb_dsp_setdma16_8(sb_dsp_t *dsp, int dma) +{ + sb_dsp_log("16-bit to 8-bit translation DMA now: %i\n", dma); + dsp->sb_16_8_dmanum = dma; +} + +void +sb_dsp_setdma16_enabled(sb_dsp_t *dsp, int enabled) +{ + sb_dsp_log("16-bit DMA now: %sabled\n", enabled ? "en" : "dis"); + dsp->sb_16_dma_enabled = enabled; +} + +void +sb_dsp_setdma16_supported(sb_dsp_t *dsp, int supported) +{ + sb_dsp_log("16-bit DMA now: %ssupported\n", supported ? "" : "not "); + dsp->sb_16_dma_supported = supported; +} + +void +sb_dsp_setdma16_translate(sb_dsp_t *dsp, int translate) +{ + sb_dsp_log("16-bit to 8-bit translation now: %sabled\n", translate ? "en" : "dis"); + dsp->sb_16_dma_translate = translate; +} + void sb_exec_command(sb_dsp_t *dsp) { - int temp, c; + int temp; + int c; sb_dsp_log("sb_exec_command : SB command %02X\n", dsp->sb_command); - /* Update 8051 ram with the current DSP command. See https://github.com/joncampbell123/dosbox-x/issues/1044 */ if (dsp->sb_type >= SB16) - dsp->sb_8051_ram[0x20] = dsp->sb_command; + dsp->sb_8051_ram[0x20] = dsp->sb_command; switch (dsp->sb_command) { - case 0x01: /* ???? */ - if (dsp->sb_type >= SB16) - dsp->asp_data_len = dsp->sb_data[0] + (dsp->sb_data[1] << 8) + 1; - break; - case 0x03: /* ASP status */ - if (dsp->sb_type >= SB16) - sb_add_data(dsp, 0); - break; - case 0x10: /* 8-bit direct mode */ - sb_dsp_update(dsp); - dsp->sbdat = dsp->sbdatl = dsp->sbdatr = (dsp->sb_data[0] ^ 0x80) << 8; - break; - case 0x14: /* 8-bit single cycle DMA output */ - sb_start_dma(dsp, 1, 0, 0, dsp->sb_data[0] + (dsp->sb_data[1] << 8)); - break; - case 0x17: /* 2-bit ADPCM output with reference */ - dsp->sbref = sb_8_read_dma(dsp); - dsp->sbstep = 0; - /* Fall through */ - case 0x16: /* 2-bit ADPCM output */ - sb_start_dma(dsp, 1, 0, ADPCM_2, dsp->sb_data[0] + (dsp->sb_data[1] << 8)); - dsp->sbdat2 = sb_8_read_dma(dsp); - dsp->sb_8_length--; - if (dsp->sb_command == 0x17) - dsp->sb_8_length--; - break; - case 0x1C: /* 8-bit autoinit DMA output */ - if (dsp->sb_type >= SB15) - sb_start_dma(dsp, 1, 1, 0, dsp->sb_8_autolen); - break; - case 0x1F: /* 2-bit ADPCM autoinit output */ - if (dsp->sb_type >= SB15) { - sb_start_dma(dsp, 1, 1, ADPCM_2, dsp->sb_data[0] + (dsp->sb_data[1] << 8)); - dsp->sbdat2 = sb_8_read_dma(dsp); - dsp->sb_8_length--; - } - break; - case 0x20: /* 8-bit direct input */ - sb_add_data(dsp, (dsp->record_buffer[dsp->record_pos_read]>>8) ^0x80); - /* Due to the current implementation, I need to emulate a samplerate, even if this - mode does not imply such samplerate. Position is increased in sb_poll_i(). */ - if (!timer_is_enabled(&dsp->input_timer)) { - dsp->sb_timei = 256 - 22; - dsp->sblatchi = TIMER_USEC * 22; - temp = 1000000 / 22; - dsp->sb_freq = temp; - timer_set_delay_u64(&dsp->input_timer, dsp->sblatchi); - } - break; - case 0x24: /* 8-bit single cycle DMA input */ - sb_start_dma_i(dsp, 1, 0, 0, dsp->sb_data[0] + (dsp->sb_data[1] << 8)); - break; - case 0x28: /* Direct ADC, 8-bit (Burst) */ - break; - case 0x2C: /* 8-bit autoinit DMA input */ - if (dsp->sb_type >= SB15) - sb_start_dma_i(dsp, 1, 1, 0, dsp->sb_data[0] + (dsp->sb_data[1] << 8)); - break; - case 0x30: /* MIDI Polling mode input */ - sb_dsp_log("MIDI polling mode input\n"); - dsp->midi_in_poll = 1; - dsp->uart_irq = 0; - break; - case 0x31: /* MIDI Interrupt mode input */ - sb_dsp_log("MIDI interrupt mode input\n"); - dsp->midi_in_poll = 0; - dsp->uart_irq = 1; - break; - case 0x32: /* MIDI Read Timestamp Poll */ - break; - case 0x33: /* MIDI Read Timestamp Interrupt */ - break; - case 0x34: /* MIDI In poll */ - if (dsp->sb_type < SB2) - break; - sb_dsp_log("MIDI poll in\n"); - dsp->midi_in_poll = 1; - dsp->uart_midi = 1; - dsp->uart_irq = 0; - break; - case 0x35: /* MIDI In irq */ - if (dsp->sb_type < SB2) - break; - sb_dsp_log("MIDI irq in\n"); - dsp->midi_in_poll = 0; - dsp->uart_midi = 1; - dsp->uart_irq = 1; - break; - case 0x36: case 0x37: /* MIDI timestamps */ - break; - case 0x38: /* Write to SB MIDI Output (Raw) */ - dsp->onebyte_midi = 1; - break; - case 0x40: /* Set time constant */ - dsp->sb_timei = dsp->sb_timeo = dsp->sb_data[0]; - dsp->sblatcho = dsp->sblatchi = TIMER_USEC * (256 - dsp->sb_data[0]); - temp = 256 - dsp->sb_data[0]; - temp = 1000000 / temp; - sb_dsp_log("Sample rate - %ihz (%i)\n",temp, dsp->sblatcho); - if ((dsp->sb_freq != temp) && (dsp->sb_type >= SB16)) - recalc_sb16_filter(0, temp); - dsp->sb_freq = temp; - break; - case 0x41: /* Set output sampling rate */ - case 0x42: /* Set input sampling rate */ - if (dsp->sb_type >= SB16) { - dsp->sblatcho = (uint64_t)(TIMER_USEC * (1000000.0f / (float)(dsp->sb_data[1] + (dsp->sb_data[0] << 8)))); - sb_dsp_log("Sample rate - %ihz (%i)\n",dsp->sb_data[1]+(dsp->sb_data[0]<<8), dsp->sblatcho); - temp = dsp->sb_freq; - dsp->sb_freq = dsp->sb_data[1] + (dsp->sb_data[0] << 8); - dsp->sb_timeo = 256LL + dsp->sb_freq; - dsp->sblatchi = dsp->sblatcho; - dsp->sb_timei = dsp->sb_timeo; - if (dsp->sb_freq != temp && dsp->sb_type >= SB16) - recalc_sb16_filter(0, dsp->sb_freq); - dsp->sb_8051_ram[0x13] = dsp->sb_freq & 0xff; - dsp->sb_8051_ram[0x14] = (dsp->sb_freq >> 8) & 0xff; - } - break; - case 0x45: /* Continue Auto-Initialize DMA, 8-bit */ - break; - case 0x47: /* Continue Auto-Initialize DMA, 16-bit */ - break; - case 0x48: /* Set DSP block transfer size */ - dsp->sb_8_autolen = dsp->sb_data[0] + (dsp->sb_data[1] << 8); - break; - case 0x75: /* 4-bit ADPCM output with reference */ - dsp->sbref = sb_8_read_dma(dsp); - dsp->sbstep = 0; - /* Fall through */ - case 0x74: /* 4-bit ADPCM output */ - sb_start_dma(dsp, 1, 0, ADPCM_4, dsp->sb_data[0] + (dsp->sb_data[1] << 8)); - dsp->sbdat2 = sb_8_read_dma(dsp); - dsp->sb_8_length--; - if (dsp->sb_command == 0x75) - dsp->sb_8_length--; - break; - case 0x77: /* 2.6-bit ADPCM output with reference */ - dsp->sbref = sb_8_read_dma(dsp); - dsp->sbstep = 0; - /* Fall through */ - case 0x76: /* 2.6-bit ADPCM output */ - sb_start_dma(dsp, 1, 0, ADPCM_26, dsp->sb_data[0] + (dsp->sb_data[1] << 8)); - dsp->sbdat2 = sb_8_read_dma(dsp); - dsp->sb_8_length--; - if (dsp->sb_command == 0x77) - dsp->sb_8_length--; - break; - case 0x7D: /* 4-bit ADPCM autoinit output */ - if (dsp->sb_type >= SB15) { - sb_start_dma(dsp, 1, 1, ADPCM_4, dsp->sb_data[0] + (dsp->sb_data[1] << 8)); - dsp->sbdat2 = sb_8_read_dma(dsp); - dsp->sb_8_length--; - } - break; - case 0x7F: /* 2.6-bit ADPCM autoinit output */ - if (dsp->sb_type >= SB15) { - sb_start_dma(dsp, 1, 1, ADPCM_26, dsp->sb_data[0] + (dsp->sb_data[1] << 8)); - dsp->sbdat2 = sb_8_read_dma(dsp); - dsp->sb_8_length--; - } - break; - case 0x80: /* Pause DAC */ - dsp->sb_pausetime = dsp->sb_data[0] + (dsp->sb_data[1] << 8); - if (!timer_is_enabled(&dsp->output_timer)) - timer_set_delay_u64(&dsp->output_timer, dsp->sblatcho); - break; - case 0x90: /* High speed 8-bit autoinit DMA output */ - if (dsp->sb_type >= SB2) - sb_start_dma(dsp, 1, 1, 0, dsp->sb_8_autolen); - break; - case 0x91: /* High speed 8-bit single cycle DMA output */ - if (dsp->sb_type >= SB2) - sb_start_dma(dsp, 1, 0, 0, dsp->sb_8_autolen); - break; - case 0x98: /* High speed 8-bit autoinit DMA input */ - if (dsp->sb_type >= SB2) - sb_start_dma_i(dsp, 1, 1, 0, dsp->sb_8_autolen); - break; - case 0x99: /* High speed 8-bit single cycle DMA input */ - if (dsp->sb_type >= SB2) - sb_start_dma_i(dsp, 1, 0, 0, dsp->sb_8_autolen); - break; - case 0xA0: /* Set input mode to mono */ - case 0xA8: /* Set input mode to stereo */ - if ((dsp->sb_type < SB2) || (dsp->sb_type > SBPRO2)) - break; - /* TODO: Implement. 3.xx-only command. */ - break; - case 0xB0: case 0xB1: case 0xB2: case 0xB3: - case 0xB4: case 0xB5: case 0xB6: case 0xB7: /* 16-bit DMA output */ - if (dsp->sb_type >= SB16) { - sb_start_dma(dsp, 0, dsp->sb_command & 4, dsp->sb_data[0], dsp->sb_data[1] + (dsp->sb_data[2] << 8)); - dsp->sb_16_autolen = dsp->sb_data[1] + (dsp->sb_data[2] << 8); - } - break; - case 0xB8: case 0xB9: case 0xBA: case 0xBB: - case 0xBC: case 0xBD: case 0xBE: case 0xBF: /* 16-bit DMA input */ - if (dsp->sb_type >= SB16) { - sb_start_dma_i(dsp, 0, dsp->sb_command & 4, dsp->sb_data[0], dsp->sb_data[1] + (dsp->sb_data[2] << 8)); - dsp->sb_16_autolen = dsp->sb_data[1] + (dsp->sb_data[2] << 8); - } - break; - case 0xC0: case 0xC1: case 0xC2: case 0xC3: - case 0xC4: case 0xC5: case 0xC6: case 0xC7: /* 8-bit DMA output */ - if (dsp->sb_type >= SB16) { - sb_start_dma(dsp, 1, dsp->sb_command & 4, dsp->sb_data[0], dsp->sb_data[1] + (dsp->sb_data[2] << 8)); - dsp->sb_8_autolen = dsp->sb_data[1] + (dsp->sb_data[2] << 8); - } - break; - case 0xC8: case 0xC9: case 0xCA: case 0xCB: - case 0xCC: case 0xCD: case 0xCE: case 0xCF: /* 8-bit DMA input */ - if (dsp->sb_type >= SB16) { - sb_start_dma_i(dsp, 1, dsp->sb_command & 4, dsp->sb_data[0], dsp->sb_data[1] + (dsp->sb_data[2] << 8)); - dsp->sb_8_autolen = dsp->sb_data[1] + (dsp->sb_data[2] << 8); - } - break; - case 0xD0: /* Pause 8-bit DMA */ - dsp->sb_8_pause = 1; - break; - case 0xD1: /* Speaker on */ - if (dsp->sb_type < SB15) - dsp->sb_8_pause = 1; - else if (dsp->sb_type < SB16) - dsp->muted = 0; - dsp->sb_speaker = 1; - break; - case 0xD3: /* Speaker off */ - if (dsp->sb_type < SB15 ) - dsp->sb_8_pause = 1; - else if (dsp->sb_type < SB16) - dsp->muted = 1; - dsp->sb_speaker = 0; - break; - case 0xD4: /* Continue 8-bit DMA */ - dsp->sb_8_pause = 0; - break; - case 0xD5: /* Pause 16-bit DMA */ - if (dsp->sb_type >= SB16) - dsp->sb_16_pause = 1; - break; - case 0xD6: /* Continue 16-bit DMA */ - if (dsp->sb_type >= SB16) - dsp->sb_16_pause = 0; - break; - case 0xD8: /* Get speaker status */ - sb_add_data(dsp, dsp->sb_speaker ? 0xff : 0); - break; - case 0xD9: /* Exit 16-bit auto-init mode */ - if (dsp->sb_type >= SB16) - dsp->sb_16_autoinit = 0; - break; - case 0xDA: /* Exit 8-bit auto-init mode */ - dsp->sb_8_autoinit = 0; - break; - case 0xE0: /* DSP identification */ - sb_add_data(dsp, ~dsp->sb_data[0]); - break; - case 0xE1: /* Get DSP version */ - if (IS_AZTECH(dsp)) { - if (dsp->sb_subtype == SB_SUBTYPE_CLONE_AZT2316A_0X11) { - sb_add_data(dsp, 0x3); - sb_add_data(dsp, 0x1); - } else if (dsp->sb_subtype == SB_SUBTYPE_CLONE_AZT1605_0X0C) { - sb_add_data(dsp, 0x2); - sb_add_data(dsp, 0x1); - } - break; - } - sb_add_data(dsp, sb_dsp_versions[dsp->sb_type] >> 8); - sb_add_data(dsp, sb_dsp_versions[dsp->sb_type] & 0xff); - break; - case 0xE2: /* Stupid ID/protection */ - for (c = 0; c < 8; c++) { - if (dsp->sb_data[0] & (1 << c)) - dsp->sbe2 += sbe2dat[dsp->sbe2count & 3][c]; - } - dsp->sbe2 += sbe2dat[dsp->sbe2count & 3][8]; - dsp->sbe2count++; - sb_8_write_dma(dsp, dsp->sbe2); - break; - case 0xE3: /* DSP copyright */ - if (dsp->sb_type >= SB16) { - c = 0; - while (sb16_copyright[c]) - sb_add_data(dsp, sb16_copyright[c++]); - sb_add_data(dsp, 0); - } - break; - case 0xE4: /* Write test register */ - dsp->sb_test = dsp->sb_data[0]; - break; - case 0xE8: /* Read test register */ - sb_add_data(dsp, dsp->sb_test); - break; - case 0xF2: /* Trigger 8-bit IRQ */ - sb_dsp_log("Trigger IRQ\n"); - sb_irq(dsp, 1); - break; - case 0xF3: /* Trigger 16-bit IRQ */ - sb_dsp_log("Trigger IRQ\n"); - sb_irq(dsp, 0); - break; - case 0xE7: /* ???? */ - break; - case 0x07: case 0xFF: /* No, that's not how you program auto-init DMA */ - break; - case 0x08: /* ASP get version / AZTECH type/EEPROM access */ - if (IS_AZTECH(dsp)) { - if ((dsp->sb_data[0] == 0x05 || dsp->sb_data[0] == 0x55)&& dsp->sb_subtype == SB_SUBTYPE_CLONE_AZT2316A_0X11) - sb_add_data(dsp, 0x11); /* AZTECH get type, WASHINGTON/latest - according to devkit. E.g.: The one in the Itautec Infoway Multimidia */ - else if ((dsp->sb_data[0] == 0x05 || dsp->sb_data[0] == 0x55) && dsp->sb_subtype == SB_SUBTYPE_CLONE_AZT1605_0X0C) - sb_add_data(dsp, 0x0C); /* AZTECH get type, CLINTON - according to devkit. E.g.: The one in the Packard Bell Legend 100CD */ - else if (dsp->sb_data[0] == 0x08) { - /* EEPROM address to write followed by byte */ - if (dsp->sb_data[1] < 0 || dsp->sb_data[1] >= AZTECH_EEPROM_SIZE) - fatal("AZT EEPROM: out of bounds write to %02X\n", dsp->sb_data[1]); - sb_dsp_log("EEPROM write = %02x\n", dsp->sb_data[2]); - dsp->azt_eeprom[dsp->sb_data[1]] = dsp->sb_data[2]; - break; - } else if (dsp->sb_data[0] == 0x07) { - /* EEPROM address to read */ - if (dsp->sb_data[1] < 0 || dsp->sb_data[1] >= AZTECH_EEPROM_SIZE) - fatal("AZT EEPROM: out of bounds read to %02X\n", dsp->sb_data[1]); - sb_dsp_log("EEPROM read = %02x\n", dsp->azt_eeprom[dsp->sb_data[1]]); - sb_add_data(dsp, dsp->azt_eeprom[dsp->sb_data[1]]); - break; - } else - sb_dsp_log("AZT2316A: UNKNOWN 0x08 COMMAND: %02X\n", dsp->sb_data[0]); /* 0x08 (when shutting down, driver tries to read 1 byte of response), 0x55, 0x0D, 0x08D seen */ - break; - } - if (dsp->sb_type == SBAWE64) /* AWE64 has no ASP or a socket for it */ - sb_add_data(dsp, 0xFF); - else if (dsp->sb_type >= SB16) - sb_add_data(dsp, 0x18); - break; - case 0x0E: /* ASP set register */ - if (dsp->sb_type >= SB16) { - dsp->sb_asp_regs[dsp->sb_data[0]] = dsp->sb_data[1]; + case 0x01: /* ???? */ + if (dsp->sb_type >= SB16) + dsp->asp_data_len = dsp->sb_data[0] + (dsp->sb_data[1] << 8) + 1; + break; + case 0x03: /* ASP status */ + if (dsp->sb_type >= SB16) + sb_add_data(dsp, 0); + break; + case 0x04: /* ASP set mode register */ + if (dsp->sb_type >= SB16) { + dsp->sb_asp_mode = dsp->sb_data[0]; + if (dsp->sb_asp_mode & 4) + dsp->sb_asp_ram_index = 0; + sb_dsp_log("SB16 ASP set mode %02X\n", dsp->sb_asp_mode); + } /* else DSP Status (Obsolete) */ + break; + case 0x05: /* ASP set codec parameter */ + if (dsp->sb_type >= SB16) + sb_dsp_log("SB16 ASP unknown codec params %02X, %02X\n", dsp->sb_data[0], dsp->sb_data[1]); + break; + case 0x07: + break; + case 0x08: /* ASP get version / AZTECH type/EEPROM access */ + if (IS_AZTECH(dsp)) { + if ((dsp->sb_data[0] == 0x05 || dsp->sb_data[0] == 0x55) && dsp->sb_subtype == SB_SUBTYPE_CLONE_AZT2316A_0X11) + sb_add_data(dsp, 0x11); /* AZTECH get type, WASHINGTON/latest - according to devkit. E.g.: The one in the Itautec Infoway Multimidia */ + else if ((dsp->sb_data[0] == 0x05 || dsp->sb_data[0] == 0x55) && dsp->sb_subtype == SB_SUBTYPE_CLONE_AZT1605_0X0C) + sb_add_data(dsp, 0x0C); /* AZTECH get type, CLINTON - according to devkit. E.g.: The one in the Packard Bell Legend 100CD */ + else if (dsp->sb_data[0] == 0x08) { + /* EEPROM address to write followed by byte */ + if (dsp->sb_data[1] < 0 || dsp->sb_data[1] >= AZTECH_EEPROM_SIZE) + fatal("AZT EEPROM: out of bounds write to %02X\n", dsp->sb_data[1]); + sb_dsp_log("EEPROM write = %02x\n", dsp->sb_data[2]); + dsp->azt_eeprom[dsp->sb_data[1]] = dsp->sb_data[2]; + break; + } else if (dsp->sb_data[0] == 0x07) { + /* EEPROM address to read */ + if (dsp->sb_data[1] < 0 || dsp->sb_data[1] >= AZTECH_EEPROM_SIZE) + fatal("AZT EEPROM: out of bounds read to %02X\n", dsp->sb_data[1]); + sb_dsp_log("EEPROM read = %02x\n", dsp->azt_eeprom[dsp->sb_data[1]]); + sb_add_data(dsp, dsp->azt_eeprom[dsp->sb_data[1]]); + break; + } else + sb_dsp_log("AZT2316A: UNKNOWN 0x08 COMMAND: %02X\n", dsp->sb_data[0]); /* 0x08 (when shutting down, driver tries to read 1 byte of response), 0x55, 0x0D, 0x08D seen */ + break; + } + if (dsp->sb_type == SBAWE64) /* AWE64 has no ASP or a socket for it */ + sb_add_data(dsp, 0xFF); + else if (dsp->sb_type >= SB16) + sb_add_data(dsp, 0x18); + break; + case 0x09: /* AZTECH mode set */ + if (IS_AZTECH(dsp)) { + if (dsp->sb_data[0] == 0x00) { + sb_dsp_log("AZT2316A: WSS MODE!\n"); + azt2316a_enable_wss(1, dsp->parent); + } else if (dsp->sb_data[0] == 0x01) { + sb_dsp_log("AZT2316A: SB8PROV2 MODE!\n"); + azt2316a_enable_wss(0, dsp->parent); + } else + sb_dsp_log("AZT2316A: UNKNOWN MODE! = %02x\n", dsp->sb_data[0]); // sequences 0x02->0xFF, 0x04->0xFF seen + } + break; + case 0x0E: /* ASP set register */ + if (dsp->sb_type >= SB16) { + dsp->sb_asp_regs[dsp->sb_data[0]] = dsp->sb_data[1]; - if ((dsp->sb_data[0] == 0x83) && (dsp->sb_asp_mode & 128) && (dsp->sb_asp_mode & 8)) { /* ASP memory write */ - if (dsp->sb_asp_mode & 8) - dsp->sb_asp_ram_index = 0; + if ((dsp->sb_data[0] == 0x83) && (dsp->sb_asp_mode & 128) && (dsp->sb_asp_mode & 8)) { /* ASP memory write */ + if (dsp->sb_asp_mode & 8) + dsp->sb_asp_ram_index = 0; - dsp->sb_asp_ram[dsp->sb_asp_ram_index] = dsp->sb_data[1]; + dsp->sb_asp_ram[dsp->sb_asp_ram_index] = dsp->sb_data[1]; - if (dsp->sb_asp_mode & 2) { - dsp->sb_asp_ram_index++; - if (dsp->sb_asp_ram_index >= 2048) - dsp->sb_asp_ram_index = 0; - } - } - sb_dsp_log("SB16 ASP write reg %02X, val %02X\n", dsp->sb_data[0], dsp->sb_data[1]); - } - break; - case 0x0F: /* ASP get register */ - if (dsp->sb_type >= SB16) { - if ((dsp->sb_data[0] == 0x83) && (dsp->sb_asp_mode & 128) && (dsp->sb_asp_mode & 8)) { /* ASP memory read */ - if (dsp->sb_asp_mode & 8) - dsp->sb_asp_ram_index = 0; + if (dsp->sb_asp_mode & 2) { + dsp->sb_asp_ram_index++; + if (dsp->sb_asp_ram_index >= 2048) + dsp->sb_asp_ram_index = 0; + } + } + sb_dsp_log("SB16 ASP write reg %02X, val %02X\n", dsp->sb_data[0], dsp->sb_data[1]); + } + break; + case 0x0F: /* ASP get register */ + if (dsp->sb_type >= SB16) { + if ((dsp->sb_data[0] == 0x83) && (dsp->sb_asp_mode & 128) && (dsp->sb_asp_mode & 8)) { /* ASP memory read */ + if (dsp->sb_asp_mode & 8) + dsp->sb_asp_ram_index = 0; - dsp->sb_asp_regs[0x83] = dsp->sb_asp_ram[dsp->sb_asp_ram_index]; + dsp->sb_asp_regs[0x83] = dsp->sb_asp_ram[dsp->sb_asp_ram_index]; - if (dsp->sb_asp_mode & 1) { - dsp->sb_asp_ram_index++; - if (dsp->sb_asp_ram_index >= 2048) - dsp->sb_asp_ram_index = 0; - } - } else if (dsp->sb_data[0] == 0x83) { - dsp->sb_asp_regs[0x83] = 0x18; - } - sb_add_data(dsp, dsp->sb_asp_regs[dsp->sb_data[0]]); - sb_dsp_log("SB16 ASP read reg %02X, val %02X\n", dsp->sb_data[0], dsp->sb_asp_regs[dsp->sb_data[0]]); - } - break; - case 0xF8: - if (dsp->sb_type < SB16) - sb_add_data(dsp, 0); - break; - case 0xF9: /* SB16 8051 RAM read */ - if (dsp->sb_type >= SB16) - sb_add_data(dsp, dsp->sb_8051_ram[dsp->sb_data[0]]); - break; - case 0xFA: /* SB16 8051 RAM write */ - if (dsp->sb_type >= SB16) - dsp->sb_8051_ram[dsp->sb_data[0]] = dsp->sb_data[1]; - break; - case 0x04: /* ASP set mode register */ - if (dsp->sb_type >= SB16) { - dsp->sb_asp_mode = dsp->sb_data[0]; - if (dsp->sb_asp_mode & 4) - dsp->sb_asp_ram_index = 0; - sb_dsp_log("SB16 ASP set mode %02X\n", dsp->sb_asp_mode); - } /* else DSP Status (Obsolete) */ - break; - case 0x05: /* ASP set codec parameter */ - if (dsp->sb_type >= SB16) - sb_dsp_log("SB16 ASP unknown codec params %02X, %02X\n", dsp->sb_data[0], dsp->sb_data[1]); - break; + if (dsp->sb_asp_mode & 1) { + dsp->sb_asp_ram_index++; + if (dsp->sb_asp_ram_index >= 2048) + dsp->sb_asp_ram_index = 0; + } + } else if (dsp->sb_data[0] == 0x83) { + dsp->sb_asp_regs[0x83] = 0x18; + } + sb_add_data(dsp, dsp->sb_asp_regs[dsp->sb_data[0]]); + sb_dsp_log("SB16 ASP read reg %02X, val %02X\n", dsp->sb_data[0], dsp->sb_asp_regs[dsp->sb_data[0]]); + } + break; + case 0x10: /* 8-bit direct mode */ + sb_dsp_update(dsp); + dsp->sbdat = dsp->sbdatl = dsp->sbdatr = (dsp->sb_data[0] ^ 0x80) << 8; + break; + case 0x14: /* 8-bit single cycle DMA output */ + sb_start_dma(dsp, 1, 0, 0, dsp->sb_data[0] + (dsp->sb_data[1] << 8)); + break; + case 0x17: /* 2-bit ADPCM output with reference */ + dsp->sbref = dsp->dma_readb(dsp->dma_priv); + dsp->sbstep = 0; + fallthrough; + case 0x16: /* 2-bit ADPCM output */ + sb_start_dma(dsp, 1, 0, ADPCM_2, dsp->sb_data[0] + (dsp->sb_data[1] << 8)); + dsp->sbdat2 = dsp->dma_readb(dsp->dma_priv); + dsp->sb_8_length--; + if (dsp->sb_command == 0x17) + dsp->sb_8_length--; + break; + case 0x1C: /* 8-bit autoinit DMA output */ + if (dsp->sb_type >= SB15) + sb_start_dma(dsp, 1, 1, 0, dsp->sb_8_autolen); + break; + case 0x1F: /* 2-bit ADPCM autoinit output */ + if (dsp->sb_type >= SB15) { + sb_start_dma(dsp, 1, 1, ADPCM_2, dsp->sb_data[0] + (dsp->sb_data[1] << 8)); + dsp->sbdat2 = dsp->dma_readb(dsp->dma_priv); + dsp->sb_8_length--; + } + break; + case 0x20: /* 8-bit direct input */ + sb_add_data(dsp, (dsp->record_buffer[dsp->record_pos_read] >> 8) ^ 0x80); + /* Due to the current implementation, I need to emulate a samplerate, even if this + mode does not imply such samplerate. Position is increased in sb_poll_i(). */ + if (!timer_is_enabled(&dsp->input_timer)) { + dsp->sb_timei = 256 - 22; + dsp->sblatchi = TIMER_USEC * 22; + temp = 1000000 / 22; + dsp->sb_freq = temp; + timer_set_delay_u64(&dsp->input_timer, dsp->sblatchi); + } + break; + case 0x24: /* 8-bit single cycle DMA input */ + sb_start_dma_i(dsp, 1, 0, 0, dsp->sb_data[0] + (dsp->sb_data[1] << 8)); + break; + case 0x28: /* Direct ADC, 8-bit (Burst) */ + break; + case 0x2C: /* 8-bit autoinit DMA input */ + if (dsp->sb_type >= SB15) + sb_start_dma_i(dsp, 1, 1, 0, dsp->sb_data[0] + (dsp->sb_data[1] << 8)); + break; + case 0x30: /* MIDI Polling mode input */ + sb_dsp_log("MIDI polling mode input\n"); + dsp->midi_in_poll = 1; + dsp->uart_irq = 0; + break; + case 0x31: /* MIDI Interrupt mode input */ + sb_dsp_log("MIDI interrupt mode input\n"); + dsp->midi_in_poll = 0; + dsp->uart_irq = 1; + break; + case 0x32: /* MIDI Read Timestamp Poll */ + break; + case 0x33: /* MIDI Read Timestamp Interrupt */ + break; + case 0x34: /* MIDI In poll */ + if (dsp->sb_type < SB2) + break; + sb_dsp_log("MIDI poll in\n"); + dsp->midi_in_poll = 1; + dsp->uart_midi = 1; + dsp->uart_irq = 0; + break; + case 0x35: /* MIDI In irq */ + if (dsp->sb_type < SB2) + break; + sb_dsp_log("MIDI irq in\n"); + dsp->midi_in_poll = 0; + dsp->uart_midi = 1; + dsp->uart_irq = 1; + break; + case 0x36: + case 0x37: /* MIDI timestamps */ + break; + case 0x38: /* Write to SB MIDI Output (Raw) */ + dsp->onebyte_midi = 1; + break; + case 0x40: /* Set time constant */ + dsp->sb_timei = dsp->sb_timeo = dsp->sb_data[0]; + dsp->sblatcho = dsp->sblatchi = TIMER_USEC * (256 - dsp->sb_data[0]); + temp = 256 - dsp->sb_data[0]; + temp = 1000000 / temp; + sb_dsp_log("Sample rate - %ihz (%i)\n", temp, dsp->sblatcho); + if ((dsp->sb_freq != temp) && (dsp->sb_type >= SB16)) + recalc_sb16_filter(0, temp); + dsp->sb_freq = temp; + break; + case 0x41: /* Set output sampling rate */ + case 0x42: /* Set input sampling rate */ + if (dsp->sb_type >= SB16) { + dsp->sblatcho = (uint64_t) (TIMER_USEC * (1000000.0f / (float) (dsp->sb_data[1] + (dsp->sb_data[0] << 8)))); + sb_dsp_log("Sample rate - %ihz (%i)\n", dsp->sb_data[1] + (dsp->sb_data[0] << 8), dsp->sblatcho); + temp = dsp->sb_freq; + dsp->sb_freq = dsp->sb_data[1] + (dsp->sb_data[0] << 8); + dsp->sb_timeo = 256LL + dsp->sb_freq; + dsp->sblatchi = dsp->sblatcho; + dsp->sb_timei = dsp->sb_timeo; + if (dsp->sb_freq != temp && dsp->sb_type >= SB16) + recalc_sb16_filter(0, dsp->sb_freq); + dsp->sb_8051_ram[0x13] = dsp->sb_freq & 0xff; + dsp->sb_8051_ram[0x14] = (dsp->sb_freq >> 8) & 0xff; + } + break; + case 0x45: /* Continue Auto-Initialize DMA, 8-bit */ + break; + case 0x47: /* Continue Auto-Initialize DMA, 16-bit */ + break; + case 0x48: /* Set DSP block transfer size */ + dsp->sb_8_autolen = dsp->sb_data[0] + (dsp->sb_data[1] << 8); + break; + case 0x75: /* 4-bit ADPCM output with reference */ + dsp->sbref = dsp->dma_readb(dsp->dma_priv); + dsp->sbstep = 0; + fallthrough; + case 0x74: /* 4-bit ADPCM output */ + sb_start_dma(dsp, 1, 0, ADPCM_4, dsp->sb_data[0] + (dsp->sb_data[1] << 8)); + dsp->sbdat2 = dsp->dma_readb(dsp->dma_priv); + dsp->sb_8_length--; + if (dsp->sb_command == 0x75) + dsp->sb_8_length--; + break; + case 0x77: /* 2.6-bit ADPCM output with reference */ + dsp->sbref = dsp->dma_readb(dsp->dma_priv); + dsp->sbstep = 0; + fallthrough; + case 0x76: /* 2.6-bit ADPCM output */ + sb_start_dma(dsp, 1, 0, ADPCM_26, dsp->sb_data[0] + (dsp->sb_data[1] << 8)); + dsp->sbdat2 = dsp->dma_readb(dsp->dma_priv); + dsp->sb_8_length--; + if (dsp->sb_command == 0x77) + dsp->sb_8_length--; + break; + case 0x7D: /* 4-bit ADPCM autoinit output */ + if (dsp->sb_type >= SB15) { + sb_start_dma(dsp, 1, 1, ADPCM_4, dsp->sb_data[0] + (dsp->sb_data[1] << 8)); + dsp->sbdat2 = dsp->dma_readb(dsp->dma_priv); + dsp->sb_8_length--; + } + break; + case 0x7F: /* 2.6-bit ADPCM autoinit output */ + if (dsp->sb_type >= SB15) { + sb_start_dma(dsp, 1, 1, ADPCM_26, dsp->sb_data[0] + (dsp->sb_data[1] << 8)); + dsp->sbdat2 = dsp->dma_readb(dsp->dma_priv); + dsp->sb_8_length--; + } + break; + case 0x80: /* Pause DAC */ + dsp->sb_pausetime = dsp->sb_data[0] + (dsp->sb_data[1] << 8); + if (!timer_is_enabled(&dsp->output_timer)) + timer_set_delay_u64(&dsp->output_timer, dsp->sblatcho); + break; + case 0x90: /* High speed 8-bit autoinit DMA output */ + if (dsp->sb_type >= SB2) + sb_start_dma(dsp, 1, 1, 0, dsp->sb_8_autolen); + break; + case 0x91: /* High speed 8-bit single cycle DMA output */ + if (dsp->sb_type >= SB2) + sb_start_dma(dsp, 1, 0, 0, dsp->sb_8_autolen); + break; + case 0x98: /* High speed 8-bit autoinit DMA input */ + if (dsp->sb_type >= SB2) + sb_start_dma_i(dsp, 1, 1, 0, dsp->sb_8_autolen); + break; + case 0x99: /* High speed 8-bit single cycle DMA input */ + if (dsp->sb_type >= SB2) + sb_start_dma_i(dsp, 1, 0, 0, dsp->sb_8_autolen); + break; + case 0xA0: /* Set input mode to mono */ + case 0xA8: /* Set input mode to stereo */ + if ((dsp->sb_type < SB2) || (dsp->sb_type > SBPRO2)) + break; + /* TODO: Implement. 3.xx-only command. */ + break; + case 0xB0: + case 0xB1: + case 0xB2: + case 0xB3: + case 0xB4: + case 0xB5: + case 0xB6: + case 0xB7: /* 16-bit DMA output */ + if (dsp->sb_type >= SB16) { + sb_start_dma(dsp, 0, dsp->sb_command & 4, dsp->sb_data[0], + dsp->sb_data[1] + (dsp->sb_data[2] << 8)); + dsp->sb_16_autolen = dsp->sb_data[1] + (dsp->sb_data[2] << 8); + } + break; + case 0xB8: + case 0xB9: + case 0xBA: + case 0xBB: + case 0xBC: + case 0xBD: + case 0xBE: + case 0xBF: /* 16-bit DMA input */ + if (dsp->sb_type >= SB16) { + sb_start_dma_i(dsp, 0, dsp->sb_command & 4, dsp->sb_data[0], + dsp->sb_data[1] + (dsp->sb_data[2] << 8)); + dsp->sb_16_autolen = dsp->sb_data[1] + (dsp->sb_data[2] << 8); + } + break; + case 0xC0: + case 0xC1: + case 0xC2: + case 0xC3: + case 0xC4: + case 0xC5: + case 0xC6: + case 0xC7: /* 8-bit DMA output */ + if (dsp->sb_type >= SB16) { + sb_start_dma(dsp, 1, dsp->sb_command & 4, dsp->sb_data[0], + dsp->sb_data[1] + (dsp->sb_data[2] << 8)); + dsp->sb_8_autolen = dsp->sb_data[1] + (dsp->sb_data[2] << 8); + } + break; + case 0xC8: + case 0xC9: + case 0xCA: + case 0xCB: + case 0xCC: + case 0xCD: + case 0xCE: + case 0xCF: /* 8-bit DMA input */ + if (dsp->sb_type >= SB16) { + sb_start_dma_i(dsp, 1, dsp->sb_command & 4, dsp->sb_data[0], + dsp->sb_data[1] + (dsp->sb_data[2] << 8)); + dsp->sb_8_autolen = dsp->sb_data[1] + (dsp->sb_data[2] << 8); + } + break; + case 0xD0: /* Pause 8-bit DMA */ + dsp->sb_8_pause = 1; + break; + case 0xD1: /* Speaker on */ + if (dsp->sb_type < SB15) + dsp->sb_8_pause = 1; + else if (dsp->sb_type < SB16) + dsp->muted = 0; + dsp->sb_speaker = 1; + break; + case 0xD3: /* Speaker off */ + if (dsp->sb_type < SB15) + dsp->sb_8_pause = 1; + else if (dsp->sb_type < SB16) + dsp->muted = 1; + dsp->sb_speaker = 0; + break; + case 0xD4: /* Continue 8-bit DMA */ + dsp->sb_8_pause = 0; + break; + case 0xD5: /* Pause 16-bit DMA */ + if (dsp->sb_type >= SB16) + dsp->sb_16_pause = 1; + break; + case 0xD6: /* Continue 16-bit DMA */ + if (dsp->sb_type >= SB16) + dsp->sb_16_pause = 0; + break; + case 0xD8: /* Get speaker status */ + sb_add_data(dsp, dsp->sb_speaker ? 0xff : 0); + break; + case 0xD9: /* Exit 16-bit auto-init mode */ + if (dsp->sb_type >= SB16) + dsp->sb_16_autoinit = 0; + break; + case 0xDA: /* Exit 8-bit auto-init mode */ + dsp->sb_8_autoinit = 0; + break; + case 0xE0: /* DSP identification */ + sb_add_data(dsp, ~dsp->sb_data[0]); + break; + case 0xE1: /* Get DSP version */ + if (IS_AZTECH(dsp)) { + if (dsp->sb_subtype == SB_SUBTYPE_CLONE_AZT2316A_0X11) { + sb_add_data(dsp, 0x3); + sb_add_data(dsp, 0x1); + } else if (dsp->sb_subtype == SB_SUBTYPE_CLONE_AZT1605_0X0C) { + sb_add_data(dsp, 0x2); + sb_add_data(dsp, 0x1); + } + break; + } + sb_add_data(dsp, sb_dsp_versions[dsp->sb_type] >> 8); + sb_add_data(dsp, sb_dsp_versions[dsp->sb_type] & 0xff); + break; + case 0xE2: /* Stupid ID/protection */ + for (c = 0; c < 8; c++) { + if (dsp->sb_data[0] & (1 << c)) + dsp->sbe2 += sbe2dat[dsp->sbe2count & 3][c]; + } + dsp->sbe2 += sbe2dat[dsp->sbe2count & 3][8]; + dsp->sbe2count++; + dsp->dma_writeb(dsp->dma_priv, dsp->sbe2); + break; + case 0xE3: /* DSP copyright */ + if (dsp->sb_type >= SB16) { + c = 0; + while (sb16_copyright[c]) + sb_add_data(dsp, sb16_copyright[c++]); + sb_add_data(dsp, 0); + } + break; + case 0xE4: /* Write test register */ + dsp->sb_test = dsp->sb_data[0]; + break; + case 0xE7: /* ???? */ + break; + case 0xE8: /* Read test register */ + sb_add_data(dsp, dsp->sb_test); + break; + case 0xF2: /* Trigger 8-bit IRQ */ + sb_dsp_log("Trigger IRQ\n"); + sb_irq(dsp, 1); + break; + case 0xF3: /* Trigger 16-bit IRQ */ + sb_dsp_log("Trigger IRQ\n"); + sb_irq(dsp, 0); + break; + case 0xF8: + if (dsp->sb_type < SB16) + sb_add_data(dsp, 0); + break; + case 0xF9: /* SB16 8051 RAM read */ + if (dsp->sb_type >= SB16) + sb_add_data(dsp, dsp->sb_8051_ram[dsp->sb_data[0]]); + break; + case 0xFA: /* SB16 8051 RAM write */ + if (dsp->sb_type >= SB16) + dsp->sb_8051_ram[dsp->sb_data[0]] = dsp->sb_data[1]; + break; + case 0xFF: /* No, that's not how you program auto-init DMA */ + break; - case 0x09: /* AZTECH mode set */ - if (IS_AZTECH(dsp)) { - if (dsp->sb_data[0] == 0x00) { - sb_dsp_log("AZT2316A: WSS MODE!\n"); - azt2316a_enable_wss(1, dsp->parent); - } else if (dsp->sb_data[0] == 0x01) { - sb_dsp_log("AZT2316A: SB8PROV2 MODE!\n"); - azt2316a_enable_wss(0, dsp->parent); - } else - sb_dsp_log("AZT2316A: UNKNOWN MODE! = %02x\n", dsp->sb_data[0]); // sequences 0x02->0xFF, 0x04->0xFF seen - } - break; + /* TODO: Some more data about the DSP registeres + * http://the.earth.li/~tfm/oldpage/sb_dsp.html + * http://www.synchrondata.com/pheaven/www/area19.htm + * http://www.dcee.net/Files/Programm/Sound/ + * 0E3h DSP Copyright SBPro2??? + * 0F0h Sine Generator SB + * 0F1h DSP Auxiliary Status (Obsolete) SB-Pro2 + * 0F2h IRQ Request, 8-bit SB + * 0F3h IRQ Request, 16-bit SB16 + * 0FBh DSP Status SB16 + * 0FCh DSP Auxiliary Status SB16 + * 0FDh DSP Command Status SB16 + */ - /* TODO: Some more data about the DSP registeres - * http://the.earth.li/~tfm/oldpage/sb_dsp.html - * http://www.synchrondata.com/pheaven/www/area19.htm - * http://www.dcee.net/Files/Programm/Sound/ - * 0E3h DSP Copyright SBPro2??? - * 0F0h Sine Generator SB - * 0F1h DSP Auxiliary Status (Obsolete) SB-Pro2 - * 0F2h IRQ Request, 8-bit SB - * 0F3h IRQ Request, 16-bit SB16 - * 0FBh DSP Status SB16 - * 0FCh DSP Auxiliary Status SB16 - * 0FDh DSP Command Status SB16 - */ + default: + sb_dsp_log("Unknown DSP command: %02X\n", dsp->sb_command); + break; } - /* Update 8051 ram with the last DSP command. See https://github.com/joncampbell123/dosbox-x/issues/1044 */ if (dsp->sb_type >= SB16) - dsp->sb_8051_ram[0x30] = dsp->sb_command; + dsp->sb_8051_ram[0x30] = dsp->sb_command; } - void sb_write(uint16_t a, uint8_t v, void *priv) { sb_dsp_t *dsp = (sb_dsp_t *) priv; + /* Sound Blasters prior to Sound Blaster 16 alias the I/O ports. */ + if (dsp->sb_type < SB16) + a &= 0xfffe; + switch (a & 0xF) { - case 6: /* Reset */ - if (!dsp->uart_midi) { - if (!(v & 1) && (dsp->sbreset & 1)) { - sb_dsp_reset(dsp); - sb_add_data(dsp, 0xAA); - } - dsp->sbreset = v; - } - dsp->uart_midi = 0; - dsp->uart_irq = 0; - dsp->onebyte_midi = 0; - return; - case 0xC: /* Command/data write */ - if (dsp->uart_midi || dsp->onebyte_midi ) { - midi_raw_out_byte(v); - dsp->onebyte_midi = 0; - return; - } - timer_set_delay_u64(&dsp->wb_timer, TIMER_USEC * 1); - if (dsp->asp_data_len) { - sb_dsp_log("ASP data %i\n", dsp->asp_data_len); - dsp->asp_data_len--; - if (!dsp->asp_data_len) - sb_add_data(dsp, 0); - return; - } - if (dsp->sb_data_stat == -1) { - dsp->sb_command = v; - if (v == 0x01) - sb_add_data(dsp, 0); - dsp->sb_data_stat++; - } else { - dsp->sb_data[dsp->sb_data_stat++] = v; - if (IS_AZTECH(dsp)) { - /* variable length commands */ - if (dsp->sb_command == 0x08 && dsp->sb_data_stat == 1 && dsp->sb_data[0] == 0x08) - sb_commands[dsp->sb_command] = 3; - else if (dsp->sb_command == 0x08 && dsp->sb_data_stat == 1 && dsp->sb_data[0] == 0x07) - sb_commands[dsp->sb_command] = 2; - } - } - if (dsp->sb_data_stat == sb_commands[dsp->sb_command] || sb_commands[dsp->sb_command] == -1) { - sb_exec_command(dsp); - dsp->sb_data_stat = -1; - if (IS_AZTECH(dsp)) { - /* variable length commands */ - if (dsp->sb_command == 0x08) - sb_commands[dsp->sb_command] = 1; - } - } - break; + case 6: /* Reset */ + if (!dsp->uart_midi) { + if (!(v & 1) && (dsp->sbreset & 1)) { + sb_dsp_reset(dsp); + sb_add_data(dsp, 0xAA); + } + dsp->sbreset = v; + } + dsp->uart_midi = 0; + dsp->uart_irq = 0; + dsp->onebyte_midi = 0; + return; + case 0xC: /* Command/data write */ + if (dsp->uart_midi || dsp->onebyte_midi) { + midi_raw_out_byte(v); + dsp->onebyte_midi = 0; + return; + } + timer_set_delay_u64(&dsp->wb_timer, TIMER_USEC * 1); + if (dsp->asp_data_len) { + sb_dsp_log("ASP data %i\n", dsp->asp_data_len); + dsp->asp_data_len--; + if (!dsp->asp_data_len) + sb_add_data(dsp, 0); + return; + } + if (dsp->sb_data_stat == -1) { + dsp->sb_command = v; + if (v == 0x01) + sb_add_data(dsp, 0); + dsp->sb_data_stat++; + } else { + dsp->sb_data[dsp->sb_data_stat++] = v; + if (IS_AZTECH(dsp)) { + /* variable length commands */ + if (dsp->sb_command == 0x08 && dsp->sb_data_stat == 1 && dsp->sb_data[0] == 0x08) + sb_commands[dsp->sb_command] = 3; + else if (dsp->sb_command == 0x08 && dsp->sb_data_stat == 1 && dsp->sb_data[0] == 0x07) + sb_commands[dsp->sb_command] = 2; + } + } + if (dsp->sb_data_stat == sb_commands[dsp->sb_command] || sb_commands[dsp->sb_command] == -1) { + sb_exec_command(dsp); + dsp->sb_data_stat = -1; + if (IS_AZTECH(dsp)) { + /* variable length commands */ + if (dsp->sb_command == 0x08) + sb_commands[dsp->sb_command] = 1; + } + } + break; + + default: + break; } } - uint8_t sb_read(uint16_t a, void *priv) { sb_dsp_t *dsp = (sb_dsp_t *) priv; - uint8_t ret = 0x00; + uint8_t ret = 0x00; + + /* Sound Blasters prior to Sound Blaster 16 alias the I/O ports. */ + if (dsp->sb_type < SB16) + a &= 0xfffe; switch (a & 0xf) { - case 0xA: /* Read data */ - if (dsp->mpu && dsp->uart_midi) { - ret = MPU401_ReadData(dsp->mpu); - } else { - dsp->sbreaddat = dsp->sb_read_data[dsp->sb_read_rp]; - if (dsp->sb_read_rp != dsp->sb_read_wp) { - dsp->sb_read_rp++; - dsp->sb_read_rp &= 0xff; - } - return dsp->sbreaddat; - } - break; - case 0xC: /* Write data ready */ - if (dsp->sb_8_enable || dsp->sb_type >= SB16) - dsp->busy_count = (dsp->busy_count + 1) & 3; - else - dsp->busy_count = 0; - if (dsp->wb_full || (dsp->busy_count & 2)) { - dsp->wb_full = timer_is_enabled(&dsp->wb_timer); - if (IS_AZTECH(dsp)) { - sb_dsp_log("SB Write Data Aztech read 0x80\n"); - return 0x80; - } else { - sb_dsp_log("SB Write Data Creative read 0xff\n"); - return 0xff; - } - } - if (IS_AZTECH(dsp)) { - sb_dsp_log("SB Write Data Aztech read 0x00\n"); - ret = 0x00; - } else { - sb_dsp_log("SB Write Data Creative read 0x7f\n"); - ret = 0x7f; - } - break; - case 0xE: /* Read data ready */ - picintc(1 << dsp->sb_irqnum); - dsp->sb_irq8 = dsp->sb_irq16 = 0; - /* Only bit 7 is defined but aztech diagnostics fail if the others are set. Keep the original behavior to not interfere with what's already working. */ - if (IS_AZTECH(dsp)) { - sb_dsp_log("SB Read Data Aztech read %02X, Read RP = %d, Read WP = %d\n",(dsp->sb_read_rp == dsp->sb_read_wp) ? 0x00 : 0x80, dsp->sb_read_rp, dsp->sb_read_wp); - ret = (dsp->sb_read_rp == dsp->sb_read_wp) ? 0x00 : 0x80; - } else { - sb_dsp_log("SB Read Data Creative read %02X\n",(dsp->sb_read_rp == dsp->sb_read_wp) ? 0x7f : 0xff); - ret = (dsp->sb_read_rp == dsp->sb_read_wp) ? 0x7f : 0xff; - } - break; - case 0xF: /* 16-bit ack */ - dsp->sb_irq16 = 0; - if (!dsp->sb_irq8) - picintc(1 << dsp->sb_irqnum); - sb_dsp_log("SB 16-bit ACK read 0xFF\n"); - ret = 0xff; - break; - } + case 0xA: /* Read data */ + if (dsp->mpu && dsp->uart_midi) { + ret = MPU401_ReadData(dsp->mpu); + } else { + dsp->sbreaddat = dsp->sb_read_data[dsp->sb_read_rp]; + if (dsp->sb_read_rp != dsp->sb_read_wp) { + dsp->sb_read_rp++; + dsp->sb_read_rp &= 0xff; + } + return dsp->sbreaddat; + } + break; + case 0xC: /* Write data ready */ + if (dsp->sb_8_enable || dsp->sb_type >= SB16) + dsp->busy_count = (dsp->busy_count + 1) & 3; + else + dsp->busy_count = 0; + if (dsp->wb_full || (dsp->busy_count & 2)) { + dsp->wb_full = timer_is_enabled(&dsp->wb_timer); + if (IS_AZTECH(dsp)) { + sb_dsp_log("SB Write Data Aztech read 0x80\n"); + return 0x80; + } else { + sb_dsp_log("SB Write Data Creative read 0xff\n"); + return 0xff; + } + } + if (IS_AZTECH(dsp)) { + sb_dsp_log("SB Write Data Aztech read 0x00\n"); + ret = 0x00; + } else { + sb_dsp_log("SB Write Data Creative read 0x7f\n"); + ret = 0x7f; + } + break; + case 0xE: /* Read data ready */ + dsp->irq_update(dsp->irq_priv, 0); + dsp->sb_irq8 = dsp->sb_irq16 = 0; + /* Only bit 7 is defined but aztech diagnostics fail if the others are set. Keep the original behavior to not interfere with what's already working. */ + if (IS_AZTECH(dsp)) { + sb_dsp_log("SB Read Data Aztech read %02X, Read RP = %d, Read WP = %d\n", (dsp->sb_read_rp == dsp->sb_read_wp) ? 0x00 : 0x80, dsp->sb_read_rp, dsp->sb_read_wp); + ret = (dsp->sb_read_rp == dsp->sb_read_wp) ? 0x00 : 0x80; + } else { + sb_dsp_log("SB Read Data Creative read %02X\n", (dsp->sb_read_rp == dsp->sb_read_wp) ? 0x7f : 0xff); + ret = (dsp->sb_read_rp == dsp->sb_read_wp) ? 0x7f : 0xff; + } + break; + case 0xF: /* 16-bit ack */ + dsp->sb_irq16 = 0; + if (!dsp->sb_irq8) + dsp->irq_update(dsp->irq_priv, 0); + sb_dsp_log("SB 16-bit ACK read 0xFF\n"); + ret = 0xff; + break; - return ret; + default: + break; + } + + return ret; } - -void -sb_dsp_input_msg(void *p, uint8_t *msg, uint32_t len) +void +sb_dsp_input_msg(void *priv, uint8_t *msg, uint32_t len) { - sb_dsp_t *dsp = (sb_dsp_t *) p; - uint8_t i = 0; + sb_dsp_t *dsp = (sb_dsp_t *) priv; sb_dsp_log("MIDI in sysex = %d, uart irq = %d, msg = %d\n", dsp->midi_in_sysex, dsp->uart_irq, len); if (!dsp->uart_irq && !dsp->midi_in_poll && (dsp->mpu != NULL)) { - MPU401_InputMsg(dsp->mpu, msg, len); - return; + MPU401_InputMsg(dsp->mpu, msg, len); + return; } if (dsp->midi_in_sysex) - return; + return; if (dsp->uart_irq) { - for (i = 0; i < len; i++) - sb_add_data(dsp, msg[i]); - sb_irq(dsp, 1); - } else if (dsp->midi_in_poll) { - for (i = 0; i < len; i++) - sb_add_data(dsp, msg[i]); + for (uint32_t i = 0; i < len; i++) + sb_add_data(dsp, msg[i]); + sb_irq(dsp, 1); + } else if (dsp->midi_in_poll) { + for (uint32_t i = 0; i < len; i++) + sb_add_data(dsp, msg[i]); } } - -int -sb_dsp_input_sysex(void *p, uint8_t *buffer, uint32_t len, int abort) +int +sb_dsp_input_sysex(void *priv, uint8_t *buffer, uint32_t len, int abort) { - sb_dsp_t *dsp = (sb_dsp_t *) p; - uint32_t i; + sb_dsp_t *dsp = (sb_dsp_t *) priv; if (!dsp->uart_irq && !dsp->midi_in_poll && (dsp->mpu != NULL)) - return MPU401_InputSysex(dsp->mpu, buffer, len, abort); + return MPU401_InputSysex(dsp->mpu, buffer, len, abort); if (abort) { - dsp->midi_in_sysex = 0; - return 0; + dsp->midi_in_sysex = 0; + return 0; } dsp->midi_in_sysex = 1; - for (i = 0; i < len; i++) { - if (dsp->sb_read_rp == dsp->sb_read_wp) { - sb_dsp_log("Length sysex SB = %d\n", len - i); - return (len - i); - } + for (uint32_t i = 0; i < len; i++) { + if (dsp->sb_read_rp == dsp->sb_read_wp) { + sb_dsp_log("Length sysex SB = %d\n", len - i); + return (len - i); + } - sb_add_data(dsp, buffer[i]); + sb_add_data(dsp, buffer[i]); } dsp->midi_in_sysex = 0; @@ -1102,19 +1224,28 @@ sb_dsp_input_sysex(void *p, uint8_t *buffer, uint32_t len, int abort) return 0; } - void sb_dsp_init(sb_dsp_t *dsp, int type, int subtype, void *parent) { - dsp->sb_type = type; + dsp->sb_type = type; dsp->sb_subtype = subtype; - dsp->parent = parent; + dsp->parent = parent; /* Default values. Use sb_dsp_setxxx() methods to change. */ - dsp->sb_irqnum = 7; - dsp->sb_8_dmanum = 1; + dsp->sb_irqnum = 7; + dsp->sb_8_dmanum = 1; dsp->sb_16_dmanum = 5; - dsp->mpu = NULL; + dsp->mpu = NULL; + + dsp->sbleftright_default = 0; + + dsp->irq_update = sb_irq_update_pic; + dsp->irq_priv = dsp; + dsp->dma_readb = sb_8_read_dma; + dsp->dma_readw = sb_16_read_dma; + dsp->dma_writeb = sb_8_write_dma; + dsp->dma_writew = sb_16_write_dma; + dsp->dma_priv = dsp; sb_doreset(dsp); @@ -1124,8 +1255,9 @@ sb_dsp_init(sb_dsp_t *dsp, int type, int subtype, void *parent) /* Initialise SB16 filter to same cutoff as 8-bit SBs (3.2 kHz). This will be recalculated when a set frequency command is sent. */ - recalc_sb16_filter(0, 3200*2); - recalc_sb16_filter(1, 44100); + recalc_sb16_filter(0, 3200 * 2); + recalc_sb16_filter(1, FREQ_44100); + recalc_sb16_filter(2, 18939); /* Initialize SB16 8051 RAM and ASP internal RAM */ memset(dsp->sb_8051_ram, 0x00, sizeof(dsp->sb_8051_ram)); @@ -1136,405 +1268,436 @@ sb_dsp_init(sb_dsp_t *dsp, int type, int subtype, void *parent) memset(dsp->sb_asp_ram, 0xff, sizeof(dsp->sb_asp_ram)); } - void sb_dsp_setaddr(sb_dsp_t *dsp, uint16_t addr) { sb_dsp_log("sb_dsp_setaddr : %04X\n", addr); if (dsp->sb_addr != 0) { - io_removehandler(dsp->sb_addr + 6, 0x0002, sb_read, NULL, NULL, sb_write, NULL, NULL, dsp); - io_removehandler(dsp->sb_addr + 0xa, 0x0006, sb_read, NULL, NULL, sb_write, NULL, NULL, dsp); + io_removehandler(dsp->sb_addr + 6, 0x0002, sb_read, NULL, NULL, sb_write, NULL, NULL, dsp); + io_removehandler(dsp->sb_addr + 0xa, 0x0006, sb_read, NULL, NULL, sb_write, NULL, NULL, dsp); } dsp->sb_addr = addr; if (dsp->sb_addr != 0) { - io_sethandler(dsp->sb_addr + 6, 0x0002, sb_read, NULL, NULL, sb_write, NULL, NULL, dsp); - io_sethandler(dsp->sb_addr + 0xa, 0x0006, sb_read, NULL, NULL, sb_write, NULL, NULL, dsp); + io_sethandler(dsp->sb_addr + 6, 0x0002, sb_read, NULL, NULL, sb_write, NULL, NULL, dsp); + io_sethandler(dsp->sb_addr + 0xa, 0x0006, sb_read, NULL, NULL, sb_write, NULL, NULL, dsp); } } - void sb_dsp_set_stereo(sb_dsp_t *dsp, int stereo) { dsp->stereo = stereo; } +void +sb_dsp_irq_attach(sb_dsp_t *dsp, void (*irq_update)(void *priv, int set), void *priv) +{ + dsp->irq_update = irq_update; + dsp->irq_priv = priv; +} void -pollsb(void *p) +sb_dsp_dma_attach(sb_dsp_t *dsp, + int (*dma_readb)(void *priv), + int (*dma_readw)(void *priv), + int (*dma_writeb)(void *priv, uint8_t val), + int (*dma_writew)(void *priv, uint16_t val), + void *priv) { - sb_dsp_t *dsp = (sb_dsp_t *) p; - int tempi, ref; - int data[2]; + dsp->dma_readb = dma_readb; + dsp->dma_readw = dma_readw; + dsp->dma_writeb = dma_writeb; + dsp->dma_writew = dma_writew; + dsp->dma_priv = priv; +} + +void +pollsb(void *priv) +{ + sb_dsp_t *dsp = (sb_dsp_t *) priv; + int tempi; + int ref; + int data[2]; timer_advance_u64(&dsp->output_timer, dsp->sblatcho); if (dsp->sb_8_enable && !dsp->sb_8_pause && dsp->sb_pausetime < 0 && dsp->sb_8_output) { - sb_dsp_update(dsp); + sb_dsp_update(dsp); - switch (dsp->sb_8_format) { - case 0x00: /* Mono unsigned */ - data[0] = sb_8_read_dma(dsp); - /* Needed to prevent clicking in Worms, which programs the DSP to - auto-init DMA but programs the DMA controller to single cycle */ - if (data[0] == DMA_NODATA) - break; - dsp->sbdat = (data[0] ^ 0x80) << 8; - if ((dsp->sb_type >= SBPRO) && (dsp->sb_type < SB16) && dsp->stereo) { - sb_dsp_log("pollsb: Mono unsigned, dsp->stereo, %s channel, %04X\n", - dsp->sbleftright ? "left" : "right", dsp->sbdat); - if (dsp->sbleftright) - dsp->sbdatl = dsp->sbdat; - else - dsp->sbdatr = dsp->sbdat; - dsp->sbleftright = !dsp->sbleftright; - } else - dsp->sbdatl = dsp->sbdatr = dsp->sbdat; - dsp->sb_8_length--; - break; - case 0x10: /* Mono signed */ - data[0] = sb_8_read_dma(dsp); - if (data[0] == DMA_NODATA) - break; - dsp->sbdat = data[0] << 8; - if ((dsp->sb_type >= SBPRO) && (dsp->sb_type < SB16) && dsp->stereo) { - sb_dsp_log("pollsb: Mono signed, dsp->stereo, %s channel, %04X\n", - dsp->sbleftright ? "left" : "right", data[0], dsp->sbdat); - if (dsp->sbleftright) - dsp->sbdatl = dsp->sbdat; - else - dsp->sbdatr = dsp->sbdat; - dsp->sbleftright = !dsp->sbleftright; - } else - dsp->sbdatl = dsp->sbdatr = dsp->sbdat; - dsp->sb_8_length--; - break; - case 0x20: /* Stereo unsigned */ - data[0] = sb_8_read_dma(dsp); - data[1] = sb_8_read_dma(dsp); - if ((data[0] == DMA_NODATA) || (data[1] == DMA_NODATA)) - break; - dsp->sbdatl = (data[0] ^ 0x80) << 8; - dsp->sbdatr = (data[1] ^ 0x80) << 8; - dsp->sb_8_length -= 2; - break; - case 0x30: /* Stereo signed */ - data[0] = sb_8_read_dma(dsp); - data[1] = sb_8_read_dma(dsp); - if ((data[0] == DMA_NODATA) || (data[1] == DMA_NODATA)) - break; - dsp->sbdatl = data[0] << 8; - dsp->sbdatr = data[1] << 8; - dsp->sb_8_length -= 2; - break; + switch (dsp->sb_8_format) { + case 0x00: /* Mono unsigned */ + data[0] = dsp->dma_readb(dsp->dma_priv); + /* Needed to prevent clicking in Worms, which programs the DSP to + auto-init DMA but programs the DMA controller to single cycle */ + if (data[0] == DMA_NODATA) + break; + dsp->sbdat = (data[0] ^ 0x80) << 8; + if (dsp->stereo) { + sb_dsp_log("pollsb: Mono unsigned, dsp->stereo, %s channel, %04X\n", + dsp->sbleftright ? "left" : "right", dsp->sbdat); + if (dsp->sbleftright) + dsp->sbdatl = dsp->sbdat; + else + dsp->sbdatr = dsp->sbdat; + dsp->sbleftright = !dsp->sbleftright; + } else + dsp->sbdatl = dsp->sbdatr = dsp->sbdat; + dsp->sb_8_length--; + break; + case 0x10: /* Mono signed */ + data[0] = dsp->dma_readb(dsp->dma_priv); + if (data[0] == DMA_NODATA) + break; + dsp->sbdat = data[0] << 8; + if (dsp->stereo) { + sb_dsp_log("pollsb: Mono signed, dsp->stereo, %s channel, %04X\n", + dsp->sbleftright ? "left" : "right", data[0], dsp->sbdat); + if (dsp->sbleftright) + dsp->sbdatl = dsp->sbdat; + else + dsp->sbdatr = dsp->sbdat; + dsp->sbleftright = !dsp->sbleftright; + } else + dsp->sbdatl = dsp->sbdatr = dsp->sbdat; + dsp->sb_8_length--; + break; + case 0x20: /* Stereo unsigned */ + data[0] = dsp->dma_readb(dsp->dma_priv); + data[1] = dsp->dma_readb(dsp->dma_priv); + if ((data[0] == DMA_NODATA) || (data[1] == DMA_NODATA)) + break; + dsp->sbdatl = (data[0] ^ 0x80) << 8; + dsp->sbdatr = (data[1] ^ 0x80) << 8; + dsp->sb_8_length -= 2; + break; + case 0x30: /* Stereo signed */ + data[0] = dsp->dma_readb(dsp->dma_priv); + data[1] = dsp->dma_readb(dsp->dma_priv); + if ((data[0] == DMA_NODATA) || (data[1] == DMA_NODATA)) + break; + dsp->sbdatl = data[0] << 8; + dsp->sbdatr = data[1] << 8; + dsp->sb_8_length -= 2; + break; - case ADPCM_4: - if (dsp->sbdacpos) - tempi = (dsp->sbdat2 & 0xF) + dsp->sbstep; - else - tempi = (dsp->sbdat2 >> 4) + dsp->sbstep; - if (tempi < 0) - tempi = 0; - if (tempi > 63) - tempi = 63; + case ADPCM_4: + if (dsp->sbdacpos) + tempi = (dsp->sbdat2 & 0xF) + dsp->sbstep; + else + tempi = (dsp->sbdat2 >> 4) + dsp->sbstep; + if (tempi < 0) + tempi = 0; + if (tempi > 63) + tempi = 63; - ref = dsp->sbref + scaleMap4[tempi]; - if (ref > 0xff) - dsp->sbref = 0xff; - else if (ref < 0x00) - dsp->sbref = 0x00; - else - dsp->sbref = ref; + ref = dsp->sbref + scaleMap4[tempi]; + if (ref > 0xff) + dsp->sbref = 0xff; + else if (ref < 0x00) + dsp->sbref = 0x00; + else + dsp->sbref = ref; - dsp->sbstep = (dsp->sbstep + adjustMap4[tempi]) & 0xff; - dsp->sbdat = (dsp->sbref ^ 0x80) << 8; + dsp->sbstep = (dsp->sbstep + adjustMap4[tempi]) & 0xff; + dsp->sbdat = (dsp->sbref ^ 0x80) << 8; - dsp->sbdacpos++; + dsp->sbdacpos++; - if (dsp->sbdacpos >= 2) { - dsp->sbdacpos = 0; - dsp->sbdat2 = sb_8_read_dma(dsp); - dsp->sb_8_length--; - } + if (dsp->sbdacpos >= 2) { + dsp->sbdacpos = 0; + dsp->sbdat2 = dsp->dma_readb(dsp->dma_priv); + dsp->sb_8_length--; + } - if ((dsp->sb_type >= SBPRO) && (dsp->sb_type < SB16) && dsp->stereo) { - sb_dsp_log("pollsb: ADPCM 4, dsp->stereo, %s channel, %04X\n", - dsp->sbleftright ? "left" : "right", dsp->sbdat); - if (dsp->sbleftright) - dsp->sbdatl = dsp->sbdat; - else - dsp->sbdatr = dsp->sbdat; - dsp->sbleftright = !dsp->sbleftright; - } else - dsp->sbdatl = dsp->sbdatr = dsp->sbdat; - break; + if (dsp->stereo) { + sb_dsp_log("pollsb: ADPCM 4, dsp->stereo, %s channel, %04X\n", + dsp->sbleftright ? "left" : "right", dsp->sbdat); + if (dsp->sbleftright) + dsp->sbdatl = dsp->sbdat; + else + dsp->sbdatr = dsp->sbdat; + dsp->sbleftright = !dsp->sbleftright; + } else + dsp->sbdatl = dsp->sbdatr = dsp->sbdat; + break; - case ADPCM_26: - if (!dsp->sbdacpos) - tempi = (dsp->sbdat2 >> 5) + dsp->sbstep; - else if (dsp->sbdacpos == 1) - tempi = ((dsp->sbdat2 >> 2) & 7) + dsp->sbstep; - else - tempi = ((dsp->sbdat2 << 1) & 7) + dsp->sbstep; + case ADPCM_26: + if (!dsp->sbdacpos) + tempi = (dsp->sbdat2 >> 5) + dsp->sbstep; + else if (dsp->sbdacpos == 1) + tempi = ((dsp->sbdat2 >> 2) & 7) + dsp->sbstep; + else + tempi = ((dsp->sbdat2 << 1) & 7) + dsp->sbstep; - if (tempi < 0) - tempi = 0; - if (tempi > 39) - tempi = 39; + if (tempi < 0) + tempi = 0; + if (tempi > 39) + tempi = 39; - ref = dsp->sbref + scaleMap26[tempi]; - if (ref > 0xff) - dsp->sbref = 0xff; - else if (ref < 0x00) - dsp->sbref = 0x00; - else - dsp->sbref = ref; - dsp->sbstep = (dsp->sbstep + adjustMap26[tempi]) & 0xff; + ref = dsp->sbref + scaleMap26[tempi]; + if (ref > 0xff) + dsp->sbref = 0xff; + else if (ref < 0x00) + dsp->sbref = 0x00; + else + dsp->sbref = ref; + dsp->sbstep = (dsp->sbstep + adjustMap26[tempi]) & 0xff; - dsp->sbdat = (dsp->sbref ^ 0x80) << 8; + dsp->sbdat = (dsp->sbref ^ 0x80) << 8; - dsp->sbdacpos++; - if (dsp->sbdacpos >= 3) { - dsp->sbdacpos = 0; - dsp->sbdat2 = sb_8_read_dma(dsp); - dsp->sb_8_length--; - } + dsp->sbdacpos++; + if (dsp->sbdacpos >= 3) { + dsp->sbdacpos = 0; + dsp->sbdat2 = dsp->dma_readb(dsp->dma_priv); + dsp->sb_8_length--; + } - if ((dsp->sb_type >= SBPRO) && (dsp->sb_type < SB16) && dsp->stereo) { - sb_dsp_log("pollsb: ADPCM 26, dsp->stereo, %s channel, %04X\n", - dsp->sbleftright ? "left" : "right", dsp->sbdat); - if (dsp->sbleftright) - dsp->sbdatl = dsp->sbdat; - else - dsp->sbdatr = dsp->sbdat; - dsp->sbleftright = !dsp->sbleftright; - } else - dsp->sbdatl = dsp->sbdatr = dsp->sbdat; - break; + if (dsp->stereo) { + sb_dsp_log("pollsb: ADPCM 26, dsp->stereo, %s channel, %04X\n", + dsp->sbleftright ? "left" : "right", dsp->sbdat); + if (dsp->sbleftright) + dsp->sbdatl = dsp->sbdat; + else + dsp->sbdatr = dsp->sbdat; + dsp->sbleftright = !dsp->sbleftright; + } else + dsp->sbdatl = dsp->sbdatr = dsp->sbdat; + break; - case ADPCM_2: - tempi = ((dsp->sbdat2 >> ((3 - dsp->sbdacpos) * 2)) & 3) + dsp->sbstep; - if (tempi < 0) - tempi = 0; - if (tempi > 23) - tempi = 23; + case ADPCM_2: + tempi = ((dsp->sbdat2 >> ((3 - dsp->sbdacpos) * 2)) & 3) + dsp->sbstep; + if (tempi < 0) + tempi = 0; + if (tempi > 23) + tempi = 23; - ref = dsp->sbref + scaleMap2[tempi]; - if (ref > 0xff) - dsp->sbref = 0xff; - else if (ref < 0x00) - dsp->sbref = 0x00; - else - dsp->sbref = ref; - dsp->sbstep = (dsp->sbstep + adjustMap2[tempi]) & 0xff; + ref = dsp->sbref + scaleMap2[tempi]; + if (ref > 0xff) + dsp->sbref = 0xff; + else if (ref < 0x00) + dsp->sbref = 0x00; + else + dsp->sbref = ref; + dsp->sbstep = (dsp->sbstep + adjustMap2[tempi]) & 0xff; - dsp->sbdat = (dsp->sbref ^ 0x80) << 8; + dsp->sbdat = (dsp->sbref ^ 0x80) << 8; - dsp->sbdacpos++; - if (dsp->sbdacpos >= 4) { - dsp->sbdacpos = 0; - dsp->sbdat2 = sb_8_read_dma(dsp); - } + dsp->sbdacpos++; + if (dsp->sbdacpos >= 4) { + dsp->sbdacpos = 0; + dsp->sbdat2 = dsp->dma_readb(dsp->dma_priv); + } - if ((dsp->sb_type >= SBPRO) && (dsp->sb_type < SB16) && dsp->stereo) { - sb_dsp_log("pollsb: ADPCM 2, dsp->stereo, %s channel, %04X\n", - dsp->sbleftright ? "left" : "right", dsp->sbdat); - if (dsp->sbleftright) - dsp->sbdatl = dsp->sbdat; - else - dsp->sbdatr = dsp->sbdat; - dsp->sbleftright = !dsp->sbleftright; - } else - dsp->sbdatl = dsp->sbdatr = dsp->sbdat; - break; - } + if (dsp->stereo) { + sb_dsp_log("pollsb: ADPCM 2, dsp->stereo, %s channel, %04X\n", + dsp->sbleftright ? "left" : "right", dsp->sbdat); + if (dsp->sbleftright) + dsp->sbdatl = dsp->sbdat; + else + dsp->sbdatr = dsp->sbdat; + dsp->sbleftright = !dsp->sbleftright; + } else + dsp->sbdatl = dsp->sbdatr = dsp->sbdat; + break; - if (dsp->sb_8_length < 0) { - if (dsp->sb_8_autoinit) - dsp->sb_8_length = dsp->sb_8_autolen; - else { - dsp->sb_8_enable = 0; - timer_disable(&dsp->output_timer); - } - sb_irq(dsp, 1); - } + default: + break; + } + + if (dsp->sb_8_length < 0) { + if (dsp->sb_8_autoinit) + dsp->sb_8_length = dsp->sb_8_origlength = dsp->sb_8_autolen; + else { + dsp->sb_8_enable = 0; + timer_disable(&dsp->output_timer); + } + sb_irq(dsp, 1); + } } if (dsp->sb_16_enable && !dsp->sb_16_pause && (dsp->sb_pausetime < 0LL) && dsp->sb_16_output) { - sb_dsp_update(dsp); + sb_dsp_update(dsp); - switch (dsp->sb_16_format) { - case 0x00: /* Mono unsigned */ - data[0] = sb_16_read_dma(dsp); - if (data[0] == DMA_NODATA) - break; - dsp->sbdatl = dsp->sbdatr = data[0] ^ 0x8000; - dsp->sb_16_length--; - break; - case 0x10: /* Mono signed */ - data[0] = sb_16_read_dma(dsp); - if (data[0] == DMA_NODATA) - break; - dsp->sbdatl = dsp->sbdatr = data[0]; - dsp->sb_16_length--; - break; - case 0x20: /* Stereo unsigned */ - data[0] = sb_16_read_dma(dsp); - data[1] = sb_16_read_dma(dsp); - if ((data[0] == DMA_NODATA) || (data[1] == DMA_NODATA)) - break; - dsp->sbdatl = data[0] ^ 0x8000; - dsp->sbdatr = data[1] ^ 0x8000; - dsp->sb_16_length -= 2; - break; - case 0x30: /* Stereo signed */ - data[0] = sb_16_read_dma(dsp); - data[1] = sb_16_read_dma(dsp); - if ((data[0] == DMA_NODATA) || (data[1] == DMA_NODATA)) - break; - dsp->sbdatl = data[0]; - dsp->sbdatr = data[1]; - dsp->sb_16_length -= 2; - break; - } + switch (dsp->sb_16_format) { + case 0x00: /* Mono unsigned */ + data[0] = dsp->dma_readw(dsp->dma_priv); + if (data[0] == DMA_NODATA) + break; + dsp->sbdatl = dsp->sbdatr = data[0] ^ 0x8000; + dsp->sb_16_length--; + break; + case 0x10: /* Mono signed */ + data[0] = dsp->dma_readw(dsp->dma_priv); + if (data[0] == DMA_NODATA) + break; + dsp->sbdatl = dsp->sbdatr = data[0]; + dsp->sb_16_length--; + break; + case 0x20: /* Stereo unsigned */ + data[0] = dsp->dma_readw(dsp->dma_priv); + data[1] = dsp->dma_readw(dsp->dma_priv); + if ((data[0] == DMA_NODATA) || (data[1] == DMA_NODATA)) + break; + dsp->sbdatl = data[0] ^ 0x8000; + dsp->sbdatr = data[1] ^ 0x8000; + dsp->sb_16_length -= 2; + break; + case 0x30: /* Stereo signed */ + data[0] = dsp->dma_readw(dsp->dma_priv); + data[1] = dsp->dma_readw(dsp->dma_priv); + if ((data[0] == DMA_NODATA) || (data[1] == DMA_NODATA)) + break; + dsp->sbdatl = data[0]; + dsp->sbdatr = data[1]; + dsp->sb_16_length -= 2; + break; - if (dsp->sb_16_length < 0) { - sb_dsp_log("16DMA over %i\n", dsp->sb_16_autoinit); - if (dsp->sb_16_autoinit) - dsp->sb_16_length = dsp->sb_16_autolen; - else { - dsp->sb_16_enable = 0; - timer_disable(&dsp->output_timer); - } - sb_irq(dsp, 0); - } + default: + break; + } + + if (dsp->sb_16_length < 0) { + sb_dsp_log("16DMA over %i\n", dsp->sb_16_autoinit); + if (dsp->sb_16_autoinit) + dsp->sb_16_length = dsp->sb_16_origlength = dsp->sb_16_autolen; + else { + dsp->sb_16_enable = 0; + timer_disable(&dsp->output_timer); + } + sb_irq(dsp, 0); + } } if (dsp->sb_pausetime > -1) { - dsp->sb_pausetime--; - if (dsp->sb_pausetime < 0) { - sb_irq(dsp, 1); - if (!dsp->sb_8_enable) - timer_disable(&dsp->output_timer); - sb_dsp_log("SB pause over\n"); - } + dsp->sb_pausetime--; + if (dsp->sb_pausetime < 0) { + sb_irq(dsp, 1); + if (!dsp->sb_8_enable) + timer_disable(&dsp->output_timer); + sb_dsp_log("SB pause over\n"); + } } } - void -sb_poll_i(void *p) +sb_poll_i(void *priv) { - sb_dsp_t *dsp = (sb_dsp_t *) p; - int processed = 0; + sb_dsp_t *dsp = (sb_dsp_t *) priv; + int processed = 0; timer_advance_u64(&dsp->input_timer, dsp->sblatchi); if (dsp->sb_8_enable && !dsp->sb_8_pause && dsp->sb_pausetime < 0 && !dsp->sb_8_output) { - switch (dsp->sb_8_format) { - case 0x00: /* Mono unsigned As the manual says, only the left channel is recorded */ - sb_8_write_dma(dsp, (dsp->record_buffer[dsp->record_pos_read]>>8) ^0x80); - dsp->sb_8_length--; - dsp->record_pos_read += 2; - dsp->record_pos_read &= 0xFFFF; - break; - case 0x10: /* Mono signed As the manual says, only the left channel is recorded */ - sb_8_write_dma(dsp, (dsp->record_buffer[dsp->record_pos_read]>>8)); - dsp->sb_8_length--; - dsp->record_pos_read += 2; - dsp->record_pos_read &= 0xFFFF; - break; - case 0x20: /* Stereo unsigned */ - sb_8_write_dma(dsp, (dsp->record_buffer[dsp->record_pos_read]>>8)^0x80); - sb_8_write_dma(dsp, (dsp->record_buffer[dsp->record_pos_read+1]>>8)^0x80); - dsp->sb_8_length -= 2; - dsp->record_pos_read += 2; - dsp->record_pos_read &= 0xFFFF; - break; - case 0x30: /* Stereo signed */ - sb_8_write_dma(dsp, (dsp->record_buffer[dsp->record_pos_read]>>8)); - sb_8_write_dma(dsp, (dsp->record_buffer[dsp->record_pos_read+1]>>8)); - dsp->sb_8_length -= 2; - dsp->record_pos_read += 2; - dsp->record_pos_read &= 0xFFFF; - break; - } + switch (dsp->sb_8_format) { + case 0x00: /* Mono unsigned As the manual says, only the left channel is recorded */ + dsp->dma_writeb(dsp->dma_priv, (dsp->record_buffer[dsp->record_pos_read] >> 8) ^ 0x80); + dsp->sb_8_length--; + dsp->record_pos_read += 2; + dsp->record_pos_read &= 0xFFFF; + break; + case 0x10: /* Mono signed As the manual says, only the left channel is recorded */ + dsp->dma_writeb(dsp->dma_priv, (dsp->record_buffer[dsp->record_pos_read] >> 8)); + dsp->sb_8_length--; + dsp->record_pos_read += 2; + dsp->record_pos_read &= 0xFFFF; + break; + case 0x20: /* Stereo unsigned */ + dsp->dma_writeb(dsp->dma_priv, (dsp->record_buffer[dsp->record_pos_read] >> 8) ^ 0x80); + dsp->dma_writeb(dsp->dma_priv, (dsp->record_buffer[dsp->record_pos_read + 1] >> 8) ^ 0x80); + dsp->sb_8_length -= 2; + dsp->record_pos_read += 2; + dsp->record_pos_read &= 0xFFFF; + break; + case 0x30: /* Stereo signed */ + dsp->dma_writeb(dsp->dma_priv, (dsp->record_buffer[dsp->record_pos_read] >> 8)); + dsp->dma_writeb(dsp->dma_priv, (dsp->record_buffer[dsp->record_pos_read + 1] >> 8)); + dsp->sb_8_length -= 2; + dsp->record_pos_read += 2; + dsp->record_pos_read &= 0xFFFF; + break; - if (dsp->sb_8_length < 0) { - if (dsp->sb_8_autoinit) - dsp->sb_8_length = dsp->sb_8_autolen; - else { - dsp->sb_8_enable = 0; - timer_disable(&dsp->input_timer); - } - sb_irq(dsp, 1); - } - processed = 1; + default: + break; + } + + if (dsp->sb_8_length < 0) { + if (dsp->sb_8_autoinit) + dsp->sb_8_length = dsp->sb_8_origlength = dsp->sb_8_autolen; + else { + dsp->sb_8_enable = 0; + timer_disable(&dsp->input_timer); + } + sb_irq(dsp, 1); + } + processed = 1; } if (dsp->sb_16_enable && !dsp->sb_16_pause && (dsp->sb_pausetime < 0LL) && !dsp->sb_16_output) { - switch (dsp->sb_16_format) { - case 0x00: /* Unsigned mono. As the manual says, only the left channel is recorded */ - if (sb_16_write_dma(dsp, dsp->record_buffer[dsp->record_pos_read]^0x8000)) - return; - dsp->sb_16_length--; - dsp->record_pos_read += 2; - dsp->record_pos_read &= 0xFFFF; - break; - case 0x10: /* Signed mono. As the manual says, only the left channel is recorded */ - if (sb_16_write_dma(dsp, dsp->record_buffer[dsp->record_pos_read])) - return; - dsp->sb_16_length--; - dsp->record_pos_read += 2; - dsp->record_pos_read &= 0xFFFF; - break; - case 0x20: /* Unsigned stereo */ - if (sb_16_write_dma(dsp, dsp->record_buffer[dsp->record_pos_read]^0x8000)) - return; - sb_16_write_dma(dsp, dsp->record_buffer[dsp->record_pos_read+1]^0x8000); - dsp->sb_16_length -= 2; - dsp->record_pos_read += 2; - dsp->record_pos_read &= 0xFFFF; - break; - case 0x30: /* Signed stereo */ - if (sb_16_write_dma(dsp, dsp->record_buffer[dsp->record_pos_read])) - return; - sb_16_write_dma(dsp, dsp->record_buffer[dsp->record_pos_read+1]); - dsp->sb_16_length -= 2; - dsp->record_pos_read += 2; - dsp->record_pos_read &= 0xFFFF; - break; - } + switch (dsp->sb_16_format) { + case 0x00: /* Unsigned mono. As the manual says, only the left channel is recorded */ + if (dsp->dma_writew(dsp->dma_priv, dsp->record_buffer[dsp->record_pos_read] ^ 0x8000)) + return; + dsp->sb_16_length--; + dsp->record_pos_read += 2; + dsp->record_pos_read &= 0xFFFF; + break; + case 0x10: /* Signed mono. As the manual says, only the left channel is recorded */ + if (dsp->dma_writew(dsp->dma_priv, dsp->record_buffer[dsp->record_pos_read])) + return; + dsp->sb_16_length--; + dsp->record_pos_read += 2; + dsp->record_pos_read &= 0xFFFF; + break; + case 0x20: /* Unsigned stereo */ + if (dsp->dma_writew(dsp->dma_priv, dsp->record_buffer[dsp->record_pos_read] ^ 0x8000)) + return; + dsp->dma_writew(dsp->dma_priv, dsp->record_buffer[dsp->record_pos_read + 1] ^ 0x8000); + dsp->sb_16_length -= 2; + dsp->record_pos_read += 2; + dsp->record_pos_read &= 0xFFFF; + break; + case 0x30: /* Signed stereo */ + if (dsp->dma_writew(dsp->dma_priv, dsp->record_buffer[dsp->record_pos_read])) + return; + dsp->dma_writew(dsp->dma_priv, dsp->record_buffer[dsp->record_pos_read + 1]); + dsp->sb_16_length -= 2; + dsp->record_pos_read += 2; + dsp->record_pos_read &= 0xFFFF; + break; - if (dsp->sb_16_length < 0) { - if (dsp->sb_16_autoinit) - dsp->sb_16_length = dsp->sb_16_autolen; - else { - dsp->sb_16_enable = 0; - timer_disable(&dsp->input_timer); - } - sb_irq(dsp, 0); - } - processed = 1; + default: + break; + } + + if (dsp->sb_16_length < 0) { + if (dsp->sb_16_autoinit) + dsp->sb_16_length = dsp->sb_16_origlength = dsp->sb_16_autolen; + else { + dsp->sb_16_enable = 0; + timer_disable(&dsp->input_timer); + } + sb_irq(dsp, 0); + } + processed = 1; } /* Assume this is direct mode */ if (!processed) { - dsp->record_pos_read += 2; - dsp->record_pos_read &= 0xFFFF; + dsp->record_pos_read += 2; + dsp->record_pos_read &= 0xFFFF; } } - -void sb_dsp_update(sb_dsp_t *dsp) -{ - if (dsp->muted) { - dsp->sbdatl = 0; - dsp->sbdatr = 0; - } - for (; dsp->pos < sound_pos_global; dsp->pos++) { - dsp->buffer[dsp->pos*2] = dsp->sbdatl; - dsp->buffer[dsp->pos*2 + 1] = dsp->sbdatr; - } -} - - void -sb_dsp_close(sb_dsp_t *dsp) +sb_dsp_update(sb_dsp_t *dsp) { + if (dsp->muted) { + dsp->sbdatl = 0; + dsp->sbdatr = 0; + } + for (; dsp->pos < sound_pos_global; dsp->pos++) { + dsp->buffer[dsp->pos * 2] = dsp->sbdatl; + dsp->buffer[dsp->pos * 2 + 1] = dsp->sbdatr; + } +} + +void +sb_dsp_close(UNUSED(sb_dsp_t *dsp)) +{ + // } diff --git a/src/sound/snd_sn76489.c b/src/sound/snd_sn76489.c index e4ba68742..519219934 100644 --- a/src/sound/snd_sn76489.c +++ b/src/sound/snd_sn76489.c @@ -1,311 +1,328 @@ -#include #include -#include +#include #include -#include +#include #include +#include + #include <86box/86box.h> -#include <86box/io.h> #include <86box/device.h> +#include <86box/io.h> #include <86box/sound.h> #include <86box/snd_sn76489.h> - +#include <86box/plat_unused.h> int sn76489_mute; - -static float volslog[16]= -{ - 0.00000f,0.59715f,0.75180f,0.94650f, - 1.19145f,1.50000f,1.88835f,2.37735f, - 2.99295f,3.76785f,4.74345f,5.97165f, - 7.51785f,9.46440f,11.9194f,15.0000f +static float volslog[16] = { + 0.00000f, 0.59715f, 0.75180f, 0.94650f, + 1.19145f, 1.50000f, 1.88835f, 2.37735f, + 2.99295f, 3.76785f, 4.74345f, 5.97165f, + 7.51785f, 9.46440f, 11.9194f, 15.0000f }; -void sn76489_update(sn76489_t *sn76489) +void +sn76489_update(sn76489_t *sn76489) { - for (; sn76489->pos < sound_pos_global; sn76489->pos++) - { - int c; - int16_t result = 0; - - for (c = 1; c < 4; c++) - { - if (sn76489->latch[c] > 256) result += (int16_t) (volslog[sn76489->vol[c]] * sn76489->stat[c]); - else result += (int16_t) (volslog[sn76489->vol[c]] * 127); + for (; sn76489->pos < sound_pos_global; sn76489->pos++) { + int16_t result = 0; - sn76489->count[c] -= (256 * sn76489->psgconst); - while ((int)sn76489->count[c] < 0) - { - sn76489->count[c] += sn76489->latch[c]; - sn76489->stat[c] = -sn76489->stat[c]; - } - } - result += (((sn76489->shift & 1) ^ 1) * 127 * volslog[sn76489->vol[0]] * 2); + for (uint8_t c = 1; c < 4; c++) { + if (sn76489->latch[c] > 256) + result += (int16_t) (volslog[sn76489->vol[c]] * sn76489->stat[c]); + else + result += (int16_t) (volslog[sn76489->vol[c]] * 127); - sn76489->count[0] -= (512 * sn76489->psgconst); - while ((int)sn76489->count[0] < 0 && sn76489->latch[0]) - { - sn76489->count[0] += (sn76489->latch[0] * 4); - if (!(sn76489->noise & 4)) - { - if (sn76489->shift & 1) - sn76489->shift |= 0x8000; - sn76489->shift >>= 1; - } - else - { - if ((sn76489->shift & 1) ^ ((sn76489->shift >> 1) & 1)) - sn76489->shift |= 0x8000; - sn76489->shift >>= 1; - } - } - - sn76489->buffer[sn76489->pos] = result; + sn76489->count[c] -= (256 * sn76489->psgconst); + while (sn76489->count[c] < 0) { + sn76489->count[c] += sn76489->latch[c]; + sn76489->stat[c] = -sn76489->stat[c]; + } } -} + result += (((sn76489->shift & 1) ^ 1) * 127 * volslog[sn76489->vol[0]] * 2); -void sn76489_get_buffer(int32_t *buffer, int len, void *p) -{ - sn76489_t *sn76489 = (sn76489_t *)p; - - int c; - - sn76489_update(sn76489); - - if (!sn76489_mute) - { - for (c = 0; c < len * 2; c++) - buffer[c] += sn76489->buffer[c >> 1]; + sn76489->count[0] -= (512 * sn76489->psgconst); + while (sn76489->count[0] < 0 && sn76489->latch[0]) { + sn76489->count[0] += (sn76489->latch[0] * 4); + if (!(sn76489->noise & 4)) { + if (sn76489->shift & 1) + sn76489->shift |= 0x8000; + sn76489->shift >>= 1; + } else { + if ((sn76489->shift & 1) ^ ((sn76489->shift >> 1) & 1)) + sn76489->shift |= 0x8000; + sn76489->shift >>= 1; + } } - sn76489->pos = 0; + sn76489->buffer[sn76489->pos] = result; + } } -void sn76489_write(uint16_t addr, uint8_t data, void *p) +void +sn76489_get_buffer(int32_t *buffer, int len, void *priv) { - sn76489_t *sn76489 = (sn76489_t *)p; - int freq; + sn76489_t *sn76489 = (sn76489_t *) priv; - sn76489_update(sn76489); - - if (data & 0x80) - { - sn76489->firstdat = data; - switch (data & 0x70) - { - case 0: - sn76489->freqlo[3] = data & 0xf; - sn76489->latch[3] = (sn76489->freqlo[3] | (sn76489->freqhi[3] << 4)) << 6; - if (sn76489->extra_divide) - sn76489->latch[3] &= 0x3ff; - if (!sn76489->latch[3]) - sn76489->latch[3] = (sn76489->extra_divide ? 2048 : 1024) << 6; - sn76489->lasttone = 3; - break; - case 0x10: - data &= 0xf; - sn76489->vol[3] = 0xf - data; - break; - case 0x20: - sn76489->freqlo[2] = data & 0xf; - sn76489->latch[2] = (sn76489->freqlo[2] | (sn76489->freqhi[2] << 4)) << 6; - if (sn76489->extra_divide) - sn76489->latch[2] &= 0x3ff; - if (!sn76489->latch[2]) - sn76489->latch[2] = (sn76489->extra_divide ? 2048 : 1024) << 6; - sn76489->lasttone = 2; - break; - case 0x30: - data &= 0xf; - sn76489->vol[2] = 0xf - data; - break; - case 0x40: - sn76489->freqlo[1] = data & 0xf; - sn76489->latch[1] = (sn76489->freqlo[1] | (sn76489->freqhi[1] << 4)) << 6; - if (sn76489->extra_divide) - sn76489->latch[1] &= 0x3ff; - if (!sn76489->latch[1]) - sn76489->latch[1] = (sn76489->extra_divide ? 2048 : 1024) << 6; - sn76489->lasttone = 1; - break; - case 0x50: - data &= 0xf; - sn76489->vol[1] = 0xf - data; - break; - case 0x60: - if ((data & 4) != (sn76489->noise & 4) || sn76489->type == SN76496) - sn76489->shift = 0x4000; - sn76489->noise = data & 0xf; - if ((data & 3) == 3) sn76489->latch[0] = sn76489->latch[1]; - else sn76489->latch[0] = 0x400 << (data & 3); - if (sn76489->extra_divide) - sn76489->latch[0] &= 0x3ff; - if (!sn76489->latch[0]) - sn76489->latch[0] = (sn76489->extra_divide ? 2048 : 1024) << 6; - break; - case 0x70: - data &= 0xf; - sn76489->vol[0] = 0xf - data; - break; - } + sn76489_update(sn76489); + + if (!sn76489_mute) { + for (int c = 0; c < len * 2; c++) + buffer[c] += sn76489->buffer[c >> 1]; + } + + sn76489->pos = 0; +} + +void +sn76489_write(UNUSED(uint16_t addr), uint8_t data, void *priv) +{ + sn76489_t *sn76489 = (sn76489_t *) priv; + int freq; + + sn76489_update(sn76489); + + if (data & 0x80) { + sn76489->firstdat = data; + switch (data & 0x70) { + case 0: + sn76489->freqlo[3] = data & 0xf; + sn76489->latch[3] = (sn76489->freqlo[3] | (sn76489->freqhi[3] << 4)) << 6; + if (sn76489->extra_divide) + sn76489->latch[3] &= 0x3ff; + if (!sn76489->latch[3]) + sn76489->latch[3] = (sn76489->extra_divide ? 2048 : 1024) << 6; + sn76489->lasttone = 3; + break; + case 0x10: + data &= 0xf; + sn76489->vol[3] = 0xf - data; + break; + case 0x20: + sn76489->freqlo[2] = data & 0xf; + sn76489->latch[2] = (sn76489->freqlo[2] | (sn76489->freqhi[2] << 4)) << 6; + if (sn76489->extra_divide) + sn76489->latch[2] &= 0x3ff; + if (!sn76489->latch[2]) + sn76489->latch[2] = (sn76489->extra_divide ? 2048 : 1024) << 6; + sn76489->lasttone = 2; + break; + case 0x30: + data &= 0xf; + sn76489->vol[2] = 0xf - data; + break; + case 0x40: + sn76489->freqlo[1] = data & 0xf; + sn76489->latch[1] = (sn76489->freqlo[1] | (sn76489->freqhi[1] << 4)) << 6; + if (sn76489->extra_divide) + sn76489->latch[1] &= 0x3ff; + if (!sn76489->latch[1]) + sn76489->latch[1] = (sn76489->extra_divide ? 2048 : 1024) << 6; + sn76489->lasttone = 1; + break; + case 0x50: + data &= 0xf; + sn76489->vol[1] = 0xf - data; + break; + case 0x60: + if ((data & 4) != (sn76489->noise & 4) || sn76489->type == SN76496) + sn76489->shift = 0x4000; + sn76489->noise = data & 0xf; + if ((data & 3) == 3) + sn76489->latch[0] = sn76489->latch[1]; + else + sn76489->latch[0] = 0x400 << (data & 3); + if (sn76489->extra_divide) + sn76489->latch[0] &= 0x3ff; + if (!sn76489->latch[0]) + sn76489->latch[0] = (sn76489->extra_divide ? 2048 : 1024) << 6; + break; + case 0x70: + data &= 0xf; + sn76489->vol[0] = 0xf - data; + break; + + default: + break; } - else - { - if ((sn76489->firstdat & 0x70) == 0x60 && (sn76489->type == SN76496)) - { - if ((data & 4) != (sn76489->noise & 4) || sn76489->type == SN76496) - sn76489->shift = 0x4000; - sn76489->noise = data & 0xf; - if ((data & 3) == 3) sn76489->latch[0] = sn76489->latch[1]; - else sn76489->latch[0] = 0x400 << (data & 3); - if (!sn76489->latch[0]) - sn76489->latch[0] = 1024 << 6; - } - else if ((sn76489->firstdat & 0x70) != 0x60) - { - sn76489->freqhi[sn76489->lasttone] = data & 0x7F; - freq = sn76489->freqlo[sn76489->lasttone] | (sn76489->freqhi[sn76489->lasttone] << 4); - if (sn76489->extra_divide) - freq &= 0x3ff; - if (!freq) - freq = sn76489->extra_divide ? 2048 : 1024; - if ((sn76489->noise & 3) == 3 && sn76489->lasttone == 1) - sn76489->latch[0] = freq << 6; - sn76489->latch[sn76489->lasttone] = freq << 6; - } + } else { + if ((sn76489->firstdat & 0x70) == 0x60 && (sn76489->type == SN76496)) { + if ((data & 4) != (sn76489->noise & 4) || sn76489->type == SN76496) + sn76489->shift = 0x4000; + sn76489->noise = data & 0xf; + if ((data & 3) == 3) + sn76489->latch[0] = sn76489->latch[1]; + else + sn76489->latch[0] = 0x400 << (data & 3); + if (!sn76489->latch[0]) + sn76489->latch[0] = 1024 << 6; + } else if ((sn76489->firstdat & 0x70) != 0x60) { + sn76489->freqhi[sn76489->lasttone] = data & 0x7F; + freq = sn76489->freqlo[sn76489->lasttone] | (sn76489->freqhi[sn76489->lasttone] << 4); + if (sn76489->extra_divide) + freq &= 0x3ff; + if (!freq) + freq = sn76489->extra_divide ? 2048 : 1024; + if ((sn76489->noise & 3) == 3 && sn76489->lasttone == 1) + sn76489->latch[0] = freq << 6; + sn76489->latch[sn76489->lasttone] = freq << 6; } + } } -void sn74689_set_extra_divide(sn76489_t *sn76489, int enable) +void +sn74689_set_extra_divide(sn76489_t *sn76489, int enable) { - sn76489->extra_divide = enable; + sn76489->extra_divide = enable; } -void sn76489_init(sn76489_t *sn76489, uint16_t base, uint16_t size, int type, int freq) +void +sn76489_init(sn76489_t *sn76489, uint16_t base, uint16_t size, int type, int freq) { - sound_add_handler(sn76489_get_buffer, sn76489); + sound_add_handler(sn76489_get_buffer, sn76489); - sn76489->latch[0] = sn76489->latch[1] = sn76489->latch[2] = sn76489->latch[3] = 0x3FF << 6; - sn76489->vol[0] = 0; - sn76489->vol[1] = sn76489->vol[2] = sn76489->vol[3] = 8; - sn76489->stat[0] = sn76489->stat[1] = sn76489->stat[2] = sn76489->stat[3] = 127; - srand(time(NULL)); - sn76489->count[0] = 0; - sn76489->count[1] = (rand()&0x3FF)<<6; - sn76489->count[2] = (rand()&0x3FF)<<6; - sn76489->count[3] = (rand()&0x3FF)<<6; - sn76489->noise = 3; - sn76489->shift = 0x4000; - sn76489->type = type; - sn76489->psgconst = (((double)freq / 64.0) / 48000.0); + sn76489->latch[0] = sn76489->latch[1] = sn76489->latch[2] = sn76489->latch[3] = 0x3FF << 6; + sn76489->vol[0] = 0; + sn76489->vol[1] = sn76489->vol[2] = sn76489->vol[3] = 8; + sn76489->stat[0] = sn76489->stat[1] = sn76489->stat[2] = sn76489->stat[3] = 127; + srand(time(NULL)); + sn76489->count[0] = 0; + sn76489->count[1] = (rand() & 0x3FF) << 6; + sn76489->count[2] = (rand() & 0x3FF) << 6; + sn76489->count[3] = (rand() & 0x3FF) << 6; + sn76489->noise = 3; + sn76489->shift = 0x4000; + sn76489->type = type; + sn76489->psgconst = (((double) freq / 64.0) / (double) FREQ_48000); - sn76489_mute = 0; + sn76489_mute = 0; - io_sethandler(base, size, NULL, NULL, NULL, sn76489_write, NULL, NULL, sn76489); + io_sethandler(base, size, NULL, NULL, NULL, sn76489_write, NULL, NULL, sn76489); } -void *sn76489_device_init(const device_t *info) +void * +sn76489_device_init(UNUSED(const device_t *info)) { - sn76489_t *sn76489 = malloc(sizeof(sn76489_t)); - memset(sn76489, 0, sizeof(sn76489_t)); + sn76489_t *sn76489 = malloc(sizeof(sn76489_t)); + memset(sn76489, 0, sizeof(sn76489_t)); - sn76489_init(sn76489, 0x00c0, 0x0008, SN76496, 3579545); + sn76489_init(sn76489, 0x00c0, 0x0008, SN76496, 3579545); - return sn76489; -} -void *ncr8496_device_init(const device_t *info) -{ - sn76489_t *sn76489 = malloc(sizeof(sn76489_t)); - memset(sn76489, 0, sizeof(sn76489_t)); - - sn76489_init(sn76489, 0x00c0, 0x0008, NCR8496, 3579545); - - return sn76489; + return sn76489; } -#if defined(DEV_BRANCH) && defined(USE_TANDY_ISA) -void *tndy_device_init(const device_t *info) +void * +ncr8496_device_init(UNUSED(const device_t *info)) { - sn76489_t *sn76489 = malloc(sizeof(sn76489_t)); - memset(sn76489, 0, sizeof(sn76489_t)); + sn76489_t *sn76489 = malloc(sizeof(sn76489_t)); + memset(sn76489, 0, sizeof(sn76489_t)); - uint16_t addr = device_get_config_hex16("base"); + sn76489_init(sn76489, 0x00c0, 0x0008, NCR8496, 3579545); - sn76489_init(sn76489, addr, 0x0008, SN76496, 3579545); - - return sn76489; -} -#endif - -void sn76489_device_close(void *p) -{ - sn76489_t *sn76489 = (sn76489_t *)p; - - free(sn76489); + return sn76489; } -#if defined(DEV_BRANCH) && defined(USE_TANDY_ISA) -static const device_config_t tndy_config[] = +void * +tndy_device_init(UNUSED(const device_t *info)) { - { - "base", "Address", CONFIG_HEX16, "", 0x0C0, "", { 0 }, - { - { - "0x0C0", 0x0C0 - }, - { - "0x1E0", 0x1E0 - }, - { - "0x2C0", 0x2C0 - }, - { - "" - } - } - }, - { - "", "", -1 + sn76489_t *sn76489 = malloc(sizeof(sn76489_t)); + memset(sn76489, 0, sizeof(sn76489_t)); + + uint16_t addr = device_get_config_hex16("base"); + + sn76489_init(sn76489, addr, 0x0008, SN76496, 3579545); + + return sn76489; +} + +void +sn76489_device_close(void *priv) +{ + sn76489_t *sn76489 = (sn76489_t *) priv; + + free(sn76489); +} + +static const device_config_t tndy_config[] = { + // clang-format off + { + .name = "base", + .description = "Address", + .type = CONFIG_HEX16, + .default_string = "", + .default_int = 0x0C0, + .file_filter = "", + .spinner = { 0 }, + .selection = { + { + .description = "0x0C0", + .value = 0x0C0 + }, + { + .description = "0x0E0", + .value = 0x0E0 + }, + { + .description = "0x1C0", + .value = 0x1C0 + }, + { + .description = "0x1E0", + .value = 0x1E0 + }, + { + .description = "0x2C0", + .value = 0x2C0 + }, + { + .description = "0x2E0", + .value = 0x2E0 + }, + { .description = "" } } -}; -#endif - -const device_t sn76489_device = -{ - "TI SN74689 PSG", - "sn76489", - 0, - 0, - sn76489_device_init, - sn76489_device_close, - NULL, { NULL }, NULL, - NULL + }, + { .name = "", .description = "", .type = CONFIG_END } + // clang-format on }; -const device_t ncr8496_device = -{ - "NCR8496 PSG", - "ncr8496", - 0, - 0, - ncr8496_device_init, - sn76489_device_close, - NULL, { NULL }, NULL, - NULL +const device_t sn76489_device = { + .name = "TI SN74689 PSG", + .internal_name = "sn76489", + .flags = 0, + .local = 0, + .init = sn76489_device_init, + .close = sn76489_device_close, + .reset = NULL, + { .available = NULL }, + .speed_changed = NULL, + .force_redraw = NULL, + .config = NULL }; -#if defined(DEV_BRANCH) && defined(USE_TANDY_ISA) -const device_t tndy_device = -{ - "TNDY", - "tndy", - DEVICE_ISA, - 0, - tndy_device_init, - sn76489_device_close, - NULL, { NULL }, NULL, - NULL, - tndy_config +const device_t ncr8496_device = { + .name = "NCR8496 PSG", + .internal_name = "ncr8496", + .flags = 0, + .local = 0, + .init = ncr8496_device_init, + .close = sn76489_device_close, + .reset = NULL, + { .available = NULL }, + .speed_changed = NULL, + .force_redraw = NULL, + .config = NULL +}; + +const device_t tndy_device = { + .name = "TNDY", + .internal_name = "tndy", + .flags = DEVICE_ISA, + .local = 0, + .init = tndy_device_init, + .close = sn76489_device_close, + .reset = NULL, + { .available = NULL }, + .speed_changed = NULL, + .force_redraw = NULL, + .config = tndy_config }; -#endif diff --git a/src/sound/snd_speaker.c b/src/sound/snd_speaker.c index 027febf40..0537cd09a 100644 --- a/src/sound/snd_speaker.c +++ b/src/sound/snd_speaker.c @@ -1,108 +1,113 @@ /* - * 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. + * 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. + * This file is part of the 86Box distribution. * - * Emulation of the PC speaker. + * Emulation of the PC speaker. * * * - * Authors: Sarah Walker, - * Miran Grca, + * Authors: Sarah Walker, + * Miran Grca, * - * Copyright 2008-2019 Sarah Walker. - * Copyright 2016-2019 Miran Grca. + * Copyright 2008-2019 Sarah Walker. + * Copyright 2016-2019 Miran Grca. */ -#include #include +#include #include #include + #include <86box/86box.h> #include <86box/timer.h> #include <86box/pit.h> -#include <86box/sound.h> #include <86box/snd_speaker.h> +#include <86box/sound.h> +#include <86box/plat_unused.h> +int speaker_mute = 0; +int speaker_gated = 0; +int speaker_enable = 0; +int was_speaker_enable = 0; -int speaker_mute = 0, speaker_gated = 0; -int speaker_enable = 0, was_speaker_enable = 0; - -int gated, speakval, speakon; - +int gated; +int speakval; +int speakon; static int32_t speaker_buffer[SOUNDBUFLEN]; -static int speaker_pos = 0; - -static uint8_t speaker_mode = 0; -static double speaker_count = 65535.0; +static int speaker_pos = 0; +static uint8_t speaker_mode = 0; +static double speaker_count = 65535.0; void speaker_set_count(uint8_t new_m, int new_count) { - speaker_mode = new_m; + speaker_mode = new_m; speaker_count = (double) new_count; } - void speaker_update(void) { int32_t val; - double amplitude; + double amplitude; amplitude = ((speaker_count / 64.0) * 10240.0) - 5120.0; if (amplitude > 5120.0) - amplitude = 5120.0; + amplitude = 5120.0; if (speaker_pos < sound_pos_global) { - for (; speaker_pos < sound_pos_global; speaker_pos++) { - if (speaker_gated && was_speaker_enable) { - if ((speaker_mode == 0) || (speaker_mode == 4)) - val = (int32_t) amplitude; - else if (speaker_count < 64.0) - val = 0xa00; - else - val = speakon ? 0x1400 : 0; - } else { - if (speaker_mode == 1) - val = was_speaker_enable ? (int32_t) amplitude : 0; - else - val = was_speaker_enable ? 0x1400 : 0; - } + for (; speaker_pos < sound_pos_global; speaker_pos++) { + if (speaker_gated && was_speaker_enable) { + if ((speaker_mode == 0) || (speaker_mode == 4)) + val = (int32_t) amplitude; + else if (speaker_count < 64.0) + val = 0xa00; + else + val = speakon ? 0x1400 : 0; + } else { + if (speaker_mode == 1) + val = was_speaker_enable ? (int32_t) amplitude : 0; + else + val = was_speaker_enable ? 0x1400 : 0; + } - if (!speaker_enable) - was_speaker_enable = 0; + if (!speaker_enable) + was_speaker_enable = 0; - speaker_buffer[speaker_pos] = val; - } + speaker_buffer[speaker_pos] = val; + } } } - void -speaker_get_buffer(int32_t *buffer, int len, void *p) +speaker_get_buffer(int32_t *buffer, int len, UNUSED(void *priv)) { - int32_t c, val; + double val_l, val_r; speaker_update(); if (!speaker_mute) { - for (c = 0; c < len * 2; c += 2) { - val = speaker_buffer[c >> 1]; - buffer[c] += val; - buffer[c + 1] += val; - } + for (int c = 0; c < len * 2; c += 2) { + val_l = val_r = (double) speaker_buffer[c >> 1]; + /* Apply PC speaker volume and filters */ + if (filter_pc_speaker != NULL) { + filter_pc_speaker(0, &val_l, filter_pc_speaker_p); + filter_pc_speaker(1, &val_r, filter_pc_speaker_p); + } + buffer[c] += (int32_t) val_l; + buffer[c + 1] += (int32_t) val_r; + } } speaker_pos = 0; } - void speaker_init(void) { diff --git a/src/sound/snd_ssi2001.c b/src/sound/snd_ssi2001.c index 1aba2210a..1f3c294ce 100644 --- a/src/sound/snd_ssi2001.c +++ b/src/sound/snd_ssi2001.c @@ -1,126 +1,141 @@ #include #include #include -#include #include +#include #include #define HAVE_STDARG_H + #include <86box/86box.h> -#include <86box/io.h> #include <86box/device.h> #include <86box/gameport.h> -#include <86box/sound.h> +#include <86box/io.h> #include <86box/snd_resid.h> +#include <86box/sound.h> +#include <86box/plat_unused.h> - -typedef struct ssi2001_t -{ - void *psid; - int16_t buffer[SOUNDBUFLEN * 2]; - int pos; - int gameport_enabled; +typedef struct ssi2001_t { + void *psid; + int16_t buffer[SOUNDBUFLEN * 2]; + int pos; + int gameport_enabled; } ssi2001_t; -static void ssi2001_update(ssi2001_t *ssi2001) +static void +ssi2001_update(ssi2001_t *ssi2001) { - if (ssi2001->pos >= sound_pos_global) - return; - - sid_fillbuf(&ssi2001->buffer[ssi2001->pos], sound_pos_global - ssi2001->pos, ssi2001->psid); - ssi2001->pos = sound_pos_global; + if (ssi2001->pos >= sound_pos_global) + return; + + sid_fillbuf(&ssi2001->buffer[ssi2001->pos], sound_pos_global - ssi2001->pos, ssi2001->psid); + ssi2001->pos = sound_pos_global; } -static void ssi2001_get_buffer(int32_t *buffer, int len, void *p) +static void +ssi2001_get_buffer(int32_t *buffer, int len, void *priv) { - ssi2001_t *ssi2001 = (ssi2001_t *)p; - int c; + ssi2001_t *ssi2001 = (ssi2001_t *) priv; - ssi2001_update(ssi2001); - - for (c = 0; c < len * 2; c++) - buffer[c] += ssi2001->buffer[c >> 1] / 2; + ssi2001_update(ssi2001); - ssi2001->pos = 0; + for (int c = 0; c < len * 2; c++) + buffer[c] += ssi2001->buffer[c >> 1] / 2; + + ssi2001->pos = 0; } -static uint8_t ssi2001_read(uint16_t addr, void *p) +static uint8_t +ssi2001_read(uint16_t addr, void *priv) { - ssi2001_t *ssi2001 = (ssi2001_t *)p; - - ssi2001_update(ssi2001); - - return sid_read(addr, p); + ssi2001_t *ssi2001 = (ssi2001_t *) priv; + + ssi2001_update(ssi2001); + + return sid_read(addr, priv); } -static void ssi2001_write(uint16_t addr, uint8_t val, void *p) +static void +ssi2001_write(uint16_t addr, uint8_t val, void *priv) { - ssi2001_t *ssi2001 = (ssi2001_t *)p; - - ssi2001_update(ssi2001); - sid_write(addr, val, p); + ssi2001_t *ssi2001 = (ssi2001_t *) priv; + + ssi2001_update(ssi2001); + sid_write(addr, val, priv); } -void *ssi2001_init(const device_t *info) +void * +ssi2001_init(UNUSED(const device_t *info)) { - ssi2001_t *ssi2001 = malloc(sizeof(ssi2001_t)); - memset(ssi2001, 0, sizeof(ssi2001_t)); + ssi2001_t *ssi2001 = malloc(sizeof(ssi2001_t)); + memset(ssi2001, 0, sizeof(ssi2001_t)); - ssi2001->psid = sid_init(); - sid_reset(ssi2001->psid); - uint16_t addr = device_get_config_hex16("base"); - ssi2001->gameport_enabled = device_get_config_int("gameport"); - io_sethandler(addr, 0x0020, ssi2001_read, NULL, NULL, ssi2001_write, NULL, NULL, ssi2001); - if (ssi2001->gameport_enabled) + ssi2001->psid = sid_init(); + sid_reset(ssi2001->psid); + uint16_t addr = device_get_config_hex16("base"); + ssi2001->gameport_enabled = device_get_config_int("gameport"); + io_sethandler(addr, 0x0020, ssi2001_read, NULL, NULL, ssi2001_write, NULL, NULL, ssi2001); + if (ssi2001->gameport_enabled) gameport_remap(gameport_add(&gameport_201_device), 0x201); - sound_add_handler(ssi2001_get_buffer, ssi2001); - return ssi2001; + sound_add_handler(ssi2001_get_buffer, ssi2001); + return ssi2001; } -void ssi2001_close(void *p) +void +ssi2001_close(void *priv) { - ssi2001_t *ssi2001 = (ssi2001_t *)p; - - sid_close(ssi2001->psid); + ssi2001_t *ssi2001 = (ssi2001_t *) priv; - free(ssi2001); + sid_close(ssi2001->psid); + + free(ssi2001); } -static const device_config_t ssi2001_config[] = -{ - { - "base", "Address", CONFIG_HEX16, "", 0x280, "", { 0 }, - { - { - "0x280", 0x280 - }, - { - "0x2A0", 0x2A0 - }, - { - "0x2C0", 0x2C0 - }, - { - "0x2E0", 0x2E0 - }, - { - "" - } - } - }, - { - "gameport", "Enable Game port", CONFIG_BINARY, "", 1 - }, - { - "", "", -1 +static const device_config_t ssi2001_config[] = { + // clang-format off + { + .name = "base", + .description = "Address", + .type = CONFIG_HEX16, + .default_string = "", + .default_int = 0x280, + .file_filter = "", + .spinner = { 0 }, + .selection = { + { + .description = "0x280", + .value = 0x280 + }, + { + .description = "0x2A0", + .value = 0x2A0 + }, + { + .description = "0x2C0", + .value = 0x2C0 + }, + { + .description = "0x2E0", + .value = 0x2E0 + }, + { .description = "" } } + }, + { "gameport", "Enable Game port", CONFIG_BINARY, "", 1 }, + { "", "", -1 } +// clang-format off }; const device_t ssi2001_device = { - "Innovation SSI-2001", - "ssi2001", - DEVICE_ISA, 0, - ssi2001_init, ssi2001_close, NULL, - { NULL }, NULL, NULL, - ssi2001_config + .name = "Innovation SSI-2001", + .internal_name = "ssi2001", + .flags = DEVICE_ISA, + .local = 0, + .init = ssi2001_init, + .close = ssi2001_close, + .reset = NULL, + { .available = NULL }, + .speed_changed = NULL, + .force_redraw = NULL, + .config = ssi2001_config }; diff --git a/src/sound/snd_wss.c b/src/sound/snd_wss.c index d9739958c..a69d746da 100644 --- a/src/sound/snd_wss.c +++ b/src/sound/snd_wss.c @@ -1,38 +1,39 @@ /* - * 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. + * 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. + * This file is part of the 86Box distribution. * - * Windows Sound System emulation. + * Windows Sound System emulation. * * * - * Authors: Sarah Walker, - * TheCollector1995, + * Authors: Sarah Walker, + * TheCollector1995, * - * Copyright 2012-2018 Sarah Walker. - * Copyright 2018 TheCollector1995. + * Copyright 2012-2018 Sarah Walker. + * Copyright 2018 TheCollector1995. */ -#include +#include #include -#include +#include #include +#include #include -#include + #include <86box/86box.h> +#include <86box/device.h> +#include <86box/dma.h> #include <86box/io.h> -#include <86box/timer.h> #include <86box/mca.h> #include <86box/pic.h> -#include <86box/dma.h> -#include <86box/device.h> #include <86box/sound.h> +#include <86box/timer.h> #include <86box/snd_ad1848.h> #include <86box/snd_opl.h> - +#include <86box/plat_unused.h> /* 530, 11, 3 - 530=23 * 530, 11, 1 - 530=22 @@ -45,31 +46,28 @@ * f40, 11, 1 - 530=22 */ - -static const int wss_dma[4] = {0, 0, 1, 3}; -static const int wss_irq[8] = {5, 7, 9, 10, 11, 12, 14, 15}; /* W95 only uses 7-9, others may be wrong */ - +static const int wss_dma[4] = { 0, 0, 1, 3 }; +static const int wss_irq[8] = { 5, 7, 9, 10, 11, 12, 14, 15 }; /* W95 only uses 7-9, others may be wrong */ typedef struct wss_t { - uint8_t config; + uint8_t config; - ad1848_t ad1848; - opl_t opl; + ad1848_t ad1848; + fm_drv_t opl; - int opl_enabled; - uint8_t pos_regs[8]; + int opl_enabled; + uint8_t pos_regs[8]; } wss_t; - uint8_t -wss_read(uint16_t addr, void *priv) { - wss_t *wss = (wss_t *) priv; +wss_read(UNUSED(uint16_t addr), void *priv) +{ + const wss_t *wss = (wss_t *) priv; return 4 | (wss->config & 0x40); } - void -wss_write(uint16_t addr, uint8_t val, void *priv) +wss_write(UNUSED(uint16_t addr), uint8_t val, void *priv) { wss_t *wss = (wss_t *) priv; @@ -78,36 +76,38 @@ wss_write(uint16_t addr, uint8_t val, void *priv) ad1848_setirq(&wss->ad1848, wss_irq[(val >> 3) & 7]); } - static void wss_get_buffer(int32_t *buffer, int len, void *priv) { wss_t *wss = (wss_t *) priv; - int c; + const int32_t *opl_buf = NULL; + + if (wss->opl_enabled) + opl_buf = wss->opl.update(wss->opl.priv); - opl3_update(&wss->opl); ad1848_update(&wss->ad1848); - for (c = 0; c < len * 2; c++) { - buffer[c] += wss->opl.buffer[c]; - buffer[c] += wss->ad1848.buffer[c] / 2; + for (int c = 0; c < len * 2; c++) { + if (opl_buf) + buffer[c] += opl_buf[c]; + buffer[c] += wss->ad1848.buffer[c] / 2; } - wss->opl.pos = 0; + if (wss->opl_enabled) + wss->opl.reset_buffer(wss->opl.priv); wss->ad1848.pos = 0; } - void * -wss_init(const device_t *info) +wss_init(UNUSED(const device_t *info)) { wss_t *wss = malloc(sizeof(wss_t)); memset(wss, 0, sizeof(wss_t)); - uint16_t addr = device_get_config_hex16("base"); + uint16_t addr = device_get_config_hex16("base"); wss->opl_enabled = device_get_config_int("opl"); if (wss->opl_enabled) - opl3_init(&wss->opl); + fm_driver_get(FM_YMF262, &wss->opl); ad1848_init(&wss->ad1848, AD1848_TYPE_DEFAULT); @@ -115,71 +115,94 @@ wss_init(const device_t *info) ad1848_setdma(&wss->ad1848, 3); if (wss->opl_enabled) - io_sethandler(0x0388, 0x0004, opl3_read, NULL, NULL, opl3_write, NULL, NULL, &wss->opl); + io_sethandler(0x0388, 0x0004, + wss->opl.read, NULL, NULL, + wss->opl.write, NULL, NULL, + wss->opl.priv); - io_sethandler(addr, 0x0004, wss_read, NULL, NULL, wss_write, NULL, NULL, wss); - io_sethandler(addr+4, 0x0004, ad1848_read, NULL, NULL, ad1848_write, NULL, NULL, &wss->ad1848); + io_sethandler(addr, 0x0004, + wss_read, NULL, NULL, + wss_write, NULL, NULL, + wss); + io_sethandler(addr + 4, 0x0004, + ad1848_read, NULL, NULL, + ad1848_write, NULL, NULL, + &wss->ad1848); sound_add_handler(wss_get_buffer, wss); return wss; } - static uint8_t ncr_audio_mca_read(int port, void *priv) { - wss_t *wss = (wss_t *) priv; + const wss_t *wss = (wss_t *) priv; return wss->pos_regs[port & 7]; } - static void ncr_audio_mca_write(int port, uint8_t val, void *priv) { - wss_t *wss = (wss_t *) priv; - uint16_t ports[4] = {0x530, 0xE80, 0xF40, 0x604}; + wss_t *wss = (wss_t *) priv; + uint16_t ports[4] = { 0x530, 0xE80, 0xF40, 0x604 }; uint16_t addr; if (port < 0x102) - return; + return; wss->opl_enabled = (wss->pos_regs[2] & 0x20) ? 1 : 0; - addr = ports[(wss->pos_regs[2] & 0x18) >> 3]; + addr = ports[(wss->pos_regs[2] & 0x18) >> 3]; - io_removehandler(0x0388, 0x0004, opl3_read, NULL, NULL, opl3_write, NULL, NULL, &wss->opl); - io_removehandler(addr, 0x0004, wss_read, NULL, NULL, wss_write, NULL, NULL, wss); - io_removehandler(addr+4, 0x0004, ad1848_read, NULL, NULL, ad1848_write, NULL, NULL, &wss->ad1848); + io_removehandler(0x0388, 0x0004, + wss->opl.read, NULL, NULL, + wss->opl.write, NULL, NULL, + wss->opl.priv); + io_removehandler(addr, 0x0004, + wss_read, NULL, NULL, + wss_write, NULL, NULL, + wss); + io_removehandler(addr + 4, 0x0004, + ad1848_read, NULL, NULL, + ad1848_write, NULL, NULL, + &wss->ad1848); wss->pos_regs[port & 7] = val; if (wss->pos_regs[2] & 1) { - addr = ports[(wss->pos_regs[2] & 0x18) >> 3]; + addr = ports[(wss->pos_regs[2] & 0x18) >> 3]; - if (wss->opl_enabled) - io_sethandler(0x0388, 0x0004, opl3_read, NULL, NULL, opl3_write, NULL, NULL, &wss->opl); - - io_sethandler(addr, 0x0004, wss_read, NULL, NULL, wss_write, NULL, NULL, wss); - io_sethandler(addr+4, 0x0004, ad1848_read, NULL, NULL, ad1848_write, NULL, NULL, &wss->ad1848); + if (wss->opl_enabled) + io_sethandler(0x0388, 0x0004, + wss->opl.read, NULL, NULL, + wss->opl.write, NULL, NULL, + wss->opl.priv); + + io_sethandler(addr, 0x0004, + wss_read, NULL, NULL, + wss_write, NULL, NULL, + wss); + io_sethandler(addr + 4, 0x0004, + ad1848_read, NULL, NULL, + ad1848_write, NULL, NULL, + &wss->ad1848); } } - static uint8_t ncr_audio_mca_feedb(void *priv) { - wss_t *wss = (wss_t *) priv; + const wss_t *wss = (wss_t *) priv; return (wss->pos_regs[2] & 1); } - void * -ncr_audio_init(const device_t *info) +ncr_audio_init(UNUSED(const device_t *info)) { wss_t *wss = malloc(sizeof(wss_t)); memset(wss, 0, sizeof(wss_t)); - opl3_init(&wss->opl); + fm_driver_get(FM_YMF262, &wss->opl); ad1848_init(&wss->ad1848, AD1848_TYPE_DEFAULT); ad1848_setirq(&wss->ad1848, 7); @@ -194,7 +217,6 @@ ncr_audio_init(const device_t *info) return wss; } - void wss_close(void *priv) { @@ -202,7 +224,6 @@ wss_close(void *priv) free(wss); } - void wss_speed_changed(void *priv) { @@ -210,57 +231,71 @@ wss_speed_changed(void *priv) ad1848_speed_changed(&wss->ad1848); } - static const device_config_t wss_config[] = { + // clang-format off { - "base", "Address", CONFIG_HEX16, "", 0x530, "", { 0 }, - { - { - "0x530", 0x530 - }, - { - "0x604", 0x604 - }, - { - "0xe80", 0xe80 - }, - { - "0xf40", 0xf40 - }, - { - "" - } - } + .name = "base", + .description = "Address", + .type = CONFIG_HEX16, + .default_string = "", + .default_int = 0x530, + .file_filter = "", + .spinner = { 0 }, + .selection = { + { + .description = "0x530", + .value = 0x530 + }, + { + .description = "0x604", + .value = 0x604 + }, + { + .description = "0xe80", + .value = 0xe80 + }, + { + .description = "0xf40", + .value = 0xf40 + }, + { .description = "" } + } }, { - "opl", "Enable OPL", CONFIG_BINARY, "", 1 + .name = "opl", + .description = "Enable OPL", + .type = CONFIG_BINARY, + .default_string = "", + .default_int = 1 }, - { - "", "", -1 - } + { .name = "", .description = "", .type = CONFIG_END } + // clang-format on }; - -const device_t wss_device = -{ - "Windows Sound System", - "wss", - DEVICE_ISA | DEVICE_AT, 0, - wss_init, wss_close, NULL, - { NULL }, - wss_speed_changed, - NULL, - wss_config +const device_t wss_device = { + .name = "Windows Sound System", + .internal_name = "wss", + .flags = DEVICE_ISA | DEVICE_AT, + .local = 0, + .init = wss_init, + .close = wss_close, + .reset = NULL, + { .available = NULL }, + .speed_changed = wss_speed_changed, + .force_redraw = NULL, + .config = wss_config }; -const device_t ncr_business_audio_device = -{ - "NCR Business Audio", - "ncraudio", - DEVICE_MCA, 0, - ncr_audio_init, wss_close, NULL, - { NULL }, - wss_speed_changed, - NULL, - NULL +const device_t ncr_business_audio_device = { + .name = "NCR Business Audio", + .internal_name = "ncraudio", + .flags = DEVICE_MCA, + .local = 0, + .init = ncr_audio_init, + .close = wss_close, + .reset = NULL, + { .available = NULL }, + .speed_changed = wss_speed_changed, + .force_redraw = NULL, + .config = NULL }; diff --git a/src/sound/snd_ym7128.c b/src/sound/snd_ym7128.c index 42d21ba63..59e5691e9 100644 --- a/src/sound/snd_ym7128.c +++ b/src/sound/snd_ym7128.c @@ -1,138 +1,157 @@ -#include #include +#include #include #include + #include <86box/86box.h> #include <86box/snd_ym7128.h> - +#include <86box/plat_unused.h> static int attenuation[32]; static int tap_position[32]; - -void ym7128_init(ym7128_t *ym7128) +void +ym7128_init(UNUSED(ym7128_t *ym7128)) { - int c; - double out = 65536.0; - - for (c = 0; c < 32; c++) - tap_position[c] = c * (2400 / 31); + int c; + double out = 65536.0; - for (c = 31; c >= 1; c--) - { - attenuation[c] = (int)out; - out /= 1.25963; /*2 dB steps*/ - } - attenuation[0] = 0; + for (c = 0; c < 32; c++) + tap_position[c] = c * (2400 / 31); + + for (c = 31; c >= 1; c--) { + attenuation[c] = (int) out; + out /= 1.25963; /*2 dB steps*/ + } + attenuation[0] = 0; } #define GET_ATTENUATION(val) (val & 0x20) ? -attenuation[val & 0x1f] : attenuation[val & 0x1f] -void ym7128_write(ym7128_t *ym7128, uint8_t val) +void +ym7128_write(ym7128_t *ym7128, uint8_t val) { - int new_dat = val & 1; - int new_sci = val & 2; - int new_a0 = val & 4; - if (!ym7128->sci && new_sci) - ym7128->dat = (ym7128->dat << 1) | new_dat; - - if (ym7128->a0 != new_a0) - { - if (!ym7128->a0) - ym7128->reg_sel = ym7128->dat & 0x1f; - else - { - switch (ym7128->reg_sel) - { - case 0x00: case 0x01: case 0x02: case 0x03: - case 0x04: case 0x05: case 0x06: case 0x07: - ym7128->gl[ym7128->reg_sel & 7] = GET_ATTENUATION(ym7128->dat); - break; - case 0x08: case 0x09: case 0x0a: case 0x0b: - case 0x0c: case 0x0d: case 0x0e: case 0x0f: - ym7128->gr[ym7128->reg_sel & 7] = GET_ATTENUATION(ym7128->dat); - break; - - case 0x10: - ym7128->vm = GET_ATTENUATION(ym7128->dat); - break; - case 0x11: - ym7128->vc = GET_ATTENUATION(ym7128->dat); - break; - case 0x12: - ym7128->vl = GET_ATTENUATION(ym7128->dat); - break; - case 0x13: - ym7128->vr = GET_ATTENUATION(ym7128->dat); - break; + int new_dat = val & 1; + int new_sci = val & 2; + int new_a0 = val & 4; + if (!ym7128->sci && new_sci) + ym7128->dat = (ym7128->dat << 1) | new_dat; - case 0x14: - ym7128->c0 = (ym7128->dat & 0x3f) << 6; - if (ym7128->dat & 0x20) - ym7128->c0 |= 0xfffff000; - break; - case 0x15: - ym7128->c1 = (ym7128->dat & 0x3f) << 6; - if (ym7128->dat & 0x20) - ym7128->c1 |= 0xfffff000; - break; + if (ym7128->a0 != new_a0) { + if (!ym7128->a0) + ym7128->reg_sel = ym7128->dat & 0x1f; + else { + switch (ym7128->reg_sel) { + case 0x00: + case 0x01: + case 0x02: + case 0x03: + case 0x04: + case 0x05: + case 0x06: + case 0x07: + ym7128->gl[ym7128->reg_sel & 7] = GET_ATTENUATION(ym7128->dat); + break; + case 0x08: + case 0x09: + case 0x0a: + case 0x0b: + case 0x0c: + case 0x0d: + case 0x0e: + case 0x0f: + ym7128->gr[ym7128->reg_sel & 7] = GET_ATTENUATION(ym7128->dat); + break; - case 0x16: case 0x17: case 0x18: case 0x19: - case 0x1a: case 0x1b: case 0x1c: case 0x1d: case 0x1e: - ym7128->t[ym7128->reg_sel - 0x16] = tap_position[ym7128->dat & 0x1f]; - break; - } - ym7128->regs[ym7128->reg_sel] = ym7128->dat; - } - ym7128->dat = 0; + case 0x10: + ym7128->vm = GET_ATTENUATION(ym7128->dat); + break; + case 0x11: + ym7128->vc = GET_ATTENUATION(ym7128->dat); + break; + case 0x12: + ym7128->vl = GET_ATTENUATION(ym7128->dat); + break; + case 0x13: + ym7128->vr = GET_ATTENUATION(ym7128->dat); + break; + + case 0x14: + ym7128->c0 = (ym7128->dat & 0x3f) << 6; + if (ym7128->dat & 0x20) + ym7128->c0 |= 0xfffff000; + break; + case 0x15: + ym7128->c1 = (ym7128->dat & 0x3f) << 6; + if (ym7128->dat & 0x20) + ym7128->c1 |= 0xfffff000; + break; + + case 0x16: + case 0x17: + case 0x18: + case 0x19: + case 0x1a: + case 0x1b: + case 0x1c: + case 0x1d: + case 0x1e: + ym7128->t[ym7128->reg_sel - 0x16] = tap_position[ym7128->dat & 0x1f]; + break; + + default: + break; + } + ym7128->regs[ym7128->reg_sel] = ym7128->dat; } + ym7128->dat = 0; + } - ym7128->sci = new_sci; - ym7128->a0 = new_a0; + ym7128->sci = new_sci; + ym7128->a0 = new_a0; } #define GET_DELAY_SAMPLE(ym7128, offset) (((ym7128->delay_pos - offset) < 0) ? ym7128->delay_buffer[(ym7128->delay_pos - offset) + 2400] : ym7128->delay_buffer[ym7128->delay_pos - offset]) -void ym7128_apply(ym7128_t *ym7128, int16_t *buffer, int len) +void +ym7128_apply(ym7128_t *ym7128, int16_t *buffer, int len) { - int c, d; - - for (c = 0; c < len*2; c += 4) - { - /*YM7128 samples a mono stream at ~24 kHz, so downsample*/ - int32_t samp = ((int32_t)buffer[c] + (int32_t)buffer[c+1] + (int32_t)buffer[c+2] + (int32_t)buffer[c+3]) / 4; - int32_t filter_temp, filter_out; - int32_t samp_l = 0, samp_r = 0; + for (int c = 0; c < len * 2; c += 4) { + /*YM7128 samples a mono stream at ~24 kHz, so downsample*/ + int32_t samp = ((int32_t) buffer[c] + (int32_t) buffer[c + 1] + (int32_t) buffer[c + 2] + (int32_t) buffer[c + 3]) / 4; + int32_t filter_temp; + int32_t filter_out; + int32_t samp_l = 0; + int32_t samp_r = 0; - filter_temp = GET_DELAY_SAMPLE(ym7128, ym7128->t[0]); - filter_out = ((filter_temp * ym7128->c0) >> 11) + ((ym7128->filter_dat * ym7128->c1) >> 11); - filter_out = (filter_out * ym7128->vc) >> 16; + filter_temp = GET_DELAY_SAMPLE(ym7128, ym7128->t[0]); + filter_out = ((filter_temp * ym7128->c0) >> 11) + ((ym7128->filter_dat * ym7128->c1) >> 11); + filter_out = (filter_out * ym7128->vc) >> 16; - samp = (samp * ym7128->vm) >> 16; - samp += filter_out; - - ym7128->delay_buffer[ym7128->delay_pos] = samp; - - for (d = 0; d < 8; d++) - { - samp_l += (GET_DELAY_SAMPLE(ym7128, ym7128->t[d+1]) * ym7128->gl[d]) >> 16; - samp_r += (GET_DELAY_SAMPLE(ym7128, ym7128->t[d+1]) * ym7128->gr[d]) >> 16; - } - - samp_l = (samp_l * ym7128->vl*2) >> 16; - samp_r = (samp_r * ym7128->vr*2) >> 16; - - buffer[c] += ((int32_t)samp_l + (int32_t)ym7128->prev_l) / 2; - buffer[c+1] += ((int32_t)samp_r + (int32_t)ym7128->prev_r) / 2; - buffer[c+2] += samp_l; - buffer[c+3] += samp_r; - - ym7128->delay_pos++; - if (ym7128->delay_pos >= 2400) - ym7128->delay_pos = 0; - - ym7128->filter_dat = filter_temp; - ym7128->prev_l = samp_l; - ym7128->prev_r = samp_r; + samp = (samp * ym7128->vm) >> 16; + samp += filter_out; + + ym7128->delay_buffer[ym7128->delay_pos] = samp; + + for (uint8_t d = 0; d < 8; d++) { + samp_l += (GET_DELAY_SAMPLE(ym7128, ym7128->t[d + 1]) * ym7128->gl[d]) >> 16; + samp_r += (GET_DELAY_SAMPLE(ym7128, ym7128->t[d + 1]) * ym7128->gr[d]) >> 16; } + + samp_l = (samp_l * ym7128->vl * 2) >> 16; + samp_r = (samp_r * ym7128->vr * 2) >> 16; + + buffer[c] += (samp_l + (int32_t) ym7128->prev_l) / 2; + buffer[c + 1] += (samp_r + (int32_t) ym7128->prev_r) / 2; + buffer[c + 2] += samp_l; + buffer[c + 3] += samp_r; + + ym7128->delay_pos++; + if (ym7128->delay_pos >= 2400) + ym7128->delay_pos = 0; + + ym7128->filter_dat = filter_temp; + ym7128->prev_l = samp_l; + ym7128->prev_r = samp_r; + } } diff --git a/src/sound/sound.c b/src/sound/sound.c index 7fbbd4d1c..ed7f821e0 100644 --- a/src/sound/sound.c +++ b/src/sound/sound.c @@ -1,220 +1,240 @@ /* - * 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. + * 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. + * This file is part of the 86Box distribution. * - * Sound emulation core. + * Sound emulation core. * * * - * Authors: Sarah Walker, - * Miran Grca, + * Authors: Sarah Walker, + * Miran Grca, * - * Copyright 2008-2020 Sarah Walker. - * Copyright 2016-2020 Miran Grca. + * Copyright 2008-2020 Sarah Walker. + * Copyright 2016-2020 Miran Grca. */ #include #include #include #include -#include #include +#include #include #define HAVE_STDARG_H -#include <86box/86box.h> -#include <86box/device.h> -#include <86box/timer.h> -#include <86box/cdrom.h> -#include <86box/hdc_ide.h> -#include <86box/plat.h> -#include <86box/machine.h> -#include <86box/sound.h> -#include <86box/midi.h> -#include <86box/snd_opl.h> -#include <86box/snd_mpu401.h> -#include <86box/snd_sb_dsp.h> -#include <86box/snd_azt2316a.h> -#include <86box/snd_ac97.h> -#include <86box/filters.h> +#include <86box/86box.h> +#include <86box/cdrom.h> +#include <86box/device.h> +#include <86box/filters.h> +#include <86box/hdc_ide.h> +#include <86box/machine.h> +#include <86box/midi.h> +#include <86box/plat.h> +#include <86box/thread.h> +#include <86box/snd_ac97.h> +#include <86box/snd_azt2316a.h> +#include <86box/timer.h> +#include <86box/snd_mpu401.h> +#include <86box/sound.h> +#include <86box/snd_opl.h> +#include <86box/snd_sb_dsp.h> typedef struct { - const device_t *device; + const device_t *device; } SOUND_CARD; typedef struct { - void (*get_buffer)(int32_t *buffer, int len, void *p); - void *priv; + void (*get_buffer)(int32_t *buffer, int len, void *priv); + void *priv; } sound_handler_t; - -int sound_card_current = 0; -int sound_pos_global = 0; -int sound_gain = 0; - +int sound_card_current[SOUND_CARD_MAX] = { 0, 0, 0, 0 }; +int sound_pos_global = 0; +int sound_gain = 0; static sound_handler_t sound_handlers[8]; -static thread_t *sound_cd_thread_h; -static event_t *sound_cd_event; -static event_t *sound_cd_start_event; -static int32_t *outbuffer; -static float *outbuffer_ex; -static int16_t *outbuffer_ex_int16; -static int sound_handlers_num; +static thread_t *sound_cd_thread_h; +static event_t *sound_cd_event; +static event_t *sound_cd_start_event; +static int32_t *outbuffer; +static float *outbuffer_ex; +static int16_t *outbuffer_ex_int16; +static int sound_handlers_num; static pc_timer_t sound_poll_timer; -static uint64_t sound_poll_latch; +static uint64_t sound_poll_latch; -static int16_t cd_buffer[CDROM_NUM][CD_BUFLEN * 2]; -static float cd_out_buffer[CD_BUFLEN * 2]; -static int16_t cd_out_buffer_int16[CD_BUFLEN * 2]; -static unsigned int cd_vol_l, cd_vol_r; -static int cd_buf_update = CD_BUFLEN / SOUNDBUFLEN; -static volatile int cdaudioon = 0; -static int cd_thread_enable = 0; +static int16_t cd_buffer[CDROM_NUM][CD_BUFLEN * 2]; +static float cd_out_buffer[CD_BUFLEN * 2]; +static int16_t cd_out_buffer_int16[CD_BUFLEN * 2]; +static unsigned int cd_vol_l; +static unsigned int cd_vol_r; +static int cd_buf_update = CD_BUFLEN / SOUNDBUFLEN; +static volatile int cdaudioon = 0; +static int cd_thread_enable = 0; -static void (*filter_cd_audio)(int channel, double *buffer, void *p) = NULL; -static void *filter_cd_audio_p = NULL; +static void (*filter_cd_audio)(int channel, double *buffer, void *priv) = NULL; +static void *filter_cd_audio_p = NULL; +void (*filter_pc_speaker)(int channel, double *buffer, void *priv) = NULL; +void *filter_pc_speaker_p = NULL; static const device_t sound_none_device = { - "None", - "none", - 0, 0, - NULL, NULL, NULL, - { NULL }, NULL, NULL, - NULL + .name = "None", + .internal_name = "none", + .flags = 0, + .local = 0, + .init = NULL, + .close = NULL, + .reset = NULL, + { .available = NULL }, + .speed_changed = NULL, + .force_redraw = NULL, + .config = NULL }; + static const device_t sound_internal_device = { - "Internal", - "internal", - 0, 0, - NULL, NULL, NULL, - { NULL }, NULL, NULL, - NULL + .name = "Internal", + .internal_name = "internal", + .flags = 0, + .local = 0, + .init = NULL, + .close = NULL, + .reset = NULL, + { .available = NULL }, + .speed_changed = NULL, + .force_redraw = NULL, + .config = NULL }; - -static const SOUND_CARD sound_cards[] = -{ - { &sound_none_device }, - { &sound_internal_device }, - { &adlib_device }, - { &adgold_device }, - { &azt2316a_device }, - { &azt1605_device }, - { &cs4236b_device }, - { &sb_1_device }, - { &sb_15_device }, - { &sb_2_device }, - { &sb_pro_v1_device }, - { &sb_pro_v2_device }, - { &sb_16_device }, - { &sb_16_pnp_device }, - { &sb_32_pnp_device }, - { &sb_awe32_device }, - { &sb_awe32_pnp_device }, - { &sb_awe64_value_device }, - { &sb_awe64_device }, - { &sb_awe64_gold_device }, +static const SOUND_CARD sound_cards[] = { + // clang-format off + { &sound_none_device }, + { &sound_internal_device }, + { &acermagic_s20_device }, + { &mirosound_pcm10_device }, + { &adlib_device }, + { &adgold_device }, + { &azt2316a_device }, + { &azt1605_device }, + { &cms_device }, + { &cs4235_device }, + { &cs4236b_device }, + { &gus_device }, + { &sb_1_device }, + { &sb_15_device }, + { &sb_2_device }, + { &sb_pro_v1_device }, + { &sb_pro_v2_device }, + { &sb_16_device }, + { &sb_16_pnp_device }, + { &sb_32_pnp_device }, + { &sb_awe32_device }, + { &sb_awe32_pnp_device }, + { &sb_awe64_value_device }, + { &sb_awe64_device }, + { &sb_awe64_gold_device }, + { &sb_vibra16c_device }, + { &sb_vibra16s_device }, + { &sb_vibra16xv_device }, + { &ssi2001_device }, #if defined(DEV_BRANCH) && defined(USE_PAS16) - { &pas16_device }, + { &pas16_device }, #endif -#if defined(DEV_BRANCH) && defined(USE_TANDY_ISA) - { &pssj_isa_device }, - { &tndy_device }, -#endif - { &wss_device }, - { &adlib_mca_device }, - { &ncr_business_audio_device }, - { &sb_mcv_device }, - { &sb_pro_mcv_device }, - { &es1371_device }, - { &ad1881_device }, - { &cs4297a_device }, - { NULL } + { &pssj_isa_device }, + { &tndy_device }, + { &wss_device }, + { &adlib_mca_device }, + { &ncr_business_audio_device }, + { &sb_mcv_device }, + { &sb_pro_mcv_device }, + { &sb_16_reply_mca_device }, + { &cmi8338_device }, + { &cmi8738_device }, + { &es1371_device }, + { &ad1881_device }, + { &cs4297a_device }, + { NULL } + // clang-format on }; - #ifdef ENABLE_SOUND_LOG int sound_do_log = ENABLE_SOUND_LOG; - static void sound_log(const char *fmt, ...) { va_list ap; if (sound_do_log) { - va_start(ap, fmt); - pclog_ex(fmt, ap); - va_end(ap); + va_start(ap, fmt); + pclog_ex(fmt, ap); + va_end(ap); } } #else -#define sound_log(fmt, ...) +# define sound_log(fmt, ...) #endif - int sound_card_available(int card) { if (sound_cards[card].device) - return device_available(sound_cards[card].device); + return device_available(sound_cards[card].device); return 1; } - const device_t * sound_card_getdevice(int card) { return sound_cards[card].device; } - int sound_card_has_config(int card) { if (!sound_cards[card].device) - return 0; - return sound_cards[card].device->config ? 1 : 0; + return 0; + return device_has_config(sound_cards[card].device) ? 1 : 0; } - -char * +const char * sound_card_get_internal_name(int card) { return device_get_internal_name(sound_cards[card].device); } - int -sound_card_get_from_internal_name(char *s) +sound_card_get_from_internal_name(const char *s) { int c = 0; while (sound_cards[c].device != NULL) { - if (!strcmp((char *) sound_cards[c].device->internal_name, s)) - return c; - c++; + if (!strcmp(sound_cards[c].device->internal_name, s)) + return c; + c++; } return 0; } - void sound_card_init(void) { - if (sound_cards[sound_card_current].device) - device_add(sound_cards[sound_card_current].device); + if ((sound_card_current[0] > SOUND_INTERNAL) && (sound_cards[sound_card_current[0]].device)) + device_add(sound_cards[sound_card_current[0]].device); + if ((sound_card_current[1] > SOUND_INTERNAL) && (sound_cards[sound_card_current[1]].device)) + device_add(sound_cards[sound_card_current[1]].device); + if ((sound_card_current[2] > SOUND_INTERNAL) && (sound_cards[sound_card_current[2]].device)) + device_add(sound_cards[sound_card_current[2]].device); + if ((sound_card_current[3] > SOUND_INTERNAL) && (sound_cards[sound_card_current[3]].device)) + device_add(sound_cards[sound_card_current[3]].device); } - void sound_set_cd_volume(unsigned int vol_l, unsigned int vol_r) { @@ -222,221 +242,222 @@ sound_set_cd_volume(unsigned int vol_l, unsigned int vol_r) cd_vol_r = vol_r; } - static void sound_cd_clean_buffers(void) { if (sound_is_float) - memset(cd_out_buffer, 0, (CD_BUFLEN * 2) * sizeof(float)); + memset(cd_out_buffer, 0, (CD_BUFLEN * 2) * sizeof(float)); else - memset(cd_out_buffer_int16, 0, (CD_BUFLEN * 2) * sizeof(int16_t)); + memset(cd_out_buffer_int16, 0, (CD_BUFLEN * 2) * sizeof(int16_t)); } - static void -sound_cd_thread(void *param) +sound_cd_thread(UNUSED(void *param)) { uint32_t lba; - int c, r, i, pre, channel_select[2]; - double audio_vol_l, audio_vol_r; - double cd_buffer_temp[2] = {0.0, 0.0}; + int r; + int pre; + int channel_select[2]; + double audio_vol_l; + double audio_vol_r; + double cd_buffer_temp[2] = { 0.0, 0.0 }; thread_set_event(sound_cd_start_event); while (cdaudioon) { - thread_wait_event(sound_cd_event, -1); - thread_reset_event(sound_cd_event); + thread_wait_event(sound_cd_event, -1); + thread_reset_event(sound_cd_event); - if (!cdaudioon) - return; + if (!cdaudioon) + return; - sound_cd_clean_buffers(); + sound_cd_clean_buffers(); - for (i = 0; i < CDROM_NUM; i++) { - if ((cdrom[i].bus_type == CDROM_BUS_DISABLED) || - (cdrom[i].cd_status == CD_STATUS_EMPTY)) - continue; - lba = cdrom[i].seek_pos; - r = cdrom_audio_callback(&(cdrom[i]), cd_buffer[i], CD_BUFLEN * 2); - if (!cdrom[i].bus_type || !cdrom[i].sound_on || !r) - continue; - pre = cdrom_is_pre(&(cdrom[i]), lba); + for (uint8_t i = 0; i < CDROM_NUM; i++) { + if ((cdrom[i].bus_type == CDROM_BUS_DISABLED) || (cdrom[i].cd_status == CD_STATUS_EMPTY)) + continue; + lba = cdrom[i].seek_pos; + r = cdrom_audio_callback(&(cdrom[i]), cd_buffer[i], CD_BUFLEN * 2); + if (!cdrom[i].bus_type || !cdrom[i].sound_on || !r) + continue; + pre = cdrom_is_pre(&(cdrom[i]), lba); - if (cdrom[i].get_volume) { - audio_vol_l = (float) (cdrom[i].get_volume(cdrom[i].priv, 0)); - audio_vol_r = (float) (cdrom[i].get_volume(cdrom[i].priv, 1)); - } else { - audio_vol_l = 255.0; - audio_vol_r = 255.0; - } + if (cdrom[i].get_volume) { + audio_vol_l = (float) (cdrom[i].get_volume(cdrom[i].priv, 0)); + audio_vol_r = (float) (cdrom[i].get_volume(cdrom[i].priv, 1)); + } else { + audio_vol_l = 255.0; + audio_vol_r = 255.0; + } - /* Calculate attenuation per the specification. */ - if (audio_vol_l >= 255.0) - audio_vol_l = 1.0; - else if (audio_vol_l > 0.0) - audio_vol_l = (48.0 + (20.0 * log(audio_vol_l / 256.0))) / 48.0; - else - audio_vol_l = 0.0; + /* Calculate attenuation per the specification. */ + if (audio_vol_l >= 255.0) + audio_vol_l = 1.0; + else if (audio_vol_l > 0.0) + audio_vol_l = (48.0 + (20.0 * log(audio_vol_l / 256.0))) / 48.0; + else + audio_vol_l = 0.0; - if (audio_vol_r >= 255.0) - audio_vol_r = 1.0; - else if (audio_vol_r > 0.0) - audio_vol_r = (48.0 + (20.0 * log(audio_vol_r / 256.0))) / 48.0; - else - audio_vol_r = 0.0; + if (audio_vol_r >= 255.0) + audio_vol_r = 1.0; + else if (audio_vol_r > 0.0) + audio_vol_r = (48.0 + (20.0 * log(audio_vol_r / 256.0))) / 48.0; + else + audio_vol_r = 0.0; - if (cdrom[i].get_channel) { - channel_select[0] = cdrom[i].get_channel(cdrom[i].priv, 0); - channel_select[1] = cdrom[i].get_channel(cdrom[i].priv, 1); - } else { - channel_select[0] = 1; - channel_select[1] = 2; - } + if (cdrom[i].get_channel) { + channel_select[0] = cdrom[i].get_channel(cdrom[i].priv, 0); + channel_select[1] = cdrom[i].get_channel(cdrom[i].priv, 1); + } else { + channel_select[0] = 1; + channel_select[1] = 2; + } - for (c = 0; c < CD_BUFLEN*2; c += 2) { - /*Apply ATAPI channel select*/ - cd_buffer_temp[0] = cd_buffer_temp[1] = 0.0; + for (uint16_t c = 0; c < CD_BUFLEN * 2; c += 2) { + /*Apply ATAPI channel select*/ + cd_buffer_temp[0] = cd_buffer_temp[1] = 0.0; - if ((audio_vol_l != 0.0) && (channel_select[0] != 0)) { - if (channel_select[0] & 1) - cd_buffer_temp[0] += ((double) cd_buffer[i][c]); /* Channel 0 => Port 0 */ - if (channel_select[0] & 2) - cd_buffer_temp[0] += ((double) cd_buffer[i][c + 1]); /* Channel 1 => Port 0 */ + if ((audio_vol_l != 0.0) && (channel_select[0] != 0)) { + if (channel_select[0] & 1) + cd_buffer_temp[0] += ((double) cd_buffer[i][c]); /* Channel 0 => Port 0 */ + if (channel_select[0] & 2) + cd_buffer_temp[0] += ((double) cd_buffer[i][c + 1]); /* Channel 1 => Port 0 */ - cd_buffer_temp[0] *= audio_vol_l; /* Multiply Port 0 by Port 0 volume */ + cd_buffer_temp[0] *= audio_vol_l; /* Multiply Port 0 by Port 0 volume */ - if (pre) - cd_buffer_temp[0] = deemph_iir(0, cd_buffer_temp[0]); /* De-emphasize if necessary */ - } + if (pre) + cd_buffer_temp[0] = deemph_iir(0, cd_buffer_temp[0]); /* De-emphasize if necessary */ + } - if ((audio_vol_r != 0.0) && (channel_select[1] != 0)) { - if (channel_select[1] & 1) - cd_buffer_temp[1] += ((double) cd_buffer[i][c]); /* Channel 0 => Port 1 */ - if (channel_select[1] & 2) - cd_buffer_temp[1] += ((double) cd_buffer[i][c + 1]); /* Channel 1 => Port 1 */ + if ((audio_vol_r != 0.0) && (channel_select[1] != 0)) { + if (channel_select[1] & 1) + cd_buffer_temp[1] += ((double) cd_buffer[i][c]); /* Channel 0 => Port 1 */ + if (channel_select[1] & 2) + cd_buffer_temp[1] += ((double) cd_buffer[i][c + 1]); /* Channel 1 => Port 1 */ - cd_buffer_temp[1] *= audio_vol_r; /* Multiply Port 1 by Port 1 volume */ + cd_buffer_temp[1] *= audio_vol_r; /* Multiply Port 1 by Port 1 volume */ - if (pre) - cd_buffer_temp[1] = deemph_iir(1, cd_buffer_temp[1]); /* De-emphasize if necessary */ - } + if (pre) + cd_buffer_temp[1] = deemph_iir(1, cd_buffer_temp[1]); /* De-emphasize if necessary */ + } - /* Apply sound card CD volume and filters */ - if (filter_cd_audio != NULL) { - filter_cd_audio(0, &(cd_buffer_temp[0]), filter_cd_audio_p); - filter_cd_audio(1, &(cd_buffer_temp[1]), filter_cd_audio_p); - } + /* Apply sound card CD volume and filters */ + if (filter_cd_audio != NULL) { + filter_cd_audio(0, &(cd_buffer_temp[0]), filter_cd_audio_p); + filter_cd_audio(1, &(cd_buffer_temp[1]), filter_cd_audio_p); + } - if (sound_is_float) { - cd_out_buffer[c] += (float) (cd_buffer_temp[0] / 32768.0); - cd_out_buffer[c+1] += (float) (cd_buffer_temp[1] / 32768.0); - } else { - if (cd_buffer_temp[0] > 32767) - cd_buffer_temp[0] = 32767; - if (cd_buffer_temp[0] < -32768) - cd_buffer_temp[0] = -32768; - if (cd_buffer_temp[1] > 32767) - cd_buffer_temp[1] = 32767; - if (cd_buffer_temp[1] < -32768) - cd_buffer_temp[1] = -32768; + if (sound_is_float) { + cd_out_buffer[c] += (float) (cd_buffer_temp[0] / 32768.0); + cd_out_buffer[c + 1] += (float) (cd_buffer_temp[1] / 32768.0); + } else { + if (cd_buffer_temp[0] > 32767) + cd_buffer_temp[0] = 32767; + if (cd_buffer_temp[0] < -32768) + cd_buffer_temp[0] = -32768; + if (cd_buffer_temp[1] > 32767) + cd_buffer_temp[1] = 32767; + if (cd_buffer_temp[1] < -32768) + cd_buffer_temp[1] = -32768; - cd_out_buffer_int16[c] += (int16_t) cd_buffer_temp[0]; - cd_out_buffer_int16[c+1] += (int16_t) cd_buffer_temp[1]; - } - } - } + cd_out_buffer_int16[c] += (int16_t) cd_buffer_temp[0]; + cd_out_buffer_int16[c + 1] += (int16_t) cd_buffer_temp[1]; + } + } + } -#ifdef USE_OPENAL - if (sound_is_float) - givealbuffer_cd(cd_out_buffer); - else - givealbuffer_cd(cd_out_buffer_int16); -#endif + if (sound_is_float) + givealbuffer_cd(cd_out_buffer); + else + givealbuffer_cd(cd_out_buffer_int16); } } - static void sound_realloc_buffers(void) { if (outbuffer_ex != NULL) { - free(outbuffer_ex); - outbuffer_ex = NULL; + free(outbuffer_ex); + outbuffer_ex = NULL; } if (outbuffer_ex_int16 != NULL) { - free(outbuffer_ex_int16); - outbuffer_ex_int16 = NULL; + free(outbuffer_ex_int16); + outbuffer_ex_int16 = NULL; } if (sound_is_float) { outbuffer_ex = calloc(SOUNDBUFLEN * 2, sizeof(float)); - memset(outbuffer_ex, 0x00, SOUNDBUFLEN * 2 * sizeof(float)); + memset(outbuffer_ex, 0x00, SOUNDBUFLEN * 2 * sizeof(float)); } else { outbuffer_ex_int16 = calloc(SOUNDBUFLEN * 2, sizeof(int16_t)); - memset(outbuffer_ex_int16, 0x00, SOUNDBUFLEN * 2 * sizeof(int16_t)); + memset(outbuffer_ex_int16, 0x00, SOUNDBUFLEN * 2 * sizeof(int16_t)); } } - void sound_init(void) { - int i = 0; int available_cdrom_drives = 0; - outbuffer_ex = NULL; + outbuffer_ex = NULL; outbuffer_ex_int16 = NULL; outbuffer = NULL; outbuffer = calloc(SOUNDBUFLEN * 2, sizeof(int32_t)); memset(outbuffer, 0x00, SOUNDBUFLEN * 2 * sizeof(int32_t)); - for (i = 0; i < CDROM_NUM; i++) { - if (cdrom[i].bus_type != CDROM_BUS_DISABLED) - available_cdrom_drives++; + for (uint8_t i = 0; i < CDROM_NUM; i++) { + if (cdrom[i].bus_type != CDROM_BUS_DISABLED) + available_cdrom_drives++; } if (available_cdrom_drives) { - cdaudioon = 1; + cdaudioon = 1; - sound_cd_start_event = thread_create_event(); + sound_cd_start_event = thread_create_event(); - sound_cd_event = thread_create_event(); - sound_cd_thread_h = thread_create(sound_cd_thread, NULL); + sound_cd_event = thread_create_event(); + sound_cd_thread_h = thread_create(sound_cd_thread, NULL); - sound_log("Waiting for CD start event...\n"); - thread_wait_event(sound_cd_start_event, -1); - thread_reset_event(sound_cd_start_event); - sound_log("Done!\n"); + sound_log("Waiting for CD start event...\n"); + thread_wait_event(sound_cd_start_event, -1); + thread_reset_event(sound_cd_start_event); + sound_log("Done!\n"); } else - cdaudioon = 0; + cdaudioon = 0; cd_thread_enable = available_cdrom_drives ? 1 : 0; } - void -sound_add_handler(void (*get_buffer)(int32_t *buffer, int len, void *p), void *p) +sound_add_handler(void (*get_buffer)(int32_t *buffer, int len, void *priv), void *priv) { sound_handlers[sound_handlers_num].get_buffer = get_buffer; - sound_handlers[sound_handlers_num].priv = p; + sound_handlers[sound_handlers_num].priv = priv; sound_handlers_num++; } - void -sound_set_cd_audio_filter(void (*filter)(int channel, double *buffer, void *p), void *p) +sound_set_cd_audio_filter(void (*filter)(int channel, double *buffer, void *priv), void *priv) { if ((filter_cd_audio == NULL) || (filter == NULL)) { - filter_cd_audio = filter; - filter_cd_audio_p = p; + filter_cd_audio = filter; + filter_cd_audio_p = priv; } } +void +sound_set_pc_speaker_filter(void (*filter)(int channel, double *buffer, void *priv), void *priv) +{ + if ((filter_pc_speaker == NULL) || (filter == NULL)) { + filter_pc_speaker = filter; + filter_pc_speaker_p = priv; + } +} void -sound_poll(void *priv) +sound_poll(UNUSED(void *priv)) { timer_advance_u64(&sound_poll_timer, sound_poll_latch); @@ -444,149 +465,134 @@ sound_poll(void *priv) sound_pos_global++; if (sound_pos_global == SOUNDBUFLEN) { - int c; + int c; - memset(outbuffer, 0x00, SOUNDBUFLEN * 2 * sizeof(int32_t)); + memset(outbuffer, 0x00, SOUNDBUFLEN * 2 * sizeof(int32_t)); - for (c = 0; c < sound_handlers_num; c++) - sound_handlers[c].get_buffer(outbuffer, SOUNDBUFLEN, sound_handlers[c].priv); + for (c = 0; c < sound_handlers_num; c++) + sound_handlers[c].get_buffer(outbuffer, SOUNDBUFLEN, sound_handlers[c].priv); - for (c = 0; c < SOUNDBUFLEN * 2; c++) { - if (sound_is_float) - outbuffer_ex[c] = ((float) outbuffer[c]) / 32768.0; - else { - if (outbuffer[c] > 32767) - outbuffer[c] = 32767; - if (outbuffer[c] < -32768) - outbuffer[c] = -32768; + for (c = 0; c < SOUNDBUFLEN * 2; c++) { + if (sound_is_float) + outbuffer_ex[c] = ((float) outbuffer[c]) / (float) 32768.0; + else { + if (outbuffer[c] > 32767) + outbuffer[c] = 32767; + if (outbuffer[c] < -32768) + outbuffer[c] = -32768; - outbuffer_ex_int16[c] = outbuffer[c]; - } - } + outbuffer_ex_int16[c] = outbuffer[c]; + } + } -#ifdef USE_OPENAL - if (sound_is_float) - givealbuffer(outbuffer_ex); - else - givealbuffer(outbuffer_ex_int16); -#endif + if (sound_is_float) + givealbuffer(outbuffer_ex); + else + givealbuffer(outbuffer_ex_int16); - if (cd_thread_enable) { - cd_buf_update--; - if (!cd_buf_update) { - cd_buf_update = (48000 / SOUNDBUFLEN) / (CD_FREQ / CD_BUFLEN); - thread_set_event(sound_cd_event); - } - } + if (cd_thread_enable) { + cd_buf_update--; + if (!cd_buf_update) { + cd_buf_update = (SOUND_FREQ / SOUNDBUFLEN) / (CD_FREQ / CD_BUFLEN); + thread_set_event(sound_cd_event); + } + } - sound_pos_global = 0; + sound_pos_global = 0; } } - void sound_speed_changed(void) { - sound_poll_latch = (uint64_t)((double)TIMER_USEC * (1000000.0 / 48000.0)); + sound_poll_latch = (uint64_t) ((double) TIMER_USEC * (1000000.0 / (double) SOUND_FREQ)); } - void sound_reset(void) { sound_realloc_buffers(); - midi_device_init(); + midi_out_device_init(); midi_in_device_init(); -#ifdef USE_OPENAL + inital(); -#endif timer_add(&sound_poll_timer, sound_poll, NULL, 1); sound_handlers_num = 0; memset(sound_handlers, 0x00, 8 * sizeof(sound_handler_t)); - filter_cd_audio = NULL; + filter_cd_audio = NULL; filter_cd_audio_p = NULL; - sound_set_cd_volume(65535, 65535); -} + filter_pc_speaker = NULL; + filter_pc_speaker_p = NULL; + sound_set_cd_volume(65535, 65535); + + /* Reset the MPU-401 already loaded flag and the chain of input/output handlers. */ + midi_in_handlers_clear(); +} void sound_card_reset(void) { - /* Reset the MPU-401 already loaded flag and the chain of input/output handlers. */ - midi_in_handlers_clear(); - sound_card_init(); if (mpu401_standalone_enable) - mpu401_device_add(); - - if (GUS) - device_add(&gus_device); - - if (GAMEBLASTER) - device_add(&cms_device); - - if (SSI2001) - device_add(&ssi2001_device); + mpu401_device_add(); } - void sound_cd_thread_end(void) { if (cdaudioon) { - cdaudioon = 0; + cdaudioon = 0; - sound_log("Waiting for CD Audio thread to terminate...\n"); - thread_set_event(sound_cd_event); - thread_wait(sound_cd_thread_h); - sound_log("CD Audio thread terminated...\n"); + sound_log("Waiting for CD Audio thread to terminate...\n"); + thread_set_event(sound_cd_event); + thread_wait(sound_cd_thread_h); + sound_log("CD Audio thread terminated...\n"); - if (sound_cd_event) { - thread_destroy_event(sound_cd_event); - sound_cd_event = NULL; - } + if (sound_cd_event) { + thread_destroy_event(sound_cd_event); + sound_cd_event = NULL; + } - sound_cd_thread_h = NULL; + sound_cd_thread_h = NULL; - if (sound_cd_start_event) { - thread_destroy_event(sound_cd_start_event); - sound_cd_event = NULL; - } + if (sound_cd_start_event) { + thread_destroy_event(sound_cd_start_event); + sound_cd_event = NULL; + } } } - void sound_cd_thread_reset(void) { - int i = 0; int available_cdrom_drives = 0; - for (i = 0; i < CDROM_NUM; i++) { - cdrom_stop(&(cdrom[i])); + for (uint8_t i = 0; i < CDROM_NUM; i++) { + cdrom_stop(&(cdrom[i])); - if (cdrom[i].bus_type != CDROM_BUS_DISABLED) - available_cdrom_drives++; + if (cdrom[i].bus_type != CDROM_BUS_DISABLED) + available_cdrom_drives++; } if (available_cdrom_drives && !cd_thread_enable) { - cdaudioon = 1; + cdaudioon = 1; - sound_cd_start_event = thread_create_event(); + sound_cd_start_event = thread_create_event(); - sound_cd_event = thread_create_event(); - sound_cd_thread_h = thread_create(sound_cd_thread, NULL); + sound_cd_event = thread_create_event(); + sound_cd_thread_h = thread_create(sound_cd_thread, NULL); - thread_wait_event(sound_cd_start_event, -1); - thread_reset_event(sound_cd_start_event); + thread_wait_event(sound_cd_start_event, -1); + thread_reset_event(sound_cd_start_event); } else if (!available_cdrom_drives && cd_thread_enable) - sound_cd_thread_end(); + sound_cd_thread_end(); cd_thread_enable = available_cdrom_drives ? 1 : 0; } diff --git a/src/sound/xaudio2.c b/src/sound/xaudio2.c new file mode 100644 index 000000000..0d9e7d909 --- /dev/null +++ b/src/sound/xaudio2.c @@ -0,0 +1,292 @@ +/* + * 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. + * + * Interface to the XAudio2 audio processing library. + * + * + * + * Authors: Cacodemon345 + * + * Copyright 2022 Cacodemon345. + */ +#include +#include +#include +#include +#include +#include + +#if defined(_WIN32) && !defined(USE_FAUDIO) +# define COBJMACROS +# include +#else +# include +# include +#endif + +#include <86box/86box.h> +#include <86box/midi.h> +#include <86box/plat_dynld.h> +#include <86box/sound.h> +#include <86box/plat_unused.h> + +#if defined(_WIN32) && !defined(USE_FAUDIO) +static void *xaudio2_handle = NULL; +static HRESULT(WINAPI *pXAudio2Create)(IXAudio2 **ppXAudio2, uint32_t Flags, XAUDIO2_PROCESSOR XAudio2Processor); +static dllimp_t xaudio2_imports[] = { + {"XAudio2Create", &pXAudio2Create}, + { NULL, NULL }, +}; +# define XAudio2Create pXAudio2Create +#endif + +static int midi_freq = FREQ_44100; +static int midi_buf_size = 4410; +static int initialized = 0; +static IXAudio2 *xaudio2 = NULL; +static IXAudio2MasteringVoice *mastervoice = NULL; +static IXAudio2SourceVoice *srcvoice = NULL; +static IXAudio2SourceVoice *srcvoicemidi = NULL; +static IXAudio2SourceVoice *srcvoicecd = NULL; + +#define FREQ SOUND_FREQ +#define BUFLEN SOUNDBUFLEN + +static void WINAPI +OnVoiceProcessingPassStart(UNUSED(IXAudio2VoiceCallback *callback), UNUSED(uint32_t bytesRequired)) +{ + // +} +static void WINAPI +OnVoiceProcessingPassEnd(UNUSED(IXAudio2VoiceCallback *callback)) +{ + // +} +static void WINAPI +OnStreamEnd(UNUSED(IXAudio2VoiceCallback *callback)) +{ + // +} +static void WINAPI +OnBufferStart(UNUSED(IXAudio2VoiceCallback *callback), UNUSED(void *pBufferContext)) +{ + // +} +static void WINAPI +OnLoopEnd(UNUSED(IXAudio2VoiceCallback *callback), UNUSED(void *pBufferContext)) +{ + // +} +static void WINAPI +OnVoiceError(UNUSED(IXAudio2VoiceCallback *callback), UNUSED(void *pBufferContext), UNUSED(HRESULT error)) +{ + // +} + +static void WINAPI +OnBufferEnd(UNUSED(IXAudio2VoiceCallback *callback), UNUSED(void *pBufferContext)) +{ + free(pBufferContext); +} + +#if defined(_WIN32) && !defined(USE_FAUDIO) +static IXAudio2VoiceCallbackVtbl callbacksVtbl = +#else +static FAudioVoiceCallback callbacks = +#endif + { + .OnVoiceProcessingPassStart = OnVoiceProcessingPassStart, + .OnVoiceProcessingPassEnd = OnVoiceProcessingPassEnd, + .OnStreamEnd = OnStreamEnd, + .OnBufferStart = OnBufferStart, + .OnBufferEnd = OnBufferEnd, + .OnLoopEnd = OnLoopEnd, + .OnVoiceError = OnVoiceError + }; + +#if defined(_WIN32) && !defined(USE_FAUDIO) +static IXAudio2VoiceCallback callbacks = { &callbacksVtbl }; +#endif + +void +inital(void) +{ +#if defined(_WIN32) && !defined(USE_FAUDIO) + if (xaudio2_handle == NULL) { + xaudio2_handle = dynld_module("xaudio2_9.dll", xaudio2_imports); + } + + if (xaudio2_handle == NULL) { + xaudio2_handle = dynld_module("xaudio2_9redist.dll", xaudio2_imports); + } + + if (xaudio2_handle == NULL) { + return; + } +#endif + + if (XAudio2Create(&xaudio2, 0, XAUDIO2_DEFAULT_PROCESSOR)) { + return; + } + + if (IXAudio2_CreateMasteringVoice(xaudio2, &mastervoice, 2, FREQ, 0, 0, NULL, 0)) { + IXAudio2_Release(xaudio2); + xaudio2 = NULL; + return; + } + + WAVEFORMATEX fmt; + fmt.nChannels = 2; + + if (sound_is_float) { + fmt.wFormatTag = WAVE_FORMAT_IEEE_FLOAT; + fmt.wBitsPerSample = 32; + } else { + fmt.wFormatTag = WAVE_FORMAT_PCM; + fmt.wBitsPerSample = 16; + } + + fmt.nSamplesPerSec = FREQ; + fmt.nBlockAlign = fmt.nChannels * fmt.wBitsPerSample / 8; + fmt.nAvgBytesPerSec = fmt.nSamplesPerSec * fmt.nBlockAlign; + fmt.cbSize = 0; + + if (IXAudio2_CreateSourceVoice(xaudio2, &srcvoice, &fmt, 0, 2.0f, &callbacks, NULL, NULL)) { + IXAudio2MasteringVoice_DestroyVoice(mastervoice); + IXAudio2_Release(xaudio2); + xaudio2 = NULL; + mastervoice = NULL; + return; + } + + fmt.nSamplesPerSec = CD_FREQ; + fmt.nBlockAlign = fmt.nChannels * fmt.wBitsPerSample / 8; + fmt.nAvgBytesPerSec = fmt.nSamplesPerSec * fmt.nBlockAlign; + + IXAudio2_CreateSourceVoice(xaudio2, &srcvoicecd, &fmt, 0, 2.0f, &callbacks, NULL, NULL); + + IXAudio2SourceVoice_SetVolume(srcvoice, 1, XAUDIO2_COMMIT_NOW); + IXAudio2SourceVoice_Start(srcvoice, 0, XAUDIO2_COMMIT_NOW); + IXAudio2SourceVoice_Start(srcvoicecd, 0, XAUDIO2_COMMIT_NOW); + + const char *mdn = midi_out_device_get_internal_name(midi_output_device_current); + + if (strcmp(mdn, "none") && strcmp(mdn, SYSTEM_MIDI_INTERNAL_NAME)) { + fmt.nSamplesPerSec = midi_freq; + fmt.nBlockAlign = fmt.nChannels * fmt.wBitsPerSample / 8; + fmt.nAvgBytesPerSec = fmt.nSamplesPerSec * fmt.nBlockAlign; + IXAudio2_CreateSourceVoice(xaudio2, &srcvoicemidi, &fmt, 0, 2.0f, &callbacks, NULL, NULL); + IXAudio2SourceVoice_Start(srcvoicemidi, 0, XAUDIO2_COMMIT_NOW); + } + + initialized = 1; + atexit(closeal); +} + +void +closeal(void) +{ + if (!initialized) + return; + initialized = 0; + IXAudio2SourceVoice_Stop(srcvoice, 0, XAUDIO2_COMMIT_NOW); + IXAudio2SourceVoice_FlushSourceBuffers(srcvoice); + IXAudio2SourceVoice_Stop(srcvoicecd, 0, XAUDIO2_COMMIT_NOW); + IXAudio2SourceVoice_FlushSourceBuffers(srcvoicecd); + if (srcvoicemidi) { + IXAudio2SourceVoice_Stop(srcvoicemidi, 0, XAUDIO2_COMMIT_NOW); + IXAudio2SourceVoice_FlushSourceBuffers(srcvoicemidi); + IXAudio2SourceVoice_DestroyVoice(srcvoicemidi); + } + IXAudio2SourceVoice_DestroyVoice(srcvoice); + IXAudio2SourceVoice_DestroyVoice(srcvoicecd); + IXAudio2MasteringVoice_DestroyVoice(mastervoice); + IXAudio2_Release(xaudio2); + srcvoice = srcvoicecd = srcvoicemidi = NULL; + mastervoice = NULL; + xaudio2 = NULL; + +#if defined(_WIN32) && !defined(USE_FAUDIO) + dynld_close(xaudio2_handle); + xaudio2_handle = NULL; +#endif +} + +void +givealbuffer_common(void *buf, IXAudio2SourceVoice *sourcevoice, size_t buflen) +{ + if (!initialized) + return; + + IXAudio2MasteringVoice_SetVolume(mastervoice, pow(10.0, (double) sound_gain / 20.0), XAUDIO2_COMMIT_NOW); + XAUDIO2_BUFFER buffer = { 0 }; + buffer.Flags = 0; + if (sound_is_float) { + buffer.pAudioData = calloc(buflen, sizeof(float)); + buffer.AudioBytes = buflen * sizeof(float); + } else { + buffer.pAudioData = calloc(buflen, sizeof(int16_t)); + buffer.AudioBytes = buflen * sizeof(int16_t); + } + if (buffer.pAudioData == NULL) { + fatal("xaudio2: Out Of Memory!"); + } + memcpy((void *) buffer.pAudioData, buf, buffer.AudioBytes); + buffer.PlayBegin = buffer.PlayLength = 0; + buffer.PlayLength = buflen >> 1; + buffer.pContext = (void *) buffer.pAudioData; + IXAudio2SourceVoice_SubmitSourceBuffer(sourcevoice, &buffer, NULL); +} + +void +givealbuffer(void *buf) +{ + givealbuffer_common(buf, srcvoice, BUFLEN << 1); +} + +void +givealbuffer_cd(void *buf) +{ + if (srcvoicecd) + givealbuffer_common(buf, srcvoicecd, CD_BUFLEN << 1); +} + +void +al_set_midi(int freq, int buf_size) +{ + midi_freq = freq; + midi_buf_size = buf_size; + + if (initialized && srcvoicemidi) { + IXAudio2SourceVoice_Stop(srcvoicemidi, 0, XAUDIO2_COMMIT_NOW); + IXAudio2SourceVoice_FlushSourceBuffers(srcvoicemidi); + IXAudio2SourceVoice_DestroyVoice(srcvoicemidi); + srcvoicemidi = NULL; + WAVEFORMATEX fmt; + fmt.nChannels = 2; + if (sound_is_float) { + fmt.wFormatTag = WAVE_FORMAT_IEEE_FLOAT; + fmt.wBitsPerSample = 32; + } else { + fmt.wFormatTag = WAVE_FORMAT_PCM; + fmt.wBitsPerSample = 16; + } + fmt.nSamplesPerSec = midi_freq; + fmt.nBlockAlign = fmt.nChannels * fmt.wBitsPerSample / 8; + fmt.nAvgBytesPerSec = fmt.nSamplesPerSec * fmt.nBlockAlign; + fmt.cbSize = 0; + IXAudio2_CreateSourceVoice(xaudio2, &srcvoicemidi, &fmt, 0, 2.0f, &callbacks, NULL, NULL); + IXAudio2SourceVoice_Start(srcvoicemidi, 0, XAUDIO2_COMMIT_NOW); + } +} + +void +givealbuffer_midi(void *buf, uint32_t size) +{ + givealbuffer_common(buf, srcvoicemidi, size); +} diff --git a/src/sound/ymfm/CMakeLists.txt b/src/sound/ymfm/CMakeLists.txt new file mode 100644 index 000000000..e1ff35369 --- /dev/null +++ b/src/sound/ymfm/CMakeLists.txt @@ -0,0 +1,12 @@ +# +# 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. +# + +add_library(ymfm STATIC ymfm_misc.cpp ymfm_opl.cpp ymfm_opm.cpp ymfm_opn.cpp ymfm_opq.cpp ymfm_opz.cpp ymfm_pcm.cpp ymfm_adpcm.cpp) \ No newline at end of file diff --git a/src/sound/ymfm/ymfm.h b/src/sound/ymfm/ymfm.h new file mode 100644 index 000000000..4f8ba1243 --- /dev/null +++ b/src/sound/ymfm/ymfm.h @@ -0,0 +1,575 @@ +// BSD 3-Clause License +// +// Copyright (c) 2021, Aaron Giles +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// 1. Redistributions of source code must retain the above copyright notice, this +// list of conditions and the following disclaimer. +// +// 2. Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// 3. Neither the name of the copyright holder nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#ifndef YMFM_H +#define YMFM_H + +#pragma once + +#if defined(_MSC_VER) && !defined(_CRT_SECURE_NO_WARNINGS) + #define _CRT_SECURE_NO_WARNINGS +#endif + +#include +#include +#include +#include +#include +#include +#include +#include + +#define SNPRINTF_BUFFER_SIZE_CALC (256 - (end - &buffer[0])) + +namespace ymfm +{ + +//********************************************************* +// DEBUGGING +//********************************************************* + +class debug +{ +public: + // masks to help isolate specific channels + static constexpr uint32_t GLOBAL_FM_CHANNEL_MASK = 0xffffffff; + static constexpr uint32_t GLOBAL_ADPCM_A_CHANNEL_MASK = 0xffffffff; + static constexpr uint32_t GLOBAL_ADPCM_B_CHANNEL_MASK = 0xffffffff; + static constexpr uint32_t GLOBAL_PCM_CHANNEL_MASK = 0xffffffff; + + // types of logging + static constexpr bool LOG_FM_WRITES = false; + static constexpr bool LOG_KEYON_EVENTS = false; + static constexpr bool LOG_UNEXPECTED_READ_WRITES = false; + + // helpers to write based on the log type + template static void log_fm_write(Params &&... args) { if (LOG_FM_WRITES) log(args...); } + template static void log_keyon(Params &&... args) { if (LOG_KEYON_EVENTS) log(args...); } + template static void log_unexpected_read_write(Params &&... args) { if (LOG_UNEXPECTED_READ_WRITES) log(args...); } + + // downstream helper to output log data; defaults to printf + template static void log(Params &&... args) { printf(args...); } +}; + + + +//********************************************************* +// GLOBAL HELPERS +//********************************************************* + +//------------------------------------------------- +// bitfield - extract a bitfield from the given +// value, starting at bit 'start' for a length of +// 'length' bits +//------------------------------------------------- + +inline uint32_t bitfield(uint32_t value, int start, int length = 1) +{ + return (value >> start) & ((1 << length) - 1); +} + + +//------------------------------------------------- +// clamp - clamp between the minimum and maximum +// values provided +//------------------------------------------------- + +inline int32_t clamp(int32_t value, int32_t minval, int32_t maxval) +{ + if (value < minval) + return minval; + if (value > maxval) + return maxval; + return value; +} + + +//------------------------------------------------- +// array_size - return the size of an array +//------------------------------------------------- + +template +constexpr uint32_t array_size(ArrayType (&array)[ArraySize]) +{ + return ArraySize; +} + + +//------------------------------------------------- +// count_leading_zeros - return the number of +// leading zeros in a 32-bit value; CPU-optimized +// versions for various architectures are included +// below +//------------------------------------------------- + +#if defined(__GNUC__) + +inline uint8_t count_leading_zeros(uint32_t value) +{ + if (value == 0) + return 32; + return __builtin_clz(value); +} + +#elif defined(_MSC_VER) + +inline uint8_t count_leading_zeros(uint32_t value) +{ + unsigned long index; + return _BitScanReverse(&index, value) ? uint8_t(31U - index) : 32U; +} + +#else + +inline uint8_t count_leading_zeros(uint32_t value) +{ + if (value == 0) + return 32; + uint8_t count; + for (count = 0; int32_t(value) >= 0; count++) + value <<= 1; + return count; +} + +#endif + + +// Many of the Yamaha FM chips emit a floating-point value, which is sent to +// a DAC for processing. The exact format of this floating-point value is +// documented below. This description only makes sense if the "internal" +// format treats sign as 1=positive and 0=negative, so the helpers below +// presume that. +// +// Internal OPx data 16-bit signed data Exp Sign Mantissa +// ================= ================= === ==== ======== +// 1 1xxxxxxxx------ -> 0 1xxxxxxxx------ -> 111 1 1xxxxxxx +// 1 01xxxxxxxx----- -> 0 01xxxxxxxx----- -> 110 1 1xxxxxxx +// 1 001xxxxxxxx---- -> 0 001xxxxxxxx---- -> 101 1 1xxxxxxx +// 1 0001xxxxxxxx--- -> 0 0001xxxxxxxx--- -> 100 1 1xxxxxxx +// 1 00001xxxxxxxx-- -> 0 00001xxxxxxxx-- -> 011 1 1xxxxxxx +// 1 000001xxxxxxxx- -> 0 000001xxxxxxxx- -> 010 1 1xxxxxxx +// 1 000000xxxxxxxxx -> 0 000000xxxxxxxxx -> 001 1 xxxxxxxx +// 0 111111xxxxxxxxx -> 1 111111xxxxxxxxx -> 001 0 xxxxxxxx +// 0 111110xxxxxxxx- -> 1 111110xxxxxxxx- -> 010 0 0xxxxxxx +// 0 11110xxxxxxxx-- -> 1 11110xxxxxxxx-- -> 011 0 0xxxxxxx +// 0 1110xxxxxxxx--- -> 1 1110xxxxxxxx--- -> 100 0 0xxxxxxx +// 0 110xxxxxxxx---- -> 1 110xxxxxxxx---- -> 101 0 0xxxxxxx +// 0 10xxxxxxxx----- -> 1 10xxxxxxxx----- -> 110 0 0xxxxxxx +// 0 0xxxxxxxx------ -> 1 0xxxxxxxx------ -> 111 0 0xxxxxxx + +//------------------------------------------------- +// encode_fp - given a 32-bit signed input value +// convert it to a signed 3.10 floating-point +// value +//------------------------------------------------- + +inline int16_t encode_fp(int32_t value) +{ + // handle overflows first + if (value < -32768) + return (7 << 10) | 0x000; + if (value > 32767) + return (7 << 10) | 0x3ff; + + // we need to count the number of leading sign bits after the sign + // we can use count_leading_zeros if we invert negative values + int32_t scanvalue = value ^ (int32_t(value) >> 31); + + // exponent is related to the number of leading bits starting from bit 14 + int exponent = 7 - count_leading_zeros(scanvalue << 17); + + // smallest exponent value allowed is 1 + exponent = std::max(exponent, 1); + + // mantissa + int32_t mantissa = value >> (exponent - 1); + + // assemble into final form, inverting the sign + return ((exponent << 10) | (mantissa & 0x3ff)) ^ 0x200; +} + + +//------------------------------------------------- +// decode_fp - given a 3.10 floating-point value, +// convert it to a signed 16-bit value +//------------------------------------------------- + +inline int16_t decode_fp(int16_t value) +{ + // invert the sign and the exponent + value ^= 0x1e00; + + // shift mantissa up to 16 bits then apply inverted exponent + return int16_t(value << 6) >> bitfield(value, 10, 3); +} + + +//------------------------------------------------- +// roundtrip_fp - compute the result of a round +// trip through the encode/decode process above +//------------------------------------------------- + +inline int16_t roundtrip_fp(int32_t value) +{ + // handle overflows first + if (value < -32768) + return -32768; + if (value > 32767) + return 32767; + + // we need to count the number of leading sign bits after the sign + // we can use count_leading_zeros if we invert negative values + int32_t scanvalue = value ^ (int32_t(value) >> 31); + + // exponent is related to the number of leading bits starting from bit 14 + int exponent = 7 - count_leading_zeros(scanvalue << 17); + + // smallest exponent value allowed is 1 + exponent = std::max(exponent, 1); + + // apply the shift back and forth to zero out bits that are lost + exponent -= 1; + return (value >> exponent) << exponent; +} + + + +//********************************************************* +// HELPER CLASSES +//********************************************************* + +// various envelope states +enum envelope_state : uint32_t +{ + EG_DEPRESS = 0, // OPLL only; set EG_HAS_DEPRESS to enable + EG_ATTACK = 1, + EG_DECAY = 2, + EG_SUSTAIN = 3, + EG_RELEASE = 4, + EG_REVERB = 5, // OPQ/OPZ only; set EG_HAS_REVERB to enable + EG_STATES = 6 +}; + +// external I/O access classes +enum access_class : uint32_t +{ + ACCESS_IO = 0, + ACCESS_ADPCM_A, + ACCESS_ADPCM_B, + ACCESS_PCM, + ACCESS_CLASSES +}; + + + +//********************************************************* +// HELPER CLASSES +//********************************************************* + +// ======================> ymfm_output + +// struct containing an array of output values +template +struct ymfm_output +{ + // clear all outputs to 0 + ymfm_output &clear() + { + for (uint32_t index = 0; index < NumOutputs; index++) + data[index] = 0; + return *this; + } + + // clamp all outputs to a 16-bit signed value + ymfm_output &clamp16() + { + for (uint32_t index = 0; index < NumOutputs; index++) + data[index] = clamp(data[index], -32768, 32767); + return *this; + } + + // run each output value through the floating-point processor + ymfm_output &roundtrip_fp() + { + for (uint32_t index = 0; index < NumOutputs; index++) + data[index] = ymfm::roundtrip_fp(data[index]); + return *this; + } + + // internal state + int32_t data[NumOutputs]; +}; + + +// ======================> ymfm_wavfile + +// this class is a debugging helper that accumulates data and writes it to wav files +template +class ymfm_wavfile +{ +public: + // construction + ymfm_wavfile(uint32_t samplerate = 44100) : + m_samplerate(samplerate) + { + } + + // configuration + ymfm_wavfile &set_index(uint32_t index) { m_index = index; return *this; } + ymfm_wavfile &set_samplerate(uint32_t samplerate) { m_samplerate = samplerate; return *this; } + + // destruction + ~ymfm_wavfile() + { + if (!m_buffer.empty()) + { + // create file + char name[20]; + snprintf(name, sizeof(name), "wavlog-%02d.wav", m_index); + FILE *out = fopen(name, "wb"); + + // make the wav file header + uint8_t header[44]; + memcpy(&header[0], "RIFF", 4); + *(uint32_t *)&header[4] = m_buffer.size() * 2 + 44 - 8; + memcpy(&header[8], "WAVE", 4); + memcpy(&header[12], "fmt ", 4); + *(uint32_t *)&header[16] = 16; + *(uint16_t *)&header[20] = 1; + *(uint16_t *)&header[22] = Channels; + *(uint32_t *)&header[24] = m_samplerate; + *(uint32_t *)&header[28] = m_samplerate * 2 * Channels; + *(uint16_t *)&header[32] = 2 * Channels; + *(uint16_t *)&header[34] = 16; + memcpy(&header[36], "data", 4); + *(uint32_t *)&header[40] = m_buffer.size() * 2 + 44 - 44; + + // write header then data + fwrite(&header[0], 1, sizeof(header), out); + fwrite(&m_buffer[0], 2, m_buffer.size(), out); + fclose(out); + } + } + + // add data to the file + template + void add(ymfm_output output) + { + int16_t sum[Channels] = { 0 }; + for (int index = 0; index < Outputs; index++) + sum[index % Channels] += output.data[index]; + for (int index = 0; index < Channels; index++) + m_buffer.push_back(sum[index]); + } + + // add data to the file, using a reference + template + void add(ymfm_output output, ymfm_output const &ref) + { + int16_t sum[Channels] = { 0 }; + for (int index = 0; index < Outputs; index++) + sum[index % Channels] += output.data[index] - ref.data[index]; + for (int index = 0; index < Channels; index++) + m_buffer.push_back(sum[index]); + } + +private: + // internal state + uint32_t m_index; + uint32_t m_samplerate; + std::vector m_buffer; +}; + + +// ======================> ymfm_saved_state + +// this class contains a managed vector of bytes that is used to save and +// restore state +class ymfm_saved_state +{ +public: + // construction + ymfm_saved_state(std::vector &buffer, bool saving) : + m_buffer(buffer), + m_offset(saving ? -1 : 0) + { + if (saving) + buffer.resize(0); + } + + // are we saving or restoring? + bool saving() const { return (m_offset < 0); } + + // generic save/restore + template + void save_restore(DataType &data) + { + if (saving()) + save(data); + else + restore(data); + } + +public: + // save data to the buffer + void save(bool &data) { write(data ? 1 : 0); } + void save(int8_t &data) { write(data); } + void save(uint8_t &data) { write(data); } + void save(int16_t &data) { write(uint8_t(data)).write(data >> 8); } + void save(uint16_t &data) { write(uint8_t(data)).write(data >> 8); } + void save(int32_t &data) { write(data).write(data >> 8).write(data >> 16).write(data >> 24); } + void save(uint32_t &data) { write(data).write(data >> 8).write(data >> 16).write(data >> 24); } + void save(envelope_state &data) { write(uint8_t(data)); } + template + void save(DataType (&data)[Count]) { for (uint32_t index = 0; index < Count; index++) save(data[index]); } + + // restore data from the buffer + void restore(bool &data) { data = read() ? true : false; } + void restore(int8_t &data) { data = read(); } + void restore(uint8_t &data) { data = read(); } + void restore(int16_t &data) { data = read(); data |= read() << 8; } + void restore(uint16_t &data) { data = read(); data |= read() << 8; } + void restore(int32_t &data) { data = read(); data |= read() << 8; data |= read() << 16; data |= read() << 24; } + void restore(uint32_t &data) { data = read(); data |= read() << 8; data |= read() << 16; data |= read() << 24; } + void restore(envelope_state &data) { data = envelope_state(read()); } + template + void restore(DataType (&data)[Count]) { for (uint32_t index = 0; index < Count; index++) restore(data[index]); } + + // internal helper + ymfm_saved_state &write(uint8_t data) { m_buffer.push_back(data); return *this; } + uint8_t read() { return (m_offset < int32_t(m_buffer.size())) ? m_buffer[m_offset++] : 0; } + + // internal state + std::vector &m_buffer; + int32_t m_offset; +}; + + + +//********************************************************* +// INTERFACE CLASSES +//********************************************************* + +// ======================> ymfm_engine_callbacks + +// this class represents functions in the engine that the ymfm_interface +// needs to be able to call; it is represented here as a separate interface +// that is independent of the actual engine implementation +class ymfm_engine_callbacks +{ +public: + // timer callback; called by the interface when a timer fires + virtual void engine_timer_expired(uint32_t tnum) = 0; + + // check interrupts; called by the interface after synchronization + virtual void engine_check_interrupts() = 0; + + // mode register write; called by the interface after synchronization + virtual void engine_mode_write(uint8_t data) = 0; +}; + + +// ======================> ymfm_interface + +// this class represents the interface between the fm_engine and the outside +// world; it provides hooks for timers, synchronization, and I/O +class ymfm_interface +{ + // the engine is our friend + template friend class fm_engine_base; + +public: + // the following functions must be implemented by any derived classes; the + // default implementations are sufficient for some minimal operation, but will + // likely need to be overridden to integrate with the outside world; they are + // all prefixed with ymfm_ to reduce the likelihood of namespace collisions + + // + // timing and synchronizaton + // + + // the chip implementation calls this when a write happens to the mode + // register, which could affect timers and interrupts; our responsibility + // is to ensure the system is up to date before calling the engine's + // engine_mode_write() method + virtual void ymfm_sync_mode_write(uint8_t data) { m_engine->engine_mode_write(data); } + + // the chip implementation calls this when the chip's status has changed, + // which may affect the interrupt state; our responsibility is to ensure + // the system is up to date before calling the engine's + // engine_check_interrupts() method + virtual void ymfm_sync_check_interrupts() { m_engine->engine_check_interrupts(); } + + // the chip implementation calls this when one of the two internal timers + // has changed state; our responsibility is to arrange to call the engine's + // engine_timer_expired() method after the provided number of clocks; if + // duration_in_clocks is negative, we should cancel any outstanding timers + virtual void ymfm_set_timer(uint32_t tnum, int32_t duration_in_clocks) { } + + // the chip implementation calls this to indicate that the chip should be + // considered in a busy state until the given number of clocks has passed; + // our responsibility is to compute and remember the ending time based on + // the chip's clock for later checking + virtual void ymfm_set_busy_end(uint32_t clocks) { } + + // the chip implementation calls this to see if the chip is still currently + // is a busy state, as specified by a previous call to ymfm_set_busy_end(); + // our responsibility is to compare the current time against the previously + // noted busy end time and return true if we haven't yet passed it + virtual bool ymfm_is_busy() { return false; } + + virtual uint32_t get_special_flags(void) { return 0x0000; } + + // + // I/O functions + // + + // the chip implementation calls this when the state of the IRQ signal has + // changed due to a status change; our responsibility is to respond as + // needed to the change in IRQ state, signaling any consumers + virtual void ymfm_update_irq(bool asserted) { } + + // the chip implementation calls this whenever data is read from outside + // of the chip; our responsibility is to provide the data requested + virtual uint8_t ymfm_external_read(access_class type, uint32_t address) { return 0; } + + // the chip implementation calls this whenever data is written outside + // of the chip; our responsibility is to pass the written data on to any consumers + virtual void ymfm_external_write(access_class type, uint32_t address, uint8_t data) { } + +protected: + // pointer to engine callbacks -- this is set directly by the engine at + // construction time + ymfm_engine_callbacks *m_engine; +}; + +} + +#endif // YMFM_H diff --git a/src/sound/ymfm/ymfm_adpcm.cpp b/src/sound/ymfm/ymfm_adpcm.cpp new file mode 100644 index 000000000..4bc22beb2 --- /dev/null +++ b/src/sound/ymfm/ymfm_adpcm.cpp @@ -0,0 +1,807 @@ +// BSD 3-Clause License +// +// Copyright (c) 2021, Aaron Giles +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// 1. Redistributions of source code must retain the above copyright notice, this +// list of conditions and the following disclaimer. +// +// 2. Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// 3. Neither the name of the copyright holder nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#include "ymfm_adpcm.h" + +namespace ymfm +{ + +//********************************************************* +// ADPCM "A" REGISTERS +//********************************************************* + +//------------------------------------------------- +// reset - reset the register state +//------------------------------------------------- + +void adpcm_a_registers::reset() +{ + std::fill_n(&m_regdata[0], REGISTERS, 0); + + // initialize the pans to on by default, and max instrument volume; + // some neogeo homebrews (for example ffeast) rely on this + m_regdata[0x08] = m_regdata[0x09] = m_regdata[0x0a] = + m_regdata[0x0b] = m_regdata[0x0c] = m_regdata[0x0d] = 0xdf; +} + + +//------------------------------------------------- +// save_restore - save or restore the data +//------------------------------------------------- + +void adpcm_a_registers::save_restore(ymfm_saved_state &state) +{ + state.save_restore(m_regdata); +} + + +//********************************************************* +// ADPCM "A" CHANNEL +//********************************************************* + +//------------------------------------------------- +// adpcm_a_channel - constructor +//------------------------------------------------- + +adpcm_a_channel::adpcm_a_channel(adpcm_a_engine &owner, uint32_t choffs, uint32_t addrshift) : + m_choffs(choffs), + m_address_shift(addrshift), + m_playing(0), + m_curnibble(0), + m_curbyte(0), + m_curaddress(0), + m_accumulator(0), + m_step_index(0), + m_regs(owner.regs()), + m_owner(owner) +{ +} + + +//------------------------------------------------- +// reset - reset the channel state +//------------------------------------------------- + +void adpcm_a_channel::reset() +{ + m_playing = 0; + m_curnibble = 0; + m_curbyte = 0; + m_curaddress = 0; + m_accumulator = 0; + m_step_index = 0; +} + + +//------------------------------------------------- +// save_restore - save or restore the data +//------------------------------------------------- + +void adpcm_a_channel::save_restore(ymfm_saved_state &state) +{ + state.save_restore(m_playing); + state.save_restore(m_curnibble); + state.save_restore(m_curbyte); + state.save_restore(m_curaddress); + state.save_restore(m_accumulator); + state.save_restore(m_step_index); +} + + +//------------------------------------------------- +// keyonoff - signal key on/off +//------------------------------------------------- + +void adpcm_a_channel::keyonoff(bool on) +{ + // QUESTION: repeated key ons restart the sample? + m_playing = on; + if (m_playing) + { + m_curaddress = m_regs.ch_start(m_choffs) << m_address_shift; + m_curnibble = 0; + m_curbyte = 0; + m_accumulator = 0; + m_step_index = 0; + + // don't log masked channels + if (((debug::GLOBAL_ADPCM_A_CHANNEL_MASK >> m_choffs) & 1) != 0) + debug::log_keyon("KeyOn ADPCM-A%d: pan=%d%d start=%04X end=%04X level=%02X\n", + m_choffs, + m_regs.ch_pan_left(m_choffs), + m_regs.ch_pan_right(m_choffs), + m_regs.ch_start(m_choffs), + m_regs.ch_end(m_choffs), + m_regs.ch_instrument_level(m_choffs)); + } +} + + +//------------------------------------------------- +// clock - master clocking function +//------------------------------------------------- + +bool adpcm_a_channel::clock() +{ + // if not playing, just output 0 + if (m_playing == 0) + { + m_accumulator = 0; + return false; + } + + // if we're about to read nibble 0, fetch the data + uint8_t data; + if (m_curnibble == 0) + { + // stop when we hit the end address; apparently only low 20 bits are used for + // comparison on the YM2610: this affects sample playback in some games, for + // example twinspri character select screen music will skip some samples if + // this is not correct + // + // note also: end address is inclusive, so wait until we are about to fetch + // the sample just after the end before stopping; this is needed for nitd's + // jump sound, for example + uint32_t end = (m_regs.ch_end(m_choffs) + 1) << m_address_shift; + if (((m_curaddress ^ end) & 0xfffff) == 0) + { + m_playing = m_accumulator = 0; + return true; + } + + m_curbyte = m_owner.intf().ymfm_external_read(ACCESS_ADPCM_A, m_curaddress++); + data = m_curbyte >> 4; + m_curnibble = 1; + } + + // otherwise just extract from the previosuly-fetched byte + else + { + data = m_curbyte & 0xf; + m_curnibble = 0; + } + + // compute the ADPCM delta + static uint16_t const s_steps[49] = + { + 16, 17, 19, 21, 23, 25, 28, + 31, 34, 37, 41, 45, 50, 55, + 60, 66, 73, 80, 88, 97, 107, + 118, 130, 143, 157, 173, 190, 209, + 230, 253, 279, 307, 337, 371, 408, + 449, 494, 544, 598, 658, 724, 796, + 876, 963, 1060, 1166, 1282, 1411, 1552 + }; + int32_t delta = (2 * bitfield(data, 0, 3) + 1) * s_steps[m_step_index] / 8; + if (bitfield(data, 3)) + delta = -delta; + + // the 12-bit accumulator wraps on the ym2610 and ym2608 (like the msm5205) + m_accumulator = (m_accumulator + delta) & 0xfff; + + // adjust ADPCM step + static int8_t const s_step_inc[8] = { -1, -1, -1, -1, 2, 5, 7, 9 }; + m_step_index = clamp(m_step_index + s_step_inc[bitfield(data, 0, 3)], 0, 48); + + return false; +} + + +//------------------------------------------------- +// output - return the computed output value, with +// panning applied +//------------------------------------------------- + +template +void adpcm_a_channel::output(ymfm_output &output) const +{ + // volume combines instrument and total levels + int vol = (m_regs.ch_instrument_level(m_choffs) ^ 0x1f) + (m_regs.total_level() ^ 0x3f); + + // if combined is maximum, don't add to outputs + if (vol >= 63) + return; + + // convert into a shift and a multiplier + // QUESTION: verify this from other sources + int8_t mul = 15 - (vol & 7); + uint8_t shift = 4 + 1 + (vol >> 3); + + // m_accumulator is a 12-bit value; shift up to sign-extend; + // the downshift is incorporated into 'shift' + int16_t value = ((int16_t(m_accumulator << 4) * mul) >> shift) & ~3; + + // apply to left/right as appropriate + if (NumOutputs == 1 || m_regs.ch_pan_left(m_choffs)) + output.data[0] += value; + if (NumOutputs > 1 && m_regs.ch_pan_right(m_choffs)) + output.data[1] += value; +} + + + +//********************************************************* +// ADPCM "A" ENGINE +//********************************************************* + +//------------------------------------------------- +// adpcm_a_engine - constructor +//------------------------------------------------- + +adpcm_a_engine::adpcm_a_engine(ymfm_interface &intf, uint32_t addrshift) : + m_intf(intf) +{ + // create the channels + for (int chnum = 0; chnum < CHANNELS; chnum++) + m_channel[chnum] = std::make_unique(*this, chnum, addrshift); +} + + +//------------------------------------------------- +// reset - reset the engine state +//------------------------------------------------- + +void adpcm_a_engine::reset() +{ + // reset register state + m_regs.reset(); + + // reset each channel + for (auto &chan : m_channel) + chan->reset(); +} + + +//------------------------------------------------- +// save_restore - save or restore the data +//------------------------------------------------- + +void adpcm_a_engine::save_restore(ymfm_saved_state &state) +{ + // save register state + m_regs.save_restore(state); + + // save channel state + for (int chnum = 0; chnum < CHANNELS; chnum++) + m_channel[chnum]->save_restore(state); +} + + +//------------------------------------------------- +// clock - master clocking function +//------------------------------------------------- + +uint32_t adpcm_a_engine::clock(uint32_t chanmask) +{ + // clock each channel, setting a bit in result if it finished + uint32_t result = 0; + for (int chnum = 0; chnum < CHANNELS; chnum++) + if (bitfield(chanmask, chnum)) + if (m_channel[chnum]->clock()) + result |= 1 << chnum; + + // return the bitmask of completed samples + return result; +} + + +//------------------------------------------------- +// update - master update function +//------------------------------------------------- + +template +void adpcm_a_engine::output(ymfm_output &output, uint32_t chanmask) +{ + // mask out some channels for debug purposes + chanmask &= debug::GLOBAL_ADPCM_A_CHANNEL_MASK; + + // compute the output of each channel + for (int chnum = 0; chnum < CHANNELS; chnum++) + if (bitfield(chanmask, chnum)) + m_channel[chnum]->output(output); +} + +template void adpcm_a_engine::output<1>(ymfm_output<1> &output, uint32_t chanmask); +template void adpcm_a_engine::output<2>(ymfm_output<2> &output, uint32_t chanmask); + + +//------------------------------------------------- +// write - handle writes to the ADPCM-A registers +//------------------------------------------------- + +void adpcm_a_engine::write(uint32_t regnum, uint8_t data) +{ + // store the raw value to the register array; + // most writes are passive, consumed only when needed + m_regs.write(regnum, data); + + // actively handle writes to the control register + if (regnum == 0x00) + for (int chnum = 0; chnum < CHANNELS; chnum++) + if (bitfield(data, chnum)) + m_channel[chnum]->keyonoff(bitfield(~data, 7)); +} + + + +//********************************************************* +// ADPCM "B" REGISTERS +//********************************************************* + +//------------------------------------------------- +// reset - reset the register state +//------------------------------------------------- + +void adpcm_b_registers::reset() +{ + std::fill_n(&m_regdata[0], REGISTERS, 0); + + // default limit to wide open + m_regdata[0x0c] = m_regdata[0x0d] = 0xff; +} + + +//------------------------------------------------- +// save_restore - save or restore the data +//------------------------------------------------- + +void adpcm_b_registers::save_restore(ymfm_saved_state &state) +{ + state.save_restore(m_regdata); +} + + + +//********************************************************* +// ADPCM "B" CHANNEL +//********************************************************* + +//------------------------------------------------- +// adpcm_b_channel - constructor +//------------------------------------------------- + +adpcm_b_channel::adpcm_b_channel(adpcm_b_engine &owner, uint32_t addrshift) : + m_address_shift(addrshift), + m_status(STATUS_BRDY), + m_curnibble(0), + m_curbyte(0), + m_dummy_read(0), + m_position(0), + m_curaddress(0), + m_accumulator(0), + m_prev_accum(0), + m_adpcm_step(STEP_MIN), + m_regs(owner.regs()), + m_owner(owner) +{ +} + + +//------------------------------------------------- +// reset - reset the channel state +//------------------------------------------------- + +void adpcm_b_channel::reset() +{ + m_status = STATUS_BRDY; + m_curnibble = 0; + m_curbyte = 0; + m_dummy_read = 0; + m_position = 0; + m_curaddress = 0; + m_accumulator = 0; + m_prev_accum = 0; + m_adpcm_step = STEP_MIN; +} + + +//------------------------------------------------- +// save_restore - save or restore the data +//------------------------------------------------- + +void adpcm_b_channel::save_restore(ymfm_saved_state &state) +{ + state.save_restore(m_status); + state.save_restore(m_curnibble); + state.save_restore(m_curbyte); + state.save_restore(m_dummy_read); + state.save_restore(m_position); + state.save_restore(m_curaddress); + state.save_restore(m_accumulator); + state.save_restore(m_prev_accum); + state.save_restore(m_adpcm_step); +} + + +//------------------------------------------------- +// clock - master clocking function +//------------------------------------------------- + +void adpcm_b_channel::clock() +{ + // only process if active and not recording (which we don't support) + if (!m_regs.execute() || m_regs.record() || (m_status & STATUS_PLAYING) == 0) + { + m_status &= ~STATUS_PLAYING; + return; + } + + // otherwise, advance the step + uint32_t position = m_position + m_regs.delta_n(); + m_position = uint16_t(position); + if (position < 0x10000) + return; + + // if we're about to process nibble 0, fetch sample + if (m_curnibble == 0) + { + // playing from RAM/ROM + if (m_regs.external()) + m_curbyte = m_owner.intf().ymfm_external_read(ACCESS_ADPCM_B, m_curaddress); + } + + // extract the nibble from our current byte + uint8_t data = uint8_t(m_curbyte << (4 * m_curnibble)) >> 4; + m_curnibble ^= 1; + + // we just processed the last nibble + if (m_curnibble == 0) + { + // if playing from RAM/ROM, check the end/limit address or advance + if (m_regs.external()) + { + // handle the sample end, either repeating or stopping + if (at_end()) + { + // if repeating, go back to the start + if (m_regs.repeat()) + load_start(); + + // otherwise, done; set the EOS bit + else + { + m_accumulator = 0; + m_prev_accum = 0; + m_status = (m_status & ~STATUS_PLAYING) | STATUS_EOS; + debug::log_keyon("%s\n", "ADPCM EOS"); + return; + } + } + + // wrap at the limit address + else if (at_limit()) + m_curaddress = 0; + + // otherwise, advance the current address + else + { + m_curaddress++; + m_curaddress &= 0xffffff; + } + } + + // if CPU-driven, copy the next byte and request more + else + { + m_curbyte = m_regs.cpudata(); + m_status |= STATUS_BRDY; + } + } + + // remember previous value for interpolation + m_prev_accum = m_accumulator; + + // forecast to next forecast: 1/8, 3/8, 5/8, 7/8, 9/8, 11/8, 13/8, 15/8 + int32_t delta = (2 * bitfield(data, 0, 3) + 1) * m_adpcm_step / 8; + if (bitfield(data, 3)) + delta = -delta; + + // add and clamp to 16 bits + m_accumulator = clamp(m_accumulator + delta, -32768, 32767); + + // scale the ADPCM step: 0.9, 0.9, 0.9, 0.9, 1.2, 1.6, 2.0, 2.4 + static uint8_t const s_step_scale[8] = { 57, 57, 57, 57, 77, 102, 128, 153 }; + m_adpcm_step = clamp((m_adpcm_step * s_step_scale[bitfield(data, 0, 3)]) / 64, STEP_MIN, STEP_MAX); +} + + +//------------------------------------------------- +// output - return the computed output value, with +// panning applied +//------------------------------------------------- + +template +void adpcm_b_channel::output(ymfm_output &output, uint32_t rshift) const +{ + // mask out some channels for debug purposes + if ((debug::GLOBAL_ADPCM_B_CHANNEL_MASK & 1) == 0) + return; + + // do a linear interpolation between samples + int32_t result = (m_prev_accum * int32_t((m_position ^ 0xffff) + 1) + m_accumulator * int32_t(m_position)) >> 16; + + // apply volume (level) in a linear fashion and reduce + result = (result * int32_t(m_regs.level())) >> (8 + rshift); + + // apply to left/right + if (NumOutputs == 1 || m_regs.pan_left()) + output.data[0] += result; + if (NumOutputs > 1 && m_regs.pan_right()) + output.data[1] += result; +} + + +//------------------------------------------------- +// read - handle special register reads +//------------------------------------------------- + +uint8_t adpcm_b_channel::read(uint32_t regnum) +{ + uint8_t result = 0; + + // register 8 reads over the bus under some conditions + if (regnum == 0x08 && !m_regs.execute() && !m_regs.record() && m_regs.external()) + { + // two dummy reads are consumed first + if (m_dummy_read != 0) + { + load_start(); + m_dummy_read--; + } + + // read the data + else + { + // read from outside of the chip + result = m_owner.intf().ymfm_external_read(ACCESS_ADPCM_B, m_curaddress++); + + // did we hit the end? if so, signal EOS + if (at_end()) + { + m_status = STATUS_EOS | STATUS_BRDY; + debug::log_keyon("%s\n", "ADPCM EOS"); + } + else + { + // signal ready + m_status = STATUS_BRDY; + } + + // wrap at the limit address + if (at_limit()) + m_curaddress = 0; + } + } + return result; +} + + +//------------------------------------------------- +// write - handle special register writes +//------------------------------------------------- + +void adpcm_b_channel::write(uint32_t regnum, uint8_t value) +{ + // register 0 can do a reset; also use writes here to reset the + // dummy read counter + if (regnum == 0x00) + { + if (m_regs.execute()) + { + load_start(); + + // don't log masked channels + if ((debug::GLOBAL_ADPCM_B_CHANNEL_MASK & 1) != 0) + debug::log_keyon("KeyOn ADPCM-B: rep=%d spk=%d pan=%d%d dac=%d 8b=%d rom=%d ext=%d rec=%d start=%04X end=%04X pre=%04X dn=%04X lvl=%02X lim=%04X\n", + m_regs.repeat(), + m_regs.speaker(), + m_regs.pan_left(), + m_regs.pan_right(), + m_regs.dac_enable(), + m_regs.dram_8bit(), + m_regs.rom_ram(), + m_regs.external(), + m_regs.record(), + m_regs.start(), + m_regs.end(), + m_regs.prescale(), + m_regs.delta_n(), + m_regs.level(), + m_regs.limit()); + } + else + m_status &= ~STATUS_EOS; + if (m_regs.resetflag()) + reset(); + if (m_regs.external()) + m_dummy_read = 2; + } + + // register 8 writes over the bus under some conditions + else if (regnum == 0x08) + { + // if writing from the CPU during execute, clear the ready flag + if (m_regs.execute() && !m_regs.record() && !m_regs.external()) + m_status &= ~STATUS_BRDY; + + // if writing during "record", pass through as data + else if (!m_regs.execute() && m_regs.record() && m_regs.external()) + { + // clear out dummy reads and set start address + if (m_dummy_read != 0) + { + load_start(); + m_dummy_read = 0; + } + + // did we hit the end? if so, signal EOS + if (at_end()) + { + debug::log_keyon("%s\n", "ADPCM EOS"); + m_status = STATUS_EOS | STATUS_BRDY; + } + + // otherwise, write the data and signal ready + else + { + m_owner.intf().ymfm_external_write(ACCESS_ADPCM_B, m_curaddress++, value); + m_status = STATUS_BRDY; + } + } + } +} + + +//------------------------------------------------- +// address_shift - compute the current address +// shift amount based on register settings +//------------------------------------------------- + +uint32_t adpcm_b_channel::address_shift() const +{ + // if a constant address shift, just provide that + if (m_address_shift != 0) + return m_address_shift; + + // if ROM or 8-bit DRAM, shift is 5 bits + if (m_regs.rom_ram()) + return 5; + if (m_regs.dram_8bit()) + return 5; + + // otherwise, shift is 2 bits + return 2; +} + + +//------------------------------------------------- +// load_start - load the start address and +// initialize the state +//------------------------------------------------- + +void adpcm_b_channel::load_start() +{ + m_status = (m_status & ~STATUS_EOS) | STATUS_PLAYING; + m_curaddress = m_regs.external() ? (m_regs.start() << address_shift()) : 0; + m_curnibble = 0; + m_curbyte = 0; + m_position = 0; + m_accumulator = 0; + m_prev_accum = 0; + m_adpcm_step = STEP_MIN; +} + + + +//********************************************************* +// ADPCM "B" ENGINE +//********************************************************* + +//------------------------------------------------- +// adpcm_b_engine - constructor +//------------------------------------------------- + +adpcm_b_engine::adpcm_b_engine(ymfm_interface &intf, uint32_t addrshift) : + m_intf(intf) +{ + // create the channel (only one supported for now, but leaving possibilities open) + m_channel = std::make_unique(*this, addrshift); +} + + +//------------------------------------------------- +// reset - reset the engine state +//------------------------------------------------- + +void adpcm_b_engine::reset() +{ + // reset registers + m_regs.reset(); + + // reset each channel + m_channel->reset(); +} + + +//------------------------------------------------- +// save_restore - save or restore the data +//------------------------------------------------- + +void adpcm_b_engine::save_restore(ymfm_saved_state &state) +{ + // save our state + m_regs.save_restore(state); + + // save channel state + m_channel->save_restore(state); +} + + +//------------------------------------------------- +// clock - master clocking function +//------------------------------------------------- + +void adpcm_b_engine::clock() +{ + // clock each channel, setting a bit in result if it finished + m_channel->clock(); +} + + +//------------------------------------------------- +// output - master output function +//------------------------------------------------- + +template +void adpcm_b_engine::output(ymfm_output &output, uint32_t rshift) +{ + // compute the output of each channel + m_channel->output(output, rshift); +} + +template void adpcm_b_engine::output<1>(ymfm_output<1> &output, uint32_t rshift); +template void adpcm_b_engine::output<2>(ymfm_output<2> &output, uint32_t rshift); + + +//------------------------------------------------- +// write - handle writes to the ADPCM-B registers +//------------------------------------------------- + +void adpcm_b_engine::write(uint32_t regnum, uint8_t data) +{ + // store the raw value to the register array; + // most writes are passive, consumed only when needed + m_regs.write(regnum, data); + + // let the channel handle any special writes + m_channel->write(regnum, data); +} + +} diff --git a/src/sound/ymfm/ymfm_adpcm.h b/src/sound/ymfm/ymfm_adpcm.h new file mode 100644 index 000000000..d74e24f27 --- /dev/null +++ b/src/sound/ymfm/ymfm_adpcm.h @@ -0,0 +1,411 @@ +// BSD 3-Clause License +// +// Copyright (c) 2021, Aaron Giles +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// 1. Redistributions of source code must retain the above copyright notice, this +// list of conditions and the following disclaimer. +// +// 2. Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// 3. Neither the name of the copyright holder nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#ifndef YMFM_ADPCM_H +#define YMFM_ADPCM_H + +#pragma once + +#include "ymfm.h" + +namespace ymfm +{ + +//********************************************************* +// INTERFACE CLASSES +//********************************************************* + +// forward declarations +class adpcm_a_engine; +class adpcm_b_engine; + + +// ======================> adpcm_a_registers + +// +// ADPCM-A register map: +// +// System-wide registers: +// 00 x------- Dump (disable=1) or keyon (0) control +// --xxxxxx Mask of channels to dump or keyon +// 01 --xxxxxx Total level +// 02 xxxxxxxx Test register +// 08-0D x------- Pan left +// -x------ Pan right +// ---xxxxx Instrument level +// 10-15 xxxxxxxx Start address (low) +// 18-1D xxxxxxxx Start address (high) +// 20-25 xxxxxxxx End address (low) +// 28-2D xxxxxxxx End address (high) +// +class adpcm_a_registers +{ +public: + // constants + static constexpr uint32_t OUTPUTS = 2; + static constexpr uint32_t CHANNELS = 6; + static constexpr uint32_t REGISTERS = 0x30; + static constexpr uint32_t ALL_CHANNELS = (1 << CHANNELS) - 1; + + // constructor + adpcm_a_registers() { } + + // reset to initial state + void reset(); + + // save/restore + void save_restore(ymfm_saved_state &state); + + // map channel number to register offset + static constexpr uint32_t channel_offset(uint32_t chnum) + { + assert(chnum < CHANNELS); + return chnum; + } + + // direct read/write access + void write(uint32_t index, uint8_t data) { m_regdata[index] = data; } + + // system-wide registers + uint32_t dump() const { return bitfield(m_regdata[0x00], 7); } + uint32_t dump_mask() const { return bitfield(m_regdata[0x00], 0, 6); } + uint32_t total_level() const { return bitfield(m_regdata[0x01], 0, 6); } + uint32_t test() const { return m_regdata[0x02]; } + + // per-channel registers + uint32_t ch_pan_left(uint32_t choffs) const { return bitfield(m_regdata[choffs + 0x08], 7); } + uint32_t ch_pan_right(uint32_t choffs) const { return bitfield(m_regdata[choffs + 0x08], 6); } + uint32_t ch_instrument_level(uint32_t choffs) const { return bitfield(m_regdata[choffs + 0x08], 0, 5); } + uint32_t ch_start(uint32_t choffs) const { return m_regdata[choffs + 0x10] | (m_regdata[choffs + 0x18] << 8); } + uint32_t ch_end(uint32_t choffs) const { return m_regdata[choffs + 0x20] | (m_regdata[choffs + 0x28] << 8); } + + // per-channel writes + void write_start(uint32_t choffs, uint32_t address) + { + write(choffs + 0x10, address); + write(choffs + 0x18, address >> 8); + } + void write_end(uint32_t choffs, uint32_t address) + { + write(choffs + 0x20, address); + write(choffs + 0x28, address >> 8); + } + +private: + // internal state + uint8_t m_regdata[REGISTERS]; // register data +}; + + +// ======================> adpcm_a_channel + +class adpcm_a_channel +{ +public: + // constructor + adpcm_a_channel(adpcm_a_engine &owner, uint32_t choffs, uint32_t addrshift); + + // reset the channel state + void reset(); + + // save/restore + void save_restore(ymfm_saved_state &state); + + // signal key on/off + void keyonoff(bool on); + + // master clockingfunction + bool clock(); + + // return the computed output value, with panning applied + template + void output(ymfm_output &output) const; + +private: + // internal state + uint32_t const m_choffs; // channel offset + uint32_t const m_address_shift; // address bits shift-left + uint32_t m_playing; // currently playing? + uint32_t m_curnibble; // index of the current nibble + uint32_t m_curbyte; // current byte of data + uint32_t m_curaddress; // current address + int32_t m_accumulator; // accumulator + int32_t m_step_index; // index in the stepping table + adpcm_a_registers &m_regs; // reference to registers + adpcm_a_engine &m_owner; // reference to our owner +}; + + +// ======================> adpcm_a_engine + +class adpcm_a_engine +{ +public: + static constexpr int CHANNELS = adpcm_a_registers::CHANNELS; + + // constructor + adpcm_a_engine(ymfm_interface &intf, uint32_t addrshift); + + // reset our status + void reset(); + + // save/restore + void save_restore(ymfm_saved_state &state); + + // master clocking function + uint32_t clock(uint32_t chanmask); + + // compute sum of channel outputs + template + void output(ymfm_output &output, uint32_t chanmask); + + // write to the ADPCM-A registers + void write(uint32_t regnum, uint8_t data); + + // set the start/end address for a channel (for hardcoded YM2608 percussion) + void set_start_end(uint8_t chnum, uint16_t start, uint16_t end) + { + uint32_t choffs = adpcm_a_registers::channel_offset(chnum); + m_regs.write_start(choffs, start); + m_regs.write_end(choffs, end); + } + + // return a reference to our interface + ymfm_interface &intf() { return m_intf; } + + // return a reference to our registers + adpcm_a_registers ®s() { return m_regs; } + +private: + // internal state + ymfm_interface &m_intf; // reference to the interface + std::unique_ptr m_channel[CHANNELS]; // array of channels + adpcm_a_registers m_regs; // registers +}; + + +// ======================> adpcm_b_registers + +// +// ADPCM-B register map: +// +// System-wide registers: +// 00 x------- Start of synthesis/analysis +// -x------ Record +// --x----- External/manual driving +// ---x---- Repeat playback +// ----x--- Speaker off +// -------x Reset +// 01 x------- Pan left +// -x------ Pan right +// ----x--- Start conversion +// -----x-- DAC enable +// ------x- DRAM access (1=8-bit granularity; 0=1-bit) +// -------x RAM/ROM (1=ROM, 0=RAM) +// 02 xxxxxxxx Start address (low) +// 03 xxxxxxxx Start address (high) +// 04 xxxxxxxx End address (low) +// 05 xxxxxxxx End address (high) +// 06 xxxxxxxx Prescale value (low) +// 07 -----xxx Prescale value (high) +// 08 xxxxxxxx CPU data/buffer +// 09 xxxxxxxx Delta-N frequency scale (low) +// 0a xxxxxxxx Delta-N frequency scale (high) +// 0b xxxxxxxx Level control +// 0c xxxxxxxx Limit address (low) +// 0d xxxxxxxx Limit address (high) +// 0e xxxxxxxx DAC data [YM2608/10] +// 0f xxxxxxxx PCM data [YM2608/10] +// 0e xxxxxxxx DAC data high [Y8950] +// 0f xx------ DAC data low [Y8950] +// 10 -----xxx DAC data exponent [Y8950] +// +class adpcm_b_registers +{ +public: + // constants + static constexpr uint32_t REGISTERS = 0x11; + + // constructor + adpcm_b_registers() { } + + // reset to initial state + void reset(); + + // save/restore + void save_restore(ymfm_saved_state &state); + + // direct read/write access + void write(uint32_t index, uint8_t data) { m_regdata[index] = data; } + + // system-wide registers + uint32_t execute() const { return bitfield(m_regdata[0x00], 7); } + uint32_t record() const { return bitfield(m_regdata[0x00], 6); } + uint32_t external() const { return bitfield(m_regdata[0x00], 5); } + uint32_t repeat() const { return bitfield(m_regdata[0x00], 4); } + uint32_t speaker() const { return bitfield(m_regdata[0x00], 3); } + uint32_t resetflag() const { return bitfield(m_regdata[0x00], 0); } + uint32_t pan_left() const { return bitfield(m_regdata[0x01], 7); } + uint32_t pan_right() const { return bitfield(m_regdata[0x01], 6); } + uint32_t start_conversion() const { return bitfield(m_regdata[0x01], 3); } + uint32_t dac_enable() const { return bitfield(m_regdata[0x01], 2); } + uint32_t dram_8bit() const { return bitfield(m_regdata[0x01], 1); } + uint32_t rom_ram() const { return bitfield(m_regdata[0x01], 0); } + uint32_t start() const { return m_regdata[0x02] | (m_regdata[0x03] << 8); } + uint32_t end() const { return m_regdata[0x04] | (m_regdata[0x05] << 8); } + uint32_t prescale() const { return m_regdata[0x06] | (bitfield(m_regdata[0x07], 0, 3) << 8); } + uint32_t cpudata() const { return m_regdata[0x08]; } + uint32_t delta_n() const { return m_regdata[0x09] | (m_regdata[0x0a] << 8); } + uint32_t level() const { return m_regdata[0x0b]; } + uint32_t limit() const { return m_regdata[0x0c] | (m_regdata[0x0d] << 8); } + uint32_t dac() const { return m_regdata[0x0e]; } + uint32_t pcm() const { return m_regdata[0x0f]; } + +private: + // internal state + uint8_t m_regdata[REGISTERS]; // register data +}; + + +// ======================> adpcm_b_channel + +class adpcm_b_channel +{ + static constexpr int32_t STEP_MIN = 127; + static constexpr int32_t STEP_MAX = 24576; + +public: + static constexpr uint8_t STATUS_EOS = 0x01; + static constexpr uint8_t STATUS_BRDY = 0x02; + static constexpr uint8_t STATUS_PLAYING = 0x04; + + // constructor + adpcm_b_channel(adpcm_b_engine &owner, uint32_t addrshift); + + // reset the channel state + void reset(); + + // save/restore + void save_restore(ymfm_saved_state &state); + + // signal key on/off + void keyonoff(bool on); + + // master clocking function + void clock(); + + // return the computed output value, with panning applied + template + void output(ymfm_output &output, uint32_t rshift) const; + + // return the status register + uint8_t status() const { return m_status; } + + // handle special register reads + uint8_t read(uint32_t regnum); + + // handle special register writes + void write(uint32_t regnum, uint8_t value); + +private: + // helper - return the current address shift + uint32_t address_shift() const; + + // load the start address + void load_start(); + + // limit checker; stops at the last byte of the chunk described by address_shift() + bool at_limit() const { return (m_curaddress == (((m_regs.limit() + 1) << address_shift()) - 1)); } + + // end checker; stops at the last byte of the chunk described by address_shift() + bool at_end() const { return (m_curaddress == (((m_regs.end() + 1) << address_shift()) - 1)); } + + // internal state + uint32_t const m_address_shift; // address bits shift-left + uint32_t m_status; // currently playing? + uint32_t m_curnibble; // index of the current nibble + uint32_t m_curbyte; // current byte of data + uint32_t m_dummy_read; // dummy read tracker + uint32_t m_position; // current fractional position + uint32_t m_curaddress; // current address + int32_t m_accumulator; // accumulator + int32_t m_prev_accum; // previous accumulator (for linear interp) + int32_t m_adpcm_step; // next forecast + adpcm_b_registers &m_regs; // reference to registers + adpcm_b_engine &m_owner; // reference to our owner +}; + + +// ======================> adpcm_b_engine + +class adpcm_b_engine +{ +public: + // constructor + adpcm_b_engine(ymfm_interface &intf, uint32_t addrshift = 0); + + // reset our status + void reset(); + + // save/restore + void save_restore(ymfm_saved_state &state); + + // master clocking function + void clock(); + + // compute sum of channel outputs + template + void output(ymfm_output &output, uint32_t rshift); + + // read from the ADPCM-B registers + uint32_t read(uint32_t regnum) { return m_channel->read(regnum); } + + // write to the ADPCM-B registers + void write(uint32_t regnum, uint8_t data); + + // status + uint8_t status() const { return m_channel->status(); } + + // return a reference to our interface + ymfm_interface &intf() { return m_intf; } + + // return a reference to our registers + adpcm_b_registers ®s() { return m_regs; } + +private: + // internal state + ymfm_interface &m_intf; // reference to our interface + std::unique_ptr m_channel; // channel pointer + adpcm_b_registers m_regs; // registers +}; + +} + +#endif // YMFM_ADPCM_H diff --git a/src/sound/ymfm/ymfm_fm.h b/src/sound/ymfm/ymfm_fm.h new file mode 100644 index 000000000..81795f8fe --- /dev/null +++ b/src/sound/ymfm/ymfm_fm.h @@ -0,0 +1,463 @@ +// BSD 3-Clause License +// +// Copyright (c) 2021, Aaron Giles +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// 1. Redistributions of source code must retain the above copyright notice, this +// list of conditions and the following disclaimer. +// +// 2. Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// 3. Neither the name of the copyright holder nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#ifndef YMFM_FM_H +#define YMFM_FM_H + +#pragma once + +#define YMFM_DEBUG_LOG_WAVFILES (0) + +namespace ymfm +{ + +//********************************************************* +// GLOBAL ENUMERATORS +//********************************************************* + +// three different keyon sources; actual keyon is an OR over all of these +enum keyon_type : uint32_t +{ + KEYON_NORMAL = 0, + KEYON_RHYTHM = 1, + KEYON_CSM = 2 +}; + + + +//********************************************************* +// CORE IMPLEMENTATION +//********************************************************* + +// ======================> opdata_cache + +// this class holds data that is computed once at the start of clocking +// and remains static during subsequent sound generation +struct opdata_cache +{ + // set phase_step to this value to recalculate it each sample; needed + // in the case of PM LFO changes + static constexpr uint32_t PHASE_STEP_DYNAMIC = 1; + + uint16_t const *waveform; // base of sine table + uint32_t phase_step; // phase step, or PHASE_STEP_DYNAMIC if PM is active + uint32_t total_level; // total level * 8 + KSL + uint32_t block_freq; // raw block frequency value (used to compute phase_step) + int32_t detune; // detuning value (used to compute phase_step) + uint32_t multiple; // multiple value (x.1, used to compute phase_step) + uint32_t eg_sustain; // sustain level, shifted up to envelope values + uint8_t eg_rate[EG_STATES]; // envelope rate, including KSR + uint8_t eg_shift = 0; // envelope shift amount +}; + + +// ======================> fm_registers_base + +// base class for family-specific register classes; this provides a few +// constants, common defaults, and helpers, but mostly each derived class is +// responsible for defining all commonly-called methods +class fm_registers_base +{ +public: + // this value is returned from the write() function for rhythm channels + static constexpr uint32_t RHYTHM_CHANNEL = 0xff; + + // this is the size of a full sin waveform + static constexpr uint32_t WAVEFORM_LENGTH = 0x400; + + // + // the following constants need to be defined per family: + // uint32_t OUTPUTS: The number of outputs exposed (1-4) + // uint32_t CHANNELS: The number of channels on the chip + // uint32_t ALL_CHANNELS: A bitmask of all channels + // uint32_t OPERATORS: The number of operators on the chip + // uint32_t WAVEFORMS: The number of waveforms offered + // uint32_t REGISTERS: The number of 8-bit registers allocated + // uint32_t DEFAULT_PRESCALE: The starting clock prescale + // uint32_t EG_CLOCK_DIVIDER: The clock divider of the envelope generator + // uint32_t CSM_TRIGGER_MASK: Mask of channels to trigger in CSM mode + // uint32_t REG_MODE: The address of the "mode" register controlling timers + // uint8_t STATUS_TIMERA: Status bit to set when timer A fires + // uint8_t STATUS_TIMERB: Status bit to set when tiemr B fires + // uint8_t STATUS_BUSY: Status bit to set when the chip is busy + // uint8_t STATUS_IRQ: Status bit to set when an IRQ is signalled + // + // the following constants are uncommon: + // bool DYNAMIC_OPS: True if ops/channel can be changed at runtime (OPL3+) + // bool EG_HAS_DEPRESS: True if the chip has a DP ("depress"?) envelope stage (OPLL) + // bool EG_HAS_REVERB: True if the chip has a faux reverb envelope stage (OPQ/OPZ) + // bool EG_HAS_SSG: True if the chip has SSG envelope support (OPN) + // bool MODULATOR_DELAY: True if the modulator is delayed by 1 sample (OPL pre-OPL3) + // + static constexpr bool DYNAMIC_OPS = false; + static constexpr bool EG_HAS_DEPRESS = false; + static constexpr bool EG_HAS_REVERB = false; + static constexpr bool EG_HAS_SSG = false; + static constexpr bool MODULATOR_DELAY = false; + + // system-wide register defaults + uint32_t status_mask() const { return 0; } // OPL only + uint32_t irq_reset() const { return 0; } // OPL only + uint32_t noise_enable() const { return 0; } // OPM only + uint32_t rhythm_enable() const { return 0; } // OPL only + + // per-operator register defaults + uint32_t op_ssg_eg_enable(uint32_t opoffs) const { return 0; } // OPN(A) only + uint32_t op_ssg_eg_mode(uint32_t opoffs) const { return 0; } // OPN(A) only + +protected: + // helper to encode four operator numbers into a 32-bit value in the + // operator maps for each register class + static constexpr uint32_t operator_list(uint8_t o1 = 0xff, uint8_t o2 = 0xff, uint8_t o3 = 0xff, uint8_t o4 = 0xff) + { + return o1 | (o2 << 8) | (o3 << 16) | (o4 << 24); + } + + // helper to apply KSR to the raw ADSR rate, ignoring ksr if the + // raw value is 0, and clamping to 63 + static constexpr uint32_t effective_rate(uint32_t rawrate, uint32_t ksr) + { + return (rawrate == 0) ? 0 : std::min(rawrate + ksr, 63); + } +}; + + + +//********************************************************* +// CORE ENGINE CLASSES +//********************************************************* + +// forward declarations +template class fm_engine_base; + +// ======================> fm_operator + +// fm_operator represents an FM operator (or "slot" in FM parlance), which +// produces an output sine wave modulated by an envelope +template +class fm_operator +{ + // "quiet" value, used to optimize when we can skip doing work + static constexpr uint32_t EG_QUIET = 0x380; + +public: + // constructor + fm_operator(fm_engine_base &owner, uint32_t opoffs); + + // save/restore + void save_restore(ymfm_saved_state &state); + + // reset the operator state + void reset(); + + // return the operator/channel offset + uint32_t opoffs() const { return m_opoffs; } + uint32_t choffs() const { return m_choffs; } + + // set the current channel + void set_choffs(uint32_t choffs) { m_choffs = choffs; } + + // prepare prior to clocking + bool prepare(); + + // master clocking function + void clock(uint32_t env_counter, int32_t lfo_raw_pm); + + // return the current phase value + uint32_t phase() const { return m_phase >> 10; } + + // compute operator volume + int32_t compute_volume(uint32_t phase, uint32_t am_offset) const; + + // compute volume for the OPM noise channel + int32_t compute_noise_volume(uint32_t am_offset) const; + + // key state control + void keyonoff(uint32_t on, keyon_type type); + + // return a reference to our registers + RegisterType ®s() const { return m_regs; } + + // simple getters for debugging + envelope_state debug_eg_state() const { return m_env_state; } + uint16_t debug_eg_attenuation() const { return m_env_attenuation; } + uint8_t debug_ssg_inverted() const { return m_ssg_inverted; } + opdata_cache &debug_cache() { return m_cache; } + +private: + // start the attack phase + void start_attack(bool is_restart = false); + + // start the release phase + void start_release(); + + // clock phases + void clock_keystate(uint32_t keystate); + void clock_ssg_eg_state(); + void clock_envelope(uint32_t env_counter); + void clock_phase(int32_t lfo_raw_pm); + + // return effective attenuation of the envelope + uint32_t envelope_attenuation(uint32_t am_offset) const; + + // internal state + uint32_t m_choffs; // channel offset in registers + uint32_t m_opoffs; // operator offset in registers + uint32_t m_phase; // current phase value (10.10 format) + uint16_t m_env_attenuation; // computed envelope attenuation (4.6 format) + envelope_state m_env_state; // current envelope state + uint8_t m_ssg_inverted; // non-zero if the output should be inverted (bit 0) + uint8_t m_key_state; // current key state: on or off (bit 0) + uint8_t m_keyon_live; // live key on state (bit 0 = direct, bit 1 = rhythm, bit 2 = CSM) + opdata_cache m_cache; // cached values for performance + RegisterType &m_regs; // direct reference to registers + fm_engine_base &m_owner; // reference to the owning engine +}; + + +// ======================> fm_channel + +// fm_channel represents an FM channel which combines the output of 2 or 4 +// operators into a final result +template +class fm_channel +{ + using output_data = ymfm_output; + +public: + // constructor + fm_channel(fm_engine_base &owner, uint32_t choffs); + + // save/restore + void save_restore(ymfm_saved_state &state); + + // reset the channel state + void reset(); + + // return the channel offset + uint32_t choffs() const { return m_choffs; } + + // assign operators + void assign(uint32_t index, fm_operator *op) + { + assert(index < array_size(m_op)); + m_op[index] = op; + if (op != nullptr) + op->set_choffs(m_choffs); + } + + // signal key on/off to our operators + void keyonoff(uint32_t states, keyon_type type, uint32_t chnum); + + // prepare prior to clocking + bool prepare(); + + // master clocking function + void clock(uint32_t env_counter, int32_t lfo_raw_pm); + + // specific 2-operator and 4-operator output handlers + void output_2op(output_data &output, uint32_t rshift, int32_t clipmax) const; + void output_4op(output_data &output, uint32_t rshift, int32_t clipmax) const; + + // compute the special OPL rhythm channel outputs + void output_rhythm_ch6(output_data &output, uint32_t rshift, int32_t clipmax) const; + void output_rhythm_ch7(uint32_t phase_select, output_data &output, uint32_t rshift, int32_t clipmax) const; + void output_rhythm_ch8(uint32_t phase_select, output_data &output, uint32_t rshift, int32_t clipmax) const; + + // are we a 4-operator channel or a 2-operator one? + bool is4op() const + { + if (RegisterType::DYNAMIC_OPS) + return (m_op[2] != nullptr); + return (RegisterType::OPERATORS / RegisterType::CHANNELS == 4); + } + + // return a reference to our registers + RegisterType ®s() const { return m_regs; } + + // simple getters for debugging + fm_operator *debug_operator(uint32_t index) const { return m_op[index]; } + +private: + // helper to add values to the outputs based on channel enables + void add_to_output(uint32_t choffs, output_data &output, int32_t value) const + { + // create these constants to appease overzealous compilers checking array + // bounds in unreachable code (looking at you, clang) + constexpr int out0_index = 0; + constexpr int out1_index = 1 % RegisterType::OUTPUTS; + constexpr int out2_index = 2 % RegisterType::OUTPUTS; + constexpr int out3_index = 3 % RegisterType::OUTPUTS; + + if (RegisterType::OUTPUTS == 1 || m_regs.ch_output_0(choffs)) + output.data[out0_index] += value; + if (RegisterType::OUTPUTS >= 2 && m_regs.ch_output_1(choffs)) + output.data[out1_index] += value; + if (RegisterType::OUTPUTS >= 3 && m_regs.ch_output_2(choffs)) + output.data[out2_index] += value; + if (RegisterType::OUTPUTS >= 4 && m_regs.ch_output_3(choffs)) + output.data[out3_index] += value; + } + + // internal state + uint32_t m_choffs; // channel offset in registers + int16_t m_feedback[2]; // feedback memory for operator 1 + mutable int16_t m_feedback_in; // next input value for op 1 feedback (set in output) + fm_operator *m_op[4]; // up to 4 operators + RegisterType &m_regs; // direct reference to registers + fm_engine_base &m_owner; // reference to the owning engine +}; + + +// ======================> fm_engine_base + +// fm_engine_base represents a set of operators and channels which together +// form a Yamaha FM core; chips that implement other engines (ADPCM, wavetable, +// etc) take this output and combine it with the others externally +template +class fm_engine_base : public ymfm_engine_callbacks +{ +public: + // expose some constants from the registers + static constexpr uint32_t OUTPUTS = RegisterType::OUTPUTS; + static constexpr uint32_t CHANNELS = RegisterType::CHANNELS; + static constexpr uint32_t ALL_CHANNELS = RegisterType::ALL_CHANNELS; + static constexpr uint32_t OPERATORS = RegisterType::OPERATORS; + + // also expose status flags for consumers that inject additional bits + static constexpr uint8_t STATUS_TIMERA = RegisterType::STATUS_TIMERA; + static constexpr uint8_t STATUS_TIMERB = RegisterType::STATUS_TIMERB; + static constexpr uint8_t STATUS_BUSY = RegisterType::STATUS_BUSY; + static constexpr uint8_t STATUS_IRQ = RegisterType::STATUS_IRQ; + + // expose the correct output class + using output_data = ymfm_output; + + // constructor + fm_engine_base(ymfm_interface &intf); + + // save/restore + void save_restore(ymfm_saved_state &state); + + // reset the overall state + void reset(); + + // master clocking function + uint32_t clock(uint32_t chanmask); + + // compute sum of channel outputs + void output(output_data &output, uint32_t rshift, int32_t clipmax, uint32_t chanmask) const; + + // write to the OPN registers + void write(uint16_t regnum, uint8_t data); + + // return the current status + uint8_t status() const; + + // set/reset bits in the status register, updating the IRQ status + uint8_t set_reset_status(uint8_t set, uint8_t reset) + { + m_status = (m_status | set) & ~(reset | STATUS_BUSY); + m_intf.ymfm_sync_check_interrupts(); + return m_status & ~m_regs.status_mask(); + } + + // set the IRQ mask + void set_irq_mask(uint8_t mask) { m_irq_mask = mask; m_intf.ymfm_sync_check_interrupts(); } + + // return the current clock prescale + uint32_t clock_prescale() const { return m_clock_prescale; } + + // set prescale factor (2/3/6) + void set_clock_prescale(uint32_t prescale) { m_clock_prescale = prescale; } + + // compute sample rate + uint32_t sample_rate(uint32_t baseclock) const + { +#if (YMFM_DEBUG_LOG_WAVFILES) + for (uint32_t chnum = 0; chnum < CHANNELS; chnum++) + m_wavfile[chnum].set_samplerate(baseclock / (m_clock_prescale * OPERATORS)); +#endif + return baseclock / (m_clock_prescale * OPERATORS); + } + + // return the owning device + ymfm_interface &intf() const { return m_intf; } + + // return a reference to our registers + RegisterType ®s() { return m_regs; } + + // invalidate any caches + void invalidate_caches() { m_modified_channels = RegisterType::ALL_CHANNELS; } + + // simple getters for debugging + fm_channel *debug_channel(uint32_t index) const { return m_channel[index].get(); } + fm_operator *debug_operator(uint32_t index) const { return m_operator[index].get(); } + +public: + // timer callback; called by the interface when a timer fires + virtual void engine_timer_expired(uint32_t tnum) override; + + // check interrupts; called by the interface after synchronization + virtual void engine_check_interrupts() override; + + // mode register write; called by the interface after synchronization + virtual void engine_mode_write(uint8_t data) override; + +protected: + // assign the current set of operators to channels + void assign_operators(); + + // update the state of the given timer + void update_timer(uint32_t which, uint32_t enable, int32_t delta_clocks); + + // internal state + ymfm_interface &m_intf; // reference to the system interface + uint32_t m_env_counter; // envelope counter; low 2 bits are sub-counter + uint8_t m_status; // current status register + uint8_t m_clock_prescale; // prescale factor (2/3/6) + uint8_t m_irq_mask; // mask of which bits signal IRQs + uint8_t m_irq_state; // current IRQ state + uint8_t m_timer_running[2]; // current timer running state + uint8_t m_total_clocks; // low 8 bits of the total number of clocks processed + uint32_t m_active_channels; // mask of active channels (computed by prepare) + uint32_t m_modified_channels; // mask of channels that have been modified + uint32_t m_prepare_count; // counter to do periodic prepare sweeps + RegisterType m_regs; // register accessor + std::unique_ptr> m_channel[CHANNELS]; // channel pointers + std::unique_ptr> m_operator[OPERATORS]; // operator pointers +#if (YMFM_DEBUG_LOG_WAVFILES) + mutable ymfm_wavfile<1> m_wavfile[CHANNELS]; // for debugging +#endif +}; + +} + +#endif // YMFM_FM_H diff --git a/src/sound/ymfm/ymfm_fm.ipp b/src/sound/ymfm/ymfm_fm.ipp new file mode 100644 index 000000000..55cdd643d --- /dev/null +++ b/src/sound/ymfm/ymfm_fm.ipp @@ -0,0 +1,1599 @@ +// BSD 3-Clause License +// +// Copyright (c) 2021, Aaron Giles +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// 1. Redistributions of source code must retain the above copyright notice, this +// list of conditions and the following disclaimer. +// +// 2. Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// 3. Neither the name of the copyright holder nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +namespace ymfm +{ + +//********************************************************* +// GLOBAL TABLE LOOKUPS +//********************************************************* + +//------------------------------------------------- +// abs_sin_attenuation - given a sin (phase) input +// where the range 0-2*PI is mapped onto 10 bits, +// return the absolute value of sin(input), +// logarithmically-adjusted and treated as an +// attenuation value, in 4.8 fixed point format +//------------------------------------------------- + +inline uint32_t abs_sin_attenuation(uint32_t input) +{ + // the values here are stored as 4.8 logarithmic values for 1/4 phase + // this matches the internal format of the OPN chip, extracted from the die + static uint16_t const s_sin_table[256] = + { + 0x859,0x6c3,0x607,0x58b,0x52e,0x4e4,0x4a6,0x471,0x443,0x41a,0x3f5,0x3d3,0x3b5,0x398,0x37e,0x365, + 0x34e,0x339,0x324,0x311,0x2ff,0x2ed,0x2dc,0x2cd,0x2bd,0x2af,0x2a0,0x293,0x286,0x279,0x26d,0x261, + 0x256,0x24b,0x240,0x236,0x22c,0x222,0x218,0x20f,0x206,0x1fd,0x1f5,0x1ec,0x1e4,0x1dc,0x1d4,0x1cd, + 0x1c5,0x1be,0x1b7,0x1b0,0x1a9,0x1a2,0x19b,0x195,0x18f,0x188,0x182,0x17c,0x177,0x171,0x16b,0x166, + 0x160,0x15b,0x155,0x150,0x14b,0x146,0x141,0x13c,0x137,0x133,0x12e,0x129,0x125,0x121,0x11c,0x118, + 0x114,0x10f,0x10b,0x107,0x103,0x0ff,0x0fb,0x0f8,0x0f4,0x0f0,0x0ec,0x0e9,0x0e5,0x0e2,0x0de,0x0db, + 0x0d7,0x0d4,0x0d1,0x0cd,0x0ca,0x0c7,0x0c4,0x0c1,0x0be,0x0bb,0x0b8,0x0b5,0x0b2,0x0af,0x0ac,0x0a9, + 0x0a7,0x0a4,0x0a1,0x09f,0x09c,0x099,0x097,0x094,0x092,0x08f,0x08d,0x08a,0x088,0x086,0x083,0x081, + 0x07f,0x07d,0x07a,0x078,0x076,0x074,0x072,0x070,0x06e,0x06c,0x06a,0x068,0x066,0x064,0x062,0x060, + 0x05e,0x05c,0x05b,0x059,0x057,0x055,0x053,0x052,0x050,0x04e,0x04d,0x04b,0x04a,0x048,0x046,0x045, + 0x043,0x042,0x040,0x03f,0x03e,0x03c,0x03b,0x039,0x038,0x037,0x035,0x034,0x033,0x031,0x030,0x02f, + 0x02e,0x02d,0x02b,0x02a,0x029,0x028,0x027,0x026,0x025,0x024,0x023,0x022,0x021,0x020,0x01f,0x01e, + 0x01d,0x01c,0x01b,0x01a,0x019,0x018,0x017,0x017,0x016,0x015,0x014,0x014,0x013,0x012,0x011,0x011, + 0x010,0x00f,0x00f,0x00e,0x00d,0x00d,0x00c,0x00c,0x00b,0x00a,0x00a,0x009,0x009,0x008,0x008,0x007, + 0x007,0x007,0x006,0x006,0x005,0x005,0x005,0x004,0x004,0x004,0x003,0x003,0x003,0x002,0x002,0x002, + 0x002,0x001,0x001,0x001,0x001,0x001,0x001,0x001,0x000,0x000,0x000,0x000,0x000,0x000,0x000,0x000 + }; + + // if the top bit is set, we're in the second half of the curve + // which is a mirror image, so invert the index + if (bitfield(input, 8)) + input = ~input; + + // return the value from the table + return s_sin_table[input & 0xff]; +} + + +//------------------------------------------------- +// attenuation_to_volume - given a 5.8 fixed point +// logarithmic attenuation value, return a 13-bit +// linear volume +//------------------------------------------------- + +inline uint32_t attenuation_to_volume(uint32_t input) +{ + // the values here are 10-bit mantissas with an implied leading bit + // this matches the internal format of the OPN chip, extracted from the die + + // as a nod to performance, the implicit 0x400 bit is pre-incorporated, and + // the values are left-shifted by 2 so that a simple right shift is all that + // is needed; also the order is reversed to save a NOT on the input +#define X(a) (((a) | 0x400) << 2) + static uint16_t const s_power_table[256] = + { + X(0x3fa),X(0x3f5),X(0x3ef),X(0x3ea),X(0x3e4),X(0x3df),X(0x3da),X(0x3d4), + X(0x3cf),X(0x3c9),X(0x3c4),X(0x3bf),X(0x3b9),X(0x3b4),X(0x3ae),X(0x3a9), + X(0x3a4),X(0x39f),X(0x399),X(0x394),X(0x38f),X(0x38a),X(0x384),X(0x37f), + X(0x37a),X(0x375),X(0x370),X(0x36a),X(0x365),X(0x360),X(0x35b),X(0x356), + X(0x351),X(0x34c),X(0x347),X(0x342),X(0x33d),X(0x338),X(0x333),X(0x32e), + X(0x329),X(0x324),X(0x31f),X(0x31a),X(0x315),X(0x310),X(0x30b),X(0x306), + X(0x302),X(0x2fd),X(0x2f8),X(0x2f3),X(0x2ee),X(0x2e9),X(0x2e5),X(0x2e0), + X(0x2db),X(0x2d6),X(0x2d2),X(0x2cd),X(0x2c8),X(0x2c4),X(0x2bf),X(0x2ba), + X(0x2b5),X(0x2b1),X(0x2ac),X(0x2a8),X(0x2a3),X(0x29e),X(0x29a),X(0x295), + X(0x291),X(0x28c),X(0x288),X(0x283),X(0x27f),X(0x27a),X(0x276),X(0x271), + X(0x26d),X(0x268),X(0x264),X(0x25f),X(0x25b),X(0x257),X(0x252),X(0x24e), + X(0x249),X(0x245),X(0x241),X(0x23c),X(0x238),X(0x234),X(0x230),X(0x22b), + X(0x227),X(0x223),X(0x21e),X(0x21a),X(0x216),X(0x212),X(0x20e),X(0x209), + X(0x205),X(0x201),X(0x1fd),X(0x1f9),X(0x1f5),X(0x1f0),X(0x1ec),X(0x1e8), + X(0x1e4),X(0x1e0),X(0x1dc),X(0x1d8),X(0x1d4),X(0x1d0),X(0x1cc),X(0x1c8), + X(0x1c4),X(0x1c0),X(0x1bc),X(0x1b8),X(0x1b4),X(0x1b0),X(0x1ac),X(0x1a8), + X(0x1a4),X(0x1a0),X(0x19c),X(0x199),X(0x195),X(0x191),X(0x18d),X(0x189), + X(0x185),X(0x181),X(0x17e),X(0x17a),X(0x176),X(0x172),X(0x16f),X(0x16b), + X(0x167),X(0x163),X(0x160),X(0x15c),X(0x158),X(0x154),X(0x151),X(0x14d), + X(0x149),X(0x146),X(0x142),X(0x13e),X(0x13b),X(0x137),X(0x134),X(0x130), + X(0x12c),X(0x129),X(0x125),X(0x122),X(0x11e),X(0x11b),X(0x117),X(0x114), + X(0x110),X(0x10c),X(0x109),X(0x106),X(0x102),X(0x0ff),X(0x0fb),X(0x0f8), + X(0x0f4),X(0x0f1),X(0x0ed),X(0x0ea),X(0x0e7),X(0x0e3),X(0x0e0),X(0x0dc), + X(0x0d9),X(0x0d6),X(0x0d2),X(0x0cf),X(0x0cc),X(0x0c8),X(0x0c5),X(0x0c2), + X(0x0be),X(0x0bb),X(0x0b8),X(0x0b5),X(0x0b1),X(0x0ae),X(0x0ab),X(0x0a8), + X(0x0a4),X(0x0a1),X(0x09e),X(0x09b),X(0x098),X(0x094),X(0x091),X(0x08e), + X(0x08b),X(0x088),X(0x085),X(0x082),X(0x07e),X(0x07b),X(0x078),X(0x075), + X(0x072),X(0x06f),X(0x06c),X(0x069),X(0x066),X(0x063),X(0x060),X(0x05d), + X(0x05a),X(0x057),X(0x054),X(0x051),X(0x04e),X(0x04b),X(0x048),X(0x045), + X(0x042),X(0x03f),X(0x03c),X(0x039),X(0x036),X(0x033),X(0x030),X(0x02d), + X(0x02a),X(0x028),X(0x025),X(0x022),X(0x01f),X(0x01c),X(0x019),X(0x016), + X(0x014),X(0x011),X(0x00e),X(0x00b),X(0x008),X(0x006),X(0x003),X(0x000) + }; +#undef X + + // look up the fractional part, then shift by the whole + return s_power_table[input & 0xff] >> (input >> 8); +} + + +//------------------------------------------------- +// attenuation_increment - given a 6-bit ADSR +// rate value and a 3-bit stepping index, +// return a 4-bit increment to the attenutaion +// for this step (or for the attack case, the +// fractional scale factor to decrease by) +//------------------------------------------------- + +inline uint32_t attenuation_increment(uint32_t rate, uint32_t index) +{ + static uint32_t const s_increment_table[64] = + { + 0x00000000, 0x00000000, 0x10101010, 0x10101010, // 0-3 (0x00-0x03) + 0x10101010, 0x10101010, 0x11101110, 0x11101110, // 4-7 (0x04-0x07) + 0x10101010, 0x10111010, 0x11101110, 0x11111110, // 8-11 (0x08-0x0B) + 0x10101010, 0x10111010, 0x11101110, 0x11111110, // 12-15 (0x0C-0x0F) + 0x10101010, 0x10111010, 0x11101110, 0x11111110, // 16-19 (0x10-0x13) + 0x10101010, 0x10111010, 0x11101110, 0x11111110, // 20-23 (0x14-0x17) + 0x10101010, 0x10111010, 0x11101110, 0x11111110, // 24-27 (0x18-0x1B) + 0x10101010, 0x10111010, 0x11101110, 0x11111110, // 28-31 (0x1C-0x1F) + 0x10101010, 0x10111010, 0x11101110, 0x11111110, // 32-35 (0x20-0x23) + 0x10101010, 0x10111010, 0x11101110, 0x11111110, // 36-39 (0x24-0x27) + 0x10101010, 0x10111010, 0x11101110, 0x11111110, // 40-43 (0x28-0x2B) + 0x10101010, 0x10111010, 0x11101110, 0x11111110, // 44-47 (0x2C-0x2F) + 0x11111111, 0x21112111, 0x21212121, 0x22212221, // 48-51 (0x30-0x33) + 0x22222222, 0x42224222, 0x42424242, 0x44424442, // 52-55 (0x34-0x37) + 0x44444444, 0x84448444, 0x84848484, 0x88848884, // 56-59 (0x38-0x3B) + 0x88888888, 0x88888888, 0x88888888, 0x88888888 // 60-63 (0x3C-0x3F) + }; + return bitfield(s_increment_table[rate], 4*index, 4); +} + + +//------------------------------------------------- +// detune_adjustment - given a 5-bit key code +// value and a 3-bit detune parameter, return a +// 6-bit signed phase displacement; this table +// has been verified against Nuked's equations, +// but the equations are rather complicated, so +// we'll keep the simplicity of the table +//------------------------------------------------- + +inline int32_t detune_adjustment(uint32_t detune, uint32_t keycode) +{ + static uint8_t const s_detune_adjustment[32][4] = + { + { 0, 0, 1, 2 }, { 0, 0, 1, 2 }, { 0, 0, 1, 2 }, { 0, 0, 1, 2 }, + { 0, 1, 2, 2 }, { 0, 1, 2, 3 }, { 0, 1, 2, 3 }, { 0, 1, 2, 3 }, + { 0, 1, 2, 4 }, { 0, 1, 3, 4 }, { 0, 1, 3, 4 }, { 0, 1, 3, 5 }, + { 0, 2, 4, 5 }, { 0, 2, 4, 6 }, { 0, 2, 4, 6 }, { 0, 2, 5, 7 }, + { 0, 2, 5, 8 }, { 0, 3, 6, 8 }, { 0, 3, 6, 9 }, { 0, 3, 7, 10 }, + { 0, 4, 8, 11 }, { 0, 4, 8, 12 }, { 0, 4, 9, 13 }, { 0, 5, 10, 14 }, + { 0, 5, 11, 16 }, { 0, 6, 12, 17 }, { 0, 6, 13, 19 }, { 0, 7, 14, 20 }, + { 0, 8, 16, 22 }, { 0, 8, 16, 22 }, { 0, 8, 16, 22 }, { 0, 8, 16, 22 } + }; + int32_t result = s_detune_adjustment[keycode][detune & 3]; + return bitfield(detune, 2) ? -result : result; +} + + +//------------------------------------------------- +// opm_key_code_to_phase_step - converts an +// OPM concatenated block (3 bits), keycode +// (4 bits) and key fraction (6 bits) to a 0.10 +// phase step, after applying the given delta; +// this applies to OPM and OPZ, so it lives here +// in a central location +//------------------------------------------------- + +inline uint32_t opm_key_code_to_phase_step(uint32_t block_freq, int32_t delta) +{ + // The phase step is essentially the fnum in OPN-speak. To compute this table, + // we used the standard formula for computing the frequency of a note, and + // then converted that frequency to fnum using the formula documented in the + // YM2608 manual. + // + // However, the YM2608 manual describes everything in terms of a nominal 8MHz + // clock, which produces an FM clock of: + // + // 8000000 / 24(operators) / 6(prescale) = 55555Hz FM clock + // + // Whereas the descriptions for the YM2151 use a nominal 3.579545MHz clock: + // + // 3579545 / 32(operators) / 2(prescale) = 55930Hz FM clock + // + // To correct for this, the YM2608 formula was adjusted to use a clock of + // 8053920Hz, giving this equation for the fnum: + // + // fnum = (double(144) * freq * (1 << 20)) / double(8053920) / 4; + // + // Unfortunately, the computed table differs in a few spots from the data + // verified from an actual chip. The table below comes from David Viens' + // analysis, used with his permission. + static const uint32_t s_phase_step[12*64] = + { + 41568,41600,41632,41664,41696,41728,41760,41792,41856,41888,41920,41952,42016,42048,42080,42112, + 42176,42208,42240,42272,42304,42336,42368,42400,42464,42496,42528,42560,42624,42656,42688,42720, + 42784,42816,42848,42880,42912,42944,42976,43008,43072,43104,43136,43168,43232,43264,43296,43328, + 43392,43424,43456,43488,43552,43584,43616,43648,43712,43744,43776,43808,43872,43904,43936,43968, + 44032,44064,44096,44128,44192,44224,44256,44288,44352,44384,44416,44448,44512,44544,44576,44608, + 44672,44704,44736,44768,44832,44864,44896,44928,44992,45024,45056,45088,45152,45184,45216,45248, + 45312,45344,45376,45408,45472,45504,45536,45568,45632,45664,45728,45760,45792,45824,45888,45920, + 45984,46016,46048,46080,46144,46176,46208,46240,46304,46336,46368,46400,46464,46496,46528,46560, + 46656,46688,46720,46752,46816,46848,46880,46912,46976,47008,47072,47104,47136,47168,47232,47264, + 47328,47360,47392,47424,47488,47520,47552,47584,47648,47680,47744,47776,47808,47840,47904,47936, + 48032,48064,48096,48128,48192,48224,48288,48320,48384,48416,48448,48480,48544,48576,48640,48672, + 48736,48768,48800,48832,48896,48928,48992,49024,49088,49120,49152,49184,49248,49280,49344,49376, + 49440,49472,49504,49536,49600,49632,49696,49728,49792,49824,49856,49888,49952,49984,50048,50080, + 50144,50176,50208,50240,50304,50336,50400,50432,50496,50528,50560,50592,50656,50688,50752,50784, + 50880,50912,50944,50976,51040,51072,51136,51168,51232,51264,51328,51360,51424,51456,51488,51520, + 51616,51648,51680,51712,51776,51808,51872,51904,51968,52000,52064,52096,52160,52192,52224,52256, + 52384,52416,52448,52480,52544,52576,52640,52672,52736,52768,52832,52864,52928,52960,52992,53024, + 53120,53152,53216,53248,53312,53344,53408,53440,53504,53536,53600,53632,53696,53728,53792,53824, + 53920,53952,54016,54048,54112,54144,54208,54240,54304,54336,54400,54432,54496,54528,54592,54624, + 54688,54720,54784,54816,54880,54912,54976,55008,55072,55104,55168,55200,55264,55296,55360,55392, + 55488,55520,55584,55616,55680,55712,55776,55808,55872,55936,55968,56032,56064,56128,56160,56224, + 56288,56320,56384,56416,56480,56512,56576,56608,56672,56736,56768,56832,56864,56928,56960,57024, + 57120,57152,57216,57248,57312,57376,57408,57472,57536,57568,57632,57664,57728,57792,57824,57888, + 57952,57984,58048,58080,58144,58208,58240,58304,58368,58400,58464,58496,58560,58624,58656,58720, + 58784,58816,58880,58912,58976,59040,59072,59136,59200,59232,59296,59328,59392,59456,59488,59552, + 59648,59680,59744,59776,59840,59904,59936,60000,60064,60128,60160,60224,60288,60320,60384,60416, + 60512,60544,60608,60640,60704,60768,60800,60864,60928,60992,61024,61088,61152,61184,61248,61280, + 61376,61408,61472,61536,61600,61632,61696,61760,61824,61856,61920,61984,62048,62080,62144,62208, + 62272,62304,62368,62432,62496,62528,62592,62656,62720,62752,62816,62880,62944,62976,63040,63104, + 63200,63232,63296,63360,63424,63456,63520,63584,63648,63680,63744,63808,63872,63904,63968,64032, + 64096,64128,64192,64256,64320,64352,64416,64480,64544,64608,64672,64704,64768,64832,64896,64928, + 65024,65056,65120,65184,65248,65312,65376,65408,65504,65536,65600,65664,65728,65792,65856,65888, + 65984,66016,66080,66144,66208,66272,66336,66368,66464,66496,66560,66624,66688,66752,66816,66848, + 66944,66976,67040,67104,67168,67232,67296,67328,67424,67456,67520,67584,67648,67712,67776,67808, + 67904,67936,68000,68064,68128,68192,68256,68288,68384,68448,68512,68544,68640,68672,68736,68800, + 68896,68928,68992,69056,69120,69184,69248,69280,69376,69440,69504,69536,69632,69664,69728,69792, + 69920,69952,70016,70080,70144,70208,70272,70304,70400,70464,70528,70560,70656,70688,70752,70816, + 70912,70976,71040,71104,71136,71232,71264,71360,71424,71488,71552,71616,71648,71744,71776,71872, + 71968,72032,72096,72160,72192,72288,72320,72416,72480,72544,72608,72672,72704,72800,72832,72928, + 72992,73056,73120,73184,73216,73312,73344,73440,73504,73568,73632,73696,73728,73824,73856,73952, + 74080,74144,74208,74272,74304,74400,74432,74528,74592,74656,74720,74784,74816,74912,74944,75040, + 75136,75200,75264,75328,75360,75456,75488,75584,75648,75712,75776,75840,75872,75968,76000,76096, + 76224,76288,76352,76416,76448,76544,76576,76672,76736,76800,76864,76928,77024,77120,77152,77248, + 77344,77408,77472,77536,77568,77664,77696,77792,77856,77920,77984,78048,78144,78240,78272,78368, + 78464,78528,78592,78656,78688,78784,78816,78912,78976,79040,79104,79168,79264,79360,79392,79488, + 79616,79680,79744,79808,79840,79936,79968,80064,80128,80192,80256,80320,80416,80512,80544,80640, + 80768,80832,80896,80960,80992,81088,81120,81216,81280,81344,81408,81472,81568,81664,81696,81792, + 81952,82016,82080,82144,82176,82272,82304,82400,82464,82528,82592,82656,82752,82848,82880,82976 + }; + + // extract the block (octave) first + uint32_t block = bitfield(block_freq, 10, 3); + + // the keycode (bits 6-9) is "gappy", mapping 12 values over 16 in each + // octave; to correct for this, we multiply the 4-bit value by 3/4 (or + // rather subtract 1/4); note that a (invalid) value of 15 will bleed into + // the next octave -- this is confirmed + uint32_t adjusted_code = bitfield(block_freq, 6, 4) - bitfield(block_freq, 8, 2); + + // now re-insert the 6-bit fraction + int32_t eff_freq = (adjusted_code << 6) | bitfield(block_freq, 0, 6); + + // now that the gaps are removed, add the delta + eff_freq += delta; + + // handle over/underflow by adjusting the block: + if (uint32_t(eff_freq) >= 768) + { + // minimum delta is -512 (PM), so we can only underflow by 1 octave + if (eff_freq < 0) + { + eff_freq += 768; + if (block-- == 0) + return s_phase_step[0] >> 7; + } + + // maximum delta is +512+608 (PM+detune), so we can overflow by up to 2 octaves + else + { + eff_freq -= 768; + if (eff_freq >= 768) + block++, eff_freq -= 768; + if (block++ >= 7) + return s_phase_step[767]; + } + } + + // look up the phase shift for the key code, then shift by octave + return s_phase_step[eff_freq] >> (block ^ 7); +} + + +//------------------------------------------------- +// opn_lfo_pm_phase_adjustment - given the 7 most +// significant frequency number bits, plus a 3-bit +// PM depth value and a signed 5-bit raw PM value, +// return a signed PM adjustment to the frequency; +// algorithm written to match Nuked behavior +//------------------------------------------------- + +inline int32_t opn_lfo_pm_phase_adjustment(uint32_t fnum_bits, uint32_t pm_sensitivity, int32_t lfo_raw_pm) +{ + // this table encodes 2 shift values to apply to the top 7 bits + // of fnum; it is effectively a cheap multiply by a constant + // value containing 0-2 bits + static uint8_t const s_lfo_pm_shifts[8][8] = + { + { 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77 }, + { 0x77, 0x77, 0x77, 0x77, 0x72, 0x72, 0x72, 0x72 }, + { 0x77, 0x77, 0x77, 0x72, 0x72, 0x72, 0x17, 0x17 }, + { 0x77, 0x77, 0x72, 0x72, 0x17, 0x17, 0x12, 0x12 }, + { 0x77, 0x77, 0x72, 0x17, 0x17, 0x17, 0x12, 0x07 }, + { 0x77, 0x77, 0x17, 0x12, 0x07, 0x07, 0x02, 0x01 }, + { 0x77, 0x77, 0x17, 0x12, 0x07, 0x07, 0x02, 0x01 }, + { 0x77, 0x77, 0x17, 0x12, 0x07, 0x07, 0x02, 0x01 } + }; + + // look up the relevant shifts + int32_t abs_pm = (lfo_raw_pm < 0) ? -lfo_raw_pm : lfo_raw_pm; + uint32_t const shifts = s_lfo_pm_shifts[pm_sensitivity][bitfield(abs_pm, 0, 3)]; + + // compute the adjustment + int32_t adjust = (fnum_bits >> bitfield(shifts, 0, 4)) + (fnum_bits >> bitfield(shifts, 4, 4)); + if (pm_sensitivity > 5) + adjust <<= pm_sensitivity - 5; + adjust >>= 2; + + // every 16 cycles it inverts sign + return (lfo_raw_pm < 0) ? -adjust : adjust; +} + + + +//********************************************************* +// FM OPERATOR +//********************************************************* + +//------------------------------------------------- +// fm_operator - constructor +//------------------------------------------------- + +template +fm_operator::fm_operator(fm_engine_base &owner, uint32_t opoffs) : + m_choffs(0), + m_opoffs(opoffs), + m_phase(0), + m_env_attenuation(0x3ff), + m_env_state(EG_RELEASE), + m_ssg_inverted(false), + m_key_state(0), + m_keyon_live(0), + m_regs(owner.regs()), + m_owner(owner) +{ +} + + +//------------------------------------------------- +// reset - reset the channel state +//------------------------------------------------- + +template +void fm_operator::reset() +{ + // reset our data + m_phase = 0; + m_env_attenuation = 0x3ff; + m_env_state = EG_RELEASE; + m_ssg_inverted = 0; + m_key_state = 0; + m_keyon_live = 0; +} + + +//------------------------------------------------- +// save_restore - save or restore the data +//------------------------------------------------- + +template +void fm_operator::save_restore(ymfm_saved_state &state) +{ + state.save_restore(m_phase); + state.save_restore(m_env_attenuation); + state.save_restore(m_env_state); + state.save_restore(m_ssg_inverted); + state.save_restore(m_key_state); + state.save_restore(m_keyon_live); +} + + +//------------------------------------------------- +// prepare - prepare for clocking +//------------------------------------------------- + +template +bool fm_operator::prepare() +{ + // cache the data + m_regs.cache_operator_data(m_choffs, m_opoffs, m_cache); + + // clock the key state + clock_keystate(uint32_t(m_keyon_live != 0)); + m_keyon_live &= ~(1 << KEYON_CSM); + + // we're active until we're quiet after the release + return (m_env_state != (RegisterType::EG_HAS_REVERB ? EG_REVERB : EG_RELEASE) || m_env_attenuation < EG_QUIET); +} + + +//------------------------------------------------- +// clock - master clocking function +//------------------------------------------------- + +template +void fm_operator::clock(uint32_t env_counter, int32_t lfo_raw_pm) +{ + // clock the SSG-EG state (OPN/OPNA) + if (m_regs.op_ssg_eg_enable(m_opoffs)) + clock_ssg_eg_state(); + else + m_ssg_inverted = false; + + // clock the envelope if on an envelope cycle; env_counter is a x.2 value + if (bitfield(env_counter, 0, 2) == 0) + clock_envelope(env_counter >> 2); + + // clock the phase + clock_phase(lfo_raw_pm); +} + + +//------------------------------------------------- +// compute_volume - compute the 14-bit signed +// volume of this operator, given a phase +// modulation and an AM LFO offset +//------------------------------------------------- + +template +int32_t fm_operator::compute_volume(uint32_t phase, uint32_t am_offset) const +{ + // the low 10 bits of phase represents a full 2*PI period over + // the full sin wave + + // early out if the envelope is effectively off + if (m_env_attenuation > EG_QUIET) + return 0; + + // get the absolute value of the sin, as attenuation, as a 4.8 fixed point value + uint32_t sin_attenuation = m_cache.waveform[phase & (RegisterType::WAVEFORM_LENGTH - 1)]; + + // get the attenuation from the evelope generator as a 4.6 value, shifted up to 4.8 + uint32_t env_attenuation = envelope_attenuation(am_offset) << 2; + + // combine into a 5.8 value, then convert from attenuation to 13-bit linear volume + int32_t result = attenuation_to_volume((sin_attenuation & 0x7fff) + env_attenuation); + + // negate if in the negative part of the sin wave (sign bit gives 14 bits) + return bitfield(sin_attenuation, 15) ? -result : result; +} + + +//------------------------------------------------- +// compute_noise_volume - compute the 14-bit +// signed noise volume of this operator, given a +// noise input value and an AM offset +//------------------------------------------------- + +template +int32_t fm_operator::compute_noise_volume(uint32_t am_offset) const +{ + // application manual says the logarithmic transform is not applied here, so we + // just use the raw envelope attenuation, inverted (since 0 attenuation should be + // maximum), and shift it up from a 10-bit value to an 11-bit value + int32_t result = (envelope_attenuation(am_offset) ^ 0x3ff) << 1; + + // QUESTION: is AM applied still? + + // negate based on the noise state + return bitfield(m_regs.noise_state(), 0) ? -result : result; +} + + +//------------------------------------------------- +// keyonoff - signal a key on/off event +//------------------------------------------------- + +template +void fm_operator::keyonoff(uint32_t on, keyon_type type) +{ + m_keyon_live = (m_keyon_live & ~(1 << int(type))) | (bitfield(on, 0) << int(type)); +} + + +//------------------------------------------------- +// start_attack - start the attack phase; called +// when a keyon happens or when an SSG-EG cycle +// is complete and restarts +//------------------------------------------------- + +template +void fm_operator::start_attack(bool is_restart) +{ + // don't change anything if already in attack state + if (m_env_state == EG_ATTACK) + return; + m_env_state = EG_ATTACK; + + // generally not inverted at start, except if SSG-EG is enabled and + // one of the inverted modes is specified; leave this alone on a + // restart, as it is managed by the clock_ssg_eg_state() code + if (RegisterType::EG_HAS_SSG && !is_restart) + m_ssg_inverted = m_regs.op_ssg_eg_enable(m_opoffs) & bitfield(m_regs.op_ssg_eg_mode(m_opoffs), 2); + + // reset the phase when we start an attack due to a key on + // (but not when due to an SSG-EG restart except in certain cases + // managed directly by the SSG-EG code) + if (!is_restart) + m_phase = 0; + + // if the attack rate >= 62 then immediately go to max attenuation + if (m_cache.eg_rate[EG_ATTACK] >= 62) + m_env_attenuation = 0; +} + + +//------------------------------------------------- +// start_release - start the release phase; +// called when a keyoff happens +//------------------------------------------------- + +template +void fm_operator::start_release() +{ + // don't change anything if already in release state + if (m_env_state >= EG_RELEASE) + return; + m_env_state = EG_RELEASE; + + // if attenuation if inverted due to SSG-EG, snap the inverted attenuation + // as the starting point + if (RegisterType::EG_HAS_SSG && m_ssg_inverted) + { + m_env_attenuation = (0x200 - m_env_attenuation) & 0x3ff; + m_ssg_inverted = false; + } +} + + +//------------------------------------------------- +// clock_keystate - clock the keystate to match +// the incoming keystate +//------------------------------------------------- + +template +void fm_operator::clock_keystate(uint32_t keystate) +{ + assert(keystate == 0 || keystate == 1); + + // has the key changed? + if ((keystate ^ m_key_state) != 0) + { + m_key_state = keystate; + + // if the key has turned on, start the attack + if (keystate != 0) + { + // OPLL has a DP ("depress"?) state to bring the volume + // down before starting the attack + if (RegisterType::EG_HAS_DEPRESS && m_env_attenuation < 0x200) + m_env_state = EG_DEPRESS; + else + start_attack(); + } + + // otherwise, start the release + else + start_release(); + } +} + + +//------------------------------------------------- +// clock_ssg_eg_state - clock the SSG-EG state; +// should only be called if SSG-EG is enabled +//------------------------------------------------- + +template +void fm_operator::clock_ssg_eg_state() +{ + // work only happens once the attenuation crosses above 0x200 + if (!bitfield(m_env_attenuation, 9)) + return; + + // 8 SSG-EG modes: + // 000: repeat normally + // 001: run once, hold low + // 010: repeat, alternating between inverted/non-inverted + // 011: run once, hold high + // 100: inverted repeat normally + // 101: inverted run once, hold low + // 110: inverted repeat, alternating between inverted/non-inverted + // 111: inverted run once, hold high + uint32_t mode = m_regs.op_ssg_eg_mode(m_opoffs); + + // hold modes (1/3/5/7) + if (bitfield(mode, 0)) + { + // set the inverted flag to the end state (0 for modes 1/7, 1 for modes 3/5) + m_ssg_inverted = bitfield(mode, 2) ^ bitfield(mode, 1); + + // if holding, force the attenuation to the expected value once we're + // past the attack phase + if (m_env_state != EG_ATTACK) + m_env_attenuation = m_ssg_inverted ? 0x200 : 0x3ff; + } + + // continuous modes (0/2/4/6) + else + { + // toggle invert in alternating mode (even in attack state) + m_ssg_inverted ^= bitfield(mode, 1); + + // restart attack if in decay/sustain states + if (m_env_state == EG_DECAY || m_env_state == EG_SUSTAIN) + start_attack(true); + + // phase is reset to 0 in modes 0/4 + if (bitfield(mode, 1) == 0) + m_phase = 0; + } + + // in all modes, once we hit release state, attenuation is forced to maximum + if (m_env_state == EG_RELEASE) + m_env_attenuation = 0x3ff; +} + + +//------------------------------------------------- +// clock_envelope - clock the envelope state +// according to the given count +//------------------------------------------------- + +template +void fm_operator::clock_envelope(uint32_t env_counter) +{ + // handle attack->decay transitions + if (m_env_state == EG_ATTACK && m_env_attenuation == 0) + m_env_state = EG_DECAY; + + // handle decay->sustain transitions; it is important to do this immediately + // after the attack->decay transition above in the event that the sustain level + // is set to 0 (in which case we will skip right to sustain without doing any + // decay); as an example where this can be heard, check the cymbals sound + // in channel 0 of shinobi's test mode sound #5 + if (m_env_state == EG_DECAY && m_env_attenuation >= m_cache.eg_sustain) + m_env_state = EG_SUSTAIN; + + // fetch the appropriate 6-bit rate value from the cache + uint32_t rate = m_cache.eg_rate[m_env_state]; + + // compute the rate shift value; this is the shift needed to + // apply to the env_counter such that it becomes a 5.11 fixed + // point number + uint32_t rate_shift = rate >> 2; + env_counter <<= rate_shift; + + // see if the fractional part is 0; if not, it's not time to clock + if (bitfield(env_counter, 0, 11) != 0) + return; + + // determine the increment based on the non-fractional part of env_counter + uint32_t relevant_bits = bitfield(env_counter, (rate_shift <= 11) ? 11 : rate_shift, 3); + uint32_t increment = attenuation_increment(rate, relevant_bits); + + // attack is the only one that increases + if (m_env_state == EG_ATTACK) + { + // glitch means that attack rates of 62/63 don't increment if + // changed after the initial key on (where they are handled + // specially); nukeykt confirms this happens on OPM, OPN, OPL/OPLL + // at least so assuming it is true for everyone + if (rate < 62) + m_env_attenuation += (~m_env_attenuation * increment) >> 4; + } + + // all other cases are similar + else + { + // non-SSG-EG cases just apply the increment + if (!m_regs.op_ssg_eg_enable(m_opoffs)) + m_env_attenuation += increment; + + // SSG-EG only applies if less than mid-point, and then at 4x + else if (m_env_attenuation < 0x200) + m_env_attenuation += 4 * increment; + + // clamp the final attenuation + if (m_env_attenuation >= 0x400) + m_env_attenuation = 0x3ff; + + // transition from depress to attack + if (RegisterType::EG_HAS_DEPRESS && m_env_state == EG_DEPRESS && m_env_attenuation >= 0x200) + start_attack(); + + // transition from release to reverb, should switch at -18dB + if (RegisterType::EG_HAS_REVERB && m_env_state == EG_RELEASE && m_env_attenuation >= 0xc0) + m_env_state = EG_REVERB; + } +} + + +//------------------------------------------------- +// clock_phase - clock the 10.10 phase value; the +// OPN version of the logic has been verified +// against the Nuked phase generator +//------------------------------------------------- + +template +void fm_operator::clock_phase(int32_t lfo_raw_pm) +{ + // read from the cache, or recalculate if PM active + uint32_t phase_step = m_cache.phase_step; + if (phase_step == opdata_cache::PHASE_STEP_DYNAMIC) + phase_step = m_regs.compute_phase_step(m_choffs, m_opoffs, m_cache, lfo_raw_pm); + + // finally apply the step to the current phase value + m_phase += phase_step; +} + + +//------------------------------------------------- +// envelope_attenuation - return the effective +// attenuation of the envelope +//------------------------------------------------- + +template +uint32_t fm_operator::envelope_attenuation(uint32_t am_offset) const +{ + uint32_t result = m_env_attenuation >> m_cache.eg_shift; + + // invert if necessary due to SSG-EG + if (RegisterType::EG_HAS_SSG && m_ssg_inverted) + result = (0x200 - result) & 0x3ff; + + // add in LFO AM modulation + if (m_regs.op_lfo_am_enable(m_opoffs)) + result += am_offset; + + // add in total level and KSL from the cache + result += m_cache.total_level; + + // clamp to max, apply shift, and return + return std::min(result, 0x3ff); +} + + + +//********************************************************* +// FM CHANNEL +//********************************************************* + +//------------------------------------------------- +// fm_channel - constructor +//------------------------------------------------- + +template +fm_channel::fm_channel(fm_engine_base &owner, uint32_t choffs) : + m_choffs(choffs), + m_feedback{ 0, 0 }, + m_feedback_in(0), + m_op{ nullptr, nullptr, nullptr, nullptr }, + m_regs(owner.regs()), + m_owner(owner) +{ +} + + +//------------------------------------------------- +// reset - reset the channel state +//------------------------------------------------- + +template +void fm_channel::reset() +{ + // reset our data + m_feedback[0] = m_feedback[1] = 0; + m_feedback_in = 0; +} + + +//------------------------------------------------- +// save_restore - save or restore the data +//------------------------------------------------- + +template +void fm_channel::save_restore(ymfm_saved_state &state) +{ + state.save_restore(m_feedback[0]); + state.save_restore(m_feedback[1]); + state.save_restore(m_feedback_in); +} + + +//------------------------------------------------- +// keyonoff - signal key on/off to our operators +//------------------------------------------------- + +template +void fm_channel::keyonoff(uint32_t states, keyon_type type, uint32_t chnum) +{ + for (uint32_t opnum = 0; opnum < array_size(m_op); opnum++) + if (m_op[opnum] != nullptr) + m_op[opnum]->keyonoff(bitfield(states, opnum), type); + + if (debug::LOG_KEYON_EVENTS && ((debug::GLOBAL_FM_CHANNEL_MASK >> chnum) & 1) != 0) + for (uint32_t opnum = 0; opnum < array_size(m_op); opnum++) + if (m_op[opnum] != nullptr) + debug::log_keyon("%c%s\n", bitfield(states, opnum) ? '+' : '-', m_regs.log_keyon(m_choffs, m_op[opnum]->opoffs()).c_str()); +} + + +//------------------------------------------------- +// prepare - prepare for clocking +//------------------------------------------------- + +template +bool fm_channel::prepare() +{ + uint32_t active_mask = 0; + + // prepare all operators and determine if they are active + for (uint32_t opnum = 0; opnum < array_size(m_op); opnum++) + if (m_op[opnum] != nullptr) + if (m_op[opnum]->prepare()) + active_mask |= 1 << opnum; + + return (active_mask != 0); +} + + +//------------------------------------------------- +// clock - master clock of all operators +//------------------------------------------------- + +template +void fm_channel::clock(uint32_t env_counter, int32_t lfo_raw_pm) +{ + // clock the feedback through + m_feedback[0] = m_feedback[1]; + m_feedback[1] = m_feedback_in; + + for (uint32_t opnum = 0; opnum < array_size(m_op); opnum++) + if (m_op[opnum] != nullptr) + m_op[opnum]->clock(env_counter, lfo_raw_pm); + +/* +useful temporary code for envelope debugging +if (m_choffs == 0x101) +{ + for (uint32_t opnum = 0; opnum < array_size(m_op); opnum++) + { + auto &op = *m_op[((opnum & 1) << 1) | ((opnum >> 1) & 1)]; + printf(" %c%03X%c%c ", + "PADSRV"[op.debug_eg_state()], + op.debug_eg_attenuation(), + op.debug_ssg_inverted() ? '-' : '+', + m_regs.op_ssg_eg_enable(op.opoffs()) ? '0' + m_regs.op_ssg_eg_mode(op.opoffs()) : ' '); + } +printf(" -- "); +} +*/ +} + + +//------------------------------------------------- +// output_2op - combine 4 operators according to +// the specified algorithm, returning a sum +// according to the rshift and clipmax parameters, +// which vary between different implementations +//------------------------------------------------- + +template +void fm_channel::output_2op(output_data &output, uint32_t rshift, int32_t clipmax) const +{ + // The first 2 operators should be populated + assert(m_op[0] != nullptr); + assert(m_op[1] != nullptr); + + // AM amount is the same across all operators; compute it once + uint32_t am_offset = m_regs.lfo_am_offset(m_choffs); + + // operator 1 has optional self-feedback + int32_t opmod = 0; + uint32_t feedback = m_regs.ch_feedback(m_choffs); + if (feedback != 0) + opmod = (m_feedback[0] + m_feedback[1]) >> (10 - feedback); + + // compute the 14-bit volume/value of operator 1 and update the feedback + int32_t op1value = m_feedback_in = m_op[0]->compute_volume(m_op[0]->phase() + opmod, am_offset); + + // now that the feedback has been computed, skip the rest if all volumes + // are clear; no need to do all this work for nothing + if (m_regs.ch_output_any(m_choffs) == 0) + return; + + // Algorithms for two-operator case: + // 0: O1 -> O2 -> out + // 1: (O1 + O2) -> out + int32_t result; + if (bitfield(m_regs.ch_algorithm(m_choffs), 0) == 0) + { + // some OPL chips use the previous sample for modulation instead of + // the current sample + opmod = (RegisterType::MODULATOR_DELAY ? m_feedback[1] : op1value) >> 1; + result = m_op[1]->compute_volume(m_op[1]->phase() + opmod, am_offset) >> rshift; + } + else + { + result = (RegisterType::MODULATOR_DELAY ? m_feedback[1] : op1value) >> rshift; + result += m_op[1]->compute_volume(m_op[1]->phase(), am_offset) >> rshift; + int32_t clipmin = -clipmax - 1; + result = clamp(result, clipmin, clipmax); + } + + // add to the output + add_to_output(m_choffs, output, result); +} + + +//------------------------------------------------- +// output_4op - combine 4 operators according to +// the specified algorithm, returning a sum +// according to the rshift and clipmax parameters, +// which vary between different implementations +//------------------------------------------------- + +template +void fm_channel::output_4op(output_data &output, uint32_t rshift, int32_t clipmax) const +{ + // all 4 operators should be populated + assert(m_op[0] != nullptr); + assert(m_op[1] != nullptr); + assert(m_op[2] != nullptr); + assert(m_op[3] != nullptr); + + // AM amount is the same across all operators; compute it once + uint32_t am_offset = m_regs.lfo_am_offset(m_choffs); + + // operator 1 has optional self-feedback + int32_t opmod = 0; + uint32_t feedback = m_regs.ch_feedback(m_choffs); + if (feedback != 0) + opmod = (m_feedback[0] + m_feedback[1]) >> (10 - feedback); + + // compute the 14-bit volume/value of operator 1 and update the feedback + int32_t op1value = m_feedback_in = m_op[0]->compute_volume(m_op[0]->phase() + opmod, am_offset); + + // now that the feedback has been computed, skip the rest if all volumes + // are clear; no need to do all this work for nothing + if (m_regs.ch_output_any(m_choffs) == 0) + return; + + // OPM/OPN offer 8 different connection algorithms for 4 operators, + // and OPL3 offers 4 more, which we designate here as 8-11. + // + // The operators are computed in order, with the inputs pulled from + // an array of values (opout) that is populated as we go: + // 0 = 0 + // 1 = O1 + // 2 = O2 + // 3 = O3 + // 4 = (O4) + // 5 = O1+O2 + // 6 = O1+O3 + // 7 = O2+O3 + // + // The s_algorithm_ops table describes the inputs and outputs of each + // algorithm as follows: + // + // ---------x use opout[x] as operator 2 input + // ------xxx- use opout[x] as operator 3 input + // ---xxx---- use opout[x] as operator 4 input + // --x------- include opout[1] in final sum + // -x-------- include opout[2] in final sum + // x--------- include opout[3] in final sum + #define ALGORITHM(op2in, op3in, op4in, op1out, op2out, op3out) \ + ((op2in) | ((op3in) << 1) | ((op4in) << 4) | ((op1out) << 7) | ((op2out) << 8) | ((op3out) << 9)) + static uint16_t const s_algorithm_ops[8+4] = + { + ALGORITHM(1,2,3, 0,0,0), // 0: O1 -> O2 -> O3 -> O4 -> out (O4) + ALGORITHM(0,5,3, 0,0,0), // 1: (O1 + O2) -> O3 -> O4 -> out (O4) + ALGORITHM(0,2,6, 0,0,0), // 2: (O1 + (O2 -> O3)) -> O4 -> out (O4) + ALGORITHM(1,0,7, 0,0,0), // 3: ((O1 -> O2) + O3) -> O4 -> out (O4) + ALGORITHM(1,0,3, 0,1,0), // 4: ((O1 -> O2) + (O3 -> O4)) -> out (O2+O4) + ALGORITHM(1,1,1, 0,1,1), // 5: ((O1 -> O2) + (O1 -> O3) + (O1 -> O4)) -> out (O2+O3+O4) + ALGORITHM(1,0,0, 0,1,1), // 6: ((O1 -> O2) + O3 + O4) -> out (O2+O3+O4) + ALGORITHM(0,0,0, 1,1,1), // 7: (O1 + O2 + O3 + O4) -> out (O1+O2+O3+O4) + ALGORITHM(1,2,3, 0,0,0), // 8: O1 -> O2 -> O3 -> O4 -> out (O4) [same as 0] + ALGORITHM(0,2,3, 1,0,0), // 9: (O1 + (O2 -> O3 -> O4)) -> out (O1+O4) [unique] + ALGORITHM(1,0,3, 0,1,0), // 10: ((O1 -> O2) + (O3 -> O4)) -> out (O2+O4) [same as 4] + ALGORITHM(0,2,0, 1,0,1) // 11: (O1 + (O2 -> O3) + O4) -> out (O1+O3+O4) [unique] + }; + uint32_t algorithm_ops = s_algorithm_ops[m_regs.ch_algorithm(m_choffs)]; + + // populate the opout table + int16_t opout[8]; + opout[0] = 0; + opout[1] = op1value; + + // compute the 14-bit volume/value of operator 2 + opmod = opout[bitfield(algorithm_ops, 0, 1)] >> 1; + opout[2] = m_op[1]->compute_volume(m_op[1]->phase() + opmod, am_offset); + opout[5] = opout[1] + opout[2]; + + // compute the 14-bit volume/value of operator 3 + opmod = opout[bitfield(algorithm_ops, 1, 3)] >> 1; + opout[3] = m_op[2]->compute_volume(m_op[2]->phase() + opmod, am_offset); + opout[6] = opout[1] + opout[3]; + opout[7] = opout[2] + opout[3]; + + // compute the 14-bit volume/value of operator 4; this could be a noise + // value on the OPM; all algorithms consume OP4 output at a minimum + int32_t result; + if (m_regs.noise_enable() && m_choffs == 7) + result = m_op[3]->compute_noise_volume(am_offset); + else + { + opmod = opout[bitfield(algorithm_ops, 4, 3)] >> 1; + result = m_op[3]->compute_volume(m_op[3]->phase() + opmod, am_offset); + } + result >>= rshift; + + // optionally add OP1, OP2, OP3 + int32_t clipmin = -clipmax - 1; + if (bitfield(algorithm_ops, 7) != 0) + result = clamp(result + (opout[1] >> rshift), clipmin, clipmax); + if (bitfield(algorithm_ops, 8) != 0) + result = clamp(result + (opout[2] >> rshift), clipmin, clipmax); + if (bitfield(algorithm_ops, 9) != 0) + result = clamp(result + (opout[3] >> rshift), clipmin, clipmax); + + // add to the output + add_to_output(m_choffs, output, result); +} + + +//------------------------------------------------- +// output_rhythm_ch6 - special case output +// computation for OPL channel 6 in rhythm mode, +// which outputs a Bass Drum instrument +//------------------------------------------------- + +template +void fm_channel::output_rhythm_ch6(output_data &output, uint32_t rshift, int32_t clipmax) const +{ + // AM amount is the same across all operators; compute it once + uint32_t am_offset = m_regs.lfo_am_offset(m_choffs); + + // Bass Drum: this uses operators 12 and 15 (i.e., channel 6) + // in an almost-normal way, except that if the algorithm is 1, + // the first operator is ignored instead of added in + + // operator 1 has optional self-feedback + int32_t opmod = 0; + uint32_t feedback = m_regs.ch_feedback(m_choffs); + if (feedback != 0) + opmod = (m_feedback[0] + m_feedback[1]) >> (10 - feedback); + + // compute the 14-bit volume/value of operator 1 and update the feedback + int32_t opout1 = m_feedback_in = m_op[0]->compute_volume(m_op[0]->phase() + opmod, am_offset); + + // compute the 14-bit volume/value of operator 2, which is the result + opmod = bitfield(m_regs.ch_algorithm(m_choffs), 0) ? 0 : (opout1 >> 1); + int32_t result = m_op[1]->compute_volume(m_op[1]->phase() + opmod, am_offset) >> rshift; + + // add to the output + add_to_output(m_choffs, output, result * 2); +} + + +//------------------------------------------------- +// output_rhythm_ch7 - special case output +// computation for OPL channel 7 in rhythm mode, +// which outputs High Hat and Snare Drum +// instruments +//------------------------------------------------- + +template +void fm_channel::output_rhythm_ch7(uint32_t phase_select, output_data &output, uint32_t rshift, int32_t clipmax) const +{ + // AM amount is the same across all operators; compute it once + uint32_t am_offset = m_regs.lfo_am_offset(m_choffs); + uint32_t noise_state = bitfield(m_regs.noise_state(), 0); + + // High Hat: this uses the envelope from operator 13 (channel 7), + // and a combination of noise and the operator 13/17 phase select + // to compute the phase + uint32_t phase = (phase_select << 9) | (0xd0 >> (2 * (noise_state ^ phase_select))); + int32_t result = m_op[0]->compute_volume(phase, am_offset) >> rshift; + + // Snare Drum: this uses the envelope from operator 16 (channel 7), + // and a combination of noise and operator 13 phase to pick a phase + uint32_t op13phase = m_op[0]->phase(); + phase = (0x100 << bitfield(op13phase, 8)) ^ (noise_state << 8); + result += m_op[1]->compute_volume(phase, am_offset) >> rshift; + result = clamp(result, -clipmax - 1, clipmax); + + // add to the output + add_to_output(m_choffs, output, result * 2); +} + + +//------------------------------------------------- +// output_rhythm_ch8 - special case output +// computation for OPL channel 8 in rhythm mode, +// which outputs Tom Tom and Top Cymbal instruments +//------------------------------------------------- + +template +void fm_channel::output_rhythm_ch8(uint32_t phase_select, output_data &output, uint32_t rshift, int32_t clipmax) const +{ + // AM amount is the same across all operators; compute it once + uint32_t am_offset = m_regs.lfo_am_offset(m_choffs); + + // Tom Tom: this is just a single operator processed normally + int32_t result = m_op[0]->compute_volume(m_op[0]->phase(), am_offset) >> rshift; + + // Top Cymbal: this uses the envelope from operator 17 (channel 8), + // and the operator 13/17 phase select to compute the phase + uint32_t phase = 0x100 | (phase_select << 9); + result += m_op[1]->compute_volume(phase, am_offset) >> rshift; + result = clamp(result, -clipmax - 1, clipmax); + + // add to the output + add_to_output(m_choffs, output, result * 2); +} + + + +//********************************************************* +// FM ENGINE BASE +//********************************************************* + +//------------------------------------------------- +// fm_engine_base - constructor +//------------------------------------------------- + +template +fm_engine_base::fm_engine_base(ymfm_interface &intf) : + m_intf(intf), + m_env_counter(0), + m_status(0), + m_clock_prescale(RegisterType::DEFAULT_PRESCALE), + m_irq_mask(STATUS_TIMERA | STATUS_TIMERB), + m_irq_state(0), + m_timer_running{0,0}, + m_total_clocks(0), + m_active_channels(ALL_CHANNELS), + m_modified_channels(ALL_CHANNELS), + m_prepare_count(0) +{ + // inform the interface of their engine + m_intf.m_engine = this; + + // create the channels + for (uint32_t chnum = 0; chnum < CHANNELS; chnum++) + m_channel[chnum] = std::make_unique>(*this, RegisterType::channel_offset(chnum)); + + // create the operators + for (uint32_t opnum = 0; opnum < OPERATORS; opnum++) + m_operator[opnum] = std::make_unique>(*this, RegisterType::operator_offset(opnum)); + +#if (YMFM_DEBUG_LOG_WAVFILES) + for (uint32_t chnum = 0; chnum < CHANNELS; chnum++) + m_wavfile[chnum].set_index(chnum); +#endif + + // do the initial operator assignment + assign_operators(); +} + + +//------------------------------------------------- +// reset - reset the overall state +//------------------------------------------------- + +template +void fm_engine_base::reset() +{ + // reset all status bits + set_reset_status(0, 0xff); + + // register type-specific initialization + m_regs.reset(); + + // explicitly write to the mode register since it has side-effects + // QUESTION: old cores initialize this to 0x30 -- who is right? + write(RegisterType::REG_MODE, 0); + + // reset the channels + for (auto &chan : m_channel) + chan->reset(); + + // reset the operators + for (auto &op : m_operator) + op->reset(); +} + + +//------------------------------------------------- +// save_restore - save or restore the data +//------------------------------------------------- + +template +void fm_engine_base::save_restore(ymfm_saved_state &state) +{ + // save our data + state.save_restore(m_env_counter); + state.save_restore(m_status); + state.save_restore(m_clock_prescale); + state.save_restore(m_irq_mask); + state.save_restore(m_irq_state); + state.save_restore(m_timer_running[0]); + state.save_restore(m_timer_running[1]); + state.save_restore(m_total_clocks); + + // save the register/family data + m_regs.save_restore(state); + + // save channel data + for (uint32_t chnum = 0; chnum < CHANNELS; chnum++) + m_channel[chnum]->save_restore(state); + + // save operator data + for (uint32_t opnum = 0; opnum < OPERATORS; opnum++) + m_operator[opnum]->save_restore(state); + + // invalidate any caches + invalidate_caches(); +} + + +//------------------------------------------------- +// clock - iterate over all channels, clocking +// them forward one step +//------------------------------------------------- + +template +uint32_t fm_engine_base::clock(uint32_t chanmask) +{ + // update the clock counter + m_total_clocks++; + + // if something was modified, prepare + // also prepare every 4k samples to catch ending notes + if (m_modified_channels != 0 || m_prepare_count++ >= 4096) + { + // reassign operators to channels if dynamic + if (RegisterType::DYNAMIC_OPS) + assign_operators(); + + // call each channel to prepare + m_active_channels = 0; + for (uint32_t chnum = 0; chnum < CHANNELS; chnum++) + if (bitfield(chanmask, chnum)) + if (m_channel[chnum]->prepare()) + m_active_channels |= 1 << chnum; + + // reset the modified channels and prepare count + m_modified_channels = m_prepare_count = 0; + } + + // if the envelope clock divider is 1, just increment by 4; + // otherwise, increment by 1 and manually wrap when we reach the divide count + if (RegisterType::EG_CLOCK_DIVIDER == 1) + m_env_counter += 4; + else if (bitfield(++m_env_counter, 0, 2) == RegisterType::EG_CLOCK_DIVIDER) + m_env_counter += 4 - RegisterType::EG_CLOCK_DIVIDER; + + // clock the noise generator + int32_t lfo_raw_pm = m_regs.clock_noise_and_lfo(); + + // now update the state of all the channels and operators + for (uint32_t chnum = 0; chnum < CHANNELS; chnum++) + if (bitfield(chanmask, chnum)) + m_channel[chnum]->clock(m_env_counter, lfo_raw_pm); + + // return the envelope counter as it is used to clock ADPCM-A + return m_env_counter; +} + + +//------------------------------------------------- +// output - compute a sum over the relevant +// channels +//------------------------------------------------- + +template +void fm_engine_base::output(output_data &output, uint32_t rshift, int32_t clipmax, uint32_t chanmask) const +{ + // mask out some channels for debug purposes + chanmask &= debug::GLOBAL_FM_CHANNEL_MASK; + + // mask out inactive channels + if (!YMFM_DEBUG_LOG_WAVFILES) + chanmask &= m_active_channels; + + // handle the rhythm case, where some of the operators are dedicated + // to percussion (this is an OPL-specific feature) + if (m_regs.rhythm_enable()) + { + // we don't support the OPM noise channel here; ensure it is off + assert(m_regs.noise_enable() == 0); + + // precompute the operator 13+17 phase selection value + uint32_t op13phase = m_operator[13]->phase(); + uint32_t op17phase = m_operator[17]->phase(); + uint32_t phase_select = (bitfield(op13phase, 2) ^ bitfield(op13phase, 7)) | bitfield(op13phase, 3) | (bitfield(op17phase, 5) ^ bitfield(op17phase, 3)); + + // sum over all the desired channels + for (uint32_t chnum = 0; chnum < CHANNELS; chnum++) + if (bitfield(chanmask, chnum)) + { +#if (YMFM_DEBUG_LOG_WAVFILES) + auto reference = output; +#endif + if (chnum == 6) + m_channel[chnum]->output_rhythm_ch6(output, rshift, clipmax); + else if (chnum == 7) + m_channel[chnum]->output_rhythm_ch7(phase_select, output, rshift, clipmax); + else if (chnum == 8) + m_channel[chnum]->output_rhythm_ch8(phase_select, output, rshift, clipmax); + else if (m_channel[chnum]->is4op()) + m_channel[chnum]->output_4op(output, rshift, clipmax); + else + m_channel[chnum]->output_2op(output, rshift, clipmax); +#if (YMFM_DEBUG_LOG_WAVFILES) + m_wavfile[chnum].add(output, reference); +#endif + } + } + else + { + // sum over all the desired channels + for (uint32_t chnum = 0; chnum < CHANNELS; chnum++) + if (bitfield(chanmask, chnum)) + { +#if (YMFM_DEBUG_LOG_WAVFILES) + auto reference = output; +#endif + if (m_channel[chnum]->is4op()) + m_channel[chnum]->output_4op(output, rshift, clipmax); + else + m_channel[chnum]->output_2op(output, rshift, clipmax); +#if (YMFM_DEBUG_LOG_WAVFILES) + m_wavfile[chnum].add(output, reference); +#endif + } + } +} + + +//------------------------------------------------- +// write - handle writes to the OPN registers +//------------------------------------------------- + +template +void fm_engine_base::write(uint16_t regnum, uint8_t data) +{ + debug::log_fm_write("%03X = %02X\n", regnum, data); + + // special case: writes to the mode register can impact IRQs; + // schedule these writes to ensure ordering with timers + if (regnum == RegisterType::REG_MODE) + { + m_intf.ymfm_sync_mode_write(data); + return; + } + + // for now just mark all channels as modified + m_modified_channels = ALL_CHANNELS; + + // most writes are passive, consumed only when needed + uint32_t keyon_channel; + uint32_t keyon_opmask; + if (m_regs.write(regnum, data, keyon_channel, keyon_opmask)) + { + // handle writes to the keyon register(s) + if (keyon_channel < CHANNELS) + { + // normal channel on/off + m_channel[keyon_channel]->keyonoff(keyon_opmask, KEYON_NORMAL, keyon_channel); + } + else if (CHANNELS >= 9 && keyon_channel == RegisterType::RHYTHM_CHANNEL) + { + // special case for the OPL rhythm channels + m_channel[6]->keyonoff(bitfield(keyon_opmask, 4) ? 3 : 0, KEYON_RHYTHM, 6); + m_channel[7]->keyonoff(bitfield(keyon_opmask, 0) | (bitfield(keyon_opmask, 3) << 1), KEYON_RHYTHM, 7); + m_channel[8]->keyonoff(bitfield(keyon_opmask, 2) | (bitfield(keyon_opmask, 1) << 1), KEYON_RHYTHM, 8); + } + } +} + + +//------------------------------------------------- +// status - return the current state of the +// status flags +//------------------------------------------------- + +template +uint8_t fm_engine_base::status() const +{ + return m_status & ~STATUS_BUSY & ~m_regs.status_mask(); +} + + +//------------------------------------------------- +// assign_operators - get the current mapping of +// operators to channels and assign them all +//------------------------------------------------- + +template +void fm_engine_base::assign_operators() +{ + typename RegisterType::operator_mapping map; + m_regs.operator_map(map); + + for (uint32_t chnum = 0; chnum < CHANNELS; chnum++) + for (uint32_t index = 0; index < 4; index++) + { + uint32_t opnum = bitfield(map.chan[chnum], 8 * index, 8); + m_channel[chnum]->assign(index, (opnum == 0xff) ? nullptr : m_operator[opnum].get()); + } +} + + +//------------------------------------------------- +// update_timer - update the state of the given +// timer +//------------------------------------------------- + +template +void fm_engine_base::update_timer(uint32_t tnum, uint32_t enable, int32_t delta_clocks) +{ + uint32_t subtract = !!(tnum >> 15); + tnum &= 0x7fff; + + // if the timer is live, but not currently enabled, set the timer + if (enable && !m_timer_running[tnum]) + { + // period comes from the registers, and is different for each + uint32_t period = (tnum == 0) ? (1024 - subtract - m_regs.timer_a_value()) : 16 * (256 - subtract - m_regs.timer_b_value()); + + // caller can also specify a delta to account for other effects + period += delta_clocks; + + // reset it + m_intf.ymfm_set_timer(tnum, period * OPERATORS * m_clock_prescale); + m_timer_running[tnum] = 1; + } + + // if the timer is not live, ensure it is not enabled + else if (!enable) + { + m_intf.ymfm_set_timer(tnum, -1); + m_timer_running[tnum] = 0; + } +} + + +//------------------------------------------------- +// engine_timer_expired - timer has expired - signal +// status and possibly IRQs +//------------------------------------------------- + +template +void fm_engine_base::engine_timer_expired(uint32_t tnum) +{ + // update status + if (tnum == 0 && m_regs.enable_timer_a()) + set_reset_status(STATUS_TIMERA, 0); + else if (tnum == 1 && m_regs.enable_timer_b()) + set_reset_status(STATUS_TIMERB, 0); + + // if timer A fired in CSM mode, trigger CSM on all relevant channels + if (tnum == 0 && m_regs.csm()) + for (uint32_t chnum = 0; chnum < CHANNELS; chnum++) + if (bitfield(RegisterType::CSM_TRIGGER_MASK, chnum)) + { + m_channel[chnum]->keyonoff(1, KEYON_CSM, chnum); + m_modified_channels |= 1 << chnum; + } + + // Make sure the array does not go out of bounds to keep gcc happy + if ((tnum < 2) || (sizeof(m_timer_running) > (2 * sizeof(uint8_t)))) { + // reset + m_timer_running[tnum] = false; + } + update_timer(tnum, 1, 0); +} + + +//------------------------------------------------- +// check_interrupts - check the interrupt sources +// for interrupts +//------------------------------------------------- + +template +void fm_engine_base::engine_check_interrupts() +{ + // update the state + uint8_t old_state = m_irq_state; + m_irq_state = ((m_status & m_irq_mask & ~m_regs.status_mask()) != 0); + + // set the IRQ status bit + if (m_irq_state) + m_status |= STATUS_IRQ; + else + m_status &= ~STATUS_IRQ; + + // if changed, signal the new state + if (old_state != m_irq_state) + m_intf.ymfm_update_irq(m_irq_state ? true : false); +} + + +//------------------------------------------------- +// engine_mode_write - handle a mode register write +// via timer callback +//------------------------------------------------- + +template +void fm_engine_base::engine_mode_write(uint8_t data) +{ + // mark all channels as modified + m_modified_channels = ALL_CHANNELS; + + // actually write the mode register now + uint32_t dummy1, dummy2; + m_regs.write(RegisterType::REG_MODE, data, dummy1, dummy2); + + // reset IRQ status -- when written, all other bits are ignored + // QUESTION: should this maybe just reset the IRQ bit and not all the bits? + // That is, check_interrupts would only set, this would only clear? + if (m_regs.irq_reset()) + set_reset_status(0, 0x78); + else + { + // reset timer status + uint8_t reset_mask = 0; + if (m_regs.reset_timer_b()) + reset_mask |= RegisterType::STATUS_TIMERB; + if (m_regs.reset_timer_a()) + reset_mask |= RegisterType::STATUS_TIMERA; + set_reset_status(0, reset_mask); + + // load timers; note that timer B gets a small negative adjustment because + // the *16 multiplier is free-running, so the first tick of the clock + // is a bit shorter + // OPL3 begins counting immediately instead of after the first period is over. + // We use bit 15 of the timer number on those chips to inform that this was a + // control register write, and to therefore, subtract 1 counting cycle. + update_timer(1 | m_intf.get_special_flags(), m_regs.load_timer_b(), -(m_total_clocks & 15)); + update_timer(0 | m_intf.get_special_flags(), m_regs.load_timer_a(), 0); + } +} + +} diff --git a/src/sound/ymfm/ymfm_misc.cpp b/src/sound/ymfm/ymfm_misc.cpp new file mode 100644 index 000000000..fd0575f55 --- /dev/null +++ b/src/sound/ymfm/ymfm_misc.cpp @@ -0,0 +1,175 @@ +// BSD 3-Clause License +// +// Copyright (c) 2021, Aaron Giles +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// 1. Redistributions of source code must retain the above copyright notice, this +// list of conditions and the following disclaimer. +// +// 2. Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// 3. Neither the name of the copyright holder nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#include "ymfm_misc.h" + +namespace ymfm +{ + +//********************************************************* +// YM2149 +//********************************************************* + +//------------------------------------------------- +// ym2149 - constructor +//------------------------------------------------- + +ym2149::ym2149(ymfm_interface &intf) : + m_address(0), + m_ssg(intf) +{ +} + + +//------------------------------------------------- +// reset - reset the system +//------------------------------------------------- + +void ym2149::reset() +{ + // reset the engines + m_ssg.reset(); +} + + +//------------------------------------------------- +// save_restore - save or restore the data +//------------------------------------------------- + +void ym2149::save_restore(ymfm_saved_state &state) +{ + state.save_restore(m_address); + m_ssg.save_restore(state); +} + + +//------------------------------------------------- +// read_data - read the data register +//------------------------------------------------- + +uint8_t ym2149::read_data() +{ + return m_ssg.read(m_address & 0x0f); +} + + +//------------------------------------------------- +// read - handle a read from the device +//------------------------------------------------- + +uint8_t ym2149::read(uint32_t offset) +{ + uint8_t result = 0xff; + switch (offset & 3) // BC2,BC1 + { + case 0: // inactive + break; + + case 1: // address + break; + + case 2: // inactive + break; + + case 3: // read + result = read_data(); + break; + } + return result; +} + + +//------------------------------------------------- +// write_address - handle a write to the address +// register +//------------------------------------------------- + +void ym2149::write_address(uint8_t data) +{ + // just set the address + m_address = data; +} + + +//------------------------------------------------- +// write - handle a write to the register +// interface +//------------------------------------------------- + +void ym2149::write_data(uint8_t data) +{ + m_ssg.write(m_address & 0x0f, data); +} + + +//------------------------------------------------- +// write - handle a write to the register +// interface +//------------------------------------------------- + +void ym2149::write(uint32_t offset, uint8_t data) +{ + switch (offset & 3) // BC2,BC1 + { + case 0: // address + write_address(data); + break; + + case 1: // inactive + break; + + case 2: // write + write_data(data); + break; + + case 3: // address + write_address(data); + break; + } +} + + +//------------------------------------------------- +// generate - generate samples of SSG sound +//------------------------------------------------- + +void ym2149::generate(output_data *output, uint32_t numsamples) +{ + for (uint32_t samp = 0; samp < numsamples; samp++, output++) + { + // clock the SSG + m_ssg.clock(); + + // YM2149 keeps the three SSG outputs independent + m_ssg.output(*output); + } +} + +} diff --git a/src/sound/ymfm/ymfm_misc.h b/src/sound/ymfm/ymfm_misc.h new file mode 100644 index 000000000..628d128f6 --- /dev/null +++ b/src/sound/ymfm/ymfm_misc.h @@ -0,0 +1,93 @@ +// BSD 3-Clause License +// +// Copyright (c) 2021, Aaron Giles +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// 1. Redistributions of source code must retain the above copyright notice, this +// list of conditions and the following disclaimer. +// +// 2. Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// 3. Neither the name of the copyright holder nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#ifndef YMFM_MISC_H +#define YMFM_MISC_H + +#pragma once + +#include "ymfm.h" +#include "ymfm_adpcm.h" +#include "ymfm_ssg.h" + +namespace ymfm +{ + +//********************************************************* +// SSG IMPLEMENTATION CLASSES +//********************************************************* + +// ======================> ym2149 + +// ym2149 is just an SSG with no FM part, but we expose FM-like parts so that it +// integrates smoothly with everything else; they just don't do anything +class ym2149 +{ +public: + static constexpr uint32_t OUTPUTS = ssg_engine::OUTPUTS; + static constexpr uint32_t SSG_OUTPUTS = ssg_engine::OUTPUTS; + using output_data = ymfm_output; + + // constructor + ym2149(ymfm_interface &intf); + + // configuration + void ssg_override(ssg_override &intf) { m_ssg.override(intf); } + + // reset + void reset(); + + // save/restore + void save_restore(ymfm_saved_state &state); + + // pass-through helpers + uint32_t sample_rate(uint32_t input_clock) const { return input_clock / ssg_engine::CLOCK_DIVIDER / 8; } + + // read access + uint8_t read_data(); + uint8_t read(uint32_t offset); + + // write access + void write_address(uint8_t data); + void write_data(uint8_t data); + void write(uint32_t offset, uint8_t data); + + // generate one sample of sound + void generate(output_data *output, uint32_t numsamples = 1); + +protected: + // internal state + uint8_t m_address; // address register + ssg_engine m_ssg; // SSG engine +}; + +} + +#endif // YMFM_MISC_H diff --git a/src/sound/ymfm/ymfm_opl.cpp b/src/sound/ymfm/ymfm_opl.cpp new file mode 100644 index 000000000..bb91c5dc0 --- /dev/null +++ b/src/sound/ymfm/ymfm_opl.cpp @@ -0,0 +1,2220 @@ +// BSD 3-Clause License +// +// Copyright (c) 2021, Aaron Giles +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// 1. Redistributions of source code must retain the above copyright notice, this +// list of conditions and the following disclaimer. +// +// 2. Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// 3. Neither the name of the copyright holder nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#include "ymfm_opl.h" +#include "ymfm_fm.ipp" + +namespace ymfm +{ + +//------------------------------------------------- +// opl_key_scale_atten - converts an +// OPL concatenated block (3 bits) and fnum +// (10 bits) into an attenuation offset; values +// here are for 6dB/octave, in 0.75dB units +// (matching total level LSB) +//------------------------------------------------- + +inline uint32_t opl_key_scale_atten(uint32_t block, uint32_t fnum_4msb) +{ + // this table uses the top 4 bits of FNUM and are the maximal values + // (for when block == 7). Values for other blocks can be computed by + // subtracting 8 for each block below 7. + static uint8_t const fnum_to_atten[16] = { 0,24,32,37,40,43,45,47,48,50,51,52,53,54,55,56 }; + int32_t result = fnum_to_atten[fnum_4msb] - 8 * (block ^ 7); + return std::max(0, result); +} + + +//********************************************************* +// OPL REGISTERS +//********************************************************* + +//------------------------------------------------- +// opl_registers_base - constructor +//------------------------------------------------- + +template +opl_registers_base::opl_registers_base() : + m_lfo_am_counter(0), + m_lfo_pm_counter(0), + m_noise_lfsr(1), + m_lfo_am(0) +{ + // create these pointers to appease overzealous compilers checking array + // bounds in unreachable code (looking at you, clang) + uint16_t *wf0 = &m_waveform[0][0]; + uint16_t *wf1 = &m_waveform[1 % WAVEFORMS][0]; + uint16_t *wf2 = &m_waveform[2 % WAVEFORMS][0]; + uint16_t *wf3 = &m_waveform[3 % WAVEFORMS][0]; + uint16_t *wf4 = &m_waveform[4 % WAVEFORMS][0]; + uint16_t *wf5 = &m_waveform[5 % WAVEFORMS][0]; + uint16_t *wf6 = &m_waveform[6 % WAVEFORMS][0]; + uint16_t *wf7 = &m_waveform[7 % WAVEFORMS][0]; + + // create the waveforms + for (uint32_t index = 0; index < WAVEFORM_LENGTH; index++) + wf0[index] = abs_sin_attenuation(index) | (bitfield(index, 9) << 15); + + if (WAVEFORMS >= 4) + { + uint16_t zeroval = wf0[0]; + for (uint32_t index = 0; index < WAVEFORM_LENGTH; index++) + { + wf1[index] = bitfield(index, 9) ? zeroval : wf0[index]; + wf2[index] = wf0[index] & 0x7fff; + wf3[index] = bitfield(index, 8) ? zeroval : (wf0[index] & 0x7fff); + if (WAVEFORMS >= 8) + { + wf4[index] = bitfield(index, 9) ? zeroval : wf0[index * 2]; + wf5[index] = bitfield(index, 9) ? zeroval : wf0[(index * 2) & 0x1ff]; + wf6[index] = bitfield(index, 9) << 15; + wf7[index] = (bitfield(index, 9) ? (index ^ 0x13ff) : index) << 3; + } + } + } + + // OPL3/OPL4 have dynamic operators, so initialize the fourop_enable value here + // since operator_map() is called right away, prior to reset() + if (Revision > 2) + m_regdata[0x104 % REGISTERS] = 0; +} + + +//------------------------------------------------- +// reset - reset to initial state +//------------------------------------------------- + +template +void opl_registers_base::reset() +{ + std::fill_n(&m_regdata[0], REGISTERS, 0); +} + + +//------------------------------------------------- +// save_restore - save or restore the data +//------------------------------------------------- + +template +void opl_registers_base::save_restore(ymfm_saved_state &state) +{ + state.save_restore(m_lfo_am_counter); + state.save_restore(m_lfo_pm_counter); + state.save_restore(m_lfo_am); + state.save_restore(m_noise_lfsr); + state.save_restore(m_regdata); +} + + +//------------------------------------------------- +// operator_map - return an array of operator +// indices for each channel; for OPL this is fixed +//------------------------------------------------- + +template +void opl_registers_base::operator_map(operator_mapping &dest) const +{ + if (Revision <= 2) + { + // OPL/OPL2 has a fixed map, all 2 operators + static const operator_mapping s_fixed_map = + { { + operator_list( 0, 3 ), // Channel 0 operators + operator_list( 1, 4 ), // Channel 1 operators + operator_list( 2, 5 ), // Channel 2 operators + operator_list( 6, 9 ), // Channel 3 operators + operator_list( 7, 10 ), // Channel 4 operators + operator_list( 8, 11 ), // Channel 5 operators + operator_list( 12, 15 ), // Channel 6 operators + operator_list( 13, 16 ), // Channel 7 operators + operator_list( 14, 17 ), // Channel 8 operators + } }; + dest = s_fixed_map; + } + else + { + // OPL3/OPL4 can be configured for 2 or 4 operators + uint32_t fourop = fourop_enable(); + + dest.chan[ 0] = bitfield(fourop, 0) ? operator_list( 0, 3, 6, 9 ) : operator_list( 0, 3 ); + dest.chan[ 1] = bitfield(fourop, 1) ? operator_list( 1, 4, 7, 10 ) : operator_list( 1, 4 ); + dest.chan[ 2] = bitfield(fourop, 2) ? operator_list( 2, 5, 8, 11 ) : operator_list( 2, 5 ); + dest.chan[ 3] = bitfield(fourop, 0) ? operator_list() : operator_list( 6, 9 ); + dest.chan[ 4] = bitfield(fourop, 1) ? operator_list() : operator_list( 7, 10 ); + dest.chan[ 5] = bitfield(fourop, 2) ? operator_list() : operator_list( 8, 11 ); + dest.chan[ 6] = operator_list( 12, 15 ); + dest.chan[ 7] = operator_list( 13, 16 ); + dest.chan[ 8] = operator_list( 14, 17 ); + + dest.chan[ 9] = bitfield(fourop, 3) ? operator_list( 18, 21, 24, 27 ) : operator_list( 18, 21 ); + dest.chan[10] = bitfield(fourop, 4) ? operator_list( 19, 22, 25, 28 ) : operator_list( 19, 22 ); + dest.chan[11] = bitfield(fourop, 5) ? operator_list( 20, 23, 26, 29 ) : operator_list( 20, 23 ); + dest.chan[12] = bitfield(fourop, 3) ? operator_list() : operator_list( 24, 27 ); + dest.chan[13] = bitfield(fourop, 4) ? operator_list() : operator_list( 25, 28 ); + dest.chan[14] = bitfield(fourop, 5) ? operator_list() : operator_list( 26, 29 ); + dest.chan[15] = operator_list( 30, 33 ); + dest.chan[16] = operator_list( 31, 34 ); + dest.chan[17] = operator_list( 32, 35 ); + } +} + + +//------------------------------------------------- +// write - handle writes to the register array +//------------------------------------------------- + +template +bool opl_registers_base::write(uint16_t index, uint8_t data, uint32_t &channel, uint32_t &opmask) +{ + assert(index < REGISTERS); + + // writes to the mode register with high bit set ignore the low bits + if (index == REG_MODE && bitfield(data, 7) != 0) + m_regdata[index] |= 0x80; + else + m_regdata[index] = data; + + // handle writes to the rhythm keyons + if (index == 0xbd) + { + channel = RHYTHM_CHANNEL; + opmask = bitfield(data, 5) ? bitfield(data, 0, 5) : 0; + return true; + } + + // handle writes to the channel keyons + if ((index & 0xf0) == 0xb0) + { + channel = index & 0x0f; + if (channel < 9) + { + if (IsOpl3Plus) + channel += 9 * bitfield(index, 8); + opmask = bitfield(data, 5) ? 15 : 0; + return true; + } + } + return false; +} + + +//------------------------------------------------- +// clock_noise_and_lfo - clock the noise and LFO, +// handling clock division, depth, and waveform +// computations +//------------------------------------------------- + +static int32_t opl_clock_noise_and_lfo(uint32_t &noise_lfsr, uint16_t &lfo_am_counter, uint16_t &lfo_pm_counter, uint8_t &lfo_am, uint32_t am_depth, uint32_t pm_depth) +{ + // OPL has a 23-bit noise generator for the rhythm section, running at + // a constant rate, used only for percussion input + noise_lfsr <<= 1; + noise_lfsr |= bitfield(noise_lfsr, 23) ^ bitfield(noise_lfsr, 9) ^ bitfield(noise_lfsr, 8) ^ bitfield(noise_lfsr, 1); + + // OPL has two fixed-frequency LFOs, one for AM, one for PM + + // the AM LFO has 210*64 steps; at a nominal 50kHz output, + // this equates to a period of 50000/(210*64) = 3.72Hz + uint32_t am_counter = lfo_am_counter++; + if (am_counter >= 210*64 - 1) + lfo_am_counter = 0; + + // low 8 bits are fractional; depth 0 is divided by 2, while depth 1 is times 2 + int shift = 9 - 2 * am_depth; + + // AM value is the upper bits of the value, inverted across the midpoint + // to produce a triangle + lfo_am = ((am_counter < 105*64) ? am_counter : (210*64+63 - am_counter)) >> shift; + + // the PM LFO has 8192 steps, or a nominal period of 6.1Hz + uint32_t pm_counter = lfo_pm_counter++; + + // PM LFO is broken into 8 chunks, each lasting 1024 steps; the PM value + // depends on the upper bits of FNUM, so this value is a fraction and + // sign to apply to that value, as a 1.3 value + static int8_t const pm_scale[8] = { 8, 4, 0, -4, -8, -4, 0, 4 }; + return pm_scale[bitfield(pm_counter, 10, 3)] >> (pm_depth ^ 1); +} + +template +int32_t opl_registers_base::clock_noise_and_lfo() +{ + return opl_clock_noise_and_lfo(m_noise_lfsr, m_lfo_am_counter, m_lfo_pm_counter, m_lfo_am, lfo_am_depth(), lfo_pm_depth()); +} + + +//------------------------------------------------- +// cache_operator_data - fill the operator cache +// with prefetched data; note that this code is +// also used by ymopna_registers, so it must +// handle upper channels cleanly +//------------------------------------------------- + +template +void opl_registers_base::cache_operator_data(uint32_t choffs, uint32_t opoffs, opdata_cache &cache) +{ + // set up the easy stuff + cache.waveform = &m_waveform[op_waveform(opoffs) % WAVEFORMS][0]; + + // get frequency from the channel + uint32_t block_freq = cache.block_freq = ch_block_freq(choffs); + + // compute the keycode: block_freq is: + // + // 111 | + // 21098|76543210 + // BBBFF|FFFFFFFF + // ^^^?? + // + // the 4-bit keycode uses the top 3 bits plus one of the next two bits + uint32_t keycode = bitfield(block_freq, 10, 3) << 1; + + // lowest bit is determined by note_select(); note that it is + // actually reversed from what the manual says, however + keycode |= bitfield(block_freq, 9 - note_select(), 1); + + // no detune adjustment on OPL + cache.detune = 0; + + // multiple value, as an x.1 value (0 means 0.5) + // replace the low bit with a table lookup to give 0,1,2,3,4,5,6,7,8,9,10,10,12,12,15,15 + uint32_t multiple = op_multiple(opoffs); + cache.multiple = ((multiple & 0xe) | bitfield(0xc2aa, multiple)) * 2; + if (cache.multiple == 0) + cache.multiple = 1; + + // phase step, or PHASE_STEP_DYNAMIC if PM is active; this depends on block_freq, detune, + // and multiple, so compute it after we've done those + if (op_lfo_pm_enable(opoffs) == 0) + cache.phase_step = compute_phase_step(choffs, opoffs, cache, 0); + else + cache.phase_step = opdata_cache::PHASE_STEP_DYNAMIC; + + // total level, scaled by 8 + cache.total_level = op_total_level(opoffs) << 3; + + // pre-add key scale level + uint32_t ksl = op_ksl(opoffs); + if (ksl != 0) + cache.total_level += opl_key_scale_atten(bitfield(block_freq, 10, 3), bitfield(block_freq, 6, 4)) << ksl; + + // 4-bit sustain level, but 15 means 31 so effectively 5 bits + cache.eg_sustain = op_sustain_level(opoffs); + cache.eg_sustain |= (cache.eg_sustain + 1) & 0x10; + cache.eg_sustain <<= 5; + + // determine KSR adjustment for enevlope rates + uint32_t ksrval = keycode >> (2 * (op_ksr(opoffs) ^ 1)); + cache.eg_rate[EG_ATTACK] = effective_rate(op_attack_rate(opoffs) * 4, ksrval); + cache.eg_rate[EG_DECAY] = effective_rate(op_decay_rate(opoffs) * 4, ksrval); + cache.eg_rate[EG_SUSTAIN] = op_eg_sustain(opoffs) ? 0 : effective_rate(op_release_rate(opoffs) * 4, ksrval); + cache.eg_rate[EG_RELEASE] = effective_rate(op_release_rate(opoffs) * 4, ksrval); + cache.eg_rate[EG_DEPRESS] = 0x3f; +} + + +//------------------------------------------------- +// compute_phase_step - compute the phase step +//------------------------------------------------- + +static uint32_t opl_compute_phase_step(uint32_t block_freq, uint32_t multiple, int32_t lfo_raw_pm) +{ + // OPL phase calculation has no detuning, but uses FNUMs like + // the OPN version, and computes PM a bit differently + + // extract frequency number as a 12-bit fraction + uint32_t fnum = bitfield(block_freq, 0, 10) << 2; + + // apply the phase adjustment based on the upper 3 bits + // of FNUM and the PM depth parameters + fnum += (lfo_raw_pm * bitfield(block_freq, 7, 3)) >> 1; + + // keep fnum to 12 bits + fnum &= 0xfff; + + // apply block shift to compute phase step + uint32_t block = bitfield(block_freq, 10, 3); + uint32_t phase_step = (fnum << block) >> 2; + + // apply frequency multiplier (which is cached as an x.1 value) + return (phase_step * multiple) >> 1; +} + +template +uint32_t opl_registers_base::compute_phase_step(uint32_t choffs, uint32_t opoffs, opdata_cache const &cache, int32_t lfo_raw_pm) +{ + return opl_compute_phase_step(cache.block_freq, cache.multiple, op_lfo_pm_enable(opoffs) ? lfo_raw_pm : 0); +} + + +//------------------------------------------------- +// log_keyon - log a key-on event +//------------------------------------------------- + +template +std::string opl_registers_base::log_keyon(uint32_t choffs, uint32_t opoffs) +{ + uint32_t chnum = (choffs & 15) + 9 * bitfield(choffs, 8); + uint32_t opnum = (opoffs & 31) - 2 * ((opoffs & 31) / 8) + 18 * bitfield(opoffs, 8); + + char buffer[256]; + char *end = &buffer[0]; + + end += snprintf(end, SNPRINTF_BUFFER_SIZE_CALC, "%2u.%02u freq=%04X fb=%u alg=%X mul=%X tl=%02X ksr=%u ns=%u ksl=%u adr=%X/%X/%X sl=%X sus=%u", + chnum, opnum, + ch_block_freq(choffs), + ch_feedback(choffs), + ch_algorithm(choffs), + op_multiple(opoffs), + op_total_level(opoffs), + op_ksr(opoffs), + note_select(), + op_ksl(opoffs), + op_attack_rate(opoffs), + op_decay_rate(opoffs), + op_release_rate(opoffs), + op_sustain_level(opoffs), + op_eg_sustain(opoffs)); + + if (OUTPUTS > 1) + end += snprintf(end, SNPRINTF_BUFFER_SIZE_CALC, " out=%c%c%c%c", + ch_output_0(choffs) ? 'L' : '-', + ch_output_1(choffs) ? 'R' : '-', + ch_output_2(choffs) ? '0' : '-', + ch_output_3(choffs) ? '1' : '-'); + if (op_lfo_am_enable(opoffs) != 0) + end += snprintf(end, SNPRINTF_BUFFER_SIZE_CALC, " am=%u", lfo_am_depth()); + if (op_lfo_pm_enable(opoffs) != 0) + end += snprintf(end, SNPRINTF_BUFFER_SIZE_CALC, " pm=%u", lfo_pm_depth()); + if (waveform_enable() && op_waveform(opoffs) != 0) + end += snprintf(end, SNPRINTF_BUFFER_SIZE_CALC, " wf=%u", op_waveform(opoffs)); + if (is_rhythm(choffs)) + end += snprintf(end, SNPRINTF_BUFFER_SIZE_CALC, " rhy=1"); + if (DYNAMIC_OPS) + { + operator_mapping map; + operator_map(map); + if (bitfield(map.chan[chnum], 16, 8) != 0xff) + end += snprintf(end, SNPRINTF_BUFFER_SIZE_CALC, " 4op"); + } + + return buffer; +} + + +//********************************************************* +// OPLL SPECIFICS +//********************************************************* + +//------------------------------------------------- +// opll_registers - constructor +//------------------------------------------------- + +opll_registers::opll_registers() : + m_lfo_am_counter(0), + m_lfo_pm_counter(0), + m_noise_lfsr(1), + m_lfo_am(0) +{ + // create the waveforms + for (uint32_t index = 0; index < WAVEFORM_LENGTH; index++) + m_waveform[0][index] = abs_sin_attenuation(index) | (bitfield(index, 9) << 15); + + uint16_t zeroval = m_waveform[0][0]; + for (uint32_t index = 0; index < WAVEFORM_LENGTH; index++) + m_waveform[1][index] = bitfield(index, 9) ? zeroval : m_waveform[0][index]; + + // initialize the instruments to something sane + for (uint32_t choffs = 0; choffs < CHANNELS; choffs++) + m_chinst[choffs] = &m_regdata[0]; + for (uint32_t opoffs = 0; opoffs < OPERATORS; opoffs++) + m_opinst[opoffs] = &m_regdata[bitfield(opoffs, 0)]; +} + + +//------------------------------------------------- +// reset - reset to initial state +//------------------------------------------------- + +void opll_registers::reset() +{ + std::fill_n(&m_regdata[0], REGISTERS, 0); +} + + +//------------------------------------------------- +// save_restore - save or restore the data +//------------------------------------------------- + +void opll_registers::save_restore(ymfm_saved_state &state) +{ + state.save_restore(m_lfo_am_counter); + state.save_restore(m_lfo_pm_counter); + state.save_restore(m_lfo_am); + state.save_restore(m_noise_lfsr); + state.save_restore(m_regdata); +} + + +//------------------------------------------------- +// operator_map - return an array of operator +// indices for each channel; for OPLL this is fixed +//------------------------------------------------- + +void opll_registers::operator_map(operator_mapping &dest) const +{ + static const operator_mapping s_fixed_map = + { { + operator_list( 0, 1 ), // Channel 0 operators + operator_list( 2, 3 ), // Channel 1 operators + operator_list( 4, 5 ), // Channel 2 operators + operator_list( 6, 7 ), // Channel 3 operators + operator_list( 8, 9 ), // Channel 4 operators + operator_list( 10, 11 ), // Channel 5 operators + operator_list( 12, 13 ), // Channel 6 operators + operator_list( 14, 15 ), // Channel 7 operators + operator_list( 16, 17 ), // Channel 8 operators + } }; + dest = s_fixed_map; +} + + +//------------------------------------------------- +// write - handle writes to the register array; +// note that this code is also used by +// ymopl3_registers, so it must handle upper +// channels cleanly +//------------------------------------------------- + +bool opll_registers::write(uint16_t index, uint8_t data, uint32_t &channel, uint32_t &opmask) +{ + // unclear the address is masked down to 6 bits or if writes above + // the register top are ignored; assuming the latter for now + if (index >= REGISTERS) + return false; + + // write the new data + m_regdata[index] = data; + + // handle writes to the rhythm keyons + if (index == 0x0e) + { + channel = RHYTHM_CHANNEL; + opmask = bitfield(data, 5) ? bitfield(data, 0, 5) : 0; + return true; + } + + // handle writes to the channel keyons + if ((index & 0xf0) == 0x20) + { + channel = index & 0x0f; + if (channel < CHANNELS) + { + opmask = bitfield(data, 4) ? 3 : 0; + return true; + } + } + return false; +} + + +//------------------------------------------------- +// clock_noise_and_lfo - clock the noise and LFO, +// handling clock division, depth, and waveform +// computations +//------------------------------------------------- + +int32_t opll_registers::clock_noise_and_lfo() +{ + // implementation is the same as OPL with fixed depths + return opl_clock_noise_and_lfo(m_noise_lfsr, m_lfo_am_counter, m_lfo_pm_counter, m_lfo_am, 1, 1); +} + + +//------------------------------------------------- +// cache_operator_data - fill the operator cache +// with prefetched data; note that this code is +// also used by ymopna_registers, so it must +// handle upper channels cleanly +//------------------------------------------------- + +void opll_registers::cache_operator_data(uint32_t choffs, uint32_t opoffs, opdata_cache &cache) +{ + // first set up the instrument data + uint32_t instrument = ch_instrument(choffs); + if (rhythm_enable() && choffs >= 6) + m_chinst[choffs] = &m_instdata[8 * (15 + (choffs - 6))]; + else + m_chinst[choffs] = (instrument == 0) ? &m_regdata[0] : &m_instdata[8 * (instrument - 1)]; + m_opinst[opoffs] = m_chinst[choffs] + bitfield(opoffs, 0); + + // set up the easy stuff + cache.waveform = &m_waveform[op_waveform(opoffs) % WAVEFORMS][0]; + + // get frequency from the channel + uint32_t block_freq = cache.block_freq = ch_block_freq(choffs); + + // compute the keycode: block_freq is: + // + // 11 | + // 1098|76543210 + // BBBF|FFFFFFFF + // ^^^^ + // + // the 4-bit keycode uses the top 4 bits + uint32_t keycode = bitfield(block_freq, 8, 4); + + // no detune adjustment on OPLL + cache.detune = 0; + + // multiple value, as an x.1 value (0 means 0.5) + // replace the low bit with a table lookup to give 0,1,2,3,4,5,6,7,8,9,10,10,12,12,15,15 + uint32_t multiple = op_multiple(opoffs); + cache.multiple = ((multiple & 0xe) | bitfield(0xc2aa, multiple)) * 2; + if (cache.multiple == 0) + cache.multiple = 1; + + // phase step, or PHASE_STEP_DYNAMIC if PM is active; this depends on + // block_freq, detune, and multiple, so compute it after we've done those + if (op_lfo_pm_enable(opoffs) == 0) + cache.phase_step = compute_phase_step(choffs, opoffs, cache, 0); + else + cache.phase_step = opdata_cache::PHASE_STEP_DYNAMIC; + + // total level, scaled by 8; for non-rhythm operator 0, this is the total + // level from the instrument data; for other operators it is 4*volume + if (bitfield(opoffs, 0) == 1 || (rhythm_enable() && choffs >= 7)) + cache.total_level = op_volume(opoffs) * 4; + else + cache.total_level = ch_total_level(choffs); + cache.total_level <<= 3; + + // pre-add key scale level + uint32_t ksl = op_ksl(opoffs); + if (ksl != 0) + cache.total_level += opl_key_scale_atten(bitfield(block_freq, 9, 3), bitfield(block_freq, 5, 4)) << ksl; + + // 4-bit sustain level, but 15 means 31 so effectively 5 bits + cache.eg_sustain = op_sustain_level(opoffs); + cache.eg_sustain |= (cache.eg_sustain + 1) & 0x10; + cache.eg_sustain <<= 5; + + // The envelope diagram in the YM2413 datasheet gives values for these + // in ms from 0->48dB. The attack/decay tables give values in ms from + // 0->96dB, so to pick an equivalent decay rate, we want to find the + // closest match that is 2x the 0->48dB value: + // + // DP = 10ms (0->48db) -> 20ms (0->96db); decay of 12 gives 19.20ms + // RR = 310ms (0->48db) -> 620ms (0->96db); decay of 7 gives 613.76ms + // RS = 1200ms (0->48db) -> 2400ms (0->96db); decay of 5 gives 2455.04ms + // + // The envelope diagram for percussive sounds (eg_sustain() == 0) also uses + // "RR" to mean both the constant RR above and the Release Rate specified in + // the instrument data. In this case, Relief Pitcher's credit sound bears out + // that the Release Rate is used during sustain, and that the constant RR + // (or RS) is used during the release phase. + constexpr uint8_t DP = 12 * 4; + constexpr uint8_t RR = 7 * 4; + constexpr uint8_t RS = 5 * 4; + + // determine KSR adjustment for envelope rates + uint32_t ksrval = keycode >> (2 * (op_ksr(opoffs) ^ 1)); + cache.eg_rate[EG_DEPRESS] = DP; + cache.eg_rate[EG_ATTACK] = effective_rate(op_attack_rate(opoffs) * 4, ksrval); + cache.eg_rate[EG_DECAY] = effective_rate(op_decay_rate(opoffs) * 4, ksrval); + if (op_eg_sustain(opoffs)) + { + cache.eg_rate[EG_SUSTAIN] = 0; + cache.eg_rate[EG_RELEASE] = ch_sustain(choffs) ? RS : effective_rate(op_release_rate(opoffs) * 4, ksrval); + } + else + { + cache.eg_rate[EG_SUSTAIN] = effective_rate(op_release_rate(opoffs) * 4, ksrval); + cache.eg_rate[EG_RELEASE] = ch_sustain(choffs) ? RS : RR; + } +} + + +//------------------------------------------------- +// compute_phase_step - compute the phase step +//------------------------------------------------- + +uint32_t opll_registers::compute_phase_step(uint32_t choffs, uint32_t opoffs, opdata_cache const &cache, int32_t lfo_raw_pm) +{ + // phase step computation is the same as OPL but the block_freq has one + // more bit, which we shift in + return opl_compute_phase_step(cache.block_freq << 1, cache.multiple, op_lfo_pm_enable(opoffs) ? lfo_raw_pm : 0); +} + + +//------------------------------------------------- +// log_keyon - log a key-on event +//------------------------------------------------- + +std::string opll_registers::log_keyon(uint32_t choffs, uint32_t opoffs) +{ + uint32_t chnum = choffs; + uint32_t opnum = opoffs; + + char buffer[256]; + char *end = &buffer[0]; + + end += snprintf(end, SNPRINTF_BUFFER_SIZE_CALC, "%u.%02u freq=%04X inst=%X fb=%u mul=%X", + chnum, opnum, + ch_block_freq(choffs), + ch_instrument(choffs), + ch_feedback(choffs), + op_multiple(opoffs)); + + if (bitfield(opoffs, 0) == 1 || (is_rhythm(choffs) && choffs >= 6)) + end += snprintf(end, SNPRINTF_BUFFER_SIZE_CALC, " vol=%X", op_volume(opoffs)); + else + end += snprintf(end, SNPRINTF_BUFFER_SIZE_CALC, " tl=%02X", ch_total_level(choffs)); + + end += snprintf(end, SNPRINTF_BUFFER_SIZE_CALC, " ksr=%u ksl=%u adr=%X/%X/%X sl=%X sus=%u/%u", + op_ksr(opoffs), + op_ksl(opoffs), + op_attack_rate(opoffs), + op_decay_rate(opoffs), + op_release_rate(opoffs), + op_sustain_level(opoffs), + op_eg_sustain(opoffs), + ch_sustain(choffs)); + + if (op_lfo_am_enable(opoffs)) + end += snprintf(end, SNPRINTF_BUFFER_SIZE_CALC, " am=1"); + if (op_lfo_pm_enable(opoffs)) + end += snprintf(end, SNPRINTF_BUFFER_SIZE_CALC, " pm=1"); + if (op_waveform(opoffs) != 0) + end += snprintf(end, SNPRINTF_BUFFER_SIZE_CALC, " wf=1"); + if (is_rhythm(choffs)) + end += snprintf(end, SNPRINTF_BUFFER_SIZE_CALC, " rhy=1"); + + return buffer; +} + + + +//********************************************************* +// YM3526 +//********************************************************* + +//------------------------------------------------- +// ym3526 - constructor +//------------------------------------------------- + +ym3526::ym3526(ymfm_interface &intf) : + m_address(0), + m_fm(intf) +{ +} + + +//------------------------------------------------- +// reset - reset the system +//------------------------------------------------- + +void ym3526::reset() +{ + // reset the engines + m_fm.reset(); +} + + +//------------------------------------------------- +// save_restore - save or restore the data +//------------------------------------------------- + +void ym3526::save_restore(ymfm_saved_state &state) +{ + state.save_restore(m_address); + m_fm.save_restore(state); +} + + +//------------------------------------------------- +// read_status - read the status register +//------------------------------------------------- + +uint8_t ym3526::read_status() +{ + return m_fm.status() | 0x06; +} + + +//------------------------------------------------- +// read - handle a read from the device +//------------------------------------------------- + +uint8_t ym3526::read(uint32_t offset) +{ + uint8_t result = 0xff; + switch (offset & 1) + { + case 0: // status port + result = read_status(); + break; + + case 1: // when A0=1 datasheet says "the data on the bus are not guaranteed" + break; + } + return result; +} + + +//------------------------------------------------- +// write_address - handle a write to the address +// register +//------------------------------------------------- + +void ym3526::write_address(uint8_t data) +{ + // YM3526 doesn't expose a busy signal, and the datasheets don't indicate + // delays, but all other OPL chips need 12 cycles for address writes + m_fm.intf().ymfm_set_busy_end(12 * m_fm.clock_prescale()); + + // just set the address + m_address = data; +} + + +//------------------------------------------------- +// write - handle a write to the register +// interface +//------------------------------------------------- + +void ym3526::write_data(uint8_t data) +{ + // YM3526 doesn't expose a busy signal, and the datasheets don't indicate + // delays, but all other OPL chips need 84 cycles for data writes + m_fm.intf().ymfm_set_busy_end(84 * m_fm.clock_prescale()); + + // write to FM + m_fm.write(m_address, data); +} + + +//------------------------------------------------- +// write - handle a write to the register +// interface +//------------------------------------------------- + +void ym3526::write(uint32_t offset, uint8_t data) +{ + switch (offset & 1) + { + case 0: // address port + write_address(data); + break; + + case 1: // data port + write_data(data); + break; + } +} + + +//------------------------------------------------- +// generate - generate samples of sound +//------------------------------------------------- + +void ym3526::generate(output_data *output, uint32_t numsamples) +{ + for (uint32_t samp = 0; samp < numsamples; samp++, output++) + { + // clock the system + m_fm.clock(fm_engine::ALL_CHANNELS); + + // update the FM content; mixing details for YM3526 need verification + m_fm.output(output->clear(), 1, 32767, fm_engine::ALL_CHANNELS); + + // YM3526 uses an external DAC (YM3014) with mantissa/exponent format + // convert to 10.3 floating point value and back to simulate truncation + output->roundtrip_fp(); + } +} + + + +//********************************************************* +// Y8950 +//********************************************************* + +//------------------------------------------------- +// y8950 - constructor +//------------------------------------------------- + +y8950::y8950(ymfm_interface &intf) : + m_address(0), + m_io_ddr(0), + m_fm(intf), + m_adpcm_b(intf) +{ +} + + +//------------------------------------------------- +// reset - reset the system +//------------------------------------------------- + +void y8950::reset() +{ + // reset the engines + m_fm.reset(); + m_adpcm_b.reset(); +} + + +//------------------------------------------------- +// save_restore - save or restore the data +//------------------------------------------------- + +void y8950::save_restore(ymfm_saved_state &state) +{ + state.save_restore(m_address); + state.save_restore(m_io_ddr); + m_fm.save_restore(state); +} + + +//------------------------------------------------- +// read_status - read the status register +//------------------------------------------------- + +uint8_t y8950::read_status() +{ + // start with current FM status, masking out bits we might set + uint8_t status = m_fm.status() & ~(STATUS_ADPCM_B_EOS | STATUS_ADPCM_B_BRDY | STATUS_ADPCM_B_PLAYING); + + // insert the live ADPCM status bits + uint8_t adpcm_status = m_adpcm_b.status(); + if ((adpcm_status & adpcm_b_channel::STATUS_EOS) != 0) + status |= STATUS_ADPCM_B_EOS; + if ((adpcm_status & adpcm_b_channel::STATUS_BRDY) != 0) + status |= STATUS_ADPCM_B_BRDY; + if ((adpcm_status & adpcm_b_channel::STATUS_PLAYING) != 0) + status |= STATUS_ADPCM_B_PLAYING; + + // run it through the FM engine to handle interrupts for us + return m_fm.set_reset_status(status, ~status); +} + + +//------------------------------------------------- +// read_data - read the data port +//------------------------------------------------- + +uint8_t y8950::read_data() +{ + uint8_t result = 0xff; + switch (m_address) + { + case 0x05: // keyboard in + result = m_fm.intf().ymfm_external_read(ACCESS_IO, 1); + break; + + case 0x09: // ADPCM data + case 0x1a: + result = m_adpcm_b.read(m_address - 0x07); + break; + + case 0x19: // I/O data + result = m_fm.intf().ymfm_external_read(ACCESS_IO, 0); + break; + + default: + debug::log_unexpected_read_write("Unexpected read from Y8950 data port %02X\n", m_address); + break; + } + return result; +} + + +//------------------------------------------------- +// read - handle a read from the device +//------------------------------------------------- + +uint8_t y8950::read(uint32_t offset) +{ + uint8_t result = 0xff; + switch (offset & 1) + { + case 0: // status port + result = read_status(); + break; + + case 1: // when A0=1 datasheet says "the data on the bus are not guaranteed" + result = read_data(); + break; + } + return result; +} + + +//------------------------------------------------- +// write_address - handle a write to the address +// register +//------------------------------------------------- + +void y8950::write_address(uint8_t data) +{ + // Y8950 doesn't expose a busy signal, but it does indicate that + // address writes should be no faster than every 12 clocks + m_fm.intf().ymfm_set_busy_end(12 * m_fm.clock_prescale()); + + // just set the address + m_address = data; +} + + +//------------------------------------------------- +// write - handle a write to the register +// interface +//------------------------------------------------- + +void y8950::write_data(uint8_t data) +{ + // Y8950 doesn't expose a busy signal, but it does indicate that + // data writes should be no faster than every 12 clocks for + // registers 00-1A, or every 84 clocks for other registers + m_fm.intf().ymfm_set_busy_end(((m_address <= 0x1a) ? 12 : 84) * m_fm.clock_prescale()); + + // handle special addresses + switch (m_address) + { + case 0x04: // IRQ control + m_fm.write(m_address, data); + read_status(); + break; + + case 0x06: // keyboard out + m_fm.intf().ymfm_external_write(ACCESS_IO, 1, data); + break; + + case 0x08: // split FM/ADPCM-B + m_adpcm_b.write(m_address - 0x07, (data & 0x0f) | 0x80); + m_fm.write(m_address, data & 0xc0); + break; + + case 0x07: // ADPCM-B registers + case 0x09: + case 0x0a: + case 0x0b: + case 0x0c: + case 0x0d: + case 0x0e: + case 0x0f: + case 0x10: + case 0x11: + case 0x12: + case 0x15: + case 0x16: + case 0x17: + m_adpcm_b.write(m_address - 0x07, data); + break; + + case 0x18: // I/O direction + m_io_ddr = data & 0x0f; + break; + + case 0x19: // I/O data + m_fm.intf().ymfm_external_write(ACCESS_IO, 0, data & m_io_ddr); + break; + + default: // everything else to FM + m_fm.write(m_address, data); + break; + } +} + + +//------------------------------------------------- +// write - handle a write to the register +// interface +//------------------------------------------------- + +void y8950::write(uint32_t offset, uint8_t data) +{ + switch (offset & 1) + { + case 0: // address port + write_address(data); + break; + + case 1: // data port + write_data(data); + break; + } +} + + +//------------------------------------------------- +// generate - generate samples of sound +//------------------------------------------------- + +void y8950::generate(output_data *output, uint32_t numsamples) +{ + for (uint32_t samp = 0; samp < numsamples; samp++, output++) + { + // clock the system + m_fm.clock(fm_engine::ALL_CHANNELS); + m_adpcm_b.clock(); + + // update the FM content; clipping need verification + m_fm.output(output->clear(), 1, 32767, fm_engine::ALL_CHANNELS); + + // mix in the ADPCM; ADPCM-B is stereo, but only one channel + // not sure how it's wired up internally + m_adpcm_b.output(*output, 3); + + // Y8950 uses an external DAC (YM3014) with mantissa/exponent format + // convert to 10.3 floating point value and back to simulate truncation + output->roundtrip_fp(); + } +} + + + +//********************************************************* +// YM3812 +//********************************************************* + +//------------------------------------------------- +// ym3812 - constructor +//------------------------------------------------- + +ym3812::ym3812(ymfm_interface &intf) : + m_address(0), + m_fm(intf) +{ +} + + +//------------------------------------------------- +// reset - reset the system +//------------------------------------------------- + +void ym3812::reset() +{ + // reset the engines + m_fm.reset(); +} + + +//------------------------------------------------- +// save_restore - save or restore the data +//------------------------------------------------- + +void ym3812::save_restore(ymfm_saved_state &state) +{ + state.save_restore(m_address); + m_fm.save_restore(state); +} + + +//------------------------------------------------- +// read_status - read the status register +//------------------------------------------------- + +uint8_t ym3812::read_status() +{ + return m_fm.status() | 0x06; +} + + +//------------------------------------------------- +// read - handle a read from the device +//------------------------------------------------- + +uint8_t ym3812::read(uint32_t offset) +{ + uint8_t result = 0xff; + switch (offset & 1) + { + case 0: // status port + result = read_status(); + break; + + case 1: // "inhibit" according to datasheet + break; + } + return result; +} + + +//------------------------------------------------- +// write_address - handle a write to the address +// register +//------------------------------------------------- + +void ym3812::write_address(uint8_t data) +{ + // YM3812 doesn't expose a busy signal, but it does indicate that + // address writes should be no faster than every 12 clocks + m_fm.intf().ymfm_set_busy_end(12 * m_fm.clock_prescale()); + + // just set the address + m_address = data; +} + + +//------------------------------------------------- +// write - handle a write to the register +// interface +//------------------------------------------------- + +void ym3812::write_data(uint8_t data) +{ + // YM3812 doesn't expose a busy signal, but it does indicate that + // data writes should be no faster than every 84 clocks + m_fm.intf().ymfm_set_busy_end(84 * m_fm.clock_prescale()); + + // write to FM + m_fm.write(m_address, data); +} + + +//------------------------------------------------- +// write - handle a write to the register +// interface +//------------------------------------------------- + +void ym3812::write(uint32_t offset, uint8_t data) +{ + switch (offset & 1) + { + case 0: // address port + write_address(data); + break; + + case 1: // data port + write_data(data); + break; + } +} + + +//------------------------------------------------- +// generate - generate samples of sound +//------------------------------------------------- + +void ym3812::generate(output_data *output, uint32_t numsamples) +{ + for (uint32_t samp = 0; samp < numsamples; samp++, output++) + { + // clock the system + m_fm.clock(fm_engine::ALL_CHANNELS); + + // update the FM content; mixing details for YM3812 need verification + m_fm.output(output->clear(), 1, 32767, fm_engine::ALL_CHANNELS); + + // YM3812 uses an external DAC (YM3014) with mantissa/exponent format + // convert to 10.3 floating point value and back to simulate truncation + output->roundtrip_fp(); + } +} + + + +//********************************************************* +// YMF262 +//********************************************************* + +//------------------------------------------------- +// ymf262 - constructor +//------------------------------------------------- + +ymf262::ymf262(ymfm_interface &intf) : + m_address(0), + m_fm(intf) +{ +} + + +//------------------------------------------------- +// reset - reset the system +//------------------------------------------------- + +void ymf262::reset() +{ + // reset the engines + m_fm.reset(); +} + + +//------------------------------------------------- +// save_restore - save or restore the data +//------------------------------------------------- + +void ymf262::save_restore(ymfm_saved_state &state) +{ + state.save_restore(m_address); + m_fm.save_restore(state); +} + + +//------------------------------------------------- +// read_status - read the status register +//------------------------------------------------- + +uint8_t ymf262::read_status() +{ + return m_fm.status(); +} + + +//------------------------------------------------- +// read - handle a read from the device +//------------------------------------------------- + +uint8_t ymf262::read(uint32_t offset) +{ + uint8_t result = 0xff; + switch (offset & 3) + { + case 0: // status port + result = read_status(); + break; + + case 1: + case 2: + case 3: + debug::log_unexpected_read_write("Unexpected read from YMF262 offset %d\n", offset & 3); + break; + } + return result; +} + + +//------------------------------------------------- +// write_address - handle a write to the address +// register +//------------------------------------------------- + +void ymf262::write_address(uint8_t data) +{ + // YMF262 doesn't expose a busy signal, but it does indicate that + // address writes should be no faster than every 32 clocks + m_fm.intf().ymfm_set_busy_end(32 * m_fm.clock_prescale()); + + // just set the address + m_address = data; +} + + +//------------------------------------------------- +// write_data - handle a write to the data +// register +//------------------------------------------------- + +void ymf262::write_data(uint8_t data) +{ + // YMF262 doesn't expose a busy signal, but it does indicate that + // data writes should be no faster than every 32 clocks + m_fm.intf().ymfm_set_busy_end(32 * m_fm.clock_prescale()); + + // write to FM + m_fm.write(m_address, data); +} + + +//------------------------------------------------- +// write_address_hi - handle a write to the upper +// address register +//------------------------------------------------- + +void ymf262::write_address_hi(uint8_t data) +{ + // YMF262 doesn't expose a busy signal, but it does indicate that + // address writes should be no faster than every 32 clocks + m_fm.intf().ymfm_set_busy_end(32 * m_fm.clock_prescale()); + + // just set the address + m_address = data | 0x100; + + // tests reveal that in compatibility mode, upper bit is masked + // except for register 0x105 + if (m_fm.regs().newflag() == 0 && m_address != 0x105) + m_address &= 0xff; +} + + +//------------------------------------------------- +// write - handle a write to the register +// interface +//------------------------------------------------- + +void ymf262::write(uint32_t offset, uint8_t data) +{ + switch (offset & 3) + { + case 0: // address port + write_address(data); + break; + + case 1: // data port + write_data(data); + break; + + case 2: // address port + write_address_hi(data); + break; + + case 3: // data port + write_data(data); + break; + } +} + + +//------------------------------------------------- +// generate - generate samples of sound +//------------------------------------------------- + +void ymf262::generate(output_data *output, uint32_t numsamples) +{ + for (uint32_t samp = 0; samp < numsamples; samp++, output++) + { + // clock the system + m_fm.clock(fm_engine::ALL_CHANNELS); + + // update the FM content; mixing details for YMF262 need verification + m_fm.output(output->clear(), 0, 32767, fm_engine::ALL_CHANNELS); + + // YMF262 output is 16-bit offset serial via YAC512 DAC + output->clamp16(); + } +} + + + +//********************************************************* +// YMF289B +//********************************************************* + +// YMF289B is a YMF262 with the following changes: +// * "Power down" mode added +// * Bulk register clear added +// * Busy flag added to the status register +// * Shorter busy times +// * All registers can be read +// * Only 2 outputs exposed + +//------------------------------------------------- +// ymf289b - constructor +//------------------------------------------------- + +ymf289b::ymf289b(ymfm_interface &intf) : + m_address(0), + m_fm(intf) +{ +} + + +//------------------------------------------------- +// reset - reset the system +//------------------------------------------------- + +void ymf289b::reset() +{ + // reset the engines + m_fm.reset(); +} + + +//------------------------------------------------- +// save_restore - save or restore the data +//------------------------------------------------- + +void ymf289b::save_restore(ymfm_saved_state &state) +{ + state.save_restore(m_address); + m_fm.save_restore(state); +} + + +//------------------------------------------------- +// read_status - read the status register +//------------------------------------------------- + +uint8_t ymf289b::read_status() +{ + uint8_t result = m_fm.status(); + + // YMF289B adds a busy flag + if (ymf289b_mode() && m_fm.intf().ymfm_is_busy()) + result |= STATUS_BUSY_FLAGS; + return result; +} + + +//------------------------------------------------- +// read_data - read the data register +//------------------------------------------------- + +uint8_t ymf289b::read_data() +{ + uint8_t result = 0xff; + + // YMF289B can read register data back + if (ymf289b_mode()) + result = m_fm.regs().read(m_address); + return result; +} + + +//------------------------------------------------- +// read - handle a read from the device +//------------------------------------------------- + +uint8_t ymf289b::read(uint32_t offset) +{ + uint8_t result = 0xff; + switch (offset & 3) + { + case 0: // status port + result = read_status(); + break; + + case 1: // data port + result = read_data(); + break; + + case 2: + case 3: + debug::log_unexpected_read_write("Unexpected read from YMF289B offset %d\n", offset & 3); + break; + } + return result; +} + + +//------------------------------------------------- +// write_address - handle a write to the address +// register +//------------------------------------------------- + +void ymf289b::write_address(uint8_t data) +{ + m_address = data; + + // count busy time + m_fm.intf().ymfm_set_busy_end(56); +} + + +//------------------------------------------------- +// write_data - handle a write to the data +// register +//------------------------------------------------- + +void ymf289b::write_data(uint8_t data) +{ + // write to FM + m_fm.write(m_address, data); + + // writes to 0x108 with the CLR flag set clear the registers + if (m_address == 0x108 && bitfield(data, 2) != 0) + m_fm.regs().reset(); + + // count busy time + m_fm.intf().ymfm_set_busy_end(56); +} + + +//------------------------------------------------- +// write_address_hi - handle a write to the upper +// address register +//------------------------------------------------- + +void ymf289b::write_address_hi(uint8_t data) +{ + // just set the address + m_address = data | 0x100; + + // tests reveal that in compatibility mode, upper bit is masked + // except for register 0x105 + if (m_fm.regs().newflag() == 0 && m_address != 0x105) + m_address &= 0xff; + + // count busy time + m_fm.intf().ymfm_set_busy_end(56); +} + + +//------------------------------------------------- +// write - handle a write to the register +// interface +//------------------------------------------------- + +void ymf289b::write(uint32_t offset, uint8_t data) +{ + switch (offset & 3) + { + case 0: // address port + write_address(data); + break; + + case 1: // data port + write_data(data); + break; + + case 2: // address port + write_address_hi(data); + break; + + case 3: // data port + write_data(data); + break; + } +} + + +//------------------------------------------------- +// generate - generate samples of sound +//------------------------------------------------- + +void ymf289b::generate(output_data *output, uint32_t numsamples) +{ + for (uint32_t samp = 0; samp < numsamples; samp++, output++) + { + // clock the system + m_fm.clock(fm_engine::ALL_CHANNELS); + + // update the FM content; mixing details for YMF262 need verification + fm_engine::output_data full; + m_fm.output(full.clear(), 0, 32767, fm_engine::ALL_CHANNELS); + + // YMF278B output is 16-bit offset serial via YAC512 DAC, but + // only 2 of the 4 outputs are exposed + output->data[0] = full.data[0]; + output->data[1] = full.data[1]; + output->clamp16(); + } +} + + + +//********************************************************* +// YMF278B +//********************************************************* + +//------------------------------------------------- +// ymf278b - constructor +//------------------------------------------------- + +ymf278b::ymf278b(ymfm_interface &intf) : + m_address(0), + m_fm_pos(0), + m_load_remaining(0), + m_next_status_id(false), + m_fm(intf), + m_pcm(intf) +{ +} + + +//------------------------------------------------- +// reset - reset the system +//------------------------------------------------- + +void ymf278b::reset() +{ + // reset the engines + m_fm.reset(); + m_pcm.reset(); + + // next status read will return ID + m_next_status_id = true; +} + + +//------------------------------------------------- +// save_restore - save or restore the data +//------------------------------------------------- + +void ymf278b::save_restore(ymfm_saved_state &state) +{ + state.save_restore(m_address); + state.save_restore(m_fm_pos); + state.save_restore(m_load_remaining); + state.save_restore(m_next_status_id); + m_fm.save_restore(state); + m_pcm.save_restore(state); +} + + +//------------------------------------------------- +// read_status - read the status register +//------------------------------------------------- + +uint8_t ymf278b::read_status() +{ + uint8_t result; + + // first status read after initialization returns a chip ID, which + // varies based on the "new" flags, indicating the mode + if (m_next_status_id) + { + if (m_fm.regs().new2flag()) + result = 0x02; + else if (m_fm.regs().newflag()) + result = 0x00; + else + result = 0x06; + m_next_status_id = false; + } + else + { + result = m_fm.status(); + if (m_fm.intf().ymfm_is_busy()) + result |= STATUS_BUSY; + if (m_load_remaining != 0) + result |= STATUS_LD; + + // if new2 flag is not set, we're in OPL2 or OPL3 mode + if (!m_fm.regs().new2flag()) + result &= ~(STATUS_BUSY | STATUS_LD); + } + return result; +} + + +//------------------------------------------------- +// write_data_pcm - handle a write to the PCM data +// register +//------------------------------------------------- + +uint8_t ymf278b::read_data_pcm() +{ + // read from PCM + if (bitfield(m_address, 9) != 0) + { + uint8_t result = m_pcm.read(m_address & 0xff); + if ((m_address & 0xff) == 0x02) + result |= 0x20; + + return result; + } + return 0; +} + + +//------------------------------------------------- +// read - handle a read from the device +//------------------------------------------------- + +uint8_t ymf278b::read(uint32_t offset) +{ + uint8_t result = 0xff; + switch (offset & 7) + { + case 0: // status port + result = read_status(); + break; + + case 5: // PCM data port + result = read_data_pcm(); + break; + + default: + debug::log_unexpected_read_write("Unexpected read from ymf278b offset %d\n", offset & 3); + break; + } + return result; +} + + +//------------------------------------------------- +// write_address - handle a write to the address +// register +//------------------------------------------------- + +void ymf278b::write_address(uint8_t data) +{ + // just set the address + m_address = data; +} + + +//------------------------------------------------- +// write_data - handle a write to the data +// register +//------------------------------------------------- + +void ymf278b::write_data(uint8_t data) +{ + // write to FM + if (bitfield(m_address, 9) == 0) + { + uint8_t old = m_fm.regs().new2flag(); + m_fm.write(m_address, data); + + // changing NEW2 from 0->1 causes the next status read to + // return the chip ID + if (old == 0 && m_fm.regs().new2flag() != 0) + m_next_status_id = true; + } + + // BUSY goes for 56 clocks on FM writes + m_fm.intf().ymfm_set_busy_end(56); +} + + +//------------------------------------------------- +// write_address_hi - handle a write to the upper +// address register +//------------------------------------------------- + +void ymf278b::write_address_hi(uint8_t data) +{ + // just set the address + m_address = data | 0x100; + + // YMF262, in compatibility mode, treats the upper bit as masked + // except for register 0x105; assuming YMF278B works the same way? + if (m_fm.regs().newflag() == 0 && m_address != 0x105) + m_address &= 0xff; +} + + +//------------------------------------------------- +// write_address_pcm - handle a write to the upper +// address register +//------------------------------------------------- + +void ymf278b::write_address_pcm(uint8_t data) +{ + // just set the address + m_address = data | 0x200; +} + + +//------------------------------------------------- +// write_data_pcm - handle a write to the PCM data +// register +//------------------------------------------------- + +void ymf278b::write_data_pcm(uint8_t data) +{ + // ignore data writes if new2 is not yet set + if (m_fm.regs().new2flag() == 0) + return; + + // write to FM + if (bitfield(m_address, 9) != 0) + { + uint8_t addr = m_address & 0xff; + m_pcm.write(addr, data); + + // writes to the waveform number cause loads to happen for "about 300usec" + // which is ~13 samples at the nominal output frequency of 44.1kHz + if (addr >= 0x08 && addr <= 0x1f) + m_load_remaining = 13; + } + + // BUSY goes for 88 clocks on PCM writes + m_fm.intf().ymfm_set_busy_end(88); +} + + +//------------------------------------------------- +// write - handle a write to the register +// interface +//------------------------------------------------- + +void ymf278b::write(uint32_t offset, uint8_t data) +{ + switch (offset & 7) + { + case 0: // address port + write_address(data); + break; + + case 1: // data port + write_data(data); + break; + + case 2: // address port + write_address_hi(data); + break; + + case 3: // data port + write_data(data); + break; + + case 4: // PCM address port + write_address_pcm(data); + break; + + case 5: // PCM address port + write_data_pcm(data); + break; + + default: + debug::log_unexpected_read_write("Unexpected write to ymf278b offset %d\n", offset & 7); + break; + } +} + + +//------------------------------------------------- +// generate - generate one sample of sound +//------------------------------------------------- + +void ymf278b::generate(output_data *output, uint32_t numsamples) +{ + static const int16_t s_mix_scale[8] = { 0x7fa, 0x5a4, 0x3fd, 0x2d2, 0x1fe, 0x169, 0xff, 0 }; + int32_t const pcm_l = s_mix_scale[m_pcm.regs().mix_pcm_l()]; + int32_t const pcm_r = s_mix_scale[m_pcm.regs().mix_pcm_r()]; + int32_t const fm_l = s_mix_scale[m_pcm.regs().mix_fm_l()]; + int32_t const fm_r = s_mix_scale[m_pcm.regs().mix_fm_r()]; + for (uint32_t samp = 0; samp < numsamples; samp++, output++) + { + // clock the system + m_fm_pos += FM_EXTRA_SAMPLE_STEP; + if (m_fm_pos >= FM_EXTRA_SAMPLE_THRESH) + { + m_fm.clock(fm_engine::ALL_CHANNELS); + m_fm_pos -= FM_EXTRA_SAMPLE_THRESH; + } + m_fm.clock(fm_engine::ALL_CHANNELS); + m_pcm.clock(pcm_engine::ALL_CHANNELS); + + // update the FM content; mixing details for YMF278B need verification + fm_engine::output_data fmout; + m_fm.output(fmout.clear(), 0, 32767, fm_engine::ALL_CHANNELS); + + // update the PCM content + pcm_engine::output_data pcmout; + m_pcm.output(pcmout.clear(), pcm_engine::ALL_CHANNELS); + + // DO0 output: FM channels 2+3 only + output->data[0] = fmout.data[2]; + output->data[1] = fmout.data[3]; + + // DO1 output: wavetable channels 2+3 only + output->data[2] = pcmout.data[2]; + output->data[3] = pcmout.data[3]; + + // DO2 output: mixed FM channels 0+1 and wavetable channels 0+1 + output->data[4] = (fmout.data[0] * fm_l + pcmout.data[0] * pcm_l) >> 11; + output->data[5] = (fmout.data[1] * fm_r + pcmout.data[1] * pcm_r) >> 11; + + // YMF278B output is 16-bit 2s complement serial + output->clamp16(); + } + + // decrement the load waiting count + if (m_load_remaining > 0) + m_load_remaining -= std::min(m_load_remaining, numsamples); +} + + + +//********************************************************* +// OPLL BASE +//********************************************************* + +//------------------------------------------------- +// opll_base - constructor +//------------------------------------------------- + +opll_base::opll_base(ymfm_interface &intf, uint8_t const *instrument_data) : + m_address(0), + m_fm(intf) +{ + m_fm.regs().set_instrument_data(instrument_data); +} + + +//------------------------------------------------- +// reset - reset the system +//------------------------------------------------- + +void opll_base::reset() +{ + // reset the engines + m_fm.reset(); +} + + +//------------------------------------------------- +// save_restore - save or restore the data +//------------------------------------------------- + +void opll_base::save_restore(ymfm_saved_state &state) +{ + state.save_restore(m_address); + m_fm.save_restore(state); +} + + +//------------------------------------------------- +// write_address - handle a write to the address +// register +//------------------------------------------------- + +void opll_base::write_address(uint8_t data) +{ + // OPLL doesn't expose a busy signal, but datasheets are pretty consistent + // in indicating that address writes should be no faster than every 12 clocks + m_fm.intf().ymfm_set_busy_end(12); + + // just set the address + m_address = data; +} + + +//------------------------------------------------- +// write - handle a write to the register +// interface +//------------------------------------------------- + +void opll_base::write_data(uint8_t data) +{ + // OPLL doesn't expose a busy signal, but datasheets are pretty consistent + // in indicating that address writes should be no faster than every 84 clocks + m_fm.intf().ymfm_set_busy_end(84); + + // write to FM + m_fm.write(m_address, data); +} + + +//------------------------------------------------- +// write - handle a write to the register +// interface +//------------------------------------------------- + +void opll_base::write(uint32_t offset, uint8_t data) +{ + switch (offset & 1) + { + case 0: // address port + write_address(data); + break; + + case 1: // data port + write_data(data); + break; + } +} + + +//------------------------------------------------- +// generate - generate one sample of sound +//------------------------------------------------- + +void opll_base::generate(output_data *output, uint32_t numsamples) +{ + for (uint32_t samp = 0; samp < numsamples; samp++, output++) + { + // clock the system + m_fm.clock(fm_engine::ALL_CHANNELS); + + // update the FM content; OPLL has a built-in 9-bit DAC + m_fm.output(output->clear(), 5, 256, fm_engine::ALL_CHANNELS); + + // final output is multiplexed; we don't simulate that here except + // to average over everything + output->data[0] = (output->data[0] * 128) / 9; + output->data[1] = (output->data[1] * 128) / 9; + } +} + + + +//********************************************************* +// YM2413 +//********************************************************* + +//------------------------------------------------- +// ym2413 - constructor +//------------------------------------------------- + +ym2413::ym2413(ymfm_interface &intf, uint8_t const *instrument_data) : + opll_base(intf, (instrument_data != nullptr) ? instrument_data : s_default_instruments) +{ +}; + +// table below taken from https://github.com/plgDavid/misc/wiki/Copyright-free-OPLL(x)-ROM-patches +uint8_t const ym2413::s_default_instruments[] = +{ + //April 2015 David Viens, tweaked May 19-21th 2015 Hubert Lamontagne + 0x71, 0x61, 0x1E, 0x17, 0xEF, 0x7F, 0x00, 0x17, //Violin + 0x13, 0x41, 0x1A, 0x0D, 0xF8, 0xF7, 0x23, 0x13, //Guitar + 0x13, 0x01, 0x99, 0x00, 0xF2, 0xC4, 0x11, 0x23, //Piano + 0x31, 0x61, 0x0E, 0x07, 0x98, 0x64, 0x70, 0x27, //Flute + 0x22, 0x21, 0x1E, 0x06, 0xBF, 0x76, 0x00, 0x28, //Clarinet + 0x31, 0x22, 0x16, 0x05, 0xE0, 0x71, 0x0F, 0x18, //Oboe + 0x21, 0x61, 0x1D, 0x07, 0x82, 0x8F, 0x10, 0x07, //Trumpet + 0x23, 0x21, 0x2D, 0x14, 0xFF, 0x7F, 0x00, 0x07, //Organ + 0x41, 0x61, 0x1B, 0x06, 0x64, 0x65, 0x10, 0x17, //Horn + 0x61, 0x61, 0x0B, 0x18, 0x85, 0xFF, 0x81, 0x07, //Synthesizer + 0x13, 0x01, 0x83, 0x11, 0xFA, 0xE4, 0x10, 0x04, //Harpsichord + 0x17, 0x81, 0x23, 0x07, 0xF8, 0xF8, 0x22, 0x12, //Vibraphone + 0x61, 0x50, 0x0C, 0x05, 0xF2, 0xF5, 0x29, 0x42, //Synthesizer Bass + 0x01, 0x01, 0x54, 0x03, 0xC3, 0x92, 0x03, 0x02, //Acoustic Bass + 0x41, 0x41, 0x89, 0x03, 0xF1, 0xE5, 0x11, 0x13, //Electric Guitar + 0x01, 0x01, 0x18, 0x0F, 0xDF, 0xF8, 0x6A, 0x6D, //rhythm 1 + 0x01, 0x01, 0x00, 0x00, 0xC8, 0xD8, 0xA7, 0x48, //rhythm 2 + 0x05, 0x01, 0x00, 0x00, 0xF8, 0xAA, 0x59, 0x55 //rhythm 3 +}; + + + +//********************************************************* +// YM2423 +//********************************************************* + +//------------------------------------------------- +// ym2423 - constructor +//------------------------------------------------- + +ym2423::ym2423(ymfm_interface &intf, uint8_t const *instrument_data) : + opll_base(intf, (instrument_data != nullptr) ? instrument_data : s_default_instruments) +{ +}; + +// table below taken from https://github.com/plgDavid/misc/wiki/Copyright-free-OPLL(x)-ROM-patches +uint8_t const ym2423::s_default_instruments[] = +{ + // May 4-6 2016 Hubert Lamontagne + // Doesn't seem to have any diff between opllx-x and opllx-y + // Drums seem identical to regular opll + 0x61, 0x61, 0x1B, 0x07, 0x94, 0x5F, 0x10, 0x06, //1 Strings Saw wave with vibrato Violin + 0x93, 0xB1, 0x51, 0x04, 0xF3, 0xF2, 0x70, 0xFB, //2 Guitar Jazz GuitarPiano + 0x41, 0x21, 0x11, 0x85, 0xF2, 0xF2, 0x70, 0x75, //3 Electric Guitar Same as OPLL No.15 Synth + 0x93, 0xB2, 0x28, 0x07, 0xF3, 0xF2, 0x70, 0xB4, //4 Electric Piano 2 Slow attack, tremoloDing-a-ling + 0x72, 0x31, 0x97, 0x05, 0x51, 0x6F, 0x60, 0x09, //5 Flute Same as OPLL No.4Clarinet + 0x13, 0x30, 0x18, 0x06, 0xF7, 0xF4, 0x50, 0x85, //6 Marimba Also be used as steel drumXyophone + 0x51, 0x31, 0x1C, 0x07, 0x51, 0x71, 0x20, 0x26, //7 Trumpet Same as OPLL No.7Trumpet + 0x41, 0xF4, 0x1B, 0x07, 0x74, 0x34, 0x00, 0x06, //8 Harmonica Harmonica synth + 0x50, 0x30, 0x4D, 0x03, 0x42, 0x65, 0x20, 0x06, //9 Tuba Tuba + 0x40, 0x20, 0x10, 0x85, 0xF3, 0xF5, 0x20, 0x04, //10 Synth Brass 2 Synth sweep + 0x61, 0x61, 0x1B, 0x07, 0xC5, 0x96, 0xF3, 0xF6, //11 Short Saw Saw wave with short envelopeSynth hit + 0xF9, 0xF1, 0xDC, 0x00, 0xF5, 0xF3, 0x77, 0xF2, //12 Vibraphone Bright vibraphoneVibes + 0x60, 0xA2, 0x91, 0x03, 0x94, 0xC1, 0xF7, 0xF7, //13 Electric Guitar 2 Clean guitar with feedbackHarmonic bass + 0x30, 0x30, 0x17, 0x06, 0xF3, 0xF1, 0xB7, 0xFC, //14 Synth Bass 2Snappy bass + 0x31, 0x36, 0x0D, 0x05, 0xF2, 0xF4, 0x27, 0x9C, //15 Sitar Also be used as ShamisenBanjo + 0x01, 0x01, 0x18, 0x0F, 0xDF, 0xF8, 0x6A, 0x6D, //rhythm 1 + 0x01, 0x01, 0x00, 0x00, 0xC8, 0xD8, 0xA7, 0x48, //rhythm 2 + 0x05, 0x01, 0x00, 0x00, 0xF8, 0xAA, 0x59, 0x55 //rhythm 3 +}; + + + +//********************************************************* +// YMF281 +//********************************************************* + +//------------------------------------------------- +// ymf281 - constructor +//------------------------------------------------- + +ymf281::ymf281(ymfm_interface &intf, uint8_t const *instrument_data) : + opll_base(intf, (instrument_data != nullptr) ? instrument_data : s_default_instruments) +{ +}; + +// table below taken from https://github.com/plgDavid/misc/wiki/Copyright-free-OPLL(x)-ROM-patches +uint8_t const ymf281::s_default_instruments[] = +{ + // May 14th 2015 Hubert Lamontagne + 0x72, 0x21, 0x1A, 0x07, 0xF6, 0x64, 0x01, 0x16, // Clarinet ~~ Electric String Square wave with vibrato + 0x00, 0x10, 0x45, 0x00, 0xF6, 0x83, 0x73, 0x63, // Synth Bass ~~ Bow wow Triangular wave + 0x13, 0x01, 0x96, 0x00, 0xF1, 0xF4, 0x31, 0x23, // Piano ~~ Electric Guitar Despite of its name, same as Piano of YM2413. + 0x71, 0x21, 0x0B, 0x0F, 0xF9, 0x64, 0x70, 0x17, // Flute ~~ Organ Sine wave + 0x02, 0x21, 0x1E, 0x06, 0xF9, 0x76, 0x00, 0x28, // Square Wave ~~ Clarinet Same as ones of YM2413. + 0x00, 0x61, 0x82, 0x0E, 0xF9, 0x61, 0x20, 0x27, // Space Oboe ~~ Saxophone Saw wave with vibrato + 0x21, 0x61, 0x1B, 0x07, 0x84, 0x8F, 0x10, 0x07, // Trumpet ~~ Trumpet Same as ones of YM2413. + 0x37, 0x32, 0xCA, 0x02, 0x66, 0x64, 0x47, 0x29, // Wow Bell ~~ Street Organ Calliope + 0x41, 0x41, 0x07, 0x03, 0xF5, 0x70, 0x51, 0xF5, // Electric Guitar ~~ Synth Brass Same as Synthesizer of YM2413. + 0x36, 0x01, 0x5E, 0x07, 0xF2, 0xF3, 0xF7, 0xF7, // Vibes ~~ Electric Piano Simulate of Rhodes Piano + 0x00, 0x00, 0x18, 0x06, 0xC5, 0xF3, 0x20, 0xF2, // Bass ~~ Bass Electric bass + 0x17, 0x81, 0x25, 0x07, 0xF7, 0xF3, 0x21, 0xF7, // Vibraphone ~~ Vibraphone Same as ones of YM2413. + 0x35, 0x64, 0x00, 0x00, 0xFF, 0xF3, 0x77, 0xF5, // Vibrato Bell ~~ Chime Bell + 0x11, 0x31, 0x00, 0x07, 0xDD, 0xF3, 0xFF, 0xFB, // Click Sine ~~ Tom Tom II Tom + 0x3A, 0x21, 0x00, 0x07, 0x95, 0x84, 0x0F, 0xF5, // Noise and Tone ~~ Noise for S.E. + 0x01, 0x01, 0x18, 0x0F, 0xDF, 0xF8, 0x6A, 0x6D, //rhythm 1 + 0x01, 0x01, 0x00, 0x00, 0xC8, 0xD8, 0xA7, 0x48, //rhythm 2 + 0x05, 0x01, 0x00, 0x00, 0xF8, 0xAA, 0x59, 0x55 //rhythm 3 +}; + + + +//********************************************************* +// DS1001 +//********************************************************* + +//------------------------------------------------- +// ds1001 - constructor +//------------------------------------------------- + +ds1001::ds1001(ymfm_interface &intf, uint8_t const *instrument_data) : + opll_base(intf, (instrument_data != nullptr) ? instrument_data : s_default_instruments) +{ +}; + +// table below taken from https://github.com/plgDavid/misc/wiki/Copyright-free-OPLL(x)-ROM-patches +uint8_t const ds1001::s_default_instruments[] = +{ + // May 15th 2015 Hubert Lamontagne & David Viens + 0x03, 0x21, 0x05, 0x06, 0xC8, 0x81, 0x42, 0x27, // Buzzy Bell + 0x13, 0x41, 0x14, 0x0D, 0xF8, 0xF7, 0x23, 0x12, // Guitar + 0x31, 0x11, 0x08, 0x08, 0xFA, 0xC2, 0x28, 0x22, // Wurly + 0x31, 0x61, 0x0C, 0x07, 0xF8, 0x64, 0x60, 0x27, // Flute + 0x22, 0x21, 0x1E, 0x06, 0xFF, 0x76, 0x00, 0x28, // Clarinet + 0x02, 0x01, 0x05, 0x00, 0xAC, 0xF2, 0x03, 0x02, // Synth + 0x21, 0x61, 0x1D, 0x07, 0x82, 0x8F, 0x10, 0x07, // Trumpet + 0x23, 0x21, 0x22, 0x17, 0xFF, 0x73, 0x00, 0x17, // Organ + 0x15, 0x11, 0x25, 0x00, 0x41, 0x71, 0x00, 0xF1, // Bells + 0x95, 0x01, 0x10, 0x0F, 0xB8, 0xAA, 0x50, 0x02, // Vibes + 0x17, 0xC1, 0x5E, 0x07, 0xFA, 0xF8, 0x22, 0x12, // Vibraphone + 0x71, 0x23, 0x11, 0x06, 0x65, 0x74, 0x10, 0x16, // Tutti + 0x01, 0x02, 0xD3, 0x05, 0xF3, 0x92, 0x83, 0xF2, // Fretless + 0x61, 0x63, 0x0C, 0x00, 0xA4, 0xFF, 0x30, 0x06, // Synth Bass + 0x21, 0x62, 0x0D, 0x00, 0xA1, 0xFF, 0x50, 0x08, // Sweep + 0x01, 0x01, 0x18, 0x0F, 0xDF, 0xF8, 0x6A, 0x6D, //rhythm 1 + 0x01, 0x01, 0x00, 0x00, 0xC8, 0xD8, 0xA7, 0x48, //rhythm 2 + 0x05, 0x01, 0x00, 0x00, 0xF8, 0xAA, 0x59, 0x55 //rhythm 3 +}; + + +//********************************************************* +// EXPLICIT INSTANTIATION +//********************************************************* + +template class opl_registers_base<4>; +template class fm_engine_base>; + +} diff --git a/src/sound/ymfm/ymfm_opl.h b/src/sound/ymfm/ymfm_opl.h new file mode 100644 index 000000000..843e5b274 --- /dev/null +++ b/src/sound/ymfm/ymfm_opl.h @@ -0,0 +1,902 @@ +// BSD 3-Clause License +// +// Copyright (c) 2021, Aaron Giles +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// 1. Redistributions of source code must retain the above copyright notice, this +// list of conditions and the following disclaimer. +// +// 2. Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// 3. Neither the name of the copyright holder nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#ifndef YMFM_OPL_H +#define YMFM_OPL_H + +#pragma once + +#include "ymfm.h" +#include "ymfm_adpcm.h" +#include "ymfm_fm.h" +#include "ymfm_pcm.h" + +namespace ymfm +{ + +//********************************************************* +// REGISTER CLASSES +//********************************************************* + +// ======================> opl_registers_base + +// +// OPL/OPL2/OPL3/OPL4 register map: +// +// System-wide registers: +// 01 xxxxxxxx Test register +// --x----- Enable OPL compatibility mode [OPL2 only] (1 = enable) +// 02 xxxxxxxx Timer A value (4 * OPN) +// 03 xxxxxxxx Timer B value +// 04 x------- RST +// -x------ Mask timer A +// --x----- Mask timer B +// ------x- Load timer B +// -------x Load timer A +// 08 x------- CSM mode [OPL/OPL2 only] +// -x------ Note select +// BD x------- AM depth +// -x------ PM depth +// --x----- Rhythm enable +// ---x---- Bass drum key on +// ----x--- Snare drum key on +// -----x-- Tom key on +// ------x- Top cymbal key on +// -------x High hat key on +// 101 --xxxxxx Test register 2 [OPL3 only] +// 104 --x----- Channel 6 4-operator mode [OPL3 only] +// ---x---- Channel 5 4-operator mode [OPL3 only] +// ----x--- Channel 4 4-operator mode [OPL3 only] +// -----x-- Channel 3 4-operator mode [OPL3 only] +// ------x- Channel 2 4-operator mode [OPL3 only] +// -------x Channel 1 4-operator mode [OPL3 only] +// 105 -------x New [OPL3 only] +// ------x- New2 [OPL4 only] +// +// Per-channel registers (channel in address bits 0-3) +// Note that all these apply to address+100 as well on OPL3+ +// A0-A8 xxxxxxxx F-number (low 8 bits) +// B0-B8 --x----- Key on +// ---xxx-- Block (octvate, 0-7) +// ------xx F-number (high two bits) +// C0-C8 x------- CHD output (to DO0 pin) [OPL3+ only] +// -x------ CHC output (to DO0 pin) [OPL3+ only] +// --x----- CHB output (mixed right, to DO2 pin) [OPL3+ only] +// ---x---- CHA output (mixed left, to DO2 pin) [OPL3+ only] +// ----xxx- Feedback level for operator 1 (0-7) +// -------x Operator connection algorithm +// +// Per-operator registers (operator in bits 0-5) +// Note that all these apply to address+100 as well on OPL3+ +// 20-35 x------- AM enable +// -x------ PM enable (VIB) +// --x----- EG type +// ---x---- Key scale rate +// ----xxxx Multiple value (0-15) +// 40-55 xx------ Key scale level (0-3) +// --xxxxxx Total level (0-63) +// 60-75 xxxx---- Attack rate (0-15) +// ----xxxx Decay rate (0-15) +// 80-95 xxxx---- Sustain level (0-15) +// ----xxxx Release rate (0-15) +// E0-F5 ------xx Wave select (0-3) [OPL2 only] +// -----xxx Wave select (0-7) [OPL3+ only] +// + +template +class opl_registers_base : public fm_registers_base +{ + static constexpr bool IsOpl2 = (Revision == 2); + static constexpr bool IsOpl2Plus = (Revision >= 2); + static constexpr bool IsOpl3Plus = (Revision >= 3); + static constexpr bool IsOpl4Plus = (Revision >= 4); + +public: + // constants + static constexpr uint32_t OUTPUTS = IsOpl3Plus ? 4 : 1; + static constexpr uint32_t CHANNELS = IsOpl3Plus ? 18 : 9; + static constexpr uint32_t ALL_CHANNELS = (1 << CHANNELS) - 1; + static constexpr uint32_t OPERATORS = CHANNELS * 2; + static constexpr uint32_t WAVEFORMS = IsOpl3Plus ? 8 : (IsOpl2Plus ? 4 : 1); + static constexpr uint32_t REGISTERS = IsOpl3Plus ? 0x200 : 0x100; + static constexpr uint32_t REG_MODE = 0x04; + static constexpr uint32_t DEFAULT_PRESCALE = IsOpl4Plus ? 19 : (IsOpl3Plus ? 8 : 4); + static constexpr uint32_t EG_CLOCK_DIVIDER = 1; + static constexpr uint32_t CSM_TRIGGER_MASK = ALL_CHANNELS; + static constexpr bool DYNAMIC_OPS = IsOpl3Plus; + static constexpr bool MODULATOR_DELAY = !IsOpl3Plus; + static constexpr uint8_t STATUS_TIMERA = 0x40; + static constexpr uint8_t STATUS_TIMERB = 0x20; + static constexpr uint8_t STATUS_BUSY = 0; + static constexpr uint8_t STATUS_IRQ = 0x80; + + // constructor + opl_registers_base(); + + // reset to initial state + void reset(); + + // save/restore + void save_restore(ymfm_saved_state &state); + + // map channel number to register offset + static constexpr uint32_t channel_offset(uint32_t chnum) + { + assert(chnum < CHANNELS); + if (!IsOpl3Plus) + return chnum; + else + return (chnum % 9) + 0x100 * (chnum / 9); + } + + // map operator number to register offset + static constexpr uint32_t operator_offset(uint32_t opnum) + { + assert(opnum < OPERATORS); + if (!IsOpl3Plus) + return opnum + 2 * (opnum / 6); + else + return (opnum % 18) + 2 * ((opnum % 18) / 6) + 0x100 * (opnum / 18); + } + + // return an array of operator indices for each channel + struct operator_mapping { uint32_t chan[CHANNELS]; }; + void operator_map(operator_mapping &dest) const; + + // OPL4 apparently can read back FM registers? + uint8_t read(uint16_t index) const { return m_regdata[index]; } + + // handle writes to the register array + bool write(uint16_t index, uint8_t data, uint32_t &chan, uint32_t &opmask); + + // clock the noise and LFO, if present, returning LFO PM value + int32_t clock_noise_and_lfo(); + + // reset the LFO + void reset_lfo() { m_lfo_am_counter = m_lfo_pm_counter = 0; } + + // return the AM offset from LFO for the given channel + // on OPL this is just a fixed value + uint32_t lfo_am_offset(uint32_t choffs) const { return m_lfo_am; } + + // return LFO/noise states + uint32_t noise_state() const { return m_noise_lfsr >> 23; } + + // caching helpers + void cache_operator_data(uint32_t choffs, uint32_t opoffs, opdata_cache &cache); + + // compute the phase step, given a PM value + uint32_t compute_phase_step(uint32_t choffs, uint32_t opoffs, opdata_cache const &cache, int32_t lfo_raw_pm); + + // log a key-on event + std::string log_keyon(uint32_t choffs, uint32_t opoffs); + + // system-wide registers + uint32_t test() const { return byte(0x01, 0, 8); } + uint32_t waveform_enable() const { return IsOpl2 ? byte(0x01, 5, 1) : (IsOpl3Plus ? 1 : 0); } + uint32_t timer_a_value() const { return byte(0x02, 0, 8) * 4; } // 8->10 bits + uint32_t timer_b_value() const { return byte(0x03, 0, 8); } + uint32_t status_mask() const { return byte(0x04, 0, 8) & 0x78; } + uint32_t irq_reset() const { return byte(0x04, 7, 1); } + uint32_t reset_timer_b() const { return byte(0x04, 7, 1) | byte(0x04, 5, 1); } + uint32_t reset_timer_a() const { return byte(0x04, 7, 1) | byte(0x04, 6, 1); } + uint32_t enable_timer_b() const { return 1; } + uint32_t enable_timer_a() const { return 1; } + uint32_t load_timer_b() const { return byte(0x04, 1, 1); } + uint32_t load_timer_a() const { return byte(0x04, 0, 1); } + uint32_t csm() const { return IsOpl3Plus ? 0 : byte(0x08, 7, 1); } + uint32_t note_select() const { return byte(0x08, 6, 1); } + uint32_t lfo_am_depth() const { return byte(0xbd, 7, 1); } + uint32_t lfo_pm_depth() const { return byte(0xbd, 6, 1); } + uint32_t rhythm_enable() const { return byte(0xbd, 5, 1); } + uint32_t rhythm_keyon() const { return byte(0xbd, 4, 0); } + uint32_t newflag() const { return IsOpl3Plus ? byte(0x105, 0, 1) : 0; } + uint32_t new2flag() const { return IsOpl4Plus ? byte(0x105, 1, 1) : 0; } + uint32_t fourop_enable() const { return IsOpl3Plus ? byte(0x104, 0, 6) : 0; } + + // per-channel registers + uint32_t ch_block_freq(uint32_t choffs) const { return word(0xb0, 0, 5, 0xa0, 0, 8, choffs); } + uint32_t ch_feedback(uint32_t choffs) const { return byte(0xc0, 1, 3, choffs); } + uint32_t ch_algorithm(uint32_t choffs) const { return byte(0xc0, 0, 1, choffs) | (IsOpl3Plus ? (8 | (byte(0xc3, 0, 1, choffs) << 1)) : 0); } + uint32_t ch_output_any(uint32_t choffs) const { return newflag() ? byte(0xc0 + choffs, 4, 4) : 1; } + uint32_t ch_output_0(uint32_t choffs) const { return newflag() ? byte(0xc0 + choffs, 4, 1) : 1; } + uint32_t ch_output_1(uint32_t choffs) const { return newflag() ? byte(0xc0 + choffs, 5, 1) : (IsOpl3Plus ? 1 : 0); } + uint32_t ch_output_2(uint32_t choffs) const { return newflag() ? byte(0xc0 + choffs, 6, 1) : 0; } + uint32_t ch_output_3(uint32_t choffs) const { return newflag() ? byte(0xc0 + choffs, 7, 1) : 0; } + + // per-operator registers + uint32_t op_lfo_am_enable(uint32_t opoffs) const { return byte(0x20, 7, 1, opoffs); } + uint32_t op_lfo_pm_enable(uint32_t opoffs) const { return byte(0x20, 6, 1, opoffs); } + uint32_t op_eg_sustain(uint32_t opoffs) const { return byte(0x20, 5, 1, opoffs); } + uint32_t op_ksr(uint32_t opoffs) const { return byte(0x20, 4, 1, opoffs); } + uint32_t op_multiple(uint32_t opoffs) const { return byte(0x20, 0, 4, opoffs); } + uint32_t op_ksl(uint32_t opoffs) const { uint32_t temp = byte(0x40, 6, 2, opoffs); return bitfield(temp, 1) | (bitfield(temp, 0) << 1); } + uint32_t op_total_level(uint32_t opoffs) const { return byte(0x40, 0, 6, opoffs); } + uint32_t op_attack_rate(uint32_t opoffs) const { return byte(0x60, 4, 4, opoffs); } + uint32_t op_decay_rate(uint32_t opoffs) const { return byte(0x60, 0, 4, opoffs); } + uint32_t op_sustain_level(uint32_t opoffs) const { return byte(0x80, 4, 4, opoffs); } + uint32_t op_release_rate(uint32_t opoffs) const { return byte(0x80, 0, 4, opoffs); } + uint32_t op_waveform(uint32_t opoffs) const { return IsOpl2Plus ? byte(0xe0, 0, newflag() ? 3 : 2, opoffs) : 0; } + +protected: + // return a bitfield extracted from a byte + uint32_t byte(uint32_t offset, uint32_t start, uint32_t count, uint32_t extra_offset = 0) const + { + return bitfield(m_regdata[offset + extra_offset], start, count); + } + + // return a bitfield extracted from a pair of bytes, MSBs listed first + uint32_t word(uint32_t offset1, uint32_t start1, uint32_t count1, uint32_t offset2, uint32_t start2, uint32_t count2, uint32_t extra_offset = 0) const + { + return (byte(offset1, start1, count1, extra_offset) << count2) | byte(offset2, start2, count2, extra_offset); + } + + // helper to determine if the this channel is an active rhythm channel + bool is_rhythm(uint32_t choffs) const + { + return rhythm_enable() && (choffs >= 6 && choffs <= 8); + } + + // internal state + uint16_t m_lfo_am_counter; // LFO AM counter + uint16_t m_lfo_pm_counter; // LFO PM counter + uint32_t m_noise_lfsr; // noise LFSR state + uint8_t m_lfo_am; // current LFO AM value + uint8_t m_regdata[REGISTERS]; // register data + uint16_t m_waveform[WAVEFORMS][WAVEFORM_LENGTH]; // waveforms +}; + +using opl_registers = opl_registers_base<1>; +using opl2_registers = opl_registers_base<2>; +using opl3_registers = opl_registers_base<3>; +using opl4_registers = opl_registers_base<4>; + + + +// ======================> opll_registers + +// +// OPLL register map: +// +// System-wide registers: +// 0E --x----- Rhythm enable +// ---x---- Bass drum key on +// ----x--- Snare drum key on +// -----x-- Tom key on +// ------x- Top cymbal key on +// -------x High hat key on +// 0F xxxxxxxx Test register +// +// Per-channel registers (channel in address bits 0-3) +// 10-18 xxxxxxxx F-number (low 8 bits) +// 20-28 --x----- Sustain on +// ---x---- Key on +// --- xxx- Block (octvate, 0-7) +// -------x F-number (high bit) +// 30-38 xxxx---- Instrument selection +// ----xxxx Volume +// +// User instrument registers (for carrier, modulator operators) +// 00-01 x------- AM enable +// -x------ PM enable (VIB) +// --x----- EG type +// ---x---- Key scale rate +// ----xxxx Multiple value (0-15) +// 02 xx------ Key scale level (carrier, 0-3) +// --xxxxxx Total level (modulator, 0-63) +// 03 xx------ Key scale level (modulator, 0-3) +// ---x---- Rectified wave (carrier) +// ----x--- Rectified wave (modulator) +// -----xxx Feedback level for operator 1 (0-7) +// 04-05 xxxx---- Attack rate (0-15) +// ----xxxx Decay rate (0-15) +// 06-07 xxxx---- Sustain level (0-15) +// ----xxxx Release rate (0-15) +// +// Internal (fake) registers: +// 40-48 xxxxxxxx Current instrument base address +// 4E-5F xxxxxxxx Current instrument base address + operator slot (0/1) +// 70-FF xxxxxxxx Data for instruments (1-16 plus 3 drums) +// + +class opll_registers : public fm_registers_base +{ +public: + static constexpr uint32_t OUTPUTS = 2; + static constexpr uint32_t CHANNELS = 9; + static constexpr uint32_t ALL_CHANNELS = (1 << CHANNELS) - 1; + static constexpr uint32_t OPERATORS = CHANNELS * 2; + static constexpr uint32_t WAVEFORMS = 2; + static constexpr uint32_t REGISTERS = 0x40; + static constexpr uint32_t REG_MODE = 0x3f; + static constexpr uint32_t DEFAULT_PRESCALE = 4; + static constexpr uint32_t EG_CLOCK_DIVIDER = 1; + static constexpr uint32_t CSM_TRIGGER_MASK = 0; + static constexpr bool EG_HAS_DEPRESS = true; + static constexpr bool MODULATOR_DELAY = true; + static constexpr uint8_t STATUS_TIMERA = 0; + static constexpr uint8_t STATUS_TIMERB = 0; + static constexpr uint8_t STATUS_BUSY = 0; + static constexpr uint8_t STATUS_IRQ = 0; + + // OPLL-specific constants + static constexpr uint32_t INSTDATA_SIZE = 0x90; + + // constructor + opll_registers(); + + // reset to initial state + void reset(); + + // save/restore + void save_restore(ymfm_saved_state &state); + + // map channel number to register offset + static constexpr uint32_t channel_offset(uint32_t chnum) + { + assert(chnum < CHANNELS); + return chnum; + } + + // map operator number to register offset + static constexpr uint32_t operator_offset(uint32_t opnum) + { + assert(opnum < OPERATORS); + return opnum; + } + + // return an array of operator indices for each channel + struct operator_mapping { uint32_t chan[CHANNELS]; }; + void operator_map(operator_mapping &dest) const; + + // read a register value + uint8_t read(uint16_t index) const { return m_regdata[index]; } + + // handle writes to the register array + bool write(uint16_t index, uint8_t data, uint32_t &chan, uint32_t &opmask); + + // clock the noise and LFO, if present, returning LFO PM value + int32_t clock_noise_and_lfo(); + + // reset the LFO + void reset_lfo() { m_lfo_am_counter = m_lfo_pm_counter = 0; } + + // return the AM offset from LFO for the given channel + // on OPL this is just a fixed value + uint32_t lfo_am_offset(uint32_t choffs) const { return m_lfo_am; } + + // return LFO/noise states + uint32_t noise_state() const { return m_noise_lfsr >> 23; } + + // caching helpers + void cache_operator_data(uint32_t choffs, uint32_t opoffs, opdata_cache &cache); + + // compute the phase step, given a PM value + uint32_t compute_phase_step(uint32_t choffs, uint32_t opoffs, opdata_cache const &cache, int32_t lfo_raw_pm); + + // log a key-on event + std::string log_keyon(uint32_t choffs, uint32_t opoffs); + + // set the instrument data + void set_instrument_data(uint8_t const *data) + { + std::copy_n(data, INSTDATA_SIZE, &m_instdata[0]); + } + + // system-wide registers + uint32_t rhythm_enable() const { return byte(0x0e, 5, 1); } + uint32_t rhythm_keyon() const { return byte(0x0e, 4, 0); } + uint32_t test() const { return byte(0x0f, 0, 8); } + uint32_t waveform_enable() const { return 1; } + uint32_t timer_a_value() const { return 0; } + uint32_t timer_b_value() const { return 0; } + uint32_t status_mask() const { return 0; } + uint32_t irq_reset() const { return 0; } + uint32_t reset_timer_b() const { return 0; } + uint32_t reset_timer_a() const { return 0; } + uint32_t enable_timer_b() const { return 0; } + uint32_t enable_timer_a() const { return 0; } + uint32_t load_timer_b() const { return 0; } + uint32_t load_timer_a() const { return 0; } + uint32_t csm() const { return 0; } + + // per-channel registers + uint32_t ch_block_freq(uint32_t choffs) const { return word(0x20, 0, 4, 0x10, 0, 8, choffs); } + uint32_t ch_sustain(uint32_t choffs) const { return byte(0x20, 5, 1, choffs); } + uint32_t ch_total_level(uint32_t choffs) const { return instchbyte(0x02, 0, 6, choffs); } + uint32_t ch_feedback(uint32_t choffs) const { return instchbyte(0x03, 0, 3, choffs); } + uint32_t ch_algorithm(uint32_t choffs) const { return 0; } + uint32_t ch_instrument(uint32_t choffs) const { return byte(0x30, 4, 4, choffs); } + uint32_t ch_output_any(uint32_t choffs) const { return 1; } + uint32_t ch_output_0(uint32_t choffs) const { return !is_rhythm(choffs); } + uint32_t ch_output_1(uint32_t choffs) const { return is_rhythm(choffs); } + uint32_t ch_output_2(uint32_t choffs) const { return 0; } + uint32_t ch_output_3(uint32_t choffs) const { return 0; } + + // per-operator registers + uint32_t op_lfo_am_enable(uint32_t opoffs) const { return instopbyte(0x00, 7, 1, opoffs); } + uint32_t op_lfo_pm_enable(uint32_t opoffs) const { return instopbyte(0x00, 6, 1, opoffs); } + uint32_t op_eg_sustain(uint32_t opoffs) const { return instopbyte(0x00, 5, 1, opoffs); } + uint32_t op_ksr(uint32_t opoffs) const { return instopbyte(0x00, 4, 1, opoffs); } + uint32_t op_multiple(uint32_t opoffs) const { return instopbyte(0x00, 0, 4, opoffs); } + uint32_t op_ksl(uint32_t opoffs) const { return instopbyte(0x02, 6, 2, opoffs); } + uint32_t op_waveform(uint32_t opoffs) const { return instchbyte(0x03, 3 + bitfield(opoffs, 0), 1, opoffs >> 1); } + uint32_t op_attack_rate(uint32_t opoffs) const { return instopbyte(0x04, 4, 4, opoffs); } + uint32_t op_decay_rate(uint32_t opoffs) const { return instopbyte(0x04, 0, 4, opoffs); } + uint32_t op_sustain_level(uint32_t opoffs) const { return instopbyte(0x06, 4, 4, opoffs); } + uint32_t op_release_rate(uint32_t opoffs) const { return instopbyte(0x06, 0, 4, opoffs); } + uint32_t op_volume(uint32_t opoffs) const { return byte(0x30, 4 * bitfield(~opoffs, 0), 4, opoffs >> 1); } + +private: + // return a bitfield extracted from a byte + uint32_t byte(uint32_t offset, uint32_t start, uint32_t count, uint32_t extra_offset = 0) const + { + return bitfield(m_regdata[offset + extra_offset], start, count); + } + + // return a bitfield extracted from a pair of bytes, MSBs listed first + uint32_t word(uint32_t offset1, uint32_t start1, uint32_t count1, uint32_t offset2, uint32_t start2, uint32_t count2, uint32_t extra_offset = 0) const + { + return (byte(offset1, start1, count1, extra_offset) << count2) | byte(offset2, start2, count2, extra_offset); + } + + // helpers to read from instrument channel/operator data + uint32_t instchbyte(uint32_t offset, uint32_t start, uint32_t count, uint32_t choffs) const { return bitfield(m_chinst[choffs][offset], start, count); } + uint32_t instopbyte(uint32_t offset, uint32_t start, uint32_t count, uint32_t opoffs) const { return bitfield(m_opinst[opoffs][offset], start, count); } + + // helper to determine if the this channel is an active rhythm channel + bool is_rhythm(uint32_t choffs) const + { + return rhythm_enable() && choffs >= 6; + } + + // internal state + uint16_t m_lfo_am_counter; // LFO AM counter + uint16_t m_lfo_pm_counter; // LFO PM counter + uint32_t m_noise_lfsr; // noise LFSR state + uint8_t m_lfo_am; // current LFO AM value + uint8_t const *m_chinst[CHANNELS]; // pointer to instrument data for each channel + uint8_t const *m_opinst[OPERATORS]; // pointer to instrument data for each operator + uint8_t m_regdata[REGISTERS]; // register data + uint8_t m_instdata[INSTDATA_SIZE]; // instrument data + uint16_t m_waveform[WAVEFORMS][WAVEFORM_LENGTH]; // waveforms +}; + + + +//********************************************************* +// OPL IMPLEMENTATION CLASSES +//********************************************************* + +// ======================> ym3526 + +class ym3526 +{ +public: + using fm_engine = fm_engine_base; + using output_data = fm_engine::output_data; + static constexpr uint32_t OUTPUTS = fm_engine::OUTPUTS; + + // constructor + ym3526(ymfm_interface &intf); + + // reset + void reset(); + + // save/restore + void save_restore(ymfm_saved_state &state); + + // pass-through helpers + uint32_t sample_rate(uint32_t input_clock) const { return m_fm.sample_rate(input_clock); } + void invalidate_caches() { m_fm.invalidate_caches(); } + + // read access + uint8_t read_status(); + uint8_t read(uint32_t offset); + + // write access + void write_address(uint8_t data); + void write_data(uint8_t data); + void write(uint32_t offset, uint8_t data); + + // generate samples of sound + void generate(output_data *output, uint32_t numsamples = 1); +protected: + // internal state + uint8_t m_address; // address register + fm_engine m_fm; // core FM engine +}; + + +// ======================> y8950 + +class y8950 +{ +public: + using fm_engine = fm_engine_base; + using output_data = fm_engine::output_data; + static constexpr uint32_t OUTPUTS = fm_engine::OUTPUTS; + + static constexpr uint8_t STATUS_ADPCM_B_PLAYING = 0x01; + static constexpr uint8_t STATUS_ADPCM_B_BRDY = 0x08; + static constexpr uint8_t STATUS_ADPCM_B_EOS = 0x10; + static constexpr uint8_t ALL_IRQS = STATUS_ADPCM_B_BRDY | STATUS_ADPCM_B_EOS | fm_engine::STATUS_TIMERA | fm_engine::STATUS_TIMERB; + + // constructor + y8950(ymfm_interface &intf); + + // reset + void reset(); + + // save/restore + void save_restore(ymfm_saved_state &state); + + // pass-through helpers + uint32_t sample_rate(uint32_t input_clock) const { return m_fm.sample_rate(input_clock); } + void invalidate_caches() { m_fm.invalidate_caches(); } + + // read access + uint8_t read_status(); + uint8_t read_data(); + uint8_t read(uint32_t offset); + + // write access + void write_address(uint8_t data); + void write_data(uint8_t data); + void write(uint32_t offset, uint8_t data); + + // generate samples of sound + void generate(output_data *output, uint32_t numsamples = 1); + +protected: + // internal state + uint8_t m_address; // address register + uint8_t m_io_ddr; // data direction register for I/O + fm_engine m_fm; // core FM engine + adpcm_b_engine m_adpcm_b; // ADPCM-B engine +}; + + + +//********************************************************* +// OPL2 IMPLEMENTATION CLASSES +//********************************************************* + +// ======================> ym3812 + +class ym3812 +{ +public: + using fm_engine = fm_engine_base; + using output_data = fm_engine::output_data; + static constexpr uint32_t OUTPUTS = fm_engine::OUTPUTS; + + // constructor + ym3812(ymfm_interface &intf); + + // reset + void reset(); + + // save/restore + void save_restore(ymfm_saved_state &state); + + // pass-through helpers + uint32_t sample_rate(uint32_t input_clock) const { return m_fm.sample_rate(input_clock); } + void invalidate_caches() { m_fm.invalidate_caches(); } + + // read access + uint8_t read_status(); + uint8_t read(uint32_t offset); + + // write access + void write_address(uint8_t data); + void write_data(uint8_t data); + void write(uint32_t offset, uint8_t data); + + // generate samples of sound + void generate(output_data *output, uint32_t numsamples = 1); + +protected: + // internal state + uint8_t m_address; // address register + fm_engine m_fm; // core FM engine +}; + + + +//********************************************************* +// OPL3 IMPLEMENTATION CLASSES +//********************************************************* + +// ======================> ymf262 + +class ymf262 +{ +public: + using fm_engine = fm_engine_base; + using output_data = fm_engine::output_data; + static constexpr uint32_t OUTPUTS = fm_engine::OUTPUTS; + + // constructor + ymf262(ymfm_interface &intf); + + // reset + void reset(); + + // save/restore + void save_restore(ymfm_saved_state &state); + + // pass-through helpers + uint32_t sample_rate(uint32_t input_clock) const { return m_fm.sample_rate(input_clock); } + void invalidate_caches() { m_fm.invalidate_caches(); } + + // read access + uint8_t read_status(); + uint8_t read(uint32_t offset); + + // write access + void write_address(uint8_t data); + void write_data(uint8_t data); + void write_address_hi(uint8_t data); + void write(uint32_t offset, uint8_t data); + + // generate samples of sound + void generate(output_data *output, uint32_t numsamples = 1); + +protected: + // internal state + uint16_t m_address; // address register + fm_engine m_fm; // core FM engine +}; + + +// ======================> ymf289b + +class ymf289b +{ + static constexpr uint8_t STATUS_BUSY_FLAGS = 0x05; + +public: + using fm_engine = fm_engine_base; + using output_data = fm_engine::output_data; + static constexpr uint32_t OUTPUTS = 2; + + // constructor + ymf289b(ymfm_interface &intf); + + // reset + void reset(); + + // save/restore + void save_restore(ymfm_saved_state &state); + + // pass-through helpers + uint32_t sample_rate(uint32_t input_clock) const { return m_fm.sample_rate(input_clock); } + void invalidate_caches() { m_fm.invalidate_caches(); } + + // read access + uint8_t read_status(); + uint8_t read_data(); + uint8_t read(uint32_t offset); + + // write access + void write_address(uint8_t data); + void write_data(uint8_t data); + void write_address_hi(uint8_t data); + void write(uint32_t offset, uint8_t data); + + // generate samples of sound + void generate(output_data *output, uint32_t numsamples = 1); + +protected: + // internal helpers + bool ymf289b_mode() { return ((m_fm.regs().read(0x105) & 0x04) != 0); } + + // internal state + uint16_t m_address; // address register + fm_engine m_fm; // core FM engine +}; + + + +//********************************************************* +// OPL4 IMPLEMENTATION CLASSES +//********************************************************* + +// ======================> ymf278b + +class ymf278b +{ + // Using the nominal datasheet frequency of 33.868MHz, the output of the + // chip will be clock/768 = 44.1kHz. However, the FM engine is clocked + // internally at clock/(19*36), or 49.515kHz, so the FM output needs to + // be downsampled. We treat this as needing to clock the FM engine an + // extra tick every few samples. The exact ratio is 768/(19*36) or + // 768/684 = 192/171. So if we always clock the FM once, we'll have + // 192/171 - 1 = 21/171 left. Thus we count 21 for each sample and when + // it gets above 171, we tick an extra time. + static constexpr uint32_t FM_EXTRA_SAMPLE_THRESH = 171; + static constexpr uint32_t FM_EXTRA_SAMPLE_STEP = 192 - FM_EXTRA_SAMPLE_THRESH; + +public: + using fm_engine = fm_engine_base; + static constexpr uint32_t OUTPUTS = 6; + using output_data = ymfm_output; + + static constexpr uint8_t STATUS_BUSY = 0x01; + static constexpr uint8_t STATUS_LD = 0x02; + + // constructor + ymf278b(ymfm_interface &intf); + + // reset + void reset(); + + // save/restore + void save_restore(ymfm_saved_state &state); + + // pass-through helpers + uint32_t sample_rate(uint32_t input_clock) const { return input_clock / 768; } + void invalidate_caches() { m_fm.invalidate_caches(); } + + // read access + uint8_t read_status(); + uint8_t read_data_pcm(); + uint8_t read(uint32_t offset); + + // write access + void write_address(uint8_t data); + void write_data(uint8_t data); + void write_address_hi(uint8_t data); + void write_address_pcm(uint8_t data); + void write_data_pcm(uint8_t data); + void write(uint32_t offset, uint8_t data); + + // generate samples of sound + void generate(output_data *output, uint32_t numsamples = 1); + +protected: + // internal state + uint16_t m_address; // address register + uint32_t m_fm_pos; // FM resampling position + uint32_t m_load_remaining; // how many more samples until LD flag clears + bool m_next_status_id; // flag to track which status ID to return + fm_engine m_fm; // core FM engine + pcm_engine m_pcm; // core PCM engine +}; + + + +//********************************************************* +// OPLL IMPLEMENTATION CLASSES +//********************************************************* + +// ======================> opll_base + +class opll_base +{ +public: + using fm_engine = fm_engine_base; + using output_data = fm_engine::output_data; + static constexpr uint32_t OUTPUTS = fm_engine::OUTPUTS; + + // constructor + opll_base(ymfm_interface &intf, uint8_t const *data); + + // configuration + void set_instrument_data(uint8_t const *data) { m_fm.regs().set_instrument_data(data); } + + // reset + void reset(); + + // save/restore + void save_restore(ymfm_saved_state &state); + + // pass-through helpers + uint32_t sample_rate(uint32_t input_clock) const { return m_fm.sample_rate(input_clock); } + void invalidate_caches() { m_fm.invalidate_caches(); } + + // read access -- doesn't really have any, but provide these for consistency + uint8_t read_status() { return 0x00; } + uint8_t read(uint32_t offset) { return 0x00; } + + // write access + void write_address(uint8_t data); + void write_data(uint8_t data); + void write(uint32_t offset, uint8_t data); + + // generate samples of sound + void generate(output_data *output, uint32_t numsamples = 1); + +protected: + // internal state + uint8_t m_address; // address register + fm_engine m_fm; // core FM engine +}; + + +// ======================> ym2413 + +class ym2413 : public opll_base +{ +public: + // constructor + ym2413(ymfm_interface &intf, uint8_t const *instrument_data = nullptr); + +private: + // internal state + static uint8_t const s_default_instruments[]; +}; + + +// ======================> ym2413 + +class ym2423 : public opll_base +{ +public: + // constructor + ym2423(ymfm_interface &intf, uint8_t const *instrument_data = nullptr); + +private: + // internal state + static uint8_t const s_default_instruments[]; +}; + + +// ======================> ymf281 + +class ymf281 : public opll_base +{ +public: + // constructor + ymf281(ymfm_interface &intf, uint8_t const *instrument_data = nullptr); + +private: + // internal state + static uint8_t const s_default_instruments[]; +}; + + +// ======================> ds1001 + +class ds1001 : public opll_base +{ +public: + // constructor + ds1001(ymfm_interface &intf, uint8_t const *instrument_data = nullptr); + +private: + // internal state + static uint8_t const s_default_instruments[]; +}; + +} + +#endif // YMFM_OPL_H diff --git a/src/sound/ymfm/ymfm_opm.cpp b/src/sound/ymfm/ymfm_opm.cpp new file mode 100644 index 000000000..c72badb57 --- /dev/null +++ b/src/sound/ymfm/ymfm_opm.cpp @@ -0,0 +1,539 @@ +// BSD 3-Clause License +// +// Copyright (c) 2021, Aaron Giles +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// 1. Redistributions of source code must retain the above copyright notice, this +// list of conditions and the following disclaimer. +// +// 2. Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// 3. Neither the name of the copyright holder nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#include "ymfm_opm.h" +#include "ymfm_fm.ipp" + +namespace ymfm +{ + +//********************************************************* +// OPM REGISTERS +//********************************************************* + +//------------------------------------------------- +// opm_registers - constructor +//------------------------------------------------- + +opm_registers::opm_registers() : + m_lfo_counter(0), + m_noise_lfsr(1), + m_noise_counter(0), + m_noise_state(0), + m_noise_lfo(0), + m_lfo_am(0) +{ + // create the waveforms + for (uint32_t index = 0; index < WAVEFORM_LENGTH; index++) + m_waveform[0][index] = abs_sin_attenuation(index) | (bitfield(index, 9) << 15); + + // create the LFO waveforms; AM in the low 8 bits, PM in the upper 8 + // waveforms are adjusted to match the pictures in the application manual + for (uint32_t index = 0; index < LFO_WAVEFORM_LENGTH; index++) + { + // waveform 0 is a sawtooth + uint8_t am = index ^ 0xff; + int8_t pm = int8_t(index); + m_lfo_waveform[0][index] = am | (pm << 8); + + // waveform 1 is a square wave + am = bitfield(index, 7) ? 0 : 0xff; + pm = int8_t(am ^ 0x80); + m_lfo_waveform[1][index] = am | (pm << 8); + + // waveform 2 is a triangle wave + am = bitfield(index, 7) ? (index << 1) : ((index ^ 0xff) << 1); + pm = int8_t(bitfield(index, 6) ? am : ~am); + m_lfo_waveform[2][index] = am | (pm << 8); + + // waveform 3 is noise; it is filled in dynamically + m_lfo_waveform[3][index] = 0; + } +} + + +//------------------------------------------------- +// reset - reset to initial state +//------------------------------------------------- + +void opm_registers::reset() +{ + std::fill_n(&m_regdata[0], REGISTERS, 0); + + // enable output on both channels by default + m_regdata[0x20] = m_regdata[0x21] = m_regdata[0x22] = m_regdata[0x23] = 0xc0; + m_regdata[0x24] = m_regdata[0x25] = m_regdata[0x26] = m_regdata[0x27] = 0xc0; +} + + +//------------------------------------------------- +// save_restore - save or restore the data +//------------------------------------------------- + +void opm_registers::save_restore(ymfm_saved_state &state) +{ + state.save_restore(m_lfo_counter); + state.save_restore(m_lfo_am); + state.save_restore(m_noise_lfsr); + state.save_restore(m_noise_counter); + state.save_restore(m_noise_state); + state.save_restore(m_noise_lfo); + state.save_restore(m_regdata); +} + + +//------------------------------------------------- +// operator_map - return an array of operator +// indices for each channel; for OPM this is fixed +//------------------------------------------------- + +void opm_registers::operator_map(operator_mapping &dest) const +{ + // Note that the channel index order is 0,2,1,3, so we bitswap the index. + // + // This is because the order in the map is: + // carrier 1, carrier 2, modulator 1, modulator 2 + // + // But when wiring up the connections, the more natural order is: + // carrier 1, modulator 1, carrier 2, modulator 2 + static const operator_mapping s_fixed_map = + { { + operator_list( 0, 16, 8, 24 ), // Channel 0 operators + operator_list( 1, 17, 9, 25 ), // Channel 1 operators + operator_list( 2, 18, 10, 26 ), // Channel 2 operators + operator_list( 3, 19, 11, 27 ), // Channel 3 operators + operator_list( 4, 20, 12, 28 ), // Channel 4 operators + operator_list( 5, 21, 13, 29 ), // Channel 5 operators + operator_list( 6, 22, 14, 30 ), // Channel 6 operators + operator_list( 7, 23, 15, 31 ), // Channel 7 operators + } }; + dest = s_fixed_map; +} + + +//------------------------------------------------- +// write - handle writes to the register array +//------------------------------------------------- + +bool opm_registers::write(uint16_t index, uint8_t data, uint32_t &channel, uint32_t &opmask) +{ + assert(index < REGISTERS); + + // LFO AM/PM depth are written to the same register (0x19); + // redirect the PM depth to an unused neighbor (0x1a) + if (index == 0x19) + m_regdata[index + bitfield(data, 7)] = data; + else if (index != 0x1a) + m_regdata[index] = data; + + // handle writes to the key on index + if (index == 0x08) + { + channel = bitfield(data, 0, 3); + opmask = bitfield(data, 3, 4); + return true; + } + return false; +} + + +//------------------------------------------------- +// clock_noise_and_lfo - clock the noise and LFO, +// handling clock division, depth, and waveform +// computations +//------------------------------------------------- + +int32_t opm_registers::clock_noise_and_lfo() +{ + // base noise frequency is measured at 2x 1/2 FM frequency; this + // means each tick counts as two steps against the noise counter + uint32_t freq = noise_frequency(); + for (int rep = 0; rep < 2; rep++) + { + // evidence seems to suggest the LFSR is clocked continually and just + // sampled at the noise frequency for output purposes; note that the + // low 8 bits are the most recent 8 bits of history while bits 8-24 + // contain the 17 bit LFSR state + m_noise_lfsr <<= 1; + m_noise_lfsr |= bitfield(m_noise_lfsr, 17) ^ bitfield(m_noise_lfsr, 14) ^ 1; + + // compare against the frequency and latch when we exceed it + if (m_noise_counter++ >= freq) + { + m_noise_counter = 0; + m_noise_state = bitfield(m_noise_lfsr, 17); + } + } + + // treat the rate as a 4.4 floating-point step value with implied + // leading 1; this matches exactly the frequencies in the application + // manual, though it might not be implemented exactly this way on chip + uint32_t rate = lfo_rate(); + m_lfo_counter += (0x10 | bitfield(rate, 0, 4)) << bitfield(rate, 4, 4); + + // bit 1 of the test register is officially undocumented but has been + // discovered to hold the LFO in reset while active + if (lfo_reset()) + m_lfo_counter = 0; + + // now pull out the non-fractional LFO value + uint32_t lfo = bitfield(m_lfo_counter, 22, 8); + + // fill in the noise entry 1 ahead of our current position; this + // ensures the current value remains stable for a full LFO clock + // and effectively latches the running value when the LFO advances + uint32_t lfo_noise = bitfield(m_noise_lfsr, 17, 8); + m_lfo_waveform[3][(lfo + 1) & 0xff] = lfo_noise | (lfo_noise << 8); + + // fetch the AM/PM values based on the waveform; AM is unsigned and + // encoded in the low 8 bits, while PM signed and encoded in the upper + // 8 bits + int32_t ampm = m_lfo_waveform[lfo_waveform()][lfo]; + + // apply depth to the AM value and store for later + m_lfo_am = ((ampm & 0xff) * lfo_am_depth()) >> 7; + + // apply depth to the PM value and return it + return ((ampm >> 8) * int32_t(lfo_pm_depth())) >> 7; +} + + +//------------------------------------------------- +// lfo_am_offset - return the AM offset from LFO +// for the given channel +//------------------------------------------------- + +uint32_t opm_registers::lfo_am_offset(uint32_t choffs) const +{ + // OPM maps AM quite differently from OPN + + // shift value for AM sensitivity is [*, 0, 1, 2], + // mapping to values of [0, 23.9, 47.8, and 95.6dB] + uint32_t am_sensitivity = ch_lfo_am_sens(choffs); + if (am_sensitivity == 0) + return 0; + + // QUESTION: see OPN note below for the dB range mapping; it applies + // here as well + + // raw LFO AM value on OPM is 0-FF, which is already a factor of 2 + // larger than the OPN below, putting our staring point at 2x theirs; + // this works out since our minimum is 2x their maximum + return m_lfo_am << (am_sensitivity - 1); +} + + +//------------------------------------------------- +// cache_operator_data - fill the operator cache +// with prefetched data +//------------------------------------------------- + +void opm_registers::cache_operator_data(uint32_t choffs, uint32_t opoffs, opdata_cache &cache) +{ + // set up the easy stuff + cache.waveform = &m_waveform[0][0]; + + // get frequency from the channel + uint32_t block_freq = cache.block_freq = ch_block_freq(choffs); + + // compute the keycode: block_freq is: + // + // BBBCCCCFFFFFF + // ^^^^^ + // + // the 5-bit keycode is just the top 5 bits (block + top 2 bits + // of the key code) + uint32_t keycode = bitfield(block_freq, 8, 5); + + // detune adjustment + cache.detune = detune_adjustment(op_detune(opoffs), keycode); + + // multiple value, as an x.1 value (0 means 0.5) + cache.multiple = op_multiple(opoffs) * 2; + if (cache.multiple == 0) + cache.multiple = 1; + + // phase step, or PHASE_STEP_DYNAMIC if PM is active; this depends on + // block_freq, detune, and multiple, so compute it after we've done those + if (lfo_pm_depth() == 0 || ch_lfo_pm_sens(choffs) == 0) + cache.phase_step = compute_phase_step(choffs, opoffs, cache, 0); + else + cache.phase_step = opdata_cache::PHASE_STEP_DYNAMIC; + + // total level, scaled by 8 + cache.total_level = op_total_level(opoffs) << 3; + + // 4-bit sustain level, but 15 means 31 so effectively 5 bits + cache.eg_sustain = op_sustain_level(opoffs); + cache.eg_sustain |= (cache.eg_sustain + 1) & 0x10; + cache.eg_sustain <<= 5; + + // determine KSR adjustment for enevlope rates + uint32_t ksrval = keycode >> (op_ksr(opoffs) ^ 3); + cache.eg_rate[EG_ATTACK] = effective_rate(op_attack_rate(opoffs) * 2, ksrval); + cache.eg_rate[EG_DECAY] = effective_rate(op_decay_rate(opoffs) * 2, ksrval); + cache.eg_rate[EG_SUSTAIN] = effective_rate(op_sustain_rate(opoffs) * 2, ksrval); + cache.eg_rate[EG_RELEASE] = effective_rate(op_release_rate(opoffs) * 4 + 2, ksrval); +} + + +//------------------------------------------------- +// compute_phase_step - compute the phase step +//------------------------------------------------- + +uint32_t opm_registers::compute_phase_step(uint32_t choffs, uint32_t opoffs, opdata_cache const &cache, int32_t lfo_raw_pm) +{ + // OPM logic is rather unique here, due to extra detune + // and the use of key codes (not to be confused with keycode) + + // start with coarse detune delta; table uses cents value from + // manual, converted into 1/64ths + static const int16_t s_detune2_delta[4] = { 0, (600*64+50)/100, (781*64+50)/100, (950*64+50)/100 }; + int32_t delta = s_detune2_delta[op_detune2(opoffs)]; + + // add in the PM delta + uint32_t pm_sensitivity = ch_lfo_pm_sens(choffs); + if (pm_sensitivity != 0) + { + // raw PM value is -127..128 which is +/- 200 cents + // manual gives these magnitudes in cents: + // 0, +/-5, +/-10, +/-20, +/-50, +/-100, +/-400, +/-700 + // this roughly corresponds to shifting the 200-cent value: + // 0 >> 5, >> 4, >> 3, >> 2, >> 1, << 1, << 2 + if (pm_sensitivity < 6) + delta += lfo_raw_pm >> (6 - pm_sensitivity); + else + delta += lfo_raw_pm << (pm_sensitivity - 5); + } + + // apply delta and convert to a frequency number + uint32_t phase_step = opm_key_code_to_phase_step(cache.block_freq, delta); + + // apply detune based on the keycode + phase_step += cache.detune; + + // apply frequency multiplier (which is cached as an x.1 value) + return (phase_step * cache.multiple) >> 1; +} + + +//------------------------------------------------- +// log_keyon - log a key-on event +//------------------------------------------------- + +std::string opm_registers::log_keyon(uint32_t choffs, uint32_t opoffs) +{ + uint32_t chnum = choffs; + uint32_t opnum = opoffs; + + char buffer[256]; + char *end = &buffer[0]; + + end += snprintf(end, SNPRINTF_BUFFER_SIZE_CALC, "%u.%02u freq=%04X dt2=%u dt=%u fb=%u alg=%X mul=%X tl=%02X ksr=%u adsr=%02X/%02X/%02X/%X sl=%X out=%c%c", + chnum, opnum, + ch_block_freq(choffs), + op_detune2(opoffs), + op_detune(opoffs), + ch_feedback(choffs), + ch_algorithm(choffs), + op_multiple(opoffs), + op_total_level(opoffs), + op_ksr(opoffs), + op_attack_rate(opoffs), + op_decay_rate(opoffs), + op_sustain_rate(opoffs), + op_release_rate(opoffs), + op_sustain_level(opoffs), + ch_output_0(choffs) ? 'L' : '-', + ch_output_1(choffs) ? 'R' : '-'); + + bool am = (lfo_am_depth() != 0 && ch_lfo_am_sens(choffs) != 0 && op_lfo_am_enable(opoffs) != 0); + if (am) + end += snprintf(end, SNPRINTF_BUFFER_SIZE_CALC, " am=%u/%02X", ch_lfo_am_sens(choffs), lfo_am_depth()); + bool pm = (lfo_pm_depth() != 0 && ch_lfo_pm_sens(choffs) != 0); + if (pm) + end += snprintf(end, SNPRINTF_BUFFER_SIZE_CALC, " pm=%u/%02X", ch_lfo_pm_sens(choffs), lfo_pm_depth()); + if (am || pm) + end += snprintf(end, SNPRINTF_BUFFER_SIZE_CALC, " lfo=%02X/%c", lfo_rate(), "WQTN"[lfo_waveform()]); + if (noise_enable() && opoffs == 31) + end += snprintf(end, SNPRINTF_BUFFER_SIZE_CALC, " noise=1"); + + return buffer; +} + + + +//********************************************************* +// YM2151 +//********************************************************* + +//------------------------------------------------- +// ym2151 - constructor +//------------------------------------------------- + +ym2151::ym2151(ymfm_interface &intf, opm_variant variant) : + m_variant(variant), + m_address(0), + m_fm(intf) +{ +} + + +//------------------------------------------------- +// reset - reset the system +//------------------------------------------------- + +void ym2151::reset() +{ + // reset the engines + m_fm.reset(); +} + + +//------------------------------------------------- +// save_restore - save or restore the data +//------------------------------------------------- + +void ym2151::save_restore(ymfm_saved_state &state) +{ + m_fm.save_restore(state); + state.save_restore(m_address); +} + + +//------------------------------------------------- +// read_status - read the status register +//------------------------------------------------- + +uint8_t ym2151::read_status() +{ + uint8_t result = m_fm.status(); + if (m_fm.intf().ymfm_is_busy()) + result |= fm_engine::STATUS_BUSY; + return result; +} + + +//------------------------------------------------- +// read - handle a read from the device +//------------------------------------------------- + +uint8_t ym2151::read(uint32_t offset) +{ + uint8_t result = 0xff; + switch (offset & 1) + { + case 0: // data port (unused) + debug::log_unexpected_read_write("Unexpected read from YM2151 offset %d\n", offset & 3); + break; + + case 1: // status port, YM2203 compatible + result = read_status(); + break; + } + return result; +} + + +//------------------------------------------------- +// write_address - handle a write to the address +// register +//------------------------------------------------- + +void ym2151::write_address(uint8_t data) +{ + // just set the address + m_address = data; +} + + +//------------------------------------------------- +// write - handle a write to the register +// interface +//------------------------------------------------- + +void ym2151::write_data(uint8_t data) +{ + // write the FM register + m_fm.write(m_address, data); + + // special cases + if (m_address == 0x1b) + { + // writes to register 0x1B send the upper 2 bits to the output lines + m_fm.intf().ymfm_external_write(ACCESS_IO, 0, data >> 6); + } + + // mark busy for a bit + m_fm.intf().ymfm_set_busy_end(32 * m_fm.clock_prescale()); +} + + +//------------------------------------------------- +// write - handle a write to the register +// interface +//------------------------------------------------- + +void ym2151::write(uint32_t offset, uint8_t data) +{ + switch (offset & 1) + { + case 0: // address port + write_address(data); + break; + + case 1: // data port + write_data(data); + break; + } +} + + +//------------------------------------------------- +// generate - generate one sample of sound +//------------------------------------------------- + +void ym2151::generate(output_data *output, uint32_t numsamples) +{ + for (uint32_t samp = 0; samp < numsamples; samp++, output++) + { + // clock the system + m_fm.clock(fm_engine::ALL_CHANNELS); + + // update the FM content; OPM is full 14-bit with no intermediate clipping + m_fm.output(output->clear(), 0, 32767, fm_engine::ALL_CHANNELS); + + // YM2151 uses an external DAC (YM3012) with mantissa/exponent format + // convert to 10.3 floating point value and back to simulate truncation + output->roundtrip_fp(); + } +} + +} diff --git a/src/sound/ymfm/ymfm_opm.h b/src/sound/ymfm/ymfm_opm.h new file mode 100644 index 000000000..b126135d4 --- /dev/null +++ b/src/sound/ymfm/ymfm_opm.h @@ -0,0 +1,322 @@ +// BSD 3-Clause License +// +// Copyright (c) 2021, Aaron Giles +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// 1. Redistributions of source code must retain the above copyright notice, this +// list of conditions and the following disclaimer. +// +// 2. Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// 3. Neither the name of the copyright holder nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#ifndef YMFM_OPM_H +#define YMFM_OPM_H + +#pragma once + +#include "ymfm.h" +#include "ymfm_fm.h" + +namespace ymfm +{ + +//********************************************************* +// REGISTER CLASSES +//********************************************************* + +// ======================> opm_registers + +// +// OPM register map: +// +// System-wide registers: +// 01 xxxxxx-x Test register +// ------x- LFO reset +// 08 -x------ Key on/off operator 4 +// --x----- Key on/off operator 3 +// ---x---- Key on/off operator 2 +// ----x--- Key on/off operator 1 +// -----xxx Channel select +// 0F x------- Noise enable +// ---xxxxx Noise frequency +// 10 xxxxxxxx Timer A value (upper 8 bits) +// 11 ------xx Timer A value (lower 2 bits) +// 12 xxxxxxxx Timer B value +// 14 x------- CSM mode +// --x----- Reset timer B +// ---x---- Reset timer A +// ----x--- Enable timer B +// -----x-- Enable timer A +// ------x- Load timer B +// -------x Load timer A +// 18 xxxxxxxx LFO frequency +// 19 0xxxxxxx AM LFO depth +// 1xxxxxxx PM LFO depth +// 1B xx------ CT (2 output data lines) +// ------xx LFO waveform +// +// Per-channel registers (channel in address bits 0-2) +// 20-27 x------- Pan right +// -x------ Pan left +// --xxx--- Feedback level for operator 1 (0-7) +// -----xxx Operator connection algorithm (0-7) +// 28-2F -xxxxxxx Key code +// 30-37 xxxxxx-- Key fraction +// 38-3F -xxx---- LFO PM sensitivity +// ------xx LFO AM shift +// +// Per-operator registers (channel in address bits 0-2, operator in bits 3-4) +// 40-5F -xxx---- Detune value (0-7) +// ----xxxx Multiple value (0-15) +// 60-7F -xxxxxxx Total level (0-127) +// 80-9F xx------ Key scale rate (0-3) +// ---xxxxx Attack rate (0-31) +// A0-BF x------- LFO AM enable +// ---xxxxx Decay rate (0-31) +// C0-DF xx------ Detune 2 value (0-3) +// ---xxxxx Sustain rate (0-31) +// E0-FF xxxx---- Sustain level (0-15) +// ----xxxx Release rate (0-15) +// +// Internal (fake) registers: +// 1A -xxxxxxx PM depth +// + +class opm_registers : public fm_registers_base +{ + // LFO waveforms are 256 entries long + static constexpr uint32_t LFO_WAVEFORM_LENGTH = 256; + +public: + // constants + static constexpr uint32_t OUTPUTS = 2; + static constexpr uint32_t CHANNELS = 8; + static constexpr uint32_t ALL_CHANNELS = (1 << CHANNELS) - 1; + static constexpr uint32_t OPERATORS = CHANNELS * 4; + static constexpr uint32_t WAVEFORMS = 1; + static constexpr uint32_t REGISTERS = 0x100; + static constexpr uint32_t DEFAULT_PRESCALE = 2; + static constexpr uint32_t EG_CLOCK_DIVIDER = 3; + static constexpr uint32_t CSM_TRIGGER_MASK = ALL_CHANNELS; + static constexpr uint32_t REG_MODE = 0x14; + static constexpr uint8_t STATUS_TIMERA = 0x01; + static constexpr uint8_t STATUS_TIMERB = 0x02; + static constexpr uint8_t STATUS_BUSY = 0x80; + static constexpr uint8_t STATUS_IRQ = 0; + + // constructor + opm_registers(); + + // reset to initial state + void reset(); + + // save/restore + void save_restore(ymfm_saved_state &state); + + // map channel number to register offset + static constexpr uint32_t channel_offset(uint32_t chnum) + { + assert(chnum < CHANNELS); + return chnum; + } + + // map operator number to register offset + static constexpr uint32_t operator_offset(uint32_t opnum) + { + assert(opnum < OPERATORS); + return opnum; + } + + // return an array of operator indices for each channel + struct operator_mapping { uint32_t chan[CHANNELS]; }; + void operator_map(operator_mapping &dest) const; + + // handle writes to the register array + bool write(uint16_t index, uint8_t data, uint32_t &chan, uint32_t &opmask); + + // clock the noise and LFO, if present, returning LFO PM value + int32_t clock_noise_and_lfo(); + + // return the AM offset from LFO for the given channel + uint32_t lfo_am_offset(uint32_t choffs) const; + + // return the current noise state, gated by the noise clock + uint32_t noise_state() const { return m_noise_state; } + + // caching helpers + void cache_operator_data(uint32_t choffs, uint32_t opoffs, opdata_cache &cache); + + // compute the phase step, given a PM value + uint32_t compute_phase_step(uint32_t choffs, uint32_t opoffs, opdata_cache const &cache, int32_t lfo_raw_pm); + + // log a key-on event + std::string log_keyon(uint32_t choffs, uint32_t opoffs); + + // system-wide registers + uint32_t test() const { return byte(0x01, 0, 8); } + uint32_t lfo_reset() const { return byte(0x01, 1, 1); } + uint32_t noise_frequency() const { return byte(0x0f, 0, 5) ^ 0x1f; } + uint32_t noise_enable() const { return byte(0x0f, 7, 1); } + uint32_t timer_a_value() const { return word(0x10, 0, 8, 0x11, 0, 2); } + uint32_t timer_b_value() const { return byte(0x12, 0, 8); } + uint32_t csm() const { return byte(0x14, 7, 1); } + uint32_t reset_timer_b() const { return byte(0x14, 5, 1); } + uint32_t reset_timer_a() const { return byte(0x14, 4, 1); } + uint32_t enable_timer_b() const { return byte(0x14, 3, 1); } + uint32_t enable_timer_a() const { return byte(0x14, 2, 1); } + uint32_t load_timer_b() const { return byte(0x14, 1, 1); } + uint32_t load_timer_a() const { return byte(0x14, 0, 1); } + uint32_t lfo_rate() const { return byte(0x18, 0, 8); } + uint32_t lfo_am_depth() const { return byte(0x19, 0, 7); } + uint32_t lfo_pm_depth() const { return byte(0x1a, 0, 7); } + uint32_t output_bits() const { return byte(0x1b, 6, 2); } + uint32_t lfo_waveform() const { return byte(0x1b, 0, 2); } + + // per-channel registers + uint32_t ch_output_any(uint32_t choffs) const { return byte(0x20, 6, 2, choffs); } + uint32_t ch_output_0(uint32_t choffs) const { return byte(0x20, 6, 1, choffs); } + uint32_t ch_output_1(uint32_t choffs) const { return byte(0x20, 7, 1, choffs); } + uint32_t ch_output_2(uint32_t choffs) const { return 0; } + uint32_t ch_output_3(uint32_t choffs) const { return 0; } + uint32_t ch_feedback(uint32_t choffs) const { return byte(0x20, 3, 3, choffs); } + uint32_t ch_algorithm(uint32_t choffs) const { return byte(0x20, 0, 3, choffs); } + uint32_t ch_block_freq(uint32_t choffs) const { return word(0x28, 0, 7, 0x30, 2, 6, choffs); } + uint32_t ch_lfo_pm_sens(uint32_t choffs) const { return byte(0x38, 4, 3, choffs); } + uint32_t ch_lfo_am_sens(uint32_t choffs) const { return byte(0x38, 0, 2, choffs); } + + // per-operator registers + uint32_t op_detune(uint32_t opoffs) const { return byte(0x40, 4, 3, opoffs); } + uint32_t op_multiple(uint32_t opoffs) const { return byte(0x40, 0, 4, opoffs); } + uint32_t op_total_level(uint32_t opoffs) const { return byte(0x60, 0, 7, opoffs); } + uint32_t op_ksr(uint32_t opoffs) const { return byte(0x80, 6, 2, opoffs); } + uint32_t op_attack_rate(uint32_t opoffs) const { return byte(0x80, 0, 5, opoffs); } + uint32_t op_lfo_am_enable(uint32_t opoffs) const { return byte(0xa0, 7, 1, opoffs); } + uint32_t op_decay_rate(uint32_t opoffs) const { return byte(0xa0, 0, 5, opoffs); } + uint32_t op_detune2(uint32_t opoffs) const { return byte(0xc0, 6, 2, opoffs); } + uint32_t op_sustain_rate(uint32_t opoffs) const { return byte(0xc0, 0, 5, opoffs); } + uint32_t op_sustain_level(uint32_t opoffs) const { return byte(0xe0, 4, 4, opoffs); } + uint32_t op_release_rate(uint32_t opoffs) const { return byte(0xe0, 0, 4, opoffs); } + +protected: + // return a bitfield extracted from a byte + uint32_t byte(uint32_t offset, uint32_t start, uint32_t count, uint32_t extra_offset = 0) const + { + return bitfield(m_regdata[offset + extra_offset], start, count); + } + + // return a bitfield extracted from a pair of bytes, MSBs listed first + uint32_t word(uint32_t offset1, uint32_t start1, uint32_t count1, uint32_t offset2, uint32_t start2, uint32_t count2, uint32_t extra_offset = 0) const + { + return (byte(offset1, start1, count1, extra_offset) << count2) | byte(offset2, start2, count2, extra_offset); + } + + // internal state + uint32_t m_lfo_counter; // LFO counter + uint32_t m_noise_lfsr; // noise LFSR state + uint8_t m_noise_counter; // noise counter + uint8_t m_noise_state; // latched noise state + uint8_t m_noise_lfo; // latched LFO noise value + uint8_t m_lfo_am; // current LFO AM value + uint8_t m_regdata[REGISTERS]; // register data + int16_t m_lfo_waveform[4][LFO_WAVEFORM_LENGTH]; // LFO waveforms; AM in low 8, PM in upper 8 + uint16_t m_waveform[WAVEFORMS][WAVEFORM_LENGTH]; // waveforms +}; + + + +//********************************************************* +// OPM IMPLEMENTATION CLASSES +//********************************************************* + +// ======================> ym2151 + +class ym2151 +{ +public: + using fm_engine = fm_engine_base; + using output_data = fm_engine::output_data; + static constexpr uint32_t OUTPUTS = fm_engine::OUTPUTS; + + // constructor + ym2151(ymfm_interface &intf) : ym2151(intf, VARIANT_YM2151) { } + + // reset + void reset(); + + // save/restore + void save_restore(ymfm_saved_state &state); + + // pass-through helpers + uint32_t sample_rate(uint32_t input_clock) const { return m_fm.sample_rate(input_clock); } + void invalidate_caches() { m_fm.invalidate_caches(); } + + // read access + uint8_t read_status(); + uint8_t read(uint32_t offset); + + // write access + void write_address(uint8_t data); + void write_data(uint8_t data); + void write(uint32_t offset, uint8_t data); + + // generate one sample of sound + void generate(output_data *output, uint32_t numsamples = 1); + +protected: + // variants + enum opm_variant + { + VARIANT_YM2151, + VARIANT_YM2164 + }; + + // internal constructor + ym2151(ymfm_interface &intf, opm_variant variant); + + // internal state + opm_variant m_variant; // chip variant + uint8_t m_address; // address register + fm_engine m_fm; // core FM engine +}; + + + +//********************************************************* +// OPP IMPLEMENTATION CLASSES +//********************************************************* + +// ======================> ym2164 + +// the YM2164 is almost 100% functionally identical to the YM2151, except +// it apparently has some mystery registers in the 00-07 range, and timer +// B's frequency is half that of the 2151 +class ym2164 : public ym2151 +{ +public: + // constructor + ym2164(ymfm_interface &intf) : ym2151(intf, VARIANT_YM2164) { } +}; + +} + + +#endif // YMFM_OPM_H diff --git a/src/sound/ymfm/ymfm_opn.cpp b/src/sound/ymfm/ymfm_opn.cpp new file mode 100644 index 000000000..388162dfe --- /dev/null +++ b/src/sound/ymfm/ymfm_opn.cpp @@ -0,0 +1,2488 @@ +// BSD 3-Clause License +// +// Copyright (c) 2021, Aaron Giles +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// 1. Redistributions of source code must retain the above copyright notice, this +// list of conditions and the following disclaimer. +// +// 2. Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// 3. Neither the name of the copyright holder nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#include "ymfm_opn.h" +#include "ymfm_fm.ipp" + +namespace ymfm +{ + +//********************************************************* +// OPN/OPNA REGISTERS +//********************************************************* + +//------------------------------------------------- +// opn_registers_base - constructor +//------------------------------------------------- + +template +opn_registers_base::opn_registers_base() : + m_lfo_counter(0), + m_lfo_am(0) +{ + // create the waveforms + for (uint32_t index = 0; index < WAVEFORM_LENGTH; index++) + m_waveform[0][index] = abs_sin_attenuation(index) | (bitfield(index, 9) << 15); +} + + +//------------------------------------------------- +// reset - reset to initial state +//------------------------------------------------- + +template +void opn_registers_base::reset() +{ + std::fill_n(&m_regdata[0], REGISTERS, 0); + if (IsOpnA) + { + // enable output on both channels by default + m_regdata[0xb4] = m_regdata[0xb5] = m_regdata[0xb6] = 0xc0; + m_regdata[0x1b4] = m_regdata[0x1b5] = m_regdata[0x1b6] = 0xc0; + } +} + + +//------------------------------------------------- +// save_restore - save or restore the data +//------------------------------------------------- + +template +void opn_registers_base::save_restore(ymfm_saved_state &state) +{ + if (IsOpnA) + { + state.save_restore(m_lfo_counter); + state.save_restore(m_lfo_am); + } + state.save_restore(m_regdata); +} + + +//------------------------------------------------- +// operator_map - return an array of operator +// indices for each channel; for OPN this is fixed +//------------------------------------------------- + +template<> +void opn_registers_base::operator_map(operator_mapping &dest) const +{ + // Note that the channel index order is 0,2,1,3, so we bitswap the index. + // + // This is because the order in the map is: + // carrier 1, carrier 2, modulator 1, modulator 2 + // + // But when wiring up the connections, the more natural order is: + // carrier 1, modulator 1, carrier 2, modulator 2 + static const operator_mapping s_fixed_map = + { { + operator_list( 0, 6, 3, 9 ), // Channel 0 operators + operator_list( 1, 7, 4, 10 ), // Channel 1 operators + operator_list( 2, 8, 5, 11 ), // Channel 2 operators + } }; + dest = s_fixed_map; +} + +template<> +void opn_registers_base::operator_map(operator_mapping &dest) const +{ + // Note that the channel index order is 0,2,1,3, so we bitswap the index. + // + // This is because the order in the map is: + // carrier 1, carrier 2, modulator 1, modulator 2 + // + // But when wiring up the connections, the more natural order is: + // carrier 1, modulator 1, carrier 2, modulator 2 + static const operator_mapping s_fixed_map = + { { + operator_list( 0, 6, 3, 9 ), // Channel 0 operators + operator_list( 1, 7, 4, 10 ), // Channel 1 operators + operator_list( 2, 8, 5, 11 ), // Channel 2 operators + operator_list( 12, 18, 15, 21 ), // Channel 3 operators + operator_list( 13, 19, 16, 22 ), // Channel 4 operators + operator_list( 14, 20, 17, 23 ), // Channel 5 operators + } }; + dest = s_fixed_map; +} + + +//------------------------------------------------- +// write - handle writes to the register array +//------------------------------------------------- + +template +bool opn_registers_base::write(uint16_t index, uint8_t data, uint32_t &channel, uint32_t &opmask) +{ + assert(index < REGISTERS); + + // writes in the 0xa0-af/0x1a0-af region are handled as latched pairs + // borrow unused registers 0xb8-bf/0x1b8-bf as temporary holding locations + if ((index & 0xf0) == 0xa0) + { + if (bitfield(index, 0, 2) == 3) + return false; + + uint32_t latchindex = 0xb8 | bitfield(index, 3); + if (IsOpnA) + latchindex |= index & 0x100; + + // writes to the upper half just latch (only low 6 bits matter) + if (bitfield(index, 2)) + m_regdata[latchindex] = data | 0x80; + + // writes to the lower half only commit if the latch is there + else if (bitfield(m_regdata[latchindex], 7)) + { + m_regdata[index] = data; + m_regdata[index | 4] = m_regdata[latchindex] & 0x3f; + m_regdata[latchindex] = 0; + } + return false; + } + else if ((index & 0xf8) == 0xb8) + { + // registers 0xb8-0xbf are used internally + return false; + } + + // everything else is normal + m_regdata[index] = data; + + // handle writes to the key on index + if (index == 0x28) + { + channel = bitfield(data, 0, 2); + if (channel == 3) + return false; + if (IsOpnA) + channel += bitfield(data, 2, 1) * 3; + opmask = bitfield(data, 4, 4); + return true; + } + return false; +} + + +//------------------------------------------------- +// clock_noise_and_lfo - clock the noise and LFO, +// handling clock division, depth, and waveform +// computations +//------------------------------------------------- + +template +int32_t opn_registers_base::clock_noise_and_lfo() +{ + // OPN has no noise generation + + // if LFO not enabled (not present on OPN), quick exit with 0s + if (!IsOpnA || !lfo_enable()) + { + m_lfo_counter = 0; + + // special case: if LFO is disabled on OPNA, it basically just keeps the counter + // at 0; since position 0 gives an AM value of 0x3f, it is important to reflect + // that here; for example, MegaDrive Venom plays some notes with LFO globally + // disabled but enabling LFO on the operators, and it expects this added attenutation + m_lfo_am = IsOpnA ? 0x3f : 0x00; + return 0; + } + + // this table is based on converting the frequencies in the applications + // manual to clock dividers, based on the assumption of a 7-bit LFO value + static uint8_t const lfo_max_count[8] = { 109, 78, 72, 68, 63, 45, 9, 6 }; + uint32_t subcount = uint8_t(m_lfo_counter++); + + // when we cross the divider count, add enough to zero it and cause an + // increment at bit 8; the 7-bit value lives from bits 8-14 + if (subcount >= lfo_max_count[lfo_rate()]) + { + // note: to match the published values this should be 0x100 - subcount; + // however, tests on the hardware and nuked bear out an off-by-one + // error exists that causes the max LFO rate to be faster than published + m_lfo_counter += 0x101 - subcount; + } + + // AM value is 7 bits, staring at bit 8; grab the low 6 directly + m_lfo_am = bitfield(m_lfo_counter, 8, 6); + + // first half of the AM period (bit 6 == 0) is inverted + if (bitfield(m_lfo_counter, 8+6) == 0) + m_lfo_am ^= 0x3f; + + // PM value is 5 bits, starting at bit 10; grab the low 3 directly + int32_t pm = bitfield(m_lfo_counter, 10, 3); + + // PM is reflected based on bit 3 + if (bitfield(m_lfo_counter, 10+3)) + pm ^= 7; + + // PM is negated based on bit 4 + return bitfield(m_lfo_counter, 10+4) ? -pm : pm; +} + + +//------------------------------------------------- +// lfo_am_offset - return the AM offset from LFO +// for the given channel +//------------------------------------------------- + +template +uint32_t opn_registers_base::lfo_am_offset(uint32_t choffs) const +{ + // shift value for AM sensitivity is [7, 3, 1, 0], + // mapping to values of [0, 1.4, 5.9, and 11.8dB] + uint32_t am_shift = (1 << (ch_lfo_am_sens(choffs) ^ 3)) - 1; + + // QUESTION: max sensitivity should give 11.8dB range, but this value + // is directly added to an x.8 attenuation value, which will only give + // 126/256 or ~4.9dB range -- what am I missing? The calculation below + // matches several other emulators, including the Nuked implemenation. + + // raw LFO AM value on OPN is 0-3F, scale that up by a factor of 2 + // (giving 7 bits) before applying the final shift + return (m_lfo_am << 1) >> am_shift; +} + + +//------------------------------------------------- +// cache_operator_data - fill the operator cache +// with prefetched data +//------------------------------------------------- + +template +void opn_registers_base::cache_operator_data(uint32_t choffs, uint32_t opoffs, opdata_cache &cache) +{ + // set up the easy stuff + cache.waveform = &m_waveform[0][0]; + + // get frequency from the channel + uint32_t block_freq = cache.block_freq = ch_block_freq(choffs); + + // if multi-frequency mode is enabled and this is channel 2, + // fetch one of the special frequencies + if (multi_freq() && choffs == 2) + { + if (opoffs == 2) + block_freq = cache.block_freq = multi_block_freq(1); + else if (opoffs == 10) + block_freq = cache.block_freq = multi_block_freq(2); + else if (opoffs == 6) + block_freq = cache.block_freq = multi_block_freq(0); + } + + // compute the keycode: block_freq is: + // + // BBBFFFFFFFFFFF + // ^^^^??? + // + // the 5-bit keycode uses the top 4 bits plus a magic formula + // for the final bit + uint32_t keycode = bitfield(block_freq, 10, 4) << 1; + + // lowest bit is determined by a mix of next lower FNUM bits + // according to this equation from the YM2608 manual: + // + // (F11 & (F10 | F9 | F8)) | (!F11 & F10 & F9 & F8) + // + // for speed, we just look it up in a 16-bit constant + keycode |= bitfield(0xfe80, bitfield(block_freq, 7, 4)); + + // detune adjustment + cache.detune = detune_adjustment(op_detune(opoffs), keycode); + + // multiple value, as an x.1 value (0 means 0.5) + cache.multiple = op_multiple(opoffs) * 2; + if (cache.multiple == 0) + cache.multiple = 1; + + // phase step, or PHASE_STEP_DYNAMIC if PM is active; this depends on + // block_freq, detune, and multiple, so compute it after we've done those + if (!IsOpnA || lfo_enable() == 0 || ch_lfo_pm_sens(choffs) == 0) + cache.phase_step = compute_phase_step(choffs, opoffs, cache, 0); + else + cache.phase_step = opdata_cache::PHASE_STEP_DYNAMIC; + + // total level, scaled by 8 + cache.total_level = op_total_level(opoffs) << 3; + + // 4-bit sustain level, but 15 means 31 so effectively 5 bits + cache.eg_sustain = op_sustain_level(opoffs); + cache.eg_sustain |= (cache.eg_sustain + 1) & 0x10; + cache.eg_sustain <<= 5; + + // determine KSR adjustment for enevlope rates + uint32_t ksrval = keycode >> (op_ksr(opoffs) ^ 3); + cache.eg_rate[EG_ATTACK] = effective_rate(op_attack_rate(opoffs) * 2, ksrval); + cache.eg_rate[EG_DECAY] = effective_rate(op_decay_rate(opoffs) * 2, ksrval); + cache.eg_rate[EG_SUSTAIN] = effective_rate(op_sustain_rate(opoffs) * 2, ksrval); + cache.eg_rate[EG_RELEASE] = effective_rate(op_release_rate(opoffs) * 4 + 2, ksrval); +} + + +//------------------------------------------------- +// compute_phase_step - compute the phase step +//------------------------------------------------- + +template +uint32_t opn_registers_base::compute_phase_step(uint32_t choffs, uint32_t opoffs, opdata_cache const &cache, int32_t lfo_raw_pm) +{ + // OPN phase calculation has only a single detune parameter + // and uses FNUMs instead of keycodes + + // extract frequency number (low 11 bits of block_freq) + uint32_t fnum = bitfield(cache.block_freq, 0, 11) << 1; + + // if there's a non-zero PM sensitivity, compute the adjustment + uint32_t pm_sensitivity = ch_lfo_pm_sens(choffs); + if (pm_sensitivity != 0) + { + // apply the phase adjustment based on the upper 7 bits + // of FNUM and the PM depth parameters + fnum += opn_lfo_pm_phase_adjustment(bitfield(cache.block_freq, 4, 7), pm_sensitivity, lfo_raw_pm); + + // keep fnum to 12 bits + fnum &= 0xfff; + } + + // apply block shift to compute phase step + uint32_t block = bitfield(cache.block_freq, 11, 3); + uint32_t phase_step = (fnum << block) >> 2; + + // apply detune based on the keycode + phase_step += cache.detune; + + // clamp to 17 bits in case detune overflows + // QUESTION: is this specific to the YM2612/3438? + phase_step &= 0x1ffff; + + // apply frequency multiplier (which is cached as an x.1 value) + return (phase_step * cache.multiple) >> 1; +} + + +//------------------------------------------------- +// log_keyon - log a key-on event +//------------------------------------------------- + +template +std::string opn_registers_base::log_keyon(uint32_t choffs, uint32_t opoffs) +{ + uint32_t chnum = (choffs & 3) + 3 * bitfield(choffs, 8); + uint32_t opnum = (opoffs & 15) - ((opoffs & 15) / 4) + 12 * bitfield(opoffs, 8); + + uint32_t block_freq = ch_block_freq(choffs); + if (multi_freq() && choffs == 2) + { + if (opoffs == 2) + block_freq = multi_block_freq(1); + else if (opoffs == 10) + block_freq = multi_block_freq(2); + else if (opoffs == 6) + block_freq = multi_block_freq(0); + } + + char buffer[256]; + char *end = &buffer[0]; + + end += snprintf(end, SNPRINTF_BUFFER_SIZE_CALC, "%u.%02u freq=%04X dt=%u fb=%u alg=%X mul=%X tl=%02X ksr=%u adsr=%02X/%02X/%02X/%X sl=%X", + chnum, opnum, + block_freq, + op_detune(opoffs), + ch_feedback(choffs), + ch_algorithm(choffs), + op_multiple(opoffs), + op_total_level(opoffs), + op_ksr(opoffs), + op_attack_rate(opoffs), + op_decay_rate(opoffs), + op_sustain_rate(opoffs), + op_release_rate(opoffs), + op_sustain_level(opoffs)); + + if (OUTPUTS > 1) + end += snprintf(end, SNPRINTF_BUFFER_SIZE_CALC, " out=%c%c", + ch_output_0(choffs) ? 'L' : '-', + ch_output_1(choffs) ? 'R' : '-'); + if (op_ssg_eg_enable(opoffs)) + end += snprintf(end, SNPRINTF_BUFFER_SIZE_CALC, " ssg=%X", op_ssg_eg_mode(opoffs)); + bool am = (op_lfo_am_enable(opoffs) && ch_lfo_am_sens(choffs) != 0); + if (am) + end += snprintf(end, SNPRINTF_BUFFER_SIZE_CALC, " am=%u", ch_lfo_am_sens(choffs)); + bool pm = (ch_lfo_pm_sens(choffs) != 0); + if (pm) + end += snprintf(end, SNPRINTF_BUFFER_SIZE_CALC, " pm=%u", ch_lfo_pm_sens(choffs)); + if (am || pm) + end += snprintf(end, SNPRINTF_BUFFER_SIZE_CALC, " lfo=%02X", lfo_rate()); + if (multi_freq() && choffs == 2) + end += snprintf(end, SNPRINTF_BUFFER_SIZE_CALC, " multi=1"); + + return buffer; +} + + + +//********************************************************* +// SSG RESAMPLER +//********************************************************* + +//------------------------------------------------- +// add_last - helper to add the last computed +// value to the sums, applying the given scale +//------------------------------------------------- + +template +void ssg_resampler::add_last(int32_t &sum0, int32_t &sum1, int32_t &sum2, int32_t scale) +{ + sum0 += m_last.data[0] * scale; + sum1 += m_last.data[1] * scale; + sum2 += m_last.data[2] * scale; +} + + +//------------------------------------------------- +// clock_and_add - helper to clock a new value +// and then add it to the sums, applying the +// given scale +//------------------------------------------------- + +template +void ssg_resampler::clock_and_add(int32_t &sum0, int32_t &sum1, int32_t &sum2, int32_t scale) +{ + m_ssg.clock(); + m_ssg.output(m_last); + add_last(sum0, sum1, sum2, scale); +} + + +//------------------------------------------------- +// write_to_output - helper to write the sums to +// the appropriate outputs, applying the given +// divisor to the final result +//------------------------------------------------- + +template +void ssg_resampler::write_to_output(OutputType *output, int32_t sum0, int32_t sum1, int32_t sum2, int32_t divisor) +{ + if (MixTo1) + { + // mixing to one, apply a 2/3 factor to prevent overflow + output->data[FirstOutput] = (sum0 + sum1 + sum2) * 2 / (3 * divisor); + } + else + { + // write three outputs in a row + output->data[FirstOutput + 0] = sum0 / divisor; + output->data[FirstOutput + 1] = sum1 / divisor; + output->data[FirstOutput + 2] = sum2 / divisor; + } + + // track the sample index here + m_sampindex++; +} + + +//------------------------------------------------- +// ssg_resampler - constructor +//------------------------------------------------- + +template +ssg_resampler::ssg_resampler(ssg_engine &ssg) : + m_ssg(ssg), + m_sampindex(0), + m_resampler(&ssg_resampler::resample_nop) +{ + m_last.clear(); +} + + +//------------------------------------------------- +// save_restore - save or restore the data +//------------------------------------------------- + +template +void ssg_resampler::save_restore(ymfm_saved_state &state) +{ + state.save_restore(m_sampindex); + state.save_restore(m_last.data); +} + + +//------------------------------------------------- +// configure - configure a new ratio +//------------------------------------------------- + +template +void ssg_resampler::configure(uint8_t outsamples, uint8_t srcsamples) +{ + switch (outsamples * 10 + srcsamples) + { + case 4*10 + 1: /* 4:1 */ m_resampler = &ssg_resampler::resample_n_1<4>; break; + case 2*10 + 1: /* 2:1 */ m_resampler = &ssg_resampler::resample_n_1<2>; break; + case 4*10 + 3: /* 4:3 */ m_resampler = &ssg_resampler::resample_4_3; break; + case 1*10 + 1: /* 1:1 */ m_resampler = &ssg_resampler::resample_n_1<1>; break; + case 2*10 + 3: /* 2:3 */ m_resampler = &ssg_resampler::resample_2_3; break; + case 1*10 + 3: /* 1:3 */ m_resampler = &ssg_resampler::resample_1_n<3>; break; + case 2*10 + 9: /* 2:9 */ m_resampler = &ssg_resampler::resample_2_9; break; + case 1*10 + 6: /* 1:6 */ m_resampler = &ssg_resampler::resample_1_n<6>; break; + case 0*10 + 0: /* 0:0 */ m_resampler = &ssg_resampler::resample_nop; break; + default: assert(false); break; + } +} + + +//------------------------------------------------- +// resample_n_1 - resample SSG output to the +// target at a rate of 1 SSG sample to every +// n output sample +//------------------------------------------------- + +template +template +void ssg_resampler::resample_n_1(OutputType *output, uint32_t numsamples) +{ + for (uint32_t samp = 0; samp < numsamples; samp++, output++) + { + if (m_sampindex % Multiplier == 0) + { + m_ssg.clock(); + m_ssg.output(m_last); + } + write_to_output(output, m_last.data[0], m_last.data[1], m_last.data[2]); + } +} + + +//------------------------------------------------- +// resample_1_n - resample SSG output to the +// target at a rate of n SSG samples to every +// 1 output sample +//------------------------------------------------- + +template +template +void ssg_resampler::resample_1_n(OutputType *output, uint32_t numsamples) +{ + for (uint32_t samp = 0; samp < numsamples; samp++, output++) + { + int32_t sum0 = 0, sum1 = 0, sum2 = 0; + for (int rep = 0; rep < Divisor; rep++) + clock_and_add(sum0, sum1, sum2); + write_to_output(output, sum0, sum1, sum2, Divisor); + } +} + + +//------------------------------------------------- +// resample_2_9 - resample SSG output to the +// target at a rate of 9 SSG samples to every +// 2 output samples +//------------------------------------------------- + +template +void ssg_resampler::resample_2_9(OutputType *output, uint32_t numsamples) +{ + for (uint32_t samp = 0; samp < numsamples; samp++, output++) + { + int32_t sum0 = 0, sum1 = 0, sum2 = 0; + if (bitfield(m_sampindex, 0) != 0) + add_last(sum0, sum1, sum2, 1); + clock_and_add(sum0, sum1, sum2, 2); + clock_and_add(sum0, sum1, sum2, 2); + clock_and_add(sum0, sum1, sum2, 2); + clock_and_add(sum0, sum1, sum2, 2); + if (bitfield(m_sampindex, 0) == 0) + clock_and_add(sum0, sum1, sum2, 1); + write_to_output(output, sum0, sum1, sum2, 9); + } +} + + +//------------------------------------------------- +// resample_2_3 - resample SSG output to the +// target at a rate of 3 SSG samples to every +// 2 output samples +//------------------------------------------------- + +template +void ssg_resampler::resample_2_3(OutputType *output, uint32_t numsamples) +{ + for (uint32_t samp = 0; samp < numsamples; samp++, output++) + { + int32_t sum0 = 0, sum1 = 0, sum2 = 0; + if (bitfield(m_sampindex, 0) == 0) + { + clock_and_add(sum0, sum1, sum2, 2); + clock_and_add(sum0, sum1, sum2, 1); + } + else + { + add_last(sum0, sum1, sum2, 1); + clock_and_add(sum0, sum1, sum2, 2); + } + write_to_output(output, sum0, sum1, sum2, 3); + } +} + + +//------------------------------------------------- +// resample_4_3 - resample SSG output to the +// target at a rate of 3 SSG samples to every +// 4 output samples +//------------------------------------------------- + +template +void ssg_resampler::resample_4_3(OutputType *output, uint32_t numsamples) +{ + for (uint32_t samp = 0; samp < numsamples; samp++, output++) + { + int32_t sum0 = 0, sum1 = 0, sum2 = 0; + int32_t step = bitfield(m_sampindex, 0, 2); + add_last(sum0, sum1, sum2, step); + if (step != 3) + clock_and_add(sum0, sum1, sum2, 3 - step); + write_to_output(output, sum0, sum1, sum2, 3); + } +} + + +//------------------------------------------------- +// resample_nop - no-op resampler +//------------------------------------------------- + +template +void ssg_resampler::resample_nop(OutputType *output, uint32_t numsamples) +{ + // nothing to do except increment the sample index + m_sampindex += numsamples; +} + + + +//********************************************************* +// YM2203 +//********************************************************* + +//------------------------------------------------- +// ym2203 - constructor +//------------------------------------------------- + +ym2203::ym2203(ymfm_interface &intf) : + m_fidelity(OPN_FIDELITY_MAX), + m_address(0), + m_fm(intf), + m_ssg(intf), + m_ssg_resampler(m_ssg) +{ + m_last_fm.clear(); + update_prescale(m_fm.clock_prescale()); +} + + +//------------------------------------------------- +// reset - reset the system +//------------------------------------------------- + +void ym2203::reset() +{ + // reset the engines + m_fm.reset(); + m_ssg.reset(); +} + + +//------------------------------------------------- +// save_restore - save or restore the data +//------------------------------------------------- + +void ym2203::save_restore(ymfm_saved_state &state) +{ + state.save_restore(m_address); + state.save_restore(m_last_fm.data); + + m_fm.save_restore(state); + m_ssg.save_restore(state); + m_ssg_resampler.save_restore(state); + + update_prescale(m_fm.clock_prescale()); +} + + +//------------------------------------------------- +// read_status - read the status register +//------------------------------------------------- + +uint8_t ym2203::read_status() +{ + uint8_t result = m_fm.status(); + if (m_fm.intf().ymfm_is_busy()) + result |= fm_engine::STATUS_BUSY; + return result; +} + + +//------------------------------------------------- +// read_data - read the data register +//------------------------------------------------- + +uint8_t ym2203::read_data() +{ + uint8_t result = 0; + if (m_address < 0x10) + { + // 00-0F: Read from SSG + result = m_ssg.read(m_address & 0x0f); + } + return result; +} + + +//------------------------------------------------- +// read - handle a read from the device +//------------------------------------------------- + +uint8_t ym2203::read(uint32_t offset) +{ + uint8_t result = 0xff; + switch (offset & 1) + { + case 0: // status port + result = read_status(); + break; + + case 1: // data port (only SSG) + result = read_data(); + break; + } + return result; +} + + +//------------------------------------------------- +// write_address - handle a write to the address +// register +//------------------------------------------------- + +void ym2203::write_address(uint8_t data) +{ + // just set the address + m_address = data; + + // special case: update the prescale + if (m_address >= 0x2d && m_address <= 0x2f) + { + // 2D-2F: prescaler select + if (m_address == 0x2d) + update_prescale(6); + else if (m_address == 0x2e && m_fm.clock_prescale() == 6) + update_prescale(3); + else if (m_address == 0x2f) + update_prescale(2); + } +} + + +//------------------------------------------------- +// write - handle a write to the register +// interface +//------------------------------------------------- + +void ym2203::write_data(uint8_t data) +{ + if (m_address < 0x10) + { + // 00-0F: write to SSG + m_ssg.write(m_address & 0x0f, data); + } + else + { + // 10-FF: write to FM + m_fm.write(m_address, data); + } + + // mark busy for a bit + m_fm.intf().ymfm_set_busy_end(32 * m_fm.clock_prescale()); +} + + +//------------------------------------------------- +// write - handle a write to the register +// interface +//------------------------------------------------- + +void ym2203::write(uint32_t offset, uint8_t data) +{ + switch (offset & 1) + { + case 0: // address port + write_address(data); + break; + + case 1: // data port + write_data(data); + break; + } +} + + +//------------------------------------------------- +// generate - generate one sample of sound +//------------------------------------------------- + +void ym2203::generate(output_data *output, uint32_t numsamples) +{ + // FM output is just repeated the prescale number of times; note that + // 0 is a special 1.5 case + if (m_fm_samples_per_output != 0) + { + for (uint32_t samp = 0; samp < numsamples; samp++, output++) + { + if ((m_ssg_resampler.sampindex() + samp) % m_fm_samples_per_output == 0) + clock_fm(); + output->data[0] = m_last_fm.data[0]; + } + } + else + { + for (uint32_t samp = 0; samp < numsamples; samp++, output++) + { + uint32_t step = (m_ssg_resampler.sampindex() + samp) % 3; + if (step == 0) + clock_fm(); + output->data[0] = m_last_fm.data[0]; + if (step == 1) + { + clock_fm(); + output->data[0] = (output->data[0] + m_last_fm.data[0]) / 2; + } + } + } + + // resample the SSG as configured + m_ssg_resampler.resample(output - numsamples, numsamples); +} + + +//------------------------------------------------- +// update_prescale - update the prescale value, +// recomputing derived values +//------------------------------------------------- + +void ym2203::update_prescale(uint8_t prescale) +{ + // tell the FM engine + m_fm.set_clock_prescale(prescale); + m_ssg.prescale_changed(); + + // Fidelity: ---- minimum ---- ---- medium ----- ---- maximum----- + // rate = clock/24 rate = clock/12 rate = clock/4 + // Prescale FM rate SSG rate FM rate SSG rate FM rate SSG rate + // 6 3:1 2:3 6:1 4:3 18:1 4:1 + // 3 1.5:1 1:3 3:1 2:3 9:1 2:1 + // 2 1:1 1:6 2:1 1:3 6:1 1:1 + + // compute the number of FM samples per output sample, and select the + // resampler function + if (m_fidelity == OPN_FIDELITY_MIN) + { + switch (prescale) + { + default: + case 6: m_fm_samples_per_output = 3; m_ssg_resampler.configure(2, 3); break; + case 3: m_fm_samples_per_output = 0; m_ssg_resampler.configure(1, 3); break; + case 2: m_fm_samples_per_output = 1; m_ssg_resampler.configure(1, 6); break; + } + } + else if (m_fidelity == OPN_FIDELITY_MED) + { + switch (prescale) + { + default: + case 6: m_fm_samples_per_output = 6; m_ssg_resampler.configure(4, 3); break; + case 3: m_fm_samples_per_output = 3; m_ssg_resampler.configure(2, 3); break; + case 2: m_fm_samples_per_output = 2; m_ssg_resampler.configure(1, 3); break; + } + } + else + { + switch (prescale) + { + default: + case 6: m_fm_samples_per_output = 18; m_ssg_resampler.configure(4, 1); break; + case 3: m_fm_samples_per_output = 9; m_ssg_resampler.configure(2, 1); break; + case 2: m_fm_samples_per_output = 6; m_ssg_resampler.configure(1, 1); break; + } + } + + // if overriding the SSG, override the configuration with the nop + // resampler to at least keep the sample index moving forward + if (m_ssg.overridden()) + m_ssg_resampler.configure(0, 0); +} + + +//------------------------------------------------- +// clock_fm - clock FM state +//------------------------------------------------- + +void ym2203::clock_fm() +{ + // clock the system + m_fm.clock(fm_engine::ALL_CHANNELS); + + // update the FM content; OPN is full 14-bit with no intermediate clipping + m_fm.output(m_last_fm.clear(), 0, 32767, fm_engine::ALL_CHANNELS); + + // convert to 10.3 floating point value for the DAC and back + m_last_fm.roundtrip_fp(); +} + + + +//********************************************************* +// YM2608 +//********************************************************* + +//------------------------------------------------- +// ym2608 - constructor +//------------------------------------------------- + +ym2608::ym2608(ymfm_interface &intf) : + m_fidelity(OPN_FIDELITY_MAX), + m_address(0), + m_irq_enable(0x1f), + m_flag_control(0x1c), + m_fm(intf), + m_ssg(intf), + m_ssg_resampler(m_ssg), + m_adpcm_a(intf, 0), + m_adpcm_b(intf) +{ + m_last_fm.clear(); + update_prescale(m_fm.clock_prescale()); +} + + +//------------------------------------------------- +// reset - reset the system +//------------------------------------------------- + +void ym2608::reset() +{ + // reset the engines + m_fm.reset(); + m_ssg.reset(); + m_adpcm_a.reset(); + m_adpcm_b.reset(); + + // configure ADPCM percussion sounds; these are present in an embedded ROM + m_adpcm_a.set_start_end(0, 0x0000, 0x01bf); // bass drum + m_adpcm_a.set_start_end(1, 0x01c0, 0x043f); // snare drum + m_adpcm_a.set_start_end(2, 0x0440, 0x1b7f); // top cymbal + m_adpcm_a.set_start_end(3, 0x1b80, 0x1cff); // high hat + m_adpcm_a.set_start_end(4, 0x1d00, 0x1f7f); // tom tom + m_adpcm_a.set_start_end(5, 0x1f80, 0x1fff); // rim shot + + // initialize our special interrupt states, then read the upper status + // register, which updates the IRQs + m_irq_enable = 0x1f; + m_flag_control = 0x1c; + read_status_hi(); +} + + +//------------------------------------------------- +// save_restore - save or restore the data +//------------------------------------------------- + +void ym2608::save_restore(ymfm_saved_state &state) +{ + state.save_restore(m_address); + state.save_restore(m_irq_enable); + state.save_restore(m_flag_control); + state.save_restore(m_last_fm.data); + + m_fm.save_restore(state); + m_ssg.save_restore(state); + m_ssg_resampler.save_restore(state); + m_adpcm_a.save_restore(state); + m_adpcm_b.save_restore(state); +} + + +//------------------------------------------------- +// read_status - read the status register +//------------------------------------------------- + +uint8_t ym2608::read_status() +{ + uint8_t result = m_fm.status() & (fm_engine::STATUS_TIMERA | fm_engine::STATUS_TIMERB); + if (m_fm.intf().ymfm_is_busy()) + result |= fm_engine::STATUS_BUSY; + return result; +} + + +//------------------------------------------------- +// read_data - read the data register +//------------------------------------------------- + +uint8_t ym2608::read_data() +{ + uint8_t result = 0; + if (m_address < 0x10) + { + // 00-0F: Read from SSG + result = m_ssg.read(m_address & 0x0f); + } + else if (m_address == 0xff) + { + // FF: ID code + result = 1; + } + return result; +} + + +//------------------------------------------------- +// read_status_hi - read the extended status +// register +//------------------------------------------------- + +uint8_t ym2608::read_status_hi() +{ + // fetch regular status + uint8_t status = m_fm.status() & ~(STATUS_ADPCM_B_EOS | STATUS_ADPCM_B_BRDY | STATUS_ADPCM_B_PLAYING); + + // fetch ADPCM-B status, and merge in the bits + uint8_t adpcm_status = m_adpcm_b.status(); + if ((adpcm_status & adpcm_b_channel::STATUS_EOS) != 0) + status |= STATUS_ADPCM_B_EOS; + if ((adpcm_status & adpcm_b_channel::STATUS_BRDY) != 0) + status |= STATUS_ADPCM_B_BRDY; + if ((adpcm_status & adpcm_b_channel::STATUS_PLAYING) != 0) + status |= STATUS_ADPCM_B_PLAYING; + + // turn off any bits that have been requested to be masked + status &= ~(m_flag_control & 0x1f); + + // update the status so that IRQs are propagated + m_fm.set_reset_status(status, ~status); + + // merge in the busy flag + if (m_fm.intf().ymfm_is_busy()) + status |= fm_engine::STATUS_BUSY; + return status; +} + + +//------------------------------------------------- +// read_data_hi - read the upper data register +//------------------------------------------------- + +uint8_t ym2608::read_data_hi() +{ + uint8_t result = 0; + if ((m_address & 0xff) < 0x10) + { + // 00-0F: Read from ADPCM-B + result = m_adpcm_b.read(m_address & 0x0f); + } + return result; +} + + +//------------------------------------------------- +// read - handle a read from the device +//------------------------------------------------- + +uint8_t ym2608::read(uint32_t offset) +{ + uint8_t result = 0; + switch (offset & 3) + { + case 0: // status port, YM2203 compatible + result = read_status(); + break; + + case 1: // data port (only SSG) + result = read_data(); + break; + + case 2: // status port, extended + result = read_status_hi(); + break; + + case 3: // ADPCM-B data + result = read_data_hi(); + break; + } + return result; +} + + +//------------------------------------------------- +// write_address - handle a write to the address +// register +//------------------------------------------------- + +void ym2608::write_address(uint8_t data) +{ + // just set the address + m_address = data; + + // special case: update the prescale + if (m_address >= 0x2d && m_address <= 0x2f) + { + // 2D-2F: prescaler select + if (m_address == 0x2d) + update_prescale(6); + else if (m_address == 0x2e && m_fm.clock_prescale() == 6) + update_prescale(3); + else if (m_address == 0x2f) + update_prescale(2); + } +} + + +//------------------------------------------------- +// write - handle a write to the data register +//------------------------------------------------- + +void ym2608::write_data(uint8_t data) +{ + // ignore if paired with upper address + if (bitfield(m_address, 8)) + return; + + if (m_address < 0x10) + { + // 00-0F: write to SSG + m_ssg.write(m_address & 0x0f, data); + } + else if (m_address < 0x20) + { + // 10-1F: write to ADPCM-A + m_adpcm_a.write(m_address & 0x0f, data); + } + else if (m_address == 0x29) + { + // 29: special IRQ mask register + m_irq_enable = data; + m_fm.set_irq_mask(m_irq_enable & ~m_flag_control & 0x1f); + } + else + { + // 20-28, 2A-FF: write to FM + m_fm.write(m_address, data); + } + + // mark busy for a bit + m_fm.intf().ymfm_set_busy_end(32 * m_fm.clock_prescale()); +} + + +//------------------------------------------------- +// write_address_hi - handle a write to the upper +// address register +//------------------------------------------------- + +void ym2608::write_address_hi(uint8_t data) +{ + // just set the address + m_address = 0x100 | data; +} + + +//------------------------------------------------- +// write_data_hi - handle a write to the upper +// data register +//------------------------------------------------- + +void ym2608::write_data_hi(uint8_t data) +{ + // ignore if paired with upper address + if (!bitfield(m_address, 8)) + return; + + if (m_address < 0x110) + { + // 100-10F: write to ADPCM-B + m_adpcm_b.write(m_address & 0x0f, data); + } + else if (m_address == 0x110) + { + // 110: IRQ flag control + if (bitfield(data, 7)) + m_fm.set_reset_status(0, 0xff); + else + { + m_flag_control = data; + m_fm.set_irq_mask(m_irq_enable & ~m_flag_control & 0x1f); + } + } + else + { + // 111-1FF: write to FM + m_fm.write(m_address, data); + } + + // mark busy for a bit + m_fm.intf().ymfm_set_busy_end(32 * m_fm.clock_prescale()); +} + + +//------------------------------------------------- +// write - handle a write to the register +// interface +//------------------------------------------------- + +void ym2608::write(uint32_t offset, uint8_t data) +{ + switch (offset & 3) + { + case 0: // address port + write_address(data); + break; + + case 1: // data port + write_data(data); + break; + + case 2: // upper address port + write_address_hi(data); + break; + + case 3: // upper data port + write_data_hi(data); + break; + } +} + + +//------------------------------------------------- +// generate - generate one sample of sound +//------------------------------------------------- + +void ym2608::generate(output_data *output, uint32_t numsamples) +{ + // FM output is just repeated the prescale number of times; note that + // 0 is a special 1.5 case + if (m_fm_samples_per_output != 0) + { + for (uint32_t samp = 0; samp < numsamples; samp++, output++) + { + if ((m_ssg_resampler.sampindex() + samp) % m_fm_samples_per_output == 0) + clock_fm_and_adpcm(); + output->data[0] = m_last_fm.data[0]; + output->data[1] = m_last_fm.data[1]; + } + } + else + { + for (uint32_t samp = 0; samp < numsamples; samp++, output++) + { + uint32_t step = (m_ssg_resampler.sampindex() + samp) % 3; + if (step == 0) + clock_fm_and_adpcm(); + output->data[0] = m_last_fm.data[0]; + output->data[1] = m_last_fm.data[1]; + if (step == 1) + { + clock_fm_and_adpcm(); + output->data[0] = (output->data[0] + m_last_fm.data[0]) / 2; + output->data[1] = (output->data[1] + m_last_fm.data[1]) / 2; + } + } + } + + // resample the SSG as configured + m_ssg_resampler.resample(output - numsamples, numsamples); +} + + +//------------------------------------------------- +// update_prescale - update the prescale value, +// recomputing derived values +//------------------------------------------------- + +void ym2608::update_prescale(uint8_t prescale) +{ + // tell the FM engine + m_fm.set_clock_prescale(prescale); + m_ssg.prescale_changed(); + + // Fidelity: ---- minimum ---- ---- medium ----- ---- maximum----- + // rate = clock/48 rate = clock/24 rate = clock/8 + // Prescale FM rate SSG rate FM rate SSG rate FM rate SSG rate + // 6 3:1 2:3 6:1 4:3 18:1 4:1 + // 3 1.5:1 1:3 3:1 2:3 9:1 2:1 + // 2 1:1 1:6 2:1 1:3 6:1 1:1 + + // compute the number of FM samples per output sample, and select the + // resampler function + if (m_fidelity == OPN_FIDELITY_MIN) + { + switch (prescale) + { + default: + case 6: m_fm_samples_per_output = 3; m_ssg_resampler.configure(2, 3); break; + case 3: m_fm_samples_per_output = 0; m_ssg_resampler.configure(1, 3); break; + case 2: m_fm_samples_per_output = 1; m_ssg_resampler.configure(1, 6); break; + } + } + else if (m_fidelity == OPN_FIDELITY_MED) + { + switch (prescale) + { + default: + case 6: m_fm_samples_per_output = 6; m_ssg_resampler.configure(4, 3); break; + case 3: m_fm_samples_per_output = 3; m_ssg_resampler.configure(2, 3); break; + case 2: m_fm_samples_per_output = 2; m_ssg_resampler.configure(1, 3); break; + } + } + else + { + switch (prescale) + { + default: + case 6: m_fm_samples_per_output = 18; m_ssg_resampler.configure(4, 1); break; + case 3: m_fm_samples_per_output = 9; m_ssg_resampler.configure(2, 1); break; + case 2: m_fm_samples_per_output = 6; m_ssg_resampler.configure(1, 1); break; + } + } + + // if overriding the SSG, override the configuration with the nop + // resampler to at least keep the sample index moving forward + if (m_ssg.overridden()) + m_ssg_resampler.configure(0, 0); +} + + +//------------------------------------------------- +// clock_fm_and_adpcm - clock FM and ADPCM state +//------------------------------------------------- + +void ym2608::clock_fm_and_adpcm() +{ + // top bit of the IRQ enable flags controls 3-channel vs 6-channel mode + uint32_t fmmask = bitfield(m_irq_enable, 7) ? 0x3f : 0x07; + + // clock the system + uint32_t env_counter = m_fm.clock(fm_engine::ALL_CHANNELS); + + // clock the ADPCM-A engine on every envelope cycle + // (channels 4 and 5 clock every 2 envelope clocks) + if (bitfield(env_counter, 0, 2) == 0) + m_adpcm_a.clock(bitfield(env_counter, 2) ? 0x0f : 0x3f); + + // clock the ADPCM-B engine every cycle + m_adpcm_b.clock(); + + // update the FM content; OPNA is 13-bit with no intermediate clipping + m_fm.output(m_last_fm.clear(), 1, 32767, fmmask); + + // mix in the ADPCM and clamp + m_adpcm_a.output(m_last_fm, 0x3f); + m_adpcm_b.output(m_last_fm, 1); + m_last_fm.clamp16(); +} + + +//********************************************************* +// YMF288 +//********************************************************* + +// YMF288 is a YM2608 with the following changes: +// * ADPCM-B part removed +// * prescaler removed (fixed at 6) +// * CSM removed +// * Low power mode added +// * SSG tone frequency is altered in some way? (explicitly DC for Tp 0-7, also double volume in some cases) +// * I/O ports removed +// * Shorter busy times +// * All registers can be read + +//------------------------------------------------- +// ymf288 - constructor +//------------------------------------------------- + +ymf288::ymf288(ymfm_interface &intf) : + m_fidelity(OPN_FIDELITY_MAX), + m_address(0), + m_irq_enable(0x03), + m_flag_control(0x03), + m_fm(intf), + m_ssg(intf), + m_ssg_resampler(m_ssg), + m_adpcm_a(intf, 0) +{ + m_last_fm.clear(); + update_prescale(); +} + + +//------------------------------------------------- +// reset - reset the system +//------------------------------------------------- + +void ymf288::reset() +{ + // reset the engines + m_fm.reset(); + m_ssg.reset(); + m_adpcm_a.reset(); + + // configure ADPCM percussion sounds; these are present in an embedded ROM + m_adpcm_a.set_start_end(0, 0x0000, 0x01bf); // bass drum + m_adpcm_a.set_start_end(1, 0x01c0, 0x043f); // snare drum + m_adpcm_a.set_start_end(2, 0x0440, 0x1b7f); // top cymbal + m_adpcm_a.set_start_end(3, 0x1b80, 0x1cff); // high hat + m_adpcm_a.set_start_end(4, 0x1d00, 0x1f7f); // tom tom + m_adpcm_a.set_start_end(5, 0x1f80, 0x1fff); // rim shot + + // initialize our special interrupt states, then read the upper status + // register, which updates the IRQs + m_irq_enable = 0x03; + m_flag_control = 0x00; + read_status_hi(); +} + + +//------------------------------------------------- +// save_restore - save or restore the data +//------------------------------------------------- + +void ymf288::save_restore(ymfm_saved_state &state) +{ + state.save_restore(m_address); + state.save_restore(m_irq_enable); + state.save_restore(m_flag_control); + state.save_restore(m_last_fm.data); + + m_fm.save_restore(state); + m_ssg.save_restore(state); + m_ssg_resampler.save_restore(state); + m_adpcm_a.save_restore(state); +} + + +//------------------------------------------------- +// read_status - read the status register +//------------------------------------------------- + +uint8_t ymf288::read_status() +{ + uint8_t result = m_fm.status() & (fm_engine::STATUS_TIMERA | fm_engine::STATUS_TIMERB); + if (m_fm.intf().ymfm_is_busy()) + result |= fm_engine::STATUS_BUSY; + return result; +} + + +//------------------------------------------------- +// read_data - read the data register +//------------------------------------------------- + +uint8_t ymf288::read_data() +{ + uint8_t result = 0; + if (m_address < 0x0e) + { + // 00-0D: Read from SSG + result = m_ssg.read(m_address & 0x0f); + } + else if (m_address < 0x10) + { + // 0E-0F: I/O ports not supported + result = 0xff; + } + else if (m_address == 0xff) + { + // FF: ID code + result = 2; + } + else if (ymf288_mode()) + { + // registers are readable in YMF288 mode + result = m_fm.regs().read(m_address); + } + return result; +} + + +//------------------------------------------------- +// read_status_hi - read the extended status +// register +//------------------------------------------------- + +uint8_t ymf288::read_status_hi() +{ + // fetch regular status + uint8_t status = m_fm.status() & (fm_engine::STATUS_TIMERA | fm_engine::STATUS_TIMERB); + + // turn off any bits that have been requested to be masked + status &= ~(m_flag_control & 0x03); + + // update the status so that IRQs are propagated + m_fm.set_reset_status(status, ~status); + + // merge in the busy flag + if (m_fm.intf().ymfm_is_busy()) + status |= fm_engine::STATUS_BUSY; + return status; +} + + +//------------------------------------------------- +// read - handle a read from the device +//------------------------------------------------- + +uint8_t ymf288::read(uint32_t offset) +{ + uint8_t result = 0; + switch (offset & 3) + { + case 0: // status port, YM2203 compatible + result = read_status(); + break; + + case 1: // data port + result = read_data(); + break; + + case 2: // status port, extended + result = read_status_hi(); + break; + + case 3: // unmapped + debug::log_unexpected_read_write("Unexpected read from YMF288 offset %d\n", offset & 3); + break; + } + return result; +} + + +//------------------------------------------------- +// write_address - handle a write to the address +// register +//------------------------------------------------- + +void ymf288::write_address(uint8_t data) +{ + // just set the address + m_address = data; + + // in YMF288 mode, busy is signaled after address writes too + if (ymf288_mode()) + m_fm.intf().ymfm_set_busy_end(16); +} + + +//------------------------------------------------- +// write - handle a write to the data register +//------------------------------------------------- + +void ymf288::write_data(uint8_t data) +{ + // ignore if paired with upper address + if (bitfield(m_address, 8)) + return; + + // wait times are shorter in YMF288 mode + int busy_cycles = ymf288_mode() ? 16 : 32 * m_fm.clock_prescale(); + if (m_address < 0x0e) + { + // 00-0D: write to SSG + m_ssg.write(m_address & 0x0f, data); + } + else if (m_address < 0x10) + { + // 0E-0F: I/O ports not supported + } + else if (m_address < 0x20) + { + // 10-1F: write to ADPCM-A + m_adpcm_a.write(m_address & 0x0f, data); + busy_cycles = 32 * m_fm.clock_prescale(); + } + else if (m_address == 0x27) + { + // 27: mode register; CSM isn't supported so disable it + data &= 0x7f; + m_fm.write(m_address, data); + } + else if (m_address == 0x29) + { + // 29: special IRQ mask register + m_irq_enable = data; + m_fm.set_irq_mask(m_irq_enable & ~m_flag_control & 0x03); + } + else + { + // 20-27, 2A-FF: write to FM + m_fm.write(m_address, data); + } + + // mark busy for a bit + m_fm.intf().ymfm_set_busy_end(busy_cycles); +} + + +//------------------------------------------------- +// write_address_hi - handle a write to the upper +// address register +//------------------------------------------------- + +void ymf288::write_address_hi(uint8_t data) +{ + // just set the address + m_address = 0x100 | data; + + // in YMF288 mode, busy is signaled after address writes too + if (ymf288_mode()) + m_fm.intf().ymfm_set_busy_end(16); +} + + +//------------------------------------------------- +// write_data_hi - handle a write to the upper +// data register +//------------------------------------------------- + +void ymf288::write_data_hi(uint8_t data) +{ + // ignore if paired with upper address + if (!bitfield(m_address, 8)) + return; + + // wait times are shorter in YMF288 mode + int busy_cycles = ymf288_mode() ? 16 : 32 * m_fm.clock_prescale(); + if (m_address == 0x110) + { + // 110: IRQ flag control + if (bitfield(data, 7)) + m_fm.set_reset_status(0, 0xff); + else + { + m_flag_control = data; + m_fm.set_irq_mask(m_irq_enable & ~m_flag_control & 0x03); + } + } + else + { + // 100-10F,111-1FF: write to FM + m_fm.write(m_address, data); + } + + // mark busy for a bit + m_fm.intf().ymfm_set_busy_end(busy_cycles); +} + + +//------------------------------------------------- +// write - handle a write to the register +// interface +//------------------------------------------------- + +void ymf288::write(uint32_t offset, uint8_t data) +{ + switch (offset & 3) + { + case 0: // address port + write_address(data); + break; + + case 1: // data port + write_data(data); + break; + + case 2: // upper address port + write_address_hi(data); + break; + + case 3: // upper data port + write_data_hi(data); + break; + } +} + + +//------------------------------------------------- +// generate - generate one sample of sound +//------------------------------------------------- + +void ymf288::generate(output_data *output, uint32_t numsamples) +{ + // FM output is just repeated the prescale number of times; note that + // 0 is a special 1.5 case + if (m_fm_samples_per_output != 0) + { + for (uint32_t samp = 0; samp < numsamples; samp++, output++) + { + if ((m_ssg_resampler.sampindex() + samp) % m_fm_samples_per_output == 0) + clock_fm_and_adpcm(); + output->data[0] = m_last_fm.data[0]; + output->data[1] = m_last_fm.data[1]; + } + } + else + { + for (uint32_t samp = 0; samp < numsamples; samp++, output++) + { + uint32_t step = (m_ssg_resampler.sampindex() + samp) % 3; + if (step == 0) + clock_fm_and_adpcm(); + output->data[0] = m_last_fm.data[0]; + output->data[1] = m_last_fm.data[1]; + if (step == 1) + { + clock_fm_and_adpcm(); + output->data[0] = (output->data[0] + m_last_fm.data[0]) / 2; + output->data[1] = (output->data[1] + m_last_fm.data[1]) / 2; + } + } + } + + // resample the SSG as configured + m_ssg_resampler.resample(output - numsamples, numsamples); +} + + +//------------------------------------------------- +// update_prescale - update the prescale value, +// recomputing derived values +//------------------------------------------------- + +void ymf288::update_prescale() +{ + // Fidelity: ---- minimum ---- ---- medium ----- ---- maximum----- + // rate = clock/144 rate = clock/144 rate = clock/16 + // Prescale FM rate SSG rate FM rate SSG rate FM rate SSG rate + // 6 1:1 2:9 1:1 2:9 9:1 2:1 + + // compute the number of FM samples per output sample, and select the + // resampler function + if (m_fidelity == OPN_FIDELITY_MIN || m_fidelity == OPN_FIDELITY_MED) + { + m_fm_samples_per_output = 1; + m_ssg_resampler.configure(2, 9); + } + else + { + m_fm_samples_per_output = 9; + m_ssg_resampler.configure(2, 1); + } + + // if overriding the SSG, override the configuration with the nop + // resampler to at least keep the sample index moving forward + if (m_ssg.overridden()) + m_ssg_resampler.configure(0, 0); +} + + +//------------------------------------------------- +// clock_fm_and_adpcm - clock FM and ADPCM state +//------------------------------------------------- + +void ymf288::clock_fm_and_adpcm() +{ + // top bit of the IRQ enable flags controls 3-channel vs 6-channel mode + uint32_t fmmask = bitfield(m_irq_enable, 7) ? 0x3f : 0x07; + + // clock the system + uint32_t env_counter = m_fm.clock(fm_engine::ALL_CHANNELS); + + // clock the ADPCM-A engine on every envelope cycle + // (channels 4 and 5 clock every 2 envelope clocks) + if (bitfield(env_counter, 0, 2) == 0) + m_adpcm_a.clock(bitfield(env_counter, 2) ? 0x0f : 0x3f); + + // update the FM content; OPNA is 13-bit with no intermediate clipping + m_fm.output(m_last_fm.clear(), 1, 32767, fmmask); + + // mix in the ADPCM + m_adpcm_a.output(m_last_fm, 0x3f); +} + + + +//********************************************************* +// YM2610 +//********************************************************* + +//------------------------------------------------- +// ym2610 - constructor +//------------------------------------------------- + +ym2610::ym2610(ymfm_interface &intf, uint8_t channel_mask) : + m_fidelity(OPN_FIDELITY_MAX), + m_address(0), + m_fm_mask(channel_mask), + m_eos_status(0x00), + m_flag_mask(EOS_FLAGS_MASK), + m_fm(intf), + m_ssg(intf), + m_ssg_resampler(m_ssg), + m_adpcm_a(intf, 8), + m_adpcm_b(intf, 8) +{ + update_prescale(); +} + + +//------------------------------------------------- +// reset - reset the system +//------------------------------------------------- + +void ym2610::reset() +{ + // reset the engines + m_fm.reset(); + m_ssg.reset(); + m_adpcm_a.reset(); + m_adpcm_b.reset(); + + // initialize our special interrupt states + m_eos_status = 0x00; + m_flag_mask = EOS_FLAGS_MASK; +} + + +//------------------------------------------------- +// save_restore - save or restore the data +//------------------------------------------------- + +void ym2610::save_restore(ymfm_saved_state &state) +{ + state.save_restore(m_address); + state.save_restore(m_eos_status); + state.save_restore(m_flag_mask); + + m_fm.save_restore(state); + m_ssg.save_restore(state); + m_ssg_resampler.save_restore(state); + m_adpcm_a.save_restore(state); + m_adpcm_b.save_restore(state); +} + + +//------------------------------------------------- +// read_status - read the status register +//------------------------------------------------- + +uint8_t ym2610::read_status() +{ + uint8_t result = m_fm.status() & (fm_engine::STATUS_TIMERA | fm_engine::STATUS_TIMERB); + if (m_fm.intf().ymfm_is_busy()) + result |= fm_engine::STATUS_BUSY; + return result; +} + + +//------------------------------------------------- +// read_data - read the data register +//------------------------------------------------- + +uint8_t ym2610::read_data() +{ + uint8_t result = 0; + if (m_address < 0x0e) + { + // 00-0D: Read from SSG + result = m_ssg.read(m_address & 0x0f); + } + else if (m_address < 0x10) + { + // 0E-0F: I/O ports not supported + result = 0xff; + } + else if (m_address == 0xff) + { + // FF: ID code + result = 1; + } + return result; +} + + +//------------------------------------------------- +// read_status_hi - read the extended status +// register +//------------------------------------------------- + +uint8_t ym2610::read_status_hi() +{ + return m_eos_status & m_flag_mask; +} + + +//------------------------------------------------- +// read_data_hi - read the upper data register +//------------------------------------------------- + +uint8_t ym2610::read_data_hi() +{ + uint8_t result = 0; + return result; +} + + +//------------------------------------------------- +// read - handle a read from the device +//------------------------------------------------- + +uint8_t ym2610::read(uint32_t offset) +{ + uint8_t result = 0; + switch (offset & 3) + { + case 0: // status port, YM2203 compatible + result = read_status(); + break; + + case 1: // data port (only SSG) + result = read_data(); + break; + + case 2: // status port, extended + result = read_status_hi(); + break; + + case 3: // ADPCM-B data + result = read_data_hi(); + break; + } + return result; +} + + +//------------------------------------------------- +// write_address - handle a write to the address +// register +//------------------------------------------------- + +void ym2610::write_address(uint8_t data) +{ + // just set the address + m_address = data; +} + + +//------------------------------------------------- +// write - handle a write to the data register +//------------------------------------------------- + +void ym2610::write_data(uint8_t data) +{ + // ignore if paired with upper address + if (bitfield(m_address, 8)) + return; + + if (m_address < 0x0e) + { + // 00-0D: write to SSG + m_ssg.write(m_address & 0x0f, data); + } + else if (m_address < 0x10) + { + // 0E-0F: I/O ports not supported + } + else if (m_address < 0x1c) + { + // 10-1B: write to ADPCM-B + // YM2610 effectively forces external mode on, and disables recording + if (m_address == 0x10) + data = (data | 0x20) & ~0x40; + m_adpcm_b.write(m_address & 0x0f, data); + } + else if (m_address == 0x1c) + { + // 1C: EOS flag reset + m_flag_mask = ~data & EOS_FLAGS_MASK; + m_eos_status &= ~(data & EOS_FLAGS_MASK); + } + else + { + // 1D-FF: write to FM + m_fm.write(m_address, data); + } + + // mark busy for a bit + m_fm.intf().ymfm_set_busy_end(32 * m_fm.clock_prescale()); +} + + +//------------------------------------------------- +// write_address_hi - handle a write to the upper +// address register +//------------------------------------------------- + +void ym2610::write_address_hi(uint8_t data) +{ + // just set the address + m_address = 0x100 | data; +} + + +//------------------------------------------------- +// write_data_hi - handle a write to the upper +// data register +//------------------------------------------------- + +void ym2610::write_data_hi(uint8_t data) +{ + // ignore if paired with upper address + if (!bitfield(m_address, 8)) + return; + + if (m_address < 0x130) + { + // 100-12F: write to ADPCM-A + m_adpcm_a.write(m_address & 0x3f, data); + } + else + { + // 130-1FF: write to FM + m_fm.write(m_address, data); + } + + // mark busy for a bit + m_fm.intf().ymfm_set_busy_end(32 * m_fm.clock_prescale()); +} + + +//------------------------------------------------- +// write - handle a write to the register +// interface +//------------------------------------------------- + +void ym2610::write(uint32_t offset, uint8_t data) +{ + switch (offset & 3) + { + case 0: // address port + write_address(data); + break; + + case 1: // data port + write_data(data); + break; + + case 2: // upper address port + write_address_hi(data); + break; + + case 3: // upper data port + write_data_hi(data); + break; + } +} + + +//------------------------------------------------- +// generate - generate one sample of sound +//------------------------------------------------- + +void ym2610::generate(output_data *output, uint32_t numsamples) +{ + // FM output is just repeated the prescale number of times + for (uint32_t samp = 0; samp < numsamples; samp++, output++) + { + if ((m_ssg_resampler.sampindex() + samp) % m_fm_samples_per_output == 0) + clock_fm_and_adpcm(); + output->data[0] = m_last_fm.data[0]; + output->data[1] = m_last_fm.data[1]; + } + + // resample the SSG as configured + m_ssg_resampler.resample(output - numsamples, numsamples); +} + + +//------------------------------------------------- +// update_prescale - update the prescale value, +// recomputing derived values +//------------------------------------------------- + +void ym2610::update_prescale() +{ + // Fidelity: ---- minimum ---- ---- medium ----- ---- maximum----- + // rate = clock/144 rate = clock/144 rate = clock/16 + // Prescale FM rate SSG rate FM rate SSG rate FM rate SSG rate + // 6 1:1 2:9 1:1 2:9 9:1 2:1 + + // compute the number of FM samples per output sample, and select the + // resampler function + if (m_fidelity == OPN_FIDELITY_MIN || m_fidelity == OPN_FIDELITY_MED) + { + m_fm_samples_per_output = 1; + m_ssg_resampler.configure(2, 9); + } + else + { + m_fm_samples_per_output = 9; + m_ssg_resampler.configure(2, 1); + } + + // if overriding the SSG, override the configuration with the nop + // resampler to at least keep the sample index moving forward + if (m_ssg.overridden()) + m_ssg_resampler.configure(0, 0); +} + + +//------------------------------------------------- +// clock_fm_and_adpcm - clock FM and ADPCM state +//------------------------------------------------- + +void ym2610::clock_fm_and_adpcm() +{ + // clock the system + uint32_t env_counter = m_fm.clock(m_fm_mask); + + // clock the ADPCM-A engine on every envelope cycle + if (bitfield(env_counter, 0, 2) == 0) + m_eos_status |= m_adpcm_a.clock(0x3f); + + // clock the ADPCM-B engine every cycle + m_adpcm_b.clock(); + + // we track the last ADPCM-B EOS value in bit 6 (which is hidden from callers); + // if it changed since the last sample, update the visible EOS state in bit 7 + uint8_t live_eos = ((m_adpcm_b.status() & adpcm_b_channel::STATUS_EOS) != 0) ? 0x40 : 0x00; + if (((live_eos ^ m_eos_status) & 0x40) != 0) + m_eos_status = (m_eos_status & ~0xc0) | live_eos | (live_eos << 1); + + // update the FM content; OPNB is 13-bit with no intermediate clipping + m_fm.output(m_last_fm.clear(), 1, 32767, m_fm_mask); + + // mix in the ADPCM and clamp + m_adpcm_a.output(m_last_fm, 0x3f); + m_adpcm_b.output(m_last_fm, 1); + m_last_fm.clamp16(); +} + + + +//********************************************************* +// YM2612 +//********************************************************* + +//------------------------------------------------- +// ym2612 - constructor +//------------------------------------------------- + +ym2612::ym2612(ymfm_interface &intf) : + m_address(0), + m_dac_data(0), + m_dac_enable(0), + m_fm(intf) +{ +} + + +//------------------------------------------------- +// reset - reset the system +//------------------------------------------------- + +void ym2612::reset() +{ + // reset the engines + m_fm.reset(); +} + + +//------------------------------------------------- +// save_restore - save or restore the data +//------------------------------------------------- + +void ym2612::save_restore(ymfm_saved_state &state) +{ + state.save_restore(m_address); + state.save_restore(m_dac_data); + state.save_restore(m_dac_enable); + m_fm.save_restore(state); +} + + +//------------------------------------------------- +// read_status - read the status register +//------------------------------------------------- + +uint8_t ym2612::read_status() +{ + uint8_t result = m_fm.status(); + if (m_fm.intf().ymfm_is_busy()) + result |= fm_engine::STATUS_BUSY; + return result; +} + + +//------------------------------------------------- +// read - handle a read from the device +//------------------------------------------------- + +uint8_t ym2612::read(uint32_t offset) +{ + uint8_t result = 0; + switch (offset & 3) + { + case 0: // status port, YM2203 compatible + result = read_status(); + break; + + case 1: // data port (unused) + case 2: // status port, extended + case 3: // data port (unused) + debug::log_unexpected_read_write("Unexpected read from YM2612 offset %d\n", offset & 3); + break; + } + return result; +} + + +//------------------------------------------------- +// write_address - handle a write to the address +// register +//------------------------------------------------- + +void ym2612::write_address(uint8_t data) +{ + // just set the address + m_address = data; +} + + +//------------------------------------------------- +// write_data - handle a write to the data +// register +//------------------------------------------------- + +void ym2612::write_data(uint8_t data) +{ + // ignore if paired with upper address + if (bitfield(m_address, 8)) + return; + + if (m_address == 0x2a) + { + // 2A: DAC data (most significant 8 bits) + m_dac_data = (m_dac_data & ~0x1fe) | ((data ^ 0x80) << 1); + } + else if (m_address == 0x2b) + { + // 2B: DAC enable (bit 7) + m_dac_enable = bitfield(data, 7); + } + else if (m_address == 0x2c) + { + // 2C: test/low DAC bit + m_dac_data = (m_dac_data & ~1) | bitfield(data, 3); + } + else + { + // 00-29, 2D-FF: write to FM + m_fm.write(m_address, data); + } + + // mark busy for a bit + m_fm.intf().ymfm_set_busy_end(32 * m_fm.clock_prescale()); +} + + +//------------------------------------------------- +// write_address_hi - handle a write to the upper +// address register +//------------------------------------------------- + +void ym2612::write_address_hi(uint8_t data) +{ + // just set the address + m_address = 0x100 | data; +} + + +//------------------------------------------------- +// write_data_hi - handle a write to the upper +// data register +//------------------------------------------------- + +void ym2612::write_data_hi(uint8_t data) +{ + // ignore if paired with upper address + if (!bitfield(m_address, 8)) + return; + + // 100-1FF: write to FM + m_fm.write(m_address, data); + + // mark busy for a bit + m_fm.intf().ymfm_set_busy_end(32 * m_fm.clock_prescale()); +} + + +//------------------------------------------------- +// write - handle a write to the register +// interface +//------------------------------------------------- + +void ym2612::write(uint32_t offset, uint8_t data) +{ + switch (offset & 3) + { + case 0: // address port + write_address(data); + break; + + case 1: // data port + write_data(data); + break; + + case 2: // upper address port + write_address_hi(data); + break; + + case 3: // upper data port + write_data_hi(data); + break; + } +} + + +//------------------------------------------------- +// generate - generate one sample of sound +//------------------------------------------------- + +void ym2612::generate(output_data *output, uint32_t numsamples) +{ + for (uint32_t samp = 0; samp < numsamples; samp++, output++) + { + // clock the system + m_fm.clock(fm_engine::ALL_CHANNELS); + + // sum individual channels to apply DAC discontinuity on each + output->clear(); + output_data temp; + + // first do FM-only channels; OPN2 is 9-bit with intermediate clipping + int const last_fm_channel = m_dac_enable ? 5 : 6; + for (int chan = 0; chan < last_fm_channel; chan++) + { + m_fm.output(temp.clear(), 5, 256, 1 << chan); + output->data[0] += dac_discontinuity(temp.data[0]); + output->data[1] += dac_discontinuity(temp.data[1]); + } + + // add in DAC + if (m_dac_enable) + { + // DAC enabled: start with DAC value then add the first 5 channels only + int32_t dacval = dac_discontinuity(int16_t(m_dac_data << 7) >> 7); + output->data[0] += m_fm.regs().ch_output_0(0x102) ? dacval : dac_discontinuity(0); + output->data[1] += m_fm.regs().ch_output_1(0x102) ? dacval : dac_discontinuity(0); + } + + // output is technically multiplexed rather than mixed, but that requires + // a better sound mixer than we usually have, so just average over the six + // channels; also apply a 64/65 factor to account for the discontinuity + // adjustment above + output->data[0] = (output->data[0] * 128) * 64 / (6 * 65); + output->data[1] = (output->data[1] * 128) * 64 / (6 * 65); + } +} + + +//------------------------------------------------- +// generate - generate one sample of sound +//------------------------------------------------- + +void ym3438::generate(output_data *output, uint32_t numsamples) +{ + for (uint32_t samp = 0; samp < numsamples; samp++, output++) + { + // clock the system + m_fm.clock(fm_engine::ALL_CHANNELS); + + // first do FM-only channels; OPN2C is 9-bit with intermediate clipping + if (!m_dac_enable) + { + // DAC disabled: all 6 channels sum together + m_fm.output(output->clear(), 5, 256, fm_engine::ALL_CHANNELS); + } + else + { + // DAC enabled: start with DAC value then add the first 5 channels only + int32_t dacval = int16_t(m_dac_data << 7) >> 7; + output->data[0] = m_fm.regs().ch_output_0(0x102) ? dacval : 0; + output->data[1] = m_fm.regs().ch_output_1(0x102) ? dacval : 0; + m_fm.output(*output, 5, 256, fm_engine::ALL_CHANNELS ^ (1 << 5)); + } + + // YM3438 doesn't have the same DAC discontinuity, though its output is + // multiplexed like the YM2612 + output->data[0] = (output->data[0] * 128) / 6; + output->data[1] = (output->data[1] * 128) / 6; + } +} + + +//------------------------------------------------- +// generate - generate one sample of sound +//------------------------------------------------- + +void ymf276::generate(output_data *output, uint32_t numsamples) +{ + for (uint32_t samp = 0; samp < numsamples; samp++, output++) + { + // clock the system + m_fm.clock(fm_engine::ALL_CHANNELS); + + // first do FM-only channels; OPN2L is 14-bit with intermediate clipping + if (!m_dac_enable) + { + // DAC disabled: all 6 channels sum together + m_fm.output(output->clear(), 0, 8191, fm_engine::ALL_CHANNELS); + } + else + { + // DAC enabled: start with DAC value then add the first 5 channels only + int32_t dacval = int16_t(m_dac_data << 7) >> 7; + output->data[0] = m_fm.regs().ch_output_0(0x102) ? dacval : 0; + output->data[1] = m_fm.regs().ch_output_1(0x102) ? dacval : 0; + m_fm.output(*output, 0, 8191, fm_engine::ALL_CHANNELS ^ (1 << 5)); + } + + // YMF276 is properly mixed; it shifts down 1 bit before clamping + output->data[0] = clamp(output->data[0] >> 1, -32768, 32767); + output->data[1] = clamp(output->data[1] >> 1, -32768, 32767); + } +} + +} diff --git a/src/sound/ymfm/ymfm_opn.h b/src/sound/ymfm/ymfm_opn.h new file mode 100644 index 000000000..bab68ed93 --- /dev/null +++ b/src/sound/ymfm/ymfm_opn.h @@ -0,0 +1,802 @@ +// BSD 3-Clause License +// +// Copyright (c) 2021, Aaron Giles +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// 1. Redistributions of source code must retain the above copyright notice, this +// list of conditions and the following disclaimer. +// +// 2. Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// 3. Neither the name of the copyright holder nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#ifndef YMFM_OPN_H +#define YMFM_OPN_H + +#pragma once + +#include "ymfm.h" +#include "ymfm_adpcm.h" +#include "ymfm_fm.h" +#include "ymfm_ssg.h" + +namespace ymfm +{ + +//********************************************************* +// REGISTER CLASSES +//********************************************************* + +// ======================> opn_registers_base + +// +// OPN register map: +// +// System-wide registers: +// 21 xxxxxxxx Test register +// 22 ----x--- LFO enable [OPNA+ only] +// -----xxx LFO rate [OPNA+ only] +// 24 xxxxxxxx Timer A value (upper 8 bits) +// 25 ------xx Timer A value (lower 2 bits) +// 26 xxxxxxxx Timer B value +// 27 xx------ CSM/Multi-frequency mode for channel #2 +// --x----- Reset timer B +// ---x---- Reset timer A +// ----x--- Enable timer B +// -----x-- Enable timer A +// ------x- Load timer B +// -------x Load timer A +// 28 x------- Key on/off operator 4 +// -x------ Key on/off operator 3 +// --x----- Key on/off operator 2 +// ---x---- Key on/off operator 1 +// ------xx Channel select +// +// Per-channel registers (channel in address bits 0-1) +// Note that all these apply to address+100 as well on OPNA+ +// A0-A3 xxxxxxxx Frequency number lower 8 bits +// A4-A7 --xxx--- Block (0-7) +// -----xxx Frequency number upper 3 bits +// B0-B3 --xxx--- Feedback level for operator 1 (0-7) +// -----xxx Operator connection algorithm (0-7) +// B4-B7 x------- Pan left [OPNA] +// -x------ Pan right [OPNA] +// --xx---- LFO AM shift (0-3) [OPNA+ only] +// -----xxx LFO PM depth (0-7) [OPNA+ only] +// +// Per-operator registers (channel in address bits 0-1, operator in bits 2-3) +// Note that all these apply to address+100 as well on OPNA+ +// 30-3F -xxx---- Detune value (0-7) +// ----xxxx Multiple value (0-15) +// 40-4F -xxxxxxx Total level (0-127) +// 50-5F xx------ Key scale rate (0-3) +// ---xxxxx Attack rate (0-31) +// 60-6F x------- LFO AM enable [OPNA] +// ---xxxxx Decay rate (0-31) +// 70-7F ---xxxxx Sustain rate (0-31) +// 80-8F xxxx---- Sustain level (0-15) +// ----xxxx Release rate (0-15) +// 90-9F ----x--- SSG-EG enable +// -----xxx SSG-EG envelope (0-7) +// +// Special multi-frequency registers (channel implicitly #2; operator in address bits 0-1) +// A8-AB xxxxxxxx Frequency number lower 8 bits +// AC-AF --xxx--- Block (0-7) +// -----xxx Frequency number upper 3 bits +// +// Internal (fake) registers: +// B8-BB --xxxxxx Latched frequency number upper bits (from A4-A7) +// BC-BF --xxxxxx Latched frequency number upper bits (from AC-AF) +// + +template +class opn_registers_base : public fm_registers_base +{ +public: + // constants + static constexpr uint32_t OUTPUTS = IsOpnA ? 2 : 1; + static constexpr uint32_t CHANNELS = IsOpnA ? 6 : 3; + static constexpr uint32_t ALL_CHANNELS = (1 << CHANNELS) - 1; + static constexpr uint32_t OPERATORS = CHANNELS * 4; + static constexpr uint32_t WAVEFORMS = 1; + static constexpr uint32_t REGISTERS = IsOpnA ? 0x200 : 0x100; + static constexpr uint32_t REG_MODE = 0x27; + static constexpr uint32_t DEFAULT_PRESCALE = 6; + static constexpr uint32_t EG_CLOCK_DIVIDER = 3; + static constexpr bool EG_HAS_SSG = true; + static constexpr bool MODULATOR_DELAY = false; + static constexpr uint32_t CSM_TRIGGER_MASK = 1 << 2; + static constexpr uint8_t STATUS_TIMERA = 0x01; + static constexpr uint8_t STATUS_TIMERB = 0x02; + static constexpr uint8_t STATUS_BUSY = 0x80; + static constexpr uint8_t STATUS_IRQ = 0; + + // constructor + opn_registers_base(); + + // reset to initial state + void reset(); + + // save/restore + void save_restore(ymfm_saved_state &state); + + // map channel number to register offset + static constexpr uint32_t channel_offset(uint32_t chnum) + { + assert(chnum < CHANNELS); + if (!IsOpnA) + return chnum; + else + return (chnum % 3) + 0x100 * (chnum / 3); + } + + // map operator number to register offset + static constexpr uint32_t operator_offset(uint32_t opnum) + { + assert(opnum < OPERATORS); + if (!IsOpnA) + return opnum + opnum / 3; + else + return (opnum % 12) + ((opnum % 12) / 3) + 0x100 * (opnum / 12); + } + + // return an array of operator indices for each channel + struct operator_mapping { uint32_t chan[CHANNELS]; }; + void operator_map(operator_mapping &dest) const; + + // read a register value + uint8_t read(uint16_t index) const { return m_regdata[index]; } + + // handle writes to the register array + bool write(uint16_t index, uint8_t data, uint32_t &chan, uint32_t &opmask); + + // clock the noise and LFO, if present, returning LFO PM value + int32_t clock_noise_and_lfo(); + + // reset the LFO + void reset_lfo() { m_lfo_counter = 0; } + + // return the AM offset from LFO for the given channel + uint32_t lfo_am_offset(uint32_t choffs) const; + + // return LFO/noise states + uint32_t noise_state() const { return 0; } + + // caching helpers + void cache_operator_data(uint32_t choffs, uint32_t opoffs, opdata_cache &cache); + + // compute the phase step, given a PM value + uint32_t compute_phase_step(uint32_t choffs, uint32_t opoffs, opdata_cache const &cache, int32_t lfo_raw_pm); + + // log a key-on event + std::string log_keyon(uint32_t choffs, uint32_t opoffs); + + // system-wide registers + uint32_t test() const { return byte(0x21, 0, 8); } + uint32_t lfo_enable() const { return IsOpnA ? byte(0x22, 3, 1) : 0; } + uint32_t lfo_rate() const { return IsOpnA ? byte(0x22, 0, 3) : 0; } + uint32_t timer_a_value() const { return word(0x24, 0, 8, 0x25, 0, 2); } + uint32_t timer_b_value() const { return byte(0x26, 0, 8); } + uint32_t csm() const { return (byte(0x27, 6, 2) == 2); } + uint32_t multi_freq() const { return (byte(0x27, 6, 2) != 0); } + uint32_t reset_timer_b() const { return byte(0x27, 5, 1); } + uint32_t reset_timer_a() const { return byte(0x27, 4, 1); } + uint32_t enable_timer_b() const { return byte(0x27, 3, 1); } + uint32_t enable_timer_a() const { return byte(0x27, 2, 1); } + uint32_t load_timer_b() const { return byte(0x27, 1, 1); } + uint32_t load_timer_a() const { return byte(0x27, 0, 1); } + uint32_t multi_block_freq(uint32_t num) const { return word(0xac, 0, 6, 0xa8, 0, 8, num); } + + // per-channel registers + uint32_t ch_block_freq(uint32_t choffs) const { return word(0xa4, 0, 6, 0xa0, 0, 8, choffs); } + uint32_t ch_feedback(uint32_t choffs) const { return byte(0xb0, 3, 3, choffs); } + uint32_t ch_algorithm(uint32_t choffs) const { return byte(0xb0, 0, 3, choffs); } + uint32_t ch_output_any(uint32_t choffs) const { return IsOpnA ? byte(0xb4, 6, 2, choffs) : 1; } + uint32_t ch_output_0(uint32_t choffs) const { return IsOpnA ? byte(0xb4, 7, 1, choffs) : 1; } + uint32_t ch_output_1(uint32_t choffs) const { return IsOpnA ? byte(0xb4, 6, 1, choffs) : 0; } + uint32_t ch_output_2(uint32_t choffs) const { return 0; } + uint32_t ch_output_3(uint32_t choffs) const { return 0; } + uint32_t ch_lfo_am_sens(uint32_t choffs) const { return IsOpnA ? byte(0xb4, 4, 2, choffs) : 0; } + uint32_t ch_lfo_pm_sens(uint32_t choffs) const { return IsOpnA ? byte(0xb4, 0, 3, choffs) : 0; } + + // per-operator registers + uint32_t op_detune(uint32_t opoffs) const { return byte(0x30, 4, 3, opoffs); } + uint32_t op_multiple(uint32_t opoffs) const { return byte(0x30, 0, 4, opoffs); } + uint32_t op_total_level(uint32_t opoffs) const { return byte(0x40, 0, 7, opoffs); } + uint32_t op_ksr(uint32_t opoffs) const { return byte(0x50, 6, 2, opoffs); } + uint32_t op_attack_rate(uint32_t opoffs) const { return byte(0x50, 0, 5, opoffs); } + uint32_t op_decay_rate(uint32_t opoffs) const { return byte(0x60, 0, 5, opoffs); } + uint32_t op_lfo_am_enable(uint32_t opoffs) const { return IsOpnA ? byte(0x60, 7, 1, opoffs) : 0; } + uint32_t op_sustain_rate(uint32_t opoffs) const { return byte(0x70, 0, 5, opoffs); } + uint32_t op_sustain_level(uint32_t opoffs) const { return byte(0x80, 4, 4, opoffs); } + uint32_t op_release_rate(uint32_t opoffs) const { return byte(0x80, 0, 4, opoffs); } + uint32_t op_ssg_eg_enable(uint32_t opoffs) const { return byte(0x90, 3, 1, opoffs); } + uint32_t op_ssg_eg_mode(uint32_t opoffs) const { return byte(0x90, 0, 3, opoffs); } + +protected: + // return a bitfield extracted from a byte + uint32_t byte(uint32_t offset, uint32_t start, uint32_t count, uint32_t extra_offset = 0) const + { + return bitfield(m_regdata[offset + extra_offset], start, count); + } + + // return a bitfield extracted from a pair of bytes, MSBs listed first + uint32_t word(uint32_t offset1, uint32_t start1, uint32_t count1, uint32_t offset2, uint32_t start2, uint32_t count2, uint32_t extra_offset = 0) const + { + return (byte(offset1, start1, count1, extra_offset) << count2) | byte(offset2, start2, count2, extra_offset); + } + + // internal state + uint32_t m_lfo_counter; // LFO counter + uint8_t m_lfo_am; // current LFO AM value + uint8_t m_regdata[REGISTERS]; // register data + uint16_t m_waveform[WAVEFORMS][WAVEFORM_LENGTH]; // waveforms +}; + +using opn_registers = opn_registers_base; +using opna_registers = opn_registers_base; + + + +//********************************************************* +// OPN IMPLEMENTATION CLASSES +//********************************************************* + +// A note about prescaling and sample rates. +// +// YM2203, YM2608, and YM2610 contain an onboard SSG (basically, a YM2149). +// In order to properly generate sound at fully fidelity, the output sample +// rate of the YM2149 must be input_clock / 8. This is much higher than the +// FM needs, but in the interest of keeping things simple, the OPN generate +// functions will output at the higher rate and just replicate the last FM +// sample as many times as needed. +// +// To make things even more complicated, the YM2203 and YM2608 allow for +// software-controlled prescaling, which affects the FM and SSG clocks in +// different ways. There are three settings: divide by 6/4 (FM/SSG); divide +// by 3/2; and divide by 2/1. +// +// Thus, the minimum output sample rate needed by each part of the chip +// varies with the prescale as follows: +// +// ---- YM2203 ----- ---- YM2608 ----- ---- YM2610 ----- +// Prescale FM rate SSG rate FM rate SSG rate FM rate SSG rate +// 6 /72 /16 /144 /32 /144 /32 +// 3 /36 /8 /72 /16 +// 2 /24 /4 /48 /8 +// +// If we standardized on the fastest SSG rate, we'd end up with the following +// (ratios are output_samples:source_samples): +// +// ---- YM2203 ----- ---- YM2608 ----- ---- YM2610 ----- +// rate = clock/4 rate = clock/8 rate = clock/16 +// Prescale FM rate SSG rate FM rate SSG rate FM rate SSG rate +// 6 18:1 4:1 18:1 4:1 9:1 2:1 +// 3 9:1 2:1 9:1 2:1 +// 2 6:1 1:1 6:1 1:1 +// +// However, that's a pretty big performance hit for minimal gain. Going to +// the other extreme, we could standardize on the fastest FM rate, but then +// at least one prescale case (3) requires the FM to be smeared across two +// output samples: +// +// ---- YM2203 ----- ---- YM2608 ----- ---- YM2610 ----- +// rate = clock/24 rate = clock/48 rate = clock/144 +// Prescale FM rate SSG rate FM rate SSG rate FM rate SSG rate +// 6 3:1 2:3 3:1 2:3 1:1 2:9 +// 3 1.5:1 1:3 1.5:1 1:3 +// 2 1:1 1:6 1:1 1:6 +// +// Stepping back one factor of 2 addresses that issue: +// +// ---- YM2203 ----- ---- YM2608 ----- ---- YM2610 ----- +// rate = clock/12 rate = clock/24 rate = clock/144 +// Prescale FM rate SSG rate FM rate SSG rate FM rate SSG rate +// 6 6:1 4:3 6:1 4:3 1:1 2:9 +// 3 3:1 2:3 3:1 2:3 +// 2 2:1 1:3 2:1 1:3 +// +// This gives us three levels of output fidelity: +// OPN_FIDELITY_MAX -- highest sample rate, using fastest SSG rate +// OPN_FIDELITY_MIN -- lowest sample rate, using fastest FM rate +// OPN_FIDELITY_MED -- medium sample rate such that FM is never smeared +// +// At the maximum clocks for YM2203/YM2608 (4Mhz/8MHz), these rates will +// end up as: +// OPN_FIDELITY_MAX = 1000kHz +// OPN_FIDELITY_MIN = 166kHz +// OPN_FIEDLITY_MED = 333kHz + + +// ======================> opn_fidelity + +enum opn_fidelity : uint8_t +{ + OPN_FIDELITY_MAX, + OPN_FIDELITY_MIN, + OPN_FIDELITY_MED, + + OPN_FIDELITY_DEFAULT = OPN_FIDELITY_MAX +}; + + +// ======================> ssg_resampler + +template +class ssg_resampler +{ +private: + // helper to add the last computed value to the sums, applying the given scale + void add_last(int32_t &sum0, int32_t &sum1, int32_t &sum2, int32_t scale = 1); + + // helper to clock a new value and then add it to the sums, applying the given scale + void clock_and_add(int32_t &sum0, int32_t &sum1, int32_t &sum2, int32_t scale = 1); + + // helper to write the sums to the appropriate outputs, applying the given + // divisor to the final result + void write_to_output(OutputType *output, int32_t sum0, int32_t sum1, int32_t sum2, int32_t divisor = 1); + +public: + // constructor + ssg_resampler(ssg_engine &ssg); + + // save/restore + void save_restore(ymfm_saved_state &state); + + // get the current sample index + uint32_t sampindex() const { return m_sampindex; } + + // configure the ratio + void configure(uint8_t outsamples, uint8_t srcsamples); + + // resample + void resample(OutputType *output, uint32_t numsamples) + { + (this->*m_resampler)(output, numsamples); + } + +private: + // resample SSG output to the target at a rate of 1 SSG sample + // to every n output samples + template + void resample_n_1(OutputType *output, uint32_t numsamples); + + // resample SSG output to the target at a rate of n SSG samples + // to every 1 output sample + template + void resample_1_n(OutputType *output, uint32_t numsamples); + + // resample SSG output to the target at a rate of 9 SSG samples + // to every 2 output samples + void resample_2_9(OutputType *output, uint32_t numsamples); + + // resample SSG output to the target at a rate of 3 SSG samples + // to every 1 output sample + void resample_1_3(OutputType *output, uint32_t numsamples); + + // resample SSG output to the target at a rate of 3 SSG samples + // to every 2 output samples + void resample_2_3(OutputType *output, uint32_t numsamples); + + // resample SSG output to the target at a rate of 3 SSG samples + // to every 4 output samples + void resample_4_3(OutputType *output, uint32_t numsamples); + + // no-op resampler + void resample_nop(OutputType *output, uint32_t numsamples); + + // define a pointer type + using resample_func = void (ssg_resampler::*)(OutputType *output, uint32_t numsamples); + + // internal state + ssg_engine &m_ssg; + uint32_t m_sampindex; + resample_func m_resampler; + ssg_engine::output_data m_last; +}; + + +// ======================> ym2203 + +class ym2203 +{ +public: + using fm_engine = fm_engine_base; + static constexpr uint32_t FM_OUTPUTS = fm_engine::OUTPUTS; + static constexpr uint32_t SSG_OUTPUTS = ssg_engine::OUTPUTS; + static constexpr uint32_t OUTPUTS = FM_OUTPUTS + SSG_OUTPUTS; + using output_data = ymfm_output; + + // constructor + ym2203(ymfm_interface &intf); + + // configuration + void ssg_override(ssg_override &intf) { m_ssg.override(intf); } + void set_fidelity(opn_fidelity fidelity) { m_fidelity = fidelity; update_prescale(m_fm.clock_prescale()); } + + // reset + void reset(); + + // save/restore + void save_restore(ymfm_saved_state &state); + + // pass-through helpers + uint32_t sample_rate(uint32_t input_clock) const + { + switch (m_fidelity) + { + case OPN_FIDELITY_MIN: return input_clock / 24; + case OPN_FIDELITY_MED: return input_clock / 12; + default: + case OPN_FIDELITY_MAX: return input_clock / 4; + } + } + uint32_t ssg_effective_clock(uint32_t input_clock) const { uint32_t scale = m_fm.clock_prescale() * 2 / 3; return input_clock * 2 / scale; } + void invalidate_caches() { m_fm.invalidate_caches(); } + + // read access + uint8_t read_status(); + uint8_t read_data(); + uint8_t read(uint32_t offset); + + // write access + void write_address(uint8_t data); + void write_data(uint8_t data); + void write(uint32_t offset, uint8_t data); + + // generate one sample of sound + void generate(output_data *output, uint32_t numsamples = 1); + +protected: + // internal helpers + void update_prescale(uint8_t prescale); + void clock_fm(); + + // internal state + opn_fidelity m_fidelity; // configured fidelity + uint8_t m_address; // address register + uint8_t m_fm_samples_per_output; // how many samples to repeat + fm_engine::output_data m_last_fm; // last FM output + fm_engine m_fm; // core FM engine + ssg_engine m_ssg; // SSG engine + ssg_resampler m_ssg_resampler; // SSG resampler helper +}; + + + +//********************************************************* +// OPNA IMPLEMENTATION CLASSES +//********************************************************* + +// ======================> ym2608 + +class ym2608 +{ + static constexpr uint8_t STATUS_ADPCM_B_EOS = 0x04; + static constexpr uint8_t STATUS_ADPCM_B_BRDY = 0x08; + static constexpr uint8_t STATUS_ADPCM_B_ZERO = 0x10; + static constexpr uint8_t STATUS_ADPCM_B_PLAYING = 0x20; + +public: + using fm_engine = fm_engine_base; + static constexpr uint32_t FM_OUTPUTS = fm_engine::OUTPUTS; + static constexpr uint32_t SSG_OUTPUTS = 1; + static constexpr uint32_t OUTPUTS = FM_OUTPUTS + SSG_OUTPUTS; + using output_data = ymfm_output; + + // constructor + ym2608(ymfm_interface &intf); + + // configuration + void ssg_override(ssg_override &intf) { m_ssg.override(intf); } + void set_fidelity(opn_fidelity fidelity) { m_fidelity = fidelity; update_prescale(m_fm.clock_prescale()); } + + // reset + void reset(); + + // save/restore + void save_restore(ymfm_saved_state &state); + + // pass-through helpers + uint32_t sample_rate(uint32_t input_clock) const + { + switch (m_fidelity) + { + case OPN_FIDELITY_MIN: return input_clock / 48; + case OPN_FIDELITY_MED: return input_clock / 24; + default: + case OPN_FIDELITY_MAX: return input_clock / 8; + } + } + uint32_t ssg_effective_clock(uint32_t input_clock) const { uint32_t scale = m_fm.clock_prescale() * 2 / 3; return input_clock / scale; } + void invalidate_caches() { m_fm.invalidate_caches(); } + + // read access + uint8_t read_status(); + uint8_t read_data(); + uint8_t read_status_hi(); + uint8_t read_data_hi(); + uint8_t read(uint32_t offset); + + // write access + void write_address(uint8_t data); + void write_data(uint8_t data); + void write_address_hi(uint8_t data); + void write_data_hi(uint8_t data); + void write(uint32_t offset, uint8_t data); + + // generate one sample of sound + void generate(output_data *output, uint32_t numsamples = 1); + +protected: + // internal helpers + void update_prescale(uint8_t prescale); + void clock_fm_and_adpcm(); + + // internal state + opn_fidelity m_fidelity; // configured fidelity + uint16_t m_address; // address register + uint8_t m_fm_samples_per_output; // how many samples to repeat + uint8_t m_irq_enable; // IRQ enable register + uint8_t m_flag_control; // flag control register + fm_engine::output_data m_last_fm; // last FM output + fm_engine m_fm; // core FM engine + ssg_engine m_ssg; // SSG engine + ssg_resampler m_ssg_resampler; // SSG resampler helper + adpcm_a_engine m_adpcm_a; // ADPCM-A engine + adpcm_b_engine m_adpcm_b; // ADPCM-B engine +}; + + +// ======================> ymf288 + +class ymf288 +{ +public: + using fm_engine = fm_engine_base; + static constexpr uint32_t FM_OUTPUTS = fm_engine::OUTPUTS; + static constexpr uint32_t SSG_OUTPUTS = 1; + static constexpr uint32_t OUTPUTS = FM_OUTPUTS + SSG_OUTPUTS; + using output_data = ymfm_output; + + // constructor + ymf288(ymfm_interface &intf); + + // configuration + void ssg_override(ssg_override &intf) { m_ssg.override(intf); } + void set_fidelity(opn_fidelity fidelity) { m_fidelity = fidelity; update_prescale(); } + + // reset + void reset(); + + // save/restore + void save_restore(ymfm_saved_state &state); + + // pass-through helpers + uint32_t sample_rate(uint32_t input_clock) const + { + switch (m_fidelity) + { + case OPN_FIDELITY_MIN: return input_clock / 144; + case OPN_FIDELITY_MED: return input_clock / 144; + default: + case OPN_FIDELITY_MAX: return input_clock / 16; + } + } + uint32_t ssg_effective_clock(uint32_t input_clock) const { return input_clock / 4; } + void invalidate_caches() { m_fm.invalidate_caches(); } + + // read access + uint8_t read_status(); + uint8_t read_data(); + uint8_t read_status_hi(); + uint8_t read(uint32_t offset); + + // write access + void write_address(uint8_t data); + void write_data(uint8_t data); + void write_address_hi(uint8_t data); + void write_data_hi(uint8_t data); + void write(uint32_t offset, uint8_t data); + + // generate one sample of sound + void generate(output_data *output, uint32_t numsamples = 1); + +protected: + // internal helpers + bool ymf288_mode() { return ((m_fm.regs().read(0x20) & 0x02) != 0); } + void update_prescale(); + void clock_fm_and_adpcm(); + + // internal state + opn_fidelity m_fidelity; // configured fidelity + uint16_t m_address; // address register + uint8_t m_fm_samples_per_output; // how many samples to repeat + uint8_t m_irq_enable; // IRQ enable register + uint8_t m_flag_control; // flag control register + fm_engine::output_data m_last_fm; // last FM output + fm_engine m_fm; // core FM engine + ssg_engine m_ssg; // SSG engine + ssg_resampler m_ssg_resampler; // SSG resampler helper + adpcm_a_engine m_adpcm_a; // ADPCM-A engine +}; + + +// ======================> ym2610/ym2610b + +class ym2610 +{ + static constexpr uint8_t EOS_FLAGS_MASK = 0xbf; + +public: + using fm_engine = fm_engine_base; + static constexpr uint32_t FM_OUTPUTS = fm_engine::OUTPUTS; + static constexpr uint32_t SSG_OUTPUTS = 1; + static constexpr uint32_t OUTPUTS = FM_OUTPUTS + SSG_OUTPUTS; + using output_data = ymfm_output; + + // constructor + ym2610(ymfm_interface &intf, uint8_t channel_mask = 0x36); + + // configuration + void ssg_override(ssg_override &intf) { m_ssg.override(intf); } + void set_fidelity(opn_fidelity fidelity) { m_fidelity = fidelity; update_prescale(); } + + // reset + void reset(); + + // save/restore + void save_restore(ymfm_saved_state &state); + + // pass-through helpers + uint32_t sample_rate(uint32_t input_clock) const + { + switch (m_fidelity) + { + case OPN_FIDELITY_MIN: return input_clock / 144; + case OPN_FIDELITY_MED: return input_clock / 144; + default: + case OPN_FIDELITY_MAX: return input_clock / 16; + } + } + uint32_t ssg_effective_clock(uint32_t input_clock) const { return input_clock / 4; } + void invalidate_caches() { m_fm.invalidate_caches(); } + + // read access + uint8_t read_status(); + uint8_t read_data(); + uint8_t read_status_hi(); + uint8_t read_data_hi(); + uint8_t read(uint32_t offset); + + // write access + void write_address(uint8_t data); + void write_data(uint8_t data); + void write_address_hi(uint8_t data); + void write_data_hi(uint8_t data); + void write(uint32_t offset, uint8_t data); + + // generate one sample of sound + void generate(output_data *output, uint32_t numsamples = 1); + +protected: + // internal helpers + void update_prescale(); + void clock_fm_and_adpcm(); + + // internal state + opn_fidelity m_fidelity; // configured fidelity + uint16_t m_address; // address register + uint8_t const m_fm_mask; // FM channel mask + uint8_t m_fm_samples_per_output; // how many samples to repeat + uint8_t m_eos_status; // end-of-sample signals + uint8_t m_flag_mask; // flag mask control + fm_engine::output_data m_last_fm; // last FM output + fm_engine m_fm; // core FM engine + ssg_engine m_ssg; // core FM engine + ssg_resampler m_ssg_resampler; // SSG resampler helper + adpcm_a_engine m_adpcm_a; // ADPCM-A engine + adpcm_b_engine m_adpcm_b; // ADPCM-B engine +}; + +class ym2610b : public ym2610 +{ +public: + // constructor + ym2610b(ymfm_interface &intf) : ym2610(intf, 0x3f) { } +}; + + +// ======================> ym2612 + +class ym2612 +{ +public: + using fm_engine = fm_engine_base; + static constexpr uint32_t OUTPUTS = fm_engine::OUTPUTS; + using output_data = fm_engine::output_data; + + // constructor + ym2612(ymfm_interface &intf); + + // reset + void reset(); + + // save/restore + void save_restore(ymfm_saved_state &state); + + // pass-through helpers + uint32_t sample_rate(uint32_t input_clock) const { return m_fm.sample_rate(input_clock); } + void invalidate_caches() { m_fm.invalidate_caches(); } + + // read access + uint8_t read_status(); + uint8_t read(uint32_t offset); + + // write access + void write_address(uint8_t data); + void write_data(uint8_t data); + void write_address_hi(uint8_t data); + void write_data_hi(uint8_t data); + void write(uint32_t offset, uint8_t data); + + // generate one sample of sound + void generate(output_data *output, uint32_t numsamples = 1); + +protected: + // simulate the DAC discontinuity + constexpr int32_t dac_discontinuity(int32_t value) const { return (value < 0) ? (value - 3) : (value + 4); } + + // internal state + uint16_t m_address; // address register + uint16_t m_dac_data; // 9-bit DAC data + uint8_t m_dac_enable; // DAC enabled? + fm_engine m_fm; // core FM engine +}; + + +// ======================> ym3438 + +class ym3438 : public ym2612 +{ +public: + ym3438(ymfm_interface &intf) : ym2612(intf) { } + + // generate one sample of sound + void generate(output_data *output, uint32_t numsamples = 1); +}; + + +// ======================> ymf276 + +class ymf276 : public ym2612 +{ +public: + ymf276(ymfm_interface &intf) : ym2612(intf) { } + + // generate one sample of sound + void generate(output_data *output, uint32_t numsamples); +}; + +} + + +#endif // YMFM_OPN_H diff --git a/src/sound/ymfm/ymfm_opq.cpp b/src/sound/ymfm/ymfm_opq.cpp new file mode 100644 index 000000000..e6f6fa5ea --- /dev/null +++ b/src/sound/ymfm/ymfm_opq.cpp @@ -0,0 +1,480 @@ +// BSD 3-Clause License +// +// Copyright (c) 2021, Aaron Giles +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// 1. Redistributions of source code must retain the above copyright notice, this +// list of conditions and the following disclaimer. +// +// 2. Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// 3. Neither the name of the copyright holder nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#include "ymfm_opq.h" +#include "ymfm_fm.ipp" + +#define TEMPORARY_DEBUG_PRINTS (0) + +// +// OPQ (aka YM3806/YM3533) +// +// This chip is not officially documented as far as I know. What I have +// comes from Jari Kangas' work on reverse engineering the PSR70: +// +// https://github.com/JKN0/PSR70-reverse +// +// OPQ appears be bsaically a mixture of OPM and OPN. +// + +namespace ymfm +{ + +//********************************************************* +// OPQ SPECIFICS +//********************************************************* + +//------------------------------------------------- +// opq_registers - constructor +//------------------------------------------------- + +opq_registers::opq_registers() : + m_lfo_counter(0), + m_lfo_am(0) +{ + // create the waveforms + for (uint32_t index = 0; index < WAVEFORM_LENGTH; index++) + m_waveform[0][index] = abs_sin_attenuation(index) | (bitfield(index, 9) << 15); + + uint16_t zeroval = m_waveform[0][0]; + for (uint32_t index = 0; index < WAVEFORM_LENGTH; index++) + m_waveform[1][index] = bitfield(index, 9) ? zeroval : m_waveform[0][index]; +} + + +//------------------------------------------------- +// reset - reset to initial state +//------------------------------------------------- + +void opq_registers::reset() +{ + std::fill_n(&m_regdata[0], REGISTERS, 0); + + // enable output on both channels by default + m_regdata[0x10] = m_regdata[0x11] = m_regdata[0x12] = m_regdata[0x13] = 0xc0; + m_regdata[0x14] = m_regdata[0x15] = m_regdata[0x16] = m_regdata[0x17] = 0xc0; +} + + +//------------------------------------------------- +// save_restore - save or restore the data +//------------------------------------------------- + +void opq_registers::save_restore(ymfm_saved_state &state) +{ + state.save_restore(m_lfo_counter); + state.save_restore(m_lfo_am); + state.save_restore(m_regdata); +} + + +//------------------------------------------------- +// operator_map - return an array of operator +// indices for each channel; for OPM this is fixed +//------------------------------------------------- + +void opq_registers::operator_map(operator_mapping &dest) const +{ + // seems like the operators are not swizzled like they are on OPM/OPN? + static const operator_mapping s_fixed_map = + { { + operator_list( 0, 8, 16, 24 ), // Channel 0 operators + operator_list( 1, 9, 17, 25 ), // Channel 1 operators + operator_list( 2, 10, 18, 26 ), // Channel 2 operators + operator_list( 3, 11, 19, 27 ), // Channel 3 operators + operator_list( 4, 12, 20, 28 ), // Channel 4 operators + operator_list( 5, 13, 21, 29 ), // Channel 5 operators + operator_list( 6, 14, 22, 30 ), // Channel 6 operators + operator_list( 7, 15, 23, 31 ), // Channel 7 operators + } }; + dest = s_fixed_map; +} + + +//------------------------------------------------- +// write - handle writes to the register array +//------------------------------------------------- + +bool opq_registers::write(uint16_t index, uint8_t data, uint32_t &channel, uint32_t &opmask) +{ + assert(index < REGISTERS); + + // detune/multiple share a register based on the MSB of what is written + // remap the multiple values to 100-11F + if ((index & 0xe0) == 0x40 && bitfield(data, 7) != 0) + index += 0xc0; + + m_regdata[index] = data; + + // handle writes to the key on index + if (index == 0x05) + { + channel = bitfield(data, 0, 3); + opmask = bitfield(data, 3, 4); + return true; + } + return false; +} + + +//------------------------------------------------- +// clock_noise_and_lfo - clock the noise and LFO, +// handling clock division, depth, and waveform +// computations +//------------------------------------------------- + +int32_t opq_registers::clock_noise_and_lfo() +{ + // OPQ LFO is not well-understood, but the enable and rate values + // look a lot like OPN, so we'll crib from there as a starting point + + // if LFO not enabled (not present on OPN), quick exit with 0s + if (!lfo_enable()) + { + m_lfo_counter = 0; + m_lfo_am = 0; + return 0; + } + + // this table is based on converting the frequencies in the applications + // manual to clock dividers, based on the assumption of a 7-bit LFO value + static uint8_t const lfo_max_count[8] = { 109, 78, 72, 68, 63, 45, 9, 6 }; + uint32_t subcount = uint8_t(m_lfo_counter++); + + // when we cross the divider count, add enough to zero it and cause an + // increment at bit 8; the 7-bit value lives from bits 8-14 + if (subcount >= lfo_max_count[lfo_rate()]) + m_lfo_counter += 0x101 - subcount; + + // AM value is 7 bits, staring at bit 8; grab the low 6 directly + m_lfo_am = bitfield(m_lfo_counter, 8, 6); + + // first half of the AM period (bit 6 == 0) is inverted + if (bitfield(m_lfo_counter, 8+6) == 0) + m_lfo_am ^= 0x3f; + + // PM value is 5 bits, starting at bit 10; grab the low 3 directly + int32_t pm = bitfield(m_lfo_counter, 10, 3); + + // PM is reflected based on bit 3 + if (bitfield(m_lfo_counter, 10+3)) + pm ^= 7; + + // PM is negated based on bit 4 + return bitfield(m_lfo_counter, 10+4) ? -pm : pm; +} + + +//------------------------------------------------- +// lfo_am_offset - return the AM offset from LFO +// for the given channel +//------------------------------------------------- + +uint32_t opq_registers::lfo_am_offset(uint32_t choffs) const +{ + // OPM maps AM quite differently from OPN + + // shift value for AM sensitivity is [*, 0, 1, 2], + // mapping to values of [0, 23.9, 47.8, and 95.6dB] + uint32_t am_sensitivity = ch_lfo_am_sens(choffs); + if (am_sensitivity == 0) + return 0; + + // QUESTION: see OPN note below for the dB range mapping; it applies + // here as well + + // raw LFO AM value on OPM is 0-FF, which is already a factor of 2 + // larger than the OPN below, putting our staring point at 2x theirs; + // this works out since our minimum is 2x their maximum + return m_lfo_am << (am_sensitivity - 1); +} + + +//------------------------------------------------- +// cache_operator_data - fill the operator cache +// with prefetched data +//------------------------------------------------- + +void opq_registers::cache_operator_data(uint32_t choffs, uint32_t opoffs, opdata_cache &cache) +{ + // set up the easy stuff + cache.waveform = &m_waveform[op_waveform(opoffs)][0]; + + // get frequency from the appropriate registers + uint32_t block_freq = cache.block_freq = (opoffs & 8) ? ch_block_freq_24(choffs) : ch_block_freq_13(choffs); + + // compute the keycode: block_freq is: + // + // BBBFFFFFFFFFFFF + // ^^^^??? + // + // keycode is not understood, so just guessing it is like OPN: + // the 5-bit keycode uses the top 4 bits plus a magic formula + // for the final bit + uint32_t keycode = bitfield(block_freq, 11, 4) << 1; + + // lowest bit is determined by a mix of next lower FNUM bits + // according to this equation from the YM2608 manual: + // + // (F11 & (F10 | F9 | F8)) | (!F11 & F10 & F9 & F8) + // + // for speed, we just look it up in a 16-bit constant + keycode |= bitfield(0xfe80, bitfield(block_freq, 8, 4)); + + // detune adjustment: the detune values supported by the OPQ are + // a much larger range (6 bits vs 3 bits) compared to any other + // known FM chip; based on experiments, it seems that the extra + // bits provide a bigger detune range rather than finer control, + // so until we get true measurements just assemble a net detune + // value by summing smaller detunes + int32_t detune = int32_t(op_detune(opoffs)) - 0x20; + int32_t abs_detune = std::abs(detune); + int32_t adjust = (abs_detune / 3) * detune_adjustment(3, keycode) + detune_adjustment(abs_detune % 3, keycode); + cache.detune = (detune >= 0) ? adjust : -adjust; + + // multiple value, as an x.1 value (0 means 0.5) + static const uint8_t s_multiple_map[16] = { 1,2,4,6,8,10,12,14,16,18,20,24,30,32,34,36 }; + cache.multiple = s_multiple_map[op_multiple(opoffs)]; + + // phase step, or PHASE_STEP_DYNAMIC if PM is active; this depends on + // block_freq, detune, and multiple, so compute it after we've done those + if (lfo_enable() == 0 || ch_lfo_pm_sens(choffs) == 0) + cache.phase_step = compute_phase_step(choffs, opoffs, cache, 0); + else + cache.phase_step = opdata_cache::PHASE_STEP_DYNAMIC; + + // total level, scaled by 8 + cache.total_level = op_total_level(opoffs) << 3; + + // 4-bit sustain level, but 15 means 31 so effectively 5 bits + cache.eg_sustain = op_sustain_level(opoffs); + cache.eg_sustain |= (cache.eg_sustain + 1) & 0x10; + cache.eg_sustain <<= 5; + + // determine KSR adjustment for enevlope rates + uint32_t ksrval = keycode >> (op_ksr(opoffs) ^ 3); + cache.eg_rate[EG_ATTACK] = effective_rate(op_attack_rate(opoffs) * 2, ksrval); + cache.eg_rate[EG_DECAY] = effective_rate(op_decay_rate(opoffs) * 2, ksrval); + cache.eg_rate[EG_SUSTAIN] = effective_rate(op_sustain_rate(opoffs) * 2, ksrval); + cache.eg_rate[EG_RELEASE] = effective_rate(op_release_rate(opoffs) * 4 + 2, ksrval); + cache.eg_rate[EG_REVERB] = (ch_reverb(choffs) != 0) ? 5*4 : cache.eg_rate[EG_RELEASE]; + cache.eg_shift = 0; +} + + +//------------------------------------------------- +// compute_phase_step - compute the phase step +//------------------------------------------------- + +uint32_t opq_registers::compute_phase_step(uint32_t choffs, uint32_t opoffs, opdata_cache const &cache, int32_t lfo_raw_pm) +{ + // OPN phase calculation has only a single detune parameter + // and uses FNUMs instead of keycodes + + // extract frequency number (low 12 bits of block_freq) + uint32_t fnum = bitfield(cache.block_freq, 0, 12); + + // if there's a non-zero PM sensitivity, compute the adjustment + uint32_t pm_sensitivity = ch_lfo_pm_sens(choffs); + if (pm_sensitivity != 0) + { + // apply the phase adjustment based on the upper 7 bits + // of FNUM and the PM depth parameters + fnum += opn_lfo_pm_phase_adjustment(bitfield(cache.block_freq, 5, 7), pm_sensitivity, lfo_raw_pm); + + // keep fnum to 12 bits + fnum &= 0xfff; + } + + // apply block shift to compute phase step + uint32_t block = bitfield(cache.block_freq, 12, 3); + uint32_t phase_step = (fnum << block) >> 2; + + // apply detune based on the keycode + phase_step += cache.detune; + + // clamp to 17 bits in case detune overflows + // QUESTION: is this specific to the YM2612/3438? + phase_step &= 0x1ffff; + + // apply frequency multiplier (which is cached as an x.1 value) + return (phase_step * cache.multiple) >> 1; +} + + +//------------------------------------------------- +// log_keyon - log a key-on event +//------------------------------------------------- + +std::string opq_registers::log_keyon(uint32_t choffs, uint32_t opoffs) +{ + uint32_t chnum = choffs; + uint32_t opnum = opoffs; + + char buffer[256]; + char *end = &buffer[0]; + + end += snprintf(end, SNPRINTF_BUFFER_SIZE_CALC, "%u.%02u freq=%04X dt=%+2d fb=%u alg=%X mul=%X tl=%02X ksr=%u adsr=%02X/%02X/%02X/%X sl=%X out=%c%c", + chnum, opnum, + (opoffs & 1) ? ch_block_freq_24(choffs) : ch_block_freq_13(choffs), + int32_t(op_detune(opoffs)) - 0x20, + ch_feedback(choffs), + ch_algorithm(choffs), + op_multiple(opoffs), + op_total_level(opoffs), + op_ksr(opoffs), + op_attack_rate(opoffs), + op_decay_rate(opoffs), + op_sustain_rate(opoffs), + op_release_rate(opoffs), + op_sustain_level(opoffs), + ch_output_0(choffs) ? 'L' : '-', + ch_output_1(choffs) ? 'R' : '-'); + + bool am = (lfo_enable() && op_lfo_am_enable(opoffs) && ch_lfo_am_sens(choffs) != 0); + if (am) + end += snprintf(end, SNPRINTF_BUFFER_SIZE_CALC, " am=%u", ch_lfo_am_sens(choffs)); + bool pm = (lfo_enable() && ch_lfo_pm_sens(choffs) != 0); + if (pm) + end += snprintf(end, SNPRINTF_BUFFER_SIZE_CALC, " pm=%u", ch_lfo_pm_sens(choffs)); + if (am || pm) + end += snprintf(end, SNPRINTF_BUFFER_SIZE_CALC, " lfo=%02X", lfo_rate()); + if (ch_reverb(choffs)) + end += snprintf(end, SNPRINTF_BUFFER_SIZE_CALC, " reverb"); + + return buffer; +} + + + +//********************************************************* +// YM3806 +//********************************************************* + +//------------------------------------------------- +// ym3806 - constructor +//------------------------------------------------- + +ym3806::ym3806(ymfm_interface &intf) : + m_fm(intf) +{ +} + + +//------------------------------------------------- +// reset - reset the system +//------------------------------------------------- + +void ym3806::reset() +{ + // reset the engines + m_fm.reset(); +} + + +//------------------------------------------------- +// save_restore - save or restore the data +//------------------------------------------------- + +void ym3806::save_restore(ymfm_saved_state &state) +{ + m_fm.save_restore(state); +} + + +//------------------------------------------------- +// read_status - read the status register +//------------------------------------------------- + +uint8_t ym3806::read_status() +{ + uint8_t result = m_fm.status(); + if (m_fm.intf().ymfm_is_busy()) + result |= fm_engine::STATUS_BUSY; + return result; +} + + +//------------------------------------------------- +// read - handle a read from the device +//------------------------------------------------- + +uint8_t ym3806::read(uint32_t offset) +{ + uint8_t result = 0xff; + switch (offset) + { + case 0: // status port + result = read_status(); + break; + + default: // unknown + debug::log_unexpected_read_write("Unexpected read from YM3806 offset %02X\n", offset); + break; + } +if (TEMPORARY_DEBUG_PRINTS && offset != 0) printf("Read %02X = %02X\n", offset, result); + return result; +} + + +//------------------------------------------------- +// write - handle a write to the register +// interface +//------------------------------------------------- + +void ym3806::write(uint32_t offset, uint8_t data) +{ +if (TEMPORARY_DEBUG_PRINTS && (offset != 3 || data != 0x71)) printf("Write %02X = %02X\n", offset, data); + // write the FM register + m_fm.write(offset, data); +} + + +//------------------------------------------------- +// generate - generate one sample of sound +//------------------------------------------------- + +void ym3806::generate(output_data *output, uint32_t numsamples) +{ + for (uint32_t samp = 0; samp < numsamples; samp++, output++) + { + // clock the system + m_fm.clock(fm_engine::ALL_CHANNELS); + + // update the FM content; YM3806 is full 14-bit with no intermediate clipping + m_fm.output(output->clear(), 0, 32767, fm_engine::ALL_CHANNELS); + + // YM3608 appears to go through a YM3012 DAC, which means we want to apply + // the FP truncation logic to the outputs + output->roundtrip_fp(); + } +} + +} diff --git a/src/sound/ymfm/ymfm_opq.h b/src/sound/ymfm/ymfm_opq.h new file mode 100644 index 000000000..f530ac070 --- /dev/null +++ b/src/sound/ymfm/ymfm_opq.h @@ -0,0 +1,293 @@ +// BSD 3-Clause License +// +// Copyright (c) 2021, Aaron Giles +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// 1. Redistributions of source code must retain the above copyright notice, this +// list of conditions and the following disclaimer. +// +// 2. Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// 3. Neither the name of the copyright holder nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#ifndef YMFM_OPQ_H +#define YMFM_OPQ_H + +#pragma once + +#include "ymfm.h" +#include "ymfm_fm.h" + +namespace ymfm +{ + +//********************************************************* +// REGISTER CLASSES +//********************************************************* + +// ======================> opq_registers + +// +// OPQ register map: +// +// System-wide registers: +// 03 xxxxxxxx Timer control (unknown; 0x71 causes interrupts at ~10ms) +// 04 ----x--- LFO disable +// -----xxx LFO frequency (0=~4Hz, 6=~10Hz, 7=~47Hz) +// 05 -x------ Key on/off operator 4 +// --x----- Key on/off operator 3 +// ---x---- Key on/off operator 2 +// ----x--- Key on/off operator 1 +// -----xxx Channel select +// +// Per-channel registers (channel in address bits 0-2) +// 10-17 x------- Pan right +// -x------ Pan left +// --xxx--- Feedback level for operator 1 (0-7) +// -----xxx Operator connection algorithm (0-7) +// 18-1F x------- Reverb +// -xxx---- PM sensitivity +// ------xx AM shift +// 20-27 -xxx---- Block (0-7), Operator 2 & 4 +// ----xxxx Frequency number upper 4 bits, Operator 2 & 4 +// 28-2F -xxx---- Block (0-7), Operator 1 & 3 +// ----xxxx Frequency number upper 4 bits, Operator 1 & 3 +// 30-37 xxxxxxxx Frequency number lower 8 bits, Operator 2 & 4 +// 38-3F xxxxxxxx Frequency number lower 8 bits, Operator 1 & 3 +// +// Per-operator registers (channel in address bits 0-2, operator in bits 3-4) +// 40-5F 0-xxxxxx Detune value (0-63) +// 1---xxxx Multiple value (0-15) +// 60-7F -xxxxxxx Total level (0-127) +// 80-9F xx------ Key scale rate (0-3) +// ---xxxxx Attack rate (0-31) +// A0-BF x------- LFO AM enable, retrigger disable +// x------ Waveform select +// ---xxxxx Decay rate (0-31) +// C0-DF ---xxxxx Sustain rate (0-31) +// E0-FF xxxx---- Sustain level (0-15) +// ----xxxx Release rate (0-15) +// +// Diffs from OPM: +// - 2 frequencies/channel +// - retrigger disable +// - 2 waveforms +// - uses FNUM +// - reverb behavior +// - larger detune range +// +// Questions: +// - timer information is pretty light +// - how does echo work? +// - + +class opq_registers : public fm_registers_base +{ +public: + // constants + static constexpr uint32_t OUTPUTS = 2; + static constexpr uint32_t CHANNELS = 8; + static constexpr uint32_t ALL_CHANNELS = (1 << CHANNELS) - 1; + static constexpr uint32_t OPERATORS = CHANNELS * 4; + static constexpr uint32_t WAVEFORMS = 2; + static constexpr uint32_t REGISTERS = 0x120; + static constexpr uint32_t REG_MODE = 0x03; + static constexpr uint32_t DEFAULT_PRESCALE = 2; + static constexpr uint32_t EG_CLOCK_DIVIDER = 3; + static constexpr bool EG_HAS_REVERB = true; + static constexpr bool MODULATOR_DELAY = false; + static constexpr uint32_t CSM_TRIGGER_MASK = ALL_CHANNELS; + static constexpr uint8_t STATUS_TIMERA = 0; + static constexpr uint8_t STATUS_TIMERB = 0x04; + static constexpr uint8_t STATUS_BUSY = 0x80; + static constexpr uint8_t STATUS_IRQ = 0; + + // constructor + opq_registers(); + + // reset to initial state + void reset(); + + // save/restore + void save_restore(ymfm_saved_state &state); + + // map channel number to register offset + static constexpr uint32_t channel_offset(uint32_t chnum) + { + assert(chnum < CHANNELS); + return chnum; + } + + // map operator number to register offset + static constexpr uint32_t operator_offset(uint32_t opnum) + { + assert(opnum < OPERATORS); + return opnum; + } + + // return an array of operator indices for each channel + struct operator_mapping { uint32_t chan[CHANNELS]; }; + void operator_map(operator_mapping &dest) const; + + // handle writes to the register array + bool write(uint16_t index, uint8_t data, uint32_t &chan, uint32_t &opmask); + + // clock the noise and LFO, if present, returning LFO PM value + int32_t clock_noise_and_lfo(); + + // reset the LFO + void reset_lfo() { m_lfo_counter = 0; } + + // return the AM offset from LFO for the given channel + uint32_t lfo_am_offset(uint32_t choffs) const; + + // return the current noise state, gated by the noise clock + uint32_t noise_state() const { return 0; } + + // caching helpers + void cache_operator_data(uint32_t choffs, uint32_t opoffs, opdata_cache &cache); + + // compute the phase step, given a PM value + uint32_t compute_phase_step(uint32_t choffs, uint32_t opoffs, opdata_cache const &cache, int32_t lfo_raw_pm); + + // log a key-on event + std::string log_keyon(uint32_t choffs, uint32_t opoffs); + + // system-wide registers + uint32_t timer_a_value() const { return 0; } + uint32_t timer_b_value() const { return byte(0x03, 2, 6) | 0xc0; } // ??? + uint32_t csm() const { return 0; } + uint32_t reset_timer_b() const { return byte(0x03, 0, 1); } // ??? + uint32_t reset_timer_a() const { return 0; } + uint32_t enable_timer_b() const { return byte(0x03, 0, 1); } // ??? + uint32_t enable_timer_a() const { return 0; } + uint32_t load_timer_b() const { return byte(0x03, 0, 1); } // ??? + uint32_t load_timer_a() const { return 0; } + uint32_t lfo_enable() const { return byte(0x04, 3, 1) ^ 1; } + uint32_t lfo_rate() const { return byte(0x04, 0, 3); } + + // per-channel registers + uint32_t ch_output_any(uint32_t choffs) const { return byte(0x10, 6, 2, choffs); } + uint32_t ch_output_0(uint32_t choffs) const { return byte(0x10, 6, 1, choffs); } + uint32_t ch_output_1(uint32_t choffs) const { return byte(0x10, 7, 1, choffs); } + uint32_t ch_output_2(uint32_t choffs) const { return 0; } + uint32_t ch_output_3(uint32_t choffs) const { return 0; } + uint32_t ch_feedback(uint32_t choffs) const { return byte(0x10, 3, 3, choffs); } + uint32_t ch_algorithm(uint32_t choffs) const { return byte(0x10, 0, 3, choffs); } + uint32_t ch_reverb(uint32_t choffs) const { return byte(0x18, 7, 1, choffs); } + uint32_t ch_lfo_pm_sens(uint32_t choffs) const { return byte(0x18, 4, 3, choffs); } + uint32_t ch_lfo_am_sens(uint32_t choffs) const { return byte(0x18, 0, 2, choffs); } + uint32_t ch_block_freq_24(uint32_t choffs) const { return word(0x20, 0, 7, 0x30, 0, 8, choffs); } + uint32_t ch_block_freq_13(uint32_t choffs) const { return word(0x28, 0, 7, 0x38, 0, 8, choffs); } + + // per-operator registers + uint32_t op_detune(uint32_t opoffs) const { return byte(0x40, 0, 6, opoffs); } + uint32_t op_multiple(uint32_t opoffs) const { return byte(0x100, 0, 4, opoffs); } + uint32_t op_total_level(uint32_t opoffs) const { return byte(0x60, 0, 7, opoffs); } + uint32_t op_ksr(uint32_t opoffs) const { return byte(0x80, 6, 2, opoffs); } + uint32_t op_attack_rate(uint32_t opoffs) const { return byte(0x80, 0, 5, opoffs); } + uint32_t op_lfo_am_enable(uint32_t opoffs) const { return byte(0xa0, 7, 1, opoffs); } + uint32_t op_waveform(uint32_t opoffs) const { return byte(0xa0, 6, 1, opoffs); } + uint32_t op_decay_rate(uint32_t opoffs) const { return byte(0xa0, 0, 5, opoffs); } + uint32_t op_sustain_rate(uint32_t opoffs) const { return byte(0xc0, 0, 5, opoffs); } + uint32_t op_sustain_level(uint32_t opoffs) const { return byte(0xe0, 4, 4, opoffs); } + uint32_t op_release_rate(uint32_t opoffs) const { return byte(0xe0, 0, 4, opoffs); } + +protected: + // return a bitfield extracted from a byte + uint32_t byte(uint32_t offset, uint32_t start, uint32_t count, uint32_t extra_offset = 0) const + { + return bitfield(m_regdata[offset + extra_offset], start, count); + } + + // return a bitfield extracted from a pair of bytes, MSBs listed first + uint32_t word(uint32_t offset1, uint32_t start1, uint32_t count1, uint32_t offset2, uint32_t start2, uint32_t count2, uint32_t extra_offset = 0) const + { + return (byte(offset1, start1, count1, extra_offset) << count2) | byte(offset2, start2, count2, extra_offset); + } + + // internal state + uint32_t m_lfo_counter; // LFO counter + uint8_t m_lfo_am; // current LFO AM value + uint8_t m_regdata[REGISTERS]; // register data + uint16_t m_waveform[WAVEFORMS][WAVEFORM_LENGTH]; // waveforms +}; + + + +//********************************************************* +// IMPLEMENTATION CLASSES +//********************************************************* + +// ======================> ym3806 + +class ym3806 +{ +public: + using fm_engine = fm_engine_base; + static constexpr uint32_t OUTPUTS = fm_engine::OUTPUTS; + using output_data = fm_engine::output_data; + + // constructor + ym3806(ymfm_interface &intf); + + // reset + void reset(); + + // save/restore + void save_restore(ymfm_saved_state &state); + + // pass-through helpers + uint32_t sample_rate(uint32_t input_clock) const { return m_fm.sample_rate(input_clock); } + void invalidate_caches() { m_fm.invalidate_caches(); } + + // read access + uint8_t read_status(); + uint8_t read(uint32_t offset); + + // write access + void write_address(uint8_t data) { /* not supported; only direct writes */ } + void write_data(uint8_t data) { /* not supported; only direct writes */ } + void write(uint32_t offset, uint8_t data); + + // generate one sample of sound + void generate(output_data *output, uint32_t numsamples = 1); + +protected: + // internal state + fm_engine m_fm; // core FM engine +}; + + +// ======================> ym3533 + +class ym3533 : public ym3806 +{ +public: + // constructor + ym3533(ymfm_interface &intf) : + ym3806(intf) { } +}; + +} + + +#endif // YMFM_OPQ_H diff --git a/src/sound/ymfm/ymfm_opx.h b/src/sound/ymfm/ymfm_opx.h new file mode 100644 index 000000000..9f9bbdba7 --- /dev/null +++ b/src/sound/ymfm/ymfm_opx.h @@ -0,0 +1,290 @@ +// BSD 3-Clause License +// +// Copyright (c) 2021, Aaron Giles +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// 1. Redistributions of source code must retain the above copyright notice, this +// list of conditions and the following disclaimer. +// +// 2. Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// 3. Neither the name of the copyright holder nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#ifndef YMFM_OPX_H +#define YMFM_OPX_H + +#pragma once + +#include "ymfm.h" +#include "ymfm_fm.h" + +namespace ymfm +{ + +//********************************************************* +// REGISTER CLASSES +//********************************************************* + +// ======================> opx_registers + +// +// OPX register map: +// +// System-wide registers: +// +// Per-channel registers (channel in address bits 0-2) +// +// Per-operator registers (4 banks): +// 00-0F x------- Enable +// -xxxx--- EXT out +// -------x Key on +// 10-1F xxxxxxxx LFO frequency +// 20-2F xx------ AM sensitivity (0-3) +// --xxx--- PM sensitivity (0-7) +// ------xx LFO waveform (0=disable, 1=saw, 2= +// 30-3F -xxx---- Detune (0-7) +// ----xxxx Multiple (0-15) +// 40-4F -xxxxxxx Total level (0-127) +// 50-5F xxx----- Key scale (0-7) +// ---xxxxx Attack rate (0-31) +// 60-6F ---xxxxx Decay rate (0-31) +// 70-7F ---xxxxx Sustain rate (0-31) +// 80-8F xxxx---- Sustain level (0-15) +// ----xxxx Release rate (0-15) +// 90-9F xxxxxxxx Frequency number (low 8 bits) +// A0-AF xxxx---- Block (0-15) +// ----xxxx Frequency number (high 4 bits) +// B0-BF x------- Acc on +// -xxx---- Feedback level (0-7) +// -----xxx Waveform (0-7, 7=PCM) +// C0-CF ----xxxx Algorithm (0-15) +// D0-DF xxxx---- CH0 level (0-15) +// ----xxxx CH1 level (0-15) +// E0-EF xxxx---- CH2 level (0-15) +// ----xxxx CH3 level (0-15) +// + +class opx_registers : public fm_registers_base +{ + // LFO waveforms are 256 entries long + static constexpr uint32_t LFO_WAVEFORM_LENGTH = 256; + +public: + // constants + static constexpr uint32_t OUTPUTS = 8; + static constexpr uint32_t CHANNELS = 24; + static constexpr uint32_t ALL_CHANNELS = (1 << CHANNELS) - 1; + static constexpr uint32_t OPERATORS = CHANNELS * 2; + static constexpr uint32_t WAVEFORMS = 8; + static constexpr uint32_t REGISTERS = 0x800; + static constexpr uint32_t DEFAULT_PRESCALE = 8; + static constexpr uint32_t EG_CLOCK_DIVIDER = 2; + static constexpr uint32_t CSM_TRIGGER_MASK = ALL_CHANNELS; + static constexpr uint32_t REG_MODE = 0x14; + static constexpr uint8_t STATUS_TIMERA = 0x01; + static constexpr uint8_t STATUS_TIMERB = 0x02; + static constexpr uint8_t STATUS_BUSY = 0x80; + static constexpr uint8_t STATUS_IRQ = 0; + + // constructor + opz_registers(); + + // reset to initial state + void reset(); + + // save/restore + void save_restore(ymfm_saved_state &state); + + // map channel number to register offset + static constexpr uint32_t channel_offset(uint32_t chnum) + { + assert(chnum < CHANNELS); + return chnum; + } + + // map operator number to register offset + static constexpr uint32_t operator_offset(uint32_t opnum) + { + assert(opnum < OPERATORS); + return opnum; + } + + // return an array of operator indices for each channel + struct operator_mapping { uint32_t chan[CHANNELS]; }; + void operator_map(operator_mapping &dest) const; + + // handle writes to the register array + bool write(uint16_t index, uint8_t data, uint32_t &chan, uint32_t &opmask); + + // clock the noise and LFO, if present, returning LFO PM value + int32_t clock_noise_and_lfo(); + + // return the AM offset from LFO for the given channel + uint32_t lfo_am_offset(uint32_t choffs) const; + + // return the current noise state, gated by the noise clock + uint32_t noise_state() const { return m_noise_state; } + + // caching helpers + void cache_operator_data(uint32_t choffs, uint32_t opoffs, opdata_cache &cache); + + // compute the phase step, given a PM value + uint32_t compute_phase_step(uint32_t choffs, uint32_t opoffs, opdata_cache const &cache, int32_t lfo_raw_pm); + + // log a key-on event + std::string log_keyon(uint32_t choffs, uint32_t opoffs); + + // system-wide registers + uint32_t noise_frequency() const { return byte(0x0f, 0, 5); } + uint32_t noise_enable() const { return byte(0x0f, 7, 1); } + uint32_t timer_a_value() const { return word(0x10, 0, 8, 0x11, 0, 2); } + uint32_t timer_b_value() const { return byte(0x12, 0, 8); } + uint32_t csm() const { return byte(0x14, 7, 1); } + uint32_t reset_timer_b() const { return byte(0x14, 5, 1); } + uint32_t reset_timer_a() const { return byte(0x14, 4, 1); } + uint32_t enable_timer_b() const { return byte(0x14, 3, 1); } + uint32_t enable_timer_a() const { return byte(0x14, 2, 1); } + uint32_t load_timer_b() const { return byte(0x14, 1, 1); } + uint32_t load_timer_a() const { return byte(0x14, 0, 1); } + uint32_t lfo2_pm_depth() const { return byte(0x148, 0, 7); } // fake + uint32_t lfo2_rate() const { return byte(0x16, 0, 8); } + uint32_t lfo2_am_depth() const { return byte(0x17, 0, 7); } + uint32_t lfo_rate() const { return byte(0x18, 0, 8); } + uint32_t lfo_am_depth() const { return byte(0x19, 0, 7); } + uint32_t lfo_pm_depth() const { return byte(0x149, 0, 7); } // fake + uint32_t output_bits() const { return byte(0x1b, 6, 2); } + uint32_t lfo2_sync() const { return byte(0x1b, 5, 1); } + uint32_t lfo_sync() const { return byte(0x1b, 4, 1); } + uint32_t lfo2_waveform() const { return byte(0x1b, 2, 2); } + uint32_t lfo_waveform() const { return byte(0x1b, 0, 2); } + + // per-channel registers + uint32_t ch_volume(uint32_t choffs) const { return byte(0x00, 0, 8, choffs); } + uint32_t ch_output_any(uint32_t choffs) const { return byte(0x20, 7, 1, choffs) | byte(0x30, 0, 1, choffs); } + uint32_t ch_output_0(uint32_t choffs) const { return byte(0x30, 0, 1, choffs); } + uint32_t ch_output_1(uint32_t choffs) const { return byte(0x20, 7, 1, choffs) | byte(0x30, 0, 1, choffs); } + uint32_t ch_output_2(uint32_t choffs) const { return 0; } + uint32_t ch_output_3(uint32_t choffs) const { return 0; } + uint32_t ch_key_on(uint32_t choffs) const { return byte(0x20, 6, 1, choffs); } + uint32_t ch_feedback(uint32_t choffs) const { return byte(0x20, 3, 3, choffs); } + uint32_t ch_algorithm(uint32_t choffs) const { return byte(0x20, 0, 3, choffs); } + uint32_t ch_block_freq(uint32_t choffs) const { return word(0x28, 0, 7, 0x30, 2, 6, choffs); } + uint32_t ch_lfo_pm_sens(uint32_t choffs) const { return byte(0x38, 4, 3, choffs); } + uint32_t ch_lfo_am_sens(uint32_t choffs) const { return byte(0x38, 0, 2, choffs); } + uint32_t ch_lfo2_pm_sens(uint32_t choffs) const { return byte(0x140, 4, 3, choffs); } // fake + uint32_t ch_lfo2_am_sens(uint32_t choffs) const { return byte(0x140, 0, 2, choffs); } // fake + + // per-operator registers + uint32_t op_detune(uint32_t opoffs) const { return byte(0x40, 4, 3, opoffs); } + uint32_t op_multiple(uint32_t opoffs) const { return byte(0x40, 0, 4, opoffs); } + uint32_t op_fix_range(uint32_t opoffs) const { return byte(0x40, 4, 3, opoffs); } + uint32_t op_fix_frequency(uint32_t opoffs) const { return byte(0x40, 0, 4, opoffs); } + uint32_t op_waveform(uint32_t opoffs) const { return byte(0x100, 4, 3, opoffs); } // fake + uint32_t op_fine(uint32_t opoffs) const { return byte(0x100, 0, 4, opoffs); } // fake + uint32_t op_total_level(uint32_t opoffs) const { return byte(0x60, 0, 7, opoffs); } + uint32_t op_ksr(uint32_t opoffs) const { return byte(0x80, 6, 2, opoffs); } + uint32_t op_fix_mode(uint32_t opoffs) const { return byte(0x80, 5, 1, opoffs); } + uint32_t op_attack_rate(uint32_t opoffs) const { return byte(0x80, 0, 5, opoffs); } + uint32_t op_lfo_am_enable(uint32_t opoffs) const { return byte(0xa0, 7, 1, opoffs); } + uint32_t op_decay_rate(uint32_t opoffs) const { return byte(0xa0, 0, 5, opoffs); } + uint32_t op_detune2(uint32_t opoffs) const { return byte(0xc0, 6, 2, opoffs); } + uint32_t op_sustain_rate(uint32_t opoffs) const { return byte(0xc0, 0, 5, opoffs); } + uint32_t op_eg_shift(uint32_t opoffs) const { return byte(0x120, 6, 2, opoffs); } // fake + uint32_t op_reverb_rate(uint32_t opoffs) const { return byte(0x120, 0, 3, opoffs); } // fake + uint32_t op_sustain_level(uint32_t opoffs) const { return byte(0xe0, 4, 4, opoffs); } + uint32_t op_release_rate(uint32_t opoffs) const { return byte(0xe0, 0, 4, opoffs); } + +protected: + // return a bitfield extracted from a byte + uint32_t byte(uint32_t offset, uint32_t start, uint32_t count, uint32_t extra_offset = 0) const + { + return bitfield(m_regdata[offset + extra_offset], start, count); + } + + // return a bitfield extracted from a pair of bytes, MSBs listed first + uint32_t word(uint32_t offset1, uint32_t start1, uint32_t count1, uint32_t offset2, uint32_t start2, uint32_t count2, uint32_t extra_offset = 0) const + { + return (byte(offset1, start1, count1, extra_offset) << count2) | byte(offset2, start2, count2, extra_offset); + } + + // internal state + uint32_t m_lfo_counter[2]; // LFO counter + uint32_t m_noise_lfsr; // noise LFSR state + uint8_t m_noise_counter; // noise counter + uint8_t m_noise_state; // latched noise state + uint8_t m_noise_lfo; // latched LFO noise value + uint8_t m_lfo_am[2]; // current LFO AM value + uint8_t m_regdata[REGISTERS]; // register data + uint16_t m_phase_substep[OPERATORS]; // phase substep for fixed frequency + int16_t m_lfo_waveform[4][LFO_WAVEFORM_LENGTH]; // LFO waveforms; AM in low 8, PM in upper 8 + uint16_t m_waveform[WAVEFORMS][WAVEFORM_LENGTH]; // waveforms +}; + + + +//********************************************************* +// IMPLEMENTATION CLASSES +//********************************************************* + +// ======================> ym2414 + +class ym2414 +{ +public: + using fm_engine = fm_engine_base; + static constexpr uint32_t OUTPUTS = fm_engine::OUTPUTS; + using output_data = fm_engine::output_data; + + // constructor + ym2414(ymfm_interface &intf); + + // reset + void reset(); + + // save/restore + void save_restore(ymfm_saved_state &state); + + // pass-through helpers + uint32_t sample_rate(uint32_t input_clock) const { return m_fm.sample_rate(input_clock); } + void invalidate_caches() { m_fm.invalidate_caches(); } + + // read access + uint8_t read_status(); + uint8_t read(uint32_t offset); + + // write access + void write_address(uint8_t data); + void write_data(uint8_t data); + void write(uint32_t offset, uint8_t data); + + // generate one sample of sound + void generate(output_data *output, uint32_t numsamples = 1); + +protected: + // internal state + uint8_t m_address; // address register + fm_engine m_fm; // core FM engine +}; + +} + + +#endif // YMFM_OPZ_H diff --git a/src/sound/ymfm/ymfm_opz.cpp b/src/sound/ymfm/ymfm_opz.cpp new file mode 100644 index 000000000..a5ec912aa --- /dev/null +++ b/src/sound/ymfm/ymfm_opz.cpp @@ -0,0 +1,808 @@ +// BSD 3-Clause License +// +// Copyright (c) 2021, Aaron Giles +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// 1. Redistributions of source code must retain the above copyright notice, this +// list of conditions and the following disclaimer. +// +// 2. Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// 3. Neither the name of the copyright holder nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#include "ymfm_opz.h" +#include "ymfm_fm.ipp" + +#define TEMPORARY_DEBUG_PRINTS (0) + +// +// OPZ (aka YM2414) +// +// This chip is not officially documented as far as I know. What I have +// comes from this site: +// +// http://sr4.sakura.ne.jp/fmsound/opz.html +// +// and from reading the TX81Z operator manual, which describes how a number +// of these new features work. +// +// OPZ appears be bsaically OPM with a bunch of extra features. +// +// For starters, there are two LFO generators. I have presumed that they +// operate identically since identical parameters are offered for each. I +// have also presumed the effects are additive between them. The LFOs on +// the OPZ have an extra "sync" option which apparently causes the LFO to +// reset whenever a key on is received. +// +// At the channel level, there is an additional 8-bit volume control. This +// might work as an addition to total level, or some other way. Completely +// unknown, and unimplemented. +// +// At the operator level, there are a number of extra features. First, there +// are 8 different waveforms to choose from. These are different than the +// waveforms introduced in the OPL2 and later chips. +// +// Second, there is an additional "reverb" stage added to the envelope +// generator, which kicks in when the envelope reaches -18dB. It specifies +// a slower decay rate to produce a sort of faux reverb effect. +// +// The envelope generator also supports a 2-bit shift value, which can be +// used to reduce the effect of the envelope attenuation. +// +// OPZ supports a "fixed frequency" mode for each operator, with a 3-bit +// range and 4-bit frequency value, plus a 1-bit enable. Not sure how that +// works at all, so it's not implemented. +// +// There are also several mystery fields in the operators which I have no +// clue about: "fine" (4 bits), "eg_shift" (2 bits), and "rev" (3 bits). +// eg_shift is some kind of envelope generator effect, but how it works is +// unknown. +// +// Also, according to the site above, the panning controls are changed from +// OPM, with a "mono" bit and only one control bit for the right channel. +// Current implementation is just a guess. +// + +namespace ymfm +{ + +//********************************************************* +// OPZ REGISTERS +//********************************************************* + +//------------------------------------------------- +// opz_registers - constructor +//------------------------------------------------- + +opz_registers::opz_registers() : + m_lfo_counter{ 0, 0 }, + m_noise_lfsr(1), + m_noise_counter(0), + m_noise_state(0), + m_noise_lfo(0), + m_lfo_am{ 0, 0 } +{ + // create the waveforms + for (uint32_t index = 0; index < WAVEFORM_LENGTH; index++) + m_waveform[0][index] = abs_sin_attenuation(index) | (bitfield(index, 9) << 15); + + // we only have the diagrams to judge from, but suspecting waveform 1 (and + // derived waveforms) are sin^2, based on OPX description of similar wave- + // forms; since our sin table is logarithmic, this ends up just being + // 2*existing value + uint16_t zeroval = m_waveform[0][0]; + for (uint32_t index = 0; index < WAVEFORM_LENGTH; index++) + m_waveform[1][index] = std::min(2 * (m_waveform[0][index] & 0x7fff), zeroval) | (bitfield(index, 9) << 15); + + // remaining waveforms are just derivations of the 2 main ones + for (uint32_t index = 0; index < WAVEFORM_LENGTH; index++) + { + m_waveform[2][index] = bitfield(index, 9) ? zeroval : m_waveform[0][index]; + m_waveform[3][index] = bitfield(index, 9) ? zeroval : m_waveform[1][index]; + m_waveform[4][index] = bitfield(index, 9) ? zeroval : m_waveform[0][index * 2]; + m_waveform[5][index] = bitfield(index, 9) ? zeroval : m_waveform[1][index * 2]; + m_waveform[6][index] = bitfield(index, 9) ? zeroval : m_waveform[0][(index * 2) & 0x1ff]; + m_waveform[7][index] = bitfield(index, 9) ? zeroval : m_waveform[1][(index * 2) & 0x1ff]; + } + + // create the LFO waveforms; AM in the low 8 bits, PM in the upper 8 + // waveforms are adjusted to match the pictures in the application manual + for (uint32_t index = 0; index < LFO_WAVEFORM_LENGTH; index++) + { + // waveform 0 is a sawtooth + uint8_t am = index ^ 0xff; + int8_t pm = int8_t(index); + m_lfo_waveform[0][index] = am | (pm << 8); + + // waveform 1 is a square wave + am = bitfield(index, 7) ? 0 : 0xff; + pm = int8_t(am ^ 0x80); + m_lfo_waveform[1][index] = am | (pm << 8); + + // waveform 2 is a triangle wave + am = bitfield(index, 7) ? (index << 1) : ((index ^ 0xff) << 1); + pm = int8_t(bitfield(index, 6) ? am : ~am); + m_lfo_waveform[2][index] = am | (pm << 8); + + // waveform 3 is noise; it is filled in dynamically + } +} + + +//------------------------------------------------- +// reset - reset to initial state +//------------------------------------------------- + +void opz_registers::reset() +{ + std::fill_n(&m_regdata[0], REGISTERS, 0); + + // enable output on both channels by default + m_regdata[0x30] = m_regdata[0x31] = m_regdata[0x32] = m_regdata[0x33] = 0x01; + m_regdata[0x34] = m_regdata[0x35] = m_regdata[0x36] = m_regdata[0x37] = 0x01; +} + + +//------------------------------------------------- +// save_restore - save or restore the data +//------------------------------------------------- + +void opz_registers::save_restore(ymfm_saved_state &state) +{ + state.save_restore(m_lfo_counter); + state.save_restore(m_lfo_am); + state.save_restore(m_noise_lfsr); + state.save_restore(m_noise_counter); + state.save_restore(m_noise_state); + state.save_restore(m_noise_lfo); + state.save_restore(m_regdata); + state.save_restore(m_phase_substep); +} + + +//------------------------------------------------- +// operator_map - return an array of operator +// indices for each channel; for OPZ this is fixed +//------------------------------------------------- + +void opz_registers::operator_map(operator_mapping &dest) const +{ + // Note that the channel index order is 0,2,1,3, so we bitswap the index. + // + // This is because the order in the map is: + // carrier 1, carrier 2, modulator 1, modulator 2 + // + // But when wiring up the connections, the more natural order is: + // carrier 1, modulator 1, carrier 2, modulator 2 + static const operator_mapping s_fixed_map = + { { + operator_list( 0, 16, 8, 24 ), // Channel 0 operators + operator_list( 1, 17, 9, 25 ), // Channel 1 operators + operator_list( 2, 18, 10, 26 ), // Channel 2 operators + operator_list( 3, 19, 11, 27 ), // Channel 3 operators + operator_list( 4, 20, 12, 28 ), // Channel 4 operators + operator_list( 5, 21, 13, 29 ), // Channel 5 operators + operator_list( 6, 22, 14, 30 ), // Channel 6 operators + operator_list( 7, 23, 15, 31 ), // Channel 7 operators + } }; + dest = s_fixed_map; +} + + +//------------------------------------------------- +// write - handle writes to the register array +//------------------------------------------------- + +bool opz_registers::write(uint16_t index, uint8_t data, uint32_t &channel, uint32_t &opmask) +{ + assert(index < REGISTERS); + + // special mappings: + // 0x16 -> 0x188 if bit 7 is set + // 0x19 -> 0x189 if bit 7 is set + // 0x38..0x3F -> 0x180..0x187 if bit 7 is set + // 0x40..0x5F -> 0x100..0x11F if bit 7 is set + // 0xC0..0xDF -> 0x120..0x13F if bit 5 is set + if (index == 0x17 && bitfield(data, 7) != 0) + m_regdata[0x188] = data; + else if (index == 0x19 && bitfield(data, 7) != 0) + m_regdata[0x189] = data; + else if ((index & 0xf8) == 0x38 && bitfield(data, 7) != 0) + m_regdata[0x180 + (index & 7)] = data; + else if ((index & 0xe0) == 0x40 && bitfield(data, 7) != 0) + m_regdata[0x100 + (index & 0x1f)] = data; + else if ((index & 0xe0) == 0xc0 && bitfield(data, 5) != 0) + m_regdata[0x120 + (index & 0x1f)] = data; + else if (index < 0x100) + m_regdata[index] = data; + + // preset writes restore some values from a preset memory; not sure + // how this really works but the TX81Z will overwrite the sustain level/ + // release rate register and the envelope shift/reverb rate register to + // dampen sound, then write the preset number to register 8 to restore them + if (index == 0x08) + { + int chan = bitfield(data, 0, 3); + if (TEMPORARY_DEBUG_PRINTS) + printf("Loading preset %d\n", chan); + m_regdata[0xe0 + chan + 0] = m_regdata[0x140 + chan + 0]; + m_regdata[0xe0 + chan + 8] = m_regdata[0x140 + chan + 8]; + m_regdata[0xe0 + chan + 16] = m_regdata[0x140 + chan + 16]; + m_regdata[0xe0 + chan + 24] = m_regdata[0x140 + chan + 24]; + m_regdata[0x120 + chan + 0] = m_regdata[0x160 + chan + 0]; + m_regdata[0x120 + chan + 8] = m_regdata[0x160 + chan + 8]; + m_regdata[0x120 + chan + 16] = m_regdata[0x160 + chan + 16]; + m_regdata[0x120 + chan + 24] = m_regdata[0x160 + chan + 24]; + } + + // store the presets under some unknown condition; the pattern of writes + // when setting a new preset is: + // + // 08 (0-7), 80-9F, A0-BF, C0-DF, C0-DF (alt), 20-27, 40-5F, 40-5F (alt), + // C0-DF (alt -- again?), 38-3F, 1B, 18, E0-FF + // + // So it writes 0-7 to 08 to either reset all presets or to indicate + // that we're going to be loading them. Immediately after all the writes + // above, the very next write will be temporary values to blow away the + // values loaded into E0-FF, so somehow it also knows that anything after + // that point is not part of the preset. + // + // For now, try using the 40-5F (alt) writes as flags that presets are + // being loaded until the E0-FF writes happen. + bool is_setting_preset = (bitfield(m_regdata[0x100 + (index & 0x1f)], 7) != 0); + if (is_setting_preset) + { + if ((index & 0xe0) == 0xe0) + { + m_regdata[0x140 + (index & 0x1f)] = data; + m_regdata[0x100 + (index & 0x1f)] &= 0x7f; + } + else if ((index & 0xe0) == 0xc0 && bitfield(data, 5) != 0) + m_regdata[0x160 + (index & 0x1f)] = data; + } + + // handle writes to the key on index + if ((index & 0xf8) == 0x20 && bitfield(index, 0, 3) == bitfield(m_regdata[0x08], 0, 3)) + { + channel = bitfield(index, 0, 3); + opmask = ch_key_on(channel) ? 0xf : 0; + + // according to the TX81Z manual, the sync option causes the LFOs + // to reset at each note on + if (opmask != 0) + { + if (lfo_sync()) + m_lfo_counter[0] = 0; + if (lfo2_sync()) + m_lfo_counter[1] = 0; + } + return true; + } + return false; +} + + +//------------------------------------------------- +// clock_noise_and_lfo - clock the noise and LFO, +// handling clock division, depth, and waveform +// computations +//------------------------------------------------- + +int32_t opz_registers::clock_noise_and_lfo() +{ + // base noise frequency is measured at 2x 1/2 FM frequency; this + // means each tick counts as two steps against the noise counter + uint32_t freq = noise_frequency(); + for (int rep = 0; rep < 2; rep++) + { + // evidence seems to suggest the LFSR is clocked continually and just + // sampled at the noise frequency for output purposes; note that the + // low 8 bits are the most recent 8 bits of history while bits 8-24 + // contain the 17 bit LFSR state + m_noise_lfsr <<= 1; + m_noise_lfsr |= bitfield(m_noise_lfsr, 17) ^ bitfield(m_noise_lfsr, 14) ^ 1; + + // compare against the frequency and latch when we exceed it + if (m_noise_counter++ >= freq) + { + m_noise_counter = 0; + m_noise_state = bitfield(m_noise_lfsr, 17); + } + } + + // treat the rate as a 4.4 floating-point step value with implied + // leading 1; this matches exactly the frequencies in the application + // manual, though it might not be implemented exactly this way on chip + uint32_t rate0 = lfo_rate(); + uint32_t rate1 = lfo2_rate(); + m_lfo_counter[0] += (0x10 | bitfield(rate0, 0, 4)) << bitfield(rate0, 4, 4); + m_lfo_counter[1] += (0x10 | bitfield(rate1, 0, 4)) << bitfield(rate1, 4, 4); + uint32_t lfo0 = bitfield(m_lfo_counter[0], 22, 8); + uint32_t lfo1 = bitfield(m_lfo_counter[1], 22, 8); + + // fill in the noise entry 1 ahead of our current position; this + // ensures the current value remains stable for a full LFO clock + // and effectively latches the running value when the LFO advances + uint32_t lfo_noise = bitfield(m_noise_lfsr, 17, 8); + m_lfo_waveform[3][(lfo0 + 1) & 0xff] = lfo_noise | (lfo_noise << 8); + m_lfo_waveform[3][(lfo1 + 1) & 0xff] = lfo_noise | (lfo_noise << 8); + + // fetch the AM/PM values based on the waveform; AM is unsigned and + // encoded in the low 8 bits, while PM signed and encoded in the upper + // 8 bits + int32_t ampm0 = m_lfo_waveform[lfo_waveform()][lfo0]; + int32_t ampm1 = m_lfo_waveform[lfo2_waveform()][lfo1]; + + // apply depth to the AM values and store for later + m_lfo_am[0] = ((ampm0 & 0xff) * lfo_am_depth()) >> 7; + m_lfo_am[1] = ((ampm1 & 0xff) * lfo2_am_depth()) >> 7; + + // apply depth to the PM values and return them combined into two + int32_t pm0 = ((ampm0 >> 8) * int32_t(lfo_pm_depth())) >> 7; + int32_t pm1 = ((ampm1 >> 8) * int32_t(lfo2_pm_depth())) >> 7; + return (pm0 & 0xff) | (pm1 << 8); +} + + +//------------------------------------------------- +// lfo_am_offset - return the AM offset from LFO +// for the given channel +//------------------------------------------------- + +uint32_t opz_registers::lfo_am_offset(uint32_t choffs) const +{ + // not sure how this works for real, but just adding the two + // AM LFOs together + uint32_t result = 0; + + // shift value for AM sensitivity is [*, 0, 1, 2], + // mapping to values of [0, 23.9, 47.8, and 95.6dB] + uint32_t am_sensitivity = ch_lfo_am_sens(choffs); + if (am_sensitivity != 0) + result = m_lfo_am[0] << (am_sensitivity - 1); + + // QUESTION: see OPN note below for the dB range mapping; it applies + // here as well + + // raw LFO AM value on OPZ is 0-FF, which is already a factor of 2 + // larger than the OPN below, putting our staring point at 2x theirs; + // this works out since our minimum is 2x their maximum + uint32_t am_sensitivity2 = ch_lfo2_am_sens(choffs); + if (am_sensitivity2 != 0) + result += m_lfo_am[1] << (am_sensitivity2 - 1); + + return result; +} + + +//------------------------------------------------- +// cache_operator_data - fill the operator cache +// with prefetched data +//------------------------------------------------- + +void opz_registers::cache_operator_data(uint32_t choffs, uint32_t opoffs, opdata_cache &cache) +{ + // TODO: how does fixed frequency mode work? appears to be enabled by + // op_fix_mode(), and controlled by op_fix_range(), op_fix_frequency() + + // TODO: what is op_rev()? + + // set up the easy stuff + cache.waveform = &m_waveform[op_waveform(opoffs)][0]; + + // get frequency from the channel + uint32_t block_freq = cache.block_freq = ch_block_freq(choffs); + + // compute the keycode: block_freq is: + // + // BBBCCCCFFFFFF + // ^^^^^ + // + // the 5-bit keycode is just the top 5 bits (block + top 2 bits + // of the key code) + uint32_t keycode = bitfield(block_freq, 8, 5); + + // detune adjustment + cache.detune = detune_adjustment(op_detune(opoffs), keycode); + + // multiple value, as an x.4 value (0 means 0.5) + // the "fine" control provides the fractional bits + cache.multiple = op_multiple(opoffs) << 4; + if (cache.multiple == 0) + cache.multiple = 0x08; + cache.multiple |= op_fine(opoffs); + + // phase step, or PHASE_STEP_DYNAMIC if PM is active; this depends on + // block_freq, detune, and multiple, so compute it after we've done those; + // note that fix frequency mode is also treated as dynamic + if (!op_fix_mode(opoffs) && (lfo_pm_depth() == 0 || ch_lfo_pm_sens(choffs) == 0) && (lfo2_pm_depth() == 0 || ch_lfo2_pm_sens(choffs) == 0)) + cache.phase_step = compute_phase_step(choffs, opoffs, cache, 0); + else + cache.phase_step = opdata_cache::PHASE_STEP_DYNAMIC; + + // total level, scaled by 8 + // TODO: how does ch_volume() fit into this? + cache.total_level = op_total_level(opoffs) << 3; + + // 4-bit sustain level, but 15 means 31 so effectively 5 bits + cache.eg_sustain = op_sustain_level(opoffs); + cache.eg_sustain |= (cache.eg_sustain + 1) & 0x10; + cache.eg_sustain <<= 5; + + // determine KSR adjustment for enevlope rates + uint32_t ksrval = keycode >> (op_ksr(opoffs) ^ 3); + cache.eg_rate[EG_ATTACK] = effective_rate(op_attack_rate(opoffs) * 2, ksrval); + cache.eg_rate[EG_DECAY] = effective_rate(op_decay_rate(opoffs) * 2, ksrval); + cache.eg_rate[EG_SUSTAIN] = effective_rate(op_sustain_rate(opoffs) * 2, ksrval); + cache.eg_rate[EG_RELEASE] = effective_rate(op_release_rate(opoffs) * 4 + 2, ksrval); + cache.eg_rate[EG_REVERB] = cache.eg_rate[EG_RELEASE]; + uint32_t reverb = op_reverb_rate(opoffs); + if (reverb != 0) + cache.eg_rate[EG_REVERB] = std::min(effective_rate(reverb * 4 + 2, ksrval), cache.eg_rate[EG_REVERB]); + + // set the envelope shift; TX81Z manual says operator 1 shift is fixed at "off" + cache.eg_shift = ((opoffs & 0x18) == 0) ? 0 : op_eg_shift(opoffs); +} + + +//------------------------------------------------- +// compute_phase_step - compute the phase step +//------------------------------------------------- + +uint32_t opz_registers::compute_phase_step(uint32_t choffs, uint32_t opoffs, opdata_cache const &cache, int32_t lfo_raw_pm) +{ + // OPZ has a fixed frequency mode; it is unclear whether the + // detune and multiple parameters affect things + + uint32_t phase_step; + if (op_fix_mode(opoffs)) + { + // the baseline frequency in hz comes from the fix frequency and fine + // registers, which can specify values 8-255Hz in 1Hz increments; that + // value is then shifted up by the 3-bit range + uint32_t freq = op_fix_frequency(opoffs) << 4; + if (freq == 0) + freq = 8; + freq |= op_fine(opoffs); + freq <<= op_fix_range(opoffs); + + // there is not enough resolution in the plain phase step to track the + // full range of frequencies, so we keep a per-operator sub step with an + // additional 12 bits of resolution; this calculation gives us, for + // example, a frequency of 8.0009Hz when 8Hz is requested + uint32_t substep = m_phase_substep[opoffs]; + substep += 75 * freq; + phase_step = substep >> 12; + m_phase_substep[opoffs] = substep & 0xfff; + + // detune/multiple occupy the same space as fix_range/fix_frequency so + // don't apply them in addition + return phase_step; + } + else + { + // start with coarse detune delta; table uses cents value from + // manual, converted into 1/64ths + static const int16_t s_detune2_delta[4] = { 0, (600*64+50)/100, (781*64+50)/100, (950*64+50)/100 }; + int32_t delta = s_detune2_delta[op_detune2(opoffs)]; + + // add in the PM deltas + uint32_t pm_sensitivity = ch_lfo_pm_sens(choffs); + if (pm_sensitivity != 0) + { + // raw PM value is -127..128 which is +/- 200 cents + // manual gives these magnitudes in cents: + // 0, +/-5, +/-10, +/-20, +/-50, +/-100, +/-400, +/-700 + // this roughly corresponds to shifting the 200-cent value: + // 0 >> 5, >> 4, >> 3, >> 2, >> 1, << 1, << 2 + if (pm_sensitivity < 6) + delta += int8_t(lfo_raw_pm) >> (6 - pm_sensitivity); + else + delta += int8_t(lfo_raw_pm) << (pm_sensitivity - 5); + } + uint32_t pm_sensitivity2 = ch_lfo2_pm_sens(choffs); + if (pm_sensitivity2 != 0) + { + // raw PM value is -127..128 which is +/- 200 cents + // manual gives these magnitudes in cents: + // 0, +/-5, +/-10, +/-20, +/-50, +/-100, +/-400, +/-700 + // this roughly corresponds to shifting the 200-cent value: + // 0 >> 5, >> 4, >> 3, >> 2, >> 1, << 1, << 2 + if (pm_sensitivity2 < 6) + delta += int8_t(lfo_raw_pm >> 8) >> (6 - pm_sensitivity2); + else + delta += int8_t(lfo_raw_pm >> 8) << (pm_sensitivity2 - 5); + } + + // apply delta and convert to a frequency number; this translation is + // the same as OPM so just re-use that helper + phase_step = opm_key_code_to_phase_step(cache.block_freq, delta); + + // apply detune based on the keycode + phase_step += cache.detune; + + // apply frequency multiplier (which is cached as an x.4 value) + return (phase_step * cache.multiple) >> 4; + } +} + + +//------------------------------------------------- +// log_keyon - log a key-on event +//------------------------------------------------- + +std::string opz_registers::log_keyon(uint32_t choffs, uint32_t opoffs) +{ + uint32_t chnum = choffs; + uint32_t opnum = opoffs; + + char buffer[256]; + char *end = &buffer[0]; + + end += snprintf(end, SNPRINTF_BUFFER_SIZE_CALC, "%u.%02u", chnum, opnum); + + if (op_fix_mode(opoffs)) + end += snprintf(end, SNPRINTF_BUFFER_SIZE_CALC, " fixfreq=%X fine=%X shift=%X", op_fix_frequency(opoffs), op_fine(opoffs), op_fix_range(opoffs)); + else + end += snprintf(end, SNPRINTF_BUFFER_SIZE_CALC, " freq=%04X dt2=%u fine=%X", ch_block_freq(choffs), op_detune2(opoffs), op_fine(opoffs)); + + end += snprintf(end, SNPRINTF_BUFFER_SIZE_CALC, " dt=%u fb=%u alg=%X mul=%X tl=%02X ksr=%u adsr=%02X/%02X/%02X/%X sl=%X out=%c%c", + op_detune(opoffs), + ch_feedback(choffs), + ch_algorithm(choffs), + op_multiple(opoffs), + op_total_level(opoffs), + op_ksr(opoffs), + op_attack_rate(opoffs), + op_decay_rate(opoffs), + op_sustain_rate(opoffs), + op_release_rate(opoffs), + op_sustain_level(opoffs), + ch_output_0(choffs) ? 'L' : '-', + ch_output_1(choffs) ? 'R' : '-'); + + if (op_eg_shift(opoffs) != 0) + end += snprintf(end, SNPRINTF_BUFFER_SIZE_CALC, " egshift=%u", op_eg_shift(opoffs)); + + bool am = (lfo_am_depth() != 0 && ch_lfo_am_sens(choffs) != 0 && op_lfo_am_enable(opoffs) != 0); + if (am) + end += snprintf(end, SNPRINTF_BUFFER_SIZE_CALC, " am=%u/%02X", ch_lfo_am_sens(choffs), lfo_am_depth()); + bool pm = (lfo_pm_depth() != 0 && ch_lfo_pm_sens(choffs) != 0); + if (pm) + end += snprintf(end, SNPRINTF_BUFFER_SIZE_CALC, " pm=%u/%02X", ch_lfo_pm_sens(choffs), lfo_pm_depth()); + if (am || pm) + end += snprintf(end, SNPRINTF_BUFFER_SIZE_CALC, " lfo=%02X/%c", lfo_rate(), "WQTN"[lfo_waveform()]); + + bool am2 = (lfo2_am_depth() != 0 && ch_lfo2_am_sens(choffs) != 0 && op_lfo_am_enable(opoffs) != 0); + if (am2) + end += snprintf(end, SNPRINTF_BUFFER_SIZE_CALC, " am2=%u/%02X", ch_lfo2_am_sens(choffs), lfo2_am_depth()); + bool pm2 = (lfo2_pm_depth() != 0 && ch_lfo2_pm_sens(choffs) != 0); + if (pm2) + end += snprintf(end, SNPRINTF_BUFFER_SIZE_CALC, " pm2=%u/%02X", ch_lfo2_pm_sens(choffs), lfo2_pm_depth()); + if (am2 || pm2) + end += snprintf(end, SNPRINTF_BUFFER_SIZE_CALC, " lfo2=%02X/%c", lfo2_rate(), "WQTN"[lfo2_waveform()]); + + if (op_reverb_rate(opoffs) != 0) + end += snprintf(end, SNPRINTF_BUFFER_SIZE_CALC, " rev=%u", op_reverb_rate(opoffs)); + if (op_waveform(opoffs) != 0) + end += snprintf(end, SNPRINTF_BUFFER_SIZE_CALC, " wf=%u", op_waveform(opoffs)); + if (noise_enable() && opoffs == 31) + end += snprintf(end, SNPRINTF_BUFFER_SIZE_CALC, " noise=1"); + + return buffer; +} + + + +//********************************************************* +// YM2414 +//********************************************************* + +//------------------------------------------------- +// ym2414 - constructor +//------------------------------------------------- + +ym2414::ym2414(ymfm_interface &intf) : + m_address(0), + m_fm(intf) +{ +} + + +//------------------------------------------------- +// reset - reset the system +//------------------------------------------------- + +void ym2414::reset() +{ + // reset the engines + m_fm.reset(); +} + + +//------------------------------------------------- +// save_restore - save or restore the data +//------------------------------------------------- + +void ym2414::save_restore(ymfm_saved_state &state) +{ + m_fm.save_restore(state); + state.save_restore(m_address); +} + + +//------------------------------------------------- +// read_status - read the status register +//------------------------------------------------- + +uint8_t ym2414::read_status() +{ + uint8_t result = m_fm.status(); + if (m_fm.intf().ymfm_is_busy()) + result |= fm_engine::STATUS_BUSY; + return result; +} + + +//------------------------------------------------- +// read - handle a read from the device +//------------------------------------------------- + +uint8_t ym2414::read(uint32_t offset) +{ + uint8_t result = 0xff; + switch (offset & 1) + { + case 0: // data port (unused) + debug::log_unexpected_read_write("Unexpected read from YM2414 offset %d\n", offset & 3); + break; + + case 1: // status port, YM2203 compatible + result = read_status(); + break; + } + return result; +} + + +//------------------------------------------------- +// write_address - handle a write to the address +// register +//------------------------------------------------- + +void ym2414::write_address(uint8_t data) +{ + // just set the address + m_address = data; +} + + +//------------------------------------------------- +// write - handle a write to the register +// interface +//------------------------------------------------- + +void ym2414::write_data(uint8_t data) +{ + // write the FM register + m_fm.write(m_address, data); + if (TEMPORARY_DEBUG_PRINTS) + { + switch (m_address & 0xe0) + { + case 0x00: + printf("CTL %02X = %02X\n", m_address, data); + break; + + case 0x20: + switch (m_address & 0xf8) + { + case 0x20: printf("R/FBL/ALG %d = %02X\n", m_address & 7, data); break; + case 0x28: printf("KC %d = %02X\n", m_address & 7, data); break; + case 0x30: printf("KF/M %d = %02X\n", m_address & 7, data); break; + case 0x38: printf("PMS/AMS %d = %02X\n", m_address & 7, data); break; + } + break; + + case 0x40: + if (bitfield(data, 7) == 0) + printf("DT1/MUL %d.%d = %02X\n", m_address & 7, (m_address >> 3) & 3, data); + else + printf("OW/FINE %d.%d = %02X\n", m_address & 7, (m_address >> 3) & 3, data); + break; + + case 0x60: + printf("TL %d.%d = %02X\n", m_address & 7, (m_address >> 3) & 3, data); + break; + + case 0x80: + printf("KRS/FIX/AR %d.%d = %02X\n", m_address & 7, (m_address >> 3) & 3, data); + break; + + case 0xa0: + printf("A/D1R %d.%d = %02X\n", m_address & 7, (m_address >> 3) & 3, data); + break; + + case 0xc0: + if (bitfield(data, 5) == 0) + printf("DT2/D2R %d.%d = %02X\n", m_address & 7, (m_address >> 3) & 3, data); + else + printf("EGS/REV %d.%d = %02X\n", m_address & 7, (m_address >> 3) & 3, data); + break; + + case 0xe0: + printf("D1L/RR %d.%d = %02X\n", m_address & 7, (m_address >> 3) & 3, data); + break; + } + } + + // special cases + if (m_address == 0x1b) + { + // writes to register 0x1B send the upper 2 bits to the output lines + m_fm.intf().ymfm_external_write(ACCESS_IO, 0, data >> 6); + } + + // mark busy for a bit + m_fm.intf().ymfm_set_busy_end(32 * m_fm.clock_prescale()); +} + + +//------------------------------------------------- +// write - handle a write to the register +// interface +//------------------------------------------------- + +void ym2414::write(uint32_t offset, uint8_t data) +{ + switch (offset & 1) + { + case 0: // address port + write_address(data); + break; + + case 1: // data port + write_data(data); + break; + } +} + + +//------------------------------------------------- +// generate - generate one sample of sound +//------------------------------------------------- + +void ym2414::generate(output_data *output, uint32_t numsamples) +{ + for (uint32_t samp = 0; samp < numsamples; samp++, output++) + { + // clock the system + m_fm.clock(fm_engine::ALL_CHANNELS); + + // update the FM content; YM2414 is full 14-bit with no intermediate clipping + m_fm.output(output->clear(), 0, 32767, fm_engine::ALL_CHANNELS); + + // unsure about YM2414 outputs; assume it is like YM2151 + output->roundtrip_fp(); + } +} + +} diff --git a/src/sound/ymfm/ymfm_opz.h b/src/sound/ymfm/ymfm_opz.h new file mode 100644 index 000000000..997ba32f9 --- /dev/null +++ b/src/sound/ymfm/ymfm_opz.h @@ -0,0 +1,332 @@ +// BSD 3-Clause License +// +// Copyright (c) 2021, Aaron Giles +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// 1. Redistributions of source code must retain the above copyright notice, this +// list of conditions and the following disclaimer. +// +// 2. Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// 3. Neither the name of the copyright holder nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#ifndef YMFM_OPZ_H +#define YMFM_OPZ_H + +#pragma once + +#include "ymfm.h" +#include "ymfm_fm.h" + +namespace ymfm +{ + +//********************************************************* +// REGISTER CLASSES +//********************************************************* + +// ======================> opz_registers + +// +// OPZ register map: +// +// System-wide registers: +// 08 -----xxx Load preset (not sure how it gets saved) +// 0F x------- Noise enable +// ---xxxxx Noise frequency +// 10 xxxxxxxx Timer A value (upper 8 bits) +// 11 ------xx Timer A value (lower 2 bits) +// 12 xxxxxxxx Timer B value +// 14 x------- CSM mode +// --x----- Reset timer B +// ---x---- Reset timer A +// ----x--- Enable timer B +// -----x-- Enable timer A +// ------x- Load timer B +// -------x Load timer A +// 16 xxxxxxxx LFO #2 frequency +// 17 0xxxxxxx AM LFO #2 depth +// 1xxxxxxx PM LFO #2 depth +// 18 xxxxxxxx LFO frequency +// 19 0xxxxxxx AM LFO depth +// 1xxxxxxx PM LFO depth +// 1B xx------ CT (2 output data lines) +// --x----- LFO #2 sync +// ---x---- LFO sync +// ----xx-- LFO #2 waveform +// ------xx LFO waveform +// +// Per-channel registers (channel in address bits 0-2) +// 00-07 xxxxxxxx Channel volume +// 20-27 x------- Pan right +// -x------ Key on (0)/off(1) +// --xxx--- Feedback level for operator 1 (0-7) +// -----xxx Operator connection algorithm (0-7) +// 28-2F -xxxxxxx Key code +// 30-37 xxxxxx-- Key fraction +// -------x Mono? mode +// 38-3F 0xxx---- LFO PM sensitivity +// -----0xx LFO AM shift +// 1xxx---- LFO #2 PM sensitivity +// -----1xx LFO #2 AM shift +// +// Per-operator registers (channel in address bits 0-2, operator in bits 3-4) +// 40-5F 0xxx---- Detune value (0-7) +// 0---xxxx Multiple value (0-15) +// 0xxx---- Fix range (0-15) +// 0---xxxx Fix frequency (0-15) +// 1xxx---- Oscillator waveform (0-7) +// 1---xxxx Fine? (0-15) +// 60-7F -xxxxxxx Total level (0-127) +// 80-9F xx------ Key scale rate (0-3) +// --x----- Fix frequency mode +// ---xxxxx Attack rate (0-31) +// A0-BF x------- LFO AM enable +// ---xxxxx Decay rate (0-31) +// C0-DF xx0----- Detune 2 value (0-3) +// --0xxxxx Sustain rate (0-31) +// xx1----- Envelope generator shift? (0-3) +// --1--xxx Rev? (0-7) +// E0-FF xxxx---- Sustain level (0-15) +// ----xxxx Release rate (0-15) +// +// Internal (fake) registers: +// 100-11F -xxx---- Oscillator waveform (0-7) +// ----xxxx Fine? (0-15) +// 120-13F xx------ Envelope generator shift (0-3) +// -----xxx Reverb rate (0-7) +// 140-15F xxxx---- Preset sustain level (0-15) +// ----xxxx Preset release rate (0-15) +// 160-17F xx------ Envelope generator shift (0-3) +// -----xxx Reverb rate (0-7) +// 180-187 -xxx---- LFO #2 PM sensitivity +// ---- xxx LFO #2 AM shift +// 188 -xxxxxxx LFO #2 PM depth +// 189 -xxxxxxx LFO PM depth +// + +class opz_registers : public fm_registers_base +{ + // LFO waveforms are 256 entries long + static constexpr uint32_t LFO_WAVEFORM_LENGTH = 256; + +public: + // constants + static constexpr uint32_t OUTPUTS = 2; + static constexpr uint32_t CHANNELS = 8; + static constexpr uint32_t ALL_CHANNELS = (1 << CHANNELS) - 1; + static constexpr uint32_t OPERATORS = CHANNELS * 4; + static constexpr uint32_t WAVEFORMS = 8; + static constexpr uint32_t REGISTERS = 0x190; + static constexpr uint32_t DEFAULT_PRESCALE = 2; + static constexpr uint32_t EG_CLOCK_DIVIDER = 3; + static constexpr bool EG_HAS_REVERB = true; + static constexpr uint32_t CSM_TRIGGER_MASK = ALL_CHANNELS; + static constexpr uint32_t REG_MODE = 0x14; + static constexpr uint8_t STATUS_TIMERA = 0x01; + static constexpr uint8_t STATUS_TIMERB = 0x02; + static constexpr uint8_t STATUS_BUSY = 0x80; + static constexpr uint8_t STATUS_IRQ = 0; + + // constructor + opz_registers(); + + // reset to initial state + void reset(); + + // save/restore + void save_restore(ymfm_saved_state &state); + + // map channel number to register offset + static constexpr uint32_t channel_offset(uint32_t chnum) + { + assert(chnum < CHANNELS); + return chnum; + } + + // map operator number to register offset + static constexpr uint32_t operator_offset(uint32_t opnum) + { + assert(opnum < OPERATORS); + return opnum; + } + + // return an array of operator indices for each channel + struct operator_mapping { uint32_t chan[CHANNELS]; }; + void operator_map(operator_mapping &dest) const; + + // handle writes to the register array + bool write(uint16_t index, uint8_t data, uint32_t &chan, uint32_t &opmask); + + // clock the noise and LFO, if present, returning LFO PM value + int32_t clock_noise_and_lfo(); + + // return the AM offset from LFO for the given channel + uint32_t lfo_am_offset(uint32_t choffs) const; + + // return the current noise state, gated by the noise clock + uint32_t noise_state() const { return m_noise_state; } + + // caching helpers + void cache_operator_data(uint32_t choffs, uint32_t opoffs, opdata_cache &cache); + + // compute the phase step, given a PM value + uint32_t compute_phase_step(uint32_t choffs, uint32_t opoffs, opdata_cache const &cache, int32_t lfo_raw_pm); + + // log a key-on event + std::string log_keyon(uint32_t choffs, uint32_t opoffs); + + // system-wide registers + uint32_t noise_frequency() const { return byte(0x0f, 0, 5); } + uint32_t noise_enable() const { return byte(0x0f, 7, 1); } + uint32_t timer_a_value() const { return word(0x10, 0, 8, 0x11, 0, 2); } + uint32_t timer_b_value() const { return byte(0x12, 0, 8); } + uint32_t csm() const { return byte(0x14, 7, 1); } + uint32_t reset_timer_b() const { return byte(0x14, 5, 1); } + uint32_t reset_timer_a() const { return byte(0x14, 4, 1); } + uint32_t enable_timer_b() const { return byte(0x14, 3, 1); } + uint32_t enable_timer_a() const { return byte(0x14, 2, 1); } + uint32_t load_timer_b() const { return byte(0x14, 1, 1); } + uint32_t load_timer_a() const { return byte(0x14, 0, 1); } + uint32_t lfo2_pm_depth() const { return byte(0x188, 0, 7); } // fake + uint32_t lfo2_rate() const { return byte(0x16, 0, 8); } + uint32_t lfo2_am_depth() const { return byte(0x17, 0, 7); } + uint32_t lfo_rate() const { return byte(0x18, 0, 8); } + uint32_t lfo_am_depth() const { return byte(0x19, 0, 7); } + uint32_t lfo_pm_depth() const { return byte(0x189, 0, 7); } // fake + uint32_t output_bits() const { return byte(0x1b, 6, 2); } + uint32_t lfo2_sync() const { return byte(0x1b, 5, 1); } + uint32_t lfo_sync() const { return byte(0x1b, 4, 1); } + uint32_t lfo2_waveform() const { return byte(0x1b, 2, 2); } + uint32_t lfo_waveform() const { return byte(0x1b, 0, 2); } + + // per-channel registers + uint32_t ch_volume(uint32_t choffs) const { return byte(0x00, 0, 8, choffs); } + uint32_t ch_output_any(uint32_t choffs) const { return byte(0x20, 7, 1, choffs) | byte(0x30, 0, 1, choffs); } + uint32_t ch_output_0(uint32_t choffs) const { return byte(0x30, 0, 1, choffs); } + uint32_t ch_output_1(uint32_t choffs) const { return byte(0x20, 7, 1, choffs) | byte(0x30, 0, 1, choffs); } + uint32_t ch_output_2(uint32_t choffs) const { return 0; } + uint32_t ch_output_3(uint32_t choffs) const { return 0; } + uint32_t ch_key_on(uint32_t choffs) const { return byte(0x20, 6, 1, choffs); } + uint32_t ch_feedback(uint32_t choffs) const { return byte(0x20, 3, 3, choffs); } + uint32_t ch_algorithm(uint32_t choffs) const { return byte(0x20, 0, 3, choffs); } + uint32_t ch_block_freq(uint32_t choffs) const { return word(0x28, 0, 7, 0x30, 2, 6, choffs); } + uint32_t ch_lfo_pm_sens(uint32_t choffs) const { return byte(0x38, 4, 3, choffs); } + uint32_t ch_lfo_am_sens(uint32_t choffs) const { return byte(0x38, 0, 2, choffs); } + uint32_t ch_lfo2_pm_sens(uint32_t choffs) const { return byte(0x180, 4, 3, choffs); } // fake + uint32_t ch_lfo2_am_sens(uint32_t choffs) const { return byte(0x180, 0, 2, choffs); } // fake + + // per-operator registers + uint32_t op_detune(uint32_t opoffs) const { return byte(0x40, 4, 3, opoffs); } + uint32_t op_multiple(uint32_t opoffs) const { return byte(0x40, 0, 4, opoffs); } + uint32_t op_fix_range(uint32_t opoffs) const { return byte(0x40, 4, 3, opoffs); } + uint32_t op_fix_frequency(uint32_t opoffs) const { return byte(0x40, 0, 4, opoffs); } + uint32_t op_waveform(uint32_t opoffs) const { return byte(0x100, 4, 3, opoffs); } // fake + uint32_t op_fine(uint32_t opoffs) const { return byte(0x100, 0, 4, opoffs); } // fake + uint32_t op_total_level(uint32_t opoffs) const { return byte(0x60, 0, 7, opoffs); } + uint32_t op_ksr(uint32_t opoffs) const { return byte(0x80, 6, 2, opoffs); } + uint32_t op_fix_mode(uint32_t opoffs) const { return byte(0x80, 5, 1, opoffs); } + uint32_t op_attack_rate(uint32_t opoffs) const { return byte(0x80, 0, 5, opoffs); } + uint32_t op_lfo_am_enable(uint32_t opoffs) const { return byte(0xa0, 7, 1, opoffs); } + uint32_t op_decay_rate(uint32_t opoffs) const { return byte(0xa0, 0, 5, opoffs); } + uint32_t op_detune2(uint32_t opoffs) const { return byte(0xc0, 6, 2, opoffs); } + uint32_t op_sustain_rate(uint32_t opoffs) const { return byte(0xc0, 0, 5, opoffs); } + uint32_t op_eg_shift(uint32_t opoffs) const { return byte(0x120, 6, 2, opoffs); } // fake + uint32_t op_reverb_rate(uint32_t opoffs) const { return byte(0x120, 0, 3, opoffs); } // fake + uint32_t op_sustain_level(uint32_t opoffs) const { return byte(0xe0, 4, 4, opoffs); } + uint32_t op_release_rate(uint32_t opoffs) const { return byte(0xe0, 0, 4, opoffs); } + +protected: + // return a bitfield extracted from a byte + uint32_t byte(uint32_t offset, uint32_t start, uint32_t count, uint32_t extra_offset = 0) const + { + return bitfield(m_regdata[offset + extra_offset], start, count); + } + + // return a bitfield extracted from a pair of bytes, MSBs listed first + uint32_t word(uint32_t offset1, uint32_t start1, uint32_t count1, uint32_t offset2, uint32_t start2, uint32_t count2, uint32_t extra_offset = 0) const + { + return (byte(offset1, start1, count1, extra_offset) << count2) | byte(offset2, start2, count2, extra_offset); + } + + // internal state + uint32_t m_lfo_counter[2]; // LFO counter + uint32_t m_noise_lfsr; // noise LFSR state + uint8_t m_noise_counter; // noise counter + uint8_t m_noise_state; // latched noise state + uint8_t m_noise_lfo; // latched LFO noise value + uint8_t m_lfo_am[2]; // current LFO AM value + uint8_t m_regdata[REGISTERS]; // register data + uint16_t m_phase_substep[OPERATORS]; // phase substep for fixed frequency + int16_t m_lfo_waveform[4][LFO_WAVEFORM_LENGTH]; // LFO waveforms; AM in low 8, PM in upper 8 + uint16_t m_waveform[WAVEFORMS][WAVEFORM_LENGTH]; // waveforms +}; + + + +//********************************************************* +// IMPLEMENTATION CLASSES +//********************************************************* + +// ======================> ym2414 + +class ym2414 +{ +public: + using fm_engine = fm_engine_base; + static constexpr uint32_t OUTPUTS = fm_engine::OUTPUTS; + using output_data = fm_engine::output_data; + + // constructor + ym2414(ymfm_interface &intf); + + // reset + void reset(); + + // save/restore + void save_restore(ymfm_saved_state &state); + + // pass-through helpers + uint32_t sample_rate(uint32_t input_clock) const { return m_fm.sample_rate(input_clock); } + void invalidate_caches() { m_fm.invalidate_caches(); } + + // read access + uint8_t read_status(); + uint8_t read(uint32_t offset); + + // write access + void write_address(uint8_t data); + void write_data(uint8_t data); + void write(uint32_t offset, uint8_t data); + + // generate one sample of sound + void generate(output_data *output, uint32_t numsamples = 1); + +protected: + // internal state + uint8_t m_address; // address register + fm_engine m_fm; // core FM engine +}; + +} + + +#endif // YMFM_OPZ_H diff --git a/src/sound/ymfm/ymfm_pcm.cpp b/src/sound/ymfm/ymfm_pcm.cpp new file mode 100644 index 000000000..34417490c --- /dev/null +++ b/src/sound/ymfm/ymfm_pcm.cpp @@ -0,0 +1,714 @@ +// BSD 3-Clause License +// +// Copyright (c) 2021, Aaron Giles +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// 1. Redistributions of source code must retain the above copyright notice, this +// list of conditions and the following disclaimer. +// +// 2. Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// 3. Neither the name of the copyright holder nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#include "ymfm_pcm.h" +#include "ymfm_fm.h" +#include "ymfm_fm.ipp" + +namespace ymfm +{ + +//********************************************************* +// PCM REGISTERS +//********************************************************* + +//------------------------------------------------- +// reset - reset the register state +//------------------------------------------------- + +void pcm_registers::reset() +{ + std::fill_n(&m_regdata[0], REGISTERS, 0); + m_regdata[0xf8] = 0x1b; +} + + +//------------------------------------------------- +// save_restore - save or restore the data +//------------------------------------------------- + +void pcm_registers::save_restore(ymfm_saved_state &state) +{ + state.save_restore(m_regdata); +} + + +//------------------------------------------------- +// cache_channel_data - update the cache with +// data from the registers +//------------------------------------------------- + +void pcm_registers::cache_channel_data(uint32_t choffs, pcm_cache &cache) +{ + // compute step from octave and fnumber; the math here implies + // a .18 fraction but .16 should be perfectly fine + int32_t octave = int8_t(ch_octave(choffs) << 4) >> 4; + uint32_t fnum = ch_fnumber(choffs); + cache.step = ((0x400 | fnum) << (octave + 7)) >> 2; + + // total level is computed as a .10 value for interpolation + cache.total_level = ch_total_level(choffs) << 10; + + // compute panning values in terms of envelope attenuation + int32_t panpot = int8_t(ch_panpot(choffs) << 4) >> 4; + if (panpot >= 0) + { + cache.pan_left = (panpot == 7) ? 0x3ff : 0x20 * panpot; + cache.pan_right = 0; + } + else if (panpot >= -7) + { + cache.pan_left = 0; + cache.pan_right = (panpot == -7) ? 0x3ff : -0x20 * panpot; + } + else + cache.pan_left = cache.pan_right = 0x3ff; + + // determine the LFO stepping value; this how much to add to a running + // x.18 value for the LFO; steps were derived from frequencies in the + // manual and come out very close with these values + static const uint8_t s_lfo_steps[8] = { 1, 12, 19, 25, 31, 35, 37, 42 }; + cache.lfo_step = s_lfo_steps[ch_lfo_speed(choffs)]; + + // AM LFO depth values, derived from the manual; note each has at most + // 2 bits to make the "multiply" easy in hardware + static const uint8_t s_am_depth[8] = { 0, 0x14, 0x20, 0x28, 0x30, 0x40, 0x50, 0x80 }; + cache.am_depth = s_am_depth[ch_am_depth(choffs)]; + + // PM LFO depth values; these are converted from the manual's cents values + // into f-numbers; the computations come out quite cleanly so pretty sure + // these are correct + static const uint8_t s_pm_depth[8] = { 0, 2, 3, 4, 6, 12, 24, 48 }; + cache.pm_depth = s_pm_depth[ch_vibrato(choffs)]; + + // 4-bit sustain level, but 15 means 31 so effectively 5 bits + cache.eg_sustain = ch_sustain_level(choffs); + cache.eg_sustain |= (cache.eg_sustain + 1) & 0x10; + cache.eg_sustain <<= 5; + + // compute the key scaling correction factor; 15 means don't do any correction + int32_t correction = ch_rate_correction(choffs); + if (correction == 15) + correction = 0; + else + correction = (octave + correction) * 2 + bitfield(fnum, 9); + + // compute the envelope generator rates + cache.eg_rate[EG_ATTACK] = effective_rate(ch_attack_rate(choffs), correction); + cache.eg_rate[EG_DECAY] = effective_rate(ch_decay_rate(choffs), correction); + cache.eg_rate[EG_SUSTAIN] = effective_rate(ch_sustain_rate(choffs), correction); + cache.eg_rate[EG_RELEASE] = effective_rate(ch_release_rate(choffs), correction); + cache.eg_rate[EG_REVERB] = 5; + + // if damping is on, override some things; essentially decay at a hardcoded + // rate of 48 until -12db (0x80), then at maximum rate for the rest + if (ch_damp(choffs) != 0) + { + cache.eg_rate[EG_DECAY] = 48; + cache.eg_rate[EG_SUSTAIN] = 63; + cache.eg_rate[EG_RELEASE] = 63; + cache.eg_sustain = 0x80; + } +} + + +//------------------------------------------------- +// effective_rate - return the effective rate, +// clamping and applying corrections as needed +//------------------------------------------------- + +uint32_t pcm_registers::effective_rate(uint32_t raw, uint32_t correction) +{ + // raw rates of 0 and 15 just pin to min/max + if (raw == 0) + return 0; + if (raw == 15) + return 63; + + // otherwise add the correction and clamp to range + return clamp(raw * 4 + correction, 0, 63); +} + + + +//********************************************************* +// PCM CHANNEL +//********************************************************* + +//------------------------------------------------- +// pcm_channel - constructor +//------------------------------------------------- + +pcm_channel::pcm_channel(pcm_engine &owner, uint32_t choffs) : + m_choffs(choffs), + m_baseaddr(0), + m_endpos(0), + m_looppos(0), + m_curpos(0), + m_nextpos(0), + m_lfo_counter(0), + m_eg_state(EG_RELEASE), + m_env_attenuation(0x3ff), + m_total_level(0x7f << 10), + m_format(0), + m_key_state(0), + m_regs(owner.regs()), + m_owner(owner) +{ +} + + +//------------------------------------------------- +// reset - reset the channel state +//------------------------------------------------- + +void pcm_channel::reset() +{ + m_baseaddr = 0; + m_endpos = 0; + m_looppos = 0; + m_curpos = 0; + m_nextpos = 0; + m_lfo_counter = 0; + m_eg_state = EG_RELEASE; + m_env_attenuation = 0x3ff; + m_total_level = 0x7f << 10; + m_format = 0; + m_key_state = 0; +} + + +//------------------------------------------------- +// save_restore - save or restore the data +//------------------------------------------------- + +void pcm_channel::save_restore(ymfm_saved_state &state) +{ + state.save_restore(m_baseaddr); + state.save_restore(m_endpos); + state.save_restore(m_looppos); + state.save_restore(m_curpos); + state.save_restore(m_nextpos); + state.save_restore(m_lfo_counter); + state.save_restore(m_eg_state); + state.save_restore(m_env_attenuation); + state.save_restore(m_total_level); + state.save_restore(m_format); + state.save_restore(m_key_state); +} + + +//------------------------------------------------- +// prepare - prepare for clocking +//------------------------------------------------- + +bool pcm_channel::prepare() +{ + // cache the data + m_regs.cache_channel_data(m_choffs, m_cache); + + // clock the key state + if ((m_key_state & KEY_PENDING) != 0) + { + uint8_t oldstate = m_key_state; + m_key_state = (m_key_state >> 1) & KEY_ON; + if (((oldstate ^ m_key_state) & KEY_ON) != 0) + { + if ((m_key_state & KEY_ON) != 0) + start_attack(); + else + start_release(); + } + } + + // set the total level directly if not interpolating + if (m_regs.ch_level_direct(m_choffs)) + m_total_level = m_cache.total_level; + + // we're active until we're quiet after the release + return (m_eg_state < EG_RELEASE || m_env_attenuation < EG_QUIET); +} + + +//------------------------------------------------- +// clock - master clocking function +//------------------------------------------------- + +void pcm_channel::clock(uint32_t env_counter) +{ + // clock the LFO, which is an x.18 value incremented based on the + // LFO speed value + m_lfo_counter += m_cache.lfo_step; + + // clock the envelope + clock_envelope(env_counter); + + // determine the step after applying vibrato + uint32_t step = m_cache.step; + if (m_cache.pm_depth != 0) + { + // shift the LFO by 1/4 cycle for PM so that it starts at 0 + uint32_t lfo_shifted = m_lfo_counter + (1 << 16); + int32_t lfo_value = bitfield(lfo_shifted, 10, 7); + if (bitfield(lfo_shifted, 17) != 0) + lfo_value ^= 0x7f; + lfo_value -= 0x40; + step += (lfo_value * int32_t(m_cache.pm_depth)) >> 7; + } + + // advance the sample step and loop as needed + m_curpos = m_nextpos; + m_nextpos = m_curpos + step; + if (m_nextpos >= m_endpos) + m_nextpos += m_looppos - m_endpos; + + // interpolate total level if needed + if (m_total_level != m_cache.total_level) + { + // max->min volume takes 156.4ms, or pretty close to 19/1024 per 44.1kHz sample + // min->max volume is half that, so advance by 38/1024 per sample + if (m_total_level < m_cache.total_level) + m_total_level = std::min(m_total_level + 19, m_cache.total_level); + else + m_total_level = std::max(m_total_level - 38, m_cache.total_level); + } +} + + +//------------------------------------------------- +// output - return the computed output value, with +// panning applied +//------------------------------------------------- + +void pcm_channel::output(output_data &output) const +{ + // early out if the envelope is effectively off + uint32_t envelope = m_env_attenuation; + if (envelope > EG_QUIET) + return; + + // add in LFO AM modulation + if (m_cache.am_depth != 0) + { + uint32_t lfo_value = bitfield(m_lfo_counter, 10, 7); + if (bitfield(m_lfo_counter, 17) != 0) + lfo_value ^= 0x7f; + envelope += (lfo_value * m_cache.am_depth) >> 7; + } + + // add in the current interpolated total level value, which is a .10 + // value shifted left by 2 + envelope += m_total_level >> 8; + + // add in panning effect and clamp + uint32_t lenv = std::min(envelope + m_cache.pan_left, 0x3ff); + uint32_t renv = std::min(envelope + m_cache.pan_right, 0x3ff); + + // convert to volume as a .11 fraction + int32_t lvol = attenuation_to_volume(lenv << 2); + int32_t rvol = attenuation_to_volume(renv << 2); + + // fetch current sample and add + int16_t sample = fetch_sample(); + uint32_t outnum = m_regs.ch_output_channel(m_choffs) * 2; + output.data[outnum + 0] += (lvol * sample) >> 15; + output.data[outnum + 1] += (rvol * sample) >> 15; +} + + +//------------------------------------------------- +// keyonoff - signal key on/off +//------------------------------------------------- + +void pcm_channel::keyonoff(bool on) +{ + // mark the key state as pending + m_key_state |= KEY_PENDING | (on ? KEY_PENDING_ON : 0); + + // don't log masked channels + if ((m_key_state & (KEY_PENDING_ON | KEY_ON)) == KEY_PENDING_ON && ((debug::GLOBAL_PCM_CHANNEL_MASK >> m_choffs) & 1) != 0) + { + debug::log_keyon("KeyOn PCM-%02d: num=%3d oct=%2d fnum=%03X level=%02X%c ADSR=%X/%X/%X/%X SL=%X", + m_choffs, + m_regs.ch_wave_table_num(m_choffs), + int8_t(m_regs.ch_octave(m_choffs) << 4) >> 4, + m_regs.ch_fnumber(m_choffs), + m_regs.ch_total_level(m_choffs), + m_regs.ch_level_direct(m_choffs) ? '!' : '/', + m_regs.ch_attack_rate(m_choffs), + m_regs.ch_decay_rate(m_choffs), + m_regs.ch_sustain_rate(m_choffs), + m_regs.ch_release_rate(m_choffs), + m_regs.ch_sustain_level(m_choffs)); + + if (m_regs.ch_rate_correction(m_choffs) != 15) + debug::log_keyon(" RC=%X", m_regs.ch_rate_correction(m_choffs)); + + if (m_regs.ch_pseudo_reverb(m_choffs) != 0) + debug::log_keyon(" %s", "REV"); + if (m_regs.ch_damp(m_choffs) != 0) + debug::log_keyon(" %s", "DAMP"); + + if (m_regs.ch_vibrato(m_choffs) != 0 || m_regs.ch_am_depth(m_choffs) != 0) + { + if (m_regs.ch_vibrato(m_choffs) != 0) + debug::log_keyon(" VIB=%d", m_regs.ch_vibrato(m_choffs)); + if (m_regs.ch_am_depth(m_choffs) != 0) + debug::log_keyon(" AM=%d", m_regs.ch_am_depth(m_choffs)); + debug::log_keyon(" LFO=%d", m_regs.ch_lfo_speed(m_choffs)); + } + debug::log_keyon("%s", "\n"); + } +} + + +//------------------------------------------------- +// load_wavetable - load a wavetable by fetching +// its data from external memory +//------------------------------------------------- + +void pcm_channel::load_wavetable() +{ + // determine the address of the wave table header + uint32_t wavnum = m_regs.ch_wave_table_num(m_choffs); + uint32_t wavheader = 12 * wavnum; + + // above 384 it may be in a different bank + if (wavnum >= 384) + { + uint32_t bank = m_regs.wave_table_header(); + if (bank != 0) + wavheader = 512*1024 * bank + (wavnum - 384) * 12; + } + + // fetch the 22-bit base address and 2-bit format + uint8_t byte = read_pcm(wavheader + 0); + m_format = bitfield(byte, 6, 2); + m_baseaddr = bitfield(byte, 0, 6) << 16; + m_baseaddr |= read_pcm(wavheader + 1) << 8; + m_baseaddr |= read_pcm(wavheader + 2) << 0; + + // fetch the 16-bit loop position + m_looppos = read_pcm(wavheader + 3) << 8; + m_looppos |= read_pcm(wavheader + 4); + m_looppos <<= 16; + + // fetch the 16-bit end position, which is stored as a negative value + // for some reason that is unclear + m_endpos = read_pcm(wavheader + 5) << 8; + m_endpos |= read_pcm(wavheader + 6); + m_endpos = -int32_t(m_endpos) << 16; + + // remaining data values set registers + m_owner.write(0x80 + m_choffs, read_pcm(wavheader + 7)); + m_owner.write(0x98 + m_choffs, read_pcm(wavheader + 8)); + m_owner.write(0xb0 + m_choffs, read_pcm(wavheader + 9)); + m_owner.write(0xc8 + m_choffs, read_pcm(wavheader + 10)); + m_owner.write(0xe0 + m_choffs, read_pcm(wavheader + 11)); + + // reset the envelope so we don't continue playing mid-sample from previous key ons + m_env_attenuation = 0x3ff; +} + + +//------------------------------------------------- +// read_pcm - read a byte from the external PCM +// memory interface +//------------------------------------------------- + +uint8_t pcm_channel::read_pcm(uint32_t address) const +{ + return m_owner.intf().ymfm_external_read(ACCESS_PCM, address); +} + + +//------------------------------------------------- +// start_attack - start the attack phase +//------------------------------------------------- + +void pcm_channel::start_attack() +{ + // don't change anything if already in attack state + if (m_eg_state == EG_ATTACK) + return; + m_eg_state = EG_ATTACK; + + // reset the LFO if requested + if (m_regs.ch_lfo_reset(m_choffs)) + m_lfo_counter = 0; + + // if the attack rate == 63 then immediately go to max attenuation + if (m_cache.eg_rate[EG_ATTACK] == 63) + m_env_attenuation = 0; + + // reset the positions + m_curpos = m_nextpos = 0; +} + + +//------------------------------------------------- +// start_release - start the release phase +//------------------------------------------------- + +void pcm_channel::start_release() +{ + // don't change anything if already in release or reverb state + if (m_eg_state >= EG_RELEASE) + return; + m_eg_state = EG_RELEASE; +} + + +//------------------------------------------------- +// clock_envelope - clock the envelope generator +//------------------------------------------------- + +void pcm_channel::clock_envelope(uint32_t env_counter) +{ + // handle attack->decay transitions + if (m_eg_state == EG_ATTACK && m_env_attenuation == 0) + m_eg_state = EG_DECAY; + + // handle decay->sustain transitions + if (m_eg_state == EG_DECAY && m_env_attenuation >= m_cache.eg_sustain) + m_eg_state = EG_SUSTAIN; + + // fetch the appropriate 6-bit rate value from the cache + uint32_t rate = m_cache.eg_rate[m_eg_state]; + + // compute the rate shift value; this is the shift needed to + // apply to the env_counter such that it becomes a 5.11 fixed + // point number + uint32_t rate_shift = rate >> 2; + env_counter <<= rate_shift; + + // see if the fractional part is 0; if not, it's not time to clock + if (bitfield(env_counter, 0, 11) != 0) + return; + + // determine the increment based on the non-fractional part of env_counter + uint32_t relevant_bits = bitfield(env_counter, (rate_shift <= 11) ? 11 : rate_shift, 3); + uint32_t increment = attenuation_increment(rate, relevant_bits); + + // attack is the only one that increases + if (m_eg_state == EG_ATTACK) + m_env_attenuation += (~m_env_attenuation * increment) >> 4; + + // all other cases are similar + else + { + // apply the increment + m_env_attenuation += increment; + + // clamp the final attenuation + if (m_env_attenuation >= 0x400) + m_env_attenuation = 0x3ff; + + // transition to reverb at -18dB if enabled + if (m_env_attenuation >= 0xc0 && m_eg_state < EG_REVERB && m_regs.ch_pseudo_reverb(m_choffs)) + m_eg_state = EG_REVERB; + } +} + + +//------------------------------------------------- +// fetch_sample - fetch a sample at the current +// position +//------------------------------------------------- + +int16_t pcm_channel::fetch_sample() const +{ + uint32_t addr = m_baseaddr; + uint32_t pos = m_curpos >> 16; + + // 8-bit PCM: shift up by 8 + if (m_format == 0) + return read_pcm(addr + pos) << 8; + + // 16-bit PCM: assemble from 2 halves + if (m_format == 2) + { + addr += pos * 2; + return (read_pcm(addr) << 8) | read_pcm(addr + 1); + } + + // 12-bit PCM: assemble out of half of 3 bytes + addr += (pos / 2) * 3; + if ((pos & 1) == 0) + return (read_pcm(addr + 0) << 8) | ((read_pcm(addr + 1) << 4) & 0xf0); + else + return (read_pcm(addr + 2) << 8) | ((read_pcm(addr + 1) << 0) & 0xf0); +} + + + +//********************************************************* +// PCM ENGINE +//********************************************************* + +//------------------------------------------------- +// pcm_engine - constructor +//------------------------------------------------- + +pcm_engine::pcm_engine(ymfm_interface &intf) : + m_intf(intf), + m_env_counter(0), + m_modified_channels(ALL_CHANNELS), + m_active_channels(ALL_CHANNELS) +{ + // create the channels + for (int chnum = 0; chnum < CHANNELS; chnum++) + m_channel[chnum] = std::make_unique(*this, chnum); +} + + +//------------------------------------------------- +// reset - reset the engine state +//------------------------------------------------- + +void pcm_engine::reset() +{ + // reset register state + m_regs.reset(); + + // reset each channel + for (auto &chan : m_channel) + chan->reset(); +} + + +//------------------------------------------------- +// save_restore - save or restore the data +//------------------------------------------------- + +void pcm_engine::save_restore(ymfm_saved_state &state) +{ + // save our data + state.save_restore(m_env_counter); + + // save channel state + for (int chnum = 0; chnum < CHANNELS; chnum++) + m_channel[chnum]->save_restore(state); +} + + +//------------------------------------------------- +// clock - master clocking function +//------------------------------------------------- + +void pcm_engine::clock(uint32_t chanmask) +{ + // if something was modified, prepare + // also prepare every 4k samples to catch ending notes + if (m_modified_channels != 0 || m_prepare_count++ >= 4096) + { + // call each channel to prepare + m_active_channels = 0; + for (int chnum = 0; chnum < CHANNELS; chnum++) + if (bitfield(chanmask, chnum)) + if (m_channel[chnum]->prepare()) + m_active_channels |= 1 << chnum; + + // reset the modified channels and prepare count + m_modified_channels = m_prepare_count = 0; + } + + // increment the envelope counter; the envelope generator + // only clocks every other sample in order to make the PCM + // envelopes line up with the FM envelopes (after taking into + // account the different FM sampling rate) + m_env_counter++; + + // now update the state of all the channels and operators + for (int chnum = 0; chnum < CHANNELS; chnum++) + if (bitfield(chanmask, chnum)) + m_channel[chnum]->clock(m_env_counter >> 1); +} + + +//------------------------------------------------- +// update - master update function +//------------------------------------------------- + +void pcm_engine::output(output_data &output, uint32_t chanmask) +{ + // mask out some channels for debug purposes + chanmask &= debug::GLOBAL_PCM_CHANNEL_MASK; + + // compute the output of each channel + for (int chnum = 0; chnum < CHANNELS; chnum++) + if (bitfield(chanmask, chnum)) + m_channel[chnum]->output(output); +} + + +//------------------------------------------------- +// read - handle reads from the PCM registers +//------------------------------------------------- + +uint8_t pcm_engine::read(uint32_t regnum) +{ + // handle reads from the data register + if (regnum == 0x06 && m_regs.memory_access_mode() != 0) + return m_intf.ymfm_external_read(ACCESS_PCM, m_regs.memory_address_autoinc()); + + return m_regs.read(regnum); +} + + +//------------------------------------------------- +// write - handle writes to the PCM registers +//------------------------------------------------- + +void pcm_engine::write(uint32_t regnum, uint8_t data) +{ + // handle reads to the data register + if (regnum == 0x06 && m_regs.memory_access_mode() != 0) + { + m_intf.ymfm_external_write(ACCESS_PCM, m_regs.memory_address_autoinc(), data); + return; + } + + // for now just mark all channels as modified + m_modified_channels = ALL_CHANNELS; + + // most writes are passive, consumed only when needed + m_regs.write(regnum, data); + + // however, process keyons immediately + if (regnum >= 0x68 && regnum <= 0x7f) + m_channel[regnum - 0x68]->keyonoff(bitfield(data, 7)); + + // and also wavetable writes + else if (regnum >= 0x08 && regnum <= 0x1f) + m_channel[regnum - 0x08]->load_wavetable(); +} + +} diff --git a/src/sound/ymfm/ymfm_pcm.h b/src/sound/ymfm/ymfm_pcm.h new file mode 100644 index 000000000..b471fa611 --- /dev/null +++ b/src/sound/ymfm/ymfm_pcm.h @@ -0,0 +1,347 @@ +// BSD 3-Clause License +// +// Copyright (c) 2021, Aaron Giles +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// 1. Redistributions of source code must retain the above copyright notice, this +// list of conditions and the following disclaimer. +// +// 2. Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// 3. Neither the name of the copyright holder nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#ifndef YMFM_PCM_H +#define YMFM_PCM_H + +#pragma once + +#include "ymfm.h" + +namespace ymfm +{ + +/* +Note to self: Sega "Multi-PCM" is almost identical to this + +28 channels + +Writes: +00 = data reg, causes write +01 = target slot = data - (data / 8) +02 = address (clamped to 7) + +Slot data (registers with ADSR/KSR seem to be inaccessible): +0: xxxx---- panpot +1: xxxxxxxx wavetable low +2: xxxxxx-- pitch low + -------x wavetable high +3: xxxx---- octave + ----xxxx pitch hi +4: x------- key on +5: xxxxxxx- total level + -------x level direct (0=interpolate) +6: --xxx--- LFO frequency + -----xxx PM sensitivity +7: -----xxx AM sensitivity + +Sample data: ++00: start hi ++01: start mid ++02: start low ++03: loop hi ++04: loop low ++05: -end hi ++06: -end low ++07: vibrato (reg 6) ++08: attack/decay ++09: sustain level/rate ++0A: ksr/release ++0B: LFO amplitude (reg 7) + +*/ + +//********************************************************* +// INTERFACE CLASSES +//********************************************************* + +class pcm_engine; + + +// ======================> pcm_cache + +// this class holds data that is computed once at the start of clocking +// and remains static during subsequent sound generation +struct pcm_cache +{ + uint32_t step; // sample position step, as a .16 value + uint32_t total_level; // target total level, as a .10 value + uint32_t pan_left; // left panning attenuation + uint32_t pan_right; // right panning attenuation + uint32_t eg_sustain; // sustain level, shifted up to envelope values + uint8_t eg_rate[EG_STATES]; // envelope rate, including KSR + uint8_t lfo_step; // stepping value for LFO + uint8_t am_depth; // scale value for AM LFO + uint8_t pm_depth; // scale value for PM LFO +}; + + +// ======================> pcm_registers + +// +// PCM register map: +// +// System-wide registers: +// 00-01 xxxxxxxx LSI Test +// 02 -------x Memory access mode (0=sound gen, 1=read/write) +// ------x- Memory type (0=ROM, 1=ROM+SRAM) +// ---xxx-- Wave table header +// xxx----- Device ID (=1 for YMF278B) +// 03 --xxxxxx Memory address high +// 04 xxxxxxxx Memory address mid +// 05 xxxxxxxx Memory address low +// 06 xxxxxxxx Memory data +// F8 --xxx--- Mix control (FM_R) +// -----xxx Mix control (FM_L) +// F9 --xxx--- Mix control (PCM_R) +// -----xxx Mix control (PCM_L) +// +// Channel-specific registers: +// 08-1F xxxxxxxx Wave table number low +// 20-37 -------x Wave table number high +// xxxxxxx- F-number low +// 38-4F -----xxx F-number high +// ----x--- Pseudo-reverb +// xxxx---- Octave +// 50-67 xxxxxxx- Total level +// -------x Level direct +// 68-7F x------- Key on +// -x------ Damp +// --x----- LFO reset +// ---x---- Output channel +// ----xxxx Panpot +// 80-97 --xxx--- LFO speed +// -----xxx Vibrato +// 98-AF xxxx---- Attack rate +// ----xxxx Decay rate +// B0-C7 xxxx---- Sustain level +// ----xxxx Sustain rate +// C8-DF xxxx---- Rate correction +// ----xxxx Release rate +// E0-F7 -----xxx AM depth + +class pcm_registers +{ +public: + // constants + static constexpr uint32_t OUTPUTS = 4; + static constexpr uint32_t CHANNELS = 24; + static constexpr uint32_t REGISTERS = 0x100; + static constexpr uint32_t ALL_CHANNELS = (1 << CHANNELS) - 1; + + // constructor + pcm_registers() { } + + // save/restore + void save_restore(ymfm_saved_state &state); + + // reset to initial state + void reset(); + + // update cache information + void cache_channel_data(uint32_t choffs, pcm_cache &cache); + + // direct read/write access + uint8_t read(uint32_t index ) { return m_regdata[index]; } + void write(uint32_t index, uint8_t data) { m_regdata[index] = data; } + + // system-wide registers + uint32_t memory_access_mode() const { return bitfield(m_regdata[0x02], 0); } + uint32_t memory_type() const { return bitfield(m_regdata[0x02], 1); } + uint32_t wave_table_header() const { return bitfield(m_regdata[0x02], 2, 3); } + uint32_t device_id() const { return bitfield(m_regdata[0x02], 5, 3); } + uint32_t memory_address() const { return (bitfield(m_regdata[0x03], 0, 6) << 16) | (m_regdata[0x04] << 8) | m_regdata[0x05]; } + uint32_t memory_data() const { return m_regdata[0x06]; } + uint32_t mix_fm_r() const { return bitfield(m_regdata[0xf8], 3, 3); } + uint32_t mix_fm_l() const { return bitfield(m_regdata[0xf8], 0, 3); } + uint32_t mix_pcm_r() const { return bitfield(m_regdata[0xf9], 3, 3); } + uint32_t mix_pcm_l() const { return bitfield(m_regdata[0xf9], 0, 3); } + + // per-channel registers + uint32_t ch_wave_table_num(uint32_t choffs) const { return m_regdata[choffs + 0x08] | (bitfield(m_regdata[choffs + 0x20], 0) << 8); } + uint32_t ch_fnumber(uint32_t choffs) const { return bitfield(m_regdata[choffs + 0x20], 1, 7) | (bitfield(m_regdata[choffs + 0x38], 0, 3) << 7); } + uint32_t ch_pseudo_reverb(uint32_t choffs) const { return bitfield(m_regdata[choffs + 0x38], 3); } + uint32_t ch_octave(uint32_t choffs) const { return bitfield(m_regdata[choffs + 0x38], 4, 4); } + uint32_t ch_total_level(uint32_t choffs) const { return bitfield(m_regdata[choffs + 0x50], 1, 7); } + uint32_t ch_level_direct(uint32_t choffs) const { return bitfield(m_regdata[choffs + 0x50], 0); } + uint32_t ch_keyon(uint32_t choffs) const { return bitfield(m_regdata[choffs + 0x68], 7); } + uint32_t ch_damp(uint32_t choffs) const { return bitfield(m_regdata[choffs + 0x68], 6); } + uint32_t ch_lfo_reset(uint32_t choffs) const { return bitfield(m_regdata[choffs + 0x68], 5); } + uint32_t ch_output_channel(uint32_t choffs) const { return bitfield(m_regdata[choffs + 0x68], 4); } + uint32_t ch_panpot(uint32_t choffs) const { return bitfield(m_regdata[choffs + 0x68], 0, 4); } + uint32_t ch_lfo_speed(uint32_t choffs) const { return bitfield(m_regdata[choffs + 0x80], 3, 3); } + uint32_t ch_vibrato(uint32_t choffs) const { return bitfield(m_regdata[choffs + 0x80], 0, 3); } + uint32_t ch_attack_rate(uint32_t choffs) const { return bitfield(m_regdata[choffs + 0x98], 4, 4); } + uint32_t ch_decay_rate(uint32_t choffs) const { return bitfield(m_regdata[choffs + 0x98], 0, 4); } + uint32_t ch_sustain_level(uint32_t choffs) const { return bitfield(m_regdata[choffs + 0xb0], 4, 4); } + uint32_t ch_sustain_rate(uint32_t choffs) const { return bitfield(m_regdata[choffs + 0xb0], 0, 4); } + uint32_t ch_rate_correction(uint32_t choffs) const { return bitfield(m_regdata[choffs + 0xc8], 4, 4); } + uint32_t ch_release_rate(uint32_t choffs) const { return bitfield(m_regdata[choffs + 0xc8], 0, 4); } + uint32_t ch_am_depth(uint32_t choffs) const { return bitfield(m_regdata[choffs + 0xe0], 0, 3); } + + // return the memory address and increment it + uint32_t memory_address_autoinc() + { + uint32_t result = memory_address(); + uint32_t newval = result + 1; + m_regdata[0x05] = newval >> 0; + m_regdata[0x04] = newval >> 8; + m_regdata[0x03] = (newval >> 16) & 0x3f; + return result; + } + +private: + // internal helpers + uint32_t effective_rate(uint32_t raw, uint32_t correction); + + // internal state + uint8_t m_regdata[REGISTERS]; // register data +}; + + +// ======================> pcm_channel + +class pcm_channel +{ + static constexpr uint8_t KEY_ON = 0x01; + static constexpr uint8_t KEY_PENDING_ON = 0x02; + static constexpr uint8_t KEY_PENDING = 0x04; + + // "quiet" value, used to optimize when we can skip doing working + static constexpr uint32_t EG_QUIET = 0x200; + +public: + using output_data = ymfm_output; + + // constructor + pcm_channel(pcm_engine &owner, uint32_t choffs); + + // save/restore + void save_restore(ymfm_saved_state &state); + + // reset the channel state + void reset(); + + // return the channel offset + uint32_t choffs() const { return m_choffs; } + + // prepare prior to clocking + bool prepare(); + + // master clocking function + void clock(uint32_t env_counter); + + // return the computed output value, with panning applied + void output(output_data &output) const; + + // signal key on/off + void keyonoff(bool on); + + // load a new wavetable entry + void load_wavetable(); + +private: + // internal helpers + void start_attack(); + void start_release(); + void clock_envelope(uint32_t env_counter); + int16_t fetch_sample() const; + uint8_t read_pcm(uint32_t address) const; + + // internal state + uint32_t const m_choffs; // channel offset + uint32_t m_baseaddr; // base address + uint32_t m_endpos; // ending position + uint32_t m_looppos; // loop position + uint32_t m_curpos; // current position + uint32_t m_nextpos; // next position + uint32_t m_lfo_counter; // LFO counter + envelope_state m_eg_state; // envelope state + uint16_t m_env_attenuation; // computed envelope attenuation + uint32_t m_total_level; // total level with as 7.10 for interp + uint8_t m_format; // sample format + uint8_t m_key_state; // current key state + pcm_cache m_cache; // cached data + pcm_registers &m_regs; // reference to registers + pcm_engine &m_owner; // reference to our owner +}; + + +// ======================> pcm_engine + +class pcm_engine +{ +public: + static constexpr int OUTPUTS = pcm_registers::OUTPUTS; + static constexpr int CHANNELS = pcm_registers::CHANNELS; + static constexpr uint32_t ALL_CHANNELS = pcm_registers::ALL_CHANNELS; + using output_data = pcm_channel::output_data; + + // constructor + pcm_engine(ymfm_interface &intf); + + // reset our status + void reset(); + + // save/restore + void save_restore(ymfm_saved_state &state); + + // master clocking function + void clock(uint32_t chanmask); + + // compute sum of channel outputs + void output(output_data &output, uint32_t chanmask); + + // read from the PCM registers + uint8_t read(uint32_t regnum); + + // write to the PCM registers + void write(uint32_t regnum, uint8_t data); + + // return a reference to our interface + ymfm_interface &intf() { return m_intf; } + + // return a reference to our registers + pcm_registers ®s() { return m_regs; } + +private: + // internal state + ymfm_interface &m_intf; // reference to the interface + uint32_t m_env_counter; // envelope counter + uint32_t m_modified_channels; // bitmask of modified channels + uint32_t m_active_channels; // bitmask of active channels + uint32_t m_prepare_count; // counter to do periodic prepare sweeps + std::unique_ptr m_channel[CHANNELS]; // array of channels + pcm_registers m_regs; // registers +}; + +} + +#endif // YMFM_PCM_H diff --git a/src/sound/ymfm/ymfm_ssg.cpp b/src/sound/ymfm/ymfm_ssg.cpp new file mode 100644 index 000000000..1c477d0de --- /dev/null +++ b/src/sound/ymfm/ymfm_ssg.cpp @@ -0,0 +1,279 @@ +// BSD 3-Clause License +// +// Copyright (c) 2021, Aaron Giles +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// 1. Redistributions of source code must retain the above copyright notice, this +// list of conditions and the following disclaimer. +// +// 2. Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// 3. Neither the name of the copyright holder nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#include "ymfm_ssg.h" + +namespace ymfm +{ + +//********************************************************* +// SSG REGISTERS +//********************************************************* + +//------------------------------------------------- +// reset - reset the register state +//------------------------------------------------- + +void ssg_registers::reset() +{ + std::fill_n(&m_regdata[0], REGISTERS, 0); +} + + +//------------------------------------------------- +// save_restore - save or restore the data +//------------------------------------------------- + +void ssg_registers::save_restore(ymfm_saved_state &state) +{ + state.save_restore(m_regdata); +} + + + +//********************************************************* +// SSG ENGINE +//********************************************************* + +//------------------------------------------------- +// ssg_engine - constructor +//------------------------------------------------- + +ssg_engine::ssg_engine(ymfm_interface &intf) : + m_intf(intf), + m_tone_count{ 0,0,0 }, + m_tone_state{ 0,0,0 }, + m_envelope_count(0), + m_envelope_state(0), + m_noise_count(0), + m_noise_state(1), + m_override(nullptr) +{ +} + + +//------------------------------------------------- +// reset - reset the engine state +//------------------------------------------------- + +void ssg_engine::reset() +{ + // defer to the override if present + if (m_override != nullptr) + return m_override->ssg_reset(); + + // reset register state + m_regs.reset(); + + // reset engine state + for (int chan = 0; chan < 3; chan++) + { + m_tone_count[chan] = 0; + m_tone_state[chan] = 0; + } + m_envelope_count = 0; + m_envelope_state = 0; + m_noise_count = 0; + m_noise_state = 1; +} + + +//------------------------------------------------- +// save_restore - save or restore the data +//------------------------------------------------- + +void ssg_engine::save_restore(ymfm_saved_state &state) +{ + // save register state + m_regs.save_restore(state); + + // save engine state + state.save_restore(m_tone_count); + state.save_restore(m_tone_state); + state.save_restore(m_envelope_count); + state.save_restore(m_envelope_state); + state.save_restore(m_noise_count); + state.save_restore(m_noise_state); +} + + +//------------------------------------------------- +// clock - master clocking function +//------------------------------------------------- + +void ssg_engine::clock() +{ + // clock tones; tone period units are clock/16 but since we run at clock/8 + // that works out for us to toggle the state (50% duty cycle) at twice the + // programmed period + for (int chan = 0; chan < 3; chan++) + { + m_tone_count[chan]++; + if (m_tone_count[chan] >= m_regs.ch_tone_period(chan)) + { + m_tone_state[chan] ^= 1; + m_tone_count[chan] = 0; + } + } + + // clock noise; noise period units are clock/16 but since we run at clock/8, + // our counter needs a right shift prior to compare; note that a period of 0 + // should produce an indentical result to a period of 1, so add a special + // check against that case + m_noise_count++; + if ((m_noise_count >> 1) >= m_regs.noise_period() && m_noise_count != 1) + { + m_noise_state ^= (bitfield(m_noise_state, 0) ^ bitfield(m_noise_state, 3)) << 17; + m_noise_state >>= 1; + m_noise_count = 0; + } + + // clock envelope; envelope period units are clock/8 (manual says clock/256 + // but that's for all 32 steps) + m_envelope_count++; + if (m_envelope_count >= m_regs.envelope_period()) + { + m_envelope_state++; + m_envelope_count = 0; + } +} + + +//------------------------------------------------- +// output - output the current state +//------------------------------------------------- + +void ssg_engine::output(output_data &output) +{ + // volume to amplitude table, taken from MAME's implementation but biased + // so that 0 == 0 + static int16_t const s_amplitudes[32] = + { + 0, 32, 78, 141, 178, 222, 262, 306, + 369, 441, 509, 585, 701, 836, 965, 1112, + 1334, 1595, 1853, 2146, 2576, 3081, 3576, 4135, + 5000, 6006, 7023, 8155, 9963,11976,14132,16382 + }; + + // compute the envelope volume + uint32_t envelope_volume; + if ((m_regs.envelope_hold() | (m_regs.envelope_continue() ^ 1)) && m_envelope_state >= 32) + { + m_envelope_state = 32; + envelope_volume = ((m_regs.envelope_attack() ^ m_regs.envelope_alternate()) & m_regs.envelope_continue()) ? 31 : 0; + } + else + { + uint32_t attack = m_regs.envelope_attack(); + if (m_regs.envelope_alternate()) + attack ^= bitfield(m_envelope_state, 5); + envelope_volume = (m_envelope_state & 31) ^ (attack ? 0 : 31); + } + + // iterate over channels + for (int chan = 0; chan < 3; chan++) + { + // noise depends on the noise state, which is the LSB of m_noise_state + uint32_t noise_on = m_regs.ch_noise_enable_n(chan) | m_noise_state; + + // tone depends on the current tone state + uint32_t tone_on = m_regs.ch_tone_enable_n(chan) | m_tone_state[chan]; + + // if neither tone nor noise enabled, return 0 + uint32_t volume; + if ((noise_on & tone_on) == 0) + volume = 0; + + // if the envelope is enabled, use its amplitude + else if (m_regs.ch_envelope_enable(chan)) + volume = envelope_volume; + + // otherwise, scale the tone amplitude up to match envelope values + // according to the datasheet, amplitude 15 maps to envelope 31 + else + { + volume = m_regs.ch_amplitude(chan) * 2; + if (volume != 0) + volume |= 1; + } + + // convert to amplitude + output.data[chan] = s_amplitudes[volume]; + } +} + + +//------------------------------------------------- +// read - handle reads from the SSG registers +//------------------------------------------------- + +uint8_t ssg_engine::read(uint32_t regnum) +{ + // defer to the override if present + if (m_override != nullptr) + return m_override->ssg_read(regnum); + + // read from the I/O ports call the handlers if they are configured for input + if (regnum == 0x0e && !m_regs.io_a_out()) + return m_intf.ymfm_external_read(ACCESS_IO, 0); + else if (regnum == 0x0f && !m_regs.io_b_out()) + return m_intf.ymfm_external_read(ACCESS_IO, 1); + + // otherwise just return the register value + return m_regs.read(regnum); +} + + +//------------------------------------------------- +// write - handle writes to the SSG registers +//------------------------------------------------- + +void ssg_engine::write(uint32_t regnum, uint8_t data) +{ + // defer to the override if present + if (m_override != nullptr) + return m_override->ssg_write(regnum, data); + + // store the raw value to the register array; + // most writes are passive, consumed only when needed + m_regs.write(regnum, data); + + // writes to the envelope shape register reset the state + if (regnum == 0x0d) + m_envelope_state = 0; + + // writes to the I/O ports call the handlers if they are configured for output + else if (regnum == 0x0e && m_regs.io_a_out()) + m_intf.ymfm_external_write(ACCESS_IO, 0, data); + else if (regnum == 0x0f && m_regs.io_b_out()) + m_intf.ymfm_external_write(ACCESS_IO, 1, data); +} + +} diff --git a/src/sound/ymfm/ymfm_ssg.h b/src/sound/ymfm/ymfm_ssg.h new file mode 100644 index 000000000..749ad146f --- /dev/null +++ b/src/sound/ymfm/ymfm_ssg.h @@ -0,0 +1,205 @@ +// BSD 3-Clause License +// +// Copyright (c) 2021, Aaron Giles +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// 1. Redistributions of source code must retain the above copyright notice, this +// list of conditions and the following disclaimer. +// +// 2. Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// 3. Neither the name of the copyright holder nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#ifndef YMFM_SSG_H +#define YMFM_SSG_H + +#pragma once + +#include "ymfm.h" + +namespace ymfm +{ + +//********************************************************* +// OVERRIDE INTERFACE +//********************************************************* + +// ======================> ssg_override + +// this class describes a simple interface to allow the internal SSG to be +// overridden with another implementation +class ssg_override +{ +public: + // reset our status + virtual void ssg_reset() = 0; + + // read/write to the SSG registers + virtual uint8_t ssg_read(uint32_t regnum) = 0; + virtual void ssg_write(uint32_t regnum, uint8_t data) = 0; + + // notification when the prescale has changed + virtual void ssg_prescale_changed() = 0; +}; + + +//********************************************************* +// REGISTER CLASS +//********************************************************* + +// ======================> ssg_registers + +// +// SSG register map: +// +// System-wide registers: +// 06 ---xxxxx Noise period +// 07 x------- I/O B in(0) or out(1) +// -x------ I/O A in(0) or out(1) +// --x----- Noise enable(0) or disable(1) for channel C +// ---x---- Noise enable(0) or disable(1) for channel B +// ----x--- Noise enable(0) or disable(1) for channel A +// -----x-- Tone enable(0) or disable(1) for channel C +// ------x- Tone enable(0) or disable(1) for channel B +// -------x Tone enable(0) or disable(1) for channel A +// 0B xxxxxxxx Envelope period fine +// 0C xxxxxxxx Envelope period coarse +// 0D ----x--- Envelope shape: continue +// -----x-- Envelope shape: attack/decay +// ------x- Envelope shape: alternate +// -------x Envelope shape: hold +// 0E xxxxxxxx 8-bit parallel I/O port A +// 0F xxxxxxxx 8-bit parallel I/O port B +// +// Per-channel registers: +// 00,02,04 xxxxxxxx Tone period (fine) for channel A,B,C +// 01,03,05 ----xxxx Tone period (coarse) for channel A,B,C +// 08,09,0A ---x---- Mode: fixed(0) or variable(1) for channel A,B,C +// ----xxxx Amplitude for channel A,B,C +// +class ssg_registers +{ +public: + // constants + static constexpr uint32_t OUTPUTS = 3; + static constexpr uint32_t CHANNELS = 3; + static constexpr uint32_t REGISTERS = 0x10; + static constexpr uint32_t ALL_CHANNELS = (1 << CHANNELS) - 1; + + // constructor + ssg_registers() { } + + // reset to initial state + void reset(); + + // save/restore + void save_restore(ymfm_saved_state &state); + + // direct read/write access + uint8_t read(uint32_t index) { return m_regdata[index]; } + void write(uint32_t index, uint8_t data) { m_regdata[index] = data; } + + // system-wide registers + uint32_t noise_period() const { return bitfield(m_regdata[0x06], 0, 5); } + uint32_t io_b_out() const { return bitfield(m_regdata[0x07], 7); } + uint32_t io_a_out() const { return bitfield(m_regdata[0x07], 6); } + uint32_t envelope_period() const { return m_regdata[0x0b] | (m_regdata[0x0c] << 8); } + uint32_t envelope_continue() const { return bitfield(m_regdata[0x0d], 3); } + uint32_t envelope_attack() const { return bitfield(m_regdata[0x0d], 2); } + uint32_t envelope_alternate() const { return bitfield(m_regdata[0x0d], 1); } + uint32_t envelope_hold() const { return bitfield(m_regdata[0x0d], 0); } + uint32_t io_a_data() const { return m_regdata[0x0e]; } + uint32_t io_b_data() const { return m_regdata[0x0f]; } + + // per-channel registers + uint32_t ch_noise_enable_n(uint32_t choffs) const { return bitfield(m_regdata[0x07], 3 + choffs); } + uint32_t ch_tone_enable_n(uint32_t choffs) const { return bitfield(m_regdata[0x07], 0 + choffs); } + uint32_t ch_tone_period(uint32_t choffs) const { return m_regdata[0x00 + 2 * choffs] | (bitfield(m_regdata[0x01 + 2 * choffs], 0, 4) << 8); } + uint32_t ch_envelope_enable(uint32_t choffs) const { return bitfield(m_regdata[0x08 + choffs], 4); } + uint32_t ch_amplitude(uint32_t choffs) const { return bitfield(m_regdata[0x08 + choffs], 0, 4); } + +private: + // internal state + uint8_t m_regdata[REGISTERS]; // register data +}; + + +// ======================> ssg_engine + +class ssg_engine +{ +public: + static constexpr int OUTPUTS = ssg_registers::OUTPUTS; + static constexpr int CHANNELS = ssg_registers::CHANNELS; + static constexpr int CLOCK_DIVIDER = 8; + + using output_data = ymfm_output; + + // constructor + ssg_engine(ymfm_interface &intf); + + // configure an override + void override(ssg_override &override) { m_override = &override; } + + // reset our status + void reset(); + + // save/restore + void save_restore(ymfm_saved_state &state); + + // master clocking function + void clock(); + + // compute sum of channel outputs + void output(output_data &output); + + // read/write to the SSG registers + uint8_t read(uint32_t regnum); + void write(uint32_t regnum, uint8_t data); + + // return a reference to our interface + ymfm_interface &intf() { return m_intf; } + + // return a reference to our registers + ssg_registers ®s() { return m_regs; } + + // true if we are overridden + bool overridden() const { return (m_override != nullptr); } + + // indicate the prescale has changed + void prescale_changed() { if (m_override != nullptr) m_override->ssg_prescale_changed(); } + +private: + // internal state + ymfm_interface &m_intf; // reference to the interface + uint32_t m_tone_count[3]; // current tone counter + uint32_t m_tone_state[3]; // current tone state + uint32_t m_envelope_count; // envelope counter + uint32_t m_envelope_state; // envelope state + uint32_t m_noise_count; // current noise counter + uint32_t m_noise_state; // current noise state + ssg_registers m_regs; // registers + ssg_override *m_override; // override interface +}; + +} + +#endif // YMFM_SSG_H diff --git a/src/thread.cpp b/src/thread.cpp index 4134befba..1b4311f37 100644 --- a/src/thread.cpp +++ b/src/thread.cpp @@ -3,12 +3,12 @@ #include #include <86box/plat.h> +#include <86box/thread.h> -struct event_cpp11_t -{ +struct event_cpp11_t { std::condition_variable cond; - std::mutex mutex; - bool state = false; + std::mutex mutex; + bool state = false; }; extern "C" { @@ -17,7 +17,7 @@ thread_t * thread_create(void (*thread_rout)(void *param), void *param) { auto thread = new std::thread([thread_rout, param] { - thread_rout(param); + thread_rout(param); }); return thread; } @@ -25,7 +25,9 @@ thread_create(void (*thread_rout)(void *param), void *param) int thread_wait(thread_t *arg) { - auto thread = reinterpret_cast(arg); + if (!arg) + return 0; + auto thread = reinterpret_cast(arg); thread->join(); return 0; } @@ -37,34 +39,42 @@ thread_create_mutex(void) return mutex; } +int +thread_test_mutex(mutex_t *_mutex) +{ + if (_mutex == nullptr) + return 0; + + auto mutex = reinterpret_cast(_mutex); + return mutex->try_lock() ? 1 : 0; +} + int thread_wait_mutex(mutex_t *_mutex) { if (_mutex == nullptr) - return 0; + return 0; - auto mutex = reinterpret_cast(_mutex); + auto mutex = reinterpret_cast(_mutex); mutex->lock(); return 1; } - int thread_release_mutex(mutex_t *_mutex) { if (_mutex == nullptr) - return 0; + return 0; - auto mutex = reinterpret_cast(_mutex); + auto mutex = reinterpret_cast(_mutex); mutex->unlock(); return 1; } - void thread_close_mutex(mutex_t *_mutex) { - auto mutex = reinterpret_cast(_mutex); + auto mutex = reinterpret_cast(_mutex); delete mutex; } @@ -78,13 +88,13 @@ thread_create_event() int thread_wait_event(event_t *handle, int timeout) { - auto event = reinterpret_cast(handle); - auto lock = std::unique_lock(event->mutex); + auto event = reinterpret_cast(handle); + auto lock = std::unique_lock(event->mutex); if (timeout < 0) { event->cond.wait(lock, [event] { return event->state; }); } else { - auto to = std::chrono::system_clock::now() + std::chrono::milliseconds(timeout); + auto to = std::chrono::system_clock::now() + std::chrono::milliseconds(timeout); std::cv_status status; do { @@ -101,9 +111,9 @@ thread_wait_event(event_t *handle, int timeout) void thread_set_event(event_t *handle) { - auto event = reinterpret_cast(handle); + auto event = reinterpret_cast(handle); { - auto lock = std::unique_lock(event->mutex); + auto lock = std::unique_lock(event->mutex); event->state = true; } event->cond.notify_all(); @@ -112,16 +122,15 @@ thread_set_event(event_t *handle) void thread_reset_event(event_t *handle) { - auto event = reinterpret_cast(handle); - auto lock = std::unique_lock(event->mutex); + auto event = reinterpret_cast(handle); + auto lock = std::unique_lock(event->mutex); event->state = false; } void thread_destroy_event(event_t *handle) { - auto event = reinterpret_cast(handle); + auto event = reinterpret_cast(handle); delete event; } - } diff --git a/src/timer.c b/src/timer.c index 32d382d54..fa8376bde 100644 --- a/src/timer.c +++ b/src/timer.c @@ -5,7 +5,6 @@ #include <86box/86box.h> #include <86box/timer.h> - uint64_t TIMER_USEC; uint32_t timer_target; @@ -16,140 +15,141 @@ pc_timer_t *timer_head = NULL; /* Are we initialized? */ int timer_inited = 0; +static void timer_advance_ex(pc_timer_t *timer, int start); void timer_enable(pc_timer_t *timer) { pc_timer_t *timer_node = timer_head; + int ret = 0; if (!timer_inited || (timer == NULL)) - return; + return; if (timer->flags & TIMER_ENABLED) - timer_disable(timer); + timer_disable(timer); if (timer->next || timer->prev) - fatal("timer_enable - timer->next\n"); - - timer->flags |= TIMER_ENABLED; + fatal("timer_enable - timer->next\n"); /*List currently empty - add to head*/ if (!timer_head) { - timer_head = timer; - timer->next = timer->prev = NULL; - timer_target = timer_head->ts.ts32.integer; - return; + timer_head = timer; + timer->next = timer->prev = NULL; + timer_target = timer_head->ts.ts32.integer; + ret = 1; + } else if (TIMER_LESS_THAN(timer, timer_head)) { + timer->next = timer_head; + timer->prev = NULL; + timer_head->prev = timer; + timer_head = timer; + timer_target = timer_head->ts.ts32.integer; + ret = 1; + } else if (!timer_head->next) { + timer_head->next = timer; + timer->prev = timer_head; + ret = 1; } - timer_node = timer_head; + if (ret == 0) { + pc_timer_t *prev = timer_head; + timer_node = timer_head->next; - while(1) { - /*Timer expires before timer_node. Add to list in front of timer_node*/ - if (TIMER_LESS_THAN(timer, timer_node)) { - timer->next = timer_node; - timer->prev = timer_node->prev; - timer_node->prev = timer; - if (timer->prev) - timer->prev->next = timer; - else { - timer_head = timer; - timer_target = timer_head->ts.ts32.integer; - } - return; - } + while (1) { + /*Timer expires before timer_node. Add to list in front of timer_node*/ + if (TIMER_LESS_THAN(timer, timer_node)) { + timer->next = timer_node; + timer->prev = prev; + timer_node->prev = timer; + prev->next = timer; + ret = 1; + break; + } - /*timer_node is last in the list. Add timer to end of list*/ - if (!timer_node->next) { - timer_node->next = timer; - timer->prev = timer_node; - return; - } + /*timer_node is last in the list. Add timer to end of list*/ + if (!timer_node->next) { + timer_node->next = timer; + timer->prev = timer_node; + ret = 1; + break; + } - timer_node = timer_node->next; + prev = timer_node; + timer_node = timer_node->next; + } } + + /* Do not mark it as enabled if it has failed every single condition. */ + if (ret == 1) + timer->flags |= TIMER_ENABLED; } - void timer_disable(pc_timer_t *timer) { if (!timer_inited || (timer == NULL) || !(timer->flags & TIMER_ENABLED)) - return; + return; if (!timer->next && !timer->prev && timer != timer_head) - fatal("timer_disable - !timer->next\n"); + fatal("timer_disable - !timer->next\n"); timer->flags &= ~TIMER_ENABLED; if (timer->prev) - timer->prev->next = timer->next; + timer->prev->next = timer->next; else - timer_head = timer->next; + timer_head = timer->next; if (timer->next) - timer->next->prev = timer->prev; + timer->next->prev = timer->prev; timer->prev = timer->next = NULL; } - -void -timer_remove_head(void) -{ - pc_timer_t *timer; - - if (!timer_inited) - return; - - if (timer_head) { - timer = timer_head; - timer_head = timer->next; - if (timer_head) { - timer_head->prev = NULL; - timer->next->prev = NULL; - } - timer->next = timer->prev = NULL; - timer->flags &= ~TIMER_ENABLED; - } -} - - void timer_process(void) { pc_timer_t *timer; - if (!timer_inited || !timer_head) - return; + if (!timer_head) + return; - while(1) { - timer = timer_head; + while (1) { + timer = timer_head; - if (!TIMER_LESS_THAN_VAL(timer, (uint32_t)tsc)) - break; + if (!TIMER_LESS_THAN_VAL(timer, (uint32_t) tsc)) + break; - timer_remove_head(); + timer_head = timer->next; + if (timer_head) + timer_head->prev = NULL; - if (timer->flags & TIMER_SPLIT) - timer_advance_ex(timer, 0); /* We're splitting a > 1 s period into multiple <= 1 s periods. */ - else if (timer->callback != NULL) /* Make sure it's no NULL, so that we can have a NULL callback when no operation is needed. */ - timer->callback(timer->p); + timer->next = timer->prev = NULL; + timer->flags &= ~TIMER_ENABLED; + + if (timer->flags & TIMER_SPLIT) + timer_advance_ex(timer, 0); /* We're splitting a > 1 s period into + multiple <= 1 s periods. */ + else if (timer->callback != NULL) /* Make sure it's not NULL, so that we can + have a NULL callback when no operation + is needed. */ + timer->callback(timer->priv); } timer_target = timer_head->ts.ts32.integer; } - void timer_close(void) { - pc_timer_t *t = timer_head, *r; + pc_timer_t *t = timer_head; + pc_timer_t *r; /* Set all timers' prev and next to NULL so it is assured that timers that are not in malloc'd structs don't keep pointing to timers that may be in malloc'd structs. */ while (t != NULL) { - r = t; - r->prev = r->next = NULL; - t = r->next; + r = t; + r->prev = r->next = NULL; + t = r->next; } timer_head = NULL; @@ -157,97 +157,90 @@ timer_close(void) timer_inited = 0; } - void timer_init(void) { timer_target = 0ULL; - tsc = 0; + tsc = 0; timer_inited = 1; } - void -timer_add(pc_timer_t *timer, void (*callback)(void *p), void *p, int start_timer) +timer_add(pc_timer_t *timer, void (*callback)(void *priv), void *priv, int start_timer) { memset(timer, 0, sizeof(pc_timer_t)); timer->callback = callback; - timer->p = p; - timer->flags = 0; + timer->priv = priv; + timer->flags = 0; timer->prev = timer->next = NULL; if (start_timer) - timer_set_delay_u64(timer, 0); + timer_set_delay_u64(timer, 0); } - /* The API for big timer periods starts here. */ void timer_stop(pc_timer_t *timer) { if (!timer_inited || (timer == NULL)) - return; + return; timer->period = 0.0; timer_disable(timer); timer->flags &= ~TIMER_SPLIT; } - static void timer_do_period(pc_timer_t *timer, uint64_t period, int start) { if (!timer_inited || (timer == NULL)) - return; + return; if (start) - timer_set_delay_u64(timer, period); + timer_set_delay_u64(timer, period); else - timer_advance_u64(timer, period); + timer_advance_u64(timer, period); } - -void +static void timer_advance_ex(pc_timer_t *timer, int start) { if (!timer_inited || (timer == NULL)) - return; + return; if (timer->period > MAX_USEC) { - timer_do_period(timer, MAX_USEC64 * TIMER_USEC, start); - timer->period -= MAX_USEC; - timer->flags |= TIMER_SPLIT; + timer_do_period(timer, MAX_USEC64 * TIMER_USEC, start); + timer->period -= MAX_USEC; + timer->flags |= TIMER_SPLIT; } else { - if (timer->period > 0.0) - timer_do_period(timer, (uint64_t) (timer->period * ((double) TIMER_USEC)), start); - else - timer_disable(timer); - timer->period = 0.0; - timer->flags &= ~TIMER_SPLIT; + if (timer->period > 0.0) + timer_do_period(timer, (uint64_t) (timer->period * ((double) TIMER_USEC)), start); + else + timer_disable(timer); + timer->period = 0.0; + timer->flags &= ~TIMER_SPLIT; } } - -void +static void timer_on(pc_timer_t *timer, double period, int start) { if (!timer_inited || (timer == NULL)) - return; + return; timer->period = period; timer_advance_ex(timer, start); } - void timer_on_auto(pc_timer_t *timer, double period) { if (!timer_inited || (timer == NULL)) - return; + return; if (period > 0.0) - timer_on(timer, period, (timer->period == 0.0)); + timer_on(timer, period, timer->period <= 0.0); else - timer_stop(timer); + timer_stop(timer); } diff --git a/src/unix/CMakeLists.txt b/src/unix/CMakeLists.txt index ca0a6a6e4..43c730315 100644 --- a/src/unix/CMakeLists.txt +++ b/src/unix/CMakeLists.txt @@ -1,21 +1,23 @@ # -# 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. +# 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. +# This file is part of the 86Box distribution. # -# CMake build script. +# CMake build script. # -# Authors: Cacodemon345 -# David HrdliÄka, +# Authors: Cacodemon345 +# David HrdliÄka, # -# Copyright 2021 Cacodemon345. -# Copyright 2021 David HrdliÄka. +# Copyright 2021 Cacodemon345. +# Copyright 2021 David HrdliÄka. +# Copyright 2021 Andreas J. Reichel. +# Copyright 2021-2022 Jasmine Iwanek. # -add_library(plat OBJECT unix.c) +add_library(plat OBJECT unix.c unix_serial_passthrough.c) if (NOT CPPTHREADS) target_sources(plat PRIVATE unix_thread.c) @@ -27,4 +29,8 @@ target_link_libraries(86Box Threads::Threads) add_library(ui OBJECT unix_sdl.c unix_cdrom.c) target_compile_definitions(ui PUBLIC _FILE_OFFSET_BITS=64) -target_link_libraries(ui dl) +target_link_libraries(ui ${CMAKE_DL_LIBS}) + +if(APPLE) + target_sources(plat PRIVATE macOSXGlue.m) +endif() diff --git a/src/unix/assets/128x128/net.86box.86Box.png b/src/unix/assets/128x128/net.86box.86Box.png new file mode 100644 index 000000000..bf521d3ec Binary files /dev/null and b/src/unix/assets/128x128/net.86box.86Box.png differ diff --git a/src/unix/assets/192x192/net.86box.86Box.png b/src/unix/assets/192x192/net.86box.86Box.png new file mode 100644 index 000000000..4bed7df13 Binary files /dev/null and b/src/unix/assets/192x192/net.86box.86Box.png differ diff --git a/src/unix/assets/256x256/net.86box.86Box.png b/src/unix/assets/256x256/net.86box.86Box.png new file mode 100644 index 000000000..4ef8b2120 Binary files /dev/null and b/src/unix/assets/256x256/net.86box.86Box.png differ diff --git a/src/unix/assets/48x48/net.86box.86Box.png b/src/unix/assets/48x48/net.86box.86Box.png new file mode 100644 index 000000000..75411ba16 Binary files /dev/null and b/src/unix/assets/48x48/net.86box.86Box.png differ diff --git a/src/unix/assets/512x512/net.86box.86Box.png b/src/unix/assets/512x512/net.86box.86Box.png new file mode 100644 index 000000000..2fef558d6 Binary files /dev/null and b/src/unix/assets/512x512/net.86box.86Box.png differ diff --git a/src/unix/assets/64x64/net.86box.86Box.png b/src/unix/assets/64x64/net.86box.86Box.png new file mode 100644 index 000000000..24d668e0c Binary files /dev/null and b/src/unix/assets/64x64/net.86box.86Box.png differ diff --git a/src/unix/assets/72x72/net.86box.86Box.png b/src/unix/assets/72x72/net.86box.86Box.png new file mode 100644 index 000000000..e01c47829 Binary files /dev/null and b/src/unix/assets/72x72/net.86box.86Box.png differ diff --git a/src/unix/assets/86Box.spec b/src/unix/assets/86Box.spec new file mode 100644 index 000000000..60e23d93c --- /dev/null +++ b/src/unix/assets/86Box.spec @@ -0,0 +1,125 @@ +# Fedora RPM spec file for 86Box including roms +# +# To create RPM files from this spec file, run the following commands: +# sudo dnf install rpm-build +# mkdir -p ~/rpmbuild/{BUILD,RPMS,SOURCES,SPECS,SRPMS} +# +# copy this 86Box.spec file to ~/rpmbuild/SPECS and run the following commands: +# cd ~/rpmbuild +# sudo dnf builddep SPECS/86Box.spec +# rpmbuild --undefine=_disable_source_fetch -ba SPECS/86Box.spec +# +# After a successful build, you can install the RPMs as follows: +# sudo dnf install RPMS/$(uname -m)/86Box-3* RPMS/noarch/86Box-roms* + +%global romver 4.0.1 + +Name: 86Box +Version: 4.0.2 +Release: 1%{?dist} +Summary: Classic PC emulator +License: GPLv2+ +URL: https://86box.net + +Source0: https://github.com/86Box/86Box/archive/refs/tags/v%{version}.tar.gz +Source1: https://github.com/86Box/roms/archive/refs/tags/v%{romver}.zip + +BuildRequires: cmake +BuildRequires: desktop-file-utils +BuildRequires: extra-cmake-modules +BuildRequires: fluidsynth-devel +BuildRequires: freetype-devel +BuildRequires: gcc-c++ +BuildRequires: libFAudio-devel +BuildRequires: libappstream-glib +BuildRequires: libatomic +BuildRequires: libevdev-devel +BuildRequires: libslirp-devel +BuildRequires: libxkbcommon-x11-devel +BuildRequires: libXi-devel +BuildRequires: ninja-build +BuildRequires: openal-soft-devel +BuildRequires: qt5-linguist +BuildRequires: qt5-qtconfiguration-devel +BuildRequires: qt5-qtbase-private-devel +BuildRequires: qt5-qtbase-static +BuildRequires: rtmidi-devel +BuildRequires: wayland-devel +BuildRequires: SDL2-devel + +Requires: hicolor-icon-theme +Requires: fluid-soundfont-gm +Requires: 86Box-roms + +%description +86Box is 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. + +It supports various models of PCs, graphics and sound cards, and CPUs. + +%package roms +Summary: ROMs for use with 86Box +Version: %{romver} +License: Proprietary +BuildArch: noarch + +%description roms +Collection of ROMs for use with 86Box. + +%prep +%autosetup -p1 -a1 + +%build +%ifarch i386 x86_64 + %cmake -DRELEASE=on +%else + %ifarch arm aarch64 + %cmake -DRELEASE=on -DNEW_DYNAREC=on + %else + %cmake -DRELEASE=on -DDYNAREC=off + %endif +%endif +%cmake_build + +%install +# install base package +%cmake_install + +# install icons +for i in 48 64 72 96 128 192 256 512; do + mkdir -p $RPM_BUILD_ROOT%{_datadir}/icons/hicolor/${i}x${i}/apps + cp src/unix/assets/${i}x${i}/net.86box.86Box.png $RPM_BUILD_ROOT%{_datadir}/icons/hicolor/${i}x${i}/apps +done + +# install desktop file +desktop-file-install --dir=%{buildroot}%{_datadir}/applications src/unix/assets/net.86box.86Box.desktop + +# install metadata +mkdir -p %{buildroot}%{_metainfodir} +cp src/unix/assets/net.86box.86Box.metainfo.xml %{buildroot}%{_metainfodir} +appstream-util validate-relax --nonet %{buildroot}%{_metainfodir}/net.86box.86Box.metainfo.xml + +# install roms +pushd roms-%{romver} + mkdir -p %{buildroot}%{_datadir}/%{name}/roms + cp -a * %{buildroot}%{_datadir}/%{name}/roms/ +popd + +# files part of the main package +%files +%license COPYING +%{_bindir}/86Box +%{_datadir}/applications/net.86box.86Box.desktop +%{_metainfodir}/net.86box.86Box.metainfo.xml +%{_datadir}/icons/hicolor/*/apps/net.86box.86Box.png + +# files part of the rom package +%files roms +%license roms-%{romver}/LICENSE +%{_datadir}/%{name}/roms + +%changelog +* Mon Oct 16 2023 Robert de Rooy 4.0.2-1 +- Bump release diff --git a/src/unix/assets/96x96/net.86box.86Box.png b/src/unix/assets/96x96/net.86box.86Box.png new file mode 100644 index 000000000..ee24db6ea Binary files /dev/null and b/src/unix/assets/96x96/net.86box.86Box.png differ diff --git a/src/unix/assets/net.86box.86Box.desktop b/src/unix/assets/net.86box.86Box.desktop new file mode 100644 index 000000000..83d20b9e7 --- /dev/null +++ b/src/unix/assets/net.86box.86Box.desktop @@ -0,0 +1,9 @@ +[Desktop Entry] +Name=86Box +GenericName=Classic PC emulator +Comment=An emulator for classic IBM PC clones +Exec=86Box +Icon=net.86box.86Box +Terminal=false +Type=Application +Categories=System;Emulator; diff --git a/src/unix/assets/net.86box.86Box.metainfo.xml b/src/unix/assets/net.86box.86Box.metainfo.xml new file mode 100644 index 000000000..ce4e8e430 --- /dev/null +++ b/src/unix/assets/net.86box.86Box.metainfo.xml @@ -0,0 +1,37 @@ + + + net.86box.86Box + CC0-1.0 + GPL-2.0-or-later + 86Box + An emulator for classic IBM PC clones + + Emulation + + net.86box.86Box.desktop + + + + + +

+ 86Box is 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. + + It supports various models of PCs, graphics and sound + cards, and CPUs. +

+

+ To use 86Box you will need to dump BIOS ROMs for each machine you + want to emulate. +

+
+ + + https://raw.githubusercontent.com/86Box/86Box/master/src/unix/assets/screenshots/86Box.png + + + https://86box.net +
diff --git a/src/unix/assets/screenshots/86Box.png b/src/unix/assets/screenshots/86Box.png new file mode 100644 index 000000000..5f72485f3 Binary files /dev/null and b/src/unix/assets/screenshots/86Box.png differ diff --git a/src/mac/macOSXGlue.h b/src/unix/macOSXGlue.h similarity index 87% rename from src/mac/macOSXGlue.h rename to src/unix/macOSXGlue.h index cd3a880bd..44bf9e7f6 100644 --- a/src/mac/macOSXGlue.h +++ b/src/unix/macOSXGlue.h @@ -13,11 +13,10 @@ CF_IMPLICIT_BRIDGING_ENABLED CF_EXTERN_C_BEGIN -void getDefaultROMPath(char*); -int toto(); +void getDefaultROMPath(char *); +int toto(void); CF_EXTERN_C_END CF_IMPLICIT_BRIDGING_DISABLED - #endif /* macOSXGlue_h */ diff --git a/src/unix/macOSXGlue.m b/src/unix/macOSXGlue.m new file mode 100644 index 000000000..95deb545d --- /dev/null +++ b/src/unix/macOSXGlue.m @@ -0,0 +1,46 @@ +// +// macOSXGlue.m +// 86BOx MacoSx Glue.... +// Todo: so much +// Created by Jerome Vernet on 18/11/2021. +// Copyright © 2021 Jerome Vernet. All rights reserved. +// + +#import + +void +getDefaultROMPath(char *Path) +{ + NSFileManager *sharedFM = [NSFileManager defaultManager]; + NSArray *possibleURLs = [sharedFM URLsForDirectory:NSApplicationSupportDirectory + inDomains:NSUserDomainMask]; + NSURL *appSupportDir = nil; + NSURL *appDirectory = nil; + + if ([possibleURLs count] >= 1) { + // Use the first directory (if multiple are returned) + appSupportDir = [possibleURLs objectAtIndex:0]; + } + + // If a valid app support directory exists, add the + // app's bundle ID to it to specify the final directory. + if (appSupportDir) { + NSString *appBundleID = [[NSBundle mainBundle] bundleIdentifier]; + appDirectory = [appSupportDir URLByAppendingPathComponent:appBundleID]; + appDirectory = [appDirectory URLByAppendingPathComponent:@"roms"]; + } + // create ~/Library/Application Support/... stuff + + NSError *theError = nil; + if (![sharedFM createDirectoryAtURL:appDirectory + withIntermediateDirectories:YES + attributes:nil + error:&theError]) { + // Handle the error. + NSLog(@"Error creating user library rom path"); + } else + NSLog(@"Create user rom path sucessfull"); + + strcpy(Path, [appDirectory fileSystemRepresentation]); + // return appDirectory; +} diff --git a/src/unix/unix.c b/src/unix/unix.c index 11f00b786..ecd17cadb 100644 --- a/src/unix/unix.c +++ b/src/unix/unix.c @@ -1,6 +1,6 @@ #ifdef __linux__ -#define _FILE_OFFSET_BITS 64 -#define _LARGEFILE64_SOURCE 1 +# define _FILE_OFFSET_BITS 64 +# define _LARGEFILE64_SOURCE 1 #endif #include #include @@ -18,192 +18,206 @@ #include #include #include +#include #include +#ifdef __APPLE__ +# include "macOSXGlue.h" +#endif + #include <86box/86box.h> +#include <86box/mem.h> +#include <86box/rom.h> #include <86box/keyboard.h> #include <86box/mouse.h> #include <86box/config.h> +#include <86box/path.h> #include <86box/plat.h> #include <86box/plat_dynld.h> +#include <86box/thread.h> #include <86box/device.h> #include <86box/gameport.h> #include <86box/unix_sdl.h> #include <86box/timer.h> #include <86box/nvr.h> +#include <86box/version.h> +#include <86box/video.h> #include <86box/ui.h> +#include <86box/gdbstub.h> -static int first_use = 1; -static uint64_t StartingTime; +static int first_use = 1; +static uint64_t StartingTime; static uint64_t Frequency; -int rctrl_is_lalt; -int update_icons; -int kbd_req_capture; -int hide_status_bar; -int hide_tool_bar; -int fixed_size_x = 640; -int fixed_size_y = 480; -extern int title_set; -extern wchar_t sdl_win_title[512]; -plat_joystick_t plat_joystick_state[MAX_PLAT_JOYSTICKS]; -joystick_t joystick_state[MAX_JOYSTICKS]; -int joysticks_present; -int status_icons_fullscreen = 0; /* unused. */ -SDL_mutex *blitmtx; -SDL_threadID eventthread; -static int exit_event = 0; -static int fullscreen_pending = 0; -uint32_t lang_id = 0x0409, lang_sys = 0x0409; // Multilangual UI variables, for now all set to LCID of en-US -char icon_set[256] = ""; /* name of the iconset to be used */ +int rctrl_is_lalt; +int update_icons; +int kbd_req_capture; +int hide_status_bar; +int hide_tool_bar; +int fixed_size_x = 640; +int fixed_size_y = 480; +extern int title_set; +extern wchar_t sdl_win_title[512]; +plat_joystick_t plat_joystick_state[MAX_PLAT_JOYSTICKS]; +joystick_t joystick_state[MAX_JOYSTICKS]; +int joysticks_present; +int status_icons_fullscreen = 0; /* unused. */ +SDL_mutex *blitmtx; +SDL_threadID eventthread; +static int exit_event = 0; +static int fullscreen_pending = 0; +uint32_t lang_id = 0x0409; // Multilangual UI variables, for now all set to LCID of en-US +uint32_t lang_sys = 0x0409; // Multilangual UI variables, for now all set to LCID of en-US +char icon_set[256] = ""; /* name of the iconset to be used */ -static const uint16_t sdl_to_xt[0x200] = -{ - [SDL_SCANCODE_ESCAPE] = 0x01, - [SDL_SCANCODE_1] = 0x02, - [SDL_SCANCODE_2] = 0x03, - [SDL_SCANCODE_3] = 0x04, - [SDL_SCANCODE_4] = 0x05, - [SDL_SCANCODE_5] = 0x06, - [SDL_SCANCODE_6] = 0x07, - [SDL_SCANCODE_7] = 0x08, - [SDL_SCANCODE_8] = 0x09, - [SDL_SCANCODE_9] = 0x0A, - [SDL_SCANCODE_0] = 0x0B, - [SDL_SCANCODE_MINUS] = 0x0C, - [SDL_SCANCODE_EQUALS] = 0x0D, - [SDL_SCANCODE_BACKSPACE] = 0x0E, - [SDL_SCANCODE_TAB] = 0x0F, - [SDL_SCANCODE_Q] = 0x10, - [SDL_SCANCODE_W] = 0x11, - [SDL_SCANCODE_E] = 0x12, - [SDL_SCANCODE_R] = 0x13, - [SDL_SCANCODE_T] = 0x14, - [SDL_SCANCODE_Y] = 0x15, - [SDL_SCANCODE_U] = 0x16, - [SDL_SCANCODE_I] = 0x17, - [SDL_SCANCODE_O] = 0x18, - [SDL_SCANCODE_P] = 0x19, - [SDL_SCANCODE_LEFTBRACKET] = 0x1A, +static const uint16_t sdl_to_xt[0x200] = { + [SDL_SCANCODE_ESCAPE] = 0x01, + [SDL_SCANCODE_1] = 0x02, + [SDL_SCANCODE_2] = 0x03, + [SDL_SCANCODE_3] = 0x04, + [SDL_SCANCODE_4] = 0x05, + [SDL_SCANCODE_5] = 0x06, + [SDL_SCANCODE_6] = 0x07, + [SDL_SCANCODE_7] = 0x08, + [SDL_SCANCODE_8] = 0x09, + [SDL_SCANCODE_9] = 0x0A, + [SDL_SCANCODE_0] = 0x0B, + [SDL_SCANCODE_MINUS] = 0x0C, + [SDL_SCANCODE_EQUALS] = 0x0D, + [SDL_SCANCODE_BACKSPACE] = 0x0E, + [SDL_SCANCODE_TAB] = 0x0F, + [SDL_SCANCODE_Q] = 0x10, + [SDL_SCANCODE_W] = 0x11, + [SDL_SCANCODE_E] = 0x12, + [SDL_SCANCODE_R] = 0x13, + [SDL_SCANCODE_T] = 0x14, + [SDL_SCANCODE_Y] = 0x15, + [SDL_SCANCODE_U] = 0x16, + [SDL_SCANCODE_I] = 0x17, + [SDL_SCANCODE_O] = 0x18, + [SDL_SCANCODE_P] = 0x19, + [SDL_SCANCODE_LEFTBRACKET] = 0x1A, [SDL_SCANCODE_RIGHTBRACKET] = 0x1B, - [SDL_SCANCODE_RETURN] = 0x1C, - [SDL_SCANCODE_LCTRL] = 0x1D, - [SDL_SCANCODE_A] = 0x1E, - [SDL_SCANCODE_S] = 0x1F, - [SDL_SCANCODE_D] = 0x20, - [SDL_SCANCODE_F] = 0x21, - [SDL_SCANCODE_G] = 0x22, - [SDL_SCANCODE_H] = 0x23, - [SDL_SCANCODE_J] = 0x24, - [SDL_SCANCODE_K] = 0x25, - [SDL_SCANCODE_L] = 0x26, - [SDL_SCANCODE_SEMICOLON] = 0x27, - [SDL_SCANCODE_APOSTROPHE] = 0x28, - [SDL_SCANCODE_GRAVE] = 0x29, - [SDL_SCANCODE_LSHIFT] = 0x2A, - [SDL_SCANCODE_BACKSLASH] = 0x2B, - [SDL_SCANCODE_Z] = 0x2C, - [SDL_SCANCODE_X] = 0x2D, - [SDL_SCANCODE_C] = 0x2E, - [SDL_SCANCODE_V] = 0x2F, - [SDL_SCANCODE_B] = 0x30, - [SDL_SCANCODE_N] = 0x31, - [SDL_SCANCODE_M] = 0x32, - [SDL_SCANCODE_COMMA] = 0x33, - [SDL_SCANCODE_PERIOD] = 0x34, - [SDL_SCANCODE_SLASH] = 0x35, - [SDL_SCANCODE_RSHIFT] = 0x36, - [SDL_SCANCODE_KP_MULTIPLY] = 0x37, - [SDL_SCANCODE_LALT] = 0x38, - [SDL_SCANCODE_SPACE] = 0x39, - [SDL_SCANCODE_CAPSLOCK] = 0x3A, - [SDL_SCANCODE_F1] = 0x3B, - [SDL_SCANCODE_F2] = 0x3C, - [SDL_SCANCODE_F3] = 0x3D, - [SDL_SCANCODE_F4] = 0x3E, - [SDL_SCANCODE_F5] = 0x3F, - [SDL_SCANCODE_F6] = 0x40, - [SDL_SCANCODE_F7] = 0x41, - [SDL_SCANCODE_F8] = 0x42, - [SDL_SCANCODE_F9] = 0x43, - [SDL_SCANCODE_F10] = 0x44, + [SDL_SCANCODE_RETURN] = 0x1C, + [SDL_SCANCODE_LCTRL] = 0x1D, + [SDL_SCANCODE_A] = 0x1E, + [SDL_SCANCODE_S] = 0x1F, + [SDL_SCANCODE_D] = 0x20, + [SDL_SCANCODE_F] = 0x21, + [SDL_SCANCODE_G] = 0x22, + [SDL_SCANCODE_H] = 0x23, + [SDL_SCANCODE_J] = 0x24, + [SDL_SCANCODE_K] = 0x25, + [SDL_SCANCODE_L] = 0x26, + [SDL_SCANCODE_SEMICOLON] = 0x27, + [SDL_SCANCODE_APOSTROPHE] = 0x28, + [SDL_SCANCODE_GRAVE] = 0x29, + [SDL_SCANCODE_LSHIFT] = 0x2A, + [SDL_SCANCODE_BACKSLASH] = 0x2B, + [SDL_SCANCODE_Z] = 0x2C, + [SDL_SCANCODE_X] = 0x2D, + [SDL_SCANCODE_C] = 0x2E, + [SDL_SCANCODE_V] = 0x2F, + [SDL_SCANCODE_B] = 0x30, + [SDL_SCANCODE_N] = 0x31, + [SDL_SCANCODE_M] = 0x32, + [SDL_SCANCODE_COMMA] = 0x33, + [SDL_SCANCODE_PERIOD] = 0x34, + [SDL_SCANCODE_SLASH] = 0x35, + [SDL_SCANCODE_RSHIFT] = 0x36, + [SDL_SCANCODE_KP_MULTIPLY] = 0x37, + [SDL_SCANCODE_LALT] = 0x38, + [SDL_SCANCODE_SPACE] = 0x39, + [SDL_SCANCODE_CAPSLOCK] = 0x3A, + [SDL_SCANCODE_F1] = 0x3B, + [SDL_SCANCODE_F2] = 0x3C, + [SDL_SCANCODE_F3] = 0x3D, + [SDL_SCANCODE_F4] = 0x3E, + [SDL_SCANCODE_F5] = 0x3F, + [SDL_SCANCODE_F6] = 0x40, + [SDL_SCANCODE_F7] = 0x41, + [SDL_SCANCODE_F8] = 0x42, + [SDL_SCANCODE_F9] = 0x43, + [SDL_SCANCODE_F10] = 0x44, [SDL_SCANCODE_NUMLOCKCLEAR] = 0x45, - [SDL_SCANCODE_SCROLLLOCK] = 0x46, - [SDL_SCANCODE_HOME] = 0x147, - [SDL_SCANCODE_UP] = 0x148, - [SDL_SCANCODE_PAGEUP] = 0x149, - [SDL_SCANCODE_KP_MINUS] = 0x4A, - [SDL_SCANCODE_LEFT] = 0x14B, - [SDL_SCANCODE_KP_5] = 0x4C, - [SDL_SCANCODE_RIGHT] = 0x14D, - [SDL_SCANCODE_KP_PLUS] = 0x4E, - [SDL_SCANCODE_END] = 0x14F, - [SDL_SCANCODE_DOWN] = 0x150, - [SDL_SCANCODE_PAGEDOWN] = 0x151, - [SDL_SCANCODE_INSERT] = 0x152, - [SDL_SCANCODE_DELETE] = 0x153, - [SDL_SCANCODE_F11] = 0x57, - [SDL_SCANCODE_F12] = 0x58, + [SDL_SCANCODE_SCROLLLOCK] = 0x46, + [SDL_SCANCODE_HOME] = 0x147, + [SDL_SCANCODE_UP] = 0x148, + [SDL_SCANCODE_PAGEUP] = 0x149, + [SDL_SCANCODE_KP_MINUS] = 0x4A, + [SDL_SCANCODE_LEFT] = 0x14B, + [SDL_SCANCODE_KP_5] = 0x4C, + [SDL_SCANCODE_RIGHT] = 0x14D, + [SDL_SCANCODE_KP_PLUS] = 0x4E, + [SDL_SCANCODE_END] = 0x14F, + [SDL_SCANCODE_DOWN] = 0x150, + [SDL_SCANCODE_PAGEDOWN] = 0x151, + [SDL_SCANCODE_INSERT] = 0x152, + [SDL_SCANCODE_DELETE] = 0x153, + [SDL_SCANCODE_F11] = 0x57, + [SDL_SCANCODE_F12] = 0x58, - [SDL_SCANCODE_KP_ENTER] = 0x11c, - [SDL_SCANCODE_RCTRL] = 0x11d, + [SDL_SCANCODE_KP_ENTER] = 0x11c, + [SDL_SCANCODE_RCTRL] = 0x11d, [SDL_SCANCODE_KP_DIVIDE] = 0x135, - [SDL_SCANCODE_RALT] = 0x138, - [SDL_SCANCODE_KP_9] = 0x49, - [SDL_SCANCODE_KP_8] = 0x48, - [SDL_SCANCODE_KP_7] = 0x47, - [SDL_SCANCODE_KP_6] = 0x4D, - [SDL_SCANCODE_KP_4] = 0x4B, - [SDL_SCANCODE_KP_3] = 0x51, - [SDL_SCANCODE_KP_2] = 0x50, - [SDL_SCANCODE_KP_1] = 0x4F, - [SDL_SCANCODE_KP_0] = 0x52, + [SDL_SCANCODE_RALT] = 0x138, + [SDL_SCANCODE_KP_9] = 0x49, + [SDL_SCANCODE_KP_8] = 0x48, + [SDL_SCANCODE_KP_7] = 0x47, + [SDL_SCANCODE_KP_6] = 0x4D, + [SDL_SCANCODE_KP_4] = 0x4B, + [SDL_SCANCODE_KP_3] = 0x51, + [SDL_SCANCODE_KP_2] = 0x50, + [SDL_SCANCODE_KP_1] = 0x4F, + [SDL_SCANCODE_KP_0] = 0x52, [SDL_SCANCODE_KP_PERIOD] = 0x53, - [SDL_SCANCODE_LGUI] = 0x15B, - [SDL_SCANCODE_RGUI] = 0x15C, + [SDL_SCANCODE_LGUI] = 0x15B, + [SDL_SCANCODE_RGUI] = 0x15C, [SDL_SCANCODE_APPLICATION] = 0x15D, [SDL_SCANCODE_PRINTSCREEN] = 0x137 }; -typedef struct sdl_blit_params -{ - int x, y, w, h; +typedef struct sdl_blit_params { + int x; + int y; + int w; + int h; } sdl_blit_params; -sdl_blit_params params = { 0, 0, 0, 0 }; -int blitreq = 0; +sdl_blit_params params = { 0, 0, 0, 0 }; +int blitreq = 0; -void* dynld_module(const char *name, dllimp_t *table) +void * +dynld_module(const char *name, dllimp_t *table) { - dllimp_t* imp; - void* modhandle = dlopen(name, RTLD_LAZY | RTLD_GLOBAL); - if (modhandle) - { - for (imp = table; imp->name != NULL; imp++) - { - if ((*(void**)imp->func = dlsym(modhandle, imp->name)) == NULL) - { + dllimp_t *imp; + void *modhandle = dlopen(name, RTLD_LAZY | RTLD_GLOBAL); + + if (modhandle) { + for (imp = table; imp->name != NULL; imp++) { + if ((*(void **) imp->func = dlsym(modhandle, imp->name)) == NULL) { dlclose(modhandle); return NULL; } } } + return modhandle; } void plat_tempfile(char *bufp, char *prefix, char *suffix) { - struct tm* calendertime; + struct tm *calendertime; struct timeval t; - time_t curtime; + time_t curtime; if (prefix != NULL) - sprintf(bufp, "%s-", prefix); - else - strcpy(bufp, ""); + sprintf(bufp, "%s-", prefix); + else + strcpy(bufp, ""); gettimeofday(&t, NULL); - curtime = time(NULL); + curtime = time(NULL); calendertime = localtime(&curtime); sprintf(&bufp[strlen(bufp)], "%d%02d%02d-%02d%02d%02d-%03ld%s", calendertime->tm_year, calendertime->tm_mon, calendertime->tm_mday, calendertime->tm_hour, calendertime->tm_min, calendertime->tm_sec, t.tv_usec / 1000, suffix); } @@ -215,52 +229,53 @@ plat_getcwd(char *bufp, int max) } int -plat_chdir(char* str) +plat_chdir(char *str) { return chdir(str); } -void dynld_close(void *handle) +void +dynld_close(void *handle) { - dlclose(handle); + dlclose(handle); } -wchar_t* plat_get_string(int i) +wchar_t * +plat_get_string(int i) { - switch (i) - { + switch (i) { case IDS_2077: - return L"Click to capture mouse."; + return L"Click to capture mouse"; case IDS_2078: return L"Press CTRL-END to release mouse"; case IDS_2079: return L"Press CTRL-END or middle button to release mouse"; - case IDS_2080: - return L"Failed to initialize FluidSynth"; + case IDS_2131: + return L"Invalid configuration"; case IDS_4099: return L"MFM/RLL or ESDI CD-ROM drives never existed"; - case IDS_2093: - return L"Failed to set up PCap"; case IDS_2094: + return L"Failed to set up PCap"; + case IDS_2095: return L"No PCap devices found"; - case IDS_2110: - return L"Unable to initialize FreeType"; - case IDS_2111: + case IDS_2096: + return L"Invalid PCap device"; + case IDS_2112: return L"Unable to initialize SDL, libsdl2 is required"; - case IDS_2131: - return L"libfreetype is required for ESC/P printer emulation."; - case IDS_2132: + case IDS_2133: return L"libgs is required for automatic conversion of PostScript files to PDF.\n\nAny documents sent to the generic PostScript printer will be saved as PostScript (.ps) files."; - case IDS_2129: + case IDS_2130: return L"Make sure libpcap is installed and that you are on a libpcap-compatible network connection."; - case IDS_2114: + case IDS_2115: return L"Unable to initialize Ghostscript"; case IDS_2063: return L"Machine \"%hs\" is not available due to missing ROMs in the roms/machines directory. Switching to an available machine."; case IDS_2064: return L"Video card \"%hs\" is not available due to missing ROMs in the roms/video directory. Switching to an available video card."; - case IDS_2128: + case IDS_2129: return L"Hardware not available"; + case IDS_2143: + return L"Monitor in sleep mode"; } return L""; } @@ -278,17 +293,35 @@ plat_fopen64(const char *path, const char *mode) } int -plat_path_abs(char *path) +path_abs(char *path) { return path[0] == '/'; } void -plat_path_slash(char *path) +path_normalize(char *path) { - if ((path[strlen(path)-1] != '/')) { - strcat(path, "/"); + /* No-op. */ +} + +void +path_slash(char *path) +{ + if (path[strlen(path) - 1] != '/') { + strcat(path, "/"); } + path_normalize(path); +} + +const char * +path_get_slash(char *path) +{ + char *ret = ""; + + if (path[strlen(path) - 1] != '/') + ret = "/"; + + return ret; } void @@ -297,61 +330,59 @@ plat_put_backslash(char *s) int c = strlen(s) - 1; if (s[c] != '/') - s[c] = '/'; + s[c] = '/'; } /* Return the last element of a pathname. */ char * plat_get_basename(const char *path) { - int c = (int)strlen(path); + int c = (int) strlen(path); while (c > 0) { - if (path[c] == '/') - return((char *)&path[c + 1]); - c--; + if (path[c] == '/') + return ((char *) &path[c + 1]); + c--; } - return((char *)path); + return ((char *) path); } char * -plat_get_filename(char *s) +path_get_filename(char *s) { int c = strlen(s) - 1; while (c > 0) { - if (s[c] == '/' || s[c] == '\\') - return(&s[c+1]); - c--; + if (s[c] == '/' || s[c] == '\\') + return (&s[c + 1]); + c--; } - return(s); + return s; } - char * -plat_get_extension(char *s) +path_get_extension(char *s) { int c = strlen(s) - 1; if (c <= 0) - return(s); + return s; while (c && s[c] != '.') - c--; + c--; if (!c) - return(&s[strlen(s)]); + return (&s[strlen(s)]); - return(&s[c+1]); + return (&s[c + 1]); } - void -plat_append_filename(char *dest, const char *s1, const char *s2) +path_append_filename(char *dest, const char *s1, const char *s2) { strcpy(dest, s1); - plat_path_slash(dest); + path_slash(dest); strcat(dest, s2); } @@ -359,8 +390,7 @@ int plat_dir_check(char *path) { struct stat dummy; - if (stat(path, &dummy) < 0) - { + if (stat(path, &dummy) < 0) { return 0; } return S_ISDIR(dummy.st_mode); @@ -398,30 +428,34 @@ plat_timer_read(void) static uint64_t plat_get_ticks_common(void) { - uint64_t EndingTime, ElapsedMicroseconds; + uint64_t EndingTime; + uint64_t ElapsedMicroseconds; + if (first_use) { - Frequency = SDL_GetPerformanceFrequency(); - StartingTime = SDL_GetPerformanceCounter(); - first_use = 0; + Frequency = SDL_GetPerformanceFrequency(); + StartingTime = SDL_GetPerformanceCounter(); + first_use = 0; } - EndingTime = SDL_GetPerformanceCounter(); + EndingTime = SDL_GetPerformanceCounter(); ElapsedMicroseconds = ((EndingTime - StartingTime) * 1000000) / Frequency; + return ElapsedMicroseconds; } uint32_t plat_get_ticks(void) { - return (uint32_t)(plat_get_ticks_common() / 1000); + return (uint32_t) (plat_get_ticks_common() / 1000); } uint32_t plat_get_micro_ticks(void) { - return (uint32_t)plat_get_ticks_common(); + return (uint32_t) plat_get_ticks_common(); } -void plat_remove(char* path) +void +plat_remove(char *path) { remove(path); } @@ -429,13 +463,13 @@ void plat_remove(char* path) void ui_sb_update_icon_state(int tag, int state) { - + /* No-op. */ } void ui_sb_update_icon(int tag, int active) { - + /* No-op. */ } void @@ -447,54 +481,55 @@ plat_delay_ms(uint32_t count) void ui_sb_update_tip(int arg) { - + /* No-op. */ } void -ui_sb_update_panes() +ui_sb_update_panes(void) { - + /* No-op. */ } void -ui_sb_update_text() +ui_sb_update_text(void) { - + /* No-op. */ } void -plat_get_dirname(char *dest, const char *path) +path_get_dirname(char *dest, const char *path) { - int c = (int)strlen(path); - char *ptr; - - ptr = (char *)path; + int c = (int) strlen(path); + char *ptr = (char *) path; while (c > 0) { - if (path[c] == '/' || path[c] == '\\') { - ptr = (char *)&path[c]; - break; - } - c--; + if (path[c] == '/' || path[c] == '\\') { + ptr = (char *) &path[c]; + break; + } + c--; } /* Copy to destination. */ while (path < ptr) - *dest++ = *path++; + *dest++ = *path++; *dest = '\0'; } volatile int cpu_thread_run = 1; -void ui_sb_set_text_w(wchar_t *wstr) +void +ui_sb_set_text_w(wchar_t *wstr) { - + /* No-op. */ } -int stricmp(const char* s1, const char* s2) +int +stricmp(const char *s1, const char *s2) { return strcasecmp(s1, s2); } -int strnicmp(const char *s1, const char *s2, size_t n) +int +strnicmp(const char *s1, const char *s2, size_t n) { return strncasecmp(s1, s2, n); } @@ -502,50 +537,58 @@ int strnicmp(const char *s1, const char *s2, size_t n) void main_thread(void *param) { - uint32_t old_time, new_time; - int drawits, frames; + uint32_t old_time; + uint32_t new_time; + int drawits; + int frames; SDL_SetThreadPriority(SDL_THREAD_PRIORITY_HIGH); framecountx = 0; - //title_update = 1; + // title_update = 1; old_time = SDL_GetTicks(); drawits = frames = 0; while (!is_quit && cpu_thread_run) { - /* See if it is time to run a frame of code. */ - new_time = SDL_GetTicks(); - drawits += (new_time - old_time); - old_time = new_time; - if (drawits > 0 && !dopause) { - /* Yes, so do one frame now. */ - drawits -= 10; - if (drawits > 50) - drawits = 0; + /* See if it is time to run a frame of code. */ + new_time = SDL_GetTicks(); +#ifdef USE_GDBSTUB + if (gdbstub_next_asap && (drawits <= 0)) + drawits = 10; + else +#endif + drawits += (new_time - old_time); + old_time = new_time; + if (drawits > 0 && !dopause) { + /* Yes, so do one frame now. */ + drawits -= 10; + if (drawits > 50) + drawits = 0; - /* Run a block of code. */ - pc_run(); + /* Run a block of code. */ + pc_run(); - /* Every 200 frames we save the machine status. */ - if (++frames >= 200 && nvr_dosave) { - nvr_save(); - nvr_dosave = 0; - frames = 0; - } - } else /* Just so we dont overload the host OS. */ - SDL_Delay(1); + /* Every 200 frames we save the machine status. */ + if (++frames >= 200 && nvr_dosave) { + nvr_save(); + nvr_dosave = 0; + frames = 0; + } + } else /* Just so we dont overload the host OS. */ + SDL_Delay(1); - /* If needed, handle a screen resize. */ - if (!atomic_flag_test_and_set(&doresize) && !video_fullscreen && !is_quit) { - if (vid_resize & 2) - plat_resize(fixed_size_x, fixed_size_y); - else - plat_resize(scrnsz_x, scrnsz_y); - } + /* If needed, handle a screen resize. */ + if (atomic_load(&doresize_monitors[0]) && !video_fullscreen && !is_quit) { + if (vid_resize & 2) + plat_resize(fixed_size_x, fixed_size_y); + else + plat_resize(scrnsz_x, scrnsz_y); + atomic_store(&doresize_monitors[0], 1); + } } is_quit = 1; } -thread_t* thMain = NULL; +thread_t *thMain = NULL; void do_start(void) @@ -564,24 +607,18 @@ do_start(void) void do_stop(void) { - if (SDL_ThreadID() != eventthread) - { + if (SDL_ThreadID() != eventthread) { exit_event = 1; return; } - if (blitreq) - { + if (blitreq) { blitreq = 0; - extern void video_blit_complete(); video_blit_complete(); } - while(SDL_TryLockMutex(blitmtx) == SDL_MUTEX_TIMEDOUT) - { - if (blitreq) - { + while (SDL_TryLockMutex(blitmtx) == SDL_MUTEX_TIMEDOUT) { + if (blitreq) { blitreq = 0; - extern void video_blit_complete(); video_blit_complete(); } } @@ -595,44 +632,53 @@ do_stop(void) thMain = NULL; } -int ui_msgbox(int flags, void *message) +int +ui_msgbox(int flags, void *message) { return ui_msgbox_header(flags, NULL, message); } -int ui_msgbox_header(int flags, void *header, void* message) +int +ui_msgbox_header(int flags, void *header, void *message) { - SDL_MessageBoxData msgdata; + SDL_MessageBoxData msgdata; SDL_MessageBoxButtonData msgbtn; - if (!header) header = (flags & MBX_ANSI) ? "86Box" : L"86Box"; - if (header <= (void*)7168) header = plat_get_string(header); - if (message <= (void*)7168) message = plat_get_string(message); + +#if 0 + if (!header) + header = (void *) (flags & MBX_ANSI) ? "86Box" : L"86Box"; +#endif + if (header <= (void *) 7168) + header = (void *) plat_get_string((uintptr_t) header); + if (message <= (void *) 7168) + message = (void *) plat_get_string((uintptr_t) message); + msgbtn.buttonid = 1; - msgbtn.text = "OK"; - msgbtn.flags = 0; + msgbtn.text = "OK"; + msgbtn.flags = 0; memset(&msgdata, 0, sizeof(SDL_MessageBoxData)); msgdata.numbuttons = 1; - msgdata.buttons = &msgbtn; - int msgflags = 0; - if (msgflags & MBX_FATAL) msgflags |= SDL_MESSAGEBOX_ERROR; - else if (msgflags & MBX_ERROR || msgflags & MBX_WARNING) msgflags |= SDL_MESSAGEBOX_WARNING; - else msgflags |= SDL_MESSAGEBOX_INFORMATION; + msgdata.buttons = &msgbtn; + int msgflags = 0; + if (msgflags & MBX_FATAL) + msgflags |= SDL_MESSAGEBOX_ERROR; + else if (msgflags & MBX_ERROR || msgflags & MBX_WARNING) + msgflags |= SDL_MESSAGEBOX_WARNING; + else + msgflags |= SDL_MESSAGEBOX_INFORMATION; msgdata.flags = msgflags; - if (flags & MBX_ANSI) - { - int button = 0; - msgdata.title = header; + if (flags & MBX_ANSI) { + int button = 0; + msgdata.title = header; msgdata.message = message; SDL_ShowMessageBox(&msgdata, &button); return button; - } - else - { - int button = 0; - char *res = SDL_iconv_string("UTF-8", sizeof(wchar_t) == 2 ? "UTF-16LE" : "UTF-32LE", (char *)message, wcslen(message) * sizeof(wchar_t) + sizeof(wchar_t)); - char *res2 = SDL_iconv_string("UTF-8", sizeof(wchar_t) == 2 ? "UTF-16LE" : "UTF-32LE", (char *)header, wcslen(header) * sizeof(wchar_t) + sizeof(wchar_t)); + } else { + int button = 0; + char *res = SDL_iconv_string("UTF-8", sizeof(wchar_t) == 2 ? "UTF-16LE" : "UTF-32LE", (char *) message, wcslen(message) * sizeof(wchar_t) + sizeof(wchar_t)); + char *res2 = SDL_iconv_string("UTF-8", sizeof(wchar_t) == 2 ? "UTF-16LE" : "UTF-32LE", (char *) header, wcslen(header) * sizeof(wchar_t) + sizeof(wchar_t)); msgdata.message = res; - msgdata.title = res2; + msgdata.title = res2; SDL_ShowMessageBox(&msgdata, &button); free(res); free(res2); @@ -642,9 +688,11 @@ int ui_msgbox_header(int flags, void *header, void* message) return 0; } -void plat_get_exe_name(char *s, int size) +void +plat_get_exe_name(char *s, int size) { - char* basepath = SDL_GetBasePath(); + char *basepath = SDL_GetBasePath(); + snprintf(s, size, "%s%s", basepath, basepath[strlen(basepath) - 1] == '/' ? "86box" : "/86box"); } @@ -662,167 +710,237 @@ plat_power_off(void) cpu_thread_run = 0; } -void ui_sb_bugui(char *str) +void +ui_sb_bugui(char *str) { - + /* No-op. */ } -extern void sdl_blit(int x, int y, int w, int h); +extern void sdl_blit(int x, int y, int w, int h); -typedef struct mouseinputdata -{ - int deltax, deltay, deltaz; +typedef struct mouseinputdata { + int deltax; + int deltay; + int deltaz; int mousebuttons; } mouseinputdata; -SDL_mutex* mousemutex; -static mouseinputdata mousedata; -void mouse_poll() + +SDL_mutex *mousemutex; +int real_sdl_w; +int real_sdl_h; + +void +ui_sb_set_ready(int ready) { - SDL_LockMutex(mousemutex); - mouse_x = mousedata.deltax; - mouse_y = mousedata.deltay; - mouse_z = mousedata.deltaz; - mousedata.deltax = mousedata.deltay = mousedata.deltaz = 0; - mouse_buttons = mousedata.mousebuttons; - SDL_UnlockMutex(mousemutex); + /* No-op. */ } - -int real_sdl_w, real_sdl_h; -void ui_sb_set_ready(int ready) {} -char* xargv[512]; +char *xargv[512]; // From musl. -char *local_strsep(char **str, const char *sep) +char * +local_strsep(char **str, const char *sep) { - char *s = *str, *end; - if (!s) return NULL; - end = s + strcspn(s, sep); - if (*end) *end++ = 0; - else end = 0; - *str = end; - return s; + char *s = *str; + char *end; + + if (!s) + return NULL; + end = s + strcspn(s, sep); + if (*end) + *end++ = 0; + else + end = 0; + *str = end; + + return s; } void plat_pause(int p) { static wchar_t oldtitle[512]; - wchar_t title[512]; + wchar_t title[512]; if ((p == 0) && (time_sync & TIME_SYNC_ENABLED)) - nvr_time_sync(); + nvr_time_sync(); dopause = p; if (p) { - wcsncpy(oldtitle, ui_window_title(NULL), sizeof_w(oldtitle) - 1); - wcscpy(title, oldtitle); - wcscat(title, L" - PAUSED"); - ui_window_title(title); + wcsncpy(oldtitle, ui_window_title(NULL), sizeof_w(oldtitle) - 1); + wcscpy(title, oldtitle); + wcscat(title, L" - PAUSED"); + ui_window_title(title); } else { - ui_window_title(oldtitle); + ui_window_title(oldtitle); } } -bool process_media_commands_3(uint8_t* id, char* fn, uint8_t* wp, int cmdargc) +void +plat_init_rom_paths(void) +{ +#ifndef __APPLE__ + if (getenv("XDG_DATA_HOME")) { + char xdg_rom_path[1024] = { 0 }; + + strncpy(xdg_rom_path, getenv("XDG_DATA_HOME"), 1024); + path_slash(xdg_rom_path); + strncat(xdg_rom_path, "86Box/", 1024); + + if (!plat_dir_check(xdg_rom_path)) + plat_dir_create(xdg_rom_path); + strcat(xdg_rom_path, "roms/"); + + if (!plat_dir_check(xdg_rom_path)) + plat_dir_create(xdg_rom_path); + rom_add_path(xdg_rom_path); + } else { + char home_rom_path[1024] = { 0 }; + + snprintf(home_rom_path, 1024, "%s/.local/share/86Box/", getenv("HOME") ? getenv("HOME") : getpwuid(getuid())->pw_dir); + + if (!plat_dir_check(home_rom_path)) + plat_dir_create(home_rom_path); + strcat(home_rom_path, "roms/"); + + if (!plat_dir_check(home_rom_path)) + plat_dir_create(home_rom_path); + rom_add_path(home_rom_path); + } + if (getenv("XDG_DATA_DIRS")) { + char *xdg_rom_paths = strdup(getenv("XDG_DATA_DIRS")); + char *xdg_rom_paths_orig = xdg_rom_paths; + char *cur_xdg_rom_path = NULL; + + if (xdg_rom_paths) { + while (xdg_rom_paths[strlen(xdg_rom_paths) - 1] == ':') { + xdg_rom_paths[strlen(xdg_rom_paths) - 1] = '\0'; + } + while ((cur_xdg_rom_path = local_strsep(&xdg_rom_paths, ";")) != NULL) { + char real_xdg_rom_path[1024] = { '\0' }; + strcat(real_xdg_rom_path, cur_xdg_rom_path); + path_slash(real_xdg_rom_path); + strcat(real_xdg_rom_path, "86Box/roms/"); + rom_add_path(real_xdg_rom_path); + } + } + free(xdg_rom_paths_orig); + } else { + rom_add_path("/usr/local/share/86Box/roms/"); + rom_add_path("/usr/share/86Box/roms/"); + } +#else + char default_rom_path[1024] = { '\0 ' }; + getDefaultROMPath(default_rom_path); + rom_add_path(default_rom_path); +#endif +} + +void +plat_get_global_config_dir(char *strptr) +{ +#ifdef __APPLE__ + char *prefPath = SDL_GetPrefPath(NULL, "net.86Box.86Box"); +#else + char *prefPath = SDL_GetPrefPath(NULL, "86Box"); +#endif + strncpy(strptr, prefPath, 1024); + path_slash(strptr); +} + +bool +process_media_commands_3(uint8_t *id, char *fn, uint8_t *wp, int cmdargc) { bool err = false; - *id = atoi(xargv[1]); - if (xargv[2][0] == '\'' || xargv[2][0] == '"') - { - int curarg = 2; - for (curarg = 2; curarg < cmdargc; curarg++) - { - if (strlen(fn) + strlen(xargv[curarg]) >= PATH_MAX) - { + + *id = atoi(xargv[1]); + + if (xargv[2][0] == '\'' || xargv[2][0] == '"') { + for (int curarg = 2; curarg < cmdargc; curarg++) { + if (strlen(fn) + strlen(xargv[curarg]) >= PATH_MAX) { err = true; fprintf(stderr, "Path name too long.\n"); } strcat(fn, xargv[curarg] + (xargv[curarg][0] == '\'' || xargv[curarg][0] == '"')); if (fn[strlen(fn) - 1] == '\'' - || fn[strlen(fn) - 1] == '"') - { - if (curarg + 1 < cmdargc) - { + || fn[strlen(fn) - 1] == '"') { + if (curarg + 1 < cmdargc) { *wp = atoi(xargv[curarg + 1]); } break; } strcat(fn, " "); } - } - else - { - if (strlen(xargv[2]) < PATH_MAX) - { + } else { + if (strlen(xargv[2]) < PATH_MAX) { strcpy(fn, xargv[2]); *wp = atoi(xargv[3]); - } - else - { + } else { fprintf(stderr, "Path name too long.\n"); err = true; } } if (fn[strlen(fn) - 1] == '\'' - || fn[strlen(fn) - 1] == '"') fn[strlen(fn) - 1] = '\0'; + || fn[strlen(fn) - 1] == '"') + fn[strlen(fn) - 1] = '\0'; return err; } -char* (*f_readline)(const char*) = NULL; -int (*f_add_history)(const char *) = NULL; +char *(*f_readline)(const char *) = NULL; +int (*f_add_history)(const char *) = NULL; void (*f_rl_callback_handler_remove)(void) = NULL; #ifdef __APPLE__ -#define LIBEDIT_LIBRARY "libedit.dylib" +# define LIBEDIT_LIBRARY "libedit.dylib" #else -#define LIBEDIT_LIBRARY "libedit.so" +# define LIBEDIT_LIBRARY "libedit.so" #endif -uint32_t timer_onesec(uint32_t interval, void* param) + +uint32_t +timer_onesec(uint32_t interval, void *param) { - pc_onesec(); - return interval; + pc_onesec(); + return interval; } -void monitor_thread(void* param) +void +monitor_thread(void *param) { #ifndef USE_CLI - if (isatty(fileno(stdin)) && isatty(fileno(stdout))) - { - char* line = NULL; + if (isatty(fileno(stdin)) && isatty(fileno(stdout))) { + char *line = NULL; size_t n; + printf("86Box monitor console.\n"); - while (!exit_event) - { - if (feof(stdin)) break; + while (!exit_event) { + if (feof(stdin)) + break; if (f_readline) line = f_readline("(86Box) "); - else - { + else { printf("(86Box) "); - getline(&line, &n, stdin); + !getline(&line, &n, stdin); } - if (line) - { - int cmdargc = 0; - char* linecpy; + if (line) { + int cmdargc = 0; + char *linecpy; + line[strcspn(line, "\r\n")] = '\0'; - linecpy = strdup(line); - if (!linecpy) - { + linecpy = strdup(line); + if (!linecpy) { free(line); line = NULL; continue; } - if (f_add_history) f_add_history(line); + if (f_add_history) + f_add_history(line); memset(xargv, 0, sizeof(xargv)); - while(1) - { + while (1) { xargv[cmdargc++] = local_strsep(&linecpy, " "); - if (xargv[cmdargc - 1] == NULL || cmdargc >= 512) break; + if (xargv[cmdargc - 1] == NULL || cmdargc >= 512) + break; } cmdargc--; - if (strncasecmp(xargv[0], "help", 4) == 0) - { + if (strncasecmp(xargv[0], "help", 4) == 0) { printf( "fddload - Load floppy disk image into drive .\n" "cdload - Load CD-ROM image into drive .\n" @@ -837,34 +955,60 @@ void monitor_thread(void* param) "hardreset - hard reset the emulated system.\n" "pause - pause the the emulated system.\n" "fullscreen - toggle fullscreen.\n" + "version - print version and license information.\n" "exit - exit 86Box.\n"); - } - else if (strncasecmp(xargv[0], "exit", 4) == 0) - { + } else if (strncasecmp(xargv[0], "exit", 4) == 0) { exit_event = 1; - } - else if (strncasecmp(xargv[0], "fullscreen", 10) == 0) - { - video_fullscreen = video_fullscreen ? 0 : 1; + } else if (strncasecmp(xargv[0], "version", 7) == 0) { +# ifndef EMU_GIT_HASH +# define EMU_GIT_HASH "0000000" +# endif + +# if defined(__arm__) || defined(__TARGET_ARCH_ARM) +# define ARCH_STR "arm" +# elif defined(__aarch64__) || defined(_M_ARM64) +# define ARCH_STR "arm64" +# elif defined(__i386) || defined(__i386__) || defined(_M_IX86) +# define ARCH_STR "i386" +# elif defined(__x86_64) || defined(__x86_64__) || defined(__amd64) || defined(_M_X64) +# define ARCH_STR "x86_64" +# else +# define ARCH_STR "unknown arch" +# endif + +# ifdef USE_DYNAREC +# ifdef USE_NEW_DYNAREC +# define DYNAREC_STR "new dynarec" +# else +# define DYNAREC_STR "old dynarec" +# endif +# else +# define DYNAREC_STR "no dynarec" +# endif + + printf( + "%s v%s [%s] [%s, %s]\n\n" + "An emulator of old computers\n" + "Authors: Miran GrÄa (OBattler), RichardG867, Jasmine Iwanek, TC1995, coldbrewed, Teemu Korhonen (Manaatti), " + "Joakim L. Gilje, Adrien Moulin (elyosh), Daniel Balsom (gloriouscow), Cacodemon345, Fred N. van Kempen (waltje), " + "Tiseno100, reenigne, and others.\n" + "With previous core contributions from Sarah Walker, leilei, JohnElliott, greatpsycho, and others.\n\n" + "Released under the GNU General Public License version 2 or later. See LICENSE for more information.\n", + EMU_NAME, EMU_VERSION_FULL, EMU_GIT_HASH, ARCH_STR, DYNAREC_STR); + } else if (strncasecmp(xargv[0], "fullscreen", 10) == 0) { + video_fullscreen = video_fullscreen ? 0 : 1; fullscreen_pending = 1; - } - else if (strncasecmp(xargv[0], "pause", 5) == 0) - { + } else if (strncasecmp(xargv[0], "pause", 5) == 0) { plat_pause(dopause ^ 1); printf("%s", dopause ? "Paused.\n" : "Unpaused.\n"); - } - else if (strncasecmp(xargv[0], "hardreset", 9) == 0) - { + } else if (strncasecmp(xargv[0], "hardreset", 9) == 0) { pc_reset_hard(); - } - else if (strncasecmp(xargv[0], "cdload", 6) == 0 && cmdargc >= 3) - { + } else if (strncasecmp(xargv[0], "cdload", 6) == 0 && cmdargc >= 3) { uint8_t id; - bool err = false; - char fn[PATH_MAX]; - - if (!xargv[2] || !xargv[1]) - { + bool err = false; + char fn[PATH_MAX]; + + if (!xargv[2] || !xargv[1]) { free(line); free(linecpy); line = NULL; @@ -872,149 +1016,131 @@ void monitor_thread(void* param) } id = atoi(xargv[1]); memset(fn, 0, sizeof(fn)); - if (xargv[2][0] == '\'' || xargv[2][0] == '"') - { + if (xargv[2][0] == '\'' || xargv[2][0] == '"') { int curarg = 2; - for (curarg = 2; curarg < cmdargc; curarg++) - { - if (strlen(fn) + strlen(xargv[curarg]) >= PATH_MAX) - { + + for (curarg = 2; curarg < cmdargc; curarg++) { + if (strlen(fn) + strlen(xargv[curarg]) >= PATH_MAX) { err = true; fprintf(stderr, "Path name too long.\n"); } strcat(fn, xargv[curarg] + (xargv[curarg][0] == '\'' || xargv[curarg][0] == '"')); if (fn[strlen(fn) - 1] == '\'' - || fn[strlen(fn) - 1] == '"') - { + || fn[strlen(fn) - 1] == '"') { break; } strcat(fn, " "); } - } - else - { - if (strlen(xargv[2]) < PATH_MAX) - { + } else { + if (strlen(xargv[2]) < PATH_MAX) { strcpy(fn, xargv[2]); - } - else - { + } else { fprintf(stderr, "Path name too long.\n"); } } - if (!err) - { + if (!err) { if (fn[strlen(fn) - 1] == '\'' - || fn[strlen(fn) - 1] == '"') fn[strlen(fn) - 1] = '\0'; + || fn[strlen(fn) - 1] == '"') + fn[strlen(fn) - 1] = '\0'; printf("Inserting disc into CD-ROM drive %hhu: %s\n", id, fn); cdrom_mount(id, fn); } - } - else if (strncasecmp(xargv[0], "fddeject", 8) == 0 && cmdargc >= 2) - { + } else if (strncasecmp(xargv[0], "fddeject", 8) == 0 && cmdargc >= 2) { floppy_eject(atoi(xargv[1])); - } - else if (strncasecmp(xargv[0], "cdeject", 8) == 0 && cmdargc >= 2) - { + } else if (strncasecmp(xargv[0], "cdeject", 8) == 0 && cmdargc >= 2) { cdrom_mount(atoi(xargv[1]), ""); - } - else if (strncasecmp(xargv[0], "moeject", 8) == 0 && cmdargc >= 2) - { + } else if (strncasecmp(xargv[0], "moeject", 8) == 0 && cmdargc >= 2) { mo_eject(atoi(xargv[1])); - } - else if (strncasecmp(xargv[0], "carteject", 8) == 0 && cmdargc >= 2) - { + } else if (strncasecmp(xargv[0], "carteject", 8) == 0 && cmdargc >= 2) { cartridge_eject(atoi(xargv[1])); - } - else if (strncasecmp(xargv[0], "zipeject", 8) == 0 && cmdargc >= 2) - { + } else if (strncasecmp(xargv[0], "zipeject", 8) == 0 && cmdargc >= 2) { zip_eject(atoi(xargv[1])); - } - else if (strncasecmp(xargv[0], "fddload", 7) == 0 && cmdargc >= 4) - { - uint8_t id, wp; - bool err = false; - char fn[PATH_MAX]; + } else if (strncasecmp(xargv[0], "fddload", 7) == 0 && cmdargc >= 4) { + uint8_t id; + uint8_t wp; + bool err = false; + char fn[PATH_MAX]; + memset(fn, 0, sizeof(fn)); - if (!xargv[2] || !xargv[1]) - { + + if (!xargv[2] || !xargv[1]) { free(line); free(linecpy); line = NULL; continue; } err = process_media_commands_3(&id, fn, &wp, cmdargc); - if (!err) - { + if (!err) { if (fn[strlen(fn) - 1] == '\'' - || fn[strlen(fn) - 1] == '"') fn[strlen(fn) - 1] = '\0'; + || fn[strlen(fn) - 1] == '"') + fn[strlen(fn) - 1] = '\0'; printf("Inserting disk into floppy drive %c: %s\n", id + 'A', fn); floppy_mount(id, fn, wp); } - } - else if (strncasecmp(xargv[0], "moload", 7) == 0 && cmdargc >= 4) - { - uint8_t id, wp; - bool err = false; - char fn[PATH_MAX]; + } else if (strncasecmp(xargv[0], "moload", 7) == 0 && cmdargc >= 4) { + uint8_t id; + uint8_t wp; + bool err = false; + char fn[PATH_MAX]; + memset(fn, 0, sizeof(fn)); - if (!xargv[2] || !xargv[1]) - { + + if (!xargv[2] || !xargv[1]) { free(line); free(linecpy); line = NULL; continue; } err = process_media_commands_3(&id, fn, &wp, cmdargc); - if (!err) - { + if (!err) { if (fn[strlen(fn) - 1] == '\'' - || fn[strlen(fn) - 1] == '"') fn[strlen(fn) - 1] = '\0'; + || fn[strlen(fn) - 1] == '"') + fn[strlen(fn) - 1] = '\0'; printf("Inserting into mo drive %hhu: %s\n", id, fn); mo_mount(id, fn, wp); } - } - else if (strncasecmp(xargv[0], "cartload", 7) == 0 && cmdargc >= 4) - { - uint8_t id, wp; - bool err = false; - char fn[PATH_MAX]; + } else if (strncasecmp(xargv[0], "cartload", 7) == 0 && cmdargc >= 4) { + uint8_t id; + uint8_t wp; + bool err = false; + char fn[PATH_MAX]; + memset(fn, 0, sizeof(fn)); - if (!xargv[2] || !xargv[1]) - { + + if (!xargv[2] || !xargv[1]) { free(line); free(linecpy); line = NULL; continue; } err = process_media_commands_3(&id, fn, &wp, cmdargc); - if (!err) - { + if (!err) { if (fn[strlen(fn) - 1] == '\'' - || fn[strlen(fn) - 1] == '"') fn[strlen(fn) - 1] = '\0'; + || fn[strlen(fn) - 1] == '"') + fn[strlen(fn) - 1] = '\0'; printf("Inserting tape into cartridge holder %hhu: %s\n", id, fn); cartridge_mount(id, fn, wp); } - } - else if (strncasecmp(xargv[0], "zipload", 7) == 0 && cmdargc >= 4) - { - uint8_t id, wp; - bool err = false; - char fn[PATH_MAX]; + } else if (strncasecmp(xargv[0], "zipload", 7) == 0 && cmdargc >= 4) { + uint8_t id; + uint8_t wp; + bool err = false; + char fn[PATH_MAX]; + memset(fn, 0, sizeof(fn)); - if (!xargv[2] || !xargv[1]) - { + + if (!xargv[2] || !xargv[1]) { free(line); free(linecpy); line = NULL; continue; } err = process_media_commands_3(&id, fn, &wp, cmdargc); - if (!err) - { + if (!err) { if (fn[strlen(fn) - 1] == '\'' - || fn[strlen(fn) - 1] == '"') fn[strlen(fn) - 1] = '\0'; + || fn[strlen(fn) - 1] == '"') + fn[strlen(fn) - 1] = '\0'; printf("Inserting disk into ZIP drive %c: %s\n", id + 'A', fn); zip_mount(id, fn, wp); } @@ -1028,51 +1154,50 @@ void monitor_thread(void* param) #endif } -int main(int argc, char** argv) +extern int gfxcard[2]; +int +main(int argc, char **argv) { SDL_Event event; - void* libedithandle; + void *libedithandle; SDL_Init(0); pc_init(argc, argv); - if (! pc_init_modules()) { + if (!pc_init_modules()) { ui_msgbox_header(MBX_FATAL, L"No ROMs found.", L"86Box could not find any usable ROM images.\n\nPlease download a ROM set and extract it into the \"roms\" directory."); SDL_Quit(); return 6; } - + + gfxcard[1] = 0; eventthread = SDL_ThreadID(); - blitmtx = SDL_CreateMutex(); - if (!blitmtx) - { + blitmtx = SDL_CreateMutex(); + if (!blitmtx) { fprintf(stderr, "Failed to create blit mutex: %s", SDL_GetError()); return -1; } libedithandle = dlopen(LIBEDIT_LIBRARY, RTLD_LOCAL | RTLD_LAZY); - if (libedithandle) - { - f_readline = dlsym(libedithandle, "readline"); + if (libedithandle) { + f_readline = dlsym(libedithandle, "readline"); f_add_history = dlsym(libedithandle, "add_history"); - if (!f_readline) - { + if (!f_readline) { fprintf(stderr, "readline in libedit not found, line editing will be limited.\n"); } f_rl_callback_handler_remove = dlsym(libedithandle, "rl_callback_handler_remove"); - } - else fprintf(stderr, "libedit not found, line editing will be limited.\n"); + } else + fprintf(stderr, "libedit not found, line editing will be limited.\n"); mousemutex = SDL_CreateMutex(); sdl_initho(); - if (start_in_fullscreen) - { + if (start_in_fullscreen) { video_fullscreen = 1; - sdl_set_fs(1); + sdl_set_fs(1); } /* Fire up the machine. */ pc_reset_hard_init(); /* Set the PAUSE mode depending on the renderer. */ - //plat_pause(0); + // plat_pause(0); /* Initialize the rendering window, or fullscreen. */ @@ -1081,143 +1206,132 @@ int main(int argc, char** argv) thread_create(monitor_thread, NULL); #endif SDL_AddTimer(1000, timer_onesec, NULL); - while (!is_quit) - { + while (!is_quit) { static int mouse_inside = 0; - while (SDL_PollEvent(&event)) - { - switch(event.type) - { + + while (SDL_PollEvent(&event)) { + switch (event.type) { case SDL_QUIT: exit_event = 1; break; case SDL_MOUSEWHEEL: - { - if (mouse_capture || video_fullscreen) { - if (event.wheel.direction == SDL_MOUSEWHEEL_FLIPPED) - { - event.wheel.x *= -1; - event.wheel.y *= -1; + if (mouse_capture || video_fullscreen) { + if (event.wheel.direction == SDL_MOUSEWHEEL_FLIPPED) { + event.wheel.x *= -1; + event.wheel.y *= -1; + } + SDL_LockMutex(mousemutex); + mouse_set_z(event.wheel.y); + SDL_UnlockMutex(mousemutex); } - SDL_LockMutex(mousemutex); - mousedata.deltaz = event.wheel.y; - SDL_UnlockMutex(mousemutex); + break; } - break; - } case SDL_MOUSEMOTION: - { - if (mouse_capture || video_fullscreen) { - SDL_LockMutex(mousemutex); - mousedata.deltax += event.motion.xrel; - mousedata.deltay += event.motion.yrel; - SDL_UnlockMutex(mousemutex); + if (mouse_capture || video_fullscreen) { + SDL_LockMutex(mousemutex); + mouse_scale(event.motion.xrel, event.motion.yrel); + SDL_UnlockMutex(mousemutex); + } + break; } - break; - } case SDL_MOUSEBUTTONDOWN: case SDL_MOUSEBUTTONUP: - { - if ((event.button.button == SDL_BUTTON_LEFT) - && !(mouse_capture || video_fullscreen) - && event.button.state == SDL_RELEASED - && mouse_inside) { - plat_mouse_capture(1); - break; - } - if (mouse_get_buttons() < 3 && event.button.button == SDL_BUTTON_MIDDLE && !video_fullscreen) - { - plat_mouse_capture(0); - break; - } - if (mouse_capture || video_fullscreen) - { - int buttonmask = 0; + if ((event.button.button == SDL_BUTTON_LEFT) + && !(mouse_capture || video_fullscreen) + && event.button.state == SDL_RELEASED + && mouse_inside) { + plat_mouse_capture(1); + break; + } + if (mouse_get_buttons() < 3 && event.button.button == SDL_BUTTON_MIDDLE && !video_fullscreen) { + plat_mouse_capture(0); + break; + } + if (mouse_capture || video_fullscreen) { + int buttonmask = 0; - switch(event.button.button) - { - case SDL_BUTTON_LEFT: - buttonmask = 1; - break; - case SDL_BUTTON_RIGHT: - buttonmask = 2; - break; - case SDL_BUTTON_MIDDLE: - buttonmask = 4; - break; + switch (event.button.button) { + case SDL_BUTTON_LEFT: + buttonmask = 1; + break; + case SDL_BUTTON_RIGHT: + buttonmask = 2; + break; + case SDL_BUTTON_MIDDLE: + buttonmask = 4; + break; + case SDL_BUTTON_X1: + buttonmask = 8; + break; + case SDL_BUTTON_X2: + buttonmask = 16; + break; + } + SDL_LockMutex(mousemutex); + if (event.button.state == SDL_PRESSED) + mouse_set_buttons_ex(mouse_get_buttons_ex() | buttonmask); + else + mouse_set_buttons_ex(mouse_get_buttons_ex() & ~buttonmask); + SDL_UnlockMutex(mousemutex); } - SDL_LockMutex(mousemutex); - if (event.button.state == SDL_PRESSED) - { - mousedata.mousebuttons |= buttonmask; - } - else mousedata.mousebuttons &= ~buttonmask; - SDL_UnlockMutex(mousemutex); + break; } - break; - } case SDL_RENDER_DEVICE_RESET: case SDL_RENDER_TARGETS_RESET: - { - extern void sdl_reinit_texture(); + { + extern void sdl_reinit_texture(void); + sdl_reinit_texture(); break; } case SDL_KEYDOWN: case SDL_KEYUP: - { - uint16_t xtkey = 0; - switch(event.key.keysym.scancode) { - default: - xtkey = sdl_to_xt[event.key.keysym.scancode]; - break; + uint16_t xtkey = 0; + + switch (event.key.keysym.scancode) { + default: + xtkey = sdl_to_xt[event.key.keysym.scancode]; + break; + } + keyboard_input(event.key.state == SDL_PRESSED, xtkey); } - keyboard_input(event.key.state == SDL_PRESSED, xtkey); - } case SDL_WINDOWEVENT: - { - switch (event.window.event) { - case SDL_WINDOWEVENT_ENTER: - mouse_inside = 1; - break; - case SDL_WINDOWEVENT_LEAVE: - mouse_inside = 0; - break; + switch (event.window.event) { + case SDL_WINDOWEVENT_ENTER: + mouse_inside = 1; + break; + case SDL_WINDOWEVENT_LEAVE: + mouse_inside = 0; + break; + } } - } } - } - if (mouse_capture && keyboard_ismsexit()) - { + } + if (mouse_capture && keyboard_ismsexit()) { plat_mouse_capture(0); - } - if (blitreq) - { + } + if (blitreq) { extern void sdl_blit(int x, int y, int w, int h); sdl_blit(params.x, params.y, params.w, params.h); } - if (title_set) - { - extern void ui_window_title_real(); + if (title_set) { + extern void ui_window_title_real(void); ui_window_title_real(); } - if (video_fullscreen && keyboard_isfsexit()) - { + if (video_fullscreen && keyboard_isfsexit()) { sdl_set_fs(0); video_fullscreen = 0; } - if (fullscreen_pending) - { + if (fullscreen_pending) { sdl_set_fs(video_fullscreen); fullscreen_pending = 0; } - if (exit_event) - { + if (exit_event) { do_stop(); break; } @@ -1226,10 +1340,12 @@ int main(int argc, char** argv) SDL_DestroyMutex(blitmtx); SDL_DestroyMutex(mousemutex); SDL_Quit(); - if (f_rl_callback_handler_remove) f_rl_callback_handler_remove(); + if (f_rl_callback_handler_remove) + f_rl_callback_handler_remove(); return 0; } -char* plat_vidapi_name(int i) +char * +plat_vidapi_name(int i) { return "default"; } @@ -1240,37 +1356,68 @@ set_language(uint32_t id) lang_id = id; } - /* Sets up the program language before initialization. */ -uint32_t plat_language_code(char* langcode) +uint32_t +plat_language_code(char *langcode) { - /* or maybe not */ + /* or maybe not */ return 0; } +void +plat_get_cpu_string(char *outbuf, uint8_t len) { + char cpu_string[] = "Unknown"; + + strncpy(outbuf, cpu_string, len); +} + /* Converts back the language code to LCID */ void -plat_language_code_r(uint32_t lcid, char* outbuf, int len) +plat_language_code_r(uint32_t lcid, char *outbuf, int len) { - /* or maybe not */ + /* or maybe not */ return; } -void joystick_init(void) {} -void joystick_close(void) {} -void joystick_process(void) {} -void startblit() +void +joystick_init(void) +{ + /* No-op. */ +} + +void +joystick_close(void) +{ + /* No-op. */ +} + +void +joystick_process(void) +{ + /* No-op. */ +} + +void +startblit(void) { SDL_LockMutex(blitmtx); } -void endblit() +void +endblit(void) { SDL_UnlockMutex(blitmtx); } /* API */ void -ui_sb_mt32lcd(char* str) +ui_sb_mt32lcd(char *str) { + /* No-op. */ +} + +void +ui_hard_reset_completed(void) +{ + /* No-op. */ } diff --git a/src/unix/unix_cdrom.c b/src/unix/unix_cdrom.c index 9eb3d962a..424f1a9a3 100644 --- a/src/unix/unix_cdrom.c +++ b/src/unix/unix_cdrom.c @@ -1,21 +1,20 @@ /* - * 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. + * 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. + * This file is part of the 86Box distribution. * - * Handle the platform-side of CDROM/ZIP/MO drives. + * Handle the platform-side of CDROM/ZIP/MO drives. * * * - * Authors: Sarah Walker, - * Miran Grca, - * Fred N. van Kempen, + * Authors: Miran Grca, + * Fred N. van Kempen, * - * Copyright 2016-2018 Miran Grca. - * Copyright 2017,2018 Fred N. van Kempen. + * Copyright 2016-2018 Miran Grca. + * Copyright 2017-2018 Fred N. van Kempen. */ #include @@ -39,8 +38,6 @@ #include <86box/plat.h> #include <86box/ui.h> - - void cassette_mount(char *fn, uint8_t wp) { @@ -49,49 +46,53 @@ cassette_mount(char *fn, uint8_t wp) cassette_ui_writeprot = wp; pc_cas_set_fname(cassette, fn); if (fn != NULL) - memcpy(cassette_fname, fn, MIN(511, strlen(fn))); + memcpy(cassette_fname, fn, MIN(511, strlen(fn))); ui_sb_update_icon_state(SB_CASSETTE, (fn == NULL) ? 1 : 0); - //media_menu_update_cassette(); +#if 0 + media_menu_update_cassette(); +#endif ui_sb_update_tip(SB_CASSETTE); config_save(); } - void cassette_eject(void) { pc_cas_set_fname(cassette, NULL); memset(cassette_fname, 0x00, sizeof(cassette_fname)); ui_sb_update_icon_state(SB_CASSETTE, 1); - //media_menu_update_cassette(); +#if 0 + media_menu_update_cassette(); +#endif ui_sb_update_tip(SB_CASSETTE); config_save(); } - void cartridge_mount(uint8_t id, char *fn, uint8_t wp) { cart_close(id); cart_load(id, fn); ui_sb_update_icon_state(SB_CARTRIDGE | id, strlen(cart_fns[id]) ? 0 : 1); - //media_menu_update_cartridge(id); +#if 0 + media_menu_update_cartridge(id); +#endif ui_sb_update_tip(SB_CARTRIDGE | id); config_save(); } - void cartridge_eject(uint8_t id) { cart_close(id); ui_sb_update_icon_state(SB_CARTRIDGE | id, 1); - //media_menu_update_cartridge(id); +#if 0 + media_menu_update_cartridge(id); +#endif ui_sb_update_tip(SB_CARTRIDGE | id); config_save(); } - void floppy_mount(uint8_t id, char *fn, uint8_t wp) { @@ -99,36 +100,40 @@ floppy_mount(uint8_t id, char *fn, uint8_t wp) ui_writeprot[id] = wp; fdd_load(id, fn); ui_sb_update_icon_state(SB_FLOPPY | id, strlen(floppyfns[id]) ? 0 : 1); - //media_menu_update_floppy(id); +#if 0 + media_menu_update_floppy(id); +#endif ui_sb_update_tip(SB_FLOPPY | id); config_save(); } - void floppy_eject(uint8_t id) { fdd_close(id); ui_sb_update_icon_state(SB_FLOPPY | id, 1); - //media_menu_update_floppy(id); +#if 0 + media_menu_update_floppy(id); +#endif ui_sb_update_tip(SB_FLOPPY | id); config_save(); } - void plat_cdrom_ui_update(uint8_t id, uint8_t reload) { cdrom_t *drv = &cdrom[id]; if (drv->host_drive == 0) { - ui_sb_update_icon_state(SB_CDROM|id, 1); + ui_sb_update_icon_state(SB_CDROM | id, 1); } else { - ui_sb_update_icon_state(SB_CDROM|id, 0); + ui_sb_update_icon_state(SB_CDROM | id, 0); } - //media_menu_update_cdrom(id); - ui_sb_update_tip(SB_CDROM|id); +#if 0 + media_menu_update_cdrom(id); +#endif + ui_sb_update_tip(SB_CDROM | id); } void @@ -137,20 +142,22 @@ cdrom_mount(uint8_t id, char *fn) cdrom[id].prev_host_drive = cdrom[id].host_drive; strcpy(cdrom[id].prev_image_path, cdrom[id].image_path); if (cdrom[id].ops && cdrom[id].ops->exit) - cdrom[id].ops->exit(&(cdrom[id])); + cdrom[id].ops->exit(&(cdrom[id])); cdrom[id].ops = NULL; memset(cdrom[id].image_path, 0, sizeof(cdrom[id].image_path)); cdrom_image_open(&(cdrom[id]), fn); /* Signal media change to the emulated machine. */ if (cdrom[id].insert) - cdrom[id].insert(cdrom[id].priv); + cdrom[id].insert(cdrom[id].priv); cdrom[id].host_drive = (strlen(cdrom[id].image_path) == 0) ? 0 : 200; if (cdrom[id].host_drive == 200) { - ui_sb_update_icon_state(SB_CDROM | id, 0); + ui_sb_update_icon_state(SB_CDROM | id, 0); } else { - ui_sb_update_icon_state(SB_CDROM | id, 1); + ui_sb_update_icon_state(SB_CDROM | id, 1); } - //media_menu_update_cdrom(id); +#if 0 + media_menu_update_cdrom(id); +#endif ui_sb_update_tip(SB_CDROM | id); config_save(); } @@ -162,17 +169,18 @@ mo_eject(uint8_t id) mo_disk_close(dev); if (mo_drives[id].bus_type) { - /* Signal disk change to the emulated machine. */ - mo_insert(dev); + /* Signal disk change to the emulated machine. */ + mo_insert(dev); } ui_sb_update_icon_state(SB_MO | id, 1); - //media_menu_update_mo(id); +#if 0 + media_menu_update_mo(id); +#endif ui_sb_update_tip(SB_MO | id); config_save(); } - void mo_mount(uint8_t id, char *fn, uint8_t wp) { @@ -184,13 +192,14 @@ mo_mount(uint8_t id, char *fn, uint8_t wp) mo_insert(dev); ui_sb_update_icon_state(SB_MO | id, strlen(mo_drives[id].image_path) ? 0 : 1); - //media_menu_update_mo(id); +#if 0 + media_menu_update_mo(id); +#endif ui_sb_update_tip(SB_MO | id); config_save(); } - void mo_reload(uint8_t id) { @@ -198,13 +207,15 @@ mo_reload(uint8_t id) mo_disk_reload(dev); if (strlen(mo_drives[id].image_path) == 0) { - ui_sb_update_icon_state(SB_MO|id, 1); + ui_sb_update_icon_state(SB_MO | id, 1); } else { - ui_sb_update_icon_state(SB_MO|id, 0); + ui_sb_update_icon_state(SB_MO | id, 0); } - //media_menu_update_mo(id); - ui_sb_update_tip(SB_MO|id); +#if 0 + media_menu_update_mo(id); +#endif + ui_sb_update_tip(SB_MO | id); config_save(); } @@ -216,17 +227,18 @@ zip_eject(uint8_t id) zip_disk_close(dev); if (zip_drives[id].bus_type) { - /* Signal disk change to the emulated machine. */ - zip_insert(dev); + /* Signal disk change to the emulated machine. */ + zip_insert(dev); } ui_sb_update_icon_state(SB_ZIP | id, 1); - //media_menu_update_zip(id); +#if 0 + media_menu_update_zip(id); +#endif ui_sb_update_tip(SB_ZIP | id); config_save(); } - void zip_mount(uint8_t id, char *fn, uint8_t wp) { @@ -238,13 +250,14 @@ zip_mount(uint8_t id, char *fn, uint8_t wp) zip_insert(dev); ui_sb_update_icon_state(SB_ZIP | id, strlen(zip_drives[id].image_path) ? 0 : 1); - //media_menu_update_zip(id); +#if 0 + media_menu_update_zip(id); +#endif ui_sb_update_tip(SB_ZIP | id); config_save(); } - void zip_reload(uint8_t id) { @@ -252,13 +265,15 @@ zip_reload(uint8_t id) zip_disk_reload(dev); if (strlen(zip_drives[id].image_path) == 0) { - ui_sb_update_icon_state(SB_ZIP|id, 1); + ui_sb_update_icon_state(SB_ZIP | id, 1); } else { - ui_sb_update_icon_state(SB_ZIP|id, 0); + ui_sb_update_icon_state(SB_ZIP | id, 0); } - //media_menu_update_zip(id); - ui_sb_update_tip(SB_ZIP|id); +#if 0 + media_menu_update_zip(id); +#endif + ui_sb_update_tip(SB_ZIP | id); config_save(); } diff --git a/src/unix/unix_sdl.c b/src/unix/unix_sdl.c index 356305d1c..19af4b71e 100644 --- a/src/unix/unix_sdl.c +++ b/src/unix/unix_sdl.c @@ -18,156 +18,176 @@ #include <86box/version.h> #include <86box/unix_sdl.h> -#define RENDERER_FULL_SCREEN 1 -#define RENDERER_HARDWARE 2 -#define RENDERER_OPENGL 4 +#define RENDERER_FULL_SCREEN 1 +#define RENDERER_HARDWARE 2 +#define RENDERER_OPENGL 4 -typedef struct sdl_blit_params -{ - int x, y, w, h; +typedef struct sdl_blit_params { + int x; + int y; + int w; + int h; } sdl_blit_params; extern sdl_blit_params params; -extern int blitreq; +extern int blitreq; -SDL_Window *sdl_win = NULL; -SDL_Renderer *sdl_render = NULL; -static SDL_Texture *sdl_tex = NULL; -int sdl_w = SCREEN_RES_X, sdl_h = SCREEN_RES_Y; -static int sdl_fs, sdl_flags = -1; -static int cur_w, cur_h; -static int cur_wx = 0, cur_wy = 0, cur_ww =0, cur_wh = 0; -static volatile int sdl_enabled = 1; -static SDL_mutex* sdl_mutex = NULL; -int mouse_capture; -int title_set = 0; -int resize_pending = 0; -int resize_w = 0; -int resize_h = 0; -static uint8_t interpixels[17842176]; +SDL_Window *sdl_win = NULL; +SDL_Renderer *sdl_render = NULL; +static SDL_Texture *sdl_tex = NULL; +int sdl_w = SCREEN_RES_X; +int sdl_h = SCREEN_RES_Y; +static int sdl_fs; +static int sdl_flags = -1; +static int cur_w; +static int cur_h; +static int cur_wx = 0; +static int cur_wy = 0; +static int cur_ww = 0; +static int cur_wh = 0; +static volatile int sdl_enabled = 1; +static SDL_mutex *sdl_mutex = NULL; +int mouse_capture; +int title_set = 0; +int resize_pending = 0; +int resize_w = 0; +int resize_h = 0; +static void *pixeldata; -extern void RenderImGui(); +extern void RenderImGui(void); static void sdl_integer_scale(double *d, double *g) { double ratio; if (*d > *g) { - ratio = floor(*d / *g); - *d = *g * ratio; + ratio = floor(*d / *g); + *d = *g * ratio; } else { - ratio = ceil(*d / *g); - *d = *g / ratio; + ratio = ceil(*d / *g); + *d = *g / ratio; } } -void sdl_reinit_texture(); +void sdl_reinit_texture(void); static void sdl_stretch(int *w, int *h, int *x, int *y) { - double hw, gw, hh, gh, dx, dy, dw, dh, gsr, hsr; - int real_sdl_w, real_sdl_h; + double hw; + double gw; + double hh; + double gh; + double dx; + double dy; + double dw; + double dh; + double gsr; + double hsr; + int real_sdl_w; + int real_sdl_h; SDL_GL_GetDrawableSize(sdl_win, &real_sdl_w, &real_sdl_h); - hw = (double) real_sdl_w; - hh = (double) real_sdl_h; - gw = (double) *w; - gh = (double) *h; + hw = (double) real_sdl_w; + hh = (double) real_sdl_h; + gw = (double) *w; + gh = (double) *h; hsr = hw / hh; switch (video_fullscreen_scale) { - case FULLSCR_SCALE_FULL: - default: - *w = real_sdl_w; - *h = real_sdl_h; - *x = 0; - *y = 0; - break; - case FULLSCR_SCALE_43: - case FULLSCR_SCALE_KEEPRATIO: - if (video_fullscreen_scale == FULLSCR_SCALE_43) - gsr = 4.0 / 3.0; - else - gsr = gw / gh; - if (gsr <= hsr) { - dw = hh * gsr; - dh = hh; - } else { - dw = hw; - dh = hw / gsr; - } - dx = (hw - dw) / 2.0; - dy = (hh - dh) / 2.0; - *w = (int) dw; - *h = (int) dh; - *x = (int) dx; - *y = (int) dy; - break; - case FULLSCR_SCALE_INT: - gsr = gw / gh; - if (gsr <= hsr) { - dw = hh * gsr; - dh = hh; - } else { - dw = hw; - dh = hw / gsr; - } - sdl_integer_scale(&dw, &gw); - sdl_integer_scale(&dh, &gh); - dx = (hw - dw) / 2.0; - dy = (hh - dh) / 2.0; - *w = (int) dw; - *h = (int) dh; - *x = (int) dx; - *y = (int) dy; - break; + case FULLSCR_SCALE_FULL: + default: + *w = real_sdl_w; + *h = real_sdl_h; + *x = 0; + *y = 0; + break; + case FULLSCR_SCALE_43: + case FULLSCR_SCALE_KEEPRATIO: + if (video_fullscreen_scale == FULLSCR_SCALE_43) + gsr = 4.0 / 3.0; + else + gsr = gw / gh; + if (gsr <= hsr) { + dw = hh * gsr; + dh = hh; + } else { + dw = hw; + dh = hw / gsr; + } + dx = (hw - dw) / 2.0; + dy = (hh - dh) / 2.0; + *w = (int) dw; + *h = (int) dh; + *x = (int) dx; + *y = (int) dy; + break; + case FULLSCR_SCALE_INT: + gsr = gw / gh; + if (gsr <= hsr) { + dw = hh * gsr; + dh = hh; + } else { + dw = hw; + dh = hw / gsr; + } + sdl_integer_scale(&dw, &gw); + sdl_integer_scale(&dh, &gh); + dx = (hw - dw) / 2.0; + dy = (hh - dh) / 2.0; + *w = (int) dw; + *h = (int) dh; + *x = (int) dx; + *y = (int) dy; + break; } } - void -sdl_blit_shim(int x, int y, int w, int h) +sdl_blit_shim(int x, int y, int w, int h, int monitor_index) { params.x = x; params.y = y; params.w = w; params.h = h; - if (!(!sdl_enabled || (x < 0) || (y < 0) || (w <= 0) || (h <= 0) || (w > 2048) || (h > 2048) || (buffer32 == NULL) || (sdl_render == NULL) || (sdl_tex == NULL))) - video_copy(interpixels, &(buffer32->line[y][x]), h * 2048 * sizeof(uint32_t)); - if (screenshots) - video_screenshot(interpixels, 0, 0, 2048); + + if (!(!sdl_enabled || (x < 0) || (y < 0) || (w <= 0) || (h <= 0) || (w > 2048) || (h > 2048) || (buffer32 == NULL) || (sdl_render == NULL) || (sdl_tex == NULL)) || (monitor_index >= 1)) + for (int row = 0; row < h; ++row) + video_copy(&(((uint8_t *) pixeldata)[row * 2048 * sizeof(uint32_t)]), &(buffer32->line[y + row][x]), w * sizeof(uint32_t)); + + if (monitors[monitor_index].mon_screenshots) + video_screenshot((uint32_t *) pixeldata, 0, 0, 2048); blitreq = 1; - video_blit_complete(); + + video_blit_complete_monitor(monitor_index); } -void ui_window_title_real(); +void ui_window_title_real(void); void -sdl_real_blit(SDL_Rect* r_src) +sdl_real_blit(SDL_Rect *r_src) { SDL_Rect r_dst; - int ret, winx, winy; + int ret; + int winx; + int winy; + SDL_GL_GetDrawableSize(sdl_win, &winx, &winy); SDL_RenderClear(sdl_render); - r_dst = *r_src; + r_dst = *r_src; r_dst.x = r_dst.y = 0; - - if (sdl_fs) - { - sdl_stretch(&r_dst.w, &r_dst.h, &r_dst.x, &r_dst.y); - } - else - { - r_dst.w *= ((float)winx / (float) r_dst.w); - r_dst.h *= ((float)winy / (float) r_dst.h); - } + if (sdl_fs) { + sdl_stretch(&r_dst.w, &r_dst.h, &r_dst.x, &r_dst.y); + } else { + r_dst.w *= ((float) winx / (float) r_dst.w); + r_dst.h *= ((float) winy / (float) r_dst.h); + } ret = SDL_RenderCopy(sdl_render, sdl_tex, r_src, &r_dst); if (ret) - fprintf(stderr, "SDL: unable to copy texture to renderer (%s)\n", SDL_GetError()); + fprintf(stderr, "SDL: unable to copy texture to renderer (%s)\n", SDL_GetError()); SDL_RenderPresent(sdl_render); } @@ -178,27 +198,27 @@ sdl_blit(int x, int y, int w, int h) SDL_Rect r_src; if (!sdl_enabled || (x < 0) || (y < 0) || (w <= 0) || (h <= 0) || (w > 2048) || (h > 2048) || (buffer32 == NULL) || (sdl_render == NULL) || (sdl_tex == NULL)) { - r_src.x = x; - r_src.y = y; - r_src.w = w; - r_src.h = h; - sdl_real_blit(&r_src); - blitreq = 0; - return; + r_src.x = x; + r_src.y = y; + r_src.w = w; + r_src.h = h; + sdl_real_blit(&r_src); + blitreq = 0; + return; } SDL_LockMutex(sdl_mutex); - if (resize_pending) - { - if (!video_fullscreen) sdl_resize(resize_w, resize_h); + if (resize_pending) { + if (!video_fullscreen) + sdl_resize(resize_w, resize_h); resize_pending = 0; } r_src.x = x; r_src.y = y; r_src.w = w; r_src.h = h; - SDL_UpdateTexture(sdl_tex, &r_src, interpixels, 2048 * 4); + SDL_UpdateTexture(sdl_tex, &r_src, pixeldata, 2048 * 4); blitreq = 0; sdl_real_blit(&r_src); @@ -209,27 +229,24 @@ static void sdl_destroy_window(void) { if (sdl_win != NULL) { - if (window_remember) - { - SDL_GetWindowSize(sdl_win, &window_w, &window_h); - if (strncasecmp(SDL_GetCurrentVideoDriver(), "wayland", 7) != 0) - { - SDL_GetWindowPosition(sdl_win, &window_x, &window_y); + if (window_remember) { + SDL_GetWindowSize(sdl_win, &window_w, &window_h); + if (strncasecmp(SDL_GetCurrentVideoDriver(), "wayland", 7) != 0) { + SDL_GetWindowPosition(sdl_win, &window_x, &window_y); + } } - } - SDL_DestroyWindow(sdl_win); - sdl_win = NULL; + SDL_DestroyWindow(sdl_win); + sdl_win = NULL; } } - static void sdl_destroy_texture(void) { /* SDL_DestroyRenderer also automatically destroys all associated textures. */ if (sdl_render != NULL) { - SDL_DestroyRenderer(sdl_render); - sdl_render = NULL; + SDL_DestroyRenderer(sdl_render); + sdl_render = NULL; } } @@ -237,17 +254,17 @@ void sdl_close(void) { if (sdl_mutex != NULL) - SDL_LockMutex(sdl_mutex); + SDL_LockMutex(sdl_mutex); /* Unregister our renderer! */ video_setblit(NULL); if (sdl_enabled) - sdl_enabled = 0; + sdl_enabled = 0; if (sdl_mutex != NULL) { - SDL_DestroyMutex(sdl_mutex); - sdl_mutex = NULL; + SDL_DestroyMutex(sdl_mutex); + sdl_mutex = NULL; } sdl_destroy_texture(); @@ -258,20 +275,18 @@ sdl_close(void) sdl_flags = -1; } -static int old_capture = 0; - void sdl_enable(int enable) { if (sdl_flags == -1) - return; + return; SDL_LockMutex(sdl_mutex); sdl_enabled = !!enable; if (enable == 1) { - SDL_SetWindowSize(sdl_win, cur_ww, cur_wh); - sdl_reinit_texture(); + SDL_SetWindowSize(sdl_win, cur_ww, cur_wh); + sdl_reinit_texture(); } SDL_UnlockMutex(sdl_mutex); @@ -280,33 +295,30 @@ sdl_enable(int enable) static void sdl_select_best_hw_driver(void) { - int i; SDL_RendererInfo renderInfo; - for (i = 0; i < SDL_GetNumRenderDrivers(); ++i) - { - SDL_GetRenderDriverInfo(i, &renderInfo); - if (renderInfo.flags & SDL_RENDERER_ACCELERATED) { - SDL_SetHint(SDL_HINT_RENDER_DRIVER, renderInfo.name); - return; - } + for (int i = 0; i < SDL_GetNumRenderDrivers(); ++i) { + SDL_GetRenderDriverInfo(i, &renderInfo); + if (renderInfo.flags & SDL_RENDERER_ACCELERATED) { + SDL_SetHint(SDL_HINT_RENDER_DRIVER, renderInfo.name); + return; + } } } void -sdl_reinit_texture() +sdl_reinit_texture(void) { sdl_destroy_texture(); if (sdl_flags & RENDERER_HARDWARE) { - sdl_render = SDL_CreateRenderer(sdl_win, -1, SDL_RENDERER_ACCELERATED); - SDL_SetHint(SDL_HINT_RENDER_SCALE_QUALITY, video_filter_method ? "1" : "0"); + sdl_render = SDL_CreateRenderer(sdl_win, -1, SDL_RENDERER_ACCELERATED); + SDL_SetHint(SDL_HINT_RENDER_SCALE_QUALITY, video_filter_method ? "1" : "0"); } else - sdl_render = SDL_CreateRenderer(sdl_win, -1, SDL_RENDERER_SOFTWARE); + sdl_render = SDL_CreateRenderer(sdl_win, -1, SDL_RENDERER_SOFTWARE); sdl_tex = SDL_CreateTexture(sdl_render, SDL_PIXELFORMAT_ARGB8888, - SDL_TEXTUREACCESS_STREAMING, 2048, 2048); - + SDL_TEXTUREACCESS_STREAMING, 2048, 2048); } void @@ -314,14 +326,14 @@ sdl_set_fs(int fs) { SDL_LockMutex(sdl_mutex); SDL_SetWindowFullscreen(sdl_win, fs ? SDL_WINDOW_FULLSCREEN_DESKTOP : 0); - SDL_SetRelativeMouseMode((SDL_bool)mouse_capture); + SDL_SetRelativeMouseMode((SDL_bool) mouse_capture); sdl_fs = fs; if (fs) - sdl_flags |= RENDERER_FULL_SCREEN; + sdl_flags |= RENDERER_FULL_SCREEN; else - sdl_flags &= ~RENDERER_FULL_SCREEN; + sdl_flags &= ~RENDERER_FULL_SCREEN; sdl_reinit_texture(); SDL_UnlockMutex(sdl_mutex); @@ -330,13 +342,16 @@ sdl_set_fs(int fs) void sdl_resize(int x, int y) { - int ww = 0, wh = 0, wx = 0, wy = 0; + int ww = 0; + int wh = 0; + int wx = 0; + int wy = 0; if (video_fullscreen & 2) - return; + return; if ((x == cur_w) && (y == cur_h)) - return; + return; SDL_LockMutex(sdl_mutex); @@ -361,19 +376,18 @@ sdl_resize(int x, int y) void sdl_reload(void) { - if (sdl_flags & RENDERER_HARDWARE) - { - SDL_LockMutex(sdl_mutex); + if (sdl_flags & RENDERER_HARDWARE) { + SDL_LockMutex(sdl_mutex); - SDL_SetHint(SDL_HINT_RENDER_SCALE_QUALITY, video_filter_method ? "1" : "0"); - sdl_reinit_texture(); + SDL_SetHint(SDL_HINT_RENDER_SCALE_QUALITY, video_filter_method ? "1" : "0"); + sdl_reinit_texture(); - SDL_UnlockMutex(sdl_mutex); - } + SDL_UnlockMutex(sdl_mutex); + } } int -plat_vidapi(char* api) +plat_vidapi(char *api) { return 0; } @@ -381,7 +395,6 @@ plat_vidapi(char* api) static int sdl_init_common(int flags) { - wchar_t temp[128]; SDL_version ver; /* Get and log the version of the DLL we are using. */ @@ -390,30 +403,27 @@ sdl_init_common(int flags) /* Initialize the SDL system. */ if (SDL_Init(SDL_INIT_VIDEO) < 0) { - fprintf(stderr, "SDL: initialization failed (%s)\n", SDL_GetError()); - return(0); + fprintf(stderr, "SDL: initialization failed (%s)\n", SDL_GetError()); + return (0); } if (flags & RENDERER_HARDWARE) { - if (flags & RENDERER_OPENGL) { - SDL_SetHint(SDL_HINT_RENDER_DRIVER, "OpenGL"); - } - else - sdl_select_best_hw_driver(); + if (flags & RENDERER_OPENGL) { + SDL_SetHint(SDL_HINT_RENDER_DRIVER, "OpenGL"); + } else + sdl_select_best_hw_driver(); } sdl_mutex = SDL_CreateMutex(); - sdl_win = SDL_CreateWindow("86Box", strncasecmp(SDL_GetCurrentVideoDriver(), "wayland", 7) != 0 && window_remember ? window_x : SDL_WINDOWPOS_CENTERED, strncasecmp(SDL_GetCurrentVideoDriver(), "wayland", 7) != 0 && window_remember ? window_y : SDL_WINDOWPOS_CENTERED, scrnsz_x, scrnsz_y, SDL_WINDOW_OPENGL | (vid_resize & 1 ? SDL_WINDOW_RESIZABLE : 0)); + sdl_win = SDL_CreateWindow("86Box", strncasecmp(SDL_GetCurrentVideoDriver(), "wayland", 7) != 0 && window_remember ? window_x : SDL_WINDOWPOS_CENTERED, strncasecmp(SDL_GetCurrentVideoDriver(), "wayland", 7) != 0 && window_remember ? window_y : SDL_WINDOWPOS_CENTERED, scrnsz_x, scrnsz_y, SDL_WINDOW_OPENGL | (vid_resize & 1 ? SDL_WINDOW_RESIZABLE : 0)); sdl_set_fs(video_fullscreen); - if (!(video_fullscreen & 1)) - { + if (!(video_fullscreen & 1)) { if (vid_resize & 2) - plat_resize(fixed_size_x, fixed_size_y); + plat_resize(fixed_size_x, fixed_size_y); else - plat_resize(scrnsz_x, scrnsz_y); + plat_resize(scrnsz_x, scrnsz_y); } - if ((vid_resize < 2) && window_remember) - { + if ((vid_resize < 2) && window_remember) { SDL_SetWindowSize(sdl_win, window_w, window_h); } @@ -425,70 +435,67 @@ sdl_init_common(int flags) sdl_enabled = 1; - return(1); + return (1); } int -sdl_inits() +sdl_inits(void) { return sdl_init_common(0); } - int -sdl_inith() +sdl_inith(void) { return sdl_init_common(RENDERER_HARDWARE); } - int -sdl_initho() +sdl_initho(void) { return sdl_init_common(RENDERER_HARDWARE | RENDERER_OPENGL); } - int sdl_pause(void) { - return(0); + return 0; } void plat_mouse_capture(int on) { SDL_LockMutex(sdl_mutex); - SDL_SetRelativeMouseMode((SDL_bool)on); + SDL_SetRelativeMouseMode((SDL_bool) on); mouse_capture = on; SDL_UnlockMutex(sdl_mutex); } -void plat_resize(int w, int h) +void +plat_resize(int w, int h) { SDL_LockMutex(sdl_mutex); - resize_w = w; - resize_h = h; + resize_w = w; + resize_h = h; resize_pending = 1; SDL_UnlockMutex(sdl_mutex); } -wchar_t sdl_win_title[512] = { L'8', L'6', L'B', L'o', L'x', 0 }; -SDL_mutex* titlemtx = NULL; +wchar_t sdl_win_title[512] = { L'8', L'6', L'B', L'o', L'x', 0 }; +SDL_mutex *titlemtx = NULL; -void ui_window_title_real() +void +ui_window_title_real(void) { - char* res; - if (sizeof(wchar_t) == 1) - { - SDL_SetWindowTitle(sdl_win, (char*)sdl_win_title); + char *res; + if (sizeof(wchar_t) == 1) { + SDL_SetWindowTitle(sdl_win, (char *) sdl_win_title); return; } - res = SDL_iconv_string("UTF-8", sizeof(wchar_t) == 2 ? "UTF-16LE" : "UTF-32LE", (char*)sdl_win_title, wcslen(sdl_win_title) * sizeof(wchar_t) + sizeof(wchar_t)); - if (res) - { + res = SDL_iconv_string("UTF-8", sizeof(wchar_t) == 2 ? "UTF-16LE" : "UTF-32LE", (char *) sdl_win_title, wcslen(sdl_win_title) * sizeof(wchar_t) + sizeof(wchar_t)); + if (res) { SDL_SetWindowTitle(sdl_win, res); - SDL_free((void*)res); + SDL_free((void *) res); } title_set = 0; } @@ -496,9 +503,11 @@ extern SDL_threadID eventthread; /* Only activate threading path on macOS, otherwise it will softlock Xorg. Wayland doesn't seem to have this issue. */ -wchar_t* ui_window_title(wchar_t* str) +wchar_t * +ui_window_title(wchar_t *str) { - if (!str) return sdl_win_title; + if (!str) + return sdl_win_title; #ifdef __APPLE__ if (eventthread == SDL_ThreadID()) #endif @@ -515,3 +524,21 @@ wchar_t* ui_window_title(wchar_t* str) #endif return str; } + +void +ui_init_monitor(int monitor_index) +{ + /* No-op. */ +} + +void +ui_deinit_monitor(int monitor_index) +{ + /* No-op. */ +} + +void +plat_resize_request(int w, int h, int monitor_index) +{ + atomic_store((&doresize_monitors[monitor_index]), 1); +} diff --git a/src/unix/unix_serial_passthrough.c b/src/unix/unix_serial_passthrough.c new file mode 100644 index 000000000..d80f8a1e7 --- /dev/null +++ b/src/unix/unix_serial_passthrough.c @@ -0,0 +1,319 @@ +/* + * 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. + * + * Definitions for platform specific serial to host passthrough + * + * + * Authors: Andreas J. Reichel , + * Jasmine Iwanek + * + * Copyright 2021 Andreas J. Reichel. + * Copyright 2021-2022 Jasmine Iwanek. + */ + +#ifndef __APPLE__ +# define _XOPEN_SOURCE 500 +# define _DEFAULT_SOURCE 1 +# define _BSD_SOURCE 1 +#endif +#if defined(__FreeBSD__) || defined(__OpenBSD__) || defined(__NetBSD__) || defined(__DragonFly__) +# define __BSD_VISIBLE 1 +#endif +#include +#include +#include +#include +#include +#include +#include +#include + +#include <86box/86box.h> +#include <86box/log.h> +#include <86box/plat.h> +#include <86box/device.h> +#include <86box/serial_passthrough.h> +#include <86box/plat_serial_passthrough.h> +#include +#include + +#define LOG_PREFIX "serial_passthrough: " + +int +plat_serpt_read(void *priv, uint8_t *data) +{ + serial_passthrough_t *dev = (serial_passthrough_t *) priv; + int res; + struct timeval tv; + fd_set rdfds; + + switch (dev->mode) { + case SERPT_MODE_VCON: + case SERPT_MODE_HOSTSER: + FD_ZERO(&rdfds); + FD_SET(dev->master_fd, &rdfds); + tv.tv_sec = 0; + tv.tv_usec = 0; + + res = select(dev->master_fd + 1, &rdfds, NULL, NULL, &tv); + if (res <= 0 || !FD_ISSET(dev->master_fd, &rdfds)) { + return 0; + } + + if (read(dev->master_fd, data, 1) > 0) { + return 1; + } + break; + default: + break; + } + return 0; +} + +void +plat_serpt_close(void *priv) +{ + serial_passthrough_t *dev = (serial_passthrough_t *) priv; + + if (dev->mode == SERPT_MODE_HOSTSER) { + tcsetattr(dev->master_fd, TCSANOW, (struct termios *) dev->backend_priv); + free(dev->backend_priv); + } + close(dev->master_fd); +} + +static void +plat_serpt_write_vcon(serial_passthrough_t *dev, uint8_t data) +{ +#if 0 + fd_set wrfds; + int res; +#endif + size_t res; + + /* We cannot use select here, this would block the hypervisor! */ +#if 0 + FD_ZERO(&wrfds); + FD_SET(ctx->master_fd, &wrfds); + + res = select(ctx->master_fd + 1, NULL, &wrfds, NULL, NULL); + + if (res <= 0) { + return; + } +#endif + + /* just write it out */ + if (dev->mode == SERPT_MODE_HOSTSER) { + do { + res = write(dev->master_fd, &data, 1); + } while (res == 0 || (res == -1 && (errno == EAGAIN || res == EWOULDBLOCK))); + } else + res = write(dev->master_fd, &data, 1); +} + +void +plat_serpt_set_params(void *priv) +{ + serial_passthrough_t *dev = (serial_passthrough_t *) priv; + + if (dev->mode == SERPT_MODE_HOSTSER) { + struct termios term_attr; + tcgetattr(dev->master_fd, &term_attr); +#define BAUDRATE_RANGE(baud_rate, min, max, val) \ + if (baud_rate >= min && baud_rate < max) { \ + cfsetispeed(&term_attr, val); \ + cfsetospeed(&term_attr, val); \ + } + + BAUDRATE_RANGE(dev->baudrate, 50, 75, B50); + BAUDRATE_RANGE(dev->baudrate, 75, 110, B75); + BAUDRATE_RANGE(dev->baudrate, 110, 134, B110); + BAUDRATE_RANGE(dev->baudrate, 134, 150, B134); + BAUDRATE_RANGE(dev->baudrate, 150, 200, B150); + BAUDRATE_RANGE(dev->baudrate, 200, 300, B200); + BAUDRATE_RANGE(dev->baudrate, 300, 600, B300); + BAUDRATE_RANGE(dev->baudrate, 600, 1200, B600); + BAUDRATE_RANGE(dev->baudrate, 1200, 1800, B1200); + BAUDRATE_RANGE(dev->baudrate, 1800, 2400, B1800); + BAUDRATE_RANGE(dev->baudrate, 2400, 4800, B2400); + BAUDRATE_RANGE(dev->baudrate, 4800, 9600, B4800); + BAUDRATE_RANGE(dev->baudrate, 9600, 19200, B9600); + BAUDRATE_RANGE(dev->baudrate, 19200, 38400, B19200); + BAUDRATE_RANGE(dev->baudrate, 38400, 57600, B38400); + BAUDRATE_RANGE(dev->baudrate, 57600, 115200, B57600); + BAUDRATE_RANGE(dev->baudrate, 115200, 0xFFFFFFFF, B115200); + + term_attr.c_cflag &= ~CSIZE; + switch (dev->data_bits) { + case 8: + default: + term_attr.c_cflag |= CS8; + break; + case 7: + term_attr.c_cflag |= CS7; + break; + case 6: + term_attr.c_cflag |= CS6; + break; + case 5: + term_attr.c_cflag |= CS5; + break; + } + term_attr.c_cflag &= ~CSTOPB; + if (dev->serial->lcr & 0x04) + term_attr.c_cflag |= CSTOPB; +#if !defined(__linux__) + term_attr.c_cflag &= ~(PARENB | PARODD); +#else + term_attr.c_cflag &= ~(PARENB | PARODD | CMSPAR); +#endif + if (dev->serial->lcr & 0x08) { + term_attr.c_cflag |= PARENB; + if (!(dev->serial->lcr & 0x10)) + term_attr.c_cflag |= PARODD; +#if defined(__linux__) + if ((dev->serial->lcr & 0x20)) + term_attr.c_cflag |= CMSPAR; +#endif + } + tcsetattr(dev->master_fd, TCSANOW, &term_attr); +#undef BAUDRATE_RANGE + } +} + +void +plat_serpt_write(void *priv, uint8_t data) +{ + serial_passthrough_t *dev = (serial_passthrough_t *) priv; + + switch (dev->mode) { + case SERPT_MODE_VCON: + case SERPT_MODE_HOSTSER: + plat_serpt_write_vcon(dev, data); + break; + default: + break; + } +} + +static int +open_pseudo_terminal(serial_passthrough_t *dev) +{ + int master_fd = open("/dev/ptmx", O_RDWR | O_NONBLOCK); + char *ptname; + struct termios term_attr_raw; + + if (!master_fd) { + return 0; + } + + /* get name of slave device */ + if (!(ptname = ptsname(master_fd))) { + pclog(LOG_PREFIX "could not get name of slave pseudo terminal"); + close(master_fd); + return 0; + } + memset(dev->slave_pt, 0, sizeof(dev->slave_pt)); + strncpy(dev->slave_pt, ptname, sizeof(dev->slave_pt) - 1); + + fprintf(stderr, LOG_PREFIX "Slave side is %s\n", dev->slave_pt); + + if (grantpt(master_fd)) { + pclog(LOG_PREFIX "error in grantpt()\n"); + close(master_fd); + return 0; + } + + if (unlockpt(master_fd)) { + pclog(LOG_PREFIX "error in unlockpt()\n"); + close(master_fd); + return 0; + } + + tcgetattr(master_fd, &term_attr_raw); + cfmakeraw(&term_attr_raw); + tcsetattr(master_fd, TCSANOW, &term_attr_raw); + + dev->master_fd = master_fd; + + return master_fd; +} + +static int +open_host_serial_port(serial_passthrough_t *dev) +{ + struct termios *term_attr = NULL; + struct termios term_attr_raw = {}; + int fd = open(dev->host_serial_path, O_RDWR | O_NOCTTY | O_NONBLOCK); + if (fd == -1) { + return 0; + } + + if (!isatty(fd)) { + return 0; + } + + term_attr = calloc(1, sizeof(struct termios)); + if (!term_attr) { + close(fd); + return 0; + } + + if (tcgetattr(fd, term_attr) == -1) { + free(term_attr); + close(fd); + return 0; + } + term_attr_raw = *term_attr; + /* "Raw" mode. */ + cfmakeraw(&term_attr_raw); + term_attr_raw.c_cflag &= CSIZE; + switch (dev->data_bits) { + case 8: + default: + term_attr_raw.c_cflag |= CS8; + break; + case 7: + term_attr_raw.c_cflag |= CS7; + break; + case 6: + term_attr_raw.c_cflag |= CS6; + break; + case 5: + term_attr_raw.c_cflag |= CS5; + break; + } + tcsetattr(fd, TCSANOW, &term_attr_raw); + dev->backend_priv = term_attr; + dev->master_fd = fd; + pclog(LOG_PREFIX "Opened host TTY/serial port %s\n", dev->host_serial_path); + return 1; +} + +int +plat_serpt_open_device(void *priv) +{ + serial_passthrough_t *dev = (serial_passthrough_t *) priv; + + switch (dev->mode) { + case SERPT_MODE_VCON: + if (!open_pseudo_terminal(dev)) { + return 1; + } + break; + case SERPT_MODE_HOSTSER: + if (!open_host_serial_port(dev)) { + return 1; + } + break; + default: + break; + } + return 0; +} diff --git a/src/unix/unix_thread.c b/src/unix/unix_thread.c index 564b1943b..0c2e9bf6b 100644 --- a/src/unix/unix_thread.c +++ b/src/unix/unix_thread.c @@ -5,31 +5,25 @@ #include #include <86box/86box.h> #include <86box/plat.h> +#include <86box/thread.h> - -typedef struct event_pthread_t -{ - pthread_cond_t cond; - pthread_mutex_t mutex; - int state; +typedef struct event_pthread_t { + pthread_cond_t cond; + pthread_mutex_t mutex; + int state; } event_pthread_t; - -typedef struct thread_param -{ - void (*thread_rout)(void*); - void * param; +typedef struct thread_param { + void (*thread_rout)(void *); + void *param; } thread_param; - -typedef struct pt_mutex_t -{ - pthread_mutex_t mutex; +typedef struct pt_mutex_t { + pthread_mutex_t mutex; } pt_mutex_t; - void * -thread_run_wrapper(thread_param* arg) +thread_run_wrapper(thread_param *arg) { thread_param localparam = *arg; free(arg); @@ -37,28 +31,25 @@ thread_run_wrapper(thread_param* arg) return NULL; } - thread_t * thread_create(void (*thread_rout)(void *param), void *param) { - pthread_t *thread = malloc(sizeof(pthread_t)); + pthread_t *thread = malloc(sizeof(pthread_t)); thread_param *thrparam = malloc(sizeof(thread_param)); - thrparam->thread_rout = thread_rout; - thrparam->param = param; + thrparam->thread_rout = thread_rout; + thrparam->param = param; - pthread_create(thread, NULL, (void* (*)(void*))thread_run_wrapper, thrparam); + pthread_create(thread, NULL, (void *(*) (void *) ) thread_run_wrapper, thrparam); return thread; } - int thread_wait(thread_t *arg) { - return pthread_join(*(pthread_t*)(arg), NULL); + return pthread_join(*(pthread_t *) (arg), NULL); } - event_t * thread_create_event() { @@ -68,14 +59,13 @@ thread_create_event() pthread_mutex_init(&event->mutex, NULL); event->state = 0; - return (event_t *)event; + return (event_t *) event; } - void thread_set_event(event_t *handle) { - event_pthread_t *event = (event_pthread_t *)handle; + event_pthread_t *event = (event_pthread_t *) handle; pthread_mutex_lock(&event->mutex); event->state = 1; @@ -83,48 +73,45 @@ thread_set_event(event_t *handle) pthread_mutex_unlock(&event->mutex); } - void thread_reset_event(event_t *handle) { - event_pthread_t *event = (event_pthread_t *)handle; + event_pthread_t *event = (event_pthread_t *) handle; pthread_mutex_lock(&event->mutex); event->state = 0; pthread_mutex_unlock(&event->mutex); } - int thread_wait_event(event_t *handle, int timeout) { - event_pthread_t *event = (event_pthread_t *)handle; - struct timespec abstime; + event_pthread_t *event = (event_pthread_t *) handle; + struct timespec abstime; clock_gettime(CLOCK_REALTIME, &abstime); abstime.tv_nsec += (timeout % 1000) * 1000000; abstime.tv_sec += (timeout / 1000); if (abstime.tv_nsec > 1000000000) { - abstime.tv_nsec -= 1000000000; - abstime.tv_sec++; + abstime.tv_nsec -= 1000000000; + abstime.tv_sec++; } pthread_mutex_lock(&event->mutex); if (timeout == -1) { - while (!event->state) - pthread_cond_wait(&event->cond, &event->mutex); + while (!event->state) + pthread_cond_wait(&event->cond, &event->mutex); } else if (!event->state) - pthread_cond_timedwait(&event->cond, &event->mutex, &abstime); + pthread_cond_timedwait(&event->cond, &event->mutex, &abstime); pthread_mutex_unlock(&event->mutex); return 0; } - void thread_destroy_event(event_t *handle) { - event_pthread_t *event = (event_pthread_t *)handle; + event_pthread_t *event = (event_pthread_t *) handle; pthread_cond_destroy(&event->cond); pthread_mutex_destroy(&event->mutex); @@ -132,7 +119,6 @@ thread_destroy_event(event_t *handle) free(event); } - mutex_t * thread_create_mutex(void) { @@ -143,34 +129,40 @@ thread_create_mutex(void) return mutex; } - int thread_wait_mutex(mutex_t *_mutex) { if (_mutex == NULL) - return(0); - pt_mutex_t *mutex = (pt_mutex_t *)_mutex; + return 0; + pt_mutex_t *mutex = (pt_mutex_t *) _mutex; - return - pthread_mutex_lock(&mutex->mutex) != 0; + return pthread_mutex_lock(&mutex->mutex) != 0; } +int +thread_test_mutex(mutex_t *_mutex) +{ + if (_mutex == NULL) + return 0; + pt_mutex_t *mutex = (pt_mutex_t *) _mutex; + + return pthread_mutex_trylock(&mutex->mutex) != 0; +} int thread_release_mutex(mutex_t *_mutex) { if (_mutex == NULL) - return(0); - pt_mutex_t *mutex = (pt_mutex_t *)_mutex; + return 0; + pt_mutex_t *mutex = (pt_mutex_t *) _mutex; return pthread_mutex_unlock(&mutex->mutex) != 0; } - void thread_close_mutex(mutex_t *_mutex) { - pt_mutex_t *mutex = (pt_mutex_t *)_mutex; + pt_mutex_t *mutex = (pt_mutex_t *) _mutex; pthread_mutex_destroy(&mutex->mutex); diff --git a/src/upi42.c b/src/upi42.c new file mode 100644 index 000000000..50f5c44c9 --- /dev/null +++ b/src/upi42.c @@ -0,0 +1,1456 @@ +/* + * 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. + * + * Intel UPI-42/MCS-48 microcontroller emulation. + * + * + * + * Authors: RichardG, + * + * Copyright 2022 RichardG. + */ +#include +#include +#include +#include +#include <86box/plat_unused.h> + +#ifdef UPI42_STANDALONE +# define fatal(...) \ + { \ + upi42_log(__VA_ARGS__); \ + abort(); \ + } +# define upi42_log(...) \ + { \ + printf(__VA_ARGS__); \ + fflush(stdout); \ + } +#else +# include +# define HAVE_STDARG_H +# include <86box/86box.h> +# include <86box/device.h> +# include <86box/io.h> +# include <86box/timer.h> + +# ifdef ENABLE_UPI42_LOG +int upi42_do_log = ENABLE_UPI42_LOG; + +void +upi42_log(const char *fmt, ...) +{ + va_list ap; + + if (upi42_do_log) { + va_start(ap, fmt); + pclog_ex(fmt, ap); + va_end(ap); + } +} +# else +# define upi42_log(fmt, ...) +# endif +#endif + +#define UPI42_REG(upi42, r, op) ((upi42->psw & 0x10) ? (upi42->ram[24 + ((r) &7)] op) : (upi42->ram[(r) &7] op)) + +#define UPI42_ROM_SHIFT 0 /* actually the mask */ +#define UPI42_RAM_SHIFT 16 /* actually the mask */ +#define UPI42_TYPE_MCS (0 << 24) +#define UPI42_TYPE_UPI (1 << 24) +#define UPI42_EXT_C42 (1 << 25) + +#define UPI42_8048 ((1023 << UPI42_ROM_SHIFT) | (63 << UPI42_RAM_SHIFT) | UPI42_TYPE_MCS) +#define UPI42_8049 ((2047 << UPI42_ROM_SHIFT) | (127 << UPI42_RAM_SHIFT) | UPI42_TYPE_MCS) +#define UPI42_8041 ((1023 << UPI42_ROM_SHIFT) | (127 << UPI42_RAM_SHIFT) | UPI42_TYPE_UPI) +#define UPI42_8042 ((2047 << UPI42_ROM_SHIFT) | (255 << UPI42_RAM_SHIFT) | UPI42_TYPE_UPI) +#define UPI42_80C42 ((4095 << UPI42_ROM_SHIFT) | (255 << UPI42_RAM_SHIFT) | UPI42_TYPE_UPI | UPI42_EXT_C42) + +typedef struct _upi42_ { + int (*ops[256])(struct _upi42_ *upi42, uint32_t fetchdat); + uint32_t type; + uint8_t ram[256], *rom, /* memory */ + ports_in[8], ports_out[8], /* I/O ports */ + dbb_in, dbb_out; /* UPI-42 data buffer */ + + uint8_t rammask, /* RAM mask */ + a, /* accumulator */ + t, /* timer counter */ + psw, /* program status word */ + sts; /* UPI-42 status */ + + uint16_t pc, rommask; /* program counter and ROM mask */ + + unsigned int prescaler : 5, tf : 1, skip_timer_inc : 1, /* timer/counter */ + run_timer : 1, run_counter : 1, tcnti : 1, /* timer/counter enables */ + i : 1, i_raise : 1, tcnti_raise : 1, irq_mask : 1, /* interrupts */ + t0 : 1, t1 : 1, /* T0/T1 signals */ + flags : 1, dbf : 1, suspend : 1; /* UPI-42 flags */ + + int cycs; /* cycle counter */ + +#ifndef UPI42_STANDALONE + uint8_t ram_index; + uint16_t rom_index; +#endif +} upi42_t; + +static inline void +upi42_mirror_f0(upi42_t *upi42) +{ + /* Update status register F0 flag to match PSW F0 flag. */ + upi42->sts = ((upi42->psw & 0x20) >> 3) | (upi42->sts & ~0x04); +} + +static int +upi42_op_MOV_A_Rr(upi42_t *upi42, uint32_t fetchdat) +{ + upi42->a = UPI42_REG(upi42, fetchdat, ); + return 1; +} + +static int +upi42_op_MOV_Rr_A(upi42_t *upi42, uint32_t fetchdat) +{ + UPI42_REG(upi42, fetchdat, = upi42->a); + return 1; +} + +static int +upi42_op_MOV_A_indRr(upi42_t *upi42, uint32_t fetchdat) +{ + upi42->a = upi42->ram[upi42->ram[fetchdat & 1] & upi42->rammask]; + return 1; +} + +static int +upi42_op_MOV_indRr_A(upi42_t *upi42, uint32_t fetchdat) +{ + upi42->ram[upi42->ram[fetchdat & 1] & upi42->rammask] = upi42->a; + return 1; +} + +static int +upi42_op_MOV_Rr_imm(upi42_t *upi42, uint32_t fetchdat) +{ + UPI42_REG(upi42, fetchdat, = fetchdat >> 8); + upi42->cycs--; + return 2; +} + +static int +upi42_op_MOV_indRr_imm(upi42_t *upi42, uint32_t fetchdat) +{ + upi42->ram[upi42->ram[fetchdat & 1] & upi42->rammask] = fetchdat >> 8; + upi42->cycs--; + return 2; +} + +static int +upi42_op_MOV_A_imm(upi42_t *upi42, uint32_t fetchdat) +{ + upi42->a = fetchdat >> 8; + upi42->cycs--; + return 2; +} + +static int +upi42_op_MOV_A_PSW(upi42_t *upi42, UNUSED(uint32_t fetchdat)) +{ + upi42->a = upi42->psw; + upi42_mirror_f0(upi42); + return 1; +} + +static int +upi42_op_MOV_PSW_A(upi42_t *upi42, UNUSED(uint32_t fetchdat)) +{ + upi42->psw = upi42->a; + upi42_mirror_f0(upi42); + return 1; +} + +static int +upi42_op_MOV_A_T(upi42_t *upi42, UNUSED(uint32_t fetchdat)) +{ + upi42->a = upi42->t; + return 1; +} + +static int +upi42_op_MOV_T_A(upi42_t *upi42, UNUSED(uint32_t fetchdat)) +{ + upi42->t = upi42->a; + return 1; +} + +static int +upi42_op_MOV_STS_A(upi42_t *upi42, UNUSED(uint32_t fetchdat)) +{ + upi42->sts = (upi42->a & 0xf0) | (upi42->sts & 0x0f); + return 1; +} + +static int +upi42_op_MOVP_A_indA(upi42_t *upi42, UNUSED(uint32_t fetchdat)) +{ + upi42->a = upi42->rom[(upi42->pc & 0xff00) | upi42->a]; + upi42->cycs--; + return 1; +} + +static int +upi42_op_MOVP3_A_indA(upi42_t *upi42, UNUSED(uint32_t fetchdat)) +{ + upi42->a = upi42->rom[0x300 | upi42->a]; + upi42->cycs--; + return 1; +} + +static int +upi42_op_XCH_A_Rr(upi42_t *upi42, uint32_t fetchdat) +{ + uint8_t temp = upi42->a; + upi42->a = UPI42_REG(upi42, fetchdat, ); + UPI42_REG(upi42, fetchdat, = temp); + return 1; +} + +static int +upi42_op_XCH_A_indRr(upi42_t *upi42, uint32_t fetchdat) +{ + uint8_t temp = upi42->a; + uint8_t addr = upi42->ram[fetchdat & 1] & upi42->rammask; + upi42->a = upi42->ram[addr]; + upi42->ram[addr] = temp; + return 1; +} + +static int +upi42_op_XCHD_A_indRr(upi42_t *upi42, uint32_t fetchdat) +{ + uint8_t temp = upi42->a; + uint8_t addr = upi42->ram[fetchdat & 1] & upi42->rammask; + upi42->a = (upi42->a & 0xf0) | (upi42->ram[addr] & 0x0f); + upi42->ram[addr] = (upi42->ram[addr] & 0xf0) | (temp & 0x0f); + return 1; +} + +static int +upi42_op_SWAP_A(upi42_t *upi42, UNUSED(uint32_t fetchdat)) +{ + upi42->a = (upi42->a << 4) | (upi42->a >> 4); + return 1; +} + +static int +upi42_op_IN_A_Pp(upi42_t *upi42, uint32_t fetchdat) +{ + int port = fetchdat & 3; + upi42->a = upi42->ports_in[port] & upi42->ports_out[port]; + upi42->cycs--; + return 1; +} + +static int +upi42_op_IN_A_DBB(upi42_t *upi42, UNUSED(uint32_t fetchdat)) +{ + upi42->a = upi42->dbb_in; + upi42->sts &= ~0x02; /* clear IBF */ + return 1; +} + +static int +upi42_op_OUTL_Pp_A(upi42_t *upi42, UNUSED(uint32_t fetchdat)) +{ + upi42->ports_out[fetchdat & 3] = upi42->a; + upi42->cycs--; + return 1; +} + +static int +upi42_op_OUT_DBB_A(upi42_t *upi42, UNUSED(uint32_t fetchdat)) +{ + upi42->dbb_out = upi42->a; + upi42->sts |= 0x01; /* set OBF */ + return 1; +} + +static int +upi42_op_MOVD_A_Pp(upi42_t *upi42, uint32_t fetchdat) +{ + int port = 4 | (fetchdat & 3); + upi42->a = (upi42->ports_in[port] & upi42->ports_out[port]) & 0x0f; + upi42->cycs--; + return 1; +} + +static int +upi42_op_MOVD_Pp_A(upi42_t *upi42, uint32_t fetchdat) +{ + upi42->ports_out[4 | (fetchdat & 3)] = upi42->a & 0x0f; + upi42->cycs--; + return 1; +} + +static int +upi42_op_ANL_A_Rr(upi42_t *upi42, uint32_t fetchdat) +{ + upi42->a &= UPI42_REG(upi42, fetchdat, ); + return 1; +} + +static int +upi42_op_ORL_A_Rr(upi42_t *upi42, uint32_t fetchdat) +{ + upi42->a |= UPI42_REG(upi42, fetchdat, ); + return 1; +} + +static int +upi42_op_XRL_A_Rr(upi42_t *upi42, uint32_t fetchdat) +{ + upi42->a ^= UPI42_REG(upi42, fetchdat, ); + return 1; +} + +static int +upi42_op_ANL_A_indRr(upi42_t *upi42, uint32_t fetchdat) +{ + upi42->a &= upi42->ram[upi42->ram[fetchdat & 1] & upi42->rammask]; + return 1; +} + +static int +upi42_op_ORL_A_indRr(upi42_t *upi42, uint32_t fetchdat) +{ + upi42->a |= upi42->ram[upi42->ram[fetchdat & 1] & upi42->rammask]; + return 1; +} + +static int +upi42_op_XRL_A_indRr(upi42_t *upi42, uint32_t fetchdat) +{ + upi42->a ^= upi42->ram[upi42->ram[fetchdat & 1] & upi42->rammask]; + return 1; +} + +static int +upi42_op_ANL_A_imm(upi42_t *upi42, uint32_t fetchdat) +{ + upi42->a &= fetchdat >> 8; + upi42->cycs--; + return 2; +} + +static int +upi42_op_ORL_A_imm(upi42_t *upi42, uint32_t fetchdat) +{ + upi42->a |= fetchdat >> 8; + upi42->cycs--; + return 2; +} + +static int +upi42_op_XRL_A_imm(upi42_t *upi42, uint32_t fetchdat) +{ + upi42->a ^= fetchdat >> 8; + upi42->cycs--; + return 2; +} + +static int +upi42_op_ANL_Pp_imm(upi42_t *upi42, uint32_t fetchdat) +{ + upi42->ports_out[fetchdat & 3] &= fetchdat >> 8; + upi42->cycs--; + return 2; +} + +static int +upi42_op_ORL_Pp_imm(upi42_t *upi42, uint32_t fetchdat) +{ + upi42->ports_out[fetchdat & 3] |= fetchdat >> 8; + upi42->cycs--; + return 2; +} + +static int +upi42_op_ANLD_Pp_A(upi42_t *upi42, uint32_t fetchdat) +{ + upi42->ports_out[4 | (fetchdat & 3)] &= upi42->a; + upi42->cycs--; + return 1; +} + +static int +upi42_op_ORLD_Pp_A(upi42_t *upi42, uint32_t fetchdat) +{ + upi42->ports_out[4 | (fetchdat & 3)] |= upi42->a; + upi42->cycs--; + return 1; +} + +static int +upi42_op_RR_A(upi42_t *upi42, UNUSED(uint32_t fetchdat)) +{ + upi42->a = (upi42->a << 7) | (upi42->a >> 1); + return 1; +} + +static int +upi42_op_RL_A(upi42_t *upi42, UNUSED(uint32_t fetchdat)) +{ + upi42->a = (upi42->a >> 7) | (upi42->a << 1); + return 1; +} + +static int +upi42_op_RRC_A(upi42_t *upi42, UNUSED(uint32_t fetchdat)) +{ + uint8_t temp = upi42->a; + upi42->a = (upi42->psw & 0x80) | (temp >> 1); + upi42->psw = (temp << 7) | (upi42->psw & ~0x80); + return 1; +} + +static int +upi42_op_RLC_A(upi42_t *upi42, UNUSED(uint32_t fetchdat)) +{ + uint8_t temp = upi42->a; + upi42->a = (temp << 1) | (upi42->psw >> 7); + upi42->psw = (temp & 0x80) | (upi42->psw & ~0x80); + return 1; +} + +static int +upi42_op_INC_A(upi42_t *upi42, UNUSED(uint32_t fetchdat)) +{ + upi42->a++; + return 1; +} + +static int +upi42_op_INC_Rr(upi42_t *upi42, uint32_t fetchdat) +{ + UPI42_REG(upi42, fetchdat, ++); + return 1; +} + +static int +upi42_op_INC_indRr(upi42_t *upi42, uint32_t fetchdat) +{ + upi42->ram[upi42->ram[fetchdat & 1] & upi42->rammask]++; + return 1; +} + +static int +upi42_op_DEC_A(upi42_t *upi42, UNUSED(uint32_t fetchdat)) +{ + upi42->a--; + return 1; +} + +static int +upi42_op_DEC_Rr(upi42_t *upi42, uint32_t fetchdat) +{ + UPI42_REG(upi42, fetchdat, --); + return 1; +} + +static int +upi42_op_DJNZ_Rr_imm(upi42_t *upi42, uint32_t fetchdat) +{ + upi42->cycs--; + UPI42_REG(upi42, fetchdat, --); + if (UPI42_REG(upi42, fetchdat, )) { + upi42->pc = (upi42->pc & 0xff00) | ((fetchdat >> 8) & 0xff); + return 0; + } else { + return 2; + } +} + +static int +upi42_op_ADD_A_Rr(upi42_t *upi42, uint32_t fetchdat) +{ + int res = upi42->a + UPI42_REG(upi42, fetchdat, ); + upi42->a = res; + upi42->psw = ((res >> 1) & 0x80) | (upi42->psw & ~0x80); + return 1; +} + +static int +upi42_op_ADDC_A_Rr(upi42_t *upi42, uint32_t fetchdat) +{ + int res = upi42->a + (upi42->psw >> 7) + UPI42_REG(upi42, fetchdat, ); + upi42->a = res; + upi42->psw = ((res >> 1) & 0x80) | (upi42->psw & ~0x80); + return 1; +} + +static int +upi42_op_ADD_A_indRr(upi42_t *upi42, uint32_t fetchdat) +{ + int res = upi42->a + upi42->ram[UPI42_REG(upi42, fetchdat, ) & upi42->rammask]; + upi42->a = res; + upi42->psw = ((res >> 1) & 0x80) | (upi42->psw & ~0x80); + return 1; +} + +static int +upi42_op_ADDC_A_indRr(upi42_t *upi42, uint32_t fetchdat) +{ + int res = upi42->a + (upi42->psw >> 7) + upi42->ram[UPI42_REG(upi42, fetchdat, ) & upi42->rammask]; + upi42->a = res; + upi42->psw = ((res >> 1) & 0x80) | (upi42->psw & ~0x80); + return 1; +} + +static int +upi42_op_ADD_A_imm(upi42_t *upi42, uint32_t fetchdat) +{ + int res = upi42->a + (fetchdat >> 8); + upi42->a = res; + upi42->psw = ((res >> 1) & 0x80) | (upi42->psw & ~0x80); + upi42->cycs--; + return 2; +} + +static int +upi42_op_ADDC_A_imm(upi42_t *upi42, uint32_t fetchdat) +{ + int res = upi42->a + (upi42->psw >> 7) + (fetchdat >> 8); + upi42->a = res; + upi42->psw = ((res >> 1) & 0x80) | (upi42->psw & ~0x80); + upi42->cycs--; + return 2; +} + +static int +upi42_op_CLR_A(upi42_t *upi42, UNUSED(uint32_t fetchdat)) +{ + upi42->a = 0; + return 1; +} + +static int +upi42_op_CPL_A(upi42_t *upi42, UNUSED(uint32_t fetchdat)) +{ + upi42->a = ~upi42->a; + return 1; +} + +static int +upi42_op_DA_A(upi42_t *upi42, UNUSED(uint32_t fetchdat)) +{ + if (((upi42->a & 0x0f) > 9) || (upi42->psw & 0x40)) + upi42->a += 6; + if (((upi42->a >> 4) > 9) || (upi42->psw & 0x80)) { + int res = upi42->a + (6 << 4); + upi42->a = res; + upi42->psw = ((res >> 1) & 0x80) | (upi42->psw & ~0x80); + } + return 1; +} + +static int +upi42_op_CLR_C(upi42_t *upi42, UNUSED(uint32_t fetchdat)) +{ + upi42->psw &= ~0x80; + return 1; +} + +static int +upi42_op_CPL_C(upi42_t *upi42, UNUSED(uint32_t fetchdat)) +{ + upi42->psw ^= 0x80; + return 1; +} + +static int +upi42_op_CLR_F0(upi42_t *upi42, UNUSED(uint32_t fetchdat)) +{ + upi42->psw &= ~0x20; + upi42_mirror_f0(upi42); + return 1; +} + +static int +upi42_op_CPL_F0(upi42_t *upi42, UNUSED(uint32_t fetchdat)) +{ + upi42->psw ^= 0x20; + upi42_mirror_f0(upi42); + return 1; +} + +static int +upi42_op_CLR_F1(upi42_t *upi42, UNUSED(uint32_t fetchdat)) +{ + upi42->sts &= ~0x08; + return 1; +} + +static int +upi42_op_CPL_F1(upi42_t *upi42, UNUSED(uint32_t fetchdat)) +{ + upi42->sts ^= 0x08; + return 1; +} + +static int +upi42_op_EN_I(upi42_t *upi42, UNUSED(uint32_t fetchdat)) +{ + upi42->i = 1; + upi42->skip_timer_inc = 1; + return 1; +} + +static int +upi42_op_DIS_I(upi42_t *upi42, UNUSED(uint32_t fetchdat)) +{ + upi42->i = 0; + upi42->skip_timer_inc = 1; + return 1; +} + +static int +upi42_op_EN_TCNTI(upi42_t *upi42, UNUSED(uint32_t fetchdat)) +{ + upi42->tcnti = 1; + return 1; +} + +static int +upi42_op_DIS_TCNTI(upi42_t *upi42, UNUSED(uint32_t fetchdat)) +{ + upi42->tcnti = upi42->tcnti_raise = 0; + return 1; +} + +static int +upi42_op_STRT_T(upi42_t *upi42, UNUSED(uint32_t fetchdat)) +{ + upi42->run_timer = 1; + upi42->prescaler = 0; + upi42->skip_timer_inc = 1; + return 1; +} + +static int +upi42_op_STRT_CNT(upi42_t *upi42, UNUSED(uint32_t fetchdat)) +{ + upi42->run_counter = 1; + upi42->skip_timer_inc = 1; + return 1; +} + +static int +upi42_op_STOP_TCNT(upi42_t *upi42, UNUSED(uint32_t fetchdat)) +{ + upi42->run_timer = upi42->run_counter = 0; + upi42->skip_timer_inc = 1; + return 1; +} + +static int +upi42_op_SEL_PMB0(upi42_t *upi42, UNUSED(uint32_t fetchdat)) +{ + upi42->dbf = 0; + return 1; +} + +static int +upi42_op_SEL_PMB1(upi42_t *upi42, UNUSED(uint32_t fetchdat)) +{ + upi42->dbf = 1; + return 1; +} + +static int +upi42_op_SEL_RB0(upi42_t *upi42, UNUSED(uint32_t fetchdat)) +{ + upi42->psw &= ~0x10; + return 1; +} + +static int +upi42_op_SEL_RB1(upi42_t *upi42, UNUSED(uint32_t fetchdat)) +{ + upi42->psw |= 0x10; + return 1; +} + +static int +upi42_op_NOP(UNUSED(upi42_t *upi42), UNUSED(uint32_t fetchdat)) +{ + return 1; +} + +static int +upi42_op_CALL_imm(upi42_t *upi42, uint32_t fetchdat) +{ + /* Push new frame onto stack. */ + uint8_t sp = (upi42->psw & 0x07) << 1; + upi42->ram[8 + sp++] = upi42->pc + 2; /* stack frame format is undocumented! */ + upi42->ram[8 + sp++] = (upi42->psw & 0xf0) | ((upi42->pc >> 8) & 0x07); + upi42->psw = (upi42->psw & 0xf8) | (sp >> 1); + + /* Load new program counter. */ + upi42->pc = (upi42->dbf << 11) | ((fetchdat << 3) & 0x0700) | ((fetchdat >> 8) & 0x00ff); + + upi42->cycs--; + return 0; +} + +static int +upi42_op_RET(upi42_t *upi42, uint32_t fetchdat) +{ + /* Pop frame off the stack. */ + uint8_t sp = (upi42->psw & 0x07) << 1; + uint8_t frame1 = upi42->ram[8 + --sp]; + uint8_t frame0 = upi42->ram[8 + --sp]; + upi42->psw = (upi42->psw & 0xf8) | (sp >> 1); + + /* Load new program counter. */ + upi42->pc = ((frame1 & 0x0f) << 8) | frame0; + + /* Load new Program Status Word and unmask interrupts if this is RETR. */ + if (fetchdat & 0x10) { + upi42->psw = (frame1 & 0xf0) | (upi42->psw & 0x0f); + upi42_mirror_f0(upi42); + + upi42->irq_mask = 0; + } + + upi42->cycs--; + return 0; +} + +static int +upi42_op_JMP_imm(upi42_t *upi42, uint32_t fetchdat) +{ + upi42->pc = (upi42->dbf << 11) | ((fetchdat << 3) & 0x0700) | ((fetchdat >> 8) & 0x00ff); + upi42->cycs--; + return 0; +} + +static int +upi42_op_JMPP_indA(upi42_t *upi42, UNUSED(uint32_t fetchdat)) +{ + upi42->pc = (upi42->pc & 0xff00) | upi42->a; + upi42->cycs--; + return 0; +} + +#define UPI42_COND_JMP_IMM(insn, cond, post) \ + static int \ + upi42_op_##insn##_imm(upi42_t *upi42, uint32_t fetchdat) \ + { \ + if (cond) \ + upi42->pc = (upi42->pc & 0xff00) | ((fetchdat >> 8) & 0x00ff); \ + post; \ + upi42->cycs--; \ + return 2 * !(cond); \ + } +UPI42_COND_JMP_IMM(JC, upi42->psw & 0x80, ) +UPI42_COND_JMP_IMM(JNC, !(upi42->psw & 0x80), ) +UPI42_COND_JMP_IMM(JZ, !upi42->a, ) +UPI42_COND_JMP_IMM(JNZ, upi42->a, ) +UPI42_COND_JMP_IMM(JT0, upi42->t0, ) +UPI42_COND_JMP_IMM(JNT0, !upi42->t0, ) +UPI42_COND_JMP_IMM(JT1, upi42->t1, ) +UPI42_COND_JMP_IMM(JNT1, !upi42->t1, ) +UPI42_COND_JMP_IMM(JF0, upi42->psw & 0x20, ) +UPI42_COND_JMP_IMM(JF1, upi42->sts & 0x08, ) +UPI42_COND_JMP_IMM(JTF, !upi42->tf, upi42->tf = 0) +UPI42_COND_JMP_IMM(JBb, upi42->a & (1 << ((fetchdat >> 5) & 7)), ) +UPI42_COND_JMP_IMM(JNIBF, !(upi42->sts & 0x02), ) +UPI42_COND_JMP_IMM(JOBF, upi42->sts & 0x01, ) + +static int +upi42_op_EN_A20(UNUSED(upi42_t *upi42), UNUSED(uint32_t fetchdat)) +{ + /* Enable fast A20 until reset. */ + return 1; +} + +static int +upi42_op_EN_DMA(UNUSED(upi42_t *upi42), UNUSED(uint32_t fetchdat)) +{ + return 1; +} + +static int +upi42_op_EN_FLAGS(upi42_t *upi42, UNUSED(uint32_t fetchdat)) +{ + upi42->flags = 1; + return 1; +} + +static int +upi42_op_SUSPEND(upi42_t *upi42, UNUSED(uint32_t fetchdat)) +{ + /* Inhibit execution until reset. */ + upi42->suspend = 1; + return 1; +} + +static const int (*ops_80c42[256])(upi42_t *upi42, uint32_t fetchdat) = { + // clang-format off + /* 0 / 8 */ /* 1 / 9 */ /* 2 / a */ /* 3 / b */ /* 4 / c */ /* 5 / d */ /* 6 / e */ /* 7 / f */ + /* 00 */ upi42_op_NOP, NULL, upi42_op_OUT_DBB_A, upi42_op_ADD_A_imm, upi42_op_JMP_imm, upi42_op_EN_I, NULL, upi42_op_DEC_A, + /* 08 */ upi42_op_IN_A_Pp, upi42_op_IN_A_Pp, upi42_op_IN_A_Pp, NULL, upi42_op_MOVD_A_Pp, upi42_op_MOVD_A_Pp, upi42_op_MOVD_A_Pp, upi42_op_MOVD_A_Pp, + /* 10 */ upi42_op_INC_indRr, upi42_op_INC_indRr, upi42_op_JBb_imm, upi42_op_ADDC_A_imm, upi42_op_CALL_imm, upi42_op_DIS_I, upi42_op_JTF_imm, upi42_op_INC_A, + /* 18 */ upi42_op_INC_Rr, upi42_op_INC_Rr, upi42_op_INC_Rr, upi42_op_INC_Rr, upi42_op_INC_Rr, upi42_op_INC_Rr, upi42_op_INC_Rr, upi42_op_INC_Rr, + /* 20 */ upi42_op_XCH_A_indRr, upi42_op_XCH_A_indRr, upi42_op_IN_A_DBB, upi42_op_MOV_A_imm, upi42_op_JMP_imm, upi42_op_EN_TCNTI, upi42_op_JNT0_imm, upi42_op_CLR_A, + /* 28 */ upi42_op_XCH_A_Rr, upi42_op_XCH_A_Rr, upi42_op_XCH_A_Rr, upi42_op_XCH_A_Rr, upi42_op_XCH_A_Rr, upi42_op_XCH_A_Rr, upi42_op_XCH_A_Rr, upi42_op_XCH_A_Rr, + /* 30 */ upi42_op_XCHD_A_indRr, upi42_op_XCHD_A_indRr, upi42_op_JBb_imm, upi42_op_EN_A20, upi42_op_CALL_imm, upi42_op_DIS_TCNTI, upi42_op_JT0_imm, upi42_op_CPL_A, + /* 38 */ upi42_op_OUTL_Pp_A, upi42_op_OUTL_Pp_A, upi42_op_OUTL_Pp_A, upi42_op_OUTL_Pp_A, upi42_op_MOVD_Pp_A, upi42_op_MOVD_Pp_A, upi42_op_MOVD_Pp_A, upi42_op_MOVD_Pp_A, + /* 40 */ upi42_op_ORL_A_indRr, upi42_op_ORL_A_indRr, upi42_op_MOV_A_T, upi42_op_ORL_A_imm, upi42_op_JMP_imm, upi42_op_STRT_CNT, upi42_op_JNT1_imm, upi42_op_SWAP_A, + /* 48 */ upi42_op_ORL_A_Rr, upi42_op_ORL_A_Rr, upi42_op_ORL_A_Rr, upi42_op_ORL_A_Rr, upi42_op_ORL_A_Rr, upi42_op_ORL_A_Rr, upi42_op_ORL_A_Rr, upi42_op_ORL_A_Rr, + /* 50 */ upi42_op_ANL_A_indRr, upi42_op_ANL_A_indRr, upi42_op_JBb_imm, upi42_op_ANL_A_imm, upi42_op_CALL_imm, upi42_op_STRT_T, upi42_op_JT1_imm, upi42_op_DA_A, + /* 58 */ upi42_op_ANL_A_Rr, upi42_op_ANL_A_Rr, upi42_op_ANL_A_Rr, upi42_op_ANL_A_Rr, upi42_op_ANL_A_Rr, upi42_op_ANL_A_Rr, upi42_op_ANL_A_Rr, upi42_op_ANL_A_Rr, + /* 60 */ upi42_op_ADD_A_indRr, upi42_op_ADD_A_indRr, upi42_op_MOV_T_A, upi42_op_SEL_PMB0, upi42_op_JMP_imm, upi42_op_STOP_TCNT, NULL, upi42_op_RRC_A, + /* 68 */ upi42_op_ADD_A_Rr, upi42_op_ADD_A_Rr, upi42_op_ADD_A_Rr, upi42_op_ADD_A_Rr, upi42_op_ADD_A_Rr, upi42_op_ADD_A_Rr, upi42_op_ADD_A_Rr, upi42_op_ADD_A_Rr, + /* 70 */ upi42_op_ADDC_A_indRr, upi42_op_ADDC_A_indRr, upi42_op_JBb_imm, upi42_op_SEL_PMB1, upi42_op_CALL_imm, NULL, upi42_op_JF1_imm, upi42_op_RR_A, + /* 78 */ upi42_op_ADDC_A_Rr, upi42_op_ADDC_A_Rr, upi42_op_ADDC_A_Rr, upi42_op_ADDC_A_Rr, upi42_op_ADDC_A_Rr, upi42_op_ADDC_A_Rr, upi42_op_ADDC_A_Rr, upi42_op_ADDC_A_Rr, + /* 80 */ NULL, NULL, upi42_op_SUSPEND, upi42_op_RET, upi42_op_JMP_imm, upi42_op_CLR_F0, upi42_op_JOBF_imm, NULL, + /* 88 */ upi42_op_ORL_Pp_imm, upi42_op_ORL_Pp_imm, upi42_op_ORL_Pp_imm, upi42_op_ORL_Pp_imm, upi42_op_ORLD_Pp_A, upi42_op_ORLD_Pp_A, upi42_op_ORLD_Pp_A, upi42_op_ORLD_Pp_A, + /* 90 */ upi42_op_MOV_STS_A, NULL, upi42_op_JBb_imm, upi42_op_RET, upi42_op_CALL_imm, upi42_op_CPL_F0, upi42_op_JNZ_imm, upi42_op_CLR_C, + /* 98 */ upi42_op_ANL_Pp_imm, upi42_op_ANL_Pp_imm, upi42_op_ANL_Pp_imm, upi42_op_ANL_Pp_imm, upi42_op_ANLD_Pp_A, upi42_op_ANLD_Pp_A, upi42_op_ANLD_Pp_A, upi42_op_ANLD_Pp_A, + /* a0 */ upi42_op_MOV_indRr_A, upi42_op_MOV_indRr_A, NULL, upi42_op_MOVP_A_indA, upi42_op_JMP_imm, upi42_op_CLR_F1, NULL, upi42_op_CPL_C, + /* a8 */ upi42_op_MOV_Rr_A, upi42_op_MOV_Rr_A, upi42_op_MOV_Rr_A, upi42_op_MOV_Rr_A, upi42_op_MOV_Rr_A, upi42_op_MOV_Rr_A, upi42_op_MOV_Rr_A, upi42_op_MOV_Rr_A, + /* b0 */ upi42_op_MOV_indRr_imm,upi42_op_MOV_indRr_imm,upi42_op_JBb_imm, upi42_op_JMPP_indA, upi42_op_CALL_imm, upi42_op_CPL_F1, upi42_op_JF0_imm, NULL, + /* b8 */ upi42_op_MOV_Rr_imm, upi42_op_MOV_Rr_imm, upi42_op_MOV_Rr_imm, upi42_op_MOV_Rr_imm, upi42_op_MOV_Rr_imm, upi42_op_MOV_Rr_imm, upi42_op_MOV_Rr_imm, upi42_op_MOV_Rr_imm, + /* c0 */ NULL, NULL, NULL, NULL, upi42_op_JMP_imm, NULL, upi42_op_JZ_imm, upi42_op_MOV_A_PSW, + /* c8 */ upi42_op_DEC_Rr, upi42_op_DEC_Rr, upi42_op_DEC_Rr, upi42_op_DEC_Rr, upi42_op_DEC_Rr, upi42_op_DEC_Rr, upi42_op_DEC_Rr, upi42_op_DEC_Rr, + /* d0 */ upi42_op_XRL_A_indRr, upi42_op_XRL_A_indRr, upi42_op_JBb_imm, upi42_op_XRL_A_imm, upi42_op_CALL_imm, NULL, upi42_op_JNIBF_imm, upi42_op_MOV_PSW_A, + /* d8 */ upi42_op_XRL_A_Rr, upi42_op_XRL_A_Rr, upi42_op_XRL_A_Rr, upi42_op_XRL_A_Rr, upi42_op_XRL_A_Rr, upi42_op_XRL_A_Rr, upi42_op_XRL_A_Rr, upi42_op_XRL_A_Rr, + /* e0 */ NULL, NULL, upi42_op_SUSPEND, upi42_op_MOVP3_A_indA, upi42_op_JMP_imm, upi42_op_EN_DMA, upi42_op_JNC_imm, upi42_op_RL_A, + /* e8 */ upi42_op_DJNZ_Rr_imm, upi42_op_DJNZ_Rr_imm, upi42_op_DJNZ_Rr_imm, upi42_op_DJNZ_Rr_imm, upi42_op_DJNZ_Rr_imm, upi42_op_DJNZ_Rr_imm, upi42_op_DJNZ_Rr_imm, upi42_op_DJNZ_Rr_imm, + /* f0 */ upi42_op_MOV_A_indRr, upi42_op_MOV_A_indRr, upi42_op_JBb_imm, NULL, upi42_op_CALL_imm, upi42_op_EN_FLAGS, upi42_op_JC_imm, upi42_op_RLC_A, + /* f8 */ upi42_op_MOV_A_Rr, upi42_op_MOV_A_Rr, upi42_op_MOV_A_Rr, upi42_op_MOV_A_Rr, upi42_op_MOV_A_Rr, upi42_op_MOV_A_Rr, upi42_op_MOV_A_Rr, upi42_op_MOV_A_Rr + // clang-format on +}; + +static void +upi42_exec(void *priv) +{ + upi42_t *upi42 = (upi42_t *) priv; + + /* Skip everything if we're suspended, or just process timer if we're in a multi-cycle instruction. */ + if (upi42->suspend) + return; + else if (++upi42->cycs < 0) + goto timer; + + /* Trigger interrupt if requested. */ + if (upi42->irq_mask) { + /* Masked, we're currently in an ISR. */ + } else if (upi42->i_raise) { + /* External interrupt. Higher priority than the timer interrupt. */ + upi42->irq_mask = 1; + upi42->i_raise = 0; + + upi42->pc -= 2; + upi42->cycs++; + upi42_op_CALL_imm(upi42, 3 << 8); + return; + } else if (upi42->tcnti_raise) { + /* Timer interrupt. */ + upi42->irq_mask = 1; + upi42->tcnti_raise = 0; + + upi42->pc -= 2; + upi42->cycs++; + upi42_op_CALL_imm(upi42, 7 << 8); + return; + } + + /* Fetch instruction. */ + uint32_t fetchdat = *((uint32_t *) &upi42->rom[upi42->pc]); + + /* Decode instruction. */ + uint8_t insn = fetchdat & 0xff; + if (upi42->ops[insn]) { + /* Execute instruction. */ + int pc_inc = upi42->ops[insn](upi42, fetchdat); + + /* Increment lower 11 bits of the program counter. */ + upi42->pc = (upi42->pc & 0xf800) | ((upi42->pc + pc_inc) & 0x07ff); + + /* Decrement cycle counter. Multi-cycle instructions also decrement within their code. */ + upi42->cycs--; + } else { + fatal("UPI42: Unknown opcode %02X (%08X)\n", insn, fetchdat); + return; + } + +timer: + /* Process timer. */ + if (!upi42->run_timer) { + /* Timer disabled. */ + } else if (upi42->skip_timer_inc) { + /* Some instructions don't increment the timer. */ + upi42->skip_timer_inc = 0; + } else { + /* Increment counter once the prescaler overflows, + and set timer flag once the main value overflows. */ + if ((++upi42->prescaler == 0) && (++upi42->t == 0)) { + upi42->tf = 1; + + /* Fire counter interrupt if enabled. */ + if (upi42->tcnti) + upi42->tcnti_raise = 1; + } + } +} + +uint8_t +upi42_port_read(void *priv, int port) +{ + const upi42_t *upi42 = (upi42_t *) priv; + + /* Read base port value. */ + port &= 7; + uint8_t ret = upi42->ports_in[port] & upi42->ports_out[port]; + + /* Apply special meanings. */ + switch (port) { + default: + break; + } + + upi42_log("UPI42: port_read(%d) = %02X\n", port, ret); + return ret; +} + +void +upi42_port_write(void *priv, int port, uint8_t val) +{ + upi42_t *upi42 = (upi42_t *) priv; + + port &= 7; + upi42_log("UPI42: port_write(%d, %02X)\n", port, val); + + /* Set input level. */ + upi42->ports_in[port] = val; +} + +/* NOTE: The dbb/sts/cmd functions use I/O handler signatures; port is ignored. */ + +uint8_t +upi42_dbb_read(UNUSED(uint16_t port), void *priv) +{ + upi42_t *upi42 = (upi42_t *) priv; + + uint8_t ret = upi42->dbb_out; + upi42_log("UPI42: dbb_read(%04X) = %02X\n", port, ret); + upi42->sts &= ~0x01; /* clear OBF */ + return ret; +} + +void +upi42_dbb_write(UNUSED(uint16_t port), uint8_t val, void *priv) +{ + upi42_t *upi42 = (upi42_t *) priv; + + upi42_log("UPI42: dbb_write(%04X, %02X)\n", port, val); + upi42->dbb_in = val; + upi42->sts = (upi42->sts & ~0x08) | 0x02; /* clear F1 and set IBF */ + if (upi42->i) /* fire IBF interrupt if enabled */ + upi42->i_raise = 1; +} + +uint8_t +upi42_sts_read(UNUSED(uint16_t port), void *priv) +{ + const upi42_t *upi42 = (upi42_t *) priv; + + uint8_t ret = upi42->sts; + upi42_log("UPI42: sts_read(%04X) = %02X\n", port, ret); + return ret; +} + +void +upi42_cmd_write(UNUSED(uint16_t port), uint8_t val, void *priv) +{ + upi42_t *upi42 = (upi42_t *) priv; + + upi42_log("UPI42: cmd_write(%04X, %02X)\n", port, val); + upi42->dbb_in = val; + upi42->sts |= 0x0a; /* set F1 and IBF */ + if (upi42->i) /* fire IBF interrupt if enabled */ + upi42->i_raise = 1; +} + +void +upi42_reset(upi42_t *upi42) +{ + upi42->pc = 0; /* program counter */ + upi42->psw = 0; /* stack pointer, register bank and F0 */ + upi42->dbf = 0; /* ROM bank */ + upi42->i = 0; /* external interrupt */ + upi42->tcnti = 0; /* timer/counter interrupt */ + upi42->tf = 0; /* timer flag */ + upi42->sts = 0; /* F1 */ + upi42->flags = 0; /* UPI-42 buffer interrupts */ + upi42->suspend = 0; /* 80C42 suspend flag */ +} + +void +upi42_do_init(upi32_t type, uint8_t *rom) +{ + memset(upi42, 0x00, sizeof(upi42_t)); + upi42->rom = rom; + + /* Set chip type. */ + upi42->type = type; + upi42->rommask = type >> UPI42_ROM_SHIFT; + upi42->rammask = type >> UPI42_RAM_SHIFT; + + /* Build instruction table. */ + memcpy(upi42->ops, ops_80c42, sizeof(ops_80c42)); + if (!(type & UPI42_EXT_C42)) { + /* Remove 80C42-only instructions. */ + upi42->ops[0x33] = NULL; /* EN A20 */ + upi42->ops[0x63] = NULL; /* SEL PMB0 */ + upi42->ops[0x73] = NULL; /* SEL PMB1 */ + upi42->ops[0x42] = NULL; /* SUSPEND */ + upi42->ops[0xe2] = NULL; /* SUSPEND */ + } + + memset(upi42_t->ports_in, 0xff, sizeof(upi42_t->ports_in)); + upi42_t->t0 = 1; + upi42_t->t1 = 1; +} + +void * +upi42_init(uint32_t type, uint8_t *rom) +{ + /* Allocate state structure. */ + upi42_t *upi42 = (upi42_t *) malloc(sizeof(upi42_t)); + upi42_do_init(type, rom); + + return upi42; +} + +#ifdef UPI42_STANDALONE +static const char *flags_8042[] = { "OBF", "IBF", "F0", "F1", "ST4", "ST5", "ST6", "ST7" }; + +int +main(int argc, char **argv) +{ + /* Check arguments. */ + if (argc < 2) { + upi42_log("Specify a ROM file to execute.\n"); + return 1; + } + + /* Load ROM. */ + uint8_t rom[4096] = { 0 }; + FILE *fp = fopen(argv[1], "rb"); + if (!fp) { + upi42_log("Could not read ROM file.\n"); + return 2; + } + size_t rom_size = fread(rom, sizeof(rom[0]), sizeof(rom), fp); + fclose(fp); + + /* Determine chip type from ROM. */ + upi42_log("%d-byte ROM, ", rom_size); + uint32_t type; + switch (rom_size) { + case 0 ... 1024: + upi42_log("emulating 8041"); + type = UPI42_8041; + break; + + case 1025 ... 2048: + upi42_log("emulating 8042"); + type = UPI42_8042; + break; + + case 2049 ... 4096: + upi42_log("emulating 80C42"); + type = UPI42_80C42; + break; + + default: + upi42_log("unknown!\n"); + return 3; + } + upi42_log(".\n"); + + /* Initialize emulator. */ + upi42_t *upi42 = (upi42_t *) upi42_init(type, rom); + + /* Start execution. */ + char cmd, cmd_buf[256]; + int val, go_until = -1; + while (1) { + /* Output status. */ + upi42_log("PC=%04X I=%02X(%02X) A=%02X", upi42->pc, upi42->rom[upi42->pc], upi42->rom[upi42->pc + 1], upi42->a); + for (val = 0; val < 8; val++) + upi42_log(" R%d=%02X", val, UPI42_REG(upi42, val, )); + upi42_log(" T=%02X PSW=%02X TF=%d I=%d TCNTI=%d", upi42->t, upi42->psw, upi42->tf, upi42->i, upi42->tcnti); + if (type & UPI42_TYPE_UPI) { + upi42_log(" STS=%02X", upi42->sts); + for (val = 0; val < 8; val++) { + if (upi42->sts & (1 << val)) { + upi42_log(" [%s]", flags_8042[val]); + } else { + upi42_log(" %s ", flags_8042[val]); + } + } + } + upi42_log("\n"); + + /* Break for command only if stepping. */ + if ((go_until < 0) || (upi42->pc == go_until)) { +retry: + go_until = -1; + upi42_log("> "); + + /* Read command. */ + cmd = '\0'; + scanf("%c", &cmd); + + /* Execute command. */ + switch (cmd) { + case 'c': /* write command */ + if (scanf("%X%*c", &val, &cmd_buf)) + upi42_cmd_write(0, val, upi42); + goto retry; + + case 'd': /* write data */ + if (scanf("%X%*c", &val, &cmd_buf)) + upi42_dbb_write(0, val, upi42); + goto retry; + + case 'g': /* go until */ + if (!scanf("%X%*c", &go_until, &cmd_buf)) + go_until = -1; + break; + + case 'r': /* read data */ + upi42_dbb_read(0, upi42); /* return value will be logged */ + goto skip_and_retry; + + case 'q': /* exit */ + return 0; + + case '\r': /* step */ + case '\n': + case '\0': + break; + + default: + upi42_log("Monitor commands:\n"); + upi42_log("- Return (no command) - Step execution\n"); + upi42_log("- q (or Ctrl+C) - Exit\n"); + upi42_log("- gXXXX - Execute until PC is hex value XXXX\n"); + upi42_log("- dXX - Write hex value XX to data port\n"); + upi42_log("- cXX - Write hex value XX to command port\n"); + upi42_log("- r - Read from data port and reset OBF\n"); +skip_and_retry: + scanf("%*c", &cmd_buf); + goto retry; + } + } + + /* Execute a cycle. */ + upi42_exec(upi42); + } + + return 0; +} +#else +static void +upi42_write(uint16_t port, uint8_t val, void *priv) +{ + upi42_t *upi42 = (upi42_t *) priv; + uint32_t temp_type; + uint8_t *temp_rom; + int i; + + switch (port) { + /* Write to data port. */ + case 0x0060: + case 0x0160: + upi42_dbb_write(0, val, upi42); + break; + + /* RAM Index. */ + case 0x0162: + upi42->ram_index = val & upi42->rammask; + break; + + /* RAM. */ + case 0x0163: + upi42->ram[upi42->ram_index & upi42->rammask] = val; + break; + + /* Write to command port. */ + case 0x0064: + case 0x0164: + upi42_cmd_write(0, val, upi42); + break; + + /* Input ports. */ + case 0x0180 ... 0x0187: + upi42->ports_in[addr & 0x0007] = val; + break; + + /* Output ports. */ + case 0x0188 ... 0x018f: + upi42->ports_out[addr & 0x0007] = val; + break; + + /* 4 = T0, 5 = T1. */ + case 0x0194: + upi42->t0 = (val >> 4) & 0x01; + upi42->t1 = (val >> 5) & 0x01; + break; + + /* Program counter. */ + case 0x0196: + upi42->pc = (upi42->pc & 0xff00) | val; + break; + case 0x0197: + upi42->pc = (upi42->pc & 0x00ff) | (val << 8); + break; + + /* Input data buffer. */ + case 0x019a: + upi42->dbb_in = val; + break; + + /* Output data buffer. */ + case 0x019b: + upi42->dbb_out = val; + break; + + /* ROM Index. */ + case 0x01a0: + upi42->rom_index = (upi42->rom_index & 0xff00) | val; + break; + case 0x01a1: + upi42->rom_index = (upi42->rom_index & 0x00ff) | (val << 8); + break; + + /* Hard reset. */ + case 0x01a2: + temp_type = upi42->type; + temp_rom = upi42->rom; + upi42_do_init(temp_type, temp_rom); + break; + + /* Soft reset. */ + case 0x01a3: + upi42_reset(upi42); + break; + + /* ROM. */ + case 0x01a4: + upi42->rom[upi42->rom_index & upi42->rommask] = val; + break; + case 0x01a5: + upi42->rom[(upi42->rom_index + 1) & upi42->rommask] = val; + break; + case 0x01a6: + upi42->rom[(upi42->rom_index + 2) & upi42->rommask] = val; + break; + case 0x01a7: + upi42->rom[(upi42->rom_index + 3) & upi42->rommask] = val; + break; + + /* Pause. */ + case 0x01a8: + break; + + /* Resume. */ + case 0x01a9: + break; + + /* Bus master ROM: 0 = direction (0 = to memory, 1 = from memory). */ + case 0x01aa: + if (val & 0x01) { + for (i = 0; i <= upi42->rommask; i += 4) + *(uint32_t *) &(upi42->rom[i]) = mem_readl_phys(upi42->ram_addr + i); + } else { + for (i = 0; i <= upi42->rommask; i += 4) + mem_writel_phys(upi42->ram_addr + i, *(uint32_t *) &(upi42->rom[i])); + } + upi42->bm_stat = (val & 0x01) | 0x02; + break; + } +} + +static uint8_t +upi42_read(uint16_t port, void *priv) +{ + upi42_t *upi42 = (upi42_t *) priv; + uint8_t ret = 0xff; + + switch (port) { + /* Type. */ + case 0x015c: + ret = upi42->type & 0xff; + break; + case 0x015d: + ret = upi42->type >> 8; + break; + case 0x015e: + ret = upi42->type >> 16; + break; + case 0x015f: + ret = upi42->type >> 24; + break; + + /* Read from data port and reset OBF. */ + case 0x0060: + case 0x0160: + ret = upi42->dbb_out; + upi42->sts &= ~0x01; /* clear OBF */ + break; + + /* RAM Mask. */ + case 0x0161: + ret = upi42->rammask; + break; + + /* RAM Index. */ + case 0x0162: + ret = upi42->ram_index; + break; + + /* RAM. */ + case 0x0163: + ret = upi42->ram[upi42->ram_index & upi42->rammask]; + break; + + /* Read status. */ + case 0x0064: + case 0x0164: + ret = upi42->sts; + break; + + /* Input ports. */ + case 0x0180 ... 0x0187: + ret = upi42->ports_in[addr & 0x0007]; + break; + + /* Output ports. */ + case 0x0188 ... 0x018f: + ret = upi42->ports_out[addr & 0x0007]; + break; + + /* Accumulator. */ + case 0x0190: + ret = upi42->a; + break; + + /* Timer counter. */ + case 0x0191: + ret = upi42->t; + break; + + /* Program status word. */ + case 0x0192: + ret = upi42->psw; + break; + + /* 0-4 = Prescaler, 5 = TF, 6 = Skip Timer Inc, 7 = Run Timer. */ + case 0x0193: + ret = (upi42->prescaler & 0x1f) || ((upi42->tf & 0x01) << 5) || ((upi42->skip_timer_inc & 0x01) << 6) || ((upi42->run_timer & 0x01) << 7); + break; + + /* 0 = I, 1 = I Raise, 2 = TCNTI Raise, 3 = IRQ Mask, 4 = T0, 5 = T1, 6 = Flags, 7 = DBF. */ + case 0x0194: + ret = (upi42->i & 0x01) || ((upi42->i_raise & 0x01) << 1) || ((upi42->tcnti_raise & 0x01) << 2) || ((upi42->irq_mask & 0x01) << 3) || ((upi42->t0 & 0x01) << 4) || ((upi42->t1 & 0x01) << 5) || ((upi42->flags & 0x01) << 6) || ((upi42->dbf & 0x01) << 7); + break; + + /* 0 = Suspend. */ + case 0x0195: + ret = (upi42->suspend & 0x01); + break; + + /* Program counter. */ + case 0x0196: + ret = upi42->pc & 0xff; + break; + case 0x0197: + ret = upi42->pc >> 8; + break; + + /* ROM Mask. */ + case 0x0198: + ret = upi42->rommask & 0xff; + break; + case 0x0199: + ret = upi42->rommask >> 8; + break; + + /* Input data buffer. */ + case 0x019a: + ret = upi42->dbb_in; + break; + + /* Output data buffer. */ + case 0x019b: + ret = upi42->dbb_out; + break; + + /* Cycle counter. */ + case 0x019c: + ret = upi42->cycs & 0xff; + break; + case 0x019d: + ret = upi42->cycs >> 8; + break; + case 0x019e: + ret = upi42->cycs >> 16; + break; + case 0x019f: + ret = upi42->cycs >> 24; + break; + + /* ROM Index. */ + case 0x01a0: + ret = upi42->rom_index & 0xff; + break; + case 0x01a1: + ret = upi42->rom_index >> 8; + break; + + /* ROM. */ + case 0x01a4: + ret = upi42->rom[upi42->rom_index & upi42->rommask]; + break; + case 0x01a5: + ret = upi42->rom[(upi42->rom_index + 1) & upi42->rommask]; + break; + case 0x01a6: + ret = upi42->rom[(upi42->rom_index + 2) & upi42->rommask]; + break; + case 0x01a7: + ret = upi42->rom[(upi42->rom_index + 3) & upi42->rommask]; + break; + + /* Bus master status: 0 = direction, 1 = finished. */ + case 0x01ab: + ret = upi42->bm_stat; + break; + } + + return ret; +} +#endif diff --git a/src/usb.c b/src/usb.c index 784f8f151..6bdc8e6c0 100644 --- a/src/usb.c +++ b/src/usb.c @@ -1,19 +1,19 @@ /* - * 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. + * 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. + * This file is part of the 86Box distribution. * - * Universal Serial Bus emulation (currently dummy UHCI and - * OHCI). + * Universal Serial Bus emulation (currently dummy UHCI and + * OHCI). * * * - * Authors: Miran Grca, + * Authors: Miran Grca, * - * Copyright 2020 Miran Grca. + * Copyright 2020 Miran Grca. */ #include #include @@ -28,33 +28,32 @@ #include <86box/mem.h> #include <86box/usb.h> #include "cpu.h" - +#include <86box/plat_unused.h> #ifdef ENABLE_USB_LOG int usb_do_log = ENABLE_USB_LOG; - static void usb_log(const char *fmt, ...) { va_list ap; if (usb_do_log) { - va_start(ap, fmt); - pclog_ex(fmt, ap); - va_end(ap); + va_start(ap, fmt); + pclog_ex(fmt, ap); + va_end(ap); } } #else -#define usb_log(fmt, ...) +# define usb_log(fmt, ...) #endif - static uint8_t -uhci_reg_read(uint16_t addr, void *p) +uhci_reg_read(uint16_t addr, void *priv) { - usb_t *dev = (usb_t *) p; - uint8_t ret, *regs = dev->uhci_io; + const usb_t *dev = (usb_t *) priv; + uint8_t ret; + const uint8_t *regs = dev->uhci_io; addr &= 0x0000001f; @@ -63,294 +62,312 @@ uhci_reg_read(uint16_t addr, void *p) return ret; } - static void -uhci_reg_write(uint16_t addr, uint8_t val, void *p) +uhci_reg_write(uint16_t addr, uint8_t val, void *priv) { - usb_t *dev = (usb_t *) p; + usb_t *dev = (usb_t *) priv; uint8_t *regs = dev->uhci_io; addr &= 0x0000001f; switch (addr) { - case 0x02: - regs[0x02] &= ~(val & 0x3f); - break; - case 0x04: - regs[0x04] = (val & 0x0f); - break; - case 0x09: - regs[0x09] = (val & 0xf0); - break; - case 0x0a: case 0x0b: - regs[addr] = val; - break; - case 0x0c: - regs[0x0c] = (val & 0x7f); - break; + case 0x02: + regs[0x02] &= ~(val & 0x3f); + break; + case 0x04: + regs[0x04] = (val & 0x0f); + break; + case 0x09: + regs[0x09] = (val & 0xf0); + break; + case 0x0a: + case 0x0b: + regs[addr] = val; + break; + case 0x0c: + regs[0x0c] = (val & 0x7f); + break; + + default: + break; } } - static void -uhci_reg_writew(uint16_t addr, uint16_t val, void *p) +uhci_reg_writew(uint16_t addr, uint16_t val, void *priv) { - usb_t *dev = (usb_t *) p; + usb_t *dev = (usb_t *) priv; uint16_t *regs = (uint16_t *) dev->uhci_io; addr &= 0x0000001f; switch (addr) { - case 0x00: - if ((val & 0x0001) && !(regs[0x00] & 0x0001)) - regs[0x01] &= ~0x20; - else if (!(val & 0x0001)) - regs[0x01] |= 0x20; - regs[0x00] = (val & 0x00ff); - break; - case 0x06: - regs[0x03] = (val & 0x07ff); - break; - case 0x10: case 0x12: - regs[addr >> 1] = ((regs[addr >> 1] & 0xedbb) | (val & 0x1244)) & ~(val & 0x080a); - break; - default: - uhci_reg_write(addr, val & 0xff, p); - uhci_reg_write(addr + 1, (val >> 8) & 0xff, p); - break; + case 0x00: + if ((val & 0x0001) && !(regs[0x00] & 0x0001)) + regs[0x01] &= ~0x20; + else if (!(val & 0x0001)) + regs[0x01] |= 0x20; + regs[0x00] = (val & 0x00ff); + break; + case 0x06: + regs[0x03] = (val & 0x07ff); + break; + case 0x10: + case 0x12: + regs[addr >> 1] = ((regs[addr >> 1] & 0xedbb) | (val & 0x1244)) & ~(val & 0x080a); + break; + default: + uhci_reg_write(addr, val & 0xff, priv); + uhci_reg_write(addr + 1, (val >> 8) & 0xff, priv); + break; } } - void uhci_update_io_mapping(usb_t *dev, uint8_t base_l, uint8_t base_h, int enable) { if (dev->uhci_enable && (dev->uhci_io_base != 0x0000)) - io_removehandler(dev->uhci_io_base, 0x20, uhci_reg_read, NULL, NULL, uhci_reg_write, uhci_reg_writew, NULL, dev); + io_removehandler(dev->uhci_io_base, 0x20, uhci_reg_read, NULL, NULL, uhci_reg_write, uhci_reg_writew, NULL, dev); dev->uhci_io_base = base_l | (base_h << 8); - dev->uhci_enable = enable; + dev->uhci_enable = enable; if (dev->uhci_enable && (dev->uhci_io_base != 0x0000)) - io_sethandler(dev->uhci_io_base, 0x20, uhci_reg_read, NULL, NULL, uhci_reg_write, uhci_reg_writew, NULL, dev); + io_sethandler(dev->uhci_io_base, 0x20, uhci_reg_read, NULL, NULL, uhci_reg_write, uhci_reg_writew, NULL, dev); } - static uint8_t -ohci_mmio_read(uint32_t addr, void *p) +ohci_mmio_read(uint32_t addr, void *priv) { - usb_t *dev = (usb_t *) p; - uint8_t ret = 0x00; + const usb_t *dev = (usb_t *) priv; + uint8_t ret = 0x00; addr &= 0x00000fff; ret = dev->ohci_mmio[addr]; if (addr == 0x101) - ret = (ret & 0xfe) | (!!mem_a20_key); + ret = (ret & 0xfe) | (!!mem_a20_key); return ret; } - static void -ohci_mmio_write(uint32_t addr, uint8_t val, void *p) +ohci_mmio_write(uint32_t addr, uint8_t val, void *priv) { - usb_t *dev = (usb_t *) p; + usb_t *dev = (usb_t *) priv; uint8_t old; addr &= 0x00000fff; switch (addr) { - case 0x04: - if ((val & 0xc0) == 0x00) { - /* UsbReset */ - dev->ohci_mmio[0x56] = dev->ohci_mmio[0x5a] = 0x16; - } - break; - case 0x08: /* HCCOMMANDSTATUS */ - /* bit OwnershipChangeRequest triggers an ownership change (SMM <-> OS) */ - if (val & 0x08) { - dev->ohci_mmio[0x0f] = 0x40; - if ((dev->ohci_mmio[0x13] & 0xc0) == 0xc0) - smi_line = 1; - } + case 0x04: + if ((val & 0xc0) == 0x00) { + /* UsbReset */ + dev->ohci_mmio[0x56] = dev->ohci_mmio[0x5a] = 0x16; + } + break; + case 0x08: /* HCCOMMANDSTATUS */ + /* bit OwnershipChangeRequest triggers an ownership change (SMM <-> OS) */ + if (val & 0x08) { + dev->ohci_mmio[0x0f] = 0x40; + if ((dev->ohci_mmio[0x13] & 0xc0) == 0xc0) + smi_raise(); + } - /* bit HostControllerReset must be cleared for the controller to be seen as initialized */ - if (val & 0x01) { - memset(dev->ohci_mmio, 0x00, 4096); - dev->ohci_mmio[0x00] = 0x10; - dev->ohci_mmio[0x01] = 0x01; - dev->ohci_mmio[0x48] = 0x02; - val &= ~0x01; - } - break; - case 0x0c: - dev->ohci_mmio[addr] &= ~(val & 0x7f); - return; - case 0x0d: case 0x0e: - return; - case 0x0f: - dev->ohci_mmio[addr] &= ~(val & 0x40); - return; - case 0x3b: - dev->ohci_mmio[addr] = (val & 0x80); - return; - case 0x39: case 0x41: - dev->ohci_mmio[addr] = (val & 0x3f); - return; - case 0x45: - dev->ohci_mmio[addr] = (val & 0x0f); - return; - case 0x3a: - case 0x3e: case 0x3f: case 0x42: case 0x43: - case 0x46: case 0x47: case 0x48: case 0x4a: - return; - case 0x49: - dev->ohci_mmio[addr] = (val & 0x1b); - if (val & 0x02) { - dev->ohci_mmio[0x55] |= 0x01; - dev->ohci_mmio[0x59] |= 0x01; - } - return; - case 0x4b: - dev->ohci_mmio[addr] = (val & 0x03); - return; - case 0x4c: case 0x4e: - dev->ohci_mmio[addr] = (val & 0x06); - if ((addr == 0x4c) && !(val & 0x04)) { - if (!(dev->ohci_mmio[0x58] & 0x01)) - dev->ohci_mmio[0x5a] |= 0x01; - dev->ohci_mmio[0x58] |= 0x01; - } if ((addr == 0x4c) && !(val & 0x02)) { - if (!(dev->ohci_mmio[0x54] & 0x01)) - dev->ohci_mmio[0x56] |= 0x01; - dev->ohci_mmio[0x54] |= 0x01; - } - return; - case 0x4d: case 0x4f: - return; - case 0x50: - if (val & 0x01) { - if ((dev->ohci_mmio[0x49] & 0x03) == 0x00) { - dev->ohci_mmio[0x55] &= ~0x01; - dev->ohci_mmio[0x54] &= ~0x17; - dev->ohci_mmio[0x56] &= ~0x17; - dev->ohci_mmio[0x59] &= ~0x01; - dev->ohci_mmio[0x58] &= ~0x17; - dev->ohci_mmio[0x5a] &= ~0x17; - } else if ((dev->ohci_mmio[0x49] & 0x03) == 0x01) { - if (!(dev->ohci_mmio[0x4e] & 0x02)) { - dev->ohci_mmio[0x55] &= ~0x01; - dev->ohci_mmio[0x54] &= ~0x17; - dev->ohci_mmio[0x56] &= ~0x17; - } - if (!(dev->ohci_mmio[0x4e] & 0x04)) { - dev->ohci_mmio[0x59] &= ~0x01; - dev->ohci_mmio[0x58] &= ~0x17; - dev->ohci_mmio[0x5a] &= ~0x17; - } - } - } - return; - case 0x51: - if (val & 0x80) - dev->ohci_mmio[addr] |= 0x80; - return; - case 0x52: - dev->ohci_mmio[addr] &= ~(val & 0x02); - if (val & 0x01) { - if ((dev->ohci_mmio[0x49] & 0x03) == 0x00) { - dev->ohci_mmio[0x55] |= 0x01; - dev->ohci_mmio[0x59] |= 0x01; - } else if ((dev->ohci_mmio[0x49] & 0x03) == 0x01) { - if (!(dev->ohci_mmio[0x4e] & 0x02)) - dev->ohci_mmio[0x55] |= 0x01; - if (!(dev->ohci_mmio[0x4e] & 0x04)) - dev->ohci_mmio[0x59] |= 0x01; - } - } - return; - case 0x53: - if (val & 0x80) - dev->ohci_mmio[0x51] &= ~0x80; - return; - case 0x54: case 0x58: - old = dev->ohci_mmio[addr]; + /* bit HostControllerReset must be cleared for the controller to be seen as initialized */ + if (val & 0x01) { + memset(dev->ohci_mmio, 0x00, 4096); + dev->ohci_mmio[0x00] = 0x10; + dev->ohci_mmio[0x01] = 0x01; + dev->ohci_mmio[0x48] = 0x02; + val &= ~0x01; + } + break; + case 0x0c: + dev->ohci_mmio[addr] &= ~(val & 0x7f); + return; + case 0x0d: + case 0x0e: + return; + case 0x0f: + dev->ohci_mmio[addr] &= ~(val & 0x40); + return; + case 0x3b: + dev->ohci_mmio[addr] = (val & 0x80); + return; + case 0x39: + case 0x41: + dev->ohci_mmio[addr] = (val & 0x3f); + return; + case 0x45: + dev->ohci_mmio[addr] = (val & 0x0f); + return; + case 0x3a: + case 0x3e: + case 0x3f: + case 0x42: + case 0x43: + case 0x46: + case 0x47: + case 0x48: + case 0x4a: + return; + case 0x49: + dev->ohci_mmio[addr] = (val & 0x1b); + if (val & 0x02) { + dev->ohci_mmio[0x55] |= 0x01; + dev->ohci_mmio[0x59] |= 0x01; + } + return; + case 0x4b: + dev->ohci_mmio[addr] = (val & 0x03); + return; + case 0x4c: + case 0x4e: + dev->ohci_mmio[addr] = (val & 0x06); + if ((addr == 0x4c) && !(val & 0x04)) { + if (!(dev->ohci_mmio[0x58] & 0x01)) + dev->ohci_mmio[0x5a] |= 0x01; + dev->ohci_mmio[0x58] |= 0x01; + } + if ((addr == 0x4c) && !(val & 0x02)) { + if (!(dev->ohci_mmio[0x54] & 0x01)) + dev->ohci_mmio[0x56] |= 0x01; + dev->ohci_mmio[0x54] |= 0x01; + } + return; + case 0x4d: + case 0x4f: + return; + case 0x50: + if (val & 0x01) { + if ((dev->ohci_mmio[0x49] & 0x03) == 0x00) { + dev->ohci_mmio[0x55] &= ~0x01; + dev->ohci_mmio[0x54] &= ~0x17; + dev->ohci_mmio[0x56] &= ~0x17; + dev->ohci_mmio[0x59] &= ~0x01; + dev->ohci_mmio[0x58] &= ~0x17; + dev->ohci_mmio[0x5a] &= ~0x17; + } else if ((dev->ohci_mmio[0x49] & 0x03) == 0x01) { + if (!(dev->ohci_mmio[0x4e] & 0x02)) { + dev->ohci_mmio[0x55] &= ~0x01; + dev->ohci_mmio[0x54] &= ~0x17; + dev->ohci_mmio[0x56] &= ~0x17; + } + if (!(dev->ohci_mmio[0x4e] & 0x04)) { + dev->ohci_mmio[0x59] &= ~0x01; + dev->ohci_mmio[0x58] &= ~0x17; + dev->ohci_mmio[0x5a] &= ~0x17; + } + } + } + return; + case 0x51: + if (val & 0x80) + dev->ohci_mmio[addr] |= 0x80; + return; + case 0x52: + dev->ohci_mmio[addr] &= ~(val & 0x02); + if (val & 0x01) { + if ((dev->ohci_mmio[0x49] & 0x03) == 0x00) { + dev->ohci_mmio[0x55] |= 0x01; + dev->ohci_mmio[0x59] |= 0x01; + } else if ((dev->ohci_mmio[0x49] & 0x03) == 0x01) { + if (!(dev->ohci_mmio[0x4e] & 0x02)) + dev->ohci_mmio[0x55] |= 0x01; + if (!(dev->ohci_mmio[0x4e] & 0x04)) + dev->ohci_mmio[0x59] |= 0x01; + } + } + return; + case 0x53: + if (val & 0x80) + dev->ohci_mmio[0x51] &= ~0x80; + return; + case 0x54: + case 0x58: + old = dev->ohci_mmio[addr]; - if (val & 0x10) { - if (old & 0x01) { - dev->ohci_mmio[addr] |= 0x10; - /* TODO: The clear should be on a 10 ms timer. */ - dev->ohci_mmio[addr] &= ~0x10; - dev->ohci_mmio[addr + 2] |= 0x10; - } else - dev->ohci_mmio[addr + 2] |= 0x01; - } - if (val & 0x08) - dev->ohci_mmio[addr] &= ~0x04; - if (val & 0x04) - dev->ohci_mmio[addr] |= 0x04; - if (val & 0x02) { - if (old & 0x01) - dev->ohci_mmio[addr] |= 0x02; - else - dev->ohci_mmio[addr + 2] |= 0x01; - } - if (val & 0x01) { - if (old & 0x01) - dev->ohci_mmio[addr] &= ~0x02; - else - dev->ohci_mmio[addr + 2] |= 0x01; - } + if (val & 0x10) { + if (old & 0x01) { + dev->ohci_mmio[addr] |= 0x10; + /* TODO: The clear should be on a 10 ms timer. */ + dev->ohci_mmio[addr] &= ~0x10; + dev->ohci_mmio[addr + 2] |= 0x10; + } else + dev->ohci_mmio[addr + 2] |= 0x01; + } + if (val & 0x08) + dev->ohci_mmio[addr] &= ~0x04; + if (val & 0x04) + dev->ohci_mmio[addr] |= 0x04; + if (val & 0x02) { + if (old & 0x01) + dev->ohci_mmio[addr] |= 0x02; + else + dev->ohci_mmio[addr + 2] |= 0x01; + } + if (val & 0x01) { + if (old & 0x01) + dev->ohci_mmio[addr] &= ~0x02; + else + dev->ohci_mmio[addr + 2] |= 0x01; + } - if (!(dev->ohci_mmio[addr] & 0x04) && (old & 0x04)) - dev->ohci_mmio[addr + 2] |= 0x04; - /* if (!(dev->ohci_mmio[addr] & 0x02)) - dev->ohci_mmio[addr + 2] |= 0x02; */ - return; - case 0x55: - if ((val & 0x02) && ((dev->ohci_mmio[0x49] & 0x03) == 0x00) && (dev->ohci_mmio[0x4e] & 0x02)) { - dev->ohci_mmio[addr] &= ~0x01; - dev->ohci_mmio[0x54] &= ~0x17; - dev->ohci_mmio[0x56] &= ~0x17; - } if ((val & 0x01) && ((dev->ohci_mmio[0x49] & 0x03) == 0x00) && (dev->ohci_mmio[0x4e] & 0x02)) { - dev->ohci_mmio[addr] |= 0x01; - dev->ohci_mmio[0x58] &= ~0x17; - dev->ohci_mmio[0x5a] &= ~0x17; - } - return; - case 0x59: - if ((val & 0x02) && ((dev->ohci_mmio[0x49] & 0x03) == 0x00) && (dev->ohci_mmio[0x4e] & 0x04)) - dev->ohci_mmio[addr] &= ~0x01; - if ((val & 0x01) && ((dev->ohci_mmio[0x49] & 0x03) == 0x00) && (dev->ohci_mmio[0x4e] & 0x04)) - dev->ohci_mmio[addr] |= 0x01; - return; - case 0x56: case 0x5a: - dev->ohci_mmio[addr] &= ~(val & 0x1f); - return; - case 0x57: case 0x5b: - return; + if (!(dev->ohci_mmio[addr] & 0x04) && (old & 0x04)) + dev->ohci_mmio[addr + 2] |= 0x04; +#if 0 + if (!(dev->ohci_mmio[addr] & 0x02)) + dev->ohci_mmio[addr + 2] |= 0x02; +#endif + return; + case 0x55: + if ((val & 0x02) && ((dev->ohci_mmio[0x49] & 0x03) == 0x00) && (dev->ohci_mmio[0x4e] & 0x02)) { + dev->ohci_mmio[addr] &= ~0x01; + dev->ohci_mmio[0x54] &= ~0x17; + dev->ohci_mmio[0x56] &= ~0x17; + } + if ((val & 0x01) && ((dev->ohci_mmio[0x49] & 0x03) == 0x00) && (dev->ohci_mmio[0x4e] & 0x02)) { + dev->ohci_mmio[addr] |= 0x01; + dev->ohci_mmio[0x58] &= ~0x17; + dev->ohci_mmio[0x5a] &= ~0x17; + } + return; + case 0x59: + if ((val & 0x02) && ((dev->ohci_mmio[0x49] & 0x03) == 0x00) && (dev->ohci_mmio[0x4e] & 0x04)) + dev->ohci_mmio[addr] &= ~0x01; + if ((val & 0x01) && ((dev->ohci_mmio[0x49] & 0x03) == 0x00) && (dev->ohci_mmio[0x4e] & 0x04)) + dev->ohci_mmio[addr] |= 0x01; + return; + case 0x56: + case 0x5a: + dev->ohci_mmio[addr] &= ~(val & 0x1f); + return; + case 0x57: + case 0x5b: + return; + + default: + break; } dev->ohci_mmio[addr] = val; } - void ohci_update_mem_mapping(usb_t *dev, uint8_t base1, uint8_t base2, uint8_t base3, int enable) { if (dev->ohci_enable && (dev->ohci_mem_base != 0x00000000)) - mem_mapping_disable(&dev->ohci_mmio_mapping); + mem_mapping_disable(&dev->ohci_mmio_mapping); dev->ohci_mem_base = ((base1 << 8) | (base2 << 16) | (base3 << 24)) & 0xfffff000; - dev->ohci_enable = enable; + dev->ohci_enable = enable; if (dev->ohci_enable && (dev->ohci_mem_base != 0x00000000)) - mem_mapping_set_addr(&dev->ohci_mmio_mapping, dev->ohci_mem_base, 0x1000); + mem_mapping_set_addr(&dev->ohci_mmio_mapping, dev->ohci_mem_base, 0x1000); } - static void usb_reset(void *priv) { @@ -372,7 +389,6 @@ usb_reset(void *priv) dev->ohci_enable = 0; } - static void usb_close(void *priv) { @@ -381,14 +397,14 @@ usb_close(void *priv) free(dev); } - static void * -usb_init(const device_t *info) +usb_init(UNUSED(const device_t *info)) { usb_t *dev; - dev = (usb_t *)malloc(sizeof(usb_t)); - if (dev == NULL) return(NULL); + dev = (usb_t *) malloc(sizeof(usb_t)); + if (dev == NULL) + return (NULL); memset(dev, 0x00, sizeof(usb_t)); memset(dev->uhci_io, 0x00, 128); @@ -401,26 +417,24 @@ usb_init(const device_t *info) dev->ohci_mmio[0x48] = 0x02; mem_mapping_add(&dev->ohci_mmio_mapping, 0, 0, - ohci_mmio_read, NULL, NULL, - ohci_mmio_write, NULL, NULL, - NULL, MEM_MAPPING_EXTERNAL, dev); + ohci_mmio_read, NULL, NULL, + ohci_mmio_write, NULL, NULL, + NULL, MEM_MAPPING_EXTERNAL, dev); usb_reset(dev); return dev; } - -const device_t usb_device = -{ - "Universal Serial Bus", - "usb", - DEVICE_PCI, - 0, - usb_init, - usb_close, - usb_reset, - { NULL }, - NULL, - NULL, - NULL +const device_t usb_device = { + .name = "Universal Serial Bus", + .internal_name = "usb", + .flags = DEVICE_PCI, + .local = 0, + .init = usb_init, + .close = usb_close, + .reset = usb_reset, + { .available = NULL }, + .speed_changed = NULL, + .force_redraw = NULL, + .config = NULL }; diff --git a/src/video/CMakeLists.txt b/src/video/CMakeLists.txt index c58b2f054..59205f235 100644 --- a/src/video/CMakeLists.txt +++ b/src/video/CMakeLists.txt @@ -1,30 +1,32 @@ # -# 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. +# 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. +# This file is part of the 86Box distribution. # -# CMake build script. +# CMake build script. # -# Authors: David HrdliÄka, +# Authors: David HrdliÄka, # -# Copyright 2020,2021 David HrdliÄka. +# Copyright 2020-2021 David HrdliÄka. # add_library(vid OBJECT agpgart.c video.c vid_table.c vid_cga.c vid_cga_comp.c vid_compaq_cga.c vid_mda.c vid_hercules.c vid_herculesplus.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_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_ati68875_ramdac.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_et4000.c vid_sc1148x_ramdac.c vid_sc1502x_ramdac.c vid_et4000w32.c - vid_stg_ramdac.c vid_ht216.c vid_oak_oti.c vid_paradise.c vid_rtg310x.c - vid_f82c425.c vid_ti_cf62011.c vid_tvga.c vid_tgui9440.c vid_tkd8001_ramdac.c - vid_att20c49x_ramdac.c vid_s3.c vid_s3_virge.c vid_ibm_rgb528_ramdac.c - vid_sdac_ramdac.c vid_ogc.c vid_nga.c vid_tvp3026_ramdac.c vid_att2xc498_ramdac.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 + vid_rtg310x.c vid_f82c425.c vid_ti_cf62011.c vid_tvga.c vid_tgui9440.c + vid_tkd8001_ramdac.c vid_att20c49x_ramdac.c vid_s3.c vid_s3_virge.c + vid_ibm_rgb528_ramdac.c vid_sdac_ramdac.c vid_ogc.c vid_nga.c + vid_tvp3026_ramdac.c vid_att2xc498_ramdac.c vid_xga.c) if(MGA) target_compile_definitions(vid PRIVATE USE_MGA) @@ -47,9 +49,3 @@ add_library(voodoo OBJECT vid_voodoo.c vid_voodoo_banshee.c if(NOT MSVC AND (ARCH STREQUAL "i386" OR ARCH STREQUAL "x86_64")) target_compile_options(voodoo PRIVATE "-msse2") endif() - -# Suppress GCC false positive warnings in vid_voodoo_codegen_x86[-64].h -# that cause ~3000 lines to be output into the logs each time -if(CMAKE_C_COMPILER_ID STREQUAL "GNU") - target_compile_options(voodoo PRIVATE "-Wstringop-overflow=0") -endif() \ No newline at end of file diff --git a/src/video/agpgart.c b/src/video/agpgart.c index 05bf2d631..b8ae2bdc8 100644 --- a/src/video/agpgart.c +++ b/src/video/agpgart.c @@ -1,18 +1,18 @@ /* - * 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. + * 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. + * This file is part of the 86Box distribution. * - * AGP Graphics Address Remapping Table remapping emulation. + * AGP Graphics Address Remapping Table remapping emulation. * * * - * Authors: RichardG, + * Authors: RichardG, * - * Copyright 2021 RichardG. + * Copyright 2021 RichardG. */ #include #include @@ -23,14 +23,8 @@ #include <86box/86box.h> #include <86box/device.h> #include <86box/mem.h> - - -typedef struct { - int aperture_enable; - uint32_t aperture_base, aperture_size, aperture_mask, gart_base; - mem_mapping_t aperture_mapping; -} agpgart_t; - +#include <86box/agpgart.h> +#include <86box/plat_unused.h> #ifdef ENABLE_AGPGART_LOG int agpgart_do_log = ENABLE_AGPGART_LOG; @@ -41,51 +35,45 @@ agpgart_log(const char *fmt, ...) va_list ap; if (agpgart_do_log) { - va_start(ap, fmt); - pclog_ex(fmt, ap); - va_end(ap); + va_start(ap, fmt); + pclog_ex(fmt, ap); + va_end(ap); } } #else -#define agpgart_log(fmt, ...) +# define agpgart_log(fmt, ...) #endif - void -agpgart_set_aperture(void *handle, uint32_t base, uint32_t size, int enable) +agpgart_set_aperture(agpgart_t *dev, uint32_t base, uint32_t size, int enable) { - agpgart_t *dev = (agpgart_t *) handle; - agpgart_log("AGP GART: set_aperture(%08X, %d, %d)\n", base, size, enable); /* Disable old aperture mapping. */ mem_mapping_disable(&dev->aperture_mapping); - /* Set new aperture base address, size and mask. */ - dev->aperture_base = base; - dev->aperture_size = size; - dev->aperture_mask = size - 1; + /* Set new aperture base address, size, mask and enable. */ + dev->aperture_base = base; + dev->aperture_size = size; + dev->aperture_mask = size - 1; + dev->aperture_enable = enable; /* Enable new aperture mapping if requested. */ if (dev->aperture_base && dev->aperture_size && dev->aperture_enable) { - mem_mapping_set_addr(&dev->aperture_mapping, dev->aperture_base, dev->aperture_size); - mem_mapping_enable(&dev->aperture_mapping); + mem_mapping_set_addr(&dev->aperture_mapping, dev->aperture_base, dev->aperture_size); + mem_mapping_enable(&dev->aperture_mapping); } } - void -agpgart_set_gart(void *handle, uint32_t base) +agpgart_set_gart(agpgart_t *dev, uint32_t base) { - agpgart_t *dev = (agpgart_t *) handle; - agpgart_log("AGP GART: set_gart(%08X)\n", base); /* Set GART base address. */ dev->gart_base = base; } - static uint32_t agpgart_translate(uint32_t addr, agpgart_t *dev) { @@ -99,7 +87,6 @@ agpgart_translate(uint32_t addr, agpgart_t *dev) return gart_ptr | (addr & 0x00000fff); } - static uint8_t agpgart_aperture_readb(uint32_t addr, void *priv) { @@ -107,7 +94,6 @@ agpgart_aperture_readb(uint32_t addr, void *priv) return mem_readb_phys(agpgart_translate(addr, dev)); } - static uint16_t agpgart_aperture_readw(uint32_t addr, void *priv) { @@ -115,7 +101,6 @@ agpgart_aperture_readw(uint32_t addr, void *priv) return mem_readw_phys(agpgart_translate(addr, dev)); } - static uint32_t agpgart_aperture_readl(uint32_t addr, void *priv) { @@ -123,7 +108,6 @@ agpgart_aperture_readl(uint32_t addr, void *priv) return mem_readl_phys(agpgart_translate(addr, dev)); } - static void agpgart_aperture_writeb(uint32_t addr, uint8_t val, void *priv) { @@ -131,7 +115,6 @@ agpgart_aperture_writeb(uint32_t addr, uint8_t val, void *priv) mem_writeb_phys(agpgart_translate(addr, dev), val); } - static void agpgart_aperture_writew(uint32_t addr, uint16_t val, void *priv) { @@ -139,7 +122,6 @@ agpgart_aperture_writew(uint32_t addr, uint16_t val, void *priv) mem_writew_phys(agpgart_translate(addr, dev), val); } - static void agpgart_aperture_writel(uint32_t addr, uint32_t val, void *priv) { @@ -147,9 +129,8 @@ agpgart_aperture_writel(uint32_t addr, uint32_t val, void *priv) mem_writel_phys(agpgart_translate(addr, dev), val); } - static void * -agpgart_init(const device_t *info) +agpgart_init(UNUSED(const device_t *info)) { agpgart_t *dev = malloc(sizeof(agpgart_t)); memset(dev, 0, sizeof(agpgart_t)); @@ -158,14 +139,13 @@ agpgart_init(const device_t *info) /* Create aperture mapping. */ mem_mapping_add(&dev->aperture_mapping, 0, 0, - agpgart_aperture_readb, agpgart_aperture_readw, agpgart_aperture_readl, - agpgart_aperture_writeb, agpgart_aperture_writew, agpgart_aperture_writel, - NULL, MEM_MAPPING_EXTERNAL, dev); + agpgart_aperture_readb, agpgart_aperture_readw, agpgart_aperture_readl, + agpgart_aperture_writeb, agpgart_aperture_writew, agpgart_aperture_writel, + NULL, MEM_MAPPING_EXTERNAL, dev); return dev; } - static void agpgart_close(void *priv) { @@ -179,16 +159,16 @@ agpgart_close(void *priv) free(dev); } - -const device_t agpgart_device = -{ - "AGP Graphics Address Remapping Table", - "agpgart", - DEVICE_PCI, - 0, - agpgart_init, agpgart_close, NULL, - { NULL }, - NULL, - NULL, - NULL +const device_t agpgart_device = { + .name = "AGP Graphics Address Remapping Table", + .internal_name = "agpgart", + .flags = DEVICE_PCI, + .local = 0, + .init = agpgart_init, + .close = agpgart_close, + .reset = NULL, + { .available = NULL }, + .speed_changed = NULL, + .force_redraw = NULL, + .config = NULL }; diff --git a/src/video/vid_8514a.c b/src/video/vid_8514a.c new file mode 100644 index 000000000..a2cabfb0d --- /dev/null +++ b/src/video/vid_8514a.c @@ -0,0 +1,4442 @@ +/* + * 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 card from IBM for the MCA bus and + * ISA bus clones. + * + * + * + * 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/machine.h> +#include <86box/mem.h> +#include <86box/timer.h> +#include <86box/mca.h> +#include <86box/rom.h> +#include <86box/plat.h> +#include <86box/thread.h> +#include <86box/video.h> +#include <86box/vid_8514a.h> +#include <86box/vid_xga.h> +#include <86box/vid_svga.h> +#include <86box/vid_svga_render.h> +#include "cpu.h" + +static void ibm8514_accel_outb(uint16_t port, uint8_t val, void *priv); +static void ibm8514_accel_outw(uint16_t port, uint16_t val, void *priv); +static uint8_t ibm8514_accel_inb(uint16_t port, void *priv); +static uint16_t ibm8514_accel_inw(uint16_t port, void *priv); + +#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); \ + } 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) \ + if (dev->bpp) { \ + dat = vram_w[(addr) & (dev->vram_mask >> 1)]; \ + } else { \ + dat = (dev->vram[(addr) & (dev->vram_mask)]); \ + } + +#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) >> 1; \ + break; \ + case 0x16: \ + dest_dat = (src_dat - dest_dat) >> 1; \ + break; \ + case 0x17: \ + dest_dat = (dest_dat + src_dat) >> 1; \ + 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(~0, (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 = (~0 < (src_dat + dest_dat)) ? ~0 : ((src_dat + dest_dat) >> 1); \ + break; \ + } \ + } + +#define WRITE(addr, dat) \ + if (dev->bpp) { \ + vram_w[((addr)) & (dev->vram_mask >> 1)] = dat; \ + dev->changedvram[(((addr)) & (dev->vram_mask >> 1)) >> 11] = changeframecount; \ + } else { \ + dev->vram[((addr)) & (dev->vram_mask)] = dat; \ + dev->changedvram[(((addr)) & (dev->vram_mask)) >> 12] = changeframecount; \ + } + +int ibm8514_active = 0; + +int +ibm8514_cpu_src(svga_t *svga) +{ + const ibm8514_t *dev = (ibm8514_t *) svga->dev8514; + + if (!(dev->accel.cmd & 0x100)) + return 0; + + if (dev->accel.cmd & 1) + return 1; + + return 0; +} + +int +ibm8514_cpu_dest(svga_t *svga) +{ + const ibm8514_t *dev = (ibm8514_t *) svga->dev8514; + + if (!(dev->accel.cmd & 0x100)) + return 0; + + if (dev->accel.cmd & 1) + return 0; + + return 1; +} + +void +ibm8514_accel_out_pixtrans(svga_t *svga, UNUSED(uint16_t port), uint16_t val, int len) +{ + ibm8514_t *dev = (ibm8514_t *) svga->dev8514; + uint8_t nibble = 0; + uint32_t pixelxfer = 0; + uint32_t monoxfer = 0xffffffff; + int pixcnt = 0; + int pixcntl = (dev->accel.multifunc[0x0a] >> 6) & 3; + int frgd_mix = (dev->accel.frgd_mix >> 5) & 3; + int bkgd_mix = (dev->accel.bkgd_mix >> 5) & 3; + int cmd = dev->accel.cmd >> 13; + int and3 = dev->accel.cur_x & 3; + + if (dev->accel.cmd & 0x100) { + if (len != 1) { + /*Bus size*/ + if (dev->accel.cmd & 0x200) /*16-bit*/ + pixcnt = 16; + else /*8-bit*/ + pixcnt = 8; + + /*Pixel transfer data mode, can't be the same as Foreground/Background CPU data*/ + if (pixcntl == 2) { + if ((frgd_mix == 2) || (bkgd_mix == 2)) { + pixelxfer = val; + } else { + if (dev->accel.cmd & 2) { + if (pixcnt == 16) { + if ((cmd >= 2) && (dev->accel.cmd & 0x1000)) + val = (val >> 8) | (val << 8); + } + if (and3 == 3) { + if (dev->accel.cmd & 0x1000) + goto regular_nibble; + if (val & 0x02) + nibble |= 0x10; + if (val & 0x04) + nibble |= 0x08; + if (val & 0x08) + nibble |= 0x04; + if (val & 0x10) + nibble |= 0x02; + if (val & 0x200) + nibble |= 0x01; + if (val & 0x400) + nibble |= 0x80; + if (val & 0x800) + nibble |= 0x40; + if (val & 0x1000) + nibble |= 0x20; + } else if (and3 == 2) { + if (dev->accel.cmd & 0x1000) + goto regular_nibble; + if (val & 0x02) + nibble |= 0x20; + if (val & 0x04) + nibble |= 0x10; + if (val & 0x08) + nibble |= 0x08; + if (val & 0x10) + nibble |= 0x04; + if (val & 0x200) + nibble |= 0x02; + if (val & 0x400) + nibble |= 0x01; + if (val & 0x800) + nibble |= 0x80; + if (val & 0x1000) + nibble |= 0x40; + } else if (and3 == 1) { + if (dev->accel.cmd & 0x1000) + goto regular_nibble; + if (val & 0x02) + nibble |= 0x40; + if (val & 0x04) + nibble |= 0x20; + if (val & 0x08) + nibble |= 0x10; + if (val & 0x10) + nibble |= 0x08; + if (val & 0x200) + nibble |= 0x04; + if (val & 0x400) + nibble |= 0x02; + if (val & 0x800) + nibble |= 0x01; + if (val & 0x1000) + nibble |= 0x80; + } else { +regular_nibble: + if (val & 0x02) + nibble |= 0x80; + if (val & 0x04) + nibble |= 0x40; + if (val & 0x08) + nibble |= 0x20; + if (val & 0x10) + nibble |= 0x10; + if (val & 0x200) + nibble |= 0x08; + if (val & 0x400) + nibble |= 0x04; + if (val & 0x800) + nibble |= 0x02; + if (val & 0x1000) + nibble |= 0x01; + } + + if ((and3 == 0) || (dev->accel.cmd & 0x1000) || ((dev->accel.cmd & 8) && ibm8514_cpu_src(svga))) { + if ((dev->accel.cmd & 8) && ibm8514_cpu_src(svga)) { + monoxfer = val; + } else + monoxfer = nibble; + ibm8514_accel_start(pixcnt, 1, monoxfer, pixelxfer, svga, len); + if (dev->accel.nibbleset != NULL) { + free(dev->accel.nibbleset); + dev->accel.nibbleset = NULL; + } + if (dev->accel.writemono != NULL) { + free(dev->accel.writemono); + dev->accel.writemono = NULL; + } + return; + } + + dev->accel.writemono[dev->accel.x_count] = nibble; + if (val & 0x1c00) { + if (and3 == 1) { + if (val & 0x1000) + dev->accel.nibbleset[dev->accel.x_count] = 0x80; + else + dev->accel.nibbleset[dev->accel.x_count] = 0; + } else if (and3 == 2) { + if (val & 0x1000) { + if (val & 0x800) + dev->accel.nibbleset[dev->accel.x_count] = 0xc0; + else + dev->accel.nibbleset[dev->accel.x_count] = 0x40; + } else if (val & 0x800) { + if (val & 0x1000) + dev->accel.nibbleset[dev->accel.x_count] = 0xc0; + else + dev->accel.nibbleset[dev->accel.x_count] = 0x80; + } else + dev->accel.nibbleset[dev->accel.x_count] = 0; + } else if (and3 == 3) { + if (val & 0x1000) { + if (val & 0x800) { + if (val & 0x400) + dev->accel.nibbleset[dev->accel.x_count] = 0xe0; + else + dev->accel.nibbleset[dev->accel.x_count] = 0x60; + } else if (val & 0x400) { + if (val & 0x800) + dev->accel.nibbleset[dev->accel.x_count] = 0xe0; + else + dev->accel.nibbleset[dev->accel.x_count] = 0xa0; + } else + dev->accel.nibbleset[dev->accel.x_count] = 0x20; + } else if (val & 0x800) { + if (val & 0x400) { + if (val & 0x1000) + dev->accel.nibbleset[dev->accel.x_count] = 0xe0; + else + dev->accel.nibbleset[dev->accel.x_count] = 0xc0; + } else if (val & 0x1000) { + if (val & 0x400) + dev->accel.nibbleset[dev->accel.x_count] = 0xe0; + else + dev->accel.nibbleset[dev->accel.x_count] = 0x60; + } else + dev->accel.nibbleset[dev->accel.x_count] = 0x40; + } else if (val & 0x400) { + if (val & 0x800) { + if (val & 0x1000) + dev->accel.nibbleset[dev->accel.x_count] = 0xe0; + else + dev->accel.nibbleset[dev->accel.x_count] = 0xc0; + } else if (val & 0x1000) { + if (val & 0x800) + dev->accel.nibbleset[dev->accel.x_count] = 0xe0; + else + dev->accel.nibbleset[dev->accel.x_count] = 0xa0; + } else + dev->accel.nibbleset[dev->accel.x_count] = 0x80; + } else + dev->accel.nibbleset[dev->accel.x_count] = 0; + } + } else + dev->accel.nibbleset[dev->accel.x_count] = 0; + + dev->accel.x_count++; + if (dev->accel.x_count == dev->accel.sys_cnt) { + for (int i = 0; i < dev->accel.x_count; i++) { + dev->accel.writemono[i] &= ~dev->accel.nibbleset[i]; + dev->accel.writemono[i] |= dev->accel.nibbleset[i + 1]; + ibm8514_accel_start(pixcnt, 1, dev->accel.writemono[i], pixelxfer, svga, len); + } + + dev->accel.x_count = 0; + if (dev->accel.nibbleset != NULL) { + free(dev->accel.nibbleset); + dev->accel.nibbleset = NULL; + } + if (dev->accel.writemono != NULL) { + free(dev->accel.writemono); + dev->accel.writemono = NULL; + } + } + return; + } + monoxfer = val; + } + } else { + pixelxfer = val; + } + ibm8514_accel_start(pixcnt, 1, monoxfer, pixelxfer, svga, len); + } + } +} + +static void +ibm8514_accel_out_fifo(svga_t *svga, uint16_t port, uint32_t val, int len) +{ + ibm8514_t *dev = (ibm8514_t *) svga->dev8514; + + 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 { + 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 { + 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; + fallthrough; + case 0xd2e8: + 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 & 0x700) | val; + else { + dev->accel.maj_axis_pcnt = val & 0x7ff; + } + 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; + 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); + 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: + 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 >= 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 (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 (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 (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 (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 (val & 0x400) + dev->accel.clip_top |= ~0x3ff; + } + if ((dev->accel.multifunc_cntl >> 12) == 2) { + dev->accel.clip_left = val & 0x7ff; + if (val & 0x400) + dev->accel.clip_left |= ~0x3ff; + } + 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 (port == 0xfee9) + dev->accel.cmd_back = 1; + else + dev->accel.cmd_back = 0; + } + break; + + default: + break; + } +} + +void +ibm8514_ramdac_out(uint16_t port, uint8_t val, void *priv) +{ + svga_t *svga = (svga_t *) priv; + + svga_out(port, val, svga); +} + +uint8_t +ibm8514_ramdac_in(uint16_t port, void *priv) +{ + svga_t *svga = (svga_t *) priv; + uint8_t ret; + + ret = svga_in(port, svga); + return ret; +} + +static void +ibm8514_io_set(svga_t *svga) +{ + io_sethandler(0x2e8, 0x0002, ibm8514_accel_inb, ibm8514_accel_inw, NULL, ibm8514_accel_outb, ibm8514_accel_outw, NULL, svga); + io_sethandler(0x2ea, 0x0004, ibm8514_ramdac_in, NULL, NULL, ibm8514_ramdac_out, NULL, NULL, svga); + io_sethandler(0x6e8, 0x0002, ibm8514_accel_inb, ibm8514_accel_inw, NULL, ibm8514_accel_outb, ibm8514_accel_outw, NULL, svga); + io_sethandler(0xae8, 0x0002, ibm8514_accel_inb, ibm8514_accel_inw, NULL, ibm8514_accel_outb, ibm8514_accel_outw, NULL, svga); + io_sethandler(0xee8, 0x0002, ibm8514_accel_inb, ibm8514_accel_inw, NULL, ibm8514_accel_outb, ibm8514_accel_outw, NULL, svga); + io_sethandler(0x12e8, 0x0002, ibm8514_accel_inb, ibm8514_accel_inw, NULL, ibm8514_accel_outb, ibm8514_accel_outw, NULL, svga); + io_sethandler(0x16e8, 0x0002, ibm8514_accel_inb, ibm8514_accel_inw, NULL, ibm8514_accel_outb, ibm8514_accel_outw, NULL, svga); + io_sethandler(0x1ae8, 0x0002, ibm8514_accel_inb, ibm8514_accel_inw, NULL, ibm8514_accel_outb, ibm8514_accel_outw, NULL, svga); + io_sethandler(0x1ee8, 0x0002, ibm8514_accel_inb, ibm8514_accel_inw, NULL, ibm8514_accel_outb, ibm8514_accel_outw, NULL, svga); + io_sethandler(0x22e8, 0x0002, ibm8514_accel_inb, ibm8514_accel_inw, NULL, ibm8514_accel_outb, ibm8514_accel_outw, NULL, svga); + io_sethandler(0x26e8, 0x0002, ibm8514_accel_inb, ibm8514_accel_inw, NULL, ibm8514_accel_outb, ibm8514_accel_outw, NULL, svga); + io_sethandler(0x2ee8, 0x0002, ibm8514_accel_inb, ibm8514_accel_inw, NULL, ibm8514_accel_outb, ibm8514_accel_outw, NULL, svga); + io_sethandler(0x42e8, 0x0002, ibm8514_accel_inb, ibm8514_accel_inw, NULL, ibm8514_accel_outb, ibm8514_accel_outw, NULL, svga); + io_sethandler(0x4ae8, 0x0002, ibm8514_accel_inb, ibm8514_accel_inw, NULL, ibm8514_accel_outb, ibm8514_accel_outw, NULL, svga); + io_sethandler(0x52e8, 0x0002, ibm8514_accel_inb, ibm8514_accel_inw, NULL, ibm8514_accel_outb, ibm8514_accel_outw, NULL, svga); + io_sethandler(0x56e8, 0x0002, ibm8514_accel_inb, ibm8514_accel_inw, NULL, ibm8514_accel_outb, ibm8514_accel_outw, NULL, svga); + io_sethandler(0x5ae8, 0x0002, ibm8514_accel_inb, ibm8514_accel_inw, NULL, ibm8514_accel_outb, ibm8514_accel_outw, NULL, svga); + io_sethandler(0x5ee8, 0x0002, ibm8514_accel_inb, ibm8514_accel_inw, NULL, ibm8514_accel_outb, ibm8514_accel_outw, NULL, svga); + io_sethandler(0x82e8, 0x0002, ibm8514_accel_inb, ibm8514_accel_inw, NULL, ibm8514_accel_outb, ibm8514_accel_outw, NULL, svga); + io_sethandler(0x86e8, 0x0002, ibm8514_accel_inb, ibm8514_accel_inw, NULL, ibm8514_accel_outb, ibm8514_accel_outw, NULL, svga); + io_sethandler(0x8ae8, 0x0002, ibm8514_accel_inb, ibm8514_accel_inw, NULL, ibm8514_accel_outb, ibm8514_accel_outw, NULL, svga); + io_sethandler(0x8ee8, 0x0002, ibm8514_accel_inb, ibm8514_accel_inw, NULL, ibm8514_accel_outb, ibm8514_accel_outw, NULL, svga); + io_sethandler(0x92e8, 0x0002, ibm8514_accel_inb, ibm8514_accel_inw, NULL, ibm8514_accel_outb, ibm8514_accel_outw, NULL, svga); + io_sethandler(0x96e8, 0x0002, ibm8514_accel_inb, ibm8514_accel_inw, NULL, ibm8514_accel_outb, ibm8514_accel_outw, NULL, svga); + io_sethandler(0x9ae8, 0x0002, ibm8514_accel_inb, ibm8514_accel_inw, NULL, ibm8514_accel_outb, ibm8514_accel_outw, NULL, svga); + io_sethandler(0x9ee8, 0x0002, ibm8514_accel_inb, ibm8514_accel_inw, NULL, ibm8514_accel_outb, ibm8514_accel_outw, NULL, svga); + io_sethandler(0xa2e8, 0x0002, ibm8514_accel_inb, ibm8514_accel_inw, NULL, ibm8514_accel_outb, ibm8514_accel_outw, NULL, svga); + io_sethandler(0xa6e8, 0x0002, ibm8514_accel_inb, ibm8514_accel_inw, NULL, ibm8514_accel_outb, ibm8514_accel_outw, NULL, svga); + io_sethandler(0xaae8, 0x0002, ibm8514_accel_inb, ibm8514_accel_inw, NULL, ibm8514_accel_outb, ibm8514_accel_outw, NULL, svga); + io_sethandler(0xaee8, 0x0002, ibm8514_accel_inb, ibm8514_accel_inw, NULL, ibm8514_accel_outb, ibm8514_accel_outw, NULL, svga); + io_sethandler(0xb2e8, 0x0002, ibm8514_accel_inb, ibm8514_accel_inw, NULL, ibm8514_accel_outb, ibm8514_accel_outw, NULL, svga); + io_sethandler(0xb6e8, 0x0002, ibm8514_accel_inb, ibm8514_accel_inw, NULL, ibm8514_accel_outb, ibm8514_accel_outw, NULL, svga); + io_sethandler(0xbae8, 0x0002, ibm8514_accel_inb, ibm8514_accel_inw, NULL, ibm8514_accel_outb, ibm8514_accel_outw, NULL, svga); + io_sethandler(0xbee8, 0x0002, ibm8514_accel_inb, ibm8514_accel_inw, NULL, ibm8514_accel_outb, ibm8514_accel_outw, NULL, svga); + io_sethandler(0xe2e8, 0x0002, ibm8514_accel_inb, ibm8514_accel_inw, NULL, ibm8514_accel_outb, ibm8514_accel_outw, NULL, svga); + + io_sethandler(0xc2e8, 0x0002, ibm8514_accel_inb, ibm8514_accel_inw, NULL, ibm8514_accel_outb, ibm8514_accel_outw, NULL, svga); + io_sethandler(0xc6e8, 0x0002, ibm8514_accel_inb, ibm8514_accel_inw, NULL, ibm8514_accel_outb, ibm8514_accel_outw, NULL, svga); + io_sethandler(0xcae8, 0x0002, ibm8514_accel_inb, ibm8514_accel_inw, NULL, ibm8514_accel_outb, ibm8514_accel_outw, NULL, svga); + io_sethandler(0xcee8, 0x0002, ibm8514_accel_inb, ibm8514_accel_inw, NULL, ibm8514_accel_outb, ibm8514_accel_outw, NULL, svga); + io_sethandler(0xd2e8, 0x0002, ibm8514_accel_inb, ibm8514_accel_inw, NULL, ibm8514_accel_outb, ibm8514_accel_outw, NULL, svga); + io_sethandler(0xd6e8, 0x0002, ibm8514_accel_inb, ibm8514_accel_inw, NULL, ibm8514_accel_outb, ibm8514_accel_outw, NULL, svga); + io_sethandler(0xdae8, 0x0002, ibm8514_accel_inb, ibm8514_accel_inw, NULL, ibm8514_accel_outb, ibm8514_accel_outw, NULL, svga); + io_sethandler(0xdee8, 0x0002, ibm8514_accel_inb, ibm8514_accel_inw, NULL, ibm8514_accel_outb, ibm8514_accel_outw, NULL, svga); + io_sethandler(0xe6e8, 0x0002, ibm8514_accel_inb, ibm8514_accel_inw, NULL, ibm8514_accel_outb, ibm8514_accel_outw, NULL, svga); + io_sethandler(0xeae8, 0x0002, ibm8514_accel_inb, ibm8514_accel_inw, NULL, ibm8514_accel_outb, ibm8514_accel_outw, NULL, svga); + io_sethandler(0xeee8, 0x0002, ibm8514_accel_inb, ibm8514_accel_inw, NULL, ibm8514_accel_outb, ibm8514_accel_outw, NULL, svga); + io_sethandler(0xf2e8, 0x0002, ibm8514_accel_inb, ibm8514_accel_inw, NULL, ibm8514_accel_outb, ibm8514_accel_outw, NULL, svga); + io_sethandler(0xf6e8, 0x0002, ibm8514_accel_inb, ibm8514_accel_inw, NULL, ibm8514_accel_outb, ibm8514_accel_outw, NULL, svga); + io_sethandler(0xfae8, 0x0002, ibm8514_accel_inb, ibm8514_accel_inw, NULL, ibm8514_accel_outb, ibm8514_accel_outw, NULL, svga); + io_sethandler(0xfee8, 0x0002, ibm8514_accel_inb, ibm8514_accel_inw, NULL, ibm8514_accel_outb, ibm8514_accel_outw, NULL, svga); +} + +static void +ibm8514_accel_out(uint16_t port, uint32_t val, svga_t *svga, int len) +{ + ibm8514_t *dev = (ibm8514_t *) svga->dev8514; + + if (port & 0x8000) { + ibm8514_accel_out_fifo(svga, 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); + ibm8514_log("IBM 8514/A: H_TOTAL write 02E8 = %d\n", dev->htotal + 1); + svga_recalctimings(svga); + } + break; + + case 0x6e8: + dev->hdisp = val; + ibm8514_log("IBM 8514/A: H_DISP write 06E8 = %d\n", dev->hdisp + 1); + svga_recalctimings(svga); + break; + + case 0xae8: + ibm8514_log("IBM 8514/A: H_SYNC_STRT write 0AE8 = %d\n", val + 1); + svga_recalctimings(svga); + break; + + case 0xee8: + ibm8514_log("IBM 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); + ibm8514_log("IBM 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); + ibm8514_log("IBM 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); + ibm8514_log("IBM 8514/A: V_SYNC_STRT write 1AE8 = %d\n", dev->vsyncstart); + svga_recalctimings(svga); + } + break; + + case 0x1ee8: + dev->vsyncwidth = 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); + ibm8514_log("IBM 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); + } + break; + case 0x42e9: + if (len == 1) { + dev->subsys_cntl = val; + } + break; + + case 0x4ae8: + if (!val) + break; + dev->accel.advfunc_cntl = val & 0x0f; + dev->on = val & 0x01; + vga_on = !dev->on; + ibm8514_log("IBM 8514/A: VGA ON = %i, val = %02x\n", vga_on, val); + svga_recalctimings(svga); + break; + + default: + break; + } + } +} + +static void +ibm8514_accel_outb(uint16_t port, uint8_t val, void *priv) +{ + svga_t *svga = (svga_t *) priv; + + ibm8514_accel_out(port, val, svga, 1); +} + +static void +ibm8514_accel_outw(uint16_t port, uint16_t val, void *priv) +{ + svga_t *svga = (svga_t *) priv; + + ibm8514_accel_out(port, val, svga, 2); +} + +static uint32_t +ibm8514_accel_in(uint16_t port, svga_t *svga, int len) +{ + ibm8514_t *dev = (ibm8514_t *) svga->dev8514; + uint32_t temp = 0; + int cmd; + int vpos = 0; + int vblankend = svga->vblankstart + svga->crtc[0x16]; + + switch (port) { + case 0x2e8: + vpos = dev->vc & 0x7ff; + if (vblankend > dev->v_total) { + vblankend -= dev->v_total; + 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: + vpos = dev->vc & 0x7ff; + if (vblankend > dev->v_total) { + vblankend -= dev->v_total; + 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 0x42e9: + if (len == 1) + temp |= 0x80; + break; + + case 0x92e8: + if (len != 1) { + temp = dev->test; + } + 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*/ + dev->data_available = 0; + } + } + 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*/ + dev->data_available2 = 0; + } + } + break; + + case 0xe2e8: + case 0xe6e8: + if (ibm8514_cpu_dest(svga)) { + if (len == 1) { + ; // READ_PIXTRANS_BYTE_IO(0) + } else { + cmd = (dev->accel.cmd >> 13); + READ_PIXTRANS_WORD(dev->accel.cx, 0) + if (dev->accel.input && !dev->accel.odd_in && !dev->accel.sx) { + temp &= ~0xff00; + temp |= (dev->vram[(dev->accel.newdest_in + dev->accel.cur_x) & dev->vram_mask] << 8); + } + } + ibm8514_accel_out_pixtrans(svga, port, temp, len); + } + break; + case 0xe2e9: + case 0xe6e9: + if (ibm8514_cpu_dest(svga)) { + if (len == 1) { + ; // READ_PIXTRANS_BYTE_IO(1) + ibm8514_accel_out_pixtrans(svga, port, temp, len); + } + } + break; + + default: + break; + } + return temp; +} + +static uint8_t +ibm8514_accel_inb(uint16_t port, void *priv) +{ + svga_t *svga = (svga_t *) priv; + + return ibm8514_accel_in(port, svga, 1); +} + +static uint16_t +ibm8514_accel_inw(uint16_t port, void *priv) +{ + svga_t *svga = (svga_t *) priv; + + return ibm8514_accel_in(port, svga, 2); +} + +void +ibm8514_short_stroke_start(int count, int cpu_input, uint32_t mix_dat, uint32_t cpu_dat, svga_t *svga, uint8_t ssv, int len) +{ + ibm8514_t *dev = (ibm8514_t *) svga->dev8514; + + if (!cpu_input) { + dev->accel.ssv_len = ssv & 0x0f; + dev->accel.ssv_dir = ssv & 0xe0; + dev->accel.ssv_draw = ssv & 0x10; + + if (ibm8514_cpu_src(svga)) { + return; /*Wait for data from CPU*/ + } + } + + ibm8514_accel_start(count, cpu_input, mix_dat, cpu_dat, svga, len); +} + +void +ibm8514_accel_start(int count, int cpu_input, uint32_t mix_dat, uint32_t cpu_dat, svga_t *svga, UNUSED(int len)) +{ + ibm8514_t *dev = (ibm8514_t *) svga->dev8514; + uint16_t *vram_w = (uint16_t *) dev->vram; + uint16_t src_dat = 0; + uint16_t dest_dat; + uint16_t old_dest_dat; + int frgd_mix; + int 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; + uint16_t mix_mask = dev->bpp ? 0x8000 : 0x80; + uint16_t compare = dev->accel.color_cmp; + int compare_mode = dev->accel.multifunc[0x0a] & 0x38; + int cmd = dev->accel.cmd >> 13; + 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; + uint16_t poly_src = 0; + + if (!dev->bpp) { + 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; + dev->force_busy2 = 1; + } + + frgd_mix = (dev->accel.frgd_mix >> 5) & 3; + bkgd_mix = (dev->accel.bkgd_mix >> 5) & 3; + + if (cpu_input) { + if ((dev->accel.cmd & 2) || (pixcntl == 2)) { + if ((frgd_mix == 2) || (bkgd_mix == 2)) { + count >>= 3; + } else if (pixcntl == 2) { + if (dev->accel.cmd & 2) { + count >>= 1; + } else + count >>= 3; + } + } else { + count >>= 3; + } + + if (dev->bpp) { + if ((dev->accel.cmd & 0x200) && (count == 2)) + count >>= 1; + } + } + + if (pixcntl == 1) { + mix_dat = 0; + if (and3 == 3) { + if (dev->accel.multifunc[8] & 0x02) + mix_dat |= 0x08; + if (dev->accel.multifunc[8] & 0x04) + mix_dat |= 0x10; + if (dev->accel.multifunc[8] & 0x08) + mix_dat |= 0x20; + if (dev->accel.multifunc[8] & 0x10) + mix_dat |= 0x40; + if (dev->accel.multifunc[9] & 0x02) + mix_dat |= 0x80; + if (dev->accel.multifunc[9] & 0x04) + mix_dat |= 0x01; + if (dev->accel.multifunc[9] & 0x08) + mix_dat |= 0x02; + if (dev->accel.multifunc[9] & 0x10) + mix_dat |= 0x04; + } + if (and3 == 2) { + if (dev->accel.multifunc[8] & 0x02) + mix_dat |= 0x04; + if (dev->accel.multifunc[8] & 0x04) + mix_dat |= 0x08; + if (dev->accel.multifunc[8] & 0x08) + mix_dat |= 0x10; + if (dev->accel.multifunc[8] & 0x10) + mix_dat |= 0x20; + if (dev->accel.multifunc[9] & 0x02) + mix_dat |= 0x40; + if (dev->accel.multifunc[9] & 0x04) + mix_dat |= 0x80; + if (dev->accel.multifunc[9] & 0x08) + mix_dat |= 0x01; + if (dev->accel.multifunc[9] & 0x10) + mix_dat |= 0x02; + } + if (and3 == 1) { + if (dev->accel.multifunc[8] & 0x02) + mix_dat |= 0x02; + if (dev->accel.multifunc[8] & 0x04) + mix_dat |= 0x04; + if (dev->accel.multifunc[8] & 0x08) + mix_dat |= 0x08; + if (dev->accel.multifunc[8] & 0x10) + mix_dat |= 0x10; + if (dev->accel.multifunc[9] & 0x02) + mix_dat |= 0x20; + if (dev->accel.multifunc[9] & 0x04) + mix_dat |= 0x40; + if (dev->accel.multifunc[9] & 0x08) + mix_dat |= 0x80; + if (dev->accel.multifunc[9] & 0x10) + mix_dat |= 0x01; + } + if (and3 == 0) { + if (dev->accel.multifunc[8] & 0x02) + mix_dat |= 0x01; + if (dev->accel.multifunc[8] & 0x04) + mix_dat |= 0x02; + if (dev->accel.multifunc[8] & 0x08) + mix_dat |= 0x04; + if (dev->accel.multifunc[8] & 0x10) + mix_dat |= 0x08; + if (dev->accel.multifunc[9] & 0x02) + mix_dat |= 0x10; + if (dev->accel.multifunc[9] & 0x04) + mix_dat |= 0x20; + if (dev->accel.multifunc[9] & 0x08) + mix_dat |= 0x40; + if (dev->accel.multifunc[9] & 0x10) + mix_dat |= 0x80; + } + } + + old_mix_dat = mix_dat; + + /*Bit 4 of the Command register is the draw yes bit, which enables writing to memory/reading from memory when enabled. + When this bit is disabled, no writing to memory/reading from memory is allowed. (This bit is almost meaningless on + the NOP command)*/ + ibm8514_log("CMD8514: CMD=%d, full=%04x, pixcntl=%x, count=%d, frgdmix = %02x, bkgdmix = %02x, polygon=%x.\n", cmd, dev->accel.cmd, pixcntl, count, frgd_mix, bkgd_mix, dev->accel.multifunc[0x0a] & 6); + + switch (cmd) { + case 0: /*NOP (Short Stroke Vectors)*/ + if (dev->accel.ssv_state == 0) + break; + + if (dev->accel.cmd & 8) { + 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; + + default: + break; + } + 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 (dev->bpp) + cpu_dat >>= 16; + else + cpu_dat >>= 8; + + if (!dev->accel.ssv_len) + break; + + switch (dev->accel.ssv_dir & 0xe0) { + case 0x00: + dev->accel.cx++; + break; + case 0x20: + dev->accel.cx++; + dev->accel.cy--; + break; + case 0x40: + dev->accel.cy--; + break; + case 0x60: + dev->accel.cx--; + dev->accel.cy--; + break; + case 0x80: + dev->accel.cx--; + break; + case 0xa0: + dev->accel.cx--; + dev->accel.cy++; + break; + case 0xc0: + dev->accel.cy++; + break; + case 0xe0: + dev->accel.cx++; + dev->accel.cy++; + break; + + default: + break; + } + + 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; + + default: + break; + } + + 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 (dev->bpp) + 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; + + default: + 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; + + default: + break; + } + + dev->accel.ssv_len--; + } + } + dev->accel.cur_x = dev->accel.cx; + dev->accel.cur_y = dev->accel.cy; + break; + + case 1: /*Draw line*/ + if (!cpu_input) { + dev->accel.xx_count = 0; + 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; + } + + dev->accel.sy = dev->accel.maj_axis_pcnt; + + if (ibm8514_cpu_src(svga)) { + if (dev->accel.cmd & 2) { + if (dev->accel.cmd & 8) { + if (and3 == 1) { + dev->accel.sy += 4; + if (dev->accel.cmd & 0x20) + dev->accel.cx += 4; + else + dev->accel.cx -= 4; + } else if (and3 == 2) { + dev->accel.sy += 5; + if (dev->accel.cmd & 0x20) + dev->accel.cx += 5; + else + dev->accel.cx -= 5; + } else if (and3 == 3) { + dev->accel.sy += 6; + if (dev->accel.cmd & 0x20) + dev->accel.cx += 6; + else + dev->accel.cx -= 6; + } else { + dev->accel.sy += 3; + if (dev->accel.cmd & 0x20) + dev->accel.cx += 3; + else + dev->accel.cx -= 3; + } + } + } + dev->data_available = 0; + dev->data_available2 = 0; + return; /*Wait for data from CPU*/ + } else if (ibm8514_cpu_dest(svga)) { + dev->data_available = 1; + dev->data_available2 = 1; + return; + } + } + + if (dev->accel.cmd & 8) { /*Vector Line*/ + if (ibm8514_cpu_dest(svga) && cpu_input && (dev->accel.cmd & 2)) + count >>= 1; + dev->accel.xx_count++; + while (count-- && (dev->accel.sy >= 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) { + if (ibm8514_cpu_dest(svga) && (pixcntl == 0)) { + mix_dat = mix_mask; /* Mix data = forced to foreground register. */ + } else if (ibm8514_cpu_dest(svga) && (pixcntl == 3)) { + /* Mix data = current video memory value. */ + READ((dev->accel.cy * dev->pitch) + dev->accel.cx, mix_dat); + mix_dat = ((mix_dat & rd_mask) == rd_mask); + mix_dat = mix_dat ? mix_mask : 0; + } + + if (ibm8514_cpu_dest(svga)) { + READ((dev->accel.cy * dev->pitch) + dev->accel.cx, src_dat); + if (pixcntl == 3) + src_dat = ((src_dat & rd_mask) == rd_mask); + } else + 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; + + default: + break; + } + + 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.cmd & 2) && ibm8514_cpu_src(svga)) { + if (and3 == 1) { + if (dev->accel.xx_count >= 2) { + if ((dev->accel.cmd & 4) && dev->accel.sy) { + 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); + } + } + } else if (and3 == 2) { + if (dev->accel.xx_count == 2) { + if (count <= 2) { + if ((dev->accel.cmd & 4) && dev->accel.sy) { + 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); + } + } + } else if (dev->accel.xx_count >= 3) { + if ((dev->accel.cmd & 4) && dev->accel.sy) { + 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); + } + } + } else if (and3 == 3) { + if (dev->accel.xx_count == 2) { + if (count <= 1) { + if ((dev->accel.cmd & 4) && dev->accel.sy) { + 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); + } + } + } else if (dev->accel.xx_count >= 3) { + if ((dev->accel.cmd & 4) && dev->accel.sy) { + 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); + } + } + } else { + if (dev->accel.xx_count == 1) { + if (!count) { + if ((dev->accel.cmd & 4) && dev->accel.sy) { + 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); + } + } + } else if (dev->accel.xx_count >= 2) { + if ((dev->accel.cmd & 4) && dev->accel.sy) { + 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); + } + } + } + } else { + if (ibm8514_cpu_src(svga) || !cpu_input) { + if ((dev->accel.cmd & 4) && dev->accel.sy) { + 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 (dev->bpp) + cpu_dat >>= 16; + else + cpu_dat >>= 8; + + if (dev->accel.sy == 0) { + break; + } + + switch (dev->accel.cmd & 0xe0) { + case 0x00: + dev->accel.cx++; + break; + case 0x20: + dev->accel.cx++; + dev->accel.cy--; + break; + case 0x40: + dev->accel.cy--; + break; + case 0x60: + dev->accel.cx--; + dev->accel.cy--; + break; + case 0x80: + dev->accel.cx--; + break; + case 0xa0: + dev->accel.cx--; + dev->accel.cy++; + break; + case 0xc0: + dev->accel.cy++; + break; + case 0xe0: + dev->accel.cx++; + dev->accel.cy++; + break; + + default: + break; + } + + dev->accel.sy--; + } + dev->accel.cur_x = dev->accel.cx; + dev->accel.cur_y = dev->accel.cy; + } else { /*Bresenham*/ + if (pixcntl == 1) { + dev->accel.temp_cnt = 8; + while (count-- && (dev->accel.sy >= 0)) { + if (dev->accel.temp_cnt == 0) { + dev->accel.temp_cnt = 8; + mix_dat = old_mix_dat; + } + 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) { + if (ibm8514_cpu_dest(svga)) { + READ((dev->accel.cy * dev->pitch) + dev->accel.cx, src_dat); + } else + switch ((mix_dat & 1) ? 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; + + default: + break; + } + + 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 & 1, dest_dat, src_dat); + dest_dat = (dest_dat & wrt_mask) | (old_dest_dat & ~wrt_mask); + if ((dev->accel.cmd & 4) && dev->accel.sy) { + 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); + } + } + } + + dev->accel.temp_cnt--; + mix_dat >>= 1; + if (dev->bpp) + cpu_dat >>= 16; + else + cpu_dat >>= 8; + + if (dev->accel.sy == 0) { + 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; + + default: + 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; + + default: + break; + } + + dev->accel.sy--; + } + } else { + while (count-- && (dev->accel.sy >= 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) { + if (ibm8514_cpu_dest(svga) && (pixcntl == 0)) { + mix_dat = mix_mask; /* Mix data = forced to foreground register. */ + } else if (ibm8514_cpu_dest(svga) && (pixcntl == 3)) { + /* Mix data = current video memory value. */ + READ((dev->accel.cy * dev->pitch) + dev->accel.cx, mix_dat); + mix_dat = ((mix_dat & rd_mask) == rd_mask); + mix_dat = mix_dat ? mix_mask : 0; + } + + if (ibm8514_cpu_dest(svga)) { + READ((dev->accel.cy * dev->pitch) + dev->accel.cx, src_dat); + if (pixcntl == 3) + src_dat = ((src_dat & rd_mask) == rd_mask); + } else + 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; + + default: + break; + } + + 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.cmd & 4) && dev->accel.sy) { + 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 (dev->bpp) + cpu_dat >>= 16; + else + cpu_dat >>= 8; + + if (dev->accel.sy == 0) { + 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; + + default: + 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; + + default: + break; + } + + dev->accel.sy--; + } + } + dev->accel.cur_x = dev->accel.cx; + dev->accel.cur_y = dev->accel.cy; + } + break; + + case 2: /*Rectangle fill (X direction)*/ + case 3: /*Rectangle fill (Y direction)*/ + case 4: /*Rectangle fill (Y direction using nibbles)*/ + if (!cpu_input) { + dev->accel.x_count = 0; + dev->accel.xx_count = 0; + dev->accel.odd_out = 0; + dev->accel.odd_in = 0; + dev->accel.input = 0; + dev->accel.output = 0; + dev->accel.newdest_out = 0; + dev->accel.newdest_in = 0; + + dev->accel.sx = dev->accel.maj_axis_pcnt & 0x7ff; + dev->accel.sy = dev->accel.multifunc[0] & 0x7ff; + + 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; + + if ((dev->local >= 2) && dev->accel.ge_offset && (dev->accel_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) + dev->accel.cmd |= 2; + else if (cmd == 3) + dev->accel.cmd &= ~2; + + if (ibm8514_cpu_src(svga)) { + if (dev->accel.cmd & 2) { + if (!(dev->accel.cmd & 0x1000)) { + if (!(dev->accel.cmd & 8)) { + dev->accel.sx += and3; + dev->accel.nibbleset = (uint8_t *) calloc(1, (dev->accel.sx >> 3) + 1); + dev->accel.writemono = (uint8_t *) calloc(1, (dev->accel.sx >> 3) + 1); + dev->accel.sys_cnt = (dev->accel.sx >> 3) + 1; + } else { + if (and3 == 1) { + dev->accel.sx += 4; + if (dev->accel.cmd & 0x20) + dev->accel.cx += 4; + else + dev->accel.cx -= 4; + } else if (and3 == 2) { + dev->accel.sx += 5; + if (dev->accel.cmd & 0x20) + dev->accel.cx += 5; + else + dev->accel.cx -= 5; + } else if (and3 == 3) { + dev->accel.sx += 6; + if (dev->accel.cmd & 0x20) + dev->accel.cx += 6; + else + dev->accel.cx -= 6; + } else { + dev->accel.sx += 3; + if (dev->accel.cmd & 0x20) + dev->accel.cx += 3; + else + dev->accel.cx -= 3; + } + } + } + } else { + if (!(dev->accel.cmd & 0x40) && (frgd_mix == 2) && (bkgd_mix == 2) && (pixcntl == 0) && (cmd == 2)) { + if (!(dev->accel.sx & 1)) { + dev->accel.output = 1; + if ((dev->local >= 2) && dev->accel.ge_offset && (dev->accel_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; + } + } + } + dev->data_available = 0; + dev->data_available2 = 0; + return; /*Wait for data from CPU*/ + } else if (ibm8514_cpu_dest(svga)) { + if (!(dev->accel.cmd & 2) && (frgd_mix == 2) && (pixcntl == 0) && (cmd == 2)) { + if (!(dev->accel.sx & 1)) { + dev->accel.input = 1; + if ((dev->local >= 2) && dev->accel.ge_offset && (dev->accel_bpp == 24)) + dev->accel.newdest_in = (dev->accel.ge_offset << 2) + ((dev->accel.cy + 1) * dev->pitch); + else + dev->accel.newdest_in = (dev->accel.cy + 1) * dev->pitch; + } + } else if (dev->accel.cmd & 2) { + if (dev->accel.cmd & 8) { + dev->accel.sx += and3; + dev->accel.nibbleset = (uint8_t *) calloc(1, (dev->accel.sx >> 3) + 1); + dev->accel.writemono = (uint8_t *) calloc(1, (dev->accel.sx >> 3) + 1); + dev->accel.sys_cnt = (dev->accel.sx >> 3) + 1; + } + } + dev->data_available = 1; + dev->data_available2 = 1; + return; /*Wait for data from CPU*/ + } + } + + if (dev->accel.cmd & 2) { + if (cpu_input) { +rect_fill_pix: + if ((dev->accel.cmd & 8) && ibm8514_cpu_src(svga)) { + dev->accel.xx_count++; + while (count-- && (dev->accel.sy >= 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; + + default: + break; + } + + READ(dev->accel.dest + 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 (and3 == 1) { + if (dev->accel.xx_count >= 2) { + if ((dev->accel.cmd & 4) && dev->accel.sx) { + WRITE(dev->accel.dest + dev->accel.cx, dest_dat); + } else if (!(dev->accel.cmd & 4)) { + WRITE(dev->accel.dest + dev->accel.cx, dest_dat); + } + } + } else if (and3 == 2) { + if (dev->accel.xx_count == 2) { + if (count <= 2) { + if ((dev->accel.cmd & 4) && dev->accel.sx) { + WRITE(dev->accel.dest + dev->accel.cx, dest_dat); + } else if (!(dev->accel.cmd & 4)) { + WRITE(dev->accel.dest + dev->accel.cx, dest_dat); + } + } + } else if (dev->accel.xx_count >= 3) { + if ((dev->accel.cmd & 4) && dev->accel.sx) { + WRITE(dev->accel.dest + dev->accel.cx, dest_dat); + } else if (!(dev->accel.cmd & 4)) { + WRITE(dev->accel.dest + dev->accel.cx, dest_dat); + } + } + } else if (and3 == 3) { + if (dev->accel.xx_count == 2) { + if (count <= 1) { + if ((dev->accel.cmd & 4) && dev->accel.sx) { + WRITE(dev->accel.dest + dev->accel.cx, dest_dat); + } else if (!(dev->accel.cmd & 4)) { + WRITE(dev->accel.dest + dev->accel.cx, dest_dat); + } + } + } else if (dev->accel.xx_count >= 3) { + if ((dev->accel.cmd & 4) && dev->accel.sx) { + WRITE(dev->accel.dest + dev->accel.cx, dest_dat); + } else if (!(dev->accel.cmd & 4)) { + WRITE(dev->accel.dest + dev->accel.cx, dest_dat); + } + } + } else { + if (dev->accel.xx_count == 1) { + if (!count) { + if ((dev->accel.cmd & 4) && dev->accel.sx) { + WRITE(dev->accel.dest + dev->accel.cx, dest_dat); + } else if (!(dev->accel.cmd & 4)) { + WRITE(dev->accel.dest + dev->accel.cx, dest_dat); + } + } + } else if (dev->accel.xx_count >= 2) { + if ((dev->accel.cmd & 4) && dev->accel.sx) { + WRITE(dev->accel.dest + dev->accel.cx, dest_dat); + } else if (!(dev->accel.cmd & 4)) { + WRITE(dev->accel.dest + dev->accel.cx, dest_dat); + } + } + } + } + } + + mix_dat <<= 1; + mix_dat |= 1; + if (dev->bpp) + cpu_dat >>= 16; + else + cpu_dat >>= 8; + + switch (dev->accel.cmd & 0xe0) { + case 0x00: + dev->accel.cx++; + break; + case 0x20: + dev->accel.cx++; + break; + case 0x60: + dev->accel.cx--; + break; + case 0x80: + dev->accel.cx--; + break; + case 0xa0: + dev->accel.cx--; + break; + case 0xe0: + dev->accel.cx++; + break; + + default: + break; + } + + dev->accel.sx--; + if (dev->accel.sx < 0) { + dev->accel.sx = dev->accel.maj_axis_pcnt & 0x7ff; + if (and3 == 1) { + dev->accel.sx += 4; + } else if (and3 == 2) { + dev->accel.sx += 5; + } else if (and3 == 3) { + dev->accel.sx += 6; + } else { + dev->accel.sx += 3; + } + + if (dev->accel.cmd & 0x20) + dev->accel.cx -= (dev->accel.sx + 1); + else + dev->accel.cx += (dev->accel.sx + 1); + + switch (dev->accel.cmd & 0xe0) { + case 0x20: + dev->accel.cy--; + break; + case 0x40: + dev->accel.cy--; + break; + case 0x60: + dev->accel.cy--; + break; + case 0xa0: + dev->accel.cy++; + break; + case 0xc0: + dev->accel.cy++; + break; + case 0xe0: + dev->accel.cy++; + break; + + default: + break; + } + + if ((dev->local >= 2) && dev->accel.ge_offset && (dev->accel_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; + } + } + break; + } + if (count < 8) { + while (count-- && (dev->accel.sy >= 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) { + if (ibm8514_cpu_dest(svga) && (pixcntl == 0)) { + mix_dat = mix_mask; /* Mix data = forced to foreground register. */ + } else if (ibm8514_cpu_dest(svga) && (pixcntl == 3)) { + /* Mix data = current video memory value. */ + READ(dev->accel.dest + dev->accel.cx, mix_dat); + mix_dat = ((mix_dat & rd_mask) == rd_mask); + mix_dat = mix_dat ? mix_mask : 0; + } + + if (ibm8514_cpu_dest(svga)) { + READ(dev->accel.dest + dev->accel.cx, src_dat); + if (pixcntl == 3) + src_dat = ((src_dat & rd_mask) == rd_mask); + } else + 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; + + default: + break; + } + + READ(dev->accel.dest + 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); + WRITE(dev->accel.dest + dev->accel.cx, dest_dat); + } + } + + mix_dat <<= 1; + mix_dat |= 1; + if (dev->bpp) + cpu_dat >>= 16; + else + cpu_dat >>= 8; + + if (dev->accel.cmd & 0x20) + dev->accel.cx++; + else + dev->accel.cx--; + + dev->accel.sx--; + if (dev->accel.sx < 0) { + dev->accel.sx = dev->accel.maj_axis_pcnt & 0x7ff; + + if (dev->accel.cmd & 2) { + dev->accel.sx += (dev->accel.cur_x & 3); + } + + if (dev->accel.cmd & 0x20) { + dev->accel.cx -= (dev->accel.sx) + 1; + } else + dev->accel.cx += (dev->accel.sx) + 1; + + if (dev->accel.cmd & 0x80) + dev->accel.cy++; + else + dev->accel.cy--; + + if ((dev->local >= 2) && dev->accel.ge_offset && (dev->accel_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; + } + } + } else { + while (count-- && (dev->accel.sy >= 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) { + if (ibm8514_cpu_dest(svga) && (pixcntl == 0)) { + mix_dat = 1; /* Mix data = forced to foreground register. */ + } else if (ibm8514_cpu_dest(svga) && (pixcntl == 3)) { + /* Mix data = current video memory value. */ + READ(dev->accel.dest + dev->accel.cx, mix_dat); + mix_dat = ((mix_dat & rd_mask) == rd_mask); + mix_dat = mix_dat ? 1 : 0; + } + + if (ibm8514_cpu_dest(svga)) { + READ(dev->accel.dest + dev->accel.cx, src_dat); + if (pixcntl == 3) + src_dat = ((src_dat & rd_mask) == rd_mask); + } else { + switch ((mix_dat & 1) ? 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; + + default: + break; + } + } + + READ(dev->accel.dest + 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 & 1, dest_dat, src_dat); + dest_dat = (dest_dat & wrt_mask) | (old_dest_dat & ~wrt_mask); + WRITE(dev->accel.dest + dev->accel.cx, dest_dat); + } + } + mix_dat >>= 1; + if (dev->bpp) + cpu_dat >>= 16; + else + cpu_dat >>= 8; + + if (dev->accel.cmd & 0x20) + dev->accel.cx++; + else + dev->accel.cx--; + + dev->accel.sx--; + if (dev->accel.sx < 0) { + dev->accel.sx = dev->accel.maj_axis_pcnt & 0x7ff; + + if (dev->accel.cmd & 2) { + if (!(dev->accel.cmd & 0x1000)) + dev->accel.sx += (dev->accel.cur_x & 3); + } + + if (dev->accel.cmd & 0x20) { + dev->accel.cx -= (dev->accel.sx) + 1; + } else + dev->accel.cx += (dev->accel.sx) + 1; + + if (dev->accel.cmd & 2) { + if (dev->accel.cmd & 0x1000) { + dev->accel.cx = dev->accel.cur_x; + if (dev->accel.cur_x >= 0x600) + dev->accel.cx |= ~0x5ff; + } + } + + if (dev->accel.cmd & 0x80) + dev->accel.cy++; + else + dev->accel.cy--; + + if ((dev->local >= 2) && dev->accel.ge_offset && (dev->accel_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; + } + } + } + } else { + goto rect_fill; + } + } else { + if (cpu_input) { + if (pixcntl == 2) { + goto rect_fill_pix; + } else { + if (dev->accel.input && !dev->accel.output) { + while (count-- && (dev->accel.sy >= 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) { + mix_dat = mix_mask; /* Mix data = forced to foreground register. */ + if (!dev->accel.odd_in && !dev->accel.sx) { + READ(dev->accel.newdest_in + dev->accel.cur_x, src_dat); + READ(dev->accel.newdest_in + dev->accel.cur_x, dest_dat); + } else { + READ(dev->accel.dest + dev->accel.cx, src_dat); + READ(dev->accel.dest + 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.odd_in && !dev->accel.sx) { + WRITE(dev->accel.newdest_in + dev->accel.cur_x, dest_dat); + } else { + WRITE(dev->accel.dest + dev->accel.cx, dest_dat); + } + } + } + mix_dat <<= 1; + mix_dat |= 1; + + if (dev->accel.cmd & 0x20) + dev->accel.cx++; + else + dev->accel.cx--; + + dev->accel.sx--; + if (dev->accel.odd_in) { + if (dev->accel.sx < 0) { + dev->accel.sx = dev->accel.maj_axis_pcnt & 0x7ff; + dev->accel.odd_in = 0; + dev->accel.cx = dev->accel.cur_x; + if (dev->accel.cmd & 0x80) + dev->accel.cy++; + else + dev->accel.cy--; + + if ((dev->local >= 2) && dev->accel.ge_offset && (dev->accel_bpp == 24)) { + dev->accel.dest = (dev->accel.ge_offset << 2) + (dev->accel.cy * dev->pitch); + dev->accel.newdest_in = (dev->accel.ge_offset << 2) + ((dev->accel.cy + 1) * dev->pitch); + } else { + dev->accel.dest = dev->accel.cy * dev->pitch; + dev->accel.newdest_in = (dev->accel.cy + 1) * dev->pitch; + } + dev->accel.sy--; + return; + } + } else { + if (dev->accel.sx < 0) { + dev->accel.sx = dev->accel.maj_axis_pcnt & 0x7ff; + dev->accel.sx--; + dev->accel.cx = dev->accel.cur_x; + dev->accel.odd_in = 1; + if (dev->accel.cmd & 0x20) + dev->accel.cx++; + else + dev->accel.cx--; + if (dev->accel.cmd & 0x80) + dev->accel.cy++; + else + dev->accel.cy--; + + if ((dev->local >= 2) && dev->accel.ge_offset && (dev->accel_bpp == 24)) { + dev->accel.dest = (dev->accel.ge_offset << 2) + (dev->accel.cy * dev->pitch); + dev->accel.newdest_in = (dev->accel.ge_offset << 2) + ((dev->accel.cy + 1) * dev->pitch); + } else { + dev->accel.dest = dev->accel.cy * dev->pitch; + dev->accel.newdest_in = (dev->accel.cy + 1) * dev->pitch; + } + dev->accel.sy--; + return; + } + } + } + } else if (dev->accel.output && !dev->accel.input) { + while (count-- && (dev->accel.sy >= 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) { + src_dat = cpu_dat; + if (!dev->accel.odd_out && !dev->accel.sx) { + READ(dev->accel.newdest_out + dev->accel.cur_x, dest_dat); + } else { + READ(dev->accel.dest + 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.odd_out && !dev->accel.sx) { + WRITE(dev->accel.newdest_out + dev->accel.cur_x, dest_dat); + } else { + WRITE(dev->accel.dest + dev->accel.cx, dest_dat); + } + } + } + mix_dat <<= 1; + mix_dat |= 1; + if (dev->bpp) + cpu_dat >>= 16; + else + cpu_dat >>= 8; + + if (dev->accel.cmd & 0x20) + dev->accel.cx++; + else + dev->accel.cx--; + + dev->accel.sx--; + if (dev->accel.odd_out) { + if (dev->accel.sx < 0) { + dev->accel.sx = dev->accel.maj_axis_pcnt & 0x7ff; + dev->accel.odd_out = 0; + dev->accel.cx = dev->accel.cur_x; + if (dev->accel.cmd & 0x80) + dev->accel.cy++; + else + dev->accel.cy--; + + if ((dev->local >= 2) && dev->accel.ge_offset && (dev->accel_bpp == 24)) { + dev->accel.dest = (dev->accel.ge_offset << 2) + (dev->accel.cy * dev->pitch); + dev->accel.newdest_out = (dev->accel.ge_offset << 2) + ((dev->accel.cy + 1) * dev->pitch); + } else { + dev->accel.dest = dev->accel.cy * dev->pitch; + dev->accel.newdest_out = (dev->accel.cy + 1) * dev->pitch; + } + dev->accel.sy--; + return; + } + } else { + if (dev->accel.sx < 0) { + dev->accel.sx = dev->accel.maj_axis_pcnt & 0x7ff; + dev->accel.odd_out = 1; + dev->accel.sx--; + dev->accel.cx = dev->accel.cur_x; + if (dev->accel.cmd & 0x20) + dev->accel.cx++; + else + dev->accel.cx--; + if (dev->accel.cmd & 0x80) + dev->accel.cy++; + else + dev->accel.cy--; + + if ((dev->local >= 2) && dev->accel.ge_offset && (dev->accel_bpp == 24)) { + dev->accel.dest = (dev->accel.ge_offset << 2) + (dev->accel.cy * dev->pitch); + dev->accel.newdest_out = (dev->accel.ge_offset << 2) + ((dev->accel.cy + 1) * dev->pitch); + } else { + dev->accel.dest = dev->accel.cy * dev->pitch; + dev->accel.newdest_out = (dev->accel.cy + 1) * dev->pitch; + } + dev->accel.sy--; + return; + } + } + } + } else { + while (count-- && (dev->accel.sy >= 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) { + if (ibm8514_cpu_dest(svga) && (pixcntl == 0)) { + mix_dat = mix_mask; /* Mix data = forced to foreground register. */ + } else if (ibm8514_cpu_dest(svga) && (pixcntl == 3)) { + /* Mix data = current video memory value. */ + READ(dev->accel.dest + dev->accel.cx, mix_dat); + mix_dat = ((mix_dat & rd_mask) == rd_mask); + mix_dat = mix_dat ? mix_mask : 0; + } + + if (ibm8514_cpu_dest(svga)) { + READ(dev->accel.dest + dev->accel.cx, src_dat); + if (pixcntl == 3) { + src_dat = ((src_dat & rd_mask) == rd_mask); + } + } else + 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; + + default: + break; + } + + READ(dev->accel.dest + 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; + if (ibm8514_cpu_dest(svga)) { + if (pixcntl == 3) { + MIX(mix_dat & mix_mask, dest_dat, src_dat); + } + } else { + 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.cx, dest_dat); + } + } + + mix_dat <<= 1; + mix_dat |= 1; + if (dev->bpp) + cpu_dat >>= 16; + else + cpu_dat >>= 8; + + if (dev->accel.cmd & 0x20) + dev->accel.cx++; + else + dev->accel.cx--; + + dev->accel.sx--; + if (dev->accel.sx < 0) { + dev->accel.sx = dev->accel.maj_axis_pcnt & 0x7ff; + + if (dev->accel.cmd & 0x20) { + dev->accel.cx -= (dev->accel.sx) + 1; + } else + dev->accel.cx += (dev->accel.sx) + 1; + + if (dev->accel.cmd & 0x80) + dev->accel.cy++; + else + dev->accel.cy--; + + if ((dev->local >= 2) && dev->accel.ge_offset && (dev->accel_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; + } + } + } + } + } else { +rect_fill: + if (pixcntl == 1) { + if (dev->accel.cmd & 0x40) { + count = dev->accel.maj_axis_pcnt + 1; + dev->accel.temp_cnt = 8; + while (count-- && dev->accel.sy >= 0) { + if (dev->accel.temp_cnt == 0) { + mix_dat >>= 8; + dev->accel.temp_cnt = 8; + } + 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 = 0; + break; + case 3: + src_dat = 0; + break; + + default: + break; + } + + READ(dev->accel.dest + 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); + + WRITE(dev->accel.dest + dev->accel.cx, dest_dat); + } + } + + if (dev->accel.temp_cnt > 0) { + dev->accel.temp_cnt--; + mix_dat <<= 1; + mix_dat |= 1; + } + + if (dev->accel.cmd & 0x20) + dev->accel.cx++; + else + dev->accel.cx--; + + dev->accel.sx--; + if (dev->accel.sx < 0) { + dev->accel.sx = dev->accel.maj_axis_pcnt & 0x7ff; + + if (dev->accel.cmd & 0x20) { + dev->accel.cx -= (dev->accel.sx) + 1; + } else + dev->accel.cx += (dev->accel.sx) + 1; + + if (dev->accel.cmd & 0x80) + dev->accel.cy++; + else + dev->accel.cy--; + + if ((dev->local >= 2) && dev->accel.ge_offset && (dev->accel_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--; + + dev->accel.cur_x = dev->accel.cx; + dev->accel.cur_y = dev->accel.cy; + return; + } + } + } else { + dev->accel.temp_cnt = 8; + while (count-- && dev->accel.sy >= 0) { + if (dev->accel.temp_cnt == 0) { + dev->accel.temp_cnt = 8; + mix_dat = old_mix_dat; + } + 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 & 1) ? frgd_mix : bkgd_mix) { + case 0: + src_dat = bkgd_color; + break; + case 1: + src_dat = frgd_color; + break; + case 2: + src_dat = 0; + break; + case 3: + src_dat = 0; + break; + + default: + break; + } + + READ(dev->accel.dest + 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 & 1, dest_dat, src_dat); + dest_dat = (dest_dat & wrt_mask) | (old_dest_dat & ~wrt_mask); + + WRITE(dev->accel.dest + dev->accel.cx, dest_dat); + } + } + + dev->accel.temp_cnt--; + mix_dat >>= 1; + + if (dev->accel.cmd & 0x20) + dev->accel.cx++; + else + dev->accel.cx--; + + dev->accel.sx--; + if (dev->accel.sx < 0) { + dev->accel.sx = dev->accel.maj_axis_pcnt & 0x7ff; + + if (dev->accel.cmd & 0x20) { + dev->accel.cx -= (dev->accel.sx) + 1; + } else + dev->accel.cx += (dev->accel.sx) + 1; + + if (dev->accel.cmd & 0x80) + dev->accel.cy++; + else + dev->accel.cy--; + + if ((dev->local >= 2) && dev->accel.ge_offset && (dev->accel_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--; + + if (dev->accel.sy < 0) { + dev->accel.cur_x = dev->accel.cx; + dev->accel.cur_y = dev->accel.cy; + return; + } + } + } + } + } else { + if (dev->accel.multifunc[0x0a] & 6) { + while (count-- && dev->accel.sy >= 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 = 0; + break; + case 3: + src_dat = 0; + break; + + default: + break; + } + + READ(dev->accel.dest + dev->accel.cx, poly_src); + if (dev->accel.multifunc[0x0a] & 2) { + poly_src = ((poly_src & wrt_mask) == wrt_mask); + } else { + poly_src = ((poly_src & rd_mask_polygon) == rd_mask_polygon); + } + + if (poly_src) { + dev->accel.fill_state ^= 1; + } + + if (dev->accel.fill_state) { + READ(dev->accel.dest + 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); + WRITE(dev->accel.dest + dev->accel.cx, dest_dat); + } + } + } + + mix_dat <<= 1; + mix_dat |= 1; + + if (dev->accel.cmd & 0x20) { + dev->accel.cx++; + } else { + dev->accel.cx--; + } + + dev->accel.sx--; + if (dev->accel.sx < 0) { + dev->accel.sx = dev->accel.maj_axis_pcnt & 0x7ff; + dev->accel.fill_state = 0; + + if (dev->accel.cmd & 0x20) { + dev->accel.cx -= (dev->accel.sx) + 1; + } else { + dev->accel.cx += (dev->accel.sx) + 1; + } + + if (dev->accel.cmd & 0x80) + dev->accel.cy++; + else + dev->accel.cy--; + + if ((dev->local >= 2) && dev->accel.ge_offset && (dev->accel_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--; + + if (dev->accel.sy < 0) { + dev->accel.cur_x = dev->accel.cx; + dev->accel.cur_y = dev->accel.cy; + return; + } + } + } + } else { + while (count-- && dev->accel.sy >= 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 = 0; + break; + case 3: + src_dat = 0; + break; + + default: + break; + } + + READ(dev->accel.dest + 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); + WRITE(dev->accel.dest + dev->accel.cx, dest_dat); + } + } + + mix_dat <<= 1; + mix_dat |= 1; + + if (dev->accel.cmd & 0x20) + dev->accel.cx++; + else + dev->accel.cx--; + + dev->accel.sx--; + if (dev->accel.sx < 0) { + dev->accel.sx = dev->accel.maj_axis_pcnt & 0x7ff; + + if (dev->accel.cmd & 0x20) { + dev->accel.cx -= (dev->accel.sx) + 1; + } else + dev->accel.cx += (dev->accel.sx) + 1; + + if (dev->accel.cmd & 0x80) + dev->accel.cy++; + else + dev->accel.cy--; + + if ((dev->local >= 2) && dev->accel.ge_offset && (dev->accel_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--; + + if (dev->accel.sy < 0) { + dev->accel.cur_x = dev->accel.cx; + dev->accel.cur_y = dev->accel.cy; + return; + } + } + } + } + } + } + } + break; + + case 5: /*Draw Polygon Boundary Line*/ + if (!cpu_input) { + 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; + dev->accel.oldcy = dev->accel.cy; + dev->accel.sy = 0; + + if (ibm8514_cpu_src(svga)) { + dev->data_available = 0; + dev->data_available2 = 0; + return; /*Wait for data from CPU*/ + } else if (ibm8514_cpu_dest(svga)) { + dev->data_available = 1; + dev->data_available2 = 1; + return; + } + } + + while (count-- && (dev->accel.sy >= 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; + + default: + break; + } + + 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.cmd & 4) { + if (dev->accel.sy < dev->accel.maj_axis_pcnt) { + if (dev->accel.cmd & 0x40) { + WRITE((dev->accel.cy * dev->pitch) + (dev->accel.cx), dest_dat); + } else { + if (dev->accel.cy == (dev->accel.oldcy + 1)) { + if (dev->accel.cmd & 0x20) { + if (dev->accel.err_term < (dev->accel.destx_distp + dev->accel.desty_axstp)) { + WRITE((dev->accel.cy * dev->pitch) + (dev->accel.cx), dest_dat); + } + } else { + if (dev->accel.err_term >= 0) { + WRITE((dev->accel.cy * dev->pitch) + (dev->accel.cx), dest_dat); + } + } + } + } + } + } else { + if (dev->accel.cmd & 0x40) { + WRITE((dev->accel.cy * dev->pitch) + (dev->accel.cx), dest_dat); + } else { + if (dev->accel.cy == (dev->accel.oldcy + 1)) { + if (dev->accel.cmd & 0x20) { + if (dev->accel.err_term < (dev->accel.destx_distp + dev->accel.desty_axstp)) { + WRITE((dev->accel.cy * dev->pitch) + (dev->accel.cx), dest_dat); + } + } else { + if (dev->accel.err_term >= 0) { + WRITE((dev->accel.cy * dev->pitch) + (dev->accel.cx), dest_dat); + } + } + } + } + } + } + } + + mix_dat <<= 1; + mix_dat |= 1; + if (dev->bpp) + cpu_dat >>= 16; + else + cpu_dat >>= 8; + + if (dev->accel.sy == dev->accel.maj_axis_pcnt) { + break; + } + + /*Step major axis*/ + switch (dev->accel.cmd & 0xe0) { + case 0x00: + dev->accel.cx--; + break; + case 0x20: + dev->accel.cx++; + break; + case 0x40: + dev->accel.oldcy = dev->accel.cy; + dev->accel.cy--; + break; + case 0x60: + dev->accel.oldcy = dev->accel.cy; + dev->accel.cy--; + break; + case 0x80: + dev->accel.cx--; + break; + case 0xa0: + dev->accel.cx++; + break; + case 0xc0: + dev->accel.oldcy = dev->accel.cy; + dev->accel.cy++; + break; + case 0xe0: + dev->accel.oldcy = dev->accel.cy; + dev->accel.cy++; + break; + + default: + break; + } + + if (dev->accel.err_term >= 0) { + dev->accel.err_term += dev->accel.destx_distp; + /*Step minor axis*/ + switch (dev->accel.cmd & 0xe0) { + case 0x00: + dev->accel.oldcy = dev->accel.cy; + dev->accel.cy--; + break; + case 0x20: + dev->accel.oldcy = dev->accel.cy; + dev->accel.cy--; + break; + case 0x40: + dev->accel.cx--; + break; + case 0x60: + dev->accel.cx++; + break; + case 0x80: + dev->accel.oldcy = dev->accel.cy; + dev->accel.cy++; + break; + case 0xa0: + dev->accel.oldcy = dev->accel.cy; + dev->accel.cy++; + break; + case 0xc0: + dev->accel.cx--; + break; + case 0xe0: + dev->accel.cx++; + break; + + default: + break; + } + } else + dev->accel.err_term += dev->accel.desty_axstp; + + dev->accel.sy++; + } + break; + + case 6: /*BitBlt*/ + if (!cpu_input) /*!cpu_input is trigger to start operation*/ + { + dev->accel.x_count = 0; + dev->accel.output = 0; + + dev->accel.sx = dev->accel.maj_axis_pcnt & 0x7ff; + dev->accel.sy = dev->accel.multifunc[0] & 0x7ff; + + dev->accel.dx = dev->accel.destx_distp; + dev->accel.dy = dev->accel.desty_axstp; + + 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; + 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; + + dev->accel.src = dev->accel.cy * dev->pitch; + dev->accel.dest = dev->accel.dy * dev->pitch; + + if (ibm8514_cpu_src(svga)) { + if (dev->accel.cmd & 2) { + if (!(dev->accel.cmd & 0x1000)) { + dev->accel.sx += (dev->accel.cur_x & 3); + dev->accel.nibbleset = (uint8_t *) calloc(1, (dev->accel.sx >> 3) + 1); + dev->accel.writemono = (uint8_t *) calloc(1, (dev->accel.sx >> 3) + 1); + dev->accel.sys_cnt = (dev->accel.sx >> 3) + 1; + } + } + dev->data_available = 0; + dev->data_available2 = 0; + return; /*Wait for data from CPU*/ + } else if (ibm8514_cpu_dest(svga)) { + dev->data_available = 1; + dev->data_available2 = 1; + return; /*Wait for data from CPU*/ + } + } + + if (dev->accel.cmd & 2) { + if (cpu_input) { +bitblt_pix: + if (count < 8) { + 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) { + if (!(dev->accel.cmd & 0x10) && ((frgd_mix != 3) || (bkgd_mix != 3))) { + READ(dev->accel.src + dev->accel.cx, mix_dat); + mix_dat = ((mix_dat & rd_mask) == rd_mask); + mix_dat = mix_dat ? mix_mask : 0; + } else if (dev->accel.cmd & 0x10) { + READ(dev->accel.src + dev->accel.cx, mix_dat); + mix_dat = ((mix_dat & rd_mask) == rd_mask); + mix_dat = mix_dat ? mix_mask : 0; + } + } + 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: + READ(dev->accel.src + dev->accel.cx, src_dat); + if (pixcntl == 3) { + if (dev->accel.cmd & 0x10) { + src_dat = ((src_dat & rd_mask) == rd_mask); + } + } + break; + + default: + break; + } + + READ(dev->accel.dest + dev->accel.dx, 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); + WRITE(dev->accel.dest + dev->accel.dx, dest_dat); + } + } + + mix_dat <<= 1; + mix_dat |= 1; + if (dev->bpp) + 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) { + dev->accel.sx = dev->accel.maj_axis_pcnt & 0x7ff; + + if (dev->accel.cmd & 2) { + dev->accel.sx += (dev->accel.cur_x & 3); + } + + if (dev->accel.cmd & 0x20) { + dev->accel.dx -= (dev->accel.sx) + 1; + dev->accel.cx -= (dev->accel.sx) + 1; + } else { + dev->accel.dx += (dev->accel.sx) + 1; + dev->accel.cx += (dev->accel.sx) + 1; + } + + if (dev->accel.cmd & 0x80) { + dev->accel.dy++; + dev->accel.cy++; + } else { + dev->accel.dy--; + dev->accel.cy--; + } + + dev->accel.src = dev->accel.cy * dev->pitch; + dev->accel.dest = dev->accel.dy * dev->pitch; + dev->accel.sy--; + return; + } + } + } else { + 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) { + if (!(dev->accel.cmd & 0x10) && ((frgd_mix != 3) || (bkgd_mix != 3))) { + READ(dev->accel.src + dev->accel.cx, mix_dat); + mix_dat = ((mix_dat & rd_mask) == rd_mask); + mix_dat = mix_dat ? 1 : 0; + } else if (dev->accel.cmd & 0x10) { + READ(dev->accel.src + dev->accel.cx, mix_dat); + mix_dat = ((mix_dat & rd_mask) == rd_mask); + mix_dat = mix_dat ? 1 : 0; + } + } + switch ((mix_dat & 1) ? 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: + READ(dev->accel.src + dev->accel.cx, src_dat); + if (pixcntl == 3) { + if (dev->accel.cmd & 0x10) { + src_dat = ((src_dat & rd_mask) == rd_mask); + } + } + break; + + default: + break; + } + + READ(dev->accel.dest + dev->accel.dx, 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 & 1, dest_dat, src_dat); + dest_dat = (dest_dat & wrt_mask) | (old_dest_dat & ~wrt_mask); + WRITE(dev->accel.dest + dev->accel.dx, dest_dat); + } + } + mix_dat >>= 1; + if (dev->bpp) + 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) { + dev->accel.sx = dev->accel.maj_axis_pcnt & 0x7ff; + + if (dev->accel.cmd & 2) { + if (!(dev->accel.cmd & 0x1000)) + dev->accel.sx += (dev->accel.cur_x & 3); + } + + if (dev->accel.cmd & 0x20) { + dev->accel.dx -= (dev->accel.sx) + 1; + dev->accel.cx -= (dev->accel.sx) + 1; + } else { + dev->accel.dx += (dev->accel.sx) + 1; + dev->accel.cx += (dev->accel.sx) + 1; + } + + if (dev->accel.cmd & 2) { + if (dev->accel.cmd & 0x1000) { + 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; + } + } + + if (dev->accel.cmd & 0x80) { + dev->accel.dy++; + dev->accel.cy++; + } else { + dev->accel.dy--; + dev->accel.cy--; + } + + dev->accel.dest = dev->accel.dy * dev->pitch; + dev->accel.src = dev->accel.cy * dev->pitch; + dev->accel.sy--; + return; + } + } + } + } else { + goto bitblt; + } + } else { + if (cpu_input) { + if (pixcntl == 2) { + goto bitblt_pix; + } else { + 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) { + if (!(dev->accel.cmd & 0x10) && ((frgd_mix != 3) || (bkgd_mix != 3))) { + READ(dev->accel.src + dev->accel.cx, mix_dat); + mix_dat = ((mix_dat & rd_mask) == rd_mask); + mix_dat = mix_dat ? mix_mask : 0; + } else if (dev->accel.cmd & 0x10) { + READ(dev->accel.src + dev->accel.cx, mix_dat); + mix_dat = ((mix_dat & rd_mask) == rd_mask); + mix_dat = mix_dat ? mix_mask : 0; + } + } + 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: + READ(dev->accel.src + dev->accel.cx, src_dat); + if (pixcntl == 3) { + if (dev->accel.cmd & 0x10) { + src_dat = ((src_dat & rd_mask) == rd_mask); + } + } + break; + + default: + break; + } + + READ(dev->accel.dest + dev->accel.dx, 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); + WRITE(dev->accel.dest + dev->accel.dx, dest_dat); + } + } + mix_dat <<= 1; + mix_dat |= 1; + if (dev->bpp) + 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) { + dev->accel.sx = dev->accel.maj_axis_pcnt & 0x7ff; + + if (dev->accel.cmd & 0x20) { + dev->accel.dx -= (dev->accel.sx) + 1; + dev->accel.cx -= (dev->accel.sx) + 1; + } else { + dev->accel.dx += (dev->accel.sx) + 1; + dev->accel.cx += (dev->accel.sx) + 1; + } + + if (dev->accel.cmd & 0x80) { + dev->accel.dy++; + dev->accel.cy++; + } else { + dev->accel.dy--; + dev->accel.cy--; + } + + dev->accel.dest = dev->accel.dy * dev->pitch; + dev->accel.src = dev->accel.cy * dev->pitch; + dev->accel.sy--; + return; + } + } + } + } else { +bitblt: + if (pixcntl == 1) { + if (dev->accel.cmd & 0x40) { + count = dev->accel.maj_axis_pcnt + 1; + dev->accel.temp_cnt = 8; + while (count-- && dev->accel.sy >= 0) { + if (!dev->accel.temp_cnt) { + mix_dat >>= 8; + dev->accel.temp_cnt = 8; + } + 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) { + 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 = 0; + break; + case 3: + READ(dev->accel.src + dev->accel.cx, src_dat); + break; + + default: + break; + } + + READ(dev->accel.dest + dev->accel.dx, 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); + + WRITE(dev->accel.dest + dev->accel.dx, dest_dat); + } + } + + if (dev->accel.temp_cnt > 0) { + dev->accel.temp_cnt--; + mix_dat <<= 1; + mix_dat |= 1; + } + + 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) { + dev->accel.sx = dev->accel.maj_axis_pcnt & 0x7ff; + + if (dev->accel.cmd & 0x20) { + dev->accel.dx -= (dev->accel.sx) + 1; + dev->accel.cx -= (dev->accel.sx) + 1; + } else { + dev->accel.dx += (dev->accel.sx) + 1; + dev->accel.cx += (dev->accel.sx) + 1; + } + + if (dev->accel.cmd & 0x80) { + dev->accel.dy++; + dev->accel.cy++; + } else { + dev->accel.dy--; + dev->accel.cy--; + } + + dev->accel.dest = dev->accel.dy * dev->pitch; + dev->accel.src = dev->accel.cy * dev->pitch; + dev->accel.sy--; + return; + } + } + } else { + dev->accel.temp_cnt = 8; + while (count-- && dev->accel.sy >= 0) { + if (!dev->accel.temp_cnt) { + dev->accel.temp_cnt = 8; + mix_dat = old_mix_dat; + } + 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) { + switch ((mix_dat & 1) ? frgd_mix : bkgd_mix) { + case 0: + src_dat = bkgd_color; + break; + case 1: + src_dat = frgd_color; + break; + case 2: + src_dat = 0; + break; + case 3: + READ(dev->accel.src + dev->accel.cx, src_dat); + break; + + default: + break; + } + + READ(dev->accel.dest + dev->accel.dx, 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 & 1, dest_dat, src_dat); + dest_dat = (dest_dat & wrt_mask) | (old_dest_dat & ~wrt_mask); + + WRITE(dev->accel.dest + dev->accel.dx, dest_dat); + } + } + dev->accel.temp_cnt--; + mix_dat >>= 1; + + 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) { + dev->accel.sx = dev->accel.maj_axis_pcnt & 0x7ff; + + if (dev->accel.cmd & 0x20) { + dev->accel.dx -= (dev->accel.sx) + 1; + dev->accel.cx -= (dev->accel.sx) + 1; + } else { + dev->accel.dx += (dev->accel.sx) + 1; + dev->accel.cx += (dev->accel.sx) + 1; + } + + if (dev->accel.cmd & 0x80) { + dev->accel.dy++; + dev->accel.cy++; + } else { + dev->accel.dy--; + dev->accel.cy--; + } + + dev->accel.dest = dev->accel.dy * dev->pitch; + dev->accel.src = dev->accel.cy * dev->pitch; + dev->accel.sy--; + + if (dev->accel.sy < 0) { + return; + } + } + } + } + } else { + if ((dev->accel_bpp == 24) && (dev->local >= 2) && (dev->accel.cmd == 0xc2b5)) { + int64_t cx; + int64_t 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) { + if (!(dev->accel.cmd & 0x10) && ((frgd_mix != 3) || (bkgd_mix != 3))) { + READ(dev->accel.src + dev->accel.cx, mix_dat); + mix_dat = ((mix_dat & rd_mask) == rd_mask); + mix_dat = mix_dat ? mix_mask : 0; + } else if (dev->accel.cmd & 0x10) { + READ(dev->accel.src + dev->accel.cx, mix_dat); + mix_dat = ((mix_dat & rd_mask) == rd_mask); + mix_dat = mix_dat ? mix_mask : 0; + } + } + 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 = 0; + break; + case 3: + READ(dev->accel.src + dev->accel.cx, src_dat); + if (pixcntl == 3) { + if (dev->accel.cmd & 0x10) { + src_dat = ((src_dat & rd_mask) == rd_mask); + } + } + break; + + default: + break; + } + + READ(dev->accel.dest + dev->accel.dx, 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.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; + mix_dat |= 1; + + 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) { + dev->accel.sx = dev->accel.maj_axis_pcnt & 0x7ff; + + if (dev->accel.cmd & 0x20) { + dev->accel.dx -= (dev->accel.sx) + 1; + dev->accel.cx -= (dev->accel.sx) + 1; + } else { + dev->accel.dx += (dev->accel.sx) + 1; + dev->accel.cx += (dev->accel.sx) + 1; + } + + if (dev->accel.cmd & 0x80) { + dev->accel.dy++; + dev->accel.cy++; + } else { + dev->accel.dy--; + dev->accel.cy--; + } + + dev->accel.dest = dev->accel.dy * dev->pitch; + dev->accel.src = dev->accel.cy * dev->pitch; + dev->accel.sy--; + + if (dev->accel.sy < 0) { + return; + } + } + } + } + } + } + break; + + default: + break; + } +} + +void +ibm8514_render_8bpp(svga_t *svga) +{ + ibm8514_t *dev = (ibm8514_t *) svga->dev8514; + uint32_t *p; + uint32_t dat; + + if ((dev->displine + svga->y_add) < 0) { + return; + } + + if (dev->changedvram[dev->ma >> 12] || dev->changedvram[(dev->ma >> 12) + 1] || svga->fullchange) { + p = &buffer32->line[dev->displine + svga->y_add][svga->x_add]; + + if (dev->firstline_draw == 2000) + dev->firstline_draw = dev->displine; + dev->lastline_draw = dev->displine; + + for (int x = 0; x <= dev->h_disp; x += 8) { + dat = *(uint32_t *) (&dev->vram[dev->ma & dev->vram_mask]); + p[0] = dev->pallook[dat & 0xff]; + p[1] = dev->pallook[(dat >> 8) & 0xff]; + p[2] = dev->pallook[(dat >> 16) & 0xff]; + p[3] = dev->pallook[(dat >> 24) & 0xff]; + + dat = *(uint32_t *) (&dev->vram[(dev->ma + 4) & dev->vram_mask]); + p[4] = dev->pallook[dat & 0xff]; + p[5] = dev->pallook[(dat >> 8) & 0xff]; + p[6] = dev->pallook[(dat >> 16) & 0xff]; + p[7] = dev->pallook[(dat >> 24) & 0xff]; + + dev->ma += 8; + p += 8; + } + dev->ma &= dev->vram_mask; + } +} + +void +ibm8514_render_15bpp(svga_t *svga) +{ + ibm8514_t *dev = (ibm8514_t *) svga->dev8514; + int x; + uint32_t *p; + uint32_t dat; + + if ((dev->displine + svga->y_add) < 0) { + return; + } + + if (dev->changedvram[dev->ma >> 12] || dev->changedvram[(dev->ma >> 12) + 1] || svga->fullchange) { + p = &buffer32->line[dev->displine + svga->y_add][svga->x_add]; + + if (dev->firstline_draw == 2000) + dev->firstline_draw = dev->displine; + dev->lastline_draw = dev->displine; + + for (x = 0; x <= dev->h_disp; x += 8) { + dat = *(uint32_t *) (&dev->vram[(dev->ma + (x << 1)) & dev->vram_mask]); + p[x] = video_15to32[dat & 0xffff]; + p[x + 1] = video_15to32[dat >> 16]; + + dat = *(uint32_t *) (&dev->vram[(dev->ma + (x << 1) + 4) & dev->vram_mask]); + p[x + 2] = video_15to32[dat & 0xffff]; + p[x + 3] = video_15to32[dat >> 16]; + + dat = *(uint32_t *) (&dev->vram[(dev->ma + (x << 1) + 8) & dev->vram_mask]); + p[x + 4] = video_15to32[dat & 0xffff]; + p[x + 5] = video_15to32[dat >> 16]; + + dat = *(uint32_t *) (&dev->vram[(dev->ma + (x << 1) + 12) & dev->vram_mask]); + p[x + 6] = video_15to32[dat & 0xffff]; + p[x + 7] = video_15to32[dat >> 16]; + } + dev->ma += (x << 1); + dev->ma &= dev->vram_mask; + } +} + +void +ibm8514_render_16bpp(svga_t *svga) +{ + ibm8514_t *dev = (ibm8514_t *) svga->dev8514; + int x; + uint32_t *p; + uint32_t dat; + + if ((dev->displine + svga->y_add) < 0) { + return; + } + + if (dev->changedvram[dev->ma >> 12] || dev->changedvram[(dev->ma >> 12) + 1] || svga->fullchange) { + p = &buffer32->line[dev->displine + svga->y_add][svga->x_add]; + + if (dev->firstline_draw == 2000) + dev->firstline_draw = dev->displine; + dev->lastline_draw = dev->displine; + + for (x = 0; x <= dev->h_disp; x += 8) { + dat = *(uint32_t *) (&dev->vram[(dev->ma + (x << 1)) & dev->vram_mask]); + p[x] = video_16to32[dat & 0xffff]; + p[x + 1] = video_16to32[dat >> 16]; + + dat = *(uint32_t *) (&dev->vram[(dev->ma + (x << 1) + 4) & dev->vram_mask]); + p[x + 2] = video_16to32[dat & 0xffff]; + p[x + 3] = video_16to32[dat >> 16]; + + dat = *(uint32_t *) (&dev->vram[(dev->ma + (x << 1) + 8) & dev->vram_mask]); + p[x + 4] = video_16to32[dat & 0xffff]; + p[x + 5] = video_16to32[dat >> 16]; + + dat = *(uint32_t *) (&dev->vram[(dev->ma + (x << 1) + 12) & dev->vram_mask]); + p[x + 6] = video_16to32[dat & 0xffff]; + p[x + 7] = video_16to32[dat >> 16]; + } + dev->ma += (x << 1); + dev->ma &= dev->vram_mask; + } +} + +void +ibm8514_render_24bpp(svga_t *svga) +{ + ibm8514_t *dev = (ibm8514_t *) svga->dev8514; + uint32_t *p; + uint32_t dat; + + if ((dev->displine + svga->y_add) < 0) + return; + + if (dev->changedvram[dev->ma >> 12] || dev->changedvram[(dev->ma >> 12) + 1] || svga->fullchange) { + p = &buffer32->line[dev->displine + svga->y_add][svga->x_add]; + + if (dev->firstline_draw == 2000) + dev->firstline_draw = dev->displine; + dev->lastline_draw = dev->displine; + + for (int x = 0; x <= dev->h_disp; x += 4) { + dat = *(uint32_t *) (&dev->vram[dev->ma & dev->vram_mask]); + p[x] = dat & 0xffffff; + + dat = *(uint32_t *) (&dev->vram[(dev->ma + 3) & dev->vram_mask]); + p[x + 1] = dat & 0xffffff; + + dat = *(uint32_t *) (&dev->vram[(dev->ma + 6) & dev->vram_mask]); + p[x + 2] = dat & 0xffffff; + + dat = *(uint32_t *) (&dev->vram[(dev->ma + 9) & dev->vram_mask]); + p[x + 3] = dat & 0xffffff; + + dev->ma += 12; + } + dev->ma &= dev->vram_mask; + } +} + +void +ibm8514_render_BGR(svga_t *svga) +{ + ibm8514_t *dev = (ibm8514_t *) svga->dev8514; + uint32_t *p; + uint32_t dat; + + if ((dev->displine + svga->y_add) < 0) + return; + + if (dev->changedvram[dev->ma >> 12] || dev->changedvram[(dev->ma >> 12) + 1] || svga->fullchange) { + p = &buffer32->line[dev->displine + svga->y_add][svga->x_add]; + + if (dev->firstline_draw == 2000) + dev->firstline_draw = dev->displine; + dev->lastline_draw = dev->displine; + + for (int x = 0; x <= dev->h_disp; x += 4) { + dat = *(uint32_t *) (&dev->vram[dev->ma & dev->vram_mask]); + p[x] = ((dat & 0xff0000) >> 16) | (dat & 0x00ff00) | ((dat & 0x0000ff) << 16); + + dat = *(uint32_t *) (&dev->vram[(dev->ma + 3) & dev->vram_mask]); + p[x + 1] = ((dat & 0xff0000) >> 16) | (dat & 0x00ff00) | ((dat & 0x0000ff) << 16); + + dat = *(uint32_t *) (&dev->vram[(dev->ma + 6) & dev->vram_mask]); + p[x + 2] = ((dat & 0xff0000) >> 16) | (dat & 0x00ff00) | ((dat & 0x0000ff) << 16); + + dat = *(uint32_t *) (&dev->vram[(dev->ma + 9) & dev->vram_mask]); + p[x + 3] = ((dat & 0xff0000) >> 16) | (dat & 0x00ff00) | ((dat & 0x0000ff) << 16); + + dev->ma += 12; + } + dev->ma &= dev->vram_mask; + } +} + +void +ibm8514_render_ABGR8888(svga_t *svga) +{ + ibm8514_t *dev = (ibm8514_t *) svga->dev8514; + int x; + uint32_t *p; + uint32_t dat; + + if ((dev->displine + svga->y_add) < 0) + return; + + if (dev->changedvram[dev->ma >> 12] || dev->changedvram[(dev->ma >> 12) + 1] || svga->fullchange) { + p = &buffer32->line[dev->displine + svga->y_add][svga->x_add]; + + if (dev->firstline_draw == 2000) + dev->firstline_draw = dev->displine; + dev->lastline_draw = dev->displine; + + for (x = 0; x <= dev->h_disp; x++) { + dat = *(uint32_t *) (&dev->vram[(dev->ma + (x << 2)) & dev->vram_mask]); + *p++ = ((dat & 0xff0000) >> 16) | (dat & 0x00ff00) | ((dat & 0x0000ff) << 16); + } + dev->ma += (x * 4); + dev->ma &= dev->vram_mask; + } +} + +void +ibm8514_render_RGBA8888(svga_t *svga) +{ + ibm8514_t *dev = (ibm8514_t *) svga->dev8514; + int x; + uint32_t *p; + uint32_t dat; + + if ((dev->displine + svga->y_add) < 0) + return; + + if (dev->changedvram[dev->ma >> 12] || dev->changedvram[(dev->ma >> 12) + 1] || svga->fullchange) { + p = &buffer32->line[dev->displine + svga->y_add][svga->x_add]; + + if (dev->firstline_draw == 2000) + dev->firstline_draw = dev->displine; + dev->lastline_draw = dev->displine; + + for (x = 0; x <= dev->h_disp; x++) { + dat = *(uint32_t *) (&dev->vram[(dev->ma + (x << 2)) & dev->vram_mask]); + *p++ = dat >> 8; + } + dev->ma += (x * 4); + dev->ma &= dev->vram_mask; + } +} + +static void +ibm8514_render_overscan_left(ibm8514_t *dev, svga_t *svga) +{ + if ((dev->displine + svga->y_add) < 0) + return; + + if (svga->scrblank || (dev->h_disp == 0)) + return; + + for (int i = 0; i < svga->x_add; i++) + buffer32->line[dev->displine + svga->y_add][i] = svga->overscan_color; +} + +static void +ibm8514_render_overscan_right(ibm8514_t *dev, svga_t *svga) +{ + int right; + + if ((dev->displine + svga->y_add) < 0) + return; + + if (svga->scrblank || (dev->h_disp == 0)) + return; + + right = (overscan_x >> 1); + for (int i = 0; i < right; i++) + buffer32->line[dev->displine + svga->y_add][svga->x_add + dev->h_disp + i] = svga->overscan_color; +} + +void +ibm8514_poll(void *priv, svga_t *svga) +{ + ibm8514_t *dev = (ibm8514_t *) priv; + uint32_t x; + int wx; + int wy; + + if (!dev->linepos) { + if ((dev->displine == dev->hwcursor_latch.y) && dev->hwcursor_latch.ena) { + dev->hwcursor_on = dev->hwcursor_latch.cur_ysize - dev->hwcursor_latch.yoff; + dev->hwcursor_oddeven = 0; + } + + if ((dev->displine == (dev->hwcursor_latch.y + 1)) && dev->hwcursor_latch.ena && dev->interlace) { + dev->hwcursor_on = dev->hwcursor_latch.cur_ysize - (dev->hwcursor_latch.yoff + 1); + dev->hwcursor_oddeven = 1; + } + + timer_advance_u64(&svga->timer, svga->dispofftime); + svga->cgastat |= 1; + dev->linepos = 1; + + if (dev->dispon) { + dev->hdisp_on = 1; + + dev->ma &= dev->vram_mask; + + if (dev->firstline == 2000) { + dev->firstline = dev->displine; + video_wait_for_buffer_monitor(svga->monitor_index); + } + + if (dev->hwcursor_on) + dev->changedvram[dev->ma >> 12] = dev->changedvram[(dev->ma >> 12) + 1] = dev->interlace ? 3 : 2; + + svga->render8514(svga); + + svga->x_add = (overscan_x >> 1); + ibm8514_render_overscan_left(dev, svga); + ibm8514_render_overscan_right(dev, svga); + svga->x_add = (overscan_x >> 1); + + if (dev->hwcursor_on) { + if (svga->hwcursor_draw) + svga->hwcursor_draw(svga, dev->displine + svga->y_add); + dev->hwcursor_on--; + if (dev->hwcursor_on && dev->interlace) + dev->hwcursor_on--; + } + + if (dev->lastline < dev->displine) + dev->lastline = dev->displine; + } + + dev->displine++; + if (dev->interlace) + dev->displine++; + if ((svga->cgastat & 8) && ((dev->displine & 0x0f) == (svga->crtc[0x11] & 0x0f)) && svga->vslines) + svga->cgastat &= ~8; + svga->vslines++; + if (dev->displine > 1500) + dev->displine = 0; + } else { + timer_advance_u64(&svga->timer, svga->dispontime); + if (dev->dispon) + svga->cgastat &= ~1; + dev->hdisp_on = 0; + + dev->linepos = 0; + if (dev->dispon) { + if (dev->sc == dev->rowcount) { + dev->sc = 0; + dev->maback += (dev->rowoffset << 3); + if (dev->interlace) + dev->maback += (dev->rowoffset << 3); + dev->maback &= dev->vram_mask; + dev->ma = dev->maback; + } else { + dev->sc++; + dev->sc &= 0x1f; + dev->ma = dev->maback; + } + } + + dev->vc++; + dev->vc &= 0x7ff; + + if (dev->vc == dev->dispend) { + dev->dispon = 0; + + for (x = 0; x < ((dev->vram_mask + 1) >> 12); x++) { + if (dev->changedvram[x]) + dev->changedvram[x]--; + } + + if (svga->fullchange) + svga->fullchange--; + } + if (dev->vc == dev->v_syncstart) { + dev->dispon = 0; + svga->cgastat |= 8; + x = dev->h_disp; + + if (dev->interlace && !dev->oddeven) + dev->lastline++; + if (dev->interlace && dev->oddeven) + dev->firstline--; + + wx = x; + + wy = dev->lastline - dev->firstline; + svga_doblit(wx, wy, svga); + + dev->firstline = 2000; + dev->lastline = 0; + + dev->firstline_draw = 2000; + dev->lastline_draw = 0; + + dev->oddeven ^= 1; + + svga->monitor->mon_changeframecount = dev->interlace ? 3 : 2; + svga->vslines = 0; + + if (dev->interlace && dev->oddeven) + dev->ma = dev->maback = (dev->rowoffset << 1); + else + dev->ma = dev->maback = 0; + + dev->ma = (dev->ma << 2); + dev->maback = (dev->maback << 2); + } + if (dev->vc == dev->v_total) { + dev->vc = 0; + dev->sc = 0; + dev->dispon = 1; + dev->displine = (dev->interlace && dev->oddeven) ? 1 : 0; + + svga->x_add = (overscan_x >> 1); + + dev->hwcursor_on = 0; + dev->hwcursor_latch = dev->hwcursor; + } + } +} + +void +ibm8514_recalctimings(svga_t *svga) +{ + ibm8514_t *dev = (ibm8514_t *) svga->dev8514; + + if (dev->on) { + dev->h_disp = (dev->hdisp + 1) << 3; + 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); + dev->rowcount = !!(dev->disp_cntl & 0x08); + dev->dispend = ((dev->vdisp >> 1) + 1); + if (dev->dispend == 766) + dev->dispend += 2; + + if (dev->dispend == 598) + dev->dispend += 2; + + if (dev->accel.advfunc_cntl & 4) { + if (dev->h_disp == 8) { + dev->h_disp = 1024; + dev->dispend = 768; + dev->v_total = 1536; + dev->v_syncstart = 1536; + } + + if (dev->dispend == 598) + dev->dispend = 600; + + if (dev->interlace) { + dev->dispend >>= 1; + dev->v_syncstart >>= 2; + dev->v_total >>= 2; + } else { + dev->v_syncstart >>= 1; + dev->v_total >>= 1; + } + + dev->rowoffset = 0x80; + + 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 (dev->h_disp == 1024) { + dev->h_disp = 640; + dev->dispend = 480; + } + + if (dev->interlace) { + dev->dispend >>= 1; + dev->v_syncstart >>= 2; + dev->v_total >>= 2; + } else { + dev->v_syncstart >>= 1; + dev->v_total >>= 1; + } + + dev->rowoffset = 0x80; + + svga->clock = (cpuclock * (double) (1ULL << 32)) / 25175000.0; + } + svga->render8514 = ibm8514_render_8bpp; + 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_standalone_enabled); + } + 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 +ibm8514_mca_read(int port, void *priv) +{ + const svga_t *svga = (svga_t *) priv; + const ibm8514_t *dev = (ibm8514_t *) svga->dev8514; + + return (dev->pos_regs[port & 7]); +} + +static void +ibm8514_mca_write(int port, uint8_t val, void *priv) +{ + svga_t *svga = (svga_t *) priv; + ibm8514_t *dev = (ibm8514_t *) svga->dev8514; + + /* MCA does not write registers below 0x0100. */ + if (port < 0x0102) + return; + + /* Save the MCA register value. */ + dev->pos_regs[port & 7] = val; +} + +static uint8_t +ibm8514_mca_feedb(void *priv) +{ + const svga_t *svga = (svga_t *) priv; + const ibm8514_t *dev = (ibm8514_t *) svga->dev8514; + + return dev->pos_regs[2] & 1; +} + +static void * +ibm8514_init(const device_t *info) +{ + if (svga_get_pri() == NULL) + return NULL; + + svga_t *svga = svga_get_pri(); + ibm8514_t *dev = (ibm8514_t *) calloc(1, sizeof(ibm8514_t)); + + svga->dev8514 = dev; + + 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 = dev->pallook; + + dev->type = info->flags; + dev->bpp = 0; + + ibm8514_io_set(svga); + + if (dev->type & DEVICE_MCA) { + dev->pos_regs[0] = 0x7f; + dev->pos_regs[1] = 0xef; + mca_add(ibm8514_mca_read, ibm8514_mca_write, ibm8514_mca_feedb, NULL, svga); + } + + return svga; +} + +static void +ibm8514_close(void *priv) +{ + svga_t *svga = (svga_t *) priv; + ibm8514_t *dev = (ibm8514_t *) svga->dev8514; + + if (dev) { + free(dev->vram); + free(dev->changedvram); + + free(dev); + } +} + +static void +ibm8514_speed_changed(void *priv) +{ + svga_t *svga = (svga_t *) priv; + + svga_recalctimings(svga); +} + +static void +ibm8514_force_redraw(void *priv) +{ + svga_t *svga = (svga_t *) priv; + + svga->fullchange = changeframecount; +} + +// clang-format off +const device_t gen8514_isa_device = { + .name = "Generic 8514/A clone (ISA)", + .internal_name = "8514_isa", + .flags = DEVICE_AT | DEVICE_ISA, + .local = 0, + .init = ibm8514_init, + .close = ibm8514_close, + .reset = NULL, + { .available = NULL }, + .speed_changed = ibm8514_speed_changed, + .force_redraw = ibm8514_force_redraw, + .config = NULL +}; + +const device_t ibm8514_mca_device = { + .name = "IBM 8514/A (MCA)", + .internal_name = "8514_mca", + .flags = DEVICE_MCA, + .local = 0, + .init = ibm8514_init, + .close = ibm8514_close, + .reset = NULL, + { .available = NULL }, + .speed_changed = ibm8514_speed_changed, + .force_redraw = ibm8514_force_redraw, + .config = NULL +}; + + +void +ibm8514_device_add(void) +{ + if (!ibm8514_standalone_enabled) + return; + + if (machine_has_bus(machine, MACHINE_BUS_MCA)) + device_add(&ibm8514_mca_device); + else + device_add(&gen8514_isa_device); +} diff --git a/src/video/vid_ati18800.c b/src/video/vid_ati18800.c index ec63b1dea..5847faa39 100644 --- a/src/video/vid_ati18800.c +++ b/src/video/vid_ati18800.c @@ -1,20 +1,20 @@ /* - * 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. + * 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. + * This file is part of the 86Box distribution. * - * ATI 18800 emulation (VGA Edge-16) + * ATI 18800 emulation (VGA Edge-16) * * * - * Authors: Sarah Walker, - * Miran Grca, + * Authors: Sarah Walker, + * Miran Grca, * - * Copyright 2008-2020 Sarah Walker. - * Copyright 2016-2020 Miran Grca. + * Copyright 2008-2020 Sarah Walker. + * Copyright 2016-2020 Miran Grca. */ #include #include @@ -32,294 +32,297 @@ #include <86box/vid_svga.h> #include <86box/vid_svga_render.h> - #if defined(DEV_BRANCH) && defined(USE_VGAWONDER) -#define BIOS_ROM_PATH_WONDER "roms/video/ati18800/VGA_Wonder_V3-1.02.bin" +# define BIOS_ROM_PATH_WONDER "roms/video/ati18800/VGA_Wonder_V3-1.02.bin" #endif -#define BIOS_ROM_PATH_VGA88 "roms/video/ati18800/vga88.bin" -#define BIOS_ROM_PATH_EDGE16 "roms/video/ati18800/vgaedge16.vbi" +#define BIOS_ROM_PATH_VGA88 "roms/video/ati18800/vga88.bin" +#define BIOS_ROM_PATH_EDGE16 "roms/video/ati18800/vgaedge16.vbi" enum { #if defined(DEV_BRANCH) && defined(USE_VGAWONDER) - ATI18800_WONDER = 0, - ATI18800_VGA88, - ATI18800_EDGE16 + ATI18800_WONDER = 0, + ATI18800_VGA88, + ATI18800_EDGE16 #else - ATI18800_VGA88 = 0, - ATI18800_EDGE16 + ATI18800_VGA88 = 0, + ATI18800_EDGE16 #endif }; +typedef struct ati18800_t { + svga_t svga; + ati_eeprom_t eeprom; -typedef struct ati18800_t -{ - svga_t svga; - ati_eeprom_t eeprom; + rom_t bios_rom; - rom_t bios_rom; - - uint8_t regs[256]; - int index; + uint8_t regs[256]; + int index; } ati18800_t; -static video_timings_t timing_ati18800 = {VIDEO_ISA, 8, 16, 32, 8, 16, 32}; +static video_timings_t timing_ati18800 = { .type = VIDEO_ISA, .write_b = 8, .write_w = 16, .write_l = 32, .read_b = 8, .read_w = 16, .read_l = 32 }; - -static void ati18800_out(uint16_t addr, uint8_t val, void *p) +static void +ati18800_out(uint16_t addr, uint8_t val, void *priv) { - ati18800_t *ati18800 = (ati18800_t *)p; - svga_t *svga = &ati18800->svga; - uint8_t old; + ati18800_t *ati18800 = (ati18800_t *) priv; + svga_t *svga = &ati18800->svga; + uint8_t old; - if (((addr & 0xfff0) == 0x3d0 || (addr & 0xfff0) == 0x3b0) && !(svga->miscout & 1)) - addr ^= 0x60; + if (((addr & 0xfff0) == 0x3d0 || (addr & 0xfff0) == 0x3b0) && !(svga->miscout & 1)) + addr ^= 0x60; - switch (addr) - { - case 0x1ce: - ati18800->index = val; - break; - case 0x1cf: - ati18800->regs[ati18800->index] = val; - switch (ati18800->index) - { - case 0xb0: - svga_recalctimings(svga); - break; - case 0xb2: - case 0xbe: - if (ati18800->regs[0xbe] & 8) /*Read/write bank mode*/ - { - svga->read_bank = ((ati18800->regs[0xb2] >> 5) & 7) * 0x10000; - svga->write_bank = ((ati18800->regs[0xb2] >> 1) & 7) * 0x10000; - } - else /*Single bank mode*/ - svga->read_bank = svga->write_bank = ((ati18800->regs[0xb2] >> 1) & 7) * 0x10000; - break; - case 0xb3: - ati_eeprom_write(&ati18800->eeprom, val & 8, val & 2, val & 1); - break; - } - break; - - case 0x3D4: - svga->crtcreg = val & 0x3f; - return; - case 0x3D5: - if ((svga->crtcreg < 7) && (svga->crtc[0x11] & 0x80) && !(ati18800->regs[0xb4] & 0x80)) - return; - if ((svga->crtcreg == 7) && (svga->crtc[0x11] & 0x80) && !(ati18800->regs[0xb4] & 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); -} + switch (addr) { + case 0x1ce: + ati18800->index = val; + break; + case 0x1cf: + ati18800->regs[ati18800->index] = val; + switch (ati18800->index) { + case 0xb0: + svga_recalctimings(svga); + break; + case 0xb2: + case 0xbe: + if (ati18800->regs[0xbe] & 8) /*Read/write bank mode*/ + { + svga->read_bank = ((ati18800->regs[0xb2] >> 5) & 7) * 0x10000; + svga->write_bank = ((ati18800->regs[0xb2] >> 1) & 7) * 0x10000; + } else /*Single bank mode*/ + svga->read_bank = svga->write_bank = ((ati18800->regs[0xb2] >> 1) & 7) * 0x10000; + break; + case 0xb3: + ati_eeprom_write(&ati18800->eeprom, val & 8, val & 2, val & 1); + break; -static uint8_t ati18800_in(uint16_t addr, void *p) -{ - ati18800_t *ati18800 = (ati18800_t *)p; - svga_t *svga = &ati18800->svga; - uint8_t temp = 0xff; - - if (((addr&0xFFF0) == 0x3D0 || (addr&0xFFF0) == 0x3B0) && !(svga->miscout&1)) addr ^= 0x60; - - switch (addr) - { - case 0x1ce: - temp = ati18800->index; - break; - case 0x1cf: - switch (ati18800->index) - { - case 0xb7: - temp = ati18800->regs[ati18800->index] & ~8; - if (ati_eeprom_read(&ati18800->eeprom)) - temp |= 8; - break; - default: - temp = ati18800->regs[ati18800->index]; - break; - } - break; - - case 0x3D4: - temp = svga->crtcreg; - break; - case 0x3D5: - temp = svga->crtc[svga->crtcreg]; - break; default: - temp = svga_in(addr, svga); - break; - } - return temp; + break; + } + break; + + case 0x3D4: + svga->crtcreg = val & 0x3f; + return; + case 0x3D5: + if ((svga->crtcreg < 7) && (svga->crtc[0x11] & 0x80) && !(ati18800->regs[0xb4] & 0x80)) + return; + if ((svga->crtcreg == 7) && (svga->crtc[0x11] & 0x80) && !(ati18800->regs[0xb4] & 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; + + default: + break; + } + svga_out(addr, val, svga); } -static void ati18800_recalctimings(svga_t *svga) +static uint8_t +ati18800_in(uint16_t addr, void *priv) { - ati18800_t *ati18800 = (ati18800_t *)svga->p; + ati18800_t *ati18800 = (ati18800_t *) priv; + svga_t *svga = &ati18800->svga; + uint8_t temp = 0xff; - if(svga->crtc[0x17] & 4) - { - svga->vtotal <<= 1; - svga->dispend <<= 1; - svga->vsyncstart <<= 1; - svga->split <<= 1; - svga->vblankstart <<= 1; - } + if (((addr & 0xFFF0) == 0x3D0 || (addr & 0xFFF0) == 0x3B0) && !(svga->miscout & 1)) + addr ^= 0x60; - if (!svga->scrblank && ((ati18800->regs[0xb0] & 0x02) || (ati18800->regs[0xb0] & 0x04))) /*Extended 256 colour modes*/ - { - svga->render = svga_render_8bpp_highres; - svga->bpp = 8; - svga->rowoffset <<= 1; - svga->ma <<= 1; - } + switch (addr) { + case 0x1ce: + temp = ati18800->index; + break; + case 0x1cf: + switch (ati18800->index) { + case 0xb7: + temp = ati18800->regs[ati18800->index] & ~8; + if (ati_eeprom_read(&ati18800->eeprom)) + temp |= 8; + break; + default: + temp = ati18800->regs[ati18800->index]; + break; + } + break; + + case 0x3D4: + temp = svga->crtcreg; + break; + case 0x3D5: + temp = svga->crtc[svga->crtcreg]; + break; + default: + temp = svga_in(addr, svga); + break; + } + return temp; } -static void *ati18800_init(const device_t *info) +static void +ati18800_recalctimings(svga_t *svga) { - ati18800_t *ati18800 = malloc(sizeof(ati18800_t)); - memset(ati18800, 0, sizeof(ati18800_t)); + const ati18800_t *ati18800 = (ati18800_t *) svga->priv; - video_inform(VIDEO_FLAG_TYPE_SPECIAL, &timing_ati18800); + if (svga->crtc[0x17] & 4) { + svga->vtotal <<= 1; + svga->dispend <<= 1; + svga->vsyncstart <<= 1; + svga->split <<= 1; + svga->vblankstart <<= 1; + } - switch (info->local) { + if (!svga->scrblank && ((ati18800->regs[0xb0] & 0x02) || (ati18800->regs[0xb0] & 0x04))) /*Extended 256 colour modes*/ + { + svga->render = svga_render_8bpp_highres; + svga->bpp = 8; + svga->rowoffset <<= 1; + svga->ma <<= 1; + } +} + +static void * +ati18800_init(const device_t *info) +{ + ati18800_t *ati18800 = malloc(sizeof(ati18800_t)); + memset(ati18800, 0, sizeof(ati18800_t)); + + video_inform(VIDEO_FLAG_TYPE_SPECIAL, &timing_ati18800); + + switch (info->local) { + default: #if defined(DEV_BRANCH) && defined(USE_VGAWONDER) - case ATI18800_WONDER: + case ATI18800_WONDER: + rom_init(&ati18800->bios_rom, BIOS_ROM_PATH_WONDER, 0xc0000, 0x8000, 0x7fff, 0, MEM_MAPPING_EXTERNAL); + break; #endif - default: -#if defined(DEV_BRANCH) && defined(USE_VGAWONDER) - rom_init(&ati18800->bios_rom, BIOS_ROM_PATH_WONDER, 0xc0000, 0x8000, 0x7fff, 0, MEM_MAPPING_EXTERNAL); - break; -#endif - case ATI18800_VGA88: - rom_init(&ati18800->bios_rom, BIOS_ROM_PATH_VGA88, 0xc0000, 0x8000, 0x7fff, 0, MEM_MAPPING_EXTERNAL); - break; - case ATI18800_EDGE16: - rom_init(&ati18800->bios_rom, BIOS_ROM_PATH_EDGE16, 0xc0000, 0x8000, 0x7fff, 0, MEM_MAPPING_EXTERNAL); - break; - }; + case ATI18800_VGA88: + rom_init(&ati18800->bios_rom, BIOS_ROM_PATH_VGA88, 0xc0000, 0x8000, 0x7fff, 0, MEM_MAPPING_EXTERNAL); + break; + case ATI18800_EDGE16: + rom_init(&ati18800->bios_rom, BIOS_ROM_PATH_EDGE16, 0xc0000, 0x8000, 0x7fff, 0, MEM_MAPPING_EXTERNAL); + break; + } - if (info->local == ATI18800_EDGE16) { - svga_init(info, &ati18800->svga, ati18800, 1 << 18, /*256kb*/ - ati18800_recalctimings, - ati18800_in, ati18800_out, - NULL, - NULL); - } else { - svga_init(info, &ati18800->svga, ati18800, 1 << 19, /*512kb*/ - ati18800_recalctimings, - ati18800_in, ati18800_out, - NULL, - NULL); - } + if (info->local == ATI18800_EDGE16) { + svga_init(info, &ati18800->svga, ati18800, 1 << 18, /*256kb*/ + ati18800_recalctimings, + ati18800_in, ati18800_out, + NULL, + NULL); + } else { + svga_init(info, &ati18800->svga, ati18800, 1 << 19, /*512kb*/ + ati18800_recalctimings, + ati18800_in, ati18800_out, + NULL, + NULL); + } - io_sethandler(0x01ce, 0x0002, ati18800_in, NULL, NULL, ati18800_out, NULL, NULL, ati18800); - io_sethandler(0x03c0, 0x0020, ati18800_in, NULL, NULL, ati18800_out, NULL, NULL, ati18800); + io_sethandler(0x01ce, 0x0002, ati18800_in, NULL, NULL, ati18800_out, NULL, NULL, ati18800); + io_sethandler(0x03c0, 0x0020, ati18800_in, NULL, NULL, ati18800_out, NULL, NULL, ati18800); - ati18800->svga.miscout = 1; + ati18800->svga.miscout = 1; - ati_eeprom_load(&ati18800->eeprom, "ati18800.nvr", 0); + ati_eeprom_load(&ati18800->eeprom, "ati18800.nvr", 0); - return ati18800; + return ati18800; } #if defined(DEV_BRANCH) && defined(USE_VGAWONDER) -static int ati18800_wonder_available(void) +static int +ati18800_wonder_available(void) { - return rom_present(BIOS_ROM_PATH_WONDER); + return rom_present(BIOS_ROM_PATH_WONDER); } #endif -static int ati18800_vga88_available(void) +static int +ati18800_vga88_available(void) { - return rom_present(BIOS_ROM_PATH_VGA88); + return rom_present(BIOS_ROM_PATH_VGA88); } -static int ati18800_available(void) +static int +ati18800_available(void) { - return rom_present(BIOS_ROM_PATH_EDGE16); + return rom_present(BIOS_ROM_PATH_EDGE16); } -static void ati18800_close(void *p) +static void +ati18800_close(void *priv) { - ati18800_t *ati18800 = (ati18800_t *)p; + ati18800_t *ati18800 = (ati18800_t *) priv; - svga_close(&ati18800->svga); - - free(ati18800); + svga_close(&ati18800->svga); + + free(ati18800); } -static void ati18800_speed_changed(void *p) +static void +ati18800_speed_changed(void *priv) { - ati18800_t *ati18800 = (ati18800_t *)p; - - svga_recalctimings(&ati18800->svga); + ati18800_t *ati18800 = (ati18800_t *) priv; + + svga_recalctimings(&ati18800->svga); } -static void ati18800_force_redraw(void *p) +static void +ati18800_force_redraw(void *priv) { - ati18800_t *ati18800 = (ati18800_t *)p; + ati18800_t *ati18800 = (ati18800_t *) priv; - ati18800->svga.fullchange = changeframecount; + ati18800->svga.fullchange = changeframecount; } #if defined(DEV_BRANCH) && defined(USE_VGAWONDER) -const device_t ati18800_wonder_device = -{ - "ATI-18800", - "ati18800w", - DEVICE_ISA, ATI18800_WONDER, - ati18800_init, - ati18800_close, - NULL, - { ati18800_wonder_available }, - ati18800_speed_changed, - ati18800_force_redraw, - NULL +const device_t ati18800_wonder_device = { + .name = "ATI-18800", + .internal_name = "ati18800w", + .flags = DEVICE_ISA, + .local = ATI18800_WONDER, + .init = ati18800_init, + .close = ati18800_close, + .reset = NULL, + { .available = ati18800_wonder_available }, + .speed_changed = ati18800_speed_changed, + .force_redraw = ati18800_force_redraw, + .config = NULL }; #endif -const device_t ati18800_vga88_device = -{ - "ATI-18800-1", - "ati18800v", - DEVICE_ISA, ATI18800_VGA88, - ati18800_init, - ati18800_close, - NULL, - { ati18800_vga88_available }, - ati18800_speed_changed, - ati18800_force_redraw, - NULL +const device_t ati18800_vga88_device = { + .name = "ATI-18800-1", + .internal_name = "ati18800v", + .flags = DEVICE_ISA, + .local = ATI18800_VGA88, + .init = ati18800_init, + .close = ati18800_close, + .reset = NULL, + { .available = ati18800_vga88_available }, + .speed_changed = ati18800_speed_changed, + .force_redraw = ati18800_force_redraw, + .config = NULL }; -const device_t ati18800_device = -{ - "ATI-18800-5", - "ati18800", - DEVICE_ISA, ATI18800_EDGE16, - ati18800_init, - ati18800_close, - NULL, - { ati18800_available }, - ati18800_speed_changed, - ati18800_force_redraw, - NULL +const device_t ati18800_device = { + .name = "ATI-18800-5", + .internal_name = "ati18800", + .flags = DEVICE_ISA, + .local = ATI18800_EDGE16, + .init = ati18800_init, + .close = ati18800_close, + .reset = NULL, + { .available = ati18800_available }, + .speed_changed = ati18800_speed_changed, + .force_redraw = ati18800_force_redraw, + .config = NULL }; diff --git a/src/video/vid_ati28800.c b/src/video/vid_ati28800.c index dcabd636a..aa5800d1c 100644 --- a/src/video/vid_ati28800.c +++ b/src/video/vid_ati28800.c @@ -1,22 +1,22 @@ /* - * 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. + * 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. + * This file is part of the 86Box distribution. * - * ATI 28800 emulation (VGA Charger and Korean VGA) + * ATI 28800 emulation (VGA Charger and Korean VGA) * * * - * Authors: Sarah Walker, - * Miran Grca, - * greatpsycho, + * Authors: Sarah Walker, + * Miran Grca, + * greatpsycho, * - * Copyright 2008-2018 Sarah Walker. - * Copyright 2016-2018 Miran Grca. - * Copyright 2018 greatpsycho. + * Copyright 2008-2018 Sarah Walker. + * Copyright 2016-2018 Miran Grca. + * Copyright 2018 greatpsycho. */ #include #include @@ -36,470 +36,508 @@ #include <86box/vid_svga.h> #include <86box/vid_svga_render.h> - -#define VGAWONDERXL 1 +#define VGAWONDERXL 1 #if defined(DEV_BRANCH) && defined(USE_XL24) -#define VGAWONDERXL24 2 +# define VGAWONDERXL24 2 #endif -#define BIOS_ATIKOR_PATH "roms/video/ati28800/atikorvga.bin" +#define BIOS_ATIKOR_PATH "roms/video/ati28800/atikorvga.bin" #define BIOS_ATIKOR_4620P_PATH_L "roms/machines/spc4620p/31005h.u8" #define BIOS_ATIKOR_4620P_PATH_H "roms/machines/spc4620p/31005h.u10" -#define BIOS_ATIKOR_6033P_PATH "roms/machines/spc6033p/phoenix.BIN" -#define FONT_ATIKOR_PATH "roms/video/ati28800/ati_ksc5601.rom" -#define FONT_ATIKOR_4620P_PATH "roms/machines/spc4620p/svb6120a_font.rom" -#define FONT_ATIKOR_6033P_PATH "roms/machines/spc6033p/svb6120a_font.rom" +#define BIOS_ATIKOR_6033P_PATH "roms/machines/spc6033p/phoenix.BIN" +#define FONT_ATIKOR_PATH "roms/video/ati28800/ati_ksc5601.rom" +#define FONT_ATIKOR_4620P_PATH "roms/machines/spc4620p/svb6120a_font.rom" +#define FONT_ATIKOR_6033P_PATH "roms/machines/spc6033p/svb6120a_font.rom" -#define BIOS_VGAXL_EVEN_PATH "roms/video/ati28800/xleven.bin" -#define BIOS_VGAXL_ODD_PATH "roms/video/ati28800/xlodd.bin" +#define BIOS_VGAXL_EVEN_PATH "roms/video/ati28800/xleven.bin" +#define BIOS_VGAXL_ODD_PATH "roms/video/ati28800/xlodd.bin" #if defined(DEV_BRANCH) && defined(USE_XL24) -#define BIOS_XL24_EVEN_PATH "roms/video/ati28800/112-14318-102.bin" -#define BIOS_XL24_ODD_PATH "roms/video/ati28800/112-14319-102.bin" +# define BIOS_XL24_EVEN_PATH "roms/video/ati28800/112-14318-102.bin" +# define BIOS_XL24_ODD_PATH "roms/video/ati28800/112-14319-102.bin" #endif -#define BIOS_ROM_PATH "roms/video/ati28800/bios.bin" +#define BIOS_ROM_PATH "roms/video/ati28800/bios.bin" #define BIOS_VGAXL_ROM_PATH "roms/video/ati28800/ATI_VGAWonder_XL.bin" +typedef struct ati28800_t { + svga_t svga; + ati_eeprom_t eeprom; -typedef struct ati28800_t -{ - svga_t svga; - ati_eeprom_t eeprom; + rom_t bios_rom; - rom_t bios_rom; + uint8_t regs[256]; + int index; + uint16_t vtotal; - uint8_t regs[256]; - int index; - uint16_t vtotal; + uint32_t memory; + uint8_t id; - uint32_t memory; - uint8_t id; + uint8_t port_03dd_val; + uint16_t get_korean_font_kind; + int in_get_korean_font_kind_set; + int get_korean_font_enabled; + int get_korean_font_index; + uint16_t get_korean_font_base; + int ksc5601_mode_enabled; - uint8_t port_03dd_val; - uint16_t get_korean_font_kind; - int in_get_korean_font_kind_set; - int get_korean_font_enabled; - int get_korean_font_index; - uint16_t get_korean_font_base; - int ksc5601_mode_enabled; - - int type, type_korean; + int type, type_korean; } ati28800_t; - -static video_timings_t timing_ati28800 = {VIDEO_ISA, 3, 3, 6, 5, 5, 10}; -static video_timings_t timing_ati28800_spc = {VIDEO_ISA, 2, 2, 4, 4, 4, 8}; - +static video_timings_t timing_ati28800 = { .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_ati28800_spc = { .type = VIDEO_ISA, .write_b = 2, .write_w = 2, .write_l = 4, .read_b = 4, .read_w = 4, .read_l = 8 }; #ifdef ENABLE_ATI28800_LOG int ati28800_do_log = ENABLE_ATI28800_LOG; - static void ati28800_log(const char *fmt, ...) { va_list ap; if (ati28800_do_log) { - va_start(ap, fmt); - pclog_ex(fmt, ap); - va_end(ap); + va_start(ap, fmt); + pclog_ex(fmt, ap); + va_end(ap); } } #else -#define ati28800_log(fmt, ...) +# define ati28800_log(fmt, ...) #endif - static void ati28800_recalctimings(svga_t *svga); static void -ati28800_out(uint16_t addr, uint8_t val, void *p) +ati28800_out(uint16_t addr, uint8_t val, void *priv) { - ati28800_t *ati28800 = (ati28800_t *)p; - svga_t *svga = &ati28800->svga; - uint8_t old; + ati28800_t *ati28800 = (ati28800_t *) priv; + svga_t *svga = &ati28800->svga; + uint8_t old; ati28800_log("ati28800_out : %04X %02X\n", addr, val); if (((addr & 0xFFF0) == 0x3D0 || (addr & 0xFFF0) == 0x3B0) && !(svga->miscout & 1)) - addr ^= 0x60; + addr ^= 0x60; switch (addr) { - case 0x1ce: - ati28800->index = val; - break; - case 0x1cf: - old = ati28800->regs[ati28800->index]; - ati28800->regs[ati28800->index] = val; - ati28800_log("ATI 28800 write reg=0x%02X, val=0x%02X\n", ati28800->index, val); - switch (ati28800->index) { - case 0xa3: - if ((old ^ val) & 0x10) - svga_recalctimings(svga); - break; - case 0xa7: - if ((old ^ val) & 0x80) - svga_recalctimings(svga); - break; - case 0xb0: - if ((old ^ val) & 0x60) - svga_recalctimings(svga); - break; - case 0xb2: - case 0xbe: - if (ati28800->regs[0xbe] & 0x08) { /* Read/write bank mode */ - svga->read_bank = (((ati28800->regs[0xb2] & 0x01) << 3) | ((ati28800->regs[0xb2] & 0xe0) >> 5)) * 0x10000; - svga->write_bank = ((ati28800->regs[0xb2] & 0x1e) >> 1) * 0x10000; - } else { /* Single bank mode */ - svga->read_bank = ((ati28800->regs[0xb2] & 0x1e) >> 1) * 0x10000; - svga->write_bank = ((ati28800->regs[0xb2] & 0x1e) >> 1) * 0x10000; - } - if (ati28800->index == 0xbe) { - if ((old ^ val) & 0x10) - svga_recalctimings(svga); - } - break; - case 0xb3: - ati_eeprom_write(&ati28800->eeprom, val & 8, val & 2, val & 1); - break; - case 0xb6: - if ((old ^ val) & 0x10) - svga_recalctimings(svga); - break; - case 0xb8: - if ((old ^ val) & 0x40) - svga_recalctimings(svga); - break; - case 0xb9: - if ((old ^ val) & 2) - svga_recalctimings(svga); - break; - } - break; + case 0x1ce: + ati28800->index = val; + break; + case 0x1cf: + old = ati28800->regs[ati28800->index]; + ati28800->regs[ati28800->index] = val; + ati28800_log("ATI 28800 write reg=0x%02X, val=0x%02X\n", ati28800->index, val); + switch (ati28800->index) { + case 0xa3: + if ((old ^ val) & 0x10) + svga_recalctimings(svga); + break; + case 0xa7: + if ((old ^ val) & 0x80) + svga_recalctimings(svga); + break; + case 0xb0: + if ((old ^ val) & 0x60) + svga_recalctimings(svga); + break; + case 0xb2: + case 0xbe: + if (ati28800->regs[0xbe] & 0x08) { /* Read/write bank mode */ + svga->read_bank = (((ati28800->regs[0xb2] & 0x01) << 3) | ((ati28800->regs[0xb2] & 0xe0) >> 5)) * 0x10000; + svga->write_bank = ((ati28800->regs[0xb2] & 0x1e) >> 1) * 0x10000; + } else { /* Single bank mode */ + svga->read_bank = ((ati28800->regs[0xb2] & 0x1e) >> 1) * 0x10000; + svga->write_bank = ((ati28800->regs[0xb2] & 0x1e) >> 1) * 0x10000; + } + if (ati28800->index == 0xbe) { + if ((old ^ val) & 0x10) + svga_recalctimings(svga); + } + break; + case 0xb3: + ati_eeprom_write(&ati28800->eeprom, val & 8, val & 2, val & 1); + break; + case 0xb6: + if ((old ^ val) & 0x10) + svga_recalctimings(svga); + break; + case 0xb8: + if ((old ^ val) & 0x40) + svga_recalctimings(svga); + break; + case 0xb9: + if ((old ^ val) & 2) + svga_recalctimings(svga); + break; - case 0x3C6: case 0x3C7: case 0x3C8: case 0x3C9: - if (ati28800->type == 1) - sc1148x_ramdac_out(addr, 0, val, svga->ramdac, svga); - else - svga_out(addr, val, svga); - return; + default: + break; + } + 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); + case 0x3C6: + case 0x3C7: + case 0x3C8: + case 0x3C9: + if (ati28800->type == 1) + sc1148x_ramdac_out(addr, 0, val, svga->ramdac, svga); + else + svga_out(addr, val, svga); + return; - 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); - } - } + 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; + } + break; + + default: + break; } svga_out(addr, val, svga); } - static void -ati28800k_out(uint16_t addr, uint8_t val, void *p) +ati28800k_out(uint16_t addr, uint8_t val, void *priv) { - ati28800_t *ati28800 = (ati28800_t *)p; - svga_t *svga = &ati28800->svga; - uint16_t oldaddr = addr; + ati28800_t *ati28800 = (ati28800_t *) priv; + svga_t *svga = &ati28800->svga; + uint16_t oldaddr = addr; + + if (((addr & 0xFFF0) == 0x3D0 || (addr & 0xFFF0) == 0x3B0) && !(svga->miscout & 1)) + addr ^= 0x60; - if (((addr&0xFFF0) == 0x3D0 || (addr&0xFFF0) == 0x3B0) && !(svga->miscout&1)) - addr ^= 0x60; - switch (addr) { - case 0x1CF: - if (ati28800->index == 0xBF && ((ati28800->regs[0xBF] ^ val) & 0x20)) { - ati28800->ksc5601_mode_enabled = val & 0x20; - svga_recalctimings(svga); - } - ati28800_out(oldaddr, val, p); - break; - case 0x3DD: - ati28800->port_03dd_val = val; - if (val == 1) - ati28800->get_korean_font_enabled = 0; - if (ati28800->in_get_korean_font_kind_set) { - ati28800->get_korean_font_kind = (val << 8) | (ati28800->get_korean_font_kind & 0xFF); - ati28800->get_korean_font_enabled = 1; - ati28800->get_korean_font_index = 0; - ati28800->in_get_korean_font_kind_set = 0; - } - break; - case 0x3DE: - ati28800->in_get_korean_font_kind_set = 0; - if (ati28800->get_korean_font_enabled) { - if ((ati28800->get_korean_font_base & 0x7F) > 0x20 && (ati28800->get_korean_font_base & 0x7F) < 0x7F) { - fontdatksc5601_user[(ati28800->get_korean_font_kind & 4) * 24 + - (ati28800->get_korean_font_base & 0x7F) - 0x20].chr[ati28800->get_korean_font_index] = val; - } - ati28800->get_korean_font_index++; - ati28800->get_korean_font_index &= 0x1F; - } else { - switch (ati28800->port_03dd_val) { - case 0x10: - ati28800->get_korean_font_base = ((val & 0x7F) << 7) | (ati28800->get_korean_font_base & 0x7F); - break; - case 8: - ati28800->get_korean_font_base = (ati28800->get_korean_font_base & 0x3F80) | (val & 0x7F); - break; - case 1: - ati28800->get_korean_font_kind = (ati28800->get_korean_font_kind & 0xFF00) | val; - if (val & 2) - ati28800->in_get_korean_font_kind_set = 1; - break; - } - break; - } - break; - default: - ati28800_out(oldaddr, val, p); - break; + case 0x1CF: + if (ati28800->index == 0xBF && ((ati28800->regs[0xBF] ^ val) & 0x20)) { + ati28800->ksc5601_mode_enabled = val & 0x20; + svga_recalctimings(svga); + } + ati28800_out(oldaddr, val, priv); + break; + case 0x3DD: + ati28800->port_03dd_val = val; + if (val == 1) + ati28800->get_korean_font_enabled = 0; + if (ati28800->in_get_korean_font_kind_set) { + ati28800->get_korean_font_kind = (val << 8) | (ati28800->get_korean_font_kind & 0xFF); + ati28800->get_korean_font_enabled = 1; + ati28800->get_korean_font_index = 0; + ati28800->in_get_korean_font_kind_set = 0; + } + break; + case 0x3DE: + ati28800->in_get_korean_font_kind_set = 0; + if (ati28800->get_korean_font_enabled) { + if ((ati28800->get_korean_font_base & 0x7F) > 0x20 && (ati28800->get_korean_font_base & 0x7F) < 0x7F) { + fontdatksc5601_user[(ati28800->get_korean_font_kind & 4) * 24 + (ati28800->get_korean_font_base & 0x7F) - 0x20].chr[ati28800->get_korean_font_index] = val; + } + ati28800->get_korean_font_index++; + ati28800->get_korean_font_index &= 0x1F; + } else { + switch (ati28800->port_03dd_val) { + case 0x10: + ati28800->get_korean_font_base = ((val & 0x7F) << 7) | (ati28800->get_korean_font_base & 0x7F); + break; + case 8: + ati28800->get_korean_font_base = (ati28800->get_korean_font_base & 0x3F80) | (val & 0x7F); + break; + case 1: + ati28800->get_korean_font_kind = (ati28800->get_korean_font_kind & 0xFF00) | val; + if (val & 2) + ati28800->in_get_korean_font_kind_set = 1; + break; + + default: + break; + } + break; + } + break; + default: + ati28800_out(oldaddr, val, priv); + break; } } - static uint8_t -ati28800_in(uint16_t addr, void *p) +ati28800_in(uint16_t addr, void *priv) { - ati28800_t *ati28800 = (ati28800_t *)p; - svga_t *svga = &ati28800->svga; - uint8_t temp; + ati28800_t *ati28800 = (ati28800_t *) priv; + svga_t *svga = &ati28800->svga; + uint8_t temp; if (addr != 0x3da) - ati28800_log("ati28800_in : %04X ", addr); - - if (((addr&0xFFF0) == 0x3D0 || (addr&0xFFF0) == 0x3B0) && !(svga->miscout&1)) - addr ^= 0x60; + ati28800_log("ati28800_in : %04X ", addr); + + if (((addr & 0xFFF0) == 0x3D0 || (addr & 0xFFF0) == 0x3B0) && !(svga->miscout & 1)) + addr ^= 0x60; switch (addr) { - case 0x1ce: - temp = ati28800->index; - break; - case 0x1cf: - switch (ati28800->index) { - case 0xaa: - temp = ati28800->id; - break; - case 0xb0: - temp = ati28800->regs[0xb0] | 0x80; - if (ati28800->memory == 1024) { - temp &= ~0x10; - temp |= 0x08; - } else if (ati28800->memory == 512) { - temp |= 0x10; - temp &= ~0x08; - } else { - temp &= ~0x18; - } - break; - case 0xb7: - temp = ati28800->regs[0xb7] & ~8; - if (ati_eeprom_read(&ati28800->eeprom)) - temp |= 8; - break; + case 0x1ce: + temp = ati28800->index; + break; + case 0x1cf: + switch (ati28800->index) { + case 0xaa: + temp = ati28800->id; + break; + case 0xb0: + temp = ati28800->regs[0xb0] | 0x80; + if (ati28800->memory == 1024) { + temp &= ~0x10; + temp |= 0x08; + } else if (ati28800->memory == 512) { + temp |= 0x10; + temp &= ~0x08; + } else { + temp &= ~0x18; + } + break; + case 0xb7: + temp = ati28800->regs[0xb7] & ~8; + if (ati_eeprom_read(&ati28800->eeprom)) + temp |= 8; + break; - default: - temp = ati28800->regs[ati28800->index]; - break; - } - break; + default: + temp = ati28800->regs[ati28800->index]; + break; + } + break; - case 0x3c2: - if ((svga->vgapal[0].r + svga->vgapal[0].g + svga->vgapal[0].b) >= 0x50) - temp = 0; - else - temp = 0x10; - break; + case 0x3c2: + if ((svga->vgapal[0].r + svga->vgapal[0].g + svga->vgapal[0].b) >= 0x50) + temp = 0; + else + temp = 0x10; + break; - case 0x3C6: case 0x3C7: case 0x3C8: case 0x3C9: - if (ati28800->type == 1) - return sc1148x_ramdac_in(addr, 0, svga->ramdac, svga); - return svga_in(addr, svga); + case 0x3C6: + case 0x3C7: + case 0x3C8: + case 0x3C9: + if (ati28800->type == 1) + return sc1148x_ramdac_in(addr, 0, svga->ramdac, svga); + return svga_in(addr, svga); - case 0x3D4: - temp = svga->crtcreg; - break; - case 0x3D5: - temp = svga->crtc[svga->crtcreg]; - break; - default: - temp = svga_in(addr, svga); - break; + case 0x3D4: + temp = svga->crtcreg; + break; + case 0x3D5: + temp = svga->crtc[svga->crtcreg]; + break; + default: + temp = svga_in(addr, svga); + break; } if (addr != 0x3da) - ati28800_log("%02X\n", temp); + ati28800_log("%02X\n", temp); return temp; } - static uint8_t -ati28800k_in(uint16_t addr, void *p) +ati28800k_in(uint16_t addr, void *priv) { - ati28800_t *ati28800 = (ati28800_t *)p; - svga_t *svga = &ati28800->svga; - uint16_t oldaddr = addr; - uint8_t temp = 0xFF; + ati28800_t *ati28800 = (ati28800_t *) priv; + const svga_t *svga = &ati28800->svga; + uint16_t oldaddr = addr; + uint8_t temp = 0xFF; if (addr != 0x3da) - ati28800_log("ati28800k_in : %04X ", addr); + ati28800_log("ati28800k_in : %04X ", addr); - if (((addr&0xFFF0) == 0x3D0 || (addr&0xFFF0) == 0x3B0) && !(svga->miscout&1)) - addr ^= 0x60; + if (((addr & 0xFFF0) == 0x3D0 || (addr & 0xFFF0) == 0x3B0) && !(svga->miscout & 1)) + addr ^= 0x60; switch (addr) { - case 0x3DE: - if (ati28800->get_korean_font_enabled) { - switch (ati28800->get_korean_font_kind >> 8) { - case 4: /* ROM font */ - temp = fontdatksc5601[ati28800->get_korean_font_base].chr[ati28800->get_korean_font_index++]; - break; - case 2: /* User defined font */ - if ((ati28800->get_korean_font_base & 0x7F) > 0x20 && (ati28800->get_korean_font_base & 0x7F) < 0x7F) { - temp = fontdatksc5601_user[(ati28800->get_korean_font_kind & 4) * 24 + - (ati28800->get_korean_font_base & 0x7F) - 0x20].chr[ati28800->get_korean_font_index]; - } else - temp = 0xFF; - ati28800->get_korean_font_index++; - break; - default: - break; - } - ati28800->get_korean_font_index &= 0x1F; - } - break; - default: - temp = ati28800_in(oldaddr, p); - break; + case 0x3DE: + if (ati28800->get_korean_font_enabled) { + switch (ati28800->get_korean_font_kind >> 8) { + case 4: /* ROM font */ + temp = fontdatksc5601[ati28800->get_korean_font_base].chr[ati28800->get_korean_font_index++]; + break; + case 2: /* User defined font */ + if ((ati28800->get_korean_font_base & 0x7F) > 0x20 && (ati28800->get_korean_font_base & 0x7F) < 0x7F) { + temp = fontdatksc5601_user[(ati28800->get_korean_font_kind & 4) * 24 + (ati28800->get_korean_font_base & 0x7F) - 0x20].chr[ati28800->get_korean_font_index]; + } else + temp = 0xFF; + ati28800->get_korean_font_index++; + break; + default: + break; + } + ati28800->get_korean_font_index &= 0x1F; + } + break; + default: + temp = ati28800_in(oldaddr, priv); + break; } if (addr != 0x3da) - ati28800_log("%02X\n", temp); + ati28800_log("%02X\n", temp); return temp; } - static void ati28800_recalctimings(svga_t *svga) { - ati28800_t *ati28800 = (ati28800_t *)svga->p; + const ati28800_t *ati28800 = (ati28800_t *) svga->priv; - if (ati28800->regs[0xa3] & 0x10) - svga->ma_latch |= 0x10000; + if (ati28800->regs[0xa3] & 0x10) + svga->ma_latch |= 0x10000; - if (ati28800->regs[0xb0] & 0x40) - svga->ma_latch |= 0x20000; - - switch (((ati28800->regs[0xbe] & 0x10) >> 1) | ((ati28800->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: ati28800_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: ati28800_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 (ati28800->regs[0xb0] & 0x40) + svga->ma_latch |= 0x20000; - if (ati28800->regs[0xb8] & 0x40) - svga->clock *= 2; + switch (((ati28800->regs[0xbe] & 0x10) >> 1) | ((ati28800->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: + ati28800_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: + ati28800_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 (ati28800->regs[0xa7] & 0x80) - svga->clock *= 3; + if (ati28800->regs[0xb8] & 0x40) + svga->clock *= 2; - if (ati28800->regs[0xb6] & 0x10) { - svga->hdisp <<= 1; - svga->htotal <<= 1; - svga->rowoffset <<= 1; - svga->gdcreg[5] &= ~0x40; - } - - if (ati28800->regs[0xb0] & 0x20) { - svga->gdcreg[5] |= 0x40; - } + if (ati28800->regs[0xa7] & 0x80) + svga->clock *= 3; - if (!svga->scrblank && 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->rowoffset <<= 1; - svga->ma_latch <<= 1; - } - break; - case 15: - if (svga->lowres) - svga->render = svga_render_15bpp_lowres; - else { - svga->render = svga_render_15bpp_highres; - svga->hdisp >>= 1; - svga->rowoffset <<= 1; - svga->ma_latch <<= 1; - } - break; - } - break; - } - } - } + if (ati28800->regs[0xb6] & 0x10) { + svga->hdisp <<= 1; + svga->htotal <<= 1; + svga->rowoffset <<= 1; + svga->gdcreg[5] &= ~0x40; + } + + if (ati28800->regs[0xb0] & 0x20) { + svga->gdcreg[5] |= 0x40; + } + + if (!svga->scrblank && 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->rowoffset <<= 1; + svga->ma_latch <<= 1; + } + break; + case 15: + if (svga->lowres) + svga->render = svga_render_15bpp_lowres; + else { + svga->render = svga_render_15bpp_highres; + svga->hdisp >>= 1; + svga->rowoffset <<= 1; + svga->ma_latch <<= 1; + } + break; + + default: + break; + } + break; + + default: + break; + } + } + } } - static void ati28800k_recalctimings(svga_t *svga) { - ati28800_t *ati28800 = (ati28800_t *) svga->p; + const ati28800_t *ati28800 = (ati28800_t *) svga->priv; ati28800_recalctimings(svga); if (svga->render == svga_render_text_80 && ati28800->ksc5601_mode_enabled) - svga->render = svga_render_text_80_ksc5601; + svga->render = svga_render_text_80_ksc5601; } void * @@ -508,57 +546,57 @@ ati28800k_init(const device_t *info) ati28800_t *ati28800 = (ati28800_t *) malloc(sizeof(ati28800_t)); memset(ati28800, 0, sizeof(ati28800_t)); - ati28800->type_korean = info->local; + ati28800->type_korean = info->local; if (ati28800->type_korean == 0) { - ati28800->memory = device_get_config_int("memory"); - video_inform(VIDEO_FLAG_TYPE_SPECIAL, &timing_ati28800); + ati28800->memory = device_get_config_int("memory"); + video_inform(VIDEO_FLAG_TYPE_SPECIAL, &timing_ati28800); } else { - ati28800->memory = 512; - video_inform(VIDEO_FLAG_TYPE_SPECIAL, &timing_ati28800_spc); + ati28800->memory = 512; + video_inform(VIDEO_FLAG_TYPE_SPECIAL, &timing_ati28800_spc); } - ati28800->port_03dd_val = 0; - ati28800->get_korean_font_base = 0; - ati28800->get_korean_font_index = 0; - ati28800->get_korean_font_enabled = 0; - ati28800->get_korean_font_kind = 0; + ati28800->port_03dd_val = 0; + ati28800->get_korean_font_base = 0; + ati28800->get_korean_font_index = 0; + ati28800->get_korean_font_enabled = 0; + ati28800->get_korean_font_kind = 0; ati28800->in_get_korean_font_kind_set = 0; - ati28800->ksc5601_mode_enabled = 0; + ati28800->ksc5601_mode_enabled = 0; - switch(ati28800->type_korean) { - case 0: - default: - rom_init(&ati28800->bios_rom, BIOS_ATIKOR_PATH, 0xc0000, 0x8000, 0x7fff, 0, MEM_MAPPING_EXTERNAL); - loadfont(FONT_ATIKOR_PATH, 6); - break; - case 1: - rom_init_interleaved(&ati28800->bios_rom, BIOS_ATIKOR_4620P_PATH_L, BIOS_ATIKOR_4620P_PATH_H, 0xc0000, - 0x8000, 0x7fff, 0, MEM_MAPPING_EXTERNAL); - loadfont(FONT_ATIKOR_4620P_PATH, 6); - break; - case 2: - rom_init(&ati28800->bios_rom, BIOS_ATIKOR_6033P_PATH, 0xc0000, 0x8000, 0x7fff, 0, MEM_MAPPING_EXTERNAL); - loadfont(FONT_ATIKOR_6033P_PATH, 6); - break; + switch (ati28800->type_korean) { + default: + case 0: + rom_init(&ati28800->bios_rom, BIOS_ATIKOR_PATH, 0xc0000, 0x8000, 0x7fff, 0, MEM_MAPPING_EXTERNAL); + loadfont(FONT_ATIKOR_PATH, 6); + break; + case 1: + rom_init_interleaved(&ati28800->bios_rom, BIOS_ATIKOR_4620P_PATH_L, BIOS_ATIKOR_4620P_PATH_H, 0xc0000, + 0x8000, 0x7fff, 0, MEM_MAPPING_EXTERNAL); + loadfont(FONT_ATIKOR_4620P_PATH, 6); + break; + case 2: + rom_init(&ati28800->bios_rom, BIOS_ATIKOR_6033P_PATH, 0xc0000, 0x8000, 0x7fff, 0, MEM_MAPPING_EXTERNAL); + loadfont(FONT_ATIKOR_6033P_PATH, 6); + break; } svga_init(info, &ati28800->svga, ati28800, ati28800->memory << 10, /*Memory size, default 512KB*/ - ati28800k_recalctimings, - ati28800k_in, ati28800k_out, - NULL, - NULL); + ati28800k_recalctimings, + ati28800k_in, ati28800k_out, + NULL, + NULL); io_sethandler(0x01ce, 0x0002, ati28800k_in, NULL, NULL, ati28800k_out, NULL, NULL, ati28800); io_sethandler(0x03c0, 0x0020, ati28800k_in, NULL, NULL, ati28800k_out, NULL, NULL, ati28800); - ati28800->svga.miscout = 1; - ati28800->svga.bpp = 8; - ati28800->svga.packed_chain4 = 1; - ati28800->svga.ksc5601_sbyte_mask = 0; - ati28800->svga.ksc5601_udc_area_msb[0] = 0xC9; - ati28800->svga.ksc5601_udc_area_msb[1] = 0xFE; - ati28800->svga.ksc5601_swap_mode = 0; + ati28800->svga.miscout = 1; + ati28800->svga.bpp = 8; + ati28800->svga.packed_chain4 = 1; + ati28800->svga.ksc5601_sbyte_mask = 0; + ati28800->svga.ksc5601_udc_area_msb[0] = 0xC9; + ati28800->svga.ksc5601_udc_area_msb[1] = 0xFE; + ati28800->svga.ksc5601_swap_mode = 0; ati28800->svga.ksc5601_english_font_type = 0; ati_eeprom_load(&ati28800->eeprom, "atikorvga.nvr", 0); @@ -566,7 +604,6 @@ ati28800k_init(const device_t *info) return ati28800; } - static void * ati28800_init(const device_t *info) { @@ -578,258 +615,270 @@ ati28800_init(const device_t *info) ati28800->memory = device_get_config_int("memory"); - ati28800->type = info->local; + ati28800->type = info->local; - switch(ati28800->type) { - case VGAWONDERXL: - ati28800->id = 5; - rom_init(&ati28800->bios_rom, - BIOS_VGAXL_ROM_PATH, - 0xc0000, 0x8000, 0x7fff, - 0, MEM_MAPPING_EXTERNAL); - ati28800->svga.ramdac = device_add(&sc11486_ramdac_device); - break; + switch (ati28800->type) { + case VGAWONDERXL: + ati28800->id = 5; + rom_init(&ati28800->bios_rom, + BIOS_VGAXL_ROM_PATH, + 0xc0000, 0x8000, 0x7fff, + 0, MEM_MAPPING_EXTERNAL); + ati28800->svga.ramdac = device_add(&sc11486_ramdac_device); + break; #if defined(DEV_BRANCH) && defined(USE_XL24) - case VGAWONDERXL24: - ati28800->id = 6; - rom_init_interleaved(&ati28800->bios_rom, - BIOS_XL24_EVEN_PATH, - BIOS_XL24_ODD_PATH, - 0xc0000, 0x10000, 0xffff, - 0, MEM_MAPPING_EXTERNAL); - break; + case VGAWONDERXL24: + ati28800->id = 6; + rom_init_interleaved(&ati28800->bios_rom, + BIOS_XL24_EVEN_PATH, + BIOS_XL24_ODD_PATH, + 0xc0000, 0x10000, 0xffff, + 0, MEM_MAPPING_EXTERNAL); + break; #endif - default: - ati28800->id = 5; - rom_init(&ati28800->bios_rom, - BIOS_ROM_PATH, - 0xc0000, 0x8000, 0x7fff, - 0, MEM_MAPPING_EXTERNAL); - break; + default: + ati28800->id = 5; + rom_init(&ati28800->bios_rom, + BIOS_ROM_PATH, + 0xc0000, 0x8000, 0x7fff, + 0, MEM_MAPPING_EXTERNAL); + break; } svga_init(info, &ati28800->svga, ati28800, ati28800->memory << 10, /*default: 512kb*/ - ati28800_recalctimings, - ati28800_in, ati28800_out, - NULL, - NULL); - - io_sethandler(0x01ce, 2, - ati28800_in, NULL, NULL, - ati28800_out, NULL, NULL, ati28800); - io_sethandler(0x03c0, 32, - ati28800_in, NULL, NULL, - ati28800_out, NULL, NULL, ati28800); + ati28800_recalctimings, + ati28800_in, ati28800_out, + NULL, + NULL); - ati28800->svga.miscout = 1; - ati28800->svga.bpp = 8; - ati28800->svga.packed_chain4 = 1; + io_sethandler(0x01ce, 2, + ati28800_in, NULL, NULL, + ati28800_out, NULL, NULL, ati28800); + io_sethandler(0x03c0, 32, + ati28800_in, NULL, NULL, + ati28800_out, NULL, NULL, ati28800); + + ati28800->svga.miscout = 1; + ati28800->svga.bpp = 8; + ati28800->svga.packed_chain4 = 1; switch (ati28800->type) { - case VGAWONDERXL: - ati_eeprom_load(&ati28800->eeprom, "ati28800xl.nvr", 0); - break; + case VGAWONDERXL: + ati_eeprom_load(&ati28800->eeprom, "ati28800xl.nvr", 0); + break; #if defined(DEV_BRANCH) && defined(USE_XL24) - case VGAWONDERXL24: - ati_eeprom_load(&ati28800->eeprom, "ati28800xl24.nvr", 0); - break; + case VGAWONDERXL24: + ati_eeprom_load(&ati28800->eeprom, "ati28800xl24.nvr", 0); + break; #endif - default: - ati_eeprom_load(&ati28800->eeprom, "ati28800.nvr", 0); - break; - } + default: + ati_eeprom_load(&ati28800->eeprom, "ati28800.nvr", 0); + break; + } - return(ati28800); + return ati28800; } - static int ati28800_available(void) { - return(rom_present(BIOS_ROM_PATH)); + return (rom_present(BIOS_ROM_PATH)); } - static int ati28800k_available(void) { - return ((rom_present(BIOS_ATIKOR_PATH) && rom_present(FONT_ATIKOR_PATH))); + return (rom_present(BIOS_ATIKOR_PATH) && rom_present(FONT_ATIKOR_PATH)); } - static int compaq_ati28800_available(void) { - return((rom_present(BIOS_VGAXL_ROM_PATH))); + return (rom_present(BIOS_VGAXL_ROM_PATH)); } - #if defined(DEV_BRANCH) && defined(USE_XL24) static int ati28800_wonderxl24_available(void) { - return((rom_present(BIOS_XL24_EVEN_PATH) && rom_present(BIOS_XL24_ODD_PATH))); + return (rom_present(BIOS_XL24_EVEN_PATH) && rom_present(BIOS_XL24_ODD_PATH)); } #endif - static void ati28800_close(void *priv) { - ati28800_t *ati28800 = (ati28800_t *)priv; + ati28800_t *ati28800 = (ati28800_t *) priv; svga_close(&ati28800->svga); free(ati28800); } - static void -ati28800_speed_changed(void *p) +ati28800_speed_changed(void *priv) { - ati28800_t *ati28800 = (ati28800_t *)p; - - svga_recalctimings(&ati28800->svga); -} + ati28800_t *ati28800 = (ati28800_t *) priv; + svga_recalctimings(&ati28800->svga); +} static void ati28800_force_redraw(void *priv) { - ati28800_t *ati28800 = (ati28800_t *)priv; + ati28800_t *ati28800 = (ati28800_t *) priv; ati28800->svga.fullchange = changeframecount; } - -static const device_config_t ati28800_config[] = -{ - { - "memory", "Memory size", CONFIG_SELECTION, "", 512, "", { 0 }, - { - { - "256 kB", 256 - }, - { - "512 kB", 512 - }, - { - "1 MB", 1024 - }, - { - "" - } - } - }, - { - "", "", -1 +// clang-format off +static const device_config_t ati28800_config[] = { + { + .name = "memory", + .description = "Memory size", + .type = CONFIG_SELECTION, + .default_int = 512, + .selection = { + { + .description = "256 kB", + .value = 256 + }, + { + .description = "512 kB", + .value = 512 + }, + { + .description = "1 MB", + .value = 1024 + }, + { + .description = "" + } } + }, + { + .type = CONFIG_END + } }; #if defined(DEV_BRANCH) && defined(USE_XL24) -static const device_config_t ati28800_wonderxl_config[] = -{ - { - "memory", "Memory size", CONFIG_SELECTION, "", 512, "", { 0 }, - { - { - "256 kB", 256 - }, - { - "512 kB", 512 - }, - { - "1 MB", 1024 - }, - { - "" - } - } - }, - { - "", "", -1 +static const device_config_t ati28800_wonderxl_config[] = { + { + .name = "memory", + .description = "Memory size", + .type = CONFIG_SELECTION, + .default_int = 512, + .selection = { + { + .description = "256 kB", + .value = 256 + }, + { + .description = "512 kB", + .value = 512 + }, + { + .description = "1 MB", + .value = 1024 + }, + { + .description = "" + } } + }, + { + .type = CONFIG_END + } }; #endif +// clang-format on -const device_t ati28800_device = -{ - "ATI 28800-5 (ATI VGA Charger)", - "ati28800", - DEVICE_ISA, - 0, - ati28800_init, ati28800_close, NULL, - { ati28800_available }, - ati28800_speed_changed, - ati28800_force_redraw, - ati28800_config +const device_t ati28800_device = { + .name = "ATI 28800-5 (ATI VGA Charger)", + .internal_name = "ati28800", + .flags = DEVICE_ISA, + .local = 0, + .init = ati28800_init, + .close = ati28800_close, + .reset = NULL, + { .available = ati28800_available }, + .speed_changed = ati28800_speed_changed, + .force_redraw = ati28800_force_redraw, + .config = ati28800_config }; -const device_t ati28800k_device = -{ - "ATI Korean VGA", - "ati28800k", - DEVICE_ISA, - 0, - ati28800k_init, ati28800_close, NULL, - { ati28800k_available }, - ati28800_speed_changed, - ati28800_force_redraw, - ati28800_config +const device_t ati28800k_device = { + .name = "ATI Korean VGA", + .internal_name = "ati28800k", + .flags = DEVICE_ISA, + .local = 0, + .init = ati28800k_init, + .close = ati28800_close, + .reset = NULL, + { .available = ati28800k_available }, + .speed_changed = ati28800_speed_changed, + .force_redraw = ati28800_force_redraw, + .config = ati28800_config }; -const device_t ati28800k_spc4620p_device = -{ - "ATI Korean VGA On-Board SPC-4620P", - "ati28800k_spc4620p", - DEVICE_ISA, - 1, - ati28800k_init, ati28800_close, NULL, - { NULL }, - ati28800_speed_changed, - ati28800_force_redraw +const device_t ati28800k_spc4620p_device = { + .name = "ATI Korean VGA On-Board SPC-4620P", + .internal_name = "ati28800k_spc4620p", + .flags = DEVICE_ISA, + .local = 1, + .init = ati28800k_init, + .close = ati28800_close, + .reset = NULL, + { .available = NULL }, + .speed_changed = ati28800_speed_changed, + .force_redraw = ati28800_force_redraw, + .config = NULL }; -const device_t ati28800k_spc6033p_device = -{ - "ATI Korean VGA On-Board SPC-6033P", - "ati28800k_spc6033p", - DEVICE_ISA, - 2, - ati28800k_init, ati28800_close, NULL, - { NULL }, - ati28800_speed_changed, - ati28800_force_redraw +const device_t ati28800k_spc6033p_device = { + .name = "ATI Korean VGA On-Board SPC-6033P", + .internal_name = "ati28800k_spc6033p", + .flags = DEVICE_ISA, + .local = 2, + .init = ati28800k_init, + .close = ati28800_close, + .reset = NULL, + { .available = NULL }, + .speed_changed = ati28800_speed_changed, + .force_redraw = ati28800_force_redraw, + .config = NULL }; -const device_t compaq_ati28800_device = -{ - "ATI 28800-5 (ATI VGA Wonder XL)", - "compaq_ati28800", - DEVICE_ISA, - VGAWONDERXL, - ati28800_init, ati28800_close, NULL, - { compaq_ati28800_available }, - ati28800_speed_changed, - ati28800_force_redraw, - ati28800_config +const device_t compaq_ati28800_device = { + .name = "ATI 28800-5 (ATI VGA Wonder XL)", + .internal_name = "compaq_ati28800", + .flags = DEVICE_ISA, + .local = VGAWONDERXL, + .init = ati28800_init, + .close = ati28800_close, + .reset = NULL, + { .available = compaq_ati28800_available }, + .speed_changed = ati28800_speed_changed, + .force_redraw = ati28800_force_redraw, + .config = ati28800_config }; #if defined(DEV_BRANCH) && defined(USE_XL24) -const device_t ati28800_wonderxl24_device = -{ - "ATI-28800 (VGA Wonder XL24)", - "ati28800w", - DEVICE_ISA, - VGAWONDERXL24, - ati28800_init, ati28800_close, NULL, - { ati28800_wonderxl24_available }, - ati28800_speed_changed, - ati28800_force_redraw, - ati28800_wonderxl_config +const device_t ati28800_wonderxl24_device = { + .name = "ATI-28800 (VGA Wonder XL24)", + .internal_name = "ati28800w", + .flags = DEVICE_ISA, + .local = VGAWONDERXL24, + .init = ati28800_init, + .close = ati28800_close, + .reset = NULL, + { .available = ati28800_wonderxl24_available }, + .speed_changed = ati28800_speed_changed, + .force_redraw = ati28800_force_redraw, + .config = ati28800_wonderxl_config }; #endif diff --git a/src/video/vid_ati68860_ramdac.c b/src/video/vid_ati68860_ramdac.c index 2a7299d00..8b4c4924b 100644 --- a/src/video/vid_ati68860_ramdac.c +++ b/src/video/vid_ati68860_ramdac.c @@ -1,40 +1,40 @@ /* - * 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. + * 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. + * This file is part of the 86Box distribution. * - * ATI 68860 RAMDAC emulation (for Mach64) + * ATI 68860 RAMDAC emulation (for Mach64) * - * ATI 68860/68880 Truecolor DACs: - * REG08 (R/W): - * bit 0-? Always 2 ?? + * ATI 68860/68880 Truecolor DACs: + * REG08 (R/W): + * bit 0-? Always 2 ?? * - * REG0A (R/W): - * bit 0-? Always 1Dh ?? + * REG0A (R/W): + * bit 0-? Always 1Dh ?? * - * REG0B (R/W): (GMR ?) - * bit 0-7 Mode. 82h: 4bpp, 83h: 8bpp, - * A0h: 15bpp, A1h: 16bpp, C0h: 24bpp, - * E3h: 32bpp (80h for VGA modes ?) - * - * REG0C (R/W): Device Setup Register A - * bit 0 Controls 6/8bit DAC. 0: 8bit DAC/LUT, 1: 6bit DAC/LUT - * 2-3 Depends on Video memory (= VRAM width ?) . - * 1: Less than 1Mb, 2: 1Mb, 3: > 1Mb - * 5-6 Always set ? - * 7 If set can remove "snow" in some cases - * (A860_Delay_L ?) ?? + * REG0B (R/W): (GMR ?) + * bit 0-7 Mode. 82h: 4bpp, 83h: 8bpp, + * A0h: 15bpp, A1h: 16bpp, C0h: 24bpp, + * E3h: 32bpp (80h for VGA modes ?) + * + * REG0C (R/W): Device Setup Register A + * bit 0 Controls 6/8bit DAC. 0: 8bit DAC/LUT, 1: 6bit DAC/LUT + * 2-3 Depends on Video memory (= VRAM width ?) . + * 1: Less than 1Mb, 2: 1Mb, 3: > 1Mb + * 5-6 Always set ? + * 7 If set can remove "snow" in some cases + * (A860_Delay_L ?) ?? * * * - * Authors: Sarah Walker, - * Miran Grca, + * Authors: Sarah Walker, + * Miran Grca, * - * Copyright 2008-2018 Sarah Walker. - * Copyright 2016-2018 Miran Grca. + * Copyright 2008-2018 Sarah Walker. + * Copyright 2016-2018 Miran Grca. */ #include #include @@ -46,178 +46,190 @@ #include <86box/mem.h> #include <86box/timer.h> #include <86box/video.h> +#include <86box/vid_8514a.h> #include <86box/vid_svga.h> #include <86box/vid_svga_render.h> +#include <86box/plat_unused.h> - -typedef struct ati68860_ramdac_t -{ +typedef struct ati68860_ramdac_t { uint8_t regs[16]; void (*render)(struct svga_t *svga); - int dac_addr, dac_pos; - int dac_r, dac_g; - PALETTE pal; + int dac_addr; + int dac_pos; + int dac_r; + int dac_g; + PALETTE pal; uint32_t pallook[2]; int ramdac_type; } ati68860_ramdac_t; - void -ati68860_ramdac_out(uint16_t addr, uint8_t val, void *p, svga_t *svga) +ati68860_ramdac_out(uint16_t addr, uint8_t val, void *priv, svga_t *svga) { - ati68860_ramdac_t *ramdac = (ati68860_ramdac_t *) p; + ati68860_ramdac_t *ramdac = (ati68860_ramdac_t *) priv; + const ibm8514_t *dev = (ibm8514_t *) svga->dev8514; switch (addr) { - case 0: - svga_out(0x3c8, val, svga); - break; - case 1: - svga_out(0x3c9, val, svga); - break; - case 2: - svga_out(0x3c6, val, svga); - break; - case 3: - svga_out(0x3c7, val, svga); - break; - default: - ramdac->regs[addr & 0xf] = val; - switch (addr & 0xf) { - case 0x4: - ramdac->dac_addr = val; - ramdac->dac_pos = 0; - break; - case 0x5: - switch (ramdac->dac_pos) { - case 0: - ramdac->dac_r = val; - ramdac->dac_pos++; - break; - case 1: - ramdac->dac_g = val; - ramdac->dac_pos++; - break; - case 2: - if (ramdac->dac_addr > 1) - break; - ramdac->pal[ramdac->dac_addr].r = ramdac->dac_r; - ramdac->pal[ramdac->dac_addr].g = ramdac->dac_g; - ramdac->pal[ramdac->dac_addr].b = val; - if (ramdac->ramdac_type == RAMDAC_8BIT) - ramdac->pallook[ramdac->dac_addr] = makecol32(ramdac->pal[ramdac->dac_addr].r, - ramdac->pal[ramdac->dac_addr].g, - ramdac->pal[ramdac->dac_addr].b); - else - ramdac->pallook[ramdac->dac_addr] = makecol32(video_6to8[ramdac->pal[ramdac->dac_addr].r & 0x3f], - video_6to8[ramdac->pal[ramdac->dac_addr].g & 0x3f], - video_6to8[ramdac->pal[ramdac->dac_addr].b & 0x3f]); - ramdac->dac_pos = 0; - ramdac->dac_addr = (ramdac->dac_addr + 1) & 255; - break; - } - break; - case 0xb: - switch (val) { - case 0x82: - ramdac->render = svga_render_4bpp_highres; - break; - case 0x83: - ramdac->render = svga_render_8bpp_highres; - break; - case 0xa0: case 0xb0: - ramdac->render = svga_render_15bpp_highres; - break; - case 0xa1: case 0xb1: - ramdac->render = svga_render_16bpp_highres; - break; - case 0xc0: case 0xd0: - ramdac->render = svga_render_24bpp_highres; - break; - case 0xe2: case 0xf7: - ramdac->render = svga_render_32bpp_highres; - break; - case 0xe3: - ramdac->render = svga_render_ABGR8888_highres; - break; - case 0xf2: - ramdac->render = svga_render_RGBA8888_highres; - break; - default: - ramdac->render = svga_render_8bpp_highres; - break; - } - break; - case 0xc: - svga_set_ramdac_type(svga, (val & 1) ? RAMDAC_6BIT : RAMDAC_8BIT); - break; - } - break; + case 0: + svga_out((dev && dev->on) ? 0x2ec : 0x3c8, val, svga); + break; + case 1: + svga_out((dev && dev->on) ? 0x2ed : 0x3c9, val, svga); + break; + case 2: + svga_out((dev && dev->on) ? 0x2ea : 0x3c6, val, svga); + break; + case 3: + svga_out((dev && dev->on) ? 0x2eb : 0x3c7, val, svga); + break; + default: + ramdac->regs[addr & 0xf] = val; + switch (addr & 0xf) { + case 0x4: + ramdac->dac_addr = val; + ramdac->dac_pos = 0; + break; + case 0x5: + switch (ramdac->dac_pos) { + case 0: + ramdac->dac_r = val; + ramdac->dac_pos++; + break; + case 1: + ramdac->dac_g = val; + ramdac->dac_pos++; + break; + case 2: + if (ramdac->dac_addr > 1) + break; + ramdac->pal[ramdac->dac_addr].r = ramdac->dac_r; + ramdac->pal[ramdac->dac_addr].g = ramdac->dac_g; + ramdac->pal[ramdac->dac_addr].b = val; + if (ramdac->ramdac_type == RAMDAC_8BIT) + ramdac->pallook[ramdac->dac_addr] = makecol32(ramdac->pal[ramdac->dac_addr].r, + ramdac->pal[ramdac->dac_addr].g, + ramdac->pal[ramdac->dac_addr].b); + else + ramdac->pallook[ramdac->dac_addr] = makecol32(video_6to8[ramdac->pal[ramdac->dac_addr].r & 0x3f], + video_6to8[ramdac->pal[ramdac->dac_addr].g & 0x3f], + video_6to8[ramdac->pal[ramdac->dac_addr].b & 0x3f]); + ramdac->dac_pos = 0; + ramdac->dac_addr = (ramdac->dac_addr + 1) & 255; + break; + + default: + break; + } + break; + case 0xb: + switch (val) { + case 0x82: + ramdac->render = svga_render_4bpp_highres; + break; + case 0x83: + ramdac->render = svga_render_8bpp_highres; + break; + case 0xa0: + case 0xb0: + ramdac->render = svga_render_15bpp_highres; + break; + case 0xa1: + case 0xb1: + ramdac->render = svga_render_16bpp_highres; + break; + case 0xc0: + case 0xd0: + ramdac->render = svga_render_24bpp_highres; + break; + case 0xe2: + case 0xf7: + ramdac->render = svga_render_32bpp_highres; + break; + case 0xe3: + ramdac->render = svga_render_ABGR8888_highres; + break; + case 0xf2: + ramdac->render = svga_render_RGBA8888_highres; + break; + default: + ramdac->render = svga_render_8bpp_highres; + break; + } + break; + case 0xc: + svga_set_ramdac_type(svga, (val & 1) ? RAMDAC_6BIT : RAMDAC_8BIT); + break; + + default: + break; + } + break; } } uint8_t -ati68860_ramdac_in(uint16_t addr, void *p, svga_t *svga) +ati68860_ramdac_in(uint16_t addr, void *priv, svga_t *svga) { - ati68860_ramdac_t *ramdac = (ati68860_ramdac_t *) p; - uint8_t temp = 0; + const ati68860_ramdac_t *ramdac = (ati68860_ramdac_t *) priv; + const ibm8514_t *dev = (ibm8514_t *) svga->dev8514; + uint8_t temp = 0; switch (addr) { - case 0: - temp = svga_in(0x3c8, svga); - break; - case 1: - temp = svga_in(0x3c9, svga); - break; - case 2: - temp = svga_in(0x3c6, svga); - break; - case 3: - temp = svga_in(0x3c7, svga); - break; - case 4: case 8: - temp = 2; - break; - case 6: case 0xa: - temp = 0x1d; - break; - case 0xf: - temp = 0xd0; - break; + case 0: + temp = svga_in((dev && dev->on) ? 0x2ec : 0x3c8, svga); + break; + case 1: + temp = svga_in((dev && dev->on) ? 0x2ed : 0x3c9, svga); + break; + case 2: + temp = svga_in((dev && dev->on) ? 0x2ea : 0x3c6, svga); + break; + case 3: + temp = svga_in((dev && dev->on) ? 0x2eb : 0x3c7, svga); + break; + case 4: + case 8: + temp = 2; + break; + case 6: + case 0xa: + temp = 0x1d; + break; + case 0xf: + temp = 0xd0; + break; - default: - temp = ramdac->regs[addr & 0xf]; - break; + default: + temp = ramdac->regs[addr & 0xf]; + break; } return temp; } - void -ati68860_set_ramdac_type(void *p, int type) +ati68860_set_ramdac_type(void *priv, int type) { - ati68860_ramdac_t *ramdac = (ati68860_ramdac_t *) p; - int c; + ati68860_ramdac_t *ramdac = (ati68860_ramdac_t *) priv; if (ramdac->ramdac_type != type) { - ramdac->ramdac_type = type; + ramdac->ramdac_type = type; - for (c = 0; c < 2; c++) { - if (ramdac->ramdac_type == RAMDAC_8BIT) - ramdac->pallook[c] = makecol32(ramdac->pal[c].r, ramdac->pal[c].g, - ramdac->pal[c].b); - else - ramdac->pallook[c] = makecol32(video_6to8[ramdac->pal[c].r & 0x3f], video_6to8[ramdac->pal[c].g & 0x3f], - video_6to8[ramdac->pal[c].b & 0x3f]); - } + for (uint8_t c = 0; c < 2; c++) { + if (ramdac->ramdac_type == RAMDAC_8BIT) + ramdac->pallook[c] = makecol32(ramdac->pal[c].r, ramdac->pal[c].g, + ramdac->pal[c].b); + else + ramdac->pallook[c] = makecol32(video_6to8[ramdac->pal[c].r & 0x3f], video_6to8[ramdac->pal[c].g & 0x3f], + video_6to8[ramdac->pal[c].b & 0x3f]); + } } } - static void * -ati68860_ramdac_init(const device_t *info) +ati68860_ramdac_init(UNUSED(const device_t *info)) { ati68860_ramdac_t *ramdac = (ati68860_ramdac_t *) malloc(sizeof(ati68860_ramdac_t)); memset(ramdac, 0, sizeof(ati68860_ramdac_t)); @@ -227,71 +239,79 @@ ati68860_ramdac_init(const device_t *info) return ramdac; } - void -ati68860_ramdac_set_render(void *p, svga_t *svga) +ati68860_ramdac_set_render(void *priv, svga_t *svga) { - ati68860_ramdac_t *ramdac = (ati68860_ramdac_t *) p; + ati68860_ramdac_t *ramdac = (ati68860_ramdac_t *) priv; svga->render = ramdac->render; } - void -ati68860_ramdac_set_pallook(void *p, int i, uint32_t col) +ati68860_ramdac_set_pallook(void *priv, int i, uint32_t col) { - ati68860_ramdac_t *ramdac = (ati68860_ramdac_t *) p; + ati68860_ramdac_t *ramdac = (ati68860_ramdac_t *) priv; ramdac->pallook[i] = col; } - void ati68860_hwcursor_draw(svga_t *svga, int displine) { - ati68860_ramdac_t *ramdac = (ati68860_ramdac_t *) svga->ramdac; - int x, offset; - uint8_t dat; - uint32_t col0 = ramdac->pallook[0]; - uint32_t col1 = ramdac->pallook[1]; + const ati68860_ramdac_t *ramdac = (ati68860_ramdac_t *) svga->ramdac; + int offset; + uint8_t dat; + uint32_t col0 = ramdac->pallook[0]; + uint32_t col1 = ramdac->pallook[1]; offset = svga->dac_hwcursor_latch.xoff; - for (x = 0; x < 64 - svga->dac_hwcursor_latch.xoff; x += 4) { - dat = svga->vram[svga->dac_hwcursor_latch.addr + (offset >> 2)]; - if (!(dat & 2)) buffer32->line[displine][svga->dac_hwcursor_latch.x + x + svga->x_add] = (dat & 1) ? col1 : col0; - else if ((dat & 3) == 3) buffer32->line[displine][svga->dac_hwcursor_latch.x + x + svga->x_add] ^= 0xFFFFFF; - dat >>= 2; - if (!(dat & 2)) buffer32->line[displine][svga->dac_hwcursor_latch.x + x + svga->x_add + 1] = (dat & 1) ? col1 : col0; - else if ((dat & 3) == 3) buffer32->line[displine][svga->dac_hwcursor_latch.x + x + svga->x_add + 1] ^= 0xFFFFFF; - dat >>= 2; - if (!(dat & 2)) buffer32->line[displine][svga->dac_hwcursor_latch.x + x + svga->x_add + 2] = (dat & 1) ? col1 : col0; - else if ((dat & 3) == 3) buffer32->line[displine][svga->dac_hwcursor_latch.x + x + svga->x_add + 2] ^= 0xFFFFFF; - dat >>= 2; - if (!(dat & 2)) buffer32->line[displine][svga->dac_hwcursor_latch.x + x + svga->x_add + 3] = (dat & 1) ? col1 : col0; - else if ((dat & 3) == 3) buffer32->line[displine][svga->dac_hwcursor_latch.x + x + svga->x_add + 3] ^= 0xFFFFFF; - dat >>= 2; - offset += 4; + for (uint32_t x = 0; x < 64 - svga->dac_hwcursor_latch.xoff; x += 4) { + dat = svga->vram[svga->dac_hwcursor_latch.addr + (offset >> 2)]; + if (!(dat & 2)) + buffer32->line[displine][svga->dac_hwcursor_latch.x + x + svga->x_add] = (dat & 1) ? col1 : col0; + else if ((dat & 3) == 3) + buffer32->line[displine][svga->dac_hwcursor_latch.x + x + svga->x_add] ^= 0xFFFFFF; + dat >>= 2; + if (!(dat & 2)) + buffer32->line[displine][svga->dac_hwcursor_latch.x + x + svga->x_add + 1] = (dat & 1) ? col1 : col0; + else if ((dat & 3) == 3) + buffer32->line[displine][svga->dac_hwcursor_latch.x + x + svga->x_add + 1] ^= 0xFFFFFF; + dat >>= 2; + if (!(dat & 2)) + buffer32->line[displine][svga->dac_hwcursor_latch.x + x + svga->x_add + 2] = (dat & 1) ? col1 : col0; + else if ((dat & 3) == 3) + buffer32->line[displine][svga->dac_hwcursor_latch.x + x + svga->x_add + 2] ^= 0xFFFFFF; + dat >>= 2; + if (!(dat & 2)) + buffer32->line[displine][svga->dac_hwcursor_latch.x + x + svga->x_add + 3] = (dat & 1) ? col1 : col0; + else if ((dat & 3) == 3) + buffer32->line[displine][svga->dac_hwcursor_latch.x + x + svga->x_add + 3] ^= 0xFFFFFF; + dat >>= 2; + offset += 4; } svga->dac_hwcursor_latch.addr += 16; } - static void ati68860_ramdac_close(void *priv) { ati68860_ramdac_t *ramdac = (ati68860_ramdac_t *) priv; if (ramdac) - free(ramdac); + free(ramdac); } - -const device_t ati68860_ramdac_device = -{ - "ATI-68860 RAMDAC", - "ati68860_ramdac", - 0, 0, - ati68860_ramdac_init, ati68860_ramdac_close, - NULL, { NULL }, NULL, NULL +const device_t ati68860_ramdac_device = { + .name = "ATI-68860 RAMDAC", + .internal_name = "ati68860_ramdac", + .flags = 0, + .local = 0, + .init = ati68860_ramdac_init, + .close = ati68860_ramdac_close, + .reset = NULL, + { .available = NULL }, + .speed_changed = NULL, + .force_redraw = NULL, + .config = NULL }; diff --git a/src/video/vid_ati68875_ramdac.c b/src/video/vid_ati68875_ramdac.c new file mode 100644 index 000000000..447a8eca8 --- /dev/null +++ b/src/video/vid_ati68875_ramdac.c @@ -0,0 +1,167 @@ +/* + * 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 Mach32-compatible ATI 68875 RAMDAC and clones. + * + * + * + * Authors: TheCollector1995. + * + * Copyright 2022-2023 TheCollector1995. + */ +#include +#include +#include +#include +#include +#include <86box/86box.h> +#include <86box/device.h> +#include <86box/mem.h> +#include <86box/timer.h> +#include <86box/video.h> +#include <86box/vid_svga.h> +#include <86box/vid_svga_render.h> +#include <86box/plat_unused.h> + +typedef struct ati68875_ramdac_t { + uint8_t gen_cntl; + uint8_t in_clk_sel; + uint8_t out_clk_sel; + uint8_t mux_cntl; + uint8_t palette_page_sel; + uint8_t test_reg; +} ati68875_ramdac_t; + +void +ati68875_ramdac_out(uint16_t addr, int rs2, int rs3, uint8_t val, void *priv, svga_t *svga) +{ + ati68875_ramdac_t *ramdac = (ati68875_ramdac_t *) priv; + uint8_t rs = (addr & 0x03); + + rs |= (!!rs2 << 2); + rs |= (!!rs3 << 3); + + switch (rs) { + case 0x00: /* Palette Write Index Register (RS value = 0000) */ + case 0x01: /* Palette Data Register (RS value = 0001) */ + case 0x02: /* Pixel Read Mask Register (RS value = 0010) */ + case 0x03: + svga_out(addr, val, svga); + break; + case 0x08: /* General Control Register (RS value = 1000) */ + ramdac->gen_cntl = val; + break; + case 0x09: /* Input Clock Selection Register (RS value = 1001) */ + ramdac->in_clk_sel = val; + break; + case 0x0a: /* Output Clock Selection Register (RS value = 1010) */ + ramdac->out_clk_sel = val; + break; + case 0x0b: /* MUX Control Register (RS value = 1011) */ + ramdac->mux_cntl = val; + break; + case 0x0c: /* Palette Page Register (RS value = 1100) */ + ramdac->palette_page_sel = val; + break; + case 0x0e: /* Test Register (RS value = 1110) */ + ramdac->test_reg = val; + break; + case 0x0f: /* Reset State (RS value = 1111) */ + ramdac->mux_cntl = 0x2d; + break; + + default: + break; + } + + return; +} + +uint8_t +ati68875_ramdac_in(uint16_t addr, int rs2, int rs3, void *priv, svga_t *svga) +{ + const ati68875_ramdac_t *ramdac = (ati68875_ramdac_t *) priv; + uint8_t rs = (addr & 0x03); + uint8_t temp = 0; + + rs |= (!!rs2 << 2); + rs |= (!!rs3 << 3); + + switch (rs) { + case 0x00: /* Palette Write Index Register (RS value = 0000) */ + case 0x01: /* Palette Data Register (RS value = 0001) */ + case 0x02: /* Pixel Read Mask Register (RS value = 0010) */ + case 0x03: + temp = svga_in(addr, svga); + break; + case 0x08: /* General Control Register (RS value = 1000) */ + temp = ramdac->gen_cntl; + break; + case 0x09: /* Input Clock Selection Register (RS value = 1001) */ + temp = ramdac->in_clk_sel; + break; + case 0x0a: /* Output Clock Selection Register (RS value = 1010) */ + temp = ramdac->out_clk_sel; + break; + case 0x0b: /* MUX Control Register (RS value = 1011) */ + temp = ramdac->mux_cntl; + break; + case 0x0c: /* Palette Page Register (RS value = 1100) */ + temp = ramdac->palette_page_sel; + break; + case 0x0e: /* Test Register (RS value = 1110) */ + switch (ramdac->test_reg & 0x07) { + case 0x03: + temp = 0x75; + break; + + default: + break; + } + break; + + default: + break; + } + + return temp; +} + +static void * +ati68875_ramdac_init(UNUSED(const device_t *info)) +{ + ati68875_ramdac_t *ramdac = (ati68875_ramdac_t *) malloc(sizeof(ati68875_ramdac_t)); + memset(ramdac, 0, sizeof(ati68875_ramdac_t)); + + ramdac->mux_cntl = 0x2d; + + return ramdac; +} + +static void +ati68875_ramdac_close(void *priv) +{ + ati68875_ramdac_t *ramdac = (ati68875_ramdac_t *) priv; + + if (ramdac) + free(ramdac); +} + +const device_t ati68875_ramdac_device = { + .name = "ATI 68875 RAMDAC", + .internal_name = "ati68875_ramdac", + .flags = 0, + .local = 0, + .init = ati68875_ramdac_init, + .close = ati68875_ramdac_close, + .reset = NULL, + { .available = NULL }, + .speed_changed = NULL, + .force_redraw = NULL, + .config = NULL +}; diff --git a/src/video/vid_ati_eeprom.c b/src/video/vid_ati_eeprom.c index 3d14474f2..054d83d36 100644 --- a/src/video/vid_ati_eeprom.c +++ b/src/video/vid_ati_eeprom.c @@ -1,20 +1,20 @@ /* - * 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. + * 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. + * This file is part of the 86Box distribution. * - * Emulation of the EEPROM on select ATI cards. + * Emulation of the EEPROM on select ATI cards. * * * - * Authors: Sarah Walker, - * Miran Grca, + * Authors: Sarah Walker, + * Miran Grca, * - * Copyright 2008-2020 Sarah Walker. - * Copyright 2016-2020 Miran Grca. + * Copyright 2008-2020 Sarah Walker. + * Copyright 2016-2020 Miran Grca. */ #include #include @@ -26,186 +26,204 @@ #include <86box/timer.h> #include <86box/nvr.h> #include <86box/vid_ati_eeprom.h> +#include <86box/plat_fallthrough.h> - -void ati_eeprom_load(ati_eeprom_t *eeprom, char *fn, int type) +void +ati_eeprom_load(ati_eeprom_t *eeprom, char *fn, int type) { - FILE *f; - int size; - eeprom->type = type; - strncpy(eeprom->fn, fn, sizeof(eeprom->fn) - 1); - f = nvr_fopen(eeprom->fn, "rb"); - size = eeprom->type ? 512 : 128; - if (!f) { - memset(eeprom->data, 0xff, size); - return; - } - if (fread(eeprom->data, 1, size, f) != size) - memset(eeprom->data, 0, size); - fclose(f); + FILE *fp; + int size; + eeprom->type = type; + strncpy(eeprom->fn, fn, sizeof(eeprom->fn) - 1); + fp = nvr_fopen(eeprom->fn, "rb"); + size = eeprom->type ? 512 : 128; + if (!fp) { + memset(eeprom->data, 0xff, size); + return; + } + if (fread(eeprom->data, 1, size, fp) != size) + memset(eeprom->data, 0, size); + fclose(fp); } -void ati_eeprom_save(ati_eeprom_t *eeprom) +void +ati_eeprom_load_mach8(ati_eeprom_t *eeprom, char *fn) { - FILE *f = nvr_fopen(eeprom->fn, "wb"); - if (!f) return; - fwrite(eeprom->data, 1, eeprom->type ? 512 : 128, f); - fclose(f); + FILE *fp; + int size; + eeprom->type = 0; + strncpy(eeprom->fn, fn, sizeof(eeprom->fn) - 1); + fp = nvr_fopen(eeprom->fn, "rb"); + size = 128; + if (!fp) { /*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); + fp = nvr_fopen(eeprom->fn, "wb"); + fwrite(eeprom->data, 1, size, fp); + } + if (fread(eeprom->data, 1, size, fp) != size) + memset(eeprom->data, 0, size); + fclose(fp); } -void ati_eeprom_write(ati_eeprom_t *eeprom, int ena, int clk, int dat) +void +ati_eeprom_save(ati_eeprom_t *eeprom) { - int c; - if (!ena) - { - eeprom->out = 1; - } - if (clk && !eeprom->oldclk) - { - if (ena && !eeprom->oldena) - { - eeprom->state = EEPROM_WAIT; - eeprom->opcode = 0; - eeprom->count = 3; - eeprom->out = 1; - } - else if (ena) - { - switch (eeprom->state) - { - case EEPROM_WAIT: - if (!dat) + FILE *fp = nvr_fopen(eeprom->fn, "wb"); + if (!fp) + return; + fwrite(eeprom->data, 1, eeprom->type ? 512 : 128, fp); + fclose(fp); +} + +void +ati_eeprom_write(ati_eeprom_t *eeprom, int ena, int clk, int dat) +{ + if (!ena) { + eeprom->out = 1; + } + if (clk && !eeprom->oldclk) { + if (ena && !eeprom->oldena) { + eeprom->state = EEPROM_WAIT; + eeprom->opcode = 0; + eeprom->count = 3; + eeprom->out = 1; + } else if (ena) { + switch (eeprom->state) { + case EEPROM_WAIT: + if (!dat) + break; + eeprom->state = EEPROM_OPCODE; + fallthrough; + case EEPROM_OPCODE: + eeprom->opcode = (eeprom->opcode << 1) | (dat ? 1 : 0); + eeprom->count--; + if (!eeprom->count) { + switch (eeprom->opcode) { + case EEPROM_OP_WRITE: + eeprom->count = eeprom->type ? 24 : 22; + eeprom->state = EEPROM_INPUT; + eeprom->dat = 0; + break; + case EEPROM_OP_READ: + eeprom->count = eeprom->type ? 8 : 6; + eeprom->state = EEPROM_INPUT; + eeprom->dat = 0; + break; + case EEPROM_OP_EW: + eeprom->count = 2; + eeprom->state = EEPROM_INPUT; + eeprom->dat = 0; + break; + case EEPROM_OP_ERASE: + eeprom->count = eeprom->type ? 8 : 6; + eeprom->state = EEPROM_INPUT; + eeprom->dat = 0; + break; + + default: + break; + } + } + break; + + case EEPROM_INPUT: + eeprom->dat = (eeprom->dat << 1) | (dat ? 1 : 0); + eeprom->count--; + if (!eeprom->count) { + switch (eeprom->opcode) { + case EEPROM_OP_WRITE: + if (!eeprom->wp) { + eeprom->data[(eeprom->dat >> 16) & (eeprom->type ? 255 : 63)] = eeprom->dat & 0xffff; + ati_eeprom_save(eeprom); + } + eeprom->state = EEPROM_IDLE; + eeprom->out = 1; + break; + + case EEPROM_OP_READ: + eeprom->count = 17; + eeprom->state = EEPROM_OUTPUT; + eeprom->dat = eeprom->data[eeprom->dat]; + break; + case EEPROM_OP_EW: + switch (eeprom->dat) { + case EEPROM_OP_EWDS: + eeprom->wp = 1; break; - eeprom->state = EEPROM_OPCODE; - /* fall through */ - case EEPROM_OPCODE: - eeprom->opcode = (eeprom->opcode << 1) | (dat ? 1 : 0); - eeprom->count--; - if (!eeprom->count) - { - switch (eeprom->opcode) - { - case EEPROM_OP_WRITE: - eeprom->count = eeprom->type ? 24 : 22; - eeprom->state = EEPROM_INPUT; - eeprom->dat = 0; - break; - case EEPROM_OP_READ: - eeprom->count = eeprom->type ? 8 : 6; - eeprom->state = EEPROM_INPUT; - eeprom->dat = 0; - break; - case EEPROM_OP_EW: - eeprom->count = 2; - eeprom->state = EEPROM_INPUT; - eeprom->dat = 0; - break; - case EEPROM_OP_ERASE: - eeprom->count = eeprom->type ? 8 : 6; - eeprom->state = EEPROM_INPUT; - eeprom->dat = 0; - break; + case EEPROM_OP_WRAL: + eeprom->opcode = EEPROM_OP_WRALMAIN; + eeprom->count = 20; + break; + case EEPROM_OP_ERAL: + if (!eeprom->wp) { + memset(eeprom->data, 0xff, 128); + ati_eeprom_save(eeprom); } + break; + case EEPROM_OP_EWEN: + eeprom->wp = 0; + break; + + default: + break; } + eeprom->state = EEPROM_IDLE; + eeprom->out = 1; break; - - case EEPROM_INPUT: - eeprom->dat = (eeprom->dat << 1) | (dat ? 1 : 0); - eeprom->count--; - if (!eeprom->count) - { - switch (eeprom->opcode) - { - case EEPROM_OP_WRITE: - if (!eeprom->wp) - { - eeprom->data[(eeprom->dat >> 16) & (eeprom->type ? 255 : 63)] = eeprom->dat & 0xffff; - ati_eeprom_save(eeprom); - } - eeprom->state = EEPROM_IDLE; - eeprom->out = 1; - break; - case EEPROM_OP_READ: - eeprom->count = 17; - eeprom->state = EEPROM_OUTPUT; - eeprom->dat = eeprom->data[eeprom->dat]; - break; - case EEPROM_OP_EW: - switch (eeprom->dat) - { - case EEPROM_OP_EWDS: - eeprom->wp = 1; - break; - case EEPROM_OP_WRAL: - eeprom->opcode = EEPROM_OP_WRALMAIN; - eeprom->count = 20; - break; - case EEPROM_OP_ERAL: - if (!eeprom->wp) - { - memset(eeprom->data, 0xff, 128); - ati_eeprom_save(eeprom); - } - break; - case EEPROM_OP_EWEN: - eeprom->wp = 0; - break; - } - eeprom->state = EEPROM_IDLE; - eeprom->out = 1; - break; - - case EEPROM_OP_ERASE: - if (!eeprom->wp) - { - eeprom->data[eeprom->dat] = 0xffff; - ati_eeprom_save(eeprom); - } - eeprom->state = EEPROM_IDLE; - eeprom->out = 1; - break; - - case EEPROM_OP_WRALMAIN: - if (!eeprom->wp) - { - for (c = 0; c < 256; c++) - eeprom->data[c] = eeprom->dat; - ati_eeprom_save(eeprom); - } - eeprom->state = EEPROM_IDLE; - eeprom->out = 1; - break; - } + case EEPROM_OP_ERASE: + if (!eeprom->wp) { + eeprom->data[eeprom->dat] = 0xffff; + ati_eeprom_save(eeprom); } + eeprom->state = EEPROM_IDLE; + eeprom->out = 1; + break; + + case EEPROM_OP_WRALMAIN: + if (!eeprom->wp) { + for (uint16_t c = 0; c < 256; c++) + eeprom->data[c] = eeprom->dat; + ati_eeprom_save(eeprom); + } + eeprom->state = EEPROM_IDLE; + eeprom->out = 1; + break; + + default: break; } - } - eeprom->oldena = ena; + } + break; + + default: + break; + } } - else if (!clk && eeprom->oldclk) - { - if (ena) - { - switch (eeprom->state) - { - case EEPROM_OUTPUT: - eeprom->out = (eeprom->dat & 0x10000) ? 1 : 0; - eeprom->dat <<= 1; - eeprom->count--; - if (!eeprom->count) - { - eeprom->state = EEPROM_IDLE; - } - break; - } - } + eeprom->oldena = ena; + } else if (!clk && eeprom->oldclk) { + if (ena) { + switch (eeprom->state) { + case EEPROM_OUTPUT: + eeprom->out = (eeprom->dat & 0x10000) ? 1 : 0; + eeprom->dat <<= 1; + eeprom->count--; + if (!eeprom->count) { + eeprom->state = EEPROM_IDLE; + } + break; + + default: + break; + } } - eeprom->oldclk = clk; + } + eeprom->oldclk = clk; } -int ati_eeprom_read(ati_eeprom_t *eeprom) +int +ati_eeprom_read(ati_eeprom_t *eeprom) { - return eeprom->out; + return eeprom->out; } - diff --git a/src/video/vid_ati_mach64.c b/src/video/vid_ati_mach64.c index 72493dc82..da1b5d556 100644 --- a/src/video/vid_ati_mach64.c +++ b/src/video/vid_ati_mach64.c @@ -1,20 +1,20 @@ /* - * 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. + * 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. + * This file is part of the 86Box distribution. * - * ATi Mach64 graphics card emulation. + * ATi Mach64 graphics card emulation. * * * - * Authors: Sarah Walker, - * Miran Grca, + * Authors: Sarah Walker, + * Miran Grca, * - * Copyright 2008-2019 Sarah Walker. - * Copyright 2016-2019 Miran Grca. + * Copyright 2008-2019 Sarah Walker. + * Copyright 2016-2019 Miran Grca. */ #include #include @@ -22,6 +22,7 @@ #include #include #include +#include #define HAVE_STDARG_H #include <86box/86box.h> #include <86box/device.h> @@ -31,6 +32,7 @@ #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> @@ -39,301 +41,335 @@ #include <86box/vid_ati_eeprom.h> #ifdef CLAMP -#undef CLAMP +# undef CLAMP #endif -#define BIOS_ROM_PATH "roms/video/mach64/bios.bin" -#define BIOS_ISA_ROM_PATH "roms/video/mach64/M64-1994.VBI" -#define BIOS_VLB_ROM_PATH "roms/video/mach64/mach64_vlb_vram.bin" -#define BIOS_ROMVT2_PATH "roms/video/mach64/atimach64vt2pci.bin" +#define BIOS_ROM_PATH "roms/video/mach64/bios.bin" +#define BIOS_ISA_ROM_PATH "roms/video/mach64/M64-1994.VBI" +#define BIOS_VLB_ROM_PATH "roms/video/mach64/mach64_vlb_vram.bin" +#define BIOS_ROMVT2_PATH "roms/video/mach64/atimach64vt2pci.bin" +#define FIFO_SIZE 65536 +#define FIFO_MASK (FIFO_SIZE - 1) +#define FIFO_ENTRY_SIZE (1 << 31) -#define FIFO_SIZE 65536 -#define FIFO_MASK (FIFO_SIZE - 1) -#define FIFO_ENTRY_SIZE (1 << 31) +#define FIFO_ENTRIES (mach64->fifo_write_idx - mach64->fifo_read_idx) +#define FIFO_FULL ((mach64->fifo_write_idx - mach64->fifo_read_idx) >= FIFO_SIZE) +#define FIFO_EMPTY (mach64->fifo_read_idx == mach64->fifo_write_idx) -#define FIFO_ENTRIES (mach64->fifo_write_idx - mach64->fifo_read_idx) -#define FIFO_FULL ((mach64->fifo_write_idx - mach64->fifo_read_idx) >= FIFO_SIZE) -#define FIFO_EMPTY (mach64->fifo_read_idx == mach64->fifo_write_idx) +#define FIFO_TYPE 0xff000000 +#define FIFO_ADDR 0x00ffffff -#define FIFO_TYPE 0xff000000 -#define FIFO_ADDR 0x00ffffff - -enum -{ - FIFO_INVALID = (0x00 << 24), - FIFO_WRITE_BYTE = (0x01 << 24), - FIFO_WRITE_WORD = (0x02 << 24), - FIFO_WRITE_DWORD = (0x03 << 24) +enum { + FIFO_INVALID = (0x00 << 24), + FIFO_WRITE_BYTE = (0x01 << 24), + FIFO_WRITE_WORD = (0x02 << 24), + FIFO_WRITE_DWORD = (0x03 << 24) }; -typedef struct -{ - uint32_t addr_type; - uint32_t val; +typedef struct fifo_entry_t { + uint32_t addr_type; + uint32_t val; } fifo_entry_t; -enum -{ - MACH64_GX = 0, - MACH64_VT2 +enum { + MACH64_GX = 0, + MACH64_VT2 }; -typedef struct mach64_t -{ - mem_mapping_t linear_mapping; - mem_mapping_t mmio_mapping; - mem_mapping_t mmio_linear_mapping; - mem_mapping_t mmio_linear_mapping_2; +typedef struct mach64_t { + mem_mapping_t linear_mapping; + mem_mapping_t mmio_mapping; + mem_mapping_t mmio_linear_mapping; + mem_mapping_t mmio_linear_mapping_2; - ati_eeprom_t eeprom; - svga_t svga; - - rom_t bios_rom; - - uint8_t regs[256]; - int index; + ati_eeprom_t eeprom; + svga_t svga; - int type, pci, - bit32; - - uint8_t pci_regs[256]; - uint8_t int_line; - int card; + rom_t bios_rom; - int bank_r[2]; - int bank_w[2]; + uint8_t regs[256]; + int index; - uint32_t vram_size; - uint32_t vram_mask; - - uint32_t config_cntl; + int type; + int pci; - uint32_t context_load_cntl; - uint32_t context_mask; - - uint32_t crtc_gen_cntl; - uint8_t crtc_int_cntl; - uint32_t crtc_h_total_disp; - uint32_t crtc_v_sync_strt_wid; - uint32_t crtc_v_total_disp; - uint32_t crtc_off_pitch; + uint8_t pci_slot; + uint8_t irq_state; - uint32_t clock_cntl; + uint8_t pci_regs[256]; + uint8_t int_line; - uint32_t clr_cmp_clr; - uint32_t clr_cmp_cntl; - uint32_t clr_cmp_mask; + int bank_r[2]; + int bank_w[2]; + + uint32_t vram_size; + uint32_t vram_mask; + + uint32_t config_cntl; + + uint32_t context_load_cntl; + uint32_t context_mask; + + uint32_t crtc_gen_cntl; + uint8_t crtc_int_cntl; + uint32_t crtc_h_total_disp; + uint32_t crtc_v_sync_strt_wid; + uint32_t crtc_v_total_disp; + uint32_t crtc_off_pitch; + + uint32_t clock_cntl; + + uint32_t clr_cmp_clr; + uint32_t clr_cmp_cntl; + uint32_t clr_cmp_mask; + + uint32_t cur_horz_vert_off; + uint32_t cur_horz_vert_posn; + uint32_t cur_offset; + + uint32_t dac_cntl; + + uint32_t dp_bkgd_clr; + uint32_t dp_frgd_clr; + uint32_t dp_mix; + uint32_t dp_pix_width; + uint32_t dp_src; + + uint32_t dst_bres_lnth; + uint32_t dst_bres_dec; + uint32_t dst_bres_err; + uint32_t dst_bres_inc; + + uint32_t dst_cntl; + uint32_t dst_height_width; + uint32_t dst_off_pitch; + uint32_t dst_y_x; + + uint32_t gen_test_cntl; + + uint32_t gui_traj_cntl; + + uint32_t host_cntl; + + uint32_t mem_cntl; + + uint32_t ovr_clr; + uint32_t ovr_wid_left_right; + uint32_t ovr_wid_top_bottom; + + uint32_t pat_cntl; + uint32_t pat_reg0; + uint32_t pat_reg1; + + uint32_t sc_left_right; + uint32_t sc_top_bottom; + + uint32_t scratch_reg0; + uint32_t scratch_reg1; + + uint32_t src_cntl; + uint32_t src_off_pitch; + uint32_t src_y_x; + uint32_t src_y_x_start; + uint32_t src_height1_width1; + uint32_t src_height2_width2; + + uint32_t write_mask; + uint32_t chain_mask; + + uint32_t linear_base; + uint32_t io_base; + + struct { + int op; + + int dst_x; + int dst_y; + int dst_x_start; + int dst_y_start; + int src_x; + int src_y; + int src_x_start; + int src_y_start; + int xinc; + int yinc; + int x_count; + int y_count; + int xx_count; + int src_x_count; + int src_y_count; + int src_width1; + int src_height1; + int src_width2; + int src_height2; + uint32_t src_offset; + uint32_t src_pitch; + uint32_t dst_offset; + uint32_t dst_pitch; + int mix_bg; + int mix_fg; + int source_bg; + int source_fg; + int source_mix; + int source_host; + int dst_width; + int dst_height; + int busy; + int pattern[8][8]; + uint8_t pattern_clr4x2[2][4]; + uint8_t pattern_clr8x1[8]; + int sc_left; + int sc_right; + int sc_top; + int sc_bottom; + int dst_pix_width; + int src_pix_width; + int host_pix_width; + int dst_size; + int src_size; + int host_size; + int temp_cnt; - uint32_t cur_horz_vert_off; - uint32_t cur_horz_vert_posn; - uint32_t cur_offset; - - uint32_t dac_cntl; - uint32_t dp_bkgd_clr; uint32_t dp_frgd_clr; - uint32_t dp_mix; - uint32_t dp_pix_width; - uint32_t dp_src; - - uint32_t dst_bres_lnth; - uint32_t dst_bres_dec; - uint32_t dst_bres_err; - uint32_t dst_bres_inc; - - uint32_t dst_cntl; - uint32_t dst_height_width; - uint32_t dst_off_pitch; - uint32_t dst_y_x; + uint32_t write_mask; - uint32_t gen_test_cntl; - - uint32_t gui_traj_cntl; + uint32_t clr_cmp_clr; + uint32_t clr_cmp_mask; + int clr_cmp_fn; + int clr_cmp_src; - uint32_t host_cntl; - - uint32_t mem_cntl; + int err; + int poly_draw; + } accel; - uint32_t ovr_clr; - uint32_t ovr_wid_left_right; - uint32_t ovr_wid_top_bottom; - - uint32_t pat_cntl; - uint32_t pat_reg0, pat_reg1; - - uint32_t sc_left_right, sc_top_bottom; - - uint32_t scratch_reg0, scratch_reg1; + fifo_entry_t fifo[FIFO_SIZE]; + atomic_int fifo_read_idx; + atomic_int fifo_write_idx; - uint32_t src_cntl; - uint32_t src_off_pitch; - uint32_t src_y_x; - uint32_t src_y_x_start; - uint32_t src_height1_width1, src_height2_width2; + thread_t *fifo_thread; + event_t *wake_fifo_thread; + event_t *fifo_not_full_event; + int blitter_busy; + uint64_t blitter_time; + uint64_t status_time; - uint32_t linear_base, old_linear_base; - uint32_t io_base; + uint16_t pci_id; + uint32_t config_chip_id; + uint32_t block_decoded_io; + int use_block_decoded_io; - struct - { - int op; - - int dst_x, dst_y; - int dst_x_start, dst_y_start; - int src_x, src_y; - int src_x_start, src_y_start; - int xinc, yinc; - int x_count, y_count; - int src_x_count, src_y_count; - int src_width1, src_height1; - int src_width2, src_height2; - uint32_t src_offset, src_pitch; - uint32_t dst_offset, dst_pitch; - int mix_bg, mix_fg; - int source_bg, source_fg, source_mix; - int source_host; - int dst_width, dst_height; - int busy; - int pattern[8][8]; - uint8_t pattern_clr4x2[2][4]; - uint8_t pattern_clr8x1[8]; - int sc_left, sc_right, sc_top, sc_bottom; - int dst_pix_width, src_pix_width, host_pix_width; - int dst_size, src_size, host_size; + int pll_addr; + uint8_t pll_regs[16]; + double pll_freq[4]; - uint32_t dp_bkgd_clr; - uint32_t dp_frgd_clr; + uint32_t config_stat0; - uint32_t clr_cmp_clr; - uint32_t clr_cmp_mask; - int clr_cmp_fn; - int clr_cmp_src; - - int err; - int poly_draw; - } accel; + uint32_t cur_clr0; + uint32_t cur_clr1; - int blitter_busy; - uint64_t blitter_time; - uint64_t status_time; - - uint16_t pci_id; - uint32_t config_chip_id; - uint32_t block_decoded_io; - int use_block_decoded_io; - - int pll_addr; - uint8_t pll_regs[16]; - double pll_freq[4]; - - uint32_t config_stat0; - - uint32_t cur_clr0, cur_clr1; - - uint32_t overlay_dat[1024]; - uint32_t overlay_graphics_key_clr, overlay_graphics_key_msk; - uint32_t overlay_video_key_clr, overlay_video_key_msk; - uint32_t overlay_key_cntl; - uint32_t overlay_scale_inc; - uint32_t overlay_scale_cntl; - uint32_t overlay_y_x_start, overlay_y_x_end; - - uint32_t scaler_height_width; - int scaler_format; - int scaler_update; - - uint32_t buf_offset[2], buf_pitch[2]; - - int overlay_v_acc; + uint32_t overlay_dat[1024]; + uint32_t overlay_graphics_key_clr; + uint32_t overlay_graphics_key_msk; + uint32_t overlay_video_key_clr; + uint32_t overlay_video_key_msk; + uint32_t overlay_key_cntl; + uint32_t overlay_scale_inc; + uint32_t overlay_scale_cntl; + uint32_t overlay_y_x_start; + uint32_t overlay_y_x_end; - uint8_t thread_run; - void *i2c, *ddc; + uint32_t scaler_height_width; + int scaler_format; + int scaler_update; + + uint32_t buf_offset[2]; + uint32_t buf_pitch[2]; + + int overlay_v_acc; + + uint8_t thread_run; + void *i2c; + void *ddc; } mach64_t; -static video_timings_t timing_mach64_isa = {VIDEO_ISA, 3, 3, 6, 5, 5, 10}; -static video_timings_t timing_mach64_vlb = {VIDEO_BUS, 2, 2, 1, 20, 20, 21}; -static video_timings_t timing_mach64_pci = {VIDEO_PCI, 2, 2, 1, 20, 20, 21}; +static video_timings_t timing_mach64_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_mach64_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_mach64_pci = { .type = VIDEO_PCI, .write_b = 2, .write_w = 2, .write_l = 1, .read_b = 20, .read_w = 20, .read_l = 21 }; -enum -{ - SRC_BG = 0, - SRC_FG = 1, - SRC_HOST = 2, - SRC_BLITSRC = 3, - SRC_PAT = 4 +enum { + SRC_BG = 0, + SRC_FG = 1, + SRC_HOST = 2, + SRC_BLITSRC = 3, + SRC_PAT = 4 }; -enum -{ - MONO_SRC_1 = 0, - MONO_SRC_PAT = 1, - MONO_SRC_HOST = 2, - MONO_SRC_BLITSRC = 3 +enum { + MONO_SRC_1 = 0, + MONO_SRC_PAT = 1, + MONO_SRC_HOST = 2, + MONO_SRC_BLITSRC = 3 }; -enum -{ - BPP_1 = 0, - BPP_4 = 1, - BPP_8 = 2, - BPP_15 = 3, - BPP_16 = 4, - BPP_32 = 5 +enum { + BPP_1 = 0, + BPP_4 = 1, + BPP_8 = 2, + BPP_15 = 3, + BPP_16 = 4, + BPP_24 = 5, + BPP_32 = 6 }; -enum -{ - OP_RECT, - OP_LINE +enum { + OP_RECT, + OP_LINE }; -enum -{ - SRC_PATT_EN = 1, - SRC_PATT_ROT_EN = 2, - SRC_LINEAR_EN = 4 +enum { + SRC_PATT_EN = 1, + SRC_PATT_ROT_EN = 2, + SRC_LINEAR_EN = 4 }; -enum -{ - DP_BYTE_PIX_ORDER = (1 << 24) +enum { + DP_BYTE_PIX_ORDER = (1 << 24) }; #define WIDTH_1BIT 3 -static int mach64_width[8] = {WIDTH_1BIT, 0, 0, 1, 1, 2, 2, 0}; +static int mach64_width[8] = { WIDTH_1BIT, 0, 0, 1, 1, 2, 2, 0 }; -enum -{ - DST_X_DIR = 0x01, - DST_Y_DIR = 0x02, - DST_Y_MAJOR = 0x04, - DST_X_TILE = 0x08, - DST_Y_TILE = 0x10, - DST_LAST_PEL = 0x20, - DST_POLYGON_EN = 0x40, - DST_24_ROT_EN = 0x80 +enum { + DST_X_DIR = 0x01, + DST_Y_DIR = 0x02, + DST_Y_MAJOR = 0x04, + DST_X_TILE = 0x08, + DST_Y_TILE = 0x10, + DST_LAST_PEL = 0x20, + DST_POLYGON_EN = 0x40, + DST_24_ROT_EN = 0x80 }; -enum -{ - HOST_BYTE_ALIGN = (1 << 0) +enum { + HOST_BYTE_ALIGN = (1 << 0) }; -void mach64_write(uint32_t addr, uint8_t val, void *priv); -void mach64_writew(uint32_t addr, uint16_t val, void *priv); -void mach64_writel(uint32_t addr, uint32_t val, void *priv); -uint8_t mach64_read(uint32_t addr, void *priv); +void mach64_write(uint32_t addr, uint8_t val, void *priv); +void mach64_writew(uint32_t addr, uint16_t val, void *priv); +void mach64_writel(uint32_t addr, uint32_t val, void *priv); +uint8_t mach64_read(uint32_t addr, void *priv); uint16_t mach64_readw(uint32_t addr, void *priv); uint32_t mach64_readl(uint32_t addr, void *priv); -void mach64_updatemapping(mach64_t *mach64); -void mach64_recalctimings(svga_t *svga); -void mach64_start_fill(mach64_t *mach64); -void mach64_start_line(mach64_t *mach64); -void mach64_blit(uint32_t cpu_dat, int count, mach64_t *mach64); -void mach64_load_context(mach64_t *mach64); +void mach64_updatemapping(mach64_t *mach64); +void mach64_recalctimings(svga_t *svga); +void mach64_start_fill(mach64_t *mach64); +void mach64_start_line(mach64_t *mach64); +void mach64_blit(uint32_t cpu_dat, int count, mach64_t *mach64); +void mach64_load_context(mach64_t *mach64); uint8_t mach64_ext_readb(uint32_t addr, void *priv); uint16_t mach64_ext_readw(uint32_t addr, void *priv); @@ -342,3198 +378,4274 @@ void mach64_ext_writeb(uint32_t addr, uint8_t val, void *priv); void mach64_ext_writew(uint32_t addr, uint16_t val, void *priv); void mach64_ext_writel(uint32_t addr, uint32_t val, void *priv); - #ifdef ENABLE_MACH64_LOG int mach64_do_log = ENABLE_MACH64_LOG; - static void mach64_log(const char *fmt, ...) { va_list ap; if (mach64_do_log) { - va_start(ap, fmt); - pclog_ex(fmt, ap); - va_end(ap); + va_start(ap, fmt); + pclog_ex(fmt, ap); + va_end(ap); } } #else -#define mach64_log(fmt, ...) +# define mach64_log(fmt, ...) #endif - -void mach64_out(uint16_t addr, uint8_t val, void *p) +void +mach64_out(uint16_t addr, uint8_t val, void *priv) { - mach64_t *mach64 = p; - svga_t *svga = &mach64->svga; - uint8_t old; - - if (((addr&0xFFF0) == 0x3D0 || (addr&0xFFF0) == 0x3B0) && !(svga->miscout & 1)) - addr ^= 0x60; + mach64_t *mach64 = priv; + svga_t *svga = &mach64->svga; + uint8_t old; - switch (addr) - { - case 0x1ce: - mach64->index = val; - break; - case 0x1cf: - mach64->regs[mach64->index & 0x3f] = val; - if ((mach64->index & 0x3f) == 0x36) + if (((addr & 0xFFF0) == 0x3D0 || (addr & 0xFFF0) == 0x3B0) && !(svga->miscout & 1)) + addr ^= 0x60; + + switch (addr) { + case 0x1ce: + mach64->index = val; + break; + case 0x1cf: + mach64->regs[mach64->index & 0x3f] = val; + if ((mach64->index & 0x3f) == 0x36) + svga_recalctimings(svga); + break; + + case 0x3C6: + case 0x3C7: + case 0x3C8: + case 0x3C9: + if (mach64->type == MACH64_GX) + ati68860_ramdac_out((addr & 3) | ((mach64->dac_cntl & 3) << 2), val, svga->ramdac, 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)) + mach64_updatemapping(mach64); + return; + } + break; + + 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 = svga->monitor->mon_changeframecount; svga_recalctimings(svga); - break; - - case 0x3C6: case 0x3C7: case 0x3C8: case 0x3C9: - if (mach64->type == MACH64_GX) - ati68860_ramdac_out((addr & 3) | ((mach64->dac_cntl & 3) << 2), val, mach64->svga.ramdac, 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)) - mach64_updatemapping(mach64); - 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); - if (svga->crtcreg > 0x18) - return; - old = svga->crtc[svga->crtcreg]; - svga->crtc[svga->crtcreg] = val; + } + break; - 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); + default: + break; + } + svga_out(addr, val, svga); } -uint8_t mach64_in(uint16_t addr, void *p) +uint8_t +mach64_in(uint16_t addr, void *priv) { - mach64_t *mach64 = p; - svga_t *svga = &mach64->svga; + mach64_t *mach64 = priv; + svga_t *svga = &mach64->svga; - if (((addr&0xFFF0) == 0x3D0 || (addr&0xFFF0) == 0x3B0) && !(svga->miscout&1)) - addr ^= 0x60; - - switch (addr) - { - case 0x1ce: - return mach64->index; - case 0x1cf: - return mach64->regs[mach64->index & 0x3f]; + if (((addr & 0xFFF0) == 0x3D0 || (addr & 0xFFF0) == 0x3B0) && !(svga->miscout & 1)) + addr ^= 0x60; - case 0x3C6: case 0x3C7: case 0x3C8: case 0x3C9: - if (mach64->type == MACH64_GX) - return ati68860_ramdac_in((addr & 3) | ((mach64->dac_cntl & 3) << 2), mach64->svga.ramdac, svga); - return svga_in(addr, svga); - - case 0x3D4: - return svga->crtcreg; - case 0x3D5: - if (svga->crtcreg > 0x18) - return 0xff; - return svga->crtc[svga->crtcreg]; - } - return svga_in(addr, svga); + switch (addr) { + case 0x1ce: + return mach64->index; + case 0x1cf: + return mach64->regs[mach64->index & 0x3f]; + + case 0x3C6: + case 0x3C7: + case 0x3C8: + case 0x3C9: + if (mach64->type == MACH64_GX) + return ati68860_ramdac_in((addr & 3) | ((mach64->dac_cntl & 3) << 2), svga->ramdac, svga); + return svga_in(addr, svga); + + case 0x3D4: + return svga->crtcreg; + case 0x3D5: + if (svga->crtcreg > 0x20) + return 0xff; + return svga->crtc[svga->crtcreg]; + + default: + break; + } + return svga_in(addr, svga); } -void mach64_recalctimings(svga_t *svga) +void +mach64_recalctimings(svga_t *svga) { - mach64_t *mach64 = (mach64_t *)svga->p; + const mach64_t *mach64 = (mach64_t *) svga->priv; - if (((mach64->crtc_gen_cntl >> 24) & 3) == 3) - { - svga->vtotal = (mach64->crtc_v_total_disp & 2047) + 1; - svga->dispend = ((mach64->crtc_v_total_disp >> 16) & 2047) + 1; - svga->htotal = (mach64->crtc_h_total_disp & 255) + 1; - svga->hdisp_time = svga->hdisp = ((mach64->crtc_h_total_disp >> 16) & 255) + 1; - svga->vsyncstart = (mach64->crtc_v_sync_strt_wid & 2047) + 1; - svga->rowoffset = (mach64->crtc_off_pitch >> 22); - svga->clock = (cpuclock * (double)(1ull << 32)) / ics2595_getclock(svga->clock_gen); - svga->ma_latch = (mach64->crtc_off_pitch & 0x1fffff) * 2; - svga->linedbl = svga->rowcount = 0; - svga->split = 0xffffff; - svga->vblankstart = svga->dispend; - svga->rowcount = mach64->crtc_gen_cntl & 1; + if (((mach64->crtc_gen_cntl >> 24) & 3) == 3) { + svga->vtotal = (mach64->crtc_v_total_disp & 2047) + 1; + svga->dispend = ((mach64->crtc_v_total_disp >> 16) & 2047) + 1; + svga->htotal = (mach64->crtc_h_total_disp & 255) + 1; + svga->hdisp_time = svga->hdisp = ((mach64->crtc_h_total_disp >> 16) & 255) + 1; + svga->vsyncstart = (mach64->crtc_v_sync_strt_wid & 2047) + 1; + svga->rowoffset = (mach64->crtc_off_pitch >> 22); + svga->clock = (cpuclock * (double) (1ULL << 32)) / ics2595_getclock(svga->clock_gen); + svga->ma_latch = (mach64->crtc_off_pitch & 0x1fffff) * 2; + svga->linedbl = svga->rowcount = 0; + svga->split = 0xffffff; + svga->vblankstart = svga->dispend; + svga->rowcount = mach64->crtc_gen_cntl & 1; + svga->rowoffset <<= 1; + if (mach64->type == MACH64_GX) + ati68860_ramdac_set_render(svga->ramdac, svga); + switch ((mach64->crtc_gen_cntl >> 8) & 7) { + case BPP_4: + if (mach64->type != MACH64_GX) + svga->render = svga_render_4bpp_highres; + svga->hdisp <<= 3; + break; + case BPP_8: + if (mach64->type != MACH64_GX) + svga->render = svga_render_8bpp_highres; + svga->hdisp <<= 3; + svga->rowoffset >>= 1; + break; + case BPP_15: + if (mach64->type != MACH64_GX) + svga->render = svga_render_15bpp_highres; + svga->hdisp <<= 3; + break; + case BPP_16: + if (mach64->type != MACH64_GX) + svga->render = svga_render_16bpp_highres; + svga->hdisp <<= 3; + break; + case BPP_24: + if (mach64->type != MACH64_GX) + svga->render = svga_render_24bpp_highres; + 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 <<= 3; svga->rowoffset <<= 1; - if (mach64->type == MACH64_GX) - ati68860_ramdac_set_render(svga->ramdac, svga); - switch ((mach64->crtc_gen_cntl >> 8) & 7) - { - case 1: - if (mach64->type != MACH64_GX) - svga->render = svga_render_4bpp_highres; - svga->hdisp *= 8; - break; - case 2: - if (mach64->type != MACH64_GX) - svga->render = svga_render_8bpp_highres; - svga->hdisp *= 8; - svga->rowoffset /= 2; - break; - case 3: - if (mach64->type != MACH64_GX) - svga->render = svga_render_15bpp_highres; - svga->hdisp *= 8; - break; - case 4: - if (mach64->type != MACH64_GX) - svga->render = svga_render_16bpp_highres; - svga->hdisp *= 8; - break; - case 5: - if (mach64->type != MACH64_GX) - svga->render = svga_render_24bpp_highres; - svga->hdisp *= 8; - svga->rowoffset = (svga->rowoffset * 3) / 2; - break; - case 6: - if (mach64->type != MACH64_GX) - svga->render = svga_render_32bpp_highres; - svga->hdisp *= 8; - svga->rowoffset *= 2; - break; - } + break; - svga->vram_display_mask = mach64->vram_mask; - } - else - { - svga->vram_display_mask = (mach64->regs[0x36] & 0x01) ? mach64->vram_mask : 0x3ffff; + default: + break; } + + svga->vram_display_mask = mach64->vram_mask; + } else { + svga->vram_display_mask = (mach64->regs[0x36] & 0x01) ? mach64->vram_mask : 0x3ffff; + } } -void mach64_updatemapping(mach64_t *mach64) +void +mach64_updatemapping(mach64_t *mach64) { - svga_t *svga = &mach64->svga; - - if (!(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); - mem_mapping_disable(&mach64->mmio_mapping); - mem_mapping_disable(&mach64->mmio_linear_mapping); - mem_mapping_disable(&mach64->mmio_linear_mapping_2); - return; - } + svga_t *svga = &mach64->svga; + 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); 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_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_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_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_addr(&svga->mapping, 0xb8000, 0x08000); - svga->banked_mask = 0x7fff; - break; - } - 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 - { - /*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 - { - /*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 - { - mem_mapping_disable(&mach64->linear_mapping); - mem_mapping_disable(&mach64->mmio_linear_mapping); - mem_mapping_disable(&mach64->mmio_linear_mapping_2); + mem_mapping_disable(&mach64->mmio_linear_mapping); + mem_mapping_disable(&mach64->mmio_linear_mapping_2); + return; + } + + mem_mapping_disable(&mach64->mmio_mapping); + switch (svga->gdcreg[6] & 0xc) { + case 0x0: /*128k at A0000*/ + 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(&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(&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(&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; + + default: + 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 { + /*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 { + /*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 { + mem_mapping_disable(&mach64->linear_mapping); + mem_mapping_disable(&mach64->mmio_linear_mapping); + mem_mapping_disable(&mach64->mmio_linear_mapping_2); + } } -static void mach64_update_irqs(mach64_t *mach64) +static void +mach64_update_irqs(mach64_t *mach64) { - if (!mach64->pci) - { - return; - } + if (!mach64->pci) { + return; + } - if ((mach64->crtc_int_cntl & 0xaa0024) & ((mach64->crtc_int_cntl << 1) & 0xaa0024)) - pci_set_irq(mach64->card, PCI_INTA); - else - pci_clear_irq(mach64->card, PCI_INTA); + if ((mach64->crtc_int_cntl & 0xaa0024) & ((mach64->crtc_int_cntl << 1) & 0xaa0024)) + pci_set_irq(mach64->pci_slot, PCI_INTA, &mach64->irq_state); + else + pci_clear_irq(mach64->pci_slot, PCI_INTA, &mach64->irq_state); } #if 0 -static __inline void wake_fifo_thread(mach64_t *mach64) +static __inline void +wake_fifo_thread(mach64_t *mach64) { - thread_set_event(mach64->wake_fifo_thread); /*Wake up FIFO thread if moving from idle*/ + thread_set_event(mach64->wake_fifo_thread); /*Wake up FIFO thread if moving from idle*/ } -static void mach64_wait_fifo_idle(mach64_t *mach64) +static void +mach64_wait_fifo_idle(mach64_t *mach64) { - while (!FIFO_EMPTY) - { - wake_fifo_thread(mach64); - thread_wait_event(mach64->fifo_not_full_event, 1); - } + while (!FIFO_EMPTY) { + wake_fifo_thread(mach64); + thread_wait_event(mach64->fifo_not_full_event, 1); + } } #endif -#define READ8(addr, var) switch ((addr) & 3) \ - { \ - case 0: ret = (var) & 0xff; break; \ - case 1: ret = ((var) >> 8) & 0xff; break; \ - case 2: ret = ((var) >> 16) & 0xff; break; \ - case 3: ret = ((var) >> 24) & 0xff; break; \ - } - -#define WRITE8(addr, var, val) switch ((addr) & 3) \ - { \ - case 0: var = (var & 0xffffff00) | (val); break; \ - case 1: var = (var & 0xffff00ff) | ((val) << 8); break; \ - case 2: var = (var & 0xff00ffff) | ((val) << 16); break; \ - case 3: var = (var & 0x00ffffff) | ((val) << 24); break; \ - } +#define READ8(addr, var) \ + switch ((addr) &3) { \ + case 0: \ + ret = (var) &0xff; \ + break; \ + case 1: \ + ret = ((var) >> 8) & 0xff; \ + break; \ + case 2: \ + ret = ((var) >> 16) & 0xff; \ + break; \ + case 3: \ + ret = ((var) >> 24) & 0xff; \ + break; \ + } -static void mach64_accel_write_fifo(mach64_t *mach64, uint32_t addr, uint8_t val) +#define WRITE8(addr, var, val) \ + switch ((addr) &3) { \ + case 0: \ + var = (var & 0xffffff00) | (val); \ + break; \ + case 1: \ + var = (var & 0xffff00ff) | ((val) << 8); \ + break; \ + case 2: \ + var = (var & 0xff00ffff) | ((val) << 16); \ + break; \ + case 3: \ + var = (var & 0x00ffffff) | ((val) << 24); \ + break; \ + } + +static void +mach64_accel_write_fifo(mach64_t *mach64, uint32_t addr, uint8_t val) { - switch (addr & 0x3ff) - { - case 0x100: case 0x101: case 0x102: case 0x103: - WRITE8(addr, mach64->dst_off_pitch, val); - break; - case 0x104: case 0x105: case 0x11c: case 0x11d: - WRITE8(addr + 2, mach64->dst_y_x, val); - break; - case 0x108: case 0x109: - WRITE8(addr, mach64->dst_y_x, val); - break; - case 0x10c: case 0x10d: case 0x10e: case 0x10f: - WRITE8(addr, mach64->dst_y_x, val); - break; - case 0x110: case 0x111: - WRITE8(addr + 2, mach64->dst_height_width, val); - break; - case 0x114: case 0x115: - case 0x118: case 0x119: case 0x11a: case 0x11b: - case 0x11e: case 0x11f: - WRITE8(addr, mach64->dst_height_width, val); - /*FALLTHROUGH*/ - case 0x113: - if (((addr & 0x3ff) == 0x11b || (addr & 0x3ff) == 0x11f || - (addr & 0x3ff) == 0x113) && !(val & 0x80)) - { - mach64_start_fill(mach64); - mach64_log("%i %i %i %i %i %08x\n", (mach64->dst_height_width & 0x7ff), (mach64->dst_height_width & 0x7ff0000), - ((mach64->dp_src & 7) != SRC_HOST), (((mach64->dp_src >> 8) & 7) != SRC_HOST), - (((mach64->dp_src >> 16) & 3) != MONO_SRC_HOST), mach64->dp_src); - if ((mach64->dst_height_width & 0x7ff) && (mach64->dst_height_width & 0x7ff0000) && - ((mach64->dp_src & 7) != SRC_HOST) && (((mach64->dp_src >> 8) & 7) != SRC_HOST) && - (((mach64->dp_src >> 16) & 3) != MONO_SRC_HOST)) - mach64_blit(0, -1, mach64); - } - break; + switch (addr & 0x3ff) { + case 0x100: + case 0x101: + case 0x102: + case 0x103: + WRITE8(addr, mach64->dst_off_pitch, val); + break; + case 0x104: + case 0x105: + case 0x11c: + case 0x11d: + WRITE8(addr + 2, mach64->dst_y_x, val); + break; + case 0x108: + case 0x109: + WRITE8(addr, mach64->dst_y_x, val); + break; + case 0x10c: + case 0x10d: + case 0x10e: + case 0x10f: + WRITE8(addr, mach64->dst_y_x, val); + break; + case 0x110: + case 0x111: + WRITE8(addr + 2, mach64->dst_height_width, val); + break; + case 0x114: + case 0x115: + case 0x118: + case 0x119: + case 0x11a: + case 0x11b: + case 0x11e: + case 0x11f: + WRITE8(addr, mach64->dst_height_width, val); + fallthrough; + case 0x113: + if (((addr & 0x3ff) == 0x11b || (addr & 0x3ff) == 0x11f || (addr & 0x3ff) == 0x113) && !(val & 0x80)) { + mach64_start_fill(mach64); + mach64_log("%i %i %i %i %i %08x\n", (mach64->dst_height_width & 0x7ff), (mach64->dst_height_width & 0x7ff0000), + ((mach64->dp_src & 7) != SRC_HOST), (((mach64->dp_src >> 8) & 7) != SRC_HOST), + (((mach64->dp_src >> 16) & 3) != MONO_SRC_HOST), mach64->dp_src); + if ((mach64->dst_height_width & 0x7ff) && (mach64->dst_height_width & 0x7ff0000) && ((mach64->dp_src & 7) != SRC_HOST) && (((mach64->dp_src >> 8) & 7) != SRC_HOST) && (((mach64->dp_src >> 16) & 3) != MONO_SRC_HOST)) + mach64_blit(0, -1, mach64); + } + break; - case 0x120: case 0x121: case 0x122: case 0x123: - WRITE8(addr, mach64->dst_bres_lnth, val); - if ((addr & 0x3ff) == 0x123 && !(val & 0x80)) - { - mach64_start_line(mach64); + case 0x120: + case 0x121: + case 0x122: + case 0x123: + WRITE8(addr, mach64->dst_bres_lnth, val); + if ((addr & 0x3ff) == 0x123 && !(val & 0x80)) { + mach64_start_line(mach64); - if ((mach64->dst_bres_lnth & 0x7fff) && - ((mach64->dp_src & 7) != SRC_HOST) && (((mach64->dp_src >> 8) & 7) != SRC_HOST) && - (((mach64->dp_src >> 16) & 3) != MONO_SRC_HOST)) - mach64_blit(0, -1, mach64); - } - break; - case 0x124: case 0x125: case 0x126: case 0x127: - WRITE8(addr, mach64->dst_bres_err, val); - break; - case 0x128: case 0x129: case 0x12a: case 0x12b: - WRITE8(addr, mach64->dst_bres_inc, val); - break; - case 0x12c: case 0x12d: case 0x12e: case 0x12f: - WRITE8(addr, mach64->dst_bres_dec, val); - break; + if ((mach64->dst_bres_lnth & 0x7fff) && ((mach64->dp_src & 7) != SRC_HOST) && (((mach64->dp_src >> 8) & 7) != SRC_HOST) && (((mach64->dp_src >> 16) & 3) != MONO_SRC_HOST)) + mach64_blit(0, -1, mach64); + } + break; + case 0x124: + case 0x125: + case 0x126: + case 0x127: + WRITE8(addr, mach64->dst_bres_err, val); + break; + case 0x128: + case 0x129: + case 0x12a: + case 0x12b: + WRITE8(addr, mach64->dst_bres_inc, val); + break; + case 0x12c: + case 0x12d: + case 0x12e: + case 0x12f: + WRITE8(addr, mach64->dst_bres_dec, val); + break; - case 0x130: case 0x131: case 0x132: case 0x133: - WRITE8(addr, mach64->dst_cntl, val); - break; + case 0x130: + case 0x131: + case 0x132: + case 0x133: + WRITE8(addr, mach64->dst_cntl, val); + break; - case 0x180: case 0x181: case 0x182: case 0x183: - WRITE8(addr, mach64->src_off_pitch, val); - break; - case 0x184: case 0x185: - WRITE8(addr, mach64->src_y_x, val); - break; - case 0x188: case 0x189: - WRITE8(addr + 2, mach64->src_y_x, val); - break; - case 0x18c: case 0x18d: case 0x18e: case 0x18f: - WRITE8(addr, mach64->src_y_x, val); - break; - case 0x190: case 0x191: - WRITE8(addr + 2, mach64->src_height1_width1, val); - break; - case 0x194: case 0x195: - WRITE8(addr, mach64->src_height1_width1, val); - break; - case 0x198: case 0x199: case 0x19a: case 0x19b: - WRITE8(addr, mach64->src_height1_width1, val); - break; - case 0x19c: case 0x19d: - WRITE8(addr, mach64->src_y_x_start, val); - break; - case 0x1a0: case 0x1a1: - WRITE8(addr + 2, mach64->src_y_x_start, val); - break; - case 0x1a4: case 0x1a5: case 0x1a6: case 0x1a7: - WRITE8(addr, mach64->src_y_x_start, val); - break; - case 0x1a8: case 0x1a9: - WRITE8(addr + 2, mach64->src_height2_width2, val); - break; - case 0x1ac: case 0x1ad: - WRITE8(addr, mach64->src_height2_width2, val); - break; - case 0x1b0: case 0x1b1: case 0x1b2: case 0x1b3: - WRITE8(addr, mach64->src_height2_width2, val); - break; + case 0x180: + case 0x181: + case 0x182: + case 0x183: + WRITE8(addr, mach64->src_off_pitch, val); + break; + case 0x184: + case 0x185: + WRITE8(addr, mach64->src_y_x, val); + break; + case 0x188: + case 0x189: + WRITE8(addr + 2, mach64->src_y_x, val); + break; + case 0x18c: + case 0x18d: + case 0x18e: + case 0x18f: + WRITE8(addr, mach64->src_y_x, val); + break; + case 0x190: + case 0x191: + WRITE8(addr + 2, mach64->src_height1_width1, val); + break; + case 0x194: + case 0x195: + WRITE8(addr, mach64->src_height1_width1, val); + break; + case 0x198: + case 0x199: + case 0x19a: + case 0x19b: + WRITE8(addr, mach64->src_height1_width1, val); + break; + case 0x19c: + case 0x19d: + WRITE8(addr, mach64->src_y_x_start, val); + break; + case 0x1a0: + case 0x1a1: + WRITE8(addr + 2, mach64->src_y_x_start, val); + break; + case 0x1a4: + case 0x1a5: + case 0x1a6: + case 0x1a7: + WRITE8(addr, mach64->src_y_x_start, val); + break; + case 0x1a8: + case 0x1a9: + WRITE8(addr + 2, mach64->src_height2_width2, val); + break; + case 0x1ac: + case 0x1ad: + WRITE8(addr, mach64->src_height2_width2, val); + break; + case 0x1b0: + case 0x1b1: + case 0x1b2: + case 0x1b3: + WRITE8(addr, mach64->src_height2_width2, val); + break; - case 0x1b4: case 0x1b5: case 0x1b6: case 0x1b7: - WRITE8(addr, mach64->src_cntl, val); - break; + case 0x1b4: + case 0x1b5: + case 0x1b6: + case 0x1b7: + WRITE8(addr, mach64->src_cntl, val); + break; - case 0x200: case 0x201: case 0x202: case 0x203: - case 0x204: case 0x205: case 0x206: case 0x207: - case 0x208: case 0x209: case 0x20a: case 0x20b: - case 0x20c: case 0x20d: case 0x20e: case 0x20f: - case 0x210: case 0x211: case 0x212: case 0x213: - case 0x214: case 0x215: case 0x216: case 0x217: - case 0x218: case 0x219: case 0x21a: case 0x21b: - case 0x21c: case 0x21d: case 0x21e: case 0x21f: - case 0x220: case 0x221: case 0x222: case 0x223: - case 0x224: case 0x225: case 0x226: case 0x227: - case 0x228: case 0x229: case 0x22a: case 0x22b: - case 0x22c: case 0x22d: case 0x22e: case 0x22f: - case 0x230: case 0x231: case 0x232: case 0x233: - case 0x234: case 0x235: case 0x236: case 0x237: - case 0x238: case 0x239: case 0x23a: case 0x23b: - case 0x23c: case 0x23d: case 0x23e: case 0x23f: - mach64_blit(val, 8, mach64); - break; - - case 0x240: case 0x241: case 0x242: case 0x243: - WRITE8(addr, mach64->host_cntl, val); - break; + case 0x200: + case 0x201: + case 0x202: + case 0x203: + case 0x204: + case 0x205: + case 0x206: + case 0x207: + case 0x208: + case 0x209: + case 0x20a: + case 0x20b: + case 0x20c: + case 0x20d: + case 0x20e: + case 0x20f: + case 0x210: + case 0x211: + case 0x212: + case 0x213: + case 0x214: + case 0x215: + case 0x216: + case 0x217: + case 0x218: + case 0x219: + case 0x21a: + case 0x21b: + case 0x21c: + case 0x21d: + case 0x21e: + case 0x21f: + case 0x220: + case 0x221: + case 0x222: + case 0x223: + case 0x224: + case 0x225: + case 0x226: + case 0x227: + case 0x228: + case 0x229: + case 0x22a: + case 0x22b: + case 0x22c: + case 0x22d: + case 0x22e: + case 0x22f: + case 0x230: + case 0x231: + case 0x232: + case 0x233: + case 0x234: + case 0x235: + case 0x236: + case 0x237: + case 0x238: + case 0x239: + case 0x23a: + case 0x23b: + case 0x23c: + case 0x23d: + case 0x23e: + case 0x23f: + mach64_blit(val, 8, mach64); + break; - case 0x280: case 0x281: case 0x282: case 0x283: - WRITE8(addr, mach64->pat_reg0, val); - break; - case 0x284: case 0x285: case 0x286: case 0x287: - WRITE8(addr, mach64->pat_reg1, val); - break; + case 0x240: + case 0x241: + case 0x242: + case 0x243: + WRITE8(addr, mach64->host_cntl, val); + break; - case 0x288: case 0x289: case 0x28a: case 0x28b: - WRITE8(addr, mach64->pat_cntl, val); - break; + case 0x280: + case 0x281: + case 0x282: + case 0x283: + WRITE8(addr, mach64->pat_reg0, val); + break; + case 0x284: + case 0x285: + case 0x286: + case 0x287: + WRITE8(addr, mach64->pat_reg1, val); + break; - case 0x2a0: case 0x2a1: case 0x2a8: case 0x2a9: - WRITE8(addr, mach64->sc_left_right, val); - break; - case 0x2a4: case 0x2a5: - addr += 2; - /*FALLTHROUGH*/ - case 0x2aa: case 0x2ab: - WRITE8(addr, mach64->sc_left_right, val); - break; + case 0x288: + case 0x289: + case 0x28a: + case 0x28b: + WRITE8(addr, mach64->pat_cntl, val); + break; - case 0x2ac: case 0x2ad: case 0x2b4: case 0x2b5: - WRITE8(addr, mach64->sc_top_bottom, val); - break; - case 0x2b0: case 0x2b1: - addr += 2; - /*FALLTHROUGH*/ - case 0x2b6: case 0x2b7: - WRITE8(addr, mach64->sc_top_bottom, val); - break; + case 0x2a0: + case 0x2a1: + case 0x2a8: + case 0x2a9: + WRITE8(addr, mach64->sc_left_right, val); + break; + case 0x2a4: + case 0x2a5: + addr += 2; + fallthrough; + case 0x2aa: + case 0x2ab: + WRITE8(addr, mach64->sc_left_right, val); + break; - case 0x2c0: case 0x2c1: case 0x2c2: case 0x2c3: - WRITE8(addr, mach64->dp_bkgd_clr, val); - break; - case 0x2c4: case 0x2c5: case 0x2c6: case 0x2c7: - WRITE8(addr, mach64->dp_frgd_clr, val); - break; + case 0x2ac: + case 0x2ad: + case 0x2b4: + case 0x2b5: + WRITE8(addr, mach64->sc_top_bottom, val); + break; + case 0x2b0: + case 0x2b1: + addr += 2; + fallthrough; + case 0x2b6: + case 0x2b7: + WRITE8(addr, mach64->sc_top_bottom, val); + break; - case 0x2d0: case 0x2d1: case 0x2d2: case 0x2d3: - WRITE8(addr, mach64->dp_pix_width, val); - break; - case 0x2d4: case 0x2d5: case 0x2d6: case 0x2d7: - WRITE8(addr, mach64->dp_mix, val); - break; - case 0x2d8: case 0x2d9: case 0x2da: case 0x2db: - WRITE8(addr, mach64->dp_src, val); - break; + case 0x2c0: + case 0x2c1: + case 0x2c2: + case 0x2c3: + WRITE8(addr, mach64->dp_bkgd_clr, val); + break; + case 0x2c4: + case 0x2c5: + case 0x2c6: + case 0x2c7: + WRITE8(addr, mach64->dp_frgd_clr, val); + break; + case 0x2c8: + case 0x2c9: + case 0x2ca: + case 0x2cb: + WRITE8(addr, mach64->write_mask, val); + break; + case 0x2cc: + case 0x2cd: + case 0x2ce: + case 0x2cf: + WRITE8(addr, mach64->chain_mask, val); + break; - case 0x300: case 0x301: case 0x302: case 0x303: - WRITE8(addr, mach64->clr_cmp_clr, val); - break; - case 0x304: case 0x305: case 0x306: case 0x307: - WRITE8(addr, mach64->clr_cmp_mask, val); - break; - case 0x308: case 0x309: case 0x30a: case 0x30b: - WRITE8(addr, mach64->clr_cmp_cntl, val); - break; + case 0x2d0: + case 0x2d1: + case 0x2d2: + case 0x2d3: + WRITE8(addr, mach64->dp_pix_width, val); + break; + case 0x2d4: + case 0x2d5: + case 0x2d6: + case 0x2d7: + WRITE8(addr, mach64->dp_mix, val); + break; + case 0x2d8: + case 0x2d9: + case 0x2da: + case 0x2db: + WRITE8(addr, mach64->dp_src, val); + break; - case 0x320: case 0x321: case 0x322: case 0x323: - WRITE8(addr, mach64->context_mask, val); - break; + case 0x300: + case 0x301: + case 0x302: + case 0x303: + WRITE8(addr, mach64->clr_cmp_clr, val); + break; + case 0x304: + case 0x305: + case 0x306: + case 0x307: + WRITE8(addr, mach64->clr_cmp_mask, val); + break; + case 0x308: + case 0x309: + case 0x30a: + case 0x30b: + WRITE8(addr, mach64->clr_cmp_cntl, val); + break; - case 0x330: case 0x331: - WRITE8(addr, mach64->dst_cntl, val); - break; - case 0x332: - WRITE8(addr - 2, mach64->src_cntl, val); - break; - case 0x333: - WRITE8(addr - 3, mach64->pat_cntl, val & 7); - if (val & 0x10) - mach64->host_cntl |= HOST_BYTE_ALIGN; - else - mach64->host_cntl &= ~HOST_BYTE_ALIGN; - break; - } + case 0x320: + case 0x321: + case 0x322: + case 0x323: + WRITE8(addr, mach64->context_mask, val); + break; + + case 0x330: + case 0x331: + WRITE8(addr, mach64->dst_cntl, val); + break; + case 0x332: + WRITE8(addr - 2, mach64->src_cntl, val); + break; + case 0x333: + WRITE8(addr - 3, mach64->pat_cntl, val & 7); + if (val & 0x10) + mach64->host_cntl |= HOST_BYTE_ALIGN; + else + mach64->host_cntl &= ~HOST_BYTE_ALIGN; + break; + + default: + break; + } } -static void mach64_accel_write_fifo_w(mach64_t *mach64, uint32_t addr, uint16_t val) +static void +mach64_accel_write_fifo_w(mach64_t *mach64, uint32_t addr, uint16_t val) { - switch (addr & 0x3fe) - { - case 0x200: case 0x202: case 0x204: case 0x206: - case 0x208: case 0x20a: case 0x20c: case 0x20e: - case 0x210: case 0x212: case 0x214: case 0x216: - case 0x218: case 0x21a: case 0x21c: case 0x21e: - case 0x220: case 0x222: case 0x224: case 0x226: - case 0x228: case 0x22a: case 0x22c: case 0x22e: - case 0x230: case 0x232: case 0x234: case 0x236: - case 0x238: case 0x23a: case 0x23c: case 0x23e: - mach64_blit(val, 16, mach64); - break; + switch (addr & 0x3fe) { + case 0x200: + case 0x202: + case 0x204: + case 0x206: + case 0x208: + case 0x20a: + case 0x20c: + case 0x20e: + case 0x210: + case 0x212: + case 0x214: + case 0x216: + case 0x218: + case 0x21a: + case 0x21c: + case 0x21e: + case 0x220: + case 0x222: + case 0x224: + case 0x226: + case 0x228: + case 0x22a: + case 0x22c: + case 0x22e: + case 0x230: + case 0x232: + case 0x234: + case 0x236: + case 0x238: + case 0x23a: + case 0x23c: + case 0x23e: + mach64_blit(val, 16, mach64); + break; - case 0x32c: - mach64->context_load_cntl = (mach64->context_load_cntl & 0xffff0000) | val; - break; + case 0x32c: + mach64->context_load_cntl = (mach64->context_load_cntl & 0xffff0000) | val; + break; - case 0x32e: - mach64->context_load_cntl = (mach64->context_load_cntl & 0x0000ffff) | (val << 16); - if (val & 0x30000) - mach64_load_context(mach64); - break; + case 0x32e: + mach64->context_load_cntl = (mach64->context_load_cntl & 0x0000ffff) | (val << 16); + if (val & 0x30000) + mach64_load_context(mach64); + break; - default: - mach64_accel_write_fifo(mach64, addr, val); - mach64_accel_write_fifo(mach64, addr + 1, val >> 8); - break; - } + default: + mach64_accel_write_fifo(mach64, addr, val); + mach64_accel_write_fifo(mach64, addr + 1, val >> 8); + break; + } } -static void mach64_accel_write_fifo_l(mach64_t *mach64, uint32_t addr, uint32_t val) +static void +mach64_accel_write_fifo_l(mach64_t *mach64, uint32_t addr, uint32_t val) { - switch (addr & 0x3fc) - { - case 0x32c: - mach64->context_load_cntl = val; - if (val & 0x30000) - mach64_load_context(mach64); - break; - - case 0x200: case 0x204: case 0x208: case 0x20c: - case 0x210: case 0x214: case 0x218: case 0x21c: - case 0x220: case 0x224: case 0x228: case 0x22c: - case 0x230: case 0x234: case 0x238: case 0x23c: - if (mach64->accel.source_host || (mach64->dp_pix_width & DP_BYTE_PIX_ORDER)) - mach64_blit(val, 32, mach64); - else - mach64_blit(((val & 0xff000000) >> 24) | ((val & 0x00ff0000) >> 8) | ((val & 0x0000ff00) << 8) | ((val & 0x000000ff) << 24), 32, mach64); - break; + switch (addr & 0x3fc) { + case 0x32c: + mach64->context_load_cntl = val; + if (val & 0x30000) + mach64_load_context(mach64); + break; - default: - mach64_accel_write_fifo_w(mach64, addr, val); - mach64_accel_write_fifo_w(mach64, addr + 2, val >> 16); - break; - } + case 0x200: + case 0x204: + case 0x208: + case 0x20c: + case 0x210: + case 0x214: + case 0x218: + case 0x21c: + case 0x220: + case 0x224: + case 0x228: + case 0x22c: + case 0x230: + case 0x234: + case 0x238: + case 0x23c: + if (mach64->accel.source_host || (mach64->dp_pix_width & DP_BYTE_PIX_ORDER)) + mach64_blit(val, 32, mach64); + else + mach64_blit(((val & 0xff000000) >> 24) | ((val & 0x00ff0000) >> 8) | ((val & 0x0000ff00) << 8) | ((val & 0x000000ff) << 24), 32, mach64); + break; + + default: + mach64_accel_write_fifo_w(mach64, addr, val); + mach64_accel_write_fifo_w(mach64, addr + 2, val >> 16); + break; + } } #if 0 -static void fifo_thread(void *param) +static void +fifo_thread(void *param) { - mach64_t *mach64 = (mach64_t *)param; - - while (mach64->thread_run) - { + mach64_t *mach64 = (mach64_t *) param; + + while (mach64->thread_run) { + thread_set_event(mach64->fifo_not_full_event); + thread_wait_event(mach64->wake_fifo_thread, -1); + thread_reset_event(mach64->wake_fifo_thread); + mach64->blitter_busy = 1; + while (!FIFO_EMPTY) { + uint64_t start_time = plat_timer_read(); + uint64_t end_time; + fifo_entry_t *fifo = &mach64->fifo[mach64->fifo_read_idx & FIFO_MASK]; + + switch (fifo->addr_type & FIFO_TYPE) { + case FIFO_WRITE_BYTE: + mach64_accel_write_fifo(mach64, fifo->addr_type & FIFO_ADDR, fifo->val); + break; + case FIFO_WRITE_WORD: + mach64_accel_write_fifo_w(mach64, fifo->addr_type & FIFO_ADDR, fifo->val); + break; + case FIFO_WRITE_DWORD: + mach64_accel_write_fifo_l(mach64, fifo->addr_type & FIFO_ADDR, fifo->val); + break; + + default: + break; + } + + mach64->fifo_read_idx++; + fifo->addr_type = FIFO_INVALID; + + if (FIFO_ENTRIES > 0xe000) thread_set_event(mach64->fifo_not_full_event); - thread_wait_event(mach64->wake_fifo_thread, -1); - thread_reset_event(mach64->wake_fifo_thread); - mach64->blitter_busy = 1; - while (!FIFO_EMPTY) - { - uint64_t start_time = plat_timer_read(); - uint64_t end_time; - fifo_entry_t *fifo = &mach64->fifo[mach64->fifo_read_idx & FIFO_MASK]; - switch (fifo->addr_type & FIFO_TYPE) - { - case FIFO_WRITE_BYTE: - mach64_accel_write_fifo(mach64, fifo->addr_type & FIFO_ADDR, fifo->val); - break; - case FIFO_WRITE_WORD: - mach64_accel_write_fifo_w(mach64, fifo->addr_type & FIFO_ADDR, fifo->val); - break; - case FIFO_WRITE_DWORD: - mach64_accel_write_fifo_l(mach64, fifo->addr_type & FIFO_ADDR, fifo->val); - break; - } - - mach64->fifo_read_idx++; - fifo->addr_type = FIFO_INVALID; - - if (FIFO_ENTRIES > 0xe000) - thread_set_event(mach64->fifo_not_full_event); - - end_time = plat_timer_read(); - mach64->blitter_time += end_time - start_time; - } - mach64->blitter_busy = 0; + end_time = plat_timer_read(); + mach64->blitter_time += end_time - start_time; } + mach64->blitter_busy = 0; + } } -static void mach64_queue(mach64_t *mach64, uint32_t addr, uint32_t val, uint32_t type) +static void +mach64_queue(mach64_t *mach64, uint32_t addr, uint32_t val, uint32_t type) { - fifo_entry_t *fifo = &mach64->fifo[mach64->fifo_write_idx & FIFO_MASK]; + fifo_entry_t *fifo = &mach64->fifo[mach64->fifo_write_idx & FIFO_MASK]; - if (FIFO_FULL) - { - thread_reset_event(mach64->fifo_not_full_event); - if (FIFO_FULL) - { - thread_wait_event(mach64->fifo_not_full_event, -1); /*Wait for room in ringbuffer*/ - } + if (FIFO_FULL) { + thread_reset_event(mach64->fifo_not_full_event); + if (FIFO_FULL) { + thread_wait_event(mach64->fifo_not_full_event, -1); /*Wait for room in ringbuffer*/ } + } - fifo->val = val; - fifo->addr_type = (addr & FIFO_ADDR) | type; + fifo->val = val; + fifo->addr_type = (addr & FIFO_ADDR) | type; - mach64->fifo_write_idx++; - - if (FIFO_ENTRIES > 0xe000 || FIFO_ENTRIES < 8) - wake_fifo_thread(mach64); + mach64->fifo_write_idx++; + + if (FIFO_ENTRIES > 0xe000 || FIFO_ENTRIES < 8) + wake_fifo_thread(mach64); } #endif -void mach64_cursor_dump(mach64_t *mach64) +void +mach64_start_fill(mach64_t *mach64) { - return; + mach64->accel.dst_x = 0; + mach64->accel.dst_y = 0; + + mach64->accel.dst_x_start = (mach64->dst_y_x >> 16) & 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; + + if (((mach64->dp_src >> 16) & 7) == MONO_SRC_BLITSRC) { + if (mach64->accel.dst_width & 7) + mach64->accel.dst_width = (mach64->accel.dst_width & ~7) + 8; + } + + 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; + 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 + mach64->accel.src_x_count = (mach64->src_height1_width1 >> 16) & 0x7fff; + if (!(mach64->src_cntl & SRC_PATT_EN)) + mach64->accel.src_y_count = 0x7ffffff; /*Essentially infinite*/ + else + mach64->accel.src_y_count = mach64->src_height1_width1 & 0x1fff; + + mach64->accel.src_width1 = (mach64->src_height1_width1 >> 16) & 0x7fff; + mach64->accel.src_height1 = mach64->src_height1_width1 & 0x1fff; + mach64->accel.src_width2 = (mach64->src_height2_width2 >> 16) & 0x7fff; + mach64->accel.src_height2 = mach64->src_height2_width2 & 0x1fff; + + mach64_log("src %i %i %i %i %08X %08X\n", mach64->accel.src_x_count, + mach64->accel.src_y_count, + mach64->accel.src_width1, + mach64->accel.src_height1, + mach64->src_height1_width1, + mach64->src_height2_width2); + + 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) << 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; + + mach64->accel.source_bg = mach64->dp_src & 7; + mach64->accel.source_fg = (mach64->dp_src >> 8) & 7; + mach64->accel.source_mix = (mach64->dp_src >> 16) & 7; + + mach64->accel.dst_pix_width = mach64->dp_pix_width & 7; + mach64->accel.src_pix_width = (mach64->dp_pix_width >> 8) & 7; + mach64->accel.host_pix_width = (mach64->dp_pix_width >> 16) & 7; + + mach64->accel.dst_size = mach64_width[mach64->accel.dst_pix_width]; + mach64->accel.src_size = mach64_width[mach64->accel.src_pix_width]; + mach64->accel.host_size = mach64_width[mach64->accel.host_pix_width]; + + if (mach64->accel.src_size == WIDTH_1BIT) + mach64->accel.src_offset <<= 3; + else + mach64->accel.src_offset >>= mach64->accel.src_size; + + if (mach64->accel.dst_size == WIDTH_1BIT) + mach64->accel.dst_offset <<= 3; + else + mach64->accel.dst_offset >>= mach64->accel.dst_size; + + mach64->accel.xinc = (mach64->dst_cntl & DST_X_DIR) ? 1 : -1; + mach64->accel.yinc = (mach64->dst_cntl & DST_Y_DIR) ? 1 : -1; + + mach64->accel.source_host = ((mach64->dp_src & 7) == SRC_HOST) || (((mach64->dp_src >> 8) & 7) == SRC_HOST); + + if (mach64->pat_cntl & 1) { + for (uint8_t y = 0; y < 8; y++) { + for (uint8_t x = 0; x < 8; x++) { + uint32_t temp = (y & 4) ? mach64->pat_reg1 : mach64->pat_reg0; + mach64->accel.pattern[y][7 - x] = (temp >> (x + ((y & 3) << 3))) & 1; + } + } + } + + if (mach64->pat_cntl & 2) { + mach64->accel.pattern_clr4x2[0][0] = (mach64->pat_reg0 & 0xff); + mach64->accel.pattern_clr4x2[0][1] = ((mach64->pat_reg0 >> 8) & 0xff); + mach64->accel.pattern_clr4x2[0][2] = ((mach64->pat_reg0 >> 16) & 0xff); + mach64->accel.pattern_clr4x2[0][3] = ((mach64->pat_reg0 >> 24) & 0xff); + mach64->accel.pattern_clr4x2[1][0] = (mach64->pat_reg1 & 0xff); + mach64->accel.pattern_clr4x2[1][1] = ((mach64->pat_reg1 >> 8) & 0xff); + mach64->accel.pattern_clr4x2[1][2] = ((mach64->pat_reg1 >> 16) & 0xff); + mach64->accel.pattern_clr4x2[1][3] = ((mach64->pat_reg1 >> 24) & 0xff); + } + + if (mach64->pat_cntl & 4) { + mach64->accel.pattern_clr8x1[0] = (mach64->pat_reg0 & 0xff); + mach64->accel.pattern_clr8x1[1] = ((mach64->pat_reg0 >> 8) & 0xff); + mach64->accel.pattern_clr8x1[2] = ((mach64->pat_reg0 >> 16) & 0xff); + mach64->accel.pattern_clr8x1[3] = ((mach64->pat_reg0 >> 24) & 0xff); + mach64->accel.pattern_clr8x1[4] = (mach64->pat_reg1 & 0xff); + mach64->accel.pattern_clr8x1[5] = ((mach64->pat_reg1 >> 8) & 0xff); + mach64->accel.pattern_clr8x1[6] = ((mach64->pat_reg1 >> 16) & 0xff); + mach64->accel.pattern_clr8x1[7] = ((mach64->pat_reg1 >> 24) & 0xff); + } + + mach64->accel.sc_left = mach64->sc_left_right & 0x1fff; + mach64->accel.sc_right = (mach64->sc_left_right >> 16) & 0x1fff; + mach64->accel.sc_top = mach64->sc_top_bottom & 0x7fff; + mach64->accel.sc_bottom = (mach64->sc_top_bottom >> 16) & 0x7fff; + + mach64->accel.dp_frgd_clr = mach64->dp_frgd_clr; + mach64->accel.dp_bkgd_clr = mach64->dp_bkgd_clr; + mach64->accel.write_mask = mach64->write_mask; + + mach64->accel.clr_cmp_clr = mach64->clr_cmp_clr & mach64->clr_cmp_mask; + mach64->accel.clr_cmp_mask = mach64->clr_cmp_mask; + mach64->accel.clr_cmp_fn = mach64->clr_cmp_cntl & 7; + mach64->accel.clr_cmp_src = mach64->clr_cmp_cntl & (1 << 24); + + mach64->accel.poly_draw = 0; + + mach64->accel.busy = 1; + mach64_log("mach64_start_fill : dst %i, %i src %i, %i size %i, %i src pitch %i offset %X dst pitch %i offset %X scissor %i %i %i %i src_fg %i mix %02X %02X\n", mach64->accel.dst_x_start, mach64->accel.dst_y_start, mach64->accel.src_x_start, mach64->accel.src_y_start, mach64->accel.dst_width, mach64->accel.dst_height, mach64->accel.src_pitch, mach64->accel.src_offset, mach64->accel.dst_pitch, mach64->accel.dst_offset, mach64->accel.sc_left, mach64->accel.sc_right, mach64->accel.sc_top, mach64->accel.sc_bottom, mach64->accel.source_fg, mach64->accel.mix_fg, mach64->accel.mix_bg); + + mach64->accel.op = OP_RECT; } -void mach64_start_fill(mach64_t *mach64) +void +mach64_start_line(mach64_t *mach64) { - int x, y; - - 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; + mach64->accel.dst_x = (mach64->dst_y_x >> 16) & 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.dst_width = (mach64->dst_height_width >> 16) & 0x1fff; - mach64->accel.dst_height = mach64->dst_height_width & 0x1fff; + mach64->accel.src_x = (mach64->src_y_x >> 16) & 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; - if (((mach64->dp_src >> 16) & 7) == MONO_SRC_BLITSRC) - { - if (mach64->accel.dst_width & 7) - mach64->accel.dst_width = (mach64->accel.dst_width & ~7) + 8; - } + mach64->accel.src_pitch = (mach64->src_off_pitch >> 22) << 3; + mach64->accel.src_offset = (mach64->src_off_pitch & 0xfffff) << 3; - mach64->accel.x_count = mach64->accel.dst_width; - - 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_cntl & SRC_LINEAR_EN) - mach64->accel.src_x_count = 0x7ffffff; /*Essentially infinite*/ - else - mach64->accel.src_x_count = (mach64->src_height1_width1 >> 16) & 0x7fff; - if (!(mach64->src_cntl & SRC_PATT_EN)) - mach64->accel.src_y_count = 0x7ffffff; /*Essentially infinite*/ - else - mach64->accel.src_y_count = mach64->src_height1_width1 & 0x1fff; + mach64->accel.dst_pitch = (mach64->dst_off_pitch >> 22) << 3; + mach64->accel.dst_offset = (mach64->dst_off_pitch & 0xfffff) << 3; - mach64->accel.src_width1 = (mach64->src_height1_width1 >> 16) & 0x7fff; - mach64->accel.src_height1 = mach64->src_height1_width1 & 0x1fff; - mach64->accel.src_width2 = (mach64->src_height2_width2 >> 16) & 0x7fff; - mach64->accel.src_height2 = mach64->src_height2_width2 & 0x1fff; + mach64->accel.mix_fg = (mach64->dp_mix >> 16) & 0x1f; + mach64->accel.mix_bg = mach64->dp_mix & 0x1f; - mach64_log("src %i %i %i %i %08X %08X\n", mach64->accel.src_x_count, - mach64->accel.src_y_count, - mach64->accel.src_width1, - mach64->accel.src_height1, - 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.source_bg = mach64->dp_src & 7; + mach64->accel.source_fg = (mach64->dp_src >> 8) & 7; + mach64->accel.source_mix = (mach64->dp_src >> 16) & 7; - mach64->accel.dst_pitch = (mach64->dst_off_pitch >> 22) * 8; - mach64->accel.dst_offset = (mach64->dst_off_pitch & 0xfffff) * 8; - - mach64->accel.mix_fg = (mach64->dp_mix >> 16) & 0x1f; - mach64->accel.mix_bg = mach64->dp_mix & 0x1f; - - mach64->accel.source_bg = mach64->dp_src & 7; - mach64->accel.source_fg = (mach64->dp_src >> 8) & 7; - mach64->accel.source_mix = (mach64->dp_src >> 16) & 7; - - mach64->accel.dst_pix_width = mach64->dp_pix_width & 7; - mach64->accel.src_pix_width = (mach64->dp_pix_width >> 8) & 7; - mach64->accel.host_pix_width = (mach64->dp_pix_width >> 16) & 7; - - mach64->accel.dst_size = mach64_width[mach64->accel.dst_pix_width]; - mach64->accel.src_size = mach64_width[mach64->accel.src_pix_width]; - mach64->accel.host_size = mach64_width[mach64->accel.host_pix_width]; + mach64->accel.dst_pix_width = mach64->dp_pix_width & 7; + mach64->accel.src_pix_width = (mach64->dp_pix_width >> 8) & 7; + mach64->accel.host_pix_width = (mach64->dp_pix_width >> 16) & 7; - if (mach64->accel.src_size == WIDTH_1BIT) - mach64->accel.src_offset <<= 3; - else - mach64->accel.src_offset >>= mach64->accel.src_size; - - if (mach64->accel.dst_size == WIDTH_1BIT) - mach64->accel.dst_offset <<= 3; - else - mach64->accel.dst_offset >>= mach64->accel.dst_size; - - mach64->accel.xinc = (mach64->dst_cntl & DST_X_DIR) ? 1 : -1; - mach64->accel.yinc = (mach64->dst_cntl & DST_Y_DIR) ? 1 : -1; - - mach64->accel.source_host = ((mach64->dp_src & 7) == SRC_HOST) || (((mach64->dp_src >> 8) & 7) == SRC_HOST); - - - for (y = 0; y < 8; y++) - { - for (x = 0; x < 8; x++) - { - uint32_t temp = (y & 4) ? mach64->pat_reg1 : mach64->pat_reg0; - mach64->accel.pattern[y][7 - x] = (temp >> (x + ((y & 3) * 8))) & 1; - } + mach64->accel.dst_size = mach64_width[mach64->accel.dst_pix_width]; + mach64->accel.src_size = mach64_width[mach64->accel.src_pix_width]; + mach64->accel.host_size = mach64_width[mach64->accel.host_pix_width]; + + if (mach64->accel.src_size == WIDTH_1BIT) + mach64->accel.src_offset <<= 3; + else + mach64->accel.src_offset >>= mach64->accel.src_size; + + if (mach64->accel.dst_size == WIDTH_1BIT) + mach64->accel.dst_offset <<= 3; + else + mach64->accel.dst_offset >>= mach64->accel.dst_size; + + mach64->accel.source_host = ((mach64->dp_src & 7) == SRC_HOST) || (((mach64->dp_src >> 8) & 7) == SRC_HOST); + + if (mach64->pat_cntl & 1) { + for (uint8_t y = 0; y < 8; y++) { + for (uint8_t x = 0; x < 8; x++) { + uint32_t temp = (y & 4) ? mach64->pat_reg1 : mach64->pat_reg0; + mach64->accel.pattern[y][7 - x] = (temp >> (x + ((y & 3) << 3))) & 1; + } } + } - if (mach64->pat_cntl & 2) { - mach64->accel.pattern_clr4x2[0][0] = (mach64->pat_reg0 & 0xff); - mach64->accel.pattern_clr4x2[0][1] = ((mach64->pat_reg0 >> 8) & 0xff); - mach64->accel.pattern_clr4x2[0][2] = ((mach64->pat_reg0 >> 16) & 0xff); - mach64->accel.pattern_clr4x2[0][3] = ((mach64->pat_reg0 >> 24) & 0xff); - mach64->accel.pattern_clr4x2[1][0] = (mach64->pat_reg1 & 0xff); - mach64->accel.pattern_clr4x2[1][1] = ((mach64->pat_reg1 >> 8) & 0xff); - mach64->accel.pattern_clr4x2[1][2] = ((mach64->pat_reg1 >> 16) & 0xff); - mach64->accel.pattern_clr4x2[1][3] = ((mach64->pat_reg1 >> 24) & 0xff); - } else if (mach64->pat_cntl & 4) { - mach64->accel.pattern_clr8x1[0] = (mach64->pat_reg0 & 0xff); - mach64->accel.pattern_clr8x1[1] = ((mach64->pat_reg0 >> 8) & 0xff); - mach64->accel.pattern_clr8x1[2] = ((mach64->pat_reg0 >> 16) & 0xff); - mach64->accel.pattern_clr8x1[3] = ((mach64->pat_reg0 >> 24) & 0xff); - mach64->accel.pattern_clr8x1[4] = (mach64->pat_reg1 & 0xff); - mach64->accel.pattern_clr8x1[5] = ((mach64->pat_reg1 >> 8) & 0xff); - mach64->accel.pattern_clr8x1[6] = ((mach64->pat_reg1 >> 16) & 0xff); - mach64->accel.pattern_clr8x1[7] = ((mach64->pat_reg1 >> 24) & 0xff); - } - - mach64->accel.sc_left = mach64->sc_left_right & 0x1fff; - mach64->accel.sc_right = (mach64->sc_left_right >> 16) & 0x1fff; - mach64->accel.sc_top = mach64->sc_top_bottom & 0x7fff; - mach64->accel.sc_bottom = (mach64->sc_top_bottom >> 16) & 0x7fff; + mach64->accel.sc_left = mach64->sc_left_right & 0x1fff; + mach64->accel.sc_right = (mach64->sc_left_right >> 16) & 0x1fff; + mach64->accel.sc_top = mach64->sc_top_bottom & 0x7fff; + mach64->accel.sc_bottom = (mach64->sc_top_bottom >> 16) & 0x7fff; - mach64->accel.dp_frgd_clr = mach64->dp_frgd_clr; - mach64->accel.dp_bkgd_clr = mach64->dp_bkgd_clr; + mach64->accel.dp_frgd_clr = mach64->dp_frgd_clr; + mach64->accel.dp_bkgd_clr = mach64->dp_bkgd_clr; + mach64->accel.write_mask = mach64->write_mask; - mach64->accel.clr_cmp_clr = mach64->clr_cmp_clr & mach64->clr_cmp_mask; - mach64->accel.clr_cmp_mask = mach64->clr_cmp_mask; - mach64->accel.clr_cmp_fn = mach64->clr_cmp_cntl & 7; - mach64->accel.clr_cmp_src = mach64->clr_cmp_cntl & (1 << 24); - - mach64->accel.poly_draw = 0; - - mach64->accel.busy = 1; - mach64_log("mach64_start_fill : dst %i, %i src %i, %i size %i, %i src pitch %i offset %X dst pitch %i offset %X scissor %i %i %i %i src_fg %i mix %02X %02X\n", mach64->accel.dst_x_start, mach64->accel.dst_y_start, mach64->accel.src_x_start, mach64->accel.src_y_start, mach64->accel.dst_width, mach64->accel.dst_height, mach64->accel.src_pitch, mach64->accel.src_offset, mach64->accel.dst_pitch, mach64->accel.dst_offset, mach64->accel.sc_left, mach64->accel.sc_right, mach64->accel.sc_top, mach64->accel.sc_bottom, mach64->accel.source_fg, mach64->accel.mix_fg, mach64->accel.mix_bg); + mach64->accel.x_count = mach64->dst_bres_lnth & 0x7fff; + mach64->accel.err = (mach64->dst_bres_err & 0x3ffff) | ((mach64->dst_bres_err & 0x40000) ? 0xfffc0000 : 0); - mach64->accel.op = OP_RECT; + mach64->accel.clr_cmp_clr = mach64->clr_cmp_clr & mach64->clr_cmp_mask; + mach64->accel.clr_cmp_mask = mach64->clr_cmp_mask; + mach64->accel.clr_cmp_fn = mach64->clr_cmp_cntl & 7; + mach64->accel.clr_cmp_src = mach64->clr_cmp_cntl & (1 << 24); + + mach64->accel.xinc = (mach64->dst_cntl & DST_X_DIR) ? 1 : -1; + mach64->accel.yinc = (mach64->dst_cntl & DST_Y_DIR) ? 1 : -1; + + mach64->accel.busy = 1; + mach64_log("mach64_start_line\n"); + + mach64->accel.op = OP_LINE; } -void mach64_start_line(mach64_t *mach64) +#define READ(addr, dat, width) \ + if (width == 0) \ + dat = svga->vram[((addr)) & mach64->vram_mask]; \ + else if (width == 1) \ + dat = *(uint16_t *) &svga->vram[((addr) << 1) & mach64->vram_mask]; \ + else if (width == 2) \ + dat = *(uint32_t *) &svga->vram[((addr) << 2) & mach64->vram_mask]; \ + else if (mach64->dp_pix_width & DP_BYTE_PIX_ORDER) \ + dat = (svga->vram[((addr) >> 3) & mach64->vram_mask] >> ((addr) &7)) & 1; \ + else \ + dat = (svga->vram[((addr) >> 3) & mach64->vram_mask] >> (7 - ((addr) &7))) & 1; + +#define MIX \ + switch (mix ? mach64->accel.mix_fg : mach64->accel.mix_bg) { \ + case 0x0: \ + dest_dat = ~dest_dat; \ + break; \ + case 0x1: \ + dest_dat = 0; \ + break; \ + case 0x2: \ + dest_dat = 0xffffffff; \ + break; \ + case 0x3: \ + dest_dat = dest_dat; \ + break; \ + case 0x4: \ + dest_dat = ~src_dat; \ + break; \ + case 0x5: \ + dest_dat = src_dat ^ dest_dat; \ + break; \ + case 0x6: \ + dest_dat = ~(src_dat ^ dest_dat); \ + break; \ + case 0x7: \ + dest_dat = src_dat; \ + break; \ + case 0x8: \ + dest_dat = ~(src_dat & dest_dat); \ + break; \ + case 0x9: \ + dest_dat = ~src_dat | dest_dat; \ + break; \ + case 0xa: \ + dest_dat = src_dat | ~dest_dat; \ + break; \ + case 0xb: \ + dest_dat = src_dat | dest_dat; \ + break; \ + case 0xc: \ + dest_dat = src_dat & dest_dat; \ + break; \ + case 0xd: \ + dest_dat = src_dat & ~dest_dat; \ + break; \ + case 0xe: \ + dest_dat = ~src_dat & dest_dat; \ + break; \ + case 0xf: \ + dest_dat = ~(src_dat | dest_dat); \ + break; \ + case 0x17: \ + dest_dat = (dest_dat + src_dat) >> 1; \ + break; \ + } + +#define WRITE(addr, width) \ + if (width == 0) { \ + svga->vram[(addr) &mach64->vram_mask] = dest_dat; \ + svga->changedvram[((addr) &mach64->vram_mask) >> 12] = svga->monitor->mon_changeframecount; \ + } else if (width == 1) { \ + *(uint16_t *) &svga->vram[((addr) << 1) & mach64->vram_mask] = dest_dat; \ + svga->changedvram[(((addr) << 1) & mach64->vram_mask) >> 12] = svga->monitor->mon_changeframecount; \ + } else if (width == 2) { \ + *(uint32_t *) &svga->vram[((addr) << 2) & mach64->vram_mask] = dest_dat; \ + svga->changedvram[(((addr) << 2) & mach64->vram_mask) >> 12] = svga->monitor->mon_changeframecount; \ + } else { \ + if (dest_dat & 1) { \ + if (mach64->dp_pix_width & DP_BYTE_PIX_ORDER) \ + svga->vram[((addr) >> 3) & mach64->vram_mask] |= 1 << ((addr) &7); \ + else \ + svga->vram[((addr) >> 3) & mach64->vram_mask] |= 1 << (7 - ((addr) &7)); \ + } else { \ + if (mach64->dp_pix_width & DP_BYTE_PIX_ORDER) \ + svga->vram[((addr) >> 3) & mach64->vram_mask] &= ~(1 << ((addr) &7)); \ + else \ + svga->vram[((addr) >> 3) & mach64->vram_mask] &= ~(1 << (7 - ((addr) &7))); \ + } \ + svga->changedvram[(((addr) >> 3) & mach64->vram_mask) >> 12] = svga->monitor->mon_changeframecount; \ + } + +void +mach64_blit(uint32_t cpu_dat, int count, mach64_t *mach64) { - int x, y; - - mach64->accel.dst_x = (mach64->dst_y_x >> 16) & 0xfff; - mach64->accel.dst_y = mach64->dst_y_x & 0xfff; + svga_t *svga = &mach64->svga; + int cmp_clr = 0; + int mix = 0; - mach64->accel.src_x = (mach64->src_y_x >> 16) & 0xfff; - mach64->accel.src_y = mach64->src_y_x & 0xfff; + if (!mach64->accel.busy) { + mach64_log("mach64_blit : return as not busy\n"); + return; + } - mach64->accel.src_pitch = (mach64->src_off_pitch >> 22) * 8; - mach64->accel.src_offset = (mach64->src_off_pitch & 0xfffff) * 8; + 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 dst_x; + int dst_y; + int src_x; + int src_y; - mach64->accel.dst_pitch = (mach64->dst_off_pitch >> 22) * 8; - mach64->accel.dst_offset = (mach64->dst_off_pitch & 0xfffff) * 8; - - mach64->accel.mix_fg = (mach64->dp_mix >> 16) & 0x1f; - mach64->accel.mix_bg = mach64->dp_mix & 0x1f; - - mach64->accel.source_bg = mach64->dp_src & 7; - mach64->accel.source_fg = (mach64->dp_src >> 8) & 7; - mach64->accel.source_mix = (mach64->dp_src >> 16) & 7; - - mach64->accel.dst_pix_width = mach64->dp_pix_width & 7; - mach64->accel.src_pix_width = (mach64->dp_pix_width >> 8) & 7; - mach64->accel.host_pix_width = (mach64->dp_pix_width >> 16) & 7; - - mach64->accel.dst_size = mach64_width[mach64->accel.dst_pix_width]; - mach64->accel.src_size = mach64_width[mach64->accel.src_pix_width]; - mach64->accel.host_size = mach64_width[mach64->accel.host_pix_width]; - - if (mach64->accel.src_size == WIDTH_1BIT) - mach64->accel.src_offset <<= 3; - else - mach64->accel.src_offset >>= mach64->accel.src_size; - - if (mach64->accel.dst_size == WIDTH_1BIT) - mach64->accel.dst_offset <<= 3; - else - mach64->accel.dst_offset >>= mach64->accel.dst_size; + dst_x = (mach64->accel.dst_x + mach64->accel.dst_x_start) & 0xfff; + dst_y = (mach64->accel.dst_y + mach64->accel.dst_y_start) & 0x3fff; -/* 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 (y = 0; y < 8; y++) - { - for (x = 0; x < 8; x++) - { - uint32_t temp = (y & 4) ? mach64->pat_reg1 : mach64->pat_reg0; - mach64->accel.pattern[y][7 - x] = (temp >> (x + ((y & 3) * 8))) & 1; - } - } - - mach64->accel.sc_left = mach64->sc_left_right & 0x1fff; - mach64->accel.sc_right = (mach64->sc_left_right >> 16) & 0x1fff; - mach64->accel.sc_top = mach64->sc_top_bottom & 0x7fff; - mach64->accel.sc_bottom = (mach64->sc_top_bottom >> 16) & 0x7fff; - - mach64->accel.dp_frgd_clr = mach64->dp_frgd_clr; - mach64->accel.dp_bkgd_clr = mach64->dp_bkgd_clr; - - mach64->accel.x_count = mach64->dst_bres_lnth & 0x7fff; - mach64->accel.err = (mach64->dst_bres_err & 0x3ffff) | ((mach64->dst_bres_err & 0x40000) ? 0xfffc0000 : 0); - - mach64->accel.clr_cmp_clr = mach64->clr_cmp_clr & mach64->clr_cmp_mask; - mach64->accel.clr_cmp_mask = mach64->clr_cmp_mask; - mach64->accel.clr_cmp_fn = mach64->clr_cmp_cntl & 7; - mach64->accel.clr_cmp_src = mach64->clr_cmp_cntl & (1 << 24); + 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; - mach64->accel.busy = 1; - mach64_log("mach64_start_line\n"); + src_y = (mach64->accel.src_y + mach64->accel.src_y_start) & 0x3fff; - mach64->accel.op = OP_LINE; -} + if (mach64->accel.source_host) { + host_dat = cpu_dat; + switch (mach64->accel.host_size) { + case 0: + cpu_dat >>= 8; + count -= 8; + break; + case 1: + cpu_dat >>= 16; + count -= 16; + break; + case 2: + count -= 32; + break; -#define READ(addr, dat, width) if (width == 0) dat = svga->vram[((addr)) & mach64->vram_mask]; \ - else if (width == 1) dat = *(uint16_t *)&svga->vram[((addr) << 1) & mach64->vram_mask]; \ - else if (width == 2) dat = *(uint32_t *)&svga->vram[((addr) << 2) & mach64->vram_mask]; \ - else if (mach64->dp_pix_width & DP_BYTE_PIX_ORDER) dat = (svga->vram[((addr) >> 3) & mach64->vram_mask] >> ((addr) & 7)) & 1; \ - else dat = (svga->vram[((addr) >> 3) & mach64->vram_mask] >> (7 - ((addr) & 7))) & 1; - -#define MIX switch (mix ? mach64->accel.mix_fg : mach64->accel.mix_bg) \ - { \ - case 0x0: dest_dat = ~dest_dat; break; \ - case 0x1: dest_dat = 0; break; \ - case 0x2: dest_dat = 0xffffffff; break; \ - case 0x3: dest_dat = dest_dat; break; \ - case 0x4: dest_dat = ~src_dat; break; \ - case 0x5: dest_dat = src_dat ^ dest_dat; break; \ - case 0x6: dest_dat = ~(src_dat ^ dest_dat); break; \ - case 0x7: dest_dat = src_dat; break; \ - case 0x8: dest_dat = ~(src_dat & dest_dat); break; \ - case 0x9: dest_dat = ~src_dat | dest_dat; break; \ - case 0xa: dest_dat = src_dat | ~dest_dat; break; \ - case 0xb: dest_dat = src_dat | dest_dat; break; \ - case 0xc: dest_dat = src_dat & dest_dat; break; \ - case 0xd: dest_dat = src_dat & ~dest_dat; break; \ - case 0xe: dest_dat = ~src_dat & dest_dat; break; \ - case 0xf: dest_dat = ~(src_dat | dest_dat); break; \ - } - -#define WRITE(addr, width) if (width == 0) \ - { \ - svga->vram[(addr) & mach64->vram_mask] = dest_dat; \ - svga->changedvram[((addr) & mach64->vram_mask) >> 12] = changeframecount; \ - } \ - else if (width == 1) \ - { \ - *(uint16_t *)&svga->vram[((addr) << 1) & mach64->vram_mask] = dest_dat; \ - svga->changedvram[(((addr) << 1) & mach64->vram_mask) >> 12] = changeframecount; \ - } \ - else if (width == 2) \ - { \ - *(uint32_t *)&svga->vram[((addr) << 2) & mach64->vram_mask] = dest_dat; \ - svga->changedvram[(((addr) << 2) & mach64->vram_mask) >> 12] = changeframecount; \ - } \ - else \ - { \ - if (dest_dat & 1) { \ - if (mach64->dp_pix_width & DP_BYTE_PIX_ORDER) \ - svga->vram[((addr) >> 3) & mach64->vram_mask] |= 1 << ((addr) & 7); \ - else \ - svga->vram[((addr) >> 3) & mach64->vram_mask] |= 1 << (7 - ((addr) & 7)); \ - } else { \ - if (mach64->dp_pix_width & DP_BYTE_PIX_ORDER) \ - svga->vram[((addr) >> 3) & mach64->vram_mask] &= ~(1 << ((addr) & 7)); \ - else \ - svga->vram[((addr) >> 3) & mach64->vram_mask] &= ~(1 << (7 - ((addr) & 7)));\ - } \ - svga->changedvram[(((addr) >> 3) & mach64->vram_mask) >> 12] = changeframecount; \ - } + default: + break; + } + } else + count--; -void mach64_blit(uint32_t cpu_dat, int count, mach64_t *mach64) -{ - svga_t *svga = &mach64->svga; - int cmp_clr = 0; - - if (!mach64->accel.busy) - { - mach64_log("mach64_blit : return as not busy\n"); - return; - } - switch (mach64->accel.op) - { - case OP_RECT: - while (count) - { - uint32_t src_dat, dest_dat; - uint32_t host_dat = 0; - 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 src_x; - int src_y = (mach64->accel.src_y + mach64->accel.src_y_start) & 0xfff; - - 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; - - if (mach64->accel.source_host) - { - host_dat = cpu_dat; - switch (mach64->accel.host_size) - { - case 0: - cpu_dat >>= 8; - count -= 8; - break; - case 1: - cpu_dat >>= 16; - count -= 16; - break; - case 2: - count -= 32; - break; - } + switch (mach64->accel.source_mix) { + case MONO_SRC_HOST: + if (mach64->dp_pix_width & DP_BYTE_PIX_ORDER) { + mix = cpu_dat & 1; + cpu_dat >>= 1; + } else { + mix = cpu_dat >> 0x1f; + cpu_dat <<= 1; } - else - count--; - - switch (mach64->accel.source_mix) - { - case MONO_SRC_HOST: - if (mach64->dp_pix_width & DP_BYTE_PIX_ORDER) - { - mix = cpu_dat & 1; - cpu_dat >>= 1; - } - else - { - mix = cpu_dat >> 31; - cpu_dat <<= 1; - } - break; - case MONO_SRC_PAT: + break; + case MONO_SRC_PAT: + if (mach64->dst_cntl & DST_24_ROT_EN) { + if (!mach64->accel.xx_count) mix = mach64->accel.pattern[dst_y & 7][dst_x & 7]; - break; - case MONO_SRC_1: - mix = 1; - break; - case MONO_SRC_BLITSRC: - if (mach64->src_cntl & SRC_LINEAR_EN) - { - READ(mach64->accel.src_offset + src_x, mix, WIDTH_1BIT); + } else + mix = mach64->accel.pattern[dst_y & 7][dst_x & 7]; + break; + case MONO_SRC_1: + mix = 1; + break; + case MONO_SRC_BLITSRC: + if (mach64->src_cntl & SRC_LINEAR_EN) { + READ(mach64->accel.src_offset + src_x, mix, WIDTH_1BIT); + } else { + READ(mach64->accel.src_offset + (src_y * mach64->accel.src_pitch) + src_x, mix, WIDTH_1BIT); + } + break; + + default: + 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) { + switch (mix ? mach64->accel.source_fg : mach64->accel.source_bg) { + case SRC_HOST: + src_dat = host_dat; + break; + case SRC_BLITSRC: + 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_24_ROT_EN) { + if (mach64->accel.xinc == -1) { + if (mach64->accel.xx_count == 2) + src_dat = mach64->accel.dp_frgd_clr & 0xff; + else if (mach64->accel.xx_count == 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 == 2) + src_dat = (mach64->accel.dp_frgd_clr >> 16) & 0xff; + else if (mach64->accel.xx_count == 1) + src_dat = (mach64->accel.dp_frgd_clr >> 8) & 0xff; + else + src_dat = mach64->accel.dp_frgd_clr & 0xff; } - else - { - READ(mach64->accel.src_offset + (src_y * mach64->accel.src_pitch) + src_x, mix, WIDTH_1BIT); + } else + src_dat = mach64->accel.dp_frgd_clr; + break; + case SRC_BG: + if (mach64->dst_cntl & DST_24_ROT_EN) { + if (mach64->accel.xinc == -1) { + if (mach64->accel.xx_count == 2) + src_dat = mach64->accel.dp_bkgd_clr & 0xff; + else if (mach64->accel.xx_count == 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 == 2) + src_dat = (mach64->accel.dp_bkgd_clr >> 16) & 0xff; + else if (mach64->accel.xx_count == 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; + case SRC_PAT: + if (mach64->pat_cntl & 2) { + src_dat = mach64->accel.pattern_clr4x2[dst_y & 1][dst_x & 3]; + break; + } else if (mach64->pat_cntl & 4) { + src_dat = mach64->accel.pattern_clr8x1[dst_x & 7]; + break; + } + + default: + src_dat = 0; + break; + } + + if (mach64->dst_cntl & DST_POLYGON_EN) { + int poly_src; + READ(mach64->accel.src_offset + (src_y * mach64->accel.src_pitch) + src_x, poly_src, mach64->accel.src_size); + if (poly_src) + mach64->accel.poly_draw = !mach64->accel.poly_draw; + } + + 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); + + switch (mach64->accel.clr_cmp_fn) { + case 1: /*TRUE*/ + cmp_clr = 1; + break; + case 4: /*DST_CLR != CLR_CMP_CLR*/ + cmp_clr = (((mach64->accel.clr_cmp_src) ? src_dat : dest_dat) & mach64->accel.clr_cmp_mask) != mach64->accel.clr_cmp_clr; + break; + case 5: /*DST_CLR == CLR_CMP_CLR*/ + cmp_clr = (((mach64->accel.clr_cmp_src) ? src_dat : dest_dat) & mach64->accel.clr_cmp_mask) == mach64->accel.clr_cmp_clr; + break; + + default: 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) - { - switch (mix ? mach64->accel.source_fg : mach64->accel.source_bg) - { - case SRC_HOST: - src_dat = host_dat; - break; - case SRC_BLITSRC: - READ(mach64->accel.src_offset + (src_y * mach64->accel.src_pitch) + src_x, src_dat, mach64->accel.src_size); - break; - case SRC_FG: - src_dat = mach64->accel.dp_frgd_clr; - break; - case SRC_BG: - src_dat = mach64->accel.dp_bkgd_clr; - break; - case SRC_PAT: - if (mach64->pat_cntl & 2) { - src_dat = mach64->accel.pattern_clr4x2[dst_y & 1][dst_x & 3]; - break; - } else if (mach64->pat_cntl & 4) { - src_dat = mach64->accel.pattern_clr8x1[dst_x & 7]; - break; - } - default: - src_dat = 0; - break; - } - if (mach64->dst_cntl & DST_POLYGON_EN) - { - int poly_src; - READ(mach64->accel.src_offset + (src_y * mach64->accel.src_pitch) + src_x, poly_src, mach64->accel.src_size); - if (poly_src) - mach64->accel.poly_draw = !mach64->accel.poly_draw; - } - 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); - - switch (mach64->accel.clr_cmp_fn) - { - case 1: /*TRUE*/ - cmp_clr = 1; - break; - case 4: /*DST_CLR != CLR_CMP_CLR*/ - cmp_clr = (((mach64->accel.clr_cmp_src) ? src_dat : dest_dat) & mach64->accel.clr_cmp_mask) != mach64->accel.clr_cmp_clr; - break; - case 5: /*DST_CLR == CLR_CMP_CLR*/ - cmp_clr = (((mach64->accel.clr_cmp_src) ? src_dat : dest_dat) & mach64->accel.clr_cmp_mask) == mach64->accel.clr_cmp_clr; - break; - } - - if (!cmp_clr) - MIX - - WRITE(mach64->accel.dst_offset + (dst_y * mach64->accel.dst_pitch) + dst_x, mach64->accel.dst_size); + if (!cmp_clr) { + old_dest_dat = dest_dat; + MIX + if (mach64->dst_cntl & DST_24_ROT_EN) { + if (mach64->accel.xinc == -1) { + if (mach64->accel.xx_count == 2) + write_mask = mach64->accel.write_mask & 0xff; + else if (mach64->accel.xx_count == 1) + write_mask = (mach64->accel.write_mask >> 8) & 0xff; + else + write_mask = (mach64->accel.write_mask >> 16) & 0xff; + } else { + if (mach64->accel.xx_count == 2) + write_mask = (mach64->accel.write_mask >> 16) & 0xff; + else if (mach64->accel.xx_count == 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); } - - if (mach64->dst_cntl & 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.src_x += mach64->accel.xinc; - mach64->accel.dst_x += mach64->accel.xinc; - if (!(mach64->src_cntl & SRC_LINEAR_EN)) - { - mach64->accel.src_x_count--; - if (mach64->accel.src_x_count <= 0) - { - 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; - mach64->accel.src_x_count = mach64->accel.src_width2; - } - else - mach64->accel.src_x_count = mach64->accel.src_width1; - } - } - - mach64->accel.x_count--; - - if (mach64->accel.x_count <= 0) - { - mach64->accel.x_count = mach64->accel.dst_width; - mach64->accel.dst_x = 0; - mach64->accel.dst_y += mach64->accel.yinc; - mach64->accel.src_x_start = (mach64->src_y_x >> 16) & 0xfff; - mach64->accel.src_x_count = mach64->accel.src_width1; - if (!(mach64->src_cntl & SRC_LINEAR_EN)) - { - mach64->accel.src_x = 0; - mach64->accel.src_y += mach64->accel.yinc; - mach64->accel.src_y_count--; - 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_count = mach64->accel.src_height2; - } - else - mach64->accel.src_y_count = mach64->accel.src_height1; - } - } + WRITE(mach64->accel.dst_offset + ((dst_y) * mach64->accel.dst_pitch) + (dst_x), mach64->accel.dst_size); + } + } - mach64->accel.poly_draw = 0; - - mach64->accel.dst_height--; - - if (mach64->accel.dst_height <= 0) - { - /*Blit finished*/ - mach64_log("mach64 blit finished\n"); - mach64->accel.busy = 0; - if (mach64->dst_cntl & DST_X_TILE) - mach64->dst_y_x = (mach64->dst_y_x & 0xfff) | ((mach64->dst_y_x + (mach64->accel.dst_width << 16)) & 0xfff0000); - if (mach64->dst_cntl & DST_Y_TILE) - mach64->dst_y_x = (mach64->dst_y_x & 0xfff0000) | ((mach64->dst_y_x + (mach64->dst_height_width & 0x1fff)) & 0xfff); - return; - } - if (mach64->host_cntl & HOST_BYTE_ALIGN) - { - if (mach64->accel.source_mix == MONO_SRC_HOST) - { - if (mach64->dp_pix_width & DP_BYTE_PIX_ORDER) - cpu_dat >>= (count & 7); - else - cpu_dat <<= (count & 7); - count &= ~7; - } - } - } - } - break; - - case OP_LINE: - while (count) - { - uint32_t src_dat = 0, dest_dat; - uint32_t host_dat = 0; - int mix = 0; - int draw_pixel = !(mach64->dst_cntl & DST_POLYGON_EN); - - if (mach64->accel.source_host) - { - host_dat = cpu_dat; - switch (mach64->accel.src_size) - { - case 0: - cpu_dat >>= 8; - count -= 8; - break; - case 1: - cpu_dat >>= 16; - count -= 16; - break; - case 2: - count -= 32; - break; - } - } - else - count--; + mach64->accel.src_x += mach64->accel.xinc; + mach64->accel.dst_x += mach64->accel.xinc; + if (!(mach64->src_cntl & SRC_LINEAR_EN)) { + mach64->accel.src_x_count--; + if (mach64->accel.src_x_count <= 0) { + 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; + } + } - switch (mach64->accel.source_mix) - { - case MONO_SRC_HOST: + mach64->accel.x_count--; + mach64->accel.xx_count = (mach64->accel.xx_count + 1) % 3; + if (mach64->accel.x_count <= 0) { + mach64->accel.x_count = mach64->accel.dst_width; + mach64->accel.xx_count = 0; + mach64->accel.dst_x = 0; + mach64->accel.dst_y += mach64->accel.yinc; + mach64->accel.src_x_start = (mach64->src_y_x >> 16) & 0xfff; + mach64->accel.src_x_count = mach64->accel.src_width1; + + if (!(mach64->src_cntl & SRC_LINEAR_EN)) { + mach64->accel.src_x = 0; + mach64->accel.src_y += mach64->accel.yinc; + mach64->accel.src_y_count--; + 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 & 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; + } + } + + mach64->accel.poly_draw = 0; + mach64->accel.dst_height--; + if (mach64->accel.dst_height <= 0) { + /*Blit finished*/ + mach64_log("mach64 blit finished\n"); + mach64->accel.busy = 0; + if (mach64->dst_cntl & DST_X_TILE) + mach64->dst_y_x = (mach64->dst_y_x & 0xfff) | ((mach64->dst_y_x + (mach64->accel.dst_width << 16)) & 0xfff0000); + if (mach64->dst_cntl & DST_Y_TILE) + mach64->dst_y_x = (mach64->dst_y_x & 0xfff0000) | ((mach64->dst_y_x + (mach64->dst_height_width & 0x1fff)) & 0xfff); + return; + } + if (mach64->host_cntl & HOST_BYTE_ALIGN) { + if (mach64->accel.source_mix == MONO_SRC_HOST) { + if (mach64->dp_pix_width & DP_BYTE_PIX_ORDER) + cpu_dat >>= (count & 7); + else + cpu_dat <<= (count & 7); + count &= ~7; + } + } + } + } + break; + + case OP_LINE: + if (((mach64->crtc_gen_cntl >> 8) & 7) == BPP_24) { + int x = 0; + while (count) { + uint32_t src_dat = 0; + uint32_t dest_dat; + uint32_t host_dat = 0; + int mix = 0; + + if (mach64->accel.source_host) { + host_dat = cpu_dat; + switch (mach64->accel.host_size) { + case 0: + cpu_dat >>= 8; + count -= 8; + break; + case 1: + cpu_dat >>= 16; + count -= 16; + break; + case 2: + count -= 32; + break; + + default: + break; + } + } else + count--; + + switch (mach64->accel.source_mix) { + case MONO_SRC_HOST: + if (mach64->dp_pix_width & DP_BYTE_PIX_ORDER) { + mix = cpu_dat & 1; + cpu_dat >>= 1; + } else { mix = cpu_dat >> 31; cpu_dat <<= 1; - break; - case MONO_SRC_PAT: - mix = mach64->accel.pattern[mach64->accel.dst_y & 7][mach64->accel.dst_x & 7]; - break; - case MONO_SRC_1: - default: - mix = 1; - break; - } - - if (mach64->dst_cntl & DST_POLYGON_EN) - { - if (mach64->dst_cntl & DST_Y_MAJOR) - draw_pixel = 1; - else if ((mach64->dst_cntl & DST_X_DIR) && mach64->accel.err < (mach64->dst_bres_dec + mach64->dst_bres_inc)) /*X+*/ - draw_pixel = 1; - else if (!(mach64->dst_cntl & DST_X_DIR) && mach64->accel.err >= 0) /*X-*/ - draw_pixel = 1; - } + } + break; + case MONO_SRC_PAT: + mix = mach64->accel.pattern[mach64->accel.dst_y & 7][mach64->accel.dst_x & 7]; + break; + case MONO_SRC_1: + mix = 1; + break; + case MONO_SRC_BLITSRC: + READ(mach64->accel.src_offset + (mach64->accel.src_y * mach64->accel.src_pitch) + mach64->accel.src_x, mix, WIDTH_1BIT); + break; - if (mach64->accel.x_count == 1 && !(mach64->dst_cntl & DST_LAST_PEL)) - draw_pixel = 0; + default: + break; + } - if (mach64->accel.dst_x >= mach64->accel.sc_left && mach64->accel.dst_x <= mach64->accel.sc_right && - mach64->accel.dst_y >= mach64->accel.sc_top && mach64->accel.dst_y <= mach64->accel.sc_bottom && draw_pixel) - { - switch (mix ? mach64->accel.source_fg : mach64->accel.source_bg) - { - case SRC_HOST: - src_dat = host_dat; - break; - case SRC_BLITSRC: - READ(mach64->accel.src_offset + (mach64->accel.src_y * mach64->accel.src_pitch) + mach64->accel.src_x, src_dat, mach64->accel.src_size); - break; - case SRC_FG: - src_dat = mach64->accel.dp_frgd_clr; - break; - case SRC_BG: - src_dat = mach64->accel.dp_bkgd_clr; - break; - default: - src_dat = 0; - break; + if ((mach64->accel.dst_x >= mach64->accel.sc_left) && (mach64->accel.dst_x <= mach64->accel.sc_right) && (mach64->accel.dst_y >= mach64->accel.sc_top) && (mach64->accel.dst_y <= mach64->accel.sc_bottom)) { + switch (mix ? mach64->accel.source_fg : mach64->accel.source_bg) { + case SRC_HOST: + src_dat = host_dat; + break; + case SRC_BLITSRC: + READ(mach64->accel.src_offset + (mach64->accel.src_y * mach64->accel.src_pitch) + mach64->accel.src_x, src_dat, mach64->accel.src_size); + break; + case SRC_FG: + src_dat = mach64->accel.dp_frgd_clr; + break; + case SRC_BG: + src_dat = mach64->accel.dp_bkgd_clr; + break; + case SRC_PAT: + if (mach64->pat_cntl & 2) { + src_dat = mach64->accel.pattern_clr4x2[mach64->accel.dst_y & 1][mach64->accel.dst_x & 3]; + break; + } else if (mach64->pat_cntl & 4) { + src_dat = mach64->accel.pattern_clr8x1[mach64->accel.dst_x & 7]; + break; } - - READ(mach64->accel.dst_offset + (mach64->accel.dst_y * mach64->accel.dst_pitch) + mach64->accel.dst_x, dest_dat, mach64->accel.dst_size); - - switch (mach64->accel.clr_cmp_fn) - { - case 1: /*TRUE*/ - cmp_clr = 1; - break; - case 4: /*DST_CLR != CLR_CMP_CLR*/ - cmp_clr = (((mach64->accel.clr_cmp_src) ? src_dat : dest_dat) & mach64->accel.clr_cmp_mask) != mach64->accel.clr_cmp_clr; - break; - case 5: /*DST_CLR == CLR_CMP_CLR*/ - cmp_clr = (((mach64->accel.clr_cmp_src) ? src_dat : dest_dat) & mach64->accel.clr_cmp_mask) == mach64->accel.clr_cmp_clr; - break; - } - - 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); - } - - mach64->accel.x_count--; - if (mach64->accel.x_count <= 0) - { - /*Blit finished*/ - mach64_log("mach64 blit finished\n"); - mach64->accel.busy = 0; - return; - } - - switch (mach64->dst_cntl & 7) - { - case 0: case 2: - mach64->accel.src_x--; - mach64->accel.dst_x--; + default: + src_dat = 0; break; - case 1: case 3: - mach64->accel.src_x++; - mach64->accel.dst_x++; + } + + READ(mach64->accel.dst_offset + (mach64->accel.dst_y * mach64->accel.dst_pitch) + mach64->accel.dst_x, dest_dat, mach64->accel.dst_size); + + switch (mach64->accel.clr_cmp_fn) { + case 1: /*TRUE*/ + cmp_clr = 1; break; - case 4: case 5: + case 4: /*DST_CLR != CLR_CMP_CLR*/ + cmp_clr = (((mach64->accel.clr_cmp_src) ? src_dat : dest_dat) & mach64->accel.clr_cmp_mask) != mach64->accel.clr_cmp_clr; + break; + case 5: /*DST_CLR == CLR_CMP_CLR*/ + cmp_clr = (((mach64->accel.clr_cmp_src) ? src_dat : dest_dat) & mach64->accel.clr_cmp_mask) == mach64->accel.clr_cmp_clr; + break; + + default: + break; + } + + if (!cmp_clr) + MIX + + if (!(mach64->dst_cntl & DST_Y_MAJOR)) { + if (!x) + dest_dat &= ~1; + } else { + if (x == (mach64->accel.x_count - 1)) + dest_dat &= ~1; + } + + WRITE(mach64->accel.dst_offset + (mach64->accel.dst_y * mach64->accel.dst_pitch) + mach64->accel.dst_x, mach64->accel.dst_size); + } + + x++; + if (x >= mach64->accel.x_count) { + mach64->accel.busy = 0; + mach64_log("mach64 line24 finished\n"); + return; + } + + if (mach64->dst_cntl & DST_Y_MAJOR) { + mach64->accel.dst_y += mach64->accel.yinc; + if (mach64->accel.err >= 0) { + mach64->accel.err += mach64->dst_bres_dec; + mach64->accel.dst_x += mach64->accel.xinc; + } else { + mach64->accel.err += mach64->dst_bres_inc; + } + } else { + mach64->accel.dst_x += mach64->accel.xinc; + if (mach64->accel.err >= 0) { + mach64->accel.err += mach64->dst_bres_dec; + mach64->accel.dst_y += mach64->accel.yinc; + } else { + mach64->accel.err += mach64->dst_bres_inc; + } + } + } + } else { + while (count) { + uint32_t src_dat = 0; + uint32_t dest_dat; + uint32_t host_dat = 0; + int mix = 0; + int draw_pixel = !(mach64->dst_cntl & DST_POLYGON_EN); + + if (mach64->accel.source_host) { + host_dat = cpu_dat; + switch (mach64->accel.host_size) { + case 0: + cpu_dat >>= 8; + count -= 8; + break; + case 1: + cpu_dat >>= 16; + count -= 16; + break; + case 2: + count -= 32; + break; + + default: + break; + } + } else + count--; + + switch (mach64->accel.source_mix) { + case MONO_SRC_HOST: + mix = cpu_dat >> 31; + cpu_dat <<= 1; + break; + case MONO_SRC_PAT: + mix = mach64->accel.pattern[mach64->accel.dst_y & 7][mach64->accel.dst_x & 7]; + break; + case MONO_SRC_1: + default: + mix = 1; + break; + } + + if (mach64->dst_cntl & DST_POLYGON_EN) { + if (mach64->dst_cntl & DST_Y_MAJOR) + draw_pixel = 1; + else if ((mach64->dst_cntl & DST_X_DIR) && mach64->accel.err < (mach64->dst_bres_dec + mach64->dst_bres_inc)) /*X+*/ + draw_pixel = 1; + else if (!(mach64->dst_cntl & DST_X_DIR) && mach64->accel.err >= 0) /*X-*/ + draw_pixel = 1; + } + + if (mach64->accel.x_count == 1 && !(mach64->dst_cntl & DST_LAST_PEL)) + draw_pixel = 0; + + if (mach64->accel.dst_x >= mach64->accel.sc_left && mach64->accel.dst_x <= mach64->accel.sc_right && mach64->accel.dst_y >= mach64->accel.sc_top && mach64->accel.dst_y <= mach64->accel.sc_bottom && draw_pixel) { + switch (mix ? mach64->accel.source_fg : mach64->accel.source_bg) { + case SRC_HOST: + src_dat = host_dat; + break; + case SRC_BLITSRC: + READ(mach64->accel.src_offset + (mach64->accel.src_y * mach64->accel.src_pitch) + mach64->accel.src_x, src_dat, mach64->accel.src_size); + break; + case SRC_FG: + src_dat = mach64->accel.dp_frgd_clr; + break; + case SRC_BG: + src_dat = mach64->accel.dp_bkgd_clr; + break; + default: + src_dat = 0; + break; + } + + READ(mach64->accel.dst_offset + (mach64->accel.dst_y * mach64->accel.dst_pitch) + mach64->accel.dst_x, dest_dat, mach64->accel.dst_size); + + switch (mach64->accel.clr_cmp_fn) { + case 1: /*TRUE*/ + cmp_clr = 1; + break; + case 4: /*DST_CLR != CLR_CMP_CLR*/ + cmp_clr = (((mach64->accel.clr_cmp_src) ? src_dat : dest_dat) & mach64->accel.clr_cmp_mask) != mach64->accel.clr_cmp_clr; + break; + case 5: /*DST_CLR == CLR_CMP_CLR*/ + cmp_clr = (((mach64->accel.clr_cmp_src) ? src_dat : dest_dat) & mach64->accel.clr_cmp_mask) == mach64->accel.clr_cmp_clr; + break; + + default: + break; + } + + 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); + } + + mach64->accel.x_count--; + if (mach64->accel.x_count <= 0) { + /*Blit finished*/ + mach64_log("mach64 blit finished\n"); + mach64->accel.busy = 0; + return; + } + + switch (mach64->dst_cntl & 7) { + case 0: + case 2: + mach64->accel.src_x--; + mach64->accel.dst_x--; + break; + case 1: + case 3: + mach64->accel.src_x++; + mach64->accel.dst_x++; + break; + case 4: + case 5: + mach64->accel.src_y--; + mach64->accel.dst_y--; + break; + case 6: + case 7: + mach64->accel.src_y++; + mach64->accel.dst_y++; + break; + + default: + break; + } + mach64_log("x %i y %i err %i inc %i dec %i\n", mach64->accel.dst_x, mach64->accel.dst_y, mach64->accel.err, mach64->dst_bres_inc, mach64->dst_bres_dec); + if (mach64->accel.err >= 0) { + mach64->accel.err += mach64->dst_bres_dec; + + switch (mach64->dst_cntl & 7) { + case 0: + case 1: mach64->accel.src_y--; mach64->accel.dst_y--; break; - case 6: case 7: + case 2: + case 3: mach64->accel.src_y++; mach64->accel.dst_y++; break; + case 4: + case 6: + mach64->accel.src_x--; + mach64->accel.dst_x--; + break; + case 5: + case 7: + mach64->accel.src_x++; + mach64->accel.dst_x++; + break; + + default: + break; } - mach64_log("x %i y %i err %i inc %i dec %i\n", mach64->accel.dst_x, mach64->accel.dst_y, mach64->accel.err, mach64->dst_bres_inc, mach64->dst_bres_dec); - if (mach64->accel.err >= 0) - { - mach64->accel.err += mach64->dst_bres_dec; - - switch (mach64->dst_cntl & 7) - { - case 0: case 1: - mach64->accel.src_y--; - mach64->accel.dst_y--; - break; - case 2: case 3: - mach64->accel.src_y++; - mach64->accel.dst_y++; - break; - case 4: case 6: - mach64->accel.src_x--; - mach64->accel.dst_x--; - break; - case 5: case 7: - mach64->accel.src_x++; - mach64->accel.dst_x++; - break; - } - } - else - mach64->accel.err += mach64->dst_bres_inc; + } else + mach64->accel.err += mach64->dst_bres_inc; } - break; - } + } + break; + + default: + break; + } } -void mach64_load_context(mach64_t *mach64) +void +mach64_load_context(mach64_t *mach64) { - svga_t *svga = &mach64->svga; - uint32_t addr; - - while (mach64->context_load_cntl & 0x30000) - { - addr = ((0x3fff - (mach64->context_load_cntl & 0x3fff)) * 256) & mach64->vram_mask; - mach64->context_mask = *(uint32_t *)&svga->vram[addr]; - mach64_log("mach64_load_context %08X from %08X : mask %08X\n", mach64->context_load_cntl, addr, mach64->context_mask); + svga_t *svga = &mach64->svga; + uint32_t addr; - if (mach64->context_mask & (1 << 2)) - mach64_accel_write_fifo_l(mach64, 0x100, *(uint32_t *)&svga->vram[addr + 0x08]); - if (mach64->context_mask & (1 << 3)) - mach64_accel_write_fifo_l(mach64, 0x10c, *(uint32_t *)&svga->vram[addr + 0x0c]); - if (mach64->context_mask & (1 << 4)) - mach64_accel_write_fifo_l(mach64, 0x118, *(uint32_t *)&svga->vram[addr + 0x10]); - if (mach64->context_mask & (1 << 5)) - mach64_accel_write_fifo_l(mach64, 0x124, *(uint32_t *)&svga->vram[addr + 0x14]); - if (mach64->context_mask & (1 << 6)) - mach64_accel_write_fifo_l(mach64, 0x128, *(uint32_t *)&svga->vram[addr + 0x18]); - if (mach64->context_mask & (1 << 7)) - mach64_accel_write_fifo_l(mach64, 0x12c, *(uint32_t *)&svga->vram[addr + 0x1c]); - if (mach64->context_mask & (1 << 8)) - mach64_accel_write_fifo_l(mach64, 0x180, *(uint32_t *)&svga->vram[addr + 0x20]); - if (mach64->context_mask & (1 << 9)) - mach64_accel_write_fifo_l(mach64, 0x18c, *(uint32_t *)&svga->vram[addr + 0x24]); - if (mach64->context_mask & (1 << 10)) - mach64_accel_write_fifo_l(mach64, 0x198, *(uint32_t *)&svga->vram[addr + 0x28]); - if (mach64->context_mask & (1 << 11)) - mach64_accel_write_fifo_l(mach64, 0x1a4, *(uint32_t *)&svga->vram[addr + 0x2c]); - if (mach64->context_mask & (1 << 12)) - mach64_accel_write_fifo_l(mach64, 0x1b0, *(uint32_t *)&svga->vram[addr + 0x30]); - if (mach64->context_mask & (1 << 13)) - mach64_accel_write_fifo_l(mach64, 0x280, *(uint32_t *)&svga->vram[addr + 0x34]); - if (mach64->context_mask & (1 << 14)) - mach64_accel_write_fifo_l(mach64, 0x284, *(uint32_t *)&svga->vram[addr + 0x38]); - if (mach64->context_mask & (1 << 15)) - mach64_accel_write_fifo_l(mach64, 0x2a8, *(uint32_t *)&svga->vram[addr + 0x3c]); - if (mach64->context_mask & (1 << 16)) - mach64_accel_write_fifo_l(mach64, 0x2b4, *(uint32_t *)&svga->vram[addr + 0x40]); - if (mach64->context_mask & (1 << 17)) - mach64_accel_write_fifo_l(mach64, 0x2c0, *(uint32_t *)&svga->vram[addr + 0x44]); - if (mach64->context_mask & (1 << 18)) - mach64_accel_write_fifo_l(mach64, 0x2c4, *(uint32_t *)&svga->vram[addr + 0x48]); - if (mach64->context_mask & (1 << 19)) - mach64_accel_write_fifo_l(mach64, 0x2c8, *(uint32_t *)&svga->vram[addr + 0x4c]); - if (mach64->context_mask & (1 << 20)) - mach64_accel_write_fifo_l(mach64, 0x2cc, *(uint32_t *)&svga->vram[addr + 0x50]); - if (mach64->context_mask & (1 << 21)) - mach64_accel_write_fifo_l(mach64, 0x2d0, *(uint32_t *)&svga->vram[addr + 0x54]); - if (mach64->context_mask & (1 << 22)) - mach64_accel_write_fifo_l(mach64, 0x2d4, *(uint32_t *)&svga->vram[addr + 0x58]); - if (mach64->context_mask & (1 << 23)) - mach64_accel_write_fifo_l(mach64, 0x2d8, *(uint32_t *)&svga->vram[addr + 0x5c]); - if (mach64->context_mask & (1 << 24)) - mach64_accel_write_fifo_l(mach64, 0x300, *(uint32_t *)&svga->vram[addr + 0x60]); - if (mach64->context_mask & (1 << 25)) - mach64_accel_write_fifo_l(mach64, 0x304, *(uint32_t *)&svga->vram[addr + 0x64]); - if (mach64->context_mask & (1 << 26)) - mach64_accel_write_fifo_l(mach64, 0x308, *(uint32_t *)&svga->vram[addr + 0x68]); - if (mach64->context_mask & (1 << 27)) - mach64_accel_write_fifo_l(mach64, 0x330, *(uint32_t *)&svga->vram[addr + 0x6c]); - - mach64->context_load_cntl = *(uint32_t *)&svga->vram[addr + 0x70]; - } + while (mach64->context_load_cntl & 0x30000) { + addr = ((0x3fff - (mach64->context_load_cntl & 0x3fff)) * 256) & mach64->vram_mask; + mach64->context_mask = *(uint32_t *) &svga->vram[addr]; + mach64_log("mach64_load_context %08X from %08X : mask %08X\n", mach64->context_load_cntl, addr, mach64->context_mask); + + if (mach64->context_mask & (1 << 2)) + mach64_accel_write_fifo_l(mach64, 0x100, *(uint32_t *) &svga->vram[addr + 0x08]); + if (mach64->context_mask & (1 << 3)) + mach64_accel_write_fifo_l(mach64, 0x10c, *(uint32_t *) &svga->vram[addr + 0x0c]); + if (mach64->context_mask & (1 << 4)) + mach64_accel_write_fifo_l(mach64, 0x118, *(uint32_t *) &svga->vram[addr + 0x10]); + if (mach64->context_mask & (1 << 5)) + mach64_accel_write_fifo_l(mach64, 0x124, *(uint32_t *) &svga->vram[addr + 0x14]); + if (mach64->context_mask & (1 << 6)) + mach64_accel_write_fifo_l(mach64, 0x128, *(uint32_t *) &svga->vram[addr + 0x18]); + if (mach64->context_mask & (1 << 7)) + mach64_accel_write_fifo_l(mach64, 0x12c, *(uint32_t *) &svga->vram[addr + 0x1c]); + if (mach64->context_mask & (1 << 8)) + mach64_accel_write_fifo_l(mach64, 0x180, *(uint32_t *) &svga->vram[addr + 0x20]); + if (mach64->context_mask & (1 << 9)) + mach64_accel_write_fifo_l(mach64, 0x18c, *(uint32_t *) &svga->vram[addr + 0x24]); + if (mach64->context_mask & (1 << 10)) + mach64_accel_write_fifo_l(mach64, 0x198, *(uint32_t *) &svga->vram[addr + 0x28]); + if (mach64->context_mask & (1 << 11)) + mach64_accel_write_fifo_l(mach64, 0x1a4, *(uint32_t *) &svga->vram[addr + 0x2c]); + if (mach64->context_mask & (1 << 12)) + mach64_accel_write_fifo_l(mach64, 0x1b0, *(uint32_t *) &svga->vram[addr + 0x30]); + if (mach64->context_mask & (1 << 13)) + mach64_accel_write_fifo_l(mach64, 0x280, *(uint32_t *) &svga->vram[addr + 0x34]); + if (mach64->context_mask & (1 << 14)) + mach64_accel_write_fifo_l(mach64, 0x284, *(uint32_t *) &svga->vram[addr + 0x38]); + if (mach64->context_mask & (1 << 15)) + mach64_accel_write_fifo_l(mach64, 0x2a8, *(uint32_t *) &svga->vram[addr + 0x3c]); + if (mach64->context_mask & (1 << 16)) + mach64_accel_write_fifo_l(mach64, 0x2b4, *(uint32_t *) &svga->vram[addr + 0x40]); + if (mach64->context_mask & (1 << 17)) + mach64_accel_write_fifo_l(mach64, 0x2c0, *(uint32_t *) &svga->vram[addr + 0x44]); + if (mach64->context_mask & (1 << 18)) + mach64_accel_write_fifo_l(mach64, 0x2c4, *(uint32_t *) &svga->vram[addr + 0x48]); + if (mach64->context_mask & (1 << 19)) + mach64_accel_write_fifo_l(mach64, 0x2c8, *(uint32_t *) &svga->vram[addr + 0x4c]); + if (mach64->context_mask & (1 << 20)) + mach64_accel_write_fifo_l(mach64, 0x2cc, *(uint32_t *) &svga->vram[addr + 0x50]); + if (mach64->context_mask & (1 << 21)) + mach64_accel_write_fifo_l(mach64, 0x2d0, *(uint32_t *) &svga->vram[addr + 0x54]); + if (mach64->context_mask & (1 << 22)) + mach64_accel_write_fifo_l(mach64, 0x2d4, *(uint32_t *) &svga->vram[addr + 0x58]); + if (mach64->context_mask & (1 << 23)) + mach64_accel_write_fifo_l(mach64, 0x2d8, *(uint32_t *) &svga->vram[addr + 0x5c]); + if (mach64->context_mask & (1 << 24)) + mach64_accel_write_fifo_l(mach64, 0x300, *(uint32_t *) &svga->vram[addr + 0x60]); + if (mach64->context_mask & (1 << 25)) + mach64_accel_write_fifo_l(mach64, 0x304, *(uint32_t *) &svga->vram[addr + 0x64]); + if (mach64->context_mask & (1 << 26)) + mach64_accel_write_fifo_l(mach64, 0x308, *(uint32_t *) &svga->vram[addr + 0x68]); + if (mach64->context_mask & (1 << 27)) + mach64_accel_write_fifo_l(mach64, 0x330, *(uint32_t *) &svga->vram[addr + 0x6c]); + + mach64->context_load_cntl = *(uint32_t *) &svga->vram[addr + 0x70]; + } } #define PLL_REF_DIV 0x2 #define VCLK_POST_DIV 0x6 #define VCLK0_FB_DIV 0x7 -static void pll_write(mach64_t *mach64, uint32_t addr, uint8_t val) +static void +pll_write(mach64_t *mach64, uint32_t addr, uint8_t val) { - int c; - - switch (addr & 3) - { - case 0: /*Clock sel*/ - break; - case 1: /*Addr*/ - mach64->pll_addr = (val >> 2) & 0xf; - break; - case 2: /*Data*/ - mach64->pll_regs[mach64->pll_addr] = val; - mach64_log("pll_write %02x,%02x\n", mach64->pll_addr, val); + switch (addr & 3) { + case 0: /*Clock sel*/ + break; + case 1: /*Addr*/ + mach64->pll_addr = (val >> 2) & 0xf; + break; + case 2: /*Data*/ + mach64->pll_regs[mach64->pll_addr] = val; + mach64_log("pll_write %02x,%02x\n", mach64->pll_addr, val); - for (c = 0; c < 4; c++) - { - double m = (double)mach64->pll_regs[PLL_REF_DIV]; - double n = (double)mach64->pll_regs[VCLK0_FB_DIV+c]; - double r = 14318184.0; - double p = (double)(1 << ((mach64->pll_regs[VCLK_POST_DIV] >> (c*2)) & 3)); - - mach64_log("PLLfreq %i = %g %g m=%02x n=%02x p=%02x\n", c, (2.0 * r * n) / (m * p), p, mach64->pll_regs[PLL_REF_DIV], mach64->pll_regs[VCLK0_FB_DIV+c], mach64->pll_regs[VCLK_POST_DIV]); - mach64->pll_freq[c] = (2.0 * r * n) / (m * p); - mach64_log(" %g\n", mach64->pll_freq[c]); - } - break; - } + for (uint8_t c = 0; c < 4; c++) { + double m = (double) mach64->pll_regs[PLL_REF_DIV]; + double n = (double) mach64->pll_regs[VCLK0_FB_DIV + c]; + double r = 14318184.0; + double p = (double) (1 << ((mach64->pll_regs[VCLK_POST_DIV] >> (c * 2)) & 3)); + + mach64_log("PLLfreq %i = %g %g m=%02x n=%02x p=%02x\n", c, (2.0 * r * n) / (m * p), p, mach64->pll_regs[PLL_REF_DIV], mach64->pll_regs[VCLK0_FB_DIV + c], mach64->pll_regs[VCLK_POST_DIV]); + mach64->pll_freq[c] = (2.0 * r * n) / (m * p); + mach64_log(" %g\n", mach64->pll_freq[c]); + } + break; + + default: + break; + } } #define OVERLAY_EN (1 << 30) -static void mach64_vblank_start(svga_t *svga) +static void +mach64_vblank_start(svga_t *svga) { - mach64_t *mach64 = (mach64_t *)svga->p; - int overlay_cmp_mix = (mach64->overlay_key_cntl >> 8) & 0xf; - - mach64->crtc_int_cntl |= 4; - mach64_update_irqs(mach64); - - svga->overlay.x = (mach64->overlay_y_x_start >> 16) & 0x7ff; - svga->overlay.y = mach64->overlay_y_x_start & 0x7ff; - - svga->overlay.xsize = ((mach64->overlay_y_x_end >> 16) & 0x7ff) - svga->overlay.x; - svga->overlay.ysize = (mach64->overlay_y_x_end & 0x7ff) - svga->overlay.y; - - svga->overlay.addr = mach64->buf_offset[0] & 0x3ffff8; - svga->overlay.pitch = mach64->buf_pitch[0] & 0xfff; - - svga->overlay.ena = (mach64->overlay_scale_cntl & OVERLAY_EN) && (overlay_cmp_mix != 1); - - mach64->overlay_v_acc = 0; - mach64->scaler_update = 1; + mach64_t *mach64 = (mach64_t *) svga->priv; + int overlay_cmp_mix = (mach64->overlay_key_cntl >> 8) & 0xf; + + mach64->crtc_int_cntl |= 4; + mach64_update_irqs(mach64); + + svga->overlay.x = (mach64->overlay_y_x_start >> 16) & 0x7ff; + svga->overlay.y = mach64->overlay_y_x_start & 0x7ff; + + svga->overlay.cur_xsize = ((mach64->overlay_y_x_end >> 16) & 0x7ff) - svga->overlay.x; + svga->overlay.cur_ysize = (mach64->overlay_y_x_end & 0x7ff) - svga->overlay.y; + + svga->overlay.addr = mach64->buf_offset[0] & 0x3ffff8; + svga->overlay.pitch = mach64->buf_pitch[0] & 0xfff; + + svga->overlay.ena = (mach64->overlay_scale_cntl & OVERLAY_EN) && (overlay_cmp_mix != 1); + + mach64->overlay_v_acc = 0; + mach64->scaler_update = 1; } -uint8_t mach64_ext_readb(uint32_t addr, void *p) +uint8_t +mach64_ext_readb(uint32_t addr, void *priv) { - mach64_t *mach64 = (mach64_t *)p; + mach64_t *mach64 = (mach64_t *) priv; - uint8_t ret = 0xff; - if (!(addr & 0x400)) - { - mach64_log("nmach64_ext_readb: addr=%04x\n", addr); - switch (addr & 0x3ff) - { - case 0x00: case 0x01: case 0x02: case 0x03: - READ8(addr, mach64->overlay_y_x_start); - break; - case 0x04: case 0x05: case 0x06: case 0x07: - READ8(addr, mach64->overlay_y_x_end); - break; - case 0x08: case 0x09: case 0x0a: case 0x0b: - READ8(addr, mach64->overlay_video_key_clr); - break; - case 0x0c: case 0x0d: case 0x0e: case 0x0f: - READ8(addr, mach64->overlay_video_key_msk); - break; - case 0x10: case 0x11: case 0x12: case 0x13: - READ8(addr, mach64->overlay_graphics_key_clr); - break; - case 0x14: case 0x15: case 0x16: case 0x17: - READ8(addr, mach64->overlay_graphics_key_msk); - break; - case 0x18: case 0x19: case 0x1a: case 0x1b: - READ8(addr, mach64->overlay_key_cntl); - break; + uint8_t ret = 0xff; + if (!(addr & 0x400)) { + mach64_log("nmach64_ext_readb: addr=%04x\n", addr); + switch (addr & 0x3ff) { + case 0x00: + case 0x01: + case 0x02: + case 0x03: + READ8(addr, mach64->overlay_y_x_start); + break; + case 0x04: + case 0x05: + case 0x06: + case 0x07: + READ8(addr, mach64->overlay_y_x_end); + break; + case 0x08: + case 0x09: + case 0x0a: + case 0x0b: + READ8(addr, mach64->overlay_video_key_clr); + break; + case 0x0c: + case 0x0d: + case 0x0e: + case 0x0f: + READ8(addr, mach64->overlay_video_key_msk); + break; + case 0x10: + case 0x11: + case 0x12: + case 0x13: + READ8(addr, mach64->overlay_graphics_key_clr); + break; + case 0x14: + case 0x15: + case 0x16: + case 0x17: + READ8(addr, mach64->overlay_graphics_key_msk); + break; + case 0x18: + case 0x19: + case 0x1a: + case 0x1b: + READ8(addr, mach64->overlay_key_cntl); + break; - case 0x20: case 0x21: case 0x22: case 0x23: - READ8(addr, mach64->overlay_scale_inc); - break; - case 0x24: case 0x25: case 0x26: case 0x27: - READ8(addr, mach64->overlay_scale_cntl); - break; - case 0x28: case 0x29: case 0x2a: case 0x2b: - READ8(addr, mach64->scaler_height_width); - break; - - case 0x4a: - ret = mach64->scaler_format; - break; - - default: - ret = 0xff; - break; - } + case 0x20: + case 0x21: + case 0x22: + case 0x23: + READ8(addr, mach64->overlay_scale_inc); + break; + case 0x24: + case 0x25: + case 0x26: + case 0x27: + READ8(addr, mach64->overlay_scale_cntl); + break; + case 0x28: + case 0x29: + case 0x2a: + case 0x2b: + READ8(addr, mach64->scaler_height_width); + break; + + case 0x4a: + ret = mach64->scaler_format; + break; + + default: + ret = 0xff; + break; } - else switch (addr & 0x3ff) - { - case 0x00: case 0x01: case 0x02: case 0x03: + } else + switch (addr & 0x3ff) { + case 0x00: + case 0x01: + case 0x02: + case 0x03: READ8(addr, mach64->crtc_h_total_disp); break; - case 0x08: case 0x09: case 0x0a: case 0x0b: + case 0x08: + case 0x09: + case 0x0a: + case 0x0b: READ8(addr, mach64->crtc_v_total_disp); break; - case 0x0c: case 0x0d: case 0x0e: case 0x0f: + case 0x0c: + case 0x0d: + case 0x0e: + case 0x0f: READ8(addr, mach64->crtc_v_sync_strt_wid); break; - case 0x12: case 0x13: + case 0x12: + case 0x13: READ8(addr - 2, mach64->svga.vc); break; - - case 0x14: case 0x15: case 0x16: case 0x17: + + case 0x14: + case 0x15: + case 0x16: + case 0x17: READ8(addr, mach64->crtc_off_pitch); break; - - case 0x18: + + case 0x18: ret = mach64->crtc_int_cntl & ~1; if (mach64->svga.cgastat & 8) - ret |= 1; + ret |= 1; break; - case 0x1c: case 0x1d: case 0x1e: case 0x1f: + case 0x1c: + case 0x1d: + case 0x1e: + case 0x1f: READ8(addr, mach64->crtc_gen_cntl); break; - case 0x40: case 0x41: case 0x42: case 0x43: + case 0x40: + case 0x41: + case 0x42: + case 0x43: READ8(addr, mach64->ovr_clr); break; - case 0x44: case 0x45: case 0x46: case 0x47: + case 0x44: + case 0x45: + case 0x46: + case 0x47: READ8(addr, mach64->ovr_wid_left_right); break; - case 0x48: case 0x49: case 0x4a: case 0x4b: + case 0x48: + case 0x49: + case 0x4a: + case 0x4b: READ8(addr, mach64->ovr_wid_top_bottom); break; - case 0x60: case 0x61: case 0x62: case 0x63: + case 0x60: + case 0x61: + case 0x62: + case 0x63: READ8(addr, mach64->cur_clr0); break; - case 0x64: case 0x65: case 0x66: case 0x67: + case 0x64: + case 0x65: + case 0x66: + case 0x67: READ8(addr, mach64->cur_clr1); break; - case 0x68: case 0x69: case 0x6a: case 0x6b: + case 0x68: + case 0x69: + case 0x6a: + case 0x6b: READ8(addr, mach64->cur_offset); break; - case 0x6c: case 0x6d: case 0x6e: case 0x6f: + case 0x6c: + case 0x6d: + case 0x6e: + case 0x6f: READ8(addr, mach64->cur_horz_vert_posn); break; - case 0x70: case 0x71: case 0x72: case 0x73: + case 0x70: + case 0x71: + case 0x72: + case 0x73: READ8(addr, mach64->cur_horz_vert_off); break; - case 0x79: + case 0x79: ret = 0x30; break; - - case 0x80: case 0x81: case 0x82: case 0x83: + + case 0x80: + case 0x81: + case 0x82: + case 0x83: READ8(addr, mach64->scratch_reg0); break; - case 0x84: case 0x85: case 0x86: case 0x87: + case 0x84: + case 0x85: + case 0x86: + case 0x87: READ8(addr, mach64->scratch_reg1); break; - case 0x90: case 0x91: case 0x92: case 0x93: + case 0x90: + case 0x91: + case 0x92: + case 0x93: READ8(addr, mach64->clock_cntl); break; - case 0xb0: case 0xb1: case 0xb2: case 0xb3: + case 0xb0: + case 0xb1: + case 0xb2: + case 0xb3: READ8(addr, mach64->mem_cntl); break; - case 0xc0: case 0xc1: case 0xc2: case 0xc3: + case 0xc0: + case 0xc1: + case 0xc2: + case 0xc3: if (mach64->type == MACH64_GX) - ret = ati68860_ramdac_in((addr & 3) | ((mach64->dac_cntl & 3) << 2), mach64->svga.ramdac, &mach64->svga); + ret = ati68860_ramdac_in((addr & 3) | ((mach64->dac_cntl & 3) << 2), mach64->svga.ramdac, &mach64->svga); else - ret = ati68860_ramdac_in(addr & 3, mach64->svga.ramdac, &mach64->svga); + ret = ati68860_ramdac_in(addr & 3, mach64->svga.ramdac, &mach64->svga); break; - case 0xc4: case 0xc5: case 0xc6: + case 0xc4: + case 0xc5: + case 0xc6: READ8(addr, mach64->dac_cntl); break; - - case 0xc7: + + case 0xc7: READ8(addr, mach64->dac_cntl); if (mach64->type == MACH64_VT2) { - ret &= 0xf9; - if (i2c_gpio_get_scl(mach64->i2c)) - ret |= 0x04; - if (i2c_gpio_get_sda(mach64->i2c)) - ret |= 0x02; + ret &= 0xf9; + if (i2c_gpio_get_scl(mach64->i2c)) + ret |= 0x04; + if (i2c_gpio_get_sda(mach64->i2c)) + ret |= 0x02; } break; - case 0xd0: case 0xd1: case 0xd2: case 0xd3: + case 0xd0: + case 0xd1: + case 0xd2: + case 0xd3: READ8(addr, mach64->gen_test_cntl); break; - case 0xdc: case 0xdd: case 0xde: case 0xdf: + case 0xdc: + case 0xdd: + case 0xde: + case 0xdf: if (mach64->type == MACH64_GX) - mach64->config_cntl = (mach64->config_cntl & ~0x3ff0) | ((mach64->linear_base >> 22) << 4); + 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); + mach64->config_cntl = (mach64->config_cntl & ~0x3ff0) | ((mach64->linear_base >> 24) << 4); + READ8(addr, mach64->config_cntl); break; - case 0xe0: case 0xe1: case 0xe2: case 0xe3: + case 0xe0: + case 0xe1: + case 0xe2: + case 0xe3: READ8(addr, mach64->config_chip_id); break; - case 0xe4: case 0xe5: case 0xe6: case 0xe7: + case 0xe4: + case 0xe5: + case 0xe6: + case 0xe7: READ8(addr, mach64->config_stat0); break; - - case 0x100: case 0x101: case 0x102: case 0x103: + + case 0x100: + case 0x101: + case 0x102: + case 0x103: + //mach64_wait_fifo_idle(mach64); READ8(addr, mach64->dst_off_pitch); break; - case 0x104: case 0x105: + case 0x104: + case 0x105: + //mach64_wait_fifo_idle(mach64); READ8(addr, mach64->dst_y_x); break; - case 0x108: case 0x109: case 0x11c: case 0x11d: + case 0x108: + case 0x109: + case 0x11c: + case 0x11d: + //mach64_wait_fifo_idle(mach64); READ8(addr + 2, mach64->dst_y_x); break; - case 0x10c: case 0x10d: case 0x10e: case 0x10f: + case 0x10c: + case 0x10d: + case 0x10e: + case 0x10f: + //mach64_wait_fifo_idle(mach64); READ8(addr, mach64->dst_y_x); break; - case 0x110: case 0x111: + case 0x110: + case 0x111: addr += 2; - /*FALLTHROUGH*/ - case 0x114: case 0x115: - case 0x118: case 0x119: case 0x11a: case 0x11b: - case 0x11e: case 0x11f: + fallthrough; + case 0x114: + case 0x115: + case 0x118: + case 0x119: + case 0x11a: + case 0x11b: + case 0x11e: + case 0x11f: + //mach64_wait_fifo_idle(mach64); READ8(addr, mach64->dst_height_width); break; - case 0x120: case 0x121: case 0x122: case 0x123: + case 0x120: + case 0x121: + case 0x122: + case 0x123: + //mach64_wait_fifo_idle(mach64); READ8(addr, mach64->dst_bres_lnth); break; - case 0x124: case 0x125: case 0x126: case 0x127: + case 0x124: + case 0x125: + case 0x126: + case 0x127: + //mach64_wait_fifo_idle(mach64); READ8(addr, mach64->dst_bres_err); break; - case 0x128: case 0x129: case 0x12a: case 0x12b: + case 0x128: + case 0x129: + case 0x12a: + case 0x12b: + //mach64_wait_fifo_idle(mach64); READ8(addr, mach64->dst_bres_inc); break; - case 0x12c: case 0x12d: case 0x12e: case 0x12f: + case 0x12c: + case 0x12d: + case 0x12e: + case 0x12f: + //mach64_wait_fifo_idle(mach64); READ8(addr, mach64->dst_bres_dec); break; - case 0x130: case 0x131: case 0x132: case 0x133: + case 0x130: + case 0x131: + case 0x132: + case 0x133: + //mach64_wait_fifo_idle(mach64); READ8(addr, mach64->dst_cntl); break; - case 0x180: case 0x181: case 0x182: case 0x183: + case 0x180: + case 0x181: + case 0x182: + case 0x183: + //mach64_wait_fifo_idle(mach64); READ8(addr, mach64->src_off_pitch); break; - case 0x184: case 0x185: + case 0x184: + case 0x185: + //mach64_wait_fifo_idle(mach64); READ8(addr, mach64->src_y_x); break; - case 0x188: case 0x189: + case 0x188: + case 0x189: + //mach64_wait_fifo_idle(mach64); READ8(addr + 2, mach64->src_y_x); break; - case 0x18c: case 0x18d: case 0x18e: case 0x18f: + case 0x18c: + case 0x18d: + case 0x18e: + case 0x18f: + //mach64_wait_fifo_idle(mach64); READ8(addr, mach64->src_y_x); break; - case 0x190: case 0x191: + case 0x190: + case 0x191: + //mach64_wait_fifo_idle(mach64); READ8(addr + 2, mach64->src_height1_width1); break; - case 0x194: case 0x195: + case 0x194: + case 0x195: + //mach64_wait_fifo_idle(mach64); READ8(addr, mach64->src_height1_width1); break; - case 0x198: case 0x199: case 0x19a: case 0x19b: + case 0x198: + case 0x199: + case 0x19a: + case 0x19b: + //mach64_wait_fifo_idle(mach64); READ8(addr, mach64->src_height1_width1); break; - case 0x19c: case 0x19d: + case 0x19c: + case 0x19d: + //mach64_wait_fifo_idle(mach64); READ8(addr, mach64->src_y_x_start); break; - case 0x1a0: case 0x1a1: + case 0x1a0: + case 0x1a1: + //mach64_wait_fifo_idle(mach64); READ8(addr + 2, mach64->src_y_x_start); break; - case 0x1a4: case 0x1a5: case 0x1a6: case 0x1a7: + case 0x1a4: + case 0x1a5: + case 0x1a6: + case 0x1a7: + //mach64_wait_fifo_idle(mach64); READ8(addr, mach64->src_y_x_start); break; - case 0x1a8: case 0x1a9: + case 0x1a8: + case 0x1a9: + //mach64_wait_fifo_idle(mach64); READ8(addr + 2, mach64->src_height2_width2); break; - case 0x1ac: case 0x1ad: + case 0x1ac: + case 0x1ad: + //mach64_wait_fifo_idle(mach64); READ8(addr, mach64->src_height2_width2); break; - case 0x1b0: case 0x1b1: case 0x1b2: case 0x1b3: + case 0x1b0: + case 0x1b1: + case 0x1b2: + case 0x1b3: + //mach64_wait_fifo_idle(mach64); READ8(addr, mach64->src_height2_width2); break; - case 0x1b4: case 0x1b5: case 0x1b6: case 0x1b7: + case 0x1b4: + case 0x1b5: + case 0x1b6: + case 0x1b7: + //mach64_wait_fifo_idle(mach64); READ8(addr, mach64->src_cntl); break; - case 0x240: case 0x241: case 0x242: case 0x243: + case 0x240: + case 0x241: + case 0x242: + case 0x243: + //mach64_wait_fifo_idle(mach64); READ8(addr, mach64->host_cntl); break; - case 0x280: case 0x281: case 0x282: case 0x283: + case 0x280: + case 0x281: + case 0x282: + case 0x283: + //mach64_wait_fifo_idle(mach64); READ8(addr, mach64->pat_reg0); break; - case 0x284: case 0x285: case 0x286: case 0x287: + case 0x284: + case 0x285: + case 0x286: + case 0x287: + //mach64_wait_fifo_idle(mach64); READ8(addr, mach64->pat_reg1); break; - - case 0x288: case 0x289: case 0x28a: case 0x28b: + + case 0x288: + case 0x289: + case 0x28a: + case 0x28b: + //mach64_wait_fifo_idle(mach64); READ8(addr, mach64->pat_cntl); break; - case 0x2a0: case 0x2a1: case 0x2a8: case 0x2a9: + case 0x2a0: + case 0x2a1: + case 0x2a8: + case 0x2a9: + //mach64_wait_fifo_idle(mach64); READ8(addr, mach64->sc_left_right); break; - case 0x2a4: case 0x2a5: + case 0x2a4: + case 0x2a5: addr += 2; - /*FALLTHROUGH*/ - case 0x2aa: case 0x2ab: + fallthrough; + case 0x2aa: + case 0x2ab: + //mach64_wait_fifo_idle(mach64); READ8(addr, mach64->sc_left_right); break; - case 0x2ac: case 0x2ad: case 0x2b4: case 0x2b5: + case 0x2ac: + case 0x2ad: + case 0x2b4: + case 0x2b5: + //mach64_wait_fifo_idle(mach64); READ8(addr, mach64->sc_top_bottom); break; - case 0x2b0: case 0x2b1: + case 0x2b0: + case 0x2b1: addr += 2; - /*FALLTHROUGH*/ - case 0x2b6: case 0x2b7: + fallthrough; + case 0x2b6: + case 0x2b7: + //mach64_wait_fifo_idle(mach64); READ8(addr, mach64->sc_top_bottom); break; - case 0x2c0: case 0x2c1: case 0x2c2: case 0x2c3: + case 0x2c0: + case 0x2c1: + case 0x2c2: + case 0x2c3: + //mach64_wait_fifo_idle(mach64); READ8(addr, mach64->dp_bkgd_clr); break; - case 0x2c4: case 0x2c5: case 0x2c6: case 0x2c7: + case 0x2c4: + case 0x2c5: + case 0x2c6: + case 0x2c7: + //mach64_wait_fifo_idle(mach64); READ8(addr, mach64->dp_frgd_clr); break; - - case 0x2d0: case 0x2d1: case 0x2d2: case 0x2d3: + + case 0x2c8: + case 0x2c9: + case 0x2ca: + case 0x2cb: + //mach64_wait_fifo_idle(mach64); + READ8(addr, mach64->write_mask); + break; + + case 0x2cc: + case 0x2cd: + case 0x2ce: + case 0x2cf: + //mach64_wait_fifo_idle(mach64); + READ8(addr, mach64->chain_mask); + break; + + case 0x2d0: + case 0x2d1: + case 0x2d2: + case 0x2d3: + //mach64_wait_fifo_idle(mach64); READ8(addr, mach64->dp_pix_width); break; - case 0x2d4: case 0x2d5: case 0x2d6: case 0x2d7: + case 0x2d4: + case 0x2d5: + case 0x2d6: + case 0x2d7: + //mach64_wait_fifo_idle(mach64); READ8(addr, mach64->dp_mix); break; - case 0x2d8: case 0x2d9: case 0x2da: case 0x2db: + case 0x2d8: + case 0x2d9: + case 0x2da: + case 0x2db: + //mach64_wait_fifo_idle(mach64); READ8(addr, mach64->dp_src); break; - case 0x300: case 0x301: case 0x302: case 0x303: + case 0x300: + case 0x301: + case 0x302: + case 0x303: + //mach64_wait_fifo_idle(mach64); READ8(addr, mach64->clr_cmp_clr); break; - case 0x304: case 0x305: case 0x306: case 0x307: + case 0x304: + case 0x305: + case 0x306: + case 0x307: + //mach64_wait_fifo_idle(mach64); READ8(addr, mach64->clr_cmp_mask); break; - case 0x308: case 0x309: case 0x30a: case 0x30b: + case 0x308: + case 0x309: + case 0x30a: + case 0x30b: + //mach64_wait_fifo_idle(mach64); READ8(addr, mach64->clr_cmp_cntl); break; - - case 0x310: case 0x311: + + case 0x310: + case 0x311: ret = 0; break; - - case 0x320: case 0x321: case 0x322: case 0x323: + + case 0x320: + case 0x321: + case 0x322: + case 0x323: + //mach64_wait_fifo_idle(mach64); READ8(addr, mach64->context_mask); break; - case 0x330: case 0x331: + case 0x330: + case 0x331: + //mach64_wait_fifo_idle(mach64); READ8(addr, mach64->dst_cntl); break; - case 0x332: + case 0x332: + //mach64_wait_fifo_idle(mach64); READ8(addr - 2, mach64->src_cntl); break; - case 0x333: + case 0x333: + //mach64_wait_fifo_idle(mach64); READ8(addr - 3, mach64->pat_cntl); break; - - case 0x338: + + case 0x338: ret = 0; break; - default: + default: ret = 0; break; } - if ((addr & 0x3fc) != 0x018) mach64_log("mach64_ext_readb : addr %08X ret %02X\n", addr, ret); - return ret; + if ((addr & 0x3fc) != 0x018) + mach64_log("mach64_ext_readb : addr %08X ret %02X\n", addr, ret); + return ret; } -uint16_t mach64_ext_readw(uint32_t addr, void *p) +uint16_t +mach64_ext_readw(uint32_t addr, void *priv) { - mach64_t *mach64 = (mach64_t *)p; - uint16_t ret; - if (!(addr & 0x400)) - { - mach64_log("nmach64_ext_readw: addr=%04x\n", addr); - ret = 0xffff; - } - else switch (addr & 0x3ff) - { - case 0xb4: case 0xb6: + const mach64_t *mach64 = (mach64_t *) priv; + uint16_t ret; + + if (!(addr & 0x400)) { + mach64_log("nmach64_ext_readw: addr=%04x\n", addr); + ret = 0xffff; + } else + switch (addr & 0x3ff) { + case 0xb4: + case 0xb6: ret = (mach64->bank_w[(addr & 2) >> 1] >> 15); break; - case 0xb8: case 0xba: + case 0xb8: + case 0xba: ret = (mach64->bank_r[(addr & 2) >> 1] >> 15); break; - default: - ret = mach64_ext_readb(addr, p); - ret |= mach64_ext_readb(addr + 1, p) << 8; + default: + ret = mach64_ext_readb(addr, priv); + ret |= mach64_ext_readb(addr + 1, priv) << 8; break; } - if ((addr & 0x3fc) != 0x018) mach64_log("mach64_ext_readw : addr %08X ret %04X\n", addr, ret); - return ret; + if ((addr & 0x3fc) != 0x018) + mach64_log("mach64_ext_readw : addr %08X ret %04X\n", addr, ret); + return ret; } -uint32_t mach64_ext_readl(uint32_t addr, void *p) +uint32_t +mach64_ext_readl(uint32_t addr, void *priv) { - mach64_t *mach64 = (mach64_t *)p; - uint32_t ret; - if (!(addr & 0x400)) - { - mach64_log("nmach64_ext_readl: addr=%04x\n", addr); - ret = 0xffffffff; - } - else switch (addr & 0x3ff) - { - case 0x18: + const mach64_t *mach64 = (mach64_t *) priv; + uint32_t ret; + + if (!(addr & 0x400)) { + mach64_log("nmach64_ext_readl: addr=%04x\n", addr); + ret = 0xffffffff; + } else + switch (addr & 0x3ff) { + case 0x18: ret = mach64->crtc_int_cntl & ~1; if (mach64->svga.cgastat & 8) - ret |= 1; + ret |= 1; break; - case 0xb4: + case 0xb4: ret = (mach64->bank_w[0] >> 15) | ((mach64->bank_w[1] >> 15) << 16); break; - case 0xb8: + case 0xb8: ret = (mach64->bank_r[0] >> 15) | ((mach64->bank_r[1] >> 15) << 16); break; - default: - ret = mach64_ext_readw(addr, p); - ret |= mach64_ext_readw(addr + 2, p) << 16; + default: + ret = mach64_ext_readw(addr, priv); + ret |= mach64_ext_readw(addr + 2, priv) << 16; break; } - if ((addr & 0x3fc) != 0x018) mach64_log("mach64_ext_readl : addr %08X ret %08X\n", addr, ret); - return ret; + if ((addr & 0x3fc) != 0x018) + mach64_log("mach64_ext_readl : addr %08X ret %08X\n", addr, ret); + return ret; } -void mach64_ext_writeb(uint32_t addr, uint8_t val, void *p) +void +mach64_ext_writeb(uint32_t addr, uint8_t val, void *priv) { - mach64_t *mach64 = (mach64_t *)p; - svga_t *svga = &mach64->svga; + mach64_t *mach64 = (mach64_t *) priv; + svga_t *svga = &mach64->svga; - mach64_log("mach64_ext_writeb : addr %08X val %02X\n", addr, val); + mach64_log("mach64_ext_writeb : addr %08X val %02X\n", addr, val); - if (!(addr & 0x400)) - { - switch (addr & 0x3ff) - { - case 0x00: case 0x01: case 0x02: case 0x03: - WRITE8(addr, mach64->overlay_y_x_start, val); - break; - case 0x04: case 0x05: case 0x06: case 0x07: - WRITE8(addr, mach64->overlay_y_x_end, val); - break; - case 0x08: case 0x09: case 0x0a: case 0x0b: - WRITE8(addr, mach64->overlay_video_key_clr, val); - break; - case 0x0c: case 0x0d: case 0x0e: case 0x0f: - WRITE8(addr, mach64->overlay_video_key_msk, val); - break; - case 0x10: case 0x11: case 0x12: case 0x13: - WRITE8(addr, mach64->overlay_graphics_key_clr, val); - break; - case 0x14: case 0x15: case 0x16: case 0x17: - WRITE8(addr, mach64->overlay_graphics_key_msk, val); - break; - case 0x18: case 0x19: case 0x1a: case 0x1b: - WRITE8(addr, mach64->overlay_key_cntl, val); - break; + if (!(addr & 0x400)) { + switch (addr & 0x3ff) { + case 0x00: + case 0x01: + case 0x02: + case 0x03: + WRITE8(addr, mach64->overlay_y_x_start, val); + break; + case 0x04: + case 0x05: + case 0x06: + case 0x07: + WRITE8(addr, mach64->overlay_y_x_end, val); + break; + case 0x08: + case 0x09: + case 0x0a: + case 0x0b: + WRITE8(addr, mach64->overlay_video_key_clr, val); + break; + case 0x0c: + case 0x0d: + case 0x0e: + case 0x0f: + WRITE8(addr, mach64->overlay_video_key_msk, val); + break; + case 0x10: + case 0x11: + case 0x12: + case 0x13: + WRITE8(addr, mach64->overlay_graphics_key_clr, val); + break; + case 0x14: + case 0x15: + case 0x16: + case 0x17: + WRITE8(addr, mach64->overlay_graphics_key_msk, val); + break; + case 0x18: + case 0x19: + case 0x1a: + case 0x1b: + WRITE8(addr, mach64->overlay_key_cntl, val); + break; - case 0x20: case 0x21: case 0x22: case 0x23: - WRITE8(addr, mach64->overlay_scale_inc, val); - break; - case 0x24: case 0x25: case 0x26: case 0x27: - WRITE8(addr, mach64->overlay_scale_cntl, val); - break; - case 0x28: case 0x29: case 0x2a: case 0x2b: - WRITE8(addr, mach64->scaler_height_width, val); - break; + case 0x20: + case 0x21: + case 0x22: + case 0x23: + WRITE8(addr, mach64->overlay_scale_inc, val); + break; + case 0x24: + case 0x25: + case 0x26: + case 0x27: + WRITE8(addr, mach64->overlay_scale_cntl, val); + break; + case 0x28: + case 0x29: + case 0x2a: + case 0x2b: + WRITE8(addr, mach64->scaler_height_width, val); + break; - case 0x4a: - mach64->scaler_format = val & 0xf; - break; + case 0x4a: + mach64->scaler_format = val & 0xf; + break; - case 0x80: case 0x81: case 0x82: case 0x83: - WRITE8(addr, mach64->buf_offset[0], val); - break; + case 0x80: + case 0x81: + case 0x82: + case 0x83: + WRITE8(addr, mach64->buf_offset[0], val); + break; - case 0x8c: case 0x8d: case 0x8e: case 0x8f: - WRITE8(addr, mach64->buf_pitch[0], val); - break; + case 0x8c: + case 0x8d: + case 0x8e: + case 0x8f: + WRITE8(addr, mach64->buf_pitch[0], val); + break; - case 0x98: case 0x99: case 0x9a: case 0x9b: - WRITE8(addr, mach64->buf_offset[1], val); - break; + case 0x98: + case 0x99: + case 0x9a: + case 0x9b: + WRITE8(addr, mach64->buf_offset[1], val); + break; - case 0xa4: case 0xa5: case 0xa6: case 0xa7: - WRITE8(addr, mach64->buf_pitch[1], val); - break; - } + case 0xa4: + case 0xa5: + case 0xa6: + case 0xa7: + WRITE8(addr, mach64->buf_pitch[1], val); + break; - mach64_log("nmach64_ext_writeb: addr=%04x val=%02x\n", addr, val); + default: + break; } - else if (addr & 0x300) - { - mach64_accel_write_fifo(mach64, addr & 0x3ff, val); - } - else switch (addr & 0x3ff) - { - case 0x00: case 0x01: case 0x02: case 0x03: + + mach64_log("nmach64_ext_writeb: addr=%04x val=%02x\n", addr, val); + } else if (addr & 0x300) { + mach64_accel_write_fifo(mach64, addr & 0x3ff, val); + } else + switch (addr & 0x3ff) { + case 0x00: + case 0x01: + case 0x02: + case 0x03: WRITE8(addr, mach64->crtc_h_total_disp, val); svga_recalctimings(&mach64->svga); + svga->fullchange = svga->monitor->mon_changeframecount; break; - case 0x08: case 0x09: case 0x0a: case 0x0b: + case 0x08: + case 0x09: + case 0x0a: + case 0x0b: WRITE8(addr, mach64->crtc_v_total_disp, val); svga_recalctimings(&mach64->svga); + svga->fullchange = svga->monitor->mon_changeframecount; break; - case 0x0c: case 0x0d: case 0x0e: case 0x0f: + case 0x0c: + case 0x0d: + case 0x0e: + case 0x0f: WRITE8(addr, mach64->crtc_v_sync_strt_wid, val); svga_recalctimings(&mach64->svga); + svga->fullchange = svga->monitor->mon_changeframecount; break; - case 0x14: case 0x15: case 0x16: case 0x17: + case 0x14: + case 0x15: + case 0x16: + case 0x17: WRITE8(addr, mach64->crtc_off_pitch, val); svga_recalctimings(&mach64->svga); - svga->fullchange = changeframecount; + svga->fullchange = svga->monitor->mon_changeframecount; break; - - case 0x18: + + case 0x18: mach64->crtc_int_cntl = (mach64->crtc_int_cntl & 0x75) | (val & ~0x75); if (val & 4) - mach64->crtc_int_cntl &= ~4; + mach64->crtc_int_cntl &= ~4; mach64_update_irqs(mach64); break; - case 0x1c: case 0x1d: case 0x1e: case 0x1f: + case 0x1c: + case 0x1d: + case 0x1e: + case 0x1f: WRITE8(addr, mach64->crtc_gen_cntl, val); if (((mach64->crtc_gen_cntl >> 24) & 3) == 3) - svga->fb_only = 1; + svga->fb_only = 1; else - svga->fb_only = 0; + svga->fb_only = 0; svga->dpms = !!(mach64->crtc_gen_cntl & 0x0c); svga_recalctimings(&mach64->svga); + svga->fullchange = svga->monitor->mon_changeframecount; break; - case 0x40: case 0x41: case 0x42: case 0x43: + case 0x40: + case 0x41: + case 0x42: + case 0x43: WRITE8(addr, mach64->ovr_clr, val); break; - case 0x44: case 0x45: case 0x46: case 0x47: + case 0x44: + case 0x45: + case 0x46: + case 0x47: WRITE8(addr, mach64->ovr_wid_left_right, val); break; - case 0x48: case 0x49: case 0x4a: case 0x4b: + case 0x48: + case 0x49: + case 0x4a: + case 0x4b: WRITE8(addr, mach64->ovr_wid_top_bottom, val); break; - case 0x60: case 0x61: case 0x62: case 0x63: + case 0x60: + case 0x61: + case 0x62: + case 0x63: WRITE8(addr, mach64->cur_clr0, val); if (mach64->type == MACH64_VT2) - ati68860_ramdac_set_pallook(mach64->svga.ramdac, 0, makecol32((mach64->cur_clr0 >> 24) & 0xff, (mach64->cur_clr0 >> 16) & 0xff, (mach64->cur_clr0 >> 8) & 0xff)); + ati68860_ramdac_set_pallook(mach64->svga.ramdac, 0, makecol32((mach64->cur_clr0 >> 24) & 0xff, (mach64->cur_clr0 >> 16) & 0xff, (mach64->cur_clr0 >> 8) & 0xff)); break; - case 0x64: case 0x65: case 0x66: case 0x67: + case 0x64: + case 0x65: + case 0x66: + case 0x67: WRITE8(addr, mach64->cur_clr1, val); if (mach64->type == MACH64_VT2) - ati68860_ramdac_set_pallook(mach64->svga.ramdac, 1, makecol32((mach64->cur_clr1 >> 24) & 0xff, (mach64->cur_clr1 >> 16) & 0xff, (mach64->cur_clr1 >> 8) & 0xff)); + ati68860_ramdac_set_pallook(mach64->svga.ramdac, 1, makecol32((mach64->cur_clr1 >> 24) & 0xff, (mach64->cur_clr1 >> 16) & 0xff, (mach64->cur_clr1 >> 8) & 0xff)); break; - case 0x68: case 0x69: case 0x6a: case 0x6b: + case 0x68: + case 0x69: + case 0x6a: + case 0x6b: WRITE8(addr, mach64->cur_offset, val); svga->dac_hwcursor.addr = (mach64->cur_offset & 0xfffff) * 8; - mach64_cursor_dump(mach64); break; - case 0x6c: case 0x6d: case 0x6e: case 0x6f: + case 0x6c: + case 0x6d: + case 0x6e: + case 0x6f: WRITE8(addr, mach64->cur_horz_vert_posn, val); svga->dac_hwcursor.x = mach64->cur_horz_vert_posn & 0x7ff; svga->dac_hwcursor.y = (mach64->cur_horz_vert_posn >> 16) & 0x7ff; - mach64_cursor_dump(mach64); break; - case 0x70: case 0x71: case 0x72: case 0x73: + case 0x70: + case 0x71: + case 0x72: + case 0x73: WRITE8(addr, mach64->cur_horz_vert_off, val); svga->dac_hwcursor.xoff = mach64->cur_horz_vert_off & 0x3f; svga->dac_hwcursor.yoff = (mach64->cur_horz_vert_off >> 16) & 0x3f; - mach64_cursor_dump(mach64); break; - case 0x80: case 0x81: case 0x82: case 0x83: + case 0x80: + case 0x81: + case 0x82: + case 0x83: WRITE8(addr, mach64->scratch_reg0, val); break; - case 0x84: case 0x85: case 0x86: case 0x87: + case 0x84: + case 0x85: + case 0x86: + case 0x87: WRITE8(addr, mach64->scratch_reg1, val); break; - case 0x90: case 0x91: case 0x92: case 0x93: + case 0x90: + case 0x91: + case 0x92: + case 0x93: WRITE8(addr, mach64->clock_cntl, val); if (mach64->type == MACH64_GX) - ics2595_write(svga->clock_gen, val & 0x40, val & 0xf); - else - { - pll_write(mach64, addr, val); - ics2595_setclock(svga->clock_gen, mach64->pll_freq[mach64->clock_cntl & 3]); + ics2595_write(svga->clock_gen, val & 0x40, val & 0xf); + else { + pll_write(mach64, addr, val); + ics2595_setclock(svga->clock_gen, mach64->pll_freq[mach64->clock_cntl & 3]); } svga_recalctimings(&mach64->svga); break; - case 0xb0: case 0xb1: case 0xb2: case 0xb3: + case 0xb0: + case 0xb1: + case 0xb2: + case 0xb3: WRITE8(addr, mach64->mem_cntl, val); break; - case 0xb4: + case 0xb4: mach64->bank_w[0] = val * 32768; mach64_log("mach64 : write bank A0000-A7FFF set to %08X\n", mach64->bank_w[0]); break; - case 0xb5: case 0xb6: + case 0xb5: + case 0xb6: mach64->bank_w[1] = val * 32768; mach64_log("mach64 : write bank A8000-AFFFF set to %08X\n", mach64->bank_w[1]); break; - case 0xb8: + case 0xb8: mach64->bank_r[0] = val * 32768; mach64_log("mach64 : read bank A0000-A7FFF set to %08X\n", mach64->bank_r[0]); break; - case 0xb9: case 0xba: + case 0xb9: + case 0xba: mach64->bank_r[1] = val * 32768; mach64_log("mach64 : read bank A8000-AFFFF set to %08X\n", mach64->bank_r[1]); break; - case 0xc0: case 0xc1: case 0xc2: case 0xc3: + case 0xc0: + case 0xc1: + case 0xc2: + case 0xc3: if (mach64->type == MACH64_GX) - ati68860_ramdac_out((addr & 3) | ((mach64->dac_cntl & 3) << 2), val, mach64->svga.ramdac, &mach64->svga); + ati68860_ramdac_out((addr & 3) | ((mach64->dac_cntl & 3) << 2), val, mach64->svga.ramdac, &mach64->svga); else - ati68860_ramdac_out(addr & 3, val, mach64->svga.ramdac, &mach64->svga); + ati68860_ramdac_out(addr & 3, val, mach64->svga.ramdac, &mach64->svga); break; - case 0xc4: case 0xc5: case 0xc6: case 0xc7: + case 0xc4: + case 0xc5: + case 0xc6: + case 0xc7: WRITE8(addr, mach64->dac_cntl, val); svga_set_ramdac_type(svga, (mach64->dac_cntl & 0x100) ? RAMDAC_8BIT : RAMDAC_6BIT); ati68860_set_ramdac_type(mach64->svga.ramdac, (mach64->dac_cntl & 0x100) ? RAMDAC_8BIT : RAMDAC_6BIT); i2c_gpio_set(mach64->i2c, !(mach64->dac_cntl & 0x20000000) || (mach64->dac_cntl & 0x04000000), !(mach64->dac_cntl & 0x10000000) || (mach64->dac_cntl & 0x02000000)); - break; - - case 0xd0: case 0xd1: case 0xd2: case 0xd3: - WRITE8(addr, mach64->gen_test_cntl, val); - ati_eeprom_write(&mach64->eeprom, mach64->gen_test_cntl & 0x10, mach64->gen_test_cntl & 2, mach64->gen_test_cntl & 1); - mach64->gen_test_cntl = (mach64->gen_test_cntl & ~8) | (ati_eeprom_read(&mach64->eeprom) ? 8 : 0); - svga->dac_hwcursor.ena = mach64->gen_test_cntl & 0x80; - mach64_cursor_dump(mach64); break; - case 0xdc: case 0xdd: case 0xde: case 0xdf: + case 0xd0: + case 0xd1: + case 0xd2: + case 0xd3: + WRITE8(addr, mach64->gen_test_cntl, val); + ati_eeprom_write(&mach64->eeprom, mach64->gen_test_cntl & 0x10, mach64->gen_test_cntl & 2, mach64->gen_test_cntl & 1); + mach64->gen_test_cntl = (mach64->gen_test_cntl & ~8) | (ati_eeprom_read(&mach64->eeprom) ? 8 : 0); + svga->dac_hwcursor.ena = mach64->gen_test_cntl & 0x80; + break; + + case 0xdc: + case 0xdd: + case 0xde: + case 0xdf: WRITE8(addr, mach64->config_cntl, val); mach64_updatemapping(mach64); break; - case 0xe4: case 0xe5: case 0xe6: case 0xe7: + case 0xe4: + case 0xe5: + case 0xe6: + case 0xe7: if (mach64->type != MACH64_GX) - WRITE8(addr, mach64->config_stat0, val); + WRITE8(addr, mach64->config_stat0, val); + break; + + default: break; } } -void mach64_ext_writew(uint32_t addr, uint16_t val, void *p) +void +mach64_ext_writew(uint32_t addr, uint16_t val, void *priv) { - mach64_t *mach64 = (mach64_t *)p; - mach64_log("mach64_ext_writew : addr %08X val %04X\n", addr, val); - if (!(addr & 0x400)) - { - mach64_log("nmach64_ext_writew: addr=%04x val=%04x\n", addr, val); + mach64_t *mach64 = (mach64_t *) priv; + mach64_log("mach64_ext_writew : addr %08X val %04X\n", addr, val); + if (!(addr & 0x400)) { + mach64_log("mach64_ext_writew: addr=%04x val=%04x\n", addr, val); - mach64_ext_writeb(addr, val, p); - mach64_ext_writeb(addr + 1, val >> 8, p); - } - else if (addr & 0x300) - { - mach64_accel_write_fifo_w(mach64, addr & 0x3fe, val); - } - else switch (addr & 0x3fe) - { - default: - mach64_ext_writeb(addr, val, p); - mach64_ext_writeb(addr + 1, val >> 8, p); + mach64_ext_writeb(addr, val, priv); + mach64_ext_writeb(addr + 1, val >> 8, priv); + } else if (addr & 0x300) { + mach64_accel_write_fifo_w(mach64, addr & 0x3fe, val); + } else + switch (addr & 0x3fe) { + default: + mach64_ext_writeb(addr, val, priv); + mach64_ext_writeb(addr + 1, val >> 8, priv); break; } } -void mach64_ext_writel(uint32_t addr, uint32_t val, void *p) +void +mach64_ext_writel(uint32_t addr, uint32_t val, void *priv) { - mach64_t *mach64 = (mach64_t *)p; - if ((addr & 0x3c0) != 0x200) - mach64_log("mach64_ext_writel : addr %08X val %08X\n", addr, val); - if (!(addr & 0x400)) - { - mach64_log("nmach64_ext_writel: addr=%04x val=%08x\n", addr, val); + mach64_t *mach64 = (mach64_t *) priv; + if ((addr & 0x3c0) != 0x200) + mach64_log("mach64_ext_writel : addr %08X val %08X\n", addr, val); + if (!(addr & 0x400)) { + mach64_log("mach64_ext_writel: addr=%04x val=%08x\n", addr, val); - mach64_ext_writew(addr, val, p); - mach64_ext_writew(addr + 2, val >> 16, p); - } - else if (addr & 0x300) - { - mach64_accel_write_fifo_l(mach64, addr & 0x3fc, val); - } - else switch (addr & 0x3fc) - { - default: - mach64_ext_writew(addr, val, p); - mach64_ext_writew(addr + 2, val >> 16, p); + mach64_ext_writew(addr, val, priv); + mach64_ext_writew(addr + 2, val >> 16, priv); + } else if (addr & 0x300) { + mach64_accel_write_fifo_l(mach64, addr & 0x3fc, val); + } else + switch (addr & 0x3fc) { + default: + mach64_ext_writew(addr, val, priv); + mach64_ext_writew(addr + 2, val >> 16, priv); break; } } -uint8_t mach64_ext_inb(uint16_t port, void *p) +uint8_t +mach64_ext_inb(uint16_t port, void *priv) { - mach64_t *mach64 = (mach64_t *)p; - uint8_t ret; + mach64_t *mach64 = (mach64_t *) priv; + uint8_t ret = 0xff; - switch (port) - { - case 0x02ec: case 0x02ed: case 0x02ee: case 0x02ef: - case 0x7eec: case 0x7eed: case 0x7eee: case 0x7eef: - ret = mach64_ext_readb(0x400 | 0x00 | (port & 3), p); + switch (port) { + case 0x02ec: + case 0x02ed: + case 0x02ee: + case 0x02ef: + case 0x7eec: + case 0x7eed: + case 0x7eee: + case 0x7eef: + ret = mach64_ext_readb(0x400 | 0x00 | (port & 3), priv); + break; + case 0x0aec: + case 0x0aed: + case 0x0aee: + case 0x0aef: + ret = mach64_ext_readb(0x400 | 0x08 | (port & 3), priv); + break; + case 0x0eec: + case 0x0eed: + case 0x0eee: + case 0x0eef: + ret = mach64_ext_readb(0x400 | 0x0c | (port & 3), priv); + break; + + case 0x12ec: + case 0x12ed: + case 0x12ee: + case 0x12ef: + ret = mach64_ext_readb(0x400 | 0x10 | (port & 3), priv); + break; + + case 0x16ec: + case 0x16ed: + case 0x16ee: + case 0x16ef: + ret = mach64_ext_readb(0x400 | 0x14 | (port & 3), priv); + break; + + case 0x1aec: + ret = mach64_ext_readb(0x400 | 0x18, priv); + break; + + case 0x1eec: + case 0x1eed: + case 0x1eee: + case 0x1eef: + ret = mach64_ext_readb(0x400 | 0x1c | (port & 3), priv); + break; + + case 0x22ec: + case 0x22ed: + case 0x22ee: + case 0x22ef: + ret = mach64_ext_readb(0x400 | 0x40 | (port & 3), priv); + break; + case 0x26ec: + case 0x26ed: + case 0x26ee: + case 0x26ef: + ret = mach64_ext_readb(0x400 | 0x44 | (port & 3), priv); + break; + case 0x2aec: + case 0x2aed: + case 0x2aee: + case 0x2aef: + ret = mach64_ext_readb(0x400 | 0x48 | (port & 3), priv); + break; + case 0x2eec: + case 0x2eed: + case 0x2eee: + case 0x2eef: + ret = mach64_ext_readb(0x400 | 0x60 | (port & 3), priv); + break; + + case 0x32ec: + case 0x32ed: + case 0x32ee: + case 0x32ef: + ret = mach64_ext_readb(0x400 | 0x64 | (port & 3), priv); + break; + case 0x36ec: + case 0x36ed: + case 0x36ee: + case 0x36ef: + ret = mach64_ext_readb(0x400 | 0x68 | (port & 3), priv); + break; + case 0x3aec: + case 0x3aed: + case 0x3aee: + case 0x3aef: + ret = mach64_ext_readb(0x400 | 0x6c | (port & 3), priv); + break; + case 0x3eec: + case 0x3eed: + case 0x3eee: + case 0x3eef: + ret = mach64_ext_readb(0x400 | 0x70 | (port & 3), priv); + break; + + case 0x42ec: + case 0x42ed: + case 0x42ee: + case 0x42ef: + ret = mach64_ext_readb(0x400 | 0x80 | (port & 3), priv); + break; + case 0x46ec: + case 0x46ed: + case 0x46ee: + case 0x46ef: + ret = mach64_ext_readb(0x400 | 0x84 | (port & 3), priv); + break; + case 0x4aec: + case 0x4aed: + case 0x4aee: + case 0x4aef: + ret = mach64_ext_readb(0x400 | 0x90 | (port & 3), priv); + break; + + case 0x52ec: + case 0x52ed: + case 0x52ee: + case 0x52ef: + ret = mach64_ext_readb(0x400 | 0xb0 | (port & 3), priv); + break; + + case 0x56ec: + ret = mach64_ext_readb(0x400 | 0xb4, priv); + break; + case 0x56ed: + case 0x56ee: + ret = mach64_ext_readb(0x400 | 0xb5, priv); + break; + case 0x5aec: + ret = mach64_ext_readb(0x400 | 0xb8, priv); + break; + case 0x5aed: + case 0x5aee: + ret = mach64_ext_readb(0x400 | 0xb9, priv); + break; + + case 0x5eec: + case 0x5eed: + case 0x5eee: + case 0x5eef: + if (mach64->type == MACH64_GX) + ret = ati68860_ramdac_in((port & 3) | ((mach64->dac_cntl & 3) << 2), mach64->svga.ramdac, &mach64->svga); + else + ret = ati68860_ramdac_in(port & 3, mach64->svga.ramdac, &mach64->svga); + break; + + case 0x62ec: + case 0x62ed: + case 0x62ee: + case 0x62ef: + ret = mach64_ext_readb(0x400 | 0xc4 | (port & 3), priv); + break; + + case 0x66ec: + case 0x66ed: + case 0x66ee: + case 0x66ef: + ret = mach64_ext_readb(0x400 | 0xd0 | (port & 3), priv); + break; + + case 0x6aec: + case 0x6aed: + case 0x6aee: + case 0x6aef: + mach64->config_cntl = (mach64->config_cntl & ~0x3ff0) | ((mach64->linear_base >> 22) << 4); + READ8(port, mach64->config_cntl); + break; + + case 0x6eec: + case 0x6eed: + case 0x6eee: + case 0x6eef: + ret = mach64_ext_readb(0x400 | 0xe0 | (port & 3), priv); + break; + + case 0x72ec: + case 0x72ed: + case 0x72ee: + case 0x72ef: + ret = mach64_ext_readb(0x400 | 0xe4 | (port & 3), priv); + break; + + default: + ret = 0; + break; + } + mach64_log("mach64_ext_inb : port %04X ret %02X\n", port, ret); + return ret; +} +uint16_t +mach64_ext_inw(uint16_t port, void *priv) +{ + uint16_t ret; + switch (port) { + default: + ret = mach64_ext_inb(port, priv); + ret |= (mach64_ext_inb(port + 1, priv) << 8); + break; + } + mach64_log("mach64_ext_inw : port %04X ret %04X\n", port, ret); + return ret; +} +uint32_t +mach64_ext_inl(uint16_t port, void *priv) +{ + uint32_t ret; + switch (port) { + case 0x56ec: + ret = mach64_ext_readl(0x400 | 0xb4, priv); + break; + case 0x5aec: + ret = mach64_ext_readl(0x400 | 0xb8, priv); + break; + + default: + ret = mach64_ext_inw(port, priv); + ret |= (mach64_ext_inw(port + 2, priv) << 16); + break; + } + mach64_log("mach64_ext_inl : port %04X ret %08X\n", port, ret); + return ret; +} + +void +mach64_ext_outb(uint16_t port, uint8_t val, void *priv) +{ + mach64_t *mach64 = (mach64_t *) priv; + + mach64_log("mach64_ext_outb : port %04X val %02X\n", port, val); + switch (port) { + case 0x02ec: + case 0x02ed: + case 0x02ee: + case 0x02ef: + case 0x7eec: + case 0x7eed: + case 0x7eee: + case 0x7eef: + mach64_ext_writeb(0x400 | 0x00 | (port & 3), val, priv); + break; + case 0x0aec: + case 0x0aed: + case 0x0aee: + case 0x0aef: + mach64_ext_writeb(0x400 | 0x08 | (port & 3), val, priv); + break; + case 0x0eec: + case 0x0eed: + case 0x0eee: + case 0x0eef: + mach64_ext_writeb(0x400 | 0x0c | (port & 3), val, priv); + break; + + case 0x16ec: + case 0x16ed: + case 0x16ee: + case 0x16ef: + mach64_ext_writeb(0x400 | 0x14 | (port & 3), val, priv); + break; + + case 0x1aec: + mach64_ext_writeb(0x400 | 0x18, val, priv); + break; + + case 0x1eec: + case 0x1eed: + case 0x1eee: + case 0x1eef: + mach64_ext_writeb(0x400 | 0x1c | (port & 3), val, priv); + break; + + case 0x22ec: + case 0x22ed: + case 0x22ee: + case 0x22ef: + mach64_ext_writeb(0x400 | 0x40 | (port & 3), val, priv); + break; + case 0x26ec: + case 0x26ed: + case 0x26ee: + case 0x26ef: + mach64_ext_writeb(0x400 | 0x44 | (port & 3), val, priv); + break; + case 0x2aec: + case 0x2aed: + case 0x2aee: + case 0x2aef: + mach64_ext_writeb(0x400 | 0x48 | (port & 3), val, priv); + break; + case 0x2eec: + case 0x2eed: + case 0x2eee: + case 0x2eef: + mach64_ext_writeb(0x400 | 0x60 | (port & 3), val, priv); + break; + + case 0x32ec: + case 0x32ed: + case 0x32ee: + case 0x32ef: + mach64_ext_writeb(0x400 | 0x64 | (port & 3), val, priv); + break; + case 0x36ec: + case 0x36ed: + case 0x36ee: + case 0x36ef: + mach64_ext_writeb(0x400 | 0x68 | (port & 3), val, priv); + break; + case 0x3aec: + case 0x3aed: + case 0x3aee: + case 0x3aef: + mach64_ext_writeb(0x400 | 0x6c | (port & 3), val, priv); + break; + case 0x3eec: + case 0x3eed: + case 0x3eee: + case 0x3eef: + mach64_ext_writeb(0x400 | 0x70 | (port & 3), val, priv); + break; + + case 0x42ec: + case 0x42ed: + case 0x42ee: + case 0x42ef: + mach64_ext_writeb(0x400 | 0x80 | (port & 3), val, priv); + break; + case 0x46ec: + case 0x46ed: + case 0x46ee: + case 0x46ef: + mach64_ext_writeb(0x400 | 0x84 | (port & 3), val, priv); + break; + case 0x4aec: + case 0x4aed: + case 0x4aee: + case 0x4aef: + mach64_ext_writeb(0x400 | 0x90 | (port & 3), val, priv); + break; + + case 0x52ec: + case 0x52ed: + case 0x52ee: + case 0x52ef: + mach64_ext_writeb(0x400 | 0xb0 | (port & 3), val, priv); + break; + + case 0x56ec: + mach64_ext_writeb(0x400 | 0xb4, val, priv); + break; + case 0x56ed: + case 0x56ee: + mach64_ext_writeb(0x400 | 0xb5, val, priv); + break; + case 0x5aec: + mach64_ext_writeb(0x400 | 0xb8, val, priv); + break; + case 0x5aed: + case 0x5aee: + mach64_ext_writeb(0x400 | 0xb9, val, priv); + break; + + case 0x5eec: + case 0x5eed: + case 0x5eee: + case 0x5eef: + if (mach64->type == MACH64_GX) + ati68860_ramdac_out((port & 3) | ((mach64->dac_cntl & 3) << 2), val, mach64->svga.ramdac, &mach64->svga); + else + ati68860_ramdac_out(port & 3, val, mach64->svga.ramdac, &mach64->svga); + break; + + case 0x62ec: + case 0x62ed: + case 0x62ee: + case 0x62ef: + mach64_ext_writeb(0x400 | 0xc4 | (port & 3), val, priv); + break; + + case 0x66ec: + case 0x66ed: + case 0x66ee: + case 0x66ef: + mach64_ext_writeb(0x400 | 0xd0 | (port & 3), val, priv); + break; + + case 0x6aec: + case 0x6aed: + case 0x6aee: + case 0x6aef: + WRITE8(port, mach64->config_cntl, val); + mach64_updatemapping(mach64); + break; + + default: + break; + } +} +void +mach64_ext_outw(uint16_t port, uint16_t val, void *priv) +{ + mach64_log("mach64_ext_outw : port %04X val %04X\n", port, val); + switch (port) { + default: + mach64_ext_outb(port, val, priv); + mach64_ext_outb(port + 1, val >> 8, priv); + break; + } +} +void +mach64_ext_outl(uint16_t port, uint32_t val, void *priv) +{ + mach64_log("mach64_ext_outl : port %04X val %08X\n", port, val); + switch (port) { + default: + mach64_ext_outw(port, val, priv); + mach64_ext_outw(port + 2, val >> 16, priv); + break; + } +} + +static uint8_t +mach64_block_inb(uint16_t port, void *priv) +{ + mach64_t *mach64 = (mach64_t *) priv; + uint8_t ret; + + ret = mach64_ext_readb(0x400 | (port & 0x3ff), mach64); + mach64_log("mach64_block_inb : port %04X ret %02X\n", port, ret); + return ret; +} +static uint16_t +mach64_block_inw(uint16_t port, void *priv) +{ + mach64_t *mach64 = (mach64_t *) priv; + uint16_t ret; + + ret = mach64_ext_readw(0x400 | (port & 0x3ff), mach64); + mach64_log("mach64_block_inw : port %04X ret %04X\n", port, ret); + return ret; +} +static uint32_t +mach64_block_inl(uint16_t port, void *priv) +{ + mach64_t *mach64 = (mach64_t *) priv; + uint32_t ret; + + ret = mach64_ext_readl(0x400 | (port & 0x3ff), mach64); + mach64_log("mach64_block_inl : port %04X ret %08X\n", port, ret); + return ret; +} + +static void +mach64_block_outb(uint16_t port, uint8_t val, void *priv) +{ + mach64_t *mach64 = (mach64_t *) priv; + + mach64_log("mach64_block_outb : port %04X val %02X\n ", port, val); + mach64_ext_writeb(0x400 | (port & 0x3ff), val, mach64); +} +static void +mach64_block_outw(uint16_t port, uint16_t val, void *priv) +{ + mach64_t *mach64 = (mach64_t *) priv; + + mach64_log("mach64_block_outw : port %04X val %04X\n ", port, val); + mach64_ext_writew(0x400 | (port & 0x3ff), val, mach64); +} +static void +mach64_block_outl(uint16_t port, uint32_t val, void *priv) +{ + mach64_t *mach64 = (mach64_t *) priv; + + mach64_log("mach64_block_outl : port %04X val %08X\n ", port, val); + mach64_ext_writel(0x400 | (port & 0x3ff), val, mach64); +} + +void +mach64_write(uint32_t addr, uint8_t val, void *priv) +{ + mach64_t *mach64 = (mach64_t *) priv; + svga_t *svga = &mach64->svga; + addr = (addr & 0x7fff) + mach64->bank_w[(addr >> 15) & 1]; + svga_write_linear(addr, val, svga); +} +void +mach64_writew(uint32_t addr, uint16_t val, void *priv) +{ + mach64_t *mach64 = (mach64_t *) priv; + svga_t *svga = &mach64->svga; + + addr = (addr & 0x7fff) + mach64->bank_w[(addr >> 15) & 1]; + svga_writew_linear(addr, val, svga); +} +void +mach64_writel(uint32_t addr, uint32_t val, void *priv) +{ + mach64_t *mach64 = (mach64_t *) priv; + svga_t *svga = &mach64->svga; + + addr = (addr & 0x7fff) + mach64->bank_w[(addr >> 15) & 1]; + svga_writel_linear(addr, val, svga); +} + +uint8_t +mach64_read(uint32_t addr, void *priv) +{ + mach64_t *mach64 = (mach64_t *) priv; + svga_t *svga = &mach64->svga; + uint8_t ret; + addr = (addr & 0x7fff) + mach64->bank_r[(addr >> 15) & 1]; + ret = svga_read_linear(addr, svga); + return ret; +} +uint16_t +mach64_readw(uint32_t addr, void *priv) +{ + mach64_t *mach64 = (mach64_t *) priv; + svga_t *svga = &mach64->svga; + + addr = (addr & 0x7fff) + mach64->bank_r[(addr >> 15) & 1]; + return svga_readw_linear(addr, svga); +} +uint32_t +mach64_readl(uint32_t addr, void *priv) +{ + mach64_t *mach64 = (mach64_t *) priv; + svga_t *svga = &mach64->svga; + + addr = (addr & 0x7fff) + mach64->bank_r[(addr >> 15) & 1]; + return svga_readl_linear(addr, svga); +} + +#define CLAMP(x) \ + do { \ + if ((x) & ~0xff) \ + x = ((x) < 0) ? 0 : 0xff; \ + } while (0) + +#define DECODE_ARGB1555() \ + do { \ + for (x = 0; x < mach64->svga.overlay_latch.cur_xsize; x++) { \ + uint16_t dat = ((uint16_t *) src)[x]; \ + \ + int b = dat & 0x1f; \ + int g = (dat >> 5) & 0x1f; \ + int r = (dat >> 10) & 0x1f; \ + \ + b = (b << 3) | (b >> 2); \ + g = (g << 3) | (g >> 2); \ + r = (r << 3) | (r >> 2); \ + \ + mach64->overlay_dat[x] = (r << 16) | (g << 8) | b; \ + } \ + } while (0) + +#define DECODE_RGB565() \ + do { \ + for (x = 0; x < mach64->svga.overlay_latch.cur_xsize; x++) { \ + uint16_t dat = ((uint16_t *) src)[x]; \ + \ + int b = dat & 0x1f; \ + int g = (dat >> 5) & 0x3f; \ + int r = (dat >> 11) & 0x1f; \ + \ + b = (b << 3) | (b >> 2); \ + g = (g << 2) | (g >> 4); \ + r = (r << 3) | (r >> 2); \ + \ + mach64->overlay_dat[x] = (r << 16) | (g << 8) | b; \ + } \ + } while (0) + +#define DECODE_ARGB8888() \ + do { \ + for (x = 0; x < mach64->svga.overlay_latch.cur_xsize; x++) { \ + int b = src[0]; \ + int g = src[1]; \ + int r = src[2]; \ + src += 4; \ + \ + mach64->overlay_dat[x] = (r << 16) | (g << 8) | b; \ + } \ + } while (0) + +#define DECODE_VYUY422() \ + do { \ + for (x = 0; x < mach64->svga.overlay_latch.cur_xsize; x += 2) { \ + uint8_t y1, y2; \ + int8_t u, v; \ + int dR, dG, dB; \ + int r, g, b; \ + \ + y1 = src[0]; \ + u = src[1] - 0x80; \ + y2 = src[2]; \ + v = src[3] - 0x80; \ + src += 4; \ + \ + dR = (359 * v) >> 8; \ + dG = (88 * u + 183 * v) >> 8; \ + dB = (453 * u) >> 8; \ + \ + r = y1 + dR; \ + CLAMP(r); \ + g = y1 - dG; \ + CLAMP(g); \ + b = y1 + dB; \ + CLAMP(b); \ + mach64->overlay_dat[x] = (r << 16) | (g << 8) | b; \ + \ + r = y2 + dR; \ + CLAMP(r); \ + g = y2 - dG; \ + CLAMP(g); \ + b = y2 + dB; \ + CLAMP(b); \ + mach64->overlay_dat[x + 1] = (r << 16) | (g << 8) | b; \ + } \ + } while (0) + +#define DECODE_YVYU422() \ + do { \ + for (x = 0; x < mach64->svga.overlay_latch.cur_xsize; x += 2) { \ + uint8_t y1, y2; \ + int8_t u, v; \ + int dR, dG, dB; \ + int r, g, b; \ + \ + u = src[0] - 0x80; \ + y1 = src[1]; \ + v = src[2] - 0x80; \ + y2 = src[3]; \ + src += 4; \ + \ + dR = (359 * v) >> 8; \ + dG = (88 * u + 183 * v) >> 8; \ + dB = (453 * u) >> 8; \ + \ + r = y1 + dR; \ + CLAMP(r); \ + g = y1 - dG; \ + CLAMP(g); \ + b = y1 + dB; \ + CLAMP(b); \ + mach64->overlay_dat[x] = (r << 16) | (g << 8) | b; \ + \ + r = y2 + dR; \ + CLAMP(r); \ + g = y2 - dG; \ + CLAMP(g); \ + b = y2 + dB; \ + CLAMP(b); \ + mach64->overlay_dat[x + 1] = (r << 16) | (g << 8) | b; \ + } \ + } while (0) + +void +mach64_overlay_draw(svga_t *svga, int displine) +{ + mach64_t *mach64 = (mach64_t *) svga->priv; + int x; + int h_acc = 0; + int h_max = (mach64->scaler_height_width >> 16) & 0x3ff; + int h_inc = mach64->overlay_scale_inc >> 16; + int v_max = mach64->scaler_height_width & 0x3ff; + int v_inc = mach64->overlay_scale_inc & 0xffff; + uint32_t *p; + uint8_t *src = &svga->vram[svga->overlay.addr]; + int old_y = mach64->overlay_v_acc; + int y_diff; + int video_key_fn = mach64->overlay_key_cntl & 5; + int graphics_key_fn = (mach64->overlay_key_cntl >> 4) & 5; + int overlay_cmp_mix = (mach64->overlay_key_cntl >> 8) & 0xf; + + p = &buffer32->line[displine][svga->x_add + mach64->svga.overlay_latch.x]; + + if (mach64->scaler_update) { + switch (mach64->scaler_format) { + case 0x3: + DECODE_ARGB1555(); break; - case 0x0aec: case 0x0aed: case 0x0aee: case 0x0aef: - ret = mach64_ext_readb(0x400 | 0x08 | (port & 3), p); + case 0x4: + DECODE_RGB565(); break; - case 0x0eec: case 0x0eed: case 0x0eee: case 0x0eef: - ret = mach64_ext_readb(0x400 | 0x0c | (port & 3), p); + case 0x6: + DECODE_ARGB8888(); + break; + case 0xb: + DECODE_VYUY422(); + break; + case 0xc: + DECODE_YVYU422(); break; - case 0x12ec: case 0x12ed: case 0x12ee: case 0x12ef: - ret = mach64_ext_readb(0x400 | 0x10 | (port & 3), p); + default: + mach64_log("Unknown Mach64 scaler format %x\n", mach64->scaler_format); + /*Fill buffer with something recognisably wrong*/ + for (x = 0; x < mach64->svga.overlay_latch.cur_xsize; x++) + mach64->overlay_dat[x] = 0xff00ff; break; + } + } - case 0x16ec: case 0x16ed: case 0x16ee: case 0x16ef: - ret = mach64_ext_readb(0x400 | 0x14 | (port & 3), p); - break; + if (overlay_cmp_mix == 2) { + for (x = 0; x < mach64->svga.overlay_latch.cur_xsize; x++) { + int h = h_acc >> 12; - case 0x1aec: - ret = mach64_ext_readb(0x400 | 0x18, p); - break; + p[x] = mach64->overlay_dat[h]; - case 0x1eec: case 0x1eed: case 0x1eee: case 0x1eef: - ret = mach64_ext_readb(0x400 | 0x1c | (port & 3), p); - break; + h_acc += h_inc; + if (h_acc > (h_max << 12)) + h_acc = (h_max << 12); + } + } else { + for (x = 0; x < mach64->svga.overlay_latch.cur_xsize; x++) { + int h = h_acc >> 12; + int gr_cmp = 0; + int vid_cmp = 0; + int use_video = 0; - case 0x22ec: case 0x22ed: case 0x22ee: case 0x22ef: - ret = mach64_ext_readb(0x400 | 0x40 | (port & 3), p); - break; - case 0x26ec: case 0x26ed: case 0x26ee: case 0x26ef: - ret = mach64_ext_readb(0x400 | 0x44 | (port & 3), p); - break; - case 0x2aec: case 0x2aed: case 0x2aee: case 0x2aef: - ret = mach64_ext_readb(0x400 | 0x48 | (port & 3), p); - break; - case 0x2eec: case 0x2eed: case 0x2eee: case 0x2eef: - ret = mach64_ext_readb(0x400 | 0x60 | (port & 3), p); - break; - - case 0x32ec: case 0x32ed: case 0x32ee: case 0x32ef: - ret = mach64_ext_readb(0x400 | 0x64 | (port & 3), p); - break; - case 0x36ec: case 0x36ed: case 0x36ee: case 0x36ef: - ret = mach64_ext_readb(0x400 | 0x68 | (port & 3), p); - break; - case 0x3aec: case 0x3aed: case 0x3aee: case 0x3aef: - ret = mach64_ext_readb(0x400 | 0x6c | (port & 3), p); - break; - case 0x3eec: case 0x3eed: case 0x3eee: case 0x3eef: - ret = mach64_ext_readb(0x400 | 0x70 | (port & 3), p); - break; - - case 0x42ec: case 0x42ed: case 0x42ee: case 0x42ef: - ret = mach64_ext_readb(0x400 | 0x80 | (port & 3), p); - break; - case 0x46ec: case 0x46ed: case 0x46ee: case 0x46ef: - ret = mach64_ext_readb(0x400 | 0x84 | (port & 3), p); - break; - case 0x4aec: case 0x4aed: case 0x4aee: case 0x4aef: - ret = mach64_ext_readb(0x400 | 0x90 | (port & 3), p); - break; - - case 0x52ec: case 0x52ed: case 0x52ee: case 0x52ef: - ret = mach64_ext_readb(0x400 | 0xb0 | (port & 3), p); - break; - - case 0x56ec: - ret = mach64_ext_readb(0x400 | 0xb4, p); - break; - case 0x56ed: case 0x56ee: - ret = mach64_ext_readb(0x400 | 0xb5, p); - break; - case 0x5aec: - ret = mach64_ext_readb(0x400 | 0xb8, p); - break; - case 0x5aed: case 0x5aee: - ret = mach64_ext_readb(0x400 | 0xb9, p); - break; - - case 0x5eec: case 0x5eed: case 0x5eee: case 0x5eef: - if (mach64->type == MACH64_GX) - ret = ati68860_ramdac_in((port & 3) | ((mach64->dac_cntl & 3) << 2), mach64->svga.ramdac, &mach64->svga); - else - ret = ati68860_ramdac_in(port & 3, mach64->svga.ramdac, &mach64->svga); - break; - - case 0x62ec: case 0x62ed: case 0x62ee: case 0x62ef: - ret = mach64_ext_readb(0x400 | 0xc4 | (port & 3), p); - break; - - case 0x66ec: case 0x66ed: case 0x66ee: case 0x66ef: - ret = mach64_ext_readb(0x400 | 0xd0 | (port & 3), p); - break; - - case 0x6aec: case 0x6aed: case 0x6aee: case 0x6aef: - mach64->config_cntl = (mach64->config_cntl & ~0x3ff0) | ((mach64->linear_base >> 22) << 4); - READ8(port, mach64->config_cntl); - break; - - case 0x6eec: case 0x6eed: case 0x6eee: case 0x6eef: - ret = mach64_ext_readb(0x400 | 0xe0 | (port & 3), p); - break; - - case 0x72ec: case 0x72ed: case 0x72ee: case 0x72ef: - ret = mach64_ext_readb(0x400 | 0xe4 | (port & 3), p); - break; + switch (video_key_fn) { + case 0: + vid_cmp = 0; + break; + case 1: + vid_cmp = 1; + break; + case 4: + vid_cmp = ((mach64->overlay_dat[h] ^ mach64->overlay_video_key_clr) & mach64->overlay_video_key_msk); + break; + case 5: + vid_cmp = !((mach64->overlay_dat[h] ^ mach64->overlay_video_key_clr) & mach64->overlay_video_key_msk); + break; default: - ret = 0; - break; - } - mach64_log("mach64_ext_inb : port %04X ret %02X\n", port, ret); - return ret; -} -uint16_t mach64_ext_inw(uint16_t port, void *p) -{ - uint16_t ret; - switch (port) - { - default: - ret = mach64_ext_inb(port, p); - ret |= (mach64_ext_inb(port + 1, p) << 8); - break; - } - mach64_log("mach64_ext_inw : port %04X ret %04X\n", port, ret); - return ret; -} -uint32_t mach64_ext_inl(uint16_t port, void *p) -{ - uint32_t ret; - switch (port) - { - case 0x56ec: - ret = mach64_ext_readl(0x400 | 0xb4, p); - break; - case 0x5aec: - ret = mach64_ext_readl(0x400 | 0xb8, p); - break; + break; + } + switch (graphics_key_fn) { + case 0: + gr_cmp = 0; + break; + case 1: + gr_cmp = 1; + break; + case 4: + gr_cmp = (((p[x]) ^ mach64->overlay_graphics_key_clr) & mach64->overlay_graphics_key_msk & 0xffffff); + break; + case 5: + gr_cmp = !(((p[x]) ^ mach64->overlay_graphics_key_clr) & mach64->overlay_graphics_key_msk & 0xffffff); + break; default: - ret = mach64_ext_inw(port, p); - ret |= (mach64_ext_inw(port + 2, p) << 16); - break; - } - mach64_log("mach64_ext_inl : port %04X ret %08X\n", port, ret); - return ret; -} + break; + } + vid_cmp = vid_cmp ? -1 : 0; + gr_cmp = gr_cmp ? -1 : 0; -void mach64_ext_outb(uint16_t port, uint8_t val, void *p) -{ - mach64_t *mach64 = (mach64_t *)p; + switch (overlay_cmp_mix) { + case 0x0: + use_video = gr_cmp; + break; + case 0x1: + use_video = 0; + break; + case 0x2: + use_video = ~0; + break; + case 0x3: + use_video = ~gr_cmp; + break; + case 0x4: + use_video = ~vid_cmp; + break; + case 0x5: + use_video = gr_cmp ^ vid_cmp; + break; + case 0x6: + use_video = ~gr_cmp ^ vid_cmp; + break; + case 0x7: + use_video = vid_cmp; + break; + case 0x8: + use_video = ~gr_cmp | ~vid_cmp; + break; + case 0x9: + use_video = gr_cmp | ~vid_cmp; + break; + case 0xa: + use_video = ~gr_cmp | vid_cmp; + break; + case 0xb: + use_video = gr_cmp | vid_cmp; + break; + case 0xc: + use_video = gr_cmp & vid_cmp; + break; + case 0xd: + use_video = ~gr_cmp & vid_cmp; + break; + case 0xe: + use_video = gr_cmp & ~vid_cmp; + break; + case 0xf: + use_video = ~gr_cmp & ~vid_cmp; + break; - mach64_log("mach64_ext_outb : port %04X val %02X\n", port, val); - switch (port) - { - case 0x02ec: case 0x02ed: case 0x02ee: case 0x02ef: - case 0x7eec: case 0x7eed: case 0x7eee: case 0x7eef: - mach64_ext_writeb(0x400 | 0x00 | (port & 3), val, p); - break; - case 0x0aec: case 0x0aed: case 0x0aee: case 0x0aef: - mach64_ext_writeb(0x400 | 0x08 | (port & 3), val, p); - break; - case 0x0eec: case 0x0eed: case 0x0eee: case 0x0eef: - mach64_ext_writeb(0x400 | 0x0c | (port & 3), val, p); - break; - - case 0x16ec: case 0x16ed: case 0x16ee: case 0x16ef: - mach64_ext_writeb(0x400 | 0x14 | (port & 3), val, p); - break; - - case 0x1aec: - mach64_ext_writeb(0x400 | 0x18, val, p); - break; - - case 0x1eec: case 0x1eed: case 0x1eee: case 0x1eef: - mach64_ext_writeb(0x400 | 0x1c | (port & 3), val, p); - break; - - case 0x22ec: case 0x22ed: case 0x22ee: case 0x22ef: - mach64_ext_writeb(0x400 | 0x40 | (port & 3), val, p); - break; - case 0x26ec: case 0x26ed: case 0x26ee: case 0x26ef: - mach64_ext_writeb(0x400 | 0x44 | (port & 3), val, p); - break; - case 0x2aec: case 0x2aed: case 0x2aee: case 0x2aef: - mach64_ext_writeb(0x400 | 0x48 | (port & 3), val, p); - break; - case 0x2eec: case 0x2eed: case 0x2eee: case 0x2eef: - mach64_ext_writeb(0x400 | 0x60 | (port & 3), val, p); - break; - - case 0x32ec: case 0x32ed: case 0x32ee: case 0x32ef: - mach64_ext_writeb(0x400 | 0x64 | (port & 3), val, p); - break; - case 0x36ec: case 0x36ed: case 0x36ee: case 0x36ef: - mach64_ext_writeb(0x400 | 0x68 | (port & 3), val, p); - break; - case 0x3aec: case 0x3aed: case 0x3aee: case 0x3aef: - mach64_ext_writeb(0x400 | 0x6c | (port & 3), val, p); - break; - case 0x3eec: case 0x3eed: case 0x3eee: case 0x3eef: - mach64_ext_writeb(0x400 | 0x70 | (port & 3), val, p); - break; - - case 0x42ec: case 0x42ed: case 0x42ee: case 0x42ef: - mach64_ext_writeb(0x400 | 0x80 | (port & 3), val, p); - break; - case 0x46ec: case 0x46ed: case 0x46ee: case 0x46ef: - mach64_ext_writeb(0x400 | 0x84 | (port & 3), val, p); - break; - case 0x4aec: case 0x4aed: case 0x4aee: case 0x4aef: - mach64_ext_writeb(0x400 | 0x90 | (port & 3), val, p); - break; - - case 0x52ec: case 0x52ed: case 0x52ee: case 0x52ef: - mach64_ext_writeb(0x400 | 0xb0 | (port & 3), val, p); - break; - - case 0x56ec: - mach64_ext_writeb(0x400 | 0xb4, val, p); - break; - case 0x56ed: case 0x56ee: - mach64_ext_writeb(0x400 | 0xb5, val, p); - break; - case 0x5aec: - mach64_ext_writeb(0x400 | 0xb8, val, p); - break; - case 0x5aed: case 0x5aee: - mach64_ext_writeb(0x400 | 0xb9, val, p); - break; - - case 0x5eec: case 0x5eed: case 0x5eee: case 0x5eef: - if (mach64->type == MACH64_GX) - ati68860_ramdac_out((port & 3) | ((mach64->dac_cntl & 3) << 2), val, mach64->svga.ramdac, &mach64->svga); - else - ati68860_ramdac_out(port & 3, val, mach64->svga.ramdac, &mach64->svga); - break; - - case 0x62ec: case 0x62ed: case 0x62ee: case 0x62ef: - mach64_ext_writeb(0x400 | 0xc4 | (port & 3), val, p); - break; - - case 0x66ec: case 0x66ed: case 0x66ee: case 0x66ef: - mach64_ext_writeb(0x400 | 0xd0 | (port & 3), val, p); - break; - - case 0x6aec: case 0x6aed: case 0x6aee: case 0x6aef: - WRITE8(port, mach64->config_cntl, val); - mach64_updatemapping(mach64); - break; - } -} -void mach64_ext_outw(uint16_t port, uint16_t val, void *p) -{ - mach64_log("mach64_ext_outw : port %04X val %04X\n", port, val); - switch (port) - { default: - mach64_ext_outb(port, val, p); - mach64_ext_outb(port + 1, val >> 8, p); - break; + break; + } + + if (use_video) + p[x] = mach64->overlay_dat[h]; + + h_acc += h_inc; + if (h_acc > (h_max << 12)) + h_acc = (h_max << 12); } + } + + mach64->overlay_v_acc += v_inc; + if (mach64->overlay_v_acc > (v_max << 12)) + mach64->overlay_v_acc = v_max << 12; + + y_diff = (mach64->overlay_v_acc >> 12) - (old_y >> 12); + + if (mach64->scaler_format == 6) + svga->overlay.addr += svga->overlay.pitch * 4 * y_diff; + else + svga->overlay.addr += svga->overlay.pitch * 2 * y_diff; + + mach64->scaler_update = y_diff; } -void mach64_ext_outl(uint16_t port, uint32_t val, void *p) + +static void +mach64_io_remove(mach64_t *mach64) { - mach64_log("mach64_ext_outl : port %04X val %08X\n", port, val); - switch (port) - { - default: - mach64_ext_outw(port, val, p); - mach64_ext_outw(port + 2, val >> 16, p); - break; + uint16_t io_base = 0x02ec; + + switch (mach64->io_base) { + default: + case 0: + io_base = 0x02ec; + break; + case 1: + io_base = 0x01cc; + break; + case 2: + io_base = 0x01c8; + break; + case 3: + fatal("Attempting to use the reserved value for I/O Base\n"); + return; + } + + io_removehandler(0x03c0, 0x0020, mach64_in, NULL, NULL, mach64_out, NULL, NULL, mach64); + + for (uint8_t c = 0; c < 8; c++) { + io_removehandler((c * 0x1000) + 0x0000 + io_base, 0x0004, mach64_ext_inb, mach64_ext_inw, mach64_ext_inl, mach64_ext_outb, mach64_ext_outw, mach64_ext_outl, mach64); + io_removehandler((c * 0x1000) + 0x0400 + io_base, 0x0004, mach64_ext_inb, mach64_ext_inw, mach64_ext_inl, mach64_ext_outb, mach64_ext_outw, mach64_ext_outl, mach64); + io_removehandler((c * 0x1000) + 0x0800 + io_base, 0x0004, mach64_ext_inb, mach64_ext_inw, mach64_ext_inl, mach64_ext_outb, mach64_ext_outw, mach64_ext_outl, mach64); + io_removehandler((c * 0x1000) + 0x0c00 + io_base, 0x0004, mach64_ext_inb, mach64_ext_inw, mach64_ext_inl, mach64_ext_outb, mach64_ext_outw, mach64_ext_outl, mach64); + } + + io_removehandler(0x01ce, 0x0002, mach64_in, NULL, NULL, mach64_out, NULL, NULL, mach64); + + if (mach64->block_decoded_io && mach64->block_decoded_io < 0x10000) + io_removehandler(mach64->block_decoded_io, 0x0400, mach64_block_inb, mach64_block_inw, mach64_block_inl, mach64_block_outb, mach64_block_outw, mach64_block_outl, mach64); +} + +static void +mach64_io_set(mach64_t *mach64) +{ + mach64_io_remove(mach64); + + io_sethandler(0x03c0, 0x0020, mach64_in, NULL, NULL, mach64_out, NULL, NULL, mach64); + + if (!mach64->use_block_decoded_io) { + for (uint8_t c = 0; c < 8; c++) { + io_sethandler((c * 0x1000) + 0x2ec, 0x0004, mach64_ext_inb, mach64_ext_inw, mach64_ext_inl, mach64_ext_outb, mach64_ext_outw, mach64_ext_outl, mach64); + io_sethandler((c * 0x1000) + 0x6ec, 0x0004, mach64_ext_inb, mach64_ext_inw, mach64_ext_inl, mach64_ext_outb, mach64_ext_outw, mach64_ext_outl, mach64); + io_sethandler((c * 0x1000) + 0xaec, 0x0004, mach64_ext_inb, mach64_ext_inw, mach64_ext_inl, mach64_ext_outb, mach64_ext_outw, mach64_ext_outl, mach64); + io_sethandler((c * 0x1000) + 0xeec, 0x0004, mach64_ext_inb, mach64_ext_inw, mach64_ext_inl, mach64_ext_outb, mach64_ext_outw, mach64_ext_outl, mach64); } + } + + io_sethandler(0x01ce, 0x0002, mach64_in, NULL, NULL, mach64_out, NULL, NULL, mach64); + + if (mach64->use_block_decoded_io && mach64->block_decoded_io && mach64->block_decoded_io < 0x10000) + io_sethandler(mach64->block_decoded_io, 0x0400, mach64_block_inb, mach64_block_inw, mach64_block_inl, mach64_block_outb, mach64_block_outw, mach64_block_outl, mach64); } -static uint8_t mach64_block_inb(uint16_t port, void *p) +uint8_t +mach64_pci_read(UNUSED(int func), int addr, void *priv) { - mach64_t *mach64 = (mach64_t *)p; - uint8_t ret; - - ret = mach64_ext_readb(0x400 | (port & 0x3ff), mach64); - mach64_log("mach64_block_inb : port %04X ret %02X\n", port, ret); - return ret; -} -static uint16_t mach64_block_inw(uint16_t port, void *p) -{ - mach64_t *mach64 = (mach64_t *)p; - uint16_t ret; - - ret = mach64_ext_readw(0x400 | (port & 0x3ff), mach64); - mach64_log("mach64_block_inw : port %04X ret %04X\n", port, ret); - return ret; -} -static uint32_t mach64_block_inl(uint16_t port, void *p) -{ - mach64_t *mach64 = (mach64_t *)p; - uint32_t ret; - - ret = mach64_ext_readl(0x400 | (port & 0x3ff), mach64); - mach64_log("mach64_block_inl : port %04X ret %08X\n", port, ret); - return ret; + const mach64_t *mach64 = (mach64_t *) priv; + + switch (addr) { + case 0x00: + return 0x02; /*ATi*/ + case 0x01: + return 0x10; + + case 0x02: + return mach64->pci_id & 0xff; + case 0x03: + return mach64->pci_id >> 8; + + case PCI_REG_COMMAND: + return mach64->pci_regs[PCI_REG_COMMAND]; /*Respond to IO and memory accesses*/ + + case 0x07: + return 1 << 1; /*Medium DEVSEL timing*/ + + case 0x08: /*Revision ID*/ + if (mach64->type == MACH64_GX) + return 0; + return 0x40; + + case 0x09: + return 0; /*Programming interface*/ + + case 0x0a: + return 0x01; /*Supports VGA interface, XGA compatible*/ + case 0x0b: + return 0x03; + + case 0x10: + return 0x00; /*Linear frame buffer address*/ + case 0x11: + return 0x00; + case 0x12: + return mach64->linear_base >> 16; + case 0x13: + return mach64->linear_base >> 24; + + case 0x14: + if (mach64->type == MACH64_VT2) + return 0x01; /*Block decoded IO address*/ + return 0x00; + case 0x15: + if (mach64->type == MACH64_VT2) + return mach64->block_decoded_io >> 8; + return 0x00; + case 0x16: + if (mach64->type == MACH64_VT2) + return mach64->block_decoded_io >> 16; + return 0x00; + case 0x17: + if (mach64->type == MACH64_VT2) + return mach64->block_decoded_io >> 24; + return 0x00; + + case 0x30: + return mach64->pci_regs[0x30] & 0x01; /*BIOS ROM address*/ + case 0x31: + return 0x00; + case 0x32: + return mach64->pci_regs[0x32]; + case 0x33: + return mach64->pci_regs[0x33]; + + case 0x3c: + return mach64->int_line; + case 0x3d: + return PCI_INTA; + + case 0x40: + return mach64->use_block_decoded_io | mach64->io_base; + + default: + break; + } + return 0; } -static void mach64_block_outb(uint16_t port, uint8_t val, void *p) +void +mach64_pci_write(UNUSED(int func), int addr, uint8_t val, void *priv) { - mach64_t *mach64 = (mach64_t *)p; - - mach64_log("mach64_block_outb : port %04X val %02X\n ", port, val); - mach64_ext_writeb(0x400 | (port & 0x3ff), val, mach64); -} -static void mach64_block_outw(uint16_t port, uint16_t val, void *p) -{ - mach64_t *mach64 = (mach64_t *)p; - - mach64_log("mach64_block_outw : port %04X val %04X\n ", port, val); - mach64_ext_writew(0x400 | (port & 0x3ff), val, mach64); -} -static void mach64_block_outl(uint16_t port, uint32_t val, void *p) -{ - mach64_t *mach64 = (mach64_t *)p; - - mach64_log("mach64_block_outl : port %04X val %08X\n ", port, val); - mach64_ext_writel(0x400 | (port & 0x3ff), val, mach64); -} + mach64_t *mach64 = (mach64_t *) priv; -void mach64_write(uint32_t addr, uint8_t val, void *p) -{ - mach64_t *mach64 = (mach64_t *)p; - svga_t *svga = &mach64->svga; - addr = (addr & 0x7fff) + mach64->bank_w[(addr >> 15) & 1]; - svga_write_linear(addr, val, svga); -} -void mach64_writew(uint32_t addr, uint16_t val, void *p) -{ - mach64_t *mach64 = (mach64_t *)p; - svga_t *svga = &mach64->svga; + switch (addr) { + case PCI_REG_COMMAND: + mach64->pci_regs[PCI_REG_COMMAND] = val & 0x27; + if (val & PCI_COMMAND_IO) + mach64_io_set(mach64); + else + mach64_io_remove(mach64); + mach64_updatemapping(mach64); + break; - addr = (addr & 0x7fff) + mach64->bank_w[(addr >> 15) & 1]; - svga_writew_linear(addr, val, svga); -} -void mach64_writel(uint32_t addr, uint32_t val, void *p) -{ - mach64_t *mach64 = (mach64_t *)p; - svga_t *svga = &mach64->svga; + case 0x12: + if (mach64->type == MACH64_VT2) + val = 0; + mach64->linear_base = (mach64->linear_base & 0xff000000) | ((val & 0x80) << 16); + mach64_updatemapping(mach64); + break; + case 0x13: + mach64->linear_base = (mach64->linear_base & 0x800000) | (val << 24); + mach64_updatemapping(mach64); + break; - addr = (addr & 0x7fff) + mach64->bank_w[(addr >> 15) & 1]; - svga_writel_linear(addr, val, svga); -} + case 0x15: + if (mach64->type == MACH64_VT2) { + if (mach64->pci_regs[PCI_REG_COMMAND] & PCI_COMMAND_IO) + mach64_io_remove(mach64); + mach64->block_decoded_io = (mach64->block_decoded_io & 0xffff0000) | ((val & 0xfc) << 8); + if (mach64->pci_regs[PCI_REG_COMMAND] & PCI_COMMAND_IO) + mach64_io_set(mach64); + } + break; + case 0x16: + if (mach64->type == MACH64_VT2) { + if (mach64->pci_regs[PCI_REG_COMMAND] & PCI_COMMAND_IO) + mach64_io_remove(mach64); + mach64->block_decoded_io = (mach64->block_decoded_io & 0xff00fc00) | (val << 16); + if (mach64->pci_regs[PCI_REG_COMMAND] & PCI_COMMAND_IO) + mach64_io_set(mach64); + } + break; + case 0x17: + if (mach64->type == MACH64_VT2) { + if (mach64->pci_regs[PCI_REG_COMMAND] & PCI_COMMAND_IO) + mach64_io_remove(mach64); + mach64->block_decoded_io = (mach64->block_decoded_io & 0x00fffc00) | (val << 24); + if (mach64->pci_regs[PCI_REG_COMMAND] & PCI_COMMAND_IO) + mach64_io_set(mach64); + } + break; -uint8_t mach64_read(uint32_t addr, void *p) -{ - mach64_t *mach64 = (mach64_t *)p; - svga_t *svga = &mach64->svga; - uint8_t ret; - addr = (addr & 0x7fff) + mach64->bank_r[(addr >> 15) & 1]; - ret = svga_read_linear(addr, svga); - return ret; -} -uint16_t mach64_readw(uint32_t addr, void *p) -{ - mach64_t *mach64 = (mach64_t *)p; - svga_t *svga = &mach64->svga; - - addr = (addr & 0x7fff) + mach64->bank_r[(addr >> 15) & 1]; - return svga_readw_linear(addr, svga); -} -uint32_t mach64_readl(uint32_t addr, void *p) -{ - mach64_t *mach64 = (mach64_t *)p; - svga_t *svga = &mach64->svga; - - addr = (addr & 0x7fff) + mach64->bank_r[(addr >> 15) & 1]; - return svga_readl_linear(addr, svga); -} - - -#define CLAMP(x) do \ - { \ - if ((x) & ~0xff) \ - x = ((x) < 0) ? 0 : 0xff; \ - } \ - while (0) - -#define DECODE_ARGB1555() \ - do \ - { \ - for (x = 0; x < mach64->svga.overlay_latch.xsize; x++) \ - { \ - uint16_t dat = ((uint16_t *)src)[x]; \ - \ - int b = dat & 0x1f; \ - int g = (dat >> 5) & 0x1f; \ - int r = (dat >> 10) & 0x1f; \ - \ - b = (b << 3) | (b >> 2); \ - g = (g << 3) | (g >> 2); \ - r = (r << 3) | (r >> 2); \ - \ - mach64->overlay_dat[x] = (r << 16) | (g << 8) | b; \ - } \ - } while (0) - -#define DECODE_RGB565() \ - do \ - { \ - for (x = 0; x < mach64->svga.overlay_latch.xsize; x++) \ - { \ - uint16_t dat = ((uint16_t *)src)[x]; \ - \ - int b = dat & 0x1f; \ - int g = (dat >> 5) & 0x3f; \ - int r = (dat >> 11) & 0x1f; \ - \ - b = (b << 3) | (b >> 2); \ - g = (g << 2) | (g >> 4); \ - r = (r << 3) | (r >> 2); \ - \ - mach64->overlay_dat[x] = (r << 16) | (g << 8) | b; \ - } \ - } while (0) - -#define DECODE_ARGB8888() \ - do \ - { \ - for (x = 0; x < mach64->svga.overlay_latch.xsize; x++) \ - { \ - int b = src[0]; \ - int g = src[1]; \ - int r = src[2]; \ - src += 4; \ - \ - mach64->overlay_dat[x] = (r << 16) | (g << 8) | b; \ - } \ - } while (0) - -#define DECODE_VYUY422() \ - do \ - { \ - for (x = 0; x < mach64->svga.overlay_latch.xsize; x += 2) \ - { \ - uint8_t y1, y2; \ - int8_t u, v; \ - int dR, dG, dB; \ - int r, g, b; \ - \ - y1 = src[0]; \ - u = src[1] - 0x80; \ - y2 = src[2]; \ - v = src[3] - 0x80; \ - src += 4; \ - \ - dR = (359*v) >> 8; \ - dG = (88*u + 183*v) >> 8; \ - dB = (453*u) >> 8; \ - \ - r = y1 + dR; \ - CLAMP(r); \ - g = y1 - dG; \ - CLAMP(g); \ - b = y1 + dB; \ - CLAMP(b); \ - mach64->overlay_dat[x] = (r << 16) | (g << 8) | b; \ - \ - r = y2 + dR; \ - CLAMP(r); \ - g = y2 - dG; \ - CLAMP(g); \ - b = y2 + dB; \ - CLAMP(b); \ - mach64->overlay_dat[x+1] = (r << 16) | (g << 8) | b; \ - } \ - } while (0) - -#define DECODE_YVYU422() \ - do \ - { \ - for (x = 0; x < mach64->svga.overlay_latch.xsize; x += 2) \ - { \ - uint8_t y1, y2; \ - int8_t u, v; \ - int dR, dG, dB; \ - int r, g, b; \ - \ - u = src[0] - 0x80; \ - y1 = src[1]; \ - v = src[2] - 0x80; \ - y2 = src[3]; \ - src += 4; \ - \ - dR = (359*v) >> 8; \ - dG = (88*u + 183*v) >> 8; \ - dB = (453*u) >> 8; \ - \ - r = y1 + dR; \ - CLAMP(r); \ - g = y1 - dG; \ - CLAMP(g); \ - b = y1 + dB; \ - CLAMP(b); \ - mach64->overlay_dat[x] = (r << 16) | (g << 8) | b; \ - \ - r = y2 + dR; \ - CLAMP(r); \ - g = y2 - dG; \ - CLAMP(g); \ - b = y2 + dB; \ - CLAMP(b); \ - mach64->overlay_dat[x+1] = (r << 16) | (g << 8) | b; \ - } \ - } while (0) - -void mach64_overlay_draw(svga_t *svga, int displine) -{ - mach64_t *mach64 = (mach64_t *)svga->p; - int x; - int h_acc = 0; - int h_max = (mach64->scaler_height_width >> 16) & 0x3ff; - int h_inc = mach64->overlay_scale_inc >> 16; - int v_max = mach64->scaler_height_width & 0x3ff; - int v_inc = mach64->overlay_scale_inc & 0xffff; - uint32_t *p; - uint8_t *src = &svga->vram[svga->overlay.addr]; - int old_y = mach64->overlay_v_acc; - int y_diff; - int video_key_fn = mach64->overlay_key_cntl & 5; - int graphics_key_fn = (mach64->overlay_key_cntl >> 4) & 5; - int overlay_cmp_mix = (mach64->overlay_key_cntl >> 8) & 0xf; - - p = &buffer32->line[displine][svga->x_add + mach64->svga.overlay_latch.x]; - - if (mach64->scaler_update) - { - switch (mach64->scaler_format) - { - case 0x3: - DECODE_ARGB1555(); - break; - case 0x4: - DECODE_RGB565(); - break; - case 0x6: - DECODE_ARGB8888(); - break; - case 0xb: - DECODE_VYUY422(); - break; - case 0xc: - DECODE_YVYU422(); - break; - - default: - mach64_log("Unknown Mach64 scaler format %x\n", mach64->scaler_format); - /*Fill buffer with something recognisably wrong*/ - for (x = 0; x < mach64->svga.overlay_latch.xsize; x++) - mach64->overlay_dat[x] = 0xff00ff; - break; - } - } - - if (overlay_cmp_mix == 2) - { - for (x = 0; x < mach64->svga.overlay_latch.xsize; x++) - { - int h = h_acc >> 12; - - p[x] = mach64->overlay_dat[h]; - - h_acc += h_inc; - if (h_acc > (h_max << 12)) - h_acc = (h_max << 12); - } - } - else - { - for (x = 0; x < mach64->svga.overlay_latch.xsize; x++) - { - int h = h_acc >> 12; - int gr_cmp = 0, vid_cmp = 0; - int use_video = 0; - - switch (video_key_fn) - { - case 0: vid_cmp = 0; break; - case 1: vid_cmp = 1; break; - case 4: vid_cmp = ((mach64->overlay_dat[h] ^ mach64->overlay_video_key_clr) & mach64->overlay_video_key_msk); break; - case 5: vid_cmp = !((mach64->overlay_dat[h] ^ mach64->overlay_video_key_clr) & mach64->overlay_video_key_msk); break; - } - switch (graphics_key_fn) - { - case 0: gr_cmp = 0; break; - case 1: gr_cmp = 1; break; - case 4: gr_cmp = (((p[x]) ^ mach64->overlay_graphics_key_clr) & mach64->overlay_graphics_key_msk & 0xffffff); break; - case 5: gr_cmp = !(((p[x]) ^ mach64->overlay_graphics_key_clr) & mach64->overlay_graphics_key_msk & 0xffffff); break; - } - vid_cmp = vid_cmp ? -1 : 0; - gr_cmp = gr_cmp ? -1 : 0; - - switch (overlay_cmp_mix) - { - case 0x0: use_video = gr_cmp; break; - case 0x1: use_video = 0; break; - case 0x2: use_video = ~0; break; - case 0x3: use_video = ~gr_cmp; break; - case 0x4: use_video = ~vid_cmp; break; - case 0x5: use_video = gr_cmp ^ vid_cmp; break; - case 0x6: use_video = ~gr_cmp ^ vid_cmp; break; - case 0x7: use_video = vid_cmp; break; - case 0x8: use_video = ~gr_cmp | ~vid_cmp; break; - case 0x9: use_video = gr_cmp | ~vid_cmp; break; - case 0xa: use_video = ~gr_cmp | vid_cmp; break; - case 0xb: use_video = gr_cmp | vid_cmp; break; - case 0xc: use_video = gr_cmp & vid_cmp; break; - case 0xd: use_video = ~gr_cmp & vid_cmp; break; - case 0xe: use_video = gr_cmp & ~vid_cmp; break; - case 0xf: use_video = ~gr_cmp & ~vid_cmp; break; - } - - if (use_video) - p[x] = mach64->overlay_dat[h]; - - h_acc += h_inc; - if (h_acc > (h_max << 12)) - h_acc = (h_max << 12); - } - } - - mach64->overlay_v_acc += v_inc; - if (mach64->overlay_v_acc > (v_max << 12)) - mach64->overlay_v_acc = v_max << 12; - - y_diff = (mach64->overlay_v_acc >> 12) - (old_y >> 12); - - if (mach64->scaler_format == 6) - svga->overlay.addr += svga->overlay.pitch*4*y_diff; - else - svga->overlay.addr += svga->overlay.pitch*2*y_diff; - - mach64->scaler_update = y_diff; -} - -static void mach64_io_remove(mach64_t *mach64) -{ - int c; - uint16_t io_base = 0x02ec; - - switch (mach64->io_base) - { - case 0: - default: - io_base = 0x02ec; - break; - case 1: - io_base = 0x01cc; - break; - case 2: - io_base = 0x01c8; - break; - case 3: - fatal("Attempting to use the reserved value for I/O Base\n"); - return; - } - - io_removehandler(0x03c0, 0x0020, mach64_in, NULL, NULL, mach64_out, NULL, NULL, mach64); - - for (c = 0; c < 8; c++) - { - io_removehandler((c * 0x1000) + 0x0000 + io_base, 0x0004, mach64_ext_inb, mach64_ext_inw, mach64_ext_inl, mach64_ext_outb, mach64_ext_outw, mach64_ext_outl, mach64); - io_removehandler((c * 0x1000) + 0x0400 + io_base, 0x0004, mach64_ext_inb, mach64_ext_inw, mach64_ext_inl, mach64_ext_outb, mach64_ext_outw, mach64_ext_outl, mach64); - io_removehandler((c * 0x1000) + 0x0800 + io_base, 0x0004, mach64_ext_inb, mach64_ext_inw, mach64_ext_inl, mach64_ext_outb, mach64_ext_outw, mach64_ext_outl, mach64); - io_removehandler((c * 0x1000) + 0x0c00 + io_base, 0x0004, mach64_ext_inb, mach64_ext_inw, mach64_ext_inl, mach64_ext_outb, mach64_ext_outw, mach64_ext_outl, mach64); - } - - io_removehandler(0x01ce, 0x0002, mach64_in, NULL, NULL, mach64_out, NULL, NULL, mach64); - - if (mach64->block_decoded_io && mach64->block_decoded_io < 0x10000) - io_removehandler(mach64->block_decoded_io, 0x0400, mach64_block_inb, mach64_block_inw, mach64_block_inl, mach64_block_outb, mach64_block_outw, mach64_block_outl, mach64); -} - -static void mach64_io_set(mach64_t *mach64) -{ - int c; - - mach64_io_remove(mach64); - - io_sethandler(0x03c0, 0x0020, mach64_in, NULL, NULL, mach64_out, NULL, NULL, mach64); - - if (!mach64->use_block_decoded_io) - { - for (c = 0; c < 8; c++) - { - io_sethandler((c * 0x1000) + 0x2ec, 0x0004, mach64_ext_inb, mach64_ext_inw, mach64_ext_inl, mach64_ext_outb, mach64_ext_outw, mach64_ext_outl, mach64); - io_sethandler((c * 0x1000) + 0x6ec, 0x0004, mach64_ext_inb, mach64_ext_inw, mach64_ext_inl, mach64_ext_outb, mach64_ext_outw, mach64_ext_outl, mach64); - io_sethandler((c * 0x1000) + 0xaec, 0x0004, mach64_ext_inb, mach64_ext_inw, mach64_ext_inl, mach64_ext_outb, mach64_ext_outw, mach64_ext_outl, mach64); - io_sethandler((c * 0x1000) + 0xeec, 0x0004, mach64_ext_inb, mach64_ext_inw, mach64_ext_inl, mach64_ext_outb, mach64_ext_outw, mach64_ext_outl, mach64); - } - } - - io_sethandler(0x01ce, 0x0002, mach64_in, NULL, NULL, mach64_out, NULL, NULL, mach64); - - if (mach64->use_block_decoded_io && mach64->block_decoded_io && mach64->block_decoded_io < 0x10000) - io_sethandler(mach64->block_decoded_io, 0x0400, mach64_block_inb, mach64_block_inw, mach64_block_inl, mach64_block_outb, mach64_block_outw, mach64_block_outl, mach64); -} - -uint8_t mach64_pci_read(int func, int addr, void *p) -{ - mach64_t *mach64 = (mach64_t *)p; - - switch (addr) - { - case 0x00: return 0x02; /*ATi*/ - case 0x01: return 0x10; - - case 0x02: return mach64->pci_id & 0xff; - case 0x03: return mach64->pci_id >> 8; - - case PCI_REG_COMMAND: - return mach64->pci_regs[PCI_REG_COMMAND]; /*Respond to IO and memory accesses*/ - - case 0x07: return 1 << 1; /*Medium DEVSEL timing*/ - - case 0x08: /*Revision ID*/ - if (mach64->type == MACH64_GX) - return 0; - return 0x40; - - case 0x09: return 0; /*Programming interface*/ - - case 0x0a: return 0x01; /*Supports VGA interface, XGA compatible*/ - case 0x0b: return 0x03; - - case 0x10: return 0x00; /*Linear frame buffer address*/ - case 0x11: return 0x00; - case 0x12: return mach64->linear_base >> 16; - case 0x13: return mach64->linear_base >> 24; - - case 0x14: - if (mach64->type == MACH64_VT2) - return 0x01; /*Block decoded IO address*/ - return 0x00; - case 0x15: - if (mach64->type == MACH64_VT2) - return mach64->block_decoded_io >> 8; - return 0x00; - case 0x16: - if (mach64->type == MACH64_VT2) - return mach64->block_decoded_io >> 16; - return 0x00; - case 0x17: - if (mach64->type == MACH64_VT2) - return mach64->block_decoded_io >> 24; - return 0x00; - - case 0x30: return mach64->pci_regs[0x30] & 0x01; /*BIOS ROM address*/ - case 0x31: return 0x00; - case 0x32: return mach64->pci_regs[0x32]; - case 0x33: return mach64->pci_regs[0x33]; - - case 0x3c: return mach64->int_line; - case 0x3d: return PCI_INTA; - - case 0x40: return mach64->use_block_decoded_io | mach64->io_base; - } - return 0; -} - -void mach64_pci_write(int func, int addr, uint8_t val, void *p) -{ - mach64_t *mach64 = (mach64_t *)p; - - switch (addr) - { - case PCI_REG_COMMAND: - mach64->pci_regs[PCI_REG_COMMAND] = val & 0x27; - if (val & PCI_COMMAND_IO) - mach64_io_set(mach64); - else - mach64_io_remove(mach64); - mach64_updatemapping(mach64); - break; - - case 0x12: - if (mach64->type == MACH64_VT2) - val = 0; - mach64->linear_base = (mach64->linear_base & 0xff000000) | ((val & 0x80) << 16); - mach64_updatemapping(mach64); - break; - case 0x13: - mach64->linear_base = (mach64->linear_base & 0x800000) | (val << 24); - mach64_updatemapping(mach64); - break; - - case 0x15: - if (mach64->type == MACH64_VT2) - { - if (mach64->pci_regs[PCI_REG_COMMAND] & PCI_COMMAND_IO) - mach64_io_remove(mach64); - mach64->block_decoded_io = (mach64->block_decoded_io & 0xffff0000) | ((val & 0xfc) << 8); - if (mach64->pci_regs[PCI_REG_COMMAND] & PCI_COMMAND_IO) - mach64_io_set(mach64); - } - break; - case 0x16: - if (mach64->type == MACH64_VT2) - { - if (mach64->pci_regs[PCI_REG_COMMAND] & PCI_COMMAND_IO) - mach64_io_remove(mach64); - mach64->block_decoded_io = (mach64->block_decoded_io & 0xff00fc00) | (val << 16); - if (mach64->pci_regs[PCI_REG_COMMAND] & PCI_COMMAND_IO) - mach64_io_set(mach64); - } - break; - case 0x17: - if (mach64->type == MACH64_VT2) - { - if (mach64->pci_regs[PCI_REG_COMMAND] & PCI_COMMAND_IO) - mach64_io_remove(mach64); - mach64->block_decoded_io = (mach64->block_decoded_io & 0x00fffc00) | (val << 24); - if (mach64->pci_regs[PCI_REG_COMMAND] & PCI_COMMAND_IO) - mach64_io_set(mach64); - } - break; - - case 0x30: case 0x32: case 0x33: - mach64->pci_regs[addr] = val; - if (mach64->pci_regs[0x30] & 0x01) - { - uint32_t addr = (mach64->pci_regs[0x32] << 16) | (mach64->pci_regs[0x33] << 24); - mach64_log("Mach64 bios_rom enabled at %08x\n", addr); - mem_mapping_set_addr(&mach64->bios_rom.mapping, addr, 0x8000); - } - else - { - mach64_log("Mach64 bios_rom disabled\n"); - mem_mapping_disable(&mach64->bios_rom.mapping); - } - return; - - case 0x3c: - mach64->int_line = val; - break; - - case 0x40: - if (mach64->pci_regs[PCI_REG_COMMAND] & PCI_COMMAND_IO) - mach64_io_remove(mach64); - mach64->io_base = val & 0x03; - if (mach64->type == MACH64_VT2) - mach64->use_block_decoded_io = val & 0x04; - if (mach64->pci_regs[PCI_REG_COMMAND] & PCI_COMMAND_IO) - mach64_io_set(mach64); - break; - } -} - -static void *mach64_common_init(const device_t *info) -{ - mach64_t *mach64 = malloc(sizeof(mach64_t)); - memset(mach64, 0, sizeof(mach64_t)); - - mach64->vram_size = device_get_config_int("memory"); - mach64->vram_mask = (mach64->vram_size << 20) - 1; - - svga_init(info, &mach64->svga, mach64, mach64->vram_size << 20, - mach64_recalctimings, - mach64_in, mach64_out, - NULL, - mach64_overlay_draw); - mach64->svga.dac_hwcursor.ysize = 64; - - if (info->flags & DEVICE_PCI) + case 0x30: + case 0x32: + case 0x33: + mach64->pci_regs[addr] = val; + if (mach64->pci_regs[0x30] & 0x01) { + uint32_t addr = (mach64->pci_regs[0x32] << 16) | (mach64->pci_regs[0x33] << 24); + mach64_log("Mach64 bios_rom enabled at %08x\n", addr); + mem_mapping_set_addr(&mach64->bios_rom.mapping, addr, 0x8000); + } else { + mach64_log("Mach64 bios_rom disabled\n"); mem_mapping_disable(&mach64->bios_rom.mapping); + } + return; - mem_mapping_add(&mach64->linear_mapping, 0, 0, svga_read_linear, svga_readw_linear, svga_readl_linear, svga_write_linear, svga_writew_linear, svga_writel_linear, NULL, MEM_MAPPING_EXTERNAL, &mach64->svga); - mem_mapping_add(&mach64->mmio_linear_mapping, 0, 0, mach64_ext_readb, mach64_ext_readw, mach64_ext_readl, mach64_ext_writeb, mach64_ext_writew, mach64_ext_writel, NULL, MEM_MAPPING_EXTERNAL, mach64); - mem_mapping_add(&mach64->mmio_linear_mapping_2, 0, 0, mach64_ext_readb, mach64_ext_readw, mach64_ext_readl, mach64_ext_writeb, mach64_ext_writew, mach64_ext_writel, NULL, MEM_MAPPING_EXTERNAL, mach64); - mem_mapping_add(&mach64->mmio_mapping, 0xbc000, 0x04000, mach64_ext_readb, mach64_ext_readw, mach64_ext_readl, mach64_ext_writeb, mach64_ext_writew, mach64_ext_writel, NULL, MEM_MAPPING_EXTERNAL, mach64); - mem_mapping_disable(&mach64->mmio_mapping); + case 0x3c: + mach64->int_line = val; + break; - mach64_io_set(mach64); + case 0x40: + if (mach64->pci_regs[PCI_REG_COMMAND] & PCI_COMMAND_IO) + mach64_io_remove(mach64); + mach64->io_base = val & 0x03; + if (mach64->type == MACH64_VT2) + mach64->use_block_decoded_io = val & 0x04; + if (mach64->pci_regs[PCI_REG_COMMAND] & PCI_COMMAND_IO) + mach64_io_set(mach64); + break; - 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; - mach64->pci_regs[0x32] = 0x0c; - mach64->pci_regs[0x33] = 0x00; - - mach64->svga.ramdac = device_add(&ati68860_ramdac_device); - mach64->svga.dac_hwcursor_draw = ati68860_hwcursor_draw; - - mach64->svga.clock_gen = device_add(&ics2595_device); - - mach64->dst_cntl = 3; - - mach64->i2c = i2c_gpio_init("ddc_ati_mach64"); - mach64->ddc = ddc_init(i2c_gpio_get_bus(mach64->i2c)); - - return mach64; + default: + break; + } } -static void *mach64gx_init(const device_t *info) +static void * +mach64_common_init(const device_t *info) { - mach64_t *mach64 = mach64_common_init(info); + svga_t *svga; + mach64_t *mach64 = malloc(sizeof(mach64_t)); + memset(mach64, 0, sizeof(mach64_t)); - if (info->flags & DEVICE_ISA) - video_inform(VIDEO_FLAG_TYPE_SPECIAL, &timing_mach64_isa); - else if (info->flags & DEVICE_PCI) - video_inform(VIDEO_FLAG_TYPE_SPECIAL, &timing_mach64_pci); - else - video_inform(VIDEO_FLAG_TYPE_SPECIAL, &timing_mach64_vlb); + svga = &mach64->svga; - mach64->type = MACH64_GX; - mach64->pci = !!(info->flags & DEVICE_PCI); - mach64->pci_id = (int)'X' | ((int)'G' << 8); - mach64->config_chip_id = 0x020000d7; - mach64->dac_cntl = 5 << 16; /*ATI 68860 RAMDAC*/ - mach64->config_stat0 = (5 << 9) | (3 << 3); /*ATI-68860, 256Kx16 DRAM*/ - if (info->flags & DEVICE_PCI) - mach64->config_stat0 |= 0; /*PCI, 256Kx16 DRAM*/ - else if (info->flags & DEVICE_VLB) - mach64->config_stat0 |= 1; /*VLB, 256Kx16 DRAM*/ - else if (info->flags & DEVICE_ISA) - mach64->config_stat0 |= 7; /*ISA 16-bit, 256k16 DRAM*/ + mach64->vram_size = device_get_config_int("memory"); + mach64->vram_mask = (mach64->vram_size << 20) - 1; - ati_eeprom_load(&mach64->eeprom, "mach64.nvr", 1); + svga_init(info, svga, mach64, mach64->vram_size << 20, + mach64_recalctimings, + mach64_in, mach64_out, + NULL, + mach64_overlay_draw); + svga->dac_hwcursor.cur_ysize = 64; - if (info->flags & DEVICE_PCI) - rom_init(&mach64->bios_rom, BIOS_ROM_PATH, 0xc0000, 0x8000, 0x7fff, 0, MEM_MAPPING_EXTERNAL); - else if (info->flags & DEVICE_VLB) - rom_init(&mach64->bios_rom, BIOS_VLB_ROM_PATH, 0xc0000, 0x8000, 0x7fff, 0, MEM_MAPPING_EXTERNAL); - else if (info->flags & DEVICE_ISA) - rom_init(&mach64->bios_rom, BIOS_ISA_ROM_PATH, 0xc0000, 0x8000, 0x7fff, 0, MEM_MAPPING_EXTERNAL); - - return mach64; -} -static void *mach64vt2_init(const device_t *info) -{ - mach64_t *mach64 = mach64_common_init(info); - svga_t *svga = &mach64->svga; + mem_mapping_add(&mach64->linear_mapping, 0, 0, svga_read_linear, svga_readw_linear, svga_readl_linear, svga_write_linear, svga_writew_linear, svga_writel_linear, NULL, MEM_MAPPING_EXTERNAL, svga); + mem_mapping_add(&mach64->mmio_linear_mapping, 0, 0, mach64_ext_readb, mach64_ext_readw, mach64_ext_readl, mach64_ext_writeb, mach64_ext_writew, mach64_ext_writel, NULL, MEM_MAPPING_EXTERNAL, mach64); + mem_mapping_add(&mach64->mmio_linear_mapping_2, 0, 0, mach64_ext_readb, mach64_ext_readw, mach64_ext_readl, mach64_ext_writeb, mach64_ext_writew, mach64_ext_writel, NULL, MEM_MAPPING_EXTERNAL, mach64); + mem_mapping_add(&mach64->mmio_mapping, 0xbc000, 0x04000, mach64_ext_readb, mach64_ext_readw, mach64_ext_readl, mach64_ext_writeb, mach64_ext_writew, mach64_ext_writel, NULL, MEM_MAPPING_EXTERNAL, mach64); + mem_mapping_disable(&mach64->mmio_mapping); - if (info->flags & DEVICE_PCI) - video_inform(VIDEO_FLAG_TYPE_SPECIAL, &timing_mach64_pci); - else - video_inform(VIDEO_FLAG_TYPE_SPECIAL, &timing_mach64_vlb); + mach64_io_set(mach64); - mach64->type = MACH64_VT2; - mach64->pci = 1; - mach64->pci_id = 0x5654; - mach64->config_chip_id = 0x40005654; - mach64->dac_cntl = 1 << 16; /*Internal 24-bit DAC*/ - mach64->config_stat0 = 4; - mach64->use_block_decoded_io = 4; - - ati_eeprom_load(&mach64->eeprom, "mach64vt.nvr", 1); + if (info->flags & DEVICE_PCI) + pci_add_card(PCI_ADD_NORMAL, mach64_pci_read, mach64_pci_write, mach64, &mach64->pci_slot); - rom_init(&mach64->bios_rom, BIOS_ROMVT2_PATH, 0xc0000, 0x8000, 0x7fff, 0, MEM_MAPPING_EXTERNAL); - - svga->vblank_start = mach64_vblank_start; - - return mach64; + mach64->pci_regs[PCI_REG_COMMAND] = 3; + mach64->pci_regs[0x30] = 0x00; + mach64->pci_regs[0x32] = 0x0c; + mach64->pci_regs[0x33] = 0x00; + + svga->ramdac = device_add(&ati68860_ramdac_device); + svga->dac_hwcursor_draw = ati68860_hwcursor_draw; + + svga->clock_gen = device_add(&ics2595_device); + + mach64->dst_cntl = 3; + + mach64->i2c = i2c_gpio_init("ddc_ati_mach64"); + mach64->ddc = ddc_init(i2c_gpio_get_bus(mach64->i2c)); + + return mach64; } -int mach64gx_available(void) +static void * +mach64gx_init(const device_t *info) { - return rom_present(BIOS_ROM_PATH); + mach64_t *mach64 = mach64_common_init(info); + + if (info->flags & DEVICE_ISA) + video_inform(VIDEO_FLAG_TYPE_SPECIAL, &timing_mach64_isa); + else if (info->flags & DEVICE_PCI) + video_inform(VIDEO_FLAG_TYPE_SPECIAL, &timing_mach64_pci); + else + video_inform(VIDEO_FLAG_TYPE_SPECIAL, &timing_mach64_vlb); + + mach64->type = MACH64_GX; + mach64->pci = !!(info->flags & DEVICE_PCI); + mach64->pci_id = 'X' | ('G' << 8); + 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) + mach64->config_stat0 |= 0; /*PCI, 256Kx16 DRAM*/ + else if (info->flags & DEVICE_VLB) + mach64->config_stat0 |= 1; /*VLB, 256Kx16 DRAM*/ + else if (info->flags & DEVICE_ISA) + mach64->config_stat0 |= 7; /*ISA 16-bit, 256k16 DRAM*/ + + ati_eeprom_load(&mach64->eeprom, "mach64.nvr", 1); + + if (info->flags & DEVICE_PCI) + rom_init(&mach64->bios_rom, BIOS_ROM_PATH, 0xc0000, 0x8000, 0x7fff, 0, MEM_MAPPING_EXTERNAL); + else if (info->flags & DEVICE_VLB) + rom_init(&mach64->bios_rom, BIOS_VLB_ROM_PATH, 0xc0000, 0x8000, 0x7fff, 0, MEM_MAPPING_EXTERNAL); + else if (info->flags & DEVICE_ISA) + rom_init(&mach64->bios_rom, BIOS_ISA_ROM_PATH, 0xc0000, 0x8000, 0x7fff, 0, MEM_MAPPING_EXTERNAL); + + if (info->flags & DEVICE_PCI) + mem_mapping_disable(&mach64->bios_rom.mapping); + + return mach64; } -int mach64gx_isa_available(void) +static void * +mach64vt2_init(const device_t *info) { - return rom_present(BIOS_ISA_ROM_PATH); -} -int mach64gx_vlb_available(void) -{ - return rom_present(BIOS_VLB_ROM_PATH); -} -int mach64vt2_available(void) -{ - return rom_present(BIOS_ROMVT2_PATH); + mach64_t *mach64 = mach64_common_init(info); + svga_t *svga = &mach64->svga; + + video_inform(VIDEO_FLAG_TYPE_SPECIAL, &timing_mach64_pci); + + mach64->type = MACH64_VT2; + mach64->pci = 1; + mach64->pci_id = 0x5654; + mach64->config_chip_id = 0x40005654; + mach64->dac_cntl = 1 << 16; /*Internal 24-bit DAC*/ + mach64->config_stat0 = 4; + mach64->use_block_decoded_io = 4; + + ati_eeprom_load(&mach64->eeprom, "mach64vt.nvr", 1); + + rom_init(&mach64->bios_rom, BIOS_ROMVT2_PATH, 0xc0000, 0x8000, 0x7fff, 0, MEM_MAPPING_EXTERNAL); + + mem_mapping_disable(&mach64->bios_rom.mapping); + + svga->vblank_start = mach64_vblank_start; + + return mach64; } -void mach64_close(void *p) +int +mach64gx_available(void) { - mach64_t *mach64 = (mach64_t *)p; - - svga_close(&mach64->svga); - - ddc_close(mach64->ddc); - i2c_gpio_close(mach64->i2c); - - free(mach64); + return rom_present(BIOS_ROM_PATH); +} +int +mach64gx_isa_available(void) +{ + return rom_present(BIOS_ISA_ROM_PATH); +} +int +mach64gx_vlb_available(void) +{ + return rom_present(BIOS_VLB_ROM_PATH); +} +int +mach64vt2_available(void) +{ + return rom_present(BIOS_ROMVT2_PATH); } -void mach64_speed_changed(void *p) +void +mach64_close(void *priv) { - mach64_t *mach64 = (mach64_t *)p; - - svga_recalctimings(&mach64->svga); + mach64_t *mach64 = (mach64_t *) priv; + + svga_close(&mach64->svga); + + ddc_close(mach64->ddc); + i2c_gpio_close(mach64->i2c); + + free(mach64); } -void mach64_force_redraw(void *p) +void +mach64_speed_changed(void *priv) { - mach64_t *mach64 = (mach64_t *)p; + mach64_t *mach64 = (mach64_t *) priv; - mach64->svga.fullchange = changeframecount; + svga_recalctimings(&mach64->svga); } -static const device_config_t mach64gx_config[] = +void +mach64_force_redraw(void *priv) { - { - "memory", "Memory size", CONFIG_SELECTION, "", 4, "", { 0 }, - { - { - "1 MB", 1 - }, - { - "2 MB", 2 - }, - { - "4 MB", 4 - }, - { - "" - } - } - }, - { - "", "", -1 + mach64_t *mach64 = (mach64_t *) priv; + + mach64->svga.fullchange = mach64->svga.monitor->mon_changeframecount; +} + +// clang-format off +static const device_config_t mach64gx_config[] = { + { + .name = "memory", + .description = "Memory size", + .type = CONFIG_SELECTION, + .default_int = 4, + .selection = { + { + .description = "1 MB", + .value = 1 + }, + { + .description = "2 MB", + .value = 2 + }, + { + .description = "4 MB", + .value = 4 + }, + { + .description = "" + } } + }, + { + .type = CONFIG_END + } }; -static const device_config_t mach64vt2_config[] = -{ - { - "memory", "Memory size", CONFIG_SELECTION, "", 4, "", { 0 }, - { - { - "2 MB", 2 - }, - { - "4 MB", 4 - }, - { - "" - } - } - }, - { - "", "", -1 +static const device_config_t mach64vt2_config[] = { + { + .name = "memory", + .description = "Memory size", + .type = CONFIG_SELECTION, + .default_int = 4, + .selection = { + { + .description = "2 MB", + .value = 2 + }, + { + .description = "4 MB", + .value = 4 + }, + { + .description = "" + } } + }, + { + .type = CONFIG_END + } +}; +// clang-format on + +const device_t mach64gx_isa_device = { + .name = "ATI Mach64GX ISA", + .internal_name = "mach64gx_isa", + .flags = DEVICE_AT | DEVICE_ISA, + .local = 0, + .init = mach64gx_init, + .close = mach64_close, + .reset = NULL, + { .available = mach64gx_isa_available }, + .speed_changed = mach64_speed_changed, + .force_redraw = mach64_force_redraw, + .config = mach64gx_config }; -const device_t mach64gx_isa_device = -{ - "ATI Mach64GX ISA", - "mach64gx_isa", - DEVICE_AT | DEVICE_ISA, - 0, - mach64gx_init, mach64_close, NULL, - { mach64gx_isa_available }, - mach64_speed_changed, - mach64_force_redraw, - mach64gx_config +const device_t mach64gx_vlb_device = { + .name = "ATI Mach64GX VLB", + .internal_name = "mach64gx_vlb", + .flags = DEVICE_VLB, + .local = 0, + .init = mach64gx_init, + .close = mach64_close, + .reset = NULL, + { .available = mach64gx_vlb_available }, + .speed_changed = mach64_speed_changed, + .force_redraw = mach64_force_redraw, + .config = mach64gx_config }; -const device_t mach64gx_vlb_device = -{ - "ATI Mach64GX VLB", - "mach64gx_vlb", - DEVICE_VLB, - 0, - mach64gx_init, mach64_close, NULL, - { mach64gx_vlb_available }, - mach64_speed_changed, - mach64_force_redraw, - mach64gx_config +const device_t mach64gx_pci_device = { + .name = "ATI Mach64GX PCI", + .internal_name = "mach64gx_pci", + .flags = DEVICE_PCI, + .local = 0, + .init = mach64gx_init, + .close = mach64_close, + .reset = NULL, + { .available = mach64gx_available }, + .speed_changed = mach64_speed_changed, + .force_redraw = mach64_force_redraw, + .config = mach64gx_config }; -const device_t mach64gx_pci_device = -{ - "ATI Mach64GX PCI", - "mach64gx_pci", - DEVICE_PCI, - 0, - mach64gx_init, mach64_close, NULL, - { mach64gx_available }, - mach64_speed_changed, - mach64_force_redraw, - mach64gx_config -}; - -const device_t mach64vt2_device = -{ - "ATI Mach64VT2", - "mach64vt2", - DEVICE_PCI, - 0, - mach64vt2_init, mach64_close, NULL, - { mach64vt2_available }, - mach64_speed_changed, - mach64_force_redraw, - mach64vt2_config +const device_t mach64vt2_device = { + .name = "ATI Mach64VT2", + .internal_name = "mach64vt2", + .flags = DEVICE_PCI, + .local = 0, + .init = mach64vt2_init, + .close = mach64_close, + .reset = NULL, + { .available = mach64vt2_available }, + .speed_changed = mach64_speed_changed, + .force_redraw = mach64_force_redraw, + .config = mach64vt2_config }; diff --git a/src/video/vid_ati_mach8.c b/src/video/vid_ati_mach8.c new file mode 100644 index 000000000..8e7174666 --- /dev/null +++ b/src/video/vid_ati_mach8.c @@ -0,0 +1,6009 @@ +/* + * 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_8514a.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/ATi Mach32 Graphics Pro ISA.BIN" +#define BIOS_MACH32_VLB_ROM_PATH "roms/video/mach32/MACH32VLB.VBI" +#define BIOS_MACH32_MCA_ROM_PATH "roms/video/mach32/MACH32MCA_Olivetti.BIN" +#define BIOS_MACH32_PCI_ROM_PATH "roms/video/mach32/intelopt_00000.rom" + +typedef struct mach_t { + ati_eeprom_t eeprom; + svga_t svga; + + rom_t bios_rom; + rom_t bios_rom2; + mem_mapping_t mmio_linear_mapping; + + int mca_bus; + int pci_bus; + int vlb_bus; + int has_bios; + + uint8_t regs[256]; + uint8_t pci_regs[256]; + uint8_t int_line; + uint8_t pci_slot; + uint8_t irq_state; + + int index; + int ramdac_type; + int old_mode; + + uint32_t memory; + + uint16_t config1; + uint16_t config2; + + uint8_t pos_regs[8]; + uint8_t pci_cntl_reg; + uint8_t cursor_col_0; + uint8_t cursor_col_1; + uint8_t ext_cur_col_0_r; + uint8_t ext_cur_col_1_r; + uint8_t ext_cur_col_0_g; + uint8_t ext_cur_col_1_g; + uint16_t cursor_col_0_rg; + uint16_t cursor_col_1_rg; + uint16_t cursor_col_b; + uint16_t cursor_offset_lo; + uint16_t cursor_offset_hi; + uint16_t cursor_offset_hi_reg; + uint16_t cursor_vh_offset; + uint16_t cursor_x; + uint16_t 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; + uint8_t bank_r; + uint16_t shadow_set; + int ext_on; + int ati_mode; + + 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; + uint16_t src_y; + int16_t bres_count; + uint16_t clock_sel; + uint16_t crt_pitch; + uint16_t ge_pitch; + 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]; + uint8_t test3[2]; + int src_y_dir; + int cmd_type; + int block_write_mono_pattern_enable; + int mono_pattern_enable; + int16_t cx_end_line; + int16_t cy_end_line; + int16_t cx; + int16_t cx_end; + int16_t cy_end; + int16_t dx; + int16_t dx_end; + int16_t dy_end; + int16_t dx_start; + int16_t dy_start; + int16_t cy; + int16_t sx_start; + int16_t sx_end; + int16_t sx; + int16_t x_count; + int16_t xx_count; + int16_t xxx_count; + int16_t sy; + int16_t y_count; + int16_t err; + int16_t width; + int16_t src_width; + int16_t height; + int poly_src; + int temp_cnt; + int stepx; + int stepy; + int 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; +} 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_mca = { .type = VIDEO_MCA, .write_b = 4, .write_w = 5, .write_l = 10, .read_b = 5, .read_w = 5, .read_l = 10 }; +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 *priv); +static void mach_accel_outw(uint16_t port, uint16_t val, void *priv); +static uint8_t mach_accel_inb(uint16_t port, void *priv); +static uint16_t mach_accel_inw(uint16_t port, void *priv); +static uint8_t mach_in(uint16_t addr, void *priv); + +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 WRITE8(addr, var, val) \ + switch ((addr) & 1) { \ + case 0: \ + var = (var & 0xff00) | (val); \ + break; \ + case 1: \ + var = (var & 0x00ff) | ((val) << 8); \ + break; \ + } + +#define READ8(addr, var) \ + switch ((addr) & 1) { \ + case 0: \ + temp = (var) & 0xff; \ + break; \ + case 1: \ + temp = ((var) >> 8) & 0xff; \ + break; \ + } + +#define READ_PIXTRANS_BYTE_IO(cx, n) \ + if ((mach->accel.cmd_type == 2) || (mach->accel.cmd_type == 5)) { \ + if (dev->bpp) { \ + if (n == 0) \ + mach->accel.pix_trans[(n)] = vram_w[(dev->accel.dest + (cx) + (n)) & (dev->vram_mask >> 1)] & 0xff; \ + else \ + mach->accel.pix_trans[(n)] = vram_w[(dev->accel.dest + (cx) + (n)) & (dev->vram_mask >> 1)] >> 8; \ + } else { \ + mach->accel.pix_trans[(n)] = dev->vram[(dev->accel.dest + (cx) + (n)) & dev->vram_mask]; \ + } \ + } + +#define READ_PIXTRANS_WORD(cx, n) \ + if ((cmd == 0) || (cmd == 1) || (cmd == 5) || (mach->accel.cmd_type == -1)) { \ + if (dev->bpp) { \ + temp = vram_w[((dev->accel.cy * dev->pitch) + (cx) + (n)) & (dev->vram_mask >> 1)]; \ + } 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 (dev->bpp) \ + temp = vram_w[((dev->accel.dest) + (cx) + (n)) & (dev->vram_mask >> 1)]; \ + 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 ((mach->accel.cmd_type == 3) || (mach->accel.cmd_type == 4)) { \ + if (dev->bpp) \ + temp = vram_w[((mach->accel.ge_offset << 1) + ((dev->accel.cy) * (dev->pitch)) + (cx) + (n)) & (dev->vram_mask >> 1)]; \ + 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); \ + } \ + } + +#define READ(addr, dat) \ + if (dev->bpp) \ + dat = vram_w[(addr) & (dev->vram_mask >> 1)]; \ + else \ + dat = dev->vram[(addr) & (dev->vram_mask)]; + +#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) \ + if (dev->bpp) { \ + vram_w[((addr)) & (dev->vram_mask >> 1)] = dat; \ + dev->changedvram[(((addr)) & (dev->vram_mask >> 1)) >> 11] = changeframecount; \ + } else { \ + dev->vram[((addr)) & (dev->vram_mask)] = dat; \ + dev->changedvram[(((addr)) & (dev->vram_mask)) >> 12] = 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 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; + int bkgd_sel; + int mono_src; + int compare = 0; + uint16_t src_dat = 0; + uint16_t dest_dat = 0; + uint16_t old_dest_dat; + uint16_t *vram_w = (uint16_t *) dev->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; + uint32_t mono_dat1 = 0; + + if (!dev->bpp) { + 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; + dev->force_busy = 1; + dev->force_busy2 = 1; + } + + if (cpu_input) { + if (dev->bpp) { + if ((mach->accel.dp_config & 0x200) && (count == 2)) { + count >>= 1; + } + } + } + + if ((dev->accel_bpp == 8) || (dev->accel_bpp == 15) || (dev->accel_bpp == 16) || (dev->accel_bpp == 24)) { + if (dev->accel_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", dev->accel_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) { + 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 (dev->bpp) { + READ((mach->accel.ge_offset << 1) + ((dev->accel.cy) * (dev->pitch)) + (dev->accel.cx), mix); + } else { + READ((mach->accel.ge_offset << 2) + ((dev->accel.cy) * (dev->pitch)) + (dev->accel.cx), mix); + } + mix = (mix & rd_mask) == rd_mask; + break; + + default: + 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 (dev->bpp) { + READ((mach->accel.ge_offset << 1) + ((dev->accel.cy) * (dev->pitch)) + (dev->accel.cx), poly_src); + } else { + READ((mach->accel.ge_offset << 2) + ((dev->accel.cy) * (dev->pitch)) + (dev->accel.cx), poly_src); + } + 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 (dev->bpp) { + READ((mach->accel.ge_offset << 1) + ((dev->accel.cy) * (dev->pitch)) + (dev->accel.cx), src_dat); + } else { + READ((mach->accel.ge_offset << 2) + ((dev->accel.cy) * (dev->pitch)) + (dev->accel.cx), src_dat); + } + 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; + + default: + break; + } + + if (dev->bpp) { + READ((mach->accel.ge_offset << 1) + ((dev->accel.dy) * (dev->pitch)) + (dev->accel.dx), dest_dat); + } else { + READ((mach->accel.ge_offset << 2) + ((dev->accel.dy) * (dev->pitch)) + (dev->accel.dx), dest_dat); + } + } + + 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; + + default: + 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 (dev->bpp) { + WRITE((mach->accel.ge_offset << 1) + ((dev->accel.dy) * (dev->pitch)) + (dev->accel.dx), dest_dat); + } else { + WRITE((mach->accel.ge_offset << 2) + ((dev->accel.dy) * (dev->pitch)) + (dev->accel.dx), dest_dat); + } + } + } else { + if (dev->bpp) { + WRITE((mach->accel.ge_offset << 1) + ((dev->accel.dy) * (dev->pitch)) + (dev->accel.dx), dest_dat); + } else { + WRITE((mach->accel.ge_offset << 2) + ((dev->accel.dy) * (dev->pitch)) + (dev->accel.dx), dest_dat); + } + } + } + } + + if ((mono_src == 1) && !count) + break; + else if ((mono_src != 1) && (dev->accel.sx >= mach->accel.width)) + break; + + if (dev->bpp) + cpu_dat >>= 16; + else + cpu_dat >>= 8; + + 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; + + default: + break; + } + + dev->accel.sx++; + } + } else { /*Bresenham*/ + while (count--) { + switch (mono_src) { + case 0: + mix = 1; + break; + case 1: + 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: + if (dev->bpp) { + READ((mach->accel.ge_offset << 1) + ((dev->accel.cy) * (dev->pitch)) + (dev->accel.cx), mix); + } else { + READ((mach->accel.ge_offset << 2) + ((dev->accel.cy) * (dev->pitch)) + (dev->accel.cx), mix); + } + mix = (mix & rd_mask) == rd_mask; + break; + + default: + 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 (dev->bpp) { + READ((mach->accel.ge_offset << 1) + ((dev->accel.cy) * (dev->pitch)) + (dev->accel.cx), poly_src); + } else { + READ((mach->accel.ge_offset << 2) + ((dev->accel.cy) * (dev->pitch)) + (dev->accel.cx), poly_src); + } + 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 (dev->bpp) { + READ((mach->accel.ge_offset << 1) + ((dev->accel.cy) * (dev->pitch)) + (dev->accel.cx), src_dat); + } else { + READ((mach->accel.ge_offset << 2) + ((dev->accel.cy) * (dev->pitch)) + (dev->accel.cx), src_dat); + } + 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; + + default: + break; + } + + if (dev->bpp) { + READ((mach->accel.ge_offset << 1) + ((dev->accel.dy) * (dev->pitch)) + (dev->accel.dx), dest_dat); + } else { + READ((mach->accel.ge_offset << 2) + ((dev->accel.dy) * (dev->pitch)) + (dev->accel.dx), dest_dat); + } + } + + 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; + + default: + 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 (dev->bpp) { + WRITE((mach->accel.ge_offset << 1) + ((dev->accel.dy) * (dev->pitch)) + (dev->accel.dx), dest_dat); + } else { + WRITE((mach->accel.ge_offset << 2) + ((dev->accel.dy) * (dev->pitch)) + (dev->accel.dx), dest_dat); + } + } + } else { + if (dev->bpp) { + WRITE((mach->accel.ge_offset << 1) + ((dev->accel.dy) * (dev->pitch)) + (dev->accel.dx), dest_dat); + } else { + WRITE((mach->accel.ge_offset << 2) + ((dev->accel.dy) * (dev->pitch)) + (dev->accel.dx), dest_dat); + } + } + } + } + + if ((mono_src == 1) && !count) + break; + else if ((mono_src != 1) && (dev->accel.sx >= mach->accel.width)) + break; + + if (dev->bpp) + cpu_dat >>= 16; + else + cpu_dat >>= 8; + + 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 ((dev->accel_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 ((dev->accel_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 (dev->bpp) + 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 (dev->bpp) + 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 ((dev->accel_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 (dev->bpp) { + 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 ((dev->accel_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 ((dev->accel_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); + mix = (mix & rd_mask) == rd_mask; + break; + + default: + 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); + 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); + if (mono_src == 3) { + src_dat = (src_dat & rd_mask) == rd_mask; + } + } + break; + case 5: + if (mix) { + if (dev->bpp) { + 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; + + default: + break; + } + } + + if ((dev->accel_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); + } else { + READ(dev->accel.dest + dev->accel.dx, dest_dat); + } + } else { + READ(dev->accel.dest + dev->accel.dx, dest_dat); + } + + 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; + + default: + 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 ((dev->accel_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); + } else { + WRITE(dev->accel.dest + dev->accel.dx, dest_dat); + } + } else { + WRITE(dev->accel.dest + dev->accel.dx, dest_dat); + } + } + } + + if (dev->bpp) + cpu_dat >>= 16; + else + cpu_dat >>= 8; + + 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 (dev->bpp) + 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 ((dev->accel_bpp == 8) || ((dev->accel_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 ((dev->accel_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 ((dev->accel_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 ((dev->accel_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 (dev->bpp) { + 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 (dev->bpp) + 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) && (dev->accel_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 ((dev->accel_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) && (dev->accel_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; + + default: + break; + } + + if (dev->bpp) { + READ((mach->accel.ge_offset << 1) + ((dev->accel.cy) * (dev->pitch)) + (dev->accel.cx), dest_dat); + } else { + READ((mach->accel.ge_offset << 2) + ((dev->accel.cy) * (dev->pitch)) + (dev->accel.cx), dest_dat); + } + + 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; + + default: + 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 (dev->bpp) { + WRITE((mach->accel.ge_offset << 1) + ((dev->accel.cy) * (dev->pitch)) + (dev->accel.cx), dest_dat); + } else { + WRITE((mach->accel.ge_offset << 2) + ((dev->accel.cy) * (dev->pitch)) + (dev->accel.cx), dest_dat); + } + } + } else + mach->accel.clip_overrun = ((mach->accel.clip_overrun + 1) & 0x0f); + + if (!count) + break; + + if (dev->bpp) + cpu_dat >>= 16; + else + cpu_dat >>= 8; + + 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; + + default: + 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; + + default: + break; + } + + if (dev->bpp) { + READ((mach->accel.ge_offset << 1) + ((dev->accel.cy) * (dev->pitch)) + (dev->accel.cx), dest_dat); + } else { + READ((mach->accel.ge_offset << 2) + ((dev->accel.cy) * (dev->pitch)) + (dev->accel.cx), dest_dat); + } + + 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; + + default: + 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 (dev->bpp) { + WRITE((mach->accel.ge_offset << 1) + ((dev->accel.cy) * (dev->pitch)) + (dev->accel.cx), dest_dat); + } else { + WRITE((mach->accel.ge_offset << 2) + ((dev->accel.cy) * (dev->pitch)) + (dev->accel.cx), dest_dat); + } + } + } else { + if (dev->bpp) { + WRITE((mach->accel.ge_offset << 1) + ((dev->accel.cy) * (dev->pitch)) + (dev->accel.cx), dest_dat); + } else { + WRITE((mach->accel.ge_offset << 2) + ((dev->accel.cy) * (dev->pitch)) + (dev->accel.cx), dest_dat); + } + } + } + } else + mach->accel.clip_overrun = ((mach->accel.clip_overrun + 1) & 0x0f); + + if (dev->accel.sx >= mach->accel.width) + break; + + if (dev->bpp) + cpu_dat >>= 16; + else + cpu_dat >>= 8; + + 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; + + default: + break; + } + + if (dev->bpp) { + READ((mach->accel.ge_offset << 1) + ((dev->accel.cy) * (dev->pitch)) + (dev->accel.cx), dest_dat); + } else { + READ((mach->accel.ge_offset << 2) + ((dev->accel.cy) * (dev->pitch)) + (dev->accel.cx), dest_dat); + } + 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; + + default: + 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 (dev->bpp) { + WRITE((mach->accel.ge_offset << 1) + ((dev->accel.cy) * (dev->pitch)) + (dev->accel.cx), dest_dat); + } else { + WRITE((mach->accel.ge_offset << 2) + ((dev->accel.cy) * (dev->pitch)) + (dev->accel.cx), dest_dat); + } + } + } else + mach->accel.clip_overrun = ((mach->accel.clip_overrun + 1) & 0x0f); + + if (!count) + break; + + if (dev->bpp) + cpu_dat >>= 16; + else + cpu_dat >>= 8; + + 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; + + default: + 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; + + default: + break; + } + + if (dev->bpp) { + READ((mach->accel.ge_offset << 1) + ((dev->accel.cy) * (dev->pitch)) + (dev->accel.cx), dest_dat); + } else { + READ((mach->accel.ge_offset << 2) + ((dev->accel.cy) * (dev->pitch)) + (dev->accel.cx), dest_dat); + } + + 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; + + default: + 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 (dev->bpp) { + WRITE((mach->accel.ge_offset << 1) + ((dev->accel.cy) * (dev->pitch)) + (dev->accel.cx), dest_dat); + } else { + WRITE((mach->accel.ge_offset << 2) + ((dev->accel.cy) * (dev->pitch)) + (dev->accel.cx), dest_dat); + } + } + } else { + if (dev->bpp) { + WRITE((mach->accel.ge_offset << 1) + ((dev->accel.cy) * (dev->pitch)) + (dev->accel.cx), dest_dat); + } else { + WRITE((mach->accel.ge_offset << 2) + ((dev->accel.cy) * (dev->pitch)) + (dev->accel.cx), dest_dat); + } + } + } + } else + mach->accel.clip_overrun = ((mach->accel.clip_overrun + 1) & 0x0f); + + if (dev->accel.sx >= mach->accel.width) + break; + + if (dev->bpp) + cpu_dat >>= 16; + else + cpu_dat >>= 8; + + 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 ((dev->accel_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 (dev->bpp) + 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 (dev->bpp) + 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 ((dev->accel_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 (dev->accel_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) { + 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); + mix = (mix & rd_mask) == rd_mask; + break; + + default: + 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); + if (mono_src == 3) { + src_dat = (src_dat & rd_mask) == rd_mask; + } + } + break; + case 5: + if (mix) { + if (dev->accel_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; + + default: + break; + } + + READ(dev->accel.dest + (dev->accel.dx), dest_dat); + + 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; + + default: + 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); + } + } + + if (dev->bpp) + cpu_dat >>= 16; + else + cpu_dat >>= 8; + + 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 (dev->bpp) + 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 ((dev->accel_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 ((dev->accel_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 (dev->bpp) + 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; + + default: + break; + } +} + +static void +mach_accel_out_pixtrans(mach_t *mach, ibm8514_t *dev, uint16_t val) +{ + int frgd_sel; + int bkgd_sel; + int 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 >= 2)) + val = (val >> 8) | (val << 8); + mach_accel_start(mach->accel.cmd_type, 1, 8, val | (val << 16), 0, mach, dev); + } else + mach_accel_start(mach->accel.cmd_type, 1, 1, -1, val | (val << 16), mach, dev); + } else + mach_accel_start(mach->accel.cmd_type, 1, 1, -1, val | (val << 16), mach, dev); + 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); + } else { + mach_accel_start(mach->accel.cmd_type, 1, 2, -1, val | (val << 16), mach, dev); + } + } else { + mach_accel_start(mach->accel.cmd_type, 1, 2, -1, val | (val << 16), mach, dev); + } + break; + + default: + break; + } +} + +static void +mach_out(uint16_t addr, uint8_t val, void *priv) +{ + mach_t *mach = (mach_t *) priv; + svga_t *svga = &mach->svga; + const ibm8514_t *dev = (ibm8514_t *) svga->dev8514; + uint8_t old; + uint8_t rs2; + uint8_t rs3; + + 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 >= 2) { + 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 >= 2) { + mach->bank_r |= ((mach->regs[0xae] & 0x0c) << 2); + mach->bank_w |= ((mach->regs[0xae] & 3) << 4); + } + if (dev->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 >= 2) { + mach->bank_w |= ((mach->regs[0xae] & 3) << 4); + } + mach->bank_r = mach->bank_w; + if (dev->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 >= 2) { + 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; + + default: + break; + } + break; + + case 0x2ea: + case 0x2eb: + case 0x2ec: + case 0x2ed: + rs2 = !!(mach->accel.ext_ge_config & 0x1000); + rs3 = !!(mach->accel.ext_ge_config & 0x2000); + if (dev->local >= 2) { + if (mach->pci_bus && !mach->ramdac_type) + ati68860_ramdac_out((addr & 3) | (rs2 << 2) | (rs3 << 3), val, svga->ramdac, svga); + else + ati68875_ramdac_out(addr, rs2, rs3, val, svga->ramdac, svga); + } else + svga_out(addr, val, svga); + return; + + case 0x3C6: + case 0x3C7: + case 0x3C8: + case 0x3C9: + rs2 = !!(mach->regs[0xa0] & 0x20); + rs3 = !!(mach->regs[0xa0] & 0x40); + if (dev->local >= 2) { + if (mach->pci_bus && !mach->ramdac_type) + ati68860_ramdac_out((addr & 3) | (rs2 << 2) | (rs3 << 3), val, svga->ramdac, svga); + else + ati68875_ramdac_out(addr, rs2, rs3, val, svga->ramdac, svga); + } else + svga_out(addr, val, svga); + return; + + case 0x3D4: + svga->crtcreg = val & 0x3f; + return; + case 0x3D5: + if (svga->crtcreg & 0x20) + return; + if ((svga->crtcreg < 7) && (svga->crtc[0x11] & 0x80) && !(mach->regs[0xb4] & 0x80)) + return; + if ((svga->crtcreg == 7) && (svga->crtc[0x11] & 0x80) && !(mach->regs[0xb4] & 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; + + default: + break; + } + svga_out(addr, val, svga); +} + +static uint8_t +mach_in(uint16_t addr, void *priv) +{ + mach_t *mach = (mach_t *) priv; + svga_t *svga = &mach->svga; + const ibm8514_t *dev = (ibm8514_t *) svga->dev8514; + uint8_t temp = 0xff; + uint8_t rs2; + uint8_t rs3; + + 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 >= 2) { /*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; + + case 0xbd: + temp = mach->regs[0xbd] | 0x10; + break; + + default: + temp = mach->regs[mach->index]; + break; + } + break; + + case 0x2ea: + case 0x2eb: + case 0x2ec: + case 0x2ed: + rs2 = !!(mach->accel.ext_ge_config & 0x1000); + rs3 = !!(mach->accel.ext_ge_config & 0x2000); + if (dev->local >= 2) { + if (mach->pci_bus && !mach->ramdac_type) + temp = ati68860_ramdac_in((addr & 3) | (rs2 << 2) | (rs3 << 3), svga->ramdac, svga); + else + temp = ati68875_ramdac_in(addr, rs2, rs3, svga->ramdac, svga); + } else + temp = svga_in(addr, svga); + break; + + case 0x3C6: + case 0x3C7: + case 0x3C8: + case 0x3C9: + rs2 = !!(mach->regs[0xa0] & 0x20); + rs3 = !!(mach->regs[0xa0] & 0x40); + if (dev->local >= 2) { + if (mach->pci_bus && !mach->ramdac_type) + temp = ati68860_ramdac_in((addr & 3) | (rs2 << 2) | (rs3 << 3), svga->ramdac, svga); + else + temp = ati68875_ramdac_in(addr, rs2, rs3, svga->ramdac, svga); + } else + temp = svga_in(addr, svga); + break; + + 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; +} + +static void +mach_recalctimings(svga_t *svga) +{ + const mach_t *mach = (mach_t *) svga->priv; + ibm8514_t *dev = (ibm8514_t *) svga->dev8514; + int clock_sel; + + clock_sel = ((svga->miscout >> 2) & 3) | ((mach->regs[0xbe] & 0x10) >> 1) | ((mach->regs[0xb9] & 2) << 1); + + if (dev->local >= 2) { + if (mach->regs[0xad] & 0x04) + svga->ma_latch |= 0x40000; + + if (mach->regs[0xad] & 0x08) + svga->ma_latch |= 0x80000; + } + + if (mach->regs[0xa3] & 0x10) + svga->ma_latch |= 0x10000; + + if (mach->regs[0xb0] & 0x40) + svga->ma_latch |= 0x20000; + + 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 (dev->on) { + mach_log("8514/A ON.\n"); + if (dev->local >= 2) { + dev->h_disp = (dev->hdisp + 1) << 3; + dev->h_total = (dev->htotal + 1); + dev->v_total = (dev->vtotal + 1); + dev->v_syncstart = (dev->vsyncstart + 1); + dev->dispend = ((dev->vdisp >> 1) + 1); + dev->rowcount = !!(dev->disp_cntl & 0x08); + + if (dev->dispend == 766) + dev->dispend += 2; + + if (dev->dispend == 598) + dev->dispend += 2; + + if (dev->h_disp == 1024) + dev->accel.advfunc_cntl |= 4; /*Bit 2 means high resolution e.g.: 1024x768*/ + + if (dev->accel.advfunc_cntl & 4) { + if (mach->shadow_set & 2) { + if (dev->h_disp == 8) { + dev->h_disp = 1024; + dev->dispend = 768; + dev->v_total = 1536; + dev->v_syncstart = 1536; + } + mach_log("Shadow set 2.\n"); + svga->clock = (cpuclock * (double) (1ULL << 32)) / 44900000.0; + } else + svga->clock = (cpuclock * (double) (1ULL << 32)) / svga->getclock((mach->accel.clock_sel >> 2) & 0x0f, svga->clock_gen); + } else { + if (dev->h_disp == 1024) { + dev->h_disp = 640; + dev->dispend = 480; + } + if (mach->shadow_set & 1) { + mach_log("Shadow set 1.\n"); + svga->clock = (cpuclock * (double) (1ULL << 32)) / 25175000.0; + } else + svga->clock = (cpuclock * (double) (1ULL << 32)) / svga->getclock((mach->accel.clock_sel >> 2) & 0x0f, svga->clock_gen); + } + + if (dev->interlace) { + dev->dispend >>= 1; + dev->v_syncstart >>= 2; + dev->v_total >>= 2; + } else { + dev->v_syncstart >>= 1; + dev->v_total >>= 1; + } + + dev->pitch = dev->ext_pitch; + dev->rowoffset = dev->ext_crt_pitch; + if ((mach->accel.ext_ge_config & 0x800) || (!(mach->accel.ext_ge_config & 0x8000) && !(mach->accel.ext_ge_config & 0x800))) { + if ((mach->accel.ext_ge_config & 0x30) == 0x20) { + if ((mach->accel.ext_ge_config & 0xc0) == 0x40) + dev->accel_bpp = 16; + else + dev->accel_bpp = 15; + } else if ((mach->accel.ext_ge_config & 0x30) == 0x30) { + if (mach->accel.ext_ge_config & 0x200) + dev->accel_bpp = 32; + else + dev->accel_bpp = 24; + } else + dev->accel_bpp = 8; + + mach_log("hv(%d,%d), pitch=%d, rowoffset=%d, gextconfig=%03x, bpp=%d.\n", dev->h_disp, dev->dispend, dev->pitch, dev->ext_crt_pitch, mach->accel.ext_ge_config & 0xcec0, dev->accel_bpp); + switch (dev->accel_bpp) { + case 8: + svga->render8514 = ibm8514_render_8bpp; + break; + case 15: + svga->render8514 = ibm8514_render_15bpp; + break; + case 16: + svga->render8514 = ibm8514_render_16bpp; + break; + case 24: + if (mach->accel.ext_ge_config & 0x400) + svga->render8514 = ibm8514_render_BGR; + else + svga->render8514 = ibm8514_render_24bpp; + break; + case 32: + if (mach->accel.ext_ge_config & 0x400) + svga->render8514 = ibm8514_render_ABGR8888; + else + svga->render8514 = ibm8514_render_RGBA8888; + break; + + default: + break; + } + } + switch (mach->regs[0xb8] & 0xc0) { + case 0x40: + svga->clock *= 2; + break; + case 0x80: + svga->clock *= 3; + break; + case 0xc0: + svga->clock *= 4; + break; + + default: + break; + } + } else { + dev->h_disp = (dev->hdisp + 1) << 3; + dev->h_total = (dev->htotal + 1); + dev->v_total = (dev->vtotal + 1); + dev->v_syncstart = (dev->vsyncstart + 1); + dev->rowcount = !!(dev->disp_cntl & 0x08); + dev->dispend = ((dev->vdisp >> 1) + 1); + + if (dev->dispend == 766) + dev->dispend += 2; + + if (dev->dispend == 598) + dev->dispend += 2; + + if (dev->accel.advfunc_cntl & 4) { + if (mach->shadow_set & 2) { + if (dev->h_disp == 8) { + dev->h_disp = 1024; + dev->dispend = 768; + dev->v_total = 1536; + dev->v_syncstart = 1536; + } + svga->clock = (cpuclock * (double) (1ULL << 32)) / 44900000.0; + } else + svga->clock = (cpuclock * (double) (1ULL << 32)) / svga->getclock((mach->accel.clock_sel >> 2) & 0x0f, svga->clock_gen); + } else { + if (dev->h_disp == 1024) { + dev->h_disp = 640; + dev->dispend = 480; + } + if (mach->shadow_set & 1) { + svga->clock = (cpuclock * (double) (1ULL << 32)) / 25175000.0; + } else + svga->clock = (cpuclock * (double) (1ULL << 32)) / svga->getclock((mach->accel.clock_sel >> 2) & 0x0f, svga->clock_gen); + } + if (dev->interlace) { + dev->dispend >>= 1; + dev->v_syncstart >>= 2; + dev->v_total >>= 2; + } else { + dev->v_syncstart >>= 1; + dev->v_total >>= 1; + } + dev->pitch = dev->ext_pitch; + dev->rowoffset = dev->ext_crt_pitch; + mach_log("cntl=%d, hv(%d,%d), pitch=%d, rowoffset=%d, gextconfig=%03x.\n", dev->accel.advfunc_cntl & 4, dev->h_disp, dev->dispend, dev->pitch, dev->rowoffset, mach->accel.ext_ge_config & 0xcec0); + svga->map8 = dev->pallook; + svga->render8514 = ibm8514_render_8bpp; + if (mach->regs[0xb8] & 0x40) + svga->clock *= 2; + } + } + + if (!svga->scrblank && (svga->crtc[0x17] & 0x80) && svga->attr_palette_enable) { + if (((svga->gdcreg[6] & 1) || (svga->attrregs[0x10] & 1))) { + mach_log("VGA clock=%02x.\n", mach->regs[0xa7] & 0x80); + svga->clock = (cpuclock * (double) (1ULL << 32)) / svga->getclock(clock_sel, svga->clock_gen); + if (mach->regs[0xa7] & 0x80) + svga->clock *= 3; + 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) { + default: + 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; + + default: + break; + } + } + } +} + +static void +mach_accel_out_fifo(mach_t *mach, svga_t *svga, ibm8514_t *dev, uint16_t port, uint16_t val, int len) +{ + int frgd_sel; + int bkgd_sel; + int 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; + fallthrough; + + 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, val); + } 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); + } else + mach_accel_start(mach->accel.cmd_type, 1, 1, -1, mach->accel.pix_trans[0] | (mach->accel.pix_trans[1] << 8), mach, dev); + } else + mach_accel_start(mach->accel.cmd_type, 1, 1, -1, mach->accel.pix_trans[0] | (mach->accel.pix_trans[1] << 8), mach, dev); + 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); + else + mach_accel_start(mach->accel.cmd_type, 1, 16, mach->accel.pix_trans[0] | (mach->accel.pix_trans[1] << 8), 0, mach, dev); + } else + mach_accel_start(mach->accel.cmd_type, 1, 2, -1, mach->accel.pix_trans[0] | (mach->accel.pix_trans[1] << 8), mach, dev); + } else + mach_accel_start(mach->accel.cmd_type, 1, 2, -1, mach->accel.pix_trans[0] | (mach->accel.pix_trans[1] << 8), mach, dev); + break; + + default: + 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, val); + } 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); + } else + mach_accel_start(mach->accel.cmd_type, 1, 1, -1, mach->accel.pix_trans[0] | (mach->accel.pix_trans[1] << 8), mach, dev); + } else + mach_accel_start(mach->accel.cmd_type, 1, 1, -1, mach->accel.pix_trans[0] | (mach->accel.pix_trans[1] << 8), mach, dev); + 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); + else + mach_accel_start(mach->accel.cmd_type, 1, 16, mach->accel.pix_trans[0] | (mach->accel.pix_trans[1] << 8), 0, mach, dev); + } else + mach_accel_start(mach->accel.cmd_type, 1, 2, -1, mach->accel.pix_trans[0] | (mach->accel.pix_trans[1] << 8), mach, dev); + } else + mach_accel_start(mach->accel.cmd_type, 1, 2, -1, mach->accel.pix_trans[0] | (mach->accel.pix_trans[1] << 8), mach, dev); + break; + + default: + 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], dev->accel_bpp, dev->pitch); + if ((dev->accel.multifunc_cntl >> 12) == 5) { + if (dev->local < 2) + 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 < 2) + 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 ((dev->accel_bpp == 24) && (mach->accel.patt_len == 0x17) && (frgd_sel == 5)) { + mach->accel.patt_data_idx += 2; + dev->accel.y1 = 1; + } else { + if (dev->accel_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 ((dev->accel_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); + } + 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); + } + 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); + } + 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); + } + 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); + } + 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); + } + 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); + mach->accel.line_idx = (mach->accel.line_idx == 5) ? 4 : 2; + break; + } + mach->accel.line_idx++; + } + break; + + default: + break; + } +} + +static void +mach_accel_out(uint16_t port, uint8_t val, mach_t *mach) +{ + svga_t *svga = &mach->svga; + ibm8514_t *dev = (ibm8514_t *) svga->dev8514; + + mach_log("Port accel out = %04x, val = %04x.\n", port, val); + + switch (port) { + case 0x2e8: + case 0x2e9: + WRITE8(port, dev->htotal, val); + svga_recalctimings(svga); + break; + case 0x6e8: + case 0x6e9: + if (!(port & 1)) { + 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: + case 0x12e9: + WRITE8(port, dev->vtotal, val); + dev->vtotal &= 0x1fff; + svga_recalctimings(svga); + break; + + case 0x16e8: + case 0x16e9: + WRITE8(port, dev->vdisp, val); + dev->vdisp &= 0x1fff; + svga_recalctimings(svga); + break; + + case 0x1ae8: + case 0x1ae9: + WRITE8(port, dev->vsyncstart, val); + dev->vsyncstart &= 0x1fff; + svga_recalctimings(svga); + break; + + case 0x1ee8: + case 0x1ee9: + 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); + svga_recalctimings(svga); + mach_log("ATI 8514/A: DISP_CNTL write 22E8 = %02x, SCANMODULOS = %d\n", dev->disp_cntl, dev->scanmodulos); + break; + + case 0x42e8: + dev->subsys_stat &= ~val; + break; + case 0x42e9: + dev->subsys_cntl = val; + break; + + case 0x4ae8: + case 0x4ae9: + if (!(port & 1)) { + if (dev->local < 2) + dev->ext_crt_pitch = 128; + + dev->accel.advfunc_cntl = val & 0x0f; + } else { + dev->on = (dev->accel.advfunc_cntl & 0x01); + vga_on = !dev->on; + mach->ext_on = dev->on; + mach_log("ATI 8514/A: (0x4ae9) val = %04x, ext = %d.\n", dev->accel.advfunc_cntl & 0x01, mach->ext_on); + mach32_updatemapping(mach); + } + mach->ati_mode = 0; + svga_recalctimings(svga); + break; + + /*ATI Mach8/32 specific registers*/ + case 0x2ee: + mach_log("2EE write val = %02x.\n", val); + break; + case 0x2ef: + mach_log("2EF write val = %02x.\n", val); + break; + + case 0x6ee: + mach_log("6EE write val = %02x.\n", val); + break; + case 0x6ef: + mach_log("6EF write val = %02x.\n", val); + break; + + case 0xaee: + case 0xaef: + WRITE8(port, mach->cursor_offset_lo, val); + break; + + case 0xeee: + case 0xeef: + WRITE8(port, mach->cursor_offset_hi_reg, val); + mach->cursor_offset_hi = mach->cursor_offset_hi_reg & 0x0f; + dev->hwcursor.addr = (mach->cursor_offset_lo | (mach->cursor_offset_hi << 16)) << 2; + dev->hwcursor.ena = !!(mach->cursor_offset_hi_reg & 0x8000); + break; + + case 0x12ee: + case 0x12ef: + WRITE8(port, mach->cursor_x, val); + dev->hwcursor.x = mach->cursor_x & 0x7ff; + break; + + case 0x16ee: + case 0x16ef: + WRITE8(port, mach->cursor_y, val); + dev->hwcursor.y = mach->cursor_y & 0xfff; + break; + + case 0x1aee: + case 0x1aef: + WRITE8(port, mach->cursor_col_b, val); + mach->cursor_col_0 = mach->cursor_col_b & 0xff; + mach->cursor_col_1 = (mach->cursor_col_b >> 8) & 0xff; + break; + + case 0x1eee: + case 0x1eef: + WRITE8(port, mach->cursor_vh_offset, val); + dev->hwcursor.xoff = mach->cursor_vh_offset & 0x3f; + dev->hwcursor.yoff = (mach->cursor_vh_offset >> 8) & 0x3f; + break; + + case 0x22ee: + if (mach->pci_bus) { + mach->pci_cntl_reg = val; + mach32_updatemapping(mach); + } + break; + + case 0x26ee: + case 0x26ef: + WRITE8(port, mach->accel.crt_pitch, val); + dev->ext_crt_pitch = mach->accel.crt_pitch & 0xff; + if (dev->accel_bpp > 8) { + if (dev->accel_bpp == 24) + dev->ext_crt_pitch *= 3; + else if (dev->accel_bpp == 32) + dev->ext_crt_pitch <<= 2; + else + dev->ext_crt_pitch <<= 1; + } + svga_recalctimings(svga); + break; + + case 0x32ee: + case 0x32ef: + WRITE8(port, mach->local_cntl, val); + mach32_updatemapping(mach); + break; + + case 0x36ee: + case 0x36ef: + mach_log("ATI 8514/A: (0x%04x) val = %04x.\n", port, val); + WRITE8(port, mach->misc, val); + mach->misc &= 0xfff0; + break; + + case 0x3aee: + case 0x3aef: + WRITE8(port, mach->cursor_col_0_rg, val); + mach->ext_cur_col_0_g = mach->cursor_col_0_rg & 0xff; + mach->ext_cur_col_0_r = (mach->cursor_col_0_rg >> 8) & 0xff; + break; + + case 0x3eee: + case 0x3eef: + WRITE8(port, mach->cursor_col_1_rg, val); + mach->ext_cur_col_1_g = mach->cursor_col_1_rg & 0xff; + mach->ext_cur_col_1_r = (mach->cursor_col_1_rg >> 8) & 0xff; + 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: + case 0x4aef: + WRITE8(port, mach->accel.clock_sel, val); + if (port & 1) { + dev->on = mach->accel.clock_sel & 0x01; + mach->ext_on = dev->on; + vga_on = !dev->on; + mach_log("ATI 8514/A: (0x4aef) val = %04x, ext = %d.\n", mach->accel.clock_sel & 0x01, mach->ext_on); + } + mach->ati_mode = 1; + svga_recalctimings(svga); + break; + + case 0x52ee: + case 0x52ef: + mach_log("ATI 8514/A: (0x%04x) val = %04x.\n", port, val); + WRITE8(port, mach->accel.scratch0, val); + if (port & 1) + mach->ext_on = 1; + break; + + case 0x56ee: + case 0x56ef: + mach_log("ATI 8514/A: (0x%04x) val = %04x.\n", port, val); + WRITE8(port, mach->accel.scratch1, val); + if (port & 1) + mach->ext_on = 1; + break; + + case 0x5aee: + case 0x5aef: + WRITE8(port, mach->shadow_set, val); + if (port & 1) + mach_log("Shadow set = %02x.\n", mach->shadow_set & 0x03); + + svga_recalctimings(svga); + break; + + case 0x5eee: + case 0x5eef: + WRITE8(port, mach->memory_aperture, val); + mach_log("Memory Aperture = %04x.\n", mach->memory_aperture); + 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: + case 0x6aef: + WRITE8(port, mach->accel.max_waitstates, val); + break; + + case 0x6eee: + case 0x6eef: + WRITE8(port, mach->accel.ge_offset_lo, val); + dev->accel.ge_offset = mach->accel.ge_offset_lo; + break; + + case 0x72ee: + case 0x72ef: + WRITE8(port, mach->accel.ge_offset_hi, val); + dev->accel.ge_offset = mach->accel.ge_offset_lo | (mach->accel.ge_offset_hi << 16); + break; + + case 0x76ee: + case 0x76ef: + WRITE8(port, mach->accel.ge_pitch, val); + dev->ext_pitch = ((mach->accel.ge_pitch & 0xff) << 3); + svga_recalctimings(svga); + break; + + case 0x7aee: + case 0x7aef: + WRITE8(port, mach->accel.ext_ge_config, val); + if (dev->local >= 2) { + if (mach->accel.crt_pitch & 0xff) + dev->ext_crt_pitch = mach->accel.crt_pitch & 0xff; + switch (mach->accel.ext_ge_config & 0x30) { + case 0: + case 0x10: + dev->bpp = 0; + break; + case 0x20: + dev->bpp = 1; + dev->ext_crt_pitch <<= 1; + break; + case 0x30: + dev->bpp = 0; + if (mach->accel.ext_ge_config & 0x200) + dev->ext_crt_pitch <<= 2; + else + dev->ext_crt_pitch *= 3; + break; + + default: + break; + } + svga_set_ramdac_type(svga, !!(mach->accel.ext_ge_config & 0x4000)); + if (port & 1) { + mach->ati_mode = 1; + mach_log("ATI 8514/A: (0x%04x) val = %04x.\n", port, val); + mach32_updatemapping(mach); + } + } + svga_recalctimings(svga); + break; + + case 0x7eee: + case 0x7eef: + WRITE8(port, mach->accel.eeprom_control, val); + ati_eeprom_write(&mach->eeprom, mach->accel.eeprom_control & 4, mach->accel.eeprom_control & 2, mach->accel.eeprom_control & 1); + mach_log("[%04X]: 7EEE+%d VGA ON = %d, Ext = %i, val = %04x, pagesel = %04x.\n", CS, port & 1, vga_on, ibm8514_on, mach->accel.eeprom_control & 0x10ff, (mach->accel.eeprom_control & 0xf0) << 7); + svga_recalctimings(svga); + break; + + default: + break; + } +} + +static uint16_t +mach_accel_in_fifo(mach_t *mach, svga_t *svga, ibm8514_t *dev, uint16_t port, int len) +{ + const uint16_t *vram_w = (uint16_t *) dev->vram; + uint16_t temp = 0; + int cmd; + int frgd_sel; + int bkgd_sel; + int mono_src; + + switch (port) { + 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) + temp = mach->accel.pix_trans[1]; + } else { + if (mach->accel.cmd_type == 3) { + READ_PIXTRANS_WORD(dev->accel.cx, 0) + } else { + READ_PIXTRANS_WORD(dev->accel.dx, 0) + } + mach_accel_out_pixtrans(mach, dev, temp); + } + } + } else { + if (ibm8514_cpu_dest(svga)) { + cmd = (dev->accel.cmd >> 13); + if (len != 1) { + READ_PIXTRANS_WORD(dev->accel.cx, 0) + if (dev->accel.input && !dev->accel.odd_in && !dev->accel.sx) { + temp &= ~0xff00; + 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) + + 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); + } else + mach_accel_start(mach->accel.cmd_type, 1, 1, -1, mach->accel.pix_trans[0] | (mach->accel.pix_trans[1] << 8), mach, dev); + } else + mach_accel_start(mach->accel.cmd_type, 1, 1, -1, mach->accel.pix_trans[0] | (mach->accel.pix_trans[1] << 8), mach, dev); + 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); + else + mach_accel_start(mach->accel.cmd_type, 1, 16, mach->accel.pix_trans[0] | (mach->accel.pix_trans[1] << 8), 0, mach, dev); + } else + mach_accel_start(mach->accel.cmd_type, 1, 2, -1, mach->accel.pix_trans[0] | (mach->accel.pix_trans[1] << 8), mach, dev); + } else + mach_accel_start(mach->accel.cmd_type, 1, 2, -1, mach->accel.pix_trans[0] | (mach->accel.pix_trans[1] << 8), mach, dev); + break; + + default: + 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; + + default: + break; + } + } + 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; + + mach_log("ExtGE Read = %04x, len=%d.\n", temp, len); + break; + case 0x8eef: + if (len == 1) + temp = mach->accel.ext_ge_config >> 8; + break; + + case 0x92ee: + if (len == 1) + temp = mach->accel.eeprom_control & 0xff; + else + temp = mach->accel.eeprom_control; + + mach_log("EEPROM cntl read=%04x, len=%d.\n", temp, len); + break; + case 0x92ef: + if (len == 1) + temp = mach->accel.eeprom_control >> 8; + + mach_log("EEPROM cntl read+1=%02x, len=%d.\n", temp, len); + 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 = dev->vc & 0xff; + else + temp = dev->vc & 0x7ff; + break; + case 0xceef: + if (len == 1) + temp = (dev->vc >> 8) & 7; + break; + + case 0xdaee: + if (len != 1) { + temp = mach->accel.src_x; + if (dev->local >= 2) + temp &= 0x7ff; + } else + temp = mach->accel.src_x & 0xff; + break; + case 0xdaef: + if (len == 1) + temp = mach->accel.src_x >> 8; + break; + + case 0xdeee: + if (len != 1) { + temp = mach->accel.src_y; + if (dev->local >= 2) + temp &= 0x7ff; + } else + temp = mach->accel.src_y & 0xff; + break; + case 0xdeef: + if (len == 1) + temp = mach->accel.src_y >> 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; + + default: + break; + } + + mach_log("Port FIFO IN=%04x, temp=%04x, len=%d.\n", port, temp, len); + return temp; +} + +static uint8_t +mach_accel_in(uint16_t port, mach_t *mach) +{ + svga_t *svga = &mach->svga; + ibm8514_t *dev = (ibm8514_t *) svga->dev8514; + uint8_t temp = 0; + int vpos = 0; + int vblankend = svga->vblankstart + svga->crtc[0x16]; + + switch (port) { + case 0x2e8: + vpos = dev->vc & 0x7ff; + if (vblankend > dev->v_total) { + vblankend -= dev->v_total; + 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: + case 0x26e9: + READ8(port, dev->htotal); + break; + + case 0x2ee8: + temp = dev->subsys_cntl; + break; + case 0x2ee9: + temp = 0xff; + break; + + case 0x42e8: + case 0x42e9: + vpos = dev->vc & 0x7ff; + if (vblankend > dev->v_total) { + vblankend -= dev->v_total; + if (vpos >= svga->vblankstart || vpos <= vblankend) + dev->subsys_stat |= 1; + } else { + if (vpos >= svga->vblankstart && vpos <= vblankend) + dev->subsys_stat |= 1; + } + + if (port & 1) { + temp = 0x80; + } else { + temp = dev->subsys_stat | 0x80; + if (mach->accel.ext_ge_config & 0x08) { + temp |= ((mach->accel.ext_ge_config & 0x07) << 4); + } else + temp |= 0x20; + } + break; + + case 0x4ae8: + temp = dev->accel.advfunc_cntl; + break; + + /*ATI Mach8/32 specific registers*/ + case 0x12ee: + case 0x12ef: + READ8(port, mach->config1); + break; + + case 0x16ee: + case 0x16ef: + READ8(port, mach->config2); + break; + + case 0x22ee: + if (mach->pci_bus) { + temp = mach->pci_cntl_reg; + } + break; + + case 0x32ee: + case 0x32ef: + READ8(port, mach->local_cntl); + break; + + case 0x36ee: + case 0x36ef: + READ8(port, mach->misc); + + if (!(port & 1)) { + switch (mach->memory) { + case 512: + temp &= ~0x0c; + break; + case 1024: + temp |= 0x04; + break; + case 2048: + temp |= 0x08; + break; + case 4096: + temp |= 0x0c; + break; + + default: + break; + } + } + 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: + case 0x4aef: + READ8(port, mach->accel.clock_sel); + break; + + case 0x52ee: + case 0x52ef: + READ8(port, mach->accel.scratch0); + break; + + case 0x56ee: + case 0x56ef: + READ8(port, mach->accel.scratch1); + break; + + case 0x5eee: + case 0x5eef: + if (mach->pci_bus) + mach->memory_aperture = (mach->memory_aperture & ~0xfff0) | ((mach->linear_base >> 20) << 4); + + READ8(port, mach->memory_aperture); + break; + + case 0x62ee: + temp = mach->accel.clip_overrun; + mach_log("ClipOverrun = %02x.\n", temp); + break; + case 0x62ef: + if (mach->force_busy) + temp |= 0x20; + mach->force_busy = 0; + if (ati_eeprom_read(&mach->eeprom)) + temp |= 0x40; + mach_log("Mach busy temp=%02x.\n", temp); + break; + + case 0x6aee: + case 0x6aef: + READ8(port, mach->accel.max_waitstates); + break; + + case 0x72ee: + case 0x72ef: + READ8(port, dev->accel.clip_left); + break; + + case 0x76ee: + case 0x76ef: + READ8(port, dev->accel.clip_top); + break; + + case 0x7aee: + case 0x7aef: + READ8(port, dev->accel.multifunc[4]); + break; + + case 0x7eee: + case 0x7eef: + READ8(port, dev->accel.multifunc[3]); + break; + + default: + break; + } + mach_log("Port accel in = %04x, temp = %04x.\n", port, temp); + return temp; +} + +static void +mach_accel_outb(uint16_t port, uint8_t val, void *priv) +{ + mach_t *mach = (mach_t *) priv; + svga_t *svga = &mach->svga; + + if (port & 0x8000) + mach_accel_out_fifo(mach, svga, (ibm8514_t *) svga->dev8514, port, val, 1); + else + mach_accel_out(port, val, mach); +} + +static void +mach_accel_outw(uint16_t port, uint16_t val, void *priv) +{ + mach_t *mach = (mach_t *) priv; + svga_t *svga = &mach->svga; + + if (port & 0x8000) + mach_accel_out_fifo(mach, svga, (ibm8514_t *) svga->dev8514, port, val, 2); + else { + mach_accel_out(port, val, mach); + mach_accel_out(port + 1, (val >> 8), mach); + } +} + +static void +mach_accel_outl(uint16_t port, uint32_t val, void *priv) +{ + mach_t *mach = (mach_t *) priv; + svga_t *svga = &mach->svga; + + if (port & 0x8000) { + mach_accel_out_fifo(mach, svga, (ibm8514_t *) svga->dev8514, port, val & 0xffff, 2); + mach_accel_out_fifo(mach, svga, (ibm8514_t *) svga->dev8514, port + 2, val >> 16, 2); + } else { + mach_accel_out(port, val, mach); + mach_accel_out(port + 1, (val >> 8), mach); + mach_accel_out(port + 2, (val >> 16), mach); + mach_accel_out(port + 3, (val >> 24), mach); + } +} +static uint8_t +mach_accel_inb(uint16_t port, void *priv) +{ + mach_t *mach = (mach_t *) priv; + svga_t *svga = &mach->svga; + uint8_t temp; + + if (port & 0x8000) + temp = mach_accel_in_fifo(mach, svga, (ibm8514_t *) svga->dev8514, port, 1); + else + temp = mach_accel_in(port, mach); + + return temp; +} + +static uint16_t +mach_accel_inw(uint16_t port, void *priv) +{ + mach_t *mach = (mach_t *) priv; + svga_t *svga = &mach->svga; + uint16_t temp; + + if (port & 0x8000) + temp = mach_accel_in_fifo(mach, svga, (ibm8514_t *) svga->dev8514, port, 2); + else { + temp = mach_accel_in(port, mach); + temp |= (mach_accel_in(port + 1, mach) << 8); + } + return temp; +} + +static uint32_t +mach_accel_inl(uint16_t port, void *priv) +{ + mach_t *mach = (mach_t *) priv; + svga_t *svga = &mach->svga; + uint32_t temp; + + if (port & 0x8000) { + temp = mach_accel_in_fifo(mach, svga, (ibm8514_t *) svga->dev8514, port, 2); + temp = (mach_accel_in_fifo(mach, svga, (ibm8514_t *) svga->dev8514, port + 2, 2) << 16); + } else { + temp = mach_accel_in(port, mach); + temp |= (mach_accel_in(port + 1, mach) << 8); + temp |= (mach_accel_in(port + 2, mach) << 16); + temp |= (mach_accel_in(port + 3, mach) << 24); + } + return temp; +} + +static void +mach32_write_linear(uint32_t addr, uint8_t val, void *priv) +{ + svga_t *svga = (svga_t *) priv; + ibm8514_t *dev = (ibm8514_t *) svga->dev8514; + int writemask2 = svga->writemask; + int reset_wm = 0; + latch_t vall; + uint8_t wm = svga->writemask; + uint8_t count; + uint8_t i; + + cycles -= svga->monitor->mon_video_timing_write_b; + + if (!(svga->gdcreg[6] & 1)) + svga->fullchange = 2; + + if (((svga->chain4 && (svga->packed_chain4 || svga->force_old_addr)) || svga->fb_only) && (svga->writemode < 4)) { + writemask2 = 1 << (addr & 3); + addr &= ~3; + } else if (svga->chain4 && (svga->writemode < 4)) { + writemask2 = 1 << (addr & 3); + addr = ((addr & 0xfffc) << 2) | ((addr & 0x30000) >> 14) | (addr & ~0x3ffff); + } else if (svga->chain2_write) { + writemask2 &= ~0xa; + if (addr & 1) + writemask2 <<= 1; + addr &= ~1; + addr &= dev->vram_mask; + } else { + writemask2 = 1 << (addr & 3); + addr &= ~3; + addr &= dev->vram_mask; + } + addr &= svga->decode_mask; + + if (addr >= dev->vram_size) + return; + + addr &= dev->vram_mask; + + dev->changedvram[addr >> 12] = svga->monitor->mon_changeframecount; + + count = 4; + + switch (svga->writemode) { + case 0: + val = ((val >> (svga->gdcreg[3] & 7)) | (val << (8 - (svga->gdcreg[3] & 7)))); + if ((svga->gdcreg[8] == 0xff) && !(svga->gdcreg[3] & 0x18) && (!svga->gdcreg[1] || svga->set_reset_disabled)) { + for (i = 0; i < count; i++) { + if (writemask2 & (1 << i)) + dev->vram[addr | i] = val; + } + return; + } else { + for (i = 0; i < count; i++) { + if (svga->gdcreg[1] & (1 << i)) + vall.b[i] = !!(svga->gdcreg[0] & (1 << i)) * 0xff; + else + vall.b[i] = val; + } + } + break; + case 1: + for (i = 0; i < count; i++) { + if (writemask2 & (1 << i)) + dev->vram[addr | i] = svga->latch.b[i]; + } + return; + case 2: + for (i = 0; i < count; i++) + vall.b[i] = !!(val & (1 << i)) * 0xff; + + if (!(svga->gdcreg[3] & 0x18) && (!svga->gdcreg[1] || svga->set_reset_disabled)) { + for (i = 0; i < count; i++) { + if (writemask2 & (1 << i)) + dev->vram[addr | i] = (vall.b[i] & svga->gdcreg[8]) | (svga->latch.b[i] & ~svga->gdcreg[8]); + } + return; + } + break; + case 3: + val = ((val >> (svga->gdcreg[3] & 7)) | (val << (8 - (svga->gdcreg[3] & 7)))); + wm = svga->gdcreg[8]; + svga->gdcreg[8] &= val; + + for (i = 0; i < count; i++) + vall.b[i] = !!(svga->gdcreg[0] & (1 << i)) * 0xff; + + reset_wm = 1; + break; + default: + break; + } + + switch (svga->gdcreg[3] & 0x18) { + case 0x00: /* Set */ + for (i = 0; i < count; i++) { + if (writemask2 & (1 << i)) + dev->vram[addr | i] = (vall.b[i] & svga->gdcreg[8]) | (svga->latch.b[i] & ~svga->gdcreg[8]); + } + break; + case 0x08: /* AND */ + for (i = 0; i < count; i++) { + if (writemask2 & (1 << i)) + dev->vram[addr | i] = (vall.b[i] | ~svga->gdcreg[8]) & svga->latch.b[i]; + } + break; + case 0x10: /* OR */ + for (i = 0; i < count; i++) { + if (writemask2 & (1 << i)) + dev->vram[addr | i] = (vall.b[i] & svga->gdcreg[8]) | svga->latch.b[i]; + } + break; + case 0x18: /* XOR */ + for (i = 0; i < count; i++) { + if (writemask2 & (1 << i)) + dev->vram[addr | i] = (vall.b[i] & svga->gdcreg[8]) ^ svga->latch.b[i]; + } + break; + + default: + break; + } + + if (reset_wm) + svga->gdcreg[8] = wm; +} + +static void +mach32_write(uint32_t addr, uint8_t val, void *priv) +{ + mach_t *mach = (mach_t *) priv; + svga_t *svga = &mach->svga; + + addr = (addr & svga->banked_mask) + svga->write_bank; + mach32_write_linear(addr, val, svga); +} + +static void +mach32_writew(uint32_t addr, uint16_t val, void *priv) +{ + mach_t *mach = (mach_t *) priv; + svga_t *svga = &mach->svga; + + addr = (addr & svga->banked_mask) + svga->write_bank; + mach32_write_linear(addr, val & 0xff, svga); + mach32_write_linear(addr + 1, val >> 8, svga); +} + +static void +mach32_writel(uint32_t addr, uint32_t val, void *priv) +{ + mach_t *mach = (mach_t *) priv; + svga_t *svga = &mach->svga; + + addr = (addr & svga->banked_mask) + svga->write_bank; + mach32_write_linear(addr, val & 0xff, svga); + mach32_write_linear(addr + 1, val >> 8, svga); + mach32_write_linear(addr + 2, val >> 16, svga); + mach32_write_linear(addr + 3, val >> 24, svga); +} + +static uint8_t +mach32_read_linear(uint32_t addr, void *priv) +{ + svga_t *svga = (svga_t *) priv; + const ibm8514_t *dev = (ibm8514_t *) svga->dev8514; + uint32_t latch_addr = 0; + int readplane = svga->readplane; + uint8_t count; + uint8_t temp; + uint8_t ret; + + cycles -= svga->monitor->mon_video_timing_read_b; + + count = 2; + + latch_addr = (addr << count) & svga->decode_mask; + count = (1 << count); + + if ((svga->chain4 && (svga->packed_chain4 || svga->force_old_addr)) || svga->fb_only) { + addr &= svga->decode_mask; + if (addr >= dev->vram_size) + return 0xff; + latch_addr = (addr & dev->vram_mask) & ~3; + for (uint8_t i = 0; i < count; i++) + svga->latch.b[i] = dev->vram[latch_addr | i]; + return dev->vram[addr & dev->vram_mask]; + } else if (svga->chain4 && !svga->force_old_addr) { + readplane = addr & 3; + addr = ((addr & 0xfffc) << 2) | ((addr & 0x30000) >> 14) | (addr & ~0x3ffff); + } else if (svga->chain2_read) { + readplane = (readplane & 2) | (addr & 1); + addr &= ~1; + addr &= dev->vram_mask; + } else { + addr &= svga->decode_mask; + if (addr >= dev->vram_size) + return 0xff; + latch_addr = (addr & dev->vram_mask) & ~3; + for (uint8_t i = 0; i < count; i++) + svga->latch.b[i] = dev->vram[latch_addr | i]; + return dev->vram[addr & dev->vram_mask]; + } + + addr &= svga->decode_mask; + + /* standard VGA latched access */ + if (latch_addr >= dev->vram_size) { + for (uint8_t i = 0; i < count; i++) + svga->latch.b[i] = 0xff; + } else { + latch_addr &= dev->vram_mask; + + for (uint8_t i = 0; i < count; i++) + svga->latch.b[i] = dev->vram[latch_addr | i]; + } + + if (addr >= dev->vram_size) + return 0xff; + + addr &= dev->vram_mask; + + if (svga->readmode) { + temp = 0xff; + + for (uint8_t pixel = 0; pixel < 8; pixel++) { + for (uint8_t plane = 0; plane < count; plane++) { + if (svga->colournocare & (1 << plane)) { + /* If we care about a plane, and the pixel has a mismatch on it, clear its bit. */ + if (((svga->latch.b[plane] >> pixel) & 1) != ((svga->colourcompare >> plane) & 1)) + temp &= ~(1 << pixel); + } + } + } + + ret = temp; + } else + ret = dev->vram[addr | readplane]; + + return ret; +} + +static uint8_t +mach32_read(uint32_t addr, void *priv) +{ + mach_t *mach = (mach_t *) priv; + svga_t *svga = &mach->svga; + uint8_t ret; + + addr = (addr & svga->banked_mask) + svga->read_bank; + ret = mach32_read_linear(addr, svga); + return ret; +} + +static uint16_t +mach32_readw(uint32_t addr, void *priv) +{ + mach_t *mach = (mach_t *) priv; + svga_t *svga = &mach->svga; + uint16_t ret; + + addr = (addr & svga->banked_mask) + svga->read_bank; + ret = mach32_read_linear(addr, svga); + ret |= (mach32_read_linear(addr + 1, svga) << 8); + return ret; +} + +static uint32_t +mach32_readl(uint32_t addr, void *priv) +{ + mach_t *mach = (mach_t *) priv; + svga_t *svga = &mach->svga; + uint32_t ret; + + addr = (addr & svga->banked_mask) + svga->read_bank; + ret = mach32_read_linear(addr, svga); + ret |= (mach32_read_linear(addr + 1, svga) << 8); + ret |= (mach32_read_linear(addr + 2, svga) << 16); + ret |= (mach32_read_linear(addr + 3, svga) << 24); + return ret; +} + +static void +mach32_ap_writeb(uint32_t addr, uint8_t val, void *priv) +{ + mach_t *mach = (mach_t *) priv; + svga_t *svga = &mach->svga; + uint8_t port_dword = addr & 0xfc; + + if (((mach->local_cntl & 0x20) || (mach->pci_cntl_reg & 0x80)) && + ((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); + mach32_write_linear(addr, val, svga); + } +} + +static void +mach32_ap_writew(uint32_t addr, uint16_t val, void *priv) +{ + mach_t *mach = (mach_t *) priv; + svga_t *svga = &mach->svga; + uint8_t port_dword = addr & 0xfc; + + if (((mach->local_cntl & 0x20) || (mach->pci_cntl_reg & 0x80)) && + ((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); + mach32_write_linear(addr, val & 0xff, svga); + mach32_write_linear(addr + 1, val >> 8, svga); + } +} + +static void +mach32_ap_writel(uint32_t addr, uint32_t val, void *priv) +{ + mach_t *mach = (mach_t *) priv; + svga_t *svga = &mach->svga; + uint8_t port_dword = addr & 0xfc; + + if (((mach->local_cntl & 0x20) || (mach->pci_cntl_reg & 0x80)) && + ((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.\n", addr); + mach32_write_linear(addr, val & 0xff, svga); + mach32_write_linear(addr + 1, val >> 8, svga); + mach32_write_linear(addr + 2, val >> 16, svga); + mach32_write_linear(addr + 3, val >> 24, svga); + } +} + +static uint8_t +mach32_ap_readb(uint32_t addr, void *priv) +{ + mach_t *mach = (mach_t *) priv; + svga_t *svga = &mach->svga; + uint8_t temp; + uint8_t port_dword = addr & 0xfc; + + if (((mach->local_cntl & 0x20) || (mach->pci_cntl_reg & 0x80)) && + ((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 = mach32_read_linear(addr, svga); + + return temp; +} + +static uint16_t +mach32_ap_readw(uint32_t addr, void *priv) +{ + mach_t *mach = (mach_t *) priv; + svga_t *svga = &mach->svga; + uint16_t temp; + uint8_t port_dword = addr & 0xfc; + + if (((mach->local_cntl & 0x20) || (mach->pci_cntl_reg & 0x80)) && + ((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 = mach32_read_linear(addr, svga); + temp |= (mach32_read_linear(addr + 1, svga) << 8); + } + + return temp; +} + +static uint32_t +mach32_ap_readl(uint32_t addr, void *priv) +{ + mach_t *mach = (mach_t *) priv; + svga_t *svga = &mach->svga; + uint32_t temp; + uint8_t port_dword = addr & 0xfc; + + if (((mach->local_cntl & 0x20) || (mach->pci_cntl_reg & 0x80)) && + ((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 = mach32_read_linear(addr, svga); + temp |= (mach32_read_linear(addr + 1, svga) << 8); + temp |= (mach32_read_linear(addr + 2, svga) << 16); + temp |= (mach32_read_linear(addr + 3, svga) << 24); + } + + return temp; +} + +static void +mach32_updatemapping(mach_t *mach) +{ + svga_t *svga = &mach->svga; + ibm8514_t *dev = (ibm8514_t *) svga->dev8514; + + 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; + } 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; + + default: + 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); + } + } else { + mach->ap_size = 4; + mem_mapping_disable(&mach->mmio_linear_mapping); + } + if (mach->ext_on && (dev->local >= 2) && mach->ati_mode) { + mem_mapping_set_handler(&svga->mapping, mach32_read, mach32_readw, mach32_readl, mach32_write, mach32_writew, mach32_writel); + mem_mapping_set_p(&svga->mapping, mach); + } else { + 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); + } +} + +static void +mach32_hwcursor_draw(svga_t *svga, int displine) +{ + const mach_t *mach = (mach_t *) svga->priv; + ibm8514_t *dev = (ibm8514_t *) svga->dev8514; + uint16_t dat; + int comb; + int offset = dev->hwcursor_latch.x - dev->hwcursor_latch.xoff; + uint32_t color0; + uint32_t color1; + + if (dev->accel_bpp == 8) { + color0 = dev->pallook[mach->cursor_col_0]; + color1 = dev->pallook[mach->cursor_col_1]; + } else if (dev->accel_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]; + } else if (dev->accel_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]; + } 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); + } + + if (dev->interlace && dev->hwcursor_oddeven) + dev->hwcursor_latch.addr += 16; + + for (int x = 0; x < 64; x += 8) { + dat = dev->vram[dev->hwcursor_latch.addr & dev->vram_mask] | (dev->vram[(dev->hwcursor_latch.addr + 1) & dev->vram_mask] << 8); + for (int xx = 0; xx < 8; xx++) { + comb = (dat >> (xx << 1)) & 0x03; + if (offset >= dev->hwcursor_latch.x) { + switch (comb) { + case 0: + (svga->monitor->target_buffer->line[displine])[offset + svga->x_add] = color0; + break; + case 1: + (svga->monitor->target_buffer->line[displine])[offset + svga->x_add] = color1; + break; + case 3: + (svga->monitor->target_buffer->line[displine])[offset + svga->x_add] ^= 0xffffff; + break; + + default: + break; + } + } + offset++; + } + dev->hwcursor_latch.addr += 2; + } + if (dev->interlace && !dev->hwcursor_oddeven) + dev->hwcursor_latch.addr += 16; +} + +#if 0 +static void +mach_io_remove(mach_t *mach) +{ + io_removehandler(0x2e8, 0x0002, mach_accel_inb, mach_accel_inw, mach_accel_inl, mach_accel_outb, mach_accel_outw, mach_accel_outl, mach); + io_removehandler(0x6e8, 0x0002, mach_accel_inb, mach_accel_inw, mach_accel_inl, mach_accel_outb, mach_accel_outw, mach_accel_outl, mach); + io_removehandler(0xae8, 0x0002, mach_accel_inb, mach_accel_inw, mach_accel_inl, mach_accel_outb, mach_accel_outw, mach_accel_outl, mach); + io_removehandler(0xee8, 0x0002, mach_accel_inb, mach_accel_inw, mach_accel_inl, mach_accel_outb, mach_accel_outw, mach_accel_outl, mach); + io_removehandler(0x12e8, 0x0002, mach_accel_inb, mach_accel_inw, mach_accel_inl, mach_accel_outb, mach_accel_outw, mach_accel_outl, mach); + io_removehandler(0x16e8, 0x0002, mach_accel_inb, mach_accel_inw, mach_accel_inl, mach_accel_outb, mach_accel_outw, mach_accel_outl, mach); + io_removehandler(0x1ae8, 0x0002, mach_accel_inb, mach_accel_inw, mach_accel_inl, mach_accel_outb, mach_accel_outw, mach_accel_outl, mach); + io_removehandler(0x1ee8, 0x0002, mach_accel_inb, mach_accel_inw, mach_accel_inl, mach_accel_outb, mach_accel_outw, mach_accel_outl, mach); + io_removehandler(0x22e8, 0x0002, mach_accel_inb, mach_accel_inw, mach_accel_inl, mach_accel_outb, mach_accel_outw, mach_accel_outl, mach); + io_removehandler(0x26e8, 0x0002, mach_accel_inb, mach_accel_inw, mach_accel_inl, mach_accel_outb, mach_accel_outw, mach_accel_outl, mach); + io_removehandler(0x2ee8, 0x0002, mach_accel_inb, mach_accel_inw, mach_accel_inl, mach_accel_outb, mach_accel_outw, mach_accel_outl, mach); + io_removehandler(0x42e8, 0x0002, mach_accel_inb, mach_accel_inw, mach_accel_inl, mach_accel_outb, mach_accel_outw, mach_accel_outl, mach); + io_removehandler(0x4ae8, 0x0002, mach_accel_inb, mach_accel_inw, mach_accel_inl, mach_accel_outb, mach_accel_outw, mach_accel_outl, mach); + io_removehandler(0x52e8, 0x0002, mach_accel_inb, mach_accel_inw, mach_accel_inl, mach_accel_outb, mach_accel_outw, mach_accel_outl, mach); + io_removehandler(0x56e8, 0x0002, mach_accel_inb, mach_accel_inw, mach_accel_inl, mach_accel_outb, mach_accel_outw, mach_accel_outl, mach); + io_removehandler(0x5ae8, 0x0002, mach_accel_inb, mach_accel_inw, mach_accel_inl, mach_accel_outb, mach_accel_outw, mach_accel_outl, mach); + io_removehandler(0x5ee8, 0x0002, mach_accel_inb, mach_accel_inw, mach_accel_inl, mach_accel_outb, mach_accel_outw, mach_accel_outl, mach); + io_removehandler(0x82e8, 0x0002, mach_accel_inb, mach_accel_inw, mach_accel_inl, mach_accel_outb, mach_accel_outw, mach_accel_outl, mach); + io_removehandler(0x86e8, 0x0002, mach_accel_inb, mach_accel_inw, mach_accel_inl, mach_accel_outb, mach_accel_outw, mach_accel_outl, mach); + io_removehandler(0x8ae8, 0x0002, mach_accel_inb, mach_accel_inw, mach_accel_inl, mach_accel_outb, mach_accel_outw, mach_accel_outl, mach); + io_removehandler(0x8ee8, 0x0002, mach_accel_inb, mach_accel_inw, mach_accel_inl, mach_accel_outb, mach_accel_outw, mach_accel_outl, mach); + io_removehandler(0x92e8, 0x0002, mach_accel_inb, mach_accel_inw, mach_accel_inl, mach_accel_outb, mach_accel_outw, mach_accel_outl, mach); + io_removehandler(0x96e8, 0x0002, mach_accel_inb, mach_accel_inw, mach_accel_inl, mach_accel_outb, mach_accel_outw, mach_accel_outl, mach); + io_removehandler(0x9ae8, 0x0002, mach_accel_inb, mach_accel_inw, mach_accel_inl, mach_accel_outb, mach_accel_outw, mach_accel_outl, mach); + io_removehandler(0x9ee8, 0x0002, mach_accel_inb, mach_accel_inw, mach_accel_inl, mach_accel_outb, mach_accel_outw, mach_accel_outl, mach); + io_removehandler(0xa2e8, 0x0002, mach_accel_inb, mach_accel_inw, mach_accel_inl, mach_accel_outb, mach_accel_outw, mach_accel_outl, mach); + io_removehandler(0xa6e8, 0x0002, mach_accel_inb, mach_accel_inw, mach_accel_inl, mach_accel_outb, mach_accel_outw, mach_accel_outl, mach); + io_removehandler(0xaae8, 0x0002, mach_accel_inb, mach_accel_inw, mach_accel_inl, mach_accel_outb, mach_accel_outw, mach_accel_outl, mach); + io_removehandler(0xaee8, 0x0002, mach_accel_inb, mach_accel_inw, mach_accel_inl, mach_accel_outb, mach_accel_outw, mach_accel_outl, mach); + io_removehandler(0xb2e8, 0x0002, mach_accel_inb, mach_accel_inw, mach_accel_inl, mach_accel_outb, mach_accel_outw, mach_accel_outl, mach); + io_removehandler(0xb6e8, 0x0002, mach_accel_inb, mach_accel_inw, mach_accel_inl, mach_accel_outb, mach_accel_outw, mach_accel_outl, mach); + io_removehandler(0xbae8, 0x0002, mach_accel_inb, mach_accel_inw, mach_accel_inl, mach_accel_outb, mach_accel_outw, mach_accel_outl, mach); + io_removehandler(0xbee8, 0x0002, mach_accel_inb, mach_accel_inw, mach_accel_inl, mach_accel_outb, mach_accel_outw, mach_accel_outl, mach); + io_removehandler(0xe2e8, 0x0002, mach_accel_inb, mach_accel_inw, mach_accel_inl, mach_accel_outb, mach_accel_outw, mach_accel_outl, mach); + + io_removehandler(0xc2e8, 0x0002, mach_accel_inb, mach_accel_inw, mach_accel_inl, mach_accel_outb, mach_accel_outw, mach_accel_outl, mach); + io_removehandler(0xc6e8, 0x0002, mach_accel_inb, mach_accel_inw, mach_accel_inl, mach_accel_outb, mach_accel_outw, mach_accel_outl, mach); + io_removehandler(0xcae8, 0x0002, mach_accel_inb, mach_accel_inw, mach_accel_inl, mach_accel_outb, mach_accel_outw, mach_accel_outl, mach); + io_removehandler(0xcee8, 0x0002, mach_accel_inb, mach_accel_inw, mach_accel_inl, mach_accel_outb, mach_accel_outw, mach_accel_outl, mach); + io_removehandler(0xd2e8, 0x0002, mach_accel_inb, mach_accel_inw, mach_accel_inl, mach_accel_outb, mach_accel_outw, mach_accel_outl, mach); + io_removehandler(0xd6e8, 0x0002, mach_accel_inb, mach_accel_inw, mach_accel_inl, mach_accel_outb, mach_accel_outw, mach_accel_outl, mach); + io_removehandler(0xdae8, 0x0002, mach_accel_inb, mach_accel_inw, mach_accel_inl, mach_accel_outb, mach_accel_outw, mach_accel_outl, mach); + io_removehandler(0xdee8, 0x0002, mach_accel_inb, mach_accel_inw, mach_accel_inl, mach_accel_outb, mach_accel_outw, mach_accel_outl, mach); + io_removehandler(0xe6e8, 0x0002, mach_accel_inb, mach_accel_inw, mach_accel_inl, mach_accel_outb, mach_accel_outw, mach_accel_outl, mach); + io_removehandler(0xeae8, 0x0002, mach_accel_inb, mach_accel_inw, mach_accel_inl, mach_accel_outb, mach_accel_outw, mach_accel_outl, mach); + io_removehandler(0xeee8, 0x0002, mach_accel_inb, mach_accel_inw, mach_accel_inl, mach_accel_outb, mach_accel_outw, mach_accel_outl, mach); + io_removehandler(0xf2e8, 0x0002, mach_accel_inb, mach_accel_inw, mach_accel_inl, mach_accel_outb, mach_accel_outw, mach_accel_outl, mach); + io_removehandler(0xf6e8, 0x0002, mach_accel_inb, mach_accel_inw, mach_accel_inl, mach_accel_outb, mach_accel_outw, mach_accel_outl, mach); + io_removehandler(0xfae8, 0x0002, mach_accel_inb, mach_accel_inw, mach_accel_inl, mach_accel_outb, mach_accel_outw, mach_accel_outl, mach); + io_removehandler(0xfee8, 0x0002, mach_accel_inb, mach_accel_inw, mach_accel_inl, mach_accel_outb, mach_accel_outw, mach_accel_outl, mach); + + io_removehandler(0x02ee, 0x0002, mach_accel_inb, mach_accel_inw, mach_accel_inl, mach_accel_outb, mach_accel_outw, mach_accel_outl, mach); + io_removehandler(0x06ee, 0x0002, mach_accel_inb, mach_accel_inw, mach_accel_inl, mach_accel_outb, mach_accel_outw, mach_accel_outl, mach); + io_removehandler(0x0aee, 0x0002, mach_accel_inb, mach_accel_inw, mach_accel_inl, mach_accel_outb, mach_accel_outw, mach_accel_outl, mach); + io_removehandler(0x0eee, 0x0002, mach_accel_inb, mach_accel_inw, mach_accel_inl, mach_accel_outb, mach_accel_outw, mach_accel_outl, mach); + io_removehandler(0x12ee, 0x0002, mach_accel_inb, mach_accel_inw, mach_accel_inl, mach_accel_outb, mach_accel_outw, mach_accel_outl, mach); + io_removehandler(0x16ee, 0x0002, mach_accel_inb, mach_accel_inw, mach_accel_inl, mach_accel_outb, mach_accel_outw, mach_accel_outl, mach); + io_removehandler(0x1aee, 0x0002, mach_accel_inb, mach_accel_inw, mach_accel_inl, mach_accel_outb, mach_accel_outw, mach_accel_outl, mach); + io_removehandler(0x1eee, 0x0002, mach_accel_inb, mach_accel_inw, mach_accel_inl, mach_accel_outb, mach_accel_outw, mach_accel_outl, mach); + io_removehandler(0x22ee, 0x0002, mach_accel_inb, mach_accel_inw, mach_accel_inl, mach_accel_outb, mach_accel_outw, mach_accel_outl, mach); + io_removehandler(0x26ee, 0x0002, mach_accel_inb, mach_accel_inw, mach_accel_inl, mach_accel_outb, mach_accel_outw, mach_accel_outl, mach); + io_removehandler(0x2aee, 0x0002, mach_accel_inb, mach_accel_inw, mach_accel_inl, mach_accel_outb, mach_accel_outw, mach_accel_outl, mach); + io_removehandler(0x2eee, 0x0002, mach_accel_inb, mach_accel_inw, mach_accel_inl, mach_accel_outb, mach_accel_outw, mach_accel_outl, mach); + io_removehandler(0x32ee, 0x0002, mach_accel_inb, mach_accel_inw, mach_accel_inl, mach_accel_outb, mach_accel_outw, mach_accel_outl, mach); + io_removehandler(0x36ee, 0x0002, mach_accel_inb, mach_accel_inw, mach_accel_inl, mach_accel_outb, mach_accel_outw, mach_accel_outl, mach); + io_removehandler(0x3aee, 0x0002, mach_accel_inb, mach_accel_inw, mach_accel_inl, mach_accel_outb, mach_accel_outw, mach_accel_outl, mach); + io_removehandler(0x3eee, 0x0002, mach_accel_inb, mach_accel_inw, mach_accel_inl, mach_accel_outb, mach_accel_outw, mach_accel_outl, mach); + io_removehandler(0x42ee, 0x0002, mach_accel_inb, mach_accel_inw, mach_accel_inl, mach_accel_outb, mach_accel_outw, mach_accel_outl, mach); + io_removehandler(0x46ee, 0x0002, mach_accel_inb, mach_accel_inw, mach_accel_inl, mach_accel_outb, mach_accel_outw, mach_accel_outl, mach); + io_removehandler(0x4aee, 0x0002, mach_accel_inb, mach_accel_inw, mach_accel_inl, mach_accel_outb, mach_accel_outw, mach_accel_outl, mach); + io_removehandler(0x52ee, 0x0002, mach_accel_inb, mach_accel_inw, mach_accel_inl, mach_accel_outb, mach_accel_outw, mach_accel_outl, mach); + io_removehandler(0x56ee, 0x0002, mach_accel_inb, mach_accel_inw, mach_accel_inl, mach_accel_outb, mach_accel_outw, mach_accel_outl, mach); + io_removehandler(0x5aee, 0x0002, mach_accel_inb, mach_accel_inw, mach_accel_inl, mach_accel_outb, mach_accel_outw, mach_accel_outl, mach); + io_removehandler(0x5eee, 0x0002, mach_accel_inb, mach_accel_inw, mach_accel_inl, mach_accel_outb, mach_accel_outw, mach_accel_outl, mach); + io_removehandler(0x62ee, 0x0002, mach_accel_inb, mach_accel_inw, mach_accel_inl, mach_accel_outb, mach_accel_outw, mach_accel_outl, mach); + io_removehandler(0x66ee, 0x0002, mach_accel_inb, mach_accel_inw, mach_accel_inl, mach_accel_outb, mach_accel_outw, mach_accel_outl, mach); + io_removehandler(0x6aee, 0x0002, mach_accel_inb, mach_accel_inw, mach_accel_inl, mach_accel_outb, mach_accel_outw, mach_accel_outl, mach); + io_removehandler(0x6eee, 0x0002, mach_accel_inb, mach_accel_inw, mach_accel_inl, mach_accel_outb, mach_accel_outw, mach_accel_outl, mach); + io_removehandler(0x72ee, 0x0002, mach_accel_inb, mach_accel_inw, mach_accel_inl, mach_accel_outb, mach_accel_outw, mach_accel_outl, mach); + io_removehandler(0x76ee, 0x0002, mach_accel_inb, mach_accel_inw, mach_accel_inl, mach_accel_outb, mach_accel_outw, mach_accel_outl, mach); + io_removehandler(0x7aee, 0x0002, mach_accel_inb, mach_accel_inw, mach_accel_inl, mach_accel_outb, mach_accel_outw, mach_accel_outl, mach); + io_removehandler(0x7eee, 0x0002, mach_accel_inb, mach_accel_inw, mach_accel_inl, mach_accel_outb, mach_accel_outw, mach_accel_outl, mach); + io_removehandler(0x82ee, 0x0002, mach_accel_inb, mach_accel_inw, mach_accel_inl, mach_accel_outb, mach_accel_outw, mach_accel_outl, mach); + io_removehandler(0x8eee, 0x0002, mach_accel_inb, mach_accel_inw, mach_accel_inl, mach_accel_outb, mach_accel_outw, mach_accel_outl, mach); + io_removehandler(0x92ee, 0x0002, mach_accel_inb, mach_accel_inw, mach_accel_inl, mach_accel_outb, mach_accel_outw, mach_accel_outl, mach); + io_removehandler(0x96ee, 0x0002, mach_accel_inb, mach_accel_inw, mach_accel_inl, mach_accel_outb, mach_accel_outw, mach_accel_outl, mach); + io_removehandler(0x9aee, 0x0002, mach_accel_inb, mach_accel_inw, mach_accel_inl, mach_accel_outb, mach_accel_outw, mach_accel_outl, mach); + io_removehandler(0xa2ee, 0x0002, mach_accel_inb, mach_accel_inw, mach_accel_inl, mach_accel_outb, mach_accel_outw, mach_accel_outl, mach); + io_removehandler(0xa6ee, 0x0002, mach_accel_inb, mach_accel_inw, mach_accel_inl, mach_accel_outb, mach_accel_outw, mach_accel_outl, mach); + io_removehandler(0xaaee, 0x0002, mach_accel_inb, mach_accel_inw, mach_accel_inl, mach_accel_outb, mach_accel_outw, mach_accel_outl, mach); + io_removehandler(0xaeee, 0x0002, mach_accel_inb, mach_accel_inw, mach_accel_inl, mach_accel_outb, mach_accel_outw, mach_accel_outl, mach); + io_removehandler(0xb2ee, 0x0002, mach_accel_inb, mach_accel_inw, mach_accel_inl, mach_accel_outb, mach_accel_outw, mach_accel_outl, mach); + io_removehandler(0xb6ee, 0x0002, mach_accel_inb, mach_accel_inw, mach_accel_inl, mach_accel_outb, mach_accel_outw, mach_accel_outl, mach); + io_removehandler(0xbaee, 0x0002, mach_accel_inb, mach_accel_inw, mach_accel_inl, mach_accel_outb, mach_accel_outw, mach_accel_outl, mach); + io_removehandler(0xbeee, 0x0002, mach_accel_inb, mach_accel_inw, mach_accel_inl, mach_accel_outb, mach_accel_outw, mach_accel_outl, mach); + io_removehandler(0xc2ee, 0x0002, mach_accel_inb, mach_accel_inw, mach_accel_inl, mach_accel_outb, mach_accel_outw, mach_accel_outl, mach); + io_removehandler(0xc6ee, 0x0002, mach_accel_inb, mach_accel_inw, mach_accel_inl, mach_accel_outb, mach_accel_outw, mach_accel_outl, mach); + io_removehandler(0xcaee, 0x0002, mach_accel_inb, mach_accel_inw, mach_accel_inl, mach_accel_outb, mach_accel_outw, mach_accel_outl, mach); + io_removehandler(0xceee, 0x0002, mach_accel_inb, mach_accel_inw, mach_accel_inl, mach_accel_outb, mach_accel_outw, mach_accel_outl, mach); + io_removehandler(0xd2ee, 0x0002, mach_accel_inb, mach_accel_inw, mach_accel_inl, mach_accel_outb, mach_accel_outw, mach_accel_outl, mach); + io_removehandler(0xd6ee, 0x0002, mach_accel_inb, mach_accel_inw, mach_accel_inl, mach_accel_outb, mach_accel_outw, mach_accel_outl, mach); + io_removehandler(0xdaee, 0x0002, mach_accel_inb, mach_accel_inw, mach_accel_inl, mach_accel_outb, mach_accel_outw, mach_accel_outl, mach); + io_removehandler(0xdeee, 0x0002, mach_accel_inb, mach_accel_inw, mach_accel_inl, mach_accel_outb, mach_accel_outw, mach_accel_outl, mach); + io_removehandler(0xe2ee, 0x0002, mach_accel_inb, mach_accel_inw, mach_accel_inl, mach_accel_outb, mach_accel_outw, mach_accel_outl, mach); + io_removehandler(0xe6ee, 0x0002, mach_accel_inb, mach_accel_inw, mach_accel_inl, mach_accel_outb, mach_accel_outw, mach_accel_outl, mach); + io_removehandler(0xeeee, 0x0002, mach_accel_inb, mach_accel_inw, mach_accel_inl, mach_accel_outb, mach_accel_outw, mach_accel_outl, mach); + io_removehandler(0xf2ee, 0x0002, mach_accel_inb, mach_accel_inw, mach_accel_inl, mach_accel_outb, mach_accel_outw, mach_accel_outl, mach); + io_removehandler(0xfaee, 0x0002, mach_accel_inb, mach_accel_inw, mach_accel_inl, mach_accel_outb, mach_accel_outw, mach_accel_outl, mach); + io_removehandler(0xfeee, 0x0002, mach_accel_inb, mach_accel_inw, mach_accel_inl, mach_accel_outb, mach_accel_outw, mach_accel_outl, mach); +} +#endif + +static void +mach_io_set(mach_t *mach) +{ + io_sethandler(0x2e8, 0x0002, mach_accel_inb, mach_accel_inw, mach_accel_inl, mach_accel_outb, mach_accel_outw, mach_accel_outl, mach); + io_sethandler(0x6e8, 0x0002, mach_accel_inb, mach_accel_inw, mach_accel_inl, mach_accel_outb, mach_accel_outw, mach_accel_outl, mach); + io_sethandler(0xae8, 0x0002, mach_accel_inb, mach_accel_inw, mach_accel_inl, mach_accel_outb, mach_accel_outw, mach_accel_outl, mach); + io_sethandler(0xee8, 0x0002, mach_accel_inb, mach_accel_inw, mach_accel_inl, mach_accel_outb, mach_accel_outw, mach_accel_outl, mach); + io_sethandler(0x12e8, 0x0002, mach_accel_inb, mach_accel_inw, mach_accel_inl, mach_accel_outb, mach_accel_outw, mach_accel_outl, mach); + io_sethandler(0x16e8, 0x0002, mach_accel_inb, mach_accel_inw, mach_accel_inl, mach_accel_outb, mach_accel_outw, mach_accel_outl, mach); + io_sethandler(0x1ae8, 0x0002, mach_accel_inb, mach_accel_inw, mach_accel_inl, mach_accel_outb, mach_accel_outw, mach_accel_outl, mach); + io_sethandler(0x1ee8, 0x0002, mach_accel_inb, mach_accel_inw, mach_accel_inl, mach_accel_outb, mach_accel_outw, mach_accel_outl, mach); + io_sethandler(0x22e8, 0x0002, mach_accel_inb, mach_accel_inw, mach_accel_inl, mach_accel_outb, mach_accel_outw, mach_accel_outl, mach); + io_sethandler(0x26e8, 0x0002, mach_accel_inb, mach_accel_inw, mach_accel_inl, mach_accel_outb, mach_accel_outw, mach_accel_outl, mach); + io_sethandler(0x2ee8, 0x0002, mach_accel_inb, mach_accel_inw, mach_accel_inl, mach_accel_outb, mach_accel_outw, mach_accel_outl, mach); + io_sethandler(0x42e8, 0x0002, mach_accel_inb, mach_accel_inw, mach_accel_inl, mach_accel_outb, mach_accel_outw, mach_accel_outl, mach); + io_sethandler(0x4ae8, 0x0002, mach_accel_inb, mach_accel_inw, mach_accel_inl, mach_accel_outb, mach_accel_outw, mach_accel_outl, mach); + io_sethandler(0x52e8, 0x0002, mach_accel_inb, mach_accel_inw, mach_accel_inl, mach_accel_outb, mach_accel_outw, mach_accel_outl, mach); + io_sethandler(0x56e8, 0x0002, mach_accel_inb, mach_accel_inw, mach_accel_inl, mach_accel_outb, mach_accel_outw, mach_accel_outl, mach); + io_sethandler(0x5ae8, 0x0002, mach_accel_inb, mach_accel_inw, mach_accel_inl, mach_accel_outb, mach_accel_outw, mach_accel_outl, mach); + io_sethandler(0x5ee8, 0x0002, mach_accel_inb, mach_accel_inw, mach_accel_inl, mach_accel_outb, mach_accel_outw, mach_accel_outl, mach); + io_sethandler(0x82e8, 0x0002, mach_accel_inb, mach_accel_inw, mach_accel_inl, mach_accel_outb, mach_accel_outw, mach_accel_outl, mach); + io_sethandler(0x86e8, 0x0002, mach_accel_inb, mach_accel_inw, mach_accel_inl, mach_accel_outb, mach_accel_outw, mach_accel_outl, mach); + io_sethandler(0x8ae8, 0x0002, mach_accel_inb, mach_accel_inw, mach_accel_inl, mach_accel_outb, mach_accel_outw, mach_accel_outl, mach); + io_sethandler(0x8ee8, 0x0002, mach_accel_inb, mach_accel_inw, mach_accel_inl, mach_accel_outb, mach_accel_outw, mach_accel_outl, mach); + io_sethandler(0x92e8, 0x0002, mach_accel_inb, mach_accel_inw, mach_accel_inl, mach_accel_outb, mach_accel_outw, mach_accel_outl, mach); + io_sethandler(0x96e8, 0x0002, mach_accel_inb, mach_accel_inw, mach_accel_inl, mach_accel_outb, mach_accel_outw, mach_accel_outl, mach); + io_sethandler(0x9ae8, 0x0002, mach_accel_inb, mach_accel_inw, mach_accel_inl, mach_accel_outb, mach_accel_outw, mach_accel_outl, mach); + io_sethandler(0x9ee8, 0x0002, mach_accel_inb, mach_accel_inw, mach_accel_inl, mach_accel_outb, mach_accel_outw, mach_accel_outl, mach); + io_sethandler(0xa2e8, 0x0002, mach_accel_inb, mach_accel_inw, mach_accel_inl, mach_accel_outb, mach_accel_outw, mach_accel_outl, mach); + io_sethandler(0xa6e8, 0x0002, mach_accel_inb, mach_accel_inw, mach_accel_inl, mach_accel_outb, mach_accel_outw, mach_accel_outl, mach); + io_sethandler(0xaae8, 0x0002, mach_accel_inb, mach_accel_inw, mach_accel_inl, mach_accel_outb, mach_accel_outw, mach_accel_outl, mach); + io_sethandler(0xaee8, 0x0002, mach_accel_inb, mach_accel_inw, mach_accel_inl, mach_accel_outb, mach_accel_outw, mach_accel_outl, mach); + io_sethandler(0xb2e8, 0x0002, mach_accel_inb, mach_accel_inw, mach_accel_inl, mach_accel_outb, mach_accel_outw, mach_accel_outl, mach); + io_sethandler(0xb6e8, 0x0002, mach_accel_inb, mach_accel_inw, mach_accel_inl, mach_accel_outb, mach_accel_outw, mach_accel_outl, mach); + io_sethandler(0xbae8, 0x0002, mach_accel_inb, mach_accel_inw, mach_accel_inl, mach_accel_outb, mach_accel_outw, mach_accel_outl, mach); + io_sethandler(0xbee8, 0x0002, mach_accel_inb, mach_accel_inw, mach_accel_inl, mach_accel_outb, mach_accel_outw, mach_accel_outl, mach); + io_sethandler(0xe2e8, 0x0002, mach_accel_inb, mach_accel_inw, mach_accel_inl, mach_accel_outb, mach_accel_outw, mach_accel_outl, mach); + + io_sethandler(0xc2e8, 0x0002, mach_accel_inb, mach_accel_inw, mach_accel_inl, mach_accel_outb, mach_accel_outw, mach_accel_outl, mach); + io_sethandler(0xc6e8, 0x0002, mach_accel_inb, mach_accel_inw, mach_accel_inl, mach_accel_outb, mach_accel_outw, mach_accel_outl, mach); + io_sethandler(0xcae8, 0x0002, mach_accel_inb, mach_accel_inw, mach_accel_inl, mach_accel_outb, mach_accel_outw, mach_accel_outl, mach); + io_sethandler(0xcee8, 0x0002, mach_accel_inb, mach_accel_inw, mach_accel_inl, mach_accel_outb, mach_accel_outw, mach_accel_outl, mach); + io_sethandler(0xd2e8, 0x0002, mach_accel_inb, mach_accel_inw, mach_accel_inl, mach_accel_outb, mach_accel_outw, mach_accel_outl, mach); + io_sethandler(0xd6e8, 0x0002, mach_accel_inb, mach_accel_inw, mach_accel_inl, mach_accel_outb, mach_accel_outw, mach_accel_outl, mach); + io_sethandler(0xdae8, 0x0002, mach_accel_inb, mach_accel_inw, mach_accel_inl, mach_accel_outb, mach_accel_outw, mach_accel_outl, mach); + io_sethandler(0xdee8, 0x0002, mach_accel_inb, mach_accel_inw, mach_accel_inl, mach_accel_outb, mach_accel_outw, mach_accel_outl, mach); + io_sethandler(0xe6e8, 0x0002, mach_accel_inb, mach_accel_inw, mach_accel_inl, mach_accel_outb, mach_accel_outw, mach_accel_outl, mach); + io_sethandler(0xeae8, 0x0002, mach_accel_inb, mach_accel_inw, mach_accel_inl, mach_accel_outb, mach_accel_outw, mach_accel_outl, mach); + io_sethandler(0xeee8, 0x0002, mach_accel_inb, mach_accel_inw, mach_accel_inl, mach_accel_outb, mach_accel_outw, mach_accel_outl, mach); + io_sethandler(0xf2e8, 0x0002, mach_accel_inb, mach_accel_inw, mach_accel_inl, mach_accel_outb, mach_accel_outw, mach_accel_outl, mach); + io_sethandler(0xf6e8, 0x0002, mach_accel_inb, mach_accel_inw, mach_accel_inl, mach_accel_outb, mach_accel_outw, mach_accel_outl, mach); + io_sethandler(0xfae8, 0x0002, mach_accel_inb, mach_accel_inw, mach_accel_inl, mach_accel_outb, mach_accel_outw, mach_accel_outl, mach); + io_sethandler(0xfee8, 0x0002, mach_accel_inb, mach_accel_inw, mach_accel_inl, mach_accel_outb, mach_accel_outw, mach_accel_outl, mach); + + io_sethandler(0x02ee, 0x0002, mach_accel_inb, mach_accel_inw, mach_accel_inl, mach_accel_outb, mach_accel_outw, mach_accel_outl, mach); + io_sethandler(0x06ee, 0x0002, mach_accel_inb, mach_accel_inw, mach_accel_inl, mach_accel_outb, mach_accel_outw, mach_accel_outl, mach); + io_sethandler(0x0aee, 0x0002, mach_accel_inb, mach_accel_inw, mach_accel_inl, mach_accel_outb, mach_accel_outw, mach_accel_outl, mach); + io_sethandler(0x0eee, 0x0002, mach_accel_inb, mach_accel_inw, mach_accel_inl, mach_accel_outb, mach_accel_outw, mach_accel_outl, mach); + io_sethandler(0x12ee, 0x0002, mach_accel_inb, mach_accel_inw, mach_accel_inl, mach_accel_outb, mach_accel_outw, mach_accel_outl, mach); + io_sethandler(0x16ee, 0x0002, mach_accel_inb, mach_accel_inw, mach_accel_inl, mach_accel_outb, mach_accel_outw, mach_accel_outl, mach); + io_sethandler(0x1aee, 0x0002, mach_accel_inb, mach_accel_inw, mach_accel_inl, mach_accel_outb, mach_accel_outw, mach_accel_outl, mach); + io_sethandler(0x1eee, 0x0002, mach_accel_inb, mach_accel_inw, mach_accel_inl, mach_accel_outb, mach_accel_outw, mach_accel_outl, mach); + io_sethandler(0x22ee, 0x0002, mach_accel_inb, mach_accel_inw, mach_accel_inl, mach_accel_outb, mach_accel_outw, mach_accel_outl, mach); + io_sethandler(0x26ee, 0x0002, mach_accel_inb, mach_accel_inw, mach_accel_inl, mach_accel_outb, mach_accel_outw, mach_accel_outl, mach); + io_sethandler(0x2aee, 0x0002, mach_accel_inb, mach_accel_inw, mach_accel_inl, mach_accel_outb, mach_accel_outw, mach_accel_outl, mach); + io_sethandler(0x2eee, 0x0002, mach_accel_inb, mach_accel_inw, mach_accel_inl, mach_accel_outb, mach_accel_outw, mach_accel_outl, mach); + io_sethandler(0x32ee, 0x0002, mach_accel_inb, mach_accel_inw, mach_accel_inl, mach_accel_outb, mach_accel_outw, mach_accel_outl, mach); + io_sethandler(0x36ee, 0x0002, mach_accel_inb, mach_accel_inw, mach_accel_inl, mach_accel_outb, mach_accel_outw, mach_accel_outl, mach); + io_sethandler(0x3aee, 0x0002, mach_accel_inb, mach_accel_inw, mach_accel_inl, mach_accel_outb, mach_accel_outw, mach_accel_outl, mach); + io_sethandler(0x3eee, 0x0002, mach_accel_inb, mach_accel_inw, mach_accel_inl, mach_accel_outb, mach_accel_outw, mach_accel_outl, mach); + io_sethandler(0x42ee, 0x0002, mach_accel_inb, mach_accel_inw, mach_accel_inl, mach_accel_outb, mach_accel_outw, mach_accel_outl, mach); + io_sethandler(0x46ee, 0x0002, mach_accel_inb, mach_accel_inw, mach_accel_inl, mach_accel_outb, mach_accel_outw, mach_accel_outl, mach); + io_sethandler(0x4aee, 0x0002, mach_accel_inb, mach_accel_inw, mach_accel_inl, mach_accel_outb, mach_accel_outw, mach_accel_outl, mach); + io_sethandler(0x52ee, 0x0002, mach_accel_inb, mach_accel_inw, mach_accel_inl, mach_accel_outb, mach_accel_outw, mach_accel_outl, mach); + io_sethandler(0x56ee, 0x0002, mach_accel_inb, mach_accel_inw, mach_accel_inl, mach_accel_outb, mach_accel_outw, mach_accel_outl, mach); + io_sethandler(0x5aee, 0x0002, mach_accel_inb, mach_accel_inw, mach_accel_inl, mach_accel_outb, mach_accel_outw, mach_accel_outl, mach); + io_sethandler(0x5eee, 0x0002, mach_accel_inb, mach_accel_inw, mach_accel_inl, mach_accel_outb, mach_accel_outw, mach_accel_outl, mach); + io_sethandler(0x62ee, 0x0002, mach_accel_inb, mach_accel_inw, mach_accel_inl, mach_accel_outb, mach_accel_outw, mach_accel_outl, mach); + io_sethandler(0x66ee, 0x0002, mach_accel_inb, mach_accel_inw, mach_accel_inl, mach_accel_outb, mach_accel_outw, mach_accel_outl, mach); + io_sethandler(0x6aee, 0x0002, mach_accel_inb, mach_accel_inw, mach_accel_inl, mach_accel_outb, mach_accel_outw, mach_accel_outl, mach); + io_sethandler(0x6eee, 0x0002, mach_accel_inb, mach_accel_inw, mach_accel_inl, mach_accel_outb, mach_accel_outw, mach_accel_outl, mach); + io_sethandler(0x72ee, 0x0002, mach_accel_inb, mach_accel_inw, mach_accel_inl, mach_accel_outb, mach_accel_outw, mach_accel_outl, mach); + io_sethandler(0x76ee, 0x0002, mach_accel_inb, mach_accel_inw, mach_accel_inl, mach_accel_outb, mach_accel_outw, mach_accel_outl, mach); + io_sethandler(0x7aee, 0x0002, mach_accel_inb, mach_accel_inw, mach_accel_inl, mach_accel_outb, mach_accel_outw, mach_accel_outl, mach); + io_sethandler(0x7eee, 0x0002, mach_accel_inb, mach_accel_inw, mach_accel_inl, mach_accel_outb, mach_accel_outw, mach_accel_outl, mach); + io_sethandler(0x82ee, 0x0002, mach_accel_inb, mach_accel_inw, mach_accel_inl, mach_accel_outb, mach_accel_outw, mach_accel_outl, mach); + io_sethandler(0x8eee, 0x0002, mach_accel_inb, mach_accel_inw, mach_accel_inl, mach_accel_outb, mach_accel_outw, mach_accel_outl, mach); + io_sethandler(0x92ee, 0x0002, mach_accel_inb, mach_accel_inw, mach_accel_inl, mach_accel_outb, mach_accel_outw, mach_accel_outl, mach); + io_sethandler(0x96ee, 0x0002, mach_accel_inb, mach_accel_inw, mach_accel_inl, mach_accel_outb, mach_accel_outw, mach_accel_outl, mach); + io_sethandler(0x9aee, 0x0002, mach_accel_inb, mach_accel_inw, mach_accel_inl, mach_accel_outb, mach_accel_outw, mach_accel_outl, mach); + io_sethandler(0xa2ee, 0x0002, mach_accel_inb, mach_accel_inw, mach_accel_inl, mach_accel_outb, mach_accel_outw, mach_accel_outl, mach); + io_sethandler(0xa6ee, 0x0002, mach_accel_inb, mach_accel_inw, mach_accel_inl, mach_accel_outb, mach_accel_outw, mach_accel_outl, mach); + io_sethandler(0xaaee, 0x0002, mach_accel_inb, mach_accel_inw, mach_accel_inl, mach_accel_outb, mach_accel_outw, mach_accel_outl, mach); + io_sethandler(0xaeee, 0x0002, mach_accel_inb, mach_accel_inw, mach_accel_inl, mach_accel_outb, mach_accel_outw, mach_accel_outl, mach); + io_sethandler(0xb2ee, 0x0002, mach_accel_inb, mach_accel_inw, mach_accel_inl, mach_accel_outb, mach_accel_outw, mach_accel_outl, mach); + io_sethandler(0xb6ee, 0x0002, mach_accel_inb, mach_accel_inw, mach_accel_inl, mach_accel_outb, mach_accel_outw, mach_accel_outl, mach); + io_sethandler(0xbaee, 0x0002, mach_accel_inb, mach_accel_inw, mach_accel_inl, mach_accel_outb, mach_accel_outw, mach_accel_outl, mach); + io_sethandler(0xbeee, 0x0002, mach_accel_inb, mach_accel_inw, mach_accel_inl, mach_accel_outb, mach_accel_outw, mach_accel_outl, mach); + io_sethandler(0xc2ee, 0x0002, mach_accel_inb, mach_accel_inw, mach_accel_inl, mach_accel_outb, mach_accel_outw, mach_accel_outl, mach); + io_sethandler(0xc6ee, 0x0002, mach_accel_inb, mach_accel_inw, mach_accel_inl, mach_accel_outb, mach_accel_outw, mach_accel_outl, mach); + io_sethandler(0xcaee, 0x0002, mach_accel_inb, mach_accel_inw, mach_accel_inl, mach_accel_outb, mach_accel_outw, mach_accel_outl, mach); + io_sethandler(0xceee, 0x0002, mach_accel_inb, mach_accel_inw, mach_accel_inl, mach_accel_outb, mach_accel_outw, mach_accel_outl, mach); + io_sethandler(0xd2ee, 0x0002, mach_accel_inb, mach_accel_inw, mach_accel_inl, mach_accel_outb, mach_accel_outw, mach_accel_outl, mach); + io_sethandler(0xd6ee, 0x0002, mach_accel_inb, mach_accel_inw, mach_accel_inl, mach_accel_outb, mach_accel_outw, mach_accel_outl, mach); + io_sethandler(0xdaee, 0x0002, mach_accel_inb, mach_accel_inw, mach_accel_inl, mach_accel_outb, mach_accel_outw, mach_accel_outl, mach); + io_sethandler(0xdeee, 0x0002, mach_accel_inb, mach_accel_inw, mach_accel_inl, mach_accel_outb, mach_accel_outw, mach_accel_outl, mach); + io_sethandler(0xe2ee, 0x0002, mach_accel_inb, mach_accel_inw, mach_accel_inl, mach_accel_outb, mach_accel_outw, mach_accel_outl, mach); + io_sethandler(0xe6ee, 0x0002, mach_accel_inb, mach_accel_inw, mach_accel_inl, mach_accel_outb, mach_accel_outw, mach_accel_outl, mach); + io_sethandler(0xeeee, 0x0002, mach_accel_inb, mach_accel_inw, mach_accel_inl, mach_accel_outb, mach_accel_outw, mach_accel_outl, mach); + io_sethandler(0xf2ee, 0x0002, mach_accel_inb, mach_accel_inw, mach_accel_inl, mach_accel_outb, mach_accel_outw, mach_accel_outl, mach); + io_sethandler(0xfaee, 0x0002, mach_accel_inb, mach_accel_inw, mach_accel_inl, mach_accel_outb, mach_accel_outw, mach_accel_outl, mach); + io_sethandler(0xfeee, 0x0002, mach_accel_inb, mach_accel_inw, mach_accel_inl, mach_accel_outb, mach_accel_outw, mach_accel_outl, mach); +} + +static uint8_t +mach_mca_read(int port, void *priv) +{ + const mach_t *mach = (mach_t *) priv; + + mach_log("[%04X]: MCA read port = %x, val = %02x.\n", CS, port & 7, mach->pos_regs[port & 7]); + return mach->pos_regs[port & 7]; +} + +static void +mach_mca_write(int port, uint8_t val, void *priv) +{ + mach_t *mach = (mach_t *) priv; + + if (port < 0x102) + return; + + mach->pos_regs[port & 7] = val; + mach_log("[%04X]: MCA write port = %x, val = %02x, biosaddr = %05x.\n", CS, port & 7, mach->pos_regs[port & 7], (((mach->pos_regs[3] & 0x3e) << 0x0c) >> 1) + 0xc0000); + mem_mapping_disable(&mach->bios_rom.mapping); + mem_mapping_disable(&mach->bios_rom2.mapping); + if (mach->pos_regs[2] & 0x01) { + mem_mapping_enable(&mach->bios_rom.mapping); + mem_mapping_enable(&mach->bios_rom2.mapping); + } +} + +static uint8_t +mach_mca_feedb(void *priv) +{ + const mach_t *mach = (mach_t *) priv; + + mach_log("FeedB = %x.\n", mach->pos_regs[2] & 0x01); + return mach->pos_regs[2] & 0x01; +} + +static void +mach_mca_reset(void *priv) +{ + mach_t *mach = (mach_t *) priv; + svga_t *svga = &mach->svga; + ibm8514_t *dev = (ibm8514_t *) svga->dev8514; + + mem_mapping_disable(&mach->bios_rom.mapping); + mem_mapping_disable(&mach->bios_rom2.mapping); + mach_log("MCA reset.\n"); + dev->on = 0; + vga_on = 1; + mach_mca_write(0x102, 0, mach); +} + +static uint8_t +mach32_pci_read(UNUSED(int func), int addr, void *priv) +{ + const mach_t *mach = (mach_t *) priv; + uint8_t ret = 0x00; + + if ((addr >= 0x30) && (addr <= 0x33) && !mach->has_bios) + return ret; + + 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; + + default: + break; + } + + return ret; +} + +static void +mach32_pci_write(UNUSED(int func), int addr, uint8_t val, void *priv) +{ + mach_t *mach = (mach_t *) priv; + if ((addr >= 0x30) && (addr <= 0x33) && !mach->has_bios) + return; + + switch (addr) { + case PCI_REG_COMMAND: + mach->pci_regs[PCI_REG_COMMAND] = val & 0x27; + if (val & PCI_COMMAND_IO) { + io_removehandler(0x02ea, 4, mach_in, NULL, NULL, mach_out, NULL, NULL, mach); + io_removehandler(0x03c0, 32, mach_in, NULL, NULL, mach_out, NULL, NULL, mach); + io_sethandler(0x02ea, 4, mach_in, NULL, NULL, mach_out, NULL, NULL, mach); + io_sethandler(0x03c0, 32, mach_in, NULL, NULL, mach_out, NULL, NULL, mach); + } else { + io_removehandler(0x03c0, 32, mach_in, NULL, NULL, mach_out, NULL, NULL, mach); + io_removehandler(0x02ea, 4, mach_in, NULL, NULL, mach_out, NULL, NULL, mach); + } + mach32_updatemapping(mach); + break; + + case 0x12: + mach->linear_base = (mach->linear_base & 0xff000000) | ((val & 0xc0) << 16); + mach->ati_mode = 1; + mach32_updatemapping(mach); + break; + case 0x13: + mach->linear_base = (mach->linear_base & 0xc00000) | (val << 24); + mach->ati_mode = 1; + 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; + + default: + break; + } +} + +static void * +mach8_init(const device_t *info) +{ + mach_t *mach; + svga_t *svga; + ibm8514_t *dev; + + mach = calloc(1, sizeof(mach_t)); + + svga = &mach->svga; + dev = (ibm8514_t *) calloc(1, sizeof(ibm8514_t)); + + svga->dev8514 = dev; + + mach->pci_bus = !!(info->flags & DEVICE_PCI); + mach->vlb_bus = !!(info->flags & DEVICE_VLB); + mach->mca_bus = !!(info->flags & DEVICE_MCA); + dev->type = info->flags; + dev->local = info->local & 0xff; + mach->has_bios = !(info->local & 0xff00); + mach->memory = device_get_config_int("memory"); + mach->ramdac_type = mach->pci_bus ? device_get_config_int("ramdac") : 1; + + if (dev->local >= 2) { + if (mach->pci_bus) { + if (mach->has_bios) { + rom_init(&mach->bios_rom, + BIOS_MACH32_PCI_ROM_PATH, + 0xc0000, 0x8000, 0x7fff, + 0, MEM_MAPPING_EXTERNAL); + } + } + else if (mach->vlb_bus) + rom_init(&mach->bios_rom, + BIOS_MACH32_VLB_ROM_PATH, + 0xc0000, 0x8000, 0x7fff, + 0, MEM_MAPPING_EXTERNAL); + else if (mach->mca_bus) { + rom_init(&mach->bios_rom, + BIOS_MACH32_MCA_ROM_PATH, + 0xc0000, 0x8000, 0x7fff, + 0, MEM_MAPPING_EXTERNAL); + rom_init(&mach->bios_rom2, + BIOS_MACH32_MCA_ROM_PATH, + 0xc8000, 0x1000, 0x0fff, + 0x8000, 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); + } + + if (dev->local >= 2) { + svga_init(info, svga, mach, mach->memory << 10, /*default: 2MB for Mach32*/ + mach_recalctimings, + mach_in, mach_out, + mach32_hwcursor_draw, + NULL); + dev->vram_size = mach->memory << 10; + dev->vram = calloc(dev->vram_size, 1); + dev->changedvram = calloc(dev->vram_size >> 12, 1); + dev->vram_mask = dev->vram_size - 1; + dev->hwcursor.cur_ysize = 64; + mach->config1 = 0x20; + if (mach->pci_bus && !mach->ramdac_type) + svga->ramdac = device_add(&ati68860_ramdac_device); + else + svga->ramdac = device_add(&ati68875_ramdac_device); + if (mach->vlb_bus) { + video_inform(VIDEO_FLAG_TYPE_8514, &timing_mach32_vlb); + if (!is486) + mach->config1 |= 0x0a; + else + mach->config1 |= 0x0c; + mach->config1 |= 0x0400; + svga->clock_gen = device_add(&ati18811_0_device); + } else if (mach->mca_bus) { + video_inform(VIDEO_FLAG_TYPE_8514, &timing_mach32_mca); + if (is286 && !is386) + mach->config1 |= 0x04; + else + mach->config1 |= 0x06; + mach->config1 |= 0x0400; + mach->config1 |= 0x1000; + svga->clock_gen = device_add(&ati18811_1_device); + } else if (mach->pci_bus) { + video_inform(VIDEO_FLAG_TYPE_8514, &timing_mach32_pci); + mach->config1 |= 0x0e; + if (mach->ramdac_type) + mach->config1 |= 0x0400; + else + mach->config1 |= 0x0a00; + mach->config2 |= 0x2000; + svga->clock_gen = device_add(&ati18811_0_device); + } else { + video_inform(VIDEO_FLAG_TYPE_8514, &timing_gfxultra_isa); + mach->config1 |= 0x0400; + svga->clock_gen = device_add(&ati18811_0_device); + } + 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 { + svga_init(info, svga, mach, (512 << 10), /*default: 512kB VGA for 28800-6 + 1MB for Mach8*/ + mach_recalctimings, + mach_in, mach_out, + NULL, + NULL); + 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; + video_inform(VIDEO_FLAG_TYPE_8514, &timing_gfxultra_isa); + mach->config1 = 0x02 | 0x20 | 0x80; + mach->config2 = 0x02; + svga->clock_gen = device_add(&ati18810_device); + } + dev->bpp = 0; + svga->getclock = ics2494_getclock; + + dev->on = 0; + dev->ext_pitch = 1024; + dev->ext_crt_pitch = 0x80; + dev->accel_bpp = 8; + svga->force_old_addr = 1; + svga->miscout = 1; + svga->bpp = 8; + svga->packed_chain4 = 1; + dev->rowoffset = 0x80; + 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(0x02ea, 4, mach_in, NULL, NULL, mach_out, NULL, NULL, mach); + mach_io_set(mach); + + if (dev->local >= 2) { + 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; + if (mach->vlb_bus) + ati_eeprom_load(&mach->eeprom, "mach32_vlb.nvr", 1); + else if (mach->mca_bus) { + ati_eeprom_load(&mach->eeprom, "mach32_mca.nvr", 1); + mem_mapping_disable(&mach->bios_rom.mapping); + mem_mapping_disable(&mach->bios_rom2.mapping); + mach->pos_regs[0] = 0x89; + mach->pos_regs[1] = 0x80; + mca_add(mach_mca_read, mach_mca_write, mach_mca_feedb, mach_mca_reset, mach); + } else if (mach->pci_bus) { + ati_eeprom_load(&mach->eeprom, "mach32_pci.nvr", 1); + if (mach->has_bios) { + mem_mapping_disable(&mach->bios_rom.mapping); + pci_add_card(PCI_ADD_NORMAL, mach32_pci_read, mach32_pci_write, mach, &mach->pci_slot); + } else + pci_add_card(PCI_ADD_VIDEO, mach32_pci_read, mach32_pci_write, mach, &mach->pci_slot); + 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_mca_available(void) +{ + return rom_present(BIOS_MACH32_MCA_ROM_PATH); +} + +static int +mach32_pci_available(void) +{ + return rom_present(BIOS_MACH32_PCI_ROM_PATH); +} + +static void +mach_close(void *priv) +{ + mach_t *mach = (mach_t *) priv; + svga_t *svga = &mach->svga; + ibm8514_t *dev = (ibm8514_t *) svga->dev8514; + + if (dev) { + free(dev->vram); + free(dev->changedvram); + + free(dev); + } + + svga_close(svga); + free(mach); +} + +static void +mach_speed_changed(void *priv) +{ + mach_t *mach = (mach_t *) priv; + svga_t *svga = &mach->svga; + + svga_recalctimings(svga); +} + +static void +mach_force_redraw(void *priv) +{ + mach_t *mach = (mach_t *) priv; + svga_t *svga = &mach->svga; + + svga->fullchange = svga->monitor->mon_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 + } +}; + +// clang-format off +static const device_config_t mach32_pci_config[] = { + { + .name = "ramdac", + .description = "RAMDAC type", + .type = CONFIG_SELECTION, + .default_int = 0, + .selection = { + { + .description = "ATI 68860", + .value = 0 + }, + { + .description = "ATI 68875", + .value = 1 + }, + { + .description = "" + } + } + }, + { + .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 = 1, + .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 = 2, + .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 = 2, + .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_mca_device = { + .name = "ATI Mach32 (MCA)", + .internal_name = "mach32_mca", + .flags = DEVICE_MCA, + .local = 2, + .init = mach8_init, + .close = mach_close, + .reset = NULL, + { .available = mach32_mca_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 = 2, + .init = mach8_init, + .close = mach_close, + .reset = NULL, + { .available = mach32_pci_available }, + .speed_changed = mach_speed_changed, + .force_redraw = mach_force_redraw, + .config = mach32_pci_config +}; + +const device_t mach32_onboard_pci_device = { + .name = "ATI Mach32 (PCI) On-Board", + .internal_name = "mach32_pci_onboard", + .flags = DEVICE_PCI, + .local = 2 | 0x100, + .init = mach8_init, + .close = mach_close, + .reset = NULL, + { .available = NULL }, + .speed_changed = mach_speed_changed, + .force_redraw = mach_force_redraw, + .config = mach32_pci_config +}; + diff --git a/src/video/vid_att20c49x_ramdac.c b/src/video/vid_att20c49x_ramdac.c index e533015b0..f13740d34 100644 --- a/src/video/vid_att20c49x_ramdac.c +++ b/src/video/vid_att20c49x_ramdac.c @@ -1,20 +1,18 @@ /* - * 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. + * 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. + * This file is part of the 86Box distribution. * - * Emulation of a AT&T 20c490/491 and 492/493 RAMDAC. + * Emulation of a AT&T 20c490/491 and 492/493 RAMDAC. * * * - * Authors: Sarah Walker, - * Miran Grca, + * Authors: Miran Grca, * - * Copyright 2008-2018 Sarah Walker. - * Copyright 2016-2018 Miran Grca. + * Copyright 2016-2018 Miran Grca. */ #include #include @@ -28,131 +26,134 @@ #include <86box/video.h> #include <86box/vid_svga.h> - -typedef struct -{ - int type; - int state; +typedef struct att49x_ramdac_t { + int type; + int state; uint8_t ctrl; } att49x_ramdac_t; - -enum -{ - ATT_490 = 0, - ATT_491, - ATT_492 +enum { + ATT_490 = 0, + ATT_491, + ATT_492 }; - static void -att49x_ramdac_control(uint8_t val, void *p, svga_t *svga) +att49x_ramdac_control(uint8_t val, void *priv, svga_t *svga) { - att49x_ramdac_t *ramdac = (att49x_ramdac_t *) p; - ramdac->ctrl = val; - switch ((ramdac->ctrl >> 5) & 7) { - case 0: - case 1: - case 2: - case 3: - svga->bpp = 8; - break; - case 4: - case 5: - svga->bpp = 15; - break; - case 6: - svga->bpp = 16; - break; - case 7: - svga->bpp = 24; - break; - } - if (ramdac->type == ATT_490 || ramdac->type == ATT_491) - svga_set_ramdac_type(svga, (val & 2) ? RAMDAC_8BIT : RAMDAC_6BIT); - svga_recalctimings(svga); + att49x_ramdac_t *ramdac = (att49x_ramdac_t *) priv; + ramdac->ctrl = val; + switch ((ramdac->ctrl >> 5) & 7) { + case 0: + case 1: + case 2: + case 3: + svga->bpp = 8; + break; + case 4: + case 5: + svga->bpp = 15; + break; + case 6: + svga->bpp = 16; + break; + case 7: + svga->bpp = 24; + break; + + default: + break; + } + if (ramdac->type == ATT_490 || ramdac->type == ATT_491) + svga_set_ramdac_type(svga, (val & 2) ? RAMDAC_8BIT : RAMDAC_6BIT); + svga_recalctimings(svga); } void -att49x_ramdac_out(uint16_t addr, int rs2, uint8_t val, void *p, svga_t *svga) +att49x_ramdac_out(uint16_t addr, int rs2, uint8_t val, void *priv, svga_t *svga) { - att49x_ramdac_t *ramdac = (att49x_ramdac_t *) p; - uint8_t rs = (addr & 0x03); + att49x_ramdac_t *ramdac = (att49x_ramdac_t *) priv; + uint8_t rs = (addr & 0x03); rs |= ((!!rs2) << 2); switch (rs) { - case 0x00: - case 0x01: - case 0x03: - case 0x04: - case 0x05: - case 0x07: - svga_out(addr, val, svga); - ramdac->state = 0; - break; - case 0x02: - switch (ramdac->state) { - case 4: - att49x_ramdac_control(val, ramdac, svga); - break; - default: - svga_out(addr, val, svga); - break; - } - break; - case 0x06: - att49x_ramdac_control(val, ramdac, svga); - ramdac->state = 0; - break; + case 0x00: + case 0x01: + case 0x03: + case 0x04: + case 0x05: + case 0x07: + svga_out(addr, val, svga); + ramdac->state = 0; + break; + case 0x02: + switch (ramdac->state) { + case 4: + att49x_ramdac_control(val, ramdac, svga); + break; + default: + svga_out(addr, val, svga); + break; + } + break; + case 0x06: + att49x_ramdac_control(val, ramdac, svga); + ramdac->state = 0; + break; + + default: + break; } } - uint8_t -att49x_ramdac_in(uint16_t addr, int rs2, void *p, svga_t *svga) +att49x_ramdac_in(uint16_t addr, int rs2, void *priv, svga_t *svga) { - att49x_ramdac_t *ramdac = (att49x_ramdac_t *) p; - uint8_t temp = 0xff; - uint8_t rs = (addr & 0x03); + att49x_ramdac_t *ramdac = (att49x_ramdac_t *) priv; + uint8_t temp = 0xff; + uint8_t rs = (addr & 0x03); rs |= ((!!rs2) << 2); switch (rs) { - case 0x00: - case 0x01: - case 0x03: - case 0x04: - case 0x05: - case 0x07: - temp = svga_in(addr, svga); - ramdac->state = 0; - break; - case 0x02: - switch (ramdac->state) { - case 1: - case 2: case 3: - temp = 0x00; - ramdac->state++; - break; - case 4: - temp = ramdac->ctrl; - ramdac->state = 0; - break; - default: - temp = svga_in(addr, svga); - ramdac->state++; - break; - } - break; - case 0x06: - temp = ramdac->ctrl; - ramdac->state = 0; - break; + case 0x00: + case 0x01: + case 0x03: + case 0x04: + case 0x05: + case 0x07: + temp = svga_in(addr, svga); + ramdac->state = 0; + break; + case 0x02: + switch (ramdac->state) { + case 1: + case 2: + case 3: + temp = 0x00; + ramdac->state++; + break; + case 4: + temp = ramdac->ctrl; + ramdac->state = 0; + break; + default: + temp = svga_in(addr, svga); + ramdac->state++; + break; + } + break; + case 0x06: + temp = ramdac->ctrl; + ramdac->state = 0; + break; + + default: + break; } return temp; } - static void * att49x_ramdac_init(const device_t *info) { @@ -160,44 +161,57 @@ att49x_ramdac_init(const device_t *info) memset(ramdac, 0, sizeof(att49x_ramdac_t)); ramdac->type = info->local; - + return ramdac; } - static void att49x_ramdac_close(void *priv) { att49x_ramdac_t *ramdac = (att49x_ramdac_t *) priv; if (ramdac) - free(ramdac); + free(ramdac); } - -const device_t att490_ramdac_device = -{ - "AT&T 20c490 RAMDAC", - "att490_ramdac", - 0, ATT_490, - att49x_ramdac_init, att49x_ramdac_close, - NULL, { NULL }, NULL, NULL +const device_t att490_ramdac_device = { + .name = "AT&T 20c490 RAMDAC", + .internal_name = "att490_ramdac", + .flags = 0, + .local = ATT_490, + .init = att49x_ramdac_init, + .close = att49x_ramdac_close, + .reset = NULL, + { .available = NULL }, + .speed_changed = NULL, + .force_redraw = NULL, + .config = NULL }; -const device_t att491_ramdac_device = -{ - "AT&T 20c491 RAMDAC", - "att491_ramdac", - 0, ATT_491, - att49x_ramdac_init, att49x_ramdac_close, - NULL, { NULL }, NULL, NULL +const device_t att491_ramdac_device = { + .name = "AT&T 20c491 RAMDAC", + .internal_name = "att491_ramdac", + .flags = 0, + .local = ATT_491, + .init = att49x_ramdac_init, + .close = att49x_ramdac_close, + .reset = NULL, + { .available = NULL }, + .speed_changed = NULL, + .force_redraw = NULL, + .config = NULL }; -const device_t att492_ramdac_device = -{ - "AT&T 20c492 RAMDAC", - "att492_ramdac", - 0, ATT_492, - att49x_ramdac_init, att49x_ramdac_close, - NULL, { NULL }, NULL, NULL -}; \ No newline at end of file +const device_t att492_ramdac_device = { + .name = "AT&T 20c492 RAMDAC", + .internal_name = "att492_ramdac", + .flags = 0, + .local = ATT_492, + .init = att49x_ramdac_init, + .close = att49x_ramdac_close, + .reset = NULL, + { .available = NULL }, + .speed_changed = NULL, + .force_redraw = NULL, + .config = NULL +}; diff --git a/src/video/vid_att2xc498_ramdac.c b/src/video/vid_att2xc498_ramdac.c index 122a97d2c..47eebccae 100644 --- a/src/video/vid_att2xc498_ramdac.c +++ b/src/video/vid_att2xc498_ramdac.c @@ -1,20 +1,18 @@ /* - * 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. + * 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. + * This file is part of the 86Box distribution. * - * Emulation of a AT&T 2xc498 RAMDAC. + * Emulation of a AT&T 2xc498 RAMDAC. * * * - * Authors: Sarah Walker, - * Miran Grca, + * Authors: Miran Grca, * - * Copyright 2008-2018 Sarah Walker. - * Copyright 2016-2018 Miran Grca. + * Copyright 2016-2018 Miran Grca. */ #include #include @@ -28,133 +26,135 @@ #include <86box/video.h> #include <86box/vid_svga.h> - -typedef struct -{ - int type; - int state; - int loop; +typedef struct att498_ramdac_t { + int type; + int state; + int loop; uint8_t ctrl; } att498_ramdac_t; static void -att498_ramdac_control(uint8_t val, void *p, svga_t *svga) +att498_ramdac_control(uint8_t val, void *priv, svga_t *svga) { - att498_ramdac_t *ramdac = (att498_ramdac_t *) p; - ramdac->ctrl = val; + att498_ramdac_t *ramdac = (att498_ramdac_t *) priv; + ramdac->ctrl = val; - if (val == 0xff) - return; + if (val == 0xff) + return; - switch ((ramdac->ctrl >> 4) & 0x0f) { - default: - svga->bpp = 8; - break; - case 1: - if (ramdac->ctrl & 4) - svga->bpp = 15; - else - svga->bpp = 8; - break; - case 3: - case 6: - svga->bpp = 16; - break; - case 5: - case 7: - svga->bpp = 32; - break; - case 0x0e: - svga->bpp = 24; - break; - } + switch ((ramdac->ctrl >> 4) & 0x0f) { + default: + svga->bpp = 8; + break; + case 1: + if (ramdac->ctrl & 4) + svga->bpp = 15; + else + svga->bpp = 8; + break; + case 3: + case 6: + svga->bpp = 16; + break; + case 5: + case 7: + svga->bpp = 32; + break; + case 0x0e: + svga->bpp = 24; + break; + } - svga_set_ramdac_type(svga, (ramdac->ctrl & 2) ? RAMDAC_8BIT : RAMDAC_6BIT); - svga_recalctimings(svga); + svga_set_ramdac_type(svga, (ramdac->ctrl & 2) ? RAMDAC_8BIT : RAMDAC_6BIT); + svga_recalctimings(svga); } void -att498_ramdac_out(uint16_t addr, int rs2, uint8_t val, void *p, svga_t *svga) +att498_ramdac_out(uint16_t addr, int rs2, uint8_t val, void *priv, svga_t *svga) { - att498_ramdac_t *ramdac = (att498_ramdac_t *) p; - uint8_t rs = (addr & 0x03); + att498_ramdac_t *ramdac = (att498_ramdac_t *) priv; + uint8_t rs = (addr & 0x03); rs |= ((!!rs2) << 2); switch (rs) { - case 0x00: - case 0x01: - case 0x03: - case 0x04: - case 0x05: - case 0x07: - svga_out(addr, val, svga); - ramdac->state = 0; - break; - case 0x02: - switch (ramdac->state) { - case 4: - att498_ramdac_control(val, ramdac, svga); - break; - default: - svga_out(addr, val, svga); - break; - } - break; - case 0x06: - att498_ramdac_control(val, ramdac, svga); - break; + case 0x00: + case 0x01: + case 0x03: + case 0x04: + case 0x05: + case 0x07: + svga_out(addr, val, svga); + ramdac->state = 0; + break; + case 0x02: + switch (ramdac->state) { + case 4: + att498_ramdac_control(val, ramdac, svga); + break; + default: + svga_out(addr, val, svga); + break; + } + break; + case 0x06: + att498_ramdac_control(val, ramdac, svga); + break; + + default: + break; } } - uint8_t -att498_ramdac_in(uint16_t addr, int rs2, void *p, svga_t *svga) +att498_ramdac_in(uint16_t addr, int rs2, void *priv, svga_t *svga) { - att498_ramdac_t *ramdac = (att498_ramdac_t *) p; - uint8_t temp = 0xff; - uint8_t rs = (addr & 0x03); + att498_ramdac_t *ramdac = (att498_ramdac_t *) priv; + uint8_t temp = 0xff; + uint8_t rs = (addr & 0x03); rs |= ((!!rs2) << 2); switch (rs) { - case 0x00: - case 0x01: - case 0x03: - case 0x04: - case 0x05: - case 0x07: - temp = svga_in(addr, svga); - ramdac->state = 0; - break; - case 0x02: - switch (ramdac->state) { - case 4: - temp = ramdac->ctrl; - ramdac->state++; - break; - case 5: - temp = 0x84; - ramdac->state++; - break; - case 6: - temp = ramdac->ctrl; - ramdac->state = 0; - break; - default: - temp = svga_in(addr, svga); - ramdac->state++; - break; - } - break; - case 0x06: - temp = ramdac->ctrl; - ramdac->state = 0; - break; + case 0x00: + case 0x01: + case 0x03: + case 0x04: + case 0x05: + case 0x07: + temp = svga_in(addr, svga); + ramdac->state = 0; + break; + case 0x02: + switch (ramdac->state) { + case 4: + temp = ramdac->ctrl; + ramdac->state++; + break; + case 5: + temp = 0x84; + ramdac->state++; + break; + case 6: + temp = ramdac->ctrl; + ramdac->state = 0; + break; + default: + temp = svga_in(addr, svga); + ramdac->state++; + break; + } + break; + case 0x06: + temp = ramdac->ctrl; + ramdac->state = 0; + break; + + default: + break; } return temp; } - static void * att498_ramdac_init(const device_t *info) { @@ -162,26 +162,29 @@ att498_ramdac_init(const device_t *info) memset(ramdac, 0, sizeof(att498_ramdac_t)); ramdac->type = info->local; - + return ramdac; } - static void att498_ramdac_close(void *priv) { att498_ramdac_t *ramdac = (att498_ramdac_t *) priv; if (ramdac) - free(ramdac); + free(ramdac); } - -const device_t att498_ramdac_device = -{ - "AT&T 22c498 RAMDAC", - "att498_ramdac", - 0, 0, - att498_ramdac_init, att498_ramdac_close, - NULL, { NULL }, NULL, NULL -}; \ No newline at end of file +const device_t att498_ramdac_device = { + .name = "AT&T 22c498 RAMDAC", + .internal_name = "att498_ramdac", + .flags = 0, + .local = 0, + .init = att498_ramdac_init, + .close = att498_ramdac_close, + .reset = NULL, + { .available = NULL }, + .speed_changed = NULL, + .force_redraw = NULL, + .config = NULL +}; diff --git a/src/video/vid_av9194.c b/src/video/vid_av9194.c index a2e208621..e7cf75dee 100644 --- a/src/video/vid_av9194.c +++ b/src/video/vid_av9194.c @@ -1,20 +1,20 @@ /* - * 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. + * 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. + * This file is part of the 86Box distribution. * - * AV9194 clock generator emulation. + * AV9194 clock generator emulation. * - * Used by the S3 86c801 (V7-Mirage) card. + * Used by the S3 86c801 (V7-Mirage) card. * * * - * Authors: Miran Grca, + * Authors: Miran Grca, * - * Copyright 2016-2018 Miran Grca. + * Copyright 2016-2018 Miran Grca. */ #include #include @@ -27,80 +27,84 @@ #include <86box/timer.h> #include <86box/video.h> #include <86box/vid_svga.h> - +#include <86box/plat_unused.h> float -av9194_getclock(int clock, void *p) +av9194_getclock(int clock, UNUSED(void *priv)) { float ret = 0.0; - - switch (clock & 0x0f) - { - case 0: - ret = 25175000.0; - break; - case 1: - ret = 28322000.0; - break; - case 2: - ret = 40000000.0; - break; - case 4: - ret = 50000000.0; - break; - case 5: - ret = 77000000.0; - break; - case 6: - ret = 36000000.0; - break; - case 7: - ret = 44900000.0; - break; - case 8: - ret = 130000000.0; - break; - case 9: - ret = 120000000.0; - break; - case 0xa: - ret = 80000000.0; - break; - case 0xb: - ret = 31500000.0; - break; - case 0xc: - ret = 110000000.0; - break; - case 0xd: - ret = 65000000.0; - break; - case 0xe: - ret = 75000000.0; - break; - case 0xf: - ret = 94500000.0; - break; + + switch (clock & 0x0f) { + case 0: + ret = 25175000.0; + break; + case 1: + ret = 28322000.0; + break; + case 2: + ret = 40000000.0; + break; + case 4: + ret = 50000000.0; + break; + case 5: + ret = 77000000.0; + break; + case 6: + ret = 36000000.0; + break; + case 7: + ret = 44900000.0; + break; + case 8: + ret = 130000000.0; + break; + case 9: + ret = 120000000.0; + break; + case 0xa: + ret = 80000000.0; + break; + case 0xb: + ret = 31500000.0; + break; + case 0xc: + ret = 110000000.0; + break; + case 0xd: + ret = 65000000.0; + break; + case 0xe: + ret = 75000000.0; + break; + case 0xf: + ret = 94500000.0; + break; + + default: + break; } - + return ret; } - static void * -av9194_init(const device_t *info) +av9194_init(UNUSED(const device_t *info)) { /* Return something non-NULL. */ return (void *) &av9194_device; } - -const device_t av9194_device = -{ - "AV9194 Clock Generator", - "av9194", - 0, 0, - av9194_init, NULL, - NULL, { NULL }, NULL, NULL +const device_t av9194_device = { + .name = "AV9194 Clock Generator", + .internal_name = "av9194", + .flags = 0, + .local = 0, + .init = av9194_init, + .close = NULL, + .reset = NULL, + { .available = NULL }, + .speed_changed = NULL, + .force_redraw = NULL, + .config = NULL }; - diff --git a/src/video/vid_bt48x_ramdac.c b/src/video/vid_bt48x_ramdac.c index 0d02922ae..91ddce956 100644 --- a/src/video/vid_bt48x_ramdac.c +++ b/src/video/vid_bt48x_ramdac.c @@ -1,21 +1,21 @@ /* - * 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. + * 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. + * This file is part of the 86Box distribution. * - * Emulation of the Brooktree BT484-485A true colour RAMDAC - * family. + * Emulation of the Brooktree BT484-485A true colour RAMDAC + * family. * * * - * Authors: Miran Grca, - * TheCollector1995, + * Authors: Miran Grca, + * TheCollector1995, * - * Copyright 2016-2018 Miran Grca. - * Copyright 2018 TheCollector1995. + * Copyright 2016-2018 Miran Grca. + * Copyright 2018 TheCollector1995. */ #include #include @@ -29,344 +29,364 @@ #include <86box/video.h> #include <86box/vid_svga.h> - -typedef struct -{ - PALETTE extpal; - uint32_t extpallook[256]; - uint8_t cursor32_data[256]; - uint8_t cursor64_data[1024]; - int hwc_y, hwc_x; - uint8_t cmd_r0; - uint8_t cmd_r1; - uint8_t cmd_r2; - uint8_t cmd_r3; - uint8_t cmd_r4; - uint8_t status; - uint8_t type; +typedef struct bt48x_ramdac_t { + PALETTE extpal; + uint32_t extpallook[256]; + uint8_t cursor32_data[256]; + uint8_t cursor64_data[1024]; + int hwc_y; + int hwc_x; + uint8_t cmd_r0; + uint8_t cmd_r1; + uint8_t cmd_r2; + uint8_t cmd_r3; + uint8_t cmd_r4; + uint8_t status; + uint8_t type; } bt48x_ramdac_t; - enum { - BT484 = 0, - ATT20C504, - BT485, - ATT20C505, - BT485A + BT484 = 0, + ATT20C504, + BT485, + ATT20C505, + BT485A }; - static void bt48x_set_bpp(bt48x_ramdac_t *ramdac, svga_t *svga) { if ((!(ramdac->cmd_r2 & 0x20)) || ((ramdac->type >= BT485A) && ((ramdac->cmd_r3 & 0x60) == 0x60))) - svga->bpp = 8; + svga->bpp = 8; else if ((ramdac->type >= BT485A) && ((ramdac->cmd_r3 & 0x60) == 0x40)) - svga->bpp = 24; - else switch (ramdac->cmd_r1 & 0x60) { - case 0x00: - svga->bpp = 32; - break; - case 0x20: - if (ramdac->cmd_r1 & 0x08) - svga->bpp = 16; - else - svga->bpp = 15; - break; - case 0x40: - svga->bpp = 8; - break; - case 0x60: - svga->bpp = 4; - break; - } + svga->bpp = 24; + else + switch (ramdac->cmd_r1 & 0x60) { + case 0x00: + svga->bpp = 32; + break; + case 0x20: + if (ramdac->cmd_r1 & 0x08) + svga->bpp = 16; + else + svga->bpp = 15; + break; + case 0x40: + svga->bpp = 8; + break; + case 0x60: + svga->bpp = 4; + break; + + default: + break; + } svga_recalctimings(svga); } - void -bt48x_ramdac_out(uint16_t addr, int rs2, int rs3, uint8_t val, void *p, svga_t *svga) +bt48x_ramdac_out(uint16_t addr, int rs2, int rs3, uint8_t val, void *priv, svga_t *svga) { - bt48x_ramdac_t *ramdac = (bt48x_ramdac_t *) p; - uint32_t o32; - uint8_t *cd; - uint16_t index; - uint8_t rs = (addr & 0x03); - uint16_t da_mask = 0x03ff; + bt48x_ramdac_t *ramdac = (bt48x_ramdac_t *) priv; + uint32_t o32; + uint8_t *cd; + uint16_t index; + uint8_t rs = (addr & 0x03); + uint16_t da_mask = 0x03ff; rs |= (!!rs2 << 2); rs |= (!!rs3 << 3); if (ramdac->type < BT485) - da_mask = 0x00ff; + da_mask = 0x00ff; switch (rs) { - case 0x00: /* Palette Write Index Register (RS value = 0000) */ - case 0x04: /* Ext Palette Write Index Register (RS value = 0100) */ - case 0x03: - case 0x07: /* Ext Palette Read Index Register (RS value = 0111) */ - svga->dac_pos = 0; - svga->dac_status = addr & 0x03; - svga->dac_addr = val; - if (ramdac->type >= BT485) - svga->dac_addr |= ((int) (ramdac->cmd_r3 & 0x03) << 8); - if (svga->dac_status) - svga->dac_addr = (svga->dac_addr + 1) & da_mask; - break; - case 0x01: /* Palette Data Register (RS value = 0001) */ - case 0x02: /* Pixel Read Mask Register (RS value = 0010) */ - svga_out(addr, val, svga); - break; - case 0x05: /* Ext Palette Data Register (RS value = 0101) */ - svga->dac_status = 0; - svga->fullchange = changeframecount; - switch (svga->dac_pos) { - case 0: - svga->dac_r = val; - svga->dac_pos++; - break; - case 1: - svga->dac_g = val; - svga->dac_pos++; - break; - case 2: - index = svga->dac_addr & 3; - ramdac->extpal[index].r = svga->dac_r; - ramdac->extpal[index].g = svga->dac_g; - ramdac->extpal[index].b = val; - if (svga->ramdac_type == RAMDAC_8BIT) - ramdac->extpallook[index] = makecol32(ramdac->extpal[index].r, ramdac->extpal[index].g, ramdac->extpal[index].b); - else - ramdac->extpallook[index] = makecol32(video_6to8[ramdac->extpal[index].r & 0x3f], video_6to8[ramdac->extpal[index].g & 0x3f], video_6to8[ramdac->extpal[index].b & 0x3f]); + case 0x00: /* Palette Write Index Register (RS value = 0000) */ + case 0x04: /* Ext Palette Write Index Register (RS value = 0100) */ + case 0x03: + case 0x07: /* Ext Palette Read Index Register (RS value = 0111) */ + svga->dac_pos = 0; + svga->dac_status = addr & 0x03; + svga->dac_addr = val; + if (ramdac->type >= BT485) + svga->dac_addr |= ((ramdac->cmd_r3 & 0x03) << 8); + if (svga->dac_status) + svga->dac_addr = (svga->dac_addr + 1) & da_mask; + break; + case 0x01: /* Palette Data Register (RS value = 0001) */ + case 0x02: /* Pixel Read Mask Register (RS value = 0010) */ + svga_out(addr, val, svga); + break; + case 0x05: /* Ext Palette Data Register (RS value = 0101) */ + svga->dac_status = 0; + svga->fullchange = changeframecount; + switch (svga->dac_pos) { + case 0: + svga->dac_r = val; + svga->dac_pos++; + break; + case 1: + svga->dac_g = val; + svga->dac_pos++; + break; + case 2: + index = svga->dac_addr & 3; + ramdac->extpal[index].r = svga->dac_r; + ramdac->extpal[index].g = svga->dac_g; + ramdac->extpal[index].b = val; + if (svga->ramdac_type == RAMDAC_8BIT) + ramdac->extpallook[index] = makecol32(ramdac->extpal[index].r, ramdac->extpal[index].g, ramdac->extpal[index].b); + else + ramdac->extpallook[index] = makecol32(video_6to8[ramdac->extpal[index].r & 0x3f], video_6to8[ramdac->extpal[index].g & 0x3f], video_6to8[ramdac->extpal[index].b & 0x3f]); - if (svga->ext_overscan && !index) { - o32 = svga->overscan_color; - svga->overscan_color = ramdac->extpallook[0]; - if (o32 != svga->overscan_color) - svga_recalctimings(svga); - } - svga->dac_addr = (svga->dac_addr + 1) & 0xff; - svga->dac_pos = 0; - break; - } - break; - case 0x06: /* Command Register 0 (RS value = 0110) */ - ramdac->cmd_r0 = val; - svga->ramdac_type = (val & 0x02) ? RAMDAC_8BIT : RAMDAC_6BIT; - break; - case 0x08: /* Command Register 1 (RS value = 1000) */ - ramdac->cmd_r1 = val; - bt48x_set_bpp(ramdac, svga); - break; - case 0x09: /* Command Register 2 (RS value = 1001) */ - ramdac->cmd_r2 = val; - svga->dac_hwcursor.ena = !!(val & 0x03); - bt48x_set_bpp(ramdac, svga); - break; - case 0x0a: - if ((ramdac->type >= BT485) && (ramdac->cmd_r0 & 0x80)) { - switch ((svga->dac_addr & ((ramdac->type >= BT485A) ? 0xff : 0x3f))) { - case 0x01: - /* Command Register 3 (RS value = 1010) */ - ramdac->cmd_r3 = val; - if (ramdac->type >= BT485A) - bt48x_set_bpp(ramdac, svga); - svga->dac_hwcursor.xsize = svga->dac_hwcursor.ysize = (val & 4) ? 64 : 32; - svga->dac_hwcursor.x = ramdac->hwc_x - svga->dac_hwcursor.xsize; - svga->dac_hwcursor.y = ramdac->hwc_y - svga->dac_hwcursor.ysize; - svga->dac_addr = (svga->dac_addr & 0x00ff) | ((val & 0x03) << 8); - svga_recalctimings(svga); - break; - case 0x02: - case 0x20: - case 0x21: - case 0x22: - if (ramdac->type != BT485A) - break; - else if (svga->dac_addr == 2) { - ramdac->cmd_r4 = val; - break; - } - break; - } - } - break; - case 0x0b: /* Cursor RAM Data Register (RS value = 1011) */ - index = svga->dac_addr & da_mask; - if ((ramdac->type >= BT485) && (svga->dac_hwcursor.xsize == 64)) - cd = (uint8_t *) ramdac->cursor64_data; - else { - index &= 0xff; - cd = (uint8_t *) ramdac->cursor32_data; - } + if (svga->ext_overscan && !index) { + o32 = svga->overscan_color; + svga->overscan_color = ramdac->extpallook[0]; + if (o32 != svga->overscan_color) + svga_recalctimings(svga); + } + svga->dac_addr = (svga->dac_addr + 1) & 0xff; + svga->dac_pos = 0; + break; - cd[index] = val; + default: + break; + } + break; + case 0x06: /* Command Register 0 (RS value = 0110) */ + ramdac->cmd_r0 = val; + svga->ramdac_type = (val & 0x02) ? RAMDAC_8BIT : RAMDAC_6BIT; + break; + case 0x08: /* Command Register 1 (RS value = 1000) */ + ramdac->cmd_r1 = val; + bt48x_set_bpp(ramdac, svga); + break; + case 0x09: /* Command Register 2 (RS value = 1001) */ + ramdac->cmd_r2 = val; + svga->dac_hwcursor.ena = !!(val & 0x03); + bt48x_set_bpp(ramdac, svga); + break; + case 0x0a: + if ((ramdac->type >= BT485) && (ramdac->cmd_r0 & 0x80)) { + switch (svga->dac_addr & ((ramdac->type >= BT485A) ? 0xff : 0x3f)) { + case 0x01: + /* Command Register 3 (RS value = 1010) */ + ramdac->cmd_r3 = val; + if (ramdac->type >= BT485A) + bt48x_set_bpp(ramdac, svga); + svga->dac_hwcursor.cur_xsize = svga->dac_hwcursor.cur_ysize = (val & 4) ? 64 : 32; + svga->dac_hwcursor.x = ramdac->hwc_x - svga->dac_hwcursor.cur_xsize; + svga->dac_hwcursor.y = ramdac->hwc_y - svga->dac_hwcursor.cur_ysize; + svga->dac_addr = (svga->dac_addr & 0x00ff) | ((val & 0x03) << 8); + svga_recalctimings(svga); + break; + case 0x02: + case 0x20: + case 0x21: + case 0x22: + if (ramdac->type != BT485A) + break; + else if (svga->dac_addr == 2) { + ramdac->cmd_r4 = val; + break; + } + break; - svga->dac_addr = (svga->dac_addr + 1) & da_mask; - break; - case 0x0c: /* Cursor X Low Register (RS value = 1100) */ - ramdac->hwc_x = (ramdac->hwc_x & 0x0f00) | val; - svga->dac_hwcursor.x = ramdac->hwc_x - svga->dac_hwcursor.xsize; - break; - case 0x0d: /* Cursor X High Register (RS value = 1101) */ - ramdac->hwc_x = (ramdac->hwc_x & 0x00ff) | ((val & 0x0f) << 8); - svga->dac_hwcursor.x = ramdac->hwc_x - svga->dac_hwcursor.xsize; - break; - case 0x0e: /* Cursor Y Low Register (RS value = 1110) */ - ramdac->hwc_y = (ramdac->hwc_y & 0x0f00) | val; - svga->dac_hwcursor.y = ramdac->hwc_y - svga->dac_hwcursor.ysize; - break; - case 0x0f: /* Cursor Y High Register (RS value = 1111) */ - ramdac->hwc_y = (ramdac->hwc_y & 0x00ff) | ((val & 0x0f) << 8); - svga->dac_hwcursor.y = ramdac->hwc_y - svga->dac_hwcursor.ysize; - break; + default: + break; + } + } + break; + case 0x0b: /* Cursor RAM Data Register (RS value = 1011) */ + index = svga->dac_addr & da_mask; + if ((ramdac->type >= BT485) && (svga->dac_hwcursor.cur_xsize == 64)) + cd = (uint8_t *) ramdac->cursor64_data; + else { + index &= 0xff; + cd = (uint8_t *) ramdac->cursor32_data; + } + + cd[index] = val; + + svga->dac_addr = (svga->dac_addr + 1) & da_mask; + break; + case 0x0c: /* Cursor X Low Register (RS value = 1100) */ + ramdac->hwc_x = (ramdac->hwc_x & 0x0f00) | val; + svga->dac_hwcursor.x = ramdac->hwc_x - svga->dac_hwcursor.cur_xsize; + break; + case 0x0d: /* Cursor X High Register (RS value = 1101) */ + ramdac->hwc_x = (ramdac->hwc_x & 0x00ff) | ((val & 0x0f) << 8); + svga->dac_hwcursor.x = ramdac->hwc_x - svga->dac_hwcursor.cur_xsize; + break; + case 0x0e: /* Cursor Y Low Register (RS value = 1110) */ + ramdac->hwc_y = (ramdac->hwc_y & 0x0f00) | val; + svga->dac_hwcursor.y = ramdac->hwc_y - svga->dac_hwcursor.cur_ysize; + break; + case 0x0f: /* Cursor Y High Register (RS value = 1111) */ + ramdac->hwc_y = (ramdac->hwc_y & 0x00ff) | ((val & 0x0f) << 8); + svga->dac_hwcursor.y = ramdac->hwc_y - svga->dac_hwcursor.cur_ysize; + break; + + default: + break; } return; } - uint8_t -bt48x_ramdac_in(uint16_t addr, int rs2, int rs3, void *p, svga_t *svga) +bt48x_ramdac_in(uint16_t addr, int rs2, int rs3, void *priv, svga_t *svga) { - bt48x_ramdac_t *ramdac = (bt48x_ramdac_t *) p; - uint8_t temp = 0xff; - uint8_t *cd; - uint16_t index; - uint8_t rs = (addr & 0x03); - uint16_t da_mask = 0x03ff; + bt48x_ramdac_t *ramdac = (bt48x_ramdac_t *) priv; + uint8_t temp = 0xff; + const uint8_t *cd; + uint16_t index; + uint8_t rs = (addr & 0x03); + uint16_t da_mask = 0x03ff; rs |= (!!rs2 << 2); rs |= (!!rs3 << 3); if (ramdac->type < BT485) - da_mask = 0x00ff; + da_mask = 0x00ff; switch (rs) { - case 0x00: /* Palette Write Index Register (RS value = 0000) */ - case 0x01: /* Palette Data Register (RS value = 0001) */ - case 0x02: /* Pixel Read Mask Register (RS value = 0010) */ - case 0x04: /* Ext Palette Write Index Register (RS value = 0100) */ - temp = svga_in(addr, svga); - break; - case 0x03: /* Palette Read Index Register (RS value = 0011) */ - case 0x07: /* Ext Palette Read Index Register (RS value = 0111) */ - temp = svga->dac_addr & 0xff; - break; - case 0x05: /* Ext Palette Data Register (RS value = 0101) */ - index = (svga->dac_addr - 1) & 3; - svga->dac_status = 3; - switch (svga->dac_pos) { - case 0: - svga->dac_pos++; - if (svga->ramdac_type == RAMDAC_8BIT) - temp = ramdac->extpal[index].r; - else - temp = ramdac->extpal[index].r & 0x3f; - break; - case 1: - svga->dac_pos++; - if (svga->ramdac_type == RAMDAC_8BIT) - temp = ramdac->extpal[index].g; - else - temp = ramdac->extpal[index].g & 0x3f; - break; - case 2: - svga->dac_pos=0; - svga->dac_addr = svga->dac_addr + 1; - if (svga->ramdac_type == RAMDAC_8BIT) - temp = ramdac->extpal[index].b; - else - temp = ramdac->extpal[index].b & 0x3f; - break; - } - break; - case 0x06: /* Command Register 0 (RS value = 0110) */ - temp = ramdac->cmd_r0; - break; - case 0x08: /* Command Register 1 (RS value = 1000) */ - temp = ramdac->cmd_r1; - break; - case 0x09: /* Command Register 2 (RS value = 1001) */ - temp = ramdac->cmd_r2; - break; - case 0x0a: - if ((ramdac->type >= BT485) && (ramdac->cmd_r0 & 0x80)) { - switch ((svga->dac_addr & ((ramdac->type >= BT485A) ? 0xff : 0x3f))) { - case 0x00: - default: - temp = ramdac->status | (svga->dac_status ? 0x04 : 0x00); - break; - case 0x01: - temp = ramdac->cmd_r3 & 0xfc; - temp |= (svga->dac_addr & 0x300) >> 8; - break; - case 0x02: - case 0x20: - case 0x21: - case 0x22: - if (ramdac->type != BT485A) - break; - else if (svga->dac_addr == 2) { - temp = ramdac->cmd_r4; - break; - } else { - /* TODO: Red, Green, and Blue Signature Analysis Registers */ - temp = 0xff; - break; - } - break; - } - } else - temp = ramdac->status | (svga->dac_status ? 0x04 : 0x00); - break; - case 0x0b: /* Cursor RAM Data Register (RS value = 1011) */ - index = (svga->dac_addr - 1) & da_mask; - if ((ramdac->type >= BT485) && (svga->dac_hwcursor.xsize == 64)) - cd = (uint8_t *) ramdac->cursor64_data; - else { - index &= 0xff; - cd = (uint8_t *) ramdac->cursor32_data; - } + case 0x00: /* Palette Write Index Register (RS value = 0000) */ + case 0x01: /* Palette Data Register (RS value = 0001) */ + case 0x02: /* Pixel Read Mask Register (RS value = 0010) */ + case 0x04: /* Ext Palette Write Index Register (RS value = 0100) */ + temp = svga_in(addr, svga); + break; + case 0x03: /* Palette Read Index Register (RS value = 0011) */ + case 0x07: /* Ext Palette Read Index Register (RS value = 0111) */ + temp = svga->dac_addr & 0xff; + break; + case 0x05: /* Ext Palette Data Register (RS value = 0101) */ + index = (svga->dac_addr - 1) & 3; + svga->dac_status = 3; + switch (svga->dac_pos) { + case 0: + svga->dac_pos++; + if (svga->ramdac_type == RAMDAC_8BIT) + temp = ramdac->extpal[index].r; + else + temp = ramdac->extpal[index].r & 0x3f; + break; + case 1: + svga->dac_pos++; + if (svga->ramdac_type == RAMDAC_8BIT) + temp = ramdac->extpal[index].g; + else + temp = ramdac->extpal[index].g & 0x3f; + break; + case 2: + svga->dac_pos = 0; + svga->dac_addr = svga->dac_addr + 1; + if (svga->ramdac_type == RAMDAC_8BIT) + temp = ramdac->extpal[index].b; + else + temp = ramdac->extpal[index].b & 0x3f; + break; - temp = cd[index]; + default: + break; + } + break; + case 0x06: /* Command Register 0 (RS value = 0110) */ + temp = ramdac->cmd_r0; + break; + case 0x08: /* Command Register 1 (RS value = 1000) */ + temp = ramdac->cmd_r1; + break; + case 0x09: /* Command Register 2 (RS value = 1001) */ + temp = ramdac->cmd_r2; + break; + case 0x0a: + if ((ramdac->type >= BT485) && (ramdac->cmd_r0 & 0x80)) { + switch (svga->dac_addr & ((ramdac->type >= BT485A) ? 0xff : 0x3f)) { + default: + case 0x00: + temp = ramdac->status | (svga->dac_status ? 0x04 : 0x00); + break; + case 0x01: + temp = ramdac->cmd_r3 & 0xfc; + temp |= (svga->dac_addr & 0x300) >> 8; + break; + case 0x02: + case 0x20: + case 0x21: + case 0x22: + if (ramdac->type != BT485A) + break; + else if (svga->dac_addr == 2) { + temp = ramdac->cmd_r4; + break; + } else { + /* TODO: Red, Green, and Blue Signature Analysis Registers */ + temp = 0xff; + break; + } + } + } else + temp = ramdac->status | (svga->dac_status ? 0x04 : 0x00); + break; + case 0x0b: /* Cursor RAM Data Register (RS value = 1011) */ + index = (svga->dac_addr - 1) & da_mask; + if ((ramdac->type >= BT485) && (svga->dac_hwcursor.cur_xsize == 64)) + cd = (uint8_t *) ramdac->cursor64_data; + else { + index &= 0xff; + cd = (uint8_t *) ramdac->cursor32_data; + } - svga->dac_addr = (svga->dac_addr + 1) & da_mask; - break; - case 0x0c: /* Cursor X Low Register (RS value = 1100) */ - temp = ramdac->hwc_x & 0xff; - break; - case 0x0d: /* Cursor X High Register (RS value = 1101) */ - temp = (ramdac->hwc_x >> 8) & 0xff; - break; - case 0x0e: /* Cursor Y Low Register (RS value = 1110) */ - temp = ramdac->hwc_y & 0xff; - break; - case 0x0f: /* Cursor Y High Register (RS value = 1111) */ - temp = (ramdac->hwc_y >> 8) & 0xff; - break; + temp = cd[index]; + + svga->dac_addr = (svga->dac_addr + 1) & da_mask; + break; + case 0x0c: /* Cursor X Low Register (RS value = 1100) */ + temp = ramdac->hwc_x & 0xff; + break; + case 0x0d: /* Cursor X High Register (RS value = 1101) */ + temp = (ramdac->hwc_x >> 8) & 0xff; + break; + case 0x0e: /* Cursor Y Low Register (RS value = 1110) */ + temp = ramdac->hwc_y & 0xff; + break; + case 0x0f: /* Cursor Y High Register (RS value = 1111) */ + temp = (ramdac->hwc_y >> 8) & 0xff; + break; + + default: + break; } return temp; } - void -bt48x_recalctimings(void *p, svga_t *svga) +bt48x_recalctimings(void *priv, svga_t *svga) { - bt48x_ramdac_t *ramdac = (bt48x_ramdac_t *) p; + const bt48x_ramdac_t *ramdac = (bt48x_ramdac_t *) priv; svga->interlace = ramdac->cmd_r2 & 0x08; if (ramdac->cmd_r3 & 0x08) - svga->hdisp *= 2; /* x2 clock multiplier */ + svga->hdisp *= 2; /* x2 clock multiplier */ } - void bt48x_hwcursor_draw(svga_t *svga, int displine) { - int x, xx, comb, b0, b1; - uint16_t dat[2]; - int offset = svga->dac_hwcursor_latch.x - svga->dac_hwcursor_latch.xoff; - int pitch, bppl, mode, x_pos, y_pos; - uint32_t clr1, clr2, clr3, *p; - uint8_t *cd; + int comb; + int b0; + int b1; + uint16_t dat[2]; + int offset = svga->dac_hwcursor_latch.x - svga->dac_hwcursor_latch.xoff; + int pitch; + int bppl; + int mode; + int x_pos; + int y_pos; + uint32_t clr1; + uint32_t clr2; + uint32_t clr3; + uint32_t *p; + const uint8_t *cd; bt48x_ramdac_t *ramdac = (bt48x_ramdac_t *) svga->ramdac; clr1 = ramdac->extpallook[1]; @@ -376,85 +396,94 @@ bt48x_hwcursor_draw(svga_t *svga, int displine) /* The planes come in two parts, and each plane is 1bpp, so a 32x32 cursor has 4 bytes per line, and a 64x64 cursor has 8 bytes per line. */ - pitch = (svga->dac_hwcursor_latch.xsize >> 3); /* Bytes per line. */ + pitch = (svga->dac_hwcursor_latch.cur_xsize >> 3); /* Bytes per line. */ /* A 32x32 cursor has 128 bytes per line, and a 64x64 cursor has 512 bytes per line. */ - bppl = (pitch * svga->dac_hwcursor_latch.ysize); /* Bytes per plane. */ + bppl = (pitch * svga->dac_hwcursor_latch.cur_ysize); /* Bytes per plane. */ mode = ramdac->cmd_r2 & 0x03; if (svga->interlace && svga->dac_hwcursor_oddeven) - svga->dac_hwcursor_latch.addr += pitch; + svga->dac_hwcursor_latch.addr += pitch; - if (svga->dac_hwcursor_latch.xsize == 64) - cd = (uint8_t *) ramdac->cursor64_data; + if (svga->dac_hwcursor_latch.cur_xsize == 64) + cd = (uint8_t *) ramdac->cursor64_data; else - cd = (uint8_t *) ramdac->cursor32_data; + cd = (uint8_t *) ramdac->cursor32_data; - for (x = 0; x < svga->dac_hwcursor_latch.xsize; x += 16) { - dat[0] = (cd[svga->dac_hwcursor_latch.addr] << 8) | - cd[svga->dac_hwcursor_latch.addr + 1]; - dat[1] = (cd[svga->dac_hwcursor_latch.addr + bppl] << 8) | - cd[svga->dac_hwcursor_latch.addr + bppl + 1]; + for (int x = 0; x < svga->dac_hwcursor_latch.cur_xsize; x += 16) { + dat[0] = (cd[svga->dac_hwcursor_latch.addr] << 8) | cd[svga->dac_hwcursor_latch.addr + 1]; + dat[1] = (cd[svga->dac_hwcursor_latch.addr + bppl] << 8) | cd[svga->dac_hwcursor_latch.addr + bppl + 1]; - for (xx = 0; xx < 16; xx++) { - b0 = (dat[0] >> (15 - xx)) & 1; - b1 = (dat[1] >> (15 - xx)) & 1; - comb = (b0 | (b1 << 1)); + for (uint8_t xx = 0; xx < 16; xx++) { + b0 = (dat[0] >> (15 - xx)) & 1; + b1 = (dat[1] >> (15 - xx)) & 1; + comb = (b0 | (b1 << 1)); - y_pos = displine; - x_pos = offset + svga->x_add; - p = buffer32->line[y_pos]; + y_pos = displine; + x_pos = offset + svga->x_add; + p = buffer32->line[y_pos]; - if (offset >= svga->dac_hwcursor_latch.x) { - switch (mode) { - case 1: /* Three Color */ - switch (comb) { - case 1: - p[x_pos] = clr1; - break; - case 2: - p[x_pos] = clr2; - break; - case 3: - p[x_pos] = clr3; - break; - } - break; - case 2: /* PM/Windows */ - switch (comb) { - case 0: - p[x_pos] = clr1; - break; - case 1: - p[x_pos] = clr2; - break; - case 3: - p[x_pos] ^= 0xffffff; - break; - } - break; - case 3: /* X-Windows */ - switch (comb) { - case 2: - p[x_pos] = clr1; - break; - case 3: - p[x_pos] = clr2; - break; - } - break; - } - } - offset++; - } - svga->dac_hwcursor_latch.addr += 2; + if (offset >= svga->dac_hwcursor_latch.x) { + switch (mode) { + case 1: /* Three Color */ + switch (comb) { + case 1: + p[x_pos] = clr1; + break; + case 2: + p[x_pos] = clr2; + break; + case 3: + p[x_pos] = clr3; + break; + + default: + break; + } + break; + case 2: /* PM/Windows */ + switch (comb) { + case 0: + p[x_pos] = clr1; + break; + case 1: + p[x_pos] = clr2; + break; + case 3: + p[x_pos] ^= 0xffffff; + break; + + default: + break; + } + break; + case 3: /* X-Windows */ + switch (comb) { + case 2: + p[x_pos] = clr1; + break; + case 3: + p[x_pos] = clr2; + break; + + default: + break; + } + break; + + default: + break; + } + } + offset++; + } + svga->dac_hwcursor_latch.addr += 2; } if (svga->interlace && !svga->dac_hwcursor_oddeven) - svga->dac_hwcursor_latch.addr += pitch; + svga->dac_hwcursor_latch.addr += pitch; } - void * bt48x_ramdac_init(const device_t *info) { @@ -465,82 +494,108 @@ bt48x_ramdac_init(const device_t *info) /* Set the RAM DAC status byte to the correct ID bits. - Both the BT484 and BT485 datasheets say this: - SR7-SR6: These bits are identification values. SR7=0 and SR6=1. - But all other sources seem to assume SR7=1 and SR6=0. */ + Both the BT484 and BT485 datasheets say this: + SR7-SR6: These bits are identification values. SR7=0 and SR6=1. + But all other sources seem to assume SR7=1 and SR6=0. */ switch (ramdac->type) { - case BT484: - ramdac->status = 0x40; - break; - case ATT20C504: - ramdac->status = 0x40; - break; - case BT485: - ramdac->status = 0x60; - break; - case ATT20C505: - ramdac->status = 0xd0; - break; - case BT485A: - ramdac->status = 0x20; - break; + case BT484: + ramdac->status = 0x40; + break; + case ATT20C504: + ramdac->status = 0x40; + break; + case BT485: + ramdac->status = 0x60; + break; + case ATT20C505: + ramdac->status = 0xd0; + break; + case BT485A: + ramdac->status = 0x20; + break; + + default: + break; } return ramdac; } - static void bt48x_ramdac_close(void *priv) { bt48x_ramdac_t *ramdac = (bt48x_ramdac_t *) priv; if (ramdac) - free(ramdac); + free(ramdac); } - -const device_t bt484_ramdac_device = -{ - "Brooktree Bt484 RAMDAC", - "bt484_ramdac", - 0, BT484, - bt48x_ramdac_init, bt48x_ramdac_close, - NULL, { NULL }, NULL, NULL +const device_t bt484_ramdac_device = { + .name = "Brooktree Bt484 RAMDAC", + .internal_name = "bt484_ramdac", + .flags = 0, + .local = BT484, + .init = bt48x_ramdac_init, + .close = bt48x_ramdac_close, + .reset = NULL, + { .available = NULL }, + .speed_changed = NULL, + .force_redraw = NULL, + .config = NULL }; -const device_t att20c504_ramdac_device = -{ - "AT&T 20c504 RAMDAC", - "att20c504_ramdac", - 0, ATT20C504, - bt48x_ramdac_init, bt48x_ramdac_close, - NULL, { NULL }, NULL, NULL +const device_t att20c504_ramdac_device = { + .name = "AT&T 20c504 RAMDAC", + .internal_name = "att20c504_ramdac", + .flags = 0, + .local = ATT20C504, + .init = bt48x_ramdac_init, + .close = bt48x_ramdac_close, + .reset = NULL, + { .available = NULL }, + .speed_changed = NULL, + .force_redraw = NULL, + .config = NULL }; -const device_t bt485_ramdac_device = -{ - "Brooktree Bt485 RAMDAC", - "bt485_ramdac", - 0, BT485, - bt48x_ramdac_init, bt48x_ramdac_close, - NULL, { NULL }, NULL, NULL +const device_t bt485_ramdac_device = { + .name = "Brooktree Bt485 RAMDAC", + .internal_name = "bt485_ramdac", + .flags = 0, + .local = BT485, + .init = bt48x_ramdac_init, + .close = bt48x_ramdac_close, + .reset = NULL, + { .available = NULL }, + .speed_changed = NULL, + .force_redraw = NULL, + .config = NULL }; -const device_t att20c505_ramdac_device = -{ - "AT&T 20c505 RAMDAC", - "att20c505_ramdac", - 0, ATT20C505, - bt48x_ramdac_init, bt48x_ramdac_close, - NULL, { NULL }, NULL, NULL +const device_t att20c505_ramdac_device = { + .name = "AT&T 20c505 RAMDAC", + .internal_name = "att20c505_ramdac", + .flags = 0, + .local = ATT20C505, + .init = bt48x_ramdac_init, + .close = bt48x_ramdac_close, + .reset = NULL, + { .available = NULL }, + .speed_changed = NULL, + .force_redraw = NULL, + .config = NULL }; -const device_t bt485a_ramdac_device = -{ - "Brooktree Bt485A RAMDAC", - "bt485a_ramdac", - 0, BT485A, - bt48x_ramdac_init, bt48x_ramdac_close, - NULL, { NULL }, NULL, NULL +const device_t bt485a_ramdac_device = { + .name = "Brooktree Bt485A RAMDAC", + .internal_name = "bt485a_ramdac", + .flags = 0, + .local = BT485A, + .init = bt48x_ramdac_init, + .close = bt48x_ramdac_close, + .reset = NULL, + { .available = NULL }, + .speed_changed = NULL, + .force_redraw = NULL, + .config = NULL }; diff --git a/src/video/vid_cga.c b/src/video/vid_cga.c index 651039517..3d806d95b 100644 --- a/src/video/vid_cga.c +++ b/src/video/vid_cga.c @@ -1,20 +1,22 @@ /* - * 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. + * 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. + * This file is part of the 86Box distribution. * - * Emulation of the old and new IBM CGA graphics cards. + * Emulation of the old and new IBM CGA graphics cards. * * * - * Authors: Sarah Walker, - * Miran Grca, + * Authors: Sarah Walker, + * Miran Grca, + * W. M. Martinez, * - * Copyright 2008-2019 Sarah Walker. - * Copyright 2016-2019 Miran Grca. + * Copyright 2008-2019 Sarah Walker. + * Copyright 2016-2019 Miran Grca. + * Copyright 2023 W. M. Martinez */ #include #include @@ -33,491 +35,482 @@ #include <86box/video.h> #include <86box/vid_cga.h> #include <86box/vid_cga_comp.h> +#include <86box/plat_unused.h> - -#define CGA_RGB 0 +#define CGA_RGB 0 #define CGA_COMPOSITE 1 #define COMPOSITE_OLD 0 #define COMPOSITE_NEW 1 -static uint8_t 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 uint8_t 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 video_timings_t timing_cga = {VIDEO_ISA, 8, 16, 32, 8, 16, 32}; +static video_timings_t timing_cga = { .type = VIDEO_ISA, .write_b = 8, .write_w = 16, .write_l = 32, .read_b = 8, .read_w = 16, .read_l = 32 }; void cga_recalctimings(cga_t *cga); - void -cga_out(uint16_t addr, uint8_t val, void *p) +cga_out(uint16_t addr, uint8_t val, void *priv) { - cga_t *cga = (cga_t *) p; + cga_t *cga = (cga_t *) priv; uint8_t old; if ((addr >= 0x3d0) && (addr <= 0x3d7)) - addr = (addr & 0xff9) | 0x004; + addr = (addr & 0xff9) | 0x004; switch (addr) { - case 0x3D4: - cga->crtcreg = val & 31; - return; - case 0x3D5: - old = cga->crtc[cga->crtcreg]; - cga->crtc[cga->crtcreg] = val & crtcmask[cga->crtcreg]; - if (old != val) { - if ((cga->crtcreg < 0xe) || (cga->crtcreg > 0x10)) { - fullchange = changeframecount; - cga_recalctimings(cga); - } - } - return; - case 0x3D8: - old = cga->cgamode; - cga->cgamode = val; + case 0x3D4: + cga->crtcreg = val & 31; + return; + case 0x3D5: + old = cga->crtc[cga->crtcreg]; + cga->crtc[cga->crtcreg] = val & crtcmask[cga->crtcreg]; + if (old != val) { + if ((cga->crtcreg < 0xe) || (cga->crtcreg > 0x10)) { + cga->fullchange = changeframecount; + cga_recalctimings(cga); + } + } + return; + case 0x3D8: + old = cga->cgamode; + cga->cgamode = val; - if (old ^ val) { - if ((old ^ val) & 0x05) - update_cga16_color(val); + if (old ^ val) { + if ((old ^ val) & 0x07) + update_cga16_color(val); - cga_recalctimings(cga); - } - return; - case 0x3D9: - old = cga->cgacol; - cga->cgacol = val; - if (old ^ val) - cga_recalctimings(cga); - return; + cga_recalctimings(cga); + } + return; + case 0x3D9: + old = cga->cgacol; + cga->cgacol = val; + if (old ^ val) + cga_recalctimings(cga); + return; + + default: + break; } } - uint8_t -cga_in(uint16_t addr, void *p) +cga_in(uint16_t addr, void *priv) { - cga_t *cga = (cga_t *) p; + const cga_t *cga = (cga_t *) priv; uint8_t ret = 0xff; if ((addr >= 0x3d0) && (addr <= 0x3d7)) - addr = (addr & 0xff9) | 0x004; + addr = (addr & 0xff9) | 0x004; switch (addr) { - case 0x3D4: - ret = cga->crtcreg; - break; - case 0x3D5: - ret = cga->crtc[cga->crtcreg]; - break; - case 0x3DA: - ret = cga->cgastat; - break; + case 0x3D4: + ret = cga->crtcreg; + break; + case 0x3D5: + ret = cga->crtc[cga->crtcreg]; + break; + case 0x3DA: + ret = cga->cgastat; + break; + + default: + break; } return ret; } +void +cga_pravetz_out(UNUSED(uint16_t addr), uint8_t val, void *priv) +{ + cga_t *cga = (cga_t *) priv; + + cga->fontbase = (((unsigned int) val) << 8); +} + +uint8_t +cga_pravetz_in(UNUSED(uint16_t addr), void *priv) +{ + const cga_t *cga = (cga_t *) priv; + + return (cga->fontbase >> 8); +} void -cga_waitstates(void *p) +cga_waitstates(UNUSED(void *priv)) { - int ws_array[16] = {3, 4, 5, 6, 7, 8, 4, 5, 6, 7, 8, 4, 5, 6, 7, 8}; + 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]; cycles -= ws; } - void -cga_write(uint32_t addr, uint8_t val, void *p) +cga_write(uint32_t addr, uint8_t val, void *priv) { - cga_t *cga = (cga_t *) p; + cga_t *cga = (cga_t *) priv; cga->vram[addr & 0x3fff] = val; if (cga->snow_enabled) { - int offset = ((timer_get_remaining_u64(&cga->timer) / CGACONST) * 2) & 0xfc; - cga->charbuffer[offset] = cga->vram[addr & 0x3fff]; - cga->charbuffer[offset | 1] = cga->vram[addr & 0x3fff]; + int offset = ((timer_get_remaining_u64(&cga->timer) / CGACONST) * 2) & 0xfc; + cga->charbuffer[offset] = cga->vram[addr & 0x3fff]; + cga->charbuffer[offset | 1] = cga->vram[addr & 0x3fff]; } cga_waitstates(cga); } - uint8_t -cga_read(uint32_t addr, void *p) +cga_read(uint32_t addr, void *priv) { - cga_t *cga = (cga_t *) p; + cga_t *cga = (cga_t *) priv; cga_waitstates(cga); if (cga->snow_enabled) { - int offset = ((timer_get_remaining_u64(&cga->timer) / CGACONST) * 2) & 0xfc; - cga->charbuffer[offset] = cga->vram[addr & 0x3fff]; - cga->charbuffer[offset | 1] = cga->vram[addr & 0x3fff]; + int offset = ((timer_get_remaining_u64(&cga->timer) / CGACONST) * 2) & 0xfc; + cga->charbuffer[offset] = cga->vram[addr & 0x3fff]; + cga->charbuffer[offset | 1] = cga->vram[addr & 0x3fff]; } return cga->vram[addr & 0x3fff]; } - void cga_recalctimings(cga_t *cga) { double disptime; - double _dispontime, _dispofftime; + double _dispontime; + double _dispofftime; if (cga->cgamode & 1) { - disptime = (double) (cga->crtc[0] + 1); - _dispontime = (double) cga->crtc[1]; + disptime = (double) (cga->crtc[0] + 1); + _dispontime = (double) cga->crtc[1]; } else { - disptime = (double) ((cga->crtc[0] + 1) << 1); - _dispontime = (double) (cga->crtc[1] << 1); + disptime = (double) ((cga->crtc[0] + 1) << 1); + _dispontime = (double) (cga->crtc[1] << 1); } - _dispofftime = disptime - _dispontime; - _dispontime = _dispontime * CGACONST; - _dispofftime = _dispofftime * CGACONST; - cga->dispontime = (uint64_t)(_dispontime); - cga->dispofftime = (uint64_t)(_dispofftime); + _dispofftime = disptime - _dispontime; + _dispontime = _dispontime * CGACONST; + _dispofftime = _dispofftime * CGACONST; + cga->dispontime = (uint64_t) (_dispontime); + cga->dispofftime = (uint64_t) (_dispofftime); } - void -cga_poll(void *p) +cga_poll(void *priv) { - cga_t *cga = (cga_t *)p; - uint16_t ca = (cga->crtc[15] | (cga->crtc[14] << 8)) & 0x3fff; - int drawcursor; - int x, c, xs_temp, ys_temp; - int oldvc; - uint8_t chr, attr; - uint8_t border; + cga_t *cga = (cga_t *) priv; + uint16_t ca = (cga->crtc[15] | (cga->crtc[14] << 8)) & 0x3fff; + int drawcursor; + int x; + int c; + int xs_temp; + int ys_temp; + int oldvc; + uint8_t chr; + uint8_t attr; + uint8_t border; uint16_t dat; - int cols[4]; - int col; - int oldsc; + int cols[4]; + int col; + int oldsc; if (!cga->linepos) { - timer_advance_u64(&cga->timer, cga->dispofftime); - cga->cgastat |= 1; - cga->linepos = 1; - oldsc = cga->sc; - if ((cga->crtc[8] & 3) == 3) - cga->sc = ((cga->sc << 1) + cga->oddeven) & 7; - if (cga->cgadispon) { - if (cga->displine < cga->firstline) { - cga->firstline = cga->displine; - video_wait_for_buffer(); - } - cga->lastline = cga->displine; - for (c = 0; c < 8; c++) { - if ((cga->cgamode & 0x12) == 0x12) { - buffer32->line[(cga->displine << 1)][c] = - buffer32->line[(cga->displine << 1) + 1][c] = 0; - if (cga->cgamode & 1) { - buffer32->line[(cga->displine << 1)][c + (cga->crtc[1] << 3) + 8] = - buffer32->line[(cga->displine << 1) + 1][c + (cga->crtc[1] << 3) + 8] = 0; - } else { - buffer32->line[(cga->displine << 1)][c + (cga->crtc[1] << 4) + 8] = - buffer32->line[(cga->displine << 1) + 1][c + (cga->crtc[1] << 4) + 8] = 0; - } - } else { - buffer32->line[(cga->displine << 1)][c] = - buffer32->line[(cga->displine << 1) + 1][c] = (cga->cgacol & 15) + 16; - if (cga->cgamode & 1) { - buffer32->line[(cga->displine << 1)][c + (cga->crtc[1] << 3) + 8] = - buffer32->line[(cga->displine << 1) + 1][c + (cga->crtc[1] << 3) + 8] = (cga->cgacol & 15) + 16; - } else { - buffer32->line[(cga->displine << 1)][c + (cga->crtc[1] << 4) + 8] = - buffer32->line[(cga->displine << 1) + 1][c + (cga->crtc[1] << 4) + 8] = (cga->cgacol & 15) + 16; - } - } - } - if (cga->cgamode & 1) { - for (x = 0; x < cga->crtc[1]; x++) { - if (cga->cgamode & 8) { - chr = cga->charbuffer[x << 1]; - attr = cga->charbuffer[(x << 1) + 1]; - } else - chr = attr = 0; - drawcursor = ((cga->ma == ca) && cga->con && cga->cursoron); - cols[1] = (attr & 15) + 16; - if (cga->cgamode & 0x20) { - cols[0] = ((attr >> 4) & 7) + 16; - if ((cga->cgablink & 8) && (attr & 0x80) && !cga->drawcursor) - cols[1] = cols[0]; - } else - cols[0] = (attr >> 4) + 16; - if (drawcursor) { - for (c = 0; c < 8; c++) { - buffer32->line[(cga->displine << 1)][(x << 3) + c + 8] = - buffer32->line[(cga->displine << 1) + 1][(x << 3) + c + 8] = - cols[(fontdat[chr + cga->fontbase][cga->sc & 7] & (1 << (c ^ 7))) ? 1 : 0] ^ 15; - } - } else { - for (c = 0; c < 8; c++) { - buffer32->line[(cga->displine << 1)][(x << 3) + c + 8] = - buffer32->line[(cga->displine << 1) + 1][(x << 3) + c + 8] = - cols[(fontdat[chr + cga->fontbase][cga->sc & 7] & (1 << (c ^ 7))) ? 1 : 0]; - } - } - cga->ma++; - } - } else if (!(cga->cgamode & 2)) { - for (x = 0; x < cga->crtc[1]; x++) { - if (cga->cgamode & 8) { - chr = cga->vram[((cga->ma << 1) & 0x3fff)]; - attr = cga->vram[(((cga->ma << 1) + 1) & 0x3fff)]; - } else - chr = attr = 0; - drawcursor = ((cga->ma == ca) && cga->con && cga->cursoron); - cols[1] = (attr & 15) + 16; - if (cga->cgamode & 0x20) { - cols[0] = ((attr >> 4) & 7) + 16; - if ((cga->cgablink & 8) && (attr & 0x80)) - cols[1] = cols[0]; - } else - cols[0] = (attr >> 4) + 16; - cga->ma++; - if (drawcursor) { - for (c = 0; c < 8; c++) { - buffer32->line[(cga->displine << 1)][(x << 4) + (c << 1) + 8] = - buffer32->line[(cga->displine << 1)][(x << 4) + (c << 1) + 1 + 8] = - buffer32->line[(cga->displine << 1) + 1][(x << 4) + (c << 1) + 8] = - buffer32->line[(cga->displine << 1) + 1][(x << 4) + (c << 1) + 1 + 8] = - cols[(fontdat[chr + cga->fontbase][cga->sc & 7] & (1 << (c ^ 7))) ? 1 : 0] ^ 15; - } - } else { - for (c = 0; c < 8; c++) { - buffer32->line[(cga->displine << 1)][(x << 4) + (c << 1) + 8] = - buffer32->line[(cga->displine << 1)][(x << 4) + (c << 1) + 1 + 8] = - buffer32->line[(cga->displine << 1) + 1][(x << 4) + (c << 1) + 8] = - buffer32->line[(cga->displine << 1) + 1][(x << 4) + (c << 1) + 1 + 8] = - cols[(fontdat[chr + cga->fontbase][cga->sc & 7] & (1 << (c ^ 7))) ? 1 : 0]; - } - } - } - } else if (!(cga->cgamode & 16)) { - cols[0] = (cga->cgacol & 15) | 16; - col = (cga->cgacol & 16) ? 24 : 16; - if (cga->cgamode & 4) { - cols[1] = col | 3; /* Cyan */ - cols[2] = col | 4; /* Red */ - cols[3] = col | 7; /* White */ - } else if (cga->cgacol & 32) { - cols[1] = col | 3; /* Cyan */ - cols[2] = col | 5; /* Magenta */ - cols[3] = col | 7; /* White */ - } else { - cols[1] = col | 2; /* Green */ - cols[2] = col | 4; /* Red */ - cols[3] = col | 6; /* Yellow */ - } - for (x = 0; x < cga->crtc[1]; x++) { - if (cga->cgamode & 8) - dat = (cga->vram[((cga->ma << 1) & 0x1fff) + ((cga->sc & 1) * 0x2000)] << 8) | cga->vram[((cga->ma << 1) & 0x1fff) + ((cga->sc & 1) * 0x2000) + 1]; - else - dat = 0; - cga->ma++; - for (c = 0; c < 8; c++) { - buffer32->line[(cga->displine << 1)][(x << 4) + (c << 1) + 8] = - buffer32->line[(cga->displine << 1)][(x << 4) + (c << 1) + 1 + 8] = - buffer32->line[(cga->displine << 1) + 1][(x << 4) + (c << 1) + 8] = - buffer32->line[(cga->displine << 1) + 1][(x << 4) + (c << 1) + 1 + 8] = - cols[dat >> 14]; - dat <<= 2; - } - } - } else { - cols[0] = 0; cols[1] = (cga->cgacol & 15) + 16; - for (x = 0; x < cga->crtc[1]; x++) { - if (cga->cgamode & 8) - dat = (cga->vram[((cga->ma << 1) & 0x1fff) + ((cga->sc & 1) * 0x2000)] << 8) | cga->vram[((cga->ma << 1) & 0x1fff) + ((cga->sc & 1) * 0x2000) + 1]; - else - dat = 0; - cga->ma++; - for (c = 0; c < 16; c++) { - buffer32->line[(cga->displine << 1)][(x << 4) + c + 8] = - buffer32->line[(cga->displine << 1) + 1][(x << 4) + c + 8] = - cols[dat >> 15]; - dat <<= 1; - } - } - } - } else { - cols[0] = ((cga->cgamode & 0x12) == 0x12) ? 0 : (cga->cgacol & 15) + 16; - if (cga->cgamode & 1) { - hline(buffer32, 0, (cga->displine << 1), ((cga->crtc[1] << 3) + 16) << 2, cols[0]); - hline(buffer32, 0, (cga->displine << 1) + 1, ((cga->crtc[1] << 3) + 16) << 2, cols[0]); - } else { - hline(buffer32, 0, (cga->displine << 1), ((cga->crtc[1] << 4) + 16) << 2, cols[0]); - hline(buffer32, 0, (cga->displine << 1) + 1, ((cga->crtc[1] << 4) + 16) << 2, cols[0]); - } - } + timer_advance_u64(&cga->timer, cga->dispofftime); + cga->cgastat |= 1; + cga->linepos = 1; + oldsc = cga->sc; + if ((cga->crtc[8] & 3) == 3) + cga->sc = ((cga->sc << 1) + cga->oddeven) & 7; + if (cga->cgadispon) { + if (cga->displine < cga->firstline) { + cga->firstline = cga->displine; + video_wait_for_buffer(); + } + cga->lastline = cga->displine; + if ((cga->cgamode & 0x12) == 0x12) { + for (c = 0; c < 8; ++c) { + buffer32->line[cga->displine][c] = 0; + if (cga->cgamode & 1) + buffer32->line[cga->displine][c + (cga->crtc[1] << 3) + 8] = 0; + else + buffer32->line[cga->displine][c + (cga->crtc[1] << 4) + 8] = 0; + } + } else { + for (c = 0; c < 8; ++c) { + buffer32->line[cga->displine][c] = (cga->cgacol & 15) + 16; + if (cga->cgamode & 1) + buffer32->line[cga->displine][c + (cga->crtc[1] << 3) + 8] = (cga->cgacol & 15) + 16; + else + buffer32->line[cga->displine][c + (cga->crtc[1] << 4) + 8] = (cga->cgacol & 15) + 16; + } + } + if (cga->cgamode & 1) { + for (x = 0; x < cga->crtc[1]; x++) { + if (cga->cgamode & 8) { + chr = cga->charbuffer[x << 1]; + attr = cga->charbuffer[(x << 1) + 1]; + } else + chr = attr = 0; + drawcursor = ((cga->ma == ca) && cga->con && cga->cursoron); + cols[1] = (attr & 15) + 16; + if (cga->cgamode & 0x20) { + cols[0] = ((attr >> 4) & 7) + 16; + if ((cga->cgablink & 8) && (attr & 0x80) && !cga->drawcursor) + cols[1] = cols[0]; + } else + cols[0] = (attr >> 4) + 16; + if (drawcursor) { + for (c = 0; c < 8; c++) { + buffer32->line[cga->displine][(x << 3) + c + 8] = cols[(fontdat[chr + cga->fontbase][cga->sc & 7] & (1 << (c ^ 7))) ? 1 : 0] ^ 15; + } + } else { + for (c = 0; c < 8; c++) { + buffer32->line[cga->displine][(x << 3) + c + 8] = cols[(fontdat[chr + cga->fontbase][cga->sc & 7] & (1 << (c ^ 7))) ? 1 : 0]; + } + } + cga->ma++; + } + } else if (!(cga->cgamode & 2)) { + for (x = 0; x < cga->crtc[1]; x++) { + if (cga->cgamode & 8) { + chr = cga->vram[(cga->ma << 1) & 0x3fff]; + attr = cga->vram[((cga->ma << 1) + 1) & 0x3fff]; + } else + chr = attr = 0; + drawcursor = ((cga->ma == ca) && cga->con && cga->cursoron); + cols[1] = (attr & 15) + 16; + if (cga->cgamode & 0x20) { + cols[0] = ((attr >> 4) & 7) + 16; + if ((cga->cgablink & 8) && (attr & 0x80)) + cols[1] = cols[0]; + } else + cols[0] = (attr >> 4) + 16; + cga->ma++; + if (drawcursor) { + for (c = 0; c < 8; c++) { + buffer32->line[cga->displine][(x << 4) + (c << 1) + 8] + = buffer32->line[cga->displine][(x << 4) + (c << 1) + 9] + = cols[(fontdat[chr + cga->fontbase][cga->sc & 7] & (1 << (c ^ 7))) ? 1 : 0] ^ 15; + } + } else { + for (c = 0; c < 8; c++) { + buffer32->line[cga->displine][(x << 4) + (c << 1) + 8] + = buffer32->line[cga->displine][(x << 4) + (c << 1) + 9] + = cols[(fontdat[chr + cga->fontbase][cga->sc & 7] & (1 << (c ^ 7))) ? 1 : 0]; + } + } + } + } else if (!(cga->cgamode & 16)) { + cols[0] = (cga->cgacol & 15) | 16; + col = (cga->cgacol & 16) ? 24 : 16; + if (cga->cgamode & 4) { + cols[1] = col | 3; /* Cyan */ + cols[2] = col | 4; /* Red */ + cols[3] = col | 7; /* White */ + } else if (cga->cgacol & 32) { + cols[1] = col | 3; /* Cyan */ + cols[2] = col | 5; /* Magenta */ + cols[3] = col | 7; /* White */ + } else { + cols[1] = col | 2; /* Green */ + cols[2] = col | 4; /* Red */ + cols[3] = col | 6; /* Yellow */ + } + for (x = 0; x < cga->crtc[1]; x++) { + if (cga->cgamode & 8) + dat = (cga->vram[((cga->ma << 1) & 0x1fff) + ((cga->sc & 1) * 0x2000)] << 8) | cga->vram[((cga->ma << 1) & 0x1fff) + ((cga->sc & 1) * 0x2000) + 1]; + else + dat = 0; + cga->ma++; + for (c = 0; c < 8; c++) { + buffer32->line[cga->displine][(x << 4) + (c << 1) + 8] + = buffer32->line[cga->displine][(x << 4) + (c << 1) + 9] + = cols[dat >> 14]; + dat <<= 2; + } + } + } else { + cols[0] = 0; + cols[1] = (cga->cgacol & 15) + 16; + for (x = 0; x < cga->crtc[1]; x++) { + if (cga->cgamode & 8) + dat = (cga->vram[((cga->ma << 1) & 0x1fff) + ((cga->sc & 1) * 0x2000)] << 8) | cga->vram[((cga->ma << 1) & 0x1fff) + ((cga->sc & 1) * 0x2000) + 1]; + else + dat = 0; + cga->ma++; + for (c = 0; c < 16; c++) { + buffer32->line[cga->displine][(x << 4) + c + 8] = cols[dat >> 15]; + dat <<= 1; + } + } + } + } else { + cols[0] = ((cga->cgamode & 0x12) == 0x12) ? 0 : (cga->cgacol & 15) + 16; + if (cga->cgamode & 1) { + hline(buffer32, 0, cga->displine, (cga->crtc[1] << 3) + 16, cols[0]); + } else { + hline(buffer32, 0, cga->displine, (cga->crtc[1] << 4) + 16, cols[0]); + } + } - if (cga->cgamode & 1) - x = (cga->crtc[1] << 3) + 16; - else - x = (cga->crtc[1] << 4) + 16; + if (cga->cgamode & 1) + x = (cga->crtc[1] << 3) + 16; + else + x = (cga->crtc[1] << 4) + 16; - if (cga->composite) { - if (cga->cgamode & 0x10) - border = 0x00; - else - border = cga->cgacol & 0x0f; + if (cga->composite) { + border = ((cga->cgamode & 0x12) == 0x12) ? 0 : (cga->cgacol & 15); - Composite_Process(cga->cgamode, border, x >> 2, buffer32->line[(cga->displine << 1)]); - Composite_Process(cga->cgamode, border, x >> 2, buffer32->line[(cga->displine << 1) + 1]); - } + Composite_Process(cga->cgamode, border, x >> 2, buffer32->line[cga->displine]); + } else { + video_process_8(x, cga->displine); + } - cga->sc = oldsc; - if (cga->vc == cga->crtc[7] && !cga->sc) - cga->cgastat |= 8; - cga->displine++; - if (cga->displine >= 360) - cga->displine = 0; + cga->sc = oldsc; + if (cga->vc == cga->crtc[7] && !cga->sc) + cga->cgastat |= 8; + cga->displine++; + if (cga->displine >= 360) + cga->displine = 0; } else { - timer_advance_u64(&cga->timer, cga->dispontime); - cga->linepos = 0; - if (cga->vsynctime) { - cga->vsynctime--; - if (!cga->vsynctime) - cga->cgastat &= ~8; - } - if (cga->sc == (cga->crtc[11] & 31) || ((cga->crtc[8] & 3) == 3 && cga->sc == ((cga->crtc[11] & 31) >> 1))) { - cga->con = 0; - cga->coff = 1; - } - if ((cga->crtc[8] & 3) == 3 && cga->sc == (cga->crtc[9] >> 1)) - cga->maback = cga->ma; - if (cga->vadj) { - cga->sc++; - cga->sc &= 31; - cga->ma = cga->maback; - cga->vadj--; - if (!cga->vadj) { - cga->cgadispon = 1; - cga->ma = cga->maback = (cga->crtc[13] | (cga->crtc[12] << 8)) & 0x3fff; - cga->sc = 0; - } - } else if (cga->sc == cga->crtc[9]) { - cga->maback = cga->ma; - cga->sc = 0; - oldvc = cga->vc; - cga->vc++; - cga->vc &= 127; + timer_advance_u64(&cga->timer, cga->dispontime); + cga->linepos = 0; + if (cga->vsynctime) { + cga->vsynctime--; + if (!cga->vsynctime) + cga->cgastat &= ~8; + } + if (cga->sc == (cga->crtc[11] & 31) || ((cga->crtc[8] & 3) == 3 && cga->sc == ((cga->crtc[11] & 31) >> 1))) { + cga->con = 0; + cga->coff = 1; + } + if ((cga->crtc[8] & 3) == 3 && cga->sc == (cga->crtc[9] >> 1)) + cga->maback = cga->ma; + if (cga->vadj) { + cga->sc++; + cga->sc &= 31; + cga->ma = cga->maback; + cga->vadj--; + if (!cga->vadj) { + cga->cgadispon = 1; + cga->ma = cga->maback = (cga->crtc[13] | (cga->crtc[12] << 8)) & 0x3fff; + cga->sc = 0; + } + } else if (cga->sc == cga->crtc[9]) { + cga->maback = cga->ma; + cga->sc = 0; + oldvc = cga->vc; + cga->vc++; + cga->vc &= 127; - if (cga->vc == cga->crtc[6]) - cga->cgadispon = 0; + if (cga->vc == cga->crtc[6]) + cga->cgadispon = 0; - if (oldvc == cga->crtc[4]) { - cga->vc = 0; - cga->vadj = cga->crtc[5]; - if (!cga->vadj) { - cga->cgadispon = 1; - cga->ma = cga->maback = (cga->crtc[13] | (cga->crtc[12] << 8)) & 0x3fff; - } - switch (cga->crtc[10] & 0x60) { - case 0x20: - cga->cursoron = 0; - break; - case 0x60: - cga->cursoron = cga->cgablink & 0x10; - break; - default: - cga->cursoron = cga->cgablink & 0x08; - break; - } - } + if (oldvc == cga->crtc[4]) { + cga->vc = 0; + cga->vadj = cga->crtc[5]; + if (!cga->vadj) { + cga->cgadispon = 1; + cga->ma = cga->maback = (cga->crtc[13] | (cga->crtc[12] << 8)) & 0x3fff; + } + switch (cga->crtc[10] & 0x60) { + case 0x20: + cga->cursoron = 0; + break; + case 0x60: + cga->cursoron = cga->cgablink & 0x10; + break; + default: + cga->cursoron = cga->cgablink & 0x08; + break; + } + } - if (cga->vc == cga->crtc[7]) { - cga->cgadispon = 0; - cga->displine = 0; - cga->vsynctime = 16; - if (cga->crtc[7]) { - if (cga->cgamode & 1) - x = (cga->crtc[1] << 3) + 16; - else - x = (cga->crtc[1] << 4) + 16; - cga->lastline++; + if (cga->vc == cga->crtc[7]) { + cga->cgadispon = 0; + cga->displine = 0; + cga->vsynctime = 16; + if (cga->crtc[7]) { + if (cga->cgamode & 1) + x = (cga->crtc[1] << 3) + 16; + else + x = (cga->crtc[1] << 4) + 16; + cga->lastline++; - xs_temp = x; - ys_temp = (cga->lastline - cga->firstline) << 1; + xs_temp = x; + ys_temp = cga->lastline - cga->firstline; - if ((xs_temp > 0) && (ys_temp > 0)) { - if (xs_temp < 64) xs_temp = 656; - if (ys_temp < 32) ys_temp = 400; - if (!enable_overscan) - xs_temp -= 16; + if ((xs_temp > 0) && (ys_temp > 0)) { + if (xs_temp < 64) + xs_temp = 656; + if (ys_temp < 32) + ys_temp = 200; + if (!enable_overscan) + xs_temp -= 16; - if ((cga->cgamode & 8) && ((xs_temp != xsize) || (ys_temp != ysize) || video_force_resize_get())) { - xsize = xs_temp; - ysize = ys_temp; - set_screen_size(xsize, ysize + (enable_overscan ? 16 : 0)); + if ((cga->cgamode & 8) && ((xs_temp != xsize) || (ys_temp != ysize) || video_force_resize_get())) { + xsize = xs_temp; + ysize = ys_temp; + set_screen_size(xsize, ysize + (enable_overscan ? 8 : 0)); - if (video_force_resize_get()) - video_force_resize_set(0); - } + if (video_force_resize_get()) + video_force_resize_set(0); + } - if (enable_overscan) { - if (cga->composite) - video_blit_memtoscreen(0, (cga->firstline - 4) << 1, - xsize, ((cga->lastline - cga->firstline) + 8) << 1); - else - video_blit_memtoscreen_8(0, (cga->firstline - 4) << 1, - xsize, ((cga->lastline - cga->firstline) + 8) << 1); - } else { - if (cga->composite) - video_blit_memtoscreen(8, cga->firstline << 1, - xsize, (cga->lastline - cga->firstline) << 1); - else - video_blit_memtoscreen_8(8, cga->firstline << 1, - xsize, (cga->lastline - cga->firstline) << 1); - } - } + if (enable_overscan) { + video_blit_memtoscreen(0, cga->firstline - 4, + xsize, (cga->lastline - cga->firstline) + 8); + } else { + video_blit_memtoscreen(8, cga->firstline, + xsize, cga->lastline - cga->firstline); + } + } - frames++; + frames++; - video_res_x = xsize; - video_res_y = ysize; - if (cga->cgamode & 1) { - video_res_x /= 8; - video_res_y /= cga->crtc[9] + 1; - video_bpp = 0; - } else if (!(cga->cgamode & 2)) { - video_res_x /= 16; - video_res_y /= cga->crtc[9] + 1; - video_bpp = 0; - } else if (!(cga->cgamode & 16)) { - video_res_x /= 2; - video_bpp = 2; - } else - video_bpp = 1; - } - cga->firstline = 1000; - cga->lastline = 0; - cga->cgablink++; - cga->oddeven ^= 1; - } - } else { - cga->sc++; - cga->sc &= 31; - cga->ma = cga->maback; - } - if (cga->cgadispon) - cga->cgastat &= ~1; - if ((cga->sc == (cga->crtc[10] & 31) || ((cga->crtc[8] & 3) == 3 && cga->sc == ((cga->crtc[10] & 31) >> 1)))) - cga->con = 1; - if (cga->cgadispon && (cga->cgamode & 1)) { - for (x = 0; x < (cga->crtc[1] << 1); x++) - cga->charbuffer[x] = cga->vram[(((cga->ma << 1) + x) & 0x3fff)]; - } + video_res_x = xsize; + video_res_y = ysize; + if (cga->cgamode & 1) { + video_res_x /= 8; + video_res_y /= cga->crtc[9] + 1; + video_bpp = 0; + } else if (!(cga->cgamode & 2)) { + video_res_x /= 16; + video_res_y /= cga->crtc[9] + 1; + video_bpp = 0; + } else if (!(cga->cgamode & 16)) { + video_res_x /= 2; + video_bpp = 2; + } else + video_bpp = 1; + } + cga->firstline = 1000; + cga->lastline = 0; + cga->cgablink++; + cga->oddeven ^= 1; + } + } else { + cga->sc++; + cga->sc &= 31; + cga->ma = cga->maback; + } + if (cga->cgadispon) + cga->cgastat &= ~1; + if (cga->sc == (cga->crtc[10] & 31) || ((cga->crtc[8] & 3) == 3 && cga->sc == ((cga->crtc[10] & 31) >> 1))) + cga->con = 1; + if (cga->cgadispon && (cga->cgamode & 1)) { + for (x = 0; x < (cga->crtc[1] << 1); x++) + cga->charbuffer[x] = cga->vram[((cga->ma << 1) + x) & 0x3fff]; + } } } - void cga_init(cga_t *cga) { @@ -525,19 +518,18 @@ cga_init(cga_t *cga) cga->composite = 0; } - void * -cga_standalone_init(const device_t *info) +cga_standalone_init(UNUSED(const device_t *info)) { - int display_type; + int display_type; cga_t *cga = malloc(sizeof(cga_t)); memset(cga, 0, sizeof(cga_t)); video_inform(VIDEO_FLAG_TYPE_CGA, &timing_cga); - display_type = device_get_config_int("display_type"); - cga->composite = (display_type != CGA_RGB); - cga->revision = device_get_config_int("composite_type"); + display_type = device_get_config_int("display_type"); + cga->composite = (display_type != CGA_RGB); + cga->revision = device_get_config_int("composite_type"); cga->snow_enabled = device_get_config_int("snow_enabled"); cga->vram = malloc(0x4000); @@ -550,104 +542,152 @@ cga_standalone_init(const device_t *info) overscan_x = overscan_y = 16; cga->rgb_type = device_get_config_int("rgb_type"); - cga_palette = (cga->rgb_type << 1); + cga_palette = (cga->rgb_type << 1); cgapal_rebuild(); + update_cga16_color(cga->cgamode); return cga; } +void * +cga_pravetz_init(const device_t *info) +{ + cga_t *cga = cga_standalone_init(info); + + loadfont("roms/video/cga/PRAVETZ-VDC2.BIN", 10); + + io_removehandler(0x03dd, 0x0001, cga_in, NULL, NULL, cga_out, NULL, NULL, cga); + io_sethandler(0x03dd, 0x0001, cga_pravetz_in, NULL, NULL, cga_pravetz_out, NULL, NULL, cga); + + cga->fontbase = 0x0300; + + return cga; +} void -cga_close(void *p) +cga_close(void *priv) { - cga_t *cga = (cga_t *) p; + cga_t *cga = (cga_t *) priv; free(cga->vram); free(cga); } - void -cga_speed_changed(void *p) +cga_speed_changed(void *priv) { - cga_t *cga = (cga_t *) p; + cga_t *cga = (cga_t *) priv; cga_recalctimings(cga); } - -const device_config_t cga_config[] = -{ - { - "display_type", "Display type", CONFIG_SELECTION, "", CGA_RGB, "", { 0 }, - { - { - "RGB", CGA_RGB - }, - { - "Composite", CGA_COMPOSITE - }, - { - "" - } - } - }, - { - "composite_type", "Composite type", CONFIG_SELECTION, "", COMPOSITE_OLD, "", { 0 }, - { - { - "Old", COMPOSITE_OLD - }, - { - "New", COMPOSITE_NEW - }, - { - "" - } - } - }, - { - "rgb_type", "RGB type", CONFIG_SELECTION, "", 0, "", { 0 }, - { - { - "Color", 0 - }, - { - "Green Monochrome", 1 - }, - { - "Amber Monochrome", 2 - }, - { - "Gray Monochrome", 3 - }, - { - "Color (no brown)", 4 - }, - { - "" - } - } - }, - { - "snow_enabled", "Snow emulation", CONFIG_BINARY, "", 1 - }, - { - "", "", -1 +// clang-format off +const device_config_t cga_config[] = { + { + .name = "display_type", + .description = "Display type", + .type = CONFIG_SELECTION, + .default_int = CGA_RGB, + .selection = { + { + .description = "RGB", + .value = CGA_RGB + }, + { + .description = "Composite", + .value = CGA_COMPOSITE + }, + { + .description = "" + } } + }, + { + .name = "composite_type", + .description = "Composite type", + .type = CONFIG_SELECTION, + .default_int = COMPOSITE_OLD, + .selection = { + { + .description = "Old", + .value = COMPOSITE_OLD + }, + { + .description = "New", + .value = COMPOSITE_NEW + }, + { + .description = "" + } + } + }, + { + .name = "rgb_type", + .description = "RGB type", + .type = CONFIG_SELECTION, + .default_int = 0, + .selection = { + { + .description = "Color", + .value = 0 + }, + { + .description = "Green Monochrome", + .value = 1 + }, + { + .description = "Amber Monochrome", + .value = 2 + }, + { + .description = "Gray Monochrome", + .value = 3 + }, + { + .description = "Color (no brown)", + .value = 4 + }, + { + .description = "" + } + } + }, + { + .name = "snow_enabled", + .description = "Snow emulation", + .type = CONFIG_BINARY, + .default_int = 1 + }, + { + .type = CONFIG_END + } +}; +// clang-format on + +const device_t cga_device = { + .name = "CGA", + .internal_name = "cga", + .flags = DEVICE_ISA, + .local = 0, + .init = cga_standalone_init, + .close = cga_close, + .reset = NULL, + { .available = NULL }, + .speed_changed = cga_speed_changed, + .force_redraw = NULL, + .config = cga_config }; - -const device_t cga_device = -{ - "CGA", - "cga", - DEVICE_ISA, 0, - cga_standalone_init, - cga_close, - NULL, - { NULL }, - cga_speed_changed, - NULL, - cga_config +const device_t cga_pravetz_device = { + .name = "Pravetz VDC-2", + .internal_name = "cga_pravetz", + .flags = DEVICE_ISA, + .local = 0, + .init = cga_pravetz_init, + .close = cga_close, + .reset = NULL, + { .available = NULL }, + .speed_changed = cga_speed_changed, + .force_redraw = NULL, + .config = cga_config }; diff --git a/src/video/vid_cga_comp.c b/src/video/vid_cga_comp.c index a0b5c08a8..d580f0c06 100644 --- a/src/video/vid_cga_comp.c +++ b/src/video/vid_cga_comp.c @@ -1,21 +1,21 @@ /* - * 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. + * 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. + * This file is part of the 86Box distribution. * - * IBM CGA composite filter, borrowed from reenigne's DOSBox - * patch and ported to C. + * IBM CGA composite filter, borrowed from reenigne's DOSBox + * patch and ported to C. * * * - * Authors: reenigne, - * Miran Grca, + * Authors: reenigne, + * Miran Grca, * - * Copyright 2015-2019 reenigne. - * Copyright 2015-2019 Miran Grca. + * Copyright 2015-2019 reenigne. + * Copyright 2015-2019 Miran Grca. */ #include #include @@ -29,14 +29,12 @@ #include <86box/vid_cga.h> #include <86box/vid_cga_comp.h> - int CGA_Composite_Table[1024]; - static double brightness = 0; -static double contrast = 100; +static double contrast = 100; static double saturation = 100; -static double sharpness = 0; +static double sharpness = 0; static double hue_offset = 0; /* New algorithm by reenigne @@ -45,27 +43,31 @@ static double hue_offset = 0; static const double tau = 6.28318531; /* == 2*pi */ static unsigned char chroma_multiplexer[256] = { - 2, 2, 2, 2, 114,174, 4, 3, 2, 1,133,135, 2,113,150, 4, - 133, 2, 1, 99, 151,152, 2, 1, 3, 2, 96,136, 151,152,151,152, - 2, 56, 62, 4, 111,250,118, 4, 0, 51,207,137, 1,171,209, 5, - 140, 50, 54,100, 133,202, 57, 4, 2, 50,153,149, 128,198,198,135, - 32, 1, 36, 81, 147,158, 1, 42, 33, 1,210,254, 34,109,169, 77, - 177, 2, 0,165, 189,154, 3, 44, 33, 0, 91,197, 178,142,144,192, - 4, 2, 61, 67, 117,151,112, 83, 4, 0,249,255, 3,107,249,117, - 147, 1, 50,162, 143,141, 52, 54, 3, 0,145,206, 124,123,192,193, - 72, 78, 2, 0, 159,208, 4, 0, 53, 58,164,159, 37,159,171, 1, - 248,117, 4, 98, 212,218, 5, 2, 54, 59, 93,121, 176,181,134,130, - 1, 61, 31, 0, 160,255, 34, 1, 1, 58,197,166, 0,177,194, 2, - 162,111, 34, 96, 205,253, 32, 1, 1, 57,123,125, 119,188,150,112, - 78, 4, 0, 75, 166,180, 20, 38, 78, 1,143,246, 42,113,156, 37, - 252, 4, 1,188, 175,129, 1, 37, 118, 4, 88,249, 202,150,145,200, - 61, 59, 60, 60, 228,252,117, 77, 60, 58,248,251, 81,212,254,107, - 198, 59, 58,169, 250,251, 81, 80, 100, 58,154,250, 251,252,252,252}; + // clang-format off + 2, 2, 2, 2, 114,174, 4, 3, 2, 1,133,135, 2,113,150, 4, + 133, 2, 1, 99, 151,152, 2, 1, 3, 2, 96,136, 151,152,151,152, + 2, 56, 62, 4, 111,250,118, 4, 0, 51,207,137, 1,171,209, 5, + 140, 50, 54,100, 133,202, 57, 4, 2, 50,153,149, 128,198,198,135, + 32, 1, 36, 81, 147,158, 1, 42, 33, 1,210,254, 34,109,169, 77, + 177, 2, 0,165, 189,154, 3, 44, 33, 0, 91,197, 178,142,144,192, + 4, 2, 61, 67, 117,151,112, 83, 4, 0,249,255, 3,107,249,117, + 147, 1, 50,162, 143,141, 52, 54, 3, 0,145,206, 124,123,192,193, + 72, 78, 2, 0, 159,208, 4, 0, 53, 58,164,159, 37,159,171, 1, + 248,117, 4, 98, 212,218, 5, 2, 54, 59, 93,121, 176,181,134,130, + 1, 61, 31, 0, 160,255, 34, 1, 1, 58,197,166, 0,177,194, 2, + 162,111, 34, 96, 205,253, 32, 1, 1, 57,123,125, 119,188,150,112, + 78, 4, 0, 75, 166,180, 20, 38, 78, 1,143,246, 42,113,156, 37, + 252, 4, 1,188, 175,129, 1, 37, 118, 4, 88,249, 202,150,145,200, + 61, 59, 60, 60, 228,252,117, 77, 60, 58,248,251, 81,212,254,107, + 198, 59, 58,169, 250,251, 81, 80, 100, 58,154,250, 251,252,252,252 + // clang-format on +}; static double intensity[4] = { - 77.175381, 88.654656, 166.564623, 174.228438}; + 77.175381, 88.654656, 166.564623, 174.228438 +}; -#define NEW_CGA(c,i,r,g,b) (((c)/0.72)*0.29 + ((i)/0.28)*0.32 + ((r)/0.28)*0.1 + ((g)/0.28)*0.22 + ((b)/0.28)*0.07) +#define NEW_CGA(c, i, r, g, b) (((c) / 0.72) * 0.29 + ((i) / 0.28) * 0.32 + ((r) / 0.28) * 0.1 + ((g) / 0.28) * 0.22 + ((b) / 0.28) * 0.07) double mode_brightness; double mode_contrast; @@ -73,273 +75,311 @@ double mode_hue; double min_v; double max_v; -double video_ri, video_rq, video_gi, video_gq, video_bi, video_bq; -int video_sharpness; -int tandy_mode_control = 0; +double video_ri; +double video_rq; +double video_gi; +double video_gq; +double video_bi; +double video_bq; +int video_sharpness; +int tandy_mode_control = 0; static bool new_cga = 0; -void update_cga16_color(uint8_t cgamode) { - int x; - double c, i, v; - double q, a, s, r; - double iq_adjust_i, iq_adjust_q; - double i0, i3, mode_saturation; +void +update_cga16_color(uint8_t cgamode) +{ + double c; + double i; + double v; + double q; + double a; + double s; + double r; + double iq_adjust_i; + double iq_adjust_q; + double i0; + double i3; + double mode_saturation; - static const double ri = 0.9563; - static const double rq = 0.6210; - static const double gi = -0.2721; - static const double gq = -0.6474; - static const double bi = -1.1069; - static const double bq = 1.7046; + static const double ri = 0.9563; + static const double rq = 0.6210; + static const double gi = -0.2721; + static const double gq = -0.6474; + static const double bi = -1.1069; + static const double bq = 1.7046; - if (!new_cga) { - min_v = chroma_multiplexer[0] + intensity[0]; - max_v = chroma_multiplexer[255] + intensity[3]; + if (!new_cga) { + min_v = chroma_multiplexer[0] + intensity[0]; + max_v = chroma_multiplexer[255] + intensity[3]; + } else { + i0 = intensity[0]; + i3 = intensity[3]; + min_v = NEW_CGA(chroma_multiplexer[0], i0, i0, i0, i0); + max_v = NEW_CGA(chroma_multiplexer[255], i3, i3, i3, i3); + } + mode_contrast = 256 / (max_v - min_v); + mode_brightness = -min_v * mode_contrast; + if ((cgamode & 3) == 1) + mode_hue = 14; + else + mode_hue = 4; + + mode_contrast *= contrast * (new_cga ? 1.2 : 1) / 100; /* new CGA: 120% */ + mode_brightness += (new_cga ? brightness - 10 : brightness) * 5; /* new CGA: -10 */ + mode_saturation = (new_cga ? 4.35 : 2.9) * saturation / 100; /* new CGA: 150% */ + + for (uint16_t x = 0; x < 1024; ++x) { + int phase = x & 3; + int right = (x >> 2) & 15; + int left = (x >> 6) & 15; + int rc = right; + int lc = left; + if ((cgamode & 4) != 0) { + rc = (right & 8) | ((right & 7) != 0 ? 7 : 0); + lc = (left & 8) | ((left & 7) != 0 ? 7 : 0); } + c = chroma_multiplexer[((lc & 7) << 5) | ((rc & 7) << 2) | phase]; + i = intensity[(left >> 3) | ((right >> 2) & 2)]; + if (!new_cga) + v = c + i; else { - i0 = intensity[0]; - i3 = intensity[3]; - min_v = NEW_CGA(chroma_multiplexer[0], i0, i0, i0, i0); - max_v = NEW_CGA(chroma_multiplexer[255], i3, i3, i3, i3); + double r = intensity[((left >> 2) & 1) | ((right >> 1) & 2)]; + double g = intensity[((left >> 1) & 1) | (right & 2)]; + double b = intensity[(left & 1) | ((right << 1) & 2)]; + v = NEW_CGA(c, i, r, g, b); } - mode_contrast = 256/(max_v - min_v); - mode_brightness = -min_v*mode_contrast; - if ((cgamode & 3) == 1) - mode_hue = 14; - else - mode_hue = 4; + CGA_Composite_Table[x] = (int) (v * mode_contrast + mode_brightness); + } - mode_contrast *= contrast * (new_cga ? 1.2 : 1)/100; /* new CGA: 120% */ - mode_brightness += (new_cga ? brightness-10 : brightness)*5; /* new CGA: -10 */ - mode_saturation = (new_cga ? 4.35 : 2.9)*saturation/100; /* new CGA: 150% */ + i = CGA_Composite_Table[6 * 68] - CGA_Composite_Table[6 * 68 + 2]; + q = CGA_Composite_Table[6 * 68 + 1] - CGA_Composite_Table[6 * 68 + 3]; - for (x = 0; x < 1024; ++x) { - int phase = x & 3; - int right = (x >> 2) & 15; - int left = (x >> 6) & 15; - int rc = right; - int lc = left; - if ((cgamode & 4) != 0) { - rc = (right & 8) | ((right & 7) != 0 ? 7 : 0); - lc = (left & 8) | ((left & 7) != 0 ? 7 : 0); - } - c = chroma_multiplexer[((lc & 7) << 5) | ((rc & 7) << 2) | phase]; - i = intensity[(left >> 3) | ((right >> 2) & 2)]; - if (!new_cga) - v = c + i; - else { - double r = intensity[((left >> 2) & 1) | ((right >> 1) & 2)]; - double g = intensity[((left >> 1) & 1) | (right & 2)]; - double b = intensity[(left & 1) | ((right << 1) & 2)]; - v = NEW_CGA(c, i, r, g, b); - } - CGA_Composite_Table[x] = (int) (v*mode_contrast + mode_brightness); - } + a = tau * (33 + 90 + hue_offset + mode_hue) / 360.0; + c = cos(a); + s = sin(a); + r = 256 * mode_saturation / sqrt(i * i + q * q); - i = CGA_Composite_Table[6*68] - CGA_Composite_Table[6*68 + 2]; - q = CGA_Composite_Table[6*68 + 1] - CGA_Composite_Table[6*68 + 3]; + iq_adjust_i = -(i * c + q * s) * r; + iq_adjust_q = (q * c - i * s) * r; - a = tau*(33 + 90 + hue_offset + mode_hue)/360.0; - c = cos(a); - s = sin(a); - r = 256*mode_saturation/sqrt(i*i+q*q); - - iq_adjust_i = -(i*c + q*s)*r; - iq_adjust_q = (q*c - i*s)*r; - - video_ri = (int) (ri*iq_adjust_i + rq*iq_adjust_q); - video_rq = (int) (-ri*iq_adjust_q + rq*iq_adjust_i); - video_gi = (int) (gi*iq_adjust_i + gq*iq_adjust_q); - video_gq = (int) (-gi*iq_adjust_q + gq*iq_adjust_i); - video_bi = (int) (bi*iq_adjust_i + bq*iq_adjust_q); - video_bq = (int) (-bi*iq_adjust_q + bq*iq_adjust_i); - video_sharpness = (int) (sharpness*256/100); + video_ri = (int) (ri * iq_adjust_i + rq * iq_adjust_q); + video_rq = (int) (-ri * iq_adjust_q + rq * iq_adjust_i); + video_gi = (int) (gi * iq_adjust_i + gq * iq_adjust_q); + video_gq = (int) (-gi * iq_adjust_q + gq * iq_adjust_i); + video_bi = (int) (bi * iq_adjust_i + bq * iq_adjust_q); + video_bq = (int) (-bi * iq_adjust_q + bq * iq_adjust_i); + video_sharpness = (int) (sharpness * 256 / 100); } -static Bit8u byte_clamp(int v) { - v >>= 13; - return v < 0 ? 0 : (v > 255 ? 255 : v); +static uint8_t +byte_clamp(int v) +{ + v >>= 13; + return v < 0 ? 0 : (v > 255 ? 255 : v); } /* 2048x1536 is the maximum we can possibly support. */ #define SCALER_MAXWIDTH 2048 -static int temp[SCALER_MAXWIDTH + 10]={0}; -static int atemp[SCALER_MAXWIDTH + 2]={0}; -static int btemp[SCALER_MAXWIDTH + 2]={0}; +static int temp[SCALER_MAXWIDTH + 10] = { 0 }; +static int atemp[SCALER_MAXWIDTH + 2] = { 0 }; +static int btemp[SCALER_MAXWIDTH + 2] = { 0 }; -Bit32u * Composite_Process(uint8_t cgamode, Bit8u border, Bit32u blocks/*, bool doublewidth*/, Bit32u *TempLine) +uint32_t * +Composite_Process(uint8_t cgamode, uint8_t border, uint32_t blocks /*, bool doublewidth*/, uint32_t *TempLine) { - int x; - Bit32u x2; + uint32_t x2; - int w = blocks*4; + int w = blocks * 4; - int *o; - Bit32u *rgbi; - int *b; - int *i; - Bit32u* srgb; - int *ap, *bp; + int *o; + const uint32_t *rgbi; + const int *b; + int *i; + uint32_t *srgb; + int *ap; + int *bp; -#define COMPOSITE_CONVERT(I, Q) do { \ - i[1] = (i[1]<<3) - ap[1]; \ - a = ap[0]; \ - b = bp[0]; \ - c = i[0]+i[0]; \ - d = i[-1]+i[1]; \ - y = ((c+d)<<8) + video_sharpness*(c-d); \ - rr = y + video_ri*(I) + video_rq*(Q); \ - gg = y + video_gi*(I) + video_gq*(Q); \ - bb = y + video_bi*(I) + video_bq*(Q); \ - ++i; \ - ++ap; \ - ++bp; \ - *srgb = (byte_clamp(rr)<<16) | (byte_clamp(gg)<<8) | byte_clamp(bb); \ - ++srgb; \ -} while (0) +#define COMPOSITE_CONVERT(I, Q) \ + do { \ + i[1] = (i[1] << 3) - ap[1]; \ + a = ap[0]; \ + b = bp[0]; \ + c = i[0] + i[0]; \ + d = i[-1] + i[1]; \ + y = ((c + d) << 8) + video_sharpness * (c - d); \ + rr = y + video_ri * (I) + video_rq * (Q); \ + gg = y + video_gi * (I) + video_gq * (Q); \ + bb = y + video_bi * (I) + video_bq * (Q); \ + ++i; \ + ++ap; \ + ++bp; \ + *srgb = (byte_clamp(rr) << 16) | (byte_clamp(gg) << 8) | byte_clamp(bb); \ + ++srgb; \ + } while (0) -#define OUT(v) do { *o = (v); ++o; } while (0) +#define OUT(v) \ + do { \ + *o = (v); \ + ++o; \ + } while (0) - /* Simulate CGA composite output */ - o = temp; - rgbi = TempLine; - b = &CGA_Composite_Table[border*68]; - for (x = 0; x < 4; ++x) - OUT(b[(x+3)&3]); - OUT(CGA_Composite_Table[(border<<6) | ((*rgbi & 0x0f)<<2) | 3]); - for (x = 0; x < w-1; ++x) { - OUT(CGA_Composite_Table[((rgbi[0] & 0x0f)<<6) | ((rgbi[1] & 0x0f)<<2) | (x&3)]); - ++rgbi; + /* Simulate CGA composite output */ + o = temp; + rgbi = TempLine; + b = &CGA_Composite_Table[border * 68]; + for (uint8_t x = 0; x < 4; ++x) + OUT(b[(x + 3) & 3]); + OUT(CGA_Composite_Table[(border << 6) | ((*rgbi & 0x0f) << 2) | 3]); + for (int x = 0; x < w - 1; ++x) { + OUT(CGA_Composite_Table[((rgbi[0] & 0x0f) << 6) | ((rgbi[1] & 0x0f) << 2) | (x & 3)]); + ++rgbi; + } + OUT(CGA_Composite_Table[((*rgbi & 0x0f) << 6) | (border << 2) | 3]); + for (uint8_t x = 0; x < 5; ++x) + OUT(b[x & 3]); + + if ((cgamode & 4) != 0) { + /* Decode */ + i = temp + 5; + srgb = TempLine; + for (x2 = 0; x2 < blocks * 4; ++x2) { + int c = (i[0] + i[0]) << 3; + int d = (i[-1] + i[1]) << 3; + int y = ((c + d) << 8) + video_sharpness * (c - d); + ++i; + *srgb = byte_clamp(y) * 0x10101; + ++srgb; } - OUT(CGA_Composite_Table[((*rgbi & 0x0f)<<6) | (border<<2) | 3]); - for (x = 0; x < 5; ++x) - OUT(b[x&3]); - - if ((cgamode & 4) != 0) { - /* Decode */ - i = temp + 5; - srgb = (Bit32u *)TempLine; - for (x2 = 0; x2 < blocks*4; ++x2) { - int c = (i[0]+i[0])<<3; - int d = (i[-1]+i[1])<<3; - int y = ((c+d)<<8) + video_sharpness*(c-d); - ++i; - *srgb = byte_clamp(y)*0x10101; - ++srgb; - } + } else { + /* Store chroma */ + i = temp + 4; + ap = atemp + 1; + bp = btemp + 1; + for (int x = -1; x < w + 1; ++x) { + ap[x] = i[-4] - ((i[-2] - i[0] + i[2]) << 1) + i[4]; + bp[x] = (i[-3] - i[-1] + i[1] - i[3]) << 1; + ++i; } - else { - /* Store chroma */ - i = temp + 4; - ap = atemp + 1; - bp = btemp + 1; - for (x = -1; x < w + 1; ++x) { - ap[x] = i[-4]-((i[-2]-i[0]+i[2])<<1)+i[4]; - bp[x] = (i[-3]-i[-1]+i[1]-i[3])<<1; - ++i; - } - /* Decode */ - i = temp + 5; - i[-1] = (i[-1]<<3) - ap[-1]; - i[0] = (i[0]<<3) - ap[0]; - srgb = (Bit32u *)TempLine; - for (x2 = 0; x2 < blocks; ++x2) { - int y,a,b,c,d,rr,gg,bb; - COMPOSITE_CONVERT(a, b); - COMPOSITE_CONVERT(-b, a); - COMPOSITE_CONVERT(-a, -b); - COMPOSITE_CONVERT(b, -a); - } + /* Decode */ + i = temp + 5; + i[-1] = (i[-1] << 3) - ap[-1]; + i[0] = (i[0] << 3) - ap[0]; + srgb = TempLine; + for (x2 = 0; x2 < blocks; ++x2) { + int y; + int a; + int b; + int c; + int d; + int rr; + int gg; + int bb; + COMPOSITE_CONVERT(a, b); + COMPOSITE_CONVERT(-b, a); + COMPOSITE_CONVERT(-a, -b); + COMPOSITE_CONVERT(b, -a); } + } #undef COMPOSITE_CONVERT #undef OUT - return TempLine; + return TempLine; } -void IncreaseHue(uint8_t cgamode) +void +IncreaseHue(uint8_t cgamode) { - hue_offset += 5.0; + hue_offset += 5.0; - update_cga16_color(cgamode); + update_cga16_color(cgamode); } -void DecreaseHue(uint8_t cgamode) +void +DecreaseHue(uint8_t cgamode) { - hue_offset -= 5.0; + hue_offset -= 5.0; - update_cga16_color(cgamode); + update_cga16_color(cgamode); } -void IncreaseSaturation(uint8_t cgamode) +void +IncreaseSaturation(uint8_t cgamode) { - saturation += 5; + saturation += 5; - update_cga16_color(cgamode); + update_cga16_color(cgamode); } -void DecreaseSaturation(uint8_t cgamode) +void +DecreaseSaturation(uint8_t cgamode) { - saturation -= 5; + saturation -= 5; - update_cga16_color(cgamode); + update_cga16_color(cgamode); } -void IncreaseContrast(uint8_t cgamode) +void +IncreaseContrast(uint8_t cgamode) { - contrast += 5; + contrast += 5; - update_cga16_color(cgamode); + update_cga16_color(cgamode); } -void DecreaseContrast(uint8_t cgamode) +void +DecreaseContrast(uint8_t cgamode) { - contrast -= 5; + contrast -= 5; - update_cga16_color(cgamode); + update_cga16_color(cgamode); } -void IncreaseBrightness(uint8_t cgamode) +void +IncreaseBrightness(uint8_t cgamode) { - brightness += 5; + brightness += 5; - update_cga16_color(cgamode); + update_cga16_color(cgamode); } -void DecreaseBrightness(uint8_t cgamode) +void +DecreaseBrightness(uint8_t cgamode) { - brightness -= 5; + brightness -= 5; - update_cga16_color(cgamode); + update_cga16_color(cgamode); } -void IncreaseSharpness(uint8_t cgamode) +void +IncreaseSharpness(uint8_t cgamode) { - sharpness += 10; + sharpness += 10; - update_cga16_color(cgamode); + update_cga16_color(cgamode); } -void DecreaseSharpness(uint8_t cgamode) +void +DecreaseSharpness(uint8_t cgamode) { - sharpness -= 10; + sharpness -= 10; - update_cga16_color(cgamode); + update_cga16_color(cgamode); } -void cga_comp_init(int revision) +void +cga_comp_init(int revision) { - new_cga = revision; + new_cga = revision; - /* Making sure this gets reset after reset. */ - brightness = 0; - contrast = 100; - saturation = 100; - sharpness = 0; - hue_offset = 0; + /* Making sure this gets reset after reset. */ + brightness = 0; + contrast = 100; + saturation = 100; + sharpness = 0; + hue_offset = 0; - update_cga16_color(0); + update_cga16_color(0); } diff --git a/src/video/vid_cl54xx.c b/src/video/vid_cl54xx.c index ff543cfa0..83c4f5a63 100644 --- a/src/video/vid_cl54xx.c +++ b/src/video/vid_cl54xx.c @@ -1,23 +1,23 @@ /* - * 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. + * 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. + * This file is part of the 86Box distribution. * - * Emulation of select Cirrus Logic cards (CL-GD 5428, - * CL-GD 5429, CL-GD 5430, CL-GD 5434 and CL-GD 5436 are supported). + * Emulation of select Cirrus Logic cards (CL-GD 5428, + * CL-GD 5429, CL-GD 5430, CL-GD 5434 and CL-GD 5436 are supported). * * * - * Authors: Miran Grca, - * tonioni, - * TheCollector1995, + * Authors: Miran Grca, + * tonioni, + * TheCollector1995, * - * Copyright 2016-2020 Miran Grca. - * Copyright 2020 tonioni. - * Copyright 2016-2020 TheCollector1995. + * Copyright 2016-2020 Miran Grca. + * Copyright 2020 tonioni. + * Copyright 2016-2020 TheCollector1995. */ #include #include @@ -39,60 +39,66 @@ #include <86box/vid_ddc.h> #include <86box/vid_svga.h> #include <86box/vid_svga_render.h> +#include <86box/plat_fallthrough.h> +#include <86box/plat_unused.h> -#define BIOS_GD5401_PATH "roms/video/cirruslogic/avga1.rom" -#define BIOS_GD5402_PATH "roms/video/cirruslogic/avga2.rom" -#define BIOS_GD5402_ONBOARD_PATH "roms/machines/cmdsl386sx25/c000.rom" -#define BIOS_GD5420_PATH "roms/video/cirruslogic/5420.vbi" -#define BIOS_GD5422_PATH "roms/video/cirruslogic/cl5422.bin" -#define BIOS_GD5426_DIAMOND_A1_ISA_PATH "roms/video/cirruslogic/diamond5426.vbi" -#define BIOS_GD5428_DIAMOND_B1_VLB_PATH "roms/video/cirruslogic/Diamond SpeedStar PRO VLB v3.04.bin" -#define BIOS_GD5428_ISA_PATH "roms/video/cirruslogic/5428.bin" -#define BIOS_GD5428_MCA_PATH "roms/video/cirruslogic/SVGA141.ROM" -#define BIOS_GD5428_PATH "roms/video/cirruslogic/vlbusjapan.BIN" -#define BIOS_GD5429_PATH "roms/video/cirruslogic/5429.vbi" -#define BIOS_GD5430_DIAMOND_A8_VLB_PATH "roms/video/cirruslogic/diamondvlbus.bin" -#define BIOS_GD5430_PATH "roms/video/cirruslogic/pci.bin" -#define BIOS_GD5434_DIAMOND_A3_ISA_PATH "roms/video/cirruslogic/Diamond Multimedia SpeedStar 64 v2.02 EPROM Backup from ST M27C256B-12F1.BIN" -#define BIOS_GD5434_PATH "roms/video/cirruslogic/gd5434.BIN" -#define BIOS_GD5436_PATH "roms/video/cirruslogic/5436.vbi" -#define BIOS_GD5440_PATH "roms/video/cirruslogic/BIOS.BIN" -#define BIOS_GD5446_PATH "roms/video/cirruslogic/5446bv.vbi" -#define BIOS_GD5446_STB_PATH "roms/video/cirruslogic/stb nitro64v.BIN" -#define BIOS_GD5480_PATH "roms/video/cirruslogic/clgd5480.rom" +#define BIOS_GD5401_PATH "roms/video/cirruslogic/avga1.rom" +#define BIOS_GD5402_PATH "roms/video/cirruslogic/avga2.rom" +#define BIOS_GD5402_ONBOARD_PATH "roms/machines/cmdsl386sx25/c000.rom" +#define BIOS_GD5420_PATH "roms/video/cirruslogic/5420.vbi" +#define BIOS_GD5422_PATH "roms/video/cirruslogic/cl5422.bin" +#define BIOS_GD5426_DIAMOND_A1_ISA_PATH "roms/video/cirruslogic/diamond5426.vbi" +#define BIOS_GD5426_MCA_PATH "roms/video/cirruslogic/Reply.BIN" +#define BIOS_GD5428_DIAMOND_B1_VLB_PATH "roms/video/cirruslogic/Diamond SpeedStar PRO VLB v3.04.bin" +#define BIOS_GD5428_ISA_PATH "roms/video/cirruslogic/5428.bin" +#define BIOS_GD5428_MCA_PATH "roms/video/cirruslogic/SVGA141.ROM" +#define BIOS_GD5428_PATH "roms/video/cirruslogic/vlbusjapan.BIN" +#define BIOS_GD5428_BOCA_ISA_PATH_1 "roms/video/cirruslogic/boca_gd5428_1.30b_1.bin" +#define BIOS_GD5428_BOCA_ISA_PATH_2 "roms/video/cirruslogic/boca_gd5428_1.30b_2.bin" +#define BIOS_GD5429_PATH "roms/video/cirruslogic/5429.vbi" +#define BIOS_GD5430_DIAMOND_A8_VLB_PATH "roms/video/cirruslogic/diamondvlbus.bin" +#define BIOS_GD5430_ORCHID_VLB_PATH "roms/video/cirruslogic/orchidvlbus.bin" +#define BIOS_GD5430_PATH "roms/video/cirruslogic/pci.bin" +#define BIOS_GD5434_DIAMOND_A3_ISA_PATH "roms/video/cirruslogic/Diamond Multimedia SpeedStar 64 v2.02 EPROM Backup from ST M27C256B-12F1.BIN" +#define BIOS_GD5434_PATH "roms/video/cirruslogic/gd5434.BIN" +#define BIOS_GD5436_PATH "roms/video/cirruslogic/5436.vbi" +#define BIOS_GD5440_PATH "roms/video/cirruslogic/BIOS.BIN" +#define BIOS_GD5446_PATH "roms/video/cirruslogic/5446bv.vbi" +#define BIOS_GD5446_STB_PATH "roms/video/cirruslogic/stb nitro64v.BIN" +#define BIOS_GD5480_PATH "roms/video/cirruslogic/clgd5480.rom" -#define CIRRUS_ID_CLGD5401 0x88 -#define CIRRUS_ID_CLGD5402 0x89 -#define CIRRUS_ID_CLGD5420 0x8a -#define CIRRUS_ID_CLGD5422 0x8c -#define CIRRUS_ID_CLGD5424 0x94 -#define CIRRUS_ID_CLGD5426 0x90 -#define CIRRUS_ID_CLGD5428 0x98 -#define CIRRUS_ID_CLGD5429 0x9c -#define CIRRUS_ID_CLGD5430 0xa0 -#define CIRRUS_ID_CLGD5432 0xa2 -#define CIRRUS_ID_CLGD5434_4 0xa4 -#define CIRRUS_ID_CLGD5434 0xa8 -#define CIRRUS_ID_CLGD5436 0xac -#define CIRRUS_ID_CLGD5440 0xa0 /* Yes, the 5440 has the same ID as the 5430. */ -#define CIRRUS_ID_CLGD5446 0xb8 -#define CIRRUS_ID_CLGD5480 0xbc +#define CIRRUS_ID_CLGD5401 0x88 +#define CIRRUS_ID_CLGD5402 0x89 +#define CIRRUS_ID_CLGD5420 0x8a +#define CIRRUS_ID_CLGD5422 0x8c +#define CIRRUS_ID_CLGD5424 0x94 +#define CIRRUS_ID_CLGD5426 0x90 +#define CIRRUS_ID_CLGD5428 0x98 +#define CIRRUS_ID_CLGD5429 0x9c +#define CIRRUS_ID_CLGD5430 0xa0 +#define CIRRUS_ID_CLGD5432 0xa2 +#define CIRRUS_ID_CLGD5434_4 0xa4 +#define CIRRUS_ID_CLGD5434 0xa8 +#define CIRRUS_ID_CLGD5436 0xac +#define CIRRUS_ID_CLGD5440 0xa0 /* Yes, the 5440 has the same ID as the 5430. */ +#define CIRRUS_ID_CLGD5446 0xb8 +#define CIRRUS_ID_CLGD5480 0xbc /* sequencer 0x07 */ -#define CIRRUS_SR7_BPP_VGA 0x00 -#define CIRRUS_SR7_BPP_SVGA 0x01 -#define CIRRUS_SR7_BPP_MASK 0x0e -#define CIRRUS_SR7_BPP_8 0x00 -#define CIRRUS_SR7_BPP_16_DOUBLEVCLK 0x02 -#define CIRRUS_SR7_BPP_24 0x04 -#define CIRRUS_SR7_BPP_16 0x06 -#define CIRRUS_SR7_BPP_32 0x08 -#define CIRRUS_SR7_ISAADDR_MASK 0xe0 +#define CIRRUS_SR7_BPP_VGA 0x00 +#define CIRRUS_SR7_BPP_SVGA 0x01 +#define CIRRUS_SR7_BPP_MASK 0x0e +#define CIRRUS_SR7_BPP_8 0x00 +#define CIRRUS_SR7_BPP_16_DOUBLEVCLK 0x02 +#define CIRRUS_SR7_BPP_24 0x04 +#define CIRRUS_SR7_BPP_16 0x06 +#define CIRRUS_SR7_BPP_32 0x08 +#define CIRRUS_SR7_ISAADDR_MASK 0xe0 /* sequencer 0x12 */ -#define CIRRUS_CURSOR_SHOW 0x01 -#define CIRRUS_CURSOR_HIDDENPEL 0x02 -#define CIRRUS_CURSOR_LARGE 0x04 /* 64x64 if set, 32x32 if clear */ +#define CIRRUS_CURSOR_SHOW 0x01 +#define CIRRUS_CURSOR_HIDDENPEL 0x02 +#define CIRRUS_CURSOR_LARGE 0x04 /* 64x64 if set, 32x32 if clear */ /* sequencer 0x17 */ #define CIRRUS_BUSTYPE_VLBFAST 0x10 @@ -100,34 +106,34 @@ #define CIRRUS_BUSTYPE_VLBSLOW 0x30 #define CIRRUS_BUSTYPE_ISA 0x38 #define CIRRUS_MMIO_ENABLE 0x04 -#define CIRRUS_MMIO_USE_PCIADDR 0x40 /* 0xb8000 if cleared. */ +#define CIRRUS_MMIO_USE_PCIADDR 0x40 /* 0xb8000 if cleared. */ #define CIRRUS_MEMSIZEEXT_DOUBLE 0x80 /* control 0x0b */ -#define CIRRUS_BANKING_DUAL 0x01 -#define CIRRUS_BANKING_GRANULARITY_16K 0x20 /* set:16k, clear:4k */ +#define CIRRUS_BANKING_DUAL 0x01 +#define CIRRUS_BANKING_GRANULARITY_16K 0x20 /* set:16k, clear:4k */ /* control 0x30 */ -#define CIRRUS_BLTMODE_BACKWARDS 0x01 -#define CIRRUS_BLTMODE_MEMSYSDEST 0x02 -#define CIRRUS_BLTMODE_MEMSYSSRC 0x04 -#define CIRRUS_BLTMODE_TRANSPARENTCOMP 0x08 -#define CIRRUS_BLTMODE_PATTERNCOPY 0x40 -#define CIRRUS_BLTMODE_COLOREXPAND 0x80 -#define CIRRUS_BLTMODE_PIXELWIDTHMASK 0x30 -#define CIRRUS_BLTMODE_PIXELWIDTH8 0x00 -#define CIRRUS_BLTMODE_PIXELWIDTH16 0x10 -#define CIRRUS_BLTMODE_PIXELWIDTH24 0x20 -#define CIRRUS_BLTMODE_PIXELWIDTH32 0x30 +#define CIRRUS_BLTMODE_BACKWARDS 0x01 +#define CIRRUS_BLTMODE_MEMSYSDEST 0x02 +#define CIRRUS_BLTMODE_MEMSYSSRC 0x04 +#define CIRRUS_BLTMODE_TRANSPARENTCOMP 0x08 +#define CIRRUS_BLTMODE_PATTERNCOPY 0x40 +#define CIRRUS_BLTMODE_COLOREXPAND 0x80 +#define CIRRUS_BLTMODE_PIXELWIDTHMASK 0x30 +#define CIRRUS_BLTMODE_PIXELWIDTH8 0x00 +#define CIRRUS_BLTMODE_PIXELWIDTH16 0x10 +#define CIRRUS_BLTMODE_PIXELWIDTH24 0x20 +#define CIRRUS_BLTMODE_PIXELWIDTH32 0x30 /* control 0x31 */ -#define CIRRUS_BLT_BUSY 0x01 -#define CIRRUS_BLT_START 0x02 -#define CIRRUS_BLT_RESET 0x04 -#define CIRRUS_BLT_FIFOUSED 0x10 -#define CIRRUS_BLT_PAUSED 0x20 -#define CIRRUS_BLT_APERTURE2 0x40 -#define CIRRUS_BLT_AUTOSTART 0x80 +#define CIRRUS_BLT_BUSY 0x01 +#define CIRRUS_BLT_START 0x02 +#define CIRRUS_BLT_RESET 0x04 +#define CIRRUS_BLT_FIFOUSED 0x10 +#define CIRRUS_BLT_PAUSED 0x20 +#define CIRRUS_BLT_APERTURE2 0x40 +#define CIRRUS_BLT_AUTOSTART 0x80 /* control 0x33 */ #define CIRRUS_BLTMODEEXT_BACKGROUNDONLY 0x08 @@ -135,350 +141,366 @@ #define CIRRUS_BLTMODEEXT_COLOREXPINV 0x02 #define CIRRUS_BLTMODEEXT_DWORDGRANULARITY 0x01 -#define CL_GD5428_SYSTEM_BUS_MCA 5 -#define CL_GD5428_SYSTEM_BUS_VESA 6 -#define CL_GD5428_SYSTEM_BUS_ISA 7 +#define CL_GD5428_SYSTEM_BUS_MCA 5 +#define CL_GD5428_SYSTEM_BUS_VESA 6 +#define CL_GD5428_SYSTEM_BUS_ISA 7 -#define CL_GD5429_SYSTEM_BUS_VESA 5 -#define CL_GD5429_SYSTEM_BUS_ISA 7 +#define CL_GD5429_SYSTEM_BUS_VESA 5 +#define CL_GD5429_SYSTEM_BUS_ISA 7 -#define CL_GD543X_SYSTEM_BUS_PCI 4 -#define CL_GD543X_SYSTEM_BUS_VESA 6 -#define CL_GD543X_SYSTEM_BUS_ISA 7 +#define CL_GD543X_SYSTEM_BUS_PCI 4 +#define CL_GD543X_SYSTEM_BUS_VESA 6 +#define CL_GD543X_SYSTEM_BUS_ISA 7 -typedef struct gd54xx_t -{ - mem_mapping_t mmio_mapping; - mem_mapping_t linear_mapping; - mem_mapping_t aperture2_mapping; - mem_mapping_t vgablt_mapping; +typedef struct gd54xx_t { + mem_mapping_t mmio_mapping; + mem_mapping_t linear_mapping; + mem_mapping_t aperture2_mapping; + mem_mapping_t vgablt_mapping; - svga_t svga; + svga_t svga; - int has_bios, rev, - bit32; - rom_t bios_rom; + int has_bios; + int rev; + int bit32; + rom_t bios_rom; - uint32_t vram_size; - uint32_t vram_mask; + uint32_t vram_size; + uint32_t vram_mask; - uint8_t vclk_n[4]; - uint8_t vclk_d[4]; + uint8_t vclk_n[4]; + uint8_t vclk_d[4]; struct { - uint8_t state; - int ctrl; - } ramdac; - + uint8_t state; + int ctrl; + } ramdac; + struct { - uint16_t width, height; - uint16_t dst_pitch, src_pitch; - uint16_t trans_col, trans_mask; - uint16_t height_internal; - uint16_t msd_buf_pos, msd_buf_cnt; + uint16_t width; + uint16_t height; + uint16_t dst_pitch; + uint16_t src_pitch; + uint16_t trans_col; + uint16_t trans_mask; + uint16_t height_internal; + uint16_t msd_buf_pos; + uint16_t msd_buf_cnt; - uint8_t status; - uint8_t mask, mode, rop, modeext; - uint8_t ms_is_dest, msd_buf[32]; + uint8_t status; + uint8_t mask; + uint8_t mode; + uint8_t rop; + uint8_t modeext; + uint8_t ms_is_dest; + uint8_t msd_buf[32]; - uint32_t fg_col, bg_col; - uint32_t dst_addr_backup, src_addr_backup; - uint32_t dst_addr, src_addr; - uint32_t sys_src32, sys_cnt; + uint32_t fg_col; + uint32_t bg_col; + uint32_t dst_addr_backup; + uint32_t src_addr_backup; + uint32_t dst_addr; + uint32_t src_addr; + uint32_t sys_src32; + uint32_t sys_cnt; - /* Internal state */ - int pixel_width, pattern_x; - int x_count, y_count; - int xx_count, dir; - int unlock_special; + /* Internal state */ + int pixel_width; + int pattern_x; + int x_count; + int y_count; + int xx_count; + int dir; + int unlock_special; } blt; struct { - int mode; - uint16_t stride, r1sz, r1adjust, r2sz, - r2adjust, r2sdz, wvs, wve, - hzoom, vzoom; - uint8_t occlusion, colorkeycomparemask, - colorkeycompare; - int region1size, region2size, - colorkeymode; - uint32_t ck; + int mode; + uint16_t stride; + uint16_t r1sz; + uint16_t r1adjust; + uint16_t r2sz; + uint16_t r2adjust; + uint16_t r2sdz; + uint16_t wvs; + uint16_t wve; + uint16_t hzoom; + uint16_t vzoom; + uint8_t occlusion; + uint8_t colorkeycomparemask; + uint8_t colorkeycompare; + int region1size; + int region2size; + int colorkeymode; + uint32_t ck; } overlay; - int pci, vlb, mca, countminusone; - int vblank_irq, vportsync; + int pci; + int vlb; + int mca; + int countminusone; + int vblank_irq; + int vportsync; - uint8_t pci_regs[256]; - uint8_t int_line, unlocked, status, extensions; - uint8_t crtcreg_mask; + uint8_t pci_regs[256]; + uint8_t int_line; + uint8_t unlocked; + uint8_t status; + uint8_t extensions; + uint8_t crtcreg_mask; - uint8_t fc; /* Feature Connector */ + uint8_t fc; /* Feature Connector */ - int card, id; - - uint8_t pos_regs[8]; + int id; - uint32_t lfb_base, vgablt_base; + uint8_t pci_slot; + uint8_t irq_state; - int mmio_vram_overlap; + uint8_t pos_regs[8]; - uint32_t extpallook[256]; - PALETTE extpal; + uint32_t lfb_base; + uint32_t vgablt_base; - void *i2c, *ddc; + int mmio_vram_overlap; + + uint32_t extpallook[256]; + PALETTE extpal; + + void *i2c; + void *ddc; } gd54xx_t; +static video_timings_t timing_gd54xx_isa = { .type = VIDEO_ISA, .write_b = 3, .write_w = 3, .write_l = 6, .read_b = 8, .read_w = 8, .read_l = 12 }; +static video_timings_t timing_gd54xx_vlb = { .type = VIDEO_BUS, .write_b = 4, .write_w = 4, .write_l = 8, .read_b = 10, .read_w = 10, .read_l = 20 }; +static video_timings_t timing_gd54xx_pci = { .type = VIDEO_PCI, .write_b = 4, .write_w = 4, .write_l = 8, .read_b = 10, .read_w = 10, .read_l = 20 }; -static video_timings_t timing_gd54xx_isa = {VIDEO_ISA, 3, 3, 6, 8, 8, 12}; -static video_timings_t timing_gd54xx_vlb = {VIDEO_BUS, 4, 4, 8, 10, 10, 20}; -static video_timings_t timing_gd54xx_pci = {VIDEO_PCI, 4, 4, 8, 10, 10, 20}; - - -static void -gd543x_mmio_write(uint32_t addr, uint8_t val, void *p); -static void -gd543x_mmio_writeb(uint32_t addr, uint8_t val, void *p); -static void -gd543x_mmio_writew(uint32_t addr, uint16_t val, void *p); -static void -gd543x_mmio_writel(uint32_t addr, uint32_t val, void *p); +static void +gd543x_mmio_write(uint32_t addr, uint8_t val, void *priv); +static void +gd543x_mmio_writeb(uint32_t addr, uint8_t val, void *priv); +static void +gd543x_mmio_writew(uint32_t addr, uint16_t val, void *priv); +static void +gd543x_mmio_writel(uint32_t addr, uint32_t val, void *priv); static uint8_t -gd543x_mmio_read(uint32_t addr, void *p); +gd543x_mmio_read(uint32_t addr, void *priv); static uint16_t -gd543x_mmio_readw(uint32_t addr, void *p); +gd543x_mmio_readw(uint32_t addr, void *priv); static uint32_t -gd543x_mmio_readl(uint32_t addr, void *p); +gd543x_mmio_readl(uint32_t addr, void *priv); -static void +static void gd54xx_recalc_banking(gd54xx_t *gd54xx); -static void +static void gd543x_recalc_mapping(gd54xx_t *gd54xx); static void gd54xx_reset_blit(gd54xx_t *gd54xx); -static void +static void gd54xx_start_blit(uint32_t cpu_dat, uint32_t count, gd54xx_t *gd54xx, svga_t *svga); +#define CLAMP(x) \ + do { \ + if ((x) & ~0xff) \ + x = ((x) < 0) ? 0 : 0xff; \ + } while (0) -#define CLAMP(x) do \ - { \ - if ((x) & ~0xff) \ - x = ((x) < 0) ? 0 : 0xff; \ - } \ - while (0) - -#define DECODE_YCbCr() \ - do \ - { \ - int c; \ - \ - for (c = 0; c < 2; c++) \ - { \ - uint8_t y1, y2; \ - int8_t Cr, Cb; \ - int dR, dG, dB; \ - \ - y1 = src[0]; \ - Cr = src[1] - 0x80; \ - y2 = src[2]; \ - Cb = src[3] - 0x80; \ - src += 4; \ - \ - dR = (359*Cr) >> 8; \ - dG = (88*Cb + 183*Cr) >> 8; \ - dB = (453*Cb) >> 8; \ - \ - r[x_write] = y1 + dR; \ - CLAMP(r[x_write]); \ - g[x_write] = y1 - dG; \ - CLAMP(g[x_write]); \ - b[x_write] = y1 + dB; \ - CLAMP(b[x_write]); \ - \ - r[x_write+1] = y2 + dR; \ - CLAMP(r[x_write+1]); \ - g[x_write+1] = y2 - dG; \ - CLAMP(g[x_write+1]); \ - b[x_write+1] = y2 + dB; \ - CLAMP(b[x_write+1]); \ - \ - x_write = (x_write + 2) & 7; \ - } \ - } while (0) +#define DECODE_YCbCr() \ + do { \ + int c; \ + \ + for (c = 0; c < 2; c++) { \ + uint8_t y1, y2; \ + int8_t Cr, Cb; \ + int dR, dG, dB; \ + \ + y1 = src[0]; \ + Cr = src[1] - 0x80; \ + y2 = src[2]; \ + Cb = src[3] - 0x80; \ + src += 4; \ + \ + dR = (359 * Cr) >> 8; \ + dG = (88 * Cb + 183 * Cr) >> 8; \ + dB = (453 * Cb) >> 8; \ + \ + r[x_write] = y1 + dR; \ + CLAMP(r[x_write]); \ + g[x_write] = y1 - dG; \ + CLAMP(g[x_write]); \ + b[x_write] = y1 + dB; \ + CLAMP(b[x_write]); \ + \ + r[x_write + 1] = y2 + dR; \ + CLAMP(r[x_write + 1]); \ + g[x_write + 1] = y2 - dG; \ + CLAMP(g[x_write + 1]); \ + b[x_write + 1] = y2 + dB; \ + CLAMP(b[x_write + 1]); \ + \ + x_write = (x_write + 2) & 7; \ + } \ + } while (0) /*Both YUV formats are untested*/ -#define DECODE_YUV211() \ - do \ - { \ - uint8_t y1, y2, y3, y4; \ - int8_t U, V; \ - int dR, dG, dB; \ - \ - U = src[0] - 0x80; \ - y1 = (298 * (src[1] - 16)) >> 8; \ - y2 = (298 * (src[2] - 16)) >> 8; \ - V = src[3] - 0x80; \ - y3 = (298 * (src[4] - 16)) >> 8; \ - y4 = (298 * (src[5] - 16)) >> 8; \ - src += 6; \ - \ - dR = (309*V) >> 8; \ - dG = (100*U + 208*V) >> 8; \ - dB = (516*U) >> 8; \ - \ - r[x_write] = y1 + dR; \ - CLAMP(r[x_write]); \ - g[x_write] = y1 - dG; \ - CLAMP(g[x_write]); \ - b[x_write] = y1 + dB; \ - CLAMP(b[x_write]); \ - \ - r[x_write+1] = y2 + dR; \ - CLAMP(r[x_write+1]); \ - g[x_write+1] = y2 - dG; \ - CLAMP(g[x_write+1]); \ - b[x_write+1] = y2 + dB; \ - CLAMP(b[x_write+1]); \ - \ - r[x_write+2] = y3 + dR; \ - CLAMP(r[x_write+2]); \ - g[x_write+2] = y3 - dG; \ - CLAMP(g[x_write+2]); \ - b[x_write+2] = y3 + dB; \ - CLAMP(b[x_write+2]); \ - \ - r[x_write+3] = y4 + dR; \ - CLAMP(r[x_write+3]); \ - g[x_write+3] = y4 - dG; \ - CLAMP(g[x_write+3]); \ - b[x_write+3] = y4 + dB; \ - CLAMP(b[x_write+3]); \ - \ - x_write = (x_write + 4) & 7; \ - } while (0) +#define DECODE_YUV211() \ + do { \ + uint8_t y1, y2, y3, y4; \ + int8_t U, V; \ + int dR, dG, dB; \ + \ + U = src[0] - 0x80; \ + y1 = (298 * (src[1] - 16)) >> 8; \ + y2 = (298 * (src[2] - 16)) >> 8; \ + V = src[3] - 0x80; \ + y3 = (298 * (src[4] - 16)) >> 8; \ + y4 = (298 * (src[5] - 16)) >> 8; \ + src += 6; \ + \ + dR = (309 * V) >> 8; \ + dG = (100 * U + 208 * V) >> 8; \ + dB = (516 * U) >> 8; \ + \ + r[x_write] = y1 + dR; \ + CLAMP(r[x_write]); \ + g[x_write] = y1 - dG; \ + CLAMP(g[x_write]); \ + b[x_write] = y1 + dB; \ + CLAMP(b[x_write]); \ + \ + r[x_write + 1] = y2 + dR; \ + CLAMP(r[x_write + 1]); \ + g[x_write + 1] = y2 - dG; \ + CLAMP(g[x_write + 1]); \ + b[x_write + 1] = y2 + dB; \ + CLAMP(b[x_write + 1]); \ + \ + r[x_write + 2] = y3 + dR; \ + CLAMP(r[x_write + 2]); \ + g[x_write + 2] = y3 - dG; \ + CLAMP(g[x_write + 2]); \ + b[x_write + 2] = y3 + dB; \ + CLAMP(b[x_write + 2]); \ + \ + r[x_write + 3] = y4 + dR; \ + CLAMP(r[x_write + 3]); \ + g[x_write + 3] = y4 - dG; \ + CLAMP(g[x_write + 3]); \ + b[x_write + 3] = y4 + dB; \ + CLAMP(b[x_write + 3]); \ + \ + x_write = (x_write + 4) & 7; \ + } while (0) -#define DECODE_YUV422() \ - do \ - { \ - int c; \ - \ - for (c = 0; c < 2; c++) \ - { \ - uint8_t y1, y2; \ - int8_t U, V; \ - int dR, dG, dB; \ - \ - U = src[0] - 0x80; \ - y1 = (298 * (src[1] - 16)) >> 8; \ - V = src[2] - 0x80; \ - y2 = (298 * (src[3] - 16)) >> 8; \ - src += 4; \ - \ - dR = (309*V) >> 8; \ - dG = (100*U + 208*V) >> 8; \ - dB = (516*U) >> 8; \ - \ - r[x_write] = y1 + dR; \ - CLAMP(r[x_write]); \ - g[x_write] = y1 - dG; \ - CLAMP(g[x_write]); \ - b[x_write] = y1 + dB; \ - CLAMP(b[x_write]); \ - \ - r[x_write+1] = y2 + dR; \ - CLAMP(r[x_write+1]); \ - g[x_write+1] = y2 - dG; \ - CLAMP(g[x_write+1]); \ - b[x_write+1] = y2 + dB; \ - CLAMP(b[x_write+1]); \ - \ - x_write = (x_write + 2) & 7; \ - } \ - } while (0) +#define DECODE_YUV422() \ + do { \ + int c; \ + \ + for (c = 0; c < 2; c++) { \ + uint8_t y1, y2; \ + int8_t U, V; \ + int dR, dG, dB; \ + \ + U = src[0] - 0x80; \ + y1 = (298 * (src[1] - 16)) >> 8; \ + V = src[2] - 0x80; \ + y2 = (298 * (src[3] - 16)) >> 8; \ + src += 4; \ + \ + dR = (309 * V) >> 8; \ + dG = (100 * U + 208 * V) >> 8; \ + dB = (516 * U) >> 8; \ + \ + r[x_write] = y1 + dR; \ + CLAMP(r[x_write]); \ + g[x_write] = y1 - dG; \ + CLAMP(g[x_write]); \ + b[x_write] = y1 + dB; \ + CLAMP(b[x_write]); \ + \ + r[x_write + 1] = y2 + dR; \ + CLAMP(r[x_write + 1]); \ + g[x_write + 1] = y2 - dG; \ + CLAMP(g[x_write + 1]); \ + b[x_write + 1] = y2 + dB; \ + CLAMP(b[x_write + 1]); \ + \ + x_write = (x_write + 2) & 7; \ + } \ + } while (0) -#define DECODE_RGB555() \ - do \ - { \ - int c; \ - \ - for (c = 0; c < 4; c++) \ - { \ - uint16_t dat; \ - \ - dat = *(uint16_t *)src; \ - src += 2; \ - \ - r[x_write + c] = ((dat & 0x001f) << 3) | ((dat & 0x001f) >> 2); \ - g[x_write + c] = ((dat & 0x03e0) >> 2) | ((dat & 0x03e0) >> 7); \ - b[x_write + c] = ((dat & 0x7c00) >> 7) | ((dat & 0x7c00) >> 12); \ - } \ - x_write = (x_write + 4) & 7; \ - } while (0) +#define DECODE_RGB555() \ + do { \ + int c; \ + \ + for (c = 0; c < 4; c++) { \ + uint16_t dat; \ + \ + dat = *(uint16_t *) src; \ + src += 2; \ + \ + r[x_write + c] = ((dat & 0x001f) << 3) | ((dat & 0x001f) >> 2); \ + g[x_write + c] = ((dat & 0x03e0) >> 2) | ((dat & 0x03e0) >> 7); \ + b[x_write + c] = ((dat & 0x7c00) >> 7) | ((dat & 0x7c00) >> 12); \ + } \ + x_write = (x_write + 4) & 7; \ + } while (0) -#define DECODE_RGB565() \ - do \ - { \ - int c; \ - \ - for (c = 0; c < 4; c++) \ - { \ - uint16_t dat; \ - \ - dat = *(uint16_t *)src; \ - src += 2; \ - \ - r[x_write + c] = ((dat & 0x001f) << 3) | ((dat & 0x001f) >> 2); \ - g[x_write + c] = ((dat & 0x07e0) >> 3) | ((dat & 0x07e0) >> 9); \ - b[x_write + c] = ((dat & 0xf800) >> 8) | ((dat & 0xf800) >> 13); \ - } \ - x_write = (x_write + 4) & 7; \ - } while (0) +#define DECODE_RGB565() \ + do { \ + int c; \ + \ + for (c = 0; c < 4; c++) { \ + uint16_t dat; \ + \ + dat = *(uint16_t *) src; \ + src += 2; \ + \ + r[x_write + c] = ((dat & 0x001f) << 3) | ((dat & 0x001f) >> 2); \ + g[x_write + c] = ((dat & 0x07e0) >> 3) | ((dat & 0x07e0) >> 9); \ + b[x_write + c] = ((dat & 0xf800) >> 8) | ((dat & 0xf800) >> 13); \ + } \ + x_write = (x_write + 4) & 7; \ + } while (0) -#define DECODE_CLUT() \ - do \ - { \ - int c; \ - \ - for (c = 0; c < 4; c++) \ - { \ - uint8_t dat; \ - \ - dat = *(uint8_t *)src; \ - src++; \ - \ - r[x_write + c] = svga->pallook[dat] >> 0; \ - g[x_write + c] = svga->pallook[dat] >> 8; \ - b[x_write + c] = svga->pallook[dat] >> 16; \ - } \ - x_write = (x_write + 4) & 7; \ - } while (0) - - - -#define OVERLAY_SAMPLE() \ - do \ - { \ - switch (gd54xx->overlay.mode) \ - { \ - case 0: \ - DECODE_YUV422(); \ - break; \ - case 2: \ - DECODE_CLUT(); \ - break; \ - case 3: \ - DECODE_YUV211(); \ - break; \ - case 4: \ - DECODE_RGB555(); \ - break; \ - case 5: \ - DECODE_RGB565(); \ - break; \ - } \ - } while (0) +#define DECODE_CLUT() \ + do { \ + int c; \ + \ + for (c = 0; c < 4; c++) { \ + uint8_t dat; \ + \ + dat = *(uint8_t *) src; \ + src++; \ + \ + r[x_write + c] = svga->pallook[dat] >> 0; \ + g[x_write + c] = svga->pallook[dat] >> 8; \ + b[x_write + c] = svga->pallook[dat] >> 16; \ + } \ + x_write = (x_write + 4) & 7; \ + } while (0) +#define OVERLAY_SAMPLE() \ + do { \ + switch (gd54xx->overlay.mode) { \ + case 0: \ + DECODE_YUV422(); \ + break; \ + case 2: \ + DECODE_CLUT(); \ + break; \ + case 3: \ + DECODE_YUV211(); \ + break; \ + case 4: \ + DECODE_RGB555(); \ + break; \ + case 5: \ + DECODE_RGB565(); \ + break; \ + } \ + } while (0) static int gd54xx_interrupt_enabled(gd54xx_t *gd54xx) @@ -486,123 +508,112 @@ gd54xx_interrupt_enabled(gd54xx_t *gd54xx) return !gd54xx->pci || (gd54xx->svga.gdcreg[0x17] & 0x04); } - static int gd54xx_vga_vsync_enabled(gd54xx_t *gd54xx) { - if (!(gd54xx->svga.crtc[0x11] & 0x20) && (gd54xx->svga.crtc[0x11] & 0x10) && - gd54xx_interrupt_enabled(gd54xx)) + if (!(gd54xx->svga.crtc[0x11] & 0x20) && (gd54xx->svga.crtc[0x11] & 0x10) && gd54xx_interrupt_enabled(gd54xx)) return 1; return 0; } - static void gd54xx_update_irqs(gd54xx_t *gd54xx) { if (!gd54xx->pci) - return; + return; if ((gd54xx->vblank_irq > 0) && gd54xx_vga_vsync_enabled(gd54xx)) - pci_set_irq(gd54xx->card, PCI_INTA); + pci_set_irq(gd54xx->pci_slot, PCI_INTA, &gd54xx->irq_state); else - pci_clear_irq(gd54xx->card, PCI_INTA); + pci_clear_irq(gd54xx->pci_slot, PCI_INTA, &gd54xx->irq_state); } - static void gd54xx_vblank_start(svga_t *svga) { - gd54xx_t *gd54xx = (gd54xx_t*) svga->p; + gd54xx_t *gd54xx = (gd54xx_t *) svga->priv; if (gd54xx->vblank_irq >= 0) { gd54xx->vblank_irq = 1; gd54xx_update_irqs(gd54xx); } } - /* Returns 1 if the card is a 5422+ */ static int gd54xx_is_5422(svga_t *svga) { if (svga->crtc[0x27] >= CIRRUS_ID_CLGD5422) - return 1; + return 1; else - return 0; + return 0; } - static void gd54xx_overlay_draw(svga_t *svga, int displine) { - gd54xx_t *gd54xx = (gd54xx_t *) svga->p; - int shift = (svga->crtc[0x27] >= CIRRUS_ID_CLGD5446) ? 2 : 0; - int h_acc = svga->overlay_latch.h_acc; - int r[8], g[8], b[8]; - int x_read = 4, x_write = 4; - int x; - uint32_t *p; - uint8_t *src = &svga->vram[(svga->overlay_latch.addr << shift) & svga->vram_mask]; - int bpp = svga->bpp; - int bytesperpix = (bpp + 7) / 8; - uint8_t *src2 = &svga->vram[(svga->ma - (svga->hdisp * bytesperpix)) & svga->vram_display_mask]; - int w = gd54xx->overlay.r2sdz; - int occl, ckval; + const gd54xx_t *gd54xx = (gd54xx_t *) svga->priv; + int shift = (svga->crtc[0x27] >= CIRRUS_ID_CLGD5446) ? 2 : 0; + int h_acc = svga->overlay_latch.h_acc; + int r[8]; + int g[8]; + int b[8]; + int x_read = 4; + int x_write = 4; + uint32_t *p; + uint8_t *src = &svga->vram[(svga->overlay_latch.addr << shift) & svga->vram_mask]; + int bpp = svga->bpp; + int bytesperpix = (bpp + 7) / 8; + uint8_t *src2 = &svga->vram[(svga->ma - (svga->hdisp * bytesperpix)) & svga->vram_display_mask]; + int occl; + int ckval; - if (gd54xx->overlay.mode == 2) - w *= 4; - else - w *= 2; - - p = &((uint32_t *)buffer32->line[displine])[gd54xx->overlay.region1size + svga->x_add]; + p = &(svga->monitor->target_buffer->line[displine])[gd54xx->overlay.region1size + svga->x_add]; src2 += gd54xx->overlay.region1size * bytesperpix; OVERLAY_SAMPLE(); - for (x = 0; (x < gd54xx->overlay.region2size) && - ((x + gd54xx->overlay.region1size) < svga->hdisp); x++) { - if (gd54xx->overlay.occlusion) { - occl = 1; - ckval = gd54xx->overlay.ck; - if (bytesperpix == 1) { - if (*src2 == ckval) - occl = 0; - } else if (bytesperpix == 2) { - if (*((uint16_t*)src2) == ckval) - occl = 0; - } else - occl = 0; - if (!occl) - *p++ = r[x_read] | (g[x_read] << 8) | (b[x_read] << 16); - src2 += bytesperpix; - } else - *p++ = r[x_read] | (g[x_read] << 8) | (b[x_read] << 16); + for (int x = 0; (x < gd54xx->overlay.region2size) && ((x + gd54xx->overlay.region1size) < svga->hdisp); x++) { + if (gd54xx->overlay.occlusion) { + occl = 1; + ckval = gd54xx->overlay.ck; + if (bytesperpix == 1) { + if (*src2 == ckval) + occl = 0; + } else if (bytesperpix == 2) { + if (*((uint16_t *) src2) == ckval) + occl = 0; + } else + occl = 0; + if (!occl) + *p++ = r[x_read] | (g[x_read] << 8) | (b[x_read] << 16); + src2 += bytesperpix; + } else + *p++ = r[x_read] | (g[x_read] << 8) | (b[x_read] << 16); - h_acc += gd54xx->overlay.hzoom; - if (h_acc >= 256) { - if ((x_read ^ (x_read + 1)) & ~3) - OVERLAY_SAMPLE(); - x_read = (x_read + 1) & 7; + h_acc += gd54xx->overlay.hzoom; + if (h_acc >= 256) { + if ((x_read ^ (x_read + 1)) & ~3) + OVERLAY_SAMPLE(); + x_read = (x_read + 1) & 7; - h_acc -= 256; - } + h_acc -= 256; + } } svga->overlay_latch.v_acc += gd54xx->overlay.vzoom; if (svga->overlay_latch.v_acc >= 256) { - svga->overlay_latch.v_acc -= 256; - svga->overlay_latch.addr += svga->overlay.pitch << 1; + svga->overlay_latch.v_acc -= 256; + svga->overlay_latch.addr += svga->overlay.pitch << 1; } } - static void gd54xx_update_overlay(gd54xx_t *gd54xx) { svga_t *svga = &gd54xx->svga; - int bpp = svga->bpp; + int bpp = svga->bpp; - svga->overlay.ysize = gd54xx->overlay.wve - gd54xx->overlay.wvs + 1; + svga->overlay.cur_ysize = gd54xx->overlay.wve - gd54xx->overlay.wvs + 1; gd54xx->overlay.region1size = 32 * gd54xx->overlay.r1sz / bpp + (gd54xx->overlay.r1adjust * 8 / bpp); gd54xx->overlay.region2size = 32 * gd54xx->overlay.r2sz / bpp + (gd54xx->overlay.r2adjust * 8 / bpp); @@ -610,1377 +621,1496 @@ gd54xx_update_overlay(gd54xx_t *gd54xx) /* Mask and chroma key ignored. */ if (gd54xx->overlay.colorkeymode == 0) - gd54xx->overlay.ck = gd54xx->overlay.colorkeycompare; + gd54xx->overlay.ck = gd54xx->overlay.colorkeycompare; else if (gd54xx->overlay.colorkeymode == 1) - gd54xx->overlay.ck = gd54xx->overlay.colorkeycompare | (gd54xx->overlay.colorkeycomparemask << 8); + gd54xx->overlay.ck = gd54xx->overlay.colorkeycompare | (gd54xx->overlay.colorkeycomparemask << 8); else - gd54xx->overlay.occlusion = 0; + gd54xx->overlay.occlusion = 0; } - /* Returns 1 if the card supports the 8-bpp/16-bpp transparency color or mask. */ static int gd54xx_has_transp(svga_t *svga, int mask) { - if (((svga->crtc[0x27] == CIRRUS_ID_CLGD5446) || (svga->crtc[0x27] == CIRRUS_ID_CLGD5480)) && - !mask) - return 1; /* 5446 and 5480 have mask but not transparency. */ + if (((svga->crtc[0x27] == CIRRUS_ID_CLGD5446) || (svga->crtc[0x27] == CIRRUS_ID_CLGD5480)) && !mask) + return 1; /* 5446 and 5480 have mask but not transparency. */ if ((svga->crtc[0x27] == CIRRUS_ID_CLGD5426) || (svga->crtc[0x27] == CIRRUS_ID_CLGD5428)) - return 1; /* 5426 and 5428 have both. */ + return 1; /* 5426 and 5428 have both. */ else - return 0; /* The rest have neither. */ + return 0; /* The rest have neither. */ } - /* Returns 1 if the card is a 5434, 5436/46, or 5480. */ static int gd54xx_is_5434(svga_t *svga) { if (svga->crtc[0x27] >= CIRRUS_ID_CLGD5434) - return 1; + return 1; else - return 0; + return 0; } - static void -gd54xx_out(uint16_t addr, uint8_t val, void *p) +gd54xx_out(uint16_t addr, uint8_t val, void *priv) { - gd54xx_t *gd54xx = (gd54xx_t *)p; - svga_t *svga = &gd54xx->svga; - uint8_t old; - int c; - uint8_t o, index; - uint32_t o32; + gd54xx_t *gd54xx = (gd54xx_t *) priv; + svga_t *svga = &gd54xx->svga; + uint8_t old; + uint8_t o; + uint8_t index; + uint32_t o32; - if (((addr & 0xfff0) == 0x3d0 || (addr & 0xfff0) == 0x3b0) && !(svga->miscout & 1)) - addr ^= 0x60; + if (((addr & 0xfff0) == 0x3d0 || (addr & 0xfff0) == 0x3b0) && !(svga->miscout & 1)) + addr ^= 0x60; switch (addr) { - case 0x3c0: - case 0x3c1: - if (!svga->attrff) { - svga->attraddr = val & 31; - if ((val & 0x20) != svga->attr_palette_enable) { - svga->fullchange = 3; - svga->attr_palette_enable = val & 0x20; - svga_recalctimings(svga); - } - } else { - o = svga->attrregs[svga->attraddr & 31]; - svga->attrregs[svga->attraddr & 31] = val; - if (svga->attraddr < 16) - svga->fullchange = changeframecount; - if (svga->attraddr == 0x10 || svga->attraddr == 0x14 || svga->attraddr < 0x10) { - for (c = 0; c < 16; c++) { - if (svga->attrregs[0x10] & 0x80) svga->egapal[c] = (svga->attrregs[c] & 0xf) | ((svga->attrregs[0x14] & 0xf) << 4); - else svga->egapal[c] = (svga->attrregs[c] & 0x3f) | ((svga->attrregs[0x14] & 0xc) << 4); - } - } - /* Recalculate timings on change of attribute register 0x11 (overscan border color) too. */ - if (svga->attraddr == 0x10) { - if (o != val) - svga_recalctimings(svga); - } else if (svga->attraddr == 0x11) { - if (!(svga->seqregs[0x12] & 0x80)) { - svga->overscan_color = svga->pallook[svga->attrregs[0x11]]; - if (o != val) svga_recalctimings(svga); - } - } else if (svga->attraddr == 0x12) { - if ((val & 0xf) != svga->plane_mask) - svga->fullchange = changeframecount; - svga->plane_mask = val & 0xf; - } - } - svga->attrff ^= 1; - return; - - case 0x3c4: - svga->seqaddr = val; - break; - case 0x3c5: - if ((svga->seqaddr == 2) && !gd54xx->unlocked) { - o = svga->seqregs[svga->seqaddr & 0x1f]; - svga_out(addr, val, svga); - svga->seqregs[svga->seqaddr & 0x1f] = (o & 0xf0) | (val & 0x0f); - return; - } else if ((svga->seqaddr > 6) && !gd54xx->unlocked) - return; + case 0x3c0: + case 0x3c1: + if (!svga->attrff) { + svga->attraddr = val & 31; + if ((val & 0x20) != svga->attr_palette_enable) { + svga->fullchange = 3; + svga->attr_palette_enable = val & 0x20; + svga_recalctimings(svga); + } + } else { + o = svga->attrregs[svga->attraddr & 31]; + svga->attrregs[svga->attraddr & 31] = val; + if (svga->attraddr < 16) + svga->fullchange = changeframecount; + if (svga->attraddr == 0x10 || svga->attraddr == 0x14 || svga->attraddr < 0x10) { + for (uint8_t c = 0; c < 16; c++) { + if (svga->attrregs[0x10] & 0x80) + svga->egapal[c] = (svga->attrregs[c] & 0xf) | ((svga->attrregs[0x14] & 0xf) << 4); + else + svga->egapal[c] = (svga->attrregs[c] & 0x3f) | ((svga->attrregs[0x14] & 0xc) << 4); + } + } + /* Recalculate timings on change of attribute register 0x11 (overscan border color) too. */ + if (svga->attraddr == 0x10) { + if (o != val) + svga_recalctimings(svga); + } else if (svga->attraddr == 0x11) { + if (!(svga->seqregs[0x12] & 0x80)) { + svga->overscan_color = svga->pallook[svga->attrregs[0x11]]; + if (o != val) + svga_recalctimings(svga); + } + } else if (svga->attraddr == 0x12) { + if ((val & 0xf) != svga->plane_mask) + svga->fullchange = changeframecount; + svga->plane_mask = val & 0xf; + } + } + svga->attrff ^= 1; + return; - if (svga->seqaddr > 5) { - o = svga->seqregs[svga->seqaddr & 0x1f]; - svga->seqregs[svga->seqaddr & 0x1f] = val; - switch (svga->seqaddr) { - case 6: - val &= 0x17; - if (val == 0x12) - svga->seqregs[6] = 0x12; - else - svga->seqregs[6] = 0x0f; - if (svga->crtc[0x27] < CIRRUS_ID_CLGD5429) - gd54xx->unlocked = (svga->seqregs[6] == 0x12); - break; - case 0x08: - if (gd54xx->i2c) - i2c_gpio_set(gd54xx->i2c, !!(val & 0x01), !!(val & 0x02)); - break; - case 0x0b: case 0x0c: case 0x0d: case 0x0e: /* VCLK stuff */ - gd54xx->vclk_n[svga->seqaddr-0x0b] = val; - break; - case 0x1b: case 0x1c: case 0x1d: case 0x1e: /* VCLK stuff */ - gd54xx->vclk_d[svga->seqaddr-0x1b] = val; - break; - case 0x10: case 0x30: case 0x50: case 0x70: - case 0x90: case 0xb0: case 0xd0: case 0xf0: - svga->hwcursor.x = (val << 3) | (svga->seqaddr >> 5); - break; - case 0x11: case 0x31: case 0x51: case 0x71: - case 0x91: case 0xb1: case 0xd1: case 0xf1: - svga->hwcursor.y = (val << 3) | (svga->seqaddr >> 5); - break; - case 0x12: - svga->ext_overscan = !!(val & 0x80); - if (svga->ext_overscan && (svga->crtc[0x27] >= CIRRUS_ID_CLGD5426)) - svga->overscan_color = gd54xx->extpallook[2]; - else - svga->overscan_color = svga->pallook[svga->attrregs[0x11]]; - svga_recalctimings(svga); - svga->hwcursor.ena = val & CIRRUS_CURSOR_SHOW; - if (svga->crtc[0x27] >= CIRRUS_ID_CLGD5422) - svga->hwcursor.xsize = svga->hwcursor.ysize = - ((val & CIRRUS_CURSOR_LARGE) && (svga->crtc[0x27] >= CIRRUS_ID_CLGD5422)) ? 64 : 32; - else - svga->hwcursor.xsize = 32; + case 0x3c4: + svga->seqaddr = val; + break; + case 0x3c5: + if ((svga->seqaddr == 2) && !gd54xx->unlocked) { + o = svga->seqregs[svga->seqaddr & 0x1f]; + svga_out(addr, val, svga); + if (svga->gdcreg[0xb] & 0x04) + svga->seqregs[svga->seqaddr & 0x1f] = (o & 0xf0) | (val & 0x0f); + return; + } else if ((svga->seqaddr > 6) && !gd54xx->unlocked) + return; - if ((svga->seqregs[0x12] & CIRRUS_CURSOR_LARGE) && (svga->crtc[0x27] >= CIRRUS_ID_CLGD5422)) - svga->hwcursor.addr = ((gd54xx->vram_size - 0x4000) + ((svga->seqregs[0x13] & 0x3c) * 256)); - else - svga->hwcursor.addr = ((gd54xx->vram_size - 0x4000) + ((svga->seqregs[0x13] & 0x3f) * 256)); - break; - case 0x13: - if ((svga->seqregs[0x12] & CIRRUS_CURSOR_LARGE) && (svga->crtc[0x27] >= CIRRUS_ID_CLGD5422)) - svga->hwcursor.addr = ((gd54xx->vram_size - 0x4000) + ((val & 0x3c) * 256)); - else - svga->hwcursor.addr = ((gd54xx->vram_size - 0x4000) + ((val & 0x3f) * 256)); - break; - case 0x07: - svga->packed_chain4 = svga->seqregs[7] & 1; - svga_recalctimings(svga); - if (gd54xx_is_5422(svga)) - gd543x_recalc_mapping(gd54xx); - else - svga->seqregs[svga->seqaddr] &= 0x0f; - if (svga->crtc[0x27] >= CIRRUS_ID_CLGD5429) - svga->set_reset_disabled = svga->seqregs[7] & 1; - break; - case 0x17: - if (gd54xx_is_5422(svga)) - gd543x_recalc_mapping(gd54xx); - else - return; - break; - } - return; - } - break; - case 0x3c6: - if (!gd54xx->unlocked) - break; - if (gd54xx->ramdac.state == 4) { - gd54xx->ramdac.state = 0; - gd54xx->ramdac.ctrl = val; - svga_recalctimings(svga); - return; - } - gd54xx->ramdac.state = 0; - break; - case 0x3c7: case 0x3c8: - gd54xx->ramdac.state = 0; - break; - case 0x3c9: - gd54xx->ramdac.state = 0; - svga->dac_status = 0; - svga->fullchange = changeframecount; - switch (svga->dac_pos) { - case 0: - svga->dac_r = val; - svga->dac_pos++; - break; - case 1: - svga->dac_g = val; - svga->dac_pos++; - break; - case 2: - index = svga->dac_addr & 0xff; - if (svga->seqregs[0x12] & 2) { - index &= 0x0f; - gd54xx->extpal[index].r = svga->dac_r; - gd54xx->extpal[index].g = svga->dac_g; - gd54xx->extpal[index].b = val; - gd54xx->extpallook[index] = makecol32(video_6to8[gd54xx->extpal[index].r & 0x3f], video_6to8[gd54xx->extpal[index].g & 0x3f], video_6to8[gd54xx->extpal[index].b & 0x3f]); - if (svga->ext_overscan && (index == 2)) { - o32 = svga->overscan_color; - svga->overscan_color = gd54xx->extpallook[2]; - if (o32 != svga->overscan_color) - svga_recalctimings(svga); - } - } else { - svga->vgapal[index].r = svga->dac_r; - svga->vgapal[index].g = svga->dac_g; - svga->vgapal[index].b = val; - svga->pallook[index] = makecol32(video_6to8[svga->vgapal[index].r & 0x3f], video_6to8[svga->vgapal[index].g & 0x3f], video_6to8[svga->vgapal[index].b & 0x3f]); - } - svga->dac_addr = (svga->dac_addr + 1) & 255; - svga->dac_pos = 0; + if (svga->seqaddr > 5) { + o = svga->seqregs[svga->seqaddr & 0x1f]; + svga->seqregs[svga->seqaddr & 0x1f] = val; + switch (svga->seqaddr) { + case 6: + val &= 0x17; + if (val == 0x12) + svga->seqregs[6] = 0x12; + else + svga->seqregs[6] = 0x0f; + if (svga->crtc[0x27] < CIRRUS_ID_CLGD5429) + gd54xx->unlocked = (svga->seqregs[6] == 0x12); + break; + case 0x08: + if (gd54xx->i2c) + i2c_gpio_set(gd54xx->i2c, !!(val & 0x01), !!(val & 0x02)); + break; + case 0x0b: + case 0x0c: + case 0x0d: + case 0x0e: /* VCLK stuff */ + gd54xx->vclk_n[svga->seqaddr - 0x0b] = val; + break; + case 0x1b: + case 0x1c: + case 0x1d: + case 0x1e: /* VCLK stuff */ + gd54xx->vclk_d[svga->seqaddr - 0x1b] = val; + break; + case 0x10: + case 0x30: + case 0x50: + case 0x70: + case 0x90: + case 0xb0: + case 0xd0: + case 0xf0: + svga->hwcursor.x = (val << 3) | (svga->seqaddr >> 5); + break; + case 0x11: + case 0x31: + case 0x51: + case 0x71: + case 0x91: + case 0xb1: + case 0xd1: + case 0xf1: + svga->hwcursor.y = (val << 3) | (svga->seqaddr >> 5); + break; + case 0x12: + svga->ext_overscan = !!(val & 0x80); + if (svga->ext_overscan && (svga->crtc[0x27] >= CIRRUS_ID_CLGD5426)) + svga->overscan_color = gd54xx->extpallook[2]; + else + svga->overscan_color = svga->pallook[svga->attrregs[0x11]]; + svga_recalctimings(svga); + svga->hwcursor.ena = val & CIRRUS_CURSOR_SHOW; + if (svga->crtc[0x27] >= CIRRUS_ID_CLGD5422) + svga->hwcursor.cur_xsize = svga->hwcursor.cur_ysize = ((val & CIRRUS_CURSOR_LARGE) && (svga->crtc[0x27] >= CIRRUS_ID_CLGD5422)) ? 64 : 32; + else + svga->hwcursor.cur_xsize = 32; + + if ((svga->seqregs[0x12] & CIRRUS_CURSOR_LARGE) && (svga->crtc[0x27] >= CIRRUS_ID_CLGD5422)) + svga->hwcursor.addr = ((gd54xx->vram_size - 0x4000) + ((svga->seqregs[0x13] & 0x3c) * 256)); + else + svga->hwcursor.addr = ((gd54xx->vram_size - 0x4000) + ((svga->seqregs[0x13] & 0x3f) * 256)); + break; + case 0x13: + if ((svga->seqregs[0x12] & CIRRUS_CURSOR_LARGE) && (svga->crtc[0x27] >= CIRRUS_ID_CLGD5422)) + svga->hwcursor.addr = ((gd54xx->vram_size - 0x4000) + ((val & 0x3c) * 256)); + else + svga->hwcursor.addr = ((gd54xx->vram_size - 0x4000) + ((val & 0x3f) * 256)); + break; + case 0x07: + svga->packed_chain4 = svga->seqregs[7] & 1; + svga_recalctimings(svga); + if (gd54xx_is_5422(svga)) + gd543x_recalc_mapping(gd54xx); + else + svga->seqregs[svga->seqaddr] &= 0x0f; + if (svga->crtc[0x27] >= CIRRUS_ID_CLGD5429) + svga->set_reset_disabled = svga->seqregs[7] & 1; + break; + case 0x17: + if (gd54xx_is_5422(svga)) + gd543x_recalc_mapping(gd54xx); + else + return; + break; + + default: break; } return; - case 0x3ce: - /* Per the CL-GD 5446 manual: bits 0-5 are the GDC register index, bits 6-7 are reserved. */ - svga->gdcaddr = val/* & 0x3f*/; - return; - case 0x3cf: - if ((svga->gdcaddr > 0x1f) && ((svga->crtc[0x27] <= CIRRUS_ID_CLGD5422) || - (svga->crtc[0x27] == CIRRUS_ID_CLGD5424))) - return; - - o = svga->gdcreg[svga->gdcaddr]; - - if ((svga->gdcaddr < 2) && !gd54xx->unlocked) - svga->gdcreg[svga->gdcaddr] = (svga->gdcreg[svga->gdcaddr] & 0xf0) | (val & 0x0f); - else if ((svga->gdcaddr <= 8) || gd54xx->unlocked) - svga->gdcreg[svga->gdcaddr] = val; - - if (svga->gdcaddr <= 8) { - switch (svga->gdcaddr) { - case 0: - gd543x_mmio_write(0xb8000, val, gd54xx); - break; - case 1: - gd543x_mmio_write(0xb8004, val, gd54xx); - break; - case 2: - svga->colourcompare = val; - break; - case 4: - svga->readplane = val & 3; - break; - case 5: - if (svga->gdcreg[0xb] & 0x04) - svga->writemode = val & 7; - else - svga->writemode = val & 3; - svga->readmode = val & 8; - svga->chain2_read = val & 0x10; - break; - case 6: - if ((o ^ val) & 0x0c) - gd543x_recalc_mapping(gd54xx); - break; - case 7: - svga->colournocare = val; - break; - } - - if ((svga->crtc[0x27] == CIRRUS_ID_CLGD5422) || (svga->crtc[0x27] == CIRRUS_ID_CLGD5424)) - svga->fast = (svga->gdcreg[8] == 0xff && !(svga->gdcreg[3] & 0x18) && - !svga->gdcreg[1]) && ((svga->chain4 && svga->packed_chain4) || svga->fb_only) && !(svga->adv_flags & FLAG_ADDR_BY8); /*TODO: needs verification on other Cirrus chips*/ - else - svga->fast = (svga->gdcreg[8] == 0xff && !(svga->gdcreg[3] & 0x18) && - !svga->gdcreg[1]) && ((svga->chain4 && svga->packed_chain4) || svga->fb_only); - if (((svga->gdcaddr == 5) && ((val ^ o) & 0x70)) || - ((svga->gdcaddr == 6) && ((val ^ o) & 1))) - svga_recalctimings(svga); - } else { - switch (svga->gdcaddr) { - case 0x09: case 0x0a: case 0x0b: - if (svga->gdcreg[0xb] & 0x04) - svga->writemode = svga->gdcreg[5] & 7; - else - svga->writemode = svga->gdcreg[5] & 3; - svga->adv_flags = 0; - if (svga->gdcreg[0xb] & 0x01) - svga->adv_flags = FLAG_EXTRA_BANKS; - if (svga->gdcreg[0xb] & 0x02) - svga->adv_flags |= FLAG_ADDR_BY8; - if (svga->gdcreg[0xb] & 0x04) - svga->adv_flags |= FLAG_EXT_WRITE; - if (svga->gdcreg[0xb] & 0x08) - svga->adv_flags |= FLAG_LATCH8; - if (svga->gdcreg[0xb] & 0x10) - svga->adv_flags |= FLAG_ADDR_BY16; - gd54xx_recalc_banking(gd54xx); - break; - - case 0x0c: - gd54xx->overlay.colorkeycompare = val; - gd54xx_update_overlay(gd54xx); - break; - case 0x0d: - gd54xx->overlay.colorkeycomparemask = val; - gd54xx_update_overlay(gd54xx); - break; - - case 0x0e: - if (svga->crtc[0x27] >= CIRRUS_ID_CLGD5429) { - svga->dpms = (val & 0x06) && ((svga->miscout & ((val & 0x06) << 5)) != 0xc0); - svga_recalctimings(svga); - } - break; - - case 0x10: - gd543x_mmio_write(0xb8001, val, gd54xx); - break; - case 0x11: - gd543x_mmio_write(0xb8005, val, gd54xx); - break; - case 0x12: - gd543x_mmio_write(0xb8002, val, gd54xx); - break; - case 0x13: - gd543x_mmio_write(0xb8006, val, gd54xx); - break; - case 0x14: - gd543x_mmio_write(0xb8003, val, gd54xx); - break; - case 0x15: - gd543x_mmio_write(0xb8007, val, gd54xx); - break; - - case 0x20: - gd543x_mmio_write(0xb8008, val, gd54xx); - break; - case 0x21: - gd543x_mmio_write(0xb8009, val, gd54xx); - break; - case 0x22: - gd543x_mmio_write(0xb800a, val, gd54xx); - break; - case 0x23: - gd543x_mmio_write(0xb800b, val, gd54xx); - break; - case 0x24: - gd543x_mmio_write(0xb800c, val, gd54xx); - break; - case 0x25: - gd543x_mmio_write(0xb800d, val, gd54xx); - break; - case 0x26: - gd543x_mmio_write(0xb800e, val, gd54xx); - break; - case 0x27: - gd543x_mmio_write(0xb800f, val, gd54xx); - break; - - case 0x28: - gd543x_mmio_write(0xb8010, val, gd54xx); - break; - case 0x29: - gd543x_mmio_write(0xb8011, val, gd54xx); - break; - case 0x2a: - gd543x_mmio_write(0xb8012, val, gd54xx); - break; - - case 0x2c: - gd543x_mmio_write(0xb8014, val, gd54xx); - break; - case 0x2d: - gd543x_mmio_write(0xb8015, val, gd54xx); - break; - case 0x2e: - gd543x_mmio_write(0xb8016, val, gd54xx); - break; - - case 0x2f: - gd543x_mmio_write(0xb8017, val, gd54xx); - break; - case 0x30: - gd543x_mmio_write(0xb8018, val, gd54xx); - break; - - case 0x32: - gd543x_mmio_write(0xb801a, val, gd54xx); - break; - - case 0x33: - gd543x_mmio_write(0xb801b, val, gd54xx); - break; - - case 0x31: - gd543x_mmio_write(0xb8040, val, gd54xx); - break; - - case 0x34: - gd543x_mmio_write(0xb801c, val, gd54xx); - break; - - case 0x35: - gd543x_mmio_write(0xb801d, val, gd54xx); - break; - - case 0x38: - gd543x_mmio_write(0xb8020, val, gd54xx); - break; - - case 0x39: - gd543x_mmio_write(0xb8021, val, gd54xx); - break; - } - } - return; - - case 0x3d4: - svga->crtcreg = val & gd54xx->crtcreg_mask; - return; - case 0x3d5: - if (((svga->crtcreg == 0x19) || (svga->crtcreg == 0x1a) || - (svga->crtcreg == 0x1b) || (svga->crtcreg == 0x1d) || - (svga->crtcreg == 0x25) || (svga->crtcreg == 0x27)) && - !gd54xx->unlocked) - 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 (svga->crtcreg == 0x11) { - if (!(val & 0x10)) { - if (gd54xx->vblank_irq > 0) - gd54xx->vblank_irq = -1; - } else if (gd54xx->vblank_irq < 0) - gd54xx->vblank_irq = 0; - gd54xx_update_irqs(gd54xx); - if ((val & ~0x30) == (old & ~0x30)) - old = val; - } - - if (old != val) { - /* Overlay registers */ - switch (svga->crtcreg) { - case 0x1d: - if (((old >> 3) & 7) != ((val >> 3) & 7)) { - gd54xx->overlay.colorkeymode = (val >> 3) & 7; - gd54xx_update_overlay(gd54xx); - } - break; - case 0x31: - gd54xx->overlay.hzoom = val == 0 ? 256 : val; - gd54xx_update_overlay(gd54xx); - break; - case 0x32: - gd54xx->overlay.vzoom = val == 0 ? 256 : val; - gd54xx_update_overlay(gd54xx); - break; - case 0x33: - gd54xx->overlay.r1sz &= ~0xff; - gd54xx->overlay.r1sz |= val; - gd54xx_update_overlay(gd54xx); - break; - case 0x34: - gd54xx->overlay.r2sz &= ~0xff; - gd54xx->overlay.r2sz |= val; - gd54xx_update_overlay(gd54xx); - break; - case 0x35: - gd54xx->overlay.r2sdz &= ~0xff; - gd54xx->overlay.r2sdz |= val; - gd54xx_update_overlay(gd54xx); - break; - case 0x36: - gd54xx->overlay.r1sz &= 0xff; - gd54xx->overlay.r1sz |= (val << 8) & 0x300; - gd54xx->overlay.r2sz &= 0xff; - gd54xx->overlay.r2sz |= (val << 6) & 0x300; - gd54xx->overlay.r2sdz &= 0xff; - gd54xx->overlay.r2sdz |= (val << 4) & 0x300; - gd54xx_update_overlay(gd54xx); - break; - case 0x37: - gd54xx->overlay.wvs &= ~0xff; - gd54xx->overlay.wvs |= val; - svga->overlay.y = gd54xx->overlay.wvs; - break; - case 0x38: - gd54xx->overlay.wve &= ~0xff; - gd54xx->overlay.wve |= val; - gd54xx_update_overlay(gd54xx); - break; - case 0x39: - gd54xx->overlay.wvs &= 0xff; - gd54xx->overlay.wvs |= (val << 8) & 0x300; - gd54xx->overlay.wve &= 0xff; - gd54xx->overlay.wve |= (val << 6) & 0x300; - gd54xx_update_overlay(gd54xx); - break; - case 0x3a: - svga->overlay.addr &= ~0xff; - svga->overlay.addr |= val; - gd54xx_update_overlay(gd54xx); - break; - case 0x3b: - svga->overlay.addr &= ~0xff00; - svga->overlay.addr |= val << 8; - gd54xx_update_overlay(gd54xx); - break; - case 0x3c: - svga->overlay.addr &= ~0x0f0000; - svga->overlay.addr |= (val << 16) & 0x0f0000; - svga->overlay.pitch &= ~0x100; - svga->overlay.pitch |= (val & 0x20) << 3; - gd54xx_update_overlay(gd54xx); - break; - case 0x3d: - svga->overlay.pitch &= ~0xff; - svga->overlay.pitch |= val; - gd54xx_update_overlay(gd54xx); - break; - case 0x3e: - gd54xx->overlay.mode = (val >> 1) & 7; - svga->overlay.ena = (val & 1) != 0; - gd54xx_update_overlay(gd54xx); - break; - } - - 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; + case 0x3c6: + if (!gd54xx->unlocked) + break; + if (gd54xx->ramdac.state == 4) { + gd54xx->ramdac.state = 0; + gd54xx->ramdac.ctrl = val; + svga_recalctimings(svga); + return; + } + gd54xx->ramdac.state = 0; + break; + case 0x3c7: + case 0x3c8: + gd54xx->ramdac.state = 0; + break; + case 0x3c9: + gd54xx->ramdac.state = 0; + svga->dac_status = 0; + svga->fullchange = changeframecount; + switch (svga->dac_pos) { + case 0: + svga->dac_r = val; + svga->dac_pos++; + break; + case 1: + svga->dac_g = val; + svga->dac_pos++; + break; + case 2: + index = svga->dac_addr & 0xff; + if (svga->seqregs[0x12] & 2) { + index &= 0x0f; + gd54xx->extpal[index].r = svga->dac_r; + gd54xx->extpal[index].g = svga->dac_g; + gd54xx->extpal[index].b = val; + gd54xx->extpallook[index] = makecol32(video_6to8[gd54xx->extpal[index].r & 0x3f], video_6to8[gd54xx->extpal[index].g & 0x3f], video_6to8[gd54xx->extpal[index].b & 0x3f]); + if (svga->ext_overscan && (index == 2)) { + o32 = svga->overscan_color; + svga->overscan_color = gd54xx->extpallook[2]; + if (o32 != svga->overscan_color) + svga_recalctimings(svga); } - } - break; + } else { + svga->vgapal[index].r = svga->dac_r; + svga->vgapal[index].g = svga->dac_g; + svga->vgapal[index].b = val; + svga->pallook[index] = makecol32(video_6to8[svga->vgapal[index].r & 0x3f], video_6to8[svga->vgapal[index].g & 0x3f], video_6to8[svga->vgapal[index].b & 0x3f]); + } + svga->dac_addr = (svga->dac_addr + 1) & 255; + svga->dac_pos = 0; + break; + + default: + break; + } + return; + case 0x3ce: + /* Per the CL-GD 5446 manual: bits 0-5 are the GDC register index, bits 6-7 are reserved. */ + svga->gdcaddr = val /* & 0x3f*/; + return; + case 0x3cf: + if ((svga->gdcaddr > 0x1f) && ((svga->crtc[0x27] <= CIRRUS_ID_CLGD5422) || (svga->crtc[0x27] == CIRRUS_ID_CLGD5424))) + return; + + o = svga->gdcreg[svga->gdcaddr]; + + if ((svga->gdcaddr < 2) && !gd54xx->unlocked) + svga->gdcreg[svga->gdcaddr] = (svga->gdcreg[svga->gdcaddr] & 0xf0) | (val & 0x0f); + else if ((svga->gdcaddr <= 8) || gd54xx->unlocked) + svga->gdcreg[svga->gdcaddr] = val; + + if (svga->gdcaddr <= 8) { + switch (svga->gdcaddr) { + case 0: + gd543x_mmio_write(0xb8000, val, gd54xx); + break; + case 1: + gd543x_mmio_write(0xb8004, val, gd54xx); + break; + case 2: + svga->colourcompare = val; + break; + case 4: + svga->readplane = val & 3; + break; + case 5: + if (svga->gdcreg[0xb] & 0x04) + svga->writemode = val & 7; + else + svga->writemode = val & 3; + svga->readmode = val & 8; + svga->chain2_read = val & 0x10; + break; + case 6: + if ((o ^ val) & 0x0c) + gd543x_recalc_mapping(gd54xx); + break; + case 7: + svga->colournocare = val; + break; + + default: + break; + } + + if ((svga->crtc[0x27] == CIRRUS_ID_CLGD5422) || (svga->crtc[0x27] == CIRRUS_ID_CLGD5424)) + svga->fast = (svga->gdcreg[8] == 0xff && !(svga->gdcreg[3] & 0x18) && !svga->gdcreg[1]) && ((svga->chain4 && svga->packed_chain4) || svga->fb_only) && !(svga->adv_flags & FLAG_ADDR_BY8); /*TODO: needs verification on other Cirrus chips*/ + else + svga->fast = (svga->gdcreg[8] == 0xff && !(svga->gdcreg[3] & 0x18) && !svga->gdcreg[1]) && ((svga->chain4 && svga->packed_chain4) || svga->fb_only); + if (((svga->gdcaddr == 5) && ((val ^ o) & 0x70)) || ((svga->gdcaddr == 6) && ((val ^ o) & 1))) + svga_recalctimings(svga); + } else { + switch (svga->gdcaddr) { + case 0x0b: + svga->adv_flags = 0; + if (svga->gdcreg[0xb] & 0x01) + svga->adv_flags = FLAG_EXTRA_BANKS; + if (svga->gdcreg[0xb] & 0x02) + svga->adv_flags |= FLAG_ADDR_BY8; + if (svga->gdcreg[0xb] & 0x04) + svga->adv_flags |= FLAG_EXT_WRITE; + if (svga->gdcreg[0xb] & 0x08) + svga->adv_flags |= FLAG_LATCH8; + if ((svga->gdcreg[0xb] & 0x10) && (svga->adv_flags & FLAG_EXT_WRITE)) + svga->adv_flags |= FLAG_ADDR_BY16; + if (svga->gdcreg[0xb] & 0x04) + svga->writemode = svga->gdcreg[5] & 7; + else if (o & 0x4) { + svga->gdcreg[5] &= ~0x04; + svga->writemode = svga->gdcreg[5] & 3; + svga->adv_flags &= (FLAG_EXTRA_BANKS | FLAG_ADDR_BY8 | FLAG_LATCH8); + if (svga->crtc[0x27] != CIRRUS_ID_CLGD5436) { + svga->gdcreg[0] &= 0x0f; + gd543x_mmio_write(0xb8000, svga->gdcreg[0], gd54xx); + svga->gdcreg[1] &= 0x0f; + gd543x_mmio_write(0xb8004, svga->gdcreg[1], gd54xx); + } + svga->seqregs[2] &= 0x0f; + } + fallthrough; + case 0x09: + case 0x0a: + gd54xx_recalc_banking(gd54xx); + break; + + case 0x0c: + gd54xx->overlay.colorkeycompare = val; + gd54xx_update_overlay(gd54xx); + break; + case 0x0d: + gd54xx->overlay.colorkeycomparemask = val; + gd54xx_update_overlay(gd54xx); + break; + + case 0x0e: + if (svga->crtc[0x27] >= CIRRUS_ID_CLGD5429) { + svga->dpms = (val & 0x06) && ((svga->miscout & ((val & 0x06) << 5)) != 0xc0); + svga_recalctimings(svga); + } + break; + + case 0x10: + gd543x_mmio_write(0xb8001, val, gd54xx); + break; + case 0x11: + gd543x_mmio_write(0xb8005, val, gd54xx); + break; + case 0x12: + gd543x_mmio_write(0xb8002, val, gd54xx); + break; + case 0x13: + gd543x_mmio_write(0xb8006, val, gd54xx); + break; + case 0x14: + gd543x_mmio_write(0xb8003, val, gd54xx); + break; + case 0x15: + gd543x_mmio_write(0xb8007, val, gd54xx); + break; + + case 0x20: + gd543x_mmio_write(0xb8008, val, gd54xx); + break; + case 0x21: + gd543x_mmio_write(0xb8009, val, gd54xx); + break; + case 0x22: + gd543x_mmio_write(0xb800a, val, gd54xx); + break; + case 0x23: + gd543x_mmio_write(0xb800b, val, gd54xx); + break; + case 0x24: + gd543x_mmio_write(0xb800c, val, gd54xx); + break; + case 0x25: + gd543x_mmio_write(0xb800d, val, gd54xx); + break; + case 0x26: + gd543x_mmio_write(0xb800e, val, gd54xx); + break; + case 0x27: + gd543x_mmio_write(0xb800f, val, gd54xx); + break; + + case 0x28: + gd543x_mmio_write(0xb8010, val, gd54xx); + break; + case 0x29: + gd543x_mmio_write(0xb8011, val, gd54xx); + break; + case 0x2a: + gd543x_mmio_write(0xb8012, val, gd54xx); + break; + + case 0x2c: + gd543x_mmio_write(0xb8014, val, gd54xx); + break; + case 0x2d: + gd543x_mmio_write(0xb8015, val, gd54xx); + break; + case 0x2e: + gd543x_mmio_write(0xb8016, val, gd54xx); + break; + + case 0x2f: + gd543x_mmio_write(0xb8017, val, gd54xx); + break; + case 0x30: + gd543x_mmio_write(0xb8018, val, gd54xx); + break; + + case 0x32: + gd543x_mmio_write(0xb801a, val, gd54xx); + break; + + case 0x33: + gd543x_mmio_write(0xb801b, val, gd54xx); + break; + + case 0x31: + gd543x_mmio_write(0xb8040, val, gd54xx); + break; + + case 0x34: + gd543x_mmio_write(0xb801c, val, gd54xx); + break; + + case 0x35: + gd543x_mmio_write(0xb801d, val, gd54xx); + break; + + case 0x38: + gd543x_mmio_write(0xb8020, val, gd54xx); + break; + + case 0x39: + gd543x_mmio_write(0xb8021, val, gd54xx); + break; + + default: + break; + } + } + return; + + case 0x3d4: + svga->crtcreg = val & gd54xx->crtcreg_mask; + return; + case 0x3d5: + if (((svga->crtcreg == 0x19) || (svga->crtcreg == 0x1a) || (svga->crtcreg == 0x1b) || (svga->crtcreg == 0x1d) || (svga->crtcreg == 0x25) || (svga->crtcreg == 0x27)) && !gd54xx->unlocked) + return; + if ((svga->crtcreg == 0x25) || (svga->crtcreg == 0x27)) + 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 (svga->crtcreg == 0x11) { + if (!(val & 0x10)) { + if (gd54xx->vblank_irq > 0) + gd54xx->vblank_irq = -1; + } else if (gd54xx->vblank_irq < 0) + gd54xx->vblank_irq = 0; + gd54xx_update_irqs(gd54xx); + if ((val & ~0x30) == (old & ~0x30)) + old = val; + } + + if (old != val) { + /* Overlay registers */ + switch (svga->crtcreg) { + case 0x1d: + if (((old >> 3) & 7) != ((val >> 3) & 7)) { + gd54xx->overlay.colorkeymode = (val >> 3) & 7; + gd54xx_update_overlay(gd54xx); + } + break; + case 0x31: + gd54xx->overlay.hzoom = val == 0 ? 256 : val; + gd54xx_update_overlay(gd54xx); + break; + case 0x32: + gd54xx->overlay.vzoom = val == 0 ? 256 : val; + gd54xx_update_overlay(gd54xx); + break; + case 0x33: + gd54xx->overlay.r1sz &= ~0xff; + gd54xx->overlay.r1sz |= val; + gd54xx_update_overlay(gd54xx); + break; + case 0x34: + gd54xx->overlay.r2sz &= ~0xff; + gd54xx->overlay.r2sz |= val; + gd54xx_update_overlay(gd54xx); + break; + case 0x35: + gd54xx->overlay.r2sdz &= ~0xff; + gd54xx->overlay.r2sdz |= val; + gd54xx_update_overlay(gd54xx); + break; + case 0x36: + gd54xx->overlay.r1sz &= 0xff; + gd54xx->overlay.r1sz |= (val << 8) & 0x300; + gd54xx->overlay.r2sz &= 0xff; + gd54xx->overlay.r2sz |= (val << 6) & 0x300; + gd54xx->overlay.r2sdz &= 0xff; + gd54xx->overlay.r2sdz |= (val << 4) & 0x300; + gd54xx_update_overlay(gd54xx); + break; + case 0x37: + gd54xx->overlay.wvs &= ~0xff; + gd54xx->overlay.wvs |= val; + svga->overlay.y = gd54xx->overlay.wvs; + break; + case 0x38: + gd54xx->overlay.wve &= ~0xff; + gd54xx->overlay.wve |= val; + gd54xx_update_overlay(gd54xx); + break; + case 0x39: + gd54xx->overlay.wvs &= 0xff; + gd54xx->overlay.wvs |= (val << 8) & 0x300; + gd54xx->overlay.wve &= 0xff; + gd54xx->overlay.wve |= (val << 6) & 0x300; + gd54xx_update_overlay(gd54xx); + break; + case 0x3a: + svga->overlay.addr &= ~0xff; + svga->overlay.addr |= val; + gd54xx_update_overlay(gd54xx); + break; + case 0x3b: + svga->overlay.addr &= ~0xff00; + svga->overlay.addr |= val << 8; + gd54xx_update_overlay(gd54xx); + break; + case 0x3c: + svga->overlay.addr &= ~0x0f0000; + svga->overlay.addr |= (val << 16) & 0x0f0000; + svga->overlay.pitch &= ~0x100; + svga->overlay.pitch |= (val & 0x20) << 3; + gd54xx_update_overlay(gd54xx); + break; + case 0x3d: + svga->overlay.pitch &= ~0xff; + svga->overlay.pitch |= val; + gd54xx_update_overlay(gd54xx); + break; + case 0x3e: + gd54xx->overlay.mode = (val >> 1) & 7; + svga->overlay.ena = (val & 1) != 0; + gd54xx_update_overlay(gd54xx); + break; + + default: + break; + } + + 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; + + default: + break; } svga_out(addr, val, svga); } - static uint8_t -gd54xx_in(uint16_t addr, void *p) +gd54xx_in(uint16_t addr, void *priv) { - gd54xx_t *gd54xx = (gd54xx_t *)p; - svga_t *svga = &gd54xx->svga; + gd54xx_t *gd54xx = (gd54xx_t *) priv; + svga_t *svga = &gd54xx->svga; - uint8_t index, ret = 0xff; + uint8_t index; + uint8_t ret = 0xff; - if (((addr & 0xfff0) == 0x3d0 || (addr & 0xfff0) == 0x3b0) && !(svga->miscout & 1)) - addr ^= 0x60; + if (((addr & 0xfff0) == 0x3d0 || (addr & 0xfff0) == 0x3b0) && !(svga->miscout & 1)) + addr ^= 0x60; switch (addr) { - case 0x3c2: - ret = svga_in(addr, svga); - ret |= gd54xx->vblank_irq > 0 ? 0x80 : 0x00; - break; + case 0x3c2: + ret = svga_in(addr, svga); + ret |= gd54xx->vblank_irq > 0 ? 0x80 : 0x00; + break; - case 0x3c4: - if (svga->seqregs[6] == 0x12) { - ret = svga->seqaddr; - if ((ret & 0x1e) == 0x10) { - if (ret & 1) - ret = ((svga->hwcursor.y & 7) << 5) | 0x11; - else - ret = ((svga->hwcursor.x & 7) << 5) | 0x10; - } - } else - ret = svga->seqaddr; - break; + case 0x3c4: + if (svga->seqregs[6] == 0x12) { + ret = svga->seqaddr; + if ((ret & 0x1e) == 0x10) { + if (ret & 1) + ret = ((svga->hwcursor.y & 7) << 5) | 0x11; + else + ret = ((svga->hwcursor.x & 7) << 5) | 0x10; + } + } else + ret = svga->seqaddr; + break; - case 0x3c5: - if ((svga->seqaddr == 2) && !gd54xx->unlocked) - ret = svga_in(addr, svga) & 0x0f; - else if ((svga->seqaddr > 6) && !gd54xx->unlocked) - ret = 0xff; - else if (svga->seqaddr > 5) { - ret = svga->seqregs[svga->seqaddr & 0x3f]; - switch (svga->seqaddr) { - case 6: - ret = svga->seqregs[6]; - break; - case 0x08: - if (gd54xx->i2c) { - ret &= 0x7b; - if (i2c_gpio_get_scl(gd54xx->i2c)) - ret |= 0x04; - if (i2c_gpio_get_sda(gd54xx->i2c)) - ret |= 0x80; - } - break; - case 0x0a: /*Scratch Pad 1 (Memory size for 5402/542x)*/ - ret = svga->seqregs[0x0a] & ~0x1a; - if (svga->crtc[0x27] == CIRRUS_ID_CLGD5402) { - ret |= 0x01; /*512K of memory*/ - } else if (svga->crtc[0x27] > CIRRUS_ID_CLGD5402) { - switch (gd54xx->vram_size >> 10) { - case 512: - ret |= 0x08; - break; - case 1024: - ret |= 0x10; - break; - case 2048: - ret |= 0x18; - break; - } - } - break; - case 0x0b: case 0x0c: case 0x0d: case 0x0e: - ret = gd54xx->vclk_n[svga->seqaddr-0x0b]; - break; - case 0x0f: /*DRAM control*/ - ret = svga->seqregs[0x0f] & ~0x98; - switch (gd54xx->vram_size >> 10) { - case 512: - ret |= 0x08; /*16-bit DRAM data bus width*/ - break; - case 1024: - ret |= 0x10; /*32-bit DRAM data bus width for 1M of memory*/ - break; - case 2048: - ret |= (gd54xx_is_5434(svga)) ? 0x98 : 0x18; /*32-bit (Pre-5434)/64-bit (5434 and up) DRAM data bus width for 2M of memory*/ - break; - case 4096: - ret |= 0x98; /*64-bit (5434 and up) DRAM data bus width for 4M of memory*/ - break; - } - break; - case 0x15: /*Scratch Pad 3 (Memory size for 543x)*/ - ret = svga->seqregs[0x15] & ~0x0f; - if (svga->crtc[0x27] >= CIRRUS_ID_CLGD5430) { - switch (gd54xx->vram_size >> 20) { - case 1: - ret |= 0x02; - break; - case 2: - ret |= 0x03; - break; - case 4: - ret |= 0x04; - break; - } - } - break; - case 0x17: - ret = svga->seqregs[0x17] & ~(7 << 3); - if (svga->crtc[0x27] <= CIRRUS_ID_CLGD5429) { - if ((svga->crtc[0x27] == CIRRUS_ID_CLGD5428) || (svga->crtc[0x27] == CIRRUS_ID_CLGD5426)) { - if (gd54xx->vlb) - ret |= (CL_GD5428_SYSTEM_BUS_VESA << 3); - else if (gd54xx->mca) - ret |= (CL_GD5428_SYSTEM_BUS_MCA << 3); - else - ret |= (CL_GD5428_SYSTEM_BUS_ISA << 3); - } else { - if (gd54xx->vlb) - ret |= (CL_GD5429_SYSTEM_BUS_VESA << 3); - else - ret |= (CL_GD5429_SYSTEM_BUS_ISA << 3); - } - } else { - if (gd54xx->pci) - ret |= (CL_GD543X_SYSTEM_BUS_PCI << 3); - else if (gd54xx->vlb) - ret |= (CL_GD543X_SYSTEM_BUS_VESA << 3); - else - ret |= (CL_GD543X_SYSTEM_BUS_ISA << 3); - } - break; - case 0x18: - ret = svga->seqregs[0x18] & 0xfe; - break; - case 0x1b: case 0x1c: case 0x1d: case 0x1e: - ret = gd54xx->vclk_d[svga->seqaddr - 0x1b]; - break; - } - break; - } else - ret = svga_in(addr, svga); - break; - case 0x3c6: - if (!gd54xx->unlocked) - ret = svga_in(addr, svga); - else if (gd54xx->ramdac.state == 4) { - /* CL-GD 5428 does not lock the register when it's read. */ - if (svga->crtc[0x27] != CIRRUS_ID_CLGD5428) - gd54xx->ramdac.state = 0; - ret = gd54xx->ramdac.ctrl; - } else { - gd54xx->ramdac.state++; - if (gd54xx->ramdac.state == 4) - ret = gd54xx->ramdac.ctrl; - else - ret = svga_in(addr, svga); - } - break; - case 0x3c7: case 0x3c8: - gd54xx->ramdac.state = 0; - ret = svga_in(addr, svga); - break; - case 0x3c9: - gd54xx->ramdac.state = 0; - svga->dac_status = 3; - index = (svga->dac_addr - 1) & 0xff; - if (svga->seqregs[0x12] & 2) - index &= 0x0f; - switch (svga->dac_pos) { - case 0: - svga->dac_pos++; - if (svga->seqregs[0x12] & 2) - ret = gd54xx->extpal[index].r & 0x3f; - else - ret = svga->vgapal[index].r & 0x3f; - break; - case 1: - svga->dac_pos++; - if (svga->seqregs[0x12] & 2) - ret = gd54xx->extpal[index].g & 0x3f; - else - ret = svga->vgapal[index].g & 0x3f; - break; - case 2: - svga->dac_pos=0; - svga->dac_addr = (svga->dac_addr + 1) & 255; - if (svga->seqregs[0x12] & 2) - ret = gd54xx->extpal[index].b & 0x3f; - else - ret = svga->vgapal[index].b & 0x3f; - break; + case 0x3c5: + if ((svga->seqaddr == 2) && !gd54xx->unlocked) + ret = svga_in(addr, svga) & 0x0f; + else if ((svga->seqaddr > 6) && !gd54xx->unlocked) + ret = 0xff; + else if (svga->seqaddr > 5) { + ret = svga->seqregs[svga->seqaddr & 0x3f]; + switch (svga->seqaddr) { + case 6: + ret = svga->seqregs[6]; + break; + case 0x08: + if (gd54xx->i2c) { + ret &= 0x7b; + if (i2c_gpio_get_scl(gd54xx->i2c)) + ret |= 0x04; + if (i2c_gpio_get_sda(gd54xx->i2c)) + ret |= 0x80; + } + break; + case 0x0a: /*Scratch Pad 1 (Memory size for 5402/542x)*/ + ret = svga->seqregs[0x0a] & ~0x1a; + if (svga->crtc[0x27] == CIRRUS_ID_CLGD5402) { + ret |= 0x01; /*512K of memory*/ + } else if (svga->crtc[0x27] > CIRRUS_ID_CLGD5402) { + switch (gd54xx->vram_size >> 10) { + case 512: + ret |= 0x08; + break; + case 1024: + ret |= 0x10; + break; + case 2048: + ret |= 0x18; + break; + + default: + break; + } + } + break; + case 0x0b: + case 0x0c: + case 0x0d: + case 0x0e: + ret = gd54xx->vclk_n[svga->seqaddr - 0x0b]; + break; + case 0x0f: /*DRAM control*/ + ret = svga->seqregs[0x0f] & ~0x98; + switch (gd54xx->vram_size >> 10) { + case 512: + ret |= 0x08; /*16-bit DRAM data bus width*/ + break; + case 1024: + ret |= 0x10; /*32-bit DRAM data bus width for 1M of memory*/ + break; + case 2048: + ret |= (gd54xx_is_5434(svga)) ? 0x98 : 0x18; /*32-bit (Pre-5434)/64-bit (5434 and up) DRAM data bus width for 2M of memory*/ + break; + case 4096: + ret |= 0x98; /*64-bit (5434 and up) DRAM data bus width for 4M of memory*/ + break; + + default: + break; + } + break; + case 0x15: /*Scratch Pad 3 (Memory size for 543x)*/ + ret = svga->seqregs[0x15] & ~0x0f; + if (svga->crtc[0x27] >= CIRRUS_ID_CLGD5430) { + switch (gd54xx->vram_size >> 20) { + case 1: + ret |= 0x02; + break; + case 2: + ret |= 0x03; + break; + case 4: + ret |= 0x04; + break; + + default: + break; + } + } + break; + case 0x17: + ret = svga->seqregs[0x17] & ~(7 << 3); + if (svga->crtc[0x27] <= CIRRUS_ID_CLGD5429) { + if ((svga->crtc[0x27] == CIRRUS_ID_CLGD5428) || (svga->crtc[0x27] == CIRRUS_ID_CLGD5426)) { + if (gd54xx->vlb) + ret |= (CL_GD5428_SYSTEM_BUS_VESA << 3); + else if (gd54xx->mca) + ret |= (CL_GD5428_SYSTEM_BUS_MCA << 3); + else + ret |= (CL_GD5428_SYSTEM_BUS_ISA << 3); + } else { + if (gd54xx->vlb) + ret |= (CL_GD5429_SYSTEM_BUS_VESA << 3); + else + ret |= (CL_GD5429_SYSTEM_BUS_ISA << 3); + } + } else { + if (gd54xx->pci) + ret |= (CL_GD543X_SYSTEM_BUS_PCI << 3); + else if (gd54xx->vlb) + ret |= (CL_GD543X_SYSTEM_BUS_VESA << 3); + else + ret |= (CL_GD543X_SYSTEM_BUS_ISA << 3); + } + break; + case 0x18: + ret = svga->seqregs[0x18] & 0xfe; + break; + case 0x1b: + case 0x1c: + case 0x1d: + case 0x1e: + ret = gd54xx->vclk_d[svga->seqaddr - 0x1b]; + break; + + default: + break; } break; - case 0x3ce: - ret = svga->gdcaddr & 0x3f; - break; - case 0x3cf: - if (svga->gdcaddr >= 0x10) { - if ((svga->gdcaddr > 8) && !gd54xx->unlocked) - ret = 0xff; - else if ((svga->gdcaddr > 0x1f) && ((svga->crtc[0x27] <= CIRRUS_ID_CLGD5422) || - (svga->crtc[0x27] == CIRRUS_ID_CLGD5424))) - ret = 0xff; - else switch (svga->gdcaddr) { - case 0x10: - ret = gd543x_mmio_read(0xb8001, gd54xx); - break; - case 0x11: - ret = gd543x_mmio_read(0xb8005, gd54xx); - break; - case 0x12: - ret = gd543x_mmio_read(0xb8002, gd54xx); - break; - case 0x13: - ret = gd543x_mmio_read(0xb8006, gd54xx); - break; - case 0x14: - ret = gd543x_mmio_read(0xb8003, gd54xx); - break; - case 0x15: - ret = gd543x_mmio_read(0xb8007, gd54xx); - break; + } else + ret = svga_in(addr, svga); + break; + case 0x3c6: + if (!gd54xx->unlocked) + ret = svga_in(addr, svga); + else if (gd54xx->ramdac.state == 4) { + /* CL-GD 5428 does not lock the register when it's read. */ + if (svga->crtc[0x27] != CIRRUS_ID_CLGD5428) + gd54xx->ramdac.state = 0; + ret = gd54xx->ramdac.ctrl; + } else { + gd54xx->ramdac.state++; + if (gd54xx->ramdac.state == 4) + ret = gd54xx->ramdac.ctrl; + else + ret = svga_in(addr, svga); + } + break; + case 0x3c7: + case 0x3c8: + gd54xx->ramdac.state = 0; + ret = svga_in(addr, svga); + break; + case 0x3c9: + gd54xx->ramdac.state = 0; + svga->dac_status = 3; + index = (svga->dac_addr - 1) & 0xff; + if (svga->seqregs[0x12] & 2) + index &= 0x0f; + switch (svga->dac_pos) { + case 0: + svga->dac_pos++; + if (svga->seqregs[0x12] & 2) + ret = gd54xx->extpal[index].r & 0x3f; + else + ret = svga->vgapal[index].r & 0x3f; + break; + case 1: + svga->dac_pos++; + if (svga->seqregs[0x12] & 2) + ret = gd54xx->extpal[index].g & 0x3f; + else + ret = svga->vgapal[index].g & 0x3f; + break; + case 2: + svga->dac_pos = 0; + svga->dac_addr = (svga->dac_addr + 1) & 255; + if (svga->seqregs[0x12] & 2) + ret = gd54xx->extpal[index].b & 0x3f; + else + ret = svga->vgapal[index].b & 0x3f; + break; - case 0x20: - ret = gd543x_mmio_read(0xb8008, gd54xx); - break; - case 0x21: - ret = gd543x_mmio_read(0xb8009, gd54xx); - break; - case 0x22: - ret = gd543x_mmio_read(0xb800a, gd54xx); - break; - case 0x23: - ret = gd543x_mmio_read(0xb800b, gd54xx); - break; - case 0x24: - ret = gd543x_mmio_read(0xb800c, gd54xx); - break; - case 0x25: - ret = gd543x_mmio_read(0xb800d, gd54xx); - break; - case 0x26: - ret = gd543x_mmio_read(0xb800e, gd54xx); - break; - case 0x27: - ret = gd543x_mmio_read(0xb800f, gd54xx); - break; + default: + break; + } + break; + case 0x3ce: + ret = svga->gdcaddr & 0x3f; + break; + case 0x3cf: + if (svga->gdcaddr >= 0x10) { + if ((svga->gdcaddr > 8) && !gd54xx->unlocked) + ret = 0xff; + else if ((svga->gdcaddr > 0x1f) && ((svga->crtc[0x27] <= CIRRUS_ID_CLGD5422) || (svga->crtc[0x27] == CIRRUS_ID_CLGD5424))) + ret = 0xff; + else + switch (svga->gdcaddr) { + case 0x10: + ret = gd543x_mmio_read(0xb8001, gd54xx); + break; + case 0x11: + ret = gd543x_mmio_read(0xb8005, gd54xx); + break; + case 0x12: + ret = gd543x_mmio_read(0xb8002, gd54xx); + break; + case 0x13: + ret = gd543x_mmio_read(0xb8006, gd54xx); + break; + case 0x14: + ret = gd543x_mmio_read(0xb8003, gd54xx); + break; + case 0x15: + ret = gd543x_mmio_read(0xb8007, gd54xx); + break; - case 0x28: - ret = gd543x_mmio_read(0xb8010, gd54xx); - break; - case 0x29: - ret = gd543x_mmio_read(0xb8011, gd54xx); - break; - case 0x2a: - ret = gd543x_mmio_read(0xb8012, gd54xx); - break; + case 0x20: + ret = gd543x_mmio_read(0xb8008, gd54xx); + break; + case 0x21: + ret = gd543x_mmio_read(0xb8009, gd54xx); + break; + case 0x22: + ret = gd543x_mmio_read(0xb800a, gd54xx); + break; + case 0x23: + ret = gd543x_mmio_read(0xb800b, gd54xx); + break; + case 0x24: + ret = gd543x_mmio_read(0xb800c, gd54xx); + break; + case 0x25: + ret = gd543x_mmio_read(0xb800d, gd54xx); + break; + case 0x26: + ret = gd543x_mmio_read(0xb800e, gd54xx); + break; + case 0x27: + ret = gd543x_mmio_read(0xb800f, gd54xx); + break; - case 0x2c: - ret = gd543x_mmio_read(0xb8014, gd54xx); - break; - case 0x2d: - ret = gd543x_mmio_read(0xb8015, gd54xx); - break; - case 0x2e: - ret = gd543x_mmio_read(0xb8016, gd54xx); - break; + case 0x28: + ret = gd543x_mmio_read(0xb8010, gd54xx); + break; + case 0x29: + ret = gd543x_mmio_read(0xb8011, gd54xx); + break; + case 0x2a: + ret = gd543x_mmio_read(0xb8012, gd54xx); + break; - case 0x2f: - ret = gd543x_mmio_read(0xb8017, gd54xx); - break; - case 0x30: - ret = gd543x_mmio_read(0xb8018, gd54xx); - break; + case 0x2c: + ret = gd543x_mmio_read(0xb8014, gd54xx); + break; + case 0x2d: + ret = gd543x_mmio_read(0xb8015, gd54xx); + break; + case 0x2e: + ret = gd543x_mmio_read(0xb8016, gd54xx); + break; - case 0x32: - ret = gd543x_mmio_read(0xb801a, gd54xx); - break; + case 0x2f: + ret = gd543x_mmio_read(0xb8017, gd54xx); + break; + case 0x30: + ret = gd543x_mmio_read(0xb8018, gd54xx); + break; - case 0x33: - ret = gd543x_mmio_read(0xb801b, gd54xx); - break; + case 0x32: + ret = gd543x_mmio_read(0xb801a, gd54xx); + break; - case 0x31: - ret = gd543x_mmio_read(0xb8040, gd54xx); - break; + case 0x33: + ret = gd543x_mmio_read(0xb801b, gd54xx); + break; - case 0x34: - ret = gd543x_mmio_read(0xb801c, gd54xx); - break; + case 0x31: + ret = gd543x_mmio_read(0xb8040, gd54xx); + break; - case 0x35: - ret = gd543x_mmio_read(0xb801d, gd54xx); - break; + case 0x34: + ret = gd543x_mmio_read(0xb801c, gd54xx); + break; - case 0x38: - ret = gd543x_mmio_read(0xb8020, gd54xx); - break; + case 0x35: + ret = gd543x_mmio_read(0xb801d, gd54xx); + break; - case 0x39: - ret = gd543x_mmio_read(0xb8021, gd54xx); - break; + case 0x38: + ret = gd543x_mmio_read(0xb8020, gd54xx); + break; - case 0x3f: - if (svga->crtc[0x27] == CIRRUS_ID_CLGD5446) - gd54xx->vportsync = !gd54xx->vportsync; - ret = gd54xx->vportsync ? 0x80 : 0x00; - break; - } - } else { - if ((svga->gdcaddr < 2) && !gd54xx->unlocked) - ret = (svga->gdcreg[svga->gdcaddr] & 0x0f); - else { - if (svga->gdcaddr == 0) - ret = gd543x_mmio_read(0xb8000, gd54xx); - else if (svga->gdcaddr == 1) - ret = gd543x_mmio_read(0xb8004, gd54xx); - else - ret = svga->gdcreg[svga->gdcaddr]; - } - } - break; - case 0x3d4: - ret = svga->crtcreg; - break; - case 0x3d5: - ret = svga->crtc[svga->crtcreg]; - if (((svga->crtcreg == 0x19) || (svga->crtcreg == 0x1a) || - (svga->crtcreg == 0x1b) || (svga->crtcreg == 0x1d) || - (svga->crtcreg == 0x25) || (svga->crtcreg == 0x27)) && - !gd54xx->unlocked) - ret = 0xff; - else switch (svga->crtcreg) { - case 0x22: /*Graphics Data Latches Readback Register*/ - /*Should this be & 7 if 8 byte latch is enabled? */ - ret = svga->latch.b[svga->gdcreg[4] & 3]; - break; - case 0x24: /*Attribute controller toggle readback (R)*/ - ret = svga->attrff << 7; - break; - case 0x26: /*Attribute controller index readback (R)*/ - ret = svga->attraddr & 0x3f; - break; - case 0x27: /*ID*/ - ret = svga->crtc[0x27]; /*GD542x/GD543x*/ - break; - case 0x28: /*Class ID*/ - if ((svga->crtc[0x27] == CIRRUS_ID_CLGD5430) || (svga->crtc[0x27] == CIRRUS_ID_CLGD5440)) - ret = 0xff; /*Standard CL-GD5430/40*/ - break; - } - break; - default: - ret = svga_in(addr, svga); - break; + case 0x39: + ret = gd543x_mmio_read(0xb8021, gd54xx); + break; + + case 0x3f: + if (svga->crtc[0x27] == CIRRUS_ID_CLGD5446) + gd54xx->vportsync = !gd54xx->vportsync; + ret = gd54xx->vportsync ? 0x80 : 0x00; + break; + + default: + break; + } + } else { + if ((svga->gdcaddr < 2) && !gd54xx->unlocked) + ret = (svga->gdcreg[svga->gdcaddr] & 0x0f); + else { + if (svga->gdcaddr == 0) + ret = gd543x_mmio_read(0xb8000, gd54xx); + else if (svga->gdcaddr == 1) + ret = gd543x_mmio_read(0xb8004, gd54xx); + else + ret = svga->gdcreg[svga->gdcaddr]; + } + } + break; + case 0x3d4: + ret = svga->crtcreg; + break; + case 0x3d5: + ret = svga->crtc[svga->crtcreg]; + if (((svga->crtcreg == 0x19) || (svga->crtcreg == 0x1a) || (svga->crtcreg == 0x1b) || (svga->crtcreg == 0x1d) || (svga->crtcreg == 0x25) || (svga->crtcreg == 0x27)) && !gd54xx->unlocked) + ret = 0xff; + else + switch (svga->crtcreg) { + case 0x22: /*Graphics Data Latches Readback Register*/ + /*Should this be & 7 if 8 byte latch is enabled? */ + ret = svga->latch.b[svga->gdcreg[4] & 3]; + break; + case 0x24: /*Attribute controller toggle readback (R)*/ + ret = svga->attrff << 7; + break; + case 0x26: /*Attribute controller index readback (R)*/ + ret = svga->attraddr & 0x3f; + break; + case 0x27: /*ID*/ + ret = svga->crtc[0x27]; /*GD542x/GD543x*/ + break; + case 0x28: /*Class ID*/ + if ((svga->crtc[0x27] == CIRRUS_ID_CLGD5430) || (svga->crtc[0x27] == CIRRUS_ID_CLGD5440)) + ret = 0xff; /*Standard CL-GD5430/40*/ + break; + + default: + break; + } + break; + default: + ret = svga_in(addr, svga); + break; } return ret; } - static void gd54xx_recalc_banking(gd54xx_t *gd54xx) { svga_t *svga = &gd54xx->svga; if (!gd54xx_is_5422(svga)) { - svga->extra_banks[0] = (svga->gdcreg[0x09] & 0x7f) << 12; + svga->extra_banks[0] = (svga->gdcreg[0x09] & 0x7f) << 12; - if (svga->gdcreg[0x0b] & CIRRUS_BANKING_DUAL) - svga->extra_banks[1] = (svga->gdcreg[0x0a] & 0x7f) << 12; - else - svga->extra_banks[1] = svga->extra_banks[0] + 0x8000; + if (svga->gdcreg[0x0b] & CIRRUS_BANKING_DUAL) + svga->extra_banks[1] = (svga->gdcreg[0x0a] & 0x7f) << 12; + else + svga->extra_banks[1] = svga->extra_banks[0] + 0x8000; } else { - if ((svga->gdcreg[0x0b] & CIRRUS_BANKING_GRANULARITY_16K) && - (svga->crtc[0x27] >= CIRRUS_ID_CLGD5426) && (svga->crtc[0x27] != CIRRUS_ID_CLGD5424)) - svga->extra_banks[0] = svga->gdcreg[0x09] << 14; - else - svga->extra_banks[0] = svga->gdcreg[0x09] << 12; + if ((svga->gdcreg[0x0b] & CIRRUS_BANKING_GRANULARITY_16K) && (svga->crtc[0x27] >= CIRRUS_ID_CLGD5426) && (svga->crtc[0x27] != CIRRUS_ID_CLGD5424)) + svga->extra_banks[0] = svga->gdcreg[0x09] << 14; + else + svga->extra_banks[0] = svga->gdcreg[0x09] << 12; - if (svga->gdcreg[0x0b] & CIRRUS_BANKING_DUAL) { - if ((svga->gdcreg[0x0b] & CIRRUS_BANKING_GRANULARITY_16K) && - (svga->crtc[0x27] >= CIRRUS_ID_CLGD5426) && (svga->crtc[0x27] != CIRRUS_ID_CLGD5424)) - svga->extra_banks[1] = svga->gdcreg[0x0a] << 14; - else - svga->extra_banks[1] = svga->gdcreg[0x0a] << 12; - } else - svga->extra_banks[1] = svga->extra_banks[0] + 0x8000; + if (svga->gdcreg[0x0b] & CIRRUS_BANKING_DUAL) { + if ((svga->gdcreg[0x0b] & CIRRUS_BANKING_GRANULARITY_16K) && (svga->crtc[0x27] >= CIRRUS_ID_CLGD5426) && (svga->crtc[0x27] != CIRRUS_ID_CLGD5424)) + svga->extra_banks[1] = svga->gdcreg[0x0a] << 14; + else + svga->extra_banks[1] = svga->gdcreg[0x0a] << 12; + } else + svga->extra_banks[1] = svga->extra_banks[0] + 0x8000; } svga->write_bank = svga->read_bank = svga->extra_banks[0]; } - -static void +static void gd543x_recalc_mapping(gd54xx_t *gd54xx) { - svga_t *svga = &gd54xx->svga; - uint32_t base, size; + svga_t *svga = &gd54xx->svga; + uint32_t base; + uint32_t size; - if ((gd54xx->pci && (!(gd54xx->pci_regs[PCI_REG_COMMAND] & PCI_COMMAND_MEM))) || - (gd54xx->mca && (!(gd54xx->pos_regs[2] & 1)))) { - mem_mapping_disable(&svga->mapping); - mem_mapping_disable(&gd54xx->linear_mapping); - mem_mapping_disable(&gd54xx->mmio_mapping); - return; + if (gd54xx->pci && (!(gd54xx->pci_regs[PCI_REG_COMMAND] & PCI_COMMAND_MEM))) { + mem_mapping_disable(&svga->mapping); + mem_mapping_disable(&gd54xx->linear_mapping); + mem_mapping_disable(&gd54xx->mmio_mapping); + return; } - + gd54xx->mmio_vram_overlap = 0; if (!gd54xx_is_5422(svga) || !(svga->seqregs[7] & 0xf0) || !(svga->seqregs[0x07] & 0x01)) { - mem_mapping_disable(&gd54xx->linear_mapping); - mem_mapping_disable(&gd54xx->aperture2_mapping); - 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; - gd54xx->mmio_vram_overlap = 1; - break; - } + mem_mapping_disable(&gd54xx->linear_mapping); + mem_mapping_disable(&gd54xx->aperture2_mapping); + 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; + gd54xx->mmio_vram_overlap = 1; + break; - if ((svga->seqregs[0x17] & CIRRUS_MMIO_ENABLE) && (svga->seqregs[0x07] & 0x01) && - (svga->crtc[0x27] >= CIRRUS_ID_CLGD5429)) { - if (gd54xx->mmio_vram_overlap) { - mem_mapping_disable(&svga->mapping); - mem_mapping_set_addr(&gd54xx->mmio_mapping, 0xb8000, 0x08000); - } else - mem_mapping_set_addr(&gd54xx->mmio_mapping, 0xb8000, 0x00100); - } else - mem_mapping_disable(&gd54xx->mmio_mapping); + default: + break; + } + + if ((svga->seqregs[0x17] & CIRRUS_MMIO_ENABLE) && (svga->seqregs[0x07] & 0x01) && (svga->crtc[0x27] >= CIRRUS_ID_CLGD5429)) { + if (gd54xx->mmio_vram_overlap) { + mem_mapping_disable(&svga->mapping); + mem_mapping_set_addr(&gd54xx->mmio_mapping, 0xb8000, 0x08000); + } else + mem_mapping_set_addr(&gd54xx->mmio_mapping, 0xb8000, 0x00100); + } else + mem_mapping_disable(&gd54xx->mmio_mapping); } else { - if ((svga->crtc[0x27] <= CIRRUS_ID_CLGD5429) || (!gd54xx->pci && !gd54xx->vlb)) { - if (svga->gdcreg[0x0b] & CIRRUS_BANKING_GRANULARITY_16K) { - base = (svga->seqregs[7] & 0xf0) << 16; - size = 1 * 1024 * 1024; - } else { - base = (svga->seqregs[7] & 0xe0) << 16; - size = 2 * 1024 * 1024; - } - } else if (gd54xx->pci) { - base = gd54xx->lfb_base; - /* if (svga->crtc[0x27] == CIRRUS_ID_CLGD5480) - size = 32 * 1024 * 1024; - else */ if (svga->crtc[0x27] >= CIRRUS_ID_CLGD5436) - size = 16 * 1024 * 1024; - else - size = 4 * 1024 * 1024; - } else { /*VLB/ISA/MCA*/ - base = 128*1024*1024; - if (svga->crtc[0x27] >= CIRRUS_ID_CLGD5436) - size = 16 * 1024 * 1024; - else - size = 4 * 1024 * 1024; - } + if ((svga->crtc[0x27] <= CIRRUS_ID_CLGD5429) || (!gd54xx->pci && !gd54xx->vlb)) { + if (svga->gdcreg[0x0b] & CIRRUS_BANKING_GRANULARITY_16K) { + base = (svga->seqregs[7] & 0xf0) << 16; + size = 1 * 1024 * 1024; + } else { + base = (svga->seqregs[7] & 0xe0) << 16; + size = 2 * 1024 * 1024; + } + } else if (gd54xx->pci) { + base = gd54xx->lfb_base; +#if 0 + if (svga->crtc[0x27] == CIRRUS_ID_CLGD5480) + size = 32 * 1024 * 1024; + else +#endif + if (svga->crtc[0x27] >= CIRRUS_ID_CLGD5436) + size = 16 * 1024 * 1024; + else + size = 4 * 1024 * 1024; + } else { /*VLB/ISA/MCA*/ + base = 128 * 1024 * 1024; + if (svga->crtc[0x27] >= CIRRUS_ID_CLGD5436) + size = 16 * 1024 * 1024; + else + size = 4 * 1024 * 1024; + } - mem_mapping_disable(&svga->mapping); - mem_mapping_set_addr(&gd54xx->linear_mapping, base, size); - if ((svga->seqregs[0x17] & CIRRUS_MMIO_ENABLE) && (svga->crtc[0x27] >= CIRRUS_ID_CLGD5429)) { - if (svga->seqregs[0x17] & CIRRUS_MMIO_USE_PCIADDR) - mem_mapping_disable(&gd54xx->mmio_mapping); /* MMIO is handled in the linear read/write functions */ - else - mem_mapping_set_addr(&gd54xx->mmio_mapping, 0xb8000, 0x00100); - } else - mem_mapping_disable(&gd54xx->mmio_mapping); + mem_mapping_disable(&svga->mapping); + mem_mapping_set_addr(&gd54xx->linear_mapping, base, size); + if ((svga->seqregs[0x17] & CIRRUS_MMIO_ENABLE) && (svga->crtc[0x27] >= CIRRUS_ID_CLGD5429)) { + if (svga->seqregs[0x17] & CIRRUS_MMIO_USE_PCIADDR) + mem_mapping_disable(&gd54xx->mmio_mapping); /* MMIO is handled in the linear read/write functions */ + else + mem_mapping_set_addr(&gd54xx->mmio_mapping, 0xb8000, 0x00100); + } else + mem_mapping_disable(&gd54xx->mmio_mapping); - if ((svga->crtc[0x27] >= CIRRUS_ID_CLGD5436) && (gd54xx->blt.status & CIRRUS_BLT_APERTURE2) && - ((gd54xx->blt.mode & (CIRRUS_BLTMODE_COLOREXPAND | CIRRUS_BLTMODE_MEMSYSSRC)) == - (CIRRUS_BLTMODE_COLOREXPAND | CIRRUS_BLTMODE_MEMSYSSRC))) { - if (svga->crtc[0x27] == CIRRUS_ID_CLGD5480) - mem_mapping_set_addr(&gd54xx->aperture2_mapping, gd54xx->lfb_base + (16777216), 16777216); - else - mem_mapping_set_addr(&gd54xx->aperture2_mapping, 0xbc000, 0x04000); - } else - mem_mapping_disable(&gd54xx->aperture2_mapping); + if ((svga->crtc[0x27] >= CIRRUS_ID_CLGD5436) && (gd54xx->blt.status & CIRRUS_BLT_APERTURE2) && ((gd54xx->blt.mode & (CIRRUS_BLTMODE_COLOREXPAND | CIRRUS_BLTMODE_MEMSYSSRC)) == (CIRRUS_BLTMODE_COLOREXPAND | CIRRUS_BLTMODE_MEMSYSSRC))) { + if (svga->crtc[0x27] == CIRRUS_ID_CLGD5480) + mem_mapping_set_addr(&gd54xx->aperture2_mapping, gd54xx->lfb_base + 16777216, 16777216); + else + mem_mapping_set_addr(&gd54xx->aperture2_mapping, 0xbc000, 0x04000); + } else + mem_mapping_disable(&gd54xx->aperture2_mapping); } } - static void gd54xx_recalctimings(svga_t *svga) { - gd54xx_t *gd54xx = (gd54xx_t *)svga->p; - uint8_t clocksel, rdmask; - uint8_t linedbl = svga->dispend * 9 / 10 >= svga->hdisp; + const gd54xx_t *gd54xx = (gd54xx_t *) svga->priv; + uint8_t clocksel; + uint8_t rdmask; + uint8_t linedbl = svga->dispend * 9 / 10 >= svga->hdisp; svga->rowoffset = (svga->crtc[0x13]) | (((int) (uint32_t) (svga->crtc[0x1b] & 0x10)) << 4); svga->interlace = (svga->crtc[0x1a] & 0x01); + if (!(svga->gdcreg[6] & 1) && !(svga->attrregs[0x10] & 1)) { /*Text mode*/ + svga->interlace = 0; + } + svga->map8 = svga->pallook; if (svga->seqregs[7] & CIRRUS_SR7_BPP_SVGA) { - if (linedbl) - svga->render = svga_render_8bpp_lowres; - else { - svga->render = svga_render_8bpp_highres; - if ((svga->dispend == 512) && !svga->interlace && gd54xx_is_5434(svga)) - svga->hdisp <<= 1; - } + if (linedbl) + svga->render = svga_render_8bpp_lowres; + else { + svga->render = svga_render_8bpp_highres; + if ((svga->dispend == 512) && !svga->interlace && gd54xx_is_5434(svga)) + svga->hdisp <<= 1; + } } else if (svga->gdcreg[5] & 0x40) - svga->render = svga_render_8bpp_lowres; + svga->render = svga_render_8bpp_lowres; svga->ma_latch |= ((svga->crtc[0x1b] & 0x01) << 16) | ((svga->crtc[0x1b] & 0xc) << 15); svga->bpp = 8; - if (gd54xx->ramdac.ctrl & 0x80) { - if (gd54xx->ramdac.ctrl & 0x40) { - if ((svga->crtc[0x27] >= CIRRUS_ID_CLGD5428) || (svga->crtc[0x27] == CIRRUS_ID_CLGD5426)) - rdmask = 0xf; - else - rdmask = 0x7; + if (gd54xx->ramdac.ctrl & 0x80) { + if (gd54xx->ramdac.ctrl & 0x40) { + if ((svga->crtc[0x27] >= CIRRUS_ID_CLGD5428) || (svga->crtc[0x27] == CIRRUS_ID_CLGD5426)) + rdmask = 0xf; + else + rdmask = 0x7; - switch (gd54xx->ramdac.ctrl & rdmask) { - case 0: - svga->bpp = 15; - if (linedbl) { - if (gd54xx->ramdac.ctrl & 0x10) - svga->render = svga_render_15bpp_mix_lowres; - else - svga->render = svga_render_15bpp_lowres; - } else { - if (gd54xx->ramdac.ctrl & 0x10) - svga->render = svga_render_15bpp_mix_highres; - else - svga->render = svga_render_15bpp_highres; - } - break; + switch (gd54xx->ramdac.ctrl & rdmask) { + case 0: + svga->bpp = 15; + if (linedbl) { + if (gd54xx->ramdac.ctrl & 0x10) + svga->render = svga_render_15bpp_mix_lowres; + else + svga->render = svga_render_15bpp_lowres; + } else { + if (gd54xx->ramdac.ctrl & 0x10) + svga->render = svga_render_15bpp_mix_highres; + else + svga->render = svga_render_15bpp_highres; + } + break; - case 1: - svga->bpp = 16; - if (linedbl) - svga->render = svga_render_16bpp_lowres; - else - svga->render = svga_render_16bpp_highres; - break; + case 1: + svga->bpp = 16; + if (linedbl) + svga->render = svga_render_16bpp_lowres; + else + svga->render = svga_render_16bpp_highres; + break; - case 5: - if (gd54xx_is_5434(svga) && (svga->seqregs[7] & CIRRUS_SR7_BPP_32)) { - svga->bpp = 32; - if (linedbl) - svga->render = svga_render_32bpp_lowres; - else - svga->render = svga_render_32bpp_highres; - if (svga->crtc[0x27] < CIRRUS_ID_CLGD5436) { - svga->rowoffset *= 2; - } - } else { - svga->bpp = 24; - if (linedbl) - svga->render = svga_render_24bpp_lowres; - else - svga->render = svga_render_24bpp_highres; - } - break; + case 5: + if (gd54xx_is_5434(svga) && (svga->seqregs[7] & CIRRUS_SR7_BPP_32)) { + svga->bpp = 32; + if (linedbl) + svga->render = svga_render_32bpp_lowres; + else + svga->render = svga_render_32bpp_highres; + if (svga->crtc[0x27] < CIRRUS_ID_CLGD5436) { + svga->rowoffset *= 2; + } + } else { + svga->bpp = 24; + if (linedbl) + svga->render = svga_render_24bpp_lowres; + else + svga->render = svga_render_24bpp_highres; + } + break; - case 8: - svga->bpp = 8; - svga->map8 = video_8togs; - if (linedbl) - svga->render = svga_render_8bpp_lowres; - else - svga->render = svga_render_8bpp_highres; - break; + case 8: + svga->bpp = 8; + svga->map8 = video_8togs; + if (linedbl) + svga->render = svga_render_8bpp_lowres; + else + svga->render = svga_render_8bpp_highres; + break; - case 9: - svga->bpp = 8; - svga->map8 = video_8to32; - if (linedbl) - svga->render = svga_render_8bpp_lowres; - else - svga->render = svga_render_8bpp_highres; - break; + case 9: + svga->bpp = 8; + svga->map8 = video_8to32; + if (linedbl) + svga->render = svga_render_8bpp_lowres; + else + svga->render = svga_render_8bpp_highres; + break; - case 0xf: - switch (svga->seqregs[7] & CIRRUS_SR7_BPP_MASK) { - case CIRRUS_SR7_BPP_32: - if (svga->crtc[0x27] >= CIRRUS_ID_CLGD5430) { - svga->bpp = 32; - if (linedbl) - svga->render = svga_render_32bpp_lowres; - else - svga->render = svga_render_32bpp_highres; - svga->rowoffset *= 2; - } - break; + case 0xf: + switch (svga->seqregs[7] & CIRRUS_SR7_BPP_MASK) { + case CIRRUS_SR7_BPP_32: + if (svga->crtc[0x27] >= CIRRUS_ID_CLGD5430) { + svga->bpp = 32; + if (linedbl) + svga->render = svga_render_32bpp_lowres; + else + svga->render = svga_render_32bpp_highres; + svga->rowoffset *= 2; + } + break; - case CIRRUS_SR7_BPP_24: - svga->bpp = 24; - if (linedbl) - svga->render = svga_render_24bpp_lowres; - else - svga->render = svga_render_24bpp_highres; - break; + case CIRRUS_SR7_BPP_24: + svga->bpp = 24; + if (linedbl) + svga->render = svga_render_24bpp_lowres; + else + svga->render = svga_render_24bpp_highres; + break; - case CIRRUS_SR7_BPP_16: - if ((svga->crtc[0x27] >= CIRRUS_ID_CLGD5428) || (svga->crtc[0x27] == CIRRUS_ID_CLGD5426)) { - svga->bpp = 16; - if (linedbl) - svga->render = svga_render_16bpp_lowres; - else - svga->render = svga_render_16bpp_highres; - } - break; + case CIRRUS_SR7_BPP_16: + if ((svga->crtc[0x27] >= CIRRUS_ID_CLGD5428) || (svga->crtc[0x27] == CIRRUS_ID_CLGD5426)) { + svga->bpp = 16; + if (linedbl) + svga->render = svga_render_16bpp_lowres; + else + svga->render = svga_render_16bpp_highres; + } + break; - case CIRRUS_SR7_BPP_16_DOUBLEVCLK: - svga->bpp = 16; - if (linedbl) - svga->render = svga_render_16bpp_lowres; - else - svga->render = svga_render_16bpp_highres; - break; + case CIRRUS_SR7_BPP_16_DOUBLEVCLK: + svga->bpp = 16; + if (linedbl) + svga->render = svga_render_16bpp_lowres; + else + svga->render = svga_render_16bpp_highres; + break; - case CIRRUS_SR7_BPP_8: - svga->bpp = 8; - if (linedbl) - svga->render = svga_render_8bpp_lowres; - else - svga->render = svga_render_8bpp_highres; - break; - } - break; - } - } else { - svga->bpp = 15; - if (linedbl) { - if (gd54xx->ramdac.ctrl & 0x10) - svga->render = svga_render_15bpp_mix_lowres; - else - svga->render = svga_render_15bpp_lowres; - } else { - if (gd54xx->ramdac.ctrl & 0x10) - svga->render = svga_render_15bpp_mix_highres; - else - svga->render = svga_render_15bpp_highres; - } - } + case CIRRUS_SR7_BPP_8: + svga->bpp = 8; + if (linedbl) + svga->render = svga_render_8bpp_lowres; + else + svga->render = svga_render_8bpp_highres; + break; + + default: + break; + } + break; + + default: + break; + } + } else { + svga->bpp = 15; + if (linedbl) { + if (gd54xx->ramdac.ctrl & 0x10) + svga->render = svga_render_15bpp_mix_lowres; + else + svga->render = svga_render_15bpp_lowres; + } else { + if (gd54xx->ramdac.ctrl & 0x10) + svga->render = svga_render_15bpp_mix_highres; + else + svga->render = svga_render_15bpp_highres; + } + } } clocksel = (svga->miscout >> 2) & 3; if (!gd54xx->vclk_n[clocksel] || !gd54xx->vclk_d[clocksel]) - svga->clock = (cpuclock * (float)(1ull << 32)) / ((svga->miscout & 0xc) ? 28322000.0 : 25175000.0); + svga->clock = (cpuclock * (float) (1ULL << 32)) / ((svga->miscout & 0xc) ? 28322000.0 : 25175000.0); else { - int n = gd54xx->vclk_n[clocksel] & 0x7f; - int d = (gd54xx->vclk_d[clocksel] & 0x3e) >> 1; - int m = gd54xx->vclk_d[clocksel] & 0x01 ? 2 : 1; - float freq = (14318184.0 * ((float)n / ((float)d * m))); - if (gd54xx_is_5422(svga)) { - switch (svga->seqregs[7] & (gd54xx_is_5434(svga) ? 0xe : 6)) { - case 2: - freq /= 2.0; - break; - case 4: - if (!gd54xx_is_5434(svga)) - freq /= 3.0; - break; - } - } - svga->clock = (cpuclock * (double)(1ull << 32)) / freq; + int n = gd54xx->vclk_n[clocksel] & 0x7f; + int d = (gd54xx->vclk_d[clocksel] & 0x3e) >> 1; + uint8_t m = gd54xx->vclk_d[clocksel] & 0x01 ? 2 : 1; + float freq = (14318184.0F * ((float) n / ((float) d * m))); + if (gd54xx_is_5422(svga)) { + switch (svga->seqregs[7] & (gd54xx_is_5434(svga) ? 0xe : 6)) { + case 2: + freq /= 2.0F; + break; + case 4: + if (!gd54xx_is_5434(svga)) + freq /= 3.0F; + break; + + default: + break; + } + } + svga->clock = (cpuclock * (double) (1ULL << 32)) / freq; } svga->vram_display_mask = (svga->crtc[0x1b] & 2) ? gd54xx->vram_mask : 0x3ffff; + + if (!(svga->gdcreg[6] & 1) && !(svga->attrregs[0x10] & 1)) { /*Text mode*/ + if (svga->seqregs[1] & 8) { + svga->render = svga_render_text_40; + } else + svga->render = svga_render_text_80; + } } - -static -void gd54xx_hwcursor_draw(svga_t *svga, int displine) +static void +gd54xx_hwcursor_draw(svga_t *svga, int displine) { - gd54xx_t *gd54xx = (gd54xx_t *)svga->p; - int x, xx, comb, b0, b1; - uint8_t dat[2]; - int offset = svga->hwcursor_latch.x - svga->hwcursor_latch.xoff; - int pitch = (svga->hwcursor.xsize == 64) ? 16 : 4; - uint32_t bgcol = gd54xx->extpallook[0x00]; - uint32_t fgcol = gd54xx->extpallook[0x0f]; - uint8_t linedbl = svga->dispend * 9 / 10 >= svga->hdisp; + const gd54xx_t *gd54xx = (gd54xx_t *) svga->priv; + int comb; + int b0; + int b1; + uint8_t dat[2]; + int offset = svga->hwcursor_latch.x - svga->hwcursor_latch.xoff; + int pitch = (svga->hwcursor.cur_xsize == 64) ? 16 : 4; + uint32_t bgcol = gd54xx->extpallook[0x00]; + uint32_t fgcol = gd54xx->extpallook[0x0f]; + uint8_t linedbl = svga->dispend * 9 / 10 >= svga->hdisp; offset <<= linedbl; if (svga->interlace && svga->hwcursor_oddeven) - svga->hwcursor_latch.addr += pitch; + svga->hwcursor_latch.addr += pitch; - for (x = 0; x < svga->hwcursor.xsize; x += 8) { - dat[0] = svga->vram[svga->hwcursor_latch.addr & svga->vram_display_mask]; - if (svga->hwcursor.xsize == 64) - dat[1] = svga->vram[(svga->hwcursor_latch.addr + 0x08) & svga->vram_display_mask]; - else - dat[1] = svga->vram[(svga->hwcursor_latch.addr + 0x80) & svga->vram_display_mask]; - for (xx = 0; xx < 8; xx++) { - b0 = (dat[0] >> (7 - xx)) & 1; - b1 = (dat[1] >> (7 - xx)) & 1; - comb = (b1 | (b0 << 1)); - if (offset >= svga->hwcursor_latch.x) { - switch(comb) { - case 0: - /* The original screen pixel is shown (invisible cursor) */ - break; - case 1: - /* The pixel is shown in the cursor background color */ - ((uint32_t *)buffer32->line[displine])[offset + svga->x_add] = bgcol; - break; - case 2: - /* The pixel is shown as the inverse of the original screen pixel - (XOR cursor) */ - ((uint32_t *)buffer32->line[displine])[offset + svga->x_add] ^= 0xffffff; - break; - case 3: - /* The pixel is shown in the cursor foreground color */ - ((uint32_t *)buffer32->line[displine])[offset + svga->x_add] = fgcol; - break; - } - } - - offset++; - } - svga->hwcursor_latch.addr++; + for (int x = 0; x < svga->hwcursor.cur_xsize; x += 8) { + dat[0] = svga->vram[svga->hwcursor_latch.addr & svga->vram_display_mask]; + if (svga->hwcursor.cur_xsize == 64) + dat[1] = svga->vram[(svga->hwcursor_latch.addr + 0x08) & svga->vram_display_mask]; + else + dat[1] = svga->vram[(svga->hwcursor_latch.addr + 0x80) & svga->vram_display_mask]; + for (uint8_t xx = 0; xx < 8; xx++) { + b0 = (dat[0] >> (7 - xx)) & 1; + b1 = (dat[1] >> (7 - xx)) & 1; + comb = (b1 | (b0 << 1)); + if (offset >= svga->hwcursor_latch.x) { + switch (comb) { + case 0: + /* The original screen pixel is shown (invisible cursor) */ + break; + case 1: + /* The pixel is shown in the cursor background color */ + (svga->monitor->target_buffer->line[displine])[offset + svga->x_add] = bgcol; + break; + case 2: + /* The pixel is shown as the inverse of the original screen pixel + (XOR cursor) */ + (svga->monitor->target_buffer->line[displine])[offset + svga->x_add] ^= 0xffffff; + break; + case 3: + /* The pixel is shown in the cursor foreground color */ + (svga->monitor->target_buffer->line[displine])[offset + svga->x_add] = fgcol; + break; + + default: + break; + } + } + + offset++; + } + svga->hwcursor_latch.addr++; } - if (svga->hwcursor.xsize == 64) - svga->hwcursor_latch.addr += 8; + if (svga->hwcursor.cur_xsize == 64) + svga->hwcursor_latch.addr += 8; if (svga->interlace && !svga->hwcursor_oddeven) - svga->hwcursor_latch.addr += pitch; + svga->hwcursor_latch.addr += pitch; } - static void -gd54xx_rop(gd54xx_t *gd54xx, uint8_t *res, uint8_t *dst, const uint8_t *src) { +gd54xx_rop(gd54xx_t *gd54xx, uint8_t *res, uint8_t *dst, const uint8_t *src) +{ switch (gd54xx->blt.rop) { - case 0x00: *res = 0x00; break; - case 0x05: *res = *src & *dst; break; - case 0x06: *res = *dst; break; - case 0x09: *res = *src & ~*dst; break; - case 0x0b: *res = ~*dst; break; - case 0x0d: *res = *src; break; - case 0x0e: *res = 0xff; break; - case 0x50: *res = ~*src & *dst; break; - case 0x59: *res = *src ^ *dst; break; - case 0x6d: *res = *src | *dst; break; - case 0x90: *res = ~(*src | *dst); break; - case 0x95: *res = ~(*src ^ *dst); break; - case 0xad: *res = *src | ~*dst; break; - case 0xd0: *res = ~*src; break; - case 0xd6: *res = ~*src | *dst; break; - case 0xda: *res = ~(*src & *dst); break; + case 0x00: + *res = 0x00; + break; + case 0x05: + *res = *src & *dst; + break; + case 0x06: + *res = *dst; + break; + case 0x09: + *res = *src & ~*dst; + break; + case 0x0b: + *res = ~*dst; + break; + case 0x0d: + *res = *src; + break; + case 0x0e: + *res = 0xff; + break; + case 0x50: + *res = ~*src & *dst; + break; + case 0x59: + *res = *src ^ *dst; + break; + case 0x6d: + *res = *src | *dst; + break; + case 0x90: + *res = ~(*src | *dst); + break; + case 0x95: + *res = ~(*src ^ *dst); + break; + case 0xad: + *res = *src | ~*dst; + break; + case 0xd0: + *res = ~*src; + break; + case 0xd6: + *res = ~*src | *dst; + break; + case 0xda: + *res = ~(*src & *dst); + break; + + default: + break; } } - static uint8_t gd54xx_mem_sys_dest_read(gd54xx_t *gd54xx) { uint8_t ret = 0xff; if (gd54xx->blt.msd_buf_cnt != 0) { - ret = gd54xx->blt.msd_buf[gd54xx->blt.msd_buf_pos++]; - gd54xx->blt.msd_buf_cnt--; + ret = gd54xx->blt.msd_buf[gd54xx->blt.msd_buf_pos++]; + gd54xx->blt.msd_buf_cnt--; - if (gd54xx->blt.msd_buf_cnt == 0) { - if (gd54xx->countminusone == 1) { - gd54xx->blt.msd_buf_pos = 0; - if ((gd54xx->blt.mode & CIRRUS_BLTMODE_COLOREXPAND) && - !(gd54xx->blt.modeext & CIRRUS_BLTMODEEXT_DWORDGRANULARITY)) - gd54xx_start_blit(0xff, 8, gd54xx, &gd54xx->svga); - else - gd54xx_start_blit(0xffffffff, 32, gd54xx, &gd54xx->svga); - } else - gd54xx_reset_blit(gd54xx); /* End of blit, do no more. */ - } + if (gd54xx->blt.msd_buf_cnt == 0) { + if (gd54xx->countminusone == 1) { + gd54xx->blt.msd_buf_pos = 0; + if ((gd54xx->blt.mode & CIRRUS_BLTMODE_COLOREXPAND) && !(gd54xx->blt.modeext & CIRRUS_BLTMODEEXT_DWORDGRANULARITY)) + gd54xx_start_blit(0xff, 8, gd54xx, &gd54xx->svga); + else + gd54xx_start_blit(0xffffffff, 32, gd54xx, &gd54xx->svga); + } else + gd54xx_reset_blit(gd54xx); /* End of blit, do no more. */ + } } return ret; } - static void gd54xx_mem_sys_src_write(gd54xx_t *gd54xx, uint8_t val) { - int i; - gd54xx->blt.sys_src32 &= ~(0xff << (gd54xx->blt.sys_cnt << 3)); gd54xx->blt.sys_src32 |= (val << (gd54xx->blt.sys_cnt << 3)); gd54xx->blt.sys_cnt = (gd54xx->blt.sys_cnt + 1) & 3; if (gd54xx->blt.sys_cnt == 0) { - if ((gd54xx->blt.mode & CIRRUS_BLTMODE_COLOREXPAND) && - !(gd54xx->blt.modeext & CIRRUS_BLTMODEEXT_DWORDGRANULARITY)) { - for (i = 0; i < 32; i += 8) - gd54xx_start_blit((gd54xx->blt.sys_src32 >> i) & 0xff, 8, gd54xx, &gd54xx->svga); - } else - gd54xx_start_blit(gd54xx->blt.sys_src32, 32, gd54xx, &gd54xx->svga); + if ((gd54xx->blt.mode & CIRRUS_BLTMODE_COLOREXPAND) && !(gd54xx->blt.modeext & CIRRUS_BLTMODEEXT_DWORDGRANULARITY)) { + for (uint8_t i = 0; i < 32; i += 8) + gd54xx_start_blit((gd54xx->blt.sys_src32 >> i) & 0xff, 8, gd54xx, &gd54xx->svga); + } else + gd54xx_start_blit(gd54xx->blt.sys_src32, 32, gd54xx, &gd54xx->svga); } } - static void -gd54xx_write(uint32_t addr, uint8_t val, void *p) +gd54xx_write(uint32_t addr, uint8_t val, void *priv) { - gd54xx_t *gd54xx = (gd54xx_t *)p; - svga_t *svga = &gd54xx->svga; + gd54xx_t *gd54xx = (gd54xx_t *) priv; + svga_t *svga = &gd54xx->svga; - if (gd54xx->countminusone && !gd54xx->blt.ms_is_dest && - !(gd54xx->blt.status & CIRRUS_BLT_PAUSED)) { - gd54xx_mem_sys_src_write(gd54xx, val); - return; + if (gd54xx->countminusone && !gd54xx->blt.ms_is_dest && !(gd54xx->blt.status & CIRRUS_BLT_PAUSED)) { + gd54xx_mem_sys_src_write(gd54xx, val); + return; } if ((svga->seqregs[0x07] & 0x01) == 0) { - svga_write(addr, val, svga); - return; + svga_write(addr, val, svga); + return; } addr = (addr & 0x7fff) + svga->extra_banks[(addr >> 15) & 1]; @@ -1988,127 +2118,123 @@ gd54xx_write(uint32_t addr, uint8_t val, void *p) svga_write_linear(addr, val, svga); } - -static void -gd54xx_writew(uint32_t addr, uint16_t val, void *p) -{ - gd54xx_t *gd54xx = (gd54xx_t *)p; - svga_t *svga = &gd54xx->svga; - - if (gd54xx->countminusone && !gd54xx->blt.ms_is_dest && - !(gd54xx->blt.status & CIRRUS_BLT_PAUSED)) { - gd54xx_write(addr, val, gd54xx); - gd54xx_write(addr + 1, val >> 8, gd54xx); - return; - } - - if ((svga->seqregs[0x07] & 0x01) == 0) { - svga_writew(addr, val, svga); - return; - } - - addr = (addr & 0x7fff) + svga->extra_banks[(addr >> 15) & 1]; - - if (svga->writemode < 4) - svga_writew_linear(addr, val, svga); - else { - svga_write_linear(addr, val, svga); - svga_write_linear(addr + 1, val >> 8, svga); - } -} - - static void -gd54xx_writel(uint32_t addr, uint32_t val, void *p) +gd54xx_writew(uint32_t addr, uint16_t val, void *priv) { - gd54xx_t *gd54xx = (gd54xx_t *)p; - svga_t *svga = &gd54xx->svga; + gd54xx_t *gd54xx = (gd54xx_t *) priv; + svga_t *svga = &gd54xx->svga; - if (gd54xx->countminusone && !gd54xx->blt.ms_is_dest && - !(gd54xx->blt.status & CIRRUS_BLT_PAUSED)) { - gd54xx_write(addr, val, gd54xx); - gd54xx_write(addr + 1, val >> 8, gd54xx); - gd54xx_write(addr + 2, val >> 16, gd54xx); - gd54xx_write(addr + 3, val >> 24, gd54xx); - return; + if (gd54xx->countminusone && !gd54xx->blt.ms_is_dest && !(gd54xx->blt.status & CIRRUS_BLT_PAUSED)) { + gd54xx_write(addr, val, gd54xx); + gd54xx_write(addr + 1, val >> 8, gd54xx); + return; } if ((svga->seqregs[0x07] & 0x01) == 0) { - svga_writel(addr, val, svga); - return; + svga_writew(addr, val, svga); + return; } addr = (addr & 0x7fff) + svga->extra_banks[(addr >> 15) & 1]; if (svga->writemode < 4) - svga_writel_linear(addr, val, svga); + svga_writew_linear(addr, val, svga); else { - svga_write_linear(addr, val, svga); - svga_write_linear(addr+1, val >> 8, svga); - svga_write_linear(addr+2, val >> 16, svga); - svga_write_linear(addr+3, val >> 24, svga); + svga_write_linear(addr, val, svga); + svga_write_linear(addr + 1, val >> 8, svga); } } +static void +gd54xx_writel(uint32_t addr, uint32_t val, void *priv) +{ + gd54xx_t *gd54xx = (gd54xx_t *) priv; + svga_t *svga = &gd54xx->svga; + + if (gd54xx->countminusone && !gd54xx->blt.ms_is_dest && !(gd54xx->blt.status & CIRRUS_BLT_PAUSED)) { + gd54xx_write(addr, val, gd54xx); + gd54xx_write(addr + 1, val >> 8, gd54xx); + gd54xx_write(addr + 2, val >> 16, gd54xx); + gd54xx_write(addr + 3, val >> 24, gd54xx); + return; + } + + if ((svga->seqregs[0x07] & 0x01) == 0) { + svga_writel(addr, val, svga); + return; + } + + addr = (addr & 0x7fff) + svga->extra_banks[(addr >> 15) & 1]; + + if (svga->writemode < 4) + svga_writel_linear(addr, val, svga); + else { + svga_write_linear(addr, val, svga); + svga_write_linear(addr + 1, val >> 8, svga); + svga_write_linear(addr + 2, val >> 16, svga); + svga_write_linear(addr + 3, val >> 24, svga); + } +} /* This adds write modes 4 and 5 to SVGA. */ static void gd54xx_write_modes45(svga_t *svga, uint8_t val, uint32_t addr) { - uint32_t i, j; + uint32_t i; + uint32_t j; switch (svga->writemode) { - case 4: - if (svga->adv_flags & FLAG_ADDR_BY16) { - addr &= svga->decode_mask; + case 4: + if (svga->adv_flags & FLAG_ADDR_BY16) { + addr &= svga->decode_mask; - for (i = 0; i < 8; i++) { - if (val & svga->seqregs[2] & (0x80 >> i)) { - svga->vram[addr + (i << 1)] = svga->gdcreg[1]; - svga->vram[addr + (i << 1) + 1] = svga->gdcreg[0x11]; - } - } - } else { - addr <<= 1; - addr &= svga->decode_mask; + for (i = 0; i < 8; i++) { + if (val & svga->seqregs[2] & (0x80 >> i)) { + svga->vram[addr + (i << 1)] = svga->gdcreg[1]; + svga->vram[addr + (i << 1) + 1] = svga->gdcreg[0x11]; + } + } + } else { + addr <<= 1; + addr &= svga->decode_mask; - for (i = 0; i < 8; i++) { - if (val & svga->seqregs[2] & (0x80 >> i)) - svga->vram[addr + i] = svga->gdcreg[1]; - } - } - break; + for (i = 0; i < 8; i++) { + if (val & svga->seqregs[2] & (0x80 >> i)) + svga->vram[addr + i] = svga->gdcreg[1]; + } + } + break; - case 5: - if (svga->adv_flags & FLAG_ADDR_BY16) { - addr &= svga->decode_mask; + case 5: + if (svga->adv_flags & FLAG_ADDR_BY16) { + addr &= svga->decode_mask; - for (i = 0; i < 8; i++) { - j = (0x80 >> i); - if (svga->seqregs[2] & j) { - svga->vram[addr + (i << 1)] = (val & j) ? - svga->gdcreg[1] : svga->gdcreg[0]; - svga->vram[addr + (i << 1) + 1] = (val & j) ? - svga->gdcreg[0x11] : svga->gdcreg[0x10]; - } - } - } else { - addr <<= 1; - addr &= svga->decode_mask; + for (i = 0; i < 8; i++) { + j = (0x80 >> i); + if (svga->seqregs[2] & j) { + svga->vram[addr + (i << 1)] = (val & j) ? svga->gdcreg[1] : svga->gdcreg[0]; + svga->vram[addr + (i << 1) + 1] = (val & j) ? svga->gdcreg[0x11] : svga->gdcreg[0x10]; + } + } + } else { + addr <<= 1; + addr &= svga->decode_mask; - for (i = 0; i < 8; i++) { - j = (0x80 >> i); - if (svga->seqregs[2] & j) - svga->vram[addr + i] = (val & j) ? svga->gdcreg[1] : svga->gdcreg[0]; - } - } - break; + for (i = 0; i < 8; i++) { + j = (0x80 >> i); + if (svga->seqregs[2] & j) + svga->vram[addr + i] = (val & j) ? svga->gdcreg[1] : svga->gdcreg[0]; + } + } + break; + + default: + break; } svga->changedvram[addr >> 12] = changeframecount; } - static uint8_t gd54xx_get_aperture(uint32_t addr) { @@ -2116,1312 +2242,1282 @@ gd54xx_get_aperture(uint32_t addr) return (uint8_t) (ap & 0x03); } - static int gd54xx_aperture2_enabled(gd54xx_t *gd54xx) { - svga_t *svga = &gd54xx->svga; + const svga_t *svga = &gd54xx->svga; if (svga->crtc[0x27] < CIRRUS_ID_CLGD5436) - return 0; + return 0; if (!(gd54xx->blt.mode & CIRRUS_BLTMODE_COLOREXPAND)) - return 0; + return 0; if (!(gd54xx->blt.status & CIRRUS_BLT_APERTURE2)) - return 0; + return 0; return 1; } - static uint8_t -gd54xx_readb_linear(uint32_t addr, void *p) +gd54xx_readb_linear(uint32_t addr, void *priv) { - gd54xx_t *gd54xx = (gd54xx_t *)p; - svga_t *svga = &gd54xx->svga; + gd54xx_t *gd54xx = (gd54xx_t *) priv; + svga_t *svga = &gd54xx->svga; uint8_t ap = gd54xx_get_aperture(addr); - addr &= 0x003fffff; /* 4 MB mask */ + addr &= 0x003fffff; /* 4 MB mask */ if ((svga->seqregs[0x07] & 0x01) == 0) - return svga_read_linear(addr, svga); + return svga_read_linear(addr, svga); if ((addr >= (svga->vram_max - 256)) && (addr < svga->vram_max)) { - if ((svga->seqregs[0x17] & CIRRUS_MMIO_ENABLE) && (svga->seqregs[0x17] & CIRRUS_MMIO_USE_PCIADDR)) - return gd543x_mmio_read(addr & 0x000000ff, gd54xx); + if ((svga->seqregs[0x17] & CIRRUS_MMIO_ENABLE) && (svga->seqregs[0x17] & CIRRUS_MMIO_USE_PCIADDR)) + return gd543x_mmio_read(addr & 0x000000ff, gd54xx); } /* Do mem sys dest reads here if the blitter is neither paused, nor is there a second aperture. */ - if (gd54xx->countminusone && gd54xx->blt.ms_is_dest && - !gd54xx_aperture2_enabled(gd54xx) && !(gd54xx->blt.status & CIRRUS_BLT_PAUSED)) - return gd54xx_mem_sys_dest_read(gd54xx); + if (gd54xx->countminusone && gd54xx->blt.ms_is_dest && !gd54xx_aperture2_enabled(gd54xx) && !(gd54xx->blt.status & CIRRUS_BLT_PAUSED)) + return gd54xx_mem_sys_dest_read(gd54xx); switch (ap) { - case 0: - default: - break; - case 1: - /* 0 -> 1, 1 -> 0, 2 -> 3, 3 -> 2 */ - addr ^= 0x00000001; - break; - case 2: - /* 0 -> 3, 1 -> 2, 2 -> 1, 3 -> 0 */ - addr ^= 0x00000003; - break; - case 3: - return 0xff; + default: + case 0: + break; + case 1: + /* 0 -> 1, 1 -> 0, 2 -> 3, 3 -> 2 */ + addr ^= 0x00000001; + break; + case 2: + /* 0 -> 3, 1 -> 2, 2 -> 1, 3 -> 0 */ + addr ^= 0x00000003; + break; + case 3: + return 0xff; } return svga_read_linear(addr, svga); } - static uint16_t -gd54xx_readw_linear(uint32_t addr, void *p) +gd54xx_readw_linear(uint32_t addr, void *priv) { - gd54xx_t *gd54xx = (gd54xx_t *)p; - svga_t *svga = &gd54xx->svga; + gd54xx_t *gd54xx = (gd54xx_t *) priv; + svga_t *svga = &gd54xx->svga; - uint8_t ap = gd54xx_get_aperture(addr); + uint8_t ap = gd54xx_get_aperture(addr); uint16_t temp; - addr &= 0x003fffff; /* 4 MB mask */ + addr &= 0x003fffff; /* 4 MB mask */ if ((svga->seqregs[0x07] & 0x01) == 0) - return svga_readw_linear(addr, svga); + return svga_readw_linear(addr, svga); if ((addr >= (svga->vram_max - 256)) && (addr < svga->vram_max)) { - if ((svga->seqregs[0x17] & CIRRUS_MMIO_ENABLE) && (svga->seqregs[0x17] & CIRRUS_MMIO_USE_PCIADDR)) { - temp = gd543x_mmio_readw(addr & 0x000000ff, gd54xx); - return temp; - } + if ((svga->seqregs[0x17] & CIRRUS_MMIO_ENABLE) && (svga->seqregs[0x17] & CIRRUS_MMIO_USE_PCIADDR)) { + temp = gd543x_mmio_readw(addr & 0x000000ff, gd54xx); + return temp; + } } /* Do mem sys dest reads here if the blitter is neither paused, nor is there a second aperture. */ - if (gd54xx->countminusone && gd54xx->blt.ms_is_dest && - !gd54xx_aperture2_enabled(gd54xx) && !(gd54xx->blt.status & CIRRUS_BLT_PAUSED)) { - temp = gd54xx_readb_linear(addr, p); - temp |= gd54xx_readb_linear(addr + 1, p) << 8; - return temp; + if (gd54xx->countminusone && gd54xx->blt.ms_is_dest && !gd54xx_aperture2_enabled(gd54xx) && !(gd54xx->blt.status & CIRRUS_BLT_PAUSED)) { + temp = gd54xx_readb_linear(addr, priv); + temp |= gd54xx_readb_linear(addr + 1, priv) << 8; + return temp; } switch (ap) { - case 0: - default: - return svga_readw_linear(addr, svga); - case 2: - /* 0 -> 3, 1 -> 2, 2 -> 1, 3 -> 0 */ - addr ^= 0x00000002; - case 1: - temp = svga_readb_linear(addr + 1, svga); - temp |= (svga_readb_linear(addr, svga) << 8); + default: + case 0: + return svga_readw_linear(addr, svga); + case 2: + /* 0 -> 3, 1 -> 2, 2 -> 1, 3 -> 0 */ + addr ^= 0x00000002; + fallthrough; + case 1: + temp = svga_readb_linear(addr + 1, svga); + temp |= (svga_readb_linear(addr, svga) << 8); - if (svga->fast) - cycles -= video_timing_read_w; + if (svga->fast) + cycles -= svga->monitor->mon_video_timing_read_w; - return temp; - case 3: - return 0xffff; + return temp; + case 3: + return 0xffff; } } - static uint32_t -gd54xx_readl_linear(uint32_t addr, void *p) +gd54xx_readl_linear(uint32_t addr, void *priv) { - gd54xx_t *gd54xx = (gd54xx_t *)p; - svga_t *svga = &gd54xx->svga; + gd54xx_t *gd54xx = (gd54xx_t *) priv; + svga_t *svga = &gd54xx->svga; - uint8_t ap = gd54xx_get_aperture(addr); + uint8_t ap = gd54xx_get_aperture(addr); uint32_t temp; - addr &= 0x003fffff; /* 4 MB mask */ + addr &= 0x003fffff; /* 4 MB mask */ if ((svga->seqregs[0x07] & 0x01) == 0) - return svga_readl_linear(addr, svga); + return svga_readl_linear(addr, svga); if ((addr >= (svga->vram_max - 256)) && (addr < svga->vram_max)) { - if ((svga->seqregs[0x17] & CIRRUS_MMIO_ENABLE) && (svga->seqregs[0x17] & CIRRUS_MMIO_USE_PCIADDR)) { - temp = gd543x_mmio_readl(addr & 0x000000ff, gd54xx); - return temp; - } + if ((svga->seqregs[0x17] & CIRRUS_MMIO_ENABLE) && (svga->seqregs[0x17] & CIRRUS_MMIO_USE_PCIADDR)) { + temp = gd543x_mmio_readl(addr & 0x000000ff, gd54xx); + return temp; + } } /* Do mem sys dest reads here if the blitter is neither paused, nor is there a second aperture. */ - if (gd54xx->countminusone && gd54xx->blt.ms_is_dest && - !gd54xx_aperture2_enabled(gd54xx) && !(gd54xx->blt.status & CIRRUS_BLT_PAUSED)) { - temp = gd54xx_readb_linear(addr, p); - temp |= gd54xx_readb_linear(addr + 1, p) << 8; - temp |= gd54xx_readb_linear(addr + 2, p) << 16; - temp |= gd54xx_readb_linear(addr + 3, p) << 24; - return temp; + if (gd54xx->countminusone && gd54xx->blt.ms_is_dest && !gd54xx_aperture2_enabled(gd54xx) && !(gd54xx->blt.status & CIRRUS_BLT_PAUSED)) { + temp = gd54xx_readb_linear(addr, priv); + temp |= gd54xx_readb_linear(addr + 1, priv) << 8; + temp |= gd54xx_readb_linear(addr + 2, priv) << 16; + temp |= gd54xx_readb_linear(addr + 3, priv) << 24; + return temp; } switch (ap) { - case 0: - default: - return svga_readl_linear(addr, svga); - case 1: - temp = svga_readb_linear(addr + 1, svga); - temp |= (svga_readb_linear(addr, svga) << 8); - temp |= (svga_readb_linear(addr + 3, svga) << 16); - temp |= (svga_readb_linear(addr + 2, svga) << 24); + default: + case 0: + return svga_readl_linear(addr, svga); + case 1: + temp = svga_readb_linear(addr + 1, svga); + temp |= (svga_readb_linear(addr, svga) << 8); + temp |= (svga_readb_linear(addr + 3, svga) << 16); + temp |= (svga_readb_linear(addr + 2, svga) << 24); - if (svga->fast) - cycles -= video_timing_read_l; + if (svga->fast) + cycles -= svga->monitor->mon_video_timing_read_l; - return temp; - case 2: - temp = svga_readb_linear(addr + 3, svga); - temp |= (svga_readb_linear(addr + 2, svga) << 8); - temp |= (svga_readb_linear(addr + 1, svga) << 16); - temp |= (svga_readb_linear(addr, svga) << 24); + return temp; + case 2: + temp = svga_readb_linear(addr + 3, svga); + temp |= (svga_readb_linear(addr + 2, svga) << 8); + temp |= (svga_readb_linear(addr + 1, svga) << 16); + temp |= (svga_readb_linear(addr, svga) << 24); - if (svga->fast) - cycles -= video_timing_read_l; + if (svga->fast) + cycles -= svga->monitor->mon_video_timing_read_l; - return temp; - case 3: - return 0xffffffff; + return temp; + case 3: + return 0xffffffff; } } - static uint8_t -gd5436_aperture2_readb(uint32_t addr, void *p) +gd5436_aperture2_readb(UNUSED(uint32_t addr), void *priv) { - gd54xx_t *gd54xx = (gd54xx_t *)p; + gd54xx_t *gd54xx = (gd54xx_t *) priv; - if (gd54xx->countminusone && gd54xx->blt.ms_is_dest && - gd54xx_aperture2_enabled(gd54xx) && !(gd54xx->blt.status & CIRRUS_BLT_PAUSED)) - return gd54xx_mem_sys_dest_read(gd54xx); + if (gd54xx->countminusone && gd54xx->blt.ms_is_dest && gd54xx_aperture2_enabled(gd54xx) && !(gd54xx->blt.status & CIRRUS_BLT_PAUSED)) + return gd54xx_mem_sys_dest_read(gd54xx); return 0xff; } - static uint16_t -gd5436_aperture2_readw(uint32_t addr, void *p) +gd5436_aperture2_readw(uint32_t addr, void *priv) { - gd54xx_t *gd54xx = (gd54xx_t *)p; - uint16_t ret = 0xffff; + gd54xx_t *gd54xx = (gd54xx_t *) priv; + uint16_t ret = 0xffff; - if (gd54xx->countminusone && gd54xx->blt.ms_is_dest && - gd54xx_aperture2_enabled(gd54xx) && !(gd54xx->blt.status & CIRRUS_BLT_PAUSED)) { - ret = gd5436_aperture2_readb(addr, p); - ret |= gd5436_aperture2_readb(addr + 1, p) << 8; - return ret; + if (gd54xx->countminusone && gd54xx->blt.ms_is_dest && gd54xx_aperture2_enabled(gd54xx) && !(gd54xx->blt.status & CIRRUS_BLT_PAUSED)) { + ret = gd5436_aperture2_readb(addr, priv); + ret |= gd5436_aperture2_readb(addr + 1, priv) << 8; + return ret; } return ret; } - static uint32_t -gd5436_aperture2_readl(uint32_t addr, void *p) +gd5436_aperture2_readl(uint32_t addr, void *priv) { - gd54xx_t *gd54xx = (gd54xx_t *)p; - uint32_t ret = 0xffffffff; + gd54xx_t *gd54xx = (gd54xx_t *) priv; + uint32_t ret = 0xffffffff; - if (gd54xx->countminusone && gd54xx->blt.ms_is_dest && - gd54xx_aperture2_enabled(gd54xx) && !(gd54xx->blt.status & CIRRUS_BLT_PAUSED)) { - ret = gd5436_aperture2_readb(addr, p); - ret |= gd5436_aperture2_readb(addr + 1, p) << 8; - ret |= gd5436_aperture2_readb(addr + 2, p) << 16; - ret |= gd5436_aperture2_readb(addr + 3, p) << 24; - return ret; + if (gd54xx->countminusone && gd54xx->blt.ms_is_dest && gd54xx_aperture2_enabled(gd54xx) && !(gd54xx->blt.status & CIRRUS_BLT_PAUSED)) { + ret = gd5436_aperture2_readb(addr, priv); + ret |= gd5436_aperture2_readb(addr + 1, priv) << 8; + ret |= gd5436_aperture2_readb(addr + 2, priv) << 16; + ret |= gd5436_aperture2_readb(addr + 3, priv) << 24; + return ret; } return ret; } - static void -gd5436_aperture2_writeb(uint32_t addr, uint8_t val, void *p) +gd5436_aperture2_writeb(UNUSED(uint32_t addr), uint8_t val, void *priv) { - gd54xx_t *gd54xx = (gd54xx_t *)p; + gd54xx_t *gd54xx = (gd54xx_t *) priv; if (gd54xx->countminusone && !gd54xx->blt.ms_is_dest - && gd54xx_aperture2_enabled(gd54xx) && !(gd54xx->blt.status & CIRRUS_BLT_PAUSED)) - gd54xx_mem_sys_src_write(gd54xx, val); + && gd54xx_aperture2_enabled(gd54xx) && !(gd54xx->blt.status & CIRRUS_BLT_PAUSED)) + gd54xx_mem_sys_src_write(gd54xx, val); } - static void -gd5436_aperture2_writew(uint32_t addr, uint16_t val, void *p) +gd5436_aperture2_writew(uint32_t addr, uint16_t val, void *priv) { - gd54xx_t *gd54xx = (gd54xx_t *)p; + gd54xx_t *gd54xx = (gd54xx_t *) priv; if (gd54xx->countminusone && !gd54xx->blt.ms_is_dest - && gd54xx_aperture2_enabled(gd54xx) && !(gd54xx->blt.status & CIRRUS_BLT_PAUSED)) { - gd5436_aperture2_writeb(addr, val, gd54xx); - gd5436_aperture2_writeb(addr + 1, val >> 8, gd54xx); + && gd54xx_aperture2_enabled(gd54xx) && !(gd54xx->blt.status & CIRRUS_BLT_PAUSED)) { + gd5436_aperture2_writeb(addr, val, gd54xx); + gd5436_aperture2_writeb(addr + 1, val >> 8, gd54xx); } } - static void -gd5436_aperture2_writel(uint32_t addr, uint32_t val, void *p) +gd5436_aperture2_writel(uint32_t addr, uint32_t val, void *priv) { - gd54xx_t *gd54xx = (gd54xx_t *)p; + gd54xx_t *gd54xx = (gd54xx_t *) priv; if (gd54xx->countminusone && !gd54xx->blt.ms_is_dest - && gd54xx_aperture2_enabled(gd54xx) && !(gd54xx->blt.status & CIRRUS_BLT_PAUSED)) { - gd5436_aperture2_writeb(addr, val, gd54xx); - gd5436_aperture2_writeb(addr + 1, val >> 8, gd54xx); - gd5436_aperture2_writeb(addr + 2, val >> 16, gd54xx); - gd5436_aperture2_writeb(addr + 3, val >> 24, gd54xx); + && gd54xx_aperture2_enabled(gd54xx) && !(gd54xx->blt.status & CIRRUS_BLT_PAUSED)) { + gd5436_aperture2_writeb(addr, val, gd54xx); + gd5436_aperture2_writeb(addr + 1, val >> 8, gd54xx); + gd5436_aperture2_writeb(addr + 2, val >> 16, gd54xx); + gd5436_aperture2_writeb(addr + 3, val >> 24, gd54xx); } } - static void -gd54xx_writeb_linear(uint32_t addr, uint8_t val, void *p) +gd54xx_writeb_linear(uint32_t addr, uint8_t val, void *priv) { - gd54xx_t *gd54xx = (gd54xx_t *)p; - svga_t *svga = &gd54xx->svga; + gd54xx_t *gd54xx = (gd54xx_t *) priv; + svga_t *svga = &gd54xx->svga; uint8_t ap = gd54xx_get_aperture(addr); if ((svga->seqregs[0x07] & 0x01) == 0) { - svga_write_linear(addr, val, svga); - return; + svga_write_linear(addr, val, svga); + return; } - addr &= 0x003fffff; /* 4 MB mask */ + addr &= 0x003fffff; /* 4 MB mask */ if ((addr >= (svga->vram_max - 256)) && (addr < svga->vram_max)) { - if ((svga->seqregs[0x17] & CIRRUS_MMIO_ENABLE) && (svga->seqregs[0x17] & CIRRUS_MMIO_USE_PCIADDR)) { - gd543x_mmio_write(addr & 0x000000ff, val, gd54xx); - return; - } + if ((svga->seqregs[0x17] & CIRRUS_MMIO_ENABLE) && (svga->seqregs[0x17] & CIRRUS_MMIO_USE_PCIADDR)) { + gd543x_mmio_write(addr & 0x000000ff, val, gd54xx); + return; + } } /* Do mem sys src writes here if the blitter is neither paused, nor is there a second aperture. */ - if (gd54xx->countminusone && !gd54xx->blt.ms_is_dest && - !gd54xx_aperture2_enabled(gd54xx) && !(gd54xx->blt.status & CIRRUS_BLT_PAUSED)) { - gd54xx_mem_sys_src_write(gd54xx, val); - return; + if (gd54xx->countminusone && !gd54xx->blt.ms_is_dest && !gd54xx_aperture2_enabled(gd54xx) && !(gd54xx->blt.status & CIRRUS_BLT_PAUSED)) { + gd54xx_mem_sys_src_write(gd54xx, val); + return; } switch (ap) { - case 0: - default: - break; - case 1: - /* 0 -> 1, 1 -> 0, 2 -> 3, 3 -> 2 */ - addr ^= 0x00000001; - break; - case 2: - /* 0 -> 3, 1 -> 2, 2 -> 1, 3 -> 0 */ - addr ^= 0x00000003; - break; - case 3: - return; + default: + case 0: + break; + case 1: + /* 0 -> 1, 1 -> 0, 2 -> 3, 3 -> 2 */ + addr ^= 0x00000001; + break; + case 2: + /* 0 -> 3, 1 -> 2, 2 -> 1, 3 -> 0 */ + addr ^= 0x00000003; + break; + case 3: + return; } svga_write_linear(addr, val, svga); } - -static void -gd54xx_writew_linear(uint32_t addr, uint16_t val, void *p) +static void +gd54xx_writew_linear(uint32_t addr, uint16_t val, void *priv) { - gd54xx_t *gd54xx = (gd54xx_t *)p; - svga_t *svga = &gd54xx->svga; + gd54xx_t *gd54xx = (gd54xx_t *) priv; + svga_t *svga = &gd54xx->svga; uint8_t ap = gd54xx_get_aperture(addr); if ((svga->seqregs[0x07] & 0x01) == 0) { - svga_writew_linear(addr, val, svga); - return; + svga_writew_linear(addr, val, svga); + return; } - addr &= 0x003fffff; /* 4 MB mask */ + addr &= 0x003fffff; /* 4 MB mask */ if ((addr >= (svga->vram_max - 256)) && (addr < svga->vram_max)) { - if ((svga->seqregs[0x17] & CIRRUS_MMIO_ENABLE) && (svga->seqregs[0x17] & CIRRUS_MMIO_USE_PCIADDR)) { - gd543x_mmio_writew(addr & 0x000000ff, val, gd54xx); - return; - } + if ((svga->seqregs[0x17] & CIRRUS_MMIO_ENABLE) && (svga->seqregs[0x17] & CIRRUS_MMIO_USE_PCIADDR)) { + gd543x_mmio_writew(addr & 0x000000ff, val, gd54xx); + return; + } } /* Do mem sys src writes here if the blitter is neither paused, nor is there a second aperture. */ - if (gd54xx->countminusone && !gd54xx->blt.ms_is_dest && - !gd54xx_aperture2_enabled(gd54xx) && !(gd54xx->blt.status & CIRRUS_BLT_PAUSED)) { - gd54xx_writeb_linear(addr, val, gd54xx); - gd54xx_writeb_linear(addr + 1, val >> 8, gd54xx); - return; + if (gd54xx->countminusone && !gd54xx->blt.ms_is_dest && !gd54xx_aperture2_enabled(gd54xx) && !(gd54xx->blt.status & CIRRUS_BLT_PAUSED)) { + gd54xx_writeb_linear(addr, val, gd54xx); + gd54xx_writeb_linear(addr + 1, val >> 8, gd54xx); + return; } if (svga->writemode < 4) { - switch(ap) { - case 0: - default: - svga_writew_linear(addr, val, svga); - return; - case 2: - addr ^= 0x00000002; - case 1: - svga_writeb_linear(addr + 1, val & 0xff, svga); - svga_writeb_linear(addr, val >> 8, svga); + switch (ap) { + default: + case 0: + svga_writew_linear(addr, val, svga); + return; + case 2: + addr ^= 0x00000002; + case 1: + svga_writeb_linear(addr + 1, val & 0xff, svga); + svga_writeb_linear(addr, val >> 8, svga); - if (svga->fast) - cycles -= video_timing_write_w; - case 3: - return; - } + if (svga->fast) + cycles -= svga->monitor->mon_video_timing_write_w; + return; + case 3: + return; + } } else { - switch(ap) { - case 0: - default: - svga_write_linear(addr, val & 0xff, svga); - svga_write_linear(addr + 1, val >> 8, svga); - return; - case 2: - addr ^= 0x00000002; - case 1: - svga_write_linear(addr + 1, val & 0xff, svga); - svga_write_linear(addr, val >> 8, svga); - case 3: - return; - } + switch (ap) { + default: + case 0: + svga_write_linear(addr, val & 0xff, svga); + svga_write_linear(addr + 1, val >> 8, svga); + return; + case 2: + addr ^= 0x00000002; + fallthrough; + case 1: + svga_write_linear(addr + 1, val & 0xff, svga); + svga_write_linear(addr, val >> 8, svga); + return; + case 3: + return; + } } } - -static void -gd54xx_writel_linear(uint32_t addr, uint32_t val, void *p) +static void +gd54xx_writel_linear(uint32_t addr, uint32_t val, void *priv) { - gd54xx_t *gd54xx = (gd54xx_t *)p; - svga_t *svga = &gd54xx->svga; + gd54xx_t *gd54xx = (gd54xx_t *) priv; + svga_t *svga = &gd54xx->svga; uint8_t ap = gd54xx_get_aperture(addr); if ((svga->seqregs[0x07] & 0x01) == 0) { - svga_writel_linear(addr, val, svga); - return; + svga_writel_linear(addr, val, svga); + return; } - addr &= 0x003fffff; /* 4 MB mask */ + addr &= 0x003fffff; /* 4 MB mask */ if ((addr >= (svga->vram_max - 256)) && (addr < svga->vram_max)) { - if ((svga->seqregs[0x17] & CIRRUS_MMIO_ENABLE) && (svga->seqregs[0x17] & CIRRUS_MMIO_USE_PCIADDR)) { - gd543x_mmio_writel(addr & 0x000000ff, val, gd54xx); - return; - } + if ((svga->seqregs[0x17] & CIRRUS_MMIO_ENABLE) && (svga->seqregs[0x17] & CIRRUS_MMIO_USE_PCIADDR)) { + gd543x_mmio_writel(addr & 0x000000ff, val, gd54xx); + return; + } } /* Do mem sys src writes here if the blitter is neither paused, nor is there a second aperture. */ - if (gd54xx->countminusone && !gd54xx->blt.ms_is_dest && - !gd54xx_aperture2_enabled(gd54xx) && !(gd54xx->blt.status & CIRRUS_BLT_PAUSED)) { - gd54xx_writeb_linear(addr, val, gd54xx); - gd54xx_writeb_linear(addr + 1, val >> 8, gd54xx); - gd54xx_writeb_linear(addr + 2, val >> 16, gd54xx); - gd54xx_writeb_linear(addr + 3, val >> 24, gd54xx); - return; + if (gd54xx->countminusone && !gd54xx->blt.ms_is_dest && !gd54xx_aperture2_enabled(gd54xx) && !(gd54xx->blt.status & CIRRUS_BLT_PAUSED)) { + gd54xx_writeb_linear(addr, val, gd54xx); + gd54xx_writeb_linear(addr + 1, val >> 8, gd54xx); + gd54xx_writeb_linear(addr + 2, val >> 16, gd54xx); + gd54xx_writeb_linear(addr + 3, val >> 24, gd54xx); + return; } if (svga->writemode < 4) { - switch(ap) { - case 0: - default: - svga_writel_linear(addr, val, svga); - return; - case 1: - svga_writeb_linear(addr + 1, val & 0xff, svga); - svga_writeb_linear(addr, val >> 8, svga); - svga_writeb_linear(addr + 3, val >> 16, svga); - svga_writeb_linear(addr + 2, val >> 24, svga); - return; - case 2: - svga_writeb_linear(addr + 3, val & 0xff, svga); - svga_writeb_linear(addr + 2, val >> 8, svga); - svga_writeb_linear(addr + 1, val >> 16, svga); - svga_writeb_linear(addr, val >> 24, svga); - case 3: - return; - } + switch (ap) { + default: + case 0: + svga_writel_linear(addr, val, svga); + return; + case 1: + svga_writeb_linear(addr + 1, val & 0xff, svga); + svga_writeb_linear(addr, val >> 8, svga); + svga_writeb_linear(addr + 3, val >> 16, svga); + svga_writeb_linear(addr + 2, val >> 24, svga); + return; + case 2: + svga_writeb_linear(addr + 3, val & 0xff, svga); + svga_writeb_linear(addr + 2, val >> 8, svga); + svga_writeb_linear(addr + 1, val >> 16, svga); + svga_writeb_linear(addr, val >> 24, svga); + return; + case 3: + return; + } } else { - switch(ap) { - case 0: - default: - svga_write_linear(addr, val & 0xff, svga); - svga_write_linear(addr+1, val >> 8, svga); - svga_write_linear(addr+2, val >> 16, svga); - svga_write_linear(addr+3, val >> 24, svga); - return; - case 1: - svga_write_linear(addr + 1, val & 0xff, svga); - svga_write_linear(addr, val >> 8, svga); - svga_write_linear(addr + 3, val >> 16, svga); - svga_write_linear(addr + 2, val >> 24, svga); - return; - case 2: - svga_write_linear(addr + 3, val & 0xff, svga); - svga_write_linear(addr + 2, val >> 8, svga); - svga_write_linear(addr + 1, val >> 16, svga); - svga_write_linear(addr, val >> 24, svga); - case 3: - return; - } + switch (ap) { + default: + case 0: + svga_write_linear(addr, val & 0xff, svga); + svga_write_linear(addr + 1, val >> 8, svga); + svga_write_linear(addr + 2, val >> 16, svga); + svga_write_linear(addr + 3, val >> 24, svga); + return; + case 1: + svga_write_linear(addr + 1, val & 0xff, svga); + svga_write_linear(addr, val >> 8, svga); + svga_write_linear(addr + 3, val >> 16, svga); + svga_write_linear(addr + 2, val >> 24, svga); + return; + case 2: + svga_write_linear(addr + 3, val & 0xff, svga); + svga_write_linear(addr + 2, val >> 8, svga); + svga_write_linear(addr + 1, val >> 16, svga); + svga_write_linear(addr, val >> 24, svga); + return; + case 3: + return; + } } } - static uint8_t -gd54xx_read(uint32_t addr, void *p) +gd54xx_read(uint32_t addr, void *priv) { - gd54xx_t *gd54xx = (gd54xx_t *)p; - svga_t *svga = &gd54xx->svga; + gd54xx_t *gd54xx = (gd54xx_t *) priv; + svga_t *svga = &gd54xx->svga; if ((svga->seqregs[0x07] & 0x01) == 0) - return svga_read(addr, svga); + return svga_read(addr, svga); - if (gd54xx->countminusone && gd54xx->blt.ms_is_dest && - !(gd54xx->blt.status & CIRRUS_BLT_PAUSED)) - return gd54xx_mem_sys_dest_read(gd54xx); + if (gd54xx->countminusone && gd54xx->blt.ms_is_dest && !(gd54xx->blt.status & CIRRUS_BLT_PAUSED)) + return gd54xx_mem_sys_dest_read(gd54xx); addr = (addr & 0x7fff) + svga->extra_banks[(addr >> 15) & 1]; return svga_read_linear(addr, svga); } - static uint16_t -gd54xx_readw(uint32_t addr, void *p) +gd54xx_readw(uint32_t addr, void *priv) { - gd54xx_t *gd54xx = (gd54xx_t *)p; - svga_t *svga = &gd54xx->svga; - uint16_t ret; + gd54xx_t *gd54xx = (gd54xx_t *) priv; + svga_t *svga = &gd54xx->svga; + uint16_t ret; if ((svga->seqregs[0x07] & 0x01) == 0) - return svga_readw(addr, svga); + return svga_readw(addr, svga); - if (gd54xx->countminusone && gd54xx->blt.ms_is_dest && - !(gd54xx->blt.status & CIRRUS_BLT_PAUSED)) { - ret = gd54xx_read(addr, p); - ret |= gd54xx_read(addr + 1, p) << 8; - return ret; + if (gd54xx->countminusone && gd54xx->blt.ms_is_dest && !(gd54xx->blt.status & CIRRUS_BLT_PAUSED)) { + ret = gd54xx_read(addr, priv); + ret |= gd54xx_read(addr + 1, priv) << 8; + return ret; } addr = (addr & 0x7fff) + svga->extra_banks[(addr >> 15) & 1]; return svga_readw_linear(addr, svga); } - static uint32_t -gd54xx_readl(uint32_t addr, void *p) +gd54xx_readl(uint32_t addr, void *priv) { - gd54xx_t *gd54xx = (gd54xx_t *)p; - svga_t *svga = &gd54xx->svga; - uint32_t ret; + gd54xx_t *gd54xx = (gd54xx_t *) priv; + svga_t *svga = &gd54xx->svga; + uint32_t ret; if ((svga->seqregs[0x07] & 0x01) == 0) - return svga_readl(addr, svga); + return svga_readl(addr, svga); - if (gd54xx->countminusone && gd54xx->blt.ms_is_dest && - !(gd54xx->blt.status & CIRRUS_BLT_PAUSED)) { - ret = gd54xx_read(addr, p); - ret |= gd54xx_read(addr + 1, p) << 8; - ret |= gd54xx_read(addr + 2, p) << 16; - ret |= gd54xx_read(addr + 3, p) << 24; - return ret; + if (gd54xx->countminusone && gd54xx->blt.ms_is_dest && !(gd54xx->blt.status & CIRRUS_BLT_PAUSED)) { + ret = gd54xx_read(addr, priv); + ret |= gd54xx_read(addr + 1, priv) << 8; + ret |= gd54xx_read(addr + 2, priv) << 16; + ret |= gd54xx_read(addr + 3, priv) << 24; + return ret; } addr = (addr & 0x7fff) + svga->extra_banks[(addr >> 15) & 1]; return svga_readl_linear(addr, svga); } - static int gd543x_do_mmio(svga_t *svga, uint32_t addr) { if (svga->seqregs[0x17] & CIRRUS_MMIO_USE_PCIADDR) - return 1; + return 1; else - return ((addr & ~0xff) == 0xb8000); + return ((addr & ~0xff) == 0xb8000); } - static void -gd543x_mmio_write(uint32_t addr, uint8_t val, void *p) +gd543x_mmio_write(uint32_t addr, uint8_t val, void *priv) { - gd54xx_t *gd54xx = (gd54xx_t *)p; - svga_t *svga = &gd54xx->svga; - uint8_t old; + gd54xx_t *gd54xx = (gd54xx_t *) priv; + svga_t *svga = &gd54xx->svga; + uint8_t old; if (gd543x_do_mmio(svga, addr)) { - switch (addr & 0xff) { - case 0x00: - if (gd54xx_is_5434(svga)) - gd54xx->blt.bg_col = (gd54xx->blt.bg_col & 0xffffff00) | val; - else - gd54xx->blt.bg_col = (gd54xx->blt.bg_col & 0xff00) | val; - break; - case 0x01: - if (gd54xx_is_5434(svga)) - gd54xx->blt.bg_col = (gd54xx->blt.bg_col & 0xffff00ff) | (val << 8); - else - gd54xx->blt.bg_col = (gd54xx->blt.bg_col & 0x00ff) | (val << 8); - break; - case 0x02: - if (gd54xx_is_5434(svga)) - gd54xx->blt.bg_col = (gd54xx->blt.bg_col & 0xff00ffff) | (val << 16); - break; - case 0x03: - if (gd54xx_is_5434(svga)) - gd54xx->blt.bg_col = (gd54xx->blt.bg_col & 0x00ffffff) | (val << 24); - break; + switch (addr & 0xff) { + case 0x00: + if (gd54xx_is_5434(svga)) + gd54xx->blt.bg_col = (gd54xx->blt.bg_col & 0xffffff00) | val; + else + gd54xx->blt.bg_col = (gd54xx->blt.bg_col & 0xff00) | val; + break; + case 0x01: + if (gd54xx_is_5434(svga)) + gd54xx->blt.bg_col = (gd54xx->blt.bg_col & 0xffff00ff) | (val << 8); + else + gd54xx->blt.bg_col = (gd54xx->blt.bg_col & 0x00ff) | (val << 8); + break; + case 0x02: + if (gd54xx_is_5434(svga)) + gd54xx->blt.bg_col = (gd54xx->blt.bg_col & 0xff00ffff) | (val << 16); + break; + case 0x03: + if (gd54xx_is_5434(svga)) + gd54xx->blt.bg_col = (gd54xx->blt.bg_col & 0x00ffffff) | (val << 24); + break; - case 0x04: - if (gd54xx_is_5434(svga)) - gd54xx->blt.fg_col = (gd54xx->blt.fg_col & 0xffffff00) | val; - else - gd54xx->blt.fg_col = (gd54xx->blt.fg_col & 0xff00) | val; - break; - case 0x05: - if (gd54xx_is_5434(svga)) - gd54xx->blt.fg_col = (gd54xx->blt.fg_col & 0xffff00ff) | (val << 8); - else - gd54xx->blt.fg_col = (gd54xx->blt.fg_col & 0x00ff) | (val << 8); - break; - case 0x06: - if (gd54xx_is_5434(svga)) - gd54xx->blt.fg_col = (gd54xx->blt.fg_col & 0xff00ffff) | (val << 16); - break; - case 0x07: - if (gd54xx_is_5434(svga)) - gd54xx->blt.fg_col = (gd54xx->blt.fg_col & 0x00ffffff) | (val << 24); - break; + case 0x04: + if (gd54xx_is_5434(svga)) + gd54xx->blt.fg_col = (gd54xx->blt.fg_col & 0xffffff00) | val; + else + gd54xx->blt.fg_col = (gd54xx->blt.fg_col & 0xff00) | val; + break; + case 0x05: + if (gd54xx_is_5434(svga)) + gd54xx->blt.fg_col = (gd54xx->blt.fg_col & 0xffff00ff) | (val << 8); + else + gd54xx->blt.fg_col = (gd54xx->blt.fg_col & 0x00ff) | (val << 8); + break; + case 0x06: + if (gd54xx_is_5434(svga)) + gd54xx->blt.fg_col = (gd54xx->blt.fg_col & 0xff00ffff) | (val << 16); + break; + case 0x07: + if (gd54xx_is_5434(svga)) + gd54xx->blt.fg_col = (gd54xx->blt.fg_col & 0x00ffffff) | (val << 24); + break; - case 0x08: - gd54xx->blt.width = (gd54xx->blt.width & 0xff00) | val; - break; - case 0x09: - gd54xx->blt.width = (gd54xx->blt.width & 0x00ff) | (val << 8); - if (gd54xx_is_5434(svga)) - gd54xx->blt.width &= 0x1fff; - else - gd54xx->blt.width &= 0x07ff; - break; - case 0x0a: - gd54xx->blt.height = (gd54xx->blt.height & 0xff00) | val; - break; - case 0x0b: - gd54xx->blt.height = (gd54xx->blt.height & 0x00ff) | (val << 8); - if (svga->crtc[0x27] >= CIRRUS_ID_CLGD5436) - gd54xx->blt.height &= 0x07ff; - else - gd54xx->blt.height &= 0x03ff; - break; - case 0x0c: - gd54xx->blt.dst_pitch = (gd54xx->blt.dst_pitch & 0xff00) | val; - break; - case 0x0d: - gd54xx->blt.dst_pitch = (gd54xx->blt.dst_pitch & 0x00ff) | (val << 8); - gd54xx->blt.dst_pitch &= 0x1fff; - break; - case 0x0e: - gd54xx->blt.src_pitch = (gd54xx->blt.src_pitch & 0xff00) | val; - break; - case 0x0f: - gd54xx->blt.src_pitch = (gd54xx->blt.src_pitch & 0x00ff) | (val << 8); - gd54xx->blt.src_pitch &= 0x1fff; - break; + case 0x08: + gd54xx->blt.width = (gd54xx->blt.width & 0xff00) | val; + break; + case 0x09: + gd54xx->blt.width = (gd54xx->blt.width & 0x00ff) | (val << 8); + if (gd54xx_is_5434(svga)) + gd54xx->blt.width &= 0x1fff; + else + gd54xx->blt.width &= 0x07ff; + break; + case 0x0a: + gd54xx->blt.height = (gd54xx->blt.height & 0xff00) | val; + break; + case 0x0b: + gd54xx->blt.height = (gd54xx->blt.height & 0x00ff) | (val << 8); + if (svga->crtc[0x27] >= CIRRUS_ID_CLGD5436) + gd54xx->blt.height &= 0x07ff; + else + gd54xx->blt.height &= 0x03ff; + break; + case 0x0c: + gd54xx->blt.dst_pitch = (gd54xx->blt.dst_pitch & 0xff00) | val; + break; + case 0x0d: + gd54xx->blt.dst_pitch = (gd54xx->blt.dst_pitch & 0x00ff) | (val << 8); + gd54xx->blt.dst_pitch &= 0x1fff; + break; + case 0x0e: + gd54xx->blt.src_pitch = (gd54xx->blt.src_pitch & 0xff00) | val; + break; + case 0x0f: + gd54xx->blt.src_pitch = (gd54xx->blt.src_pitch & 0x00ff) | (val << 8); + gd54xx->blt.src_pitch &= 0x1fff; + break; - case 0x10: - gd54xx->blt.dst_addr = (gd54xx->blt.dst_addr & 0xffff00) | val; - break; - case 0x11: - gd54xx->blt.dst_addr = (gd54xx->blt.dst_addr & 0xff00ff) | (val << 8); - break; - case 0x12: - gd54xx->blt.dst_addr = (gd54xx->blt.dst_addr & 0x00ffff) | (val << 16); - if (gd54xx_is_5434(svga)) - gd54xx->blt.dst_addr &= 0x3fffff; - else - gd54xx->blt.dst_addr &= 0x1fffff; + case 0x10: + gd54xx->blt.dst_addr = (gd54xx->blt.dst_addr & 0xffff00) | val; + break; + case 0x11: + gd54xx->blt.dst_addr = (gd54xx->blt.dst_addr & 0xff00ff) | (val << 8); + break; + case 0x12: + gd54xx->blt.dst_addr = (gd54xx->blt.dst_addr & 0x00ffff) | (val << 16); + if (gd54xx_is_5434(svga)) + gd54xx->blt.dst_addr &= 0x3fffff; + else + gd54xx->blt.dst_addr &= 0x1fffff; - if ((svga->crtc[0x27] >= CIRRUS_ID_CLGD5436) && (gd54xx->blt.status & CIRRUS_BLT_AUTOSTART) && - !(gd54xx->blt.status & CIRRUS_BLT_BUSY)) { - gd54xx->blt.status |= CIRRUS_BLT_BUSY; - gd54xx_start_blit(0, 0xffffffff, gd54xx, svga); - } - break; + if ((svga->crtc[0x27] >= CIRRUS_ID_CLGD5436) && (gd54xx->blt.status & CIRRUS_BLT_AUTOSTART) && !(gd54xx->blt.status & CIRRUS_BLT_BUSY)) { + gd54xx->blt.status |= CIRRUS_BLT_BUSY; + gd54xx_start_blit(0, 0xffffffff, gd54xx, svga); + } + break; - case 0x14: - gd54xx->blt.src_addr = (gd54xx->blt.src_addr & 0xffff00) | val; - break; - case 0x15: - gd54xx->blt.src_addr = (gd54xx->blt.src_addr & 0xff00ff) | (val << 8); - break; - case 0x16: - gd54xx->blt.src_addr = (gd54xx->blt.src_addr & 0x00ffff) | (val << 16); - if (gd54xx_is_5434(svga)) - gd54xx->blt.src_addr &= 0x3fffff; - else - gd54xx->blt.src_addr &= 0x1fffff; - break; + case 0x14: + gd54xx->blt.src_addr = (gd54xx->blt.src_addr & 0xffff00) | val; + break; + case 0x15: + gd54xx->blt.src_addr = (gd54xx->blt.src_addr & 0xff00ff) | (val << 8); + break; + case 0x16: + gd54xx->blt.src_addr = (gd54xx->blt.src_addr & 0x00ffff) | (val << 16); + if (gd54xx_is_5434(svga)) + gd54xx->blt.src_addr &= 0x3fffff; + else + gd54xx->blt.src_addr &= 0x1fffff; + break; - case 0x17: - gd54xx->blt.mask = val; - break; - case 0x18: - gd54xx->blt.mode = val; - gd543x_recalc_mapping(gd54xx); - break; + case 0x17: + gd54xx->blt.mask = val; + break; + case 0x18: + gd54xx->blt.mode = val; + gd543x_recalc_mapping(gd54xx); + break; - case 0x1a: - gd54xx->blt.rop = val; - break; + case 0x1a: + gd54xx->blt.rop = val; + break; - case 0x1b: - if (svga->crtc[0x27] >= CIRRUS_ID_CLGD5436) - gd54xx->blt.modeext = val; - break; + case 0x1b: + if (svga->crtc[0x27] >= CIRRUS_ID_CLGD5436) + gd54xx->blt.modeext = val; + break; - case 0x1c: - gd54xx->blt.trans_col = (gd54xx->blt.trans_col & 0xff00) | val; - break; - case 0x1d: - gd54xx->blt.trans_col = (gd54xx->blt.trans_col & 0x00ff) | (val << 8); - break; + case 0x1c: + gd54xx->blt.trans_col = (gd54xx->blt.trans_col & 0xff00) | val; + break; + case 0x1d: + gd54xx->blt.trans_col = (gd54xx->blt.trans_col & 0x00ff) | (val << 8); + break; - case 0x20: - gd54xx->blt.trans_mask = (gd54xx->blt.trans_mask & 0xff00) | val; - break; - case 0x21: - gd54xx->blt.trans_mask = (gd54xx->blt.trans_mask & 0x00ff) | (val << 8); - break; + case 0x20: + gd54xx->blt.trans_mask = (gd54xx->blt.trans_mask & 0xff00) | val; + break; + case 0x21: + gd54xx->blt.trans_mask = (gd54xx->blt.trans_mask & 0x00ff) | (val << 8); + break; - case 0x40: - old = gd54xx->blt.status; - gd54xx->blt.status = val; - gd543x_recalc_mapping(gd54xx); - if (!(old & CIRRUS_BLT_RESET) && (gd54xx->blt.status & CIRRUS_BLT_RESET)) - gd54xx_reset_blit(gd54xx); - else if (!(old & CIRRUS_BLT_START) && (gd54xx->blt.status & CIRRUS_BLT_START)) { - gd54xx->blt.status |= CIRRUS_BLT_BUSY; - gd54xx_start_blit(0, 0xffffffff, gd54xx, svga); - } - break; - } + case 0x40: + old = gd54xx->blt.status; + gd54xx->blt.status = val; + gd543x_recalc_mapping(gd54xx); + if (!(old & CIRRUS_BLT_RESET) && (gd54xx->blt.status & CIRRUS_BLT_RESET)) + gd54xx_reset_blit(gd54xx); + else if (!(old & CIRRUS_BLT_START) && (gd54xx->blt.status & CIRRUS_BLT_START)) { + gd54xx->blt.status |= CIRRUS_BLT_BUSY; + gd54xx_start_blit(0, 0xffffffff, gd54xx, svga); + } + break; + + default: + break; + } } else if (gd54xx->mmio_vram_overlap) - gd54xx_write(addr, val, gd54xx); + gd54xx_write(addr, val, gd54xx); } - static void -gd543x_mmio_writeb(uint32_t addr, uint8_t val, void *p) +gd543x_mmio_writeb(uint32_t addr, uint8_t val, void *priv) { - gd54xx_t *gd54xx = (gd54xx_t *)p; - svga_t *svga = &gd54xx->svga; + gd54xx_t *gd54xx = (gd54xx_t *) priv; + svga_t *svga = &gd54xx->svga; - if (!gd543x_do_mmio(svga, addr) && !gd54xx->blt.ms_is_dest && - gd54xx->countminusone && !(gd54xx->blt.status & CIRRUS_BLT_PAUSED)) { - gd54xx_mem_sys_src_write(gd54xx, val); - return; + if (!gd543x_do_mmio(svga, addr) && !gd54xx->blt.ms_is_dest && gd54xx->countminusone && !(gd54xx->blt.status & CIRRUS_BLT_PAUSED)) { + gd54xx_mem_sys_src_write(gd54xx, val); + return; } - gd543x_mmio_write(addr, val, p); + gd543x_mmio_write(addr, val, priv); } - static void -gd543x_mmio_writew(uint32_t addr, uint16_t val, void *p) +gd543x_mmio_writew(uint32_t addr, uint16_t val, void *priv) { - gd54xx_t *gd54xx = (gd54xx_t *)p; - svga_t *svga = &gd54xx->svga; + gd54xx_t *gd54xx = (gd54xx_t *) priv; + svga_t *svga = &gd54xx->svga; if (gd543x_do_mmio(svga, addr)) { - gd543x_mmio_write(addr, val & 0xff, gd54xx); - gd543x_mmio_write(addr + 1, val >> 8, gd54xx); + gd543x_mmio_write(addr, val & 0xff, gd54xx); + gd543x_mmio_write(addr + 1, val >> 8, gd54xx); } else if (gd54xx->mmio_vram_overlap) { - if (gd54xx->countminusone && !gd54xx->blt.ms_is_dest && - !(gd54xx->blt.status & CIRRUS_BLT_PAUSED)) { - gd543x_mmio_write(addr, val & 0xff, gd54xx); - gd543x_mmio_write(addr + 1, val >> 8, gd54xx); - } else { - gd54xx_write(addr, val, gd54xx); - gd54xx_write(addr + 1, val >> 8, gd54xx); - } + if (gd54xx->countminusone && !gd54xx->blt.ms_is_dest && !(gd54xx->blt.status & CIRRUS_BLT_PAUSED)) { + gd543x_mmio_write(addr, val & 0xff, gd54xx); + gd543x_mmio_write(addr + 1, val >> 8, gd54xx); + } else { + gd54xx_write(addr, val, gd54xx); + gd54xx_write(addr + 1, val >> 8, gd54xx); + } } } - static void -gd543x_mmio_writel(uint32_t addr, uint32_t val, void *p) +gd543x_mmio_writel(uint32_t addr, uint32_t val, void *priv) { - gd54xx_t *gd54xx = (gd54xx_t *)p; - svga_t *svga = &gd54xx->svga; + gd54xx_t *gd54xx = (gd54xx_t *) priv; + svga_t *svga = &gd54xx->svga; if (gd543x_do_mmio(svga, addr)) { - gd543x_mmio_write(addr, val & 0xff, gd54xx); - gd543x_mmio_write(addr+1, val >> 8, gd54xx); - gd543x_mmio_write(addr+2, val >> 16, gd54xx); - gd543x_mmio_write(addr+3, val >> 24, gd54xx); + gd543x_mmio_write(addr, val & 0xff, gd54xx); + gd543x_mmio_write(addr + 1, val >> 8, gd54xx); + gd543x_mmio_write(addr + 2, val >> 16, gd54xx); + gd543x_mmio_write(addr + 3, val >> 24, gd54xx); } else if (gd54xx->mmio_vram_overlap) { - if (gd54xx->countminusone && !gd54xx->blt.ms_is_dest && - !(gd54xx->blt.status & CIRRUS_BLT_PAUSED)) { - gd543x_mmio_write(addr, val & 0xff, gd54xx); - gd543x_mmio_write(addr+1, val >> 8, gd54xx); - gd543x_mmio_write(addr+2, val >> 16, gd54xx); - gd543x_mmio_write(addr+3, val >> 24, gd54xx); - } else { - gd54xx_write(addr, val, gd54xx); - gd54xx_write(addr+1, val >> 8, gd54xx); - gd54xx_write(addr+2, val >> 16, gd54xx); - gd54xx_write(addr+3, val >> 24, gd54xx); - } + if (gd54xx->countminusone && !gd54xx->blt.ms_is_dest && !(gd54xx->blt.status & CIRRUS_BLT_PAUSED)) { + gd543x_mmio_write(addr, val & 0xff, gd54xx); + gd543x_mmio_write(addr + 1, val >> 8, gd54xx); + gd543x_mmio_write(addr + 2, val >> 16, gd54xx); + gd543x_mmio_write(addr + 3, val >> 24, gd54xx); + } else { + gd54xx_write(addr, val, gd54xx); + gd54xx_write(addr + 1, val >> 8, gd54xx); + gd54xx_write(addr + 2, val >> 16, gd54xx); + gd54xx_write(addr + 3, val >> 24, gd54xx); + } } } - static uint8_t -gd543x_mmio_read(uint32_t addr, void *p) +gd543x_mmio_read(uint32_t addr, void *priv) { - gd54xx_t *gd54xx = (gd54xx_t *)p; - svga_t *svga = &gd54xx->svga; - uint8_t ret = 0xff; + gd54xx_t *gd54xx = (gd54xx_t *) priv; + svga_t *svga = &gd54xx->svga; + uint8_t ret = 0xff; if (gd543x_do_mmio(svga, addr)) { - switch (addr & 0xff) { - case 0x00: - ret = gd54xx->blt.bg_col & 0xff; - break; - case 0x01: - ret = (gd54xx->blt.bg_col >> 8) & 0xff; - break; - case 0x02: - if (gd54xx_is_5434(svga)) - ret = (gd54xx->blt.bg_col >> 16) & 0xff; - break; - case 0x03: - if (gd54xx_is_5434(svga)) - ret = (gd54xx->blt.bg_col >> 24) & 0xff; - break; + switch (addr & 0xff) { + case 0x00: + ret = gd54xx->blt.bg_col & 0xff; + break; + case 0x01: + ret = (gd54xx->blt.bg_col >> 8) & 0xff; + break; + case 0x02: + if (gd54xx_is_5434(svga)) + ret = (gd54xx->blt.bg_col >> 16) & 0xff; + break; + case 0x03: + if (gd54xx_is_5434(svga)) + ret = (gd54xx->blt.bg_col >> 24) & 0xff; + break; - case 0x04: - ret = gd54xx->blt.fg_col & 0xff; - break; - case 0x05: - ret = (gd54xx->blt.fg_col >> 8) & 0xff; - break; - case 0x06: - if (gd54xx_is_5434(svga)) - ret = (gd54xx->blt.fg_col >> 16) & 0xff; - break; - case 0x07: - if (gd54xx_is_5434(svga)) - ret = (gd54xx->blt.fg_col >> 24) & 0xff; - break; + case 0x04: + ret = gd54xx->blt.fg_col & 0xff; + break; + case 0x05: + ret = (gd54xx->blt.fg_col >> 8) & 0xff; + break; + case 0x06: + if (gd54xx_is_5434(svga)) + ret = (gd54xx->blt.fg_col >> 16) & 0xff; + break; + case 0x07: + if (gd54xx_is_5434(svga)) + ret = (gd54xx->blt.fg_col >> 24) & 0xff; + break; - case 0x08: - ret = gd54xx->blt.width & 0xff; - break; - case 0x09: - if (gd54xx_is_5434(svga)) - ret = (gd54xx->blt.width >> 8) & 0x1f; - else - ret = (gd54xx->blt.width >> 8) & 0x07; - break; - case 0x0a: - ret = gd54xx->blt.height & 0xff; - break; - case 0x0b: - if (svga->crtc[0x27] >= CIRRUS_ID_CLGD5436) - ret = (gd54xx->blt.height >> 8) & 0x07; - else - ret = (gd54xx->blt.height >> 8) & 0x03; - break; - case 0x0c: - ret = gd54xx->blt.dst_pitch & 0xff; - break; - case 0x0d: - ret = (gd54xx->blt.dst_pitch >> 8) & 0x1f; - break; - case 0x0e: - ret = gd54xx->blt.src_pitch & 0xff; - break; - case 0x0f: - ret = (gd54xx->blt.src_pitch >> 8) & 0x1f; - break; + case 0x08: + ret = gd54xx->blt.width & 0xff; + break; + case 0x09: + if (gd54xx_is_5434(svga)) + ret = (gd54xx->blt.width >> 8) & 0x1f; + else + ret = (gd54xx->blt.width >> 8) & 0x07; + break; + case 0x0a: + ret = gd54xx->blt.height & 0xff; + break; + case 0x0b: + if (svga->crtc[0x27] >= CIRRUS_ID_CLGD5436) + ret = (gd54xx->blt.height >> 8) & 0x07; + else + ret = (gd54xx->blt.height >> 8) & 0x03; + break; + case 0x0c: + ret = gd54xx->blt.dst_pitch & 0xff; + break; + case 0x0d: + ret = (gd54xx->blt.dst_pitch >> 8) & 0x1f; + break; + case 0x0e: + ret = gd54xx->blt.src_pitch & 0xff; + break; + case 0x0f: + ret = (gd54xx->blt.src_pitch >> 8) & 0x1f; + break; - case 0x10: - ret = gd54xx->blt.dst_addr & 0xff; - break; - case 0x11: - ret = (gd54xx->blt.dst_addr >> 8) & 0xff; - break; - case 0x12: - if (gd54xx_is_5434(svga)) - ret = (gd54xx->blt.dst_addr >> 16) & 0x3f; - else - ret = (gd54xx->blt.dst_addr >> 16) & 0x1f; - break; + case 0x10: + ret = gd54xx->blt.dst_addr & 0xff; + break; + case 0x11: + ret = (gd54xx->blt.dst_addr >> 8) & 0xff; + break; + case 0x12: + if (gd54xx_is_5434(svga)) + ret = (gd54xx->blt.dst_addr >> 16) & 0x3f; + else + ret = (gd54xx->blt.dst_addr >> 16) & 0x1f; + break; - case 0x14: - ret = gd54xx->blt.src_addr & 0xff; - break; - case 0x15: - ret = (gd54xx->blt.src_addr >> 8) & 0xff; - break; - case 0x16: - if (gd54xx_is_5434(svga)) - ret = (gd54xx->blt.src_addr >> 16) & 0x3f; - else - ret = (gd54xx->blt.src_addr >> 16) & 0x1f; - break; + case 0x14: + ret = gd54xx->blt.src_addr & 0xff; + break; + case 0x15: + ret = (gd54xx->blt.src_addr >> 8) & 0xff; + break; + case 0x16: + if (gd54xx_is_5434(svga)) + ret = (gd54xx->blt.src_addr >> 16) & 0x3f; + else + ret = (gd54xx->blt.src_addr >> 16) & 0x1f; + break; - case 0x17: - ret = gd54xx->blt.mask; - break; - case 0x18: - ret = gd54xx->blt.mode; - break; + case 0x17: + ret = gd54xx->blt.mask; + break; + case 0x18: + ret = gd54xx->blt.mode; + break; - case 0x1a: - ret = gd54xx->blt.rop; - break; + case 0x1a: + ret = gd54xx->blt.rop; + break; - case 0x1b: - if (svga->crtc[0x27] >= CIRRUS_ID_CLGD5436) - ret = gd54xx->blt.modeext; - break; + case 0x1b: + if (svga->crtc[0x27] >= CIRRUS_ID_CLGD5436) + ret = gd54xx->blt.modeext; + break; - case 0x1c: - ret = gd54xx->blt.trans_col & 0xff; - break; - case 0x1d: - ret = (gd54xx->blt.trans_col >> 8) & 0xff; - break; + case 0x1c: + ret = gd54xx->blt.trans_col & 0xff; + break; + case 0x1d: + ret = (gd54xx->blt.trans_col >> 8) & 0xff; + break; - case 0x20: - ret = gd54xx->blt.trans_mask & 0xff; - break; - case 0x21: - ret = (gd54xx->blt.trans_mask >> 8) & 0xff; - break; + case 0x20: + ret = gd54xx->blt.trans_mask & 0xff; + break; + case 0x21: + ret = (gd54xx->blt.trans_mask >> 8) & 0xff; + break; - case 0x40: - ret = gd54xx->blt.status; - break; - } + case 0x40: + ret = gd54xx->blt.status; + break; + + default: + break; + } } else if (gd54xx->mmio_vram_overlap) - ret = gd54xx_read(addr, gd54xx); - else if (gd54xx->countminusone && gd54xx->blt.ms_is_dest && - !(gd54xx->blt.status & CIRRUS_BLT_PAUSED)) { - ret = gd54xx_mem_sys_dest_read(gd54xx); + ret = gd54xx_read(addr, gd54xx); + else if (gd54xx->countminusone && gd54xx->blt.ms_is_dest && !(gd54xx->blt.status & CIRRUS_BLT_PAUSED)) { + ret = gd54xx_mem_sys_dest_read(gd54xx); } return ret; } - static uint16_t -gd543x_mmio_readw(uint32_t addr, void *p) +gd543x_mmio_readw(uint32_t addr, void *priv) { - gd54xx_t *gd54xx = (gd54xx_t *)p; - svga_t *svga = &gd54xx->svga; - uint16_t ret = 0xffff; + gd54xx_t *gd54xx = (gd54xx_t *) priv; + svga_t *svga = &gd54xx->svga; + uint16_t ret = 0xffff; if (gd543x_do_mmio(svga, addr)) - ret = gd543x_mmio_read(addr, gd54xx) | (gd543x_mmio_read(addr+1, gd54xx) << 8); + ret = gd543x_mmio_read(addr, gd54xx) | (gd543x_mmio_read(addr + 1, gd54xx) << 8); else if (gd54xx->mmio_vram_overlap) - ret = gd54xx_read(addr, gd54xx) | (gd54xx_read(addr+1, gd54xx) << 8); - else if (gd54xx->countminusone && gd54xx->blt.ms_is_dest && - !(gd54xx->blt.status & CIRRUS_BLT_PAUSED)) { - ret = gd543x_mmio_read(addr, p); - ret |= gd543x_mmio_read(addr + 1, p) << 8; - return ret; + ret = gd54xx_read(addr, gd54xx) | (gd54xx_read(addr + 1, gd54xx) << 8); + else if (gd54xx->countminusone && gd54xx->blt.ms_is_dest && !(gd54xx->blt.status & CIRRUS_BLT_PAUSED)) { + ret = gd543x_mmio_read(addr, priv); + ret |= gd543x_mmio_read(addr + 1, priv) << 8; + return ret; } return ret; } - static uint32_t -gd543x_mmio_readl(uint32_t addr, void *p) +gd543x_mmio_readl(uint32_t addr, void *priv) { - gd54xx_t *gd54xx = (gd54xx_t *)p; - svga_t *svga = &gd54xx->svga; - uint32_t ret = 0xffffffff; + gd54xx_t *gd54xx = (gd54xx_t *) priv; + svga_t *svga = &gd54xx->svga; + uint32_t ret = 0xffffffff; if (gd543x_do_mmio(svga, addr)) - ret = gd543x_mmio_read(addr, gd54xx) | (gd543x_mmio_read(addr+1, gd54xx) << 8) | (gd543x_mmio_read(addr+2, gd54xx) << 16) | (gd543x_mmio_read(addr+3, gd54xx) << 24); + ret = gd543x_mmio_read(addr, gd54xx) | (gd543x_mmio_read(addr + 1, gd54xx) << 8) | (gd543x_mmio_read(addr + 2, gd54xx) << 16) | (gd543x_mmio_read(addr + 3, gd54xx) << 24); else if (gd54xx->mmio_vram_overlap) - ret = gd54xx_read(addr, gd54xx) | (gd54xx_read(addr+1, gd54xx) << 8) | (gd54xx_read(addr+2, gd54xx) << 16) | (gd54xx_read(addr+3, gd54xx) << 24); - else if (gd54xx->countminusone && gd54xx->blt.ms_is_dest && - !(gd54xx->blt.status & CIRRUS_BLT_PAUSED)) { - ret = gd543x_mmio_read(addr, p); - ret |= gd543x_mmio_read(addr + 1, p) << 8; - ret |= gd543x_mmio_read(addr + 2, p) << 16; - ret |= gd543x_mmio_read(addr + 3, p) << 24; - return ret; + ret = gd54xx_read(addr, gd54xx) | (gd54xx_read(addr + 1, gd54xx) << 8) | (gd54xx_read(addr + 2, gd54xx) << 16) | (gd54xx_read(addr + 3, gd54xx) << 24); + else if (gd54xx->countminusone && gd54xx->blt.ms_is_dest && !(gd54xx->blt.status & CIRRUS_BLT_PAUSED)) { + ret = gd543x_mmio_read(addr, priv); + ret |= gd543x_mmio_read(addr + 1, priv) << 8; + ret |= gd543x_mmio_read(addr + 2, priv) << 16; + ret |= gd543x_mmio_read(addr + 3, priv) << 24; + return ret; } return ret; } - static void -gd5480_vgablt_write(uint32_t addr, uint8_t val, void *p) +gd5480_vgablt_write(uint32_t addr, uint8_t val, void *priv) { addr &= 0x00000fff; if ((addr >= 0x00000100) && (addr < 0x00000200)) - gd543x_mmio_writeb((addr & 0x000000ff) | 0x000b8000, val, p); + gd543x_mmio_writeb((addr & 0x000000ff) | 0x000b8000, val, priv); else if (addr < 0x00000100) - gd54xx_out(0x03c0 + addr, val, p); + gd54xx_out(0x03c0 + addr, val, priv); } - static void -gd5480_vgablt_writew(uint32_t addr, uint16_t val, void *p) +gd5480_vgablt_writew(uint32_t addr, uint16_t val, void *priv) { addr &= 0x00000fff; if ((addr >= 0x00000100) && (addr < 0x00000200)) - gd543x_mmio_writew((addr & 0x000000ff) | 0x000b8000, val, p); + gd543x_mmio_writew((addr & 0x000000ff) | 0x000b8000, val, priv); else if (addr < 0x00000100) { - gd5480_vgablt_write(addr, val & 0xff, p); - gd5480_vgablt_write(addr + 1, val >> 8, p); - } + gd5480_vgablt_write(addr, val & 0xff, priv); + gd5480_vgablt_write(addr + 1, val >> 8, priv); + } } - static void -gd5480_vgablt_writel(uint32_t addr, uint32_t val, void *p) +gd5480_vgablt_writel(uint32_t addr, uint32_t val, void *priv) { addr &= 0x00000fff; if ((addr >= 0x00000100) && (addr < 0x00000200)) - gd543x_mmio_writel((addr & 0x000000ff) | 0x000b8000, val, p); + gd543x_mmio_writel((addr & 0x000000ff) | 0x000b8000, val, priv); else if (addr < 0x00000100) { - gd5480_vgablt_writew(addr, val & 0xffff, p); - gd5480_vgablt_writew(addr + 2, val >> 16, p); - } + gd5480_vgablt_writew(addr, val & 0xffff, priv); + gd5480_vgablt_writew(addr + 2, val >> 16, priv); + } } - static uint8_t -gd5480_vgablt_read(uint32_t addr, void *p) +gd5480_vgablt_read(uint32_t addr, void *priv) { uint8_t ret = 0xff; addr &= 0x00000fff; if ((addr >= 0x00000100) && (addr < 0x00000200)) - ret = gd543x_mmio_read((addr & 0x000000ff) | 0x000b8000, p); + ret = gd543x_mmio_read((addr & 0x000000ff) | 0x000b8000, priv); else if (addr < 0x00000100) - ret = gd54xx_in(0x03c0 + addr, p); + ret = gd54xx_in(0x03c0 + addr, priv); return ret; } - static uint16_t -gd5480_vgablt_readw(uint32_t addr, void *p) +gd5480_vgablt_readw(uint32_t addr, void *priv) { uint16_t ret = 0xffff; addr &= 0x00000fff; if ((addr >= 0x00000100) && (addr < 0x00000200)) - ret = gd543x_mmio_readw((addr & 0x000000ff) | 0x000b8000, p); + ret = gd543x_mmio_readw((addr & 0x000000ff) | 0x000b8000, priv); else if (addr < 0x00000100) { - ret = gd5480_vgablt_read(addr, p); - ret |= (gd5480_vgablt_read(addr + 1, p) << 8); + ret = gd5480_vgablt_read(addr, priv); + ret |= (gd5480_vgablt_read(addr + 1, priv) << 8); } return ret; } - static uint32_t -gd5480_vgablt_readl(uint32_t addr, void *p) +gd5480_vgablt_readl(uint32_t addr, void *priv) { uint32_t ret = 0xffffffff; addr &= 0x00000fff; if ((addr >= 0x00000100) && (addr < 0x00000200)) - ret = gd543x_mmio_readl((addr & 0x000000ff) | 0x000b8000, p); + ret = gd543x_mmio_readl((addr & 0x000000ff) | 0x000b8000, priv); else if (addr < 0x00000100) { - ret = gd5480_vgablt_readw(addr, p); - ret |= (gd5480_vgablt_readw(addr + 2, p) << 16); + ret = gd5480_vgablt_readw(addr, priv); + ret |= (gd5480_vgablt_readw(addr + 2, priv) << 16); } return ret; } - static uint8_t gd54xx_color_expand(gd54xx_t *gd54xx, int mask, int shift) { uint8_t ret; if (gd54xx->blt.mode & CIRRUS_BLTMODE_TRANSPARENTCOMP) - ret = gd54xx->blt.fg_col >> (shift << 3); + ret = gd54xx->blt.fg_col >> (shift << 3); else - ret = mask ? (gd54xx->blt.fg_col >> (shift << 3)) : (gd54xx->blt.bg_col >> (shift << 3)); + ret = mask ? (gd54xx->blt.fg_col >> (shift << 3)) : (gd54xx->blt.bg_col >> (shift << 3)); return ret; } - static int gd54xx_get_pixel_width(gd54xx_t *gd54xx) { int ret = 1; switch (gd54xx->blt.mode & CIRRUS_BLTMODE_PIXELWIDTHMASK) { - case CIRRUS_BLTMODE_PIXELWIDTH8: - ret = 1; - break; - case CIRRUS_BLTMODE_PIXELWIDTH16: - ret = 2; - break; - case CIRRUS_BLTMODE_PIXELWIDTH24: - ret = 3; - break; - case CIRRUS_BLTMODE_PIXELWIDTH32: - ret = 4; - break; + case CIRRUS_BLTMODE_PIXELWIDTH8: + ret = 1; + break; + case CIRRUS_BLTMODE_PIXELWIDTH16: + ret = 2; + break; + case CIRRUS_BLTMODE_PIXELWIDTH24: + ret = 3; + break; + case CIRRUS_BLTMODE_PIXELWIDTH32: + ret = 4; + break; + + default: + break; } return ret; } - static void gd54xx_blit(gd54xx_t *gd54xx, uint8_t mask, uint8_t *dst, uint8_t target, int skip) { - int is_transp, is_bgonly; + int is_transp; + int is_bgonly; /* skip indicates whether or not it is a pixel to be skipped (used for left skip); mask indicates transparency or not (only when transparent comparison is enabled): - color expand: direct pattern bit; 1 = write, 0 = do not write - (the other way around in inverse mode); - normal 8-bpp or 16-bpp: does not match transparent color = write, - matches transparent color = do not write */ + color expand: direct pattern bit; 1 = write, 0 = do not write + (the other way around in inverse mode); + normal 8-bpp or 16-bpp: does not match transparent color = write, + matches transparent color = do not write */ /* Make sure to always ignore transparency and skip in case of mem sys dest. */ is_transp = (gd54xx->blt.mode & CIRRUS_BLTMODE_MEMSYSDEST) ? 0 : (gd54xx->blt.mode & CIRRUS_BLTMODE_TRANSPARENTCOMP); is_bgonly = (gd54xx->blt.mode & CIRRUS_BLTMODE_MEMSYSDEST) ? 0 : (gd54xx->blt.modeext & CIRRUS_BLTMODEEXT_BACKGROUNDONLY); - skip = (gd54xx->blt.mode & CIRRUS_BLTMODE_MEMSYSDEST) ? 0 : skip; + skip = (gd54xx->blt.mode & CIRRUS_BLTMODE_MEMSYSDEST) ? 0 : skip; if (is_transp) { - if ((gd54xx->blt.mode & CIRRUS_BLTMODE_COLOREXPAND) && - (gd54xx->blt.modeext & CIRRUS_BLTMODEEXT_COLOREXPINV)) - mask = !mask; + if ((gd54xx->blt.mode & CIRRUS_BLTMODE_COLOREXPAND) && (gd54xx->blt.modeext & CIRRUS_BLTMODEEXT_COLOREXPINV)) + mask = !mask; - /* If mask is 1 and it is not a pixel to be skipped, write it. */ - if (mask && !skip) - *dst = target; + /* If mask is 1 and it is not a pixel to be skipped, write it. */ + if (mask && !skip) + *dst = target; } else if ((gd54xx->blt.mode & CIRRUS_BLTMODE_COLOREXPAND) && is_bgonly) { - /* If mask is 1 or it is not a pixel to be skipped, write it. - (Skip only background pixels.) */ - if (mask || !skip) - *dst = target; + /* If mask is 1 or it is not a pixel to be skipped, write it. + (Skip only background pixels.) */ + if (mask || !skip) + *dst = target; } else { - /* If if it is not a pixel to be skipped, write it. */ - if (!skip) - *dst = target; + /* If if it is not a pixel to be skipped, write it. */ + if (!skip) + *dst = target; } } - static int gd54xx_transparent_comp(gd54xx_t *gd54xx, uint32_t xx, uint8_t src) { svga_t *svga = &gd54xx->svga; - int ret = 1; + int ret = 1; if ((gd54xx->blt.pixel_width <= 2) && gd54xx_has_transp(svga, 0)) { - ret = src ^ ((uint8_t *) &(gd54xx->blt.trans_col))[xx]; - if (gd54xx_has_transp(svga, 1)) - ret &= ~(((uint8_t *) &(gd54xx->blt.trans_mask))[xx]); - ret = !ret; + ret = src ^ ((uint8_t *) &(gd54xx->blt.trans_col))[xx]; + if (gd54xx_has_transp(svga, 1)) + ret &= ~(((uint8_t *) &(gd54xx->blt.trans_mask))[xx]); + ret = !ret; } return ret; } - static void gd54xx_pattern_copy(gd54xx_t *gd54xx) { - uint8_t target, src, *dst; - int x, y, pattern_y, pattern_pitch; - uint32_t bitmask = 0, xx, pixel; - uint32_t srca, srca2, dsta; - svga_t *svga = &gd54xx->svga; + uint8_t target; + uint8_t src; + uint8_t *dst; + int pattern_y; + int pattern_pitch; + uint32_t bitmask = 0; + uint32_t pixel; + uint32_t srca; + uint32_t srca2; + uint32_t dsta; + svga_t *svga = &gd54xx->svga; pattern_pitch = gd54xx->blt.pixel_width << 3; if (gd54xx->blt.pixel_width == 3) - pattern_pitch = 32; + pattern_pitch = 32; if (gd54xx->blt.mode & CIRRUS_BLTMODE_COLOREXPAND) - pattern_pitch = 1; + pattern_pitch = 1; dsta = gd54xx->blt.dst_addr & svga->vram_mask; /* The vertical offset is in the three low-order bits of the Source Address register. */ pattern_y = gd54xx->blt.src_addr & 0x07; - /* Mode Pattern bytes Pattern line bytes + /* Mode Pattern bytes Pattern line bytes --------------------------------------------------- - Color Expansion 8 1 - 8-bpp 64 8 - 16-bpp 128 16 - 24-bpp 256 32 - 32-bpp 256 32 + Color Expansion 8 1 + 8-bpp 64 8 + 16-bpp 128 16 + 24-bpp 256 32 + 32-bpp 256 32 */ /* The boundary has to be equal to the size of the pattern. */ srca = (gd54xx->blt.src_addr & ~0x07) & svga->vram_mask; - for (y = 0; y <= gd54xx->blt.height; y++) { - /* Go to the correct pattern line. */ - srca2 = srca + (pattern_y * pattern_pitch); - pixel = 0; - for (x = 0; x <= gd54xx->blt.width; x += gd54xx->blt.pixel_width) { - if (gd54xx->blt.mode & CIRRUS_BLTMODE_COLOREXPAND) { - if (gd54xx->blt.modeext & CIRRUS_BLTMODEEXT_SOLIDFILL) - bitmask = 1; - else - bitmask = svga->vram[srca2 & svga->vram_mask] & (0x80 >> pixel); - } - for (xx = 0; xx < gd54xx->blt.pixel_width; xx++) { - if (gd54xx->blt.mode & CIRRUS_BLTMODE_COLOREXPAND) - src = gd54xx_color_expand(gd54xx, bitmask, xx); - else { - src = svga->vram[(srca2 + (x % (gd54xx->blt.pixel_width << 3)) + xx) & svga->vram_mask]; - bitmask = gd54xx_transparent_comp(gd54xx, xx, src); - } - dst = &(svga->vram[(dsta + x + xx) & svga->vram_mask]); - target = *dst; - gd54xx_rop(gd54xx, &target, &target, &src); - if (gd54xx->blt.pixel_width == 3) - gd54xx_blit(gd54xx, bitmask, dst, target, ((x + xx) < gd54xx->blt.pattern_x)); - else - gd54xx_blit(gd54xx, bitmask, dst, target, (x < gd54xx->blt.pattern_x)); - } - pixel = (pixel + 1) & 7; - svga->changedvram[((dsta + x) & svga->vram_mask) >> 12] = changeframecount; - } - pattern_y = (pattern_y + 1) & 7; - dsta += gd54xx->blt.dst_pitch; + for (uint16_t y = 0; y <= gd54xx->blt.height; y++) { + /* Go to the correct pattern line. */ + srca2 = srca + (pattern_y * pattern_pitch); + pixel = 0; + for (uint16_t x = 0; x <= gd54xx->blt.width; x += gd54xx->blt.pixel_width) { + if (gd54xx->blt.mode & CIRRUS_BLTMODE_COLOREXPAND) { + if (gd54xx->blt.modeext & CIRRUS_BLTMODEEXT_SOLIDFILL) + bitmask = 1; + else + bitmask = svga->vram[srca2 & svga->vram_mask] & (0x80 >> pixel); + } + for (int xx = 0; xx < gd54xx->blt.pixel_width; xx++) { + if (gd54xx->blt.mode & CIRRUS_BLTMODE_COLOREXPAND) + src = gd54xx_color_expand(gd54xx, bitmask, xx); + else { + src = svga->vram[(srca2 + (x % (gd54xx->blt.pixel_width << 3)) + xx) & svga->vram_mask]; + bitmask = gd54xx_transparent_comp(gd54xx, xx, src); + } + dst = &(svga->vram[(dsta + x + xx) & svga->vram_mask]); + target = *dst; + gd54xx_rop(gd54xx, &target, &target, &src); + if (gd54xx->blt.pixel_width == 3) + gd54xx_blit(gd54xx, bitmask, dst, target, ((x + xx) < gd54xx->blt.pattern_x)); + else + gd54xx_blit(gd54xx, bitmask, dst, target, (x < gd54xx->blt.pattern_x)); + } + pixel = (pixel + 1) & 7; + svga->changedvram[((dsta + x) & svga->vram_mask) >> 12] = changeframecount; + } + pattern_y = (pattern_y + 1) & 7; + dsta += gd54xx->blt.dst_pitch; } } - static void gd54xx_reset_blit(gd54xx_t *gd54xx) { gd54xx->countminusone = 0; - gd54xx->blt.status &= ~(CIRRUS_BLT_START|CIRRUS_BLT_BUSY|CIRRUS_BLT_FIFOUSED); + gd54xx->blt.status &= ~(CIRRUS_BLT_START | CIRRUS_BLT_BUSY | CIRRUS_BLT_FIFOUSED); } - /* Each blit is either 1 byte -> 1 byte (non-color expand blit) or 1 byte -> 8/16/24/32 bytes (color expand blit). */ static void gd54xx_mem_sys_src(gd54xx_t *gd54xx, uint32_t cpu_dat, uint32_t count) { - uint8_t *dst, exp, target; - int mask_shift; - uint32_t byte_pos, bitmask = 0; - svga_t *svga = &gd54xx->svga; + uint8_t *dst; + uint8_t exp; + uint8_t target; + int mask_shift; + uint32_t byte_pos; + uint32_t bitmask = 0; + svga_t *svga = &gd54xx->svga; gd54xx->blt.ms_is_dest = 0; if (gd54xx->blt.mode & (CIRRUS_BLTMODE_MEMSYSDEST | CIRRUS_BLTMODE_PATTERNCOPY)) - gd54xx_reset_blit(gd54xx); + gd54xx_reset_blit(gd54xx); else if (count == 0xffffffff) { - gd54xx->blt.dst_addr_backup = gd54xx->blt.dst_addr; - gd54xx->blt.src_addr_backup = gd54xx->blt.src_addr; - gd54xx->blt.x_count = gd54xx->blt.xx_count = 0; - gd54xx->blt.y_count = 0; - gd54xx->countminusone = 1; - gd54xx->blt.sys_src32 = 0x00000000; - gd54xx->blt.sys_cnt = 0; - return; + gd54xx->blt.dst_addr_backup = gd54xx->blt.dst_addr; + gd54xx->blt.src_addr_backup = gd54xx->blt.src_addr; + gd54xx->blt.x_count = gd54xx->blt.xx_count = 0; + gd54xx->blt.y_count = 0; + gd54xx->countminusone = 1; + gd54xx->blt.sys_src32 = 0x00000000; + gd54xx->blt.sys_cnt = 0; + return; } else if (gd54xx->countminusone) { - if (!(gd54xx->blt.mode & CIRRUS_BLTMODE_COLOREXPAND) || (gd54xx->blt.modeext & CIRRUS_BLTMODEEXT_DWORDGRANULARITY)) { - if (!gd54xx->blt.xx_count && !gd54xx->blt.x_count) - byte_pos = (((gd54xx->blt.mask >> 5) & 3) << 3); - else - byte_pos = 0; - mask_shift = 31 - byte_pos; - if (!(gd54xx->blt.mode & CIRRUS_BLTMODE_COLOREXPAND)) - cpu_dat >>= byte_pos; - } else - mask_shift = 7; + if (!(gd54xx->blt.mode & CIRRUS_BLTMODE_COLOREXPAND) || (gd54xx->blt.modeext & CIRRUS_BLTMODEEXT_DWORDGRANULARITY)) { + if (!gd54xx->blt.xx_count && !gd54xx->blt.x_count) + byte_pos = (((gd54xx->blt.mask >> 5) & 3) << 3); + else + byte_pos = 0; + mask_shift = 31 - byte_pos; + if (!(gd54xx->blt.mode & CIRRUS_BLTMODE_COLOREXPAND)) + cpu_dat >>= byte_pos; + } else + mask_shift = 7; - while (mask_shift > -1) { - if (gd54xx->blt.mode & CIRRUS_BLTMODE_COLOREXPAND) { - bitmask = (cpu_dat >> mask_shift) & 0x01; - exp = gd54xx_color_expand(gd54xx, bitmask, gd54xx->blt.xx_count); - } else { - exp = cpu_dat & 0xff; - bitmask = gd54xx_transparent_comp(gd54xx, gd54xx->blt.xx_count, exp); - } + while (mask_shift > -1) { + if (gd54xx->blt.mode & CIRRUS_BLTMODE_COLOREXPAND) { + bitmask = (cpu_dat >> mask_shift) & 0x01; + exp = gd54xx_color_expand(gd54xx, bitmask, gd54xx->blt.xx_count); + } else { + exp = cpu_dat & 0xff; + bitmask = gd54xx_transparent_comp(gd54xx, gd54xx->blt.xx_count, exp); + } - dst = &(svga->vram[gd54xx->blt.dst_addr_backup & svga->vram_mask]); - target = *dst; - gd54xx_rop(gd54xx, &target, &target, &exp); - if ((gd54xx->blt.pixel_width == 3) && (gd54xx->blt.mode & CIRRUS_BLTMODE_COLOREXPAND)) - gd54xx_blit(gd54xx, bitmask, dst, target, ((gd54xx->blt.x_count + gd54xx->blt.xx_count) < gd54xx->blt.pattern_x)); - else - gd54xx_blit(gd54xx, bitmask, dst, target, (gd54xx->blt.x_count < gd54xx->blt.pattern_x)); + dst = &(svga->vram[gd54xx->blt.dst_addr_backup & svga->vram_mask]); + target = *dst; + gd54xx_rop(gd54xx, &target, &target, &exp); + if ((gd54xx->blt.pixel_width == 3) && (gd54xx->blt.mode & CIRRUS_BLTMODE_COLOREXPAND)) + gd54xx_blit(gd54xx, bitmask, dst, target, ((gd54xx->blt.x_count + gd54xx->blt.xx_count) < gd54xx->blt.pattern_x)); + else + gd54xx_blit(gd54xx, bitmask, dst, target, (gd54xx->blt.x_count < gd54xx->blt.pattern_x)); - gd54xx->blt.dst_addr_backup += gd54xx->blt.dir; + gd54xx->blt.dst_addr_backup += gd54xx->blt.dir; - if (gd54xx->blt.mode & CIRRUS_BLTMODE_COLOREXPAND) - gd54xx->blt.xx_count = (gd54xx->blt.xx_count + 1) % gd54xx->blt.pixel_width; + if (gd54xx->blt.mode & CIRRUS_BLTMODE_COLOREXPAND) + gd54xx->blt.xx_count = (gd54xx->blt.xx_count + 1) % gd54xx->blt.pixel_width; - svga->changedvram[(gd54xx->blt.dst_addr_backup & svga->vram_mask) >> 12] = changeframecount; + svga->changedvram[(gd54xx->blt.dst_addr_backup & svga->vram_mask) >> 12] = changeframecount; - if (!gd54xx->blt.xx_count) { - /* 1 mask bit = 1 blitted pixel */ - if (gd54xx->blt.mode & CIRRUS_BLTMODE_COLOREXPAND) - mask_shift--; - else { - cpu_dat >>= 8; - mask_shift -= 8; - } + if (!gd54xx->blt.xx_count) { + /* 1 mask bit = 1 blitted pixel */ + if (gd54xx->blt.mode & CIRRUS_BLTMODE_COLOREXPAND) + mask_shift--; + else { + cpu_dat >>= 8; + mask_shift -= 8; + } - if (gd54xx->blt.mode & CIRRUS_BLTMODE_COLOREXPAND) - gd54xx->blt.x_count = (gd54xx->blt.x_count + gd54xx->blt.pixel_width) % (gd54xx->blt.width + 1); - else - gd54xx->blt.x_count = (gd54xx->blt.x_count + 1) % (gd54xx->blt.width + 1); + if (gd54xx->blt.mode & CIRRUS_BLTMODE_COLOREXPAND) + gd54xx->blt.x_count = (gd54xx->blt.x_count + gd54xx->blt.pixel_width) % (gd54xx->blt.width + 1); + else + gd54xx->blt.x_count = (gd54xx->blt.x_count + 1) % (gd54xx->blt.width + 1); - if (!gd54xx->blt.x_count) { - gd54xx->blt.y_count = (gd54xx->blt.y_count + 1) % (gd54xx->blt.height + 1); - if (gd54xx->blt.y_count) - gd54xx->blt.dst_addr_backup = gd54xx->blt.dst_addr + (gd54xx->blt.dst_pitch * gd54xx->blt.y_count * gd54xx->blt.dir); - else { - /* If we're here, the blit is over, reset. */ - gd54xx_reset_blit(gd54xx); - } - /* Stop blitting and request new data if end of line reached. */ - return; - } - } - } + if (!gd54xx->blt.x_count) { + gd54xx->blt.y_count = (gd54xx->blt.y_count + 1) % (gd54xx->blt.height + 1); + if (gd54xx->blt.y_count) + gd54xx->blt.dst_addr_backup = gd54xx->blt.dst_addr + (gd54xx->blt.dst_pitch * gd54xx->blt.y_count * gd54xx->blt.dir); + else { + /* If we're here, the blit is over, reset. */ + gd54xx_reset_blit(gd54xx); + } + /* Stop blitting and request new data if end of line reached. */ + return; + } + } + } } } - static void gd54xx_normal_blit(uint32_t count, gd54xx_t *gd54xx, svga_t *svga) { - uint8_t src = 0, dst; + uint8_t src = 0; + uint8_t dst; uint16_t width = gd54xx->blt.width; - int x_max = 0, shift = 0, mask = 0; + int x_max = 0; + int shift = 0; + int mask = 0; uint32_t src_addr = gd54xx->blt.src_addr; uint32_t dst_addr = gd54xx->blt.dst_addr; @@ -3430,377 +3526,387 @@ gd54xx_normal_blit(uint32_t count, gd54xx_t *gd54xx, svga_t *svga) gd54xx->blt.dst_addr_backup = gd54xx->blt.dst_addr; gd54xx->blt.src_addr_backup = gd54xx->blt.src_addr; gd54xx->blt.height_internal = gd54xx->blt.height; - gd54xx->blt.x_count = 0; - gd54xx->blt.y_count = 0; + gd54xx->blt.x_count = 0; + gd54xx->blt.y_count = 0; while (count) { - src = 0; - mask = 0; + src = 0; + mask = 0; - if (gd54xx->blt.mode & CIRRUS_BLTMODE_COLOREXPAND) { - mask = svga->vram[src_addr & svga->vram_mask] & (0x80 >> (gd54xx->blt.x_count / gd54xx->blt.pixel_width)); - shift = (gd54xx->blt.x_count % gd54xx->blt.pixel_width); - src = gd54xx_color_expand(gd54xx, mask, shift); - } else { - src = svga->vram[src_addr & svga->vram_mask]; - src_addr += gd54xx->blt.dir; - mask = 1; - } - count--; + if (gd54xx->blt.mode & CIRRUS_BLTMODE_COLOREXPAND) { + mask = svga->vram[src_addr & svga->vram_mask] & (0x80 >> (gd54xx->blt.x_count / gd54xx->blt.pixel_width)); + shift = (gd54xx->blt.x_count % gd54xx->blt.pixel_width); + src = gd54xx_color_expand(gd54xx, mask, shift); + } else { + src = svga->vram[src_addr & svga->vram_mask]; + src_addr += gd54xx->blt.dir; + mask = 1; + } + count--; - dst = svga->vram[dst_addr & svga->vram_mask]; - svga->changedvram[(dst_addr & svga->vram_mask) >> 12] = changeframecount; + dst = svga->vram[dst_addr & svga->vram_mask]; + svga->changedvram[(dst_addr & svga->vram_mask) >> 12] = changeframecount; - gd54xx_rop(gd54xx, (uint8_t *) &dst, (uint8_t *) &dst, (const uint8_t *) &src); + gd54xx_rop(gd54xx, &dst, &dst, (const uint8_t *) &src); - if ((gd54xx->blt.mode & CIRRUS_BLTMODE_COLOREXPAND) && (gd54xx->blt.modeext & CIRRUS_BLTMODEEXT_COLOREXPINV)) - mask = !mask; + if ((gd54xx->blt.mode & CIRRUS_BLTMODE_COLOREXPAND) && (gd54xx->blt.modeext & CIRRUS_BLTMODEEXT_COLOREXPINV)) + mask = !mask; - /* This handles 8bpp and 16bpp non-color-expanding transparent comparisons. */ - if ((gd54xx->blt.mode & CIRRUS_BLTMODE_TRANSPARENTCOMP) && !(gd54xx->blt.mode & CIRRUS_BLTMODE_COLOREXPAND) && - ((gd54xx->blt.mode & CIRRUS_BLTMODE_PIXELWIDTHMASK) <= CIRRUS_BLTMODE_PIXELWIDTH16) && - (src != ((gd54xx->blt.trans_mask >> (shift << 3)) & 0xff))) - mask = 0; + /* This handles 8bpp and 16bpp non-color-expanding transparent comparisons. */ + if ((gd54xx->blt.mode & CIRRUS_BLTMODE_TRANSPARENTCOMP) && !(gd54xx->blt.mode & CIRRUS_BLTMODE_COLOREXPAND) && ((gd54xx->blt.mode & CIRRUS_BLTMODE_PIXELWIDTHMASK) <= CIRRUS_BLTMODE_PIXELWIDTH16) && (src != ((gd54xx->blt.trans_mask >> (shift << 3)) & 0xff))) + mask = 0; - if (((gd54xx->blt.width - width) >= gd54xx->blt.pattern_x) && - !((gd54xx->blt.mode & CIRRUS_BLTMODE_TRANSPARENTCOMP) && !mask)) { - svga->vram[dst_addr & svga->vram_mask] = dst; - } + if (((gd54xx->blt.width - width) >= gd54xx->blt.pattern_x) && !((gd54xx->blt.mode & CIRRUS_BLTMODE_TRANSPARENTCOMP) && !mask)) { + svga->vram[dst_addr & svga->vram_mask] = dst; + } - dst_addr += gd54xx->blt.dir; - gd54xx->blt.x_count++; + dst_addr += gd54xx->blt.dir; + gd54xx->blt.x_count++; - if (gd54xx->blt.x_count == x_max) { - gd54xx->blt.x_count = 0; - if (gd54xx->blt.mode & CIRRUS_BLTMODE_COLOREXPAND) - src_addr++; - } + if (gd54xx->blt.x_count == x_max) { + gd54xx->blt.x_count = 0; + if (gd54xx->blt.mode & CIRRUS_BLTMODE_COLOREXPAND) + src_addr++; + } - width--; - if (width == 0xffff) { - width = gd54xx->blt.width; - dst_addr = gd54xx->blt.dst_addr_backup = gd54xx->blt.dst_addr_backup + (gd54xx->blt.dst_pitch * gd54xx->blt.dir); - gd54xx->blt.y_count = (gd54xx->blt.y_count + gd54xx->blt.dir) & 7; + width--; + if (width == 0xffff) { + width = gd54xx->blt.width; + dst_addr = gd54xx->blt.dst_addr_backup = gd54xx->blt.dst_addr_backup + (gd54xx->blt.dst_pitch * gd54xx->blt.dir); + gd54xx->blt.y_count = (gd54xx->blt.y_count + gd54xx->blt.dir) & 7; - if (gd54xx->blt.mode & CIRRUS_BLTMODE_COLOREXPAND) { - if (gd54xx->blt.x_count != 0) - src_addr++; - } else - src_addr = gd54xx->blt.src_addr_backup = gd54xx->blt.src_addr_backup + (gd54xx->blt.src_pitch * gd54xx->blt.dir); + if (gd54xx->blt.mode & CIRRUS_BLTMODE_COLOREXPAND) { + if (gd54xx->blt.x_count != 0) + src_addr++; + } else + src_addr = gd54xx->blt.src_addr_backup = gd54xx->blt.src_addr_backup + (gd54xx->blt.src_pitch * gd54xx->blt.dir); - dst_addr &= svga->vram_mask; - gd54xx->blt.dst_addr_backup &= svga->vram_mask; - src_addr &= svga->vram_mask; - gd54xx->blt.src_addr_backup &= svga->vram_mask; + dst_addr &= svga->vram_mask; + gd54xx->blt.dst_addr_backup &= svga->vram_mask; + src_addr &= svga->vram_mask; + gd54xx->blt.src_addr_backup &= svga->vram_mask; - gd54xx->blt.x_count = 0; + gd54xx->blt.x_count = 0; - gd54xx->blt.height_internal--; - if (gd54xx->blt.height_internal == 0xffff) { - gd54xx_reset_blit(gd54xx); - return; - } - } + gd54xx->blt.height_internal--; + if (gd54xx->blt.height_internal == 0xffff) { + gd54xx_reset_blit(gd54xx); + return; + } + } } /* Count exhausted, stuff still left to blit. */ gd54xx_reset_blit(gd54xx); } - static void gd54xx_mem_sys_dest(uint32_t count, gd54xx_t *gd54xx, svga_t *svga) { gd54xx->blt.ms_is_dest = 1; if (gd54xx->blt.mode & CIRRUS_BLTMODE_PATTERNCOPY) { - fatal("mem sys dest pattern copy not allowed (see 1994 manual)\n"); - gd54xx_reset_blit(gd54xx); + fatal("mem sys dest pattern copy not allowed (see 1994 manual)\n"); + gd54xx_reset_blit(gd54xx); } else if (gd54xx->blt.mode & CIRRUS_BLTMODE_COLOREXPAND) { - fatal("mem sys dest color expand not allowed (see 1994 manual)\n"); - gd54xx_reset_blit(gd54xx); + fatal("mem sys dest color expand not allowed (see 1994 manual)\n"); + gd54xx_reset_blit(gd54xx); } else { - if (count == 0xffffffff) { - gd54xx->blt.dst_addr_backup = gd54xx->blt.dst_addr; - gd54xx->blt.msd_buf_cnt = 0; - gd54xx->blt.src_addr_backup = gd54xx->blt.src_addr; - gd54xx->blt.x_count = gd54xx->blt.xx_count = 0; - gd54xx->blt.y_count = 0; - gd54xx->countminusone = 1; - count = 32; - } + if (count == 0xffffffff) { + gd54xx->blt.dst_addr_backup = gd54xx->blt.dst_addr; + gd54xx->blt.msd_buf_cnt = 0; + gd54xx->blt.src_addr_backup = gd54xx->blt.src_addr; + gd54xx->blt.x_count = gd54xx->blt.xx_count = 0; + gd54xx->blt.y_count = 0; + gd54xx->countminusone = 1; + count = 32; + } - gd54xx->blt.msd_buf_pos = 0; + gd54xx->blt.msd_buf_pos = 0; - while (gd54xx->blt.msd_buf_pos < 32) { - gd54xx->blt.msd_buf[gd54xx->blt.msd_buf_pos & 0x1f] = svga->vram[gd54xx->blt.src_addr_backup & svga->vram_mask]; - gd54xx->blt.src_addr_backup += gd54xx->blt.dir; - gd54xx->blt.msd_buf_pos++; + while (gd54xx->blt.msd_buf_pos < 32) { + gd54xx->blt.msd_buf[gd54xx->blt.msd_buf_pos & 0x1f] = svga->vram[gd54xx->blt.src_addr_backup & svga->vram_mask]; + gd54xx->blt.src_addr_backup += gd54xx->blt.dir; + gd54xx->blt.msd_buf_pos++; - gd54xx->blt.x_count = (gd54xx->blt.x_count + 1) % (gd54xx->blt.width + 1); + gd54xx->blt.x_count = (gd54xx->blt.x_count + 1) % (gd54xx->blt.width + 1); - if (!gd54xx->blt.x_count) { - gd54xx->blt.y_count = (gd54xx->blt.y_count + 1) % (gd54xx->blt.height + 1); + if (!gd54xx->blt.x_count) { + gd54xx->blt.y_count = (gd54xx->blt.y_count + 1) % (gd54xx->blt.height + 1); - if (gd54xx->blt.y_count) - gd54xx->blt.src_addr_backup = gd54xx->blt.src_addr + (gd54xx->blt.src_pitch * gd54xx->blt.y_count * gd54xx->blt.dir); - else - gd54xx->countminusone = 2; /* Signal end of blit. */ - /* End of line reached, stop and notify regardless of how much we already transferred. */ - goto request_more_data; - } - } + if (gd54xx->blt.y_count) + gd54xx->blt.src_addr_backup = gd54xx->blt.src_addr + (gd54xx->blt.src_pitch * gd54xx->blt.y_count * gd54xx->blt.dir); + else + gd54xx->countminusone = 2; /* Signal end of blit. */ + /* End of line reached, stop and notify regardless of how much we already transferred. */ + goto request_more_data; + } + } - /* End of while. */ + /* End of while. */ request_more_data: - /* If the byte count we have blitted are not divisible by 4, round them up. */ - if (gd54xx->blt.msd_buf_pos & 3) - gd54xx->blt.msd_buf_cnt = (gd54xx->blt.msd_buf_pos & ~3) + 4; - else - gd54xx->blt.msd_buf_cnt = gd54xx->blt.msd_buf_pos; - gd54xx->blt.msd_buf_pos = 0; - return; + /* If the byte count we have blitted are not divisible by 4, round them up. */ + if (gd54xx->blt.msd_buf_pos & 3) + gd54xx->blt.msd_buf_cnt = (gd54xx->blt.msd_buf_pos & ~3) + 4; + else + gd54xx->blt.msd_buf_cnt = gd54xx->blt.msd_buf_pos; + gd54xx->blt.msd_buf_pos = 0; + return; } } - -static void +static void gd54xx_start_blit(uint32_t cpu_dat, uint32_t count, gd54xx_t *gd54xx, svga_t *svga) { - if ((gd54xx->blt.mode & CIRRUS_BLTMODE_BACKWARDS) && - !(gd54xx->blt.mode & (CIRRUS_BLTMODE_PATTERNCOPY|CIRRUS_BLTMODE_COLOREXPAND)) && - !(gd54xx->blt.mode & CIRRUS_BLTMODE_TRANSPARENTCOMP)) - gd54xx->blt.dir = -1; + if ((gd54xx->blt.mode & CIRRUS_BLTMODE_BACKWARDS) && !(gd54xx->blt.mode & (CIRRUS_BLTMODE_PATTERNCOPY | CIRRUS_BLTMODE_COLOREXPAND)) && !(gd54xx->blt.mode & CIRRUS_BLTMODE_TRANSPARENTCOMP)) + gd54xx->blt.dir = -1; else - gd54xx->blt.dir = 1; + gd54xx->blt.dir = 1; gd54xx->blt.pixel_width = gd54xx_get_pixel_width(gd54xx); - if (gd54xx->blt.mode & (CIRRUS_BLTMODE_PATTERNCOPY|CIRRUS_BLTMODE_COLOREXPAND)) { - if (gd54xx->blt.pixel_width == 3) - gd54xx->blt.pattern_x = gd54xx->blt.mask & 0x1f; /* (Mask & 0x1f) bytes. */ - else - gd54xx->blt.pattern_x = (gd54xx->blt.mask & 0x07) * gd54xx->blt.pixel_width; /* (Mask & 0x07) pixels. */ + if (gd54xx->blt.mode & (CIRRUS_BLTMODE_PATTERNCOPY | CIRRUS_BLTMODE_COLOREXPAND)) { + if (gd54xx->blt.pixel_width == 3) + gd54xx->blt.pattern_x = gd54xx->blt.mask & 0x1f; /* (Mask & 0x1f) bytes. */ + else + gd54xx->blt.pattern_x = (gd54xx->blt.mask & 0x07) * gd54xx->blt.pixel_width; /* (Mask & 0x07) pixels. */ } else - gd54xx->blt.pattern_x = 0; /* No skip in normal blit mode. */ + gd54xx->blt.pattern_x = 0; /* No skip in normal blit mode. */ if (gd54xx->blt.mode & CIRRUS_BLTMODE_MEMSYSSRC) - gd54xx_mem_sys_src(gd54xx, cpu_dat, count); + gd54xx_mem_sys_src(gd54xx, cpu_dat, count); else if (gd54xx->blt.mode & CIRRUS_BLTMODE_MEMSYSDEST) - gd54xx_mem_sys_dest(count, gd54xx, svga); + gd54xx_mem_sys_dest(count, gd54xx, svga); else if (gd54xx->blt.mode & CIRRUS_BLTMODE_PATTERNCOPY) { - gd54xx_pattern_copy(gd54xx); - gd54xx_reset_blit(gd54xx); + gd54xx_pattern_copy(gd54xx); + gd54xx_reset_blit(gd54xx); } else - gd54xx_normal_blit(count, gd54xx, svga); + gd54xx_normal_blit(count, gd54xx, svga); } - -static uint8_t -cl_pci_read(int func, int addr, void *p) +static uint8_t +cl_pci_read(UNUSED(int func), int addr, void *priv) { - gd54xx_t *gd54xx = (gd54xx_t *)p; - svga_t *svga = &gd54xx->svga; - uint8_t ret = 0x00; + const gd54xx_t *gd54xx = (gd54xx_t *) priv; + const svga_t *svga = &gd54xx->svga; + uint8_t ret = 0x00; if ((addr >= 0x30) && (addr <= 0x33) && (!gd54xx->has_bios)) - ret = 0x00; - else switch (addr) { - case 0x00: - ret = 0x13; /*Cirrus Logic*/ - break; - case 0x01: - ret = 0x10; - break; + ret = 0x00; + else switch (addr) { + case 0x00: + ret = 0x13; /*Cirrus Logic*/ + break; + case 0x01: + ret = 0x10; + break; - case 0x02: - ret = svga->crtc[0x27]; - break; - case 0x03: - ret = 0x00; - break; - - case PCI_REG_COMMAND: - ret = gd54xx->pci_regs[PCI_REG_COMMAND]; /*Respond to IO and memory accesses*/ - break; + case 0x02: + ret = svga->crtc[0x27]; + break; + case 0x03: + ret = 0x00; + break; - case 0x07: - ret = 0x02; /*Fast DEVSEL timing*/ - break; + case PCI_REG_COMMAND: + ret = gd54xx->pci_regs[PCI_REG_COMMAND]; /*Respond to IO and memory accesses*/ + break; - case 0x08: - ret = gd54xx->rev; /*Revision ID*/ - break; - case 0x09: - ret = 0x00; /*Programming interface*/ - break; + case 0x07: + ret = 0x02; /*Fast DEVSEL timing*/ + break; - case 0x0a: - ret = 0x00; /*Supports VGA interface*/ - break; - case 0x0b: - ret = 0x03; - break; + case 0x08: + ret = gd54xx->rev; /*Revision ID*/ + break; + case 0x09: + ret = 0x00; /*Programming interface*/ + break; - case 0x10: - ret = 0x08; /*Linear frame buffer address*/ - break; - case 0x11: - ret = 0x00; - break; - case 0x12: - ret = 0x00; - break; - case 0x13: - ret = gd54xx->lfb_base >> 24; - if (svga->crtc[0x27] == CIRRUS_ID_CLGD5480) - ret = 0xfe; - break; + case 0x0a: + ret = 0x00; /*Supports VGA interface*/ + break; + case 0x0b: + ret = 0x03; + break; - case 0x14: - ret = 0x00; /*PCI VGA/BitBLT Register Base Address*/ - break; - case 0x15: - ret = (svga->crtc[0x27] == CIRRUS_ID_CLGD5480) ? ((gd54xx->vgablt_base >> 8) & 0xf0) : 0x00; - break; - case 0x16: - ret = (svga->crtc[0x27] == CIRRUS_ID_CLGD5480) ? ((gd54xx->vgablt_base >> 16) & 0xff) : 0x00; - break; - case 0x17: - ret = (svga->crtc[0x27] == CIRRUS_ID_CLGD5480) ? ((gd54xx->vgablt_base >> 24) & 0xff) : 0x00; - break; + case 0x10: + ret = 0x08; /*Linear frame buffer address*/ + break; + case 0x11: + ret = 0x00; + break; + case 0x12: + ret = 0x00; + break; + case 0x13: + ret = gd54xx->lfb_base >> 24; + if (svga->crtc[0x27] == CIRRUS_ID_CLGD5480) + ret &= 0xfe; + break; - case 0x30: - ret = (gd54xx->pci_regs[0x30] & 0x01); /*BIOS ROM address*/ - break; - case 0x31: - ret = 0x00; - break; - case 0x32: - ret = gd54xx->pci_regs[0x32]; - break; - case 0x33: - ret = gd54xx->pci_regs[0x33]; - break; + case 0x14: + ret = 0x00; /*PCI VGA/BitBLT Register Base Address*/ + break; + case 0x15: + ret = (svga->crtc[0x27] == CIRRUS_ID_CLGD5480) ? ((gd54xx->vgablt_base >> 8) & 0xf0) : 0x00; + break; + case 0x16: + ret = (svga->crtc[0x27] == CIRRUS_ID_CLGD5480) ? ((gd54xx->vgablt_base >> 16) & 0xff) : 0x00; + break; + case 0x17: + ret = (svga->crtc[0x27] == CIRRUS_ID_CLGD5480) ? ((gd54xx->vgablt_base >> 24) & 0xff) : 0x00; + break; - case 0x3c: - ret = gd54xx->int_line; - break; - case 0x3d: - ret = PCI_INTA; - break; + case 0x30: + ret = (gd54xx->pci_regs[0x30] & 0x01); /*BIOS ROM address*/ + break; + case 0x31: + ret = 0x00; + break; + case 0x32: + ret = gd54xx->pci_regs[0x32]; + break; + case 0x33: + ret = gd54xx->pci_regs[0x33]; + break; + + case 0x3c: + ret = gd54xx->int_line; + break; + case 0x3d: + ret = PCI_INTA; + break; + + default: + break; } return ret; } - -static void -cl_pci_write(int func, int addr, uint8_t val, void *p) +static void +cl_pci_write(UNUSED(int func), int addr, uint8_t val, void *priv) { - gd54xx_t *gd54xx = (gd54xx_t *)p; - svga_t *svga = &gd54xx->svga; - uint32_t byte; + gd54xx_t *gd54xx = (gd54xx_t *) priv; + const svga_t *svga = &gd54xx->svga; + uint32_t byte; if ((addr >= 0x30) && (addr <= 0x33) && (!gd54xx->has_bios)) - return; + return; switch (addr) { - case PCI_REG_COMMAND: - gd54xx->pci_regs[PCI_REG_COMMAND] = val & 0x23; - mem_mapping_disable(&gd54xx->vgablt_mapping); - io_removehandler(0x03c0, 0x0020, gd54xx_in, NULL, NULL, gd54xx_out, NULL, NULL, gd54xx); - if (val & PCI_COMMAND_IO) - io_sethandler(0x03c0, 0x0020, gd54xx_in, NULL, NULL, gd54xx_out, NULL, NULL, gd54xx); - if ((val & PCI_COMMAND_MEM) && (gd54xx->vgablt_base != 0x00000000) && (gd54xx->vgablt_base < 0xfff00000)) - mem_mapping_set_addr(&gd54xx->vgablt_mapping, gd54xx->vgablt_base, 0x1000); - gd543x_recalc_mapping(gd54xx); - break; + case PCI_REG_COMMAND: + gd54xx->pci_regs[PCI_REG_COMMAND] = val & 0x23; + mem_mapping_disable(&gd54xx->vgablt_mapping); + io_removehandler(0x03c0, 0x0020, gd54xx_in, NULL, NULL, gd54xx_out, NULL, NULL, gd54xx); + if (val & PCI_COMMAND_IO) + io_sethandler(0x03c0, 0x0020, gd54xx_in, NULL, NULL, gd54xx_out, NULL, NULL, gd54xx); + if ((val & PCI_COMMAND_MEM) && (gd54xx->vgablt_base != 0x00000000) && (gd54xx->vgablt_base < 0xfff00000)) + mem_mapping_set_addr(&gd54xx->vgablt_mapping, gd54xx->vgablt_base, 0x1000); + if ((gd54xx->pci_regs[PCI_REG_COMMAND] & PCI_COMMAND_MEM) && (gd54xx->pci_regs[0x30] & 0x01)) { + uint32_t addr = (gd54xx->pci_regs[0x32] << 16) | (gd54xx->pci_regs[0x33] << 24); + mem_mapping_set_addr(&gd54xx->bios_rom.mapping, addr, 0x8000); + } else + mem_mapping_disable(&gd54xx->bios_rom.mapping); + gd543x_recalc_mapping(gd54xx); + break; - case 0x13: - /* 5480, like 5446 rev. B, has a 32 MB aperture, with the second set used for - BitBLT transfers. */ - if (svga->crtc[0x27] == CIRRUS_ID_CLGD5480) - val &= 0xfe; - gd54xx->lfb_base = val << 24; - gd543x_recalc_mapping(gd54xx); - break; + case 0x13: + /* 5480, like 5446 rev. B, has a 32 MB aperture, with the second set used for + BitBLT transfers. */ + if (svga->crtc[0x27] == CIRRUS_ID_CLGD5480) + val &= 0xfe; + gd54xx->lfb_base = val << 24; + gd543x_recalc_mapping(gd54xx); + break; - case 0x15: case 0x16: case 0x17: - if (svga->crtc[0x27] != CIRRUS_ID_CLGD5480) - return; - byte = (addr & 3) << 3; - gd54xx->vgablt_base &= ~(0xff << byte); - if (addr == 0x15) - val &= 0xf0; - gd54xx->vgablt_base |= (val << byte); - mem_mapping_disable(&gd54xx->vgablt_mapping); - if ((gd54xx->pci_regs[PCI_REG_COMMAND] & PCI_COMMAND_MEM) && (gd54xx->vgablt_base != 0x00000000) && (gd54xx->vgablt_base < 0xfff00000)) - mem_mapping_set_addr(&gd54xx->vgablt_mapping, gd54xx->vgablt_base, 0x1000); - break; + case 0x15: + case 0x16: + case 0x17: + if (svga->crtc[0x27] != CIRRUS_ID_CLGD5480) + return; + byte = (addr & 3) << 3; + gd54xx->vgablt_base &= ~(0xff << byte); + if (addr == 0x15) + val &= 0xf0; + gd54xx->vgablt_base |= (val << byte); + mem_mapping_disable(&gd54xx->vgablt_mapping); + if ((gd54xx->pci_regs[PCI_REG_COMMAND] & PCI_COMMAND_MEM) && (gd54xx->vgablt_base != 0x00000000) && (gd54xx->vgablt_base < 0xfff00000)) + mem_mapping_set_addr(&gd54xx->vgablt_mapping, gd54xx->vgablt_base, 0x1000); + break; - case 0x30: case 0x32: case 0x33: - gd54xx->pci_regs[addr] = val; - if (gd54xx->pci_regs[0x30] & 0x01) { - uint32_t addr = (gd54xx->pci_regs[0x32] << 16) | (gd54xx->pci_regs[0x33] << 24); - mem_mapping_set_addr(&gd54xx->bios_rom.mapping, addr, 0x8000); - } else - mem_mapping_disable(&gd54xx->bios_rom.mapping); - return; + case 0x30: + case 0x32: + case 0x33: + gd54xx->pci_regs[addr] = val; + if ((gd54xx->pci_regs[PCI_REG_COMMAND] & PCI_COMMAND_MEM) && (gd54xx->pci_regs[0x30] & 0x01)) { + uint32_t addr = (gd54xx->pci_regs[0x32] << 16) | (gd54xx->pci_regs[0x33] << 24); + mem_mapping_set_addr(&gd54xx->bios_rom.mapping, addr, 0x8000); + } else + mem_mapping_disable(&gd54xx->bios_rom.mapping); + return; - case 0x3c: - gd54xx->int_line = val; - return; + case 0x3c: + gd54xx->int_line = val; + return; + + default: + break; } } -static uint8_t -gd5428_mca_read(int port, void *p) +static uint8_t +gd5428_mca_read(int port, void *priv) { - gd54xx_t *gd54xx = (gd54xx_t *)p; - - return gd54xx->pos_regs[port & 7]; + const gd54xx_t *gd54xx = (gd54xx_t *) priv; + + return gd54xx->pos_regs[port & 7]; } -static void -gd5428_mca_write(int port, uint8_t val, void *p) +static void +gd5428_mca_write(int port, uint8_t val, void *priv) { - gd54xx_t *gd54xx = (gd54xx_t *)p; + gd54xx_t *gd54xx = (gd54xx_t *) priv; - if (port < 0x102) - return; - - gd54xx->pos_regs[port & 7] = val; - gd543x_recalc_mapping(gd54xx); + if (port < 0x102) + return; + + gd54xx->pos_regs[port & 7] = val; + mem_mapping_disable(&gd54xx->bios_rom.mapping); + if (gd54xx->pos_regs[2] & 0x01) + mem_mapping_enable(&gd54xx->bios_rom.mapping); } -static uint8_t -gd5428_mca_feedb(void *p) +static uint8_t +gd5428_mca_feedb(void *priv) { - return 1; + const gd54xx_t *gd54xx = (gd54xx_t *) priv; + + return gd54xx->pos_regs[2] & 0x01; } static void gd54xx_reset(void *priv) { gd54xx_t *gd54xx = (gd54xx_t *) priv; - svga_t *svga = &gd54xx->svga; + svga_t *svga = &gd54xx->svga; memset(svga->crtc, 0x00, sizeof(svga->crtc)); memset(svga->seqregs, 0x00, sizeof(svga->seqregs)); memset(svga->gdcreg, 0x00, sizeof(svga->gdcreg)); - svga->crtc[0] = 63; - svga->crtc[6] = 255; - svga->dispontime = 1000ull << 32; - svga->dispofftime = 1000ull << 32; - svga->bpp = 8; + svga->crtc[0] = 63; + svga->crtc[6] = 255; + svga->dispontime = 1000ULL << 32; + svga->dispofftime = 1000ULL << 32; + svga->bpp = 8; io_removehandler(0x03c0, 0x0020, gd54xx_in, NULL, NULL, gd54xx_out, NULL, NULL, gd54xx); io_sethandler(0x03c0, 0x0020, gd54xx_in, NULL, NULL, gd54xx_out, NULL, NULL, gd54xx); mem_mapping_disable(&gd54xx->vgablt_mapping); - if (gd54xx->has_bios && gd54xx->pci) - mem_mapping_disable(&gd54xx->bios_rom.mapping); + if (gd54xx->has_bios && (gd54xx->pci || gd54xx->mca)) + mem_mapping_disable(&gd54xx->bios_rom.mapping); memset(gd54xx->pci_regs, 0x00, 256); @@ -3816,23 +3922,23 @@ gd54xx_reset(void *priv) svga->hwcursor.yoff = svga->hwcursor.xoff = 0; if (gd54xx->id >= CIRRUS_ID_CLGD5420) { - gd54xx->vclk_n[0] = 0x4a; - gd54xx->vclk_d[0] = 0x2b; - gd54xx->vclk_n[1] = 0x5b; - gd54xx->vclk_d[1] = 0x2f; - gd54xx->vclk_n[2] = 0x45; - gd54xx->vclk_d[2] = 0x30; - gd54xx->vclk_n[3] = 0x7e; - gd54xx->vclk_d[3] = 0x33; + gd54xx->vclk_n[0] = 0x4a; + gd54xx->vclk_d[0] = 0x2b; + gd54xx->vclk_n[1] = 0x5b; + gd54xx->vclk_d[1] = 0x2f; + gd54xx->vclk_n[2] = 0x45; + gd54xx->vclk_d[2] = 0x30; + gd54xx->vclk_n[3] = 0x7e; + gd54xx->vclk_d[3] = 0x33; } else { - gd54xx->vclk_n[0] = 0x66; - gd54xx->vclk_d[0] = 0x3b; - gd54xx->vclk_n[1] = 0x5b; - gd54xx->vclk_d[1] = 0x2f; - gd54xx->vclk_n[2] = 0x45; - gd54xx->vclk_d[2] = 0x2c; - gd54xx->vclk_n[3] = 0x7e; - gd54xx->vclk_d[3] = 0x33; + gd54xx->vclk_n[0] = 0x66; + gd54xx->vclk_d[0] = 0x3b; + gd54xx->vclk_n[1] = 0x5b; + gd54xx->vclk_d[1] = 0x2f; + gd54xx->vclk_n[2] = 0x45; + gd54xx->vclk_d[2] = 0x2c; + gd54xx->vclk_n[3] = 0x7e; + gd54xx->vclk_d[3] = 0x33; } svga->extra_banks[1] = 0x8000; @@ -3847,228 +3953,255 @@ gd54xx_reset(void *priv) svga->seqregs[6] = 0x0f; if (svga->crtc[0x27] >= CIRRUS_ID_CLGD5429) - gd54xx->unlocked = 1; + gd54xx->unlocked = 1; else - gd54xx->unlocked = 0; + gd54xx->unlocked = 0; } - -static void -*gd54xx_init(const device_t *info) +static void * +gd54xx_init(const device_t *info) { - gd54xx_t *gd54xx = malloc(sizeof(gd54xx_t)); - svga_t *svga = &gd54xx->svga; - int id = info->local & 0xff; - int vram; - char *romfn = NULL; + gd54xx_t *gd54xx = malloc(sizeof(gd54xx_t)); + svga_t *svga = &gd54xx->svga; + int id = info->local & 0xff; + int vram; + const char *romfn = NULL; + const char *romfn1 = NULL; + const char *romfn2 = NULL; + memset(gd54xx, 0, sizeof(gd54xx_t)); - gd54xx->pci = !!(info->flags & DEVICE_PCI); - gd54xx->vlb = !!(info->flags & DEVICE_VLB); - gd54xx->mca = !!(info->flags & DEVICE_MCA); + gd54xx->pci = !!(info->flags & DEVICE_PCI); + gd54xx->vlb = !!(info->flags & DEVICE_VLB); + gd54xx->mca = !!(info->flags & DEVICE_MCA); gd54xx->bit32 = gd54xx->pci || gd54xx->vlb; - gd54xx->rev = 0; + gd54xx->rev = 0; gd54xx->has_bios = 1; gd54xx->id = id; - switch (id) { - case CIRRUS_ID_CLGD5401: - romfn = BIOS_GD5401_PATH; - break; - - case CIRRUS_ID_CLGD5402: - if (info->local & 0x200) - romfn = BIOS_GD5402_ONBOARD_PATH; - else - romfn = BIOS_GD5402_PATH; - break; + switch (id) { + case CIRRUS_ID_CLGD5401: + romfn = BIOS_GD5401_PATH; + break; - case CIRRUS_ID_CLGD5420: - romfn = BIOS_GD5420_PATH; - break; + case CIRRUS_ID_CLGD5402: + if (info->local & 0x200) + romfn = BIOS_GD5402_ONBOARD_PATH; + else + romfn = BIOS_GD5402_PATH; + break; - case CIRRUS_ID_CLGD5422: - case CIRRUS_ID_CLGD5424: - romfn = BIOS_GD5422_PATH; - break; + case CIRRUS_ID_CLGD5420: + romfn = BIOS_GD5420_PATH; + break; - case CIRRUS_ID_CLGD5426: - if (info->local & 0x200) - romfn = NULL; - else { - if (info->local & 0x100) - romfn = BIOS_GD5426_DIAMOND_A1_ISA_PATH; - else { - if (gd54xx->vlb) - romfn = BIOS_GD5428_PATH; - else - romfn = BIOS_GD5428_ISA_PATH; - } - } - break; + case CIRRUS_ID_CLGD5422: + case CIRRUS_ID_CLGD5424: + romfn = BIOS_GD5422_PATH; + break; - case CIRRUS_ID_CLGD5428: - if (info->local & 0x100) - romfn = BIOS_GD5428_DIAMOND_B1_VLB_PATH; - else { - if (gd54xx->vlb) - romfn = BIOS_GD5428_PATH; - else if (gd54xx->mca) - romfn = BIOS_GD5428_MCA_PATH; - else - romfn = BIOS_GD5428_ISA_PATH; - } - break; + case CIRRUS_ID_CLGD5426: + if (info->local & 0x200) + romfn = NULL; + else { + if (info->local & 0x100) + romfn = BIOS_GD5426_DIAMOND_A1_ISA_PATH; + else { + if (gd54xx->vlb) + romfn = BIOS_GD5428_PATH; + else if (gd54xx->mca) + romfn = BIOS_GD5426_MCA_PATH; + else + romfn = BIOS_GD5428_ISA_PATH; + } + } + break; - case CIRRUS_ID_CLGD5429: - romfn = BIOS_GD5429_PATH; - break; + case CIRRUS_ID_CLGD5428: + if (info->local & 0x100) + if (gd54xx->vlb) + romfn = BIOS_GD5428_DIAMOND_B1_VLB_PATH; + else { + romfn1 = BIOS_GD5428_BOCA_ISA_PATH_1; + romfn2 = BIOS_GD5428_BOCA_ISA_PATH_2; + } + else { + if (gd54xx->vlb) + romfn = BIOS_GD5428_PATH; + else if (gd54xx->mca) + romfn = BIOS_GD5428_MCA_PATH; + else + romfn = BIOS_GD5428_ISA_PATH; + } + break; - case CIRRUS_ID_CLGD5432: - case CIRRUS_ID_CLGD5434_4: - if (info->local & 0x200) { - romfn = NULL; - gd54xx->has_bios = 0; - } - break; + case CIRRUS_ID_CLGD5429: + romfn = BIOS_GD5429_PATH; + break; - case CIRRUS_ID_CLGD5434: - if (info->local & 0x200) { - romfn = NULL; - gd54xx->has_bios = 0; - } else { - if (info->local & 0x100) - romfn = BIOS_GD5434_DIAMOND_A3_ISA_PATH; - else - romfn = BIOS_GD5434_PATH; - } - break; + case CIRRUS_ID_CLGD5432: + case CIRRUS_ID_CLGD5434_4: + if (info->local & 0x200) { + romfn = NULL; + gd54xx->has_bios = 0; + } + break; - case CIRRUS_ID_CLGD5436: - romfn = BIOS_GD5436_PATH; - break; + case CIRRUS_ID_CLGD5434: + if (info->local & 0x200) { + romfn = NULL; + gd54xx->has_bios = 0; + } else if (gd54xx->vlb) { + romfn = BIOS_GD5430_ORCHID_VLB_PATH; + } else { + if (info->local & 0x100) + romfn = BIOS_GD5434_DIAMOND_A3_ISA_PATH; + else + romfn = BIOS_GD5434_PATH; + } + break; - case CIRRUS_ID_CLGD5430: - if (info->local & 0x400) { - /* CL-GD 5440 */ - gd54xx->rev = 0x47; - if (info->local & 0x200) { - romfn = NULL; - gd54xx->has_bios = 0; - } else - romfn = BIOS_GD5440_PATH; - } else { - /* CL-GD 5430 */ - if (info->local & 0x200) { - romfn = NULL; - gd54xx->has_bios = 0; - } else if (gd54xx->pci) - romfn = BIOS_GD5430_PATH; - else - romfn = BIOS_GD5430_DIAMOND_A8_VLB_PATH; - } - break; + case CIRRUS_ID_CLGD5436: + romfn = BIOS_GD5436_PATH; + break; - case CIRRUS_ID_CLGD5446: - if (info->local & 0x100) - romfn = BIOS_GD5446_STB_PATH; - else - romfn = BIOS_GD5446_PATH; - break; + case CIRRUS_ID_CLGD5430: + if (info->local & 0x400) { + /* CL-GD 5440 */ + gd54xx->rev = 0x47; + if (info->local & 0x200) { + romfn = NULL; + gd54xx->has_bios = 0; + } else + romfn = BIOS_GD5440_PATH; + } else { + /* CL-GD 5430 */ + if (info->local & 0x200) { + romfn = NULL; + gd54xx->has_bios = 0; + } else if (gd54xx->pci) + romfn = BIOS_GD5430_PATH; + else if ((gd54xx->vlb) && (info->local & 0x100)) + romfn = BIOS_GD5430_ORCHID_VLB_PATH; + else + romfn = BIOS_GD5430_DIAMOND_A8_VLB_PATH; + } + break; - case CIRRUS_ID_CLGD5480: - romfn = BIOS_GD5480_PATH; - break; + case CIRRUS_ID_CLGD5446: + if (info->local & 0x100) + romfn = BIOS_GD5446_STB_PATH; + else + romfn = BIOS_GD5446_PATH; + break; + + case CIRRUS_ID_CLGD5480: + romfn = BIOS_GD5480_PATH; + break; + + default: + break; } - + if (info->flags & DEVICE_MCA) { - vram = 1024; - gd54xx->vram_size = vram << 10; + if (id == CIRRUS_ID_CLGD5428) + vram = 1024; + else + vram = device_get_config_int("memory"); + gd54xx->vram_size = vram << 10; } else { - if (id <= CIRRUS_ID_CLGD5428) { - if ((id == CIRRUS_ID_CLGD5426) && (info->local & 0x200)) - vram = 1024; - else if (id == CIRRUS_ID_CLGD5401) - vram = 256; - else if (id == CIRRUS_ID_CLGD5402) - vram = 512; - else - vram = device_get_config_int("memory"); - gd54xx->vram_size = vram << 10; - } else { - vram = device_get_config_int("memory"); - gd54xx->vram_size = vram << 20; - } + if (id <= CIRRUS_ID_CLGD5428) { + if ((id == CIRRUS_ID_CLGD5426) && (info->local & 0x200)) + vram = 1024; + else if (id == CIRRUS_ID_CLGD5401) + vram = 256; + else if (id == CIRRUS_ID_CLGD5402) + vram = 512; + else + vram = device_get_config_int("memory"); + gd54xx->vram_size = vram << 10; + } else { + vram = device_get_config_int("memory"); + gd54xx->vram_size = vram << 20; + } } gd54xx->vram_mask = gd54xx->vram_size - 1; if (romfn) - rom_init(&gd54xx->bios_rom, romfn, 0xc0000, 0x8000, 0x7fff, 0, MEM_MAPPING_EXTERNAL); + rom_init(&gd54xx->bios_rom, romfn, 0xc0000, 0x8000, 0x7fff, 0, MEM_MAPPING_EXTERNAL); + else if (romfn1 && romfn2) + rom_init_interleaved(&gd54xx->bios_rom, BIOS_GD5428_BOCA_ISA_PATH_1, BIOS_GD5428_BOCA_ISA_PATH_2, 0xc0000, + 0x8000, 0x7fff, 0, MEM_MAPPING_EXTERNAL); if (info->flags & DEVICE_ISA) - video_inform(VIDEO_FLAG_TYPE_SPECIAL, &timing_gd54xx_isa); + video_inform(VIDEO_FLAG_TYPE_SPECIAL, &timing_gd54xx_isa); else if (info->flags & DEVICE_PCI) - video_inform(VIDEO_FLAG_TYPE_SPECIAL, &timing_gd54xx_pci); + video_inform(VIDEO_FLAG_TYPE_SPECIAL, &timing_gd54xx_pci); else - video_inform(VIDEO_FLAG_TYPE_SPECIAL, &timing_gd54xx_vlb); + video_inform(VIDEO_FLAG_TYPE_SPECIAL, &timing_gd54xx_vlb); if (id >= CIRRUS_ID_CLGD5426) { - svga_init(info, &gd54xx->svga, gd54xx, gd54xx->vram_size, - gd54xx_recalctimings, gd54xx_in, gd54xx_out, - gd54xx_hwcursor_draw, gd54xx_overlay_draw); + svga_init(info, &gd54xx->svga, gd54xx, gd54xx->vram_size, + gd54xx_recalctimings, gd54xx_in, gd54xx_out, + gd54xx_hwcursor_draw, gd54xx_overlay_draw); } else { - svga_init(info, &gd54xx->svga, gd54xx, gd54xx->vram_size, - gd54xx_recalctimings, gd54xx_in, gd54xx_out, - gd54xx_hwcursor_draw, NULL); + svga_init(info, &gd54xx->svga, gd54xx, gd54xx->vram_size, + gd54xx_recalctimings, gd54xx_in, gd54xx_out, + gd54xx_hwcursor_draw, NULL); } svga->vblank_start = gd54xx_vblank_start; - svga->ven_write = gd54xx_write_modes45; - if ((vram == 1) || (vram >= 256 && vram <= 1024)) - svga->decode_mask = gd54xx->vram_mask; + svga->ven_write = gd54xx_write_modes45; + if ((vram == 1) || (vram >= 256 && vram <= 1024)) + svga->decode_mask = gd54xx->vram_mask; if (gd54xx->bit32) { - mem_mapping_set_handler(&svga->mapping, gd54xx_read, gd54xx_readw, gd54xx_readl, gd54xx_write, gd54xx_writew, gd54xx_writel); - mem_mapping_add(&gd54xx->mmio_mapping, 0, 0, - gd543x_mmio_read, gd543x_mmio_readw, gd543x_mmio_readl, - gd543x_mmio_writeb, gd543x_mmio_writew, gd543x_mmio_writel, - NULL, MEM_MAPPING_EXTERNAL, gd54xx); - mem_mapping_add(&gd54xx->linear_mapping, 0, 0, - gd54xx_readb_linear, gd54xx_readw_linear, gd54xx_readl_linear, - gd54xx_writeb_linear, gd54xx_writew_linear, gd54xx_writel_linear, - NULL, MEM_MAPPING_EXTERNAL, gd54xx); - mem_mapping_add(&gd54xx->aperture2_mapping, 0, 0, - gd5436_aperture2_readb, gd5436_aperture2_readw, gd5436_aperture2_readl, - gd5436_aperture2_writeb, gd5436_aperture2_writew, gd5436_aperture2_writel, - NULL, MEM_MAPPING_EXTERNAL, gd54xx); - mem_mapping_add(&gd54xx->vgablt_mapping, 0, 0, - gd5480_vgablt_read, gd5480_vgablt_readw, gd5480_vgablt_readl, - gd5480_vgablt_write, gd5480_vgablt_writew, gd5480_vgablt_writel, - NULL, MEM_MAPPING_EXTERNAL, gd54xx); + mem_mapping_set_handler(&svga->mapping, gd54xx_read, gd54xx_readw, gd54xx_readl, gd54xx_write, gd54xx_writew, gd54xx_writel); + mem_mapping_add(&gd54xx->mmio_mapping, 0, 0, + gd543x_mmio_read, gd543x_mmio_readw, gd543x_mmio_readl, + gd543x_mmio_writeb, gd543x_mmio_writew, gd543x_mmio_writel, + NULL, MEM_MAPPING_EXTERNAL, gd54xx); + mem_mapping_add(&gd54xx->linear_mapping, 0, 0, + gd54xx_readb_linear, gd54xx_readw_linear, gd54xx_readl_linear, + gd54xx_writeb_linear, gd54xx_writew_linear, gd54xx_writel_linear, + NULL, MEM_MAPPING_EXTERNAL, gd54xx); + mem_mapping_add(&gd54xx->aperture2_mapping, 0, 0, + gd5436_aperture2_readb, gd5436_aperture2_readw, gd5436_aperture2_readl, + gd5436_aperture2_writeb, gd5436_aperture2_writew, gd5436_aperture2_writel, + NULL, MEM_MAPPING_EXTERNAL, gd54xx); + mem_mapping_add(&gd54xx->vgablt_mapping, 0, 0, + gd5480_vgablt_read, gd5480_vgablt_readw, gd5480_vgablt_readl, + gd5480_vgablt_write, gd5480_vgablt_writew, gd5480_vgablt_writel, + NULL, MEM_MAPPING_EXTERNAL, gd54xx); } else { - mem_mapping_set_handler(&svga->mapping, gd54xx_read, gd54xx_readw, NULL, gd54xx_write, gd54xx_writew, NULL); - mem_mapping_add(&gd54xx->mmio_mapping, 0, 0, - gd543x_mmio_read, gd543x_mmio_readw, NULL, - gd543x_mmio_writeb, gd543x_mmio_writew, NULL, - NULL, MEM_MAPPING_EXTERNAL, gd54xx); - mem_mapping_add(&gd54xx->linear_mapping, 0, 0, - gd54xx_readb_linear, gd54xx_readw_linear, NULL, - gd54xx_writeb_linear, gd54xx_writew_linear, NULL, - NULL, MEM_MAPPING_EXTERNAL, gd54xx); - mem_mapping_add(&gd54xx->aperture2_mapping, 0, 0, - gd5436_aperture2_readb, gd5436_aperture2_readw, NULL, - gd5436_aperture2_writeb, gd5436_aperture2_writew, NULL, - NULL, MEM_MAPPING_EXTERNAL, gd54xx); - mem_mapping_add(&gd54xx->vgablt_mapping, 0, 0, - gd5480_vgablt_read, gd5480_vgablt_readw, NULL, - gd5480_vgablt_write, gd5480_vgablt_writew, NULL, - NULL, MEM_MAPPING_EXTERNAL, gd54xx); + mem_mapping_set_handler(&svga->mapping, gd54xx_read, gd54xx_readw, NULL, gd54xx_write, gd54xx_writew, NULL); + mem_mapping_add(&gd54xx->mmio_mapping, 0, 0, + gd543x_mmio_read, gd543x_mmio_readw, NULL, + gd543x_mmio_writeb, gd543x_mmio_writew, NULL, + NULL, MEM_MAPPING_EXTERNAL, gd54xx); + mem_mapping_add(&gd54xx->linear_mapping, 0, 0, + gd54xx_readb_linear, gd54xx_readw_linear, NULL, + gd54xx_writeb_linear, gd54xx_writew_linear, NULL, + NULL, MEM_MAPPING_EXTERNAL, gd54xx); + mem_mapping_add(&gd54xx->aperture2_mapping, 0, 0, + gd5436_aperture2_readb, gd5436_aperture2_readw, NULL, + gd5436_aperture2_writeb, gd5436_aperture2_writew, NULL, + NULL, MEM_MAPPING_EXTERNAL, gd54xx); + mem_mapping_add(&gd54xx->vgablt_mapping, 0, 0, + gd5480_vgablt_read, gd5480_vgablt_readw, NULL, + gd5480_vgablt_write, gd5480_vgablt_writew, NULL, + NULL, MEM_MAPPING_EXTERNAL, gd54xx); } io_sethandler(0x03c0, 0x0020, gd54xx_in, NULL, NULL, gd54xx_out, NULL, NULL, gd54xx); - - if (gd54xx->pci && id >= CIRRUS_ID_CLGD5430) - pci_add_card(PCI_ADD_VIDEO, cl_pci_read, cl_pci_write, gd54xx); + + if (gd54xx->pci && id >= CIRRUS_ID_CLGD5430) { + if (romfn == NULL) + pci_add_card(PCI_ADD_VIDEO, cl_pci_read, cl_pci_write, gd54xx, &gd54xx->pci_slot); + else + pci_add_card(PCI_ADD_NORMAL, cl_pci_read, cl_pci_write, gd54xx, &gd54xx->pci_slot); + mem_mapping_disable(&gd54xx->bios_rom.mapping); + } mem_mapping_set_p(&svga->mapping, gd54xx); mem_mapping_disable(&gd54xx->mmio_mapping); @@ -4079,23 +4212,23 @@ static void svga->hwcursor.yoff = svga->hwcursor.xoff = 0; if (id >= CIRRUS_ID_CLGD5420) { - gd54xx->vclk_n[0] = 0x4a; - gd54xx->vclk_d[0] = 0x2b; - gd54xx->vclk_n[1] = 0x5b; - gd54xx->vclk_d[1] = 0x2f; - gd54xx->vclk_n[2] = 0x45; - gd54xx->vclk_d[2] = 0x30; - gd54xx->vclk_n[3] = 0x7e; - gd54xx->vclk_d[3] = 0x33; + gd54xx->vclk_n[0] = 0x4a; + gd54xx->vclk_d[0] = 0x2b; + gd54xx->vclk_n[1] = 0x5b; + gd54xx->vclk_d[1] = 0x2f; + gd54xx->vclk_n[2] = 0x45; + gd54xx->vclk_d[2] = 0x30; + gd54xx->vclk_n[3] = 0x7e; + gd54xx->vclk_d[3] = 0x33; } else { - gd54xx->vclk_n[0] = 0x66; - gd54xx->vclk_d[0] = 0x3b; - gd54xx->vclk_n[1] = 0x5b; - gd54xx->vclk_d[1] = 0x2f; - gd54xx->vclk_n[2] = 0x45; - gd54xx->vclk_d[2] = 0x2c; - gd54xx->vclk_n[3] = 0x7e; - gd54xx->vclk_d[3] = 0x33; + gd54xx->vclk_n[0] = 0x66; + gd54xx->vclk_d[0] = 0x3b; + gd54xx->vclk_n[1] = 0x5b; + gd54xx->vclk_d[1] = 0x2f; + gd54xx->vclk_n[2] = 0x45; + gd54xx->vclk_d[2] = 0x2c; + gd54xx->vclk_n[3] = 0x7e; + gd54xx->vclk_d[3] = 0x33; } svga->extra_banks[1] = 0x8000; @@ -4109,26 +4242,27 @@ static void svga->crtc[0x27] = id; svga->seqregs[6] = 0x0f; - + if (svga->crtc[0x27] >= CIRRUS_ID_CLGD5429) - gd54xx->unlocked = 1; + gd54xx->unlocked = 1; if (gd54xx->mca) { - gd54xx->pos_regs[0] = 0x7b; - gd54xx->pos_regs[1] = 0x91; - mca_add(gd5428_mca_read, gd5428_mca_write, gd5428_mca_feedb, NULL, gd54xx); - io_sethandler(0x46e8, 0x0001, gd54xx_in, NULL, NULL, gd54xx_out, NULL, NULL, gd54xx); + gd54xx->pos_regs[0] = svga->crtc[0x27] == CIRRUS_ID_CLGD5426 ? 0x82 : 0x7b; + gd54xx->pos_regs[1] = svga->crtc[0x27] == CIRRUS_ID_CLGD5426 ? 0x81 : 0x91; + mem_mapping_disable(&gd54xx->bios_rom.mapping); + mca_add(gd5428_mca_read, gd5428_mca_write, gd5428_mca_feedb, NULL, gd54xx); + io_sethandler(0x46e8, 0x0001, gd54xx_in, NULL, NULL, gd54xx_out, NULL, NULL, gd54xx); } if (gd54xx_is_5434(svga)) { - gd54xx->i2c = i2c_gpio_init("ddc_cl54xx"); - gd54xx->ddc = ddc_init(i2c_gpio_get_bus(gd54xx->i2c)); + gd54xx->i2c = i2c_gpio_init("ddc_cl54xx"); + gd54xx->ddc = ddc_init(i2c_gpio_get_bus(gd54xx->i2c)); } if (svga->crtc[0x27] >= CIRRUS_ID_CLGD5446) - gd54xx->crtcreg_mask = 0x7f; + gd54xx->crtcreg_mask = 0x7f; else - gd54xx->crtcreg_mask = 0x3f; + gd54xx->crtcreg_mask = 0x3f; gd54xx->overlay.colorkeycompare = 0xff; @@ -4177,12 +4311,24 @@ gd5428_diamond_b1_available(void) return rom_present(BIOS_GD5428_DIAMOND_B1_VLB_PATH); } +static int +gd5428_boca_isa_available(void) +{ + return rom_present(BIOS_GD5428_BOCA_ISA_PATH_1) && rom_present(BIOS_GD5428_BOCA_ISA_PATH_2); +} + static int gd5428_isa_available(void) { return rom_present(BIOS_GD5428_ISA_PATH); } +static int +gd5426_mca_available(void) +{ + return rom_present(BIOS_GD5426_MCA_PATH); +} + static int gd5428_mca_available(void) { @@ -4213,6 +4359,18 @@ gd5434_available(void) return rom_present(BIOS_GD5434_PATH); } +static int +gd5434_isa_available(void) +{ + return rom_present(BIOS_GD5434_PATH); +} + +static int +gd5430_orchid_vlb_available(void) +{ + return rom_present(BIOS_GD5430_ORCHID_VLB_PATH); +} + static int gd5434_diamond_a3_available(void) { @@ -4250,714 +4408,744 @@ gd5480_available(void) } void -gd54xx_close(void *p) +gd54xx_close(void *priv) { - gd54xx_t *gd54xx = (gd54xx_t *)p; + gd54xx_t *gd54xx = (gd54xx_t *) priv; svga_close(&gd54xx->svga); if (gd54xx->i2c) { - ddc_close(gd54xx->ddc); - i2c_gpio_close(gd54xx->i2c); + ddc_close(gd54xx->ddc); + i2c_gpio_close(gd54xx->i2c); } - + free(gd54xx); } - void -gd54xx_speed_changed(void *p) +gd54xx_speed_changed(void *priv) { - gd54xx_t *gd54xx = (gd54xx_t *)p; - + gd54xx_t *gd54xx = (gd54xx_t *) priv; + svga_recalctimings(&gd54xx->svga); } - void -gd54xx_force_redraw(void *p) +gd54xx_force_redraw(void *priv) { - gd54xx_t *gd54xx = (gd54xx_t *)p; + gd54xx_t *gd54xx = (gd54xx_t *) priv; - gd54xx->svga.fullchange = changeframecount; + gd54xx->svga.fullchange = gd54xx->svga.monitor->mon_changeframecount; } -static const device_config_t gd542x_config[] = -{ - { - .name = "memory", - .description = "Memory size", - .type = CONFIG_SELECTION, - .selection = - { - { - .description = "512 KB", - .value = 512 - }, - { - .description = "1 MB", - .value = 1024 - }, - { - .description = "" - } - }, - .default_int = 512 +// clang-format off +static const device_config_t gd542x_config[] = { + { + .name = "memory", + .description = "Memory size", + .type = CONFIG_SELECTION, + .selection = { + { + .description = "512 KB", + .value = 512 + }, + { + .description = "1 MB", + .value = 1024 + }, + { + .description = "" + } }, - { - .type = -1 - } + .default_int = 512 + }, + { + .type = CONFIG_END + } }; -static const device_config_t gd5426_config[] = -{ - { - .name = "memory", - .description = "Memory size", - .type = CONFIG_SELECTION, - .selection = - { - { - .description = "512 KB", - .value = 512 - }, - { - .description = "1 MB", - .value = 1024 - }, - { - .description = "2 MB", - .value = 2048 - }, - { - .description = "" - } - }, - .default_int = 2048 +static const device_config_t gd5426_config[] = { + { + .name = "memory", + .description = "Memory size", + .type = CONFIG_SELECTION, + .selection = { + { + .description = "512 KB", + .value = 512 + }, + { + .description = "1 MB", + .value = 1024 + }, + { + .description = "2 MB", + .value = 2048 + }, + { + .description = "" + } }, - { - .type = -1 - } + .default_int = 2048 + }, + { + .type = CONFIG_END + } }; -static const device_config_t gd5428_onboard_config[] = -{ - { - .name = "memory", - .description = "Onboard memory size", - .type = CONFIG_SELECTION, - .selection = - { - { - .description = "512 KB", - .value = 512 - }, - { - .description = "1 MB", - .value = 1024 - }, - { - .description = "2 MB", - .value = 2048 - }, - { - .description = "" - } - }, - .default_int = 2048 +static const device_config_t gd5428_onboard_config[] = { + { + .name = "memory", + .description = "Onboard memory size", + .type = CONFIG_SELECTION, + .selection = { + { + .description = "512 KB", + .value = 512 + }, + { + .description = "1 MB", + .value = 1024 + }, + { + .description = "2 MB", + .value = 2048 + }, + { + .description = "" + } }, - { - .type = -1 - } + .default_int = 2048 + }, + { + .type = CONFIG_END + } }; -static const device_config_t gd5429_config[] = -{ - { - .name = "memory", - .description = "Memory size", - .type = CONFIG_SELECTION, - .selection = - { - { - .description = "1 MB", - .value = 1 - }, - { - .description = "2 MB", - .value = 2 - }, - { - .description = "" - } - }, - .default_int = 2 +static const device_config_t gd5429_config[] = { + { + .name = "memory", + .description = "Memory size", + .type = CONFIG_SELECTION, + .selection = { + { + .description = "1 MB", + .value = 1 + }, + { + .description = "2 MB", + .value = 2 + }, + { + .description = "" + } }, - { - .type = -1 - } + .default_int = 2 + }, + { + .type = CONFIG_END + } }; -static const device_config_t gd5440_onboard_config[] = -{ - { - .name = "memory", - .description = "Onboard memory size", - .type = CONFIG_SELECTION, - .selection = - { - { - .description = "1 MB", - .value = 1 - }, - { - .description = "2 MB", - .value = 2 - }, - { - .description = "" - } - }, - .default_int = 2 +static const device_config_t gd5440_onboard_config[] = { + { + .name = "memory", + .description = "Onboard memory size", + .type = CONFIG_SELECTION, + .selection = { + { + .description = "1 MB", + .value = 1 + }, + { + .description = "2 MB", + .value = 2 + }, + { + .description = "" + } }, - { - .type = -1 - } + .default_int = 2 + }, + { + .type = CONFIG_END + } }; -static const device_config_t gd5434_config[] = -{ - { - .name = "memory", - .description = "Memory size", - .type = CONFIG_SELECTION, - .selection = - { - { - .description = "1 MB", - .value = 1 - }, - { - .description = "2 MB", - .value = 2 - }, - { - .description = "4 MB", - .value = 4 - }, - { - .description = "" - } - }, - .default_int = 4 +static const device_config_t gd5434_config[] = { + { + .name = "memory", + .description = "Memory size", + .type = CONFIG_SELECTION, + .selection = { + { + .description = "1 MB", + .value = 1 + }, + { + .description = "2 MB", + .value = 2 + }, + { + .description = "4 MB", + .value = 4 + }, + { + .description = "" + } }, - { - .type = -1 - } + .default_int = 4 + }, + { + .type = CONFIG_END + } }; -static const device_config_t gd5434_onboard_config[] = -{ - { - .name = "memory", - .description = "Onboard memory size", - .type = CONFIG_SELECTION, - .selection = - { - { - .description = "1 MB", - .value = 1 - }, - { - .description = "2 MB", - .value = 2 - }, - { - .description = "4 MB", - .value = 4 - }, - { - .description = "" - } - }, - .default_int = 4 +static const device_config_t gd5434_onboard_config[] = { + { + .name = "memory", + .description = "Onboard memory size", + .type = CONFIG_SELECTION, + .selection = { + { + .description = "1 MB", + .value = 1 + }, + { + .description = "2 MB", + .value = 2 + }, + { + .description = "4 MB", + .value = 4 + }, + { + .description = "" + } }, - { - .type = -1 - } + .default_int = 4 + }, + { + .type = CONFIG_END + } }; -static const device_config_t gd5480_config[] = -{ - { - .name = "memory", - .description = "Memory size", - .type = CONFIG_SELECTION, - .selection = - { - { - .description = "2 MB", - .value = 2 - }, - { - .description = "4 MB", - .value = 4 - }, - { - .description = "" - } - }, - .default_int = 4 +static const device_config_t gd5480_config[] = { + { + .name = "memory", + .description = "Memory size", + .type = CONFIG_SELECTION, + .selection = { + { + .description = "2 MB", + .value = 2 + }, + { + .description = "4 MB", + .value = 4 + }, + { + .description = "" + } }, - { - .type = -1 - } + .default_int = 4 + }, + { + .type = -1 + } +}; +// clang-format on + +const device_t gd5401_isa_device = { + .name = "Cirrus Logic GD5401 (ISA) (ACUMOS AVGA1)", + .internal_name = "cl_gd5401_isa", + .flags = DEVICE_ISA, + .local = CIRRUS_ID_CLGD5401, + .init = gd54xx_init, + .close = gd54xx_close, + .reset = gd54xx_reset, + { .available = gd5401_available }, + .speed_changed = gd54xx_speed_changed, + .force_redraw = gd54xx_force_redraw, + .config = NULL, }; -const device_t gd5401_isa_device = -{ - "Cirrus Logic GD5401 (ISA) (ACUMOS AVGA1)", - "cl_gd5401_isa", - DEVICE_ISA, - CIRRUS_ID_CLGD5401, - gd54xx_init, gd54xx_close, - gd54xx_reset, - { gd5401_available }, - gd54xx_speed_changed, - gd54xx_force_redraw, - NULL, +const device_t gd5402_isa_device = { + .name = "Cirrus Logic GD5402 (ISA) (ACUMOS AVGA2)", + .internal_name = "cl_gd5402_isa", + .flags = DEVICE_ISA, + .local = CIRRUS_ID_CLGD5402, + .init = gd54xx_init, + .close = gd54xx_close, + .reset = gd54xx_reset, + { .available = gd5402_available }, + .speed_changed = gd54xx_speed_changed, + .force_redraw = gd54xx_force_redraw, + .config = NULL, }; -const device_t gd5402_isa_device = -{ - "Cirrus Logic GD5402 (ISA) (ACUMOS AVGA2)", - "cl_gd5402_isa", - DEVICE_ISA, - CIRRUS_ID_CLGD5402, - gd54xx_init, gd54xx_close, - gd54xx_reset, - { gd5402_available }, - gd54xx_speed_changed, - gd54xx_force_redraw, - NULL, +const device_t gd5402_onboard_device = { + .name = "Cirrus Logic GD5402 (ISA) (ACUMOS AVGA2) (On-Board)", + .internal_name = "cl_gd5402_onboard", + .flags = DEVICE_AT | DEVICE_ISA, + .local = CIRRUS_ID_CLGD5402 | 0x200, + .init = gd54xx_init, + .close = gd54xx_close, + .reset = gd54xx_reset, + { .available = NULL }, + .speed_changed = gd54xx_speed_changed, + .force_redraw = gd54xx_force_redraw, + .config = NULL, }; -const device_t gd5402_onboard_device = -{ - "Cirrus Logic GD5402 (ISA) (ACUMOS AVGA2) (On-Board)", - "cl_gd5402_onboard", - DEVICE_AT | DEVICE_ISA, - CIRRUS_ID_CLGD5402 | 0x200, - gd54xx_init, gd54xx_close, - gd54xx_reset, - { NULL }, - gd54xx_speed_changed, - gd54xx_force_redraw, - NULL, -}; - -const device_t gd5420_isa_device = -{ - "Cirrus Logic GD5420 (ISA)", - "cl_gd5420_isa", - DEVICE_AT | DEVICE_ISA, - CIRRUS_ID_CLGD5420, - gd54xx_init, gd54xx_close, - gd54xx_reset, - { gd5420_available }, - gd54xx_speed_changed, - gd54xx_force_redraw, - gd542x_config, +const device_t gd5420_isa_device = { + .name = "Cirrus Logic GD5420 (ISA)", + .internal_name = "cl_gd5420_isa", + .flags = DEVICE_AT | DEVICE_ISA, + .local = CIRRUS_ID_CLGD5420, + .init = gd54xx_init, + .close = gd54xx_close, + .reset = gd54xx_reset, + { .available = gd5420_available }, + .speed_changed = gd54xx_speed_changed, + .force_redraw = gd54xx_force_redraw, + .config = gd542x_config, }; const device_t gd5422_isa_device = { - "Cirrus Logic GD5422 (ISA)", - "cl_gd5422_isa", - DEVICE_AT | DEVICE_ISA, - CIRRUS_ID_CLGD5422, - gd54xx_init, gd54xx_close, - gd54xx_reset, - { gd5422_available }, /* Common BIOS between 5422 and 5424 */ - gd54xx_speed_changed, - gd54xx_force_redraw, - gd542x_config, + .name = "Cirrus Logic GD5422 (ISA)", + .internal_name = "cl_gd5422_isa", + .flags = DEVICE_AT | DEVICE_ISA, + .local = CIRRUS_ID_CLGD5422, + .init = gd54xx_init, + .close = gd54xx_close, + .reset = gd54xx_reset, + { .available = gd5422_available }, /* Common BIOS between 5422 and 5424 */ + .speed_changed = gd54xx_speed_changed, + .force_redraw = gd54xx_force_redraw, + .config = gd542x_config, }; const device_t gd5424_vlb_device = { - "Cirrus Logic GD5424 (VLB)", - "cl_gd5424_vlb", - DEVICE_VLB, - CIRRUS_ID_CLGD5424, - gd54xx_init, gd54xx_close, - gd54xx_reset, - { gd5422_available }, /* Common BIOS between 5422 and 5424 */ - gd54xx_speed_changed, - gd54xx_force_redraw, - gd542x_config, + .name = "Cirrus Logic GD5424 (VLB)", + .internal_name = "cl_gd5424_vlb", + .flags = DEVICE_VLB, + .local = CIRRUS_ID_CLGD5424, + .init = gd54xx_init, + .close = gd54xx_close, + .reset = gd54xx_reset, + { .available = gd5422_available }, /* Common BIOS between 5422 and 5424 */ + .speed_changed = gd54xx_speed_changed, + .force_redraw = gd54xx_force_redraw, + .config = gd542x_config, }; -const device_t gd5426_isa_device = -{ - "Cirrus Logic GD5426 (ISA)", - "cl_gd5426_isa", - DEVICE_AT | DEVICE_ISA, - CIRRUS_ID_CLGD5426, - gd54xx_init, - gd54xx_close, - gd54xx_reset, - { gd5428_isa_available }, - gd54xx_speed_changed, - gd54xx_force_redraw, - gd5426_config -}; - - -/*According to a Diamond bios file listing and vgamuseum*/ -const device_t gd5426_diamond_speedstar_pro_a1_isa_device = -{ - "Cirrus Logic GD5426 (ISA) (Diamond SpeedStar Pro Rev. A1)", - "cl_gd5426_diamond_a1_isa", - DEVICE_AT | DEVICE_ISA, - CIRRUS_ID_CLGD5426 | 0x100, - gd54xx_init, - gd54xx_close, - gd54xx_reset, - { gd5426_diamond_a1_available }, - gd54xx_speed_changed, - gd54xx_force_redraw, - gd5426_config -}; - -const device_t gd5426_vlb_device = -{ - "Cirrus Logic GD5426 (VLB)", - "cl_gd5426_vlb", - DEVICE_VLB, - CIRRUS_ID_CLGD5426, - gd54xx_init, - gd54xx_close, - gd54xx_reset, - { gd5428_available }, - gd54xx_speed_changed, - gd54xx_force_redraw, - gd5426_config -}; - - -const device_t gd5426_onboard_device = -{ - "Cirrus Logic GD5426 (VLB) (On-Board)", - "cl_gd5426_onboard", - DEVICE_VLB, - CIRRUS_ID_CLGD5426 | 0x200, - gd54xx_init, - gd54xx_close, - gd54xx_reset, - { NULL }, - gd54xx_speed_changed, - gd54xx_force_redraw, - NULL -}; - -const device_t gd5428_isa_device = -{ - "Cirrus Logic GD5428 (ISA)", - "cl_gd5428_isa", - DEVICE_AT | DEVICE_ISA, - CIRRUS_ID_CLGD5428, - gd54xx_init, - gd54xx_close, - gd54xx_reset, - { gd5428_isa_available }, - gd54xx_speed_changed, - gd54xx_force_redraw, - gd5426_config -}; - -const device_t gd5428_vlb_device = -{ - "Cirrus Logic GD5428 (VLB)", - "cl_gd5428_vlb", - DEVICE_VLB, - CIRRUS_ID_CLGD5428, - gd54xx_init, - gd54xx_close, - gd54xx_reset, - { gd5428_available }, - gd54xx_speed_changed, - gd54xx_force_redraw, - gd5426_config +const device_t gd5426_isa_device = { + .name = "Cirrus Logic GD5426 (ISA)", + .internal_name = "cl_gd5426_isa", + .flags = DEVICE_AT | DEVICE_ISA, + .local = CIRRUS_ID_CLGD5426, + .init = gd54xx_init, + .close = gd54xx_close, + .reset = gd54xx_reset, + { .available = gd5428_isa_available }, + .speed_changed = gd54xx_speed_changed, + .force_redraw = gd54xx_force_redraw, + .config = gd5426_config }; /*According to a Diamond bios file listing and vgamuseum*/ -const device_t gd5428_diamond_speedstar_pro_b1_vlb_device = -{ - "Cirrus Logic GD5428 (VLB) (Diamond SpeedStar Pro Rev. B1)", - "cl_gd5428_diamond_b1_vlb", - DEVICE_VLB, - CIRRUS_ID_CLGD5428 | 0x100, - gd54xx_init, - gd54xx_close, - gd54xx_reset, - { gd5428_diamond_b1_available }, - gd54xx_speed_changed, - gd54xx_force_redraw, - gd5426_config +const device_t gd5426_diamond_speedstar_pro_a1_isa_device = { + .name = "Cirrus Logic GD5426 (ISA) (Diamond SpeedStar Pro Rev. A1)", + .internal_name = "cl_gd5426_diamond_a1_isa", + .flags = DEVICE_AT | DEVICE_ISA, + .local = CIRRUS_ID_CLGD5426 | 0x100, + .init = gd54xx_init, + .close = gd54xx_close, + .reset = gd54xx_reset, + { .available = gd5426_diamond_a1_available }, + .speed_changed = gd54xx_speed_changed, + .force_redraw = gd54xx_force_redraw, + .config = gd5426_config }; -const device_t gd5428_mca_device = -{ - "Cirrus Logic GD5428 (MCA) (IBM SVGA Adapter/A)", - "ibm1mbsvga", - DEVICE_MCA, - CIRRUS_ID_CLGD5428, - gd54xx_init, - gd54xx_close, - gd54xx_reset, - { gd5428_mca_available }, - gd54xx_speed_changed, - gd54xx_force_redraw, - NULL +const device_t gd5426_vlb_device = { + .name = "Cirrus Logic GD5426 (VLB)", + .internal_name = "cl_gd5426_vlb", + .flags = DEVICE_VLB, + .local = CIRRUS_ID_CLGD5426, + .init = gd54xx_init, + .close = gd54xx_close, + .reset = gd54xx_reset, + { .available = gd5428_available }, + .speed_changed = gd54xx_speed_changed, + .force_redraw = gd54xx_force_redraw, + .config = gd5426_config }; -const device_t gd5428_onboard_device = -{ - "Cirrus Logic GD5428 (ISA) (On-Board)", - "cl_gd5428_onboard", - DEVICE_AT | DEVICE_ISA, - CIRRUS_ID_CLGD5428, - gd54xx_init, - gd54xx_close, - gd54xx_reset, - { gd5428_isa_available }, - gd54xx_speed_changed, - gd54xx_force_redraw, - gd5428_onboard_config +const device_t gd5426_onboard_device = { + .name = "Cirrus Logic GD5426 (VLB) (On-Board)", + .internal_name = "cl_gd5426_onboard", + .flags = DEVICE_VLB, + .local = CIRRUS_ID_CLGD5426 | 0x200, + .init = gd54xx_init, + .close = gd54xx_close, + .reset = gd54xx_reset, + { .available = NULL }, + .speed_changed = gd54xx_speed_changed, + .force_redraw = gd54xx_force_redraw, + .config = NULL }; -const device_t gd5429_isa_device = -{ - "Cirrus Logic GD5429 (ISA)", - "cl_gd5429_isa", - DEVICE_AT | DEVICE_ISA, - CIRRUS_ID_CLGD5429, - gd54xx_init, - gd54xx_close, - gd54xx_reset, - { gd5429_available }, - gd54xx_speed_changed, - gd54xx_force_redraw, - gd5429_config +const device_t gd5428_isa_device = { + .name = "Cirrus Logic GD5428 (ISA)", + .internal_name = "cl_gd5428_isa", + .flags = DEVICE_AT | DEVICE_ISA, + .local = CIRRUS_ID_CLGD5428, + .init = gd54xx_init, + .close = gd54xx_close, + .reset = gd54xx_reset, + { .available = gd5428_isa_available }, + .speed_changed = gd54xx_speed_changed, + .force_redraw = gd54xx_force_redraw, + .config = gd5426_config }; -const device_t gd5429_vlb_device = -{ - "Cirrus Logic GD5429 (VLB)", - "cl_gd5429_vlb", - DEVICE_VLB, - CIRRUS_ID_CLGD5429, - gd54xx_init, - gd54xx_close, - gd54xx_reset, - { gd5429_available }, - gd54xx_speed_changed, - gd54xx_force_redraw, - gd5429_config +const device_t gd5428_vlb_device = { + .name = "Cirrus Logic GD5428 (VLB)", + .internal_name = "cl_gd5428_vlb", + .flags = DEVICE_VLB, + .local = CIRRUS_ID_CLGD5428, + .init = gd54xx_init, + .close = gd54xx_close, + .reset = gd54xx_reset, + { .available = gd5428_available }, + .speed_changed = gd54xx_speed_changed, + .force_redraw = gd54xx_force_redraw, + .config = gd5426_config }; /*According to a Diamond bios file listing and vgamuseum*/ -const device_t gd5430_diamond_speedstar_pro_se_a8_vlb_device = -{ - "Cirrus Logic GD5430 (VLB) (Diamond SpeedStar Pro SE Rev. A8)", - "cl_gd5430_vlb", - DEVICE_VLB, - CIRRUS_ID_CLGD5430, - gd54xx_init, - gd54xx_close, - gd54xx_reset, - { gd5430_diamond_a8_available }, - gd54xx_speed_changed, - gd54xx_force_redraw, - gd5429_config +const device_t gd5428_diamond_speedstar_pro_b1_vlb_device = { + .name = "Cirrus Logic GD5428 (VLB) (Diamond SpeedStar Pro Rev. B1)", + .internal_name = "cl_gd5428_diamond_b1_vlb", + .flags = DEVICE_VLB, + .local = CIRRUS_ID_CLGD5428 | 0x100, + .init = gd54xx_init, + .close = gd54xx_close, + .reset = gd54xx_reset, + { .available = gd5428_diamond_b1_available }, + .speed_changed = gd54xx_speed_changed, + .force_redraw = gd54xx_force_redraw, + .config = gd5426_config }; -const device_t gd5430_pci_device = -{ - "Cirrus Logic GD5430 (PCI)", - "cl_gd5430_pci", - DEVICE_PCI, - CIRRUS_ID_CLGD5430, - gd54xx_init, - gd54xx_close, - gd54xx_reset, - { gd5430_available }, - gd54xx_speed_changed, - gd54xx_force_redraw, - gd5429_config +const device_t gd5428_boca_isa_device = { + .name = "Cirrus Logic GD5428 (ISA) (BOCA Research 4610)", + .internal_name = "cl_gd5428_boca_isa", + .flags = DEVICE_AT | DEVICE_ISA, + .local = CIRRUS_ID_CLGD5428 | 0x100, + .init = gd54xx_init, + .close = gd54xx_close, + .reset = gd54xx_reset, + { .available = gd5428_boca_isa_available }, + .speed_changed = gd54xx_speed_changed, + .force_redraw = gd54xx_force_redraw, + .config = gd5426_config }; -const device_t gd5434_isa_device = -{ - "Cirrus Logic GD5434 (ISA)", - "cl_gd5434_isa", - DEVICE_AT | DEVICE_ISA, - CIRRUS_ID_CLGD5434, - gd54xx_init, - gd54xx_close, - gd54xx_reset, - { gd5434_available }, - gd54xx_speed_changed, - gd54xx_force_redraw, - gd5434_config +const device_t gd5428_mca_device = { + .name = "Cirrus Logic GD5428 (MCA) (IBM SVGA Adapter/A)", + .internal_name = "ibm1mbsvga", + .flags = DEVICE_MCA, + .local = CIRRUS_ID_CLGD5428, + .init = gd54xx_init, + .close = gd54xx_close, + .reset = gd54xx_reset, + { .available = gd5428_mca_available }, + .speed_changed = gd54xx_speed_changed, + .force_redraw = gd54xx_force_redraw, + .config = NULL +}; + +const device_t gd5426_mca_device = { + .name = "Cirrus Logic GD5426 (MCA) (Reply Video Adapter)", + .internal_name = "replymcasvga", + .flags = DEVICE_MCA, + .local = CIRRUS_ID_CLGD5426, + .init = gd54xx_init, + .close = gd54xx_close, + .reset = gd54xx_reset, + { .available = gd5426_mca_available }, + .speed_changed = gd54xx_speed_changed, + .force_redraw = gd54xx_force_redraw, + .config = gd5426_config +}; + +const device_t gd5428_onboard_device = { + .name = "Cirrus Logic GD5428 (ISA) (On-Board)", + .internal_name = "cl_gd5428_onboard", + .flags = DEVICE_AT | DEVICE_ISA, + .local = CIRRUS_ID_CLGD5428, + .init = gd54xx_init, + .close = gd54xx_close, + .reset = gd54xx_reset, + { .available = gd5428_isa_available }, + .speed_changed = gd54xx_speed_changed, + .force_redraw = gd54xx_force_redraw, + .config = gd5428_onboard_config +}; + +const device_t gd5429_isa_device = { + .name = "Cirrus Logic GD5429 (ISA)", + .internal_name = "cl_gd5429_isa", + .flags = DEVICE_AT | DEVICE_ISA, + .local = CIRRUS_ID_CLGD5429, + .init = gd54xx_init, + .close = gd54xx_close, + .reset = gd54xx_reset, + { .available = gd5429_available }, + .speed_changed = gd54xx_speed_changed, + .force_redraw = gd54xx_force_redraw, + .config = gd5429_config +}; + +const device_t gd5429_vlb_device = { + .name = "Cirrus Logic GD5429 (VLB)", + .internal_name = "cl_gd5429_vlb", + .flags = DEVICE_VLB, + .local = CIRRUS_ID_CLGD5429, + .init = gd54xx_init, + .close = gd54xx_close, + .reset = gd54xx_reset, + { .available = gd5429_available }, + .speed_changed = gd54xx_speed_changed, + .force_redraw = gd54xx_force_redraw, + .config = gd5429_config }; /*According to a Diamond bios file listing and vgamuseum*/ -const device_t gd5434_diamond_speedstar_64_a3_isa_device = -{ - "Cirrus Logic GD5434 (ISA) (Diamond SpeedStar 64 Rev. A3)", - "cl_gd5434_diamond_a3_isa", - DEVICE_AT | DEVICE_ISA, - CIRRUS_ID_CLGD5434 | 0x100, - gd54xx_init, - gd54xx_close, - gd54xx_reset, - { gd5434_diamond_a3_available }, - gd54xx_speed_changed, - gd54xx_force_redraw, - gd5429_config +const device_t gd5430_diamond_speedstar_pro_se_a8_vlb_device = { + .name = "Cirrus Logic GD5430 (VLB) (Diamond SpeedStar Pro SE Rev. A8)", + .internal_name = "cl_gd5430_vlb_diamond", + .flags = DEVICE_VLB, + .local = CIRRUS_ID_CLGD5430, + .init = gd54xx_init, + .close = gd54xx_close, + .reset = gd54xx_reset, + { .available = gd5430_diamond_a8_available }, + .speed_changed = gd54xx_speed_changed, + .force_redraw = gd54xx_force_redraw, + .config = gd5429_config }; -const device_t gd5434_onboard_pci_device = -{ - "Cirrus Logic GD5434-4 (PCI) (On-Board)", - "cl_gd5434_onboard_pci", - DEVICE_PCI, - CIRRUS_ID_CLGD5434 | 0x200, - gd54xx_init, - gd54xx_close, - gd54xx_reset, - { NULL }, - gd54xx_speed_changed, - gd54xx_force_redraw, - gd5434_onboard_config +const device_t gd5430_vlb_device = { + .name = "Cirrus Logic GD5430", + .internal_name = "cl_gd5430_vlb", + .flags = DEVICE_VLB, + .local = CIRRUS_ID_CLGD5430 | 0x100, + .init = gd54xx_init, + .close = gd54xx_close, + .reset = gd54xx_reset, + { .available = gd5430_orchid_vlb_available }, + .speed_changed = gd54xx_speed_changed, + .force_redraw = gd54xx_force_redraw, + .config = gd5429_config }; -const device_t gd5434_vlb_device = -{ - "Cirrus Logic GD5434 (VLB)", - "cl_gd5434_vlb", - DEVICE_VLB, - CIRRUS_ID_CLGD5434, - gd54xx_init, - gd54xx_close, - gd54xx_reset, - { gd5434_available }, - gd54xx_speed_changed, - gd54xx_force_redraw, - gd5434_config +const device_t gd5430_onboard_vlb_device = { + .name = "Cirrus Logic GD5430 (On-Board)", + .internal_name = "cl_gd5430_onboard_vlb", + .flags = DEVICE_VLB, + .local = CIRRUS_ID_CLGD5430 | 0x200, + .init = gd54xx_init, + .close = gd54xx_close, + .reset = gd54xx_reset, + { .available = NULL }, + .speed_changed = gd54xx_speed_changed, + .force_redraw = gd54xx_force_redraw, + .config = gd5429_config }; -const device_t gd5434_pci_device = -{ - "Cirrus Logic GD5434 (PCI)", - "cl_gd5434_pci", - DEVICE_PCI, - CIRRUS_ID_CLGD5434, - gd54xx_init, - gd54xx_close, - gd54xx_reset, - { gd5434_available }, - gd54xx_speed_changed, - gd54xx_force_redraw, - gd5434_config +const device_t gd5430_pci_device = { + .name = "Cirrus Logic GD5430 (PCI)", + .internal_name = "cl_gd5430_pci", + .flags = DEVICE_PCI, + .local = CIRRUS_ID_CLGD5430, + .init = gd54xx_init, + .close = gd54xx_close, + .reset = gd54xx_reset, + { .available = gd5430_available }, + .speed_changed = gd54xx_speed_changed, + .force_redraw = gd54xx_force_redraw, + .config = gd5429_config }; -const device_t gd5436_pci_device = -{ - "Cirrus Logic GD5436 (PCI)", - "cl_gd5436_pci", - DEVICE_PCI, - CIRRUS_ID_CLGD5436, - gd54xx_init, - gd54xx_close, - gd54xx_reset, - { gd5436_available }, - gd54xx_speed_changed, - gd54xx_force_redraw, - gd5434_config +const device_t gd5430_onboard_pci_device = { + .name = "Cirrus Logic GD5430 (PCI) (On-Board)", + .internal_name = "cl_gd5430_onboard_pci", + .flags = DEVICE_PCI, + .local = CIRRUS_ID_CLGD5430 | 0x200, + .init = gd54xx_init, + .close = gd54xx_close, + .reset = gd54xx_reset, + { .available = NULL }, + .speed_changed = gd54xx_speed_changed, + .force_redraw = gd54xx_force_redraw, + .config = gd5429_config }; -const device_t gd5440_onboard_pci_device = -{ - "Cirrus Logic GD5440 (PCI) (On-Board)", - "cl_gd5440_onboard_pci", - DEVICE_PCI, - CIRRUS_ID_CLGD5440 | 0x600, - gd54xx_init, - gd54xx_close, - gd54xx_reset, - { NULL }, - gd54xx_speed_changed, - gd54xx_force_redraw, - gd5440_onboard_config +const device_t gd5434_isa_device = { + .name = "Cirrus Logic GD5434 (ISA)", + .internal_name = "cl_gd5434_isa", + .flags = DEVICE_AT | DEVICE_ISA, + .local = CIRRUS_ID_CLGD5434, + .init = gd54xx_init, + .close = gd54xx_close, + .reset = gd54xx_reset, + { .available = gd5434_isa_available }, + .speed_changed = gd54xx_speed_changed, + .force_redraw = gd54xx_force_redraw, + .config = gd5434_config }; -const device_t gd5440_pci_device = -{ - "Cirrus Logic GD5440 (PCI)", - "cl_gd5440_pci", - DEVICE_PCI, - CIRRUS_ID_CLGD5440 | 0x400, - gd54xx_init, - gd54xx_close, - gd54xx_reset, - { gd5440_available }, - gd54xx_speed_changed, - gd54xx_force_redraw, - gd5429_config +/*According to a Diamond bios file listing and vgamuseum*/ +const device_t gd5434_diamond_speedstar_64_a3_isa_device = { + .name = "Cirrus Logic GD5434 (ISA) (Diamond SpeedStar 64 Rev. A3)", + .internal_name = "cl_gd5434_diamond_a3_isa", + .flags = DEVICE_AT | DEVICE_ISA, + .local = CIRRUS_ID_CLGD5434 | 0x100, + .init = gd54xx_init, + .close = gd54xx_close, + .reset = gd54xx_reset, + { .available = gd5434_diamond_a3_available }, + .speed_changed = gd54xx_speed_changed, + .force_redraw = gd54xx_force_redraw, + .config = gd5429_config }; -const device_t gd5446_pci_device = -{ - "Cirrus Logic GD5446 (PCI)", - "cl_gd5446_pci", - DEVICE_PCI, - CIRRUS_ID_CLGD5446, - gd54xx_init, - gd54xx_close, - gd54xx_reset, - { gd5446_available }, - gd54xx_speed_changed, - gd54xx_force_redraw, - gd5434_config +const device_t gd5434_onboard_pci_device = { + .name = "Cirrus Logic GD5434-4 (PCI) (On-Board)", + .internal_name = "cl_gd5434_onboard_pci", + .flags = DEVICE_PCI, + .local = CIRRUS_ID_CLGD5434 | 0x200, + .init = gd54xx_init, + .close = gd54xx_close, + .reset = gd54xx_reset, + { .available = NULL }, + .speed_changed = gd54xx_speed_changed, + .force_redraw = gd54xx_force_redraw, + .config = gd5434_onboard_config }; -const device_t gd5446_stb_pci_device = -{ - "Cirrus Logic GD5446 (PCI) (STB Nitro 64V)", - "cl_gd5446_stb_pci", - DEVICE_PCI, - CIRRUS_ID_CLGD5446 | 0x100, - gd54xx_init, - gd54xx_close, - gd54xx_reset, - { gd5446_stb_available }, - gd54xx_speed_changed, - gd54xx_force_redraw, - gd5434_config +const device_t gd5434_vlb_device = { + .name = "Cirrus Logic GD5434 (VLB)", + .internal_name = "cl_gd5434_vlb", + .flags = DEVICE_VLB, + .local = CIRRUS_ID_CLGD5434, + .init = gd54xx_init, + .close = gd54xx_close, + .reset = gd54xx_reset, + { .available = gd5430_orchid_vlb_available }, + .speed_changed = gd54xx_speed_changed, + .force_redraw = gd54xx_force_redraw, + .config = gd5434_config }; -const device_t gd5480_pci_device = -{ - "Cirrus Logic GD5480 (PCI)", - "cl_gd5480_pci", - DEVICE_PCI, - CIRRUS_ID_CLGD5480, - gd54xx_init, - gd54xx_close, - gd54xx_reset, - { gd5480_available }, - gd54xx_speed_changed, - gd54xx_force_redraw, - gd5480_config +const device_t gd5434_pci_device = { + .name = "Cirrus Logic GD5434 (PCI)", + .internal_name = "cl_gd5434_pci", + .flags = DEVICE_PCI, + .local = CIRRUS_ID_CLGD5434, + .init = gd54xx_init, + .close = gd54xx_close, + .reset = gd54xx_reset, + { .available = gd5434_available }, + .speed_changed = gd54xx_speed_changed, + .force_redraw = gd54xx_force_redraw, + .config = gd5434_config +}; + +const device_t gd5436_pci_device = { + .name = "Cirrus Logic GD5436 (PCI)", + .internal_name = "cl_gd5436_pci", + .flags = DEVICE_PCI, + .local = CIRRUS_ID_CLGD5436, + .init = gd54xx_init, + .close = gd54xx_close, + .reset = gd54xx_reset, + { .available = gd5436_available }, + .speed_changed = gd54xx_speed_changed, + .force_redraw = gd54xx_force_redraw, + .config = gd5434_config +}; + +const device_t gd5440_onboard_pci_device = { + .name = "Cirrus Logic GD5440 (PCI) (On-Board)", + .internal_name = "cl_gd5440_onboard_pci", + .flags = DEVICE_PCI, + .local = CIRRUS_ID_CLGD5440 | 0x600, + .init = gd54xx_init, + .close = gd54xx_close, + .reset = gd54xx_reset, + { .available = NULL }, + .speed_changed = gd54xx_speed_changed, + .force_redraw = gd54xx_force_redraw, + .config = gd5440_onboard_config +}; + +const device_t gd5440_pci_device = { + .name = "Cirrus Logic GD5440 (PCI)", + .internal_name = "cl_gd5440_pci", + .flags = DEVICE_PCI, + .local = CIRRUS_ID_CLGD5440 | 0x400, + .init = gd54xx_init, + .close = gd54xx_close, + .reset = gd54xx_reset, + { .available = gd5440_available }, + .speed_changed = gd54xx_speed_changed, + .force_redraw = gd54xx_force_redraw, + .config = gd5429_config +}; + +const device_t gd5446_pci_device = { + .name = "Cirrus Logic GD5446 (PCI)", + .internal_name = "cl_gd5446_pci", + .flags = DEVICE_PCI, + .local = CIRRUS_ID_CLGD5446, + .init = gd54xx_init, + .close = gd54xx_close, + .reset = gd54xx_reset, + { .available = gd5446_available }, + .speed_changed = gd54xx_speed_changed, + .force_redraw = gd54xx_force_redraw, + .config = gd5434_config +}; + +const device_t gd5446_stb_pci_device = { + .name = "Cirrus Logic GD5446 (PCI) (STB Nitro 64V)", + .internal_name = "cl_gd5446_stb_pci", + .flags = DEVICE_PCI, + .local = CIRRUS_ID_CLGD5446 | 0x100, + .init = gd54xx_init, + .close = gd54xx_close, + .reset = gd54xx_reset, + { .available = gd5446_stb_available }, + .speed_changed = gd54xx_speed_changed, + .force_redraw = gd54xx_force_redraw, + .config = gd5434_config +}; + +const device_t gd5480_pci_device = { + .name = "Cirrus Logic GD5480 (PCI)", + .internal_name = "cl_gd5480_pci", + .flags = DEVICE_PCI, + .local = CIRRUS_ID_CLGD5480, + .init = gd54xx_init, + .close = gd54xx_close, + .reset = gd54xx_reset, + { .available = gd5480_available }, + .speed_changed = gd54xx_speed_changed, + .force_redraw = gd54xx_force_redraw, + .config = gd5480_config }; diff --git a/src/video/vid_colorplus.c b/src/video/vid_colorplus.c index 7f2a4e004..dcc72a76b 100644 --- a/src/video/vid_colorplus.c +++ b/src/video/vid_colorplus.c @@ -1,20 +1,20 @@ /* - * 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. + * 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. + * This file is part of the 86Box distribution. * - * Plantronics ColorPlus emulation. + * Plantronics ColorPlus emulation. * * * - * Authors: Sarah Walker, - * Miran Grca, + * Authors: Sarah Walker, + * Miran Grca, * - * Copyright 2008-2018 Sarah Walker. - * Copyright 2016-2018 Miran Grca. + * Copyright 2008-2018 Sarah Walker. + * Copyright 2016-2018 Miran Grca. */ #include #include @@ -34,446 +34,413 @@ #include <86box/vid_cga.h> #include <86box/vid_colorplus.h> #include <86box/vid_cga_comp.h> - +#include <86box/plat_unused.h> /* Bits in the colorplus control register: */ -#define COLORPLUS_PLANE_SWAP 0x40 /* Swap planes at 0000h and 4000h */ -#define COLORPLUS_640x200_MODE 0x20 /* 640x200x4 mode active */ -#define COLORPLUS_320x200_MODE 0x10 /* 320x200x16 mode active */ -#define COLORPLUS_EITHER_MODE 0x30 /* Either mode active */ +#define COLORPLUS_PLANE_SWAP 0x40 /* Swap planes at 0000h and 4000h */ +#define COLORPLUS_640x200_MODE 0x20 /* 640x200x4 mode active */ +#define COLORPLUS_320x200_MODE 0x10 /* 320x200x16 mode active */ +#define COLORPLUS_EITHER_MODE 0x30 /* Either mode active */ /* Bits in the CGA graphics mode register */ -#define CGA_GRAPHICS_MODE 0x02 /* CGA graphics mode selected? */ +#define CGA_GRAPHICS_MODE 0x02 /* CGA graphics mode selected? */ -#define CGA_RGB 0 -#define CGA_COMPOSITE 1 +#define CGA_RGB 0 +#define CGA_COMPOSITE 1 -#define COMPOSITE_OLD 0 -#define COMPOSITE_NEW 1 - - -video_timings_t timing_colorplus = {VIDEO_ISA, 8, 16, 32, 8, 16, 32}; +#define COMPOSITE_OLD 0 +#define COMPOSITE_NEW 1 +video_timings_t timing_colorplus = { .type = VIDEO_ISA, .write_b = 8, .write_w = 16, .write_l = 32, .read_b = 8, .read_w = 16, .read_l = 32 }; void cga_recalctimings(cga_t *cga); -void colorplus_out(uint16_t addr, uint8_t val, void *p) +void +colorplus_out(uint16_t addr, uint8_t val, void *priv) { - colorplus_t *colorplus = (colorplus_t *)p; + colorplus_t *colorplus = (colorplus_t *) priv; - if (addr == 0x3DD) + if (addr == 0x3DD) { + colorplus->control = val & 0x70; + } else { + cga_out(addr, val, &colorplus->cga); + } +} + +uint8_t +colorplus_in(uint16_t addr, void *priv) +{ + colorplus_t *colorplus = (colorplus_t *) priv; + + return cga_in(addr, &colorplus->cga); +} + +void +colorplus_write(uint32_t addr, uint8_t val, void *priv) +{ + colorplus_t *colorplus = (colorplus_t *) priv; + + if ((colorplus->control & COLORPLUS_PLANE_SWAP) && (colorplus->control & COLORPLUS_EITHER_MODE) && (colorplus->cga.cgamode & CGA_GRAPHICS_MODE)) { + addr ^= 0x4000; + } else if (!(colorplus->control & COLORPLUS_EITHER_MODE)) { + addr &= 0x3FFF; + } + colorplus->cga.vram[addr & 0x7fff] = val; + if (colorplus->cga.snow_enabled) { + int offset = ((timer_get_remaining_u64(&colorplus->cga.timer) / CGACONST) * 2) & 0xfc; + colorplus->cga.charbuffer[offset] = colorplus->cga.vram[addr & 0x7fff]; + colorplus->cga.charbuffer[offset | 1] = colorplus->cga.vram[addr & 0x7fff]; + } + cycles -= 4; +} + +uint8_t +colorplus_read(uint32_t addr, void *priv) +{ + colorplus_t *colorplus = (colorplus_t *) priv; + + if ((colorplus->control & COLORPLUS_PLANE_SWAP) && (colorplus->control & COLORPLUS_EITHER_MODE) && (colorplus->cga.cgamode & CGA_GRAPHICS_MODE)) { + addr ^= 0x4000; + } else if (!(colorplus->control & COLORPLUS_EITHER_MODE)) { + addr &= 0x3FFF; + } + cycles -= 4; + if (colorplus->cga.snow_enabled) { + int offset = ((timer_get_remaining_u64(&colorplus->cga.timer) / CGACONST) * 2) & 0xfc; + colorplus->cga.charbuffer[offset] = colorplus->cga.vram[addr & 0x7fff]; + colorplus->cga.charbuffer[offset | 1] = colorplus->cga.vram[addr & 0x7fff]; + } + return colorplus->cga.vram[addr & 0x7fff]; +} + +void +colorplus_recalctimings(colorplus_t *colorplus) +{ + cga_recalctimings(&colorplus->cga); +} + +void +colorplus_poll(void *priv) +{ + colorplus_t *colorplus = (colorplus_t *) priv; + int x; + int c; + int oldvc; + uint16_t dat0; + uint16_t dat1; + int cols[4]; + int col; + int oldsc; + static const int cols16[16] = { 0x10, 0x12, 0x14, 0x16, + 0x18, 0x1A, 0x1C, 0x1E, + 0x11, 0x13, 0x15, 0x17, + 0x19, 0x1B, 0x1D, 0x1F }; + const uint8_t *plane0 = colorplus->cga.vram; + const uint8_t *plane1 = colorplus->cga.vram + 0x4000; + + /* If one of the extra modes is not selected, drop down to the CGA + * drawing code. */ + if (!((colorplus->control & COLORPLUS_EITHER_MODE) && (colorplus->cga.cgamode & CGA_GRAPHICS_MODE))) { + cga_poll(&colorplus->cga); + return; + } + + if (!colorplus->cga.linepos) { + timer_advance_u64(&colorplus->cga.timer, colorplus->cga.dispofftime); + colorplus->cga.cgastat |= 1; + colorplus->cga.linepos = 1; + oldsc = colorplus->cga.sc; + if ((colorplus->cga.crtc[8] & 3) == 3) + colorplus->cga.sc = ((colorplus->cga.sc << 1) + colorplus->cga.oddeven) & 7; + if (colorplus->cga.cgadispon) { + if (colorplus->cga.displine < colorplus->cga.firstline) { + colorplus->cga.firstline = colorplus->cga.displine; + video_wait_for_buffer(); + } + colorplus->cga.lastline = colorplus->cga.displine; + /* Left / right border */ + for (c = 0; c < 8; c++) { + buffer32->line[colorplus->cga.displine][c] = buffer32->line[colorplus->cga.displine][c + (colorplus->cga.crtc[1] << 4) + 8] = (colorplus->cga.cgacol & 15) + 16; + } + if (colorplus->control & COLORPLUS_320x200_MODE) { + for (x = 0; x < colorplus->cga.crtc[1]; x++) { + dat0 = (plane0[((colorplus->cga.ma << 1) & 0x1fff) + ((colorplus->cga.sc & 1) * 0x2000)] << 8) | plane0[((colorplus->cga.ma << 1) & 0x1fff) + ((colorplus->cga.sc & 1) * 0x2000) + 1]; + dat1 = (plane1[((colorplus->cga.ma << 1) & 0x1fff) + ((colorplus->cga.sc & 1) * 0x2000)] << 8) | plane1[((colorplus->cga.ma << 1) & 0x1fff) + ((colorplus->cga.sc & 1) * 0x2000) + 1]; + colorplus->cga.ma++; + for (c = 0; c < 8; c++) { + buffer32->line[colorplus->cga.displine][(x << 4) + (c << 1) + 8] = buffer32->line[colorplus->cga.displine][(x << 4) + (c << 1) + 1 + 8] = cols16[(dat0 >> 14) | ((dat1 >> 14) << 2)]; + dat0 <<= 2; + dat1 <<= 2; + } + } + } else if (colorplus->control & COLORPLUS_640x200_MODE) { + cols[0] = (colorplus->cga.cgacol & 15) | 16; + col = (colorplus->cga.cgacol & 16) ? 24 : 16; + if (colorplus->cga.cgamode & 4) { + cols[1] = col | 3; + cols[2] = col | 4; + cols[3] = col | 7; + } else if (colorplus->cga.cgacol & 32) { + cols[1] = col | 3; + cols[2] = col | 5; + cols[3] = col | 7; + } else { + cols[1] = col | 2; + cols[2] = col | 4; + cols[3] = col | 6; + } + for (x = 0; x < colorplus->cga.crtc[1]; x++) { + dat0 = (plane0[((colorplus->cga.ma << 1) & 0x1fff) + ((colorplus->cga.sc & 1) * 0x2000)] << 8) | plane0[((colorplus->cga.ma << 1) & 0x1fff) + ((colorplus->cga.sc & 1) * 0x2000) + 1]; + dat1 = (plane1[((colorplus->cga.ma << 1) & 0x1fff) + ((colorplus->cga.sc & 1) * 0x2000)] << 8) | plane1[((colorplus->cga.ma << 1) & 0x1fff) + ((colorplus->cga.sc & 1) * 0x2000) + 1]; + colorplus->cga.ma++; + for (c = 0; c < 16; c++) { + buffer32->line[colorplus->cga.displine][(x << 4) + c + 8] = cols[(dat0 >> 15) | ((dat1 >> 15) << 1)]; + dat0 <<= 1; + dat1 <<= 1; + } + } + } + } else /* Top / bottom border */ { - colorplus->control = val & 0x70; - } + cols[0] = (colorplus->cga.cgacol & 15) + 16; + hline(buffer32, 0, colorplus->cga.displine, (colorplus->cga.crtc[1] << 4) + 16, cols[0]); + } + + x = (colorplus->cga.crtc[1] << 4) + 16; + + if (colorplus->cga.composite) + Composite_Process(colorplus->cga.cgamode, 0, x >> 2, buffer32->line[colorplus->cga.displine]); else - { - cga_out(addr, val, &colorplus->cga); - } -} + video_process_8(x, colorplus->cga.displine); -uint8_t colorplus_in(uint16_t addr, void *p) -{ - colorplus_t *colorplus = (colorplus_t *)p; - - return cga_in(addr, &colorplus->cga); -} - -void colorplus_write(uint32_t addr, uint8_t val, void *p) -{ - colorplus_t *colorplus = (colorplus_t *)p; - - if ((colorplus->control & COLORPLUS_PLANE_SWAP) && - (colorplus->control & COLORPLUS_EITHER_MODE) && - (colorplus->cga.cgamode & CGA_GRAPHICS_MODE)) - { - addr ^= 0x4000; - } - else if (!(colorplus->control & COLORPLUS_EITHER_MODE)) - { - addr &= 0x3FFF; - } - colorplus->cga.vram[addr & 0x7fff] = val; - if (colorplus->cga.snow_enabled) - { - int offset = ((timer_get_remaining_u64(&colorplus->cga.timer) / CGACONST) * 2) & 0xfc; - colorplus->cga.charbuffer[offset] = colorplus->cga.vram[addr & 0x7fff]; - colorplus->cga.charbuffer[offset | 1] = colorplus->cga.vram[addr & 0x7fff]; + colorplus->cga.sc = oldsc; + if (colorplus->cga.vc == colorplus->cga.crtc[7] && !colorplus->cga.sc) + colorplus->cga.cgastat |= 8; + colorplus->cga.displine++; + if (colorplus->cga.displine >= 360) + colorplus->cga.displine = 0; + } else { + timer_advance_u64(&colorplus->cga.timer, colorplus->cga.dispontime); + colorplus->cga.linepos = 0; + if (colorplus->cga.vsynctime) { + colorplus->cga.vsynctime--; + if (!colorplus->cga.vsynctime) + colorplus->cga.cgastat &= ~8; } - cycles -= 4; -} - -uint8_t colorplus_read(uint32_t addr, void *p) -{ - colorplus_t *colorplus = (colorplus_t *)p; - - if ((colorplus->control & COLORPLUS_PLANE_SWAP) && - (colorplus->control & COLORPLUS_EITHER_MODE) && - (colorplus->cga.cgamode & CGA_GRAPHICS_MODE)) - { - addr ^= 0x4000; - } - else if (!(colorplus->control & COLORPLUS_EITHER_MODE)) - { - addr &= 0x3FFF; - } - cycles -= 4; - if (colorplus->cga.snow_enabled) - { - int offset = ((timer_get_remaining_u64(&colorplus->cga.timer) / CGACONST) * 2) & 0xfc; - colorplus->cga.charbuffer[offset] = colorplus->cga.vram[addr & 0x7fff]; - colorplus->cga.charbuffer[offset | 1] = colorplus->cga.vram[addr & 0x7fff]; + if (colorplus->cga.sc == (colorplus->cga.crtc[11] & 31) || ((colorplus->cga.crtc[8] & 3) == 3 && colorplus->cga.sc == ((colorplus->cga.crtc[11] & 31) >> 1))) { + colorplus->cga.con = 0; + colorplus->cga.coff = 1; } - return colorplus->cga.vram[addr & 0x7fff]; -} + if ((colorplus->cga.crtc[8] & 3) == 3 && colorplus->cga.sc == (colorplus->cga.crtc[9] >> 1)) + colorplus->cga.maback = colorplus->cga.ma; + if (colorplus->cga.vadj) { + colorplus->cga.sc++; + colorplus->cga.sc &= 31; + colorplus->cga.ma = colorplus->cga.maback; + colorplus->cga.vadj--; + if (!colorplus->cga.vadj) { + colorplus->cga.cgadispon = 1; + colorplus->cga.ma = colorplus->cga.maback = (colorplus->cga.crtc[13] | (colorplus->cga.crtc[12] << 8)) & 0x3fff; + colorplus->cga.sc = 0; + } + } else if (colorplus->cga.sc == colorplus->cga.crtc[9]) { + colorplus->cga.maback = colorplus->cga.ma; + colorplus->cga.sc = 0; + oldvc = colorplus->cga.vc; + colorplus->cga.vc++; + colorplus->cga.vc &= 127; -void colorplus_recalctimings(colorplus_t *colorplus) -{ - cga_recalctimings(&colorplus->cga); -} + if (colorplus->cga.vc == colorplus->cga.crtc[6]) + colorplus->cga.cgadispon = 0; -void colorplus_poll(void *p) -{ - colorplus_t *colorplus = (colorplus_t *)p; - int x, c; - int oldvc; - uint16_t dat0, dat1; - int cols[4]; - int col; - int oldsc; - static const int cols16[16] = { 0x10,0x12,0x14,0x16, - 0x18,0x1A,0x1C,0x1E, - 0x11,0x13,0x15,0x17, - 0x19,0x1B,0x1D,0x1F }; - uint8_t *plane0 = colorplus->cga.vram; - uint8_t *plane1 = colorplus->cga.vram + 0x4000; - - /* If one of the extra modes is not selected, drop down to the CGA - * drawing code. */ - if (!((colorplus->control & COLORPLUS_EITHER_MODE) && - (colorplus->cga.cgamode & CGA_GRAPHICS_MODE))) - { - cga_poll(&colorplus->cga); - return; - } - - if (!colorplus->cga.linepos) - { - timer_advance_u64(&colorplus->cga.timer, colorplus->cga.dispofftime); - colorplus->cga.cgastat |= 1; - colorplus->cga.linepos = 1; - oldsc = colorplus->cga.sc; - if ((colorplus->cga.crtc[8] & 3) == 3) - colorplus->cga.sc = ((colorplus->cga.sc << 1) + colorplus->cga.oddeven) & 7; - if (colorplus->cga.cgadispon) - { - if (colorplus->cga.displine < colorplus->cga.firstline) - { - colorplus->cga.firstline = colorplus->cga.displine; - video_wait_for_buffer(); - } - colorplus->cga.lastline = colorplus->cga.displine; - /* Left / right border */ - for (c = 0; c < 8; c++) - { - buffer32->line[colorplus->cga.displine][c] = - buffer32->line[colorplus->cga.displine][c + (colorplus->cga.crtc[1] << 4) + 8] = - (colorplus->cga.cgacol & 15) + 16; - } - if (colorplus->control & COLORPLUS_320x200_MODE) - { - for (x = 0; x < colorplus->cga.crtc[1]; x++) - { - dat0 = (plane0[((colorplus->cga.ma << 1) & 0x1fff) + ((colorplus->cga.sc & 1) * 0x2000)] << 8) | - plane0[((colorplus->cga.ma << 1) & 0x1fff) + ((colorplus->cga.sc & 1) * 0x2000) + 1]; - dat1 = (plane1[((colorplus->cga.ma << 1) & 0x1fff) + ((colorplus->cga.sc & 1) * 0x2000)] << 8) | - plane1[((colorplus->cga.ma << 1) & 0x1fff) + ((colorplus->cga.sc & 1) * 0x2000) + 1]; - colorplus->cga.ma++; - for (c = 0; c < 8; c++) - { - buffer32->line[colorplus->cga.displine][(x << 4) + (c << 1) + 8] = - buffer32->line[colorplus->cga.displine][(x << 4) + (c << 1) + 1 + 8] = - cols16[(dat0 >> 14) | ((dat1 >> 14) << 2)]; - dat0 <<= 2; - dat1 <<= 2; - } - } - } - else if (colorplus->control & COLORPLUS_640x200_MODE) - { - cols[0] = (colorplus->cga.cgacol & 15) | 16; - col = (colorplus->cga.cgacol & 16) ? 24 : 16; - if (colorplus->cga.cgamode & 4) - { - cols[1] = col | 3; - cols[2] = col | 4; - cols[3] = col | 7; - } - else if (colorplus->cga.cgacol & 32) - { - cols[1] = col | 3; - cols[2] = col | 5; - cols[3] = col | 7; - } - else - { - cols[1] = col | 2; - cols[2] = col | 4; - cols[3] = col | 6; - } - for (x = 0; x < colorplus->cga.crtc[1]; x++) - { - dat0 = (plane0[((colorplus->cga.ma << 1) & 0x1fff) + ((colorplus->cga.sc & 1) * 0x2000)] << 8) | - plane0[((colorplus->cga.ma << 1) & 0x1fff) + ((colorplus->cga.sc & 1) * 0x2000) + 1]; - dat1 = (plane1[((colorplus->cga.ma << 1) & 0x1fff) + ((colorplus->cga.sc & 1) * 0x2000)] << 8) | - plane1[((colorplus->cga.ma << 1) & 0x1fff) + ((colorplus->cga.sc & 1) * 0x2000) + 1]; - colorplus->cga.ma++; - for (c = 0; c < 16; c++) - { - buffer32->line[colorplus->cga.displine][(x << 4) + c + 8] = - cols[(dat0 >> 15) | ((dat1 >> 15) << 1)]; - dat0 <<= 1; - dat1 <<= 1; - } - } - } - } - else /* Top / bottom border */ - { - cols[0] = (colorplus->cga.cgacol & 15) + 16; - hline(buffer32, 0, colorplus->cga.displine, (colorplus->cga.crtc[1] << 4) + 16, cols[0]); - } - - x = (colorplus->cga.crtc[1] << 4) + 16; - - if (colorplus->cga.composite) - Composite_Process(colorplus->cga.cgamode, 0, x >> 2, buffer32->line[colorplus->cga.displine]); - - colorplus->cga.sc = oldsc; - if (colorplus->cga.vc == colorplus->cga.crtc[7] && !colorplus->cga.sc) - colorplus->cga.cgastat |= 8; - colorplus->cga.displine++; - if (colorplus->cga.displine >= 360) - colorplus->cga.displine = 0; - } - else - { - timer_advance_u64(&colorplus->cga.timer, colorplus->cga.dispontime); - colorplus->cga.linepos = 0; - if (colorplus->cga.vsynctime) - { - colorplus->cga.vsynctime--; - if (!colorplus->cga.vsynctime) - colorplus->cga.cgastat &= ~8; - } - if (colorplus->cga.sc == (colorplus->cga.crtc[11] & 31) || ((colorplus->cga.crtc[8] & 3) == 3 && colorplus->cga.sc == ((colorplus->cga.crtc[11] & 31) >> 1))) - { - colorplus->cga.con = 0; - colorplus->cga.coff = 1; - } - if ((colorplus->cga.crtc[8] & 3) == 3 && colorplus->cga.sc == (colorplus->cga.crtc[9] >> 1)) - colorplus->cga.maback = colorplus->cga.ma; - if (colorplus->cga.vadj) - { - colorplus->cga.sc++; - colorplus->cga.sc &= 31; - colorplus->cga.ma = colorplus->cga.maback; - colorplus->cga.vadj--; - if (!colorplus->cga.vadj) - { - colorplus->cga.cgadispon = 1; - colorplus->cga.ma = colorplus->cga.maback = (colorplus->cga.crtc[13] | (colorplus->cga.crtc[12] << 8)) & 0x3fff; - colorplus->cga.sc = 0; - } - } - else if (colorplus->cga.sc == colorplus->cga.crtc[9]) - { - colorplus->cga.maback = colorplus->cga.ma; - colorplus->cga.sc = 0; - oldvc = colorplus->cga.vc; - colorplus->cga.vc++; - colorplus->cga.vc &= 127; - - if (colorplus->cga.vc == colorplus->cga.crtc[6]) - colorplus->cga.cgadispon = 0; - - if (oldvc == colorplus->cga.crtc[4]) - { - colorplus->cga.vc = 0; - colorplus->cga.vadj = colorplus->cga.crtc[5]; - if (!colorplus->cga.vadj) colorplus->cga.cgadispon = 1; - if (!colorplus->cga.vadj) colorplus->cga.ma = colorplus->cga.maback = (colorplus->cga.crtc[13] | (colorplus->cga.crtc[12] << 8)) & 0x3fff; - if ((colorplus->cga.crtc[10] & 0x60) == 0x20) colorplus->cga.cursoron = 0; - else colorplus->cga.cursoron = colorplus->cga.cgablink & 8; - } - - if (colorplus->cga.vc == colorplus->cga.crtc[7]) - { - colorplus->cga.cgadispon = 0; - colorplus->cga.displine = 0; - colorplus->cga.vsynctime = 16; - if (colorplus->cga.crtc[7]) - { - if (colorplus->cga.cgamode & 1) x = (colorplus->cga.crtc[1] << 3) + 16; - else x = (colorplus->cga.crtc[1] << 4) + 16; - colorplus->cga.lastline++; - if (x != xsize || (colorplus->cga.lastline - colorplus->cga.firstline) != ysize) - { - xsize = x; - ysize = colorplus->cga.lastline - colorplus->cga.firstline; - if (xsize < 64) xsize = 656; - if (ysize < 32) ysize = 200; - set_screen_size(xsize, (ysize << 1) + 16); - } - - if (colorplus->cga.composite) - video_blit_memtoscreen(0, colorplus->cga.firstline - 4, xsize, (colorplus->cga.lastline - colorplus->cga.firstline) + 8); - else - video_blit_memtoscreen_8(0, colorplus->cga.firstline - 4, xsize, (colorplus->cga.lastline - colorplus->cga.firstline) + 8); - frames++; - - video_res_x = xsize - 16; - video_res_y = ysize; - if (colorplus->cga.cgamode & 1) - { - video_res_x /= 8; - video_res_y /= colorplus->cga.crtc[9] + 1; - video_bpp = 0; - } - else if (!(colorplus->cga.cgamode & 2)) - { - video_res_x /= 16; - video_res_y /= colorplus->cga.crtc[9] + 1; - video_bpp = 0; - } - else if (!(colorplus->cga.cgamode & 16)) - { - video_res_x /= 2; - video_bpp = 2; - } - else - { - video_bpp = 1; - } - } - colorplus->cga.firstline = 1000; - colorplus->cga.lastline = 0; - colorplus->cga.cgablink++; - colorplus->cga.oddeven ^= 1; - } - } + if (oldvc == colorplus->cga.crtc[4]) { + colorplus->cga.vc = 0; + colorplus->cga.vadj = colorplus->cga.crtc[5]; + if (!colorplus->cga.vadj) + colorplus->cga.cgadispon = 1; + if (!colorplus->cga.vadj) + colorplus->cga.ma = colorplus->cga.maback = (colorplus->cga.crtc[13] | (colorplus->cga.crtc[12] << 8)) & 0x3fff; + if ((colorplus->cga.crtc[10] & 0x60) == 0x20) + colorplus->cga.cursoron = 0; else - { - colorplus->cga.sc++; - colorplus->cga.sc &= 31; - colorplus->cga.ma = colorplus->cga.maback; - } - if (colorplus->cga.cgadispon) - colorplus->cga.cgastat &= ~1; - if ((colorplus->cga.sc == (colorplus->cga.crtc[10] & 31) || ((colorplus->cga.crtc[8] & 3) == 3 && colorplus->cga.sc == ((colorplus->cga.crtc[10] & 31) >> 1)))) - colorplus->cga.con = 1; - if (colorplus->cga.cgadispon && (colorplus->cga.cgamode & 1)) - { - for (x = 0; x < (colorplus->cga.crtc[1] << 1); x++) - colorplus->cga.charbuffer[x] = colorplus->cga.vram[(((colorplus->cga.ma << 1) + x) & 0x3fff)]; + colorplus->cga.cursoron = colorplus->cga.cgablink & 8; + } + + if (colorplus->cga.vc == colorplus->cga.crtc[7]) { + colorplus->cga.cgadispon = 0; + colorplus->cga.displine = 0; + colorplus->cga.vsynctime = 16; + if (colorplus->cga.crtc[7]) { + if (colorplus->cga.cgamode & 1) + x = (colorplus->cga.crtc[1] << 3) + 16; + else + x = (colorplus->cga.crtc[1] << 4) + 16; + colorplus->cga.lastline++; + if (x != xsize || (colorplus->cga.lastline - colorplus->cga.firstline) != ysize) { + xsize = x; + ysize = colorplus->cga.lastline - colorplus->cga.firstline; + if (xsize < 64) + xsize = 656; + if (ysize < 32) + ysize = 200; + set_screen_size(xsize, (ysize << 1) + 16); + } + + video_blit_memtoscreen(0, colorplus->cga.firstline - 4, xsize, (colorplus->cga.lastline - colorplus->cga.firstline) + 8); + frames++; + + video_res_x = xsize - 16; + video_res_y = ysize; + if (colorplus->cga.cgamode & 1) { + video_res_x /= 8; + video_res_y /= colorplus->cga.crtc[9] + 1; + video_bpp = 0; + } else if (!(colorplus->cga.cgamode & 2)) { + video_res_x /= 16; + video_res_y /= colorplus->cga.crtc[9] + 1; + video_bpp = 0; + } else if (!(colorplus->cga.cgamode & 16)) { + video_res_x /= 2; + video_bpp = 2; + } else { + video_bpp = 1; + } } + colorplus->cga.firstline = 1000; + colorplus->cga.lastline = 0; + colorplus->cga.cgablink++; + colorplus->cga.oddeven ^= 1; + } + } else { + colorplus->cga.sc++; + colorplus->cga.sc &= 31; + colorplus->cga.ma = colorplus->cga.maback; } -} - -void colorplus_init(colorplus_t *colorplus) -{ - cga_init(&colorplus->cga); -} - -void *colorplus_standalone_init(const device_t *info) -{ - int display_type; - - colorplus_t *colorplus = malloc(sizeof(colorplus_t)); - memset(colorplus, 0, sizeof(colorplus_t)); - - video_inform(VIDEO_FLAG_TYPE_CGA, &timing_colorplus); - - /* Copied from the CGA init. Ideally this would be done by - * calling a helper function rather than duplicating code */ - display_type = device_get_config_int("display_type"); - colorplus->cga.composite = (display_type != CGA_RGB); - colorplus->cga.revision = device_get_config_int("composite_type"); - colorplus->cga.snow_enabled = device_get_config_int("snow_enabled"); - - colorplus->cga.vram = malloc(0x8000); - - cga_comp_init(colorplus->cga.revision); - timer_add(&colorplus->cga.timer, colorplus_poll, colorplus, 1); - mem_mapping_add(&colorplus->cga.mapping, 0xb8000, 0x08000, colorplus_read, NULL, NULL, colorplus_write, NULL, NULL, NULL, MEM_MAPPING_EXTERNAL, colorplus); - io_sethandler(0x03d0, 0x0010, colorplus_in, NULL, NULL, colorplus_out, NULL, NULL, colorplus); - - lpt3_init(0x3BC); - - return colorplus; -} - -void colorplus_close(void *p) -{ - colorplus_t *colorplus = (colorplus_t *)p; - - free(colorplus->cga.vram); - free(colorplus); -} - -void colorplus_speed_changed(void *p) -{ - colorplus_t *colorplus = (colorplus_t *)p; - - cga_recalctimings(&colorplus->cga); -} - -static const device_config_t colorplus_config[] = -{ - { - "display_type", "Display type", CONFIG_SELECTION, "", CGA_RGB, "", { 0 }, - { - { - "RGB", CGA_RGB - }, - { - "Composite", CGA_COMPOSITE - }, - { - "" - } - } - }, - { - "composite_type", "Composite type", CONFIG_SELECTION, "", COMPOSITE_OLD, "", { 0 }, - { - { - "Old", COMPOSITE_OLD - }, - { - "New", COMPOSITE_NEW - }, - { - "" - } - } - }, - { - "snow_enabled", "Snow emulation", CONFIG_BINARY, "", 1 - }, - { - "", "", -1 + if (colorplus->cga.cgadispon) + colorplus->cga.cgastat &= ~1; + if (colorplus->cga.sc == (colorplus->cga.crtc[10] & 31) || ((colorplus->cga.crtc[8] & 3) == 3 && colorplus->cga.sc == ((colorplus->cga.crtc[10] & 31) >> 1))) + colorplus->cga.con = 1; + if (colorplus->cga.cgadispon && (colorplus->cga.cgamode & 1)) { + for (x = 0; x < (colorplus->cga.crtc[1] << 1); x++) + colorplus->cga.charbuffer[x] = colorplus->cga.vram[((colorplus->cga.ma << 1) + x) & 0x3fff]; } + } +} + +void +colorplus_init(colorplus_t *colorplus) +{ + cga_init(&colorplus->cga); +} + +void * +colorplus_standalone_init(UNUSED(const device_t *info)) +{ + int display_type; + + colorplus_t *colorplus = malloc(sizeof(colorplus_t)); + memset(colorplus, 0, sizeof(colorplus_t)); + + video_inform(VIDEO_FLAG_TYPE_CGA, &timing_colorplus); + + /* Copied from the CGA init. Ideally this would be done by + * calling a helper function rather than duplicating code */ + display_type = device_get_config_int("display_type"); + colorplus->cga.composite = (display_type != CGA_RGB); + colorplus->cga.revision = device_get_config_int("composite_type"); + colorplus->cga.snow_enabled = device_get_config_int("snow_enabled"); + + colorplus->cga.vram = malloc(0x8000); + + cga_comp_init(colorplus->cga.revision); + timer_add(&colorplus->cga.timer, colorplus_poll, colorplus, 1); + mem_mapping_add(&colorplus->cga.mapping, 0xb8000, 0x08000, colorplus_read, NULL, NULL, colorplus_write, NULL, NULL, NULL, MEM_MAPPING_EXTERNAL, colorplus); + io_sethandler(0x03d0, 0x0010, colorplus_in, NULL, NULL, colorplus_out, NULL, NULL, colorplus); + + lpt3_init(0x3BC); + + return colorplus; +} + +void +colorplus_close(void *priv) +{ + colorplus_t *colorplus = (colorplus_t *) priv; + + free(colorplus->cga.vram); + free(colorplus); +} + +void +colorplus_speed_changed(void *priv) +{ + colorplus_t *colorplus = (colorplus_t *) priv; + + cga_recalctimings(&colorplus->cga); +} + +static const device_config_t colorplus_config[] = { + // clang-format off + { + .name = "display_type", + .description = "Display type", + .type = CONFIG_SELECTION, + .default_int = CGA_RGB, + .selection = { + { + .description = "RGB", + .value = CGA_RGB + }, + { + .description = "Composite", + .value = CGA_COMPOSITE + }, + { + .description = "" + } + } + }, + { + .name = "composite_type", + .description = "Composite type", + .type = CONFIG_SELECTION, + .default_int = COMPOSITE_OLD, + .selection = { + { + .description = "Old", + .value = COMPOSITE_OLD + }, + { + .description = "New", + .value = COMPOSITE_NEW + }, + { + .description = "" + } + } + }, + { + .name = "snow_enabled", + .description = "Snow emulation", + .type = CONFIG_BINARY, + .default_int = 1 + }, + { + .type = CONFIG_END + } + // clang-format on }; -const device_t colorplus_device = -{ - "Colorplus", - "plantronics", - DEVICE_ISA, 0, - colorplus_standalone_init, - colorplus_close, - NULL, { NULL }, - colorplus_speed_changed, - NULL, - colorplus_config +const device_t colorplus_device = { + .name = "Colorplus", + .internal_name = "plantronics", + .flags = DEVICE_ISA, + .local = 0, + .init = colorplus_standalone_init, + .close = colorplus_close, + .reset = NULL, + { .available = NULL }, + .speed_changed = colorplus_speed_changed, + .force_redraw = NULL, + .config = colorplus_config }; diff --git a/src/video/vid_compaq_cga.c b/src/video/vid_compaq_cga.c index 821b4c4a9..4753ec223 100644 --- a/src/video/vid_compaq_cga.c +++ b/src/video/vid_compaq_cga.c @@ -1,29 +1,31 @@ /* - * 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. + * 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. + * This file is part of the 86Box distribution. * - * Emulation of the Compaq CGA graphics cards. + * Emulation of the Compaq CGA graphics cards. * * * - * Authors: John Elliott, - * Sarah Walker, - * Miran Grca, + * Authors: John Elliott, + * Sarah Walker, + * Miran Grca, * - * Copyright 2016-2019 John Elliott. - * Copyright 2008-2019 Sarah Walker. - * Copyright 2016-2019 Miran Grca. + * Copyright 2016-2019 John Elliott. + * Copyright 2008-2019 Sarah Walker. + * Copyright 2016-2019 Miran Grca. */ +#include #include #include #include #include #include #include +#define HAVE_STDARG_H #include <86box/86box.h> #include "cpu.h" #include <86box/io.h> @@ -36,378 +38,374 @@ #include <86box/vid_cga.h> #include <86box/vid_cga_comp.h> - -#define CGA_RGB 0 +#define CGA_RGB 0 #define CGA_COMPOSITE 1 +static uint32_t vflags; +static uint8_t mdaattr[256][2][2]; -static uint32_t vflags; -static uint8_t mdaattr[256][2][2]; - - -typedef struct compaq_cga_t -{ +typedef struct compaq_cga_t { cga_t cga; } compaq_cga_t; - #ifdef ENABLE_COMPAQ_CGA_LOG int compaq_cga_do_log = ENABLE_COMPAQ_CGA_LOG; - static void compaq_cga_log(const char *fmt, ...) { va_list ap; if (compaq_cga_do_log) { - va_start(ap, fmt); - pclog_ex(fmt, ap); - va_end(ap); + va_start(ap, fmt); + pclog_ex(fmt, ap); + va_end(ap); } } #else -#define compaq_cga_log(fmt, ...) +# define compaq_cga_log(fmt, ...) #endif - void compaq_cga_recalctimings(compaq_cga_t *self) { - double _dispontime, _dispofftime, disptime; + double _dispontime; + double _dispofftime; + double disptime; disptime = self->cga.crtc[0] + 1; - _dispontime = self->cga.crtc[1]; + _dispontime = self->cga.crtc[1]; _dispofftime = disptime - _dispontime; _dispontime *= MDACONST; _dispofftime *= MDACONST; - self->cga.dispontime = (uint64_t)(_dispontime); - self->cga.dispofftime = (uint64_t)(_dispofftime); + self->cga.dispontime = (uint64_t) (_dispontime); + self->cga.dispofftime = (uint64_t) (_dispofftime); } - void -compaq_cga_poll(void *p) +compaq_cga_poll(void *priv) { - compaq_cga_t *self = (compaq_cga_t *)p; - uint16_t ca = (self->cga.crtc[15] | (self->cga.crtc[14] << 8)) & 0x3fff; - int drawcursor; - int x, c, xs_temp, ys_temp; - int oldvc; - uint8_t chr, attr; - uint8_t border; - uint8_t cols[4]; - int oldsc; - int underline = 0; - int blink = 0; + compaq_cga_t *self = (compaq_cga_t *) priv; + uint16_t ca = (self->cga.crtc[15] | (self->cga.crtc[14] << 8)) & 0x3fff; + int drawcursor; + int x; + int c; + int xs_temp; + int ys_temp; + int oldvc; + uint8_t chr; + uint8_t attr; + uint8_t border; + uint8_t cols[4]; + int oldsc; + int underline = 0; + int blink = 0; /* If in graphics mode or character height is not 13, behave as CGA */ if ((self->cga.cgamode & 0x12) || (self->cga.crtc[9] != 13)) { - overscan_x = overscan_y = 16; - cga_poll(&self->cga); - return; + overscan_x = overscan_y = 16; + cga_poll(&self->cga); + return; } else - overscan_x = overscan_y = 0; + overscan_x = overscan_y = 0; /* We are in Compaq 350-line CGA territory */ if (!self->cga.linepos) { - timer_advance_u64(&self->cga.timer, self->cga.dispofftime); - self->cga.cgastat |= 1; - self->cga.linepos = 1; - oldsc = self->cga.sc; - if ((self->cga.crtc[8] & 3) == 3) - self->cga.sc = ((self->cga.sc << 1) + self->cga.oddeven) & 7; - if (self->cga.cgadispon) { - if (self->cga.displine < self->cga.firstline) { - self->cga.firstline = self->cga.displine; - video_wait_for_buffer(); - compaq_cga_log("Firstline %i\n", firstline); - } - self->cga.lastline = self->cga.displine; + timer_advance_u64(&self->cga.timer, self->cga.dispofftime); + self->cga.cgastat |= 1; + self->cga.linepos = 1; + oldsc = self->cga.sc; + if ((self->cga.crtc[8] & 3) == 3) + self->cga.sc = ((self->cga.sc << 1) + self->cga.oddeven) & 7; + if (self->cga.cgadispon) { + if (self->cga.displine < self->cga.firstline) { + self->cga.firstline = self->cga.displine; + video_wait_for_buffer(); + compaq_cga_log("Firstline %i\n", firstline); + } + self->cga.lastline = self->cga.displine; - cols[0] = (self->cga.cgacol & 15) + 16; + cols[0] = (self->cga.cgacol & 15) + 16; - for (c = 0; c < 8; c++) { - buffer32->line[self->cga.displine][c] = cols[0]; - if (self->cga.cgamode & 1) - buffer32->line[self->cga.displine][c + (self->cga.crtc[1] << 3) + 8] = cols[0]; - else - buffer32->line[self->cga.displine][c + (self->cga.crtc[1] << 4) + 8] = cols[0]; - } + for (c = 0; c < 8; c++) { + buffer32->line[self->cga.displine][c] = cols[0]; + if (self->cga.cgamode & 1) + buffer32->line[self->cga.displine][c + (self->cga.crtc[1] << 3) + 8] = cols[0]; + else + buffer32->line[self->cga.displine][c + (self->cga.crtc[1] << 4) + 8] = cols[0]; + } - if (self->cga.cgamode & 1) { - for (x = 0; x < self->cga.crtc[1]; x++) { - chr = self->cga.charbuffer[x << 1]; - attr = self->cga.charbuffer[(x << 1) + 1]; - drawcursor = ((self->cga.ma == ca) && self->cga.con && self->cga.cursoron); + if (self->cga.cgamode & 1) { + for (x = 0; x < self->cga.crtc[1]; x++) { + chr = self->cga.charbuffer[x << 1]; + attr = self->cga.charbuffer[(x << 1) + 1]; + drawcursor = ((self->cga.ma == ca) && self->cga.con && self->cga.cursoron); - if (vflags) { - underline = 0; - blink = ((self->cga.cgablink & 8) && (self->cga.cgamode & 0x20) && (attr & 0x80) && !drawcursor); - } + if (vflags) { + underline = 0; + blink = ((self->cga.cgablink & 8) && (self->cga.cgamode & 0x20) && (attr & 0x80) && !drawcursor); + } - if (vflags && (self->cga.cgamode & 0x80)) { - cols[0] = mdaattr[attr][blink][0]; - cols[1] = mdaattr[attr][blink][1]; + if (vflags && (self->cga.cgamode & 0x80)) { + cols[0] = mdaattr[attr][blink][0]; + cols[1] = mdaattr[attr][blink][1]; - if ((self->cga.sc == 12) && ((attr & 7) == 1)) - underline = 1; - } else if (self->cga.cgamode & 0x20) { - cols[1] = (attr & 15) + 16; - cols[0] = ((attr >> 4) & 7) + 16; + if ((self->cga.sc == 12) && ((attr & 7) == 1)) + underline = 1; + } else if (self->cga.cgamode & 0x20) { + cols[1] = (attr & 15) + 16; + cols[0] = ((attr >> 4) & 7) + 16; - if (vflags) { - if (blink) - cols[1] = cols[0]; - } else { - if ((self->cga.cgablink & 8) && (attr & 0x80) && !self->cga.drawcursor) - cols[1] = cols[0]; - } - } else { - cols[1] = (attr & 15) + 16; - cols[0] = (attr >> 4) + 16; - } + if (vflags) { + if (blink) + cols[1] = cols[0]; + } else { + if ((self->cga.cgablink & 8) && (attr & 0x80) && !self->cga.drawcursor) + cols[1] = cols[0]; + } + } else { + cols[1] = (attr & 15) + 16; + cols[0] = (attr >> 4) + 16; + } - if (vflags && underline) { - for (c = 0; c < 8; c++) - buffer32->line[self->cga.displine][(x << 3) + c + 8] = mdaattr[attr][blink][1]; - } else if (drawcursor) { - for (c = 0; c < 8; c++) - buffer32->line[self->cga.displine][(x << 3) + c + 8] = cols[(fontdatm[chr + self->cga.fontbase][self->cga.sc & 15] & (1 << (c ^ 7))) ? 1 : 0] ^ 15; - } else { - for (c = 0; c < 8; c++) - buffer32->line[self->cga.displine][(x << 3) + c + 8] = cols[(fontdatm[chr + self->cga.fontbase][self->cga.sc & 15] & (1 << (c ^ 7))) ? 1 : 0]; - } - self->cga.ma++; - } - } else { - for (x = 0; x < self->cga.crtc[1]; x++) { - chr = self->cga.vram[((self->cga.ma << 1) & 0x3fff)]; - attr = self->cga.vram[(((self->cga.ma << 1) + 1) & 0x3fff)]; - drawcursor = ((self->cga.ma == ca) && self->cga.con && self->cga.cursoron); + if (vflags && underline) { + for (c = 0; c < 8; c++) + buffer32->line[self->cga.displine][(x << 3) + c + 8] = mdaattr[attr][blink][1]; + } else if (drawcursor) { + for (c = 0; c < 8; c++) + buffer32->line[self->cga.displine][(x << 3) + c + 8] = cols[(fontdatm[chr + self->cga.fontbase][self->cga.sc & 15] & (1 << (c ^ 7))) ? 1 : 0] ^ 15; + } else { + for (c = 0; c < 8; c++) + buffer32->line[self->cga.displine][(x << 3) + c + 8] = cols[(fontdatm[chr + self->cga.fontbase][self->cga.sc & 15] & (1 << (c ^ 7))) ? 1 : 0]; + } + self->cga.ma++; + } + } else { + for (x = 0; x < self->cga.crtc[1]; x++) { + chr = self->cga.vram[(self->cga.ma << 1) & 0x3fff]; + attr = self->cga.vram[((self->cga.ma << 1) + 1) & 0x3fff]; + drawcursor = ((self->cga.ma == ca) && self->cga.con && self->cga.cursoron); - if (vflags) { - underline = 0; - blink = ((self->cga.cgablink & 8) && (self->cga.cgamode & 0x20) && (attr & 0x80) && !drawcursor); - } + if (vflags) { + underline = 0; + blink = ((self->cga.cgablink & 8) && (self->cga.cgamode & 0x20) && (attr & 0x80) && !drawcursor); + } - if (vflags && (self->cga.cgamode & 0x80)) { - cols[0] = mdaattr[attr][blink][0]; - cols[1] = mdaattr[attr][blink][1]; - if (self->cga.sc == 12 && (attr & 7) == 1) underline = 1; - } else if (self->cga.cgamode & 0x20) { - cols[1] = (attr & 15) + 16; - cols[0] = ((attr >> 4) & 7) + 16; + if (vflags && (self->cga.cgamode & 0x80)) { + cols[0] = mdaattr[attr][blink][0]; + cols[1] = mdaattr[attr][blink][1]; + if (self->cga.sc == 12 && (attr & 7) == 1) + underline = 1; + } else if (self->cga.cgamode & 0x20) { + cols[1] = (attr & 15) + 16; + cols[0] = ((attr >> 4) & 7) + 16; - if (vflags) { - if (blink) - cols[1] = cols[0]; - } else { - if ((self->cga.cgablink & 8) && (attr & 0x80) && !self->cga.drawcursor) - cols[1] = cols[0]; - } - } else { - cols[1] = (attr & 15) + 16; - cols[0] = (attr >> 4) + 16; - } - self->cga.ma++; + if (vflags) { + if (blink) + cols[1] = cols[0]; + } else { + if ((self->cga.cgablink & 8) && (attr & 0x80) && !self->cga.drawcursor) + cols[1] = cols[0]; + } + } else { + cols[1] = (attr & 15) + 16; + cols[0] = (attr >> 4) + 16; + } + self->cga.ma++; - if (vflags && underline) { - for (c = 0; c < 8; c++) - buffer32->line[self->cga.displine][(x << 4)+(c << 1) + 8] = - buffer32->line[self->cga.displine][(x << 4)+(c << 1) + 9] = mdaattr[attr][blink][1]; - } else if (drawcursor) { - for (c = 0; c < 8; c++) - buffer32->line[self->cga.displine][(x << 4)+(c << 1) + 8] = - buffer32->line[self->cga.displine][(x << 4) + (c << 1) + 1 + 8] = - cols[(fontdatm[chr + self->cga.fontbase][self->cga.sc & 15] & (1 << (c ^ 7))) ? 1 : 0] ^ 15; - } else { - for (c = 0; c < 8; c++) - buffer32->line[self->cga.displine][(x << 4) + (c << 1) + 8] = - buffer32->line[self->cga.displine][(x << 4) + (c << 1) + 1 + 8] = - cols[(fontdatm[chr + self->cga.fontbase][self->cga.sc & 15] & (1 << (c ^ 7))) ? 1 : 0]; - } - } - } - } else { - cols[0] = (self->cga.cgacol & 15) + 16; + if (vflags && underline) { + for (c = 0; c < 8; c++) + buffer32->line[self->cga.displine][(x << 4) + (c << 1) + 8] = buffer32->line[self->cga.displine][(x << 4) + (c << 1) + 9] = mdaattr[attr][blink][1]; + } else if (drawcursor) { + for (c = 0; c < 8; c++) + buffer32->line[self->cga.displine][(x << 4) + (c << 1) + 8] = buffer32->line[self->cga.displine][(x << 4) + (c << 1) + 1 + 8] = cols[(fontdatm[chr + self->cga.fontbase][self->cga.sc & 15] & (1 << (c ^ 7))) ? 1 : 0] ^ 15; + } else { + for (c = 0; c < 8; c++) + buffer32->line[self->cga.displine][(x << 4) + (c << 1) + 8] = buffer32->line[self->cga.displine][(x << 4) + (c << 1) + 1 + 8] = cols[(fontdatm[chr + self->cga.fontbase][self->cga.sc & 15] & (1 << (c ^ 7))) ? 1 : 0]; + } + } + } + } else { + cols[0] = (self->cga.cgacol & 15) + 16; - if (self->cga.cgamode & 1) hline(buffer32, 0, self->cga.displine, (self->cga.crtc[1] << 3) + 16, cols[0]); - else hline(buffer32, 0, self->cga.displine, (self->cga.crtc[1] << 4) + 16, cols[0]); - } + if (self->cga.cgamode & 1) + hline(buffer32, 0, self->cga.displine, (self->cga.crtc[1] << 3) + 16, cols[0]); + else + hline(buffer32, 0, self->cga.displine, (self->cga.crtc[1] << 4) + 16, cols[0]); + } - if (self->cga.cgamode & 1) x = (self->cga.crtc[1] << 3) + 16; - else x = (self->cga.crtc[1] << 4) + 16; + if (self->cga.cgamode & 1) + x = (self->cga.crtc[1] << 3) + 16; + else + x = (self->cga.crtc[1] << 4) + 16; - if (self->cga.composite) { - if (self->cga.cgamode & 0x10) - border = 0x00; - else - border = self->cga.cgacol & 0x0f; + if (self->cga.composite) { + if (self->cga.cgamode & 0x10) + border = 0x00; + else + border = self->cga.cgacol & 0x0f; - if (vflags) - Composite_Process(self->cga.cgamode & 0x7f, border, x >> 2, buffer32->line[self->cga.displine]); - else - Composite_Process(self->cga.cgamode, border, x >> 2, buffer32->line[self->cga.displine]); - } + if (vflags) + Composite_Process(self->cga.cgamode & 0x7f, border, x >> 2, buffer32->line[self->cga.displine]); + else + Composite_Process(self->cga.cgamode, border, x >> 2, buffer32->line[self->cga.displine]); + } else + video_process_8(x, self->cga.displine); - self->cga.sc = oldsc; - if (self->cga.vc == self->cga.crtc[7] && !self->cga.sc) - self->cga.cgastat |= 8; - self->cga.displine++; - if (self->cga.displine >= 500) - self->cga.displine = 0; + self->cga.sc = oldsc; + if (self->cga.vc == self->cga.crtc[7] && !self->cga.sc) + self->cga.cgastat |= 8; + self->cga.displine++; + if (self->cga.displine >= 500) + self->cga.displine = 0; } else { - timer_advance_u64(&self->cga.timer, self->cga.dispontime); - self->cga.linepos = 0; - if (self->cga.vsynctime) { - self->cga.vsynctime--; - if (!self->cga.vsynctime) - self->cga.cgastat &= ~8; - } + timer_advance_u64(&self->cga.timer, self->cga.dispontime); + self->cga.linepos = 0; + if (self->cga.vsynctime) { + self->cga.vsynctime--; + if (!self->cga.vsynctime) + self->cga.cgastat &= ~8; + } - if (self->cga.sc == (self->cga.crtc[11] & 31) || ((self->cga.crtc[8] & 3) == 3 && self->cga.sc == ((self->cga.crtc[11] & 31) >> 1))) { - self->cga.con = 0; - self->cga.coff = 1; - } - if ((self->cga.crtc[8] & 3) == 3 && self->cga.sc == (self->cga.crtc[9] >> 1)) - self->cga.maback = self->cga.ma; - if (self->cga.vadj) { - self->cga.sc++; - self->cga.sc &= 31; - self->cga.ma = self->cga.maback; - self->cga.vadj--; - if (!self->cga.vadj) { - self->cga.cgadispon = 1; - self->cga.ma = self->cga.maback = (self->cga.crtc[13] | (self->cga.crtc[12] << 8)) & 0x3fff; - self->cga.sc = 0; - } - } else if (self->cga.sc == self->cga.crtc[9]) { - self->cga.maback = self->cga.ma; - self->cga.sc = 0; - oldvc = self->cga.vc; - self->cga.vc++; - self->cga.vc &= 127; + if (self->cga.sc == (self->cga.crtc[11] & 31) || ((self->cga.crtc[8] & 3) == 3 && self->cga.sc == ((self->cga.crtc[11] & 31) >> 1))) { + self->cga.con = 0; + self->cga.coff = 1; + } + if ((self->cga.crtc[8] & 3) == 3 && self->cga.sc == (self->cga.crtc[9] >> 1)) + self->cga.maback = self->cga.ma; + if (self->cga.vadj) { + self->cga.sc++; + self->cga.sc &= 31; + self->cga.ma = self->cga.maback; + self->cga.vadj--; + if (!self->cga.vadj) { + self->cga.cgadispon = 1; + self->cga.ma = self->cga.maback = (self->cga.crtc[13] | (self->cga.crtc[12] << 8)) & 0x3fff; + self->cga.sc = 0; + } + } else if (self->cga.sc == self->cga.crtc[9]) { + self->cga.maback = self->cga.ma; + self->cga.sc = 0; + oldvc = self->cga.vc; + self->cga.vc++; + self->cga.vc &= 127; - if (self->cga.vc == self->cga.crtc[6]) - self->cga.cgadispon = 0; + if (self->cga.vc == self->cga.crtc[6]) + self->cga.cgadispon = 0; - if (oldvc == self->cga.crtc[4]) { - self->cga.vc = 0; - self->cga.vadj = self->cga.crtc[5]; + if (oldvc == self->cga.crtc[4]) { + self->cga.vc = 0; + self->cga.vadj = self->cga.crtc[5]; - if (!self->cga.vadj) self->cga.cgadispon = 1; + if (!self->cga.vadj) + self->cga.cgadispon = 1; - if (!self->cga.vadj) self->cga.ma = self->cga.maback = (self->cga.crtc[13] | (self->cga.crtc[12] << 8)) & 0x3fff; + if (!self->cga.vadj) + self->cga.ma = self->cga.maback = (self->cga.crtc[13] | (self->cga.crtc[12] << 8)) & 0x3fff; - if ((self->cga.crtc[10] & 0x60) == 0x20) - self->cga.cursoron = 0; - else - self->cga.cursoron = self->cga.cgablink & 8; - } + if ((self->cga.crtc[10] & 0x60) == 0x20) + self->cga.cursoron = 0; + else + self->cga.cursoron = self->cga.cgablink & 8; + } - if (self->cga.vc == self->cga.crtc[7]) { - self->cga.cgadispon = 0; - self->cga.displine = 0; - self->cga.vsynctime = 16; + if (self->cga.vc == self->cga.crtc[7]) { + self->cga.cgadispon = 0; + self->cga.displine = 0; + self->cga.vsynctime = 16; - if (self->cga.crtc[7]) { - compaq_cga_log("Lastline %i Firstline %i %i\n", self->cga.lastline, - self->cga.firstline ,self->cga.lastline - self->cga.firstline); + if (self->cga.crtc[7]) { + compaq_cga_log("Lastline %i Firstline %i %i\n", self->cga.lastline, + self->cga.firstline, self->cga.lastline - self->cga.firstline); - if (self->cga.cgamode & 1) x = (self->cga.crtc[1] << 3) + 16; - else x = (self->cga.crtc[1] << 4) + 16; + if (self->cga.cgamode & 1) + x = (self->cga.crtc[1] << 3) + 16; + else + x = (self->cga.crtc[1] << 4) + 16; - self->cga.lastline++; + self->cga.lastline++; - xs_temp = x; - ys_temp = (self->cga.lastline - self->cga.firstline); + xs_temp = x; + ys_temp = (self->cga.lastline - self->cga.firstline); - if ((xs_temp > 0) && (ys_temp > 0)) { - if (xs_temp < 64) xs_temp = 656; - if (ys_temp < 32) ys_temp = 400; - if (!enable_overscan) - xs_temp -= 16; + if ((xs_temp > 0) && (ys_temp > 0)) { + if (xs_temp < 64) + xs_temp = 656; + if (ys_temp < 32) + ys_temp = 400; + if (!enable_overscan) + xs_temp -= 16; - if ((self->cga.cgamode & 8) && ((xs_temp != xsize) || (ys_temp != ysize) || video_force_resize_get())) { - xsize = xs_temp; - ysize = ys_temp; - set_screen_size(xsize, ysize + (enable_overscan ? 16 : 0)); + if ((self->cga.cgamode & 8) && ((xs_temp != xsize) || (ys_temp != ysize) || video_force_resize_get())) { + xsize = xs_temp; + ysize = ys_temp; + set_screen_size(xsize, ysize + (enable_overscan ? 16 : 0)); - if (video_force_resize_get()) - video_force_resize_set(0); - } + if (video_force_resize_get()) + video_force_resize_set(0); + } - if (enable_overscan) { - if (self->cga.composite) - video_blit_memtoscreen(0, self->cga.firstline - 8, xsize, (self->cga.lastline - self->cga.firstline) + 16); - else - video_blit_memtoscreen_8(0, self->cga.firstline - 8, xsize, (self->cga.lastline - self->cga.firstline) + 16); - } else { - if (self->cga.composite) - video_blit_memtoscreen(8, self->cga.firstline, xsize, self->cga.lastline - self->cga.firstline); - else - video_blit_memtoscreen_8(8, self->cga.firstline, xsize, self->cga.lastline - self->cga.firstline); - } - } + if (enable_overscan) + video_blit_memtoscreen(0, self->cga.firstline - 8, xsize, (self->cga.lastline - self->cga.firstline) + 16); + else + video_blit_memtoscreen(8, self->cga.firstline, xsize, self->cga.lastline - self->cga.firstline); + } - frames++; + frames++; - video_res_x = xsize; - if (enable_overscan) - xsize -= 16; - video_res_y = ysize; - if (self->cga.cgamode & 1) { - video_res_x /= 8; - video_res_y /= self->cga.crtc[9] + 1; - video_bpp = 0; - } else if (!(self->cga.cgamode & 2)) { - video_res_x /= 16; - video_res_y /= self->cga.crtc[9] + 1; - video_bpp = 0; - } else if (!(self->cga.cgamode & 16)) { - video_res_x /= 2; - video_bpp = 2; - } else - video_bpp = 1; - } + video_res_x = xsize; + if (enable_overscan) + xsize -= 16; + video_res_y = ysize; + if (self->cga.cgamode & 1) { + video_res_x /= 8; + video_res_y /= self->cga.crtc[9] + 1; + video_bpp = 0; + } else if (!(self->cga.cgamode & 2)) { + video_res_x /= 16; + video_res_y /= self->cga.crtc[9] + 1; + video_bpp = 0; + } else if (!(self->cga.cgamode & 16)) { + video_res_x /= 2; + video_bpp = 2; + } else + video_bpp = 1; + } - self->cga.firstline = 1000; - self->cga.lastline = 0; - self->cga.cgablink++; - self->cga.oddeven ^= 1; - } - } else { - self->cga.sc++; - self->cga.sc &= 31; - self->cga.ma = self->cga.maback; - } + self->cga.firstline = 1000; + self->cga.lastline = 0; + self->cga.cgablink++; + self->cga.oddeven ^= 1; + } + } else { + self->cga.sc++; + self->cga.sc &= 31; + self->cga.ma = self->cga.maback; + } - if (self->cga.cgadispon) - self->cga.cgastat &= ~1; + if (self->cga.cgadispon) + self->cga.cgastat &= ~1; - if ((self->cga.sc == (self->cga.crtc[10] & 31) || ((self->cga.crtc[8] & 3) == 3 && self->cga.sc == ((self->cga.crtc[10] & 31) >> 1)))) - self->cga.con = 1; + if (self->cga.sc == (self->cga.crtc[10] & 31) || ((self->cga.crtc[8] & 3) == 3 && self->cga.sc == ((self->cga.crtc[10] & 31) >> 1))) + self->cga.con = 1; - if (self->cga.cgadispon && (self->cga.cgamode & 1)) { - for (x = 0; x < (self->cga.crtc[1] << 1); x++) - self->cga.charbuffer[x] = self->cga.vram[(((self->cga.ma << 1) + x) & 0x3fff)]; - } + if (self->cga.cgadispon && (self->cga.cgamode & 1)) { + for (x = 0; x < (self->cga.crtc[1] << 1); x++) + self->cga.charbuffer[x] = self->cga.vram[((self->cga.ma << 1) + x) & 0x3fff]; + } } } - void * compaq_cga_init(const device_t *info) { - int display_type; - int c; + int display_type; compaq_cga_t *self = malloc(sizeof(compaq_cga_t)); memset(self, 0, sizeof(compaq_cga_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"); + display_type = device_get_config_int("display_type"); + self->cga.composite = (display_type != CGA_RGB); + self->cga.revision = device_get_config_int("composite_type"); self->cga.snow_enabled = device_get_config_int("snow_enabled"); self->cga.vram = malloc(0x4000); @@ -418,24 +416,26 @@ compaq_cga_init(const device_t *info) io_sethandler(0x03d0, 0x0010, cga_in, NULL, NULL, cga_out, NULL, NULL, self); if (info->local) { - 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; - } + for (uint16_t 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; + 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; } vflags = info->local; @@ -443,7 +443,7 @@ compaq_cga_init(const device_t *info) overscan_x = overscan_y = 16; self->cga.rgb_type = device_get_config_int("rgb_type"); - cga_palette = (self->cga.rgb_type << 1); + cga_palette = (self->cga.rgb_type << 1); cgapal_rebuild(); self->cga.crtc[9] = 13; @@ -451,55 +451,52 @@ compaq_cga_init(const device_t *info) return self; } - void -compaq_cga_close(void *p) +compaq_cga_close(void *priv) { - compaq_cga_t *self = (compaq_cga_t *)p; + compaq_cga_t *self = (compaq_cga_t *) priv; free(self->cga.vram); free(self); } - void -compaq_cga_speed_changed(void *p) +compaq_cga_speed_changed(void *priv) { - compaq_cga_t *self = (compaq_cga_t *)p; + compaq_cga_t *self = (compaq_cga_t *) priv; - if (self->cga.crtc[9] == 13) /* Character height */ - compaq_cga_recalctimings(self); + if (self->cga.crtc[9] == 13) /* Character height */ + compaq_cga_recalctimings(self); else - cga_recalctimings(&self->cga); + cga_recalctimings(&self->cga); } - extern const device_config_t cga_config[]; -const device_t compaq_cga_device = -{ - "Compaq CGA", - "compaq_cga", - DEVICE_ISA, 0, - compaq_cga_init, - compaq_cga_close, - NULL, - { NULL }, - compaq_cga_speed_changed, - NULL, - cga_config +const device_t compaq_cga_device = { + .name = "Compaq CGA", + .internal_name = "compaq_cga", + .flags = DEVICE_ISA, + .local = 0, + .init = compaq_cga_init, + .close = compaq_cga_close, + .reset = NULL, + { .available = NULL }, + .speed_changed = compaq_cga_speed_changed, + .force_redraw = NULL, + .config = cga_config }; -const device_t compaq_cga_2_device = -{ - "Compaq CGA 2", - "compaq_cga_2", - DEVICE_ISA, 1, - compaq_cga_init, - compaq_cga_close, - NULL, - { NULL }, - compaq_cga_speed_changed, - NULL, - cga_config +const device_t compaq_cga_2_device = { + .name = "Compaq CGA 2", + .internal_name = "compaq_cga_2", + .flags = DEVICE_ISA, + .local = 1, + .init = compaq_cga_init, + .close = compaq_cga_close, + .reset = NULL, + { .available = NULL }, + .speed_changed = compaq_cga_speed_changed, + .force_redraw = NULL, + .config = cga_config }; diff --git a/src/video/vid_ddc.c b/src/video/vid_ddc.c index 6fc8276e4..387edaeb8 100644 --- a/src/video/vid_ddc.c +++ b/src/video/vid_ddc.c @@ -1,18 +1,18 @@ /* - * 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. + * 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. + * This file is part of the 86Box distribution. * - * DDC monitor emulation. + * DDC monitor emulation. * * * - * Authors: RichardG, + * Authors: RichardG, * - * Copyright 2020 RichardG. + * Copyright 2020 RichardG. */ #include #include @@ -24,30 +24,30 @@ #include <86box/86box.h> #include <86box/i2c.h> - -#define PIXEL_MM(px) ((uint16_t) (((px) * 25.4) / 96)) -#define STANDARD_TIMING(slot, width, aspect_ratio, refresh) do { \ - edid->slot.horiz_pixels = ((width) >> 3) - 31; \ - edid->slot.aspect_ratio_refresh_rate = ((aspect_ratio) << 6) | ((refresh) - 60); \ - } while (0) -#define DETAILED_TIMING(slot, clk, width, height, hblank, vblank, hfp, hsp, vfp, vsp) do { \ - edid->slot.pixel_clock_lsb = ((clk) / 10) & 0xff; \ - edid->slot.pixel_clock_msb = ((clk) / 10) >> 8; \ - edid->slot.h_active_lsb = (width) & 0xff; \ - edid->slot.h_blank_lsb = (hblank) & 0xff; \ - edid->slot.h_active_blank_msb = (((width) >> 4) & 0xf0) | (((hblank) >> 8) & 0x0f); \ - edid->slot.v_active_lsb = (height) & 0xff; \ - edid->slot.v_blank_lsb = (vblank) & 0xff; \ - edid->slot.v_active_blank_msb = (((height) >> 4) & 0xf0) | (((vblank) >> 8) & 0x0f); \ - edid->slot.h_front_porch_lsb = (hfp) & 0xff; \ - edid->slot.h_sync_pulse_lsb = (hsp) & 0xff; \ - edid->slot.v_front_porch_sync_pulse_lsb = (((vfp) & 0x0f) << 4) | ((vsp) & 0x0f); \ - edid->slot.hv_front_porch_sync_pulse_msb = (((hfp) >> 2) & 0xc0) | (((hsp) >> 4) & 0x30) | (((vfp) >> 2) & 0x0c) | (((vsp) >> 4) & 0x03); \ - edid->slot.h_size_lsb = horiz_mm & 0xff; \ - edid->slot.v_size_lsb = vert_mm & 0xff; \ - edid->slot.hv_size_msb = ((horiz_mm >> 4) & 0xf0) | ((vert_mm >> 8) & 0x0f); \ - } while (0) - +#define PIXEL_MM(px) (((px) * 25.4) / 96.0) +#define STANDARD_TIMING(slot, width, aspect_ratio, refresh) \ + do { \ + edid->slot.horiz_pixels = ((width) >> 3) - 31; \ + edid->slot.aspect_ratio_refresh_rate = ((aspect_ratio) << 6) | ((refresh) -60); \ + } while (0) +#define DETAILED_TIMING(slot, clk, width, height, hblank, vblank, hfp, hsp, vfp, vsp) \ + do { \ + edid->slot.pixel_clock_lsb = ((clk) / 10) & 0xff; \ + edid->slot.pixel_clock_msb = ((clk) / 10) >> 8; \ + edid->slot.h_active_lsb = (width) &0xff; \ + edid->slot.h_blank_lsb = (hblank) &0xff; \ + edid->slot.h_active_blank_msb = (((width) >> 4) & 0xf0) | (((hblank) >> 8) & 0x0f); \ + edid->slot.v_active_lsb = (height) &0xff; \ + edid->slot.v_blank_lsb = (vblank) &0xff; \ + edid->slot.v_active_blank_msb = (((height) >> 4) & 0xf0) | (((vblank) >> 8) & 0x0f); \ + edid->slot.h_front_porch_lsb = (hfp) &0xff; \ + edid->slot.h_sync_pulse_lsb = (hsp) &0xff; \ + edid->slot.v_front_porch_sync_pulse_lsb = (((vfp) &0x0f) << 4) | ((vsp) &0x0f); \ + edid->slot.hv_front_porch_sync_pulse_msb = (((hfp) >> 2) & 0xc0) | (((hsp) >> 4) & 0x30) | (((vfp) >> 2) & 0x0c) | (((vsp) >> 4) & 0x03); \ + edid->slot.h_size_lsb = (uint8_t) horiz_mm; \ + edid->slot.v_size_lsb = (uint8_t) vert_mm; \ + edid->slot.hv_size_msb = ((((uint16_t) horiz_mm) >> 4) & 0xf0) | ((((uint16_t) vert_mm) >> 8) & 0x0f); \ + } while (0) enum { STD_ASPECT_16_10 = 0x0, @@ -57,76 +57,75 @@ enum { }; typedef struct { - uint8_t horiz_pixels, aspect_ratio_refresh_rate; + uint8_t horiz_pixels, aspect_ratio_refresh_rate; } edid_standard_timing_t; typedef struct { - uint8_t pixel_clock_lsb, pixel_clock_msb, h_active_lsb, h_blank_lsb, - h_active_blank_msb, v_active_lsb, v_blank_lsb, v_active_blank_msb, - h_front_porch_lsb, h_sync_pulse_lsb, v_front_porch_sync_pulse_lsb, - hv_front_porch_sync_pulse_msb, h_size_lsb, v_size_lsb, hv_size_msb, - h_border, v_border, features; + uint8_t pixel_clock_lsb, pixel_clock_msb, h_active_lsb, h_blank_lsb, + h_active_blank_msb, v_active_lsb, v_blank_lsb, v_active_blank_msb, + h_front_porch_lsb, h_sync_pulse_lsb, v_front_porch_sync_pulse_lsb, + hv_front_porch_sync_pulse_msb, h_size_lsb, v_size_lsb, hv_size_msb, + h_border, v_border, features; } edid_detailed_timing_t; typedef struct { - uint8_t magic[2], reserved, tag, range_limit_offsets; + uint8_t magic[2], reserved, tag, range_limit_offsets; union { - char ascii[13]; - struct { - uint8_t min_v_field, max_v_field, min_h_line, max_h_line, max_pixel_clock, - timing_type; - union { - uint8_t padding[7]; - struct { - uint8_t reserved, gtf_start_freq, gtf_c, gtf_m_lsb, gtf_m_msb, - gtf_k, gtf_j; - }; - struct { - uint8_t cvt_version, add_clock_precision, max_active_pixels, - aspect_ratios, aspect_ratio_pref, scaling_support, - refresh_pref; - }; - }; - } range_limits; - struct { - edid_standard_timing_t timings[6]; - uint8_t padding; - } ext_standard_timings; - struct { - uint8_t version; - struct { - uint8_t lines_lsb, lines_msb_aspect_ratio, refresh_rate; - } timings[4]; - } cvt_timings; - struct { - uint8_t version, timings[6], reserved[6]; - } established_timings3; + char ascii[13]; + struct { + uint8_t min_v_field, max_v_field, min_h_line, max_h_line, max_pixel_clock, + timing_type; + union { + uint8_t padding[7]; + struct { + uint8_t reserved, gtf_start_freq, gtf_c, gtf_m_lsb, gtf_m_msb, + gtf_k, gtf_j; + }; + struct { + uint8_t cvt_version, add_clock_precision, max_active_pixels, + aspect_ratios, aspect_ratio_pref, scaling_support, + refresh_pref; + }; + }; + } range_limits; + struct { + edid_standard_timing_t timings[6]; + uint8_t padding; + } ext_standard_timings; + struct { + uint8_t version; + struct { + uint8_t lines_lsb, lines_msb_aspect_ratio, refresh_rate; + } timings[4]; + } cvt_timings; + struct { + uint8_t version, timings[6], reserved[6]; + } established_timings3; }; } edid_descriptor_t; typedef struct { - uint8_t magic[8], mfg[2], mfg_product[2], serial[4], mfg_week, mfg_year, - edid_version, edid_rev; - uint8_t input_params, horiz_size, vert_size, gamma, features; - uint8_t red_green_lsb, blue_white_lsb, red_x_msb, red_y_msb, green_x_msb, - green_y_msb, blue_x_msb, blue_y_msb, white_x_msb, white_y_msb; - uint8_t established_timings[3]; + uint8_t magic[8], mfg[2], mfg_product[2], serial[4], mfg_week, mfg_year, + edid_version, edid_rev; + uint8_t input_params, horiz_size, vert_size, gamma, features; + uint8_t red_green_lsb, blue_white_lsb, red_x_msb, red_y_msb, green_x_msb, + green_y_msb, blue_x_msb, blue_y_msb, white_x_msb, white_y_msb; + uint8_t established_timings[3]; edid_standard_timing_t standard_timings[8]; union { - edid_detailed_timing_t detailed_timings[4]; - edid_descriptor_t descriptors[4]; + edid_detailed_timing_t detailed_timings[4]; + edid_descriptor_t descriptors[4]; }; - uint8_t extensions, checksum; + uint8_t extensions, checksum; - uint8_t ext_tag, ext_rev, ext_dtd_offset, ext_native_dtds; + uint8_t ext_tag, ext_rev, ext_dtd_offset, ext_native_dtds; union { - edid_detailed_timing_t ext_detailed_timings[6]; - edid_descriptor_t ext_descriptors[6]; + edid_detailed_timing_t ext_detailed_timings[6]; + edid_descriptor_t ext_descriptors[6]; }; - uint8_t padding[15], checksum2; + uint8_t padding[15], checksum2; } edid_t; - void * ddc_init(void *i2c) { @@ -134,64 +133,65 @@ ddc_init(void *i2c) memset(edid, 0, sizeof(edid_t)); uint8_t *edid_bytes = (uint8_t *) edid; - uint16_t horiz_mm = PIXEL_MM(1366), vert_mm = PIXEL_MM(768); + double horiz_mm = PIXEL_MM(800); + double vert_mm = PIXEL_MM(600); memset(&edid->magic[1], 0xff, sizeof(edid->magic) - 2); - edid->mfg[0] = 0x09; /* manufacturer "BOX" (apparently unassigned by UEFI) */ - edid->mfg[1] = 0xf8; - edid->mfg_week = 48; - edid->mfg_year = 2020 - 1990; + edid->mfg[0] = 0x09; /* manufacturer "BOX" (apparently unassigned by UEFI) */ + edid->mfg[1] = 0xf8; + edid->mfg_week = 48; + edid->mfg_year = 2020 - 1990; edid->edid_version = 0x01; - edid->edid_rev = 0x03; /* EDID 1.3 */ + edid->edid_rev = 0x04; /* EDID 1.4, required for Xorg on Linux to use the preferred mode timing */ edid->input_params = 0x0e; /* analog input; separate sync; composite sync; sync on green */ - edid->horiz_size = horiz_mm / 10; - edid->vert_size = vert_mm / 10; - edid->features = 0xeb; /* DPMS standby/suspend/active-off; RGB color; first timing is preferred; GTF/CVT */ + edid->horiz_size = round(horiz_mm / 10.0); + edid->vert_size = round(vert_mm / 10.0); + edid->features = 0xeb; /* DPMS standby/suspend/active-off; RGB color; first timing is preferred; GTF/CVT */ - edid->red_green_lsb = 0x81; + edid->red_green_lsb = 0x81; edid->blue_white_lsb = 0xf1; - edid->red_x_msb = 0xa3; - edid->red_y_msb = 0x57; - edid->green_x_msb = 0x53; - edid->green_y_msb = 0x9f; - edid->blue_x_msb = 0x27; - edid->blue_y_msb = 0x0a; - edid->white_x_msb = 0x50; - edid->white_y_msb = 0x00; + edid->red_x_msb = 0xa3; + edid->red_y_msb = 0x57; + edid->green_x_msb = 0x53; + edid->green_y_msb = 0x9f; + edid->blue_x_msb = 0x27; + edid->blue_y_msb = 0x0a; + edid->white_x_msb = 0x50; + edid->white_y_msb = 0x00; memset(&edid->established_timings, 0xff, sizeof(edid->established_timings)); /* all enabled */ /* 60 Hz timings */ - STANDARD_TIMING(standard_timings[0], 1280, STD_ASPECT_16_9, 60); /* 1280x720 */ + STANDARD_TIMING(standard_timings[0], 1280, STD_ASPECT_16_9, 60); /* 1280x720 */ STANDARD_TIMING(standard_timings[1], 1280, STD_ASPECT_16_10, 60); /* 1280x800 */ - STANDARD_TIMING(standard_timings[2], 1366, STD_ASPECT_16_9, 60); /* 1360x768 (closest to 1366x768) */ + STANDARD_TIMING(standard_timings[2], 1366, STD_ASPECT_16_9, 60); /* 1360x768 (closest to 1366x768) */ STANDARD_TIMING(standard_timings[3], 1440, STD_ASPECT_16_10, 60); /* 1440x900 */ - STANDARD_TIMING(standard_timings[4], 1600, STD_ASPECT_16_9, 60); /* 1600x900 */ + STANDARD_TIMING(standard_timings[4], 1600, STD_ASPECT_16_9, 60); /* 1600x900 */ STANDARD_TIMING(standard_timings[5], 1680, STD_ASPECT_16_10, 60); /* 1680x1050 */ - STANDARD_TIMING(standard_timings[6], 1920, STD_ASPECT_16_9, 60); /* 1920x1080 */ - STANDARD_TIMING(standard_timings[7], 2048, STD_ASPECT_4_3, 60); /* 2048x1536 */ + STANDARD_TIMING(standard_timings[6], 1920, STD_ASPECT_16_9, 60); /* 1920x1080 */ + STANDARD_TIMING(standard_timings[7], 2048, STD_ASPECT_4_3, 60); /* 2048x1536 */ /* Detailed timing for the preferred mode of 800x600 @ 60 Hz */ DETAILED_TIMING(detailed_timings[0], 40000, 800, 600, 256, 28, 40, 128, 1, 4); - edid->descriptors[1].tag = 0xf7; /* established timings 3 */ + edid->descriptors[1].tag = 0xf7; /* established timings 3 */ edid->descriptors[1].established_timings3.version = 0x0a; memset(&edid->descriptors[1].established_timings3.timings, 0xff, sizeof(edid->descriptors[1].established_timings3.timings)); /* all enabled */ - edid->descriptors[1].established_timings3.timings[5] &= 0xf0; /* reserved bits */ + edid->descriptors[1].established_timings3.timings[5] &= 0xf0; /* reserved bits */ - edid->descriptors[2].tag = 0xfd; /* range limits */ - edid->descriptors[2].range_limits.min_v_field = 45; - edid->descriptors[2].range_limits.max_v_field = 125; - edid->descriptors[2].range_limits.min_h_line = 30; /* 640x480 = ~31.5 KHz */ - edid->descriptors[2].range_limits.max_h_line = 115; /* 1920x1440 = 112.5 KHz */ - edid->descriptors[2].range_limits.max_pixel_clock = 30; /* 1920x1440 = 297 MHz */ - edid->descriptors[2].range_limits.timing_type = 0x00; /* default GTF */ - edid->descriptors[2].range_limits.padding[0] = 0x0a; + edid->descriptors[2].tag = 0xfd; /* range limits */ + edid->descriptors[2].range_limits.min_v_field = 45; + edid->descriptors[2].range_limits.max_v_field = 125; + edid->descriptors[2].range_limits.min_h_line = 30; /* 640x480 = ~31.5 KHz */ + edid->descriptors[2].range_limits.max_h_line = 115; /* 1920x1440 = 112.5 KHz */ + edid->descriptors[2].range_limits.max_pixel_clock = 30; /* 1920x1440 = 297 MHz */ + edid->descriptors[2].range_limits.timing_type = 0x00; /* default GTF */ + edid->descriptors[2].range_limits.padding[0] = 0x0a; memset(&edid->descriptors[2].range_limits.padding[1], 0x20, sizeof(edid->descriptors[2].range_limits.padding) - 1); - edid->descriptors[3].tag = 0xfc; /* display name */ + edid->descriptors[3].tag = 0xfc; /* display name */ memcpy(&edid->descriptors[3].ascii, "86Box Monitor", 13); /* exactly 13 characters (would otherwise require LF termination and space padding) */ edid->extensions = 1; @@ -199,10 +199,10 @@ ddc_init(void *i2c) edid->checksum += edid_bytes[c]; edid->checksum = 256 - edid->checksum; - edid->ext_tag = 0x02; - edid->ext_rev = 0x03; + edid->ext_tag = 0x02; + edid->ext_rev = 0x03; edid->ext_native_dtds = 0x80; /* underscans IT; no native extended modes */ - edid->ext_dtd_offset = 0x04; + edid->ext_dtd_offset = 0x04; /* Detailed timing for 1366x768 */ DETAILED_TIMING(ext_detailed_timings[0], 85500, 1366, 768, 426, 30, 70, 143, 3, 3); @@ -210,12 +210,12 @@ ddc_init(void *i2c) /* High refresh rate timings (VGA is limited to 85 Hz) */ edid->ext_descriptors[1].tag = 0xfa; /* standard timing identifiers */ #define ext_standard_timings0 ext_descriptors[1].ext_standard_timings.timings - STANDARD_TIMING(ext_standard_timings0[0], 640, STD_ASPECT_4_3, 90); /* 640x480 @ 90 Hz */ - STANDARD_TIMING(ext_standard_timings0[1], 640, STD_ASPECT_4_3, 120); /* 640x480 @ 120 Hz */ - STANDARD_TIMING(ext_standard_timings0[2], 800, STD_ASPECT_4_3, 90); /* 800x600 @ 90 Hz */ - STANDARD_TIMING(ext_standard_timings0[3], 800, STD_ASPECT_4_3, 120); /* 800x600 @ 120 Hz */ - STANDARD_TIMING(ext_standard_timings0[4], 1024, STD_ASPECT_4_3, 90); /* 1024x768 @ 90 Hz */ - STANDARD_TIMING(ext_standard_timings0[5], 1280, STD_ASPECT_5_4, 90); /* 1280x1024 @ 90 Hz */ + STANDARD_TIMING(ext_standard_timings0[0], 640, STD_ASPECT_4_3, 90); /* 640x480 @ 90 Hz */ + STANDARD_TIMING(ext_standard_timings0[1], 640, STD_ASPECT_4_3, 120); /* 640x480 @ 120 Hz */ + STANDARD_TIMING(ext_standard_timings0[2], 800, STD_ASPECT_4_3, 90); /* 800x600 @ 90 Hz */ + STANDARD_TIMING(ext_standard_timings0[3], 800, STD_ASPECT_4_3, 120); /* 800x600 @ 120 Hz */ + STANDARD_TIMING(ext_standard_timings0[4], 1024, STD_ASPECT_4_3, 90); /* 1024x768 @ 90 Hz */ + STANDARD_TIMING(ext_standard_timings0[5], 1280, STD_ASPECT_5_4, 90); /* 1280x1024 @ 90 Hz */ edid->ext_descriptors[1].ext_standard_timings.padding = 0x0a; for (uint8_t c = 128; c < 255; c++) @@ -225,7 +225,6 @@ ddc_init(void *i2c) return i2c_eeprom_init(i2c, 0x50, edid_bytes, sizeof(edid_t), 0); } - void ddc_close(void *eeprom) { diff --git a/src/video/vid_ega.c b/src/video/vid_ega.c index 74892ae04..957a81304 100644 --- a/src/video/vid_ega.c +++ b/src/video/vid_ega.c @@ -1,22 +1,23 @@ /* - * 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. + * 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. + * This file is part of the 86Box distribution. * - * Emulation of the EGA and Chips & Technologies SuperEGA - * graphics cards. + * Emulation of the EGA and Chips & Technologies SuperEGA + * graphics cards. * * * - * Authors: Sarah Walker, - * Miran Grca, + * Authors: Sarah Walker, + * Miran Grca, * - * Copyright 2008-2019 Sarah Walker. - * Copyright 2016-2019 Miran Grca. + * Copyright 2008-2019 Sarah Walker. + * Copyright 2016-2019 Miran Grca. */ +#include #include #include #include @@ -26,6 +27,7 @@ #include "cpu.h" #include <86box/io.h> #include <86box/timer.h> +#include <86box/pic.h> #include <86box/pit.h> #include <86box/mem.h> #include <86box/rom.h> @@ -34,17 +36,14 @@ #include <86box/vid_ati_eeprom.h> #include <86box/vid_ega.h> - void ega_doblit(int wx, int wy, ega_t *ega); - -#define BIOS_IBM_PATH "roms/video/ega/ibm_6277356_ega_card_u44_27128.bin" -#define BIOS_CPQ_PATH "roms/video/ega/108281-001.bin" -#define BIOS_SEGA_PATH "roms/video/ega/lega.vbi" -#define BIOS_ATIEGA_PATH "roms/video/ega/ATI EGA Wonder 800+ N1.00.BIN" -#define BIOS_ISKRA_PATH "roms/video/ega/143-02.bin", "roms/video/ega/143-03.bin" -#define BIOS_TSENG_PATH "roms/video/ega/EGA ET2000.BIN" - +#define BIOS_IBM_PATH "roms/video/ega/ibm_6277356_ega_card_u44_27128.bin" +#define BIOS_CPQ_PATH "roms/video/ega/108281-001.bin" +#define BIOS_SEGA_PATH "roms/video/ega/lega.vbi" +#define BIOS_ATIEGA_PATH "roms/video/ega/ATI EGA Wonder 800+ N1.00.BIN" +#define BIOS_ISKRA_PATH "roms/video/ega/143-02.bin", "roms/video/ega/143-03.bin" +#define BIOS_TSENG_PATH "roms/video/ega/EGA ET2000.BIN" enum { EGA_IBM = 0, @@ -55,304 +54,401 @@ enum { EGA_TSENG }; +static video_timings_t timing_ega = { .type = VIDEO_ISA, .write_b = 8, .write_w = 16, .write_l = 32, .read_b = 8, .read_w = 16, .read_l = 32 }; +static uint8_t ega_rotate[8][256]; +static uint32_t pallook16[256]; +static uint32_t pallook64[256]; +static int ega_type = 0; +static int old_overscan_color = 0; -static video_timings_t timing_ega = {VIDEO_ISA, 8, 16, 32, 8, 16, 32}; -static uint8_t ega_rotate[8][256]; -static uint32_t pallook16[256], pallook64[256]; -static int ega_type = 0, old_overscan_color = 0; - -extern uint8_t edatlookup[4][4]; +uint8_t egaremap2bpp[256]; /* 3C2 controls default mode on EGA. On VGA, it determines monitor type (mono or colour): 7=CGA mode (200 lines), 9=EGA mode (350 lines), 8=EGA mode (200 lines). */ -int egaswitchread, egaswitches=9; -int update_overscan = 0; - - -uint8_t ega_in(uint16_t addr, void *p); +int egaswitchread; +int egaswitches = 9; +int update_overscan = 0; +uint8_t ega_in(uint16_t addr, void *priv); void -ega_out(uint16_t addr, uint8_t val, void *p) +ega_out(uint16_t addr, uint8_t val, void *priv) { - ega_t *ega = (ega_t *)p; - int c; - uint8_t o, old; + ega_t *ega = (ega_t *) priv; + uint8_t o; + uint8_t old; - if (((addr & 0xfff0) == 0x3d0 || (addr & 0xfff0) == 0x3b0) && !(ega->miscout & 1)) - addr ^= 0x60; + if (((addr & 0xfff0) == 0x3d0 || (addr & 0xfff0) == 0x3b0) && !(ega->miscout & 1)) + addr ^= 0x60; switch (addr) { - case 0x1ce: - ega->index = val; - break; - case 0x1cf: - ega->regs[ega->index] = val; - switch (ega->index) { - case 0xb0: - ega_recalctimings(ega); - break; - case 0xb2: case 0xbe: + case 0x1ce: + ega->index = val; + break; + case 0x1cf: + ega->regs[ega->index] = val; + switch (ega->index) { + case 0xb0: + ega_recalctimings(ega); + break; + case 0xb2: + case 0xbe: #if 0 - if (ega->regs[0xbe] & 8) { /*Read/write bank mode*/ - svga->read_bank = ((ega->regs[0xb2] >> 5) & 7) * 0x10000; - svga->write_bank = ((ega->regs[0xb2] >> 1) & 7) * 0x10000; - } else /*Single bank mode*/ - svga->read_bank = svga->write_bank = ((ega->regs[0xb2] >> 1) & 7) * 0x10000; + if (ega->regs[0xbe] & 8) { /*Read/write bank mode*/ + svga->read_bank = ((ega->regs[0xb2] >> 5) & 7) * 0x10000; + svga->write_bank = ((ega->regs[0xb2] >> 1) & 7) * 0x10000; + } else /*Single bank mode*/ + svga->read_bank = svga->write_bank = ((ega->regs[0xb2] >> 1) & 7) * 0x10000; #endif - break; - case 0xb3: - ati_eeprom_write((ati_eeprom_t *) ega->eeprom, val & 8, val & 2, val & 1); - break; - } - break; + break; + case 0xb3: + ati_eeprom_write((ati_eeprom_t *) ega->eeprom, val & 8, val & 2, val & 1); + break; - case 0x3c0: case 0x3c1: - if (!ega->attrff) { - ega->attraddr = val & 31; - if ((val & 0x20) != ega->attr_palette_enable) { - fullchange = 3; - ega->attr_palette_enable = val & 0x20; - ega_recalctimings(ega); - } - } else { - o = ega->attrregs[ega->attraddr & 31]; - ega->attrregs[ega->attraddr & 31] = val; - if (ega->attraddr < 16) - fullchange = changeframecount; - if (ega->attraddr == 0x10 || ega->attraddr == 0x14 || ega->attraddr < 0x10) { - for (c = 0; c < 16; c++) { - if (ega->attrregs[0x10] & 0x80) ega->egapal[c] = (ega->attrregs[c] & 0xf) | ((ega->attrregs[0x14] & 0xf) << 4); - else ega->egapal[c] = (ega->attrregs[c] & 0x3f) | ((ega->attrregs[0x14] & 0xc) << 4); - } - fullchange = changeframecount; - } - /* Recalculate timings on change of attribute register 0x11 - (overscan border color) too. */ - if (ega->attraddr == 0x10) { - if (o != val) - ega_recalctimings(ega); - } else if (ega->attraddr == 0x11) { - ega->overscan_color = ega->vres ? pallook16[val & 0x0f] : pallook64[val & 0x3f]; - if (o != val) - ega_recalctimings(ega); - } else if (ega->attraddr == 0x12) - ega->plane_mask = val & 0xf; - } - ega->attrff ^= 1; - break; - case 0x3c2: - o = ega->miscout; - egaswitchread = (val & 0xc) >> 2; - ega->vres = !(val & 0x80); - ega->pallook = ega->vres ? pallook16 : pallook64; - ega->vidclock = val & 4; - ega->miscout = val; - ega->overscan_color = ega->vres ? pallook16[ega->attrregs[0x11] & 0x0f] : pallook64[ega->attrregs[0x11] & 0x3f]; - io_removehandler(0x03a0, 0x0020, ega_in, NULL, NULL, ega_out, NULL, NULL, ega); - if (!(val & 1)) - io_sethandler(0x03a0, 0x0020, ega_in, NULL, NULL, ega_out, NULL, NULL, ega); - if ((o ^ val) & 0x80) - ega_recalctimings(ega); - break; - case 0x3c4: - ega->seqaddr = val; - break; - case 0x3c5: - o = ega->seqregs[ega->seqaddr & 0xf]; - ega->seqregs[ega->seqaddr & 0xf] = val; - if (o != val && (ega->seqaddr & 0xf) == 1) - ega_recalctimings(ega); - switch (ega->seqaddr & 0xf) { - case 1: - if (ega->scrblank && !(val & 0x20)) - fullchange = 3; - ega->scrblank = (ega->scrblank & ~0x20) | (val & 0x20); - break; - case 2: - ega->writemask = val & 0xf; - break; - case 3: - ega->charsetb = (((val >> 2) & 3) * 0x10000) + 2; - ega->charseta = ((val & 3) * 0x10000) + 2; - break; - case 4: - ega->chain2_write = !(val & 4); - break; - } - break; - case 0x3ce: - ega->gdcaddr = val; - break; - case 0x3cf: - ega->gdcreg[ega->gdcaddr & 15] = val; - switch (ega->gdcaddr & 15) { - case 2: - ega->colourcompare = val; - break; - case 4: - ega->readplane = val & 3; - break; - case 5: - ega->writemode = val & 3; - ega->readmode = val & 8; - ega->chain2_read = val & 0x10; - break; - case 6: - switch (val & 0xc) { - case 0x0: /*128k at A0000*/ - mem_mapping_set_addr(&ega->mapping, 0xa0000, 0x20000); - break; - case 0x4: /*64k at A0000*/ - mem_mapping_set_addr(&ega->mapping, 0xa0000, 0x10000); - break; - case 0x8: /*32k at B0000*/ - mem_mapping_set_addr(&ega->mapping, 0xb0000, 0x08000); - break; - case 0xC: /*32k at B8000*/ - mem_mapping_set_addr(&ega->mapping, 0xb8000, 0x08000); - break; - } - break; - case 7: - ega->colournocare = val; - break; - } - break; - case 0x3d0: case 0x3d4: - ega->crtcreg = val & 31; - return; - case 0x3d1: case 0x3d5: - if ((ega->crtcreg < 7) && (ega->crtc[0x11] & 0x80)) - return; - if ((ega->crtcreg == 7) && (ega->crtc[0x11] & 0x80)) - val = (ega->crtc[7] & ~0x10) | (val & 0x10); - old = ega->crtc[ega->crtcreg]; - ega->crtc[ega->crtcreg] = val; - if (old != val) { - if (ega->crtcreg < 0xe || ega->crtcreg > 0x10) { - if ((ega->crtcreg == 0xc) || (ega->crtcreg == 0xd)) { - fullchange = 3; - ega->ma_latch = ((ega->crtc[0xc] << 8) | ega->crtc[0xd]) + ((ega->crtc[8] & 0x60) >> 5); - } else { - fullchange = changeframecount; - ega_recalctimings(ega); - } - } - } - break; + default: + break; + } + break; + + case 0x3c0: + case 0x3c1: + if (!ega->attrff) { + ega->attraddr = val & 31; + if ((val & 0x20) != ega->attr_palette_enable) { + ega->fullchange = 3; + ega->attr_palette_enable = val & 0x20; + ega_recalctimings(ega); + } + } else { + o = ega->attrregs[ega->attraddr & 31]; + ega->attrregs[ega->attraddr & 31] = val; + if (ega->attraddr < 16) + ega->fullchange = changeframecount; + if (ega->attraddr == 0x10 || ega->attraddr == 0x14 || ega->attraddr < 0x10) { + for (uint8_t c = 0; c < 16; c++) { + if (ega->attrregs[0x10] & 0x80) + ega->egapal[c] = (ega->attrregs[c] & 0xf) | ((ega->attrregs[0x14] & 0xf) << 4); + else + ega->egapal[c] = (ega->attrregs[c] & 0x3f) | ((ega->attrregs[0x14] & 0xc) << 4); + } + ega->fullchange = changeframecount; + } + /* Recalculate timings on change of attribute register 0x11 + (overscan border color) too. */ + if (ega->attraddr == 0x10) { + if (o != val) + ega_recalctimings(ega); + } else if (ega->attraddr == 0x11) { + ega->overscan_color = ega->vres ? pallook16[val & 0x0f] : pallook64[val & 0x3f]; + if (o != val) + ega_recalctimings(ega); + } else if (ega->attraddr == 0x12) + ega->plane_mask = val & 0xf; + } + ega->attrff ^= 1; + break; + case 0x3c2: + o = ega->miscout; + egaswitchread = (val & 0xc) >> 2; + ega->vres = !(val & 0x80); + ega->pallook = ega->vres ? pallook16 : pallook64; + ega->vidclock = val & 4; + ega->miscout = val; + ega->overscan_color = ega->vres ? pallook16[ega->attrregs[0x11] & 0x0f] : pallook64[ega->attrregs[0x11] & 0x3f]; + io_removehandler(0x03a0, 0x0020, ega_in, NULL, NULL, ega_out, NULL, NULL, ega); + if (!(val & 1)) + io_sethandler(0x03a0, 0x0020, ega_in, NULL, NULL, ega_out, NULL, NULL, ega); + if ((o ^ val) & 0x80) + ega_recalctimings(ega); + break; + case 0x3c4: + ega->seqaddr = val; + break; + case 0x3c5: + o = ega->seqregs[ega->seqaddr & 0xf]; + ega->seqregs[ega->seqaddr & 0xf] = val; + if (o != val && (ega->seqaddr & 0xf) == 1) + ega_recalctimings(ega); + switch (ega->seqaddr & 0xf) { + case 1: + if (ega->scrblank && !(val & 0x20)) + ega->fullchange = 3; + ega->scrblank = (ega->scrblank & ~0x20) | (val & 0x20); + break; + case 2: + ega->writemask = val & 0xf; + break; + case 3: + ega->charsetb = (((val >> 2) & 3) * 0x10000) + 2; + ega->charseta = ((val & 3) * 0x10000) + 2; + break; + case 4: + ega->chain2_write = !(val & 4); + break; + + default: + break; + } + break; + case 0x3c6: + if (ega_type == 2) + ega->ctl_mode = val; + break; + case 0x3ce: + ega->gdcaddr = val; + break; + case 0x3cf: + ega->gdcreg[ega->gdcaddr & 15] = val; + switch (ega->gdcaddr & 15) { + case 2: + ega->colourcompare = val; + break; + case 4: + ega->readplane = val & 3; + break; + case 5: + ega->writemode = val & 3; + ega->readmode = val & 8; + ega->chain2_read = val & 0x10; + break; + case 6: + switch (val & 0xc) { + case 0x0: /*128k at A0000*/ + mem_mapping_set_addr(&ega->mapping, 0xa0000, 0x20000); + break; + case 0x4: /*64k at A0000*/ + mem_mapping_set_addr(&ega->mapping, 0xa0000, 0x10000); + break; + case 0x8: /*32k at B0000*/ + mem_mapping_set_addr(&ega->mapping, 0xb0000, 0x08000); + break; + case 0xC: /*32k at B8000*/ + mem_mapping_set_addr(&ega->mapping, 0xb8000, 0x08000); + break; + + default: + break; + } + break; + case 7: + ega->colournocare = val; + break; + + default: + break; + } + break; + case 0x3d0: + case 0x3d4: + ega->crtcreg = val & 31; + return; + case 0x3d1: + case 0x3d5: + if ((ega->crtcreg < 7) && (ega->crtc[0x11] & 0x80)) + return; + if ((ega->crtcreg == 7) && (ega->crtc[0x11] & 0x80)) + val = (ega->crtc[7] & ~0x10) | (val & 0x10); + old = ega->crtc[ega->crtcreg]; + ega->crtc[ega->crtcreg] = val; + if (old != val) { + if (ega->crtcreg < 0xe || ega->crtcreg > 0x10) { + if ((ega->crtcreg == 0xc) || (ega->crtcreg == 0xd)) { + ega->fullchange = 3; + ega->ma_latch = ((ega->crtc[0xc] << 8) | ega->crtc[0xd]) + ((ega->crtc[8] & 0x60) >> 5); + } else { + ega->fullchange = changeframecount; + ega_recalctimings(ega); + } + } + } + break; + + default: + break; } } - uint8_t -ega_in(uint16_t addr, void *p) +ega_in(uint16_t addr, void *priv) { - ega_t *ega = (ega_t *)p; + ega_t *ega = (ega_t *) priv; uint8_t ret = 0xff; - if (((addr & 0xfff0) == 0x3d0 || (addr & 0xfff0) == 0x3b0) && !(ega->miscout & 1)) - addr ^= 0x60; + if (((addr & 0xfff0) == 0x3d0 || (addr & 0xfff0) == 0x3b0) && !(ega->miscout & 1)) + addr ^= 0x60; switch (addr) { - case 0x1ce: - ret = ega->index; - break; - case 0x1cf: - switch (ega->index) { - case 0xb7: - ret = ega->regs[ega->index] & ~8; - if (ati_eeprom_read((ati_eeprom_t *) ega->eeprom)) - ret |= 8; - break; - default: - ret = ega->regs[ega->index]; - break; - } - break; + case 0x1ce: + ret = ega->index; + break; + case 0x1cf: + switch (ega->index) { + case 0xb7: + ret = ega->regs[ega->index] & ~8; + if (ati_eeprom_read((ati_eeprom_t *) ega->eeprom)) + ret |= 8; + break; - case 0x3c0: - if (ega_type) - ret = ega->attraddr | ega->attr_palette_enable; - break; - case 0x3c1: - if (ega_type) - ret = ega->attrregs[ega->attraddr]; - break; - case 0x3c2: - ret = (egaswitches & (8 >> egaswitchread)) ? 0x10 : 0x00; - break; - case 0x3c4: - if (ega_type) - ret = ega->seqaddr; - break; - case 0x3c5: - if (ega_type) - ret = ega->seqregs[ega->seqaddr & 0xf]; - break; - case 0x3c8: - if (ega_type) - ret = 2; - break; - case 0x3cc: - if (ega_type) - ret = ega->miscout; - break; - case 0x3ce: - if (ega_type) - ret = ega->gdcaddr; - break; - case 0x3cf: - if (ega_type) - ret = ega->gdcreg[ega->gdcaddr & 0xf]; - break; - case 0x3d0: case 0x3d4: - if (ega_type) - ret = ega->crtcreg; - break; - case 0x3d1: - case 0x3d5: - if (ega_type) - ret = ega->crtc[ega->crtcreg]; - break; - case 0x3da: - ega->attrff = 0; - ega->stat ^= 0x30; /*Fools IBM EGA video BIOS self-test*/ - ret = ega->stat; - break; + default: + ret = ega->regs[ega->index]; + break; + } + break; + + case 0x3c0: + if (ega_type) + ret = ega->attraddr | ega->attr_palette_enable; + break; + case 0x3c1: + if (ega_type) + ret = ega->attrregs[ega->attraddr]; + break; + case 0x3c2: + ret = (egaswitches & (8 >> egaswitchread)) ? 0x10 : 0x00; + break; + case 0x3c4: + if (ega_type) + ret = ega->seqaddr; + break; + case 0x3c5: + if (ega_type) + ret = ega->seqregs[ega->seqaddr & 0xf]; + break; + case 0x3c6: + if (ega_type == 2) + ret = ega->ctl_mode; + break; + case 0x3c8: + if (ega_type) + ret = 2; + break; + case 0x3cc: + if (ega_type) + ret = ega->miscout; + break; + case 0x3ce: + if (ega_type) + ret = ega->gdcaddr; + break; + case 0x3cf: + if (ega_type) + ret = ega->gdcreg[ega->gdcaddr & 0xf]; + break; + case 0x3d0: + case 0x3d4: + if (ega_type) + ret = ega->crtcreg; + break; + case 0x3d1: + case 0x3d5: + switch (ega->crtcreg) { + case 0xc: + case 0xd: + case 0xe: + case 0xf: + ret = ega->crtc[ega->crtcreg]; + break; + + case 0x10: + case 0x11: + /* TODO: Return light pen address once implemented. */ + if (ega_type) + ret = ega->crtc[ega->crtcreg]; + break; + + default: + if (ega_type) + ret = ega->crtc[ega->crtcreg]; + } + break; + case 0x3da: + ega->attrff = 0; + if (ega_type == 2) { + ret = ega->stat & 0xcf; + switch ((ega->attrregs[0x12] >> 4) & 0x03) { + case 0x00: + /* 00 = Pri. Red (5), Pri. Blue (4) */ + ret |= (ega->color_mux & 0x04) ? 0x20 : 0x00; + ret |= (ega->color_mux & 0x01) ? 0x10 : 0x00; + break; + case 0x01: + case 0x03: + /* 01 = Sec. Red (5), Sec. Green (4) */ + /* 11 = Sec. Red (5), Sec. Green (4) */ + ret |= (ega->color_mux & 0x20) ? 0x20 : 0x00; + ret |= (ega->color_mux & 0x10) ? 0x10 : 0x00; + break; + case 0x02: + /* 10 = Sec. Blue (5), Pri. Green (4) */ + ret |= (ega->color_mux & 0x08) ? 0x20 : 0x00; + ret |= (ega->color_mux & 0x02) ? 0x10 : 0x00; + break; + } + } else { + ega->stat ^= 0x30; /* Fools IBM EGA video BIOS self-test. */ + ret = ega->stat; + } + break; + case 0x7c6: + ret = 0xfd; /* EGA mode supported. */ + break; + case 0xbc6: + /* 0000 = None; + 0001 = Compaq Dual-Mode (DM) Monitor; + 0010 = RGBI Color Monitor; + 0011 = COMPAQ Color Monitor (RrGgBb) or Compatible; + 0100 - 1111 = Reserved. */ + ret = 0x01; + break; + case 0xfc6: + ret = 0xfd; + break; + + default: + break; } return ret; } - void ega_recalctimings(ega_t *ega) { int clksel; + int color; - double _dispontime, _dispofftime, disptime; + double _dispontime; + double _dispofftime; + double disptime; double crtcconst; - ega->vtotal = ega->crtc[6]; - ega->dispend = ega->crtc[0x12]; + ega->vtotal = ega->crtc[6]; + ega->dispend = ega->crtc[0x12]; ega->vsyncstart = ega->crtc[0x10]; - ega->split = ega->crtc[0x18]; + ega->split = ega->crtc[0x18]; - if (ega->crtc[7] & 1) ega->vtotal |= 0x100; - if (ega->crtc[7] & 32) ega->vtotal |= 0x200; + if (ega->crtc[7] & 1) + ega->vtotal |= 0x100; + if (ega->crtc[7] & 32) + ega->vtotal |= 0x200; ega->vtotal += 2; - if (ega->crtc[7] & 2) ega->dispend |= 0x100; - if (ega->crtc[7] & 64) ega->dispend |= 0x200; + if (ega->crtc[7] & 2) + ega->dispend |= 0x100; + if (ega->crtc[7] & 64) + ega->dispend |= 0x200; ega->dispend++; - if (ega->crtc[7] & 4) ega->vsyncstart |= 0x100; - if (ega->crtc[7] & 128) ega->vsyncstart |= 0x200; + if (ega->crtc[7] & 4) + ega->vsyncstart |= 0x100; + if (ega->crtc[7] & 128) + ega->vsyncstart |= 0x200; ega->vsyncstart++; - if (ega->crtc[7] & 0x10) ega->split |= 0x100; - if (ega->crtc[9] & 0x40) ega->split |= 0x200; + if (ega->crtc[7] & 0x10) + ega->split |= 0x100; + if (ega->crtc[9] & 0x40) + ega->split |= 0x200; ega->split++; ega->hdisp = ega->crtc[1]; @@ -360,38 +456,63 @@ ega_recalctimings(ega_t *ega) ega->rowoffset = ega->crtc[0x13]; - ega->linedbl = ega->crtc[9] & 0x80; + ega->linedbl = ega->crtc[9] & 0x80; ega->rowcount = ega->crtc[9] & 0x1f; - if (ega->eeprom) { - clksel = ((ega->miscout & 0xc) >> 2) | ((ega->regs[0xbe] & 0x10) ? 4 : 0); + if (ega_type == 2) { + color = (ega->miscout & 1); + clksel = ((ega->miscout & 0xc) >> 2); - switch (clksel) { - case 0: - crtcconst = (cpuclock / 25175000.0 * (double)(1ull << 32)); - break; - case 1: - crtcconst = (cpuclock / 28322000.0 * (double)(1ull << 32)); - break; - case 4: - crtcconst = (cpuclock / 14318181.0 * (double)(1ull << 32)); - break; - case 5: - crtcconst = (cpuclock / 16257000.0 * (double)(1ull << 32)); - break; - case 7: - default: - crtcconst = (cpuclock / 36000000.0 * (double)(1ull << 32)); - break; - } - if (!(ega->seqregs[1] & 1)) - crtcconst *= 9.0; - else - crtcconst *= 8.0; + if (color) { + if (ega->vidclock) + crtcconst = (cpuclock / 16257000.0 * (double) (1ULL << 32)); + else + crtcconst = (cpuclock / (157500000.0 / 11.0) * (double) (1ULL << 32)); + } else { + if (ega->vidclock) + crtcconst = (cpuclock / 18981000.0 * (double) (1ULL << 32)); + else + crtcconst = (cpuclock / 16872000.0 * (double) (1ULL << 32)); + } + if (!(ega->seqregs[1] & 1)) + crtcconst *= 9.0; + else + crtcconst *= 8.0; + } else if (ega->eeprom) { + clksel = ((ega->miscout & 0xc) >> 2) | ((ega->regs[0xbe] & 0x10) ? 4 : 0); + + switch (clksel) { + case 0: + crtcconst = (cpuclock / 25175000.0 * (double) (1ULL << 32)); + break; + case 1: + crtcconst = (cpuclock / 28322000.0 * (double) (1ULL << 32)); + break; + case 4: + crtcconst = (cpuclock / 14318181.0 * (double) (1ULL << 32)); + break; + case 5: + crtcconst = (cpuclock / 16257000.0 * (double) (1ULL << 32)); + break; + case 7: + default: + crtcconst = (cpuclock / 36000000.0 * (double) (1ULL << 32)); + break; + } + if (!(ega->seqregs[1] & 1)) + crtcconst *= 9.0; + else + crtcconst *= 8.0; } else { - if (ega->vidclock) crtcconst = (ega->seqregs[1] & 1) ? MDACONST : (MDACONST * (9.0 / 8.0)); - else crtcconst = (ega->seqregs[1] & 1) ? CGACONST : (CGACONST * (9.0 / 8.0)); + if (ega->vidclock) + crtcconst = (ega->seqregs[1] & 1) ? MDACONST : (MDACONST * (9.0 / 8.0)); + else + crtcconst = (ega->seqregs[1] & 1) ? CGACONST : (CGACONST * (9.0 / 8.0)); } + if (!(ega->seqregs[1] & 1)) + ega->dot_clock = crtcconst / 9.0; + else + ega->dot_clock = crtcconst / 8.0; ega->interlace = 0; @@ -399,608 +520,864 @@ ega_recalctimings(ega_t *ega) ega->render = ega_render_blank; if (!ega->scrblank && ega->attr_palette_enable) { - if (!(ega->gdcreg[6] & 1)) { - if (ega->seqregs[1] & 8) { - ega->render = ega_render_text_40; - ega->hdisp *= (ega->seqregs[1] & 1) ? 16 : 18; - } else { - ega->render = ega_render_text_80; - ega->hdisp *= (ega->seqregs[1] & 1) ? 8 : 9; - } - ega->hdisp_old = ega->hdisp; - } else { - ega->hdisp *= (ega->seqregs[1] & 8) ? 16 : 8; - ega->hdisp_old = ega->hdisp; - - switch (ega->gdcreg[5] & 0x20) { - case 0x00: - if (ega->seqregs[1] & 8) - ega->render = ega_render_4bpp_lowres; - else - ega->render = ega_render_4bpp_highres; - break; - case 0x20: - if (ega->seqregs[1] & 8) - ega->render = ega_render_2bpp_lowres; - else - ega->render = ega_render_2bpp_highres; - break; - } - } + if (!(ega->gdcreg[6] & 1)) { + if (ega->seqregs[1] & 8) + ega->hdisp *= (ega->seqregs[1] & 1) ? 16 : 18; + else + ega->hdisp *= (ega->seqregs[1] & 1) ? 8 : 9; + ega->render = ega_render_text; + ega->hdisp_old = ega->hdisp; + } else { + ega->hdisp *= (ega->seqregs[1] & 8) ? 16 : 8; + ega->render = ega_render_graphics; + ega->hdisp_old = ega->hdisp; + } } if (enable_overscan) { - overscan_y = (ega->rowcount + 1) << 1; + overscan_y = (ega->rowcount + 1) << 1; - if (overscan_y < 16) - overscan_y = 16; + if (overscan_y < 16) + overscan_y = 16; } overscan_x = (ega->seqregs[1] & 1) ? 16 : 18; - if (ega->seqregs[1] & 8) - overscan_x <<= 1; + if (ega->seqregs[1] & 8) + overscan_x <<= 1; ega->y_add = (overscan_y >> 1) - (ega->crtc[8] & 0x1f); ega->x_add = (overscan_x >> 1); if (ega->seqregs[1] & 8) { - disptime = (double) ((ega->crtc[0] + 2) << 1); - _dispontime = (double) ((ega->crtc[1] + 1) << 1); + disptime = (double) ((ega->crtc[0] + 2) << 1); + _dispontime = (double) ((ega->crtc[1] + 1) << 1); } else { - disptime = (double) (ega->crtc[0] + 2); - _dispontime = (double) (ega->crtc[1] + 1); + disptime = (double) (ega->crtc[0] + 2); + _dispontime = (double) (ega->crtc[1] + 1); } _dispofftime = disptime - _dispontime; _dispontime *= crtcconst; _dispofftime *= crtcconst; - ega->dispontime = (uint64_t)(_dispontime); - ega->dispofftime = (uint64_t)(_dispofftime); + ega->dispontime = (uint64_t) (_dispontime); + ega->dispofftime = (uint64_t) (_dispofftime); if (ega->dispontime < TIMER_USEC) - ega->dispontime = TIMER_USEC; + ega->dispontime = TIMER_USEC; if (ega->dispofftime < TIMER_USEC) - ega->dispofftime = TIMER_USEC; + ega->dispofftime = TIMER_USEC; + + ega->dot_time = (uint64_t) (ega->dot_clock); + if (ega->dot_time < TIMER_USEC) + ega->dot_time = TIMER_USEC; + + ega_recalc_remap_func(ega); } - +/* This is needed for the Compaq EGA so that it can pass the 3DA + palette mux part of the self-test. */ void -ega_poll(void *p) +ega_dot_poll(void *priv) { - ega_t *ega = (ega_t *)p; - int x, old_ma; - int wx = 640, wy = 350; - uint32_t blink_delay; + ega_t *ega = (ega_t *) priv; + static uint8_t chr; + static uint8_t attr; + const bool doublewidth = ((ega->seqregs[1] & 8) != 0); + const bool attrblink = ((ega->attrregs[0x10] & 8) != 0); + const bool attrlinechars = (ega->attrregs[0x10] & 4); + const bool crtcreset = ((ega->crtc[0x17] & 0x80) == 0); + const bool seq9dot = ((ega->seqregs[1] & 1) == 0); + const bool blinked = ega->blink & 0x10; + const int dwshift = doublewidth ? 1 : 0; + const int dotwidth = 1 << dwshift; + const int charwidth = dotwidth * (seq9dot ? 9 : 8); + const int cursoron = (ega->sc == (ega->crtc[10] & 31)); + const int cursoraddr = (ega->crtc[0xe] << 8) | ega->crtc[0xf]; + uint32_t addr; + int drawcursor; + uint32_t charaddr; + static int fg; + static int bg; + static uint32_t dat; + static int disptime; + static int _dispontime; + static int _dispofftime; + static int cclock = 0; + static int active = 0; - if (!ega->linepos) { - timer_advance_u64(&ega->timer, ega->dispofftime); - ega->stat |= 1; - ega->linepos = 1; - - if (ega->dispon) { - ega->hdisp_on = 1; - - ega->ma &= ega->vrammask; - if (ega->firstline == 2000) { - ega->firstline = ega->displine; - video_wait_for_buffer(); - } - - if (ega->vres) { - old_ma = ega->ma; - - ega->displine <<= 1; - ega->y_add <<= 1; - - ega->render(ega); - - ega->x_add = (overscan_x >> 1); - ega_render_overscan_left(ega); - ega_render_overscan_right(ega); - ega->x_add = (overscan_x >> 1) - ega->scrollcache; - - ega->displine++; - - ega->ma = old_ma; - - ega->render(ega); - - ega->x_add = (overscan_x >> 1); - ega_render_overscan_left(ega); - ega_render_overscan_right(ega); - ega->x_add = (overscan_x >> 1) - ega->scrollcache; - - ega->y_add >>= 1; - ega->displine >>= 1; - } else { - ega_render_overscan_left(ega); - ega->render(ega); - ega_render_overscan_right(ega); - } - - if (ega->lastline < ega->displine) - ega->lastline = ega->displine; - } - - ega->displine++; - if (ega->interlace) - ega->displine++; - if ((ega->stat & 8) && ((ega->displine & 15) == (ega->crtc[0x11] & 15)) && ega->vslines) - ega->stat &= ~8; - ega->vslines++; - if (ega->displine > 500) - ega->displine = 0; + if (ega->seqregs[1] & 8) { + disptime = ((ega->crtc[0] + 2) << 1); + _dispontime = ((ega->crtc[1] + 1) << 1); } else { - timer_advance_u64(&ega->timer, ega->dispontime); + disptime = (ega->crtc[0] + 2); + _dispontime = (ega->crtc[1] + 1); + } + _dispofftime = disptime - _dispontime; - if (ega->dispon) - ega->stat &= ~1; - ega->hdisp_on = 0; + timer_advance_u64(&ega->dot_timer, ega->dot_time); - ega->linepos = 0; - if ((ega->sc == (ega->crtc[11] & 31)) || (ega->sc == ega->rowcount)) - ega->con = 0; - if (ega->dispon) { - if (ega->linedbl && !ega->linecountff) { - ega->linecountff = 1; - ega->ma = ega->maback; - } if (ega->sc == (ega->crtc[9] & 31)) { - ega->linecountff = 0; - ega->sc = 0; + if (ega->render == ega_render_text) + ega->color_mux = (dat & (0x100 >> (ega->dot >> dwshift))) ? fg : bg; + else + ega->color_mux = 0x00; - ega->maback += (ega->rowoffset << 3); - if (ega->interlace) - ega->maback += (ega->rowoffset << 3); - ega->maback &= ega->vrammask; - ega->ma = ega->maback; - } else { - ega->linecountff = 0; - ega->sc++; - ega->sc &= 31; - ega->ma = ega->maback; - } - } - ega->vc++; - ega->vc &= 1023; - if (ega->vc == ega->split) { - if (ega->interlace && ega->oddeven) - ega->ma = ega->maback = ega->ma_latch + (ega->rowoffset << 1); - else - ega->ma = ega->maback = ega->ma_latch; - ega->ma <<= 2; - ega->maback <<= 2; - ega->sc = 0; - if (ega->attrregs[0x10] & 0x20) { - ega->scrollcache = 0; - ega->x_add = (overscan_x >> 1); - } - } - if (ega->vc == ega->dispend) { - ega->dispon = 0; - blink_delay = (ega->crtc[11] & 0x60) >> 5; - if (ega->crtc[10] & 0x20) - ega->cursoron = 0; - else if (blink_delay == 2) - ega->cursoron = ((ega->blink % 96) >= 48); - else - ega->cursoron = ega->blink & (16 + (16 * blink_delay)); + addr = ega->remap_func(ega, ega->cca) & ega->vrammask; - if (!(ega->gdcreg[6] & 1) && !(ega->blink & 15)) - fullchange = 2; - ega->blink = (ega->blink + 1) & 0x7f; + if (!crtcreset) { + chr = ega->vram[addr]; + attr = ega->vram[addr + 1]; + } else + chr = attr = 0; - if (fullchange) - fullchange--; - } - if (ega->vc == ega->vsyncstart) { - ega->dispon = 0; - ega->stat |= 8; - x = ega->hdisp; + drawcursor = ((ega->cca == cursoraddr) && cursoron && ega->cursoron); - if (ega->interlace && !ega->oddeven) - ega->lastline++; - if (ega->interlace && ega->oddeven) - ega->firstline--; + if (attr & 8) + charaddr = ega->charsetb + (chr * 0x80); + else + charaddr = ega->charseta + (chr * 0x80); - wx = x; + dat = ega->vram[charaddr + (ega->sc << 2)]; + dat <<= 1; + if ((chr & ~0x1F) == 0xC0 && attrlinechars) + dat |= (dat >> 1) & 1; - if (ega->vres) { - wy = (ega->lastline - ega->firstline) << 1; - ega_doblit(wx, wy, ega); - } else { - wy = ega->lastline - ega->firstline; - ega_doblit(wx, wy, ega); - } + if (!active) + dat = 0x200; - frames++; + if (drawcursor) { + bg = ega->egapal[attr & 0x0f]; + fg = ega->egapal[attr >> 4]; + } else { + fg = ega->egapal[attr & 0x0f]; + bg = ega->egapal[attr >> 4]; + if ((attr & 0x80) && attrblink) { + bg = ega->egapal[(attr >> 4) & 7]; + if (blinked) + fg = bg; + } + } - ega->firstline = 2000; - ega->lastline = 0; + ega->dot = (ega->dot + 1) % charwidth; - ega->firstline_draw = 2000; - ega->lastline_draw = 0; + if (ega->dot == 0) { + ega->cca = (ega->cca + 4) & 0x3ffff; - ega->oddeven ^= 1; + cclock++; - changeframecount = ega->interlace ? 3 : 2; - ega->vslines = 0; - - if (ega->interlace && ega->oddeven) - ega->ma = ega->maback = ega->ma_latch + (ega->rowoffset << 1); - else - ega->ma = ega->maback = ega->ma_latch; - ega->ca = (ega->crtc[0xe] << 8) | ega->crtc[0xf]; - - ega->ma <<= 2; - ega->maback <<= 2; - ega->ca <<= 2; - } - if (ega->vc == ega->vtotal) { - ega->vc = 0; - ega->sc = 0; - ega->dispon = 1; - ega->displine = (ega->interlace && ega->oddeven) ? 1 : 0; - - ega->scrollcache = (ega->attrregs[0x13] & 0x0f); - if (!(ega->gdcreg[6] & 1) && !(ega->attrregs[0x10] & 1)) { /*Text mode*/ - if (ega->seqregs[1] & 1) - ega->scrollcache &= 0x07; - else { - ega->scrollcache++; - if (ega->scrollcache > 8) - ega->scrollcache = 0; - } - } else - ega->scrollcache &= 0x07; - - if (ega->seqregs[1] & 8) - ega->scrollcache <<= 1; - - ega->x_add = (overscan_x >> 1) - ega->scrollcache; - - ega->linecountff = 0; - } - if (ega->sc == (ega->crtc[10] & 31)) - ega->con = 1; + if (active && (cclock == _dispofftime)) + active = 0; + else if (!active && (cclock == _dispontime)) + active = 1; } } +void +ega_poll(void *priv) +{ + ega_t *ega = (ega_t *) priv; + int x; + int old_ma; + int wx = 640; + int wy = 350; + uint32_t blink_delay; + + if (!ega->linepos) { + timer_advance_u64(&ega->timer, ega->dispofftime); + ega->stat |= 1; + ega->linepos = 1; + + if (ega->dispon) { + ega->hdisp_on = 1; + + ega->ma &= ega->vrammask; + if (ega->firstline == 2000) { + ega->firstline = ega->displine; + video_wait_for_buffer(); + } + + if (ega->vres) { + old_ma = ega->ma; + + ega->displine <<= 1; + ega->y_add <<= 1; + + ega->render(ega); + + ega->x_add = (overscan_x >> 1); + ega_render_overscan_left(ega); + ega_render_overscan_right(ega); + ega->x_add = (overscan_x >> 1) - ega->scrollcache; + + ega->displine++; + + ega->ma = old_ma; + + ega->render(ega); + + ega->x_add = (overscan_x >> 1); + ega_render_overscan_left(ega); + ega_render_overscan_right(ega); + ega->x_add = (overscan_x >> 1) - ega->scrollcache; + + ega->y_add >>= 1; + ega->displine >>= 1; + } else { + ega_render_overscan_left(ega); + ega->render(ega); + ega_render_overscan_right(ega); + } + + if (ega->lastline < ega->displine) + ega->lastline = ega->displine; + } + + ega->displine++; + if (ega->interlace) + ega->displine++; + if ((ega->stat & 8) && ((ega->displine & 15) == (ega->crtc[0x11] & 15)) && ega->vslines) + ega->stat &= ~8; + ega->vslines++; + if (ega->displine > 500) + ega->displine = 0; + } else { + timer_advance_u64(&ega->timer, ega->dispontime); + + if (ega->dispon) + ega->stat &= ~1; + ega->hdisp_on = 0; + + ega->linepos = 0; + if ((ega->sc == (ega->crtc[11] & 31)) || (ega->sc == ega->rowcount)) + ega->con = 0; + if (ega->dispon) { + if (ega->linedbl && !ega->linecountff) { + ega->linecountff = 1; + ega->ma = ega->maback; + ega->cca = ega->maback; + } + if (ega->sc == (ega->crtc[9] & 31)) { + ega->linecountff = 0; + ega->sc = 0; + + ega->maback += (ega->rowoffset << 3); + if (ega->interlace) + ega->maback += (ega->rowoffset << 3); + ega->maback &= ega->vrammask; + ega->ma = ega->maback; + ega->cca = ega->maback; + } else { + ega->linecountff = 0; + ega->sc++; + ega->sc &= 31; + ega->ma = ega->maback; + ega->cca = ega->maback; + } + } + ega->vc++; + ega->vc &= 511; + if (ega->vc == ega->split) { + // TODO: Implement the hardware bug where the first scanline is drawn twice when the split happens + if (ega->interlace && ega->oddeven) + ega->ma = ega->maback = ega->rowoffset << 1; + else + ega->ma = ega->maback = 0; + ega->ma <<= 2; + ega->cca = ega->ma; + ega->maback <<= 2; + ega->sc = 0; + if (ega->attrregs[0x10] & 0x20) { + ega->scrollcache = 0; + ega->x_add = (overscan_x >> 1); + } + } + if (ega->vc == ega->dispend) { + ega->dispon = 0; + blink_delay = (ega->crtc[11] & 0x60) >> 5; + if (ega->crtc[10] & 0x20) + ega->cursoron = 0; + else if (blink_delay == 2) + ega->cursoron = ((ega->blink % 96) >= 48); + else + ega->cursoron = ega->blink & (16 + (16 * blink_delay)); + + if (!(ega->gdcreg[6] & 1) && !(ega->blink & 15)) + ega->fullchange = 2; + ega->blink = (ega->blink + 1) & 0x7f; + + if (ega->fullchange) + ega->fullchange--; + } + if (ega->vc == ega->vsyncstart) { + ega->dispon = 0; + ega->stat |= 8; +#if 0 + picint(1 << 2); +#endif + x = ega->hdisp; + + if (ega->interlace && !ega->oddeven) + ega->lastline++; + if (ega->interlace && ega->oddeven) + ega->firstline--; + + wx = x; + + if (ega->vres) { + wy = (ega->lastline - ega->firstline) << 1; + ega_doblit(wx, wy, ega); + } else { + wy = ega->lastline - ega->firstline; + ega_doblit(wx, wy, ega); + } + + frames++; + + ega->firstline = 2000; + ega->lastline = 0; + + ega->firstline_draw = 2000; + ega->lastline_draw = 0; + + ega->oddeven ^= 1; + + changeframecount = ega->interlace ? 3 : 2; + ega->vslines = 0; + + if (ega->interlace && ega->oddeven) + ega->ma = ega->maback = ega->ma_latch + (ega->rowoffset << 1); + else + ega->ma = ega->maback = ega->ma_latch; + ega->ca = (ega->crtc[0xe] << 8) | ega->crtc[0xf]; + + ega->ma <<= 2; + ega->maback <<= 2; + ega->ca <<= 2; + ega->cca = ega->ma; + } + if (ega->vc == ega->vtotal) { + ega->vc = 0; + ega->sc = 0; + ega->dispon = 1; + ega->displine = (ega->interlace && ega->oddeven) ? 1 : 0; + + ega->scrollcache = (ega->attrregs[0x13] & 0x0f); + if (!(ega->gdcreg[6] & 1) && !(ega->attrregs[0x10] & 1)) { /*Text mode*/ + if (ega->seqregs[1] & 1) + ega->scrollcache &= 0x07; + else { + ega->scrollcache++; + if (ega->scrollcache > 8) + ega->scrollcache = 0; + } + } else + ega->scrollcache &= 0x07; + + if (ega->seqregs[1] & 8) + ega->scrollcache <<= 1; + + ega->x_add = (overscan_x >> 1) - ega->scrollcache; + + ega->linecountff = 0; + } + if (ega->sc == (ega->crtc[10] & 31)) + ega->con = 1; + } +} void ega_doblit(int wx, int wy, ega_t *ega) { - int y_add = (enable_overscan) ? overscan_y : 0; - int x_add = (enable_overscan) ? overscan_x : 0; - int y_start = (enable_overscan) ? 0 : (overscan_y >> 1); - int x_start = (enable_overscan) ? 0 : (overscan_x >> 1); - int bottom = (overscan_y >> 1) + (ega->crtc[8] & 0x1f); + int y_add = enable_overscan ? overscan_y : 0; + int x_add = enable_overscan ? overscan_x : 0; + int y_start = enable_overscan ? 0 : (overscan_y >> 1); + int x_start = enable_overscan ? 0 : (overscan_x >> 1); + int bottom = (overscan_y >> 1) + (ega->crtc[8] & 0x1f); uint32_t *p; - int i, j; - int xs_temp, ys_temp; + int i; + int j; + int xs_temp; + int ys_temp; if (ega->vres) { - y_add <<= 1; - y_start <<= 1; - bottom <<= 1; + y_add <<= 1; + y_start <<= 1; + bottom <<= 1; } if ((wx <= 0) || (wy <= 0)) - return; + return; if (ega->vres) - ega->y_add <<= 1; + ega->y_add <<= 1; xs_temp = wx; ys_temp = wy + 1; if (ega->vres) - ys_temp++; + ys_temp++; if (xs_temp < 64) - xs_temp = 640; + xs_temp = 640; if (ys_temp < 32) - ys_temp = 200; + ys_temp = 200; if ((ega->crtc[0x17] & 0x80) && ((xs_temp != xsize) || (ys_temp != ysize) || video_force_resize_get())) { - /* Screen res has changed.. fix up, and let them know. */ - xsize = xs_temp; - ysize = ys_temp; + /* Screen res has changed.. fix up, and let them know. */ + xsize = xs_temp; + ysize = ys_temp; - if ((xsize > 1984) || (ysize > 2016)) { - /* 2048x2048 is the biggest safe render texture, to account for overscan, - we suppress overscan starting from x 1984 and y 2016. */ - x_add = 0; - y_add = 0; - suppress_overscan = 1; - } else - suppress_overscan = 0; + if ((xsize > 1984) || (ysize > 2016)) { + /* 2048x2048 is the biggest safe render texture, to account for overscan, + we suppress overscan starting from x 1984 and y 2016. */ + x_add = 0; + y_add = 0; + suppress_overscan = 1; + } else + suppress_overscan = 0; - set_screen_size(xsize + x_add, ysize + y_add); + set_screen_size(xsize + x_add, ysize + y_add); - if (video_force_resize_get()) - video_force_resize_set(0); + if (video_force_resize_get()) + video_force_resize_set(0); } if ((wx >= 160) && ((wy + 1) >= 120)) { - /* Draw (overscan_size - scroll size) lines of overscan on top and bottom. */ - for (i = 0; i < ega->y_add; i++) { - p = &buffer32->line[i & 0x7ff][0]; + /* Draw (overscan_size - scroll size) lines of overscan on top and bottom. */ + for (i = 0; i < ega->y_add; i++) { + p = &buffer32->line[i & 0x7ff][0]; - for (j = 0; j < (xsize + x_add); j++) - p[j] = ega->overscan_color; - } + for (j = 0; j < (xsize + x_add); j++) + p[j] = ega->overscan_color; + } - for (i = 0; i < bottom; i++) { - p = &buffer32->line[(ysize + ega->y_add + i) & 0x7ff][0]; + for (i = 0; i < bottom; i++) { + p = &buffer32->line[(ysize + ega->y_add + i) & 0x7ff][0]; - for (j = 0; j < (xsize + x_add); j++) - p[j] = ega->overscan_color; - } + for (j = 0; j < (xsize + x_add); j++) + p[j] = ega->overscan_color; + } } video_blit_memtoscreen(x_start, y_start, xsize + x_add, ysize + y_add); if (ega->vres) - ega->y_add >>= 1; + ega->y_add >>= 1; } +uint32_t +ega_remap_cpu_addr(uint32_t inaddr, ega_t *ega) +{ + int a0mux; + uint32_t addr = inaddr; + + // The CPU A0 line is multiplexed via a 3-to-8 mux. + // Input bits are: + // bit 0: 1 = 64K, 0 = 128K+ (from memory expansion connector) + // bit 1: 1 = Odd/Even mode, 0 = normal mode (from GC reg 6 bit 1) + // bit 2: 1 = 128K mapping, 0 = other mapping (from memory decode PROM) + a0mux = 0; + + if (ega->gdcreg[6] & 2) { + a0mux |= 2; + } + if (ega->vram_limit <= 64 * 1024) { + a0mux |= 1; + } + + switch (ega->gdcreg[6] & 0xC) { + case 0x0: // 128K A000 + addr &= 0xFFFF; + // TODO: Confirm the behaviour of this on actual hardware + a0mux |= 4; + break; + case 0x4: // 64K A000 + addr &= 0xFFFF; + break; + case 0x8: // 32K B000 + addr &= 0x7FFF; + break; + case 0xC: // 32K B800 + addr &= 0x7FFF; + break; + + default: + break; + } + + switch (a0mux) { + case 0: + case 1: + case 4: + case 5: + case 7: // A0 becomes A0 + break; + case 2: + // A0 becomes the inversion of PGSEL (reg 0x3C2, miscout, bit 5) + // That is, 1 selects the "low" 64k, and 0 selects the "high" 64k. + addr &= ~1; + addr |= (~ega->miscout >> 5) & 1; + break; + case 3: // A0 becomes A14 + addr &= ~1; + addr |= (inaddr >> 14) & 1; + break; + case 6: // A0 becomes A16 + addr &= ~1; + addr |= (inaddr >> 16) & 1; + break; + + default: + break; + } + + // In 64k mode, only select the first 16Kword/64KB bank + if (!(ega->seqregs[4] & 2)) { + addr &= 0x3FFF; + } + return addr; +} void -ega_write(uint32_t addr, uint8_t val, void *p) +ega_write(uint32_t addr, uint8_t val, void *priv) { - ega_t *ega = (ega_t *)p; - uint8_t vala, valb, valc, vald; - int writemask2 = ega->writemask; + ega_t *ega = (ega_t *) priv; + uint8_t vala; + uint8_t valb; + uint8_t valc; + uint8_t vald; + int writemask2 = ega->writemask; cycles -= video_timing_write_b; - if (addr >= 0xB0000) addr &= 0x7fff; - else addr &= 0xffff; - if (ega->chain2_write) { - writemask2 &= ~0xa; - if (addr & 1) - writemask2 <<= 1; - addr &= ~1; - if (addr & 0x4000) - addr |= 1; - addr &= ~0x4000; + writemask2 &= ~0xa; + if (addr & 1) + writemask2 <<= 1; } + addr = ega_remap_cpu_addr(addr, ega); + addr <<= 2; if (addr >= ega->vram_limit) - return; + return; - if (!(ega->gdcreg[6] & 1)) - fullchange = 2; + if (!(ega->gdcreg[6] & 1)) + ega->fullchange = 2; switch (ega->writemode) { - case 1: - if (writemask2 & 1) ega->vram[addr] = ega->la; - if (writemask2 & 2) ega->vram[addr | 0x1] = ega->lb; - if (writemask2 & 4) ega->vram[addr | 0x2] = ega->lc; - if (writemask2 & 8) ega->vram[addr | 0x3] = ega->ld; - break; - case 0: - if (ega->gdcreg[3] & 7) - val = ega_rotate[ega->gdcreg[3] & 7][val]; + case 1: + if (writemask2 & 1) + ega->vram[addr] = ega->la; + if (writemask2 & 2) + ega->vram[addr | 0x1] = ega->lb; + if (writemask2 & 4) + ega->vram[addr | 0x2] = ega->lc; + if (writemask2 & 8) + ega->vram[addr | 0x3] = ega->ld; + break; + case 0: + if (ega->gdcreg[3] & 7) + val = ega_rotate[ega->gdcreg[3] & 7][val]; - if ((ega->gdcreg[8] == 0xff) && !(ega->gdcreg[3] & 0x18) && !ega->gdcreg[1]) { - if (writemask2 & 1) ega->vram[addr] = val; - if (writemask2 & 2) ega->vram[addr | 0x1] = val; - if (writemask2 & 4) ega->vram[addr | 0x2] = val; - if (writemask2 & 8) ega->vram[addr | 0x3] = val; - } else { - if (ega->gdcreg[1] & 1) vala = (ega->gdcreg[0] & 1) ? 0xff : 0; - else vala = val; - if (ega->gdcreg[1] & 2) valb = (ega->gdcreg[0] & 2) ? 0xff : 0; - else valb = val; - if (ega->gdcreg[1] & 4) valc = (ega->gdcreg[0] & 4) ? 0xff : 0; - else valc = val; - if (ega->gdcreg[1] & 8) vald = (ega->gdcreg[0] & 8) ? 0xff : 0; - else vald = val; - switch (ega->gdcreg[3] & 0x18) { - case 0: /*Set*/ - if (writemask2 & 1) ega->vram[addr] = (vala & ega->gdcreg[8]) | (ega->la & ~ega->gdcreg[8]); - if (writemask2 & 2) ega->vram[addr | 0x1] = (valb & ega->gdcreg[8]) | (ega->lb & ~ega->gdcreg[8]); - if (writemask2 & 4) ega->vram[addr | 0x2] = (valc & ega->gdcreg[8]) | (ega->lc & ~ega->gdcreg[8]); - if (writemask2 & 8) ega->vram[addr | 0x3] = (vald & ega->gdcreg[8]) | (ega->ld & ~ega->gdcreg[8]); - break; - case 8: /*AND*/ - if (writemask2 & 1) ega->vram[addr] = (vala | ~ega->gdcreg[8]) & ega->la; - if (writemask2 & 2) ega->vram[addr | 0x1] = (valb | ~ega->gdcreg[8]) & ega->lb; - if (writemask2 & 4) ega->vram[addr | 0x2] = (valc | ~ega->gdcreg[8]) & ega->lc; - if (writemask2 & 8) ega->vram[addr | 0x3] = (vald | ~ega->gdcreg[8]) & ega->ld; - break; - case 0x10: /*OR*/ - if (writemask2 & 1) ega->vram[addr] = (vala & ega->gdcreg[8]) | ega->la; - if (writemask2 & 2) ega->vram[addr | 0x1] = (valb & ega->gdcreg[8]) | ega->lb; - if (writemask2 & 4) ega->vram[addr | 0x2] = (valc & ega->gdcreg[8]) | ega->lc; - if (writemask2 & 8) ega->vram[addr | 0x3] = (vald & ega->gdcreg[8]) | ega->ld; - break; - case 0x18: /*XOR*/ - if (writemask2 & 1) ega->vram[addr] = (vala & ega->gdcreg[8]) ^ ega->la; - if (writemask2 & 2) ega->vram[addr | 0x1] = (valb & ega->gdcreg[8]) ^ ega->lb; - if (writemask2 & 4) ega->vram[addr | 0x2] = (valc & ega->gdcreg[8]) ^ ega->lc; - if (writemask2 & 8) ega->vram[addr | 0x3] = (vald & ega->gdcreg[8]) ^ ega->ld; - break; - } - } - break; - case 2: - if (!(ega->gdcreg[3] & 0x18) && !ega->gdcreg[1]) { - if (writemask2 & 1) ega->vram[addr] = (((val & 1) ? 0xff : 0) & ega->gdcreg[8]) | (ega->la & ~ega->gdcreg[8]); - if (writemask2 & 2) ega->vram[addr | 0x1] = (((val & 2) ? 0xff : 0) & ega->gdcreg[8]) | (ega->lb & ~ega->gdcreg[8]); - if (writemask2 & 4) ega->vram[addr | 0x2] = (((val & 4) ? 0xff : 0) & ega->gdcreg[8]) | (ega->lc & ~ega->gdcreg[8]); - if (writemask2 & 8) ega->vram[addr | 0x3] = (((val & 8) ? 0xff : 0) & ega->gdcreg[8]) | (ega->ld & ~ega->gdcreg[8]); - } else { - vala = ((val & 1) ? 0xff : 0); - valb = ((val & 2) ? 0xff : 0); - valc = ((val & 4) ? 0xff : 0); - vald = ((val & 8) ? 0xff : 0); - switch (ega->gdcreg[3] & 0x18) { - case 0: /*Set*/ - if (writemask2 & 1) ega->vram[addr] = (vala & ega->gdcreg[8]) | (ega->la & ~ega->gdcreg[8]); - if (writemask2 & 2) ega->vram[addr | 0x1] = (valb & ega->gdcreg[8]) | (ega->lb & ~ega->gdcreg[8]); - if (writemask2 & 4) ega->vram[addr | 0x2] = (valc & ega->gdcreg[8]) | (ega->lc & ~ega->gdcreg[8]); - if (writemask2 & 8) ega->vram[addr | 0x3] = (vald & ega->gdcreg[8]) | (ega->ld & ~ega->gdcreg[8]); - break; - case 8: /*AND*/ - if (writemask2 & 1) ega->vram[addr] = (vala | ~ega->gdcreg[8]) & ega->la; - if (writemask2 & 2) ega->vram[addr | 0x1] = (valb | ~ega->gdcreg[8]) & ega->lb; - if (writemask2 & 4) ega->vram[addr | 0x2] = (valc | ~ega->gdcreg[8]) & ega->lc; - if (writemask2 & 8) ega->vram[addr | 0x3] = (vald | ~ega->gdcreg[8]) & ega->ld; - break; - case 0x10: /*OR*/ - if (writemask2 & 1) ega->vram[addr] = (vala & ega->gdcreg[8]) | ega->la; - if (writemask2 & 2) ega->vram[addr | 0x1] = (valb & ega->gdcreg[8]) | ega->lb; - if (writemask2 & 4) ega->vram[addr | 0x2] = (valc & ega->gdcreg[8]) | ega->lc; - if (writemask2 & 8) ega->vram[addr | 0x3] = (vald & ega->gdcreg[8]) | ega->ld; - break; - case 0x18: /*XOR*/ - if (writemask2 & 1) ega->vram[addr] = (vala & ega->gdcreg[8]) ^ ega->la; - if (writemask2 & 2) ega->vram[addr | 0x1] = (valb & ega->gdcreg[8]) ^ ega->lb; - if (writemask2 & 4) ega->vram[addr | 0x2] = (valc & ega->gdcreg[8]) ^ ega->lc; - if (writemask2 & 8) ega->vram[addr | 0x3] = (vald & ega->gdcreg[8]) ^ ega->ld; - break; - } - } - break; + if ((ega->gdcreg[8] == 0xff) && !(ega->gdcreg[3] & 0x18) && !ega->gdcreg[1]) { + if (writemask2 & 1) + ega->vram[addr] = val; + if (writemask2 & 2) + ega->vram[addr | 0x1] = val; + if (writemask2 & 4) + ega->vram[addr | 0x2] = val; + if (writemask2 & 8) + ega->vram[addr | 0x3] = val; + } else { + if (ega->gdcreg[1] & 1) + vala = (ega->gdcreg[0] & 1) ? 0xff : 0; + else + vala = val; + if (ega->gdcreg[1] & 2) + valb = (ega->gdcreg[0] & 2) ? 0xff : 0; + else + valb = val; + if (ega->gdcreg[1] & 4) + valc = (ega->gdcreg[0] & 4) ? 0xff : 0; + else + valc = val; + if (ega->gdcreg[1] & 8) + vald = (ega->gdcreg[0] & 8) ? 0xff : 0; + else + vald = val; + switch (ega->gdcreg[3] & 0x18) { + case 0: /*Set*/ + if (writemask2 & 1) + ega->vram[addr] = (vala & ega->gdcreg[8]) | (ega->la & ~ega->gdcreg[8]); + if (writemask2 & 2) + ega->vram[addr | 0x1] = (valb & ega->gdcreg[8]) | (ega->lb & ~ega->gdcreg[8]); + if (writemask2 & 4) + ega->vram[addr | 0x2] = (valc & ega->gdcreg[8]) | (ega->lc & ~ega->gdcreg[8]); + if (writemask2 & 8) + ega->vram[addr | 0x3] = (vald & ega->gdcreg[8]) | (ega->ld & ~ega->gdcreg[8]); + break; + case 8: /*AND*/ + if (writemask2 & 1) + ega->vram[addr] = (vala | ~ega->gdcreg[8]) & ega->la; + if (writemask2 & 2) + ega->vram[addr | 0x1] = (valb | ~ega->gdcreg[8]) & ega->lb; + if (writemask2 & 4) + ega->vram[addr | 0x2] = (valc | ~ega->gdcreg[8]) & ega->lc; + if (writemask2 & 8) + ega->vram[addr | 0x3] = (vald | ~ega->gdcreg[8]) & ega->ld; + break; + case 0x10: /*OR*/ + if (writemask2 & 1) + ega->vram[addr] = (vala & ega->gdcreg[8]) | ega->la; + if (writemask2 & 2) + ega->vram[addr | 0x1] = (valb & ega->gdcreg[8]) | ega->lb; + if (writemask2 & 4) + ega->vram[addr | 0x2] = (valc & ega->gdcreg[8]) | ega->lc; + if (writemask2 & 8) + ega->vram[addr | 0x3] = (vald & ega->gdcreg[8]) | ega->ld; + break; + case 0x18: /*XOR*/ + if (writemask2 & 1) + ega->vram[addr] = (vala & ega->gdcreg[8]) ^ ega->la; + if (writemask2 & 2) + ega->vram[addr | 0x1] = (valb & ega->gdcreg[8]) ^ ega->lb; + if (writemask2 & 4) + ega->vram[addr | 0x2] = (valc & ega->gdcreg[8]) ^ ega->lc; + if (writemask2 & 8) + ega->vram[addr | 0x3] = (vald & ega->gdcreg[8]) ^ ega->ld; + break; + + default: + break; + } + } + break; + case 2: + if (!(ega->gdcreg[3] & 0x18) && !ega->gdcreg[1]) { + if (writemask2 & 1) + ega->vram[addr] = (((val & 1) ? 0xff : 0) & ega->gdcreg[8]) | (ega->la & ~ega->gdcreg[8]); + if (writemask2 & 2) + ega->vram[addr | 0x1] = (((val & 2) ? 0xff : 0) & ega->gdcreg[8]) | (ega->lb & ~ega->gdcreg[8]); + if (writemask2 & 4) + ega->vram[addr | 0x2] = (((val & 4) ? 0xff : 0) & ega->gdcreg[8]) | (ega->lc & ~ega->gdcreg[8]); + if (writemask2 & 8) + ega->vram[addr | 0x3] = (((val & 8) ? 0xff : 0) & ega->gdcreg[8]) | (ega->ld & ~ega->gdcreg[8]); + } else { + vala = ((val & 1) ? 0xff : 0); + valb = ((val & 2) ? 0xff : 0); + valc = ((val & 4) ? 0xff : 0); + vald = ((val & 8) ? 0xff : 0); + switch (ega->gdcreg[3] & 0x18) { + case 0: /*Set*/ + if (writemask2 & 1) + ega->vram[addr] = (vala & ega->gdcreg[8]) | (ega->la & ~ega->gdcreg[8]); + if (writemask2 & 2) + ega->vram[addr | 0x1] = (valb & ega->gdcreg[8]) | (ega->lb & ~ega->gdcreg[8]); + if (writemask2 & 4) + ega->vram[addr | 0x2] = (valc & ega->gdcreg[8]) | (ega->lc & ~ega->gdcreg[8]); + if (writemask2 & 8) + ega->vram[addr | 0x3] = (vald & ega->gdcreg[8]) | (ega->ld & ~ega->gdcreg[8]); + break; + case 8: /*AND*/ + if (writemask2 & 1) + ega->vram[addr] = (vala | ~ega->gdcreg[8]) & ega->la; + if (writemask2 & 2) + ega->vram[addr | 0x1] = (valb | ~ega->gdcreg[8]) & ega->lb; + if (writemask2 & 4) + ega->vram[addr | 0x2] = (valc | ~ega->gdcreg[8]) & ega->lc; + if (writemask2 & 8) + ega->vram[addr | 0x3] = (vald | ~ega->gdcreg[8]) & ega->ld; + break; + case 0x10: /*OR*/ + if (writemask2 & 1) + ega->vram[addr] = (vala & ega->gdcreg[8]) | ega->la; + if (writemask2 & 2) + ega->vram[addr | 0x1] = (valb & ega->gdcreg[8]) | ega->lb; + if (writemask2 & 4) + ega->vram[addr | 0x2] = (valc & ega->gdcreg[8]) | ega->lc; + if (writemask2 & 8) + ega->vram[addr | 0x3] = (vald & ega->gdcreg[8]) | ega->ld; + break; + case 0x18: /*XOR*/ + if (writemask2 & 1) + ega->vram[addr] = (vala & ega->gdcreg[8]) ^ ega->la; + if (writemask2 & 2) + ega->vram[addr | 0x1] = (valb & ega->gdcreg[8]) ^ ega->lb; + if (writemask2 & 4) + ega->vram[addr | 0x2] = (valc & ega->gdcreg[8]) ^ ega->lc; + if (writemask2 & 8) + ega->vram[addr | 0x3] = (vald & ega->gdcreg[8]) ^ ega->ld; + break; + + default: + break; + } + } + break; + + default: + break; } } - uint8_t -ega_read(uint32_t addr, void *p) +ega_read(uint32_t addr, void *priv) { - ega_t *ega = (ega_t *)p; - uint8_t temp, temp2, temp3, temp4; - int readplane = ega->readplane; + ega_t *ega = (ega_t *) priv; + uint8_t temp; + uint8_t temp2; + uint8_t temp3; + uint8_t temp4; + int readplane = ega->readplane; cycles -= video_timing_read_b; - if (addr >= 0xb0000) addr &= 0x7fff; - else addr &= 0xffff; if (ega->chain2_read) { - readplane = (readplane & 2) | (addr & 1); - addr &= ~1; - if (addr & 0x4000) - addr |= 1; - addr &= ~0x4000; + readplane = (readplane & 2) | (addr & 1); } + addr = ega_remap_cpu_addr(addr, ega); + addr <<= 2; if (addr >= ega->vram_limit) - return 0xff; + return 0xff; ega->la = ega->vram[addr]; ega->lb = ega->vram[addr | 0x1]; ega->lc = ega->vram[addr | 0x2]; ega->ld = ega->vram[addr | 0x3]; if (ega->readmode) { - temp = ega->la; - temp ^= (ega->colourcompare & 1) ? 0xff : 0; - temp &= (ega->colournocare & 1) ? 0xff : 0; - temp2 = ega->lb; - temp2 ^= (ega->colourcompare & 2) ? 0xff : 0; - temp2 &= (ega->colournocare & 2) ? 0xff : 0; - temp3 = ega->lc; - temp3 ^= (ega->colourcompare & 4) ? 0xff : 0; - temp3 &= (ega->colournocare & 4) ? 0xff : 0; - temp4 = ega->ld; - temp4 ^= (ega->colourcompare & 8) ? 0xff : 0; - temp4 &= (ega->colournocare & 8) ? 0xff : 0; - return ~(temp | temp2 | temp3 | temp4); + temp = ega->la; + temp ^= (ega->colourcompare & 1) ? 0xff : 0; + temp &= (ega->colournocare & 1) ? 0xff : 0; + temp2 = ega->lb; + temp2 ^= (ega->colourcompare & 2) ? 0xff : 0; + temp2 &= (ega->colournocare & 2) ? 0xff : 0; + temp3 = ega->lc; + temp3 ^= (ega->colourcompare & 4) ? 0xff : 0; + temp3 &= (ega->colournocare & 4) ? 0xff : 0; + temp4 = ega->ld; + temp4 ^= (ega->colourcompare & 8) ? 0xff : 0; + temp4 &= (ega->colournocare & 8) ? 0xff : 0; + return ~(temp | temp2 | temp3 | temp4); } return ega->vram[addr | readplane]; } - void ega_init(ega_t *ega, int monitor_type, int is_mono) { - int c, d, e; + int c; + int d; + int e; - ega->vram = malloc(0x40000); + ega->vram = malloc(0x40000); ega->vrammask = 0x3ffff; for (c = 0; c < 256; c++) { - e = c; - for (d = 0; d < 8; d++) { - ega_rotate[d][c] = e; - e = (e >> 1) | ((e & 1) ? 0x80 : 0); - } + e = c; + for (d = 0; d < 8; d++) { + ega_rotate[d][c] = e; + e = (e >> 1) | ((e & 1) ? 0x80 : 0); + } } for (c = 0; c < 4; c++) { - for (d = 0; d < 4; d++) { - edatlookup[c][d] = 0; - if (c & 1) edatlookup[c][d] |= 1; - if (d & 1) edatlookup[c][d] |= 2; - if (c & 2) edatlookup[c][d] |= 0x10; - if (d & 2) edatlookup[c][d] |= 0x20; - } + for (d = 0; d < 4; d++) { + edatlookup[c][d] = 0; + if (c & 1) + edatlookup[c][d] |= 1; + if (d & 1) + edatlookup[c][d] |= 2; + if (c & 2) + edatlookup[c][d] |= 0x10; + if (d & 2) + edatlookup[c][d] |= 0x20; + } + } + + for (c = 0; c < 256; c++) { + egaremap2bpp[c] = 0; + if (c & 0x01) + egaremap2bpp[c] |= 0x01; + if (c & 0x04) + egaremap2bpp[c] |= 0x02; + if (c & 0x10) + egaremap2bpp[c] |= 0x04; + if (c & 0x40) + egaremap2bpp[c] |= 0x08; } if (is_mono) { - for (c = 0; c < 256; c++) { - if (((c >> 3) & 3) == 0) - pallook64[c] = pallook16[c] = makecol32(0, 0, 0); - else switch (monitor_type >> 4) { - case DISPLAY_GREEN: - switch ((c >> 3) & 3) { - case 1: - pallook64[c] = pallook16[c] = makecol32(0x08, 0xc7, 0x2c); - break; - case 2: - pallook64[c] = pallook16[c] = makecol32(0x04, 0x8a, 0x20); - break; - case 3: - pallook64[c] = pallook16[c] = makecol32(0x34, 0xff, 0x5d); - break; - } - break; - case DISPLAY_AMBER: - switch ((c >> 3) & 3) { - case 1: - pallook64[c] = pallook16[c] = makecol32(0xef, 0x79, 0x00); - break; - case 2: - pallook64[c] = pallook16[c] = makecol32(0xb2, 0x4d, 0x00); - break; - case 3: - pallook64[c] = pallook16[c] = makecol32(0xff, 0xe3, 0x34); - break; - } - break; - case DISPLAY_WHITE: default: - switch ((c >> 3) & 3) { - case 1: - pallook64[c] = pallook16[c] = makecol32(0xaf, 0xb3, 0xb0); - break; - case 2: - pallook64[c] = pallook16[c] = makecol32(0x7a, 0x81, 0x83); - break; - case 3: - pallook64[c] = pallook16[c] = makecol32(0xff, 0xfd, 0xed); - break; - } - break; - } - } + for (c = 0; c < 256; c++) { + if (((c >> 3) & 3) == 0) + pallook64[c] = pallook16[c] = makecol32(0, 0, 0); + else + switch (monitor_type >> 4) { + case DISPLAY_GREEN: + switch ((c >> 3) & 3) { + case 1: + pallook64[c] = pallook16[c] = makecol32(0x08, 0xc7, 0x2c); + break; + case 2: + pallook64[c] = pallook16[c] = makecol32(0x04, 0x8a, 0x20); + break; + case 3: + pallook64[c] = pallook16[c] = makecol32(0x34, 0xff, 0x5d); + break; - io_sethandler(0x03a0, 0x0020, ega_in, NULL, NULL, ega_out, NULL, NULL, ega); + default: + break; + } + break; + case DISPLAY_AMBER: + switch ((c >> 3) & 3) { + case 1: + pallook64[c] = pallook16[c] = makecol32(0xef, 0x79, 0x00); + break; + case 2: + pallook64[c] = pallook16[c] = makecol32(0xb2, 0x4d, 0x00); + break; + case 3: + pallook64[c] = pallook16[c] = makecol32(0xff, 0xe3, 0x34); + break; + + default: + break; + } + break; + case DISPLAY_WHITE: + default: + switch ((c >> 3) & 3) { + case 1: + pallook64[c] = pallook16[c] = makecol32(0xaf, 0xb3, 0xb0); + break; + case 2: + pallook64[c] = pallook16[c] = makecol32(0x7a, 0x81, 0x83); + break; + case 3: + pallook64[c] = pallook16[c] = makecol32(0xff, 0xfd, 0xed); + break; + + default: + break; + } + break; + } + } + + io_sethandler(0x03a0, 0x0020, ega_in, NULL, NULL, ega_out, NULL, NULL, ega); } else { - for (c = 0; c < 256; c++) { - pallook64[c] = makecol32(((c >> 2) & 1) * 0xaa, ((c >> 1) & 1) * 0xaa, (c & 1) * 0xaa); - pallook64[c] += makecol32(((c >> 5) & 1) * 0x55, ((c >> 4) & 1) * 0x55, ((c >> 3) & 1) * 0x55); - pallook16[c] = makecol32(((c >> 2) & 1) * 0xaa, ((c >> 1) & 1) * 0xaa, (c & 1) * 0xaa); - pallook16[c] += makecol32(((c >> 4) & 1) * 0x55, ((c >> 4) & 1) * 0x55, ((c >> 4) & 1) * 0x55); - if ((c & 0x17) == 6) - pallook16[c] = makecol32(0xaa, 0x55, 0); - } + for (c = 0; c < 256; c++) { + pallook64[c] = makecol32(((c >> 2) & 1) * 0xaa, ((c >> 1) & 1) * 0xaa, (c & 1) * 0xaa); + pallook64[c] += makecol32(((c >> 5) & 1) * 0x55, ((c >> 4) & 1) * 0x55, ((c >> 3) & 1) * 0x55); + pallook16[c] = makecol32(((c >> 2) & 1) * 0xaa, ((c >> 1) & 1) * 0xaa, (c & 1) * 0xaa); + pallook16[c] += makecol32(((c >> 4) & 1) * 0x55, ((c >> 4) & 1) * 0x55, ((c >> 4) & 1) * 0x55); + if ((c & 0x17) == 6) + pallook16[c] = makecol32(0xaa, 0x55, 0); + } - ega->miscout |= 1; + ega->miscout |= 1; } ega->pallook = pallook16; @@ -1008,7 +1385,7 @@ ega_init(ega_t *ega, int monitor_type, int is_mono) egaswitches = monitor_type & 0xf; ega->vram_limit = 256 * 1024; - ega->vrammask = ega->vram_limit - 1; + ega->vrammask = ega->vram_limit - 1; old_overscan_color = 0; @@ -1024,16 +1401,17 @@ ega_init(ega_t *ega, int monitor_type, int is_mono) ega->crtc[6] = 255; timer_add(&ega->timer, ega_poll, ega, 1); + if (ega_type == 2) + timer_add(&ega->dot_timer, ega_dot_poll, ega, 1); } - static void * ega_standalone_init(const device_t *info) { ega_t *ega = malloc(sizeof(ega_t)); - int monitor_type, c; + int monitor_type; - memset(ega, 0, sizeof(ega_t)); + memset(ega, 0x00, sizeof(ega_t)); video_inform(VIDEO_FLAG_TYPE_SPECIAL, &timing_ega); @@ -1042,282 +1420,292 @@ ega_standalone_init(const device_t *info) ega->x_add = 8; ega->y_add = 14; - if ((info->local == EGA_IBM) || (info->local == EGA_ISKRA) || - (info->local == EGA_TSENG)) - ega_type = 0; + if ((info->local == EGA_IBM) || (info->local == EGA_ISKRA) || (info->local == EGA_TSENG)) + ega_type = 0; + else if (info->local == EGA_COMPAQ) + ega_type = 2; else - ega_type = 1; + ega_type = 1; - switch(info->local) { - case EGA_IBM: - default: - rom_init(&ega->bios_rom, BIOS_IBM_PATH, - 0xc0000, 0x8000, 0x7fff, 0, MEM_MAPPING_EXTERNAL); - break; - case EGA_COMPAQ: - rom_init(&ega->bios_rom, BIOS_CPQ_PATH, - 0xc0000, 0x8000, 0x7fff, 0, MEM_MAPPING_EXTERNAL); - break; - case EGA_SUPEREGA: - rom_init(&ega->bios_rom, BIOS_SEGA_PATH, - 0xc0000, 0x8000, 0x7fff, 0, MEM_MAPPING_EXTERNAL); - break; - case EGA_ATI: - rom_init(&ega->bios_rom, BIOS_ATIEGA_PATH, - 0xc0000, 0x8000, 0x7fff, 0, MEM_MAPPING_EXTERNAL); - break; - case EGA_ISKRA: - rom_init_interleaved(&ega->bios_rom, BIOS_ISKRA_PATH, - 0xc0000, 0x8000, 0x7fff, 0, MEM_MAPPING_EXTERNAL); - break; - case EGA_TSENG: - rom_init(&ega->bios_rom, BIOS_TSENG_PATH, - 0xc0000, 0x8000, 0x7fff, 0, MEM_MAPPING_EXTERNAL); - break; + switch (info->local) { + default: + case EGA_IBM: + rom_init(&ega->bios_rom, BIOS_IBM_PATH, + 0xc0000, 0x8000, 0x7fff, 0, MEM_MAPPING_EXTERNAL); + break; + case EGA_COMPAQ: + ega->ctl_mode = 0x21; + rom_init(&ega->bios_rom, BIOS_CPQ_PATH, + 0xc0000, 0x8000, 0x7fff, 0, MEM_MAPPING_EXTERNAL); + break; + case EGA_SUPEREGA: + rom_init(&ega->bios_rom, BIOS_SEGA_PATH, + 0xc0000, 0x8000, 0x7fff, 0, MEM_MAPPING_EXTERNAL); + break; + case EGA_ATI: + rom_init(&ega->bios_rom, BIOS_ATIEGA_PATH, + 0xc0000, 0x8000, 0x7fff, 0, MEM_MAPPING_EXTERNAL); + break; + case EGA_ISKRA: + rom_init_interleaved(&ega->bios_rom, BIOS_ISKRA_PATH, + 0xc0000, 0x8000, 0x7fff, 0, MEM_MAPPING_EXTERNAL); + break; + case EGA_TSENG: + rom_init(&ega->bios_rom, BIOS_TSENG_PATH, + 0xc0000, 0x8000, 0x7fff, 0, MEM_MAPPING_EXTERNAL); + break; } if ((ega->bios_rom.rom[0x3ffe] == 0xaa) && (ega->bios_rom.rom[0x3fff] == 0x55)) { - for (c = 0; c < 0x2000; c++) { - uint8_t temp = ega->bios_rom.rom[c]; - ega->bios_rom.rom[c] = ega->bios_rom.rom[0x3fff - c]; - ega->bios_rom.rom[0x3fff - c] = temp; - } + for (uint16_t c = 0; c < 0x2000; c++) { + uint8_t temp = ega->bios_rom.rom[c]; + ega->bios_rom.rom[c] = ega->bios_rom.rom[0x3fff - c]; + ega->bios_rom.rom[0x3fff - c] = temp; + } } monitor_type = device_get_config_int("monitor_type"); ega_init(ega, monitor_type, (monitor_type & 0x0F) == 0x0B); ega->vram_limit = device_get_config_int("memory") * 1024; - ega->vrammask = ega->vram_limit - 1; + ega->vrammask = ega->vram_limit - 1; mem_mapping_add(&ega->mapping, 0xa0000, 0x20000, ega_read, NULL, NULL, ega_write, NULL, NULL, NULL, MEM_MAPPING_EXTERNAL, ega); io_sethandler(0x03c0, 0x0020, ega_in, NULL, NULL, ega_out, NULL, NULL, ega); if (info->local == EGA_ATI) { - io_sethandler(0x01ce, 0x0002, ega_in, NULL, NULL, ega_out, NULL, NULL, ega); - ega->eeprom = malloc(sizeof(ati_eeprom_t)); - memset(ega->eeprom, 0, sizeof(ati_eeprom_t)); - ati_eeprom_load((ati_eeprom_t *) ega->eeprom, "egawonder800.nvr", 0); + io_sethandler(0x01ce, 0x0002, ega_in, NULL, NULL, ega_out, NULL, NULL, ega); + ega->eeprom = malloc(sizeof(ati_eeprom_t)); + memset(ega->eeprom, 0, sizeof(ati_eeprom_t)); + ati_eeprom_load((ati_eeprom_t *) ega->eeprom, "egawonder800.nvr", 0); + } else if (info->local == EGA_COMPAQ) { + io_sethandler(0x0084, 0x0001, ega_in, NULL, NULL, ega_out, NULL, NULL, ega); + io_sethandler(0x07c6, 0x0001, ega_in, NULL, NULL, ega_out, NULL, NULL, ega); + io_sethandler(0x0bc6, 0x0001, ega_in, NULL, NULL, ega_out, NULL, NULL, ega); + io_sethandler(0x0fc6, 0x0001, ega_in, NULL, NULL, ega_out, NULL, NULL, ega); } return ega; } - static int ega_standalone_available(void) { return rom_present(BIOS_IBM_PATH); } - static int cpqega_standalone_available(void) { return rom_present(BIOS_CPQ_PATH); } - static int sega_standalone_available(void) { return rom_present(BIOS_SEGA_PATH); } - static int atiega_standalone_available(void) { return rom_present(BIOS_ATIEGA_PATH); } - static int iskra_ega_standalone_available(void) { return rom_present("roms/video/ega/143-02.bin") && rom_present("roms/video/ega/143-03.bin"); } - static int et2000_standalone_available(void) { return rom_present(BIOS_TSENG_PATH); } - static void -ega_close(void *p) +ega_close(void *priv) { - ega_t *ega = (ega_t *)p; + ega_t *ega = (ega_t *) priv; if (ega->eeprom) - free(ega->eeprom); + free(ega->eeprom); free(ega->vram); free(ega); } - static void -ega_speed_changed(void *p) +ega_speed_changed(void *priv) { - ega_t *ega = (ega_t *)p; + ega_t *ega = (ega_t *) priv; ega_recalctimings(ega); } - /* SW1 SW2 SW3 SW4 - OFF OFF ON OFF Monochrome (5151) 1011 0x0B - ON OFF OFF ON Color 40x25 (5153) 0110 0x06 - OFF OFF OFF ON Color 80x25 (5153) 0111 0x07 - ON ON ON OFF Enhanced Color - Normal Mode (5154) 1000 0x08 - OFF ON ON OFF Enhanced Color - Enhanced Mode (5154) 1001 0x09 + OFF OFF ON OFF Monochrome (5151) 1011 0x0B + ON OFF OFF ON Color 40x25 (5153) 0110 0x06 + OFF OFF OFF ON Color 80x25 (5153) 0111 0x07 + ON ON ON OFF Enhanced Color - Normal Mode (5154) 1000 0x08 + OFF ON ON OFF Enhanced Color - Enhanced Mode (5154) 1001 0x09 0 = Switch closed (ON); 1 = Switch open (OFF). */ -static const device_config_t ega_config[] = -{ - { - "memory", "Memory size", CONFIG_SELECTION, "", 256, "", { 0 }, - { - { - "32 kB", 32 - }, - { - "64 kB", 64 - }, - { - "128 kB", 128 - }, - { - "256 kB", 256 - }, - { - "" - } - } - }, - { - .name = "monitor_type", - .description = "Monitor type", - .type = CONFIG_SELECTION, - .selection = - { - { - .description = "Monochrome (5151/MDA) (white)", - .value = 0x0B | (DISPLAY_WHITE << 4) - }, - { - .description = "Monochrome (5151/MDA) (green)", - .value = 0x0B | (DISPLAY_GREEN << 4) - }, - { - .description = "Monochrome (5151/MDA) (amber)", - .value = 0x0B | (DISPLAY_AMBER << 4) - }, - { - .description = "Color 40x25 (5153/CGA)", - .value = 0x06 - }, - { - .description = "Color 80x25 (5153/CGA)", - .value = 0x07 - }, - { - .description = "Enhanced Color - Normal Mode (5154/ECD)", - .value = 0x08 - }, - { - .description = "Enhanced Color - Enhanced Mode (5154/ECD)", - .value = 0x09 - }, - { - .description = "" - } - }, - .default_int = 9 - }, - { - .type = -1 +static const device_config_t ega_config[] = { + // clang-format off + { + .name = "memory", + .description = "Memory size", + .type = CONFIG_SELECTION, + .default_int = 256, + .selection = { + { + .description = "32 kB", + .value = 32 + }, + { + .description = "64 kB", + .value = 64 + }, + { + .description = "128 kB", + .value = 128 + }, + { + .description = "256 kB", + .value = 256 + }, + { + .description = "" + } } + }, + { + .name = "monitor_type", + .description = "Monitor type", + .type = CONFIG_SELECTION, + .selection = { + { + .description = "Monochrome (5151/MDA) (white)", + .value = 0x0B | (DISPLAY_WHITE << 4) + }, + { + .description = "Monochrome (5151/MDA) (green)", + .value = 0x0B | (DISPLAY_GREEN << 4) + }, + { + .description = "Monochrome (5151/MDA) (amber)", + .value = 0x0B | (DISPLAY_AMBER << 4) + }, + { + .description = "Color 40x25 (5153/CGA)", + .value = 0x06 + }, + { + .description = "Color 80x25 (5153/CGA)", + .value = 0x07 + }, + { + .description = "Enhanced Color - Normal Mode (5154/ECD)", + .value = 0x08 + }, + { + .description = "Enhanced Color - Enhanced Mode (5154/ECD)", + .value = 0x09 + }, + { + .description = "" + } + }, + .default_int = 9 + }, + { + .type = CONFIG_END + } + // clang-format on }; - -const device_t ega_device = -{ - "EGA", - "ega", - DEVICE_ISA, - EGA_IBM, - ega_standalone_init, ega_close, NULL, - { ega_standalone_available }, - ega_speed_changed, - NULL, - ega_config +const device_t ega_device = { + .name = "EGA", + .internal_name = "ega", + .flags = DEVICE_ISA, + .local = EGA_IBM, + .init = ega_standalone_init, + .close = ega_close, + .reset = NULL, + { .available = ega_standalone_available }, + .speed_changed = ega_speed_changed, + .force_redraw = NULL, + .config = ega_config }; -const device_t cpqega_device = -{ - "Compaq EGA", - "compaq_ega", - DEVICE_ISA, - EGA_COMPAQ, - ega_standalone_init, ega_close, NULL, - { cpqega_standalone_available }, - ega_speed_changed, - NULL, - ega_config +const device_t cpqega_device = { + .name = "Compaq EGA", + .internal_name = "compaq_ega", + .flags = DEVICE_ISA, + .local = EGA_COMPAQ, + .init = ega_standalone_init, + .close = ega_close, + .reset = NULL, + { .available = cpqega_standalone_available }, + .speed_changed = ega_speed_changed, + .force_redraw = NULL, + .config = ega_config }; -const device_t sega_device = -{ - "SuperEGA", - "superega", - DEVICE_ISA, - EGA_SUPEREGA, - ega_standalone_init, ega_close, NULL, - { sega_standalone_available }, - ega_speed_changed, - NULL, - ega_config +const device_t sega_device = { + .name = "SuperEGA", + .internal_name = "superega", + .flags = DEVICE_ISA, + .local = EGA_SUPEREGA, + .init = ega_standalone_init, + .close = ega_close, + .reset = NULL, + { .available = sega_standalone_available }, + .speed_changed = ega_speed_changed, + .force_redraw = NULL, + .config = ega_config }; -const device_t atiega_device = -{ - "ATI EGA Wonder 800+", - "egawonder800", - DEVICE_ISA, - EGA_ATI, - ega_standalone_init, ega_close, NULL, - { atiega_standalone_available }, - ega_speed_changed, - NULL, - ega_config +const device_t atiega_device = { + .name = "ATI EGA Wonder 800+", + .internal_name = "egawonder800", + .flags = DEVICE_ISA, + .local = EGA_ATI, + .init = ega_standalone_init, + .close = ega_close, + .reset = NULL, + { .available = atiega_standalone_available }, + .speed_changed = ega_speed_changed, + .force_redraw = NULL, + .config = ega_config }; -const device_t iskra_ega_device = -{ - "Iskra EGA (Cyrillic ROM)", - "iskra_ega", - DEVICE_ISA, - EGA_ISKRA, - ega_standalone_init, ega_close, NULL, - { iskra_ega_standalone_available }, - ega_speed_changed, - NULL, - ega_config +const device_t iskra_ega_device = { + .name = "Iskra EGA (Cyrillic ROM)", + .internal_name = "iskra_ega", + .flags = DEVICE_ISA, + .local = EGA_ISKRA, + .init = ega_standalone_init, + .close = ega_close, + .reset = NULL, + { .available = iskra_ega_standalone_available }, + .speed_changed = ega_speed_changed, + .force_redraw = NULL, + .config = ega_config }; -const device_t et2000_device = -{ - "Tseng Labs ET2000", - "et2000", - DEVICE_ISA, - EGA_TSENG, - ega_standalone_init, ega_close, NULL, - { et2000_standalone_available }, - ega_speed_changed, - NULL, - ega_config +const device_t et2000_device = { + .name = "Tseng Labs ET2000", + .internal_name = "et2000", + .flags = DEVICE_ISA, + .local = EGA_TSENG, + .init = ega_standalone_init, + .close = ega_close, + .reset = NULL, + { .available = et2000_standalone_available }, + .speed_changed = ega_speed_changed, + .force_redraw = NULL, + .config = ega_config }; diff --git a/src/video/vid_ega_render.c b/src/video/vid_ega_render.c index 9ea2a7bd3..2d15d6dc5 100644 --- a/src/video/vid_ega_render.c +++ b/src/video/vid_ega_render.c @@ -1,23 +1,24 @@ /* - * 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. + * 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. + * This file is part of the 86Box distribution. * - * EGA renderers. + * EGA renderers. * * * - * Author: Sarah Walker, - * Miran Grca, + * Authors: Sarah Walker, + * Miran Grca, * - * Copyright 2008-2019 Sarah Walker. - * Copyright 2016-2019 Miran Grca. + * Copyright 2008-2019 Sarah Walker. + * Copyright 2016-2019 Miran Grca. */ #include #include +#include #include #include #include <86box/86box.h> @@ -27,482 +28,224 @@ #include <86box/rom.h> #include <86box/video.h> #include <86box/vid_ega.h> - +#include <86box/vid_ega_render_remap.h> int ega_display_line(ega_t *ega) { - int y_add = (enable_overscan) ? (overscan_y >> 1) : 0; - unsigned int dl = ega->displine; + int y_add = enable_overscan ? (overscan_y >> 1) : 0; + unsigned int dl = ega->displine; if (ega->crtc[9] & 0x1f) - dl -= (ega->crtc[8] & 0x1f); + dl -= (ega->crtc[8] & 0x1f); dl += y_add; dl &= 0x7ff; return dl; } - void ega_render_blank(ega_t *ega) { - int x, xx; - if ((ega->displine + ega->y_add) < 0) - return; + return; - for (x = 0; x < (ega->hdisp + ega->scrollcache); x++) { - switch (ega->seqregs[1] & 9) { - case 0: - for (xx = 0; xx < 9; xx++) buffer32->line[ega->displine + ega->y_add][ega->x_add + (x * 9) + xx] = 0; - break; - case 1: - for (xx = 0; xx < 8; xx++) buffer32->line[ega->displine + ega->y_add][ega->x_add + (x * 8) + xx] = 0; - break; - case 8: - for (xx = 0; xx < 18; xx++) buffer32->line[ega->displine + ega->y_add][ega->x_add + (x * 18) + xx] = 0; - break; - case 9: - for (xx = 0; xx < 16; xx++) buffer32->line[ega->displine + ega->y_add][ega->x_add + (x * 16) + xx] = 0; - break; - } + for (int x = 0; x < (ega->hdisp + ega->scrollcache); x++) { + switch (ega->seqregs[1] & 9) { + case 0: + for (uint8_t xx = 0; xx < 9; xx++) + buffer32->line[ega->displine + ega->y_add][ega->x_add + (x * 9) + xx] = 0; + break; + case 1: + for (uint8_t xx = 0; xx < 8; xx++) + buffer32->line[ega->displine + ega->y_add][ega->x_add + (x * 8) + xx] = 0; + break; + case 8: + for (uint8_t xx = 0; xx < 18; xx++) + buffer32->line[ega->displine + ega->y_add][ega->x_add + (x * 18) + xx] = 0; + break; + case 9: + for (uint8_t xx = 0; xx < 16; xx++) + buffer32->line[ega->displine + ega->y_add][ega->x_add + (x * 16) + xx] = 0; + break; + + default: + break; + } } } - void ega_render_overscan_left(ega_t *ega) { - int i; - if ((ega->displine + ega->y_add) < 0) - return; + return; if (ega->scrblank || (ega->hdisp == 0)) - return; + return; - for (i = 0; i < ega->x_add; i++) - buffer32->line[ega->displine + ega->y_add][i] = ega->overscan_color; + for (int i = 0; i < ega->x_add; i++) + buffer32->line[ega->displine + ega->y_add][i] = ega->overscan_color; } - void ega_render_overscan_right(ega_t *ega) { - int i, right; + int right; if ((ega->displine + ega->y_add) < 0) - return; + return; if (ega->scrblank || (ega->hdisp == 0)) - return; + return; right = (overscan_x >> 1) + ega->scrollcache; - for (i = 0; i < right; i++) - buffer32->line[ega->displine + ega->y_add][ega->x_add + ega->hdisp + i] = ega->overscan_color; + for (int i = 0; i < right; i++) + buffer32->line[ega->displine + ega->y_add][ega->x_add + ega->hdisp + i] = ega->overscan_color; } - void -ega_render_text_40(ega_t *ega) -{ - uint32_t *p; - int x, xx; - int drawcursor, xinc; - uint8_t chr, attr, dat; - uint32_t charaddr; - int fg, bg; - - if ((ega->displine + ega->y_add) < 0) - return; - - if (ega->firstline_draw == 2000) - ega->firstline_draw = ega->displine; - ega->lastline_draw = ega->displine; - - if (fullchange) { - p = &buffer32->line[ega->displine + ega->y_add][ega->x_add]; - xinc = (ega->seqregs[1] & 1) ? 16 : 18; - - for (x = 0; x < (ega->hdisp + ega->scrollcache); x += xinc) { - drawcursor = ((ega->ma == ega->ca) && ega->con && ega->cursoron); - - if (ega->crtc[0x17] & 0x80) { - chr = ega->vram[(ega->ma << 1) & ega->vrammask]; - attr = ega->vram[((ega->ma << 1) + 1) & ega->vrammask]; - } else - chr = attr = 0; - - if (attr & 8) charaddr = ega->charsetb + (chr * 128); - else charaddr = ega->charseta + (chr * 128); - - if (drawcursor) { - bg = ega->pallook[ega->egapal[attr & 15]]; - fg = ega->pallook[ega->egapal[attr >> 4]]; - } else { - fg = ega->pallook[ega->egapal[attr & 15]]; - bg = ega->pallook[ega->egapal[attr >> 4]]; - - if (attr & 0x80 && ega->attrregs[0x10] & 8) { - bg = ega->pallook[ega->egapal[(attr >> 4) & 7]]; - if (ega->blink & 16) - fg = bg; - } - } - - dat = ega->vram[charaddr + (ega->sc << 2)]; - if (ega->seqregs[1] & 1) { - for (xx = 0; xx < 16; xx += 2) - p[xx] = p[xx + 1] = (dat & (0x80 >> (xx >> 1))) ? fg : bg; - } else { - for (xx = 0; xx < 16; xx += 2) - p[xx] = p[xx + 1] = (dat & (0x80 >> (xx >> 1))) ? fg : bg; - if ((chr & ~0x1f) != 0xc0 || !(ega->attrregs[0x10] & 4)) - p[16] = p[17] = bg; - else - p[16] = p[17] = (dat & 1) ? fg : bg; - } - ega->ma += 4; - p += xinc; - } - ega->ma &= ega->vrammask; - } -} - - -void -ega_render_text_80(ega_t *ega) +ega_render_text(ega_t *ega) { - uint32_t *p; - int x, xx; - int drawcursor, xinc; - uint8_t chr, attr, dat; - uint32_t charaddr; - int fg, bg; - if ((ega->displine + ega->y_add) < 0) - return; - - if (ega->firstline_draw == 2000) - ega->firstline_draw = ega->displine; - ega->lastline_draw = ega->displine; - - if (fullchange) { - p = &buffer32->line[ega->displine + ega->y_add][ega->x_add]; - xinc = (ega->seqregs[1] & 1) ? 8 : 9; - - for (x = 0; x < (ega->hdisp + ega->scrollcache); x += xinc) { - drawcursor = ((ega->ma == ega->ca) && ega->con && ega->cursoron); - - if (ega->crtc[0x17] & 0x80) { - chr = ega->vram[(ega->ma << 1) & ega->vrammask]; - attr = ega->vram[((ega->ma << 1) + 1) & ega->vrammask]; - } else - chr = attr = 0; - - if (attr & 8) charaddr = ega->charsetb + (chr * 128); - else charaddr = ega->charseta + (chr * 128); - - if (drawcursor) { - bg = ega->pallook[ega->egapal[attr & 15]]; - fg = ega->pallook[ega->egapal[attr >> 4]]; - } else { - fg = ega->pallook[ega->egapal[attr & 15]]; - bg = ega->pallook[ega->egapal[attr >> 4]]; - if (attr & 0x80 && ega->attrregs[0x10] & 8) { - bg = ega->pallook[ega->egapal[(attr >> 4) & 7]]; - if (ega->blink & 16) - fg = bg; - } - } - - dat = ega->vram[charaddr + (ega->sc << 2)]; - if (ega->seqregs[1] & 1) { - for (xx = 0; xx < 8; xx++) - p[xx] = (dat & (0x80 >> xx)) ? fg : bg; - } else { - for (xx = 0; xx < 8; xx++) - p[xx] = (dat & (0x80 >> xx)) ? fg : bg; - if ((chr & ~0x1F) != 0xC0 || !(ega->attrregs[0x10] & 4)) - p[8] = bg; - else - p[8] = (dat & 1) ? fg : bg; - } - ega->ma += 4; - p += xinc; - } - ega->ma &= ega->vrammask; - } -} - - -void -ega_render_2bpp_lowres(ega_t *ega) -{ - int x; - uint8_t dat[2]; - uint32_t addr, *p; - - if ((ega->displine + ega->y_add) < 0) - return; - - p = &buffer32->line[ega->displine + ega->y_add][ega->x_add]; + return; if (ega->firstline_draw == 2000) - ega->firstline_draw = ega->displine; + ega->firstline_draw = ega->displine; ega->lastline_draw = ega->displine; - for (x = 0; x <= (ega->hdisp + ega->scrollcache); x += 16) { - addr = ega->ma; + if (ega->fullchange) { + const bool doublewidth = ((ega->seqregs[1] & 8) != 0); + const bool attrblink = ((ega->attrregs[0x10] & 8) != 0); + const bool attrlinechars = (ega->attrregs[0x10] & 4); + const bool crtcreset = ((ega->crtc[0x17] & 0x80) == 0); + const bool seq9dot = ((ega->seqregs[1] & 1) == 0); + const int dwshift = doublewidth ? 1 : 0; + const int dotwidth = 1 << dwshift; + const int charwidth = dotwidth * (seq9dot ? 9 : 8); + const bool blinked = ega->blink & 0x10; + uint32_t *p = &buffer32->line[ega->displine + ega->y_add][ega->x_add]; - if (!(ega->crtc[0x17] & 0x40)) { - addr = (addr << 1) & ega->vrammask; - addr &= ~7; + for (int x = 0; x < (ega->hdisp + ega->scrollcache); x += charwidth) { + uint32_t addr = ega->remap_func(ega, ega->ma) & ega->vrammask; - if ((ega->crtc[0x17] & 0x20) && (ega->ma & 0x20000)) - addr |= 4; + int drawcursor = ((ega->ma == ega->ca) && ega->con && ega->cursoron); - if (!(ega->crtc[0x17] & 0x20) && (ega->ma & 0x8000)) - addr |= 4; - } + uint32_t chr; + uint32_t attr; + if (!crtcreset) { + chr = ega->vram[addr]; + attr = ega->vram[addr + 1]; + } else + chr = attr = 0; - if (!(ega->crtc[0x17] & 0x01)) - addr = (addr & ~0x8000) | ((ega->sc & 1) ? 0x8000 : 0); + uint32_t charaddr; + if (attr & 8) + charaddr = ega->charsetb + (chr * 0x80); + else + charaddr = ega->charseta + (chr * 0x80); - if (!(ega->crtc[0x17] & 0x02)) - addr = (addr & ~0x10000) | ((ega->sc & 2) ? 0x10000 : 0); + int fg; + int bg; + if (drawcursor) { + bg = ega->pallook[ega->egapal[attr & 0x0f]]; + fg = ega->pallook[ega->egapal[attr >> 4]]; + } else { + fg = ega->pallook[ega->egapal[attr & 0x0f]]; + bg = ega->pallook[ega->egapal[attr >> 4]]; - dat[0] = ega->vram[addr]; - dat[1] = ega->vram[addr | 0x1]; - if (ega->seqregs[1] & 4) - ega->ma += 2; - else - ega->ma += 4; + if ((attr & 0x80) && attrblink) { + bg = ega->pallook[ega->egapal[(attr >> 4) & 7]]; + if (blinked) + fg = bg; + } + } - ega->ma &= ega->vrammask; + uint32_t dat = ega->vram[charaddr + (ega->sc << 2)]; + dat <<= 1; + if ((chr & ~0x1F) == 0xC0 && attrlinechars) + dat |= (dat >> 1) & 1; - if (ega->crtc[0x17] & 0x80) { - p[0] = p[1] = ega->pallook[ega->egapal[(dat[0] >> 6) & 3]]; - p[2] = p[3] = ega->pallook[ega->egapal[(dat[0] >> 4) & 3]]; - p[4] = p[5] = ega->pallook[ega->egapal[(dat[0] >> 2) & 3]]; - p[6] = p[7] = ega->pallook[ega->egapal[dat[0] & 3]]; - p[8] = p[9] = ega->pallook[ega->egapal[(dat[1] >> 6) & 3]]; - p[10] = p[11] = ega->pallook[ega->egapal[(dat[1] >> 4) & 3]]; - p[12] = p[13] = ega->pallook[ega->egapal[(dat[1] >> 2) & 3]]; - p[14] = p[15] = ega->pallook[ega->egapal[dat[1] & 3]]; - } else - memset(p, 0x00, 16 * sizeof(uint32_t)); + for (int xx = 0; xx < charwidth; xx++) + p[xx] = (dat & (0x100 >> (xx >> dwshift))) ? fg : bg; - p += 16; + ega->ma += 4; + p += charwidth; + } + ega->ma &= 0x3ffff; } } - void -ega_render_2bpp_highres(ega_t *ega) +ega_render_graphics(ega_t *ega) { - int x; - uint8_t dat[2]; - uint32_t addr, *p; - if ((ega->displine + ega->y_add) < 0) - return; - - p = &buffer32->line[ega->displine + ega->y_add][ega->x_add]; + return; if (ega->firstline_draw == 2000) - ega->firstline_draw = ega->displine; + ega->firstline_draw = ega->displine; ega->lastline_draw = ega->displine; - for (x = 0; x <= (ega->hdisp + ega->scrollcache); x += 8) { - addr = ega->ma; + const bool doublewidth = ((ega->seqregs[1] & 8) != 0); + const bool cga2bpp = ((ega->gdcreg[5] & 0x20) != 0); + const bool attrblink = ((ega->attrregs[0x10] & 8) != 0); + const bool blinked = ega->blink & 0x10; + const bool crtcreset = ((ega->crtc[0x17] & 0x80) == 0); + const bool seqoddeven = ((ega->seqregs[1] & 4) != 0); + const uint8_t blinkmask = (attrblink && blinked ? 0x8 : 0x0); + uint32_t *p = &buffer32->line[ega->displine + ega->y_add][ega->x_add]; + const int dwshift = doublewidth ? 1 : 0; + const int dotwidth = 1 << dwshift; + const int charwidth = dotwidth * 8; + int secondcclk = 0; + for (int x = 0; x <= (ega->hdisp + ega->scrollcache); x += charwidth) { + uint32_t addr = ega->remap_func(ega, ega->ma) & ega->vrammask; - if (!(ega->crtc[0x17] & 0x40)) { - addr = (addr << 1) & ega->vrammask; - addr &= ~7; + uint8_t edat[4]; + if (seqoddeven) { + // FIXME: Verify the behaviour of planes 1,3 on actual hardware + edat[0] = ega->vram[(addr | 0) ^ secondcclk]; + edat[1] = ega->vram[(addr | 1) ^ secondcclk]; + edat[2] = ega->vram[(addr | 2) ^ secondcclk]; + edat[3] = ega->vram[(addr | 3) ^ secondcclk]; + secondcclk = (secondcclk + 1) & 1; + if (secondcclk == 0) + ega->ma += 4; + } else { + *(uint32_t *) (&edat[0]) = *(uint32_t *) (&ega->vram[addr]); + ega->ma += 4; + } + ega->ma &= 0x3ffff; - if ((ega->crtc[0x17] & 0x20) && (ega->ma & 0x20000)) - addr |= 4; + if (cga2bpp) { + // Remap CGA 2bpp-chunky data into fully planar data + uint8_t dat0 = egaremap2bpp[edat[1]] | (egaremap2bpp[edat[0]] << 4); + uint8_t dat1 = egaremap2bpp[edat[1] >> 1] | (egaremap2bpp[edat[0] >> 1] << 4); + uint8_t dat2 = egaremap2bpp[edat[3]] | (egaremap2bpp[edat[2]] << 4); + uint8_t dat3 = egaremap2bpp[edat[3] >> 1] | (egaremap2bpp[edat[2] >> 1] << 4); + edat[0] = dat0; + edat[1] = dat1; + edat[2] = dat2; + edat[3] = dat3; + } - if (!(ega->crtc[0x17] & 0x20) && (ega->ma & 0x8000)) - addr |= 4; - } + if (!crtcreset) { + for (int i = 0; i < 8; i += 2) { + const int outoffs = i << dwshift; + const int inshift = 6 - i; + uint8_t dat = (edatlookup[(edat[0] >> inshift) & 3][(edat[1] >> inshift) & 3]) + | (edatlookup[(edat[2] >> inshift) & 3][(edat[3] >> inshift) & 3] << 2); + // FIXME: Confirm blink behaviour is actually XOR on real hardware + uint32_t p0 = ega->pallook[ega->egapal[((dat >> 4) & ega->plane_mask) ^ blinkmask]]; + uint32_t p1 = ega->pallook[ega->egapal[(dat & ega->plane_mask) ^ blinkmask]]; + for (int subx = 0; subx < dotwidth; subx++) + p[outoffs + subx] = p0; + for (int subx = 0; subx < dotwidth; subx++) + p[outoffs + subx + dotwidth] = p1; + } + } else + memset(p, 0x00, charwidth * sizeof(uint32_t)); - if (!(ega->crtc[0x17] & 0x01)) - addr = (addr & ~0x8000) | ((ega->sc & 1) ? 0x8000 : 0); - - if (!(ega->crtc[0x17] & 0x02)) - addr = (addr & ~0x10000) | ((ega->sc & 2) ? 0x10000 : 0); - - dat[0] = ega->vram[addr]; - dat[1] = ega->vram[addr | 0x1]; - if (ega->seqregs[1] & 4) - ega->ma += 2; - else - ega->ma += 4; - - ega->ma &= ega->vrammask; - - if (ega->crtc[0x17] & 0x80) { - p[0] = ega->pallook[ega->egapal[(dat[0] >> 6) & 3]]; - p[1] = ega->pallook[ega->egapal[(dat[0] >> 4) & 3]]; - p[2] = ega->pallook[ega->egapal[(dat[0] >> 2) & 3]]; - p[3] = ega->pallook[ega->egapal[dat[0] & 3]]; - p[4] = ega->pallook[ega->egapal[(dat[1] >> 6) & 3]]; - p[5] = ega->pallook[ega->egapal[(dat[1] >> 4) & 3]]; - p[6] = ega->pallook[ega->egapal[(dat[1] >> 2) & 3]]; - p[7] = ega->pallook[ega->egapal[dat[1] & 3]]; - } else - memset(p, 0x00, 8 * sizeof(uint32_t)); - - p += 8; - } -} - - -void -ega_render_4bpp_lowres(ega_t *ega) -{ - int x, oddeven; - uint8_t dat, edat[4]; - uint32_t addr, *p; - - if ((ega->displine + ega->y_add) < 0) - return; - - p = &buffer32->line[ega->displine + ega->y_add][ega->x_add]; - - if (ega->firstline_draw == 2000) - ega->firstline_draw = ega->displine; - ega->lastline_draw = ega->displine; - - for (x = 0; x <= (ega->hdisp + ega->scrollcache); x += 16) { - addr = ega->ma; - oddeven = 0; - - if (!(ega->crtc[0x17] & 0x40)) { - addr = (addr << 1) & ega->vrammask; - - if (ega->seqregs[1] & 4) - oddeven = (addr & 4) ? 1 : 0; - - addr &= ~7; - - if ((ega->crtc[0x17] & 0x20) && (ega->ma & 0x20000)) - addr |= 4; - if (!(ega->crtc[0x17] & 0x20) && (ega->ma & 0x8000)) - addr |= 4; - } - - if (!(ega->crtc[0x17] & 0x01)) - addr = (addr & ~0x8000) | ((ega->sc & 1) ? 0x8000 : 0); - - if (!(ega->crtc[0x17] & 0x02)) - addr = (addr & ~0x10000) | ((ega->sc & 2) ? 0x10000 : 0); - - if (ega->seqregs[1] & 4) { - edat[0] = ega->vram[addr | oddeven]; - edat[2] = ega->vram[addr | oddeven | 0x2]; - edat[1] = edat[3] = 0; - ega->ma += 2; - } else { - edat[0] = ega->vram[addr]; - edat[1] = ega->vram[addr | 0x1]; - edat[2] = ega->vram[addr | 0x2]; - edat[3] = ega->vram[addr | 0x3]; - ega->ma += 4; - } - - ega->ma &= ega->vrammask; - - if (ega->crtc[0x17] & 0x80) { - dat = edatlookup[edat[0] >> 6][edat[1] >> 6] | (edatlookup[edat[2] >> 6][edat[3] >> 6] << 2); - p[0] = p[1] = ega->pallook[ega->egapal[(dat >> 4) & ega->plane_mask]]; - p[2] = p[3] = ega->pallook[ega->egapal[dat & ega->plane_mask]]; - dat = edatlookup[(edat[0] >> 4) & 3][(edat[1] >> 4) & 3] | (edatlookup[(edat[2] >> 4) & 3][(edat[3] >> 4) & 3] << 2); - p[4] = p[5] = ega->pallook[ega->egapal[(dat >> 4) & ega->plane_mask]]; - p[6] = p[7] = ega->pallook[ega->egapal[dat & ega->plane_mask]]; - dat = edatlookup[(edat[0] >> 2) & 3][(edat[1] >> 2) & 3] | (edatlookup[(edat[2] >> 2) & 3][(edat[3] >> 2) & 3] << 2); - p[8] = p[9] = ega->pallook[ega->egapal[(dat >> 4) & ega->plane_mask]]; - p[10] = p[11] = ega->pallook[ega->egapal[dat & ega->plane_mask]]; - dat = edatlookup[edat[0] & 3][edat[1] & 3] | (edatlookup[edat[2] & 3][edat[3] & 3] << 2); - p[12] = p[13] = ega->pallook[ega->egapal[(dat >> 4) & ega->plane_mask]]; - p[14] = p[15] = ega->pallook[ega->egapal[dat & ega->plane_mask]]; - } else - memset(p, 0x00, 16 * sizeof(uint32_t)); - - p += 16; - } -} - - -void -ega_render_4bpp_highres(ega_t *ega) -{ - int x, oddeven; - uint8_t dat, edat[4]; - uint32_t addr, *p; - - if ((ega->displine + ega->y_add) < 0) - return; - - p = &buffer32->line[ega->displine + ega->y_add][ega->x_add]; - - if (ega->firstline_draw == 2000) - ega->firstline_draw = ega->displine; - ega->lastline_draw = ega->displine; - - for (x = 0; x <= (ega->hdisp + ega->scrollcache); x += 8) { - addr = ega->ma; - oddeven = 0; - - if (!(ega->crtc[0x17] & 0x40)) { - addr = (addr << 1) & ega->vrammask; - - if (ega->seqregs[1] & 4) - oddeven = (addr & 4) ? 1 : 0; - - addr &= ~7; - - if ((ega->crtc[0x17] & 0x20) && (ega->ma & 0x20000)) - addr |= 4; - if (!(ega->crtc[0x17] & 0x20) && (ega->ma & 0x8000)) - addr |= 4; - } - - if (!(ega->crtc[0x17] & 0x01)) - addr = (addr & ~0x8000) | ((ega->sc & 1) ? 0x8000 : 0); - if (!(ega->crtc[0x17] & 0x02)) - addr = (addr & ~0x10000) | ((ega->sc & 2) ? 0x10000 : 0); - - if (ega->seqregs[1] & 4) { - edat[0] = ega->vram[addr | oddeven]; - edat[2] = ega->vram[addr | oddeven | 0x2]; - edat[1] = edat[3] = 0; - ega->ma += 2; - } else { - *(uint32_t *)(&edat[0]) = *(uint32_t *)(&ega->vram[addr]); - ega->ma += 4; - } - ega->ma &= ega->vrammask; - - if (ega->crtc[0x17] & 0x80) { - dat = edatlookup[edat[0] >> 6][edat[1] >> 6] | (edatlookup[edat[2] >> 6][edat[3] >> 6] << 2); - p[0] = ega->pallook[ega->egapal[(dat >> 4) & ega->plane_mask]]; - p[1] = ega->pallook[ega->egapal[dat & ega->plane_mask]]; - dat = edatlookup[(edat[0] >> 4) & 3][(edat[1] >> 4) & 3] | (edatlookup[(edat[2] >> 4) & 3][(edat[3] >> 4) & 3] << 2); - p[2] = ega->pallook[ega->egapal[(dat >> 4) & ega->plane_mask]]; - p[3] = ega->pallook[ega->egapal[dat & ega->plane_mask]]; - dat = edatlookup[(edat[0] >> 2) & 3][(edat[1] >> 2) & 3] | (edatlookup[(edat[2] >> 2) & 3][(edat[3] >> 2) & 3] << 2); - p[4] = ega->pallook[ega->egapal[(dat >> 4) & ega->plane_mask]]; - p[5] = ega->pallook[ega->egapal[dat & ega->plane_mask]]; - dat = edatlookup[edat[0] & 3][edat[1] & 3] | (edatlookup[edat[2] & 3][edat[3] & 3] << 2); - p[6] = ega->pallook[ega->egapal[(dat >> 4) & ega->plane_mask]]; - p[7] = ega->pallook[ega->egapal[dat & ega->plane_mask]]; - } else - memset(p, 0x00, 8 * sizeof(uint32_t)); - - p += 8; + p += charwidth; } } diff --git a/src/video/vid_et3000.c b/src/video/vid_et3000.c new file mode 100644 index 000000000..4f7dbae3e --- /dev/null +++ b/src/video/vid_et3000.c @@ -0,0 +1,320 @@ +/* + * 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 Tseng Labs ET3000. + * + * + * + * Authors: Miran Grca, + * + * Copyright 2016-2018 Miran Grca. + */ +#include +#include +#include +#include +#include +#include <86box/86box.h> +#include <86box/io.h> +#include <86box/mca.h> +#include <86box/mem.h> +#include <86box/rom.h> +#include <86box/device.h> +#include <86box/timer.h> +#include <86box/video.h> +#include <86box/vid_svga.h> +#include <86box/vid_svga_render.h> + +#define BIOS_ROM_PATH "roms/video/et3000/Tseng ET3000AX ISA VGA-VGA ULTRA.bin" + +typedef struct { + const char *name; + int type; + + svga_t svga; + + rom_t bios_rom; + + uint8_t banking; +} et3000_t; + +static video_timings_t timing_et3000_isa = { VIDEO_ISA, 3, 3, 6, 5, 5, 10 }; + +static uint8_t et3000_in(uint16_t addr, void *priv); +static void et3000_out(uint16_t addr, uint8_t val, void *priv); + +static uint8_t +et3000_in(uint16_t addr, void *priv) +{ + et3000_t *dev = (et3000_t *) priv; + svga_t *svga = &dev->svga; + + if (((addr & 0xfff0) == 0x3d0 || (addr & 0xfff0) == 0x3b0) && !(svga->miscout & 1)) + addr ^= 0x60; + + switch (addr) { + case 0x3cd: /*Banking*/ + return dev->banking; + + case 0x3d4: + return svga->crtcreg; + + case 0x3d5: + return svga->crtc[svga->crtcreg]; + + default: + break; + } + + return svga_in(addr, svga); +} + +static void +et3000_out(uint16_t addr, uint8_t val, void *priv) +{ + et3000_t *dev = (et3000_t *) priv; + svga_t *svga = &dev->svga; + uint8_t old; + + if (((addr & 0xfff0) == 0x3d0 || (addr & 0xfff0) == 0x3b0) && !(svga->miscout & 1)) + addr ^= 0x60; + + switch (addr) { + case 0x3c0: + case 0x3c1: + if (svga->attrff && (svga->attraddr == 0x16)) { + svga->attrregs[0x16] = val; + svga->chain4 &= ~0x10; + if (svga->gdcreg[5] & 0x40) + svga->chain4 |= (svga->attrregs[0x16] & 0x10); + svga_recalctimings(svga); + } + break; + + case 0x3c5: + if (svga->seqaddr == 4) { + svga->seqregs[4] = val; + + svga->chain2_write = !(val & 4); + svga->chain4 = (svga->chain4 & ~8) | (val & 8); + svga->fast = (svga->gdcreg[8] == 0xff && !(svga->gdcreg[3] & 0x18) && !svga->gdcreg[1]) && svga->chain4 && !(svga->adv_flags & FLAG_ADDR_BY8); + return; + } + break; + + case 0x3cf: + if ((svga->gdcaddr & 15) == 5) { + svga->chain4 &= ~0x10; + if (val & 0x40) + svga->chain4 |= (svga->attrregs[0x16] & 0x10); + } + break; + + case 0x3cd: /*Banking*/ + dev->banking = val; + if (!(svga->crtc[0x23] & 0x80) && !(svga->gdcreg[6] & 0x08)) { + switch ((val >> 6) & 3) { + case 0: /*128K segments*/ + svga->write_bank = (val & 7) << 17; + svga->read_bank = ((val >> 3) & 7) << 17; + break; + case 1: /*64K segments*/ + svga->write_bank = (val & 7) << 16; + svga->read_bank = ((val >> 3) & 7) << 16; + break; + + default: + break; + } + } + return; + + 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 < 0x0e || svga->crtcreg > 0x10) { + svga->fullchange = changeframecount; + svga_recalctimings(svga); + } + } + break; + + default: + break; + } + + svga_out(addr, val, svga); +} + +static void +et3000_recalctimings(svga_t *svga) +{ + svga->ma_latch |= (svga->crtc[0x23] & 2) << 15; + if (svga->crtc[0x25] & 1) + svga->vblankstart |= 0x400; + if (svga->crtc[0x25] & 2) + svga->vtotal |= 0x400; + if (svga->crtc[0x25] & 4) + svga->dispend |= 0x400; + if (svga->crtc[0x25] & 8) + svga->vsyncstart |= 0x400; + if (svga->crtc[0x25] & 0x10) + svga->split |= 0x400; + + svga->interlace = !!(svga->crtc[0x25] & 0x80); + + if (svga->attrregs[0x16] & 0x10) { + svga->ma_latch <<= (1 << 0); + svga->rowoffset <<= (1 << 0); + switch (svga->gdcreg[5] & 0x60) { + case 0x00: + svga->render = svga_render_4bpp_highres; + svga->hdisp *= 2; + break; + case 0x20: + svga->render = svga_render_2bpp_highres; + break; + case 0x40: + case 0x60: + svga->render = svga_render_8bpp_highres; + break; + + default: + break; + } + } + +#if 0 + pclog("HDISP = %i, HTOTAL = %i, ROWOFFSET = %i, INTERLACE = %i\n", + svga->hdisp, svga->htotal, svga->rowoffset, svga->interlace); +#endif + + switch (((svga->miscout >> 2) & 3) | ((svga->crtc[0x24] << 1) & 4)) { + case 0: + case 1: + break; + case 3: + svga->clock = (cpuclock * (double) (1ULL << 32)) / 40000000.0; + break; + case 5: + svga->clock = (cpuclock * (double) (1ULL << 32)) / 65000000.0; + break; + default: + svga->clock = (cpuclock * (double) (1ULL << 32)) / 36000000.0; + break; + } +} + +static void * +et3000_init(const device_t *info) +{ + const char *fn; + et3000_t *dev; + + dev = (et3000_t *) malloc(sizeof(et3000_t)); + memset(dev, 0x00, sizeof(et3000_t)); + dev->name = info->name; + dev->type = info->local; + fn = BIOS_ROM_PATH; + + switch (dev->type) { + case 0: /* ISA ET3000AX */ + video_inform(VIDEO_FLAG_TYPE_SPECIAL, &timing_et3000_isa); + svga_init(info, &dev->svga, dev, device_get_config_int("memory") << 10, + et3000_recalctimings, et3000_in, et3000_out, + NULL, NULL); + io_sethandler(0x03c0, 32, + et3000_in, NULL, NULL, et3000_out, NULL, NULL, dev); + break; + + default: + break; + } + + rom_init(&dev->bios_rom, fn, + 0xc0000, 0x8000, 0x7fff, 0, MEM_MAPPING_EXTERNAL); + + dev->svga.bpp = 8; + dev->svga.miscout = 1; + + dev->svga.packed_chain4 = 1; + + return dev; +} + +static void +et3000_close(void *priv) +{ + et3000_t *dev = (et3000_t *) priv; + + svga_close(&dev->svga); + + free(dev); +} + +static void +et3000_speed_changed(void *priv) +{ + et3000_t *dev = (et3000_t *) priv; + + svga_recalctimings(&dev->svga); +} + +static void +et3000_force_redraw(void *priv) +{ + et3000_t *dev = (et3000_t *) priv; + + dev->svga.fullchange = changeframecount; +} + +static int +et3000_available(void) +{ + return rom_present(BIOS_ROM_PATH); +} + +static const device_config_t et3000_config[] = { + { .name = "memory", + .description = "Memory size", + .type = CONFIG_SELECTION, + .default_int = 512, + .selection = { + { .description = "256 KB", + .value = 256 }, + { .description = "512 KB", + .value = 512 }, + { .description = "1 MB", + .value = 1024 }, + { .description = "" } } }, + { .type = CONFIG_END } +}; + +const device_t et3000_isa_device = { + .name = "Tseng Labs ET3000AX (ISA)", + .internal_name = "et3000ax", + .flags = DEVICE_ISA, + .local = 0, + .init = et3000_init, + .close = et3000_close, + .reset = NULL, + { .available = et3000_available }, + .speed_changed = et3000_speed_changed, + .force_redraw = et3000_force_redraw, + .config = et3000_config +}; diff --git a/src/video/vid_et4000.c b/src/video/vid_et4000.c index 529cca4bf..80da770a3 100644 --- a/src/video/vid_et4000.c +++ b/src/video/vid_et4000.c @@ -1,23 +1,23 @@ /* - * 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. + * 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. + * This file is part of the 86Box distribution. * - * Emulation of the Tseng Labs ET4000. + * Emulation of the Tseng Labs ET4000. * * * - * Authors: Fred N. van Kempen, - * Miran Grca, - * GreatPsycho, - * Sarah Walker, + * Authors: Fred N. van Kempen, + * Miran Grca, + * GreatPsycho, + * Sarah Walker, * - * Copyright 2017,2018 Fred N. van Kempen. - * Copyright 2016-2018 Miran Grca. - * Copyright 2008-2018 Sarah Walker. + * Copyright 2017-2018 Fred N. van Kempen. + * Copyright 2016-2018 Miran Grca. + * Copyright 2008-2018 Sarah Walker. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -52,41 +52,47 @@ #include <86box/video.h> #include <86box/vid_svga.h> #include <86box/vid_svga_render.h> +#include <86box/plat_fallthrough.h> +#include <86box/plat_unused.h> +#define ET4000_TYPE_ISA 1 /* ISA ET4000AX */ +#define ET4000_TYPE_MCA 2 /* MCA ET4000AX */ +#define ET4000_TYPE_KOREAN 3 /* Korean ET4000 */ +#define ET4000_TYPE_TRIGEM 4 /* Trigem 286M ET4000 */ +#define ET4000_TYPE_KASAN 5 /* Kasan ET4000 */ -#define BIOS_ROM_PATH "roms/video/et4000/ET4000.BIN" -#define KOREAN_BIOS_ROM_PATH "roms/video/et4000/tgkorvga.bin" -#define KOREAN_FONT_ROM_PATH "roms/video/et4000/tg_ksc5601.rom" -#define KASAN_BIOS_ROM_PATH "roms/video/et4000/et4000_kasan16.bin" -#define KASAN_FONT_ROM_PATH "roms/video/et4000/kasan_ksc5601.rom" +#define BIOS_ROM_PATH "roms/video/et4000/ET4000.BIN" +#define KOREAN_BIOS_ROM_PATH "roms/video/et4000/tgkorvga.bin" +#define KOREAN_FONT_ROM_PATH "roms/video/et4000/tg_ksc5601.rom" +#define KASAN_BIOS_ROM_PATH "roms/video/et4000/et4000_kasan16.bin" +#define KASAN_FONT_ROM_PATH "roms/video/et4000/kasan_ksc5601.rom" typedef struct { - const char *name; - int type; + const char *name; + int type; - svga_t svga; + svga_t svga; - uint8_t pos_regs[8]; + uint8_t pos_regs[8]; - rom_t bios_rom; + rom_t bios_rom; - uint8_t banking; - uint32_t vram_size, - vram_mask; + uint8_t banking; + uint32_t vram_size, + vram_mask; - uint8_t port_22cb_val; - uint8_t port_32cb_val; - int get_korean_font_enabled; - int get_korean_font_index; - uint16_t get_korean_font_base; - - uint8_t kasan_cfg_index; - uint8_t kasan_cfg_regs[16]; - uint16_t kasan_access_addr; - uint8_t kasan_font_data[4]; + uint8_t port_22cb_val; + uint8_t port_32cb_val; + int get_korean_font_enabled; + int get_korean_font_index; + uint16_t get_korean_font_base; + + uint8_t kasan_cfg_index; + uint8_t kasan_cfg_regs[16]; + uint16_t kasan_access_addr; + uint8_t kasan_font_data[4]; } et4000_t; - static const uint8_t crtc_mask[0x40] = { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, @@ -98,792 +104,808 @@ static const uint8_t crtc_mask[0x40] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }; -static video_timings_t timing_et4000_isa = {VIDEO_ISA, 3, 3, 6, 5, 5, 10}; -static video_timings_t timing_et4000_mca = {VIDEO_MCA, 4, 5, 10, 5, 5, 10}; +static video_timings_t timing_et4000_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_et4000_mca = { .type = VIDEO_MCA, .write_b = 4, .write_w = 5, .write_l = 10, .read_b = 5, .read_w = 5, .read_l = 10 }; -static void et4000_kasan_out(uint16_t addr, uint8_t val, void *p); -static uint8_t et4000_kasan_in(uint16_t addr, void *p); +static void et4000_kasan_out(uint16_t addr, uint8_t val, void *priv); +static uint8_t et4000_kasan_in(uint16_t addr, void *priv); static uint8_t et4000_in(uint16_t addr, void *priv) { - et4000_t *dev = (et4000_t *)priv; - svga_t *svga = &dev->svga; + et4000_t *dev = (et4000_t *) priv; + svga_t *svga = &dev->svga; - if (((addr & 0xfff0) == 0x3d0 || - (addr & 0xfff0) == 0x3b0) && !(svga->miscout & 1)) addr ^= 0x60; + if (((addr & 0xfff0) == 0x3d0 || (addr & 0xfff0) == 0x3b0) && !(svga->miscout & 1)) + addr ^= 0x60; switch (addr) { - case 0x3c2: - if (dev->type == 1) { - if ((svga->vgapal[0].r + svga->vgapal[0].g + svga->vgapal[0].b) >= 0x4e) - return 0; - else - return 0x10; - } - break; + case 0x3c2: + if (dev->type == ET4000_TYPE_MCA) { + if ((svga->vgapal[0].r + svga->vgapal[0].g + svga->vgapal[0].b) >= 0x4e) + return 0; + else + return 0x10; + } + break; - case 0x3c5: - if ((svga->seqaddr & 0xf) == 7) - return svga->seqregs[svga->seqaddr & 0xf] | 4; - break; + case 0x3c5: + if ((svga->seqaddr & 0xf) == 7) + return svga->seqregs[svga->seqaddr & 0xf] | 4; + break; - case 0x3c6: - case 0x3c7: - case 0x3c8: - case 0x3c9: - return sc1502x_ramdac_in(addr, svga->ramdac, svga); + case 0x3c6: + case 0x3c7: + case 0x3c8: + case 0x3c9: + return sc1502x_ramdac_in(addr, svga->ramdac, svga); - case 0x3cd: /*Banking*/ - return dev->banking; + case 0x3cd: /*Banking*/ + return dev->banking; - case 0x3d4: - return svga->crtcreg; + case 0x3d4: + return svga->crtcreg; - case 0x3d5: - return svga->crtc[svga->crtcreg]; + case 0x3d5: + return svga->crtc[svga->crtcreg]; + + default: + break; } return svga_in(addr, svga); } - static uint8_t et4000k_in(uint16_t addr, void *priv) { - et4000_t *dev = (et4000_t *)priv; - uint8_t val = 0xff; - + et4000_t *dev = (et4000_t *) priv; + uint8_t val = 0xff; + switch (addr) { - case 0x22cb: - return dev->port_22cb_val; + case 0x22cb: + return dev->port_22cb_val; - case 0x22cf: - val = 0; - switch(dev->get_korean_font_enabled) { - case 3: - if ((dev->port_32cb_val & 0x30) == 0x30) { - val = fontdatksc5601[dev->get_korean_font_base].chr[dev->get_korean_font_index++]; - dev->get_korean_font_index &= 0x1f; - } else - if ((dev->port_32cb_val & 0x30) == 0x20 && - (dev->get_korean_font_base & 0x7f) > 0x20 && - (dev->get_korean_font_base & 0x7f) < 0x7f) { - switch(dev->get_korean_font_base & 0x3f80) { - case 0x2480: - if (dev->get_korean_font_index < 16) - val = fontdatksc5601_user[(dev->get_korean_font_base & 0x7f) - 0x20].chr[dev->get_korean_font_index]; - else - if (dev->get_korean_font_index >= 24 && dev->get_korean_font_index < 40) - val = fontdatksc5601_user[(dev->get_korean_font_base & 0x7f) - 0x20].chr[dev->get_korean_font_index - 8]; - break; + case 0x22cf: + val = 0; + switch (dev->get_korean_font_enabled) { + case 3: + if ((dev->port_32cb_val & 0x30) == 0x30) { + val = fontdatksc5601[dev->get_korean_font_base].chr[dev->get_korean_font_index++]; + dev->get_korean_font_index &= 0x1f; + } else if ((dev->port_32cb_val & 0x30) == 0x20 && (dev->get_korean_font_base & 0x7f) > 0x20 && (dev->get_korean_font_base & 0x7f) < 0x7f) { + switch (dev->get_korean_font_base & 0x3f80) { + case 0x2480: + if (dev->get_korean_font_index < 16) + val = fontdatksc5601_user[(dev->get_korean_font_base & 0x7f) - 0x20].chr[dev->get_korean_font_index]; + else if (dev->get_korean_font_index >= 24 && dev->get_korean_font_index < 40) + val = fontdatksc5601_user[(dev->get_korean_font_base & 0x7f) - 0x20].chr[dev->get_korean_font_index - 8]; + break; - case 0x3f00: - if (dev->get_korean_font_index < 16) - val = fontdatksc5601_user[96 + (dev->get_korean_font_base & 0x7f) - 0x20].chr[dev->get_korean_font_index]; - else - if (dev->get_korean_font_index >= 24 && dev->get_korean_font_index < 40) - val = fontdatksc5601_user[96 + (dev->get_korean_font_base & 0x7f) - 0x20].chr[dev->get_korean_font_index - 8]; - break; + case 0x3f00: + if (dev->get_korean_font_index < 16) + val = fontdatksc5601_user[96 + (dev->get_korean_font_base & 0x7f) - 0x20].chr[dev->get_korean_font_index]; + else if (dev->get_korean_font_index >= 24 && dev->get_korean_font_index < 40) + val = fontdatksc5601_user[96 + (dev->get_korean_font_base & 0x7f) - 0x20].chr[dev->get_korean_font_index - 8]; + break; - default: - break; - } - dev->get_korean_font_index++; - dev->get_korean_font_index %= 72; - } - break; + default: + break; + } + dev->get_korean_font_index++; + dev->get_korean_font_index %= 72; + } + break; - case 4: - val = 0x0f; - break; + case 4: + val = 0x0f; + break; - default: - break; - } - return val; + default: + break; + } + return val; - case 0x32cb: - return dev->port_32cb_val; + case 0x32cb: + return dev->port_32cb_val; - default: - return et4000_in(addr, priv); + default: + return et4000_in(addr, priv); } } - static void et4000_out(uint16_t addr, uint8_t val, void *priv) { - et4000_t *dev = (et4000_t *)priv; - svga_t *svga = &dev->svga; - uint8_t old; + et4000_t *dev = (et4000_t *) priv; + svga_t *svga = &dev->svga; + uint8_t old; - if (((addr & 0xfff0) == 0x3d0 || - (addr & 0xfff0) == 0x3b0) && !(svga->miscout & 1)) addr ^= 0x60; + if (((addr & 0xfff0) == 0x3d0 || (addr & 0xfff0) == 0x3b0) && !(svga->miscout & 1)) + addr ^= 0x60; switch (addr) { - case 0x3c6: - case 0x3c7: - case 0x3c8: - case 0x3c9: - sc1502x_ramdac_out(addr, val, svga->ramdac, svga); - return; + case 0x3c6: + case 0x3c7: + case 0x3c8: + case 0x3c9: + sc1502x_ramdac_out(addr, val, svga->ramdac, svga); + return; - case 0x3cd: /*Banking*/ - if (!(svga->crtc[0x36] & 0x10) && !(svga->gdcreg[6] & 0x08)) { - svga->write_bank = (val & 0xf) * 0x10000; - svga->read_bank = ((val >> 4) & 0xf) * 0x10000; - } - dev->banking = val; - return; + case 0x3cd: /*Banking*/ + if (!(svga->crtc[0x36] & 0x10) && !(svga->gdcreg[6] & 0x08)) { + svga->write_bank = (val & 0xf) * 0x10000; + svga->read_bank = ((val >> 4) & 0xf) * 0x10000; + } + dev->banking = val; + return; - case 0x3cf: - if ((svga->gdcaddr & 15) == 6) { - if (!(svga->crtc[0x36] & 0x10) && !(val & 0x08)) { - svga->write_bank = (dev->banking & 0x0f) * 0x10000; - svga->read_bank = ((dev->banking >> 4) & 0x0f) * 0x10000; - } else - svga->write_bank = svga->read_bank = 0; - - old = svga->gdcreg[6]; - svga_out(addr, val, svga); - if ((old & 0xc) != 0 && (val & 0xc) == 0) - { - /*override mask - ET4000 supports linear 128k at A0000*/ - svga->banked_mask = 0x1ffff; - } - return; - } - break; + case 0x3cf: + if ((svga->gdcaddr & 15) == 6) { + if (!(svga->crtc[0x36] & 0x10) && !(val & 0x08)) { + svga->write_bank = (dev->banking & 0x0f) * 0x10000; + svga->read_bank = ((dev->banking >> 4) & 0x0f) * 0x10000; + } else + svga->write_bank = svga->read_bank = 0; - case 0x3d4: - svga->crtcreg = val & 0x3f; - return; + old = svga->gdcreg[6]; + svga_out(addr, val, svga); + if ((old & 0xc) != 0 && (val & 0xc) == 0) { + /*override mask - ET4000 supports linear 128k at A0000*/ + svga->banked_mask = 0x1ffff; + } + return; + } + break; - case 0x3d5: - if ((svga->crtcreg < 7) && (svga->crtc[0x11] & 0x80)) - return; - if ((svga->crtcreg == 0x35) && (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]; - val &= crtc_mask[svga->crtcreg]; - svga->crtc[svga->crtcreg] = val; + case 0x3d4: + svga->crtcreg = val & 0x3f; + return; - if (svga->crtcreg == 0x36) { - if (!(val & 0x10) && !(svga->gdcreg[6] & 0x08)) { - svga->write_bank = (dev->banking & 0x0f) * 0x10000; - svga->read_bank = ((dev->banking >> 4) & 0x0f) * 0x10000; - } else - svga->write_bank = svga->read_bank = 0; - } + case 0x3d5: + if ((svga->crtcreg < 7) && (svga->crtc[0x11] & 0x80)) + return; + if ((svga->crtcreg == 0x35) && (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]; + val &= crtc_mask[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; + if (svga->crtcreg == 0x36) { + if (!(val & 0x10) && !(svga->gdcreg[6] & 0x08)) { + svga->write_bank = (dev->banking & 0x0f) * 0x10000; + svga->read_bank = ((dev->banking >> 4) & 0x0f) * 0x10000; + } else + svga->write_bank = svga->read_bank = 0; + } + + 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; + + default: + break; } svga_out(addr, val, svga); } - static void et4000k_out(uint16_t addr, uint8_t val, void *priv) { - et4000_t *dev = (et4000_t *)priv; + et4000_t *dev = (et4000_t *) priv; switch (addr) { - case 0x22cb: - dev->port_22cb_val = (dev->port_22cb_val & 0xf0) | (val & 0x0f); - dev->get_korean_font_enabled = val & 7; - if (dev->get_korean_font_enabled == 3) - dev->get_korean_font_index = 0; - break; + case 0x22cb: + dev->port_22cb_val = (dev->port_22cb_val & 0xf0) | (val & 0x0f); + dev->get_korean_font_enabled = val & 7; + if (dev->get_korean_font_enabled == 3) + dev->get_korean_font_index = 0; + break; - case 0x22cf: - switch(dev->get_korean_font_enabled) { - case 1: - dev->get_korean_font_base = ((val & 0x7f) << 7) | (dev->get_korean_font_base & 0x7f); - break; + case 0x22cf: + switch (dev->get_korean_font_enabled) { + case 1: + dev->get_korean_font_base = ((val & 0x7f) << 7) | (dev->get_korean_font_base & 0x7f); + break; - case 2: - dev->get_korean_font_base = (dev->get_korean_font_base & 0x3f80) | (val & 0x7f) | (((val ^ 0x80) & 0x80) << 8); - break; + case 2: + dev->get_korean_font_base = (dev->get_korean_font_base & 0x3f80) | (val & 0x7f) | (((val ^ 0x80) & 0x80) << 8); + break; - case 3: - if ((dev->port_32cb_val & 0x30) == 0x20 && - (dev->get_korean_font_base & 0x7f) > 0x20 && - (dev->get_korean_font_base & 0x7f) < 0x7f) { - switch (dev->get_korean_font_base & 0x3f80) { - case 0x2480: - if (dev->get_korean_font_index < 16) - fontdatksc5601_user[(dev->get_korean_font_base & 0x7f) - 0x20].chr[dev->get_korean_font_index] = val; - else - if (dev->get_korean_font_index >= 24 && dev->get_korean_font_index < 40) - fontdatksc5601_user[(dev->get_korean_font_base & 0x7f) - 0x20].chr[dev->get_korean_font_index - 8] = val; - break; + case 3: + if ((dev->port_32cb_val & 0x30) == 0x20 && (dev->get_korean_font_base & 0x7f) > 0x20 && (dev->get_korean_font_base & 0x7f) < 0x7f) { + switch (dev->get_korean_font_base & 0x3f80) { + case 0x2480: + if (dev->get_korean_font_index < 16) + fontdatksc5601_user[(dev->get_korean_font_base & 0x7f) - 0x20].chr[dev->get_korean_font_index] = val; + else if (dev->get_korean_font_index >= 24 && dev->get_korean_font_index < 40) + fontdatksc5601_user[(dev->get_korean_font_base & 0x7f) - 0x20].chr[dev->get_korean_font_index - 8] = val; + break; - case 0x3f00: - if (dev->get_korean_font_index < 16) - fontdatksc5601_user[96 + (dev->get_korean_font_base & 0x7f) - 0x20].chr[dev->get_korean_font_index] = val; - else - if (dev->get_korean_font_index >= 24 && dev->get_korean_font_index < 40) - fontdatksc5601_user[96 + (dev->get_korean_font_base & 0x7f) - 0x20].chr[dev->get_korean_font_index - 8] = val; - break; + case 0x3f00: + if (dev->get_korean_font_index < 16) + fontdatksc5601_user[96 + (dev->get_korean_font_base & 0x7f) - 0x20].chr[dev->get_korean_font_index] = val; + else if (dev->get_korean_font_index >= 24 && dev->get_korean_font_index < 40) + fontdatksc5601_user[96 + (dev->get_korean_font_base & 0x7f) - 0x20].chr[dev->get_korean_font_index - 8] = val; + break; - default: - break; - } - dev->get_korean_font_index++; - } - break; + default: + break; + } + dev->get_korean_font_index++; + } + break; - default: - break; - } - break; + default: + break; + } + break; - case 0x32cb: - dev->port_32cb_val = val; - svga_recalctimings(&dev->svga); - break; + case 0x32cb: + dev->port_32cb_val = val; + svga_recalctimings(&dev->svga); + break; - default: - et4000_out(addr, val, priv); - break; + default: + et4000_out(addr, val, priv); + break; } } static uint8_t et4000_kasan_in(uint16_t addr, void *priv) { - et4000_t *et4000 = (et4000_t *)priv; - uint8_t val = 0xFF; + const et4000_t *et4000 = (et4000_t *) priv; + uint8_t val = 0xFF; - if (addr == 0x258) { - val = et4000->kasan_cfg_index; - } else if (addr == 0x259) { - if (et4000->kasan_cfg_index >= 0xF0) { - val = et4000->kasan_cfg_regs[et4000->kasan_cfg_index - 0xF0]; - if (et4000->kasan_cfg_index == 0xF4 && et4000->kasan_cfg_regs[0] & 0x20) - val |= 0x80; - } - } else if (addr >= et4000->kasan_access_addr && addr < et4000->kasan_access_addr + 8) { - switch (addr - ((et4000->kasan_cfg_regs[2] << 8) | (et4000->kasan_cfg_regs[1]))) { - case 2: - val = 0; - break; - case 5: - if (((et4000->get_korean_font_base >> 7) & 0x7F) == (et4000->svga.ksc5601_udc_area_msb[0] & 0x7F) && (et4000->svga.ksc5601_udc_area_msb[0] & 0x80)) - val = fontdatksc5601_user[(et4000->get_korean_font_base & 0x7F) - 0x20].chr[et4000->get_korean_font_index]; - else if (((et4000->get_korean_font_base >> 7) & 0x7F) == (et4000->svga.ksc5601_udc_area_msb[1] & 0x7F) && (et4000->svga.ksc5601_udc_area_msb[1] & 0x80)) - val = fontdatksc5601_user[96 + (et4000->get_korean_font_base & 0x7F) - 0x20].chr[et4000->get_korean_font_index]; - else - val = fontdatksc5601[et4000->get_korean_font_base].chr[et4000->get_korean_font_index]; - break; - default: - break; - } - } else - val = et4000_in(addr, priv); - - return val; + if (addr == 0x258) { + val = et4000->kasan_cfg_index; + } else if (addr == 0x259) { + if (et4000->kasan_cfg_index >= 0xF0) { + val = et4000->kasan_cfg_regs[et4000->kasan_cfg_index - 0xF0]; + if (et4000->kasan_cfg_index == 0xF4 && et4000->kasan_cfg_regs[0] & 0x20) + val |= 0x80; + } + } else if (addr >= et4000->kasan_access_addr && addr < et4000->kasan_access_addr + 8) { + switch (addr - ((et4000->kasan_cfg_regs[2] << 8) | (et4000->kasan_cfg_regs[1]))) { + case 2: + val = 0; + break; + case 5: + if (((et4000->get_korean_font_base >> 7) & 0x7F) == (et4000->svga.ksc5601_udc_area_msb[0] & 0x7F) && (et4000->svga.ksc5601_udc_area_msb[0] & 0x80)) + val = fontdatksc5601_user[(et4000->get_korean_font_base & 0x7F) - 0x20].chr[et4000->get_korean_font_index]; + else if (((et4000->get_korean_font_base >> 7) & 0x7F) == (et4000->svga.ksc5601_udc_area_msb[1] & 0x7F) && (et4000->svga.ksc5601_udc_area_msb[1] & 0x80)) + val = fontdatksc5601_user[96 + (et4000->get_korean_font_base & 0x7F) - 0x20].chr[et4000->get_korean_font_index]; + else + val = fontdatksc5601[et4000->get_korean_font_base].chr[et4000->get_korean_font_index]; + break; + default: + break; + } + } else + val = et4000_in(addr, priv); + + return val; } static void et4000_kasan_out(uint16_t addr, uint8_t val, void *priv) { - et4000_t *et4000 = (et4000_t *)priv; + et4000_t *et4000 = (et4000_t *) priv; - if (addr == 0x258) { - et4000->kasan_cfg_index = val; - } else if (addr == 0x259) { - if (et4000->kasan_cfg_index >= 0xF0) { - switch (et4000->kasan_cfg_index - 0xF0) { - case 0: - if (et4000->kasan_cfg_regs[4] & 8) - val = (val & 0xFC) | (et4000->kasan_cfg_regs[0] & 3); - et4000->kasan_cfg_regs[0] = val; - svga_recalctimings(&et4000->svga); - break; - case 1: - case 2: - et4000->kasan_cfg_regs[et4000->kasan_cfg_index - 0xF0] = val; - io_removehandler(et4000->kasan_access_addr, 0x0008, et4000_kasan_in, NULL, NULL, et4000_kasan_out, NULL, NULL, et4000); - et4000->kasan_access_addr = (et4000->kasan_cfg_regs[2] << 8) | et4000->kasan_cfg_regs[1]; - io_sethandler(et4000->kasan_access_addr, 0x0008, et4000_kasan_in, NULL, NULL, et4000_kasan_out, NULL, NULL, et4000); - break; - case 4: - if (et4000->kasan_cfg_regs[0] & 0x20) - val |= 0x80; - et4000->svga.ksc5601_swap_mode = (val & 4) >> 2; - et4000->kasan_cfg_regs[4] = val; - svga_recalctimings(&et4000->svga); - break; - case 5: - et4000->kasan_cfg_regs[5] = val; - et4000->svga.ksc5601_english_font_type = 0x100 | val; - case 6: - case 7: - et4000->svga.ksc5601_udc_area_msb[et4000->kasan_cfg_index - 0xF6] = val; - default: - et4000->kasan_cfg_regs[et4000->kasan_cfg_index - 0xF0] = val; - svga_recalctimings(&et4000->svga); - break; - } - } - } else if (addr >= et4000->kasan_access_addr && addr < et4000->kasan_access_addr + 8) { - switch (addr - ((et4000->kasan_cfg_regs[2] << 8) | (et4000->kasan_cfg_regs[1]))) { - case 0: - if (et4000->kasan_cfg_regs[0] & 2) { - et4000->get_korean_font_index = ((val & 1) << 4) | ((val & 0x1E) >> 1); - et4000->get_korean_font_base = (et4000->get_korean_font_base & ~7) | (val >> 5); - } - break; - case 1: - if (et4000->kasan_cfg_regs[0] & 2) - et4000->get_korean_font_base = (et4000->get_korean_font_base & ~0x7F8) | (val << 3); - break; - case 2: - if (et4000->kasan_cfg_regs[0] & 2) - et4000->get_korean_font_base = (et4000->get_korean_font_base & ~0x7F800) | ((val & 7) << 11); - break; - case 3: - case 4: - case 5: - if (et4000->kasan_cfg_regs[0] & 1) - et4000->kasan_font_data[addr - (((et4000->kasan_cfg_regs[2] << 8) | (et4000->kasan_cfg_regs[1])) + 3)] = val; - break; - case 6: - if ((et4000->kasan_cfg_regs[0] & 1) && (et4000->kasan_font_data[3] & !(val & 0x80)) && (et4000->get_korean_font_base & 0x7F) >= 0x20 && (et4000->get_korean_font_base & 0x7F) < 0x7F) { - if (((et4000->get_korean_font_base >> 7) & 0x7F) == (et4000->svga.ksc5601_udc_area_msb[0] & 0x7F) && (et4000->svga.ksc5601_udc_area_msb[0] & 0x80)) - fontdatksc5601_user[(et4000->get_korean_font_base & 0x7F) - 0x20].chr[et4000->get_korean_font_index] = et4000->kasan_font_data[2]; - else if (((et4000->get_korean_font_base >> 7) & 0x7F) == (et4000->svga.ksc5601_udc_area_msb[1] & 0x7F) && (et4000->svga.ksc5601_udc_area_msb[1] & 0x80)) - fontdatksc5601_user[96 + (et4000->get_korean_font_base & 0x7F) - 0x20].chr[et4000->get_korean_font_index] = et4000->kasan_font_data[2]; - } - et4000->kasan_font_data[3] = val; - break; - default: - break; - } - } else - et4000_out(addr, val, priv); + if (addr == 0x258) { + et4000->kasan_cfg_index = val; + } else if (addr == 0x259) { + if (et4000->kasan_cfg_index >= 0xF0) { + switch (et4000->kasan_cfg_index - 0xF0) { + case 0: + if (et4000->kasan_cfg_regs[4] & 8) + val = (val & 0xFC) | (et4000->kasan_cfg_regs[0] & 3); + et4000->kasan_cfg_regs[0] = val; + svga_recalctimings(&et4000->svga); + break; + case 1: + case 2: + et4000->kasan_cfg_regs[et4000->kasan_cfg_index - 0xF0] = val; + io_removehandler(et4000->kasan_access_addr, 0x0008, et4000_kasan_in, NULL, NULL, et4000_kasan_out, NULL, NULL, et4000); + et4000->kasan_access_addr = (et4000->kasan_cfg_regs[2] << 8) | et4000->kasan_cfg_regs[1]; + io_sethandler(et4000->kasan_access_addr, 0x0008, et4000_kasan_in, NULL, NULL, et4000_kasan_out, NULL, NULL, et4000); + break; + case 4: + if (et4000->kasan_cfg_regs[0] & 0x20) + val |= 0x80; + et4000->svga.ksc5601_swap_mode = (val & 4) >> 2; + et4000->kasan_cfg_regs[4] = val; + svga_recalctimings(&et4000->svga); + break; + case 5: + et4000->kasan_cfg_regs[5] = val; + et4000->svga.ksc5601_english_font_type = 0x100 | val; + fallthrough; + case 6: + case 7: + et4000->svga.ksc5601_udc_area_msb[et4000->kasan_cfg_index - 0xF6] = val; + default: + et4000->kasan_cfg_regs[et4000->kasan_cfg_index - 0xF0] = val; + svga_recalctimings(&et4000->svga); + break; + } + } + } else if (addr >= et4000->kasan_access_addr && addr < et4000->kasan_access_addr + 8) { + switch (addr - ((et4000->kasan_cfg_regs[2] << 8) | (et4000->kasan_cfg_regs[1]))) { + case 0: + if (et4000->kasan_cfg_regs[0] & 2) { + et4000->get_korean_font_index = ((val & 1) << 4) | ((val & 0x1E) >> 1); + et4000->get_korean_font_base = (et4000->get_korean_font_base & ~7) | (val >> 5); + } + break; + case 1: + if (et4000->kasan_cfg_regs[0] & 2) + et4000->get_korean_font_base = (et4000->get_korean_font_base & ~0x7F8) | (val << 3); + break; + case 2: + if (et4000->kasan_cfg_regs[0] & 2) + et4000->get_korean_font_base = (et4000->get_korean_font_base & ~0x7F800) | ((val & 7) << 11); + break; + case 3: + case 4: + case 5: + if (et4000->kasan_cfg_regs[0] & 1) { + et4000->kasan_font_data[addr - (((et4000->kasan_cfg_regs[2] << 8) | (et4000->kasan_cfg_regs[1])) + 3)] = val; + } + break; + case 6: + if ((et4000->kasan_cfg_regs[0] & 1) && (et4000->kasan_font_data[3] & !(val & 0x80)) && (et4000->get_korean_font_base & 0x7F) >= 0x20 && (et4000->get_korean_font_base & 0x7F) < 0x7F) { + if (((et4000->get_korean_font_base >> 7) & 0x7F) == (et4000->svga.ksc5601_udc_area_msb[0] & 0x7F) && (et4000->svga.ksc5601_udc_area_msb[0] & 0x80)) + fontdatksc5601_user[(et4000->get_korean_font_base & 0x7F) - 0x20].chr[et4000->get_korean_font_index] = et4000->kasan_font_data[2]; + else if (((et4000->get_korean_font_base >> 7) & 0x7F) == (et4000->svga.ksc5601_udc_area_msb[1] & 0x7F) && (et4000->svga.ksc5601_udc_area_msb[1] & 0x80)) + fontdatksc5601_user[96 + (et4000->get_korean_font_base & 0x7F) - 0x20].chr[et4000->get_korean_font_index] = et4000->kasan_font_data[2]; + } + et4000->kasan_font_data[3] = val; + break; + default: + break; + } + } else + et4000_out(addr, val, priv); } uint32_t -get_et4000_addr(uint32_t addr, void *p) +get_et4000_addr(uint32_t addr, void *priv) { - svga_t *svga = (svga_t *)p; - uint32_t nbank; + const svga_t *svga = (svga_t *) priv; + uint32_t nbank; - switch (svga->crtc[0x37] & 0x0B) { - case 0x00: - case 0x01: - nbank = 0; - addr &= 0xFFFF; - break; - case 0x02: - nbank = (addr & 1) << 1; - addr = (addr >> 1) & 0xFFFF; - break; - case 0x03: - nbank = addr & 3; - addr = (addr >> 2) & 0xFFFF; - break; - case 0x08: - case 0x09: - nbank = 0; - addr &= 0x3FFFF; - break; - case 0x0A: - nbank = (addr & 1) << 1; - addr = (addr >> 1) & 0x3FFFF; - break; - case 0x0B: - nbank = addr & 3; - addr = (addr >> 2) & 0x3FFFF; - break; - default: - nbank = 0; - break; - } + switch (svga->crtc[0x37] & 0x0B) { + case 0x00: + case 0x01: + nbank = 0; + addr &= 0xFFFF; + break; + case 0x02: + nbank = (addr & 1) << 1; + addr = (addr >> 1) & 0xFFFF; + break; + case 0x03: + nbank = addr & 3; + addr = (addr >> 2) & 0xFFFF; + break; + case 0x08: + case 0x09: + nbank = 0; + addr &= 0x3FFFF; + break; + case 0x0A: + nbank = (addr & 1) << 1; + addr = (addr >> 1) & 0x3FFFF; + break; + case 0x0B: + nbank = addr & 3; + addr = (addr >> 2) & 0x3FFFF; + break; + default: + nbank = 0; + break; + } - if (svga->vram_max >= 1024 * 1024) { - addr = (addr << 2) | (nbank & 3); - if ((svga->crtc[0x37] & 3) == 2) - addr >>= 1; - else if ((svga->crtc[0x37] & 3) < 2) - addr >>= 2; - } else if (svga->vram_max >= 512 * 1024) { - addr = (addr << 1) | ((nbank & 2) >> 1) | ((nbank & 1) << 19); - if ((svga->crtc[0x37] & 3) < 2) - addr >>= 1; - } else if(svga->vram_max >= 256 * 1024) - addr = addr | (nbank << 18); - else if (svga->vram_max > 128 * 1024) { - addr = (addr << 1) | ((nbank & 2) >> 1) | ((nbank & 1) << 17); - if ((svga->crtc[0x37] & 3) < 2) - addr >>= 1; - } else - addr = addr | (nbank << 16); + if (svga->vram_max >= 1024 * 1024) { + addr = (addr << 2) | (nbank & 3); + if ((svga->crtc[0x37] & 3) == 2) + addr >>= 1; + else if ((svga->crtc[0x37] & 3) < 2) + addr >>= 2; + } else if (svga->vram_max >= 512 * 1024) { + addr = (addr << 1) | ((nbank & 2) >> 1) | ((nbank & 1) << 19); + if ((svga->crtc[0x37] & 3) < 2) + addr >>= 1; + } else if (svga->vram_max >= 256 * 1024) + addr = addr | (nbank << 18); + else if (svga->vram_max > 128 * 1024) { + addr = (addr << 1) | ((nbank & 2) >> 1) | ((nbank & 1) << 17); + if ((svga->crtc[0x37] & 3) < 2) + addr >>= 1; + } else + addr = addr | (nbank << 16); - return addr; + return addr; } static void et4000_recalctimings(svga_t *svga) { - et4000_t *dev = (et4000_t *)svga->p; + const et4000_t *dev = (et4000_t *) svga->priv; - svga->ma_latch |= (svga->crtc[0x33] & 3) << 16; - if (svga->crtc[0x35] & 1) svga->vblankstart += 0x400; - if (svga->crtc[0x35] & 2) svga->vtotal += 0x400; - if (svga->crtc[0x35] & 4) svga->dispend += 0x400; - if (svga->crtc[0x35] & 8) svga->vsyncstart += 0x400; - if (svga->crtc[0x35] & 0x10) svga->split += 0x400; - if (!svga->rowoffset) svga->rowoffset = 0x100; - if (svga->crtc[0x3f] & 1) svga->htotal += 256; - if (svga->attrregs[0x16] & 0x20) svga->hdisp <<= 1; + svga->ma_latch |= (svga->crtc[0x33] & 3) << 16; + if (svga->crtc[0x35] & 1) + svga->vblankstart += 0x400; + if (svga->crtc[0x35] & 2) + svga->vtotal += 0x400; + if (svga->crtc[0x35] & 4) + svga->dispend += 0x400; + if (svga->crtc[0x35] & 8) + svga->vsyncstart += 0x400; + if (svga->crtc[0x35] & 0x10) + svga->split += 0x400; + if (!svga->rowoffset) + svga->rowoffset = 0x100; + if (svga->crtc[0x3f] & 1) + svga->htotal += 256; + if (svga->attrregs[0x16] & 0x20) + svga->hdisp <<= 1; - switch (((svga->miscout >> 2) & 3) | ((svga->crtc[0x34] << 1) & 4)) { - case 0: - case 1: - break; - case 3: - svga->clock = (cpuclock * (double)(1ull << 32)) / 40000000.0; - break; - case 5: - svga->clock = (cpuclock * (double)(1ull << 32)) / 65000000.0; - break; - default: - svga->clock = (cpuclock * (double)(1ull << 32)) / 36000000.0; - break; - } - - switch (svga->bpp) { - case 15: - case 16: - svga->hdisp /= 2; - break; + switch (((svga->miscout >> 2) & 3) | ((svga->crtc[0x34] << 1) & 4)) { + case 0: + case 1: + break; + case 3: + svga->clock = (cpuclock * (double) (1ULL << 32)) / 40000000.0; + break; + case 5: + svga->clock = (cpuclock * (double) (1ULL << 32)) / 65000000.0; + break; + default: + svga->clock = (cpuclock * (double) (1ULL << 32)) / 36000000.0; + break; + } - case 24: - svga->hdisp /= 3; - break; - } + switch (svga->bpp) { + case 15: + case 16: + svga->hdisp /= 2; + break; - if (dev->type == 2 || dev->type == 3 || dev->type == 4) { - if ((svga->render == svga_render_text_80) && ((svga->crtc[0x37] & 0x0A) == 0x0A)) { - if (dev->port_32cb_val & 0x80) { - svga->ma_latch -= 2; - svga->ca_adj = -2; - } - if ((dev->port_32cb_val & 0xB4) == ((svga->crtc[0x37] & 3) == 2 ? 0xB4 : 0xB0)) { - svga->render = svga_render_text_80_ksc5601; - } - } - } + case 24: + svga->hdisp /= 3; + break; + + default: + break; + } + + if (dev->type == ET4000_TYPE_KOREAN || dev->type == ET4000_TYPE_TRIGEM || dev->type == ET4000_TYPE_KASAN) { + if ((svga->render == svga_render_text_80) && ((svga->crtc[0x37] & 0x0A) == 0x0A)) { + if (dev->port_32cb_val & 0x80) { + svga->ma_latch -= 2; + svga->ca_adj = -2; + } + if ((dev->port_32cb_val & 0xB4) == ((svga->crtc[0x37] & 3) == 2 ? 0xB4 : 0xB0)) { + svga->render = svga_render_text_80_ksc5601; + } + } + } } static void et4000_kasan_recalctimings(svga_t *svga) { - et4000_t *et4000 = (et4000_t *)svga->p; + const et4000_t *et4000 = (et4000_t *) svga->priv; - et4000_recalctimings(svga); + et4000_recalctimings(svga); - if (svga->render == svga_render_text_80 && (et4000->kasan_cfg_regs[0] & 8)) { - svga->ma_latch -= 3; - svga->ca_adj = (et4000->kasan_cfg_regs[0] >> 6) - 3; - svga->ksc5601_sbyte_mask = (et4000->kasan_cfg_regs[0] & 4) << 5; - if((et4000->kasan_cfg_regs[0] & 0x23) == 0x20 && (et4000->kasan_cfg_regs[4] & 0x80) && ((svga->crtc[0x37] & 0x0B) == 0x0A)) - svga->render = svga_render_text_80_ksc5601; - } + if (svga->render == svga_render_text_80 && (et4000->kasan_cfg_regs[0] & 8)) { + svga->ma_latch -= 3; + svga->ca_adj = (et4000->kasan_cfg_regs[0] >> 6) - 3; + svga->ksc5601_sbyte_mask = (et4000->kasan_cfg_regs[0] & 4) << 5; + if ((et4000->kasan_cfg_regs[0] & 0x23) == 0x20 && (et4000->kasan_cfg_regs[4] & 0x80) && ((svga->crtc[0x37] & 0x0B) == 0x0A)) + svga->render = svga_render_text_80_ksc5601; + } } static uint8_t et4000_mca_read(int port, void *priv) { - et4000_t *et4000 = (et4000_t *)priv; + const et4000_t *et4000 = (et4000_t *) priv; - return(et4000->pos_regs[port & 7]); + return (et4000->pos_regs[port & 7]); } - static void et4000_mca_write(int port, uint8_t val, void *priv) { - et4000_t *et4000 = (et4000_t *)priv; + et4000_t *et4000 = (et4000_t *) priv; /* MCA does not write registers below 0x0100. */ - if (port < 0x0102) return; + if (port < 0x0102) + return; /* Save the MCA register value. */ et4000->pos_regs[port & 7] = val; } - static uint8_t -et4000_mca_feedb(void *priv) +et4000_mca_feedb(UNUSED(void *priv)) { return 1; } - static void * et4000_init(const device_t *info) { const char *fn; - et4000_t *dev; - int i; + et4000_t *dev; + int i; - dev = (et4000_t *)malloc(sizeof(et4000_t)); + dev = (et4000_t *) malloc(sizeof(et4000_t)); memset(dev, 0x00, sizeof(et4000_t)); dev->name = info->name; dev->type = info->local; - fn = BIOS_ROM_PATH; + fn = BIOS_ROM_PATH; - switch(dev->type) { - case 0: /* ISA ET4000AX */ - dev->vram_size = device_get_config_int("memory") << 10; - video_inform(VIDEO_FLAG_TYPE_SPECIAL, &timing_et4000_isa); - svga_init(info, &dev->svga, dev, dev->vram_size, - et4000_recalctimings, et4000_in, et4000_out, - NULL, NULL); - io_sethandler(0x03c0, 32, - et4000_in,NULL,NULL, et4000_out,NULL,NULL, dev); - break; + switch (dev->type) { + case ET4000_TYPE_ISA: /* ISA ET4000AX */ + dev->vram_size = device_get_config_int("memory") << 10; + video_inform(VIDEO_FLAG_TYPE_SPECIAL, &timing_et4000_isa); + svga_init(info, &dev->svga, dev, dev->vram_size, + et4000_recalctimings, et4000_in, et4000_out, + NULL, NULL); + io_sethandler(0x03c0, 32, + et4000_in, NULL, NULL, et4000_out, NULL, NULL, dev); + break; - case 1: /* MCA ET4000AX */ - dev->vram_size = 1024 << 10; - video_inform(VIDEO_FLAG_TYPE_SPECIAL, &timing_et4000_mca); - svga_init(info, &dev->svga, dev, dev->vram_size, - et4000_recalctimings, et4000_in, et4000_out, - NULL, NULL); - io_sethandler(0x03c0, 32, - et4000_in,NULL,NULL, et4000_out,NULL,NULL, dev); - dev->pos_regs[0] = 0xf2; /* ET4000 MCA board ID */ - dev->pos_regs[1] = 0x80; - mca_add(et4000_mca_read, et4000_mca_write, et4000_mca_feedb, NULL, dev); - break; + case ET4000_TYPE_MCA: /* MCA ET4000AX */ + dev->vram_size = 1024 << 10; + video_inform(VIDEO_FLAG_TYPE_SPECIAL, &timing_et4000_mca); + svga_init(info, &dev->svga, dev, dev->vram_size, + et4000_recalctimings, et4000_in, et4000_out, + NULL, NULL); + io_sethandler(0x03c0, 32, + et4000_in, NULL, NULL, et4000_out, NULL, NULL, dev); + dev->pos_regs[0] = 0xf2; /* ET4000 MCA board ID */ + dev->pos_regs[1] = 0x80; + mca_add(et4000_mca_read, et4000_mca_write, et4000_mca_feedb, NULL, dev); + break; - case 2: /* Korean ET4000 */ - case 3: /* Trigem 286M ET4000 */ - dev->vram_size = device_get_config_int("memory") << 10; - dev->port_22cb_val = 0x60; - dev->port_32cb_val = 0; - dev->svga.ksc5601_sbyte_mask = 0x80; - dev->svga.ksc5601_udc_area_msb[0] = 0xC9; - dev->svga.ksc5601_udc_area_msb[1] = 0xFE; - dev->svga.ksc5601_swap_mode = 0; - dev->svga.ksc5601_english_font_type = 0; - video_inform(VIDEO_FLAG_TYPE_SPECIAL, &timing_et4000_isa); - svga_init(info, &dev->svga, dev, dev->vram_size, - et4000_recalctimings, et4000k_in, et4000k_out, - NULL, NULL); - io_sethandler(0x03c0, 32, - et4000k_in,NULL,NULL, et4000k_out,NULL,NULL, dev); - io_sethandler(0x22cb, 1, - et4000k_in,NULL,NULL, et4000k_out,NULL,NULL, dev); - io_sethandler(0x22cf, 1, - et4000k_in,NULL,NULL, et4000k_out,NULL,NULL, dev); - io_sethandler(0x32cb, 1, - et4000k_in,NULL,NULL, et4000k_out,NULL,NULL, dev); - loadfont(KOREAN_FONT_ROM_PATH, 6); - fn = KOREAN_BIOS_ROM_PATH; - break; - case 4: /* Kasan ET4000 */ - dev->vram_size = device_get_config_int("memory") << 10; - dev->svga.ksc5601_sbyte_mask = 0; - dev->svga.ksc5601_udc_area_msb[0] = 0xC9; - dev->svga.ksc5601_udc_area_msb[1] = 0xFE; - dev->svga.ksc5601_swap_mode = 0; - dev->svga.ksc5601_english_font_type = 0x1FF; - dev->kasan_cfg_index = 0; - for (i=0; i<16; i++) - dev->kasan_cfg_regs[i] = 0; - for(i=0; i<4; i++) - dev->kasan_font_data[i] = 0; - dev->kasan_cfg_regs[1] = 0x50; - dev->kasan_cfg_regs[2] = 2; - dev->kasan_cfg_regs[3] = 6; - dev->kasan_cfg_regs[4] = 0x78; - dev->kasan_cfg_regs[5] = 0xFF; - dev->kasan_cfg_regs[6] = 0xC9; - dev->kasan_cfg_regs[7] = 0xFE; - dev->kasan_access_addr = 0x250; - video_inform(VIDEO_FLAG_TYPE_SPECIAL, &timing_et4000_isa); - svga_init(info, &dev->svga, dev, dev->vram_size, - et4000_kasan_recalctimings, et4000_in, et4000_out, - NULL, NULL); - io_sethandler(0x03c0, 32, - et4000_in,NULL,NULL, et4000_out,NULL,NULL, dev); - io_sethandler(0x0250, 8, - et4000_kasan_in, NULL, NULL, et4000_kasan_out, NULL, NULL, dev); - io_sethandler(0x0258, 2, - et4000_kasan_in, NULL, NULL, et4000_kasan_out, NULL, NULL, dev); - loadfont(KASAN_FONT_ROM_PATH, 6); - fn = KASAN_BIOS_ROM_PATH; - break; - + case ET4000_TYPE_KOREAN: /* Korean ET4000 */ + case ET4000_TYPE_TRIGEM: /* Trigem 286M ET4000 */ + dev->vram_size = device_get_config_int("memory") << 10; + dev->port_22cb_val = 0x60; + dev->port_32cb_val = 0; + dev->svga.ksc5601_sbyte_mask = 0x80; + dev->svga.ksc5601_udc_area_msb[0] = 0xC9; + dev->svga.ksc5601_udc_area_msb[1] = 0xFE; + dev->svga.ksc5601_swap_mode = 0; + dev->svga.ksc5601_english_font_type = 0; + video_inform(VIDEO_FLAG_TYPE_SPECIAL, &timing_et4000_isa); + svga_init(info, &dev->svga, dev, dev->vram_size, + et4000_recalctimings, et4000k_in, et4000k_out, + NULL, NULL); + io_sethandler(0x03c0, 32, + et4000k_in, NULL, NULL, et4000k_out, NULL, NULL, dev); + io_sethandler(0x22cb, 1, + et4000k_in, NULL, NULL, et4000k_out, NULL, NULL, dev); + io_sethandler(0x22cf, 1, + et4000k_in, NULL, NULL, et4000k_out, NULL, NULL, dev); + io_sethandler(0x32cb, 1, + et4000k_in, NULL, NULL, et4000k_out, NULL, NULL, dev); + loadfont(KOREAN_FONT_ROM_PATH, 6); + fn = KOREAN_BIOS_ROM_PATH; + break; + + case ET4000_TYPE_KASAN: /* Kasan ET4000 */ + dev->vram_size = device_get_config_int("memory") << 10; + dev->svga.ksc5601_sbyte_mask = 0; + dev->svga.ksc5601_udc_area_msb[0] = 0xC9; + dev->svga.ksc5601_udc_area_msb[1] = 0xFE; + dev->svga.ksc5601_swap_mode = 0; + dev->svga.ksc5601_english_font_type = 0x1FF; + dev->kasan_cfg_index = 0; + for (i = 0; i < 16; i++) + dev->kasan_cfg_regs[i] = 0; + for (i = 0; i < 4; i++) + dev->kasan_font_data[i] = 0; + dev->kasan_cfg_regs[1] = 0x50; + dev->kasan_cfg_regs[2] = 2; + dev->kasan_cfg_regs[3] = 6; + dev->kasan_cfg_regs[4] = 0x78; + dev->kasan_cfg_regs[5] = 0xFF; + dev->kasan_cfg_regs[6] = 0xC9; + dev->kasan_cfg_regs[7] = 0xFE; + dev->kasan_access_addr = 0x250; + video_inform(VIDEO_FLAG_TYPE_SPECIAL, &timing_et4000_isa); + svga_init(info, &dev->svga, dev, dev->vram_size, + et4000_kasan_recalctimings, et4000_in, et4000_out, + NULL, NULL); + io_sethandler(0x03c0, 32, + et4000k_in, NULL, NULL, et4000k_out, NULL, NULL, dev); + io_sethandler(0x0250, 8, + et4000_kasan_in, NULL, NULL, et4000_kasan_out, NULL, NULL, dev); + io_sethandler(0x0258, 2, + et4000_kasan_in, NULL, NULL, et4000_kasan_out, NULL, NULL, dev); + loadfont(KASAN_FONT_ROM_PATH, 6); + fn = KASAN_BIOS_ROM_PATH; + break; + + default: + break; } dev->svga.ramdac = device_add(&sc1502x_ramdac_device); dev->vram_mask = dev->vram_size - 1; - rom_init(&dev->bios_rom, (char *) fn, - 0xc0000, 0x8000, 0x7fff, 0, MEM_MAPPING_EXTERNAL); + rom_init(&dev->bios_rom, fn, + 0xc0000, 0x8000, 0x7fff, 0, MEM_MAPPING_EXTERNAL); dev->svga.translate_address = get_et4000_addr; - dev->svga.packed_chain4 = 1; + dev->svga.packed_chain4 = 1; - return(dev); + return dev; } - static void et4000_close(void *priv) { - et4000_t *dev = (et4000_t *)priv; + et4000_t *dev = (et4000_t *) priv; svga_close(&dev->svga); free(dev); } - static void et4000_speed_changed(void *priv) { - et4000_t *dev = (et4000_t *)priv; + et4000_t *dev = (et4000_t *) priv; svga_recalctimings(&dev->svga); } - static void et4000_force_redraw(void *priv) { - et4000_t *dev = (et4000_t *)priv; + et4000_t *dev = (et4000_t *) priv; dev->svga.fullchange = changeframecount; } - static int et4000_available(void) { return rom_present(BIOS_ROM_PATH); } - static int et4000k_available(void) { - return rom_present(KOREAN_BIOS_ROM_PATH) && - rom_present(KOREAN_FONT_ROM_PATH); + return rom_present(KOREAN_BIOS_ROM_PATH) && rom_present(KOREAN_FONT_ROM_PATH); } static int et4000_kasan_available(void) { - return rom_present(KASAN_BIOS_ROM_PATH) && - rom_present(KASAN_FONT_ROM_PATH); + return rom_present(KASAN_BIOS_ROM_PATH) && rom_present(KASAN_FONT_ROM_PATH); } -static const device_config_t et4000_config[] = -{ - { - "memory", "Memory size", CONFIG_SELECTION, "", 1024, "", { 0 }, - { - { - "256 KB", 256 - }, - { - "512 KB", 512 - }, - { - "1 MB", 1024 - }, - { - "" - } - } - }, - { - "", "", -1 - } +static const device_config_t et4000_config[] = { + // clang-format off + { + .name = "memory", + .description = "Memory size", + .type = CONFIG_SELECTION, + .default_int = 1024, + .selection = { + { + .description = "256 KB", + .value = 256 + }, + { + .description = "512 KB", + .value = 512 + }, + { + .description = "1 MB", + .value = 1024 + }, + { + .description = "" + } + } + }, + { + .type = CONFIG_END + } + // clang-format on }; const device_t et4000_isa_device = { - "Tseng Labs ET4000AX (ISA)", - "et4000ax", - DEVICE_ISA, - 0, - et4000_init, et4000_close, NULL, - { et4000_available }, - et4000_speed_changed, - et4000_force_redraw, - et4000_config + .name = "Tseng Labs ET4000AX (ISA)", + .internal_name = "et4000ax", + .flags = DEVICE_ISA, + .local = ET4000_TYPE_ISA, + .init = et4000_init, + .close = et4000_close, + .reset = NULL, + { .available = et4000_available }, + .speed_changed = et4000_speed_changed, + .force_redraw = et4000_force_redraw, + .config = et4000_config }; const device_t et4000_mca_device = { - "Tseng Labs ET4000AX (MCA)", - "et4000mca", - DEVICE_MCA, - 1, - et4000_init, et4000_close, NULL, - { et4000_available }, - et4000_speed_changed, - et4000_force_redraw, - et4000_config + .name = "Tseng Labs ET4000AX (MCA)", + .internal_name = "et4000mca", + .flags = DEVICE_MCA, + .local = ET4000_TYPE_MCA, + .init = et4000_init, + .close = et4000_close, + .reset = NULL, + { .available = et4000_available }, + .speed_changed = et4000_speed_changed, + .force_redraw = et4000_force_redraw, + .config = et4000_config }; const device_t et4000k_isa_device = { - "Trigem Korean VGA (Tseng Labs ET4000AX Korean)", - "tgkorvga", - DEVICE_ISA, - 2, - et4000_init, et4000_close, NULL, - { et4000k_available }, - et4000_speed_changed, - et4000_force_redraw, - et4000_config + .name = "Trigem Korean VGA (Tseng Labs ET4000AX Korean)", + .internal_name = "tgkorvga", + .flags = DEVICE_ISA, + .local = ET4000_TYPE_KOREAN, + .init = et4000_init, + .close = et4000_close, + .reset = NULL, + { .available = et4000k_available }, + .speed_changed = et4000_speed_changed, + .force_redraw = et4000_force_redraw, + .config = et4000_config }; const device_t et4000k_tg286_isa_device = { - "Trigem Korean VGA (Trigem 286M)", - "et4000k_tg286_isa", - DEVICE_ISA, - 3, - et4000_init, et4000_close, NULL, - { et4000k_available }, - et4000_speed_changed, - et4000_force_redraw, - et4000_config + .name = "Trigem Korean VGA (Trigem 286M)", + .internal_name = "et4000k_tg286_isa", + .flags = DEVICE_ISA, + .local = ET4000_TYPE_TRIGEM, + .init = et4000_init, + .close = et4000_close, + .reset = NULL, + { .available = et4000k_available }, + .speed_changed = et4000_speed_changed, + .force_redraw = et4000_force_redraw, + .config = et4000_config }; const device_t et4000_kasan_isa_device = { - "Kasan Hangulmadang-16 VGA (Tseng Labs ET4000AX Korean)", - "kasan16vga", - DEVICE_ISA, - 4, - et4000_init, et4000_close, NULL, - { et4000_kasan_available }, - et4000_speed_changed, - et4000_force_redraw, - et4000_config + .name = "Kasan Hangulmadang-16 VGA (Tseng Labs ET4000AX Korean)", + .internal_name = "kasan16vga", + .flags = DEVICE_ISA, + .local = ET4000_TYPE_KASAN, + .init = et4000_init, + .close = et4000_close, + .reset = NULL, + { .available = et4000_kasan_available }, + .speed_changed = et4000_speed_changed, + .force_redraw = et4000_force_redraw, + .config = et4000_config }; diff --git a/src/video/vid_et4000w32.c b/src/video/vid_et4000w32.c index df2eab5a2..b48135c37 100644 --- a/src/video/vid_et4000w32.c +++ b/src/video/vid_et4000w32.c @@ -1,22 +1,22 @@ /* - * 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. + * 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. + * This file is part of the 86Box distribution. * - * ET4000/W32 series emulation. + * ET4000/W32 series emulation. * - * Known bugs: Accelerator doesn't work in planar modes + * Known bugs: Accelerator doesn't work in planar modes * * * - * Authors: Sarah Walker, - * Miran Grca, + * Authors: Sarah Walker, + * Miran Grca, * - * Copyright 2008-2019 Sarah Walker. - * Copyright 2016-2019 Miran Grca. + * Copyright 2008-2019 Sarah Walker. + * Copyright 2016-2019 Miran Grca. */ #include #include @@ -37,740 +37,835 @@ #include <86box/vid_svga.h> #include <86box/vid_svga_render.h> +#define BIOS_ROM_PATH_DIAMOND "roms/video/et4000w32/et4000w32.bin" +#define BIOS_ROM_PATH_CARDEX "roms/video/et4000w32/cardex.vbi" +#define BIOS_ROM_PATH_W32 "roms/video/et4000w32/ET4000W32VLB_bios_MX27C512.BIN" +#define BIOS_ROM_PATH_W32I_ISA "roms/video/et4000w32/ET4KW32I.VBI" +#define BIOS_ROM_PATH_W32I_VLB "roms/video/et4000w32/tseng.u41.bin" +#define BIOS_ROM_PATH_W32P_VIDEOMAGIC_REVB_VLB "roms/video/et4000w32/VideoMagic-BioS-HXIRTW32PWSRL.BIN" +#define BIOS_ROM_PATH_W32P "roms/video/et4000w32/ET4K_W32.BIN" +#define BIOS_ROM_PATH_W32P_REVC "roms/video/et4000w32/et4000w32pcardex.BIN" -#define BIOS_ROM_PATH_DIAMOND "roms/video/et4000w32/et4000w32.bin" -#define BIOS_ROM_PATH_CARDEX "roms/video/et4000w32/cardex.vbi" -#define BIOS_ROM_PATH_W32 "roms/video/et4000w32/ET4000W32VLB_bios_MX27C512.BIN" -#define BIOS_ROM_PATH_W32I_ISA "roms/video/et4000w32/ET4KW32I.VBI" -#define BIOS_ROM_PATH_W32I_VLB "roms/video/et4000w32/tseng.u41.bin" -#define BIOS_ROM_PATH_W32P "roms/video/et4000w32/ET4K_W32.BIN" -#define BIOS_ROM_PATH_W32P_REVC "roms/video/et4000w32/et4000w32pcardex.BIN" +#define ACL_WRST 1 +#define ACL_RDST 2 +#define ACL_XYST 4 +#define ACL_SSO 8 - -#define ACL_WRST 1 -#define ACL_RDST 2 -#define ACL_XYST 4 -#define ACL_SSO 8 - - -enum -{ +enum { ET4000W32, ET4000W32I, ET4000W32P_REVC, + ET4000W32P_VIDEOMAGIC_REVB, ET4000W32P, ET4000W32P_CARDEX, ET4000W32P_DIAMOND }; +typedef struct et4000w32p_t { + mem_mapping_t linear_mapping; + mem_mapping_t mmu_mapping; -typedef struct et4000w32p_t -{ - mem_mapping_t linear_mapping; - mem_mapping_t mmu_mapping; + rom_t bios_rom; - rom_t bios_rom; + svga_t svga; - svga_t svga; + uint8_t banking, banking2, adjust_cursor, rev, pci_slot; - uint8_t banking, banking2, adjust_cursor, rev; + uint8_t regs[256], pci_regs[256]; - uint8_t regs[256], pci_regs[256]; + int index, vlb, pci, interleaved, + bank, type; - int index, vlb, pci, interleaved, - bank, type; - - uint32_t linearbase; - uint32_t vram_mask; + uint32_t linearbase; + uint32_t vram_mask; /* Accelerator */ struct { - struct { - uint8_t vbus, pixel_depth, xy_dir, pattern_wrap, - source_wrap, ctrl_routing, ctrl_reload, rop_fg, - rop_bg; + struct { + uint8_t vbus, pixel_depth, xy_dir, pattern_wrap, + source_wrap, ctrl_routing, ctrl_reload, rop_fg, + rop_bg; - uint16_t pattern_off, source_off, dest_off, mix_off, - count_x,count_y, pos_x, pos_y, - error, dmin, dmaj; + uint16_t pattern_off, source_off, dest_off, mix_off, + count_x, count_y, pos_x, pos_y, + error, dmin, dmaj; - uint32_t pattern_addr, source_addr, dest_addr, mix_addr; - } queued, internal; + uint32_t pattern_addr, source_addr, dest_addr, mix_addr; + } queued, internal; - uint8_t suspend_terminate, osr; - uint8_t status; - uint16_t x_count, y_count; + uint8_t suspend_terminate, osr; + uint8_t status; + uint16_t x_count, y_count; + uint16_t cpu_x_cnt, cpu_x_cnt_back, cpu_y_cnt; - int pattern_x, source_x, pattern_x_back, source_x_back, - pattern_y, source_y, cpu_dat_pos, pix_pos, - cpu_input_num, fifo_queue; + int pattern_x, source_x, pattern_x_back, source_x_back, + pattern_y, source_y, cpu_dat_pos, pix_pos, + cpu_input_num, fifo_queue; + int mmu_start; - uint32_t pattern_addr, source_addr, dest_addr, mix_addr, - pattern_back, source_back, dest_back, mix_back, - cpu_input; + uint32_t pattern_addr, source_addr, dest_addr, mix_addr, + pattern_back, source_back, dest_back, mix_back, + cpu_input; - uint64_t cpu_dat; + uint64_t cpu_dat; } acl; struct { - uint32_t base[3]; - uint8_t ctrl; + uint32_t base[3]; + uint8_t ctrl; } mmu; - - volatile int busy; + + volatile int busy; } et4000w32p_t; +static int et4000w32_vbus[4] = { 1, 2, 4, 4 }; -static int et4000w32_vbus[4] = {1, 2, 4, 4}; +static int et4000w32_max_x[8] = { 0, 0, 4, 8, 0x10, 0x20, 0x40, 0x70000000 }; +static int et4000w32_wrap_x[8] = { 0, 0, 3, 7, 0x0f, 0x1f, 0x3f, ~0 }; +static int et4000w32_wrap_y[8] = { 1, 2, 4, 8, ~0, ~0, ~0, ~0 }; -static int et4000w32_max_x[8] = {0,0,4,8,0x10,0x20,0x40,0x70000000}; -static int et4000w32_wrap_x[8] = {0,0,3,7,0x0F,0x1F,0x3F,~0}; -static int et4000w32_wrap_y[8] = {1,2,4,8,~0,~0,~0,~0}; +static video_timings_t timing_et4000w32_vlb = { .type = VIDEO_BUS, .write_b = 4, .write_w = 4, .write_l = 4, .read_b = 10, .read_w = 10, .read_l = 10 }; +static video_timings_t timing_et4000w32_pci = { .type = VIDEO_PCI, .write_b = 4, .write_w = 4, .write_l = 4, .read_b = 10, .read_w = 10, .read_l = 10 }; +static video_timings_t timing_et4000w32_isa = { .type = VIDEO_ISA, .write_b = 4, .write_w = 4, .write_l = 4, .read_b = 10, .read_w = 10, .read_l = 10 }; -static video_timings_t timing_et4000w32_vlb = {VIDEO_BUS, 4, 4, 4, 10, 10, 10}; -static video_timings_t timing_et4000w32_pci = {VIDEO_PCI, 4, 4, 4, 10, 10, 10}; -static video_timings_t timing_et4000w32_isa = {VIDEO_ISA, 4, 4, 4, 10, 10, 10}; +void et4000w32p_recalcmapping(et4000w32p_t *et4000); +static uint8_t et4000w32p_mmu_read(uint32_t addr, void *priv); +static void et4000w32p_mmu_write(uint32_t addr, uint8_t val, void *priv); -void et4000w32p_recalcmapping(et4000w32p_t *et4000); - -static uint8_t et4000w32p_mmu_read(uint32_t addr, void *p); -static void et4000w32p_mmu_write(uint32_t addr, uint8_t val, void *p); - -static void et4000w32_blit_start(et4000w32p_t *et4000); -static void et4000w32p_blit_start(et4000w32p_t *et4000); -static void et4000w32_blit(int count, int cpu_input, uint32_t src_dat, uint32_t mix_dat, et4000w32p_t *et4000); -static void et4000w32p_blit(int count, uint32_t mix, uint32_t sdat, int cpu_input, et4000w32p_t *et4000); -uint8_t et4000w32p_in(uint16_t addr, void *p); - +static void et4000w32_blit_start(et4000w32p_t *et4000); +static void et4000w32p_blit_start(et4000w32p_t *et4000); +static void et4000w32_blit(int count, int cpu_input, uint32_t src_dat, uint32_t mix_dat, et4000w32p_t *et4000); +static void et4000w32p_blit(int count, uint32_t mix, uint32_t sdat, int cpu_input, et4000w32p_t *et4000); +uint8_t et4000w32p_in(uint16_t addr, void *priv); #ifdef ENABLE_ET4000W32_LOG int et4000w32_do_log = ENABLE_ET4000W32_LOG; - static void et4000w32_log(const char *fmt, ...) { va_list ap; if (et4000w32_do_log) { - va_start(ap, fmt); - pclog_ex(fmt, ap); - va_end(ap); + va_start(ap, fmt); + pclog_ex(fmt, ap); + va_end(ap); } } #else -#define et4000w32_log(fmt, ...) +# define et4000w32_log(fmt, ...) #endif - void -et4000w32p_out(uint16_t addr, uint8_t val, void *p) +et4000w32p_out(uint16_t addr, uint8_t val, void *priv) { - et4000w32p_t *et4000 = (et4000w32p_t *)p; - svga_t *svga = &et4000->svga; - uint8_t old; - uint32_t add2addr = 0; + et4000w32p_t *et4000 = (et4000w32p_t *) priv; + svga_t *svga = &et4000->svga; + uint8_t old; + uint32_t add2addr = 0; - if (((addr & 0xfff0) == 0x3d0 || (addr & 0xfff0) == 0x3b0) && !(svga->miscout & 1)) - addr ^= 0x60; + if (((addr & 0xfff0) == 0x3d0 || (addr & 0xfff0) == 0x3b0) && !(svga->miscout & 1)) + addr ^= 0x60; switch (addr) { - case 0x3c2: - if (et4000->type == ET4000W32P_DIAMOND) - icd2061_write(svga->clock_gen, (val >> 2) & 3); - break; + case 0x3c2: + if (et4000->type == ET4000W32P_DIAMOND) + icd2061_write(svga->clock_gen, (val >> 2) & 3); + break; - case 0x3c6: case 0x3c7: case 0x3c8: case 0x3c9: - if (et4000->type <= ET4000W32P_REVC) - sdac_ramdac_out(addr, 0, val, svga->ramdac, svga); - else - stg_ramdac_out(addr, val, svga->ramdac, svga); - return; + case 0x3c6: + case 0x3c7: + case 0x3c8: + case 0x3c9: + if (et4000->type <= ET4000W32P_REVC) + sdac_ramdac_out(addr, 0, val, svga->ramdac, svga); + else + stg_ramdac_out(addr, val, svga->ramdac, svga); + return; - case 0x3cb: /* Banking extension */ - if (!(svga->crtc[0x36] & 0x10) && !(svga->gdcreg[6] & 0x08)) { - svga->write_bank = (svga->write_bank & 0xfffff) | ((val & 1) << 20); - svga->read_bank = (svga->read_bank & 0xfffff) | ((val & 0x10) << 16); - } - et4000->banking2 = val; - return; - case 0x3cd: /* Banking */ - if (!(svga->crtc[0x36] & 0x10) && !(svga->gdcreg[6] & 0x08)) { - svga->write_bank = (svga->write_bank & 0x100000) | ((val & 0xf) * 65536); - svga->read_bank = (svga->read_bank & 0x100000) | (((val >> 4) & 0xf) * 65536); - } - et4000->banking = val; - return; - case 0x3cf: - switch (svga->gdcaddr & 15) { - case 6: - if (!(svga->crtc[0x36] & 0x10) && !(val & 0x08)) { - svga->write_bank = ((et4000->banking2 & 1) << 20) | ((et4000->banking & 0xf) * 65536); - svga->read_bank = ((et4000->banking2 & 0x10) << 16) | (((et4000->banking >> 4) & 0xf) * 65536); - } else - svga->write_bank = svga->read_bank = 0; + case 0x3cb: /* Banking extension */ + if (!(svga->crtc[0x36] & 0x10) && !(svga->gdcreg[6] & 0x08)) { + svga->write_bank = (svga->write_bank & 0xfffff) | ((val & 1) << 20); + svga->read_bank = (svga->read_bank & 0xfffff) | ((val & 0x10) << 16); + } + et4000->banking2 = val; + return; + case 0x3cd: /* Banking */ + if (!(svga->crtc[0x36] & 0x10) && !(svga->gdcreg[6] & 0x08)) { + svga->write_bank = (svga->write_bank & 0x100000) | ((val & 0xf) * 65536); + svga->read_bank = (svga->read_bank & 0x100000) | (((val >> 4) & 0xf) * 65536); + } + et4000->banking = val; + return; + case 0x3cf: + switch (svga->gdcaddr & 15) { + case 6: + if (!(svga->crtc[0x36] & 0x10) && !(val & 0x08)) { + svga->write_bank = ((et4000->banking2 & 1) << 20) | ((et4000->banking & 0xf) * 65536); + svga->read_bank = ((et4000->banking2 & 0x10) << 16) | (((et4000->banking >> 4) & 0xf) * 65536); + } else + svga->write_bank = svga->read_bank = 0; - svga->gdcreg[svga->gdcaddr & 15] = val; - et4000w32p_recalcmapping(et4000); - return; - } - break; - case 0x3d4: - svga->crtcreg = val & 0x3f; - return; - case 0x3d5: - if ((svga->crtcreg < 7) && (svga->crtc[0x11] & 0x80)) - return; - if ((svga->crtcreg == 0x35) && (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 (svga->crtcreg == 0x36) { - if (!(val & 0x10) && !(svga->gdcreg[6] & 0x08)) { - svga->write_bank = ((et4000->banking2 & 1) << 20) | ((et4000->banking & 0xf) * 65536); - svga->read_bank = ((et4000->banking2 & 0x10) << 16) | (((et4000->banking >> 4) & 0xf) * 65536); - } else - svga->write_bank = svga->read_bank = 0; - } - 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); - } - } - } - if (svga->crtcreg == 0x30) { - if (et4000->pci) - et4000->linearbase = (et4000->linearbase & 0xc0000000) | ((val & 0xfc) << 22); - else - et4000->linearbase = val << 22; - et4000w32p_recalcmapping(et4000); - } - if (svga->crtcreg == 0x32 || svga->crtcreg == 0x36) - et4000w32p_recalcmapping(et4000); - break; + svga->gdcreg[svga->gdcaddr & 15] = val; + et4000w32p_recalcmapping(et4000); + return; - case 0x210a: case 0x211a: case 0x212a: case 0x213a: - case 0x214a: case 0x215a: case 0x216a: case 0x217a: - et4000->index = val; - return; - case 0x210b: case 0x211b: case 0x212b: case 0x213b: - case 0x214b: case 0x215b: case 0x216b: case 0x217b: - et4000->regs[et4000->index] = val; - svga->hwcursor.xsize = svga->hwcursor.ysize = ((et4000->regs[0xEF] & 4) || (et4000->type == ET4000W32)) ? 128 : 64; - svga->hwcursor.x = et4000->regs[0xE0] | ((et4000->regs[0xE1] & 7) << 8); - svga->hwcursor.y = et4000->regs[0xE4] | ((et4000->regs[0xE5] & 7) << 8); - svga->hwcursor.ena = !!(et4000->regs[0xF7] & 0x80); - svga->hwcursor.xoff = et4000->regs[0xE2]; - svga->hwcursor.yoff = et4000->regs[0xE6]; + default: + break; + } + break; + case 0x3d4: + svga->crtcreg = val & 0x3f; + return; + case 0x3d5: + if ((svga->crtcreg < 7) && (svga->crtc[0x11] & 0x80)) + return; + if ((svga->crtcreg == 0x35) && (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 (svga->crtcreg == 0x36) { + if (!(val & 0x10) && !(svga->gdcreg[6] & 0x08)) { + svga->write_bank = ((et4000->banking2 & 1) << 20) | ((et4000->banking & 0xf) * 65536); + svga->read_bank = ((et4000->banking2 & 0x10) << 16) | (((et4000->banking >> 4) & 0xf) * 65536); + } else + svga->write_bank = svga->read_bank = 0; + } + 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); + } + } + } + if (svga->crtcreg == 0x30) { + if (et4000->pci && (et4000->rev != 5)) + et4000->linearbase = (et4000->linearbase & 0xc0000000) | ((val & 0xfc) << 22); + else + et4000->linearbase = val << 22; + et4000w32p_recalcmapping(et4000); + } + if (svga->crtcreg == 0x32 || svga->crtcreg == 0x36) + et4000w32p_recalcmapping(et4000); + break; - if (et4000->type == ET4000W32) { - switch (svga->bpp) { - case 8: - svga->hwcursor.xoff += 32; - break; - } - } + case 0x210a: + case 0x211a: + case 0x212a: + case 0x213a: + case 0x214a: + case 0x215a: + case 0x216a: + case 0x217a: + et4000->index = val; + return; + case 0x210b: + case 0x211b: + case 0x212b: + case 0x213b: + case 0x214b: + case 0x215b: + case 0x216b: + case 0x217b: + et4000->regs[et4000->index] = val; + svga->hwcursor.x = et4000->regs[0xE0] | ((et4000->regs[0xE1] & 7) << 8); + svga->hwcursor.y = et4000->regs[0xE4] | ((et4000->regs[0xE5] & 7) << 8); + 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] >= 0x1f) && (et4000->regs[0xe6] >= 0x1f))) ? 128 : 64; - if (svga->hwcursor.xsize == 128) { - svga->hwcursor.xoff &= 0x7f; - svga->hwcursor.yoff &= 0x7f; - if (et4000->type > ET4000W32P_REVC) { - if (svga->bpp == 24) { - et4000->adjust_cursor = 2; - } - } - } else { - if (et4000->type > ET4000W32P_REVC) { - if (svga->bpp == 24 && et4000->adjust_cursor) { - et4000->adjust_cursor = 0; - } - } - svga->hwcursor.xoff &= 0x3f; - svga->hwcursor.yoff &= 0x3f; - } - svga->hwcursor.addr = (et4000->regs[0xe8] | (et4000->regs[0xe9] << 8) | ((et4000->regs[0xea] & 7) << 16)) << 2; + if (et4000->type == ET4000W32) { + if ((svga->bpp == 15) || (svga->bpp == 16)) { + svga->hwcursor.cur_xsize = svga->hwcursor.cur_ysize = 128; + } + } - add2addr = svga->hwcursor.yoff * ((svga->hwcursor.xsize == 128) ? 32 : 16); - svga->hwcursor.addr += add2addr; - return; + if ((et4000->type == ET4000W32) && (svga->hwcursor.cur_xsize == 128)) { + switch (svga->bpp) { + case 8: + svga->hwcursor.xoff += 32; + break; + + default: + break; + } + } + + if (svga->hwcursor.cur_xsize == 128) { + svga->hwcursor.xoff &= 0x7f; + svga->hwcursor.yoff &= 0x7f; + if (et4000->type > ET4000W32P_REVC) { + if (svga->bpp == 24) { + et4000->adjust_cursor = 2; + } + } + } else { + if (et4000->type > ET4000W32P_REVC) { + if ((svga->bpp == 24) && et4000->adjust_cursor) { + et4000->adjust_cursor = 0; + } + } + svga->hwcursor.xoff &= 0x3f; + svga->hwcursor.yoff &= 0x3f; + } + svga->hwcursor.addr = (et4000->regs[0xe8] | (et4000->regs[0xe9] << 8) | ((et4000->regs[0xea] & 7) << 16)) << 2; + + add2addr = svga->hwcursor.yoff * ((svga->hwcursor.cur_xsize == 128) ? 32 : 16); + svga->hwcursor.addr += add2addr; + return; + + default: + break; } svga_out(addr, val, svga); } - uint8_t -et4000w32p_in(uint16_t addr, void *p) +et4000w32p_in(uint16_t addr, void *priv) { - et4000w32p_t *et4000 = (et4000w32p_t *)p; - svga_t *svga = &et4000->svga; + et4000w32p_t *et4000 = (et4000w32p_t *) priv; + svga_t *svga = &et4000->svga; - if (((addr & 0xfff0) == 0x3d0 || (addr & 0xfff0) == 0x3b0) && !(svga->miscout & 1)) - addr ^= 0x60; + if (((addr & 0xfff0) == 0x3d0 || (addr & 0xfff0) == 0x3b0) && !(svga->miscout & 1)) + addr ^= 0x60; switch (addr) { - case 0x3c5: - if ((svga->seqaddr & 0xf) == 7) - return svga->seqregs[svga->seqaddr & 0xf] | 4; - break; + case 0x3c5: + if ((svga->seqaddr & 0xf) == 7) + return svga->seqregs[svga->seqaddr & 0xf] | 4; + break; - case 0x3c6: case 0x3c7: case 0x3c8: case 0x3c9: - if (et4000->type <= ET4000W32P_REVC) - return sdac_ramdac_in(addr, 0, svga->ramdac, svga); - else - return stg_ramdac_in(addr, svga->ramdac, svga); - break; + case 0x3c6: + case 0x3c7: + case 0x3c8: + case 0x3c9: + if (et4000->type <= ET4000W32P_REVC) + return sdac_ramdac_in(addr, 0, svga->ramdac, svga); + else + return stg_ramdac_in(addr, svga->ramdac, svga); - case 0x3cb: - return et4000->banking2; - case 0x3cd: - return et4000->banking; - case 0x3d4: - return svga->crtcreg; - case 0x3d5: - if (et4000->type == ET4000W32) { - if (svga->crtcreg == 0x37) - return 0x09; - } - return svga->crtc[svga->crtcreg]; + case 0x3cb: + return et4000->banking2; + case 0x3cd: + return et4000->banking; + case 0x3d4: + return svga->crtcreg; + case 0x3d5: + if (et4000->type == ET4000W32) { + if (svga->crtcreg == 0x37) + return 0x09; + } + return svga->crtc[svga->crtcreg]; - case 0x3da: - svga->attrff = 0; + case 0x3da: + svga->attrff = 0; - /*Bit 1 of the Input Status Register is required by the OS/2 and NT ET4000W32/I drivers to be set otherwise - the guest will loop infinitely upon reaching the GUI*/ - if (svga->cgastat & 0x01) - svga->cgastat &= ~0x32; - else - svga->cgastat ^= 0x32; - return svga->cgastat; + /*Bit 1 of the Input Status Register is required by the OS/2 and NT ET4000W32/I drivers to be set otherwise + the guest will loop infinitely upon reaching the GUI*/ + if (svga->cgastat & 0x01) + svga->cgastat &= ~0x32; + else + svga->cgastat ^= 0x32; + return svga->cgastat; - case 0x210a: case 0x211a: case 0x212a: case 0x213a: - case 0x214a: case 0x215a: case 0x216a: case 0x217a: - return et4000->index; - case 0x210B: case 0x211B: case 0x212B: case 0x213B: - case 0x214B: case 0x215B: case 0x216B: case 0x217B: - if (et4000->index == 0xec) { - return (et4000->regs[0xec] & 0xf) | (et4000->rev << 4); - } - if (et4000->index == 0xee) { - if (svga->bpp == 8) { - if ((svga->gdcreg[5] & 0x60) >= 0x40) - return 3; - else if ((svga->gdcreg[5] & 0x60) == 0x20) - return 1; - else - return 2; - } else if (svga->bpp == 15 || svga->bpp == 16) - return 4; - else - break; - } - if (et4000->index == 0xef) { - if (et4000->type >= ET4000W32P_REVC) - return (et4000->regs[0xef] & 0x0f) | (et4000->rev << 4) | et4000->pci; - else - return (et4000->regs[0xef] & 0x8f) | (et4000->rev << 4) | et4000->vlb; - } - return et4000->regs[et4000->index]; + case 0x210a: + case 0x211a: + case 0x212a: + case 0x213a: + case 0x214a: + case 0x215a: + case 0x216a: + case 0x217a: + return et4000->index; + case 0x210B: + case 0x211B: + case 0x212B: + case 0x213B: + case 0x214B: + case 0x215B: + case 0x216B: + case 0x217B: + if (et4000->index == 0xec) { + return (et4000->regs[0xec] & 0xf) | (et4000->rev << 4); + } + if (et4000->index == 0xee) { + if (svga->bpp == 8) { + if ((svga->gdcreg[5] & 0x60) >= 0x40) + return 3; + else if ((svga->gdcreg[5] & 0x60) == 0x20) + return 1; + else + return 2; + } else if (svga->bpp == 15 || svga->bpp == 16) + return 4; + else + break; + } + if (et4000->index == 0xef) { + if (et4000->pci) + return (et4000->regs[0xef] & 0x0f) | (et4000->rev << 4) | et4000->pci; + else + return (et4000->regs[0xef] & 0x8f) | (et4000->rev << 4) | et4000->vlb; + } + return et4000->regs[et4000->index]; + + default: + break; } return svga_in(addr, svga); } - void et4000w32p_recalctimings(svga_t *svga) { - et4000w32p_t *et4000 = (et4000w32p_t *)svga->p; + et4000w32p_t *et4000 = (et4000w32p_t *) svga->priv; svga->ma_latch |= (svga->crtc[0x33] & 0x7) << 16; - if (svga->crtc[0x35] & 0x01) svga->vblankstart += 0x400; - if (svga->crtc[0x35] & 0x02) svga->vtotal += 0x400; - if (svga->crtc[0x35] & 0x04) svga->dispend += 0x400; - if (svga->crtc[0x35] & 0x08) svga->vsyncstart += 0x400; - if (svga->crtc[0x35] & 0x10) svga->split += 0x400; - if (svga->crtc[0x3F] & 0x80) svga->rowoffset += 0x100; - if (svga->crtc[0x3F] & 0x01) svga->htotal += 256; - if (svga->attrregs[0x16] & 0x20) svga->hdisp <<= 1; + if (svga->crtc[0x35] & 0x01) + svga->vblankstart += 0x400; + if (svga->crtc[0x35] & 0x02) + svga->vtotal += 0x400; + if (svga->crtc[0x35] & 0x04) + svga->dispend += 0x400; + if (svga->crtc[0x35] & 0x08) + svga->vsyncstart += 0x400; + if (svga->crtc[0x35] & 0x10) + svga->split += 0x400; + if (svga->crtc[0x3F] & 0x80) + svga->rowoffset += 0x100; + if (svga->crtc[0x3F] & 0x01) + svga->htotal += 256; + if (svga->attrregs[0x16] & 0x20) + svga->hdisp <<= 1; - svga->clock = (cpuclock * (double)(1ull << 32)) / svga->getclock((svga->miscout >> 2) & 3, svga->clock_gen); + svga->clock = (cpuclock * (double) (1ULL << 32)) / svga->getclock((svga->miscout >> 2) & 3, svga->clock_gen); - if (et4000->type != ET4000W32P_DIAMOND) { - if ((svga->gdcreg[6] & 1) || (svga->attrregs[0x10] & 1)) { - if (svga->gdcreg[5] & 0x40) { - switch (svga->bpp) { - case 8: - svga->clock /= 2; - break; - case 15: case 16: - svga->clock /= 3; - break; - case 24: - svga->clock /= 4; - break; - } - } - } - } + if (et4000->type != ET4000W32P_DIAMOND) { + if ((svga->gdcreg[6] & 1) || (svga->attrregs[0x10] & 1)) { + if (svga->gdcreg[5] & 0x40) { + switch (svga->bpp) { + case 8: + svga->clock /= 2; + break; + case 15: + case 16: + svga->clock /= 3; + break; + case 24: + svga->clock /= 4; + break; - if (svga->adv_flags & FLAG_NOSKEW) { - /* On the Cardex ET4000/W32p-based cards, adjust text mode clocks by 1. */ - if (!(svga->gdcreg[6] & 1) && !(svga->attrregs[0x10] & 1)) { /* Text mode */ - svga->ma_latch--; - - if ((svga->seqregs[1] & 8)) /*40 column*/ - svga->hdisp += (svga->seqregs[1] & 1) ? 16 : 18; - else - svga->hdisp += (svga->seqregs[1] & 1) ? 8 : 9; - } else { - /* Also adjust the graphics mode clocks in some cases. */ - if ((svga->gdcreg[5] & 0x40) && (svga->bpp != 32)) { - if ((svga->bpp == 15) || (svga->bpp == 16) || (svga->bpp == 24)) - svga->hdisp += (svga->seqregs[1] & 1) ? 16 : 18; - else - svga->hdisp += (svga->seqregs[1] & 1) ? 8 : 9; - } else if ((svga->gdcreg[5] & 0x40) == 0) - svga->hdisp += (svga->seqregs[1] & 1) ? 8 : 9; - } + default: + break; + } + } + } } - if (et4000->type == ET4000W32) { - if ((svga->gdcreg[6] & 1) || (svga->attrregs[0x10] & 1)) { - if (svga->gdcreg[5] & 0x40) { - switch (svga->bpp) { - case 8: - if (svga->hdisp == 640 || svga->hdisp == 800 || svga->hdisp == 1024) - break; - svga->hdisp -= 24; - break; - } - } - } - } + if (svga->adv_flags & FLAG_NOSKEW) { + /* On the Cardex ET4000/W32p-based cards, adjust text mode clocks by 1. */ + if (!(svga->gdcreg[6] & 1) && !(svga->attrregs[0x10] & 1)) { /* Text mode */ + svga->ma_latch--; + + if (svga->seqregs[1] & 8) /*40 column*/ + svga->hdisp += (svga->seqregs[1] & 1) ? 16 : 18; + else + svga->hdisp += (svga->seqregs[1] & 1) ? 8 : 9; + } else { + /* Also adjust the graphics mode clocks in some cases. */ + if ((svga->gdcreg[5] & 0x40) && (svga->bpp != 32)) { + if ((svga->bpp == 15) || (svga->bpp == 16) || (svga->bpp == 24)) + svga->hdisp += (svga->seqregs[1] & 1) ? 16 : 18; + else + svga->hdisp += (svga->seqregs[1] & 1) ? 8 : 9; + } else if ((svga->gdcreg[5] & 0x40) == 0) { + svga->hdisp += (svga->seqregs[1] & 1) ? 8 : 9; + if (svga->hdisp == 648 || svga->hdisp == 808 || svga->hdisp == 1032) + svga->hdisp -= 8; + } + } + } + + if (et4000->type == ET4000W32) { + if ((svga->gdcreg[6] & 1) || (svga->attrregs[0x10] & 1)) { + if (svga->gdcreg[5] & 0x40) { + switch (svga->bpp) { + case 8: + if (svga->hdisp == 640 || svga->hdisp == 800 || svga->hdisp == 1024) + break; + svga->hdisp -= 24; + break; + + default: + break; + } + } + } + } et4000->adjust_cursor = 0; - - switch (svga->bpp) { - case 15: case 16: - svga->hdisp >>= 1; - if (et4000->type <= ET4000W32P_REVC) { - if (et4000->type == ET4000W32P_REVC) { - if (svga->hdisp != 1024) - et4000->adjust_cursor = 1; - } else - et4000->adjust_cursor = 1; - } - break; - case 24: - svga->hdisp /= 3; - if (et4000->type <= ET4000W32P_REVC) - et4000->adjust_cursor = 2; - if (et4000->type == ET4000W32P_DIAMOND && (svga->hdisp == 640/2 || svga->hdisp == 1232)) { - svga->hdisp = 640; - } - break; - } + + switch (svga->bpp) { + case 15: + case 16: + if ((svga->gdcreg[6] & 1) || (svga->attrregs[0x10] & 1)) + svga->hdisp >>= 1; + if (et4000->type <= ET4000W32P_REVC) { + if (et4000->type == ET4000W32P_REVC) { + if (svga->hdisp != 1024) + et4000->adjust_cursor = 1; + } else + et4000->adjust_cursor = 1; + } + break; + case 24: + svga->hdisp /= 3; + if (et4000->type <= ET4000W32P_REVC) + et4000->adjust_cursor = 2; + if ((et4000->type == ET4000W32P_DIAMOND) && ((svga->hdisp == (640 / 2)) || (svga->hdisp == 1232))) { + svga->hdisp = 640; + } + break; + + default: + break; + } svga->render = svga_render_blank; if (!svga->scrblank && svga->attr_palette_enable) { - if (!(svga->gdcreg[6] & 1) && !(svga->attrregs[0x10] & 1)) { /* Text mode */ - if (svga->seqregs[1] & 8) /* 40 column */ - svga->render = svga_render_text_40; - else - svga->render = svga_render_text_80; - } else { - if (svga->adv_flags & FLAG_NOSKEW) - svga->ma_latch--; + if (!(svga->gdcreg[6] & 1) && !(svga->attrregs[0x10] & 1)) { /* Text mode */ + if (svga->seqregs[1] & 8) /* 40 column */ + svga->render = svga_render_text_40; + else + svga->render = svga_render_text_80; + } else { + if (svga->adv_flags & FLAG_NOSKEW) { + svga->ma_latch--; + } - 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 */ - if (et4000->type <= ET4000W32P_REVC) - svga->clock /= 2; + switch (svga->gdcreg[5] & 0x60) { + case 0x00: + if (et4000->rev == 5) + svga->ma_latch++; - 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; - break; - case 15: - if (svga->lowres || (svga->seqregs[1] & 8)) - svga->render = svga_render_15bpp_lowres; - else - svga->render = svga_render_15bpp_highres; - break; - case 16: - if (svga->lowres || (svga->seqregs[1] & 8)) - svga->render = svga_render_16bpp_lowres; - else - svga->render = svga_render_16bpp_highres; - break; - case 17: - if (svga->lowres || (svga->seqregs[1] & 8)) - svga->render = svga_render_15bpp_mix_lowres; - else - svga->render = svga_render_15bpp_mix_highres; - break; - case 24: - if (svga->lowres || (svga->seqregs[1] & 8)) - svga->render = svga_render_24bpp_lowres; - else - svga->render = svga_render_24bpp_highres; - break; - case 32: - if (svga->lowres || (svga->seqregs[1] & 8)) - svga->render = svga_render_32bpp_lowres; - else - svga->render = svga_render_32bpp_highres; - break; - } - break; - } - } + 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 */ + if (et4000->type <= ET4000W32P_REVC) + svga->clock /= 2; + + 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; + break; + case 15: + if (svga->lowres || (svga->seqregs[1] & 8)) + svga->render = svga_render_15bpp_lowres; + else + svga->render = svga_render_15bpp_highres; + break; + case 16: + if (svga->lowres || (svga->seqregs[1] & 8)) + svga->render = svga_render_16bpp_lowres; + else + svga->render = svga_render_16bpp_highres; + break; + case 17: + if (svga->lowres || (svga->seqregs[1] & 8)) + svga->render = svga_render_15bpp_mix_lowres; + else + svga->render = svga_render_15bpp_mix_highres; + break; + case 24: + if (svga->lowres || (svga->seqregs[1] & 8)) + svga->render = svga_render_24bpp_lowres; + else + svga->render = svga_render_24bpp_highres; + break; + case 32: + if (svga->lowres || (svga->seqregs[1] & 8)) + svga->render = svga_render_32bpp_lowres; + else + svga->render = svga_render_32bpp_highres; + break; + + default: + break; + } + break; + + default: + break; + } + } } } - void et4000w32p_recalcmapping(et4000w32p_t *et4000) { svga_t *svga = &et4000->svga; - int map; + int map; if (et4000->pci && !(et4000->pci_regs[PCI_REG_COMMAND] & PCI_COMMAND_MEM)) { - mem_mapping_disable(&svga->mapping); - mem_mapping_disable(&et4000->linear_mapping); - mem_mapping_disable(&et4000->mmu_mapping); - return; + mem_mapping_disable(&svga->mapping); + mem_mapping_disable(&et4000->linear_mapping); + mem_mapping_disable(&et4000->mmu_mapping); + return; } - if (svga->crtc[0x36] & 0x10) { /* Linear frame buffer */ - mem_mapping_set_addr(&et4000->linear_mapping, et4000->linearbase, 0x200000); - mem_mapping_disable(&svga->mapping); - mem_mapping_disable(&et4000->mmu_mapping); + if (svga->crtc[0x36] & 0x10) { /* Linear frame buffer */ + mem_mapping_set_addr(&et4000->linear_mapping, et4000->linearbase, 0x200000); + mem_mapping_disable(&svga->mapping); + mem_mapping_disable(&et4000->mmu_mapping); } else { - map = (svga->gdcreg[6] & 0xc) >> 2; - if (svga->crtc[0x36] & 0x20) map |= 4; - if (svga->crtc[0x36] & 0x08) map |= 8; - mem_mapping_disable(&et4000->linear_mapping); - switch (map) { - case 0x0: case 0x4: case 0x8: case 0xc: /* 128k at A0000 */ - mem_mapping_set_addr(&svga->mapping, 0xa0000, 0x20000); - mem_mapping_disable(&et4000->mmu_mapping); - svga->banked_mask = 0x1ffff; - break; - case 0x1: /* 64k at A0000 */ - mem_mapping_set_addr(&svga->mapping, 0xa0000, 0x10000); - mem_mapping_disable(&et4000->mmu_mapping); - svga->banked_mask = 0xffff; - break; - case 0x2: /* 32k at B0000 */ - mem_mapping_set_addr(&svga->mapping, 0xb0000, 0x08000); - mem_mapping_disable(&et4000->mmu_mapping); - svga->banked_mask = 0x7fff; - break; - case 0x3: /* 32k at B8000 */ - mem_mapping_set_addr(&svga->mapping, 0xb8000, 0x08000); - mem_mapping_disable(&et4000->mmu_mapping); - svga->banked_mask = 0x7fff; - break; - case 0x5: case 0x9: case 0xd: /* 64k at A0000, MMU at B8000 */ - mem_mapping_set_addr(&svga->mapping, 0xa0000, 0x10000); - mem_mapping_set_addr(&et4000->mmu_mapping, 0xb8000, 0x08000); - svga->banked_mask = 0xffff; - break; - case 0x6: case 0xa: case 0xe: /* 32k at B0000, MMU at A8000 */ - mem_mapping_set_addr(&svga->mapping, 0xb0000, 0x08000); - mem_mapping_set_addr(&et4000->mmu_mapping, 0xa8000, 0x08000); - svga->banked_mask = 0x7fff; - break; - case 0x7: case 0xb: case 0xf: /* 32k at B8000, MMU at A8000 */ - mem_mapping_set_addr(&svga->mapping, 0xb8000, 0x08000); - mem_mapping_set_addr(&et4000->mmu_mapping, 0xa8000, 0x08000); - svga->banked_mask = 0x7fff; - break; - } + map = (svga->gdcreg[6] & 0xc) >> 2; + if (svga->crtc[0x36] & 0x20) + map |= 4; + if (svga->crtc[0x36] & 0x08) + map |= 8; + mem_mapping_disable(&et4000->linear_mapping); + switch (map) { + case 0x0: + case 0x4: + case 0x8: + case 0xc: /* 128k at A0000 */ + mem_mapping_set_addr(&svga->mapping, 0xa0000, 0x20000); + mem_mapping_disable(&et4000->mmu_mapping); + svga->banked_mask = 0x1ffff; + break; + case 0x1: /* 64k at A0000 */ + mem_mapping_set_addr(&svga->mapping, 0xa0000, 0x10000); + mem_mapping_disable(&et4000->mmu_mapping); + svga->banked_mask = 0xffff; + break; + case 0x2: /* 32k at B0000 */ + mem_mapping_set_addr(&svga->mapping, 0xb0000, 0x08000); + mem_mapping_disable(&et4000->mmu_mapping); + svga->banked_mask = 0x7fff; + break; + case 0x3: /* 32k at B8000 */ + mem_mapping_set_addr(&svga->mapping, 0xb8000, 0x08000); + mem_mapping_disable(&et4000->mmu_mapping); + svga->banked_mask = 0x7fff; + break; + case 0x5: + case 0x9: + case 0xd: /* 64k at A0000, MMU at B8000 */ + mem_mapping_set_addr(&svga->mapping, 0xa0000, 0x10000); + mem_mapping_set_addr(&et4000->mmu_mapping, 0xb8000, 0x08000); + svga->banked_mask = 0xffff; + break; + case 0x6: + case 0xa: + case 0xe: /* 32k at B0000, MMU at A8000 */ + mem_mapping_set_addr(&svga->mapping, 0xb0000, 0x08000); + mem_mapping_set_addr(&et4000->mmu_mapping, 0xa8000, 0x08000); + svga->banked_mask = 0x7fff; + break; + case 0x7: + case 0xb: + case 0xf: /* 32k at B8000, MMU at A8000 */ + mem_mapping_set_addr(&svga->mapping, 0xb8000, 0x08000); + mem_mapping_set_addr(&et4000->mmu_mapping, 0xa8000, 0x08000); + svga->banked_mask = 0x7fff; + break; + + default: + break; + } } if (!et4000->interleaved && (svga->crtc[0x32] & 0x80)) - mem_mapping_disable(&svga->mapping); + mem_mapping_disable(&svga->mapping); } - static void et4000w32p_accel_write_fifo(et4000w32p_t *et4000, uint32_t addr, uint8_t val) { - et4000->acl.fifo_queue++; + et4000->acl.fifo_queue++; switch (addr & 0xff) { - case 0x80: - et4000->acl.queued.pattern_addr = (et4000->acl.queued.pattern_addr & 0x3fff00) | val; - break; - case 0x81: - et4000->acl.queued.pattern_addr = (et4000->acl.queued.pattern_addr & 0x3f00ff) | (val << 8); - break; - case 0x82: - et4000->acl.queued.pattern_addr = (et4000->acl.queued.pattern_addr & 0x00ffff) | ((val & 0x3f) << 16); - break; - case 0x84: - et4000->acl.queued.source_addr = (et4000->acl.queued.source_addr & 0x3fff00) | val; - break; - case 0x85: - et4000->acl.queued.source_addr = (et4000->acl.queued.source_addr & 0x3f00ff) | (val << 8); - break; - case 0x86: - et4000->acl.queued.source_addr = (et4000->acl.queued.source_addr & 0x00ffff) | ((val & 0x3f) << 16); - break; - case 0x88: - et4000->acl.queued.pattern_off = (et4000->acl.queued.pattern_off & 0x0f00) | val; - break; - case 0x89: - et4000->acl.queued.pattern_off = (et4000->acl.queued.pattern_off & 0x00ff) | ((val & 0x0f) << 8); - break; - case 0x8a: - et4000->acl.queued.source_off = (et4000->acl.queued.source_off & 0x0f00) | val; - break; - case 0x8b: - et4000->acl.queued.source_off = (et4000->acl.queued.source_off & 0x00ff) | ((val & 0x0f) << 8); - break; - case 0x8c: - et4000->acl.queued.dest_off = (et4000->acl.queued.dest_off & 0x0f00) | val; - break; - case 0x8d: - et4000->acl.queued.dest_off = (et4000->acl.queued.dest_off & 0x00ff) | ((val & 0x0f) << 8); - break; - case 0x8e: - if (et4000->type >= ET4000W32P_REVC) - et4000->acl.queued.pixel_depth = val & 0x30; - else - et4000->acl.queued.vbus = val & 0x03; - break; - case 0x8f: - if (et4000->type >= ET4000W32P_REVC) - et4000->acl.queued.xy_dir = val & 0xb7; - else - et4000->acl.queued.xy_dir = val & 0x03; - break; - case 0x90: - et4000->acl.queued.pattern_wrap = val & 0x77; - break; - case 0x92: - et4000->acl.queued.source_wrap = val & 0x77; - break; - case 0x98: - et4000->acl.queued.count_x = (et4000->acl.queued.count_x & 0x0f00) | val; - break; - case 0x99: - et4000->acl.queued.count_x = (et4000->acl.queued.count_x & 0x00ff) | ((val & 0x0f) << 8); - break; - case 0x9a: - et4000->acl.queued.count_y = (et4000->acl.queued.count_y & 0x0f00) | val; - break; - case 0x9b: - et4000->acl.queued.count_y = (et4000->acl.queued.count_y & 0x00ff) | ((val & 0x0f) << 8); - break; - case 0x9c: - if (et4000->type >= ET4000W32P_REVC) - et4000->acl.queued.ctrl_routing = val & 0xdb; - else - et4000->acl.queued.ctrl_routing = val & 0xb7; - break; - case 0x9d: - et4000->acl.queued.ctrl_reload = val & 0x03; - break; - case 0x9e: - et4000->acl.queued.rop_bg = val; - break; - case 0x9f: - et4000->acl.queued.rop_fg = val; - break; - case 0xa0: - et4000->acl.queued.dest_addr = (et4000->acl.queued.dest_addr & 0x3fff00) | val; - break; - case 0xa1: - et4000->acl.queued.dest_addr = (et4000->acl.queued.dest_addr & 0x3f00ff) | (val << 8); - break; - case 0xa2: - et4000->acl.queued.dest_addr = (et4000->acl.queued.dest_addr & 0x00ffff) | ((val & 0x3f) << 16); - break; - case 0xa3: - et4000->acl.internal = et4000->acl.queued; - if (et4000->type >= ET4000W32P_REVC) { - et4000w32p_blit_start(et4000); - et4000w32_log("Destination Address write and start XY Block, xcnt = %i, ycnt = %i\n", et4000->acl.x_count + 1, et4000->acl.y_count + 1); - if (!(et4000->acl.queued.ctrl_routing & 0x43)) { - et4000w32p_blit(0xffffff, ~0, 0, 0, et4000); - } - if ((et4000->acl.queued.ctrl_routing & 0x40) && !(et4000->acl.internal.ctrl_routing & 3)) { - et4000w32p_blit(4, ~0, 0, 0, et4000); - } - } else { - et4000w32_blit_start(et4000); - et4000->acl.cpu_input_num = 0; - if (!(et4000->acl.queued.ctrl_routing & 0x37)) { - et4000w32_blit(-1, 0, 0, 0xffffffff, et4000); - } - } - break; - case 0xa4: - et4000->acl.queued.mix_addr = (et4000->acl.queued.mix_addr & 0xFFFFFF00) | val; - break; - case 0xa5: - et4000->acl.queued.mix_addr = (et4000->acl.queued.mix_addr & 0xFFFF00FF) | (val << 8); - break; - case 0xa6: - et4000->acl.queued.mix_addr = (et4000->acl.queued.mix_addr & 0xFF00FFFF) | (val << 16); - break; - case 0xa7: - et4000->acl.queued.mix_addr = (et4000->acl.queued.mix_addr & 0x00FFFFFF) | (val << 24); - break; - case 0xa8: - et4000->acl.queued.mix_off = (et4000->acl.queued.mix_off & 0xFF00) | val; - break; - case 0xa9: - et4000->acl.queued.mix_off = (et4000->acl.queued.mix_off & 0x00FF) | (val << 8); - break; - case 0xaa: - et4000->acl.queued.error = (et4000->acl.queued.error & 0xFF00) | val; - break; - case 0xab: - et4000->acl.queued.error = (et4000->acl.queued.error & 0x00FF) | (val << 8); - break; - case 0xac: - et4000->acl.queued.dmin = (et4000->acl.queued.dmin & 0xFF00) | val; - break; - case 0xad: - et4000->acl.queued.dmin = (et4000->acl.queued.dmin & 0x00FF) | (val << 8); - break; - case 0xae: - et4000->acl.queued.dmaj = (et4000->acl.queued.dmaj & 0xFF00) | val; - break; - case 0xaf: - et4000->acl.queued.dmaj = (et4000->acl.queued.dmaj & 0x00FF) | (val << 8); - break; + case 0x80: + et4000->acl.queued.pattern_addr = (et4000->acl.queued.pattern_addr & 0xffffff00) | val; + break; + case 0x81: + et4000->acl.queued.pattern_addr = (et4000->acl.queued.pattern_addr & 0xffff00ff) | (val << 8); + break; + case 0x82: + et4000->acl.queued.pattern_addr = (et4000->acl.queued.pattern_addr & 0xff00ffff) | (val << 16); + break; + case 0x83: + et4000->acl.queued.pattern_addr = (et4000->acl.queued.pattern_addr & 0x00ffffff) | (val << 24); + break; + case 0x84: + et4000->acl.queued.source_addr = (et4000->acl.queued.source_addr & 0xffffff00) | val; + break; + case 0x85: + et4000->acl.queued.source_addr = (et4000->acl.queued.source_addr & 0xffff00ff) | (val << 8); + break; + case 0x86: + et4000->acl.queued.source_addr = (et4000->acl.queued.source_addr & 0xff00ffff) | (val << 16); + break; + case 0x87: + et4000->acl.queued.source_addr = (et4000->acl.queued.source_addr & 0x00ffffff) | (val << 24); + break; + case 0x88: + et4000->acl.queued.pattern_off = (et4000->acl.queued.pattern_off & 0xff00) | val; + break; + case 0x89: + et4000->acl.queued.pattern_off = (et4000->acl.queued.pattern_off & 0x00ff) | (val << 8); + break; + case 0x8a: + et4000->acl.queued.source_off = (et4000->acl.queued.source_off & 0xff00) | val; + break; + case 0x8b: + et4000->acl.queued.source_off = (et4000->acl.queued.source_off & 0x00ff) | (val << 8); + break; + case 0x8c: + et4000->acl.queued.dest_off = (et4000->acl.queued.dest_off & 0xff00) | val; + break; + case 0x8d: + et4000->acl.queued.dest_off = (et4000->acl.queued.dest_off & 0x00ff) | (val << 8); + break; + case 0x8e: + if (et4000->type >= ET4000W32P_REVC) + et4000->acl.queued.pixel_depth = val & 0x30; + else + et4000->acl.queued.vbus = val & 0x03; + break; + case 0x8f: + if (et4000->type >= ET4000W32P_REVC) + et4000->acl.queued.xy_dir = val & 0xb7; + else + et4000->acl.queued.xy_dir = val & 0x03; + break; + case 0x90: + et4000->acl.queued.pattern_wrap = val & 0x77; + break; + case 0x92: + et4000->acl.queued.source_wrap = val & 0x77; + break; + case 0x98: + et4000->acl.queued.count_x = (et4000->acl.queued.count_x & 0xff00) | val; + break; + case 0x99: + et4000->acl.queued.count_x = (et4000->acl.queued.count_x & 0x00ff) | (val << 8); + break; + case 0x9a: + et4000->acl.queued.count_y = (et4000->acl.queued.count_y & 0xff00) | val; + break; + case 0x9b: + et4000->acl.queued.count_y = (et4000->acl.queued.count_y & 0x00ff) | (val << 8); + break; + case 0x9c: + if (et4000->type >= ET4000W32P_REVC) + et4000->acl.queued.ctrl_routing = val & 0xdb; + else + et4000->acl.queued.ctrl_routing = val & 0xb7; + break; + case 0x9d: + et4000->acl.queued.ctrl_reload = val & 0x03; + break; + case 0x9e: + et4000->acl.queued.rop_bg = val; + break; + case 0x9f: + et4000->acl.queued.rop_fg = val; + break; + case 0xa0: + et4000->acl.queued.dest_addr = (et4000->acl.queued.dest_addr & 0xffffff00) | val; + break; + case 0xa1: + et4000->acl.queued.dest_addr = (et4000->acl.queued.dest_addr & 0xffff00ff) | (val << 8); + break; + case 0xa2: + et4000->acl.queued.dest_addr = (et4000->acl.queued.dest_addr & 0xff00ffff) | (val << 16); + break; + case 0xa3: + et4000->acl.queued.dest_addr = (et4000->acl.queued.dest_addr & 0x00ffffff) | (val << 24); + et4000->acl.internal = et4000->acl.queued; + if (et4000->type >= ET4000W32P_REVC) { + et4000w32p_blit_start(et4000); + et4000w32_log("Destination Address write and start XY Block, xcnt = %i, ycnt = %i\n", et4000->acl.x_count + 1, et4000->acl.y_count + 1); + if (!(et4000->acl.queued.ctrl_routing & 0x43)) { + et4000w32p_blit(0xffffff, ~0, 0, 0, et4000); + } + if ((et4000->acl.queued.ctrl_routing & 0x40) && !(et4000->acl.internal.ctrl_routing & 3)) { + et4000w32p_blit(4, ~0, 0, 0, et4000); + } + } else { + et4000w32_blit_start(et4000); + et4000->acl.cpu_input_num = 0; + if (!(et4000->acl.queued.ctrl_routing & 0x37)) { + et4000->acl.mmu_start = 1; + et4000w32_blit(-1, 0, 0, 0xffffffff, et4000); + } else + et4000->acl.mmu_start = 0; + } + break; + case 0xa4: + et4000->acl.queued.mix_addr = (et4000->acl.queued.mix_addr & 0xFFFFFF00) | val; + break; + case 0xa5: + et4000->acl.queued.mix_addr = (et4000->acl.queued.mix_addr & 0xFFFF00FF) | (val << 8); + break; + case 0xa6: + et4000->acl.queued.mix_addr = (et4000->acl.queued.mix_addr & 0xFF00FFFF) | (val << 16); + break; + case 0xa7: + et4000->acl.queued.mix_addr = (et4000->acl.queued.mix_addr & 0x00FFFFFF) | (val << 24); + break; + case 0xa8: + et4000->acl.queued.mix_off = (et4000->acl.queued.mix_off & 0xFF00) | val; + break; + case 0xa9: + et4000->acl.queued.mix_off = (et4000->acl.queued.mix_off & 0x00FF) | (val << 8); + break; + case 0xaa: + et4000->acl.queued.error = (et4000->acl.queued.error & 0xFF00) | val; + break; + case 0xab: + et4000->acl.queued.error = (et4000->acl.queued.error & 0x00FF) | (val << 8); + break; + case 0xac: + et4000->acl.queued.dmin = (et4000->acl.queued.dmin & 0xFF00) | val; + break; + case 0xad: + et4000->acl.queued.dmin = (et4000->acl.queued.dmin & 0x00FF) | (val << 8); + break; + case 0xae: + et4000->acl.queued.dmaj = (et4000->acl.queued.dmaj & 0xFF00) | val; + break; + case 0xaf: + et4000->acl.queued.dmaj = (et4000->acl.queued.dmaj & 0x00FF) | (val << 8); + break; + + default: + break; } } @@ -778,338 +873,402 @@ static void et4000w32p_accel_write_mmu(et4000w32p_t *et4000, uint32_t addr, uint8_t val, uint8_t bank) { if (et4000->type >= ET4000W32P_REVC) { - if (!(et4000->acl.status & ACL_XYST)) { - et4000w32_log("XY MMU block not started\n"); - return; - } - if (et4000->acl.internal.ctrl_routing & 3) { - et4000->acl.fifo_queue++; - if ((et4000->acl.internal.ctrl_routing & 3) == 2) /*CPU data is Mix data*/ - et4000w32p_blit(8 - (et4000->acl.mix_addr & 7), val >> (et4000->acl.mix_addr & 7), 0, 1, et4000); - else if ((et4000->acl.internal.ctrl_routing & 3) == 1) /*CPU data is Source data*/ - et4000w32p_blit(1, ~0, val, 2, et4000); - } + if (!(et4000->acl.status & ACL_XYST)) { + et4000w32_log("XY MMU block not started\n"); + return; + } + if (et4000->acl.internal.ctrl_routing & 3) { + et4000->acl.fifo_queue++; + if ((et4000->acl.internal.ctrl_routing & 3) == 2) /*CPU data is Mix data*/ + et4000w32p_blit(8 - (et4000->acl.mix_addr & 7), val >> (et4000->acl.mix_addr & 7), 0, 1, et4000); + else if ((et4000->acl.internal.ctrl_routing & 3) == 1) /*CPU data is Source data*/ + et4000w32p_blit(1, ~0, val, 2, et4000); + } } else { - if (!(et4000->acl.status & ACL_XYST)) { - et4000->acl.fifo_queue++; - et4000->acl.queued.dest_addr = ((addr & 0x1fff) + et4000->mmu.base[bank]); - et4000->acl.internal = et4000->acl.queued; - et4000w32_blit_start(et4000); - et4000w32_log("Accelerated MMU aperture = %i and start XY Block (Implicit), xcnt = %i, ycnt = %i\n", bank, et4000->acl.x_count + 1, et4000->acl.y_count + 1); - et4000->acl.cpu_input_num = 0; - if (!(et4000->acl.queued.ctrl_routing & 0x37)) { - et4000w32_blit(-1, 0, 0, 0xffffffff, et4000); - } - } + if (!(et4000->acl.status & ACL_XYST)) { + et4000->acl.fifo_queue++; + et4000->acl.queued.dest_addr = ((addr & 0x1fff) + et4000->mmu.base[bank]); + et4000->acl.internal = et4000->acl.queued; + et4000w32_blit_start(et4000); + et4000w32_log("ET4000W32 Accelerated MMU aperture start XY Block (Implicit): bank = %i, patx = %i, paty = %i, wrap x = %i, wrap y = %i\n", et4000->bank, et4000->acl.pattern_x, et4000->acl.pattern_y, et4000w32_wrap_x[et4000->acl.internal.pattern_wrap & 7], et4000w32_wrap_y[(et4000->acl.internal.pattern_wrap >> 4) & 7]); + et4000->acl.cpu_input_num = 0; + if (!(et4000->acl.queued.ctrl_routing & 0x37)) { + et4000->acl.mmu_start = 1; + et4000w32_blit(-1, 0, 0, 0xffffffff, et4000); + } else { + et4000->acl.mmu_start = 0; + } + } - if (et4000->acl.internal.ctrl_routing & 7) { - et4000->acl.fifo_queue++; - et4000->acl.cpu_input = (et4000->acl.cpu_input & ~(0xff << (et4000->acl.cpu_input_num << 3))) | - (val << (et4000->acl.cpu_input_num << 3)); - et4000->acl.cpu_input_num++; + if (et4000->acl.internal.ctrl_routing & 7) { + et4000->acl.fifo_queue++; + et4000->acl.cpu_input = (et4000->acl.cpu_input & ~(0xff << (et4000->acl.cpu_input_num << 3))) | (val << (et4000->acl.cpu_input_num << 3)); + et4000->acl.cpu_input_num++; - if (et4000->acl.cpu_input_num == et4000w32_vbus[et4000->acl.internal.vbus]) { - if ((et4000->acl.internal.ctrl_routing & 7) == 2) /*CPU data is Mix data*/ - et4000w32_blit(et4000->acl.cpu_input_num << 3, 2, 0, et4000->acl.cpu_input, et4000); - else if ((et4000->acl.internal.ctrl_routing & 7) == 1) /*CPU data is Source data*/ - et4000w32_blit(et4000->acl.cpu_input_num, 1, et4000->acl.cpu_input, 0xffffffff, et4000); + if (et4000->acl.cpu_input_num == et4000w32_vbus[et4000->acl.internal.vbus]) { + if ((et4000->acl.internal.ctrl_routing & 7) == 2) /*CPU data is Mix data*/ + et4000w32_blit(et4000->acl.cpu_input_num << 3, 2, 0, et4000->acl.cpu_input, et4000); + else if ((et4000->acl.internal.ctrl_routing & 7) == 1) /*CPU data is Source data*/ + et4000w32_blit(et4000->acl.cpu_input_num, 1, et4000->acl.cpu_input, 0xffffffff, et4000); - et4000->acl.cpu_input_num = 0; - } - - if ((et4000->acl.internal.ctrl_routing & 7) == 4) /*CPU data is X Count*/ - et4000w32_blit(val | (et4000->acl.queued.count_x << 8), 0, 0, 0xffffffff, et4000); - if ((et4000->acl.internal.ctrl_routing & 7) == 5) /*CPU data is Y Count*/ - et4000w32_blit(val | (et4000->acl.queued.count_y << 8), 0, 0, 0xffffffff, et4000); - } + et4000->acl.cpu_input_num = 0; + } + + if (et4000w32_vbus[et4000->acl.internal.vbus] == 1) { + if ((et4000->acl.internal.ctrl_routing & 7) == 4) { /*CPU data is X Count*/ + et4000w32_log("ET4000W32 Accelerated MMU aperture routing = %02x: val = %02x, cx = %02x.\n", et4000->acl.internal.ctrl_routing, val, et4000->acl.internal.count_x); + et4000->acl.cpu_x_cnt = val + 1; + et4000->acl.cpu_x_cnt |= ((et4000->acl.queued.count_x >> 8) << 8); + et4000w32_blit(et4000->acl.cpu_x_cnt, 3, 0, 0xffffffff, et4000); + } else if ((et4000->acl.internal.ctrl_routing & 7) == 5) { /*CPU data is Y Count*/ + et4000w32_log("ET4000W32 Accelerated MMU aperture routing = %02x: val = %02x, cy = %02x.\n", et4000->acl.internal.ctrl_routing, val, et4000->acl.internal.count_y); + et4000->acl.cpu_y_cnt = val + 1; + et4000->acl.cpu_y_cnt |= ((et4000->acl.queued.count_y >> 8) << 8); + et4000w32_blit(et4000->acl.cpu_y_cnt, 4, 0, 0xffffffff, et4000); + } + } + } } } static void -et4000w32p_mmu_write(uint32_t addr, uint8_t val, void *p) +et4000w32p_mmu_write(uint32_t addr, uint8_t val, void *priv) { - et4000w32p_t *et4000 = (et4000w32p_t *)p; - svga_t *svga = &et4000->svga; + et4000w32p_t *et4000 = (et4000w32p_t *) priv; + svga_t *svga = &et4000->svga; switch (addr & 0x6000) { - case 0x0000: /* MMU 0 */ - case 0x2000: /* MMU 1 */ - case 0x4000: /* MMU 2 */ - et4000->bank = (addr >> 13) & 3; - if (et4000->mmu.ctrl & (1 << et4000->bank)) { - et4000w32p_accel_write_mmu(et4000, addr & 0x7fff, val, et4000->bank); - } else { - if (((addr & 0x1fff) + et4000->mmu.base[et4000->bank]) < svga->vram_max) { - svga->vram[(addr & 0x1fff) + et4000->mmu.base[et4000->bank]] = val; - svga->changedvram[((addr & 0x1fff) + et4000->mmu.base[et4000->bank]) >> 12] = changeframecount; - } - } - break; - case 0x6000: - if ((addr & 0xff) >= 0x80) { - et4000w32p_accel_write_fifo(et4000, addr & 0x7fff, val); - } else { - switch (addr & 0xff) { - case 0x00: - et4000->mmu.base[0] = (et4000->mmu.base[0] & 0x3fff00) | val; - break; - case 0x01: - et4000->mmu.base[0] = (et4000->mmu.base[0] & 0x3f00ff) | (val << 8); - break; - case 0x02: - et4000->mmu.base[0] = (et4000->mmu.base[0] & 0x00ffff) | ((val & 0x3f) << 16); - break; - case 0x04: - et4000->mmu.base[1] = (et4000->mmu.base[1] & 0x3fff00) | val; - break; - case 0x05: - et4000->mmu.base[1] = (et4000->mmu.base[1] & 0x3f00ff) | (val << 8); - break; - case 0x06: - et4000->mmu.base[1] = (et4000->mmu.base[1] & 0x00ffff) | ((val & 0x3f) << 16); - break; - case 0x08: - et4000->mmu.base[2] = (et4000->mmu.base[2] & 0x3fff00) | val; - break; - case 0x09: - et4000->mmu.base[2] = (et4000->mmu.base[2] & 0x3f00ff) | (val << 8); - break; - case 0x0a: - et4000->mmu.base[2] = (et4000->mmu.base[2] & 0x00ffff) | ((val & 0x3f) << 16); - break; - case 0x13: - et4000->mmu.ctrl = val; - break; - case 0x30: - et4000->acl.suspend_terminate = val; - break; - case 0x31: - et4000->acl.osr = val; - break; - } - } - break; + case 0x0000: /* MMU 0 */ + case 0x2000: /* MMU 1 */ + case 0x4000: /* MMU 2 */ + et4000->bank = (addr >> 13) & 3; + if (et4000->mmu.ctrl & (1 << et4000->bank)) { + et4000w32p_accel_write_mmu(et4000, addr & 0x7fff, val, et4000->bank); + } else { + if (((addr & 0x1fff) + et4000->mmu.base[et4000->bank]) < svga->vram_max) { + svga->vram[((addr & 0x1fff) + et4000->mmu.base[et4000->bank]) & et4000->vram_mask] = val; + svga->changedvram[(((addr & 0x1fff) + et4000->mmu.base[et4000->bank]) & et4000->vram_mask) >> 12] = changeframecount; + } + } + break; + case 0x6000: + if ((addr & 0xff) >= 0x80) { + et4000w32p_accel_write_fifo(et4000, addr & 0x7fff, val); + } else { + switch (addr & 0xff) { + case 0x00: + et4000->mmu.base[0] = (et4000->mmu.base[0] & 0xffffff00) | val; + break; + case 0x01: + et4000->mmu.base[0] = (et4000->mmu.base[0] & 0xffff00ff) | (val << 8); + break; + case 0x02: + et4000->mmu.base[0] = (et4000->mmu.base[0] & 0xff00ffff) | (val << 16); + break; + case 0x03: + et4000->mmu.base[0] = (et4000->mmu.base[0] & 0x00ffffff) | (val << 24); + break; + case 0x04: + et4000->mmu.base[1] = (et4000->mmu.base[1] & 0xffffff00) | val; + break; + case 0x05: + et4000->mmu.base[1] = (et4000->mmu.base[1] & 0xffff00ff) | (val << 8); + break; + case 0x06: + et4000->mmu.base[1] = (et4000->mmu.base[1] & 0xff00ffff) | (val << 16); + break; + case 0x07: + et4000->mmu.base[1] = (et4000->mmu.base[1] & 0x00ffffff) | (val << 24); + break; + case 0x08: + et4000->mmu.base[2] = (et4000->mmu.base[2] & 0xffffff00) | val; + break; + case 0x09: + et4000->mmu.base[2] = (et4000->mmu.base[2] & 0xffff00ff) | (val << 8); + break; + case 0x0a: + et4000->mmu.base[2] = (et4000->mmu.base[2] & 0xff00ffff) | (val << 16); + break; + case 0x0b: + et4000->mmu.base[2] = (et4000->mmu.base[2] & 0x00ffffff) | (val << 24); + break; + case 0x13: + et4000->mmu.ctrl = val; + break; + case 0x30: + et4000->acl.suspend_terminate = val; + break; + case 0x31: + et4000->acl.osr = val; + break; + + default: + break; + } + } + break; + + default: + break; } } static uint8_t -et4000w32p_mmu_read(uint32_t addr, void *p) +et4000w32p_mmu_read(uint32_t addr, void *priv) { - et4000w32p_t *et4000 = (et4000w32p_t *)p; - svga_t *svga = &et4000->svga; - uint8_t temp; - + et4000w32p_t *et4000 = (et4000w32p_t *) priv; + const svga_t *svga = &et4000->svga; + uint8_t temp; + switch (addr & 0x6000) { - case 0x0000: /* MMU 0 */ - case 0x2000: /* MMU 1 */ - case 0x4000: /* MMU 2 */ - et4000->bank = (addr >> 13) & 3; - if (et4000->mmu.ctrl & (1 << et4000->bank)) { - temp = 0xff; - if (et4000->acl.cpu_dat_pos) { - et4000->acl.cpu_dat_pos--; - temp = et4000->acl.cpu_dat & 0xff; - et4000->acl.cpu_dat >>= 8; - } - if ((et4000->acl.queued.ctrl_routing & 0x40) && !et4000->acl.cpu_dat_pos && !(et4000->acl.internal.ctrl_routing & 3)) - et4000w32p_blit(4, ~0, 0, 0, et4000); + case 0x0000: /* MMU 0 */ + case 0x2000: /* MMU 1 */ + case 0x4000: /* MMU 2 */ + et4000->bank = (addr >> 13) & 3; + if (et4000->mmu.ctrl & (1 << et4000->bank)) { + temp = 0xff; + if (et4000->acl.cpu_dat_pos) { + et4000->acl.cpu_dat_pos--; + temp = et4000->acl.cpu_dat & 0xff; + et4000->acl.cpu_dat >>= 8; + } + if ((et4000->acl.queued.ctrl_routing & 0x40) && !et4000->acl.cpu_dat_pos && !(et4000->acl.internal.ctrl_routing & 3)) + et4000w32p_blit(4, ~0, 0, 0, et4000); - /* ???? */ - return temp; - } + /* ???? */ + return temp; + } - if ((addr & 0x1fff) + et4000->mmu.base[et4000->bank] >= svga->vram_max) - return 0xff; - - return svga->vram[(addr & 0x1fff) + et4000->mmu.base[et4000->bank]]; + if ((addr & 0x1fff) + et4000->mmu.base[et4000->bank] >= svga->vram_max) + return 0xff; - case 0x6000: - switch (addr & 0xff) { - case 0x00: - return et4000->mmu.base[0] & 0xff; - case 0x01: - return et4000->mmu.base[0] >> 8; - case 0x02: - return et4000->mmu.base[0] >> 16; - case 0x03: - return et4000->mmu.base[0] >> 24; - case 0x04: - return et4000->mmu.base[1] & 0xff; - case 0x05: - return et4000->mmu.base[1] >> 8; - case 0x06: - return et4000->mmu.base[1] >> 16; - case 0x07: - return et4000->mmu.base[1] >> 24; - case 0x08: - return et4000->mmu.base[2] & 0xff; - case 0x09: - return et4000->mmu.base[2] >> 8; - case 0x0a: - return et4000->mmu.base[2] >> 16; - case 0x0b: - return et4000->mmu.base[2] >> 24; - case 0x13: - return et4000->mmu.ctrl; + return svga->vram[(addr & 0x1fff) + et4000->mmu.base[et4000->bank]]; - case 0x36: - if (et4000->acl.fifo_queue) { - et4000->acl.status |= ACL_RDST; - et4000->acl.fifo_queue = 0; - } else - et4000->acl.status &= ~ACL_RDST; - return et4000->acl.status; + case 0x6000: + switch (addr & 0xff) { + case 0x00: + return et4000->mmu.base[0] & 0xff; + case 0x01: + return et4000->mmu.base[0] >> 8; + case 0x02: + return et4000->mmu.base[0] >> 16; + case 0x03: + return et4000->mmu.base[0] >> 24; + case 0x04: + return et4000->mmu.base[1] & 0xff; + case 0x05: + return et4000->mmu.base[1] >> 8; + case 0x06: + return et4000->mmu.base[1] >> 16; + case 0x07: + return et4000->mmu.base[1] >> 24; + case 0x08: + return et4000->mmu.base[2] & 0xff; + case 0x09: + return et4000->mmu.base[2] >> 8; + case 0x0a: + return et4000->mmu.base[2] >> 16; + case 0x0b: + return et4000->mmu.base[2] >> 24; + case 0x13: + return et4000->mmu.ctrl; - case 0x80: - return et4000->acl.internal.pattern_addr & 0xff; - case 0x81: - return et4000->acl.internal.pattern_addr >> 8; - case 0x82: - return et4000->acl.internal.pattern_addr >> 16; - case 0x83: - return et4000->acl.internal.pattern_addr >> 24; - case 0x84: - return et4000->acl.internal.source_addr & 0xff; - case 0x85: - return et4000->acl.internal.source_addr >> 8; - case 0x86: - return et4000->acl.internal.source_addr >> 16; - case 0x87: - return et4000->acl.internal.source_addr >> 24; - case 0x88: - return et4000->acl.internal.pattern_off & 0xff; - case 0x89: - return et4000->acl.internal.pattern_off >> 8; - case 0x8a: - return et4000->acl.internal.source_off & 0xff; - case 0x8b: - return et4000->acl.internal.source_off >> 8; - case 0x8c: - return et4000->acl.internal.dest_off & 0xff; - case 0x8d: - return et4000->acl.internal.dest_off >> 8; - case 0x8e: - if (et4000->type >= ET4000W32P_REVC) - return et4000->acl.internal.pixel_depth; - else - return et4000->acl.internal.vbus; - break; - case 0x8f: return et4000->acl.internal.xy_dir; - case 0x90: return et4000->acl.internal.pattern_wrap; - case 0x92: return et4000->acl.internal.source_wrap; - case 0x98: return et4000->acl.internal.count_x & 0xff; - case 0x99: return et4000->acl.internal.count_x >> 8; - case 0x9a: return et4000->acl.internal.count_y & 0xff; - case 0x9b: return et4000->acl.internal.count_y >> 8; - case 0x9c: return et4000->acl.internal.ctrl_routing; - case 0x9d: return et4000->acl.internal.ctrl_reload; - case 0x9e: return et4000->acl.internal.rop_bg; - case 0x9f: return et4000->acl.internal.rop_fg; - case 0xa0: return et4000->acl.internal.dest_addr & 0xff; - case 0xa1: return et4000->acl.internal.dest_addr >> 8; - case 0xa2: return et4000->acl.internal.dest_addr >> 16; - case 0xa3: return et4000->acl.internal.dest_addr >> 24; - } + case 0x36: + if (et4000->acl.fifo_queue) { + et4000->acl.status |= ACL_RDST; + et4000->acl.fifo_queue = 0; + } else + et4000->acl.status &= ~ACL_RDST; + return et4000->acl.status; - return 0xff; + case 0x80: + return et4000->acl.internal.pattern_addr & 0xff; + case 0x81: + return et4000->acl.internal.pattern_addr >> 8; + case 0x82: + return et4000->acl.internal.pattern_addr >> 16; + case 0x83: + return et4000->acl.internal.pattern_addr >> 24; + case 0x84: + return et4000->acl.internal.source_addr & 0xff; + case 0x85: + return et4000->acl.internal.source_addr >> 8; + case 0x86: + return et4000->acl.internal.source_addr >> 16; + case 0x87: + return et4000->acl.internal.source_addr >> 24; + case 0x88: + return et4000->acl.internal.pattern_off & 0xff; + case 0x89: + return et4000->acl.internal.pattern_off >> 8; + case 0x8a: + return et4000->acl.internal.source_off & 0xff; + case 0x8b: + return et4000->acl.internal.source_off >> 8; + case 0x8c: + return et4000->acl.internal.dest_off & 0xff; + case 0x8d: + return et4000->acl.internal.dest_off >> 8; + case 0x8e: + if (et4000->type >= ET4000W32P_REVC) + return et4000->acl.internal.pixel_depth; + return et4000->acl.internal.vbus; + case 0x8f: + return et4000->acl.internal.xy_dir; + case 0x90: + return et4000->acl.internal.pattern_wrap; + case 0x92: + return et4000->acl.internal.source_wrap; + case 0x98: + return et4000->acl.internal.count_x & 0xff; + case 0x99: + return et4000->acl.internal.count_x >> 8; + case 0x9a: + return et4000->acl.internal.count_y & 0xff; + case 0x9b: + return et4000->acl.internal.count_y >> 8; + case 0x9c: + return et4000->acl.internal.ctrl_routing; + case 0x9d: + return et4000->acl.internal.ctrl_reload; + case 0x9e: + return et4000->acl.internal.rop_bg; + case 0x9f: + return et4000->acl.internal.rop_fg; + case 0xa0: + return et4000->acl.internal.dest_addr & 0xff; + case 0xa1: + return et4000->acl.internal.dest_addr >> 8; + case 0xa2: + return et4000->acl.internal.dest_addr >> 16; + case 0xa3: + return et4000->acl.internal.dest_addr >> 24; + + default: + break; + } + + return 0xff; + + default: + break; } return 0xff; } - void et4000w32_blit_start(et4000w32p_t *et4000) { - et4000->acl.x_count = et4000->acl.internal.count_x; - et4000->acl.y_count = et4000->acl.internal.count_y; - - et4000->acl.pattern_addr = et4000->acl.internal.pattern_addr; - et4000->acl.source_addr = et4000->acl.internal.source_addr; - et4000->acl.dest_addr = et4000->acl.internal.dest_addr; - et4000->acl.dest_back = et4000->acl.dest_addr; + et4000->acl.x_count = et4000->acl.internal.count_x; + et4000->acl.y_count = et4000->acl.internal.count_y; + + et4000->acl.pattern_addr = et4000->acl.internal.pattern_addr; + et4000->acl.source_addr = et4000->acl.internal.source_addr; + et4000->acl.dest_addr = et4000->acl.internal.dest_addr; + et4000->acl.dest_back = et4000->acl.dest_addr; et4000->acl.pattern_x = et4000->acl.source_x = et4000->acl.pattern_y = et4000->acl.source_y = 0; et4000->acl.status |= ACL_XYST; - et4000->acl.status &= ~ACL_SSO; + et4000->acl.status &= ~ACL_SSO; if (!(et4000->acl.internal.ctrl_routing & 7) || (et4000->acl.internal.ctrl_routing & 4)) - et4000->acl.status |= ACL_SSO; + et4000->acl.status |= ACL_SSO; if (et4000w32_wrap_x[et4000->acl.internal.pattern_wrap & 7]) { - et4000->acl.pattern_x = et4000->acl.pattern_addr & et4000w32_wrap_x[et4000->acl.internal.pattern_wrap & 7]; - et4000->acl.pattern_addr &= ~et4000w32_wrap_x[et4000->acl.internal.pattern_wrap & 7]; + et4000->acl.pattern_x = et4000->acl.pattern_addr & et4000w32_wrap_x[et4000->acl.internal.pattern_wrap & 7]; + et4000->acl.pattern_addr &= ~et4000w32_wrap_x[et4000->acl.internal.pattern_wrap & 7]; } et4000->acl.pattern_back = et4000->acl.pattern_addr; if (!(et4000->acl.internal.pattern_wrap & 0x40)) { - if ((et4000w32_wrap_x[et4000->acl.internal.pattern_wrap & 7] + 1) == 0x00) { /*This is to avoid a division by zero crash*/ - et4000->acl.pattern_y = (et4000->acl.pattern_addr / (0x7f + 1)) & (et4000w32_wrap_y[(et4000->acl.internal.pattern_wrap >> 4) & 7] - 1); - } else - et4000->acl.pattern_y = (et4000->acl.pattern_addr / (et4000w32_wrap_x[et4000->acl.internal.pattern_wrap & 7] + 1)) & (et4000w32_wrap_y[(et4000->acl.internal.pattern_wrap >> 4) & 7] - 1); - et4000->acl.pattern_back &= ~(((et4000w32_wrap_x[et4000->acl.internal.pattern_wrap & 7] + 1) * et4000w32_wrap_y[(et4000->acl.internal.pattern_wrap >> 4) & 7]) - 1); + if ((et4000w32_wrap_x[et4000->acl.internal.pattern_wrap & 7] + 1) == 0x00) { /*This is to avoid a division by zero crash*/ + et4000->acl.pattern_y = (et4000->acl.pattern_addr / (0x7f + 1)) & (et4000w32_wrap_y[(et4000->acl.internal.pattern_wrap >> 4) & 7] - 1); + } else + et4000->acl.pattern_y = (et4000->acl.pattern_addr / (et4000w32_wrap_x[et4000->acl.internal.pattern_wrap & 7] + 1)) & (et4000w32_wrap_y[(et4000->acl.internal.pattern_wrap >> 4) & 7] - 1); + et4000->acl.pattern_back &= ~(((et4000w32_wrap_x[et4000->acl.internal.pattern_wrap & 7] + 1) * et4000w32_wrap_y[(et4000->acl.internal.pattern_wrap >> 4) & 7]) - 1); } et4000->acl.pattern_x_back = et4000->acl.pattern_x; if (et4000w32_wrap_x[et4000->acl.internal.source_wrap & 7]) { - et4000->acl.source_x = et4000->acl.source_addr & et4000w32_wrap_x[et4000->acl.internal.source_wrap & 7]; - et4000->acl.source_addr &= ~et4000w32_wrap_x[et4000->acl.internal.source_wrap & 7]; + et4000->acl.source_x = et4000->acl.source_addr & et4000w32_wrap_x[et4000->acl.internal.source_wrap & 7]; + et4000->acl.source_addr &= ~et4000w32_wrap_x[et4000->acl.internal.source_wrap & 7]; } et4000->acl.source_back = et4000->acl.source_addr; if (!(et4000->acl.internal.source_wrap & 0x40)) { - if ((et4000w32_wrap_x[et4000->acl.internal.source_wrap & 7] + 1) == 0x00) { /*This is to avoid a division by zero crash*/ - et4000->acl.source_y = (et4000->acl.source_addr / (0x7f + 1)) & (et4000w32_wrap_y[(et4000->acl.internal.source_wrap >> 4) & 7] - 1); - } else - et4000->acl.source_y = (et4000->acl.source_addr / (et4000w32_wrap_x[et4000->acl.internal.source_wrap & 7] + 1)) & (et4000w32_wrap_y[(et4000->acl.internal.source_wrap >> 4) & 7] - 1); - et4000->acl.source_back &= ~(((et4000w32_wrap_x[et4000->acl.internal.source_wrap & 7] + 1) * et4000w32_wrap_y[(et4000->acl.internal.source_wrap >> 4) & 7]) - 1); + if ((et4000w32_wrap_x[et4000->acl.internal.source_wrap & 7] + 1) == 0x00) { /*This is to avoid a division by zero crash*/ + et4000->acl.source_y = (et4000->acl.source_addr / (0x7f + 1)) & (et4000w32_wrap_y[(et4000->acl.internal.source_wrap >> 4) & 7] - 1); + } else + et4000->acl.source_y = (et4000->acl.source_addr / (et4000w32_wrap_x[et4000->acl.internal.source_wrap & 7] + 1)) & (et4000w32_wrap_y[(et4000->acl.internal.source_wrap >> 4) & 7] - 1); + et4000->acl.source_back &= ~(((et4000w32_wrap_x[et4000->acl.internal.source_wrap & 7] + 1) * et4000w32_wrap_y[(et4000->acl.internal.source_wrap >> 4) & 7]) - 1); } et4000->acl.source_x_back = et4000->acl.source_x; -} + if ((et4000w32_wrap_x[et4000->acl.internal.pattern_wrap & 7] == 7) && !(et4000->acl.internal.ctrl_routing & 0x37) && (et4000->acl.internal.rop_fg == 0x5a)) { + if ((et4000->acl.internal.count_y > 0) && (et4000->acl.pattern_y > 0)) { + if (et4000->acl.pattern_addr == et4000->acl.pattern_back) + et4000->acl.pattern_y = 0; + else { + et4000->acl.pattern_y = (et4000->acl.pattern_addr - et4000->acl.pattern_back) & 0x70; + et4000->acl.pattern_y >>= 4; + } + } + } else if ((et4000w32_wrap_x[et4000->acl.internal.pattern_wrap & 7] == 15) && !(et4000->acl.internal.ctrl_routing & 0x37) && (et4000->acl.internal.rop_fg == 0x5a)) { + if ((et4000->acl.internal.count_y > 0) && (et4000->acl.pattern_y > 0)) { + if (et4000->acl.pattern_addr == et4000->acl.pattern_back) + et4000->acl.pattern_y = 0; + else { + et4000->acl.pattern_y = (et4000->acl.pattern_addr - et4000->acl.pattern_back) & 0xf0; + et4000->acl.pattern_y >>= 5; + } + } + } +} static void et4000w32p_blit_start(et4000w32p_t *et4000) { - et4000->acl.x_count = et4000->acl.internal.count_x; - et4000->acl.y_count = et4000->acl.internal.count_y; + et4000->acl.x_count = et4000->acl.internal.count_x; + et4000->acl.y_count = et4000->acl.internal.count_y; if (!(et4000->acl.queued.xy_dir & 0x20)) - et4000->acl.internal.error = et4000->acl.internal.dmaj / 2; - et4000->acl.pattern_addr = et4000->acl.internal.pattern_addr; - et4000->acl.source_addr = et4000->acl.internal.source_addr; - et4000->acl.mix_addr = et4000->acl.internal.mix_addr; - et4000->acl.mix_back = et4000->acl.mix_addr; - et4000->acl.dest_addr = et4000->acl.internal.dest_addr; - et4000->acl.dest_back = et4000->acl.dest_addr; - et4000->acl.internal.pos_x = et4000->acl.internal.pos_y = 0; - et4000->acl.pattern_x = et4000->acl.source_x = et4000->acl.pattern_y = et4000->acl.source_y = 0; + et4000->acl.internal.error = et4000->acl.internal.dmaj / 2; + + et4000->acl.pattern_addr = et4000->acl.internal.pattern_addr; + et4000->acl.source_addr = et4000->acl.internal.source_addr; + et4000->acl.mix_addr = et4000->acl.internal.mix_addr; + et4000->acl.mix_back = et4000->acl.mix_addr; + et4000->acl.dest_addr = et4000->acl.internal.dest_addr; + et4000->acl.dest_back = et4000->acl.dest_addr; + et4000->acl.internal.pos_x = et4000->acl.internal.pos_y = 0; + et4000->acl.pattern_x = et4000->acl.source_x = et4000->acl.pattern_y = et4000->acl.source_y = 0; et4000->acl.status |= ACL_XYST; - - et4000w32_log("ACL status XYST set\n"); - if ((!(et4000->acl.internal.ctrl_routing & 7) || (et4000->acl.internal.ctrl_routing & 4)) && !(et4000->acl.internal.ctrl_routing & 0x40)) - et4000->acl.status |= ACL_SSO; + + et4000w32_log("ACL status XYST set\n"); + if ((!(et4000->acl.internal.ctrl_routing & 7) || (et4000->acl.internal.ctrl_routing & 4)) && !(et4000->acl.internal.ctrl_routing & 0x40)) + et4000->acl.status |= ACL_SSO; if (et4000w32_wrap_x[et4000->acl.internal.pattern_wrap & 7]) { - et4000->acl.pattern_x = et4000->acl.pattern_addr & et4000w32_wrap_x[et4000->acl.internal.pattern_wrap & 7]; - et4000->acl.pattern_addr &= ~et4000w32_wrap_x[et4000->acl.internal.pattern_wrap & 7]; + et4000->acl.pattern_x = et4000->acl.pattern_addr & et4000w32_wrap_x[et4000->acl.internal.pattern_wrap & 7]; + et4000->acl.pattern_addr &= ~et4000w32_wrap_x[et4000->acl.internal.pattern_wrap & 7]; } et4000->acl.pattern_back = et4000->acl.pattern_addr; if (!(et4000->acl.internal.pattern_wrap & 0x40)) { - et4000->acl.pattern_y = (et4000->acl.pattern_addr / (et4000w32_wrap_x[et4000->acl.internal.pattern_wrap & 7] + 1)) & (et4000w32_wrap_y[(et4000->acl.internal.pattern_wrap >> 4) & 7] - 1); - et4000->acl.pattern_back &= ~(((et4000w32_wrap_x[et4000->acl.internal.pattern_wrap & 7] + 1) * et4000w32_wrap_y[(et4000->acl.internal.pattern_wrap >> 4) & 7]) - 1); + et4000->acl.pattern_y = (et4000->acl.pattern_addr / (et4000w32_wrap_x[et4000->acl.internal.pattern_wrap & 7] + 1)) & (et4000w32_wrap_y[(et4000->acl.internal.pattern_wrap >> 4) & 7] - 1); + et4000->acl.pattern_back &= ~(((et4000w32_wrap_x[et4000->acl.internal.pattern_wrap & 7] + 1) * et4000w32_wrap_y[(et4000->acl.internal.pattern_wrap >> 4) & 7]) - 1); } et4000->acl.pattern_x_back = et4000->acl.pattern_x; if (et4000w32_wrap_x[et4000->acl.internal.source_wrap & 7]) { - et4000->acl.source_x = et4000->acl.source_addr & et4000w32_wrap_x[et4000->acl.internal.source_wrap & 7]; - et4000->acl.source_addr &= ~et4000w32_wrap_x[et4000->acl.internal.source_wrap & 7]; + et4000->acl.source_x = et4000->acl.source_addr & et4000w32_wrap_x[et4000->acl.internal.source_wrap & 7]; + et4000->acl.source_addr &= ~et4000w32_wrap_x[et4000->acl.internal.source_wrap & 7]; } et4000->acl.source_back = et4000->acl.source_addr; if (!(et4000->acl.internal.source_wrap & 0x40)) { - et4000->acl.source_y = (et4000->acl.source_addr / (et4000w32_wrap_x[et4000->acl.internal.source_wrap & 7] + 1)) & (et4000w32_wrap_y[(et4000->acl.internal.source_wrap >> 4) & 7] - 1); - et4000->acl.source_back &= ~(((et4000w32_wrap_x[et4000->acl.internal.source_wrap & 7] + 1) * et4000w32_wrap_y[(et4000->acl.internal.source_wrap >> 4) & 7]) - 1); + et4000->acl.source_y = (et4000->acl.source_addr / (et4000w32_wrap_x[et4000->acl.internal.source_wrap & 7] + 1)) & (et4000w32_wrap_y[(et4000->acl.internal.source_wrap >> 4) & 7] - 1); + et4000->acl.source_back &= ~(((et4000w32_wrap_x[et4000->acl.internal.source_wrap & 7] + 1) * et4000w32_wrap_y[(et4000->acl.internal.source_wrap >> 4) & 7]) - 1); } et4000->acl.source_x_back = et4000->acl.source_x; @@ -1117,698 +1276,1308 @@ et4000w32p_blit_start(et4000w32p_t *et4000) et4000->acl.internal.count_x += (et4000->acl.internal.pixel_depth >> 4) & 3; et4000->acl.cpu_dat_pos = 0; - et4000->acl.cpu_dat = 0; + et4000->acl.cpu_dat = 0; et4000->acl.pix_pos = 0; } - void et4000w32_incx(int c, et4000w32p_t *et4000) { - et4000->acl.dest_addr += c; - et4000->acl.pattern_x += c; - et4000->acl.source_x += c; - et4000->acl.mix_addr += c; + et4000->acl.dest_addr += c; + et4000->acl.pattern_x += c; + et4000->acl.source_x += c; + et4000->acl.mix_addr += c; if (et4000->acl.pattern_x >= et4000w32_max_x[et4000->acl.internal.pattern_wrap & 7]) - et4000->acl.pattern_x -= et4000w32_max_x[et4000->acl.internal.pattern_wrap & 7]; - if (et4000->acl.source_x >= et4000w32_max_x[et4000->acl.internal.source_wrap & 7]) - et4000->acl.source_x -= et4000w32_max_x[et4000->acl.internal.source_wrap & 7]; + et4000->acl.pattern_x -= et4000w32_max_x[et4000->acl.internal.pattern_wrap & 7]; + if (et4000->acl.source_x >= et4000w32_max_x[et4000->acl.internal.source_wrap & 7]) + et4000->acl.source_x -= et4000w32_max_x[et4000->acl.internal.source_wrap & 7]; } - void et4000w32_decx(int c, et4000w32p_t *et4000) { - et4000->acl.dest_addr -= c; - et4000->acl.pattern_x -= c; - et4000->acl.source_x -= c; - et4000->acl.mix_addr -= c; + et4000->acl.dest_addr -= c; + et4000->acl.pattern_x -= c; + et4000->acl.source_x -= c; + et4000->acl.mix_addr -= c; if (et4000->acl.pattern_x < 0) - et4000->acl.pattern_x += et4000w32_max_x[et4000->acl.internal.pattern_wrap & 7]; - if (et4000->acl.source_x < 0) - et4000->acl.source_x += et4000w32_max_x[et4000->acl.internal.source_wrap & 7]; + et4000->acl.pattern_x += et4000w32_max_x[et4000->acl.internal.pattern_wrap & 7]; + if (et4000->acl.source_x < 0) + et4000->acl.source_x += et4000w32_max_x[et4000->acl.internal.source_wrap & 7]; } - void et4000w32_incy(et4000w32p_t *et4000) { - et4000->acl.pattern_addr += et4000->acl.internal.pattern_off + 1; - et4000->acl.source_addr += et4000->acl.internal.source_off + 1; - et4000->acl.mix_addr += et4000->acl.internal.mix_off + 1; - et4000->acl.dest_addr += et4000->acl.internal.dest_off + 1; + et4000->acl.pattern_addr += et4000->acl.internal.pattern_off + 1; + et4000->acl.source_addr += et4000->acl.internal.source_off + 1; + et4000->acl.mix_addr += et4000->acl.internal.mix_off + 1; + et4000->acl.dest_addr += et4000->acl.internal.dest_off + 1; et4000->acl.pattern_y++; if (et4000->acl.pattern_y == et4000w32_wrap_y[(et4000->acl.internal.pattern_wrap >> 4) & 7]) { - et4000->acl.pattern_y = 0; - et4000->acl.pattern_addr = et4000->acl.pattern_back; + et4000->acl.pattern_y = 0; + et4000->acl.pattern_addr = et4000->acl.pattern_back; } et4000->acl.source_y++; if (et4000->acl.source_y == et4000w32_wrap_y[(et4000->acl.internal.source_wrap >> 4) & 7]) { - et4000->acl.source_y = 0; - et4000->acl.source_addr = et4000->acl.source_back; + et4000->acl.source_y = 0; + et4000->acl.source_addr = et4000->acl.source_back; } } - void et4000w32_decy(et4000w32p_t *et4000) { - et4000->acl.pattern_addr -= et4000->acl.internal.pattern_off + 1; - et4000->acl.source_addr -= et4000->acl.internal.source_off + 1; - et4000->acl.mix_addr -= et4000->acl.internal.mix_off + 1; - et4000->acl.dest_addr -= et4000->acl.internal.dest_off + 1; + et4000->acl.pattern_addr -= et4000->acl.internal.pattern_off + 1; + et4000->acl.source_addr -= et4000->acl.internal.source_off + 1; + et4000->acl.mix_addr -= et4000->acl.internal.mix_off + 1; + et4000->acl.dest_addr -= et4000->acl.internal.dest_off + 1; et4000->acl.pattern_y--; - if (et4000->acl.pattern_y < 0 && !(et4000->acl.internal.pattern_wrap & 0x40)) { - et4000->acl.pattern_y = et4000w32_wrap_y[(et4000->acl.internal.pattern_wrap >> 4) & 7] - 1; - et4000->acl.pattern_addr = et4000->acl.pattern_back + (et4000w32_wrap_x[et4000->acl.internal.pattern_wrap & 7] * (et4000w32_wrap_y[(et4000->acl.internal.pattern_wrap >> 4) & 7] - 1)); + if ((et4000->acl.pattern_y < 0) && !(et4000->acl.internal.pattern_wrap & 0x40)) { + et4000->acl.pattern_y = et4000w32_wrap_y[(et4000->acl.internal.pattern_wrap >> 4) & 7] - 1; + et4000->acl.pattern_addr = et4000->acl.pattern_back + (et4000w32_wrap_x[et4000->acl.internal.pattern_wrap & 7] * (et4000w32_wrap_y[(et4000->acl.internal.pattern_wrap >> 4) & 7] - 1)); } et4000->acl.source_y--; - if (et4000->acl.source_y < 0 && !(et4000->acl.internal.source_wrap & 0x40)) { - et4000->acl.source_y = et4000w32_wrap_y[(et4000->acl.internal.source_wrap >> 4) & 7] - 1; - et4000->acl.source_addr = et4000->acl.source_back + (et4000w32_wrap_x[et4000->acl.internal.source_wrap & 7] *(et4000w32_wrap_y[(et4000->acl.internal.source_wrap >> 4) & 7] - 1)); + if ((et4000->acl.source_y < 0) && !(et4000->acl.internal.source_wrap & 0x40)) { + et4000->acl.source_y = et4000w32_wrap_y[(et4000->acl.internal.source_wrap >> 4) & 7] - 1; + et4000->acl.source_addr = et4000->acl.source_back + (et4000w32_wrap_x[et4000->acl.internal.source_wrap & 7] * (et4000w32_wrap_y[(et4000->acl.internal.source_wrap >> 4) & 7] - 1)); } } - -#define ROPMIX(R, D, P, S, out) \ - { \ - switch (R) { \ - case 0x00: out = 0; break; \ - case 0x01: out = ~(D | (P | S)); break; \ - case 0x02: out = D & ~(P | S); break; \ - case 0x03: out = ~(P | S); break; \ - case 0x04: out = S & ~(D | P); break; \ - case 0x05: out = ~(D | P); break; \ - case 0x06: out = ~(P | ~(D ^ S)); break; \ - case 0x07: out = ~(P | (D & S)); break; \ - case 0x08: out = S & (D & ~P); break; \ - case 0x09: out = ~(P | (D ^ S)); break; \ - case 0x0a: out = D & ~P; break; \ - case 0x0b: out = ~(P | (S & ~D)); break; \ - case 0x0c: out = S & ~P; break; \ - case 0x0d: out = ~(P | (D & ~S)); break; \ - case 0x0e: out = ~(P | ~(D | S)); break; \ - case 0x0f: out = ~P; break; \ - case 0x10: out = P & ~(D | S); break; \ - case 0x11: out = ~(D | S); break; \ - case 0x12: out = ~(S | ~(D ^ P)); break; \ - case 0x13: out = ~(S | (D & P)); break; \ - case 0x14: out = ~(D | ~(P ^ S)); break; \ - case 0x15: out = ~(D | (P & S)); break; \ - case 0x16: out = P ^ (S ^ (D & ~(P & S))); break; \ - case 0x17: out = ~(S ^ ((S ^ P) & (D ^ S))); break; \ - case 0x18: out = (S ^ P) & (P ^ D); break; \ - case 0x19: out = ~(S ^ (D & ~(P & S))); break; \ - case 0x1a: out = P ^ (D | (S & P)); break; \ - case 0x1b: out = ~(S ^ (D & (P ^ S))); break; \ - case 0x1c: out = P ^ (S | (D & P)); break; \ - case 0x1d: out = ~(D ^ (S & (P ^ D))); break; \ - case 0x1e: out = P ^ (D | S); break; \ - case 0x1f: out = ~(P & (D | S)); break; \ - case 0x20: out = D & (P & ~S); break; \ - case 0x21: out = ~(S | (D ^ P)); break; \ - case 0x22: out = D & ~S; break; \ - case 0x23: out = ~(S | (P & ~D)); break; \ - case 0x24: out = (S ^ P) & (D ^ S); break; \ - case 0x25: out = ~(P ^ (D & ~(S & P))); break; \ - case 0x26: out = S ^ (D | (P & S)); break; \ - case 0x27: out = S ^ (D | ~(P ^ S)); break; \ - case 0x28: out = D & (P ^ S); break; \ - case 0x29: out = ~(P ^ (S ^ (D | (P & S)))); break; \ - case 0x2a: out = D & ~(P & S); break; \ - case 0x2b: out = ~(S ^ ((S ^ P) & (P ^ D))); break; \ - case 0x2c: out = S ^ (P & (D | S)); break; \ - case 0x2d: out = P ^ (S | ~D); break; \ - case 0x2e: out = P ^ (S | (D ^ P)); break; \ - case 0x2f: out = ~(P & (S | ~D)); break; \ - case 0x30: out = P & ~S; break; \ - case 0x31: out = ~(S | (D & ~P)); break; \ - case 0x32: out = S ^ (D | (P | S)); break; \ - case 0x33: out = ~S; break; \ - case 0x34: out = S ^ (P | (D & S)); break; \ - case 0x35: out = S ^ (P | ~(D ^ S)); break; \ - case 0x36: out = S ^ (D | P); break; \ - case 0x37: out = ~(S & (D | P)); break; \ - case 0x38: out = P ^ (S & (D | P)); break; \ - case 0x39: out = S ^ (P | ~D); break; \ - case 0x3a: out = S ^ (P | (D ^ S)); break; \ - case 0x3b: out = ~(S & (P | ~D)); break; \ - case 0x3c: out = P ^ S; break; \ - case 0x3d: out = S ^ (P | ~(D | S)); break; \ - case 0x3e: out = S ^ (P | (D & ~S)); break; \ - case 0x3f: out = ~(P & S); break; \ - case 0x40: out = P & (S & ~D); break; \ - case 0x41: out = ~(D | (P ^ S)); break; \ - case 0x42: out = (S ^ D) & (P ^ D); break; \ - case 0x43: out = ~(S ^ (P & ~(D & S))); break; \ - case 0x44: out = S & ~D; break; \ - case 0x45: out = ~(D | (P & ~S)); break; \ - case 0x46: out = D ^ (S | (P & D)); break; \ - case 0x47: out = ~(P ^ (S & (D ^ P))); break; \ - case 0x48: out = S & (D ^ P); break; \ - case 0x49: out = ~(P ^ (D ^ (S | (P & D)))); break; \ - case 0x4a: out = D ^ (P & (S | D)); break; \ - case 0x4b: out = P ^ (D | ~S); break; \ - case 0x4c: out = S & ~(D & P); break; \ - case 0x4d: out = ~(S ^ ((S ^ P) | (D ^ S))); break; \ - case 0x4e: out = P ^ (D | (S ^ P)); break; \ - case 0x4f: out = ~(P & (D | ~S)); break; \ - case 0x50: out = P & ~D; break; \ - case 0x51: out = ~(D | (S & ~P)); break; \ - case 0x52: out = D ^ (P | (S & D)); break; \ - case 0x53: out = ~(S ^ (P & (D ^ S))); break; \ - case 0x54: out = ~(D | ~(P | S)); break; \ - case 0x55: out = ~D; break; \ - case 0x56: out = D ^ (P | S); break; \ - case 0x57: out = ~(D & (P | S)); break; \ - case 0x58: out = P ^ (D & (S | P)); break; \ - case 0x59: out = D ^ (P | ~S); break; \ - case 0x5a: out = D ^ P; break; \ - case 0x5b: out = D ^ (P | ~(S | D)); break; \ - case 0x5c: out = D ^ (P | (S ^ D)); break; \ - case 0x5d: out = ~(D & (P | ~S)); break; \ - case 0x5e: out = D ^ (P | (S & ~D)); break; \ - case 0x5f: out = ~(D & P); break; \ - case 0x60: out = P & (D ^ S); break; \ - case 0x61: out = ~(D ^ (S ^ (P | (D & S)))); break; \ - case 0x62: out = D ^ (S & (P | D)); break; \ - case 0x63: out = S ^ (D | ~P); break; \ - case 0x64: out = S ^ (D & (P | S)); break; \ - case 0x65: out = D ^ (S | ~P); break; \ - case 0x66: out = D ^ S; break; \ - case 0x67: out = S ^ (D | ~(P | S)); break; \ - case 0x68: out = ~(D ^ (S ^ (P | ~(D | S)))); break; \ - case 0x69: out = ~(P ^ (D ^ S)); break; \ - case 0x6a: out = D ^ (P & S); break; \ - case 0x6b: out = ~(P ^ (S ^ (D & (P | S)))); break; \ - case 0x6c: out = S ^ (D & P); break; \ - case 0x6d: out = ~(P ^ (D ^ (S & (P | D)))); break; \ - case 0x6e: out = S ^ (D & (P | ~S)); break; \ - case 0x6f: out = ~(P & ~(D ^ S)); break; \ - case 0x70: out = P & ~(D & S); break; \ - case 0x71: out = ~(S ^ ((S ^ D) & (P ^ D))); break; \ - case 0x72: out = S ^ (D | (P ^ S)); break; \ - case 0x73: out = ~(S & (D | ~P)); break; \ - case 0x74: out = D ^ (S | (P ^ D)); break; \ - case 0x75: out = ~(D & (S | ~P)); break; \ - case 0x76: out = S ^ (D | (P & ~S)); break; \ - case 0x77: out = ~(D & S); break; \ - case 0x78: out = P ^ (D & S); break; \ - case 0x79: out = ~(D ^ (S ^ (P & (D | S)))); break; \ - case 0x7a: out = D ^ (P & (S | ~D)); break; \ - case 0x7b: out = ~(S & ~(D ^ P)); break; \ - case 0x7c: out = S ^ (P & (D | ~S)); break; \ - case 0x7d: out = ~(D & ~(P ^ S)); break; \ - case 0x7e: out = (S ^ P) | (D ^ S); break; \ - case 0x7f: out = ~(D & (P & S)); break; \ - case 0x80: out = D & (P & S); break; \ - case 0x81: out = ~((S ^ P) | (D ^ S)); break; \ - case 0x82: out = D & ~(P ^ S); break; \ - case 0x83: out = ~(S ^ (P & (D | ~S))); break; \ - case 0x84: out = S & ~(D ^ P); break; \ - case 0x85: out = ~(P ^ (D & (S | ~P))); break; \ - case 0x86: out = D ^ (S ^ (P & (D | S))); break; \ - case 0x87: out = ~(P ^ (D & S)); break; \ - case 0x88: out = D & S; break; \ - case 0x89: out = ~(S ^ (D | (P & ~S))); break; \ - case 0x8a: out = D & (S | ~P); break; \ - case 0x8b: out = ~(D ^ (S | (P ^ D))); break; \ - case 0x8c: out = S & (D | ~P); break; \ - case 0x8d: out = ~(S ^ (D | (P ^ S))); break; \ - case 0x8e: out = S ^ ((S ^ D) & (P ^ D)); break; \ - case 0x8f: out = ~(P & ~(D & S)); break; \ - case 0x90: out = P & ~(D ^ S); break; \ - case 0x91: out = ~(S ^ (D & (P | ~S))); break; \ - case 0x92: out = D ^ (P ^ (S & (D | P))); break; \ - case 0x93: out = ~(S ^ (P & D)); break; \ - case 0x94: out = P ^ (S ^ (D & (P | S))); break; \ - case 0x95: out = ~(D ^ (P & S)); break; \ - case 0x96: out = D ^ (P ^ S); break; \ - case 0x97: out = P ^ (S ^ (D | ~(P | S))); break; \ - case 0x98: out = ~(S ^ (D | ~(P | S))); break; \ - case 0x99: out = ~(D ^ S); break; \ - case 0x9a: out = D ^ (P & ~S); break; \ - case 0x9b: out = ~(S ^ (D & (P | S))); break; \ - case 0x9c: out = S ^ (P & ~D); break; \ - case 0x9d: out = ~(D ^ (S & (P | D))); break; \ - case 0x9e: out = D ^ (S ^ (P | (D & S))); break; \ - case 0x9f: out = ~(P & (D ^ S)); break; \ - case 0xa0: out = D & P; break; \ - case 0xa1: out = ~(P ^ (D | (S & ~P))); break; \ - case 0xa2: out = D & (P | ~S); break; \ - case 0xa3: out = ~(D ^ (P | (S ^ D))); break; \ - case 0xa4: out = ~(P ^ (D | ~(S | P))); break; \ - case 0xa5: out = ~(P ^ D); break; \ - case 0xa6: out = D ^ (S & ~P); break; \ - case 0xa7: out = ~(P ^ (D & (S | P))); break; \ - case 0xa8: out = D & (P | S); break; \ - case 0xa9: out = ~(D ^ (P | S)); break; \ - case 0xaa: out = D; break; \ - case 0xab: out = D | ~(P | S); break; \ - case 0xac: out = S ^ (P & (D ^ S)); break; \ - case 0xad: out = ~(D ^ (P | (S & D))); break; \ - case 0xae: out = D | (S & ~P); break; \ - case 0xaf: out = D | ~P; break; \ - case 0xb0: out = P & (D | ~S); break; \ - case 0xb1: out = ~(P ^ (D | (S ^ P))); break; \ - case 0xb2: out = S ^ ((S ^ P) | (D ^ S)); break; \ - case 0xb3: out = ~(S & ~(D & P)); break; \ - case 0xb4: out = P ^ (S & ~D); break; \ - case 0xb5: out = ~(D ^ (P & (S | D))); break; \ - case 0xb6: out = D ^ (P ^ (S | (D & P))); break; \ - case 0xb7: out = ~(S & (D ^ P)); break; \ - case 0xb8: out = P ^ (S & (D ^ P)); break; \ - case 0xb9: out = ~(D ^ (S | (P & D))); break; \ - case 0xba: out = D | (P & ~S); break; \ - case 0xbb: out = D | ~S; break; \ - case 0xbc: out = S ^ (P & ~(D & S)); break; \ - case 0xbd: out = ~((S ^ D) & (P ^ D)); break; \ - case 0xbe: out = D | (P ^ S); break; \ - case 0xbf: out = D | ~(P & S); break; \ - case 0xc0: out = P & S; break; \ - case 0xc1: out = ~(S ^ (P | (D & ~S))); break; \ - case 0xc2: out = ~(S ^ (P | ~(D | S))); break; \ - case 0xc3: out = ~(P ^ S); break; \ - case 0xc4: out = S & (P | ~D); break; \ - case 0xc5: out = ~(S ^ (P | (D ^ S))); break; \ - case 0xc6: out = S ^ (D & ~P); break; \ - case 0xc7: out = ~(P ^ (S & (D | P))); break; \ - case 0xc8: out = S & (D | P); break; \ - case 0xc9: out = ~(S ^ (P | D)); break; \ - case 0xca: out = D ^ (P & (S ^ D)); break; \ - case 0xcb: out = ~(S ^ (P | (D & S))); break; \ - case 0xcc: out = S; break; \ - case 0xcd: out = S | ~(D | P); break; \ - case 0xce: out = S | (D & ~P); break; \ - case 0xcf: out = S | ~P; break; \ - case 0xd0: out = P & (S | ~D); break; \ - case 0xd1: out = ~(P ^ (S | (D ^ P))); break; \ - case 0xd2: out = P ^ (D & ~S); break; \ - case 0xd3: out = ~(S ^ (P & (D | S))); break; \ - case 0xd4: out = S ^ ((S ^ P) & (P ^ D)); break; \ - case 0xd5: out = ~(D & ~(P & S)); break; \ - case 0xd6: out = P ^ (S ^ (D | (P & S))); break; \ - case 0xd7: out = ~(D & (P ^ S)); break; \ - case 0xd8: out = P ^ (D & (S ^ P)); break; \ - case 0xd9: out = ~(S ^ (D | (P & S))); break; \ - case 0xda: out = D ^ (P & ~(S & D)); break; \ - case 0xdb: out = ~((S ^ P) & (D ^ S)); break; \ - case 0xdc: out = S | (P & ~D); break; \ - case 0xdd: out = S | ~D; break; \ - case 0xde: out = S | (D ^ P); break; \ - case 0xdf: out = S | ~(D & P); break; \ - case 0xe0: out = P & (D | S); break; \ - case 0xe1: out = ~(P ^ (D | S)); break; \ - case 0xe2: out = D ^ (S & (P ^ D)); break; \ - case 0xe3: out = ~(P ^ (S | (D & P))); break; \ - case 0xe4: out = S ^ (D & (P ^ S)); break; \ - case 0xe5: out = ~(P ^ (D | (S & P))); break; \ - case 0xe6: out = S ^ (D & ~(P & S)); break; \ - case 0xe7: out = ~((S ^ P) & (P ^ D)); break; \ - case 0xe8: out = S ^ ((S ^ P) & (D ^ S)); break; \ - case 0xe9: out = ~(D ^ (S ^ (P & ~(D & S)))); break; \ - case 0xea: out = D | (P & S); break; \ - case 0xeb: out = D | ~(P ^ S); break; \ - case 0xec: out = S | (D & P); break; \ - case 0xed: out = S | ~(D ^ P); break; \ - case 0xee: out = D | S; break; \ - case 0xef: out = S | (D | ~P); break; \ - case 0xf0: out = P; break; \ - case 0xf1: out = P | ~(D | S); break; \ - case 0xf2: out = P | (D & ~S); break; \ - case 0xf3: out = P | ~S; break; \ - case 0xf4: out = P | (S & ~D); break; \ - case 0xf5: out = P | ~D; break; \ - case 0xf6: out = P | (D ^ S); break; \ - case 0xf7: out = P | ~(D & S); break; \ - case 0xf8: out = P | (D & S); break; \ - case 0xf9: out = P | ~(D ^ S); break; \ - case 0xfa: out = D | P; break; \ - case 0xfb: out = D | (P | ~S); break; \ - case 0xfc: out = P | S; break; \ - case 0xfd: out = P | (S | ~D); break; \ - case 0xfe: out = D | (P | S); break; \ - case 0xff: out = ~0; break; \ - } \ - } +#define ROPMIX(R, D, P, S, out) \ + { \ + switch (R) { \ + case 0x00: \ + out = 0; \ + break; \ + case 0x01: \ + out = ~(D | (P | S)); \ + break; \ + case 0x02: \ + out = D & ~(P | S); \ + break; \ + case 0x03: \ + out = ~(P | S); \ + break; \ + case 0x04: \ + out = S & ~(D | P); \ + break; \ + case 0x05: \ + out = ~(D | P); \ + break; \ + case 0x06: \ + out = ~(P | ~(D ^ S)); \ + break; \ + case 0x07: \ + out = ~(P | (D & S)); \ + break; \ + case 0x08: \ + out = S & (D & ~P); \ + break; \ + case 0x09: \ + out = ~(P | (D ^ S)); \ + break; \ + case 0x0a: \ + out = D & ~P; \ + break; \ + case 0x0b: \ + out = ~(P | (S & ~D)); \ + break; \ + case 0x0c: \ + out = S & ~P; \ + break; \ + case 0x0d: \ + out = ~(P | (D & ~S)); \ + break; \ + case 0x0e: \ + out = ~(P | ~(D | S)); \ + break; \ + case 0x0f: \ + out = ~P; \ + break; \ + case 0x10: \ + out = P & ~(D | S); \ + break; \ + case 0x11: \ + out = ~(D | S); \ + break; \ + case 0x12: \ + out = ~(S | ~(D ^ P)); \ + break; \ + case 0x13: \ + out = ~(S | (D & P)); \ + break; \ + case 0x14: \ + out = ~(D | ~(P ^ S)); \ + break; \ + case 0x15: \ + out = ~(D | (P & S)); \ + break; \ + case 0x16: \ + out = P ^ (S ^ (D & ~(P & S))); \ + break; \ + case 0x17: \ + out = ~(S ^ ((S ^ P) & (D ^ S))); \ + break; \ + case 0x18: \ + out = (S ^ P) & (P ^ D); \ + break; \ + case 0x19: \ + out = ~(S ^ (D & ~(P & S))); \ + break; \ + case 0x1a: \ + out = P ^ (D | (S & P)); \ + break; \ + case 0x1b: \ + out = ~(S ^ (D & (P ^ S))); \ + break; \ + case 0x1c: \ + out = P ^ (S | (D & P)); \ + break; \ + case 0x1d: \ + out = ~(D ^ (S & (P ^ D))); \ + break; \ + case 0x1e: \ + out = P ^ (D | S); \ + break; \ + case 0x1f: \ + out = ~(P & (D | S)); \ + break; \ + case 0x20: \ + out = D & (P & ~S); \ + break; \ + case 0x21: \ + out = ~(S | (D ^ P)); \ + break; \ + case 0x22: \ + out = D & ~S; \ + break; \ + case 0x23: \ + out = ~(S | (P & ~D)); \ + break; \ + case 0x24: \ + out = (S ^ P) & (D ^ S); \ + break; \ + case 0x25: \ + out = ~(P ^ (D & ~(S & P))); \ + break; \ + case 0x26: \ + out = S ^ (D | (P & S)); \ + break; \ + case 0x27: \ + out = S ^ (D | ~(P ^ S)); \ + break; \ + case 0x28: \ + out = D & (P ^ S); \ + break; \ + case 0x29: \ + out = ~(P ^ (S ^ (D | (P & S)))); \ + break; \ + case 0x2a: \ + out = D & ~(P & S); \ + break; \ + case 0x2b: \ + out = ~(S ^ ((S ^ P) & (P ^ D))); \ + break; \ + case 0x2c: \ + out = S ^ (P & (D | S)); \ + break; \ + case 0x2d: \ + out = P ^ (S | ~D); \ + break; \ + case 0x2e: \ + out = P ^ (S | (D ^ P)); \ + break; \ + case 0x2f: \ + out = ~(P & (S | ~D)); \ + break; \ + case 0x30: \ + out = P & ~S; \ + break; \ + case 0x31: \ + out = ~(S | (D & ~P)); \ + break; \ + case 0x32: \ + out = S ^ (D | (P | S)); \ + break; \ + case 0x33: \ + out = ~S; \ + break; \ + case 0x34: \ + out = S ^ (P | (D & S)); \ + break; \ + case 0x35: \ + out = S ^ (P | ~(D ^ S)); \ + break; \ + case 0x36: \ + out = S ^ (D | P); \ + break; \ + case 0x37: \ + out = ~(S & (D | P)); \ + break; \ + case 0x38: \ + out = P ^ (S & (D | P)); \ + break; \ + case 0x39: \ + out = S ^ (P | ~D); \ + break; \ + case 0x3a: \ + out = S ^ (P | (D ^ S)); \ + break; \ + case 0x3b: \ + out = ~(S & (P | ~D)); \ + break; \ + case 0x3c: \ + out = P ^ S; \ + break; \ + case 0x3d: \ + out = S ^ (P | ~(D | S)); \ + break; \ + case 0x3e: \ + out = S ^ (P | (D & ~S)); \ + break; \ + case 0x3f: \ + out = ~(P & S); \ + break; \ + case 0x40: \ + out = P & (S & ~D); \ + break; \ + case 0x41: \ + out = ~(D | (P ^ S)); \ + break; \ + case 0x42: \ + out = (S ^ D) & (P ^ D); \ + break; \ + case 0x43: \ + out = ~(S ^ (P & ~(D & S))); \ + break; \ + case 0x44: \ + out = S & ~D; \ + break; \ + case 0x45: \ + out = ~(D | (P & ~S)); \ + break; \ + case 0x46: \ + out = D ^ (S | (P & D)); \ + break; \ + case 0x47: \ + out = ~(P ^ (S & (D ^ P))); \ + break; \ + case 0x48: \ + out = S & (D ^ P); \ + break; \ + case 0x49: \ + out = ~(P ^ (D ^ (S | (P & D)))); \ + break; \ + case 0x4a: \ + out = D ^ (P & (S | D)); \ + break; \ + case 0x4b: \ + out = P ^ (D | ~S); \ + break; \ + case 0x4c: \ + out = S & ~(D & P); \ + break; \ + case 0x4d: \ + out = ~(S ^ ((S ^ P) | (D ^ S))); \ + break; \ + case 0x4e: \ + out = P ^ (D | (S ^ P)); \ + break; \ + case 0x4f: \ + out = ~(P & (D | ~S)); \ + break; \ + case 0x50: \ + out = P & ~D; \ + break; \ + case 0x51: \ + out = ~(D | (S & ~P)); \ + break; \ + case 0x52: \ + out = D ^ (P | (S & D)); \ + break; \ + case 0x53: \ + out = ~(S ^ (P & (D ^ S))); \ + break; \ + case 0x54: \ + out = ~(D | ~(P | S)); \ + break; \ + case 0x55: \ + out = ~D; \ + break; \ + case 0x56: \ + out = D ^ (P | S); \ + break; \ + case 0x57: \ + out = ~(D & (P | S)); \ + break; \ + case 0x58: \ + out = P ^ (D & (S | P)); \ + break; \ + case 0x59: \ + out = D ^ (P | ~S); \ + break; \ + case 0x5a: \ + out = D ^ P; \ + break; \ + case 0x5b: \ + out = D ^ (P | ~(S | D)); \ + break; \ + case 0x5c: \ + out = D ^ (P | (S ^ D)); \ + break; \ + case 0x5d: \ + out = ~(D & (P | ~S)); \ + break; \ + case 0x5e: \ + out = D ^ (P | (S & ~D)); \ + break; \ + case 0x5f: \ + out = ~(D & P); \ + break; \ + case 0x60: \ + out = P & (D ^ S); \ + break; \ + case 0x61: \ + out = ~(D ^ (S ^ (P | (D & S)))); \ + break; \ + case 0x62: \ + out = D ^ (S & (P | D)); \ + break; \ + case 0x63: \ + out = S ^ (D | ~P); \ + break; \ + case 0x64: \ + out = S ^ (D & (P | S)); \ + break; \ + case 0x65: \ + out = D ^ (S | ~P); \ + break; \ + case 0x66: \ + out = D ^ S; \ + break; \ + case 0x67: \ + out = S ^ (D | ~(P | S)); \ + break; \ + case 0x68: \ + out = ~(D ^ (S ^ (P | ~(D | S)))); \ + break; \ + case 0x69: \ + out = ~(P ^ (D ^ S)); \ + break; \ + case 0x6a: \ + out = D ^ (P & S); \ + break; \ + case 0x6b: \ + out = ~(P ^ (S ^ (D & (P | S)))); \ + break; \ + case 0x6c: \ + out = S ^ (D & P); \ + break; \ + case 0x6d: \ + out = ~(P ^ (D ^ (S & (P | D)))); \ + break; \ + case 0x6e: \ + out = S ^ (D & (P | ~S)); \ + break; \ + case 0x6f: \ + out = ~(P & ~(D ^ S)); \ + break; \ + case 0x70: \ + out = P & ~(D & S); \ + break; \ + case 0x71: \ + out = ~(S ^ ((S ^ D) & (P ^ D))); \ + break; \ + case 0x72: \ + out = S ^ (D | (P ^ S)); \ + break; \ + case 0x73: \ + out = ~(S & (D | ~P)); \ + break; \ + case 0x74: \ + out = D ^ (S | (P ^ D)); \ + break; \ + case 0x75: \ + out = ~(D & (S | ~P)); \ + break; \ + case 0x76: \ + out = S ^ (D | (P & ~S)); \ + break; \ + case 0x77: \ + out = ~(D & S); \ + break; \ + case 0x78: \ + out = P ^ (D & S); \ + break; \ + case 0x79: \ + out = ~(D ^ (S ^ (P & (D | S)))); \ + break; \ + case 0x7a: \ + out = D ^ (P & (S | ~D)); \ + break; \ + case 0x7b: \ + out = ~(S & ~(D ^ P)); \ + break; \ + case 0x7c: \ + out = S ^ (P & (D | ~S)); \ + break; \ + case 0x7d: \ + out = ~(D & ~(P ^ S)); \ + break; \ + case 0x7e: \ + out = (S ^ P) | (D ^ S); \ + break; \ + case 0x7f: \ + out = ~(D & (P & S)); \ + break; \ + case 0x80: \ + out = D & (P & S); \ + break; \ + case 0x81: \ + out = ~((S ^ P) | (D ^ S)); \ + break; \ + case 0x82: \ + out = D & ~(P ^ S); \ + break; \ + case 0x83: \ + out = ~(S ^ (P & (D | ~S))); \ + break; \ + case 0x84: \ + out = S & ~(D ^ P); \ + break; \ + case 0x85: \ + out = ~(P ^ (D & (S | ~P))); \ + break; \ + case 0x86: \ + out = D ^ (S ^ (P & (D | S))); \ + break; \ + case 0x87: \ + out = ~(P ^ (D & S)); \ + break; \ + case 0x88: \ + out = D & S; \ + break; \ + case 0x89: \ + out = ~(S ^ (D | (P & ~S))); \ + break; \ + case 0x8a: \ + out = D & (S | ~P); \ + break; \ + case 0x8b: \ + out = ~(D ^ (S | (P ^ D))); \ + break; \ + case 0x8c: \ + out = S & (D | ~P); \ + break; \ + case 0x8d: \ + out = ~(S ^ (D | (P ^ S))); \ + break; \ + case 0x8e: \ + out = S ^ ((S ^ D) & (P ^ D)); \ + break; \ + case 0x8f: \ + out = ~(P & ~(D & S)); \ + break; \ + case 0x90: \ + out = P & ~(D ^ S); \ + break; \ + case 0x91: \ + out = ~(S ^ (D & (P | ~S))); \ + break; \ + case 0x92: \ + out = D ^ (P ^ (S & (D | P))); \ + break; \ + case 0x93: \ + out = ~(S ^ (P & D)); \ + break; \ + case 0x94: \ + out = P ^ (S ^ (D & (P | S))); \ + break; \ + case 0x95: \ + out = ~(D ^ (P & S)); \ + break; \ + case 0x96: \ + out = D ^ (P ^ S); \ + break; \ + case 0x97: \ + out = P ^ (S ^ (D | ~(P | S))); \ + break; \ + case 0x98: \ + out = ~(S ^ (D | ~(P | S))); \ + break; \ + case 0x99: \ + out = ~(D ^ S); \ + break; \ + case 0x9a: \ + out = D ^ (P & ~S); \ + break; \ + case 0x9b: \ + out = ~(S ^ (D & (P | S))); \ + break; \ + case 0x9c: \ + out = S ^ (P & ~D); \ + break; \ + case 0x9d: \ + out = ~(D ^ (S & (P | D))); \ + break; \ + case 0x9e: \ + out = D ^ (S ^ (P | (D & S))); \ + break; \ + case 0x9f: \ + out = ~(P & (D ^ S)); \ + break; \ + case 0xa0: \ + out = D & P; \ + break; \ + case 0xa1: \ + out = ~(P ^ (D | (S & ~P))); \ + break; \ + case 0xa2: \ + out = D & (P | ~S); \ + break; \ + case 0xa3: \ + out = ~(D ^ (P | (S ^ D))); \ + break; \ + case 0xa4: \ + out = ~(P ^ (D | ~(S | P))); \ + break; \ + case 0xa5: \ + out = ~(P ^ D); \ + break; \ + case 0xa6: \ + out = D ^ (S & ~P); \ + break; \ + case 0xa7: \ + out = ~(P ^ (D & (S | P))); \ + break; \ + case 0xa8: \ + out = D & (P | S); \ + break; \ + case 0xa9: \ + out = ~(D ^ (P | S)); \ + break; \ + case 0xaa: \ + out = D; \ + break; \ + case 0xab: \ + out = D | ~(P | S); \ + break; \ + case 0xac: \ + out = S ^ (P & (D ^ S)); \ + break; \ + case 0xad: \ + out = ~(D ^ (P | (S & D))); \ + break; \ + case 0xae: \ + out = D | (S & ~P); \ + break; \ + case 0xaf: \ + out = D | ~P; \ + break; \ + case 0xb0: \ + out = P & (D | ~S); \ + break; \ + case 0xb1: \ + out = ~(P ^ (D | (S ^ P))); \ + break; \ + case 0xb2: \ + out = S ^ ((S ^ P) | (D ^ S)); \ + break; \ + case 0xb3: \ + out = ~(S & ~(D & P)); \ + break; \ + case 0xb4: \ + out = P ^ (S & ~D); \ + break; \ + case 0xb5: \ + out = ~(D ^ (P & (S | D))); \ + break; \ + case 0xb6: \ + out = D ^ (P ^ (S | (D & P))); \ + break; \ + case 0xb7: \ + out = ~(S & (D ^ P)); \ + break; \ + case 0xb8: \ + out = P ^ (S & (D ^ P)); \ + break; \ + case 0xb9: \ + out = ~(D ^ (S | (P & D))); \ + break; \ + case 0xba: \ + out = D | (P & ~S); \ + break; \ + case 0xbb: \ + out = D | ~S; \ + break; \ + case 0xbc: \ + out = S ^ (P & ~(D & S)); \ + break; \ + case 0xbd: \ + out = ~((S ^ D) & (P ^ D)); \ + break; \ + case 0xbe: \ + out = D | (P ^ S); \ + break; \ + case 0xbf: \ + out = D | ~(P & S); \ + break; \ + case 0xc0: \ + out = P & S; \ + break; \ + case 0xc1: \ + out = ~(S ^ (P | (D & ~S))); \ + break; \ + case 0xc2: \ + out = ~(S ^ (P | ~(D | S))); \ + break; \ + case 0xc3: \ + out = ~(P ^ S); \ + break; \ + case 0xc4: \ + out = S & (P | ~D); \ + break; \ + case 0xc5: \ + out = ~(S ^ (P | (D ^ S))); \ + break; \ + case 0xc6: \ + out = S ^ (D & ~P); \ + break; \ + case 0xc7: \ + out = ~(P ^ (S & (D | P))); \ + break; \ + case 0xc8: \ + out = S & (D | P); \ + break; \ + case 0xc9: \ + out = ~(S ^ (P | D)); \ + break; \ + case 0xca: \ + out = D ^ (P & (S ^ D)); \ + break; \ + case 0xcb: \ + out = ~(S ^ (P | (D & S))); \ + break; \ + case 0xcc: \ + out = S; \ + break; \ + case 0xcd: \ + out = S | ~(D | P); \ + break; \ + case 0xce: \ + out = S | (D & ~P); \ + break; \ + case 0xcf: \ + out = S | ~P; \ + break; \ + case 0xd0: \ + out = P & (S | ~D); \ + break; \ + case 0xd1: \ + out = ~(P ^ (S | (D ^ P))); \ + break; \ + case 0xd2: \ + out = P ^ (D & ~S); \ + break; \ + case 0xd3: \ + out = ~(S ^ (P & (D | S))); \ + break; \ + case 0xd4: \ + out = S ^ ((S ^ P) & (P ^ D)); \ + break; \ + case 0xd5: \ + out = ~(D & ~(P & S)); \ + break; \ + case 0xd6: \ + out = P ^ (S ^ (D | (P & S))); \ + break; \ + case 0xd7: \ + out = ~(D & (P ^ S)); \ + break; \ + case 0xd8: \ + out = P ^ (D & (S ^ P)); \ + break; \ + case 0xd9: \ + out = ~(S ^ (D | (P & S))); \ + break; \ + case 0xda: \ + out = D ^ (P & ~(S & D)); \ + break; \ + case 0xdb: \ + out = ~((S ^ P) & (D ^ S)); \ + break; \ + case 0xdc: \ + out = S | (P & ~D); \ + break; \ + case 0xdd: \ + out = S | ~D; \ + break; \ + case 0xde: \ + out = S | (D ^ P); \ + break; \ + case 0xdf: \ + out = S | ~(D & P); \ + break; \ + case 0xe0: \ + out = P & (D | S); \ + break; \ + case 0xe1: \ + out = ~(P ^ (D | S)); \ + break; \ + case 0xe2: \ + out = D ^ (S & (P ^ D)); \ + break; \ + case 0xe3: \ + out = ~(P ^ (S | (D & P))); \ + break; \ + case 0xe4: \ + out = S ^ (D & (P ^ S)); \ + break; \ + case 0xe5: \ + out = ~(P ^ (D | (S & P))); \ + break; \ + case 0xe6: \ + out = S ^ (D & ~(P & S)); \ + break; \ + case 0xe7: \ + out = ~((S ^ P) & (P ^ D)); \ + break; \ + case 0xe8: \ + out = S ^ ((S ^ P) & (D ^ S)); \ + break; \ + case 0xe9: \ + out = ~(D ^ (S ^ (P & ~(D & S)))); \ + break; \ + case 0xea: \ + out = D | (P & S); \ + break; \ + case 0xeb: \ + out = D | ~(P ^ S); \ + break; \ + case 0xec: \ + out = S | (D & P); \ + break; \ + case 0xed: \ + out = S | ~(D ^ P); \ + break; \ + case 0xee: \ + out = D | S; \ + break; \ + case 0xef: \ + out = S | (D | ~P); \ + break; \ + case 0xf0: \ + out = P; \ + break; \ + case 0xf1: \ + out = P | ~(D | S); \ + break; \ + case 0xf2: \ + out = P | (D & ~S); \ + break; \ + case 0xf3: \ + out = P | ~S; \ + break; \ + case 0xf4: \ + out = P | (S & ~D); \ + break; \ + case 0xf5: \ + out = P | ~D; \ + break; \ + case 0xf6: \ + out = P | (D ^ S); \ + break; \ + case 0xf7: \ + out = P | ~(D & S); \ + break; \ + case 0xf8: \ + out = P | (D & S); \ + break; \ + case 0xf9: \ + out = P | ~(D ^ S); \ + break; \ + case 0xfa: \ + out = D | P; \ + break; \ + case 0xfb: \ + out = D | (P | ~S); \ + break; \ + case 0xfc: \ + out = P | S; \ + break; \ + case 0xfd: \ + out = P | (S | ~D); \ + break; \ + case 0xfe: \ + out = D | (P | S); \ + break; \ + case 0xff: \ + out = ~0; \ + break; \ + } \ + } static void et4000w32_blit(int count, int cpu_input, uint32_t src_dat, uint32_t mix_dat, et4000w32p_t *et4000) { svga_t *svga = &et4000->svga; - uint8_t pattern, source, dest; + uint8_t pattern; + uint8_t source; + uint8_t dest; uint8_t rop; - int mixmap; + uint8_t out = 0; + int mixmap; - while (count-- && et4000->acl.y_count >= 0) { - pattern = svga->vram[(et4000->acl.pattern_addr + et4000->acl.pattern_x) & et4000->vram_mask]; + if (!(et4000->acl.status & ACL_XYST) && !et4000->acl.mmu_start) { + et4000w32_log("XY Block not started\n"); + return; + } - if (cpu_input == 1) { - source = src_dat & 0xff; - src_dat >>= 8; - } else /*The source data is from the display memory if the Control Routing register is not set to 1*/ - source = svga->vram[(et4000->acl.source_addr + et4000->acl.source_x) & et4000->vram_mask]; + if (cpu_input == 3) { + while (1) { + pattern = svga->vram[(et4000->acl.pattern_addr + et4000->acl.pattern_x) & et4000->vram_mask]; + source = svga->vram[(et4000->acl.source_addr + et4000->acl.source_x) & et4000->vram_mask]; - dest = svga->vram[et4000->acl.dest_addr & et4000->vram_mask]; - mixmap = mix_dat & 1; + dest = svga->vram[et4000->acl.dest_addr & et4000->vram_mask]; + mixmap = mix_dat & 1; - /*Now determine the Raster Operation*/ - rop = mixmap ? et4000->acl.internal.rop_fg : et4000->acl.internal.rop_bg; - mix_dat >>= 1; - mix_dat |= 0x80000000; + rop = mixmap ? et4000->acl.internal.rop_fg : et4000->acl.internal.rop_bg; + mix_dat >>= 1; + mix_dat |= 0x80000000; - ROPMIX(rop, dest, pattern, source, dest); + ROPMIX(rop, dest, pattern, source, out); - /*Write the data*/ - svga->vram[et4000->acl.dest_addr & et4000->vram_mask] = dest; - svga->changedvram[(et4000->acl.dest_addr & et4000->vram_mask) >> 12] = changeframecount; + /*Write the data*/ + svga->vram[et4000->acl.dest_addr & et4000->vram_mask] = out; + svga->changedvram[(et4000->acl.dest_addr & et4000->vram_mask) >> 12] = changeframecount; - if (et4000->acl.internal.xy_dir & 1) { - et4000->acl.dest_addr--; - et4000->acl.pattern_x--; - et4000->acl.source_x--; - if (et4000->acl.pattern_x < 0) - et4000->acl.pattern_x += (et4000w32_wrap_x[et4000->acl.internal.pattern_wrap & 7] + 1); - if (et4000->acl.source_x < 0) - et4000->acl.source_x += (et4000w32_wrap_x[et4000->acl.internal.source_wrap & 7] + 1); - } else { - et4000->acl.dest_addr++; - et4000->acl.pattern_x++; - et4000->acl.source_x++; - if (et4000->acl.pattern_x >= (et4000w32_wrap_x[et4000->acl.internal.pattern_wrap & 7] + 1)) - et4000->acl.pattern_x -= (et4000w32_wrap_x[et4000->acl.internal.pattern_wrap & 7] + 1); - if (et4000->acl.source_x >= (et4000w32_wrap_x[et4000->acl.internal.source_wrap & 7] + 1)) - et4000->acl.source_x -= (et4000w32_wrap_x[et4000->acl.internal.source_wrap & 7] + 1); - } - - et4000->acl.x_count--; - if (et4000->acl.x_count == 0xffff) { - et4000->acl.x_count = et4000->acl.internal.count_x; + if (et4000->acl.internal.xy_dir & 1) + et4000w32_decx(1, et4000); + else + et4000w32_incx(1, et4000); - if (et4000->acl.internal.xy_dir & 2) { - et4000->acl.pattern_addr -= (et4000->acl.internal.pattern_off + 1); - et4000->acl.source_addr -= (et4000->acl.internal.source_off + 1); - et4000->acl.dest_addr -= (et4000->acl.internal.dest_off + 1); - et4000->acl.pattern_y--; - if ((et4000->acl.pattern_y < 0) && !(et4000->acl.internal.pattern_wrap & 0x40)) { - et4000->acl.pattern_y = et4000w32_wrap_y[(et4000->acl.internal.pattern_wrap >> 4) & 7] - 1; - et4000->acl.pattern_addr = et4000->acl.pattern_back + (et4000w32_wrap_x[et4000->acl.internal.pattern_wrap & 7] * (et4000w32_wrap_y[(et4000->acl.internal.pattern_wrap >> 4) & 7] - 1)); - } - et4000->acl.source_y--; - if ((et4000->acl.source_y < 0) && !(et4000->acl.internal.source_wrap & 0x40)) { - et4000->acl.source_y = et4000w32_wrap_y[(et4000->acl.internal.source_wrap >> 4) & 7] - 1; - et4000->acl.source_addr = et4000->acl.source_back + (et4000w32_wrap_x[et4000->acl.internal.source_wrap & 7] * (et4000w32_wrap_y[(et4000->acl.internal.source_wrap >> 4) & 7] - 1)); - } - et4000->acl.dest_back = et4000->acl.dest_addr = et4000->acl.dest_back - (et4000->acl.internal.dest_off + 1); - } else { - et4000->acl.pattern_addr += (et4000->acl.internal.pattern_off + 1); - et4000->acl.source_addr += (et4000->acl.internal.source_off + 1); - et4000->acl.dest_addr += (et4000->acl.internal.dest_off + 1); - et4000->acl.pattern_y++; - if (et4000->acl.pattern_y == et4000w32_wrap_y[(et4000->acl.internal.pattern_wrap >> 4) & 7]) { - et4000->acl.pattern_y = 0; - et4000->acl.pattern_addr = et4000->acl.pattern_back; - } - et4000->acl.source_y++; - if (et4000->acl.source_y == et4000w32_wrap_y[(et4000->acl.internal.source_wrap >> 4) & 7]) { - et4000->acl.source_y = 0; - et4000->acl.source_addr = et4000->acl.source_back; - } - et4000->acl.dest_back = et4000->acl.dest_addr = et4000->acl.dest_back + (et4000->acl.internal.dest_off + 1); - } + count--; + if (!count) { + count = et4000->acl.cpu_x_cnt; - et4000->acl.pattern_x = et4000->acl.pattern_x_back; - et4000->acl.source_x = et4000->acl.source_x_back; + if (et4000->acl.internal.xy_dir & 2) { + et4000w32_decy(et4000); + et4000->acl.dest_back = et4000->acl.dest_addr = et4000->acl.dest_back - (et4000->acl.internal.dest_off + 1); + } else { + et4000w32_incy(et4000); + et4000->acl.dest_back = et4000->acl.dest_addr = et4000->acl.dest_back + et4000->acl.internal.dest_off + 1; + } - et4000->acl.y_count--; - if (et4000->acl.y_count == 0xffff) { - et4000->acl.status &= ~ACL_XYST; - if (!(et4000->acl.internal.ctrl_routing & 7) || (et4000->acl.internal.ctrl_routing & 4)) { - et4000w32_log("W32i: end blit, xcount = %i\n", et4000->acl.x_count); - et4000->acl.status &= ~ACL_SSO; - } - et4000->acl.cpu_input_num = 0; - return; - } + et4000->acl.pattern_x = et4000->acl.pattern_x_back; + et4000->acl.source_x = et4000->acl.source_x_back; - if (cpu_input) - return; - } - } + et4000->acl.y_count--; + if (et4000->acl.y_count == 0xffff) { + et4000->acl.status &= ~ACL_XYST; + if (!(et4000->acl.internal.ctrl_routing & 7) || (et4000->acl.internal.ctrl_routing & 4)) { + et4000w32_log("W32i: end blit, xcount = %i\n", et4000->acl.x_count); + et4000->acl.status &= ~ACL_SSO; + } + return; + } + } + } + } else if (cpu_input == 4) { + while (1) { + pattern = svga->vram[(et4000->acl.pattern_addr + et4000->acl.pattern_x) & et4000->vram_mask]; + source = svga->vram[(et4000->acl.source_addr + et4000->acl.source_x) & et4000->vram_mask]; + + dest = svga->vram[et4000->acl.dest_addr & et4000->vram_mask]; + mixmap = mix_dat & 1; + + rop = mixmap ? et4000->acl.internal.rop_fg : et4000->acl.internal.rop_bg; + mix_dat >>= 1; + mix_dat |= 0x80000000; + + ROPMIX(rop, dest, pattern, source, out); + + /*Write the data*/ + svga->vram[et4000->acl.dest_addr & et4000->vram_mask] = out; + svga->changedvram[(et4000->acl.dest_addr & et4000->vram_mask) >> 12] = changeframecount; + + if (et4000->acl.internal.xy_dir & 1) + et4000w32_decx(1, et4000); + else + et4000w32_incx(1, et4000); + + et4000->acl.x_count--; + if (et4000->acl.x_count == 0xffff) { + et4000->acl.x_count = et4000->acl.internal.count_x; + + if (et4000->acl.internal.xy_dir & 2) { + et4000w32_decy(et4000); + et4000->acl.dest_back = et4000->acl.dest_addr = et4000->acl.dest_back - (et4000->acl.internal.dest_off + 1); + } else { + et4000w32_incy(et4000); + et4000->acl.dest_back = et4000->acl.dest_addr = et4000->acl.dest_back + et4000->acl.internal.dest_off + 1; + } + + et4000->acl.pattern_x = et4000->acl.pattern_x_back; + et4000->acl.source_x = et4000->acl.source_x_back; + + count--; + if (!count) { + et4000->acl.status &= ~ACL_XYST; + if (!(et4000->acl.internal.ctrl_routing & 7) || (et4000->acl.internal.ctrl_routing & 4)) { + et4000w32_log("W32i: end blit, xcount = %i\n", et4000->acl.x_count); + et4000->acl.status &= ~ACL_SSO; + } + return; + } + } + } + } else { + while (count-- && (et4000->acl.y_count >= 0)) { + pattern = svga->vram[(et4000->acl.pattern_addr + et4000->acl.pattern_x) & et4000->vram_mask]; + + if (cpu_input == 1) { + source = src_dat & 0xff; + src_dat >>= 8; + } else /*The source data is from the display memory if the Control Routing register is not set to 1*/ + source = svga->vram[(et4000->acl.source_addr + et4000->acl.source_x) & et4000->vram_mask]; + + dest = svga->vram[et4000->acl.dest_addr & et4000->vram_mask]; + mixmap = mix_dat & 1; + + /*Now determine the Raster Operation*/ + rop = mixmap ? et4000->acl.internal.rop_fg : et4000->acl.internal.rop_bg; + mix_dat >>= 1; + mix_dat |= 0x80000000; + + ROPMIX(rop, dest, pattern, source, out); + + /*Write the data*/ + svga->vram[et4000->acl.dest_addr & et4000->vram_mask] = out; + svga->changedvram[(et4000->acl.dest_addr & et4000->vram_mask) >> 12] = changeframecount; + + if (et4000->acl.internal.xy_dir & 1) + et4000w32_decx(1, et4000); + else + et4000w32_incx(1, et4000); + + et4000->acl.x_count--; + if (et4000->acl.x_count == 0xffff) { + et4000->acl.x_count = et4000->acl.internal.count_x; + + if (et4000->acl.internal.xy_dir & 2) { + et4000w32_decy(et4000); + et4000->acl.dest_back = et4000->acl.dest_addr = et4000->acl.dest_back - (et4000->acl.internal.dest_off + 1); + } else { + et4000w32_incy(et4000); + et4000->acl.dest_back = et4000->acl.dest_addr = et4000->acl.dest_back + et4000->acl.internal.dest_off + 1; + } + + et4000->acl.pattern_x = et4000->acl.pattern_x_back; + et4000->acl.source_x = et4000->acl.source_x_back; + + et4000->acl.y_count--; + if (et4000->acl.y_count == 0xffff) { + et4000->acl.status &= ~ACL_XYST; + if (!(et4000->acl.internal.ctrl_routing & 7) || (et4000->acl.internal.ctrl_routing & 4)) { + et4000w32_log("W32i: end blit, xcount = %i\n", et4000->acl.x_count); + et4000->acl.status &= ~ACL_SSO; + } + et4000->acl.cpu_input_num = 0; + return; + } + + if (cpu_input) { + return; + } + } + } + } } static void et4000w32p_blit(int count, uint32_t mix, uint32_t sdat, int cpu_input, et4000w32p_t *et4000) { svga_t *svga = &et4000->svga; - uint8_t pattern, source, dest, out; + uint8_t pattern; + uint8_t source; + uint8_t dest; + uint8_t out; uint8_t rop; - int mixdat; + int mixdat; if (!(et4000->acl.status & ACL_XYST)) { - et4000w32_log("XY Block not started\n"); - return; - } + et4000w32_log("XY Block not started\n"); + return; + } - if (et4000->acl.internal.xy_dir & 0x80) { /* Line draw */ - et4000w32_log("Line draw\n"); - while (count--) { - et4000w32_log("%i,%i : ", et4000->acl.internal.pos_x, et4000->acl.internal.pos_y); - pattern = svga->vram[(et4000->acl.pattern_addr + et4000->acl.pattern_x) & et4000->vram_mask]; - source = svga->vram[(et4000->acl.source_addr + et4000->acl.source_x) & et4000->vram_mask]; - et4000w32_log("%06X %06X ", (et4000->acl.pattern_addr + et4000->acl.pattern_x) & et4000->vram_mask, (et4000->acl.source_addr + et4000->acl.source_x) & et4000->vram_mask); - if (cpu_input == 2) { - source = sdat & 0xff; - sdat >>= 8; - } - dest = svga->vram[et4000->acl.dest_addr & et4000->vram_mask]; - out = 0; - et4000w32_log("%06X ", et4000->acl.dest_addr); - if ((et4000->acl.internal.ctrl_routing & 0xa) == 8) { - mixdat = svga->vram[(et4000->acl.mix_addr >> 3) & et4000->vram_mask] & (1 << (et4000->acl.mix_addr & 7)); - et4000w32_log("%06X %02X ", et4000->acl.mix_addr, svga->vram[(et4000->acl.mix_addr >> 3) & et4000->vram_mask]); - } else { - mixdat = mix & 1; - mix >>= 1; - mix |= 0x80000000; - } - et4000->acl.mix_addr++; - rop = mixdat ? et4000->acl.internal.rop_fg : et4000->acl.internal.rop_bg; - - ROPMIX(rop, dest, pattern, source, out); - - et4000w32_log("%06X = %02X\n", et4000->acl.dest_addr & et4000->vram_mask, out); - if (!(et4000->acl.internal.ctrl_routing & 0x40)) { - svga->vram[et4000->acl.dest_addr & et4000->vram_mask] = out; - svga->changedvram[(et4000->acl.dest_addr & et4000->vram_mask) >> 12] = changeframecount; - } else { - et4000->acl.cpu_dat |= ((uint64_t)out << (et4000->acl.cpu_dat_pos * 8)); - et4000->acl.cpu_dat_pos++; - } + if (et4000->acl.internal.xy_dir & 0x80) { /* Line draw */ + et4000w32_log("Line draw\n"); + while (count--) { + et4000w32_log("%i,%i : ", et4000->acl.internal.pos_x, et4000->acl.internal.pos_y); + pattern = svga->vram[(et4000->acl.pattern_addr + et4000->acl.pattern_x) & et4000->vram_mask]; + source = svga->vram[(et4000->acl.source_addr + et4000->acl.source_x) & et4000->vram_mask]; + et4000w32_log("%06X %06X ", (et4000->acl.pattern_addr + et4000->acl.pattern_x) & et4000->vram_mask, (et4000->acl.source_addr + et4000->acl.source_x) & et4000->vram_mask); + if (cpu_input == 2) { + source = sdat & 0xff; + sdat >>= 8; + } + dest = svga->vram[et4000->acl.dest_addr & et4000->vram_mask]; + out = 0; + et4000w32_log("%06X ", et4000->acl.dest_addr); + if ((et4000->acl.internal.ctrl_routing & 0xa) == 8) { + mixdat = svga->vram[(et4000->acl.mix_addr >> 3) & et4000->vram_mask] & (1 << (et4000->acl.mix_addr & 7)); + et4000w32_log("%06X %02X ", et4000->acl.mix_addr, svga->vram[(et4000->acl.mix_addr >> 3) & et4000->vram_mask]); + } else { + mixdat = mix & 1; + mix >>= 1; + mix |= 0x80000000; + } + et4000->acl.mix_addr++; + rop = mixdat ? et4000->acl.internal.rop_fg : et4000->acl.internal.rop_bg; - et4000->acl.pix_pos++; - et4000->acl.internal.pos_x++; - if (et4000->acl.pix_pos <= ((et4000->acl.internal.pixel_depth >> 4) & 3)) { - if (et4000->acl.internal.xy_dir & 1) et4000w32_decx(1, et4000); - else et4000w32_incx(1, et4000); - } else { - if (et4000->acl.internal.xy_dir & 1) - et4000w32_incx((et4000->acl.internal.pixel_depth >> 4) & 3, et4000); - else - et4000w32_decx((et4000->acl.internal.pixel_depth >> 4) & 3, et4000); - et4000->acl.pix_pos = 0; + ROPMIX(rop, dest, pattern, source, out); - /*Next pixel*/ - switch (et4000->acl.internal.xy_dir & 7) { - case 0: case 1: /* Y+ */ - et4000w32_incy(et4000); - et4000->acl.internal.pos_y++; - et4000->acl.internal.pos_x -= ((et4000->acl.internal.pixel_depth >> 4) & 3) + 1; - break; - case 2: case 3: /* Y- */ - et4000w32_decy(et4000); - et4000->acl.internal.pos_y++; - et4000->acl.internal.pos_x -= ((et4000->acl.internal.pixel_depth >> 4) & 3) + 1; - break; - case 4: case 6: /* X+ */ - et4000w32_incx(((et4000->acl.internal.pixel_depth >> 4) & 3) + 1, et4000); - break; - case 5: case 7: /* X- */ - et4000w32_decx(((et4000->acl.internal.pixel_depth >> 4) & 3) + 1, et4000); - break; - } - et4000->acl.internal.error += et4000->acl.internal.dmin; - if (et4000->acl.internal.error > et4000->acl.internal.dmaj) { - et4000->acl.internal.error -= et4000->acl.internal.dmaj; - switch (et4000->acl.internal.xy_dir & 7) { - case 0: case 2: /* X+ */ - et4000w32_incx(((et4000->acl.internal.pixel_depth >> 4) & 3) + 1, et4000); - et4000->acl.internal.pos_x++; - break; - case 1: case 3: /* X- */ - et4000w32_decx(((et4000->acl.internal.pixel_depth >> 4) & 3) + 1, et4000); - et4000->acl.internal.pos_x++; - break; - case 4: case 5: /* Y+ */ - et4000w32_incy(et4000); - et4000->acl.internal.pos_y++; - break; - case 6: case 7: /* Y- */ - et4000w32_decy(et4000); - et4000->acl.internal.pos_y++; - break; - } - } - if ((et4000->acl.internal.pos_x > et4000->acl.internal.count_x) || - (et4000->acl.internal.pos_y > et4000->acl.internal.count_y)) { - et4000w32_log("ACL status linedraw 0\n"); - et4000->acl.status &= ~(ACL_XYST | ACL_SSO); - return; - } - } - } + et4000w32_log("%06X = %02X\n", et4000->acl.dest_addr & et4000->vram_mask, out); + if (!(et4000->acl.internal.ctrl_routing & 0x40)) { + svga->vram[et4000->acl.dest_addr & et4000->vram_mask] = out; + svga->changedvram[(et4000->acl.dest_addr & et4000->vram_mask) >> 12] = changeframecount; + } else { + et4000->acl.cpu_dat |= ((uint64_t) out << (et4000->acl.cpu_dat_pos * 8)); + et4000->acl.cpu_dat_pos++; + } + + et4000->acl.pix_pos++; + et4000->acl.internal.pos_x++; + if (et4000->acl.pix_pos <= ((et4000->acl.internal.pixel_depth >> 4) & 3)) { + if (et4000->acl.internal.xy_dir & 1) + et4000w32_decx(1, et4000); + else + et4000w32_incx(1, et4000); + } else { + if (et4000->acl.internal.xy_dir & 1) + et4000w32_incx((et4000->acl.internal.pixel_depth >> 4) & 3, et4000); + else + et4000w32_decx((et4000->acl.internal.pixel_depth >> 4) & 3, et4000); + et4000->acl.pix_pos = 0; + + /*Next pixel*/ + switch (et4000->acl.internal.xy_dir & 7) { + case 0: + case 1: /* Y+ */ + et4000w32_incy(et4000); + et4000->acl.internal.pos_y++; + et4000->acl.internal.pos_x -= ((et4000->acl.internal.pixel_depth >> 4) & 3) + 1; + break; + case 2: + case 3: /* Y- */ + et4000w32_decy(et4000); + et4000->acl.internal.pos_y++; + et4000->acl.internal.pos_x -= ((et4000->acl.internal.pixel_depth >> 4) & 3) + 1; + break; + case 4: + case 6: /* X+ */ + et4000w32_incx(((et4000->acl.internal.pixel_depth >> 4) & 3) + 1, et4000); + break; + case 5: + case 7: /* X- */ + et4000w32_decx(((et4000->acl.internal.pixel_depth >> 4) & 3) + 1, et4000); + break; + + default: + break; + } + et4000->acl.internal.error += et4000->acl.internal.dmin; + if (et4000->acl.internal.error > et4000->acl.internal.dmaj) { + et4000->acl.internal.error -= et4000->acl.internal.dmaj; + switch (et4000->acl.internal.xy_dir & 7) { + case 0: + case 2: /* X+ */ + et4000w32_incx(((et4000->acl.internal.pixel_depth >> 4) & 3) + 1, et4000); + et4000->acl.internal.pos_x++; + break; + case 1: + case 3: /* X- */ + et4000w32_decx(((et4000->acl.internal.pixel_depth >> 4) & 3) + 1, et4000); + et4000->acl.internal.pos_x++; + break; + case 4: + case 5: /* Y+ */ + et4000w32_incy(et4000); + et4000->acl.internal.pos_y++; + break; + case 6: + case 7: /* Y- */ + et4000w32_decy(et4000); + et4000->acl.internal.pos_y++; + break; + + default: + break; + } + } + if ((et4000->acl.internal.pos_x > et4000->acl.internal.count_x) || (et4000->acl.internal.pos_y > et4000->acl.internal.count_y)) { + et4000w32_log("ACL status linedraw 0\n"); + et4000->acl.status &= ~(ACL_XYST | ACL_SSO); + return; + } + } + } } else { - et4000w32_log("BitBLT: count = %i\n", count); - while (count-- && et4000->acl.y_count >= 0) { - pattern = svga->vram[(et4000->acl.pattern_addr + et4000->acl.pattern_x) & et4000->vram_mask]; + et4000w32_log("BitBLT: count = %i\n", count); + while (count-- && et4000->acl.y_count >= 0) { + pattern = svga->vram[(et4000->acl.pattern_addr + et4000->acl.pattern_x) & et4000->vram_mask]; - if (cpu_input == 2) { - source = sdat & 0xff; - sdat >>= 8; - } else - source = svga->vram[(et4000->acl.source_addr + et4000->acl.source_x) & et4000->vram_mask]; - - dest = svga->vram[et4000->acl.dest_addr & et4000->vram_mask]; - out = 0; - - if ((et4000->acl.internal.ctrl_routing & 0xa) == 8) { - mixdat = svga->vram[(et4000->acl.mix_addr >> 3) & et4000->vram_mask] & (1 << (et4000->acl.mix_addr & 7)); - } else { - mixdat = mix & 1; - mix >>= 1; - mix |= 0x80000000; - } + if (cpu_input == 2) { + source = sdat & 0xff; + sdat >>= 8; + } else + source = svga->vram[(et4000->acl.source_addr + et4000->acl.source_x) & et4000->vram_mask]; - rop = mixdat ? et4000->acl.internal.rop_fg : et4000->acl.internal.rop_bg; + dest = svga->vram[et4000->acl.dest_addr & et4000->vram_mask]; + out = 0; - ROPMIX(rop, dest, pattern, source, out); + if ((et4000->acl.internal.ctrl_routing & 0xa) == 8) { + mixdat = svga->vram[(et4000->acl.mix_addr >> 3) & et4000->vram_mask] & (1 << (et4000->acl.mix_addr & 7)); + } else { + mixdat = mix & 1; + mix >>= 1; + mix |= 0x80000000; + } - if (!(et4000->acl.internal.ctrl_routing & 0x40)) { - svga->vram[et4000->acl.dest_addr & et4000->vram_mask] = out; - svga->changedvram[(et4000->acl.dest_addr & et4000->vram_mask) >> 12] = changeframecount; - } else { - et4000->acl.cpu_dat |= ((uint64_t)out << (et4000->acl.cpu_dat_pos * 8)); - et4000->acl.cpu_dat_pos++; - } + rop = mixdat ? et4000->acl.internal.rop_fg : et4000->acl.internal.rop_bg; - if (et4000->acl.internal.xy_dir & 1) - et4000w32_decx(1, et4000); - else - et4000w32_incx(1, et4000); - - et4000->acl.x_count--; - if (et4000->acl.x_count == 0xffff) { - if (et4000->acl.internal.xy_dir & 2) { - et4000w32_decy(et4000); - et4000->acl.mix_back = et4000->acl.mix_addr = et4000->acl.mix_back - (et4000->acl.internal.mix_off + 1); - et4000->acl.dest_back = et4000->acl.dest_addr = et4000->acl.dest_back - (et4000->acl.internal.dest_off + 1); - } else { - et4000w32_incy(et4000); - et4000->acl.mix_back = et4000->acl.mix_addr = et4000->acl.mix_back + et4000->acl.internal.mix_off + 1; - et4000->acl.dest_back = et4000->acl.dest_addr = et4000->acl.dest_back + et4000->acl.internal.dest_off + 1; - } + ROPMIX(rop, dest, pattern, source, out); - et4000->acl.pattern_x = et4000->acl.pattern_x_back; - et4000->acl.source_x = et4000->acl.source_x_back; + if (!(et4000->acl.internal.ctrl_routing & 0x40)) { + svga->vram[et4000->acl.dest_addr & et4000->vram_mask] = out; + svga->changedvram[(et4000->acl.dest_addr & et4000->vram_mask) >> 12] = changeframecount; + } else { + et4000->acl.cpu_dat |= ((uint64_t) out << (et4000->acl.cpu_dat_pos * 8)); + et4000->acl.cpu_dat_pos++; + } - et4000->acl.y_count--; - et4000->acl.x_count = et4000->acl.internal.count_x; - if (et4000->acl.y_count == 0xffff) { - et4000w32_log("BitBLT end\n"); - et4000->acl.status &= ~(ACL_XYST | ACL_SSO); - return; - } + if (et4000->acl.internal.xy_dir & 1) + et4000w32_decx(1, et4000); + else + et4000w32_incx(1, et4000); - if (cpu_input) - return; + et4000->acl.x_count--; + if (et4000->acl.x_count == 0xffff) { + if (et4000->acl.internal.xy_dir & 2) { + et4000w32_decy(et4000); + et4000->acl.mix_back = et4000->acl.mix_addr = et4000->acl.mix_back - (et4000->acl.internal.mix_off + 1); + et4000->acl.dest_back = et4000->acl.dest_addr = et4000->acl.dest_back - (et4000->acl.internal.dest_off + 1); + } else { + et4000w32_incy(et4000); + et4000->acl.mix_back = et4000->acl.mix_addr = et4000->acl.mix_back + et4000->acl.internal.mix_off + 1; + et4000->acl.dest_back = et4000->acl.dest_addr = et4000->acl.dest_back + et4000->acl.internal.dest_off + 1; + } - if (et4000->acl.internal.ctrl_routing & 0x40) { - if (et4000->acl.cpu_dat_pos & 3) - et4000->acl.cpu_dat_pos += 4 - (et4000->acl.cpu_dat_pos & 3); - return; - } - } - } + et4000->acl.pattern_x = et4000->acl.pattern_x_back; + et4000->acl.source_x = et4000->acl.source_x_back; + + et4000->acl.y_count--; + et4000->acl.x_count = et4000->acl.internal.count_x; + if (et4000->acl.y_count == 0xffff) { + et4000w32_log("BitBLT end\n"); + et4000->acl.status &= ~(ACL_XYST | ACL_SSO); + return; + } + + if (cpu_input) + return; + + if (et4000->acl.internal.ctrl_routing & 0x40) { + if (et4000->acl.cpu_dat_pos & 3) + et4000->acl.cpu_dat_pos += 4 - (et4000->acl.cpu_dat_pos & 3); + return; + } + } + } } } - void et4000w32p_hwcursor_draw(svga_t *svga, int displine) { - et4000w32p_t *et4000 = (et4000w32p_t *)svga->p; - int x, offset, xx, xx2; - int shift = (et4000->adjust_cursor + 1); - int width = (svga->hwcursor_latch.xsize - svga->hwcursor_latch.xoff); - int pitch = (svga->hwcursor_latch.xsize == 128) ? 32 : 16; - int x_acc = 4; - int minus_width = 0; - uint8_t dat; + const et4000w32p_t *et4000 = (et4000w32p_t *) svga->priv; + int offset; + int xx; + int xx2; + int shift = (et4000->adjust_cursor + 1); + int width = (svga->hwcursor_latch.cur_xsize - svga->hwcursor_latch.xoff); + int pitch = (svga->hwcursor_latch.cur_xsize == 128) ? 32 : 16; + int x_acc = 4; + int minus_width = 0; + uint8_t dat; + offset = svga->hwcursor_latch.xoff; - - if (et4000->type == ET4000W32) { - switch (svga->bpp) { - case 8: - minus_width = 0; - x_acc = 2; - break; - case 15: case 16: - minus_width = 64; - x_acc = 2; - break; - } - } - for (x = 0; x < (width - minus_width); x += x_acc) { - dat = svga->vram[svga->hwcursor_latch.addr + (offset >> 2)]; + if ((et4000->type == ET4000W32) && (pitch == 32)) { + switch (svga->bpp) { + case 8: + minus_width = 0; + x_acc = 2; + break; + case 15: + case 16: + minus_width = 64; + x_acc = 2; + break; - xx = svga->hwcursor_latch.x + svga->x_add + x; - - if (!(xx % shift)) { - xx2 = xx / shift; - if (!(dat & 2)) buffer32->line[displine][xx2] = (dat & 1) ? 0xFFFFFF : 0; - else if ((dat & 3) == 3) buffer32->line[displine][xx2] ^= 0xFFFFFF; - } - dat >>= 2; - xx++; - if (!(xx % shift)) { - xx2 = xx / shift; - if (!(dat & 2)) buffer32->line[displine][xx2] = (dat & 1) ? 0xFFFFFF : 0; - else if ((dat & 3) == 3) buffer32->line[displine][xx2] ^= 0xFFFFFF; - } - dat >>= 2; - xx++; - if (!(xx % shift)) { - xx2 = xx / shift; - if (!(dat & 2)) buffer32->line[displine][xx2] = (dat & 1) ? 0xFFFFFF : 0; - else if ((dat & 3) == 3) buffer32->line[displine][xx2] ^= 0xFFFFFF; - } - dat >>= 2; - xx++; - if (!(xx % shift)) { - xx2 = xx / shift; - if (!(dat & 2)) buffer32->line[displine][xx2] = (dat & 1) ? 0xFFFFFF : 0; - else if ((dat & 3) == 3) buffer32->line[displine][xx2] ^= 0xFFFFFF; - } - dat >>= 2; - - offset += 4; + default: + break; + } } - svga->hwcursor_latch.addr += pitch; -} + for (int x = 0; x < (width - minus_width); x += x_acc) { + dat = svga->vram[svga->hwcursor_latch.addr + (offset >> 2)]; + xx = svga->hwcursor_latch.x + svga->x_add + x; + + if (!(xx % shift)) { + xx2 = xx / shift; + if (!(dat & 2)) + buffer32->line[displine][xx2] = (dat & 1) ? 0xFFFFFF : 0; + else if ((dat & 3) == 3) + buffer32->line[displine][xx2] ^= 0xFFFFFF; + } + dat >>= 2; + xx++; + if (!(xx % shift)) { + xx2 = xx / shift; + if (!(dat & 2)) + buffer32->line[displine][xx2] = (dat & 1) ? 0xFFFFFF : 0; + else if ((dat & 3) == 3) + buffer32->line[displine][xx2] ^= 0xFFFFFF; + } + dat >>= 2; + xx++; + if (!(xx % shift)) { + xx2 = xx / shift; + if (!(dat & 2)) + buffer32->line[displine][xx2] = (dat & 1) ? 0xFFFFFF : 0; + else if ((dat & 3) == 3) + buffer32->line[displine][xx2] ^= 0xFFFFFF; + } + dat >>= 2; + xx++; + if (!(xx % shift)) { + xx2 = xx / shift; + if (!(dat & 2)) + buffer32->line[displine][xx2] = (dat & 1) ? 0xFFFFFF : 0; + else if ((dat & 3) == 3) + buffer32->line[displine][xx2] ^= 0xFFFFFF; + } + dat >>= 2; + + offset += 4; + } + + svga->hwcursor_latch.addr += pitch; +} static void et4000w32p_io_remove(et4000w32p_t *et4000) @@ -1825,7 +2594,6 @@ et4000w32p_io_remove(et4000w32p_t *et4000) io_removehandler(0x217a, 0x0002, et4000w32p_in, NULL, NULL, et4000w32p_out, NULL, NULL, et4000); } - static void et4000w32p_io_set(et4000w32p_t *et4000) { @@ -1843,221 +2611,260 @@ et4000w32p_io_set(et4000w32p_t *et4000) io_sethandler(0x217a, 0x0002, et4000w32p_in, NULL, NULL, et4000w32p_out, NULL, NULL, et4000); } - uint8_t -et4000w32p_pci_read(int func, int addr, void *p) +et4000w32p_pci_read(UNUSED(int func), int addr, void *priv) { - et4000w32p_t *et4000 = (et4000w32p_t *)p; + const et4000w32p_t *et4000 = (et4000w32p_t *) priv; addr &= 0xff; switch (addr) { - case 0x00: return 0x0c; /* Tseng Labs */ - case 0x01: return 0x10; + case 0x00: + return 0x0c; /* Tseng Labs */ + case 0x01: + return 0x10; - case 0x02: return (et4000->rev); - case 0x03: return 0x32; + case 0x02: + return (et4000->rev); + case 0x03: + return 0x32; - case PCI_REG_COMMAND: - return et4000->pci_regs[PCI_REG_COMMAND] | 0x80; /* Respond to IO and memory accesses */ + case PCI_REG_COMMAND: + return et4000->pci_regs[PCI_REG_COMMAND] | 0x80; /* Respond to IO and memory accesses */ - case 0x07: return 1 << 1; /* Medium DEVSEL timing */ + case 0x07: + return 1 << 1; /* Medium DEVSEL timing */ - case 0x08: return (et4000->rev); /* Revision ID */ - case 0x09: return 0; /* Programming interface */ + case 0x08: + return (et4000->rev); /* Revision ID */ + case 0x09: + return 0; /* Programming interface */ - case 0x0a: return 0x00; /* Supports VGA interface */ - case 0x0b: return 0x03; /* This has to be done in order to make this card work with the two 486 PCI machines. */ + case 0x0a: + return 0x00; /* Supports VGA interface */ + case 0x0b: + return 0x03; /* This has to be done in order to make this card work with the two 486 PCI machines. */ - case 0x10: return 0x00; /* Linear frame buffer address */ - case 0x11: return 0x00; - case 0x12: return 0x00; - case 0x13: return (et4000->linearbase >> 24); + case 0x10: + return 0x00; /* Linear frame buffer address */ + case 0x11: + return 0x00; + case 0x12: + return 0x00; + case 0x13: + return (et4000->linearbase >> 24); - case 0x30: return et4000->pci_regs[0x30] & 0x01; /* BIOS ROM address */ - case 0x31: return 0x00; - case 0x32: return 0x00; - case 0x33: return et4000->pci_regs[0x33] & 0xf0; + case 0x30: + return et4000->pci_regs[0x30] & 0x01; /* BIOS ROM address */ + case 0x31: + return 0x00; + case 0x32: + return 0x00; + case 0x33: + return et4000->pci_regs[0x33] & 0xf0; + + default: + break; } return 0; } - void -et4000w32p_pci_write(int func, int addr, uint8_t val, void *p) +et4000w32p_pci_write(UNUSED(int func), int addr, uint8_t val, void *priv) { - et4000w32p_t *et4000 = (et4000w32p_t *)p; - svga_t *svga = &et4000->svga; + et4000w32p_t *et4000 = (et4000w32p_t *) priv; + svga_t *svga = &et4000->svga; addr &= 0xff; switch (addr) { - case PCI_REG_COMMAND: - et4000->pci_regs[PCI_REG_COMMAND] = (val & 0x23) | 0x80; - if (val & PCI_COMMAND_IO) - et4000w32p_io_set(et4000); - else - et4000w32p_io_remove(et4000); - et4000w32p_recalcmapping(et4000); - break; + case PCI_REG_COMMAND: + et4000->pci_regs[PCI_REG_COMMAND] = (val & 0x23) | 0x80; + if (val & PCI_COMMAND_IO) + et4000w32p_io_set(et4000); + else + et4000w32p_io_remove(et4000); + et4000w32p_recalcmapping(et4000); + break; - case 0x13: - et4000->linearbase &= 0x00c00000; - et4000->linearbase |= (et4000->pci_regs[0x13] << 24); - svga->crtc[0x30] &= 3; - svga->crtc[0x30] |= ((et4000->linearbase & 0x3f000000) >> 22); - et4000w32p_recalcmapping(et4000); - break; + case 0x13: + et4000->linearbase &= 0x00c00000; + et4000->linearbase |= (et4000->pci_regs[0x13] << 24); + svga->crtc[0x30] &= 3; + svga->crtc[0x30] |= ((et4000->linearbase & 0x3f000000) >> 22); + et4000w32p_recalcmapping(et4000); + break; - case 0x30: case 0x31: case 0x32: case 0x33: - et4000->pci_regs[addr] = val; - et4000->pci_regs[0x30] = 1; - et4000->pci_regs[0x31] = 0; - et4000->pci_regs[0x32] = 0; - et4000->pci_regs[0x33] &= 0xf0; - if (et4000->pci_regs[0x30] & 0x01) { - uint32_t addr = (et4000->pci_regs[0x33] << 24); - if (!addr) - addr = 0xc0000; - et4000w32_log("ET4000 bios_rom enabled at %08x\n", addr); - mem_mapping_set_addr(&et4000->bios_rom.mapping, addr, 0x8000); - } else { - et4000w32_log("ET4000 bios_rom disabled\n"); - mem_mapping_disable(&et4000->bios_rom.mapping); - } - return; + case 0x30: + case 0x31: + case 0x32: + case 0x33: + et4000->pci_regs[addr] = val; + et4000->pci_regs[0x30] = 1; + et4000->pci_regs[0x31] = 0; + et4000->pci_regs[0x32] = 0; + et4000->pci_regs[0x33] &= 0xf0; + if (et4000->pci_regs[0x30] & 0x01) { + uint32_t biosaddr = (et4000->pci_regs[0x33] << 24); + if (!biosaddr) + biosaddr = 0xc0000; + et4000w32_log("ET4000 bios_rom enabled at %08x\n", biosaddr); + mem_mapping_set_addr(&et4000->bios_rom.mapping, biosaddr, 0x8000); + } else { + et4000w32_log("ET4000 bios_rom disabled\n"); + mem_mapping_disable(&et4000->bios_rom.mapping); + } + return; + + default: + break; } } - void * et4000w32p_init(const device_t *info) { - int vram_size; + int vram_size; et4000w32p_t *et4000 = malloc(sizeof(et4000w32p_t)); memset(et4000, 0, sizeof(et4000w32p_t)); et4000->pci = (info->flags & DEVICE_PCI) ? 0x80 : 0x00; et4000->vlb = (info->flags & DEVICE_VLB) ? 0x40 : 0x00; - - /*The ET4000/W32i ISA BIOS seems to not support 2MB of VRAM*/ - if ((info->local == ET4000W32) || ((info->local == ET4000W32I) && !(et4000->vlb))) - vram_size = 1; - else - vram_size = device_get_config_int("memory"); - /*The interleaved VRAM was introduced by the ET4000/W32i*/ + /*The ET4000/W32i ISA BIOS seems to not support 2MB of VRAM*/ + if ((info->local == ET4000W32) || ((info->local == ET4000W32I) && !(et4000->vlb))) + vram_size = 1; + else + vram_size = device_get_config_int("memory"); + + /*The interleaved VRAM was introduced by the ET4000/W32i*/ et4000->interleaved = ((vram_size == 2) && (info->local != ET4000W32)) ? 1 : 0; if (info->flags & DEVICE_PCI) - video_inform(VIDEO_FLAG_TYPE_SPECIAL, &timing_et4000w32_pci); + video_inform(VIDEO_FLAG_TYPE_SPECIAL, &timing_et4000w32_pci); else if (info->flags & DEVICE_VLB) - video_inform(VIDEO_FLAG_TYPE_SPECIAL, &timing_et4000w32_vlb); + video_inform(VIDEO_FLAG_TYPE_SPECIAL, &timing_et4000w32_vlb); else - video_inform(VIDEO_FLAG_TYPE_SPECIAL, &timing_et4000w32_isa); + video_inform(VIDEO_FLAG_TYPE_SPECIAL, &timing_et4000w32_isa); svga_init(info, &et4000->svga, et4000, vram_size << 20, - et4000w32p_recalctimings, - et4000w32p_in, et4000w32p_out, - et4000w32p_hwcursor_draw, - NULL); + et4000w32p_recalctimings, + et4000w32p_in, et4000w32p_out, + et4000w32p_hwcursor_draw, + NULL); - et4000->vram_mask = (vram_size << 20) - 1; - et4000->svga.decode_mask = (vram_size << 20) - 1; + et4000->vram_mask = (vram_size << 20) - 1; + et4000->svga.decode_mask = (vram_size << 20) - 1; et4000->type = info->local; - switch(et4000->type) { - case ET4000W32: - /* ET4000/W32 */ - et4000->rev = 0; - - rom_init(&et4000->bios_rom, BIOS_ROM_PATH_W32, 0xc0000, 0x8000, 0x7fff, 0, - MEM_MAPPING_EXTERNAL); + switch (et4000->type) { + case ET4000W32: + /* ET4000/W32 */ + et4000->rev = 0; - et4000->svga.ramdac = device_add(&tseng_ics5301_ramdac_device); - et4000->svga.clock_gen = et4000->svga.ramdac; - et4000->svga.getclock = sdac_getclock; - break; + rom_init(&et4000->bios_rom, BIOS_ROM_PATH_W32, 0xc0000, 0x8000, 0x7fff, 0, + MEM_MAPPING_EXTERNAL); - case ET4000W32I: - /* ET4000/W32i rev B */ - et4000->rev = 3; + et4000->svga.ramdac = device_add(&tseng_ics5301_ramdac_device); + et4000->svga.clock_gen = et4000->svga.ramdac; + et4000->svga.getclock = sdac_getclock; + break; - if (et4000->vlb) { - rom_init(&et4000->bios_rom, BIOS_ROM_PATH_W32I_VLB, 0xc0000, 0x8000, 0x7fff, 0, - MEM_MAPPING_EXTERNAL); - } else { - rom_init(&et4000->bios_rom, BIOS_ROM_PATH_W32I_ISA, 0xc0000, 0x8000, 0x7fff, 0, - MEM_MAPPING_EXTERNAL); - } + case ET4000W32I: + /* ET4000/W32i rev B */ + et4000->rev = 3; - et4000->svga.ramdac = device_add(&tseng_ics5301_ramdac_device); - et4000->svga.clock_gen = et4000->svga.ramdac; - et4000->svga.getclock = sdac_getclock; - break; + if (et4000->vlb) { + rom_init(&et4000->bios_rom, BIOS_ROM_PATH_W32I_VLB, 0xc0000, 0x8000, 0x7fff, 0, + MEM_MAPPING_EXTERNAL); + } else { + rom_init(&et4000->bios_rom, BIOS_ROM_PATH_W32I_ISA, 0xc0000, 0x8000, 0x7fff, 0, + MEM_MAPPING_EXTERNAL); + } - case ET4000W32P_REVC: - /* ET4000/W32p rev C */ - et4000->rev = 7; + et4000->svga.ramdac = device_add(&tseng_ics5301_ramdac_device); + et4000->svga.clock_gen = et4000->svga.ramdac; + et4000->svga.getclock = sdac_getclock; + break; - rom_init(&et4000->bios_rom, BIOS_ROM_PATH_W32P_REVC, 0xc0000, 0x8000, 0x7fff, 0, - MEM_MAPPING_EXTERNAL); + case ET4000W32P_VIDEOMAGIC_REVB: + /* ET4000/W32p rev B */ + et4000->rev = 5; - et4000->svga.ramdac = device_add(&tseng_ics5341_ramdac_device); - et4000->svga.clock_gen = et4000->svga.ramdac; - et4000->svga.getclock = sdac_getclock; - break; + rom_init(&et4000->bios_rom, BIOS_ROM_PATH_W32P_VIDEOMAGIC_REVB_VLB, 0xc0000, 0x8000, 0x7fff, 0, + MEM_MAPPING_EXTERNAL); - case ET4000W32P: - /* ET4000/W32p rev D */ - et4000->rev = 6; + et4000->svga.ramdac = device_add(&stg_ramdac_device); + et4000->svga.clock_gen = et4000->svga.ramdac; + et4000->svga.getclock = stg_getclock; + et4000->svga.adv_flags |= FLAG_NOSKEW; + break; - rom_init(&et4000->bios_rom, BIOS_ROM_PATH_W32P, 0xc0000, 0x8000, 0x7fff, 0, - MEM_MAPPING_EXTERNAL); + case ET4000W32P_REVC: + /* ET4000/W32p rev C */ + et4000->rev = 7; - et4000->svga.ramdac = device_add(&stg_ramdac_device); - et4000->svga.clock_gen = et4000->svga.ramdac; - et4000->svga.getclock = stg_getclock; - et4000->svga.adv_flags |= FLAG_NOSKEW; - break; + rom_init(&et4000->bios_rom, BIOS_ROM_PATH_W32P_REVC, 0xc0000, 0x8000, 0x7fff, 0, + MEM_MAPPING_EXTERNAL); - case ET4000W32P_CARDEX: - /* ET4000/W32p rev D */ - et4000->rev = 6; + et4000->svga.ramdac = device_add(&tseng_ics5341_ramdac_device); + et4000->svga.clock_gen = et4000->svga.ramdac; + et4000->svga.getclock = sdac_getclock; + break; - rom_init(&et4000->bios_rom, BIOS_ROM_PATH_CARDEX, 0xc0000, 0x8000, 0x7fff, 0, - MEM_MAPPING_EXTERNAL); + case ET4000W32P: + /* ET4000/W32p rev D */ + et4000->rev = 6; - et4000->svga.ramdac = device_add(&stg_ramdac_device); - et4000->svga.clock_gen = et4000->svga.ramdac; - et4000->svga.getclock = stg_getclock; - et4000->svga.adv_flags |= FLAG_NOSKEW; - break; + rom_init(&et4000->bios_rom, BIOS_ROM_PATH_W32P, 0xc0000, 0x8000, 0x7fff, 0, + MEM_MAPPING_EXTERNAL); - case ET4000W32P_DIAMOND: - /* ET4000/W32p rev D */ - et4000->rev = 6; + et4000->svga.ramdac = device_add(&stg_ramdac_device); + et4000->svga.clock_gen = et4000->svga.ramdac; + et4000->svga.getclock = stg_getclock; + et4000->svga.adv_flags |= FLAG_NOSKEW; + break; - rom_init(&et4000->bios_rom, BIOS_ROM_PATH_DIAMOND, 0xc0000, 0x8000, 0x7fff, 0, - MEM_MAPPING_EXTERNAL); + case ET4000W32P_CARDEX: + /* ET4000/W32p rev D */ + et4000->rev = 6; - et4000->svga.ramdac = device_add(&stg_ramdac_device); - et4000->svga.clock_gen = device_add(&icd2061_device); - et4000->svga.getclock = icd2061_getclock; - break; + rom_init(&et4000->bios_rom, BIOS_ROM_PATH_CARDEX, 0xc0000, 0x8000, 0x7fff, 0, + MEM_MAPPING_EXTERNAL); + + et4000->svga.ramdac = device_add(&stg_ramdac_device); + et4000->svga.clock_gen = et4000->svga.ramdac; + et4000->svga.getclock = stg_getclock; + et4000->svga.adv_flags |= FLAG_NOSKEW; + break; + + case ET4000W32P_DIAMOND: + /* ET4000/W32p rev D */ + et4000->rev = 6; + + rom_init(&et4000->bios_rom, BIOS_ROM_PATH_DIAMOND, 0xc0000, 0x8000, 0x7fff, 0, + MEM_MAPPING_EXTERNAL); + + et4000->svga.ramdac = device_add(&stg_ramdac_device); + et4000->svga.clock_gen = device_add(&icd2061_device); + et4000->svga.getclock = icd2061_getclock; + break; + + default: + break; } if (info->flags & DEVICE_PCI) - mem_mapping_disable(&et4000->bios_rom.mapping); + mem_mapping_disable(&et4000->bios_rom.mapping); mem_mapping_add(&et4000->linear_mapping, 0, 0, svga_read_linear, svga_readw_linear, svga_readl_linear, svga_write_linear, svga_writew_linear, svga_writel_linear, NULL, MEM_MAPPING_EXTERNAL, &et4000->svga); - mem_mapping_add(&et4000->mmu_mapping, 0, 0, et4000w32p_mmu_read, NULL, NULL, et4000w32p_mmu_write, NULL, NULL, NULL, MEM_MAPPING_EXTERNAL, et4000); + mem_mapping_add(&et4000->mmu_mapping, 0, 0, et4000w32p_mmu_read, NULL, NULL, et4000w32p_mmu_write, NULL, NULL, NULL, MEM_MAPPING_EXTERNAL, et4000); et4000w32p_io_set(et4000); if (info->flags & DEVICE_PCI) - pci_add_card(PCI_ADD_VIDEO, et4000w32p_pci_read, et4000w32p_pci_write, et4000); + pci_add_card(PCI_ADD_NORMAL, et4000w32p_pci_read, et4000w32p_pci_write, et4000, &et4000->pci_slot); /* Hardwired bits: 00000000 1xx0x0xx */ /* R/W bits: xx xxxx */ @@ -2074,32 +2881,34 @@ et4000w32p_init(const device_t *info) et4000->pci_regs[0x32] = 0x00; et4000->pci_regs[0x33] = 0xf0; - et4000->svga.packed_chain4 = 1; + et4000->svga.packed_chain4 = 1; return et4000; } - int et4000w32_available(void) { return rom_present(BIOS_ROM_PATH_W32); } - int et4000w32i_isa_available(void) { return rom_present(BIOS_ROM_PATH_W32I_ISA); } - int et4000w32i_vlb_available(void) { return rom_present(BIOS_ROM_PATH_W32I_VLB); } +int +et4000w32p_videomagic_revb_vlb_available(void) +{ + return rom_present(BIOS_ROM_PATH_W32P_VIDEOMAGIC_REVB_VLB); +} int et4000w32p_revc_available(void) @@ -2107,219 +2916,269 @@ et4000w32p_revc_available(void) return rom_present(BIOS_ROM_PATH_W32P_REVC); } - int et4000w32p_noncardex_available(void) { return rom_present(BIOS_ROM_PATH_W32P); } - int et4000w32p_available(void) { return rom_present(BIOS_ROM_PATH_DIAMOND); } - int et4000w32p_cardex_available(void) { return rom_present(BIOS_ROM_PATH_CARDEX); } - void -et4000w32p_close(void *p) +et4000w32p_close(void *priv) { - et4000w32p_t *et4000 = (et4000w32p_t *)p; + et4000w32p_t *et4000 = (et4000w32p_t *) priv; svga_close(&et4000->svga); free(et4000); } - void -et4000w32p_speed_changed(void *p) +et4000w32p_speed_changed(void *priv) { - et4000w32p_t *et4000 = (et4000w32p_t *)p; + et4000w32p_t *et4000 = (et4000w32p_t *) priv; svga_recalctimings(&et4000->svga); } - void -et4000w32p_force_redraw(void *p) +et4000w32p_force_redraw(void *priv) { - et4000w32p_t *et4000 = (et4000w32p_t *)p; + et4000w32p_t *et4000 = (et4000w32p_t *) priv; et4000->svga.fullchange = changeframecount; } - -static const device_config_t et4000w32p_config[] = -{ - { - "memory", "Memory size", CONFIG_SELECTION, "", 2, "", { 0 }, - { - { - "1 MB", 1 - }, - { - "2 MB", 2 - }, - { - "" - } - } - }, - { - "", "", -1 +static const device_config_t et4000w32p_config[] = { + // clang-format off + { + .name = "memory", + .description = "Memory size", + .type = CONFIG_SELECTION, + .default_int = 2, + .selection = { + { + .description = "1 MB", + .value = 1 + }, + { + .description = "2 MB", + .value = 2 + }, + { + .description = "" + } } + }, + { + .type = CONFIG_END + } + // clang-format on }; - -const device_t et4000w32_device = -{ - "Tseng Labs ET4000/w32 ISA", - "et4000w32", - DEVICE_ISA | DEVICE_AT, ET4000W32, - et4000w32p_init, et4000w32p_close, NULL, - { et4000w32_available }, - et4000w32p_speed_changed, - et4000w32p_force_redraw, - NULL +const device_t et4000w32_device = { + .name = "Tseng Labs ET4000/w32 ISA", + .internal_name = "et4000w32", + .flags = DEVICE_ISA | DEVICE_AT, + .local = ET4000W32, + .init = et4000w32p_init, + .close = et4000w32p_close, + .reset = NULL, + { .available = et4000w32_available }, + .speed_changed = et4000w32p_speed_changed, + .force_redraw = et4000w32p_force_redraw, + .config = NULL }; -const device_t et4000w32_onboard_device = -{ - "Tseng Labs ET4000/w32 (ISA) (On-Board)", - "et4000w32_onboard", - DEVICE_ISA | DEVICE_AT, ET4000W32, - et4000w32p_init, et4000w32p_close, NULL, - { et4000w32_available }, - et4000w32p_speed_changed, - et4000w32p_force_redraw, - NULL +const device_t et4000w32_onboard_device = { + .name = "Tseng Labs ET4000/w32 (ISA) (On-Board)", + .internal_name = "et4000w32_onboard", + .flags = DEVICE_ISA | DEVICE_AT, + .local = ET4000W32, + .init = et4000w32p_init, + .close = et4000w32p_close, + .reset = NULL, + { .available = et4000w32_available }, + .speed_changed = et4000w32p_speed_changed, + .force_redraw = et4000w32p_force_redraw, + .config = NULL }; -const device_t et4000w32i_isa_device = -{ - "Tseng Labs ET4000/w32i Rev. B ISA", - "et4000w32i", - DEVICE_ISA | DEVICE_AT, ET4000W32I, - et4000w32p_init, et4000w32p_close, NULL, - { et4000w32i_isa_available }, - et4000w32p_speed_changed, - et4000w32p_force_redraw, - NULL +const device_t et4000w32i_isa_device = { + .name = "Tseng Labs ET4000/w32i Rev. B ISA", + .internal_name = "et4000w32i", + .flags = DEVICE_ISA | DEVICE_AT, + .local = ET4000W32I, + .init = et4000w32p_init, + .close = et4000w32p_close, + .reset = NULL, + { .available = et4000w32i_isa_available }, + .speed_changed = et4000w32p_speed_changed, + .force_redraw = et4000w32p_force_redraw, + .config = NULL }; -const device_t et4000w32i_vlb_device = -{ - "Tseng Labs ET4000/w32i Rev. B VLB", - "et4000w32i_vlb", - DEVICE_VLB, ET4000W32I, - et4000w32p_init, et4000w32p_close, NULL, - { et4000w32i_vlb_available }, - et4000w32p_speed_changed, - et4000w32p_force_redraw, - et4000w32p_config +const device_t et4000w32i_vlb_device = { + .name = "Tseng Labs ET4000/w32i Rev. B VLB", + .internal_name = "et4000w32i_vlb", + .flags = DEVICE_VLB, + .local = ET4000W32I, + .init = et4000w32p_init, + .close = et4000w32p_close, + .reset = NULL, + { .available = et4000w32i_vlb_available }, + .speed_changed = et4000w32p_speed_changed, + .force_redraw = et4000w32p_force_redraw, + .config = et4000w32p_config }; -const device_t et4000w32p_revc_vlb_device = -{ - "Tseng Labs ET4000/w32p Rev. C VLB (Cardex)", - "et4000w32p_revc_vlb", - DEVICE_VLB, ET4000W32P_REVC, - et4000w32p_init, et4000w32p_close, NULL, - { et4000w32p_revc_available }, - et4000w32p_speed_changed, - et4000w32p_force_redraw, - et4000w32p_config +const device_t et4000w32p_videomagic_revb_vlb_device = { + .name = "Tseng Labs ET4000/w32p Rev. B VLB (VideoMagic)", + .internal_name = "et4000w32p_videomagic_revb_vlb", + .flags = DEVICE_VLB, + .local = ET4000W32P_VIDEOMAGIC_REVB, + .init = et4000w32p_init, + .close = et4000w32p_close, + .reset = NULL, + { .available = et4000w32p_videomagic_revb_vlb_available }, + .speed_changed = et4000w32p_speed_changed, + .force_redraw = et4000w32p_force_redraw, + .config = et4000w32p_config }; -const device_t et4000w32p_revc_pci_device = -{ - "Tseng Labs ET4000/w32p Rev. C PCI (Cardex)", - "et4000w32p_revc_pci", - DEVICE_PCI, ET4000W32P_REVC, - et4000w32p_init, et4000w32p_close, NULL, - { et4000w32p_revc_available }, - et4000w32p_speed_changed, - et4000w32p_force_redraw, - et4000w32p_config +const device_t et4000w32p_videomagic_revb_pci_device = { + .name = "Tseng Labs ET4000/w32p Rev. B PCI (VideoMagic)", + .internal_name = "et4000w32p_videomagic_revb_pci", + .flags = DEVICE_PCI, + .local = ET4000W32P_VIDEOMAGIC_REVB, + .init = et4000w32p_init, + .close = et4000w32p_close, + .reset = NULL, + { .available = et4000w32p_videomagic_revb_vlb_available }, + .speed_changed = et4000w32p_speed_changed, + .force_redraw = et4000w32p_force_redraw, + .config = et4000w32p_config }; -const device_t et4000w32p_noncardex_vlb_device = -{ - "Tseng Labs ET4000/w32p Rev. D VLB", - "et4000w32p_nc_vlb", - DEVICE_VLB, ET4000W32P, - et4000w32p_init, et4000w32p_close, NULL, - { et4000w32p_noncardex_available }, - et4000w32p_speed_changed, - et4000w32p_force_redraw, - et4000w32p_config +const device_t et4000w32p_revc_vlb_device = { + .name = "Tseng Labs ET4000/w32p Rev. C VLB (Cardex)", + .internal_name = "et4000w32p_revc_vlb", + .flags = DEVICE_VLB, + .local = ET4000W32P_REVC, + .init = et4000w32p_init, + .close = et4000w32p_close, + .reset = NULL, + { .available = et4000w32p_revc_available }, + .speed_changed = et4000w32p_speed_changed, + .force_redraw = et4000w32p_force_redraw, + .config = et4000w32p_config }; -const device_t et4000w32p_noncardex_pci_device = -{ - "Tseng Labs ET4000/w32p Rev. D PCI", - "et4000w32p_nc_pci", - DEVICE_PCI, ET4000W32P, - et4000w32p_init, et4000w32p_close, NULL, - { et4000w32p_noncardex_available }, - et4000w32p_speed_changed, - et4000w32p_force_redraw, - et4000w32p_config +const device_t et4000w32p_revc_pci_device = { + .name = "Tseng Labs ET4000/w32p Rev. C PCI (Cardex)", + .internal_name = "et4000w32p_revc_pci", + .flags = DEVICE_PCI, + .local = ET4000W32P_REVC, + .init = et4000w32p_init, + .close = et4000w32p_close, + .reset = NULL, + { .available = et4000w32p_revc_available }, + .speed_changed = et4000w32p_speed_changed, + .force_redraw = et4000w32p_force_redraw, + .config = et4000w32p_config }; -const device_t et4000w32p_cardex_vlb_device = -{ - "Tseng Labs ET4000/w32p Rev. D VLB (Cardex)", - "et4000w32p_vlb", - DEVICE_VLB, ET4000W32P_CARDEX, - et4000w32p_init, et4000w32p_close, NULL, - { et4000w32p_cardex_available }, - et4000w32p_speed_changed, - et4000w32p_force_redraw, - et4000w32p_config +const device_t et4000w32p_noncardex_vlb_device = { + .name = "Tseng Labs ET4000/w32p Rev. D VLB", + .internal_name = "et4000w32p_nc_vlb", + .flags = DEVICE_VLB, + .local = ET4000W32P, + .init = et4000w32p_init, + .close = et4000w32p_close, + .reset = NULL, + { .available = et4000w32p_noncardex_available }, + .speed_changed = et4000w32p_speed_changed, + .force_redraw = et4000w32p_force_redraw, + .config = et4000w32p_config }; -const device_t et4000w32p_cardex_pci_device = -{ - "Tseng Labs ET4000/w32p Rev. D PCI (Cardex)", - "et4000w32p_pci", - DEVICE_PCI, ET4000W32P_CARDEX, - et4000w32p_init, et4000w32p_close, NULL, - { et4000w32p_cardex_available }, - et4000w32p_speed_changed, - et4000w32p_force_redraw, - et4000w32p_config +const device_t et4000w32p_noncardex_pci_device = { + .name = "Tseng Labs ET4000/w32p Rev. D PCI", + .internal_name = "et4000w32p_nc_pci", + .flags = DEVICE_PCI, + .local = ET4000W32P, + .init = et4000w32p_init, + .close = et4000w32p_close, + .reset = NULL, + { .available = et4000w32p_noncardex_available }, + .speed_changed = et4000w32p_speed_changed, + .force_redraw = et4000w32p_force_redraw, + .config = et4000w32p_config }; -const device_t et4000w32p_vlb_device = -{ - "Tseng Labs ET4000/w32p Rev. D VLB (Diamond Stealth32)", - "stealth32_vlb", - DEVICE_VLB, ET4000W32P_DIAMOND, - et4000w32p_init, et4000w32p_close, NULL, - { et4000w32p_available }, - et4000w32p_speed_changed, - et4000w32p_force_redraw, - et4000w32p_config +const device_t et4000w32p_cardex_vlb_device = { + .name = "Tseng Labs ET4000/w32p Rev. D VLB (Cardex)", + .internal_name = "et4000w32p_vlb", + .flags = DEVICE_VLB, + .local = ET4000W32P_CARDEX, + .init = et4000w32p_init, + .close = et4000w32p_close, + .reset = NULL, + { .available = et4000w32p_cardex_available }, + .speed_changed = et4000w32p_speed_changed, + .force_redraw = et4000w32p_force_redraw, + .config = et4000w32p_config }; -const device_t et4000w32p_pci_device = -{ - "Tseng Labs ET4000/w32p Rev. D PCI (Diamond Stealth32)", - "stealth32_pci", - DEVICE_PCI, ET4000W32P_DIAMOND, - et4000w32p_init, et4000w32p_close, NULL, - { et4000w32p_available }, - et4000w32p_speed_changed, - et4000w32p_force_redraw, - et4000w32p_config +const device_t et4000w32p_cardex_pci_device = { + .name = "Tseng Labs ET4000/w32p Rev. D PCI (Cardex)", + .internal_name = "et4000w32p_pci", + .flags = DEVICE_PCI, + .local = ET4000W32P_CARDEX, + .init = et4000w32p_init, + .close = et4000w32p_close, + .reset = NULL, + { .available = et4000w32p_cardex_available }, + .speed_changed = et4000w32p_speed_changed, + .force_redraw = et4000w32p_force_redraw, + .config = et4000w32p_config +}; + +const device_t et4000w32p_vlb_device = { + .name = "Tseng Labs ET4000/w32p Rev. D VLB (Diamond Stealth32)", + .internal_name = "stealth32_vlb", + .flags = DEVICE_VLB, + .local = ET4000W32P_DIAMOND, + .init = et4000w32p_init, + .close = et4000w32p_close, + .reset = NULL, + { .available = et4000w32p_available }, + .speed_changed = et4000w32p_speed_changed, + .force_redraw = et4000w32p_force_redraw, + .config = et4000w32p_config +}; + +const device_t et4000w32p_pci_device = { + .name = "Tseng Labs ET4000/w32p Rev. D PCI (Diamond Stealth32)", + .internal_name = "stealth32_pci", + .flags = DEVICE_PCI, + .local = ET4000W32P_DIAMOND, + .init = et4000w32p_init, + .close = et4000w32p_close, + .reset = NULL, + { .available = et4000w32p_available }, + .speed_changed = et4000w32p_speed_changed, + .force_redraw = et4000w32p_force_redraw, + .config = et4000w32p_config }; diff --git a/src/video/vid_f82c425.c b/src/video/vid_f82c425.c index 96263e306..772926e1e 100644 --- a/src/video/vid_f82c425.c +++ b/src/video/vid_f82c425.c @@ -1,36 +1,36 @@ /* - * 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. + * 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. + * This file is part of the 86Box distribution. * - * Chips & Technologies 82C425 display controller emulation, - * with support for 640x200 LCD and SMARTMAP text contrast - * enhancement. + * Chips & Technologies 82C425 display controller emulation, + * with support for 640x200 LCD and SMARTMAP text contrast + * enhancement. * - * Relevant literature: + * Relevant literature: * - * [1] Chips and Technologies, Inc., 82C425 CGA LCD/CRT Controller, - * Data Sheet, Revision No. 2.2, September 1991. - * + * [1] Chips and Technologies, Inc., 82C425 CGA LCD/CRT Controller, + * Data Sheet, Revision No. 2.2, September 1991. + * * - * [2] Pleva et al., COLOR TO MONOCHROME CONVERSION, - * U.S. Patent 4,977,398, Dec. 11, 1990. - * + * [2] Pleva et al., COLOR TO MONOCHROME CONVERSION, + * U.S. Patent 4,977,398, Dec. 11, 1990. + * * - * Based on Toshiba T1000 plasma display emulation code. + * Based on Toshiba T1000 plasma display emulation code. * - * Authors: Fred N. van Kempen, - * Miran Grca, - * Sarah Walker, - * Lubomir Rintel, + * Authors: Fred N. van Kempen, + * Miran Grca, + * John Elliott, + * Lubomir Rintel, * - * Copyright 2018,2019 Fred N. van Kempen. - * Copyright 2018,2019 Miran Grca. - * Copyright 2018,2019 Sarah Walker. - * Copyright 2021 Lubomir Rintel. + * Copyright 2018-2019 Fred N. van Kempen. + * Copyright 2018-2019 Miran Grca. + * Copyright 2018-2019 John Elliott. + * Copyright 2021 Lubomir Rintel. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -39,7 +39,7 @@ * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * General Public License for more details. * * You should have received a copy of the GNU General Public License @@ -63,6 +63,7 @@ #include "cpu.h" #include <86box/video.h> #include <86box/vid_cga.h> +#include <86box/plat_unused.h> #define F82C425_XSIZE 640 #define F82C425_YSIZE 200 @@ -71,101 +72,103 @@ static uint32_t smartmap[256][2]; static uint32_t colormap[4]; -static video_timings_t timing_f82c425 = {VIDEO_ISA, 8,16,32, 8,16,32}; +static video_timings_t timing_f82c425 = { .type = VIDEO_ISA, .write_b = 8, .write_w = 16, .write_l = 32, .read_b = 8, .read_w = 16, .read_l = 32 }; static uint8_t st_video_options; -static uint8_t st_enabled = 1; -static int8_t st_display_internal = -1; +static uint8_t st_enabled = 1; +static int8_t st_display_internal = -1; -void f82c425_video_options_set(uint8_t options) +void +f82c425_video_options_set(uint8_t options) { - st_video_options = options; + st_video_options = options; } -void f82c425_video_enable(uint8_t enabled) +void +f82c425_video_enable(uint8_t enabled) { - st_enabled = enabled; + st_enabled = enabled; } -void f82c425_display_set(uint8_t internal) +void +f82c425_display_set(uint8_t internal) { - st_display_internal = (int8_t)internal; + st_display_internal = (int8_t) internal; } -uint8_t f82c425_display_get() +uint8_t +f82c425_display_get(void) { - return (uint8_t)st_display_internal; + return (uint8_t) st_display_internal; } +typedef struct f82c425_t { + mem_mapping_t mapping; + cga_t cga; + uint8_t crtcreg; -typedef struct f82c425_t -{ - mem_mapping_t mapping; - cga_t cga; - uint8_t crtcreg; + uint64_t dispontime, dispofftime; - uint64_t dispontime, dispofftime; + int linepos, displine; + int dispon; + uint8_t video_options; - int linepos, displine; - int dispon; - uint8_t video_options; + uint8_t *vram; - uint8_t *vram; - - /* Registers specific to 82C425. */ - uint8_t ac_limit; - uint8_t threshold; - uint8_t shift; - uint8_t hsync; - uint8_t vsync_blink; - uint8_t timing; - uint8_t function; + /* Registers specific to 82C425. */ + uint8_t ac_limit; + uint8_t threshold; + uint8_t shift; + uint8_t hsync; + uint8_t vsync_blink; + uint8_t timing; + uint8_t function; } f82c425_t; - /* Convert IRGB representation to RGBI, * useful in SMARTMAP calculations. */ -static inline uint8_t f82c425_rgbi(uint8_t irgb) +static inline uint8_t +f82c425_rgbi(uint8_t irgb) { - return ((irgb & 0x7) << 1) | (irgb >> 3); + return ((irgb & 0x7) << 1) | (irgb >> 3); } /* Convert IRGB SMARTMAP output to a RGB representation of one of 4/8 grey * shades we'd see on an actual V86P display: with some bias toward lighter * shades and a backlight with yellow/green-ish tint. */ -static inline uint32_t f82c425_makecol(uint8_t rgbi, int gs4, int inv) +static inline uint32_t +f82c425_makecol(uint8_t rgbi, int gs4, int inv) { - uint8_t c; + uint8_t c; - gs4 = 1 + !!gs4; - if (!inv) - { - rgbi = 15 - rgbi; - } - c = 0x10 * gs4 * ((rgbi >> gs4) + 2); + gs4 = 1 + !!gs4; + if (!inv) { + rgbi = 15 - rgbi; + } + c = 0x10 * gs4 * ((rgbi >> gs4) + 2); #ifdef NO_BLUE - return makecol(c, c + 0x08, c - 0x20); + return makecol(c, c + 0x08, c - 0x20); #else - return makecol(c, c + 0x08, 0x70); + return makecol(c, c + 0x08, 0x70); #endif } /* Saturating/non-saturating addition for SMARTMAP(see below). */ -static inline int f82c425_smartmap_add(int a, int b, int sat) +static inline int +f82c425_smartmap_add(int a, int b, int sat) { - int c = a + b; + int c = a + b; - /* (SATURATING OR NON SATURATING) */ - if (sat) - { - if (c < 0) - c = 0; - else if (c > 15) - c = 15; - } + /* (SATURATING OR NON SATURATING) */ + if (sat) { + if (c < 0) + c = 0; + else if (c > 15) + c = 15; + } - return c & 0xf; + return c & 0xf; } /* Calculate and cache mapping of CGA text color attribute to a @@ -174,500 +177,462 @@ static inline int f82c425_smartmap_add(int a, int b, int sat) * This is a straightforward implementation of the algorithm as described * in U.S. Patent 4,977,398 [2]. The comments in capitals refer to portions * of a figure on page 4. */ -static void f82c425_smartmap(f82c425_t *f82c425) +static void +f82c425_smartmap(f82c425_t *f82c425) { - int i; + for (uint16_t i = 0; i < 256; i++) { + uint8_t bg = f82c425_rgbi(i >> 4); + uint8_t fg = f82c425_rgbi(i & 0xf); - for (i = 0; i < 256; i++) { - uint8_t bg = f82c425_rgbi(i >> 4); - uint8_t fg = f82c425_rgbi(i & 0xf); + /* FIG._4. */ + if (abs(bg - fg) <= (f82c425->threshold & 0x0f)) { + /* FOREGROUND=BACKGROUND */ + if (bg == fg) { + /* SPECIAL CASE */ + if (f82c425->shift == 0xff) { + /* CHECK MOST SIGNIFICANT BIT */ + if (fg & 0x8) { + /* FULL WHITE */ + fg = bg = 15; + } else { + /* FULL BLACK */ + fg = bg = 0; + } + } + } else { + uint8_t sat = f82c425->threshold & 0x10; - /* FIG._4. */ - if (abs(bg - fg) <= (f82c425->threshold & 0x0f)) - { - /* FOREGROUND=BACKGROUND */ - if (bg == fg) - { - /* SPECIAL CASE */ - if (f82c425->shift == 0xff) - { - /* CHECK MOST SIGNIFICANT BIT */ - if (fg & 0x8) - { - /* FULL WHITE */ - fg = bg = 15; - } - else - { - /* FULL BLACK */ - fg = bg = 0; - } - } - } - else - { - uint8_t sat = f82c425->threshold & 0x10; + /* DETERMINE WHICH IS LIGHT */ + if (fg > bg) { + fg = f82c425_smartmap_add(fg, f82c425->shift & 0x0f, sat); + bg = f82c425_smartmap_add(bg, -(f82c425->shift >> 4), sat); + } else { + fg = f82c425_smartmap_add(fg, -(f82c425->shift & 0x0f), sat); + bg = f82c425_smartmap_add(bg, f82c425->shift >> 4, sat); + } + } + } - /* DETERMINE WHICH IS LIGHT */ - if (fg > bg) - { - fg = f82c425_smartmap_add(fg, f82c425->shift & 0x0f, sat); - bg = f82c425_smartmap_add(bg, -(f82c425->shift >> 4), sat); - } - else - { - fg = f82c425_smartmap_add(fg, -(f82c425->shift & 0x0f), sat); - bg = f82c425_smartmap_add(bg, f82c425->shift >> 4, sat); - } - } - } - - smartmap[i][0] = f82c425_makecol(bg, f82c425->threshold & 0x20, f82c425->function & 0x80); - smartmap[i][1] = f82c425_makecol(fg, f82c425->threshold & 0x20, f82c425->function & 0x80); - } + smartmap[i][0] = f82c425_makecol(bg, f82c425->threshold & 0x20, f82c425->function & 0x80); + smartmap[i][1] = f82c425_makecol(fg, f82c425->threshold & 0x20, f82c425->function & 0x80); + } } /* Calculate mapping of 320x200 graphical mode colors. */ -static void f82c425_colormap(f82c425_t *f82c425) +static void +f82c425_colormap(f82c425_t *f82c425) { - int i; - - for (i = 0; i < 4; i++) - colormap[i] = f82c425_makecol(5 * i, 0, f82c425->function & 0x80); + for (uint8_t i = 0; i < 4; i++) + colormap[i] = f82c425_makecol(5 * i, 0, f82c425->function & 0x80); } -static void f82c425_out(uint16_t addr, uint8_t val, void *p) +static void +f82c425_out(uint16_t addr, uint8_t val, void *priv) { - f82c425_t *f82c425 = (f82c425_t *)p; + f82c425_t *f82c425 = (f82c425_t *) priv; - if (addr == 0x3d4) - f82c425->crtcreg = val; + if (addr == 0x3d4) + f82c425->crtcreg = val; - if (((f82c425->function & 0x01) == 0) && ((f82c425->crtcreg != 0xdf) || (addr != 0x3d5))) - return; + if (((f82c425->function & 0x01) == 0) && ((f82c425->crtcreg != 0xdf) || (addr != 0x3d5))) + return; - if (addr != 0x3d5 || f82c425->crtcreg <= 31) - { - cga_out(addr, val, &f82c425->cga); - return; - } + if (addr != 0x3d5 || f82c425->crtcreg <= 31) { + cga_out(addr, val, &f82c425->cga); + return; + } - switch (f82c425->crtcreg) - { - case 0xd9: - f82c425->ac_limit = val; - break; - case 0xda: - f82c425->threshold = val; - f82c425_smartmap(f82c425); - break; - case 0xdb: - f82c425->shift = val; - f82c425_smartmap(f82c425); - break; - case 0xdc: - f82c425->hsync = val; - break; - case 0xdd: - f82c425->vsync_blink = val; - break; - case 0xde: - f82c425->timing = val; - break; - case 0xdf: - f82c425->function = val; - f82c425_smartmap(f82c425); - f82c425_colormap(f82c425); - break; - } + switch (f82c425->crtcreg) { + case 0xd9: + f82c425->ac_limit = val; + break; + case 0xda: + f82c425->threshold = val; + f82c425_smartmap(f82c425); + break; + case 0xdb: + f82c425->shift = val; + f82c425_smartmap(f82c425); + break; + case 0xdc: + f82c425->hsync = val; + break; + case 0xdd: + f82c425->vsync_blink = val; + break; + case 0xde: + f82c425->timing = val; + break; + case 0xdf: + f82c425->function = val; + f82c425_smartmap(f82c425); + f82c425_colormap(f82c425); + break; + + default: + break; + } } -static uint8_t f82c425_in(uint16_t addr, void *p) +static uint8_t +f82c425_in(uint16_t addr, void *priv) { - f82c425_t *f82c425 = (f82c425_t *)p; + f82c425_t *f82c425 = (f82c425_t *) priv; - if ((f82c425->function & 0x01) == 0) - return 0xff; + if ((f82c425->function & 0x01) == 0) + return 0xff; - if (addr == 0x3d4) - return f82c425->crtcreg; + if (addr == 0x3d4) + return f82c425->crtcreg; - if (addr != 0x3d5 || f82c425->crtcreg <= 31) - return cga_in(addr, &f82c425->cga); + if (addr != 0x3d5 || f82c425->crtcreg <= 31) + return cga_in(addr, &f82c425->cga); - switch (f82c425->crtcreg) - { - case 0xd9: - return f82c425->ac_limit; - case 0xda: - return f82c425->threshold; - case 0xdb: - return f82c425->shift; - case 0xdc: - return f82c425->hsync; - case 0xdd: - return f82c425->vsync_blink; - case 0xde: - return f82c425->timing; - case 0xdf: - return f82c425->function; - } + switch (f82c425->crtcreg) { + case 0xd9: + return f82c425->ac_limit; + case 0xda: + return f82c425->threshold; + case 0xdb: + return f82c425->shift; + case 0xdc: + return f82c425->hsync; + case 0xdd: + return f82c425->vsync_blink; + case 0xde: + return f82c425->timing; + case 0xdf: + return f82c425->function; - return 0xff; + default: + break; + } + + return 0xff; } -static void f82c425_write(uint32_t addr, uint8_t val, void *p) +static void +f82c425_write(uint32_t addr, uint8_t val, void *priv) { - f82c425_t *f82c425 = (f82c425_t *)p; + f82c425_t *f82c425 = (f82c425_t *) priv; - f82c425->vram[addr & 0x3fff] = val; - cycles -= 4; + f82c425->vram[addr & 0x3fff] = val; + cycles -= 4; } -static uint8_t f82c425_read(uint32_t addr, void *p) +static uint8_t +f82c425_read(uint32_t addr, void *priv) { - f82c425_t *f82c425 = (f82c425_t *)p; - cycles -= 4; + const f82c425_t *f82c425 = (f82c425_t *) priv; - return f82c425->vram[addr & 0x3fff]; + cycles -= 4; + + return f82c425->vram[addr & 0x3fff]; } -static void f82c425_recalctimings(f82c425_t *f82c425) +static void +f82c425_recalctimings(f82c425_t *f82c425) { - double disptime; - double _dispontime, _dispofftime; + double disptime; + double _dispontime; + double _dispofftime; - if (f82c425->function & 0x08) - { - cga_recalctimings(&f82c425->cga); - return; - } + if (f82c425->function & 0x08) { + cga_recalctimings(&f82c425->cga); + return; + } - disptime = 651; - _dispontime = 640; - _dispofftime = disptime - _dispontime; - f82c425->dispontime = (uint64_t)(_dispontime * xt_cpu_multi); - f82c425->dispofftime = (uint64_t)(_dispofftime * xt_cpu_multi); + disptime = 651; + _dispontime = 640; + _dispofftime = disptime - _dispontime; + f82c425->dispontime = (uint64_t) (_dispontime * xt_cpu_multi); + f82c425->dispofftime = (uint64_t) (_dispofftime * xt_cpu_multi); } /* Draw a row of text. */ -static void f82c425_text_row(f82c425_t *f82c425) +static void +f82c425_text_row(f82c425_t *f82c425) { - uint32_t colors[2]; - int x, c; - uint8_t chr, attr; - int drawcursor; - int cursorline; - int blink; - uint16_t addr; - uint8_t sc; - uint16_t ma = (f82c425->cga.crtc[0x0d] | (f82c425->cga.crtc[0x0c] << 8)) & 0x3fff; - uint16_t ca = (f82c425->cga.crtc[0x0f] | (f82c425->cga.crtc[0x0e] << 8)) & 0x3fff; - uint8_t sl = f82c425->cga.crtc[9] + 1; - int columns = f82c425->cga.crtc[1]; + uint32_t colors[2]; + int c; + uint8_t chr; + uint8_t attr; + int drawcursor; + int cursorline; + int blink; + uint16_t addr; + uint8_t sc; + uint16_t ma = (f82c425->cga.crtc[0x0d] | (f82c425->cga.crtc[0x0c] << 8)) & 0x3fff; + uint16_t ca = (f82c425->cga.crtc[0x0f] | (f82c425->cga.crtc[0x0e] << 8)) & 0x3fff; + uint8_t sl = f82c425->cga.crtc[9] + 1; + int columns = f82c425->cga.crtc[1]; - sc = (f82c425->displine) & 7; - addr = ((ma & ~1) + (f82c425->displine >> 3) * columns) * 2; - ma += (f82c425->displine >> 3) * columns; + sc = (f82c425->displine) & 7; + addr = ((ma & ~1) + (f82c425->displine >> 3) * columns) * 2; + ma += (f82c425->displine >> 3) * columns; - if ((f82c425->cga.crtc[0x0a] & 0x60) == 0x20) - { - cursorline = 0; - } - else - { - cursorline = ((f82c425->cga.crtc[0x0a] & 0x0F) <= sc) && - ((f82c425->cga.crtc[0x0b] & 0x0F) >= sc); - } + if ((f82c425->cga.crtc[0x0a] & 0x60) == 0x20) { + cursorline = 0; + } else { + cursorline = ((f82c425->cga.crtc[0x0a] & 0x0F) <= sc) && ((f82c425->cga.crtc[0x0b] & 0x0F) >= sc); + } - for (x = 0; x < columns; x++) - { - chr = f82c425->vram[(addr + 2 * x) & 0x3FFF]; - attr = f82c425->vram[(addr + 2 * x + 1) & 0x3FFF]; - drawcursor = ((ma == ca) && cursorline && - (f82c425->cga.cgamode & 0x8) && (f82c425->cga.cgablink & 0x10)); + for (int x = 0; x < columns; x++) { + chr = f82c425->vram[(addr + 2 * x) & 0x3FFF]; + attr = f82c425->vram[(addr + 2 * x + 1) & 0x3FFF]; + drawcursor = ((ma == ca) && cursorline && (f82c425->cga.cgamode & 0x8) && (f82c425->cga.cgablink & 0x10)); - blink = ((f82c425->cga.cgablink & 0x10) && (f82c425->cga.cgamode & 0x20) && - (attr & 0x80) && !drawcursor); + blink = ((f82c425->cga.cgablink & 0x10) && (f82c425->cga.cgamode & 0x20) && (attr & 0x80) && !drawcursor); - if (drawcursor) - { - colors[0] = smartmap[~attr & 0xff][0]; - colors[1] = smartmap[~attr & 0xff][1]; - } - else - { - colors[0] = smartmap[attr][0]; - colors[1] = smartmap[attr][1]; - } + if (drawcursor) { + colors[0] = smartmap[~attr & 0xff][0]; + colors[1] = smartmap[~attr & 0xff][1]; + } else { + colors[0] = smartmap[attr][0]; + colors[1] = smartmap[attr][1]; + } - if (blink) - colors[1] = colors[0]; + if (blink) + colors[1] = colors[0]; - if (f82c425->cga.cgamode & 0x01) - { - /* High resolution (80 cols) */ - for (c = 0; c < sl; c++) - { - ((uint32_t *)buffer32->line[f82c425->displine])[(x << 3) + c] = - colors[(fontdat[chr][sc] & (1 <<(c ^ 7))) ? 1 : 0]; - } - } - else - { - /* Low resolution (40 columns, stretch pixels horizontally) */ - for (c = 0; c < sl; c++) - { - ((uint32_t *)buffer32->line[f82c425->displine])[(x << 4) + c*2] = - ((uint32_t *)buffer32->line[f82c425->displine])[(x << 4) + c*2+1] = - colors[(fontdat[chr][sc] & (1 <<(c ^ 7))) ? 1 : 0]; - } - } + if (f82c425->cga.cgamode & 0x01) { + /* High resolution (80 cols) */ + for (c = 0; c < sl; c++) { + (buffer32->line[f82c425->displine])[(x << 3) + c] = colors[(fontdat[chr][sc] & (1 << (c ^ 7))) ? 1 : 0]; + } + } else { + /* Low resolution (40 columns, stretch pixels horizontally) */ + for (c = 0; c < sl; c++) { + (buffer32->line[f82c425->displine])[(x << 4) + c * 2] = (buffer32->line[f82c425->displine])[(x << 4) + c * 2 + 1] = colors[(fontdat[chr][sc] & (1 << (c ^ 7))) ? 1 : 0]; + } + } - ++ma; - } + ++ma; + } } /* Draw a line in CGA 640x200 mode */ -static void f82c425_cgaline6(f82c425_t *f82c425) +static void +f82c425_cgaline6(f82c425_t *f82c425) { - int x, c; - uint8_t dat; - uint16_t addr; + uint8_t dat; + uint16_t addr; - uint16_t ma = (f82c425->cga.crtc[0x0d] | (f82c425->cga.crtc[0x0c] << 8)) & 0x3fff; + uint16_t ma = (f82c425->cga.crtc[0x0d] | (f82c425->cga.crtc[0x0c] << 8)) & 0x3fff; - addr = ((f82c425->displine) & 1) * 0x2000 + - (f82c425->displine >> 1) * 80 + - ((ma & ~1) << 1); + addr = ((f82c425->displine) & 1) * 0x2000 + (f82c425->displine >> 1) * 80 + ((ma & ~1) << 1); - for (x = 0; x < 80; x++) - { - dat = f82c425->vram[addr & 0x3FFF]; - addr++; + for (uint8_t x = 0; x < 80; x++) { + dat = f82c425->vram[addr & 0x3FFF]; + addr++; - for (c = 0; c < 8; c++) - { - ((uint32_t *)buffer32->line[f82c425->displine])[x*8+c] = - colormap[dat & 0x80 ? 3 : 0]; + for (uint8_t c = 0; c < 8; c++) { + (buffer32->line[f82c425->displine])[x * 8 + c] = colormap[dat & 0x80 ? 3 : 0]; - dat = dat << 1; - } - } + dat = dat << 1; + } + } } /* Draw a line in CGA 320x200 mode. */ -static void f82c425_cgaline4(f82c425_t *f82c425) +static void +f82c425_cgaline4(f82c425_t *f82c425) { - int x, c; - uint8_t dat, pattern; - uint16_t addr; + uint8_t dat; + uint8_t pattern; + uint16_t addr; - uint16_t ma = (f82c425->cga.crtc[0x0d] | (f82c425->cga.crtc[0x0c] << 8)) & 0x3fff; - addr = ((f82c425->displine) & 1) * 0x2000 + - (f82c425->displine >> 1) * 80 + - ((ma & ~1) << 1); + uint16_t ma = (f82c425->cga.crtc[0x0d] | (f82c425->cga.crtc[0x0c] << 8)) & 0x3fff; + addr = ((f82c425->displine) & 1) * 0x2000 + (f82c425->displine >> 1) * 80 + ((ma & ~1) << 1); - for (x = 0; x < 80; x++) - { - dat = f82c425->vram[addr & 0x3FFF]; - addr++; + for (uint8_t x = 0; x < 80; x++) { + dat = f82c425->vram[addr & 0x3FFF]; + addr++; - for (c = 0; c < 4; c++) - { - pattern = (dat & 0xC0) >> 6; - if (!(f82c425->cga.cgamode & 0x08)) pattern = 0; + for (uint8_t c = 0; c < 4; c++) { + pattern = (dat & 0xC0) >> 6; + if (!(f82c425->cga.cgamode & 0x08)) + pattern = 0; - ((uint32_t *)buffer32->line[f82c425->displine])[x*8+2*c] = - ((uint32_t *)buffer32->line[f82c425->displine])[x*8+2*c+1] = - colormap[pattern & 3]; + (buffer32->line[f82c425->displine])[x * 8 + 2 * c] = (buffer32->line[f82c425->displine])[x * 8 + 2 * c + 1] = colormap[pattern & 3]; - dat = dat << 2; - } - } + dat = dat << 2; + } + } } -static void f82c425_poll(void *p) +static void +f82c425_poll(void *priv) { - f82c425_t *f82c425 = (f82c425_t *)p; + f82c425_t *f82c425 = (f82c425_t *) priv; - if (f82c425->video_options != st_video_options || - !!(f82c425->function & 1) != st_enabled) - { - f82c425->video_options = st_video_options; - f82c425->function &= ~1; - f82c425->function |= st_enabled ? 1 : 0; + if (f82c425->video_options != st_video_options || !!(f82c425->function & 1) != st_enabled) { + f82c425->video_options = st_video_options; + f82c425->function &= ~1; + f82c425->function |= st_enabled ? 1 : 0; - if (f82c425->function & 0x01) - mem_mapping_enable(&f82c425->mapping); - else - mem_mapping_disable(&f82c425->mapping); - } - /* Switch between internal LCD and external CRT display. */ - if (st_display_internal != -1 && st_display_internal != !!(f82c425->function & 0x08)) - { - if (st_display_internal) - { - f82c425->function &= ~0x08; - f82c425->timing &= ~0x20; - } - else - { - f82c425->function |= 0x08; - f82c425->timing |= 0x20; - } - f82c425_recalctimings(f82c425); - } + if (f82c425->function & 0x01) + mem_mapping_enable(&f82c425->mapping); + else + mem_mapping_disable(&f82c425->mapping); + } + /* Switch between internal LCD and external CRT display. */ + if (st_display_internal != -1 && st_display_internal != !!(f82c425->function & 0x08)) { + if (st_display_internal) { + f82c425->function &= ~0x08; + f82c425->timing &= ~0x20; + } else { + f82c425->function |= 0x08; + f82c425->timing |= 0x20; + } + f82c425_recalctimings(f82c425); + } - if (f82c425->function & 0x08) - { - cga_poll(&f82c425->cga); - return; - } + if (f82c425->function & 0x08) { + cga_poll(&f82c425->cga); + return; + } - if (!f82c425->linepos) - { - timer_advance_u64(&f82c425->cga.timer, f82c425->dispofftime); - f82c425->cga.cgastat |= 1; - f82c425->linepos = 1; - if (f82c425->dispon) - { - if (f82c425->displine == 0) - { - video_wait_for_buffer(); - } + if (!f82c425->linepos) { + timer_advance_u64(&f82c425->cga.timer, f82c425->dispofftime); + f82c425->cga.cgastat |= 1; + f82c425->linepos = 1; + if (f82c425->dispon) { + if (f82c425->displine == 0) { + video_wait_for_buffer(); + } - switch (f82c425->cga.cgamode & 0x13) - { - case 0x12: - f82c425_cgaline6(f82c425); - break; - case 0x02: - f82c425_cgaline4(f82c425); - break; - case 0x00: - case 0x01: - f82c425_text_row(f82c425); - break; - } - } - f82c425->displine++; + switch (f82c425->cga.cgamode & 0x13) { + case 0x12: + f82c425_cgaline6(f82c425); + break; + case 0x02: + f82c425_cgaline4(f82c425); + break; + case 0x00: + case 0x01: + f82c425_text_row(f82c425); + break; - /* Hardcode a fixed refresh rate and VSYNC timing */ - if (f82c425->displine >= 216) - { - /* End of VSYNC */ - f82c425->displine = 0; - f82c425->cga.cgastat &= ~8; - f82c425->dispon = 1; - } - else - if (f82c425->displine == (f82c425->cga.crtc[9] + 1) * f82c425->cga.crtc[6]) - { - /* Start of VSYNC */ - f82c425->cga.cgastat |= 8; - f82c425->dispon = 0; - } - } - else - { - if (f82c425->dispon) - f82c425->cga.cgastat &= ~1; - timer_advance_u64(&f82c425->cga.timer, f82c425->dispontime); - f82c425->linepos = 0; + default: + break; + } + } + f82c425->displine++; - if (f82c425->displine == 200) - { - /* Hardcode 640x200 window size */ - if ((F82C425_XSIZE != xsize) || (F82C425_YSIZE != ysize) || video_force_resize_get()) - { - xsize = F82C425_XSIZE; - ysize = F82C425_YSIZE; - set_screen_size(xsize, ysize); + /* Hardcode a fixed refresh rate and VSYNC timing */ + if (f82c425->displine >= 216) { + /* End of VSYNC */ + f82c425->displine = 0; + f82c425->cga.cgastat &= ~8; + f82c425->dispon = 1; + } else if (f82c425->displine == (f82c425->cga.crtc[9] + 1) * f82c425->cga.crtc[6]) { + /* Start of VSYNC */ + f82c425->cga.cgastat |= 8; + f82c425->dispon = 0; + } + } else { + if (f82c425->dispon) + f82c425->cga.cgastat &= ~1; + timer_advance_u64(&f82c425->cga.timer, f82c425->dispontime); + f82c425->linepos = 0; - if (video_force_resize_get()) - video_force_resize_set(0); - } - video_blit_memtoscreen(0, 0, xsize, ysize); - frames++; + if (f82c425->displine == 200) { + /* Hardcode 640x200 window size */ + if ((F82C425_XSIZE != xsize) || (F82C425_YSIZE != ysize) || video_force_resize_get()) { + xsize = F82C425_XSIZE; + ysize = F82C425_YSIZE; + set_screen_size(xsize, ysize); - /* Fixed 640x200 resolution */ - video_res_x = F82C425_XSIZE; - video_res_y = F82C425_YSIZE; + if (video_force_resize_get()) + video_force_resize_set(0); + } + video_blit_memtoscreen(0, 0, xsize, ysize); + frames++; - switch (f82c425->cga.cgamode & 0x12) - { - case 0x12: - video_bpp = 1; - break; - case 0x02: - video_bpp = 2; - break; - default: - video_bpp = 0; - } + /* Fixed 640x200 resolution */ + video_res_x = F82C425_XSIZE; + video_res_y = F82C425_YSIZE; - f82c425->cga.cgablink++; - } - } + switch (f82c425->cga.cgamode & 0x12) { + case 0x12: + video_bpp = 1; + break; + case 0x02: + video_bpp = 2; + break; + default: + video_bpp = 0; + } + + f82c425->cga.cgablink++; + } + } } -static void *f82c425_init(const device_t *info) +static void * +f82c425_init(UNUSED(const device_t *info)) { - f82c425_t *f82c425 = malloc(sizeof(f82c425_t)); - memset(f82c425, 0, sizeof(f82c425_t)); - cga_init(&f82c425->cga); - video_inform(VIDEO_FLAG_TYPE_CGA, &timing_f82c425); + f82c425_t *f82c425 = malloc(sizeof(f82c425_t)); - /* Initialize registers that don't default to zero. */ - f82c425->hsync = 0x40; - f82c425->vsync_blink = 0x72; + memset(f82c425, 0, sizeof(f82c425_t)); + cga_init(&f82c425->cga); + video_inform(VIDEO_FLAG_TYPE_CGA, &timing_f82c425); - /* 16k video RAM */ - f82c425->vram = malloc(0x4000); + /* Initialize registers that don't default to zero. */ + f82c425->hsync = 0x40; + f82c425->vsync_blink = 0x72; - timer_set_callback(&f82c425->cga.timer, f82c425_poll); - timer_set_p(&f82c425->cga.timer, f82c425); + /* 16k video RAM */ + f82c425->vram = malloc(0x4000); - /* Occupy memory between 0xB8000 and 0xBFFFF */ - mem_mapping_add(&f82c425->mapping, 0xb8000, 0x8000, f82c425_read, NULL, NULL, f82c425_write, NULL, NULL, NULL, 0, f82c425); - /* Respond to CGA I/O ports */ - io_sethandler(0x03d0, 0x000c, f82c425_in, NULL, NULL, f82c425_out, NULL, NULL, f82c425); + timer_set_callback(&f82c425->cga.timer, f82c425_poll); + timer_set_p(&f82c425->cga.timer, f82c425); - /* Initialize color maps for text & graphic modes */ - f82c425_smartmap(f82c425); - f82c425_colormap(f82c425); + /* Occupy memory between 0xB8000 and 0xBFFFF */ + mem_mapping_add(&f82c425->mapping, 0xb8000, 0x8000, f82c425_read, NULL, NULL, f82c425_write, NULL, NULL, NULL, 0, f82c425); + /* Respond to CGA I/O ports */ + io_sethandler(0x03d0, 0x000c, f82c425_in, NULL, NULL, f82c425_out, NULL, NULL, f82c425); - /* Start off in 80x25 text mode */ - f82c425->cga.cgastat = 0xF4; - f82c425->cga.vram = f82c425->vram; - f82c425->video_options = 0x01; + /* Initialize color maps for text & graphic modes */ + f82c425_smartmap(f82c425); + f82c425_colormap(f82c425); - return f82c425; + /* Start off in 80x25 text mode */ + f82c425->cga.cgastat = 0xF4; + f82c425->cga.vram = f82c425->vram; + f82c425->video_options = 0x01; + + return f82c425; } -static void f82c425_close(void *p) +static void +f82c425_close(void *priv) { - f82c425_t *f82c425 = (f82c425_t *)p; + f82c425_t *f82c425 = (f82c425_t *) priv; - free(f82c425->vram); - free(f82c425); + free(f82c425->vram); + free(f82c425); } -static void f82c425_speed_changed(void *p) +static void +f82c425_speed_changed(void *priv) { - f82c425_t *f82c425 = (f82c425_t *)p; + f82c425_t *f82c425 = (f82c425_t *) priv; - f82c425_recalctimings(f82c425); + f82c425_recalctimings(f82c425); } const device_t f82c425_video_device = { - "82C425 CGA LCD/CRT Controller", - "f82c425_video", - 0, 0, - f82c425_init, f82c425_close, NULL, - { NULL }, - f82c425_speed_changed, - NULL, - NULL + .name = "82C425 CGA LCD/CRT Controller", + .internal_name = "f82c425_video", + .flags = 0, + .local = 0, + .init = f82c425_init, + .close = f82c425_close, + .reset = NULL, + { .available = NULL }, + .speed_changed = f82c425_speed_changed, + .force_redraw = NULL, + .config = NULL }; diff --git a/src/video/vid_genius.c b/src/video/vid_genius.c index 820331d8b..4ae8e6fd1 100644 --- a/src/video/vid_genius.c +++ b/src/video/vid_genius.c @@ -1,20 +1,20 @@ /* - * 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. + * 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. + * This file is part of the 86Box distribution. * - * MDSI Genius VHR emulation. + * MDSI Genius VHR emulation. * * * - * Authors: Sarah Walker, - * Miran Grca, + * Authors: John Elliott, + * Miran Grca, * - * Copyright 2008-2019 Sarah Walker. - * Copyright 2016-2019 Miran Grca. + * Copyright 2008-2019 John Elliott. + * Copyright 2016-2019 Miran Grca. */ #include #include @@ -32,23 +32,19 @@ #include <86box/plat.h> #include <86box/video.h> +#define BIOS_ROM_PATH "roms/video/genius/8x12.bin" -#define BIOS_ROM_PATH "roms/video/genius/8x12.bin" - - -#define GENIUS_XSIZE 728 -#define GENIUS_YSIZE 1008 - +#define GENIUS_XSIZE 728 +#define GENIUS_YSIZE 1008 extern uint8_t fontdat8x12[256][16]; -static video_timings_t timing_genius = {VIDEO_ISA, 8, 16, 32, 8, 16, 32}; - +static video_timings_t timing_genius = { .type = VIDEO_ISA, .write_b = 8, .write_w = 16, .write_l = 32, .read_b = 8, .read_w = 16, .read_l = 32 }; /* I'm at something of a disadvantage writing this emulation: I don't have an - * MDSI Genius card, nor do I have the BIOS extension (VHRBIOS.SYS) that came + * MDSI Genius card, nor do I have the BIOS extension (VHRBIOS.SYS) that came * with it. What I do have are the GEM and Windows 1.04 drivers, plus a driver - * for a later MCA version of the card. The latter can be found at + * for a later MCA version of the card. The latter can be found at * and is necessary if you * want the Windows driver to work. * @@ -57,9 +53,9 @@ static video_timings_t timing_genius = {VIDEO_ISA, 8, 16, 32, 8, 16, 32}; * The GEM driver SDGEN9.VGA * The Windows 1.04 driver GENIUS.DRV * - * As far as I can see, the card uses a fixed resolution of 728x1008 pixels. + * As far as I can see, the card uses a fixed resolution of 728x1008 pixels. * It has the following modes of operation: - * + * * > MDA-compatible: 80x25 text, each character 9x15 pixels. * > CGA-compatible: 640x200 mono graphics * > Dual: MDA text in the top half, CGA graphics in the bottom @@ -67,18 +63,18 @@ static video_timings_t timing_genius = {VIDEO_ISA, 8, 16, 32, 8, 16, 32}; * > Native graphics: 728x1008 mono graphics. * * Under the covers, this seems to translate to: - * > Text framebuffer. At B000:0000, 16k. Displayed if enable bit is set + * > Text framebuffer. At B000:0000, 16k. Displayed if enable bit is set * in the MDA control register. * > Graphics framebuffer. In native modes goes from A000:0000 to A000:FFFF - * and B800:0000 to B800:FFFF. In CGA-compatible + * and B800:0000 to B800:FFFF. In CGA-compatible * mode only the section at B800:0000 to B800:7FFF * is visible. Displayed if enable bit is set in the * CGA control register. - * + * * Two card-specific registers control text and graphics display: - * + * * 03B0: Control register. - * Bit 0: Map all graphics framebuffer into memory. + * Bit 0: Map all graphics framebuffer into memory. * Bit 2: Unknown. Set by GMC /M; cleared by mode set or GMC /T. * Bit 4: Set for CGA-compatible graphics, clear for native graphics. * Bit 5: Set for black on white, clear for white on black. @@ -88,55 +84,52 @@ static video_timings_t timing_genius = {VIDEO_ISA, 8, 16, 32, 8, 16, 32}; * Bit 4: Set to double character cell height (scanlines are doubled) * Bit 7: Unknown, seems to be set for all modes except 80x66 * - * Not having the card also means I don't have its font. According to the - * card brochure the font is an 8x12 bitmap in a 9x15 character cell. I - * therefore generated it by taking the MDA font, increasing graphics to + * Not having the card also means I don't have its font. According to the + * card brochure the font is an 8x12 bitmap in a 9x15 character cell. I + * therefore generated it by taking the MDA font, increasing graphics to * 16 pixels in height and reducing the height of characters so they fit * in an 8x12 cell if necessary. */ - +typedef struct genius_t { + mem_mapping_t mapping; -typedef struct genius_t -{ - mem_mapping_t mapping; + uint8_t mda_crtc[32]; /* The 'CRTC' as the host PC sees it */ + int mda_crtcreg; /* Current CRTC register */ + uint8_t cga_crtc[32]; /* The 'CRTC' as the host PC sees it */ + int cga_crtcreg; /* Current CRTC register */ + uint8_t genius_control; /* Native control register + * I think bit 0 enables the full + * framebuffer. + */ + uint8_t genius_charh; /* Native character height register: + * 00h => chars are 15 pixels high + * 81h => chars are 14 pixels high + * 83h => chars are 12 pixels high + * 90h => chars are 30 pixels high [15 x 2] + * 93h => chars are 24 pixels high [12 x 2] + */ + uint8_t genius_mode; /* Current mode (see list at top of file) */ + uint8_t cga_ctrl; /* Emulated CGA control register */ + uint8_t mda_ctrl; /* Emulated MDA control register */ + uint8_t cga_colour; /* Emulated CGA colour register (ignored) */ - uint8_t mda_crtc[32]; /* The 'CRTC' as the host PC sees it */ - int mda_crtcreg; /* Current CRTC register */ - uint8_t cga_crtc[32]; /* The 'CRTC' as the host PC sees it */ - int cga_crtcreg; /* Current CRTC register */ - uint8_t genius_control; /* Native control register - * I think bit 0 enables the full - * framebuffer. - */ - uint8_t genius_charh; /* Native character height register: - * 00h => chars are 15 pixels high - * 81h => chars are 14 pixels high - * 83h => chars are 12 pixels high - * 90h => chars are 30 pixels high [15 x 2] - * 93h => chars are 24 pixels high [12 x 2] - */ - uint8_t genius_mode; /* Current mode (see list at top of file) */ - uint8_t cga_ctrl; /* Emulated CGA control register */ - uint8_t mda_ctrl; /* Emulated MDA control register */ - uint8_t cga_colour; /* Emulated CGA colour register (ignored) */ + uint8_t mda_stat; /* MDA status (IN 0x3BA) */ + uint8_t cga_stat; /* CGA status (IN 0x3DA) */ - uint8_t mda_stat; /* MDA status (IN 0x3BA) */ - uint8_t cga_stat; /* CGA status (IN 0x3DA) */ + int font; /* Current font, 0 or 1 */ + int enabled; /* Display enabled, 0 or 1 */ + int detach; /* Detach cursor, 0 or 1 */ - int font; /* Current font, 0 or 1 */ - int enabled; /* Display enabled, 0 or 1 */ - int detach; /* Detach cursor, 0 or 1 */ + uint64_t dispontime, dispofftime; + pc_timer_t timer; - uint64_t dispontime, dispofftime; - pc_timer_t timer; - - int linepos, displine; - int vc; - int dispon, blink; - int vsynctime; + int linepos, displine; + int vc; + int dispon, blink; + int vsynctime; - uint8_t *vram; + uint8_t *vram; } genius_t; static uint8_t genius_pal[4]; @@ -144,275 +137,309 @@ static uint8_t genius_pal[4]; /* Mapping of attributes to colours, in MDA emulation mode */ static uint8_t mdaattr[256][2][2]; -void genius_recalctimings(genius_t *genius); -void genius_write(uint32_t addr, uint8_t val, void *p); -uint8_t genius_read(uint32_t addr, void *p); - +void genius_recalctimings(genius_t *genius); +void genius_write(uint32_t addr, uint8_t val, void *priv); +uint8_t genius_read(uint32_t addr, void *priv); void -genius_out(uint16_t addr, uint8_t val, void *p) +genius_out(uint16_t addr, uint8_t val, void *priv) { - genius_t *genius = (genius_t *)p; + genius_t *genius = (genius_t *) priv; switch (addr) { - case 0x3b0: /* Command / control register */ - genius->genius_control = val; - if (val & 1) - mem_mapping_set_addr(&genius->mapping, 0xa0000, 0x28000); - else - mem_mapping_set_addr(&genius->mapping, 0xb0000, 0x10000); - break; + case 0x3b0: /* Command / control register */ + genius->genius_control = val; + if (val & 1) + mem_mapping_set_addr(&genius->mapping, 0xa0000, 0x28000); + else + mem_mapping_set_addr(&genius->mapping, 0xb0000, 0x10000); + break; - case 0x3b1: - genius->genius_charh = val; - break; + case 0x3b1: + genius->genius_charh = val; + break; - /* Emulated CRTC, register select */ - case 0x3b2: case 0x3b4: case 0x3b6: - genius->mda_crtcreg = val & 31; - break; + /* Emulated CRTC, register select */ + case 0x3b2: + case 0x3b4: + case 0x3b6: + genius->mda_crtcreg = val & 31; + break; - /* Emulated CRTC, value */ - case 0x3b3: case 0x3b5: case 0x3b7: - genius->mda_crtc[genius->mda_crtcreg] = val; - genius_recalctimings(genius); - return; + /* Emulated CRTC, value */ + case 0x3b3: + case 0x3b5: + case 0x3b7: + genius->mda_crtc[genius->mda_crtcreg] = val; + genius_recalctimings(genius); + return; - /* Emulated MDA control register */ - case 0x3b8: - genius->mda_ctrl = val; - return; + /* Emulated MDA control register */ + case 0x3b8: + genius->mda_ctrl = val; + return; - /* Emulated CRTC, register select */ - case 0x3d0: case 0x3d2: case 0x3d4: case 0x3d6: - genius->cga_crtcreg = val & 31; - break; + /* Emulated CRTC, register select */ + case 0x3d0: + case 0x3d2: + case 0x3d4: + case 0x3d6: + genius->cga_crtcreg = val & 31; + break; - /* Emulated CRTC, value */ - case 0x3d1: case 0x3d3: case 0x3d5: case 0x3d7: - genius->cga_crtc[genius->cga_crtcreg] = val; - genius_recalctimings(genius); - return; + /* Emulated CRTC, value */ + case 0x3d1: + case 0x3d3: + case 0x3d5: + case 0x3d7: + genius->cga_crtc[genius->cga_crtcreg] = val; + genius_recalctimings(genius); + return; - /* Emulated CGA control register */ - case 0x3d8: - genius->cga_ctrl = val; - return; - /* Emulated CGA colour register */ - case 0x3d9: - genius->cga_colour = val; - return; + /* Emulated CGA control register */ + case 0x3d8: + genius->cga_ctrl = val; + return; + /* Emulated CGA colour register */ + case 0x3d9: + genius->cga_colour = val; + return; + + default: + break; } } - uint8_t -genius_in(uint16_t addr, void *p) +genius_in(uint16_t addr, void *priv) { - genius_t *genius = (genius_t *)p; - uint8_t ret = 0xff; + const genius_t *genius = (genius_t *) priv; + uint8_t ret = 0xff; switch (addr) { - case 0x3b0: case 0x3b2: case 0x3b4: case 0x3b6: - ret = genius->mda_crtcreg; - break; - case 0x3b1: case 0x3b3: case 0x3b5: case 0x3b7: - ret = genius->mda_crtc[genius->mda_crtcreg]; - break; - case 0x3b8: - ret = genius->mda_ctrl; - break; - case 0x3ba: - ret = genius->mda_stat; - break; - case 0x3d0: case 0x3d2: case 0x3d4: case 0x3d6: - ret = genius->cga_crtcreg; - break; - case 0x3d1: case 0x3d3: case 0x3d5: case 0x3d7: - ret = genius->cga_crtc[genius->cga_crtcreg]; - break; - case 0x3d8: - ret = genius->cga_ctrl; - break; - case 0x3d9: - ret = genius->cga_colour; - break; - case 0x3da: - ret = genius->cga_stat; - break; + case 0x3b0: + case 0x3b2: + case 0x3b4: + case 0x3b6: + ret = genius->mda_crtcreg; + break; + case 0x3b1: + case 0x3b3: + case 0x3b5: + case 0x3b7: + ret = genius->mda_crtc[genius->mda_crtcreg]; + break; + case 0x3b8: + ret = genius->mda_ctrl; + break; + case 0x3ba: + ret = genius->mda_stat; + break; + case 0x3d0: + case 0x3d2: + case 0x3d4: + case 0x3d6: + ret = genius->cga_crtcreg; + break; + case 0x3d1: + case 0x3d3: + case 0x3d5: + case 0x3d7: + ret = genius->cga_crtc[genius->cga_crtcreg]; + break; + case 0x3d8: + ret = genius->cga_ctrl; + break; + case 0x3d9: + ret = genius->cga_colour; + break; + case 0x3da: + ret = genius->cga_stat; + break; + + default: + break; } return ret; } - static void genius_waitstates(void) { - int ws_array[16] = {3, 4, 5, 6, 7, 8, 4, 5, 6, 7, 8, 4, 5, 6, 7, 8}; + 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]; cycles -= ws; } - void -genius_write(uint32_t addr, uint8_t val, void *p) +genius_write(uint32_t addr, uint8_t val, void *priv) { - genius_t *genius = (genius_t *)p; + genius_t *genius = (genius_t *) priv; genius_waitstates(); if (genius->genius_control & 1) { - if ((addr >= 0xa0000) && (addr < 0xb0000)) - addr = (addr - 0xa0000) & 0xffff; - else if ((addr >= 0xb0000) && (addr < 0xb8000)) - addr = ((addr - 0xb0000) & 0x7fff) + 0x10000; - else - addr = ((addr - 0xb8000) & 0xffff) + 0x18000; + if ((addr >= 0xa0000) && (addr < 0xb0000)) + addr = (addr - 0xa0000) & 0xffff; + else if ((addr >= 0xb0000) && (addr < 0xb8000)) + addr = ((addr - 0xb0000) & 0x7fff) + 0x10000; + else + addr = ((addr - 0xb8000) & 0xffff) + 0x18000; } else { - /* If hi-res memory is disabled, only visible in the B000 segment */ - if (addr >= 0xb8000) - addr = (addr & 0x3FFF) + 0x18000; - else - addr = (addr & 0x7FFF) + 0x10000; + /* If hi-res memory is disabled, only visible in the B000 segment */ + if (addr >= 0xb8000) + addr = (addr & 0x3FFF) + 0x18000; + else + addr = (addr & 0x7FFF) + 0x10000; } genius->vram[addr] = val; } - uint8_t -genius_read(uint32_t addr, void *p) +genius_read(uint32_t addr, void *priv) { - genius_t *genius = (genius_t *)p; - uint8_t ret; + const genius_t *genius = (genius_t *) priv; + uint8_t ret; + genius_waitstates(); if (genius->genius_control & 1) { - if ((addr >= 0xa0000) && (addr < 0xb0000)) - addr = (addr - 0xa0000) & 0xffff; - else if ((addr >= 0xb0000) && (addr < 0xb8000)) - addr = ((addr - 0xb0000) & 0x7fff) + 0x10000; - else - addr = ((addr - 0xb8000) & 0xffff) + 0x18000; + if ((addr >= 0xa0000) && (addr < 0xb0000)) + addr = (addr - 0xa0000) & 0xffff; + else if ((addr >= 0xb0000) && (addr < 0xb8000)) + addr = ((addr - 0xb0000) & 0x7fff) + 0x10000; + else + addr = ((addr - 0xb8000) & 0xffff) + 0x18000; } else { - /* If hi-res memory is disabled, only visible in the B000 segment */ - if (addr >= 0xb8000) - addr = (addr & 0x3FFF) + 0x18000; - else - addr = (addr & 0x7FFF) + 0x10000; + /* If hi-res memory is disabled, only visible in the B000 segment */ + if (addr >= 0xb8000) + addr = (addr & 0x3FFF) + 0x18000; + else + addr = (addr & 0x7FFF) + 0x10000; } ret = genius->vram[addr]; return ret; } - void genius_recalctimings(genius_t *genius) { double disptime; - double _dispontime, _dispofftime; + double _dispontime; + double _dispofftime; - disptime = 0x31; - _dispontime = 0x28; + disptime = 0x31; + _dispontime = 0x28; _dispofftime = disptime - _dispontime; - _dispontime *= MDACONST; + _dispontime *= MDACONST; _dispofftime *= MDACONST; - genius->dispontime = (uint64_t)(_dispontime); - genius->dispofftime = (uint64_t)(_dispofftime); + genius->dispontime = (uint64_t) (_dispontime); + genius->dispofftime = (uint64_t) (_dispofftime); } - static int genius_lines(genius_t *genius) { int ret = 350; switch (genius->genius_charh & 0x13) { - case 0x00: - ret = 990; /* 80x66 */ - break; - case 0x01: - ret = 980; /* 80x70 */ - break; - case 0x02: - ret = 988; /* Guess: 80x76 */ - break; - case 0x03: - ret = 984; /* 80x82 */ - break; - case 0x10: - ret = 375; /* Logic says 80x33 but it appears to be 80x25 */ - break; - case 0x11: - ret = 490; /* Guess: 80x35, fits the logic as well, half of 80x70 */ - break; - case 0x12: - ret = 494; /* Guess: 80x38 */ - break; - case 0x13: - ret = 492; /* 80x41 */ - break; + case 0x00: + ret = 990; /* 80x66 */ + break; + case 0x01: + ret = 980; /* 80x70 */ + break; + case 0x02: + ret = 988; /* Guess: 80x76 */ + break; + case 0x03: + ret = 984; /* 80x82 */ + break; + case 0x10: + ret = 375; /* Logic says 80x33 but it appears to be 80x25 */ + break; + case 0x11: + ret = 490; /* Guess: 80x35, fits the logic as well, half of 80x70 */ + break; + case 0x12: + ret = 494; /* Guess: 80x38 */ + break; + case 0x13: + ret = 492; /* 80x41 */ + break; + + default: + break; } return ret; } - /* Draw a single line of the screen in either text mode */ static void genius_textline(genius_t *genius, uint8_t background, int mda, int cols80) { - int w = 80; /* 80 characters across */ - int cw = 9; /* Each character is 9 pixels wide */ - uint8_t chr, attr, sc, ctrl; - uint8_t *crtc, bitmap[2]; - int x, blink, c, row, charh; - int drawcursor, cursorline; - uint16_t addr; - uint16_t ma = (genius->mda_crtc[13] | (genius->mda_crtc[12] << 8)) & 0x3fff; - uint16_t ca = (genius->mda_crtc[15] | (genius->mda_crtc[14] << 8)) & 0x3fff; - unsigned char *framebuf = genius->vram + 0x10000; - uint32_t col, dl = genius->displine; + int w = 80; /* 80 characters across */ + int cw = 9; /* Each character is 9 pixels wide */ + uint8_t chr; + uint8_t attr; + uint8_t sc; + uint8_t ctrl; + const uint8_t *crtc; + uint8_t bitmap[2]; + int blink; + int c; + int row; + int charh; + int drawcursor; + int cursorline; + uint16_t addr; + uint16_t ma = (genius->mda_crtc[13] | (genius->mda_crtc[12] << 8)) & 0x3fff; + uint16_t ca = (genius->mda_crtc[15] | (genius->mda_crtc[14] << 8)) & 0x3fff; + const uint8_t *framebuf = genius->vram + 0x10000; + uint32_t col; + uint32_t dl = genius->displine; /* Character height is 12-15 */ if (mda) { - if (genius->displine >= genius_lines(genius)) - return; + if (genius->displine >= genius_lines(genius)) + return; - crtc = genius->mda_crtc; - ctrl = genius->mda_ctrl; - charh = 15 - (genius->genius_charh & 3); + crtc = genius->mda_crtc; + ctrl = genius->mda_ctrl; + charh = 15 - (genius->genius_charh & 3); #if 0 - if (genius->genius_charh & 0x10) { - row = ((dl >> 1) / charh); - sc = ((dl >> 1) % charh); - } else { - row = (dl / charh); - sc = (dl % charh); - } + if (genius->genius_charh & 0x10) { + row = ((dl >> 1) / charh); + sc = ((dl >> 1) % charh); + } else { + row = (dl / charh); + sc = (dl % charh); + } #else - row = (dl / charh); - sc = (dl % charh); + row = (dl / charh); + sc = (dl % charh); #endif } else { - if ((genius->displine < 512) || (genius->displine >= 912)) - return; + if ((genius->displine < 512) || (genius->displine >= 912)) + return; - crtc = genius->cga_crtc; - ctrl = genius->cga_ctrl; - framebuf += 0x08000; + crtc = genius->cga_crtc; + ctrl = genius->cga_ctrl; + framebuf += 0x08000; - dl -= 512; - w = crtc[1]; - cw = 8; - charh = crtc[9] + 1; + dl -= 512; + w = crtc[1]; + cw = 8; + charh = crtc[9] + 1; - row = ((dl >> 1) / charh); - sc = ((dl >> 1) % charh); + row = ((dl >> 1) / charh); + sc = ((dl >> 1) % charh); } ma = (crtc[13] | (crtc[12] << 8)) & 0x3fff; @@ -421,291 +448,295 @@ genius_textline(genius_t *genius, uint8_t background, int mda, int cols80) addr = ((ma & ~1) + row * w) * 2; if (!mda) - dl += 512; + dl += 512; ma += (row * w); if ((crtc[10] & 0x60) == 0x20) - cursorline = 0; + cursorline = 0; else - cursorline = ((crtc[10] & 0x1F) <= sc) && ((crtc[11] & 0x1F) >= sc); + cursorline = ((crtc[10] & 0x1F) <= sc) && ((crtc[11] & 0x1F) >= sc); - for (x = 0; x < w; x++) { + for (int x = 0; x < w; x++) { #if 0 - if ((genius->genius_charh & 0x10) && ((addr + 2 * x) > 0x0FFF)) - chr = 0x00; - if ((genius->genius_charh & 0x10) && ((addr + 2 * x + 1) > 0x0FFF)) - attr = 0x00; + if ((genius->genius_charh & 0x10) && ((addr + 2 * x) > 0x0FFF)) + chr = 0x00; + if ((genius->genius_charh & 0x10) && ((addr + 2 * x + 1) > 0x0FFF)) + attr = 0x00; #endif - chr = framebuf[(addr + 2 * x) & 0x3FFF]; - attr = framebuf[(addr + 2 * x + 1) & 0x3FFF]; + chr = framebuf[(addr + 2 * x) & 0x3FFF]; + attr = framebuf[(addr + 2 * x + 1) & 0x3FFF]; - drawcursor = ((ma == ca) && cursorline && genius->enabled && (ctrl & 8)); + drawcursor = ((ma == ca) && cursorline && genius->enabled && (ctrl & 8)); - switch (crtc[10] & 0x60) { - case 0x00: drawcursor = drawcursor && (genius->blink & 16); break; - case 0x60: drawcursor = drawcursor && (genius->blink & 32); break; - } + switch (crtc[10] & 0x60) { + case 0x00: + drawcursor = drawcursor && (genius->blink & 16); + break; + case 0x60: + drawcursor = drawcursor && (genius->blink & 32); + break; - blink = ((genius->blink & 16) && (ctrl & 0x20) && (attr & 0x80) && !drawcursor); + default: + break; + } - if (ctrl & 0x20) attr &= 0x7F; + blink = ((genius->blink & 16) && (ctrl & 0x20) && (attr & 0x80) && !drawcursor); - /* MDA underline */ - if (mda && (sc == charh) && ((attr & 7) == 1)) { - col = mdaattr[attr][blink][1]; + if (ctrl & 0x20) + attr &= 0x7F; - if (genius->genius_control & 0x20) - col ^= 15; + /* MDA underline */ + if (mda && (sc == charh) && ((attr & 7) == 1)) { + col = mdaattr[attr][blink][1]; - for (c = 0; c < cw; c++) { - if (col != background) { - if (cols80) - buffer32->line[dl][(x * cw) + c] = col; - else { - buffer32->line[dl][((x * cw) << 1) + (c << 1)] = - buffer32->line[dl][((x * cw) << 1) + (c << 1) + 1] = col; - } - } - } - } else { /* Draw 8 pixels of character */ - if (mda) - bitmap[0] = fontdat8x12[chr][sc]; - else - bitmap[0] = fontdat[chr][sc]; + if (genius->genius_control & 0x20) + col ^= 15; - for (c = 0; c < 8; c++) { - col = mdaattr[attr][blink][(bitmap[0] & (1 << (c ^ 7))) ? 1 : 0]; - if (!(genius->enabled) || !(ctrl & 8)) - col = mdaattr[0][0][0]; + for (c = 0; c < cw; c++) { + if (col != background) { + if (cols80) + buffer32->line[dl][(x * cw) + c] = col; + else { + buffer32->line[dl][((x * cw) << 1) + (c << 1)] = buffer32->line[dl][((x * cw) << 1) + (c << 1) + 1] = col; + } + } + } + } else { /* Draw 8 pixels of character */ + if (mda) + bitmap[0] = fontdat8x12[chr][sc]; + else + bitmap[0] = fontdat[chr][sc]; - if (genius->genius_control & 0x20) - col ^= 15; + for (c = 0; c < 8; c++) { + col = mdaattr[attr][blink][(bitmap[0] & (1 << (c ^ 7))) ? 1 : 0]; + if (!(genius->enabled) || !(ctrl & 8)) + col = mdaattr[0][0][0]; - if (col != background) { - if (cols80) - buffer32->line[dl][(x * cw) + c] = col; - else { - buffer32->line[dl][((x * cw) << 1) + (c << 1)] = - buffer32->line[dl][((x * cw) << 1) + (c << 1) + 1] = col; - } - } - } + if (genius->genius_control & 0x20) + col ^= 15; - if (cw == 9) { - /* The ninth pixel column... */ - if ((chr & ~0x1f) == 0xc0) { - /* Echo column 8 for the graphics chars */ - if (cols80) { - col = buffer32->line[dl][(x * cw) + 7]; - if (col != background) - buffer32->line[dl][(x * cw) + 8] = col; - } else { - col = buffer32->line[dl][((x * cw) << 1) + 14]; - if (col != background) { - buffer32->line[dl][((x * cw) << 1) + 16] = - buffer32->line[dl][((x * cw) << 1) + 17] = col; - } - } - } else { /* Otherwise fill with background */ - col = mdaattr[attr][blink][0]; - if (genius->genius_control & 0x20) - col ^= 15; - if (col != background) { - if (cols80) - buffer32->line[dl][(x * cw) + 8] = col; - else { - buffer32->line[dl][((x * cw) << 1) + 16] = - buffer32->line[dl][((x * cw) << 1) + 17] = col; - } - } - } - } + if (col != background) { + if (cols80) + buffer32->line[dl][(x * cw) + c] = col; + else { + buffer32->line[dl][((x * cw) << 1) + (c << 1)] = buffer32->line[dl][((x * cw) << 1) + (c << 1) + 1] = col; + } + } + } - if (drawcursor) { - for (c = 0; c < cw; c++) { - if (cols80) - buffer32->line[dl][(x * cw) + c] ^= mdaattr[attr][0][1]; - else { - buffer32->line[dl][((x * cw) << 1) + (c << 1)] ^= mdaattr[attr][0][1]; - buffer32->line[dl][((x * cw) << 1) + (c << 1) + 1] ^= mdaattr[attr][0][1]; - } - } - } - ++ma; - } + if (cw == 9) { + /* The ninth pixel column... */ + if ((chr & ~0x1f) == 0xc0) { + /* Echo column 8 for the graphics chars */ + if (cols80) { + col = buffer32->line[dl][(x * cw) + 7]; + if (col != background) + buffer32->line[dl][(x * cw) + 8] = col; + } else { + col = buffer32->line[dl][((x * cw) << 1) + 14]; + if (col != background) { + buffer32->line[dl][((x * cw) << 1) + 16] = buffer32->line[dl][((x * cw) << 1) + 17] = col; + } + } + } else { /* Otherwise fill with background */ + col = mdaattr[attr][blink][0]; + if (genius->genius_control & 0x20) + col ^= 15; + if (col != background) { + if (cols80) + buffer32->line[dl][(x * cw) + 8] = col; + else { + buffer32->line[dl][((x * cw) << 1) + 16] = buffer32->line[dl][((x * cw) << 1) + 17] = col; + } + } + } + } + + if (drawcursor) { + for (c = 0; c < cw; c++) { + if (cols80) + buffer32->line[dl][(x * cw) + c] ^= mdaattr[attr][0][1]; + else { + buffer32->line[dl][((x * cw) << 1) + (c << 1)] ^= mdaattr[attr][0][1]; + buffer32->line[dl][((x * cw) << 1) + (c << 1) + 1] ^= mdaattr[attr][0][1]; + } + } + } + ++ma; + } } } - /* Draw a line in the CGA 640x200 mode */ void genius_cgaline(genius_t *genius) { - int x, c; - uint32_t dat, addr; - uint8_t ink_f, ink_b; + uint32_t dat; + uint32_t addr; + uint8_t ink_f; + uint8_t ink_b; ink_f = (genius->genius_control & 0x20) ? genius_pal[0] : genius_pal[3]; ink_b = (genius->genius_control & 0x20) ? genius_pal[3] : genius_pal[0]; /* We draw the CGA at row 512 */ if ((genius->displine < 512) || (genius->displine >= 912)) - return; + return; addr = 0x18000 + 80 * ((genius->displine - 512) >> 2); if ((genius->displine - 512) & 2) - addr += 0x2000; + addr += 0x2000; - for (x = 0; x < 80; x++) { - dat = genius->vram[addr]; - addr++; + for (uint8_t x = 0; x < 80; x++) { + dat = genius->vram[addr]; + addr++; - for (c = 0; c < 8; c++) { - if (dat & 0x80) - buffer32->line[genius->displine][(x << 3) + c] = ink_f; - else - buffer32->line[genius->displine][(x << 3) + c] = ink_b; + for (uint8_t c = 0; c < 8; c++) { + if (dat & 0x80) + buffer32->line[genius->displine][(x << 3) + c] = ink_f; + else + buffer32->line[genius->displine][(x << 3) + c] = ink_b; - dat = dat << 1; - } + dat = dat << 1; + } } } - /* Draw a line in the native high-resolution mode */ void genius_hiresline(genius_t *genius) { - int x, c; - uint32_t dat, addr; - uint8_t ink_f, ink_b; + uint32_t dat; + uint32_t addr; + uint8_t ink_f; + uint8_t ink_b; ink_f = (genius->genius_control & 0x20) ? genius_pal[0] : genius_pal[3]; ink_b = (genius->genius_control & 0x20) ? genius_pal[3] : genius_pal[0]; /* The first 512 lines live at A0000 */ if (genius->displine < 512) - addr = 128 * genius->displine; - else /* The second 496 live at B8000 */ - addr = 0x18000 + (128 * (genius->displine - 512)); + addr = 128 * genius->displine; + else /* The second 496 live at B8000 */ + addr = 0x18000 + (128 * (genius->displine - 512)); - for (x = 0; x < 91; x++) { - dat = genius->vram[addr + x]; + for (uint8_t x = 0; x < 91; x++) { + dat = genius->vram[addr + x]; - for (c = 0; c < 8; c++) { - if (dat & 0x80) - buffer32->line[genius->displine][(x << 3) + c] = ink_f; - else - buffer32->line[genius->displine][(x << 3) + c] = ink_b; + for (uint8_t c = 0; c < 8; c++) { + if (dat & 0x80) + buffer32->line[genius->displine][(x << 3) + c] = ink_f; + else + buffer32->line[genius->displine][(x << 3) + c] = ink_b; - dat = dat << 1; - } + dat = dat << 1; + } } } - void -genius_poll(void *p) +genius_poll(void *priv) { - genius_t *genius = (genius_t *)p; - int x; - uint8_t background; + genius_t *genius = (genius_t *) priv; + uint8_t background; if (!genius->linepos) { - timer_advance_u64(&genius->timer, genius->dispofftime); - genius->cga_stat |= 1; - genius->mda_stat |= 1; - genius->linepos = 1; + timer_advance_u64(&genius->timer, genius->dispofftime); + genius->cga_stat |= 1; + genius->mda_stat |= 1; + genius->linepos = 1; - if (genius->dispon) { - if (genius->genius_control & 0x20) - background = genius_pal[3]; - else - background = genius_pal[0]; + if (genius->dispon) { + if (genius->genius_control & 0x20) + background = genius_pal[3]; + else + background = genius_pal[0]; - if (genius->displine == 0) - video_wait_for_buffer(); + if (genius->displine == 0) + video_wait_for_buffer(); - /* Start off with a blank line */ - for (x = 0; x < GENIUS_XSIZE; x++) - buffer32->line[genius->displine][x] = background; + /* Start off with a blank line */ + for (uint16_t x = 0; x < GENIUS_XSIZE; x++) + buffer32->line[genius->displine][x] = background; - /* If graphics display enabled, draw graphics on top - * of the blanked line */ - if (genius->cga_ctrl & 8) { - if (((genius->genius_control & 0x11) == 0x00) || (genius->genius_control & 0x08)) - genius_cgaline(genius); - else if ((genius->genius_control & 0x11) == 0x01) - genius_hiresline(genius); - else { - if (genius->cga_ctrl & 2) - genius_cgaline(genius); - else { - if (genius->cga_ctrl & 1) - genius_textline(genius, background, 0, 1); - else - genius_textline(genius, background, 0, 0); - } - } - } + /* If graphics display enabled, draw graphics on top + * of the blanked line */ + if (genius->cga_ctrl & 8) { + if (((genius->genius_control & 0x11) == 0x00) || (genius->genius_control & 0x08)) + genius_cgaline(genius); + else if ((genius->genius_control & 0x11) == 0x01) + genius_hiresline(genius); + else { + if (genius->cga_ctrl & 2) + genius_cgaline(genius); + else { + if (genius->cga_ctrl & 1) + genius_textline(genius, background, 0, 1); + else + genius_textline(genius, background, 0, 0); + } + } + } - /* If MDA display is enabled, draw MDA text on top - * of the lot */ - if (genius->mda_ctrl & 8) - genius_textline(genius, background, 1, 1); - } - genius->displine++; - /* Hardcode a fixed refresh rate and VSYNC timing */ - if (genius->displine == 1008) { /* Start of VSYNC */ - genius->cga_stat |= 8; - genius->mda_stat |= 8; - genius->dispon = 0; - } - if (genius->displine == 1040) { /* End of VSYNC */ - genius->displine = 0; - genius->cga_stat &= ~8; - genius->mda_stat &= ~8; - genius->dispon = 1; - } + /* If MDA display is enabled, draw MDA text on top + * of the lot */ + if (genius->mda_ctrl & 8) + genius_textline(genius, background, 1, 1); + + video_process_8(GENIUS_XSIZE, genius->displine); + } + genius->displine++; + /* Hardcode a fixed refresh rate and VSYNC timing */ + if (genius->displine == 1008) { /* Start of VSYNC */ + genius->cga_stat |= 8; + genius->mda_stat |= 8; + genius->dispon = 0; + } + if (genius->displine == 1040) { /* End of VSYNC */ + genius->displine = 0; + genius->cga_stat &= ~8; + genius->mda_stat &= ~8; + genius->dispon = 1; + } } else { - if (genius->dispon) { - genius->cga_stat &= ~1; - genius->mda_stat &= ~1; - } - timer_advance_u64(&genius->timer, genius->dispontime); - genius->linepos = 0; + if (genius->dispon) { + genius->cga_stat &= ~1; + genius->mda_stat &= ~1; + } + timer_advance_u64(&genius->timer, genius->dispontime); + genius->linepos = 0; - if (genius->displine == 1008) { -/* Hardcode GENIUS_XSIZE * GENIUS_YSIZE window size */ - if (GENIUS_XSIZE != xsize || GENIUS_YSIZE != ysize) { - xsize = GENIUS_XSIZE; - ysize = GENIUS_YSIZE; - if (xsize < 64) xsize = 656; - if (ysize < 32) ysize = 200; - set_screen_size(xsize, ysize); + if (genius->displine == 1008) { + /* Hardcode GENIUS_XSIZE * GENIUS_YSIZE window size */ + if (GENIUS_XSIZE != xsize || GENIUS_YSIZE != ysize) { + xsize = GENIUS_XSIZE; + ysize = GENIUS_YSIZE; + if (xsize < 64) + xsize = 656; + if (ysize < 32) + ysize = 200; + set_screen_size(xsize, ysize); - if (video_force_resize_get()) - video_force_resize_set(0); - } + if (video_force_resize_get()) + video_force_resize_set(0); + } - video_blit_memtoscreen_8(0, 0, xsize, ysize); + video_blit_memtoscreen(0, 0, xsize, ysize); - frames++; - /* Fixed 728x1008 resolution */ - video_res_x = GENIUS_XSIZE; - video_res_y = GENIUS_YSIZE; - video_bpp = 1; - genius->blink++; - } + frames++; + /* Fixed 728x1008 resolution */ + video_res_x = GENIUS_XSIZE; + video_res_y = GENIUS_YSIZE; + video_bpp = 1; + genius->blink++; + } } } - -void -*genius_init(const device_t *info) +void * +genius_init(UNUSED(const device_t *info)) { - int c; genius_t *genius = malloc(sizeof(genius_t)); memset(genius, 0, sizeof(genius_t)); @@ -721,82 +752,82 @@ void /* Occupy memory between 0xB0000 and 0xBFFFF (moves to 0xA0000 in * high-resolution modes) */ - mem_mapping_add(&genius->mapping, 0xb0000, 0x10000, genius_read, NULL, NULL, genius_write, NULL, NULL, NULL, MEM_MAPPING_EXTERNAL, genius); + mem_mapping_add(&genius->mapping, 0xb0000, 0x10000, genius_read, NULL, NULL, genius_write, NULL, NULL, NULL, MEM_MAPPING_EXTERNAL, genius); /* Respond to both MDA and CGA I/O ports */ io_sethandler(0x03b0, 0x000C, genius_in, NULL, NULL, genius_out, NULL, NULL, genius); io_sethandler(0x03d0, 0x0010, genius_in, NULL, NULL, genius_out, NULL, NULL, genius); - genius_pal[0] = 0 + 16; /* 0 */ - genius_pal[1] = 8 + 16; /* 8 */ - genius_pal[2] = 7 + 16; /* 7 */ - genius_pal[3] = 15 + 16; /* F */ + genius_pal[0] = 0 + 16; /* 0 */ + genius_pal[1] = 8 + 16; /* 8 */ + genius_pal[2] = 7 + 16; /* 7 */ + genius_pal[3] = 15 + 16; /* F */ /* MDA attributes */ - /* I don't know if the Genius's MDA emulation actually does + /* I don't know if the Genius's MDA emulation actually does * emulate bright / non-bright. For the time being pretend it does. */ - for (c = 0; c < 256; c++) { - mdaattr[c][0][0] = mdaattr[c][1][0] = mdaattr[c][1][1] = genius_pal[0]; - if (c & 8) mdaattr[c][0][1] = genius_pal[3]; - else mdaattr[c][0][1] = genius_pal[2]; + for (uint16_t c = 0; c < 256; c++) { + mdaattr[c][0][0] = mdaattr[c][1][0] = mdaattr[c][1][1] = genius_pal[0]; + if (c & 8) + mdaattr[c][0][1] = genius_pal[3]; + else + mdaattr[c][0][1] = genius_pal[2]; } mdaattr[0x70][0][1] = genius_pal[0]; mdaattr[0x70][0][0] = mdaattr[0x70][1][0] = mdaattr[0x70][1][1] = genius_pal[3]; - mdaattr[0xF0][0][1] = genius_pal[0]; + mdaattr[0xF0][0][1] = genius_pal[0]; mdaattr[0xF0][0][0] = mdaattr[0xF0][1][0] = mdaattr[0xF0][1][1] = genius_pal[3]; - mdaattr[0x78][0][1] = genius_pal[2]; + mdaattr[0x78][0][1] = genius_pal[2]; mdaattr[0x78][0][0] = mdaattr[0x78][1][0] = mdaattr[0x78][1][1] = genius_pal[3]; - mdaattr[0xF8][0][1] = genius_pal[2]; + mdaattr[0xF8][0][1] = genius_pal[2]; mdaattr[0xF8][0][0] = mdaattr[0xF8][1][0] = mdaattr[0xF8][1][1] = genius_pal[3]; mdaattr[0x00][0][1] = mdaattr[0x00][1][1] = genius_pal[0]; mdaattr[0x08][0][1] = mdaattr[0x08][1][1] = genius_pal[0]; mdaattr[0x80][0][1] = mdaattr[0x80][1][1] = genius_pal[0]; mdaattr[0x88][0][1] = mdaattr[0x88][1][1] = genius_pal[0]; -/* Start off in 80x25 text mode */ - genius->cga_stat = 0xF4; - genius->genius_mode = 2; - genius->enabled = 1; + /* Start off in 80x25 text mode */ + genius->cga_stat = 0xF4; + genius->genius_mode = 2; + genius->enabled = 1; genius->genius_charh = 0x90; /* Native character height register */ genius->genius_control |= 0x10; return genius; } - void -genius_close(void *p) +genius_close(void *priv) { - genius_t *genius = (genius_t *)p; + genius_t *genius = (genius_t *) priv; free(genius->vram); free(genius); } - static int -genius_available() +genius_available(void) { return rom_present(BIOS_ROM_PATH); } - void -genius_speed_changed(void *p) +genius_speed_changed(void *priv) { - genius_t *genius = (genius_t *)p; + genius_t *genius = (genius_t *) priv; genius_recalctimings(genius); } - -const device_t genius_device = -{ - "Genius VHR", - "genius", - DEVICE_ISA, 0, - genius_init, genius_close, NULL, - { genius_available }, - genius_speed_changed, - NULL, - NULL +const device_t genius_device = { + .name = "Genius VHR", + .internal_name = "genius", + .flags = DEVICE_ISA, + .local = 0, + .init = genius_init, + .close = genius_close, + .reset = NULL, + { .available = genius_available }, + .speed_changed = genius_speed_changed, + .force_redraw = NULL, + .config = NULL }; diff --git a/src/video/vid_hercules.c b/src/video/vid_hercules.c index 293732908..2a725488d 100644 --- a/src/video/vid_hercules.c +++ b/src/video/vid_hercules.c @@ -1,20 +1,20 @@ /* - * 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. + * 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. + * This file is part of the 86Box distribution. * - * Hercules emulation. + * Hercules emulation. * * * - * Authors: Sarah Walker, - * Miran Grca, + * Authors: Sarah Walker, + * Miran Grca, * - * Copyright 2008-2019 Sarah Walker. - * Copyright 2016-2019 Miran Grca. + * Copyright 2008-2019 Sarah Walker. + * Copyright 2016-2019 Miran Grca. */ #include #include @@ -32,204 +32,201 @@ #include <86box/device.h> #include <86box/video.h> #include <86box/vid_hercules.h> +#include <86box/plat_unused.h> - -static video_timings_t timing_hercules = {VIDEO_ISA, 8, 16, 32, 8, 16, 32}; - +static video_timings_t timing_hercules = { .type = VIDEO_ISA, .write_b = 8, .write_w = 16, .write_l = 32, .read_b = 8, .read_w = 16, .read_l = 32 }; static void recalc_timings(hercules_t *dev) { double disptime; - double _dispontime, _dispofftime; + double _dispontime; + double _dispofftime; - disptime = dev->crtc[0] + 1; + disptime = dev->crtc[0] + 1; _dispontime = dev->crtc[1]; _dispofftime = disptime - _dispontime; - _dispontime *= HERCCONST; + _dispontime *= HERCCONST; _dispofftime *= HERCCONST; - dev->dispontime = (uint64_t)(_dispontime); - dev->dispofftime = (uint64_t)(_dispofftime); + dev->dispontime = (uint64_t) (_dispontime); + dev->dispofftime = (uint64_t) (_dispofftime); } - -static uint8_t 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 uint8_t 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 void hercules_out(uint16_t addr, uint8_t val, void *priv) { - hercules_t *dev = (hercules_t *)priv; - uint8_t old; + hercules_t *dev = (hercules_t *) priv; + uint8_t old; + VIDEO_MONITOR_PROLOGUE() switch (addr) { - case 0x03b0: - case 0x03b2: - case 0x03b4: - case 0x03b6: - dev->crtcreg = val & 31; - break; + case 0x03b0: + case 0x03b2: + case 0x03b4: + case 0x03b6: + dev->crtcreg = val & 31; + break; - case 0x03b1: - case 0x03b3: - case 0x03b5: - case 0x03b7: - old = dev->crtc[dev->crtcreg]; - dev->crtc[dev->crtcreg] = val & crtcmask[dev->crtcreg]; + case 0x03b1: + case 0x03b3: + case 0x03b5: + case 0x03b7: + old = dev->crtc[dev->crtcreg]; + dev->crtc[dev->crtcreg] = val & crtcmask[dev->crtcreg]; - /* - * Fix for Generic Turbo XT BIOS, which - * sets up cursor registers wrong. - */ - if (dev->crtc[10] == 6 && dev->crtc[11] == 7) { - dev->crtc[10] = 0xb; - dev->crtc[11] = 0xc; - } + /* + * Fix for Generic Turbo XT BIOS, which + * sets up cursor registers wrong. + */ + if (dev->crtc[10] == 6 && dev->crtc[11] == 7) { + dev->crtc[10] = 0xb; + dev->crtc[11] = 0xc; + } - if (old != val) { - if ((dev->crtcreg < 0xe) || (dev->crtcreg > 0x10)) { - fullchange = changeframecount; - recalc_timings(dev); - } - } - break; + if (old != val) { + if ((dev->crtcreg < 0xe) || (dev->crtcreg > 0x10)) { + dev->fullchange = changeframecount; + recalc_timings(dev); + } + } + break; - case 0x03b8: - old = dev->ctrl; + case 0x03b8: + old = dev->ctrl; - /* Prevent setting of bits if they are disabled in CTRL2. */ - if ((old & 0x02) && !(val & 0x02)) - dev->ctrl &= 0xfd; - else if ((val & 0x02) && (dev->ctrl2 & 0x01)) - dev->ctrl |= 0x02; + /* Prevent setting of bits if they are disabled in CTRL2. */ + if ((old & 0x02) && !(val & 0x02)) + dev->ctrl &= 0xfd; + else if ((val & 0x02) && (dev->ctrl2 & 0x01)) + dev->ctrl |= 0x02; - if ((old & 0x80) && !(val & 0x80)) - dev->ctrl &= 0x7f; - else if ((val & 0x80) && (dev->ctrl2 & 0x02)) - dev->ctrl |= 0x80; + if ((old & 0x80) && !(val & 0x80)) + dev->ctrl &= 0x7f; + else if ((val & 0x80) && (dev->ctrl2 & 0x02)) + dev->ctrl |= 0x80; - dev->ctrl = (dev->ctrl & 0x82) | (val & 0x7d); + dev->ctrl = (dev->ctrl & 0x82) | (val & 0x7d); - if (old ^ val) - recalc_timings(dev); - break; + if (old ^ val) + recalc_timings(dev); + break; - case 0x03b9: - case 0x03bb: - dev->lp_ff = !(addr & 0x0002); - break; + case 0x03b9: + case 0x03bb: + dev->lp_ff = !(addr & 0x0002); + break; - case 0x03bf: - old = dev->ctrl2; - dev->ctrl2 = val; - /* According to the Programmer's guide to the Hercules graphics cars - by David B. Doty from 1988, the CTRL2 modes (bits 1,0) are as follow: - - 00: DIAG: Text mode only, only page 0 accessible; - - 01: HALF: Graphics mode allowed, only page 0 accessible; - - 11: FULL: Graphics mode allowed, both pages accessible. */ - if (val & 0x01) - mem_mapping_set_exec(&dev->mapping, dev->vram); - else - mem_mapping_set_exec(&dev->mapping, NULL); - if (val & 0x02) - mem_mapping_set_addr(&dev->mapping, 0xb0000, 0x10000); - else - mem_mapping_set_addr(&dev->mapping, 0xb0000, 0x08000); - if (old ^ val) - recalc_timings(dev); - break; + case 0x03bf: + old = dev->ctrl2; + dev->ctrl2 = val; + /* According to the Programmer's guide to the Hercules graphics cars + by David B. Doty from 1988, the CTRL2 modes (bits 1,0) are as follow: + - 00: DIAG: Text mode only, only page 0 accessible; + - 01: HALF: Graphics mode allowed, only page 0 accessible; + - 11: FULL: Graphics mode allowed, both pages accessible. */ + if (val & 0x01) + mem_mapping_set_exec(&dev->mapping, dev->vram); + else + mem_mapping_set_exec(&dev->mapping, NULL); + if (val & 0x02) + mem_mapping_set_addr(&dev->mapping, 0xb0000, 0x10000); + else + mem_mapping_set_addr(&dev->mapping, 0xb0000, 0x08000); + if (old ^ val) + recalc_timings(dev); + break; - default: - break; + default: + break; } -} + VIDEO_MONITOR_EPILOGUE() +} static uint8_t hercules_in(uint16_t addr, void *priv) { - hercules_t *dev = (hercules_t *)priv; - uint8_t ret = 0xff; + const hercules_t *dev = (hercules_t *) priv; + uint8_t ret = 0xff; switch (addr) { - case 0x03b0: - case 0x03b2: - case 0x03b4: - case 0x03b6: - ret = dev->crtcreg; - break; + case 0x03b0: + case 0x03b2: + case 0x03b4: + case 0x03b6: + ret = dev->crtcreg; + break; - case 0x03b1: - case 0x03b3: - case 0x03b5: - case 0x03b7: - if (dev->crtcreg == 0x0c) - ret = (dev->ma >> 8) & 0x3f; - else if (dev->crtcreg == 0x0d) - ret = dev->ma & 0xff; - else - ret = dev->crtc[dev->crtcreg]; - break; + case 0x03b1: + case 0x03b3: + case 0x03b5: + case 0x03b7: + if (dev->crtcreg == 0x0c) + ret = (dev->ma >> 8) & 0x3f; + else if (dev->crtcreg == 0x0d) + ret = dev->ma & 0xff; + else + ret = dev->crtc[dev->crtcreg]; + break; - case 0x03ba: - ret = 0x70; /* Hercules ident */ - ret |= (dev->lp_ff ? 2 : 0); - ret |= (dev->stat & 0x01); - if (dev->stat & 0x08) - ret |= 0x80; - if ((ret & 0x81) == 0x80) - ret |= 0x08; - break; + case 0x03ba: + ret = 0x70; /* Hercules ident */ + ret |= (dev->lp_ff ? 2 : 0); + ret |= (dev->stat & 0x01); + if (dev->stat & 0x08) + ret |= 0x80; + if ((ret & 0x81) == 0x80) + ret |= 0x08; + break; - default: - break; + default: + break; } - return(ret); + return ret; } - static void -hercules_waitstates(void *p) +hercules_waitstates(UNUSED(void *priv)) { - int ws_array[16] = {3, 4, 5, 6, 7, 8, 4, 5, 6, 7, 8, 4, 5, 6, 7, 8}; + 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]; cycles -= ws; } - static void hercules_write(uint32_t addr, uint8_t val, void *priv) { - hercules_t *dev = (hercules_t *)priv; + hercules_t *dev = (hercules_t *) priv; if (dev->ctrl2 & 0x01) - addr &= 0xffff; + addr &= 0xffff; else - addr &= 0x0fff; + addr &= 0x0fff; dev->vram[addr] = val; hercules_waitstates(dev); } - static uint8_t hercules_read(uint32_t addr, void *priv) { - hercules_t *dev = (hercules_t *)priv; - uint8_t ret = 0xff; + hercules_t *dev = (hercules_t *) priv; + uint8_t ret = 0xff; if (dev->ctrl2 & 0x01) - addr &= 0xffff; + addr &= 0xffff; else - addr &= 0x0fff; + addr &= 0x0fff; hercules_waitstates(dev); @@ -238,330 +235,339 @@ hercules_read(uint32_t addr, void *priv) return ret; } - static void hercules_render_overscan_left(hercules_t *dev) { - int i; uint32_t width; if (dev->ctrl & 0x02) - width = (((uint32_t) dev->crtc[1]) << 4); + width = (((uint32_t) dev->crtc[1]) << 4); else - width = (((uint32_t) dev->crtc[1]) * 9); + width = (((uint32_t) dev->crtc[1]) * 9); if ((dev->displine + 14) < 0) - return; + return; if (width == 0) - return; + return; - for (i = 0; i < 8; i++) - buffer32->line[dev->displine + 14][i] = 0x00000000; + for (uint8_t i = 0; i < 8; i++) + buffer32->line[dev->displine + 14][i] = 0x00000000; } - static void hercules_render_overscan_right(hercules_t *dev) { - int i; uint32_t width; if (dev->ctrl & 0x02) - width = (((uint32_t) dev->crtc[1]) << 4); + width = (((uint32_t) dev->crtc[1]) << 4); else - width = (((uint32_t) dev->crtc[1]) * 9); + width = (((uint32_t) dev->crtc[1]) * 9); if ((dev->displine + 14) < 0) - return; + return; if (width == 0) - return; + return; - for (i = 0; i < 8; i++) - buffer32->line[dev->displine + 14][8 + width + i] = 0x00000000; + for (uint8_t i = 0; i < 8; i++) + buffer32->line[dev->displine + 14][8 + width + i] = 0x00000000; } - static void hercules_poll(void *priv) { - hercules_t *dev = (hercules_t *)priv; - uint8_t chr, attr; - uint16_t ca, dat; - uint16_t pa; - int oldsc, blink; - int x, xx, y, yy, c, oldvc; - int drawcursor; - uint32_t *p; + hercules_t *dev = (hercules_t *) priv; + uint8_t chr; + uint8_t attr; + uint16_t ca; + uint16_t dat; + uint16_t pa; + int oldsc; + int blink; + int x; + int xx; + int y; + int yy; + int c; + int oldvc; + int drawcursor; + uint32_t *p; + VIDEO_MONITOR_PROLOGUE() ca = (dev->crtc[15] | (dev->crtc[14] << 8)) & 0x3fff; - if (! dev->linepos) { - timer_advance_u64(&dev->timer, dev->dispofftime); - dev->stat |= 1; - dev->linepos = 1; - oldsc = dev->sc; + if (!dev->linepos) { + timer_advance_u64(&dev->timer, dev->dispofftime); + dev->stat |= 1; + dev->linepos = 1; + oldsc = dev->sc; - if ((dev->crtc[8] & 3) == 3) - dev->sc = (dev->sc << 1) & 7; + if ((dev->crtc[8] & 3) == 3) + dev->sc = (dev->sc << 1) & 7; - if (dev->dispon) { - if (dev->displine < dev->firstline) { - dev->firstline = dev->displine; - video_wait_for_buffer(); - } - dev->lastline = dev->displine; + if (dev->dispon) { + if (dev->displine < dev->firstline) { + dev->firstline = dev->displine; + video_wait_for_buffer(); + } + dev->lastline = dev->displine; - hercules_render_overscan_left(dev); + hercules_render_overscan_left(dev); - if (dev->ctrl & 0x02) { - ca = (dev->sc & 3) * 0x2000; - if (dev->ctrl & 0x80) - ca += 0x8000; + if (dev->ctrl & 0x02) { + ca = (dev->sc & 3) * 0x2000; + if (dev->ctrl & 0x80) + ca += 0x8000; - for (x = 0; x < dev->crtc[1]; x++) { - if (dev->ctrl & 8) - dat = (dev->vram[((dev->ma << 1) & 0x1fff) + ca] << 8) | dev->vram[((dev->ma << 1) & 0x1fff) + ca + 1]; - else - dat = 0; - dev->ma++; - for (c = 0; c < 16; c++) - buffer32->line[dev->displine + 14][(x << 4) + c + 8] = (dat & (32768 >> c)) ? 7 : 0; - for (c = 0; c < 16; c += 8) - video_blend((x << 4) + c + 8, dev->displine + 14); - } - } else { - for (x = 0; x < dev->crtc[1]; x++) { - if (dev->ctrl & 8) { - /* Undocumented behavior: page 1 in text mode means characters are read - from page 1 and attributes from page 0. */ - chr = dev->charbuffer[x << 1]; - attr = dev->charbuffer[(x << 1) + 1]; - } else - chr = attr = 0; - drawcursor = ((dev->ma == ca) && dev->con && dev->cursoron); - blink = ((dev->blink & 16) && (dev->ctrl & 0x20) && (attr & 0x80) && !drawcursor); + for (x = 0; x < dev->crtc[1]; x++) { + if (dev->ctrl & 8) + dat = (dev->vram[((dev->ma << 1) & 0x1fff) + ca] << 8) | dev->vram[((dev->ma << 1) & 0x1fff) + ca + 1]; + else + dat = 0; + dev->ma++; + for (c = 0; c < 16; c++) + buffer32->line[dev->displine + 14][(x << 4) + c + 8] = (dat & (32768 >> c)) ? 7 : 0; + for (c = 0; c < 16; c += 8) + video_blend((x << 4) + c + 8, dev->displine + 14); + } + } else { + for (x = 0; x < dev->crtc[1]; x++) { + if (dev->ctrl & 8) { + /* Undocumented behavior: page 1 in text mode means characters are read + from page 1 and attributes from page 0. */ + chr = dev->charbuffer[x << 1]; + attr = dev->charbuffer[(x << 1) + 1]; + } else + chr = attr = 0; + drawcursor = ((dev->ma == ca) && dev->con && dev->cursoron); + blink = ((dev->blink & 16) && (dev->ctrl & 0x20) && (attr & 0x80) && !drawcursor); - if (dev->sc == 12 && ((attr & 7) == 1)) { - for (c = 0; c < 9; c++) - buffer32->line[dev->displine + 14][(x * 9) + c + 8] = dev->cols[attr][blink][1]; - } else { - for (c = 0; c < 8; c++) - buffer32->line[dev->displine + 14][(x * 9) + c + 8] = dev->cols[attr][blink][(fontdatm[chr][dev->sc] & (1 << (c ^ 7))) ? 1 : 0]; + if (dev->sc == 12 && ((attr & 7) == 1)) { + for (c = 0; c < 9; c++) + buffer32->line[dev->displine + 14][(x * 9) + c + 8] = dev->cols[attr][blink][1]; + } else { + for (c = 0; c < 8; c++) + buffer32->line[dev->displine + 14][(x * 9) + c + 8] = dev->cols[attr][blink][(fontdatm[chr][dev->sc] & (1 << (c ^ 7))) ? 1 : 0]; - if ((chr & ~0x1f) == 0xc0) - buffer32->line[dev->displine + 14][(x * 9) + 8 + 8] = dev->cols[attr][blink][fontdatm[chr][dev->sc] & 1]; - else - buffer32->line[dev->displine + 14][(x * 9) + 8 + 8] = dev->cols[attr][blink][0]; - } - if (dev->ctrl2 & 0x01) - dev->ma = (dev->ma + 1) & 0x3fff; - else - dev->ma = (dev->ma + 1) & 0x7ff; + if ((chr & ~0x1f) == 0xc0) + buffer32->line[dev->displine + 14][(x * 9) + 8 + 8] = dev->cols[attr][blink][fontdatm[chr][dev->sc] & 1]; + else + buffer32->line[dev->displine + 14][(x * 9) + 8 + 8] = dev->cols[attr][blink][0]; + } + if (dev->ctrl2 & 0x01) + dev->ma = (dev->ma + 1) & 0x3fff; + else + dev->ma = (dev->ma + 1) & 0x7ff; - if (drawcursor) { - for (c = 0; c < 9; c++) - buffer32->line[dev->displine + 14][(x * 9) + c + 8] ^= dev->cols[attr][0][1]; - } - } - } + if (drawcursor) { + for (c = 0; c < 9; c++) + buffer32->line[dev->displine + 14][(x * 9) + c + 8] ^= dev->cols[attr][0][1]; + } + } + } - hercules_render_overscan_right(dev); - } - dev->sc = oldsc; + hercules_render_overscan_right(dev); - if (dev->vc == dev->crtc[7] && !dev->sc) - dev->stat |= 8; - dev->displine++; - if (dev->displine >= 500) - dev->displine = 0; + if (dev->ctrl & 0x02) + x = dev->crtc[1] << 4; + else + x = dev->crtc[1] * 9; + + video_process_8(x + 16, dev->displine + 14); + } + dev->sc = oldsc; + + if (dev->vc == dev->crtc[7] && !dev->sc) + dev->stat |= 8; + dev->displine++; + if (dev->displine >= 500) + dev->displine = 0; } else { - timer_advance_u64(&dev->timer, dev->dispontime); + timer_advance_u64(&dev->timer, dev->dispontime); - if (dev->dispon) - dev->stat &= ~1; + if (dev->dispon) + dev->stat &= ~1; - dev->linepos = 0; - if (dev->vsynctime) { - dev->vsynctime--; - if (! dev->vsynctime) - dev->stat &= ~8; - } + dev->linepos = 0; + if (dev->vsynctime) { + dev->vsynctime--; + if (!dev->vsynctime) + dev->stat &= ~8; + } - if (dev->sc == (dev->crtc[11] & 31) || - ((dev->crtc[8] & 3)==3 && dev->sc == ((dev->crtc[11] & 31) >> 1))) { - dev->con = 0; - dev->coff = 1; - } + if (dev->sc == (dev->crtc[11] & 31) || ((dev->crtc[8] & 3) == 3 && dev->sc == ((dev->crtc[11] & 31) >> 1))) { + dev->con = 0; + dev->coff = 1; + } - if (dev->vadj) { - dev->sc++; - dev->sc &= 31; - dev->ma = dev->maback; - dev->vadj--; - if (! dev->vadj) { - dev->dispon = 1; - dev->ma = dev->maback = (dev->crtc[13] | (dev->crtc[12] << 8)) & 0x3fff; - dev->sc = 0; - } - } else if (((dev->crtc[8] & 3) != 3 && dev->sc == dev->crtc[9]) || ((dev->crtc[8] & 3) == 3 && dev->sc == (dev->crtc[9] >> 1))) { - dev->maback = dev->ma; - dev->sc = 0; - oldvc = dev->vc; - dev->vc++; - dev->vc &= 127; + if (dev->vadj) { + dev->sc++; + dev->sc &= 31; + dev->ma = dev->maback; + dev->vadj--; + if (!dev->vadj) { + dev->dispon = 1; + dev->ma = dev->maback = (dev->crtc[13] | (dev->crtc[12] << 8)) & 0x3fff; + dev->sc = 0; + } + } else if (((dev->crtc[8] & 3) != 3 && dev->sc == dev->crtc[9]) || ((dev->crtc[8] & 3) == 3 && dev->sc == (dev->crtc[9] >> 1))) { + dev->maback = dev->ma; + dev->sc = 0; + oldvc = dev->vc; + dev->vc++; + dev->vc &= 127; - if (dev->vc == dev->crtc[6]) - dev->dispon = 0; + if (dev->vc == dev->crtc[6]) + dev->dispon = 0; - if (oldvc == dev->crtc[4]) { - dev->vc = 0; - dev->vadj = dev->crtc[5]; - if (! dev->vadj) { - dev->dispon = 1; - dev->ma = dev->maback = (dev->crtc[13] | (dev->crtc[12] << 8)) & 0x3fff; - } - switch (dev->crtc[10] & 0x60) { - case 0x20: - dev->cursoron = 0; - break; - case 0x60: - dev->cursoron = dev->blink & 0x10; - break; - default: - dev->cursoron = dev->blink & 0x08; - break; - } - } + if (oldvc == dev->crtc[4]) { + dev->vc = 0; + dev->vadj = dev->crtc[5]; + if (!dev->vadj) { + dev->dispon = 1; + dev->ma = dev->maback = (dev->crtc[13] | (dev->crtc[12] << 8)) & 0x3fff; + } + switch (dev->crtc[10] & 0x60) { + case 0x20: + dev->cursoron = 0; + break; + case 0x60: + dev->cursoron = dev->blink & 0x10; + break; + default: + dev->cursoron = dev->blink & 0x08; + break; + } + } - if (dev->vc == dev->crtc[7]) { - dev->dispon = 0; - dev->displine = 0; - if ((dev->crtc[8] & 3) == 3) - dev->vsynctime = ((int32_t)dev->crtc[4] * ((dev->crtc[9] >> 1) + 1)) + dev->crtc[5] - dev->crtc[7] + 1; - else - dev->vsynctime = ((int32_t)dev->crtc[4] * (dev->crtc[9] + 1)) + dev->crtc[5] - dev->crtc[7] + 1; - if (dev->crtc[7]) { - if (dev->ctrl & 0x02) - x = dev->crtc[1] << 4; - else - x = dev->crtc[1] * 9; + if (dev->vc == dev->crtc[7]) { + dev->dispon = 0; + dev->displine = 0; + if ((dev->crtc[8] & 3) == 3) + dev->vsynctime = ((int32_t) dev->crtc[4] * ((dev->crtc[9] >> 1) + 1)) + dev->crtc[5] - dev->crtc[7] + 1; + else + dev->vsynctime = ((int32_t) dev->crtc[4] * (dev->crtc[9] + 1)) + dev->crtc[5] - dev->crtc[7] + 1; + if (dev->crtc[7]) { + if (dev->ctrl & 0x02) + x = dev->crtc[1] << 4; + else + x = dev->crtc[1] * 9; - dev->lastline++; - y = (dev->lastline - dev->firstline); + dev->lastline++; + y = (dev->lastline - dev->firstline); - if ((dev->ctrl & 8) && x && y && ((x != xsize) || (y != ysize) || video_force_resize_get())) { - xsize = x; - ysize = y; - if (xsize < 64) xsize = enable_overscan ? 640 : 656; - if (ysize < 32) ysize = 200; + if ((dev->ctrl & 8) && x && y && ((x != xsize) || (y != ysize) || video_force_resize_get())) { + xsize = x; + ysize = y; + if (xsize < 64) + xsize = enable_overscan ? 640 : 656; + if (ysize < 32) + ysize = 200; - set_screen_size(xsize + (enable_overscan ? 16 : 0), ysize + (enable_overscan ? 28 : 0)); + set_screen_size(xsize + (enable_overscan ? 16 : 0), ysize + (enable_overscan ? 28 : 0)); - if (video_force_resize_get()) - video_force_resize_set(0); - } + if (video_force_resize_get()) + video_force_resize_set(0); + } - if ((x >= 160) && ((y + 1) >= 120)) { - /* Draw (overscan_size) lines of overscan on top and bottom. */ - for (yy = 0; yy < 14; yy++) { - p = &(buffer32->line[(dev->firstline + yy) & 0x7ff][0]); + if ((x >= 160) && ((y + 1) >= 120)) { + /* Draw (overscan_size) lines of overscan on top and bottom. */ + for (yy = 0; yy < 14; yy++) { + p = &(buffer32->line[(dev->firstline + yy) & 0x7ff][0]); - for (xx = 0; xx < (x + 16); xx++) - p[xx] = 0x00000000; - } + for (xx = 0; xx < (x + 16); xx++) + p[xx] = 0x00000000; + } - for (yy = 0; yy < 14; yy++) { - p = &(buffer32->line[(dev->firstline + 14 + y + yy) & 0x7ff][0]); + for (yy = 0; yy < 14; yy++) { + p = &(buffer32->line[(dev->firstline + 14 + y + yy) & 0x7ff][0]); - for (xx = 0; xx < (x + 16); xx++) - p[xx] = 0x00000000; - } - } + for (xx = 0; xx < (x + 16); xx++) + p[xx] = 0x00000000; + } + } - if (enable_overscan) - video_blit_memtoscreen_8(0, dev->firstline, xsize + 16, ysize + 28); - else - video_blit_memtoscreen_8(8, dev->firstline + 14, xsize, ysize); - frames++; - // if ((dev->ctrl & 2) && (dev->ctrl2 & 1)) { - if (dev->ctrl & 0x02) { - video_res_x = dev->crtc[1] * 16; - video_res_y = dev->crtc[6] * 4; - video_bpp = 1; - } else { - video_res_x = dev->crtc[1]; - video_res_y = dev->crtc[6]; - video_bpp = 0; - } - } - dev->firstline = 1000; - dev->lastline = 0; - dev->blink++; - } - } else { - dev->sc++; - dev->sc &= 31; - dev->ma = dev->maback; - } + if (enable_overscan) + video_blit_memtoscreen(0, dev->firstline, xsize + 16, ysize + 28); + else + video_blit_memtoscreen(8, dev->firstline + 14, xsize, ysize); + frames++; +#if 0 + if ((dev->ctrl & 2) && (dev->ctrl2 & 1)) { +#endif + if (dev->ctrl & 0x02) { + video_res_x = dev->crtc[1] * 16; + video_res_y = dev->crtc[6] * 4; + video_bpp = 1; + } else { + video_res_x = dev->crtc[1]; + video_res_y = dev->crtc[6]; + video_bpp = 0; + } + } + dev->firstline = 1000; + dev->lastline = 0; + dev->blink++; + } + } else { + dev->sc++; + dev->sc &= 31; + dev->ma = dev->maback; + } - if ((dev->sc == (dev->crtc[10] & 31) || - ((dev->crtc[8] & 3)==3 && dev->sc == ((dev->crtc[10] & 31) >> 1)))) - dev->con = 1; - if (dev->dispon && !(dev->ctrl & 0x02)) { - for (x = 0; x < (dev->crtc[1] << 1); x++) { - pa = (dev->ctrl & 0x80) ? ((x & 1) ? 0x0000 : 0x8000) : 0x0000; - dev->charbuffer[x] = dev->vram[(((dev->ma << 1) + x) & 0x3fff) + pa]; - } - } + if (dev->sc == (dev->crtc[10] & 31) || ((dev->crtc[8] & 3) == 3 && dev->sc == ((dev->crtc[10] & 31) >> 1))) + dev->con = 1; + if (dev->dispon && !(dev->ctrl & 0x02)) { + for (x = 0; x < (dev->crtc[1] << 1); x++) { + pa = (dev->ctrl & 0x80) ? ((x & 1) ? 0x0000 : 0x8000) : 0x0000; + dev->charbuffer[x] = dev->vram[(((dev->ma << 1) + x) & 0x3fff) + pa]; + } + } } + VIDEO_MONITOR_EPILOGUE() } - static void * -hercules_init(const device_t *info) +hercules_init(UNUSED(const device_t *info)) { hercules_t *dev; - int c; - dev = (hercules_t *)malloc(sizeof(hercules_t)); + dev = (hercules_t *) malloc(sizeof(hercules_t)); memset(dev, 0x00, sizeof(hercules_t)); + dev->monitor_index = monitor_index_global; overscan_x = 16; overscan_y = 28; - dev->vram = (uint8_t *)malloc(0x10000); + dev->vram = (uint8_t *) malloc(0x10000); timer_add(&dev->timer, hercules_poll, dev, 1); mem_mapping_add(&dev->mapping, 0xb0000, 0x08000, - hercules_read,NULL,NULL, hercules_write,NULL,NULL, - NULL /*dev->vram*/, MEM_MAPPING_EXTERNAL, dev); + hercules_read, NULL, NULL, hercules_write, NULL, NULL, + NULL /*dev->vram*/, MEM_MAPPING_EXTERNAL, dev); io_sethandler(0x03b0, 16, - hercules_in,NULL,NULL, hercules_out,NULL,NULL, dev); + hercules_in, NULL, NULL, hercules_out, NULL, NULL, dev); - for (c = 0; c < 256; c++) { - dev->cols[c][0][0] = dev->cols[c][1][0] = dev->cols[c][1][1] = 16; + for (uint16_t c = 0; c < 256; c++) { + dev->cols[c][0][0] = dev->cols[c][1][0] = dev->cols[c][1][1] = 16; - if (c & 0x08) - dev->cols[c][0][1] = 15 + 16; - else - dev->cols[c][0][1] = 7 + 16; + if (c & 0x08) + dev->cols[c][0][1] = 15 + 16; + else + dev->cols[c][0][1] = 7 + 16; } dev->cols[0x70][0][1] = 16; - dev->cols[0x70][0][0] = dev->cols[0x70][1][0] = - dev->cols[0x70][1][1] = 16 + 15; - dev->cols[0xF0][0][1] = 16; - dev->cols[0xF0][0][0] = dev->cols[0xF0][1][0] = - dev->cols[0xF0][1][1] = 16 + 15; - dev->cols[0x78][0][1] = 16 + 7; - dev->cols[0x78][0][0] = dev->cols[0x78][1][0] = - dev->cols[0x78][1][1] = 16 + 15; - dev->cols[0xF8][0][1] = 16 + 7; - dev->cols[0xF8][0][0] = dev->cols[0xF8][1][0] = - dev->cols[0xF8][1][1] = 16 + 15; + dev->cols[0x70][0][0] = dev->cols[0x70][1][0] = dev->cols[0x70][1][1] = 16 + 15; + dev->cols[0xF0][0][1] = 16; + dev->cols[0xF0][0][0] = dev->cols[0xF0][1][0] = dev->cols[0xF0][1][1] = 16 + 15; + dev->cols[0x78][0][1] = 16 + 7; + dev->cols[0x78][0][0] = dev->cols[0x78][1][0] = dev->cols[0x78][1][1] = 16 + 15; + dev->cols[0xF8][0][1] = 16 + 7; + dev->cols[0xF8][0][0] = dev->cols[0xF8][1][0] = dev->cols[0xF8][1][1] = 16 + 15; dev->cols[0x00][0][1] = dev->cols[0x00][1][1] = 16; dev->cols[0x08][0][1] = dev->cols[0x08][1][1] = 16; dev->cols[0x80][0][1] = dev->cols[0x80][1][1] = 16; @@ -571,7 +577,7 @@ hercules_init(const device_t *info) cga_palette = device_get_config_int("rgb_type") << 1; if (cga_palette > 6) - cga_palette = 0; + cga_palette = 0; cgapal_rebuild(); herc_blend = device_get_config_int("blend"); @@ -581,71 +587,82 @@ hercules_init(const device_t *info) /* Force the LPT3 port to be enabled. */ lpt3_init(0x3BC); - return(dev); + return dev; } - static void hercules_close(void *priv) { - hercules_t *dev = (hercules_t *)priv; + hercules_t *dev = (hercules_t *) priv; if (!dev) - return; + return; if (dev->vram) - free(dev->vram); + free(dev->vram); free(dev); } - static void speed_changed(void *priv) { - hercules_t *dev = (hercules_t *)priv; - + hercules_t *dev = (hercules_t *) priv; + recalc_timings(dev); } - static const device_config_t hercules_config[] = { + // clang-format off { - "rgb_type", "Display type", CONFIG_SELECTION, "", 0, "", { 0 }, - { - { - "Default", 0 - }, - { - "Green", 1 - }, - { - "Amber", 2 - }, - { - "Gray", 3 - }, - { - "" - } - } + .name = "rgb_type", + .description = "Display type", + .type = CONFIG_SELECTION, + .default_int = 0, + .selection = { + { + .description = "Default", + .value = 0 + }, + { + .description = "Green", + .value = 1 + }, + { + .description = "Amber", + .value = 2 + }, + { + .description = "Gray", + .value = 3 + }, + { + .description = "" + } + } }, { - "blend", "Blend", CONFIG_BINARY, "", 1 + .name = "blend", + .description = "Blend", + .type = CONFIG_BINARY, + .default_int = 1 }, { - "", "", -1 + .type = CONFIG_END } + // clang-format on }; const device_t hercules_device = { - "Hercules", - "hercules", - DEVICE_ISA, - 0, - hercules_init, hercules_close, NULL, - { NULL }, - speed_changed, - NULL, - hercules_config + .name = "Hercules", + .internal_name = "hercules", + .flags = DEVICE_ISA, + .local = 0, + .init = hercules_init, + .close = hercules_close, + .reset = NULL, + { .available = NULL }, + .speed_changed = speed_changed, + .force_redraw = NULL, + .config = hercules_config }; diff --git a/src/video/vid_herculesplus.c b/src/video/vid_herculesplus.c index 81f436441..429632f19 100644 --- a/src/video/vid_herculesplus.c +++ b/src/video/vid_herculesplus.c @@ -1,20 +1,20 @@ /* - * 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. + * 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. + * This file is part of the 86Box distribution. * - * Hercules Plus emulation. + * Hercules Plus emulation. * * * - * Authors: Sarah Walker, - * Miran Grca, + * Authors: Sarah Walker, + * Miran Grca, * - * Copyright 2008-2018 Sarah Walker. - * Copyright 2016-2018 Miran Grca. + * Copyright 2008-2018 Sarah Walker. + * Copyright 2016-2018 Miran Grca. */ #include #include @@ -30,28 +30,28 @@ #include <86box/rom.h> #include <86box/device.h> #include <86box/video.h> - +#include <86box/plat_unused.h> /* extended CRTC registers */ -#define HERCULESPLUS_CRTC_XMODE 20 /* xMode register */ -#define HERCULESPLUS_CRTC_UNDER 21 /* Underline */ -#define HERCULESPLUS_CRTC_OVER 22 /* Overstrike */ +#define HERCULESPLUS_CRTC_XMODE 20 /* xMode register */ +#define HERCULESPLUS_CRTC_UNDER 21 /* Underline */ +#define HERCULESPLUS_CRTC_OVER 22 /* Overstrike */ /* character width */ -#define HERCULESPLUS_CW ((dev->crtc[HERCULESPLUS_CRTC_XMODE] & HERCULESPLUS_XMODE_90COL) ? 8 : 9) +#define HERCULESPLUS_CW ((dev->crtc[HERCULESPLUS_CRTC_XMODE] & HERCULESPLUS_XMODE_90COL) ? 8 : 9) /* mode control register */ -#define HERCULESPLUS_CTRL_GRAPH 0x02 -#define HERCULESPLUS_CTRL_ENABLE 0x08 -#define HERCULESPLUS_CTRL_BLINK 0x20 -#define HERCULESPLUS_CTRL_PAGE1 0x80 +#define HERCULESPLUS_CTRL_GRAPH 0x02 +#define HERCULESPLUS_CTRL_ENABLE 0x08 +#define HERCULESPLUS_CTRL_BLINK 0x20 +#define HERCULESPLUS_CTRL_PAGE1 0x80 /* CRTC status register */ -#define HERCULESPLUS_STATUS_HSYNC 0x01 /* horizontal sync */ +#define HERCULESPLUS_STATUS_HSYNC 0x01 /* horizontal sync */ #define HERCULESPLUS_STATUS_LIGHT 0x02 #define HERCULESPLUS_STATUS_VIDEO 0x08 -#define HERCULESPLUS_STATUS_ID 0x10 /* Card identification */ -#define HERCULESPLUS_STATUS_VSYNC 0x80 /* -vertical sync */ +#define HERCULESPLUS_STATUS_ID 0x10 /* Card identification */ +#define HERCULESPLUS_STATUS_VSYNC 0x80 /* -vertical sync */ /* configuration switch register */ #define HERCULESPLUS_CTRL2_GRAPH 0x01 @@ -61,594 +61,600 @@ #define HERCULESPLUS_XMODE_RAMFONT 0x01 #define HERCULESPLUS_XMODE_90COL 0x02 - typedef struct { - mem_mapping_t mapping; + mem_mapping_t mapping; - uint8_t crtc[32]; - int crtcreg; + uint8_t crtc[32]; + int crtcreg; - uint8_t ctrl, ctrl2, stat; + uint8_t ctrl, ctrl2, stat; - uint64_t dispontime, dispofftime; - pc_timer_t timer; + uint64_t dispontime, dispofftime; + pc_timer_t timer; - int firstline, lastline; + int firstline, lastline; - int linepos, displine; - int vc, sc; - uint16_t ma, maback; - int con, coff, cursoron; - int dispon, blink; - int vsynctime; - int vadj; + int linepos, displine; + int vc, sc; + uint16_t ma, maback; + int con, coff, cursoron; + int dispon, blink; + int vsynctime; + int vadj; + int monitor_index, prev_monitor_index; - int cols[256][2][2]; + int cols[256][2][2]; - uint8_t *vram; + uint8_t *vram; } herculesplus_t; -static video_timings_t timing_herculesplus = {VIDEO_ISA, 8, 16, 32, 8, 16, 32}; +#define VIDEO_MONITOR_PROLOGUE() \ + { \ + dev->prev_monitor_index = monitor_index_global; \ + monitor_index_global = dev->monitor_index; \ + } +#define VIDEO_MONITOR_EPILOGUE() \ + { \ + monitor_index_global = dev->prev_monitor_index; \ + } +static video_timings_t timing_herculesplus = { .type = VIDEO_ISA, .write_b = 8, .write_w = 16, .write_l = 32, .read_b = 8, .read_w = 16, .read_l = 32 }; static void recalc_timings(herculesplus_t *dev) { double disptime; - double _dispontime, _dispofftime; + double _dispontime; + double _dispofftime; - disptime = dev->crtc[0] + 1; + disptime = dev->crtc[0] + 1; _dispontime = dev->crtc[1]; _dispofftime = disptime - _dispontime; - _dispontime *= HERCCONST; + _dispontime *= HERCCONST; _dispofftime *= HERCCONST; - dev->dispontime = (uint64_t)(_dispontime); - dev->dispofftime = (uint64_t)(_dispofftime); + dev->dispontime = (uint64_t) (_dispontime); + dev->dispofftime = (uint64_t) (_dispofftime); } - static void herculesplus_out(uint16_t port, uint8_t val, void *priv) { - herculesplus_t *dev = (herculesplus_t *)priv; - uint8_t old; + herculesplus_t *dev = (herculesplus_t *) priv; + uint8_t old; switch (port) { - case 0x3b0: - case 0x3b2: - case 0x3b4: - case 0x3b6: - dev->crtcreg = val & 31; - return; + case 0x3b0: + case 0x3b2: + case 0x3b4: + case 0x3b6: + dev->crtcreg = val & 31; + return; - case 0x3b1: - case 0x3b3: - case 0x3b5: - case 0x3b7: - if (dev->crtcreg > 22) return; - old = dev->crtc[dev->crtcreg]; - dev->crtc[dev->crtcreg] = val; - if (dev->crtc[10] == 6 && dev->crtc[11] == 7) { - /*Fix for Generic Turbo XT BIOS, - *which sets up cursor registers wrong*/ - dev->crtc[10] = 0xb; - dev->crtc[11] = 0xc; - } - if (old ^ val) - recalc_timings(dev); - return; + case 0x3b1: + case 0x3b3: + case 0x3b5: + case 0x3b7: + if (dev->crtcreg > 22) + return; + old = dev->crtc[dev->crtcreg]; + dev->crtc[dev->crtcreg] = val; - case 0x3b8: - old = dev->ctrl; - dev->ctrl = val; - if (old ^ val) - recalc_timings(dev); - return; + if (dev->crtc[10] == 6 && dev->crtc[11] == 7) { + /*Fix for Generic Turbo XT BIOS, + *which sets up cursor registers wrong*/ + dev->crtc[10] = 0xb; + dev->crtc[11] = 0xc; + } + if (old ^ val) + recalc_timings(dev); + return; - case 0x3bf: - dev->ctrl2 = val; - if (val & 2) - mem_mapping_set_addr(&dev->mapping, 0xb0000, 0x10000); - else - mem_mapping_set_addr(&dev->mapping, 0xb0000, 0x08000); - return; - } + case 0x3b8: + old = dev->ctrl; + dev->ctrl = val; + if (old ^ val) + recalc_timings(dev); + return; + + case 0x3bf: + dev->ctrl2 = val; + if (val & 2) + mem_mapping_set_addr(&dev->mapping, 0xb0000, 0x10000); + else + mem_mapping_set_addr(&dev->mapping, 0xb0000, 0x08000); + return; + + default: + break; + } } - static uint8_t herculesplus_in(uint16_t port, void *priv) { - herculesplus_t *dev = (herculesplus_t *)priv; - uint8_t ret = 0xff; + const herculesplus_t *dev = (herculesplus_t *) priv; + uint8_t ret = 0xff; switch (port) { - case 0x3b0: - case 0x3b2: - case 0x3b4: - case 0x3b6: - ret = dev->crtcreg; - break; + case 0x3b0: + case 0x3b2: + case 0x3b4: + case 0x3b6: + ret = dev->crtcreg; + break; - case 0x3b1: - case 0x3b3: - case 0x3b5: - case 0x3b7: - if (dev->crtcreg <= 22) - ret = dev->crtc[dev->crtcreg]; - break; + case 0x3b1: + case 0x3b3: + case 0x3b5: + case 0x3b7: + if (dev->crtcreg <= 22) + ret = dev->crtc[dev->crtcreg]; + break; - case 0x3ba: - /* 0x50: InColor card identity */ - ret = (dev->stat & 0xf) | ((dev->stat & 8) << 4) | 0x10; - break; + case 0x3ba: + /* 0x10: Hercules Plus card identity */ + ret = (dev->stat & 0xf) | ((dev->stat & 8) << 4) | 0x10; + break; + + default: + break; } return ret; } - static void herculesplus_write(uint32_t addr, uint8_t val, void *priv) { - herculesplus_t *dev = (herculesplus_t *)priv; + herculesplus_t *dev = (herculesplus_t *) priv; dev->vram[addr & 0xffff] = val; } - static uint8_t herculesplus_read(uint32_t addr, void *priv) { - herculesplus_t *dev = (herculesplus_t *)priv; + const herculesplus_t *dev = (herculesplus_t *) priv; return dev->vram[addr & 0xffff]; } - static void draw_char_rom(herculesplus_t *dev, int x, uint8_t chr, uint8_t attr) { - unsigned ull, val, ifg, ibg; + unsigned ull; + unsigned val; + unsigned ifg; + unsigned ibg; const uint8_t *fnt; - int i, elg, blk; - int cw = HERCULESPLUS_CW; + int elg; + int blk; + int cw = HERCULESPLUS_CW; + int blink = dev->ctrl & HERCULESPLUS_CTRL_BLINK; blk = 0; - if (dev->ctrl & HERCULESPLUS_CTRL_BLINK) { - if (attr & 0x80) - blk = (dev->blink & 16); - attr &= 0x7f; + if (blink) { + if (attr & 0x80) + blk = (dev->blink & 16); + attr &= 0x7f; } /* MDA-compatible attributes */ ibg = 0; ifg = 7; - if ((attr & 0x77) == 0x70) { /* Invert */ - ifg = 0; - ibg = 7; - } - if (attr & 8) - ifg |= 8; /* High intensity FG */ - if (attr & 0x80) - ibg |= 8; /* High intensity BG */ - if ((attr & 0x77) == 0) /* Blank */ - ifg = ibg; + if ((attr & 0x77) == 0x70) { /* Invert */ + ifg = 0; + ibg = 7; + } + if (attr & 8) + ifg |= 8; /* High intensity FG */ + if (attr & 0x80) + ibg |= 8; /* High intensity BG */ + if ((attr & 0x77) == 0) /* Blank */ + ifg = ibg; ull = ((attr & 0x07) == 1) ? 13 : 0xffff; - if (dev->crtc[HERCULESPLUS_CRTC_XMODE] & HERCULESPLUS_XMODE_90COL) - elg = 0; - else - elg = ((chr >= 0xc0) && (chr <= 0xdf)); + if (dev->crtc[HERCULESPLUS_CRTC_XMODE] & HERCULESPLUS_XMODE_90COL) + elg = 0; + else + elg = ((chr >= 0xc0) && (chr <= 0xdf)); fnt = &(fontdatm[chr][dev->sc]); if (blk) { - val = 0x000; /* Blinking, draw all background */ - } else if (dev->sc == ull) { - val = 0x1ff; /* Underscore, draw all foreground */ + val = 0x000; /* Blinking, draw all background */ + } else if (dev->sc == ull) { + val = 0x1ff; /* Underscore, draw all foreground */ } else { - val = fnt[0] << 1; - - if (elg) - val |= (val >> 1) & 1; + val = fnt[0] << 1; + + if (elg) + val |= (val >> 1) & 1; } - for (i = 0; i < cw; i++) { - buffer32->line[dev->displine][x * cw + i] = (val & 0x100) ? ifg : ibg; - val = val << 1; + for (int i = 0; i < cw; i++) { + buffer32->line[dev->displine][x * cw + i] = (val & 0x100) ? ifg : ibg; + val = val << 1; } } - static void draw_char_ram4(herculesplus_t *dev, int x, uint8_t chr, uint8_t attr) { - unsigned ull, val, ifg, ibg, cfg; + unsigned ull; + unsigned val; + unsigned ifg; + unsigned ibg; const uint8_t *fnt; - int i, elg, blk; - int cw = HERCULESPLUS_CW; - int blink = dev->ctrl & HERCULESPLUS_CTRL_BLINK; + int elg; + int blk; + int cw = HERCULESPLUS_CW; + int blink = dev->ctrl & HERCULESPLUS_CTRL_BLINK; blk = 0; if (blink) { - if (attr & 0x80) - blk = (dev->blink & 16); - attr &= 0x7f; + if (attr & 0x80) + blk = (dev->blink & 16); + attr &= 0x7f; } /* MDA-compatible attributes */ ibg = 0; ifg = 7; - if ((attr & 0x77) == 0x70) { /* Invert */ - ifg = 0; - ibg = 7; - } - if (attr & 8) - ifg |= 8; /* High intensity FG */ - if (attr & 0x80) - ibg |= 8; /* High intensity BG */ - if ((attr & 0x77) == 0) /* Blank */ - ifg = ibg; + if ((attr & 0x77) == 0x70) { /* Invert */ + ifg = 0; + ibg = 7; + } + if (attr & 8) + ifg |= 8; /* High intensity FG */ + if (attr & 0x80) + ibg |= 8; /* High intensity BG */ + if ((attr & 0x77) == 0) /* Blank */ + ifg = ibg; ull = ((attr & 0x07) == 1) ? 13 : 0xffff; - if (dev->crtc[HERCULESPLUS_CRTC_XMODE] & HERCULESPLUS_XMODE_90COL) - elg = 0; - else - elg = ((chr >= 0xc0) && (chr <= 0xdf)); + + if (dev->crtc[HERCULESPLUS_CRTC_XMODE] & HERCULESPLUS_XMODE_90COL) + elg = 0; + else + elg = ((chr >= 0xc0) && (chr <= 0xdf)); + fnt = dev->vram + 0x4000 + 16 * chr + dev->sc; if (blk) { - /* Blinking, draw all background */ - val = 0x000; + val = 0x000; /* Blinking, draw all background */ } else if (dev->sc == ull) { - /* Underscore, draw all foreground */ - val = 0x1ff; + val = 0x1ff; /* Underscore, draw all foreground */ } else { - val = fnt[0x00000] << 1; - - if (elg) - val |= (val >> 1) & 1; + val = fnt[0] << 1; + + if (elg) + val |= (val >> 1) & 1; } - for (i = 0; i < cw; i++) { - /* Generate pixel colour */ - cfg = 0; - - /* cfg = colour of foreground pixels */ - if ((attr & 0x77) == 0) - cfg = ibg; /* 'blank' attribute */ - - buffer32->line[dev->displine][x * cw + i] = dev->cols[attr][blink][cfg]; - val = val << 1; + for (int i = 0; i < cw; i++) { + buffer32->line[dev->displine][x * cw + i] = (val & 0x100) ? ifg : ibg; + val = val << 1; } } - static void draw_char_ram48(herculesplus_t *dev, int x, uint8_t chr, uint8_t attr) { - int i, elg, blk, ul, ol, bld; - unsigned ull, oll, ulc = 0, olc = 0; - unsigned val, ibg, cfg; - const unsigned char *fnt; - int cw = HERCULESPLUS_CW; - int blink = dev->ctrl & HERCULESPLUS_CTRL_BLINK; - int font = (attr & 0x0F); + unsigned ull; + unsigned val; + unsigned ifg; + unsigned ibg; + const uint8_t *fnt; + int elg; + int blk; + int cw = HERCULESPLUS_CW; + int blink = dev->ctrl & HERCULESPLUS_CTRL_BLINK; + int font = (attr & 0x0F); - if (font >= 12) font &= 7; + if (font >= 12) + font &= 7; + + attr = (attr >> 4) ^ 0x0f; blk = 0; if (blink) { - if (attr & 0x40) - blk = (dev->blink & 16); - attr &= 0x7f; + if (attr & 0x80) + blk = (dev->blink & 16); + attr &= 0x7f; } /* MDA-compatible attributes */ - if (blink) { - ibg = (attr & 0x80) ? 8 : 0; - bld = 0; - ol = (attr & 0x20) ? 1 : 0; - ul = (attr & 0x10) ? 1 : 0; - } else { - bld = (attr & 0x80) ? 1 : 0; - ibg = (attr & 0x40) ? 0x0F : 0; - ol = (attr & 0x20) ? 1 : 0; - ul = (attr & 0x10) ? 1 : 0; + ibg = 0; + ifg = 7; + if ((attr & 0x77) == 0x70) { /* Invert */ + ifg = 0; + ibg = 7; } + if (attr & 8) + ifg |= 8; /* High intensity FG */ + if (attr & 0x80) + ibg |= 8; /* High intensity BG */ + if ((attr & 0x77) == 0) /* Blank */ + ifg = ibg; + ull = ((attr & 0x07) == 1) ? 13 : 0xffff; - if (ul) { - ull = dev->crtc[HERCULESPLUS_CRTC_UNDER] & 0x0F; - ulc = (dev->crtc[HERCULESPLUS_CRTC_UNDER] >> 4) & 0x0F; - if (ulc == 0) ulc = 7; - } else { - ull = 0xFFFF; - } + if (dev->crtc[HERCULESPLUS_CRTC_XMODE] & HERCULESPLUS_XMODE_90COL) + elg = 0; + else + elg = ((chr >= 0xc0) && (chr <= 0xdf)); - if (ol) { - oll = dev->crtc[HERCULESPLUS_CRTC_OVER] & 0x0F; - olc = (dev->crtc[HERCULESPLUS_CRTC_OVER] >> 4) & 0x0F; - if (olc == 0) olc = 7; - } else { - oll = 0xFFFF; - } - - if (dev->crtc[HERCULESPLUS_CRTC_XMODE] & HERCULESPLUS_XMODE_90COL) - elg = 0; - else - elg = ((chr >= 0xc0) && (chr <= 0xdf)); fnt = dev->vram + 0x4000 + 16 * chr + 4096 * font + dev->sc; - if (blk) { /* Blinking, draw all background */ - val = 0x000; + if (blk) { + val = 0x000; /* Blinking, draw all background */ } else if (dev->sc == ull) { - /* Underscore, draw all foreground */ - val = 0x1ff; + val = 0x1ff; /* Underscore, draw all foreground */ } else { - val = fnt[0x00000] << 1; - - if (elg) - val |= (val >> 1) & 1; - if (bld) - val |= (val >> 1); + val = fnt[0] << 1; + + if (elg) + val |= (val >> 1) & 1; } - for (i = 0; i < cw; i++) { - /* Generate pixel colour */ - cfg = val & 0x100; - if (dev->sc == oll) - cfg = olc ^ ibg; /* Strikethrough */ - else if (dev->sc == ull) - cfg = ulc ^ ibg; /* Underline */ - else - cfg |= ibg; - - buffer32->line[dev->displine][(x * cw) + i] = dev->cols[attr][blink][cfg]; - val = val << 1; + for (int i = 0; i < cw; i++) { + buffer32->line[dev->displine][x * cw + i] = (val & 0x100) ? ifg : ibg; + val = val << 1; } } - static void text_line(herculesplus_t *dev, uint16_t ca) { - int drawcursor; - int x, c; - uint8_t chr, attr; + int drawcursor; + uint8_t chr; + uint8_t attr; uint32_t col; - for (x = 0; x < dev->crtc[1]; x++) { - if (dev->ctrl & 8) { - chr = dev->vram[(dev->ma << 1) & 0xfff]; - attr = dev->vram[((dev->ma << 1) + 1) & 0xfff]; - } else - chr = attr = 0; + for (uint8_t x = 0; x < dev->crtc[1]; x++) { + if (dev->ctrl & 8) { + chr = dev->vram[(dev->ma << 1) & 0x3fff]; + attr = dev->vram[((dev->ma << 1) + 1) & 0x3fff]; + } else + chr = attr = 0; - drawcursor = ((dev->ma == ca) && dev->con && dev->cursoron); + drawcursor = ((dev->ma == ca) && dev->con && dev->cursoron); - switch (dev->crtc[HERCULESPLUS_CRTC_XMODE] & 5) { - case 0: - case 4: /* ROM font */ - draw_char_rom(dev, x, chr, attr); - break; + switch (dev->crtc[HERCULESPLUS_CRTC_XMODE] & 5) { + case 0: + case 4: /* ROM font */ + draw_char_rom(dev, x, chr, attr); + break; - case 1: /* 4k RAMfont */ - draw_char_ram4(dev, x, chr, attr); - break; + case 1: /* 4k RAMfont */ + draw_char_ram4(dev, x, chr, attr); + break; - case 5: /* 48k RAMfont */ - draw_char_ram48(dev, x, chr, attr); - break; - } - ++dev->ma; + case 5: /* 48k RAMfont */ + draw_char_ram48(dev, x, chr, attr); + break; - if (drawcursor) { - int cw = HERCULESPLUS_CW; + default: + break; + } + ++dev->ma; - col = dev->cols[attr][0][1]; - for (c = 0; c < cw; c++) - buffer32->line[dev->displine][x * cw + c] = col; - } + if (drawcursor) { + int cw = HERCULESPLUS_CW; + + col = dev->cols[attr][0][1]; + for (int c = 0; c < cw; c++) + buffer32->line[dev->displine][x * cw + c] = col; + } } } - static void graphics_line(herculesplus_t *dev) { uint16_t ca; - int x, c, plane = 0; + int c; + int plane = 0; uint16_t val; /* Graphics mode. */ ca = (dev->sc & 3) * 0x2000; if ((dev->ctrl & HERCULESPLUS_CTRL_PAGE1) && (dev->ctrl2 & HERCULESPLUS_CTRL2_PAGE1)) - ca += 0x8000; + ca += 0x8000; - for (x = 0; x < dev->crtc[1]; x++) { - if (dev->ctrl & 8) - val = (dev->vram[((dev->ma << 1) & 0x1fff) + ca + 0x10000 * plane] << 8) - | dev->vram[((dev->ma << 1) & 0x1fff) + ca + 0x10000 * plane + 1]; - else - val = 0; + for (uint8_t x = 0; x < dev->crtc[1]; x++) { + if (dev->ctrl & 8) + val = (dev->vram[((dev->ma << 1) & 0x1fff) + ca + 0x10000 * plane] << 8) + | dev->vram[((dev->ma << 1) & 0x1fff) + ca + 0x10000 * plane + 1]; + else + val = 0; - dev->ma++; - for (c = 0; c < 16; c++) { - buffer32->line[dev->displine][(x << 4) + c] = (val & 0x8000) ? 7 : 0; + dev->ma++; + for (c = 0; c < 16; c++) { + buffer32->line[dev->displine][(x << 4) + c] = (val & 0x8000) ? 7 : 0; - val <<= 1; - } + val <<= 1; + } - for (c = 0; c < 16; c += 8) - video_blend((x << 4) + c, dev->displine); + for (c = 0; c < 16; c += 8) + video_blend((x << 4) + c, dev->displine); } } - static void herculesplus_poll(void *priv) { - herculesplus_t *dev = (herculesplus_t *)priv; - uint16_t ca = (dev->crtc[15] | (dev->crtc[14] << 8)) & 0x3fff; - int x, oldvc, oldsc; + herculesplus_t *dev = (herculesplus_t *) priv; + uint16_t ca = (dev->crtc[15] | (dev->crtc[14] << 8)) & 0x3fff; + int x; + int oldvc; + int oldsc; + int cw = HERCULESPLUS_CW; - if (! dev->linepos) { - timer_advance_u64(&dev->timer, dev->dispofftime); - dev->stat |= 1; - dev->linepos = 1; - oldsc = dev->sc; - if ((dev->crtc[8] & 3) == 3) - dev->sc = (dev->sc << 1) & 7; - if (dev->dispon) { - if (dev->displine < dev->firstline) { - dev->firstline = dev->displine; - video_wait_for_buffer(); - } - dev->lastline = dev->displine; - if ((dev->ctrl & HERCULESPLUS_CTRL_GRAPH) && (dev->ctrl2 & HERCULESPLUS_CTRL2_GRAPH)) - graphics_line(dev); - else - text_line(dev, ca); - } - dev->sc = oldsc; - if (dev->vc == dev->crtc[7] && !dev->sc) - dev->stat |= 8; - dev->displine++; - if (dev->displine >= 500) - dev->displine = 0; + VIDEO_MONITOR_PROLOGUE(); + if (!dev->linepos) { + timer_advance_u64(&dev->timer, dev->dispofftime); + dev->stat |= 1; + dev->linepos = 1; + oldsc = dev->sc; + if ((dev->crtc[8] & 3) == 3) + dev->sc = (dev->sc << 1) & 7; + if (dev->dispon) { + if (dev->displine < dev->firstline) { + dev->firstline = dev->displine; + video_wait_for_buffer(); + } + dev->lastline = dev->displine; + if ((dev->ctrl & HERCULESPLUS_CTRL_GRAPH) && (dev->ctrl2 & HERCULESPLUS_CTRL2_GRAPH)) + graphics_line(dev); + else + text_line(dev, ca); + + if ((dev->ctrl & HERCULESPLUS_CTRL_GRAPH) && (dev->ctrl2 & HERCULESPLUS_CTRL2_GRAPH)) + x = dev->crtc[1] << 4; + else + x = dev->crtc[1] * cw; + + video_process_8(x, dev->displine); + } + dev->sc = oldsc; + if (dev->vc == dev->crtc[7] && !dev->sc) + dev->stat |= 8; + dev->displine++; + if (dev->displine >= 500) + dev->displine = 0; } else { - timer_advance_u64(&dev->timer, dev->dispontime); - if (dev->dispon) - dev->stat &= ~1; - dev->linepos = 0; - if (dev->vsynctime) { - dev->vsynctime--; - if (! dev->vsynctime) - dev->stat &= ~8; - } + timer_advance_u64(&dev->timer, dev->dispontime); + if (dev->dispon) + dev->stat &= ~1; + dev->linepos = 0; + if (dev->vsynctime) { + dev->vsynctime--; + if (!dev->vsynctime) + dev->stat &= ~8; + } - if (dev->sc == (dev->crtc[11] & 31) || ((dev->crtc[8] & 3) == 3 && dev->sc == ((dev->crtc[11] & 31) >> 1))) { - dev->con = 0; - dev->coff = 1; - } - if (dev->vadj) { - dev->sc++; - dev->sc &= 31; - dev->ma = dev->maback; - dev->vadj--; - if (! dev->vadj) { - dev->dispon = 1; - dev->ma = dev->maback = (dev->crtc[13] | (dev->crtc[12] << 8)) & 0x3fff; - dev->sc = 0; - } - } else if (dev->sc == dev->crtc[9] || ((dev->crtc[8] & 3) == 3 && dev->sc == (dev->crtc[9] >> 1))) { - dev->maback = dev->ma; - dev->sc = 0; - oldvc = dev->vc; - dev->vc++; - dev->vc &= 127; - if (dev->vc == dev->crtc[6]) - dev->dispon = 0; - if (oldvc == dev->crtc[4]) { - dev->vc = 0; - dev->vadj = dev->crtc[5]; - if (!dev->vadj) dev->dispon=1; - if (!dev->vadj) dev->ma = dev->maback = (dev->crtc[13] | (dev->crtc[12] << 8)) & 0x3fff; - if ((dev->crtc[10] & 0x60) == 0x20) - dev->cursoron = 0; - else - dev->cursoron = dev->blink & 16; - } - if (dev->vc == dev->crtc[7]) { - dev->dispon = 0; - dev->displine = 0; - dev->vsynctime = 16; - if (dev->crtc[7]) { - if ((dev->ctrl & HERCULESPLUS_CTRL_GRAPH) && (dev->ctrl2 & HERCULESPLUS_CTRL2_GRAPH)) - x = dev->crtc[1] << 4; - else - x = dev->crtc[1] * 9; - dev->lastline++; - if ((dev->ctrl & 8) && - ((x != xsize) || ((dev->lastline - dev->firstline) != ysize) || video_force_resize_get())) { - xsize = x; - ysize = dev->lastline - dev->firstline; - if (xsize < 64) xsize = 656; - if (ysize < 32) ysize = 200; - set_screen_size(xsize, ysize); + if (dev->sc == (dev->crtc[11] & 31) || ((dev->crtc[8] & 3) == 3 && dev->sc == ((dev->crtc[11] & 31) >> 1))) { + dev->con = 0; + dev->coff = 1; + } + if (dev->vadj) { + dev->sc++; + dev->sc &= 31; + dev->ma = dev->maback; + dev->vadj--; + if (!dev->vadj) { + dev->dispon = 1; + dev->ma = dev->maback = (dev->crtc[13] | (dev->crtc[12] << 8)) & 0x3fff; + dev->sc = 0; + } + } else if (dev->sc == dev->crtc[9] || ((dev->crtc[8] & 3) == 3 && dev->sc == (dev->crtc[9] >> 1))) { + dev->maback = dev->ma; + dev->sc = 0; + oldvc = dev->vc; + dev->vc++; + dev->vc &= 127; + if (dev->vc == dev->crtc[6]) + dev->dispon = 0; + if (oldvc == dev->crtc[4]) { + dev->vc = 0; + dev->vadj = dev->crtc[5]; + if (!dev->vadj) + dev->dispon = 1; + if (!dev->vadj) + dev->ma = dev->maback = (dev->crtc[13] | (dev->crtc[12] << 8)) & 0x3fff; + if ((dev->crtc[10] & 0x60) == 0x20) + dev->cursoron = 0; + else + dev->cursoron = dev->blink & 16; + } + if (dev->vc == dev->crtc[7]) { + dev->dispon = 0; + dev->displine = 0; + dev->vsynctime = 16; + if (dev->crtc[7]) { + if ((dev->ctrl & HERCULESPLUS_CTRL_GRAPH) && (dev->ctrl2 & HERCULESPLUS_CTRL2_GRAPH)) + x = dev->crtc[1] << 4; + else + x = dev->crtc[1] * cw; + dev->lastline++; + if ((dev->ctrl & 8) && ((x != xsize) || ((dev->lastline - dev->firstline) != ysize) || video_force_resize_get())) { + xsize = x; + ysize = dev->lastline - dev->firstline; + if (xsize < 64) + xsize = 656; + if (ysize < 32) + ysize = 200; + set_screen_size(xsize, ysize); - if (video_force_resize_get()) - video_force_resize_set(0); - } - video_blit_memtoscreen_8(0, dev->firstline, xsize, dev->lastline - dev->firstline); - frames++; - if ((dev->ctrl & HERCULESPLUS_CTRL_GRAPH) && (dev->ctrl2 & HERCULESPLUS_CTRL2_GRAPH)) { - video_res_x = dev->crtc[1] * 16; - video_res_y = dev->crtc[6] * 4; - video_bpp = 1; - } else { - video_res_x = dev->crtc[1]; - video_res_y = dev->crtc[6]; - video_bpp = 0; - } - } - dev->firstline = 1000; - dev->lastline = 0; - dev->blink++; - } - } else { - dev->sc++; - dev->sc &= 31; - dev->ma = dev->maback; - } + if (video_force_resize_get()) + video_force_resize_set(0); + } + video_blit_memtoscreen(0, dev->firstline, xsize, dev->lastline - dev->firstline); + frames++; + if ((dev->ctrl & HERCULESPLUS_CTRL_GRAPH) && (dev->ctrl2 & HERCULESPLUS_CTRL2_GRAPH)) { + video_res_x = dev->crtc[1] * 16; + video_res_y = dev->crtc[6] * 4; + video_bpp = 1; + } else { + video_res_x = dev->crtc[1]; + video_res_y = dev->crtc[6]; + video_bpp = 0; + } + } + dev->firstline = 1000; + dev->lastline = 0; + dev->blink++; + } + } else { + dev->sc++; + dev->sc &= 31; + dev->ma = dev->maback; + } - if ((dev->sc == (dev->crtc[10] & 31) || ((dev->crtc[8] & 3) == 3 && dev->sc == ((dev->crtc[10] & 31) >> 1)))) - dev->con = 1; + if (dev->sc == (dev->crtc[10] & 31) || ((dev->crtc[8] & 3) == 3 && dev->sc == ((dev->crtc[10] & 31) >> 1))) + dev->con = 1; } + + VIDEO_MONITOR_EPILOGUE(); } - static void * -herculesplus_init(const device_t *info) +herculesplus_init(UNUSED(const device_t *info)) { herculesplus_t *dev; - int c; - dev = (herculesplus_t *)malloc(sizeof(herculesplus_t)); + dev = (herculesplus_t *) malloc(sizeof(herculesplus_t)); memset(dev, 0, sizeof(herculesplus_t)); - dev->vram = (uint8_t *)malloc(0x10000); /* 64k VRAM */ + dev->vram = (uint8_t *) malloc(0x10000); /* 64k VRAM */ + dev->monitor_index = monitor_index_global; timer_add(&dev->timer, herculesplus_poll, dev, 1); - mem_mapping_add(&dev->mapping, 0xb0000, 0x10000, - herculesplus_read,NULL,NULL, - herculesplus_write,NULL,NULL, - dev->vram, MEM_MAPPING_EXTERNAL, dev); + mem_mapping_add(&dev->mapping, 0xb0000, 0x08000, + herculesplus_read, NULL, NULL, + herculesplus_write, NULL, NULL, + dev->vram, MEM_MAPPING_EXTERNAL, dev); io_sethandler(0x03b0, 16, - herculesplus_in,NULL, NULL, herculesplus_out,NULL,NULL, dev); + herculesplus_in, NULL, NULL, herculesplus_out, NULL, NULL, dev); - for (c = 0; c < 256; c++) { - dev->cols[c][0][0] = dev->cols[c][1][0] = dev->cols[c][1][1] = 16; - if (c & 8) - dev->cols[c][0][1] = 15 + 16; - else - dev->cols[c][0][1] = 7 + 16; + for (uint16_t c = 0; c < 256; c++) { + dev->cols[c][0][0] = dev->cols[c][1][0] = dev->cols[c][1][1] = 16; + if (c & 8) + dev->cols[c][0][1] = 15 + 16; + else + dev->cols[c][0][1] = 7 + 16; } dev->cols[0x70][0][1] = 16; - dev->cols[0x70][0][0] = dev->cols[0x70][1][0] = - dev->cols[0x70][1][1] = 16 + 15; - dev->cols[0xF0][0][1] = 16; - dev->cols[0xF0][0][0] = dev->cols[0xF0][1][0] = - dev->cols[0xF0][1][1] = 16 + 15; - dev->cols[0x78][0][1] = 16 + 7; - dev->cols[0x78][0][0] = dev->cols[0x78][1][0] = - dev->cols[0x78][1][1] = 16 + 15; - dev->cols[0xF8][0][1] = 16 + 7; - dev->cols[0xF8][0][0] = dev->cols[0xF8][1][0] = - dev->cols[0xF8][1][1] = 16 + 15; + dev->cols[0x70][0][0] = dev->cols[0x70][1][0] = dev->cols[0x70][1][1] = 16 + 15; + dev->cols[0xF0][0][1] = 16; + dev->cols[0xF0][0][0] = dev->cols[0xF0][1][0] = dev->cols[0xF0][1][1] = 16 + 15; + dev->cols[0x78][0][1] = 16 + 7; + dev->cols[0x78][0][0] = dev->cols[0x78][1][0] = dev->cols[0x78][1][1] = 16 + 15; + dev->cols[0xF8][0][1] = 16 + 7; + dev->cols[0xF8][0][0] = dev->cols[0xF8][1][0] = dev->cols[0xF8][1][1] = 16 + 15; dev->cols[0x00][0][1] = dev->cols[0x00][1][1] = 16; dev->cols[0x08][0][1] = dev->cols[0x08][1][1] = 16; dev->cols[0x80][0][1] = dev->cols[0x80][1][1] = 16; @@ -658,7 +664,7 @@ herculesplus_init(const device_t *info) cga_palette = device_get_config_int("rgb_type") << 1; if (cga_palette > 6) - cga_palette = 0; + cga_palette = 0; cgapal_rebuild(); video_inform(VIDEO_FLAG_TYPE_MDA, &timing_herculesplus); @@ -669,68 +675,79 @@ herculesplus_init(const device_t *info) return dev; } - static void herculesplus_close(void *priv) { - herculesplus_t *dev = (herculesplus_t *)priv; + herculesplus_t *dev = (herculesplus_t *) priv; if (!dev) - return; + return; if (dev->vram) - free(dev->vram); + free(dev->vram); free(dev); } - static void speed_changed(void *priv) { - herculesplus_t *dev = (herculesplus_t *)priv; + herculesplus_t *dev = (herculesplus_t *) priv; recalc_timings(dev); } - static const device_config_t herculesplus_config[] = { + // clang-format off { - "rgb_type", "Display type", CONFIG_SELECTION, "", 0, "", { 0 }, - { - { - "Default", 0 - }, - { - "Green", 1 - }, - { - "Amber", 2 - }, - { - "Gray", 3 - }, - { - "" - } - } + .name = "rgb_type", + .description = "Display type", + .type = CONFIG_SELECTION, + .default_int = 0, + .selection = { + { + .description = "Default", + .value = 0 + }, + { + .description = "Green", + .value = 1 + }, + { + .description = "Amber", + .value = 2 + }, + { + .description = "Gray", + .value = 3 + }, + { + .description = "" + } + } }, { - "blend", "Blend", CONFIG_BINARY, "", 1 + .name = "blend", + .description = "Blend", + .type = CONFIG_BINARY, + .default_int = 1 }, { - "", "", -1 + .type = CONFIG_END } + // clang-format on }; const device_t herculesplus_device = { - "Hercules Plus", - "hercules_plus", - DEVICE_ISA, - 0, - herculesplus_init, herculesplus_close, NULL, - { NULL }, - speed_changed, - NULL, - herculesplus_config + .name = "Hercules Plus", + .internal_name = "hercules_plus", + .flags = DEVICE_ISA, + .local = 0, + .init = herculesplus_init, + .close = herculesplus_close, + .reset = NULL, + { .available = NULL }, + .speed_changed = speed_changed, + .force_redraw = NULL, + .config = herculesplus_config }; diff --git a/src/video/vid_ht216.c b/src/video/vid_ht216.c index 2b179ba7e..9cd68e4ee 100644 --- a/src/video/vid_ht216.c +++ b/src/video/vid_ht216.c @@ -1,26 +1,28 @@ /* - * 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. + * 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. + * This file is part of the 86Box distribution. * - * Video 7 VGA 1024i emulation. + * Video 7 VGA 1024i emulation. * * * - * Authors: Sarah Walker, - * Miran Grca, + * Authors: Sarah Walker, + * Miran Grca, * - * Copyright 2019 Sarah Walker. - * Copyright 2019 Miran Grca. + * Copyright 2019 Sarah Walker. + * Copyright 2019 Miran Grca. */ +#include #include #include #include #include #include +#define HAVE_STDARG_H #include <86box/86box.h> #include "cpu.h" #include <86box/io.h> @@ -33,526 +35,540 @@ #include <86box/video.h> #include <86box/vid_svga.h> #include <86box/vid_svga_render.h> +#include <86box/plat_fallthrough.h> +#include <86box/plat_unused.h> +typedef struct ht216_t { + svga_t svga; -typedef struct ht216_t -{ - svga_t svga; + mem_mapping_t linear_mapping; - mem_mapping_t linear_mapping; + rom_t bios_rom; - rom_t bios_rom; + uint32_t vram_mask, linear_base; + uint8_t adjust_cursor, monitor_type; - uint32_t vram_mask, linear_base; - uint8_t adjust_cursor, monitor_type; + int ext_reg_enable; + int isabus; + int mca; - int ext_reg_enable; - int isabus; - int mca; - - uint8_t read_bank_reg[2], write_bank_reg[2]; - uint16_t id, misc; - uint32_t read_banks[2], write_banks[2]; - - uint8_t bg_latch[8]; - uint8_t fg_latch[4]; - uint8_t bg_plane_sel, fg_plane_sel; - - uint8_t ht_regs[256]; - uint8_t extensions, reg_3cb; - - uint8_t pos_regs[8]; + uint8_t read_bank_reg[2], write_bank_reg[2]; + uint16_t id, misc; + uint32_t read_banks[2], write_banks[2]; + + uint8_t bg_latch[8]; + uint8_t fg_latch[4]; + uint8_t bg_plane_sel, fg_plane_sel; + + uint8_t ht_regs[256]; + uint8_t extensions, reg_3cb; + + uint8_t pos_regs[8]; } ht216_t; - #define HT_MISC_PAGE_SEL (1 << 5) /*Shifts CPU VRAM read address by 3 bits, for use with fat pixel color expansion*/ -#define HT_REG_C8_MOVSB (1 << 0) -#define HT_REG_C8_E256 (1 << 4) -#define HT_REG_C8_XLAM (1 << 6) +#define HT_REG_C8_MOVSB (1 << 0) +#define HT_REG_C8_E256 (1 << 4) +#define HT_REG_C8_XLAM (1 << 6) #define HT_REG_CD_P8PCEXP (1 << 0) #define HT_REG_CD_FP8PCEXP (1 << 1) #define HT_REG_CD_BMSKSL (3 << 2) #define HT_REG_CD_RMWMDE (1 << 5) /*Use GDC data rotate as offset when reading VRAM data into latches*/ -#define HT_REG_CD_ASTODE (1 << 6) -#define HT_REG_CD_EXALU (1 << 7) +#define HT_REG_CD_ASTODE (1 << 6) +#define HT_REG_CD_EXALU (1 << 7) -#define HT_REG_E0_SBAE (1 << 7) +#define HT_REG_E0_SBAE (1 << 7) -#define HT_REG_F9_XPSEL (1 << 0) +#define HT_REG_F9_XPSEL (1 << 0) /*Enables A[14:15] of VRAM address in chain-4 modes*/ #define HT_REG_FC_ECOLRE (1 << 2) -#define HT_REG_FE_FBRC (1 << 1) -#define HT_REG_FE_FBMC (3 << 2) -#define HT_REG_FE_FBRSL (3 << 4) - +#define HT_REG_FE_FBRC (1 << 1) +#define HT_REG_FE_FBMC (3 << 2) +#define HT_REG_FE_FBRSL (3 << 4) void ht216_remap(ht216_t *ht216); -void ht216_out(uint16_t addr, uint8_t val, void *p); -uint8_t ht216_in(uint16_t addr, void *p); +void ht216_out(uint16_t addr, uint8_t val, void *priv); +uint8_t ht216_in(uint16_t addr, void *priv); +#define BIOS_G2_GC205_PATH "roms/video/video7/BIOS.BIN" +#define BIOS_VIDEO7_VGA_1024I_PATH "roms/video/video7/Video Seven VGA 1024i - BIOS - v2.19 - 435-0062-05 - U17 - 27C256.BIN" +#define BIOS_RADIUS_SVGA_MULTIVIEW_PATH "roms/video/video7/U18.BIN" +#define BIOS_HT216_32_PATH "roms/video/video7/HT21632.BIN" -#define BIOS_G2_GC205_PATH "roms/video/video7/BIOS.BIN" -#define BIOS_VIDEO7_VGA_1024I_PATH "roms/video/video7/Video Seven VGA 1024i - BIOS - v2.19 - 435-0062-05 - U17 - 27C256.BIN" -#define BIOS_RADIUS_SVGA_MULTIVIEW_PATH "roms/video/video7/U18.BIN" -#define BIOS_HT216_32_PATH "roms/video/video7/HT21632.BIN" - -static video_timings_t timing_v7vga_isa = {VIDEO_ISA, 3, 3, 6, 5, 5, 10}; -static video_timings_t timing_v7vga_mca = {VIDEO_MCA, 4, 5, 10, 5, 5, 10}; -static video_timings_t timing_v7vga_vlb = {VIDEO_BUS, 5, 5, 9, 20, 20, 30}; - +static video_timings_t timing_v7vga_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_v7vga_mca = { .type = VIDEO_MCA, .write_b = 4, .write_w = 5, .write_l = 10, .read_b = 5, .read_w = 5, .read_l = 10 }; +static video_timings_t timing_v7vga_vlb = { .type = VIDEO_BUS, .write_b = 5, .write_w = 5, .write_l = 9, .read_b = 20, .read_w = 20, .read_l = 30 }; #ifdef ENABLE_HT216_LOG int ht216_do_log = ENABLE_HT216_LOG; - static void ht216_log(const char *fmt, ...) { va_list ap; if (ht216_do_log) { - va_start(ap, fmt); - pclog_ex(fmt, ap); - va_end(ap); + va_start(ap, fmt); + pclog_ex(fmt, ap); + va_end(ap); } } #else -#define ht216_log(fmt, ...) +# define ht216_log(fmt, ...) #endif /*Remap address for chain-4/doubleword style layout*/ static __inline uint32_t dword_remap(svga_t *svga, uint32_t in_addr) { - if (svga->packed_chain4) - return in_addr; - return ((in_addr & 0xfffc) << 2) | ((in_addr & 0x30000) >> 14) | (in_addr & ~0x3ffff); + if (svga->packed_chain4) + return in_addr; + return ((in_addr & 0xfffc) << 2) | ((in_addr & 0x30000) >> 14) | (in_addr & ~0x3ffff); } static void ht216_recalc_bank_regs(ht216_t *ht216, int mode) { - svga_t *svga = &ht216->svga; - - if (mode) { - ht216->read_bank_reg[0] = ht216->ht_regs[0xe8]; - ht216->write_bank_reg[0] = ht216->ht_regs[0xe8]; - ht216->read_bank_reg[1] = ht216->ht_regs[0xe9]; - ht216->write_bank_reg[1] = ht216->ht_regs[0xe9]; + const svga_t *svga = &ht216->svga; + + if (mode) { + ht216->read_bank_reg[0] = ht216->ht_regs[0xe8]; + ht216->write_bank_reg[0] = ht216->ht_regs[0xe8]; + ht216->read_bank_reg[1] = ht216->ht_regs[0xe9]; + ht216->write_bank_reg[1] = ht216->ht_regs[0xe9]; } else { - ht216->read_bank_reg[0] = ((ht216->ht_regs[0xf6] & 0xc) << 4); - ht216->read_bank_reg[1] = ((ht216->ht_regs[0xf6] & 0xc) << 4); - ht216->write_bank_reg[0] = ((ht216->ht_regs[0xf6] & 0x3) << 6); - ht216->write_bank_reg[1] = ((ht216->ht_regs[0xf6] & 0x3) << 6); + ht216->read_bank_reg[0] = ((ht216->ht_regs[0xf6] & 0xc) << 4); + ht216->read_bank_reg[1] = ((ht216->ht_regs[0xf6] & 0xc) << 4); + ht216->write_bank_reg[0] = ((ht216->ht_regs[0xf6] & 0x3) << 6); + ht216->write_bank_reg[1] = ((ht216->ht_regs[0xf6] & 0x3) << 6); - if (svga->packed_chain4 || (ht216->ht_regs[0xfc] & HT_REG_FC_ECOLRE)) { - ht216->read_bank_reg[0] |= (ht216->misc & 0x20); - ht216->read_bank_reg[1] |= (ht216->misc & 0x20); - ht216->write_bank_reg[0] |= (ht216->misc & 0x20); - ht216->write_bank_reg[1] |= (ht216->misc & 0x20); - } + if (svga->packed_chain4 || (ht216->ht_regs[0xfc] & HT_REG_FC_ECOLRE)) { + ht216->read_bank_reg[0] |= (ht216->misc & 0x20); + ht216->read_bank_reg[1] |= (ht216->misc & 0x20); + ht216->write_bank_reg[0] |= (ht216->misc & 0x20); + ht216->write_bank_reg[1] |= (ht216->misc & 0x20); + } - if (svga->packed_chain4 || ((ht216->ht_regs[0xfc] & 0x06) == 0x04)) { - ht216->read_bank_reg[0] |= ((ht216->ht_regs[0xf9] & 1) << 4); - ht216->read_bank_reg[1] |= ((ht216->ht_regs[0xf9] & 1) << 4); - ht216->write_bank_reg[0] |= ((ht216->ht_regs[0xf9] & 1) << 4); - ht216->write_bank_reg[1] |= ((ht216->ht_regs[0xf9] & 1) << 4); - } + if (svga->packed_chain4 || ((ht216->ht_regs[0xfc] & 0x06) == 0x04)) { + ht216->read_bank_reg[0] |= ((ht216->ht_regs[0xf9] & 1) << 4); + ht216->read_bank_reg[1] |= ((ht216->ht_regs[0xf9] & 1) << 4); + ht216->write_bank_reg[0] |= ((ht216->ht_regs[0xf9] & 1) << 4); + ht216->write_bank_reg[1] |= ((ht216->ht_regs[0xf9] & 1) << 4); + } } } - void -ht216_out(uint16_t addr, uint8_t val, void *p) +ht216_out(uint16_t addr, uint8_t val, void *priv) { - ht216_t *ht216 = (ht216_t *)p; - svga_t *svga = &ht216->svga; - uint8_t old; + ht216_t *ht216 = (ht216_t *) priv; + svga_t *svga = &ht216->svga; + uint8_t old; ht216_log("ht216 %i out %04X %02X %04X:%04X\n", svga->miscout & 1, addr, val, CS, cpu_state.pc); if (((addr & 0xfff0) == 0x3d0 || (addr & 0xfff0) == 0x3b0) && !(svga->miscout & 1)) - addr ^= 0x60; + addr ^= 0x60; switch (addr) { - case 0x3c2: - /*Bit 17 of the display memory address, only active on odd/even modes, has no effect on graphics modes.*/ - ht216->misc = val; - svga->miscout = val; - ht216_log("HT216 misc val = %02x, mode = 0, chain4 = %x\n", val, svga->chain4); - ht216_recalc_bank_regs(ht216, 0); - ht216_remap(ht216); - svga_recalctimings(svga); - break; + case 0x3c2: + /*Bit 17 of the display memory address, only active on odd/even modes, has no effect on graphics modes.*/ + ht216->misc = val; + svga->miscout = val; + ht216_log("HT216 misc val = %02x, mode = 0, chain4 = %x\n", val, svga->chain4); + ht216_recalc_bank_regs(ht216, 0); + ht216_remap(ht216); + svga_recalctimings(svga); + break; - case 0x3c4: - svga->seqaddr = val; - break; + case 0x3c4: + svga->seqaddr = val; + break; - case 0x3c5: - if (svga->seqaddr == 4) { - svga->chain2_write = !(val & 4); - svga->chain4 = val & 8; - ht216_remap(ht216); - } else if (svga->seqaddr == 6) { - if (val == 0xea) - ht216->ext_reg_enable = 1; - else if (val == 0xae) - ht216->ext_reg_enable = 0; + case 0x3c5: + if (svga->seqaddr == 4) { + svga->chain2_write = !(val & 4); + svga->chain4 = val & 8; + ht216_remap(ht216); + } else if (svga->seqaddr == 6) { + if (val == 0xea) + ht216->ext_reg_enable = 1; + else if (val == 0xae) + ht216->ext_reg_enable = 0; #ifdef ENABLE_HT216_LOG - /* Functionality to output to the console a dump of all registers for debugging purposes. */ - } else if (svga->seqaddr == 0x7f) { - ht216_log(" 8 | 0 1 2 3 4 5 6 7 8 9 A B C D E F\n"); - ht216_log("----+-------------------------------------------------\n"); - ht216_log(" 8 | %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X\n", - ht216->ht_regs[0x80], ht216->ht_regs[0x81], ht216->ht_regs[0x82], ht216->ht_regs[0x83], - ht216->ht_regs[0x84], ht216->ht_regs[0x85], ht216->ht_regs[0x86], ht216->ht_regs[0x87], - ht216->ht_regs[0x88], ht216->ht_regs[0x89], ht216->ht_regs[0x8a], ht216->ht_regs[0x8b], - ht216->ht_regs[0x8c], ht216->ht_regs[0x8d], ht216->ht_regs[0x8e], ht216->ht_regs[0x8f]); - ht216_log(" 9 | %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X\n", - ht216->ht_regs[0x90], ht216->ht_regs[0x91], ht216->ht_regs[0x92], ht216->ht_regs[0x93], - ht216->ht_regs[0x94], ht216->ht_regs[0x95], ht216->ht_regs[0x96], ht216->ht_regs[0x97], - ht216->ht_regs[0x98], ht216->ht_regs[0x99], ht216->ht_regs[0x9a], ht216->ht_regs[0x9b], - ht216->ht_regs[0x9c], ht216->ht_regs[0x9d], ht216->ht_regs[0x9e], ht216->ht_regs[0x9f]); - ht216_log(" A | %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X\n", - ht216->ht_regs[0xa0], ht216->ht_regs[0xa1], ht216->ht_regs[0xa2], ht216->ht_regs[0xa3], - ht216->ht_regs[0xa4], ht216->ht_regs[0xa5], ht216->ht_regs[0xa6], ht216->ht_regs[0xa7], - ht216->ht_regs[0xa8], ht216->ht_regs[0xa9], ht216->ht_regs[0xaa], ht216->ht_regs[0xab], - ht216->ht_regs[0xac], ht216->ht_regs[0xad], ht216->ht_regs[0xae], ht216->ht_regs[0xaf]); - ht216_log(" B | %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X\n", - ht216->ht_regs[0xb0], ht216->ht_regs[0xb1], ht216->ht_regs[0xb2], ht216->ht_regs[0xb3], - ht216->ht_regs[0xb4], ht216->ht_regs[0xb5], ht216->ht_regs[0xb6], ht216->ht_regs[0xb7], - ht216->ht_regs[0xb8], ht216->ht_regs[0xb9], ht216->ht_regs[0xba], ht216->ht_regs[0xbb], - ht216->ht_regs[0xbc], ht216->ht_regs[0xbd], ht216->ht_regs[0xbe], ht216->ht_regs[0xbf]); - ht216_log(" C | %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X\n", - ht216->ht_regs[0xc0], ht216->ht_regs[0xc1], ht216->ht_regs[0xc2], ht216->ht_regs[0xc3], - ht216->ht_regs[0xc4], ht216->ht_regs[0xc5], ht216->ht_regs[0xc6], ht216->ht_regs[0xc7], - ht216->ht_regs[0xc8], ht216->ht_regs[0xc9], ht216->ht_regs[0xca], ht216->ht_regs[0xcb], - ht216->ht_regs[0xcc], ht216->ht_regs[0xcd], ht216->ht_regs[0xce], ht216->ht_regs[0xcf]); - ht216_log(" D | %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X\n", - ht216->ht_regs[0xd0], ht216->ht_regs[0xd1], ht216->ht_regs[0xd2], ht216->ht_regs[0xd3], - ht216->ht_regs[0xd4], ht216->ht_regs[0xd5], ht216->ht_regs[0xd6], ht216->ht_regs[0xd7], - ht216->ht_regs[0xd8], ht216->ht_regs[0xd9], ht216->ht_regs[0xda], ht216->ht_regs[0xdb], - ht216->ht_regs[0xdc], ht216->ht_regs[0xdd], ht216->ht_regs[0xde], ht216->ht_regs[0xdf]); - ht216_log(" E | %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X\n", - ht216->ht_regs[0xe0], ht216->ht_regs[0xe1], ht216->ht_regs[0xe2], ht216->ht_regs[0xe3], - ht216->ht_regs[0xe4], ht216->ht_regs[0xe5], ht216->ht_regs[0xe6], ht216->ht_regs[0xe7], - ht216->ht_regs[0xe8], ht216->ht_regs[0xe9], ht216->ht_regs[0xea], ht216->ht_regs[0xeb], - ht216->ht_regs[0xec], ht216->ht_regs[0xed], ht216->ht_regs[0xee], ht216->ht_regs[0xef]); - ht216_log(" F | %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X\n", - ht216->ht_regs[0xf0], ht216->ht_regs[0xf1], ht216->ht_regs[0xf2], ht216->ht_regs[0xf3], - ht216->ht_regs[0xf4], ht216->ht_regs[0xf5], ht216->ht_regs[0xf6], ht216->ht_regs[0xf7], - ht216->ht_regs[0xf8], ht216->ht_regs[0xf9], ht216->ht_regs[0xfa], ht216->ht_regs[0xfb], - ht216->ht_regs[0xfc], ht216->ht_regs[0xfd], ht216->ht_regs[0xfe], ht216->ht_regs[0xff]); - return; + /* Functionality to output to the console a dump of all registers for debugging purposes. */ + } else if (svga->seqaddr == 0x7f) { + ht216_log(" 8 | 0 1 2 3 4 5 6 7 8 9 A B C D E F\n"); + ht216_log("----+-------------------------------------------------\n"); + ht216_log(" 8 | %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X\n", + ht216->ht_regs[0x80], ht216->ht_regs[0x81], ht216->ht_regs[0x82], ht216->ht_regs[0x83], + ht216->ht_regs[0x84], ht216->ht_regs[0x85], ht216->ht_regs[0x86], ht216->ht_regs[0x87], + ht216->ht_regs[0x88], ht216->ht_regs[0x89], ht216->ht_regs[0x8a], ht216->ht_regs[0x8b], + ht216->ht_regs[0x8c], ht216->ht_regs[0x8d], ht216->ht_regs[0x8e], ht216->ht_regs[0x8f]); + ht216_log(" 9 | %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X\n", + ht216->ht_regs[0x90], ht216->ht_regs[0x91], ht216->ht_regs[0x92], ht216->ht_regs[0x93], + ht216->ht_regs[0x94], ht216->ht_regs[0x95], ht216->ht_regs[0x96], ht216->ht_regs[0x97], + ht216->ht_regs[0x98], ht216->ht_regs[0x99], ht216->ht_regs[0x9a], ht216->ht_regs[0x9b], + ht216->ht_regs[0x9c], ht216->ht_regs[0x9d], ht216->ht_regs[0x9e], ht216->ht_regs[0x9f]); + ht216_log(" A | %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X\n", + ht216->ht_regs[0xa0], ht216->ht_regs[0xa1], ht216->ht_regs[0xa2], ht216->ht_regs[0xa3], + ht216->ht_regs[0xa4], ht216->ht_regs[0xa5], ht216->ht_regs[0xa6], ht216->ht_regs[0xa7], + ht216->ht_regs[0xa8], ht216->ht_regs[0xa9], ht216->ht_regs[0xaa], ht216->ht_regs[0xab], + ht216->ht_regs[0xac], ht216->ht_regs[0xad], ht216->ht_regs[0xae], ht216->ht_regs[0xaf]); + ht216_log(" B | %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X\n", + ht216->ht_regs[0xb0], ht216->ht_regs[0xb1], ht216->ht_regs[0xb2], ht216->ht_regs[0xb3], + ht216->ht_regs[0xb4], ht216->ht_regs[0xb5], ht216->ht_regs[0xb6], ht216->ht_regs[0xb7], + ht216->ht_regs[0xb8], ht216->ht_regs[0xb9], ht216->ht_regs[0xba], ht216->ht_regs[0xbb], + ht216->ht_regs[0xbc], ht216->ht_regs[0xbd], ht216->ht_regs[0xbe], ht216->ht_regs[0xbf]); + ht216_log(" C | %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X\n", + ht216->ht_regs[0xc0], ht216->ht_regs[0xc1], ht216->ht_regs[0xc2], ht216->ht_regs[0xc3], + ht216->ht_regs[0xc4], ht216->ht_regs[0xc5], ht216->ht_regs[0xc6], ht216->ht_regs[0xc7], + ht216->ht_regs[0xc8], ht216->ht_regs[0xc9], ht216->ht_regs[0xca], ht216->ht_regs[0xcb], + ht216->ht_regs[0xcc], ht216->ht_regs[0xcd], ht216->ht_regs[0xce], ht216->ht_regs[0xcf]); + ht216_log(" D | %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X\n", + ht216->ht_regs[0xd0], ht216->ht_regs[0xd1], ht216->ht_regs[0xd2], ht216->ht_regs[0xd3], + ht216->ht_regs[0xd4], ht216->ht_regs[0xd5], ht216->ht_regs[0xd6], ht216->ht_regs[0xd7], + ht216->ht_regs[0xd8], ht216->ht_regs[0xd9], ht216->ht_regs[0xda], ht216->ht_regs[0xdb], + ht216->ht_regs[0xdc], ht216->ht_regs[0xdd], ht216->ht_regs[0xde], ht216->ht_regs[0xdf]); + ht216_log(" E | %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X\n", + ht216->ht_regs[0xe0], ht216->ht_regs[0xe1], ht216->ht_regs[0xe2], ht216->ht_regs[0xe3], + ht216->ht_regs[0xe4], ht216->ht_regs[0xe5], ht216->ht_regs[0xe6], ht216->ht_regs[0xe7], + ht216->ht_regs[0xe8], ht216->ht_regs[0xe9], ht216->ht_regs[0xea], ht216->ht_regs[0xeb], + ht216->ht_regs[0xec], ht216->ht_regs[0xed], ht216->ht_regs[0xee], ht216->ht_regs[0xef]); + ht216_log(" F | %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X\n", + ht216->ht_regs[0xf0], ht216->ht_regs[0xf1], ht216->ht_regs[0xf2], ht216->ht_regs[0xf3], + ht216->ht_regs[0xf4], ht216->ht_regs[0xf5], ht216->ht_regs[0xf6], ht216->ht_regs[0xf7], + ht216->ht_regs[0xf8], ht216->ht_regs[0xf9], ht216->ht_regs[0xfa], ht216->ht_regs[0xfb], + ht216->ht_regs[0xfc], ht216->ht_regs[0xfd], ht216->ht_regs[0xfe], ht216->ht_regs[0xff]); + return; #endif - } else if (svga->seqaddr >= 0x80 && ht216->ext_reg_enable) { - old = ht216->ht_regs[svga->seqaddr & 0xff]; - ht216->ht_regs[svga->seqaddr & 0xff] = val; + } else if (svga->seqaddr >= 0x80 && ht216->ext_reg_enable) { + old = ht216->ht_regs[svga->seqaddr & 0xff]; + ht216->ht_regs[svga->seqaddr & 0xff] = val; - switch (svga->seqaddr & 0xff) { - case 0x83: - svga->attraddr = val & 0x1f; - svga->attrff = !!(val & 0x80); - break; + switch (svga->seqaddr & 0xff) { + case 0x83: + svga->attraddr = val & 0x1f; + svga->attrff = !!(val & 0x80); + break; - case 0x94: - case 0xff: - svga->hwcursor.addr = ((ht216->ht_regs[0x94] << 6) | 0xc000 | ((ht216->ht_regs[0xff] & 0x60) << 11)) << 2; - svga->hwcursor.addr &= svga->vram_mask; - if (svga->crtc[0x17] == 0xeb) /*Looks like that 1024x768 mono mode expects 512K of video memory*/ - svga->hwcursor.addr += 0x40000; - break; - case 0x9c: case 0x9d: - svga->hwcursor.x = ht216->ht_regs[0x9d] | ((ht216->ht_regs[0x9c] & 7) << 8); - break; - case 0x9e: case 0x9f: - svga->hwcursor.y = ht216->ht_regs[0x9f] | ((ht216->ht_regs[0x9e] & 3) << 8); - break; + case 0x94: + case 0xff: + svga->hwcursor.addr = ((ht216->ht_regs[0x94] << 6) | 0xc000 | ((ht216->ht_regs[0xff] & 0x60) << 11)) << 2; + svga->hwcursor.addr &= svga->vram_mask; + if (svga->crtc[0x17] == 0xeb) /*Looks like that 1024x768 mono mode expects 512K of video memory*/ + svga->hwcursor.addr += 0x40000; + break; + case 0x9c: + case 0x9d: + svga->hwcursor.x = ht216->ht_regs[0x9d] | ((ht216->ht_regs[0x9c] & 7) << 8); + break; + case 0x9e: + case 0x9f: + svga->hwcursor.y = ht216->ht_regs[0x9f] | ((ht216->ht_regs[0x9e] & 3) << 8); + break; - case 0xa0: - svga->latch.b[0] = val; - break; - case 0xa1: - svga->latch.b[1] = val; - break; - case 0xa2: - svga->latch.b[2] = val; - break; - case 0xa3: - svga->latch.b[3] = val; - break; + case 0xa0: + svga->latch.b[0] = val; + break; + case 0xa1: + svga->latch.b[1] = val; + break; + case 0xa2: + svga->latch.b[2] = val; + break; + case 0xa3: + svga->latch.b[3] = val; + break; - case 0xa4: - case 0xf8: - svga->fullchange = changeframecount; - svga_recalctimings(svga); - break; + case 0xa4: + case 0xf8: + svga->fullchange = changeframecount; + svga_recalctimings(svga); + break; - case 0xa5: - svga->hwcursor.ena = !!(val & 0x80); - break; + case 0xa5: + svga->hwcursor.ena = !!(val & 0x80); + break; - case 0xc0: - break; + case 0xc0: + break; - case 0xc1: - break; + case 0xc1: + break; - case 0xc8: - if ((old ^ val) & HT_REG_C8_E256) { - svga->fullchange = changeframecount; - svga_recalctimings(svga); - } - ht216_remap(ht216); - break; + case 0xc8: + if ((old ^ val) & HT_REG_C8_E256) { + svga->fullchange = changeframecount; + svga_recalctimings(svga); + } + ht216_remap(ht216); + break; - case 0xc9: case 0xcf: - ht216_remap(ht216); - break; + case 0xc9: + case 0xcf: + ht216_remap(ht216); + break; - case 0xe0: - svga->adv_flags &= ~FLAG_RAMDAC_SHIFT; - if (val & 0x04) - svga->adv_flags |= FLAG_RAMDAC_SHIFT; - /* FALLTHROUGH */ - /*Bank registers*/ - case 0xe8: case 0xe9: - ht216_log("HT216 reg 0x%02x write = %02x, mode = 1, chain4 = %x\n", svga->seqaddr & 0xff, val, svga->chain4); - ht216_recalc_bank_regs(ht216, 1); - ht216_remap(ht216); - break; - - case 0xec: - ht216->fg_latch[0] = val; - break; - case 0xed: - ht216->fg_latch[1] = val; - break; - case 0xee: - ht216->fg_latch[2] = val; - break; - case 0xef: - ht216->fg_latch[3] = val; - break; + case 0xe0: + svga->adv_flags &= ~FLAG_RAMDAC_SHIFT; + if (val & 0x04) + svga->adv_flags |= FLAG_RAMDAC_SHIFT; + fallthrough; + /*Bank registers*/ + case 0xe8: + case 0xe9: + ht216_log("HT216 reg 0x%02x write = %02x, mode = 1, chain4 = %x\n", svga->seqaddr & 0xff, val, svga->chain4); + ht216_recalc_bank_regs(ht216, 1); + ht216_remap(ht216); + break; - case 0xf0: - ht216->fg_latch[ht216->fg_plane_sel] = val; - ht216->fg_plane_sel = (ht216->fg_plane_sel + 1) & 3; - break; - - case 0xf1: - ht216->bg_plane_sel = val & 3; - ht216->fg_plane_sel = (val & 0x30) >> 4; - break; - - case 0xf2: - svga->latch.b[ht216->bg_plane_sel] = val; - ht216->bg_plane_sel = (ht216->bg_plane_sel + 1) & 3; - break; + case 0xec: + ht216->fg_latch[0] = val; + break; + case 0xed: + ht216->fg_latch[1] = val; + break; + case 0xee: + ht216->fg_latch[2] = val; + break; + case 0xef: + ht216->fg_latch[3] = val; + break; - case 0xf6: - /*Bits 18 and 19 of the display memory address*/ - ht216_log("HT216 reg 0xf6 write = %02x, mode = 0, chain4 = %x, vram mask = %08x, cr17 = %02x\n", val, svga->chain4, svga->vram_display_mask, svga->crtc[0x17]); - ht216_recalc_bank_regs(ht216, 0); - ht216_remap(ht216); - svga->fullchange = changeframecount; - svga_recalctimings(svga); - break; - - case 0xf9: - /*Bit 16 of the display memory address, only active when in chain4 mode and 256 color mode.*/ - ht216_log("HT216 reg 0xf9 write = %02x, mode = 0, chain4 = %x\n", val & HT_REG_F9_XPSEL, svga->chain4); - ht216_recalc_bank_regs(ht216, 0); - ht216_remap(ht216); - break; - - case 0xfc: - ht216_log("HT216 reg 0xfc write = %02x, mode = 0, chain4 = %x, bit 7 = %02x, packedchain = %02x\n", val, svga->chain4, val & 0x80, val & 0x20); - svga->packed_chain4 = !!(val & 0x20); - ht216_recalc_bank_regs(ht216, 0); - ht216_remap(ht216); - svga->fullchange = changeframecount; - svga_recalctimings(svga); - break; - } - return; - } - break; + case 0xf0: + ht216->fg_latch[ht216->fg_plane_sel] = val; + ht216->fg_plane_sel = (ht216->fg_plane_sel + 1) & 3; + break; - case 0x3c6: case 0x3c7: case 0x3c8: case 0x3c9: - if (ht216->id == 0x7152) - sc1148x_ramdac_out(addr, 0, val, svga->ramdac, svga); - else - svga_out(addr, val, svga); - return; + case 0xf1: + ht216->bg_plane_sel = val & 3; + ht216->fg_plane_sel = (val & 0x30) >> 4; + break; - case 0x3cb: - if (ht216->id == 0x7152) { - ht216->reg_3cb = val; - svga_set_ramdac_type(svga, (val & 0x20) ? RAMDAC_6BIT : RAMDAC_8BIT); - } - break; + case 0xf2: + svga->latch.b[ht216->bg_plane_sel] = val; + ht216->bg_plane_sel = (ht216->bg_plane_sel + 1) & 3; + break; - case 0x3cf: - if (svga->gdcaddr == 5) { - svga->chain2_read = val & 0x10; - ht216_remap(ht216); - } else if (svga->gdcaddr == 6) { - if (val & 8) - svga->banked_mask = 0x7fff; - else - svga->banked_mask = 0xffff; - } + case 0xf6: + /*Bits 18 and 19 of the display memory address*/ + ht216_log("HT216 reg 0xf6 write = %02x, mode = 0, chain4 = %x, vram mask = %08x, cr17 = %02x\n", val, svga->chain4, svga->vram_display_mask, svga->crtc[0x17]); + ht216_recalc_bank_regs(ht216, 0); + ht216_remap(ht216); + svga->fullchange = changeframecount; + svga_recalctimings(svga); + break; - if (svga->gdcaddr <= 8) { - svga->fast = (svga->gdcreg[8] == 0xff && !(svga->gdcreg[3] & 0x18) && - !svga->gdcreg[1]) && svga->chain4 && svga->packed_chain4; - } - break; + case 0xf9: + /*Bit 16 of the display memory address, only active when in chain4 mode and 256 color mode.*/ + ht216_log("HT216 reg 0xf9 write = %02x, mode = 0, chain4 = %x\n", val & HT_REG_F9_XPSEL, svga->chain4); + ht216_recalc_bank_regs(ht216, 0); + ht216_remap(ht216); + 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); + case 0xfc: + ht216_log("HT216 reg 0xfc write = %02x, mode = 0, chain4 = %x, bit 7 = %02x, packedchain = %02x\n", val, svga->chain4, val & 0x80, val & 0x20); + svga->packed_chain4 = !!(val & 0x20); + ht216_recalc_bank_regs(ht216, 0); + ht216_remap(ht216); + svga->fullchange = changeframecount; + svga_recalctimings(svga); + break; - old = svga->crtc[svga->crtcreg]; - svga->crtc[svga->crtcreg] = val; + default: + break; + } + return; + } + break; - 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; + case 0x3c6: + case 0x3c7: + case 0x3c8: + case 0x3c9: + if (ht216->id == 0x7152) + sc1148x_ramdac_out(addr, 0, val, svga->ramdac, svga); + else + svga_out(addr, val, svga); + return; - case 0x46e8: - if ((ht216->id == 0x7152) && ht216->isabus) - io_removehandler(0x0105, 0x0001, ht216_in, NULL, NULL, ht216_out, NULL, NULL, ht216); - io_removehandler(0x03c0, 0x0020, ht216_in, NULL, NULL, ht216_out, NULL, NULL, ht216); - mem_mapping_disable(&svga->mapping); - mem_mapping_disable(&ht216->linear_mapping); - if (val & 8) { - if ((ht216->id == 0x7152) && ht216->isabus) - io_sethandler(0x0105, 0x0001, ht216_in, NULL, NULL, ht216_out, NULL, NULL, ht216); - io_sethandler(0x03c0, 0x0020, ht216_in, NULL, NULL, ht216_out, NULL, NULL, ht216); - mem_mapping_enable(&svga->mapping); - ht216_remap(ht216); - } - break; + case 0x3cb: + if (ht216->id == 0x7152) { + ht216->reg_3cb = val; + svga_set_ramdac_type(svga, (val & 0x20) ? RAMDAC_6BIT : RAMDAC_8BIT); + } + break; + + case 0x3cf: + if (svga->gdcaddr == 5) { + svga->chain2_read = val & 0x10; + ht216_remap(ht216); + } else if (svga->gdcaddr == 6) { + if (val & 8) + svga->banked_mask = 0x7fff; + else + svga->banked_mask = 0xffff; + } + + if (svga->gdcaddr <= 8) { + svga->fast = (svga->gdcreg[8] == 0xff && !(svga->gdcreg[3] & 0x18) && !svga->gdcreg[1]) && svga->chain4 && svga->packed_chain4; + } + 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; + + case 0x46e8: + if ((ht216->id == 0x7152) && ht216->isabus) + io_removehandler(0x0105, 0x0001, ht216_in, NULL, NULL, ht216_out, NULL, NULL, ht216); + io_removehandler(0x03c0, 0x0020, ht216_in, NULL, NULL, ht216_out, NULL, NULL, ht216); + mem_mapping_disable(&svga->mapping); + mem_mapping_disable(&ht216->linear_mapping); + if (val & 8) { + if ((ht216->id == 0x7152) && ht216->isabus) + io_sethandler(0x0105, 0x0001, ht216_in, NULL, NULL, ht216_out, NULL, NULL, ht216); + io_sethandler(0x03c0, 0x0020, ht216_in, NULL, NULL, ht216_out, NULL, NULL, ht216); + mem_mapping_enable(&svga->mapping); + ht216_remap(ht216); + } + break; + + default: + break; } svga_out(addr, val, svga); } - uint8_t -ht216_in(uint16_t addr, void *p) +ht216_in(uint16_t addr, void *priv) { - ht216_t *ht216 = (ht216_t *)p; - svga_t *svga = &ht216->svga; - uint8_t ret = 0xff; + ht216_t *ht216 = (ht216_t *) priv; + svga_t *svga = &ht216->svga; + uint8_t ret = 0xff; if (((addr & 0xfff0) == 0x3d0 || (addr & 0xfff0) == 0x3b0) && !(svga->miscout & 1)) - addr ^= 0x60; + addr ^= 0x60; if ((ht216->id == 0x7152) && ht216->isabus) { - if (addr == 0x105) - return ht216->extensions; + if (addr == 0x105) + return ht216->extensions; } switch (addr) { - case 0x3c4: - return svga->seqaddr; + case 0x3c4: + return svga->seqaddr; - case 0x3c5: - if (svga->seqaddr == 6) - return ht216->ext_reg_enable; - else if (svga->seqaddr >= 0x80) { - if (ht216->ext_reg_enable) { - ret = ht216->ht_regs[svga->seqaddr & 0xff]; + case 0x3c5: + if (svga->seqaddr == 6) + return ht216->ext_reg_enable; + else if (svga->seqaddr >= 0x80) { + if (ht216->ext_reg_enable) { + ret = ht216->ht_regs[svga->seqaddr & 0xff]; - switch (svga->seqaddr & 0xff) { - case 0x83: - if (svga->attrff) - ret = svga->attraddr | 0x80; - else - ret = svga->attraddr; - break; + switch (svga->seqaddr & 0xff) { + case 0x83: + if (svga->attrff) + ret = svga->attraddr | 0x80; + else + ret = svga->attraddr; + break; - case 0x8e: - ret = ht216->id & 0xff; - break; - case 0x8f: - ret = (ht216->id >> 8) & 0xff; - break; + case 0x8e: + ret = ht216->id & 0xff; + break; + case 0x8f: + ret = (ht216->id >> 8) & 0xff; + break; - case 0xa0: - ret = svga->latch.b[0]; - break; - case 0xa1: - ret = svga->latch.b[1]; - break; - case 0xa2: - ret = svga->latch.b[2]; - break; - case 0xa3: - ret = svga->latch.b[3]; - break; + case 0xa0: + ret = svga->latch.b[0]; + break; + case 0xa1: + ret = svga->latch.b[1]; + break; + case 0xa2: + ret = svga->latch.b[2]; + break; + case 0xa3: + ret = svga->latch.b[3]; + break; - case 0xf0: - ret = ht216->fg_latch[ht216->fg_plane_sel]; - ht216->fg_plane_sel = 0; - break; - - case 0xf2: - ret = svga->latch.b[ht216->bg_plane_sel]; - ht216->bg_plane_sel = 0; - break; - } + case 0xf0: + ret = ht216->fg_latch[ht216->fg_plane_sel]; + ht216->fg_plane_sel = 0; + break; - return ret; - } else - return 0xff; - } - break; + case 0xf2: + ret = svga->latch.b[ht216->bg_plane_sel]; + ht216->bg_plane_sel = 0; + break; - case 0x3c6: case 0x3c7: case 0x3c8: case 0x3c9: - if (ht216->id == 0x7152) - return sc1148x_ramdac_in(addr, 0, svga->ramdac, svga); - return svga_in(addr, svga); + default: + break; + } - case 0x3cb: - if (ht216->id == 0x7152) - return ht216->reg_3cb; - break; + return ret; + } else + return 0xff; + } + break; - case 0x3cc: - return svga->miscout; + case 0x3c6: + case 0x3c7: + case 0x3c8: + case 0x3c9: + if (ht216->id == 0x7152) + return sc1148x_ramdac_in(addr, 0, svga->ramdac, svga); + return svga_in(addr, svga); - case 0x3D4: - return svga->crtcreg; - case 0x3D5: - if (svga->crtcreg == 0x1f) - return svga->crtc[0xc] ^ 0xea; - return svga->crtc[svga->crtcreg]; + case 0x3cb: + if (ht216->id == 0x7152) + return ht216->reg_3cb; + break; + + case 0x3cc: + return svga->miscout; + + case 0x3D4: + return svga->crtcreg; + case 0x3D5: + if (svga->crtcreg == 0x1f) + return svga->crtc[0xc] ^ 0xea; + return svga->crtc[svga->crtcreg]; + + default: + break; } return svga_in(addr, svga); @@ -565,204 +581,226 @@ ht216_remap(ht216_t *ht216) mem_mapping_disable(&ht216->linear_mapping); if (ht216->ht_regs[0xc8] & HT_REG_C8_XLAM) { - /*Linear mapping enabled*/ - ht216_log("Linear mapping enabled\n"); - ht216->linear_base = ((ht216->ht_regs[0xc9] & 0xf) << 20) | (ht216->ht_regs[0xcf] << 24); - mem_mapping_disable(&svga->mapping); - mem_mapping_set_addr(&ht216->linear_mapping, ht216->linear_base, 0x100000); + /*Linear mapping enabled*/ + ht216_log("Linear mapping enabled\n"); + ht216->linear_base = ((ht216->ht_regs[0xc9] & 0xf) << 20) | (ht216->ht_regs[0xcf] << 24); + mem_mapping_disable(&svga->mapping); + mem_mapping_set_addr(&ht216->linear_mapping, ht216->linear_base, 0x100000); } - ht216->read_banks[0] = ht216->read_bank_reg[0] << 12; + ht216->read_banks[0] = ht216->read_bank_reg[0] << 12; ht216->write_banks[0] = ht216->write_bank_reg[0] << 12; /* Split bank: two banks used */ if (ht216->ht_regs[0xe0] & HT_REG_E0_SBAE) { - ht216->read_banks[1] = ht216->read_bank_reg[1] << 12; - ht216->write_banks[1] = ht216->write_bank_reg[1] << 12; + ht216->read_banks[1] = ht216->read_bank_reg[1] << 12; + ht216->write_banks[1] = ht216->write_bank_reg[1] << 12; } if (!svga->chain4) { - ht216->read_banks[0] = ((ht216->read_banks[0] & 0xc0000) >> 2) | (ht216->read_banks[0] & 0xffff); - ht216->read_banks[1] = ((ht216->read_banks[1] & 0xc0000) >> 2) | (ht216->read_banks[1] & 0xffff); - ht216->write_banks[0] = ((ht216->write_banks[0] & 0xc0000) >> 2) | (ht216->write_banks[0] & 0xffff); - ht216->write_banks[1] = ((ht216->write_banks[1] & 0xc0000) >> 2) | (ht216->write_banks[1] & 0xffff); + ht216->read_banks[0] = ((ht216->read_banks[0] & 0xc0000) >> 2) | (ht216->read_banks[0] & 0xffff); + ht216->read_banks[1] = ((ht216->read_banks[1] & 0xc0000) >> 2) | (ht216->read_banks[1] & 0xffff); + ht216->write_banks[0] = ((ht216->write_banks[0] & 0xc0000) >> 2) | (ht216->write_banks[0] & 0xffff); + ht216->write_banks[1] = ((ht216->write_banks[1] & 0xc0000) >> 2) | (ht216->write_banks[1] & 0xffff); } if (!(ht216->ht_regs[0xe0] & HT_REG_E0_SBAE)) { - ht216->read_banks[1] = ht216->read_banks[0] + 0x8000; - ht216->write_banks[1] = ht216->write_banks[0] + 0x8000; + ht216->read_banks[1] = ht216->read_banks[0] + 0x8000; + ht216->write_banks[1] = ht216->write_banks[0] + 0x8000; } #ifdef ENABLE_HT216_LOG ht216_log("Registers: %02X, %02X, %02X, %02X, %02X\n", ht216->misc, ht216->ht_regs[0xe8], ht216->ht_regs[0xe9], - ht216->ht_regs[0xf6], ht216->ht_regs[0xf9]); + ht216->ht_regs[0xf6], ht216->ht_regs[0xf9]); ht216_log("Banks: %08X, %08X, %08X, %08X\n", ht216->read_banks[0], ht216->read_banks[1], - ht216->write_banks[0], ht216->write_banks[1]); + ht216->write_banks[0], ht216->write_banks[1]); #endif } - void ht216_recalctimings(svga_t *svga) { - ht216_t *ht216 = (ht216_t *)svga->p; - int high_res_256 = 0; - - switch ((((((svga->miscout >> 2) & 3) || ((ht216->ht_regs[0xa4] >> 2) & 3)) | - ((ht216->ht_regs[0xa4] >> 2) & 4)) || ((ht216->ht_regs[0xf8] >> 5) & 0x0f)) | - ((ht216->ht_regs[0xf8] << 1) & 8)) { - case 0: - case 1: - break; - case 4: - svga->clock = (cpuclock * (double)(1ull << 32)) / 50350000.0; - break; - case 5: - svga->clock = (cpuclock * (double)(1ull << 32)) / 65000000.0; - break; - case 7: - svga->clock = (cpuclock * (double)(1ull << 32)) / 40000000.0; - break; - default: - svga->clock = (cpuclock * (double)(1ull << 32)) / 36000000.0; - break; - } + ht216_t *ht216 = (ht216_t *) svga->priv; + int high_res_256 = 0; + + switch ((((((svga->miscout >> 2) & 3) || ((ht216->ht_regs[0xa4] >> 2) & 3)) | ((ht216->ht_regs[0xa4] >> 2) & 4)) || ((ht216->ht_regs[0xf8] >> 5) & 0x0f)) | ((ht216->ht_regs[0xf8] << 1) & 8)) { + case 0: + case 1: + break; + case 4: + svga->clock = (cpuclock * (double) (1ULL << 32)) / 50350000.0; + break; + case 5: + svga->clock = (cpuclock * (double) (1ULL << 32)) / 65000000.0; + break; + case 7: + svga->clock = (cpuclock * (double) (1ULL << 32)) / 40000000.0; + break; + default: + svga->clock = (cpuclock * (double) (1ULL << 32)) / 36000000.0; + break; + } svga->ma_latch |= ((ht216->ht_regs[0xf6] & 0x30) << 12); svga->interlace = ht216->ht_regs[0xe0] & 1; if (svga->interlace) - high_res_256 = (svga->htotal * 8) > (svga->vtotal * 4); + high_res_256 = (svga->htotal * 8) > (svga->vtotal * 4); else - high_res_256 = (svga->htotal * 8) > (svga->vtotal * 2); + high_res_256 = (svga->htotal * 8) > (svga->vtotal * 2); ht216->adjust_cursor = 0; - - if (!svga->scrblank && svga->attr_palette_enable) { - if (!(svga->gdcreg[6] & 1) && !(svga->attrregs[0x10] & 1)) { /*Text mode*/ - if (svga->seqregs[1] & 8) /*40 column*/ { - svga->render = svga_render_text_40; - } else { - svga->render = svga_render_text_80; - } - } else { - if (svga->crtc[0x17] == 0xeb) { - svga->rowoffset <<= 1; - svga->render = svga_render_2bpp_headland_highres; - } - if (svga->bpp == 8) { - ht216_log("regC8 = %02x, gdcreg5 bit 6 = %02x, no lowres = %02x, regf8 bit 7 = %02x, regfc = %02x\n", ht216->ht_regs[0xc8] & HT_REG_C8_E256, svga->gdcreg[5] & 0x40, !svga->lowres, ht216->ht_regs[0xf6] & 0x80, ht216->ht_regs[0xfc] & HT_REG_FC_ECOLRE); - if (((ht216->ht_regs[0xc8] & HT_REG_C8_E256) || (svga->gdcreg[5] & 0x40)) && (!svga->lowres || (ht216->ht_regs[0xf6] & 0x80))) { - if (high_res_256) { - svga->hdisp >>= 1; - ht216->adjust_cursor = 1; - } - svga->render = svga_render_8bpp_highres; - } else if (svga->lowres) { - if (high_res_256) { - svga->hdisp >>= 1; - ht216->adjust_cursor = 1; - svga->render = svga_render_8bpp_highres; - } else { - ht216_log("8bpp low, packed = %02x, chain4 = %02x\n", svga->packed_chain4, svga->chain4); - svga->render = svga_render_8bpp_lowres; - } - } else if (ht216->ht_regs[0xfc] & HT_REG_FC_ECOLRE) { - if (ht216->id == 0x7152) { - svga->hdisp = svga->crtc[1] - ((svga->crtc[5] & 0x60) >> 5); - if (!(svga->crtc[1] & 1)) - svga->hdisp--; - svga->hdisp++; - svga->hdisp *= (svga->seqregs[1] & 8) ? 16 : 8; - svga->rowoffset <<= 1; - if ((svga->crtc[0x17] & 0x60) == 0x20) /*Would result in a garbled screen with trailing cursor glitches*/ - svga->crtc[0x17] |= 0x40; - } - svga->render = svga_render_8bpp_highres; - } - } else if (svga->bpp == 15) { - svga->rowoffset <<= 1; - svga->hdisp >>= 1; - if ((svga->crtc[0x17] & 0x60) == 0x20) /*Would result in a garbled screen with trailing cursor glitches*/ - svga->crtc[0x17] |= 0x40; - svga->render = svga_render_15bpp_highres; - } - } - } - - svga->ma_latch |= ((ht216->ht_regs[0xf6] & 0x30) << 14); + if (!svga->scrblank && svga->attr_palette_enable) { + if (!(svga->gdcreg[6] & 1) && !(svga->attrregs[0x10] & 1)) { /*Text mode*/ + if (svga->seqregs[1] & 8) /*40 column*/ { + svga->render = svga_render_text_40; + } else { + svga->render = svga_render_text_80; + } + } else { + if (svga->crtc[0x17] == 0xeb) { + svga->rowoffset <<= 1; + svga->render = svga_render_2bpp_headland_highres; + } + + if (svga->bpp == 8) { + ht216_log("regC8 = %02x, gdcreg5 bit 6 = %02x, no lowres = %02x, regf8 bit 7 = %02x, regfc = %02x\n", ht216->ht_regs[0xc8] & HT_REG_C8_E256, svga->gdcreg[5] & 0x40, !svga->lowres, ht216->ht_regs[0xf6] & 0x80, ht216->ht_regs[0xfc] & HT_REG_FC_ECOLRE); + if (((ht216->ht_regs[0xc8] & HT_REG_C8_E256) || (svga->gdcreg[5] & 0x40)) && (!svga->lowres || (ht216->ht_regs[0xf6] & 0x80))) { + if (high_res_256) { + svga->hdisp >>= 1; + ht216->adjust_cursor = 1; + } + svga->render = svga_render_8bpp_highres; + } else if (svga->lowres) { + if (high_res_256) { + svga->hdisp >>= 1; + ht216->adjust_cursor = 1; + svga->render = svga_render_8bpp_highres; + } else { + ht216_log("8bpp low, packed = %02x, chain4 = %02x\n", svga->packed_chain4, svga->chain4); + svga->render = svga_render_8bpp_lowres; + } + } else if (ht216->ht_regs[0xfc] & HT_REG_FC_ECOLRE) { + if (ht216->id == 0x7152) { + svga->hdisp = svga->crtc[1] - ((svga->crtc[5] & 0x60) >> 5); + if (!(svga->crtc[1] & 1)) + svga->hdisp--; + svga->hdisp++; + svga->hdisp *= (svga->seqregs[1] & 8) ? 16 : 8; + svga->rowoffset <<= 1; + if ((svga->crtc[0x17] & 0x60) == 0x20) /*Would result in a garbled screen with trailing cursor glitches*/ + svga->crtc[0x17] |= 0x40; + } + svga->render = svga_render_8bpp_highres; + } + } else if (svga->bpp == 15) { + svga->rowoffset <<= 1; + svga->hdisp >>= 1; + if ((svga->crtc[0x17] & 0x60) == 0x20) /*Would result in a garbled screen with trailing cursor glitches*/ + svga->crtc[0x17] |= 0x40; + svga->render = svga_render_15bpp_highres; + } + } + } + + svga->ma_latch |= ((ht216->ht_regs[0xf6] & 0x30) << 14); if (svga->crtc[0x17] == 0xeb) /*Looks like 1024x768 mono mode expects 512K of video memory*/ - svga->vram_display_mask = 0x7ffff; + svga->vram_display_mask = 0x7ffff; else - svga->vram_display_mask = (ht216->ht_regs[0xf6] & 0x40) ? ht216->vram_mask : 0x3ffff; + svga->vram_display_mask = (ht216->ht_regs[0xf6] & 0x40) ? ht216->vram_mask : 0x3ffff; } - static void ht216_hwcursor_draw(svga_t *svga, int displine) { - ht216_t *ht216 = (ht216_t *)svga->p; - int x, shift = (ht216->adjust_cursor ? 2 : 1); - uint32_t dat[2]; - int offset = svga->hwcursor_latch.x + svga->hwcursor_latch.xoff; - int width = (ht216->adjust_cursor ? 16 : 32); + const ht216_t *ht216 = (ht216_t *) svga->priv; + int shift = (ht216->adjust_cursor ? 2 : 1); + uint32_t dat[2]; + int offset = svga->hwcursor_latch.x + svga->hwcursor_latch.xoff; + int width = (ht216->adjust_cursor ? 16 : 32); if (ht216->adjust_cursor) - offset >>= 1; + offset >>= 1; if (svga->interlace && svga->hwcursor_oddeven) - svga->hwcursor_latch.addr += 4; + svga->hwcursor_latch.addr += 4; - dat[0] = (svga->vram[svga->hwcursor_latch.addr] << 24) | - (svga->vram[svga->hwcursor_latch.addr+1] << 16) | - (svga->vram[svga->hwcursor_latch.addr+2] << 8) | - svga->vram[svga->hwcursor_latch.addr+3]; - dat[1] = (svga->vram[svga->hwcursor_latch.addr+128] << 24) | - (svga->vram[svga->hwcursor_latch.addr+128+1] << 16) | - (svga->vram[svga->hwcursor_latch.addr+128+2] << 8) | - svga->vram[svga->hwcursor_latch.addr+128+3]; + dat[0] = (svga->vram[svga->hwcursor_latch.addr] << 24) | (svga->vram[svga->hwcursor_latch.addr + 1] << 16) | (svga->vram[svga->hwcursor_latch.addr + 2] << 8) | svga->vram[svga->hwcursor_latch.addr + 3]; + dat[1] = (svga->vram[svga->hwcursor_latch.addr + 128] << 24) | (svga->vram[svga->hwcursor_latch.addr + 128 + 1] << 16) | (svga->vram[svga->hwcursor_latch.addr + 128 + 2] << 8) | svga->vram[svga->hwcursor_latch.addr + 128 + 3]; - for (x = 0; x < width; x++) { - if (!(dat[0] & 0x80000000)) - ((uint32_t *)buffer32->line[displine])[svga->x_add + offset + x] = 0; - if (dat[1] & 0x80000000) - ((uint32_t *)buffer32->line[displine])[svga->x_add + offset + x] ^= 0xffffff; + for (int x = 0; x < width; x++) { + if (!(dat[0] & 0x80000000)) + (buffer32->line[displine])[svga->x_add + offset + x] = 0; + if (dat[1] & 0x80000000) + (buffer32->line[displine])[svga->x_add + offset + x] ^= 0xffffff; - dat[0] <<= shift; - dat[1] <<= shift; + dat[0] <<= shift; + dat[1] <<= shift; } svga->hwcursor_latch.addr += 4; if (svga->interlace && !svga->hwcursor_oddeven) - svga->hwcursor_latch.addr += 4; + svga->hwcursor_latch.addr += 4; } - static __inline uint8_t extalu(int op, uint8_t input_a, uint8_t input_b) { uint8_t val; switch (op) { - case 0x0: val = 0; break; - case 0x1: val = ~(input_a | input_b); break; - case 0x2: val = input_a & ~input_b; break; - case 0x3: val = ~input_b; break; - case 0x4: val = ~input_a & input_b; break; - case 0x5: val = ~input_a; break; - case 0x6: val = input_a ^ input_b; break; - case 0x7: val = ~(input_a & input_b); break; - case 0x8: val = input_a & input_b; break; - case 0x9: val = ~(input_a ^ input_b); break; - case 0xa: val = input_a; break; - case 0xb: val = input_a | ~input_b; break; - case 0xc: val = input_b; break; - case 0xd: val = ~input_a | input_b; break; - case 0xe: val = input_a | input_b; break; - case 0xf: default: val = 0xff; break; + case 0x0: + val = 0; + break; + case 0x1: + val = ~(input_a | input_b); + break; + case 0x2: + val = input_a & ~input_b; + break; + case 0x3: + val = ~input_b; + break; + case 0x4: + val = ~input_a & input_b; + break; + case 0x5: + val = ~input_a; + break; + case 0x6: + val = input_a ^ input_b; + break; + case 0x7: + val = ~(input_a & input_b); + break; + case 0x8: + val = input_a & input_b; + break; + case 0x9: + val = ~(input_a ^ input_b); + break; + case 0xa: + val = input_a; + break; + case 0xb: + val = input_a | ~input_b; + break; + case 0xc: + val = input_b; + break; + case 0xd: + val = ~input_a | input_b; + break; + case 0xe: + val = input_a | input_b; + break; + case 0xf: + default: + val = 0xff; + break; } return val; @@ -771,180 +809,191 @@ extalu(int op, uint8_t input_a, uint8_t input_b) static void ht216_dm_write(ht216_t *ht216, uint32_t addr, uint8_t cpu_dat, uint8_t cpu_dat_unexpanded) { - svga_t *svga = &ht216->svga; - int writemask2 = svga->writemask, reset_wm = 0; + svga_t *svga = &ht216->svga; + int writemask2 = svga->writemask; + int reset_wm = 0; latch_t vall; - uint8_t i, wm = svga->writemask; - uint8_t count = 4, fg_data[8] = {0, 0, 0, 0, 0, 0, 0, 0}; + uint8_t i; + uint8_t wm = svga->writemask; + uint8_t count = 4; + uint8_t fg_data[8] = { 0, 0, 0, 0, 0, 0, 0, 0 }; if (ht216->ht_regs[0xcd] & HT_REG_CD_P8PCEXP) - writemask2 = svga->seqregs[2]; + writemask2 = svga->seqregs[2]; if (!(svga->gdcreg[6] & 1)) - svga->fullchange = 2; + svga->fullchange = 2; - if (svga->chain4) { - writemask2 = 1 << (addr & 3); - addr = dword_remap(svga, addr) & ~3; - } else if (svga->chain2_write && (svga->crtc[0x17] != 0xeb)) { - writemask2 &= ~0xa; - if (addr & 1) - writemask2 <<= 1; - addr &= ~1; - addr <<= 2; + if (svga->chain4) { + writemask2 = 1 << (addr & 3); + addr = dword_remap(svga, addr) & ~3; + } else if (svga->chain2_write && (svga->crtc[0x17] != 0xeb)) { + writemask2 &= ~0xa; + if (addr & 1) + writemask2 <<= 1; + addr &= ~1; + addr <<= 2; } else - addr <<= 2; + addr <<= 2; if (addr >= svga->vram_max) - return; + return; svga->changedvram[addr >> 12] = changeframecount; if (ht216->ht_regs[0xcd] & HT_REG_CD_P8PCEXP) - count = 8; + count = 8; switch (ht216->ht_regs[0xfe] & HT_REG_FE_FBMC) { - case 0x00: - for (i = 0; i < count; i++) - fg_data[i] = cpu_dat; - break; - case 0x04: - if (ht216->ht_regs[0xfe] & HT_REG_FE_FBRC) { - for (i = 0; i < count; i++) { - if (ht216->ht_regs[0xfa] & (1 << i)) - fg_data[i] = cpu_dat_unexpanded; - else if (ht216->ht_regs[0xfb] & (1 << i)) - fg_data[i] = 0xff - cpu_dat_unexpanded; - } - } else { - for (i = 0; i < count; i++) { - if (ht216->ht_regs[0xfa] & (1 << i)) - fg_data[i] = ht216->ht_regs[0xf5]; - else if (ht216->ht_regs[0xfb] & (1 << i)) - fg_data[i] = 0xff - ht216->ht_regs[0xf5]; - } - } - break; - case 0x08: - case 0x0c: - for (i = 0; i < count; i++) - fg_data[i] = ht216->fg_latch[i]; - break; + case 0x00: + for (i = 0; i < count; i++) + fg_data[i] = cpu_dat; + break; + case 0x04: + if (ht216->ht_regs[0xfe] & HT_REG_FE_FBRC) { + for (i = 0; i < count; i++) { + if (ht216->ht_regs[0xfa] & (1 << i)) + fg_data[i] = cpu_dat_unexpanded; + else if (ht216->ht_regs[0xfb] & (1 << i)) + fg_data[i] = 0xff - cpu_dat_unexpanded; + } + } else { + for (i = 0; i < count; i++) { + if (ht216->ht_regs[0xfa] & (1 << i)) + fg_data[i] = ht216->ht_regs[0xf5]; + else if (ht216->ht_regs[0xfb] & (1 << i)) + fg_data[i] = 0xff - ht216->ht_regs[0xf5]; + } + } + break; + case 0x08: + case 0x0c: + for (i = 0; i < count; i++) + fg_data[i] = ht216->fg_latch[i]; + break; + + default: + break; } switch (svga->writemode) { - case 0: - if ((svga->gdcreg[8] == 0xff) && !(svga->gdcreg[3] & 0x18) && (!svga->gdcreg[1] || svga->set_reset_disabled)) { - for (i = 0; i < count; i++) { - if (ht216->ht_regs[0xcd] & HT_REG_CD_P8PCEXP) { - if (writemask2 & (0x80 >> i)) - svga->vram[addr | i] = fg_data[i]; - } else { - if (writemask2 & (1 << i)) - svga->vram[addr | i] = fg_data[i]; - } - } - return; - } else { - for (i = 0; i < count; i++) { - if (svga->gdcreg[1] & (1 << i)) - vall.b[i] = !!(svga->gdcreg[0] & (1 << i)) * 0xff; - else - vall.b[i] = fg_data[i]; - } - } - break; - case 1: - for (i = 0; i < count; i++) { - if (ht216->ht_regs[0xcd] & HT_REG_CD_P8PCEXP) { - if (writemask2 & (0x80 >> i)) - svga->vram[addr | i] = svga->latch.b[i]; - } else { - if (writemask2 & (1 << i)) - svga->vram[addr | i] = svga->latch.b[i]; - } - } - return; - case 2: - for (i = 0; i < count; i++) - vall.b[i] = !!(cpu_dat & (1 << i)) * 0xff; + case 0: + if ((svga->gdcreg[8] == 0xff) && !(svga->gdcreg[3] & 0x18) && (!svga->gdcreg[1] || svga->set_reset_disabled)) { + for (i = 0; i < count; i++) { + if (ht216->ht_regs[0xcd] & HT_REG_CD_P8PCEXP) { + if (writemask2 & (0x80 >> i)) + svga->vram[addr | i] = fg_data[i]; + } else { + if (writemask2 & (1 << i)) + svga->vram[addr | i] = fg_data[i]; + } + } + return; + } else { + for (i = 0; i < count; i++) { + if (svga->gdcreg[1] & (1 << i)) + vall.b[i] = !!(svga->gdcreg[0] & (1 << i)) * 0xff; + else + vall.b[i] = fg_data[i]; + } + } + break; + case 1: + for (i = 0; i < count; i++) { + if (ht216->ht_regs[0xcd] & HT_REG_CD_P8PCEXP) { + if (writemask2 & (0x80 >> i)) + svga->vram[addr | i] = svga->latch.b[i]; + } else { + if (writemask2 & (1 << i)) + svga->vram[addr | i] = svga->latch.b[i]; + } + } + return; + case 2: + for (i = 0; i < count; i++) + vall.b[i] = !!(cpu_dat & (1 << i)) * 0xff; - if (!(svga->gdcreg[3] & 0x18) && (!svga->gdcreg[1] || svga->set_reset_disabled)) { - for (i = 0; i < count; i++) { - if (ht216->ht_regs[0xcd] & HT_REG_CD_P8PCEXP) { - if (writemask2 & (0x80 >> i)) - svga->vram[addr | i] = (vall.b[i] & svga->gdcreg[8]) | (svga->latch.b[i] & ~svga->gdcreg[8]); - } else { - if (writemask2 & (1 << i)) - svga->vram[addr | i] = (vall.b[i] & svga->gdcreg[8]) | (svga->latch.b[i] & ~svga->gdcreg[8]); - } - } - return; - } - break; - case 3: - wm = svga->gdcreg[8]; - svga->gdcreg[8] &= cpu_dat; + if (!(svga->gdcreg[3] & 0x18) && (!svga->gdcreg[1] || svga->set_reset_disabled)) { + for (i = 0; i < count; i++) { + if (ht216->ht_regs[0xcd] & HT_REG_CD_P8PCEXP) { + if (writemask2 & (0x80 >> i)) + svga->vram[addr | i] = (vall.b[i] & svga->gdcreg[8]) | (svga->latch.b[i] & ~svga->gdcreg[8]); + } else { + if (writemask2 & (1 << i)) + svga->vram[addr | i] = (vall.b[i] & svga->gdcreg[8]) | (svga->latch.b[i] & ~svga->gdcreg[8]); + } + } + return; + } + break; + case 3: + wm = svga->gdcreg[8]; + svga->gdcreg[8] &= cpu_dat; - for (i = 0; i < count; i++) - vall.b[i] = !!(svga->gdcreg[0] & (1 << i)) * 0xff; + for (i = 0; i < count; i++) + vall.b[i] = !!(svga->gdcreg[0] & (1 << i)) * 0xff; - reset_wm = 1; - break; + reset_wm = 1; + break; + + default: + break; } switch (svga->gdcreg[3] & 0x18) { - case 0x00: /* Set */ - for (i = 0; i < count; i++) { - if (ht216->ht_regs[0xcd] & HT_REG_CD_P8PCEXP) { - if (writemask2 & (0x80 >> i)) - svga->vram[addr | i] = (vall.b[i] & svga->gdcreg[8]) | (svga->latch.b[i] & ~svga->gdcreg[8]); - } else { - if (writemask2 & (1 << i)) - svga->vram[addr | i] = (vall.b[i] & svga->gdcreg[8]) | (svga->latch.b[i] & ~svga->gdcreg[8]); - } - } - break; - case 0x08: /* AND */ - for (i = 0; i < count; i++) { - if (ht216->ht_regs[0xcd] & HT_REG_CD_P8PCEXP) { - if (writemask2 & (0x80 >> i)) - svga->vram[addr | i] = (vall.b[i] | ~svga->gdcreg[8]) & svga->latch.b[i]; - } else { - if (writemask2 & (1 << i)) - svga->vram[addr | i] = (vall.b[i] | ~svga->gdcreg[8]) & svga->latch.b[i]; - } - } - break; - case 0x10: /* OR */ - for (i = 0; i < count; i++) { - if (ht216->ht_regs[0xcd] & HT_REG_CD_P8PCEXP) { - if (writemask2 & (0x80 >> i)) - svga->vram[addr | i] = (vall.b[i] & svga->gdcreg[8]) | svga->latch.b[i]; - } else { - if (writemask2 & (1 << i)) - svga->vram[addr | i] = (vall.b[i] & svga->gdcreg[8]) | svga->latch.b[i]; - } - } - break; - case 0x18: /* XOR */ - for (i = 0; i < count; i++) { - if (ht216->ht_regs[0xcd] & HT_REG_CD_P8PCEXP) { - if (writemask2 & (0x80 >> i)) - svga->vram[addr | i] = (vall.b[i] & svga->gdcreg[8]) ^ svga->latch.b[i]; - } else { - if (writemask2 & (1 << i)) - svga->vram[addr | i] = (vall.b[i] & svga->gdcreg[8]) ^ svga->latch.b[i]; - } - } - break; + case 0x00: /* Set */ + for (i = 0; i < count; i++) { + if (ht216->ht_regs[0xcd] & HT_REG_CD_P8PCEXP) { + if (writemask2 & (0x80 >> i)) + svga->vram[addr | i] = (vall.b[i] & svga->gdcreg[8]) | (svga->latch.b[i] & ~svga->gdcreg[8]); + } else { + if (writemask2 & (1 << i)) + svga->vram[addr | i] = (vall.b[i] & svga->gdcreg[8]) | (svga->latch.b[i] & ~svga->gdcreg[8]); + } + } + break; + case 0x08: /* AND */ + for (i = 0; i < count; i++) { + if (ht216->ht_regs[0xcd] & HT_REG_CD_P8PCEXP) { + if (writemask2 & (0x80 >> i)) + svga->vram[addr | i] = (vall.b[i] | ~svga->gdcreg[8]) & svga->latch.b[i]; + } else { + if (writemask2 & (1 << i)) + svga->vram[addr | i] = (vall.b[i] | ~svga->gdcreg[8]) & svga->latch.b[i]; + } + } + break; + case 0x10: /* OR */ + for (i = 0; i < count; i++) { + if (ht216->ht_regs[0xcd] & HT_REG_CD_P8PCEXP) { + if (writemask2 & (0x80 >> i)) + svga->vram[addr | i] = (vall.b[i] & svga->gdcreg[8]) | svga->latch.b[i]; + } else { + if (writemask2 & (1 << i)) + svga->vram[addr | i] = (vall.b[i] & svga->gdcreg[8]) | svga->latch.b[i]; + } + } + break; + case 0x18: /* XOR */ + for (i = 0; i < count; i++) { + if (ht216->ht_regs[0xcd] & HT_REG_CD_P8PCEXP) { + if (writemask2 & (0x80 >> i)) + svga->vram[addr | i] = (vall.b[i] & svga->gdcreg[8]) ^ svga->latch.b[i]; + } else { + if (writemask2 & (1 << i)) + svga->vram[addr | i] = (vall.b[i] & svga->gdcreg[8]) ^ svga->latch.b[i]; + } + } + break; + + default: + break; } if (reset_wm) - svga->gdcreg[8] = wm; + svga->gdcreg[8] = wm; } - static void ht216_dm_extalu_write(ht216_t *ht216, uint32_t addr, uint8_t cpu_dat, uint8_t bit_mask, uint8_t cpu_dat_unexpanded, uint8_t rop_select) { @@ -960,123 +1009,129 @@ ht216_dm_extalu_write(ht216_t *ht216, uint32_t addr, uint8_t cpu_dat, uint8_t bi 00 = CPU byte 01 = Bit mask (3CF:8) 1x = (3C4:F5)*/ - svga_t *svga = &ht216->svga; - uint8_t input_a = 0, input_b = 0; - uint8_t fg, bg; - uint8_t output; - uint32_t remapped_addr = dword_remap(svga, addr); + svga_t *svga = &ht216->svga; + uint8_t input_a = 0; + uint8_t input_b = 0; + uint8_t fg; + uint8_t bg; + uint8_t output; + uint32_t remapped_addr = dword_remap(svga, addr); if (ht216->ht_regs[0xcd] & HT_REG_CD_RMWMDE) /*RMW*/ - input_b = svga->vram[remapped_addr]; + input_b = svga->vram[remapped_addr]; else - input_b = ht216->bg_latch[addr & 7]; + input_b = ht216->bg_latch[addr & 7]; switch (ht216->ht_regs[0xfe] & HT_REG_FE_FBMC) { - case 0x00: - input_a = cpu_dat; - break; - case 0x04: - if (ht216->ht_regs[0xfe] & HT_REG_FE_FBRC) - input_a = (cpu_dat_unexpanded & (1 << ((addr & 7) ^ 7))) ? ht216->ht_regs[0xfa] : ht216->ht_regs[0xfb]; - else - input_a = (ht216->ht_regs[0xf5] & (1 << ((addr & 7) ^ 7))) ? ht216->ht_regs[0xfa] : ht216->ht_regs[0xfb]; - break; - case 0x08: - input_a = ht216->fg_latch[addr & 3]; - break; - case 0x0c: - input_a = ht216->bg_latch[addr & 7]; - break; + case 0x00: + input_a = cpu_dat; + break; + case 0x04: + if (ht216->ht_regs[0xfe] & HT_REG_FE_FBRC) + input_a = (cpu_dat_unexpanded & (1 << ((addr & 7) ^ 7))) ? ht216->ht_regs[0xfa] : ht216->ht_regs[0xfb]; + else + input_a = (ht216->ht_regs[0xf5] & (1 << ((addr & 7) ^ 7))) ? ht216->ht_regs[0xfa] : ht216->ht_regs[0xfb]; + break; + case 0x08: + input_a = ht216->fg_latch[addr & 3]; + break; + case 0x0c: + input_a = ht216->bg_latch[addr & 7]; + break; + + default: + break; } - fg = extalu(ht216->ht_regs[0xce] >> 4, input_a, input_b); - bg = extalu(ht216->ht_regs[0xce] & 0xf, input_a, input_b); - output = (fg & rop_select) | (bg & ~rop_select); - svga->vram[addr] = (svga->vram[remapped_addr] & ~bit_mask) | (output & bit_mask); + fg = extalu(ht216->ht_regs[0xce] >> 4, input_a, input_b); + bg = extalu(ht216->ht_regs[0xce] & 0xf, input_a, input_b); + output = (fg & rop_select) | (bg & ~rop_select); + svga->vram[addr] = (svga->vram[remapped_addr] & ~bit_mask) | (output & bit_mask); svga->changedvram[remapped_addr >> 12] = changeframecount; } static void ht216_dm_masked_write(ht216_t *ht216, uint32_t addr, uint8_t val, uint8_t bit_mask) -{ - svga_t *svga = &ht216->svga; - int writemask2 = svga->writemask; - uint8_t count = 4, i; - uint8_t full_mask = 0x0f; +{ + svga_t *svga = &ht216->svga; + int writemask2 = svga->writemask; + uint8_t count = 4; + uint8_t i; + uint8_t full_mask = 0x0f; if (ht216->ht_regs[0xcd] & HT_REG_CD_P8PCEXP) - writemask2 = svga->seqregs[2]; + writemask2 = svga->seqregs[2]; if (!(svga->gdcreg[6] & 1)) - svga->fullchange = 2; + svga->fullchange = 2; - if (svga->chain4) { - writemask2 = 1 << (addr & 3); - addr = dword_remap(svga, addr) & ~3; - } else if (svga->chain2_write) { - writemask2 &= ~0xa; - if (addr & 1) - writemask2 <<= 1; - addr &= ~1; - addr <<= 2; + if (svga->chain4) { + writemask2 = 1 << (addr & 3); + addr = dword_remap(svga, addr) & ~3; + } else if (svga->chain2_write) { + writemask2 &= ~0xa; + if (addr & 1) + writemask2 <<= 1; + addr &= ~1; + addr <<= 2; } else - addr <<= 2; + addr <<= 2; if (addr >= svga->vram_max) - return; + return; addr &= svga->decode_mask; if (addr >= svga->vram_max) - return; + return; addr &= svga->vram_mask; svga->changedvram[addr >> 12] = changeframecount; if (ht216->ht_regs[0xcd] & HT_REG_CD_P8PCEXP) { - count = 8; - full_mask = 0xff; + count = 8; + full_mask = 0xff; } if (bit_mask == 0xff) { - for (i = 0; i < count; i++) { - if (writemask2 & (1 << i)) - svga->vram[addr | i] = val; - } + for (i = 0; i < count; i++) { + if (writemask2 & (1 << i)) + svga->vram[addr | i] = val; + } } else { - if (writemask2 == full_mask) { - for (i = 0; i < count; i++) - svga->vram[addr | i] = (svga->latch.b[i] & bit_mask) | (svga->vram[addr | i] & ~bit_mask); - } else { - for (i = 0; i < count; i++) { - if (writemask2 & (1 << i)) - svga->vram[addr | i] = (val & bit_mask) | (svga->vram[addr | i] & ~bit_mask); - } - } + if (writemask2 == full_mask) { + for (i = 0; i < count; i++) + svga->vram[addr | i] = (svga->latch.b[i] & bit_mask) | (svga->vram[addr | i] & ~bit_mask); + } else { + for (i = 0; i < count; i++) { + if (writemask2 & (1 << i)) + svga->vram[addr | i] = (val & bit_mask) | (svga->vram[addr | i] & ~bit_mask); + } + } } } - static void ht216_write_common(ht216_t *ht216, uint32_t addr, uint8_t val) { /*Input B = CD.5 Input A = FE[3:2] - 00 = Set/Reset output mode - output = CPU-side ALU input - 01 = Solid fg/bg mode (3C4:FA/FB) - Bit mask = 3CF.F5 or CPU byte - 10 = Dithered fg (3CF:EC-EF) - 11 = RMW (dest data) (set if CD.5 = 1) + 00 = Set/Reset output mode + output = CPU-side ALU input + 01 = Solid fg/bg mode (3C4:FA/FB) + Bit mask = 3CF.F5 or CPU byte + 10 = Dithered fg (3CF:EC-EF) + 11 = RMW (dest data) (set if CD.5 = 1) F/B ROP select = FE[5:4] - 00 = CPU byte - 01 = Bit mask (3CF:8) - 1x = (3C4:F5) + 00 = CPU byte + 01 = Bit mask (3CF:8) + 1x = (3C4:F5) */ - svga_t *svga = &ht216->svga; - int i; - uint8_t bit_mask = 0, rop_select = 0; + const svga_t *svga = &ht216->svga; + int i; + uint8_t bit_mask = 0; + uint8_t rop_select = 0; cycles -= video_timing_write_b; @@ -1085,199 +1140,201 @@ ht216_write_common(ht216_t *ht216, uint32_t addr, uint8_t val) val = ((val >> (svga->gdcreg[3] & 7)) | (val << (8 - (svga->gdcreg[3] & 7)))); if (ht216->ht_regs[0xcd] & HT_REG_CD_EXALU) { - /*Extended ALU*/ - switch (ht216->ht_regs[0xfe] & HT_REG_FE_FBRSL) { - case 0x00: - rop_select = val; - break; - case 0x10: - rop_select = svga->gdcreg[8]; - break; - case 0x20: case 0x30: - rop_select = ht216->ht_regs[0xf5]; - break; - } - switch (ht216->ht_regs[0xcd] & HT_REG_CD_BMSKSL) { - case 0x00: - bit_mask = svga->gdcreg[8]; - break; - case 0x04: - bit_mask = val; - break; - case 0x08: case 0x0c: - bit_mask = ht216->ht_regs[0xf5]; - break; - } - - if (ht216->ht_regs[0xcd] & HT_REG_CD_FP8PCEXP) { /*1->8 bit expansion*/ - addr = (addr << 3) & 0xfffff; - for (i = 0; i < 8; i++) - ht216_dm_extalu_write(ht216, addr + i, (val & (0x80 >> i)) ? 0xff : 0, (bit_mask & (0x80 >> i)) ? 0xff : 0, val, (rop_select & (0x80 >> i)) ? 0xff : 0); - } else { - ht216_dm_extalu_write(ht216, addr, val, bit_mask, val, rop_select); - } + /*Extended ALU*/ + switch (ht216->ht_regs[0xfe] & HT_REG_FE_FBRSL) { + case 0x00: + rop_select = val; + break; + case 0x10: + rop_select = svga->gdcreg[8]; + break; + case 0x20: + case 0x30: + rop_select = ht216->ht_regs[0xf5]; + break; + + default: + break; + } + switch (ht216->ht_regs[0xcd] & HT_REG_CD_BMSKSL) { + case 0x00: + bit_mask = svga->gdcreg[8]; + break; + case 0x04: + bit_mask = val; + break; + case 0x08: + case 0x0c: + bit_mask = ht216->ht_regs[0xf5]; + break; + + default: + break; + } + + if (ht216->ht_regs[0xcd] & HT_REG_CD_FP8PCEXP) { /*1->8 bit expansion*/ + addr = (addr << 3) & 0xfffff; + for (i = 0; i < 8; i++) + ht216_dm_extalu_write(ht216, addr + i, (val & (0x80 >> i)) ? 0xff : 0, (bit_mask & (0x80 >> i)) ? 0xff : 0, val, (rop_select & (0x80 >> i)) ? 0xff : 0); + } else { + ht216_dm_extalu_write(ht216, addr, val, bit_mask, val, rop_select); + } } else if (ht216->ht_regs[0xf3]) { - if (ht216->ht_regs[0xf3] & 2) { - ht216_dm_masked_write(ht216, addr, val, val); - } else - ht216_dm_masked_write(ht216, addr, val, ht216->ht_regs[0xf4]); + if (ht216->ht_regs[0xf3] & 2) { + ht216_dm_masked_write(ht216, addr, val, val); + } else + ht216_dm_masked_write(ht216, addr, val, ht216->ht_regs[0xf4]); } else { - if (ht216->ht_regs[0xcd] & HT_REG_CD_FP8PCEXP) { /*1->8 bit expansion*/ - addr = (addr << 3) & 0xfffff; - for (i = 0; i < 8; i++) - ht216_dm_write(ht216, addr + i, (val & (0x80 >> i)) ? 0xff : 0, val); - } else { - ht216_dm_write(ht216, addr, val, val); - } + if (ht216->ht_regs[0xcd] & HT_REG_CD_FP8PCEXP) { /*1->8 bit expansion*/ + addr = (addr << 3) & 0xfffff; + for (i = 0; i < 8; i++) + ht216_dm_write(ht216, addr + i, (val & (0x80 >> i)) ? 0xff : 0, val); + } else { + ht216_dm_write(ht216, addr, val, val); + } } } - static void -ht216_write(uint32_t addr, uint8_t val, void *p) +ht216_write(uint32_t addr, uint8_t val, void *priv) { - ht216_t *ht216 = (ht216_t *)p; - svga_t *svga = &ht216->svga; + ht216_t *ht216 = (ht216_t *) priv; + svga_t *svga = &ht216->svga; uint32_t prev_addr = addr; addr &= svga->banked_mask; addr = (addr & 0x7fff) + ht216->write_banks[(addr >> 15) & 1]; if (svga->crtc[0x17] == 0xeb && !(svga->gdcreg[6] & 0xc) && prev_addr >= 0xb0000) - addr += 0x10000; + addr += 0x10000; else if (svga->chain4 && ((ht216->ht_regs[0xfc] & 0x06) == 0x06)) - addr = (addr & 0xfffeffff) | (prev_addr & 0x10000); + addr = (addr & 0xfffeffff) | (prev_addr & 0x10000); if (!ht216->ht_regs[0xcd] && !ht216->ht_regs[0xfe] && !ht216->ht_regs[0xf3] && svga->crtc[0x17] != 0xeb) { - svga_write_linear(addr, val, svga); + svga_write_linear(addr, val, svga); } else - ht216_write_common(ht216, addr, val); + ht216_write_common(ht216, addr, val); } - static void -ht216_writew(uint32_t addr, uint16_t val, void *p) +ht216_writew(uint32_t addr, uint16_t val, void *priv) { - ht216_t *ht216 = (ht216_t *)p; - svga_t *svga = &ht216->svga; + ht216_t *ht216 = (ht216_t *) priv; + svga_t *svga = &ht216->svga; uint32_t prev_addr = addr; addr &= svga->banked_mask; addr = (addr & 0x7fff) + ht216->write_banks[(addr >> 15) & 1]; if (svga->crtc[0x17] == 0xeb && !(svga->gdcreg[6] & 0xc) && prev_addr >= 0xb0000) - addr += 0x10000; + addr += 0x10000; else if (svga->chain4 && ((ht216->ht_regs[0xfc] & 0x06) == 0x06)) - addr = (addr & 0xfffeffff) | (prev_addr & 0x10000); + addr = (addr & 0xfffeffff) | (prev_addr & 0x10000); if (!ht216->ht_regs[0xcd] && !ht216->ht_regs[0xfe] && !ht216->ht_regs[0xf3] && svga->crtc[0x17] != 0xeb) - svga_writew_linear(addr, val, svga); + svga_writew_linear(addr, val, svga); else { - ht216_write_common(ht216, addr, val); - ht216_write_common(ht216, addr+1, val >> 8); + ht216_write_common(ht216, addr, val); + ht216_write_common(ht216, addr + 1, val >> 8); } } - static void -ht216_writel(uint32_t addr, uint32_t val, void *p) +ht216_writel(uint32_t addr, uint32_t val, void *priv) { - ht216_t *ht216 = (ht216_t *)p; - svga_t *svga = &ht216->svga; + ht216_t *ht216 = (ht216_t *) priv; + svga_t *svga = &ht216->svga; uint32_t prev_addr = addr; addr &= svga->banked_mask; addr = (addr & 0x7fff) + ht216->write_banks[(addr >> 15) & 1]; if (svga->crtc[0x17] == 0xeb && !(svga->gdcreg[6] & 0xc) && prev_addr >= 0xb0000) - addr += 0x10000; + addr += 0x10000; else if (svga->chain4 && ((ht216->ht_regs[0xfc] & 0x06) == 0x06)) - addr = (addr & 0xfffeffff) | (prev_addr & 0x10000); + addr = (addr & 0xfffeffff) | (prev_addr & 0x10000); if (!ht216->ht_regs[0xcd] && !ht216->ht_regs[0xfe] && !ht216->ht_regs[0xf3] && svga->crtc[0x17] != 0xeb) - svga_writel_linear(addr, val, svga); + svga_writel_linear(addr, val, svga); else { - ht216_write_common(ht216, addr, val); - ht216_write_common(ht216, addr+1, val >> 8); - ht216_write_common(ht216, addr+2, val >> 16); - ht216_write_common(ht216, addr+3, val >> 24); + ht216_write_common(ht216, addr, val); + ht216_write_common(ht216, addr + 1, val >> 8); + ht216_write_common(ht216, addr + 2, val >> 16); + ht216_write_common(ht216, addr + 3, val >> 24); } } - static void -ht216_write_linear(uint32_t addr, uint8_t val, void *p) +ht216_write_linear(uint32_t addr, uint8_t val, void *priv) { - ht216_t *ht216 = (ht216_t *)p; - svga_t *svga = &ht216->svga; + ht216_t *ht216 = (ht216_t *) priv; + svga_t *svga = &ht216->svga; addr -= ht216->linear_base; - if (!svga->chain4) /*Bits 16 and 17 of linear address are unused in planar modes*/ - addr = (addr & 0xffff) | ((addr & 0xc0000) >> 2); + if (!svga->chain4) /*Bits 16 and 17 of linear address are unused in planar modes*/ + addr = (addr & 0xffff) | ((addr & 0xc0000) >> 2); addr += ht216->write_banks[0]; if (!ht216->ht_regs[0xcd] && !ht216->ht_regs[0xfe]) - svga_write_linear(addr, val, svga); + svga_write_linear(addr, val, svga); else - ht216_write_common(ht216, addr, val); + ht216_write_common(ht216, addr, val); } - static void -ht216_writew_linear(uint32_t addr, uint16_t val, void *p) +ht216_writew_linear(uint32_t addr, uint16_t val, void *priv) { - ht216_t *ht216 = (ht216_t *)p; - svga_t *svga = &ht216->svga; + ht216_t *ht216 = (ht216_t *) priv; + svga_t *svga = &ht216->svga; addr -= ht216->linear_base; - if (!svga->chain4) /*Bits 16 and 17 of linear address are unused in planar modes*/ - addr = (addr & 0xffff) | ((addr & 0xc0000) >> 2); + if (!svga->chain4) /*Bits 16 and 17 of linear address are unused in planar modes*/ + addr = (addr & 0xffff) | ((addr & 0xc0000) >> 2); addr += ht216->write_banks[0]; if (!ht216->ht_regs[0xcd] && !ht216->ht_regs[0xfe]) - svga_writew_linear(addr, val, svga); + svga_writew_linear(addr, val, svga); else { - ht216_write_common(ht216, addr, val); - ht216_write_common(ht216, addr+1, val >> 8); + ht216_write_common(ht216, addr, val); + ht216_write_common(ht216, addr + 1, val >> 8); } } - static void -ht216_writel_linear(uint32_t addr, uint32_t val, void *p) +ht216_writel_linear(uint32_t addr, uint32_t val, void *priv) { - ht216_t *ht216 = (ht216_t *)p; - svga_t *svga = &ht216->svga; + ht216_t *ht216 = (ht216_t *) priv; + svga_t *svga = &ht216->svga; addr -= ht216->linear_base; - if (!svga->chain4) /*Bits 16 and 17 of linear address are unused in planar modes*/ - addr = (addr & 0xffff) | ((addr & 0xc0000) >> 2); + if (!svga->chain4) /*Bits 16 and 17 of linear address are unused in planar modes*/ + addr = (addr & 0xffff) | ((addr & 0xc0000) >> 2); addr += ht216->write_banks[0]; if (!ht216->ht_regs[0xcd] && !ht216->ht_regs[0xfe]) - svga_writel_linear(addr, val, svga); + svga_writel_linear(addr, val, svga); else { - ht216_write_common(ht216, addr, val); - ht216_write_common(ht216, addr+1, val >> 8); - ht216_write_common(ht216, addr+2, val >> 16); - ht216_write_common(ht216, addr+3, val >> 24); + ht216_write_common(ht216, addr, val); + ht216_write_common(ht216, addr + 1, val >> 8); + ht216_write_common(ht216, addr + 2, val >> 16); + ht216_write_common(ht216, addr + 3, val >> 24); } } - static uint8_t ht216_read_common(ht216_t *ht216, uint32_t addr) { - svga_t *svga = &ht216->svga; + svga_t *svga = &ht216->svga; uint32_t latch_addr = 0; - int offset, readplane = svga->readplane; - uint8_t or, i; - uint8_t count = 2; - uint8_t plane, pixel; - uint8_t temp, ret; + int offset; + int readplane = svga->readplane; + uint8_t or; + uint8_t count = 2; + uint8_t temp; + uint8_t ret; if (ht216->ht_regs[0xc8] & HT_REG_C8_MOVSB) - addr <<= 3; + addr <<= 3; addr &= svga->vram_mask; @@ -1286,95 +1343,93 @@ ht216_read_common(ht216_t *ht216, uint32_t addr) count = (1 << count); if (svga->chain4 && svga->packed_chain4) { - addr &= svga->decode_mask; - if (addr >= svga->vram_max) - return 0xff; - latch_addr = (addr & svga->vram_mask) & ~7; - if (ht216->ht_regs[0xcd] & HT_REG_CD_ASTODE) - latch_addr += (svga->gdcreg[3] & 7); - for (i = 0; i < 8; i++) - ht216->bg_latch[i] = svga->vram[dword_remap(svga, latch_addr + i)]; - return svga->vram[dword_remap(svga, addr) & svga->vram_mask]; + addr &= svga->decode_mask; + if (addr >= svga->vram_max) + return 0xff; + latch_addr = (addr & svga->vram_mask) & ~7; + if (ht216->ht_regs[0xcd] & HT_REG_CD_ASTODE) + latch_addr += (svga->gdcreg[3] & 7); + for (uint8_t i = 0; i < 8; i++) + ht216->bg_latch[i] = svga->vram[dword_remap(svga, latch_addr + i)]; + return svga->vram[dword_remap(svga, addr) & svga->vram_mask]; } else if (svga->chain4) { - readplane = addr & 3; - addr = ((addr & 0xfffc) << 2) | ((addr & 0x30000) >> 14) | (addr & ~0x3ffff); - } else if (svga->chain2_read && (svga->crtc[0x17] != 0xeb)) { - readplane = (readplane & 2) | (addr & 1); - addr &= ~1; - addr <<= 2; + readplane = addr & 3; + addr = ((addr & 0xfffc) << 2) | ((addr & 0x30000) >> 14) | (addr & ~0x3ffff); + } else if (svga->chain2_read && (svga->crtc[0x17] != 0xeb)) { + readplane = (readplane & 2) | (addr & 1); + addr &= ~1; + addr <<= 2; } else - addr <<= 2; + addr <<= 2; addr &= svga->decode_mask; if (addr >= svga->vram_max) - return 0xff; + return 0xff; addr &= svga->vram_mask; latch_addr = addr & ~7; if (ht216->ht_regs[0xcd] & HT_REG_CD_ASTODE) { - offset = addr & 7; - for (i = 0; i < 8; i++) - ht216->bg_latch[i] = svga->vram[latch_addr | ((offset + i) & 7)]; + offset = addr & 7; + for (uint8_t i = 0; i < 8; i++) + ht216->bg_latch[i] = svga->vram[latch_addr | ((offset + i) & 7)]; } else { - for (i = 0; i < 8; i++) - ht216->bg_latch[i] = svga->vram[latch_addr | i]; + for (uint8_t i = 0; i < 8; i++) + ht216->bg_latch[i] = svga->vram[latch_addr | i]; } - + or = addr & 4; - for (i = 0; i < 4; i++) - svga->latch.b[i] = ht216->bg_latch[i | or]; - + for (uint8_t i = 0; i < 4; i++) + svga->latch.b[i] = ht216->bg_latch[i | or ]; + if (svga->readmode) { - temp = 0xff; + temp = 0xff; - for (pixel = 0; pixel < 8; pixel++) { - for (plane = 0; plane < (1 << count); plane++) { - if (svga->colournocare & (1 << plane)) { - /* If we care about a plane, and the pixel has a mismatch on it, clear its bit. */ - if (((svga->latch.b[plane] >> pixel) & 1) != ((svga->colourcompare >> plane) & 1)) - temp &= ~(1 << pixel); - } - } - } + for (uint8_t pixel = 0; pixel < 8; pixel++) { + for (uint8_t plane = 0; plane < (uint8_t)(1 << count); plane++) { + if (svga->colournocare & (1 << plane)) { + /* If we care about a plane, and the pixel has a mismatch on it, clear its bit. */ + if (((svga->latch.b[plane] >> pixel) & 1) != ((svga->colourcompare >> plane) & 1)) + temp &= ~(1 << pixel); + } + } + } - ret = temp; + ret = temp; } else - ret = svga->vram[addr | readplane]; + ret = svga->vram[addr | readplane]; return ret; } - static uint8_t -ht216_read(uint32_t addr, void *p) +ht216_read(uint32_t addr, void *priv) { - ht216_t *ht216 = (ht216_t *)p; - svga_t *svga = &ht216->svga; - uint32_t prev_addr = addr; + ht216_t *ht216 = (ht216_t *) priv; + const svga_t *svga = &ht216->svga; + uint32_t prev_addr = addr; addr &= svga->banked_mask; addr = (addr & 0x7fff) + ht216->read_banks[(addr >> 15) & 1]; - + if (svga->crtc[0x17] == 0xeb && !(svga->gdcreg[6] & 0xc) && prev_addr >= 0xb0000) - addr += 0x10000; + addr += 0x10000; else if (svga->chain4 && ((ht216->ht_regs[0xfc] & 0x06) == 0x06)) - addr = (addr & 0xfffeffff) | (prev_addr & 0x10000); + addr = (addr & 0xfffeffff) | (prev_addr & 0x10000); return ht216_read_common(ht216, addr); } - static uint8_t -ht216_read_linear(uint32_t addr, void *p) +ht216_read_linear(uint32_t addr, void *priv) { - ht216_t *ht216 = (ht216_t *)p; - svga_t *svga = &ht216->svga; + ht216_t *ht216 = (ht216_t *) priv; + const svga_t *svga = &ht216->svga; addr -= ht216->linear_base; - if (!svga->chain4) /*Bits 16 and 17 of linear address are unused in planar modes*/ - addr = (addr & 0xffff) | ((addr & 0xc0000) >> 2); + if (!svga->chain4) /*Bits 16 and 17 of linear address are unused in planar modes*/ + addr = (addr & 0xffff) | ((addr & 0xc0000) >> 2); addr += ht216->read_banks[0]; return ht216_read_common(ht216, addr); @@ -1383,134 +1438,141 @@ ht216_read_linear(uint32_t addr, void *p) static uint8_t radius_mca_read(int port, void *priv) { - ht216_t *ht216 = (ht216_t *)priv; - ht216_log("Port %03x MCA read = %02x\n", port, ht216->pos_regs[port & 7]); + const ht216_t *ht216 = (ht216_t *) priv; + + ht216_log("Port %03x MCA read = %02x\n", port, ht216->pos_regs[port & 7]); + return (ht216->pos_regs[port & 7]); } static void radius_mca_write(int port, uint8_t val, void *priv) { - ht216_t *ht216 = (ht216_t *)priv; + ht216_t *ht216 = (ht216_t *) priv; /* MCA does not write registers below 0x0100. */ - if (port < 0x0102) return; + if (port < 0x0102) + return; - ht216_log("Port %03x MCA write = %02x, setup mode = %02x\n", port, val, ht216->ht_regs[0xfc] & 0x80); + ht216_log("Port %03x MCA write = %02x, setup mode = %02x\n", port, val, ht216->ht_regs[0xfc] & 0x80); /* Save the MCA register value. */ ht216->pos_regs[port & 7] = val; } static uint8_t -radius_mca_feedb(void *priv) +radius_mca_feedb(UNUSED(void *priv)) { - return 1; + return 1; } void -*ht216_init(const device_t *info, uint32_t mem_size, int has_rom) + * + ht216_init(const device_t *info, uint32_t mem_size, int has_rom) { ht216_t *ht216 = malloc(sizeof(ht216_t)); - svga_t *svga; + svga_t *svga; memset(ht216, 0, sizeof(ht216_t)); svga = &ht216->svga; if (info->flags & DEVICE_VLB) - video_inform(VIDEO_FLAG_TYPE_SPECIAL, &timing_v7vga_vlb); + video_inform(VIDEO_FLAG_TYPE_SPECIAL, &timing_v7vga_vlb); else if (info->flags & DEVICE_MCA) - video_inform(VIDEO_FLAG_TYPE_SPECIAL, &timing_v7vga_mca); + video_inform(VIDEO_FLAG_TYPE_SPECIAL, &timing_v7vga_mca); else - video_inform(VIDEO_FLAG_TYPE_SPECIAL, &timing_v7vga_isa); - + video_inform(VIDEO_FLAG_TYPE_SPECIAL, &timing_v7vga_isa); + svga_init(info, svga, ht216, mem_size, - ht216_recalctimings, - ht216_in, ht216_out, - ht216_hwcursor_draw, - NULL); + ht216_recalctimings, + ht216_in, ht216_out, + ht216_hwcursor_draw, + NULL); switch (has_rom) { - case 1: - rom_init(&ht216->bios_rom, BIOS_G2_GC205_PATH, 0xc0000, 0x8000, 0x7fff, 0, MEM_MAPPING_EXTERNAL); - break; - case 2: - rom_init(&ht216->bios_rom, BIOS_VIDEO7_VGA_1024I_PATH, 0xc0000, 0x8000, 0x7fff, 0, MEM_MAPPING_EXTERNAL); - break; - case 3: - ht216->monitor_type = device_get_config_int("monitor_type"); - rom_init(&ht216->bios_rom, BIOS_HT216_32_PATH, 0xc0000, 0x8000, 0x7fff, 0, MEM_MAPPING_EXTERNAL); - /* Patch the BIOS for monitor type. */ - if (ht216->monitor_type & 0x10) { - /* Color */ - ht216->bios_rom.rom[0x0526] = 0x0c; - ht216->bios_rom.rom[0x0528] = 0xeb; - ht216->bios_rom.rom[0x7fff] += 0x26; - } else { - /* Mono */ - ht216->bios_rom.rom[0x0526] = 0x24; - ht216->bios_rom.rom[0x0527] = 0xef; - ht216->bios_rom.rom[0x0528] = ht216->bios_rom.rom[0x0529] = 0x90; - ht216->bios_rom.rom[0x7fff] += 0xfe; - } - /* Patch bios for interlaced/non-interlaced. */ - if (ht216->monitor_type & 0x08) { - /* Non-Interlaced */ - ht216->bios_rom.rom[0x170b] = 0x0c; - ht216->bios_rom.rom[0x170d] = ht216->bios_rom.rom[0x170e] = 0x90; - ht216->bios_rom.rom[0x7fff] += 0xf4; - } else { - /* Interlaced */ - ht216->bios_rom.rom[0x170b] = 0x24; - ht216->bios_rom.rom[0x170c] = 0xf7; - ht216->bios_rom.rom[0x170d] = 0xeb; - ht216->bios_rom.rom[0x7fff] += 0x1e; - } - break; - case 4: - if ((info->local == 0x7152) && (info->flags & DEVICE_ISA)) - ht216->extensions = device_get_config_int("extensions"); - else if ((info->local == 0x7152) && (info->flags & DEVICE_MCA)) { - ht216->pos_regs[0] = 0xb7; - ht216->pos_regs[1] = 0x80; - mca_add(radius_mca_read, radius_mca_write, radius_mca_feedb, NULL, ht216); - } - rom_init(&ht216->bios_rom, BIOS_RADIUS_SVGA_MULTIVIEW_PATH, 0xc0000, 0x8000, 0x7fff, 0, MEM_MAPPING_EXTERNAL); - break; + case 1: + rom_init(&ht216->bios_rom, BIOS_G2_GC205_PATH, 0xc0000, 0x8000, 0x7fff, 0, MEM_MAPPING_EXTERNAL); + break; + case 2: + rom_init(&ht216->bios_rom, BIOS_VIDEO7_VGA_1024I_PATH, 0xc0000, 0x8000, 0x7fff, 0, MEM_MAPPING_EXTERNAL); + break; + case 3: + ht216->monitor_type = device_get_config_int("monitor_type"); + rom_init(&ht216->bios_rom, BIOS_HT216_32_PATH, 0xc0000, 0x8000, 0x7fff, 0, MEM_MAPPING_EXTERNAL); + /* Patch the BIOS for monitor type. */ + if (ht216->monitor_type & 0x10) { + /* Color */ + ht216->bios_rom.rom[0x0526] = 0x0c; + ht216->bios_rom.rom[0x0528] = 0xeb; + ht216->bios_rom.rom[0x7fff] += 0x26; + } else { + /* Mono */ + ht216->bios_rom.rom[0x0526] = 0x24; + ht216->bios_rom.rom[0x0527] = 0xef; + ht216->bios_rom.rom[0x0528] = ht216->bios_rom.rom[0x0529] = 0x90; + ht216->bios_rom.rom[0x7fff] += 0xfe; + } + /* Patch bios for interlaced/non-interlaced. */ + if (ht216->monitor_type & 0x08) { + /* Non-Interlaced */ + ht216->bios_rom.rom[0x170b] = 0x0c; + ht216->bios_rom.rom[0x170d] = ht216->bios_rom.rom[0x170e] = 0x90; + ht216->bios_rom.rom[0x7fff] += 0xf4; + } else { + /* Interlaced */ + ht216->bios_rom.rom[0x170b] = 0x24; + ht216->bios_rom.rom[0x170c] = 0xf7; + ht216->bios_rom.rom[0x170d] = 0xeb; + ht216->bios_rom.rom[0x7fff] += 0x1e; + } + break; + case 4: + if ((info->local == 0x7152) && (info->flags & DEVICE_ISA)) + ht216->extensions = device_get_config_int("extensions"); + else if ((info->local == 0x7152) && (info->flags & DEVICE_MCA)) { + ht216->pos_regs[0] = 0xb7; + ht216->pos_regs[1] = 0x80; + mca_add(radius_mca_read, radius_mca_write, radius_mca_feedb, NULL, ht216); + } + rom_init(&ht216->bios_rom, BIOS_RADIUS_SVGA_MULTIVIEW_PATH, 0xc0000, 0x8000, 0x7fff, 0, MEM_MAPPING_EXTERNAL); + break; + + default: + break; } - svga->hwcursor.ysize = 32; - ht216->vram_mask = mem_size - 1; - svga->decode_mask = mem_size - 1; + svga->hwcursor.cur_ysize = 32; + ht216->vram_mask = mem_size - 1; + svga->decode_mask = mem_size - 1; if (has_rom == 4) - svga->ramdac = device_add(&sc11484_nors2_ramdac_device); + svga->ramdac = device_add(&sc11484_nors2_ramdac_device); if ((info->flags & DEVICE_VLB) || (info->flags & DEVICE_MCA)) { - mem_mapping_set_handler(&svga->mapping, ht216_read, NULL, NULL, ht216_write, ht216_writew, ht216_writel); - mem_mapping_add(&ht216->linear_mapping, 0, 0, ht216_read_linear, NULL, NULL, ht216_write_linear, ht216_writew_linear, ht216_writel_linear, NULL, MEM_MAPPING_EXTERNAL, svga); + mem_mapping_set_handler(&svga->mapping, ht216_read, NULL, NULL, ht216_write, ht216_writew, ht216_writel); + mem_mapping_add(&ht216->linear_mapping, 0, 0, ht216_read_linear, NULL, NULL, ht216_write_linear, ht216_writew_linear, ht216_writel_linear, NULL, MEM_MAPPING_EXTERNAL, svga); } else { - mem_mapping_set_handler(&svga->mapping, ht216_read, NULL, NULL, ht216_write, ht216_writew, NULL); - mem_mapping_add(&ht216->linear_mapping, 0, 0, ht216_read_linear, NULL, NULL, ht216_write_linear, ht216_writew_linear, NULL, NULL, MEM_MAPPING_EXTERNAL, svga); + mem_mapping_set_handler(&svga->mapping, ht216_read, NULL, NULL, ht216_write, ht216_writew, NULL); + mem_mapping_add(&ht216->linear_mapping, 0, 0, ht216_read_linear, NULL, NULL, ht216_write_linear, ht216_writew_linear, NULL, NULL, MEM_MAPPING_EXTERNAL, svga); } mem_mapping_set_p(&svga->mapping, ht216); mem_mapping_disable(&ht216->linear_mapping); - ht216->id = info->local; + ht216->id = info->local; ht216->isabus = (info->flags & DEVICE_ISA); - ht216->mca = (info->flags & DEVICE_MCA); + ht216->mca = (info->flags & DEVICE_MCA); io_sethandler(0x03c0, 0x0020, ht216_in, NULL, NULL, ht216_out, NULL, NULL, ht216); io_sethandler(0x46e8, 0x0001, ht216_in, NULL, NULL, ht216_out, NULL, NULL, ht216); - svga->bpp = 8; - svga->miscout = 1; - + svga->bpp = 8; + svga->miscout = 1; + if (ht216->id == 0x7861) - ht216->ht_regs[0xb4] = 0x08; /*32-bit DRAM bus*/ + ht216->ht_regs[0xb4] = 0x08; /*32-bit DRAM bus*/ if (ht216->id == 0x7152) - ht216->reg_3cb = 0x20; + ht216->reg_3cb = 0x20; /* Initialize the cursor pointer towards the end of its segment, needed for ht256sf.drv to work correctly when Windows 3.1 is started after boot. */ @@ -1521,7 +1583,6 @@ void return ht216; } - static void * g2_gc205_init(const device_t *info) { @@ -1530,7 +1591,6 @@ g2_gc205_init(const device_t *info) return ht216; } - static void * v7_vga_1024i_init(const device_t *info) { @@ -1539,7 +1599,6 @@ v7_vga_1024i_init(const device_t *info) return ht216; } - static void * ht216_pb410a_init(const device_t *info) { @@ -1548,7 +1607,6 @@ ht216_pb410a_init(const device_t *info) return ht216; } - static void * ht216_standalone_init(const device_t *info) { @@ -1565,21 +1623,18 @@ radius_svga_multiview_init(const device_t *info) return ht216; } - static int g2_gc205_available(void) { return rom_present(BIOS_G2_GC205_PATH); } - static int v7_vga_1024i_available(void) { return rom_present(BIOS_VIDEO7_VGA_1024I_PATH); } - static int ht216_standalone_available(void) { @@ -1592,189 +1647,186 @@ radius_svga_multiview_available(void) return rom_present(BIOS_RADIUS_SVGA_MULTIVIEW_PATH); } - void -ht216_close(void *p) +ht216_close(void *priv) { - ht216_t *ht216 = (ht216_t *)p; + ht216_t *ht216 = (ht216_t *) priv; svga_close(&ht216->svga); free(ht216); } - void -ht216_speed_changed(void *p) +ht216_speed_changed(void *priv) { - ht216_t *ht216 = (ht216_t *)p; + ht216_t *ht216 = (ht216_t *) priv; svga_recalctimings(&ht216->svga); } - void -ht216_force_redraw(void *p) +ht216_force_redraw(void *priv) { - ht216_t *ht216 = (ht216_t *)p; + ht216_t *ht216 = (ht216_t *) priv; ht216->svga.fullchange = changeframecount; } +static const device_config_t v7_vga_1024i_config[] = { + { .name = "memory", + .description = "Memory size", + .type = CONFIG_SELECTION, + .default_int = 512, + .selection = { + { .description = "256 kB", + .value = 256 }, + { .description = "512 kB", + .value = 512 }, + { .description = "" } } }, + { .type = CONFIG_END } +}; -static const device_config_t v7_vga_1024i_config[] = -{ - { - "memory", "Memory size", CONFIG_SELECTION, "", 512, "", { 0 }, - { - { - "256 kB", 256 - }, - { - "512 kB", 512 - }, - { - "" - } - } - }, - { - "", "", -1 +// clang-format off +static const device_config_t ht216_32_standalone_config[] = { + { + .name = "monitor_type", + .description = "Monitor type", + .type = CONFIG_SELECTION, + .default_int = 0x18, + .selection = { + { + .description = "Mono Interlaced", + .value = 0x00 + }, + { + .description = "Mono Non-Interlaced", + .value = 0x08 + }, + { + .description = "Color Interlaced", + .value = 0x10 + }, + { + .description = "Color Non-Interlaced", + .value = 0x18 + }, + { + .description = "" + } } + }, + { + .type = CONFIG_END + } }; -static const device_config_t ht216_32_standalone_config[] = -{ - { - "monitor_type", "Monitor type", CONFIG_SELECTION, "", 0x18, "", { 0 }, - { - { - "Mono Interlaced", 0x00 - }, - { - "Mono Non-Interlaced", 0x08 - }, - { - "Color Interlaced", 0x10 - }, - { - "Color Non-Interlaced", 0x18 - }, - { - "" - } - } - }, - { - "", "", -1 +static const device_config_t radius_svga_multiview_config[] = { + { + .name = "extensions", + .description = "Extensions", + .type = CONFIG_SELECTION, + .default_int = 0x00, + .selection = { + { + .description = "Extensions Enabled", + .value = 0x00 + }, + { + .description = "Extensions Disabled", + .value = 0x02 + }, + { + .description = "" + } } + }, + { + .type = CONFIG_END + } +}; +// clang-format on + +const device_t g2_gc205_device = { + .name = "G2 GC205", + .internal_name = "g2_gc205", + .flags = DEVICE_ISA, + .local = 0x7070, + .init = g2_gc205_init, + .close = ht216_close, + .reset = NULL, + { .available = g2_gc205_available }, + .speed_changed = ht216_speed_changed, + .force_redraw = ht216_force_redraw, + .config = NULL }; -static const device_config_t radius_svga_multiview_config[] = -{ - { - "extensions", "Extensions", CONFIG_SELECTION, "", 0x00, "", { 0 }, - { - { - "Extensions Enabled", 0x00 - }, - { - "Extensions Disabled", 0x02 - }, - { - "" - } - } - }, - { - "", "", -1 - } +const device_t v7_vga_1024i_device = { + .name = "Video 7 VGA 1024i (HT208)", + .internal_name = "v7_vga_1024i", + .flags = DEVICE_ISA, + .local = 0x7140, + .init = v7_vga_1024i_init, + .close = ht216_close, + .reset = NULL, + { .available = v7_vga_1024i_available }, + .speed_changed = ht216_speed_changed, + .force_redraw = ht216_force_redraw, + .config = v7_vga_1024i_config }; -const device_t g2_gc205_device = -{ - "G2 GC205", - "g2_gc205", - DEVICE_ISA, - 0x7070, - g2_gc205_init, - ht216_close, - NULL, - { g2_gc205_available }, - ht216_speed_changed, - ht216_force_redraw +const device_t ht216_32_pb410a_device = { + .name = "Headland HT216-32 (Packard Bell PB410A)", + .internal_name = "ht216_32_pb410a", + .flags = DEVICE_VLB, + .local = 0x7861, /*HT216-32*/ + .init = ht216_pb410a_init, + .close = ht216_close, + .reset = NULL, + { .available = NULL }, + .speed_changed = ht216_speed_changed, + .force_redraw = ht216_force_redraw, + .config = NULL }; -const device_t v7_vga_1024i_device = -{ - "Video 7 VGA 1024i (HT208)", - "v7_vga_1024i", - DEVICE_ISA, - 0x7140, - v7_vga_1024i_init, - ht216_close, - NULL, - { v7_vga_1024i_available }, - ht216_speed_changed, - ht216_force_redraw, - v7_vga_1024i_config +const device_t ht216_32_standalone_device = { + .name = "Headland HT216-32", + .internal_name = "ht216_32", + .flags = DEVICE_VLB, + .local = 0x7861, /*HT216-32*/ + .init = ht216_standalone_init, + .close = ht216_close, + .reset = NULL, + { .available = ht216_standalone_available }, + .speed_changed = ht216_speed_changed, + .force_redraw = ht216_force_redraw, + .config = ht216_32_standalone_config }; -const device_t ht216_32_pb410a_device = -{ - "Headland HT216-32 (Packard Bell PB410A)", - "ht216_32_pb410a", - DEVICE_VLB, - 0x7861, /*HT216-32*/ - ht216_pb410a_init, - ht216_close, - NULL, - { NULL }, - ht216_speed_changed, - ht216_force_redraw +const device_t radius_svga_multiview_isa_device = { + .name = "Radius SVGA Multiview ISA (HT209)", + .internal_name = "radius_isa", + .flags = DEVICE_ISA | DEVICE_AT, + .local = 0x7152, /*HT209*/ + .init = radius_svga_multiview_init, + .close = ht216_close, + .reset = NULL, + { .available = radius_svga_multiview_available }, + .speed_changed = ht216_speed_changed, + .force_redraw = ht216_force_redraw, + .config = radius_svga_multiview_config }; -const device_t ht216_32_standalone_device = -{ - "Headland HT216-32", - "ht216_32", - DEVICE_VLB, - 0x7861, /*HT216-32*/ - ht216_standalone_init, - ht216_close, - NULL, - { ht216_standalone_available }, - ht216_speed_changed, - ht216_force_redraw, - ht216_32_standalone_config -}; - -const device_t radius_svga_multiview_isa_device = -{ - "Radius SVGA Multiview ISA (HT209)", - "radius_isa", - DEVICE_ISA | DEVICE_AT, - 0x7152, /*HT209*/ - radius_svga_multiview_init, - ht216_close, - NULL, - { radius_svga_multiview_available }, - ht216_speed_changed, - ht216_force_redraw, - radius_svga_multiview_config -}; - -const device_t radius_svga_multiview_mca_device = -{ - "Radius SVGA Multiview MCA (HT209)", - "radius_mc", - DEVICE_MCA, - 0x7152, /*HT209*/ - radius_svga_multiview_init, - ht216_close, - NULL, - { radius_svga_multiview_available }, - ht216_speed_changed, - ht216_force_redraw, - NULL +const device_t radius_svga_multiview_mca_device = { + .name = "Radius SVGA Multiview MCA (HT209)", + .internal_name = "radius_mc", + .flags = DEVICE_MCA, + .local = 0x7152, /*HT209*/ + .init = radius_svga_multiview_init, + .close = ht216_close, + .reset = NULL, + { .available = radius_svga_multiview_available }, + .speed_changed = ht216_speed_changed, + .force_redraw = ht216_force_redraw, + .config = NULL }; diff --git a/src/video/vid_ibm_rgb528_ramdac.c b/src/video/vid_ibm_rgb528_ramdac.c index 8b2e11621..1b19a3a0f 100644 --- a/src/video/vid_ibm_rgb528_ramdac.c +++ b/src/video/vid_ibm_rgb528_ramdac.c @@ -1,18 +1,18 @@ /* - * 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. + * 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. + * This file is part of the 86Box distribution. * - * Emulation of the IBM RGB 528 true colour RAMDAC. + * Emulation of the IBM RGB 528 true colour RAMDAC. * * * - * Authors: Miran Grca, + * Authors: Miran Grca, * - * Copyright 2020 Miran Grca. + * Copyright 2020 Miran Grca. */ #include #include @@ -25,520 +25,510 @@ #include <86box/timer.h> #include <86box/video.h> #include <86box/vid_svga.h> +#include <86box/plat_unused.h> - -typedef union { - uint8_t pixel; - struct { - uint8_t b :2, g :3, r :2; - }; +typedef union ibm_rgb528_pixel8_t { + uint8_t pixel; + struct { + uint8_t b : 2; + uint8_t g : 3; + uint8_t r : 2; + }; } ibm_rgb528_pixel8_t; -typedef union { - uint16_t pixel; - struct { - uint16_t b_ :5, g_ :6, r_ :5; - }; - struct { - uint16_t b :5, g :5, r :5, c :1; - }; +typedef union ibm_rgb528_pixel16_t { + uint16_t pixel; + struct { + uint16_t b_ : 5; + uint16_t g_ : 6; + uint16_t r_ : 5; + }; + struct { + uint16_t b : 5; + uint16_t g : 5; + uint16_t r : 5; + uint16_t c : 1; + }; } ibm_rgb528_pixel16_t; -typedef union { - uint32_t pixel; - struct { - uint8_t b, g, r, a; - }; +typedef union ibm_rgb528_pixel32_t { + uint32_t pixel; + struct { + uint8_t b; + uint8_t g; + uint8_t r; + uint8_t a; + }; } ibm_rgb528_pixel32_t; -typedef struct -{ - PALETTE extpal; - uint32_t extpallook[256]; - uint8_t indexed_data[2048]; - uint8_t cursor32_data[256]; - uint8_t cursor64_data[1024]; - uint8_t palettes[3][256]; - ibm_rgb528_pixel32_t extra_pal[4]; - int16_t hwc_y, hwc_x; - uint16_t index, smlc_part; - uint8_t cmd_r0; - uint8_t cmd_r1; - uint8_t cmd_r2; - uint8_t cmd_r3; - uint8_t cmd_r4; - uint8_t status, indx_cntl; - uint8_t cursor_array, - cursor_hotspot_x, cursor_hotspot_y; +typedef struct ibm_rgb528_ramdac_t { + PALETTE extpal; + uint32_t extpallook[256]; + uint8_t indexed_data[2048]; + uint8_t cursor32_data[256]; + uint8_t cursor64_data[1024]; + uint8_t palettes[3][256]; + ibm_rgb528_pixel32_t extra_pal[4]; + int16_t hwc_y; + int16_t hwc_x; + uint16_t index; + uint16_t smlc_part; + uint8_t cmd_r0; + uint8_t cmd_r1; + uint8_t cmd_r2; + uint8_t cmd_r3; + uint8_t cmd_r4; + uint8_t status; + uint8_t indx_cntl; + uint8_t cursor_array; + uint8_t cursor_hotspot_x; + uint8_t cursor_hotspot_y; } ibm_rgb528_ramdac_t; - void ibm_rgb528_render_4bpp(svga_t *svga) { - int x; - uint32_t *p; - ibm_rgb528_pixel32_t dat_out; - uint8_t dat; - uint32_t dat32 = 0x00000000; - uint64_t dat64 = 0x0000000000000000ULL; - uint64_t dat642 = 0x0000000000000000ULL; - ibm_rgb528_ramdac_t *ramdac = (ibm_rgb528_ramdac_t *) svga->ramdac; - uint8_t b8_dcol = (ramdac->indexed_data[0x0c] & 0xc0) >> 6; - uint8_t partition = (ramdac->indexed_data[0x07] & 0x0f) << 4; - uint8_t swap_word = ramdac->indexed_data[0x72] & 0x10; - uint8_t swap_nib = ramdac->indexed_data[0x72] & 0x21; - uint8_t vram_size = ramdac->indexed_data[0x70] & 0x03; + uint32_t *p; + ibm_rgb528_pixel32_t dat_out; + uint8_t dat; + uint32_t dat32 = 0x00000000; + uint64_t dat64 = 0x0000000000000000ULL; + uint64_t dat642 = 0x0000000000000000ULL; + const ibm_rgb528_ramdac_t *ramdac = (ibm_rgb528_ramdac_t *) svga->ramdac; + uint8_t b8_dcol = (ramdac->indexed_data[0x0c] & 0xc0) >> 6; + uint8_t partition = (ramdac->indexed_data[0x07] & 0x0f) << 4; + uint8_t swap_word = ramdac->indexed_data[0x72] & 0x10; + uint8_t swap_nib = ramdac->indexed_data[0x72] & 0x21; + uint8_t vram_size = ramdac->indexed_data[0x70] & 0x03; if ((svga->displine + svga->y_add) < 0) - return; + return; - if (svga->changedvram[svga->ma >> 12] || svga->changedvram[(svga->ma >> 12) + 1] || svga->changedvram[(svga->ma >> 12) + 2] || svga->fullchange) { - p = &buffer32->line[svga->displine + svga->y_add][svga->x_add]; - - if (svga->firstline_draw == 2000) - svga->firstline_draw = svga->displine; - svga->lastline_draw = svga->displine; + if (svga->changedvram[svga->ma >> 12] || svga->changedvram[(svga->ma >> 12) + 1] || svga->changedvram[(svga->ma >> 12) + 2] || svga->fullchange) { + p = &buffer32->line[svga->displine + svga->y_add][svga->x_add]; - for (x = 0; x <= (svga->hdisp + svga->scrollcache); x++) { - if (svga->crtc[0x17] & 0x80) { - if (vram_size == 3) { - if (!(x & 31)) { - dat64 = *(uint64_t *)(&svga->vram[svga->ma]); - dat642 = *(uint64_t *)(&svga->vram[svga->ma + 8]); - if (swap_word) { - dat64 = (dat64 << 32ULL) | (dat64 >> 32ULL); - dat642 = (dat642 << 32ULL) | (dat642 >> 32ULL); - } - } - if (swap_nib) - dat = (((x & 16) ? dat642 : dat64) >> ((x & 15) << 2)) & 0xf; - else - dat = (((x & 16) ? dat642 : dat64) >> (((x & 15) << 2) ^ 4)) & 0xf; - } else if (vram_size == 1) { - if (!(x & 15)) { - dat64 = *(uint64_t *)(&svga->vram[svga->ma]); - if (swap_word) - dat64 = (dat64 << 32ULL) | (dat64 >> 32ULL); - } - if (swap_nib) - dat = (dat64 >> ((x & 15) << 2)) & 0xf; - else - dat = (dat64 >> (((x & 15) << 2) ^ 4)) & 0xf; - } else { - if (!(x & 7)) - dat32 = *(uint32_t *)(&svga->vram[svga->ma]); - if (swap_nib) - dat = (dat32 >> ((x & 7) << 2)) & 0xf; - else - dat = (dat32 >> (((x & 7) << 2) ^ 4)) & 0xf; - } - } else - dat = 0x00000000; - if (b8_dcol == 0x00) { - dat_out.a = 0x00; - dat_out.r = ramdac->palettes[0][partition | dat]; - dat_out.g = ramdac->palettes[1][partition | dat]; - dat_out.b = ramdac->palettes[2][partition | dat]; - } else - dat_out.pixel = video_8togs[dat]; - if (svga->lowres) { - p[x << 1] = p[(x << 1) + 1] = dat_out.pixel & 0xffffff; - } else - p[x] = dat_out.pixel & 0xffffff; + if (svga->firstline_draw == 2000) + svga->firstline_draw = svga->displine; + svga->lastline_draw = svga->displine; - if ((vram_size == 3) && ((x & 31) == 31)) - svga->ma = (svga->ma + 16) & svga->vram_display_mask; - if ((vram_size == 1) && ((x & 15) == 15)) - svga->ma = (svga->ma + 8) & svga->vram_display_mask; - else if ((!vram_size) && ((x & 7) == 7)) - svga->ma = (svga->ma + 4) & svga->vram_display_mask; - } + for (int x = 0; x <= (svga->hdisp + svga->scrollcache); x++) { + if (vram_size == 3) { + if (!(x & 31)) { + dat64 = *(uint64_t *) (&svga->vram[svga->ma]); + dat642 = *(uint64_t *) (&svga->vram[svga->ma + 8]); + if (swap_word) { + dat64 = (dat64 << 32ULL) | (dat64 >> 32ULL); + dat642 = (dat642 << 32ULL) | (dat642 >> 32ULL); + } + } + if (swap_nib) + dat = (((x & 16) ? dat642 : dat64) >> ((x & 15) << 2)) & 0xf; + else + dat = (((x & 16) ? dat642 : dat64) >> (((x & 15) << 2) ^ 4)) & 0xf; + } else if (vram_size == 1) { + if (!(x & 15)) { + dat64 = *(uint64_t *) (&svga->vram[svga->ma]); + if (swap_word) + dat64 = (dat64 << 32ULL) | (dat64 >> 32ULL); + } + if (swap_nib) + dat = (dat64 >> ((x & 15) << 2)) & 0xf; + else + dat = (dat64 >> (((x & 15) << 2) ^ 4)) & 0xf; + } else { + if (!(x & 7)) + dat32 = *(uint32_t *) (&svga->vram[svga->ma]); + if (swap_nib) + dat = (dat32 >> ((x & 7) << 2)) & 0xf; + else + dat = (dat32 >> (((x & 7) << 2) ^ 4)) & 0xf; + } + if (b8_dcol == 0x00) { + dat_out.a = 0x00; + dat_out.r = ramdac->palettes[0][partition | dat]; + dat_out.g = ramdac->palettes[1][partition | dat]; + dat_out.b = ramdac->palettes[2][partition | dat]; + } else + dat_out.pixel = video_8togs[dat]; + if (svga->lowres) { + p[x << 1] = p[(x << 1) + 1] = dat_out.pixel & 0xffffff; + } else + p[x] = dat_out.pixel & 0xffffff; + + if ((vram_size == 3) && ((x & 31) == 31)) + svga->ma = (svga->ma + 16) & svga->vram_display_mask; + if ((vram_size == 1) && ((x & 15) == 15)) + svga->ma = (svga->ma + 8) & svga->vram_display_mask; + else if ((!vram_size) && ((x & 7) == 7)) + svga->ma = (svga->ma + 4) & svga->vram_display_mask; + } } } - void ibm_rgb528_render_8bpp(svga_t *svga) { - int x; - uint32_t *p; - ibm_rgb528_pixel32_t dat_out; - uint8_t dat; - uint32_t dat32 = 0x00000000; - uint64_t dat64 = 0x0000000000000000ULL; - uint64_t dat642 = 0x0000000000000000ULL; - ibm_rgb528_ramdac_t *ramdac = (ibm_rgb528_ramdac_t *) svga->ramdac; - uint8_t b8_dcol = (ramdac->indexed_data[0x0c] & 0xc0) >> 6; - uint8_t swap_word = ramdac->indexed_data[0x72] & 0x10; - uint8_t vram_size = ramdac->indexed_data[0x70] & 0x03; + uint32_t *p; + ibm_rgb528_pixel32_t dat_out; + uint8_t dat; + uint32_t dat32 = 0x00000000; + uint64_t dat64 = 0x0000000000000000ULL; + uint64_t dat642 = 0x0000000000000000ULL; + const ibm_rgb528_ramdac_t *ramdac = (ibm_rgb528_ramdac_t *) svga->ramdac; + uint8_t b8_dcol = (ramdac->indexed_data[0x0c] & 0xc0) >> 6; + uint8_t swap_word = ramdac->indexed_data[0x72] & 0x10; + uint8_t vram_size = ramdac->indexed_data[0x70] & 0x03; if ((svga->displine + svga->y_add) < 0) - return; + return; - if (svga->changedvram[svga->ma >> 12] || svga->changedvram[(svga->ma >> 12) + 1] || svga->changedvram[(svga->ma >> 12) + 2] || svga->fullchange) { - p = &buffer32->line[svga->displine + svga->y_add][svga->x_add]; - - if (svga->firstline_draw == 2000) - svga->firstline_draw = svga->displine; - svga->lastline_draw = svga->displine; + if (svga->changedvram[svga->ma >> 12] || svga->changedvram[(svga->ma >> 12) + 1] || svga->changedvram[(svga->ma >> 12) + 2] || svga->fullchange) { + p = &buffer32->line[svga->displine + svga->y_add][svga->x_add]; - for (x = 0; x <= (svga->hdisp + svga->scrollcache); x++) { - if (svga->crtc[0x17] & 0x80) { - if (vram_size == 3) { - if (!(x & 15)) { - dat64 = *(uint64_t *)(&svga->vram[svga->ma]); - dat642 = *(uint64_t *)(&svga->vram[svga->ma + 8]); - if (swap_word) { - dat64 = (dat64 << 32ULL) | (dat64 >> 32ULL); - dat642 = (dat642 << 32ULL) | (dat642 >> 32ULL); - } - } - dat = (((x & 8) ? dat642 : dat64) >> ((x & 7) << 3)) & 0xff; - } else if (vram_size == 1) { - if (!(x & 7)) { - dat64 = *(uint64_t *)(&svga->vram[svga->ma]); - if (swap_word) - dat64 = (dat64 << 32ULL) | (dat64 >> 32ULL); - } - dat = (dat64 >> ((x & 7) << 3)) & 0xff; - } else { - if (!(x & 3)) - dat32 = *(uint32_t *)(&svga->vram[svga->ma]); - dat = (dat32 >> ((x & 3) << 3)) & 0xff; - } - } else - dat = 0x00000000; - if (b8_dcol == 0x00) { - dat_out.a = 0x00; - dat_out.r = ramdac->palettes[0][dat]; - dat_out.g = ramdac->palettes[1][dat]; - dat_out.b = ramdac->palettes[2][dat]; - } else - dat_out.pixel = video_8togs[dat]; - if (svga->lowres) { - p[x << 1] = p[(x << 1) + 1] = dat_out.pixel & 0xffffff; - } else - p[x] = dat_out.pixel & 0xffffff; + if (svga->firstline_draw == 2000) + svga->firstline_draw = svga->displine; + svga->lastline_draw = svga->displine; - if ((vram_size == 3) && ((x & 15) == 15)) - svga->ma = (svga->ma + 16) & svga->vram_display_mask; - else if ((vram_size == 1) && ((x & 7) == 7)) - svga->ma = (svga->ma + 8) & svga->vram_display_mask; - else if ((!vram_size) && ((x & 3) == 3)) - svga->ma = (svga->ma + 4) & svga->vram_display_mask; - } + for (int x = 0; x <= (svga->hdisp + svga->scrollcache); x++) { + if (vram_size == 3) { + if (!(x & 15)) { + dat64 = *(uint64_t *) (&svga->vram[svga->ma]); + dat642 = *(uint64_t *) (&svga->vram[svga->ma + 8]); + if (swap_word) { + dat64 = (dat64 << 32ULL) | (dat64 >> 32ULL); + dat642 = (dat642 << 32ULL) | (dat642 >> 32ULL); + } + } + dat = (((x & 8) ? dat642 : dat64) >> ((x & 7) << 3)) & 0xff; + } else if (vram_size == 1) { + if (!(x & 7)) { + dat64 = *(uint64_t *) (&svga->vram[svga->ma]); + if (swap_word) + dat64 = (dat64 << 32ULL) | (dat64 >> 32ULL); + } + dat = (dat64 >> ((x & 7) << 3)) & 0xff; + } else { + if (!(x & 3)) + dat32 = *(uint32_t *) (&svga->vram[svga->ma]); + dat = (dat32 >> ((x & 3) << 3)) & 0xff; + } + if (b8_dcol == 0x00) { + dat_out.a = 0x00; + dat_out.r = ramdac->palettes[0][dat]; + dat_out.g = ramdac->palettes[1][dat]; + dat_out.b = ramdac->palettes[2][dat]; + } else + dat_out.pixel = video_8togs[dat]; + if (svga->lowres) { + p[x << 1] = p[(x << 1) + 1] = dat_out.pixel & 0xffffff; + } else + p[x] = dat_out.pixel & 0xffffff; + + if ((vram_size == 3) && ((x & 15) == 15)) + svga->ma = (svga->ma + 16) & svga->vram_display_mask; + else if ((vram_size == 1) && ((x & 7) == 7)) + svga->ma = (svga->ma + 8) & svga->vram_display_mask; + else if ((!vram_size) && ((x & 3) == 3)) + svga->ma = (svga->ma + 4) & svga->vram_display_mask; + } } } - void ibm_rgb528_render_15_16bpp(svga_t *svga) { - int x; - uint32_t *p; - ibm_rgb528_pixel16_t *dat_ex; - ibm_rgb528_pixel32_t dat_out; - uint16_t dat; - uint32_t dat32 = 0x00000000; - uint64_t dat64 = 0x0000000000000000ULL; - uint64_t dat642 = 0x0000000000000000ULL; - ibm_rgb528_ramdac_t *ramdac = (ibm_rgb528_ramdac_t *) svga->ramdac; - uint8_t b16_dcol = (ramdac->indexed_data[0x0c] & 0xc0) >> 6; - uint8_t by16_pol = ramdac->indexed_data[0x0c] & 0x20; - uint8_t b555_565 = ramdac->indexed_data[0x0c] & 0x02; - uint8_t bspr_cnt = ramdac->indexed_data[0x0c] & 0x01; - uint8_t partition = (ramdac->indexed_data[0x07] & 0x0e) << 4; - uint8_t b6bit_lin = ramdac->indexed_data[0x07] & 0x80; - uint8_t swaprb = ramdac->indexed_data[0x72] & 0x80; - uint8_t swap_word = ramdac->indexed_data[0x72] & 0x10; - uint8_t vram_size = ramdac->indexed_data[0x70] & 0x01, temp; + uint32_t *p; + ibm_rgb528_pixel16_t *dat_ex; + ibm_rgb528_pixel32_t dat_out; + uint16_t dat; + uint32_t dat32 = 0x00000000; + uint64_t dat64 = 0x0000000000000000ULL; + uint64_t dat642 = 0x0000000000000000ULL; + const ibm_rgb528_ramdac_t *ramdac = (ibm_rgb528_ramdac_t *) svga->ramdac; + uint8_t b16_dcol = (ramdac->indexed_data[0x0c] & 0xc0) >> 6; + uint8_t by16_pol = ramdac->indexed_data[0x0c] & 0x20; + uint8_t b555_565 = ramdac->indexed_data[0x0c] & 0x02; + uint8_t bspr_cnt = ramdac->indexed_data[0x0c] & 0x01; + uint8_t partition = (ramdac->indexed_data[0x07] & 0x0e) << 4; + uint8_t b6bit_lin = ramdac->indexed_data[0x07] & 0x80; + uint8_t swaprb = ramdac->indexed_data[0x72] & 0x80; + uint8_t swap_word = ramdac->indexed_data[0x72] & 0x10; + uint8_t vram_size = ramdac->indexed_data[0x70] & 0x01; + uint8_t temp; if ((svga->displine + svga->y_add) < 0) - return; + return; if (b555_565 && (b16_dcol != 0x01)) - partition &= 0xc0; + partition &= 0xc0; - if (svga->changedvram[svga->ma >> 12] || svga->changedvram[(svga->ma >> 12) + 1] || svga->changedvram[(svga->ma >> 12) + 2] || svga->fullchange) { - p = &buffer32->line[svga->displine + svga->y_add][svga->x_add]; - - if (svga->firstline_draw == 2000) - svga->firstline_draw = svga->displine; - svga->lastline_draw = svga->displine; + if (svga->changedvram[svga->ma >> 12] || svga->changedvram[(svga->ma >> 12) + 1] || svga->changedvram[(svga->ma >> 12) + 2] || svga->fullchange) { + p = &buffer32->line[svga->displine + svga->y_add][svga->x_add]; - for (x = 0; x <= (svga->hdisp + svga->scrollcache); x++) { - if (svga->crtc[0x17] & 0x80) { - if (vram_size == 2) { - if (!(x & 7)) { - dat64 = *(uint64_t *)(&svga->vram[svga->ma]); - dat642 = *(uint64_t *)(&svga->vram[svga->ma + 8]); - if (swap_word) { - dat64 = (dat64 << 32ULL) | (dat64 >> 32ULL); - dat642 = (dat64 << 32ULL) | (dat642 >> 32ULL); - } - } - dat = (((x & 4) ? dat642 : dat64) >> ((x & 3) << 4)) & 0xffff; - } else if (vram_size == 1) { - if (!(x & 3)) { - dat64 = *(uint64_t *)(&svga->vram[svga->ma]); - if (swap_word) - dat64 = (dat64 << 32ULL) | (dat64 >> 32ULL); - } - dat = (dat64 >> ((x & 3) << 4)) & 0xffff; - } else { - if (!(x & 1)) - dat32 = *(uint32_t *)(&svga->vram[svga->ma]); - dat = (dat32 >> ((x & 1) << 4)) & 0xffff; - } - } else - dat = 0x00000000; - dat_ex = (ibm_rgb528_pixel16_t *) &dat; - if (b555_565 && (b16_dcol != 0x01)) { - if (swaprb) { - temp = dat_ex->r_; - dat_ex->r_ = dat_ex->b_; - dat_ex->b_ = temp; - } - if (b16_dcol == 0x00) { - dat_out.a = 0x00; - if (bspr_cnt) { - dat_out.r = ramdac->palettes[0][partition | dat_ex->r_]; - dat_out.g = ramdac->palettes[1][partition | dat_ex->g_]; - dat_out.b = ramdac->palettes[2][partition | dat_ex->b_]; - } else { - dat_out.r = ramdac->palettes[0][dat_ex->r_ << 3]; - dat_out.g = ramdac->palettes[1][dat_ex->g_ << 2]; - dat_out.b = ramdac->palettes[2][dat_ex->b_ << 3]; - } - if ((svga->ramdac_type != RAMDAC_8BIT) && !b6bit_lin) { - dat_out.r |= ((dat_out.r & 0xc0) >> 6); - dat_out.g |= ((dat_out.g & 0xc0) >> 6); - dat_out.b |= ((dat_out.b & 0xc0) >> 6); - } - } else - dat_out.pixel = video_16to32[dat_ex->pixel]; - } else { - if (swaprb) { - temp = dat_ex->r; - dat_ex->r = dat_ex->b; - dat_ex->b = temp; - } - if (by16_pol) - dat ^= 0x8000; - if ((b16_dcol == 0x00) || ((b16_dcol == 0x01) && !(dat & 0x8000))) { - dat_out.a = 0x00; - if (bspr_cnt) { - dat_out.r = ramdac->palettes[0][partition | dat_ex->r]; - dat_out.g = ramdac->palettes[1][partition | dat_ex->g]; - dat_out.b = ramdac->palettes[2][partition | dat_ex->b]; - } else { - dat_out.r = ramdac->palettes[0][dat_ex->r << 3]; - dat_out.g = ramdac->palettes[1][dat_ex->g << 3]; - dat_out.b = ramdac->palettes[2][dat_ex->b << 3]; - } - if ((svga->ramdac_type != RAMDAC_8BIT) && !b6bit_lin) { - dat_out.r |= ((dat_out.r & 0xc0) >> 6); - dat_out.g |= ((dat_out.g & 0xc0) >> 6); - dat_out.b |= ((dat_out.b & 0xc0) >> 6); - } - } else - dat_out.pixel = video_15to32[dat_ex->pixel & 0x7fff]; - } - if (svga->lowres) { - p[x << 1] = p[(x << 1) + 1] = dat_out.pixel & 0xffffff; - } else - p[x] = dat_out.pixel & 0xffffff; + if (svga->firstline_draw == 2000) + svga->firstline_draw = svga->displine; + svga->lastline_draw = svga->displine; - if ((vram_size == 3) && ((x & 7) == 7)) - svga->ma = (svga->ma + 16) & svga->vram_display_mask; - else if ((vram_size == 1) && ((x & 3) == 3)) - svga->ma = (svga->ma + 8) & svga->vram_display_mask; - else if (!vram_size && ((x & 1) == 1)) - svga->ma = (svga->ma + 4) & svga->vram_display_mask; - } + for (int x = 0; x <= (svga->hdisp + svga->scrollcache); x++) { + if (vram_size == 2) { + if (!(x & 7)) { + dat64 = *(uint64_t *) (&svga->vram[svga->ma]); + dat642 = *(uint64_t *) (&svga->vram[svga->ma + 8]); + if (swap_word) { + dat64 = (dat64 << 32ULL) | (dat64 >> 32ULL); + dat642 = (dat64 << 32ULL) | (dat642 >> 32ULL); + } + } + dat = (((x & 4) ? dat642 : dat64) >> ((x & 3) << 4)) & 0xffff; + } else if (vram_size == 1) { + if (!(x & 3)) { + dat64 = *(uint64_t *) (&svga->vram[svga->ma]); + if (swap_word) + dat64 = (dat64 << 32ULL) | (dat64 >> 32ULL); + } + dat = (dat64 >> ((x & 3) << 4)) & 0xffff; + } else { + if (!(x & 1)) + dat32 = *(uint32_t *) (&svga->vram[svga->ma]); + dat = (dat32 >> ((x & 1) << 4)) & 0xffff; + } + dat_ex = (ibm_rgb528_pixel16_t *) &dat; + if (b555_565 && (b16_dcol != 0x01)) { + if (swaprb) { + temp = dat_ex->r_; + dat_ex->r_ = dat_ex->b_; + dat_ex->b_ = temp; + } + if (b16_dcol == 0x00) { + dat_out.a = 0x00; + if (bspr_cnt) { + dat_out.r = ramdac->palettes[0][partition | dat_ex->r_]; + dat_out.g = ramdac->palettes[1][partition | dat_ex->g_]; + dat_out.b = ramdac->palettes[2][partition | dat_ex->b_]; + } else { + dat_out.r = ramdac->palettes[0][dat_ex->r_ << 3]; + dat_out.g = ramdac->palettes[1][dat_ex->g_ << 2]; + dat_out.b = ramdac->palettes[2][dat_ex->b_ << 3]; + } + if ((svga->ramdac_type != RAMDAC_8BIT) && !b6bit_lin) { + dat_out.r |= ((dat_out.r & 0xc0) >> 6); + dat_out.g |= ((dat_out.g & 0xc0) >> 6); + dat_out.b |= ((dat_out.b & 0xc0) >> 6); + } + } else + dat_out.pixel = video_16to32[dat_ex->pixel]; + } else { + if (swaprb) { + temp = dat_ex->r; + dat_ex->r = dat_ex->b; + dat_ex->b = temp; + } + if (by16_pol) + dat ^= 0x8000; + if ((b16_dcol == 0x00) || ((b16_dcol == 0x01) && !(dat & 0x8000))) { + dat_out.a = 0x00; + if (bspr_cnt) { + dat_out.r = ramdac->palettes[0][partition | dat_ex->r]; + dat_out.g = ramdac->palettes[1][partition | dat_ex->g]; + dat_out.b = ramdac->palettes[2][partition | dat_ex->b]; + } else { + dat_out.r = ramdac->palettes[0][dat_ex->r << 3]; + dat_out.g = ramdac->palettes[1][dat_ex->g << 3]; + dat_out.b = ramdac->palettes[2][dat_ex->b << 3]; + } + if ((svga->ramdac_type != RAMDAC_8BIT) && !b6bit_lin) { + dat_out.r |= ((dat_out.r & 0xc0) >> 6); + dat_out.g |= ((dat_out.g & 0xc0) >> 6); + dat_out.b |= ((dat_out.b & 0xc0) >> 6); + } + } else + dat_out.pixel = video_15to32[dat_ex->pixel & 0x7fff]; + } + if (svga->lowres) { + p[x << 1] = p[(x << 1) + 1] = dat_out.pixel & 0xffffff; + } else + p[x] = dat_out.pixel & 0xffffff; + + if ((vram_size == 3) && ((x & 7) == 7)) + svga->ma = (svga->ma + 16) & svga->vram_display_mask; + else if ((vram_size == 1) && ((x & 3) == 3)) + svga->ma = (svga->ma + 8) & svga->vram_display_mask; + else if (!vram_size && ((x & 1) == 1)) + svga->ma = (svga->ma + 4) & svga->vram_display_mask; + } } } - void ibm_rgb528_render_24bpp(svga_t *svga) { - int x; - uint32_t *p; - ibm_rgb528_pixel32_t *dat_ex; - uint32_t dat; - uint64_t dat64[6]; - uint8_t *dat8 = (uint8_t *) dat64; - ibm_rgb528_ramdac_t *ramdac = (ibm_rgb528_ramdac_t *) svga->ramdac; - uint8_t b24_dcol = ramdac->indexed_data[0x0d] & 0x01; - uint8_t swaprb = ramdac->indexed_data[0x72] & 0x80; - uint8_t swap_word = ramdac->indexed_data[0x72] & 0x10; - uint8_t vram_size = ramdac->indexed_data[0x70] & 0x01; - uint8_t b6bit_lin = ramdac->indexed_data[0x07] & 0x80, temp; + uint32_t *p; + ibm_rgb528_pixel32_t *dat_ex; + uint32_t dat; + uint64_t dat64[6]; + uint8_t *dat8 = (uint8_t *) dat64; + const ibm_rgb528_ramdac_t *ramdac = (ibm_rgb528_ramdac_t *) svga->ramdac; + uint8_t b24_dcol = ramdac->indexed_data[0x0d] & 0x01; + uint8_t swaprb = ramdac->indexed_data[0x72] & 0x80; + uint8_t swap_word = ramdac->indexed_data[0x72] & 0x10; + uint8_t vram_size = ramdac->indexed_data[0x70] & 0x01; + uint8_t b6bit_lin = ramdac->indexed_data[0x07] & 0x80; + uint8_t temp; if ((svga->displine + svga->y_add) < 0) - return; + return; - if (svga->changedvram[svga->ma >> 12] || svga->changedvram[(svga->ma >> 12) + 1] || svga->changedvram[(svga->ma >> 12) + 2] || svga->fullchange) { - p = &buffer32->line[svga->displine + svga->y_add][svga->x_add]; - - if (svga->firstline_draw == 2000) - svga->firstline_draw = svga->displine; - svga->lastline_draw = svga->displine; + if (svga->changedvram[svga->ma >> 12] || svga->changedvram[(svga->ma >> 12) + 1] || svga->changedvram[(svga->ma >> 12) + 2] || svga->fullchange) { + p = &buffer32->line[svga->displine + svga->y_add][svga->x_add]; - for (x = 0; x <= (svga->hdisp + svga->scrollcache); x++) { - dat_ex = (ibm_rgb528_pixel32_t *) &dat; - if (svga->crtc[0x17] & 0x80) { - if (vram_size == 3) { - if ((x & 15) == 0) { - dat64[0] = *(uint64_t *)(&svga->vram[svga->ma & svga->vram_display_mask]); - dat64[1] = *(uint64_t *)(&svga->vram[(svga->ma + 8) & svga->vram_display_mask]); - dat64[2] = *(uint64_t *)(&svga->vram[(svga->ma + 16) & svga->vram_display_mask]); - dat64[3] = *(uint64_t *)(&svga->vram[(svga->ma + 24) & svga->vram_display_mask]); - dat64[4] = *(uint64_t *)(&svga->vram[(svga->ma + 32) & svga->vram_display_mask]); - dat64[5] = *(uint64_t *)(&svga->vram[(svga->ma + 40) & svga->vram_display_mask]); - if (swap_word) { - dat64[0] = (dat64[0] << 32ULL) | (dat64[0] >> 32ULL); - dat64[1] = (dat64[1] << 32ULL) | (dat64[1] >> 32ULL); - dat64[2] = (dat64[2] << 32ULL) | (dat64[2] >> 32ULL); - dat64[3] = (dat64[3] << 32ULL) | (dat64[3] >> 32ULL); - dat64[4] = (dat64[4] << 32ULL) | (dat64[4] >> 32ULL); - dat64[5] = (dat64[5] << 32ULL) | (dat64[5] >> 32ULL); - } - } - dat_ex = (ibm_rgb528_pixel32_t *) &(dat8[((x & 15) * 3)]); - } else if (vram_size == 1) { - if ((x & 7) == 0) { - dat64[0] = *(uint64_t *)(&svga->vram[svga->ma & svga->vram_display_mask]); - dat64[1] = *(uint64_t *)(&svga->vram[(svga->ma + 8) & svga->vram_display_mask]); - dat64[2] = *(uint64_t *)(&svga->vram[(svga->ma + 16) & svga->vram_display_mask]); - if (swap_word) { - dat64[0] = (dat64[0] << 32ULL) | (dat64[0] >> 32ULL); - dat64[1] = (dat64[1] << 32ULL) | (dat64[1] >> 32ULL); - dat64[2] = (dat64[2] << 32ULL) | (dat64[2] >> 32ULL); - } - } - dat_ex = (ibm_rgb528_pixel32_t *) &(dat8[((x & 7) * 3)]); - } else - dat = 0x00000000; - } else - dat = 0x00000000; - if (swaprb) { - temp = dat_ex->r; - dat_ex->r = dat_ex->b; - dat_ex->b = temp; - } - if (b24_dcol == 0x00) { - dat_ex->a = 0x00; - dat_ex->r = ramdac->palettes[0][dat_ex->r]; - dat_ex->g = ramdac->palettes[1][dat_ex->g]; - dat_ex->g = ramdac->palettes[2][dat_ex->b]; - if ((svga->ramdac_type != RAMDAC_8BIT) && !b6bit_lin) { - dat_ex->r |= ((dat_ex->r & 0xc0) >> 6); - dat_ex->g |= ((dat_ex->g & 0xc0) >> 6); - dat_ex->b |= ((dat_ex->b & 0xc0) >> 6); - } - } - if (svga->lowres) { - p[x << 1] = p[(x << 1) + 1] = dat_ex->pixel & 0xffffff; - } else - p[x] = dat_ex->pixel & 0xffffff; + if (svga->firstline_draw == 2000) + svga->firstline_draw = svga->displine; + svga->lastline_draw = svga->displine; - if ((vram_size == 3) && ((x & 15) == 15)) - svga->ma = (svga->ma + 48) & svga->vram_display_mask; - else if ((vram_size == 1) && ((x & 7) == 7)) - svga->ma = (svga->ma + 24) & svga->vram_display_mask; - } + for (int x = 0; x <= (svga->hdisp + svga->scrollcache); x++) { + dat_ex = (ibm_rgb528_pixel32_t *) &dat; + if (vram_size == 3) { + if ((x & 15) == 0) { + dat64[0] = *(uint64_t *) (&svga->vram[svga->ma & svga->vram_display_mask]); + dat64[1] = *(uint64_t *) (&svga->vram[(svga->ma + 8) & svga->vram_display_mask]); + dat64[2] = *(uint64_t *) (&svga->vram[(svga->ma + 16) & svga->vram_display_mask]); + dat64[3] = *(uint64_t *) (&svga->vram[(svga->ma + 24) & svga->vram_display_mask]); + dat64[4] = *(uint64_t *) (&svga->vram[(svga->ma + 32) & svga->vram_display_mask]); + dat64[5] = *(uint64_t *) (&svga->vram[(svga->ma + 40) & svga->vram_display_mask]); + if (swap_word) { + dat64[0] = (dat64[0] << 32ULL) | (dat64[0] >> 32ULL); + dat64[1] = (dat64[1] << 32ULL) | (dat64[1] >> 32ULL); + dat64[2] = (dat64[2] << 32ULL) | (dat64[2] >> 32ULL); + dat64[3] = (dat64[3] << 32ULL) | (dat64[3] >> 32ULL); + dat64[4] = (dat64[4] << 32ULL) | (dat64[4] >> 32ULL); + dat64[5] = (dat64[5] << 32ULL) | (dat64[5] >> 32ULL); + } + } + dat_ex = (ibm_rgb528_pixel32_t *) &(dat8[(x & 15) * 3]); + } else if (vram_size == 1) { + if ((x & 7) == 0) { + dat64[0] = *(uint64_t *) (&svga->vram[svga->ma & svga->vram_display_mask]); + dat64[1] = *(uint64_t *) (&svga->vram[(svga->ma + 8) & svga->vram_display_mask]); + dat64[2] = *(uint64_t *) (&svga->vram[(svga->ma + 16) & svga->vram_display_mask]); + if (swap_word) { + dat64[0] = (dat64[0] << 32ULL) | (dat64[0] >> 32ULL); + dat64[1] = (dat64[1] << 32ULL) | (dat64[1] >> 32ULL); + dat64[2] = (dat64[2] << 32ULL) | (dat64[2] >> 32ULL); + } + } + dat_ex = (ibm_rgb528_pixel32_t *) &(dat8[(x & 7) * 3]); + } else + dat = 0x00000000; + if (swaprb) { + temp = dat_ex->r; + dat_ex->r = dat_ex->b; + dat_ex->b = temp; + } + if (b24_dcol == 0x00) { + dat_ex->a = 0x00; + dat_ex->r = ramdac->palettes[0][dat_ex->r]; + dat_ex->g = ramdac->palettes[1][dat_ex->g]; + dat_ex->g = ramdac->palettes[2][dat_ex->b]; + if ((svga->ramdac_type != RAMDAC_8BIT) && !b6bit_lin) { + dat_ex->r |= ((dat_ex->r & 0xc0) >> 6); + dat_ex->g |= ((dat_ex->g & 0xc0) >> 6); + dat_ex->b |= ((dat_ex->b & 0xc0) >> 6); + } + } + if (svga->lowres) { + p[x << 1] = p[(x << 1) + 1] = dat_ex->pixel & 0xffffff; + } else + p[x] = dat_ex->pixel & 0xffffff; + + if ((vram_size == 3) && ((x & 15) == 15)) + svga->ma = (svga->ma + 48) & svga->vram_display_mask; + else if ((vram_size == 1) && ((x & 7) == 7)) + svga->ma = (svga->ma + 24) & svga->vram_display_mask; + } } } - void ibm_rgb528_render_32bpp(svga_t *svga) { - int x; - uint32_t *p; - ibm_rgb528_pixel32_t *dat_ex; - uint32_t dat = 0x00000000; - uint64_t dat64 = 0x0000000000000000ULL; - uint64_t dat642 = 0x0000000000000000ULL; - ibm_rgb528_ramdac_t *ramdac = (ibm_rgb528_ramdac_t *) svga->ramdac; - uint8_t b32_dcol = ramdac->indexed_data[0x0e] & 0x03; - uint8_t by32_pol = ramdac->indexed_data[0x0e] & 0x04; - uint8_t swaprb = ramdac->indexed_data[0x72] & 0x80; - uint8_t swap_word = ramdac->indexed_data[0x72] & 0x10; - uint8_t vram_size = ramdac->indexed_data[0x70] & 0x01; - uint8_t b6bit_lin = ramdac->indexed_data[0x07] & 0x80, temp; + uint32_t *p; + ibm_rgb528_pixel32_t *dat_ex; + uint32_t dat = 0x00000000; + uint64_t dat64 = 0x0000000000000000ULL; + uint64_t dat642 = 0x0000000000000000ULL; + const ibm_rgb528_ramdac_t *ramdac = (ibm_rgb528_ramdac_t *) svga->ramdac; + uint8_t b32_dcol = ramdac->indexed_data[0x0e] & 0x03; + uint8_t by32_pol = ramdac->indexed_data[0x0e] & 0x04; + uint8_t swaprb = ramdac->indexed_data[0x72] & 0x80; + uint8_t swap_word = ramdac->indexed_data[0x72] & 0x10; + uint8_t vram_size = ramdac->indexed_data[0x70] & 0x01; + uint8_t b6bit_lin = ramdac->indexed_data[0x07] & 0x80; + uint8_t temp; if ((svga->displine + svga->y_add) < 0) - return; + return; - if (svga->changedvram[svga->ma >> 12] || svga->changedvram[(svga->ma >> 12) + 1] || svga->changedvram[(svga->ma >> 12) + 2] || svga->fullchange) { - p = &buffer32->line[svga->displine + svga->y_add][svga->x_add]; - - if (svga->firstline_draw == 2000) - svga->firstline_draw = svga->displine; - svga->lastline_draw = svga->displine; + if (svga->changedvram[svga->ma >> 12] || svga->changedvram[(svga->ma >> 12) + 1] || svga->changedvram[(svga->ma >> 12) + 2] || svga->fullchange) { + p = &buffer32->line[svga->displine + svga->y_add][svga->x_add]; - for (x = 0; x <= (svga->hdisp + svga->scrollcache); x++) { - if (svga->crtc[0x17] & 0x80) { - if (vram_size == 3) { - if (!(x & 3)) { - dat64 = *(uint64_t *)(&svga->vram[svga->ma]); - dat642 = *(uint64_t *)(&svga->vram[svga->ma + 8]); - if (swap_word) { - dat64 = (dat64 << 32ULL) | (dat64 >> 32ULL); - dat642 = (dat642 << 32ULL) | (dat642 >> 32ULL); - } - } - dat = (((x & 2) ? dat642 : dat64) >> ((x & 1ULL) << 5ULL)) & 0xffffffff; - } else if (vram_size == 1) { - if (!(x & 1)) { - dat64 = *(uint64_t *)(&svga->vram[svga->ma]); - if (swap_word) - dat64 = (dat64 << 32ULL) | (dat64 >> 32ULL); - } - dat = (dat64 >> ((x & 1ULL) << 5ULL)) & 0xffffffff; - } else - dat = *(uint32_t *)(&svga->vram[svga->ma]); - } else - dat = 0x00000000; - dat_ex = (ibm_rgb528_pixel32_t *) &dat; - if (swaprb) { - temp = dat_ex->r; - dat_ex->r = dat_ex->b; - dat_ex->b = temp; - } - if ((b32_dcol < 0x03) && (by32_pol)) - dat ^= 0x01000000; - if ((b32_dcol == 0x00) || ((b32_dcol == 0x01) && !(dat & 0x01000000))) { - dat_ex->a = 0x00; - dat_ex->r = ramdac->palettes[0][dat_ex->r]; - dat_ex->g = ramdac->palettes[1][dat_ex->g]; - dat_ex->g = ramdac->palettes[2][dat_ex->b]; - if ((svga->ramdac_type != RAMDAC_8BIT) && !b6bit_lin) { - dat_ex->r |= ((dat_ex->r & 0xc0) >> 6); - dat_ex->g |= ((dat_ex->g & 0xc0) >> 6); - dat_ex->b |= ((dat_ex->b & 0xc0) >> 6); - } - } - if (svga->lowres) { - p[x << 1] = p[(x << 1) + 1] = dat_ex->pixel & 0xffffff; - } else - p[x] = dat_ex->pixel & 0xffffff; + if (svga->firstline_draw == 2000) + svga->firstline_draw = svga->displine; + svga->lastline_draw = svga->displine; - if ((vram_size == 3) && ((x & 3) == 3)) - svga->ma = (svga->ma + 16) & svga->vram_display_mask; - else if ((vram_size == 1) && ((x & 1) == 1)) - svga->ma = (svga->ma + 8) & svga->vram_display_mask; - else if (!vram_size) - svga->ma = (svga->ma + 4) & svga->vram_display_mask; - } + for (int x = 0; x <= (svga->hdisp + svga->scrollcache); x++) { + if (vram_size == 3) { + if (!(x & 3)) { + dat64 = *(uint64_t *) (&svga->vram[svga->ma]); + dat642 = *(uint64_t *) (&svga->vram[svga->ma + 8]); + if (swap_word) { + dat64 = (dat64 << 32ULL) | (dat64 >> 32ULL); + dat642 = (dat642 << 32ULL) | (dat642 >> 32ULL); + } + } + dat = (((x & 2) ? dat642 : dat64) >> ((x & 1ULL) << 5ULL)) & 0xffffffff; + } else if (vram_size == 1) { + if (!(x & 1)) { + dat64 = *(uint64_t *) (&svga->vram[svga->ma]); + if (swap_word) + dat64 = (dat64 << 32ULL) | (dat64 >> 32ULL); + } + dat = (dat64 >> ((x & 1ULL) << 5ULL)) & 0xffffffff; + } else + dat = *(uint32_t *) (&svga->vram[svga->ma]); + dat_ex = (ibm_rgb528_pixel32_t *) &dat; + if (swaprb) { + temp = dat_ex->r; + dat_ex->r = dat_ex->b; + dat_ex->b = temp; + } + if ((b32_dcol < 0x03) && by32_pol) + dat ^= 0x01000000; + if ((b32_dcol == 0x00) || ((b32_dcol == 0x01) && !(dat & 0x01000000))) { + dat_ex->a = 0x00; + dat_ex->r = ramdac->palettes[0][dat_ex->r]; + dat_ex->g = ramdac->palettes[1][dat_ex->g]; + dat_ex->g = ramdac->palettes[2][dat_ex->b]; + if ((svga->ramdac_type != RAMDAC_8BIT) && !b6bit_lin) { + dat_ex->r |= ((dat_ex->r & 0xc0) >> 6); + dat_ex->g |= ((dat_ex->g & 0xc0) >> 6); + dat_ex->b |= ((dat_ex->b & 0xc0) >> 6); + } + } + if (svga->lowres) { + p[x << 1] = p[(x << 1) + 1] = dat_ex->pixel & 0xffffff; + } else + p[x] = dat_ex->pixel & 0xffffff; + + if ((vram_size == 3) && ((x & 3) == 3)) + svga->ma = (svga->ma + 16) & svga->vram_display_mask; + else if ((vram_size == 1) && ((x & 1) == 1)) + svga->ma = (svga->ma + 8) & svga->vram_display_mask; + else if (!vram_size) + svga->ma = (svga->ma + 4) & svga->vram_display_mask; + } } } - static void ibm_rgb528_set_bpp(ibm_rgb528_ramdac_t *ramdac, svga_t *svga) { @@ -546,390 +536,422 @@ ibm_rgb528_set_bpp(ibm_rgb528_ramdac_t *ramdac, svga_t *svga) uint8_t b555_565 = ramdac->indexed_data[0x0c] & 0x02; if (ramdac->indexed_data[0x071] & 0x01) - switch (ramdac->indexed_data[0x00a] & 0x07) { - case 0x02: - svga->bpp = 4; - break; - case 0x03: - default: - svga->bpp = 8; - break; - case 0x04: - if (b555_565 && (b16_dcol != 0x01)) - svga->bpp = 16; - else - svga->bpp = 15; - break; - case 0x05: - svga->bpp = 24; - break; - case 0x06: - svga->bpp = 32; - break; - } else - svga->bpp = 8; + switch (ramdac->indexed_data[0x00a] & 0x07) { + case 0x02: + svga->bpp = 4; + break; + case 0x03: + default: + svga->bpp = 8; + break; + case 0x04: + if (b555_565 && (b16_dcol != 0x01)) + svga->bpp = 16; + else + svga->bpp = 15; + break; + case 0x05: + svga->bpp = 24; + break; + case 0x06: + svga->bpp = 32; + break; + } + else + svga->bpp = 8; svga_recalctimings(svga); } - void -ibm_rgb528_ramdac_out(uint16_t addr, int rs2, uint8_t val, void *p, svga_t *svga) +ibm_rgb528_ramdac_out(uint16_t addr, int rs2, uint8_t val, void *priv, svga_t *svga) { - ibm_rgb528_ramdac_t *ramdac = (ibm_rgb528_ramdac_t *) p; - uint16_t index; - uint8_t rs = (addr & 0x03); - uint16_t da_mask = 0x03ff; - uint8_t updt_cntl = (ramdac->indexed_data[0x30] & 0x08); + ibm_rgb528_ramdac_t *ramdac = (ibm_rgb528_ramdac_t *) priv; + uint16_t index; + uint8_t rs = (addr & 0x03); + uint16_t da_mask = 0x03ff; + uint8_t updt_cntl = (ramdac->indexed_data[0x30] & 0x08); rs |= (!!rs2 << 2); switch (rs) { - case 0x00: /* Palette Write Index Register (RS value = 0000) */ - case 0x03: - svga->dac_pos = 0; - svga->dac_status = addr & 0x03; - svga->dac_addr = val; - if (svga->dac_status) - svga->dac_addr = (svga->dac_addr + 1) & da_mask; - break; - case 0x01: /* Palette Data Register (RS value = 0001) */ - index = svga->dac_addr & 255; - if (svga->ramdac_type == RAMDAC_8BIT) - ramdac->palettes[svga->dac_pos][index] = val; - else - ramdac->palettes[svga->dac_pos][index] = (val & 0x3f) << 2; - svga_out(addr, val, svga); - break; - case 0x02: /* Pixel Read Mask Register (RS value = 0010) */ - svga_out(addr, val, svga); - break; - case 0x04: - ramdac->index = (ramdac->index & 0x0700) | val; - if ((ramdac->index >= 0x0100) && (ramdac->index <= 0x04ff)) - ramdac->cursor_array = 1; - break; - case 0x05: - ramdac->index = (ramdac->index & 0x00ff) | ((val & 0x07) << 0x08); - if ((ramdac->index >= 0x0100) && (ramdac->index <= 0x04ff)) - ramdac->cursor_array = 1; - break; - case 0x06: - if ((ramdac->index < 0x0100) || (ramdac->index > 0x04ff) || ramdac->cursor_array) - ramdac->indexed_data[ramdac->index] = val; - switch (ramdac->index) { - case 0x00a: case 0x00c: - ibm_rgb528_set_bpp(ramdac, svga); - break; - case 0x030: - switch (val & 0xc0) { - case 0x00: - ramdac->smlc_part = 0x0100; - break; - case 0x40: - ramdac->smlc_part = 0x0200; - break; - case 0x80: - ramdac->smlc_part = 0x0300; - break; - case 0xc0: - ramdac->smlc_part = 0x0400; - break; - } - svga->dac_hwcursor.addr = ramdac->smlc_part; - svga->dac_hwcursor.xsize = svga->dac_hwcursor.ysize = (val & 0x04) ? 64 : 32; - svga->dac_hwcursor.ena = ((val & 0x03) != 0x00); - break; - case 0x031: - if (!updt_cntl) - break; - ramdac->hwc_x = (ramdac->hwc_x & 0xff00) | val; - svga->dac_hwcursor.x = ((int) ramdac->hwc_x) - ramdac->cursor_hotspot_x; - break; - case 0x032: - /* Sign-extend the sign bit (7) to the remaining bits (6-4). */ - val &= 0x8f; - if (val & 0x80) - val |= 0x70; - ramdac->indexed_data[ramdac->index] = val; - if (!updt_cntl) - break; - ramdac->hwc_x = (ramdac->hwc_x & 0x00ff) | (val << 8); - svga->dac_hwcursor.x = ((int) ramdac->hwc_x) - ramdac->cursor_hotspot_x; - break; - case 0x033: - if (!updt_cntl) - break; - ramdac->hwc_y = (ramdac->hwc_y & 0xff00) | val; - svga->dac_hwcursor.y = ((int) ramdac->hwc_y) - ramdac->cursor_hotspot_y; - break; - case 0x034: - /* Sign-extend the sign bit (7) to the remaining bits (6-4). */ - val &= 0x8f; - if (val & 0x80) - val |= 0x70; - ramdac->indexed_data[ramdac->index] = val; - if (updt_cntl) { - ramdac->hwc_y = (ramdac->hwc_y & 0x00ff) | (val << 8); - svga->dac_hwcursor.y = ((int) ramdac->hwc_y) - ramdac->cursor_hotspot_y; - } else { - ramdac->hwc_x = ramdac->indexed_data[0x031]; - ramdac->hwc_x |= (ramdac->indexed_data[0x032] << 8); - ramdac->hwc_y = ramdac->indexed_data[0x033]; - ramdac->hwc_y |= (val << 8); - svga->dac_hwcursor.x = ((int) ramdac->hwc_x) - ramdac->cursor_hotspot_x; - svga->dac_hwcursor.y = ((int) ramdac->hwc_y) - ramdac->cursor_hotspot_y; - } - break; - case 0x035: - if (svga->dac_hwcursor.xsize == 64) - ramdac->cursor_hotspot_x = (val & 0x3f); - else - ramdac->cursor_hotspot_x = (val & 0x1f); - svga->dac_hwcursor.x = ((int) ramdac->hwc_x) - ramdac->cursor_hotspot_x; - break; - case 0x036: - if (svga->dac_hwcursor.xsize == 64) - ramdac->cursor_hotspot_y = (val & 0x3f); - else - ramdac->cursor_hotspot_y = (val & 0x1f); - svga->dac_hwcursor.y = ((int) ramdac->hwc_y) - ramdac->cursor_hotspot_y; - break; - case 0x040: case 0x043: case 0x046: - ramdac->extra_pal[(ramdac->index - 0x40) / 3].r = val; - break; - case 0x041: case 0x044: case 0x047: - ramdac->extra_pal[(ramdac->index - 0x41) / 3].g = val; - break; - case 0x042: case 0x045: case 0x048: - ramdac->extra_pal[(ramdac->index - 0x42) / 3].b = val; - break; - case 0x060: - ramdac->extra_pal[3].r = val; - break; - case 0x061: - ramdac->extra_pal[3].g = val; - break; - case 0x062: - ramdac->extra_pal[3].b = val; - break; - case 0x071: - svga->ramdac_type = (val & 0x04) ? RAMDAC_8BIT : RAMDAC_6BIT; - ibm_rgb528_set_bpp(ramdac, svga); - break; - default: - break; - } - if (ramdac->indx_cntl) { - if (ramdac->index == 0x00ff) - ramdac->cursor_array = 0; - ramdac->index = (ramdac->index + 1) & 0x07ff; - } - break; - case 0x07: - ramdac->indx_cntl = val & 0x01; - break; + case 0x00: /* Palette Write Index Register (RS value = 0000) */ + case 0x03: + svga->dac_pos = 0; + svga->dac_status = addr & 0x03; + svga->dac_addr = val; + if (svga->dac_status) + svga->dac_addr = (svga->dac_addr + 1) & da_mask; + break; + case 0x01: /* Palette Data Register (RS value = 0001) */ + index = svga->dac_addr & 255; + if (svga->ramdac_type == RAMDAC_8BIT) + ramdac->palettes[svga->dac_pos][index] = val; + else + ramdac->palettes[svga->dac_pos][index] = (val & 0x3f) << 2; + svga_out(addr, val, svga); + break; + case 0x02: /* Pixel Read Mask Register (RS value = 0010) */ + svga_out(addr, val, svga); + break; + case 0x04: + ramdac->index = (ramdac->index & 0x0700) | val; + if ((ramdac->index >= 0x0100) && (ramdac->index <= 0x04ff)) + ramdac->cursor_array = 1; + break; + case 0x05: + ramdac->index = (ramdac->index & 0x00ff) | ((val & 0x07) << 0x08); + if ((ramdac->index >= 0x0100) && (ramdac->index <= 0x04ff)) + ramdac->cursor_array = 1; + break; + case 0x06: + if ((ramdac->index < 0x0100) || (ramdac->index > 0x04ff) || ramdac->cursor_array) + ramdac->indexed_data[ramdac->index] = val; + switch (ramdac->index) { + case 0x00a: + case 0x00c: + ibm_rgb528_set_bpp(ramdac, svga); + break; + case 0x030: + switch (val & 0xc0) { + case 0x00: + ramdac->smlc_part = 0x0100; + break; + case 0x40: + ramdac->smlc_part = 0x0200; + break; + case 0x80: + ramdac->smlc_part = 0x0300; + break; + case 0xc0: + ramdac->smlc_part = 0x0400; + break; + + default: + break; + } + svga->dac_hwcursor.addr = ramdac->smlc_part; + svga->dac_hwcursor.cur_xsize = svga->dac_hwcursor.cur_ysize = (val & 0x04) ? 64 : 32; + svga->dac_hwcursor.ena = ((val & 0x03) != 0x00); + break; + case 0x031: + if (!updt_cntl) + break; + ramdac->hwc_x = (ramdac->hwc_x & 0xff00) | val; + svga->dac_hwcursor.x = ((int) ramdac->hwc_x) - ramdac->cursor_hotspot_x; + break; + case 0x032: + /* Sign-extend the sign bit (7) to the remaining bits (6-4). */ + val &= 0x8f; + if (val & 0x80) + val |= 0x70; + ramdac->indexed_data[ramdac->index] = val; + if (!updt_cntl) + break; + ramdac->hwc_x = (ramdac->hwc_x & 0x00ff) | (val << 8); + svga->dac_hwcursor.x = ((int) ramdac->hwc_x) - ramdac->cursor_hotspot_x; + break; + case 0x033: + if (!updt_cntl) + break; + ramdac->hwc_y = (ramdac->hwc_y & 0xff00) | val; + svga->dac_hwcursor.y = ((int) ramdac->hwc_y) - ramdac->cursor_hotspot_y; + break; + case 0x034: + /* Sign-extend the sign bit (7) to the remaining bits (6-4). */ + val &= 0x8f; + if (val & 0x80) + val |= 0x70; + ramdac->indexed_data[ramdac->index] = val; + if (updt_cntl) { + ramdac->hwc_y = (ramdac->hwc_y & 0x00ff) | (val << 8); + svga->dac_hwcursor.y = ((int) ramdac->hwc_y) - ramdac->cursor_hotspot_y; + } else { + ramdac->hwc_x = ramdac->indexed_data[0x031]; + ramdac->hwc_x |= (ramdac->indexed_data[0x032] << 8); + ramdac->hwc_y = ramdac->indexed_data[0x033]; + ramdac->hwc_y |= (val << 8); + svga->dac_hwcursor.x = ((int) ramdac->hwc_x) - ramdac->cursor_hotspot_x; + svga->dac_hwcursor.y = ((int) ramdac->hwc_y) - ramdac->cursor_hotspot_y; + } + break; + case 0x035: + if (svga->dac_hwcursor.cur_xsize == 64) + ramdac->cursor_hotspot_x = (val & 0x3f); + else + ramdac->cursor_hotspot_x = (val & 0x1f); + svga->dac_hwcursor.x = ((int) ramdac->hwc_x) - ramdac->cursor_hotspot_x; + break; + case 0x036: + if (svga->dac_hwcursor.cur_xsize == 64) + ramdac->cursor_hotspot_y = (val & 0x3f); + else + ramdac->cursor_hotspot_y = (val & 0x1f); + svga->dac_hwcursor.y = ((int) ramdac->hwc_y) - ramdac->cursor_hotspot_y; + break; + case 0x040: + case 0x043: + case 0x046: + ramdac->extra_pal[(ramdac->index - 0x40) / 3].r = val; + break; + case 0x041: + case 0x044: + case 0x047: + ramdac->extra_pal[(ramdac->index - 0x41) / 3].g = val; + break; + case 0x042: + case 0x045: + case 0x048: + ramdac->extra_pal[(ramdac->index - 0x42) / 3].b = val; + break; + case 0x060: + ramdac->extra_pal[3].r = val; + break; + case 0x061: + ramdac->extra_pal[3].g = val; + break; + case 0x062: + ramdac->extra_pal[3].b = val; + break; + case 0x071: + svga->ramdac_type = (val & 0x04) ? RAMDAC_8BIT : RAMDAC_6BIT; + ibm_rgb528_set_bpp(ramdac, svga); + break; + default: + break; + } + if (ramdac->indx_cntl) { + if (ramdac->index == 0x00ff) + ramdac->cursor_array = 0; + ramdac->index = (ramdac->index + 1) & 0x07ff; + } + break; + case 0x07: + ramdac->indx_cntl = val & 0x01; + break; + + default: + break; } return; } - uint8_t -ibm_rgb528_ramdac_in(uint16_t addr, int rs2, void *p, svga_t *svga) +ibm_rgb528_ramdac_in(uint16_t addr, int rs2, void *priv, svga_t *svga) { - ibm_rgb528_ramdac_t *ramdac = (ibm_rgb528_ramdac_t *) p; - uint8_t temp = 0xff; - uint8_t rs = (addr & 0x03); - uint8_t loc_read = (ramdac->indexed_data[0x30] & 0x10); + ibm_rgb528_ramdac_t *ramdac = (ibm_rgb528_ramdac_t *) priv; + uint8_t temp = 0xff; + uint8_t rs = (addr & 0x03); + uint8_t loc_read = (ramdac->indexed_data[0x30] & 0x10); rs |= (!!rs2 << 2); switch (rs) { - case 0x00: /* Palette Write Index Register (RS value = 0000) */ - case 0x01: /* Palette Data Register (RS value = 0001) */ - case 0x02: /* Pixel Read Mask Register (RS value = 0010) */ - temp = svga_in(addr, svga); - break; - case 0x03: /* Palette Read Index Register (RS value = 0011) */ - temp = svga->dac_addr & 0xff; - if (ramdac->indexed_data[0x070] & 0x20) - temp = (temp & 0xfc) | svga->dac_status; - break; - case 0x04: - temp = ramdac->index & 0xff; - break; - case 0x05: - temp = ramdac->index >> 8; - break; - case 0x06: - temp = ramdac->indexed_data[ramdac->index]; - switch (ramdac->index) { - case 0x0000: /* Revision */ - temp = 0xe0; - break; - case 0x0001: /* ID */ - temp = 0x02; - break; - case 0x0031: - if (loc_read) - temp = ramdac->hwc_x & 0xff; - break; - case 0x0032: - if (loc_read) - temp = ramdac->hwc_x >> 8; - break; - case 0x0033: - if (loc_read) - temp = ramdac->hwc_y & 0xff; - break; - case 0x0034: - if (loc_read) - temp = ramdac->hwc_y >> 8; - break; - default: - temp = ramdac->indexed_data[ramdac->index]; - break; - } - if (ramdac->indx_cntl) { - if (ramdac->index == 0x00ff) - ramdac->cursor_array = 0; - ramdac->index = (ramdac->index + 1) & 0x07ff; - } - break; - case 0x07: - temp = ramdac->indx_cntl; - break; + case 0x00: /* Palette Write Index Register (RS value = 0000) */ + case 0x01: /* Palette Data Register (RS value = 0001) */ + case 0x02: /* Pixel Read Mask Register (RS value = 0010) */ + temp = svga_in(addr, svga); + break; + case 0x03: /* Palette Read Index Register (RS value = 0011) */ + temp = svga->dac_addr & 0xff; + if (ramdac->indexed_data[0x070] & 0x20) + temp = (temp & 0xfc) | svga->dac_status; + break; + case 0x04: + temp = ramdac->index & 0xff; + break; + case 0x05: + temp = ramdac->index >> 8; + break; + case 0x06: + temp = ramdac->indexed_data[ramdac->index]; + switch (ramdac->index) { + case 0x0000: /* Revision */ + temp = 0xe0; + break; + case 0x0001: /* ID */ + temp = 0x02; + break; + case 0x0031: + if (loc_read) + temp = ramdac->hwc_x & 0xff; + break; + case 0x0032: + if (loc_read) + temp = ramdac->hwc_x >> 8; + break; + case 0x0033: + if (loc_read) + temp = ramdac->hwc_y & 0xff; + break; + case 0x0034: + if (loc_read) + temp = ramdac->hwc_y >> 8; + break; + default: + temp = ramdac->indexed_data[ramdac->index]; + break; + } + if (ramdac->indx_cntl) { + if (ramdac->index == 0x00ff) + ramdac->cursor_array = 0; + ramdac->index = (ramdac->index + 1) & 0x07ff; + } + break; + case 0x07: + temp = ramdac->indx_cntl; + break; + + default: + break; } return temp; } - void -ibm_rgb528_recalctimings(void *p, svga_t *svga) +ibm_rgb528_recalctimings(void *priv, svga_t *svga) { - ibm_rgb528_ramdac_t *ramdac = (ibm_rgb528_ramdac_t *) p; + const ibm_rgb528_ramdac_t *ramdac = (ibm_rgb528_ramdac_t *) priv; svga->interlace = ramdac->indexed_data[0x071] & 0x20; if (svga->scrblank || !svga->attr_palette_enable) { - if ((svga->gdcreg[6] & 1) || (svga->attrregs[0x10] & 1)) { - if (((svga->gdcreg[5] & 0x60) == 0x40) || ((svga->gdcreg[5] & 0x60) == 0x60)) { - if (ramdac->indexed_data[0x071] & 0x01) { - switch (svga->bpp) { - case 4: - svga->render = ibm_rgb528_render_4bpp; - break; - case 8: - svga->render = ibm_rgb528_render_8bpp; - break; - case 15: case 16: - svga->render = ibm_rgb528_render_15_16bpp; - break; - case 24: - svga->render = ibm_rgb528_render_24bpp; - break; - case 32: - svga->render = ibm_rgb528_render_32bpp; - break; - } - } - } - } + if ((svga->gdcreg[6] & 1) || (svga->attrregs[0x10] & 1)) { + if (((svga->gdcreg[5] & 0x60) == 0x40) || ((svga->gdcreg[5] & 0x60) == 0x60)) { + if (ramdac->indexed_data[0x071] & 0x01) { + switch (svga->bpp) { + case 4: + svga->render = ibm_rgb528_render_4bpp; + break; + case 8: + svga->render = ibm_rgb528_render_8bpp; + break; + case 15: + case 16: + svga->render = ibm_rgb528_render_15_16bpp; + break; + case 24: + svga->render = ibm_rgb528_render_24bpp; + break; + case 32: + svga->render = ibm_rgb528_render_32bpp; + break; + + default: + break; + } + } + } + } } } - void ibm_rgb528_hwcursor_draw(svga_t *svga, int displine) { - uint8_t dat, four_pixels = 0x00; - int x, pitch, x_pos, y_pos, offset = svga->dac_hwcursor_latch.x - svga->dac_hwcursor_latch.xoff; - uint32_t *p; - ibm_rgb528_ramdac_t *ramdac = (ibm_rgb528_ramdac_t *) svga->ramdac; - uint8_t pix_ordr = ramdac->indexed_data[0x30] & 0x20; - uint8_t cursor_mode = ramdac->indexed_data[0x30] & 0x03; + uint8_t dat; + uint8_t four_pixels = 0x00; + int pitch; + int x_pos; + int y_pos; + int offset = svga->dac_hwcursor_latch.x - svga->dac_hwcursor_latch.xoff; + uint32_t *p; + const ibm_rgb528_ramdac_t *ramdac = (ibm_rgb528_ramdac_t *) svga->ramdac; + uint8_t pix_ordr = ramdac->indexed_data[0x30] & 0x20; + uint8_t cursor_mode = ramdac->indexed_data[0x30] & 0x03; /* The planes come in one part, and each plane is 2bpp, so a 32x32 cursor has 8 bytes per line, and a 64x64 cursor has 16 bytes per line. */ - pitch = (svga->dac_hwcursor_latch.xsize >> 2); /* Bytes per line. */ + pitch = (svga->dac_hwcursor_latch.cur_xsize >> 2); /* Bytes per line. */ if ((ramdac->indexed_data[0x071] & 0x20) && svga->dac_hwcursor_oddeven) - svga->dac_hwcursor_latch.addr += pitch; + svga->dac_hwcursor_latch.addr += pitch; y_pos = displine; x_pos = offset + svga->x_add; - p = buffer32->line[y_pos]; + p = buffer32->line[y_pos]; - for (x = 0; x < svga->dac_hwcursor_latch.xsize; x++) { - if (!(x & 3)) - four_pixels = ramdac->indexed_data[svga->dac_hwcursor_latch.addr]; + for (int x = 0; x < svga->dac_hwcursor_latch.cur_xsize; x++) { + if (!(x & 3)) + four_pixels = ramdac->indexed_data[svga->dac_hwcursor_latch.addr]; - if (pix_ordr) - dat = (four_pixels >> (((3 - x) & 3) << 1)) & 0x03; - else - dat = (four_pixels >> ((x & 3) << 1)) & 0x03; + if (pix_ordr) + dat = (four_pixels >> (((3 - x) & 3) << 1)) & 0x03; + else + dat = (four_pixels >> ((x & 3) << 1)) & 0x03; - x_pos = offset + svga->x_add + x; + x_pos = offset + svga->x_add + x; - switch (cursor_mode) { - case 0x01: - switch (dat) { - case 0x01: - /* Cursor Color 1 */ - p[x_pos] = ramdac->extra_pal[0].pixel; - break; - case 0x02: - /* Cursor Color 2 */ - p[x_pos] = ramdac->extra_pal[1].pixel; - break; - case 0x03: - /* Cursor Color 3 */ - p[x_pos] = ramdac->extra_pal[2].pixel; - break; - } - break; - case 0x02: - switch (dat) { - case 0x00: - /* Cursor Color 1 */ - p[x_pos] = ramdac->extra_pal[0].pixel; - break; - case 0x01: - /* Cursor Color 2 */ - p[x_pos] = ramdac->extra_pal[1].pixel; - break; - case 0x03: - /* Complement */ - p[x_pos] ^= 0xffffff; - break; - } - break; - case 0x03: - switch (dat) { - case 0x02: - /* Cursor Color 1 */ - p[x_pos] = ramdac->extra_pal[0].pixel; - break; - case 0x03: - /* Cursor Color 2 */ - p[x_pos] = ramdac->extra_pal[1].pixel; - break; - } - break; - } + switch (cursor_mode) { + case 0x01: + switch (dat) { + case 0x01: + /* Cursor Color 1 */ + p[x_pos] = ramdac->extra_pal[0].pixel; + break; + case 0x02: + /* Cursor Color 2 */ + p[x_pos] = ramdac->extra_pal[1].pixel; + break; + case 0x03: + /* Cursor Color 3 */ + p[x_pos] = ramdac->extra_pal[2].pixel; + break; - if ((x & 3) == 3) - svga->dac_hwcursor_latch.addr++; + default: + break; + } + break; + case 0x02: + switch (dat) { + case 0x00: + /* Cursor Color 1 */ + p[x_pos] = ramdac->extra_pal[0].pixel; + break; + case 0x01: + /* Cursor Color 2 */ + p[x_pos] = ramdac->extra_pal[1].pixel; + break; + case 0x03: + /* Complement */ + p[x_pos] ^= 0xffffff; + break; + + default: + break; + } + break; + case 0x03: + switch (dat) { + case 0x02: + /* Cursor Color 1 */ + p[x_pos] = ramdac->extra_pal[0].pixel; + break; + case 0x03: + /* Cursor Color 2 */ + p[x_pos] = ramdac->extra_pal[1].pixel; + break; + + default: + break; + } + break; + + default: + break; + } + + if ((x & 3) == 3) + svga->dac_hwcursor_latch.addr++; } if ((ramdac->indexed_data[0x071] & 0x20) && !svga->dac_hwcursor_oddeven) - svga->dac_hwcursor_latch.addr += pitch; + svga->dac_hwcursor_latch.addr += pitch; } - void * -ibm_rgb528_ramdac_init(const device_t *info) +ibm_rgb528_ramdac_init(UNUSED(const device_t *info)) { ibm_rgb528_ramdac_t *ramdac = (ibm_rgb528_ramdac_t *) malloc(sizeof(ibm_rgb528_ramdac_t)); memset(ramdac, 0, sizeof(ibm_rgb528_ramdac_t)); @@ -943,22 +965,25 @@ ibm_rgb528_ramdac_init(const device_t *info) return ramdac; } - static void ibm_rgb528_ramdac_close(void *priv) { ibm_rgb528_ramdac_t *ramdac = (ibm_rgb528_ramdac_t *) priv; if (ramdac) - free(ramdac); + free(ramdac); } - -const device_t ibm_rgb528_ramdac_device = -{ - "IBM RGB528 RAMDAC", - "ibm_rgb528_ramdac", - 0, 0, - ibm_rgb528_ramdac_init, ibm_rgb528_ramdac_close, - NULL, { NULL }, NULL, NULL, NULL +const device_t ibm_rgb528_ramdac_device = { + .name = "IBM RGB528 RAMDAC", + .internal_name = "ibm_rgb528_ramdac", + .flags = 0, + .local = 0, + .init = ibm_rgb528_ramdac_init, + .close = ibm_rgb528_ramdac_close, + .reset = NULL, + { .available = NULL }, + .speed_changed = NULL, + .force_redraw = NULL, + .config = NULL }; diff --git a/src/video/vid_icd2061.c b/src/video/vid_icd2061.c index eb7b4e61e..4c23d6ec5 100644 --- a/src/video/vid_icd2061.c +++ b/src/video/vid_icd2061.c @@ -1,149 +1,156 @@ /* - * 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. + * 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. + * This file is part of the 86Box distribution. * - * ICD2061 clock generator emulation. - * Also emulates the ICS9161 which is the same as the ICD2016, - * but without the need for tuning (which is irrelevant in - * emulation anyway). + * ICD2061 clock generator emulation. + * Also emulates the ICS9161 which is the same as the ICD2016, + * but without the need for tuning (which is irrelevant in + * emulation anyway). * - * Used by ET4000w32/p (Diamond Stealth 32) and the S3 - * Vision964 family. + * Used by ET4000w32/p (Diamond Stealth 32) and the S3 + * Vision964 family. * * * - * Authors: Miran Grca, + * Authors: Miran Grca, * - * Copyright 2016-2018 Miran Grca. + * Copyright 2016-2018 Miran Grca. */ +#include #include #include #include #include #include +#define HAVE_STDARG_H #include <86box/86box.h> #include <86box/device.h> +#include <86box/plat_unused.h> - -typedef struct icd2061_t -{ +typedef struct icd2061_t { float freq[3]; - int count, bit_count, - unlocked, state; - uint32_t data, ctrl; + int count; + int bit_count; + int unlocked; + int state; + uint32_t data; + uint32_t ctrl; } icd2061_t; - #ifdef ENABLE_ICD2061_LOG int icd2061_do_log = ENABLE_ICD2061_LOG; - static void icd2061_log(const char *fmt, ...) { va_list ap; if (icd2061_do_log) { - va_start(ap, fmt); - pclog_ex(fmt, ap); - va_end(ap); + va_start(ap, fmt); + pclog_ex(fmt, ap); + va_end(ap); } } #else -#define icd2061_log(fmt, ...) +# define icd2061_log(fmt, ...) #endif - void -icd2061_write(void *p, int val) +icd2061_write(void *priv, int val) { - icd2061_t *icd2061 = (icd2061_t *) p; + icd2061_t *icd2061 = (icd2061_t *) priv; - int nd, oc, nc; - int a, qa, q, pa, p_, m, ps; + int nd; + int oc; + int nc; + int a; + int qa; + int q; + int pa; + int p_; + int m; + int ps; - nd = (val & 2) >> 1; /* Old data. */ - oc = icd2061->state & 1; /* Old clock. */ - nc = val & 1; /* New clock. */ + nd = (val & 2) >> 1; /* Old data. */ + oc = icd2061->state & 1; /* Old clock. */ + nc = val & 1; /* New clock. */ icd2061->state = val; - if (nc && !oc) { /* Low-to-high transition of CLK. */ - if (!icd2061->unlocked) { - if (nd) { /* DATA high. */ - icd2061->count++; - icd2061_log("Low-to-high transition of CLK with DATA high, %i total\n", icd2061->count); - } else { /* DATA low. */ - if (icd2061->count >= 5) { - icd2061->unlocked = 1; - icd2061->bit_count = icd2061->data = 0; + if (nc && !oc) { /* Low-to-high transition of CLK. */ + if (!icd2061->unlocked) { + if (nd) { /* DATA high. */ + icd2061->count++; + icd2061_log("Low-to-high transition of CLK with DATA high, %i total\n", icd2061->count); + } else { /* DATA low. */ + if (icd2061->count >= 5) { + icd2061->unlocked = 1; + icd2061->bit_count = icd2061->data = 0; #ifdef ENABLE_ICD2061_LOG - icd2061_log("ICD2061 unlocked\n"); + icd2061_log("ICD2061 unlocked\n"); #endif - } else { - icd2061->count = 0; + } else { + icd2061->count = 0; #ifdef ENABLE_ICD2061_LOG - icd2061_log("ICD2061 locked\n"); + icd2061_log("ICD2061 locked\n"); #endif - } - } - } else if (nc) { - icd2061->data |= (nd << icd2061->bit_count); - icd2061->bit_count++; + } + } + } else if (nc) { + icd2061->data |= (nd << icd2061->bit_count); + icd2061->bit_count++; - if (icd2061->bit_count == 26) { - icd2061_log("26 bits received, data = %08X\n", icd2061->data); - - a = ((icd2061->data >> 22) & 0x07); /* A */ - icd2061_log("A = %01X\n", a); + if (icd2061->bit_count == 26) { + icd2061_log("26 bits received, data = %08X\n", icd2061->data); - if (a < 3) { - pa = ((icd2061->data >> 11) & 0x7f); /* P' (ICD2061) / N' (ICS9161) */ - m = ((icd2061->data >> 8) & 0x07); /* M (ICD2061) / R (ICS9161) */ - qa = ((icd2061->data >> 1) & 0x7f); /* Q' (ICD2061) / M' (ICS9161) */ + a = ((icd2061->data >> 22) & 0x07); /* A */ + icd2061_log("A = %01X\n", a); - p_ = pa + 3; /* P (ICD2061) / N (ICS9161) */ - m = 1 << m; - q = qa + 2; /* Q (ICD2061) / M (ICS9161) */ - ps = (icd2061->ctrl & (1 << a)) ? 4 : 2; /* Prescale */ + if (a < 3) { + pa = ((icd2061->data >> 11) & 0x7f); /* P' (ICD2061) / N' (ICS9161) */ + m = ((icd2061->data >> 8) & 0x07); /* M (ICD2061) / R (ICS9161) */ + qa = ((icd2061->data >> 1) & 0x7f); /* Q' (ICD2061) / M' (ICS9161) */ - icd2061->freq[a] = ((float)(p_ * ps) / (float)(q * m)) * 14318184.0f; + p_ = pa + 3; /* P (ICD2061) / N (ICS9161) */ + m = 1 << m; + q = qa + 2; /* Q (ICD2061) / M (ICS9161) */ + ps = (icd2061->ctrl & (1 << a)) ? 4 : 2; /* Prescale */ - icd2061_log("P = %02X, M = %01X, Q = %02X, freq[%i] = %f\n", p_, m, q, a, icd2061->freq[a]); - } else if (a == 6) { - icd2061->ctrl = ((icd2061->data >> 13) & 0xff); - icd2061_log("ctrl = %02X\n", icd2061->ctrl); - } - icd2061->count = icd2061->bit_count = icd2061->data = 0; - icd2061->unlocked = 0; + icd2061->freq[a] = ((float) (p_ * ps) / (float) (q * m)) * 14318184.0f; + + icd2061_log("P = %02X, M = %01X, Q = %02X, freq[%i] = %f\n", p_, m, q, a, icd2061->freq[a]); + } else if (a == 6) { + icd2061->ctrl = ((icd2061->data >> 13) & 0xff); + icd2061_log("ctrl = %02X\n", icd2061->ctrl); + } + icd2061->count = icd2061->bit_count = icd2061->data = 0; + icd2061->unlocked = 0; #ifdef ENABLE_ICD2061_LOG - icd2061_log("ICD2061 locked\n"); + icd2061_log("ICD2061 locked\n"); #endif - } - } + } + } } } - float -icd2061_getclock(int clock, void *p) +icd2061_getclock(int clock, void *priv) { - icd2061_t *icd2061 = (icd2061_t *) p; + const icd2061_t *icd2061 = (icd2061_t *) priv; if (clock > 2) - clock = 2; + clock = 2; return icd2061->freq[clock]; } - static void * -icd2061_init(const device_t *info) +icd2061_init(UNUSED(const device_t *info)) { icd2061_t *icd2061 = (icd2061_t *) malloc(sizeof(icd2061_t)); memset(icd2061, 0, sizeof(icd2061_t)); @@ -155,32 +162,39 @@ icd2061_init(const device_t *info) return icd2061; } - static void icd2061_close(void *priv) { icd2061_t *icd2061 = (icd2061_t *) priv; if (icd2061) - free(icd2061); + free(icd2061); } - -const device_t icd2061_device = -{ - "ICD2061 Clock Generator", - "icd2061", - 0, 0, - icd2061_init, icd2061_close, - NULL, { NULL }, NULL, NULL +const device_t icd2061_device = { + .name = "ICD2061 Clock Generator", + .internal_name = "icd2061", + .flags = 0, + .local = 0, + .init = icd2061_init, + .close = icd2061_close, + .reset = NULL, + { .available = NULL }, + .speed_changed = NULL, + .force_redraw = NULL, + .config = NULL }; - -const device_t ics9161_device = -{ - "ICS9161 Clock Generator", - "ics9161", - 0, 0, - icd2061_init, icd2061_close, - NULL, { NULL }, NULL, NULL +const device_t ics9161_device = { + .name = "ICS9161 Clock Generator", + .internal_name = "ics9161", + .flags = 0, + .local = 0, + .init = icd2061_init, + .close = icd2061_close, + .reset = NULL, + { .available = NULL }, + .speed_changed = NULL, + .force_redraw = NULL, + .config = NULL }; diff --git a/src/video/vid_ics2494.c b/src/video/vid_ics2494.c index 75fb38f8c..309d07966 100644 --- a/src/video/vid_ics2494.c +++ b/src/video/vid_ics2494.c @@ -1,39 +1,37 @@ /* - * 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. + * 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. + * This file is part of the 86Box distribution. * - * ICS2494 clock generator emulation. + * ICS2494 clock generator emulation. * - * Used by the AMI S3 924. + * Used by the AMI S3 924. * * * - * Authors: Miran Grca, + * Authors: Miran Grca, * - * Copyright 2020 Miran Grca. + * Copyright 2020 Miran Grca. */ +#include #include #include #include #include #include +#define HAVE_STDARG_H #include <86box/86box.h> #include <86box/device.h> - -typedef struct ics2494_t -{ +typedef struct ics2494_t { float freq[16]; } ics2494_t; - -#ifdef ENABLE_ics2494_LOG -int ics2494_do_log = ENABLE_ics2494_LOG; - +#ifdef ENABLE_ICS2494_LOG +int ics2494_do_log = ENABLE_ICS2494_LOG; static void ics2494_log(const char *fmt, ...) @@ -41,28 +39,26 @@ ics2494_log(const char *fmt, ...) va_list ap; if (ics2494_do_log) { - va_start(ap, fmt); - pclog_ex(fmt, ap); - va_end(ap); + va_start(ap, fmt); + pclog_ex(fmt, ap); + va_end(ap); } } #else -#define ics2494_log(fmt, ...) +# define ics2494_log(fmt, ...) #endif - float -ics2494_getclock(int clock, void *p) +ics2494_getclock(int clock, void *priv) { - ics2494_t *ics2494 = (ics2494_t *) p; + const ics2494_t *ics2494 = (ics2494_t *) priv; - if (clock > 16) - clock = 16; + if (clock > 15) + clock = 15; return ics2494->freq[clock]; } - static void * ics2494_init(const device_t *info) { @@ -70,46 +66,151 @@ ics2494_init(const device_t *info) memset(ics2494, 0, sizeof(ics2494_t)); switch (info->local) { - case 305: - /* ICS2494A(N)-205 for S3 86C924 */ - ics2494->freq[0x0] = 25175000.0; - ics2494->freq[0x1] = 28322000.0; - ics2494->freq[0x2] = 40000000.0; - ics2494->freq[0x3] = 0.0; - ics2494->freq[0x4] = 50000000.0; - ics2494->freq[0x5] = 77000000.0; - ics2494->freq[0x6] = 36000000.0; - ics2494->freq[0x7] = 44889000.0; - ics2494->freq[0x8] = 130000000.0; - ics2494->freq[0x9] = 120000000.0; - ics2494->freq[0xa] = 80000000.0; - ics2494->freq[0xb] = 31500000.0; - ics2494->freq[0xc] = 110000000.0; - ics2494->freq[0xd] = 65000000.0; - ics2494->freq[0xe] = 75000000.0; - ics2494->freq[0xf] = 94500000.0; - break; + case 10: + /* ATI 18810 for ATI 28800 */ + ics2494->freq[0x0] = 30240000.0; + ics2494->freq[0x1] = 32000000.0; + ics2494->freq[0x2] = 37500000.0; + ics2494->freq[0x3] = 39000000.0; + ics2494->freq[0x4] = 42954000.0; + ics2494->freq[0x5] = 48771000.0; + ics2494->freq[0x6] = 16657000.0; + ics2494->freq[0x7] = 36000000.0; + ics2494->freq[0x8] = 40000000.0; + ics2494->freq[0x9] = 56644000.0; + ics2494->freq[0xa] = 75000000.0; + ics2494->freq[0xb] = 65000000.0; + ics2494->freq[0xc] = 50350000.0; + ics2494->freq[0xd] = 56640000.0; + ics2494->freq[0xe] = 28322000.0; + ics2494->freq[0xf] = 44900000.0; + break; + case 110: + /* ATI 18811-0 for ATI Mach32 */ + ics2494->freq[0x0] = 30240000.0; + ics2494->freq[0x1] = 32000000.0; + ics2494->freq[0x2] = 110000000.0; + ics2494->freq[0x3] = 80000000.0; + ics2494->freq[0x4] = 42954000.0; + ics2494->freq[0x5] = 48771000.0; + ics2494->freq[0x6] = 92400000.0; + ics2494->freq[0x7] = 36000000.0; + ics2494->freq[0x8] = 39910000.0; + ics2494->freq[0x9] = 44900000.0; + ics2494->freq[0xa] = 75000000.0; + ics2494->freq[0xb] = 65000000.0; + ics2494->freq[0xc] = 50350000.0; + ics2494->freq[0xd] = 56640000.0; + ics2494->freq[0xe] = 0.0; + ics2494->freq[0xf] = 44900000.0; + break; + case 111: + /* ATI 18811-1 for ATI Mach32 MCA */ + ics2494->freq[0x0] = 135000000.0; + ics2494->freq[0x1] = 32000000.0; + ics2494->freq[0x2] = 110000000.0; + ics2494->freq[0x3] = 80000000.0; + ics2494->freq[0x4] = 100000000.0; + ics2494->freq[0x5] = 126000000.0; + ics2494->freq[0x6] = 92400000.0; + ics2494->freq[0x7] = 36000000.0; + ics2494->freq[0x8] = 39910000.0; + ics2494->freq[0x9] = 44900000.0; + ics2494->freq[0xa] = 75000000.0; + ics2494->freq[0xb] = 65000000.0; + ics2494->freq[0xc] = 50350000.0; + ics2494->freq[0xd] = 56640000.0; + ics2494->freq[0xe] = 0.0; + ics2494->freq[0xf] = 44900000.0; + break; + case 305: + /* ICS2494A(N)-205 for S3 86C924 */ + ics2494->freq[0x0] = 25175000.0; + ics2494->freq[0x1] = 28322000.0; + ics2494->freq[0x2] = 40000000.0; + ics2494->freq[0x3] = 0.0; + ics2494->freq[0x4] = 50000000.0; + ics2494->freq[0x5] = 77000000.0; + ics2494->freq[0x6] = 36000000.0; + ics2494->freq[0x7] = 44889000.0; + ics2494->freq[0x8] = 130000000.0; + ics2494->freq[0x9] = 120000000.0; + ics2494->freq[0xa] = 80000000.0; + ics2494->freq[0xb] = 31500000.0; + ics2494->freq[0xc] = 110000000.0; + ics2494->freq[0xd] = 65000000.0; + ics2494->freq[0xe] = 75000000.0; + ics2494->freq[0xf] = 94500000.0; + break; + + default: + break; } return ics2494; } - static void ics2494_close(void *priv) { ics2494_t *ics2494 = (ics2494_t *) priv; if (ics2494) - free(ics2494); + free(ics2494); } - -const device_t ics2494an_305_device = -{ - "ICS2494AN-305 Clock Generator", - "ics2494an_305", - 0, 305, - ics2494_init, ics2494_close, - NULL, { NULL }, NULL, NULL +const device_t ics2494an_305_device = { + .name = "ICS2494AN-305 Clock Generator", + .internal_name = "ics2494an_305", + .flags = 0, + .local = 305, + .init = ics2494_init, + .close = ics2494_close, + .reset = NULL, + { .available = NULL }, + .speed_changed = NULL, + .force_redraw = NULL, + .config = NULL +}; + +const device_t ati18810_device = { + .name = "ATI 18810 Clock Generator", + .internal_name = "ati18810", + .flags = 0, + .local = 10, + .init = ics2494_init, + .close = ics2494_close, + .reset = NULL, + { .available = NULL }, + .speed_changed = NULL, + .force_redraw = NULL, + .config = NULL +}; + +const device_t ati18811_0_device = { + .name = "ATI 18811-0 Clock Generator", + .internal_name = "ati18811_0", + .flags = 0, + .local = 110, + .init = ics2494_init, + .close = ics2494_close, + .reset = NULL, + { .available = NULL }, + .speed_changed = NULL, + .force_redraw = NULL, + .config = NULL +}; + +const device_t ati18811_1_device = { + .name = "ATI 18811-1 Clock Generator", + .internal_name = "ati18811_1", + .flags = 0, + .local = 111, + .init = ics2494_init, + .close = ics2494_close, + .reset = NULL, + { .available = NULL }, + .speed_changed = NULL, + .force_redraw = NULL, + .config = NULL }; diff --git a/src/video/vid_ics2595.c b/src/video/vid_ics2595.c index dde720d6f..ecb414f2b 100644 --- a/src/video/vid_ics2595.c +++ b/src/video/vid_ics2595.c @@ -1,20 +1,20 @@ /* - * 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. + * 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. + * This file is part of the 86Box distribution. * - * ICS2595 clock chip emulation. Used by ATI Mach64. + * ICS2595 clock chip emulation. Used by ATI Mach64. * * * - * Authors: Sarah Walker, - * Miran Grca, + * Authors: Sarah Walker, + * Miran Grca, * - * Copyright 2008-2018 Sarah Walker. - * Copyright 2016-2018 Miran Grca. + * Copyright 2008-2018 Sarah Walker. + * Copyright 2016-2018 Miran Grca. */ #include #include @@ -23,112 +23,114 @@ #include #include <86box/86box.h> #include <86box/device.h> +#include <86box/plat_unused.h> - -typedef struct ics2595_t -{ - int oldfs3, oldfs2; +typedef struct ics2595_t { + int oldfs3; + int oldfs2; int dat; - int pos, state; + int pos; + int state; double clocks[16]; double output_clock; } ics2595_t; - -enum -{ - ICS2595_IDLE = 0, - ICS2595_WRITE, - ICS2595_READ +enum { + ICS2595_IDLE = 0, + ICS2595_WRITE, + ICS2595_READ }; - -static int ics2595_div[4] = {8, 4, 2, 1}; - +static int ics2595_div[4] = { 8, 4, 2, 1 }; void -ics2595_write(void *p, int strobe, int dat) +ics2595_write(void *priv, int strobe, int dat) { - ics2595_t *ics2595 = (ics2595_t *) p; - int d, n; - int l; + ics2595_t *ics2595 = (ics2595_t *) priv; + int d; + int n; + int l; if (strobe) { - if ((dat & 8) && !ics2595->oldfs3) { /*Data clock*/ - switch (ics2595->state) { - case ICS2595_IDLE: - ics2595->state = (dat & 4) ? ICS2595_WRITE : ICS2595_IDLE; - ics2595->pos = 0; - break; - case ICS2595_WRITE: - ics2595->dat = (ics2595->dat >> 1); - if (dat & 4) - ics2595->dat |= (1 << 19); - ics2595->pos++; - if (ics2595->pos == 20) { - l = (ics2595->dat >> 2) & 0xf; - n = ((ics2595->dat >> 7) & 255) + 257; - d = ics2595_div[(ics2595->dat >> 16) & 3]; + if ((dat & 8) && !ics2595->oldfs3) { /*Data clock*/ + switch (ics2595->state) { + case ICS2595_IDLE: + ics2595->state = (dat & 4) ? ICS2595_WRITE : ICS2595_IDLE; + ics2595->pos = 0; + break; + case ICS2595_WRITE: + ics2595->dat = (ics2595->dat >> 1); + if (dat & 4) + ics2595->dat |= (1 << 19); + ics2595->pos++; + if (ics2595->pos == 20) { + l = (ics2595->dat >> 2) & 0xf; + n = ((ics2595->dat >> 7) & 255) + 257; + d = ics2595_div[(ics2595->dat >> 16) & 3]; - ics2595->clocks[l] = (14318181.8 * ((double)n / 46.0)) / (double)d; - ics2595->state = ICS2595_IDLE; - } - break; - } - } + ics2595->clocks[l] = (14318181.8 * ((double) n / 46.0)) / (double) d; + ics2595->state = ICS2595_IDLE; + } + break; - ics2595->oldfs2 = dat & 4; - ics2595->oldfs3 = dat & 8; + default: + break; + } + } + + ics2595->oldfs2 = dat & 4; + ics2595->oldfs3 = dat & 8; } ics2595->output_clock = ics2595->clocks[dat]; } - static void * -ics2595_init(const device_t *info) +ics2595_init(UNUSED(const device_t *info)) { ics2595_t *ics2595 = (ics2595_t *) malloc(sizeof(ics2595_t)); + memset(ics2595, 0, sizeof(ics2595_t)); return ics2595; } - static void ics2595_close(void *priv) { ics2595_t *ics2595 = (ics2595_t *) priv; if (ics2595) - free(ics2595); + free(ics2595); } - double -ics2595_getclock(void *p) +ics2595_getclock(void *priv) { - ics2595_t *ics2595 = (ics2595_t *) p; + const ics2595_t *ics2595 = (ics2595_t *) priv; return ics2595->output_clock; } - void -ics2595_setclock(void *p, double clock) +ics2595_setclock(void *priv, double clock) { - ics2595_t *ics2595 = (ics2595_t *) p; + ics2595_t *ics2595 = (ics2595_t *) priv; ics2595->output_clock = clock; } - -const device_t ics2595_device = -{ - "ICS2595 clock chip", - "ics2595", - 0, 0, - ics2595_init, ics2595_close, - NULL, { NULL }, NULL, NULL +const device_t ics2595_device = { + .name = "ICS2595 clock chip", + .internal_name = "ics2595", + .flags = 0, + .local = 0, + .init = ics2595_init, + .close = ics2595_close, + .reset = NULL, + { .available = NULL }, + .speed_changed = NULL, + .force_redraw = NULL, + .config = NULL }; diff --git a/src/video/vid_im1024.c b/src/video/vid_im1024.c index 4e6453b31..c7602ffd0 100644 --- a/src/video/vid_im1024.c +++ b/src/video/vid_im1024.c @@ -1,50 +1,50 @@ /* - * 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. + * 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. + * This file is part of the 86Box distribution. * - * Emulation of the ImageManager 1024 video controller. + * Emulation of the ImageManager 1024 video controller. * - * Just enough of the Vermont Microsystems IM-1024 is implemented - * to support the Windows 1.03 driver. Functions are partially - * implemented or hardwired to the behavior expected by the - * Windows driver. + * Just enough of the Vermont Microsystems IM-1024 is implemented + * to support the Windows 1.03 driver. Functions are partially + * implemented or hardwired to the behavior expected by the + * Windows driver. * - * One major difference seems to be that in hex mode, coordinates - * are passed as 2-byte integer words rather than 4-byte - * fixed-point fractions. + * One major difference seems to be that in hex mode, coordinates + * are passed as 2-byte integer words rather than 4-byte + * fixed-point fractions. * - * It is unknown what triggers this, so for now it's always on. + * It is unknown what triggers this, so for now it's always on. * - * As well as the usual PGC ring buffer at 0xC6000, the IM1024 - * appears to have an alternate method of passing commands. This - * is enabled by setting 0xC6330 to 1, and then: - * - * CX = count to write - * SI -> bytes to write - * - * Set pending bytes to 0 - * Read [C6331]. This gives number of bytes that can be written: - * 0xFF => 0, 0xFE => 1, 0xFD => 2 etc. - * Write that number of bytes to C6000. - * If there are more to come, go back to reading [C6331]. + * As well as the usual PGC ring buffer at 0xC6000, the IM1024 + * appears to have an alternate method of passing commands. This + * is enabled by setting 0xC6330 to 1, and then: * - * As far as can be determined, at least one byte is always - * written; there is no provision to pause if the queue is full. + * CX = count to write + * SI -> bytes to write * - * This is implemented by holding a FIFO of unlimited depth in - * the IM1024 to receive the data. + * Set pending bytes to 0 + * Read [C6331]. This gives number of bytes that can be written: + * 0xFF => 0, 0xFE => 1, 0xFD => 2 etc. + * Write that number of bytes to C6000. + * If there are more to come, go back to reading [C6331]. + * + * As far as can be determined, at least one byte is always + * written; there is no provision to pause if the queue is full. + * + * This is implemented by holding a FIFO of unlimited depth in + * the IM1024 to receive the data. * * * - * Authors: Fred N. van Kempen, - * John Elliott, + * Authors: Fred N. van Kempen, + * John Elliott, * - * Copyright 2019 Fred N. van Kempen. - * Copyright 2019 John Elliott. + * Copyright 2019 Fred N. van Kempen. + * Copyright 2019 John Elliott. */ #include #include @@ -62,100 +62,94 @@ #include <86box/device.h> #include <86box/pit.h> #include <86box/plat.h> +#include <86box/thread.h> #include <86box/video.h> #include <86box/vid_pgc.h> - -#define BIOS_ROM_PATH "roms/video/im1024/im1024font.bin" - +#define BIOS_ROM_PATH "roms/video/im1024/im1024font.bin" typedef struct { - pgc_t pgc; + pgc_t pgc; - uint8_t fontx[256]; - uint8_t fonty[256]; - uint8_t font[256][128]; + uint8_t fontx[256]; + uint8_t fonty[256]; + uint8_t font[256][128]; - uint8_t *fifo; - unsigned fifo_len, - fifo_wrptr, - fifo_rdptr; + uint8_t *fifo; + unsigned fifo_len, + fifo_wrptr, + fifo_rdptr; } im1024_t; - -static video_timings_t timing_im1024 = {VIDEO_ISA, 8, 16, 32, 8, 16, 32}; - +static video_timings_t timing_im1024 = { .type = VIDEO_ISA, .write_b = 8, .write_w = 16, .write_l = 32, .read_b = 8, .read_w = 16, .read_l = 32 }; #ifdef ENABLE_IM1024_LOG int im1024_do_log = ENABLE_IM1024_LOG; - static void im1024_log(const char *fmt, ...) { va_list ap; if (im1024_do_log) { - va_start(ap, fmt); - pclog_ex(fmt, ap); - va_end(ap); + va_start(ap, fmt); + pclog_ex(fmt, ap); + va_end(ap); } } #else -#define im1024_log(fmt, ...) +# define im1024_log(fmt, ...) #endif - static void fifo_write(im1024_t *dev, uint8_t val) { im1024_log("IM1024: fifo_write: %02x [rd=%04x wr=%04x]\n", - val, dev->fifo_rdptr, dev->fifo_wrptr); + val, dev->fifo_rdptr, dev->fifo_wrptr); if (((dev->fifo_wrptr + 1) % dev->fifo_len) == dev->fifo_rdptr) { - /* FIFO is full. Double its size. */ - uint8_t *buf; + /* FIFO is full. Double its size. */ + uint8_t *buf; - im1024_log("IM1024: fifo_resize: %i to %i\n", - dev->fifo_len, 2 * dev->fifo_len); + im1024_log("IM1024: fifo_resize: %i to %i\n", + dev->fifo_len, 2 * dev->fifo_len); - buf = realloc(dev->fifo, 2 * dev->fifo_len); - if (buf == NULL) return; + buf = realloc(dev->fifo, 2 * dev->fifo_len); + if (buf == NULL) + return; - /* Move the [0..wrptr] range to the newly-allocated area [len..len+wrptr] */ - memmove(buf + dev->fifo_len, buf, dev->fifo_wrptr); - dev->fifo = buf; - dev->fifo_wrptr += dev->fifo_len; - dev->fifo_len *= 2; + /* Move the [0..wrptr] range to the newly-allocated area [len..len+wrptr] */ + memmove(buf + dev->fifo_len, buf, dev->fifo_wrptr); + dev->fifo = buf; + dev->fifo_wrptr += dev->fifo_len; + dev->fifo_len *= 2; } - /* Append to the queue. */ + /* Append to the queue. */ dev->fifo[dev->fifo_wrptr++] = val; /* Wrap if end of buffer reached. */ if (dev->fifo_wrptr >= dev->fifo_len) - dev->fifo_wrptr = 0; + dev->fifo_wrptr = 0; } - static int fifo_read(im1024_t *dev) { uint8_t ret; if (dev->fifo_wrptr == dev->fifo_rdptr) - return -1; /* FIFO empty */ + return -1; /* FIFO empty */ ret = dev->fifo[dev->fifo_rdptr++]; if (dev->fifo_rdptr >= dev->fifo_len) - dev->fifo_rdptr = 0; + dev->fifo_rdptr = 0; im1024_log("IM1024: fifo_read: %02x\n", ret); - return(ret); + return ret; } - /* * Where a normal PGC would just read from the ring buffer at 0xC6300, * the IM-1024 can read from either this or from its internal FIFO. @@ -165,96 +159,92 @@ fifo_read(im1024_t *dev) static int input_byte(pgc_t *pgc, uint8_t *result) { - im1024_t *dev = (im1024_t *)pgc; + im1024_t *dev = (im1024_t *) pgc; /* If input buffer empty, wait for it to fill. */ - while (!pgc->stopped && (dev->fifo_wrptr == dev->fifo_rdptr) && - (pgc->mapram[0x300] == pgc->mapram[0x301])) { - pgc->waiting_input_fifo = 1; - pgc_sleep(pgc); + while (!pgc->stopped && (dev->fifo_wrptr == dev->fifo_rdptr) && (pgc->mapram[0x300] == pgc->mapram[0x301])) { + pgc->waiting_input_fifo = 1; + pgc_sleep(pgc); } if (pgc->stopped) - return(0); + return 0; if (pgc->mapram[0x3ff]) { - /* Reset triggered. */ - pgc_reset(pgc); - return(0); + /* Reset triggered. */ + pgc_reset(pgc); + return 0; } if (dev->fifo_wrptr == dev->fifo_rdptr) { - *result = pgc->mapram[pgc->mapram[0x301]]; - pgc->mapram[0x301]++; + *result = pgc->mapram[pgc->mapram[0x301]]; + pgc->mapram[0x301]++; } else - *result = fifo_read(dev); + *result = fifo_read(dev); - return(1); + return 1; } - /* Macros to disable clipping and save clip state. */ -#define PUSHCLIP { \ - uint16_t vp_x1, vp_x2, vp_y1, vp_y2; \ - vp_x1 = pgc->vp_x1; \ - vp_y1 = pgc->vp_y1; \ - vp_x2 = pgc->vp_x2; \ - vp_y2 = pgc->vp_y2; \ - pgc->vp_x1 = 0; \ - pgc->vp_y1 = 0; \ - pgc->vp_x2 = pgc->maxw - 1; \ - pgc->vp_y2 = pgc->maxh - 1; \ - -/* And to restore clip state */ -#define POPCLIP \ - pgc->vp_x1 = vp_x1; \ - pgc->vp_y1 = vp_y1; \ - pgc->vp_x2 = vp_x2; \ - pgc->vp_y2 = vp_y2; \ - } +#define PUSHCLIP \ + { \ + uint16_t vp_x1, vp_x2, vp_y1, vp_y2; \ + vp_x1 = pgc->vp_x1; \ + vp_y1 = pgc->vp_y1; \ + vp_x2 = pgc->vp_x2; \ + vp_y2 = pgc->vp_y2; \ + pgc->vp_x1 = 0; \ + pgc->vp_y1 = 0; \ + pgc->vp_x2 = pgc->maxw - 1; \ + pgc->vp_y2 = pgc->maxh - 1; +/* And to restore clip state */ +#define POPCLIP \ + pgc->vp_x1 = vp_x1; \ + pgc->vp_y1 = vp_y1; \ + pgc->vp_x2 = vp_x2; \ + pgc->vp_y2 = vp_y2; \ + } /* Override memory read to return FIFO space. */ static uint8_t im1024_read(uint32_t addr, void *priv) { - im1024_t *dev = (im1024_t *)priv; + im1024_t *dev = (im1024_t *) priv; if (addr == 0xc6331 && dev->pgc.mapram[0x330] == 1) { - /* Hardcode that there are 128 bytes free. */ - return(0x80); + /* Hardcode that there are 128 bytes free. */ + return 0x80; } - return(pgc_read(addr, &dev->pgc)); + return (pgc_read(addr, &dev->pgc)); } - /* Override memory write to handle writes to the FIFO. */ static void im1024_write(uint32_t addr, uint8_t val, void *priv) { - im1024_t *dev = (im1024_t *)priv; + im1024_t *dev = (im1024_t *) priv; /* * If we are in 'fast' input mode, send all * writes to the internal FIFO. */ if (addr >= 0xc6000 && addr < 0xc6100 && dev->pgc.mapram[0x330] == 1) { - fifo_write(dev, val); + fifo_write(dev, val); - im1024_log("IM1024: write(%02x)\n", val); + im1024_log("IM1024: write(%02x)\n", val); - if (dev->pgc.waiting_input_fifo) { - dev->pgc.waiting_input_fifo = 0; - pgc_wake(&dev->pgc); - } - return; + if (dev->pgc.waiting_input_fifo) { + dev->pgc.waiting_input_fifo = 0; + pgc_wake(&dev->pgc); + } + return; } pgc_write(addr, val, &dev->pgc); } - /* * I don't know what the IMGSIZ command does, only that the * Windows driver issues it. So just parse and ignore it. @@ -265,18 +255,23 @@ hndl_imgsiz(pgc_t *pgc) #if 0 im1024_t *dev = (im1024_t *)pgc; #endif - int16_t w, h; - uint8_t a, b; + int16_t w; + int16_t h; + uint8_t a; + uint8_t b; - if (! pgc_param_word(pgc, &w)) return; - if (! pgc_param_word(pgc, &h)) return; - if (! pgc_param_byte(pgc, &a)) return; - if (! pgc_param_byte(pgc, &b)) return; + if (!pgc_param_word(pgc, &w)) + return; + if (!pgc_param_word(pgc, &h)) + return; + if (!pgc_param_byte(pgc, &a)) + return; + if (!pgc_param_byte(pgc, &b)) + return; im1024_log("IM1024: IMGSIZ %i,%i,%i,%i\n", w, h, a, b); } - /* * I don't know what the IPREC command does, only that the * Windows driver issues it. So just parse and ignore it. @@ -289,15 +284,15 @@ hndl_iprec(pgc_t *pgc) #endif uint8_t param; - if (! pgc_param_byte(pgc, ¶m)) return; + if (!pgc_param_byte(pgc, ¶m)) + return; im1024_log("IM1024: IPREC %i\n", param); } - /* - * Set drawing mode. - * + * Set drawing mode. + * * 0 => Draw * 1 => Invert * 2 => XOR (IM-1024) @@ -308,16 +303,16 @@ hndl_linfun(pgc_t *pgc) { uint8_t param; - if (! pgc_param_byte(pgc, ¶m)) return; + if (!pgc_param_byte(pgc, ¶m)) + return; if (param < 4) { - pgc->draw_mode = param; - im1024_log("IM1024: LINFUN(%i)\n", param); + pgc->draw_mode = param; + im1024_log("IM1024: LINFUN(%i)\n", param); } else - pgc_error(pgc, PGC_ERROR_RANGE); + pgc_error(pgc, PGC_ERROR_RANGE); } - /* * I think PAN controls which part of the 1024x1024 framebuffer * is displayed in the 1024x800 visible screen. @@ -325,10 +320,13 @@ hndl_linfun(pgc_t *pgc) static void hndl_pan(pgc_t *pgc) { - int16_t x, y; + int16_t x; + int16_t y; - if (! pgc_param_word(pgc, &x)) return; - if (! pgc_param_word(pgc, &y)) return; + if (!pgc_param_word(pgc, &x)) + return; + if (!pgc_param_word(pgc, &y)) + return; im1024_log("IM1024: PAN %i,%i\n", x, y); @@ -336,32 +334,34 @@ hndl_pan(pgc_t *pgc) pgc->pan_y = y; } - /* PLINE draws a non-filled polyline at a fixed position. */ static void hndl_pline(pgc_t *pgc) { - int16_t x[257], y[257]; + int16_t x[257]; + int16_t y[257]; uint16_t linemask = pgc->line_pattern; - uint8_t count; + uint8_t count; unsigned n; - if (! pgc_param_byte(pgc, &count)) return; + if (!pgc_param_byte(pgc, &count)) + return; im1024_log("IM1024: PLINE (%i) ", count); for (n = 0; n < count; n++) { - if (! pgc_param_word(pgc, &x[n])) return; - if (! pgc_param_word(pgc, &y[n])) return; - im1024_log(" (%i,%i)\n", x[n], y[n]); + if (!pgc_param_word(pgc, &x[n])) + return; + if (!pgc_param_word(pgc, &y[n])) + return; + im1024_log(" (%i,%i)\n", x[n], y[n]); } for (n = 1; n < count; n++) { - linemask = pgc_draw_line(pgc, x[n - 1] << 16, y[n - 1] << 16, - x[n] << 16, y[n] << 16, linemask); + linemask = pgc_draw_line(pgc, x[n - 1] << 16, y[n - 1] << 16, + x[n] << 16, y[n] << 16, linemask); } } - /* * Blit a single row of pixels from one location to another. * @@ -376,31 +376,31 @@ blkmov_row(pgc_t *pgc, int16_t x0, int16_t x1, int16_t x2, int16_t sy, int16_t t int16_t x; for (x = x0; x <= x1; x++) { - src[x - x0] = pgc_read_pixel(pgc, x, sy); - dst[x - x0] = pgc_read_pixel(pgc, x - x0 + x2, ty); + src[x - x0] = pgc_read_pixel(pgc, x, sy); + dst[x - x0] = pgc_read_pixel(pgc, x - x0 + x2, ty); } - for (x = x0; x <= x1; x++) switch (pgc->draw_mode) { - default: - case 0: - pgc_write_pixel(pgc, (x - x0 + x2), ty, src[x - x0]); - break; + for (x = x0; x <= x1; x++) + switch (pgc->draw_mode) { + default: + case 0: + pgc_write_pixel(pgc, (x - x0 + x2), ty, src[x - x0]); + break; - case 1: - pgc_write_pixel(pgc, (x - x0 + x2), ty, dst[x - x0] ^ 0xff); - break; + case 1: + pgc_write_pixel(pgc, (x - x0 + x2), ty, dst[x - x0] ^ 0xff); + break; - case 2: - pgc_write_pixel(pgc, (x - x0 + x2), ty, src[x - x0] ^ dst[x - x0]); - break; + case 2: + pgc_write_pixel(pgc, (x - x0 + x2), ty, src[x - x0] ^ dst[x - x0]); + break; - case 3: - pgc_write_pixel(pgc, (x - x0 + x2), ty, src[x - x0] & dst[x - x0]); - break; - } + case 3: + pgc_write_pixel(pgc, (x - x0 + x2), ty, src[x - x0] & dst[x - x0]); + break; + } } - /* * BLKMOV blits a rectangular area from one location to another. * @@ -409,19 +409,28 @@ blkmov_row(pgc_t *pgc, int16_t x0, int16_t x1, int16_t x2, int16_t sy, int16_t t static void hndl_blkmov(pgc_t *pgc) { - int16_t x0, y0; - int16_t x1, y1; - int16_t x2, y2; + int16_t x0; + int16_t y0; + int16_t x1; + int16_t y1; + int16_t x2; + int16_t y2; int16_t y; - if (! pgc_param_word(pgc, &x0)) return; - if (! pgc_param_word(pgc, &y0)) return; - if (! pgc_param_word(pgc, &x1)) return; - if (! pgc_param_word(pgc, &y1)) return; - if (! pgc_param_word(pgc, &x2)) return; - if (! pgc_param_word(pgc, &y2)) return; + if (!pgc_param_word(pgc, &x0)) + return; + if (!pgc_param_word(pgc, &y0)) + return; + if (!pgc_param_word(pgc, &x1)) + return; + if (!pgc_param_word(pgc, &y1)) + return; + if (!pgc_param_word(pgc, &x2)) + return; + if (!pgc_param_word(pgc, &y2)) + return; - im1024_log("IM1024: BLKMOV %i,%i,%i,%i,%i,%i\n", x0,y0,x1,y1,x2,y2); + im1024_log("IM1024: BLKMOV %i,%i,%i,%i,%i,%i\n", x0, y0, x1, y1, x2, y2); /* Disable clipping. */ PUSHCLIP @@ -431,37 +440,38 @@ hndl_blkmov(pgc_t *pgc) * depending whether areas might overlap. */ if (y2 <= y0) { - for (y = y0; y <= y1; y++) - blkmov_row(pgc, x0, x1, x2, y, y - y0 + y2); + for (y = y0; y <= y1; y++) + blkmov_row(pgc, x0, x1, x2, y, y - y0 + y2); } else { - for (y = y1; y >= y0; y--) - blkmov_row(pgc, x0, x1, x2, y, y - y0 + y2); + for (y = y1; y >= y0; y--) + blkmov_row(pgc, x0, x1, x2, y, y - y0 + y2); } /* Restore clipping. */ POPCLIP } - /* * Override the PGC ELIPSE command to parse its * parameters as words rather than coordinates. - */ + */ static void hndl_ellipse(pgc_t *pgc) { - int16_t x, y; + int16_t x; + int16_t y; - if (! pgc_param_word(pgc, &x)) return; - if (! pgc_param_word(pgc, &y)) return; + if (!pgc_param_word(pgc, &x)) + return; + if (!pgc_param_word(pgc, &y)) + return; im1024_log("IM1024: ELLIPSE %i,%i @ %i,%i\n", - x, y, pgc->x >> 16, pgc->y >> 16); + x, y, pgc->x >> 16, pgc->y >> 16); pgc_draw_ellipse(pgc, x << 16, y << 16); } - /* * Override the PGC MOVE command to parse its * parameters as words rather than coordinates. @@ -469,10 +479,13 @@ hndl_ellipse(pgc_t *pgc) static void hndl_move(pgc_t *pgc) { - int16_t x, y; + int16_t x; + int16_t y; - if (! pgc_param_word(pgc, &x)) return; - if (! pgc_param_word(pgc, &y)) return; + if (!pgc_param_word(pgc, &x)) + return; + if (!pgc_param_word(pgc, &y)) + return; im1024_log("IM1024: MOVE %i,%i\n", x, y); @@ -480,7 +493,6 @@ hndl_move(pgc_t *pgc) pgc->y = y << 16; } - /* * Override the PGC DRAW command to parse its * parameters as words rather than coordinates. @@ -488,10 +500,13 @@ hndl_move(pgc_t *pgc) static void hndl_draw(pgc_t *pgc) { - int16_t x, y; + int16_t x; + int16_t y; - if (! pgc_param_word(pgc, &x)) return; - if (! pgc_param_word(pgc, &y)) return; + if (!pgc_param_word(pgc, &x)) + return; + if (!pgc_param_word(pgc, &y)) + return; im1024_log("IM1024: DRAW %i,%i to %i,%i\n", pgc->x >> 16, pgc->y >> 16, x, y); @@ -501,7 +516,6 @@ hndl_draw(pgc_t *pgc) pgc->y = y << 16; } - /* * Override the PGC POLY command to parse its * parameters as words rather than coordinates. @@ -509,116 +523,119 @@ hndl_draw(pgc_t *pgc) static void hndl_poly(pgc_t *pgc) { - int32_t *x, *y, *nx, *ny; - int16_t xw, yw, mask; + int32_t *x; + int32_t *y; + int32_t *nx; + int32_t *ny; + int16_t xw; + int16_t yw; + int16_t mask; unsigned realcount = 0; - unsigned n, as = 256; - int parsing = 1; - uint8_t count; + unsigned n; + unsigned as = 256; + int parsing = 1; + uint8_t count; - x = (int32_t *)malloc(as * sizeof(int32_t)); - y = (int32_t *)malloc(as * sizeof(int32_t)); + x = (int32_t *) malloc(as * sizeof(int32_t)); + y = (int32_t *) malloc(as * sizeof(int32_t)); if (!x || !y) { #ifdef ENABLE_IM1024_LOG - im1024_log("IM1024: POLY: out of memory\n"); + im1024_log("IM1024: POLY: out of memory\n"); #endif - if (x) - free(x); - if (y) - free(y); - return; + if (x) + free(x); + if (y) + free(y); + return; } while (parsing) { - if (! pgc_param_byte(pgc, &count)) { - if (x) - free(x); - if (y) - free(y); - return; - } + if (!pgc_param_byte(pgc, &count)) { + if (x) + free(x); + if (y) + free(y); + return; + } - if (count + realcount >= as) { - nx = (int32_t *)realloc(x, 2 * as * sizeof(int32_t)); - ny = (int32_t *)realloc(y, 2 * as * sizeof(int32_t)); - if (!x || !y) { + if (count + realcount >= as) { + nx = (int32_t *) realloc(x, 2 * as * sizeof(int32_t)); + ny = (int32_t *) realloc(y, 2 * as * sizeof(int32_t)); + if (!x || !y) { #ifdef ENABLE_IM1024_LOG - im1024_log("IM1024: poly: realloc failed\n"); + im1024_log("IM1024: poly: realloc failed\n"); #endif - break; - } - x = nx; - y = ny; - as *= 2; - } + break; + } + x = nx; + y = ny; + as *= 2; + } - for (n = 0; n < count; n++) { - if (! pgc_param_word(pgc, &xw)) { - if (x) - free(x); - if (y) - free(y); - return; - } - if (! pgc_param_word(pgc, &yw)) { - if (x) - free(x); - if (y) - free(y); - return; - } + for (n = 0; n < count; n++) { + if (!pgc_param_word(pgc, &xw)) { + if (x) + free(x); + if (y) + free(y); + return; + } + if (!pgc_param_word(pgc, &yw)) { + if (x) + free(x); + if (y) + free(y); + return; + } - /* Skip degenerate line segments. */ - if (realcount > 0 && - (xw << 16) == x[realcount - 1] && - (yw << 16) == y[realcount - 1]) continue; + /* Skip degenerate line segments. */ + if (realcount > 0 && (xw << 16) == x[realcount - 1] && (yw << 16) == y[realcount - 1]) + continue; - x[realcount] = xw << 16; - y[realcount] = yw << 16; - realcount++; - } + x[realcount] = xw << 16; + y[realcount] = yw << 16; + realcount++; + } - /* - * If we are in a command list, peek ahead to see if the next - * command is also POLY. If so, that's a continuation of this - * polygon! - */ - parsing = 0; - if (pgc->clcur && (pgc->clcur->rdptr+1) < pgc->clcur->wrptr && - pgc->clcur->list[pgc->clcur->rdptr] == 0x30) { + /* + * If we are in a command list, peek ahead to see if the next + * command is also POLY. If so, that's a continuation of this + * polygon! + */ + parsing = 0; + if (pgc->clcur && (pgc->clcur->rdptr + 1) < pgc->clcur->wrptr && pgc->clcur->list[pgc->clcur->rdptr] == 0x30) { #ifdef ENABLE_IM1024_LOG - im1024_log("IM1024: POLY continues!\n"); + im1024_log("IM1024: POLY continues!\n"); #endif - parsing = 1; + parsing = 1; - /* Swallow the POLY. */ - pgc->clcur->rdptr++; - } - }; + /* Swallow the POLY. */ + pgc->clcur->rdptr++; + } + } im1024_log("IM1024: POLY (%i) fill_mode=%i\n", realcount, pgc->fill_mode); #ifdef ENABLE_IM1024_LOG for (n = 0; n < realcount; n++) { - im1024_log(" (%i,%i)\n", x[n] >> 16, y[n] >> 16); + im1024_log(" (%i,%i)\n", x[n] >> 16, y[n] >> 16); } #endif if (pgc->fill_mode) - pgc_fill_polygon(pgc, realcount, x, y); + pgc_fill_polygon(pgc, realcount, x, y); /* Now draw borders. */ mask = pgc->line_pattern; for (n = 1; n < realcount; n++) - mask = pgc_draw_line(pgc, x[n - 1], y[n - 1], x[n], y[n], mask); + mask = pgc_draw_line(pgc, x[n - 1], y[n - 1], x[n], y[n], mask); pgc_draw_line(pgc, x[realcount - 1], y[realcount - 1], x[0], y[0], mask); free(y); free(x); } - static int -parse_poly(pgc_t *pgc, pgc_cl_t *cl, int c) +parse_poly(pgc_t *pgc, pgc_cl_t *cl, UNUSED(int c)) { uint8_t count; @@ -626,12 +643,13 @@ parse_poly(pgc_t *pgc, pgc_cl_t *cl, int c) im1024_log("IM1024: parse_poly\n"); #endif - if (! pgc_param_byte(pgc, &count)) return 0; + if (!pgc_param_byte(pgc, &count)) + return 0; im1024_log("IM1024: parse_poly: count=%02x\n", count); - if (! pgc_cl_append(cl, count)) { - pgc_error(pgc, PGC_ERROR_OVERFLOW); - return 0; + if (!pgc_cl_append(cl, count)) { + pgc_error(pgc, PGC_ERROR_OVERFLOW); + return 0; } im1024_log("IM1024: parse_poly: parse %i words\n", 2 * count); @@ -639,7 +657,6 @@ parse_poly(pgc_t *pgc, pgc_cl_t *cl, int c) return pgc_parse_words(pgc, cl, count * 2); } - /* * Override the PGC RECT command to parse its * parameters as words rather than coordinates. @@ -647,36 +664,50 @@ parse_poly(pgc_t *pgc, pgc_cl_t *cl, int c) static void hndl_rect(pgc_t *pgc) { - int16_t x0, y0, x1, y1, p, q; + int16_t x0; + int16_t y0; + int16_t x1; + int16_t y1; + int16_t p; + int16_t q; x0 = pgc->x >> 16; y0 = pgc->y >> 16; - if (! pgc_param_word(pgc, &x1)) return; - if (! pgc_param_word(pgc, &y1)) return; + if (!pgc_param_word(pgc, &x1)) + return; + if (!pgc_param_word(pgc, &y1)) + return; /* Convert to raster coords. */ pgc_sto_raster(pgc, &x0, &y0); pgc_sto_raster(pgc, &x1, &y1); - if (x0 > x1) { p = x0; x0 = x1; x1 = p; } - if (y0 > y1) { q = y0; y0 = y1; y1 = q; } + if (x0 > x1) { + p = x0; + x0 = x1; + x1 = p; + } + if (y0 > y1) { + q = y0; + y0 = y1; + y1 = q; + } im1024_log("IM1024: RECT (%i,%i) -> (%i,%i)\n", x0, y0, x1, y1); if (pgc->fill_mode) { - for (p = y0; p <= y1; p++) - pgc_fill_line_r(pgc, x0, x1, p); + for (p = y0; p <= y1; p++) + pgc_fill_line_r(pgc, x0, x1, p); } else { - /* Outline: 4 lines. */ - p = pgc->line_pattern; - p = pgc_draw_line_r(pgc, x0, y0, x1, y0, p); - p = pgc_draw_line_r(pgc, x1, y0, x1, y1, p); - p = pgc_draw_line_r(pgc, x1, y1, x0, y1, p); - p = pgc_draw_line_r(pgc, x0, y1, x0, y0, p); + /* Outline: 4 lines. */ + p = pgc->line_pattern; + p = pgc_draw_line_r(pgc, x0, y0, x1, y0, p); + p = pgc_draw_line_r(pgc, x1, y0, x1, y1, p); + p = pgc_draw_line_r(pgc, x1, y1, x0, y1, p); + p = pgc_draw_line_r(pgc, x0, y1, x0, y0, p); } } - /* * FIXME: * Define a font character. @@ -687,57 +718,67 @@ hndl_rect(pgc_t *pgc) static void hndl_tdefin(pgc_t *pgc) { - im1024_t *dev = (im1024_t *)pgc; - uint8_t ch, bt; - uint8_t rows, cols; - unsigned len, n; + im1024_t *dev = (im1024_t *) pgc; + uint8_t ch; + uint8_t bt; + uint8_t rows; + uint8_t cols; + unsigned len; - if (! pgc_param_byte(pgc, &ch)) return; - if (! pgc_param_byte(pgc, &cols)) return; - if (! pgc_param_byte(pgc, &rows)) return; + if (!pgc_param_byte(pgc, &ch)) + return; + if (!pgc_param_byte(pgc, &cols)) + return; + if (!pgc_param_byte(pgc, &rows)) + return; im1024_log("IM1024: TDEFIN (%i,%i,%i) 0x%02x 0x%02x\n", - ch, rows, cols, pgc->mapram[0x300], pgc->mapram[0x301]); + ch, rows, cols, pgc->mapram[0x300], pgc->mapram[0x301]); len = ((cols + 7) / 8) * rows; - for (n = 0; n < len; n++) { - if (! pgc_param_byte(pgc, &bt)) return; + for (unsigned int n = 0; n < len; n++) { + if (!pgc_param_byte(pgc, &bt)) + return; - if (n < sizeof(dev->font[ch])) - dev->font[ch][n] = bt; + if (n < sizeof(dev->font[ch])) + dev->font[ch][n] = bt; } dev->fontx[ch] = cols; dev->fonty[ch] = rows; } - static void hndl_tsize(pgc_t *pgc) { int16_t size; - if (!pgc_param_word(pgc, &size)) return; + if (!pgc_param_word(pgc, &size)) + return; im1024_log("IM1024: TSIZE(%i)\n", size); pgc->tsize = size << 16; } - static void hndl_twrite(pgc_t *pgc) { - uint8_t buf[256]; - im1024_t *dev = (im1024_t *)pgc; - uint8_t count, mask, *row; - int x, y, wb, n; - int16_t x0 = pgc->x >> 16; - int16_t y0 = pgc->y >> 16; + uint8_t buf[256]; + const im1024_t *dev = (im1024_t *) pgc; + uint8_t count; + uint8_t mask; + const uint8_t *row; + int wb; + int n; + int16_t x0 = pgc->x >> 16; + int16_t y0 = pgc->y >> 16; - if (! pgc_param_byte(pgc, &count)) return; + if (!pgc_param_byte(pgc, &count)) + return; for (n = 0; n < count; n++) - if (! pgc_param_byte(pgc, &buf[n])) return; + if (!pgc_param_byte(pgc, &buf[n])) + return; buf[count] = 0; pgc_sto_raster(pgc, &x0, &y0); @@ -745,43 +786,45 @@ hndl_twrite(pgc_t *pgc) im1024_log("IM1024: TWRITE (%i) x0=%i y0=%i\n", count, x0, y0); for (n = 0; n < count; n++) { - wb = (dev->fontx[buf[n]] + 7) / 8; - im1024_log("IM1024: ch=0x%02x w=%i h=%i wb=%i\n", - buf[n], dev->fontx[buf[n]], dev->fonty[buf[n]], wb); + wb = (dev->fontx[buf[n]] + 7) / 8; + im1024_log("IM1024: ch=0x%02x w=%i h=%i wb=%i\n", + buf[n], dev->fontx[buf[n]], dev->fonty[buf[n]], wb); - for (y = 0; y < dev->fonty[buf[n]]; y++) { - mask = 0x80; - row = &dev->font[buf[n]][y * wb]; - for (x = 0; x < dev->fontx[buf[n]]; x++) { - if (row[0] & mask) - pgc_plot(pgc, x + x0, y0 - y); - mask = mask >> 1; - if (mask == 0) { - mask = 0x80; - row++; - } - } - } + for (uint8_t y = 0; y < dev->fonty[buf[n]]; y++) { + mask = 0x80; + row = &dev->font[buf[n]][y * wb]; + for (uint8_t x = 0; x < dev->fontx[buf[n]]; x++) { + if (row[0] & mask) + pgc_plot(pgc, x + x0, y0 - y); + mask = mask >> 1; + if (mask == 0) { + mask = 0x80; + row++; + } + } + } - x0 += dev->fontx[buf[n]]; + x0 += dev->fontx[buf[n]]; } } - static void hndl_txt88(pgc_t *pgc) { - uint8_t buf[256]; - uint8_t count, mask, *row; - int16_t x0 = pgc->x >> 16; - int16_t y0 = pgc->y >> 16; - unsigned n; - int x, y; + uint8_t buf[256]; + uint8_t count; + uint8_t mask; + const uint8_t *row; + int16_t x0 = pgc->x >> 16; + int16_t y0 = pgc->y >> 16; + unsigned int n; - if (! pgc_param_byte(pgc, &count)) return; + if (!pgc_param_byte(pgc, &count)) + return; for (n = 0; n < count; n++) - if (! pgc_param_byte(pgc, &buf[n])) return; + if (!pgc_param_byte(pgc, &buf[n])) + return; buf[count] = 0; pgc_sto_raster(pgc, &x0, &y0); @@ -789,36 +832,45 @@ hndl_txt88(pgc_t *pgc) im1024_log("IM204: TXT88 (%i) x0=%i y0=%i\n", count, x0, y0); for (n = 0; n < count; n++) { - im1024_log("ch=0x%02x w=12 h=18\n", buf[n]); + im1024_log("ch=0x%02x w=12 h=18\n", buf[n]); - for (y = 0; y < 18; y++) { - mask = 0x80; - row = &fontdat12x18[buf[n]][y * 2]; - for (x = 0; x < 12; x++) { - if (row[0] & mask) pgc_plot(pgc, x + x0, y0 - y); - mask = mask >> 1; - if (mask == 0) { - mask = 0x80; - row++; - } - } - } + for (uint8_t y = 0; y < 18; y++) { + mask = 0x80; + row = &fontdat12x18[buf[n]][y * 2]; + for (uint8_t x = 0; x < 12; x++) { + if (row[0] & mask) + pgc_plot(pgc, x + x0, y0 - y); + mask = mask >> 1; + if (mask == 0) { + mask = 0x80; + row++; + } + } + } - x0 += 12; + x0 += 12; } } - static void hndl_imagew(pgc_t *pgc) { - int16_t vp_x1, vp_y1, vp_x2, vp_y2; - int16_t row1, col1, col2; - uint8_t v1, v2; + int16_t vp_x1; + int16_t vp_y1; + int16_t vp_x2; + int16_t vp_y2; + int16_t row1; + int16_t col1; + int16_t col2; + uint8_t v1; + uint8_t v2; - if (! pgc_param_word(pgc, &row1)) return; - if (! pgc_param_word(pgc, &col1)) return; - if (! pgc_param_word(pgc, &col2)) return; + if (!pgc_param_word(pgc, &row1)) + return; + if (!pgc_param_word(pgc, &col1)) + return; + if (!pgc_param_word(pgc, &col2)) + return; /* Already using raster coordinates, no need to convert. */ im1024_log("IM1024: IMAGEW (row=%i,col1=%i,col2=%i)\n", row1, col1, col2); @@ -836,39 +888,42 @@ hndl_imagew(pgc_t *pgc) /* In ASCII mode, what is written is a stream of bytes. */ if (pgc->ascii_mode) { - while (col1 <= col2) { - if (! pgc_param_byte(pgc, &v1)) - return; + while (col1 <= col2) { + if (!pgc_param_byte(pgc, &v1)) + return; - pgc_write_pixel(pgc, col1, row1, v1); - col1++; - } + pgc_write_pixel(pgc, col1, row1, v1); + col1++; + } } else { - /* In hex mode, it's RLE compressed. */ - while (col1 <= col2) { - if (! pgc_param_byte(pgc, &v1)) return; + /* In hex mode, it's RLE compressed. */ + while (col1 <= col2) { + if (!pgc_param_byte(pgc, &v1)) + return; - if (v1 & 0x80) { - /* Literal run. */ - v1 -= 0x7f; - while (col1 <= col2 && v1 != 0) { - if (! pgc_param_byte(pgc, &v2)) return; - pgc_write_pixel(pgc, col1, row1, v2); - col1++; - v1--; - } - } else { - /* Repeated run. */ - if (! pgc_param_byte(pgc, &v2)) return; + if (v1 & 0x80) { + /* Literal run. */ + v1 -= 0x7f; + while (col1 <= col2 && v1 != 0) { + if (!pgc_param_byte(pgc, &v2)) + return; + pgc_write_pixel(pgc, col1, row1, v2); + col1++; + v1--; + } + } else { + /* Repeated run. */ + if (!pgc_param_byte(pgc, &v2)) + return; - v1++; - while (col1 <= col2 && v1 != 0) { - pgc_write_pixel(pgc, col1, row1, v2); - col1++; - v1--; - } - } - } + v1++; + while (col1 <= col2 && v1 != 0) { + pgc_write_pixel(pgc, col1, row1, v2); + col1++; + v1--; + } + } + } } /* Restore clipping. */ @@ -878,7 +933,6 @@ hndl_imagew(pgc_t *pgc) pgc->vp_y2 = vp_y2; } - /* * I have called this command DOT - I don't know its proper name. * @@ -887,47 +941,51 @@ hndl_imagew(pgc_t *pgc) static void hndl_dot(pgc_t *pgc) { - int16_t x = pgc->x >> 16, - y = pgc->y >> 16; + int16_t x = pgc->x >> 16; + int16_t y = pgc->y >> 16; - pgc_sto_raster(pgc, &x, &y); + pgc_sto_raster(pgc, &x, &y); im1024_log("IM1024: DOT @ %i,%i ink=%i mode=%i\n", - x, y, pgc->color, pgc->draw_mode); + x, y, pgc->color, pgc->draw_mode); pgc_plot(pgc, x, y); } - /* - * This command (which I have called IMAGEX, since I don't know its real + * This command (which I have called IMAGEX, since I don't know its real * name) is a screen-to-memory blit. It reads a rectangle of bytes, rather - * than the single row read by IMAGER, and does not attempt to compress + * than the single row read by IMAGER, and does not attempt to compress * the result. */ static void hndl_imagex(pgc_t *pgc) { - int16_t x0, x1, y0, y1; - int16_t p,q; + int16_t x0; + int16_t x1; + int16_t y0; + int16_t y1; - if (! pgc_param_word(pgc, &x0)) return; - if (! pgc_param_word(pgc, &y0)) return; - if (! pgc_param_word(pgc, &x1)) return; - if (! pgc_param_word(pgc, &y1)) return; + if (!pgc_param_word(pgc, &x0)) + return; + if (!pgc_param_word(pgc, &y0)) + return; + if (!pgc_param_word(pgc, &x1)) + return; + if (!pgc_param_word(pgc, &y1)) + return; /* Already using raster coordinates, no need to convert. */ - im1024_log("IM1024: IMAGEX (%i,%i,%i,%i)\n", x0,y0,x1,y1); + im1024_log("IM1024: IMAGEX (%i,%i,%i,%i)\n", x0, y0, x1, y1); - for (p = y0; p <= y1; p++) { - for (q = x0; q <= x1; q++) { - if (! pgc_result_byte(pgc, pgc_read_pixel(pgc, q, p))) - return; - } + for (int16_t p = y0; p <= y1; p++) { + for (int16_t q = x0; q <= x1; q++) { + if (!pgc_result_byte(pgc, pgc_read_pixel(pgc, q, p))) + return; + } } } - /* * Commands implemented by the IM-1024. * @@ -937,105 +995,103 @@ hndl_imagex(pgc_t *pgc) * does not use them. */ static const pgc_cmd_t im1024_commands[] = { - { "BLKMOV", 0xdf, hndl_blkmov, pgc_parse_words, 6 }, - { "DRAW", 0x28, hndl_draw, pgc_parse_words, 2 }, - { "D", 0x28, hndl_draw, pgc_parse_words, 2 }, - { "DOT", 0x08, hndl_dot, NULL, 0 }, - { "ELIPSE", 0x39, hndl_ellipse, pgc_parse_words, 2 }, - { "EL", 0x39, hndl_ellipse, pgc_parse_words, 2 }, - { "IMAGEW", 0xd9, hndl_imagew, NULL, 0 }, - { "IMAGEX", 0xda, hndl_imagex, NULL, 0 }, - { "IMGSIZ", 0x4e, hndl_imgsiz, NULL, 0 }, - { "IPREC", 0xe4, hndl_iprec, NULL, 0 }, - { "IW", 0xd9, hndl_imagew, NULL, 0 }, - { "L8", 0xe6, pgc_hndl_lut8, NULL, 0 }, - { "LF", 0xeb, hndl_linfun, pgc_parse_bytes, 1 }, - { "LINFUN", 0xeb, hndl_linfun, pgc_parse_bytes, 1 }, - { "LUT8", 0xe6, pgc_hndl_lut8, NULL, 0 }, - { "LUT8RD", 0x53, pgc_hndl_lut8rd,NULL, 0 }, - { "L8RD", 0x53, pgc_hndl_lut8rd,NULL, 0 }, - { "TDEFIN", 0x84, hndl_tdefin, NULL, 0 }, - { "TD", 0x84, hndl_tdefin, NULL, 0 }, - { "TSIZE", 0x81, hndl_tsize, NULL, 0 }, - { "TS", 0x81, hndl_tsize, NULL, 0 }, - { "TWRITE", 0x8b, hndl_twrite, NULL, 0 }, - { "TXT88", 0x88, hndl_txt88, NULL, 0 }, - { "PAN", 0xb7, hndl_pan, NULL, 0 }, - { "POLY", 0x30, hndl_poly, parse_poly, 0 }, - { "P", 0x30, hndl_poly, parse_poly, 0 }, - { "PLINE", 0x36, hndl_pline, NULL, 0 }, - { "PL", 0x37, hndl_pline, NULL, 0 }, - { "MOVE", 0x10, hndl_move, pgc_parse_words, 2 }, - { "M", 0x10, hndl_move, pgc_parse_words, 2 }, - { "RECT", 0x34, hndl_rect, NULL, 0 }, - { "R", 0x34, hndl_rect, NULL, 0 }, - { "******", 0x00, NULL, NULL, 0 } + {"BLKMOV", 0xdf, hndl_blkmov, pgc_parse_words, 6}, + { "DRAW", 0x28, hndl_draw, pgc_parse_words, 2}, + { "D", 0x28, hndl_draw, pgc_parse_words, 2}, + { "DOT", 0x08, hndl_dot, NULL, 0}, + { "ELIPSE", 0x39, hndl_ellipse, pgc_parse_words, 2}, + { "EL", 0x39, hndl_ellipse, pgc_parse_words, 2}, + { "IMAGEW", 0xd9, hndl_imagew, NULL, 0}, + { "IMAGEX", 0xda, hndl_imagex, NULL, 0}, + { "IMGSIZ", 0x4e, hndl_imgsiz, NULL, 0}, + { "IPREC", 0xe4, hndl_iprec, NULL, 0}, + { "IW", 0xd9, hndl_imagew, NULL, 0}, + { "L8", 0xe6, pgc_hndl_lut8, NULL, 0}, + { "LF", 0xeb, hndl_linfun, pgc_parse_bytes, 1}, + { "LINFUN", 0xeb, hndl_linfun, pgc_parse_bytes, 1}, + { "LUT8", 0xe6, pgc_hndl_lut8, NULL, 0}, + { "LUT8RD", 0x53, pgc_hndl_lut8rd, NULL, 0}, + { "L8RD", 0x53, pgc_hndl_lut8rd, NULL, 0}, + { "TDEFIN", 0x84, hndl_tdefin, NULL, 0}, + { "TD", 0x84, hndl_tdefin, NULL, 0}, + { "TSIZE", 0x81, hndl_tsize, NULL, 0}, + { "TS", 0x81, hndl_tsize, NULL, 0}, + { "TWRITE", 0x8b, hndl_twrite, NULL, 0}, + { "TXT88", 0x88, hndl_txt88, NULL, 0}, + { "PAN", 0xb7, hndl_pan, NULL, 0}, + { "POLY", 0x30, hndl_poly, parse_poly, 0}, + { "P", 0x30, hndl_poly, parse_poly, 0}, + { "PLINE", 0x36, hndl_pline, NULL, 0}, + { "PL", 0x37, hndl_pline, NULL, 0}, + { "MOVE", 0x10, hndl_move, pgc_parse_words, 2}, + { "M", 0x10, hndl_move, pgc_parse_words, 2}, + { "RECT", 0x34, hndl_rect, NULL, 0}, + { "R", 0x34, hndl_rect, NULL, 0}, + { "******", 0x00, NULL, NULL, 0} }; - static void * -im1024_init(const device_t *info) +im1024_init(UNUSED(const device_t *info)) { im1024_t *dev; - dev = (im1024_t *)malloc(sizeof(im1024_t)); + dev = (im1024_t *) malloc(sizeof(im1024_t)); memset(dev, 0x00, sizeof(im1024_t)); loadfont(BIOS_ROM_PATH, 9); - dev->fifo_len = 4096; - dev->fifo = (uint8_t *)malloc(dev->fifo_len); + dev->fifo_len = 4096; + dev->fifo = (uint8_t *) malloc(dev->fifo_len); dev->fifo_wrptr = 0; dev->fifo_rdptr = 0; /* Create a 1024x1024 framebuffer with 1024x800 visible. */ - pgc_init(&dev->pgc, 1024, 1024, 1024, 800, input_byte, 65000000.0); + pgc_init(&dev->pgc, 1024, 1024, 1024, 800, input_byte, 65000000.0); dev->pgc.commands = im1024_commands; mem_mapping_set_handler(&dev->pgc.mapping, - im1024_read,NULL,NULL, im1024_write,NULL,NULL); + im1024_read, NULL, NULL, im1024_write, NULL, NULL); video_inform(VIDEO_FLAG_TYPE_CGA, &timing_im1024); - return(dev); + return dev; } - static void im1024_close(void *priv) { - im1024_t *dev = (im1024_t *)priv; + im1024_t *dev = (im1024_t *) priv; pgc_close_common(&dev->pgc); free(dev); } - static int -im1024_available() +im1024_available(void) { return rom_present(BIOS_ROM_PATH); } - static void im1024_speed_changed(void *priv) { - im1024_t *dev = (im1024_t *)priv; + im1024_t *dev = (im1024_t *) priv; pgc_speed_changed(&dev->pgc); } - const device_t im1024_device = { - "ImageManager 1024", - "im1024", - DEVICE_ISA | DEVICE_AT, 0, - im1024_init, im1024_close, NULL, - { im1024_available }, - im1024_speed_changed, - NULL, - NULL + .name = "ImageManager 1024", + .internal_name = "im1024", + .flags = DEVICE_ISA, + .local = 0, + .init = im1024_init, + .close = im1024_close, + .reset = NULL, + { .available = im1024_available }, + .speed_changed = im1024_speed_changed, + .force_redraw = NULL, + .config = NULL }; diff --git a/src/video/vid_incolor.c b/src/video/vid_incolor.c index d1de4a8c3..e3f37ec65 100644 --- a/src/video/vid_incolor.c +++ b/src/video/vid_incolor.c @@ -1,20 +1,20 @@ /* - * 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. + * 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. + * This file is part of the 86Box distribution. * - * Hercules InColor emulation. + * Hercules InColor emulation. * * * - * Authors: Sarah Walker, - * Miran Grca, + * Authors: Sarah Walker, + * Miran Grca, * - * Copyright 2008-2018 Sarah Walker. - * Copyright 2016-2018 Miran Grca. + * Copyright 2008-2018 Sarah Walker. + * Copyright 2016-2018 Miran Grca. */ #include #include @@ -30,11 +30,11 @@ #include <86box/rom.h> #include <86box/device.h> #include <86box/video.h> - +#include <86box/plat_unused.h> /* extended CRTC registers */ #define INCOLOR_CRTC_XMODE 20 /* xMode register */ -#define INCOLOR_CRTC_UNDER 21 /* Underline */ +#define INCOLOR_CRTC_UNDER 21 /* Underline */ #define INCOLOR_CRTC_OVER 22 /* Overstrike */ #define INCOLOR_CRTC_EXCEPT 23 /* Exception */ #define INCOLOR_CRTC_MASK 24 /* Plane display mask & write mask */ @@ -44,20 +44,20 @@ #define INCOLOR_CRTC_PALETTE 28 /* Palette */ /* character width */ -#define INCOLOR_CW ((dev->crtc[INCOLOR_CRTC_XMODE] & INCOLOR_XMODE_90COL) ? 8 : 9) +#define INCOLOR_CW ((dev->crtc[INCOLOR_CRTC_XMODE] & INCOLOR_XMODE_90COL) ? 8 : 9) /* mode control register */ -#define INCOLOR_CTRL_GRAPH 0x02 -#define INCOLOR_CTRL_ENABLE 0x08 -#define INCOLOR_CTRL_BLINK 0x20 -#define INCOLOR_CTRL_PAGE1 0x80 +#define INCOLOR_CTRL_GRAPH 0x02 +#define INCOLOR_CTRL_ENABLE 0x08 +#define INCOLOR_CTRL_BLINK 0x20 +#define INCOLOR_CTRL_PAGE1 0x80 /* CRTC status register */ -#define INCOLOR_STATUS_HSYNC 0x01 /* horizontal sync */ +#define INCOLOR_STATUS_HSYNC 0x01 /* horizontal sync */ #define INCOLOR_STATUS_LIGHT 0x02 #define INCOLOR_STATUS_VIDEO 0x08 -#define INCOLOR_STATUS_ID 0x50 /* Card identification */ -#define INCOLOR_STATUS_VSYNC 0x80 /* -vertical sync */ +#define INCOLOR_STATUS_ID 0x50 /* Card identification */ +#define INCOLOR_STATUS_VSYNC 0x80 /* -vertical sync */ /* configuration switch register */ #define INCOLOR_CTRL2_GRAPH 0x01 @@ -67,17 +67,14 @@ #define INCOLOR_XMODE_RAMFONT 0x01 #define INCOLOR_XMODE_90COL 0x02 - /* Read/write control */ #define INCOLOR_RWCTRL_WRMODE 0x30 #define INCOLOR_RWCTRL_POLARITY 0x40 /* exception register */ -#define INCOLOR_EXCEPT_CURSOR 0x0F /* Cursor colour */ -#define INCOLOR_EXCEPT_PALETTE 0x10 /* Enable palette register */ -#define INCOLOR_EXCEPT_ALTATTR 0x20 /* Use alternate attributes */ - - +#define INCOLOR_EXCEPT_CURSOR 0x0F /* Cursor colour */ +#define INCOLOR_EXCEPT_PALETTE 0x10 /* Enable palette register */ +#define INCOLOR_EXCEPT_ALTATTR 0x20 /* Use alternate attributes */ /* Default palette */ static const uint8_t defpal[16] = { @@ -87,976 +84,935 @@ static const uint8_t defpal[16] = { /* Mapping of inks to RGB */ static const uint8_t init_rgb[64][3] = { - /* rgbRGB */ - { 0x00, 0x00, 0x00 }, /* 000000 */ - { 0x00, 0x00, 0xaa }, /* 000001 */ - { 0x00, 0xaa, 0x00 }, /* 000010 */ - { 0x00, 0xaa, 0xaa }, /* 000011 */ - { 0xaa, 0x00, 0x00 }, /* 000100 */ - { 0xaa, 0x00, 0xaa }, /* 000101 */ - { 0xaa, 0xaa, 0x00 }, /* 000110 */ - { 0xaa, 0xaa, 0xaa }, /* 000111 */ - { 0x00, 0x00, 0x55 }, /* 001000 */ - { 0x00, 0x00, 0xff }, /* 001001 */ - { 0x00, 0xaa, 0x55 }, /* 001010 */ - { 0x00, 0xaa, 0xff }, /* 001011 */ - { 0xaa, 0x00, 0x55 }, /* 001100 */ - { 0xaa, 0x00, 0xff }, /* 001101 */ - { 0xaa, 0xaa, 0x55 }, /* 001110 */ - { 0xaa, 0xaa, 0xff }, /* 001111 */ - { 0x00, 0x55, 0x00 }, /* 010000 */ - { 0x00, 0x55, 0xaa }, /* 010001 */ - { 0x00, 0xff, 0x00 }, /* 010010 */ - { 0x00, 0xff, 0xaa }, /* 010011 */ - { 0xaa, 0x55, 0x00 }, /* 010100 */ - { 0xaa, 0x55, 0xaa }, /* 010101 */ - { 0xaa, 0xff, 0x00 }, /* 010110 */ - { 0xaa, 0xff, 0xaa }, /* 010111 */ - { 0x00, 0x55, 0x55 }, /* 011000 */ - { 0x00, 0x55, 0xff }, /* 011001 */ - { 0x00, 0xff, 0x55 }, /* 011010 */ - { 0x00, 0xff, 0xff }, /* 011011 */ - { 0xaa, 0x55, 0x55 }, /* 011100 */ - { 0xaa, 0x55, 0xff }, /* 011101 */ - { 0xaa, 0xff, 0x55 }, /* 011110 */ - { 0xaa, 0xff, 0xff }, /* 011111 */ - { 0x55, 0x00, 0x00 }, /* 100000 */ - { 0x55, 0x00, 0xaa }, /* 100001 */ - { 0x55, 0xaa, 0x00 }, /* 100010 */ - { 0x55, 0xaa, 0xaa }, /* 100011 */ - { 0xff, 0x00, 0x00 }, /* 100100 */ - { 0xff, 0x00, 0xaa }, /* 100101 */ - { 0xff, 0xaa, 0x00 }, /* 100110 */ - { 0xff, 0xaa, 0xaa }, /* 100111 */ - { 0x55, 0x00, 0x55 }, /* 101000 */ - { 0x55, 0x00, 0xff }, /* 101001 */ - { 0x55, 0xaa, 0x55 }, /* 101010 */ - { 0x55, 0xaa, 0xff }, /* 101011 */ - { 0xff, 0x00, 0x55 }, /* 101100 */ - { 0xff, 0x00, 0xff }, /* 101101 */ - { 0xff, 0xaa, 0x55 }, /* 101110 */ - { 0xff, 0xaa, 0xff }, /* 101111 */ - { 0x55, 0x55, 0x00 }, /* 110000 */ - { 0x55, 0x55, 0xaa }, /* 110001 */ - { 0x55, 0xff, 0x00 }, /* 110010 */ - { 0x55, 0xff, 0xaa }, /* 110011 */ - { 0xff, 0x55, 0x00 }, /* 110100 */ - { 0xff, 0x55, 0xaa }, /* 110101 */ - { 0xff, 0xff, 0x00 }, /* 110110 */ - { 0xff, 0xff, 0xaa }, /* 110111 */ - { 0x55, 0x55, 0x55 }, /* 111000 */ - { 0x55, 0x55, 0xff }, /* 111001 */ - { 0x55, 0xff, 0x55 }, /* 111010 */ - { 0x55, 0xff, 0xff }, /* 111011 */ - { 0xff, 0x55, 0x55 }, /* 111100 */ - { 0xff, 0x55, 0xff }, /* 111101 */ - { 0xff, 0xff, 0x55 }, /* 111110 */ - { 0xff, 0xff, 0xff }, /* 111111 */ + /* rgbRGB */ + {0x00, 0x00, 0x00}, /* 000000 */ + { 0x00, 0x00, 0xaa}, /* 000001 */ + { 0x00, 0xaa, 0x00}, /* 000010 */ + { 0x00, 0xaa, 0xaa}, /* 000011 */ + { 0xaa, 0x00, 0x00}, /* 000100 */ + { 0xaa, 0x00, 0xaa}, /* 000101 */ + { 0xaa, 0xaa, 0x00}, /* 000110 */ + { 0xaa, 0xaa, 0xaa}, /* 000111 */ + { 0x00, 0x00, 0x55}, /* 001000 */ + { 0x00, 0x00, 0xff}, /* 001001 */ + { 0x00, 0xaa, 0x55}, /* 001010 */ + { 0x00, 0xaa, 0xff}, /* 001011 */ + { 0xaa, 0x00, 0x55}, /* 001100 */ + { 0xaa, 0x00, 0xff}, /* 001101 */ + { 0xaa, 0xaa, 0x55}, /* 001110 */ + { 0xaa, 0xaa, 0xff}, /* 001111 */ + { 0x00, 0x55, 0x00}, /* 010000 */ + { 0x00, 0x55, 0xaa}, /* 010001 */ + { 0x00, 0xff, 0x00}, /* 010010 */ + { 0x00, 0xff, 0xaa}, /* 010011 */ + { 0xaa, 0x55, 0x00}, /* 010100 */ + { 0xaa, 0x55, 0xaa}, /* 010101 */ + { 0xaa, 0xff, 0x00}, /* 010110 */ + { 0xaa, 0xff, 0xaa}, /* 010111 */ + { 0x00, 0x55, 0x55}, /* 011000 */ + { 0x00, 0x55, 0xff}, /* 011001 */ + { 0x00, 0xff, 0x55}, /* 011010 */ + { 0x00, 0xff, 0xff}, /* 011011 */ + { 0xaa, 0x55, 0x55}, /* 011100 */ + { 0xaa, 0x55, 0xff}, /* 011101 */ + { 0xaa, 0xff, 0x55}, /* 011110 */ + { 0xaa, 0xff, 0xff}, /* 011111 */ + { 0x55, 0x00, 0x00}, /* 100000 */ + { 0x55, 0x00, 0xaa}, /* 100001 */ + { 0x55, 0xaa, 0x00}, /* 100010 */ + { 0x55, 0xaa, 0xaa}, /* 100011 */ + { 0xff, 0x00, 0x00}, /* 100100 */ + { 0xff, 0x00, 0xaa}, /* 100101 */ + { 0xff, 0xaa, 0x00}, /* 100110 */ + { 0xff, 0xaa, 0xaa}, /* 100111 */ + { 0x55, 0x00, 0x55}, /* 101000 */ + { 0x55, 0x00, 0xff}, /* 101001 */ + { 0x55, 0xaa, 0x55}, /* 101010 */ + { 0x55, 0xaa, 0xff}, /* 101011 */ + { 0xff, 0x00, 0x55}, /* 101100 */ + { 0xff, 0x00, 0xff}, /* 101101 */ + { 0xff, 0xaa, 0x55}, /* 101110 */ + { 0xff, 0xaa, 0xff}, /* 101111 */ + { 0x55, 0x55, 0x00}, /* 110000 */ + { 0x55, 0x55, 0xaa}, /* 110001 */ + { 0x55, 0xff, 0x00}, /* 110010 */ + { 0x55, 0xff, 0xaa}, /* 110011 */ + { 0xff, 0x55, 0x00}, /* 110100 */ + { 0xff, 0x55, 0xaa}, /* 110101 */ + { 0xff, 0xff, 0x00}, /* 110110 */ + { 0xff, 0xff, 0xaa}, /* 110111 */ + { 0x55, 0x55, 0x55}, /* 111000 */ + { 0x55, 0x55, 0xff}, /* 111001 */ + { 0x55, 0xff, 0x55}, /* 111010 */ + { 0x55, 0xff, 0xff}, /* 111011 */ + { 0xff, 0x55, 0x55}, /* 111100 */ + { 0xff, 0x55, 0xff}, /* 111101 */ + { 0xff, 0xff, 0x55}, /* 111110 */ + { 0xff, 0xff, 0xff}, /* 111111 */ }; - typedef struct { - mem_mapping_t mapping; + mem_mapping_t mapping; - uint8_t crtc[32]; - int crtcreg; + uint8_t crtc[32]; + int crtcreg; - uint8_t ctrl, ctrl2, stat; + uint8_t ctrl, ctrl2, stat; - uint64_t dispontime, dispofftime; - pc_timer_t timer; + uint64_t dispontime, dispofftime; + pc_timer_t timer; - int firstline, lastline; + int firstline, lastline; - int linepos, displine; - int vc, sc; - uint16_t ma, maback; - int con, coff, cursoron; - int dispon, blink; - int vsynctime; - int vadj; + int linepos, displine; + int vc, sc; + uint16_t ma, maback; + int con, coff, cursoron; + int dispon, blink; + int vsynctime; + int vadj; - uint8_t palette[16]; /* EGA-style 16 -> 64 palette registers */ - uint8_t palette_idx; /* Palette write index */ - uint8_t latch[4]; /* Memory read/write latches */ + uint8_t palette[16]; /* EGA-style 16 -> 64 palette registers */ + uint8_t palette_idx; /* Palette write index */ + uint8_t latch[4]; /* Memory read/write latches */ - uint32_t rgb[64]; + uint32_t rgb[64]; - uint8_t *vram; + uint8_t *vram; } incolor_t; -static video_timings_t timing_incolor = {VIDEO_ISA, 8, 16, 32, 8, 16, 32}; - +static video_timings_t timing_incolor = { .type = VIDEO_ISA, .write_b = 8, .write_w = 16, .write_l = 32, .read_b = 8, .read_w = 16, .read_l = 32 }; static void recalc_timings(incolor_t *dev) { double disptime; - double _dispontime, _dispofftime; + double _dispontime; + double _dispofftime; - disptime = dev->crtc[0] + 1; + disptime = dev->crtc[0] + 1; _dispontime = dev->crtc[1]; _dispofftime = disptime - _dispontime; - _dispontime *= HERCCONST; + _dispontime *= HERCCONST; _dispofftime *= HERCCONST; - dev->dispontime = (uint64_t)(_dispontime); - dev->dispofftime = (uint64_t)(_dispofftime); + dev->dispontime = (uint64_t) (_dispontime); + dev->dispofftime = (uint64_t) (_dispofftime); } - static void incolor_out(uint16_t port, uint8_t val, void *priv) { - incolor_t *dev = (incolor_t *)priv; - uint8_t old; + incolor_t *dev = (incolor_t *) priv; + uint8_t old; switch (port) { - case 0x3b0: - case 0x3b2: - case 0x3b4: - case 0x3b6: - dev->crtcreg = val & 31; - return; + case 0x3b0: + case 0x3b2: + case 0x3b4: + case 0x3b6: + dev->crtcreg = val & 31; + return; - case 0x3b1: case 0x3b3: case 0x3b5: case 0x3b7: - if (dev->crtcreg > 28) return; - /* Palette load register */ - if (dev->crtcreg == INCOLOR_CRTC_PALETTE) { - dev->palette[dev->palette_idx % 16] = val; - ++dev->palette_idx; - } - old = dev->crtc[dev->crtcreg]; - dev->crtc[dev->crtcreg] = val; + case 0x3b1: + case 0x3b3: + case 0x3b5: + case 0x3b7: + if (dev->crtcreg > 28) + return; + /* Palette load register */ + if (dev->crtcreg == INCOLOR_CRTC_PALETTE) { + dev->palette[dev->palette_idx % 16] = val; + ++dev->palette_idx; + } + old = dev->crtc[dev->crtcreg]; + dev->crtc[dev->crtcreg] = val; - if (dev->crtc[10] == 6 && dev->crtc[11] == 7) { - /*Fix for Generic Turbo XT BIOS, - * which sets up cursor registers wrong*/ - dev->crtc[10] = 0xb; - dev->crtc[11] = 0xc; - } - if (old ^ val) - recalc_timings(dev); - return; + if (dev->crtc[10] == 6 && dev->crtc[11] == 7) { + /*Fix for Generic Turbo XT BIOS, + * which sets up cursor registers wrong*/ + dev->crtc[10] = 0xb; + dev->crtc[11] = 0xc; + } + if (old ^ val) + recalc_timings(dev); + return; - case 0x3b8: - old = dev->ctrl; - dev->ctrl = val; - if (old ^ val) - recalc_timings(dev); - return; + case 0x3b8: + old = dev->ctrl; + dev->ctrl = val; + if (old ^ val) + recalc_timings(dev); + return; - case 0x3bf: - dev->ctrl2 = val; - if (val & 2) - mem_mapping_set_addr(&dev->mapping, 0xb0000, 0x10000); - else - mem_mapping_set_addr(&dev->mapping, 0xb0000, 0x08000); - return; + case 0x3bf: + dev->ctrl2 = val; + if (val & 2) + mem_mapping_set_addr(&dev->mapping, 0xb0000, 0x10000); + else + mem_mapping_set_addr(&dev->mapping, 0xb0000, 0x08000); + return; + + default: + break; } } - static uint8_t incolor_in(uint16_t port, void *priv) { - incolor_t *dev = (incolor_t *)priv; - uint8_t ret = 0xff; + incolor_t *dev = (incolor_t *) priv; + uint8_t ret = 0xff; switch (port) { - case 0x3b0: - case 0x3b2: - case 0x3b4: - case 0x3b6: - ret = dev->crtcreg; - break; + case 0x3b0: + case 0x3b2: + case 0x3b4: + case 0x3b6: + ret = dev->crtcreg; + break; - case 0x3b1: - case 0x3b3: - case 0x3b5: - case 0x3b7: - if (dev->crtcreg > 28) break; + case 0x3b1: + case 0x3b3: + case 0x3b5: + case 0x3b7: + if (dev->crtcreg > 28) + break; - dev->palette_idx = 0; /* Read resets the palette index */ - ret = dev->crtc[dev->crtcreg]; - break; + dev->palette_idx = 0; /* Read resets the palette index */ + ret = dev->crtc[dev->crtcreg]; + break; - case 0x3ba: - /* 0x50: InColor card identity */ - ret = (dev->stat & 0xf) | ((dev->stat & 8) << 4) | 0x50; - break; + case 0x3ba: + /* 0x50: InColor card identity */ + ret = (dev->stat & 0xf) | ((dev->stat & 8) << 4) | 0x50; + break; - default: - break; + default: + break; } return ret; } - static void incolor_write(uint32_t addr, uint8_t val, void *priv) { - incolor_t *dev = (incolor_t *)priv; + incolor_t *dev = (incolor_t *) priv; unsigned char wmask = dev->crtc[INCOLOR_CRTC_MASK]; unsigned char wmode = dev->crtc[INCOLOR_CRTC_RWCTRL] & INCOLOR_RWCTRL_WRMODE; - unsigned char fg = dev->crtc[INCOLOR_CRTC_RWCOL] & 0x0F; - unsigned char bg = (dev->crtc[INCOLOR_CRTC_RWCOL] >> 4)&0x0F; - unsigned char w = 0; - unsigned char vmask; /* Mask of bit within byte */ - unsigned char pmask; /* Mask of plane within colour value */ + unsigned char fg = dev->crtc[INCOLOR_CRTC_RWCOL] & 0x0F; + unsigned char bg = (dev->crtc[INCOLOR_CRTC_RWCOL] >> 4) & 0x0F; + unsigned char w = 0; + unsigned char pmask; /* Mask of plane within colour value */ unsigned char latch; - int plane; addr &= 0xffff; /* In text mode, writes to the bottom 16k always touch all 4 planes */ if (!(dev->ctrl & INCOLOR_CTRL_GRAPH) && addr < 0x4000) { - dev->vram[addr] = val; - return; + dev->vram[addr] = val; + return; } /* There are four write modes: * 0: 1 => foreground, 0 => background * 1: 1 => foreground, 0 => source latch * 2: 1 => source latch, 0 => background - * 3: 1 => source latch, 0 => ~source latch + * 3: 1 => source latch, 0 => ~source latch */ pmask = 1; - for (plane = 0; plane < 4; pmask <<= 1, wmask >>= 1, addr += 0x10000, plane++) { - if (wmask & 0x10) /* Ignore writes to selected plane */ - { - continue; - } - latch = dev->latch[plane]; - for (vmask = 0x80; vmask != 0; vmask >>= 1) { - switch (wmode) { - case 0x00: - if (val & vmask) w = (fg & pmask); - else w = (bg & pmask); - break; + for (uint8_t plane = 0; plane < 4; pmask <<= 1, wmask >>= 1, addr += 0x10000, plane++) { + if (wmask & 0x10) /* Ignore writes to selected plane */ + { + continue; + } + latch = dev->latch[plane]; + for (unsigned char vmask = 0x80 /* Mask of bit within byte */; vmask != 0; vmask >>= 1) { + switch (wmode) { + case 0x00: + if (val & vmask) + w = (fg & pmask); + else + w = (bg & pmask); + break; - case 0x10: - if (val & vmask) w = (fg & pmask); - else w = (latch & vmask); - break; + case 0x10: + if (val & vmask) + w = (fg & pmask); + else + w = (latch & vmask); + break; - case 0x20: - if (val & vmask) w = (latch & vmask); - else w = (bg & pmask); - break; + case 0x20: + if (val & vmask) + w = (latch & vmask); + else + w = (bg & pmask); + break; - case 0x30: - if (val & vmask) w = (latch & vmask); - else w = ((~latch) & vmask); - break; - } + case 0x30: + if (val & vmask) + w = (latch & vmask); + else + w = ((~latch) & vmask); + break; - /* w is nonzero to write a 1, zero to write a 0 */ - if (w) dev->vram[addr] |= vmask; - else dev->vram[addr] &= ~vmask; - } + default: + break; + } + + /* w is nonzero to write a 1, zero to write a 0 */ + if (w) + dev->vram[addr] |= vmask; + else + dev->vram[addr] &= ~vmask; + } } } - static uint8_t incolor_read(uint32_t addr, void *priv) { - incolor_t *dev = (incolor_t *)priv; - unsigned plane; - unsigned char lp = dev->crtc[INCOLOR_CRTC_PROTECT]; + incolor_t *dev = (incolor_t *) priv; + unsigned plane; + unsigned char lp = dev->crtc[INCOLOR_CRTC_PROTECT]; unsigned char value = 0; - unsigned char dc; /* "don't care" register */ - unsigned char bg; /* background colour */ + unsigned char dc; /* "don't care" register */ + unsigned char bg; /* background colour */ unsigned char fg; - unsigned char mask, pmask; + unsigned char pmask; addr &= 0xffff; /* Read the four planes into latches */ for (plane = 0; plane < 4; plane++, addr += 0x10000) { - dev->latch[plane] &= lp; - dev->latch[plane] |= (dev->vram[addr] & ~lp); + dev->latch[plane] &= lp; + dev->latch[plane] |= (dev->vram[addr] & ~lp); } addr &= 0xffff; /* In text mode, reads from the bottom 16k assume all planes have * the same contents */ if (!(dev->ctrl & INCOLOR_CTRL_GRAPH) && addr < 0x4000) { - return dev->latch[0]; + return dev->latch[0]; } /* For each pixel, work out if its colour matches the background */ - for (mask = 0x80; mask != 0; mask >>= 1) { - fg = 0; - dc = dev->crtc[INCOLOR_CRTC_RWCTRL] & 0x0F; - bg = (dev->crtc[INCOLOR_CRTC_RWCOL] >> 4) & 0x0F; - for (plane = 0, pmask = 1; plane < 4; plane++, pmask <<= 1) { - if (dc & pmask) { - fg |= (bg & pmask); - } else if (dev->latch[plane] & mask) { - fg |= pmask; - } - } - if (bg == fg) value |= mask; - } + for (unsigned char mask = 0x80; mask != 0; mask >>= 1) { + fg = 0; + dc = dev->crtc[INCOLOR_CRTC_RWCTRL] & 0x0F; + bg = (dev->crtc[INCOLOR_CRTC_RWCOL] >> 4) & 0x0F; + for (plane = 0, pmask = 1; plane < 4; plane++, pmask <<= 1) { + if (dc & pmask) { + fg |= (bg & pmask); + } else if (dev->latch[plane] & mask) { + fg |= pmask; + } + } + if (bg == fg) + value |= mask; + } - if (dev->crtc[INCOLOR_CRTC_RWCTRL] & INCOLOR_RWCTRL_POLARITY) - value = ~value; + if (dev->crtc[INCOLOR_CRTC_RWCTRL] & INCOLOR_RWCTRL_POLARITY) + value = ~value; return value; } - static void draw_char_rom(incolor_t *dev, int x, uint8_t chr, uint8_t attr) { - int i; - int elg, blk; - unsigned ull; - unsigned val; - unsigned ifg, ibg; - const unsigned char *fnt; - uint32_t fg, bg; - int cw = INCOLOR_CW; + int elg; + int blk; + unsigned ull; + unsigned val; + unsigned ifg; + unsigned ibg; + const unsigned char *fnt; + uint32_t fg; + uint32_t bg; + int cw = INCOLOR_CW; - blk = 0; - if (dev->ctrl & INCOLOR_CTRL_BLINK) - { - if (attr & 0x80) - { - blk = (dev->blink & 16); - } - attr &= 0x7f; - } + blk = 0; + if (dev->ctrl & INCOLOR_CTRL_BLINK) { + if (attr & 0x80) { + blk = (dev->blink & 16); + } + attr &= 0x7f; + } - if (dev->crtc[INCOLOR_CRTC_EXCEPT] & INCOLOR_EXCEPT_ALTATTR) - { - /* MDA-compatible attributes */ - ibg = 0; - ifg = 7; - if ((attr & 0x77) == 0x70) /* Invert */ - { - ifg = 0; - ibg = 7; - } - if (attr & 8) - { - ifg |= 8; /* High intensity FG */ - } - if (attr & 0x80) - { - ibg |= 8; /* High intensity BG */ - } - if ((attr & 0x77) == 0) /* Blank */ - { - ifg = ibg; - } - ull = ((attr & 0x07) == 1) ? 13 : 0xffff; - } - else - { - /* CGA-compatible attributes */ - ull = 0xffff; - ifg = attr & 0x0F; - ibg = (attr >> 4) & 0x0F; - } - if (dev->crtc[INCOLOR_CRTC_EXCEPT] & INCOLOR_EXCEPT_PALETTE) - { - fg = dev->rgb[dev->palette[ifg]]; - bg = dev->rgb[dev->palette[ibg]]; - } - else - { - fg = dev->rgb[defpal[ifg]]; - bg = dev->rgb[defpal[ibg]]; - } + if (dev->crtc[INCOLOR_CRTC_EXCEPT] & INCOLOR_EXCEPT_ALTATTR) { + /* MDA-compatible attributes */ + ibg = 0; + ifg = 7; + if ((attr & 0x77) == 0x70) /* Invert */ + { + ifg = 0; + ibg = 7; + } + if (attr & 8) { + ifg |= 8; /* High intensity FG */ + } + if (attr & 0x80) { + ibg |= 8; /* High intensity BG */ + } + if ((attr & 0x77) == 0) /* Blank */ + { + ifg = ibg; + } + ull = ((attr & 0x07) == 1) ? 13 : 0xffff; + } else { + /* CGA-compatible attributes */ + ull = 0xffff; + ifg = attr & 0x0F; + ibg = (attr >> 4) & 0x0F; + } + if (dev->crtc[INCOLOR_CRTC_EXCEPT] & INCOLOR_EXCEPT_PALETTE) { + fg = dev->rgb[dev->palette[ifg]]; + bg = dev->rgb[dev->palette[ibg]]; + } else { + fg = dev->rgb[defpal[ifg]]; + bg = dev->rgb[defpal[ibg]]; + } - /* ELG set to stretch 8px character to 9px */ - if (dev->crtc[INCOLOR_CRTC_XMODE] & INCOLOR_XMODE_90COL) - { - elg = 0; - } - else - { - elg = ((chr >= 0xc0) && (chr <= 0xdf)); - } + /* ELG set to stretch 8px character to 9px */ + if (dev->crtc[INCOLOR_CRTC_XMODE] & INCOLOR_XMODE_90COL) { + elg = 0; + } else { + elg = ((chr >= 0xc0) && (chr <= 0xdf)); + } - fnt = &(fontdatm[chr][dev->sc]); + fnt = &(fontdatm[chr][dev->sc]); - if (blk) - { - val = 0x000; /* Blinking, draw all background */ - } - else if (dev->sc == ull) - { - val = 0x1ff; /* Underscore, draw all foreground */ - } - else - { - val = fnt[0] << 1; - - if (elg) - { - val |= (val >> 1) & 1; - } - } - for (i = 0; i < cw; i++) - { - buffer32->line[dev->displine][x * cw + i] = (val & 0x100) ? fg : bg; - val = val << 1; - } + if (blk) { + val = 0x000; /* Blinking, draw all background */ + } else if (dev->sc == ull) { + val = 0x1ff; /* Underscore, draw all foreground */ + } else { + val = fnt[0] << 1; + + if (elg) { + val |= (val >> 1) & 1; + } + } + for (int i = 0; i < cw; i++) { + buffer32->line[dev->displine][x * cw + i] = (val & 0x100) ? fg : bg; + val = val << 1; + } } - static void draw_char_ram4(incolor_t *dev, int x, uint8_t chr, uint8_t attr) { - int i; - int elg, blk; - unsigned ull; - unsigned val[4]; - unsigned ifg, ibg, cfg, pmask, plane; - const unsigned char *fnt; - uint32_t fg; - int cw = INCOLOR_CW; - int blink = dev->ctrl & INCOLOR_CTRL_BLINK; - int altattr = dev->crtc[INCOLOR_CRTC_EXCEPT] & INCOLOR_EXCEPT_ALTATTR; - int palette = dev->crtc[INCOLOR_CRTC_EXCEPT] & INCOLOR_EXCEPT_PALETTE; + int elg; + int blk; + unsigned ull; + unsigned val[4]; + unsigned ifg; + unsigned ibg; + unsigned cfg; + unsigned pmask; + const unsigned char *fnt; + uint32_t fg; + int cw = INCOLOR_CW; + int blink = dev->ctrl & INCOLOR_CTRL_BLINK; + int altattr = dev->crtc[INCOLOR_CRTC_EXCEPT] & INCOLOR_EXCEPT_ALTATTR; + int palette = dev->crtc[INCOLOR_CRTC_EXCEPT] & INCOLOR_EXCEPT_PALETTE; - blk = 0; - if (blink) - { - if (attr & 0x80) - { - blk = (dev->blink & 16); - } - attr &= 0x7f; - } + blk = 0; + if (blink) { + if (attr & 0x80) { + blk = (dev->blink & 16); + } + attr &= 0x7f; + } - if (altattr) - { - /* MDA-compatible attributes */ - ibg = 0; - ifg = 7; - if ((attr & 0x77) == 0x70) /* Invert */ - { - ifg = 0; - ibg = 7; - } - if (attr & 8) - { - ifg |= 8; /* High intensity FG */ - } - if (attr & 0x80) - { - ibg |= 8; /* High intensity BG */ - } - if ((attr & 0x77) == 0) /* Blank */ - { - ifg = ibg; - } - ull = ((attr & 0x07) == 1) ? 13 : 0xffff; - } - else - { - /* CGA-compatible attributes */ - ull = 0xffff; - ifg = attr & 0x0F; - ibg = (attr >> 4) & 0x0F; - } - if (dev->crtc[INCOLOR_CRTC_XMODE] & INCOLOR_XMODE_90COL) - { - elg = 0; - } - else - { - elg = ((chr >= 0xc0) && (chr <= 0xdf)); - } - fnt = dev->vram + 0x4000 + 16 * chr + dev->sc; + if (altattr) { + /* MDA-compatible attributes */ + ibg = 0; + ifg = 7; + if ((attr & 0x77) == 0x70) /* Invert */ + { + ifg = 0; + ibg = 7; + } + if (attr & 8) { + ifg |= 8; /* High intensity FG */ + } + if (attr & 0x80) { + ibg |= 8; /* High intensity BG */ + } + if ((attr & 0x77) == 0) /* Blank */ + { + ifg = ibg; + } + ull = ((attr & 0x07) == 1) ? 13 : 0xffff; + } else { + /* CGA-compatible attributes */ + ull = 0xffff; + ifg = attr & 0x0F; + ibg = (attr >> 4) & 0x0F; + } + if (dev->crtc[INCOLOR_CRTC_XMODE] & INCOLOR_XMODE_90COL) { + elg = 0; + } else { + elg = ((chr >= 0xc0) && (chr <= 0xdf)); + } + fnt = dev->vram + 0x4000 + 16 * chr + dev->sc; - if (blk) - { - /* Blinking, draw all background */ - val[0] = val[1] = val[2] = val[3] = 0x000; - } - else if (dev->sc == ull) - { - /* Underscore, draw all foreground */ - val[0] = val[1] = val[2] = val[3] = 0x1ff; - } - else - { - val[0] = fnt[0x00000] << 1; - val[1] = fnt[0x10000] << 1; - val[2] = fnt[0x20000] << 1; - val[3] = fnt[0x30000] << 1; - - if (elg) - { - val[0] |= (val[0] >> 1) & 1; - val[1] |= (val[1] >> 1) & 1; - val[2] |= (val[2] >> 1) & 1; - val[3] |= (val[3] >> 1) & 1; - } - } - for (i = 0; i < cw; i++) - { - /* Generate pixel colour */ - cfg = 0; - pmask = 1; - for (plane = 0; plane < 4; plane++, pmask = pmask << 1) - { - if (val[plane] & 0x100) cfg |= (ifg & pmask); - else cfg |= (ibg & pmask); - } - /* cfg = colour of foreground pixels */ - if (altattr && (attr & 0x77) == 0) cfg = ibg; /* 'blank' attribute */ - if (palette) - { - fg = dev->rgb[dev->palette[cfg]]; - } - else - { - fg = dev->rgb[defpal[cfg]]; - } - - buffer32->line[dev->displine][x * cw + i] = fg; - val[0] = val[0] << 1; - val[1] = val[1] << 1; - val[2] = val[2] << 1; - val[3] = val[3] << 1; - } + if (blk) { + /* Blinking, draw all background */ + val[0] = val[1] = val[2] = val[3] = 0x000; + } else if (dev->sc == ull) { + /* Underscore, draw all foreground */ + val[0] = val[1] = val[2] = val[3] = 0x1ff; + } else { + val[0] = fnt[0x00000] << 1; + val[1] = fnt[0x10000] << 1; + val[2] = fnt[0x20000] << 1; + val[3] = fnt[0x30000] << 1; + + if (elg) { + val[0] |= (val[0] >> 1) & 1; + val[1] |= (val[1] >> 1) & 1; + val[2] |= (val[2] >> 1) & 1; + val[3] |= (val[3] >> 1) & 1; + } + } + for (int i = 0; i < cw; i++) { + /* Generate pixel colour */ + cfg = 0; + pmask = 1; + for (uint8_t plane = 0; plane < 4; plane++, pmask = pmask << 1) { + if (val[plane] & 0x100) + cfg |= (ifg & pmask); + else + cfg |= (ibg & pmask); + } + /* cfg = colour of foreground pixels */ + if (altattr && (attr & 0x77) == 0) + cfg = ibg; /* 'blank' attribute */ + if (palette) { + fg = dev->rgb[dev->palette[cfg]]; + } else { + fg = dev->rgb[defpal[cfg]]; + } + + buffer32->line[dev->displine][x * cw + i] = fg; + val[0] = val[0] << 1; + val[1] = val[1] << 1; + val[2] = val[2] << 1; + val[3] = val[3] << 1; + } } - static void draw_char_ram48(incolor_t *dev, int x, uint8_t chr, uint8_t attr) { - int i; - int elg, blk, ul, ol, bld; - unsigned ull, oll, ulc = 0, olc = 0; - unsigned val[4]; - unsigned ifg = 0, ibg, cfg, pmask, plane; - const unsigned char *fnt; - uint32_t fg; - int cw = INCOLOR_CW; - int blink = dev->ctrl & INCOLOR_CTRL_BLINK; - int altattr = dev->crtc[INCOLOR_CRTC_EXCEPT] & INCOLOR_EXCEPT_ALTATTR; - int palette = dev->crtc[INCOLOR_CRTC_EXCEPT] & INCOLOR_EXCEPT_PALETTE; - int font = (attr & 0x0F); + int elg; + int blk; + int ul; + int ol; + int bld; + unsigned ull; + unsigned oll; + unsigned ulc = 0; + unsigned olc = 0; + unsigned val[4]; + unsigned ifg = 0; + unsigned ibg; + unsigned cfg; + unsigned pmask; + const unsigned char *fnt; + uint32_t fg; + int cw = INCOLOR_CW; + int blink = dev->ctrl & INCOLOR_CTRL_BLINK; + int altattr = dev->crtc[INCOLOR_CRTC_EXCEPT] & INCOLOR_EXCEPT_ALTATTR; + int palette = dev->crtc[INCOLOR_CRTC_EXCEPT] & INCOLOR_EXCEPT_PALETTE; + int font = (attr & 0x0F); - if (font >= 12) font &= 7; + if (font >= 12) + font &= 7; - blk = 0; - if (blink && altattr) - { - if (attr & 0x40) - { - blk = (dev->blink & 16); - } - attr &= 0x7f; - } - if (altattr) - { - /* MDA-compatible attributes */ - if (blink) - { - ibg = (attr & 0x80) ? 8 : 0; - bld = 0; - ol = (attr & 0x20) ? 1 : 0; - ul = (attr & 0x10) ? 1 : 0; - } - else - { - bld = (attr & 0x80) ? 1 : 0; - ibg = (attr & 0x40) ? 0x0F : 0; - ol = (attr & 0x20) ? 1 : 0; - ul = (attr & 0x10) ? 1 : 0; - } - } - else - { - /* CGA-compatible attributes */ - ibg = 0; - ifg = (attr >> 4) & 0x0F; - ol = 0; - ul = 0; - bld = 0; - } - if (ul) - { - ull = dev->crtc[INCOLOR_CRTC_UNDER] & 0x0F; - ulc = (dev->crtc[INCOLOR_CRTC_UNDER] >> 4) & 0x0F; - if (ulc == 0) ulc = 7; - } - else - { - ull = 0xFFFF; - } - if (ol) - { - oll = dev->crtc[INCOLOR_CRTC_OVER] & 0x0F; - olc = (dev->crtc[INCOLOR_CRTC_OVER] >> 4) & 0x0F; - if (olc == 0) olc = 7; - } - else - { - oll = 0xFFFF; - } + blk = 0; + if (blink && altattr) { + if (attr & 0x40) { + blk = (dev->blink & 16); + } + attr &= 0x7f; + } + if (altattr) { + /* MDA-compatible attributes */ + if (blink) { + ibg = (attr & 0x80) ? 8 : 0; + bld = 0; + ol = (attr & 0x20) ? 1 : 0; + ul = (attr & 0x10) ? 1 : 0; + } else { + bld = (attr & 0x80) ? 1 : 0; + ibg = (attr & 0x40) ? 0x0F : 0; + ol = (attr & 0x20) ? 1 : 0; + ul = (attr & 0x10) ? 1 : 0; + } + } else { + /* CGA-compatible attributes */ + ibg = 0; + ifg = (attr >> 4) & 0x0F; + ol = 0; + ul = 0; + bld = 0; + } + if (ul) { + ull = dev->crtc[INCOLOR_CRTC_UNDER] & 0x0F; + ulc = (dev->crtc[INCOLOR_CRTC_UNDER] >> 4) & 0x0F; + if (ulc == 0) + ulc = 7; + } else { + ull = 0xFFFF; + } + if (ol) { + oll = dev->crtc[INCOLOR_CRTC_OVER] & 0x0F; + olc = (dev->crtc[INCOLOR_CRTC_OVER] >> 4) & 0x0F; + if (olc == 0) + olc = 7; + } else { + oll = 0xFFFF; + } - if (dev->crtc[INCOLOR_CRTC_XMODE] & INCOLOR_XMODE_90COL) - { - elg = 0; - } - else - { - elg = ((chr >= 0xc0) && (chr <= 0xdf)); - } - fnt = dev->vram + 0x4000 + 16 * chr + 4096 * font + dev->sc; + if (dev->crtc[INCOLOR_CRTC_XMODE] & INCOLOR_XMODE_90COL) { + elg = 0; + } else { + elg = ((chr >= 0xc0) && (chr <= 0xdf)); + } + fnt = dev->vram + 0x4000 + 16 * chr + 4096 * font + dev->sc; - if (blk) - { - /* Blinking, draw all background */ - val[0] = val[1] = val[2] = val[3] = 0x000; - } - else if (dev->sc == ull) - { - /* Underscore, draw all foreground */ - val[0] = val[1] = val[2] = val[3] = 0x1ff; - } - else - { - val[0] = fnt[0x00000] << 1; - val[1] = fnt[0x10000] << 1; - val[2] = fnt[0x20000] << 1; - val[3] = fnt[0x30000] << 1; - - if (elg) - { - val[0] |= (val[0] >> 1) & 1; - val[1] |= (val[1] >> 1) & 1; - val[2] |= (val[2] >> 1) & 1; - val[3] |= (val[3] >> 1) & 1; - } - if (bld) - { - val[0] |= (val[0] >> 1); - val[1] |= (val[1] >> 1); - val[2] |= (val[2] >> 1); - val[3] |= (val[3] >> 1); - } - } - for (i = 0; i < cw; i++) - { - /* Generate pixel colour */ - cfg = 0; - pmask = 1; - if (dev->sc == oll) - { - cfg = olc ^ ibg; /* Strikethrough */ - } - else if (dev->sc == ull) - { - cfg = ulc ^ ibg; /* Underline */ - } - else - { - for (plane = 0; plane < 4; plane++, pmask = pmask << 1) - { - if (val[plane] & 0x100) - { - if (altattr) cfg |= ((~ibg) & pmask); - else cfg |= ((~ifg) & pmask); - } - else if (altattr) cfg |= (ibg & pmask); - } - } - if (palette) - { - fg = dev->rgb[dev->palette[cfg]]; - } - else - { - fg = dev->rgb[defpal[cfg]]; - } - - buffer32->line[dev->displine][x * cw + i] = fg; - val[0] = val[0] << 1; - val[1] = val[1] << 1; - val[2] = val[2] << 1; - val[3] = val[3] << 1; - } + if (blk) { + /* Blinking, draw all background */ + val[0] = val[1] = val[2] = val[3] = 0x000; + } else if (dev->sc == ull) { + /* Underscore, draw all foreground */ + val[0] = val[1] = val[2] = val[3] = 0x1ff; + } else { + val[0] = fnt[0x00000] << 1; + val[1] = fnt[0x10000] << 1; + val[2] = fnt[0x20000] << 1; + val[3] = fnt[0x30000] << 1; + + if (elg) { + val[0] |= (val[0] >> 1) & 1; + val[1] |= (val[1] >> 1) & 1; + val[2] |= (val[2] >> 1) & 1; + val[3] |= (val[3] >> 1) & 1; + } + if (bld) { + val[0] |= (val[0] >> 1); + val[1] |= (val[1] >> 1); + val[2] |= (val[2] >> 1); + val[3] |= (val[3] >> 1); + } + } + for (int i = 0; i < cw; i++) { + /* Generate pixel colour */ + cfg = 0; + pmask = 1; + if (dev->sc == oll) { + cfg = olc ^ ibg; /* Strikethrough */ + } else if (dev->sc == ull) { + cfg = ulc ^ ibg; /* Underline */ + } else { + for (uint8_t plane = 0; plane < 4; plane++, pmask = pmask << 1) { + if (val[plane] & 0x100) { + if (altattr) + cfg |= ((~ibg) & pmask); + else + cfg |= ((~ifg) & pmask); + } else if (altattr) + cfg |= (ibg & pmask); + } + } + if (palette) { + fg = dev->rgb[dev->palette[cfg]]; + } else { + fg = dev->rgb[defpal[cfg]]; + } + + buffer32->line[dev->displine][x * cw + i] = fg; + val[0] = val[0] << 1; + val[1] = val[1] << 1; + val[2] = val[2] << 1; + val[3] = val[3] << 1; + } } - static void text_line(incolor_t *dev, uint16_t ca) { - int drawcursor; - int x, c; - uint8_t chr, attr; + int drawcursor; + uint8_t chr; + uint8_t attr; uint32_t col; - for (x = 0; x < dev->crtc[1]; x++) { - if (dev->ctrl & 8) { - chr = dev->vram[(dev->ma << 1) & 0xfff]; - attr = dev->vram[((dev->ma << 1) + 1) & 0xfff]; - } else - chr = attr = 0; + for (uint8_t x = 0; x < dev->crtc[1]; x++) { + if (dev->ctrl & 8) { + chr = dev->vram[(dev->ma << 1) & 0x3fff]; + attr = dev->vram[((dev->ma << 1) + 1) & 0x3fff]; + } else + chr = attr = 0; - drawcursor = ((dev->ma == ca) && dev->con && dev->cursoron); + drawcursor = ((dev->ma == ca) && dev->con && dev->cursoron); - switch (dev->crtc[INCOLOR_CRTC_XMODE] & 5) { - case 0: - case 4: /* ROM font */ - draw_char_rom(dev, x, chr, attr); - break; + switch (dev->crtc[INCOLOR_CRTC_XMODE] & 5) { + case 0: + case 4: /* ROM font */ + draw_char_rom(dev, x, chr, attr); + break; - case 1: /* 4k RAMfont */ - draw_char_ram4(dev, x, chr, attr); - break; + case 1: /* 4k RAMfont */ + draw_char_ram4(dev, x, chr, attr); + break; - case 5: /* 48k RAMfont */ - draw_char_ram48(dev, x, chr, attr); - break; - } - ++dev->ma; + case 5: /* 48k RAMfont */ + draw_char_ram48(dev, x, chr, attr); + break; - if (drawcursor) { - int cw = INCOLOR_CW; - uint8_t ink = dev->crtc[INCOLOR_CRTC_EXCEPT] & INCOLOR_EXCEPT_CURSOR; - if (ink == 0) ink = (attr & 0x08) | 7; + default: + break; + } + ++dev->ma; - /* In MDA-compatible mode, cursor brightness comes from - * background */ - if (dev->crtc[INCOLOR_CRTC_EXCEPT] & INCOLOR_EXCEPT_ALTATTR) - { - ink = (attr & 0x08) | (ink & 7); - } - if (dev->crtc[INCOLOR_CRTC_EXCEPT] & INCOLOR_EXCEPT_PALETTE) - { - col = dev->rgb[dev->palette[ink]]; - } - else - { - col = dev->rgb[defpal[ink]]; - } - for (c = 0; c < cw; c++) - { - buffer32->line[dev->displine][x * cw + c] = col; - } - } + if (drawcursor) { + int cw = INCOLOR_CW; + uint8_t ink = dev->crtc[INCOLOR_CRTC_EXCEPT] & INCOLOR_EXCEPT_CURSOR; + if (ink == 0) + ink = (attr & 0x08) | 7; + + /* In MDA-compatible mode, cursor brightness comes from + * background */ + if (dev->crtc[INCOLOR_CRTC_EXCEPT] & INCOLOR_EXCEPT_ALTATTR) { + ink = (attr & 0x08) | (ink & 7); + } + if (dev->crtc[INCOLOR_CRTC_EXCEPT] & INCOLOR_EXCEPT_PALETTE) { + col = dev->rgb[dev->palette[ink]]; + } else { + col = dev->rgb[defpal[ink]]; + } + for (int c = 0; c < cw; c++) { + buffer32->line[dev->displine][x * cw + c] = col; + } + } } } - static void graphics_line(incolor_t *dev) { - uint8_t mask; + uint8_t mask; uint16_t ca; - int x, c, plane, col; - uint8_t ink; + int plane; + int col; + uint8_t ink; uint16_t val[4]; /* Graphics mode. */ ca = (dev->sc & 3) * 0x2000; if ((dev->ctrl & INCOLOR_CTRL_PAGE1) && (dev->ctrl2 & INCOLOR_CTRL2_PAGE1)) - ca += 0x8000; + ca += 0x8000; - for (x = 0; x < dev->crtc[1]; x++) { - mask = dev->crtc[INCOLOR_CRTC_MASK]; /* Planes to display */ - for (plane = 0; plane < 4; plane++, mask = mask >> 1) - { - if (dev->ctrl & 8) { - if (mask & 1) - val[plane] = (dev->vram[((dev->ma << 1) & 0x1fff) + ca + 0x10000 * plane] << 8) | - dev->vram[((dev->ma << 1) & 0x1fff) + ca + 0x10000 * plane + 1]; - else val[plane] = 0; - } else - val[plane] = 0; - } - dev->ma++; + for (uint8_t x = 0; x < dev->crtc[1]; x++) { + mask = dev->crtc[INCOLOR_CRTC_MASK]; /* Planes to display */ + for (plane = 0; plane < 4; plane++, mask = mask >> 1) { + if (dev->ctrl & 8) { + if (mask & 1) + val[plane] = (dev->vram[((dev->ma << 1) & 0x1fff) + ca + 0x10000 * plane] << 8) | dev->vram[((dev->ma << 1) & 0x1fff) + ca + 0x10000 * plane + 1]; + else + val[plane] = 0; + } else + val[plane] = 0; + } + dev->ma++; - for (c = 0; c < 16; c++) - { - ink = 0; - for (plane = 0; plane < 4; plane++) - { - ink = ink >> 1; - if (val[plane] & 0x8000) ink |= 8; - val[plane] = val[plane] << 1; - } - /* Is palette in use? */ - if (dev->crtc[INCOLOR_CRTC_EXCEPT] & INCOLOR_EXCEPT_PALETTE) - col = dev->palette[ink]; - else col = defpal[ink]; + for (uint8_t c = 0; c < 16; c++) { + ink = 0; + for (plane = 0; plane < 4; plane++) { + ink = ink >> 1; + if (val[plane] & 0x8000) + ink |= 8; + val[plane] = val[plane] << 1; + } + /* Is palette in use? */ + if (dev->crtc[INCOLOR_CRTC_EXCEPT] & INCOLOR_EXCEPT_PALETTE) + col = dev->palette[ink]; + else + col = defpal[ink]; - buffer32->line[dev->displine][(x << 4) + c] = dev->rgb[col]; - } + buffer32->line[dev->displine][(x << 4) + c] = dev->rgb[col]; + } } } - static void incolor_poll(void *priv) { - incolor_t *dev = (incolor_t *)priv; - uint16_t ca = (dev->crtc[15] | (dev->crtc[14] << 8)) & 0x3fff; - int x; - int oldvc; - int oldsc; + incolor_t *dev = (incolor_t *) priv; + uint16_t ca = (dev->crtc[15] | (dev->crtc[14] << 8)) & 0x3fff; + int x; + int oldvc; + int oldsc; + int cw = INCOLOR_CW; - if (! dev->linepos) { - timer_advance_u64(&dev->timer, dev->dispofftime); - dev->stat |= 1; - dev->linepos = 1; - oldsc = dev->sc; - if ((dev->crtc[8] & 3) == 3) - dev->sc = (dev->sc << 1) & 7; + if (!dev->linepos) { + timer_advance_u64(&dev->timer, dev->dispofftime); + dev->stat |= 1; + dev->linepos = 1; + oldsc = dev->sc; + if ((dev->crtc[8] & 3) == 3) + dev->sc = (dev->sc << 1) & 7; - if (dev->dispon) { - if (dev->displine < dev->firstline) { - dev->firstline = dev->displine; - video_wait_for_buffer(); - } - dev->lastline = dev->displine; - if ((dev->ctrl & INCOLOR_CTRL_GRAPH) && (dev->ctrl2 & INCOLOR_CTRL2_GRAPH)) - graphics_line(dev); - else - text_line(dev, ca); - } - dev->sc = oldsc; - if (dev->vc == dev->crtc[7] && !dev->sc) - dev->stat |= 8; - dev->displine++; - if (dev->displine >= 500) - dev->displine = 0; + if (dev->dispon) { + if (dev->displine < dev->firstline) { + dev->firstline = dev->displine; + video_wait_for_buffer(); + } + dev->lastline = dev->displine; + if ((dev->ctrl & INCOLOR_CTRL_GRAPH) && (dev->ctrl2 & INCOLOR_CTRL2_GRAPH)) + graphics_line(dev); + else + text_line(dev, ca); + } + dev->sc = oldsc; + if (dev->vc == dev->crtc[7] && !dev->sc) + dev->stat |= 8; + dev->displine++; + if (dev->displine >= 500) + dev->displine = 0; } else { - timer_advance_u64(&dev->timer, dev->dispontime); - if (dev->dispon) - dev->stat &= ~1; - dev->linepos = 0; - if (dev->vsynctime) { - dev->vsynctime--; - if (! dev->vsynctime) - dev->stat &= ~8; - } + timer_advance_u64(&dev->timer, dev->dispontime); + if (dev->dispon) + dev->stat &= ~1; + dev->linepos = 0; + if (dev->vsynctime) { + dev->vsynctime--; + if (!dev->vsynctime) + dev->stat &= ~8; + } - if (dev->sc == (dev->crtc[11] & 31) || ((dev->crtc[8] & 3) == 3 && dev->sc == ((dev->crtc[11] & 31) >> 1))) { - dev->con = 0; - dev->coff = 1; - } + if (dev->sc == (dev->crtc[11] & 31) || ((dev->crtc[8] & 3) == 3 && dev->sc == ((dev->crtc[11] & 31) >> 1))) { + dev->con = 0; + dev->coff = 1; + } - if (dev->vadj) { - dev->sc++; - dev->sc &= 31; - dev->ma = dev->maback; - dev->vadj--; - if (! dev->vadj) { - dev->dispon = 1; - dev->ma = dev->maback = (dev->crtc[13] | (dev->crtc[12] << 8)) & 0x3fff; - dev->sc = 0; - } - } else if (dev->sc == dev->crtc[9] || ((dev->crtc[8] & 3) == 3 && dev->sc == (dev->crtc[9] >> 1))) { - dev->maback = dev->ma; - dev->sc = 0; - oldvc = dev->vc; - dev->vc++; - dev->vc &= 127; - if (dev->vc == dev->crtc[6]) - dev->dispon = 0; - if (oldvc == dev->crtc[4]) { - dev->vc = 0; - dev->vadj = dev->crtc[5]; - if (!dev->vadj) dev->dispon=1; - if (!dev->vadj) dev->ma = dev->maback = (dev->crtc[13] | (dev->crtc[12] << 8)) & 0x3fff; - if ((dev->crtc[10] & 0x60) == 0x20) dev->cursoron = 0; - else dev->cursoron = dev->blink & 16; - } + if (dev->vadj) { + dev->sc++; + dev->sc &= 31; + dev->ma = dev->maback; + dev->vadj--; + if (!dev->vadj) { + dev->dispon = 1; + dev->ma = dev->maback = (dev->crtc[13] | (dev->crtc[12] << 8)) & 0x3fff; + dev->sc = 0; + } + } else if (dev->sc == dev->crtc[9] || ((dev->crtc[8] & 3) == 3 && dev->sc == (dev->crtc[9] >> 1))) { + dev->maback = dev->ma; + dev->sc = 0; + oldvc = dev->vc; + dev->vc++; + dev->vc &= 127; + if (dev->vc == dev->crtc[6]) + dev->dispon = 0; + if (oldvc == dev->crtc[4]) { + dev->vc = 0; + dev->vadj = dev->crtc[5]; + if (!dev->vadj) + dev->dispon = 1; + if (!dev->vadj) + dev->ma = dev->maback = (dev->crtc[13] | (dev->crtc[12] << 8)) & 0x3fff; + if ((dev->crtc[10] & 0x60) == 0x20) + dev->cursoron = 0; + else + dev->cursoron = dev->blink & 16; + } - if (dev->vc == dev->crtc[7]) { - dev->dispon = 0; - dev->displine = 0; - dev->vsynctime = 16; - if (dev->crtc[7]) { - if ((dev->ctrl & INCOLOR_CTRL_GRAPH) && (dev->ctrl2 & INCOLOR_CTRL2_GRAPH)) - x = dev->crtc[1] << 4; - else - x = dev->crtc[1] * 9; - dev->lastline++; - if ((dev->ctrl & 8) && - ((x != xsize) || ((dev->lastline - dev->firstline) != ysize) || video_force_resize_get())) { - xsize = x; - ysize = dev->lastline - dev->firstline; - if (xsize < 64) xsize = 656; - if (ysize < 32) ysize = 200; - set_screen_size(xsize, ysize); + if (dev->vc == dev->crtc[7]) { + dev->dispon = 0; + dev->displine = 0; + dev->vsynctime = 16; + if (dev->crtc[7]) { + if ((dev->ctrl & INCOLOR_CTRL_GRAPH) && (dev->ctrl2 & INCOLOR_CTRL2_GRAPH)) + x = dev->crtc[1] << 4; + else + x = dev->crtc[1] * cw; + dev->lastline++; + if ((dev->ctrl & 8) && ((x != xsize) || ((dev->lastline - dev->firstline) != ysize) || video_force_resize_get())) { + xsize = x; + ysize = dev->lastline - dev->firstline; + if (xsize < 64) + xsize = 656; + if (ysize < 32) + ysize = 200; + set_screen_size(xsize, ysize); - if (video_force_resize_get()) - video_force_resize_set(0); - } - video_blit_memtoscreen(0, dev->firstline, xsize, dev->lastline - dev->firstline); - frames++; - if ((dev->ctrl & INCOLOR_CTRL_GRAPH) && (dev->ctrl2 & INCOLOR_CTRL2_GRAPH)) { - video_res_x = dev->crtc[1] * 16; - video_res_y = dev->crtc[6] * 4; - video_bpp = 1; - } else { - video_res_x = dev->crtc[1]; - video_res_y = dev->crtc[6]; - video_bpp = 0; - } - } - dev->firstline = 1000; - dev->lastline = 0; - dev->blink++; - } - } else { - dev->sc++; - dev->sc &= 31; - dev->ma = dev->maback; - } + if (video_force_resize_get()) + video_force_resize_set(0); + } + video_blit_memtoscreen(0, dev->firstline, xsize, dev->lastline - dev->firstline); + frames++; + if ((dev->ctrl & INCOLOR_CTRL_GRAPH) && (dev->ctrl2 & INCOLOR_CTRL2_GRAPH)) { + video_res_x = dev->crtc[1] * 16; + video_res_y = dev->crtc[6] * 4; + video_bpp = 1; + } else { + video_res_x = dev->crtc[1]; + video_res_y = dev->crtc[6]; + video_bpp = 0; + } + } + dev->firstline = 1000; + dev->lastline = 0; + dev->blink++; + } + } else { + dev->sc++; + dev->sc &= 31; + dev->ma = dev->maback; + } - if ((dev->sc == (dev->crtc[10] & 31) || ((dev->crtc[8] & 3) == 3 && dev->sc == ((dev->crtc[10] & 31) >> 1)))) - dev->con = 1; + if (dev->sc == (dev->crtc[10] & 31) || ((dev->crtc[8] & 3) == 3 && dev->sc == ((dev->crtc[10] & 31) >> 1))) + dev->con = 1; } } - static void * -incolor_init(const device_t *info) +incolor_init(UNUSED(const device_t *info)) { incolor_t *dev; - int c; + int c; - dev = (incolor_t *)malloc(sizeof(incolor_t)); + dev = (incolor_t *) malloc(sizeof(incolor_t)); memset(dev, 0x00, sizeof(incolor_t)); - dev->vram = (uint8_t *)malloc(0x40000); /* 4 planes of 64k */ + dev->vram = (uint8_t *) malloc(0x40000); /* 4 planes of 64k */ - timer_add(&dev->timer, incolor_poll, dev, 1); + timer_add(&dev->timer, incolor_poll, dev, 1); mem_mapping_add(&dev->mapping, 0xb0000, 0x08000, - incolor_read,NULL,NULL, incolor_write,NULL,NULL, - NULL, MEM_MAPPING_EXTERNAL, dev); + incolor_read, NULL, NULL, incolor_write, NULL, NULL, + NULL, MEM_MAPPING_EXTERNAL, dev); io_sethandler(0x03b0, 16, - incolor_in,NULL,NULL, incolor_out,NULL,NULL, dev); + incolor_in, NULL, NULL, incolor_out, NULL, NULL, dev); for (c = 0; c < 64; c++) { - dev->rgb[c] = makecol32(init_rgb[c][0], init_rgb[c][1], init_rgb[c][2]); + dev->rgb[c] = makecol32(init_rgb[c][0], init_rgb[c][1], init_rgb[c][2]); } /* Initialise CRTC regs to safe values */ - dev->crtc[INCOLOR_CRTC_MASK ] = 0x0F; /* All planes displayed */ + dev->crtc[INCOLOR_CRTC_MASK] = 0x0F; /* All planes displayed */ dev->crtc[INCOLOR_CRTC_RWCTRL] = INCOLOR_RWCTRL_POLARITY; - dev->crtc[INCOLOR_CRTC_RWCOL ] = 0x0F; /* White on black */ + dev->crtc[INCOLOR_CRTC_RWCOL] = 0x0F; /* White on black */ dev->crtc[INCOLOR_CRTC_EXCEPT] = INCOLOR_EXCEPT_ALTATTR; - for (c = 0; c < 16; c++) - dev->palette[c] = defpal[c]; + for (c = 0; c < 16; c++) + dev->palette[c] = defpal[c]; dev->palette_idx = 0; video_inform(VIDEO_FLAG_TYPE_MDA, &timing_incolor); @@ -1067,39 +1023,38 @@ incolor_init(const device_t *info) return dev; } - static void incolor_close(void *priv) { - incolor_t *dev = (incolor_t *)priv; + incolor_t *dev = (incolor_t *) priv; if (!dev) - return; + return; if (dev->vram) - free(dev->vram); + free(dev->vram); free(dev); } - static void speed_changed(void *priv) { - incolor_t *dev = (incolor_t *)priv; - + incolor_t *dev = (incolor_t *) priv; + recalc_timings(dev); } - const device_t incolor_device = { - "Hercules InColor", - "incolor", - DEVICE_ISA, - 0, - incolor_init, incolor_close, NULL, - { NULL }, - speed_changed, - NULL, - NULL + .name = "Hercules InColor", + .internal_name = "incolor", + .flags = DEVICE_ISA, + .local = 0, + .init = incolor_init, + .close = incolor_close, + .reset = NULL, + { .available = NULL }, + .speed_changed = speed_changed, + .force_redraw = NULL, + .config = NULL }; diff --git a/src/video/vid_mda.c b/src/video/vid_mda.c index ba95c9b81..a53199324 100644 --- a/src/video/vid_mda.c +++ b/src/video/vid_mda.c @@ -1,20 +1,20 @@ /* - * 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. + * 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. + * This file is part of the 86Box distribution. * - * MDA emulation. + * MDA emulation. * * * - * Authors: Sarah Walker, - * Miran Grca, + * Authors: Sarah Walker, + * Miran Grca, * - * Copyright 2008-2019 Sarah Walker. - * Copyright 2016-2019 Miran Grca. + * Copyright 2008-2019 Sarah Walker. + * Copyright 2016-2019 Miran Grca. */ #include #include @@ -31,338 +31,370 @@ #include <86box/device.h> #include <86box/video.h> #include <86box/vid_mda.h> +#include <86box/plat_unused.h> static int mdacols[256][2][2]; -static video_timings_t timing_mda = {VIDEO_ISA, 8, 16, 32, 8, 16, 32}; +static video_timings_t timing_mda = { .type = VIDEO_ISA, .write_b = 8, .write_w = 16, .write_l = 32, .read_b = 8, .read_w = 16, .read_l = 32 }; void mda_recalctimings(mda_t *mda); -void mda_out(uint16_t addr, uint8_t val, void *p) +void +mda_out(uint16_t addr, uint8_t val, void *priv) { - mda_t *mda = (mda_t *)p; - switch (addr) - { - case 0x3b0: case 0x3b2: case 0x3b4: case 0x3b6: - mda->crtcreg = val & 31; - return; - case 0x3b1: case 0x3b3: case 0x3b5: case 0x3b7: - mda->crtc[mda->crtcreg] = val; - if (mda->crtc[10] == 6 && mda->crtc[11] == 7) /*Fix for Generic Turbo XT BIOS, which sets up cursor registers wrong*/ - { - mda->crtc[10] = 0xb; - mda->crtc[11] = 0xc; + mda_t *mda = (mda_t *) priv; + + switch (addr) { + case 0x3b0: + case 0x3b2: + case 0x3b4: + case 0x3b6: + mda->crtcreg = val & 31; + return; + case 0x3b1: + case 0x3b3: + case 0x3b5: + case 0x3b7: + mda->crtc[mda->crtcreg] = val; + if (mda->crtc[10] == 6 && mda->crtc[11] == 7) /*Fix for Generic Turbo XT BIOS, which sets up cursor registers wrong*/ + { + mda->crtc[10] = 0xb; + mda->crtc[11] = 0xc; + } + mda_recalctimings(mda); + return; + case 0x3b8: + mda->ctrl = val; + return; + + default: + break; + } +} + +uint8_t +mda_in(uint16_t addr, void *priv) +{ + const mda_t *mda = (mda_t *) priv; + + switch (addr) { + case 0x3b0: + case 0x3b2: + case 0x3b4: + case 0x3b6: + return mda->crtcreg; + case 0x3b1: + case 0x3b3: + case 0x3b5: + case 0x3b7: + return mda->crtc[mda->crtcreg]; + case 0x3ba: + return mda->stat | 0xF0; + + default: + break; + } + return 0xff; +} + +void +mda_write(uint32_t addr, uint8_t val, void *priv) +{ + mda_t *mda = (mda_t *) priv; + mda->vram[addr & 0xfff] = val; +} + +uint8_t +mda_read(uint32_t addr, void *priv) +{ + const mda_t *mda = (mda_t *) priv; + + return mda->vram[addr & 0xfff]; +} + +void +mda_recalctimings(mda_t *mda) +{ + double _dispontime; + double _dispofftime; + double disptime; + disptime = mda->crtc[0] + 1; + _dispontime = mda->crtc[1]; + _dispofftime = disptime - _dispontime; + _dispontime *= MDACONST; + _dispofftime *= MDACONST; + mda->dispontime = (uint64_t) (_dispontime); + mda->dispofftime = (uint64_t) (_dispofftime); +} + +void +mda_poll(void *priv) +{ + mda_t *mda = (mda_t *) priv; + uint16_t ca = (mda->crtc[15] | (mda->crtc[14] << 8)) & 0x3fff; + int drawcursor; + int x; + int c; + int oldvc; + uint8_t chr; + uint8_t attr; + int oldsc; + int blink; + + VIDEO_MONITOR_PROLOGUE() + if (!mda->linepos) { + timer_advance_u64(&mda->timer, mda->dispofftime); + mda->stat |= 1; + mda->linepos = 1; + oldsc = mda->sc; + if ((mda->crtc[8] & 3) == 3) + mda->sc = (mda->sc << 1) & 7; + if (mda->dispon) { + if (mda->displine < mda->firstline) { + mda->firstline = mda->displine; + video_wait_for_buffer(); + } + mda->lastline = mda->displine; + for (x = 0; x < mda->crtc[1]; x++) { + chr = mda->vram[(mda->ma << 1) & 0xfff]; + attr = mda->vram[((mda->ma << 1) + 1) & 0xfff]; + drawcursor = ((mda->ma == ca) && mda->con && mda->cursoron); + blink = ((mda->blink & 16) && (mda->ctrl & 0x20) && (attr & 0x80) && !drawcursor); + if (mda->sc == 12 && ((attr & 7) == 1)) { + for (c = 0; c < 9; c++) + buffer32->line[mda->displine][(x * 9) + c] = mdacols[attr][blink][1]; + } else { + for (c = 0; c < 8; c++) + buffer32->line[mda->displine][(x * 9) + c] = mdacols[attr][blink][(fontdatm[chr + mda->fontbase][mda->sc] & (1 << (c ^ 7))) ? 1 : 0]; + if ((chr & ~0x1f) == 0xc0) + buffer32->line[mda->displine][(x * 9) + 8] = mdacols[attr][blink][fontdatm[chr + mda->fontbase][mda->sc] & 1]; + else + buffer32->line[mda->displine][(x * 9) + 8] = mdacols[attr][blink][0]; } - mda_recalctimings(mda); - return; - case 0x3b8: - mda->ctrl = val; - return; + mda->ma++; + if (drawcursor) { + for (c = 0; c < 9; c++) + buffer32->line[mda->displine][(x * 9) + c] ^= mdacols[attr][0][1]; + } + } + + video_process_8(mda->crtc[1] * 9, mda->displine); } -} - -uint8_t mda_in(uint16_t addr, void *p) -{ - mda_t *mda = (mda_t *)p; - switch (addr) - { - case 0x3b0: case 0x3b2: case 0x3b4: case 0x3b6: - return mda->crtcreg; - case 0x3b1: case 0x3b3: case 0x3b5: case 0x3b7: - return mda->crtc[mda->crtcreg]; - case 0x3ba: - return mda->stat | 0xF0; + mda->sc = oldsc; + if (mda->vc == mda->crtc[7] && !mda->sc) { + mda->stat |= 8; } - return 0xff; -} - -void mda_write(uint32_t addr, uint8_t val, void *p) -{ - mda_t *mda = (mda_t *)p; - mda->vram[addr & 0xfff] = val; -} - -uint8_t mda_read(uint32_t addr, void *p) -{ - mda_t *mda = (mda_t *)p; - return mda->vram[addr & 0xfff]; -} - -void mda_recalctimings(mda_t *mda) -{ - double _dispontime, _dispofftime, disptime; - disptime = mda->crtc[0] + 1; - _dispontime = mda->crtc[1]; - _dispofftime = disptime - _dispontime; - _dispontime *= MDACONST; - _dispofftime *= MDACONST; - mda->dispontime = (uint64_t)(_dispontime); - mda->dispofftime = (uint64_t)(_dispofftime); -} - -void mda_poll(void *p) -{ - mda_t *mda = (mda_t *)p; - uint16_t ca = (mda->crtc[15] | (mda->crtc[14] << 8)) & 0x3fff; - int drawcursor; - int x, c; - int oldvc; - uint8_t chr, attr; - int oldsc; - int blink; - if (!mda->linepos) - { - timer_advance_u64(&mda->timer, mda->dispofftime); - mda->stat |= 1; - mda->linepos = 1; - oldsc = mda->sc; - if ((mda->crtc[8] & 3) == 3) - mda->sc = (mda->sc << 1) & 7; - if (mda->dispon) - { - if (mda->displine < mda->firstline) - { - mda->firstline = mda->displine; - video_wait_for_buffer(); - } - mda->lastline = mda->displine; - for (x = 0; x < mda->crtc[1]; x++) - { - chr = mda->vram[(mda->ma << 1) & 0xfff]; - attr = mda->vram[((mda->ma << 1) + 1) & 0xfff]; - drawcursor = ((mda->ma == ca) && mda->con && mda->cursoron); - blink = ((mda->blink & 16) && (mda->ctrl & 0x20) && (attr & 0x80) && !drawcursor); - if (mda->sc == 12 && ((attr & 7) == 1)) - { - for (c = 0; c < 9; c++) - buffer32->line[mda->displine][(x * 9) + c] = mdacols[attr][blink][1]; - } - else - { - for (c = 0; c < 8; c++) - buffer32->line[mda->displine][(x * 9) + c] = mdacols[attr][blink][(fontdatm[chr][mda->sc] & (1 << (c ^ 7))) ? 1 : 0]; - if ((chr & ~0x1f) == 0xc0) buffer32->line[mda->displine][(x * 9) + 8] = mdacols[attr][blink][fontdatm[chr][mda->sc] & 1]; - else buffer32->line[mda->displine][(x * 9) + 8] = mdacols[attr][blink][0]; - } - mda->ma++; - if (drawcursor) - { - for (c = 0; c < 9; c++) - buffer32->line[mda->displine][(x * 9) + c] ^= mdacols[attr][0][1]; - } - } - } - mda->sc = oldsc; - if (mda->vc == mda->crtc[7] && !mda->sc) - { - mda->stat |= 8; - } - mda->displine++; - if (mda->displine >= 500) - mda->displine=0; + mda->displine++; + if (mda->displine >= 500) + mda->displine = 0; + } else { + timer_advance_u64(&mda->timer, mda->dispontime); + if (mda->dispon) + mda->stat &= ~1; + mda->linepos = 0; + if (mda->vsynctime) { + mda->vsynctime--; + if (!mda->vsynctime) { + mda->stat &= ~8; + } } - else - { - timer_advance_u64(&mda->timer, mda->dispontime); - if (mda->dispon) mda->stat&=~1; - mda->linepos=0; - if (mda->vsynctime) - { - mda->vsynctime--; - if (!mda->vsynctime) - { - mda->stat&=~8; - } - } - if (mda->sc == (mda->crtc[11] & 31) || ((mda->crtc[8] & 3) == 3 && mda->sc == ((mda->crtc[11] & 31) >> 1))) - { - mda->con = 0; - mda->coff = 1; - } - if (mda->vadj) - { - mda->sc++; - mda->sc &= 31; - mda->ma = mda->maback; - mda->vadj--; - if (!mda->vadj) - { - mda->dispon = 1; - mda->ma = mda->maback = (mda->crtc[13] | (mda->crtc[12] << 8)) & 0x3fff; - mda->sc = 0; - } - } - else if (mda->sc == mda->crtc[9] || ((mda->crtc[8] & 3) == 3 && mda->sc == (mda->crtc[9] >> 1))) - { - mda->maback = mda->ma; - mda->sc = 0; - oldvc = mda->vc; - mda->vc++; - mda->vc &= 127; - if (mda->vc == mda->crtc[6]) - mda->dispon=0; - if (oldvc == mda->crtc[4]) - { - mda->vc = 0; - mda->vadj = mda->crtc[5]; - if (!mda->vadj) mda->dispon = 1; - if (!mda->vadj) mda->ma = mda->maback = (mda->crtc[13] | (mda->crtc[12] << 8)) & 0x3fff; - if ((mda->crtc[10] & 0x60) == 0x20) mda->cursoron = 0; - else mda->cursoron = mda->blink & 16; - } - if (mda->vc == mda->crtc[7]) - { - mda->dispon = 0; - mda->displine = 0; - mda->vsynctime = 16; - if (mda->crtc[7]) - { - x = mda->crtc[1] * 9; - mda->lastline++; - if ((x != xsize) || ((mda->lastline - mda->firstline) != ysize) || video_force_resize_get()) - { - xsize = x; - ysize = mda->lastline - mda->firstline; - if (xsize < 64) xsize = 656; - if (ysize < 32) ysize = 200; - set_screen_size(xsize, ysize); - - if (video_force_resize_get()) - video_force_resize_set(0); - } - video_blit_memtoscreen_8(0, mda->firstline, xsize, ysize); - frames++; - video_res_x = mda->crtc[1]; - video_res_y = mda->crtc[6]; - video_bpp = 0; - } - mda->firstline = 1000; - mda->lastline = 0; - mda->blink++; - } - } + if (mda->sc == (mda->crtc[11] & 31) || ((mda->crtc[8] & 3) == 3 && mda->sc == ((mda->crtc[11] & 31) >> 1))) { + mda->con = 0; + mda->coff = 1; + } + if (mda->vadj) { + mda->sc++; + mda->sc &= 31; + mda->ma = mda->maback; + mda->vadj--; + if (!mda->vadj) { + mda->dispon = 1; + mda->ma = mda->maback = (mda->crtc[13] | (mda->crtc[12] << 8)) & 0x3fff; + mda->sc = 0; + } + } else if (mda->sc == mda->crtc[9] || ((mda->crtc[8] & 3) == 3 && mda->sc == (mda->crtc[9] >> 1))) { + mda->maback = mda->ma; + mda->sc = 0; + oldvc = mda->vc; + mda->vc++; + mda->vc &= 127; + if (mda->vc == mda->crtc[6]) + mda->dispon = 0; + if (oldvc == mda->crtc[4]) { + mda->vc = 0; + mda->vadj = mda->crtc[5]; + if (!mda->vadj) + mda->dispon = 1; + if (!mda->vadj) + mda->ma = mda->maback = (mda->crtc[13] | (mda->crtc[12] << 8)) & 0x3fff; + if ((mda->crtc[10] & 0x60) == 0x20) + mda->cursoron = 0; else - { - mda->sc++; - mda->sc &= 31; - mda->ma = mda->maback; - } - if ((mda->sc == (mda->crtc[10] & 31) || ((mda->crtc[8] & 3) == 3 && mda->sc == ((mda->crtc[10] & 31) >> 1)))) - { - mda->con = 1; + mda->cursoron = mda->blink & 16; + } + if (mda->vc == mda->crtc[7]) { + mda->dispon = 0; + mda->displine = 0; + mda->vsynctime = 16; + if (mda->crtc[7]) { + x = mda->crtc[1] * 9; + mda->lastline++; + if ((x != xsize) || ((mda->lastline - mda->firstline) != ysize) || video_force_resize_get()) { + xsize = x; + ysize = mda->lastline - mda->firstline; + if (xsize < 64) + xsize = 656; + if (ysize < 32) + ysize = 200; + set_screen_size(xsize, ysize); + + if (video_force_resize_get()) + video_force_resize_set(0); + } + video_blit_memtoscreen(0, mda->firstline, xsize, ysize); + frames++; + video_res_x = mda->crtc[1]; + video_res_y = mda->crtc[6]; + video_bpp = 0; } + mda->firstline = 1000; + mda->lastline = 0; + mda->blink++; + } + } else { + mda->sc++; + mda->sc &= 31; + mda->ma = mda->maback; } -} - -void mda_init(mda_t *mda) -{ - int c; - - for (c = 0; c < 256; c++) - { - mdacols[c][0][0] = mdacols[c][1][0] = mdacols[c][1][1] = 16; - if (c & 8) mdacols[c][0][1] = 15 + 16; - else mdacols[c][0][1] = 7 + 16; + if (mda->sc == (mda->crtc[10] & 31) || ((mda->crtc[8] & 3) == 3 && mda->sc == ((mda->crtc[10] & 31) >> 1))) { + mda->con = 1; } - mdacols[0x70][0][1] = 16; - mdacols[0x70][0][0] = mdacols[0x70][1][0] = mdacols[0x70][1][1] = 16 + 15; - mdacols[0xF0][0][1] = 16; - mdacols[0xF0][0][0] = mdacols[0xF0][1][0] = mdacols[0xF0][1][1] = 16 + 15; - mdacols[0x78][0][1] = 16 + 7; - mdacols[0x78][0][0] = mdacols[0x78][1][0] = mdacols[0x78][1][1] = 16 + 15; - mdacols[0xF8][0][1] = 16 + 7; - mdacols[0xF8][0][0] = mdacols[0xF8][1][0] = mdacols[0xF8][1][1] = 16 + 15; - mdacols[0x00][0][1] = mdacols[0x00][1][1] = 16; - mdacols[0x08][0][1] = mdacols[0x08][1][1] = 16; - mdacols[0x80][0][1] = mdacols[0x80][1][1] = 16; - mdacols[0x88][0][1] = mdacols[0x88][1][1] = 16; - - overscan_x = overscan_y = 0; - - cga_palette = device_get_config_int("rgb_type") << 1; - if (cga_palette > 6) - { - cga_palette = 0; - } - cgapal_rebuild(); - - timer_add(&mda->timer, mda_poll, mda, 1); + } + VIDEO_MONITOR_EPILOGUE(); } -void *mda_standalone_init(const device_t *info) +void +mda_init(mda_t *mda) { - mda_t *mda = malloc(sizeof(mda_t)); - memset(mda, 0, sizeof(mda_t)); - video_inform(VIDEO_FLAG_TYPE_MDA, &timing_mda); + for (uint16_t c = 0; c < 256; c++) { + mdacols[c][0][0] = mdacols[c][1][0] = mdacols[c][1][1] = 16; + if (c & 8) + mdacols[c][0][1] = 15 + 16; + else + mdacols[c][0][1] = 7 + 16; + } + mdacols[0x70][0][1] = 16; + mdacols[0x70][0][0] = mdacols[0x70][1][0] = mdacols[0x70][1][1] = 16 + 15; + mdacols[0xF0][0][1] = 16; + mdacols[0xF0][0][0] = mdacols[0xF0][1][0] = mdacols[0xF0][1][1] = 16 + 15; + mdacols[0x78][0][1] = 16 + 7; + mdacols[0x78][0][0] = mdacols[0x78][1][0] = mdacols[0x78][1][1] = 16 + 15; + mdacols[0xF8][0][1] = 16 + 7; + mdacols[0xF8][0][0] = mdacols[0xF8][1][0] = mdacols[0xF8][1][1] = 16 + 15; + mdacols[0x00][0][1] = mdacols[0x00][1][1] = 16; + mdacols[0x08][0][1] = mdacols[0x08][1][1] = 16; + mdacols[0x80][0][1] = mdacols[0x80][1][1] = 16; + mdacols[0x88][0][1] = mdacols[0x88][1][1] = 16; - mda->vram = malloc(0x1000); + overscan_x = overscan_y = 0; + mda->monitor_index = monitor_index_global; - mem_mapping_add(&mda->mapping, 0xb0000, 0x08000, mda_read, NULL, NULL, mda_write, NULL, NULL, NULL, MEM_MAPPING_EXTERNAL, mda); - io_sethandler(0x03b0, 0x0010, mda_in, NULL, NULL, mda_out, NULL, NULL, mda); + cga_palette = device_get_config_int("rgb_type") << 1; + if (cga_palette > 6) { + cga_palette = 0; + } + cgapal_rebuild(); - mda_init(mda); - - lpt3_init(0x3BC); - - return mda; + timer_add(&mda->timer, mda_poll, mda, 1); } -void mda_setcol(int chr, int blink, int fg, uint8_t cga_ink) +void * +mda_standalone_init(UNUSED(const device_t *info)) { - mdacols[chr][blink][fg] = 16 + cga_ink; + mda_t *mda = malloc(sizeof(mda_t)); + memset(mda, 0, sizeof(mda_t)); + video_inform(VIDEO_FLAG_TYPE_MDA, &timing_mda); + + mda->vram = malloc(0x1000); + + mem_mapping_add(&mda->mapping, 0xb0000, 0x08000, mda_read, NULL, NULL, mda_write, NULL, NULL, NULL, MEM_MAPPING_EXTERNAL, mda); + io_sethandler(0x03b0, 0x0010, mda_in, NULL, NULL, mda_out, NULL, NULL, mda); + + mda_init(mda); + + lpt3_init(0x3BC); + + return mda; } -void mda_close(void *p) +void +mda_setcol(int chr, int blink, int fg, uint8_t cga_ink) { - mda_t *mda = (mda_t *)p; - - free(mda->vram); - free(mda); + mdacols[chr][blink][fg] = 16 + cga_ink; } -void mda_speed_changed(void *p) +void +mda_close(void *priv) { - mda_t *mda = (mda_t *)p; - - mda_recalctimings(mda); + mda_t *mda = (mda_t *) priv; + + free(mda->vram); + free(mda); } -static const device_config_t mda_config[] = +void +mda_speed_changed(void *priv) { - { - "rgb_type", "Display type", CONFIG_SELECTION, "", 0, "", { 0 }, - { - { - "Default", 0 - }, - { - "Green", 1 - }, - { - "Amber", 2 - }, - { - "Gray", 3 - }, - { - "" - } - } - }, - { - "", "", -1 + mda_t *mda = (mda_t *) priv; + + mda_recalctimings(mda); +} + +static const device_config_t mda_config[] = { + // clang-format off + { + .name = "rgb_type", + .description = "Display type", + .type = CONFIG_SELECTION, + .default_int = 0, + .selection = { + { + .description = "Default", + .value = 0 + }, + { + .description = "Green", + .value = 1 + }, + { + .description = "Amber", + .value = 2 + }, + { + .description = "Gray", + .value = 3 + }, + { + .description = "" + } } + }, + { + .type = CONFIG_END + } + // clang-format on }; - -const device_t mda_device = -{ - "MDA", - "mda", - DEVICE_ISA, 0, - mda_standalone_init, mda_close, NULL, - { NULL }, - mda_speed_changed, - NULL, - mda_config +const device_t mda_device = { + .name = "MDA", + .internal_name = "mda", + .flags = DEVICE_ISA, + .local = 0, + .init = mda_standalone_init, + .close = mda_close, + .reset = NULL, + { .available = NULL }, + .speed_changed = mda_speed_changed, + .force_redraw = NULL, + .config = mda_config }; diff --git a/src/video/vid_mga.c b/src/video/vid_mga.c index fe93f0d98..74bb9d07a 100644 --- a/src/video/vid_mga.c +++ b/src/video/vid_mga.c @@ -1,23 +1,25 @@ /* - * 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. + * 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. + * This file is part of the 86Box distribution. * - * Matrox MGA graphics card emulation. + * Matrox MGA graphics card emulation. * * * - * Author: Sarah Walker, - * Copyright 2008-2020 Sarah Walker. + * Authors: Sarah Walker, + * + * Copyright 2008-2020 Sarah Walker. */ #include #include #include #include #include +#include #include <86box/86box.h> #include <86box/io.h> #include <86box/timer.h> @@ -27,33 +29,33 @@ #include <86box/device.h> #include <86box/dma.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> +#define ROM_MILLENNIUM "roms/video/matrox/matrox2064wr2.BIN" +#define ROM_MYSTIQUE "roms/video/matrox/MYSTIQUE.VBI" +#define ROM_MYSTIQUE_220 "roms/video/matrox/Myst220_66-99mhz.vbi" -#define ROM_MILLENNIUM "roms/video/matrox/matrox2064wr2.BIN" -#define ROM_MYSTIQUE "roms/video/matrox/MYSTIQUE.VBI" -#define ROM_MYSTIQUE_220 "roms/video/matrox/Myst220_66-99mhz.vbi" +#define FIFO_SIZE 65536 +#define FIFO_MASK (FIFO_SIZE - 1) +#define FIFO_ENTRY_SIZE (1 << 31) +#define FIFO_THRESHOLD 0xe000 -#define FIFO_SIZE 65536 -#define FIFO_MASK (FIFO_SIZE - 1) -#define FIFO_ENTRY_SIZE (1 << 31) -#define FIFO_THRESHOLD 0xe000 +#define WAKE_DELAY (100 * TIMER_USEC) /* 100us */ -#define WAKE_DELAY (100 * TIMER_USEC) /* 100us */ +#define FIFO_ENTRIES (mystique->fifo_write_idx - mystique->fifo_read_idx) +#define FIFO_FULL ((mystique->fifo_write_idx - mystique->fifo_read_idx) >= (FIFO_SIZE - 1)) +#define FIFO_EMPTY (mystique->fifo_read_idx == mystique->fifo_write_idx) -#define FIFO_ENTRIES (mystique->fifo_write_idx - mystique->fifo_read_idx) -#define FIFO_FULL ((mystique->fifo_write_idx - mystique->fifo_read_idx) >= (FIFO_SIZE-1)) -#define FIFO_EMPTY (mystique->fifo_read_idx == mystique->fifo_write_idx) - -#define FIFO_TYPE 0xff000000 -#define FIFO_ADDR 0x00ffffff +#define FIFO_TYPE 0xff000000 +#define FIFO_ADDR 0x00ffffff #define DMA_POLL_TIME_US 100 /*100us*/ -#define DMA_MAX_WORDS 256 /*256 quad words per 100us poll*/ +#define DMA_MAX_WORDS 256 /*256 quad words per 100us poll*/ /*These registers are also mirrored into 0x1dxx, with the mirrored versions starting the blitter*/ @@ -138,119 +140,119 @@ #define REG_CACHEFLUSH 0x1fff /*Mystique only*/ -#define REG_TMR0 0x2c00 -#define REG_TMR1 0x2c04 -#define REG_TMR2 0x2c08 -#define REG_TMR3 0x2c0c -#define REG_TMR4 0x2c10 -#define REG_TMR5 0x2c14 -#define REG_TMR6 0x2c18 -#define REG_TMR7 0x2c1c -#define REG_TMR8 0x2c20 -#define REG_TEXORG 0x2c24 -#define REG_TEXWIDTH 0x2c28 -#define REG_TEXHEIGHT 0x2c2c -#define REG_TEXCTL 0x2c30 -#define REG_TEXTRANS 0x2c34 -#define REG_SECADDRESS 0x2c40 -#define REG_SECEND 0x2c44 -#define REG_SOFTRAP 0x2c48 +#define REG_TMR0 0x2c00 +#define REG_TMR1 0x2c04 +#define REG_TMR2 0x2c08 +#define REG_TMR3 0x2c0c +#define REG_TMR4 0x2c10 +#define REG_TMR5 0x2c14 +#define REG_TMR6 0x2c18 +#define REG_TMR7 0x2c1c +#define REG_TMR8 0x2c20 +#define REG_TEXORG 0x2c24 +#define REG_TEXWIDTH 0x2c28 +#define REG_TEXHEIGHT 0x2c2c +#define REG_TEXCTL 0x2c30 +#define REG_TEXTRANS 0x2c34 +#define REG_SECADDRESS 0x2c40 +#define REG_SECEND 0x2c44 +#define REG_SOFTRAP 0x2c48 /*Mystique only*/ -#define REG_PALWTADD 0x3c00 -#define REG_PALDATA 0x3c01 -#define REG_PIXRDMSK 0x3c02 -#define REG_PALRDADD 0x3c03 -#define REG_X_DATAREG 0x3c0a -#define REG_CURPOSX 0x3c0c -#define REG_CURPOSY 0x3c0e +#define REG_PALWTADD 0x3c00 +#define REG_PALDATA 0x3c01 +#define REG_PIXRDMSK 0x3c02 +#define REG_PALRDADD 0x3c03 +#define REG_X_DATAREG 0x3c0a +#define REG_CURPOSX 0x3c0c +#define REG_CURPOSY 0x3c0e -#define REG_STATUS_VSYNCSTS (1 << 3) +#define REG_STATUS_VSYNCSTS (1 << 3) -#define CRTCX_R0_STARTADD_MASK (0xf << 0) -#define CRTCX_R0_OFFSET_MASK (3 << 4) +#define CRTCX_R0_STARTADD_MASK (0xf << 0) +#define CRTCX_R0_OFFSET_MASK (3 << 4) -#define CRTCX_R1_HTOTAL8 (1 << 0) +#define CRTCX_R1_HTOTAL8 (1 << 0) -#define CRTCX_R2_VTOTAL10 (1 << 0) -#define CRTCX_R2_VTOTAL11 (1 << 1) -#define CRTCX_R2_VDISPEND10 (1 << 2) -#define CRTCX_R2_VBLKSTR10 (1 << 3) -#define CRTCX_R2_VBLKSTR11 (1 << 4) -#define CRTCX_R2_VSYNCSTR10 (1 << 5) -#define CRTCX_R2_VSYNCSTR11 (1 << 6) -#define CRTCX_R2_LINECOMP10 (1 << 7) +#define CRTCX_R2_VTOTAL10 (1 << 0) +#define CRTCX_R2_VTOTAL11 (1 << 1) +#define CRTCX_R2_VDISPEND10 (1 << 2) +#define CRTCX_R2_VBLKSTR10 (1 << 3) +#define CRTCX_R2_VBLKSTR11 (1 << 4) +#define CRTCX_R2_VSYNCSTR10 (1 << 5) +#define CRTCX_R2_VSYNCSTR11 (1 << 6) +#define CRTCX_R2_LINECOMP10 (1 << 7) -#define CRTCX_R3_MGAMODE (1 << 7) +#define CRTCX_R3_MGAMODE (1 << 7) -#define XREG_XCURADDL 0x04 -#define XREG_XCURADDH 0x05 -#define XREG_XCURCTRL 0x06 +#define XREG_XCURADDL 0x04 +#define XREG_XCURADDH 0x05 +#define XREG_XCURCTRL 0x06 -#define XREG_XCURCOL0R 0x08 -#define XREG_XCURCOL0G 0x09 -#define XREG_XCURCOL0B 0x0a +#define XREG_XCURCOL0R 0x08 +#define XREG_XCURCOL0G 0x09 +#define XREG_XCURCOL0B 0x0a -#define XREG_XCURCOL1R 0x0c -#define XREG_XCURCOL1G 0x0d -#define XREG_XCURCOL1B 0x0e +#define XREG_XCURCOL1R 0x0c +#define XREG_XCURCOL1G 0x0d +#define XREG_XCURCOL1B 0x0e -#define XREG_XCURCOL2R 0x10 -#define XREG_XCURCOL2G 0x11 -#define XREG_XCURCOL2B 0x12 +#define XREG_XCURCOL2R 0x10 +#define XREG_XCURCOL2G 0x11 +#define XREG_XCURCOL2B 0x12 -#define XREG_XVREFCTRL 0x18 -#define XREG_XMULCTRL 0x19 -#define XREG_XPIXCLKCTRL 0x1a -#define XREG_XGENCTRL 0x1d -#define XREG_XMISCCTRL 0x1e +#define XREG_XVREFCTRL 0x18 +#define XREG_XMULCTRL 0x19 +#define XREG_XPIXCLKCTRL 0x1a +#define XREG_XGENCTRL 0x1d +#define XREG_XMISCCTRL 0x1e -#define XREG_XGENIOCTRL 0x2a -#define XREG_XGENIODATA 0x2b +#define XREG_XGENIOCTRL 0x2a +#define XREG_XGENIODATA 0x2b -#define XREG_XSYSPLLM 0x2c -#define XREG_XSYSPLLN 0x2d -#define XREG_XSYSPLLP 0x2e -#define XREG_XSYSPLLSTAT 0x2f +#define XREG_XSYSPLLM 0x2c +#define XREG_XSYSPLLN 0x2d +#define XREG_XSYSPLLP 0x2e +#define XREG_XSYSPLLSTAT 0x2f -#define XREG_XZOOMCTRL 0x38 +#define XREG_XZOOMCTRL 0x38 -#define XREG_XSENSETEST 0x3a +#define XREG_XSENSETEST 0x3a -#define XREG_XCRCREML 0x3c -#define XREG_XCRCREMH 0x3d -#define XREG_XCRCBITSEL 0x3e +#define XREG_XCRCREML 0x3c +#define XREG_XCRCREMH 0x3d +#define XREG_XCRCBITSEL 0x3e -#define XREG_XCOLKEYMSKL 0x40 -#define XREG_XCOLKEYMSKH 0x41 -#define XREG_XCOLKEYL 0x42 -#define XREG_XCOLKEYH 0x43 +#define XREG_XCOLKEYMSKL 0x40 +#define XREG_XCOLKEYMSKH 0x41 +#define XREG_XCOLKEYL 0x42 +#define XREG_XCOLKEYH 0x43 -#define XREG_XPIXPLLCM 0x4c -#define XREG_XPIXPLLCN 0x4d -#define XREG_XPIXPLLCP 0x4e -#define XREG_XPIXPLLSTAT 0x4f +#define XREG_XPIXPLLCM 0x4c +#define XREG_XPIXPLLCN 0x4d +#define XREG_XPIXPLLCP 0x4e +#define XREG_XPIXPLLSTAT 0x4f -#define XMISCCTRL_VGA8DAC (1 << 3) +#define XMISCCTRL_VGA8DAC (1 << 3) -#define XMULCTRL_DEPTH_MASK (7 << 0) -#define XMULCTRL_DEPTH_8 (0 << 0) -#define XMULCTRL_DEPTH_15 (1 << 0) -#define XMULCTRL_DEPTH_16 (2 << 0) -#define XMULCTRL_DEPTH_24 (3 << 0) -#define XMULCTRL_DEPTH_32_OVERLAYED (4 << 0) -#define XMULCTRL_DEPTH_2G8V16 (5 << 0) -#define XMULCTRL_DEPTH_G16V16 (6 << 0) -#define XMULCTRL_DEPTH_32 (7 << 0) +#define XMULCTRL_DEPTH_MASK (7 << 0) +#define XMULCTRL_DEPTH_8 (0 << 0) +#define XMULCTRL_DEPTH_15 (1 << 0) +#define XMULCTRL_DEPTH_16 (2 << 0) +#define XMULCTRL_DEPTH_24 (3 << 0) +#define XMULCTRL_DEPTH_32_OVERLAYED (4 << 0) +#define XMULCTRL_DEPTH_2G8V16 (5 << 0) +#define XMULCTRL_DEPTH_G16V16 (6 << 0) +#define XMULCTRL_DEPTH_32 (7 << 0) -#define XSYSPLLSTAT_SYSLOCK (1 << 6) +#define XSYSPLLSTAT_SYSLOCK (1 << 6) -#define XPIXPLLSTAT_SYSLOCK (1 << 6) +#define XPIXPLLSTAT_SYSLOCK (1 << 6) -#define XCURCTRL_CURMODE_MASK (3 << 0) -#define XCURCTRL_CURMODE_3COL (1 << 0) -#define XCURCTRL_CURMODE_XGA (2 << 0) -#define XCURCTRL_CURMODE_XWIN (3 << 0) +#define XCURCTRL_CURMODE_MASK (3 << 0) +#define XCURCTRL_CURMODE_3COL (1 << 0) +#define XCURCTRL_CURMODE_XGA (2 << 0) +#define XCURCTRL_CURMODE_XWIN (3 << 0) #define DWGCTRL_OPCODE_MASK (0xf << 0) #define DWGCTRL_OPCODE_LINE_OPEN (0x0 << 0) @@ -266,183 +268,179 @@ #define DWGCTRL_OPCODE_FBITBLT (0xc << 0) #define DWGCTRL_OPCODE_ILOAD_SCALE (0xd << 0) #define DWGCTRL_OPCODE_ILOAD_HIGHV (0xe << 0) -#define DWGCTRL_OPCODE_ILOAD_FILTER (0xf << 0) /* Not implemented. */ -#define DWGCTRL_ATYPE_MASK (7 << 4) -#define DWGCTRL_ATYPE_RPL (0 << 4) -#define DWGCTRL_ATYPE_RSTR (1 << 4) -#define DWGCTRL_ATYPE_ZI (3 << 4) -#define DWGCTRL_ATYPE_BLK (4 << 4) -#define DWGCTRL_ATYPE_I (7 << 4) -#define DWGCTRL_LINEAR (1 << 7) -#define DWGCTRL_ZMODE_MASK (7 << 8) -#define DWGCTRL_ZMODE_NOZCMP (0 << 8) -#define DWGCTRL_ZMODE_ZE (2 << 8) -#define DWGCTRL_ZMODE_ZNE (3 << 8) -#define DWGCTRL_ZMODE_ZLT (4 << 8) -#define DWGCTRL_ZMODE_ZLTE (5 << 8) -#define DWGCTRL_ZMODE_ZGT (6 << 8) -#define DWGCTRL_ZMODE_ZGTE (7 << 8) -#define DWGCTRL_SOLID (1 << 11) -#define DWGCTRL_ARZERO (1 << 12) -#define DWGCTRL_SGNZERO (1 << 13) -#define DWGCTRL_SHTZERO (1 << 14) -#define DWGCTRL_BOP_MASK (0xf << 16) -#define DWGCTRL_TRANS_SHIFT (20) -#define DWGCTRL_TRANS_MASK (0xf << DWGCTRL_TRANS_SHIFT) -#define DWGCTRL_BLTMOD_MASK (0xf << 25) -#define DWGCTRL_BLTMOD_BMONOLEF (0x0 << 25) -#define DWGCTRL_BLTMOD_BFCOL (0x2 << 25) -#define DWGCTRL_BLTMOD_BU32BGR (0x3 << 25) -#define DWGCTRL_BLTMOD_BMONOWF (0x4 << 25) -#define DWGCTRL_BLTMOD_BU32RGB (0x7 << 25) -#define DWGCTRL_BLTMOD_BUYUV (0xe << 25) -#define DWGCTRL_BLTMOD_BU24RGB (0xf << 25) -#define DWGCTRL_PATTERN (1 << 29) -#define DWGCTRL_TRANSC (1 << 30) -#define BOP(x) ((x) << 16) +#define DWGCTRL_OPCODE_ILOAD_FILTER (0xf << 0) /* Not implemented. */ +#define DWGCTRL_ATYPE_MASK (7 << 4) +#define DWGCTRL_ATYPE_RPL (0 << 4) +#define DWGCTRL_ATYPE_RSTR (1 << 4) +#define DWGCTRL_ATYPE_ZI (3 << 4) +#define DWGCTRL_ATYPE_BLK (4 << 4) +#define DWGCTRL_ATYPE_I (7 << 4) +#define DWGCTRL_LINEAR (1 << 7) +#define DWGCTRL_ZMODE_MASK (7 << 8) +#define DWGCTRL_ZMODE_NOZCMP (0 << 8) +#define DWGCTRL_ZMODE_ZE (2 << 8) +#define DWGCTRL_ZMODE_ZNE (3 << 8) +#define DWGCTRL_ZMODE_ZLT (4 << 8) +#define DWGCTRL_ZMODE_ZLTE (5 << 8) +#define DWGCTRL_ZMODE_ZGT (6 << 8) +#define DWGCTRL_ZMODE_ZGTE (7 << 8) +#define DWGCTRL_SOLID (1 << 11) +#define DWGCTRL_ARZERO (1 << 12) +#define DWGCTRL_SGNZERO (1 << 13) +#define DWGCTRL_SHTZERO (1 << 14) +#define DWGCTRL_BOP_MASK (0xf << 16) +#define DWGCTRL_TRANS_SHIFT (20) +#define DWGCTRL_TRANS_MASK (0xf << DWGCTRL_TRANS_SHIFT) +#define DWGCTRL_BLTMOD_MASK (0xf << 25) +#define DWGCTRL_BLTMOD_BMONOLEF (0x0 << 25) +#define DWGCTRL_BLTMOD_BFCOL (0x2 << 25) +#define DWGCTRL_BLTMOD_BU32BGR (0x3 << 25) +#define DWGCTRL_BLTMOD_BMONOWF (0x4 << 25) +#define DWGCTRL_BLTMOD_BU32RGB (0x7 << 25) +#define DWGCTRL_BLTMOD_BUYUV (0xe << 25) +#define DWGCTRL_BLTMOD_BU24RGB (0xf << 25) +#define DWGCTRL_PATTERN (1 << 29) +#define DWGCTRL_TRANSC (1 << 30) +#define BOP(x) ((x) << 16) -#define MACCESS_PWIDTH_MASK (3 << 0) -#define MACCESS_PWIDTH_8 (0 << 0) -#define MACCESS_PWIDTH_16 (1 << 0) -#define MACCESS_PWIDTH_32 (2 << 0) -#define MACCESS_PWIDTH_24 (3 << 0) -#define MACCESS_TLUTLOAD (1 << 29) -#define MACCESS_NODITHER (1 << 30) -#define MACCESS_DIT555 (1 << 31) +#define MACCESS_PWIDTH_MASK (3 << 0) +#define MACCESS_PWIDTH_8 (0 << 0) +#define MACCESS_PWIDTH_16 (1 << 0) +#define MACCESS_PWIDTH_32 (2 << 0) +#define MACCESS_PWIDTH_24 (3 << 0) +#define MACCESS_TLUTLOAD (1 << 29) +#define MACCESS_NODITHER (1 << 30) +#define MACCESS_DIT555 (1 << 31) -#define PITCH_MASK 0x7e0 -#define PITCH_YLIN (1 << 15) +#define PITCH_MASK 0x7e0 +#define PITCH_YLIN (1 << 15) -#define SGN_SDYDXL (1 << 0) -#define SGN_SCANLEFT (1 << 0) -#define SGN_SDXL (1 << 1) -#define SGN_SDY (1 << 2) -#define SGN_SDXR (1 << 5) +#define SGN_SDYDXL (1 << 0) +#define SGN_SCANLEFT (1 << 0) +#define SGN_SDXL (1 << 1) +#define SGN_SDY (1 << 2) +#define SGN_SDXR (1 << 5) -#define DMA_ADDR_MASK 0xfffffffc -#define DMA_MODE_MASK 3 +#define DMA_ADDR_MASK 0xfffffffc +#define DMA_MODE_MASK 3 -#define DMA_MODE_REG 0 -#define DMA_MODE_BLIT 1 -#define DMA_MODE_VECTOR 2 +#define DMA_MODE_REG 0 +#define DMA_MODE_BLIT 1 +#define DMA_MODE_VECTOR 2 -#define STATUS_SOFTRAPEN (1 << 0) -#define STATUS_VSYNCPEN (1 << 4) -#define STATUS_VLINEPEN (1 << 5) -#define STATUS_DWGENGSTS (1 << 16) -#define STATUS_ENDPRDMASTS (1 << 17) +#define STATUS_SOFTRAPEN (1 << 0) +#define STATUS_VSYNCPEN (1 << 4) +#define STATUS_VLINEPEN (1 << 5) +#define STATUS_DWGENGSTS (1 << 16) +#define STATUS_ENDPRDMASTS (1 << 17) -#define ICLEAR_SOFTRAPICLR (1 << 0) -#define ICLEAR_VLINEICLR (1 << 5) +#define ICLEAR_SOFTRAPICLR (1 << 0) +#define ICLEAR_VLINEICLR (1 << 5) -#define IEN_SOFTRAPEN (1 << 0) +#define IEN_SOFTRAPEN (1 << 0) -#define TEXCTL_TEXFORMAT_MASK (7 << 0) -#define TEXCTL_TEXFORMAT_TW4 (0 << 0) -#define TEXCTL_TEXFORMAT_TW8 (1 << 0) -#define TEXCTL_TEXFORMAT_TW15 (2 << 0) -#define TEXCTL_TEXFORMAT_TW16 (3 << 0) -#define TEXCTL_TEXFORMAT_TW12 (4 << 0) -#define TEXCTL_PALSEL_MASK (0xf << 4) -#define TEXCTL_TPITCH_SHIFT (16) -#define TEXCTL_TPITCH_MASK (7 << TEXCTL_TPITCH_SHIFT) -#define TEXCTL_NPCEN (1 << 21) -#define TEXCTL_DECALCKEY (1 << 24) -#define TEXCTL_TAKEY (1 << 25) -#define TEXCTL_TAMASK (1 << 26) -#define TEXCTL_CLAMPV (1 << 27) -#define TEXCTL_CLAMPU (1 << 28) -#define TEXCTL_TMODULATE (1 << 29) -#define TEXCTL_STRANS (1 << 30) -#define TEXCTL_ITRANS (1 << 31) +#define TEXCTL_TEXFORMAT_MASK (7 << 0) +#define TEXCTL_TEXFORMAT_TW4 (0 << 0) +#define TEXCTL_TEXFORMAT_TW8 (1 << 0) +#define TEXCTL_TEXFORMAT_TW15 (2 << 0) +#define TEXCTL_TEXFORMAT_TW16 (3 << 0) +#define TEXCTL_TEXFORMAT_TW12 (4 << 0) +#define TEXCTL_PALSEL_MASK (0xf << 4) +#define TEXCTL_TPITCH_SHIFT (16) +#define TEXCTL_TPITCH_MASK (7 << TEXCTL_TPITCH_SHIFT) +#define TEXCTL_NPCEN (1 << 21) +#define TEXCTL_DECALCKEY (1 << 24) +#define TEXCTL_TAKEY (1 << 25) +#define TEXCTL_TAMASK (1 << 26) +#define TEXCTL_CLAMPV (1 << 27) +#define TEXCTL_CLAMPU (1 << 28) +#define TEXCTL_TMODULATE (1 << 29) +#define TEXCTL_STRANS (1 << 30) +#define TEXCTL_ITRANS (1 << 31) -#define TEXHEIGHT_TH_MASK (0x3f << 0) -#define TEXHEIGHT_THMASK_SHIFT (18) -#define TEXHEIGHT_THMASK_MASK (0x7ff << TEXHEIGHT_THMASK_SHIFT) +#define TEXHEIGHT_TH_MASK (0x3f << 0) +#define TEXHEIGHT_THMASK_SHIFT (18) +#define TEXHEIGHT_THMASK_MASK (0x7ff << TEXHEIGHT_THMASK_SHIFT) -#define TEXWIDTH_TW_MASK (0x3f << 0) -#define TEXWIDTH_TWMASK_SHIFT (18) -#define TEXWIDTH_TWMASK_MASK (0x7ff << TEXWIDTH_TWMASK_SHIFT) +#define TEXWIDTH_TW_MASK (0x3f << 0) +#define TEXWIDTH_TWMASK_SHIFT (18) +#define TEXWIDTH_TWMASK_MASK (0x7ff << TEXWIDTH_TWMASK_SHIFT) -#define TEXTRANS_TCKEY_MASK (0xffff) -#define TEXTRANS_TKMASK_SHIFT (16) -#define TEXTRANS_TKMASK_MASK (0xffff << TEXTRANS_TKMASK_SHIFT) +#define TEXTRANS_TCKEY_MASK (0xffff) +#define TEXTRANS_TKMASK_SHIFT (16) +#define TEXTRANS_TKMASK_MASK (0xffff << TEXTRANS_TKMASK_SHIFT) -#define DITHER_565 0 -#define DITHER_NONE_565 1 -#define DITHER_555 2 -#define DITHER_NONE_555 3 +#define DITHER_565 0 +#define DITHER_NONE_565 1 +#define DITHER_555 2 +#define DITHER_NONE_555 3 /*PCI configuration registers*/ #define OPTION_INTERLEAVE (1 << 12) -enum -{ - MGA_2064W, /*Millennium*/ - MGA_1064SG, /*Mystique*/ - MGA_1164SG, /*Mystique 220*/ +enum { + MGA_2064W, /*Millennium*/ + MGA_1064SG, /*Mystique*/ + MGA_1164SG, /*Mystique 220*/ }; -enum -{ +enum { FIFO_INVALID = (0x00 << 24), FIFO_WRITE_CTRL_BYTE = (0x01 << 24), FIFO_WRITE_CTRL_LONG = (0x02 << 24), FIFO_WRITE_ILOAD_LONG = (0x03 << 24) }; -enum -{ - DMA_STATE_IDLE = 0, - DMA_STATE_PRI, - DMA_STATE_SEC +enum { + DMA_STATE_IDLE = 0, + DMA_STATE_PRI, + DMA_STATE_SEC }; - typedef struct { uint32_t addr_type; uint32_t val; } fifo_entry_t; -typedef struct mystique_t -{ +typedef struct mystique_t { svga_t svga; rom_t bios_rom; - - int type; + + int type; mem_mapping_t lfb_mapping, ctrl_mapping, - iload_mapping; + iload_mapping; uint8_t int_line, xcurctrl, - xsyspllm, xsysplln, xsyspllp, - xgenioctrl, xgeniodata, - xmulctrl, xgenctrl, - xmiscctrl, xpixclkctrl, - xvrefctrl, ien, dmamod, - dmadatasiz, dirdatasiz, - xcolkeymskl, xcolkeymskh, - xcolkeyl, xcolkeyh, - xcrcbitsel; + xsyspllm, xsysplln, xsyspllp, + xgenioctrl, xgeniodata, + xmulctrl, xgenctrl, + xmiscctrl, xpixclkctrl, + xvrefctrl, ien, dmamod, + dmadatasiz, dirdatasiz, + xcolkeymskl, xcolkeymskh, + xcolkeyl, xcolkeyh, + xcrcbitsel; + + uint8_t pci_slot, irq_state, pad, pad0; uint8_t pci_regs[256], crtcext_regs[6], - xreg_regs[256], dmamap[16]; + xreg_regs[256], dmamap[16]; - int card, vram_size, crtcext_idx, xreg_idx, - xzoomctrl, - pixel_count, trap_count; + int vram_size, crtcext_idx, xreg_idx, xzoomctrl, + pixel_count, trap_count; - volatile int busy, blitter_submit_refcount, - blitter_submit_dma_refcount, blitter_complete_refcount, - endprdmasts_pending, softrap_pending, - fifo_read_idx, fifo_write_idx; + atomic_int busy, blitter_submit_refcount, + blitter_submit_dma_refcount, blitter_complete_refcount, + endprdmasts_pending, softrap_pending, + fifo_read_idx, fifo_write_idx; uint32_t vram_mask, vram_mask_w, vram_mask_l, - lfb_base, ctrl_base, iload_base, - ma_latch_old, maccess, mctlwtst, maccess_running, - status, softrap_pending_val; + lfb_base, ctrl_base, iload_base, + ma_latch_old, maccess, mctlwtst, maccess_running, + status, softrap_pending_val; uint64_t blitter_time, status_time; @@ -456,65 +454,65 @@ typedef struct mystique_t struct { - int m, n, p, s; + int m, n, p, s; } xpixpll[3]; struct { - uint8_t funcnt, stylelen, - dmamod; + uint8_t funcnt, stylelen, + dmamod; - int16_t fxleft, fxright, - xdst; + int16_t fxleft, fxright, + xdst; - uint16_t cxleft, cxright, - length; + uint16_t cxleft, cxright, + length; - int xoff, yoff, selline, ydst, - length_cur, iload_rem_count, idump_end_of_line, words, - ta_key, ta_mask, lastpix_r, lastpix_g, - lastpix_b, highv_line, beta, dither; + int xoff, yoff, selline, ydst, + length_cur, iload_rem_count, idump_end_of_line, words, + ta_key, ta_mask, lastpix_r, lastpix_g, + lastpix_b, highv_line, beta, dither; - int pattern[8][8]; + int pattern[8][16]; - uint32_t dwgctrl, dwgctrl_running, bcol, fcol, - pitch, plnwt, ybot, ydstorg, - ytop, texorg, texwidth, texheight, - texctl, textrans, zorg, ydst_lin, - src_addr, z_base, iload_rem_data, highv_data; + uint32_t dwgctrl, dwgctrl_running, bcol, fcol, + pitch, plnwt, ybot, ydstorg, + ytop, texorg, texwidth, texheight, + texctl, textrans, zorg, ydst_lin, + src_addr, z_base, iload_rem_data, highv_data; - uint32_t src[4], ar[7], - dr[16], tmr[9]; + uint32_t src[4], ar[7], + dr[16], tmr[9]; - struct - { - int sdydxl, scanleft, sdxl, sdy, - sdxr; - } sgn; + struct + { + int sdydxl, scanleft, sdxl, sdy, + sdxr; + } sgn; } dwgreg; struct { - uint8_t r, g, b; + uint8_t r, g, b; } lut[256]; struct { - uint16_t pos_x, pos_y, - addr; - uint32_t col[3]; + uint16_t pos_x, pos_y, + addr; + uint32_t col[3]; } cursor; struct { - int pri_pos, sec_pos, iload_pos, - pri_state, sec_state, iload_state, state; + int pri_pos, sec_pos, iload_pos, + pri_state, sec_state, iload_state, state; - uint32_t primaddress, primend, secaddress, secend, - pri_header, sec_header, - iload_header; + uint32_t primaddress, primend, secaddress, secend, + pri_header, sec_header, + iload_header; - mutex_t *lock; + mutex_t *lock; } dma; uint8_t thread_run; @@ -522,292 +520,295 @@ typedef struct mystique_t void *i2c, *i2c_ddc, *ddc; } mystique_t; - -static const uint8_t trans_masks[16][16] = -{ +static const uint8_t trans_masks[16][16] = { + // clang-format off { - 1, 1, 1, 1, - 1, 1, 1, 1, - 1, 1, 1, 1, - 1, 1, 1, 1 + 1, 1, 1, 1, + 1, 1, 1, 1, + 1, 1, 1, 1, + 1, 1, 1, 1 }, { - 1, 0, 1, 0, - 0, 1, 0, 1, - 1, 0, 1, 0, - 0, 1, 0, 1 + 1, 0, 1, 0, + 0, 1, 0, 1, + 1, 0, 1, 0, + 0, 1, 0, 1 }, { - 0, 1, 0, 1, - 1, 0, 1, 0, - 0, 1, 0, 1, - 1, 0, 1, 0 + 0, 1, 0, 1, + 1, 0, 1, 0, + 0, 1, 0, 1, + 1, 0, 1, 0 }, { - 1, 0, 1, 0, - 0, 0, 0, 0, - 1, 0, 1, 0, - 0, 0, 0, 0 + 1, 0, 1, 0, + 0, 0, 0, 0, + 1, 0, 1, 0, + 0, 0, 0, 0 }, { - 0, 1, 0, 1, - 0, 0, 0, 0, - 0, 1, 0, 1, - 0, 0, 0, 0 + 0, 1, 0, 1, + 0, 0, 0, 0, + 0, 1, 0, 1, + 0, 0, 0, 0 }, { - 0, 0, 0, 0, - 1, 0, 1, 0, - 0, 0, 0, 0, - 1, 0, 1, 0 + 0, 0, 0, 0, + 1, 0, 1, 0, + 0, 0, 0, 0, + 1, 0, 1, 0 }, { - 0, 0, 0, 0, - 0, 1, 0, 1, - 0, 0, 0, 0, - 0, 1, 0, 1 + 0, 0, 0, 0, + 0, 1, 0, 1, + 0, 0, 0, 0, + 0, 1, 0, 1 }, { - 1, 0, 0, 0, - 0, 0, 0, 0, - 0, 0, 1, 0, - 0, 0, 0, 0 + 1, 0, 0, 0, + 0, 0, 0, 0, + 0, 0, 1, 0, + 0, 0, 0, 0 }, { - 0, 0, 0, 0, - 0, 1, 0, 0, - 0, 0, 0, 0, - 0, 0, 0, 1 + 0, 0, 0, 0, + 0, 1, 0, 0, + 0, 0, 0, 0, + 0, 0, 0, 1 }, { - 0, 0, 0, 1, - 0, 0, 0, 0, - 0, 1, 0, 0, - 0, 0, 0, 0 + 0, 0, 0, 1, + 0, 0, 0, 0, + 0, 1, 0, 0, + 0, 0, 0, 0 }, { - 0, 0, 0, 0, - 0, 0, 1, 0, - 0, 0, 0, 0, - 1, 0, 0, 0 + 0, 0, 0, 0, + 0, 0, 1, 0, + 0, 0, 0, 0, + 1, 0, 0, 0 }, { - 0, 0, 0, 0, - 1, 0, 0, 0, - 0, 0, 0, 0, - 0, 0, 1, 0 + 0, 0, 0, 0, + 1, 0, 0, 0, + 0, 0, 0, 0, + 0, 0, 1, 0 }, { - 0, 1, 0, 0, - 0, 0, 0, 0, - 0, 0, 0, 1, - 0, 0, 0, 0 + 0, 1, 0, 0, + 0, 0, 0, 0, + 0, 0, 0, 1, + 0, 0, 0, 0 }, { - 0, 0, 0, 0, - 0, 0, 0, 1, - 0, 0, 0, 0, - 0, 1, 0, 0 + 0, 0, 0, 0, + 0, 0, 0, 1, + 0, 0, 0, 0, + 0, 1, 0, 0 }, { - 0, 0, 1, 0, - 0, 0, 0, 0, - 1, 0, 0, 0, - 0, 0, 0, 0 + 0, 0, 1, 0, + 0, 0, 0, 0, + 1, 0, 0, 0, + 0, 0, 0, 0 }, { - 0, 0, 0, 0, - 0, 0, 0, 0, - 0, 0, 0, 0, - 0, 0, 0, 0 + 0, 0, 0, 0, + 0, 0, 0, 0, + 0, 0, 0, 0, + 0, 0, 0, 0 } + // clang-format on }; +static int8_t dither5[256][2][2]; +static int8_t dither6[256][2][2]; -static int8_t dither5[256][2][2]; -static int8_t dither6[256][2][2]; +static video_timings_t timing_matrox_millennium = { .type = VIDEO_PCI, .write_b = 2, .write_w = 2, .write_l = 1, .read_b = 10, .read_w = 10, .read_l = 10 }; +static video_timings_t timing_matrox_mystique = { .type = VIDEO_PCI, .write_b = 4, .write_w = 4, .write_l = 4, .read_b = 10, .read_w = 10, .read_l = 10 }; -static video_timings_t timing_matrox_millennium = {VIDEO_PCI, 2, 2, 1, 10, 10, 10}; -static video_timings_t timing_matrox_mystique = {VIDEO_PCI, 4, 4, 4, 10, 10, 10}; +static void mystique_start_blit(mystique_t *mystique); +static void mystique_update_irqs(mystique_t *mystique); -static void mystique_start_blit(mystique_t *mystique); -static void mystique_update_irqs(mystique_t *mystique); +static void wake_fifo_thread(mystique_t *mystique); +static void wait_fifo_idle(mystique_t *mystique); +static void mystique_queue(mystique_t *mystique, uint32_t addr, uint32_t val, uint32_t type); -static void wake_fifo_thread(mystique_t *mystique); -static void wait_fifo_idle(mystique_t *mystique); -static void mystique_queue(mystique_t *mystique, uint32_t addr, uint32_t val, uint32_t type); +static uint8_t mystique_readb_linear(uint32_t addr, void *priv); +static uint16_t mystique_readw_linear(uint32_t addr, void *priv); +static uint32_t mystique_readl_linear(uint32_t addr, void *priv); +static void mystique_writeb_linear(uint32_t addr, uint8_t val, void *priv); +static void mystique_writew_linear(uint32_t addr, uint16_t val, void *priv); +static void mystique_writel_linear(uint32_t addr, uint32_t val, void *priv); -static uint8_t mystique_readb_linear(uint32_t addr, void *p); -static uint16_t mystique_readw_linear(uint32_t addr, void *p); -static uint32_t mystique_readl_linear(uint32_t addr, void *p); -static void mystique_writeb_linear(uint32_t addr, uint8_t val, void *p); -static void mystique_writew_linear(uint32_t addr, uint16_t val, void *p); -static void mystique_writel_linear(uint32_t addr, uint32_t val, void *p); +static void mystique_recalc_mapping(mystique_t *mystique); +static int mystique_line_compare(svga_t *svga); -static void mystique_recalc_mapping(mystique_t *mystique); -static int mystique_line_compare(svga_t *svga); - -static uint8_t mystique_iload_read_b(uint32_t addr, void *p); -static uint32_t mystique_iload_read_l(uint32_t addr, void *p); -static void mystique_iload_write_b(uint32_t addr, uint8_t val, void *p); -static void mystique_iload_write_l(uint32_t addr, uint32_t val, void *p); - -static uint32_t blit_idump_read(mystique_t *mystique); -static void blit_iload_write(mystique_t *mystique, uint32_t data, int size); +static uint8_t mystique_iload_read_b(uint32_t addr, void *priv); +static uint32_t mystique_iload_read_l(uint32_t addr, void *priv); +static void mystique_iload_write_b(uint32_t addr, uint8_t val, void *priv); +static void mystique_iload_write_l(uint32_t addr, uint32_t val, void *priv); +static uint32_t blit_idump_read(mystique_t *mystique); +static void blit_iload_write(mystique_t *mystique, uint32_t data, int size); void -mystique_out(uint16_t addr, uint8_t val, void *p) +mystique_out(uint16_t addr, uint8_t val, void *priv) { - mystique_t *mystique = (mystique_t *)p; - svga_t *svga = &mystique->svga; - uint8_t old; + mystique_t *mystique = (mystique_t *) priv; + svga_t *svga = &mystique->svga; + uint8_t old; - if ((((addr&0xFFF0) == 0x3D0 || (addr&0xFFF0) == 0x3B0) && addr < 0x3de) && !(svga->miscout & 1)) - addr ^= 0x60; + if ((((addr & 0xFFF0) == 0x3D0 || (addr & 0xFFF0) == 0x3B0) && addr < 0x3de) && !(svga->miscout & 1)) + addr ^= 0x60; switch (addr) { - case 0x3c8: - mystique->xreg_idx = val; - case 0x3c6: case 0x3c7: case 0x3c9: - if (mystique->type == MGA_2064W) - { - tvp3026_ramdac_out(addr, 0, 0, val, svga->ramdac, svga); - return; - } - break; + case 0x3c8: + mystique->xreg_idx = val; + fallthrough; + case 0x3c6: + case 0x3c7: + case 0x3c9: + if (mystique->type == MGA_2064W) { + tvp3026_ramdac_out(addr, 0, 0, val, svga->ramdac, svga); + return; + } + break; - case 0x3cf: - if ((svga->gdcaddr & 15) == 6 && svga->gdcreg[6] != val) { - svga->gdcreg[svga->gdcaddr & 15] = val; - mystique_recalc_mapping(mystique); - return; - } - break; + case 0x3cf: + if ((svga->gdcaddr & 15) == 6 && svga->gdcreg[6] != val) { + svga->gdcreg[svga->gdcaddr & 15] = val; + mystique_recalc_mapping(mystique); + return; + } + break; - case 0x3D4: - svga->crtcreg = val & 0x3f; - return; - case 0x3D5: - if (((svga->crtcreg & 0x3f) < 7) && (svga->crtc[0x11] & 0x80)) - return; - if (((svga->crtcreg & 0x3f) == 7) && (svga->crtc[0x11] & 0x80)) - val = (svga->crtc[7] & ~0x10) | (val & 0x10); - old = svga->crtc[svga->crtcreg & 0x3f]; - svga->crtc[svga->crtcreg & 0x3f] = val; - if (old != val) { - if ((svga->crtcreg & 0x3f) < 0xE || (svga->crtcreg & 0x3f) > 0x10) { - if (((svga->crtcreg & 0x3f) == 0xc) || ((svga->crtcreg & 0x3f) == 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); - } - } - if (svga->crtcreg == 0x11) { - if (!(val & 0x10)) - mystique->status &= ~STATUS_VSYNCPEN; - mystique_update_irqs(mystique); - } - } - break; + case 0x3D4: + svga->crtcreg = val & 0x3f; + return; + case 0x3D5: + if (((svga->crtcreg & 0x3f) < 7) && (svga->crtc[0x11] & 0x80)) + return; + if (((svga->crtcreg & 0x3f) == 7) && (svga->crtc[0x11] & 0x80)) + val = (svga->crtc[7] & ~0x10) | (val & 0x10); + old = svga->crtc[svga->crtcreg & 0x3f]; + svga->crtc[svga->crtcreg & 0x3f] = val; + if (old != val) { + if ((svga->crtcreg & 0x3f) < 0xE || (svga->crtcreg & 0x3f) > 0x10) { + if (((svga->crtcreg & 0x3f) == 0xc) || ((svga->crtcreg & 0x3f) == 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); + } + } + if (svga->crtcreg == 0x11) { + if (!(val & 0x10)) + mystique->status &= ~STATUS_VSYNCPEN; + mystique_update_irqs(mystique); + } + } + break; - case 0x3de: - mystique->crtcext_idx = val; - break; - case 0x3df: - if (mystique->crtcext_idx < 6) - mystique->crtcext_regs[mystique->crtcext_idx] = val; - if (mystique->crtcext_idx == 1) - svga->dpms = !!(val & 0x30); - if (mystique->crtcext_idx < 4) { - svga->fullchange = changeframecount; - svga_recalctimings(svga); - } - if (mystique->crtcext_idx == 3) { - if (val & CRTCX_R3_MGAMODE) - svga->fb_only = 1; - else - svga->fb_only = 0; - svga_recalctimings(svga); - } - if (mystique->crtcext_idx == 4) { - if (svga->gdcreg[6] & 0xc) { - /*64k banks*/ - svga->read_bank = (val & 0x7f) << 16; - svga->write_bank = (val & 0x7f) << 16; - } else { - /*128k banks*/ - svga->read_bank = (val & 0x7e) << 16; - svga->write_bank = (val & 0x7e) << 16; - } - } - break; + case 0x3de: + mystique->crtcext_idx = val; + break; + case 0x3df: + if (mystique->crtcext_idx < 6) + mystique->crtcext_regs[mystique->crtcext_idx] = val; + if (mystique->crtcext_idx == 1) + svga->dpms = !!(val & 0x30); + if (mystique->crtcext_idx < 4) { + svga->fullchange = changeframecount; + svga_recalctimings(svga); + } + if (mystique->crtcext_idx == 3) { + if (val & CRTCX_R3_MGAMODE) + svga->fb_only = 1; + else + svga->fb_only = 0; + svga_recalctimings(svga); + } + if (mystique->crtcext_idx == 4) { + if (svga->gdcreg[6] & 0xc) { + /*64k banks*/ + svga->read_bank = (val & 0x7f) << 16; + svga->write_bank = (val & 0x7f) << 16; + } else { + /*128k banks*/ + svga->read_bank = (val & 0x7e) << 16; + svga->write_bank = (val & 0x7e) << 16; + } + } + break; + + default: + break; } svga_out(addr, val, svga); } - uint8_t -mystique_in(uint16_t addr, void *p) +mystique_in(uint16_t addr, void *priv) { - mystique_t *mystique = (mystique_t *)p; - svga_t *svga = &mystique->svga; - uint8_t temp = 0xff; + mystique_t *mystique = (mystique_t *) priv; + svga_t *svga = &mystique->svga; + uint8_t temp = 0xff; - if ((((addr&0xFFF0) == 0x3D0 || (addr&0xFFF0) == 0x3B0) && addr < 0x3de) && !(svga->miscout & 1)) - addr ^= 0x60; + if ((((addr & 0xFFF0) == 0x3D0 || (addr & 0xFFF0) == 0x3B0) && addr < 0x3de) && !(svga->miscout & 1)) + addr ^= 0x60; switch (addr) { - case 0x3c1: - if (svga->attraddr >= 0x15) - temp = 0; - else - temp = svga->attrregs[svga->attraddr]; - break; + case 0x3c1: + if (svga->attraddr >= 0x15) + temp = 0; + else + temp = svga->attrregs[svga->attraddr]; + break; - case 0x3c6: case 0x3c7: case 0x3c8: case 0x3c9: - if (mystique->type == MGA_2064W) - temp = tvp3026_ramdac_in(addr, 0, 0, svga->ramdac, svga); - else - temp = svga_in(addr, svga); - break; - - case 0x3D4: - temp = svga->crtcreg; - break; - case 0x3D5: - if ((svga->crtcreg >= 0x19 && svga->crtcreg <= 0x21) || - svga->crtcreg == 0x23 || svga->crtcreg == 0x25 || svga->crtcreg >= 0x27) - temp = 0; - else - temp = svga->crtc[svga->crtcreg & 0x3f]; - break; + case 0x3c6: + case 0x3c7: + case 0x3c8: + case 0x3c9: + if (mystique->type == MGA_2064W) + temp = tvp3026_ramdac_in(addr, 0, 0, svga->ramdac, svga); + else + temp = svga_in(addr, svga); + break; - case 0x3de: - temp = mystique->crtcext_idx; - break; + case 0x3D4: + temp = svga->crtcreg; + break; + case 0x3D5: + if ((svga->crtcreg >= 0x19 && svga->crtcreg <= 0x21) || svga->crtcreg == 0x23 || svga->crtcreg == 0x25 || svga->crtcreg >= 0x27) + temp = 0; + else + temp = svga->crtc[svga->crtcreg & 0x3f]; + break; - case 0x3df: - if (mystique->crtcext_idx < 6) - temp = mystique->crtcext_regs[mystique->crtcext_idx]; - break; + case 0x3de: + temp = mystique->crtcext_idx; + break; - default: - temp = svga_in(addr, svga); - break; + case 0x3df: + if (mystique->crtcext_idx < 6) + temp = mystique->crtcext_regs[mystique->crtcext_idx]; + break; + + default: + temp = svga_in(addr, svga); + break; } return temp; } - static int mystique_line_compare(svga_t *svga) { - mystique_t *mystique = (mystique_t *)svga->p; + mystique_t *mystique = (mystique_t *) svga->priv; mystique->status |= STATUS_VLINEPEN; mystique_update_irqs(mystique); @@ -815,244 +816,268 @@ mystique_line_compare(svga_t *svga) return 0; } -static void +static void mystique_vsync_callback(svga_t *svga) { - mystique_t *mystique = (mystique_t *)svga->p; + mystique_t *mystique = (mystique_t *) svga->priv; if (svga->crtc[0x11] & 0x10) { - mystique->status |= STATUS_VSYNCPEN; - mystique_update_irqs(mystique); - } + mystique->status |= STATUS_VSYNCPEN; + mystique_update_irqs(mystique); + } } static float -mystique_getclock(int clock, void *p) +mystique_getclock(int clock, void *priv) { - mystique_t *mystique = (mystique_t *)p; - - if (clock == 0) return 25175000.0; - if (clock == 1) return 28322000.0; - - int m = mystique->xpixpll[2].m; - int n = mystique->xpixpll[2].n; - int pl = mystique->xpixpll[2].p; + const mystique_t *mystique = (mystique_t *) priv; - float fvco = 14318181.0 * (n + 1) / (m + 1); - float fo = fvco / (pl + 1); + if (clock == 0) + return 25175000.0; + if (clock == 1) + return 28322000.0; - return fo; + int m = mystique->xpixpll[2].m; + int n = mystique->xpixpll[2].n; + int pl = mystique->xpixpll[2].p; + + float fvco = 14318181.0 * (n + 1) / (m + 1); + float fo = fvco / (pl + 1); + + return fo; } void mystique_recalctimings(svga_t *svga) { - mystique_t *mystique = (mystique_t *)svga->p; - int clk_sel = (svga->miscout >> 2) & 3; + mystique_t *mystique = (mystique_t *) svga->priv; + int clk_sel = (svga->miscout >> 2) & 3; - svga->clock = (cpuclock * (float)(1ull << 32)) / svga->getclock(clk_sel & 2, svga->clock_gen); + svga->clock = (cpuclock * (float) (1ULL << 32)) / svga->getclock(clk_sel & 3, svga->clock_gen); if (mystique->crtcext_regs[1] & CRTCX_R1_HTOTAL8) - svga->htotal += 0x100; + svga->htotal += 0x100; if (mystique->crtcext_regs[2] & CRTCX_R2_VTOTAL10) - svga->vtotal += 0x400; + svga->vtotal += 0x400; if (mystique->crtcext_regs[2] & CRTCX_R2_VTOTAL11) - svga->vtotal += 0x800; + svga->vtotal += 0x800; if (mystique->crtcext_regs[2] & CRTCX_R2_VDISPEND10) - svga->dispend += 0x400; + svga->dispend += 0x400; if (mystique->crtcext_regs[2] & CRTCX_R2_VBLKSTR10) - svga->vblankstart += 0x400; + svga->vblankstart += 0x400; if (mystique->crtcext_regs[2] & CRTCX_R2_VBLKSTR11) - svga->vblankstart += 0x800; + svga->vblankstart += 0x800; if (mystique->crtcext_regs[2] & CRTCX_R2_VSYNCSTR10) - svga->vsyncstart += 0x400; + svga->vsyncstart += 0x400; if (mystique->crtcext_regs[2] & CRTCX_R2_VSYNCSTR11) - svga->vsyncstart += 0x800; + svga->vsyncstart += 0x800; if (mystique->crtcext_regs[2] & CRTCX_R2_LINECOMP10) - svga->split += 0x400; + svga->split += 0x400; if (mystique->type == MGA_2064W) - tvp3026_recalctimings(svga->ramdac, svga); - else - svga->interlace = !!(mystique->crtcext_regs[0] & 0x80); + tvp3026_recalctimings(svga->ramdac, svga); + else + svga->interlace = !!(mystique->crtcext_regs[0] & 0x80); if (mystique->crtcext_regs[3] & CRTCX_R3_MGAMODE) { - svga->packed_chain4 = 1; - svga->lowres = 0; - svga->char_width = 8; - svga->hdisp = (svga->crtc[1] + 1) * 8; - svga->hdisp_time = svga->hdisp; - svga->rowoffset = svga->crtc[0x13] | ((mystique->crtcext_regs[0] & CRTCX_R0_OFFSET_MASK) << 4); - svga->ma_latch = ((mystique->crtcext_regs[0] & CRTCX_R0_STARTADD_MASK) << 16) | - (svga->crtc[0xc] << 8) | svga->crtc[0xd]; - if (mystique->pci_regs[0x41] & (OPTION_INTERLEAVE >> 8)) - { - svga->rowoffset <<= 1; - svga->ma_latch <<= 1; - } - if (mystique->type >= MGA_1064SG) { - /*Mystique, unlike most SVGA cards, allows display start to take - effect mid-screen*/ - if (svga->ma_latch != mystique->ma_latch_old) { - if (svga->interlace && svga->oddeven) - svga->ma = svga->maback = (svga->maback - (mystique->ma_latch_old << 2)) + (svga->ma_latch << 2) + (svga->rowoffset << 1); - else - svga->ma = svga->maback = (svga->maback - (mystique->ma_latch_old << 2)) + (svga->ma_latch << 2); - mystique->ma_latch_old = svga->ma_latch; - } + svga->packed_chain4 = 1; + svga->lowres = 0; + svga->char_width = 8; + svga->hdisp = (svga->crtc[1] + 1) * 8; + svga->hdisp_time = svga->hdisp; + svga->rowoffset = svga->crtc[0x13] | ((mystique->crtcext_regs[0] & CRTCX_R0_OFFSET_MASK) << 4); + svga->ma_latch = ((mystique->crtcext_regs[0] & CRTCX_R0_STARTADD_MASK) << 16) | (svga->crtc[0xc] << 8) | svga->crtc[0xd]; + if (mystique->pci_regs[0x41] & (OPTION_INTERLEAVE >> 8)) { + svga->rowoffset <<= 1; + svga->ma_latch <<= 1; + } + if (mystique->type >= MGA_1064SG) { + /*Mystique, unlike most SVGA cards, allows display start to take + effect mid-screen*/ + if (svga->ma_latch != mystique->ma_latch_old) { + if (svga->interlace && svga->oddeven) + svga->ma = svga->maback = (svga->maback - (mystique->ma_latch_old << 2)) + (svga->ma_latch << 2) + (svga->rowoffset << 1); + else + svga->ma = svga->maback = (svga->maback - (mystique->ma_latch_old << 2)) + (svga->ma_latch << 2); + mystique->ma_latch_old = svga->ma_latch; + } - switch (mystique->xmulctrl & XMULCTRL_DEPTH_MASK) { - case XMULCTRL_DEPTH_8: - case XMULCTRL_DEPTH_2G8V16: - svga->render = svga_render_8bpp_highres; - svga->bpp = 8; - break; - case XMULCTRL_DEPTH_15: - case XMULCTRL_DEPTH_G16V16: - svga->render = svga_render_15bpp_highres; - svga->bpp = 15; - break; - case XMULCTRL_DEPTH_16: - svga->render = svga_render_16bpp_highres; - svga->bpp = 16; - break; - case XMULCTRL_DEPTH_24: - svga->render = svga_render_24bpp_highres; - svga->bpp = 24; - break; - case XMULCTRL_DEPTH_32: - case XMULCTRL_DEPTH_32_OVERLAYED: - svga->render = svga_render_32bpp_highres; - svga->bpp = 32; - break; - } - } else { - switch (svga->bpp) - { - case 8: - 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; - case 32: - svga->render = svga_render_32bpp_highres; - break; - } - } - svga->line_compare = mystique_line_compare; + svga->rowoffset <<= 1; + + switch (mystique->xmulctrl & XMULCTRL_DEPTH_MASK) { + case XMULCTRL_DEPTH_8: + case XMULCTRL_DEPTH_2G8V16: + svga->render = svga_render_8bpp_highres; + svga->bpp = 8; + break; + case XMULCTRL_DEPTH_15: + case XMULCTRL_DEPTH_G16V16: + svga->render = svga_render_15bpp_highres; + svga->bpp = 15; + break; + case XMULCTRL_DEPTH_16: + svga->render = svga_render_16bpp_highres; + svga->bpp = 16; + break; + case XMULCTRL_DEPTH_24: + svga->render = svga_render_24bpp_highres; + svga->bpp = 24; + break; + case XMULCTRL_DEPTH_32: + case XMULCTRL_DEPTH_32_OVERLAYED: + svga->render = svga_render_32bpp_highres; + svga->bpp = 32; + break; + + default: + break; + } + } else { + switch (svga->bpp) { + case 8: + 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; + case 32: + svga->render = svga_render_32bpp_highres; + break; + + default: + break; + } + } + svga->line_compare = mystique_line_compare; } else { - svga->packed_chain4 = 0; - svga->line_compare = NULL; - if (mystique->type >= MGA_1064SG) - svga->bpp = 8; + svga->packed_chain4 = 0; + svga->line_compare = NULL; + if (mystique->type >= MGA_1064SG) + svga->bpp = 8; } } - -static -void mystique_recalc_mapping(mystique_t *mystique) +static void +mystique_recalc_mapping(mystique_t *mystique) { svga_t *svga = &mystique->svga; io_removehandler(0x03c0, 0x0020, mystique_in, NULL, NULL, mystique_out, NULL, NULL, mystique); if ((mystique->pci_regs[PCI_REG_COMMAND] & PCI_COMMAND_IO) && (mystique->pci_regs[0x41] & 1)) - io_sethandler(0x03c0, 0x0020, mystique_in, NULL, NULL, mystique_out, NULL, NULL, mystique); + io_sethandler(0x03c0, 0x0020, mystique_in, NULL, NULL, mystique_out, NULL, NULL, mystique); if (!(mystique->pci_regs[PCI_REG_COMMAND] & PCI_COMMAND_MEM)) { - mem_mapping_disable(&svga->mapping); - mem_mapping_disable(&mystique->ctrl_mapping); - mem_mapping_disable(&mystique->lfb_mapping); - mem_mapping_disable(&mystique->iload_mapping); - return; + mem_mapping_disable(&svga->mapping); + mem_mapping_disable(&mystique->ctrl_mapping); + mem_mapping_disable(&mystique->lfb_mapping); + mem_mapping_disable(&mystique->iload_mapping); + return; } if (mystique->ctrl_base) - mem_mapping_set_addr(&mystique->ctrl_mapping, mystique->ctrl_base, 0x4000); + mem_mapping_set_addr(&mystique->ctrl_mapping, mystique->ctrl_base, 0x4000); else - mem_mapping_disable(&mystique->ctrl_mapping); + mem_mapping_disable(&mystique->ctrl_mapping); if (mystique->lfb_base) - mem_mapping_set_addr(&mystique->lfb_mapping, mystique->lfb_base, 0x800000); + mem_mapping_set_addr(&mystique->lfb_mapping, mystique->lfb_base, 0x800000); else - mem_mapping_disable(&mystique->lfb_mapping); + mem_mapping_disable(&mystique->lfb_mapping); if (mystique->iload_base) - mem_mapping_set_addr(&mystique->iload_mapping, mystique->iload_base, 0x800000); + mem_mapping_set_addr(&mystique->iload_mapping, mystique->iload_base, 0x800000); else - mem_mapping_disable(&mystique->iload_mapping); + mem_mapping_disable(&mystique->iload_mapping); if (mystique->pci_regs[0x41] & 1) { - switch (svga->gdcreg[6] & 0x0C) { - case 0x0: /*128k at A0000*/ - mem_mapping_set_addr(&svga->mapping, 0xa0000, 0x10000); - svga->banked_mask = 0x1ffff; - break; - case 0x4: /*64k at A0000*/ - mem_mapping_set_addr(&svga->mapping, 0xa0000, 0x10000); - svga->banked_mask = 0xffff; - break; - case 0x8: /*32k at B0000*/ - mem_mapping_set_addr(&svga->mapping, 0xb0000, 0x08000); - svga->banked_mask = 0x7fff; - break; - case 0xC: /*32k at B8000*/ - mem_mapping_set_addr(&svga->mapping, 0xb8000, 0x08000); - svga->banked_mask = 0x7fff; - break; - } - if (svga->gdcreg[6] & 0xc) { - /*64k banks*/ - svga->read_bank = (mystique->crtcext_regs[4] & 0x7f) << 16; - svga->write_bank = (mystique->crtcext_regs[4] & 0x7f) << 16; - } else { - /*128k banks*/ - svga->read_bank = (mystique->crtcext_regs[4] & 0x7e) << 16; - svga->write_bank = (mystique->crtcext_regs[4] & 0x7e) << 16; - } - } else - mem_mapping_disable(&svga->mapping); -} + switch (svga->gdcreg[6] & 0x0C) { + case 0x0: /*128k at A0000*/ + mem_mapping_set_addr(&svga->mapping, 0xa0000, 0x10000); + svga->banked_mask = 0x1ffff; + 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; + default: + break; + } + if (svga->gdcreg[6] & 0xc) { + /*64k banks*/ + svga->read_bank = (mystique->crtcext_regs[4] & 0x7f) << 16; + svga->write_bank = (mystique->crtcext_regs[4] & 0x7f) << 16; + } else { + /*128k banks*/ + svga->read_bank = (mystique->crtcext_regs[4] & 0x7e) << 16; + svga->write_bank = (mystique->crtcext_regs[4] & 0x7e) << 16; + } + } else + mem_mapping_disable(&svga->mapping); +} static void mystique_update_irqs(mystique_t *mystique) { - svga_t *svga = &mystique->svga; - int irq = 0; + const svga_t *svga = &mystique->svga; + int irq = 0; if ((mystique->status & mystique->ien) & STATUS_SOFTRAPEN) - irq = 1; + irq = 1; if ((mystique->status & STATUS_VSYNCPEN) && (svga->crtc[0x11] & 0x30) == 0x10) - irq = 1; + irq = 1; if (irq) - pci_set_irq(mystique->card, PCI_INTA); + pci_set_irq(mystique->pci_slot, PCI_INTA, &mystique->irq_state); else - pci_clear_irq(mystique->card, PCI_INTA); + pci_clear_irq(mystique->pci_slot, PCI_INTA, &mystique->irq_state); } +#define READ8(addr, var) \ + switch ((addr) &3) { \ + case 0: \ + ret = (var) &0xff; \ + break; \ + case 1: \ + ret = ((var) >> 8) & 0xff; \ + break; \ + case 2: \ + ret = ((var) >> 16) & 0xff; \ + break; \ + case 3: \ + ret = ((var) >> 24) & 0xff; \ + break; \ + } -#define READ8(addr, var) switch ((addr) & 3) { \ - case 0: ret = (var) & 0xff; break; \ - case 1: ret = ((var) >> 8) & 0xff; break; \ - case 2: ret = ((var) >> 16) & 0xff; break; \ - case 3: ret = ((var) >> 24) & 0xff; break; \ - } - -#define WRITE8(addr, var, val) switch ((addr) & 3) { \ - case 0: var = (var & 0xffffff00) | (val); break; \ - case 1: var = (var & 0xffff00ff) | ((val) << 8); break; \ - case 2: var = (var & 0xff00ffff) | ((val) << 16); break; \ - case 3: var = (var & 0x00ffffff) | ((val) << 24); break; \ - } - +#define WRITE8(addr, var, val) \ + switch ((addr) &3) { \ + case 0: \ + var = (var & 0xffffff00) | (val); \ + break; \ + case 1: \ + var = (var & 0xffff00ff) | ((val) << 8); \ + break; \ + case 2: \ + var = (var & 0xff00ffff) | ((val) << 16); \ + break; \ + case 3: \ + var = (var & 0x00ffffff) | ((val) << 24); \ + break; \ + } static uint8_t mystique_read_xreg(mystique_t *mystique, int reg) @@ -1060,1340 +1085,1572 @@ mystique_read_xreg(mystique_t *mystique, int reg) uint8_t ret = 0xff; switch (reg) { - case XREG_XCURADDL: - ret = mystique->cursor.addr & 0xff; - break; - case XREG_XCURADDH: - ret = mystique->cursor.addr >> 8; - break; - case XREG_XCURCTRL: - ret = mystique->xcurctrl; - break; + case XREG_XCURADDL: + ret = mystique->cursor.addr & 0xff; + break; + case XREG_XCURADDH: + ret = mystique->cursor.addr >> 8; + break; + case XREG_XCURCTRL: + ret = mystique->xcurctrl; + break; - case XREG_XCURCOL0R: case XREG_XCURCOL0G: case XREG_XCURCOL0B: - READ8(reg, mystique->cursor.col[0]); - break; - case XREG_XCURCOL1R: case XREG_XCURCOL1G: case XREG_XCURCOL1B: - READ8(reg, mystique->cursor.col[1]); - break; - case XREG_XCURCOL2R: case XREG_XCURCOL2G: case XREG_XCURCOL2B: - READ8(reg, mystique->cursor.col[2]); - break; + case XREG_XCURCOL0R: + case XREG_XCURCOL0G: + case XREG_XCURCOL0B: + READ8(reg, mystique->cursor.col[0]); + break; + case XREG_XCURCOL1R: + case XREG_XCURCOL1G: + case XREG_XCURCOL1B: + READ8(reg, mystique->cursor.col[1]); + break; + case XREG_XCURCOL2R: + case XREG_XCURCOL2G: + case XREG_XCURCOL2B: + READ8(reg, mystique->cursor.col[2]); + break; - case XREG_XMULCTRL: - ret = mystique->xmulctrl; - break; + case XREG_XMULCTRL: + ret = mystique->xmulctrl; + break; - case XREG_XMISCCTRL: - ret = mystique->xmiscctrl; - break; + case XREG_XMISCCTRL: + ret = mystique->xmiscctrl; + break; - case XREG_XGENCTRL: - ret = mystique->xgenctrl; - break; + case XREG_XGENCTRL: + ret = mystique->xgenctrl; + break; - case XREG_XVREFCTRL: - ret = mystique->xvrefctrl; - break; + case XREG_XVREFCTRL: + ret = mystique->xvrefctrl; + break; - case XREG_XGENIOCTRL: - ret = mystique->xgenioctrl; - break; - case XREG_XGENIODATA: - ret = mystique->xgeniodata & 0xf0; - if (i2c_gpio_get_scl(mystique->i2c_ddc)) - ret |= 0x08; - if (i2c_gpio_get_scl(mystique->i2c)) - ret |= 0x04; - if (i2c_gpio_get_sda(mystique->i2c_ddc)) - ret |= 0x02; - if (i2c_gpio_get_sda(mystique->i2c)) - ret |= 0x01; - break; + case XREG_XGENIOCTRL: + ret = mystique->xgenioctrl; + break; + case XREG_XGENIODATA: + ret = mystique->xgeniodata & 0xf0; + if (i2c_gpio_get_scl(mystique->i2c_ddc)) + ret |= 0x08; + if (i2c_gpio_get_scl(mystique->i2c)) + ret |= 0x04; + if (i2c_gpio_get_sda(mystique->i2c_ddc)) + ret |= 0x02; + if (i2c_gpio_get_sda(mystique->i2c)) + ret |= 0x01; + break; - case XREG_XSYSPLLM: - ret = mystique->xsyspllm; - break; - case XREG_XSYSPLLN: - ret = mystique->xsysplln; - break; - case XREG_XSYSPLLP: - ret = mystique->xsyspllp; - break; + case XREG_XSYSPLLM: + ret = mystique->xsyspllm; + break; + case XREG_XSYSPLLN: + ret = mystique->xsysplln; + break; + case XREG_XSYSPLLP: + ret = mystique->xsyspllp; + break; - case XREG_XZOOMCTRL: - ret = mystique->xzoomctrl; - break; + case XREG_XZOOMCTRL: + ret = mystique->xzoomctrl; + break; - case XREG_XSENSETEST: - ret = 0; - if (mystique->svga.vgapal[0].b < 0x80) - ret |= 1; - if (mystique->svga.vgapal[0].g < 0x80) - ret |= 2; - if (mystique->svga.vgapal[0].r < 0x80) - ret |= 4; - break; - - case XREG_XCRCREML: /*CRC not implemented*/ - ret = 0; - break; - case XREG_XCRCREMH: - ret = 0; - break; - case XREG_XCRCBITSEL: - ret = mystique->xcrcbitsel; - break; + case XREG_XSENSETEST: + ret = 0; + if (mystique->svga.vgapal[0].b < 0x80) + ret |= 1; + if (mystique->svga.vgapal[0].g < 0x80) + ret |= 2; + if (mystique->svga.vgapal[0].r < 0x80) + ret |= 4; + break; - case XREG_XCOLKEYMSKL: - ret = mystique->xcolkeymskl; - break; - case XREG_XCOLKEYMSKH: - ret = mystique->xcolkeymskh; - break; - case XREG_XCOLKEYL: - ret = mystique->xcolkeyl; - break; - case XREG_XCOLKEYH: - ret = mystique->xcolkeyh; - break; + case XREG_XCRCREML: /*CRC not implemented*/ + ret = 0; + break; + case XREG_XCRCREMH: + ret = 0; + break; + case XREG_XCRCBITSEL: + ret = mystique->xcrcbitsel; + break; - case XREG_XPIXCLKCTRL: - ret = mystique->xpixclkctrl; - break; + case XREG_XCOLKEYMSKL: + ret = mystique->xcolkeymskl; + break; + case XREG_XCOLKEYMSKH: + ret = mystique->xcolkeymskh; + break; + case XREG_XCOLKEYL: + ret = mystique->xcolkeyl; + break; + case XREG_XCOLKEYH: + ret = mystique->xcolkeyh; + break; - case XREG_XSYSPLLSTAT: - ret = XSYSPLLSTAT_SYSLOCK; - break; + case XREG_XPIXCLKCTRL: + ret = mystique->xpixclkctrl; + break; - case XREG_XPIXPLLSTAT: - ret = XPIXPLLSTAT_SYSLOCK; - break; + case XREG_XSYSPLLSTAT: + ret = XSYSPLLSTAT_SYSLOCK; + break; - case XREG_XPIXPLLCM: - ret = mystique->xpixpll[2].m; - break; - case XREG_XPIXPLLCN: - ret = mystique->xpixpll[2].n; - break; - case XREG_XPIXPLLCP: - ret = mystique->xpixpll[2].p | (mystique->xpixpll[2].s << 3); - break; + case XREG_XPIXPLLSTAT: + ret = XPIXPLLSTAT_SYSLOCK; + break; - case 0x00: case 0x20: case 0x3f: - ret = 0xff; - break; + case XREG_XPIXPLLCM: + ret = mystique->xpixpll[2].m; + break; + case XREG_XPIXPLLCN: + ret = mystique->xpixpll[2].n; + break; + case XREG_XPIXPLLCP: + ret = mystique->xpixpll[2].p | (mystique->xpixpll[2].s << 3); + break; - default: - if (reg >= 0x50) - ret = 0xff; - break; + case 0x00: + case 0x20: + case 0x3f: + ret = 0xff; + break; + + default: + if (reg >= 0x50) + ret = 0xff; + break; } return ret; } - static void mystique_write_xreg(mystique_t *mystique, int reg, uint8_t val) { svga_t *svga = &mystique->svga; switch (reg) { - case XREG_XCURADDL: - mystique->cursor.addr = (mystique->cursor.addr & 0x1f00) | val; - svga->hwcursor.addr = mystique->cursor.addr << 10; - break; - case XREG_XCURADDH: - mystique->cursor.addr = (mystique->cursor.addr & 0x00ff) | ((val & 0x1f) << 8); - svga->hwcursor.addr = mystique->cursor.addr << 10; - break; + case XREG_XCURADDL: + mystique->cursor.addr = (mystique->cursor.addr & 0x1f00) | val; + svga->hwcursor.addr = mystique->cursor.addr << 10; + break; + case XREG_XCURADDH: + mystique->cursor.addr = (mystique->cursor.addr & 0x00ff) | ((val & 0x1f) << 8); + svga->hwcursor.addr = mystique->cursor.addr << 10; + break; - case XREG_XCURCTRL: - mystique->xcurctrl = val; - svga->hwcursor.ena = (val & 3) ? 1 : 0; - break; + case XREG_XCURCTRL: + mystique->xcurctrl = val; + svga->hwcursor.ena = (val & 3) ? 1 : 0; + break; - case XREG_XCURCOL0R: case XREG_XCURCOL0G: case XREG_XCURCOL0B: - WRITE8(reg, mystique->cursor.col[0], val); - break; - case XREG_XCURCOL1R: case XREG_XCURCOL1G: case XREG_XCURCOL1B: - WRITE8(reg, mystique->cursor.col[1], val); - break; - case XREG_XCURCOL2R: case XREG_XCURCOL2G: case XREG_XCURCOL2B: - WRITE8(reg, mystique->cursor.col[2], val); - break; + case XREG_XCURCOL0R: + case XREG_XCURCOL0G: + case XREG_XCURCOL0B: + WRITE8(reg, mystique->cursor.col[0], val); + break; + case XREG_XCURCOL1R: + case XREG_XCURCOL1G: + case XREG_XCURCOL1B: + WRITE8(reg, mystique->cursor.col[1], val); + break; + case XREG_XCURCOL2R: + case XREG_XCURCOL2G: + case XREG_XCURCOL2B: + WRITE8(reg, mystique->cursor.col[2], val); + break; - case XREG_XMULCTRL: - mystique->xmulctrl = val; - break; + case XREG_XMULCTRL: + mystique->xmulctrl = val; + break; - case XREG_XMISCCTRL: - mystique->xmiscctrl = val; - svga_set_ramdac_type(svga, (val & XMISCCTRL_VGA8DAC) ? RAMDAC_8BIT : RAMDAC_6BIT); - break; + case XREG_XMISCCTRL: + mystique->xmiscctrl = val; + svga_set_ramdac_type(svga, (val & XMISCCTRL_VGA8DAC) ? RAMDAC_8BIT : RAMDAC_6BIT); + break; - case XREG_XGENCTRL: - mystique->xgenctrl = val; - break; + case XREG_XGENCTRL: + mystique->xgenctrl = val; + break; - case XREG_XVREFCTRL: - mystique->xvrefctrl = val; - break; + case XREG_XVREFCTRL: + mystique->xvrefctrl = val; + break; - case XREG_XGENIOCTRL: - mystique->xgenioctrl = val; - i2c_gpio_set(mystique->i2c_ddc, !(mystique->xgenioctrl & 0x08) || (mystique->xgeniodata & 0x08), !(mystique->xgenioctrl & 0x02) || (mystique->xgeniodata & 0x02)); - i2c_gpio_set(mystique->i2c, !(mystique->xgenioctrl & 0x04) || (mystique->xgeniodata & 0x04), !(mystique->xgenioctrl & 0x01) || (mystique->xgeniodata & 0x01)); - break; - case XREG_XGENIODATA: - mystique->xgeniodata = val; - break; + case XREG_XGENIOCTRL: + mystique->xgenioctrl = val; + i2c_gpio_set(mystique->i2c_ddc, !(mystique->xgenioctrl & 0x08) || (mystique->xgeniodata & 0x08), !(mystique->xgenioctrl & 0x02) || (mystique->xgeniodata & 0x02)); + i2c_gpio_set(mystique->i2c, !(mystique->xgenioctrl & 0x04) || (mystique->xgeniodata & 0x04), !(mystique->xgenioctrl & 0x01) || (mystique->xgeniodata & 0x01)); + break; + case XREG_XGENIODATA: + mystique->xgeniodata = val; + break; - case XREG_XSYSPLLM: - mystique->xsyspllm = val; - break; - case XREG_XSYSPLLN: - mystique->xsysplln = val; - break; - case XREG_XSYSPLLP: - mystique->xsyspllp = val; - break; + case XREG_XSYSPLLM: + mystique->xsyspllm = val; + break; + case XREG_XSYSPLLN: + mystique->xsysplln = val; + break; + case XREG_XSYSPLLP: + mystique->xsyspllp = val; + break; - case XREG_XZOOMCTRL: - mystique->xzoomctrl = val & 3; - break; + case XREG_XZOOMCTRL: + mystique->xzoomctrl = val & 3; + break; - case XREG_XSENSETEST: - break; + case XREG_XSENSETEST: + break; - case XREG_XCRCREML: /*CRC not implemented*/ - break; - case XREG_XCRCREMH: - break; - case XREG_XCRCBITSEL: - mystique->xcrcbitsel = val & 0x1f; - break; + case XREG_XCRCREML: /*CRC not implemented*/ + break; + case XREG_XCRCREMH: + break; + case XREG_XCRCBITSEL: + mystique->xcrcbitsel = val & 0x1f; + break; - case XREG_XCOLKEYMSKL: - mystique->xcolkeymskl = val; - break; - case XREG_XCOLKEYMSKH: - mystique->xcolkeymskh = val; - break; - case XREG_XCOLKEYL: - mystique->xcolkeyl = val; - break; - case XREG_XCOLKEYH: - mystique->xcolkeyh = val; - break; + case XREG_XCOLKEYMSKL: + mystique->xcolkeymskl = val; + break; + case XREG_XCOLKEYMSKH: + mystique->xcolkeymskh = val; + break; + case XREG_XCOLKEYL: + mystique->xcolkeyl = val; + break; + case XREG_XCOLKEYH: + mystique->xcolkeyh = val; + break; - case XREG_XSYSPLLSTAT: - break; + case XREG_XSYSPLLSTAT: + break; - case XREG_XPIXPLLSTAT: - break; + case XREG_XPIXPLLSTAT: + break; - case XREG_XPIXCLKCTRL: - mystique->xpixclkctrl = val; - break; + case XREG_XPIXCLKCTRL: + mystique->xpixclkctrl = val; + break; - case XREG_XPIXPLLCM: - mystique->xpixpll[2].m = val; - break; - case XREG_XPIXPLLCN: - mystique->xpixpll[2].n = val; - break; - case XREG_XPIXPLLCP: - mystique->xpixpll[2].p = val & 7; - mystique->xpixpll[2].s = (val >> 3) & 3; - break; + case XREG_XPIXPLLCM: + mystique->xpixpll[2].m = val; + break; + case XREG_XPIXPLLCN: + mystique->xpixpll[2].n = val; + break; + case XREG_XPIXPLLCP: + mystique->xpixpll[2].p = val & 7; + mystique->xpixpll[2].s = (val >> 3) & 3; + break; - case 0x00: case 0x01: case 0x02: case 0x03: - case 0x07: case 0x0b: case 0x0f: - case 0x13: case 0x14: case 0x15: case 0x16: case 0x17: - case 0x1b: case 0x1c: case 0x20: case 0x39: case 0x3b: case 0x3f: - case 0x47: case 0x4b: - break; + case 0x00: + case 0x01: + case 0x02: + case 0x03: + case 0x07: + case 0x0b: + case 0x0f: + case 0x13: + case 0x14: + case 0x15: + case 0x16: + case 0x17: + case 0x1b: + case 0x1c: + case 0x20: + case 0x39: + case 0x3b: + case 0x3f: + case 0x47: + case 0x4b: + break; - default: - break; + default: + break; } } - static uint8_t -mystique_ctrl_read_b(uint32_t addr, void *p) +mystique_ctrl_read_b(uint32_t addr, void *priv) { - mystique_t *mystique = (mystique_t *)p; - svga_t *svga = &mystique->svga; - uint8_t ret = 0xff; - int fifocount; - uint16_t addr_0x0f = 0; - uint16_t addr_0x03 = 0; - int rs2 = 0, rs3 = 0; + mystique_t *mystique = (mystique_t *) priv; + svga_t *svga = &mystique->svga; + uint8_t ret = 0xff; + int fifocount; + uint16_t addr_0x0f = 0; + uint16_t addr_0x03 = 0; + int rs2 = 0; + int rs3 = 0; - if ((mystique->type == MGA_2064W) && (addr & 0x3e00) == 0x3c00) - { - /*RAMDAC*/ - addr_0x0f = addr & 0x0f; - - if ((addr_0x0f & 3) == 0) - addr_0x03 = 0x3c8; - else if ((addr_0x0f & 3) == 1) - addr_0x03 = 0x3c9; - else if ((addr_0x0f & 3) == 2) - addr_0x03 = 0x3c6; - else if ((addr_0x0f & 3) == 3) - addr_0x03 = 0x3c7; - - if ((addr_0x0f >= 0x04) && (addr_0x0f <= 0x07)) { - rs2 = 1; - rs3 = 0; - } else if ((addr_0x0f >= 0x08) && (addr_0x0f <= 0x0b)) { - rs2 = 0; - rs3 = 1; - } else if ((addr_0x0f >= 0x0c) && (addr_0x0f <= 0x0f)) { - rs2 = 1; - rs3 = 1; - } - - ret = tvp3026_ramdac_in(addr_0x03, rs2, rs3, svga->ramdac, svga); - } else switch (addr & 0x3fff) { - case REG_FIFOSTATUS: - fifocount = FIFO_SIZE - FIFO_ENTRIES; - if (fifocount > 64) - fifocount = 64; - ret = fifocount; - break; - case REG_FIFOSTATUS+1: - if (FIFO_EMPTY) - ret |= 2; - else if (FIFO_ENTRIES >= 64) - ret |= 1; - break; - case REG_FIFOSTATUS+2: case REG_FIFOSTATUS+3: - ret = 0; - break; + if ((mystique->type == MGA_2064W) && (addr & 0x3e00) == 0x3c00) { + /*RAMDAC*/ + addr_0x0f = addr & 0x0f; - case REG_STATUS: - ret = mystique->status & 0xff; - if (svga->cgastat & 8) - ret |= REG_STATUS_VSYNCSTS; - break; - case REG_STATUS+1: - ret = (mystique->status >> 8) & 0xff; - break; - case REG_STATUS+2: - ret = (mystique->status >> 16) & 0xff; - if (mystique->busy || - ((mystique->blitter_submit_refcount + mystique->blitter_submit_dma_refcount) != mystique->blitter_complete_refcount) || - !FIFO_EMPTY) - ret |= (STATUS_DWGENGSTS >> 16); - break; - case REG_STATUS+3: - ret = (mystique->status >> 24) & 0xff; - break; + if ((addr_0x0f & 3) == 0) + addr_0x03 = 0x3c8; + else if ((addr_0x0f & 3) == 1) + addr_0x03 = 0x3c9; + else if ((addr_0x0f & 3) == 2) + addr_0x03 = 0x3c6; + else if ((addr_0x0f & 3) == 3) + addr_0x03 = 0x3c7; - case REG_IEN: - ret = mystique->ien & 0x64; - break; - case REG_IEN+1: case REG_IEN+2: case REG_IEN+3: - ret = 0; - break; + if ((addr_0x0f >= 0x04) && (addr_0x0f <= 0x07)) { + rs2 = 1; + rs3 = 0; + } else if ((addr_0x0f >= 0x08) && (addr_0x0f <= 0x0b)) { + rs2 = 0; + rs3 = 1; + } else if ((addr_0x0f >= 0x0c) && (addr_0x0f <= 0x0f)) { + rs2 = 1; + rs3 = 1; + } - case REG_OPMODE: - ret = mystique->dmamod << 2; - break; - case REG_OPMODE+1: - ret = mystique->dmadatasiz; - break; - case REG_OPMODE+2: - ret = mystique->dirdatasiz; - break; - case REG_OPMODE+3: - ret = 0; - break; - - case REG_PRIMADDRESS: case REG_PRIMADDRESS+1: case REG_PRIMADDRESS+2: case REG_PRIMADDRESS+3: - READ8(addr, mystique->dma.primaddress); - break; - case REG_PRIMEND: case REG_PRIMEND+1: case REG_PRIMEND+2: case REG_PRIMEND+3: - READ8(addr, mystique->dma.primend); - break; - - case REG_SECADDRESS: case REG_SECADDRESS+1: case REG_SECADDRESS+2: case REG_SECADDRESS+3: - READ8(addr, mystique->dma.secaddress); - break; - - case REG_VCOUNT: case REG_VCOUNT+1: case REG_VCOUNT+2: case REG_VCOUNT+3: - READ8(addr, svga->vc); - break; - - case REG_ATTR_IDX: - ret = svga_in(0x3c0, svga); - break; - case REG_ATTR_DATA: - ret = svga_in(0x3c1, svga); - break; - - case REG_INSTS0: - ret = svga_in(0x3c2, svga); - break; - - case REG_SEQ_IDX: - ret = svga_in(0x3c4, svga); - break; - case REG_SEQ_DATA: - ret = svga_in(0x3c5, svga); - break; - - case REG_MISCREAD: - ret = svga_in(0x3cc, svga); - break; - - case REG_GCTL_IDX: - ret = mystique_in(0x3ce, mystique); - break; - case REG_GCTL_DATA: - ret = mystique_in(0x3cf, mystique); - break; - - case REG_CRTC_IDX: - ret = mystique_in(0x3d4, mystique); - break; - case REG_CRTC_DATA: - ret = mystique_in(0x3d5, mystique); - break; - - case REG_INSTS1: - ret = mystique_in(0x3da, mystique); - break; - - case REG_CRTCEXT_IDX: - ret = mystique_in(0x3de, mystique); - break; - case REG_CRTCEXT_DATA: - ret = mystique_in(0x3df, mystique); - break; - - case REG_PALWTADD: - ret = svga_in(0x3c8, svga); - break; - case REG_PALDATA: - ret = svga_in(0x3c9, svga); - break; - case REG_PIXRDMSK: - ret = svga_in(0x3c6, svga); - break; - case REG_PALRDADD: - ret = svga_in(0x3c7, svga); - break; - - case REG_X_DATAREG: - ret = mystique_read_xreg(mystique, mystique->xreg_idx); - break; - - case 0x1c40: case 0x1c41: case 0x1c42: case 0x1c43: - case 0x1d44: case 0x1d45: case 0x1d46: case 0x1d47: - case 0x1e50: case 0x1e51: case 0x1e52: case 0x1e53: - case REG_ICLEAR: case REG_ICLEAR+1: case REG_ICLEAR+2: case REG_ICLEAR+3: - case 0x2c30: case 0x2c31: case 0x2c32: case 0x2c33: - case 0x3e08: - break; - - case 0x3c08: case 0x3c09: case 0x3c0b: + ret = tvp3026_ramdac_in(addr_0x03, rs2, rs3, svga->ramdac, svga); + } else + switch (addr & 0x3fff) { + case REG_FIFOSTATUS: + fifocount = FIFO_SIZE - FIFO_ENTRIES; + if (fifocount > 64) + fifocount = 64; + ret = fifocount; + break; + case REG_FIFOSTATUS + 1: + if (FIFO_EMPTY) + ret |= 2; + else if (FIFO_ENTRIES >= 64) + ret |= 1; + break; + case REG_FIFOSTATUS + 2: + case REG_FIFOSTATUS + 3: + ret = 0; break; - - default: - if ((addr & 0x3fff) >= 0x2c00 && (addr & 0x3fff) < 0x2c40) - break; - if ((addr & 0x3fff) >= 0x3e00) - break; - break; - } + case REG_STATUS: + ret = mystique->status & 0xff; + if (svga->cgastat & 8) + ret |= REG_STATUS_VSYNCSTS; + break; + case REG_STATUS + 1: + ret = (mystique->status >> 8) & 0xff; + break; + case REG_STATUS + 2: + ret = (mystique->status >> 16) & 0xff; + if (mystique->busy || ((mystique->blitter_submit_refcount + mystique->blitter_submit_dma_refcount) != mystique->blitter_complete_refcount) || !FIFO_EMPTY) + ret |= (STATUS_DWGENGSTS >> 16); + break; + case REG_STATUS + 3: + ret = (mystique->status >> 24) & 0xff; + break; + + case REG_IEN: + ret = mystique->ien & 0x64; + break; + case REG_IEN + 1: + case REG_IEN + 2: + case REG_IEN + 3: + ret = 0; + break; + + case REG_OPMODE: + ret = mystique->dmamod << 2; + break; + case REG_OPMODE + 1: + ret = mystique->dmadatasiz; + break; + case REG_OPMODE + 2: + ret = mystique->dirdatasiz; + break; + case REG_OPMODE + 3: + ret = 0; + break; + + case REG_PRIMADDRESS: + case REG_PRIMADDRESS + 1: + case REG_PRIMADDRESS + 2: + case REG_PRIMADDRESS + 3: + READ8(addr, mystique->dma.primaddress); + break; + case REG_PRIMEND: + case REG_PRIMEND + 1: + case REG_PRIMEND + 2: + case REG_PRIMEND + 3: + READ8(addr, mystique->dma.primend); + break; + + case REG_SECADDRESS: + case REG_SECADDRESS + 1: + case REG_SECADDRESS + 2: + case REG_SECADDRESS + 3: + READ8(addr, mystique->dma.secaddress); + break; + + case REG_VCOUNT: + case REG_VCOUNT + 1: + case REG_VCOUNT + 2: + case REG_VCOUNT + 3: + READ8(addr, svga->vc); + break; + + case REG_ATTR_IDX: + ret = svga_in(0x3c0, svga); + break; + case REG_ATTR_DATA: + ret = svga_in(0x3c1, svga); + break; + + case REG_INSTS0: + ret = svga_in(0x3c2, svga); + break; + + case REG_SEQ_IDX: + ret = svga_in(0x3c4, svga); + break; + case REG_SEQ_DATA: + ret = svga_in(0x3c5, svga); + break; + + case REG_MISCREAD: + ret = svga_in(0x3cc, svga); + break; + + case REG_GCTL_IDX: + ret = mystique_in(0x3ce, mystique); + break; + case REG_GCTL_DATA: + ret = mystique_in(0x3cf, mystique); + break; + + case REG_CRTC_IDX: + ret = mystique_in(0x3d4, mystique); + break; + case REG_CRTC_DATA: + ret = mystique_in(0x3d5, mystique); + break; + + case REG_INSTS1: + ret = mystique_in(0x3da, mystique); + break; + + case REG_CRTCEXT_IDX: + ret = mystique_in(0x3de, mystique); + break; + case REG_CRTCEXT_DATA: + ret = mystique_in(0x3df, mystique); + break; + + case REG_PALWTADD: + ret = svga_in(0x3c8, svga); + break; + case REG_PALDATA: + ret = svga_in(0x3c9, svga); + break; + case REG_PIXRDMSK: + ret = svga_in(0x3c6, svga); + break; + case REG_PALRDADD: + ret = svga_in(0x3c7, svga); + break; + + case REG_X_DATAREG: + ret = mystique_read_xreg(mystique, mystique->xreg_idx); + break; + + case 0x1c40: + case 0x1c41: + case 0x1c42: + case 0x1c43: + case 0x1d44: + case 0x1d45: + case 0x1d46: + case 0x1d47: + case 0x1e50: + case 0x1e51: + case 0x1e52: + case 0x1e53: + case REG_ICLEAR: + case REG_ICLEAR + 1: + case REG_ICLEAR + 2: + case REG_ICLEAR + 3: + case 0x2c30: + case 0x2c31: + case 0x2c32: + case 0x2c33: + case 0x3e08: + break; + + case 0x3c08: + case 0x3c09: + case 0x3c0b: + break; + + default: + if ((addr & 0x3fff) >= 0x2c00 && (addr & 0x3fff) < 0x2c40) + break; + if ((addr & 0x3fff) >= 0x3e00) + break; + break; + } return ret; } - static void -mystique_accel_ctrl_write_b(uint32_t addr, uint8_t val, void *p) +mystique_accel_ctrl_write_b(uint32_t addr, uint8_t val, void *priv) { - mystique_t *mystique = (mystique_t *)p; - int start_blit = 0; - int x; + mystique_t *mystique = (mystique_t *) priv; + int start_blit = 0; if ((addr & 0x300) == 0x100) { - addr &= ~0x100; - start_blit = 1; + addr &= ~0x100; + start_blit = 1; } switch (addr & 0x3fff) { - case REG_MACCESS: case REG_MACCESS+1: case REG_MACCESS+2: case REG_MACCESS+3: - WRITE8(addr, mystique->maccess, val); - mystique->dwgreg.dither = mystique->maccess >> 30; - break; + case REG_MACCESS: + case REG_MACCESS + 1: + case REG_MACCESS + 2: + case REG_MACCESS + 3: + WRITE8(addr, mystique->maccess, val); + mystique->dwgreg.dither = mystique->maccess >> 30; + break; - case REG_MCTLWTST: case REG_MCTLWTST+1: case REG_MCTLWTST+2: case REG_MCTLWTST+3: - WRITE8(addr, mystique->mctlwtst, val); - break; + case REG_MCTLWTST: + case REG_MCTLWTST + 1: + case REG_MCTLWTST + 2: + case REG_MCTLWTST + 3: + WRITE8(addr, mystique->mctlwtst, val); + break; - case REG_PAT0: case REG_PAT0+1: case REG_PAT0+2: case REG_PAT0+3: - case REG_PAT1: case REG_PAT1+1: case REG_PAT1+2: case REG_PAT1+3: - for (x = 0; x < 8; x++) - mystique->dwgreg.pattern[addr & 7][x] = val & (1 << (7-x)); - break; + case REG_PAT0: + case REG_PAT0 + 1: + case REG_PAT0 + 2: + case REG_PAT0 + 3: + case REG_PAT1: + case REG_PAT1 + 1: + case REG_PAT1 + 2: + case REG_PAT1 + 3: + for (uint8_t x = 0; x < 8; x++) + mystique->dwgreg.pattern[addr & 7][x] = mystique->dwgreg.pattern[addr & 7][x + 8] = val & (1 << (7 - x)); + break; - case REG_XYSTRT: case REG_XYSTRT+1: - WRITE8(addr&1, mystique->dwgreg.ar[5], val); - if (mystique->dwgreg.ar[5] & 0x8000) - mystique->dwgreg.ar[5] |= 0xffff8000; - else - mystique->dwgreg.ar[5] &= ~0xffff8000; - WRITE8(addr&1, mystique->dwgreg.xdst, val); - break; - case REG_XYSTRT+2: case REG_XYSTRT+3: - WRITE8(addr & 1, mystique->dwgreg.ar[6], val); - if (mystique->dwgreg.ar[6] & 0x8000) - mystique->dwgreg.ar[6] |= 0xffff8000; - else - mystique->dwgreg.ar[6] &= ~0xffff8000; - WRITE8(addr & 1, mystique->dwgreg.ydst, val); - mystique->dwgreg.ydst_lin = ((int32_t)(int16_t)mystique->dwgreg.ydst * (mystique->dwgreg.pitch & PITCH_MASK)) + mystique->dwgreg.ydstorg; - break; + case REG_XYSTRT: + case REG_XYSTRT + 1: + WRITE8(addr & 1, mystique->dwgreg.ar[5], val); + if (mystique->dwgreg.ar[5] & 0x8000) + mystique->dwgreg.ar[5] |= 0xffff8000; + else + mystique->dwgreg.ar[5] &= ~0xffff8000; + WRITE8(addr & 1, mystique->dwgreg.xdst, val); + break; + case REG_XYSTRT + 2: + case REG_XYSTRT + 3: + WRITE8(addr & 1, mystique->dwgreg.ar[6], val); + if (mystique->dwgreg.ar[6] & 0x8000) + mystique->dwgreg.ar[6] |= 0xffff8000; + else + mystique->dwgreg.ar[6] &= ~0xffff8000; + WRITE8(addr & 1, mystique->dwgreg.ydst, val); + mystique->dwgreg.ydst_lin = ((int32_t) (int16_t) mystique->dwgreg.ydst * (mystique->dwgreg.pitch & PITCH_MASK)) + mystique->dwgreg.ydstorg; + break; - case REG_XYEND: case REG_XYEND+1: - WRITE8(addr&1, mystique->dwgreg.ar[0], val); - if (mystique->dwgreg.ar[0] & 0x8000) - mystique->dwgreg.ar[0] |= 0xffff8000; - else - mystique->dwgreg.ar[0] &= ~0xffff8000; - break; - case REG_XYEND+2: case REG_XYEND+3: - WRITE8(addr & 1, mystique->dwgreg.ar[2], val); - if (mystique->dwgreg.ar[2] & 0x8000) - mystique->dwgreg.ar[2] |= 0xffff8000; - else - mystique->dwgreg.ar[2] &= ~0xffff8000; - break; + case REG_XYEND: + case REG_XYEND + 1: + WRITE8(addr & 1, mystique->dwgreg.ar[0], val); + if (mystique->dwgreg.ar[0] & 0x8000) + mystique->dwgreg.ar[0] |= 0xffff8000; + else + mystique->dwgreg.ar[0] &= ~0xffff8000; + break; + case REG_XYEND + 2: + case REG_XYEND + 3: + WRITE8(addr & 1, mystique->dwgreg.ar[2], val); + if (mystique->dwgreg.ar[2] & 0x8000) + mystique->dwgreg.ar[2] |= 0xffff8000; + else + mystique->dwgreg.ar[2] &= ~0xffff8000; + break; - case REG_SGN: - mystique->dwgreg.sgn.sdydxl = val & SGN_SDYDXL; - mystique->dwgreg.sgn.scanleft = val & SGN_SCANLEFT; - mystique->dwgreg.sgn.sdxl = val & SGN_SDXL; - mystique->dwgreg.sgn.sdy = val & SGN_SDY; - mystique->dwgreg.sgn.sdxr = val & SGN_SDXR; - break; - case REG_SGN+1: case REG_SGN+2: case REG_SGN+3: - break; + case REG_SGN: + mystique->dwgreg.sgn.sdydxl = val & SGN_SDYDXL; + mystique->dwgreg.sgn.scanleft = val & SGN_SCANLEFT; + mystique->dwgreg.sgn.sdxl = val & SGN_SDXL; + mystique->dwgreg.sgn.sdy = val & SGN_SDY; + mystique->dwgreg.sgn.sdxr = val & SGN_SDXR; + break; + case REG_SGN + 1: + case REG_SGN + 2: + case REG_SGN + 3: + break; - case REG_LEN: case REG_LEN+1: - WRITE8(addr, mystique->dwgreg.length, val); - break; - case REG_LEN+2: - break; - case REG_LEN+3: - mystique->dwgreg.beta = val >> 4; - if (!mystique->dwgreg.beta) - mystique->dwgreg.beta = 16; - break; + case REG_LEN: + case REG_LEN + 1: + WRITE8(addr, mystique->dwgreg.length, val); + break; + case REG_LEN + 2: + break; + case REG_LEN + 3: + mystique->dwgreg.beta = val >> 4; + if (!mystique->dwgreg.beta) + mystique->dwgreg.beta = 16; + break; - case REG_CXBNDRY: case REG_CXBNDRY+1: - WRITE8(addr, mystique->dwgreg.cxleft, val); - break; - case REG_CXBNDRY+2: case REG_CXBNDRY+3: - WRITE8(addr & 1, mystique->dwgreg.cxright, val); - break; - case REG_FXBNDRY: case REG_FXBNDRY+1: - WRITE8(addr, mystique->dwgreg.fxleft, val); - break; - case REG_FXBNDRY+2: case REG_FXBNDRY+3: - WRITE8(addr & 1, mystique->dwgreg.fxright, val); - break; + case REG_CXBNDRY: + case REG_CXBNDRY + 1: + WRITE8(addr, mystique->dwgreg.cxleft, val); + break; + case REG_CXBNDRY + 2: + case REG_CXBNDRY + 3: + WRITE8(addr & 1, mystique->dwgreg.cxright, val); + break; + case REG_FXBNDRY: + case REG_FXBNDRY + 1: + WRITE8(addr, mystique->dwgreg.fxleft, val); + break; + case REG_FXBNDRY + 2: + case REG_FXBNDRY + 3: + WRITE8(addr & 1, mystique->dwgreg.fxright, val); + break; - case REG_YDSTLEN: case REG_YDSTLEN+1: - WRITE8(addr, mystique->dwgreg.length, val); - /* pclog("Write YDSTLEN+%i %i\n", addr&1, mystique->dwgreg.length); */ - break; - case REG_YDSTLEN+2: - mystique->dwgreg.ydst = (mystique->dwgreg.ydst & ~0xff) | val; - if (mystique->dwgreg.pitch & PITCH_YLIN) - mystique->dwgreg.ydst_lin = (mystique->dwgreg.ydst << 5) + mystique->dwgreg.ydstorg; - else { - mystique->dwgreg.ydst_lin = ((int32_t)(int16_t)mystique->dwgreg.ydst * (mystique->dwgreg.pitch & PITCH_MASK)) + mystique->dwgreg.ydstorg; - mystique->dwgreg.selline = val & 7; - } - break; - case REG_YDSTLEN+3: - mystique->dwgreg.ydst = (mystique->dwgreg.ydst & 0xff) | (((int32_t)(int8_t)val) << 8); - if (mystique->dwgreg.pitch & PITCH_YLIN) - mystique->dwgreg.ydst_lin = (mystique->dwgreg.ydst << 5) + mystique->dwgreg.ydstorg; - else - mystique->dwgreg.ydst_lin = ((int32_t)(int16_t)mystique->dwgreg.ydst * (mystique->dwgreg.pitch & PITCH_MASK)) + mystique->dwgreg.ydstorg; - break; + case REG_YDSTLEN: + case REG_YDSTLEN + 1: + WRITE8(addr, mystique->dwgreg.length, val); +#if 0 + pclog("Write YDSTLEN+%i %i\n", addr&1, mystique->dwgreg.length); +#endif + break; + case REG_YDSTLEN + 2: + mystique->dwgreg.ydst = (mystique->dwgreg.ydst & ~0xff) | val; + if (mystique->dwgreg.pitch & PITCH_YLIN) + mystique->dwgreg.ydst_lin = (mystique->dwgreg.ydst << 5) + mystique->dwgreg.ydstorg; + else { + mystique->dwgreg.ydst_lin = ((int32_t) (int16_t) mystique->dwgreg.ydst * (mystique->dwgreg.pitch & PITCH_MASK)) + mystique->dwgreg.ydstorg; + mystique->dwgreg.selline = val & 7; + } + break; + case REG_YDSTLEN + 3: + mystique->dwgreg.ydst = (mystique->dwgreg.ydst & 0xff) | (((int32_t) (int8_t) val) << 8); + if (mystique->dwgreg.pitch & PITCH_YLIN) + mystique->dwgreg.ydst_lin = (mystique->dwgreg.ydst << 5) + mystique->dwgreg.ydstorg; + else + mystique->dwgreg.ydst_lin = ((int32_t) (int16_t) mystique->dwgreg.ydst * (mystique->dwgreg.pitch & PITCH_MASK)) + mystique->dwgreg.ydstorg; + break; - case REG_XDST: case REG_XDST+1: - WRITE8(addr & 1, mystique->dwgreg.xdst, val); - break; - case REG_XDST+2: case REG_XDST+3: - break; + case REG_XDST: + case REG_XDST + 1: + WRITE8(addr & 1, mystique->dwgreg.xdst, val); + break; + case REG_XDST + 2: + case REG_XDST + 3: + break; - case REG_YDSTORG: case REG_YDSTORG+1: case REG_YDSTORG+2: case REG_YDSTORG+3: - WRITE8(addr, mystique->dwgreg.ydstorg, val); - mystique->dwgreg.z_base = mystique->dwgreg.ydstorg*2 + mystique->dwgreg.zorg; - break; - case REG_YTOP: case REG_YTOP+1: case REG_YTOP+2: case REG_YTOP+3: - WRITE8(addr, mystique->dwgreg.ytop, val); - break; - case REG_YBOT: case REG_YBOT+1: case REG_YBOT+2: case REG_YBOT+3: - WRITE8(addr, mystique->dwgreg.ybot, val); - break; + case REG_YDSTORG: + case REG_YDSTORG + 1: + case REG_YDSTORG + 2: + case REG_YDSTORG + 3: + WRITE8(addr, mystique->dwgreg.ydstorg, val); + mystique->dwgreg.z_base = mystique->dwgreg.ydstorg * 2 + mystique->dwgreg.zorg; + break; + case REG_YTOP: + case REG_YTOP + 1: + case REG_YTOP + 2: + case REG_YTOP + 3: + WRITE8(addr, mystique->dwgreg.ytop, val); + break; + case REG_YBOT: + case REG_YBOT + 1: + case REG_YBOT + 2: + case REG_YBOT + 3: + WRITE8(addr, mystique->dwgreg.ybot, val); + break; - case REG_CXLEFT: case REG_CXLEFT+1: - WRITE8(addr, mystique->dwgreg.cxleft, val); - break; - case REG_CXLEFT+2: case REG_CXLEFT+3: - break; - case REG_CXRIGHT: case REG_CXRIGHT+1: - WRITE8(addr, mystique->dwgreg.cxright, val); - break; - case REG_CXRIGHT+2: case REG_CXRIGHT+3: - break; + case REG_CXLEFT: + case REG_CXLEFT + 1: + WRITE8(addr, mystique->dwgreg.cxleft, val); + break; + case REG_CXLEFT + 2: + case REG_CXLEFT + 3: + break; + case REG_CXRIGHT: + case REG_CXRIGHT + 1: + WRITE8(addr, mystique->dwgreg.cxright, val); + break; + case REG_CXRIGHT + 2: + case REG_CXRIGHT + 3: + break; - case REG_FXLEFT: case REG_FXLEFT+1: - WRITE8(addr, mystique->dwgreg.fxleft, val); - break; - case REG_FXLEFT+2: case REG_FXLEFT+3: - break; - case REG_FXRIGHT: case REG_FXRIGHT+1: - WRITE8(addr, mystique->dwgreg.fxright, val); - break; - case REG_FXRIGHT+2: case REG_FXRIGHT+3: - break; + case REG_FXLEFT: + case REG_FXLEFT + 1: + WRITE8(addr, mystique->dwgreg.fxleft, val); + break; + case REG_FXLEFT + 2: + case REG_FXLEFT + 3: + break; + case REG_FXRIGHT: + case REG_FXRIGHT + 1: + WRITE8(addr, mystique->dwgreg.fxright, val); + break; + case REG_FXRIGHT + 2: + case REG_FXRIGHT + 3: + break; - case REG_SECADDRESS: case REG_SECADDRESS+1: case REG_SECADDRESS+2: case REG_SECADDRESS+3: - WRITE8(addr, mystique->dma.secaddress, val); - mystique->dma.sec_state = 0; - break; + case REG_SECADDRESS: + case REG_SECADDRESS + 1: + case REG_SECADDRESS + 2: + case REG_SECADDRESS + 3: + WRITE8(addr, mystique->dma.secaddress, val); + mystique->dma.sec_state = 0; + break; - case REG_TMR0: case REG_TMR0+1: case REG_TMR0+2: case REG_TMR0+3: - WRITE8(addr, mystique->dwgreg.tmr[0], val); - break; - case REG_TMR1: case REG_TMR1+1: case REG_TMR1+2: case REG_TMR1+3: - WRITE8(addr, mystique->dwgreg.tmr[1], val); - break; - case REG_TMR2: case REG_TMR2+1: case REG_TMR2+2: case REG_TMR2+3: - WRITE8(addr, mystique->dwgreg.tmr[2], val); - break; - case REG_TMR3: case REG_TMR3+1: case REG_TMR3+2: case REG_TMR3+3: - WRITE8(addr, mystique->dwgreg.tmr[3], val); - break; - case REG_TMR4: case REG_TMR4+1: case REG_TMR4+2: case REG_TMR4+3: - WRITE8(addr, mystique->dwgreg.tmr[4], val); - break; - case REG_TMR5: case REG_TMR5+1: case REG_TMR5+2: case REG_TMR5+3: - WRITE8(addr, mystique->dwgreg.tmr[5], val); - break; - case REG_TMR6: case REG_TMR6+1: case REG_TMR6+2: case REG_TMR6+3: - WRITE8(addr, mystique->dwgreg.tmr[6], val); - break; - case REG_TMR7: case REG_TMR7+1: case REG_TMR7+2: case REG_TMR7+3: - WRITE8(addr, mystique->dwgreg.tmr[7], val); - break; - case REG_TMR8: case REG_TMR8+1: case REG_TMR8+2: case REG_TMR8+3: - WRITE8(addr, mystique->dwgreg.tmr[8], val); - break; + case REG_TMR0: + case REG_TMR0 + 1: + case REG_TMR0 + 2: + case REG_TMR0 + 3: + WRITE8(addr, mystique->dwgreg.tmr[0], val); + break; + case REG_TMR1: + case REG_TMR1 + 1: + case REG_TMR1 + 2: + case REG_TMR1 + 3: + WRITE8(addr, mystique->dwgreg.tmr[1], val); + break; + case REG_TMR2: + case REG_TMR2 + 1: + case REG_TMR2 + 2: + case REG_TMR2 + 3: + WRITE8(addr, mystique->dwgreg.tmr[2], val); + break; + case REG_TMR3: + case REG_TMR3 + 1: + case REG_TMR3 + 2: + case REG_TMR3 + 3: + WRITE8(addr, mystique->dwgreg.tmr[3], val); + break; + case REG_TMR4: + case REG_TMR4 + 1: + case REG_TMR4 + 2: + case REG_TMR4 + 3: + WRITE8(addr, mystique->dwgreg.tmr[4], val); + break; + case REG_TMR5: + case REG_TMR5 + 1: + case REG_TMR5 + 2: + case REG_TMR5 + 3: + WRITE8(addr, mystique->dwgreg.tmr[5], val); + break; + case REG_TMR6: + case REG_TMR6 + 1: + case REG_TMR6 + 2: + case REG_TMR6 + 3: + WRITE8(addr, mystique->dwgreg.tmr[6], val); + break; + case REG_TMR7: + case REG_TMR7 + 1: + case REG_TMR7 + 2: + case REG_TMR7 + 3: + WRITE8(addr, mystique->dwgreg.tmr[7], val); + break; + case REG_TMR8: + case REG_TMR8 + 1: + case REG_TMR8 + 2: + case REG_TMR8 + 3: + WRITE8(addr, mystique->dwgreg.tmr[8], val); + break; - case REG_TEXORG: case REG_TEXORG+1: case REG_TEXORG+2: case REG_TEXORG+3: - WRITE8(addr, mystique->dwgreg.texorg, val); - break; - case REG_TEXWIDTH: case REG_TEXWIDTH+1: case REG_TEXWIDTH+2: case REG_TEXWIDTH+3: - WRITE8(addr, mystique->dwgreg.texwidth, val); - break; - case REG_TEXHEIGHT: case REG_TEXHEIGHT+1: case REG_TEXHEIGHT+2: case REG_TEXHEIGHT+3: - WRITE8(addr, mystique->dwgreg.texheight, val); - break; - case REG_TEXCTL: case REG_TEXCTL+1: case REG_TEXCTL+2: case REG_TEXCTL+3: - WRITE8(addr, mystique->dwgreg.texctl, val); - mystique->dwgreg.ta_key = (mystique->dwgreg.texctl & TEXCTL_TAKEY) ? 1 : 0; - mystique->dwgreg.ta_mask = (mystique->dwgreg.texctl & TEXCTL_TAMASK) ? 1 : 0; - break; - case REG_TEXTRANS: case REG_TEXTRANS+1: case REG_TEXTRANS+2: case REG_TEXTRANS+3: - WRITE8(addr, mystique->dwgreg.textrans, val); - break; + case REG_TEXORG: + case REG_TEXORG + 1: + case REG_TEXORG + 2: + case REG_TEXORG + 3: + WRITE8(addr, mystique->dwgreg.texorg, val); + break; + case REG_TEXWIDTH: + case REG_TEXWIDTH + 1: + case REG_TEXWIDTH + 2: + case REG_TEXWIDTH + 3: + WRITE8(addr, mystique->dwgreg.texwidth, val); + break; + case REG_TEXHEIGHT: + case REG_TEXHEIGHT + 1: + case REG_TEXHEIGHT + 2: + case REG_TEXHEIGHT + 3: + WRITE8(addr, mystique->dwgreg.texheight, val); + break; + case REG_TEXCTL: + case REG_TEXCTL + 1: + case REG_TEXCTL + 2: + case REG_TEXCTL + 3: + WRITE8(addr, mystique->dwgreg.texctl, val); + mystique->dwgreg.ta_key = (mystique->dwgreg.texctl & TEXCTL_TAKEY) ? 1 : 0; + mystique->dwgreg.ta_mask = (mystique->dwgreg.texctl & TEXCTL_TAMASK) ? 1 : 0; + break; + case REG_TEXTRANS: + case REG_TEXTRANS + 1: + case REG_TEXTRANS + 2: + case REG_TEXTRANS + 3: + WRITE8(addr, mystique->dwgreg.textrans, val); + break; - case 0x1c18: case 0x1c19: case 0x1c1a: case 0x1c1b: - case 0x1c28: case 0x1c29: case 0x1c2a: case 0x1c2b: - case 0x1c2c: case 0x1c2d: case 0x1c2e: case 0x1c2f: - case 0x1cc4: case 0x1cc5: case 0x1cc6: case 0x1cc7: - case 0x1cd4: case 0x1cd5: case 0x1cd6: case 0x1cd7: - case 0x1ce4: case 0x1ce5: case 0x1ce6: case 0x1ce7: - case 0x1cf4: case 0x1cf5: case 0x1cf6: case 0x1cf7: - break; + case 0x1c18: + case 0x1c19: + case 0x1c1a: + case 0x1c1b: + case 0x1c28: + case 0x1c29: + case 0x1c2a: + case 0x1c2b: + case 0x1c2c: + case 0x1c2d: + case 0x1c2e: + case 0x1c2f: + case 0x1cc4: + case 0x1cc5: + case 0x1cc6: + case 0x1cc7: + case 0x1cd4: + case 0x1cd5: + case 0x1cd6: + case 0x1cd7: + case 0x1ce4: + case 0x1ce5: + case 0x1ce6: + case 0x1ce7: + case 0x1cf4: + case 0x1cf5: + case 0x1cf6: + case 0x1cf7: + break; - case REG_OPMODE: - mystique->dwgreg.dmamod = (val >> 2) & 3; - mystique->dma.iload_state = 0; - break; + case REG_OPMODE: + mystique->dwgreg.dmamod = (val >> 2) & 3; + mystique->dma.iload_state = 0; + break; - default: - if ((addr & 0x3fff) >= 0x2c4c && (addr & 0x3fff) <= 0x2cff) - break; - break; + default: + if ((addr & 0x3fff) >= 0x2c4c && (addr & 0x3fff) <= 0x2cff) + break; + break; } if (start_blit) - mystique_start_blit(mystique); + mystique_start_blit(mystique); } - static void -mystique_ctrl_write_b(uint32_t addr, uint8_t val, void *p) +mystique_ctrl_write_b(uint32_t addr, uint8_t val, void *priv) { - mystique_t *mystique = (mystique_t *)p; - svga_t *svga = &mystique->svga; - uint16_t addr_0x0f = 0; - uint16_t addr_0x03 = 0; - int rs2 = 0, rs3 = 0; + mystique_t *mystique = (mystique_t *) priv; + svga_t *svga = &mystique->svga; + uint16_t addr_0x0f = 0; + uint16_t addr_0x03 = 0; + int rs2 = 0; + int rs3 = 0; - if ((mystique->type == MGA_2064W) && (addr & 0x3e00) == 0x3c00) - { - /*RAMDAC*/ - addr_0x0f = addr & 0x0f; - - if ((addr & 3) == 0) - addr_0x03 = 0x3c8; - else if ((addr & 3) == 1) - addr_0x03 = 0x3c9; - else if ((addr & 3) == 2) - addr_0x03 = 0x3c6; - else if ((addr & 3) == 3) - addr_0x03 = 0x3c7; - - if ((addr_0x0f >= 0x04) && (addr_0x0f <= 0x07)) { - rs2 = 1; - rs3 = 0; - } else if ((addr_0x0f >= 0x08) && (addr_0x0f <= 0x0b)) { - rs2 = 0; - rs3 = 1; - } else if ((addr_0x0f >= 0x0c) && (addr_0x0f <= 0x0f)) { - rs2 = 1; - rs3 = 1; - } - - tvp3026_ramdac_out(addr_0x03, rs2, rs3, val, svga->ramdac, svga); - return; - } + if ((mystique->type == MGA_2064W) && (addr & 0x3e00) == 0x3c00) { + /*RAMDAC*/ + addr_0x0f = addr & 0x0f; + + if ((addr & 3) == 0) + addr_0x03 = 0x3c8; + else if ((addr & 3) == 1) + addr_0x03 = 0x3c9; + else if ((addr & 3) == 2) + addr_0x03 = 0x3c6; + else if ((addr & 3) == 3) + addr_0x03 = 0x3c7; + + if ((addr_0x0f >= 0x04) && (addr_0x0f <= 0x07)) { + rs2 = 1; + rs3 = 0; + } else if ((addr_0x0f >= 0x08) && (addr_0x0f <= 0x0b)) { + rs2 = 0; + rs3 = 1; + } else if ((addr_0x0f >= 0x0c) && (addr_0x0f <= 0x0f)) { + rs2 = 1; + rs3 = 1; + } + + tvp3026_ramdac_out(addr_0x03, rs2, rs3, val, svga->ramdac, svga); + return; + } if ((addr & 0x3fff) < 0x1c00) { - mystique_iload_write_b(addr, val, p); - return; + mystique_iload_write_b(addr, val, priv); + return; } if ((addr & 0x3e00) == 0x1c00 || (addr & 0x3e00) == 0x2c00) { - if ((addr & 0x300) == 0x100) - mystique->blitter_submit_refcount++; - mystique_queue(mystique, addr & 0x3fff, val, FIFO_WRITE_CTRL_BYTE); - return; + if ((addr & 0x300) == 0x100) + mystique->blitter_submit_refcount++; + mystique_queue(mystique, addr & 0x3fff, val, FIFO_WRITE_CTRL_BYTE); + return; } switch (addr & 0x3fff) { - case REG_ICLEAR: - if (val & ICLEAR_SOFTRAPICLR) { - mystique->status &= ~STATUS_SOFTRAPEN; - mystique_update_irqs(mystique); - } - if (val & ICLEAR_VLINEICLR) { - mystique->status &= ~STATUS_VLINEPEN; - mystique_update_irqs(mystique); - } - break; - case REG_ICLEAR+1: case REG_ICLEAR+2: case REG_ICLEAR+3: - break; - - case REG_IEN: - mystique->ien = val & 0x65; - break; - case REG_IEN+1: case REG_IEN+2: case REG_IEN+3: - break; - - case REG_OPMODE: - thread_wait_mutex(mystique->dma.lock); - mystique->dma.state = DMA_STATE_IDLE; /* Interrupt DMA. */ - thread_release_mutex(mystique->dma.lock); - mystique->dmamod = (val >> 2) & 3; - mystique_queue(mystique, addr & 0x3fff, val, FIFO_WRITE_CTRL_BYTE); - break; - case REG_OPMODE+1: - mystique->dmadatasiz = val & 3; - break; - case REG_OPMODE+2: - mystique->dirdatasiz = val & 3; - break; - case REG_OPMODE+3: - break; - - case REG_PRIMADDRESS: case REG_PRIMADDRESS+1: case REG_PRIMADDRESS+2: case REG_PRIMADDRESS+3: - thread_wait_mutex(mystique->dma.lock); - WRITE8(addr, mystique->dma.primaddress, val); - mystique->dma.pri_state = 0; - thread_release_mutex(mystique->dma.lock); - break; - - case REG_DMAMAP: case REG_DMAMAP+0x1: case REG_DMAMAP+0x2: case REG_DMAMAP+0x3: - case REG_DMAMAP+0x4: case REG_DMAMAP+0x5: case REG_DMAMAP+0x6: case REG_DMAMAP+0x7: - case REG_DMAMAP+0x8: case REG_DMAMAP+0x9: case REG_DMAMAP+0xa: case REG_DMAMAP+0xb: - case REG_DMAMAP+0xc: case REG_DMAMAP+0xd: case REG_DMAMAP+0xe: case REG_DMAMAP+0xf: - mystique->dmamap[addr & 0xf] = val; - break; - - case REG_RST: case REG_RST+1: case REG_RST+2: case REG_RST+3: - wait_fifo_idle(mystique); - mystique->busy = 0; - mystique->blitter_submit_refcount = 0; - mystique->blitter_submit_dma_refcount = 0; - mystique->blitter_complete_refcount = 0; - mystique->dwgreg.iload_rem_count = 0; - mystique->status = STATUS_ENDPRDMASTS; - break; - - case REG_ATTR_IDX: - svga_out(0x3c0, val, svga); - break; - case REG_ATTR_DATA: - svga_out(0x3c1, val, svga); - break; - - case REG_MISC: - svga_out(0x3c2, val, svga); - break; - - case REG_SEQ_IDX: - svga_out(0x3c4, val, svga); - break; - case REG_SEQ_DATA: - svga_out(0x3c5, val, svga); - break; - - case REG_GCTL_IDX: - mystique_out(0x3ce, val, mystique); - break; - case REG_GCTL_DATA: - mystique_out(0x3cf, val, mystique); - break; - - case REG_CRTC_IDX: - mystique_out(0x3d4, val, mystique); - break; - case REG_CRTC_DATA: - mystique_out(0x3d5, val, mystique); - break; - - case REG_CRTCEXT_IDX: - mystique_out(0x3de, val, mystique); - break; - case REG_CRTCEXT_DATA: - mystique_out(0x3df, val, mystique); - break; - - case REG_CACHEFLUSH: - break; - - case REG_PALWTADD: - svga_out(0x3c8, val, svga); - mystique->xreg_idx = val; - break; - case REG_PALDATA: - svga_out(0x3c9, val, svga); - break; - case REG_PIXRDMSK: - svga_out(0x3c6, val, svga); - break; - case REG_PALRDADD: - svga_out(0x3c7, val, svga); - break; - - case REG_X_DATAREG: - mystique_write_xreg(mystique, mystique->xreg_idx, val); - break; - - case REG_CURPOSX: case REG_CURPOSX+1: - WRITE8(addr, mystique->cursor.pos_x, val); - svga->hwcursor.x = mystique->cursor.pos_x - 64; - break; - case REG_CURPOSY: case REG_CURPOSY+1: - WRITE8(addr & 1, mystique->cursor.pos_y, val); - svga->hwcursor.y = mystique->cursor.pos_y - 64; - break; - - case 0x1e50: case 0x1e51: case 0x1e52: case 0x1e53: - case 0x3c0b: case 0x3e02: case 0x3e08: - break; - - default: - if ((addr & 0x3fff) >= 0x2c4c && (addr & 0x3fff) <= 0x2cff) - break; - if ((addr & 0x3fff) >= 0x3e00) + case REG_ICLEAR: + if (val & ICLEAR_SOFTRAPICLR) { + mystique->status &= ~STATUS_SOFTRAPEN; + mystique_update_irqs(mystique); + } + if (val & ICLEAR_VLINEICLR) { + mystique->status &= ~STATUS_VLINEPEN; + mystique_update_irqs(mystique); + } + break; + case REG_ICLEAR + 1: + case REG_ICLEAR + 2: + case REG_ICLEAR + 3: + break; + + case REG_IEN: + mystique->ien = val & 0x65; + break; + case REG_IEN + 1: + case REG_IEN + 2: + case REG_IEN + 3: + break; + + case REG_OPMODE: + thread_wait_mutex(mystique->dma.lock); + mystique->dma.state = DMA_STATE_IDLE; /* Interrupt DMA. */ + thread_release_mutex(mystique->dma.lock); + mystique->dmamod = (val >> 2) & 3; + mystique_queue(mystique, addr & 0x3fff, val, FIFO_WRITE_CTRL_BYTE); + break; + case REG_OPMODE + 1: + mystique->dmadatasiz = val & 3; + break; + case REG_OPMODE + 2: + mystique->dirdatasiz = val & 3; + break; + case REG_OPMODE + 3: + break; + + case REG_PRIMADDRESS: + case REG_PRIMADDRESS + 1: + case REG_PRIMADDRESS + 2: + case REG_PRIMADDRESS + 3: + thread_wait_mutex(mystique->dma.lock); + WRITE8(addr, mystique->dma.primaddress, val); + mystique->dma.pri_state = 0; + thread_release_mutex(mystique->dma.lock); + break; + + case REG_DMAMAP: + case REG_DMAMAP + 0x1: + case REG_DMAMAP + 0x2: + case REG_DMAMAP + 0x3: + case REG_DMAMAP + 0x4: + case REG_DMAMAP + 0x5: + case REG_DMAMAP + 0x6: + case REG_DMAMAP + 0x7: + case REG_DMAMAP + 0x8: + case REG_DMAMAP + 0x9: + case REG_DMAMAP + 0xa: + case REG_DMAMAP + 0xb: + case REG_DMAMAP + 0xc: + case REG_DMAMAP + 0xd: + case REG_DMAMAP + 0xe: + case REG_DMAMAP + 0xf: + mystique->dmamap[addr & 0xf] = val; + break; + + case REG_RST: + case REG_RST + 1: + case REG_RST + 2: + case REG_RST + 3: + wait_fifo_idle(mystique); + mystique->busy = 0; + mystique->blitter_submit_refcount = 0; + mystique->blitter_submit_dma_refcount = 0; + mystique->blitter_complete_refcount = 0; + mystique->dwgreg.iload_rem_count = 0; + mystique->status = STATUS_ENDPRDMASTS; + break; + + case REG_ATTR_IDX: + svga_out(0x3c0, val, svga); + break; + case REG_ATTR_DATA: + svga_out(0x3c1, val, svga); + break; + + case REG_MISC: + svga_out(0x3c2, val, svga); + break; + + case REG_SEQ_IDX: + svga_out(0x3c4, val, svga); + break; + case REG_SEQ_DATA: + svga_out(0x3c5, val, svga); + break; + + case REG_GCTL_IDX: + mystique_out(0x3ce, val, mystique); + break; + case REG_GCTL_DATA: + mystique_out(0x3cf, val, mystique); + break; + + case REG_CRTC_IDX: + mystique_out(0x3d4, val, mystique); + break; + case REG_CRTC_DATA: + mystique_out(0x3d5, val, mystique); + break; + + case REG_CRTCEXT_IDX: + mystique_out(0x3de, val, mystique); + break; + case REG_CRTCEXT_DATA: + mystique_out(0x3df, val, mystique); + break; + + case REG_CACHEFLUSH: + break; + + case REG_PALWTADD: + svga_out(0x3c8, val, svga); + mystique->xreg_idx = val; + break; + case REG_PALDATA: + svga_out(0x3c9, val, svga); + break; + case REG_PIXRDMSK: + svga_out(0x3c6, val, svga); + break; + case REG_PALRDADD: + svga_out(0x3c7, val, svga); + break; + + case REG_X_DATAREG: + mystique_write_xreg(mystique, mystique->xreg_idx, val); + break; + + case REG_CURPOSX: + case REG_CURPOSX + 1: + WRITE8(addr, mystique->cursor.pos_x, val); + svga->hwcursor.x = mystique->cursor.pos_x - 64; + break; + case REG_CURPOSY: + case REG_CURPOSY + 1: + WRITE8(addr & 1, mystique->cursor.pos_y, val); + svga->hwcursor.y = mystique->cursor.pos_y - 64; + break; + + case 0x1e50: + case 0x1e51: + case 0x1e52: + case 0x1e53: + case 0x3c0b: + case 0x3e02: + case 0x3e08: + break; + + default: + if ((addr & 0x3fff) >= 0x2c4c && (addr & 0x3fff) <= 0x2cff) + break; + if ((addr & 0x3fff) >= 0x3e00) + break; break; - break; } } - static uint32_t -mystique_ctrl_read_l(uint32_t addr, void *p) +mystique_ctrl_read_l(uint32_t addr, void *priv) { uint32_t ret; if ((addr & 0x3fff) < 0x1c00) - return mystique_iload_read_l(addr, p); + return mystique_iload_read_l(addr, priv); - ret = mystique_ctrl_read_b(addr, p); - ret |= mystique_ctrl_read_b(addr+1, p) << 8; - ret |= mystique_ctrl_read_b(addr+2, p) << 16; - ret |= mystique_ctrl_read_b(addr+3, p) << 24; + ret = mystique_ctrl_read_b(addr, priv); + ret |= mystique_ctrl_read_b(addr + 1, priv) << 8; + ret |= mystique_ctrl_read_b(addr + 2, priv) << 16; + ret |= mystique_ctrl_read_b(addr + 3, priv) << 24; return ret; } - static void -mystique_accel_ctrl_write_l(uint32_t addr, uint32_t val, void *p) +mystique_accel_ctrl_write_l(uint32_t addr, uint32_t val, void *priv) { - mystique_t *mystique = (mystique_t *)p; - int start_blit = 0; + mystique_t *mystique = (mystique_t *) priv; + int start_blit = 0; if ((addr & 0x300) == 0x100) { - addr &= ~0x100; - start_blit = 1; + addr &= ~0x100; + start_blit = 1; } switch (addr & 0x3ffc) { - case REG_DWGCTL: - mystique->dwgreg.dwgctrl = val; + case REG_DWGCTL: + mystique->dwgreg.dwgctrl = val; - if (val & DWGCTRL_SOLID) { - int x, y; + if (val & DWGCTRL_SOLID) { + for (uint8_t y = 0; y < 8; y++) { + for (uint8_t x = 0; x < 16; x++) + mystique->dwgreg.pattern[y][x] = 1; + } + mystique->dwgreg.src[0] = 0xffffffff; + mystique->dwgreg.src[1] = 0xffffffff; + mystique->dwgreg.src[2] = 0xffffffff; + mystique->dwgreg.src[3] = 0xffffffff; + } + if (val & DWGCTRL_ARZERO) { + mystique->dwgreg.ar[0] = 0; + mystique->dwgreg.ar[1] = 0; + mystique->dwgreg.ar[2] = 0; + mystique->dwgreg.ar[4] = 0; + mystique->dwgreg.ar[5] = 0; + mystique->dwgreg.ar[6] = 0; + } + if (val & DWGCTRL_SGNZERO) { + mystique->dwgreg.sgn.sdydxl = 0; + mystique->dwgreg.sgn.scanleft = 0; + mystique->dwgreg.sgn.sdxl = 0; + mystique->dwgreg.sgn.sdy = 0; + mystique->dwgreg.sgn.sdxr = 0; + } + if (val & DWGCTRL_SHTZERO) { + mystique->dwgreg.funcnt = 0; + mystique->dwgreg.stylelen = 0; + mystique->dwgreg.xoff = 0; + mystique->dwgreg.yoff = 0; + } + break; - for (y = 0; y < 8; y++) { - for (x = 0; x < 8; x++) - mystique->dwgreg.pattern[y][x] = 1; - } - mystique->dwgreg.src[0] = 0xffffffff; - mystique->dwgreg.src[1] = 0xffffffff; - mystique->dwgreg.src[2] = 0xffffffff; - mystique->dwgreg.src[3] = 0xffffffff; - } - if (val & DWGCTRL_ARZERO) { - mystique->dwgreg.ar[0] = 0; - mystique->dwgreg.ar[1] = 0; - mystique->dwgreg.ar[2] = 0; - mystique->dwgreg.ar[4] = 0; - mystique->dwgreg.ar[5] = 0; - mystique->dwgreg.ar[6] = 0; - } - if (val & DWGCTRL_SGNZERO) { - mystique->dwgreg.sgn.sdydxl = 0; - mystique->dwgreg.sgn.scanleft = 0; - mystique->dwgreg.sgn.sdxl = 0; - mystique->dwgreg.sgn.sdy = 0; - mystique->dwgreg.sgn.sdxr = 0; - } - if (val & DWGCTRL_SHTZERO) { - mystique->dwgreg.funcnt = 0; - mystique->dwgreg.stylelen = 0; - mystique->dwgreg.xoff = 0; - mystique->dwgreg.yoff = 0; - } - break; + case REG_ZORG: + mystique->dwgreg.zorg = val; + mystique->dwgreg.z_base = mystique->dwgreg.ydstorg * 2 + mystique->dwgreg.zorg; + break; - case REG_ZORG: - mystique->dwgreg.zorg = val; - mystique->dwgreg.z_base = mystique->dwgreg.ydstorg*2 + mystique->dwgreg.zorg; - break; + case REG_PLNWT: + mystique->dwgreg.plnwt = val; + break; - case REG_PLNWT: - mystique->dwgreg.plnwt = val; - break; + case REG_SHIFT: + mystique->dwgreg.funcnt = val & 0xff; + mystique->dwgreg.xoff = val & 7; + mystique->dwgreg.yoff = (val >> 4) & 7; + mystique->dwgreg.stylelen = (val >> 16) & 0xff; + break; - case REG_SHIFT: - mystique->dwgreg.funcnt = val & 0xff; - mystique->dwgreg.xoff = val & 7; - mystique->dwgreg.yoff = (val >> 4) & 7; - mystique->dwgreg.stylelen = (val >> 16) & 0xff; - break; + case REG_PITCH: + mystique->dwgreg.pitch = val & 0xffff; + if (mystique->dwgreg.pitch & PITCH_YLIN) + mystique->dwgreg.ydst_lin = (mystique->dwgreg.ydst << 5) + mystique->dwgreg.ydstorg; + else + mystique->dwgreg.ydst_lin = ((int32_t) (int16_t) mystique->dwgreg.ydst * (mystique->dwgreg.pitch & PITCH_MASK)) + mystique->dwgreg.ydstorg; + break; - case REG_PITCH: - mystique->dwgreg.pitch = val & 0xffff; - if (mystique->dwgreg.pitch & PITCH_YLIN) - mystique->dwgreg.ydst_lin = (mystique->dwgreg.ydst << 5) + mystique->dwgreg.ydstorg; - else - mystique->dwgreg.ydst_lin = ((int32_t)(int16_t)mystique->dwgreg.ydst * (mystique->dwgreg.pitch & PITCH_MASK)) + mystique->dwgreg.ydstorg; - break; + case REG_YDST: + mystique->dwgreg.ydst = val & 0x3fffff; + if (mystique->dwgreg.pitch & PITCH_YLIN) { + mystique->dwgreg.ydst_lin = (mystique->dwgreg.ydst << 5) + mystique->dwgreg.ydstorg; + mystique->dwgreg.selline = val >> 29; + } else { + mystique->dwgreg.ydst_lin = ((int32_t) (int16_t) mystique->dwgreg.ydst * (mystique->dwgreg.pitch & PITCH_MASK)) + mystique->dwgreg.ydstorg; + mystique->dwgreg.selline = val & 7; + } + break; + case REG_BCOL: + mystique->dwgreg.bcol = val; + break; + case REG_FCOL: + mystique->dwgreg.fcol = val; + break; - case REG_YDST: - mystique->dwgreg.ydst = val & 0x3fffff; - if (mystique->dwgreg.pitch & PITCH_YLIN) { - mystique->dwgreg.ydst_lin = (mystique->dwgreg.ydst << 5) + mystique->dwgreg.ydstorg; - mystique->dwgreg.selline = val >> 29; - } else { - mystique->dwgreg.ydst_lin = ((int32_t)(int16_t)mystique->dwgreg.ydst * (mystique->dwgreg.pitch & PITCH_MASK)) + mystique->dwgreg.ydstorg; - mystique->dwgreg.selline = val & 7; - } - break; - case REG_BCOL: - mystique->dwgreg.bcol = val; - break; - case REG_FCOL: - mystique->dwgreg.fcol = val; - break; + case REG_SRC0: + { + mystique->dwgreg.src[0] = val; + for (uint8_t y = 0; y < 2; y++) { + for (uint8_t x = 0; x < 16; x++) { + mystique->dwgreg.pattern[y][x] = val & (1 << (x + (y * 16))); + } + } +#if 0 + pclog("SRC0 = 0x%08X\n", val); +#endif + if (mystique->busy && (mystique->dwgreg.dwgctrl_running & DWGCTRL_OPCODE_MASK) == DWGCTRL_OPCODE_ILOAD) + blit_iload_write(mystique, mystique->dwgreg.src[0], 32); + } + break; + case REG_SRC1: + { + mystique->dwgreg.src[1] = val; + for (uint8_t y = 2; y < 4; y++) { + for (uint8_t x = 0; x < 16; x++) { + mystique->dwgreg.pattern[y][x] = val & (1 << (x + ((y - 2) * 16))); + } + } +#if 0 + pclog("SRC1 = 0x%08X\n", val); +#endif + if (mystique->busy && (mystique->dwgreg.dwgctrl_running & DWGCTRL_OPCODE_MASK) == DWGCTRL_OPCODE_ILOAD) + blit_iload_write(mystique, mystique->dwgreg.src[1], 32); + } + break; + case REG_SRC2: + { + mystique->dwgreg.src[2] = val; + for (uint8_t y = 4; y < 6; y++) { + for (uint8_t x = 0; x < 16; x++) { + mystique->dwgreg.pattern[y][x] = val & (1 << (x + ((y - 4) * 16))); + } + } +#if 0 + pclog("SRC2 = 0x%08X\n", val); +#endif + if (mystique->busy && (mystique->dwgreg.dwgctrl_running & DWGCTRL_OPCODE_MASK) == DWGCTRL_OPCODE_ILOAD) + blit_iload_write(mystique, mystique->dwgreg.src[2], 32); + break; + } + case REG_SRC3: + { + mystique->dwgreg.src[3] = val; + for (uint8_t y = 6; y < 8; y++) { + for (uint8_t x = 0; x < 16; x++) { + mystique->dwgreg.pattern[y][x] = val & (1 << (x + ((y - 6) * 16))); + } + } +#if 0 + pclog("SRC3 = 0x%08X\n", val); +#endif + if (mystique->busy && (mystique->dwgreg.dwgctrl_running & DWGCTRL_OPCODE_MASK) == DWGCTRL_OPCODE_ILOAD) + blit_iload_write(mystique, mystique->dwgreg.src[3], 32); + break; + } - case REG_SRC0: - mystique->dwgreg.src[0] = val; - if (mystique->busy && (mystique->dwgreg.dwgctrl_running & DWGCTRL_OPCODE_MASK) == DWGCTRL_OPCODE_ILOAD) - blit_iload_write(mystique, mystique->dwgreg.src[0], 32); - break; - case REG_SRC1: - mystique->dwgreg.src[1] = val; - if (mystique->busy && (mystique->dwgreg.dwgctrl_running & DWGCTRL_OPCODE_MASK) == DWGCTRL_OPCODE_ILOAD) - blit_iload_write(mystique, mystique->dwgreg.src[1], 32); - break; - case REG_SRC2: - mystique->dwgreg.src[2] = val; - if (mystique->busy && (mystique->dwgreg.dwgctrl_running & DWGCTRL_OPCODE_MASK) == DWGCTRL_OPCODE_ILOAD) - blit_iload_write(mystique, mystique->dwgreg.src[2], 32); - break; - case REG_SRC3: - mystique->dwgreg.src[3] = val; - if (mystique->busy && (mystique->dwgreg.dwgctrl_running & DWGCTRL_OPCODE_MASK) == DWGCTRL_OPCODE_ILOAD) - blit_iload_write(mystique, mystique->dwgreg.src[3], 32); - break; + case REG_DMAPAD: + if (mystique->busy && (mystique->dwgreg.dwgctrl_running & DWGCTRL_OPCODE_MASK) == DWGCTRL_OPCODE_ILOAD) + blit_iload_write(mystique, val, 32); + break; - case REG_DMAPAD: - if (mystique->busy && (mystique->dwgreg.dwgctrl_running & DWGCTRL_OPCODE_MASK) == DWGCTRL_OPCODE_ILOAD) - blit_iload_write(mystique, val, 32); - break; + case REG_AR0: + mystique->dwgreg.ar[0] = val; + break; + case REG_AR1: + mystique->dwgreg.ar[1] = val; + break; + case REG_AR2: + mystique->dwgreg.ar[2] = val; + break; + case REG_AR3: + mystique->dwgreg.ar[3] = val; + break; + case REG_AR4: + mystique->dwgreg.ar[4] = val; + break; + case REG_AR5: + mystique->dwgreg.ar[5] = val; + break; + case REG_AR6: + mystique->dwgreg.ar[6] = val; + break; - case REG_AR0: - mystique->dwgreg.ar[0] = val; - break; - case REG_AR1: - mystique->dwgreg.ar[1] = val; - break; - case REG_AR2: - mystique->dwgreg.ar[2] = val; - break; - case REG_AR3: - mystique->dwgreg.ar[3] = val; - break; - case REG_AR4: - mystique->dwgreg.ar[4] = val; - break; - case REG_AR5: - mystique->dwgreg.ar[5] = val; - break; - case REG_AR6: - mystique->dwgreg.ar[6] = val; - break; + case REG_DR0: + mystique->dwgreg.dr[0] = val; + break; + case REG_DR2: + mystique->dwgreg.dr[2] = val; + break; + case REG_DR3: + mystique->dwgreg.dr[3] = val; + break; + case REG_DR4: + mystique->dwgreg.dr[4] = val; + break; + case REG_DR6: + mystique->dwgreg.dr[6] = val; + break; + case REG_DR7: + mystique->dwgreg.dr[7] = val; + break; + case REG_DR8: + mystique->dwgreg.dr[8] = val; + break; + case REG_DR10: + mystique->dwgreg.dr[10] = val; + break; + case REG_DR11: + mystique->dwgreg.dr[11] = val; + break; + case REG_DR12: + mystique->dwgreg.dr[12] = val; + break; + case REG_DR14: + mystique->dwgreg.dr[14] = val; + break; + case REG_DR15: + mystique->dwgreg.dr[15] = val; + break; - case REG_DR0: - mystique->dwgreg.dr[0] = val; - break; - case REG_DR2: - mystique->dwgreg.dr[2] = val; - break; - case REG_DR3: - mystique->dwgreg.dr[3] = val; - break; - case REG_DR4: - mystique->dwgreg.dr[4] = val; - break; - case REG_DR6: - mystique->dwgreg.dr[6] = val; - break; - case REG_DR7: - mystique->dwgreg.dr[7] = val; - break; - case REG_DR8: - mystique->dwgreg.dr[8] = val; - break; - case REG_DR10: - mystique->dwgreg.dr[10] = val; - break; - case REG_DR11: - mystique->dwgreg.dr[11] = val; - break; - case REG_DR12: - mystique->dwgreg.dr[12] = val; - break; - case REG_DR14: - mystique->dwgreg.dr[14] = val; - break; - case REG_DR15: - mystique->dwgreg.dr[15] = val; - break; + case REG_SECEND: + mystique->dma.secend = val; + if (mystique->dma.state != DMA_STATE_SEC && (mystique->dma.secaddress & DMA_ADDR_MASK) != (mystique->dma.secend & DMA_ADDR_MASK)) + mystique->dma.state = DMA_STATE_SEC; + break; - case REG_SECEND: - mystique->dma.secend = val; - if (mystique->dma.state != DMA_STATE_SEC && (mystique->dma.secaddress & DMA_ADDR_MASK) != (mystique->dma.secend & DMA_ADDR_MASK)) - mystique->dma.state = DMA_STATE_SEC; - break; + case REG_SOFTRAP: + mystique->dma.state = DMA_STATE_IDLE; + mystique->endprdmasts_pending = 1; + mystique->softrap_pending_val = val; + mystique->softrap_pending = 1; + break; - case REG_SOFTRAP: - mystique->dma.state = DMA_STATE_IDLE; - mystique->endprdmasts_pending = 1; - mystique->softrap_pending_val = val; - mystique->softrap_pending = 1; - break; - - default: - mystique_accel_ctrl_write_b(addr, val & 0xff, p); - mystique_accel_ctrl_write_b(addr+1, (val >> 8) & 0xff, p); - mystique_accel_ctrl_write_b(addr+2, (val >> 16) & 0xff, p); - mystique_accel_ctrl_write_b(addr+3, (val >> 24) & 0xff, p); - break; + default: + mystique_accel_ctrl_write_b(addr, val & 0xff, priv); + mystique_accel_ctrl_write_b(addr + 1, (val >> 8) & 0xff, priv); + mystique_accel_ctrl_write_b(addr + 2, (val >> 16) & 0xff, priv); + mystique_accel_ctrl_write_b(addr + 3, (val >> 24) & 0xff, priv); + break; } if (start_blit) - mystique_start_blit(mystique); + mystique_start_blit(mystique); } - static void -mystique_ctrl_write_l(uint32_t addr, uint32_t val, void *p) +mystique_ctrl_write_l(uint32_t addr, uint32_t val, void *priv) { - mystique_t *mystique = (mystique_t *)p; - uint32_t reg_addr; + mystique_t *mystique = (mystique_t *) priv; + uint32_t reg_addr; if ((addr & 0x3fff) < 0x1c00) { - mystique_iload_write_l(addr, val, p); - return; + mystique_iload_write_l(addr, val, priv); + return; } if ((addr & 0x3e00) == 0x1c00 || (addr & 0x3e00) == 0x2c00) { - if ((addr & 0x300) == 0x100) - mystique->blitter_submit_refcount++; - mystique_queue(mystique, addr & 0x3fff, val, FIFO_WRITE_CTRL_LONG); - return; + if ((addr & 0x300) == 0x100) + mystique->blitter_submit_refcount++; + mystique_queue(mystique, addr & 0x3fff, val, FIFO_WRITE_CTRL_LONG); + return; } switch (addr & 0x3ffc) { - case REG_PRIMEND: - thread_wait_mutex(mystique->dma.lock); - mystique->dma.primend = val; - if (mystique->dma.state == DMA_STATE_IDLE && (mystique->dma.primaddress & DMA_ADDR_MASK) != (mystique->dma.primend & DMA_ADDR_MASK)) { - mystique->endprdmasts_pending = 0; - mystique->status &= ~STATUS_ENDPRDMASTS; + case REG_PRIMEND: + thread_wait_mutex(mystique->dma.lock); + mystique->dma.primend = val; + if (mystique->dma.state == DMA_STATE_IDLE && (mystique->dma.primaddress & DMA_ADDR_MASK) != (mystique->dma.primend & DMA_ADDR_MASK)) { + mystique->endprdmasts_pending = 0; + mystique->status &= ~STATUS_ENDPRDMASTS; - mystique->dma.state = DMA_STATE_PRI; - mystique->dma.pri_state = 0; - wake_fifo_thread(mystique); - } - thread_release_mutex(mystique->dma.lock); - break; + mystique->dma.state = DMA_STATE_PRI; + mystique->dma.pri_state = 0; + wake_fifo_thread(mystique); + } + thread_release_mutex(mystique->dma.lock); + break; - case REG_DWG_INDIR_WT: case REG_DWG_INDIR_WT+0x04: case REG_DWG_INDIR_WT+0x08: case REG_DWG_INDIR_WT+0x0c: - case REG_DWG_INDIR_WT+0x10: case REG_DWG_INDIR_WT+0x14: case REG_DWG_INDIR_WT+0x18: case REG_DWG_INDIR_WT+0x1c: - case REG_DWG_INDIR_WT+0x20: case REG_DWG_INDIR_WT+0x24: case REG_DWG_INDIR_WT+0x28: case REG_DWG_INDIR_WT+0x2c: - case REG_DWG_INDIR_WT+0x30: case REG_DWG_INDIR_WT+0x34: case REG_DWG_INDIR_WT+0x38: case REG_DWG_INDIR_WT+0x3c: - reg_addr = (mystique->dmamap[(addr >> 2) & 0xf] & 0x7f) << 2; - if (mystique->dmamap[(addr >> 2) & 0xf] & 0x80) - reg_addr += 0x2c00; - else - reg_addr += 0x1c00; + case REG_DWG_INDIR_WT: + case REG_DWG_INDIR_WT + 0x04: + case REG_DWG_INDIR_WT + 0x08: + case REG_DWG_INDIR_WT + 0x0c: + case REG_DWG_INDIR_WT + 0x10: + case REG_DWG_INDIR_WT + 0x14: + case REG_DWG_INDIR_WT + 0x18: + case REG_DWG_INDIR_WT + 0x1c: + case REG_DWG_INDIR_WT + 0x20: + case REG_DWG_INDIR_WT + 0x24: + case REG_DWG_INDIR_WT + 0x28: + case REG_DWG_INDIR_WT + 0x2c: + case REG_DWG_INDIR_WT + 0x30: + case REG_DWG_INDIR_WT + 0x34: + case REG_DWG_INDIR_WT + 0x38: + case REG_DWG_INDIR_WT + 0x3c: + reg_addr = (mystique->dmamap[(addr >> 2) & 0xf] & 0x7f) << 2; + if (mystique->dmamap[(addr >> 2) & 0xf] & 0x80) + reg_addr += 0x2c00; + else + reg_addr += 0x1c00; - if ((reg_addr & 0x300) == 0x100) - mystique->blitter_submit_refcount++; + if ((reg_addr & 0x300) == 0x100) + mystique->blitter_submit_refcount++; - mystique_queue(mystique, reg_addr, val, FIFO_WRITE_CTRL_LONG); - break; + mystique_queue(mystique, reg_addr, val, FIFO_WRITE_CTRL_LONG); + break; - default: - mystique_ctrl_write_b(addr, val & 0xff, p); - mystique_ctrl_write_b(addr+1, (val >> 8) & 0xff, p); - mystique_ctrl_write_b(addr+2, (val >> 16) & 0xff, p); - mystique_ctrl_write_b(addr+3, (val >> 24) & 0xff, p); - break; + default: + mystique_ctrl_write_b(addr, val & 0xff, priv); + mystique_ctrl_write_b(addr + 1, (val >> 8) & 0xff, priv); + mystique_ctrl_write_b(addr + 2, (val >> 16) & 0xff, priv); + mystique_ctrl_write_b(addr + 3, (val >> 24) & 0xff, priv); + break; } } - static uint8_t -mystique_iload_read_b(uint32_t addr, void *p) +mystique_iload_read_b(UNUSED(uint32_t addr), void *priv) { - mystique_t *mystique = (mystique_t *)p; + mystique_t *mystique = (mystique_t *) priv; wait_fifo_idle(mystique); if (!mystique->busy) - return 0xff; + return 0xff; return blit_idump_read(mystique); } - static uint32_t -mystique_iload_read_l(uint32_t addr, void *p) +mystique_iload_read_l(UNUSED(uint32_t addr), void *priv) { - mystique_t *mystique = (mystique_t *)p; + mystique_t *mystique = (mystique_t *) priv; wait_fifo_idle(mystique); if (!mystique->busy) - return 0xffffffff; + return 0xffffffff; mystique->dwgreg.words++; return blit_idump_read(mystique); } - static void -mystique_iload_write_b(uint32_t addr, uint8_t val, void *p) +mystique_iload_write_b(UNUSED(uint32_t addr), UNUSED(uint8_t val), UNUSED(void *priv)) { - + // } - static void -mystique_iload_write_l(uint32_t addr, uint32_t val, void *p) +mystique_iload_write_l(UNUSED(uint32_t addr), uint32_t val, void *priv) { - mystique_t *mystique = (mystique_t *)p; + mystique_t *mystique = (mystique_t *) priv; mystique_queue(mystique, 0, val, FIFO_WRITE_ILOAD_LONG); } - static void -mystique_accel_iload_write_l(uint32_t addr, uint32_t val, void *p) +mystique_accel_iload_write_l(UNUSED(uint32_t addr), uint32_t val, void *priv) { - mystique_t *mystique = (mystique_t *)p; + mystique_t *mystique = (mystique_t *) priv; switch (mystique->dwgreg.dmamod) { - case DMA_MODE_REG: - if (mystique->dma.iload_state == 0) { - mystique->dma.iload_header = val; - mystique->dma.iload_state = 1; - } else { - uint32_t reg_addr = (mystique->dma.iload_header & 0x7f) << 2; - if (mystique->dma.iload_header & 0x80) - reg_addr += 0x2c00; - else - reg_addr += 0x1c00; + case DMA_MODE_REG: + if (mystique->dma.iload_state == 0) { + mystique->dma.iload_header = val; + mystique->dma.iload_state = 1; + } else { + uint32_t reg_addr = (mystique->dma.iload_header & 0x7f) << 2; + if (mystique->dma.iload_header & 0x80) + reg_addr += 0x2c00; + else + reg_addr += 0x1c00; - if ((reg_addr & 0x300) == 0x100) - mystique->blitter_submit_dma_refcount++; - mystique_accel_ctrl_write_l(reg_addr, val, mystique); + if ((reg_addr & 0x300) == 0x100) + mystique->blitter_submit_dma_refcount++; + mystique_accel_ctrl_write_l(reg_addr, val, mystique); - mystique->dma.iload_header >>= 8; - mystique->dma.iload_state = (mystique->dma.iload_state == 4) ? 0 : (mystique->dma.iload_state+1); - } - break; + mystique->dma.iload_header >>= 8; + mystique->dma.iload_state = (mystique->dma.iload_state == 4) ? 0 : (mystique->dma.iload_state + 1); + } + break; - case DMA_MODE_BLIT: - if (mystique->busy) - blit_iload_write(mystique, val, 32); - break; + case DMA_MODE_BLIT: + if (mystique->busy) + blit_iload_write(mystique, val, 32); + break; - /* default: - pclog("ILOAD write DMAMOD %i\n", mystique->dwgreg.dmamod); */ + default: +#if 0 + pclog("ILOAD write DMAMOD %i\n", mystique->dwgreg.dmamod); */ +#endif + break; } } - static uint8_t -mystique_readb_linear(uint32_t addr, void *p) +mystique_readb_linear(uint32_t addr, void *priv) { - svga_t *svga = (svga_t *)p; + const svga_t *svga = (svga_t *) priv; - cycles -= video_timing_read_b; + cycles -= video_timing_read_b; - addr &= svga->decode_mask; - if (addr >= svga->vram_max) - return 0xff; + addr &= svga->decode_mask; + if (addr >= svga->vram_max) + return 0xff; - return svga->vram[addr & svga->vram_mask]; + return svga->vram[addr & svga->vram_mask]; } - static uint16_t -mystique_readw_linear(uint32_t addr, void *p) +mystique_readw_linear(uint32_t addr, void *priv) { - svga_t *svga = (svga_t *)p; + svga_t *svga = (svga_t *) priv; - cycles -= video_timing_read_w; + cycles -= video_timing_read_w; - addr &= svga->decode_mask; - if (addr >= svga->vram_max) - return 0xffff; + addr &= svga->decode_mask; + if (addr >= svga->vram_max) + return 0xffff; - return *(uint16_t *)&svga->vram[addr & svga->vram_mask]; + return *(uint16_t *) &svga->vram[addr & svga->vram_mask]; } - static uint32_t -mystique_readl_linear(uint32_t addr, void *p) +mystique_readl_linear(uint32_t addr, void *priv) { - svga_t *svga = (svga_t *)p; + svga_t *svga = (svga_t *) priv; - cycles -= video_timing_read_l; + cycles -= video_timing_read_l; - addr &= svga->decode_mask; - if (addr >= svga->vram_max) - return 0xffffffff; + addr &= svga->decode_mask; + if (addr >= svga->vram_max) + return 0xffffffff; - return *(uint32_t *)&svga->vram[addr & svga->vram_mask]; + return *(uint32_t *) &svga->vram[addr & svga->vram_mask]; } - static void -mystique_writeb_linear(uint32_t addr, uint8_t val, void *p) +mystique_writeb_linear(uint32_t addr, uint8_t val, void *priv) { - svga_t *svga = (svga_t *)p; + svga_t *svga = (svga_t *) priv; - cycles -= video_timing_write_b; + cycles -= video_timing_write_b; - addr &= svga->decode_mask; - if (addr >= svga->vram_max) - return; - addr &= svga->vram_mask; - svga->changedvram[addr >> 12] = changeframecount; - svga->vram[addr] = val; + addr &= svga->decode_mask; + if (addr >= svga->vram_max) + return; + addr &= svga->vram_mask; + svga->changedvram[addr >> 12] = changeframecount; + svga->vram[addr] = val; } - static void -mystique_writew_linear(uint32_t addr, uint16_t val, void *p) +mystique_writew_linear(uint32_t addr, uint16_t val, void *priv) { - svga_t *svga = (svga_t *)p; + svga_t *svga = (svga_t *) priv; - cycles -= video_timing_write_w; + cycles -= video_timing_write_w; - addr &= svga->decode_mask; - if (addr >= svga->vram_max) - return; - addr &= svga->vram_mask; - svga->changedvram[addr >> 12] = changeframecount; - *(uint16_t *)&svga->vram[addr] = val; + addr &= svga->decode_mask; + if (addr >= svga->vram_max) + return; + addr &= svga->vram_mask; + svga->changedvram[addr >> 12] = changeframecount; + *(uint16_t *) &svga->vram[addr] = val; } - static void -mystique_writel_linear(uint32_t addr, uint32_t val, void *p) +mystique_writel_linear(uint32_t addr, uint32_t val, void *priv) { - svga_t *svga = (svga_t *)p; + svga_t *svga = (svga_t *) priv; - cycles -= video_timing_write_l; + cycles -= video_timing_write_l; - addr &= svga->decode_mask; - if (addr >= svga->vram_max) - return; - addr &= svga->vram_mask; - svga->changedvram[addr >> 12] = changeframecount; - *(uint32_t *)&svga->vram[addr] = val; + addr &= svga->decode_mask; + if (addr >= svga->vram_max) + return; + addr &= svga->vram_mask; + svga->changedvram[addr >> 12] = changeframecount; + *(uint32_t *) &svga->vram[addr] = val; } - static void run_dma(mystique_t *mystique) { @@ -2402,483 +2659,502 @@ run_dma(mystique_t *mystique) thread_wait_mutex(mystique->dma.lock); if (mystique->dma.state == DMA_STATE_IDLE) { - thread_release_mutex(mystique->dma.lock); - return; + thread_release_mutex(mystique->dma.lock); + return; } while (words_transferred < DMA_MAX_WORDS && mystique->dma.state != DMA_STATE_IDLE) { - switch (mystique->dma.state) { - case DMA_STATE_PRI: - switch (mystique->dma.primaddress & DMA_MODE_MASK) { - case DMA_MODE_REG: - if (mystique->dma.pri_state == 0) { - dma_bm_read(mystique->dma.primaddress & DMA_ADDR_MASK, (uint8_t *) &mystique->dma.pri_header, 4, 4); - mystique->dma.primaddress += 4; - } + switch (mystique->dma.state) { + case DMA_STATE_PRI: + switch (mystique->dma.primaddress & DMA_MODE_MASK) { + case DMA_MODE_REG: + if (mystique->dma.pri_state == 0) { + dma_bm_read(mystique->dma.primaddress & DMA_ADDR_MASK, (uint8_t *) &mystique->dma.pri_header, 4, 4); + mystique->dma.primaddress += 4; + } - if ((mystique->dma.pri_header & 0xff) != 0x15) { - uint32_t val, reg_addr; + if ((mystique->dma.pri_header & 0xff) != 0x15) { + uint32_t val; + uint32_t reg_addr; - dma_bm_read(mystique->dma.primaddress & DMA_ADDR_MASK, (uint8_t *) &val, 4, 4); - mystique->dma.primaddress += 4; + dma_bm_read(mystique->dma.primaddress & DMA_ADDR_MASK, (uint8_t *) &val, 4, 4); + mystique->dma.primaddress += 4; - reg_addr = (mystique->dma.pri_header & 0x7f) << 2; - if (mystique->dma.pri_header & 0x80) - reg_addr += 0x2c00; - else - reg_addr += 0x1c00; + reg_addr = (mystique->dma.pri_header & 0x7f) << 2; + if (mystique->dma.pri_header & 0x80) + reg_addr += 0x2c00; + else + reg_addr += 0x1c00; - if ((reg_addr & 0x300) == 0x100) - mystique->blitter_submit_dma_refcount++; + if ((reg_addr & 0x300) == 0x100) + mystique->blitter_submit_dma_refcount++; - mystique_accel_ctrl_write_l(reg_addr, val, mystique); - } + mystique_accel_ctrl_write_l(reg_addr, val, mystique); + } - mystique->dma.pri_header >>= 8; - mystique->dma.pri_state = (mystique->dma.pri_state + 1) & 3; + mystique->dma.pri_header >>= 8; + mystique->dma.pri_state = (mystique->dma.pri_state + 1) & 3; - words_transferred++; - if (mystique->dma.state == DMA_STATE_SEC) - mystique->dma.pri_state = 0; - else if ((mystique->dma.primaddress & DMA_ADDR_MASK) == (mystique->dma.primend & DMA_ADDR_MASK)) { - mystique->endprdmasts_pending = 1; - mystique->dma.state = DMA_STATE_IDLE; - } - break; + words_transferred++; + if (mystique->dma.state == DMA_STATE_SEC) + mystique->dma.pri_state = 0; + else if ((mystique->dma.primaddress & DMA_ADDR_MASK) == (mystique->dma.primend & DMA_ADDR_MASK)) { + mystique->endprdmasts_pending = 1; + mystique->dma.state = DMA_STATE_IDLE; + } + break; - default: - fatal("DMA_STATE_PRI: mode %i\n", mystique->dma.primaddress & DMA_MODE_MASK); - } - break; + default: + fatal("DMA_STATE_PRI: mode %i\n", mystique->dma.primaddress & DMA_MODE_MASK); + } + break; - case DMA_STATE_SEC: - switch (mystique->dma.secaddress & DMA_MODE_MASK) { - case DMA_MODE_REG: - if (mystique->dma.sec_state == 0) { - dma_bm_read(mystique->dma.secaddress & DMA_ADDR_MASK, (uint8_t *) &mystique->dma.sec_header, 4, 4); - mystique->dma.secaddress += 4; - } + case DMA_STATE_SEC: + switch (mystique->dma.secaddress & DMA_MODE_MASK) { + case DMA_MODE_REG: + if (mystique->dma.sec_state == 0) { + dma_bm_read(mystique->dma.secaddress & DMA_ADDR_MASK, (uint8_t *) &mystique->dma.sec_header, 4, 4); + mystique->dma.secaddress += 4; + } - uint32_t val, reg_addr; + uint32_t val; + uint32_t reg_addr; - dma_bm_read(mystique->dma.secaddress & DMA_ADDR_MASK, (uint8_t *) &val, 4, 4); - mystique->dma.secaddress += 4; + dma_bm_read(mystique->dma.secaddress & DMA_ADDR_MASK, (uint8_t *) &val, 4, 4); + mystique->dma.secaddress += 4; - reg_addr = (mystique->dma.sec_header & 0x7f) << 2; - if (mystique->dma.sec_header & 0x80) - reg_addr += 0x2c00; - else - reg_addr += 0x1c00; + reg_addr = (mystique->dma.sec_header & 0x7f) << 2; + if (mystique->dma.sec_header & 0x80) + reg_addr += 0x2c00; + else + reg_addr += 0x1c00; - if ((reg_addr & 0x300) == 0x100) - mystique->blitter_submit_dma_refcount++; + if ((reg_addr & 0x300) == 0x100) + mystique->blitter_submit_dma_refcount++; - mystique_accel_ctrl_write_l(reg_addr, val, mystique); + mystique_accel_ctrl_write_l(reg_addr, val, mystique); - mystique->dma.sec_header >>= 8; - mystique->dma.sec_state = (mystique->dma.sec_state + 1) & 3; + mystique->dma.sec_header >>= 8; + mystique->dma.sec_state = (mystique->dma.sec_state + 1) & 3; - words_transferred++; - if ((mystique->dma.secaddress & DMA_ADDR_MASK) == (mystique->dma.secend & DMA_ADDR_MASK)) { - if ((mystique->dma.primaddress & DMA_ADDR_MASK) == (mystique->dma.primend & DMA_ADDR_MASK)) { - mystique->endprdmasts_pending = 1; - mystique->dma.state = DMA_STATE_IDLE; - } else - mystique->dma.state = DMA_STATE_PRI; - } - break; + words_transferred++; + if ((mystique->dma.secaddress & DMA_ADDR_MASK) == (mystique->dma.secend & DMA_ADDR_MASK)) { + if ((mystique->dma.primaddress & DMA_ADDR_MASK) == (mystique->dma.primend & DMA_ADDR_MASK)) { + mystique->endprdmasts_pending = 1; + mystique->dma.state = DMA_STATE_IDLE; + } else + mystique->dma.state = DMA_STATE_PRI; + } + break; - case DMA_MODE_BLIT: { - uint32_t val; + case DMA_MODE_BLIT: + { + uint32_t val; - dma_bm_read(mystique->dma.secaddress & DMA_ADDR_MASK, (uint8_t *) &val, 4, 4); - mystique->dma.secaddress += 4; + dma_bm_read(mystique->dma.secaddress & DMA_ADDR_MASK, (uint8_t *) &val, 4, 4); + mystique->dma.secaddress += 4; - if (mystique->busy) - blit_iload_write(mystique, val, 32); + if (mystique->busy) + blit_iload_write(mystique, val, 32); - words_transferred++; - if ((mystique->dma.secaddress & DMA_ADDR_MASK) == (mystique->dma.secend & DMA_ADDR_MASK)) { - if ((mystique->dma.primaddress & DMA_ADDR_MASK) == (mystique->dma.primend & DMA_ADDR_MASK)) { - mystique->endprdmasts_pending = 1; - mystique->dma.state = DMA_STATE_IDLE; - } else - mystique->dma.state = DMA_STATE_PRI; - } - } break; + words_transferred++; + if ((mystique->dma.secaddress & DMA_ADDR_MASK) == (mystique->dma.secend & DMA_ADDR_MASK)) { + if ((mystique->dma.primaddress & DMA_ADDR_MASK) == (mystique->dma.primend & DMA_ADDR_MASK)) { + mystique->endprdmasts_pending = 1; + mystique->dma.state = DMA_STATE_IDLE; + } else + mystique->dma.state = DMA_STATE_PRI; + } + } + break; - default: - fatal("DMA_STATE_SEC: mode %i\n", mystique->dma.secaddress & DMA_MODE_MASK); - } - break; - } + default: + fatal("DMA_STATE_SEC: mode %i\n", mystique->dma.secaddress & DMA_MODE_MASK); + } + break; + + default: + break; + } } thread_release_mutex(mystique->dma.lock); } - static void -fifo_thread(void *p) +fifo_thread(void *priv) { - mystique_t *mystique = (mystique_t *)p; + mystique_t *mystique = (mystique_t *) priv; while (mystique->thread_run) { - thread_set_event(mystique->fifo_not_full_event); - thread_wait_event(mystique->wake_fifo_thread, -1); - thread_reset_event(mystique->wake_fifo_thread); + thread_set_event(mystique->fifo_not_full_event); + thread_wait_event(mystique->wake_fifo_thread, -1); + thread_reset_event(mystique->wake_fifo_thread); - while (!FIFO_EMPTY || mystique->dma.state != DMA_STATE_IDLE) { - int words_transferred = 0; + while (!FIFO_EMPTY || mystique->dma.state != DMA_STATE_IDLE) { + int words_transferred = 0; - while (!FIFO_EMPTY && words_transferred < 100) { - fifo_entry_t *fifo = &mystique->fifo[mystique->fifo_read_idx & FIFO_MASK]; + while (!FIFO_EMPTY && words_transferred < 100) { + fifo_entry_t *fifo = &mystique->fifo[mystique->fifo_read_idx & FIFO_MASK]; - switch (fifo->addr_type & FIFO_TYPE) { - case FIFO_WRITE_CTRL_BYTE: - mystique_accel_ctrl_write_b(fifo->addr_type & FIFO_ADDR, fifo->val, mystique); - break; - case FIFO_WRITE_CTRL_LONG: - mystique_accel_ctrl_write_l(fifo->addr_type & FIFO_ADDR, fifo->val, mystique); - break; - case FIFO_WRITE_ILOAD_LONG: - mystique_accel_iload_write_l(fifo->addr_type & FIFO_ADDR, fifo->val, mystique); - break; - } + switch (fifo->addr_type & FIFO_TYPE) { + case FIFO_WRITE_CTRL_BYTE: + mystique_accel_ctrl_write_b(fifo->addr_type & FIFO_ADDR, fifo->val, mystique); + break; + case FIFO_WRITE_CTRL_LONG: + mystique_accel_ctrl_write_l(fifo->addr_type & FIFO_ADDR, fifo->val, mystique); + break; + case FIFO_WRITE_ILOAD_LONG: + mystique_accel_iload_write_l(fifo->addr_type & FIFO_ADDR, fifo->val, mystique); + break; - fifo->addr_type = FIFO_INVALID; - mystique->fifo_read_idx++; + default: + break; + } - if (FIFO_ENTRIES > FIFO_THRESHOLD) - thread_set_event(mystique->fifo_not_full_event); + fifo->addr_type = FIFO_INVALID; + mystique->fifo_read_idx++; - words_transferred++; - } + if (FIFO_ENTRIES > FIFO_THRESHOLD) + thread_set_event(mystique->fifo_not_full_event); - /*Only run DMA once the FIFO is empty. Required by - Screamer 2 / Rally which will incorrectly clip an ILOAD - if DMA runs ahead*/ - if (!words_transferred) - run_dma(mystique); - } + words_transferred++; + } + + /*Only run DMA once the FIFO is empty. Required by + Screamer 2 / Rally which will incorrectly clip an ILOAD + if DMA runs ahead*/ + if (!words_transferred) + run_dma(mystique); + } } } - static void wake_fifo_thread(mystique_t *mystique) { if (!timer_is_enabled(&mystique->wake_timer)) { - /* Don't wake FIFO thread immediately - if we do that it will probably - process one word and go back to sleep, requiring it to be woken on - almost every write. Instead, wait a short while so that the CPU - emulation writes more data so we have more batched-up work. */ - timer_set_delay_u64(&mystique->wake_timer, WAKE_DELAY); + /* Don't wake FIFO thread immediately - if we do that it will probably + process one word and go back to sleep, requiring it to be woken on + almost every write. Instead, wait a short while so that the CPU + emulation writes more data so we have more batched-up work. */ + timer_set_delay_u64(&mystique->wake_timer, WAKE_DELAY); } } - static void wake_fifo_thread_now(mystique_t *mystique) { thread_set_event(mystique->wake_fifo_thread); } - static void -mystique_wake_timer(void *p) +mystique_wake_timer(void *priv) { - mystique_t *mystique = (mystique_t *)p; + mystique_t *mystique = (mystique_t *) priv; thread_set_event(mystique->wake_fifo_thread); /*Wake up FIFO thread if moving from idle*/ } - static void wait_fifo_idle(mystique_t *mystique) { while (!FIFO_EMPTY) { - wake_fifo_thread_now(mystique); - thread_wait_event(mystique->fifo_not_full_event, 1); + wake_fifo_thread_now(mystique); + thread_wait_event(mystique->fifo_not_full_event, 1); } } - /*IRQ code (PCI & PIC) is not currently thread safe. SOFTRAP IRQ requests must therefore be submitted from the main emulation thread, in this case via a timer callback. End-of-DMA status is also deferred here to prevent races between SOFTRAP IRQs and code reading the status register. Croc will get into an IRQ loop and triple fault if the ENDPRDMASTS flag is seen before the IRQ is taken*/ -static void mystique_softrap_pending_timer(void *p) +static void +mystique_softrap_pending_timer(void *priv) { - mystique_t *mystique = (mystique_t *)p; + mystique_t *mystique = (mystique_t *) priv; timer_advance_u64(&mystique->softrap_pending_timer, TIMER_USEC * 100); if (mystique->endprdmasts_pending) { - mystique->endprdmasts_pending = 0; - mystique->status |= STATUS_ENDPRDMASTS; + mystique->endprdmasts_pending = 0; + mystique->status |= STATUS_ENDPRDMASTS; } if (mystique->softrap_pending) { - mystique->softrap_pending = 0; + mystique->softrap_pending = 0; - mystique->dma.secaddress = mystique->softrap_pending_val; - mystique->status |= STATUS_SOFTRAPEN; - mystique_update_irqs(mystique); + mystique->dma.secaddress = mystique->softrap_pending_val; + mystique->status |= STATUS_SOFTRAPEN; + mystique_update_irqs(mystique); } } - -static -void mystique_queue(mystique_t *mystique, uint32_t addr, uint32_t val, uint32_t type) +static void +mystique_queue(mystique_t *mystique, uint32_t addr, uint32_t val, uint32_t type) { fifo_entry_t *fifo = &mystique->fifo[mystique->fifo_write_idx & FIFO_MASK]; if (FIFO_FULL) { - thread_reset_event(mystique->fifo_not_full_event); - if (FIFO_FULL) - thread_wait_event(mystique->fifo_not_full_event, -1); /* Wait for room in ringbuffer */ + thread_reset_event(mystique->fifo_not_full_event); + if (FIFO_FULL) + thread_wait_event(mystique->fifo_not_full_event, -1); /* Wait for room in ringbuffer */ } - fifo->val = val; + fifo->val = val; fifo->addr_type = (addr & FIFO_ADDR) | type; mystique->fifo_write_idx++; if (FIFO_ENTRIES > FIFO_THRESHOLD || FIFO_ENTRIES < 8) - wake_fifo_thread(mystique); + wake_fifo_thread(mystique); } - static uint32_t bitop(uint32_t src, uint32_t dst, uint32_t dwgctrl) { switch (dwgctrl & DWGCTRL_BOP_MASK) { - case BOP(0x0): return 0; - case BOP(0x1): return ~(dst | src); - case BOP(0x2): return dst & ~src; - case BOP(0x3): return ~src; - case BOP(0x4): return ~dst & src; - case BOP(0x5): return ~dst; - case BOP(0x6): return dst ^ src; - case BOP(0x7): return ~(dst & src); - case BOP(0x8): return dst & src; - case BOP(0x9): return ~(dst ^ src); - case BOP(0xa): return dst; - case BOP(0xb): return dst | ~src; - case BOP(0xc): return src; - case BOP(0xd): return ~dst | src; - case BOP(0xe): return dst | src; - case BOP(0xf): return ~0; + case BOP(0x0): + return 0; + case BOP(0x1): + return ~(dst | src); + case BOP(0x2): + return dst & ~src; + case BOP(0x3): + return ~src; + case BOP(0x4): + return ~dst & src; + case BOP(0x5): + return ~dst; + case BOP(0x6): + return dst ^ src; + case BOP(0x7): + return ~(dst & src); + case BOP(0x8): + return dst & src; + case BOP(0x9): + return ~(dst ^ src); + case BOP(0xa): + return dst; + case BOP(0xb): + return dst | ~src; + case BOP(0xc): + return src; + case BOP(0xd): + return ~dst | src; + case BOP(0xe): + return dst | src; + case BOP(0xf): + return ~0; + + default: + break; } return 0; } - static uint16_t dither(mystique_t *mystique, int r, int g, int b, int x, int y) { switch (mystique->dwgreg.dither) { - case DITHER_NONE_555: - return (b >> 3) | ((g >> 3) << 5) | ((r >> 3) << 10); + case DITHER_NONE_555: + return (b >> 3) | ((g >> 3) << 5) | ((r >> 3) << 10); - case DITHER_NONE_565: - return (b >> 3) | ((g >> 2) << 5) | ((r >> 3) << 11); + case DITHER_NONE_565: + return (b >> 3) | ((g >> 2) << 5) | ((r >> 3) << 11); - case DITHER_555: - return dither5[b][y][x] | (dither5[g][y][x] << 5) | (dither5[r][y][x] << 10); + case DITHER_555: + return dither5[b][y][x] | (dither5[g][y][x] << 5) | (dither5[r][y][x] << 10); - case DITHER_565: - default: - return dither5[b][y][x] | (dither6[g][y][x] << 5) | (dither5[r][y][x] << 11); + case DITHER_565: + default: + return dither5[b][y][x] | (dither6[g][y][x] << 5) | (dither5[r][y][x] << 11); } } - static uint32_t blit_idump_idump(mystique_t *mystique) { - svga_t *svga = &mystique->svga; + svga_t *svga = &mystique->svga; uint64_t val64 = 0; - uint32_t val = 0; - int count = 0; + uint32_t val = 0; + int count = 0; switch (mystique->dwgreg.dwgctrl_running & DWGCTRL_ATYPE_MASK) { - case DWGCTRL_ATYPE_RPL: - switch (mystique->dwgreg.dwgctrl_running & DWGCTRL_BLTMOD_MASK) { - case DWGCTRL_BLTMOD_BU32RGB: - case DWGCTRL_BLTMOD_BFCOL: - switch (mystique->maccess_running & MACCESS_PWIDTH_MASK) { - case MACCESS_PWIDTH_8: - while (count < 32) { - val |= (svga->vram[mystique->dwgreg.src_addr & mystique->vram_mask] << count); + case DWGCTRL_ATYPE_RPL: + switch (mystique->dwgreg.dwgctrl_running & DWGCTRL_BLTMOD_MASK) { + case DWGCTRL_BLTMOD_BU32RGB: + case DWGCTRL_BLTMOD_BFCOL: + switch (mystique->maccess_running & MACCESS_PWIDTH_MASK) { + case MACCESS_PWIDTH_8: + while (count < 32) { + val |= (svga->vram[mystique->dwgreg.src_addr & mystique->vram_mask] << count); - if (mystique->dwgreg.src_addr == mystique->dwgreg.ar[0]) { - mystique->dwgreg.ar[0] += mystique->dwgreg.ar[5]; - mystique->dwgreg.ar[3] += mystique->dwgreg.ar[5]; - mystique->dwgreg.src_addr = mystique->dwgreg.ar[3]; - } else - mystique->dwgreg.src_addr++; + if (mystique->dwgreg.src_addr == mystique->dwgreg.ar[0]) { + mystique->dwgreg.ar[0] += mystique->dwgreg.ar[5]; + mystique->dwgreg.ar[3] += mystique->dwgreg.ar[5]; + mystique->dwgreg.src_addr = mystique->dwgreg.ar[3]; + } else + mystique->dwgreg.src_addr++; - if (mystique->dwgreg.xdst == mystique->dwgreg.fxright) { - mystique->dwgreg.xdst = mystique->dwgreg.fxleft; - mystique->dwgreg.length_cur--; - if (!mystique->dwgreg.length_cur) { - mystique->busy = 0; - mystique->blitter_complete_refcount++; - break; - } - break; - } else - mystique->dwgreg.xdst = (mystique->dwgreg.xdst + 1) & 0xffff; + if (mystique->dwgreg.xdst == mystique->dwgreg.fxright) { + mystique->dwgreg.xdst = mystique->dwgreg.fxleft; + mystique->dwgreg.length_cur--; + if (!mystique->dwgreg.length_cur) { + mystique->busy = 0; + mystique->blitter_complete_refcount++; + break; + } + break; + } else + mystique->dwgreg.xdst = (mystique->dwgreg.xdst + 1) & 0xffff; - count += 8; - } - break; + count += 8; + } + break; - case MACCESS_PWIDTH_16: - while (count < 32) { - val |= (((uint16_t *)svga->vram)[mystique->dwgreg.src_addr & mystique->vram_mask_w] << count); + case MACCESS_PWIDTH_16: + while (count < 32) { + val |= (((uint16_t *) svga->vram)[mystique->dwgreg.src_addr & mystique->vram_mask_w] << count); - if (mystique->dwgreg.src_addr == mystique->dwgreg.ar[0]) { - mystique->dwgreg.ar[0] += mystique->dwgreg.ar[5]; - mystique->dwgreg.ar[3] += mystique->dwgreg.ar[5]; - mystique->dwgreg.src_addr = mystique->dwgreg.ar[3]; - } else - mystique->dwgreg.src_addr++; + if (mystique->dwgreg.src_addr == mystique->dwgreg.ar[0]) { + mystique->dwgreg.ar[0] += mystique->dwgreg.ar[5]; + mystique->dwgreg.ar[3] += mystique->dwgreg.ar[5]; + mystique->dwgreg.src_addr = mystique->dwgreg.ar[3]; + } else + mystique->dwgreg.src_addr++; - if (mystique->dwgreg.xdst == mystique->dwgreg.fxright) { - mystique->dwgreg.xdst = mystique->dwgreg.fxleft; - mystique->dwgreg.length_cur--; - if (!mystique->dwgreg.length_cur) { - mystique->busy = 0; - mystique->blitter_complete_refcount++; - break; - } - break; - } else - mystique->dwgreg.xdst = (mystique->dwgreg.xdst + 1) & 0xffff; + if (mystique->dwgreg.xdst == mystique->dwgreg.fxright) { + mystique->dwgreg.xdst = mystique->dwgreg.fxleft; + mystique->dwgreg.length_cur--; + if (!mystique->dwgreg.length_cur) { + mystique->busy = 0; + mystique->blitter_complete_refcount++; + break; + } + break; + } else + mystique->dwgreg.xdst = (mystique->dwgreg.xdst + 1) & 0xffff; - count += 16; - } - break; + count += 16; + } + break; - case MACCESS_PWIDTH_24: - if (mystique->dwgreg.idump_end_of_line) { - mystique->dwgreg.idump_end_of_line = 0; - val = mystique->dwgreg.iload_rem_data; - mystique->dwgreg.iload_rem_count = 0; - mystique->dwgreg.iload_rem_data = 0; - if (!mystique->dwgreg.length_cur) { - mystique->busy = 0; - mystique->blitter_complete_refcount++; - } - break; - } + case MACCESS_PWIDTH_24: + if (mystique->dwgreg.idump_end_of_line) { + mystique->dwgreg.idump_end_of_line = 0; + val = mystique->dwgreg.iload_rem_data; + mystique->dwgreg.iload_rem_count = 0; + mystique->dwgreg.iload_rem_data = 0; + if (!mystique->dwgreg.length_cur) { + mystique->busy = 0; + mystique->blitter_complete_refcount++; + } + break; + } - count += mystique->dwgreg.iload_rem_count; - val64 = mystique->dwgreg.iload_rem_data; + count += mystique->dwgreg.iload_rem_count; + val64 = mystique->dwgreg.iload_rem_data; - while ((count < 32) && !mystique->dwgreg.idump_end_of_line) { - val64 |= (uint64_t)((*(uint32_t *)&svga->vram[(mystique->dwgreg.src_addr * 3) & mystique->vram_mask]) & 0xffffff) << count; - - if (mystique->dwgreg.src_addr == mystique->dwgreg.ar[0]) { - mystique->dwgreg.ar[0] += mystique->dwgreg.ar[5]; - mystique->dwgreg.ar[3] += mystique->dwgreg.ar[5]; - mystique->dwgreg.src_addr = mystique->dwgreg.ar[3]; - } else - mystique->dwgreg.src_addr++; + while ((count < 32) && !mystique->dwgreg.idump_end_of_line) { + val64 |= (uint64_t) ((*(uint32_t *) &svga->vram[(mystique->dwgreg.src_addr * 3) & mystique->vram_mask]) & 0xffffff) << count; - if (mystique->dwgreg.xdst == mystique->dwgreg.fxright) { - mystique->dwgreg.xdst = mystique->dwgreg.fxleft; - mystique->dwgreg.length_cur--; - if (!mystique->dwgreg.length_cur) { - if (count > 8) - mystique->dwgreg.idump_end_of_line = 1; - else { - count = 32; - mystique->busy = 0; - mystique->blitter_complete_refcount++; - } - break; - } - if (!(mystique->dwgreg.dwgctrl_running & DWGCTRL_LINEAR)) { - if (count > 8) - mystique->dwgreg.idump_end_of_line = 1; - else { - count = 32; - break; - } - } - } else - mystique->dwgreg.xdst = (mystique->dwgreg.xdst + 1) & 0xffff; + if (mystique->dwgreg.src_addr == mystique->dwgreg.ar[0]) { + mystique->dwgreg.ar[0] += mystique->dwgreg.ar[5]; + mystique->dwgreg.ar[3] += mystique->dwgreg.ar[5]; + mystique->dwgreg.src_addr = mystique->dwgreg.ar[3]; + } else + mystique->dwgreg.src_addr++; - count += 24; - } - if (count > 32) - mystique->dwgreg.iload_rem_count = count - 32; - else - mystique->dwgreg.iload_rem_count = 0; - mystique->dwgreg.iload_rem_data = (uint32_t)(val64 >> 32); - val = val64 & 0xffffffff; - break; + if (mystique->dwgreg.xdst == mystique->dwgreg.fxright) { + mystique->dwgreg.xdst = mystique->dwgreg.fxleft; + mystique->dwgreg.length_cur--; + if (!mystique->dwgreg.length_cur) { + if (count > 8) + mystique->dwgreg.idump_end_of_line = 1; + else { + count = 32; + mystique->busy = 0; + mystique->blitter_complete_refcount++; + } + break; + } + if (!(mystique->dwgreg.dwgctrl_running & DWGCTRL_LINEAR)) { + if (count > 8) + mystique->dwgreg.idump_end_of_line = 1; + else { + count = 32; + break; + } + } + } else + mystique->dwgreg.xdst = (mystique->dwgreg.xdst + 1) & 0xffff; - case MACCESS_PWIDTH_32: - val = (((uint32_t *)svga->vram)[mystique->dwgreg.src_addr & mystique->vram_mask_l] << count); + count += 24; + } + if (count > 32) + mystique->dwgreg.iload_rem_count = count - 32; + else + mystique->dwgreg.iload_rem_count = 0; + mystique->dwgreg.iload_rem_data = (uint32_t) (val64 >> 32); + val = val64 & 0xffffffff; + break; - if (mystique->dwgreg.src_addr == mystique->dwgreg.ar[0]) { - mystique->dwgreg.ar[0] += mystique->dwgreg.ar[5]; - mystique->dwgreg.ar[3] += mystique->dwgreg.ar[5]; - mystique->dwgreg.src_addr = mystique->dwgreg.ar[3]; - } else - mystique->dwgreg.src_addr++; + case MACCESS_PWIDTH_32: + val = (((uint32_t *) svga->vram)[mystique->dwgreg.src_addr & mystique->vram_mask_l] << count); - if (mystique->dwgreg.xdst == mystique->dwgreg.fxright) { - mystique->dwgreg.xdst = mystique->dwgreg.fxleft; - mystique->dwgreg.length_cur--; - if (!mystique->dwgreg.length_cur) { - mystique->busy = 0; - mystique->blitter_complete_refcount++; - break; - } - break; - } else - mystique->dwgreg.xdst = (mystique->dwgreg.xdst + 1) & 0xffff; - break; + if (mystique->dwgreg.src_addr == mystique->dwgreg.ar[0]) { + mystique->dwgreg.ar[0] += mystique->dwgreg.ar[5]; + mystique->dwgreg.ar[3] += mystique->dwgreg.ar[5]; + mystique->dwgreg.src_addr = mystique->dwgreg.ar[3]; + } else + mystique->dwgreg.src_addr++; - default: - fatal("IDUMP DWGCTRL_BLTMOD_BU32RGB %x %08x\n", mystique->maccess_running & MACCESS_PWIDTH_MASK, mystique->maccess_running); - } - break; + if (mystique->dwgreg.xdst == mystique->dwgreg.fxright) { + mystique->dwgreg.xdst = mystique->dwgreg.fxleft; + mystique->dwgreg.length_cur--; + if (!mystique->dwgreg.length_cur) { + mystique->busy = 0; + mystique->blitter_complete_refcount++; + break; + } + break; + } else + mystique->dwgreg.xdst = (mystique->dwgreg.xdst + 1) & 0xffff; + break; - default: - fatal("IDUMP DWGCTRL_ATYPE_RPL %08x %08x\n", mystique->dwgreg.dwgctrl_running & DWGCTRL_BLTMOD_MASK, mystique->dwgreg.dwgctrl_running); - break; - } - break; + default: + fatal("IDUMP DWGCTRL_BLTMOD_BU32RGB %x %08x\n", mystique->maccess_running & MACCESS_PWIDTH_MASK, mystique->maccess_running); + } + break; - default: - fatal("Unknown IDUMP atype %03x %08x\n", mystique->dwgreg.dwgctrl_running & DWGCTRL_ATYPE_MASK, mystique->dwgreg.dwgctrl_running); + default: + fatal("IDUMP DWGCTRL_ATYPE_RPL %08x %08x\n", mystique->dwgreg.dwgctrl_running & DWGCTRL_BLTMOD_MASK, mystique->dwgreg.dwgctrl_running); + break; + } + break; + + default: + fatal("Unknown IDUMP atype %03x %08x\n", mystique->dwgreg.dwgctrl_running & DWGCTRL_ATYPE_MASK, mystique->dwgreg.dwgctrl_running); } return val; } - static uint32_t blit_idump_read(mystique_t *mystique) { uint32_t ret = 0xffffffff; switch (mystique->dwgreg.dwgctrl_running & DWGCTRL_OPCODE_MASK) { - case DWGCTRL_OPCODE_IDUMP: - ret = blit_idump_idump(mystique); - break; + case DWGCTRL_OPCODE_IDUMP: + ret = blit_idump_idump(mystique); + break; - default: - /* pclog("blit_idump_read: bad opcode %08x\n", mystique->dwgreg.dwgctrl_running); */ - break; + default: + /* pclog("blit_idump_read: bad opcode %08x\n", mystique->dwgreg.dwgctrl_running); */ + break; } return ret; @@ -2887,1978 +3163,1961 @@ blit_idump_read(mystique_t *mystique) static void blit_fbitblt(mystique_t *mystique) { - svga_t *svga = &mystique->svga; - uint32_t src_addr; - int y; - int x_dir = mystique->dwgreg.sgn.scanleft ? -1 : 1; - int16_t x_start = mystique->dwgreg.sgn.scanleft ? mystique->dwgreg.fxright : mystique->dwgreg.fxleft; - int16_t x_end = mystique->dwgreg.sgn.scanleft ? mystique->dwgreg.fxleft : mystique->dwgreg.fxright; + svga_t *svga = &mystique->svga; + uint32_t src_addr; + int x_dir = mystique->dwgreg.sgn.scanleft ? -1 : 1; + int16_t x_start = mystique->dwgreg.sgn.scanleft ? mystique->dwgreg.fxright : mystique->dwgreg.fxleft; + int16_t x_end = mystique->dwgreg.sgn.scanleft ? mystique->dwgreg.fxleft : mystique->dwgreg.fxright; - src_addr = mystique->dwgreg.ar[3]; + src_addr = mystique->dwgreg.ar[3]; - for (y = 0; y < mystique->dwgreg.length; y++) - { - int16_t x = x_start; - while (1) - { - if (x >= mystique->dwgreg.cxleft && x <= mystique->dwgreg.cxright && - mystique->dwgreg.ydst_lin >= mystique->dwgreg.ytop && mystique->dwgreg.ydst_lin <= mystique->dwgreg.ybot) - { - uint32_t src, old_dst; + for (uint16_t y = 0; y < mystique->dwgreg.length; y++) { + int16_t x = x_start; + while (1) { + if (x >= mystique->dwgreg.cxleft && x <= mystique->dwgreg.cxright && mystique->dwgreg.ydst_lin >= mystique->dwgreg.ytop && mystique->dwgreg.ydst_lin <= mystique->dwgreg.ybot) { + uint32_t src; + uint32_t old_dst; - switch (mystique->maccess_running & MACCESS_PWIDTH_MASK) - { - case MACCESS_PWIDTH_8: - src = svga->vram[src_addr & mystique->vram_mask]; + switch (mystique->maccess_running & MACCESS_PWIDTH_MASK) { + case MACCESS_PWIDTH_8: + src = svga->vram[src_addr & mystique->vram_mask]; - svga->vram[(mystique->dwgreg.ydst_lin + x) & mystique->vram_mask] = src; - svga->changedvram[((mystique->dwgreg.ydst_lin + x) & mystique->vram_mask) >> 12] = changeframecount; - break; + svga->vram[(mystique->dwgreg.ydst_lin + x) & mystique->vram_mask] = src; + svga->changedvram[((mystique->dwgreg.ydst_lin + x) & mystique->vram_mask) >> 12] = changeframecount; + break; - case MACCESS_PWIDTH_16: - src = ((uint16_t *)svga->vram)[src_addr & mystique->vram_mask_w]; + case MACCESS_PWIDTH_16: + src = ((uint16_t *) svga->vram)[src_addr & mystique->vram_mask_w]; - ((uint16_t *)svga->vram)[(mystique->dwgreg.ydst_lin + x) & mystique->vram_mask_w] = src; - svga->changedvram[((mystique->dwgreg.ydst_lin + x) & mystique->vram_mask_w) >> 11] = changeframecount; - break; + ((uint16_t *) svga->vram)[(mystique->dwgreg.ydst_lin + x) & mystique->vram_mask_w] = src; + svga->changedvram[((mystique->dwgreg.ydst_lin + x) & mystique->vram_mask_w) >> 11] = changeframecount; + break; - case MACCESS_PWIDTH_24: - src = *(uint32_t *)&svga->vram[(src_addr * 3) & mystique->vram_mask]; - old_dst = *(uint32_t *)&svga->vram[((mystique->dwgreg.ydst_lin + x) * 3) & mystique->vram_mask]; + case MACCESS_PWIDTH_24: + src = *(uint32_t *) &svga->vram[(src_addr * 3) & mystique->vram_mask]; + old_dst = *(uint32_t *) &svga->vram[((mystique->dwgreg.ydst_lin + x) * 3) & mystique->vram_mask]; - *(uint32_t *)&svga->vram[((mystique->dwgreg.ydst_lin + x) * 3) & mystique->vram_mask] = (src & 0xffffff) | (old_dst & 0xff000000); - svga->changedvram[(((mystique->dwgreg.ydst_lin + x) * 3) & mystique->vram_mask) >> 12] = changeframecount; - break; + *(uint32_t *) &svga->vram[((mystique->dwgreg.ydst_lin + x) * 3) & mystique->vram_mask] = (src & 0xffffff) | (old_dst & 0xff000000); + svga->changedvram[(((mystique->dwgreg.ydst_lin + x) * 3) & mystique->vram_mask) >> 12] = changeframecount; + break; - case MACCESS_PWIDTH_32: - src = ((uint32_t *)svga->vram)[src_addr & mystique->vram_mask_l]; + case MACCESS_PWIDTH_32: + src = ((uint32_t *) svga->vram)[src_addr & mystique->vram_mask_l]; - ((uint32_t *)svga->vram)[(mystique->dwgreg.ydst_lin + x) & mystique->vram_mask_l] = src; - svga->changedvram[((mystique->dwgreg.ydst_lin + x) & mystique->vram_mask_l) >> 10] = changeframecount; - break; + ((uint32_t *) svga->vram)[(mystique->dwgreg.ydst_lin + x) & mystique->vram_mask_l] = src; + svga->changedvram[((mystique->dwgreg.ydst_lin + x) & mystique->vram_mask_l) >> 10] = changeframecount; + break; - default: - fatal("BITBLT RPL BFCOL PWIDTH %x %08x\n", mystique->maccess_running & MACCESS_PWIDTH_MASK, mystique->dwgreg.dwgctrl_running); - } - } - - if (src_addr == mystique->dwgreg.ar[0]) - { - mystique->dwgreg.ar[0] += mystique->dwgreg.ar[5]; - mystique->dwgreg.ar[3] += mystique->dwgreg.ar[5]; - src_addr = mystique->dwgreg.ar[3]; - break; - } - else - src_addr += x_dir; - - if (x != x_end) - x += x_dir; - else - break; + default: + fatal("BITBLT RPL BFCOL PWIDTH %x %08x\n", mystique->maccess_running & MACCESS_PWIDTH_MASK, mystique->dwgreg.dwgctrl_running); } + } - if (mystique->dwgreg.sgn.sdy) - mystique->dwgreg.ydst_lin -= (mystique->dwgreg.pitch & PITCH_MASK); - else - mystique->dwgreg.ydst_lin += (mystique->dwgreg.pitch & PITCH_MASK); + if (src_addr == mystique->dwgreg.ar[0]) { + mystique->dwgreg.ar[0] += mystique->dwgreg.ar[5]; + mystique->dwgreg.ar[3] += mystique->dwgreg.ar[5]; + src_addr = mystique->dwgreg.ar[3]; + break; + } else + src_addr += x_dir; + + if (x != x_end) + x += x_dir; + else + break; } - mystique->blitter_complete_refcount++; + if (mystique->dwgreg.sgn.sdy) + mystique->dwgreg.ydst_lin -= (mystique->dwgreg.pitch & PITCH_MASK); + else + mystique->dwgreg.ydst_lin += (mystique->dwgreg.pitch & PITCH_MASK); + } + + mystique->blitter_complete_refcount++; } static void blit_iload_iload(mystique_t *mystique, uint32_t data, int size) { - svga_t *svga = &mystique->svga; - uint32_t src, dst; - uint32_t dst2; - uint64_t data64; - int min_size = 8; - uint32_t bltckey = mystique->dwgreg.fcol, bltcmsk = mystique->dwgreg.bcol; - const int transc = mystique->dwgreg.dwgctrl_running & DWGCTRL_TRANSC; - const int trans_sel = (mystique->dwgreg.dwgctrl_running & DWGCTRL_TRANS_MASK) >> DWGCTRL_TRANS_SHIFT; - uint8_t const * const trans = &trans_masks[trans_sel][(mystique->dwgreg.selline & 3) * 4]; - uint32_t data_mask = 1; + svga_t *svga = &mystique->svga; + uint32_t src; + uint32_t dst; + uint32_t dst2; + uint64_t data64; + int min_size = 8; + uint32_t bltckey = mystique->dwgreg.fcol; + uint32_t bltcmsk = mystique->dwgreg.bcol; + const int transc = mystique->dwgreg.dwgctrl_running & DWGCTRL_TRANSC; + const int trans_sel = (mystique->dwgreg.dwgctrl_running & DWGCTRL_TRANS_MASK) >> DWGCTRL_TRANS_SHIFT; + uint8_t const *const trans = &trans_masks[trans_sel][(mystique->dwgreg.selline & 3) * 4]; + uint32_t data_mask = 1; switch (mystique->maccess_running & MACCESS_PWIDTH_MASK) { - case MACCESS_PWIDTH_8: - bltckey &= 0xff; - bltcmsk &= 0xff; - break; - case MACCESS_PWIDTH_16: - bltckey &= 0xffff; - bltcmsk &= 0xffff; - break; + case MACCESS_PWIDTH_8: + bltckey &= 0xff; + bltcmsk &= 0xff; + break; + case MACCESS_PWIDTH_16: + bltckey &= 0xffff; + bltcmsk &= 0xffff; + break; } mystique->dwgreg.words++; switch (mystique->dwgreg.dwgctrl_running & DWGCTRL_ATYPE_MASK) { - case DWGCTRL_ATYPE_RPL: - if (mystique->maccess_running & MACCESS_TLUTLOAD) { - while ((mystique->dwgreg.length_cur > 0) && (size >= 16)) { - uint16_t src = data & 0xffff; + case DWGCTRL_ATYPE_RPL: + if (mystique->maccess_running & MACCESS_TLUTLOAD) { + while ((mystique->dwgreg.length_cur > 0) && (size >= 16)) { + uint16_t src = data & 0xffff; - mystique->lut[mystique->dwgreg.ydst & 0xff].r = (src >> 11) << 3; - mystique->lut[mystique->dwgreg.ydst & 0xff].g = ((src >> 5) & 0x3f) << 2; - mystique->lut[mystique->dwgreg.ydst & 0xff].b = (src & 0x1f) << 3; - mystique->dwgreg.ydst++; - mystique->dwgreg.length_cur--; - data >>= 16; - size -= 16; - } + mystique->lut[mystique->dwgreg.ydst & 0xff].r = (src >> 11) << 3; + mystique->lut[mystique->dwgreg.ydst & 0xff].g = ((src >> 5) & 0x3f) << 2; + mystique->lut[mystique->dwgreg.ydst & 0xff].b = (src & 0x1f) << 3; + mystique->dwgreg.ydst++; + mystique->dwgreg.length_cur--; + data >>= 16; + size -= 16; + } - if (!mystique->dwgreg.length_cur) { - mystique->busy = 0; - mystique->blitter_complete_refcount++; - } - break; - } - case DWGCTRL_ATYPE_RSTR: - case DWGCTRL_ATYPE_BLK: - switch (mystique->dwgreg.dwgctrl_running & DWGCTRL_BLTMOD_MASK) { - case DWGCTRL_BLTMOD_BFCOL: - size += mystique->dwgreg.iload_rem_count; - data64 = mystique->dwgreg.iload_rem_data | ((uint64_t)data << mystique->dwgreg.iload_rem_count); + if (!mystique->dwgreg.length_cur) { + mystique->busy = 0; + mystique->blitter_complete_refcount++; + } + break; + } + case DWGCTRL_ATYPE_RSTR: + case DWGCTRL_ATYPE_BLK: + switch (mystique->dwgreg.dwgctrl_running & DWGCTRL_BLTMOD_MASK) { + case DWGCTRL_BLTMOD_BFCOL: + size += mystique->dwgreg.iload_rem_count; + data64 = mystique->dwgreg.iload_rem_data | ((uint64_t) data << mystique->dwgreg.iload_rem_count); - switch (mystique->maccess_running & MACCESS_PWIDTH_MASK) { - case MACCESS_PWIDTH_8: - min_size = 8; - break; - case MACCESS_PWIDTH_16: - min_size = 16; - break; - case MACCESS_PWIDTH_24: - min_size = 24; - break; - case MACCESS_PWIDTH_32: - min_size = 32; - break; - } + switch (mystique->maccess_running & MACCESS_PWIDTH_MASK) { + case MACCESS_PWIDTH_8: + min_size = 8; + break; + case MACCESS_PWIDTH_16: + min_size = 16; + break; + case MACCESS_PWIDTH_24: + min_size = 24; + break; + case MACCESS_PWIDTH_32: + min_size = 32; + break; - while (size >= min_size) { - int draw = (!transc || (data & bltcmsk) != bltckey) && trans[mystique->dwgreg.xdst & 3]; + default: + break; + } - switch (mystique->maccess_running & MACCESS_PWIDTH_MASK) { - case MACCESS_PWIDTH_8: - if (mystique->dwgreg.xdst >= mystique->dwgreg.cxleft && mystique->dwgreg.xdst <= mystique->dwgreg.cxright && - mystique->dwgreg.ydst_lin >= mystique->dwgreg.ytop && mystique->dwgreg.ydst_lin <= mystique->dwgreg.ybot && draw) { - dst = svga->vram[(mystique->dwgreg.ydst_lin + mystique->dwgreg.xdst) & mystique->vram_mask]; + while (size >= min_size) { + int draw = (!transc || (data & bltcmsk) != bltckey) && trans[mystique->dwgreg.xdst & 3]; - dst = bitop(data & 0xff, dst, mystique->dwgreg.dwgctrl_running); - svga->vram[(mystique->dwgreg.ydst_lin + mystique->dwgreg.xdst) & mystique->vram_mask] = dst; - svga->changedvram[((mystique->dwgreg.ydst_lin + mystique->dwgreg.xdst) & mystique->vram_mask) >> 12] = changeframecount; - } + switch (mystique->maccess_running & MACCESS_PWIDTH_MASK) { + case MACCESS_PWIDTH_8: + if (mystique->dwgreg.xdst >= mystique->dwgreg.cxleft && mystique->dwgreg.xdst <= mystique->dwgreg.cxright && mystique->dwgreg.ydst_lin >= mystique->dwgreg.ytop && mystique->dwgreg.ydst_lin <= mystique->dwgreg.ybot && draw) { + dst = svga->vram[(mystique->dwgreg.ydst_lin + mystique->dwgreg.xdst) & mystique->vram_mask]; - data >>= 8; - size -= 8; - break; + dst = bitop(data & 0xff, dst, mystique->dwgreg.dwgctrl_running); + svga->vram[(mystique->dwgreg.ydst_lin + mystique->dwgreg.xdst) & mystique->vram_mask] = dst; + svga->changedvram[((mystique->dwgreg.ydst_lin + mystique->dwgreg.xdst) & mystique->vram_mask) >> 12] = changeframecount; + } - case MACCESS_PWIDTH_16: - if (mystique->dwgreg.xdst >= mystique->dwgreg.cxleft && mystique->dwgreg.xdst <= mystique->dwgreg.cxright && - mystique->dwgreg.ydst_lin >= mystique->dwgreg.ytop && mystique->dwgreg.ydst_lin <= mystique->dwgreg.ybot && draw) { - dst = ((uint16_t *)svga->vram)[(mystique->dwgreg.ydst_lin + mystique->dwgreg.xdst) & mystique->vram_mask_w]; + data >>= 8; + size -= 8; + break; - dst = bitop(data & 0xffff, dst, mystique->dwgreg.dwgctrl_running); - ((uint16_t *)svga->vram)[(mystique->dwgreg.ydst_lin + mystique->dwgreg.xdst) & mystique->vram_mask_w] = dst; - svga->changedvram[((mystique->dwgreg.ydst_lin + mystique->dwgreg.xdst) & mystique->vram_mask_w) >> 11] = changeframecount; - } + case MACCESS_PWIDTH_16: + if (mystique->dwgreg.xdst >= mystique->dwgreg.cxleft && mystique->dwgreg.xdst <= mystique->dwgreg.cxright && mystique->dwgreg.ydst_lin >= mystique->dwgreg.ytop && mystique->dwgreg.ydst_lin <= mystique->dwgreg.ybot && draw) { + dst = ((uint16_t *) svga->vram)[(mystique->dwgreg.ydst_lin + mystique->dwgreg.xdst) & mystique->vram_mask_w]; - data >>= 16; - size -= 16; - break; + dst = bitop(data & 0xffff, dst, mystique->dwgreg.dwgctrl_running); + ((uint16_t *) svga->vram)[(mystique->dwgreg.ydst_lin + mystique->dwgreg.xdst) & mystique->vram_mask_w] = dst; + svga->changedvram[((mystique->dwgreg.ydst_lin + mystique->dwgreg.xdst) & mystique->vram_mask_w) >> 11] = changeframecount; + } - case MACCESS_PWIDTH_24: - if (mystique->dwgreg.xdst >= mystique->dwgreg.cxleft && mystique->dwgreg.xdst <= mystique->dwgreg.cxright && - mystique->dwgreg.ydst_lin >= mystique->dwgreg.ytop && mystique->dwgreg.ydst_lin <= mystique->dwgreg.ybot) { - uint32_t old_dst = *((uint32_t *)&svga->vram[((mystique->dwgreg.ydst_lin + mystique->dwgreg.xdst) * 3) & mystique->vram_mask]); + data >>= 16; + size -= 16; + break; - dst = bitop(data64, old_dst, mystique->dwgreg.dwgctrl_running); - *((uint32_t *)&svga->vram[((mystique->dwgreg.ydst_lin + mystique->dwgreg.xdst) * 3) & mystique->vram_mask]) = (dst & 0xffffff) | (old_dst & 0xff000000); - svga->changedvram[(((mystique->dwgreg.ydst_lin + mystique->dwgreg.xdst) * 3) & mystique->vram_mask) >> 12] = changeframecount; - } + case MACCESS_PWIDTH_24: + if (mystique->dwgreg.xdst >= mystique->dwgreg.cxleft && mystique->dwgreg.xdst <= mystique->dwgreg.cxright && mystique->dwgreg.ydst_lin >= mystique->dwgreg.ytop && mystique->dwgreg.ydst_lin <= mystique->dwgreg.ybot) { + uint32_t old_dst = *((uint32_t *) &svga->vram[((mystique->dwgreg.ydst_lin + mystique->dwgreg.xdst) * 3) & mystique->vram_mask]); - data64 >>= 24; - size -= 24; - break; + dst = bitop(data64, old_dst, mystique->dwgreg.dwgctrl_running); + *((uint32_t *) &svga->vram[((mystique->dwgreg.ydst_lin + mystique->dwgreg.xdst) * 3) & mystique->vram_mask]) = (dst & 0xffffff) | (old_dst & 0xff000000); + svga->changedvram[(((mystique->dwgreg.ydst_lin + mystique->dwgreg.xdst) * 3) & mystique->vram_mask) >> 12] = changeframecount; + } - case MACCESS_PWIDTH_32: - if (mystique->dwgreg.xdst >= mystique->dwgreg.cxleft && mystique->dwgreg.xdst <= mystique->dwgreg.cxright && - mystique->dwgreg.ydst_lin >= mystique->dwgreg.ytop && mystique->dwgreg.ydst_lin <= mystique->dwgreg.ybot && draw) { - dst = ((uint32_t *)svga->vram)[(mystique->dwgreg.ydst_lin + mystique->dwgreg.xdst) & mystique->vram_mask_l]; + data64 >>= 24; + size -= 24; + break; - dst = bitop(data, dst, mystique->dwgreg.dwgctrl_running); - ((uint32_t *)svga->vram)[(mystique->dwgreg.ydst_lin + mystique->dwgreg.xdst) & mystique->vram_mask_l] = dst; - svga->changedvram[((mystique->dwgreg.ydst_lin + mystique->dwgreg.xdst) & mystique->vram_mask_l) >> 10] = changeframecount; - } + case MACCESS_PWIDTH_32: + if (mystique->dwgreg.xdst >= mystique->dwgreg.cxleft && mystique->dwgreg.xdst <= mystique->dwgreg.cxright && mystique->dwgreg.ydst_lin >= mystique->dwgreg.ytop && mystique->dwgreg.ydst_lin <= mystique->dwgreg.ybot && draw) { + dst = ((uint32_t *) svga->vram)[(mystique->dwgreg.ydst_lin + mystique->dwgreg.xdst) & mystique->vram_mask_l]; - size = 0; - break; + dst = bitop(data, dst, mystique->dwgreg.dwgctrl_running); + ((uint32_t *) svga->vram)[(mystique->dwgreg.ydst_lin + mystique->dwgreg.xdst) & mystique->vram_mask_l] = dst; + svga->changedvram[((mystique->dwgreg.ydst_lin + mystique->dwgreg.xdst) & mystique->vram_mask_l) >> 10] = changeframecount; + } - default: - fatal("ILOAD RSTR/RPL BFCOL pwidth %08x\n", mystique->maccess_running & MACCESS_PWIDTH_MASK); - } + size = 0; + break; - if (mystique->dwgreg.xdst == mystique->dwgreg.fxright) { - mystique->dwgreg.xdst = mystique->dwgreg.fxleft; - mystique->dwgreg.ydst_lin += (mystique->dwgreg.pitch & PITCH_MASK); - mystique->dwgreg.selline = (mystique->dwgreg.selline + 1) & 7; - mystique->dwgreg.length_cur--; - if (!mystique->dwgreg.length_cur) { - mystique->busy = 0; - mystique->blitter_complete_refcount++; - break; - } - data64 = 0; - size = 0; - break; - } else - mystique->dwgreg.xdst = (mystique->dwgreg.xdst + 1) & 0xffff; - } - mystique->dwgreg.iload_rem_count = size; - mystique->dwgreg.iload_rem_data = data64; - break; + default: + fatal("ILOAD RSTR/RPL BFCOL pwidth %08x\n", mystique->maccess_running & MACCESS_PWIDTH_MASK); + } - case DWGCTRL_BLTMOD_BMONOWF: - data = (data >> 24) | ((data & 0x00ff0000) >> 8) | ((data & 0x0000ff00) << 8) | (data << 24); - data_mask = (1 << 31); - case DWGCTRL_BLTMOD_BMONOLEF: - while (size) { - if (mystique->dwgreg.xdst >= mystique->dwgreg.cxleft && mystique->dwgreg.xdst <= mystique->dwgreg.cxright && - mystique->dwgreg.ydst_lin >= mystique->dwgreg.ytop && mystique->dwgreg.ydst_lin <= mystique->dwgreg.ybot && - ((data & data_mask) || !(mystique->dwgreg.dwgctrl_running & DWGCTRL_TRANSC)) && - trans[mystique->dwgreg.xdst & 3]) { - uint32_t old_dst; + if (mystique->dwgreg.xdst == mystique->dwgreg.fxright) { + mystique->dwgreg.xdst = mystique->dwgreg.fxleft; + mystique->dwgreg.ydst_lin += (mystique->dwgreg.pitch & PITCH_MASK); + mystique->dwgreg.selline = (mystique->dwgreg.selline + 1) & 7; + mystique->dwgreg.length_cur--; + if (!mystique->dwgreg.length_cur) { + mystique->busy = 0; + mystique->blitter_complete_refcount++; + break; + } + data64 = 0; + size = 0; + break; + } else + mystique->dwgreg.xdst = (mystique->dwgreg.xdst + 1) & 0xffff; + } + mystique->dwgreg.iload_rem_count = size; + mystique->dwgreg.iload_rem_data = data64; + break; - src = (data & data_mask) ? mystique->dwgreg.fcol : mystique->dwgreg.bcol; - switch (mystique->maccess_running & MACCESS_PWIDTH_MASK) { - case MACCESS_PWIDTH_8: - dst = svga->vram[(mystique->dwgreg.ydst_lin + mystique->dwgreg.xdst) & mystique->vram_mask]; + case DWGCTRL_BLTMOD_BMONOWF: + data = (data >> 24) | ((data & 0x00ff0000) >> 8) | ((data & 0x0000ff00) << 8) | (data << 24); + data_mask = (1 << 31); + case DWGCTRL_BLTMOD_BMONOLEF: + while (size) { + if (mystique->dwgreg.xdst >= mystique->dwgreg.cxleft && mystique->dwgreg.xdst <= mystique->dwgreg.cxright && mystique->dwgreg.ydst_lin >= mystique->dwgreg.ytop && mystique->dwgreg.ydst_lin <= mystique->dwgreg.ybot && ((data & data_mask) || !(mystique->dwgreg.dwgctrl_running & DWGCTRL_TRANSC)) && trans[mystique->dwgreg.xdst & 3]) { + uint32_t old_dst; - dst = bitop(src, dst, mystique->dwgreg.dwgctrl_running); + src = (data & data_mask) ? mystique->dwgreg.fcol : mystique->dwgreg.bcol; + switch (mystique->maccess_running & MACCESS_PWIDTH_MASK) { + case MACCESS_PWIDTH_8: + dst = svga->vram[(mystique->dwgreg.ydst_lin + mystique->dwgreg.xdst) & mystique->vram_mask]; - svga->vram[(mystique->dwgreg.ydst_lin + mystique->dwgreg.xdst) & mystique->vram_mask] = dst; - svga->changedvram[((mystique->dwgreg.ydst_lin + mystique->dwgreg.xdst) & mystique->vram_mask) >> 12] = changeframecount; - break; + dst = bitop(src, dst, mystique->dwgreg.dwgctrl_running); - case MACCESS_PWIDTH_16: - dst = ((uint16_t *)svga->vram)[(mystique->dwgreg.ydst_lin + mystique->dwgreg.xdst) & mystique->vram_mask_w]; + svga->vram[(mystique->dwgreg.ydst_lin + mystique->dwgreg.xdst) & mystique->vram_mask] = dst; + svga->changedvram[((mystique->dwgreg.ydst_lin + mystique->dwgreg.xdst) & mystique->vram_mask) >> 12] = changeframecount; + break; - dst = bitop(src, dst, mystique->dwgreg.dwgctrl_running); + case MACCESS_PWIDTH_16: + dst = ((uint16_t *) svga->vram)[(mystique->dwgreg.ydst_lin + mystique->dwgreg.xdst) & mystique->vram_mask_w]; - ((uint16_t *)svga->vram)[(mystique->dwgreg.ydst_lin + mystique->dwgreg.xdst) & mystique->vram_mask_w] = dst; - svga->changedvram[((mystique->dwgreg.ydst_lin + mystique->dwgreg.xdst) & mystique->vram_mask_w) >> 11] = changeframecount; - break; + dst = bitop(src, dst, mystique->dwgreg.dwgctrl_running); - case MACCESS_PWIDTH_24: - old_dst = *(uint32_t *)&svga->vram[((mystique->dwgreg.ydst_lin + mystique->dwgreg.xdst) * 3) & mystique->vram_mask]; + ((uint16_t *) svga->vram)[(mystique->dwgreg.ydst_lin + mystique->dwgreg.xdst) & mystique->vram_mask_w] = dst; + svga->changedvram[((mystique->dwgreg.ydst_lin + mystique->dwgreg.xdst) & mystique->vram_mask_w) >> 11] = changeframecount; + break; - dst = bitop(src, old_dst, mystique->dwgreg.dwgctrl_running); + case MACCESS_PWIDTH_24: + old_dst = *(uint32_t *) &svga->vram[((mystique->dwgreg.ydst_lin + mystique->dwgreg.xdst) * 3) & mystique->vram_mask]; - *(uint32_t *)&svga->vram[((mystique->dwgreg.ydst_lin + mystique->dwgreg.xdst) * 3) & mystique->vram_mask] = (dst & 0xffffff) | (old_dst & 0xff000000); - svga->changedvram[(((mystique->dwgreg.ydst_lin + mystique->dwgreg.xdst) * 3) & mystique->vram_mask) >> 12] = changeframecount; - break; + dst = bitop(src, old_dst, mystique->dwgreg.dwgctrl_running); - case MACCESS_PWIDTH_32: - dst = ((uint32_t *)svga->vram)[(mystique->dwgreg.ydst_lin + mystique->dwgreg.xdst) & mystique->vram_mask_l]; + *(uint32_t *) &svga->vram[((mystique->dwgreg.ydst_lin + mystique->dwgreg.xdst) * 3) & mystique->vram_mask] = (dst & 0xffffff) | (old_dst & 0xff000000); + svga->changedvram[(((mystique->dwgreg.ydst_lin + mystique->dwgreg.xdst) * 3) & mystique->vram_mask) >> 12] = changeframecount; + break; - dst = bitop(src, dst, mystique->dwgreg.dwgctrl_running); + case MACCESS_PWIDTH_32: + dst = ((uint32_t *) svga->vram)[(mystique->dwgreg.ydst_lin + mystique->dwgreg.xdst) & mystique->vram_mask_l]; - ((uint32_t *)svga->vram)[(mystique->dwgreg.ydst_lin + mystique->dwgreg.xdst) & mystique->vram_mask_l] = dst; - svga->changedvram[((mystique->dwgreg.ydst_lin + mystique->dwgreg.xdst) & mystique->vram_mask_l) >> 10] = changeframecount; - break; + dst = bitop(src, dst, mystique->dwgreg.dwgctrl_running); - default: - fatal("ILOAD RSTR/RPL BMONOWF pwidth %08x\n", mystique->maccess_running & MACCESS_PWIDTH_MASK); - } - } + ((uint32_t *) svga->vram)[(mystique->dwgreg.ydst_lin + mystique->dwgreg.xdst) & mystique->vram_mask_l] = dst; + svga->changedvram[((mystique->dwgreg.ydst_lin + mystique->dwgreg.xdst) & mystique->vram_mask_l) >> 10] = changeframecount; + break; - if (mystique->dwgreg.xdst == mystique->dwgreg.fxright) { - mystique->dwgreg.xdst = mystique->dwgreg.fxleft; - mystique->dwgreg.ydst_lin += (mystique->dwgreg.pitch & PITCH_MASK); - mystique->dwgreg.length_cur--; - if (!mystique->dwgreg.length_cur) { - mystique->busy = 0; - mystique->blitter_complete_refcount++; - break; - } - if (!(mystique->dwgreg.dwgctrl_running & DWGCTRL_LINEAR)) - break; - } else - mystique->dwgreg.xdst = (mystique->dwgreg.xdst + 1) & 0xffff; - if (data_mask == 1) - data >>= 1; - else - data <<= 1; - size--; - } - break; + default: + fatal("ILOAD RSTR/RPL BMONOWF pwidth %08x\n", mystique->maccess_running & MACCESS_PWIDTH_MASK); + } + } - case DWGCTRL_BLTMOD_BU24RGB: - size += mystique->dwgreg.iload_rem_count; - data64 = mystique->dwgreg.iload_rem_data | ((uint64_t)data << mystique->dwgreg.iload_rem_count); + if (mystique->dwgreg.xdst == mystique->dwgreg.fxright) { + mystique->dwgreg.xdst = mystique->dwgreg.fxleft; + mystique->dwgreg.ydst_lin += (mystique->dwgreg.pitch & PITCH_MASK); + mystique->dwgreg.length_cur--; + if (!mystique->dwgreg.length_cur) { + mystique->busy = 0; + mystique->blitter_complete_refcount++; + break; + } + if (!(mystique->dwgreg.dwgctrl_running & DWGCTRL_LINEAR)) + break; + } else + mystique->dwgreg.xdst = (mystique->dwgreg.xdst + 1) & 0xffff; + if (data_mask == 1) + data >>= 1; + else + data <<= 1; + size--; + } + break; - while (size >= 24) { - if (mystique->dwgreg.xdst >= mystique->dwgreg.cxleft && mystique->dwgreg.xdst <= mystique->dwgreg.cxright && - mystique->dwgreg.ydst_lin >= mystique->dwgreg.ytop && mystique->dwgreg.ydst_lin <= mystique->dwgreg.ybot) { - switch (mystique->maccess_running & MACCESS_PWIDTH_MASK) { - case MACCESS_PWIDTH_32: - dst = ((uint32_t *)svga->vram)[(mystique->dwgreg.ydst_lin + mystique->dwgreg.xdst) & mystique->vram_mask_l]; + case DWGCTRL_BLTMOD_BU24RGB: + size += mystique->dwgreg.iload_rem_count; + data64 = mystique->dwgreg.iload_rem_data | ((uint64_t) data << mystique->dwgreg.iload_rem_count); - dst = bitop(data64 & 0xffffff, dst, mystique->dwgreg.dwgctrl_running); + while (size >= 24) { + if (mystique->dwgreg.xdst >= mystique->dwgreg.cxleft && mystique->dwgreg.xdst <= mystique->dwgreg.cxright && mystique->dwgreg.ydst_lin >= mystique->dwgreg.ytop && mystique->dwgreg.ydst_lin <= mystique->dwgreg.ybot) { + switch (mystique->maccess_running & MACCESS_PWIDTH_MASK) { + case MACCESS_PWIDTH_32: + dst = ((uint32_t *) svga->vram)[(mystique->dwgreg.ydst_lin + mystique->dwgreg.xdst) & mystique->vram_mask_l]; - ((uint32_t *)svga->vram)[(mystique->dwgreg.ydst_lin + mystique->dwgreg.xdst) & mystique->vram_mask_l] = dst; - svga->changedvram[((mystique->dwgreg.ydst_lin + mystique->dwgreg.xdst) & mystique->vram_mask_l) >> 10] = changeframecount; - break; + dst = bitop(data64 & 0xffffff, dst, mystique->dwgreg.dwgctrl_running); - default: - fatal("ILOAD RSTR/RPL BU24RGB pwidth %08x\n", mystique->maccess_running & MACCESS_PWIDTH_MASK); - } - } + ((uint32_t *) svga->vram)[(mystique->dwgreg.ydst_lin + mystique->dwgreg.xdst) & mystique->vram_mask_l] = dst; + svga->changedvram[((mystique->dwgreg.ydst_lin + mystique->dwgreg.xdst) & mystique->vram_mask_l) >> 10] = changeframecount; + break; - data64 >>= 24; - size -= 24; - if (mystique->dwgreg.xdst == mystique->dwgreg.fxright) { - mystique->dwgreg.xdst = mystique->dwgreg.fxleft; - mystique->dwgreg.ydst_lin += (mystique->dwgreg.pitch & PITCH_MASK); - mystique->dwgreg.length_cur--; - if (!mystique->dwgreg.length_cur) { - mystique->busy = 0; - mystique->blitter_complete_refcount++; - break; - } - data64 = 0; - size = 0; - break; - } else - mystique->dwgreg.xdst = (mystique->dwgreg.xdst + 1) & 0xffff; - } + default: + fatal("ILOAD RSTR/RPL BU24RGB pwidth %08x\n", mystique->maccess_running & MACCESS_PWIDTH_MASK); + } + } - mystique->dwgreg.iload_rem_count = size; - mystique->dwgreg.iload_rem_data = data64; - break; + data64 >>= 24; + size -= 24; + if (mystique->dwgreg.xdst == mystique->dwgreg.fxright) { + mystique->dwgreg.xdst = mystique->dwgreg.fxleft; + mystique->dwgreg.ydst_lin += (mystique->dwgreg.pitch & PITCH_MASK); + mystique->dwgreg.length_cur--; + if (!mystique->dwgreg.length_cur) { + mystique->busy = 0; + mystique->blitter_complete_refcount++; + break; + } + data64 = 0; + size = 0; + break; + } else + mystique->dwgreg.xdst = (mystique->dwgreg.xdst + 1) & 0xffff; + } - case DWGCTRL_BLTMOD_BU32RGB: - size += mystique->dwgreg.iload_rem_count; - data64 = mystique->dwgreg.iload_rem_data | ((uint64_t)data << mystique->dwgreg.iload_rem_count); - while (size >= 32) - { - int draw = (!transc || (data & bltcmsk) != bltckey) && trans[mystique->dwgreg.xdst & 3]; + mystique->dwgreg.iload_rem_count = size; + mystique->dwgreg.iload_rem_data = data64; + break; - if (mystique->dwgreg.xdst >= mystique->dwgreg.cxleft && mystique->dwgreg.xdst <= mystique->dwgreg.cxright && - mystique->dwgreg.ydst_lin >= mystique->dwgreg.ytop && mystique->dwgreg.ydst_lin <= mystique->dwgreg.ybot && draw) - { - dst = ((uint32_t *)svga->vram)[(mystique->dwgreg.ydst_lin + mystique->dwgreg.xdst) & mystique->vram_mask_l]; + case DWGCTRL_BLTMOD_BU32RGB: + size += mystique->dwgreg.iload_rem_count; + data64 = mystique->dwgreg.iload_rem_data | ((uint64_t) data << mystique->dwgreg.iload_rem_count); + while (size >= 32) { + int draw = (!transc || (data & bltcmsk) != bltckey) && trans[mystique->dwgreg.xdst & 3]; - dst = bitop(data, dst, mystique->dwgreg.dwgctrl_running); - ((uint32_t *)svga->vram)[(mystique->dwgreg.ydst_lin + mystique->dwgreg.xdst) & mystique->vram_mask_l] = dst; - svga->changedvram[((mystique->dwgreg.ydst_lin + mystique->dwgreg.xdst) & mystique->vram_mask_l) >> 10] = changeframecount; - } + if (mystique->dwgreg.xdst >= mystique->dwgreg.cxleft && mystique->dwgreg.xdst <= mystique->dwgreg.cxright && mystique->dwgreg.ydst_lin >= mystique->dwgreg.ytop && mystique->dwgreg.ydst_lin <= mystique->dwgreg.ybot && draw) { + dst = ((uint32_t *) svga->vram)[(mystique->dwgreg.ydst_lin + mystique->dwgreg.xdst) & mystique->vram_mask_l]; - size = 0; + dst = bitop(data, dst, mystique->dwgreg.dwgctrl_running); + ((uint32_t *) svga->vram)[(mystique->dwgreg.ydst_lin + mystique->dwgreg.xdst) & mystique->vram_mask_l] = dst; + svga->changedvram[((mystique->dwgreg.ydst_lin + mystique->dwgreg.xdst) & mystique->vram_mask_l) >> 10] = changeframecount; + } - if (mystique->dwgreg.xdst == mystique->dwgreg.fxright) - { - mystique->dwgreg.xdst = mystique->dwgreg.fxleft; - mystique->dwgreg.ydst_lin += (mystique->dwgreg.pitch & PITCH_MASK); - mystique->dwgreg.selline = (mystique->dwgreg.selline + 1) & 7; - mystique->dwgreg.length_cur--; - if (!mystique->dwgreg.length_cur) - { - mystique->busy = 0; - mystique->blitter_complete_refcount++; - break; - } - data64 = 0; - size = 0; - break; - } - else - mystique->dwgreg.xdst = (mystique->dwgreg.xdst + 1) & 0xffff; - } - mystique->dwgreg.iload_rem_count = size; - mystique->dwgreg.iload_rem_data = data64; - break; + size = 0; - case DWGCTRL_BLTMOD_BU32BGR: - size += mystique->dwgreg.iload_rem_count; - while (size >= 32) { - if (mystique->dwgreg.xdst >= mystique->dwgreg.cxleft && mystique->dwgreg.xdst <= mystique->dwgreg.cxright && - mystique->dwgreg.ydst_lin >= mystique->dwgreg.ytop && mystique->dwgreg.ydst_lin <= mystique->dwgreg.ybot) { - switch (mystique->maccess_running & MACCESS_PWIDTH_MASK) { - case MACCESS_PWIDTH_32: - dst = ((uint32_t *)svga->vram)[(mystique->dwgreg.ydst_lin + mystique->dwgreg.xdst) & mystique->vram_mask_l]; - dst2 = ((dst >> 16) & 0xff) | (dst & 0xff00) | ((dst & 0xff) << 16); /* BGR to RGB */ + if (mystique->dwgreg.xdst == mystique->dwgreg.fxright) { + mystique->dwgreg.xdst = mystique->dwgreg.fxleft; + mystique->dwgreg.ydst_lin += (mystique->dwgreg.pitch & PITCH_MASK); + mystique->dwgreg.selline = (mystique->dwgreg.selline + 1) & 7; + mystique->dwgreg.length_cur--; + if (!mystique->dwgreg.length_cur) { + mystique->busy = 0; + mystique->blitter_complete_refcount++; + break; + } + data64 = 0; + size = 0; + break; + } else + mystique->dwgreg.xdst = (mystique->dwgreg.xdst + 1) & 0xffff; + } + mystique->dwgreg.iload_rem_count = size; + mystique->dwgreg.iload_rem_data = data64; + break; - dst = bitop(data, dst2, mystique->dwgreg.dwgctrl_running); + case DWGCTRL_BLTMOD_BU32BGR: + size += mystique->dwgreg.iload_rem_count; + while (size >= 32) { + if (mystique->dwgreg.xdst >= mystique->dwgreg.cxleft && mystique->dwgreg.xdst <= mystique->dwgreg.cxright && mystique->dwgreg.ydst_lin >= mystique->dwgreg.ytop && mystique->dwgreg.ydst_lin <= mystique->dwgreg.ybot) { + switch (mystique->maccess_running & MACCESS_PWIDTH_MASK) { + case MACCESS_PWIDTH_32: + dst = ((uint32_t *) svga->vram)[(mystique->dwgreg.ydst_lin + mystique->dwgreg.xdst) & mystique->vram_mask_l]; + dst2 = ((dst >> 16) & 0xff) | (dst & 0xff00) | ((dst & 0xff) << 16); /* BGR to RGB */ - ((uint32_t *)svga->vram)[(mystique->dwgreg.ydst_lin + mystique->dwgreg.xdst) & mystique->vram_mask_l] = dst; - svga->changedvram[((mystique->dwgreg.ydst_lin + mystique->dwgreg.xdst) & mystique->vram_mask_l) >> 10] = changeframecount; - break; + dst = bitop(data, dst2, mystique->dwgreg.dwgctrl_running); - default: - fatal("ILOAD RSTR/RPL BU32RGB pwidth %08x\n", mystique->maccess_running & MACCESS_PWIDTH_MASK); - } - } + ((uint32_t *) svga->vram)[(mystique->dwgreg.ydst_lin + mystique->dwgreg.xdst) & mystique->vram_mask_l] = dst; + svga->changedvram[((mystique->dwgreg.ydst_lin + mystique->dwgreg.xdst) & mystique->vram_mask_l) >> 10] = changeframecount; + break; - size = 0; - if (mystique->dwgreg.xdst == mystique->dwgreg.fxright) { - mystique->dwgreg.xdst = mystique->dwgreg.fxleft; - mystique->dwgreg.ydst_lin += (mystique->dwgreg.pitch & PITCH_MASK); - mystique->dwgreg.length_cur--; - if (!mystique->dwgreg.length_cur) { - mystique->busy = 0; - mystique->blitter_complete_refcount++; - break; - } - break; - } else - mystique->dwgreg.xdst = (mystique->dwgreg.xdst + 1) & 0xffff; - } + default: + fatal("ILOAD RSTR/RPL BU32RGB pwidth %08x\n", mystique->maccess_running & MACCESS_PWIDTH_MASK); + } + } - mystique->dwgreg.iload_rem_count = size; - break; + size = 0; + if (mystique->dwgreg.xdst == mystique->dwgreg.fxright) { + mystique->dwgreg.xdst = mystique->dwgreg.fxleft; + mystique->dwgreg.ydst_lin += (mystique->dwgreg.pitch & PITCH_MASK); + mystique->dwgreg.length_cur--; + if (!mystique->dwgreg.length_cur) { + mystique->busy = 0; + mystique->blitter_complete_refcount++; + break; + } + break; + } else + mystique->dwgreg.xdst = (mystique->dwgreg.xdst + 1) & 0xffff; + } - default: - fatal("ILOAD DWGCTRL_ATYPE_RPL\n"); - break; - } - break; + mystique->dwgreg.iload_rem_count = size; + break; - default: - fatal("Unknown ILOAD iload atype %03x %08x\n", mystique->dwgreg.dwgctrl_running & DWGCTRL_ATYPE_MASK, mystique->dwgreg.dwgctrl_running); + default: + fatal("ILOAD DWGCTRL_ATYPE_RPL\n"); + break; + } + break; + + default: + fatal("Unknown ILOAD iload atype %03x %08x\n", mystique->dwgreg.dwgctrl_running & DWGCTRL_ATYPE_MASK, mystique->dwgreg.dwgctrl_running); } } - -#define CLAMP(x) do { \ - if ((x) & ~0xff) \ - x = ((x) < 0) ? 0 : 0xff; \ - } while (0) - +#define CLAMP(x) \ + do { \ + if ((x) & ~0xff) \ + x = ((x) < 0) ? 0 : 0xff; \ + } while (0) static void blit_iload_iload_scale(mystique_t *mystique, uint32_t data, int size) { - svga_t *svga = &mystique->svga; + svga_t *svga = &mystique->svga; uint64_t data64 = 0; - int y0, y1; - int u, v; - int dR, dG, dB; - int r0, g0, b0; - int r1, g1, b1; + int y0; + int y1; + int u; + int v; + int dR; + int dG; + int dB; + int r0; + int g0; + int b0; + int r1; + int g1; + int b1; switch (mystique->dwgreg.dwgctrl_running & DWGCTRL_BLTMOD_MASK) { - case DWGCTRL_BLTMOD_BUYUV: - y0 = (298 * ((int)(data & 0xff) - 16)) >> 8; - u = ((data >> 8) & 0xff) - 0x80; - y1 = (298 * ((int)((data >> 16) & 0xff) - 16)) >> 8; - v = ((data >> 24) & 0xff) - 0x80; + case DWGCTRL_BLTMOD_BUYUV: + y0 = (298 * ((int) (data & 0xff) - 16)) >> 8; + u = ((data >> 8) & 0xff) - 0x80; + y1 = (298 * ((int) ((data >> 16) & 0xff) - 16)) >> 8; + v = ((data >> 24) & 0xff) - 0x80; - dR = (309*v) >> 8; - dG = (100*u + 208*v) >> 8; - dB = (516*u) >> 8; + dR = (309 * v) >> 8; + dG = (100 * u + 208 * v) >> 8; + dB = (516 * u) >> 8; - r0 = y0 + dR; - CLAMP(r0); - g0 = y0 - dG; - CLAMP(g0); - b0 = y0 + dB; - CLAMP(b0); - r1 = y1 + dR; - CLAMP(r1); - g1 = y1 - dG; - CLAMP(g1); - b1 = y1 + dB; - CLAMP(b1); + r0 = y0 + dR; + CLAMP(r0); + g0 = y0 - dG; + CLAMP(g0); + b0 = y0 + dB; + CLAMP(b0); + r1 = y1 + dR; + CLAMP(r1); + g1 = y1 - dG; + CLAMP(g1); + b1 = y1 + dB; + CLAMP(b1); - switch (mystique->maccess_running & MACCESS_PWIDTH_MASK) { - case MACCESS_PWIDTH_16: - data = (b0 >> 3) | ((g0 >> 2) << 5) | ((r0 >> 3) << 11); - data |= (((b1 >> 3) | ((g1 >> 2) << 5) | ((r1 >> 3) << 11)) << 16); - size = 32; - break; - case MACCESS_PWIDTH_32: - data64 = b0 | (g0 << 8) | (r0 << 16); - data64 |= ((uint64_t)b0 << 32) | ((uint64_t)g0 << 40) | ((uint64_t)r0 << 48); - size = 64; - break; + switch (mystique->maccess_running & MACCESS_PWIDTH_MASK) { + case MACCESS_PWIDTH_16: + data = (b0 >> 3) | ((g0 >> 2) << 5) | ((r0 >> 3) << 11); + data |= (((b1 >> 3) | ((g1 >> 2) << 5) | ((r1 >> 3) << 11)) << 16); + size = 32; + break; + case MACCESS_PWIDTH_32: + data64 = b0 | (g0 << 8) | (r0 << 16); + data64 |= ((uint64_t) b0 << 32) | ((uint64_t) g0 << 40) | ((uint64_t) r0 << 48); + size = 64; + break; - default: - fatal("blit_iload_iload_scale BUYUV pwidth %i\n", mystique->maccess_running & MACCESS_PWIDTH_MASK); - } - break; + default: + fatal("blit_iload_iload_scale BUYUV pwidth %i\n", mystique->maccess_running & MACCESS_PWIDTH_MASK); + } + break; - default: - fatal("blit_iload_iload_scale bltmod %08x\n", mystique->dwgreg.dwgctrl_running & DWGCTRL_BLTMOD_MASK); - break; + default: + fatal("blit_iload_iload_scale bltmod %08x\n", mystique->dwgreg.dwgctrl_running & DWGCTRL_BLTMOD_MASK); + break; } switch (mystique->maccess_running & MACCESS_PWIDTH_MASK) { - case MACCESS_PWIDTH_16: - while (size >= 16) { - if (mystique->dwgreg.xdst >= mystique->dwgreg.cxleft && mystique->dwgreg.xdst <= mystique->dwgreg.cxright && - mystique->dwgreg.ydst_lin >= mystique->dwgreg.ytop && mystique->dwgreg.ydst_lin <= mystique->dwgreg.ybot) { - uint16_t dst = ((uint16_t *)svga->vram)[(mystique->dwgreg.ydst_lin + mystique->dwgreg.xdst) & mystique->vram_mask_w]; - dst = bitop(data & 0xffff, dst, mystique->dwgreg.dwgctrl_running); - ((uint16_t *)svga->vram)[(mystique->dwgreg.ydst_lin + mystique->dwgreg.xdst) & mystique->vram_mask_w] = dst; - svga->changedvram[((mystique->dwgreg.ydst_lin + mystique->dwgreg.xdst) & mystique->vram_mask_w) >> 11] = changeframecount; - } + case MACCESS_PWIDTH_16: + while (size >= 16) { + if (mystique->dwgreg.xdst >= mystique->dwgreg.cxleft && mystique->dwgreg.xdst <= mystique->dwgreg.cxright && mystique->dwgreg.ydst_lin >= mystique->dwgreg.ytop && mystique->dwgreg.ydst_lin <= mystique->dwgreg.ybot) { + uint16_t dst = ((uint16_t *) svga->vram)[(mystique->dwgreg.ydst_lin + mystique->dwgreg.xdst) & mystique->vram_mask_w]; + dst = bitop(data & 0xffff, dst, mystique->dwgreg.dwgctrl_running); + ((uint16_t *) svga->vram)[(mystique->dwgreg.ydst_lin + mystique->dwgreg.xdst) & mystique->vram_mask_w] = dst; + svga->changedvram[((mystique->dwgreg.ydst_lin + mystique->dwgreg.xdst) & mystique->vram_mask_w) >> 11] = changeframecount; + } - mystique->dwgreg.ar[6] += mystique->dwgreg.ar[2]; - if ((int32_t)mystique->dwgreg.ar[6] >= 0) { - mystique->dwgreg.ar[6] -= (mystique->dwgreg.fxright - mystique->dwgreg.fxleft); - data >>= 16; - size -= 16; - } - - mystique->dwgreg.xdst = (mystique->dwgreg.xdst + 1) & 0xffff; - if (mystique->dwgreg.xdst == mystique->dwgreg.fxright) - { - mystique->dwgreg.xdst = mystique->dwgreg.fxleft; - mystique->dwgreg.ydst_lin += (mystique->dwgreg.pitch & PITCH_MASK); - mystique->dwgreg.ar[0] += mystique->dwgreg.ar[5]; - mystique->dwgreg.ar[3] += mystique->dwgreg.ar[5]; - mystique->dwgreg.ar[6] = mystique->dwgreg.ar[2] - (mystique->dwgreg.fxright - mystique->dwgreg.fxleft); - mystique->dwgreg.length_cur--; - if (!mystique->dwgreg.length_cur) { - mystique->busy = 0; - mystique->blitter_complete_refcount++; - break; - } - break; - } - } - break; + mystique->dwgreg.ar[6] += mystique->dwgreg.ar[2]; + if ((int32_t) mystique->dwgreg.ar[6] >= 0) { + mystique->dwgreg.ar[6] -= (mystique->dwgreg.fxright - mystique->dwgreg.fxleft); + data >>= 16; + size -= 16; + } - case MACCESS_PWIDTH_32: - while (size >= 32) { - if (mystique->dwgreg.xdst >= mystique->dwgreg.cxleft && mystique->dwgreg.xdst <= mystique->dwgreg.cxright && - mystique->dwgreg.ydst_lin >= mystique->dwgreg.ytop && mystique->dwgreg.ydst_lin <= mystique->dwgreg.ybot) { - uint32_t dst = ((uint32_t *)svga->vram)[(mystique->dwgreg.ydst_lin + mystique->dwgreg.xdst) & mystique->vram_mask_l]; - dst = bitop(data64, dst, mystique->dwgreg.dwgctrl_running); - ((uint32_t *)svga->vram)[(mystique->dwgreg.ydst_lin + mystique->dwgreg.xdst) & mystique->vram_mask_l] = dst; - svga->changedvram[((mystique->dwgreg.ydst_lin + mystique->dwgreg.xdst) & mystique->vram_mask_l) >> 10] = changeframecount; - } + mystique->dwgreg.xdst = (mystique->dwgreg.xdst + 1) & 0xffff; + if (mystique->dwgreg.xdst == mystique->dwgreg.fxright) { + mystique->dwgreg.xdst = mystique->dwgreg.fxleft; + mystique->dwgreg.ydst_lin += (mystique->dwgreg.pitch & PITCH_MASK); + mystique->dwgreg.ar[0] += mystique->dwgreg.ar[5]; + mystique->dwgreg.ar[3] += mystique->dwgreg.ar[5]; + mystique->dwgreg.ar[6] = mystique->dwgreg.ar[2] - (mystique->dwgreg.fxright - mystique->dwgreg.fxleft); + mystique->dwgreg.length_cur--; + if (!mystique->dwgreg.length_cur) { + mystique->busy = 0; + mystique->blitter_complete_refcount++; + break; + } + break; + } + } + break; - mystique->dwgreg.ar[6] += mystique->dwgreg.ar[2]; - if ((int32_t)mystique->dwgreg.ar[6] >= 0) { - mystique->dwgreg.ar[6] -= (mystique->dwgreg.fxright - mystique->dwgreg.fxleft); - data64 >>= 32; - size -= 32; - } - - mystique->dwgreg.xdst = (mystique->dwgreg.xdst + 1) & 0xffff; - if (mystique->dwgreg.xdst == mystique->dwgreg.fxright) - { - mystique->dwgreg.xdst = mystique->dwgreg.fxleft; - mystique->dwgreg.ydst_lin += (mystique->dwgreg.pitch & PITCH_MASK); - mystique->dwgreg.ar[0] += mystique->dwgreg.ar[5]; - mystique->dwgreg.ar[3] += mystique->dwgreg.ar[5]; - mystique->dwgreg.ar[6] = mystique->dwgreg.ar[2] - (mystique->dwgreg.fxright - mystique->dwgreg.fxleft); - mystique->dwgreg.length_cur--; - if (!mystique->dwgreg.length_cur) { - mystique->busy = 0; - mystique->blitter_complete_refcount++; - break; - } - break; - } - } - break; + case MACCESS_PWIDTH_32: + while (size >= 32) { + if (mystique->dwgreg.xdst >= mystique->dwgreg.cxleft && mystique->dwgreg.xdst <= mystique->dwgreg.cxright && mystique->dwgreg.ydst_lin >= mystique->dwgreg.ytop && mystique->dwgreg.ydst_lin <= mystique->dwgreg.ybot) { + uint32_t dst = ((uint32_t *) svga->vram)[(mystique->dwgreg.ydst_lin + mystique->dwgreg.xdst) & mystique->vram_mask_l]; + dst = bitop(data64, dst, mystique->dwgreg.dwgctrl_running); + ((uint32_t *) svga->vram)[(mystique->dwgreg.ydst_lin + mystique->dwgreg.xdst) & mystique->vram_mask_l] = dst; + svga->changedvram[((mystique->dwgreg.ydst_lin + mystique->dwgreg.xdst) & mystique->vram_mask_l) >> 10] = changeframecount; + } - default: - fatal("ILOAD_SCALE pwidth %08x\n", mystique->maccess_running & MACCESS_PWIDTH_MASK); + mystique->dwgreg.ar[6] += mystique->dwgreg.ar[2]; + if ((int32_t) mystique->dwgreg.ar[6] >= 0) { + mystique->dwgreg.ar[6] -= (mystique->dwgreg.fxright - mystique->dwgreg.fxleft); + data64 >>= 32; + size -= 32; + } + + mystique->dwgreg.xdst = (mystique->dwgreg.xdst + 1) & 0xffff; + if (mystique->dwgreg.xdst == mystique->dwgreg.fxright) { + mystique->dwgreg.xdst = mystique->dwgreg.fxleft; + mystique->dwgreg.ydst_lin += (mystique->dwgreg.pitch & PITCH_MASK); + mystique->dwgreg.ar[0] += mystique->dwgreg.ar[5]; + mystique->dwgreg.ar[3] += mystique->dwgreg.ar[5]; + mystique->dwgreg.ar[6] = mystique->dwgreg.ar[2] - (mystique->dwgreg.fxright - mystique->dwgreg.fxleft); + mystique->dwgreg.length_cur--; + if (!mystique->dwgreg.length_cur) { + mystique->busy = 0; + mystique->blitter_complete_refcount++; + break; + } + break; + } + } + break; + + default: + fatal("ILOAD_SCALE pwidth %08x\n", mystique->maccess_running & MACCESS_PWIDTH_MASK); } } - static void blit_iload_iload_high(mystique_t *mystique, uint32_t data, int size) { - svga_t *svga = &mystique->svga; + svga_t *svga = &mystique->svga; uint32_t out_data; - int y0, y1, u, v; - int dR, dG, dB; - int r = 0, g = 0, b = 0; - int next_r = 0, next_g = 0, next_b = 0; + int y0; + int y1; + int u; + int v; + int dR; + int dG; + int dB; + int r = 0; + int g = 0; + int b = 0; + int next_r = 0; + int next_g = 0; + int next_b = 0; switch (mystique->dwgreg.dwgctrl_running & DWGCTRL_BLTMOD_MASK) { - case DWGCTRL_BLTMOD_BUYUV: - y0 = (298 * ((int)(data & 0xff) - 16)) >> 8; - u = ((data >> 8) & 0xff) - 0x80; - y1 = (298 * ((int)((data >> 16) & 0xff) - 16)) >> 8; - v = ((data >> 24) & 0xff) - 0x80; + case DWGCTRL_BLTMOD_BUYUV: + y0 = (298 * ((int) (data & 0xff) - 16)) >> 8; + u = ((data >> 8) & 0xff) - 0x80; + y1 = (298 * ((int) ((data >> 16) & 0xff) - 16)) >> 8; + v = ((data >> 24) & 0xff) - 0x80; - dR = (309*v) >> 8; - dG = (100*u + 208*v) >> 8; - dB = (516*u) >> 8; + dR = (309 * v) >> 8; + dG = (100 * u + 208 * v) >> 8; + dB = (516 * u) >> 8; - r = y0 + dR; - CLAMP(r); - g = y0 - dG; - CLAMP(g); - b = y0 + dB; - CLAMP(b); + r = y0 + dR; + CLAMP(r); + g = y0 - dG; + CLAMP(g); + b = y0 + dB; + CLAMP(b); - next_r = y1 + dR; - CLAMP(next_r); - next_g = y1 - dG; - CLAMP(next_g); - next_b = y1 + dB; - CLAMP(next_b); + next_r = y1 + dR; + CLAMP(next_r); + next_g = y1 - dG; + CLAMP(next_g); + next_b = y1 + dB; + CLAMP(next_b); - size = 32; - break; + size = 32; + break; - case DWGCTRL_BLTMOD_BU32BGR: - r = ((data >> 16) & 0xff); - CLAMP(r); - g = ((data >> 8) & 0xff); - CLAMP(g); - b = (data & 0xff); - CLAMP(b); + case DWGCTRL_BLTMOD_BU32BGR: + r = ((data >> 16) & 0xff); + CLAMP(r); + g = ((data >> 8) & 0xff); + CLAMP(g); + b = (data & 0xff); + CLAMP(b); - next_r = r; - next_g = g; - next_b = b; + next_r = r; + next_g = g; + next_b = b; - size = 32; - break; + size = 32; + break; - default: - fatal("blit_iload_iload_high bltmod %08x\n", mystique->dwgreg.dwgctrl_running & DWGCTRL_BLTMOD_MASK); - break; + default: + fatal("blit_iload_iload_high bltmod %08x\n", mystique->dwgreg.dwgctrl_running & DWGCTRL_BLTMOD_MASK); + break; } while (size >= 16) { - if (mystique->dwgreg.xdst >= mystique->dwgreg.cxleft && mystique->dwgreg.xdst <= mystique->dwgreg.cxright && - mystique->dwgreg.ydst_lin >= mystique->dwgreg.ytop && mystique->dwgreg.ydst_lin <= mystique->dwgreg.ybot) { - uint32_t dst; - int f1 = (mystique->dwgreg.ar[6] >> 12) & 0xf; - int f0 = 0x10 - f1; - int out_r = ((mystique->dwgreg.lastpix_r * f0) + (r * f1)) >> 4; - int out_g = ((mystique->dwgreg.lastpix_g * f0) + (g * f1)) >> 4; - int out_b = ((mystique->dwgreg.lastpix_b * f0) + (b * f1)) >> 4; + if (mystique->dwgreg.xdst >= mystique->dwgreg.cxleft && mystique->dwgreg.xdst <= mystique->dwgreg.cxright && mystique->dwgreg.ydst_lin >= mystique->dwgreg.ytop && mystique->dwgreg.ydst_lin <= mystique->dwgreg.ybot) { + uint32_t dst; + int f1 = (mystique->dwgreg.ar[6] >> 12) & 0xf; + int f0 = 0x10 - f1; + int out_r = ((mystique->dwgreg.lastpix_r * f0) + (r * f1)) >> 4; + int out_g = ((mystique->dwgreg.lastpix_g * f0) + (g * f1)) >> 4; + int out_b = ((mystique->dwgreg.lastpix_b * f0) + (b * f1)) >> 4; - switch (mystique->maccess_running & MACCESS_PWIDTH_MASK) { - case MACCESS_PWIDTH_16: - out_data = (out_b >> 3) | ((out_g >> 2) << 5) | ((out_r >> 3) << 11); - dst = ((uint16_t *)svga->vram)[(mystique->dwgreg.ydst_lin + mystique->dwgreg.xdst) & mystique->vram_mask_w]; - dst = bitop(out_data, dst, mystique->dwgreg.dwgctrl_running); - ((uint16_t *)svga->vram)[(mystique->dwgreg.ydst_lin + mystique->dwgreg.xdst) & mystique->vram_mask_w] = dst; - svga->changedvram[((mystique->dwgreg.ydst_lin + mystique->dwgreg.xdst) & mystique->vram_mask_w) >> 11] = changeframecount; - break; - case MACCESS_PWIDTH_32: - out_data = out_b | (out_g << 8) | (out_r << 16); - dst = ((uint32_t *)svga->vram)[(mystique->dwgreg.ydst_lin + mystique->dwgreg.xdst) & mystique->vram_mask_l]; - dst = bitop(out_data, dst, mystique->dwgreg.dwgctrl_running); - ((uint32_t *)svga->vram)[(mystique->dwgreg.ydst_lin + mystique->dwgreg.xdst) & mystique->vram_mask_l] = dst; - svga->changedvram[((mystique->dwgreg.ydst_lin + mystique->dwgreg.xdst) & mystique->vram_mask_l) >> 10] = changeframecount; - break; + switch (mystique->maccess_running & MACCESS_PWIDTH_MASK) { + case MACCESS_PWIDTH_16: + out_data = (out_b >> 3) | ((out_g >> 2) << 5) | ((out_r >> 3) << 11); + dst = ((uint16_t *) svga->vram)[(mystique->dwgreg.ydst_lin + mystique->dwgreg.xdst) & mystique->vram_mask_w]; + dst = bitop(out_data, dst, mystique->dwgreg.dwgctrl_running); + ((uint16_t *) svga->vram)[(mystique->dwgreg.ydst_lin + mystique->dwgreg.xdst) & mystique->vram_mask_w] = dst; + svga->changedvram[((mystique->dwgreg.ydst_lin + mystique->dwgreg.xdst) & mystique->vram_mask_w) >> 11] = changeframecount; + break; + case MACCESS_PWIDTH_32: + out_data = out_b | (out_g << 8) | (out_r << 16); + dst = ((uint32_t *) svga->vram)[(mystique->dwgreg.ydst_lin + mystique->dwgreg.xdst) & mystique->vram_mask_l]; + dst = bitop(out_data, dst, mystique->dwgreg.dwgctrl_running); + ((uint32_t *) svga->vram)[(mystique->dwgreg.ydst_lin + mystique->dwgreg.xdst) & mystique->vram_mask_l] = dst; + svga->changedvram[((mystique->dwgreg.ydst_lin + mystique->dwgreg.xdst) & mystique->vram_mask_l) >> 10] = changeframecount; + break; - default: - fatal("ILOAD_SCALE_HIGH RSTR/RPL BUYUV pwidth %08x\n", mystique->maccess_running & MACCESS_PWIDTH_MASK); - } - } + default: + fatal("ILOAD_SCALE_HIGH RSTR/RPL BUYUV pwidth %08x\n", mystique->maccess_running & MACCESS_PWIDTH_MASK); + } + } - mystique->dwgreg.ar[6] += mystique->dwgreg.ar[2]; - if ((int32_t)mystique->dwgreg.ar[6] >= 0) { - mystique->dwgreg.ar[6] -= 65536; - size -= 16; + mystique->dwgreg.ar[6] += mystique->dwgreg.ar[2]; + if ((int32_t) mystique->dwgreg.ar[6] >= 0) { + mystique->dwgreg.ar[6] -= 65536; + size -= 16; - mystique->dwgreg.lastpix_r = r; - mystique->dwgreg.lastpix_g = g; - mystique->dwgreg.lastpix_b = b; - r = next_r; - g = next_g; - b = next_b; - } + mystique->dwgreg.lastpix_r = r; + mystique->dwgreg.lastpix_g = g; + mystique->dwgreg.lastpix_b = b; + r = next_r; + g = next_g; + b = next_b; + } - if (mystique->dwgreg.xdst == mystique->dwgreg.fxright) { - mystique->dwgreg.xdst = mystique->dwgreg.fxleft; - mystique->dwgreg.ydst_lin += (mystique->dwgreg.pitch & PITCH_MASK); - mystique->dwgreg.ar[6] = mystique->dwgreg.ar[2] - (mystique->dwgreg.fxright - mystique->dwgreg.fxleft); - mystique->dwgreg.lastpix_r = 0; - mystique->dwgreg.lastpix_g = 0; - mystique->dwgreg.lastpix_b = 0; + if (mystique->dwgreg.xdst == mystique->dwgreg.fxright) { + mystique->dwgreg.xdst = mystique->dwgreg.fxleft; + mystique->dwgreg.ydst_lin += (mystique->dwgreg.pitch & PITCH_MASK); + mystique->dwgreg.ar[6] = mystique->dwgreg.ar[2] - (mystique->dwgreg.fxright - mystique->dwgreg.fxleft); + mystique->dwgreg.lastpix_r = 0; + mystique->dwgreg.lastpix_g = 0; + mystique->dwgreg.lastpix_b = 0; - mystique->dwgreg.length_cur--; - if (!mystique->dwgreg.length_cur) { - mystique->busy = 0; - mystique->blitter_complete_refcount++; - break; - } - break; - } else - mystique->dwgreg.xdst = (mystique->dwgreg.xdst + 1) & 0xffff; + mystique->dwgreg.length_cur--; + if (!mystique->dwgreg.length_cur) { + mystique->busy = 0; + mystique->blitter_complete_refcount++; + break; + } + break; + } else + mystique->dwgreg.xdst = (mystique->dwgreg.xdst + 1) & 0xffff; } } - static void -blit_iload_iload_highv(mystique_t *mystique, uint32_t data, int size) +blit_iload_iload_highv(mystique_t *mystique, uint32_t data, UNUSED(int size)) { - uint8_t *src0, *src1; + const uint8_t *src0; + uint8_t *src1; switch (mystique->dwgreg.dwgctrl_running & DWGCTRL_BLTMOD_MASK) { - case DWGCTRL_BLTMOD_BUYUV: - if (!mystique->dwgreg.highv_line) { - mystique->dwgreg.highv_data = data; - mystique->dwgreg.highv_line = 1; - return; - } - mystique->dwgreg.highv_line = 0; + case DWGCTRL_BLTMOD_BUYUV: + if (!mystique->dwgreg.highv_line) { + mystique->dwgreg.highv_data = data; + mystique->dwgreg.highv_line = 1; + return; + } + mystique->dwgreg.highv_line = 0; - src0 = (uint8_t *)&mystique->dwgreg.highv_data; - src1 = (uint8_t *)&data; + src0 = (uint8_t *) &mystique->dwgreg.highv_data; + src1 = (uint8_t *) &data; - src1[0] = ((src0[0] * mystique->dwgreg.beta) + (src1[0] * (16 - mystique->dwgreg.beta))) >> 4; - src1[1] = ((src0[1] * mystique->dwgreg.beta) + (src1[1] * (16 - mystique->dwgreg.beta))) >> 4; - src1[2] = ((src0[2] * mystique->dwgreg.beta) + (src1[2] * (16 - mystique->dwgreg.beta))) >> 4; - src1[3] = ((src0[3] * mystique->dwgreg.beta) + (src1[3] * (16 - mystique->dwgreg.beta))) >> 4; - blit_iload_iload_high(mystique, data, 32); - break; + src1[0] = ((src0[0] * mystique->dwgreg.beta) + (src1[0] * (16 - mystique->dwgreg.beta))) >> 4; + src1[1] = ((src0[1] * mystique->dwgreg.beta) + (src1[1] * (16 - mystique->dwgreg.beta))) >> 4; + src1[2] = ((src0[2] * mystique->dwgreg.beta) + (src1[2] * (16 - mystique->dwgreg.beta))) >> 4; + src1[3] = ((src0[3] * mystique->dwgreg.beta) + (src1[3] * (16 - mystique->dwgreg.beta))) >> 4; + blit_iload_iload_high(mystique, data, 32); + break; - default: - fatal("blit_iload_iload_highv bltmod %08x\n", mystique->dwgreg.dwgctrl_running & DWGCTRL_BLTMOD_MASK); - break; + default: + fatal("blit_iload_iload_highv bltmod %08x\n", mystique->dwgreg.dwgctrl_running & DWGCTRL_BLTMOD_MASK); + break; } } - static void blit_iload_write(mystique_t *mystique, uint32_t data, int size) { switch (mystique->dwgreg.dwgctrl_running & DWGCTRL_OPCODE_MASK) { - case DWGCTRL_OPCODE_ILOAD: - blit_iload_iload(mystique, data, size); - break; + case DWGCTRL_OPCODE_ILOAD: + blit_iload_iload(mystique, data, size); + break; - case DWGCTRL_OPCODE_ILOAD_SCALE: - blit_iload_iload_scale(mystique, data, size); - break; + case DWGCTRL_OPCODE_ILOAD_SCALE: + blit_iload_iload_scale(mystique, data, size); + break; - case DWGCTRL_OPCODE_ILOAD_HIGH: - blit_iload_iload_high(mystique, data, size); - break; + case DWGCTRL_OPCODE_ILOAD_HIGH: + blit_iload_iload_high(mystique, data, size); + break; - case DWGCTRL_OPCODE_ILOAD_HIGHV: - blit_iload_iload_highv(mystique, data, size); - break; + case DWGCTRL_OPCODE_ILOAD_HIGHV: + blit_iload_iload_highv(mystique, data, size); + break; - default: - fatal("blit_iload_write: bad opcode %08x\n", mystique->dwgreg.dwgctrl_running); + default: + fatal("blit_iload_write: bad opcode %08x\n", mystique->dwgreg.dwgctrl_running); } } - static int -z_check(uint16_t z, uint16_t old_z, uint32_t z_mode)//mystique->dwgreg.dwgctrl & DWGCTRL_ZMODE_MASK) +z_check(uint16_t z, uint16_t old_z, uint32_t z_mode) // mystique->dwgreg.dwgctrl & DWGCTRL_ZMODE_MASK) { switch (z_mode) { - case DWGCTRL_ZMODE_ZE: - return (z == old_z); - case DWGCTRL_ZMODE_ZNE: - return (z != old_z); - case DWGCTRL_ZMODE_ZLT: - return (z < old_z); - case DWGCTRL_ZMODE_ZLTE: - return (z <= old_z); - case DWGCTRL_ZMODE_ZGT: - return (z > old_z); - case DWGCTRL_ZMODE_ZGTE: - return (z >= old_z); + case DWGCTRL_ZMODE_ZE: + return (z == old_z); + case DWGCTRL_ZMODE_ZNE: + return (z != old_z); + case DWGCTRL_ZMODE_ZLT: + return (z < old_z); + case DWGCTRL_ZMODE_ZLTE: + return (z <= old_z); + case DWGCTRL_ZMODE_ZGT: + return (z > old_z); + case DWGCTRL_ZMODE_ZGTE: + return (z >= old_z); - case DWGCTRL_ZMODE_NOZCMP: - default: - return 1; + case DWGCTRL_ZMODE_NOZCMP: + default: + return 1; } } - static void -blit_line(mystique_t *mystique, int closed) +blit_line(mystique_t *mystique, UNUSED(int closed)) { - svga_t *svga = &mystique->svga; - uint32_t src, dst, old_dst; - int x; - int z_write; + svga_t *svga = &mystique->svga; + uint32_t src; + uint32_t dst; + uint32_t old_dst; + int x; + int z_write; switch (mystique->dwgreg.dwgctrl_running & DWGCTRL_ATYPE_MASK) { - case DWGCTRL_ATYPE_RSTR: - case DWGCTRL_ATYPE_RPL: - x = mystique->dwgreg.xdst; - while (mystique->dwgreg.length > 0) { - if (x >= mystique->dwgreg.cxleft && x <= mystique->dwgreg.cxright && - mystique->dwgreg.ydst_lin >= mystique->dwgreg.ytop && mystique->dwgreg.ydst_lin <= mystique->dwgreg.ybot) { - switch (mystique->maccess_running & MACCESS_PWIDTH_MASK) { - case MACCESS_PWIDTH_8: - src = mystique->dwgreg.fcol; - dst = svga->vram[(mystique->dwgreg.ydst_lin + x) & mystique->vram_mask]; + case DWGCTRL_ATYPE_RSTR: + case DWGCTRL_ATYPE_RPL: + x = mystique->dwgreg.xdst; + while (mystique->dwgreg.length > 0) { + if (x >= mystique->dwgreg.cxleft && x <= mystique->dwgreg.cxright && mystique->dwgreg.ydst_lin >= mystique->dwgreg.ytop && mystique->dwgreg.ydst_lin <= mystique->dwgreg.ybot) { + switch (mystique->maccess_running & MACCESS_PWIDTH_MASK) { + case MACCESS_PWIDTH_8: + src = mystique->dwgreg.fcol; + dst = svga->vram[(mystique->dwgreg.ydst_lin + x) & mystique->vram_mask]; - dst = bitop(src, dst, mystique->dwgreg.dwgctrl_running); - svga->vram[(mystique->dwgreg.ydst_lin + x) & mystique->vram_mask] = dst; - svga->changedvram[((mystique->dwgreg.ydst_lin + x) & mystique->vram_mask) >> 12] = changeframecount; - break; + dst = bitop(src, dst, mystique->dwgreg.dwgctrl_running); + svga->vram[(mystique->dwgreg.ydst_lin + x) & mystique->vram_mask] = dst; + svga->changedvram[((mystique->dwgreg.ydst_lin + x) & mystique->vram_mask) >> 12] = changeframecount; + break; - case MACCESS_PWIDTH_16: - src = mystique->dwgreg.fcol; - dst = ((uint16_t *)svga->vram)[(mystique->dwgreg.ydst_lin + x) & mystique->vram_mask_w]; + case MACCESS_PWIDTH_16: + src = mystique->dwgreg.fcol; + dst = ((uint16_t *) svga->vram)[(mystique->dwgreg.ydst_lin + x) & mystique->vram_mask_w]; - dst = bitop(src, dst, mystique->dwgreg.dwgctrl_running); - ((uint16_t *)svga->vram)[(mystique->dwgreg.ydst_lin + x) & mystique->vram_mask_w] = dst; - svga->changedvram[((mystique->dwgreg.ydst_lin + x) & mystique->vram_mask_w) >> 11] = changeframecount; - break; + dst = bitop(src, dst, mystique->dwgreg.dwgctrl_running); + ((uint16_t *) svga->vram)[(mystique->dwgreg.ydst_lin + x) & mystique->vram_mask_w] = dst; + svga->changedvram[((mystique->dwgreg.ydst_lin + x) & mystique->vram_mask_w) >> 11] = changeframecount; + break; - case MACCESS_PWIDTH_24: - src = mystique->dwgreg.fcol; - old_dst = *(uint32_t *)&svga->vram[((mystique->dwgreg.ydst_lin + x) * 3) & mystique->vram_mask]; + case MACCESS_PWIDTH_24: + src = mystique->dwgreg.fcol; + old_dst = *(uint32_t *) &svga->vram[((mystique->dwgreg.ydst_lin + x) * 3) & mystique->vram_mask]; - dst = bitop(src, old_dst, mystique->dwgreg.dwgctrl_running); - *(uint32_t *)&svga->vram[((mystique->dwgreg.ydst_lin + x) * 3) & mystique->vram_mask] = (dst & 0xffffff) | (old_dst & 0xff000000); - svga->changedvram[(((mystique->dwgreg.ydst_lin + x) * 3) & mystique->vram_mask) >> 12] = changeframecount; - break; + dst = bitop(src, old_dst, mystique->dwgreg.dwgctrl_running); + *(uint32_t *) &svga->vram[((mystique->dwgreg.ydst_lin + x) * 3) & mystique->vram_mask] = (dst & 0xffffff) | (old_dst & 0xff000000); + svga->changedvram[(((mystique->dwgreg.ydst_lin + x) * 3) & mystique->vram_mask) >> 12] = changeframecount; + break; - case MACCESS_PWIDTH_32: - src = mystique->dwgreg.fcol; - dst = ((uint32_t *)svga->vram)[(mystique->dwgreg.ydst_lin + x) & mystique->vram_mask_l]; + case MACCESS_PWIDTH_32: + src = mystique->dwgreg.fcol; + dst = ((uint32_t *) svga->vram)[(mystique->dwgreg.ydst_lin + x) & mystique->vram_mask_l]; - dst = bitop(src, dst, mystique->dwgreg.dwgctrl_running); - ((uint32_t *)svga->vram)[(mystique->dwgreg.ydst_lin + x) & mystique->vram_mask_l] = dst; - svga->changedvram[((mystique->dwgreg.ydst_lin + x) & mystique->vram_mask_l) >> 10] = changeframecount; - break; + dst = bitop(src, dst, mystique->dwgreg.dwgctrl_running); + ((uint32_t *) svga->vram)[(mystique->dwgreg.ydst_lin + x) & mystique->vram_mask_l] = dst; + svga->changedvram[((mystique->dwgreg.ydst_lin + x) & mystique->vram_mask_l) >> 10] = changeframecount; + break; - default: - fatal("LINE RSTR/RPL PWIDTH %x %08x\n", mystique->maccess_running & MACCESS_PWIDTH_MASK, mystique->dwgreg.dwgctrl_running); - } - } + default: + fatal("LINE RSTR/RPL PWIDTH %x %08x\n", mystique->maccess_running & MACCESS_PWIDTH_MASK, mystique->dwgreg.dwgctrl_running); + } + } - if (mystique->dwgreg.sgn.sdydxl) - x += (mystique->dwgreg.sgn.sdxl ? -1 : 1); - else - mystique->dwgreg.ydst_lin += (mystique->dwgreg.sgn.sdy ? -(mystique->dwgreg.pitch & PITCH_MASK) : (mystique->dwgreg.pitch & PITCH_MASK)); + if (mystique->dwgreg.sgn.sdydxl) + x += (mystique->dwgreg.sgn.sdxl ? -1 : 1); + else + mystique->dwgreg.ydst_lin += (mystique->dwgreg.sgn.sdy ? -(mystique->dwgreg.pitch & PITCH_MASK) : (mystique->dwgreg.pitch & PITCH_MASK)); - if ((int32_t)mystique->dwgreg.ar[1] >= 0) { - mystique->dwgreg.ar[1] += mystique->dwgreg.ar[2]; - if (mystique->dwgreg.sgn.sdydxl) - mystique->dwgreg.ydst_lin += (mystique->dwgreg.sgn.sdy ? -(mystique->dwgreg.pitch & PITCH_MASK) : (mystique->dwgreg.pitch & PITCH_MASK)); - else - x += (mystique->dwgreg.sgn.sdxl ? -1 : 1); - } else - mystique->dwgreg.ar[1] += mystique->dwgreg.ar[0]; + if ((int32_t) mystique->dwgreg.ar[1] >= 0) { + mystique->dwgreg.ar[1] += mystique->dwgreg.ar[2]; + if (mystique->dwgreg.sgn.sdydxl) + mystique->dwgreg.ydst_lin += (mystique->dwgreg.sgn.sdy ? -(mystique->dwgreg.pitch & PITCH_MASK) : (mystique->dwgreg.pitch & PITCH_MASK)); + else + x += (mystique->dwgreg.sgn.sdxl ? -1 : 1); + } else + mystique->dwgreg.ar[1] += mystique->dwgreg.ar[0]; - mystique->dwgreg.length--; - } - break; + mystique->dwgreg.length--; + } + break; - case DWGCTRL_ATYPE_I: - case DWGCTRL_ATYPE_ZI: - z_write = ((mystique->dwgreg.dwgctrl_running & DWGCTRL_ATYPE_MASK) == DWGCTRL_ATYPE_ZI); - x = mystique->dwgreg.xdst; - while (mystique->dwgreg.length > 0) { - if (x >= mystique->dwgreg.cxleft && x <= mystique->dwgreg.cxright && - mystique->dwgreg.ydst_lin >= mystique->dwgreg.ytop && mystique->dwgreg.ydst_lin <= mystique->dwgreg.ybot) { - uint16_t z = ((int32_t)mystique->dwgreg.dr[0] < 0) ? 0 : (mystique->dwgreg.dr[0] >> 15); - uint16_t *z_p = (uint16_t *)&svga->vram[(mystique->dwgreg.ydst_lin*2 + mystique->dwgreg.zorg) & mystique->vram_mask]; - uint16_t old_z = z_p[x]; + case DWGCTRL_ATYPE_I: + case DWGCTRL_ATYPE_ZI: + z_write = ((mystique->dwgreg.dwgctrl_running & DWGCTRL_ATYPE_MASK) == DWGCTRL_ATYPE_ZI); + x = mystique->dwgreg.xdst; + while (mystique->dwgreg.length > 0) { + if (x >= mystique->dwgreg.cxleft && x <= mystique->dwgreg.cxright && mystique->dwgreg.ydst_lin >= mystique->dwgreg.ytop && mystique->dwgreg.ydst_lin <= mystique->dwgreg.ybot) { + uint16_t z = ((int32_t) mystique->dwgreg.dr[0] < 0) ? 0 : (mystique->dwgreg.dr[0] >> 15); + uint16_t *z_p = (uint16_t *) &svga->vram[(mystique->dwgreg.ydst_lin * 2 + mystique->dwgreg.zorg) & mystique->vram_mask]; + uint16_t old_z = z_p[x]; - if (z_check(z, old_z, mystique->dwgreg.dwgctrl_running & DWGCTRL_ZMODE_MASK)) { - int r = 0, g = 0, b = 0; + if (z_check(z, old_z, mystique->dwgreg.dwgctrl_running & DWGCTRL_ZMODE_MASK)) { + int r = 0; + int g = 0; + int b = 0; - if (z_write) - z_p[x] = z; + if (z_write) + z_p[x] = z; - switch (mystique->maccess_running & MACCESS_PWIDTH_MASK) { - case MACCESS_PWIDTH_16: - if (!(mystique->dwgreg.dr[4] & (1 << 23))) - r = (mystique->dwgreg.dr[4] >> 18) & 0x1f; - if (!(mystique->dwgreg.dr[8] & (1 << 23))) - g = (mystique->dwgreg.dr[8] >> 17) & 0x3f; - if (!(mystique->dwgreg.dr[12] & (1 << 23))) - b = (mystique->dwgreg.dr[12] >> 18) & 0x1f; - dst = (r << 11) | (g << 5) | b; + switch (mystique->maccess_running & MACCESS_PWIDTH_MASK) { + case MACCESS_PWIDTH_16: + if (!(mystique->dwgreg.dr[4] & (1 << 23))) + r = (mystique->dwgreg.dr[4] >> 18) & 0x1f; + if (!(mystique->dwgreg.dr[8] & (1 << 23))) + g = (mystique->dwgreg.dr[8] >> 17) & 0x3f; + if (!(mystique->dwgreg.dr[12] & (1 << 23))) + b = (mystique->dwgreg.dr[12] >> 18) & 0x1f; + dst = (r << 11) | (g << 5) | b; - ((uint16_t *)svga->vram)[(mystique->dwgreg.ydst_lin + x) & mystique->vram_mask_w] = dst; - svga->changedvram[((mystique->dwgreg.ydst_lin + x) & mystique->vram_mask_w) >> 11] = changeframecount; - break; + ((uint16_t *) svga->vram)[(mystique->dwgreg.ydst_lin + x) & mystique->vram_mask_w] = dst; + svga->changedvram[((mystique->dwgreg.ydst_lin + x) & mystique->vram_mask_w) >> 11] = changeframecount; + break; - default: - fatal("LINE I/ZI PWIDTH %x %08x\n", mystique->maccess_running & MACCESS_PWIDTH_MASK, mystique->dwgreg.dwgctrl_running); - } - } - } + default: + fatal("LINE I/ZI PWIDTH %x %08x\n", mystique->maccess_running & MACCESS_PWIDTH_MASK, mystique->dwgreg.dwgctrl_running); + } + } + } - if (mystique->dwgreg.sgn.sdydxl) - x += (mystique->dwgreg.sgn.sdxl ? -1 : 1); - else - mystique->dwgreg.ydst_lin += (mystique->dwgreg.sgn.sdy ? -(mystique->dwgreg.pitch & PITCH_MASK) : (mystique->dwgreg.pitch & PITCH_MASK)); + if (mystique->dwgreg.sgn.sdydxl) + x += (mystique->dwgreg.sgn.sdxl ? -1 : 1); + else + mystique->dwgreg.ydst_lin += (mystique->dwgreg.sgn.sdy ? -(mystique->dwgreg.pitch & PITCH_MASK) : (mystique->dwgreg.pitch & PITCH_MASK)); - mystique->dwgreg.dr[0] += mystique->dwgreg.dr[2]; - mystique->dwgreg.dr[4] += mystique->dwgreg.dr[6]; - mystique->dwgreg.dr[8] += mystique->dwgreg.dr[10]; - mystique->dwgreg.dr[12] += mystique->dwgreg.dr[14]; + mystique->dwgreg.dr[0] += mystique->dwgreg.dr[2]; + mystique->dwgreg.dr[4] += mystique->dwgreg.dr[6]; + mystique->dwgreg.dr[8] += mystique->dwgreg.dr[10]; + mystique->dwgreg.dr[12] += mystique->dwgreg.dr[14]; - if ((int32_t)mystique->dwgreg.ar[1] >= 0) { - mystique->dwgreg.ar[1] += mystique->dwgreg.ar[2]; + if ((int32_t) mystique->dwgreg.ar[1] >= 0) { + mystique->dwgreg.ar[1] += mystique->dwgreg.ar[2]; - if (mystique->dwgreg.sgn.sdydxl) - mystique->dwgreg.ydst_lin += (mystique->dwgreg.sgn.sdy ? -(mystique->dwgreg.pitch & PITCH_MASK) : (mystique->dwgreg.pitch & PITCH_MASK)); - else - x += (mystique->dwgreg.sgn.sdxl ? -1 : 1); + if (mystique->dwgreg.sgn.sdydxl) + mystique->dwgreg.ydst_lin += (mystique->dwgreg.sgn.sdy ? -(mystique->dwgreg.pitch & PITCH_MASK) : (mystique->dwgreg.pitch & PITCH_MASK)); + else + x += (mystique->dwgreg.sgn.sdxl ? -1 : 1); - mystique->dwgreg.dr[0] += mystique->dwgreg.dr[3]; - mystique->dwgreg.dr[4] += mystique->dwgreg.dr[7]; - mystique->dwgreg.dr[8] += mystique->dwgreg.dr[11]; - mystique->dwgreg.dr[12] += mystique->dwgreg.dr[15]; - } else - mystique->dwgreg.ar[1] += mystique->dwgreg.ar[0]; + mystique->dwgreg.dr[0] += mystique->dwgreg.dr[3]; + mystique->dwgreg.dr[4] += mystique->dwgreg.dr[7]; + mystique->dwgreg.dr[8] += mystique->dwgreg.dr[11]; + mystique->dwgreg.dr[12] += mystique->dwgreg.dr[15]; + } else + mystique->dwgreg.ar[1] += mystique->dwgreg.ar[0]; - mystique->dwgreg.length--; - } - break; + mystique->dwgreg.length--; + } + break; - default: - /* pclog("Unknown atype %03x %08x LINE\n", mystique->dwgreg.dwgctrl_running & DWGCTRL_ATYPE_MASK, mystique->dwgreg.dwgctrl_running); */ - break; + default: +#if 0 + pclog("Unknown atype %03x %08x LINE\n", mystique->dwgreg.dwgctrl_running & DWGCTRL_ATYPE_MASK, mystique->dwgreg.dwgctrl_running); +#endif + break; } mystique->blitter_complete_refcount++; } - static void blit_autoline(mystique_t *mystique, int closed) { - int start_x = (int32_t)mystique->dwgreg.ar[5]; - int start_y = (int32_t)mystique->dwgreg.ar[6]; - int end_x = (int32_t)mystique->dwgreg.ar[0]; - int end_y = (int32_t)mystique->dwgreg.ar[2]; - int dx = end_x - start_x; - int dy = end_y - start_y; + int start_x = (int32_t) mystique->dwgreg.ar[5]; + int start_y = (int32_t) mystique->dwgreg.ar[6]; + int end_x = (int32_t) mystique->dwgreg.ar[0]; + int end_y = (int32_t) mystique->dwgreg.ar[2]; + int dx = end_x - start_x; + int dy = end_y - start_y; if (ABS(dx) > ABS(dy)) { - mystique->dwgreg.sgn.sdydxl = 1; - mystique->dwgreg.ar[0] = 2*ABS(dy); - mystique->dwgreg.ar[1] = 2*ABS(dy) - ABS(dx) - ((start_y > end_y) ? 1 : 0); - mystique->dwgreg.ar[2] = 2*ABS(dy) - 2*ABS(dx); - mystique->dwgreg.length = ABS(end_x - start_x); + mystique->dwgreg.sgn.sdydxl = 1; + mystique->dwgreg.ar[0] = 2 * ABS(dy); + mystique->dwgreg.ar[1] = 2 * ABS(dy) - ABS(dx) - ((start_y > end_y) ? 1 : 0); + mystique->dwgreg.ar[2] = 2 * ABS(dy) - 2 * ABS(dx); + mystique->dwgreg.length = ABS(end_x - start_x); } else { - mystique->dwgreg.sgn.sdydxl = 0; - mystique->dwgreg.ar[0] = 2*ABS(dx); - mystique->dwgreg.ar[1] = 2*ABS(dx) - ABS(dy) - ((start_y > end_y) ? 1 : 0); - mystique->dwgreg.ar[2] = 2*ABS(dx) - 2*ABS(dy); - mystique->dwgreg.length = ABS(end_y - start_y); + mystique->dwgreg.sgn.sdydxl = 0; + mystique->dwgreg.ar[0] = 2 * ABS(dx); + mystique->dwgreg.ar[1] = 2 * ABS(dx) - ABS(dy) - ((start_y > end_y) ? 1 : 0); + mystique->dwgreg.ar[2] = 2 * ABS(dx) - 2 * ABS(dy); + mystique->dwgreg.length = ABS(end_y - start_y); } mystique->dwgreg.sgn.sdxl = (start_x > end_x) ? 1 : 0; - mystique->dwgreg.sgn.sdy = (start_y > end_y) ? 1 : 0; + mystique->dwgreg.sgn.sdy = (start_y > end_y) ? 1 : 0; blit_line(mystique, closed); - mystique->dwgreg.ar[5] = end_x; - mystique->dwgreg.xdst = end_x; - mystique->dwgreg.ar[6] = end_y; - mystique->dwgreg.ydst = end_y; - mystique->dwgreg.ydst_lin = ((int32_t)(int16_t)mystique->dwgreg.ydst * (mystique->dwgreg.pitch & PITCH_MASK)) + mystique->dwgreg.ydstorg; + mystique->dwgreg.ar[5] = end_x; + mystique->dwgreg.xdst = end_x; + mystique->dwgreg.ar[6] = end_y; + mystique->dwgreg.ydst = end_y; + mystique->dwgreg.ydst_lin = ((int32_t) (int16_t) mystique->dwgreg.ydst * (mystique->dwgreg.pitch & PITCH_MASK)) + mystique->dwgreg.ydstorg; } - static void blit_trap(mystique_t *mystique) { - svga_t *svga = &mystique->svga; - uint32_t z_back, r_back, g_back, b_back; - int z_write; - int y; + svga_t *svga = &mystique->svga; + uint32_t z_back; + uint32_t r_back; + uint32_t g_back; + uint32_t b_back; + int z_write; + int y; const int trans_sel = (mystique->dwgreg.dwgctrl_running & DWGCTRL_TRANS_MASK) >> DWGCTRL_TRANS_SHIFT; mystique->trap_count++; switch (mystique->dwgreg.dwgctrl_running & DWGCTRL_ATYPE_MASK) { - case DWGCTRL_ATYPE_BLK: - case DWGCTRL_ATYPE_RPL: - for (y = 0; y < mystique->dwgreg.length; y++) { - uint8_t const * const trans = &trans_masks[trans_sel][(mystique->dwgreg.selline & 3) * 4]; - int16_t x_l = mystique->dwgreg.fxleft & 0xffff; - int16_t x_r = mystique->dwgreg.fxright & 0xffff; - int yoff = (mystique->dwgreg.yoff + mystique->dwgreg.ydst) & 7; + case DWGCTRL_ATYPE_BLK: + case DWGCTRL_ATYPE_RPL: + for (y = 0; y < mystique->dwgreg.length; y++) { + uint8_t const *const trans = &trans_masks[trans_sel][(mystique->dwgreg.selline & 3) * 4]; + int16_t x_l = mystique->dwgreg.fxleft & 0xffff; + int16_t x_r = mystique->dwgreg.fxright & 0xffff; + int yoff = (mystique->dwgreg.yoff + mystique->dwgreg.ydst) & 7; - while (x_l != x_r) { - if (x_l >= mystique->dwgreg.cxleft && x_l <= mystique->dwgreg.cxright && - mystique->dwgreg.ydst_lin >= mystique->dwgreg.ytop && mystique->dwgreg.ydst_lin <= mystique->dwgreg.ybot && - trans[x_l & 3]) { - int xoff = (mystique->dwgreg.xoff + x_l) & 7; - int pattern = mystique->dwgreg.pattern[yoff][xoff]; - uint32_t dst; + while (x_l != x_r) { + if (x_l >= mystique->dwgreg.cxleft && x_l <= mystique->dwgreg.cxright && mystique->dwgreg.ydst_lin >= mystique->dwgreg.ytop && mystique->dwgreg.ydst_lin <= mystique->dwgreg.ybot && trans[x_l & 3]) { + int xoff = (mystique->dwgreg.xoff + (x_l & 7)) & 15; + int pattern = mystique->dwgreg.pattern[yoff][xoff]; + uint32_t dst; - switch (mystique->maccess_running & MACCESS_PWIDTH_MASK) { - case MACCESS_PWIDTH_8: - svga->vram[(mystique->dwgreg.ydst_lin + x_l) & mystique->vram_mask] = - (pattern ? mystique->dwgreg.fcol : mystique->dwgreg.bcol) & 0xff; - svga->changedvram[((mystique->dwgreg.ydst_lin + x_l) & mystique->vram_mask) >> 12] = changeframecount; - break; + switch (mystique->maccess_running & MACCESS_PWIDTH_MASK) { + case MACCESS_PWIDTH_8: + svga->vram[(mystique->dwgreg.ydst_lin + x_l) & mystique->vram_mask] = (pattern ? mystique->dwgreg.fcol : mystique->dwgreg.bcol) & 0xff; + svga->changedvram[((mystique->dwgreg.ydst_lin + x_l) & mystique->vram_mask) >> 12] = changeframecount; + break; - case MACCESS_PWIDTH_16: - ((uint16_t *)svga->vram)[(mystique->dwgreg.ydst_lin + x_l) & mystique->vram_mask_w] = - (pattern ? mystique->dwgreg.fcol : mystique->dwgreg.bcol) & 0xffff; - svga->changedvram[((mystique->dwgreg.ydst_lin + x_l) & mystique->vram_mask_w) >> 11] = changeframecount; - break; + case MACCESS_PWIDTH_16: + ((uint16_t *) svga->vram)[(mystique->dwgreg.ydst_lin + x_l) & mystique->vram_mask_w] = (pattern ? mystique->dwgreg.fcol : mystique->dwgreg.bcol) & 0xffff; + svga->changedvram[((mystique->dwgreg.ydst_lin + x_l) & mystique->vram_mask_w) >> 11] = changeframecount; + break; - case MACCESS_PWIDTH_24: - dst = *(uint32_t *)(&svga->vram[((mystique->dwgreg.ydst_lin + x_l) * 3) & mystique->vram_mask]) & 0xff000000; - *(uint32_t *)(&svga->vram[((mystique->dwgreg.ydst_lin + x_l) * 3) & mystique->vram_mask]) = - ((pattern ? mystique->dwgreg.fcol : mystique->dwgreg.bcol) & 0xffffff) | dst; - svga->changedvram[(((mystique->dwgreg.ydst_lin + x_l) * 3) & mystique->vram_mask) >> 12] = changeframecount; - break; + case MACCESS_PWIDTH_24: + dst = *(uint32_t *) (&svga->vram[((mystique->dwgreg.ydst_lin + x_l) * 3) & mystique->vram_mask]) & 0xff000000; + *(uint32_t *) (&svga->vram[((mystique->dwgreg.ydst_lin + x_l) * 3) & mystique->vram_mask]) = ((pattern ? mystique->dwgreg.fcol : mystique->dwgreg.bcol) & 0xffffff) | dst; + svga->changedvram[(((mystique->dwgreg.ydst_lin + x_l) * 3) & mystique->vram_mask) >> 12] = changeframecount; + break; - case MACCESS_PWIDTH_32: - ((uint32_t *)svga->vram)[(mystique->dwgreg.ydst_lin + x_l) & mystique->vram_mask_l] = - pattern ? mystique->dwgreg.fcol : mystique->dwgreg.bcol; - svga->changedvram[((mystique->dwgreg.ydst_lin + x_l) & mystique->vram_mask_l) >> 10] = changeframecount; - break; + case MACCESS_PWIDTH_32: + ((uint32_t *) svga->vram)[(mystique->dwgreg.ydst_lin + x_l) & mystique->vram_mask_l] = pattern ? mystique->dwgreg.fcol : mystique->dwgreg.bcol; + svga->changedvram[((mystique->dwgreg.ydst_lin + x_l) & mystique->vram_mask_l) >> 10] = changeframecount; + break; - default: - fatal("TRAP BLK/RPL PWIDTH %x %08x\n", mystique->maccess_running & MACCESS_PWIDTH_MASK, mystique->dwgreg.dwgctrl_running); - } - } - x_l++; - mystique->pixel_count++; - } + default: + fatal("TRAP BLK/RPL PWIDTH %x %08x\n", mystique->maccess_running & MACCESS_PWIDTH_MASK, mystique->dwgreg.dwgctrl_running); + } + } + x_l++; + mystique->pixel_count++; + } - if ((int32_t)mystique->dwgreg.ar[1] < 0) { - while ((int32_t)mystique->dwgreg.ar[1] < 0 && mystique->dwgreg.ar[0]) { - mystique->dwgreg.ar[1] += mystique->dwgreg.ar[0]; - mystique->dwgreg.fxleft += (mystique->dwgreg.sgn.sdxl ? -1 : 1); - } - } else - mystique->dwgreg.ar[1] += mystique->dwgreg.ar[2]; + if ((int32_t) mystique->dwgreg.ar[1] < 0) { + while ((int32_t) mystique->dwgreg.ar[1] < 0 && mystique->dwgreg.ar[0]) { + mystique->dwgreg.ar[1] += mystique->dwgreg.ar[0]; + mystique->dwgreg.fxleft += (mystique->dwgreg.sgn.sdxl ? -1 : 1); + } + } else + mystique->dwgreg.ar[1] += mystique->dwgreg.ar[2]; - if ((int32_t)mystique->dwgreg.ar[4] < 0) { - while ((int32_t)mystique->dwgreg.ar[4] < 0 && mystique->dwgreg.ar[6]) { - mystique->dwgreg.ar[4] += mystique->dwgreg.ar[6]; - mystique->dwgreg.fxright += (mystique->dwgreg.sgn.sdxr ? -1 : 1); - } - } else - mystique->dwgreg.ar[4] += mystique->dwgreg.ar[5]; + if ((int32_t) mystique->dwgreg.ar[4] < 0) { + while ((int32_t) mystique->dwgreg.ar[4] < 0 && mystique->dwgreg.ar[6]) { + mystique->dwgreg.ar[4] += mystique->dwgreg.ar[6]; + mystique->dwgreg.fxright += (mystique->dwgreg.sgn.sdxr ? -1 : 1); + } + } else + mystique->dwgreg.ar[4] += mystique->dwgreg.ar[5]; - mystique->dwgreg.ydst++; - mystique->dwgreg.ydst &= 0x7fffff; - mystique->dwgreg.ydst_lin += (mystique->dwgreg.pitch & PITCH_MASK); + mystique->dwgreg.ydst++; + mystique->dwgreg.ydst &= 0x7fffff; + mystique->dwgreg.ydst_lin += (mystique->dwgreg.pitch & PITCH_MASK); - mystique->dwgreg.selline = (mystique->dwgreg.selline + 1) & 7; - } - break; + mystique->dwgreg.selline = (mystique->dwgreg.selline + 1) & 7; + } + break; - case DWGCTRL_ATYPE_RSTR: - for (y = 0; y < mystique->dwgreg.length; y++) { - uint8_t const * const trans = &trans_masks[trans_sel][(mystique->dwgreg.selline & 3) * 4]; - int16_t x_l = mystique->dwgreg.fxleft & 0xffff; - int16_t x_r = mystique->dwgreg.fxright & 0xffff; - int yoff = (mystique->dwgreg.yoff + mystique->dwgreg.ydst) & 7; + case DWGCTRL_ATYPE_RSTR: + for (y = 0; y < mystique->dwgreg.length; y++) { + uint8_t const *const trans = &trans_masks[trans_sel][(mystique->dwgreg.selline & 3) * 4]; + int16_t x_l = mystique->dwgreg.fxleft & 0xffff; + int16_t x_r = mystique->dwgreg.fxright & 0xffff; + int yoff = (mystique->dwgreg.yoff + mystique->dwgreg.ydst) & 7; - while (x_l != x_r) { - if (x_l >= mystique->dwgreg.cxleft && x_l <= mystique->dwgreg.cxright && - mystique->dwgreg.ydst_lin >= mystique->dwgreg.ytop && mystique->dwgreg.ydst_lin <= mystique->dwgreg.ybot && - trans[x_l & 3]) { - int xoff = (mystique->dwgreg.xoff + x_l) & 7; - int pattern = mystique->dwgreg.pattern[yoff][xoff]; - uint32_t src = pattern ? mystique->dwgreg.fcol : mystique->dwgreg.bcol; - uint32_t dst, old_dst; + while (x_l != x_r) { + if (x_l >= mystique->dwgreg.cxleft && x_l <= mystique->dwgreg.cxright && mystique->dwgreg.ydst_lin >= mystique->dwgreg.ytop && mystique->dwgreg.ydst_lin <= mystique->dwgreg.ybot && trans[x_l & 3]) { + int xoff = (mystique->dwgreg.xoff + (x_l & 7)) & 15; + int pattern = mystique->dwgreg.pattern[yoff][xoff]; + uint32_t src = pattern ? mystique->dwgreg.fcol : mystique->dwgreg.bcol; + uint32_t dst; + uint32_t old_dst; - switch (mystique->maccess_running & MACCESS_PWIDTH_MASK) { - case MACCESS_PWIDTH_8: - dst = svga->vram[(mystique->dwgreg.ydst_lin + x_l) & mystique->vram_mask]; + switch (mystique->maccess_running & MACCESS_PWIDTH_MASK) { + case MACCESS_PWIDTH_8: + dst = svga->vram[(mystique->dwgreg.ydst_lin + x_l) & mystique->vram_mask]; - dst = bitop(src, dst, mystique->dwgreg.dwgctrl_running); - svga->vram[(mystique->dwgreg.ydst_lin + x_l) & mystique->vram_mask] = dst; - svga->changedvram[((mystique->dwgreg.ydst_lin + x_l) & mystique->vram_mask) >> 12] = changeframecount; - break; + dst = bitop(src, dst, mystique->dwgreg.dwgctrl_running); + svga->vram[(mystique->dwgreg.ydst_lin + x_l) & mystique->vram_mask] = dst; + svga->changedvram[((mystique->dwgreg.ydst_lin + x_l) & mystique->vram_mask) >> 12] = changeframecount; + break; - case MACCESS_PWIDTH_16: - dst = ((uint16_t *)svga->vram)[(mystique->dwgreg.ydst_lin + x_l) & mystique->vram_mask_w]; + case MACCESS_PWIDTH_16: + dst = ((uint16_t *) svga->vram)[(mystique->dwgreg.ydst_lin + x_l) & mystique->vram_mask_w]; - dst = bitop(src, dst, mystique->dwgreg.dwgctrl_running); - ((uint16_t *)svga->vram)[(mystique->dwgreg.ydst_lin + x_l) & mystique->vram_mask_w] = dst; - svga->changedvram[((mystique->dwgreg.ydst_lin + x_l) & mystique->vram_mask_w) >> 11] = changeframecount; - break; + dst = bitop(src, dst, mystique->dwgreg.dwgctrl_running); + ((uint16_t *) svga->vram)[(mystique->dwgreg.ydst_lin + x_l) & mystique->vram_mask_w] = dst; + svga->changedvram[((mystique->dwgreg.ydst_lin + x_l) & mystique->vram_mask_w) >> 11] = changeframecount; + break; - case MACCESS_PWIDTH_24: - old_dst = *(uint32_t *)&svga->vram[((mystique->dwgreg.ydst_lin + x_l) * 3) & mystique->vram_mask]; + case MACCESS_PWIDTH_24: + old_dst = *(uint32_t *) &svga->vram[((mystique->dwgreg.ydst_lin + x_l) * 3) & mystique->vram_mask]; - dst = bitop(src, old_dst, mystique->dwgreg.dwgctrl_running); - *(uint32_t *)&svga->vram[((mystique->dwgreg.ydst_lin + x_l) * 3) & mystique->vram_mask] = (dst & 0xffffff) | (old_dst & 0xff000000); - svga->changedvram[(((mystique->dwgreg.ydst_lin + x_l) * 3) & mystique->vram_mask) >> 12] = changeframecount; - break; + dst = bitop(src, old_dst, mystique->dwgreg.dwgctrl_running); + *(uint32_t *) &svga->vram[((mystique->dwgreg.ydst_lin + x_l) * 3) & mystique->vram_mask] = (dst & 0xffffff) | (old_dst & 0xff000000); + svga->changedvram[(((mystique->dwgreg.ydst_lin + x_l) * 3) & mystique->vram_mask) >> 12] = changeframecount; + break; - case MACCESS_PWIDTH_32: - dst = ((uint32_t *)svga->vram)[(mystique->dwgreg.ydst_lin + x_l) & mystique->vram_mask_l]; + case MACCESS_PWIDTH_32: + dst = ((uint32_t *) svga->vram)[(mystique->dwgreg.ydst_lin + x_l) & mystique->vram_mask_l]; - dst = bitop(src, dst, mystique->dwgreg.dwgctrl_running); - ((uint32_t *)svga->vram)[(mystique->dwgreg.ydst_lin + x_l) & mystique->vram_mask_l] = dst; - svga->changedvram[((mystique->dwgreg.ydst_lin + x_l) & mystique->vram_mask_l) >> 10] = changeframecount; - break; + dst = bitop(src, dst, mystique->dwgreg.dwgctrl_running); + ((uint32_t *) svga->vram)[(mystique->dwgreg.ydst_lin + x_l) & mystique->vram_mask_l] = dst; + svga->changedvram[((mystique->dwgreg.ydst_lin + x_l) & mystique->vram_mask_l) >> 10] = changeframecount; + break; - default: - fatal("TRAP RSTR PWIDTH %x %08x\n", mystique->maccess_running & MACCESS_PWIDTH_MASK, mystique->dwgreg.dwgctrl_running); - } - } - x_l++; - mystique->pixel_count++; - } + default: + fatal("TRAP RSTR PWIDTH %x %08x\n", mystique->maccess_running & MACCESS_PWIDTH_MASK, mystique->dwgreg.dwgctrl_running); + } + } + x_l++; + mystique->pixel_count++; + } - if ((int32_t)mystique->dwgreg.ar[1] < 0) { - while ((int32_t)mystique->dwgreg.ar[1] < 0 && mystique->dwgreg.ar[0]) { - mystique->dwgreg.ar[1] += mystique->dwgreg.ar[0]; - mystique->dwgreg.fxleft += (mystique->dwgreg.sgn.sdxl ? -1 : 1); - } - } else - mystique->dwgreg.ar[1] += mystique->dwgreg.ar[2]; + if ((int32_t) mystique->dwgreg.ar[1] < 0) { + while ((int32_t) mystique->dwgreg.ar[1] < 0 && mystique->dwgreg.ar[0]) { + mystique->dwgreg.ar[1] += mystique->dwgreg.ar[0]; + mystique->dwgreg.fxleft += (mystique->dwgreg.sgn.sdxl ? -1 : 1); + } + } else + mystique->dwgreg.ar[1] += mystique->dwgreg.ar[2]; - if ((int32_t)mystique->dwgreg.ar[4] < 0) { - while ((int32_t)mystique->dwgreg.ar[4] < 0 && mystique->dwgreg.ar[6]) { - mystique->dwgreg.ar[4] += mystique->dwgreg.ar[6]; - mystique->dwgreg.fxright += (mystique->dwgreg.sgn.sdxr ? -1 : 1); - } - } else - mystique->dwgreg.ar[4] += mystique->dwgreg.ar[5]; + if ((int32_t) mystique->dwgreg.ar[4] < 0) { + while ((int32_t) mystique->dwgreg.ar[4] < 0 && mystique->dwgreg.ar[6]) { + mystique->dwgreg.ar[4] += mystique->dwgreg.ar[6]; + mystique->dwgreg.fxright += (mystique->dwgreg.sgn.sdxr ? -1 : 1); + } + } else + mystique->dwgreg.ar[4] += mystique->dwgreg.ar[5]; - mystique->dwgreg.ydst++; - mystique->dwgreg.ydst &= 0x7fffff; - mystique->dwgreg.ydst_lin += (mystique->dwgreg.pitch & PITCH_MASK); + mystique->dwgreg.ydst++; + mystique->dwgreg.ydst &= 0x7fffff; + mystique->dwgreg.ydst_lin += (mystique->dwgreg.pitch & PITCH_MASK); - mystique->dwgreg.selline = (mystique->dwgreg.selline + 1) & 7; - } - break; + mystique->dwgreg.selline = (mystique->dwgreg.selline + 1) & 7; + } + break; - case DWGCTRL_ATYPE_I: - case DWGCTRL_ATYPE_ZI: - z_write = ((mystique->dwgreg.dwgctrl_running & DWGCTRL_ATYPE_MASK) == DWGCTRL_ATYPE_ZI); + case DWGCTRL_ATYPE_I: + case DWGCTRL_ATYPE_ZI: + z_write = ((mystique->dwgreg.dwgctrl_running & DWGCTRL_ATYPE_MASK) == DWGCTRL_ATYPE_ZI); - for (y = 0; y < mystique->dwgreg.length; y++) { - uint8_t const * const trans = &trans_masks[trans_sel][(mystique->dwgreg.selline & 3) * 4]; - uint16_t *z_p = (uint16_t *)&svga->vram[(mystique->dwgreg.ydst_lin*2 + mystique->dwgreg.zorg) & mystique->vram_mask]; - int16_t x_l = mystique->dwgreg.fxleft & 0xffff; - int16_t x_r = mystique->dwgreg.fxright & 0xffff; - int16_t old_x_l = x_l; - int dx; + for (y = 0; y < mystique->dwgreg.length; y++) { + uint8_t const *const trans = &trans_masks[trans_sel][(mystique->dwgreg.selline & 3) * 4]; + uint16_t *z_p = (uint16_t *) &svga->vram[(mystique->dwgreg.ydst_lin * 2 + mystique->dwgreg.zorg) & mystique->vram_mask]; + int16_t x_l = mystique->dwgreg.fxleft & 0xffff; + int16_t x_r = mystique->dwgreg.fxright & 0xffff; + int16_t old_x_l = x_l; + int dx; - z_back = mystique->dwgreg.dr[0]; - r_back = mystique->dwgreg.dr[4]; - g_back = mystique->dwgreg.dr[8]; - b_back = mystique->dwgreg.dr[12]; + z_back = mystique->dwgreg.dr[0]; + r_back = mystique->dwgreg.dr[4]; + g_back = mystique->dwgreg.dr[8]; + b_back = mystique->dwgreg.dr[12]; - while (x_l != x_r) { - if (x_l >= mystique->dwgreg.cxleft && x_l <= mystique->dwgreg.cxright && - mystique->dwgreg.ydst_lin >= mystique->dwgreg.ytop && mystique->dwgreg.ydst_lin <= mystique->dwgreg.ybot && - trans[x_l & 3]) { - uint16_t z = ((int32_t)mystique->dwgreg.dr[0] < 0) ? 0 : (mystique->dwgreg.dr[0] >> 15); - uint16_t old_z = z_p[x_l]; + while (x_l != x_r) { + if (x_l >= mystique->dwgreg.cxleft && x_l <= mystique->dwgreg.cxright && mystique->dwgreg.ydst_lin >= mystique->dwgreg.ytop && mystique->dwgreg.ydst_lin <= mystique->dwgreg.ybot && trans[x_l & 3]) { + uint16_t z = ((int32_t) mystique->dwgreg.dr[0] < 0) ? 0 : (mystique->dwgreg.dr[0] >> 15); + uint16_t old_z = z_p[x_l]; - if (z_check(z, old_z, mystique->dwgreg.dwgctrl_running & DWGCTRL_ZMODE_MASK)) { - uint32_t dst = 0, old_dst; - int r = 0, g = 0, b = 0; + if (z_check(z, old_z, mystique->dwgreg.dwgctrl_running & DWGCTRL_ZMODE_MASK)) { + uint32_t dst = 0; + uint32_t old_dst; + int r = 0; + int g = 0; + int b = 0; - if (!(mystique->dwgreg.dr[4] & (1 << 23))) - r = (mystique->dwgreg.dr[4] >> 15) & 0xff; - if (!(mystique->dwgreg.dr[8] & (1 << 23))) - g = (mystique->dwgreg.dr[8] >> 15) & 0xff; - if (!(mystique->dwgreg.dr[12] & (1 << 23))) - b = (mystique->dwgreg.dr[12] >> 15) & 0xff; + if (!(mystique->dwgreg.dr[4] & (1 << 23))) + r = (mystique->dwgreg.dr[4] >> 15) & 0xff; + if (!(mystique->dwgreg.dr[8] & (1 << 23))) + g = (mystique->dwgreg.dr[8] >> 15) & 0xff; + if (!(mystique->dwgreg.dr[12] & (1 << 23))) + b = (mystique->dwgreg.dr[12] >> 15) & 0xff; - if (z_write) - z_p[x_l] = z; + if (z_write) + z_p[x_l] = z; - switch (mystique->maccess_running & MACCESS_PWIDTH_MASK) { - case MACCESS_PWIDTH_8: - svga->vram[(mystique->dwgreg.ydst_lin + x_l) & mystique->vram_mask] = dst; - svga->changedvram[((mystique->dwgreg.ydst_lin + x_l) & mystique->vram_mask) >> 12] = changeframecount; - break; + switch (mystique->maccess_running & MACCESS_PWIDTH_MASK) { + case MACCESS_PWIDTH_8: + svga->vram[(mystique->dwgreg.ydst_lin + x_l) & mystique->vram_mask] = dst; + svga->changedvram[((mystique->dwgreg.ydst_lin + x_l) & mystique->vram_mask) >> 12] = changeframecount; + break; - case MACCESS_PWIDTH_16: - dst = dither(mystique, r, g, b, x_l & 1, mystique->dwgreg.selline & 1); - ((uint16_t *)svga->vram)[(mystique->dwgreg.ydst_lin + x_l) & mystique->vram_mask_w] = dst; - svga->changedvram[((mystique->dwgreg.ydst_lin + x_l) & mystique->vram_mask_w) >> 11] = changeframecount; - break; + case MACCESS_PWIDTH_16: + dst = dither(mystique, r, g, b, x_l & 1, mystique->dwgreg.selline & 1); + ((uint16_t *) svga->vram)[(mystique->dwgreg.ydst_lin + x_l) & mystique->vram_mask_w] = dst; + svga->changedvram[((mystique->dwgreg.ydst_lin + x_l) & mystique->vram_mask_w) >> 11] = changeframecount; + break; - case MACCESS_PWIDTH_24: - old_dst = *(uint32_t *)(&svga->vram[((mystique->dwgreg.ydst_lin + x_l) * 3) & mystique->vram_mask]) & 0xff000000; - *(uint32_t *)(&svga->vram[((mystique->dwgreg.ydst_lin + x_l) * 3) & mystique->vram_mask]) = old_dst | dst; - svga->changedvram[(((mystique->dwgreg.ydst_lin + x_l) * 3) & mystique->vram_mask) >> 12] = changeframecount; - break; + case MACCESS_PWIDTH_24: + old_dst = *(uint32_t *) (&svga->vram[((mystique->dwgreg.ydst_lin + x_l) * 3) & mystique->vram_mask]) & 0xff000000; + *(uint32_t *) (&svga->vram[((mystique->dwgreg.ydst_lin + x_l) * 3) & mystique->vram_mask]) = old_dst | dst; + svga->changedvram[(((mystique->dwgreg.ydst_lin + x_l) * 3) & mystique->vram_mask) >> 12] = changeframecount; + break; - case MACCESS_PWIDTH_32: - ((uint32_t *)svga->vram)[(mystique->dwgreg.ydst_lin + x_l) & mystique->vram_mask_l] = b | (g << 8) | (r << 16); - svga->changedvram[((mystique->dwgreg.ydst_lin + x_l) & mystique->vram_mask_l) >> 10] = changeframecount; - break; + case MACCESS_PWIDTH_32: + ((uint32_t *) svga->vram)[(mystique->dwgreg.ydst_lin + x_l) & mystique->vram_mask_l] = b | (g << 8) | (r << 16); + svga->changedvram[((mystique->dwgreg.ydst_lin + x_l) & mystique->vram_mask_l) >> 10] = changeframecount; + break; - default: - fatal("TRAP BLK/RPL PWIDTH %x %08x\n", mystique->maccess_running & MACCESS_PWIDTH_MASK, mystique->dwgreg.dwgctrl_running); - } - } - } + default: + fatal("TRAP BLK/RPL PWIDTH %x %08x\n", mystique->maccess_running & MACCESS_PWIDTH_MASK, mystique->dwgreg.dwgctrl_running); + } + } + } - mystique->dwgreg.dr[0] += mystique->dwgreg.dr[2]; - mystique->dwgreg.dr[4] += mystique->dwgreg.dr[6]; - mystique->dwgreg.dr[8] += mystique->dwgreg.dr[10]; - mystique->dwgreg.dr[12] += mystique->dwgreg.dr[14]; + mystique->dwgreg.dr[0] += mystique->dwgreg.dr[2]; + mystique->dwgreg.dr[4] += mystique->dwgreg.dr[6]; + mystique->dwgreg.dr[8] += mystique->dwgreg.dr[10]; + mystique->dwgreg.dr[12] += mystique->dwgreg.dr[14]; - x_l++; - mystique->pixel_count++; - } + x_l++; + mystique->pixel_count++; + } - mystique->dwgreg.dr[0] = z_back + mystique->dwgreg.dr[3]; - mystique->dwgreg.dr[4] = r_back + mystique->dwgreg.dr[7]; - mystique->dwgreg.dr[8] = g_back + mystique->dwgreg.dr[11]; - mystique->dwgreg.dr[12] = b_back + mystique->dwgreg.dr[15]; + mystique->dwgreg.dr[0] = z_back + mystique->dwgreg.dr[3]; + mystique->dwgreg.dr[4] = r_back + mystique->dwgreg.dr[7]; + mystique->dwgreg.dr[8] = g_back + mystique->dwgreg.dr[11]; + mystique->dwgreg.dr[12] = b_back + mystique->dwgreg.dr[15]; - while ((int32_t)mystique->dwgreg.ar[1] < 0 && mystique->dwgreg.ar[0]) { - mystique->dwgreg.ar[1] += mystique->dwgreg.ar[0]; - mystique->dwgreg.fxleft += (mystique->dwgreg.sgn.sdxl ? -1 : 1); - } - mystique->dwgreg.ar[1] += mystique->dwgreg.ar[2]; + while ((int32_t) mystique->dwgreg.ar[1] < 0 && mystique->dwgreg.ar[0]) { + mystique->dwgreg.ar[1] += mystique->dwgreg.ar[0]; + mystique->dwgreg.fxleft += (mystique->dwgreg.sgn.sdxl ? -1 : 1); + } + mystique->dwgreg.ar[1] += mystique->dwgreg.ar[2]; - while ((int32_t)mystique->dwgreg.ar[4] < 0 && mystique->dwgreg.ar[6]) { - mystique->dwgreg.ar[4] += mystique->dwgreg.ar[6]; - mystique->dwgreg.fxright += (mystique->dwgreg.sgn.sdxr ? -1 : 1); - } - mystique->dwgreg.ar[4] += mystique->dwgreg.ar[5]; + while ((int32_t) mystique->dwgreg.ar[4] < 0 && mystique->dwgreg.ar[6]) { + mystique->dwgreg.ar[4] += mystique->dwgreg.ar[6]; + mystique->dwgreg.fxright += (mystique->dwgreg.sgn.sdxr ? -1 : 1); + } + mystique->dwgreg.ar[4] += mystique->dwgreg.ar[5]; - dx = (int16_t)((mystique->dwgreg.fxleft - old_x_l) & 0xffff); - mystique->dwgreg.dr[0] += dx*mystique->dwgreg.dr[2]; - mystique->dwgreg.dr[4] += dx*mystique->dwgreg.dr[6]; - mystique->dwgreg.dr[8] += dx*mystique->dwgreg.dr[10]; - mystique->dwgreg.dr[12] += dx*mystique->dwgreg.dr[14]; + dx = (int16_t) ((mystique->dwgreg.fxleft - old_x_l) & 0xffff); + mystique->dwgreg.dr[0] += dx * mystique->dwgreg.dr[2]; + mystique->dwgreg.dr[4] += dx * mystique->dwgreg.dr[6]; + mystique->dwgreg.dr[8] += dx * mystique->dwgreg.dr[10]; + mystique->dwgreg.dr[12] += dx * mystique->dwgreg.dr[14]; - mystique->dwgreg.ydst++; - mystique->dwgreg.ydst &= 0x7fffff; - mystique->dwgreg.ydst_lin += (mystique->dwgreg.pitch & PITCH_MASK); + mystique->dwgreg.ydst++; + mystique->dwgreg.ydst &= 0x7fffff; + mystique->dwgreg.ydst_lin += (mystique->dwgreg.pitch & PITCH_MASK); - mystique->dwgreg.selline = (mystique->dwgreg.selline + 1) & 7; - } - break; + mystique->dwgreg.selline = (mystique->dwgreg.selline + 1) & 7; + } + break; - default: - fatal("Unknown atype %03x %08x TRAP\n", mystique->dwgreg.dwgctrl_running & DWGCTRL_ATYPE_MASK, mystique->dwgreg.dwgctrl_running); + default: + fatal("Unknown atype %03x %08x TRAP\n", mystique->dwgreg.dwgctrl_running & DWGCTRL_ATYPE_MASK, mystique->dwgreg.dwgctrl_running); } mystique->blitter_complete_refcount++; } - -static int texture_read(mystique_t *mystique, int *tex_r, int *tex_g, int *tex_b, int *atransp) +static int +texture_read(mystique_t *mystique, int *tex_r, int *tex_g, int *tex_b, int *atransp) { svga_t *svga = &mystique->svga; - const int tex_shift = 3 + ((mystique->dwgreg.texctl & TEXCTL_TPITCH_MASK) >> TEXCTL_TPITCH_SHIFT); - const unsigned int palsel = mystique->dwgreg.texctl & TEXCTL_PALSEL_MASK; - const uint16_t tckey = mystique->dwgreg.textrans & TEXTRANS_TCKEY_MASK; - const uint16_t tkmask = (mystique->dwgreg.textrans & TEXTRANS_TKMASK_MASK) >> TEXTRANS_TKMASK_SHIFT; - const unsigned int w_mask = (mystique->dwgreg.texwidth & TEXWIDTH_TWMASK_MASK) >> TEXWIDTH_TWMASK_SHIFT; - const unsigned int h_mask = (mystique->dwgreg.texheight & TEXHEIGHT_THMASK_MASK) >> TEXHEIGHT_THMASK_SHIFT; - uint16_t src = 0; - int s, t; + const int tex_shift = 3 + ((mystique->dwgreg.texctl & TEXCTL_TPITCH_MASK) >> TEXCTL_TPITCH_SHIFT); + const unsigned int palsel = mystique->dwgreg.texctl & TEXCTL_PALSEL_MASK; + const uint16_t tckey = mystique->dwgreg.textrans & TEXTRANS_TCKEY_MASK; + const uint16_t tkmask = (mystique->dwgreg.textrans & TEXTRANS_TKMASK_MASK) >> TEXTRANS_TKMASK_SHIFT; + const unsigned int w_mask = (mystique->dwgreg.texwidth & TEXWIDTH_TWMASK_MASK) >> TEXWIDTH_TWMASK_SHIFT; + const unsigned int h_mask = (mystique->dwgreg.texheight & TEXHEIGHT_THMASK_MASK) >> TEXHEIGHT_THMASK_SHIFT; + uint16_t src = 0; + int s; + int t; if (mystique->dwgreg.texctl & TEXCTL_NPCEN) { - const int s_shift = 20 - (mystique->dwgreg.texwidth & TEXWIDTH_TW_MASK); - const int t_shift = 20 - (mystique->dwgreg.texheight & TEXHEIGHT_TH_MASK); + const int s_shift = 20 - (mystique->dwgreg.texwidth & TEXWIDTH_TW_MASK); + const int t_shift = 20 - (mystique->dwgreg.texheight & TEXHEIGHT_TH_MASK); - s = (int32_t)mystique->dwgreg.tmr[6] >> s_shift; - t = (int32_t)mystique->dwgreg.tmr[7] >> t_shift; + s = (int32_t) mystique->dwgreg.tmr[6] >> s_shift; + t = (int32_t) mystique->dwgreg.tmr[7] >> t_shift; } else { - const int s_shift = (20 + 16) - (mystique->dwgreg.texwidth & TEXWIDTH_TW_MASK); - const int t_shift = (20 + 16) - (mystique->dwgreg.texheight & TEXHEIGHT_TH_MASK); - int64_t q = mystique->dwgreg.tmr[8] ? ((0x100000000ll / (int64_t)(int32_t)mystique->dwgreg.tmr[8]) /*>> 16*/) : 0; + const int s_shift = (20 + 16) - (mystique->dwgreg.texwidth & TEXWIDTH_TW_MASK); + const int t_shift = (20 + 16) - (mystique->dwgreg.texheight & TEXHEIGHT_TH_MASK); + int64_t q = mystique->dwgreg.tmr[8] ? (0x100000000LL / (int64_t) (int32_t) mystique->dwgreg.tmr[8] /*>> 16*/) : 0; - s = (((int64_t)(int32_t)mystique->dwgreg.tmr[6] * q) /*<< 8*/) >> s_shift;/*((16+20)-12);*/ - t = (((int64_t)(int32_t)mystique->dwgreg.tmr[7] * q) /*<< 8*/) >> t_shift;/*((16+20)-9);*/ + s = ((int64_t) (int32_t) mystique->dwgreg.tmr[6] * q /*<< 8*/) >> s_shift; /*((16+20)-12);*/ + t = ((int64_t) (int32_t) mystique->dwgreg.tmr[7] * q /*<< 8*/) >> t_shift; /*((16+20)-9);*/ } if (mystique->dwgreg.texctl & TEXCTL_CLAMPU) { - if (s < 0) - s = 0; - else if (s > w_mask) - s = w_mask; + if (s < 0) + s = 0; + else if (s > w_mask) + s = w_mask; } else - s &= w_mask; + s &= w_mask; if (mystique->dwgreg.texctl & TEXCTL_CLAMPV) { - if (t < 0) - t = 0; - else if (t > h_mask) - t = h_mask; + if (t < 0) + t = 0; + else if (t > h_mask) + t = h_mask; } else - t &= h_mask; + t &= h_mask; switch (mystique->dwgreg.texctl & TEXCTL_TEXFORMAT_MASK) { - case TEXCTL_TEXFORMAT_TW4: - src = svga->vram[(mystique->dwgreg.texorg + (((t << tex_shift) + s) >> 1)) & mystique->vram_mask]; - if (s & 1) - src >>= 4; - else - src &= 0xf; - *tex_r = mystique->lut[src | palsel].r; - *tex_g = mystique->lut[src | palsel].g; - *tex_b = mystique->lut[src | palsel].b; - *atransp = 0; - break; - case TEXCTL_TEXFORMAT_TW8: - src = svga->vram[(mystique->dwgreg.texorg + (t << tex_shift) + s) & mystique->vram_mask]; - *tex_r = mystique->lut[src].r; - *tex_g = mystique->lut[src].g; - *tex_b = mystique->lut[src].b; - *atransp = 0; - break; - case TEXCTL_TEXFORMAT_TW15: - src = ((uint16_t *)svga->vram)[((mystique->dwgreg.texorg >> 1) + (t << tex_shift) + s) & mystique->vram_mask_w]; - *tex_r = ((src >> 10) & 0x1f) << 3; - *tex_g = ((src >> 5) & 0x1f) << 3; - *tex_b = (src & 0x1f) << 3; - if (((src >> 15) & mystique->dwgreg.ta_mask) == mystique->dwgreg.ta_key) - *atransp = 1; - else - *atransp = 0; - break; - case TEXCTL_TEXFORMAT_TW16: - src = ((uint16_t *)svga->vram)[((mystique->dwgreg.texorg >> 1) + (t << tex_shift) + s) & mystique->vram_mask_w]; - *tex_r = (src >> 11) << 3; - *tex_g = ((src >> 5) & 0x3f) << 2; - *tex_b = (src & 0x1f) << 3; - *atransp = 0; - break; - default: - fatal("Unknown texture format %i\n", mystique->dwgreg.texctl & TEXCTL_TEXFORMAT_MASK); - break; + case TEXCTL_TEXFORMAT_TW4: + src = svga->vram[(mystique->dwgreg.texorg + (((t << tex_shift) + s) >> 1)) & mystique->vram_mask]; + if (s & 1) + src >>= 4; + else + src &= 0xf; + *tex_r = mystique->lut[src | palsel].r; + *tex_g = mystique->lut[src | palsel].g; + *tex_b = mystique->lut[src | palsel].b; + *atransp = 0; + break; + case TEXCTL_TEXFORMAT_TW8: + src = svga->vram[(mystique->dwgreg.texorg + (t << tex_shift) + s) & mystique->vram_mask]; + *tex_r = mystique->lut[src].r; + *tex_g = mystique->lut[src].g; + *tex_b = mystique->lut[src].b; + *atransp = 0; + break; + case TEXCTL_TEXFORMAT_TW15: + src = ((uint16_t *) svga->vram)[((mystique->dwgreg.texorg >> 1) + (t << tex_shift) + s) & mystique->vram_mask_w]; + *tex_r = ((src >> 10) & 0x1f) << 3; + *tex_g = ((src >> 5) & 0x1f) << 3; + *tex_b = (src & 0x1f) << 3; + if (((src >> 15) & mystique->dwgreg.ta_mask) == mystique->dwgreg.ta_key) + *atransp = 1; + else + *atransp = 0; + break; + case TEXCTL_TEXFORMAT_TW16: + src = ((uint16_t *) svga->vram)[((mystique->dwgreg.texorg >> 1) + (t << tex_shift) + s) & mystique->vram_mask_w]; + *tex_r = (src >> 11) << 3; + *tex_g = ((src >> 5) & 0x3f) << 2; + *tex_b = (src & 0x1f) << 3; + *atransp = 0; + break; + default: + fatal("Unknown texture format %i\n", mystique->dwgreg.texctl & TEXCTL_TEXFORMAT_MASK); + break; } return ((src & tkmask) == tckey); } - static void blit_texture_trap(mystique_t *mystique) { - svga_t *svga = &mystique->svga; - int y; - int z_write; + svga_t *svga = &mystique->svga; + int y; + int z_write; const int trans_sel = (mystique->dwgreg.dwgctrl_running & DWGCTRL_TRANS_MASK) >> DWGCTRL_TRANS_SHIFT; - const int dest32 = ((mystique->maccess_running & MACCESS_PWIDTH_MASK) == MACCESS_PWIDTH_32); + const int dest32 = ((mystique->maccess_running & MACCESS_PWIDTH_MASK) == MACCESS_PWIDTH_32); mystique->trap_count++; switch (mystique->dwgreg.dwgctrl_running & DWGCTRL_ATYPE_MASK) { - case DWGCTRL_ATYPE_I: - case DWGCTRL_ATYPE_ZI: - z_write = ((mystique->dwgreg.dwgctrl_running & DWGCTRL_ATYPE_MASK) == DWGCTRL_ATYPE_ZI); + case DWGCTRL_ATYPE_I: + case DWGCTRL_ATYPE_ZI: + z_write = ((mystique->dwgreg.dwgctrl_running & DWGCTRL_ATYPE_MASK) == DWGCTRL_ATYPE_ZI); - for (y = 0; y < mystique->dwgreg.length; y++) { - uint8_t const * const trans = &trans_masks[trans_sel][(mystique->dwgreg.selline & 3) * 4]; - uint16_t *z_p = (uint16_t *)&svga->vram[(mystique->dwgreg.ydst_lin*2 + mystique->dwgreg.zorg) & mystique->vram_mask]; - int16_t x_l = mystique->dwgreg.fxleft & 0xffff; - int16_t x_r = mystique->dwgreg.fxright & 0xffff; - int16_t old_x_l = x_l; - int dx; + for (y = 0; y < mystique->dwgreg.length; y++) { + uint8_t const *const trans = &trans_masks[trans_sel][(mystique->dwgreg.selline & 3) * 4]; + uint16_t *z_p = (uint16_t *) &svga->vram[(mystique->dwgreg.ydst_lin * 2 + mystique->dwgreg.zorg) & mystique->vram_mask]; + int16_t x_l = mystique->dwgreg.fxleft & 0xffff; + int16_t x_r = mystique->dwgreg.fxright & 0xffff; + int16_t old_x_l = x_l; + int dx; - uint32_t z_back = mystique->dwgreg.dr[0]; - uint32_t r_back = mystique->dwgreg.dr[4]; - uint32_t g_back = mystique->dwgreg.dr[8]; - uint32_t b_back = mystique->dwgreg.dr[12]; - uint32_t s_back = mystique->dwgreg.tmr[6]; - uint32_t t_back = mystique->dwgreg.tmr[7]; - uint32_t q_back = mystique->dwgreg.tmr[8]; + uint32_t z_back = mystique->dwgreg.dr[0]; + uint32_t r_back = mystique->dwgreg.dr[4]; + uint32_t g_back = mystique->dwgreg.dr[8]; + uint32_t b_back = mystique->dwgreg.dr[12]; + uint32_t s_back = mystique->dwgreg.tmr[6]; + uint32_t t_back = mystique->dwgreg.tmr[7]; + uint32_t q_back = mystique->dwgreg.tmr[8]; - while (x_l != x_r) { - if (x_l >= mystique->dwgreg.cxleft && x_l <= mystique->dwgreg.cxright && - mystique->dwgreg.ydst_lin >= mystique->dwgreg.ytop && mystique->dwgreg.ydst_lin <= mystique->dwgreg.ybot && - trans[x_l & 3]) { - uint16_t z = ((int32_t)mystique->dwgreg.dr[0] < 0) ? 0 : (mystique->dwgreg.dr[0] >> 15); - uint16_t old_z = z_p[x_l]; + while (x_l != x_r) { + if (x_l >= mystique->dwgreg.cxleft && x_l <= mystique->dwgreg.cxright && mystique->dwgreg.ydst_lin >= mystique->dwgreg.ytop && mystique->dwgreg.ydst_lin <= mystique->dwgreg.ybot && trans[x_l & 3]) { + uint16_t z = ((int32_t) mystique->dwgreg.dr[0] < 0) ? 0 : (mystique->dwgreg.dr[0] >> 15); + uint16_t old_z = z_p[x_l]; - if (z_check(z, old_z, mystique->dwgreg.dwgctrl_running & DWGCTRL_ZMODE_MASK)) { - int tex_r = 0, tex_g = 0, tex_b = 0; - int ctransp, atransp = 0; - int i_r = 0, i_g = 0, i_b = 0; + if (z_check(z, old_z, mystique->dwgreg.dwgctrl_running & DWGCTRL_ZMODE_MASK)) { + int tex_r = 0; + int tex_g = 0; + int tex_b = 0; + int ctransp; + int atransp = 0; + int i_r = 0; + int i_g = 0; + int i_b = 0; - if (!(mystique->dwgreg.dr[4] & (1 << 23))) - i_r = (mystique->dwgreg.dr[4] >> 15) & 0xff; - if (!(mystique->dwgreg.dr[8] & (1 << 23))) - i_g = (mystique->dwgreg.dr[8] >> 15) & 0xff; - if (!(mystique->dwgreg.dr[12] & (1 << 23))) - i_b = (mystique->dwgreg.dr[12] >> 15) & 0xff; + if (!(mystique->dwgreg.dr[4] & (1 << 23))) + i_r = (mystique->dwgreg.dr[4] >> 15) & 0xff; + if (!(mystique->dwgreg.dr[8] & (1 << 23))) + i_g = (mystique->dwgreg.dr[8] >> 15) & 0xff; + if (!(mystique->dwgreg.dr[12] & (1 << 23))) + i_b = (mystique->dwgreg.dr[12] >> 15) & 0xff; - ctransp = texture_read(mystique, &tex_r, &tex_g, &tex_b, &atransp); + ctransp = texture_read(mystique, &tex_r, &tex_g, &tex_b, &atransp); - switch (mystique->dwgreg.texctl & (TEXCTL_TMODULATE | TEXCTL_STRANS | TEXCTL_ITRANS | TEXCTL_DECALCKEY)) { - case 0: - if (ctransp) - goto skip_pixel; - if (atransp) { - tex_r = i_r; - tex_g = i_g; - tex_b = i_b; - } - break; + switch (mystique->dwgreg.texctl & (TEXCTL_TMODULATE | TEXCTL_STRANS | TEXCTL_ITRANS | TEXCTL_DECALCKEY)) { + case 0: + if (ctransp) + goto skip_pixel; + if (atransp) { + tex_r = i_r; + tex_g = i_g; + tex_b = i_b; + } + break; - case TEXCTL_DECALCKEY: - if (ctransp) { - tex_r = i_r; - tex_g = i_g; - tex_b = i_b; - } - break; + case TEXCTL_DECALCKEY: + if (ctransp) { + tex_r = i_r; + tex_g = i_g; + tex_b = i_b; + } + break; - case (TEXCTL_STRANS | TEXCTL_DECALCKEY): - if (ctransp) - goto skip_pixel; - break; + case (TEXCTL_STRANS | TEXCTL_DECALCKEY): + if (ctransp) + goto skip_pixel; + break; - case TEXCTL_TMODULATE: - if (ctransp) - goto skip_pixel; - if (mystique->dwgreg.texctl & TEXCTL_TMODULATE) { - tex_r = (tex_r * i_r) >> 8; - tex_g = (tex_g * i_g) >> 8; - tex_b = (tex_b * i_b) >> 8; - } - break; + case TEXCTL_TMODULATE: + if (ctransp) + goto skip_pixel; + if (mystique->dwgreg.texctl & TEXCTL_TMODULATE) { + tex_r = (tex_r * i_r) >> 8; + tex_g = (tex_g * i_g) >> 8; + tex_b = (tex_b * i_b) >> 8; + } + break; - case (TEXCTL_TMODULATE | TEXCTL_STRANS): - if (ctransp || atransp) - goto skip_pixel; - if (mystique->dwgreg.texctl & TEXCTL_TMODULATE) { - tex_r = (tex_r * i_r) >> 8; - tex_g = (tex_g * i_g) >> 8; - tex_b = (tex_b * i_b) >> 8; - } - break; + case (TEXCTL_TMODULATE | TEXCTL_STRANS): + if (ctransp || atransp) + goto skip_pixel; + if (mystique->dwgreg.texctl & TEXCTL_TMODULATE) { + tex_r = (tex_r * i_r) >> 8; + tex_g = (tex_g * i_g) >> 8; + tex_b = (tex_b * i_b) >> 8; + } + break; - default: - fatal("Bad TEXCTL %08x %08x\n", mystique->dwgreg.texctl, mystique->dwgreg.texctl & (TEXCTL_TMODULATE | TEXCTL_STRANS | TEXCTL_ITRANS | TEXCTL_DECALCKEY)); - } + default: + fatal("Bad TEXCTL %08x %08x\n", mystique->dwgreg.texctl, mystique->dwgreg.texctl & (TEXCTL_TMODULATE | TEXCTL_STRANS | TEXCTL_ITRANS | TEXCTL_DECALCKEY)); + } - if (dest32) { - ((uint32_t *)svga->vram)[(mystique->dwgreg.ydst_lin + x_l) & mystique->vram_mask_l] = tex_b | (tex_g << 8) | (tex_r << 16); - svga->changedvram[((mystique->dwgreg.ydst_lin + x_l) & mystique->vram_mask_l) >> 10] = changeframecount; - } else { - ((uint16_t *)svga->vram)[(mystique->dwgreg.ydst_lin + x_l) & mystique->vram_mask_w] = dither(mystique, tex_r, tex_g, tex_b, x_l & 1, mystique->dwgreg.selline & 1); - svga->changedvram[((mystique->dwgreg.ydst_lin + x_l) & mystique->vram_mask_w) >> 11] = changeframecount; - } - if (z_write) - z_p[x_l] = z; - } - } + if (dest32) { + ((uint32_t *) svga->vram)[(mystique->dwgreg.ydst_lin + x_l) & mystique->vram_mask_l] = tex_b | (tex_g << 8) | (tex_r << 16); + svga->changedvram[((mystique->dwgreg.ydst_lin + x_l) & mystique->vram_mask_l) >> 10] = changeframecount; + } else { + ((uint16_t *) svga->vram)[(mystique->dwgreg.ydst_lin + x_l) & mystique->vram_mask_w] = dither(mystique, tex_r, tex_g, tex_b, x_l & 1, mystique->dwgreg.selline & 1); + svga->changedvram[((mystique->dwgreg.ydst_lin + x_l) & mystique->vram_mask_w) >> 11] = changeframecount; + } + if (z_write) + z_p[x_l] = z; + } + } skip_pixel: - x_l++; - mystique->pixel_count++; + x_l++; + mystique->pixel_count++; - mystique->dwgreg.dr[0] += mystique->dwgreg.dr[2]; - mystique->dwgreg.dr[4] += mystique->dwgreg.dr[6]; - mystique->dwgreg.dr[8] += mystique->dwgreg.dr[10]; - mystique->dwgreg.dr[12] += mystique->dwgreg.dr[14]; - mystique->dwgreg.tmr[6] += mystique->dwgreg.tmr[0]; - mystique->dwgreg.tmr[7] += mystique->dwgreg.tmr[2]; - mystique->dwgreg.tmr[8] += mystique->dwgreg.tmr[4]; - } + mystique->dwgreg.dr[0] += mystique->dwgreg.dr[2]; + mystique->dwgreg.dr[4] += mystique->dwgreg.dr[6]; + mystique->dwgreg.dr[8] += mystique->dwgreg.dr[10]; + mystique->dwgreg.dr[12] += mystique->dwgreg.dr[14]; + mystique->dwgreg.tmr[6] += mystique->dwgreg.tmr[0]; + mystique->dwgreg.tmr[7] += mystique->dwgreg.tmr[2]; + mystique->dwgreg.tmr[8] += mystique->dwgreg.tmr[4]; + } - mystique->dwgreg.dr[0] = z_back + mystique->dwgreg.dr[3]; - mystique->dwgreg.dr[4] = r_back + mystique->dwgreg.dr[7]; - mystique->dwgreg.dr[8] = g_back + mystique->dwgreg.dr[11]; - mystique->dwgreg.dr[12] = b_back + mystique->dwgreg.dr[15]; - mystique->dwgreg.tmr[6] = s_back + mystique->dwgreg.tmr[1]; - mystique->dwgreg.tmr[7] = t_back + mystique->dwgreg.tmr[3]; - mystique->dwgreg.tmr[8] = q_back + mystique->dwgreg.tmr[5]; + mystique->dwgreg.dr[0] = z_back + mystique->dwgreg.dr[3]; + mystique->dwgreg.dr[4] = r_back + mystique->dwgreg.dr[7]; + mystique->dwgreg.dr[8] = g_back + mystique->dwgreg.dr[11]; + mystique->dwgreg.dr[12] = b_back + mystique->dwgreg.dr[15]; + mystique->dwgreg.tmr[6] = s_back + mystique->dwgreg.tmr[1]; + mystique->dwgreg.tmr[7] = t_back + mystique->dwgreg.tmr[3]; + mystique->dwgreg.tmr[8] = q_back + mystique->dwgreg.tmr[5]; - while ((int32_t)mystique->dwgreg.ar[1] < 0 && mystique->dwgreg.ar[0]) { - mystique->dwgreg.ar[1] += mystique->dwgreg.ar[0]; - mystique->dwgreg.fxleft += (mystique->dwgreg.sgn.sdxl ? -1 : 1); - } - mystique->dwgreg.ar[1] += mystique->dwgreg.ar[2]; + while ((int32_t) mystique->dwgreg.ar[1] < 0 && mystique->dwgreg.ar[0]) { + mystique->dwgreg.ar[1] += mystique->dwgreg.ar[0]; + mystique->dwgreg.fxleft += (mystique->dwgreg.sgn.sdxl ? -1 : 1); + } + mystique->dwgreg.ar[1] += mystique->dwgreg.ar[2]; - while ((int32_t)mystique->dwgreg.ar[4] < 0 && mystique->dwgreg.ar[6]) { - mystique->dwgreg.ar[4] += mystique->dwgreg.ar[6]; - mystique->dwgreg.fxright += (mystique->dwgreg.sgn.sdxr ? -1 : 1); - } - mystique->dwgreg.ar[4] += mystique->dwgreg.ar[5]; + while ((int32_t) mystique->dwgreg.ar[4] < 0 && mystique->dwgreg.ar[6]) { + mystique->dwgreg.ar[4] += mystique->dwgreg.ar[6]; + mystique->dwgreg.fxright += (mystique->dwgreg.sgn.sdxr ? -1 : 1); + } + mystique->dwgreg.ar[4] += mystique->dwgreg.ar[5]; - dx = (int16_t)((mystique->dwgreg.fxleft - old_x_l) & 0xffff); - mystique->dwgreg.dr[0] += dx*mystique->dwgreg.dr[2]; - mystique->dwgreg.dr[4] += dx*mystique->dwgreg.dr[6]; - mystique->dwgreg.dr[8] += dx*mystique->dwgreg.dr[10]; - mystique->dwgreg.dr[12] += dx*mystique->dwgreg.dr[14]; - mystique->dwgreg.tmr[6] += dx*mystique->dwgreg.tmr[0]; - mystique->dwgreg.tmr[7] += dx*mystique->dwgreg.tmr[2]; - mystique->dwgreg.tmr[8] += dx*mystique->dwgreg.tmr[4]; + dx = (int16_t) ((mystique->dwgreg.fxleft - old_x_l) & 0xffff); + mystique->dwgreg.dr[0] += dx * mystique->dwgreg.dr[2]; + mystique->dwgreg.dr[4] += dx * mystique->dwgreg.dr[6]; + mystique->dwgreg.dr[8] += dx * mystique->dwgreg.dr[10]; + mystique->dwgreg.dr[12] += dx * mystique->dwgreg.dr[14]; + mystique->dwgreg.tmr[6] += dx * mystique->dwgreg.tmr[0]; + mystique->dwgreg.tmr[7] += dx * mystique->dwgreg.tmr[2]; + mystique->dwgreg.tmr[8] += dx * mystique->dwgreg.tmr[4]; - mystique->dwgreg.ydst++; - mystique->dwgreg.ydst &= 0x7fffff; - mystique->dwgreg.ydst_lin += (mystique->dwgreg.pitch & PITCH_MASK); + mystique->dwgreg.ydst++; + mystique->dwgreg.ydst &= 0x7fffff; + mystique->dwgreg.ydst_lin += (mystique->dwgreg.pitch & PITCH_MASK); - mystique->dwgreg.selline = (mystique->dwgreg.selline + 1) & 7; - } - break; + mystique->dwgreg.selline = (mystique->dwgreg.selline + 1) & 7; + } + break; - default: - fatal("Unknown atype %03x %08x TEXTURE_TRAP\n", mystique->dwgreg.dwgctrl_running & DWGCTRL_ATYPE_MASK, mystique->dwgreg.dwgctrl_running); + default: + fatal("Unknown atype %03x %08x TEXTURE_TRAP\n", mystique->dwgreg.dwgctrl_running & DWGCTRL_ATYPE_MASK, mystique->dwgreg.dwgctrl_running); } mystique->blitter_complete_refcount++; } - static void blit_bitblt(mystique_t *mystique) { - svga_t *svga = &mystique->svga; - uint32_t src_addr; - int y; - int x_dir = mystique->dwgreg.sgn.scanleft ? -1 : 1; - int16_t x_start = mystique->dwgreg.sgn.scanleft ? mystique->dwgreg.fxright : mystique->dwgreg.fxleft; - int16_t x_end = mystique->dwgreg.sgn.scanleft ? mystique->dwgreg.fxleft : mystique->dwgreg.fxright; + svga_t *svga = &mystique->svga; + uint32_t src_addr; + int y; + int x_dir = mystique->dwgreg.sgn.scanleft ? -1 : 1; + int16_t x_start = mystique->dwgreg.sgn.scanleft ? mystique->dwgreg.fxright : mystique->dwgreg.fxleft; + int16_t x_end = mystique->dwgreg.sgn.scanleft ? mystique->dwgreg.fxleft : mystique->dwgreg.fxright; const int trans_sel = (mystique->dwgreg.dwgctrl_running & DWGCTRL_TRANS_MASK) >> DWGCTRL_TRANS_SHIFT; switch (mystique->dwgreg.dwgctrl_running & DWGCTRL_ATYPE_MASK) { - case DWGCTRL_ATYPE_BLK: - switch (mystique->dwgreg.dwgctrl_running & DWGCTRL_BLTMOD_MASK) { - case DWGCTRL_BLTMOD_BMONOLEF: - src_addr = mystique->dwgreg.ar[3]; + case DWGCTRL_ATYPE_BLK: + switch (mystique->dwgreg.dwgctrl_running & DWGCTRL_BLTMOD_MASK) { + case DWGCTRL_BLTMOD_BMONOLEF: + src_addr = mystique->dwgreg.ar[3]; - for (y = 0; y < mystique->dwgreg.length; y++) { - int16_t x = x_start; + for (y = 0; y < mystique->dwgreg.length; y++) { + int16_t x = x_start; - while (1) { - if (x >= mystique->dwgreg.cxleft && x <= mystique->dwgreg.cxright && - mystique->dwgreg.ydst_lin >= mystique->dwgreg.ytop && mystique->dwgreg.ydst_lin <= mystique->dwgreg.ybot) { - uint32_t byte_addr = (src_addr >> 3) & mystique->vram_mask; - int bit_offset = src_addr & 7; - uint32_t old_dst; + while (1) { + if (x >= mystique->dwgreg.cxleft && x <= mystique->dwgreg.cxright && mystique->dwgreg.ydst_lin >= mystique->dwgreg.ytop && mystique->dwgreg.ydst_lin <= mystique->dwgreg.ybot) { + uint32_t byte_addr = (src_addr >> 3) & mystique->vram_mask; + int bit_offset = src_addr & 7; + uint32_t old_dst; - switch (mystique->maccess_running & MACCESS_PWIDTH_MASK) { - case MACCESS_PWIDTH_8: - if (mystique->dwgreg.dwgctrl_running & DWGCTRL_TRANSC) { - if (svga->vram[byte_addr] & (1 << bit_offset)) - svga->vram[(mystique->dwgreg.ydst_lin + x) & mystique->vram_mask] = mystique->dwgreg.fcol; - } else - svga->vram[(mystique->dwgreg.ydst_lin + x) & mystique->vram_mask] = - (svga->vram[byte_addr] & (1 << bit_offset)) ? mystique->dwgreg.fcol : mystique->dwgreg.bcol; - svga->changedvram[((mystique->dwgreg.ydst_lin + x) & mystique->vram_mask) >> 12] = changeframecount; - break; + switch (mystique->maccess_running & MACCESS_PWIDTH_MASK) { + case MACCESS_PWIDTH_8: + if (mystique->dwgreg.dwgctrl_running & DWGCTRL_TRANSC) { + if (svga->vram[byte_addr] & (1 << bit_offset)) + svga->vram[(mystique->dwgreg.ydst_lin + x) & mystique->vram_mask] = mystique->dwgreg.fcol; + } else + svga->vram[(mystique->dwgreg.ydst_lin + x) & mystique->vram_mask] = (svga->vram[byte_addr] & (1 << bit_offset)) ? mystique->dwgreg.fcol : mystique->dwgreg.bcol; + svga->changedvram[((mystique->dwgreg.ydst_lin + x) & mystique->vram_mask) >> 12] = changeframecount; + break; - case MACCESS_PWIDTH_16: - if (mystique->dwgreg.dwgctrl_running & DWGCTRL_TRANSC) { - if (svga->vram[byte_addr] & (1 << bit_offset)) - ((uint16_t *)svga->vram)[(mystique->dwgreg.ydst_lin + x) & mystique->vram_mask_w] = mystique->dwgreg.fcol; - } else - ((uint16_t *)svga->vram)[(mystique->dwgreg.ydst_lin + x) & mystique->vram_mask_w] = - (svga->vram[byte_addr] & (1 << bit_offset)) ? mystique->dwgreg.fcol : mystique->dwgreg.bcol; - svga->changedvram[((mystique->dwgreg.ydst_lin + x) & mystique->vram_mask_w) >> 11] = changeframecount; - break; + case MACCESS_PWIDTH_16: + if (mystique->dwgreg.dwgctrl_running & DWGCTRL_TRANSC) { + if (svga->vram[byte_addr] & (1 << bit_offset)) + ((uint16_t *) svga->vram)[(mystique->dwgreg.ydst_lin + x) & mystique->vram_mask_w] = mystique->dwgreg.fcol; + } else + ((uint16_t *) svga->vram)[(mystique->dwgreg.ydst_lin + x) & mystique->vram_mask_w] = (svga->vram[byte_addr] & (1 << bit_offset)) ? mystique->dwgreg.fcol : mystique->dwgreg.bcol; + svga->changedvram[((mystique->dwgreg.ydst_lin + x) & mystique->vram_mask_w) >> 11] = changeframecount; + break; - case MACCESS_PWIDTH_24: - old_dst = *(uint32_t *)&svga->vram[((mystique->dwgreg.ydst_lin + x) * 3) & mystique->vram_mask]; - if (mystique->dwgreg.dwgctrl_running & DWGCTRL_TRANSC) { - if (svga->vram[byte_addr] & (1 << bit_offset)) - *(uint32_t *)&svga->vram[((mystique->dwgreg.ydst_lin + x) * 3) & mystique->vram_mask] = - (old_dst & 0xff000000) | (mystique->dwgreg.fcol & 0xffffff); - } else - *(uint32_t *)&svga->vram[((mystique->dwgreg.ydst_lin + x) * 3) & mystique->vram_mask] = - (old_dst & 0xff000000) | (((svga->vram[byte_addr] & (1 << bit_offset)) ? mystique->dwgreg.fcol : mystique->dwgreg.bcol) & 0xffffff); - svga->changedvram[(((mystique->dwgreg.ydst_lin + x) * 3) & mystique->vram_mask) >> 12] = changeframecount; - break; + case MACCESS_PWIDTH_24: + old_dst = *(uint32_t *) &svga->vram[((mystique->dwgreg.ydst_lin + x) * 3) & mystique->vram_mask]; + if (mystique->dwgreg.dwgctrl_running & DWGCTRL_TRANSC) { + if (svga->vram[byte_addr] & (1 << bit_offset)) + *(uint32_t *) &svga->vram[((mystique->dwgreg.ydst_lin + x) * 3) & mystique->vram_mask] = (old_dst & 0xff000000) | (mystique->dwgreg.fcol & 0xffffff); + } else + *(uint32_t *) &svga->vram[((mystique->dwgreg.ydst_lin + x) * 3) & mystique->vram_mask] = (old_dst & 0xff000000) | (((svga->vram[byte_addr] & (1 << bit_offset)) ? mystique->dwgreg.fcol : mystique->dwgreg.bcol) & 0xffffff); + svga->changedvram[(((mystique->dwgreg.ydst_lin + x) * 3) & mystique->vram_mask) >> 12] = changeframecount; + break; - case MACCESS_PWIDTH_32: - if (mystique->dwgreg.dwgctrl_running & DWGCTRL_TRANSC) { - if (svga->vram[byte_addr] & (1 << bit_offset)) - ((uint32_t *)svga->vram)[(mystique->dwgreg.ydst_lin + x) & mystique->vram_mask_l] = mystique->dwgreg.fcol; - } else - ((uint32_t *)svga->vram)[(mystique->dwgreg.ydst_lin + x) & mystique->vram_mask_l] = - (svga->vram[byte_addr] & (1 << bit_offset)) ? mystique->dwgreg.fcol : mystique->dwgreg.bcol; - svga->changedvram[((mystique->dwgreg.ydst_lin + x) & mystique->vram_mask_l) >> 11] = changeframecount; - break; + case MACCESS_PWIDTH_32: + if (mystique->dwgreg.dwgctrl_running & DWGCTRL_TRANSC) { + if (svga->vram[byte_addr] & (1 << bit_offset)) + ((uint32_t *) svga->vram)[(mystique->dwgreg.ydst_lin + x) & mystique->vram_mask_l] = mystique->dwgreg.fcol; + } else + ((uint32_t *) svga->vram)[(mystique->dwgreg.ydst_lin + x) & mystique->vram_mask_l] = (svga->vram[byte_addr] & (1 << bit_offset)) ? mystique->dwgreg.fcol : mystique->dwgreg.bcol; + svga->changedvram[((mystique->dwgreg.ydst_lin + x) & mystique->vram_mask_l) >> 11] = changeframecount; + break; - default: - fatal("BITBLT DWGCTRL_ATYPE_BLK unknown MACCESS %i\n", mystique->maccess_running & MACCESS_PWIDTH_MASK); - } - } + default: + fatal("BITBLT DWGCTRL_ATYPE_BLK unknown MACCESS %i\n", mystique->maccess_running & MACCESS_PWIDTH_MASK); + } + } - if (src_addr == mystique->dwgreg.ar[0]) { - mystique->dwgreg.ar[0] += mystique->dwgreg.ar[5]; - mystique->dwgreg.ar[3] += mystique->dwgreg.ar[5]; - src_addr = mystique->dwgreg.ar[3]; - } else - src_addr += x_dir; + if (src_addr == mystique->dwgreg.ar[0]) { + mystique->dwgreg.ar[0] += mystique->dwgreg.ar[5]; + mystique->dwgreg.ar[3] += mystique->dwgreg.ar[5]; + src_addr = mystique->dwgreg.ar[3]; + } else + src_addr += x_dir; - if (x != x_end) - x += x_dir; - else - break; - } + if (x != x_end) + x += x_dir; + else + break; + } - if (mystique->dwgreg.sgn.sdy) - mystique->dwgreg.ydst_lin -= (mystique->dwgreg.pitch & PITCH_MASK); - else - mystique->dwgreg.ydst_lin += (mystique->dwgreg.pitch & PITCH_MASK); - } - break; + if (mystique->dwgreg.sgn.sdy) + mystique->dwgreg.ydst_lin -= (mystique->dwgreg.pitch & PITCH_MASK); + else + mystique->dwgreg.ydst_lin += (mystique->dwgreg.pitch & PITCH_MASK); + } + break; - default: - fatal("BITBLT BLK %08x\n", mystique->dwgreg.dwgctrl_running & DWGCTRL_BLTMOD_MASK); - break; - } - break; + default: + fatal("BITBLT BLK %08x\n", mystique->dwgreg.dwgctrl_running & DWGCTRL_BLTMOD_MASK); + break; + } + break; - case DWGCTRL_ATYPE_RPL: - if (mystique->maccess_running & MACCESS_TLUTLOAD) { - src_addr = mystique->dwgreg.ar[3]; + case DWGCTRL_ATYPE_RPL: + if (mystique->maccess_running & MACCESS_TLUTLOAD) { + src_addr = mystique->dwgreg.ar[3]; - y = mystique->dwgreg.ydst; + y = mystique->dwgreg.ydst; - while (mystique->dwgreg.length) { - uint16_t src = ((uint16_t *)svga->vram)[src_addr & mystique->vram_mask_w]; + while (mystique->dwgreg.length) { + uint16_t src = ((uint16_t *) svga->vram)[src_addr & mystique->vram_mask_w]; - mystique->lut[y & 0xff].r = (src >> 11) << 3; - mystique->lut[y & 0xff].g = ((src >> 5) & 0x3f) << 2; - mystique->lut[y & 0xff].b = (src & 0x1f) << 3; - src_addr++; - y++; - mystique->dwgreg.length--; - } - break; - } - case DWGCTRL_ATYPE_RSTR: - switch (mystique->dwgreg.dwgctrl_running & DWGCTRL_BLTMOD_MASK) { - case DWGCTRL_BLTMOD_BMONOLEF: - if (mystique->dwgreg.dwgctrl_running & DWGCTRL_PATTERN) - fatal("BITBLT RPL/RSTR BMONOLEF with pattern\n"); + mystique->lut[y & 0xff].r = (src >> 11) << 3; + mystique->lut[y & 0xff].g = ((src >> 5) & 0x3f) << 2; + mystique->lut[y & 0xff].b = (src & 0x1f) << 3; + src_addr++; + y++; + mystique->dwgreg.length--; + } + break; + } + case DWGCTRL_ATYPE_RSTR: + switch (mystique->dwgreg.dwgctrl_running & DWGCTRL_BLTMOD_MASK) { + case DWGCTRL_BLTMOD_BMONOLEF: + if (mystique->dwgreg.dwgctrl_running & DWGCTRL_PATTERN) + fatal("BITBLT RPL/RSTR BMONOLEF with pattern\n"); - src_addr = mystique->dwgreg.ar[3]; + src_addr = mystique->dwgreg.ar[3]; - for (y = 0; y < mystique->dwgreg.length; y++) { - uint8_t const * const trans = &trans_masks[trans_sel][(mystique->dwgreg.selline & 3) * 4]; - int16_t x = x_start; + for (y = 0; y < mystique->dwgreg.length; y++) { + uint8_t const *const trans = &trans_masks[trans_sel][(mystique->dwgreg.selline & 3) * 4]; + int16_t x = x_start; - while (1) { - uint32_t byte_addr = (src_addr >> 3) & mystique->vram_mask; - int bit_offset = src_addr & 7; + while (1) { + uint32_t byte_addr = (src_addr >> 3) & mystique->vram_mask; + int bit_offset = src_addr & 7; - if (x >= mystique->dwgreg.cxleft && x <= mystique->dwgreg.cxright && - mystique->dwgreg.ydst_lin >= mystique->dwgreg.ytop && mystique->dwgreg.ydst_lin <= mystique->dwgreg.ybot && - ((svga->vram[byte_addr] & (1 << bit_offset)) || !(mystique->dwgreg.dwgctrl_running & DWGCTRL_TRANSC)) && - trans[x & 3]) { - uint32_t src = (svga->vram[byte_addr] & (1 << bit_offset)) ? mystique->dwgreg.fcol : mystique->dwgreg.bcol; - uint32_t dst, old_dst; + if (x >= mystique->dwgreg.cxleft && x <= mystique->dwgreg.cxright && mystique->dwgreg.ydst_lin >= mystique->dwgreg.ytop && mystique->dwgreg.ydst_lin <= mystique->dwgreg.ybot && ((svga->vram[byte_addr] & (1 << bit_offset)) || !(mystique->dwgreg.dwgctrl_running & DWGCTRL_TRANSC)) && trans[x & 3]) { + uint32_t src = (svga->vram[byte_addr] & (1 << bit_offset)) ? mystique->dwgreg.fcol : mystique->dwgreg.bcol; + uint32_t dst; + uint32_t old_dst; - switch (mystique->maccess_running & MACCESS_PWIDTH_MASK) { - case MACCESS_PWIDTH_8: - dst = svga->vram[(mystique->dwgreg.ydst_lin + x) & mystique->vram_mask]; + switch (mystique->maccess_running & MACCESS_PWIDTH_MASK) { + case MACCESS_PWIDTH_8: + dst = svga->vram[(mystique->dwgreg.ydst_lin + x) & mystique->vram_mask]; - dst = bitop(src, dst, mystique->dwgreg.dwgctrl_running); - - svga->vram[(mystique->dwgreg.ydst_lin + x) & mystique->vram_mask] = dst; - svga->changedvram[((mystique->dwgreg.ydst_lin + x) & mystique->vram_mask) >> 12] = changeframecount; - break; + dst = bitop(src, dst, mystique->dwgreg.dwgctrl_running); - case MACCESS_PWIDTH_16: - dst = ((uint16_t *)svga->vram)[(mystique->dwgreg.ydst_lin + x) & mystique->vram_mask_w]; + svga->vram[(mystique->dwgreg.ydst_lin + x) & mystique->vram_mask] = dst; + svga->changedvram[((mystique->dwgreg.ydst_lin + x) & mystique->vram_mask) >> 12] = changeframecount; + break; - dst = bitop(src, dst, mystique->dwgreg.dwgctrl_running); + case MACCESS_PWIDTH_16: + dst = ((uint16_t *) svga->vram)[(mystique->dwgreg.ydst_lin + x) & mystique->vram_mask_w]; - ((uint16_t *)svga->vram)[(mystique->dwgreg.ydst_lin + x) & mystique->vram_mask_w] = dst; - svga->changedvram[((mystique->dwgreg.ydst_lin + x) & mystique->vram_mask_w) >> 11] = changeframecount; - break; + dst = bitop(src, dst, mystique->dwgreg.dwgctrl_running); - case MACCESS_PWIDTH_24: - old_dst = *(uint32_t *)&svga->vram[((mystique->dwgreg.ydst_lin + x) * 3) & mystique->vram_mask]; + ((uint16_t *) svga->vram)[(mystique->dwgreg.ydst_lin + x) & mystique->vram_mask_w] = dst; + svga->changedvram[((mystique->dwgreg.ydst_lin + x) & mystique->vram_mask_w) >> 11] = changeframecount; + break; - dst = bitop(src, old_dst, mystique->dwgreg.dwgctrl_running);// & DWGCTRL_BOP_MASK + case MACCESS_PWIDTH_24: + old_dst = *(uint32_t *) &svga->vram[((mystique->dwgreg.ydst_lin + x) * 3) & mystique->vram_mask]; - *(uint32_t *)&svga->vram[((mystique->dwgreg.ydst_lin + x) * 3) & mystique->vram_mask] = (dst & 0xffffff) | (old_dst & 0xff000000); - svga->changedvram[(((mystique->dwgreg.ydst_lin + x) * 3) & mystique->vram_mask) >> 12] = changeframecount; - break; + dst = bitop(src, old_dst, mystique->dwgreg.dwgctrl_running); // & DWGCTRL_BOP_MASK - case MACCESS_PWIDTH_32: - dst = ((uint32_t *)svga->vram)[(mystique->dwgreg.ydst_lin + x) & mystique->vram_mask_l]; + *(uint32_t *) &svga->vram[((mystique->dwgreg.ydst_lin + x) * 3) & mystique->vram_mask] = (dst & 0xffffff) | (old_dst & 0xff000000); + svga->changedvram[(((mystique->dwgreg.ydst_lin + x) * 3) & mystique->vram_mask) >> 12] = changeframecount; + break; - dst = bitop(src, dst, mystique->dwgreg.dwgctrl_running); + case MACCESS_PWIDTH_32: + dst = ((uint32_t *) svga->vram)[(mystique->dwgreg.ydst_lin + x) & mystique->vram_mask_l]; - ((uint32_t *)svga->vram)[(mystique->dwgreg.ydst_lin + x) & mystique->vram_mask_l] = dst; - svga->changedvram[((mystique->dwgreg.ydst_lin + x) & mystique->vram_mask_l) >> 10] = changeframecount; - break; + dst = bitop(src, dst, mystique->dwgreg.dwgctrl_running); - default: - fatal("BITBLT RPL BMONOLEF PWIDTH %x %08x\n", mystique->maccess_running & MACCESS_PWIDTH_MASK, mystique->dwgreg.dwgctrl_running); - } - } + ((uint32_t *) svga->vram)[(mystique->dwgreg.ydst_lin + x) & mystique->vram_mask_l] = dst; + svga->changedvram[((mystique->dwgreg.ydst_lin + x) & mystique->vram_mask_l) >> 10] = changeframecount; + break; - if (src_addr == mystique->dwgreg.ar[0]) { - mystique->dwgreg.ar[0] += mystique->dwgreg.ar[5]; - mystique->dwgreg.ar[3] += mystique->dwgreg.ar[5]; - src_addr = mystique->dwgreg.ar[3]; - } else - src_addr += x_dir; + default: + fatal("BITBLT RPL BMONOLEF PWIDTH %x %08x\n", mystique->maccess_running & MACCESS_PWIDTH_MASK, mystique->dwgreg.dwgctrl_running); + } + } - if (x != x_end) - x += x_dir; - else - break; - } + if (src_addr == mystique->dwgreg.ar[0]) { + mystique->dwgreg.ar[0] += mystique->dwgreg.ar[5]; + mystique->dwgreg.ar[3] += mystique->dwgreg.ar[5]; + src_addr = mystique->dwgreg.ar[3]; + } else + src_addr += x_dir; - if (mystique->dwgreg.sgn.sdy) - mystique->dwgreg.ydst_lin -= (mystique->dwgreg.pitch & PITCH_MASK); - else - mystique->dwgreg.ydst_lin += (mystique->dwgreg.pitch & PITCH_MASK); - } - break; + if (x != x_end) + x += x_dir; + else + break; + } - case DWGCTRL_BLTMOD_BFCOL: - case DWGCTRL_BLTMOD_BU32RGB: - src_addr = mystique->dwgreg.ar[3]; + if (mystique->dwgreg.sgn.sdy) + mystique->dwgreg.ydst_lin -= (mystique->dwgreg.pitch & PITCH_MASK); + else + mystique->dwgreg.ydst_lin += (mystique->dwgreg.pitch & PITCH_MASK); + } + break; - for (y = 0; y < mystique->dwgreg.length; y++) { - uint8_t const * const trans = &trans_masks[trans_sel][(mystique->dwgreg.selline & 3) * 4]; - uint32_t old_src_addr = src_addr; - int16_t x = x_start; + case DWGCTRL_BLTMOD_BFCOL: + case DWGCTRL_BLTMOD_BU32RGB: + src_addr = mystique->dwgreg.ar[3]; - while (1) { - if (x >= mystique->dwgreg.cxleft && x <= mystique->dwgreg.cxright && - mystique->dwgreg.ydst_lin >= mystique->dwgreg.ytop && mystique->dwgreg.ydst_lin <= mystique->dwgreg.ybot && - trans[x & 3]) { - uint32_t src, dst, old_dst; + for (y = 0; y < mystique->dwgreg.length; y++) { + uint8_t const *const trans = &trans_masks[trans_sel][(mystique->dwgreg.selline & 3) * 4]; + uint32_t old_src_addr = src_addr; + int16_t x = x_start; - switch (mystique->maccess_running & MACCESS_PWIDTH_MASK) { - case MACCESS_PWIDTH_8: - src = svga->vram[src_addr & mystique->vram_mask]; - dst = svga->vram[(mystique->dwgreg.ydst_lin + x) & mystique->vram_mask]; + while (1) { + if (x >= mystique->dwgreg.cxleft && x <= mystique->dwgreg.cxright && mystique->dwgreg.ydst_lin >= mystique->dwgreg.ytop && mystique->dwgreg.ydst_lin <= mystique->dwgreg.ybot && trans[x & 3]) { + uint32_t src; + uint32_t dst; + uint32_t old_dst; - dst = bitop(src, dst, mystique->dwgreg.dwgctrl_running); + switch (mystique->maccess_running & MACCESS_PWIDTH_MASK) { + case MACCESS_PWIDTH_8: + src = svga->vram[src_addr & mystique->vram_mask]; + dst = svga->vram[(mystique->dwgreg.ydst_lin + x) & mystique->vram_mask]; - svga->vram[(mystique->dwgreg.ydst_lin + x) & mystique->vram_mask] = dst; - svga->changedvram[((mystique->dwgreg.ydst_lin + x) & mystique->vram_mask) >> 12] = changeframecount; - break; + dst = bitop(src, dst, mystique->dwgreg.dwgctrl_running); - case MACCESS_PWIDTH_16: - src = ((uint16_t *)svga->vram)[src_addr & mystique->vram_mask_w]; - dst = ((uint16_t *)svga->vram)[(mystique->dwgreg.ydst_lin + x) & mystique->vram_mask_w]; + svga->vram[(mystique->dwgreg.ydst_lin + x) & mystique->vram_mask] = dst; + svga->changedvram[((mystique->dwgreg.ydst_lin + x) & mystique->vram_mask) >> 12] = changeframecount; + break; - dst = bitop(src, dst, mystique->dwgreg.dwgctrl_running); + case MACCESS_PWIDTH_16: + src = ((uint16_t *) svga->vram)[src_addr & mystique->vram_mask_w]; + dst = ((uint16_t *) svga->vram)[(mystique->dwgreg.ydst_lin + x) & mystique->vram_mask_w]; - ((uint16_t *)svga->vram)[(mystique->dwgreg.ydst_lin + x) & mystique->vram_mask_w] = dst; - svga->changedvram[((mystique->dwgreg.ydst_lin + x) & mystique->vram_mask_w) >> 11] = changeframecount; - break; + dst = bitop(src, dst, mystique->dwgreg.dwgctrl_running); - case MACCESS_PWIDTH_24: - src = *(uint32_t *)&svga->vram[(src_addr * 3) & mystique->vram_mask]; - old_dst = *(uint32_t *)&svga->vram[((mystique->dwgreg.ydst_lin + x) * 3) & mystique->vram_mask]; + ((uint16_t *) svga->vram)[(mystique->dwgreg.ydst_lin + x) & mystique->vram_mask_w] = dst; + svga->changedvram[((mystique->dwgreg.ydst_lin + x) & mystique->vram_mask_w) >> 11] = changeframecount; + break; - dst = bitop(src, old_dst, mystique->dwgreg.dwgctrl_running); + case MACCESS_PWIDTH_24: + src = *(uint32_t *) &svga->vram[(src_addr * 3) & mystique->vram_mask]; + old_dst = *(uint32_t *) &svga->vram[((mystique->dwgreg.ydst_lin + x) * 3) & mystique->vram_mask]; - *(uint32_t *)&svga->vram[((mystique->dwgreg.ydst_lin + x) * 3) & mystique->vram_mask] = (dst & 0xffffff) | (old_dst & 0xff000000); - svga->changedvram[(((mystique->dwgreg.ydst_lin + x) * 3) & mystique->vram_mask) >> 12] = changeframecount; - break; + dst = bitop(src, old_dst, mystique->dwgreg.dwgctrl_running); - case MACCESS_PWIDTH_32: - src = ((uint32_t *)svga->vram)[src_addr & mystique->vram_mask_l]; - dst = ((uint32_t *)svga->vram)[(mystique->dwgreg.ydst_lin + x) & mystique->vram_mask_l]; + *(uint32_t *) &svga->vram[((mystique->dwgreg.ydst_lin + x) * 3) & mystique->vram_mask] = (dst & 0xffffff) | (old_dst & 0xff000000); + svga->changedvram[(((mystique->dwgreg.ydst_lin + x) * 3) & mystique->vram_mask) >> 12] = changeframecount; + break; - dst = bitop(src, dst, mystique->dwgreg.dwgctrl_running); + case MACCESS_PWIDTH_32: + src = ((uint32_t *) svga->vram)[src_addr & mystique->vram_mask_l]; + dst = ((uint32_t *) svga->vram)[(mystique->dwgreg.ydst_lin + x) & mystique->vram_mask_l]; - ((uint32_t *)svga->vram)[(mystique->dwgreg.ydst_lin + x) & mystique->vram_mask_l] = dst; - svga->changedvram[((mystique->dwgreg.ydst_lin + x) & mystique->vram_mask_l) >> 10] = changeframecount; - break; + dst = bitop(src, dst, mystique->dwgreg.dwgctrl_running); - default: - fatal("BITBLT RPL BFCOL PWIDTH %x %08x\n", mystique->maccess_running & MACCESS_PWIDTH_MASK, mystique->dwgreg.dwgctrl_running); - } - } + ((uint32_t *) svga->vram)[(mystique->dwgreg.ydst_lin + x) & mystique->vram_mask_l] = dst; + svga->changedvram[((mystique->dwgreg.ydst_lin + x) & mystique->vram_mask_l) >> 10] = changeframecount; + break; - if (mystique->dwgreg.dwgctrl_running & DWGCTRL_PATTERN) - src_addr = ((src_addr + x_dir) & 7) | (src_addr & ~7); - else if (src_addr == mystique->dwgreg.ar[0]) { - mystique->dwgreg.ar[0] += mystique->dwgreg.ar[5]; - mystique->dwgreg.ar[3] += mystique->dwgreg.ar[5]; - src_addr = mystique->dwgreg.ar[3]; - } else - src_addr += x_dir; + default: + fatal("BITBLT RPL BFCOL PWIDTH %x %08x\n", mystique->maccess_running & MACCESS_PWIDTH_MASK, mystique->dwgreg.dwgctrl_running); + } + } - if (x != x_end) - x += x_dir; - else - break; - } + if (mystique->dwgreg.dwgctrl_running & DWGCTRL_PATTERN) + src_addr = ((src_addr + x_dir) & 7) | (src_addr & ~7); + else if (src_addr == mystique->dwgreg.ar[0]) { + mystique->dwgreg.ar[0] += mystique->dwgreg.ar[5]; + mystique->dwgreg.ar[3] += mystique->dwgreg.ar[5]; + src_addr = mystique->dwgreg.ar[3]; + } else + src_addr += x_dir; - if (mystique->dwgreg.dwgctrl_running & DWGCTRL_PATTERN) { - src_addr = old_src_addr; - if (mystique->dwgreg.sgn.sdy) - src_addr = ((src_addr - 32) & 0xe0) | (src_addr & ~0xe0); - else - src_addr = ((src_addr + 32) & 0xe0) | (src_addr & ~0xe0); - } + if (x != x_end) + x += x_dir; + else + break; + } - if (mystique->dwgreg.sgn.sdy) - mystique->dwgreg.ydst_lin -= (mystique->dwgreg.pitch & PITCH_MASK); - else - mystique->dwgreg.ydst_lin += (mystique->dwgreg.pitch & PITCH_MASK); - } - break; + if (mystique->dwgreg.dwgctrl_running & DWGCTRL_PATTERN) { + src_addr = old_src_addr; + if (mystique->dwgreg.sgn.sdy) + src_addr = ((src_addr - 32) & 0xe0) | (src_addr & ~0xe0); + else + src_addr = ((src_addr + 32) & 0xe0) | (src_addr & ~0xe0); + } - default: - fatal("BITBLT DWGCTRL_ATYPE_RPL unknown BLTMOD %08x %08x\n", mystique->dwgreg.dwgctrl_running & DWGCTRL_BLTMOD_MASK, mystique->dwgreg.dwgctrl_running); - } - break; + if (mystique->dwgreg.sgn.sdy) + mystique->dwgreg.ydst_lin -= (mystique->dwgreg.pitch & PITCH_MASK); + else + mystique->dwgreg.ydst_lin += (mystique->dwgreg.pitch & PITCH_MASK); + } + break; - default: - /* pclog("Unknown BITBLT atype %03x %08x\n", mystique->dwgreg.dwgctrl_running & DWGCTRL_ATYPE_MASK, mystique->dwgreg.dwgctrl_running); */ - break; + default: + fatal("BITBLT DWGCTRL_ATYPE_RPL unknown BLTMOD %08x %08x\n", mystique->dwgreg.dwgctrl_running & DWGCTRL_BLTMOD_MASK, mystique->dwgreg.dwgctrl_running); + } + break; + + default: +#if 0 + pclog("Unknown BITBLT atype %03x %08x\n", mystique->dwgreg.dwgctrl_running & DWGCTRL_ATYPE_MASK, mystique->dwgreg.dwgctrl_running); +#endif + break; } mystique->blitter_complete_refcount++; } - static void blit_iload(mystique_t *mystique) -{ +{ switch (mystique->dwgreg.dwgctrl_running & DWGCTRL_ATYPE_MASK) { - case DWGCTRL_ATYPE_RPL: - case DWGCTRL_ATYPE_RSTR: - case DWGCTRL_ATYPE_BLK: - /* pclog("ILOAD BLTMOD DWGCTRL = %08x\n", mystique->dwgreg.dwgctrl_running & DWGCTRL_BLTMOD_MASK); */ - switch (mystique->dwgreg.dwgctrl_running & DWGCTRL_BLTMOD_MASK) { - case DWGCTRL_BLTMOD_BFCOL: - case DWGCTRL_BLTMOD_BMONOLEF: - case DWGCTRL_BLTMOD_BMONOWF: - case DWGCTRL_BLTMOD_BU24RGB: - case DWGCTRL_BLTMOD_BU32RGB: - mystique->dwgreg.length_cur = mystique->dwgreg.length; - mystique->dwgreg.xdst = mystique->dwgreg.fxleft; - mystique->dwgreg.iload_rem_data = 0; - mystique->dwgreg.iload_rem_count = 0; - mystique->busy = 1; - /* pclog("ILOAD busy\n"); */ - mystique->dwgreg.words = 0; - break; + case DWGCTRL_ATYPE_RPL: + case DWGCTRL_ATYPE_RSTR: + case DWGCTRL_ATYPE_BLK: +#if 0 + pclog("ILOAD BLTMOD DWGCTRL = %08x\n", mystique->dwgreg.dwgctrl_running & DWGCTRL_BLTMOD_MASK); +#endif + switch (mystique->dwgreg.dwgctrl_running & DWGCTRL_BLTMOD_MASK) { + case DWGCTRL_BLTMOD_BFCOL: + case DWGCTRL_BLTMOD_BMONOLEF: + case DWGCTRL_BLTMOD_BMONOWF: + case DWGCTRL_BLTMOD_BU24RGB: + case DWGCTRL_BLTMOD_BU32RGB: + mystique->dwgreg.length_cur = mystique->dwgreg.length; + mystique->dwgreg.xdst = mystique->dwgreg.fxleft; + mystique->dwgreg.iload_rem_data = 0; + mystique->dwgreg.iload_rem_count = 0; + mystique->busy = 1; +#if 0 + pclog("ILOAD busy\n"); +#endif + mystique->dwgreg.words = 0; + break; - default: - fatal("ILOAD DWGCTRL_ATYPE_RPL %08x %08x\n", mystique->dwgreg.dwgctrl_running & DWGCTRL_BLTMOD_MASK, mystique->dwgreg.dwgctrl_running); - break; - } - break; + default: + fatal("ILOAD DWGCTRL_ATYPE_RPL %08x %08x\n", mystique->dwgreg.dwgctrl_running & DWGCTRL_BLTMOD_MASK, mystique->dwgreg.dwgctrl_running); + break; + } + break; - default: - fatal("Unknown ILOAD atype %03x %08x\n", mystique->dwgreg.dwgctrl_running & DWGCTRL_ATYPE_MASK, mystique->dwgreg.dwgctrl_running); + default: + fatal("Unknown ILOAD atype %03x %08x\n", mystique->dwgreg.dwgctrl_running & DWGCTRL_ATYPE_MASK, mystique->dwgreg.dwgctrl_running); } } - static void blit_idump(mystique_t *mystique) { switch (mystique->dwgreg.dwgctrl_running & DWGCTRL_ATYPE_MASK) { - case DWGCTRL_ATYPE_RPL: - mystique->dwgreg.length_cur = mystique->dwgreg.length; - mystique->dwgreg.xdst = mystique->dwgreg.fxleft; - mystique->dwgreg.src_addr = mystique->dwgreg.ar[3]; - mystique->dwgreg.words = 0; - mystique->dwgreg.iload_rem_count = 0; - mystique->dwgreg.iload_rem_data = 0; - mystique->dwgreg.idump_end_of_line = 0; - mystique->busy = 1; - /* pclog("IDUMP ATYPE RPL busy\n"); */ - break; + case DWGCTRL_ATYPE_RPL: + mystique->dwgreg.length_cur = mystique->dwgreg.length; + mystique->dwgreg.xdst = mystique->dwgreg.fxleft; + mystique->dwgreg.src_addr = mystique->dwgreg.ar[3]; + mystique->dwgreg.words = 0; + mystique->dwgreg.iload_rem_count = 0; + mystique->dwgreg.iload_rem_data = 0; + mystique->dwgreg.idump_end_of_line = 0; + mystique->busy = 1; + /* pclog("IDUMP ATYPE RPL busy\n"); */ + break; - default: - fatal("Unknown IDUMP atype %03x %08x\n", mystique->dwgreg.dwgctrl_running & DWGCTRL_ATYPE_MASK, mystique->dwgreg.dwgctrl_running); + default: + fatal("Unknown IDUMP atype %03x %08x\n", mystique->dwgreg.dwgctrl_running & DWGCTRL_ATYPE_MASK, mystique->dwgreg.dwgctrl_running); } } - static void blit_iload_scale(mystique_t *mystique) { switch (mystique->dwgreg.dwgctrl_running & DWGCTRL_ATYPE_MASK) { - case DWGCTRL_ATYPE_RPL: - switch (mystique->dwgreg.dwgctrl_running & DWGCTRL_BLTMOD_MASK) { - case DWGCTRL_BLTMOD_BUYUV: - mystique->dwgreg.length_cur = mystique->dwgreg.length; - mystique->dwgreg.xdst = mystique->dwgreg.fxleft; - mystique->dwgreg.iload_rem_data = 0; - mystique->dwgreg.iload_rem_count = 0; - mystique->busy = 1; - mystique->dwgreg.words = 0; - /* pclog("ILOAD SCALE ATYPE RPL BLTMOD BUYUV busy\n"); */ - break; + case DWGCTRL_ATYPE_RPL: + switch (mystique->dwgreg.dwgctrl_running & DWGCTRL_BLTMOD_MASK) { + case DWGCTRL_BLTMOD_BUYUV: + mystique->dwgreg.length_cur = mystique->dwgreg.length; + mystique->dwgreg.xdst = mystique->dwgreg.fxleft; + mystique->dwgreg.iload_rem_data = 0; + mystique->dwgreg.iload_rem_count = 0; + mystique->busy = 1; + mystique->dwgreg.words = 0; + /* pclog("ILOAD SCALE ATYPE RPL BLTMOD BUYUV busy\n"); */ + break; - default: - fatal("ILOAD_SCALE DWGCTRL_ATYPE_RPL %08x %08x\n", mystique->dwgreg.dwgctrl_running & DWGCTRL_BLTMOD_MASK, mystique->dwgreg.dwgctrl_running); - break; - } - break; + default: + fatal("ILOAD_SCALE DWGCTRL_ATYPE_RPL %08x %08x\n", mystique->dwgreg.dwgctrl_running & DWGCTRL_BLTMOD_MASK, mystique->dwgreg.dwgctrl_running); + break; + } + break; - default: - fatal("Unknown ILOAD_SCALE atype %03x %08x\n", mystique->dwgreg.dwgctrl_running & DWGCTRL_ATYPE_MASK, mystique->dwgreg.dwgctrl_running); + default: + fatal("Unknown ILOAD_SCALE atype %03x %08x\n", mystique->dwgreg.dwgctrl_running & DWGCTRL_ATYPE_MASK, mystique->dwgreg.dwgctrl_running); } } - static void blit_iload_high(mystique_t *mystique) { switch (mystique->dwgreg.dwgctrl_running & DWGCTRL_ATYPE_MASK) { - case DWGCTRL_ATYPE_RPL: - switch (mystique->dwgreg.dwgctrl_running & DWGCTRL_BLTMOD_MASK) { - case DWGCTRL_BLTMOD_BUYUV: - case DWGCTRL_BLTMOD_BU32BGR: - mystique->dwgreg.length_cur = mystique->dwgreg.length; - mystique->dwgreg.xdst = mystique->dwgreg.fxleft; - mystique->dwgreg.iload_rem_data = 0; - mystique->dwgreg.iload_rem_count = 0; - mystique->busy = 1; - mystique->dwgreg.words = 0; - /* pclog("ILOAD HIGH ATYPE RPL BLTMOD BUYUV busy\n"); */ - break; + case DWGCTRL_ATYPE_RPL: + switch (mystique->dwgreg.dwgctrl_running & DWGCTRL_BLTMOD_MASK) { + case DWGCTRL_BLTMOD_BUYUV: + case DWGCTRL_BLTMOD_BU32BGR: + mystique->dwgreg.length_cur = mystique->dwgreg.length; + mystique->dwgreg.xdst = mystique->dwgreg.fxleft; + mystique->dwgreg.iload_rem_data = 0; + mystique->dwgreg.iload_rem_count = 0; + mystique->busy = 1; + mystique->dwgreg.words = 0; + /* pclog("ILOAD HIGH ATYPE RPL BLTMOD BUYUV busy\n"); */ + break; - default: - fatal("ILOAD_HIGH DWGCTRL_ATYPE_RPL %08x %08x\n", mystique->dwgreg.dwgctrl_running & DWGCTRL_BLTMOD_MASK, mystique->dwgreg.dwgctrl_running); - break; - } - break; + default: + fatal("ILOAD_HIGH DWGCTRL_ATYPE_RPL %08x %08x\n", mystique->dwgreg.dwgctrl_running & DWGCTRL_BLTMOD_MASK, mystique->dwgreg.dwgctrl_running); + break; + } + break; - default: - fatal("Unknown ILOAD_HIGH atype %03x %08x\n", mystique->dwgreg.dwgctrl_running & DWGCTRL_ATYPE_MASK, mystique->dwgreg.dwgctrl_running); + default: + fatal("Unknown ILOAD_HIGH atype %03x %08x\n", mystique->dwgreg.dwgctrl_running & DWGCTRL_ATYPE_MASK, mystique->dwgreg.dwgctrl_running); } } - -static -void blit_iload_highv(mystique_t *mystique) +static void +blit_iload_highv(mystique_t *mystique) { switch (mystique->dwgreg.dwgctrl_running & DWGCTRL_ATYPE_MASK) { - case DWGCTRL_ATYPE_RPL: - switch (mystique->dwgreg.dwgctrl_running & DWGCTRL_BLTMOD_MASK) { - case DWGCTRL_BLTMOD_BUYUV: - mystique->dwgreg.length_cur = mystique->dwgreg.length; - mystique->dwgreg.xdst = mystique->dwgreg.fxleft; - mystique->dwgreg.iload_rem_data = 0; - mystique->dwgreg.iload_rem_count = 0; - mystique->busy = 1; - mystique->dwgreg.words = 0; - mystique->dwgreg.highv_line = 0; - mystique->dwgreg.lastpix_r = 0; - mystique->dwgreg.lastpix_g = 0; - mystique->dwgreg.lastpix_b = 0; - /* pclog("ILOAD HIGHV ATYPE RPL BLTMOD BUYUV busy\n"); */ - break; + case DWGCTRL_ATYPE_RPL: + switch (mystique->dwgreg.dwgctrl_running & DWGCTRL_BLTMOD_MASK) { + case DWGCTRL_BLTMOD_BUYUV: + mystique->dwgreg.length_cur = mystique->dwgreg.length; + mystique->dwgreg.xdst = mystique->dwgreg.fxleft; + mystique->dwgreg.iload_rem_data = 0; + mystique->dwgreg.iload_rem_count = 0; + mystique->busy = 1; + mystique->dwgreg.words = 0; + mystique->dwgreg.highv_line = 0; + mystique->dwgreg.lastpix_r = 0; + mystique->dwgreg.lastpix_g = 0; + mystique->dwgreg.lastpix_b = 0; + /* pclog("ILOAD HIGHV ATYPE RPL BLTMOD BUYUV busy\n"); */ + break; - default: - fatal("ILOAD_HIGHV DWGCTRL_ATYPE_RPL %08x %08x\n", mystique->dwgreg.dwgctrl_running & DWGCTRL_BLTMOD_MASK, mystique->dwgreg.dwgctrl_running); - break; - } - break; + default: + fatal("ILOAD_HIGHV DWGCTRL_ATYPE_RPL %08x %08x\n", mystique->dwgreg.dwgctrl_running & DWGCTRL_BLTMOD_MASK, mystique->dwgreg.dwgctrl_running); + break; + } + break; - default: - fatal("Unknown ILOAD_HIGHV atype %03x %08x\n", mystique->dwgreg.dwgctrl_running & DWGCTRL_ATYPE_MASK, mystique->dwgreg.dwgctrl_running); + default: + fatal("Unknown ILOAD_HIGHV atype %03x %08x\n", mystique->dwgreg.dwgctrl_running & DWGCTRL_ATYPE_MASK, mystique->dwgreg.dwgctrl_running); } } - static void mystique_start_blit(mystique_t *mystique) { @@ -4866,361 +5125,454 @@ mystique_start_blit(mystique_t *mystique) uint64_t end_time; mystique->dwgreg.dwgctrl_running = mystique->dwgreg.dwgctrl; - mystique->maccess_running = mystique->maccess; + mystique->maccess_running = mystique->maccess; switch (mystique->dwgreg.dwgctrl_running & DWGCTRL_OPCODE_MASK) { - case DWGCTRL_OPCODE_LINE_OPEN: - blit_line(mystique, 0); - break; + case DWGCTRL_OPCODE_LINE_OPEN: + blit_line(mystique, 0); + break; - case DWGCTRL_OPCODE_AUTOLINE_OPEN: - blit_autoline(mystique, 0); - break; - - case DWGCTRL_OPCODE_LINE_CLOSE: - blit_line(mystique, 1); - break; + case DWGCTRL_OPCODE_AUTOLINE_OPEN: + blit_autoline(mystique, 0); + break; - case DWGCTRL_OPCODE_AUTOLINE_CLOSE: - blit_autoline(mystique, 1); - break; + case DWGCTRL_OPCODE_LINE_CLOSE: + blit_line(mystique, 1); + break; - case DWGCTRL_OPCODE_TRAP: - blit_trap(mystique); - break; + case DWGCTRL_OPCODE_AUTOLINE_CLOSE: + blit_autoline(mystique, 1); + break; - case DWGCTRL_OPCODE_TEXTURE_TRAP: - blit_texture_trap(mystique); - break; + case DWGCTRL_OPCODE_TRAP: + blit_trap(mystique); + break; - case DWGCTRL_OPCODE_ILOAD_HIGH: - blit_iload_high(mystique); - break; + case DWGCTRL_OPCODE_TEXTURE_TRAP: + blit_texture_trap(mystique); + break; - case DWGCTRL_OPCODE_BITBLT: - blit_bitblt(mystique); - break; + case DWGCTRL_OPCODE_ILOAD_HIGH: + blit_iload_high(mystique); + break; - case DWGCTRL_OPCODE_FBITBLT: - blit_fbitblt(mystique); - break; + case DWGCTRL_OPCODE_BITBLT: + blit_bitblt(mystique); + break; - case DWGCTRL_OPCODE_ILOAD: - blit_iload(mystique); - break; + case DWGCTRL_OPCODE_FBITBLT: + blit_fbitblt(mystique); + break; - case DWGCTRL_OPCODE_IDUMP: - blit_idump(mystique); - break; + case DWGCTRL_OPCODE_ILOAD: + blit_iload(mystique); + break; - case DWGCTRL_OPCODE_ILOAD_SCALE: - blit_iload_scale(mystique); - break; + case DWGCTRL_OPCODE_IDUMP: + blit_idump(mystique); + break; - case DWGCTRL_OPCODE_ILOAD_HIGHV: - blit_iload_highv(mystique); - break; + case DWGCTRL_OPCODE_ILOAD_SCALE: + blit_iload_scale(mystique); + break; - case DWGCTRL_OPCODE_ILOAD_FILTER: - /* TODO: Actually implement this. */ - break; + case DWGCTRL_OPCODE_ILOAD_HIGHV: + blit_iload_highv(mystique); + break; - default: - fatal("mystique_start_blit: unknown blit %08x\n", mystique->dwgreg.dwgctrl_running & DWGCTRL_OPCODE_MASK); - break; + case DWGCTRL_OPCODE_ILOAD_FILTER: + /* TODO: Actually implement this. */ + break; + + default: + fatal("mystique_start_blit: unknown blit %08x\n", mystique->dwgreg.dwgctrl_running & DWGCTRL_OPCODE_MASK); + break; } end_time = plat_timer_read(); mystique->blitter_time += end_time - start_time; } - static void mystique_hwcursor_draw(svga_t *svga, int displine) { - mystique_t *mystique = (mystique_t *)svga->p; - int x; - uint64_t dat[2]; - int offset = svga->hwcursor_latch.x - svga->hwcursor_latch.xoff; + const mystique_t *mystique = (mystique_t *) svga->priv; + uint64_t dat[2]; + int offset = svga->hwcursor_latch.x - svga->hwcursor_latch.xoff; if (svga->interlace && svga->hwcursor_oddeven) - svga->hwcursor_latch.addr += 16; + svga->hwcursor_latch.addr += 16; - dat[0] = *(uint64_t *)(&svga->vram[svga->hwcursor_latch.addr]); - dat[1] = *(uint64_t *)(&svga->vram[svga->hwcursor_latch.addr + 8]); + dat[0] = *(uint64_t *) (&svga->vram[svga->hwcursor_latch.addr]); + dat[1] = *(uint64_t *) (&svga->vram[svga->hwcursor_latch.addr + 8]); svga->hwcursor_latch.addr += 16; switch (mystique->xcurctrl & XCURCTRL_CURMODE_MASK) { - case XCURCTRL_CURMODE_XGA: - for (x = 0; x < 64; x ++) { - if (!(dat[1] & (1ull << 63))) - buffer32->line[displine][offset + svga->x_add] = (dat[0] & (1ull << 63)) ? mystique->cursor.col[1] : mystique->cursor.col[0]; - else if (dat[0] & (1ull << 63)) - buffer32->line[displine][offset + svga->x_add] ^= 0xffffff; + case XCURCTRL_CURMODE_XGA: + for (uint8_t x = 0; x < 64; x++) { + if (!(dat[1] & (1ULL << 63))) + svga->monitor->target_buffer->line[displine][offset + svga->x_add] = (dat[0] & (1ULL << 63)) ? mystique->cursor.col[1] : mystique->cursor.col[0]; + else if (dat[0] & (1ULL << 63)) + svga->monitor->target_buffer->line[displine][offset + svga->x_add] ^= 0xffffff; - offset++; - dat[0] <<= 1; - dat[1] <<= 1; - } - break; + offset++; + dat[0] <<= 1; + dat[1] <<= 1; + } + break; + + default: + break; } if (svga->interlace && !svga->hwcursor_oddeven) - svga->hwcursor_latch.addr += 16; + svga->hwcursor_latch.addr += 16; } - -static -uint8_t mystique_pci_read(int func, int addr, void *p) +static uint8_t +mystique_pci_read(UNUSED(int func), int addr, void *priv) { - mystique_t *mystique = (mystique_t *)p; - uint8_t ret = 0x00; + mystique_t *mystique = (mystique_t *) priv; + uint8_t ret = 0x00; if ((addr >= 0x30) && (addr <= 0x33) && !(mystique->pci_regs[0x43] & 0x40)) - ret = 0x00; - else switch (addr) { - case 0x00: ret = 0x2b; break; /*Matrox*/ - case 0x01: ret = 0x10; break; + ret = 0x00; + else + switch (addr) { + case 0x00: + ret = 0x2b; + break; /*Matrox*/ + case 0x01: + ret = 0x10; + break; - case 0x02: ret = (mystique->type == MGA_2064W) ? 0x19 : 0x1a; break; /*MGA*/ - case 0x03: ret = 0x05; break; + case 0x02: + ret = (mystique->type == MGA_2064W) ? 0x19 : 0x1a; + break; /*MGA*/ + case 0x03: + ret = 0x05; + break; - case PCI_REG_COMMAND: - ret = mystique->pci_regs[PCI_REG_COMMAND] | 0x80; break; /*Respond to IO and memory accesses*/ - case 0x05: - ret = 0x00; break; + case PCI_REG_COMMAND: + ret = mystique->pci_regs[PCI_REG_COMMAND] | 0x80; + break; /*Respond to IO and memory accesses*/ + case 0x05: + ret = 0x00; + break; - case 0x06: ret = 0x80; break; - case 0x07: ret = mystique->pci_regs[0x07]; break; /*Fast DEVSEL timing*/ + case 0x06: + ret = 0x80; + break; + case 0x07: + ret = mystique->pci_regs[0x07]; + break; /*Fast DEVSEL timing*/ - case 0x08: ret = 0; break; /*Revision ID*/ - case 0x09: ret = 0; break; /*Programming interface*/ + case 0x08: + ret = 0; + break; /*Revision ID*/ + case 0x09: + ret = 0; + break; /*Programming interface*/ - case 0x0a: ret = 0x00; break; /*Supports VGA interface*/ - case 0x0b: ret = 0x03; break; + case 0x0a: + ret = 0x00; + break; /*Supports VGA interface*/ + case 0x0b: + ret = 0x03; + break; - case 0x10: ret = 0x00; break; /*Control aperture*/ - case 0x11: ret = (mystique->ctrl_base >> 8) & 0xc0; break; - case 0x12: ret = mystique->ctrl_base >> 16; break; - case 0x13: ret = mystique->ctrl_base >> 24; break; + case 0x10: + ret = 0x00; + break; /*Control aperture*/ + case 0x11: + ret = (mystique->ctrl_base >> 8) & 0xc0; + break; + case 0x12: + ret = mystique->ctrl_base >> 16; + break; + case 0x13: + ret = mystique->ctrl_base >> 24; + break; - case 0x14: ret = 0x00; break; /*Linear frame buffer*/ - case 0x16: ret = (mystique->lfb_base >> 16) & 0x80; break; - case 0x17: ret = mystique->lfb_base >> 24; break; + case 0x14: + ret = 0x00; + break; /*Linear frame buffer*/ + case 0x16: + ret = (mystique->lfb_base >> 16) & 0x80; + break; + case 0x17: + ret = mystique->lfb_base >> 24; + break; - case 0x18: ret = 0x00; break; /*Pseudo-DMA (ILOAD)*/ - case 0x1a: ret = (mystique->iload_base >> 16) & 0x80; break; - case 0x1b: ret = mystique->iload_base >> 24; break; + case 0x18: + ret = 0x00; + break; /*Pseudo-DMA (ILOAD)*/ + case 0x1a: + ret = (mystique->iload_base >> 16) & 0x80; + break; + case 0x1b: + ret = mystique->iload_base >> 24; + break; - case 0x2c: ret = mystique->pci_regs[0x2c]; break; - case 0x2d: ret = mystique->pci_regs[0x2d]; break; - case 0x2e: ret = mystique->pci_regs[0x2e]; break; - case 0x2f: ret = mystique->pci_regs[0x2f]; break; + case 0x2c: + ret = mystique->pci_regs[0x2c]; + break; + case 0x2d: + ret = mystique->pci_regs[0x2d]; + break; + case 0x2e: + ret = mystique->pci_regs[0x2e]; + break; + case 0x2f: + ret = mystique->pci_regs[0x2f]; + break; - case 0x30: ret = mystique->pci_regs[0x30] & 0x01; break; /*BIOS ROM address*/ - case 0x31: ret = 0x00; break; - case 0x32: ret = mystique->pci_regs[0x32]; break; - case 0x33: ret = mystique->pci_regs[0x33]; break; + case 0x30: + ret = mystique->pci_regs[0x30] & 0x01; + break; /*BIOS ROM address*/ + case 0x31: + ret = 0x00; + break; + case 0x32: + ret = mystique->pci_regs[0x32]; + break; + case 0x33: + ret = mystique->pci_regs[0x33]; + break; - case 0x3c: ret = mystique->int_line; break; - case 0x3d: ret = PCI_INTA; break; + case 0x3c: + ret = mystique->int_line; + break; + case 0x3d: + ret = PCI_INTA; + break; - case 0x40: ret = mystique->pci_regs[0x40]; break; - case 0x41: ret = mystique->pci_regs[0x41]; break; - case 0x42: ret = mystique->pci_regs[0x42]; break; - case 0x43: ret = mystique->pci_regs[0x43]; break; + case 0x40: + ret = mystique->pci_regs[0x40]; + break; + case 0x41: + ret = mystique->pci_regs[0x41]; + break; + case 0x42: + ret = mystique->pci_regs[0x42]; + break; + case 0x43: + ret = mystique->pci_regs[0x43]; + break; - case 0x44: ret = mystique->pci_regs[0x44]; break; - case 0x45: ret = mystique->pci_regs[0x45]; break; + case 0x44: + ret = mystique->pci_regs[0x44]; + break; + case 0x45: + ret = mystique->pci_regs[0x45]; + break; - case 0x48: case 0x49: case 0x4a: case 0x4b: - addr = (mystique->pci_regs[0x44] & 0xfc) | ((mystique->pci_regs[0x45] & 0x3f) << 8) | - (addr & 3); - ret = mystique_ctrl_read_b(addr, mystique); break; - } + case 0x48: + case 0x49: + case 0x4a: + case 0x4b: + addr = (mystique->pci_regs[0x44] & 0xfc) | ((mystique->pci_regs[0x45] & 0x3f) << 8) | (addr & 3); + ret = mystique_ctrl_read_b(addr, mystique); + break; + + default: + break; + } return ret; } static void -mystique_pci_write(int func, int addr, uint8_t val, void *p) +mystique_pci_write(UNUSED(int func), int addr, uint8_t val, void *priv) { - mystique_t *mystique = (mystique_t *)p; + mystique_t *mystique = (mystique_t *) priv; switch (addr) { - case PCI_REG_COMMAND: - mystique->pci_regs[PCI_REG_COMMAND] = (val & 0x27) | 0x80; - mystique_recalc_mapping(mystique); - break; + case PCI_REG_COMMAND: + mystique->pci_regs[PCI_REG_COMMAND] = (val & 0x27) | 0x80; + mystique_recalc_mapping(mystique); + break; - case 0x07: - mystique->pci_regs[0x07] &= ~(val & 0x38); - break; + case 0x07: + mystique->pci_regs[0x07] &= ~(val & 0x38); + break; - case 0x0d: - mystique->pci_regs[0x0d] = val; - break; + case 0x0d: + mystique->pci_regs[0x0d] = val; + break; - case 0x11: - mystique->ctrl_base = (mystique->ctrl_base & 0xffff0000) | ((val & 0xc0) << 8); - mystique_recalc_mapping(mystique); - break; - case 0x12: - mystique->ctrl_base = (mystique->ctrl_base & 0xff00c000) | (val << 16); - mystique_recalc_mapping(mystique); - break; - case 0x13: - mystique->ctrl_base = (mystique->ctrl_base & 0x00ffc000) | (val << 24); - mystique_recalc_mapping(mystique); - break; + case 0x11: + mystique->ctrl_base = (mystique->ctrl_base & 0xffff0000) | ((val & 0xc0) << 8); + mystique_recalc_mapping(mystique); + break; + case 0x12: + mystique->ctrl_base = (mystique->ctrl_base & 0xff00c000) | (val << 16); + mystique_recalc_mapping(mystique); + break; + case 0x13: + mystique->ctrl_base = (mystique->ctrl_base & 0x00ffc000) | (val << 24); + mystique_recalc_mapping(mystique); + break; - case 0x16: - mystique->lfb_base = (mystique->lfb_base & 0xff000000) | ((val & 0x80) << 16); - mystique_recalc_mapping(mystique); - break; - case 0x17: - mystique->lfb_base = (mystique->lfb_base & 0x00800000) | (val << 24); - mystique_recalc_mapping(mystique); - break; + case 0x16: + mystique->lfb_base = (mystique->lfb_base & 0xff000000) | ((val & 0x80) << 16); + mystique_recalc_mapping(mystique); + break; + case 0x17: + mystique->lfb_base = (mystique->lfb_base & 0x00800000) | (val << 24); + mystique_recalc_mapping(mystique); + break; - case 0x1a: - mystique->iload_base = (mystique->iload_base & 0xff000000) | ((val & 0x80) << 16); - mystique_recalc_mapping(mystique); - break; - case 0x1b: - mystique->iload_base = (mystique->iload_base & 0x00800000) | (val << 24); - mystique_recalc_mapping(mystique); - break; + case 0x1a: + mystique->iload_base = (mystique->iload_base & 0xff000000) | ((val & 0x80) << 16); + mystique_recalc_mapping(mystique); + break; + case 0x1b: + mystique->iload_base = (mystique->iload_base & 0x00800000) | (val << 24); + mystique_recalc_mapping(mystique); + break; - case 0x30: case 0x32: case 0x33: - if (!(mystique->pci_regs[0x43] & 0x40)) - return; - mystique->pci_regs[addr] = val; - if (mystique->pci_regs[0x30] & 0x01) { - uint32_t addr = (mystique->pci_regs[0x32] << 16) | (mystique->pci_regs[0x33] << 24); - mem_mapping_set_addr(&mystique->bios_rom.mapping, addr, 0x8000); + case 0x30: + case 0x32: + case 0x33: + if (!(mystique->pci_regs[0x43] & 0x40)) + return; + mystique->pci_regs[addr] = val; + if (mystique->pci_regs[0x30] & 0x01) { + uint32_t addr = (mystique->pci_regs[0x32] << 16) | (mystique->pci_regs[0x33] << 24); + mem_mapping_set_addr(&mystique->bios_rom.mapping, addr, 0x8000); + } else + mem_mapping_disable(&mystique->bios_rom.mapping); + return; + + case 0x3c: + mystique->int_line = val; + return; + + case 0x40: + mystique->pci_regs[addr] = val & 0x3f; + break; + case 0x41: + mystique->pci_regs[addr] = val; + break; + case 0x42: + mystique->pci_regs[addr] = val & 0x1f; + break; + case 0x43: + mystique->pci_regs[addr] = val; + if (addr == 0x43) { + if (val & 0x40) { + if (mystique->pci_regs[0x30] & 0x01) { + uint32_t addr = (mystique->pci_regs[0x32] << 16) | (mystique->pci_regs[0x33] << 24); + mem_mapping_set_addr(&mystique->bios_rom.mapping, addr, 0x8000); + } else + mem_mapping_disable(&mystique->bios_rom.mapping); } else - mem_mapping_disable(&mystique->bios_rom.mapping); - return; + mem_mapping_set_addr(&mystique->bios_rom.mapping, 0x000c0000, 0x8000); + } + break; - case 0x3c: - mystique->int_line = val; - return; + case 0x4c: + case 0x4d: + case 0x4e: + case 0x4f: + mystique->pci_regs[addr - 0x20] = val; + break; - case 0x40: - mystique->pci_regs[addr] = val & 0x3f; - break; - case 0x41: - mystique->pci_regs[addr] = val; - break; - case 0x42: - mystique->pci_regs[addr] = val & 0x1f; - break; - case 0x43: - mystique->pci_regs[addr] = val; - if (addr == 0x43) { - if (val & 0x40) { - if (mystique->pci_regs[0x30] & 0x01) { - uint32_t addr = (mystique->pci_regs[0x32] << 16) | (mystique->pci_regs[0x33] << 24); - mem_mapping_set_addr(&mystique->bios_rom.mapping, addr, 0x8000); - } else - mem_mapping_disable(&mystique->bios_rom.mapping); - } else - mem_mapping_set_addr(&mystique->bios_rom.mapping, 0x000c0000, 0x8000); - } - break; + case 0x44: + mystique->pci_regs[addr] = val & 0xfc; + break; + case 0x45: + mystique->pci_regs[addr] = val & 0x3f; + break; - case 0x4c: case 0x4d: case 0x4e: case 0x4f: - mystique->pci_regs[addr - 0x20] = val; - break; + case 0x48: + case 0x49: + case 0x4a: + case 0x4b: + addr = (mystique->pci_regs[0x44] & 0xfc) | ((mystique->pci_regs[0x45] & 0x3f) << 8) | (addr & 3); +#if 0 + pclog("mystique_ctrl_write_b(%04X, %02X)\n", addr, val); +#endif + mystique_ctrl_write_b(addr, val, mystique); + break; - case 0x44: - mystique->pci_regs[addr] = val & 0xfc; - break; - case 0x45: - mystique->pci_regs[addr] = val & 0x3f; - break; - - case 0x48: case 0x49: case 0x4a: case 0x4b: - addr = (mystique->pci_regs[0x44] & 0xfc) | ((mystique->pci_regs[0x45] & 0x3f) << 8) | - (addr & 3); - /* pclog("mystique_ctrl_write_b(%04X, %02X)\n", addr, val); */ - mystique_ctrl_write_b(addr, val, mystique); - break; + default: + break; } } - - static void * mystique_init(const device_t *info) { - int c; mystique_t *mystique = malloc(sizeof(mystique_t)); - char *romfn; + const char *romfn = NULL; memset(mystique, 0, sizeof(mystique_t)); - mystique->type = info->local; - - if (mystique->type == MGA_2064W) - romfn = ROM_MILLENNIUM; - else if (mystique->type == MGA_1064SG) - romfn = ROM_MYSTIQUE; - else - romfn = ROM_MYSTIQUE_220; + mystique->type = info->local; + + if (mystique->type == MGA_2064W) + romfn = ROM_MILLENNIUM; + else if (mystique->type == MGA_1064SG) + romfn = ROM_MYSTIQUE; + else + romfn = ROM_MYSTIQUE_220; rom_init(&mystique->bios_rom, romfn, 0xc0000, 0x8000, 0x7fff, 0, MEM_MAPPING_EXTERNAL); mem_mapping_disable(&mystique->bios_rom.mapping); - mystique->vram_size = device_get_config_int("memory"); - mystique->vram_mask = (mystique->vram_size << 20) - 1; + mystique->vram_size = device_get_config_int("memory"); + mystique->vram_mask = (mystique->vram_size << 20) - 1; mystique->vram_mask_w = mystique->vram_mask >> 1; mystique->vram_mask_l = mystique->vram_mask >> 2; video_inform(VIDEO_FLAG_TYPE_SPECIAL, &timing_matrox_mystique); if (mystique->type == MGA_2064W) { - video_inform(VIDEO_FLAG_TYPE_SPECIAL, &timing_matrox_millennium); - svga_init(info, &mystique->svga, mystique, mystique->vram_size << 20, - mystique_recalctimings, - mystique_in, mystique_out, - NULL, - NULL); - mystique->svga.dac_hwcursor_draw = tvp3026_hwcursor_draw; - mystique->svga.ramdac = device_add(&tvp3026_ramdac_device); - mystique->svga.clock_gen = mystique->svga.ramdac; - mystique->svga.getclock = tvp3026_getclock; - } else { - video_inform(VIDEO_FLAG_TYPE_SPECIAL, &timing_matrox_mystique); - svga_init(info, &mystique->svga, mystique, mystique->vram_size << 20, - mystique_recalctimings, - mystique_in, mystique_out, - mystique_hwcursor_draw, - NULL); - mystique->svga.clock_gen = mystique; - mystique->svga.getclock = mystique_getclock; - } + video_inform(VIDEO_FLAG_TYPE_SPECIAL, &timing_matrox_millennium); + svga_init(info, &mystique->svga, mystique, mystique->vram_size << 20, + mystique_recalctimings, + mystique_in, mystique_out, + NULL, + NULL); + mystique->svga.dac_hwcursor_draw = tvp3026_hwcursor_draw; + mystique->svga.ramdac = device_add(&tvp3026_ramdac_device); + mystique->svga.clock_gen = mystique->svga.ramdac; + mystique->svga.getclock = tvp3026_getclock; + } else { + video_inform(VIDEO_FLAG_TYPE_SPECIAL, &timing_matrox_mystique); + svga_init(info, &mystique->svga, mystique, mystique->vram_size << 20, + mystique_recalctimings, + mystique_in, mystique_out, + mystique_hwcursor_draw, + NULL); + mystique->svga.clock_gen = mystique; + mystique->svga.getclock = mystique_getclock; + } io_sethandler(0x03c0, 0x0020, mystique_in, NULL, NULL, mystique_out, NULL, NULL, mystique); mem_mapping_add(&mystique->ctrl_mapping, 0, 0, - mystique_ctrl_read_b, NULL, mystique_ctrl_read_l, - mystique_ctrl_write_b, NULL, mystique_ctrl_write_l, - NULL, 0, mystique); + mystique_ctrl_read_b, NULL, mystique_ctrl_read_l, + mystique_ctrl_write_b, NULL, mystique_ctrl_write_l, + NULL, 0, mystique); mem_mapping_disable(&mystique->ctrl_mapping); mem_mapping_add(&mystique->lfb_mapping, 0, 0, - mystique_readb_linear, mystique_readw_linear, mystique_readl_linear, - mystique_writeb_linear, mystique_writew_linear, mystique_writel_linear, - NULL, 0, mystique); + mystique_readb_linear, mystique_readw_linear, mystique_readl_linear, + mystique_writeb_linear, mystique_writew_linear, mystique_writel_linear, + NULL, 0, mystique); mem_mapping_disable(&mystique->lfb_mapping); mem_mapping_add(&mystique->iload_mapping, 0, 0, - mystique_iload_read_b, NULL, mystique_iload_read_l, - mystique_iload_write_b, NULL, mystique_iload_write_l, - NULL, 0, mystique); + mystique_iload_read_b, NULL, mystique_iload_read_l, + mystique_iload_write_b, NULL, mystique_iload_write_l, + NULL, 0, mystique); mem_mapping_disable(&mystique->iload_mapping); - mystique->card = pci_add_card(PCI_ADD_VIDEO, mystique_pci_read, mystique_pci_write, mystique); + if (romfn == NULL) + pci_add_card(PCI_ADD_VIDEO, mystique_pci_read, mystique_pci_write, mystique, &mystique->pci_slot); + else + pci_add_card(PCI_ADD_NORMAL, mystique_pci_read, mystique_pci_write, mystique, &mystique->pci_slot); mystique->pci_regs[0x06] = 0x80; mystique->pci_regs[0x07] = 0 << 1; mystique->pci_regs[0x2c] = mystique->bios_rom.rom[0x7ff8]; @@ -5228,61 +5580,60 @@ mystique_init(const device_t *info) mystique->pci_regs[0x2e] = mystique->bios_rom.rom[0x7ffa]; mystique->pci_regs[0x2f] = mystique->bios_rom.rom[0x7ffb]; - mystique->svga.miscout = 1; - mystique->pci_regs[0x41] = 0x01; /* vgaboot = 1 */ - mystique->pci_regs[0x43] = 0x40; /* biosen = 1 */ + mystique->svga.miscout = 1; + mystique->pci_regs[0x41] = 0x01; /* vgaboot = 1 */ + mystique->pci_regs[0x43] = 0x40; /* biosen = 1 */ - for (c = 0; c < 256; c++) { - dither5[c][0][0] = c >> 3; - dither5[c][1][1] = (c + 2) >> 3; - dither5[c][1][0] = (c + 4) >> 3; - dither5[c][0][1] = (c + 6) >> 3; + for (uint16_t c = 0; c < 256; c++) { + dither5[c][0][0] = c >> 3; + dither5[c][1][1] = (c + 2) >> 3; + dither5[c][1][0] = (c + 4) >> 3; + dither5[c][0][1] = (c + 6) >> 3; - if (dither5[c][1][1] > 31) - dither5[c][1][1] = 31; - if (dither5[c][1][0] > 31) - dither5[c][1][0] = 31; - if (dither5[c][0][1] > 31) - dither5[c][0][1] = 31; + if (dither5[c][1][1] > 31) + dither5[c][1][1] = 31; + if (dither5[c][1][0] > 31) + dither5[c][1][0] = 31; + if (dither5[c][0][1] > 31) + dither5[c][0][1] = 31; - dither6[c][0][0] = c >> 2; - dither6[c][1][1] = (c + 1) >> 2; - dither6[c][1][0] = (c + 2) >> 2; - dither6[c][0][1] = (c + 3) >> 2; + dither6[c][0][0] = c >> 2; + dither6[c][1][1] = (c + 1) >> 2; + dither6[c][1][0] = (c + 2) >> 2; + dither6[c][0][1] = (c + 3) >> 2; - if (dither6[c][1][1] > 63) - dither6[c][1][1] = 63; - if (dither6[c][1][0] > 63) - dither6[c][1][0] = 63; - if (dither6[c][0][1] > 63) - dither6[c][0][1] = 63; + if (dither6[c][1][1] > 63) + dither6[c][1][1] = 63; + if (dither6[c][1][0] > 63) + dither6[c][1][0] = 63; + if (dither6[c][0][1] > 63) + dither6[c][0][1] = 63; } - mystique->wake_fifo_thread = thread_create_event(); + mystique->wake_fifo_thread = thread_create_event(); mystique->fifo_not_full_event = thread_create_event(); - mystique->thread_run = 1; - mystique->fifo_thread = thread_create(fifo_thread, mystique); - mystique->dma.lock = thread_create_mutex(); + mystique->thread_run = 1; + mystique->fifo_thread = thread_create(fifo_thread, mystique); + mystique->dma.lock = thread_create_mutex(); - timer_add(&mystique->wake_timer, mystique_wake_timer, (void *)mystique, 0); - timer_add(&mystique->softrap_pending_timer, mystique_softrap_pending_timer, (void *)mystique, 1); + timer_add(&mystique->wake_timer, mystique_wake_timer, (void *) mystique, 0); + timer_add(&mystique->softrap_pending_timer, mystique_softrap_pending_timer, (void *) mystique, 1); mystique->status = STATUS_ENDPRDMASTS; mystique->svga.vsync_callback = mystique_vsync_callback; - mystique->i2c = i2c_gpio_init("i2c_mga"); + mystique->i2c = i2c_gpio_init("i2c_mga"); mystique->i2c_ddc = i2c_gpio_init("ddc_mga"); - mystique->ddc = ddc_init(i2c_gpio_get_bus(mystique->i2c_ddc)); + mystique->ddc = ddc_init(i2c_gpio_get_bus(mystique->i2c_ddc)); return mystique; } - static void -mystique_close(void *p) +mystique_close(void *priv) { - mystique_t *mystique = (mystique_t *)p; + mystique_t *mystique = (mystique_t *) priv; mystique->thread_run = 0; thread_set_event(mystique->wake_fifo_thread); @@ -5318,99 +5669,92 @@ mystique_220_available(void) return rom_present(ROM_MYSTIQUE_220); } - static void -mystique_speed_changed(void *p) +mystique_speed_changed(void *priv) { - mystique_t *mystique = (mystique_t *)p; + mystique_t *mystique = (mystique_t *) priv; svga_recalctimings(&mystique->svga); } - static void -mystique_force_redraw(void *p) +mystique_force_redraw(void *priv) { - mystique_t *mystique = (mystique_t *)p; + mystique_t *mystique = (mystique_t *) priv; mystique->svga.fullchange = changeframecount; } - -static const device_config_t mystique_config[] = -{ +static const device_config_t mystique_config[] = { + // clang-format off { - .name = "memory", - .description = "Memory size", - .type = CONFIG_SELECTION, - .selection = - { - { - .description = "2 MB", - .value = 2 - }, - { - .description = "4 MB", - .value = 4 - }, - { - .description = "8 MB", - .value = 8 - }, - { - .description = "" - } - }, - .default_int = 8 + .name = "memory", + .description = "Memory size", + .type = CONFIG_SELECTION, + .selection = + { + { + .description = "2 MB", + .value = 2 + }, + { + .description = "4 MB", + .value = 4 + }, + { + .description = "8 MB", + .value = 8 + }, + { + .description = "" + } + }, + .default_int = 8 }, { - .type = -1 + .type = CONFIG_END } + // clang-format on }; -const device_t millennium_device = -{ - "Matrox Millennium", - "millennium", - DEVICE_PCI, - MGA_2064W, - mystique_init, - mystique_close, - NULL, - { millennium_available }, - mystique_speed_changed, - mystique_force_redraw, - mystique_config +const device_t millennium_device = { + .name = "Matrox Millennium", + .internal_name = "millennium", + .flags = DEVICE_PCI, + .local = MGA_2064W, + .init = mystique_init, + .close = mystique_close, + .reset = NULL, + { .available = millennium_available }, + .speed_changed = mystique_speed_changed, + .force_redraw = mystique_force_redraw, + .config = mystique_config }; - -const device_t mystique_device = -{ - "Matrox Mystique", - "mystique", - DEVICE_PCI, - MGA_1064SG, - mystique_init, - mystique_close, - NULL, - { mystique_available }, - mystique_speed_changed, - mystique_force_redraw, - mystique_config +const device_t mystique_device = { + .name = "Matrox Mystique", + .internal_name = "mystique", + .flags = DEVICE_PCI, + .local = MGA_1064SG, + .init = mystique_init, + .close = mystique_close, + .reset = NULL, + { .available = mystique_available }, + .speed_changed = mystique_speed_changed, + .force_redraw = mystique_force_redraw, + .config = mystique_config }; - -const device_t mystique_220_device = -{ - "Matrox Mystique 220", - "mystique_220", - DEVICE_PCI, - MGA_1164SG, - mystique_init, - mystique_close, - NULL, - { mystique_220_available }, - mystique_speed_changed, - mystique_force_redraw, - mystique_config +const device_t mystique_220_device = { + .name = "Matrox Mystique 220", + .internal_name = "mystique_220", + .flags = DEVICE_PCI, + .local = MGA_1164SG, + .init = mystique_init, + .close = mystique_close, + .reset = NULL, + { .available = mystique_220_available }, + .speed_changed = mystique_speed_changed, + .force_redraw = mystique_force_redraw, + .config = mystique_config }; diff --git a/src/video/vid_nga.c b/src/video/vid_nga.c index 9037d550a..32c103a8b 100644 --- a/src/video/vid_nga.c +++ b/src/video/vid_nga.c @@ -1,24 +1,24 @@ /* - * 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. + * 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. + * This file is part of the 86Box distribution. * - * Emulation of the NCR NGA (K511, K201) video cards. + * Emulation of the NCR NGA (K511, K201) video cards. * * * - * Authors: Sarah Walker, - * Miran Grca, - * Fred N. van Kempen, - * EngiNerd, + * Authors: Sarah Walker, + * Miran Grca, + * Fred N. van Kempen, + * EngiNerd, * - * Copyright 2008-2019 Sarah Walker. - * Copyright 2016-2019 Miran Grca. - * Copyright 2017-2019 Fred N. van Kempen. - * Copyright 2020 EngiNerd. + * Copyright 2008-2019 Sarah Walker. + * Copyright 2016-2019 Miran Grca. + * Copyright 2017-2019 Fred N. van Kempen. + * Copyright 2020 EngiNerd. */ #include @@ -38,510 +38,509 @@ #include <86box/vid_cga.h> #include <86box/vid_nga.h> #include <86box/vid_cga_comp.h> +#include <86box/plat_unused.h> - - -#define CGA_RGB 0 +#define CGA_RGB 0 #define CGA_COMPOSITE 1 #define COMPOSITE_OLD 0 #define COMPOSITE_NEW 1 - - -static video_timings_t timing_nga = {VIDEO_ISA, 8,16,32, 8,16,32}; +static video_timings_t timing_nga = { .type = VIDEO_ISA, .write_b = 8, .write_w = 16, .write_l = 32, .read_b = 8, .read_w = 16, .read_l = 32 }; void nga_recalctimings(nga_t *nga) { - double _dispontime, _dispofftime, disptime; + double _dispontime; + double _dispofftime; + double disptime; - if ((nga->cga.cgamode & 1) ) { - disptime = nga->cga.crtc[0] + 1; - _dispontime = nga->cga.crtc[1]; + if (nga->cga.cgamode & 1) { + disptime = nga->cga.crtc[0] + 1; + _dispontime = nga->cga.crtc[1]; } else { - disptime = (nga->cga.crtc[0] + 1) << 1; - _dispontime = nga->cga.crtc[1] << 1; + disptime = (nga->cga.crtc[0] + 1) << 1; + _dispontime = nga->cga.crtc[1] << 1; } _dispofftime = disptime - _dispontime; - _dispontime *= CGACONST / 2; + _dispontime *= CGACONST / 2; _dispofftime *= CGACONST / 2; - nga->cga.dispontime = (uint64_t)(_dispontime); - nga->cga.dispofftime = (uint64_t)(_dispofftime); + nga->cga.dispontime = (uint64_t) (_dispontime); + nga->cga.dispofftime = (uint64_t) (_dispofftime); } void nga_out(uint16_t addr, uint8_t val, void *priv) { - nga_t *nga = (nga_t *)priv; - - cga_out(addr, val, &nga->cga); + nga_t *nga = (nga_t *) priv; + cga_out(addr, val, &nga->cga); } uint8_t nga_in(uint16_t addr, void *priv) { - nga_t *nga = (nga_t *)priv; + nga_t *nga = (nga_t *) priv; - return cga_in(addr, &nga->cga); + return cga_in(addr, &nga->cga); } - void -nga_waitstates(void *p) +nga_waitstates(UNUSED(void *priv)) { - int ws_array[16] = {3, 4, 5, 6, 7, 8, 4, 5, 6, 7, 8, 4, 5, 6, 7, 8}; + 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); } - void nga_write(uint32_t addr, uint8_t val, void *priv) { - nga_t *nga = (nga_t *)priv; - int offset; - /* a8000-affff */ - if(!(addr & 0x10000)) - nga->vram_64k[addr & 0x7FFF]=val; - /* b8000-bffff */ - else - nga->cga.vram[addr & 0x7FFF]=val; - - if (nga->cga.snow_enabled) { - /* recreate snow effect */ - offset = ((timer_get_remaining_u64(&nga->cga.timer) / CGACONST) * 4) & 0xfc; - nga->cga.charbuffer[offset] = nga->cga.vram[addr & 0x7fff]; - nga->cga.charbuffer[offset | 1] = nga->cga.vram[addr & 0x7fff]; - } - nga_waitstates(&nga->cga); + nga_t *nga = (nga_t *) priv; + int offset; + /* a8000-affff */ + if (!(addr & 0x10000)) + nga->vram_64k[addr & 0x7FFF] = val; + /* b8000-bffff */ + else + nga->cga.vram[addr & 0x7FFF] = val; + + if (nga->cga.snow_enabled) { + /* recreate snow effect */ + offset = ((timer_get_remaining_u64(&nga->cga.timer) / CGACONST) * 4) & 0xfc; + nga->cga.charbuffer[offset] = nga->cga.vram[addr & 0x7fff]; + nga->cga.charbuffer[offset | 1] = nga->cga.vram[addr & 0x7fff]; + } + nga_waitstates(&nga->cga); } uint8_t nga_read(uint32_t addr, void *priv) { - - nga_t *nga = (nga_t *)priv; - int offset; - uint8_t ret; - /* a8000-affff */ - if(!(addr & 0x10000)) - ret = nga->vram_64k[addr & 0x7FFF]; - else - ret = nga->cga.vram[addr & 0x7FFF]; - nga_waitstates(&nga->cga); + nga_t *nga = (nga_t *) priv; + int offset; + uint8_t ret; + /* a8000-affff */ + if (!(addr & 0x10000)) + ret = nga->vram_64k[addr & 0x7FFF]; + else + ret = nga->cga.vram[addr & 0x7FFF]; - if (nga->cga.snow_enabled) { - /* recreate snow effect */ - offset = ((timer_get_remaining_u64(&nga->cga.timer) / CGACONST) * 4) & 0xfc; - nga->cga.charbuffer[offset] = nga->cga.vram[addr & 0x7fff]; - nga->cga.charbuffer[offset | 1] = nga->cga.vram[addr & 0x7fff]; - } - - return(ret); + nga_waitstates(&nga->cga); + + if (nga->cga.snow_enabled) { + /* recreate snow effect */ + offset = ((timer_get_remaining_u64(&nga->cga.timer) / CGACONST) * 4) & 0xfc; + nga->cga.charbuffer[offset] = nga->cga.vram[addr & 0x7fff]; + nga->cga.charbuffer[offset | 1] = nga->cga.vram[addr & 0x7fff]; + } + + return ret; } void nga_poll(void *priv) { - nga_t *nga = (nga_t *)priv; - /* set cursor position in memory */ + nga_t *nga = (nga_t *) priv; + /* set cursor position in memory */ uint16_t ca = (nga->cga.crtc[15] | (nga->cga.crtc[14] << 8)) & 0x3fff; - int drawcursor; - int x, c, xs_temp, ys_temp; - int oldvc; - uint8_t chr, attr; - uint16_t dat, dat2; - int cols[4]; - int col; - int oldsc; - - /* graphic mode and not high-res modes */ - if ((nga->cga.cgamode & 2) && !(nga->cga.cgamode & 0x40)) { - /* standard cga mode */ - cga_poll(&nga->cga); - return; - } else { - /* high-res or text mode */ - if (!nga->cga.linepos) { - timer_advance_u64(&nga->cga.timer, nga->cga.dispofftime); - nga->cga.cgastat |= 1; - nga->cga.linepos = 1; - oldsc = nga->cga.sc; - /* if interlaced */ - if ((nga->cga.crtc[8] & 3) == 3) - nga->cga.sc = ((nga->cga.sc << 1) + nga->cga.oddeven) & 7; - if (nga->cga.cgadispon) { - if (nga->cga.displine < nga->cga.firstline) { - nga->cga.firstline = nga->cga.displine; - video_wait_for_buffer(); - } - nga->cga.lastline = nga->cga.displine; - /* 80-col */ - if ((nga->cga.cgamode & 1) && !(nga->cga.cgamode & 2)) { - /* for each text column */ - for (x = 0; x < nga->cga.crtc[1]; x++) { - /* video output enabled */ - if (nga->cga.cgamode & 8) { - /* character */ - chr = nga->cga.charbuffer[x << 1]; - /* text attributes */ - attr = nga->cga.charbuffer[(x << 1) + 1]; - } else - chr = attr = 0; - /* check if cursor has to be drawn */ - drawcursor = ((nga->cga.ma == ca) && nga->cga.con && nga->cga.cursoron); - /* set foreground */ - cols[1] = (attr & 15) + 16; - /* blink active */ - if (nga->cga.cgamode & 0x20) { - cols[0] = ((attr >> 4) & 7) + 16; - /* attribute 7 active and not cursor */ - if ((nga->cga.cgablink & 8) && (attr & 0x80) && !nga->cga.drawcursor) { - /* set blinking */ - cols[1] = cols[0]; - } - } else { - /* Set intensity bit */ - cols[0] = (attr >> 4) + 16; - } - if (drawcursor) { - for (c = 0; c < 8; c++) - buffer32->line[nga->cga.displine][(x << 3) + c + 8] = cols[(fontdatm[chr][((nga->cga.sc & 7) << 1) | nga->lineff] & (1 << (c ^ 7))) ? 1 : 0] ^ 15; - } else { - for (c = 0; c < 8; c++) - buffer32->line[nga->cga.displine][(x << 3) + c + 8] = cols[(fontdatm[chr][((nga->cga.sc & 7) << 1) | nga->lineff] & (1 << (c ^ 7))) ? 1 : 0]; - } - - nga->cga.ma++; - } - } - /* 40-col */ - else if (!(nga->cga.cgamode & 2)) { - /* for each text column */ - for (x = 0; x < nga->cga.crtc[1]; x++) { - if (nga->cga.cgamode & 8) { - chr = nga->cga.vram[((nga->cga.ma << 1) & 0x3fff) + nga->base]; - attr = nga->cga.vram[(((nga->cga.ma << 1) + 1) & 0x3fff) + nga->base]; - } else { - chr = attr = 0; - } - drawcursor = ((nga->cga.ma == ca) && nga->cga.con && nga->cga.cursoron); - /* set foreground */ - cols[1] = (attr & 15) + 16; - /* blink active */ - if (nga->cga.cgamode & 0x20) { - cols[0] = ((attr >> 4) & 7) + 16; - if ((nga->cga.cgablink & 8) && (attr & 0x80) && !nga->cga.drawcursor) { - /* set blinking */ - cols[1] = cols[0]; - } - } else { - /* Set intensity bit */ - cols[0] = (attr >> 4) + 16; - } + int drawcursor; + int x; + int c; + int xs_temp; + int ys_temp; + int oldvc; + uint8_t chr; + uint8_t attr; + uint16_t dat; + uint16_t dat2; + int cols[4]; + int col; + int oldsc; - if (drawcursor) { - for (c = 0; c < 8; c++) - buffer32->line[nga->cga.displine][(x << 4) + (c << 1) + 8] = - buffer32->line[nga->cga.displine][(x << 4) + (c << 1) + 1 + 8] = cols[(fontdatm[chr][((nga->cga.sc & 7) << 1) | nga->lineff] & (1 << (c ^ 7))) ? 1 : 0] ^ 15; - } else { - for (c = 0; c < 8; c++) - buffer32->line[nga->cga.displine][(x << 4) + (c << 1) + 8] = - buffer32->line[nga->cga.displine][(x << 4) + (c << 1) + 1 + 8] = cols[(fontdatm[chr][((nga->cga.sc & 7) << 1) | nga->lineff] & (1 << (c ^ 7))) ? 1 : 0]; - } - - nga->cga.ma++; - - } - } else { - /* high res modes */ - if (nga->cga.cgamode & 0x40) { - /* 640x400x2 mode */ - if (nga->cga.cgamode & 0x4 || nga->cga.cgamode & 0x10) { - /* - * Scanlines are read in the following order: - * 0b8000-0b9f3f even scans (0,4,...) - * 0ba000-0bbf3f odd scans (2,6,...) - * 0bc000-0bdf3f even scans (1,5,...) - * 0be000-0bff3f odd scans (3,7,...) - */ - dat2 = ((nga->cga.sc & 1) * 0x2000) | (nga->lineff * 0x4000); - cols[0] = 0; cols[1] = 15 + 16; - /* 640x400x4 mode */ - } else { - cols[0] = (nga->cga.cgacol & 15) | 16; - col = (nga->cga.cgacol & 16) ? 24 : 16; - if (nga->cga.cgamode & 4) { - cols[1] = col | 3; /* Cyan */ - cols[2] = col | 4; /* Red */ - cols[3] = col | 7; /* White */ - } else if (nga->cga.cgacol & 32) { - cols[1] = col | 3; /* Cyan */ - cols[2] = col | 5; /* Magenta */ - cols[3] = col | 7; /* White */ - } else { - cols[1] = col | 2; /* Green */ - cols[2] = col | 4; /* Red */ - cols[3] = col | 6; /* Yellow */ - } - /* - * Scanlines are read in the following order: - * 0b8000-0bbf3f even scans (0,4,...) - * 0bc000-0bff3f odd scans (1,5,...) - * 0a8000-0abf3f even scans (2,6,...) - * 0ac000-0aff3f odd scans (3,7,...) - */ - dat2 = (nga->cga.sc & 1) * 0x4000; - } - } - else { - dat2 = (nga->cga.sc & 1) * 0x2000; - cols[0] = 0; cols[1] = (nga->cga.cgacol & 15) + 16; - } - - /* for each text column */ - for (x = 0; x < nga->cga.crtc[1]; x++) { - /* video out */ - if (nga->cga.cgamode & 8) { - /* 640x400x2 */ - if (nga->cga.cgamode & 0x4 || nga->cga.cgamode & 0x10) { - /* read two bytes at a time */ - dat = (nga->cga.vram[((nga->cga.ma << 1) & 0x1fff) + dat2] << 8) | nga->cga.vram[((nga->cga.ma << 1) & 0x1fff) + dat2 + 1]; - /* each pixel is represented by one bit, so draw 16 pixels at a time */ - /* crtc[1] is 40 column, so 40x16=640 pixels */ - for (c = 0; c < 16; c++) { - buffer32->line[nga->cga.displine][(x << 4) + c + 8] = cols[dat >> 15]; - dat <<= 1; - } - /* 640x400x4 */ - } else { - /* lines 2,3,6,7,etc. */ - if (nga->cga.sc & 2) - /* read two bytes at a time */ - dat = (nga->vram_64k[((nga->cga.ma << 1) & 0x7fff) + dat2] << 8) | nga->vram_64k[((nga->cga.ma << 1) & 0x7fff) + dat2 + 1]; - /* lines 0,1,4,5,etc. */ - else - /* read two bytes at a time */ - dat = (nga->cga.vram[((nga->cga.ma << 1) & 0x7fff) + dat2] << 8) | nga->cga.vram[((nga->cga.ma << 1) & 0x7fff) + dat2 + 1]; - /* each pixel is represented by two bits, so draw 8 pixels at a time */ - /* crtc[1] is 80 column, so 80x8=640 pixels */ - for (c = 0; c < 8; c++) { - buffer32->line[nga->cga.displine][(x << 3) + c + 8] = cols[dat >> 14]; - dat <<= 2; - } - } - } else { - dat = 0; - } - nga->cga.ma++; - } - } - } else { - - /* nga specific */ - cols[0] = ((nga->cga.cgamode & 0x12) == 0x12) ? 0 : (nga->cga.cgacol & 15) + 16; - /* 80-col */ - if ((nga->cga.cgamode & 1) ) { - hline(buffer32, 0, (nga->cga.displine << 1), ((nga->cga.crtc[1] << 3) + 16) << 2, cols[0]); - hline(buffer32, 0, (nga->cga.displine << 1) + 1, ((nga->cga.crtc[1] << 3) + 16) << 2, cols[0]); - } else { - hline(buffer32, 0, (nga->cga.displine << 1), ((nga->cga.crtc[1] << 4) + 16) << 2, cols[0]); - hline(buffer32, 0, (nga->cga.displine << 1) + 1, ((nga->cga.crtc[1] << 4) + 16) << 2, cols[0]); - } - - } + /* graphic mode and not high-res modes */ + if ((nga->cga.cgamode & 2) && !(nga->cga.cgamode & 0x40)) { + /* standard cga mode */ + cga_poll(&nga->cga); + return; + } else { + /* high-res or text mode */ + if (!nga->cga.linepos) { + timer_advance_u64(&nga->cga.timer, nga->cga.dispofftime); + nga->cga.cgastat |= 1; + nga->cga.linepos = 1; + oldsc = nga->cga.sc; + /* if interlaced */ + if ((nga->cga.crtc[8] & 3) == 3) + nga->cga.sc = ((nga->cga.sc << 1) + nga->cga.oddeven) & 7; + if (nga->cga.cgadispon) { + if (nga->cga.displine < nga->cga.firstline) { + nga->cga.firstline = nga->cga.displine; + video_wait_for_buffer(); + } + nga->cga.lastline = nga->cga.displine; + /* 80-col */ + if ((nga->cga.cgamode & 1) && !(nga->cga.cgamode & 2)) { + /* for each text column */ + for (x = 0; x < nga->cga.crtc[1]; x++) { + /* video output enabled */ + if (nga->cga.cgamode & 8) { + /* character */ + chr = nga->cga.charbuffer[x << 1]; + /* text attributes */ + attr = nga->cga.charbuffer[(x << 1) + 1]; + } else + chr = attr = 0; + /* check if cursor has to be drawn */ + drawcursor = ((nga->cga.ma == ca) && nga->cga.con && nga->cga.cursoron); + /* set foreground */ + cols[1] = (attr & 15) + 16; + /* blink active */ + if (nga->cga.cgamode & 0x20) { + cols[0] = ((attr >> 4) & 7) + 16; + /* attribute 7 active and not cursor */ + if ((nga->cga.cgablink & 8) && (attr & 0x80) && !nga->cga.drawcursor) { + /* set blinking */ + cols[1] = cols[0]; + } + } else { + /* Set intensity bit */ + cols[0] = (attr >> 4) + 16; + } + if (drawcursor) { + for (c = 0; c < 8; c++) + buffer32->line[nga->cga.displine][(x << 3) + c + 8] = cols[(fontdatm[chr][((nga->cga.sc & 7) << 1) | nga->lineff] & (1 << (c ^ 7))) ? 1 : 0] ^ 15; + } else { + for (c = 0; c < 8; c++) + buffer32->line[nga->cga.displine][(x << 3) + c + 8] = cols[(fontdatm[chr][((nga->cga.sc & 7) << 1) | nga->lineff] & (1 << (c ^ 7))) ? 1 : 0]; + } - nga->cga.sc = oldsc; - /* vertical sync */ - if (nga->cga.vc == nga->cga.crtc[7] && !nga->cga.sc) - nga->cga.cgastat |= 8; - nga->cga.displine++; - if (nga->cga.displine >= 720) - nga->cga.displine = 0; - } else { - timer_advance_u64(&nga->cga.timer, nga->cga.dispontime); - if (nga->cga.cgadispon) nga->cga.cgastat &= ~1; - nga->cga.linepos = 0; - /* nga specific */ - nga->lineff ^= 1; - - /* text mode or 640x400x2 */ - if (nga->lineff && !((nga->cga.cgamode & 1) && (nga->cga.cgamode & 0x40))) { - nga->cga.ma = nga->cga.maback; - /* 640x400x4 */ - } else { - if (nga->cga.vsynctime) { - nga->cga.vsynctime--; - if (!nga->cga.vsynctime) - nga->cga.cgastat &= ~8; - } - /* cursor stop scanline */ - if (nga->cga.sc == (nga->cga.crtc[11] & 31) || ((nga->cga.crtc[8] & 3) == 3 && nga->cga.sc == ((nga->cga.crtc[11] & 31) >> 1))) { - nga->cga.con = 0; - nga->cga.coff = 1; - } - /* interlaced and max scanline per char reached */ - if ((nga->cga.crtc[8] & 3) == 3 && nga->cga.sc == (nga->cga.crtc[9] >> 1)) - nga->cga.maback = nga->cga.ma; - - if (nga->cga.vadj) { - nga->cga.sc++; - nga->cga.sc &= 31; - nga->cga.ma = nga->cga.maback; - nga->cga.vadj--; - if (!nga->cga.vadj) { - nga->cga.cgadispon = 1; - /* change start of displayed page (crtc 12-13) */ - nga->cga.ma = nga->cga.maback = (nga->cga.crtc[13] | (nga->cga.crtc[12] << 8)) & 0x7fff; - nga->cga.sc = 0; - } - /* nga specific */ - /* end of character line reached */ - } else if (nga->cga.sc == nga->cga.crtc[9] || ((nga->cga.crtc[8] & 3) == 3 && nga->cga.sc == (nga->cga.crtc[9] >> 1))) { - nga->cga.maback = nga->cga.ma; - nga->cga.sc = 0; - oldvc = nga->cga.vc; - nga->cga.vc++; - nga->cga.vc &= 127; + nga->cga.ma++; + } + } + /* 40-col */ + else if (!(nga->cga.cgamode & 2)) { + /* for each text column */ + for (x = 0; x < nga->cga.crtc[1]; x++) { + if (nga->cga.cgamode & 8) { + chr = nga->cga.vram[((nga->cga.ma << 1) & 0x3fff) + nga->base]; + attr = nga->cga.vram[(((nga->cga.ma << 1) + 1) & 0x3fff) + nga->base]; + } else { + chr = attr = 0; + } + drawcursor = ((nga->cga.ma == ca) && nga->cga.con && nga->cga.cursoron); + /* set foreground */ + cols[1] = (attr & 15) + 16; + /* blink active */ + if (nga->cga.cgamode & 0x20) { + cols[0] = ((attr >> 4) & 7) + 16; + if ((nga->cga.cgablink & 8) && (attr & 0x80) && !nga->cga.drawcursor) { + /* set blinking */ + cols[1] = cols[0]; + } + } else { + /* Set intensity bit */ + cols[0] = (attr >> 4) + 16; + } - /* lines of character displayed */ - if (nga->cga.vc == nga->cga.crtc[6]) - nga->cga.cgadispon=0; + if (drawcursor) { + for (c = 0; c < 8; c++) + buffer32->line[nga->cga.displine][(x << 4) + (c << 1) + 8] = buffer32->line[nga->cga.displine][(x << 4) + (c << 1) + 1 + 8] = cols[(fontdatm[chr][((nga->cga.sc & 7) << 1) | nga->lineff] & (1 << (c ^ 7))) ? 1 : 0] ^ 15; + } else { + for (c = 0; c < 8; c++) + buffer32->line[nga->cga.displine][(x << 4) + (c << 1) + 8] = buffer32->line[nga->cga.displine][(x << 4) + (c << 1) + 1 + 8] = cols[(fontdatm[chr][((nga->cga.sc & 7) << 1) | nga->lineff] & (1 << (c ^ 7))) ? 1 : 0]; + } - /* total vertical lines */ - if (oldvc == nga->cga.crtc[4]) { - nga->cga.vc = 0; - /* adjust vertical lines */ - nga->cga.vadj = nga->cga.crtc[5]; - if (!nga->cga.vadj) { - nga->cga.cgadispon = 1; - /* change start of displayed page (crtc 12-13) */ - nga->cga.ma = nga->cga.maback = (nga->cga.crtc[13] | (nga->cga.crtc[12] << 8)) & 0x7fff; - } - /* cursor start */ - switch (nga->cga.crtc[10] & 0x60) { - case 0x20: - nga->cga.cursoron = 0; - break; - case 0x60: - nga->cga.cursoron = nga->cga.cgablink & 0x10; - break; - default: - nga->cga.cursoron = nga->cga.cgablink & 0x08; - break; - } - } - /* vertical line position */ - if (nga->cga.vc == nga->cga.crtc[7]) { - nga->cga.cgadispon = 0; - nga->cga.displine = 0; - /* nga specific */ - nga->cga.vsynctime = 16; - /* vsync pos */ - if (nga->cga.crtc[7]) { - if ((nga->cga.cgamode & 1)) - /* set screen width */ - x = (nga->cga.crtc[1] << 3) + 16; - else - x = (nga->cga.crtc[1] << 4) + 16; - nga->cga.lastline++; + nga->cga.ma++; + } + } else { + /* high res modes */ + if (nga->cga.cgamode & 0x40) { + /* 640x400x2 mode */ + if (nga->cga.cgamode & 0x4 || nga->cga.cgamode & 0x10) { + /* + * Scanlines are read in the following order: + * 0b8000-0b9f3f even scans (0,4,...) + * 0ba000-0bbf3f odd scans (2,6,...) + * 0bc000-0bdf3f even scans (1,5,...) + * 0be000-0bff3f odd scans (3,7,...) + */ + dat2 = ((nga->cga.sc & 1) * 0x2000) | (nga->lineff * 0x4000); + cols[0] = 0; + cols[1] = 15 + 16; + /* 640x400x4 mode */ + } else { + cols[0] = (nga->cga.cgacol & 15) | 16; + col = (nga->cga.cgacol & 16) ? 24 : 16; + if (nga->cga.cgamode & 4) { + cols[1] = col | 3; /* Cyan */ + cols[2] = col | 4; /* Red */ + cols[3] = col | 7; /* White */ + } else if (nga->cga.cgacol & 32) { + cols[1] = col | 3; /* Cyan */ + cols[2] = col | 5; /* Magenta */ + cols[3] = col | 7; /* White */ + } else { + cols[1] = col | 2; /* Green */ + cols[2] = col | 4; /* Red */ + cols[3] = col | 6; /* Yellow */ + } + /* + * Scanlines are read in the following order: + * 0b8000-0bbf3f even scans (0,4,...) + * 0bc000-0bff3f odd scans (1,5,...) + * 0a8000-0abf3f even scans (2,6,...) + * 0ac000-0aff3f odd scans (3,7,...) + */ + dat2 = (nga->cga.sc & 1) * 0x4000; + } + } else { + dat2 = (nga->cga.sc & 1) * 0x2000; + cols[0] = 0; + cols[1] = (nga->cga.cgacol & 15) + 16; + } - xs_temp = x; - ys_temp = (nga->cga.lastline - nga->cga.firstline); + /* for each text column */ + for (x = 0; x < nga->cga.crtc[1]; x++) { + /* video out */ + if (nga->cga.cgamode & 8) { + /* 640x400x2 */ + if (nga->cga.cgamode & 0x4 || nga->cga.cgamode & 0x10) { + /* read two bytes at a time */ + dat = (nga->cga.vram[((nga->cga.ma << 1) & 0x1fff) + dat2] << 8) | nga->cga.vram[((nga->cga.ma << 1) & 0x1fff) + dat2 + 1]; + /* each pixel is represented by one bit, so draw 16 pixels at a time */ + /* crtc[1] is 40 column, so 40x16=640 pixels */ + for (c = 0; c < 16; c++) { + buffer32->line[nga->cga.displine][(x << 4) + c + 8] = cols[dat >> 15]; + dat <<= 1; + } + /* 640x400x4 */ + } else { + /* lines 2,3,6,7,etc. */ + if (nga->cga.sc & 2) + /* read two bytes at a time */ + dat = (nga->vram_64k[((nga->cga.ma << 1) & 0x7fff) + dat2] << 8) | nga->vram_64k[((nga->cga.ma << 1) & 0x7fff) + dat2 + 1]; + /* lines 0,1,4,5,etc. */ + else + /* read two bytes at a time */ + dat = (nga->cga.vram[((nga->cga.ma << 1) & 0x7fff) + dat2] << 8) | nga->cga.vram[((nga->cga.ma << 1) & 0x7fff) + dat2 + 1]; + /* each pixel is represented by two bits, so draw 8 pixels at a time */ + /* crtc[1] is 80 column, so 80x8=640 pixels */ + for (c = 0; c < 8; c++) { + buffer32->line[nga->cga.displine][(x << 3) + c + 8] = cols[dat >> 14]; + dat <<= 2; + } + } + } else { + dat = 0; + } + nga->cga.ma++; + } + } + } else { - if ((xs_temp > 0) && (ys_temp > 0)) { - if (xsize < 64) xs_temp = 656; - /* nga specific */ - if (ysize < 32) ys_temp = 400; - if (!enable_overscan) - xs_temp -= 16; + /* nga specific */ + cols[0] = ((nga->cga.cgamode & 0x12) == 0x12) ? 0 : (nga->cga.cgacol & 15) + 16; + /* 80-col */ + if (nga->cga.cgamode & 1) { + hline(buffer32, 0, (nga->cga.displine << 1), ((nga->cga.crtc[1] << 3) + 16) << 2, cols[0]); + hline(buffer32, 0, (nga->cga.displine << 1) + 1, ((nga->cga.crtc[1] << 3) + 16) << 2, cols[0]); + } else { + hline(buffer32, 0, (nga->cga.displine << 1), ((nga->cga.crtc[1] << 4) + 16) << 2, cols[0]); + hline(buffer32, 0, (nga->cga.displine << 1) + 1, ((nga->cga.crtc[1] << 4) + 16) << 2, cols[0]); + } + } - - if ((nga->cga.cgamode & 8) && ((xs_temp != xsize) || (ys_temp != ysize) || video_force_resize_get())) { - xsize = xs_temp; - ysize = ys_temp; - set_screen_size(xsize, ysize + (enable_overscan ? 16 : 0)); + if (nga->cga.cgamode & 1) + /* set screen width */ + x = (nga->cga.crtc[1] << 3) + 16; + else + x = (nga->cga.crtc[1] << 4) + 16; - if (video_force_resize_get()) - video_force_resize_set(0); - } - /* nga specific */ - if (enable_overscan) { - if (nga->cga.composite) - video_blit_memtoscreen(0, (nga->cga.firstline - 8), - xsize, (nga->cga.lastline - nga->cga.firstline) + 16); - else - video_blit_memtoscreen_8(0, (nga->cga.firstline - 8), - xsize, (nga->cga.lastline - nga->cga.firstline) + 16); - } else { - if (nga->cga.composite) - video_blit_memtoscreen(8, nga->cga.firstline, - xsize, (nga->cga.lastline - nga->cga.firstline)); - else - video_blit_memtoscreen_8(8, nga->cga.firstline, - xsize, (nga->cga.lastline - nga->cga.firstline)); - } - } - frames++; + video_process_8(x, nga->cga.displine); - video_res_x = xsize; - video_res_y = ysize; - /* 80-col */ - if ((nga->cga.cgamode & 1) && !(nga->cga.cgamode & 0x40)) { - video_res_x /= 8; - video_res_y /= (nga->cga.crtc[9] + 1) * 2; - video_bpp = 0; - /* 40-col */ - } else if (!(nga->cga.cgamode & 2)) { - video_res_x /= 16; - video_res_y /= (nga->cga.crtc[9] + 1) * 2; - video_bpp = 0; - } - else if (nga->cga.cgamode & 0x40) { - video_res_x /= 8; - video_res_y /= 2; - video_bpp = 1; - } - } - nga->cga.firstline = 1000; - nga->cga.lastline = 0; - nga->cga.cgablink++; - nga->cga.oddeven ^= 1; - } - } else { - nga->cga.sc++; - nga->cga.sc &= 31; - nga->cga.ma = nga->cga.maback; - } + nga->cga.sc = oldsc; + /* vertical sync */ + if (nga->cga.vc == nga->cga.crtc[7] && !nga->cga.sc) + nga->cga.cgastat |= 8; + nga->cga.displine++; + if (nga->cga.displine >= 720) + nga->cga.displine = 0; + } else { + timer_advance_u64(&nga->cga.timer, nga->cga.dispontime); + if (nga->cga.cgadispon) + nga->cga.cgastat &= ~1; + nga->cga.linepos = 0; + /* nga specific */ + nga->lineff ^= 1; - if (nga->cga.cgadispon) - nga->cga.cgastat &= ~1; - - /* enable cursor if its scanline was reached */ - if ((nga->cga.sc == (nga->cga.crtc[10] & 31) || ((nga->cga.crtc[8] & 3) == 3 && nga->cga.sc == ((nga->cga.crtc[10] & 31) >> 1)))) - nga->cga.con = 1; - } - /* 80-columns */ - if (nga->cga.cgadispon && (nga->cga.cgamode & 1) ) { - /* for each character per line */ - for (x = 0; x < (nga->cga.crtc[1] << 1); x++) - nga->cga.charbuffer[x] = nga->cga.vram[(((nga->cga.ma << 1) + x) & 0x3fff) + nga->base]; - } - } - } + /* text mode or 640x400x2 */ + if (nga->lineff && !((nga->cga.cgamode & 1) && (nga->cga.cgamode & 0x40))) { + nga->cga.ma = nga->cga.maback; + /* 640x400x4 */ + } else { + if (nga->cga.vsynctime) { + nga->cga.vsynctime--; + if (!nga->cga.vsynctime) + nga->cga.cgastat &= ~8; + } + /* cursor stop scanline */ + if (nga->cga.sc == (nga->cga.crtc[11] & 31) || ((nga->cga.crtc[8] & 3) == 3 && nga->cga.sc == ((nga->cga.crtc[11] & 31) >> 1))) { + nga->cga.con = 0; + nga->cga.coff = 1; + } + /* interlaced and max scanline per char reached */ + if ((nga->cga.crtc[8] & 3) == 3 && nga->cga.sc == (nga->cga.crtc[9] >> 1)) + nga->cga.maback = nga->cga.ma; + + if (nga->cga.vadj) { + nga->cga.sc++; + nga->cga.sc &= 31; + nga->cga.ma = nga->cga.maback; + nga->cga.vadj--; + if (!nga->cga.vadj) { + nga->cga.cgadispon = 1; + /* change start of displayed page (crtc 12-13) */ + nga->cga.ma = nga->cga.maback = (nga->cga.crtc[13] | (nga->cga.crtc[12] << 8)) & 0x7fff; + nga->cga.sc = 0; + } + /* nga specific */ + /* end of character line reached */ + } else if (nga->cga.sc == nga->cga.crtc[9] || ((nga->cga.crtc[8] & 3) == 3 && nga->cga.sc == (nga->cga.crtc[9] >> 1))) { + nga->cga.maback = nga->cga.ma; + nga->cga.sc = 0; + oldvc = nga->cga.vc; + nga->cga.vc++; + nga->cga.vc &= 127; + + /* lines of character displayed */ + if (nga->cga.vc == nga->cga.crtc[6]) + nga->cga.cgadispon = 0; + + /* total vertical lines */ + if (oldvc == nga->cga.crtc[4]) { + nga->cga.vc = 0; + /* adjust vertical lines */ + nga->cga.vadj = nga->cga.crtc[5]; + if (!nga->cga.vadj) { + nga->cga.cgadispon = 1; + /* change start of displayed page (crtc 12-13) */ + nga->cga.ma = nga->cga.maback = (nga->cga.crtc[13] | (nga->cga.crtc[12] << 8)) & 0x7fff; + } + /* cursor start */ + switch (nga->cga.crtc[10] & 0x60) { + case 0x20: + nga->cga.cursoron = 0; + break; + case 0x60: + nga->cga.cursoron = nga->cga.cgablink & 0x10; + break; + default: + nga->cga.cursoron = nga->cga.cgablink & 0x08; + break; + } + } + /* vertical line position */ + if (nga->cga.vc == nga->cga.crtc[7]) { + nga->cga.cgadispon = 0; + nga->cga.displine = 0; + /* nga specific */ + nga->cga.vsynctime = 16; + /* vsync pos */ + if (nga->cga.crtc[7]) { + if (nga->cga.cgamode & 1) + /* set screen width */ + x = (nga->cga.crtc[1] << 3) + 16; + else + x = (nga->cga.crtc[1] << 4) + 16; + nga->cga.lastline++; + + xs_temp = x; + ys_temp = (nga->cga.lastline - nga->cga.firstline); + + if ((xs_temp > 0) && (ys_temp > 0)) { + if (xsize < 64) + xs_temp = 656; + /* nga specific */ + if (ysize < 32) + ys_temp = 400; + if (!enable_overscan) + xs_temp -= 16; + + if ((nga->cga.cgamode & 8) && ((xs_temp != xsize) || (ys_temp != ysize) || video_force_resize_get())) { + xsize = xs_temp; + ysize = ys_temp; + set_screen_size(xsize, ysize + (enable_overscan ? 16 : 0)); + + if (video_force_resize_get()) + video_force_resize_set(0); + } + /* nga specific */ + if (enable_overscan) { + video_blit_memtoscreen(0, (nga->cga.firstline - 8), + xsize, (nga->cga.lastline - nga->cga.firstline) + 16); + } else { + video_blit_memtoscreen(8, nga->cga.firstline, + xsize, (nga->cga.lastline - nga->cga.firstline)); + } + } + frames++; + + video_res_x = xsize; + video_res_y = ysize; + /* 80-col */ + if ((nga->cga.cgamode & 1) && !(nga->cga.cgamode & 0x40)) { + video_res_x /= 8; + video_res_y /= (nga->cga.crtc[9] + 1) * 2; + video_bpp = 0; + /* 40-col */ + } else if (!(nga->cga.cgamode & 2)) { + video_res_x /= 16; + video_res_y /= (nga->cga.crtc[9] + 1) * 2; + video_bpp = 0; + } else if (nga->cga.cgamode & 0x40) { + video_res_x /= 8; + video_res_y /= 2; + video_bpp = 1; + } + } + nga->cga.firstline = 1000; + nga->cga.lastline = 0; + nga->cga.cgablink++; + nga->cga.oddeven ^= 1; + } + } else { + nga->cga.sc++; + nga->cga.sc &= 31; + nga->cga.ma = nga->cga.maback; + } + + if (nga->cga.cgadispon) + nga->cga.cgastat &= ~1; + + /* enable cursor if its scanline was reached */ + if (nga->cga.sc == (nga->cga.crtc[10] & 31) || ((nga->cga.crtc[8] & 3) == 3 && nga->cga.sc == ((nga->cga.crtc[10] & 31) >> 1))) + nga->cga.con = 1; + } + /* 80-columns */ + if (nga->cga.cgadispon && (nga->cga.cgamode & 1)) { + /* for each character per line */ + for (x = 0; x < (nga->cga.crtc[1] << 1); x++) + nga->cga.charbuffer[x] = nga->cga.vram[(((nga->cga.ma << 1) + x) & 0x3fff) + nga->base]; + } + } + } } void nga_close(void *priv) { - nga_t *nga = (nga_t *)priv; - free(nga->vram_64k); + nga_t *nga = (nga_t *) priv; + free(nga->vram_64k); free(nga->cga.vram); free(nga); } @@ -549,134 +548,156 @@ nga_close(void *priv) void nga_speed_changed(void *priv) { - nga_t *nga = (nga_t *)priv; + nga_t *nga = (nga_t *) priv; nga_recalctimings(nga); } void * -nga_init(const device_t *info) +nga_init(UNUSED(const device_t *info)) { - int mem; - uint8_t charset; - nga_t *nga = (nga_t *)malloc(sizeof(nga_t)); + int mem; + uint8_t charset; + nga_t *nga = (nga_t *) malloc(sizeof(nga_t)); memset(nga, 0x00, sizeof(nga_t)); video_inform(VIDEO_FLAG_TYPE_CGA, &timing_nga); charset = device_get_config_int("charset"); - loadfont_ex("roms/video/nga/ncr_nga_35122.bin", 1, 4096 * charset); - - nga->cga.composite = 0; + loadfont_ex("roms/video/nga/ncr_nga_35122.bin", 1, 4096 * charset); + + nga->cga.composite = 0; nga->cga.snow_enabled = device_get_config_int("snow_enabled"); - - nga->cga.vram = malloc(0x8000); - nga->vram_64k = malloc(0x8000); - timer_add(&nga->cga.timer, nga_poll, nga, 1); + nga->cga.vram = malloc(0x8000); + nga->vram_64k = malloc(0x8000); + + timer_add(&nga->cga.timer, nga_poll, nga, 1); mem_mapping_add(&nga->cga.mapping, 0xb8000, 0x8000, - nga_read, NULL, NULL, - nga_write, NULL, NULL, NULL, 0, nga); - - mem = device_get_config_int("memory"); + nga_read, NULL, NULL, + nga_write, NULL, NULL, NULL, 0, nga); - if (mem > 32) { - /* make optional 32KB addessable */ - mem_mapping_add(&nga->mapping_64k, 0xa8000, 0x8000, - nga_read, NULL, NULL, - nga_write, NULL, NULL, NULL, 0, nga); - } + mem = device_get_config_int("memory"); + + if (mem > 32) { + /* make optional 32KB addessable */ + mem_mapping_add(&nga->mapping_64k, 0xa8000, 0x8000, + nga_read, NULL, NULL, + nga_write, NULL, NULL, NULL, 0, nga); + } + + io_sethandler(0x03d0, 16, nga_in, NULL, NULL, nga_out, NULL, NULL, nga); - io_sethandler(0x03d0, 16, nga_in, NULL, NULL, nga_out, NULL, NULL, nga); - overscan_x = overscan_y = 16; - nga->cga.rgb_type = device_get_config_int("rgb_type"); - cga_palette = (nga->cga.rgb_type << 1); + nga->cga.rgb_type = device_get_config_int("rgb_type"); + cga_palette = (nga->cga.rgb_type << 1); cgapal_rebuild(); - + return nga; } - -const device_config_t nga_config[] = -{ - { - "rgb_type", "RGB type", CONFIG_SELECTION, "", 0, "", { 0 }, - { - { - "Color", 0 - }, - { - "Green Monochrome", 1 - }, - { - "Amber Monochrome", 2 - }, - { - "Gray Monochrome", 3 - }, - { - "Color (no brown)", 4 - }, - { - "" - } - } - }, - { - "snow_enabled", "Snow emulation", CONFIG_BINARY, "", 1 - }, - { - "memory", "Memory size", CONFIG_SELECTION, "", 64, "", { 0 }, - { - { - "32 KB", 32 - }, - { - "64 KB", 64 - }, - { - "" - } - } - }, - { - "charset", "Character set", CONFIG_SELECTION, "", 0, "", { 0 }, - { - { - "U.S. English", 0 - }, - { - "Scandinavian", 1 - }, - { - "Other languages", 2 - }, - { - "E.F. Hutton", 3 - }, - { - "" - } - } - }, - { - "", "", -1 +const device_config_t nga_config[] = { + // clang-format off + { + .name = "rgb_type", + .description = "RGB type", + .type = CONFIG_SELECTION, + .default_int = 0, + .selection = { + { + .description = "Color", + .value = 0 + }, + { + .description = "Green Monochrome", + .value = 1 + }, + { + .description = "Amber Monochrome", + .value = 2 + }, + { + .description = "Gray Monochrome", + .value = 3 + }, + { + .description = "Color (no brown)", + .value = 4 + }, + { + .description = "" + } } + }, + { + .name = "snow_enabled", + .description = "Snow emulation", + .type = CONFIG_BINARY, + .default_int = 1 + }, + { + .name = "memory", + .description = "Memory size", + .type = CONFIG_SELECTION, + .default_int = 64, + .selection = { + { + .description = "32 KB", + .value = 32 + }, + { + .description = "64 KB", + .value = 64 + }, + { + .description = "" + } + } + }, + { + .name = "charset", + .description = "Character set", + .type = CONFIG_SELECTION, + .default_int = 0, + .selection = { + { + .description = "U.S. English", + .value = 0 + }, + { + .description = "Scandinavian", + .value = 1 + }, + { + .description = "Other languages", + .value = 2 + }, + { + .description = "E.F. Hutton", + .value = 3 + }, + { + .description = "" + } + } + }, + { + .type = CONFIG_END + } + // clang-format on }; - -const device_t nga_device = -{ - "NCR NGA", - "nga", - DEVICE_ISA, 0, - nga_init, - nga_close, - NULL, - { NULL }, - nga_speed_changed, - NULL, - nga_config +const device_t nga_device = { + .name = "NCR NGA", + .internal_name = "nga", + .flags = DEVICE_ISA, + .local = 0, + .init = nga_init, + .close = nga_close, + .reset = NULL, + { .available = NULL }, + .speed_changed = nga_speed_changed, + .force_redraw = NULL, + .config = nga_config }; diff --git a/src/video/vid_oak_oti.c b/src/video/vid_oak_oti.c index ed67d34aa..f5bc449e6 100644 --- a/src/video/vid_oak_oti.c +++ b/src/video/vid_oak_oti.c @@ -1,20 +1,20 @@ /* - * 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. + * 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. + * This file is part of the 86Box distribution. * - * Oak OTI037C/67/077 emulation. + * Oak OTI037C/67/077 emulation. * * * - * Authors: Sarah Walker, - * Miran Grca, + * Authors: Sarah Walker, + * Miran Grca, * - * Copyright 2008-2018 Sarah Walker. - * Copyright 2016-2018 Miran Grca. + * Copyright 2008-2018 Sarah Walker. + * Copyright 2016-2018 Miran Grca. */ #include #include @@ -29,20 +29,20 @@ #include <86box/video.h> #include <86box/vid_svga.h> #include <86box/vid_svga_render.h> +#include <86box/plat_unused.h> -#define BIOS_037C_PATH "roms/video/oti/bios.bin" -#define BIOS_067_AMA932J_PATH "roms/machines/ama932j/OTI067.BIN" -#define BIOS_067_M300_08_PATH "roms/machines/m30008/EVC_BIOS.ROM" -#define BIOS_067_M300_15_PATH "roms/machines/m30015/EVC_BIOS.ROM" -#define BIOS_077_PATH "roms/video/oti/oti077.vbi" - +#define BIOS_037C_PATH "roms/video/oti/bios.bin" +#define BIOS_067_AMA932J_PATH "roms/machines/ama932j/OTI067.BIN" +#define BIOS_067_M300_08_PATH "roms/machines/m30008/EVC_BIOS.ROM" +#define BIOS_067_M300_15_PATH "roms/machines/m30015/EVC_BIOS.ROM" +#define BIOS_077_PATH "roms/video/oti/oti077.vbi" enum { - OTI_037C, - OTI_067 = 2, - OTI_067_AMA932J, - OTI_067_M300 = 4, - OTI_077 = 5 + OTI_037C = 0, + OTI_067 = 2, + OTI_067_AMA932J = 3, + OTI_067_M300 = 4, + OTI_077 = 5 }; typedef struct { @@ -50,375 +50,428 @@ typedef struct { rom_t bios_rom; - int index; + int index; uint8_t regs[32]; uint8_t chip_id; uint8_t pos; uint8_t enable_register; uint8_t dipswitch_val; - + uint32_t vram_size; uint32_t vram_mask; } oti_t; -static video_timings_t timing_oti = {VIDEO_ISA, 6, 8,16, 6, 8,16}; - +static video_timings_t timing_oti = { .type = VIDEO_ISA, .write_b = 6, .write_w = 8, .write_l = 16, .read_b = 6, .read_w = 8, .read_l = 16 }; static void -oti_out(uint16_t addr, uint8_t val, void *p) +oti_out(uint16_t addr, uint8_t val, void *priv) { - oti_t *oti = (oti_t *)p; + oti_t *oti = (oti_t *) priv; svga_t *svga = &oti->svga; uint8_t old; - uint8_t idx, enable; + uint8_t idx; + uint8_t enable; if (!oti->chip_id && !(oti->enable_register & 1) && (addr != 0x3C3)) - return; + return; - if ((((addr&0xFFF0) == 0x3D0 || (addr&0xFFF0) == 0x3B0) && addr < 0x3de) && - !(svga->miscout & 1)) addr ^= 0x60; + if ((((addr & 0xFFF0) == 0x3D0 || (addr & 0xFFF0) == 0x3B0) && addr < 0x3de) && !(svga->miscout & 1)) + addr ^= 0x60; switch (addr) { - case 0x3C3: - if (!oti->chip_id) { - oti->enable_register = val & 1; - return; - } else - break; - break; - - case 0x3c6: case 0x3c7: case 0x3c8: case 0x3c9: - if (oti->chip_id == OTI_077) - sc1148x_ramdac_out(addr, 0, val, svga->ramdac, svga); - else - svga_out(addr, val, svga); - return; + case 0x3C3: + if (!oti->chip_id) { + oti->enable_register = val & 1; + return; + } + svga_out(addr, val, svga); + return; - case 0x3D4: - if (oti->chip_id) - svga->crtcreg = val & 0x3f; - else - svga->crtcreg = val; /* FIXME: The BIOS wants to set the test bit? */ - return; + case 0x3c6: + case 0x3c7: + case 0x3c8: + case 0x3c9: + if (oti->chip_id == OTI_077) + sc1148x_ramdac_out(addr, 0, val, svga->ramdac, svga); + else + svga_out(addr, val, svga); + return; - case 0x3D5: - if (oti->chip_id && (svga->crtcreg & 0x20)) - return; - idx = svga->crtcreg; - if (!oti->chip_id) - idx &= 0x1f; - if ((idx < 7) && (svga->crtc[0x11] & 0x80)) - return; - if ((idx == 7) && (svga->crtc[0x11] & 0x80)) - val = (svga->crtc[7] & ~0x10) | (val & 0x10); - old = svga->crtc[idx]; - svga->crtc[idx] = val; - if (old != val) { - if ((idx < 0x0e) || (idx > 0x10)) { - if (idx == 0x0c || idx == 0x0d) { - 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; + case 0x3D4: + if (oti->chip_id) + svga->crtcreg = val & 0x3f; + else + svga->crtcreg = val; /* FIXME: The BIOS wants to set the test bit? */ + return; - case 0x3DE: - if (oti->chip_id) - oti->index = val & 0x1f; - else - oti->index = val; - return; + case 0x3D5: + if (oti->chip_id && (svga->crtcreg & 0x20)) + return; + idx = svga->crtcreg; + if (!oti->chip_id) + idx &= 0x1f; + if ((idx < 7) && (svga->crtc[0x11] & 0x80)) + return; + if ((idx == 7) && (svga->crtc[0x11] & 0x80)) + val = (svga->crtc[7] & ~0x10) | (val & 0x10); + old = svga->crtc[idx]; + svga->crtc[idx] = val; + if (old != val) { + if ((idx < 0x0e) || (idx > 0x10)) { + if (idx == 0x0c || idx == 0x0d) { + 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; - case 0x3DF: - idx = oti->index; - if (!oti->chip_id) - idx &= 0x1f; - oti->regs[idx] = val; - switch (idx) { - case 0xD: - if (oti->chip_id == OTI_067) { - svga->vram_display_mask = (val & 0x0c) ? oti->vram_mask : 0x3ffff; - if (!(val & 0x80)) - svga->vram_display_mask = 0x3ffff; + case 0x3DE: + if (oti->chip_id) + oti->index = val & 0x1f; + else + oti->index = val; + return; - if ((val & 0x80) && oti->vram_size == 256) - mem_mapping_disable(&svga->mapping); - else - mem_mapping_enable(&svga->mapping); - } else if (oti->chip_id == OTI_077) { - svga->vram_display_mask = (val & 0x0c) ? oti->vram_mask : 0x3ffff; + case 0x3DF: + idx = oti->index; + if (!oti->chip_id) + idx &= 0x1f; + oti->regs[idx] = val; + switch (idx) { + case 0xD: + if (oti->chip_id == OTI_067) { + svga->vram_display_mask = (val & 0x0c) ? oti->vram_mask : 0x3ffff; + if (!(val & 0x80)) + svga->vram_display_mask = 0x3ffff; - switch ((val & 0xc0) >> 6) { - case 0x00: /* 256 kB of memory */ - default: - enable = (oti->vram_size >= 256); - if (val & 0x0c) - svga->vram_display_mask = MIN(oti->vram_mask, 0x3ffff); - break; - case 0x01: /* 1 MB of memory */ - case 0x03: - enable = (oti->vram_size >= 1024); - if (val & 0x0c) - svga->vram_display_mask = MIN(oti->vram_mask, 0xfffff); - break; - case 0x02: /* 512 kB of memory */ - enable = (oti->vram_size >= 512); - if (val & 0x0c) - svga->vram_display_mask = MIN(oti->vram_mask, 0x7ffff); - break; - } + if ((val & 0x80) && oti->vram_size == 256) + mem_mapping_disable(&svga->mapping); + else + mem_mapping_enable(&svga->mapping); + } else if (oti->chip_id == OTI_077) { + svga->vram_display_mask = (val & 0x0c) ? oti->vram_mask : 0x3ffff; - if (enable) - mem_mapping_enable(&svga->mapping); - else - mem_mapping_disable(&svga->mapping); - } else { - if (val & 0x80) - mem_mapping_disable(&svga->mapping); - else - mem_mapping_enable(&svga->mapping); - } - break; + switch ((val & 0xc0) >> 6) { + default: + case 0x00: /* 256 kB of memory */ + enable = (oti->vram_size >= 256); + if (val & 0x0c) + svga->vram_display_mask = MIN(oti->vram_mask, 0x3ffff); + break; + case 0x01: /* 1 MB of memory */ + case 0x03: + enable = (oti->vram_size >= 1024); + if (val & 0x0c) + svga->vram_display_mask = MIN(oti->vram_mask, 0xfffff); + break; + case 0x02: /* 512 kB of memory */ + enable = (oti->vram_size >= 512); + if (val & 0x0c) + svga->vram_display_mask = MIN(oti->vram_mask, 0x7ffff); + break; + } - case 0x11: - svga->read_bank = (val & 0xf) * 65536; - svga->write_bank = (val >> 4) * 65536; - break; - } - return; + if (enable) + mem_mapping_enable(&svga->mapping); + else + mem_mapping_disable(&svga->mapping); + } else { + if (val & 0x80) + mem_mapping_disable(&svga->mapping); + else + mem_mapping_enable(&svga->mapping); + } + break; + + case 0x11: + svga->read_bank = (val & 0xf) * 65536; + svga->write_bank = (val >> 4) * 65536; + break; + + default: + break; + } + return; + + default: + break; } svga_out(addr, val, svga); } - static uint8_t -oti_in(uint16_t addr, void *p) +oti_in(uint16_t addr, void *priv) { - oti_t *oti = (oti_t *)p; + oti_t *oti = (oti_t *) priv; svga_t *svga = &oti->svga; - uint8_t idx, temp; - + uint8_t idx; + uint8_t temp; + if (!oti->chip_id && !(oti->enable_register & 1) && (addr != 0x3C3)) - return 0xff; + return 0xff; + + if ((((addr & 0xFFF0) == 0x3D0 || (addr & 0xFFF0) == 0x3B0) && addr < 0x3de) && !(svga->miscout & 1)) + addr ^= 0x60; - if ((((addr&0xFFF0) == 0x3D0 || (addr&0xFFF0) == 0x3B0) && addr < 0x3de) && - !(svga->miscout & 1)) addr ^= 0x60; - switch (addr) { - case 0x3C2: - if ((svga->vgapal[0].r + svga->vgapal[0].g + svga->vgapal[0].b) >= 0x50) - temp = 0; - else - temp = 0x10; - break; + case 0x3C2: + if ((svga->vgapal[0].r + svga->vgapal[0].g + svga->vgapal[0].b) >= 0x50) + temp = 0; + else + temp = 0x10; + break; - case 0x3C3: - if (oti->chip_id) - temp = svga_in(addr, svga); - else - temp = oti->enable_register; - break; + case 0x3C3: + if (oti->chip_id) + temp = svga_in(addr, svga); + else + temp = oti->enable_register; + break; - case 0x3c6: case 0x3c7: case 0x3c8: case 0x3c9: - if (oti->chip_id == OTI_077) - return sc1148x_ramdac_in(addr, 0, svga->ramdac, svga); - return svga_in(addr, svga); + case 0x3c6: + case 0x3c7: + case 0x3c8: + case 0x3c9: + if (oti->chip_id == OTI_077) + return sc1148x_ramdac_in(addr, 0, svga->ramdac, svga); + return svga_in(addr, svga); - case 0x3CF: - return svga->gdcreg[svga->gdcaddr & 0xf]; + case 0x3CF: + return svga->gdcreg[svga->gdcaddr & 0xf]; - case 0x3D4: - temp = svga->crtcreg; - break; + case 0x3D4: + temp = svga->crtcreg; + break; - case 0x3D5: - if (oti->chip_id) { - if (svga->crtcreg & 0x20) - temp = 0xff; - else - temp = svga->crtc[svga->crtcreg]; - } else - temp = svga->crtc[svga->crtcreg & 0x1f]; - break; + case 0x3D5: + if (oti->chip_id) { + if (svga->crtcreg & 0x20) + temp = 0xff; + else + temp = svga->crtc[svga->crtcreg]; + } else + temp = svga->crtc[svga->crtcreg & 0x1f]; + break; - case 0x3DA: - if (oti->chip_id) { - temp = svga_in(addr, svga); - break; - } + case 0x3DA: + if (oti->chip_id) { + temp = svga_in(addr, svga); + break; + } - svga->attrff = 0; - /*The OTI-037C BIOS waits for bits 0 and 3 in 0x3da to go low, then reads 0x3da again - and expects the diagnostic bits to equal the current border colour. As I understand - it, the 0x3da active enable status does not include the border time, so this may be - an area where OTI-037C is not entirely VGA compatible.*/ - svga->cgastat &= ~0x30; - /* copy color diagnostic info from the overscan color register */ - switch (svga->attrregs[0x12] & 0x30) - { - case 0x00: /* P0 and P2 */ - if (svga->attrregs[0x11] & 0x01) - svga->cgastat |= 0x10; - if (svga->attrregs[0x11] & 0x04) - svga->cgastat |= 0x20; - break; - case 0x10: /* P4 and P5 */ - if (svga->attrregs[0x11] & 0x10) - svga->cgastat |= 0x10; - if (svga->attrregs[0x11] & 0x20) - svga->cgastat |= 0x20; - break; - case 0x20: /* P1 and P3 */ - if (svga->attrregs[0x11] & 0x02) - svga->cgastat |= 0x10; - if (svga->attrregs[0x11] & 0x08) - svga->cgastat |= 0x20; - break; - case 0x30: /* P6 and P7 */ - if (svga->attrregs[0x11] & 0x40) - svga->cgastat |= 0x10; - if (svga->attrregs[0x11] & 0x80) - svga->cgastat |= 0x20; - break; - } - temp = svga->cgastat; - break; + svga->attrff = 0; + /*The OTI-037C BIOS waits for bits 0 and 3 in 0x3da to go low, then reads 0x3da again + and expects the diagnostic bits to equal the current border colour. As I understand + it, the 0x3da active enable status does not include the border time, so this may be + an area where OTI-037C is not entirely VGA compatible.*/ + svga->cgastat &= ~0x30; + /* copy color diagnostic info from the overscan color register */ + switch (svga->attrregs[0x12] & 0x30) { + case 0x00: /* P0 and P2 */ + if (svga->attrregs[0x11] & 0x01) + svga->cgastat |= 0x10; + if (svga->attrregs[0x11] & 0x04) + svga->cgastat |= 0x20; + break; + case 0x10: /* P4 and P5 */ + if (svga->attrregs[0x11] & 0x10) + svga->cgastat |= 0x10; + if (svga->attrregs[0x11] & 0x20) + svga->cgastat |= 0x20; + break; + case 0x20: /* P1 and P3 */ + if (svga->attrregs[0x11] & 0x02) + svga->cgastat |= 0x10; + if (svga->attrregs[0x11] & 0x08) + svga->cgastat |= 0x20; + break; + case 0x30: /* P6 and P7 */ + if (svga->attrregs[0x11] & 0x40) + svga->cgastat |= 0x10; + if (svga->attrregs[0x11] & 0x80) + svga->cgastat |= 0x20; + break; - case 0x3DE: - temp = oti->index; - if (oti->chip_id) - temp |= (oti->chip_id << 5); - break; + default: + break; + } + temp = svga->cgastat; + break; - case 0x3DF: - idx = oti->index; - if (!oti->chip_id) - idx &= 0x1f; - if (idx == 0x10) - temp = oti->dipswitch_val; - else - temp = oti->regs[idx]; - break; + case 0x3DE: + temp = oti->index; + if (oti->chip_id) + temp |= (oti->chip_id << 5); + break; - default: - temp = svga_in(addr, svga); - break; + case 0x3DF: + idx = oti->index; + if (!oti->chip_id) + idx &= 0x1f; + if (idx == 0x10) + temp = oti->dipswitch_val; + else + temp = oti->regs[idx]; + break; + + default: + temp = svga_in(addr, svga); + break; } - return(temp); + return temp; } - static void -oti_pos_out(uint16_t addr, uint8_t val, void *p) +oti_pos_out(UNUSED(uint16_t addr), uint8_t val, void *priv) { - oti_t *oti = (oti_t *)p; + oti_t *oti = (oti_t *) priv; if ((val ^ oti->pos) & 8) { - if (val & 8) - io_sethandler(0x03c0, 32, oti_in, NULL, NULL, - oti_out, NULL, NULL, oti); - else - io_removehandler(0x03c0, 32, oti_in, NULL, NULL, - oti_out, NULL, NULL, oti); + if (val & 8) + io_sethandler(0x03c0, 32, oti_in, NULL, NULL, + oti_out, NULL, NULL, oti); + else + io_removehandler(0x03c0, 32, oti_in, NULL, NULL, + oti_out, NULL, NULL, oti); } oti->pos = val; } - static uint8_t -oti_pos_in(uint16_t addr, void *p) +oti_pos_in(UNUSED(uint16_t addr), void *priv) { - oti_t *oti = (oti_t *)p; + const oti_t *oti = (oti_t *) priv; - return(oti->pos); -} + return (oti->pos); +} +static float +oti_getclock(int clock) +{ + float ret = 0.0; + + switch (clock) { + default: + case 0: + ret = 25175000.0; + break; + case 1: + ret = 28322000.0; + break; + case 4: + ret = 14318000.0; + break; + case 5: + ret = 16257000.0; + break; + case 7: + ret = 35500000.0; + break; + } + + return ret; +} static void oti_recalctimings(svga_t *svga) { - oti_t *oti = (oti_t *)svga->p; + const oti_t *oti = (oti_t *) svga->priv; + int clk_sel = ((svga->miscout >> 2) & 3) | ((oti->regs[0x0d] & 0x20) >> 3); - if (oti->regs[0x14] & 0x08) svga->ma_latch |= 0x10000; - if (oti->regs[0x16] & 0x08) svga->ma_latch |= 0x20000; + svga->clock = (cpuclock * (double) (1ULL << 32)) / oti_getclock(clk_sel); - if (oti->regs[0x14] & 0x01) svga->vtotal += 0x400; - if (oti->regs[0x14] & 0x02) svga->dispend += 0x400; - if (oti->regs[0x14] & 0x04) svga->vsyncstart += 0x400; + if (oti->chip_id > 0) { + if (oti->regs[0x14] & 0x08) + svga->ma_latch |= 0x10000; + if (oti->regs[0x16] & 0x08) + svga->ma_latch |= 0x20000; - if ((oti->regs[0x0d] & 0x0c) && !(oti->regs[0x0d] & 0x10)) svga->rowoffset <<= 1; + if (oti->regs[0x14] & 0x01) + svga->vtotal += 0x400; + if (oti->regs[0x14] & 0x02) + svga->dispend += 0x400; + if (oti->regs[0x14] & 0x04) + svga->vsyncstart += 0x400; - svga->interlace = oti->regs[0x14] & 0x80; - - if (svga->bpp == 16) { - svga->render = svga_render_16bpp_highres; - svga->hdisp >>= 1; - } else if (svga->bpp == 15) { - svga->render = svga_render_15bpp_highres; - svga->hdisp >>= 1; - } + svga->interlace = oti->regs[0x14] & 0x80; + } + + if ((oti->regs[0x0d] & 0x0c) && !(oti->regs[0x0d] & 0x10)) + svga->rowoffset <<= 1; + + if (svga->bpp == 16) { + svga->render = svga_render_16bpp_highres; + svga->hdisp >>= 1; + } else if (svga->bpp == 15) { + svga->render = svga_render_15bpp_highres; + svga->hdisp >>= 1; + } } - static void * oti_init(const device_t *info) { - oti_t *oti = malloc(sizeof(oti_t)); - char *romfn = NULL; + oti_t *oti = malloc(sizeof(oti_t)); + const char *romfn = NULL; memset(oti, 0x00, sizeof(oti_t)); oti->chip_id = info->local; oti->dipswitch_val = 0x18; - switch(oti->chip_id) { - case OTI_037C: - romfn = BIOS_037C_PATH; - oti->vram_size = 256; - oti->regs[0] = 0x08; /* FIXME: The BIOS wants to read this at index 0? This index is undocumented. */ - /* io_sethandler(0x03c0, 32, - oti_in, NULL, NULL, oti_out, NULL, NULL, oti); */ - break; + switch (oti->chip_id) { + case OTI_037C: + romfn = BIOS_037C_PATH; + oti->vram_size = 256; + oti->regs[0] = 0x08; /* FIXME: The BIOS wants to read this at index 0? This index is undocumented. */ +#if 0 + io_sethandler(0x03c0, 32, + oti_in, NULL, NULL, oti_out, NULL, NULL, oti); +#endif + break; - case OTI_067_AMA932J: - romfn = BIOS_067_AMA932J_PATH; - oti->chip_id = 2; - oti->vram_size = device_get_config_int("memory"); - oti->dipswitch_val |= 0x20; - oti->pos = 0x08; /* Tell the BIOS the I/O ports are already enabled to avoid a double I/O handler mess. */ - io_sethandler(0x46e8, 1, oti_pos_in, NULL, NULL, oti_pos_out, NULL, NULL, oti); - break; + case OTI_067_AMA932J: + romfn = BIOS_067_AMA932J_PATH; + oti->chip_id = 2; + oti->vram_size = device_get_config_int("memory"); + oti->dipswitch_val |= 0x20; + oti->pos = 0x08; /* Tell the BIOS the I/O ports are already enabled to avoid a double I/O handler mess. */ + io_sethandler(0x46e8, 1, oti_pos_in, NULL, NULL, oti_pos_out, NULL, NULL, oti); + break; - case OTI_067_M300: - if (rom_present(BIOS_067_M300_15_PATH)) - romfn = BIOS_067_M300_15_PATH; - else - romfn = BIOS_067_M300_08_PATH; - oti->vram_size = device_get_config_int("memory"); - oti->pos = 0x08; /* Tell the BIOS the I/O ports are already enabled to avoid a double I/O handler mess. */ - io_sethandler(0x46e8, 1, oti_pos_in, NULL, NULL, oti_pos_out, NULL, NULL, oti); - break; + case OTI_067_M300: + if (rom_present(BIOS_067_M300_15_PATH)) + romfn = BIOS_067_M300_15_PATH; + else + romfn = BIOS_067_M300_08_PATH; + oti->vram_size = device_get_config_int("memory"); + oti->pos = 0x08; /* Tell the BIOS the I/O ports are already enabled to avoid a double I/O handler mess. */ + io_sethandler(0x46e8, 1, oti_pos_in, NULL, NULL, oti_pos_out, NULL, NULL, oti); + break; - case OTI_067: - case OTI_077: - romfn = BIOS_077_PATH; - oti->vram_size = device_get_config_int("memory"); - oti->pos = 0x08; /* Tell the BIOS the I/O ports are already enabled to avoid a double I/O handler mess. */ - io_sethandler(0x46e8, 1, oti_pos_in, NULL, NULL, oti_pos_out, NULL, NULL, oti); - break; + case OTI_067: + case OTI_077: + romfn = BIOS_077_PATH; + oti->vram_size = device_get_config_int("memory"); + oti->pos = 0x08; /* Tell the BIOS the I/O ports are already enabled to avoid a double I/O handler mess. */ + io_sethandler(0x46e8, 1, oti_pos_in, NULL, NULL, oti_pos_out, NULL, NULL, oti); + break; + + default: + break; } if (romfn != NULL) { - rom_init(&oti->bios_rom, romfn, - 0xc0000, 0x8000, 0x7fff, 0, MEM_MAPPING_EXTERNAL); + rom_init(&oti->bios_rom, romfn, + 0xc0000, 0x8000, 0x7fff, 0, MEM_MAPPING_EXTERNAL); } oti->vram_mask = (oti->vram_size << 10) - 1; @@ -426,206 +479,220 @@ oti_init(const device_t *info) video_inform(VIDEO_FLAG_TYPE_SPECIAL, &timing_oti); svga_init(info, &oti->svga, oti, oti->vram_size << 10, - oti_recalctimings, oti_in, oti_out, NULL, NULL); + oti_recalctimings, oti_in, oti_out, NULL, NULL); - if (oti->chip_id == OTI_077) - oti->svga.ramdac = device_add(&sc11487_ramdac_device); /*Actually a 82c487, probably a clone.*/ + if (oti->chip_id == OTI_077) + oti->svga.ramdac = device_add(&sc11487_ramdac_device); /*Actually a 82c487, probably a clone.*/ io_sethandler(0x03c0, 32, - oti_in, NULL, NULL, oti_out, NULL, NULL, oti); + oti_in, NULL, NULL, oti_out, NULL, NULL, oti); - oti->svga.miscout = 1; - oti->svga.packed_chain4 = 1; + oti->svga.miscout = 1; + oti->svga.packed_chain4 = 1; - return(oti); + return oti; } - static void -oti_close(void *p) +oti_close(void *priv) { - oti_t *oti = (oti_t *)p; + oti_t *oti = (oti_t *) priv; svga_close(&oti->svga); free(oti); } - static void -oti_speed_changed(void *p) +oti_speed_changed(void *priv) { - oti_t *oti = (oti_t *)p; + oti_t *oti = (oti_t *) priv; svga_recalctimings(&oti->svga); } - static void -oti_force_redraw(void *p) +oti_force_redraw(void *priv) { - oti_t *oti = (oti_t *)p; + oti_t *oti = (oti_t *) priv; oti->svga.fullchange = changeframecount; } - static int oti037c_available(void) { - return(rom_present(BIOS_037C_PATH)); + return (rom_present(BIOS_037C_PATH)); } static int oti067_ama932j_available(void) { - return(rom_present(BIOS_067_AMA932J_PATH)); + return (rom_present(BIOS_067_AMA932J_PATH)); } static int oti067_077_available(void) { - return(rom_present(BIOS_077_PATH)); + return (rom_present(BIOS_077_PATH)); } static int oti067_m300_available(void) { if (rom_present(BIOS_067_M300_15_PATH)) - return(rom_present(BIOS_067_M300_15_PATH)); - else - return(rom_present(BIOS_067_M300_08_PATH)); + return (rom_present(BIOS_067_M300_15_PATH)); + else + return (rom_present(BIOS_067_M300_08_PATH)); } - -static const device_config_t oti067_config[] = -{ - { - "memory", "Memory size", CONFIG_SELECTION, "", 512, "", { 0 }, - { - { - "256 kB", 256 - }, - { - "512 kB", 512 - }, - { - "" - } - } - }, - { - "", "", -1 - } +// clang-format off +static const device_config_t oti067_config[] = { + { + .name = "memory", + .description = "Memory size", + .type = CONFIG_SELECTION, + .default_int = 512, + .selection = { + { + .description = "256 kB", + .value = 256 + }, + { + .description = "512 kB", + .value = 512 + }, + { + .description = "" + } + } + }, + { + .type = CONFIG_END + } }; - -static const device_config_t oti067_ama932j_config[] = -{ - { - "memory", "Memory size", CONFIG_SELECTION, "", 256, "", { 0 }, - { - { - "256 kB", 256 - }, - { - "512 kB", 512 - }, - { - "" - } - } - }, - { - "", "", -1 - } +static const device_config_t oti067_ama932j_config[] = { + { + .name = "memory", + .description = "Memory size", + .type = CONFIG_SELECTION, + .default_int = 256, + .selection = { + { + .description = "256 kB", + .value = 256 + }, + { + .description = "512 kB", + .value = 512 + }, + { + .description = "" + } + } + }, + { + .type = CONFIG_END + } }; +static const device_config_t oti077_config[] = { + { + .name = "memory", + .description = "Memory size", + .type = CONFIG_SELECTION, + .default_int = 1024, + .selection = { + { + .description = "256 kB", + .value = 256 + }, + { + .description = "512 kB", + .value = 512 + }, + { + .description = "1 MB", + .value = 1024 + }, + { + .description = "" + } + } + }, + { + .type = CONFIG_END + } +}; +// clang-format on -static const device_config_t oti077_config[] = -{ - { - "memory", "Memory size", CONFIG_SELECTION, "", 1024, "", { 0 }, - { - { - "256 kB", 256 - }, - { - "512 kB", 512 - }, - { - "1 MB", 1024 - }, - { - "" - } - } - }, - { - "", "", -1 - } +const device_t oti037c_device = { + .name = "Oak OTI-037C", + .internal_name = "oti037c", + .flags = DEVICE_ISA, + .local = 0, + .init = oti_init, + .close = oti_close, + .reset = NULL, + { .available = oti037c_available }, + .speed_changed = oti_speed_changed, + .force_redraw = oti_force_redraw, + .config = NULL }; -const device_t oti037c_device = -{ - "Oak OTI-037C", - "oti037c", - DEVICE_ISA, - 0, - oti_init, oti_close, NULL, - { oti037c_available }, - oti_speed_changed, - oti_force_redraw +const device_t oti067_device = { + .name = "Oak OTI-067", + .internal_name = "oti067", + .flags = DEVICE_ISA, + .local = 2, + .init = oti_init, + .close = oti_close, + .reset = NULL, + { .available = oti067_077_available }, + .speed_changed = oti_speed_changed, + .force_redraw = oti_force_redraw, + .config = oti067_config }; -const device_t oti067_device = -{ - "Oak OTI-067", - "oti067", - DEVICE_ISA, - 2, - oti_init, oti_close, NULL, - { oti067_077_available }, - oti_speed_changed, - oti_force_redraw, - oti067_config +const device_t oti067_m300_device = { + .name = "Oak OTI-067 (Olivetti M300-08/15)", + .internal_name = "oti067_m300", + .flags = DEVICE_ISA, + .local = 4, + .init = oti_init, + .close = oti_close, + .reset = NULL, + { .available = oti067_m300_available }, + .speed_changed = oti_speed_changed, + .force_redraw = oti_force_redraw, + .config = oti067_config }; -const device_t oti067_m300_device = -{ - "Oak OTI-067 (Olivetti M300-08/15)", - "oti067_m300", - DEVICE_ISA, - 4, - oti_init, oti_close, NULL, - { oti067_m300_available }, - oti_speed_changed, - oti_force_redraw, - oti067_config +const device_t oti067_ama932j_device = { + .name = "Oak OTI-067 (AMA-932J)", + .internal_name = "oti067_ama932j", + .flags = DEVICE_ISA, + .local = 3, + .init = oti_init, + .close = oti_close, + .reset = NULL, + { .available = oti067_ama932j_available }, + .speed_changed = oti_speed_changed, + .force_redraw = oti_force_redraw, + .config = oti067_ama932j_config }; -const device_t oti067_ama932j_device = -{ - "Oak OTI-067 (AMA-932J)", - "oti067_ama932j", - DEVICE_ISA, - 3, - oti_init, oti_close, NULL, - { oti067_ama932j_available }, - oti_speed_changed, - oti_force_redraw, - oti067_ama932j_config -}; - -const device_t oti077_device = -{ - "Oak OTI-077", - "oti077", - DEVICE_ISA, - 5, - oti_init, oti_close, NULL, - { oti067_077_available }, - oti_speed_changed, - oti_force_redraw, - oti077_config +const device_t oti077_device = { + .name = "Oak OTI-077", + .internal_name = "oti077", + .flags = DEVICE_ISA, + .local = 5, + .init = oti_init, + .close = oti_close, + .reset = NULL, + { .available = oti067_077_available }, + .speed_changed = oti_speed_changed, + .force_redraw = oti_force_redraw, + .config = oti077_config }; diff --git a/src/video/vid_ogc.c b/src/video/vid_ogc.c index ca22f6d5f..c3073898d 100644 --- a/src/video/vid_ogc.c +++ b/src/video/vid_ogc.c @@ -1,25 +1,25 @@ /* - * 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. + * 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. + * This file is part of the 86Box distribution. * - * Emulation of the Olivetti OGC 8-bit ISA (GO708) and - * M21/M24/M28 16-bit bus (GO317/318/380/709) video cards. + * Emulation of the Olivetti OGC 8-bit ISA (GO708) and + * M21/M24/M28 16-bit bus (GO317/318/380/709) video cards. * * * - * Authors: Sarah Walker, - * Miran Grca, - * Fred N. van Kempen, - * EngiNerd, + * Authors: Sarah Walker, + * Miran Grca, + * Fred N. van Kempen, + * EngiNerd, * - * Copyright 2008-2019 Sarah Walker. - * Copyright 2016-2019 Miran Grca. - * Copyright 2017-2019 Fred N. van Kempen. - * Copyright 2020 EngiNerd. + * Copyright 2008-2019 Sarah Walker. + * Copyright 2016-2019 Miran Grca. + * Copyright 2017-2019 Fred N. van Kempen. + * Copyright 2020 EngiNerd. */ #include @@ -39,519 +39,504 @@ #include <86box/vid_cga.h> #include <86box/vid_ogc.h> #include <86box/vid_cga_comp.h> - - +#include <86box/plat_unused.h> /* - * Current bugs: + * Current bugs: * - Olivetti diagnostics fail with errors: 6845 crtc write / read error out 0000 in 00ff * - Dark blue (almost black) picture in composite mode */ -#define CGA_RGB 0 +#define CGA_RGB 0 #define CGA_COMPOSITE 1 #define COMPOSITE_OLD 0 #define COMPOSITE_NEW 1 +static video_timings_t timing_ogc = { .type = VIDEO_ISA, .write_b = 8, .write_w = 16, .write_l = 32, .read_b = 8, .read_w = 16, .read_l = 32 }; - -static video_timings_t timing_ogc = {VIDEO_ISA, 8,16,32, 8,16,32}; - -static uint8_t mdaattr[256][2][2]; +static uint8_t mdaattr[256][2][2]; void ogc_recalctimings(ogc_t *ogc) { - double _dispontime, _dispofftime, disptime; + double _dispontime; + double _dispofftime; + double disptime; if (ogc->cga.cgamode & 1) { - disptime = ogc->cga.crtc[0] + 1; - _dispontime = ogc->cga.crtc[1]; + disptime = ogc->cga.crtc[0] + 1; + _dispontime = ogc->cga.crtc[1]; } else { - disptime = (ogc->cga.crtc[0] + 1) << 1; - _dispontime = ogc->cga.crtc[1] << 1; + disptime = (ogc->cga.crtc[0] + 1) << 1; + _dispontime = ogc->cga.crtc[1] << 1; } _dispofftime = disptime - _dispontime; - _dispontime *= CGACONST / 2; + _dispontime *= CGACONST / 2; _dispofftime *= CGACONST / 2; - ogc->cga.dispontime = (uint64_t)(_dispontime); - ogc->cga.dispofftime = (uint64_t)(_dispofftime); + ogc->cga.dispontime = (uint64_t) (_dispontime); + ogc->cga.dispofftime = (uint64_t) (_dispofftime); } void ogc_out(uint16_t addr, uint8_t val, void *priv) { - ogc_t *ogc = (ogc_t *)priv; + ogc_t *ogc = (ogc_t *) priv; - // if (addr >= 0x3c0 && addr <= 0x3cf){ - // addr = addr + 16; - // } +#if 0 + if (addr >= 0x3c0 && addr <= 0x3cf) + addr = addr + 16; +#endif switch (addr) { - case 0x3d4: - case 0x3d5: - case 0x3d8: - case 0x3d9: - cga_out(addr, val, &ogc->cga); - break; + case 0x3d4: + case 0x3d5: + case 0x3d8: + case 0x3d9: + cga_out(addr, val, &ogc->cga); + break; - case 0x3de: - /* set control register */ - ogc->ctrl_3de = val; - /* select 1st or 2nd 16k vram block to be used */ - ogc->base = (val & 0x08) ? 0x4000 : 0; - break; - } + case 0x3de: + /* set control register */ + ogc->ctrl_3de = val; + /* select 1st or 2nd 16k vram block to be used */ + ogc->base = (val & 0x08) ? 0x4000 : 0; + break; + + default: + break; + } } uint8_t ogc_in(uint16_t addr, void *priv) { - ogc_t *ogc = (ogc_t *)priv; + ogc_t *ogc = (ogc_t *) priv; - // if (addr >= 0x3c0 && addr <= 0x3cf){ - // addr = addr + 16; - // } +#if 0 + if (addr >= 0x3c0 && addr <= 0x3cf) + addr = addr + 16; +#endif uint8_t ret = 0xff; switch (addr) { - case 0x3d4: - case 0x3d5: - case 0x3da: - /* - * bits 6-7: 3 = no DEB expansion board installed - * bits 4-5: 2 color, 3 mono - * bit 3: high during 1st half of vertical retrace in character mode (CCA standard) - * bit 2: lightpen switch (CGA standard) - * bit 1: lightpen strobe (CGA standard) - * bit 0: high during retrace (CGA standard) - */ - ret = cga_in(addr, &ogc->cga); - if (addr == 0x3da){ - ret = ret | 0xe0; - if (ogc->mono_display) - ret = ret | 0x10; - break; - } - } + case 0x3d4: + case 0x3d5: + case 0x3da: + /* + * bits 6-7: 3 = no DEB expansion board installed + * bits 4-5: 2 color, 3 mono + * bit 3: high during 1st half of vertical retrace in character mode (CCA standard) + * bit 2: lightpen switch (CGA standard) + * bit 1: lightpen strobe (CGA standard) + * bit 0: high during retrace (CGA standard) + */ + ret = cga_in(addr, &ogc->cga); + if (addr == 0x3da) { + ret = ret | 0xe0; + if (ogc->mono_display) + ret = ret | 0x10; + } + break; - return(ret); + default: + break; + } + + return ret; } - void -ogc_waitstates(void *p) +ogc_waitstates(UNUSED(void *priv)) { - int ws_array[16] = {3, 4, 5, 6, 7, 8, 4, 5, 6, 7, 8, 4, 5, 6, 7, 8}; + 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); } - void ogc_write(uint32_t addr, uint8_t val, void *priv) { - ogc_t *ogc = (ogc_t *)priv; - int offset; + ogc_t *ogc = (ogc_t *) priv; + int offset; - ogc->cga.vram[addr & 0x7FFF]=val; - if (ogc->cga.snow_enabled) { - /* recreate snow effect */ - offset = ((timer_get_remaining_u64(&ogc->cga.timer) / CGACONST) * 4) & 0xfc; - ogc->cga.charbuffer[offset] = ogc->cga.vram[addr & 0x7fff]; - ogc->cga.charbuffer[offset | 1] = ogc->cga.vram[addr & 0x7fff]; - } + ogc->cga.vram[addr & 0x7FFF] = val; + if (ogc->cga.snow_enabled) { + /* recreate snow effect */ + offset = ((timer_get_remaining_u64(&ogc->cga.timer) / CGACONST) * 4) & 0xfc; + ogc->cga.charbuffer[offset] = ogc->cga.vram[addr & 0x7fff]; + ogc->cga.charbuffer[offset | 1] = ogc->cga.vram[addr & 0x7fff]; + } ogc_waitstates(&ogc->cga); } uint8_t ogc_read(uint32_t addr, void *priv) { - - ogc_t *ogc = (ogc_t *)priv; - int offset; - ogc_waitstates(&ogc->cga); + ogc_t *ogc = (ogc_t *) priv; + int offset; - if (ogc->cga.snow_enabled) { - /* recreate snow effect */ - offset = ((timer_get_remaining_u64(&ogc->cga.timer) / CGACONST) * 4) & 0xfc; - ogc->cga.charbuffer[offset] = ogc->cga.vram[addr & 0x7fff]; - ogc->cga.charbuffer[offset | 1] = ogc->cga.vram[addr & 0x7fff]; - } - - return(ogc->cga.vram[addr & 0x7FFF]); + ogc_waitstates(&ogc->cga); + + if (ogc->cga.snow_enabled) { + /* recreate snow effect */ + offset = ((timer_get_remaining_u64(&ogc->cga.timer) / CGACONST) * 4) & 0xfc; + ogc->cga.charbuffer[offset] = ogc->cga.vram[addr & 0x7fff]; + ogc->cga.charbuffer[offset | 1] = ogc->cga.vram[addr & 0x7fff]; + } + + return (ogc->cga.vram[addr & 0x7FFF]); } void ogc_poll(void *priv) { - ogc_t *ogc = (ogc_t *)priv; - uint16_t ca = (ogc->cga.crtc[15] | (ogc->cga.crtc[14] << 8)) & 0x3fff; - int drawcursor; - int x, c, xs_temp, ys_temp; - int oldvc; - uint8_t chr, attr; - uint16_t dat, dat2; - int cols[4]; - int oldsc; - int blink = 0; - int underline = 0; - uint8_t border; - - //composito colore appare blu scuro + ogc_t *ogc = (ogc_t *) priv; + uint16_t ca = (ogc->cga.crtc[15] | (ogc->cga.crtc[14] << 8)) & 0x3fff; + int drawcursor; + int x; + int c; + int xs_temp; + int ys_temp; + int oldvc; + uint8_t chr; + uint8_t attr; + uint16_t dat; + uint16_t dat2; + int cols[4]; + int oldsc; + int blink = 0; + int underline = 0; - /* graphic mode and not mode 40h */ - if (!(ogc->ctrl_3de & 0x1 || !(ogc->cga.cgamode & 2))) { - /* standard cga mode */ - cga_poll(&ogc->cga); - return; - } else { - /* mode 40h or text mode */ - if (!ogc->cga.linepos) { - timer_advance_u64(&ogc->cga.timer, ogc->cga.dispofftime); - ogc->cga.cgastat |= 1; - ogc->cga.linepos = 1; - oldsc = ogc->cga.sc; - if ((ogc->cga.crtc[8] & 3) == 3) - ogc->cga.sc = ((ogc->cga.sc << 1) + ogc->cga.oddeven) & 7; - if (ogc->cga.cgadispon) { - if (ogc->cga.displine < ogc->cga.firstline) { - ogc->cga.firstline = ogc->cga.displine; - video_wait_for_buffer(); - } - ogc->cga.lastline = ogc->cga.displine; - /* 80-col */ - if (ogc->cga.cgamode & 1) { - /* for each text column */ - for (x = 0; x < ogc->cga.crtc[1]; x++) { - /* video output enabled */ - if (ogc->cga.cgamode & 8) { - /* character */ - chr = ogc->cga.charbuffer[x << 1]; - /* text attributes */ - attr = ogc->cga.charbuffer[(x << 1) + 1]; - } else - chr = attr = 0; - /* check if cursor has to be drawn */ - drawcursor = ((ogc->cga.ma == ca) && ogc->cga.con && ogc->cga.cursoron); - /* check if character underline mode should be set */ - underline = ((ogc->ctrl_3de & 0x40) && (attr & 0x1) && !(attr & 0x6)); - if (underline) { - /* set forecolor to white */ - attr = attr | 0x7; - } - blink = 0; - /* set foreground */ - cols[1] = (attr & 15) + 16; - /* blink active */ - if (ogc->cga.cgamode & 0x20) { - cols[0] = ((attr >> 4) & 7) + 16; - /* attribute 7 active and not cursor */ - if ((ogc->cga.cgablink & 8) && (attr & 0x80) && !ogc->cga.drawcursor) { - /* set blinking */ - cols[1] = cols[0]; - blink = 1; - } - } else { - /* Set intensity bit */ - cols[0] = (attr >> 4) + 16; - blink = (attr & 0x80) * 8 + 7 + 16; - } - /* character underline active and 7th row of pixels in character height being drawn */ - if (underline && (ogc->cga.sc == 7)) { - /* for each pixel in character width */ - for (c = 0; c < 8; c++) - buffer32->line[ogc->cga.displine][(x << 3) + c + 8] = mdaattr[attr][blink][1]; - } else if (drawcursor) { - for (c = 0; c < 8; c++) - buffer32->line[ogc->cga.displine][(x << 3) + c + 8] = cols[(fontdatm[chr][((ogc->cga.sc & 7) << 1) | ogc->lineff] & (1 << (c ^ 7))) ? 1 : 0] ^ 15; - } else { - for (c = 0; c < 8; c++) - buffer32->line[ogc->cga.displine][(x << 3) + c + 8] = cols[(fontdatm[chr][((ogc->cga.sc & 7) << 1) | ogc->lineff] & (1 << (c ^ 7))) ? 1 : 0]; - } - - ogc->cga.ma++; - } - } - /* 40-col */ - else if (!(ogc->cga.cgamode & 2)) { - for (x = 0; x < ogc->cga.crtc[1]; x++) { - if (ogc->cga.cgamode & 8) { - chr = ogc->cga.vram[((ogc->cga.ma << 1) & 0x3fff) + ogc->base]; - attr = ogc->cga.vram[(((ogc->cga.ma << 1) + 1) & 0x3fff) + ogc->base]; - } else { - chr = attr = 0; - } - drawcursor = ((ogc->cga.ma == ca) && ogc->cga.con && ogc->cga.cursoron); - /* check if character underline mode should be set */ - underline = ((ogc->ctrl_3de & 0x40) && (attr & 0x1) && !(attr & 0x6)); - if (underline) { - /* set forecolor to white */ - attr = attr | 0x7; - } - blink = 0; - /* set foreground */ - cols[1] = (attr & 15) + 16; - /* blink active */ - if (ogc->cga.cgamode & 0x20) { - cols[0] = ((attr >> 4) & 7) + 16; - if ((ogc->cga.cgablink & 8) && (attr & 0x80) && !ogc->cga.drawcursor) { - /* set blinking */ - cols[1] = cols[0]; - blink = 1; - } - } else { - /* Set intensity bit */ - cols[0] = (attr >> 4) + 16; - blink = (attr & 0x80) * 8 + 7 + 16; - } + // composito colore appare blu scuro - - /* character underline active and 7th row of pixels in character height being drawn */ - if (underline && (ogc->cga.sc == 7)) { - /* for each pixel in character width */ - for (c = 0; c < 8; c++) - buffer32->line[ogc->cga.displine][(x << 4) + (c << 1) + 8] = - buffer32->line[ogc->cga.displine][(x << 4) + (c << 1) + 1 + 8] = mdaattr[attr][blink][1]; - } else if (drawcursor) { - for (c = 0; c < 8; c++) - buffer32->line[ogc->cga.displine][(x << 4) + (c << 1) + 8] = - buffer32->line[ogc->cga.displine][(x << 4) + (c << 1) + 1 + 8] = cols[(fontdatm[chr][((ogc->cga.sc & 7) << 1) | ogc->lineff] & (1 << (c ^ 7))) ? 1 : 0] ^ 15; - } else { - for (c = 0; c < 8; c++) - buffer32->line[ogc->cga.displine][(x << 4) + (c << 1) + 8] = - buffer32->line[ogc->cga.displine][(x << 4) + (c << 1) + 1 + 8] = cols[(fontdatm[chr][((ogc->cga.sc & 7) << 1) | ogc->lineff] & (1 << (c ^ 7))) ? 1 : 0]; - } - - ogc->cga.ma++; - - } - } else { - /* 640x400 mode */ - if (ogc->ctrl_3de & 1 ) { - dat2 = ((ogc->cga.sc & 1) * 0x4000) | (ogc->lineff * 0x2000); - cols[0] = 0; cols[1] = 15 + 16; - } - else { - dat2 = (ogc->cga.sc & 1) * 0x2000; - cols[0] = 0; cols[1] = (ogc->cga.cgacol & 15) + 16; - } - - for (x = 0; x < ogc->cga.crtc[1]; x++) { - /* video out */ - if (ogc->cga.cgamode & 8) { - dat = (ogc->cga.vram[((ogc->cga.ma << 1) & 0x1fff) + dat2] << 8) | ogc->cga.vram[((ogc->cga.ma << 1) & 0x1fff) + dat2 + 1]; - } else { - dat = 0; - } - ogc->cga.ma++; - - for (c = 0; c < 16; c++) { - buffer32->line[ogc->cga.displine][(x << 4) + c + 8] = cols[dat >> 15]; - dat <<= 1; - } - } - } - } else { - - /* ogc specific */ - cols[0] = ((ogc->cga.cgamode & 0x12) == 0x12) ? 0 : (ogc->cga.cgacol & 15) + 16; - if (ogc->cga.cgamode & 1) { - hline(buffer32, 0, (ogc->cga.displine << 1), ((ogc->cga.crtc[1] << 3) + 16) << 2, cols[0]); - hline(buffer32, 0, (ogc->cga.displine << 1) + 1, ((ogc->cga.crtc[1] << 3) + 16) << 2, cols[0]); - } else { - hline(buffer32, 0, (ogc->cga.displine << 1), ((ogc->cga.crtc[1] << 4) + 16) << 2, cols[0]); - hline(buffer32, 0, (ogc->cga.displine << 1) + 1, ((ogc->cga.crtc[1] << 4) + 16) << 2, cols[0]); - } - - } + /* graphic mode and not mode 40h */ + if (!(ogc->ctrl_3de & 0x1 || !(ogc->cga.cgamode & 2))) { + /* standard cga mode */ + cga_poll(&ogc->cga); + return; + } else { + /* mode 40h or text mode */ + if (!ogc->cga.linepos) { + timer_advance_u64(&ogc->cga.timer, ogc->cga.dispofftime); + ogc->cga.cgastat |= 1; + ogc->cga.linepos = 1; + oldsc = ogc->cga.sc; + if ((ogc->cga.crtc[8] & 3) == 3) + ogc->cga.sc = ((ogc->cga.sc << 1) + ogc->cga.oddeven) & 7; + if (ogc->cga.cgadispon) { + if (ogc->cga.displine < ogc->cga.firstline) { + ogc->cga.firstline = ogc->cga.displine; + video_wait_for_buffer(); + } + ogc->cga.lastline = ogc->cga.displine; + /* 80-col */ + if (ogc->cga.cgamode & 1) { + /* for each text column */ + for (x = 0; x < ogc->cga.crtc[1]; x++) { + /* video output enabled */ + if (ogc->cga.cgamode & 8) { + /* character */ + chr = ogc->cga.charbuffer[x << 1]; + /* text attributes */ + attr = ogc->cga.charbuffer[(x << 1) + 1]; + } else + chr = attr = 0; + /* check if cursor has to be drawn */ + drawcursor = ((ogc->cga.ma == ca) && ogc->cga.con && ogc->cga.cursoron); + /* check if character underline mode should be set */ + underline = ((ogc->ctrl_3de & 0x40) && (attr & 0x1) && !(attr & 0x6)); + if (underline) { + /* set forecolor to white */ + attr = attr | 0x7; + } + blink = 0; + /* set foreground */ + cols[1] = (attr & 15) + 16; + /* blink active */ + if (ogc->cga.cgamode & 0x20) { + cols[0] = ((attr >> 4) & 7) + 16; + /* attribute 7 active and not cursor */ + if ((ogc->cga.cgablink & 8) && (attr & 0x80) && !ogc->cga.drawcursor) { + /* set blinking */ + cols[1] = cols[0]; + blink = 1; + } + } else { + /* Set intensity bit */ + cols[0] = (attr >> 4) + 16; + blink = (attr & 0x80) * 8 + 7 + 16; + } + /* character underline active and 7th row of pixels in character height being drawn */ + if (underline && (ogc->cga.sc == 7)) { + /* for each pixel in character width */ + for (c = 0; c < 8; c++) + buffer32->line[ogc->cga.displine][(x << 3) + c + 8] = mdaattr[attr][blink][1]; + } else if (drawcursor) { + for (c = 0; c < 8; c++) + buffer32->line[ogc->cga.displine][(x << 3) + c + 8] = cols[(fontdatm[chr][((ogc->cga.sc & 7) << 1) | ogc->lineff] & (1 << (c ^ 7))) ? 1 : 0] ^ 15; + } else { + for (c = 0; c < 8; c++) + buffer32->line[ogc->cga.displine][(x << 3) + c + 8] = cols[(fontdatm[chr][((ogc->cga.sc & 7) << 1) | ogc->lineff] & (1 << (c ^ 7))) ? 1 : 0]; + } - /* 80 columns */ - if (ogc->cga.cgamode & 1) - x = (ogc->cga.crtc[1] << 3) + 16; - else - x = (ogc->cga.crtc[1] << 4) + 16; + ogc->cga.ma++; + } + } + /* 40-col */ + else if (!(ogc->cga.cgamode & 2)) { + for (x = 0; x < ogc->cga.crtc[1]; x++) { + if (ogc->cga.cgamode & 8) { + chr = ogc->cga.vram[((ogc->cga.ma << 1) & 0x3fff) + ogc->base]; + attr = ogc->cga.vram[(((ogc->cga.ma << 1) + 1) & 0x3fff) + ogc->base]; + } else { + chr = attr = 0; + } + drawcursor = ((ogc->cga.ma == ca) && ogc->cga.con && ogc->cga.cursoron); + /* check if character underline mode should be set */ + underline = ((ogc->ctrl_3de & 0x40) && (attr & 0x1) && !(attr & 0x6)); + if (underline) { + /* set forecolor to white */ + attr = attr | 0x7; + } + blink = 0; + /* set foreground */ + cols[1] = (attr & 15) + 16; + /* blink active */ + if (ogc->cga.cgamode & 0x20) { + cols[0] = ((attr >> 4) & 7) + 16; + if ((ogc->cga.cgablink & 8) && (attr & 0x80) && !ogc->cga.drawcursor) { + /* set blinking */ + cols[1] = cols[0]; + blink = 1; + } + } else { + /* Set intensity bit */ + cols[0] = (attr >> 4) + 16; + blink = (attr & 0x80) * 8 + 7 + 16; + } - if (ogc->cga.composite) { - if (ogc->cga.cgamode & 0x10) - border = 0x00; - else - border = ogc->cga.cgacol & 0x0f; + /* character underline active and 7th row of pixels in character height being drawn */ + if (underline && (ogc->cga.sc == 7)) { + /* for each pixel in character width */ + for (c = 0; c < 8; c++) + buffer32->line[ogc->cga.displine][(x << 4) + (c << 1) + 8] = buffer32->line[ogc->cga.displine][(x << 4) + (c << 1) + 1 + 8] = mdaattr[attr][blink][1]; + } else if (drawcursor) { + for (c = 0; c < 8; c++) + buffer32->line[ogc->cga.displine][(x << 4) + (c << 1) + 8] = buffer32->line[ogc->cga.displine][(x << 4) + (c << 1) + 1 + 8] = cols[(fontdatm[chr][((ogc->cga.sc & 7) << 1) | ogc->lineff] & (1 << (c ^ 7))) ? 1 : 0] ^ 15; + } else { + for (c = 0; c < 8; c++) + buffer32->line[ogc->cga.displine][(x << 4) + (c << 1) + 8] = buffer32->line[ogc->cga.displine][(x << 4) + (c << 1) + 1 + 8] = cols[(fontdatm[chr][((ogc->cga.sc & 7) << 1) | ogc->lineff] & (1 << (c ^ 7))) ? 1 : 0]; + } - Composite_Process(ogc->cga.cgamode, border, x >> 2, buffer32->line[(ogc->cga.displine << 1)]); - Composite_Process(ogc->cga.cgamode, border, x >> 2, buffer32->line[(ogc->cga.displine << 1) + 1]); - } + ogc->cga.ma++; + } + } else { + /* 640x400 mode */ + if (ogc->ctrl_3de & 1) { + dat2 = ((ogc->cga.sc & 1) * 0x4000) | (ogc->lineff * 0x2000); + cols[0] = 0; + cols[1] = 15 + 16; + } else { + dat2 = (ogc->cga.sc & 1) * 0x2000; + cols[0] = 0; + cols[1] = (ogc->cga.cgacol & 15) + 16; + } + for (x = 0; x < ogc->cga.crtc[1]; x++) { + /* video out */ + if (ogc->cga.cgamode & 8) { + dat = (ogc->cga.vram[((ogc->cga.ma << 1) & 0x1fff) + dat2] << 8) | ogc->cga.vram[((ogc->cga.ma << 1) & 0x1fff) + dat2 + 1]; + } else { + dat = 0; + } + ogc->cga.ma++; - ogc->cga.sc = oldsc; - if (ogc->cga.vc == ogc->cga.crtc[7] && !ogc->cga.sc) - ogc->cga.cgastat |= 8; - ogc->cga.displine++; - if (ogc->cga.displine >= 720) - ogc->cga.displine = 0; - } else { - timer_advance_u64(&ogc->cga.timer, ogc->cga.dispontime); - if (ogc->cga.cgadispon) ogc->cga.cgastat &= ~1; - ogc->cga.linepos = 0; - /* ogc specific */ - ogc->lineff ^= 1; - if (ogc->lineff) { - ogc->cga.ma = ogc->cga.maback; - } else { - if (ogc->cga.vsynctime) { - ogc->cga.vsynctime--; - if (!ogc->cga.vsynctime) - ogc->cga.cgastat &= ~8; - } - if (ogc->cga.sc == (ogc->cga.crtc[11] & 31) || ((ogc->cga.crtc[8] & 3) == 3 && ogc->cga.sc == ((ogc->cga.crtc[11] & 31) >> 1))) { - ogc->cga.con = 0; - ogc->cga.coff = 1; - } - if ((ogc->cga.crtc[8] & 3) == 3 && ogc->cga.sc == (ogc->cga.crtc[9] >> 1)) - ogc->cga.maback = ogc->cga.ma; - if (ogc->cga.vadj) { - ogc->cga.sc++; - ogc->cga.sc &= 31; - ogc->cga.ma = ogc->cga.maback; - ogc->cga.vadj--; - if (!ogc->cga.vadj) { - ogc->cga.cgadispon = 1; - ogc->cga.ma = ogc->cga.maback = (ogc->cga.crtc[13] | (ogc->cga.crtc[12] << 8)) & 0x3fff; - ogc->cga.sc = 0; - } - // potrebbe dare problemi con composito - } else if (ogc->cga.sc == ogc->cga.crtc[9] || ((ogc->cga.crtc[8] & 3) == 3 && ogc->cga.sc == (ogc->cga.crtc[9] >> 1))) { - ogc->cga.maback = ogc->cga.ma; - ogc->cga.sc = 0; - oldvc = ogc->cga.vc; - ogc->cga.vc++; - ogc->cga.vc &= 127; + for (c = 0; c < 16; c++) { + buffer32->line[ogc->cga.displine][(x << 4) + c + 8] = cols[dat >> 15]; + dat <<= 1; + } + } + } + } else { + /* ogc specific */ + cols[0] = ((ogc->cga.cgamode & 0x12) == 0x12) ? 0 : (ogc->cga.cgacol & 15) + 16; + if (ogc->cga.cgamode & 1) + hline(buffer32, 0, ogc->cga.displine, ((ogc->cga.crtc[1] << 3) + 16) << 2, cols[0]); + else + hline(buffer32, 0, ogc->cga.displine, ((ogc->cga.crtc[1] << 4) + 16) << 2, cols[0]); + } - if (ogc->cga.vc == ogc->cga.crtc[6]) - ogc->cga.cgadispon=0; + /* 80 columns */ + if (ogc->cga.cgamode & 1) + x = (ogc->cga.crtc[1] << 3) + 16; + else + x = (ogc->cga.crtc[1] << 4) + 16; - if (oldvc == ogc->cga.crtc[4]) { - ogc->cga.vc = 0; - ogc->cga.vadj = ogc->cga.crtc[5]; - if (!ogc->cga.vadj) { - ogc->cga.cgadispon = 1; - ogc->cga.ma = ogc->cga.maback = (ogc->cga.crtc[13] | (ogc->cga.crtc[12] << 8)) & 0x3fff; - } - switch (ogc->cga.crtc[10] & 0x60) { - case 0x20: - ogc->cga.cursoron = 0; - break; - case 0x60: - ogc->cga.cursoron = ogc->cga.cgablink & 0x10; - break; - default: - ogc->cga.cursoron = ogc->cga.cgablink & 0x08; - break; - } - } - if (ogc->cga.vc == ogc->cga.crtc[7]) { - ogc->cga.cgadispon = 0; - ogc->cga.displine = 0; - /* ogc specific */ - ogc->cga.vsynctime = (ogc->cga.crtc[3] >> 4) + 1; - if (ogc->cga.crtc[7]) { - if (ogc->cga.cgamode & 1) - x = (ogc->cga.crtc[1] << 3) + 16; - else - x = (ogc->cga.crtc[1] << 4) + 16; - ogc->cga.lastline++; + video_process_8(x, ogc->cga.displine); - xs_temp = x; - ys_temp = (ogc->cga.lastline - ogc->cga.firstline); + ogc->cga.sc = oldsc; + if (ogc->cga.vc == ogc->cga.crtc[7] && !ogc->cga.sc) + ogc->cga.cgastat |= 8; + ogc->cga.displine++; + if (ogc->cga.displine >= 720) + ogc->cga.displine = 0; + } else { + timer_advance_u64(&ogc->cga.timer, ogc->cga.dispontime); + if (ogc->cga.cgadispon) + ogc->cga.cgastat &= ~1; + ogc->cga.linepos = 0; + /* ogc specific */ + ogc->lineff ^= 1; + if (ogc->lineff) { + ogc->cga.ma = ogc->cga.maback; + } else { + if (ogc->cga.vsynctime) { + ogc->cga.vsynctime--; + if (!ogc->cga.vsynctime) + ogc->cga.cgastat &= ~8; + } + if (ogc->cga.sc == (ogc->cga.crtc[11] & 31) || ((ogc->cga.crtc[8] & 3) == 3 && ogc->cga.sc == ((ogc->cga.crtc[11] & 31) >> 1))) { + ogc->cga.con = 0; + ogc->cga.coff = 1; + } + if ((ogc->cga.crtc[8] & 3) == 3 && ogc->cga.sc == (ogc->cga.crtc[9] >> 1)) + ogc->cga.maback = ogc->cga.ma; + if (ogc->cga.vadj) { + ogc->cga.sc++; + ogc->cga.sc &= 31; + ogc->cga.ma = ogc->cga.maback; + ogc->cga.vadj--; + if (!ogc->cga.vadj) { + ogc->cga.cgadispon = 1; + ogc->cga.ma = ogc->cga.maback = (ogc->cga.crtc[13] | (ogc->cga.crtc[12] << 8)) & 0x3fff; + ogc->cga.sc = 0; + } + // potrebbe dare problemi con composito + } else if (ogc->cga.sc == ogc->cga.crtc[9] || ((ogc->cga.crtc[8] & 3) == 3 && ogc->cga.sc == (ogc->cga.crtc[9] >> 1))) { + ogc->cga.maback = ogc->cga.ma; + ogc->cga.sc = 0; + oldvc = ogc->cga.vc; + ogc->cga.vc++; + ogc->cga.vc &= 127; - if ((xs_temp > 0) && (ys_temp > 0)) { - if (xsize < 64) xs_temp = 656; - /* ogc specific */ - if (ysize < 32) ys_temp = 200; - if (!enable_overscan) - xs_temp -= 16; + if (ogc->cga.vc == ogc->cga.crtc[6]) + ogc->cga.cgadispon = 0; - - if ((ogc->cga.cgamode & 8) && ((xs_temp != xsize) || (ys_temp != ysize) || video_force_resize_get())) { - xsize = xs_temp; - ysize = ys_temp; - set_screen_size(xsize, ysize + (enable_overscan ? 16 : 0)); + if (oldvc == ogc->cga.crtc[4]) { + ogc->cga.vc = 0; + ogc->cga.vadj = ogc->cga.crtc[5]; + if (!ogc->cga.vadj) { + ogc->cga.cgadispon = 1; + ogc->cga.ma = ogc->cga.maback = (ogc->cga.crtc[13] | (ogc->cga.crtc[12] << 8)) & 0x3fff; + } + switch (ogc->cga.crtc[10] & 0x60) { + case 0x20: + ogc->cga.cursoron = 0; + break; + case 0x60: + ogc->cga.cursoron = ogc->cga.cgablink & 0x10; + break; + default: + ogc->cga.cursoron = ogc->cga.cgablink & 0x08; + break; + } + } + if (ogc->cga.vc == ogc->cga.crtc[7]) { + ogc->cga.cgadispon = 0; + ogc->cga.displine = 0; + /* ogc specific */ + ogc->cga.vsynctime = (ogc->cga.crtc[3] >> 4) + 1; + if (ogc->cga.crtc[7]) { + if (ogc->cga.cgamode & 1) + x = (ogc->cga.crtc[1] << 3) + 16; + else + x = (ogc->cga.crtc[1] << 4) + 16; + ogc->cga.lastline++; - if (video_force_resize_get()) - video_force_resize_set(0); - } - /* ogc specific */ - if (enable_overscan) { - if (ogc->cga.composite) - video_blit_memtoscreen(0, (ogc->cga.firstline - 8), - xsize, (ogc->cga.lastline - ogc->cga.firstline) + 16); - else - video_blit_memtoscreen_8(0, (ogc->cga.firstline - 8), - xsize, (ogc->cga.lastline - ogc->cga.firstline) + 16); - } else { - if (ogc->cga.composite) - video_blit_memtoscreen(8, ogc->cga.firstline, - xsize, (ogc->cga.lastline - ogc->cga.firstline)); - else - video_blit_memtoscreen_8(8, ogc->cga.firstline, - xsize, (ogc->cga.lastline - ogc->cga.firstline)); - } - } - frames++; + xs_temp = x; + ys_temp = (ogc->cga.lastline - ogc->cga.firstline); - video_res_x = xsize; - video_res_y = ysize; - /* 80-col */ - if (ogc->cga.cgamode & 1) { - video_res_x /= 8; - video_res_y /= (ogc->cga.crtc[9] + 1) * 2; - video_bpp = 0; - /* 40-col */ - } else if (!(ogc->cga.cgamode & 2)) { - video_res_x /= 16; - video_res_y /= (ogc->cga.crtc[9] + 1) * 2; - video_bpp = 0; - } else if (!(ogc->ctrl_3de & 1)) { - video_res_y /= 2; - video_bpp = 1; - } - } - ogc->cga.firstline = 1000; - ogc->cga.lastline = 0; - ogc->cga.cgablink++; - ogc->cga.oddeven ^= 1; - } - } else { - ogc->cga.sc++; - ogc->cga.sc &= 31; - ogc->cga.ma = ogc->cga.maback; - } + if ((xs_temp > 0) && (ys_temp > 0)) { + if (xsize < 64) + xs_temp = 656; + /* ogc specific */ + if (ysize < 32) + ys_temp = 200; + if (!enable_overscan) + xs_temp -= 16; - if (ogc->cga.cgadispon) - ogc->cga.cgastat &= ~1; - - if ((ogc->cga.sc == (ogc->cga.crtc[10] & 31) || ((ogc->cga.crtc[8] & 3) == 3 && ogc->cga.sc == ((ogc->cga.crtc[10] & 31) >> 1)))) - ogc->cga.con = 1; - } - /* 80-columns */ - if (ogc->cga.cgadispon && (ogc->cga.cgamode & 1)) { - for (x = 0; x < (ogc->cga.crtc[1] << 1); x++) - ogc->cga.charbuffer[x] = ogc->cga.vram[(((ogc->cga.ma << 1) + x) & 0x3fff) + ogc->base]; - } - } - } + if ((ogc->cga.cgamode & 8) && ((xs_temp != xsize) || (ys_temp != ysize) || video_force_resize_get())) { + xsize = xs_temp; + ysize = ys_temp; + set_screen_size(xsize, ysize + (enable_overscan ? 16 : 0)); + + if (video_force_resize_get()) + video_force_resize_set(0); + } + /* ogc specific */ + if (enable_overscan) { + video_blit_memtoscreen(0, (ogc->cga.firstline - 8), + xsize, (ogc->cga.lastline - ogc->cga.firstline) + 16); + } else { + video_blit_memtoscreen(8, ogc->cga.firstline, + xsize, (ogc->cga.lastline - ogc->cga.firstline)); + } + } + frames++; + + video_res_x = xsize; + video_res_y = ysize; + /* 80-col */ + if (ogc->cga.cgamode & 1) { + video_res_x /= 8; + video_res_y /= (ogc->cga.crtc[9] + 1) * 2; + video_bpp = 0; + /* 40-col */ + } else if (!(ogc->cga.cgamode & 2)) { + video_res_x /= 16; + video_res_y /= (ogc->cga.crtc[9] + 1) * 2; + video_bpp = 0; + } else if (!(ogc->ctrl_3de & 1)) { + video_res_y /= 2; + video_bpp = 1; + } + } + ogc->cga.firstline = 1000; + ogc->cga.lastline = 0; + ogc->cga.cgablink++; + ogc->cga.oddeven ^= 1; + } + } else { + ogc->cga.sc++; + ogc->cga.sc &= 31; + ogc->cga.ma = ogc->cga.maback; + } + + if (ogc->cga.cgadispon) + ogc->cga.cgastat &= ~1; + + if (ogc->cga.sc == (ogc->cga.crtc[10] & 31) || ((ogc->cga.crtc[8] & 3) == 3 && ogc->cga.sc == ((ogc->cga.crtc[10] & 31) >> 1))) + ogc->cga.con = 1; + } + /* 80-columns */ + if (ogc->cga.cgadispon && (ogc->cga.cgamode & 1)) { + for (x = 0; x < (ogc->cga.crtc[1] << 1); x++) + ogc->cga.charbuffer[x] = ogc->cga.vram[(((ogc->cga.ma << 1) + x) & 0x3fff) + ogc->base]; + } + } + } } void ogc_close(void *priv) { - ogc_t *ogc = (ogc_t *)priv; + ogc_t *ogc = (ogc_t *) priv; free(ogc->cga.vram); free(ogc); @@ -560,137 +545,152 @@ ogc_close(void *priv) void ogc_speed_changed(void *priv) { - ogc_t *ogc = (ogc_t *)priv; + ogc_t *ogc = (ogc_t *) priv; ogc_recalctimings(ogc); } void -ogc_mdaattr_rebuild(){ - 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; - } +ogc_mdaattr_rebuild(void) +{ + for (uint16_t 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; + 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; } -/* +/* * Missing features * - Composite video mode not working * - Optional EGC expansion board (which handles 640x400x16) not implemented */ void * -ogc_init(const device_t *info) +ogc_init(UNUSED(const device_t *info)) { - // int display_type; - ogc_t *ogc = (ogc_t *)malloc(sizeof(ogc_t)); +#if 0 + int display_type; +#endif + ogc_t *ogc = (ogc_t *) malloc(sizeof(ogc_t)); memset(ogc, 0x00, sizeof(ogc_t)); video_inform(VIDEO_FLAG_TYPE_CGA, &timing_ogc); loadfont("roms/video/ogc/ogc graphics board go380 258 pqbq.bin", 1); - - /* composite is not working yet */ - // display_type = device_get_config_int("display_type"); - ogc->cga.composite = 0; // (display_type != CGA_RGB); - ogc->cga.revision = device_get_config_int("composite_type"); - ogc->cga.snow_enabled = device_get_config_int("snow_enabled"); - - ogc->cga.vram = malloc(0x8000); - cga_comp_init(ogc->cga.revision); + /* FIXME: composite is not working yet */ +#if 0 + display_type = device_get_config_int("display_type"); +#endif + ogc->cga.composite = 0; // (display_type != CGA_RGB); + ogc->cga.revision = device_get_config_int("composite_type"); + ogc->cga.snow_enabled = device_get_config_int("snow_enabled"); + + ogc->cga.vram = malloc(0x8000); + + cga_comp_init(ogc->cga.revision); timer_add(&ogc->cga.timer, ogc_poll, ogc, 1); mem_mapping_add(&ogc->cga.mapping, 0xb8000, 0x08000, - ogc_read, NULL, NULL, - ogc_write, NULL, NULL, NULL, 0, ogc); + ogc_read, NULL, NULL, + ogc_write, NULL, NULL, NULL, 0, ogc); io_sethandler(0x03d0, 16, ogc_in, NULL, NULL, ogc_out, NULL, NULL, ogc); - + overscan_x = overscan_y = 16; - ogc->cga.rgb_type = device_get_config_int("rgb_type"); - cga_palette = (ogc->cga.rgb_type << 1); + ogc->cga.rgb_type = device_get_config_int("rgb_type"); + cga_palette = (ogc->cga.rgb_type << 1); cgapal_rebuild(); - ogc_mdaattr_rebuild(); - - /* color display */ - if (device_get_config_int("rgb_type")==0 || device_get_config_int("rgb_type") == 4) - ogc->mono_display = 0; - else - ogc->mono_display = 1; + ogc_mdaattr_rebuild(); + + /* color display */ + if (device_get_config_int("rgb_type") == 0 || device_get_config_int("rgb_type") == 4) + ogc->mono_display = 0; + else + ogc->mono_display = 1; return ogc; } - -const device_config_t ogc_m24_config[] = -{ - { - /* Olivetti / ATT compatible displays */ - "rgb_type", "RGB type", CONFIG_SELECTION, "", CGA_RGB, "", { 0 }, - { - { - "Color", 0 - }, - { - "Green Monochrome", 1 - }, - { - "Amber Monochrome", 2 - }, - { - "Gray Monochrome", 3 - }, - { - "" - } - } - }, - { - "snow_enabled", "Snow emulation", CONFIG_BINARY, "", 1, - }, - { - "", "", -1 +const device_config_t ogc_m24_config[] = { + // clang-format off + { + /* Olivetti / ATT compatible displays */ + .name = "rgb_type", + .description = "RGB type", + .type = CONFIG_SELECTION, + .default_int = CGA_RGB, + .selection = { + { + .description = "Color", + .value = 0 + }, + { + .description = "Green Monochrome", + .value = 1 + }, + { + .description = "Amber Monochrome", + .value = 2 + }, + { + .description = "Gray Monochrome", + .value = 3 + }, + { + .description = "" + } } + }, + { + .name = "snow_enabled", + .description = "Snow emulation", + .type = CONFIG_BINARY, + .default_int = 1, + }, + { + .type = CONFIG_END + } + // clang-format on }; -const device_t ogc_m24_device = -{ - "Olivetti M21/M24/M28 (GO317/318/380/709) video card", - "ogc_m24", - DEVICE_ISA, 0, - ogc_init, - ogc_close, - NULL, - { NULL }, - ogc_speed_changed, - NULL, - ogc_m24_config +const device_t ogc_m24_device = { + .name = "Olivetti M21/M24/M28 (GO317/318/380/709) video card", + .internal_name = "ogc_m24", + .flags = DEVICE_ISA, + .local = 0, + .init = ogc_init, + .close = ogc_close, + .reset = NULL, + { .available = NULL }, + .speed_changed = ogc_speed_changed, + .force_redraw = NULL, + .config = ogc_m24_config }; -const device_t ogc_device = -{ - "Olivetti OGC (GO708)", - "ogc", - DEVICE_ISA, 0, - ogc_init, - ogc_close, - NULL, - { NULL }, - ogc_speed_changed, - NULL, - cga_config +const device_t ogc_device = { + .name = "Olivetti OGC (GO708)", + .internal_name = "ogc", + .flags = DEVICE_ISA, + .local = 0, + .init = ogc_init, + .close = ogc_close, + .reset = NULL, + { .available = NULL }, + .speed_changed = ogc_speed_changed, + .force_redraw = NULL, + .config = cga_config }; diff --git a/src/video/vid_paradise.c b/src/video/vid_paradise.c index bb8cd0394..ad197f302 100644 --- a/src/video/vid_paradise.c +++ b/src/video/vid_paradise.c @@ -1,22 +1,22 @@ /* - * 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. + * 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. + * This file is part of the 86Box distribution. * - * Paradise VGA emulation - * PC2086, PC3086 use PVGA1A - * MegaPC uses W90C11A + * Paradise VGA emulation + * PC2086, PC3086 use PVGA1A + * MegaPC uses W90C11A * * * - * Authors: Sarah Walker, - * Miran Grca, + * Authors: Sarah Walker, + * Miran Grca, * - * Copyright 2008-2019 Sarah Walker. - * Copyright 2016-2019 Miran Grca. + * Copyright 2008-2019 Sarah Walker. + * Copyright 2016-2019 Miran Grca. */ #include #include @@ -33,831 +33,917 @@ #include <86box/vid_svga.h> #include <86box/vid_svga_render.h> +typedef struct paradise_t { + svga_t svga; -typedef struct paradise_t -{ - svga_t svga; - - rom_t bios_rom; - - uint8_t bank_mask; - - enum - { - PVGA1A = 0, - WD90C11, - WD90C30 - } type; + rom_t bios_rom; - uint32_t vram_mask; + uint8_t bank_mask; - uint32_t read_bank[4], write_bank[4]; - - int interlace; - int check, check2; - - struct { - uint8_t reg_block_ptr; - uint8_t reg_idx; - uint8_t disable_autoinc; - - uint16_t int_status; - uint16_t blt_ctrl1, blt_ctrl2; - uint16_t srclow, srchigh; - uint16_t dstlow, dsthigh; + enum { + PVGA1A = 0, + WD90C11, + WD90C30 + } type; - uint32_t srcaddr, dstaddr; - - int invalid_block; - } accel; + uint32_t vram_mask; + + uint32_t read_bank[4], write_bank[4]; + + int interlace; + int check, check2; + + struct { + uint8_t reg_block_ptr; + uint8_t reg_idx; + uint8_t disable_autoinc; + + uint16_t int_status; + uint16_t blt_ctrl1, blt_ctrl2; + uint16_t srclow, srchigh; + uint16_t dstlow, dsthigh; + + uint32_t srcaddr, dstaddr; + + int invalid_block; + } accel; } paradise_t; -static video_timings_t timing_paradise_pvga1a = {VIDEO_ISA, 6, 8, 16, 6, 8, 16}; -static video_timings_t timing_paradise_wd90c = {VIDEO_ISA, 3, 3, 6, 5, 5, 10}; +static video_timings_t timing_paradise_pvga1a = { .type = VIDEO_ISA, .write_b = 6, .write_w = 8, .write_l = 16, .read_b = 6, .read_w = 8, .read_l = 16 }; +static video_timings_t timing_paradise_wd90c = { .type = VIDEO_ISA, .write_b = 3, .write_w = 3, .write_l = 6, .read_b = 5, .read_w = 5, .read_l = 10 }; void paradise_remap(paradise_t *paradise); -void paradise_out(uint16_t addr, uint8_t val, void *p) +uint8_t +paradise_in(uint16_t addr, void *priv) { - paradise_t *paradise = (paradise_t *)p; - svga_t *svga = ¶dise->svga; - uint8_t old; - - if (paradise->vram_mask <= ((512 << 10) - 1)) - paradise->bank_mask = 0x7f; - else - paradise->bank_mask = 0xff; - - if (((addr & 0xfff0) == 0x3d0 || (addr & 0xfff0) == 0x3b0) && !(svga->miscout & 1)) - addr ^= 0x60; + paradise_t *paradise = (paradise_t *) priv; + svga_t *svga = ¶dise->svga; - switch (addr) - { - case 0x3c5: - if (svga->seqaddr > 7) { - if (paradise->type < WD90C11 || svga->seqregs[6] != 0x48) - return; - svga->seqregs[svga->seqaddr & 0x1f] = val; - if (svga->seqaddr == 0x11) { - paradise_remap(paradise); - } - return; + if (((addr & 0xfff0) == 0x3d0 || (addr & 0xfff0) == 0x3b0) && !(svga->miscout & 1)) + addr ^= 0x60; + + switch (addr) { + case 0x3c5: + if (svga->seqaddr > 7) { + if (paradise->type < WD90C11 || svga->seqregs[6] != 0x48) + return 0xff; + if (svga->seqaddr > 0x12) + return 0xff; + return svga->seqregs[svga->seqaddr & 0x1f]; + } + break; + + case 0x3c6: + case 0x3c7: + case 0x3c8: + case 0x3c9: + if (paradise->type == WD90C30) + return sc1148x_ramdac_in(addr, 0, svga->ramdac, svga); + return svga_in(addr, svga); + + case 0x3cf: + if (svga->gdcaddr >= 9 && svga->gdcaddr <= 0x0e) { + if (svga->gdcreg[0x0f] & 0x10) + return 0xff; + } + switch (svga->gdcaddr) { + case 0x0b: + if (paradise->type == WD90C30) { + if (paradise->vram_mask == ((512 << 10) - 1)) { + svga->gdcreg[0x0b] |= 0xc0; + svga->gdcreg[0x0b] &= ~0x40; + } + } + return svga->gdcreg[0x0b]; + + case 0x0f: + return (svga->gdcreg[0x0f] & 0x17) | 0x80; + + default: + break; + } + break; + + case 0x3D4: + return svga->crtcreg; + case 0x3D5: + if ((paradise->type == PVGA1A) && (svga->crtcreg & 0x20)) + return 0xff; + if (svga->crtcreg > 0x29 && svga->crtcreg < 0x30 && (svga->crtc[0x29] & 0x88) != 0x80) + return 0xff; + return svga->crtc[svga->crtcreg]; + + default: + break; + } + return svga_in(addr, svga); +} + +void +paradise_out(uint16_t addr, uint8_t val, void *priv) +{ + paradise_t *paradise = (paradise_t *) priv; + svga_t *svga = ¶dise->svga; + uint8_t old; + + if (paradise->vram_mask <= ((512 << 10) - 1)) + paradise->bank_mask = 0x7f; + else + paradise->bank_mask = 0xff; + + if (((addr & 0xfff0) == 0x3d0 || (addr & 0xfff0) == 0x3b0) && !(svga->miscout & 1)) + addr ^= 0x60; + + switch (addr) { + case 0x3c5: + if (svga->seqaddr > 7) { + if (paradise->type < WD90C11 || svga->seqregs[6] != 0x48) + return; + svga->seqregs[svga->seqaddr & 0x1f] = val; + if (svga->seqaddr == 0x11) { + paradise_remap(paradise); } - break; - - case 0x3c6: case 0x3c7: case 0x3c8: case 0x3c9: - if (paradise->type == WD90C30) - sc1148x_ramdac_out(addr, 0, val, svga->ramdac, svga); - else - svga_out(addr, val, svga); - return; - - case 0x3cf: - if (svga->gdcaddr >= 9 && svga->gdcaddr <= 0x0e) { - if ((svga->gdcreg[0x0f] & 7) != 5) - return; - } - - switch (svga->gdcaddr) { - case 6: - if ((svga->gdcreg[6] & 0x0c) != (val & 0x0c)) { - switch (val & 0x0c) { - case 0x00: /*128k at A0000*/ - mem_mapping_set_addr(&svga->mapping, 0xa0000, 0x20000); - svga->banked_mask = 0xffff; - break; - case 0x04: /*64k at A0000*/ - mem_mapping_set_addr(&svga->mapping, 0xa0000, 0x10000); - svga->banked_mask = 0xffff; - break; - case 0x08: /*32k at B0000*/ - mem_mapping_set_addr(&svga->mapping, 0xb0000, 0x08000); - svga->banked_mask = 0x7fff; - break; - case 0x0c: /*32k at B8000*/ - mem_mapping_set_addr(&svga->mapping, 0xb8000, 0x08000); - svga->banked_mask = 0x7fff; - break; - } - } - svga->gdcreg[6] = val; - paradise_remap(paradise); - return; - - case 9: - case 0x0a: - svga->gdcreg[svga->gdcaddr] = val & paradise->bank_mask; - paradise_remap(paradise); - return; - case 0x0b: - svga->gdcreg[0x0b] = val; - paradise_remap(paradise); - return; - } - break; - - case 0x3D4: - svga->crtcreg = val & 0x3f; return; - case 0x3D5: - if ((paradise->type == PVGA1A) && (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); - if (svga->crtcreg > 0x29 && (svga->crtc[0x29] & 7) != 5) - return; - if (svga->crtcreg >= 0x31 && svga->crtcreg <= 0x37) - return; - 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; + + case 0x3c6: + case 0x3c7: + case 0x3c8: + case 0x3c9: + if (paradise->type == WD90C30) + sc1148x_ramdac_out(addr, 0, val, svga->ramdac, svga); + else + svga_out(addr, val, svga); + return; + + case 0x3cf: + if (svga->gdcaddr >= 9 && svga->gdcaddr <= 0x0e) { + if ((svga->gdcreg[0x0f] & 7) != 5) + return; + } + + switch (svga->gdcaddr) { + case 6: + if ((svga->gdcreg[6] & 0x0c) != (val & 0x0c)) { + switch (val & 0x0c) { + case 0x00: /*128k at A0000*/ + mem_mapping_set_addr(&svga->mapping, 0xa0000, 0x20000); + svga->banked_mask = 0xffff; + break; + case 0x04: /*64k at A0000*/ + mem_mapping_set_addr(&svga->mapping, 0xa0000, 0x10000); + svga->banked_mask = 0xffff; + break; + case 0x08: /*32k at B0000*/ + mem_mapping_set_addr(&svga->mapping, 0xb0000, 0x08000); + svga->banked_mask = 0x7fff; + break; + case 0x0c: /*32k at B8000*/ + mem_mapping_set_addr(&svga->mapping, 0xb8000, 0x08000); + svga->banked_mask = 0x7fff; + break; + + default: + break; } + } + svga->gdcreg[6] = val; + paradise_remap(paradise); + return; + + case 9: + case 0x0a: + svga->gdcreg[svga->gdcaddr] = val & paradise->bank_mask; + paradise_remap(paradise); + return; + case 0x0b: + svga->gdcreg[0x0b] = val; + paradise_remap(paradise); + return; + + default: + break; + } + break; + + case 0x3D4: + svga->crtcreg = val & 0x3f; + return; + case 0x3D5: + if ((paradise->type == PVGA1A) && (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); + if (svga->crtcreg > 0x29 && (svga->crtc[0x29] & 7) != 5) + return; + if (svga->crtcreg >= 0x31 && svga->crtcreg <= 0x37) + return; + 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; + } + break; + + case 0x46e8: + io_removehandler(0x03c0, 0x0020, paradise_in, NULL, NULL, paradise_out, NULL, NULL, paradise); + mem_mapping_disable(¶dise->svga.mapping); + if (val & 8) { + io_sethandler(0x03c0, 0x0020, paradise_in, NULL, NULL, paradise_out, NULL, NULL, paradise); + mem_mapping_enable(¶dise->svga.mapping); + } + break; + + default: + break; + } + + svga_out(addr, val, svga); +} + +void +paradise_remap(paradise_t *paradise) +{ + const svga_t *svga = ¶dise->svga; + + paradise->check = 0; + + if (svga->seqregs[0x11] & 0x80) { + paradise->read_bank[0] = paradise->read_bank[2] = svga->gdcreg[9] << 12; + paradise->read_bank[1] = paradise->read_bank[3] = (svga->gdcreg[9] << 12) + ((svga->gdcreg[6] & 0x08) ? 0 : 0x8000); + paradise->write_bank[0] = paradise->write_bank[2] = svga->gdcreg[0x0a] << 12; + paradise->write_bank[1] = paradise->write_bank[3] = (svga->gdcreg[0x0a] << 12) + ((svga->gdcreg[6] & 0x08) ? 0 : 0x8000); + } else if (svga->gdcreg[0x0b] & 0x08) { + if (svga->gdcreg[6] & 0x0c) { + paradise->read_bank[0] = paradise->read_bank[2] = svga->gdcreg[0x0a] << 12; + paradise->write_bank[0] = paradise->write_bank[2] = svga->gdcreg[0x0a] << 12; + paradise->read_bank[1] = paradise->read_bank[3] = (svga->gdcreg[9] << 12) + ((svga->gdcreg[6] & 0x08) ? 0 : 0x8000); + paradise->write_bank[1] = paradise->write_bank[3] = (svga->gdcreg[9] << 12) + ((svga->gdcreg[6] & 0x08) ? 0 : 0x8000); + } else { + paradise->read_bank[0] = paradise->write_bank[0] = svga->gdcreg[0x0a] << 12; + paradise->read_bank[1] = paradise->write_bank[1] = (svga->gdcreg[0xa] << 12) + ((svga->gdcreg[6] & 0x08) ? 0 : 0x8000); + paradise->read_bank[2] = paradise->write_bank[2] = svga->gdcreg[9] << 12; + paradise->read_bank[3] = paradise->write_bank[3] = (svga->gdcreg[9] << 12) + ((svga->gdcreg[6] & 0x08) ? 0 : 0x8000); } - - svga_out(addr, val, svga); + } else { + paradise->read_bank[0] = paradise->read_bank[2] = svga->gdcreg[9] << 12; + paradise->read_bank[1] = paradise->read_bank[3] = (svga->gdcreg[9] << 12) + ((svga->gdcreg[6] & 0x08) ? 0 : 0x8000); + paradise->write_bank[0] = paradise->write_bank[2] = svga->gdcreg[9] << 12; + paradise->write_bank[1] = paradise->write_bank[3] = (svga->gdcreg[9] << 12) + ((svga->gdcreg[6] & 0x08) ? 0 : 0x8000); + } + + if (((svga->gdcreg[0x0b] & 0xc0) == 0xc0) && !svga->chain4 && (svga->crtc[0x14] & 0x40) && ((svga->gdcreg[6] >> 2) & 3) == 1) + paradise->check = 1; + + if (paradise->bank_mask == 0x7f) { + paradise->read_bank[1] &= 0x7ffff; + paradise->write_bank[1] &= 0x7ffff; + } } -uint8_t paradise_in(uint16_t addr, void *p) +void +paradise_recalctimings(svga_t *svga) { - paradise_t *paradise = (paradise_t *)p; - svga_t *svga = ¶dise->svga; - - if (((addr & 0xfff0) == 0x3d0 || (addr & 0xfff0) == 0x3b0) && !(svga->miscout & 1)) - addr ^= 0x60; - - switch (addr) - { - case 0x3c5: - if (svga->seqaddr > 7) - { - if (paradise->type < WD90C11 || svga->seqregs[6] != 0x48) - return 0xff; - if (svga->seqaddr > 0x12) - return 0xff; - return svga->seqregs[svga->seqaddr & 0x1f]; - } - break; + const paradise_t *paradise = (paradise_t *) svga->priv; - case 0x3c6: case 0x3c7: case 0x3c8: case 0x3c9: - if (paradise->type == WD90C30) - return sc1148x_ramdac_in(addr, 0, svga->ramdac, svga); - return svga_in(addr, svga); + svga->lowres = !(svga->gdcreg[0x0e] & 0x01); - case 0x3cf: - if (svga->gdcaddr >= 9 && svga->gdcaddr <= 0x0e) { - if (svga->gdcreg[0x0f] & 0x10) - return 0xff; - } - switch (svga->gdcaddr) { - case 0x0b: - if (paradise->type == WD90C30) { - if (paradise->vram_mask == ((512 << 10) - 1)) { - svga->gdcreg[0x0b] |= 0xc0; - svga->gdcreg[0x0b] &= ~0x40; - } - } - return svga->gdcreg[0x0b]; - - case 0x0f: - return (svga->gdcreg[0x0f] & 0x17) | 0x80; - } - break; + if (paradise->type == WD90C30) { + if (svga->crtc[0x3e] & 0x01) + svga->vtotal |= 0x400; + if (svga->crtc[0x3e] & 0x02) + svga->dispend |= 0x400; + if (svga->crtc[0x3e] & 0x04) + svga->vsyncstart |= 0x400; + if (svga->crtc[0x3e] & 0x08) + svga->vblankstart |= 0x400; + if (svga->crtc[0x3e] & 0x10) + svga->split |= 0x400; - case 0x3D4: - return svga->crtcreg; - case 0x3D5: - if ((paradise->type == PVGA1A) && (svga->crtcreg & 0x20)) - return 0xff; - if (svga->crtcreg > 0x29 && svga->crtcreg < 0x30 && (svga->crtc[0x29] & 0x88) != 0x80) - return 0xff; - return svga->crtc[svga->crtcreg]; + svga->interlace = !!(svga->crtc[0x2d] & 0x20); + + if (!svga->interlace && svga->lowres && (svga->hdisp >= 1024) && ((svga->gdcreg[5] & 0x60) == 0) && (svga->miscout >= 0x27) && (svga->miscout <= 0x2f) && ((svga->gdcreg[6] & 1) || (svga->attrregs[0x10] & 1))) { /*Horrible tweak to re-enable the interlace after returning to + a windowed DOS box in Win3.x*/ + svga->interlace = 1; } - return svga_in(addr, svga); -} + } -void paradise_remap(paradise_t *paradise) -{ - svga_t *svga = ¶dise->svga; - paradise->check = 0; + if (!(svga->gdcreg[6] & 1) && !(svga->attrregs[0x10] & 1)) { /*Text mode*/ + svga->interlace = 0; + } - if (svga->seqregs[0x11] & 0x80) { - paradise->read_bank[0] = paradise->read_bank[2] = svga->gdcreg[9] << 12; - paradise->read_bank[1] = paradise->read_bank[3] = (svga->gdcreg[9] << 12) + ((svga->gdcreg[6] & 0x08) ? 0 : 0x8000); - paradise->write_bank[0] = paradise->write_bank[2] = svga->gdcreg[0x0a] << 12; - paradise->write_bank[1] = paradise->write_bank[3] = (svga->gdcreg[0x0a] << 12) + ((svga->gdcreg[6] & 0x08) ? 0 : 0x8000); - } else if (svga->gdcreg[0x0b] & 0x08) { - if (svga->gdcreg[6] & 0x0c) { - paradise->read_bank[0] = paradise->read_bank[2] = svga->gdcreg[0x0a] << 12; - paradise->write_bank[0] = paradise->write_bank[2] = svga->gdcreg[0x0a] << 12; - paradise->read_bank[1] = paradise->read_bank[3] = (svga->gdcreg[9] << 12) + ((svga->gdcreg[6] & 0x08) ? 0 : 0x8000); - paradise->write_bank[1] = paradise->write_bank[3] = (svga->gdcreg[9] << 12) + ((svga->gdcreg[6] & 0x08) ? 0 : 0x8000); - } else { - paradise->read_bank[0] = paradise->write_bank[0] = svga->gdcreg[0x0a] << 12; - paradise->read_bank[1] = paradise->write_bank[1] = (svga->gdcreg[0xa] << 12) + ((svga->gdcreg[6] & 0x08) ? 0 : 0x8000); - paradise->read_bank[2] = paradise->write_bank[2] = svga->gdcreg[9] << 12; - paradise->read_bank[3] = paradise->write_bank[3] = (svga->gdcreg[9] << 12) + ((svga->gdcreg[6] & 0x08) ? 0 : 0x8000); - } - } else { - paradise->read_bank[0] = paradise->read_bank[2] = svga->gdcreg[9] << 12; - paradise->read_bank[1] = paradise->read_bank[3] = (svga->gdcreg[9] << 12) + ((svga->gdcreg[6] & 0x08) ? 0 : 0x8000); - paradise->write_bank[0] = paradise->write_bank[2] = svga->gdcreg[9] << 12; - paradise->write_bank[1] = paradise->write_bank[3] = (svga->gdcreg[9] << 12) + ((svga->gdcreg[6] & 0x08) ? 0 : 0x8000); - } - - if ((((svga->gdcreg[0x0b] & 0xc0) == 0xc0) && !svga->chain4 && (svga->crtc[0x14] & 0x40) && ((svga->gdcreg[6] >> 2) & 3) == 1)) - paradise->check = 1; - - if (paradise->bank_mask == 0x7f) { - paradise->read_bank[1] &= 0x7ffff; - paradise->write_bank[1] &= 0x7ffff; - } -} - -void paradise_recalctimings(svga_t *svga) -{ - paradise_t *paradise = (paradise_t *) svga->p; - - svga->lowres = !(svga->gdcreg[0x0e] & 0x01); - - if (paradise->type == WD90C30) { - if (svga->crtc[0x3e] & 0x01) svga->vtotal |= 0x400; - if (svga->crtc[0x3e] & 0x02) svga->dispend |= 0x400; - if (svga->crtc[0x3e] & 0x04) svga->vsyncstart |= 0x400; - if (svga->crtc[0x3e] & 0x08) svga->vblankstart |= 0x400; - if (svga->crtc[0x3e] & 0x10) svga->split |= 0x400; - - svga->interlace = !!(svga->crtc[0x2d] & 0x20); - - if (!svga->interlace && svga->lowres && (svga->hdisp >= 1024) && - ((svga->gdcreg[5] & 0x60) == 0) && (svga->miscout >= 0x27) && - (svga->miscout <= 0x2f) && ((svga->gdcreg[6] & 1) || - (svga->attrregs[0x10] & 1))) { /*Horrible tweak to re-enable the interlace after returning to - a windowed DOS box in Win3.x*/ - svga->interlace = 1; - } - } - - if (paradise->type < WD90C30) { - if (svga->bpp >= 8 && !svga->lowres) { - svga->render = svga_render_8bpp_highres; - } - } else { - if (svga->bpp >= 8 && !svga->lowres) { - if (svga->bpp == 16) { - svga->render = svga_render_16bpp_highres; - svga->hdisp >>= 1; - } else if (svga->bpp == 15) { - svga->render = svga_render_15bpp_highres; - svga->hdisp >>= 1; - } else { - svga->render = svga_render_8bpp_highres; - } - } - } -} - -static void paradise_write(uint32_t addr, uint8_t val, void *p) -{ - paradise_t *paradise = (paradise_t *)p; - svga_t *svga = ¶dise->svga; - uint32_t prev_addr, prev_addr2; - - addr = (addr & 0x7fff) + paradise->write_bank[(addr >> 15) & 3]; - - /*Could be done in a better way but it works.*/ - if (!svga->lowres) { - if (paradise->check) { - prev_addr = addr & 3; - prev_addr2 = addr & 0xfffc; - if ((addr & 3) == 3) { - if ((addr & 0x30000) == 0x20000) - addr = (addr >> 16) | (prev_addr << 16) | prev_addr2; - else if ((addr & 0x30000) == 0x10000) - addr = (addr >> 16) | (prev_addr << 16) | prev_addr2; - else if ((addr & 0x30000) == 0x00000) - addr = (addr >> 16) | (prev_addr << 16) | prev_addr2; - } else if ((addr & 3) == 2) { - if ((addr & 0x30000) == 0x30000) - addr = (addr >> 16) | (prev_addr << 16) | prev_addr2; - else if ((addr & 0x30000) == 0x10000) - addr = (addr >> 16) | (prev_addr << 16) | prev_addr2; - else if ((addr & 0x30000) == 0x00000) - addr = (addr >> 16) | (prev_addr << 16) | prev_addr2; - } else if ((addr & 3) == 1) { - if ((addr & 0x30000) == 0x30000) - addr = (addr >> 16) | (prev_addr << 16) | prev_addr2; - else if ((addr & 0x30000) == 0x20000) - addr = (addr >> 16) | (prev_addr << 16) | prev_addr2; - else if ((addr & 0x30000) == 0x00000) - addr = (addr >> 16) | (prev_addr << 16) | prev_addr2; - } else if ((addr & 3) == 0) { - if ((addr & 0x30000) == 0x30000) - addr = (addr >> 16) | (prev_addr << 16) | prev_addr2; - else if ((addr & 0x30000) == 0x20000) - addr = (addr >> 16) | (prev_addr << 16) | prev_addr2; - else if ((addr & 0x30000) == 0x10000) - addr = (addr >> 16) | (prev_addr << 16) | prev_addr2; - } - } - } - - svga_write_linear(addr, val, svga); -} -static void paradise_writew(uint32_t addr, uint16_t val, void *p) -{ - paradise_t *paradise = (paradise_t *)p; - svga_t *svga = ¶dise->svga; - uint32_t prev_addr, prev_addr2; - - addr = (addr & 0x7fff) + paradise->write_bank[(addr >> 15) & 3]; - - /*Could be done in a better way but it works.*/ - if (!svga->lowres) { - if (paradise->check) { - prev_addr = addr & 3; - prev_addr2 = addr & 0xfffc; - if ((addr & 3) == 3) { - if ((addr & 0x30000) == 0x20000) - addr = (addr >> 16) | (prev_addr << 16) | prev_addr2; - else if ((addr & 0x30000) == 0x10000) - addr = (addr >> 16) | (prev_addr << 16) | prev_addr2; - else if ((addr & 0x30000) == 0x00000) - addr = (addr >> 16) | (prev_addr << 16) | prev_addr2; - } else if ((addr & 3) == 2) { - if ((addr & 0x30000) == 0x30000) - addr = (addr >> 16) | (prev_addr << 16) | prev_addr2; - else if ((addr & 0x30000) == 0x10000) - addr = (addr >> 16) | (prev_addr << 16) | prev_addr2; - else if ((addr & 0x30000) == 0x00000) - addr = (addr >> 16) | (prev_addr << 16) | prev_addr2; - } else if ((addr & 3) == 1) { - if ((addr & 0x30000) == 0x30000) - addr = (addr >> 16) | (prev_addr << 16) | prev_addr2; - else if ((addr & 0x30000) == 0x20000) - addr = (addr >> 16) | (prev_addr << 16) | prev_addr2; - else if ((addr & 0x30000) == 0x00000) - addr = (addr >> 16) | (prev_addr << 16) | prev_addr2; - } else if ((addr & 3) == 0) { - if ((addr & 0x30000) == 0x30000) - addr = (addr >> 16) | (prev_addr << 16) | prev_addr2; - else if ((addr & 0x30000) == 0x20000) - addr = (addr >> 16) | (prev_addr << 16) | prev_addr2; - else if ((addr & 0x30000) == 0x10000) - addr = (addr >> 16) | (prev_addr << 16) | prev_addr2; - } - } - } - - svga_writew_linear(addr, val, svga); -} - -static uint8_t paradise_read(uint32_t addr, void *p) -{ - paradise_t *paradise = (paradise_t *)p; - svga_t *svga = ¶dise->svga; - uint32_t prev_addr, prev_addr2; - - addr = (addr & 0x7fff) + paradise->read_bank[(addr >> 15) & 3]; - - /*Could be done in a better way but it works.*/ - if (!svga->lowres) { - if (paradise->check) { - prev_addr = addr & 3; - prev_addr2 = addr & 0xfffc; - if ((addr & 3) == 3) { - if ((addr & 0x30000) == 0x20000) - addr = (addr >> 16) | (prev_addr << 16) | prev_addr2; - else if ((addr & 0x30000) == 0x10000) - addr = (addr >> 16) | (prev_addr << 16) | prev_addr2; - else if ((addr & 0x30000) == 0x00000) - addr = (addr >> 16) | (prev_addr << 16) | prev_addr2; - } else if ((addr & 3) == 2) { - if ((addr & 0x30000) == 0x30000) - addr = (addr >> 16) | (prev_addr << 16) | prev_addr2; - else if ((addr & 0x30000) == 0x10000) - addr = (addr >> 16) | (prev_addr << 16) | prev_addr2; - else if ((addr & 0x30000) == 0x00000) - addr = (addr >> 16) | (prev_addr << 16) | prev_addr2; - } else if ((addr & 3) == 1) { - if ((addr & 0x30000) == 0x30000) - addr = (addr >> 16) | (prev_addr << 16) | prev_addr2; - else if ((addr & 0x30000) == 0x20000) - addr = (addr >> 16) | (prev_addr << 16) | prev_addr2; - else if ((addr & 0x30000) == 0x00000) - addr = (addr >> 16) | (prev_addr << 16) | prev_addr2; - } else if ((addr & 3) == 0) { - if ((addr & 0x30000) == 0x30000) - addr = (addr >> 16) | (prev_addr << 16) | prev_addr2; - else if ((addr & 0x30000) == 0x20000) - addr = (addr >> 16) | (prev_addr << 16) | prev_addr2; - else if ((addr & 0x30000) == 0x10000) - addr = (addr >> 16) | (prev_addr << 16) | prev_addr2; - } - } - } - - return svga_read_linear(addr, svga); -} -static uint16_t paradise_readw(uint32_t addr, void *p) -{ - paradise_t *paradise = (paradise_t *)p; - svga_t *svga = ¶dise->svga; - uint32_t prev_addr, prev_addr2; - - addr = (addr & 0x7fff) + paradise->read_bank[(addr >> 15) & 3]; - - /*Could be done in a better way but it works.*/ - if (!svga->lowres) { - if (paradise->check) { - prev_addr = addr & 3; - prev_addr2 = addr & 0xfffc; - if ((addr & 3) == 3) { - if ((addr & 0x30000) == 0x20000) - addr = (addr >> 16) | (prev_addr << 16) | prev_addr2; - else if ((addr & 0x30000) == 0x10000) - addr = (addr >> 16) | (prev_addr << 16) | prev_addr2; - else if ((addr & 0x30000) == 0x00000) - addr = (addr >> 16) | (prev_addr << 16) | prev_addr2; - } else if ((addr & 3) == 2) { - if ((addr & 0x30000) == 0x30000) - addr = (addr >> 16) | (prev_addr << 16) | prev_addr2; - else if ((addr & 0x30000) == 0x10000) - addr = (addr >> 16) | (prev_addr << 16) | prev_addr2; - else if ((addr & 0x30000) == 0x00000) - addr = (addr >> 16) | (prev_addr << 16) | prev_addr2; - } else if ((addr & 3) == 1) { - if ((addr & 0x30000) == 0x30000) - addr = (addr >> 16) | (prev_addr << 16) | prev_addr2; - else if ((addr & 0x30000) == 0x20000) - addr = (addr >> 16) | (prev_addr << 16) | prev_addr2; - else if ((addr & 0x30000) == 0x00000) - addr = (addr >> 16) | (prev_addr << 16) | prev_addr2; - } else if ((addr & 3) == 0) { - if ((addr & 0x30000) == 0x30000) - addr = (addr >> 16) | (prev_addr << 16) | prev_addr2; - else if ((addr & 0x30000) == 0x20000) - addr = (addr >> 16) | (prev_addr << 16) | prev_addr2; - else if ((addr & 0x30000) == 0x10000) - addr = (addr >> 16) | (prev_addr << 16) | prev_addr2; - } - } - } - - return svga_readw_linear(addr, svga); -} - -void *paradise_init(const device_t *info, uint32_t memsize) -{ - paradise_t *paradise = malloc(sizeof(paradise_t)); - svga_t *svga = ¶dise->svga; - memset(paradise, 0, sizeof(paradise_t)); - - if (info->local == PVGA1A) - video_inform(VIDEO_FLAG_TYPE_SPECIAL, &timing_paradise_pvga1a); - else - video_inform(VIDEO_FLAG_TYPE_SPECIAL, &timing_paradise_wd90c); - - switch(info->local) { - case PVGA1A: - svga_init(info, svga, paradise, memsize, /*256kb*/ - paradise_recalctimings, - paradise_in, paradise_out, - NULL, - NULL); - paradise->vram_mask = memsize - 1; - svga->decode_mask = memsize - 1; - break; - case WD90C11: - svga_init(info, svga, paradise, 1 << 19, /*512kb*/ - paradise_recalctimings, - paradise_in, paradise_out, - NULL, - NULL); - paradise->vram_mask = (1 << 19) - 1; - svga->decode_mask = (1 << 19) - 1; - break; - case WD90C30: - svga_init(info, svga, paradise, memsize, - paradise_recalctimings, - paradise_in, paradise_out, - NULL, - NULL); - paradise->vram_mask = memsize - 1; - svga->decode_mask = memsize - 1; - svga->ramdac = device_add(&sc11487_ramdac_device); /*Actually a Winbond W82c487-80, probably a clone.*/ - break; - } - - mem_mapping_set_handler(&svga->mapping, paradise_read, paradise_readw, NULL, paradise_write, paradise_writew, NULL); - mem_mapping_set_p(&svga->mapping, paradise); - - io_sethandler(0x03c0, 0x0020, paradise_in, NULL, NULL, paradise_out, NULL, NULL, paradise); - - /* Common to all three types. */ - svga->crtc[0x31] = 'W'; - svga->crtc[0x32] = 'D'; - svga->crtc[0x33] = '9'; - svga->crtc[0x34] = '0'; - svga->crtc[0x35] = 'C'; - - switch(info->local) { - case WD90C11: - svga->crtc[0x36] = '1'; - svga->crtc[0x37] = '1'; - break; - case WD90C30: - svga->crtc[0x36] = '3'; - svga->crtc[0x37] = '0'; - break; - } - - svga->bpp = 8; - svga->miscout = 1; - - paradise->type = info->local; - - return paradise; -} - -static void *paradise_pvga1a_ncr3302_init(const device_t *info) -{ - paradise_t *paradise = paradise_init(info, 1 << 18); - - if (paradise) - rom_init(¶dise->bios_rom, "roms/machines/3302/c000-wd_1987-1989-740011-003058-019c.bin", 0xc0000, 0x8000, 0x7fff, 0, MEM_MAPPING_EXTERNAL); - - return paradise; -} - -static void *paradise_pvga1a_pc2086_init(const device_t *info) -{ - paradise_t *paradise = paradise_init(info, 1 << 18); - - if (paradise) - rom_init(¶dise->bios_rom, "roms/machines/pc2086/40186.ic171", 0xc0000, 0x8000, 0x7fff, 0, MEM_MAPPING_EXTERNAL); - - return paradise; -} - -static void *paradise_pvga1a_pc3086_init(const device_t *info) -{ - paradise_t *paradise = paradise_init(info, 1 << 18); - - if (paradise) - rom_init(¶dise->bios_rom, "roms/machines/pc3086/c000.bin", 0xc0000, 0x8000, 0x7fff, 0, MEM_MAPPING_EXTERNAL); - - return paradise; -} - -static void *paradise_pvga1a_standalone_init(const device_t *info) -{ - paradise_t *paradise; - uint32_t memory = 512; - - memory = device_get_config_int("memory"); - memory <<= 10; - - paradise = paradise_init(info, memory); - - if (paradise) - rom_init(¶dise->bios_rom, "roms/video/pvga1a/BIOS.BIN", 0xc0000, 0x8000, 0x7fff, 0, MEM_MAPPING_EXTERNAL); - - return paradise; -} - -static int paradise_pvga1a_standalone_available(void) -{ - return rom_present("roms/video/pvga1a/BIOS.BIN"); -} - -static void *paradise_wd90c11_megapc_init(const device_t *info) -{ - paradise_t *paradise = paradise_init(info, 0); - - if (paradise) - rom_init_interleaved(¶dise->bios_rom, - "roms/machines/megapc/41651-bios lo.u18", - "roms/machines/megapc/211253-bios hi.u19", - 0xc0000, 0x8000, 0x7fff, 0, MEM_MAPPING_EXTERNAL); - - return paradise; -} - -static void *paradise_wd90c11_standalone_init(const device_t *info) -{ - paradise_t *paradise = paradise_init(info, 0); - - if (paradise) - rom_init(¶dise->bios_rom, "roms/video/wd90c11/WD90C11.VBI", 0xc0000, 0x8000, 0x7fff, 0, MEM_MAPPING_EXTERNAL); - - return paradise; -} - -static int paradise_wd90c11_standalone_available(void) -{ - return rom_present("roms/video/wd90c11/WD90C11.VBI"); -} - -static void *paradise_wd90c30_standalone_init(const device_t *info) -{ - paradise_t *paradise; - uint32_t memory = 512; - - memory = device_get_config_int("memory"); - memory <<= 10; - - paradise = paradise_init(info, memory); - - if (paradise) - rom_init(¶dise->bios_rom, "roms/video/wd90c30/90C30-LR.VBI", 0xc0000, 0x8000, 0x7fff, 0, MEM_MAPPING_EXTERNAL); - - return paradise; -} - -static int paradise_wd90c30_standalone_available(void) -{ - return rom_present("roms/video/wd90c30/90C30-LR.VBI"); -} - -void paradise_close(void *p) -{ - paradise_t *paradise = (paradise_t *)p; - - svga_close(¶dise->svga); - - free(paradise); -} - -void paradise_speed_changed(void *p) -{ - paradise_t *paradise = (paradise_t *)p; - - svga_recalctimings(¶dise->svga); -} - -void paradise_force_redraw(void *p) -{ - paradise_t *paradise = (paradise_t *)p; - - paradise->svga.fullchange = changeframecount; -} - -const device_t paradise_pvga1a_pc2086_device = -{ - "Paradise PVGA1A (Amstrad PC2086)", - "pvga1a_pc2086", - 0, - PVGA1A, - paradise_pvga1a_pc2086_init, - paradise_close, - NULL, - { NULL }, - paradise_speed_changed, - paradise_force_redraw, - NULL -}; - -const device_t paradise_pvga1a_pc3086_device = -{ - "Paradise PVGA1A (Amstrad PC3086)", - "pvga1a_pc3086", - 0, - PVGA1A, - paradise_pvga1a_pc3086_init, - paradise_close, - NULL, - { NULL }, - paradise_speed_changed, - paradise_force_redraw, - NULL -}; - -static const device_config_t paradise_pvga1a_config[] = -{ - { - "memory", "Memory size", CONFIG_SELECTION, "", 512, "", { 0 }, - { - { - "256 kB", 256 - }, - { - "512 kB", 512 - }, - { - "" - } - } - }, - { - "", "", -1 + if (paradise->type < WD90C30) { + if ((svga->bpp >= 8) && !svga->lowres) { + svga->render = svga_render_8bpp_highres; } -}; - -const device_t paradise_pvga1a_ncr3302_device = -{ - "Paradise PVGA1A (NCR 3302)", - "pvga1a_ncr3302", - 0, - PVGA1A, - paradise_pvga1a_ncr3302_init, - paradise_close, - NULL, - { NULL }, - paradise_speed_changed, - paradise_force_redraw, - paradise_pvga1a_config -}; - -const device_t paradise_pvga1a_device = -{ - "Paradise PVGA1A", - "pvga1a", - DEVICE_ISA, - PVGA1A, - paradise_pvga1a_standalone_init, - paradise_close, - NULL, - { paradise_pvga1a_standalone_available }, - paradise_speed_changed, - paradise_force_redraw, - paradise_pvga1a_config -}; -const device_t paradise_wd90c11_megapc_device = -{ - "Paradise WD90C11 (Amstrad MegaPC)", - "wd90c11_megapc", - 0, - WD90C11, - paradise_wd90c11_megapc_init, - paradise_close, - NULL, - { NULL }, - paradise_speed_changed, - paradise_force_redraw, - NULL -}; -const device_t paradise_wd90c11_device = -{ - "Paradise WD90C11-LR", - "wd90c11", - DEVICE_ISA, - WD90C11, - paradise_wd90c11_standalone_init, - paradise_close, - NULL, - { paradise_wd90c11_standalone_available }, - paradise_speed_changed, - paradise_force_redraw, - NULL -}; - -static const device_config_t paradise_wd90c30_config[] = -{ - { - "memory", "Memory size", CONFIG_SELECTION, "", 1024, "", { 0 }, - { - { - "512 kB", 512 - }, - { - "1 MB", 1024 - }, - { - "" - } - } - }, - { - "", "", -1 + } else { + if ((svga->bpp >= 8) && !svga->lowres) { + if (svga->bpp == 16) { + svga->render = svga_render_16bpp_highres; + svga->hdisp >>= 1; + if (svga->hdisp == 788) + svga->hdisp += 12; + if (svga->hdisp == 800) + svga->ma_latch -= 3; + } else if (svga->bpp == 15) { + svga->render = svga_render_15bpp_highres; + svga->hdisp >>= 1; + if (svga->hdisp == 788) + svga->hdisp += 12; + if (svga->hdisp == 800) + svga->ma_latch -= 3; + } else { + svga->render = svga_render_8bpp_highres; + } } + } + + if (!(svga->gdcreg[6] & 1) && !(svga->attrregs[0x10] & 1)) { /*Text mode*/ + if (svga->hdisp == 360) + svga->hdisp <<= 1; + if (svga->seqregs[1] & 8) { + svga->render = svga_render_text_40; + } else + svga->render = svga_render_text_80; + } +} + +static void +paradise_write(uint32_t addr, uint8_t val, void *priv) +{ + paradise_t *paradise = (paradise_t *) priv; + svga_t *svga = ¶dise->svga; + uint32_t prev_addr; + uint32_t prev_addr2; + + addr = (addr & 0x7fff) + paradise->write_bank[(addr >> 15) & 3]; + + /*Could be done in a better way but it works.*/ + if (!svga->lowres) { + if (paradise->check) { + prev_addr = addr & 3; + prev_addr2 = addr & 0xfffc; + if ((addr & 3) == 3) { + if ((addr & 0x30000) == 0x20000) + addr = (addr >> 16) | (prev_addr << 16) | prev_addr2; + else if ((addr & 0x30000) == 0x10000) + addr = (addr >> 16) | (prev_addr << 16) | prev_addr2; + else if ((addr & 0x30000) == 0x00000) + addr = (addr >> 16) | (prev_addr << 16) | prev_addr2; + } else if ((addr & 3) == 2) { + if ((addr & 0x30000) == 0x30000) + addr = (addr >> 16) | (prev_addr << 16) | prev_addr2; + else if ((addr & 0x30000) == 0x10000) + addr = (addr >> 16) | (prev_addr << 16) | prev_addr2; + else if ((addr & 0x30000) == 0x00000) + addr = (addr >> 16) | (prev_addr << 16) | prev_addr2; + } else if ((addr & 3) == 1) { + if ((addr & 0x30000) == 0x30000) + addr = (addr >> 16) | (prev_addr << 16) | prev_addr2; + else if ((addr & 0x30000) == 0x20000) + addr = (addr >> 16) | (prev_addr << 16) | prev_addr2; + else if ((addr & 0x30000) == 0x00000) + addr = (addr >> 16) | (prev_addr << 16) | prev_addr2; + } else if ((addr & 3) == 0) { + if ((addr & 0x30000) == 0x30000) + addr = (addr >> 16) | (prev_addr << 16) | prev_addr2; + else if ((addr & 0x30000) == 0x20000) + addr = (addr >> 16) | (prev_addr << 16) | prev_addr2; + else if ((addr & 0x30000) == 0x10000) + addr = (addr >> 16) | (prev_addr << 16) | prev_addr2; + } + } + } + + svga_write_linear(addr, val, svga); +} +static void +paradise_writew(uint32_t addr, uint16_t val, void *priv) +{ + paradise_t *paradise = (paradise_t *) priv; + svga_t *svga = ¶dise->svga; + uint32_t prev_addr; + uint32_t prev_addr2; + + addr = (addr & 0x7fff) + paradise->write_bank[(addr >> 15) & 3]; + + /*Could be done in a better way but it works.*/ + if (!svga->lowres) { + if (paradise->check) { + prev_addr = addr & 3; + prev_addr2 = addr & 0xfffc; + if ((addr & 3) == 3) { + if ((addr & 0x30000) == 0x20000) + addr = (addr >> 16) | (prev_addr << 16) | prev_addr2; + else if ((addr & 0x30000) == 0x10000) + addr = (addr >> 16) | (prev_addr << 16) | prev_addr2; + else if ((addr & 0x30000) == 0x00000) + addr = (addr >> 16) | (prev_addr << 16) | prev_addr2; + } else if ((addr & 3) == 2) { + if ((addr & 0x30000) == 0x30000) + addr = (addr >> 16) | (prev_addr << 16) | prev_addr2; + else if ((addr & 0x30000) == 0x10000) + addr = (addr >> 16) | (prev_addr << 16) | prev_addr2; + else if ((addr & 0x30000) == 0x00000) + addr = (addr >> 16) | (prev_addr << 16) | prev_addr2; + } else if ((addr & 3) == 1) { + if ((addr & 0x30000) == 0x30000) + addr = (addr >> 16) | (prev_addr << 16) | prev_addr2; + else if ((addr & 0x30000) == 0x20000) + addr = (addr >> 16) | (prev_addr << 16) | prev_addr2; + else if ((addr & 0x30000) == 0x00000) + addr = (addr >> 16) | (prev_addr << 16) | prev_addr2; + } else if ((addr & 3) == 0) { + if ((addr & 0x30000) == 0x30000) + addr = (addr >> 16) | (prev_addr << 16) | prev_addr2; + else if ((addr & 0x30000) == 0x20000) + addr = (addr >> 16) | (prev_addr << 16) | prev_addr2; + else if ((addr & 0x30000) == 0x10000) + addr = (addr >> 16) | (prev_addr << 16) | prev_addr2; + } + } + } + + svga_writew_linear(addr, val, svga); +} + +static uint8_t +paradise_read(uint32_t addr, void *priv) +{ + paradise_t *paradise = (paradise_t *) priv; + svga_t *svga = ¶dise->svga; + uint32_t prev_addr; + uint32_t prev_addr2; + + addr = (addr & 0x7fff) + paradise->read_bank[(addr >> 15) & 3]; + + /*Could be done in a better way but it works.*/ + if (!svga->lowres) { + if (paradise->check) { + prev_addr = addr & 3; + prev_addr2 = addr & 0xfffc; + if ((addr & 3) == 3) { + if ((addr & 0x30000) == 0x20000) + addr = (addr >> 16) | (prev_addr << 16) | prev_addr2; + else if ((addr & 0x30000) == 0x10000) + addr = (addr >> 16) | (prev_addr << 16) | prev_addr2; + else if ((addr & 0x30000) == 0x00000) + addr = (addr >> 16) | (prev_addr << 16) | prev_addr2; + } else if ((addr & 3) == 2) { + if ((addr & 0x30000) == 0x30000) + addr = (addr >> 16) | (prev_addr << 16) | prev_addr2; + else if ((addr & 0x30000) == 0x10000) + addr = (addr >> 16) | (prev_addr << 16) | prev_addr2; + else if ((addr & 0x30000) == 0x00000) + addr = (addr >> 16) | (prev_addr << 16) | prev_addr2; + } else if ((addr & 3) == 1) { + if ((addr & 0x30000) == 0x30000) + addr = (addr >> 16) | (prev_addr << 16) | prev_addr2; + else if ((addr & 0x30000) == 0x20000) + addr = (addr >> 16) | (prev_addr << 16) | prev_addr2; + else if ((addr & 0x30000) == 0x00000) + addr = (addr >> 16) | (prev_addr << 16) | prev_addr2; + } else if ((addr & 3) == 0) { + if ((addr & 0x30000) == 0x30000) + addr = (addr >> 16) | (prev_addr << 16) | prev_addr2; + else if ((addr & 0x30000) == 0x20000) + addr = (addr >> 16) | (prev_addr << 16) | prev_addr2; + else if ((addr & 0x30000) == 0x10000) + addr = (addr >> 16) | (prev_addr << 16) | prev_addr2; + } + } + } + + return svga_read_linear(addr, svga); +} +static uint16_t +paradise_readw(uint32_t addr, void *priv) +{ + paradise_t *paradise = (paradise_t *) priv; + svga_t *svga = ¶dise->svga; + uint32_t prev_addr; + uint32_t prev_addr2; + + addr = (addr & 0x7fff) + paradise->read_bank[(addr >> 15) & 3]; + + /*Could be done in a better way but it works.*/ + if (!svga->lowres) { + if (paradise->check) { + prev_addr = addr & 3; + prev_addr2 = addr & 0xfffc; + if ((addr & 3) == 3) { + if ((addr & 0x30000) == 0x20000) + addr = (addr >> 16) | (prev_addr << 16) | prev_addr2; + else if ((addr & 0x30000) == 0x10000) + addr = (addr >> 16) | (prev_addr << 16) | prev_addr2; + else if ((addr & 0x30000) == 0x00000) + addr = (addr >> 16) | (prev_addr << 16) | prev_addr2; + } else if ((addr & 3) == 2) { + if ((addr & 0x30000) == 0x30000) + addr = (addr >> 16) | (prev_addr << 16) | prev_addr2; + else if ((addr & 0x30000) == 0x10000) + addr = (addr >> 16) | (prev_addr << 16) | prev_addr2; + else if ((addr & 0x30000) == 0x00000) + addr = (addr >> 16) | (prev_addr << 16) | prev_addr2; + } else if ((addr & 3) == 1) { + if ((addr & 0x30000) == 0x30000) + addr = (addr >> 16) | (prev_addr << 16) | prev_addr2; + else if ((addr & 0x30000) == 0x20000) + addr = (addr >> 16) | (prev_addr << 16) | prev_addr2; + else if ((addr & 0x30000) == 0x00000) + addr = (addr >> 16) | (prev_addr << 16) | prev_addr2; + } else if ((addr & 3) == 0) { + if ((addr & 0x30000) == 0x30000) + addr = (addr >> 16) | (prev_addr << 16) | prev_addr2; + else if ((addr & 0x30000) == 0x20000) + addr = (addr >> 16) | (prev_addr << 16) | prev_addr2; + else if ((addr & 0x30000) == 0x10000) + addr = (addr >> 16) | (prev_addr << 16) | prev_addr2; + } + } + } + + return svga_readw_linear(addr, svga); +} + +void * +paradise_init(const device_t *info, uint32_t memsize) +{ + paradise_t *paradise = malloc(sizeof(paradise_t)); + svga_t *svga = ¶dise->svga; + memset(paradise, 0, sizeof(paradise_t)); + + if (info->local == PVGA1A) + video_inform(VIDEO_FLAG_TYPE_SPECIAL, &timing_paradise_pvga1a); + else + video_inform(VIDEO_FLAG_TYPE_SPECIAL, &timing_paradise_wd90c); + + switch (info->local) { + case PVGA1A: + svga_init(info, svga, paradise, memsize, /*256kb*/ + paradise_recalctimings, + paradise_in, paradise_out, + NULL, + NULL); + paradise->vram_mask = memsize - 1; + svga->decode_mask = memsize - 1; + break; + case WD90C11: + svga_init(info, svga, paradise, 1 << 19, /*512kb*/ + paradise_recalctimings, + paradise_in, paradise_out, + NULL, + NULL); + paradise->vram_mask = (1 << 19) - 1; + svga->decode_mask = (1 << 19) - 1; + break; + case WD90C30: + svga_init(info, svga, paradise, memsize, + paradise_recalctimings, + paradise_in, paradise_out, + NULL, + NULL); + paradise->vram_mask = memsize - 1; + svga->decode_mask = memsize - 1; + svga->ramdac = device_add(&sc11487_ramdac_device); /*Actually a Winbond W82c487-80, probably a clone.*/ + break; + + default: + break; + } + + mem_mapping_set_handler(&svga->mapping, paradise_read, paradise_readw, NULL, paradise_write, paradise_writew, NULL); + mem_mapping_set_p(&svga->mapping, paradise); + + io_sethandler(0x03c0, 0x0020, paradise_in, NULL, NULL, paradise_out, NULL, NULL, paradise); + + /* Common to all three types. */ + svga->crtc[0x31] = 'W'; + svga->crtc[0x32] = 'D'; + svga->crtc[0x33] = '9'; + svga->crtc[0x34] = '0'; + svga->crtc[0x35] = 'C'; + + switch (info->local) { + case WD90C11: + svga->crtc[0x36] = '1'; + svga->crtc[0x37] = '1'; + io_sethandler(0x46e8, 0x0001, paradise_in, NULL, NULL, paradise_out, NULL, NULL, paradise); + break; + case WD90C30: + svga->crtc[0x36] = '3'; + svga->crtc[0x37] = '0'; + break; + + default: + break; + } + + svga->bpp = 8; + svga->miscout = 1; + + paradise->type = info->local; + + return paradise; +} + +static void * +paradise_pvga1a_ncr3302_init(const device_t *info) +{ + paradise_t *paradise = paradise_init(info, 1 << 18); + + if (paradise) + rom_init(¶dise->bios_rom, "roms/machines/3302/c000-wd_1987-1989-740011-003058-019c.bin", 0xc0000, 0x8000, 0x7fff, 0, MEM_MAPPING_EXTERNAL); + + return paradise; +} + +static void * +paradise_pvga1a_pc2086_init(const device_t *info) +{ + paradise_t *paradise = paradise_init(info, 1 << 18); + + if (paradise) + rom_init(¶dise->bios_rom, "roms/machines/pc2086/40186.ic171", 0xc0000, 0x8000, 0x7fff, 0, MEM_MAPPING_EXTERNAL); + + return paradise; +} + +static void * +paradise_pvga1a_pc3086_init(const device_t *info) +{ + paradise_t *paradise = paradise_init(info, 1 << 18); + + if (paradise) + rom_init(¶dise->bios_rom, "roms/machines/pc3086/c000.bin", 0xc0000, 0x8000, 0x7fff, 0, MEM_MAPPING_EXTERNAL); + + return paradise; +} + +static void * +paradise_pvga1a_standalone_init(const device_t *info) +{ + paradise_t *paradise; + uint32_t memory = 512; + + memory = device_get_config_int("memory"); + memory <<= 10; + + paradise = paradise_init(info, memory); + + if (paradise) + rom_init(¶dise->bios_rom, "roms/video/pvga1a/BIOS.BIN", 0xc0000, 0x8000, 0x7fff, 0, MEM_MAPPING_EXTERNAL); + + return paradise; +} + +static int +paradise_pvga1a_standalone_available(void) +{ + return rom_present("roms/video/pvga1a/BIOS.BIN"); +} + +static void * +paradise_wd90c11_megapc_init(const device_t *info) +{ + paradise_t *paradise = paradise_init(info, 0); + + if (paradise) + rom_init_interleaved(¶dise->bios_rom, + "roms/machines/megapc/41651-bios lo.u18", + "roms/machines/megapc/211253-bios hi.u19", + 0xc0000, 0x8000, 0x7fff, 0, MEM_MAPPING_EXTERNAL); + + return paradise; +} + +static void * +paradise_wd90c11_standalone_init(const device_t *info) +{ + paradise_t *paradise = paradise_init(info, 0); + + if (paradise) + rom_init(¶dise->bios_rom, "roms/video/wd90c11/WD90C11.VBI", 0xc0000, 0x8000, 0x7fff, 0, MEM_MAPPING_EXTERNAL); + + return paradise; +} + +static int +paradise_wd90c11_standalone_available(void) +{ + return rom_present("roms/video/wd90c11/WD90C11.VBI"); +} + +static void * +paradise_wd90c30_standalone_init(const device_t *info) +{ + paradise_t *paradise; + uint32_t memory = 512; + + memory = device_get_config_int("memory"); + memory <<= 10; + + paradise = paradise_init(info, memory); + + if (paradise) + rom_init(¶dise->bios_rom, "roms/video/wd90c30/90C30-LR.VBI", 0xc0000, 0x8000, 0x7fff, 0, MEM_MAPPING_EXTERNAL); + + return paradise; +} + +static int +paradise_wd90c30_standalone_available(void) +{ + return rom_present("roms/video/wd90c30/90C30-LR.VBI"); +} + +void +paradise_close(void *priv) +{ + paradise_t *paradise = (paradise_t *) priv; + + svga_close(¶dise->svga); + + free(paradise); +} + +void +paradise_speed_changed(void *priv) +{ + paradise_t *paradise = (paradise_t *) priv; + + svga_recalctimings(¶dise->svga); +} + +void +paradise_force_redraw(void *priv) +{ + paradise_t *paradise = (paradise_t *) priv; + + paradise->svga.fullchange = changeframecount; +} + +const device_t paradise_pvga1a_pc2086_device = { + .name = "Paradise PVGA1A (Amstrad PC2086)", + .internal_name = "pvga1a_pc2086", + .flags = 0, + .local = PVGA1A, + .init = paradise_pvga1a_pc2086_init, + .close = paradise_close, + .reset = NULL, + { .available = NULL }, + .speed_changed = paradise_speed_changed, + .force_redraw = paradise_force_redraw, + .config = NULL }; -const device_t paradise_wd90c30_device = -{ - "Paradise WD90C30-LR", - "wd90c30", - DEVICE_ISA, - WD90C30, - paradise_wd90c30_standalone_init, - paradise_close, - NULL, - { paradise_wd90c30_standalone_available }, - paradise_speed_changed, - paradise_force_redraw, - paradise_wd90c30_config +const device_t paradise_pvga1a_pc3086_device = { + .name = "Paradise PVGA1A (Amstrad PC3086)", + .internal_name = "pvga1a_pc3086", + .flags = 0, + .local = PVGA1A, + .init = paradise_pvga1a_pc3086_init, + .close = paradise_close, + .reset = NULL, + { .available = NULL }, + .speed_changed = paradise_speed_changed, + .force_redraw = paradise_force_redraw, + .config = NULL +}; + +static const device_config_t paradise_pvga1a_config[] = { + // clang-format off + { + .name = "memory", + .description = "Memory size", + .type = CONFIG_SELECTION, + .default_int = 512, + .selection = { + { + .description = "256 kB", + .value = 256 + }, + { + .description = "512 kB", + .value = 512 + }, + { + .description = "" + } + } + }, + { + .type = CONFIG_END + } + // clang-format on +}; + +const device_t paradise_pvga1a_ncr3302_device = { + .name = "Paradise PVGA1A (NCR 3302)", + .internal_name = "pvga1a_ncr3302", + .flags = 0, + .local = PVGA1A, + .init = paradise_pvga1a_ncr3302_init, + .close = paradise_close, + .reset = NULL, + { .available = NULL }, + .speed_changed = paradise_speed_changed, + .force_redraw = paradise_force_redraw, + .config = paradise_pvga1a_config +}; + +const device_t paradise_pvga1a_device = { + .name = "Paradise PVGA1A", + .internal_name = "pvga1a", + .flags = DEVICE_ISA, + .local = PVGA1A, + .init = paradise_pvga1a_standalone_init, + .close = paradise_close, + .reset = NULL, + { .available = paradise_pvga1a_standalone_available }, + .speed_changed = paradise_speed_changed, + .force_redraw = paradise_force_redraw, + .config = paradise_pvga1a_config +}; + +const device_t paradise_wd90c11_megapc_device = { + .name = "Paradise WD90C11 (Amstrad MegaPC)", + .internal_name = "wd90c11_megapc", + .flags = 0, + .local = WD90C11, + .init = paradise_wd90c11_megapc_init, + .close = paradise_close, + .reset = NULL, + { .available = NULL }, + .speed_changed = paradise_speed_changed, + .force_redraw = paradise_force_redraw, + .config = NULL +}; + +const device_t paradise_wd90c11_device = { + .name = "Paradise WD90C11-LR", + .internal_name = "wd90c11", + .flags = DEVICE_ISA, + .local = WD90C11, + .init = paradise_wd90c11_standalone_init, + .close = paradise_close, + .reset = NULL, + { .available = paradise_wd90c11_standalone_available }, + .speed_changed = paradise_speed_changed, + .force_redraw = paradise_force_redraw, + .config = NULL +}; + +static const device_config_t paradise_wd90c30_config[] = { + // clang-format off + { + .name = "memory", + .description = "Memory size", + .type = CONFIG_SELECTION, + .default_int = 1024, + .selection = { + { + .description = "512 kB", + .value = 512 + }, + { + .description = "1 MB", + .value = 1024 + }, + { + .description = "" + } + } + }, + { + .type = CONFIG_END + } + // clang-format on +}; + +const device_t paradise_wd90c30_device = { + .name = "Paradise WD90C30-LR", + .internal_name = "wd90c30", + .flags = DEVICE_ISA, + .local = WD90C30, + .init = paradise_wd90c30_standalone_init, + .close = paradise_close, + .reset = NULL, + { .available = paradise_wd90c30_standalone_available }, + .speed_changed = paradise_speed_changed, + .force_redraw = paradise_force_redraw, + .config = paradise_wd90c30_config }; diff --git a/src/video/vid_pgc.c b/src/video/vid_pgc.c index 6c23ab7df..aa1517ddf 100644 --- a/src/video/vid_pgc.c +++ b/src/video/vid_pgc.c @@ -1,56 +1,56 @@ /* - * 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. + * 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. + * This file is part of the 86Box distribution. * - * This implements just enough of the Professional Graphics - * Controller to act as a basis for the Vermont Microsystems - * IM-1024. + * This implements just enough of the Professional Graphics + * Controller to act as a basis for the Vermont Microsystems + * IM-1024. * - * PGC features implemented include: - * > The CGA-compatible display modes - * > Switching to and from native mode - * > Communicating with the host PC - * - * Numerous features are implemented partially or not at all, - * such as: - * > 2D drawing - * > 3D drawing - * > Command lists - * Some of these are marked TODO. + * PGC features implemented include: + * > The CGA-compatible display modes + * > Switching to and from native mode + * > Communicating with the host PC * - * The PGC has two display modes: CGA (in which it appears in - * the normal CGA memory and I/O ranges) and native (in which - * all functions are accessed through reads and writes to 1K - * of memory at 0xC6000). + * Numerous features are implemented partially or not at all, + * such as: + * > 2D drawing + * > 3D drawing + * > Command lists + * Some of these are marked TODO. * - * The PGC's 8088 processor monitors this buffer and executes - * instructions left there for it. We simulate this behavior - * with a separate thread. + * The PGC has two display modes: CGA (in which it appears in + * the normal CGA memory and I/O ranges) and native (in which + * all functions are accessed through reads and writes to 1K + * of memory at 0xC6000). * - * **NOTE** This driver is not finished yet: + * The PGC's 8088 processor monitors this buffer and executes + * instructions left there for it. We simulate this behavior + * with a separate thread. * - * - cursor will blink at very high speed if used on a machine - * with clock greater than 4.77MHz. We should "scale down" - * this speed, to become relative to a 4.77MHz-based system. + * **NOTE** This driver is not finished yet: * - * - pgc_plot() should be overloaded by clones if they support - * modes other than WRITE and INVERT, like the IM-1024. + * - cursor will blink at very high speed if used on a machine + * with clock greater than 4.77MHz. We should "scale down" + * this speed, to become relative to a 4.77MHz-based system. * - * - test it with the Windows 1.x driver? + * - pgc_plot() should be overloaded by clones if they support + * modes other than WRITE and INVERT, like the IM-1024. * - * This is expected to be done shortly. + * - test it with the Windows 1.x driver? + * + * This is expected to be done shortly. * * * - * Authors: Fred N. van Kempen, - * John Elliott, + * Authors: Fred N. van Kempen, + * John Elliott, * - * Copyright 2019 Fred N. van Kempen. - * Copyright 2019 John Elliott. + * Copyright 2019 Fred N. van Kempen. + * Copyright 2019 John Elliott. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -87,19 +87,18 @@ #include <86box/device.h> #include <86box/pit.h> #include <86box/plat.h> +#include <86box/thread.h> #include <86box/video.h> #include <86box/vid_cga.h> #include <86box/vid_pgc.h> +#define PGC_CGA_WIDTH 640 +#define PGC_CGA_HEIGHT 400 -#define PGC_CGA_WIDTH 640 -#define PGC_CGA_HEIGHT 400 - -#define HWORD(u) ((u) >> 16) -#define LWORD(u) ((u) & 0xffff) - -#define WAKE_DELAY (TIMER_USEC * 500) +#define HWORD(u) ((u) >> 16) +#define LWORD(u) ((u) &0xffff) +#define WAKE_DELAY (TIMER_USEC * 500) static const char *pgc_err_msgs[] = { "Range \r", @@ -113,46 +112,40 @@ static const char *pgc_err_msgs[] = { "Too long\r", "Area \r", "Missing \r", - "Unknown \r" + "Unknown \r" }; - /* Initial palettes */ static const uint32_t init_palette[6][256] = { #include <86box/vid_pgc_palette.h> }; - -static video_timings_t timing_pgc = {VIDEO_ISA, 8, 16, 32, 8, 16, 32}; - +static video_timings_t timing_pgc = { .type = VIDEO_ISA, .write_b = 8, .write_w = 16, .write_l = 32, .read_b = 8, .read_w = 16, .read_l = 32 }; #ifdef ENABLE_PGC_LOG int pgc_do_log = ENABLE_PGC_LOG; - static void pgc_log(const char *fmt, ...) { va_list ap; if (pgc_do_log) { - va_start(ap, fmt); - pclog_ex(fmt, ap); - va_end(ap); + va_start(ap, fmt); + pclog_ex(fmt, ap); + va_end(ap); } } #else -#define pgc_log(fmt, ...) +# define pgc_log(fmt, ...) #endif - static inline int is_whitespace(char ch) { return (ch != 0 && strchr(" \r\n\t,;()+-", ch) != NULL); } - /* * Write a byte to the output buffer. * @@ -163,56 +156,55 @@ static int output_byte(pgc_t *dev, uint8_t val) { /* If output buffer full, wait for it to empty. */ - while (!dev->stopped && dev->mapram[0x302] == (uint8_t)(dev->mapram[0x303] - 1)) { - pgc_log("PGC: output buffer state: %02x %02x Sleeping\n", - dev->mapram[0x302], dev->mapram[0x303]); - dev->waiting_output_fifo = 1; - pgc_sleep(dev); + while (!dev->stopped && dev->mapram[0x302] == (uint8_t) (dev->mapram[0x303] - 1)) { + pgc_log("PGC: output buffer state: %02x %02x Sleeping\n", + dev->mapram[0x302], dev->mapram[0x303]); + dev->waiting_output_fifo = 1; + pgc_sleep(dev); } if (dev->mapram[0x3ff]) { - /* Reset triggered. */ - pgc_reset(dev); - return 0; + /* Reset triggered. */ + pgc_reset(dev); + return 0; } dev->mapram[0x100 + dev->mapram[0x302]] = val; dev->mapram[0x302]++; pgc_log("PGC: output %02x: new state: %02x %02x\n", val, - dev->mapram[0x302], dev->mapram[0x303]); + dev->mapram[0x302], dev->mapram[0x303]); return 1; } - /* Helper to write an entire string to the output buffer. */ static int output_string(pgc_t *dev, const char *s) { while (*s) { - if (! output_byte(dev, *s)) return 0; - s++; + if (!output_byte(dev, *s)) + return 0; + s++; } return 1; } - /* As output_byte, for the error buffer. */ static int error_byte(pgc_t *dev, uint8_t val) { /* If error buffer full, wait for it to empty. */ while (!dev->stopped && dev->mapram[0x304] == dev->mapram[0x305] - 1) { - dev->waiting_error_fifo = 1; - pgc_sleep(dev); + dev->waiting_error_fifo = 1; + pgc_sleep(dev); } if (dev->mapram[0x3ff]) { - /* Reset triggered. */ - pgc_reset(dev); - return 0; + /* Reset triggered. */ + pgc_reset(dev); + return 0; } dev->mapram[0x200 + dev->mapram[0x304]] = val; @@ -221,24 +213,23 @@ error_byte(pgc_t *dev, uint8_t val) return 1; } - /* As output_string, for the error buffer. */ static int error_string(pgc_t *dev, const char *s) { while (*s) { - if (! error_byte(dev, *s)) return 0; - s++; + if (!error_byte(dev, *s)) + return 0; + s++; } return 1; } - /* * Read next byte from the input buffer. * - * If no byte available will sleep until one is. Returns 0 if + * If no byte available will sleep until one is. Returns 0 if * a PGC reset has been triggered by a write to 0xC63FF. */ static int @@ -246,17 +237,17 @@ input_byte(pgc_t *dev, uint8_t *result) { /* If input buffer empty, wait for it to fill. */ while (!dev->stopped && (dev->mapram[0x300] == dev->mapram[0x301])) { - dev->waiting_input_fifo = 1; - pgc_sleep(dev); + dev->waiting_input_fifo = 1; + pgc_sleep(dev); } if (dev->stopped) - return 0; + return 0; if (dev->mapram[0x3ff]) { - /* Reset triggered. */ - pgc_reset(dev); - return 0; + /* Reset triggered. */ + pgc_reset(dev); + return 0; } *result = dev->mapram[dev->mapram[0x301]]; @@ -265,7 +256,6 @@ input_byte(pgc_t *dev, uint8_t *result) return 1; } - /* * Read a byte and interpret as ASCII. * @@ -277,17 +267,17 @@ input_char(pgc_t *dev, char *result) uint8_t ch; while (1) { - if (! dev->inputbyte(dev, &ch)) return 0; + if (!dev->inputbyte(dev, &ch)) + return 0; - ch &= 0x7f; - if (ch == '\r' || ch == '\n' || ch == '\t' || ch >= ' ') { - *result = toupper(ch); - return 1; - } + ch &= 0x7f; + if (ch == '\r' || ch == '\n' || ch == '\t' || ch >= ' ') { + *result = toupper(ch); + return 1; + } } } - /* * Read in the next command. * @@ -297,53 +287,53 @@ static int read_command(pgc_t *dev) { if (dev->stopped) - return 0; + return 0; if (dev->clcur) - return pgc_clist_byte(dev, &dev->hex_command); + return pgc_clist_byte(dev, &dev->hex_command); if (dev->ascii_mode) { - char ch; - int count = 0; + char ch; + int count = 0; - while (count < 7) { - if (dev->stopped) return 0; + while (count < 7) { + if (dev->stopped) + return 0; - if (! input_char(dev, &ch)) return 0; + if (!input_char(dev, &ch)) + return 0; - if (is_whitespace(ch)) { - /* Pad to 6 characters */ - while (count < 6) - dev->asc_command[count++] = ' '; - dev->asc_command[6] = 0; + if (is_whitespace(ch)) { + /* Pad to 6 characters */ + while (count < 6) + dev->asc_command[count++] = ' '; + dev->asc_command[6] = 0; - return 1; - } - dev->asc_command[count++] = toupper(ch); - } + return 1; + } + dev->asc_command[count++] = toupper(ch); + } - return 1; + return 1; } return dev->inputbyte(dev, &dev->hex_command); } - /* Read in the next command and parse it. */ static int parse_command(pgc_t *dev, const pgc_cmd_t **pcmd) { - const pgc_cmd_t *cmd; - char match[7]; + char match[7]; - *pcmd = NULL; + *pcmd = NULL; dev->hex_command = 0; memset(dev->asc_command, ' ', 6); dev->asc_command[6] = 0; - if (! read_command(dev)) { - /* PGC has been reset. */ - return 0; + if (!read_command(dev)) { + /* PGC has been reset. */ + return 0; } /* @@ -352,33 +342,32 @@ parse_command(pgc_t *dev, const pgc_cmd_t **pcmd) * dev->commands may be a subclass list (terminated with '*') * or the core list (terminated with '@') */ - for (cmd = dev->commands; cmd->ascii[0] != '@'; cmd++) { - /* End of subclass command list, chain to core. */ - if (cmd->ascii[0] == '*') - cmd = dev->master; + for (const pgc_cmd_t *cmd = dev->commands; cmd->ascii[0] != '@'; cmd++) { + /* End of subclass command list, chain to core. */ + if (cmd->ascii[0] == '*') + cmd = dev->master; - /* If in ASCII mode match on the ASCII command. */ - if (dev->ascii_mode && !dev->clcur) { - sprintf(match, "%-6.6s", cmd->ascii); - if (! strncmp(match, dev->asc_command, 6)) { - *pcmd = cmd; - dev->hex_command = cmd->hex; - break; - } - } else { - /* Otherwise match on the hex command. */ - if (cmd->hex == dev->hex_command) { - sprintf(dev->asc_command, "%-6.6s", cmd->ascii); - *pcmd = cmd; - break; - } - } + /* If in ASCII mode match on the ASCII command. */ + if (dev->ascii_mode && !dev->clcur) { + sprintf(match, "%-6.6s", cmd->ascii); + if (!strncmp(match, dev->asc_command, 6)) { + *pcmd = cmd; + dev->hex_command = cmd->hex; + break; + } + } else { + /* Otherwise match on the hex command. */ + if (cmd->hex == dev->hex_command) { + sprintf(dev->asc_command, "%-6.6s", cmd->ascii); + *pcmd = cmd; + break; + } + } } return 1; } - /* * Beginning of a command list. * @@ -389,48 +378,47 @@ static void hndl_clbeg(pgc_t *dev) { const pgc_cmd_t *cmd; - uint8_t param = 0; - pgc_cl_t cl; + uint8_t param = 0; + pgc_cl_t cl; - if (! pgc_param_byte(dev, ¶m)) return; + if (!pgc_param_byte(dev, ¶m)) + return; pgc_log("PGC: CLBEG(%i)\n", param); memset(&cl, 0x00, sizeof(pgc_cl_t)); while (1) { - if (! parse_command(dev, &cmd)) { - /* PGC has been reset. */ - return; - } - if (!cmd) { - pgc_error(dev, PGC_ERROR_OPCODE); - return; - } else if (dev->hex_command == 0x71) { - /* CLEND */ - dev->clist[param] = cl; - return; - } else { - if (! pgc_cl_append(&cl, dev->hex_command)) { - pgc_error(dev, PGC_ERROR_OVERFLOW); - return; - } + if (!parse_command(dev, &cmd)) { + /* PGC has been reset. */ + return; + } + if (!cmd) { + pgc_error(dev, PGC_ERROR_OPCODE); + return; + } else if (dev->hex_command == 0x71) { + /* CLEND */ + dev->clist[param] = cl; + return; + } else { + if (!pgc_cl_append(&cl, dev->hex_command)) { + pgc_error(dev, PGC_ERROR_OVERFLOW); + return; + } - if (cmd->parser) { - if (! (*cmd->parser)(dev, &cl, cmd->p)) - return; - } - } + if (cmd->parser) { + if (!(*cmd->parser)(dev, &cl, cmd->p)) + return; + } + } } } - static void -hndl_clend(pgc_t *dev) +hndl_clend(UNUSED(pgc_t *dev)) { /* Should not happen outside a CLBEG. */ } - /* * Execute a command list. * @@ -441,93 +429,92 @@ static void hndl_clrun(pgc_t *dev) { pgc_cl_t *clprev = dev->clcur; - uint8_t param = 0; + uint8_t param = 0; - if (! pgc_param_byte(dev, ¶m)) return; + if (!pgc_param_byte(dev, ¶m)) + return; - dev->clcur = &dev->clist[param]; - dev->clcur->rdptr = 0; + dev->clcur = &dev->clist[param]; + dev->clcur->rdptr = 0; dev->clcur->repeat = 1; - dev->clcur->chain = clprev; + dev->clcur->chain = clprev; } - /* Execute a command list multiple times. */ static void hndl_cloop(pgc_t *dev) { pgc_cl_t *clprev = dev->clcur; - uint8_t param = 0; - int16_t repeat = 0; + uint8_t param = 0; + int16_t repeat = 0; - if (! pgc_param_byte(dev, ¶m)) return; - if (! pgc_param_word(dev, &repeat)) return; + if (!pgc_param_byte(dev, ¶m)) + return; + if (!pgc_param_word(dev, &repeat)) + return; - dev->clcur = &dev->clist[param]; - dev->clcur->rdptr = 0; + dev->clcur = &dev->clist[param]; + dev->clcur->rdptr = 0; dev->clcur->repeat = repeat; - dev->clcur->chain = clprev; + dev->clcur->chain = clprev; } - /* Read back a command list. */ static void hndl_clread(pgc_t *dev) { - uint8_t param = 0; - uint32_t n; + uint8_t param = 0; - if (! pgc_param_byte(dev, ¶m)) return; + if (!pgc_param_byte(dev, ¶m)) + return; - for (n = 0; n < dev->clist[param].wrptr; n++) { - if (! pgc_result_byte(dev, dev->clist[param].list[n])) - return; + for (uint32_t n = 0; n < dev->clist[param].wrptr; n++) { + if (!pgc_result_byte(dev, dev->clist[param].list[n])) + return; } } - /* Delete a command list. */ static void hndl_cldel(pgc_t *dev) { uint8_t param = 0; - if (! pgc_param_byte(dev, ¶m)) return; + if (!pgc_param_byte(dev, ¶m)) + return; memset(&dev->clist[param], 0, sizeof(pgc_cl_t)); } - /* Clear the screen to a specified color. */ static void hndl_clears(pgc_t *dev) { - uint8_t param = 0; - uint32_t y; + uint8_t param = 0; - if (! pgc_param_byte(dev, ¶m)) return; + if (!pgc_param_byte(dev, ¶m)) + return; - for (y = 0; y < dev->screenh; y++) - memset(dev->vram + y * dev->maxw, param, dev->screenw); + for (uint32_t y = 0; y < dev->screenh; y++) + memset(dev->vram + y * dev->maxw, param, dev->screenw); } - /* Select drawing color. */ static void hndl_color(pgc_t *dev) { uint8_t param = 0; - if (! pgc_param_byte(dev, ¶m)) return; + if (!pgc_param_byte(dev, ¶m)) + return; pgc_log("PGC: COLOR(%i)\n", param); dev->color = param; } - /* - * Set drawing mode. - * + * Set drawing mode. + * * 0 => Draw * 1 => Invert */ @@ -536,107 +523,119 @@ hndl_linfun(pgc_t *dev) { uint8_t param = 0; - if (! pgc_param_byte(dev, ¶m)) return; + if (!pgc_param_byte(dev, ¶m)) + return; pgc_log("PGC: LINFUN(%i)\n", param); if (param < 2) - dev->draw_mode = param; + dev->draw_mode = param; else - pgc_error(dev, PGC_ERROR_RANGE); + pgc_error(dev, PGC_ERROR_RANGE); } - /* Set the line drawing pattern. */ static void hndl_linpat(pgc_t *dev) { uint16_t param = 0; - if (! pgc_param_word(dev, (int16_t *)¶m)) return; + if (!pgc_param_word(dev, (int16_t *) ¶m)) + return; pgc_log("PGC: LINPAT(0x%04x)\n", param); dev->line_pattern = param; } - /* Set the polygon fill mode (0=hollow, 1=filled, 2=fast fill). */ static void hndl_prmfil(pgc_t *dev) { uint8_t param = 0; - if (! pgc_param_byte(dev, ¶m)) return; + if (!pgc_param_byte(dev, ¶m)) + return; pgc_log("PGC: PRMFIL(%i)\n", param); if (param < 3) - dev->fill_mode = param; + dev->fill_mode = param; else - pgc_error(dev, PGC_ERROR_RANGE); + pgc_error(dev, PGC_ERROR_RANGE); } - /* Set the 2D drawing position. */ static void hndl_move(pgc_t *dev) { - int32_t x = 0, y = 0; + int32_t x = 0; + int32_t y = 0; - if (! pgc_param_coord(dev, &x)) return; - if (! pgc_param_coord(dev, &y)) return; + if (!pgc_param_coord(dev, &x)) + return; + if (!pgc_param_coord(dev, &y)) + return; pgc_log("PCG: MOVE %x.%04x,%x.%04x\n", - HWORD(x), LWORD(x), HWORD(y), LWORD(y)); + HWORD(x), LWORD(x), HWORD(y), LWORD(y)); dev->x = x; dev->y = y; } - /* Set the 3D drawing position. */ static void hndl_move3(pgc_t *dev) { - int32_t x = 0, y = 0, z = 0; + int32_t x = 0; + int32_t y = 0; + int32_t z = 0; - if (! pgc_param_coord(dev, &x)) return; - if (! pgc_param_coord(dev, &y)) return; - if (! pgc_param_coord(dev, &z)) return; + if (!pgc_param_coord(dev, &x)) + return; + if (!pgc_param_coord(dev, &y)) + return; + if (!pgc_param_coord(dev, &z)) + return; dev->x = x; dev->y = y; dev->z = z; } - /* Relative move (2D). */ static void hndl_mover(pgc_t *dev) { - int32_t x = 0, y = 0; + int32_t x = 0; + int32_t y = 0; - if (! pgc_param_coord(dev, &x)) return; - if (! pgc_param_coord(dev, &y)) return; + if (!pgc_param_coord(dev, &x)) + return; + if (!pgc_param_coord(dev, &y)) + return; dev->x += x; dev->y += y; } - /* Relative move (3D). */ static void hndl_mover3(pgc_t *dev) { - int32_t x = 0, y = 0, z = 0; + int32_t x = 0; + int32_t y = 0; + int32_t z = 0; - if (! pgc_param_coord(dev, &x)) return; - if (! pgc_param_coord(dev, &y)) return; - if (! pgc_param_coord(dev, &z)) return; + if (!pgc_param_coord(dev, &x)) + return; + if (!pgc_param_coord(dev, &y)) + return; + if (!pgc_param_coord(dev, &z)) + return; dev->x += x; dev->y += y; dev->z += z; } - /* Given raster coordinates, find the matching address in PGC video RAM. */ uint8_t * pgc_vram_addr(pgc_t *dev, int16_t x, int16_t y) @@ -644,19 +643,18 @@ pgc_vram_addr(pgc_t *dev, int16_t x, int16_t y) int offset; /* We work from the bottom left-hand corner. */ - if (y < 0 || (uint32_t)y >= dev->maxh || - x < 0 || (uint32_t)x >= dev->maxw) return NULL; + if (y < 0 || (uint32_t) y >= dev->maxh || x < 0 || (uint32_t) x >= dev->maxw) + return NULL; offset = (dev->maxh - 1 - y) * (dev->maxw) + x; pgc_log("PGC: vram_addr(x=%i,y=%i) = %i\n", x, y, offset); - if (offset < 0 || (uint32_t)offset >= (dev->maxw * dev->maxh)) - return NULL; + if (offset < 0 || (uint32_t) offset >= (dev->maxw * dev->maxh)) + return NULL; return &dev->vram[offset]; } - /* * Write a screen pixel. * X and Y are raster coordinates, ink is the value to write. @@ -667,39 +665,36 @@ pgc_write_pixel(pgc_t *dev, uint16_t x, uint16_t y, uint8_t ink) uint8_t *vram; /* Suppress out-of-range writes; clip to viewport. */ - if (x < dev->vp_x1 || x > dev->vp_x2 || x >= dev->maxw || - y < dev->vp_y1 || y > dev->vp_y2 || y >= dev->maxh) { - pgc_log("PGC: write_pixel clipped: (%i,%i) " - "vp_x1=%i vp_y1=%i vp_x2=%i vp_y2=%i " - "ink=0x%02x\n", - x, y, dev->vp_x1, dev->vp_y1, dev->vp_x2, dev->vp_y2, ink); - return; + if (x < dev->vp_x1 || x > dev->vp_x2 || x >= dev->maxw || y < dev->vp_y1 || y > dev->vp_y2 || y >= dev->maxh) { + pgc_log("PGC: write_pixel clipped: (%i,%i) " + "vp_x1=%i vp_y1=%i vp_x2=%i vp_y2=%i " + "ink=0x%02x\n", + x, y, dev->vp_x1, dev->vp_y1, dev->vp_x2, dev->vp_y2, ink); + return; } vram = pgc_vram_addr(dev, x, y); if (vram) - *vram = ink; + *vram = ink; } - /* Read a screen pixel (x and y are raster coordinates). */ uint8_t pgc_read_pixel(pgc_t *dev, uint16_t x, uint16_t y) { - uint8_t *vram; + const uint8_t *vram; /* Suppress out-of-range reads. */ - if (x >= dev->maxw || y >= dev->maxh) - return 0; + if (x >= dev->maxw || y >= dev->maxh) + return 0; vram = pgc_vram_addr(dev, x, y); if (vram) - return *vram; + return *vram; return 0; } - /* * Plot a point in the current color and draw mode. Raster coordinates. * @@ -712,47 +707,47 @@ pgc_plot(pgc_t *dev, uint16_t x, uint16_t y) uint8_t *vram; /* Only allow plotting within the current viewport. */ - if (x < dev->vp_x1 || x > dev->vp_x2 || x >= dev->maxw || - y < dev->vp_y1 || y > dev->vp_y2 || y >= dev->maxh) { - pgc_log("PGC: plot clipped: (%i,%i) %i <= x <= %i; %i <= y <= %i; " - "mode=%i ink=0x%02x\n", x, y, - dev->vp_x1, dev->vp_x2, dev->vp_y1, dev->vp_y2, - dev->draw_mode, dev->color); - return; + if (x < dev->vp_x1 || x > dev->vp_x2 || x >= dev->maxw || y < dev->vp_y1 || y > dev->vp_y2 || y >= dev->maxh) { + pgc_log("PGC: plot clipped: (%i,%i) %i <= x <= %i; %i <= y <= %i; " + "mode=%i ink=0x%02x\n", + x, y, + dev->vp_x1, dev->vp_x2, dev->vp_y1, dev->vp_y2, + dev->draw_mode, dev->color); + return; } vram = pgc_vram_addr(dev, x, y); - if (! vram) return; + if (!vram) + return; /* TODO: Does not implement the PGC plane mask (set by MASK). */ switch (dev->draw_mode) { - default: - case 0: /* WRITE */ - *vram = dev->color; - break; + default: + case 0: /* WRITE */ + *vram = dev->color; + break; - case 1: /* INVERT */ - *vram ^= 0xff; - break; + case 1: /* INVERT */ + *vram ^= 0xff; + break; - case 2: /* XOR color */ - //FIXME: see notes - *vram ^= dev->color; - break; + case 2: /* XOR color */ + // FIXME: see notes + *vram ^= dev->color; + break; - case 3: /* AND color */ - //FIXME: see notes - *vram &= dev->color; - break; + case 3: /* AND color */ + // FIXME: see notes + *vram &= dev->color; + break; } } - /* * Draw a line (using raster coordinates). * * Bresenham's Algorithm from: - * + * * * The line pattern mask to use is passed in. Return value is the * line pattern mask, rotated by the number of points drawn. @@ -760,44 +755,49 @@ pgc_plot(pgc_t *dev, uint16_t x, uint16_t y) uint16_t pgc_draw_line_r(pgc_t *dev, int32_t x0, int32_t y0, int32_t x1, int32_t y1, uint16_t linemask) { - int32_t dx, dy, sx, sy, err, e2; + int32_t dx; + int32_t dy; + int32_t sx; + int32_t sy; + int32_t err; + int32_t e2; - dx = abs(x1 - x0); - dy = abs(y1 - y0); - sx = (x0 < x1) ? 1 : -1; - sy = (y0 < y1) ? 1 : -1; + dx = abs(x1 - x0); + dy = abs(y1 - y0); + sx = (x0 < x1) ? 1 : -1; + sy = (y0 < y1) ? 1 : -1; err = (dx > dy ? dx : -dy) / 2; for (;;) { - if (linemask & 0x8000) { - pgc_plot(dev, x0, y0); - linemask = (linemask << 1) | 1; - } else - linemask = (linemask << 1); + if (linemask & 0x8000) { + pgc_plot(dev, x0, y0); + linemask = (linemask << 1) | 1; + } else + linemask = (linemask << 1); - if (x0 == x1 && y0 == y1) break; + if (x0 == x1 && y0 == y1) + break; - e2 = err; - if (e2 > -dx) { - err -= dy; - x0 += sx; - } - if (e2 < dy) { - err += dx; - y0 += sy; - } + e2 = err; + if (e2 > -dx) { + err -= dy; + x0 += sx; + } + if (e2 < dy) { + err += dx; + y0 += sy; + } } return linemask; } - /* Draw a line (using PGC fixed-point coordinates). */ uint16_t pgc_draw_line(pgc_t *dev, int32_t x0, int32_t y0, int32_t x1, int32_t y1, uint16_t linemask) { pgc_log("pgc_draw_line: (%i,%i) to (%i,%i)\n", - x0 >> 16, y0 >> 16, x1 >> 16, y1 >> 16); + x0 >> 16, y0 >> 16, x1 >> 16, y1 >> 16); /* Convert from PGC fixed-point to device coordinates */ x0 >>= 16; @@ -811,9 +811,8 @@ pgc_draw_line(pgc_t *dev, int32_t x0, int32_t y0, int32_t x1, int32_t y1, uint16 return pgc_draw_line_r(dev, x0, y0, x1, y1, linemask); } - /* - * Draw a horizontal line in the current fill pattern + * Draw a horizontal line in the current fill pattern * (using raster coordinates). */ void @@ -823,104 +822,111 @@ pgc_fill_line_r(pgc_t *dev, int32_t x0, int32_t x1, int32_t y0) int32_t x; if (x0 > x1) { - x = x1; - x1 = x0; - x0 = x; + x = x1; + x1 = x0; + x0 = x; } for (x = x0; x <= x1; x++) { - if (dev->fill_pattern[y0 & 0x0F] & mask) - pgc_plot(dev, x, y0); - mask = mask >> 1; - if (mask == 0) mask = 0x8000; - } + if (dev->fill_pattern[y0 & 0x0F] & mask) + pgc_plot(dev, x, y0); + mask = mask >> 1; + if (mask == 0) + mask = 0x8000; + } } - /* For sorting polygon nodes. */ static int compare_double(const void *a, const void *b) { - const double *da = (const double *)a; - const double *db = (const double *)b; + const double *da = (const double *) a; + const double *db = (const double *) b; - if (*da < *db) return 1; - if (*da > *db) return -1; + if (*da < *db) + return 1; + if (*da > *db) + return -1; return 0; } - /* Draw a filled polygon (using PGC fixed-point coordinates). */ void pgc_fill_polygon(pgc_t *dev, unsigned corners, int32_t *x, int32_t *y) { - double *nodex; - double *dx; - double *dy; - unsigned n, nodes, i, j; - double ymin, ymax, ypos; + double *nodex; + double *dx; + double *dy; + unsigned nodes; + unsigned i; + unsigned j; + double ymin; + double ymax; pgc_log("PGC: fill_polygon(%i corners)\n", corners); if (!x || !y || (corners < 2)) - return; /* Degenerate polygon */ + return; /* Degenerate polygon */ - nodex = (double *)malloc(corners * sizeof(double)); - dx = (double *)malloc(corners * sizeof(double)); - dy = (double *)malloc(corners * sizeof(double)); + nodex = (double *) malloc(corners * sizeof(double)); + dx = (double *) malloc(corners * sizeof(double)); + dy = (double *) malloc(corners * sizeof(double)); if (!nodex || !dx || !dy) { - if (nodex) { - free(nodex); - nodex = NULL; - } - if (dx) { - free(dx); - dx = NULL; - } - if (dy) { - free(dy); - dy = NULL; - } - return; + if (nodex) { + free(nodex); + nodex = NULL; + } + if (dx) { + free(dx); + dx = NULL; + } + if (dy) { + free(dy); + dy = NULL; + } + return; } ymin = ymax = y[0] / 65536.0; - for (n = 0; n < corners; n++) { - /* Convert from PGC fixed-point to native floating-point. */ - dx[n] = x[n] / 65536.0; - dy[n] = y[n] / 65536.0; + for (unsigned int n = 0; n < corners; n++) { + /* Convert from PGC fixed-point to native floating-point. */ + dx[n] = x[n] / 65536.0; + dy[n] = y[n] / 65536.0; - if (dy[n] < ymin) ymin = dy[n]; - if (dy[n] > ymax) ymax = dy[n]; + if (dy[n] < ymin) + ymin = dy[n]; + if (dy[n] > ymax) + ymax = dy[n]; } /* Polygon fill. Based on */ - /* For each row, work out where the polygon lines intersect with - * that row. */ - for (ypos = ymin; ypos <= ymax; ypos++) { - nodes = 0; - j = corners - 1; - for (i = 0; i < corners; i++) { - if ((dy[i] < ypos && dy[j] >= ypos) || - (dy[j] < ypos && dy[i] >= ypos)) /* Line crosses */ { - nodex[nodes++] = dx[i] + (ypos-dy[i])/(dy[j]-dy[i]) * (dx[j] - dx[i]); - } - j = i; - } + /* For each row, work out where the polygon lines intersect with + * that row. */ + for (double ypos = ymin; ypos <= ymax; ypos++) { + nodes = 0; + j = corners - 1; + for (i = 0; i < corners; i++) { + if ((dy[i] < ypos && dy[j] >= ypos) || (dy[j] < ypos && dy[i] >= ypos)) /* Line crosses */ { + nodex[nodes++] = dx[i] + (ypos - dy[i]) / (dy[j] - dy[i]) * (dx[j] - dx[i]); + } + j = i; + } - /* Sort the intersections. */ - if (nodes) - qsort(nodex, nodes, sizeof(double), compare_double); + /* Sort the intersections. */ + if (nodes) + qsort(nodex, nodes, sizeof(double), compare_double); - /* And fill between them. */ - for (i = 0; i < nodes; i += 2) { - int16_t x1 = (int16_t)nodex[i], x2 = (int16_t)nodex[i + 1], - y1 = (int16_t)ypos, y2 = (int16_t)ypos; - pgc_sto_raster(dev, &x1, &y1); - pgc_sto_raster(dev, &x2, &y2); - pgc_fill_line_r(dev, x1, x2, y1); - } + /* And fill between them. */ + for (i = 0; i < nodes; i += 2) { + int16_t x1 = (int16_t) nodex[i]; + int16_t x2 = (int16_t) nodex[i + 1]; + int16_t y1 = (int16_t) ypos; + int16_t y2 = (int16_t) ypos; + pgc_sto_raster(dev, &x1, &y1); + pgc_sto_raster(dev, &x2, &y2); + pgc_fill_line_r(dev, x1, x2, y1); + } } free(nodex); @@ -928,86 +934,85 @@ pgc_fill_polygon(pgc_t *dev, unsigned corners, int32_t *x, int32_t *y) free(dy); } - /* Draw a filled ellipse (using PGC fixed-point coordinates). */ void pgc_draw_ellipse(pgc_t *dev, int32_t x, int32_t y) { /* Convert from PGC fixed-point to native floating-point. */ - double h = y / 65536.0; - double w = x / 65536.0; - double y0 = dev->y / 65536.0; - double x0 = dev->x / 65536.0; - double ypos, xpos; - double x1; - double xlast = 0.0; + double h = y / 65536.0; + double w = x / 65536.0; + double y0 = dev->y / 65536.0; + double x0 = dev->x / 65536.0; + double x1; + double xlast = 0.0; int16_t linemask = dev->line_pattern; pgc_log("PGC: ellipse(color=%i drawmode=%i fill=%i)\n", - dev->color, dev->draw_mode, dev->fill_mode); + dev->color, dev->draw_mode, dev->fill_mode); pgc_dto_raster(dev, &x0, &y0); - for (ypos = 0; ypos <= h; ypos++) { - if (ypos == 0) { - if (dev->fill_mode) - pgc_fill_line_r(dev, (uint16_t)(x0 - w), - (uint16_t)(x0 + w), (uint16_t)y0); - if (linemask & 0x8000) { - pgc_plot(dev, (uint16_t)(x0 + w), (uint16_t)y0); - pgc_plot(dev, (uint16_t)(x0 - w), (uint16_t)y0); - linemask = (linemask << 1) | 1; - } else - linemask = linemask << 1; + for (double ypos = 0; ypos <= h; ypos++) { + if (ypos == 0) { + if (dev->fill_mode) + pgc_fill_line_r(dev, (uint16_t) (x0 - w), + (uint16_t) (x0 + w), (uint16_t) y0); + if (linemask & 0x8000) { + pgc_plot(dev, (uint16_t) (x0 + w), (uint16_t) y0); + pgc_plot(dev, (uint16_t) (x0 - w), (uint16_t) y0); + linemask = (linemask << 1) | 1; + } else + linemask = linemask << 1; - xlast = w; - } else { - x1 = sqrt((h * h) - (ypos * ypos)) * w / h; + xlast = w; + } else { + x1 = sqrt((h * h) - (ypos * ypos)) * w / h; - if (dev->fill_mode) { - pgc_fill_line_r(dev, (uint16_t)(x0 - x1), - (uint16_t)(x0 + x1), - (uint16_t)(y0 + ypos)); - pgc_fill_line_r(dev, (uint16_t)(x0 - x1), - (uint16_t)(x0 + x1), - (uint16_t)(y0 - ypos)); - } + if (dev->fill_mode) { + pgc_fill_line_r(dev, (uint16_t) (x0 - x1), + (uint16_t) (x0 + x1), + (uint16_t) (y0 + ypos)); + pgc_fill_line_r(dev, (uint16_t) (x0 - x1), + (uint16_t) (x0 + x1), + (uint16_t) (y0 - ypos)); + } - /* Draw border. */ - for (xpos = xlast; xpos >= x1; xpos--) { - if (linemask & 0x8000) { - pgc_plot(dev, (uint16_t)(x0 + xpos), - (uint16_t)(y0 + ypos)); - pgc_plot(dev, (uint16_t)(x0 - xpos), - (uint16_t)(y0 + ypos)); - pgc_plot(dev, (uint16_t)(x0 + xpos), - (uint16_t)(y0 - ypos)); - pgc_plot(dev, (uint16_t)(x0 - xpos), - (uint16_t)(y0 - ypos)); - linemask = (linemask << 1) | 1; - } else - linemask = linemask << 1; - } + /* Draw border. */ + for (double xpos = xlast; xpos >= x1; xpos--) { + if (linemask & 0x8000) { + pgc_plot(dev, (uint16_t) (x0 + xpos), + (uint16_t) (y0 + ypos)); + pgc_plot(dev, (uint16_t) (x0 - xpos), + (uint16_t) (y0 + ypos)); + pgc_plot(dev, (uint16_t) (x0 + xpos), + (uint16_t) (y0 - ypos)); + pgc_plot(dev, (uint16_t) (x0 - xpos), + (uint16_t) (y0 - ypos)); + linemask = (linemask << 1) | 1; + } else + linemask = linemask << 1; + } - xlast = x1; - } + xlast = x1; + } } } - /* Handle the ELIPSE (sic) command. */ static void hndl_ellipse(pgc_t *dev) { - int32_t x = 0, y = 0; + int32_t x = 0; + int32_t y = 0; - if (! pgc_param_coord(dev, &x)) return; - if (! pgc_param_coord(dev, &y)) return; + if (!pgc_param_coord(dev, &x)) + return; + if (!pgc_param_coord(dev, &y)) + return; pgc_draw_ellipse(dev, x, y); } - /* Handle the POLY command. */ static void hndl_poly(pgc_t *dev) @@ -1015,126 +1020,134 @@ hndl_poly(pgc_t *dev) uint8_t count; int32_t x[256]; int32_t y[256]; - int32_t n; - if (! pgc_param_byte(dev, &count)) return; + if (!pgc_param_byte(dev, &count)) + return; pgc_log("PGC: POLY (%i)\n", count); - for (n = 0; n < count; n++) { - if (! pgc_param_coord(dev, &x[n])) return; - if (! pgc_param_coord(dev, &y[n])) return; + for (uint8_t n = 0; n < count; n++) { + if (!pgc_param_coord(dev, &x[n])) + return; + if (!pgc_param_coord(dev, &y[n])) + return; } } - /* Parse but don't execute a POLY command (for adding to a command list) */ static int -parse_poly(pgc_t *dev, pgc_cl_t *cl, int c) +parse_poly(pgc_t *dev, pgc_cl_t *cl, UNUSED(int c)) { uint8_t count; #ifdef ENABLE_PGC_LOG pgc_log("PCG: parse_poly\n"); #endif - if (! pgc_param_byte(dev, &count)) return 0; + if (!pgc_param_byte(dev, &count)) + return 0; pgc_log("PCG: parse_poly: count=%02x\n", count); - if (! pgc_cl_append(cl, count)) { - pgc_error(dev, PGC_ERROR_OVERFLOW); - return 0; + if (!pgc_cl_append(cl, count)) { + pgc_error(dev, PGC_ERROR_OVERFLOW); + return 0; } pgc_log("PCG: parse_poly: parse %i coords\n", 2 * count); return pgc_parse_coords(dev, cl, 2 * count); } - /* Handle the DISPLAY command. */ static void hndl_display(pgc_t *dev) { uint8_t param; - if (! pgc_param_byte(dev, ¶m)) return; + if (!pgc_param_byte(dev, ¶m)) + return; pgc_log("PGC: DISPLAY(%i)\n", param); - if (param > 1) - pgc_error(dev, PGC_ERROR_RANGE); + if (param > 1) + pgc_error(dev, PGC_ERROR_RANGE); else - pgc_setdisplay(dev, param); + pgc_setdisplay(dev, param); } - /* Handle the IMAGEW command (memory to screen blit). */ static void hndl_imagew(pgc_t *dev) { - int16_t row, col1, col2; - uint8_t v1, v2; + int16_t row; + int16_t col1; + int16_t col2; + uint8_t v1; + uint8_t v2; - if (! pgc_param_word(dev, &row)) return; - if (! pgc_param_word(dev, &col1)) return; - if (! pgc_param_word(dev, &col2)) return; + if (!pgc_param_word(dev, &row)) + return; + if (!pgc_param_word(dev, &col1)) + return; + if (!pgc_param_word(dev, &col2)) + return; - if ((uint32_t)row >= dev->screenh || - (uint32_t)col1 >= dev->maxw || (uint32_t)col2 >= dev->maxw) { - pgc_error(dev, PGC_ERROR_RANGE); - return; + if ((uint32_t) row >= dev->screenh || (uint32_t) col1 >= dev->maxw || (uint32_t) col2 >= dev->maxw) { + pgc_error(dev, PGC_ERROR_RANGE); + return; } /* In ASCII mode, what is written is a stream of bytes. */ if (dev->ascii_mode) { - while (col1 <= col2) { - if (! pgc_param_byte(dev, &v1)) return; - pgc_write_pixel(dev, col1, row, v1); - col1++; - } + while (col1 <= col2) { + if (!pgc_param_byte(dev, &v1)) + return; + pgc_write_pixel(dev, col1, row, v1); + col1++; + } - return; + return; } /* In hex mode, it's RLE compressed. */ while (col1 <= col2) { - if (! pgc_param_byte(dev, &v1)) return; + if (!pgc_param_byte(dev, &v1)) + return; - if (v1 & 0x80) { - /* Literal run. */ - v1 -= 0x7f; - while (col1 <= col2 && v1 != 0) { - if (! pgc_param_byte(dev, &v2)) return; - pgc_write_pixel(dev, col1, row, v2); - col1++; - v1--; - } - } else { - /* Repeated run. */ - if (! pgc_param_byte(dev, &v2)) return; - - v1++; - while (col1 <= col2 && v1 != 0) { - pgc_write_pixel(dev, col1, row, v2); - col1++; - v1--; - } - } + if (v1 & 0x80) { + /* Literal run. */ + v1 -= 0x7f; + while (col1 <= col2 && v1 != 0) { + if (!pgc_param_byte(dev, &v2)) + return; + pgc_write_pixel(dev, col1, row, v2); + col1++; + v1--; + } + } else { + /* Repeated run. */ + if (!pgc_param_byte(dev, &v2)) + return; + + v1++; + while (col1 <= col2 && v1 != 0) { + pgc_write_pixel(dev, col1, row, v2); + col1++; + v1--; + } + } } } - /* Select one of the built-in palettes. */ static void init_lut(pgc_t *dev, int param) { if (param >= 0 && param < 6) - memcpy(dev->palette, init_palette[param], sizeof(dev->palette)); + memcpy(dev->palette, init_palette[param], sizeof(dev->palette)); else if (param == 0xff) - memcpy(dev->palette, dev->userpal, sizeof(dev->palette)); + memcpy(dev->palette, dev->userpal, sizeof(dev->palette)); else - pgc_error(dev, PGC_ERROR_RANGE); + pgc_error(dev, PGC_ERROR_RANGE); } - /* Save the current palette. */ static void hndl_lutsav(pgc_t *dev) @@ -1142,108 +1155,104 @@ hndl_lutsav(pgc_t *dev) memcpy(dev->userpal, dev->palette, sizeof(dev->palette)); } - /* Handle LUTINT (select palette). */ static void hndl_lutint(pgc_t *dev) { uint8_t param; - if (! pgc_param_byte(dev, ¶m)) return; + if (!pgc_param_byte(dev, ¶m)) + return; init_lut(dev, param); } - /* Handle LUTRD (read palette register). */ static void hndl_lutrd(pgc_t *dev) { - uint8_t param; + uint8_t param; uint32_t col; - if (! pgc_param_byte(dev, ¶m)) return; + if (!pgc_param_byte(dev, ¶m)) + return; col = dev->palette[param]; - pgc_result_byte(dev, (col >> 20) & 0x0f); - pgc_result_byte(dev, (col >> 12) & 0x0f); - pgc_result_byte(dev, (col >> 4) & 0x0f); + pgc_result_byte(dev, (col >> 20) & 0x0f); + pgc_result_byte(dev, (col >> 12) & 0x0f); + pgc_result_byte(dev, (col >> 4) & 0x0f); } - /* Handle LUT (write palette register). */ static void hndl_lut(pgc_t *dev) { uint8_t param[4]; - int n; - for (n = 0; n < 4; n++) { - if (! pgc_param_byte(dev, ¶m[n])) return; - if (n > 0 && param[n] > 15) { - pgc_error(dev, PGC_ERROR_RANGE); - param[n] &= 0x0f; - } + for (uint8_t n = 0; n < 4; n++) { + if (!pgc_param_byte(dev, ¶m[n])) + return; + if (n > 0 && param[n] > 15) { + pgc_error(dev, PGC_ERROR_RANGE); + param[n] &= 0x0f; + } } dev->palette[param[0]] = makecol((param[1] * 0x11), - (param[2] * 0x11), - (param[3] * 0x11)); + (param[2] * 0x11), + (param[3] * 0x11)); } - /* * LUT8RD and LUT8 are extensions implemented by several PGC clones, - * so here are functions that implement them even though they aren't + * so here are functions that implement them even though they aren't * used by the PGC. */ void pgc_hndl_lut8rd(pgc_t *dev) { - uint8_t param; + uint8_t param; uint32_t col; - if (! pgc_param_byte(dev, ¶m)) return; + if (!pgc_param_byte(dev, ¶m)) + return; col = dev->palette[param]; - pgc_result_byte(dev, (col >> 16) & 0xff); - pgc_result_byte(dev, (col >> 8) & 0xff); + pgc_result_byte(dev, (col >> 16) & 0xff); + pgc_result_byte(dev, (col >> 8) & 0xff); pgc_result_byte(dev, col & 0xff); } - void pgc_hndl_lut8(pgc_t *dev) { uint8_t param[4]; - int n; - for (n = 0; n < 4; n++) - if (! pgc_param_byte(dev, ¶m[n])) return; + for (uint8_t n = 0; n < 4; n++) + if (!pgc_param_byte(dev, ¶m[n])) + return; dev->palette[param[0]] = makecol((param[1]), (param[2]), (param[3])); } - /* Handle AREAPT (set 16x16 fill pattern). */ static void hndl_areapt(pgc_t *dev) { int16_t pat[16]; - int n; - for (n = 0; n < 16; n++) - if (! pgc_param_word(dev, &pat[n])) return; + for (uint8_t n = 0; n < 16; n++) + if (!pgc_param_word(dev, &pat[n])) + return; pgc_log("PGC: AREAPT(%04x %04x %04x %04x...)\n", - pat[0] & 0xffff, pat[1] & 0xffff, pat[2] & 0xffff, pat[3] & 0xffff); + pat[0] & 0xffff, pat[1] & 0xffff, pat[2] & 0xffff, pat[3] & 0xffff); memcpy(dev->fill_pattern, pat, sizeof(dev->fill_pattern)); } - /* Handle CA (select ASCII mode). */ static void hndl_ca(pgc_t *dev) @@ -1251,7 +1260,6 @@ hndl_ca(pgc_t *dev) dev->ascii_mode = 1; } - /* Handle CX (select hex mode). */ static void hndl_cx(pgc_t *dev) @@ -1259,7 +1267,6 @@ hndl_cx(pgc_t *dev) dev->ascii_mode = 0; } - /* * CA and CX remain valid in hex mode; they are handled * as command 0x43 ('C') with a one-byte parameter. @@ -1269,16 +1276,16 @@ hndl_c(pgc_t *dev) { uint8_t param; - if (! dev->inputbyte(dev, ¶m)) return; + if (!dev->inputbyte(dev, ¶m)) + return; if (param == 'A') - dev->ascii_mode = 1; + dev->ascii_mode = 1; if (param == 'X') - dev->ascii_mode = 0; + dev->ascii_mode = 0; } - /* RESETF resets the PGC. */ static void hndl_resetf(pgc_t *dev) @@ -1286,37 +1293,37 @@ hndl_resetf(pgc_t *dev) pgc_reset(dev); } - /* TJUST sets text justify settings. */ static void hndl_tjust(pgc_t *dev) { uint8_t param[2]; - if (! dev->inputbyte(dev, ¶m[0])) return; - if (! dev->inputbyte(dev, ¶m[1])) return; + if (!dev->inputbyte(dev, ¶m[0])) + return; + if (!dev->inputbyte(dev, ¶m[1])) + return; if (param[0] >= 1 && param[0] <= 3 && param[1] >= 1 && param[1] <= 3) { - dev->tjust_h = param[0]; - dev->tjust_v = param[1]; + dev->tjust_h = param[0]; + dev->tjust_v = param[1]; } else - pgc_error(dev, PGC_ERROR_RANGE); + pgc_error(dev, PGC_ERROR_RANGE); } - /* TSIZE controls text horizontal spacing. */ static void hndl_tsize(pgc_t *pgc) { int32_t param = 0; - if (! pgc_param_coord(pgc, ¶m)) return; + if (!pgc_param_coord(pgc, ¶m)) + return; pgc_log("PGC: TSIZE %i\n", param); pgc->tsize = param; } - /* * VWPORT sets up the viewport (roughly, the clip rectangle) in * raster coordinates, measured from the bottom left of the screen. @@ -1324,56 +1331,68 @@ hndl_tsize(pgc_t *pgc) static void hndl_vwport(pgc_t *dev) { - int16_t x1, x2, y1, y2; + int16_t x1; + int16_t x2; + int16_t y1; + int16_t y2; - if (! pgc_param_word(dev, &x1)) return; - if (! pgc_param_word(dev, &x2)) return; - if (! pgc_param_word(dev, &y1)) return; - if (! pgc_param_word(dev, &y2)) return; + if (!pgc_param_word(dev, &x1)) + return; + if (!pgc_param_word(dev, &x2)) + return; + if (!pgc_param_word(dev, &y1)) + return; + if (!pgc_param_word(dev, &y2)) + return; - pgc_log("PGC: VWPORT %i,%i,%i,%i\n", x1,x2,y1,y2); + pgc_log("PGC: VWPORT %i,%i,%i,%i\n", x1, x2, y1, y2); dev->vp_x1 = x1; dev->vp_x2 = x2; dev->vp_y1 = y1; dev->vp_y2 = y2; } - /* WINDOW defines the coordinate system in use. */ static void hndl_window(pgc_t *dev) { - int16_t x1, x2, y1, y2; + int16_t x1; + int16_t x2; + int16_t y1; + int16_t y2; - if (! pgc_param_word(dev, &x1)) return; - if (! pgc_param_word(dev, &x2)) return; - if (! pgc_param_word(dev, &y1)) return; - if (! pgc_param_word(dev, &y2)) return; + if (!pgc_param_word(dev, &x1)) + return; + if (!pgc_param_word(dev, &x2)) + return; + if (!pgc_param_word(dev, &y1)) + return; + if (!pgc_param_word(dev, &y2)) + return; - pgc_log("PGC: WINDOW %i,%i,%i,%i\n", x1,x2,y1,y2); + pgc_log("PGC: WINDOW %i,%i,%i,%i\n", x1, x2, y1, y2); dev->win_x1 = x1; dev->win_x2 = x2; dev->win_y1 = y1; dev->win_y2 = y2; } - /* * The list of commands implemented by this mini-PGC. * * In order to support the original PGC and clones, we support two lists; * core commands (listed below) and subclass commands (listed in the clone). - * + * * Each row has five parameters: - * ASCII-mode command - * Hex-mode command - * Function that executes this command - * Function that parses this command when building a command list - * Parameter for the parse function + * ASCII-mode command + * Hex-mode command + * Function that executes this command + * Function that parses this command when building a command list + * Parameter for the parse function * * TODO: This list omits numerous commands present in a genuine PGC * (ARC, AREA, AREABC, BUFFER, CIRCLE etc etc). - * TODO: Some commands don't have a parse function (for example, IMAGEW) + * TODO: Some commands don't have a parse function (for example, IMAGEW) * * The following ASCII entries have special meaning: * ~~~~~~ command is valid only in hex mode @@ -1382,83 +1401,81 @@ hndl_window(pgc_t *dev) * */ static const pgc_cmd_t pgc_commands[] = { - { "AREAPT", 0xe7, hndl_areapt, pgc_parse_words, 16 }, - { "AP", 0xe7, hndl_areapt, pgc_parse_words, 16 }, - { "~~~~~~", 0x43, hndl_c, NULL, 0 }, - { "CA", 0xd2, hndl_ca, NULL, 0 }, - { "CLBEG", 0x70, hndl_clbeg, NULL, 0 }, - { "CB", 0x70, hndl_clbeg, NULL, 0 }, - { "CLDEL", 0x74, hndl_cldel, pgc_parse_bytes, 1 }, - { "CD", 0x74, hndl_cldel, pgc_parse_bytes, 1 }, - { "CLEND", 0x71, hndl_clend, NULL, 0 }, - { "CLRUN", 0x72, hndl_clrun, pgc_parse_bytes, 1 }, - { "CR", 0x72, hndl_clrun, pgc_parse_bytes, 1 }, - { "CLRD", 0x75, hndl_clread, pgc_parse_bytes, 1 }, - { "CRD", 0x75, hndl_clread, pgc_parse_bytes, 1 }, - { "CLOOP", 0x73, hndl_cloop, NULL, 0 }, - { "CL", 0x73, hndl_cloop, NULL, 0 }, - { "CLEARS", 0x0f, hndl_clears, pgc_parse_bytes, 1 }, - { "CLS", 0x0f, hndl_clears, pgc_parse_bytes, 1 }, - { "COLOR", 0x06, hndl_color, pgc_parse_bytes, 1 }, - { "C", 0x06, hndl_color, pgc_parse_bytes, 1 }, - { "CX", 0xd1, hndl_cx, NULL, 0 }, - { "DISPLA", 0xd0, hndl_display, pgc_parse_bytes, 1 }, - { "DI", 0xd0, hndl_display, pgc_parse_bytes, 1 }, - { "ELIPSE", 0x39, hndl_ellipse, pgc_parse_coords, 2 }, - { "EL", 0x39, hndl_ellipse, pgc_parse_coords, 2 }, - { "IMAGEW", 0xd9, hndl_imagew, NULL, 0 }, - { "IW", 0xd9, hndl_imagew, NULL, 0 }, - { "LINFUN", 0xeb, hndl_linfun, pgc_parse_bytes, 1 }, - { "LF", 0xeb, hndl_linfun, pgc_parse_bytes, 1 }, - { "LINPAT", 0xea, hndl_linpat, pgc_parse_words, 1 }, - { "LP", 0xea, hndl_linpat, pgc_parse_words, 1 }, - { "LUTINT", 0xec, hndl_lutint, pgc_parse_bytes, 1 }, - { "LI", 0xec, hndl_lutint, pgc_parse_bytes, 1 }, - { "LUTRD", 0x50, hndl_lutrd, pgc_parse_bytes, 1 }, - { "LUTSAV", 0xed, hndl_lutsav, NULL, 0 }, - { "LUT", 0xee, hndl_lut, pgc_parse_bytes, 4 }, - { "MOVE", 0x10, hndl_move, pgc_parse_coords, 2 }, - { "M", 0x10, hndl_move, pgc_parse_coords, 2 }, - { "MOVE3", 0x12, hndl_move3, pgc_parse_coords, 3 }, - { "M3", 0x12, hndl_move3, pgc_parse_coords, 3 }, - { "MOVER", 0x11, hndl_mover, pgc_parse_coords, 2 }, - { "MR", 0x11, hndl_mover, pgc_parse_coords, 2 }, - { "MOVER3", 0x13, hndl_mover3, pgc_parse_coords, 3 }, - { "MR3", 0x13, hndl_mover3, pgc_parse_coords, 3 }, - { "PRMFIL", 0xe9, hndl_prmfil, pgc_parse_bytes, 1 }, - { "PF", 0xe9, hndl_prmfil, pgc_parse_bytes, 1 }, - { "POLY", 0x30, hndl_poly, parse_poly, 0 }, - { "P", 0x30, hndl_poly, parse_poly, 0 }, - { "RESETF", 0x04, hndl_resetf, NULL, 0 }, - { "RF", 0x04, hndl_resetf, NULL, 0 }, - { "TJUST", 0x85, hndl_tjust, pgc_parse_bytes, 2 }, - { "TJ", 0x85, hndl_tjust, pgc_parse_bytes, 2 }, - { "TSIZE", 0x81, hndl_tsize, pgc_parse_coords, 1 }, - { "TS", 0x81, hndl_tsize, pgc_parse_coords, 1 }, - { "VWPORT", 0xb2, hndl_vwport, pgc_parse_words, 4 }, - { "VWP", 0xb2, hndl_vwport, pgc_parse_words, 4 }, - { "WINDOW", 0xb3, hndl_window, pgc_parse_words, 4 }, - { "WI", 0xb3, hndl_window, pgc_parse_words, 4 }, + {"AREAPT", 0xe7, hndl_areapt, pgc_parse_words, 16}, + { "AP", 0xe7, hndl_areapt, pgc_parse_words, 16}, + { "~~~~~~", 0x43, hndl_c, NULL, 0 }, + { "CA", 0xd2, hndl_ca, NULL, 0 }, + { "CLBEG", 0x70, hndl_clbeg, NULL, 0 }, + { "CB", 0x70, hndl_clbeg, NULL, 0 }, + { "CLDEL", 0x74, hndl_cldel, pgc_parse_bytes, 1 }, + { "CD", 0x74, hndl_cldel, pgc_parse_bytes, 1 }, + { "CLEND", 0x71, hndl_clend, NULL, 0 }, + { "CLRUN", 0x72, hndl_clrun, pgc_parse_bytes, 1 }, + { "CR", 0x72, hndl_clrun, pgc_parse_bytes, 1 }, + { "CLRD", 0x75, hndl_clread, pgc_parse_bytes, 1 }, + { "CRD", 0x75, hndl_clread, pgc_parse_bytes, 1 }, + { "CLOOP", 0x73, hndl_cloop, NULL, 0 }, + { "CL", 0x73, hndl_cloop, NULL, 0 }, + { "CLEARS", 0x0f, hndl_clears, pgc_parse_bytes, 1 }, + { "CLS", 0x0f, hndl_clears, pgc_parse_bytes, 1 }, + { "COLOR", 0x06, hndl_color, pgc_parse_bytes, 1 }, + { "C", 0x06, hndl_color, pgc_parse_bytes, 1 }, + { "CX", 0xd1, hndl_cx, NULL, 0 }, + { "DISPLA", 0xd0, hndl_display, pgc_parse_bytes, 1 }, + { "DI", 0xd0, hndl_display, pgc_parse_bytes, 1 }, + { "ELIPSE", 0x39, hndl_ellipse, pgc_parse_coords, 2 }, + { "EL", 0x39, hndl_ellipse, pgc_parse_coords, 2 }, + { "IMAGEW", 0xd9, hndl_imagew, NULL, 0 }, + { "IW", 0xd9, hndl_imagew, NULL, 0 }, + { "LINFUN", 0xeb, hndl_linfun, pgc_parse_bytes, 1 }, + { "LF", 0xeb, hndl_linfun, pgc_parse_bytes, 1 }, + { "LINPAT", 0xea, hndl_linpat, pgc_parse_words, 1 }, + { "LP", 0xea, hndl_linpat, pgc_parse_words, 1 }, + { "LUTINT", 0xec, hndl_lutint, pgc_parse_bytes, 1 }, + { "LI", 0xec, hndl_lutint, pgc_parse_bytes, 1 }, + { "LUTRD", 0x50, hndl_lutrd, pgc_parse_bytes, 1 }, + { "LUTSAV", 0xed, hndl_lutsav, NULL, 0 }, + { "LUT", 0xee, hndl_lut, pgc_parse_bytes, 4 }, + { "MOVE", 0x10, hndl_move, pgc_parse_coords, 2 }, + { "M", 0x10, hndl_move, pgc_parse_coords, 2 }, + { "MOVE3", 0x12, hndl_move3, pgc_parse_coords, 3 }, + { "M3", 0x12, hndl_move3, pgc_parse_coords, 3 }, + { "MOVER", 0x11, hndl_mover, pgc_parse_coords, 2 }, + { "MR", 0x11, hndl_mover, pgc_parse_coords, 2 }, + { "MOVER3", 0x13, hndl_mover3, pgc_parse_coords, 3 }, + { "MR3", 0x13, hndl_mover3, pgc_parse_coords, 3 }, + { "PRMFIL", 0xe9, hndl_prmfil, pgc_parse_bytes, 1 }, + { "PF", 0xe9, hndl_prmfil, pgc_parse_bytes, 1 }, + { "POLY", 0x30, hndl_poly, parse_poly, 0 }, + { "P", 0x30, hndl_poly, parse_poly, 0 }, + { "RESETF", 0x04, hndl_resetf, NULL, 0 }, + { "RF", 0x04, hndl_resetf, NULL, 0 }, + { "TJUST", 0x85, hndl_tjust, pgc_parse_bytes, 2 }, + { "TJ", 0x85, hndl_tjust, pgc_parse_bytes, 2 }, + { "TSIZE", 0x81, hndl_tsize, pgc_parse_coords, 1 }, + { "TS", 0x81, hndl_tsize, pgc_parse_coords, 1 }, + { "VWPORT", 0xb2, hndl_vwport, pgc_parse_words, 4 }, + { "VWP", 0xb2, hndl_vwport, pgc_parse_words, 4 }, + { "WINDOW", 0xb3, hndl_window, pgc_parse_words, 4 }, + { "WI", 0xb3, hndl_window, pgc_parse_words, 4 }, - { "@@@@@@", 0x00, NULL, NULL, 0 } + { "@@@@@@", 0x00, NULL, NULL, 0 } }; - /* When the wake timer expires, that's when the drawing thread is actually * woken */ static void wake_timer(void *priv) { - pgc_t *dev = (pgc_t *)priv; + pgc_t *dev = (pgc_t *) priv; #ifdef ENABLE_PGC_LOG - pgc_log("PGC: woke up\n"); + pgc_log("PGC: woke up\n"); #endif thread_set_event(dev->pgc_wake_thread); } - /* * The PGC drawing thread main loop. * @@ -1467,7 +1484,7 @@ wake_timer(void *priv) static void pgc_thread(void *priv) { - pgc_t *dev = (pgc_t *)priv; + pgc_t *dev = (pgc_t *) priv; const pgc_cmd_t *cmd; #ifdef ENABLE_PGC_LOG @@ -1475,28 +1492,28 @@ pgc_thread(void *priv) #endif for (;;) { - if (! parse_command(dev, &cmd)) { - /* Are we shutting down? */ - if (dev->stopped) { + if (!parse_command(dev, &cmd)) { + /* Are we shutting down? */ + if (dev->stopped) { #ifdef ENABLE_PGC_LOG - pgc_log("PGC: Thread stopping...\n"); + pgc_log("PGC: Thread stopping...\n"); #endif - dev->stopped = 0; - break; - } + dev->stopped = 0; + break; + } - /* Nope, just a reset. */ - continue; - } + /* Nope, just a reset. */ + continue; + } - pgc_log("PGC: Command: [%02x] '%s' found = %i\n", - dev->hex_command, dev->asc_command, (cmd != NULL)); + pgc_log("PGC: Command: [%02x] '%s' found = %i\n", + dev->hex_command, dev->asc_command, (cmd != NULL)); - if (cmd) { - dev->result_count = 0; - (*cmd->handler)(dev); - } else - pgc_error(dev, PGC_ERROR_OPCODE); + if (cmd) { + dev->result_count = 0; + (*cmd->handler)(dev); + } else + pgc_error(dev, PGC_ERROR_OPCODE); } #ifdef ENABLE_PGC_LOG @@ -1504,7 +1521,6 @@ pgc_thread(void *priv) #endif } - /* Parameter passed is not a number: abort. */ static int err_digit(pgc_t *dev) @@ -1512,99 +1528,97 @@ err_digit(pgc_t *dev) uint8_t asc; do { - /* Swallow everything until the next separator */ - if (! dev->inputbyte(dev, &asc)) return 0; - } while (! is_whitespace(asc)); + /* Swallow everything until the next separator */ + if (!dev->inputbyte(dev, &asc)) + return 0; + } while (!is_whitespace(asc)); pgc_error(dev, PGC_ERROR_DIGIT); return 0; } - /* Output a byte, either as hex or ASCII depending on the mode. */ int pgc_result_byte(pgc_t *dev, uint8_t val) { char buf[20]; - if (! dev->ascii_mode) - return output_byte(dev, val); + if (!dev->ascii_mode) + return output_byte(dev, val); if (dev->result_count) { - if (! output_byte(dev, ',')) return 0; + if (!output_byte(dev, ',')) + return 0; } sprintf(buf, "%i", val); dev->result_count++; - return output_string(dev, buf); + return output_string(dev, buf); } - /* Output a word, either as hex or ASCII depending on the mode. */ int pgc_result_word(pgc_t *dev, int16_t val) { char buf[20]; - if (! dev->ascii_mode) { - if (! output_byte(dev, val & 0xFF)) return 0; - return output_byte(dev, val >> 8); + if (!dev->ascii_mode) { + if (!output_byte(dev, val & 0xFF)) + return 0; + return output_byte(dev, val >> 8); } if (dev->result_count) { - if (! output_byte(dev, ',')) return 0; + if (!output_byte(dev, ',')) + return 0; } sprintf(buf, "%i", val); dev->result_count++; - return output_string(dev, buf); + return output_string(dev, buf); } - /* Report an error, either in ASCII or in hex. */ int pgc_error(pgc_t *dev, int err) { if (dev->mapram[0x307]) { - /* Errors enabled? */ - if (dev->ascii_mode) { - if (err >= PGC_ERROR_RANGE && err <= PGC_ERROR_MISSING) - return error_string(dev, pgc_err_msgs[err]); - return error_string(dev, "Unknown error\r"); - } else { - return error_byte(dev, err); - } + /* Errors enabled? */ + if (dev->ascii_mode) { + if (err >= PGC_ERROR_RANGE && err <= PGC_ERROR_MISSING) + return error_string(dev, pgc_err_msgs[err]); + return error_string(dev, "Unknown error\r"); + } else { + return error_byte(dev, err); + } } return 1; } - /* Initialize RAM and registers to default values. */ void pgc_reset(pgc_t *dev) { - int n; - memset(dev->mapram, 0x00, sizeof(dev->mapram)); /* The 'CGA disable' jumper is not currently implemented. */ dev->mapram[0x30b] = dev->cga_enabled = 1; - dev->mapram[0x30c] = dev->cga_enabled; - dev->mapram[0x30d] = dev->cga_enabled; + dev->mapram[0x30c] = dev->cga_enabled; + dev->mapram[0x30d] = dev->cga_enabled; - dev->mapram[0x3f8] = 0x03; /* minor version */ - dev->mapram[0x3f9] = 0x01; /* minor version */ - dev->mapram[0x3fb] = 0xa5; /* } */ - dev->mapram[0x3fc] = 0x5a; /* PGC self-test passed */ - dev->mapram[0x3fd] = 0x55; /* } */ - dev->mapram[0x3fe] = 0x5a; /* } */ + dev->mapram[0x3f8] = 0x03; /* minor version */ + dev->mapram[0x3f9] = 0x01; /* minor version */ + dev->mapram[0x3fb] = 0xa5; /* } */ + dev->mapram[0x3fc] = 0x5a; /* PGC self-test passed */ + dev->mapram[0x3fd] = 0x55; /* } */ + dev->mapram[0x3fe] = 0x5a; /* } */ - dev->ascii_mode = 1; /* start off in ASCII mode */ + dev->ascii_mode = 1; /* start off in ASCII mode */ dev->line_pattern = 0xffff; memset(dev->fill_pattern, 0xff, sizeof(dev->fill_pattern)); - dev->color = 0xff; + dev->color = 0xff; dev->tjust_h = 1; dev->tjust_v = 1; @@ -1619,11 +1633,11 @@ pgc_reset(pgc_t *dev) dev->vp_y2 = dev->vish - 1; /* Empty command lists. */ - for (n = 0; n < 256; n++) { - dev->clist[n].wrptr = 0; - dev->clist[n].rdptr = 0; - dev->clist[n].repeat = 0; - dev->clist[n].chain = 0; + for (uint16_t n = 0; n < 256; n++) { + dev->clist[n].wrptr = 0; + dev->clist[n].rdptr = 0; + dev->clist[n].repeat = 0; + dev->clist[n].chain = 0; } dev->clcur = NULL; @@ -1636,106 +1650,100 @@ pgc_reset(pgc_t *dev) hndl_lutsav(dev); } - /* Switch between CGA mode (DISPLAY 1) and native mode (DISPLAY 0). */ void pgc_setdisplay(pgc_t *dev, int cga) { pgc_log("PGC: setdisplay(%i): cga_selected=%i cga_enabled=%i\n", - cga, dev->cga_selected, dev->cga_enabled); + cga, dev->cga_selected, dev->cga_enabled); if (dev->cga_selected != (dev->cga_enabled && cga)) { - dev->cga_selected = (dev->cga_enabled && cga); - dev->displine = 0; + dev->cga_selected = (dev->cga_enabled && cga); + dev->displine = 0; - if (dev->cga_selected) { - mem_mapping_enable(&dev->cga_mapping); - dev->screenw = PGC_CGA_WIDTH; - dev->screenh = PGC_CGA_HEIGHT; - } else { - mem_mapping_disable(&dev->cga_mapping); - dev->screenw = dev->visw; - dev->screenh = dev->vish; - } + if (dev->cga_selected) { + mem_mapping_enable(&dev->cga_mapping); + dev->screenw = PGC_CGA_WIDTH; + dev->screenh = PGC_CGA_HEIGHT; + } else { + mem_mapping_disable(&dev->cga_mapping); + dev->screenw = dev->visw; + dev->screenh = dev->vish; + } - pgc_recalctimings(dev); + pgc_recalctimings(dev); } } - /* * When idle, the PGC drawing thread sleeps. pgc_wake() awakens it - but - * not immediately. Like the Voodoo, it has a short delay so that writes + * not immediately. Like the Voodoo, it has a short delay so that writes * can be batched. */ void pgc_wake(pgc_t *dev) { if (!timer_is_enabled(&dev->wake_timer)) - timer_set_delay_u64(&dev->wake_timer, WAKE_DELAY); + timer_set_delay_u64(&dev->wake_timer, WAKE_DELAY); } - /* Wait for more input data, or for output to drain. */ void pgc_sleep(pgc_t *dev) { pgc_log("PGC: sleeping on %i %i %i %i 0x%02x 0x%02x\n", - dev->stopped, - dev->waiting_input_fifo, dev->waiting_output_fifo, - dev->waiting_error_fifo, dev->mapram[0x300], dev->mapram[0x301]); + dev->stopped, + dev->waiting_input_fifo, dev->waiting_output_fifo, + dev->waiting_error_fifo, dev->mapram[0x300], dev->mapram[0x301]); /* Avoid entering waiting state. */ if (dev->stopped) { - dev->waiting_input_fifo = 0; - dev->waiting_output_fifo = 0; - return; + dev->waiting_input_fifo = 0; + dev->waiting_output_fifo = 0; + return; } /* Race condition: If host wrote to the PGC during the that * won't be noticed */ - if (dev->waiting_input_fifo && - dev->mapram[0x300] != dev->mapram[0x301]) { - dev->waiting_input_fifo = 0; - return; + if (dev->waiting_input_fifo && dev->mapram[0x300] != dev->mapram[0x301]) { + dev->waiting_input_fifo = 0; + return; } /* Same if they read. */ - if (dev->waiting_output_fifo && - dev->mapram[0x302] != (uint8_t)(dev->mapram[0x303] - 1)) { - dev->waiting_output_fifo = 0; - return; + if (dev->waiting_output_fifo && dev->mapram[0x302] != (uint8_t) (dev->mapram[0x303] - 1)) { + dev->waiting_output_fifo = 0; + return; } thread_wait_event(dev->pgc_wake_thread, -1); thread_reset_event(dev->pgc_wake_thread); } - /* Pull the next byte from the current command list. */ int pgc_clist_byte(pgc_t *dev, uint8_t *val) { - if (dev->clcur == NULL) return 0; + if (dev->clcur == NULL) + return 0; if (dev->clcur->rdptr < dev->clcur->wrptr) - *val = dev->clcur->list[dev->clcur->rdptr++]; - else - *val = 0; + *val = dev->clcur->list[dev->clcur->rdptr++]; + else + *val = 0; /* If we've reached the end, reset to the beginning and * (if repeating) run the repeat */ if (dev->clcur->rdptr >= dev->clcur->wrptr) { - dev->clcur->rdptr = 0; - dev->clcur->repeat--; - if (dev->clcur->repeat == 0) - dev->clcur = dev->clcur->chain; + dev->clcur->rdptr = 0; + dev->clcur->repeat--; + if (dev->clcur->repeat == 0) + dev->clcur = dev->clcur->chain; } return 1; } - /* * Read in a byte, either as hex (1 byte) or ASCII (decimal). * Returns 0 if PGC reset detected while the value is being read. @@ -1746,24 +1754,24 @@ pgc_param_byte(pgc_t *dev, uint8_t *val) int32_t c; if (dev->clcur) - return pgc_clist_byte(dev, val); + return pgc_clist_byte(dev, val); - if (! dev->ascii_mode) - return dev->inputbyte(dev, val); + if (!dev->ascii_mode) + return dev->inputbyte(dev, val); - if (! pgc_param_coord(dev, &c)) return 0; + if (!pgc_param_coord(dev, &c)) + return 0; - c = (c >> 16); /* drop fractional part */ + c = (c >> 16); /* drop fractional part */ if (c > 255) { - pgc_error(dev, PGC_ERROR_RANGE); - return 0; + pgc_error(dev, PGC_ERROR_RANGE); + return 0; } - *val = (uint8_t)c; + *val = (uint8_t) c; return 1; } - /* * Read in a word, either as hex (2 bytes) or ASCII (decimal). * Returns 0 if PGC reset detected while the value is being read. @@ -1771,45 +1779,49 @@ pgc_param_byte(pgc_t *dev, uint8_t *val) int pgc_param_word(pgc_t *dev, int16_t *val) { - uint8_t lo, hi; + uint8_t lo; + uint8_t hi; int32_t c; if (dev->clcur) { - if (! pgc_clist_byte(dev, &lo)) return 0; - if (! pgc_clist_byte(dev, &hi)) return 0; - *val = (((int16_t)hi) << 8) | lo; + if (!pgc_clist_byte(dev, &lo)) + return 0; + if (!pgc_clist_byte(dev, &hi)) + return 0; + *val = (((int16_t) hi) << 8) | lo; - return 1; + return 1; } - if (! dev->ascii_mode) { - if (! dev->inputbyte(dev, &lo)) return 0; - if (! dev->inputbyte(dev, &hi)) return 0; - *val = (((int16_t)hi) << 8) | lo; + if (!dev->ascii_mode) { + if (!dev->inputbyte(dev, &lo)) + return 0; + if (!dev->inputbyte(dev, &hi)) + return 0; + *val = (((int16_t) hi) << 8) | lo; - return 1; + return 1; } - if (! pgc_param_coord(dev, &c)) return 0; + if (!pgc_param_coord(dev, &c)) + return 0; c = (c >> 16); if (c > 0x7fff || c < -0x7fff) { - pgc_error(dev, PGC_ERROR_RANGE); - return 0; + pgc_error(dev, PGC_ERROR_RANGE); + return 0; } - *val = (int16_t)c; + *val = (int16_t) c; return 1; } - typedef enum { PS_MAIN, PS_FRACTION, PS_EXPONENT } parse_state_t; - /* * Read in a PGC coordinate. * @@ -1820,136 +1832,142 @@ typedef enum { int pgc_param_coord(pgc_t *dev, int32_t *value) { - uint8_t asc; - int sign = 1; - int esign = 1; - int n; - uint16_t dp = 1; - uint16_t integer = 0; - uint16_t frac = 0; - uint16_t exponent = 0; - uint32_t res; + uint8_t asc; + int sign = 1; + int esign = 1; + int n; + uint16_t dp = 1; + uint16_t integer = 0; + uint16_t frac = 0; + uint16_t exponent = 0; + uint32_t res; parse_state_t state = PS_MAIN; - uint8_t encoded[4]; + uint8_t encoded[4]; /* If there is a command list running, pull the bytes out of that * command list */ if (dev->clcur) { - for (n = 0; n < 4; n++) - if (! pgc_clist_byte(dev, &encoded[n])) return 0; - integer = (((int16_t)encoded[1]) << 8) | encoded[0]; - frac = (((int16_t)encoded[3]) << 8) | encoded[2]; + for (n = 0; n < 4; n++) + if (!pgc_clist_byte(dev, &encoded[n])) + return 0; + integer = (((int16_t) encoded[1]) << 8) | encoded[0]; + frac = (((int16_t) encoded[3]) << 8) | encoded[2]; - *value = (((int32_t)integer) << 16) | frac; - return 1; + *value = (((int32_t) integer) << 16) | frac; + return 1; } - /* If in hex mode, read in the encoded integer and fraction parts + /* If in hex mode, read in the encoded integer and fraction parts * from the hex stream */ - if (! dev->ascii_mode) { - for (n = 0; n < 4; n++) - if (! dev->inputbyte(dev, &encoded[n])) return 0; - integer = (((int16_t)encoded[1]) << 8) | encoded[0]; - frac = (((int16_t)encoded[3]) << 8) | encoded[2]; + if (!dev->ascii_mode) { + for (n = 0; n < 4; n++) + if (!dev->inputbyte(dev, &encoded[n])) + return 0; + integer = (((int16_t) encoded[1]) << 8) | encoded[0]; + frac = (((int16_t) encoded[3]) << 8) | encoded[2]; - *value = (((int32_t)integer) << 16) | frac; - return 1; + *value = (((int32_t) integer) << 16) | frac; + return 1; } /* Parsing an ASCII value; skip separators. */ do { - if (! dev->inputbyte(dev, &asc)) return 0; - if (asc == '-') sign = -1; - } while (is_whitespace(asc)); + if (!dev->inputbyte(dev, &asc)) + return 0; + if (asc == '-') + sign = -1; + } while (is_whitespace(asc)); /* There had better be a digit next. */ - if (! isdigit(asc)) { - pgc_error(dev, PGC_ERROR_MISSING); - return 0; + if (!isdigit(asc)) { + pgc_error(dev, PGC_ERROR_MISSING); + return 0; } do { - switch (asc) { - /* Decimal point is acceptable in 'main' state - * (start of fraction) not otherwise */ - case '.': - if (state == PS_MAIN) { - if (! dev->inputbyte(dev, &asc)) return 0; - state = PS_FRACTION; - continue; - } else { - pgc_error(dev, PGC_ERROR_MISSING); - return err_digit(dev); - } - break; + switch (asc) { + /* Decimal point is acceptable in 'main' state + * (start of fraction) not otherwise */ + case '.': + if (state == PS_MAIN) { + if (!dev->inputbyte(dev, &asc)) + return 0; + state = PS_FRACTION; + continue; + } else { + pgc_error(dev, PGC_ERROR_MISSING); + return err_digit(dev); + } - /* Scientific notation. */ - case 'd': - case 'D': - case 'e': - case 'E': - esign = 1; - if (! dev->inputbyte(dev, &asc)) return 0; - if (asc == '-') { - sign = -1; - if (! dev->inputbyte(dev, &asc)) return 0; - } - state = PS_EXPONENT; - continue; + /* Scientific notation. */ + case 'd': + case 'D': + case 'e': + case 'E': + esign = 1; + if (!dev->inputbyte(dev, &asc)) + return 0; + if (asc == '-') { + sign = -1; + if (!dev->inputbyte(dev, &asc)) + return 0; + } + state = PS_EXPONENT; + continue; - /* Should be a number or a separator. */ - default: - if (is_whitespace(asc)) break; - if (! isdigit(asc)) { - pgc_error(dev, PGC_ERROR_MISSING); - return err_digit(dev); - } - asc -= '0'; /* asc is digit */ + /* Should be a number or a separator. */ + default: + if (is_whitespace(asc)) + break; + if (!isdigit(asc)) { + pgc_error(dev, PGC_ERROR_MISSING); + return err_digit(dev); + } + asc -= '0'; /* asc is digit */ - switch (state) { - case PS_MAIN: - integer = (integer * 10)+asc; - if (integer & 0x8000) { - /* Overflow */ - pgc_error(dev, PGC_ERROR_RANGE); - integer = 0x7fff; - } - break; + switch (state) { + case PS_MAIN: + integer = (integer * 10) + asc; + if (integer & 0x8000) { + /* Overflow */ + pgc_error(dev, PGC_ERROR_RANGE); + integer = 0x7fff; + } + break; - case PS_FRACTION: - frac = (frac * 10) + asc; - dp *= 10; - break; + case PS_FRACTION: + frac = (frac * 10) + asc; + dp *= 10; + break; - case PS_EXPONENT: - exponent = (exponent * 10)+asc; - break; - } - - } + case PS_EXPONENT: + exponent = (exponent * 10) + asc; + break; + } + } - if (! dev->inputbyte(dev, &asc)) return 0; - } while (! is_whitespace(asc)); + if (!dev->inputbyte(dev, &asc)) + return 0; + } while (!is_whitespace(asc)); res = (frac << 16) / dp; pgc_log("PGC: integer=%u frac=%u exponent=%u dp=%i res=0x%08lx\n", - integer, frac, exponent, dp, res); + integer, frac, exponent, dp, res); res = (res & 0xffff) | (integer << 16); if (exponent) { - for (n = 0; n < exponent; n++) { - if (esign > 0) - res *= 10; - else - res /= 10; - } + for (n = 0; n < exponent; n++) { + if (esign > 0) + res *= 10; + else + res /= 10; + } } - *value = sign*res; + *value = sign * res; return 1; } - /* * Add a byte to a command list. * @@ -1961,26 +1979,26 @@ pgc_cl_append(pgc_cl_t *list, uint8_t v) uint8_t *buf; if (list->listmax == 0 || list->list == NULL) { - list->list = (uint8_t *)malloc(4096); - if (!list->list) { + list->list = (uint8_t *) malloc(4096); + if (!list->list) { #ifdef ENABLE_PGC_LOG - pgc_log("PGC: out of memory initializing command list\n"); + pgc_log("PGC: out of memory initializing command list\n"); #endif - return 0; - } - list->listmax = 4096; + return 0; + } + list->listmax = 4096; } while (list->wrptr >= list->listmax) { - buf = (uint8_t *)realloc(list->list, 2 * list->listmax); - if (!buf) { + buf = (uint8_t *) realloc(list->list, 2 * list->listmax); + if (!buf) { #ifdef ENABLE_PGC_LOG - pgc_log("PGC: out of memory growing command list\n"); + pgc_log("PGC: out of memory growing command list\n"); #endif - return 0; - } - list->list = buf; - list->listmax *= 2; + return 0; + } + list->list = buf; + list->listmax *= 2; } list->list[list->wrptr++] = v; @@ -1988,30 +2006,28 @@ pgc_cl_append(pgc_cl_t *list, uint8_t v) return 1; } - /* Parse but don't execute a command with a fixed number of byte parameters. */ int pgc_parse_bytes(pgc_t *dev, pgc_cl_t *cl, int count) { - uint8_t *param = (uint8_t *)malloc(count); - int n; + uint8_t *param = (uint8_t *) malloc(count); - if (! param) { - pgc_error(dev, PGC_ERROR_OVERFLOW); - return 0; + if (!param) { + pgc_error(dev, PGC_ERROR_OVERFLOW); + return 0; } - for (n = 0; n < count; n++) { - if (! pgc_param_byte(dev, ¶m[n])) { - free(param); - return 0; - } + for (int n = 0; n < count; n++) { + if (!pgc_param_byte(dev, ¶m[n])) { + free(param); + return 0; + } - if (! pgc_cl_append(cl, param[n])) { - pgc_error(dev, PGC_ERROR_OVERFLOW); - free(param); - return 0; - } + if (!pgc_cl_append(cl, param[n])) { + pgc_error(dev, PGC_ERROR_OVERFLOW); + free(param); + return 0; + } } free(param); @@ -2019,31 +2035,28 @@ pgc_parse_bytes(pgc_t *dev, pgc_cl_t *cl, int count) return 1; } - /* Parse but don't execute a command with a fixed number of word parameters. */ int pgc_parse_words(pgc_t *dev, pgc_cl_t *cl, int count) { - int16_t *param = (int16_t *)malloc(count * sizeof(int16_t)); - int n; + int16_t *param = (int16_t *) malloc(count * sizeof(int16_t)); - if (! param) { - pgc_error(dev, PGC_ERROR_OVERFLOW); - return 0; + if (!param) { + pgc_error(dev, PGC_ERROR_OVERFLOW); + return 0; } - for (n = 0; n < count; n++) { - if (! pgc_param_word(dev, ¶m[n])) { - free(param); - return 0; - } + for (int n = 0; n < count; n++) { + if (!pgc_param_word(dev, ¶m[n])) { + free(param); + return 0; + } - if (!pgc_cl_append(cl, param[n] & 0xff) || - !pgc_cl_append(cl, param[n] >> 8)) { - pgc_error(dev, PGC_ERROR_OVERFLOW); - free(param); - return 0; - } + if (!pgc_cl_append(cl, param[n] & 0xff) || !pgc_cl_append(cl, param[n] >> 8)) { + pgc_error(dev, PGC_ERROR_OVERFLOW); + free(param); + return 0; + } } free(param); @@ -2051,43 +2064,40 @@ pgc_parse_words(pgc_t *dev, pgc_cl_t *cl, int count) return 1; } - /* Parse but don't execute a command with a fixed number of coord parameters */ int pgc_parse_coords(pgc_t *dev, pgc_cl_t *cl, int count) { - int32_t *param = (int32_t *)malloc(count * sizeof(int32_t)); - int n; + int32_t *param = (int32_t *) malloc(count * sizeof(int32_t)); + int n; - if (! param) { - pgc_error(dev, PGC_ERROR_OVERFLOW); - return 0; + if (!param) { + pgc_error(dev, PGC_ERROR_OVERFLOW); + return 0; } for (n = 0; n < count; n++) { - if (! pgc_param_coord(dev, ¶m[n])) { - free(param); - return 0; - } + if (!pgc_param_coord(dev, ¶m[n])) { + free(param); + return 0; + } } /* Here is how the real PGC serializes coords: * - * 100.5 -> 64 00 00 80 ie 0064.8000 + * 100.5 -> 64 00 00 80 ie 0064.8000 * 100.3 -> 64 00 CD 4C ie 0064.4CCD */ for (n = 0; n < count; n++) { - /* Serialize integer part. */ - if (!pgc_cl_append(cl, (param[n] >> 16) & 0xff) || - !pgc_cl_append(cl, (param[n] >> 24) & 0xff) || + /* Serialize integer part. */ + if (!pgc_cl_append(cl, (param[n] >> 16) & 0xff) || !pgc_cl_append(cl, (param[n] >> 24) & 0xff) || - /* Serialize fraction part. */ - !pgc_cl_append(cl, (param[n] ) & 0xff) || - !pgc_cl_append(cl, (param[n] >> 8) & 0xff)) { - pgc_error(dev, PGC_ERROR_OVERFLOW); - free(param); - return 0; - } + /* Serialize fraction part. */ + !pgc_cl_append(cl, (param[n]) & 0xff) || !pgc_cl_append(cl, (param[n] >> 8) & 0xff)) { + pgc_error(dev, PGC_ERROR_OVERFLOW); + free(param); + return 0; + } } free(param); @@ -2095,8 +2105,7 @@ pgc_parse_coords(pgc_t *dev, pgc_cl_t *cl, int count) return 1; } - -/* Convert coordinates based on the current window / viewport to raster +/* Convert coordinates based on the current window / viewport to raster * coordinates. */ void pgc_dto_raster(pgc_t *dev, double *x, double *y) @@ -2111,114 +2120,125 @@ pgc_dto_raster(pgc_t *dev, double *x, double *y) pgc_log("PGC: coords to raster: (%f, %f) -> (%f, %f)\n", x0, y0, *x, *y); } - /* Overloads that take ints. */ void pgc_sto_raster(pgc_t *dev, int16_t *x, int16_t *y) { - double xd = *x, yd = *y; + double xd = *x; + double yd = *y; pgc_dto_raster(dev, &xd, &yd); - *x = (int16_t)xd; - *y = (int16_t)yd; + *x = (int16_t) xd; + *y = (int16_t) yd; } - void pgc_ito_raster(pgc_t *dev, int32_t *x, int32_t *y) { - double xd = *x, yd = *y; + double xd = *x; + double yd = *y; pgc_dto_raster(dev, &xd, &yd); - *x = (int32_t)xd; - *y = (int32_t)yd; + *x = (int32_t) xd; + *y = (int32_t) yd; } - void pgc_recalctimings(pgc_t *dev) { - double disptime, _dispontime, _dispofftime; - double pixel_clock = (cpuclock * (double)(1ull << 32)) / (dev->cga_selected ? 25175000.0 : dev->native_pixel_clock); + double disptime; + double _dispontime; + double _dispofftime; + double pixel_clock = (cpuclock / (dev->cga_selected ? 25175000.0 : dev->native_pixel_clock) * (double) (1ULL << 32)); + uint8_t crtc0 = 97; /* Value from MDA, taken from there due to the 25 MHz refresh rate. */ + uint8_t crtc1 = 80; /* Value from MDA, taken from there due to the 25 MHz refresh rate. */ + /* Multiply pixel clock by 8. */ + pixel_clock *= 8.0; /* Use a fixed 640x400 display. */ - disptime = dev->screenw + 11; - _dispontime = dev->screenw * pixel_clock; - _dispofftime = (disptime - dev->screenw) * pixel_clock; - dev->dispontime = (uint64_t)(_dispontime); - dev->dispofftime = (uint64_t)(_dispofftime); + disptime = crtc0 + 1; + _dispontime = crtc1; + _dispofftime = disptime - _dispontime; + _dispontime *= pixel_clock; + _dispofftime *= pixel_clock; + dev->dispontime = (uint64_t) (_dispontime); + dev->dispofftime = (uint64_t) (_dispofftime); } - /* Write to CGA registers are copied into the transfer memory buffer. */ void pgc_out(uint16_t addr, uint8_t val, void *priv) { - pgc_t *dev = (pgc_t *)priv; + pgc_t *dev = (pgc_t *) priv; pgc_log("PGC: out(%04x, %02x)\n", addr, val); - switch(addr) { - case 0x03d0: /* CRTC Index register */ - case 0x03d2: - case 0x03d4: - case 0x03d6: - dev->mapram[0x03d0] = val; - break; + switch (addr) { + case 0x03d0: /* CRTC Index register */ + case 0x03d2: + case 0x03d4: + case 0x03d6: + dev->mapram[0x03d0] = val; + break; - case 0x03d1: /* CRTC Data register */ - case 0x03d3: - case 0x03d5: - case 0x03d7: - if (dev->mapram[0x03d0] < 18) - dev->mapram[0x03e0 + dev->mapram[0x03d0]] = val; - break; + case 0x03d1: /* CRTC Data register */ + case 0x03d3: + case 0x03d5: + case 0x03d7: + if (dev->mapram[0x03d0] < 18) + dev->mapram[0x03e0 + dev->mapram[0x03d0]] = val; + break; - case 0x03d8: /* CRTC Mode Control register */ - dev->mapram[0x03d8] = val; - break; + case 0x03d8: /* CRTC Mode Control register */ + dev->mapram[0x03d8] = val; + break; - case 0x03d9: /* CRTC Color Select register */ - dev->mapram[0x03d9] = val; - break; + case 0x03d9: /* CRTC Color Select register */ + dev->mapram[0x03d9] = val; + break; + + default: + break; } } - /* Read back the CGA registers. */ uint8_t pgc_in(uint16_t addr, void *priv) { - pgc_t *dev = (pgc_t *)priv; - uint8_t ret = 0xff; + const pgc_t *dev = (pgc_t *) priv; + uint8_t ret = 0xff; - switch(addr) { - case 0x03d0: /* CRTC Index register */ - case 0x03d2: - case 0x03d4: - case 0x03d6: - ret = dev->mapram[0x03d0]; - break; + switch (addr) { + case 0x03d0: /* CRTC Index register */ + case 0x03d2: + case 0x03d4: + case 0x03d6: + ret = dev->mapram[0x03d0]; + break; - case 0x03d1: /* CRTC Data register */ - case 0x03d3: - case 0x03d5: - case 0x03d7: - if (dev->mapram[0x03d0] < 18) - ret = dev->mapram[0x03e0 + dev->mapram[0x03d0]]; - break; + case 0x03d1: /* CRTC Data register */ + case 0x03d3: + case 0x03d5: + case 0x03d7: + if (dev->mapram[0x03d0] < 18) + ret = dev->mapram[0x03e0 + dev->mapram[0x03d0]]; + break; - case 0x03d8: /* CRTC Mode Control register */ - ret = dev->mapram[0x03d8]; - break; + case 0x03d8: /* CRTC Mode Control register */ + ret = dev->mapram[0x03d8]; + break; - case 0x03d9: /* CRTC Color Select register */ - ret = dev->mapram[0x03d9]; - break; + case 0x03d9: /* CRTC Color Select register */ + ret = dev->mapram[0x03d9]; + break; - case 0x03da: /* CRTC Status register */ - ret = dev->mapram[0x03da]; - break; + case 0x03da: /* CRTC Status register */ + ret = dev->mapram[0x03da]; + break; + + default: + break; } pgc_log("PGC: in(%04x) = %02x\n", addr, ret); @@ -2226,163 +2246,161 @@ pgc_in(uint16_t addr, void *priv) return ret; } - /* Memory write to the transfer buffer. */ /* TODO: Check the CGA mapping repeat stuff. */ void pgc_write(uint32_t addr, uint8_t val, void *priv) { - pgc_t *dev = (pgc_t *)priv; + pgc_t *dev = (pgc_t *) priv; /* - * It seems variable whether the PGC maps 1K or 2K at 0xc6000. + * It seems variable whether the PGC maps 1K or 2K at 0xc6000. * * Map 2K here in case a clone requires it. */ if (addr >= 0xc6000 && addr < 0xc6800) { - addr &= 0x7ff; + addr &= 0x7ff; - /* If one of the FIFOs has been updated, this may cause - * the drawing thread to be woken */ + /* If one of the FIFOs has been updated, this may cause + * the drawing thread to be woken */ - if (dev->mapram[addr] != val) { - dev->mapram[addr] = val; + if (dev->mapram[addr] != val) { + dev->mapram[addr] = val; - switch (addr) { - case 0x300: /* input write pointer */ - if (dev->waiting_input_fifo && - dev->mapram[0x300] != dev->mapram[0x301]) { - dev->waiting_input_fifo = 0; - pgc_wake(dev); - } - break; + switch (addr) { + case 0x300: /* input write pointer */ + if (dev->waiting_input_fifo && dev->mapram[0x300] != dev->mapram[0x301]) { + dev->waiting_input_fifo = 0; + pgc_wake(dev); + } + break; - case 0x303: /* output read pointer */ - if (dev->waiting_output_fifo && - dev->mapram[0x302] != (uint8_t)(dev->mapram[0x303] - 1)) { - dev->waiting_output_fifo = 0; - pgc_wake(dev); - } - break; - - case 0x305: /* error read pointer */ - if (dev->waiting_error_fifo && - dev->mapram[0x304] != (uint8_t)(dev->mapram[0x305] - 1)) { - dev->waiting_error_fifo = 0; - pgc_wake(dev); - } - break; + case 0x303: /* output read pointer */ + if (dev->waiting_output_fifo && dev->mapram[0x302] != (uint8_t) (dev->mapram[0x303] - 1)) { + dev->waiting_output_fifo = 0; + pgc_wake(dev); + } + break; - case 0x306: /* cold start flag */ - /* XXX This should be in IM-1024 specific code */ - dev->mapram[0x306] = 0; - break; + case 0x305: /* error read pointer */ + if (dev->waiting_error_fifo && dev->mapram[0x304] != (uint8_t) (dev->mapram[0x305] - 1)) { + dev->waiting_error_fifo = 0; + pgc_wake(dev); + } + break; - case 0x30c: /* display type */ - pgc_setdisplay(priv, dev->mapram[0x30c]); - dev->mapram[0x30d] = dev->mapram[0x30c]; - break; + case 0x306: /* cold start flag */ + /* XXX This should be in IM-1024 specific code */ + dev->mapram[0x306] = 0; + break; - case 0x3ff: /* reboot the PGC */ - pgc_wake(dev); - break; - } - } + case 0x30c: /* display type */ + pgc_setdisplay(priv, dev->mapram[0x30c]); + dev->mapram[0x30d] = dev->mapram[0x30c]; + break; + + case 0x3ff: /* reboot the PGC */ + pgc_wake(dev); + break; + + default: + break; + } + } } if (addr >= 0xb8000 && addr < 0xc0000 && dev->cga_selected) { - addr &= 0x3fff; - dev->cga_vram[addr] = val; + addr &= 0x3fff; + dev->cga_vram[addr] = val; } } - /* TODO: Check the CGA mapping repeat stuff. */ uint8_t pgc_read(uint32_t addr, void *priv) { - pgc_t *dev = (pgc_t *)priv; - uint8_t ret = 0xff; + const pgc_t *dev = (pgc_t *) priv; + uint8_t ret = 0xff; if (addr >= 0xc6000 && addr < 0xc6800) { - addr &= 0x7ff; - ret = dev->mapram[addr]; + addr &= 0x7ff; + ret = dev->mapram[addr]; } else if (addr >= 0xb8000 && addr < 0xc0000 && dev->cga_selected) { - addr &= 0x3fff; - ret = dev->cga_vram[addr]; + addr &= 0x3fff; + ret = dev->cga_vram[addr]; } return ret; } - /* Draw the display in CGA (640x400) text mode. */ void pgc_cga_text(pgc_t *dev, int w) { - int x, c; - uint8_t chr, attr; - int drawcursor = 0; - uint32_t cols[2]; - int pitch = (dev->mapram[0x3e9] + 1) * 2; - uint16_t sc = (dev->displine & 0x0f) % pitch; - uint16_t ma = (dev->mapram[0x3ed] | (dev->mapram[0x3ec] << 8)) & 0x3fff; - uint16_t ca = (dev->mapram[0x3ef] | (dev->mapram[0x3ee] << 8)) & 0x3fff; - uint8_t *addr; - uint32_t val; - int cw = (w == 80) ? 8 : 16; + uint8_t chr; + uint8_t attr; + int drawcursor = 0; + uint32_t cols[2]; + int pitch = (dev->mapram[0x3e9] + 1) * 2; + uint16_t sc = (dev->displine & 0x0f) % pitch; + uint16_t ma = (dev->mapram[0x3ed] | (dev->mapram[0x3ec] << 8)) & 0x3fff; + uint16_t ca = (dev->mapram[0x3ef] | (dev->mapram[0x3ee] << 8)) & 0x3fff; + const uint8_t *addr; + uint32_t val; + int cw = (w == 80) ? 8 : 16; addr = &dev->cga_vram[((ma + ((dev->displine / pitch) * w)) * 2) & 0x3ffe]; - ma += (dev->displine / pitch) * w; + ma += (dev->displine / pitch) * w; - for (x = 0; x < w; x++) { - chr = *addr++; - attr = *addr++; + for (int x = 0; x < w; x++) { + chr = *addr++; + attr = *addr++; - /* Cursor enabled? */ - if (ma == ca && (dev->cgablink & 8) && - (dev->mapram[0x3ea] & 0x60) != 0x20) { - drawcursor = ((dev->mapram[0x3ea] & 0x1f) <= (sc >> 1)) && - ((dev->mapram[0x3eb] & 0x1f) >= (sc >> 1)); - } else - drawcursor = 0; + /* Cursor enabled? */ + if (ma == ca && (dev->cgablink & 8) && (dev->mapram[0x3ea] & 0x60) != 0x20) { + drawcursor = ((dev->mapram[0x3ea] & 0x1f) <= (sc >> 1)) && ((dev->mapram[0x3eb] & 0x1f) >= (sc >> 1)); + } else + drawcursor = 0; - if (dev->mapram[0x3d8] & 0x20) { - cols[1] = (attr & 15) + 16; - cols[0] = ((attr >> 4) & 7) + 16; - if ((dev->cgablink & 8) && (attr & 0x80) && !drawcursor) - cols[1] = cols[0]; - } else { - cols[1] = (attr & 15) + 16; - cols[0] = (attr >> 4) + 16; - } + if (dev->mapram[0x3d8] & 0x20) { + cols[1] = (attr & 15) + 16; + cols[0] = ((attr >> 4) & 7) + 16; + if ((dev->cgablink & 8) && (attr & 0x80) && !drawcursor) + cols[1] = cols[0]; + } else { + cols[1] = (attr & 15) + 16; + cols[0] = (attr >> 4) + 16; + } - for (c = 0; c < cw; c++) { - if (drawcursor) - val = cols[(fontdatm[chr + dev->fontbase][sc] & (1 << (c ^ 7))) ? 1 : 0] ^ 0x0f; - else - val = cols[(fontdatm[chr + dev->fontbase][sc] & (1 << (c ^ 7))) ? 1 : 0]; - buffer32->line[dev->displine][(x * cw) + c] = val; - } + for (int c = 0; c < cw; c++) { + if (drawcursor) + val = cols[(fontdatm[chr + dev->fontbase][sc] & (1 << (c ^ 7))) ? 1 : 0] ^ 0x0f; + else + val = cols[(fontdatm[chr + dev->fontbase][sc] & (1 << (c ^ 7))) ? 1 : 0]; + if (cw == 8) /* 80x25 CGA text screen. */ + buffer32->line[dev->displine][(x * cw) + c] = val; + else { /* 40x25 CGA text screen. */ + buffer32->line[dev->displine][(x * cw) + (c * 2)] = val; + buffer32->line[dev->displine][(x * cw) + (c * 2) + 1] = val; + } + } - ma++; + ma++; } } - /* Draw the display in CGA (320x200) graphics mode. */ void pgc_cga_gfx40(pgc_t *dev) { - int x, c; - uint32_t cols[4]; - int col; - uint16_t ma = (dev->mapram[0x3ed] | (dev->mapram[0x3ec] << 8)) & 0x3fff; - uint8_t *addr; - uint16_t dat; + uint32_t cols[4]; + int col; + uint16_t ma = (dev->mapram[0x3ed] | (dev->mapram[0x3ec] << 8)) & 0x3fff; + const uint8_t *addr; + uint16_t dat; cols[0] = (dev->mapram[0x3d9] & 15) + 16; - col = ((dev->mapram[0x3d9] & 16) ? 8 : 0) + 16; + col = ((dev->mapram[0x3d9] & 16) ? 8 : 0) + 16; /* From John Elliott's site: On a real CGA, if bit 2 of port 03D8h and bit 5 of port 03D9h are both set, @@ -2390,219 +2408,214 @@ pgc_cga_gfx40(pgc_t *dev) magenta/cyan/white. You still get red/cyan/white if bit 5 of port 03D9h is not set. This is a firmware issue rather than hardware. */ if (dev->mapram[0x3d9] & 32) { - cols[1] = col | 3; - cols[2] = col | 5; - cols[3] = col | 7; + cols[1] = col | 3; + cols[2] = col | 5; + cols[3] = col | 7; } else if (dev->mapram[0x3d8] & 4) { - cols[1] = col | 3; - cols[2] = col | 4; - cols[3] = col | 7; - } else { - cols[1] = col | 2; - cols[2] = col | 4; - cols[3] = col | 6; + cols[1] = col | 3; + cols[2] = col | 4; + cols[3] = col | 7; + } else { + cols[1] = col | 2; + cols[2] = col | 4; + cols[3] = col | 6; } - for (x = 0; x < 40; x++) { - addr = &dev->cga_vram[(ma + 2 * x + 80 * (dev->displine >> 2) + 0x2000 * ((dev->displine >> 1) & 1)) & 0x3fff]; - dat = (addr[0] << 8) | addr[1]; - dev->ma++; - for (c = 0; c < 8; c++) { - buffer32->line[dev->displine][(x << 4) + (c << 1)] = - buffer32->line[dev->displine][(x << 4) + (c << 1) + 1] = cols[dat >> 14]; - dat <<= 2; - } + for (uint8_t x = 0; x < 40; x++) { + addr = &dev->cga_vram[(ma + 2 * x + 80 * (dev->displine >> 2) + 0x2000 * ((dev->displine >> 1) & 1)) & 0x3fff]; + dat = (addr[0] << 8) | addr[1]; + dev->ma++; + for (uint8_t c = 0; c < 8; c++) { + buffer32->line[dev->displine][(x << 4) + (c << 1)] = buffer32->line[dev->displine][(x << 4) + (c << 1) + 1] = cols[dat >> 14]; + dat <<= 2; + } } } - /* Draw the display in CGA (640x200) graphics mode. */ void pgc_cga_gfx80(pgc_t *dev) { - int x, c; - uint32_t cols[2]; - uint16_t ma = (dev->mapram[0x3ed] | (dev->mapram[0x3ec] << 8)) & 0x3fff; - uint8_t *addr; - uint16_t dat; + uint32_t cols[2]; + uint16_t ma = (dev->mapram[0x3ed] | (dev->mapram[0x3ec] << 8)) & 0x3fff; + const uint8_t *addr; + uint16_t dat; cols[0] = 16; cols[1] = (dev->mapram[0x3d9] & 15) + 16; - for (x = 0; x < 40; x++) { - addr = &dev->cga_vram[(ma + 2 * x + 80 * (dev->displine >> 2) + 0x2000 * ((dev->displine >> 1) & 1)) & 0x3fff]; - dat = (addr[0] << 8) | addr[1]; - dev->ma++; - for (c = 0; c < 16; c++) { - buffer32->line[dev->displine][(x << 4) + c] = cols[dat >> 15]; - dat <<= 1; - } + for (uint8_t x = 0; x < 40; x++) { + addr = &dev->cga_vram[(ma + 2 * x + 80 * (dev->displine >> 2) + 0x2000 * ((dev->displine >> 1) & 1)) & 0x3fff]; + dat = (addr[0] << 8) | addr[1]; + dev->ma++; + for (uint8_t c = 0; c < 16; c++) { + buffer32->line[dev->displine][(x << 4) + c] = cols[dat >> 15]; + dat <<= 1; + } } } - /* Draw the screen in CGA mode. */ void pgc_cga_poll(pgc_t *dev) { uint32_t cols[2]; - if (! dev->linepos) { - timer_advance_u64(&dev->timer, dev->dispofftime); - dev->mapram[0x03da] |= 1; - dev->linepos = 1; + if (!dev->linepos) { + timer_advance_u64(&dev->timer, dev->dispofftime); + dev->mapram[0x03da] |= 1; + dev->linepos = 1; - if (dev->cgadispon) { - if (dev->displine == 0) - video_wait_for_buffer(); + if (dev->cgadispon) { + if (dev->displine == 0) + video_wait_for_buffer(); - if ((dev->mapram[0x03d8] & 0x12) == 0x12) - pgc_cga_gfx80(dev); - else if (dev->mapram[0x03d8] & 0x02) - pgc_cga_gfx40(dev); - else if (dev->mapram[0x03d8] & 0x01) - pgc_cga_text(dev, 80); - else - pgc_cga_text(dev, 40); - } else { - cols[0] = ((dev->mapram[0x03d8] & 0x12) == 0x12) ? 0 : ((dev->mapram[0x03d9] & 15) + 16); - hline(buffer32, 0, dev->displine, PGC_CGA_WIDTH, cols[0]); - } + if ((dev->mapram[0x03d8] & 0x12) == 0x12) + pgc_cga_gfx80(dev); + else if (dev->mapram[0x03d8] & 0x02) + pgc_cga_gfx40(dev); + else if (dev->mapram[0x03d8] & 0x01) + pgc_cga_text(dev, 80); + else + pgc_cga_text(dev, 40); + } else { + cols[0] = ((dev->mapram[0x03d8] & 0x12) == 0x12) ? 0 : ((dev->mapram[0x03d9] & 15) + 16); + hline(buffer32, 0, dev->displine, PGC_CGA_WIDTH, cols[0]); + } - if (++dev->displine == PGC_CGA_HEIGHT) { - dev->mapram[0x3da] |= 8; - dev->cgadispon = 0; - } - if (dev->displine == PGC_CGA_HEIGHT + 32) { - dev->mapram[0x3da] &= ~8; - dev->cgadispon = 1; - dev->displine = 0; - } + video_process_8(PGC_CGA_WIDTH, dev->displine); + + if (++dev->displine == PGC_CGA_HEIGHT) { + dev->mapram[0x3da] |= 8; + dev->cgadispon = 0; + } + if (dev->displine == PGC_CGA_HEIGHT + 32) { + dev->mapram[0x3da] &= ~8; + dev->cgadispon = 1; + dev->displine = 0; + } } else { - if (dev->cgadispon) - dev->mapram[0x3da] &= ~1; - timer_advance_u64(&dev->timer, dev->dispontime); - dev->linepos = 0; + if (dev->cgadispon) + dev->mapram[0x3da] &= ~1; + timer_advance_u64(&dev->timer, dev->dispontime); + dev->linepos = 0; - if (dev->displine == PGC_CGA_HEIGHT) { - if (PGC_CGA_WIDTH != xsize || PGC_CGA_HEIGHT != ysize) { - xsize = PGC_CGA_WIDTH; - ysize = PGC_CGA_HEIGHT; - set_screen_size(xsize, ysize); + if (dev->displine == PGC_CGA_HEIGHT) { + if (PGC_CGA_WIDTH != xsize || PGC_CGA_HEIGHT != ysize) { + xsize = PGC_CGA_WIDTH; + ysize = PGC_CGA_HEIGHT; + set_screen_size(xsize, ysize); - if (video_force_resize_get()) - video_force_resize_set(0); - } - video_blit_memtoscreen_8(0, 0, xsize, ysize); - frames++; + if (video_force_resize_get()) + video_force_resize_set(0); + } + video_blit_memtoscreen(0, 0, xsize, ysize); + frames++; - /* We have a fixed 640x400 screen for CGA modes. */ - video_res_x = PGC_CGA_WIDTH; - video_res_y = PGC_CGA_HEIGHT; - switch (dev->mapram[0x3d8] & 0x12) { - case 0x12: - video_bpp = 1; - break; + /* We have a fixed 640x400 screen for CGA modes. */ + video_res_x = PGC_CGA_WIDTH; + video_res_y = PGC_CGA_HEIGHT; + switch (dev->mapram[0x3d8] & 0x12) { + case 0x12: + video_bpp = 1; + break; - case 0x02: - video_bpp = 2; - break; + case 0x02: + video_bpp = 2; + break; - default: - video_bpp = 0; - break; - } - dev->cgablink++; - } + default: + video_bpp = 0; + break; + } + dev->cgablink++; + } } } - /* Draw the screen in CGA or native mode. */ void pgc_poll(void *priv) { - pgc_t *dev = (pgc_t *)priv; - uint32_t x, y; + pgc_t *dev = (pgc_t *) priv; + uint32_t y; if (dev->cga_selected) { - pgc_cga_poll(dev); - return; + pgc_cga_poll(dev); + return; } /* Not CGA, so must be native mode. */ - if (! dev->linepos) { - timer_advance_u64(&dev->timer, dev->dispofftime); - dev->mapram[0x3da] |= 1; - dev->linepos = 1; - if (dev->cgadispon && (uint32_t)dev->displine < dev->maxh) { - if (dev->displine == 0) - video_wait_for_buffer(); + if (!dev->linepos) { + timer_advance_u64(&dev->timer, dev->dispofftime); + dev->mapram[0x3da] |= 1; + dev->linepos = 1; + if (dev->cgadispon && (uint32_t) dev->displine < dev->maxh) { + if (dev->displine == 0) + video_wait_for_buffer(); - /* Don't know why pan needs to be multiplied by -2, but - * the IM1024 driver uses PAN -112 for an offset of - * 224. */ - y = dev->displine - 2 * dev->pan_y; - for (x = 0; x < dev->screenw; x++) { - if (x + dev->pan_x < dev->maxw) - buffer32->line[dev->displine][x] = dev->palette[dev->vram[y * dev->maxw + x]]; - else - buffer32->line[dev->displine][x] = dev->palette[0]; - } - } else { - hline(buffer32, 0, dev->displine, dev->screenw, dev->palette[0]); - } + /* Don't know why pan needs to be multiplied by -2, but + * the IM1024 driver uses PAN -112 for an offset of + * 224. */ + y = dev->displine - 2 * dev->pan_y; + for (uint32_t x = 0; x < dev->screenw; x++) { + if (x + dev->pan_x < dev->maxw) + buffer32->line[dev->displine][x] = dev->palette[dev->vram[y * dev->maxw + x]]; + else + buffer32->line[dev->displine][x] = dev->palette[0]; + } + } else { + hline(buffer32, 0, dev->displine, dev->screenw, dev->palette[0]); + } - if (++dev->displine == dev->screenh) { - dev->mapram[0x3da] |= 8; - dev->cgadispon = 0; - } + if (++dev->displine == dev->screenh) { + dev->mapram[0x3da] |= 8; + dev->cgadispon = 0; + } - if (dev->displine == dev->screenh + 32) { - dev->mapram[0x3da] &= ~8; - dev->cgadispon = 1; - dev->displine = 0; - } + if (dev->displine == dev->screenh + 32) { + dev->mapram[0x3da] &= ~8; + dev->cgadispon = 1; + dev->displine = 0; + } } else { - if (dev->cgadispon) - dev->mapram[0x3da] &= ~1; - timer_advance_u64(&dev->timer, dev->dispontime); - dev->linepos = 0; + if (dev->cgadispon) + dev->mapram[0x3da] &= ~1; + timer_advance_u64(&dev->timer, dev->dispontime); + dev->linepos = 0; - if (dev->displine == dev->screenh) { - if (dev->screenw != xsize || dev->screenh != ysize) { - xsize = dev->screenw; - ysize = dev->screenh; - set_screen_size(xsize, ysize); + if (dev->displine == dev->screenh) { + if (dev->screenw != xsize || dev->screenh != ysize) { + xsize = dev->screenw; + ysize = dev->screenh; + set_screen_size(xsize, ysize); - if (video_force_resize_get()) - video_force_resize_set(0); - } - video_blit_memtoscreen(0, 0, xsize, ysize); - frames++; + if (video_force_resize_get()) + video_force_resize_set(0); + } + video_blit_memtoscreen(0, 0, xsize, ysize); + frames++; - video_res_x = dev->screenw; - video_res_y = dev->screenh; - video_bpp = 8; - dev->cgablink++; - } + video_res_x = dev->screenw; + video_res_y = dev->screenh; + video_bpp = 8; + dev->cgablink++; + } } } - void pgc_speed_changed(void *priv) { - pgc_t *dev = (pgc_t *)priv; + pgc_t *dev = (pgc_t *) priv; pgc_recalctimings(dev); } - void pgc_close_common(void *priv) { - pgc_t *dev = (pgc_t *)priv; + pgc_t *dev = (pgc_t *) priv; /* * Close down the worker thread by setting a @@ -2612,11 +2625,11 @@ pgc_close_common(void *priv) #ifdef ENABLE_PGC_LOG pgc_log("PGC: telling thread to stop...\n"); #endif - dev->stopped = 1; + dev->stopped = 1; dev->mapram[0x3ff] = 1; if (dev->waiting_input_fifo || dev->waiting_output_fifo) { - /* Do an immediate wake-up. */ - wake_timer(priv); + /* Do an immediate wake-up. */ + wake_timer(priv); } /* Wait for thread to stop. */ @@ -2630,92 +2643,87 @@ pgc_close_common(void *priv) #endif if (dev->cga_vram) - free(dev->cga_vram); + free(dev->cga_vram); if (dev->vram) - free(dev->vram); + free(dev->vram); } - void pgc_close(void *priv) { - pgc_t *dev = (pgc_t *)priv; + pgc_t *dev = (pgc_t *) priv; pgc_close_common(priv); free(dev); } - /* - * Initialization code common to the PGC and its subclasses. + * Initialization code common to the PGC and its subclasses. * - * Pass the 'input byte' function in since this is overridden in - * the IM-1024, and needs to be set before the drawing thread is + * Pass the 'input byte' function in since this is overridden in + * the IM-1024, and needs to be set before the drawing thread is * launched. */ void pgc_init(pgc_t *dev, int maxw, int maxh, int visw, int vish, - int (*inpbyte)(pgc_t *, uint8_t *), double npc) + int (*inpbyte)(pgc_t *, uint8_t *), double npc) { - int i; - /* Make it a 16k mapping at C4000 (will be C4000-C7FFF), because of the emulator's granularity - the original mapping will conflict with hard disk controller BIOS'es. */ mem_mapping_add(&dev->mapping, 0xc4000, 16384, - pgc_read,NULL,NULL, pgc_write,NULL,NULL, - NULL, MEM_MAPPING_EXTERNAL, dev); - mem_mapping_add(&dev->cga_mapping, 0xb8000, 32768, - pgc_read,NULL,NULL, pgc_write,NULL,NULL, - NULL, MEM_MAPPING_EXTERNAL, dev); + pgc_read, NULL, NULL, pgc_write, NULL, NULL, + NULL, MEM_MAPPING_EXTERNAL, dev); + mem_mapping_add(&dev->cga_mapping, 0xb8000, 32768, + pgc_read, NULL, NULL, pgc_write, NULL, NULL, + NULL, MEM_MAPPING_EXTERNAL, dev); io_sethandler(0x03d0, 16, - pgc_in,NULL,NULL, pgc_out,NULL,NULL, dev); + pgc_in, NULL, NULL, pgc_out, NULL, NULL, dev); dev->maxw = maxw; dev->maxh = maxh; dev->visw = visw; dev->vish = vish; - dev->vram = (uint8_t *)malloc(maxw * maxh); - memset(dev->vram, 0x00, maxw * maxh); - dev->cga_vram = (uint8_t *)malloc(16384); + dev->vram = (uint8_t *) malloc((size_t) maxw * maxh); + memset(dev->vram, 0x00, (size_t) maxw * maxh); + dev->cga_vram = (uint8_t *) malloc(16384); memset(dev->cga_vram, 0x00, 16384); /* Create and initialize command lists. */ - dev->clist = (pgc_cl_t *)malloc(256 * sizeof(pgc_cl_t)); + dev->clist = (pgc_cl_t *) malloc(256 * sizeof(pgc_cl_t)); memset(dev->clist, 0x00, 256 * sizeof(pgc_cl_t)); - for (i = 0; i < 256; i++) { - dev->clist[i].list = NULL; - dev->clist[i].listmax = 0; - dev->clist[i].wrptr = 0; - dev->clist[i].rdptr = 0; - dev->clist[i].repeat = 0; - dev->clist[i].chain = NULL; + for (uint16_t i = 0; i < 256; i++) { + dev->clist[i].list = NULL; + dev->clist[i].listmax = 0; + dev->clist[i].wrptr = 0; + dev->clist[i].rdptr = 0; + dev->clist[i].repeat = 0; + dev->clist[i].chain = NULL; } - dev->clcur = NULL; + dev->clcur = NULL; dev->native_pixel_clock = npc; pgc_reset(dev); dev->inputbyte = inpbyte; dev->master = dev->commands = pgc_commands; - dev->pgc_wake_thread = thread_create_event(); - dev->pgc_thread = thread_create(pgc_thread, dev); + dev->pgc_wake_thread = thread_create_event(); + dev->pgc_thread = thread_create(pgc_thread, dev); timer_add(&dev->timer, pgc_poll, dev, 1); - + timer_add(&dev->wake_timer, wake_timer, dev, 0); } - static void * pgc_standalone_init(const device_t *info) { pgc_t *dev; - dev = (pgc_t *)malloc(sizeof(pgc_t)); + dev = (pgc_t *) malloc(sizeof(pgc_t)); memset(dev, 0x00, sizeof(pgc_t)); dev->type = info->local; @@ -2724,19 +2732,19 @@ pgc_standalone_init(const device_t *info) video_inform(VIDEO_FLAG_TYPE_CGA, &timing_pgc); - return(dev); + return dev; } - const device_t pgc_device = { - "PGC", - "pgc", - DEVICE_ISA, 0, - pgc_standalone_init, - pgc_close, - NULL, - { NULL }, - pgc_speed_changed, - NULL, - NULL + .name = "PGC", + .internal_name = "pgc", + .flags = DEVICE_ISA, + .local = 0, + .init = pgc_standalone_init, + .close = pgc_close, + .reset = NULL, + { .available = NULL }, + .speed_changed = pgc_speed_changed, + .force_redraw = NULL, + .config = NULL }; diff --git a/src/video/vid_rtg310x.c b/src/video/vid_rtg310x.c index 4ab0a2d8b..eef95a910 100644 --- a/src/video/vid_rtg310x.c +++ b/src/video/vid_rtg310x.c @@ -1,18 +1,18 @@ /* - * 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. + * 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. + * This file is part of the 86Box distribution. * - * Emulation of the Realtek RTG series of VGA ISA chips. + * Emulation of the Realtek RTG series of VGA ISA chips. * * * - * Authors: TheCollector1995, + * Authors: TheCollector1995, * - * Copyright 2021 TheCollector1995. + * Copyright 2021 TheCollector1995. */ #include #include @@ -29,86 +29,87 @@ #include <86box/vid_svga.h> #include <86box/vid_svga_render.h> - -#define BIOS_ROM_PATH "roms/video/rtg/realtekrtg3106.BIN" +#define BIOS_ROM_PATH "roms/video/rtg/realtekrtg3106.BIN" typedef struct { - const char *name; - int type; + const char *name; + int type; - svga_t svga; + svga_t svga; - rom_t bios_rom; + rom_t bios_rom; - uint8_t bank3d6, - bank3d7; - - uint32_t vram_size, - vram_mask; + uint8_t bank3d6, + bank3d7; + + uint32_t vram_size, + vram_mask; } rtg_t; +static video_timings_t timing_rtg_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_rtg_isa = {VIDEO_ISA, 3, 3, 6, 5, 5, 10}; - -static void rtg_recalcbanking(rtg_t *dev) +static void +rtg_recalcbanking(rtg_t *dev) { - svga_t *svga = &dev->svga; - - svga->write_bank = (dev->bank3d7 & 0x0f) * 65536; + svga_t *svga = &dev->svga; - if (svga->gdcreg[0x0f] & 4) - svga->read_bank = (dev->bank3d6 & 0x0f) * 65536; - else - svga->read_bank = svga->write_bank; + svga->write_bank = (dev->bank3d7 & 0x0f) * 65536; + + if (svga->gdcreg[0x0f] & 4) + svga->read_bank = (dev->bank3d6 & 0x0f) * 65536; + else + svga->read_bank = svga->write_bank; } - static uint8_t rtg_in(uint16_t addr, void *priv) { - rtg_t *dev = (rtg_t *)priv; + rtg_t *dev = (rtg_t *) priv; svga_t *svga = &dev->svga; - uint8_t ret = 0; + uint8_t ret = 0; - if (((addr & 0xfff0) == 0x3d0 || - (addr & 0xfff0) == 0x3b0) && !(svga->miscout & 1)) addr ^= 0x60; + if (((addr & 0xfff0) == 0x3d0 || (addr & 0xfff0) == 0x3b0) && !(svga->miscout & 1)) + addr ^= 0x60; switch (addr) { - case 0x3ce: - return svga->gdcaddr; - - case 0x3cf: - if (svga->gdcaddr == 0x0c) - return svga->gdcreg[0x0c] | 4; - else if ((svga->gdcaddr > 8) && (svga->gdcaddr != 0x0c)) - return svga->gdcreg[svga->gdcaddr]; - break; - - case 0x3d4: - return svga->crtcreg; + case 0x3ce: + return svga->gdcaddr; - case 0x3d5: - if (!(svga->crtc[0x1e] & 0x80) && (svga->crtcreg > 0x18)) - return 0xff; - if (svga->crtcreg == 0x1a) - return dev->type << 6; - if (svga->crtcreg == 0x1e) { - if (dev->vram_size == 1024) - ret = 2; - else if (dev->vram_size == 512) - ret = 1; - else - ret = 0; - return svga->crtc[0x1e] | ret; - } - return svga->crtc[svga->crtcreg]; - - case 0x3d6: - return dev->bank3d6; - - case 0x3d7: - return dev->bank3d7; - } + case 0x3cf: + if (svga->gdcaddr == 0x0c) + return svga->gdcreg[0x0c] | 4; + else if ((svga->gdcaddr > 8) && (svga->gdcaddr != 0x0c)) + return svga->gdcreg[svga->gdcaddr]; + break; + + case 0x3d4: + return svga->crtcreg; + + case 0x3d5: + if (!(svga->crtc[0x1e] & 0x80) && (svga->crtcreg > 0x18)) + return 0xff; + if (svga->crtcreg == 0x1a) + return dev->type << 6; + if (svga->crtcreg == 0x1e) { + if (dev->vram_size == 1024) + ret = 2; + else if (dev->vram_size == 512) + ret = 1; + else + ret = 0; + return svga->crtc[0x1e] | ret; + } + return svga->crtc[svga->crtcreg]; + + case 0x3d6: + return dev->bank3d6; + + case 0x3d7: + return dev->bank3d7; + + default: + break; + } return svga_in(addr, svga); } @@ -116,81 +117,89 @@ rtg_in(uint16_t addr, void *priv) static void rtg_out(uint16_t addr, uint8_t val, void *priv) { - rtg_t *dev = (rtg_t *)priv; + rtg_t *dev = (rtg_t *) priv; svga_t *svga = &dev->svga; uint8_t old; - if (((addr & 0xfff0) == 0x3d0 || - (addr & 0xfff0) == 0x3b0) && !(svga->miscout & 1)) addr ^= 0x60; + if (((addr & 0xfff0) == 0x3d0 || (addr & 0xfff0) == 0x3b0) && !(svga->miscout & 1)) + addr ^= 0x60; switch (addr) { - case 0x3ce: - svga->gdcaddr = val; - return; - - case 0x3cf: - if (svga->gdcaddr > 8) { - svga->gdcreg[svga->gdcaddr] = val; + case 0x3ce: + svga->gdcaddr = val; + return; - switch (svga->gdcaddr) { - case 0x0b: - case 0x0c: - svga->fullchange = changeframecount; - svga_recalctimings(svga); - break; - - case 0x0f: - rtg_recalcbanking(dev); - return; - } - } - break; + case 0x3cf: + if (svga->gdcaddr > 8) { + svga->gdcreg[svga->gdcaddr] = val; - case 0x3d4: - svga->crtcreg = val & 0x3f; - return; + switch (svga->gdcaddr) { + case 0x0b: + case 0x0c: + svga->fullchange = changeframecount; + svga_recalctimings(svga); + break; - 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 (svga->crtc[0x1e] & 0x80) { - switch (svga->crtcreg) { - case 0x19: - svga->vram_display_mask = (val & 0x20) ? dev->vram_mask : 0x3ffff; - svga->fullchange = changeframecount; - svga_recalctimings(svga); - break; - } - } + case 0x0f: + rtg_recalcbanking(dev); + return; - 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; - - case 0x3d6: - dev->bank3d6 = val; - rtg_recalcbanking(dev); - return; - - case 0x3d7: - dev->bank3d7 = val; - rtg_recalcbanking(dev); - return; + default: + break; + } + } + 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 (svga->crtc[0x1e] & 0x80) { + switch (svga->crtcreg) { + case 0x19: + svga->vram_display_mask = (val & 0x20) ? dev->vram_mask : 0x3ffff; + svga->fullchange = changeframecount; + svga_recalctimings(svga); + break; + + default: + break; + } + } + + 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; + + case 0x3d6: + dev->bank3d6 = val; + rtg_recalcbanking(dev); + return; + + case 0x3d7: + dev->bank3d7 = val; + rtg_recalcbanking(dev); + return; + + default: + break; } svga_out(addr, val, svga); @@ -199,197 +208,215 @@ rtg_out(uint16_t addr, uint8_t val, void *priv) static void rtg_recalctimings(svga_t *svga) { - svga->ma_latch = ((svga->crtc[0xc] << 8) | svga->crtc[0xd]) + ((svga->crtc[8] & 0x60) >> 5); - svga->ma_latch |= ((svga->crtc[0x19] & 0x10) << 16) | ((svga->crtc[0x19] & 0x40) << 17); + svga->ma_latch = ((svga->crtc[0xc] << 8) | svga->crtc[0xd]) + ((svga->crtc[8] & 0x60) >> 5); + svga->ma_latch |= ((svga->crtc[0x19] & 0x10) << 16) | ((svga->crtc[0x19] & 0x40) << 17); - svga->interlace = (svga->crtc[0x19] & 1); - - svga->lowres = svga->attrregs[0x10] & 0x40; + svga->interlace = (svga->crtc[0x19] & 1); - /*Clock table not available, currently a guesswork*/ - switch (((svga->miscout >> 2) & 3) | ((svga->gdcreg[0x0c] & 0x20) >> 3)) { - case 0: - case 1: - break; - case 2: - svga->clock = (cpuclock * (double)(1ull << 32)) / 36000000.0; - break; - case 3: - svga->clock = (cpuclock * (double)(1ull << 32)) / 65100000.0; - break; - case 4: - svga->clock = (cpuclock * (double)(1ull << 32)) / 44900000.0; - break; - case 5: - svga->clock = (cpuclock * (double)(1ull << 32)) / 50000000.0; - break; - case 6: - svga->clock = (cpuclock * (double)(1ull << 32)) / 80000000.0; - break; - case 7: - svga->clock = (cpuclock * (double)(1ull << 32)) / 75000000.0; - break; - } - - switch (svga->gdcreg[0x0c] & 3) { - case 1: - svga->clock /= 1.5; - break; - case 2: - svga->clock /= 2; - break; - case 3: - svga->clock /= 4; - break; - } + svga->lowres = svga->attrregs[0x10] & 0x40; - 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->hdisp = svga->crtc[1] - ((svga->crtc[5] & 0x60) >> 5); - svga->hdisp++; - svga->hdisp *= 8; + /*Clock table not available, currently a guesswork*/ + switch (((svga->miscout >> 2) & 3) | ((svga->gdcreg[0x0c] & 0x20) >> 3)) { + case 0: + case 1: + break; + case 2: + svga->clock = (cpuclock * (double) (1ULL << 32)) / 36000000.0; + break; + case 3: + svga->clock = (cpuclock * (double) (1ULL << 32)) / 65100000.0; + break; + case 4: + svga->clock = (cpuclock * (double) (1ULL << 32)) / 44900000.0; + break; + case 5: + svga->clock = (cpuclock * (double) (1ULL << 32)) / 50000000.0; + break; + case 6: + svga->clock = (cpuclock * (double) (1ULL << 32)) / 80000000.0; + break; + case 7: + svga->clock = (cpuclock * (double) (1ULL << 32)) / 75000000.0; + break; - if (svga->hdisp == 1280) - svga->rowoffset >>= 1; + default: + break; + } - 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: - svga->hdisp = svga->crtc[1] - ((svga->crtc[5] & 0x60) >> 5); - svga->hdisp++; - svga->hdisp *= (svga->seqregs[1] & 8) ? 16 : 8; - if (svga->crtc[0x19] & 2) { - if (svga->hdisp == 1280) { - svga->hdisp >>= 1; - } else - svga->rowoffset <<= 1; - - svga->render = svga_render_8bpp_highres; - } else { - if (svga->lowres) - svga->render = svga_render_8bpp_lowres; - else - svga->render = svga_render_8bpp_highres; - } - break; - } - } + switch (svga->gdcreg[0x0c] & 3) { + case 1: + svga->clock /= 1.5; + break; + case 2: + svga->clock /= 2; + break; + case 3: + svga->clock /= 4; + break; + + default: + break; + } + + 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->hdisp = svga->crtc[1] - ((svga->crtc[5] & 0x60) >> 5); + svga->hdisp++; + svga->hdisp *= 8; + + if (svga->hdisp == 1280) + svga->rowoffset >>= 1; + + 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: + svga->hdisp = svga->crtc[1] - ((svga->crtc[5] & 0x60) >> 5); + svga->hdisp++; + svga->hdisp *= (svga->seqregs[1] & 8) ? 16 : 8; + if (svga->crtc[0x19] & 2) { + if (svga->hdisp == 1280) { + svga->hdisp >>= 1; + } else + svga->rowoffset <<= 1; + + svga->render = svga_render_8bpp_highres; + } else { + if (svga->lowres) + svga->render = svga_render_8bpp_lowres; + else + svga->render = svga_render_8bpp_highres; + } + break; + + default: + break; + } + } } static void * rtg_init(const device_t *info) { const char *fn; - rtg_t *dev; + rtg_t *dev; - dev = (rtg_t *)malloc(sizeof(rtg_t)); + dev = (rtg_t *) malloc(sizeof(rtg_t)); memset(dev, 0x00, sizeof(rtg_t)); dev->name = info->name; dev->type = info->local; - fn = BIOS_ROM_PATH; + fn = BIOS_ROM_PATH; - switch(dev->type) { - case 2: /* ISA RTG3106 */ - dev->vram_size = device_get_config_int("memory") << 10; - video_inform(VIDEO_FLAG_TYPE_SPECIAL, &timing_rtg_isa); - svga_init(info, &dev->svga, dev, dev->vram_size, - rtg_recalctimings, rtg_in, rtg_out, - NULL, NULL); - io_sethandler(0x03c0, 32, - rtg_in,NULL,NULL, rtg_out,NULL,NULL, dev); - break; + switch (dev->type) { + case 2: /* ISA RTG3106 */ + dev->vram_size = device_get_config_int("memory") << 10; + video_inform(VIDEO_FLAG_TYPE_SPECIAL, &timing_rtg_isa); + svga_init(info, &dev->svga, dev, dev->vram_size, + rtg_recalctimings, rtg_in, rtg_out, + NULL, NULL); + io_sethandler(0x03c0, 32, + rtg_in, NULL, NULL, rtg_out, NULL, NULL, dev); + break; + + default: + break; } - dev->svga.bpp = 8; - dev->svga.miscout = 1; + dev->svga.bpp = 8; + dev->svga.miscout = 1; dev->vram_mask = dev->vram_size - 1; - rom_init(&dev->bios_rom, (char *) fn, - 0xc0000, 0x8000, 0x7fff, 0, MEM_MAPPING_EXTERNAL); + rom_init(&dev->bios_rom, fn, + 0xc0000, 0x8000, 0x7fff, 0, MEM_MAPPING_EXTERNAL); - return(dev); + return dev; } - static void rtg_close(void *priv) { - rtg_t *dev = (rtg_t *)priv; + rtg_t *dev = (rtg_t *) priv; svga_close(&dev->svga); free(dev); } - static void rtg_speed_changed(void *priv) { - rtg_t *dev = (rtg_t *)priv; + rtg_t *dev = (rtg_t *) priv; svga_recalctimings(&dev->svga); } - static void rtg_force_redraw(void *priv) { - rtg_t *dev = (rtg_t *)priv; + rtg_t *dev = (rtg_t *) priv; dev->svga.fullchange = changeframecount; } - static int rtg_available(void) { return rom_present(BIOS_ROM_PATH); } -static const device_config_t rtg_config[] = -{ - { - "memory", "Memory size", CONFIG_SELECTION, "", 1024, "", { 0 }, - { - { - "256 KB", 256 - }, - { - "512 KB", 512 - }, - { - "1 MB", 1024 - }, - { - "" - } - } - }, - { - "", "", -1 - } +static const device_config_t rtg_config[] = { + // clang-format off + { + .name = "memory", + .description = "Memory size", + .type = CONFIG_SELECTION, + .default_int = 1024, + .selection = { + { + .description = "256 KB", + .value = 256 + }, + { + .description = "512 KB", + .value = 512 + }, + { + .description = "1 MB", + .value = 1024 + }, + { + .description = "" + } + } + }, + { + .type = CONFIG_END + } + // clang-format on }; const device_t realtek_rtg3106_device = { - "Realtek RTG3106 (ISA)", - "rtg3106", - DEVICE_ISA | DEVICE_AT, - 2, - rtg_init, rtg_close, NULL, - { rtg_available }, - rtg_speed_changed, - rtg_force_redraw, - rtg_config -}; \ No newline at end of file + .name = "Realtek RTG3106 (ISA)", + .internal_name = "rtg3106", + .flags = DEVICE_ISA | DEVICE_AT, + .local = 2, + .init = rtg_init, + .close = rtg_close, + .reset = NULL, + { .available = rtg_available }, + .speed_changed = rtg_speed_changed, + .force_redraw = rtg_force_redraw, + .config = rtg_config +}; diff --git a/src/video/vid_s3.c b/src/video/vid_s3.c index 13eb1ad1e..f35f729da 100644 --- a/src/video/vid_s3.c +++ b/src/video/vid_s3.c @@ -1,20 +1,20 @@ /* - * 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. + * 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. + * This file is part of the 86Box distribution. * - * S3 emulation. + * S3 emulation. * * * - * Authors: Sarah Walker, - * Miran Grca, + * Authors: Sarah Walker, + * Miran Grca, * - * Copyright 2008-2019 Sarah Walker. - * Copyright 2016-2019 Miran Grca. + * Copyright 2008-2019 Sarah Walker. + * Copyright 2016-2019 Miran Grca. */ #include #include @@ -22,6 +22,7 @@ #include #include #include +#include #include <86box/86box.h> #include <86box/device.h> #include <86box/io.h> @@ -30,6 +31,7 @@ #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> @@ -37,341 +39,336 @@ #include <86box/vid_svga_render.h> #include "cpu.h" -#define ROM_ORCHID_86C911 "roms/video/s3/BIOS.BIN" -#define ROM_DIAMOND_STEALTH_VRAM "roms/video/s3/Diamond Stealth VRAM BIOS v2.31 U14.BIN" -#define ROM_AMI_86C924 "roms/video/s3/S3924AMI.BIN" -#define ROM_METHEUS_86C928 "roms/video/s3/928.VBI" -#define ROM_SPEA_MERCURY_LITE_PCI "roms/video/s3/SPEAVGA.VBI" -#define ROM_SPEA_MIRAGE_86C801 "roms/video/s3/V7MIRAGE.VBI" -#define ROM_SPEA_MIRAGE_86C805 "roms/video/s3/86c805pspeavlbus.BIN" -#define ROM_MIROCRYSTAL8S_805 "roms/video/s3/S3_805VL_ATT20C491_miroCRYSTAL_8s_ver1.4.BIN" -#define ROM_MIROCRYSTAL10SD_805 "roms/video/s3/MIROcrystal10SD_VLB.VBI" -#define ROM_MIROCRYSTAL20SV_964_VLB "roms/video/s3/S3_964VL_BT485_27C256_miroCRYSTAL_20sv_ver1.2.bin" -#define ROM_MIROCRYSTAL20SV_964_PCI "roms/video/s3/mirocrystal.VBI" -#define ROM_MIROCRYSTAL20SD_864_VLB "roms/video/s3/Miro20SD.BIN" -#define ROM_PHOENIX_86C80X "roms/video/s3/805.VBI" -#define ROM_PARADISE_BAHAMAS64 "roms/video/s3/bahamas64.bin" -#define ROM_PHOENIX_VISION864 "roms/video/s3/86c864p.bin" -#define ROM_DIAMOND_STEALTH64_964 "roms/video/s3/964_107h.rom" -#define ROM_PHOENIX_TRIO32 "roms/video/s3/86c732p.bin" -#define ROM_SPEA_MIRAGE_P64 "roms/video/s3/S3_764VL_SPEAMirageP64VL_ver5_03.BIN" -#define ROM_NUMBER9_9FX "roms/video/s3/s3_764.bin" -#define ROM_PHOENIX_TRIO64 "roms/video/s3/86c764x1.bin" -#define ROM_DIAMOND_STEALTH64_764 "roms/video/s3/stealt64.bin" -#define ROM_TRIO64V2_DX_VBE20 "roms/video/s3/86c775_2.bin" -#define ROM_PHOENIX_TRIO64VPLUS "roms/video/s3/64V1506.ROM" -#define ROM_DIAMOND_STEALTH_SE "roms/video/s3/DiamondStealthSE.VBI" -#define ROM_ELSAWIN2KPROX_964 "roms/video/s3/elsaw20004m.BIN" -#define ROM_ELSAWIN2KPROX "roms/video/s3/elsaw20008m.BIN" -#define ROM_NUMBER9_9FX_531 "roms/video/s3/numbernine.BIN" -#define ROM_PHOENIX_VISION868 "roms/video/s3/1-DSV3868.BIN" -#define ROM_MIROVIDEO40SV_ERGO_968_PCI "roms/video/s3/S3_968PCI_TVP3026_miroVideo40SV_PCI_1.04.BIN" -#define ROM_SPEA_MERCURY_P64V "roms/video/s3/S3_968PCI_TVP3026_SPEAMecuryP64V_ver1.01.BIN" -#define ROM_NUMBER9_9FX_771 "roms/video/s3/no9motionfx771.BIN" -#define ROM_PHOENIX_VISION968 "roms/video/s3/1-DSV3968P.BIN" +#define ROM_ORCHID_86C911 "roms/video/s3/BIOS.BIN" +#define ROM_DIAMOND_STEALTH_VRAM "roms/video/s3/Diamond Stealth VRAM BIOS v2.31 U14.BIN" +#define ROM_AMI_86C924 "roms/video/s3/S3924AMI.BIN" +#define ROM_METHEUS_86C928 "roms/video/s3/928.VBI" +#define ROM_SPEA_MERCURY_LITE_PCI "roms/video/s3/SPEAVGA.VBI" +#define ROM_SPEA_MIRAGE_86C801 "roms/video/s3/V7MIRAGE.VBI" +#define ROM_SPEA_MIRAGE_86C805 "roms/video/s3/86c805pspeavlbus.BIN" +#define ROM_MIROCRYSTAL8S_805 "roms/video/s3/S3_805VL_ATT20C491_miroCRYSTAL_8s_ver1.4.BIN" +#define ROM_MIROCRYSTAL10SD_805 "roms/video/s3/MIROcrystal10SD_VLB.VBI" +#define ROM_MIROCRYSTAL20SV_964_VLB "roms/video/s3/S3_964VL_BT485_27C256_miroCRYSTAL_20sv_ver1.2.bin" +#define ROM_MIROCRYSTAL20SV_964_PCI "roms/video/s3/mirocrystal.VBI" +#define ROM_MIROCRYSTAL20SD_864_VLB "roms/video/s3/Miro20SD.BIN" +#define ROM_PHOENIX_86C80X "roms/video/s3/805.VBI" +#define ROM_PARADISE_BAHAMAS64 "roms/video/s3/bahamas64.bin" +#define ROM_PHOENIX_VISION864 "roms/video/s3/86c864p.bin" +#define ROM_DIAMOND_STEALTH64_964 "roms/video/s3/964_107h.rom" +#define ROM_PHOENIX_TRIO32 "roms/video/s3/86c732p.bin" +#define ROM_SPEA_MIRAGE_P64 "roms/video/s3/S3_764VL_SPEAMirageP64VL_ver5_03.BIN" +#define ROM_NUMBER9_9FX "roms/video/s3/s3_764.bin" +#define ROM_PHOENIX_TRIO64 "roms/video/s3/86c764x1.bin" +#define ROM_DIAMOND_STEALTH64_764 "roms/video/s3/stealt64.bin" +#define ROM_TRIO64V2_DX_VBE20 "roms/video/s3/86c775_2.bin" +#define ROM_PHOENIX_TRIO64VPLUS "roms/video/s3/64V1506.ROM" +#define ROM_DIAMOND_STEALTH_SE "roms/video/s3/DiamondStealthSE.VBI" +#define ROM_ELSAWIN2KPROX_964 "roms/video/s3/elsaw20004m.BIN" +#define ROM_ELSAWIN2KPROX "roms/video/s3/elsaw20008m.BIN" +#define ROM_NUMBER9_9FX_531 "roms/video/s3/numbernine.BIN" +#define ROM_PHOENIX_VISION868 "roms/video/s3/1-DSV3868.BIN" +#define ROM_MIROVIDEO40SV_ERGO_968_PCI "roms/video/s3/S3_968PCI_TVP3026_miroVideo40SV_PCI_1.04.BIN" +#define ROM_SPEA_MERCURY_P64V "roms/video/s3/S3_968PCI_TVP3026_SPEAMecuryP64V_ver1.01.BIN" +#define ROM_NUMBER9_9FX_771 "roms/video/s3/no9motionfx771.BIN" +#define ROM_PHOENIX_VISION968 "roms/video/s3/1-DSV3968P.BIN" -enum -{ - S3_NUMBER9_9FX, - S3_PARADISE_BAHAMAS64, - S3_DIAMOND_STEALTH64_964, - S3_PHOENIX_TRIO32, - S3_PHOENIX_TRIO64, - S3_PHOENIX_TRIO64_ONBOARD, - S3_PHOENIX_VISION864, - S3_DIAMOND_STEALTH64_764, - S3_SPEA_MIRAGE_86C801, - S3_SPEA_MIRAGE_86C805, - S3_PHOENIX_86C801, - S3_PHOENIX_86C805, - S3_ORCHID_86C911, - S3_METHEUS_86C928, - S3_AMI_86C924, - S3_TRIO64V2_DX, - S3_TRIO64V2_DX_ONBOARD, - S3_PHOENIX_TRIO64VPLUS, - S3_PHOENIX_TRIO64VPLUS_ONBOARD, - S3_DIAMOND_STEALTH_SE, - S3_DIAMOND_STEALTH_VRAM, - S3_ELSAWIN2KPROX_964, - S3_ELSAWIN2KPROX, - S3_PHOENIX_VISION868, - S3_MIROVIDEO40SV_ERGO_968, - S3_MIROCRYSTAL10SD_805, - S3_SPEA_MIRAGE_P64, - S3_SPEA_MERCURY_P64V, - S3_MIROCRYSTAL20SV_964, - S3_MIROCRYSTAL20SD_864, - S3_PHOENIX_VISION968, - S3_MIROCRYSTAL8S_805, - S3_NUMBER9_9FX_531, - S3_NUMBER9_9FX_771, - S3_SPEA_MERCURY_LITE_PCI +enum { + S3_NUMBER9_9FX, + S3_PARADISE_BAHAMAS64, + S3_DIAMOND_STEALTH64_964, + S3_PHOENIX_TRIO32, + S3_PHOENIX_TRIO64, + S3_PHOENIX_TRIO64_ONBOARD, + S3_PHOENIX_VISION864, + S3_DIAMOND_STEALTH64_764, + S3_SPEA_MIRAGE_86C801, + S3_SPEA_MIRAGE_86C805, + S3_PHOENIX_86C801, + S3_PHOENIX_86C805, + S3_ORCHID_86C911, + S3_METHEUS_86C928, + S3_AMI_86C924, + S3_TRIO64V2_DX, + S3_TRIO64V2_DX_ONBOARD, + S3_PHOENIX_TRIO64VPLUS, + S3_PHOENIX_TRIO64VPLUS_ONBOARD, + S3_DIAMOND_STEALTH_SE, + S3_DIAMOND_STEALTH_VRAM, + S3_ELSAWIN2KPROX_964, + S3_ELSAWIN2KPROX, + S3_PHOENIX_VISION868, + S3_MIROVIDEO40SV_ERGO_968, + S3_MIROCRYSTAL10SD_805, + S3_SPEA_MIRAGE_P64, + S3_SPEA_MERCURY_P64V, + S3_MIROCRYSTAL20SV_964, + S3_MIROCRYSTAL20SD_864, + S3_PHOENIX_VISION968, + S3_MIROCRYSTAL8S_805, + S3_NUMBER9_9FX_531, + S3_NUMBER9_9FX_771, + S3_SPEA_MERCURY_LITE_PCI, + S3_86C805_ONBOARD }; - -enum -{ - S3_86C911 = 0x00, - S3_86C924 = 0x02, - S3_86C928 = 0x04, - S3_86C928PCI = 0x06, - S3_86C801 = 0x07, - S3_86C805 = 0x08, - S3_VISION964 = 0x18, - S3_VISION968 = 0x20, - S3_VISION864 = 0x28, - S3_VISION868 = 0x30, - S3_TRIO32 = 0x38, - S3_TRIO64 = 0x40, - S3_TRIO64V = 0x48, - S3_TRIO64V2 = 0x50 +enum { + S3_86C911 = 0x00, + S3_86C924 = 0x02, + S3_86C928 = 0x04, + S3_86C928PCI = 0x06, + S3_86C801 = 0x07, + S3_86C805 = 0x08, + S3_VISION964 = 0x18, + S3_VISION968 = 0x20, + S3_VISION864 = 0x28, + S3_VISION868 = 0x30, + S3_TRIO32 = 0x38, + S3_TRIO64 = 0x40, + S3_TRIO64V = 0x48, + S3_TRIO64V2 = 0x50 }; +static video_timings_t timing_s3_86c911 = { .type = VIDEO_ISA, .write_b = 4, .write_w = 4, .write_l = 5, .read_b = 20, .read_w = 20, .read_l = 35 }; +static video_timings_t timing_s3_86c801 = { .type = VIDEO_ISA, .write_b = 4, .write_w = 4, .write_l = 5, .read_b = 20, .read_w = 20, .read_l = 35 }; +static video_timings_t timing_s3_86c805 = { .type = VIDEO_BUS, .write_b = 4, .write_w = 4, .write_l = 5, .read_b = 20, .read_w = 20, .read_l = 35 }; +static video_timings_t timing_s3_86c928pci = { .type = VIDEO_PCI, .write_b = 2, .write_w = 2, .write_l = 4, .read_b = 26, .read_w = 26, .read_l = 42 }; +static video_timings_t timing_s3_stealth64_vlb = { .type = VIDEO_BUS, .write_b = 2, .write_w = 2, .write_l = 4, .read_b = 26, .read_w = 26, .read_l = 42 }; +static video_timings_t timing_s3_stealth64_pci = { .type = VIDEO_PCI, .write_b = 2, .write_w = 2, .write_l = 4, .read_b = 26, .read_w = 26, .read_l = 42 }; +static video_timings_t timing_s3_vision864_vlb = { .type = VIDEO_BUS, .write_b = 4, .write_w = 4, .write_l = 5, .read_b = 20, .read_w = 20, .read_l = 35 }; +static video_timings_t timing_s3_vision864_pci = { .type = VIDEO_PCI, .write_b = 4, .write_w = 4, .write_l = 5, .read_b = 20, .read_w = 20, .read_l = 35 }; +static video_timings_t timing_s3_vision868_vlb = { .type = VIDEO_BUS, .write_b = 4, .write_w = 4, .write_l = 5, .read_b = 20, .read_w = 20, .read_l = 35 }; +static video_timings_t timing_s3_vision868_pci = { .type = VIDEO_PCI, .write_b = 4, .write_w = 4, .write_l = 5, .read_b = 20, .read_w = 20, .read_l = 35 }; +static video_timings_t timing_s3_vision964_vlb = { .type = VIDEO_BUS, .write_b = 2, .write_w = 2, .write_l = 4, .read_b = 20, .read_w = 20, .read_l = 35 }; +static video_timings_t timing_s3_vision964_pci = { .type = VIDEO_PCI, .write_b = 2, .write_w = 2, .write_l = 4, .read_b = 20, .read_w = 20, .read_l = 35 }; +static video_timings_t timing_s3_vision968_vlb = { .type = VIDEO_BUS, .write_b = 2, .write_w = 2, .write_l = 4, .read_b = 20, .read_w = 20, .read_l = 35 }; +static video_timings_t timing_s3_vision968_pci = { .type = VIDEO_PCI, .write_b = 2, .write_w = 2, .write_l = 4, .read_b = 20, .read_w = 20, .read_l = 35 }; +static video_timings_t timing_s3_trio32_vlb = { .type = VIDEO_BUS, .write_b = 4, .write_w = 3, .write_l = 5, .read_b = 26, .read_w = 26, .read_l = 42 }; +static video_timings_t timing_s3_trio32_pci = { .type = VIDEO_PCI, .write_b = 4, .write_w = 3, .write_l = 5, .read_b = 26, .read_w = 26, .read_l = 42 }; +static video_timings_t timing_s3_trio64_vlb = { .type = VIDEO_BUS, .write_b = 3, .write_w = 2, .write_l = 4, .read_b = 25, .read_w = 25, .read_l = 40 }; +static video_timings_t timing_s3_trio64_pci = { .type = VIDEO_PCI, .write_b = 3, .write_w = 2, .write_l = 4, .read_b = 25, .read_w = 25, .read_l = 40 }; -static video_timings_t timing_s3_86c911 = {VIDEO_ISA, 4, 4, 5, 20, 20, 35}; -static video_timings_t timing_s3_86c801 = {VIDEO_ISA, 4, 4, 5, 20, 20, 35}; -static video_timings_t timing_s3_86c805 = {VIDEO_BUS, 4, 4, 5, 20, 20, 35}; -static video_timings_t timing_s3_86c928pci = {VIDEO_PCI, 2, 2, 4, 26, 26, 42}; -static video_timings_t timing_s3_stealth64_vlb = {VIDEO_BUS, 2, 2, 4, 26, 26, 42}; -static video_timings_t timing_s3_stealth64_pci = {VIDEO_PCI, 2, 2, 4, 26, 26, 42}; -static video_timings_t timing_s3_vision864_vlb = {VIDEO_BUS, 4, 4, 5, 20, 20, 35}; -static video_timings_t timing_s3_vision864_pci = {VIDEO_PCI, 4, 4, 5, 20, 20, 35}; -static video_timings_t timing_s3_vision868_vlb = {VIDEO_BUS, 4, 4, 5, 20, 20, 35}; -static video_timings_t timing_s3_vision868_pci = {VIDEO_PCI, 4, 4, 5, 20, 20, 35}; -static video_timings_t timing_s3_vision964_vlb = {VIDEO_BUS, 2, 2, 4, 20, 20, 35}; -static video_timings_t timing_s3_vision964_pci = {VIDEO_PCI, 2, 2, 4, 20, 20, 35}; -static video_timings_t timing_s3_vision968_vlb = {VIDEO_BUS, 2, 2, 4, 20, 20, 35}; -static video_timings_t timing_s3_vision968_pci = {VIDEO_PCI, 2, 2, 4, 20, 20, 35}; -static video_timings_t timing_s3_trio32_vlb = {VIDEO_BUS, 4, 3, 5, 26, 26, 42}; -static video_timings_t timing_s3_trio32_pci = {VIDEO_PCI, 4, 3, 5, 26, 26, 42}; -static video_timings_t timing_s3_trio64_vlb = {VIDEO_BUS, 3, 2, 4, 25, 25, 40}; -static video_timings_t timing_s3_trio64_pci = {VIDEO_PCI, 3, 2, 4, 25, 25, 40}; - -enum -{ - VRAM_4MB = 0, - VRAM_8MB = 3, - VRAM_2MB = 4, - VRAM_1MB = 6, - VRAM_512KB = 7 +enum { + VRAM_4MB = 0, + VRAM_8MB = 3, + VRAM_2MB = 4, + VRAM_1MB = 6, + VRAM_512KB = 7 }; -#define FIFO_SIZE 65536 -#define FIFO_MASK (FIFO_SIZE - 1) +#define FIFO_SIZE 65536 +#define FIFO_MASK (FIFO_SIZE - 1) #define FIFO_ENTRY_SIZE (1 << 31) -#define FIFO_ENTRIES (s3->fifo_write_idx - s3->fifo_read_idx) -#define FIFO_FULL ((s3->fifo_write_idx - s3->fifo_read_idx) >= (FIFO_SIZE - 4)) -#define FIFO_EMPTY (s3->fifo_read_idx == s3->fifo_write_idx) +#define FIFO_ENTRIES (s3->fifo_write_idx - s3->fifo_read_idx) +#define FIFO_FULL ((s3->fifo_write_idx - s3->fifo_read_idx) >= (FIFO_SIZE - 4)) +#define FIFO_EMPTY (s3->fifo_read_idx == s3->fifo_write_idx) -#define FIFO_TYPE 0xff000000 -#define FIFO_ADDR 0x00ffffff +#define FIFO_TYPE 0xff000000 +#define FIFO_ADDR 0x00ffffff -enum -{ - FIFO_INVALID = (0x00 << 24), - FIFO_WRITE_BYTE = (0x01 << 24), - FIFO_WRITE_WORD = (0x02 << 24), - FIFO_WRITE_DWORD = (0x03 << 24), - FIFO_OUT_BYTE = (0x04 << 24), - FIFO_OUT_WORD = (0x05 << 24), - FIFO_OUT_DWORD = (0x06 << 24) +enum { + FIFO_INVALID = (0x00 << 24), + FIFO_WRITE_BYTE = (0x01 << 24), + FIFO_WRITE_WORD = (0x02 << 24), + FIFO_WRITE_DWORD = (0x03 << 24), + FIFO_OUT_BYTE = (0x04 << 24), + FIFO_OUT_WORD = (0x05 << 24), + FIFO_OUT_DWORD = (0x06 << 24) }; typedef struct { - uint32_t addr_type; - uint32_t val; + uint32_t addr_type; + uint32_t val; } fifo_entry_t; -typedef struct s3_t -{ - mem_mapping_t linear_mapping; - mem_mapping_t mmio_mapping; - mem_mapping_t new_mmio_mapping; - - uint8_t has_bios; - rom_t bios_rom; +typedef struct s3_t { + mem_mapping_t linear_mapping; + mem_mapping_t mmio_mapping; + mem_mapping_t new_mmio_mapping; - svga_t svga; + uint8_t has_bios; + rom_t bios_rom; - uint8_t bank; - uint8_t ma_ext; - int width, bpp; + svga_t svga; - int chip; - int pci, vlb; - int atbus; - - uint8_t id, id_ext, id_ext_pci; - - uint8_t int_line; - - int packed_mmio; - - uint32_t linear_base, linear_size; - - uint8_t pci_regs[256]; - int card; + uint8_t bank; + uint8_t ma_ext; + int width, bpp; - uint32_t vram_mask; - uint8_t data_available; - - int card_type; - - struct - { - uint16_t subsys_cntl; - uint16_t setup_md; - uint8_t advfunc_cntl; - uint16_t cur_y, cur_y2, cur_y_bitres; - uint16_t cur_x, cur_x2, cur_x_bitres; - uint16_t x2, ropmix; - uint16_t pat_x, pat_y; - int16_t desty_axstp, desty_axstp2; - int16_t destx_distp; - int16_t err_term, err_term2; - int16_t maj_axis_pcnt, maj_axis_pcnt2; - uint16_t cmd, cmd2; - uint16_t short_stroke; - uint32_t pat_bg_color, pat_fg_color; - uint32_t bkgd_color; - uint32_t frgd_color; - uint32_t wrt_mask; - uint32_t rd_mask; - uint32_t color_cmp; - uint8_t bkgd_mix; - uint8_t frgd_mix; - uint16_t multifunc_cntl; - uint16_t multifunc[16]; - uint8_t pix_trans[4]; - int ssv_state; + int chip; + int pci, vlb; + int atbus; - int cx, cy; - int px, py; - int sx, sy; - int dx, dy; - uint32_t src, dest, pattern; + uint8_t id, id_ext, id_ext_pci; - int poly_cx, poly_cx2; - int poly_cy, poly_cy2; - int poly_line_cx; - int point_1_updated, point_2_updated; - int poly_dx1, poly_dx2; - int poly_x; + uint8_t int_line; - uint32_t dat_buf; - int dat_count; - int b2e8_pix, temp_cnt; - uint8_t cur_x_bit12, cur_y_bit12; - int ssv_len; - uint8_t ssv_dir; - uint8_t ssv_draw; - - /*For non-threaded FIFO*/ - int setup_fifo_slot; - int draw_fifo_slot; - int setup_fifo, setup_fifo2; - int draw_fifo, draw_fifo2; - } accel; - - struct { - uint32_t nop; - uint32_t cntl; - uint32_t stretch_filt_const; - uint32_t src_dst_step; - uint32_t crop; - uint32_t src_base, dest_base; - uint32_t src, dest; - uint32_t srcbase, dstbase; - int32_t dda_init_accumulator; - int32_t k1, k2; - int dm_index; - int dither_matrix_idx; - int src_step, dst_step; - int sx, sx_backup, sy; - double cx, dx; - double cy, dy; - int sx_scale_int, sx_scale_int_backup; - double sx_scale; - double sx_scale_dec; - double sx_scale_inc; - double sx_scale_backup; - double sx_scale_len; - int dither, host_data, scale_down; - int input; - int len, start; - int odf, idf, yuv; - volatile int busy; - } videoengine; - - struct - { - uint32_t pri_ctrl; - uint32_t chroma_ctrl; - uint32_t sec_ctrl; - uint32_t chroma_upper_bound; - uint32_t sec_filter; - uint32_t blend_ctrl; - uint32_t pri_fb0, pri_fb1; - uint32_t pri_stride; - uint32_t buffer_ctrl; - uint32_t sec_fb0, sec_fb1; - uint32_t sec_stride; - uint32_t overlay_ctrl; - int32_t k1_vert_scale; - int32_t k2_vert_scale; - int32_t dda_vert_accumulator; - int32_t k1_horiz_scale; - int32_t k2_horiz_scale; - int32_t dda_horiz_accumulator; - uint32_t fifo_ctrl; - uint32_t pri_start; - uint32_t pri_size; - uint32_t sec_start; - uint32_t sec_size; - - int sdif; - - int pri_x, pri_y, pri_w, pri_h; - int sec_x, sec_y, sec_w, sec_h; - } streams; + int packed_mmio; - fifo_entry_t fifo[FIFO_SIZE]; - volatile int fifo_read_idx, fifo_write_idx; + uint32_t linear_base, linear_size; - uint8_t fifo_thread_run; - - thread_t *fifo_thread; - event_t *wake_fifo_thread; - event_t *fifo_not_full_event; - - int blitter_busy; - uint64_t blitter_time; - uint64_t status_time; - - uint8_t subsys_cntl, subsys_stat; - - uint32_t hwc_fg_col, hwc_bg_col; - int hwc_col_stack_pos; + uint8_t pci_regs[256]; - int translate; - int enable_8514; - int color_16bit; - volatile int busy, force_busy; + uint8_t pci_slot; + uint8_t irq_state; - uint8_t thread_run, serialport; - void *i2c, *ddc; + uint32_t vram_mask; + uint8_t data_available; - int vram; + int card_type; + + struct + { + uint16_t subsys_cntl; + uint16_t setup_md; + uint8_t advfunc_cntl; + uint16_t cur_y, cur_y2; + uint16_t cur_x, cur_x2; + uint16_t x2, ropmix; + uint16_t pat_x, pat_y; + int16_t desty_axstp, desty_axstp2; + int16_t destx_distp; + int16_t maj_axis_pcnt, maj_axis_pcnt2; + int16_t err_term, err_term2; + uint16_t cmd, cmd2; + uint16_t short_stroke; + uint32_t pat_bg_color, pat_fg_color; + uint32_t bkgd_color; + uint32_t frgd_color; + uint32_t wrt_mask; + uint32_t rd_mask; + uint32_t color_cmp; + uint8_t bkgd_mix; + uint8_t frgd_mix; + uint16_t multifunc_cntl; + uint16_t multifunc[16]; + uint8_t pix_trans[4]; + int ssv_state; + + int16_t cx, cy; + int16_t px, py; + int16_t sx, sy; + int16_t dx, dy; + uint32_t src, dest, pattern; + + int poly_cx, poly_cx2; + int poly_cy, poly_cy2; + int poly_line_cx; + int point_1_updated, point_2_updated; + int poly_dx1, poly_dx2; + int poly_x; + + uint32_t dat_buf; + int dat_count; + int b2e8_pix, temp_cnt; + int ssv_len; + uint8_t ssv_dir; + uint8_t ssv_draw; + + /*For non-threaded FIFO*/ + int setup_fifo_slot; + int draw_fifo_slot; + int setup_fifo, setup_fifo2; + int draw_fifo, draw_fifo2; + } accel; + + struct { + uint32_t nop; + uint32_t cntl; + uint32_t stretch_filt_const; + uint32_t src_dst_step; + uint32_t crop; + uint32_t src_base, dest_base; + uint32_t src, dest; + uint32_t srcbase, dstbase; + int32_t dda_init_accumulator; + int32_t k1, k2; + int dm_index; + int dither_matrix_idx; + int src_step, dst_step; + int sx, sx_backup, sy; + double cx, dx; + double cy, dy; + int sx_scale_int, sx_scale_int_backup; + double sx_scale; + double sx_scale_dec; + double sx_scale_inc; + double sx_scale_backup; + double sx_scale_len; + int dither, host_data, scale_down; + int input; + int len, start; + int odf, idf, yuv; + atomic_int busy; + } videoengine; + + struct + { + uint32_t pri_ctrl; + uint32_t chroma_ctrl; + uint32_t sec_ctrl; + uint32_t chroma_upper_bound; + uint32_t sec_filter; + uint32_t blend_ctrl; + uint32_t pri_fb0, pri_fb1; + uint32_t pri_stride; + uint32_t buffer_ctrl; + uint32_t sec_fb0, sec_fb1; + uint32_t sec_stride; + uint32_t overlay_ctrl; + int32_t k1_vert_scale; + int32_t k2_vert_scale; + int32_t dda_vert_accumulator; + int32_t k1_horiz_scale; + int32_t k2_horiz_scale; + int32_t dda_horiz_accumulator; + uint32_t fifo_ctrl; + uint32_t pri_start; + uint32_t pri_size; + uint32_t sec_start; + uint32_t sec_size; + + int sdif; + + int pri_x, pri_y, pri_w, pri_h; + int sec_x, sec_y, sec_w, sec_h; + } streams; + + fifo_entry_t fifo[FIFO_SIZE]; + atomic_int fifo_read_idx, fifo_write_idx; + + uint8_t fifo_thread_run; + + thread_t *fifo_thread; + event_t *wake_fifo_thread; + event_t *fifo_not_full_event; + + int blitter_busy; + uint64_t blitter_time; + uint64_t status_time; + + uint8_t subsys_cntl, subsys_stat; + + uint32_t hwc_fg_col, hwc_bg_col; + int hwc_col_stack_pos; + + int translate; + int enable_8514; + int color_16bit; + atomic_int busy, force_busy; + + uint8_t thread_run, serialport; + void *i2c, *ddc; + + int vram; } s3_t; -#define INT_VSY (1 << 0) -#define INT_GE_BSY (1 << 1) -#define INT_FIFO_OVR (1 << 2) -#define INT_FIFO_EMP (1 << 3) -#define INT_MASK 0xf +#define INT_VSY (1 << 0) +#define INT_GE_BSY (1 << 1) +#define INT_FIFO_OVR (1 << 2) +#define INT_FIFO_EMP (1 << 3) +#define INT_MASK 0xf #define SERIAL_PORT_SCW (1 << 0) #define SERIAL_PORT_SDW (1 << 1) @@ -380,185 +377,183 @@ typedef struct s3_t static void s3_updatemapping(s3_t *s3); -static void s3_accel_write(uint32_t addr, uint8_t val, void *p); -static void s3_accel_write_w(uint32_t addr, uint16_t val, void *p); -static void s3_accel_write_l(uint32_t addr, uint32_t val, void *p); -static uint8_t s3_accel_read(uint32_t addr, void *p); -static uint16_t s3_accel_read_w(uint32_t addr, void *p); -static uint32_t s3_accel_read_l(uint32_t addr, void *p); +static void s3_accel_write(uint32_t addr, uint8_t val, void *priv); +static void s3_accel_write_w(uint32_t addr, uint16_t val, void *priv); +static void s3_accel_write_l(uint32_t addr, uint32_t val, void *priv); +static uint8_t s3_accel_read(uint32_t addr, void *priv); +static uint16_t s3_accel_read_w(uint32_t addr, void *priv); +static uint32_t s3_accel_read_l(uint32_t addr, void *priv); -static void s3_out(uint16_t addr, uint8_t val, void *p); -static uint8_t s3_in(uint16_t addr, void *p); +static void s3_out(uint16_t addr, uint8_t val, void *priv); +static uint8_t s3_in(uint16_t addr, void *priv); -static void s3_accel_out(uint16_t port, uint8_t val, void *p); -static void s3_accel_out_w(uint16_t port, uint16_t val, void *p); -static void s3_accel_out_l(uint16_t port, uint32_t val, void *p); -static uint8_t s3_accel_in(uint16_t port, void *p); -static uint16_t s3_accel_in_w(uint16_t port, void *p); -static uint32_t s3_accel_in_l(uint16_t port, void *p); -static uint8_t s3_pci_read(int func, int addr, void *p); -static void s3_pci_write(int func, int addr, uint8_t val, void *p); +static void s3_accel_out(uint16_t port, uint8_t val, void *priv); +static void s3_accel_out_w(uint16_t port, uint16_t val, void *priv); +static void s3_accel_out_l(uint16_t port, uint32_t val, void *priv); +static uint8_t s3_accel_in(uint16_t port, void *priv); +static uint16_t s3_accel_in_w(uint16_t port, void *priv); +static uint32_t s3_accel_in_l(uint16_t port, void *priv); +static uint8_t s3_pci_read(int func, int addr, void *priv); +static void s3_pci_write(int func, int addr, uint8_t val, void *priv); /*Remap address for chain-4/doubleword style layout. These will stay for convenience.*/ static __inline uint32_t dword_remap(svga_t *svga, uint32_t in_addr) { - if (svga->packed_chain4) - return in_addr; - - return ((in_addr << 2) & 0x3fff0) | - ((in_addr >> 14) & 0xc) | - (in_addr & ~0x3fffc); + if (svga->packed_chain4 || svga->force_old_addr) + return in_addr; + + return ((in_addr << 2) & 0x3fff0) | ((in_addr >> 14) & 0xc) | (in_addr & ~0x3fffc); } static __inline uint32_t dword_remap_w(svga_t *svga, uint32_t in_addr) { - if (svga->packed_chain4) - return in_addr; - - return ((in_addr << 2) & 0x1fff8) | - ((in_addr >> 14) & 0x6) | - (in_addr & ~0x1fffe); + if (svga->packed_chain4 || svga->force_old_addr) + return in_addr; + + return ((in_addr << 2) & 0x1fff8) | ((in_addr >> 14) & 0x6) | (in_addr & ~0x1fffe); } -static __inline uint32_t +static __inline uint32_t dword_remap_l(svga_t *svga, uint32_t in_addr) { - if (svga->packed_chain4) - return in_addr; - - return ((in_addr << 2) & 0xfffc) | - ((in_addr >> 14) & 0x3) | - (in_addr & ~0xffff); + if (svga->packed_chain4 || svga->force_old_addr) + return in_addr; + + return ((in_addr << 2) & 0xfffc) | ((in_addr >> 14) & 0x3) | (in_addr & ~0xffff); } static __inline void wake_fifo_thread(s3_t *s3) { - thread_set_event(s3->wake_fifo_thread); /*Wake up FIFO thread if moving from idle*/ + thread_set_event(s3->wake_fifo_thread); /*Wake up FIFO thread if moving from idle*/ } static void s3_wait_fifo_idle(s3_t *s3) { - while (!FIFO_EMPTY) { - wake_fifo_thread(s3); - thread_wait_event(s3->fifo_not_full_event, 1); - } + while (!FIFO_EMPTY) { + wake_fifo_thread(s3); + thread_wait_event(s3->fifo_not_full_event, 1); + } } static void s3_queue(s3_t *s3, uint32_t addr, uint32_t val, uint32_t type) { - fifo_entry_t *fifo = &s3->fifo[s3->fifo_write_idx & FIFO_MASK]; + fifo_entry_t *fifo = &s3->fifo[s3->fifo_write_idx & FIFO_MASK]; - if (FIFO_FULL) { - thread_reset_event(s3->fifo_not_full_event); - if (FIFO_FULL) { - thread_wait_event(s3->fifo_not_full_event, -1); /*Wait for room in ringbuffer*/ - } - } + if (FIFO_FULL) { + thread_reset_event(s3->fifo_not_full_event); + if (FIFO_FULL) { + thread_wait_event(s3->fifo_not_full_event, -1); /*Wait for room in ringbuffer*/ + } + } - fifo->val = val; - fifo->addr_type = (addr & FIFO_ADDR) | type; + fifo->val = val; + fifo->addr_type = (addr & FIFO_ADDR) | type; - s3->fifo_write_idx++; - - if (FIFO_ENTRIES > 0xe000 || FIFO_ENTRIES < 8) - wake_fifo_thread(s3); + s3->fifo_write_idx++; + + if (FIFO_ENTRIES > 0xe000 || FIFO_ENTRIES < 8) + wake_fifo_thread(s3); } static void s3_update_irqs(s3_t *s3) { - if (!s3->pci) - return; - - if (s3->subsys_cntl & s3->subsys_stat & INT_MASK) { - pci_set_irq(s3->card, PCI_INTA); - } else { - pci_clear_irq(s3->card, PCI_INTA); - } + if (!s3->pci) + return; + + if (s3->subsys_cntl & s3->subsys_stat & INT_MASK) { + pci_set_irq(s3->pci_slot, PCI_INTA, &s3->irq_state); + } else { + pci_clear_irq(s3->pci_slot, PCI_INTA, &s3->irq_state); + } } -void s3_accel_start(int count, int cpu_input, uint32_t mix_dat, uint32_t cpu_dat, s3_t *s3); -void s3_short_stroke_start(int count, int cpu_input, uint32_t mix_dat, uint32_t cpu_dat, s3_t *s3, uint8_t ssv); +void s3_accel_start(int count, int cpu_input, uint32_t mix_dat, uint32_t cpu_dat, s3_t *s3); +void s3_short_stroke_start(int count, int cpu_input, uint32_t mix_dat, uint32_t cpu_dat, s3_t *s3, uint8_t ssv); static void s3_visionx68_video_engine_op(uint32_t cpu_dat, s3_t *s3); -#define WRITE8(addr, var, val) switch ((addr) & 3) \ - { \ - case 0: var = (var & 0xffffff00) | (val); break; \ - case 1: var = (var & 0xffff00ff) | ((val) << 8); break; \ - case 2: var = (var & 0xff00ffff) | ((val) << 16); break; \ - case 3: var = (var & 0x00ffffff) | ((val) << 24); break; \ - } - +#define WRITE8(addr, var, val) \ + switch ((addr) &3) { \ + case 0: \ + var = (var & 0xffffff00) | (val); \ + break; \ + case 1: \ + var = (var & 0xffff00ff) | ((val) << 8); \ + break; \ + case 2: \ + var = (var & 0xff00ffff) | ((val) << 16); \ + break; \ + case 3: \ + var = (var & 0x00ffffff) | ((val) << 24); \ + break; \ + } #define READ_PIXTRANS_BYTE_IO(n) \ - s3->accel.pix_trans[n] = svga->vram[dword_remap(svga, (s3->accel.dest + s3->accel.cx + n)) & s3->vram_mask]; \ + s3->accel.pix_trans[n] = svga->vram[dword_remap(svga, (s3->accel.dest + s3->accel.cx + n)) & s3->vram_mask]; #define READ_PIXTRANS_BYTE_MM \ - 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)) & s3->vram_mask]; -#define READ_PIXTRANS_WORD \ - 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 { \ - temp = vram_w[dword_remap_w(svga, (s3->accel.dest + s3->accel.cx)) & (s3->vram_mask >> 1)]; \ - } - -#define READ_PIXTRANS_LONG \ - 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); \ - temp |= (svga->vram[dword_remap(svga, (s3->accel.dest + s3->accel.cx + 3)) & s3->vram_mask] << 24); \ - } else { \ - temp = vram_w[dword_remap_w(svga, (s3->accel.dest + s3->accel.cx)) & (s3->vram_mask >> 1)]; \ - temp |= (vram_w[dword_remap_w(svga, (s3->accel.dest + s3->accel.cx + 2)) & (s3->vram_mask >> 1)] << 16); \ - } +#define READ_PIXTRANS_WORD \ + 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 { \ + temp = vram_w[dword_remap_w(svga, (s3->accel.dest + s3->accel.cx)) & (s3->vram_mask >> 1)]; \ + } + +#define READ_PIXTRANS_LONG \ + 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); \ + temp |= (svga->vram[dword_remap(svga, (s3->accel.dest + s3->accel.cx + 3)) & s3->vram_mask] << 24); \ + } else { \ + temp = vram_w[dword_remap_w(svga, (s3->accel.dest + s3->accel.cx)) & (s3->vram_mask >> 1)]; \ + temp |= (vram_w[dword_remap_w(svga, (s3->accel.dest + s3->accel.cx + 2)) & (s3->vram_mask >> 1)] << 16); \ + } static int s3_cpu_src(s3_t *s3) { if (!(s3->accel.cmd & 0x100)) - return 0; - + return 0; + if (s3->chip >= S3_VISION964) - return 1; - + return 1; + if (s3->accel.cmd & 1) - return 1; - + return 1; + return 0; } - + static int s3_cpu_dest(s3_t *s3) { if (!(s3->accel.cmd & 0x100)) - return 0; - + return 0; + if (s3->chip >= S3_VISION964) - return 0; - + return 0; + if (s3->accel.cmd & 1) - return 0; - + return 0; + return 1; } static int s3_enable_fifo(s3_t *s3) { - svga_t *svga = &s3->svga; - - if ((s3->chip == S3_TRIO32) || (s3->chip == S3_TRIO64) || - (s3->chip == S3_TRIO64V) || (s3->chip == S3_TRIO64V2) || - (s3->chip == S3_VISION864) || (s3->chip == S3_VISION964) || - (s3->chip == S3_VISION968) || (s3->chip == S3_VISION868)) - return 1; /* FIFO always enabled on these chips. */ + const svga_t *svga = &s3->svga; + + if ((s3->chip == S3_TRIO32) || (s3->chip == S3_TRIO64) || (s3->chip == S3_TRIO64V) || (s3->chip == S3_TRIO64V2) || (s3->chip == S3_VISION864) || (s3->chip == S3_VISION964) || (s3->chip == S3_VISION968) || (s3->chip == S3_VISION868)) + return 1; /* FIFO always enabled on these chips. */ return !!((svga->crtc[0x40] & 0x08) || (s3->accel.advfunc_cntl & 0x40)); } @@ -566,3908 +561,4413 @@ s3_enable_fifo(s3_t *s3) static void s3_accel_out_pixtrans_w(s3_t *s3, uint16_t val) { - svga_t *svga = &s3->svga; + const svga_t *svga = &s3->svga; - if (s3->accel.cmd & 0x100) { - switch (s3->accel.cmd & 0x600) { - case 0x000: - if (((s3->accel.multifunc[0xa] & 0xc0) == 0x80) || (s3->accel.cmd & 2)) { - if (((s3->accel.frgd_mix & 0x60) != 0x40) || ((s3->accel.bkgd_mix & 0x60) != 0x40)) { - if (s3->accel.cmd & 0x1000) - val = (val >> 8) | (val << 8); - s3_accel_start(8, 1, val | (val << 16), 0, s3); - } else - s3_accel_start(1, 1, 0xffffffff, val | (val << 16), s3); - } else { - if (s3->color_16bit) - s3_accel_start(2, 1, 0xffffffff, val | (val << 16), s3); - else - s3_accel_start(1, 1, 0xffffffff, val | (val << 16), s3); - } - break; - case 0x200: - if (((s3->accel.multifunc[0xa] & 0xc0) == 0x80) || (s3->accel.cmd & 2)) { - if (((s3->accel.frgd_mix & 0x60) != 0x40) || ((s3->accel.bkgd_mix & 0x60) != 0x40)) { - if (s3->accel.cmd & 0x1000) - val = (val >> 8) | (val << 8); - s3_accel_start(16, 1, val | (val << 16), 0, s3); - } else - s3_accel_start(2, 1, 0xffffffff, val | (val << 16), s3); - } else { - s3_accel_start(2, 1, 0xffffffff, val | (val << 16), s3); - } - break; - case 0x400: - if (svga->crtc[0x53] & 0x08) { - if (((s3->accel.multifunc[0xa] & 0xc0) == 0x80) || (s3->accel.cmd & 2)) { - if (((s3->accel.frgd_mix & 0x60) != 0x40) || ((s3->accel.bkgd_mix & 0x60) != 0x40)) { - if (s3->accel.cmd & 0x1000) - val = (val >> 8) | (val << 8); - s3_accel_start(32, 1, val | (val << 16), 0, s3); - } else - s3_accel_start(4, 1, 0xffffffff, val | (val << 16), s3); - } else - s3_accel_start(4, 1, 0xffffffff, val | (val << 16), s3); - } else { - if (((s3->accel.multifunc[0xa] & 0xc0) == 0x80) || (s3->accel.cmd & 2)) { - if (((s3->accel.frgd_mix & 0x60) != 0x40) || ((s3->accel.bkgd_mix & 0x60) != 0x40)) { - if (s3->accel.cmd & 0x1000) - val = (val >> 8) | (val << 8); - s3_accel_start(16, 1, val | (val << 16), 0, s3); - } else - s3_accel_start(4, 1, 0xffffffff, val | (val << 16), s3); - } else - s3_accel_start(4, 1, 0xffffffff, val | (val << 16), s3); - } - break; - case 0x600: - if (s3->chip == S3_TRIO32 || s3->chip == S3_VISION968 || s3->chip == S3_VISION868 || s3->chip >= S3_TRIO64V) { - if (((s3->accel.multifunc[0xa] & 0xc0) == 0x80) || (s3->accel.cmd & 2)) { - if (((s3->accel.frgd_mix & 0x60) != 0x40) || ((s3->accel.bkgd_mix & 0x60) != 0x40)) { - if (s3->accel.cmd & 0x1000) - val = (val >> 8) | (val << 8); - s3_accel_start(8, 1, (val >> 8) & 0xff, 0, s3); - s3_accel_start(8, 1, val & 0xff, 0, s3); - } - } - } - break; - } - } + if (s3->accel.cmd & 0x100) { + switch (s3->accel.cmd & 0x600) { + case 0x000: + if (((s3->accel.multifunc[0xa] & 0xc0) == 0x80) || (s3->accel.cmd & 2)) { + if (((s3->accel.frgd_mix & 0x60) != 0x40) || ((s3->accel.bkgd_mix & 0x60) != 0x40)) { + if (s3->accel.cmd & 0x1000) + val = (val >> 8) | (val << 8); + s3_accel_start(8, 1, val | (val << 16), 0, s3); + } else + s3_accel_start(1, 1, 0xffffffff, val | (val << 16), s3); + } else { + if (s3->color_16bit) + s3_accel_start(2, 1, 0xffffffff, val | (val << 16), s3); + else + s3_accel_start(1, 1, 0xffffffff, val | (val << 16), s3); + } + break; + case 0x200: + if (((s3->accel.multifunc[0xa] & 0xc0) == 0x80) || (s3->accel.cmd & 2)) { + if (((s3->accel.frgd_mix & 0x60) != 0x40) || ((s3->accel.bkgd_mix & 0x60) != 0x40)) { + if (s3->accel.cmd & 0x1000) + val = (val >> 8) | (val << 8); + s3_accel_start(16, 1, val | (val << 16), 0, s3); + } else + s3_accel_start(2, 1, 0xffffffff, val | (val << 16), s3); + } else { + s3_accel_start(2, 1, 0xffffffff, val | (val << 16), s3); + } + break; + case 0x400: + if (svga->crtc[0x53] & 0x08) { + if (((s3->accel.multifunc[0xa] & 0xc0) == 0x80) || (s3->accel.cmd & 2)) { + if (((s3->accel.frgd_mix & 0x60) != 0x40) || ((s3->accel.bkgd_mix & 0x60) != 0x40)) { + if (s3->accel.cmd & 0x1000) + val = (val >> 8) | (val << 8); + s3_accel_start(32, 1, val | (val << 16), 0, s3); + } else + s3_accel_start(4, 1, 0xffffffff, val | (val << 16), s3); + } else + s3_accel_start(4, 1, 0xffffffff, val | (val << 16), s3); + } else { + if (((s3->accel.multifunc[0xa] & 0xc0) == 0x80) || (s3->accel.cmd & 2)) { + if (((s3->accel.frgd_mix & 0x60) != 0x40) || ((s3->accel.bkgd_mix & 0x60) != 0x40)) { + if (s3->accel.cmd & 0x1000) + val = (val >> 8) | (val << 8); + s3_accel_start(16, 1, val | (val << 16), 0, s3); + } else + s3_accel_start(4, 1, 0xffffffff, val | (val << 16), s3); + } else + s3_accel_start(4, 1, 0xffffffff, val | (val << 16), s3); + } + break; + case 0x600: + if (s3->chip == S3_TRIO32 || s3->chip == S3_VISION968 || s3->chip == S3_VISION868 || s3->chip >= S3_TRIO64V) { + if (((s3->accel.multifunc[0xa] & 0xc0) == 0x80) || (s3->accel.cmd & 2)) { + if (((s3->accel.frgd_mix & 0x60) != 0x40) || ((s3->accel.bkgd_mix & 0x60) != 0x40)) { + if (s3->accel.cmd & 0x1000) + val = (val >> 8) | (val << 8); + s3_accel_start(8, 1, (val >> 8) & 0xff, 0, s3); + s3_accel_start(8, 1, val & 0xff, 0, s3); + } + } + } + break; + + default: + break; + } + } } static void s3_accel_out_pixtrans_l(s3_t *s3, uint32_t val) { - if (s3->accel.cmd & 0x100) { - switch (s3->accel.cmd & 0x600) { - case 0x000: - if (((s3->accel.multifunc[0xa] & 0xc0) == 0x80) || (s3->accel.cmd & 2)) { - if (((s3->accel.frgd_mix & 0x60) != 0x40) || ((s3->accel.bkgd_mix & 0x60) != 0x40)) { - if (s3->accel.cmd & 0x1000) - val = ((val & 0xff00ff00) >> 8) | ((val & 0x00ff00ff) << 8); - s3_accel_start(8, 1, val, 0, s3); - s3_accel_start(8, 1, val >> 16, 0, s3); - } else { - s3_accel_start(1, 1, 0xffffffff, val, s3); - s3_accel_start(1, 1, 0xffffffff, val >> 16, s3); - } - } else { - s3_accel_start(1, 1, 0xffffffff, val, s3); - s3_accel_start(1, 1, 0xffffffff, val >> 16, s3); - } - break; - case 0x200: - if (((s3->accel.multifunc[0xa] & 0xc0) == 0x80) || (s3->accel.cmd & 2)) { - if (((s3->accel.frgd_mix & 0x60) != 0x40) || ((s3->accel.bkgd_mix & 0x60) != 0x40)) { - if (s3->accel.cmd & 0x1000) - val = ((val & 0xff00ff00) >> 8) | ((val & 0x00ff00ff) << 8); - s3_accel_start(16, 1, val, 0, s3); - s3_accel_start(16, 1, val >> 16, 0, s3); - } else { - s3_accel_start(2, 1, 0xffffffff, val, s3); - s3_accel_start(2, 1, 0xffffffff, val >> 16, s3); - } - } else { - s3_accel_start(2, 1, 0xffffffff, val, s3); - s3_accel_start(2, 1, 0xffffffff, val >> 16, s3); - } - break; - case 0x400: - if (((s3->accel.multifunc[0xa] & 0xc0) == 0x80) || (s3->accel.cmd & 2)) { - if (((s3->accel.frgd_mix & 0x60) != 0x40) || ((s3->accel.bkgd_mix & 0x60) != 0x40)) { - if (s3->accel.cmd & 0x1000) - val = ((val & 0xff000000) >> 24) | ((val & 0x00ff0000) >> 8) | ((val & 0x0000ff00) << 8) | ((val & 0x000000ff) << 24); - s3_accel_start(32, 1, val, 0, s3); - } else - s3_accel_start(4, 1, 0xffffffff, val, s3); - } else - s3_accel_start(4, 1, 0xffffffff, val, s3); - break; - case 0x600: - if (s3->chip == S3_TRIO32 || s3->chip == S3_VISION968 || s3->chip == S3_VISION868 || s3->chip >= S3_TRIO64V) { - if (((s3->accel.multifunc[0xa] & 0xc0) == 0x80) || (s3->accel.cmd & 2)) { - if (((s3->accel.frgd_mix & 0x60) != 0x40) || ((s3->accel.bkgd_mix & 0x60) != 0x40)) { - if (s3->accel.cmd & 0x1000) - val = ((val & 0xff000000) >> 24) | ((val & 0x00ff0000) >> 8) | ((val & 0x0000ff00) << 8) | ((val & 0x000000ff) << 24); - s3_accel_start(8, 1, (val >> 24) & 0xff, 0, s3); - s3_accel_start(8, 1, (val >> 16) & 0xff, 0, s3); - s3_accel_start(8, 1, (val >> 8) & 0xff, 0, s3); - s3_accel_start(8, 1, val & 0xff, 0, s3); - } - } - } - break; - } - } + if (s3->accel.cmd & 0x100) { + switch (s3->accel.cmd & 0x600) { + case 0x000: + if (((s3->accel.multifunc[0xa] & 0xc0) == 0x80) || (s3->accel.cmd & 2)) { + if (((s3->accel.frgd_mix & 0x60) != 0x40) || ((s3->accel.bkgd_mix & 0x60) != 0x40)) { + if (s3->accel.cmd & 0x1000) + val = ((val & 0xff00ff00) >> 8) | ((val & 0x00ff00ff) << 8); + s3_accel_start(8, 1, val, 0, s3); + s3_accel_start(8, 1, val >> 16, 0, s3); + } else { + s3_accel_start(1, 1, 0xffffffff, val, s3); + s3_accel_start(1, 1, 0xffffffff, val >> 16, s3); + } + } else { + s3_accel_start(1, 1, 0xffffffff, val, s3); + s3_accel_start(1, 1, 0xffffffff, val >> 16, s3); + } + break; + case 0x200: + if (((s3->accel.multifunc[0xa] & 0xc0) == 0x80) || (s3->accel.cmd & 2)) { + if (((s3->accel.frgd_mix & 0x60) != 0x40) || ((s3->accel.bkgd_mix & 0x60) != 0x40)) { + if (s3->accel.cmd & 0x1000) + val = ((val & 0xff00ff00) >> 8) | ((val & 0x00ff00ff) << 8); + s3_accel_start(16, 1, val, 0, s3); + s3_accel_start(16, 1, val >> 16, 0, s3); + } else { + s3_accel_start(2, 1, 0xffffffff, val, s3); + s3_accel_start(2, 1, 0xffffffff, val >> 16, s3); + } + } else { + s3_accel_start(2, 1, 0xffffffff, val, s3); + s3_accel_start(2, 1, 0xffffffff, val >> 16, s3); + } + break; + case 0x400: + if (((s3->accel.multifunc[0xa] & 0xc0) == 0x80) || (s3->accel.cmd & 2)) { + if (((s3->accel.frgd_mix & 0x60) != 0x40) || ((s3->accel.bkgd_mix & 0x60) != 0x40)) { + if (s3->accel.cmd & 0x1000) + val = ((val & 0xff000000) >> 24) | ((val & 0x00ff0000) >> 8) | ((val & 0x0000ff00) << 8) | ((val & 0x000000ff) << 24); + s3_accel_start(32, 1, val, 0, s3); + } else + s3_accel_start(4, 1, 0xffffffff, val, s3); + } else + s3_accel_start(4, 1, 0xffffffff, val, s3); + break; + case 0x600: + if (s3->chip == S3_TRIO32 || s3->chip == S3_VISION968 || s3->chip == S3_VISION868 || s3->chip >= S3_TRIO64V) { + if (((s3->accel.multifunc[0xa] & 0xc0) == 0x80) || (s3->accel.cmd & 2)) { + if (((s3->accel.frgd_mix & 0x60) != 0x40) || ((s3->accel.bkgd_mix & 0x60) != 0x40)) { + if (s3->accel.cmd & 0x1000) + val = ((val & 0xff000000) >> 24) | ((val & 0x00ff0000) >> 8) | ((val & 0x0000ff00) << 8) | ((val & 0x000000ff) << 24); + s3_accel_start(8, 1, (val >> 24) & 0xff, 0, s3); + s3_accel_start(8, 1, (val >> 16) & 0xff, 0, s3); + s3_accel_start(8, 1, (val >> 8) & 0xff, 0, s3); + s3_accel_start(8, 1, val & 0xff, 0, s3); + } + } + } + break; + + default: + break; + } + } } static void s3_accel_out_fifo(s3_t *s3, uint16_t port, uint8_t val) -{ - svga_t *svga = &s3->svga; +{ + const svga_t *svga = &s3->svga; switch (port) { - case 0x8148: case 0x82e8: - s3->accel.cur_y_bitres = (s3->accel.cur_y_bitres & 0xff00) | val; - s3->accel.cur_y = (s3->accel.cur_y & 0xf00) | val; - s3->accel.poly_cy = s3->accel.cur_y; - break; - case 0x8149: case 0x82e9: - s3->accel.cur_y_bitres = (s3->accel.cur_y_bitres & 0xff) | (val << 8); - s3->accel.cur_y = (s3->accel.cur_y & 0xff) | ((val & 0x0f) << 8); - s3->accel.cur_y_bit12 = val & 0x10; - s3->accel.poly_cy = s3->accel.cur_y; - break; - case 0x814a: case 0x82ea: - s3->accel.cur_y2 = (s3->accel.cur_y2 & 0xf00) | val; - s3->accel.poly_cy2 = s3->accel.cur_y2; - break; - case 0x814b: case 0x82eb: - s3->accel.cur_y2 = (s3->accel.cur_y2 & 0xff) | ((val & 0x0f) << 8); - s3->accel.poly_cy2 = s3->accel.cur_y2; - break; - - case 0x8548: case 0x86e8: - s3->accel.cur_x_bitres = (s3->accel.cur_x_bitres & 0xff00) | val; - s3->accel.cur_x = (s3->accel.cur_x & 0xf00) | val; - s3->accel.poly_cx = s3->accel.cur_x << 20; - s3->accel.poly_x = s3->accel.poly_cx >> 20; - break; - case 0x8549: case 0x86e9: - s3->accel.cur_x_bitres = (s3->accel.cur_x_bitres & 0xff) | (val << 8); - s3->accel.cur_x = (s3->accel.cur_x & 0xff) | ((val & 0x0f) << 8); - s3->accel.cur_x_bit12 = val & 0x10; - s3->accel.poly_cx = s3->accel.poly_x = s3->accel.cur_x << 20; - s3->accel.poly_x = s3->accel.poly_cx >> 20; - break; - case 0x854a: case 0x86ea: - s3->accel.cur_x2 = (s3->accel.cur_x2 & 0xf00) | val; - s3->accel.poly_cx2 = s3->accel.cur_x2 << 20; - break; - case 0x854b: case 0x86eb: - s3->accel.cur_x2 = (s3->accel.cur_x2 & 0xff) | ((val & 0x0f) << 8); - s3->accel.poly_cx2 = s3->accel.cur_x2 << 20; - break; - - case 0xcae8: - case 0x8948: case 0x8ae8: - s3->accel.desty_axstp = (s3->accel.desty_axstp & 0x3f00) | val; - s3->accel.point_1_updated = 1; - break; - case 0xcae9: - case 0x8949: case 0x8ae9: - s3->accel.desty_axstp = (s3->accel.desty_axstp & 0xff) | ((val & 0x3f) << 8); - if (val & 0x20) - s3->accel.desty_axstp |= ~0x3fff; - s3->accel.point_1_updated = 1; - break; - case 0x894a: case 0x8aea: - s3->accel.desty_axstp2 = (s3->accel.desty_axstp2 & 0x3f00) | val; - s3->accel.point_2_updated = 1; - break; - case 0x849b: case 0x8aeb: - s3->accel.desty_axstp2 = (s3->accel.desty_axstp2 & 0xff) | ((val & 0x3f) << 8); - if (val & 0x20) - s3->accel.desty_axstp2 |= ~0x3fff; - s3->accel.point_2_updated = 1; - break; - - case 0x8d48: case 0x8ee8: - s3->accel.destx_distp = (s3->accel.destx_distp & 0x3f00) | val; - s3->accel.point_1_updated = 1; - break; - case 0x8d49: case 0x8ee9: - s3->accel.destx_distp = (s3->accel.destx_distp & 0xff) | ((val & 0x3f) << 8); - if (val & 0x20) - s3->accel.destx_distp |= ~0x3fff; - s3->accel.point_1_updated = 1; - break; - case 0x8d4a: case 0x8eea: - s3->accel.x2 = (s3->accel.x2 & 0xf00) | val; - s3->accel.point_2_updated = 1; - break; - case 0x8d4b: case 0x8eeb: - s3->accel.x2 = (s3->accel.x2 & 0xff) | ((val & 0x0f) << 8); - s3->accel.point_2_updated = 1; - break; - - case 0x9148: case 0x92e8: - s3->accel.err_term = (s3->accel.err_term & 0x3f00) | val; - break; - case 0x9149: case 0x92e9: - s3->accel.err_term = (s3->accel.err_term & 0xff) | ((val & 0x3f) << 8); - if (val & 0x20) - s3->accel.err_term |= ~0x3fff; - break; - case 0x914a: case 0x92ea: - s3->accel.err_term2 = (s3->accel.err_term2 & 0x3f00) | val; - break; - case 0x914b: case 0x92eb: - s3->accel.err_term2 = (s3->accel.err_term2 & 0xff) | ((val & 0x3f) << 8); - if (val & 0x20) - s3->accel.err_term2 |= ~0x3fff; - break; + case 0x8148: + case 0x82e8: + s3->accel.cur_y = (s3->accel.cur_y & 0xf00) | val; + s3->accel.poly_cy = s3->accel.cur_y; + break; + case 0x8149: + case 0x82e9: + s3->accel.cur_y = (s3->accel.cur_y & 0xff) | ((val & 0x0f) << 8); + s3->accel.poly_cy = s3->accel.cur_y; + break; + case 0x814a: + case 0x82ea: + s3->accel.cur_y2 = (s3->accel.cur_y2 & 0xf00) | val; + s3->accel.poly_cy2 = s3->accel.cur_y2; + break; + case 0x814b: + case 0x82eb: + s3->accel.cur_y2 = (s3->accel.cur_y2 & 0xff) | ((val & 0x0f) << 8); + s3->accel.poly_cy2 = s3->accel.cur_y2; + break; - case 0x9548: case 0x96e8: - s3->accel.maj_axis_pcnt = (s3->accel.maj_axis_pcnt & 0xf00) | val; - break; - case 0x9459: case 0x96e9: - s3->accel.maj_axis_pcnt = (s3->accel.maj_axis_pcnt & 0xff) | ((val & 0x0f) << 8); - if (val & 0x08) - s3->accel.maj_axis_pcnt |= ~0x0fff; - break; - case 0x954a: case 0x96ea: - s3->accel.maj_axis_pcnt2 = (s3->accel.maj_axis_pcnt2 & 0xf00) | val; - break; - case 0x954b: case 0x96eb: - s3->accel.maj_axis_pcnt2 = (s3->accel.maj_axis_pcnt2 & 0xff) | ((val & 0x0f) << 8); - if (val & 0x08) - s3->accel.maj_axis_pcnt2 |= ~0x0fff; - break; + case 0x8548: + case 0x86e8: + s3->accel.cur_x = (s3->accel.cur_x & 0xf00) | val; + s3->accel.poly_cx = s3->accel.cur_x << 20; + s3->accel.poly_x = s3->accel.poly_cx >> 20; + break; + case 0x8549: + case 0x86e9: + s3->accel.cur_x = (s3->accel.cur_x & 0xff) | ((val & 0x0f) << 8); + s3->accel.poly_cx = s3->accel.poly_x = s3->accel.cur_x << 20; + s3->accel.poly_x = s3->accel.poly_cx >> 20; + break; + case 0x854a: + case 0x86ea: + s3->accel.cur_x2 = (s3->accel.cur_x2 & 0xf00) | val; + s3->accel.poly_cx2 = s3->accel.cur_x2 << 20; + break; + case 0x854b: + case 0x86eb: + s3->accel.cur_x2 = (s3->accel.cur_x2 & 0xff) | ((val & 0x0f) << 8); + s3->accel.poly_cx2 = s3->accel.cur_x2 << 20; + break; - case 0x9948: case 0x9ae8: - s3->accel.cmd = (s3->accel.cmd & 0xff00) | val; - s3->data_available = 0; - s3->accel.b2e8_pix = 0; - break; - case 0x9949: case 0x9ae9: - s3->accel.cmd = (s3->accel.cmd & 0xff) | (val << 8); - s3->accel.ssv_state = 0; - s3_accel_start(-1, 0, 0xffffffff, 0, s3); - s3->accel.multifunc[0xe] &= ~0x10; /*hack*/ - break; + case 0xcae8: + case 0x8948: + case 0x8ae8: + s3->accel.desty_axstp = (s3->accel.desty_axstp & 0x3f00) | val; + s3->accel.point_1_updated = 1; + break; + case 0xcae9: + case 0x8949: + case 0x8ae9: + s3->accel.desty_axstp = (s3->accel.desty_axstp & 0xff) | ((val & 0x3f) << 8); + if (val & 0x20) + s3->accel.desty_axstp |= ~0x3fff; + s3->accel.point_1_updated = 1; + break; + case 0x894a: + case 0x8aea: + s3->accel.desty_axstp2 = (s3->accel.desty_axstp2 & 0x3f00) | val; + s3->accel.point_2_updated = 1; + break; + case 0x849b: + case 0x8aeb: + s3->accel.desty_axstp2 = (s3->accel.desty_axstp2 & 0xff) | ((val & 0x3f) << 8); + if (val & 0x20) + s3->accel.desty_axstp2 |= ~0x3fff; + s3->accel.point_2_updated = 1; + break; - case 0x994a: case 0x9aea: - s3->accel.cmd2 = (s3->accel.cmd2 & 0xff00) | val; - break; - case 0x994b: case 0x9aeb: - s3->accel.cmd2 = (s3->accel.cmd2 & 0xff) | (val << 8); - break; + case 0x8d48: + case 0x8ee8: + s3->accel.destx_distp = (s3->accel.destx_distp & 0x3f00) | val; + s3->accel.point_1_updated = 1; + break; + case 0x8d49: + case 0x8ee9: + s3->accel.destx_distp = (s3->accel.destx_distp & 0xff) | ((val & 0x3f) << 8); + if (val & 0x20) + s3->accel.destx_distp |= ~0x3fff; + s3->accel.point_1_updated = 1; + break; + case 0x8d4a: + case 0x8eea: + s3->accel.x2 = (s3->accel.x2 & 0xf00) | val; + s3->accel.point_2_updated = 1; + break; + case 0x8d4b: + case 0x8eeb: + s3->accel.x2 = (s3->accel.x2 & 0xff) | ((val & 0x0f) << 8); + s3->accel.point_2_updated = 1; + break; - case 0x9d48: case 0x9ee8: - s3->accel.short_stroke = (s3->accel.short_stroke & 0xff00) | val; - break; - case 0x9d49: case 0x9ee9: - s3->accel.short_stroke = (s3->accel.short_stroke & 0xff) | (val << 8); - s3->accel.ssv_state = 1; + case 0x9148: + case 0x92e8: + s3->accel.err_term = (s3->accel.err_term & 0x3f00) | val; + break; + case 0x9149: + case 0x92e9: + s3->accel.err_term = (s3->accel.err_term & 0xff) | ((val & 0x3f) << 8); + if (val & 0x20) + s3->accel.err_term |= ~0x1fff; + break; + case 0x914a: + case 0x92ea: + s3->accel.err_term2 = (s3->accel.err_term2 & 0x3f00) | val; + break; + case 0x914b: + case 0x92eb: + s3->accel.err_term2 = (s3->accel.err_term2 & 0xff) | ((val & 0x3f) << 8); + if (val & 0x20) + s3->accel.err_term2 |= ~0x1fff; + break; - s3->accel.cx = s3->accel.cur_x; - if (s3->accel.cur_x_bit12) s3->accel.cx |= ~0xfff; - s3->accel.cy = s3->accel.cur_y; - if (s3->accel.cur_y_bit12) s3->accel.cy |= ~0xfff; + case 0x9548: + case 0x96e8: + s3->accel.maj_axis_pcnt = (s3->accel.maj_axis_pcnt & 0xf00) | val; + break; + case 0x9459: + case 0x96e9: + s3->accel.maj_axis_pcnt = (s3->accel.maj_axis_pcnt & 0xff) | ((val & 0x0f) << 8); + break; + case 0x954a: + case 0x96ea: + s3->accel.maj_axis_pcnt2 = (s3->accel.maj_axis_pcnt2 & 0xf00) | val; + break; + case 0x954b: + case 0x96eb: + s3->accel.maj_axis_pcnt2 = (s3->accel.maj_axis_pcnt2 & 0xff) | ((val & 0x0f) << 8); + break; - if (s3->accel.cmd & 0x1000) { - s3_short_stroke_start(-1, 0, 0xffffffff, 0, s3, s3->accel.short_stroke & 0xff); - s3_short_stroke_start(-1, 0, 0xffffffff, 0, s3, s3->accel.short_stroke >> 8); - } else { - s3_short_stroke_start(-1, 0, 0xffffffff, 0, s3, s3->accel.short_stroke >> 8); - s3_short_stroke_start(-1, 0, 0xffffffff, 0, s3, s3->accel.short_stroke & 0xff); - } - break; + case 0x9948: + case 0x9ae8: + s3->accel.cmd = (s3->accel.cmd & 0xff00) | val; + s3->data_available = 0; + s3->accel.b2e8_pix = 0; + break; + case 0x9949: + case 0x9ae9: + s3->accel.cmd = (s3->accel.cmd & 0xff) | (val << 8); + s3->accel.ssv_state = 0; + s3_accel_start(-1, 0, 0xffffffff, 0, s3); + break; - case 0xa148: case 0xa2e8: - if (s3->bpp == 3 && s3->accel.multifunc[0xe] & 0x10 && !(s3->accel.multifunc[0xe] & 0x200)) - s3->accel.bkgd_color = (s3->accel.bkgd_color & ~0x00ff0000) | (val << 16); - else - s3->accel.bkgd_color = (s3->accel.bkgd_color & ~0x000000ff) | val; - break; - case 0xa149: case 0xa2e9: - if (s3->bpp == 3 && s3->accel.multifunc[0xe] & 0x10 && !(s3->accel.multifunc[0xe] & 0x200)) - s3->accel.bkgd_color = (s3->accel.bkgd_color & ~0xff000000) | (val << 24); - else - s3->accel.bkgd_color = (s3->accel.bkgd_color & ~0x0000ff00) | (val << 8); - if (!(s3->accel.multifunc[0xe] & 0x200)) - s3->accel.multifunc[0xe] ^= 0x10; - break; - case 0xa14a: case 0xa2ea: - if (s3->accel.multifunc[0xe] & 0x200) - s3->accel.bkgd_color = (s3->accel.bkgd_color & ~0x00ff0000) | (val << 16); - else if (s3->bpp == 3) { - if (s3->accel.multifunc[0xe] & 0x10) - s3->accel.bkgd_color = (s3->accel.bkgd_color & ~0x00ff0000) | (val << 16); - else - s3->accel.bkgd_color = (s3->accel.bkgd_color & ~0x000000ff) | val; - } - break; - case 0xa14b: case 0xa2eb: - if (s3->accel.multifunc[0xe] & 0x200) - s3->accel.bkgd_color = (s3->accel.bkgd_color & ~0xff000000) | (val << 24); - else if (s3->bpp == 3) { - if (s3->accel.multifunc[0xe] & 0x10) - s3->accel.bkgd_color = (s3->accel.bkgd_color & ~0xff000000) | (val << 24); - else - s3->accel.bkgd_color = (s3->accel.bkgd_color & ~0x0000ff00) | (val << 8); - s3->accel.multifunc[0xe] ^= 0x10; - } - break; + case 0x994a: + case 0x9aea: + s3->accel.cmd2 = (s3->accel.cmd2 & 0xff00) | val; + break; + case 0x994b: + case 0x9aeb: + s3->accel.cmd2 = (s3->accel.cmd2 & 0xff) | (val << 8); + break; - case 0xa548: case 0xa6e8: - if (s3->bpp == 3 && s3->accel.multifunc[0xe] & 0x10 && !(s3->accel.multifunc[0xe] & 0x200)) - s3->accel.frgd_color = (s3->accel.frgd_color & ~0x00ff0000) | (val << 16); - else - s3->accel.frgd_color = (s3->accel.frgd_color & ~0x000000ff) | val; - break; - case 0xa549: case 0xa6e9: - if (s3->bpp == 3 && s3->accel.multifunc[0xe] & 0x10 && !(s3->accel.multifunc[0xe] & 0x200)) - s3->accel.frgd_color = (s3->accel.frgd_color & ~0xff000000) | (val << 24); - else - s3->accel.frgd_color = (s3->accel.frgd_color & ~0x0000ff00) | (val << 8); - if (!(s3->accel.multifunc[0xe] & 0x200)) - s3->accel.multifunc[0xe] ^= 0x10; - break; - case 0xa54a: case 0xa6ea: - if (s3->accel.multifunc[0xe] & 0x200) - s3->accel.frgd_color = (s3->accel.frgd_color & ~0x00ff0000) | (val << 16); - else if (s3->bpp == 3) { - if (s3->accel.multifunc[0xe] & 0x10) - s3->accel.frgd_color = (s3->accel.frgd_color & ~0x00ff0000) | (val << 16); - else - s3->accel.frgd_color = (s3->accel.frgd_color & ~0x000000ff) | val; - } - break; - case 0xa54b: case 0xa6eb: - if (s3->accel.multifunc[0xe] & 0x200) - s3->accel.frgd_color = (s3->accel.frgd_color & ~0xff000000) | (val << 24); - else if (s3->bpp == 3) { - if (s3->accel.multifunc[0xe] & 0x10) - s3->accel.frgd_color = (s3->accel.frgd_color & ~0xff000000) | (val << 24); - else - s3->accel.frgd_color = (s3->accel.frgd_color & ~0x0000ff00) | (val << 8); - s3->accel.multifunc[0xe] ^= 0x10; - } - break; + case 0x9d48: + case 0x9ee8: + s3->accel.short_stroke = (s3->accel.short_stroke & 0xff00) | val; + break; + case 0x9d49: + case 0x9ee9: + s3->accel.short_stroke = (s3->accel.short_stroke & 0xff) | (val << 8); + s3->accel.ssv_state = 1; - case 0xa948: case 0xaae8: - if (s3->bpp == 3 && s3->accel.multifunc[0xe] & 0x10 && !(s3->accel.multifunc[0xe] & 0x200)) - s3->accel.wrt_mask = (s3->accel.wrt_mask & ~0x00ff0000) | (val << 16); - else - s3->accel.wrt_mask = (s3->accel.wrt_mask & ~0x000000ff) | val; - break; - case 0xa949: case 0xaae9: - if (s3->bpp == 3 && s3->accel.multifunc[0xe] & 0x10 && !(s3->accel.multifunc[0xe] & 0x200)) - s3->accel.wrt_mask = (s3->accel.wrt_mask & ~0xff000000) | (val << 24); - else - s3->accel.wrt_mask = (s3->accel.wrt_mask & ~0x0000ff00) | (val << 8); - if (!(s3->accel.multifunc[0xe] & 0x200)) - s3->accel.multifunc[0xe] ^= 0x10; - break; - case 0xa94a: case 0xaaea: - if (s3->accel.multifunc[0xe] & 0x200) - s3->accel.wrt_mask = (s3->accel.wrt_mask & ~0x00ff0000) | (val << 16); - else if (s3->bpp == 3) { - if (s3->accel.multifunc[0xe] & 0x10) - s3->accel.wrt_mask = (s3->accel.wrt_mask & ~0x00ff0000) | (val << 16); - else - s3->accel.wrt_mask = (s3->accel.wrt_mask & ~0x000000ff) | val; - } - break; - case 0xa94b: case 0xaaeb: - if (s3->accel.multifunc[0xe] & 0x200) - s3->accel.wrt_mask = (s3->accel.wrt_mask & ~0xff000000) | (val << 24); - else if (s3->bpp == 3) { - if (s3->accel.multifunc[0xe] & 0x10) - s3->accel.wrt_mask = (s3->accel.wrt_mask & ~0xff000000) | (val << 24); - else - s3->accel.wrt_mask = (s3->accel.wrt_mask & ~0x0000ff00) | (val << 8); - s3->accel.multifunc[0xe] ^= 0x10; - } - break; + s3->accel.cx = s3->accel.cur_x & 0xfff; + s3->accel.cy = s3->accel.cur_y & 0xfff; - case 0xad48: case 0xaee8: - if (s3->bpp == 3 && s3->accel.multifunc[0xe] & 0x10 && !(s3->accel.multifunc[0xe] & 0x200)) - s3->accel.rd_mask = (s3->accel.rd_mask & ~0x00ff0000) | (val << 16); - else - s3->accel.rd_mask = (s3->accel.rd_mask & ~0x000000ff) | val; - break; - case 0xad49: case 0xaee9: - if (s3->bpp == 3 && s3->accel.multifunc[0xe] & 0x10 && !(s3->accel.multifunc[0xe] & 0x200)) - s3->accel.rd_mask = (s3->accel.rd_mask & ~0xff000000) | (val << 24); - else - s3->accel.rd_mask = (s3->accel.rd_mask & ~0x0000ff00) | (val << 8); - if (!(s3->accel.multifunc[0xe] & 0x200)) - s3->accel.multifunc[0xe] ^= 0x10; - break; - case 0xad4a: case 0xaeea: - if (s3->accel.multifunc[0xe] & 0x200) - s3->accel.rd_mask = (s3->accel.rd_mask & ~0x00ff0000) | (val << 16); - else if (s3->bpp == 3) { - if (s3->accel.multifunc[0xe] & 0x10) - s3->accel.rd_mask = (s3->accel.rd_mask & ~0x00ff0000) | (val << 16); - else - s3->accel.rd_mask = (s3->accel.rd_mask & ~0x000000ff) | val; - } - break; - case 0xad4b: case 0xaeeb: - if (s3->accel.multifunc[0xe] & 0x200) - s3->accel.rd_mask = (s3->accel.rd_mask & ~0xff000000) | (val << 24); - else if (s3->bpp == 3) { - if (s3->accel.multifunc[0xe] & 0x10) - s3->accel.rd_mask = (s3->accel.rd_mask & ~0xff000000) | (val << 24); - else - s3->accel.rd_mask = (s3->accel.rd_mask & ~0x0000ff00) | (val << 8); - s3->accel.multifunc[0xe] ^= 0x10; - } - break; + if (s3->accel.cmd & 0x1000) { + s3_short_stroke_start(-1, 0, 0xffffffff, 0, s3, s3->accel.short_stroke & 0xff); + s3_short_stroke_start(-1, 0, 0xffffffff, 0, s3, s3->accel.short_stroke >> 8); + } else { + s3_short_stroke_start(-1, 0, 0xffffffff, 0, s3, s3->accel.short_stroke >> 8); + s3_short_stroke_start(-1, 0, 0xffffffff, 0, s3, s3->accel.short_stroke & 0xff); + } + break; - case 0xb148: case 0xb2e8: - if (s3->bpp == 3 && s3->accel.multifunc[0xe] & 0x10 && !(s3->accel.multifunc[0xe] & 0x200)) - s3->accel.color_cmp = (s3->accel.color_cmp & ~0x00ff0000) | (val << 16); - else - s3->accel.color_cmp = (s3->accel.color_cmp & ~0x000000ff) | val; - break; - case 0xb149: case 0xb2e9: - if (s3->bpp == 3 && s3->accel.multifunc[0xe] & 0x10 && !(s3->accel.multifunc[0xe] & 0x200)) - s3->accel.color_cmp = (s3->accel.color_cmp & ~0xff000000) | (val << 24); - else - s3->accel.color_cmp = (s3->accel.color_cmp & ~0x0000ff00) | (val << 8); - if (!(s3->accel.multifunc[0xe] & 0x200)) - s3->accel.multifunc[0xe] ^= 0x10; - break; - case 0xb14a: case 0xb2ea: - if (s3->accel.multifunc[0xe] & 0x200) - s3->accel.color_cmp = (s3->accel.color_cmp & ~0x00ff0000) | (val << 16); - else if (s3->bpp == 3) { - if (s3->accel.multifunc[0xe] & 0x10) - s3->accel.color_cmp = (s3->accel.color_cmp & ~0x00ff0000) | (val << 16); - else - s3->accel.color_cmp = (s3->accel.color_cmp & ~0x000000ff) | val; - } - break; - case 0xb14b: case 0xb2eb: - if (s3->accel.multifunc[0xe] & 0x200) - s3->accel.color_cmp = (s3->accel.color_cmp & ~0xff000000) | (val << 24); - else if (s3->bpp == 3) { - if (s3->accel.multifunc[0xe] & 0x10) - s3->accel.color_cmp = (s3->accel.color_cmp & ~0xff000000) | (val << 24); - else - s3->accel.color_cmp = (s3->accel.color_cmp & ~0x0000ff00) | (val << 8); - s3->accel.multifunc[0xe] ^= 0x10; - } - break; + case 0xa148: + case 0xa2e8: + if ((s3->bpp == 3) && (s3->accel.multifunc[0xe] & 0x10) && !(s3->accel.multifunc[0xe] & 0x200)) + s3->accel.bkgd_color = (s3->accel.bkgd_color & 0xff00ffff) | (val << 16); + else + s3->accel.bkgd_color = (s3->accel.bkgd_color & 0xffffff00) | val; + break; + case 0xa149: + case 0xa2e9: + if ((s3->bpp == 3) && (s3->accel.multifunc[0xe] & 0x10) && !(s3->accel.multifunc[0xe] & 0x200)) + s3->accel.bkgd_color = (s3->accel.bkgd_color & 0x00ffffff) | (val << 24); + else + s3->accel.bkgd_color = (s3->accel.bkgd_color & 0xffff00ff) | (val << 8); + if (!(s3->accel.multifunc[0xe] & 0x200)) + s3->accel.multifunc[0xe] ^= 0x10; + break; + case 0xa14a: + case 0xa2ea: + if ((s3->bpp == 3) && (s3->accel.multifunc[0xe] & 0x10) && !(s3->accel.multifunc[0xe] & 0x200)) + s3->accel.bkgd_color = (s3->accel.bkgd_color & 0xffffff00) | val; + else + s3->accel.bkgd_color = (s3->accel.bkgd_color & 0xff00ffff) | (val << 16); + break; + case 0xa14b: + case 0xa2eb: + if ((s3->bpp == 3) && (s3->accel.multifunc[0xe] & 0x10) && !(s3->accel.multifunc[0xe] & 0x200)) + s3->accel.bkgd_color = (s3->accel.bkgd_color & 0xffff00ff) | (val << 8); + else + s3->accel.bkgd_color = (s3->accel.bkgd_color & 0x00ffffff) | (val << 24); + if (!(s3->accel.multifunc[0xe] & 0x200)) + s3->accel.multifunc[0xe] ^= 0x10; + break; - case 0xb548: case 0xb6e8: - s3->accel.bkgd_mix = val; - break; + case 0xa548: + case 0xa6e8: + if ((s3->bpp == 3) && (s3->accel.multifunc[0xe] & 0x10) && !(s3->accel.multifunc[0xe] & 0x200)) + s3->accel.frgd_color = (s3->accel.frgd_color & 0xff00ffff) | (val << 16); + else + s3->accel.frgd_color = (s3->accel.frgd_color & 0xffffff00) | val; + break; + case 0xa549: + case 0xa6e9: + if ((s3->bpp == 3) && (s3->accel.multifunc[0xe] & 0x10) && !(s3->accel.multifunc[0xe] & 0x200)) + s3->accel.frgd_color = (s3->accel.frgd_color & 0x00ffffff) | (val << 24); + else + s3->accel.frgd_color = (s3->accel.frgd_color & 0xffff00ff) | (val << 8); + if (!(s3->accel.multifunc[0xe] & 0x200)) + s3->accel.multifunc[0xe] ^= 0x10; + break; + case 0xa54a: + case 0xa6ea: + if ((s3->bpp == 3) && (s3->accel.multifunc[0xe] & 0x10) && !(s3->accel.multifunc[0xe] & 0x200)) + s3->accel.frgd_color = (s3->accel.frgd_color & 0xffffff00) | val; + else + s3->accel.frgd_color = (s3->accel.frgd_color & 0xff00ffff) | (val << 16); + break; + case 0xa54b: + case 0xa6eb: + if ((s3->bpp == 3) && (s3->accel.multifunc[0xe] & 0x10) && !(s3->accel.multifunc[0xe] & 0x200)) + s3->accel.frgd_color = (s3->accel.frgd_color & 0xffff00ff) | (val << 8); + else + s3->accel.frgd_color = (s3->accel.frgd_color & 0x00ffffff) | (val << 24); + if (!(s3->accel.multifunc[0xe] & 0x200)) + s3->accel.multifunc[0xe] ^= 0x10; + break; - case 0xb948: case 0xbae8: - s3->accel.frgd_mix = val; - break; - - case 0xbd48: case 0xbee8: - s3->accel.multifunc_cntl = (s3->accel.multifunc_cntl & 0xff00) | val; - break; - case 0xbd49: case 0xbee9: - s3->accel.multifunc_cntl = (s3->accel.multifunc_cntl & 0xff) | (val << 8); - s3->accel.multifunc[s3->accel.multifunc_cntl >> 12] = s3->accel.multifunc_cntl & 0xfff; - break; + case 0xa948: + case 0xaae8: + if ((s3->bpp == 3) && (s3->accel.multifunc[0xe] & 0x10) && !(s3->accel.multifunc[0xe] & 0x200)) + s3->accel.wrt_mask = (s3->accel.wrt_mask & 0xff00ffff) | (val << 16); + else + s3->accel.wrt_mask = (s3->accel.wrt_mask & 0xffffff00) | val; + break; + case 0xa949: + case 0xaae9: + if ((s3->bpp == 3) && (s3->accel.multifunc[0xe] & 0x10) && !(s3->accel.multifunc[0xe] & 0x200)) + s3->accel.wrt_mask = (s3->accel.wrt_mask & 0x00ffffff) | (val << 24); + else + s3->accel.wrt_mask = (s3->accel.wrt_mask & 0xffff00ff) | (val << 8); + if (!(s3->accel.multifunc[0xe] & 0x200)) + s3->accel.multifunc[0xe] ^= 0x10; + break; + case 0xa94a: + case 0xaaea: + if ((s3->bpp == 3) && (s3->accel.multifunc[0xe] & 0x10) && !(s3->accel.multifunc[0xe] & 0x200)) + s3->accel.wrt_mask = (s3->accel.wrt_mask & 0xffffff00) | val; + else + s3->accel.wrt_mask = (s3->accel.wrt_mask & 0xff00ffff) | (val << 16); + break; + case 0xa94b: + case 0xaaeb: + if ((s3->bpp == 3) && (s3->accel.multifunc[0xe] & 0x10) && !(s3->accel.multifunc[0xe] & 0x200)) + s3->accel.wrt_mask = (s3->accel.wrt_mask & 0xffff00ff) | (val << 8); + else + s3->accel.wrt_mask = (s3->accel.wrt_mask & 0x00ffffff) | (val << 24); + if (!(s3->accel.multifunc[0xe] & 0x200)) + s3->accel.multifunc[0xe] ^= 0x10; + break; - case 0xd148: case 0xd2e8: - s3->accel.ropmix = (s3->accel.ropmix & 0xff00) | val; - break; - case 0xd149: case 0xd2e9: - s3->accel.ropmix = (s3->accel.ropmix & 0x00ff) | (val << 8); - break; - case 0xe548: case 0xe6e8: - if (s3->bpp == 3 && s3->accel.multifunc[0xe] & 0x10 && !(s3->accel.multifunc[0xe] & 0x200)) - s3->accel.pat_bg_color = (s3->accel.pat_bg_color & ~0x00ff0000) | (val << 16); - else - s3->accel.pat_bg_color = (s3->accel.pat_bg_color & ~0x000000ff) | val; - break; - case 0xe549: case 0xe6e9: - if (s3->bpp == 3 && s3->accel.multifunc[0xe] & 0x10 && !(s3->accel.multifunc[0xe] & 0x200)) - s3->accel.pat_bg_color = (s3->accel.pat_bg_color & ~0xff000000) | (val << 24); - else - s3->accel.pat_bg_color = (s3->accel.pat_bg_color & ~0x0000ff00) | (val << 8); - if (!(s3->accel.multifunc[0xe] & 0x200)) - s3->accel.multifunc[0xe] ^= 0x10; - break; - case 0xe54a: case 0xe6ea: - if (s3->accel.multifunc[0xe] & 0x200) - s3->accel.pat_bg_color = (s3->accel.pat_bg_color & ~0x00ff0000) | (val << 16); - else if (s3->bpp == 3) { - if (s3->accel.multifunc[0xe] & 0x10) - s3->accel.pat_bg_color = (s3->accel.pat_bg_color & ~0x00ff0000) | (val << 16); - else - s3->accel.pat_bg_color = (s3->accel.pat_bg_color & ~0x000000ff) | val; - } - break; - case 0xe54b: case 0xe6eb: - if (s3->accel.multifunc[0xe] & 0x200) - s3->accel.pat_bg_color = (s3->accel.pat_bg_color & ~0xff000000) | (val << 24); - else if (s3->bpp == 3) { - if (s3->accel.multifunc[0xe] & 0x10) - s3->accel.pat_bg_color = (s3->accel.pat_bg_color & ~0xff000000) | (val << 24); - else - s3->accel.pat_bg_color = (s3->accel.pat_bg_color & ~0x0000ff00) | (val << 8); - s3->accel.multifunc[0xe] ^= 0x10; - } - break; - case 0xe948: case 0xeae8: - s3->accel.pat_y = (s3->accel.pat_y & 0xf00) | val; - break; - case 0xe949: case 0xeae9: - s3->accel.pat_y = (s3->accel.pat_y & 0xff) | ((val & 0x1f) << 8); - break; - case 0xe94a: case 0xeaea: - s3->accel.pat_x = (s3->accel.pat_x & 0xf00) | val; - break; - case 0xe94b: case 0xeaeb: - s3->accel.pat_x = (s3->accel.pat_x & 0xff) | ((val & 0x1f) << 8); - break; - case 0xed48: case 0xeee8: - if (s3->bpp == 3 && s3->accel.multifunc[0xe] & 0x10 && !(s3->accel.multifunc[0xe] & 0x200)) - s3->accel.pat_fg_color = (s3->accel.pat_fg_color & ~0x00ff0000) | (val << 16); - else - s3->accel.pat_fg_color = (s3->accel.pat_fg_color & ~0x000000ff) | val; - break; - case 0xed49: case 0xeee9: - if (s3->bpp == 3 && s3->accel.multifunc[0xe] & 0x10 && !(s3->accel.multifunc[0xe] & 0x200)) - s3->accel.pat_fg_color = (s3->accel.pat_fg_color & ~0xff000000) | (val << 24); - else - s3->accel.pat_fg_color = (s3->accel.pat_fg_color & ~0x0000ff00) | (val << 8); - if (!(s3->accel.multifunc[0xe] & 0x200)) - s3->accel.multifunc[0xe] ^= 0x10; - break; - case 0xed4a: case 0xeeea: - if (s3->accel.multifunc[0xe] & 0x200) - s3->accel.pat_fg_color = (s3->accel.pat_fg_color & ~0x00ff0000) | (val << 16); - else if (s3->bpp == 3) { - if (s3->accel.multifunc[0xe] & 0x10) - s3->accel.pat_fg_color = (s3->accel.pat_fg_color & ~0x00ff0000) | (val << 16); - else - s3->accel.pat_fg_color = (s3->accel.pat_fg_color & ~0x000000ff) | val; - } - break; - case 0xed4b: case 0xeeeb: - if (s3->accel.multifunc[0xe] & 0x200) - s3->accel.pat_fg_color = (s3->accel.pat_fg_color & ~0xff000000) | (val << 24); - else if (s3->bpp == 3) { - if (s3->accel.multifunc[0xe] & 0x10) - s3->accel.pat_fg_color = (s3->accel.pat_fg_color & ~0xff000000) | (val << 24); - else - s3->accel.pat_fg_color = (s3->accel.pat_fg_color & ~0x0000ff00) | (val << 8); - s3->accel.multifunc[0xe] ^= 0x10; - } - break; + case 0xad48: + case 0xaee8: + if ((s3->bpp == 3) && (s3->accel.multifunc[0xe] & 0x10) && !(s3->accel.multifunc[0xe] & 0x200)) + s3->accel.rd_mask = (s3->accel.rd_mask & 0xff00ffff) | (val << 16); + else + s3->accel.rd_mask = (s3->accel.rd_mask & 0xffffff00) | val; + break; + case 0xad49: + case 0xaee9: + if ((s3->bpp == 3) && (s3->accel.multifunc[0xe] & 0x10) && !(s3->accel.multifunc[0xe] & 0x200)) + s3->accel.rd_mask = (s3->accel.rd_mask & 0x00ffffff) | (val << 24); + else + s3->accel.rd_mask = (s3->accel.rd_mask & 0xffff00ff) | (val << 8); + if (!(s3->accel.multifunc[0xe] & 0x200)) + s3->accel.multifunc[0xe] ^= 0x10; + break; + case 0xad4a: + case 0xaeea: + if ((s3->bpp == 3) && (s3->accel.multifunc[0xe] & 0x10) && !(s3->accel.multifunc[0xe] & 0x200)) + s3->accel.rd_mask = (s3->accel.rd_mask & 0xffffff00) | val; + else + s3->accel.rd_mask = (s3->accel.rd_mask & 0xff00ffff) | (val << 16); + break; + case 0xad4b: + case 0xaeeb: + if ((s3->bpp == 3) && (s3->accel.multifunc[0xe] & 0x10) && !(s3->accel.multifunc[0xe] & 0x200)) + s3->accel.rd_mask = (s3->accel.rd_mask & 0xffff00ff) | (val << 8); + else + s3->accel.rd_mask = (s3->accel.rd_mask & 0x00ffffff) | (val << 24); + if (!(s3->accel.multifunc[0xe] & 0x200)) + s3->accel.multifunc[0xe] ^= 0x10; + break; - case 0xe148: case 0xe2e8: - s3->accel.b2e8_pix = 0; - if (s3_cpu_dest(s3)) - break; - s3->accel.pix_trans[0] = val; - if (s3->accel.cmd & 0x100) { - switch (s3->accel.cmd & 0x600) { - case 0x000: - if (((s3->accel.multifunc[0xa] & 0xc0) == 0x80) || (s3->accel.cmd & 2)) { - if (((s3->accel.frgd_mix & 0x60) != 0x40) || ((s3->accel.bkgd_mix & 0x60) != 0x40)) - s3_accel_start(8, 1, s3->accel.pix_trans[0], 0, s3); - else - s3_accel_start(1, 1, 0xffffffff, s3->accel.pix_trans[0], s3); - } else { - if (s3->color_16bit) - s3_accel_start(2, 1, 0xffffffff, s3->accel.pix_trans[0], s3); - else - s3_accel_start(1, 1, 0xffffffff, s3->accel.pix_trans[0], s3); - } - break; - case 0x200: - if (((s3->accel.multifunc[0xa] & 0xc0) == 0x80) || (s3->accel.cmd & 2)) { - if (((s3->accel.frgd_mix & 0x60) != 0x40) || ((s3->accel.bkgd_mix & 0x60) != 0x40)) - s3_accel_start(16, 1, s3->accel.pix_trans[0] | (s3->accel.pix_trans[0] << 8), 0, s3); - else - s3_accel_start(2, 1, 0xffffffff, s3->accel.pix_trans[0] | (s3->accel.pix_trans[0] << 8), s3); - } else { - if (s3->chip != S3_86C928PCI && s3->chip != S3_86C928) { - s3_accel_start(2, 1, 0xffffffff, s3->accel.pix_trans[0] | (s3->accel.pix_trans[0] << 8), s3); - } - } - break; - } - } - break; - case 0xe149: case 0xe2e9: - s3->accel.b2e8_pix = 0; - if (s3_cpu_dest(s3)) - break; - s3->accel.pix_trans[1] = val; - if (s3->accel.cmd & 0x100) { - switch (s3->accel.cmd & 0x600) { - case 0x000: - if (((s3->accel.multifunc[0xa] & 0xc0) == 0x80) || (s3->accel.cmd & 2)) { - if (((s3->accel.frgd_mix & 0x60) != 0x40) || ((s3->accel.bkgd_mix & 0x60) != 0x40)) - s3_accel_start(8, 1, s3->accel.pix_trans[0] | (s3->accel.pix_trans[1] << 8), 0, s3); - else - s3_accel_start(1, 1, 0xffffffff, s3->accel.pix_trans[0] | (s3->accel.pix_trans[1] << 8), s3); - } else { - s3_accel_start(1, 1, 0xffffffff, s3->accel.pix_trans[0] | (s3->accel.pix_trans[1] << 8), s3); - } - break; - case 0x200: - /*Windows 95's built-in driver expects this to be loaded regardless of the byte swap bit (0xE2E9) in the 86c928 ISA/VLB*/ - if (((s3->accel.multifunc[0xa] & 0xc0) == 0x80) || (s3->accel.cmd & 2)) { - if (((s3->accel.frgd_mix & 0x60) != 0x40) || ((s3->accel.bkgd_mix & 0x60) != 0x40)) { - if (s3->accel.cmd & 0x1000) - s3_accel_start(16, 1, s3->accel.pix_trans[1] | (s3->accel.pix_trans[0] << 8), 0, s3); - else - s3_accel_start(16, 1, s3->accel.pix_trans[0] | (s3->accel.pix_trans[1] << 8), 0, s3); - } else { - if (s3->chip == S3_86C928 || s3->chip == S3_86C928PCI) { - s3_accel_out_pixtrans_w(s3, s3->accel.pix_trans[0] | (s3->accel.pix_trans[1] << 8)); - } else { - if (s3->accel.cmd & 0x1000) - s3_accel_start(2, 1, 0xffffffff, s3->accel.pix_trans[1] | (s3->accel.pix_trans[0] << 8), s3); - else - s3_accel_start(2, 1, 0xffffffff, s3->accel.pix_trans[0] | (s3->accel.pix_trans[1] << 8), s3); - } - } - } else { - if (s3->chip == S3_86C928 || s3->chip == S3_86C928PCI) { - s3_accel_out_pixtrans_w(s3, s3->accel.pix_trans[0] | (s3->accel.pix_trans[1] << 8)); - } else { - if (s3->accel.cmd & 0x1000) - s3_accel_start(2, 1, 0xffffffff, s3->accel.pix_trans[1] | (s3->accel.pix_trans[0] << 8), s3); - else - s3_accel_start(2, 1, 0xffffffff, s3->accel.pix_trans[0] | (s3->accel.pix_trans[1] << 8), s3); - } - } - break; - case 0x400: - if (svga->crtc[0x53] & 0x08) { - if (((s3->accel.multifunc[0xa] & 0xc0) == 0x80) || (s3->accel.cmd & 2)) { - if (((s3->accel.frgd_mix & 0x60) != 0x40) || ((s3->accel.bkgd_mix & 0x60) != 0x40)) - s3_accel_start(32, 1, s3->accel.pix_trans[0] | (s3->accel.pix_trans[1] << 8), 0, s3); - else - s3_accel_start(4, 1, 0xffffffff, s3->accel.pix_trans[0] | (s3->accel.pix_trans[1] << 8), s3); - } else - s3_accel_start(4, 1, 0xffffffff, s3->accel.pix_trans[0] | (s3->accel.pix_trans[1] << 8), s3); - } - break; - case 0x600: - if (s3->chip == S3_TRIO32 || s3->chip == S3_VISION968 || s3->chip == S3_VISION868 || s3->chip >= S3_TRIO64V) { - if (((s3->accel.multifunc[0xa] & 0xc0) == 0x80) || (s3->accel.cmd & 2)) { - if (((s3->accel.frgd_mix & 0x60) != 0x40) || ((s3->accel.bkgd_mix & 0x60) != 0x40)) { - s3_accel_start(8, 1, s3->accel.pix_trans[1], 0, s3); - s3_accel_start(8, 1, s3->accel.pix_trans[0], 0, s3); - } - } - } - break; - } - } - break; - case 0xe14a: case 0xe2ea: - if (s3_cpu_dest(s3)) - break; - s3->accel.pix_trans[2] = val; - break; - case 0xe14b: case 0xe2eb: - if (s3_cpu_dest(s3)) - break; - s3->accel.pix_trans[3] = val; - if (s3->accel.cmd & 0x100) { - switch (s3->accel.cmd & 0x600) { - case 0x000: - if (((s3->accel.multifunc[0xa] & 0xc0) == 0x80) || (s3->accel.cmd & 2)) { - if (((s3->accel.frgd_mix & 0x60) != 0x40) || ((s3->accel.bkgd_mix & 0x60) != 0x40)) - s3_accel_start(8, 1, s3->accel.pix_trans[0] | (s3->accel.pix_trans[1] << 8) | (s3->accel.pix_trans[2] << 16) | (s3->accel.pix_trans[3] << 24), 0, s3); - else - s3_accel_start(1, 1, 0xffffffff, s3->accel.pix_trans[0] | (s3->accel.pix_trans[1] << 8) | (s3->accel.pix_trans[2] << 16) | (s3->accel.pix_trans[3] << 24), s3); - } else - s3_accel_start(1, 1, 0xffffffff, s3->accel.pix_trans[0] | (s3->accel.pix_trans[1] << 8) | (s3->accel.pix_trans[2] << 16) | (s3->accel.pix_trans[3] << 24), s3); - break; - case 0x200: - /*Windows 95's built-in driver expects the upper 16 bits to be loaded instead of the whole 32-bit one, regardless of the byte swap bit (0xE2EB) in the 86c928 ISA/VLB card*/ - if (((s3->accel.multifunc[0xa] & 0xc0) == 0x80) || (s3->accel.cmd & 2)) { - if (((s3->accel.frgd_mix & 0x60) != 0x40) || ((s3->accel.bkgd_mix & 0x60) != 0x40)) { - if (s3->accel.cmd & 0x1000) - s3_accel_start(16, 1, s3->accel.pix_trans[3] | (s3->accel.pix_trans[2] << 8) | (s3->accel.pix_trans[1] << 16) | (s3->accel.pix_trans[0] << 24), 0, s3); - else - s3_accel_start(16, 1, s3->accel.pix_trans[0] | (s3->accel.pix_trans[1] << 8) | (s3->accel.pix_trans[2] << 16) | (s3->accel.pix_trans[3] << 24), 0, s3); - } else { - if (s3->chip == S3_86C928 || s3->chip == S3_86C928PCI) { - s3_accel_out_pixtrans_w(s3, s3->accel.pix_trans[2] | (s3->accel.pix_trans[3] << 8)); - } else { - if (s3->accel.cmd & 0x1000) - s3_accel_start(2, 1, 0xffffffff, s3->accel.pix_trans[3] | (s3->accel.pix_trans[2] << 8) | (s3->accel.pix_trans[1] << 16) | (s3->accel.pix_trans[0] << 24), s3); - else - s3_accel_start(2, 1, 0xffffffff, s3->accel.pix_trans[0] | (s3->accel.pix_trans[1] << 8) | (s3->accel.pix_trans[2] << 16) | (s3->accel.pix_trans[3] << 24), s3); - } - } - } else { - if (s3->chip == S3_86C928 || s3->chip == S3_86C928PCI) { - s3_accel_out_pixtrans_w(s3, s3->accel.pix_trans[2] | (s3->accel.pix_trans[3] << 8)); - } else { - if (s3->accel.cmd & 0x1000) - s3_accel_start(2, 1, 0xffffffff, s3->accel.pix_trans[3] | (s3->accel.pix_trans[2] << 8) | (s3->accel.pix_trans[1] << 16) | (s3->accel.pix_trans[0] << 24), s3); - else - s3_accel_start(2, 1, 0xffffffff, s3->accel.pix_trans[0] | (s3->accel.pix_trans[1] << 8) | (s3->accel.pix_trans[2] << 16) | (s3->accel.pix_trans[3] << 24), s3); - } - } - break; - case 0x400: - if (((s3->accel.multifunc[0xa] & 0xc0) == 0x80) || (s3->accel.cmd & 2)) { - if (((s3->accel.frgd_mix & 0x60) != 0x40) || ((s3->accel.bkgd_mix & 0x60) != 0x40)) - s3_accel_start(32, 1, s3->accel.pix_trans[0] | (s3->accel.pix_trans[1] << 8) | (s3->accel.pix_trans[2] << 16) | (s3->accel.pix_trans[3] << 24), 0, s3); - else - s3_accel_start(4, 1, 0xffffffff, s3->accel.pix_trans[0] | (s3->accel.pix_trans[1] << 8) | (s3->accel.pix_trans[2] << 16) | (s3->accel.pix_trans[3] << 24), s3); - } else - s3_accel_start(4, 1, 0xffffffff, s3->accel.pix_trans[0] | (s3->accel.pix_trans[1] << 8) | (s3->accel.pix_trans[2] << 16) | (s3->accel.pix_trans[3] << 24), s3); - break; - case 0x600: - if (s3->chip == S3_TRIO32 || s3->chip == S3_VISION968 || s3->chip == S3_VISION868 || s3->chip >= S3_TRIO64V) { - if (((s3->accel.multifunc[0xa] & 0xc0) == 0x80) || (s3->accel.cmd & 2)) { - if (((s3->accel.frgd_mix & 0x60) != 0x40) || ((s3->accel.bkgd_mix & 0x60) != 0x40)) { - s3_accel_start(8, 1, s3->accel.pix_trans[3], 0, s3); - s3_accel_start(8, 1, s3->accel.pix_trans[2], 0, s3); - s3_accel_start(8, 1, s3->accel.pix_trans[1], 0, s3); - s3_accel_start(8, 1, s3->accel.pix_trans[0], 0, s3); - } - } - } - break; - } - } - break; - } + case 0xb148: + case 0xb2e8: + if ((s3->bpp == 3) && (s3->accel.multifunc[0xe] & 0x10) && !(s3->accel.multifunc[0xe] & 0x200)) + s3->accel.color_cmp = (s3->accel.color_cmp & 0xff00ffff) | (val << 16); + else + s3->accel.color_cmp = (s3->accel.color_cmp & 0xffffff00) | val; + break; + case 0xb149: + case 0xb2e9: + if ((s3->bpp == 3) && (s3->accel.multifunc[0xe] & 0x10) && !(s3->accel.multifunc[0xe] & 0x200)) + s3->accel.color_cmp = (s3->accel.color_cmp & 0x00ffffff) | (val << 24); + else + s3->accel.color_cmp = (s3->accel.color_cmp & 0xffff00ff) | (val << 8); + if (!(s3->accel.multifunc[0xe] & 0x200)) + s3->accel.multifunc[0xe] ^= 0x10; + break; + case 0xb14a: + case 0xb2ea: + if ((s3->bpp == 3) && (s3->accel.multifunc[0xe] & 0x10) && !(s3->accel.multifunc[0xe] & 0x200)) + s3->accel.color_cmp = (s3->accel.color_cmp & 0xffffff00) | val; + else + s3->accel.color_cmp = (s3->accel.color_cmp & 0xff00ffff) | (val << 16); + break; + case 0xb14b: + case 0xb2eb: + if ((s3->bpp == 3) && (s3->accel.multifunc[0xe] & 0x10) && !(s3->accel.multifunc[0xe] & 0x200)) + s3->accel.color_cmp = (s3->accel.color_cmp & 0xffff00ff) | (val << 8); + else + s3->accel.color_cmp = (s3->accel.color_cmp & 0x00ffffff) | (val << 24); + if (!(s3->accel.multifunc[0xe] & 0x200)) + s3->accel.multifunc[0xe] ^= 0x10; + break; + + case 0xb548: + case 0xb6e8: + s3->accel.bkgd_mix = val; + break; + + case 0xb948: + case 0xbae8: + s3->accel.frgd_mix = val; + break; + + case 0xbd48: + case 0xbee8: + s3->accel.multifunc_cntl = (s3->accel.multifunc_cntl & 0xff00) | val; + break; + case 0xbd49: + case 0xbee9: + s3->accel.multifunc_cntl = (s3->accel.multifunc_cntl & 0xff) | (val << 8); + s3->accel.multifunc[s3->accel.multifunc_cntl >> 12] = s3->accel.multifunc_cntl & 0xfff; + break; + + case 0xd148: + case 0xd2e8: + s3->accel.ropmix = (s3->accel.ropmix & 0xff00) | val; + break; + case 0xd149: + case 0xd2e9: + s3->accel.ropmix = (s3->accel.ropmix & 0x00ff) | (val << 8); + break; + case 0xe548: + case 0xe6e8: + if ((s3->bpp == 3) && (s3->accel.multifunc[0xe] & 0x10) && !(s3->accel.multifunc[0xe] & 0x200)) + s3->accel.pat_bg_color = (s3->accel.pat_bg_color & 0xff00ffff) | (val << 16); + else + s3->accel.pat_bg_color = (s3->accel.pat_bg_color & 0xffffff00) | val; + break; + case 0xe549: + case 0xe6e9: + if ((s3->bpp == 3) && (s3->accel.multifunc[0xe] & 0x10) && !(s3->accel.multifunc[0xe] & 0x200)) + s3->accel.pat_bg_color = (s3->accel.pat_bg_color & 0x00ffffff) | (val << 24); + else + s3->accel.pat_bg_color = (s3->accel.pat_bg_color & 0xffff00ff) | (val << 8); + if (!(s3->accel.multifunc[0xe] & 0x200)) + s3->accel.multifunc[0xe] ^= 0x10; + break; + case 0xe54a: + case 0xe6ea: + if ((s3->bpp == 3) && (s3->accel.multifunc[0xe] & 0x10) && !(s3->accel.multifunc[0xe] & 0x200)) + s3->accel.pat_bg_color = (s3->accel.pat_bg_color & 0xffffff00) | val; + else + s3->accel.pat_bg_color = (s3->accel.pat_bg_color & 0xff00ffff) | (val << 16); + break; + case 0xe54b: + case 0xe6eb: + if ((s3->bpp == 3) && (s3->accel.multifunc[0xe] & 0x10) && !(s3->accel.multifunc[0xe] & 0x200)) + s3->accel.pat_bg_color = (s3->accel.pat_bg_color & 0xffff00ff) | (val << 8); + else + s3->accel.pat_bg_color = (s3->accel.pat_bg_color & 0x00ffffff) | (val << 24); + if (!(s3->accel.multifunc[0xe] & 0x200)) + s3->accel.multifunc[0xe] ^= 0x10; + break; + case 0xe948: + case 0xeae8: + s3->accel.pat_y = (s3->accel.pat_y & 0xf00) | val; + break; + case 0xe949: + case 0xeae9: + s3->accel.pat_y = (s3->accel.pat_y & 0xff) | ((val & 0x1f) << 8); + break; + case 0xe94a: + case 0xeaea: + s3->accel.pat_x = (s3->accel.pat_x & 0xf00) | val; + break; + case 0xe94b: + case 0xeaeb: + s3->accel.pat_x = (s3->accel.pat_x & 0xff) | ((val & 0x1f) << 8); + break; + case 0xed48: + case 0xeee8: + if ((s3->bpp == 3) && (s3->accel.multifunc[0xe] & 0x10) && !(s3->accel.multifunc[0xe] & 0x200)) + s3->accel.pat_fg_color = (s3->accel.pat_fg_color & 0xff00ffff) | (val << 16); + else + s3->accel.pat_fg_color = (s3->accel.pat_fg_color & 0xffffff00) | val; + break; + case 0xed49: + case 0xeee9: + if ((s3->bpp == 3) && (s3->accel.multifunc[0xe] & 0x10) && !(s3->accel.multifunc[0xe] & 0x200)) + s3->accel.pat_fg_color = (s3->accel.pat_fg_color & 0x00ffffff) | (val << 24); + else + s3->accel.pat_fg_color = (s3->accel.pat_fg_color & 0xffff00ff) | (val << 8); + if (!(s3->accel.multifunc[0xe] & 0x200)) + s3->accel.multifunc[0xe] ^= 0x10; + break; + case 0xed4a: + case 0xeeea: + if ((s3->bpp == 3) && (s3->accel.multifunc[0xe] & 0x10) && !(s3->accel.multifunc[0xe] & 0x200)) + s3->accel.pat_fg_color = (s3->accel.pat_fg_color & 0xffffff00) | val; + else + s3->accel.pat_fg_color = (s3->accel.pat_fg_color & 0xff00ffff) | (val << 16); + break; + case 0xed4b: + case 0xeeeb: + if ((s3->bpp == 3) && (s3->accel.multifunc[0xe] & 0x10) && !(s3->accel.multifunc[0xe] & 0x200)) + s3->accel.pat_fg_color = (s3->accel.pat_fg_color & 0xffff00ff) | (val << 8); + else + s3->accel.pat_fg_color = (s3->accel.pat_fg_color & 0x00ffffff) | (val << 24); + if (!(s3->accel.multifunc[0xe] & 0x200)) + s3->accel.multifunc[0xe] ^= 0x10; + break; + + case 0xe148: + case 0xe2e8: + s3->accel.b2e8_pix = 0; + if (s3_cpu_dest(s3)) + break; + s3->accel.pix_trans[0] = val; + if (s3->accel.cmd & 0x100) { + switch (s3->accel.cmd & 0x600) { + case 0x000: + if (((s3->accel.multifunc[0xa] & 0xc0) == 0x80) || (s3->accel.cmd & 2)) { + if (((s3->accel.frgd_mix & 0x60) != 0x40) || ((s3->accel.bkgd_mix & 0x60) != 0x40)) + s3_accel_start(8, 1, s3->accel.pix_trans[0], 0, s3); + else + s3_accel_start(1, 1, 0xffffffff, s3->accel.pix_trans[0], s3); + } else { + if (s3->color_16bit) + s3_accel_start(2, 1, 0xffffffff, s3->accel.pix_trans[0], s3); + else + s3_accel_start(1, 1, 0xffffffff, s3->accel.pix_trans[0], s3); + } + break; + + default: + break; + } + } + break; + case 0xe149: + case 0xe2e9: + s3->accel.b2e8_pix = 0; + if (s3_cpu_dest(s3)) + break; + s3->accel.pix_trans[1] = val; + if (s3->accel.cmd & 0x100) { + switch (s3->accel.cmd & 0x600) { + case 0x000: + if (((s3->accel.multifunc[0xa] & 0xc0) == 0x80) || (s3->accel.cmd & 2)) { + if (((s3->accel.frgd_mix & 0x60) != 0x40) || ((s3->accel.bkgd_mix & 0x60) != 0x40)) + s3_accel_start(8, 1, s3->accel.pix_trans[0] | (s3->accel.pix_trans[1] << 8), 0, s3); + else + s3_accel_start(1, 1, 0xffffffff, s3->accel.pix_trans[0] | (s3->accel.pix_trans[1] << 8), s3); + } else { + s3_accel_start(1, 1, 0xffffffff, s3->accel.pix_trans[0] | (s3->accel.pix_trans[1] << 8), s3); + } + break; + case 0x200: + /*Windows 95's built-in driver expects this to be loaded regardless of the byte swap bit (0xE2E9) in the 86c928 ISA/VLB*/ + if (((s3->accel.multifunc[0xa] & 0xc0) == 0x80) || (s3->accel.cmd & 2)) { + if (((s3->accel.frgd_mix & 0x60) != 0x40) || ((s3->accel.bkgd_mix & 0x60) != 0x40)) { + if (s3->accel.cmd & 0x1000) + s3_accel_start(16, 1, s3->accel.pix_trans[1] | (s3->accel.pix_trans[0] << 8), 0, s3); + else + s3_accel_start(16, 1, s3->accel.pix_trans[0] | (s3->accel.pix_trans[1] << 8), 0, s3); + } else { + if (s3->chip == S3_86C928 || s3->chip == S3_86C928PCI) { + s3_accel_out_pixtrans_w(s3, s3->accel.pix_trans[0] | (s3->accel.pix_trans[1] << 8)); + } else { + if (s3->accel.cmd & 0x1000) + s3_accel_start(2, 1, 0xffffffff, s3->accel.pix_trans[1] | (s3->accel.pix_trans[0] << 8), s3); + else + s3_accel_start(2, 1, 0xffffffff, s3->accel.pix_trans[0] | (s3->accel.pix_trans[1] << 8), s3); + } + } + } else { + if (s3->chip == S3_86C928 || s3->chip == S3_86C928PCI) { + s3_accel_out_pixtrans_w(s3, s3->accel.pix_trans[0] | (s3->accel.pix_trans[1] << 8)); + } else { + if (s3->accel.cmd & 0x1000) + s3_accel_start(2, 1, 0xffffffff, s3->accel.pix_trans[1] | (s3->accel.pix_trans[0] << 8), s3); + else + s3_accel_start(2, 1, 0xffffffff, s3->accel.pix_trans[0] | (s3->accel.pix_trans[1] << 8), s3); + } + } + break; + case 0x400: + if (svga->crtc[0x53] & 0x08) { + if (((s3->accel.multifunc[0xa] & 0xc0) == 0x80) || (s3->accel.cmd & 2)) { + if (((s3->accel.frgd_mix & 0x60) != 0x40) || ((s3->accel.bkgd_mix & 0x60) != 0x40)) + s3_accel_start(32, 1, s3->accel.pix_trans[0] | (s3->accel.pix_trans[1] << 8), 0, s3); + else + s3_accel_start(4, 1, 0xffffffff, s3->accel.pix_trans[0] | (s3->accel.pix_trans[1] << 8), s3); + } else + s3_accel_start(4, 1, 0xffffffff, s3->accel.pix_trans[0] | (s3->accel.pix_trans[1] << 8), s3); + } + break; + case 0x600: + if (s3->chip == S3_TRIO32 || s3->chip == S3_VISION968 || s3->chip == S3_VISION868 || s3->chip >= S3_TRIO64V) { + if (((s3->accel.multifunc[0xa] & 0xc0) == 0x80) || (s3->accel.cmd & 2)) { + if (((s3->accel.frgd_mix & 0x60) != 0x40) || ((s3->accel.bkgd_mix & 0x60) != 0x40)) { + s3_accel_start(8, 1, s3->accel.pix_trans[1], 0, s3); + s3_accel_start(8, 1, s3->accel.pix_trans[0], 0, s3); + } + } + } + break; + + default: + break; + } + + } + break; + case 0xe14a: + case 0xe2ea: + if (s3_cpu_dest(s3)) + break; + s3->accel.pix_trans[2] = val; + break; + case 0xe14b: + case 0xe2eb: + if (s3_cpu_dest(s3)) + break; + s3->accel.pix_trans[3] = val; + if (s3->accel.cmd & 0x100) { + switch (s3->accel.cmd & 0x600) { + case 0x000: + if (((s3->accel.multifunc[0xa] & 0xc0) == 0x80) || (s3->accel.cmd & 2)) { + if (((s3->accel.frgd_mix & 0x60) != 0x40) || ((s3->accel.bkgd_mix & 0x60) != 0x40)) + s3_accel_start(8, 1, s3->accel.pix_trans[0] | (s3->accel.pix_trans[1] << 8) | (s3->accel.pix_trans[2] << 16) | (s3->accel.pix_trans[3] << 24), 0, s3); + else + s3_accel_start(1, 1, 0xffffffff, s3->accel.pix_trans[0] | (s3->accel.pix_trans[1] << 8) | (s3->accel.pix_trans[2] << 16) | (s3->accel.pix_trans[3] << 24), s3); + } else + s3_accel_start(1, 1, 0xffffffff, s3->accel.pix_trans[0] | (s3->accel.pix_trans[1] << 8) | (s3->accel.pix_trans[2] << 16) | (s3->accel.pix_trans[3] << 24), s3); + break; + case 0x200: + /*Windows 95's built-in driver expects the upper 16 bits to be loaded instead of the whole 32-bit one, regardless of the byte swap bit (0xE2EB) in the 86c928 ISA/VLB card*/ + if (((s3->accel.multifunc[0xa] & 0xc0) == 0x80) || (s3->accel.cmd & 2)) { + if (((s3->accel.frgd_mix & 0x60) != 0x40) || ((s3->accel.bkgd_mix & 0x60) != 0x40)) { + if (s3->accel.cmd & 0x1000) + s3_accel_start(16, 1, s3->accel.pix_trans[3] | (s3->accel.pix_trans[2] << 8) | (s3->accel.pix_trans[1] << 16) | (s3->accel.pix_trans[0] << 24), 0, s3); + else + s3_accel_start(16, 1, s3->accel.pix_trans[0] | (s3->accel.pix_trans[1] << 8) | (s3->accel.pix_trans[2] << 16) | (s3->accel.pix_trans[3] << 24), 0, s3); + } else { + if (s3->chip == S3_86C928 || s3->chip == S3_86C928PCI) { + s3_accel_out_pixtrans_w(s3, s3->accel.pix_trans[2] | (s3->accel.pix_trans[3] << 8)); + } else { + if (s3->accel.cmd & 0x1000) + s3_accel_start(2, 1, 0xffffffff, s3->accel.pix_trans[3] | (s3->accel.pix_trans[2] << 8) | (s3->accel.pix_trans[1] << 16) | (s3->accel.pix_trans[0] << 24), s3); + else + s3_accel_start(2, 1, 0xffffffff, s3->accel.pix_trans[0] | (s3->accel.pix_trans[1] << 8) | (s3->accel.pix_trans[2] << 16) | (s3->accel.pix_trans[3] << 24), s3); + } + } + } else { + if (s3->chip == S3_86C928 || s3->chip == S3_86C928PCI) { + s3_accel_out_pixtrans_w(s3, s3->accel.pix_trans[2] | (s3->accel.pix_trans[3] << 8)); + } else { + if (s3->accel.cmd & 0x1000) + s3_accel_start(2, 1, 0xffffffff, s3->accel.pix_trans[3] | (s3->accel.pix_trans[2] << 8) | (s3->accel.pix_trans[1] << 16) | (s3->accel.pix_trans[0] << 24), s3); + else + s3_accel_start(2, 1, 0xffffffff, s3->accel.pix_trans[0] | (s3->accel.pix_trans[1] << 8) | (s3->accel.pix_trans[2] << 16) | (s3->accel.pix_trans[3] << 24), s3); + } + } + break; + case 0x400: + if (((s3->accel.multifunc[0xa] & 0xc0) == 0x80) || (s3->accel.cmd & 2)) { + if (((s3->accel.frgd_mix & 0x60) != 0x40) || ((s3->accel.bkgd_mix & 0x60) != 0x40)) + s3_accel_start(32, 1, s3->accel.pix_trans[0] | (s3->accel.pix_trans[1] << 8) | (s3->accel.pix_trans[2] << 16) | (s3->accel.pix_trans[3] << 24), 0, s3); + else + s3_accel_start(4, 1, 0xffffffff, s3->accel.pix_trans[0] | (s3->accel.pix_trans[1] << 8) | (s3->accel.pix_trans[2] << 16) | (s3->accel.pix_trans[3] << 24), s3); + } else + s3_accel_start(4, 1, 0xffffffff, s3->accel.pix_trans[0] | (s3->accel.pix_trans[1] << 8) | (s3->accel.pix_trans[2] << 16) | (s3->accel.pix_trans[3] << 24), s3); + break; + case 0x600: + if (s3->chip == S3_TRIO32 || s3->chip == S3_VISION968 || s3->chip == S3_VISION868 || s3->chip >= S3_TRIO64V) { + if (((s3->accel.multifunc[0xa] & 0xc0) == 0x80) || (s3->accel.cmd & 2)) { + if (((s3->accel.frgd_mix & 0x60) != 0x40) || ((s3->accel.bkgd_mix & 0x60) != 0x40)) { + s3_accel_start(8, 1, s3->accel.pix_trans[3], 0, s3); + s3_accel_start(8, 1, s3->accel.pix_trans[2], 0, s3); + s3_accel_start(8, 1, s3->accel.pix_trans[1], 0, s3); + s3_accel_start(8, 1, s3->accel.pix_trans[0], 0, s3); + } + } + } + break; + + default: + break; + } + } + break; + + default: + break; + } } static void s3_accel_out_fifo_w(s3_t *s3, uint16_t port, uint16_t val) { - if (port != 0x9ee8 && port != 0x9d48) { - if (port == 0xb2e8 || port == 0xb148) { - s3->accel.b2e8_pix = 1; - } else { - s3->accel.b2e8_pix = 0; - } - s3_accel_out_pixtrans_w(s3, val); - } else { - s3->accel.short_stroke = val; - s3->accel.ssv_state = 1; + if (port != 0x9ee8 && port != 0x9d48) { + if (port == 0xb2e8 || port == 0xb148) { + s3->accel.b2e8_pix = 1; + } else { + s3->accel.b2e8_pix = 0; + } + s3_accel_out_pixtrans_w(s3, val); + } else { + s3->accel.short_stroke = val; + s3->accel.ssv_state = 1; - s3->accel.cx = s3->accel.cur_x; - if (s3->accel.cur_x_bit12) s3->accel.cx |= ~0xfff; - s3->accel.cy = s3->accel.cur_y; - if (s3->accel.cur_y_bit12) s3->accel.cy |= ~0xfff; + s3->accel.cx = s3->accel.cur_x & 0xfff; + s3->accel.cy = s3->accel.cur_y & 0xfff; - if (s3->accel.cmd & 0x1000) { - s3_short_stroke_start(-1, 0, 0xffffffff, 0, s3, s3->accel.short_stroke & 0xff); - s3_short_stroke_start(-1, 0, 0xffffffff, 0, s3, s3->accel.short_stroke >> 8); - } else { - s3_short_stroke_start(-1, 0, 0xffffffff, 0, s3, s3->accel.short_stroke >> 8); - s3_short_stroke_start(-1, 0, 0xffffffff, 0, s3, s3->accel.short_stroke & 0xff); - } - } + if (s3->accel.cmd & 0x1000) { + s3_short_stroke_start(-1, 0, 0xffffffff, 0, s3, s3->accel.short_stroke & 0xff); + s3_short_stroke_start(-1, 0, 0xffffffff, 0, s3, s3->accel.short_stroke >> 8); + } else { + s3_short_stroke_start(-1, 0, 0xffffffff, 0, s3, s3->accel.short_stroke >> 8); + s3_short_stroke_start(-1, 0, 0xffffffff, 0, s3, s3->accel.short_stroke & 0xff); + } + } } - static void s3_accel_out_fifo_l(s3_t *s3, uint16_t port, uint32_t val) { - if (port == 0xb2e8 || port == 0xb148) { - s3->accel.b2e8_pix = 1; - } else { - s3->accel.b2e8_pix = 0; - } + if (port == 0xb2e8 || port == 0xb148) { + s3->accel.b2e8_pix = 1; + } else { + s3->accel.b2e8_pix = 0; + } - s3_accel_out_pixtrans_l(s3, val); + s3_accel_out_pixtrans_l(s3, val); } static void s3_accel_write_fifo(s3_t *s3, uint32_t addr, uint8_t val) { - svga_t *svga = &s3->svga; + const svga_t *svga = &s3->svga; if (s3->packed_mmio) { - int addr_lo = addr & 1; - if (svga->crtc[0x53] & 0x08) { - if ((addr >= 0x08000) && (addr <= 0x0803f)) - s3_pci_write(0, addr & 0xff, val, s3); - } - - switch (addr & 0x1fffe) { - case 0x8100: addr = 0x82e8; break; /*ALT_CURXY*/ - case 0x8102: addr = 0x86e8; break; - - case 0x8104: addr = 0x82ea; break; /*ALT_CURXY2*/ - case 0x8106: addr = 0x86ea; break; - - case 0x8108: addr = 0x8ae8; break; /*ALT_STEP*/ - case 0x810a: addr = 0x8ee8; break; - - case 0x810c: addr = 0x8aea; break; /*ALT_STEP2*/ - case 0x810e: addr = 0x8eea; break; + int addr_lo = addr & 1; + if (svga->crtc[0x53] & 0x08) { + if ((addr >= 0x08000) && (addr <= 0x0803f)) + s3_pci_write(0, addr & 0xff, val, s3); + } - case 0x8110: addr = 0x92e8; break; /*ALT_ERR*/ - case 0x8112: addr = 0x92ee; break; + switch (addr & 0x1fffe) { + case 0x8100: + addr = 0x82e8; + break; /*ALT_CURXY*/ + case 0x8102: + addr = 0x86e8; + break; - case 0x8118: addr = 0x9ae8; break; /*ALT_CMD*/ - case 0x811a: addr = 0x9aea; break; - - case 0x811c: addr = 0x9ee8; break; + case 0x8104: + addr = 0x82ea; + break; /*ALT_CURXY2*/ + case 0x8106: + addr = 0x86ea; + break; - case 0x8120: case 0x8122: /*BKGD_COLOR*/ - WRITE8(addr, s3->accel.bkgd_color, val); - return; - - case 0x8124: case 0x8126: /*FRGD_COLOR*/ - WRITE8(addr, s3->accel.frgd_color, val); - return; + case 0x8108: + addr = 0x8ae8; + break; /*ALT_STEP*/ + case 0x810a: + addr = 0x8ee8; + break; - case 0x8128: case 0x812a: /*WRT_MASK*/ - WRITE8(addr, s3->accel.wrt_mask, val); - return; + case 0x810c: + addr = 0x8aea; + break; /*ALT_STEP2*/ + case 0x810e: + addr = 0x8eea; + break; - case 0x812c: case 0x812e: /*RD_MASK*/ - WRITE8(addr, s3->accel.rd_mask, val); - return; + case 0x8110: + addr = 0x92e8; + break; /*ALT_ERR*/ + case 0x8112: + addr = 0x92ee; + break; - case 0x8130: case 0x8132: /*COLOR_CMP*/ - WRITE8(addr, s3->accel.color_cmp, val); - return; + case 0x8118: + addr = 0x9ae8; + break; /*ALT_CMD*/ + case 0x811a: + addr = 0x9aea; + break; - case 0x8134: addr = 0xb6e8; break; /*ALT_MIX*/ - case 0x8136: addr = 0xbae8; break; - - case 0x8138: /*SCISSORS_T*/ - WRITE8(addr & 1, s3->accel.multifunc[1], val); - return; - case 0x813a: /*SCISSORS_L*/ - WRITE8(addr & 1, s3->accel.multifunc[2], val); - return; - case 0x813c: /*SCISSORS_B*/ - WRITE8(addr & 1, s3->accel.multifunc[3], val); - return; - case 0x813e: /*SCISSORS_R*/ - WRITE8(addr & 1, s3->accel.multifunc[4], val); - return; + case 0x811c: + addr = 0x9ee8; + break; - case 0x8140: /*PIX_CNTL*/ - WRITE8(addr & 1, s3->accel.multifunc[0xa], val); - return; - case 0x8142: /*MULT_MISC2*/ - WRITE8(addr & 1, s3->accel.multifunc[0xd], val); - return; - case 0x8144: /*MULT_MISC*/ - WRITE8(addr & 1, s3->accel.multifunc[0xe], val); - return; - case 0x8146: /*READ_SEL*/ - WRITE8(addr & 1, s3->accel.multifunc[0xf], val); - return; + case 0x8120: + case 0x8122: /*BKGD_COLOR*/ + WRITE8(addr, s3->accel.bkgd_color, val); + return; - case 0x8148: /*ALT_PCNT*/ - WRITE8(addr & 1, s3->accel.multifunc[0], val); - return; - case 0x814a: addr = 0x96e8; break; - case 0x814c: addr = 0x96ea; break; + case 0x8124: + case 0x8126: /*FRGD_COLOR*/ + WRITE8(addr, s3->accel.frgd_color, val); + return; - case 0x8150: addr = 0xd2e8; break; + case 0x8128: + case 0x812a: /*WRT_MASK*/ + WRITE8(addr, s3->accel.wrt_mask, val); + return; - case 0x8154: addr = 0x8ee8; break; - case 0x8156: addr = 0x96e8; break; + case 0x812c: + case 0x812e: /*RD_MASK*/ + WRITE8(addr, s3->accel.rd_mask, val); + return; - case 0x8164: case 0x8166: - WRITE8(addr, s3->accel.pat_bg_color, val); - return; + case 0x8130: + case 0x8132: /*COLOR_CMP*/ + WRITE8(addr, s3->accel.color_cmp, val); + return; - case 0x8168: addr = 0xeae8; break; - case 0x816a: addr = 0xeaea; break; - - case 0x816c: case 0x816e: - WRITE8(addr, s3->accel.pat_fg_color, val); - return; - } - addr |= addr_lo; + case 0x8134: + addr = 0xb6e8; + break; /*ALT_MIX*/ + case 0x8136: + addr = 0xbae8; + break; + + case 0x8138: /*SCISSORS_T*/ + WRITE8(addr & 1, s3->accel.multifunc[1], val); + return; + case 0x813a: /*SCISSORS_L*/ + WRITE8(addr & 1, s3->accel.multifunc[2], val); + return; + case 0x813c: /*SCISSORS_B*/ + WRITE8(addr & 1, s3->accel.multifunc[3], val); + return; + case 0x813e: /*SCISSORS_R*/ + WRITE8(addr & 1, s3->accel.multifunc[4], val); + return; + + case 0x8140: /*PIX_CNTL*/ + WRITE8(addr & 1, s3->accel.multifunc[0xa], val); + return; + case 0x8142: /*MULT_MISC2*/ + WRITE8(addr & 1, s3->accel.multifunc[0xd], val); + return; + case 0x8144: /*MULT_MISC*/ + WRITE8(addr & 1, s3->accel.multifunc[0xe], val); + return; + case 0x8146: /*READ_SEL*/ + WRITE8(addr & 1, s3->accel.multifunc[0xf], val); + return; + + case 0x8148: /*ALT_PCNT*/ + WRITE8(addr & 1, s3->accel.multifunc[0], val); + return; + case 0x814a: + addr = 0x96e8; + break; + case 0x814c: + addr = 0x96ea; + break; + + case 0x8150: + addr = 0xd2e8; + break; + + case 0x8154: + addr = 0x8ee8; + break; + case 0x8156: + addr = 0x96e8; + break; + + case 0x8164: + case 0x8166: + WRITE8(addr, s3->accel.pat_bg_color, val); + return; + + case 0x8168: + addr = 0xeae8; + break; + case 0x816a: + addr = 0xeaea; + break; + + case 0x816c: + case 0x816e: + WRITE8(addr, s3->accel.pat_fg_color, val); + return; + + default: + break; + } + addr |= addr_lo; } if (svga->crtc[0x53] & 0x08) { - if ((addr & 0x1ffff) < 0x8000) { - if (s3->accel.cmd & 0x100) { - if (((s3->accel.multifunc[0xa] & 0xc0) == 0x80) || (s3->accel.cmd & 2)) { - if (((s3->accel.frgd_mix & 0x60) != 0x40) || ((s3->accel.bkgd_mix & 0x60) != 0x40)) - s3_accel_start(8, 1, val | (val << 8) | (val << 16) | (val << 24), 0, s3); - else - s3_accel_start(1, 1, 0xffffffff, val | (val << 8) | (val << 16) | (val << 24), s3); - } else - s3_accel_start(1, 1, 0xffffffff, val | (val << 8) | (val << 16) | (val << 24), s3); - } - } else { - switch (addr & 0x1ffff) { - case 0x83b0: case 0x83b1: case 0x83b2: case 0x83b3: - case 0x83b4: case 0x83b5: case 0x83b6: case 0x83b7: - case 0x83b8: case 0x83b9: case 0x83ba: case 0x83bb: - case 0x83bc: case 0x83bd: case 0x83be: case 0x83bf: - case 0x83c0: case 0x83c1: case 0x83c2: case 0x83c3: - case 0x83c4: case 0x83c5: case 0x83c6: case 0x83c7: - case 0x83c8: case 0x83c9: case 0x83ca: case 0x83cb: - case 0x83cc: case 0x83cd: case 0x83ce: case 0x83cf: - case 0x83d0: case 0x83d1: case 0x83d2: case 0x83d3: - case 0x83d4: case 0x83d5: case 0x83d6: case 0x83d7: - case 0x83d8: case 0x83d9: case 0x83da: case 0x83db: - case 0x83dc: case 0x83dd: case 0x83de: case 0x83df: - s3_out(addr & 0x3ff, val, s3); - break; - case 0x8504: - s3->subsys_stat &= ~val; - s3_update_irqs(s3); - break; - case 0x8505: - s3->subsys_cntl = val; - s3_update_irqs(s3); - break; - case 0x850c: - s3->accel.advfunc_cntl = val; - s3_updatemapping(s3); - break; - case 0xff20: - s3->serialport = val; - i2c_gpio_set(s3->i2c, !!(val & SERIAL_PORT_SCW), !!(val & SERIAL_PORT_SDW)); - break; - default: - s3_accel_out_fifo(s3, addr & 0xffff, val); - break; - } - } + if ((addr & 0x1ffff) < 0x8000) { + if (s3->accel.cmd & 0x100) { + if (((s3->accel.multifunc[0xa] & 0xc0) == 0x80) || (s3->accel.cmd & 2)) { + if (((s3->accel.frgd_mix & 0x60) != 0x40) || ((s3->accel.bkgd_mix & 0x60) != 0x40)) + s3_accel_start(8, 1, val | (val << 8) | (val << 16) | (val << 24), 0, s3); + else + s3_accel_start(1, 1, 0xffffffff, val | (val << 8) | (val << 16) | (val << 24), s3); + } else + s3_accel_start(1, 1, 0xffffffff, val | (val << 8) | (val << 16) | (val << 24), s3); + } + } else { + switch (addr & 0x1ffff) { + case 0x83b0: + case 0x83b1: + case 0x83b2: + case 0x83b3: + case 0x83b4: + case 0x83b5: + case 0x83b6: + case 0x83b7: + case 0x83b8: + case 0x83b9: + case 0x83ba: + case 0x83bb: + case 0x83bc: + case 0x83bd: + case 0x83be: + case 0x83bf: + case 0x83c0: + case 0x83c1: + case 0x83c2: + case 0x83c3: + case 0x83c4: + case 0x83c5: + case 0x83c6: + case 0x83c7: + case 0x83c8: + case 0x83c9: + case 0x83ca: + case 0x83cb: + case 0x83cc: + case 0x83cd: + case 0x83ce: + case 0x83cf: + case 0x83d0: + case 0x83d1: + case 0x83d2: + case 0x83d3: + case 0x83d4: + case 0x83d5: + case 0x83d6: + case 0x83d7: + case 0x83d8: + case 0x83d9: + case 0x83da: + case 0x83db: + case 0x83dc: + case 0x83dd: + case 0x83de: + case 0x83df: + s3_out(addr & 0x3ff, val, s3); + break; + case 0x8504: + s3->subsys_stat &= ~val; + s3_update_irqs(s3); + break; + case 0x8505: + s3->subsys_cntl = val; + s3_update_irqs(s3); + break; + case 0x850c: + s3->accel.advfunc_cntl = val; + s3_updatemapping(s3); + break; + case 0xff20: + s3->serialport = val; + i2c_gpio_set(s3->i2c, !!(val & SERIAL_PORT_SCW), !!(val & SERIAL_PORT_SDW)); + break; + default: + s3_accel_out_fifo(s3, addr & 0xffff, val); + break; + } + } } else { - if (addr & 0x8000) { - s3_accel_out_fifo(s3, addr & 0xffff, val); - } else { - if (s3->accel.cmd & 0x100) { - if ((s3->accel.cmd & 0x600) == 0x200) { - if (((s3->accel.multifunc[0xa] & 0xc0) == 0x80) || (s3->accel.cmd & 2)) { - if (((s3->accel.frgd_mix & 0x60) != 0x40) || ((s3->accel.bkgd_mix & 0x60) != 0x40)) - s3_accel_start(16, 1, val | (val << 8) | (val << 16) | (val << 24), 0, s3); - else - s3_accel_start(2, 1, 0xffffffff, val | (val << 8) | (val << 16) | (val << 24), s3); - } else - s3_accel_start(2, 1, 0xffffffff, val | (val << 8) | (val << 16) | (val << 24), s3); - } else { - if (((s3->accel.multifunc[0xa] & 0xc0) == 0x80) || (s3->accel.cmd & 2)) { - if (((s3->accel.frgd_mix & 0x60) != 0x40) || ((s3->accel.bkgd_mix & 0x60) != 0x40)) - s3_accel_start(8, 1, val | (val << 8) | (val << 16) | (val << 24), 0, s3); - else - s3_accel_start(1, 1, 0xffffffff, val | (val << 8) | (val << 16) | (val << 24), s3); - } else - s3_accel_start(1, 1, 0xffffffff, val | (val << 8) | (val << 16) | (val << 24), s3); - } - } - } + if (addr & 0x8000) { + if ((addr == 0xe2e8) || (addr == 0xe2e9)) { + if ((s3->chip == S3_86C801) || (s3->chip == S3_86C805)) + goto mmio_byte_write; + else + s3_accel_out_fifo(s3, addr & 0xffff, val); + } else + s3_accel_out_fifo(s3, addr & 0xffff, val); + } else { +mmio_byte_write: + if (s3->accel.cmd & 0x100) { + if ((s3->accel.cmd & 0x600) == 0x200) { + if (((s3->accel.multifunc[0xa] & 0xc0) == 0x80) || (s3->accel.cmd & 2)) { + if (((s3->accel.frgd_mix & 0x60) != 0x40) || ((s3->accel.bkgd_mix & 0x60) != 0x40)) + s3_accel_start(16, 1, val | (val << 8) | (val << 16) | (val << 24), 0, s3); + else + s3_accel_start(2, 1, 0xffffffff, val | (val << 8) | (val << 16) | (val << 24), s3); + } else + s3_accel_start(2, 1, 0xffffffff, val | (val << 8) | (val << 16) | (val << 24), s3); + } else { + if (((s3->accel.multifunc[0xa] & 0xc0) == 0x80) || (s3->accel.cmd & 2)) { + if (((s3->accel.frgd_mix & 0x60) != 0x40) || ((s3->accel.bkgd_mix & 0x60) != 0x40)) + s3_accel_start(8, 1, val | (val << 8) | (val << 16) | (val << 24), 0, s3); + else + s3_accel_start(1, 1, 0xffffffff, val | (val << 8) | (val << 16) | (val << 24), s3); + } else + s3_accel_start(1, 1, 0xffffffff, val | (val << 8) | (val << 16) | (val << 24), s3); + } + } + } } } static void s3_accel_write_fifo_w(s3_t *s3, uint32_t addr, uint16_t val) -{ - svga_t *svga = &s3->svga; +{ + const svga_t *svga = &s3->svga; - if (svga->crtc[0x53] & 0x08) { - if ((addr & 0x1fffe) < 0x8000) { - s3_accel_out_pixtrans_w(s3, val); - } else { - switch (addr & 0x1fffe) { - case 0x83d4: - default: - s3_accel_write_fifo(s3, addr, val); - s3_accel_write_fifo(s3, addr + 1, val >> 8); - break; - case 0xff20: - s3_accel_write_fifo(s3, addr, val); - break; - case 0x811c: - s3_accel_out_fifo_w(s3, 0x9ee8, val); - break; - } - } - } else { - if (addr & 0x8000) { - if (addr == 0x811c) - s3_accel_out_fifo_w(s3, 0x9ee8, val); - else { - if (addr == 0xe2e8 || addr == 0xe2ea) { - if (s3->chip == S3_86C928 || s3->chip == S3_86C928PCI) - s3_accel_out_pixtrans_w(s3, val); - else { - s3_accel_write_fifo(s3, addr, val); - s3_accel_write_fifo(s3, addr + 1, val >> 8); - } - } else { - s3_accel_write_fifo(s3, addr, val); - s3_accel_write_fifo(s3, addr + 1, val >> 8); - } - } - } else { - s3_accel_out_pixtrans_w(s3, val); - } - } + if (svga->crtc[0x53] & 0x08) { + if ((addr & 0x1fffe) < 0x8000) { + s3_accel_out_pixtrans_w(s3, val); + } else { + switch (addr & 0x1fffe) { + default: + case 0x83d4: + s3_accel_write_fifo(s3, addr, val); + s3_accel_write_fifo(s3, addr + 1, val >> 8); + break; + case 0xff20: + s3_accel_write_fifo(s3, addr, val); + break; + case 0x811c: + s3_accel_out_fifo_w(s3, 0x9ee8, val); + break; + } + } + } else { + if (addr & 0x8000) { + if (addr == 0x811c) + s3_accel_out_fifo_w(s3, 0x9ee8, val); + else { + if ((addr == 0xe2e8) || (addr == 0xe2ea)) { + if ((s3->chip == S3_86C801) || (s3->chip == S3_86C805) || (s3->chip == S3_86C928) || (s3->chip == S3_86C928PCI)) + s3_accel_out_pixtrans_w(s3, val); + else { + s3_accel_write_fifo(s3, addr, val); + s3_accel_write_fifo(s3, addr + 1, val >> 8); + } + } else { + s3_accel_write_fifo(s3, addr, val); + s3_accel_write_fifo(s3, addr + 1, val >> 8); + } + } + } else { + s3_accel_out_pixtrans_w(s3, val); + } + } } - static void s3_accel_write_fifo_l(s3_t *s3, uint32_t addr, uint32_t val) { svga_t *svga = &s3->svga; if (svga->crtc[0x53] & 0x08) { - if ((addr & 0x1fffc) < 0x8000 || ((addr & 0x1fffc) >= 0x10000 && (addr & 0x1fffc) < 0x18000)) { - if ((addr & 0x1fffc) >= 0x10000 && (addr & 0x1fffc) < 0x18000) { - s3_visionx68_video_engine_op(val, s3); - } else if ((addr & 0x1fffc) < 0x8000) { - s3_accel_out_pixtrans_l(s3, val); - } - } else { - switch (addr & 0x1fffc) { - case 0x8180: - s3->streams.pri_ctrl = val; - svga_recalctimings(svga); - svga->fullchange = changeframecount; - break; - case 0x8184: - s3->streams.chroma_ctrl = val; - break; - case 0x8190: - s3->streams.sec_ctrl = val; - s3->streams.dda_horiz_accumulator = val & 0xfff; - if (val & (1 << 11)) - s3->streams.dda_horiz_accumulator |= 0xfffff800; - s3->streams.sdif = (val >> 24) & 7; - break; - case 0x8194: - s3->streams.chroma_upper_bound = val; - break; - case 0x8198: - s3->streams.sec_filter = val; - s3->streams.k1_horiz_scale = val & 0x7ff; - if (val & (1 << 10)) - s3->streams.k1_horiz_scale |= 0xfffff800; - s3->streams.k2_horiz_scale = (val >> 16) & 0x7ff; - if ((val >> 16) & (1 << 10)) - s3->streams.k2_horiz_scale |= 0xfffff800; - break; - case 0x81a0: - s3->streams.blend_ctrl = val; - break; - case 0x81c0: - s3->streams.pri_fb0 = val & 0x3fffff; - svga_recalctimings(svga); - svga->fullchange = changeframecount; - break; - case 0x81c4: - s3->streams.pri_fb1 = val & 0x3fffff; - svga_recalctimings(svga); - svga->fullchange = changeframecount; - break; - case 0x81c8: - s3->streams.pri_stride = val & 0xfff; - svga_recalctimings(svga); - svga->fullchange = changeframecount; - break; - case 0x81cc: - s3->streams.buffer_ctrl = val; - svga_recalctimings(svga); - svga->fullchange = changeframecount; - break; - case 0x81d0: - s3->streams.sec_fb0 = val; - svga_recalctimings(svga); - svga->fullchange = changeframecount; - break; - case 0x81d4: - s3->streams.sec_fb1 = val; - svga_recalctimings(svga); - svga->fullchange = changeframecount; - break; - case 0x81d8: - s3->streams.sec_stride = val; - svga_recalctimings(svga); - svga->fullchange = changeframecount; - break; - case 0x81dc: - s3->streams.overlay_ctrl = val; - break; - case 0x81e0: - s3->streams.k1_vert_scale = val & 0x7ff; - if (val & (1 << 10)) - s3->streams.k1_vert_scale |= 0xfffff800; - break; - case 0x81e4: - s3->streams.k2_vert_scale = val & 0x7ff; - if (val & (1 << 10)) - s3->streams.k2_vert_scale |= 0xfffff800; - break; - case 0x81e8: - s3->streams.dda_vert_accumulator = val & 0xfff; - if (val & (1 << 11)) - s3->streams.dda_vert_accumulator |= 0xfffff800; - break; - case 0x81ec: - s3->streams.fifo_ctrl = val; - break; - case 0x81f0: - s3->streams.pri_start = val; - s3->streams.pri_x = (val >> 16) & 0x7ff; - s3->streams.pri_y = val & 0x7ff; - svga_recalctimings(svga); - svga->fullchange = changeframecount; - break; - case 0x81f4: - s3->streams.pri_size = val; - s3->streams.pri_w = (val >> 16) & 0x7ff; - s3->streams.pri_h = val & 0x7ff; - svga_recalctimings(svga); - svga->fullchange = changeframecount; - break; - case 0x81f8: - s3->streams.sec_start = val; - s3->streams.sec_x = (val >> 16) & 0x7ff; - s3->streams.sec_y = val & 0x7ff; - svga_recalctimings(svga); - svga->fullchange = changeframecount; - break; - case 0x81fc: - s3->streams.sec_size = val; - s3->streams.sec_w = (val >> 16) & 0x7ff; - s3->streams.sec_h = val & 0x7ff; - svga_recalctimings(svga); - svga->fullchange = changeframecount; - break; + if ((addr & 0x1fffc) < 0x8000 || ((addr & 0x1fffc) >= 0x10000 && (addr & 0x1fffc) < 0x18000)) { + if ((addr & 0x1fffc) >= 0x10000 && (addr & 0x1fffc) < 0x18000) { + s3_visionx68_video_engine_op(val, s3); + } else if ((addr & 0x1fffc) < 0x8000) { + s3_accel_out_pixtrans_l(s3, val); + } + } else { + switch (addr & 0x1fffc) { + case 0x8180: + s3->streams.pri_ctrl = val; + svga_recalctimings(svga); + svga->fullchange = svga->monitor->mon_changeframecount; + break; + case 0x8184: + s3->streams.chroma_ctrl = val; + break; + case 0x8190: + s3->streams.sec_ctrl = val; + s3->streams.dda_horiz_accumulator = val & 0xfff; + if (val & (1 << 11)) + s3->streams.dda_horiz_accumulator |= 0xfffff800; + s3->streams.sdif = (val >> 24) & 7; + break; + case 0x8194: + s3->streams.chroma_upper_bound = val; + break; + case 0x8198: + s3->streams.sec_filter = val; + s3->streams.k1_horiz_scale = val & 0x7ff; + if (val & (1 << 10)) + s3->streams.k1_horiz_scale |= 0xfffff800; + s3->streams.k2_horiz_scale = (val >> 16) & 0x7ff; + if ((val >> 16) & (1 << 10)) + s3->streams.k2_horiz_scale |= 0xfffff800; + break; + case 0x81a0: + s3->streams.blend_ctrl = val; + break; + case 0x81c0: + s3->streams.pri_fb0 = val & 0x3fffff; + svga_recalctimings(svga); + svga->fullchange = svga->monitor->mon_changeframecount; + break; + case 0x81c4: + s3->streams.pri_fb1 = val & 0x3fffff; + svga_recalctimings(svga); + svga->fullchange = svga->monitor->mon_changeframecount; + break; + case 0x81c8: + s3->streams.pri_stride = val & 0xfff; + svga_recalctimings(svga); + svga->fullchange = svga->monitor->mon_changeframecount; + break; + case 0x81cc: + s3->streams.buffer_ctrl = val; + svga_recalctimings(svga); + svga->fullchange = svga->monitor->mon_changeframecount; + break; + case 0x81d0: + s3->streams.sec_fb0 = val; + svga_recalctimings(svga); + svga->fullchange = svga->monitor->mon_changeframecount; + break; + case 0x81d4: + s3->streams.sec_fb1 = val; + svga_recalctimings(svga); + svga->fullchange = svga->monitor->mon_changeframecount; + break; + case 0x81d8: + s3->streams.sec_stride = val; + svga_recalctimings(svga); + svga->fullchange = svga->monitor->mon_changeframecount; + break; + case 0x81dc: + s3->streams.overlay_ctrl = val; + break; + case 0x81e0: + s3->streams.k1_vert_scale = val & 0x7ff; + if (val & (1 << 10)) + s3->streams.k1_vert_scale |= 0xfffff800; + break; + case 0x81e4: + s3->streams.k2_vert_scale = val & 0x7ff; + if (val & (1 << 10)) + s3->streams.k2_vert_scale |= 0xfffff800; + break; + case 0x81e8: + s3->streams.dda_vert_accumulator = val & 0xfff; + if (val & (1 << 11)) + s3->streams.dda_vert_accumulator |= 0xfffff800; + break; + case 0x81ec: + s3->streams.fifo_ctrl = val; + break; + case 0x81f0: + s3->streams.pri_start = val; + s3->streams.pri_x = (val >> 16) & 0x7ff; + s3->streams.pri_y = val & 0x7ff; + svga_recalctimings(svga); + svga->fullchange = svga->monitor->mon_changeframecount; + break; + case 0x81f4: + s3->streams.pri_size = val; + s3->streams.pri_w = (val >> 16) & 0x7ff; + s3->streams.pri_h = val & 0x7ff; + svga_recalctimings(svga); + svga->fullchange = svga->monitor->mon_changeframecount; + break; + case 0x81f8: + s3->streams.sec_start = val; + s3->streams.sec_x = (val >> 16) & 0x7ff; + s3->streams.sec_y = val & 0x7ff; + svga_recalctimings(svga); + svga->fullchange = svga->monitor->mon_changeframecount; + break; + case 0x81fc: + s3->streams.sec_size = val; + s3->streams.sec_w = (val >> 16) & 0x7ff; + s3->streams.sec_h = val & 0x7ff; + svga_recalctimings(svga); + svga->fullchange = svga->monitor->mon_changeframecount; + break; - case 0x8504: - s3->subsys_stat &= ~(val & 0xff); - s3->subsys_cntl = (val >> 8); - s3_update_irqs(s3); - break; - - case 0x850c: - s3->accel.advfunc_cntl = val & 0xff; - s3_updatemapping(s3); - break; + case 0x8504: + s3->subsys_stat &= ~(val & 0xff); + s3->subsys_cntl = (val >> 8); + s3_update_irqs(s3); + break; - case 0xff20: - s3_accel_write_fifo(s3, addr, val); - break; + case 0x850c: + s3->accel.advfunc_cntl = val & 0xff; + s3_updatemapping(s3); + break; - case 0x18080: - s3->videoengine.nop = 1; - break; + case 0xff20: + s3_accel_write_fifo(s3, addr, val); + break; - case 0x18088: - s3->videoengine.cntl = val; - s3->videoengine.dda_init_accumulator = val & 0xfff; - s3->videoengine.odf = (val >> 16) & 7; - s3->videoengine.yuv = !!(val & (1 << 19)); - s3->videoengine.idf = (val >> 20) & 7; - s3->videoengine.dither = !!(val & (1 << 29)); - s3->videoengine.dm_index = (val >> 23) & 7; - break; + case 0x18080: + s3->videoengine.nop = 1; + break; - case 0x1808c: - s3->videoengine.stretch_filt_const = val; - s3->videoengine.k2 = val & 0x7ff; - s3->videoengine.k1 = (val >> 16) & 0x7ff; - s3->videoengine.host_data = !!(val & (1 << 30)); - s3->videoengine.scale_down = !!(val & (1 << 31)); - break; - - case 0x18090: - s3->videoengine.src_dst_step = val; - s3->videoengine.dst_step = val & 0x1fff; - s3->videoengine.src_step = (val >> 16) & 0x1fff; - break; - - case 0x18094: - s3->videoengine.crop = val; - s3->videoengine.len = val & 0xfff; - s3->videoengine.start = (val >> 16) & 0xfff; - s3->videoengine.input = 1; - break; - - case 0x18098: - s3->videoengine.src_base = val & 0xffffff; - break; - - case 0x1809c: - s3->videoengine.dest_base = val & 0xffffff; - break; - - default: - s3_accel_write_fifo(s3, addr, val); - s3_accel_write_fifo(s3, addr + 1, val >> 8); - s3_accel_write_fifo(s3, addr + 2, val >> 16); - s3_accel_write_fifo(s3, addr + 3, val >> 24); - break; - } - } + case 0x18088: + s3->videoengine.cntl = val; + s3->videoengine.dda_init_accumulator = val & 0xfff; + s3->videoengine.odf = (val >> 16) & 7; + s3->videoengine.yuv = !!(val & (1 << 19)); + s3->videoengine.idf = (val >> 20) & 7; + s3->videoengine.dither = !!(val & (1 << 29)); + s3->videoengine.dm_index = (val >> 23) & 7; + break; + + case 0x1808c: + s3->videoengine.stretch_filt_const = val; + s3->videoengine.k2 = val & 0x7ff; + s3->videoengine.k1 = (val >> 16) & 0x7ff; + s3->videoengine.host_data = !!(val & (1 << 30)); + s3->videoengine.scale_down = !!(val & (1 << 31)); + break; + + case 0x18090: + s3->videoengine.src_dst_step = val; + s3->videoengine.dst_step = val & 0x1fff; + s3->videoengine.src_step = (val >> 16) & 0x1fff; + break; + + case 0x18094: + s3->videoengine.crop = val; + s3->videoengine.len = val & 0xfff; + s3->videoengine.start = (val >> 16) & 0xfff; + s3->videoengine.input = 1; + break; + + case 0x18098: + s3->videoengine.src_base = val & 0xffffff; + break; + + case 0x1809c: + s3->videoengine.dest_base = val & 0xffffff; + break; + + default: + s3_accel_write_fifo(s3, addr, val); + s3_accel_write_fifo(s3, addr + 1, val >> 8); + s3_accel_write_fifo(s3, addr + 2, val >> 16); + s3_accel_write_fifo(s3, addr + 3, val >> 24); + break; + } + } } else { - if (addr & 0x8000) { - if (addr == 0xe2e8) { - if (s3->chip == S3_86C928 || s3->chip == S3_86C928PCI) - s3_accel_out_pixtrans_l(s3, val); - else { - s3_accel_write_fifo(s3, addr, val); - s3_accel_write_fifo(s3, addr + 1, val >> 8); - s3_accel_write_fifo(s3, addr + 2, val >> 16); - s3_accel_write_fifo(s3, addr + 3, val >> 24); - } - } else { - s3_accel_write_fifo(s3, addr, val); - s3_accel_write_fifo(s3, addr + 1, val >> 8); - s3_accel_write_fifo(s3, addr + 2, val >> 16); - s3_accel_write_fifo(s3, addr + 3, val >> 24); - } - } else { - s3_accel_out_pixtrans_l(s3, val); - } + if (addr & 0x8000) { + if (addr == 0xe2e8) { + if (s3->chip == S3_86C928 || s3->chip == S3_86C928PCI) + s3_accel_out_pixtrans_l(s3, val); + else { + s3_accel_write_fifo(s3, addr, val); + s3_accel_write_fifo(s3, addr + 1, val >> 8); + s3_accel_write_fifo(s3, addr + 2, val >> 16); + s3_accel_write_fifo(s3, addr + 3, val >> 24); + } + } else { + s3_accel_write_fifo(s3, addr, val); + s3_accel_write_fifo(s3, addr + 1, val >> 8); + s3_accel_write_fifo(s3, addr + 2, val >> 16); + s3_accel_write_fifo(s3, addr + 3, val >> 24); + } + } else { + s3_accel_out_pixtrans_l(s3, val); + } } } - static void s3_vblank_start(svga_t *svga) { - s3_t *s3 = (s3_t *)svga->p; + s3_t *s3 = (s3_t *) svga->priv; - s3->subsys_stat |= INT_VSY; - s3_update_irqs(s3); + s3->subsys_stat |= INT_VSY; + s3_update_irqs(s3); } - static uint32_t s3_hwcursor_convert_addr(svga_t *svga) { if ((svga->bpp == 8) && ((svga->gdcreg[5] & 0x60) >= 0x20) && (svga->crtc[0x45] & 0x10)) { - if ((svga->gdcreg[5] & 0x60) >= 0x40) - return ((svga->hwcursor_latch.addr & 0xfffff1ff) | ((svga->hwcursor_latch.addr & 0x200) << 2)) | 0x600; - else if ((svga->gdcreg[5] & 0x60) == 0x20) - return ((svga->hwcursor_latch.addr & 0xfffff0ff) | ((svga->hwcursor_latch.addr & 0x300) << 2)) | 0x300; - else - return svga->hwcursor_latch.addr; + if ((svga->gdcreg[5] & 0x60) >= 0x40) + return ((svga->hwcursor_latch.addr & 0xfffff1ff) | ((svga->hwcursor_latch.addr & 0x200) << 2)) | 0x600; + else if ((svga->gdcreg[5] & 0x60) == 0x20) + return ((svga->hwcursor_latch.addr & 0xfffff0ff) | ((svga->hwcursor_latch.addr & 0x300) << 2)) | 0x300; + else + return svga->hwcursor_latch.addr; } else - return svga->hwcursor_latch.addr; + return svga->hwcursor_latch.addr; } - - static void s3_hwcursor_draw(svga_t *svga, int displine) { - s3_t *s3 = (s3_t *)svga->p; - int x, shift = 1; - int width = 16; - uint16_t dat[2]; - int xx; - int offset = svga->hwcursor_latch.x - svga->hwcursor_latch.xoff; - uint32_t fg, bg; - uint32_t real_addr; - uint32_t remapped_addr; + const s3_t *s3 = (s3_t *) svga->priv; + int shift = 1; + int width = 16; + uint16_t dat[2]; + int xx; + int offset = svga->hwcursor_latch.x - svga->hwcursor_latch.xoff; + uint32_t fg; + uint32_t bg; + uint32_t real_addr; + uint32_t remapped_addr; - switch (svga->bpp) - { - case 15: - fg = video_15to32[s3->hwc_fg_col & 0xffff]; - bg = video_15to32[s3->hwc_bg_col & 0xffff]; - if (s3->chip >= S3_86C928 && s3->chip <= S3_86C805) { - if (s3->card_type != S3_MIROCRYSTAL10SD_805 && s3->card_type != S3_MIROCRYSTAL8S_805) { - if (!(svga->crtc[0x45] & 0x04)) { - shift = 2; - width = 8; - } - } - } - break; - - case 16: - fg = video_16to32[s3->hwc_fg_col & 0xffff]; - bg = video_16to32[s3->hwc_bg_col & 0xffff]; - if (s3->chip >= S3_86C928 && s3->chip <= S3_86C805) { - if (s3->card_type != S3_MIROCRYSTAL10SD_805 && s3->card_type != S3_MIROCRYSTAL8S_805) { - if (!(svga->crtc[0x45] & 0x04)) { - shift = 2; - width = 8; - } - } else if (s3->card_type == S3_MIROCRYSTAL10SD_805) { - if (!(svga->crtc[0x45] & 0x04)) { - offset <<= 1; - } - } - } - break; - - case 24: - fg = s3->hwc_fg_col; - bg = s3->hwc_bg_col; - break; - - case 32: - fg = s3->hwc_fg_col; - bg = s3->hwc_bg_col; - break; - - default: - if (s3->chip >= S3_TRIO32) - { - fg = svga->pallook[s3->hwc_fg_col & 0xff]; - bg = svga->pallook[s3->hwc_bg_col & 0xff]; - } - else - { - fg = svga->pallook[svga->crtc[0xe]]; - bg = svga->pallook[svga->crtc[0xf]]; - } - break; - } - - if (svga->interlace && svga->hwcursor_oddeven) - svga->hwcursor_latch.addr += 16; - - real_addr = s3_hwcursor_convert_addr(svga); - - for (x = 0; x < 64; x += 16) - { - remapped_addr = dword_remap(svga, real_addr); - - dat[0] = (svga->vram[remapped_addr & s3->vram_mask] << 8) | svga->vram[(remapped_addr + 1) & s3->vram_mask]; - dat[1] = (svga->vram[(remapped_addr + 2) & s3->vram_mask] << 8) | svga->vram[(remapped_addr + 3) & s3->vram_mask]; - - if (svga->crtc[0x55] & 0x10) { - /*X11*/ - for (xx = 0; xx < 16; xx++) { - if (offset >= 0) { - if (dat[0] & 0x8000) - buffer32->line[displine][offset + svga->x_add] = (dat[1] & 0x8000) ? fg : bg; - } - - offset++; - dat[0] <<= shift; - dat[1] <<= shift; - } - } else { - /*Windows*/ - for (xx = 0; xx < width; xx++) { - if (offset >= 0) { - if (!(dat[0] & 0x8000)) - buffer32->line[displine][offset + svga->x_add] = (dat[1] & 0x8000) ? fg : bg; - else if (dat[1] & 0x8000) - buffer32->line[displine][offset + svga->x_add] ^= 0xffffff; - } - - offset++; - dat[0] <<= shift; - dat[1] <<= shift; - } + switch (svga->bpp) { + case 15: + fg = video_15to32[s3->hwc_fg_col & 0xffff]; + bg = video_15to32[s3->hwc_bg_col & 0xffff]; + if (s3->chip >= S3_86C928 && s3->chip <= S3_86C805) { + if (s3->card_type != S3_MIROCRYSTAL10SD_805 && s3->card_type != S3_MIROCRYSTAL8S_805) { + if (!(svga->crtc[0x45] & 0x04)) { + shift = 2; + width = 8; + } } - svga->hwcursor_latch.addr += 4; - real_addr = s3_hwcursor_convert_addr(svga); - } - if (svga->interlace && !svga->hwcursor_oddeven) - svga->hwcursor_latch.addr += 16; + } + break; + + case 16: + fg = video_16to32[s3->hwc_fg_col & 0xffff]; + bg = video_16to32[s3->hwc_bg_col & 0xffff]; + if (s3->chip >= S3_86C928 && s3->chip <= S3_86C805) { + if (s3->card_type != S3_MIROCRYSTAL10SD_805 && s3->card_type != S3_MIROCRYSTAL8S_805) { + if (!(svga->crtc[0x45] & 0x04)) { + shift = 2; + width = 8; + } + } else if (s3->card_type == S3_MIROCRYSTAL10SD_805) { + if (!(svga->crtc[0x45] & 0x04)) { + offset <<= 1; + } + } + } + break; + + case 24: + fg = s3->hwc_fg_col; + bg = s3->hwc_bg_col; + break; + + case 32: + fg = s3->hwc_fg_col; + bg = s3->hwc_bg_col; + break; + + default: + if (s3->chip >= S3_TRIO32) { + fg = svga->pallook[s3->hwc_fg_col & 0xff]; + bg = svga->pallook[s3->hwc_bg_col & 0xff]; + } else { + fg = svga->pallook[svga->crtc[0xe]]; + bg = svga->pallook[svga->crtc[0xf]]; + } + break; + } + + if (svga->interlace && svga->hwcursor_oddeven) + svga->hwcursor_latch.addr += 16; + + real_addr = s3_hwcursor_convert_addr(svga); + + for (uint8_t x = 0; x < 64; x += 16) { + remapped_addr = dword_remap(svga, real_addr); + + dat[0] = (svga->vram[remapped_addr & s3->vram_mask] << 8) | svga->vram[(remapped_addr + 1) & s3->vram_mask]; + dat[1] = (svga->vram[(remapped_addr + 2) & s3->vram_mask] << 8) | svga->vram[(remapped_addr + 3) & s3->vram_mask]; + + if (svga->crtc[0x55] & 0x10) { + /*X11*/ + for (xx = 0; xx < 16; xx++) { + if (offset >= 0) { + if (dat[0] & 0x8000) + buffer32->line[displine][offset + svga->x_add] = (dat[1] & 0x8000) ? fg : bg; + } + + offset++; + dat[0] <<= shift; + dat[1] <<= shift; + } + } else { + /*Windows*/ + for (xx = 0; xx < width; xx++) { + if (offset >= 0) { + if (!(dat[0] & 0x8000)) + buffer32->line[displine][offset + svga->x_add] = (dat[1] & 0x8000) ? fg : bg; + else if (dat[1] & 0x8000) + buffer32->line[displine][offset + svga->x_add] ^= 0xffffff; + } + + offset++; + dat[0] <<= shift; + dat[1] <<= shift; + } + } + svga->hwcursor_latch.addr += 4; + real_addr = s3_hwcursor_convert_addr(svga); + } + if (svga->interlace && !svga->hwcursor_oddeven) + svga->hwcursor_latch.addr += 16; } -#define CLAMP(x) do \ - { \ - if ((x) & ~0xff) \ - x = ((x) < 0) ? 0 : 0xff; \ - } \ - while (0) +#define CLAMP(x) \ + do { \ + if ((x) & ~0xff) \ + x = ((x) < 0) ? 0 : 0xff; \ + } while (0) -#define DECODE_YCbCr() \ - do \ - { \ - int c; \ - \ - for (c = 0; c < 2; c++) \ - { \ - uint8_t y1, y2; \ - int8_t Cr, Cb; \ - int dR, dG, dB; \ - \ - y1 = src[0]; \ - Cr = src[1] - 0x80; \ - y2 = src[2]; \ - Cb = src[3] - 0x80; \ - src += 4; \ - \ - dR = (359*Cr) >> 8; \ - dG = (88*Cb + 183*Cr) >> 8; \ - dB = (453*Cb) >> 8; \ - \ - r[x_write] = y1 + dR; \ - CLAMP(r[x_write]); \ - g[x_write] = y1 - dG; \ - CLAMP(g[x_write]); \ - b[x_write] = y1 + dB; \ - CLAMP(b[x_write]); \ - \ - r[x_write+1] = y2 + dR; \ - CLAMP(r[x_write+1]); \ - g[x_write+1] = y2 - dG; \ - CLAMP(g[x_write+1]); \ - b[x_write+1] = y2 + dB; \ - CLAMP(b[x_write+1]); \ - \ - x_write = (x_write + 2) & 7; \ - } \ - } while (0) +#define DECODE_YCbCr() \ + do { \ + int c; \ + \ + for (c = 0; c < 2; c++) { \ + uint8_t y1, y2; \ + int8_t Cr, Cb; \ + int dR, dG, dB; \ + \ + y1 = src[0]; \ + Cr = src[1] - 0x80; \ + y2 = src[2]; \ + Cb = src[3] - 0x80; \ + src += 4; \ + \ + dR = (359 * Cr) >> 8; \ + dG = (88 * Cb + 183 * Cr) >> 8; \ + dB = (453 * Cb) >> 8; \ + \ + r[x_write] = y1 + dR; \ + CLAMP(r[x_write]); \ + g[x_write] = y1 - dG; \ + CLAMP(g[x_write]); \ + b[x_write] = y1 + dB; \ + CLAMP(b[x_write]); \ + \ + r[x_write + 1] = y2 + dR; \ + CLAMP(r[x_write + 1]); \ + g[x_write + 1] = y2 - dG; \ + CLAMP(g[x_write + 1]); \ + b[x_write + 1] = y2 + dB; \ + CLAMP(b[x_write + 1]); \ + \ + x_write = (x_write + 2) & 7; \ + } \ + } while (0) /*Both YUV formats are untested*/ -#define DECODE_YUV211() \ - do \ - { \ - uint8_t y1, y2, y3, y4; \ - int8_t U, V; \ - int dR, dG, dB; \ - \ - U = src[0] - 0x80; \ - y1 = (298 * (src[1] - 16)) >> 8; \ - y2 = (298 * (src[2] - 16)) >> 8; \ - V = src[3] - 0x80; \ - y3 = (298 * (src[4] - 16)) >> 8; \ - y4 = (298 * (src[5] - 16)) >> 8; \ - src += 6; \ - \ - dR = (309*V) >> 8; \ - dG = (100*U + 208*V) >> 8; \ - dB = (516*U) >> 8; \ - \ - r[x_write] = y1 + dR; \ - CLAMP(r[x_write]); \ - g[x_write] = y1 - dG; \ - CLAMP(g[x_write]); \ - b[x_write] = y1 + dB; \ - CLAMP(b[x_write]); \ - \ - r[x_write+1] = y2 + dR; \ - CLAMP(r[x_write+1]); \ - g[x_write+1] = y2 - dG; \ - CLAMP(g[x_write+1]); \ - b[x_write+1] = y2 + dB; \ - CLAMP(b[x_write+1]); \ - \ - r[x_write+2] = y3 + dR; \ - CLAMP(r[x_write+2]); \ - g[x_write+2] = y3 - dG; \ - CLAMP(g[x_write+2]); \ - b[x_write+2] = y3 + dB; \ - CLAMP(b[x_write+2]); \ - \ - r[x_write+3] = y4 + dR; \ - CLAMP(r[x_write+3]); \ - g[x_write+3] = y4 - dG; \ - CLAMP(g[x_write+3]); \ - b[x_write+3] = y4 + dB; \ - CLAMP(b[x_write+3]); \ - \ - x_write = (x_write + 4) & 7; \ - } while (0) +#define DECODE_YUV211() \ + do { \ + uint8_t y1, y2, y3, y4; \ + int8_t U, V; \ + int dR, dG, dB; \ + \ + U = src[0] - 0x80; \ + y1 = (298 * (src[1] - 16)) >> 8; \ + y2 = (298 * (src[2] - 16)) >> 8; \ + V = src[3] - 0x80; \ + y3 = (298 * (src[4] - 16)) >> 8; \ + y4 = (298 * (src[5] - 16)) >> 8; \ + src += 6; \ + \ + dR = (309 * V) >> 8; \ + dG = (100 * U + 208 * V) >> 8; \ + dB = (516 * U) >> 8; \ + \ + r[x_write] = y1 + dR; \ + CLAMP(r[x_write]); \ + g[x_write] = y1 - dG; \ + CLAMP(g[x_write]); \ + b[x_write] = y1 + dB; \ + CLAMP(b[x_write]); \ + \ + r[x_write + 1] = y2 + dR; \ + CLAMP(r[x_write + 1]); \ + g[x_write + 1] = y2 - dG; \ + CLAMP(g[x_write + 1]); \ + b[x_write + 1] = y2 + dB; \ + CLAMP(b[x_write + 1]); \ + \ + r[x_write + 2] = y3 + dR; \ + CLAMP(r[x_write + 2]); \ + g[x_write + 2] = y3 - dG; \ + CLAMP(g[x_write + 2]); \ + b[x_write + 2] = y3 + dB; \ + CLAMP(b[x_write + 2]); \ + \ + r[x_write + 3] = y4 + dR; \ + CLAMP(r[x_write + 3]); \ + g[x_write + 3] = y4 - dG; \ + CLAMP(g[x_write + 3]); \ + b[x_write + 3] = y4 + dB; \ + CLAMP(b[x_write + 3]); \ + \ + x_write = (x_write + 4) & 7; \ + } while (0) -#define DECODE_YUV422() \ - do \ - { \ - int c; \ - \ - for (c = 0; c < 2; c++) \ - { \ - uint8_t y1, y2; \ - int8_t U, V; \ - int dR, dG, dB; \ - \ - U = src[0] - 0x80; \ - y1 = (298 * (src[1] - 16)) >> 8; \ - V = src[2] - 0x80; \ - y2 = (298 * (src[3] - 16)) >> 8; \ - src += 4; \ - \ - dR = (309*V) >> 8; \ - dG = (100*U + 208*V) >> 8; \ - dB = (516*U) >> 8; \ - \ - r[x_write] = y1 + dR; \ - CLAMP(r[x_write]); \ - g[x_write] = y1 - dG; \ - CLAMP(g[x_write]); \ - b[x_write] = y1 + dB; \ - CLAMP(b[x_write]); \ - \ - r[x_write+1] = y2 + dR; \ - CLAMP(r[x_write+1]); \ - g[x_write+1] = y2 - dG; \ - CLAMP(g[x_write+1]); \ - b[x_write+1] = y2 + dB; \ - CLAMP(b[x_write+1]); \ - \ - x_write = (x_write + 2) & 7; \ - } \ - } while (0) +#define DECODE_YUV422() \ + do { \ + int c; \ + \ + for (c = 0; c < 2; c++) { \ + uint8_t y1, y2; \ + int8_t U, V; \ + int dR, dG, dB; \ + \ + U = src[0] - 0x80; \ + y1 = (298 * (src[1] - 16)) >> 8; \ + V = src[2] - 0x80; \ + y2 = (298 * (src[3] - 16)) >> 8; \ + src += 4; \ + \ + dR = (309 * V) >> 8; \ + dG = (100 * U + 208 * V) >> 8; \ + dB = (516 * U) >> 8; \ + \ + r[x_write] = y1 + dR; \ + CLAMP(r[x_write]); \ + g[x_write] = y1 - dG; \ + CLAMP(g[x_write]); \ + b[x_write] = y1 + dB; \ + CLAMP(b[x_write]); \ + \ + r[x_write + 1] = y2 + dR; \ + CLAMP(r[x_write + 1]); \ + g[x_write + 1] = y2 - dG; \ + CLAMP(g[x_write + 1]); \ + b[x_write + 1] = y2 + dB; \ + CLAMP(b[x_write + 1]); \ + \ + x_write = (x_write + 2) & 7; \ + } \ + } while (0) -#define DECODE_RGB555() \ - do \ - { \ - int c; \ - \ - for (c = 0; c < 4; c++) \ - { \ - uint16_t dat; \ - \ - dat = *(uint16_t *)src; \ - src += 2; \ - \ - r[x_write + c] = ((dat & 0x001f) << 3) | ((dat & 0x001f) >> 2); \ - g[x_write + c] = ((dat & 0x03e0) >> 2) | ((dat & 0x03e0) >> 7); \ - b[x_write + c] = ((dat & 0x7c00) >> 7) | ((dat & 0x7c00) >> 12); \ - } \ - x_write = (x_write + 4) & 7; \ - } while (0) +#define DECODE_RGB555() \ + do { \ + int c; \ + \ + for (c = 0; c < 4; c++) { \ + uint16_t dat; \ + \ + dat = *(uint16_t *) src; \ + src += 2; \ + \ + r[x_write + c] = ((dat & 0x001f) << 3) | ((dat & 0x001f) >> 2); \ + g[x_write + c] = ((dat & 0x03e0) >> 2) | ((dat & 0x03e0) >> 7); \ + b[x_write + c] = ((dat & 0x7c00) >> 7) | ((dat & 0x7c00) >> 12); \ + } \ + x_write = (x_write + 4) & 7; \ + } while (0) -#define DECODE_RGB565() \ - do \ - { \ - int c; \ - \ - for (c = 0; c < 4; c++) \ - { \ - uint16_t dat; \ - \ - dat = *(uint16_t *)src; \ - src += 2; \ - \ - r[x_write + c] = ((dat & 0x001f) << 3) | ((dat & 0x001f) >> 2); \ - g[x_write + c] = ((dat & 0x07e0) >> 3) | ((dat & 0x07e0) >> 9); \ - b[x_write + c] = ((dat & 0xf800) >> 8) | ((dat & 0xf800) >> 13); \ - } \ - x_write = (x_write + 4) & 7; \ - } while (0) +#define DECODE_RGB565() \ + do { \ + int c; \ + \ + for (c = 0; c < 4; c++) { \ + uint16_t dat; \ + \ + dat = *(uint16_t *) src; \ + src += 2; \ + \ + r[x_write + c] = ((dat & 0x001f) << 3) | ((dat & 0x001f) >> 2); \ + g[x_write + c] = ((dat & 0x07e0) >> 3) | ((dat & 0x07e0) >> 9); \ + b[x_write + c] = ((dat & 0xf800) >> 8) | ((dat & 0xf800) >> 13); \ + } \ + x_write = (x_write + 4) & 7; \ + } while (0) -#define DECODE_RGB888() \ - do \ - { \ - int c; \ - \ - for (c = 0; c < 4; c++) \ - { \ - r[x_write + c] = src[0]; \ - g[x_write + c] = src[1]; \ - b[x_write + c] = src[2]; \ - src += 3; \ - } \ - x_write = (x_write + 4) & 7; \ - } while (0) +#define DECODE_RGB888() \ + do { \ + int c; \ + \ + for (c = 0; c < 4; c++) { \ + r[x_write + c] = src[0]; \ + g[x_write + c] = src[1]; \ + b[x_write + c] = src[2]; \ + src += 3; \ + } \ + x_write = (x_write + 4) & 7; \ + } while (0) -#define DECODE_XRGB8888() \ - do \ - { \ - int c; \ - \ - for (c = 0; c < 4; c++) \ - { \ - r[x_write + c] = src[0]; \ - g[x_write + c] = src[1]; \ - b[x_write + c] = src[2]; \ - src += 4; \ - } \ - x_write = (x_write + 4) & 7; \ - } while (0) +#define DECODE_XRGB8888() \ + do { \ + int c; \ + \ + for (c = 0; c < 4; c++) { \ + r[x_write + c] = src[0]; \ + g[x_write + c] = src[1]; \ + b[x_write + c] = src[2]; \ + src += 4; \ + } \ + x_write = (x_write + 4) & 7; \ + } while (0) -#define OVERLAY_SAMPLE() \ - do \ - { \ - switch (s3->streams.sdif) \ - { \ - case 1: \ - DECODE_YCbCr(); \ - break; \ - case 2: \ - DECODE_YUV422(); \ - break; \ - case 3: \ - DECODE_RGB555(); \ - break; \ - case 4: \ - DECODE_YUV211(); \ - break; \ - case 5: \ - DECODE_RGB565(); \ - break; \ - case 6: \ - DECODE_RGB888(); \ - break; \ - case 7: \ - default: \ - DECODE_XRGB8888(); \ - break; \ - } \ - } while (0) +#define OVERLAY_SAMPLE() \ + do { \ + switch (s3->streams.sdif) { \ + case 1: \ + DECODE_YCbCr(); \ + break; \ + case 2: \ + DECODE_YUV422(); \ + break; \ + case 3: \ + DECODE_RGB555(); \ + break; \ + case 4: \ + DECODE_YUV211(); \ + break; \ + case 5: \ + DECODE_RGB565(); \ + break; \ + case 6: \ + DECODE_RGB888(); \ + break; \ + case 7: \ + default: \ + DECODE_XRGB8888(); \ + break; \ + } \ + } while (0) - -static void s3_trio64v_overlay_draw(svga_t *svga, int displine) +static void +s3_trio64v_overlay_draw(svga_t *svga, int displine) { - s3_t *s3 = (s3_t *)svga->p; - int offset = (s3->streams.sec_x - s3->streams.pri_x) + 1; - int h_acc = s3->streams.dda_horiz_accumulator; - int r[8], g[8], b[8]; - int x_size, x_read = 4, x_write = 4; - int x; - uint32_t *p; - uint8_t *src = &svga->vram[svga->overlay_latch.addr]; + const s3_t *s3 = (s3_t *) svga->priv; + int offset = (s3->streams.sec_x - s3->streams.pri_x) + 1; + int h_acc = s3->streams.dda_horiz_accumulator; + int r[8]; + int g[8]; + int b[8]; + int x_size; + int x_read = 4; + int x_write = 4; + uint32_t *p; + uint8_t *src = &svga->vram[svga->overlay_latch.addr]; - p = &(buffer32->line[displine][offset + svga->x_add]); + p = &(buffer32->line[displine][offset + svga->x_add]); - if ((offset + s3->streams.sec_w) > s3->streams.pri_w) - x_size = (s3->streams.pri_w - s3->streams.sec_x) + 1; - else - x_size = s3->streams.sec_w + 1; + if ((offset + s3->streams.sec_w) > s3->streams.pri_w) + x_size = (s3->streams.pri_w - s3->streams.sec_x) + 1; + else + x_size = s3->streams.sec_w + 1; - OVERLAY_SAMPLE(); - - for (x = 0; x < x_size; x++) - { - *p++ = r[x_read] | (g[x_read] << 8) | (b[x_read] << 16); + OVERLAY_SAMPLE(); - h_acc += s3->streams.k1_horiz_scale; - if (h_acc >= 0) - { - if ((x_read ^ (x_read + 1)) & ~3) - OVERLAY_SAMPLE(); - x_read = (x_read + 1) & 7; + for (int x = 0; x < x_size; x++) { + *p++ = r[x_read] | (g[x_read] << 8) | (b[x_read] << 16); - h_acc += (s3->streams.k2_horiz_scale - s3->streams.k1_horiz_scale); - } + h_acc += s3->streams.k1_horiz_scale; + if (h_acc >= 0) { + if ((x_read ^ (x_read + 1)) & ~3) + OVERLAY_SAMPLE(); + x_read = (x_read + 1) & 7; + + h_acc += (s3->streams.k2_horiz_scale - s3->streams.k1_horiz_scale); } + } - svga->overlay_latch.v_acc += s3->streams.k1_vert_scale; - if (svga->overlay_latch.v_acc >= 0) - { - svga->overlay_latch.v_acc += (s3->streams.k2_vert_scale - s3->streams.k1_vert_scale); - svga->overlay_latch.addr += s3->streams.sec_stride; - } + svga->overlay_latch.v_acc += s3->streams.k1_vert_scale; + if (svga->overlay_latch.v_acc >= 0) { + svga->overlay_latch.v_acc += (s3->streams.k2_vert_scale - s3->streams.k1_vert_scale); + svga->overlay_latch.addr += s3->streams.sec_stride; + } } static void s3_io_remove_alt(s3_t *s3) { - if (!s3->translate) - return; + if (!s3->translate) + return; - io_removehandler(0x4148, 0x0002, s3_accel_in, NULL, NULL, s3_accel_out, NULL, NULL, s3); - io_removehandler(0x4548, 0x0002, s3_accel_in, NULL, NULL, s3_accel_out, NULL, NULL, s3); - io_removehandler(0x4948, 0x0002, s3_accel_in, NULL, NULL, s3_accel_out, NULL, NULL, s3); - io_removehandler(0x8148, 0x0004, s3_accel_in, NULL, NULL, s3_accel_out, NULL, NULL, s3); - io_removehandler(0x8548, 0x0004, s3_accel_in, NULL, NULL, s3_accel_out, NULL, NULL, s3); - io_removehandler(0x8948, 0x0004, s3_accel_in, NULL, NULL, s3_accel_out, NULL, NULL, s3); - io_removehandler(0x8d48, 0x0004, s3_accel_in, NULL, NULL, s3_accel_out, NULL, NULL, s3); - io_removehandler(0x9148, 0x0004, s3_accel_in, NULL, NULL, s3_accel_out, NULL, NULL, s3); - io_removehandler(0x9548, 0x0004, s3_accel_in, NULL, NULL, s3_accel_out, NULL, NULL, s3); - io_removehandler(0x9948, 0x0004, s3_accel_in, NULL, NULL, s3_accel_out, NULL, NULL, s3); - io_removehandler(0x9d48, 0x0002, s3_accel_in, s3_accel_in_w, NULL, s3_accel_out, s3_accel_out_w, NULL, s3); - io_removehandler(0xa148, 0x0004, s3_accel_in, NULL, NULL, s3_accel_out, NULL, NULL, s3); - io_removehandler(0xa548, 0x0004, s3_accel_in, NULL, NULL, s3_accel_out, NULL, NULL, s3); - io_removehandler(0xa948, 0x0004, s3_accel_in, NULL, NULL, s3_accel_out, NULL, NULL, s3); - io_removehandler(0xad48, 0x0004, s3_accel_in, NULL, NULL, s3_accel_out, NULL, NULL, s3); - if (s3->chip >= S3_86C928) - io_removehandler(0xb148, 0x0004, s3_accel_in, NULL, NULL, s3_accel_out, NULL, NULL, s3); - else - io_removehandler(0xb148, 0x0002, s3_accel_in, s3_accel_in_w, NULL, s3_accel_out, s3_accel_out_w, s3_accel_out_l, s3); - io_removehandler(0xb548, 0x0002, s3_accel_in, NULL, NULL, s3_accel_out, NULL, NULL, s3); - io_removehandler(0xb948, 0x0002, s3_accel_in, NULL, NULL, s3_accel_out, NULL, NULL, s3); - io_removehandler(0xbd48, 0x0002, s3_accel_in, NULL, NULL, s3_accel_out, NULL, NULL, s3); - io_removehandler(0xd148, 0x0002, s3_accel_in, NULL, NULL, s3_accel_out, NULL, NULL, s3); - io_removehandler(0xe148, 0x0004, s3_accel_in, s3_accel_in_w, s3_accel_in_l, s3_accel_out, s3_accel_out_w, s3_accel_out_l, s3); - io_removehandler(0xe548, 0x0004, s3_accel_in, NULL, NULL, s3_accel_out, NULL, NULL, s3); - io_removehandler(0xe948, 0x0004, s3_accel_in, NULL, NULL, s3_accel_out, NULL, NULL, s3); - io_removehandler(0xed48, 0x0004, s3_accel_in, NULL, NULL, s3_accel_out, NULL, NULL, s3); + io_removehandler(0x4148, 0x0002, s3_accel_in, NULL, NULL, s3_accel_out, NULL, NULL, s3); + io_removehandler(0x4548, 0x0002, s3_accel_in, NULL, NULL, s3_accel_out, NULL, NULL, s3); + io_removehandler(0x4948, 0x0002, s3_accel_in, NULL, NULL, s3_accel_out, NULL, NULL, s3); + io_removehandler(0x8148, 0x0004, s3_accel_in, NULL, NULL, s3_accel_out, NULL, NULL, s3); + io_removehandler(0x8548, 0x0004, s3_accel_in, NULL, NULL, s3_accel_out, NULL, NULL, s3); + io_removehandler(0x8948, 0x0004, s3_accel_in, NULL, NULL, s3_accel_out, NULL, NULL, s3); + io_removehandler(0x8d48, 0x0004, s3_accel_in, NULL, NULL, s3_accel_out, NULL, NULL, s3); + io_removehandler(0x9148, 0x0004, s3_accel_in, NULL, NULL, s3_accel_out, NULL, NULL, s3); + io_removehandler(0x9548, 0x0004, s3_accel_in, NULL, NULL, s3_accel_out, NULL, NULL, s3); + io_removehandler(0x9948, 0x0004, s3_accel_in, NULL, NULL, s3_accel_out, NULL, NULL, s3); + io_removehandler(0x9d48, 0x0002, s3_accel_in, s3_accel_in_w, NULL, s3_accel_out, s3_accel_out_w, NULL, s3); + io_removehandler(0xa148, 0x0004, s3_accel_in, NULL, NULL, s3_accel_out, NULL, NULL, s3); + io_removehandler(0xa548, 0x0004, s3_accel_in, NULL, NULL, s3_accel_out, NULL, NULL, s3); + io_removehandler(0xa948, 0x0004, s3_accel_in, NULL, NULL, s3_accel_out, NULL, NULL, s3); + io_removehandler(0xad48, 0x0004, s3_accel_in, NULL, NULL, s3_accel_out, NULL, NULL, s3); + if (s3->chip >= S3_86C928) + io_removehandler(0xb148, 0x0004, s3_accel_in, NULL, NULL, s3_accel_out, NULL, NULL, s3); + else + io_removehandler(0xb148, 0x0002, s3_accel_in, s3_accel_in_w, NULL, s3_accel_out, s3_accel_out_w, s3_accel_out_l, s3); + io_removehandler(0xb548, 0x0002, s3_accel_in, NULL, NULL, s3_accel_out, NULL, NULL, s3); + io_removehandler(0xb948, 0x0002, s3_accel_in, NULL, NULL, s3_accel_out, NULL, NULL, s3); + io_removehandler(0xbd48, 0x0002, s3_accel_in, NULL, NULL, s3_accel_out, NULL, NULL, s3); + io_removehandler(0xd148, 0x0002, s3_accel_in, NULL, NULL, s3_accel_out, NULL, NULL, s3); + io_removehandler(0xe148, 0x0004, s3_accel_in, s3_accel_in_w, s3_accel_in_l, s3_accel_out, s3_accel_out_w, s3_accel_out_l, s3); + io_removehandler(0xe548, 0x0004, s3_accel_in, NULL, NULL, s3_accel_out, NULL, NULL, s3); + io_removehandler(0xe948, 0x0004, s3_accel_in, NULL, NULL, s3_accel_out, NULL, NULL, s3); + io_removehandler(0xed48, 0x0004, s3_accel_in, NULL, NULL, s3_accel_out, NULL, NULL, s3); } static void s3_io_remove(s3_t *s3) { - io_removehandler(0x03c0, 0x0020, s3_in, NULL, NULL, s3_out, NULL, NULL, s3); + io_removehandler(0x03c0, 0x0020, s3_in, NULL, NULL, s3_out, NULL, NULL, s3); - io_removehandler(0x42e8, 0x0002, s3_accel_in, NULL, NULL, s3_accel_out, NULL, NULL, s3); - io_removehandler(0x46e8, 0x0002, s3_accel_in, NULL, NULL, s3_accel_out, NULL, NULL, s3); - io_removehandler(0x4ae8, 0x0002, s3_accel_in, NULL, NULL, s3_accel_out, NULL, NULL, s3); - io_removehandler(0x82e8, 0x0004, s3_accel_in, NULL, NULL, s3_accel_out, NULL, NULL, s3); - io_removehandler(0x86e8, 0x0004, s3_accel_in, NULL, NULL, s3_accel_out, NULL, NULL, s3); - io_removehandler(0x8ae8, 0x0004, s3_accel_in, NULL, NULL, s3_accel_out, NULL, NULL, s3); - io_removehandler(0x8ee8, 0x0004, s3_accel_in, NULL, NULL, s3_accel_out, NULL, NULL, s3); - io_removehandler(0x92e8, 0x0004, s3_accel_in, NULL, NULL, s3_accel_out, NULL, NULL, s3); - io_removehandler(0x96e8, 0x0004, s3_accel_in, NULL, NULL, s3_accel_out, NULL, NULL, s3); - io_removehandler(0x9ae8, 0x0002, s3_accel_in, NULL, NULL, s3_accel_out, NULL, NULL, s3); - io_removehandler(0x9ee8, 0x0002, s3_accel_in, s3_accel_in_w, NULL, s3_accel_out, s3_accel_out_w, NULL, s3); - io_removehandler(0xa2e8, 0x0004, s3_accel_in, NULL, NULL, s3_accel_out, NULL, NULL, s3); - io_removehandler(0xa6e8, 0x0004, s3_accel_in, NULL, NULL, s3_accel_out, NULL, NULL, s3); - io_removehandler(0xaae8, 0x0004, s3_accel_in, NULL, NULL, s3_accel_out, NULL, NULL, s3); - io_removehandler(0xaee8, 0x0004, s3_accel_in, NULL, NULL, s3_accel_out, NULL, NULL, s3); - if (s3->chip >= S3_86C928) - io_removehandler(0xb2e8, 0x0004, s3_accel_in, NULL, NULL, s3_accel_out, NULL, NULL, s3); - else - io_removehandler(0xb2e8, 0x0002, s3_accel_in, s3_accel_in_w, NULL, s3_accel_out, s3_accel_out_w, s3_accel_out_l, s3); - io_removehandler(0xb6e8, 0x0002, s3_accel_in, NULL, NULL, s3_accel_out, NULL, NULL, s3); - io_removehandler(0xbae8, 0x0002, s3_accel_in, NULL, NULL, s3_accel_out, NULL, NULL, s3); - io_removehandler(0xbee8, 0x0002, s3_accel_in, NULL, NULL, s3_accel_out, NULL, NULL, s3); - io_removehandler(0xcae8, 0x0002, s3_accel_in, NULL, NULL, s3_accel_out, NULL, NULL, s3); - io_removehandler(0xd2e8, 0x0002, s3_accel_in, NULL, NULL, s3_accel_out, NULL, NULL, s3); - io_removehandler(0xe2e8, 0x0004, s3_accel_in, s3_accel_in_w, s3_accel_in_l, s3_accel_out, s3_accel_out_w, s3_accel_out_l, s3); - io_removehandler(0xe6e8, 0x0004, s3_accel_in, NULL, NULL, s3_accel_out, NULL, NULL, s3); - io_removehandler(0xeae8, 0x0004, s3_accel_in, NULL, NULL, s3_accel_out, NULL, NULL, s3); - io_removehandler(0xeee8, 0x0004, s3_accel_in, NULL, NULL, s3_accel_out, NULL, NULL, s3); - io_removehandler(0xfee8, 0x0002, s3_accel_in, NULL, NULL, s3_accel_out, NULL, NULL, s3); + io_removehandler(0x42e8, 0x0002, s3_accel_in, NULL, NULL, s3_accel_out, NULL, NULL, s3); + io_removehandler(0x46e8, 0x0002, s3_accel_in, NULL, NULL, s3_accel_out, NULL, NULL, s3); + io_removehandler(0x4ae8, 0x0002, s3_accel_in, NULL, NULL, s3_accel_out, NULL, NULL, s3); + io_removehandler(0x82e8, 0x0004, s3_accel_in, NULL, NULL, s3_accel_out, NULL, NULL, s3); + io_removehandler(0x86e8, 0x0004, s3_accel_in, NULL, NULL, s3_accel_out, NULL, NULL, s3); + io_removehandler(0x8ae8, 0x0004, s3_accel_in, NULL, NULL, s3_accel_out, NULL, NULL, s3); + io_removehandler(0x8ee8, 0x0004, s3_accel_in, NULL, NULL, s3_accel_out, NULL, NULL, s3); + io_removehandler(0x92e8, 0x0004, s3_accel_in, NULL, NULL, s3_accel_out, NULL, NULL, s3); + io_removehandler(0x96e8, 0x0004, s3_accel_in, NULL, NULL, s3_accel_out, NULL, NULL, s3); + io_removehandler(0x9ae8, 0x0002, s3_accel_in, NULL, NULL, s3_accel_out, NULL, NULL, s3); + io_removehandler(0x9ee8, 0x0002, s3_accel_in, s3_accel_in_w, NULL, s3_accel_out, s3_accel_out_w, NULL, s3); + io_removehandler(0xa2e8, 0x0004, s3_accel_in, NULL, NULL, s3_accel_out, NULL, NULL, s3); + io_removehandler(0xa6e8, 0x0004, s3_accel_in, NULL, NULL, s3_accel_out, NULL, NULL, s3); + io_removehandler(0xaae8, 0x0004, s3_accel_in, NULL, NULL, s3_accel_out, NULL, NULL, s3); + io_removehandler(0xaee8, 0x0004, s3_accel_in, NULL, NULL, s3_accel_out, NULL, NULL, s3); + if (s3->chip >= S3_86C928) + io_removehandler(0xb2e8, 0x0004, s3_accel_in, NULL, NULL, s3_accel_out, NULL, NULL, s3); + else + io_removehandler(0xb2e8, 0x0002, s3_accel_in, s3_accel_in_w, NULL, s3_accel_out, s3_accel_out_w, s3_accel_out_l, s3); + io_removehandler(0xb6e8, 0x0002, s3_accel_in, NULL, NULL, s3_accel_out, NULL, NULL, s3); + io_removehandler(0xbae8, 0x0002, s3_accel_in, NULL, NULL, s3_accel_out, NULL, NULL, s3); + io_removehandler(0xbee8, 0x0002, s3_accel_in, NULL, NULL, s3_accel_out, NULL, NULL, s3); + io_removehandler(0xcae8, 0x0002, s3_accel_in, NULL, NULL, s3_accel_out, NULL, NULL, s3); + io_removehandler(0xd2e8, 0x0002, s3_accel_in, NULL, NULL, s3_accel_out, NULL, NULL, s3); + io_removehandler(0xe2e8, 0x0004, s3_accel_in, s3_accel_in_w, s3_accel_in_l, s3_accel_out, s3_accel_out_w, s3_accel_out_l, s3); + io_removehandler(0xe6e8, 0x0004, s3_accel_in, NULL, NULL, s3_accel_out, NULL, NULL, s3); + io_removehandler(0xeae8, 0x0004, s3_accel_in, NULL, NULL, s3_accel_out, NULL, NULL, s3); + io_removehandler(0xeee8, 0x0004, s3_accel_in, NULL, NULL, s3_accel_out, NULL, NULL, s3); + io_removehandler(0xfee8, 0x0002, s3_accel_in, NULL, NULL, s3_accel_out, NULL, NULL, s3); - s3_io_remove_alt(s3); + s3_io_remove_alt(s3); } static void s3_io_set_alt(s3_t *s3) { - svga_t *svga = &s3->svga; - - if (!s3->translate) - return; + const svga_t *svga = &s3->svga; - if ((s3->chip == S3_VISION968 || s3->chip == S3_VISION868) && (svga->seqregs[9] & 0x80)) { - return; - } + if (!s3->translate) + return; - io_sethandler(0x4148, 0x0002, s3_accel_in, NULL, NULL, s3_accel_out, NULL, NULL, s3); - io_sethandler(0x4548, 0x0002, s3_accel_in, NULL, NULL, s3_accel_out, NULL, NULL, s3); - io_sethandler(0x4948, 0x0002, s3_accel_in, NULL, NULL, s3_accel_out, NULL, NULL, s3); - if (s3->chip == S3_TRIO64 || s3->chip >= S3_TRIO64V || s3->chip == S3_VISION968 || s3->chip == S3_VISION868) - { - io_sethandler(0x8148, 0x0004, s3_accel_in, NULL, NULL, s3_accel_out, NULL, NULL, s3); - io_sethandler(0x8548, 0x0004, s3_accel_in, NULL, NULL, s3_accel_out, NULL, NULL, s3); - io_sethandler(0x8948, 0x0004, s3_accel_in, NULL, NULL, s3_accel_out, NULL, NULL, s3); - io_sethandler(0x8d48, 0x0004, s3_accel_in, NULL, NULL, s3_accel_out, NULL, NULL, s3); - io_sethandler(0x9148, 0x0004, s3_accel_in, NULL, NULL, s3_accel_out, NULL, NULL, s3); - io_sethandler(0x9548, 0x0004, s3_accel_in, NULL, NULL, s3_accel_out, NULL, NULL, s3); - } - else - { - io_sethandler(0x8148, 0x0002, s3_accel_in, NULL, NULL, s3_accel_out, NULL, NULL, s3); - io_sethandler(0x8548, 0x0002, s3_accel_in, NULL, NULL, s3_accel_out, NULL, NULL, s3); - io_sethandler(0x8948, 0x0002, s3_accel_in, NULL, NULL, s3_accel_out, NULL, NULL, s3); - io_sethandler(0x8d48, 0x0002, s3_accel_in, NULL, NULL, s3_accel_out, NULL, NULL, s3); - io_sethandler(0x9148, 0x0002, s3_accel_in, NULL, NULL, s3_accel_out, NULL, NULL, s3); - io_sethandler(0x9548, 0x0002, s3_accel_in, NULL, NULL, s3_accel_out, NULL, NULL, s3); - } - if (s3->chip == S3_VISION968 || s3->chip == S3_VISION868) - io_sethandler(0x9948, 0x0004, s3_accel_in, NULL, NULL, s3_accel_out, NULL, NULL, s3); - else - io_sethandler(0x9948, 0x0002, s3_accel_in, NULL, NULL, s3_accel_out, NULL, NULL, s3); - io_sethandler(0x9d48, 0x0002, s3_accel_in, s3_accel_in_w, NULL, s3_accel_out, s3_accel_out_w, NULL, s3); - io_sethandler(0xa148, 0x0004, s3_accel_in, NULL, NULL, s3_accel_out, NULL, NULL, s3); - io_sethandler(0xa548, 0x0004, s3_accel_in, NULL, NULL, s3_accel_out, NULL, NULL, s3); - io_sethandler(0xa948, 0x0004, s3_accel_in, NULL, NULL, s3_accel_out, NULL, NULL, s3); - io_sethandler(0xad48, 0x0004, s3_accel_in, NULL, NULL, s3_accel_out, NULL, NULL, s3); - if (s3->chip >= S3_86C928) - io_sethandler(0xb148, 0x0004, s3_accel_in, NULL, NULL, s3_accel_out, NULL, NULL, s3); - else - io_sethandler(0xb148, 0x0002, s3_accel_in, s3_accel_in_w, NULL, s3_accel_out, s3_accel_out_w, s3_accel_out_l, s3); - io_sethandler(0xb548, 0x0002, s3_accel_in, NULL, NULL, s3_accel_out, NULL, NULL, s3); - io_sethandler(0xb948, 0x0002, s3_accel_in, NULL, NULL, s3_accel_out, NULL, NULL, s3); - io_sethandler(0xbd48, 0x0002, s3_accel_in, NULL, NULL, s3_accel_out, NULL, NULL, s3); - io_sethandler(0xe148, 0x0004, s3_accel_in, s3_accel_in_w, s3_accel_in_l, s3_accel_out, s3_accel_out_w, s3_accel_out_l, s3); - if (s3->chip == S3_VISION968 || s3->chip == S3_VISION868) { - io_sethandler(0xd148, 0x0002, s3_accel_in, NULL, NULL, s3_accel_out, NULL, NULL, s3); - io_sethandler(0xe548, 0x0004, s3_accel_in, NULL, NULL, s3_accel_out, NULL, NULL, s3); - io_sethandler(0xe948, 0x0004, s3_accel_in, NULL, NULL, s3_accel_out, NULL, NULL, s3); - io_sethandler(0xed48, 0x0004, s3_accel_in, NULL, NULL, s3_accel_out, NULL, NULL, s3); - } + if ((s3->chip == S3_VISION968 || s3->chip == S3_VISION868) && (svga->seqregs[9] & 0x80)) { + return; + } + + io_sethandler(0x4148, 0x0002, s3_accel_in, NULL, NULL, s3_accel_out, NULL, NULL, s3); + io_sethandler(0x4548, 0x0002, s3_accel_in, NULL, NULL, s3_accel_out, NULL, NULL, s3); + io_sethandler(0x4948, 0x0002, s3_accel_in, NULL, NULL, s3_accel_out, NULL, NULL, s3); + if (s3->chip == S3_TRIO64 || s3->chip >= S3_TRIO64V || s3->chip == S3_VISION968 || s3->chip == S3_VISION868) { + io_sethandler(0x8148, 0x0004, s3_accel_in, NULL, NULL, s3_accel_out, NULL, NULL, s3); + io_sethandler(0x8548, 0x0004, s3_accel_in, NULL, NULL, s3_accel_out, NULL, NULL, s3); + io_sethandler(0x8948, 0x0004, s3_accel_in, NULL, NULL, s3_accel_out, NULL, NULL, s3); + io_sethandler(0x8d48, 0x0004, s3_accel_in, NULL, NULL, s3_accel_out, NULL, NULL, s3); + io_sethandler(0x9148, 0x0004, s3_accel_in, NULL, NULL, s3_accel_out, NULL, NULL, s3); + io_sethandler(0x9548, 0x0004, s3_accel_in, NULL, NULL, s3_accel_out, NULL, NULL, s3); + } else { + io_sethandler(0x8148, 0x0002, s3_accel_in, NULL, NULL, s3_accel_out, NULL, NULL, s3); + io_sethandler(0x8548, 0x0002, s3_accel_in, NULL, NULL, s3_accel_out, NULL, NULL, s3); + io_sethandler(0x8948, 0x0002, s3_accel_in, NULL, NULL, s3_accel_out, NULL, NULL, s3); + io_sethandler(0x8d48, 0x0002, s3_accel_in, NULL, NULL, s3_accel_out, NULL, NULL, s3); + io_sethandler(0x9148, 0x0002, s3_accel_in, NULL, NULL, s3_accel_out, NULL, NULL, s3); + io_sethandler(0x9548, 0x0002, s3_accel_in, NULL, NULL, s3_accel_out, NULL, NULL, s3); + } + if (s3->chip == S3_VISION968 || s3->chip == S3_VISION868) + io_sethandler(0x9948, 0x0004, s3_accel_in, NULL, NULL, s3_accel_out, NULL, NULL, s3); + else + io_sethandler(0x9948, 0x0002, s3_accel_in, NULL, NULL, s3_accel_out, NULL, NULL, s3); + io_sethandler(0x9d48, 0x0002, s3_accel_in, s3_accel_in_w, NULL, s3_accel_out, s3_accel_out_w, NULL, s3); + io_sethandler(0xa148, 0x0004, s3_accel_in, NULL, NULL, s3_accel_out, NULL, NULL, s3); + io_sethandler(0xa548, 0x0004, s3_accel_in, NULL, NULL, s3_accel_out, NULL, NULL, s3); + io_sethandler(0xa948, 0x0004, s3_accel_in, NULL, NULL, s3_accel_out, NULL, NULL, s3); + io_sethandler(0xad48, 0x0004, s3_accel_in, NULL, NULL, s3_accel_out, NULL, NULL, s3); + if (s3->chip >= S3_86C928) + io_sethandler(0xb148, 0x0004, s3_accel_in, NULL, NULL, s3_accel_out, NULL, NULL, s3); + else + io_sethandler(0xb148, 0x0002, s3_accel_in, s3_accel_in_w, NULL, s3_accel_out, s3_accel_out_w, s3_accel_out_l, s3); + io_sethandler(0xb548, 0x0002, s3_accel_in, NULL, NULL, s3_accel_out, NULL, NULL, s3); + io_sethandler(0xb948, 0x0002, s3_accel_in, NULL, NULL, s3_accel_out, NULL, NULL, s3); + io_sethandler(0xbd48, 0x0002, s3_accel_in, NULL, NULL, s3_accel_out, NULL, NULL, s3); + io_sethandler(0xe148, 0x0004, s3_accel_in, s3_accel_in_w, s3_accel_in_l, s3_accel_out, s3_accel_out_w, s3_accel_out_l, s3); + if (s3->chip == S3_VISION968 || s3->chip == S3_VISION868) { + io_sethandler(0xd148, 0x0002, s3_accel_in, NULL, NULL, s3_accel_out, NULL, NULL, s3); + io_sethandler(0xe548, 0x0004, s3_accel_in, NULL, NULL, s3_accel_out, NULL, NULL, s3); + io_sethandler(0xe948, 0x0004, s3_accel_in, NULL, NULL, s3_accel_out, NULL, NULL, s3); + io_sethandler(0xed48, 0x0004, s3_accel_in, NULL, NULL, s3_accel_out, NULL, NULL, s3); + } } static void s3_io_set(s3_t *s3) { - svga_t *svga = &s3->svga; - - s3_io_remove(s3); + const svga_t *svga = &s3->svga; - io_sethandler(0x03c0, 0x0020, s3_in, NULL, NULL, s3_out, NULL, NULL, s3); + s3_io_remove(s3); - if ((s3->chip == S3_VISION968 || s3->chip == S3_VISION868) && (svga->seqregs[9] & 0x80)) { - return; - } + io_sethandler(0x03c0, 0x0020, s3_in, NULL, NULL, s3_out, NULL, NULL, s3); - io_sethandler(0x42e8, 0x0002, s3_accel_in, NULL, NULL, s3_accel_out, NULL, NULL, s3); - io_sethandler(0x46e8, 0x0002, s3_accel_in, NULL, NULL, s3_accel_out, NULL, NULL, s3); - io_sethandler(0x4ae8, 0x0002, s3_accel_in, NULL, NULL, s3_accel_out, NULL, NULL, s3); - if (s3->chip == S3_TRIO64 || s3->chip >= S3_TRIO64V || s3->chip == S3_VISION968 || s3->chip == S3_VISION868) - { - io_sethandler(0x82e8, 0x0004, s3_accel_in, NULL, NULL, s3_accel_out, NULL, NULL, s3); - io_sethandler(0x86e8, 0x0004, s3_accel_in, NULL, NULL, s3_accel_out, NULL, NULL, s3); - io_sethandler(0x8ae8, 0x0004, s3_accel_in, NULL, NULL, s3_accel_out, NULL, NULL, s3); - io_sethandler(0x8ee8, 0x0004, s3_accel_in, NULL, NULL, s3_accel_out, NULL, NULL, s3); - io_sethandler(0x92e8, 0x0004, s3_accel_in, NULL, NULL, s3_accel_out, NULL, NULL, s3); - io_sethandler(0x96e8, 0x0004, s3_accel_in, NULL, NULL, s3_accel_out, NULL, NULL, s3); - } - else - { - io_sethandler(0x82e8, 0x0002, s3_accel_in, NULL, NULL, s3_accel_out, NULL, NULL, s3); - io_sethandler(0x86e8, 0x0002, s3_accel_in, NULL, NULL, s3_accel_out, NULL, NULL, s3); - io_sethandler(0x8ae8, 0x0002, s3_accel_in, NULL, NULL, s3_accel_out, NULL, NULL, s3); - io_sethandler(0x8ee8, 0x0002, s3_accel_in, NULL, NULL, s3_accel_out, NULL, NULL, s3); - io_sethandler(0x92e8, 0x0002, s3_accel_in, NULL, NULL, s3_accel_out, NULL, NULL, s3); - io_sethandler(0x96e8, 0x0002, s3_accel_in, NULL, NULL, s3_accel_out, NULL, NULL, s3); - } - if (s3->chip == S3_VISION968 || s3->chip == S3_VISION868) - io_sethandler(0x9ae8, 0x0004, s3_accel_in, NULL, NULL, s3_accel_out, NULL, NULL, s3); - else - io_sethandler(0x9ae8, 0x0002, s3_accel_in, NULL, NULL, s3_accel_out, NULL, NULL, s3); - io_sethandler(0x9ee8, 0x0002, s3_accel_in, s3_accel_in_w, NULL, s3_accel_out, s3_accel_out_w, NULL, s3); - io_sethandler(0xa2e8, 0x0004, s3_accel_in, NULL, NULL, s3_accel_out, NULL, NULL, s3); - io_sethandler(0xa6e8, 0x0004, s3_accel_in, NULL, NULL, s3_accel_out, NULL, NULL, s3); - io_sethandler(0xaae8, 0x0004, s3_accel_in, NULL, NULL, s3_accel_out, NULL, NULL, s3); - io_sethandler(0xaee8, 0x0004, s3_accel_in, NULL, NULL, s3_accel_out, NULL, NULL, s3); - if (s3->chip >= S3_86C928) - io_sethandler(0xb2e8, 0x0004, s3_accel_in, NULL, NULL, s3_accel_out, NULL, NULL, s3); - else - io_sethandler(0xb2e8, 0x0002, s3_accel_in, s3_accel_in_w, NULL, s3_accel_out, s3_accel_out_w, s3_accel_out_l, s3); - io_sethandler(0xb6e8, 0x0002, s3_accel_in, NULL, NULL, s3_accel_out, NULL, NULL, s3); - io_sethandler(0xbae8, 0x0002, s3_accel_in, NULL, NULL, s3_accel_out, NULL, NULL, s3); - io_sethandler(0xbee8, 0x0002, s3_accel_in, NULL, NULL, s3_accel_out, NULL, NULL, s3); - io_sethandler(0xcae8, 0x0002, s3_accel_in, NULL, NULL, s3_accel_out, NULL, NULL, s3); - io_sethandler(0xe2e8, 0x0004, s3_accel_in, s3_accel_in_w, s3_accel_in_l, s3_accel_out, s3_accel_out_w, s3_accel_out_l, s3); - if (s3->chip == S3_VISION968 || s3->chip == S3_VISION868) { - io_sethandler(0xd2e8, 0x0002, s3_accel_in, NULL, NULL, s3_accel_out, NULL, NULL, s3); - io_sethandler(0xe6e8, 0x0004, s3_accel_in, NULL, NULL, s3_accel_out, NULL, NULL, s3); - io_sethandler(0xeae8, 0x0004, s3_accel_in, NULL, NULL, s3_accel_out, NULL, NULL, s3); - io_sethandler(0xeee8, 0x0004, s3_accel_in, NULL, NULL, s3_accel_out, NULL, NULL, s3); - } - io_sethandler(0xfee8, 0x0002, s3_accel_in, NULL, NULL, s3_accel_out, NULL, NULL, s3); - - s3_io_set_alt(s3); + if ((s3->chip == S3_VISION968 || s3->chip == S3_VISION868) && (svga->seqregs[9] & 0x80)) { + return; + } + + io_sethandler(0x42e8, 0x0002, s3_accel_in, NULL, NULL, s3_accel_out, NULL, NULL, s3); + io_sethandler(0x46e8, 0x0002, s3_accel_in, NULL, NULL, s3_accel_out, NULL, NULL, s3); + io_sethandler(0x4ae8, 0x0002, s3_accel_in, NULL, NULL, s3_accel_out, NULL, NULL, s3); + if (s3->chip == S3_TRIO64 || s3->chip >= S3_TRIO64V || s3->chip == S3_VISION968 || s3->chip == S3_VISION868) { + io_sethandler(0x82e8, 0x0004, s3_accel_in, NULL, NULL, s3_accel_out, NULL, NULL, s3); + io_sethandler(0x86e8, 0x0004, s3_accel_in, NULL, NULL, s3_accel_out, NULL, NULL, s3); + io_sethandler(0x8ae8, 0x0004, s3_accel_in, NULL, NULL, s3_accel_out, NULL, NULL, s3); + io_sethandler(0x8ee8, 0x0004, s3_accel_in, NULL, NULL, s3_accel_out, NULL, NULL, s3); + io_sethandler(0x92e8, 0x0004, s3_accel_in, NULL, NULL, s3_accel_out, NULL, NULL, s3); + io_sethandler(0x96e8, 0x0004, s3_accel_in, NULL, NULL, s3_accel_out, NULL, NULL, s3); + } else { + io_sethandler(0x82e8, 0x0002, s3_accel_in, NULL, NULL, s3_accel_out, NULL, NULL, s3); + io_sethandler(0x86e8, 0x0002, s3_accel_in, NULL, NULL, s3_accel_out, NULL, NULL, s3); + io_sethandler(0x8ae8, 0x0002, s3_accel_in, NULL, NULL, s3_accel_out, NULL, NULL, s3); + io_sethandler(0x8ee8, 0x0002, s3_accel_in, NULL, NULL, s3_accel_out, NULL, NULL, s3); + io_sethandler(0x92e8, 0x0002, s3_accel_in, NULL, NULL, s3_accel_out, NULL, NULL, s3); + io_sethandler(0x96e8, 0x0002, s3_accel_in, NULL, NULL, s3_accel_out, NULL, NULL, s3); + } + if (s3->chip == S3_VISION968 || s3->chip == S3_VISION868) + io_sethandler(0x9ae8, 0x0004, s3_accel_in, NULL, NULL, s3_accel_out, NULL, NULL, s3); + else + io_sethandler(0x9ae8, 0x0002, s3_accel_in, NULL, NULL, s3_accel_out, NULL, NULL, s3); + io_sethandler(0x9ee8, 0x0002, s3_accel_in, s3_accel_in_w, NULL, s3_accel_out, s3_accel_out_w, NULL, s3); + io_sethandler(0xa2e8, 0x0004, s3_accel_in, NULL, NULL, s3_accel_out, NULL, NULL, s3); + io_sethandler(0xa6e8, 0x0004, s3_accel_in, NULL, NULL, s3_accel_out, NULL, NULL, s3); + io_sethandler(0xaae8, 0x0004, s3_accel_in, NULL, NULL, s3_accel_out, NULL, NULL, s3); + io_sethandler(0xaee8, 0x0004, s3_accel_in, NULL, NULL, s3_accel_out, NULL, NULL, s3); + if (s3->chip >= S3_86C928) + io_sethandler(0xb2e8, 0x0004, s3_accel_in, NULL, NULL, s3_accel_out, NULL, NULL, s3); + else + io_sethandler(0xb2e8, 0x0002, s3_accel_in, s3_accel_in_w, NULL, s3_accel_out, s3_accel_out_w, s3_accel_out_l, s3); + io_sethandler(0xb6e8, 0x0002, s3_accel_in, NULL, NULL, s3_accel_out, NULL, NULL, s3); + io_sethandler(0xbae8, 0x0002, s3_accel_in, NULL, NULL, s3_accel_out, NULL, NULL, s3); + io_sethandler(0xbee8, 0x0002, s3_accel_in, NULL, NULL, s3_accel_out, NULL, NULL, s3); + io_sethandler(0xcae8, 0x0002, s3_accel_in, NULL, NULL, s3_accel_out, NULL, NULL, s3); + io_sethandler(0xe2e8, 0x0004, s3_accel_in, s3_accel_in_w, s3_accel_in_l, s3_accel_out, s3_accel_out_w, s3_accel_out_l, s3); + if (s3->chip == S3_VISION968 || s3->chip == S3_VISION868) { + io_sethandler(0xd2e8, 0x0002, s3_accel_in, NULL, NULL, s3_accel_out, NULL, NULL, s3); + io_sethandler(0xe6e8, 0x0004, s3_accel_in, NULL, NULL, s3_accel_out, NULL, NULL, s3); + io_sethandler(0xeae8, 0x0004, s3_accel_in, NULL, NULL, s3_accel_out, NULL, NULL, s3); + io_sethandler(0xeee8, 0x0004, s3_accel_in, NULL, NULL, s3_accel_out, NULL, NULL, s3); + } + io_sethandler(0xfee8, 0x0002, s3_accel_in, NULL, NULL, s3_accel_out, NULL, NULL, s3); + + s3_io_set_alt(s3); } static void -s3_out(uint16_t addr, uint8_t val, void *p) +s3_out(uint16_t addr, uint8_t val, void *priv) { - s3_t *s3 = (s3_t *)p; - svga_t *svga = &s3->svga; - uint8_t old, mask; - int rs2, rs3; + s3_t *s3 = (s3_t *) priv; + svga_t *svga = &s3->svga; + uint8_t old; + uint8_t mask; + int rs2; + int rs3; - if (((addr & 0xfff0) == 0x3d0 || (addr & 0xfff0) == 0x3b0) && !(svga->miscout & 1)) - addr ^= 0x60; + if (((addr & 0xfff0) == 0x3d0 || (addr & 0xfff0) == 0x3b0) && !(svga->miscout & 1)) + addr ^= 0x60; - switch (addr) - { - case 0x3c2: - if ((s3->chip == S3_VISION964) || (s3->chip == S3_VISION968) || (s3->chip == S3_86C928)) { - if ((s3->card_type != S3_SPEA_MERCURY_P64V) && (s3->card_type != S3_MIROVIDEO40SV_ERGO_968)) { - if (((val >> 2) & 3) != 3) - icd2061_write(svga->clock_gen, (val >> 2) & 3); - } - } - break; - - case 0x3c5: - if (svga->seqaddr >= 0x10 && svga->seqaddr < 0x20) - { - svga->seqregs[svga->seqaddr] = val; - switch (svga->seqaddr) - { - case 0x12: case 0x13: - svga_recalctimings(svga); - return; - } - } - if (svga->seqaddr == 4) /*Chain-4 - update banking*/ - { - if (val & 0x08) - svga->write_bank = svga->read_bank = s3->bank << 16; - else - svga->write_bank = svga->read_bank = s3->bank << 14; - } else if (svga->seqaddr == 9) { - svga->seqregs[svga->seqaddr] = val & 0x80; - s3_io_set(s3); - return; - } else if (svga->seqaddr == 0xa) { - svga->seqregs[svga->seqaddr] = val & 0x80; - return; - } else if (s3->chip >= S3_VISION964) { - if (svga->seqaddr == 0x08) { - svga->seqregs[svga->seqaddr] = val & 0x0f; - return; - } else if ((svga->seqaddr == 0x0d) && (svga->seqregs[0x08] == 0x06)) { - svga->seqregs[svga->seqaddr] = val; - svga->dpms = ((s3->chip >= S3_VISION964) && (svga->seqregs[0x0d] & 0x50)) || (svga->crtc[0x56] & ((s3->chip >= S3_TRIO32) ? 0x06 : 0x20)); - svga_recalctimings(svga); - return; - } - } - break; - - case 0x3C6: case 0x3C7: case 0x3C8: case 0x3C9: - if ((svga->crtc[0x55] & 0x03) == 0x00) - rs2 = !!(svga->crtc[0x43] & 0x02); - else - rs2 = (svga->crtc[0x55] & 0x01); - if (s3->chip >= S3_TRIO32) - svga_out(addr, val, svga); - else if ((s3->chip == S3_VISION964 && s3->card_type != S3_ELSAWIN2KPROX_964) || (s3->chip == S3_86C928)) { - if (!(svga->crtc[0x45] & 0x20) || (s3->chip == S3_86C928)) - rs3 = !!(svga->crtc[0x55] & 0x02); - else - rs3 = 0; - bt48x_ramdac_out(addr, rs2, rs3, val, svga->ramdac, svga); - } else if ((s3->chip == S3_VISION964 && s3->card_type == S3_ELSAWIN2KPROX_964) || (s3->chip == S3_VISION968 && (s3->card_type == S3_ELSAWIN2KPROX || - s3->card_type == S3_PHOENIX_VISION968 || s3->card_type == S3_NUMBER9_9FX_771))) - ibm_rgb528_ramdac_out(addr, rs2, val, svga->ramdac, svga); - else if ((s3->chip == S3_VISION968 && (s3->card_type == S3_SPEA_MERCURY_P64V || s3->card_type == S3_MIROVIDEO40SV_ERGO_968))) { - rs3 = !!(svga->crtc[0x55] & 0x02); - tvp3026_ramdac_out(addr, rs2, rs3, val, svga->ramdac, svga); - } else if (((s3->chip == S3_86C801) || (s3->chip == S3_86C805)) && (s3->card_type != S3_MIROCRYSTAL10SD_805 && s3->card_type != S3_MIROCRYSTAL8S_805)) - att49x_ramdac_out(addr, rs2, val, svga->ramdac, svga); - else if (s3->chip <= S3_86C924) { - sc1148x_ramdac_out(addr, rs2, val, svga->ramdac, svga); - } else if (s3->card_type == S3_NUMBER9_9FX_531) - att498_ramdac_out(addr, rs2, val, svga->ramdac, svga); - else if ((s3->chip == S3_86C928PCI) && (s3->card_type == S3_SPEA_MERCURY_LITE_PCI)) - sc1502x_ramdac_out(addr, val, svga->ramdac, svga); - else - sdac_ramdac_out(addr, rs2, val, svga->ramdac, svga); - return; - - case 0x3D4: - svga->crtcreg = (s3->chip == S3_TRIO64V2) ? val : (val & 0x7f); - return; - case 0x3D5: - if ((svga->crtcreg < 7) && (svga->crtc[0x11] & 0x80)) - return; - if ((svga->crtcreg == 7) && (svga->crtc[0x11] & 0x80)) - val = (svga->crtc[7] & ~0x10) | (val & 0x10); - if ((svga->crtcreg >= 0x20) && (svga->crtcreg < 0x40) && - (svga->crtcreg != 0x36) && (svga->crtcreg != 0x38) && - (svga->crtcreg != 0x39) && ((svga->crtc[0x38] & 0xcc) != 0x48)) - return; - if ((svga->crtcreg >= 0x40) && ((svga->crtc[0x39] & 0xe0) != 0xa0)) - return; - if ((svga->crtcreg == 0x36) && (svga->crtc[0x39] != 0xa5)) - return; - if ((s3->chip == S3_TRIO64V2) && (svga->crtcreg >= 0x80)) - return; - if ((s3->chip <= S3_86C924) && (svga->crtcreg >= 0x50)) - return; - old = svga->crtc[svga->crtcreg]; - svga->crtc[svga->crtcreg] = val; - - switch (svga->crtcreg) - { - case 0x31: - s3->ma_ext = (s3->ma_ext & 0x1c) | ((val & 0x30) >> 4); - break; - case 0x32: - if ((svga->crtc[0x31] & 0x30) && (svga->crtc[0x51] & 0x01) && (val & 0x40)) - svga->vram_display_mask = 0x3ffff; - else - svga->vram_display_mask = s3->vram_mask; - break; - - case 0x40: - s3->enable_8514 = (val & 0x01); - break; - - case 0x50: - mask = 0xc0; - if (s3->chip != S3_86C801) - mask |= 0x01; - switch (svga->crtc[0x50] & mask) - { - case 0x00: s3->width = (svga->crtc[0x31] & 2) ? 2048 : 1024; break; - case 0x01: s3->width = 1152; break; - case 0x40: s3->width = 640; break; - case 0x80: s3->width = ((s3->chip > S3_86C805) && (s3->accel.advfunc_cntl & 4)) ? 1600 : 800; break; - case 0x81: s3->width = 1600; break; - case 0xc0: s3->width = 1280; break; - } - s3->bpp = (svga->crtc[0x50] >> 4) & 3; - break; - - case 0x5c: - if ((val & 0xa0) == 0x80) - i2c_gpio_set(s3->i2c, !!(val & 0x40), !!(val & 0x10)); - if (s3->card_type == S3_PHOENIX_VISION868 || s3->card_type == S3_PHOENIX_VISION968) { - if ((val & 0x20) && (!(svga->crtc[0x55] & 0x01) && !(svga->crtc[0x43] & 2))) - svga->dac_addr |= 0x20; - } else if (s3->card_type == S3_MIROVIDEO40SV_ERGO_968) { - if ((val & 0x80) && (!(svga->crtc[0x55] & 0x01) && !(svga->crtc[0x43] & 2))) - svga->dac_addr |= 0x02; - } - break; - - case 0x69: - if (s3->chip >= S3_VISION964) - s3->ma_ext = val & 0x1f; - break; - - case 0x35: - s3->bank = (s3->bank & 0x70) | (val & 0xf); - if (svga->chain4) - svga->write_bank = svga->read_bank = s3->bank << 16; - else - svga->write_bank = svga->read_bank = s3->bank << 14; - break; - - case 0x51: - if (s3->chip == S3_86C801 || s3->chip == S3_86C805) { - s3->bank = (s3->bank & 0x6f) | ((val & 0x4) << 2); - s3->ma_ext = (s3->ma_ext & ~0x4) | ((val & 1) << 2); - } else { - s3->bank = (s3->bank & 0x4f) | ((val & 0xc) << 2); - s3->ma_ext = (s3->ma_ext & ~0xc) | ((val & 3) << 2); - } - if (svga->chain4) - svga->write_bank = svga->read_bank = s3->bank << 16; - else - svga->write_bank = svga->read_bank = s3->bank << 14; - break; - - case 0x6a: - if (s3->chip >= S3_VISION964) { - s3->bank = val; - if (svga->chain4) - svga->write_bank = svga->read_bank = s3->bank << 16; - else - svga->write_bank = svga->read_bank = s3->bank << 14; - } - break; - - case 0x45: - if (s3->chip == S3_VISION964 || s3->chip == S3_VISION968) - break; - svga->hwcursor.ena = val & 1; - break; - case 0x46: case 0x47: case 0x48: case 0x49: - case 0x4c: case 0x4d: case 0x4e: case 0x4f: - if (s3->chip == S3_VISION964 || s3->chip == S3_VISION968) - break; - svga->hwcursor.x = ((svga->crtc[0x46] << 8) | svga->crtc[0x47]) & 0x7ff; - if (svga->bpp == 32) svga->hwcursor.x >>= 1; - svga->hwcursor.y = ((svga->crtc[0x48] << 8) | svga->crtc[0x49]) & 0x7ff; - svga->hwcursor.xoff = svga->crtc[0x4e] & 0x3f; - svga->hwcursor.yoff = svga->crtc[0x4f] & 0x3f; - svga->hwcursor.addr = ((((svga->crtc[0x4c] << 8) | svga->crtc[0x4d]) & 0xfff) * 1024) + (svga->hwcursor.yoff * 16); - if ((s3->chip >= S3_TRIO32) && svga->bpp == 32) - svga->hwcursor.x <<= 1; - else if ((s3->chip >= S3_86C928 && s3->chip <= S3_86C805) && (svga->bpp == 15 || svga->bpp == 16)) { - if ((s3->card_type == S3_MIROCRYSTAL10SD_805) && !(svga->crtc[0x45] & 0x04) && svga->bpp == 16) - svga->hwcursor.x >>= 2; - else - svga->hwcursor.x >>= 1; - } else if ((s3->chip >= S3_86C928 && s3->chip <= S3_86C805) && (svga->bpp == 24)) - svga->hwcursor.x /= 3; - break; - - case 0x4a: - switch (s3->hwc_col_stack_pos) - { - case 0: - s3->hwc_fg_col = (s3->hwc_fg_col & 0xffff00) | val; - break; - case 1: - s3->hwc_fg_col = (s3->hwc_fg_col & 0xff00ff) | (val << 8); - break; - case 2: - s3->hwc_fg_col = (s3->hwc_fg_col & 0x00ffff) | (val << 16); - break; - } - s3->hwc_col_stack_pos = (s3->hwc_col_stack_pos + 1) & 3; - break; - case 0x4b: - switch (s3->hwc_col_stack_pos) - { - case 0: - s3->hwc_bg_col = (s3->hwc_bg_col & 0xffff00) | val; - break; - case 1: - s3->hwc_bg_col = (s3->hwc_bg_col & 0xff00ff) | (val << 8); - break; - case 2: - s3->hwc_bg_col = (s3->hwc_bg_col & 0x00ffff) | (val << 16); - break; - } - s3->hwc_col_stack_pos = (s3->hwc_col_stack_pos + 1) & 3; - break; - - case 0x53: - case 0x58: case 0x59: case 0x5a: - s3_updatemapping(s3); - break; - - case 0x55: - if (s3->chip == S3_86C928) { - if ((val & 0x08) || ((val & 0x20) == 0x20)) { - svga->hwcursor_draw = NULL; - svga->dac_hwcursor_draw = bt48x_hwcursor_draw; - } else { - svga->hwcursor_draw = s3_hwcursor_draw; - svga->dac_hwcursor_draw = NULL; - } - } - break; - - case 0x42: - if ((s3->chip == S3_VISION964) || (s3->chip == S3_VISION968) || (s3->chip == S3_86C928)) { - if (((svga->miscout >> 2) & 3) == 3) - icd2061_write(svga->clock_gen, svga->crtc[0x42] & 0x0f); - } - break; - - case 0x43: - if (s3->chip < S3_VISION964) { - s3_io_remove_alt(s3); - s3->translate = !!(val & 0x10); - s3_io_set_alt(s3); - } - break; - - case 0x56: - svga->dpms = ((s3->chip >= S3_VISION964) && (svga->seqregs[0x0d] & 0x50)) || (svga->crtc[0x56] & ((s3->chip >= S3_TRIO32) ? 0x06 : 0x20)); - old = ~val; /* force recalc */ - break; - - case 0x67: - if (s3->chip >= S3_TRIO32) { - switch (val >> 4) - { - case 3: svga->bpp = 15; break; - case 5: svga->bpp = 16; break; - case 7: svga->bpp = 24; break; - case 13: svga->bpp = 32; break; - default: svga->bpp = 8; break; - } - } - break; - } - if (old != val) - { - if (svga->crtcreg < 0xe || svga->crtcreg > 0x10) - { - 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); - if ((((svga->crtc[0x67] & 0xc) != 0xc) && (s3->chip >= S3_TRIO64V)) || (s3->chip < S3_TRIO64V)) - svga->ma_latch |= (s3->ma_ext << 16); - } else { - svga->fullchange = changeframecount; - svga_recalctimings(svga); - } - } + switch (addr) { + case 0x3c2: + if ((s3->chip == S3_VISION964) || (s3->chip == S3_VISION968) || (s3->chip == S3_86C928)) { + if ((s3->card_type != S3_SPEA_MERCURY_P64V) && (s3->card_type != S3_MIROVIDEO40SV_ERGO_968)) { + if (((val >> 2) & 3) != 3) + icd2061_write(svga->clock_gen, (val >> 2) & 3); } - break; - } - svga_out(addr, val, svga); + } + break; + + case 0x3c5: + if (svga->seqaddr >= 0x10 && svga->seqaddr < 0x20) { + svga->seqregs[svga->seqaddr] = val; + switch (svga->seqaddr) { + case 0x12: + case 0x13: + svga_recalctimings(svga); + return; + + default: + break; + } + } + if (svga->seqaddr == 4) /*Chain-4 - update banking*/ + { + if (val & 0x08) + svga->write_bank = svga->read_bank = s3->bank << 16; + else + svga->write_bank = svga->read_bank = s3->bank << 14; + } else if (svga->seqaddr == 9) { + svga->seqregs[svga->seqaddr] = val & 0x80; + s3_io_set(s3); + return; + } else if (svga->seqaddr == 0xa) { + svga->seqregs[svga->seqaddr] = val & 0x80; + return; + } else if (s3->chip >= S3_VISION964) { + if (svga->seqaddr == 0x08) { + svga->seqregs[svga->seqaddr] = val & 0x0f; + return; + } else if ((svga->seqaddr == 0x0d) && (svga->seqregs[0x08] == 0x06)) { + svga->seqregs[svga->seqaddr] = val; + svga->dpms = ((s3->chip >= S3_VISION964) && (svga->seqregs[0x0d] & 0x50)) || (svga->crtc[0x56] & ((s3->chip >= S3_TRIO32) ? 0x06 : 0x20)); + svga_recalctimings(svga); + return; + } + } + break; + + case 0x3C6: + case 0x3C7: + case 0x3C8: + case 0x3C9: + if ((svga->crtc[0x55] & 0x03) == 0x00) + rs2 = !!(svga->crtc[0x43] & 0x02); + else + rs2 = (svga->crtc[0x55] & 0x01); + if (s3->chip >= S3_TRIO32) + svga_out(addr, val, svga); + else if ((s3->chip == S3_VISION964 && s3->card_type != S3_ELSAWIN2KPROX_964) || (s3->chip == S3_86C928)) { + if (!(svga->crtc[0x45] & 0x20) || (s3->chip == S3_86C928)) + rs3 = !!(svga->crtc[0x55] & 0x02); + else + rs3 = 0; + bt48x_ramdac_out(addr, rs2, rs3, val, svga->ramdac, svga); + } else if ((s3->chip == S3_VISION964 && s3->card_type == S3_ELSAWIN2KPROX_964) || (s3->chip == S3_VISION968 && (s3->card_type == S3_ELSAWIN2KPROX || s3->card_type == S3_PHOENIX_VISION968 || s3->card_type == S3_NUMBER9_9FX_771))) + ibm_rgb528_ramdac_out(addr, rs2, val, svga->ramdac, svga); + else if (s3->chip == S3_VISION968 && (s3->card_type == S3_SPEA_MERCURY_P64V || s3->card_type == S3_MIROVIDEO40SV_ERGO_968)) { + rs3 = !!(svga->crtc[0x55] & 0x02); + tvp3026_ramdac_out(addr, rs2, rs3, val, svga->ramdac, svga); + } else if (((s3->chip == S3_86C801) || (s3->chip == S3_86C805)) && (s3->card_type != S3_MIROCRYSTAL10SD_805 && s3->card_type != S3_MIROCRYSTAL8S_805)) + att49x_ramdac_out(addr, rs2, val, svga->ramdac, svga); + else if (s3->chip <= S3_86C924) { + sc1148x_ramdac_out(addr, rs2, val, svga->ramdac, svga); + } else if (s3->card_type == S3_NUMBER9_9FX_531) + att498_ramdac_out(addr, rs2, val, svga->ramdac, svga); + else if ((s3->chip == S3_86C928PCI) && (s3->card_type == S3_SPEA_MERCURY_LITE_PCI)) + sc1502x_ramdac_out(addr, val, svga->ramdac, svga); + else + sdac_ramdac_out(addr, rs2, val, svga->ramdac, svga); + return; + + case 0x3D4: + svga->crtcreg = (s3->chip == S3_TRIO64V2) ? val : (val & 0x7f); + return; + case 0x3D5: + if ((svga->crtcreg < 7) && (svga->crtc[0x11] & 0x80)) + return; + if ((svga->crtcreg == 7) && (svga->crtc[0x11] & 0x80)) + val = (svga->crtc[7] & ~0x10) | (val & 0x10); + if ((svga->crtcreg >= 0x20) && (svga->crtcreg < 0x40) && (svga->crtcreg != 0x36) && (svga->crtcreg != 0x38) && (svga->crtcreg != 0x39) && ((svga->crtc[0x38] & 0xcc) != 0x48)) + return; + if ((svga->crtcreg >= 0x40) && ((svga->crtc[0x39] & 0xe0) != 0xa0)) + return; + if ((svga->crtcreg == 0x36) && (svga->crtc[0x39] != 0xa5)) + return; + if ((s3->chip == S3_TRIO64V2) && (svga->crtcreg >= 0x80)) + return; + if ((s3->chip <= S3_86C924) && (svga->crtcreg >= 0x50)) + return; + + old = svga->crtc[svga->crtcreg]; + svga->crtc[svga->crtcreg] = val; + + switch (svga->crtcreg) { + case 0x31: + s3->ma_ext = (s3->ma_ext & 0x1c) | ((val & 0x30) >> 4); + svga->force_dword_mode = !!(val & 0x08); + break; + case 0x32: + if ((svga->crtc[0x31] & 0x30) && (svga->crtc[0x51] & 0x01) && (val & 0x40)) + svga->vram_display_mask = 0x3ffff; + else + svga->vram_display_mask = s3->vram_mask; + break; + + case 0x40: + s3->enable_8514 = (val & 0x01); + break; + + case 0x50: + mask = 0xc0; + if (s3->chip != S3_86C801) + mask |= 0x01; + switch (svga->crtc[0x50] & mask) { + case 0x00: + s3->width = (svga->crtc[0x31] & 2) ? 2048 : 1024; + break; + case 0x01: + s3->width = 1152; + break; + case 0x40: + s3->width = 640; + break; + case 0x80: + s3->width = ((s3->chip > S3_86C805) && (s3->accel.advfunc_cntl & 4)) ? 1600 : 800; + break; + case 0x81: + s3->width = 1600; + break; + case 0xc0: + s3->width = 1280; + break; + + default: + break; + } + s3->bpp = (svga->crtc[0x50] >> 4) & 3; + break; + + case 0x5c: + if ((val & 0xa0) == 0x80) + i2c_gpio_set(s3->i2c, !!(val & 0x40), !!(val & 0x10)); + if (s3->card_type == S3_PHOENIX_VISION868 || s3->card_type == S3_PHOENIX_VISION968) { + if ((val & 0x20) && (!(svga->crtc[0x55] & 0x01) && !(svga->crtc[0x43] & 2))) + svga->dac_addr |= 0x20; + } else if (s3->card_type == S3_MIROVIDEO40SV_ERGO_968) { + if ((val & 0x80) && (!(svga->crtc[0x55] & 0x01) && !(svga->crtc[0x43] & 2))) + svga->dac_addr |= 0x02; + } + break; + + case 0x69: + if (s3->chip >= S3_VISION964) + s3->ma_ext = val & 0x1f; + break; + + case 0x35: + s3->bank = (s3->bank & 0x70) | (val & 0xf); + if (svga->chain4) + svga->write_bank = svga->read_bank = s3->bank << 16; + else + svga->write_bank = svga->read_bank = s3->bank << 14; + break; + + case 0x51: + if (s3->chip == S3_86C801 || s3->chip == S3_86C805) { + s3->bank = (s3->bank & 0x6f) | ((val & 0x4) << 2); + s3->ma_ext = (s3->ma_ext & ~0x4) | ((val & 1) << 2); + } else { + s3->bank = (s3->bank & 0x4f) | ((val & 0xc) << 2); + s3->ma_ext = (s3->ma_ext & ~0xc) | ((val & 3) << 2); + } + if (svga->chain4) + svga->write_bank = svga->read_bank = s3->bank << 16; + else + svga->write_bank = svga->read_bank = s3->bank << 14; + break; + + case 0x6a: + if (s3->chip >= S3_VISION964) { + s3->bank = val; + if (svga->chain4) + svga->write_bank = svga->read_bank = s3->bank << 16; + else + svga->write_bank = svga->read_bank = s3->bank << 14; + } + break; + + case 0x45: + if (s3->chip == S3_VISION964 || s3->chip == S3_VISION968) + break; + svga->hwcursor.ena = val & 1; + break; + case 0x46: + case 0x47: + case 0x48: + case 0x49: + case 0x4c: + case 0x4d: + case 0x4e: + case 0x4f: + if (s3->chip == S3_VISION964 || s3->chip == S3_VISION968) + break; + svga->hwcursor.x = ((svga->crtc[0x46] << 8) | svga->crtc[0x47]) & 0x7ff; + if (svga->bpp == 32) + svga->hwcursor.x >>= 1; + svga->hwcursor.y = ((svga->crtc[0x48] << 8) | svga->crtc[0x49]) & 0x7ff; + svga->hwcursor.xoff = svga->crtc[0x4e] & 0x3f; + svga->hwcursor.yoff = svga->crtc[0x4f] & 0x3f; + svga->hwcursor.addr = ((((svga->crtc[0x4c] << 8) | svga->crtc[0x4d]) & 0xfff) * 1024) + (svga->hwcursor.yoff * 16); + if ((s3->chip >= S3_TRIO32) && svga->bpp == 32) + svga->hwcursor.x <<= 1; + else if ((s3->chip >= S3_86C928 && s3->chip <= S3_86C805) && (svga->bpp == 15 || svga->bpp == 16)) { + if ((s3->card_type == S3_MIROCRYSTAL10SD_805) && !(svga->crtc[0x45] & 0x04) && svga->bpp == 16) + svga->hwcursor.x >>= 2; + else + svga->hwcursor.x >>= 1; + } else if ((s3->chip >= S3_86C928 && s3->chip <= S3_86C805) && (svga->bpp == 24)) + svga->hwcursor.x /= 3; + break; + + case 0x4a: + switch (s3->hwc_col_stack_pos) { + case 0: + s3->hwc_fg_col = (s3->hwc_fg_col & 0xffff00) | val; + break; + case 1: + s3->hwc_fg_col = (s3->hwc_fg_col & 0xff00ff) | (val << 8); + break; + case 2: + s3->hwc_fg_col = (s3->hwc_fg_col & 0x00ffff) | (val << 16); + break; + + default: + break; + } + s3->hwc_col_stack_pos = (s3->hwc_col_stack_pos + 1) & 3; + break; + case 0x4b: + switch (s3->hwc_col_stack_pos) { + case 0: + s3->hwc_bg_col = (s3->hwc_bg_col & 0xffff00) | val; + break; + case 1: + s3->hwc_bg_col = (s3->hwc_bg_col & 0xff00ff) | (val << 8); + break; + case 2: + s3->hwc_bg_col = (s3->hwc_bg_col & 0x00ffff) | (val << 16); + break; + + default: + break; + } + s3->hwc_col_stack_pos = (s3->hwc_col_stack_pos + 1) & 3; + break; + + case 0x53: + case 0x58: + case 0x59: + case 0x5a: + s3_updatemapping(s3); + break; + + case 0x55: + if (s3->chip == S3_86C928) { + if ((val & 0x08) || ((val & 0x20) == 0x20)) { + svga->hwcursor_draw = NULL; + svga->dac_hwcursor_draw = bt48x_hwcursor_draw; + } else { + svga->hwcursor_draw = s3_hwcursor_draw; + svga->dac_hwcursor_draw = NULL; + } + } + break; + + case 0x42: + if ((s3->chip == S3_VISION964) || (s3->chip == S3_VISION968) || (s3->chip == S3_86C928)) { + if (((svga->miscout >> 2) & 3) == 3) + icd2061_write(svga->clock_gen, svga->crtc[0x42] & 0x0f); + } + break; + + case 0x43: + if (s3->chip < S3_VISION964) { + s3_io_remove_alt(s3); + s3->translate = !!(val & 0x10); + s3_io_set_alt(s3); + } + break; + + case 0x56: + svga->dpms = ((s3->chip >= S3_VISION964) && (svga->seqregs[0x0d] & 0x50)) || (svga->crtc[0x56] & ((s3->chip >= S3_TRIO32) ? 0x06 : 0x20)); + old = ~val; /* force recalc */ + break; + + case 0x67: + if (s3->chip >= S3_TRIO32) { + switch (val >> 4) { + case 3: + svga->bpp = 15; + break; + case 5: + svga->bpp = 16; + break; + case 7: + svga->bpp = 24; + break; + case 13: + svga->bpp = 32; + break; + default: + svga->bpp = 8; + break; + } + } + break; + + default: + break; + } + 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); + if ((((svga->crtc[0x67] & 0xc) != 0xc) && (s3->chip >= S3_TRIO64V)) || (s3->chip < S3_TRIO64V)) + svga->ma_latch |= (s3->ma_ext << 16); + } else { + svga->fullchange = svga->monitor->mon_changeframecount; + svga_recalctimings(svga); + } + } + } + break; + + default: + break; + } + svga_out(addr, val, svga); } static uint8_t -s3_in(uint16_t addr, void *p) +s3_in(uint16_t addr, void *priv) { - s3_t *s3 = (s3_t *)p; - svga_t *svga = &s3->svga; - int rs2, rs3; - uint8_t temp; + s3_t *s3 = (s3_t *) priv; + svga_t *svga = &s3->svga; + int rs2; + int rs3; + uint8_t temp; - if (((addr & 0xfff0) == 0x3d0 || (addr & 0xfff0) == 0x3b0) && !(svga->miscout & 1)) - addr ^= 0x60; + if (((addr & 0xfff0) == 0x3d0 || (addr & 0xfff0) == 0x3b0) && !(svga->miscout & 1)) + addr ^= 0x60; - switch (addr) - { - case 0x3c1: - if (svga->attraddr > 0x14) - return 0xff; - break; - - case 0x3c2: - if (s3->chip <= S3_86C924) - return svga_in(addr, svga) | 0x10; - break; + switch (addr) { + case 0x3c1: + if (svga->attraddr > 0x14) + return 0xff; + break; - case 0x3c5: - if (svga->seqaddr >= 0x10 && svga->seqaddr < 0x20) { - temp = svga->seqregs[svga->seqaddr]; - /* This is needed for the Intel Advanced/ATX's built-in S3 Trio64V+ BIOS to not - get stuck in an infinite loop. */ - if ((s3->card_type == S3_PHOENIX_TRIO64VPLUS_ONBOARD) && (svga->seqaddr == 0x17)) - svga->seqregs[svga->seqaddr] ^= 0x01; - return temp; - } - break; - - case 0x3c6: case 0x3c7: case 0x3c8: case 0x3c9: - rs2 = (svga->crtc[0x55] & 0x01) || !!(svga->crtc[0x43] & 2); - if (s3->chip >= S3_TRIO32) - return svga_in(addr, svga); - else if ((s3->chip == S3_VISION964 && s3->card_type != S3_ELSAWIN2KPROX_964) || (s3->chip == S3_86C928)) { - rs3 = !!(svga->crtc[0x55] & 0x02); - return bt48x_ramdac_in(addr, rs2, rs3, svga->ramdac, svga); - } else if ((s3->chip == S3_VISION964 && s3->card_type == S3_ELSAWIN2KPROX_964) || (s3->chip == S3_VISION968 && (s3->card_type == S3_ELSAWIN2KPROX || - s3->card_type == S3_PHOENIX_VISION968 || s3->card_type == S3_NUMBER9_9FX_771))) - return ibm_rgb528_ramdac_in(addr, rs2, svga->ramdac, svga); - else if ((s3->chip == S3_VISION968 && (s3->card_type == S3_SPEA_MERCURY_P64V || s3->card_type == S3_MIROVIDEO40SV_ERGO_968))) { - rs3 = !!(svga->crtc[0x55] & 0x02); - return tvp3026_ramdac_in(addr, rs2, rs3, svga->ramdac, svga); - } else if (((s3->chip == S3_86C801) || (s3->chip == S3_86C805)) && (s3->card_type != S3_MIROCRYSTAL10SD_805 && s3->card_type != S3_MIROCRYSTAL8S_805)) - return att49x_ramdac_in(addr, rs2, svga->ramdac, svga); - else if (s3->chip <= S3_86C924) - return sc1148x_ramdac_in(addr, rs2, svga->ramdac, svga); - else if (s3->card_type == S3_NUMBER9_9FX_531) - return att498_ramdac_in(addr, rs2, svga->ramdac, svga); - else if ((s3->chip == S3_86C928PCI) && (s3->card_type == S3_SPEA_MERCURY_LITE_PCI)) - return sc1502x_ramdac_in(addr, svga->ramdac, svga); - else - return sdac_ramdac_in(addr, rs2, svga->ramdac, svga); - break; + case 0x3c2: + if (s3->chip <= S3_86C924) + return svga_in(addr, svga) | 0x10; + break; - case 0x3d4: - return svga->crtcreg; - case 0x3d5: - switch (svga->crtcreg) - { - case 0x2d: return (s3->chip == S3_TRIO64V2) ? 0x89 : 0x88; /*Extended chip ID*/ - case 0x2e: return s3->id_ext; /*New chip ID*/ - case 0x2f: return (s3->chip == S3_TRIO64V) ? 0x40 : 0; /*Revision level*/ - case 0x30: return s3->id; /*Chip ID*/ - case 0x31: return (svga->crtc[0x31] & 0xcf) | ((s3->ma_ext & 3) << 4); - case 0x35: return (svga->crtc[0x35] & 0xf0) | (s3->bank & 0xf); - case 0x45: s3->hwc_col_stack_pos = 0; break; - case 0x51: return (svga->crtc[0x51] & 0xf0) | ((s3->bank >> 2) & 0xc) | ((s3->ma_ext >> 2) & 3); - case 0x5c: /* General Output Port Register */ - temp = svga->crtc[svga->crtcreg] & 0xa0; - if (((svga->miscout >> 2) & 3) == 3) - temp |= svga->crtc[0x42] & 0x0f; - else - temp |= ((svga->miscout >> 2) & 3); - if ((temp & 0xa0) == 0xa0) { - if ((svga->crtc[0x5c] & 0x40) && i2c_gpio_get_scl(s3->i2c)) - temp |= 0x40; - if ((svga->crtc[0x5c] & 0x10) && i2c_gpio_get_sda(s3->i2c)) - temp |= 0x10; - } - return temp; - case 0x69: return s3->ma_ext; - case 0x6a: return s3->bank; - /* Phoenix S3 video BIOS'es seem to expect CRTC registers 6B and 6C - to be mirrors of 59 and 5A. */ - case 0x6b: - if (s3->chip != S3_TRIO64V2) { - if (svga->crtc[0x53] & 0x08) { - return (s3->chip == S3_TRIO64V) ? (svga->crtc[0x59] & 0xfc) : (svga->crtc[0x59] & 0xfe); - } else { - return svga->crtc[0x59]; - } - } else - return svga->crtc[0x6b]; - break; - case 0x6c: - if (s3->chip != S3_TRIO64V2) { - if (svga->crtc[0x53] & 0x08) { - return 0x00; - } else - return (svga->crtc[0x5a] & 0x80); - } else - return svga->crtc[0x6c]; - break; - } - return svga->crtc[svga->crtcreg]; - } - return svga_in(addr, svga); + case 0x3c5: + if (svga->seqaddr >= 0x10 && svga->seqaddr < 0x20) { + temp = svga->seqregs[svga->seqaddr]; + /* This is needed for the Intel Advanced/ATX's built-in S3 Trio64V+ BIOS to not + get stuck in an infinite loop. */ + if ((s3->card_type == S3_PHOENIX_TRIO64VPLUS_ONBOARD) && (svga->seqaddr == 0x17)) + svga->seqregs[svga->seqaddr] ^= 0x01; + return temp; + } + break; + + case 0x3c6: + case 0x3c7: + case 0x3c8: + case 0x3c9: + rs2 = (svga->crtc[0x55] & 0x01) || !!(svga->crtc[0x43] & 2); + if (s3->chip >= S3_TRIO32) + return svga_in(addr, svga); + else if ((s3->chip == S3_VISION964 && s3->card_type != S3_ELSAWIN2KPROX_964) || (s3->chip == S3_86C928)) { + rs3 = !!(svga->crtc[0x55] & 0x02); + return bt48x_ramdac_in(addr, rs2, rs3, svga->ramdac, svga); + } else if ((s3->chip == S3_VISION964 && s3->card_type == S3_ELSAWIN2KPROX_964) || (s3->chip == S3_VISION968 && (s3->card_type == S3_ELSAWIN2KPROX || s3->card_type == S3_PHOENIX_VISION968 || s3->card_type == S3_NUMBER9_9FX_771))) + return ibm_rgb528_ramdac_in(addr, rs2, svga->ramdac, svga); + else if (s3->chip == S3_VISION968 && (s3->card_type == S3_SPEA_MERCURY_P64V || s3->card_type == S3_MIROVIDEO40SV_ERGO_968)) { + rs3 = !!(svga->crtc[0x55] & 0x02); + return tvp3026_ramdac_in(addr, rs2, rs3, svga->ramdac, svga); + } else if (((s3->chip == S3_86C801) || (s3->chip == S3_86C805)) && (s3->card_type != S3_MIROCRYSTAL10SD_805 && s3->card_type != S3_MIROCRYSTAL8S_805)) + return att49x_ramdac_in(addr, rs2, svga->ramdac, svga); + else if (s3->chip <= S3_86C924) + return sc1148x_ramdac_in(addr, rs2, svga->ramdac, svga); + else if (s3->card_type == S3_NUMBER9_9FX_531) + return att498_ramdac_in(addr, rs2, svga->ramdac, svga); + else if ((s3->chip == S3_86C928PCI) && (s3->card_type == S3_SPEA_MERCURY_LITE_PCI)) + return sc1502x_ramdac_in(addr, svga->ramdac, svga); + else + return sdac_ramdac_in(addr, rs2, svga->ramdac, svga); + + case 0x3d4: + return svga->crtcreg; + case 0x3d5: + switch (svga->crtcreg) { + case 0x2d: + return (s3->chip == S3_TRIO64V2) ? 0x89 : 0x88; /*Extended chip ID*/ + case 0x2e: + return s3->id_ext; /*New chip ID*/ + case 0x2f: + return (s3->chip == S3_TRIO64V) ? 0x40 : 0; /*Revision level*/ + case 0x30: + return s3->id; /*Chip ID*/ + case 0x31: + return (svga->crtc[0x31] & 0xcf) | ((s3->ma_ext & 3) << 4); + case 0x35: + return (svga->crtc[0x35] & 0xf0) | (s3->bank & 0xf); + case 0x45: + s3->hwc_col_stack_pos = 0; + break; + case 0x51: + return (svga->crtc[0x51] & 0xf0) | ((s3->bank >> 2) & 0xc) | ((s3->ma_ext >> 2) & 3); + case 0x5c: /* General Output Port Register */ + temp = svga->crtc[svga->crtcreg] & 0xa0; + if (((svga->miscout >> 2) & 3) == 3) + temp |= svga->crtc[0x42] & 0x0f; + else + temp |= ((svga->miscout >> 2) & 3); + if ((temp & 0xa0) == 0xa0) { + if ((svga->crtc[0x5c] & 0x40) && i2c_gpio_get_scl(s3->i2c)) + temp |= 0x40; + if ((svga->crtc[0x5c] & 0x10) && i2c_gpio_get_sda(s3->i2c)) + temp |= 0x10; + } + return temp; + case 0x69: + return s3->ma_ext; + case 0x6a: + return s3->bank; + /* Phoenix S3 video BIOS'es seem to expect CRTC registers 6B and 6C + to be mirrors of 59 and 5A. */ + case 0x6b: + if (s3->chip != S3_TRIO64V2) { + if (svga->crtc[0x53] & 0x08) { + return (s3->chip == S3_TRIO64V) ? (svga->crtc[0x59] & 0xfc) : (svga->crtc[0x59] & 0xfe); + } else { + return svga->crtc[0x59]; + } + } else + return svga->crtc[0x6b]; + case 0x6c: + if (s3->chip != S3_TRIO64V2) { + if (svga->crtc[0x53] & 0x08) { + return 0x00; + } else + return (svga->crtc[0x5a] & 0x80); + } else + return svga->crtc[0x6c]; + + default: + break; + } + return svga->crtc[svga->crtcreg]; + + default: + break; + } + return svga_in(addr, svga); } -static void s3_recalctimings(svga_t *svga) +static void +s3_recalctimings(svga_t *svga) { - s3_t *s3 = (s3_t *)svga->p; - int clk_sel = (svga->miscout >> 2) & 3; + s3_t *s3 = (s3_t *) svga->priv; + int clk_sel = (svga->miscout >> 2) & 3; - if (!svga->scrblank && svga->attr_palette_enable) { - if ((svga->gdcreg[6] & 1) || (svga->attrregs[0x10] & 1)) { - if (svga->crtc[0x3a] & 0x10) { /*256+ color register*/ - svga->gdcreg[5] |= 0x40; - } - } - } - - svga->ma_latch |= (s3->ma_ext << 16); - if (s3->chip >= S3_86C928) { - svga->hdisp = svga->hdisp_old; - - if (svga->crtc[0x5d] & 0x01) svga->htotal |= 0x100; - if (svga->crtc[0x5d] & 0x02) { - svga->hdisp_time |= 0x100; - svga->hdisp |= 0x100 * ((svga->seqregs[1] & 8) ? 16 : 8); - } - if (svga->crtc[0x5e] & 0x01) svga->vtotal |= 0x400; - if (svga->crtc[0x5e] & 0x02) svga->dispend |= 0x400; - if (svga->crtc[0x5e] & 0x04) svga->vblankstart |= 0x400; - if (svga->crtc[0x5e] & 0x10) svga->vsyncstart |= 0x400; - if (svga->crtc[0x5e] & 0x40) svga->split |= 0x400; - if (svga->crtc[0x51] & 0x30) svga->rowoffset |= (svga->crtc[0x51] & 0x30) << 4; - else if (svga->crtc[0x43] & 0x04) svga->rowoffset |= 0x100; - } - if (!svga->rowoffset) svga->rowoffset = 256; - - if ((s3->chip == S3_VISION964) || (s3->chip == S3_86C928)) { - if (s3->card_type == S3_ELSAWIN2KPROX_964) - ibm_rgb528_recalctimings(svga->ramdac, svga); - else - bt48x_recalctimings(svga->ramdac, svga); - } else if (s3->chip == S3_VISION968) { - if (s3->card_type == S3_SPEA_MERCURY_P64V || s3->card_type == S3_MIROVIDEO40SV_ERGO_968) - tvp3026_recalctimings(svga->ramdac, svga); - else - ibm_rgb528_recalctimings(svga->ramdac, svga); - } else - svga->interlace = !!(svga->crtc[0x42] & 0x20); - - if ((((svga->miscout >> 2) & 3) == 3) && s3->chip < S3_TRIO32) - clk_sel = svga->crtc[0x42] & 0x0f; - - svga->clock = (cpuclock * (double)(1ull << 32)) / svga->getclock(clk_sel, svga->clock_gen); - - switch (svga->crtc[0x67] >> 4) { - case 3: case 5: case 7: - svga->clock /= 2; - break; - } - - svga->lowres = !((svga->gdcreg[5] & 0x40) && (svga->crtc[0x3a] & 0x10)); - - if (s3->card_type == S3_MIROCRYSTAL10SD_805 || s3->card_type == S3_MIROCRYSTAL20SD_864 || - s3->card_type == S3_MIROCRYSTAL20SV_964 || s3->card_type == S3_SPEA_MIRAGE_86C801 || - s3->card_type == S3_SPEA_MIRAGE_86C805 || s3->card_type == S3_MIROCRYSTAL8S_805 || - s3->card_type == S3_NUMBER9_9FX_531 || s3->card_type == S3_SPEA_MERCURY_LITE_PCI) { - if (!(svga->crtc[0x5e] & 0x04)) - svga->vblankstart = svga->dispend; - if (svga->bpp != 32) { - if (svga->crtc[0x31] & 2) /*This is needed if the pixel width gets set with delays*/ - s3->width = 2048; - else { - if (s3->card_type == S3_MIROCRYSTAL10SD_805) { - if (svga->hdisp == 1280 && s3->width == 1024) { - s3->width = 1280; - } - } - } - } else { - if (s3->card_type == S3_NUMBER9_9FX_531) { - if (svga->hdisp == 1600 && s3->width == 1600) - s3->width = 800; - } - } - } else if (s3->chip == S3_86C928) { - if (svga->bpp == 15) { - if (s3->width == 800) - s3->width = 1024; - } - } - - if ((svga->crtc[0x43] & 0x08) && (s3->color_16bit == 0) && (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->color_16bit = 0; - if (s3->chip <= S3_86C924) { - if (s3->accel.advfunc_cntl & 4) - s3->width = 1024; - else - s3->width = 640; - } - } - - if ((svga->gdcreg[5] & 0x40) && (svga->crtc[0x3a] & 0x10)) { - svga->fb_only = 1; - switch (svga->bpp) { - case 8: - svga->render = svga_render_8bpp_highres; - if (s3->chip != S3_VISION868) { - if (s3->chip == S3_86C928) { - if (s3->width == 2048 || s3->width == 1280 || s3->width == 1600) - svga->hdisp <<= 1; - } else if ((s3->chip != S3_86C801) && (s3->chip != S3_86C805) && (s3->chip != S3_TRIO32) && - (s3->chip != S3_TRIO64) && (s3->chip != S3_VISION964) && (s3->chip != S3_VISION968)) { - if (s3->width == 1280 || s3->width == 1600) - svga->hdisp <<= 1; - } else if (s3->card_type == S3_SPEA_MERCURY_P64V) { - if (s3->width == 1280 || s3->width == 1600) - svga->hdisp <<= 1; - } else if (s3->card_type == S3_NUMBER9_9FX_771) - svga->hdisp <<= 1; - - if (s3->card_type == S3_MIROVIDEO40SV_ERGO_968 || s3->card_type == S3_MIROCRYSTAL20SD_864 || - s3->card_type == S3_PHOENIX_VISION968 || s3->card_type == S3_SPEA_MERCURY_P64V) { - if (svga->hdisp != 1408) - svga->hdisp = s3->width; - if (s3->card_type == S3_MIROCRYSTAL20SD_864) { - if (s3->width == 2048 || s3->width == 1600 || s3->width == 800) { - switch (svga->dispend) { - case 400: - case 480: - svga->hdisp = 640; - break; - - case 576: - svga->hdisp = 768; - break; - - case 600: - if (s3->width == 1600) - s3->width = 800; - svga->hdisp = 800; - break; - - case 768: - svga->hdisp = 1024; - break; - - case 864: - svga->hdisp = 1152; - break; - - case 1024: - if (svga->vtotal == 1066) - svga->hdisp = 1280; - break; - } - } - } - } - if (s3->card_type == S3_MIROCRYSTAL10SD_805 || s3->card_type == S3_MIROCRYSTAL8S_805) { - if (svga->rowoffset == 256 && (((svga->crtc[0x51] & 0x30) == 0x00 && !(svga->crtc[0x43] & 0x04)))) - svga->rowoffset >>= 1; - } - } - break; - case 15: - svga->render = svga_render_15bpp_highres; - if ((s3->chip != S3_VISION964) && (s3->card_type != S3_SPEA_MIRAGE_86C801) && - (s3->card_type != S3_SPEA_MIRAGE_86C805)) { - if (s3->chip == S3_86C928) - svga->hdisp <<= 1; - else if (s3->chip != S3_VISION968) - svga->hdisp >>= 1; - } - if ((s3->chip != S3_VISION868) && (s3->chip != S3_TRIO32) && - (s3->chip != S3_TRIO64) && (s3->chip != S3_VISION964)) { - if (s3->width == 1280 || s3->width == 1600) - svga->hdisp <<= 1; - else if (s3->card_type == S3_NUMBER9_9FX_771) - svga->hdisp <<= 1; - } - if (s3->card_type == S3_MIROVIDEO40SV_ERGO_968 || s3->card_type == S3_PHOENIX_VISION968 || - s3->card_type == S3_SPEA_MERCURY_P64V) { - if (svga->hdisp == (1408*2)) - svga->hdisp >>= 1; - else - svga->hdisp = s3->width; - } - - if (s3->card_type == S3_SPEA_MIRAGE_86C801 || s3->card_type == S3_SPEA_MIRAGE_86C805 || - s3->card_type == S3_SPEA_MERCURY_LITE_PCI) - svga->hdisp = s3->width; - break; - case 16: - svga->render = svga_render_16bpp_highres; - if ((s3->chip != S3_VISION964) && (s3->card_type != S3_SPEA_MIRAGE_86C801) && - (s3->card_type != S3_SPEA_MIRAGE_86C805)) { - if (s3->chip == S3_86C928) - svga->hdisp <<= 1; - else if (s3->chip != S3_VISION968) - svga->hdisp >>= 1; - } else if ((s3->card_type == S3_SPEA_MIRAGE_86C801) || (s3->card_type == S3_SPEA_MIRAGE_86C805)) - svga->hdisp >>= 1; - if ((s3->chip != S3_VISION868) && (s3->chip != S3_TRIO32) && - (s3->chip != S3_TRIO64) && (s3->chip != S3_VISION964)) { - if (s3->width == 1280 || s3->width == 1600) - svga->hdisp <<= 1; - else if (s3->card_type == S3_NUMBER9_9FX_771) - svga->hdisp <<= 1; - } - if (s3->card_type == S3_MIROVIDEO40SV_ERGO_968 || s3->card_type == S3_PHOENIX_VISION968 || - s3->card_type == S3_SPEA_MERCURY_P64V) { - if (svga->hdisp == (1408*2)) - svga->hdisp >>= 1; - else - svga->hdisp = s3->width; - } - - if (s3->card_type == S3_SPEA_MIRAGE_86C801 || s3->card_type == S3_SPEA_MIRAGE_86C805 || - s3->card_type == S3_SPEA_MERCURY_LITE_PCI) - svga->hdisp = s3->width; - break; - case 24: - svga->render = svga_render_24bpp_highres; - if (s3->chip != S3_VISION968) { - if (s3->chip != S3_86C928 && s3->chip != S3_86C801 && s3->chip != S3_86C805) - svga->hdisp /= 3; - else - svga->hdisp = (svga->hdisp * 2) / 3; - - if (s3->card_type == S3_SPEA_MERCURY_LITE_PCI) { - if (s3->width == 2048) - switch (svga->dispend) { - case 480: - svga->hdisp = 640; - break; - } - } - } else { - if (s3->card_type == S3_MIROVIDEO40SV_ERGO_968 || s3->card_type == S3_PHOENIX_VISION968 || - s3->card_type == S3_SPEA_MERCURY_P64V) - svga->hdisp = s3->width; - } - break; - case 32: - svga->render = svga_render_32bpp_highres; - if ((s3->chip < S3_TRIO32) && (s3->chip != S3_VISION964) && - (s3->chip != S3_VISION968) && (s3->chip != S3_86C928)) { - if (s3->chip == S3_VISION868) - svga->hdisp >>= 1; - else - svga->hdisp >>= 2; - } - if (s3->width == 1280 || s3->width == 1600 || (s3->card_type == S3_SPEA_MERCURY_P64V || - s3->card_type == S3_NUMBER9_9FX_771)) - svga->hdisp <<= 1; - if (s3->card_type == S3_MIROVIDEO40SV_ERGO_968 || s3->card_type == S3_MIROCRYSTAL20SV_964 || - s3->card_type == S3_MIROCRYSTAL20SD_864 || s3->card_type == S3_PHOENIX_VISION968 || - s3->card_type == S3_SPEA_MERCURY_P64V) { - svga->hdisp = s3->width; - if (s3->card_type == S3_MIROCRYSTAL20SD_864 || s3->card_type == S3_MIROCRYSTAL20SV_964) { - if (s3->width == 800 || s3->width == 1024 || s3->width == 1600) { - switch (svga->dispend) { - case 400: - case 480: - svga->hdisp = 640; - break; - - case 576: - if (s3->width == 1600) - s3->width = 800; - svga->hdisp = 768; - break; - - case 600: - if (s3->width == 1600) - s3->width = 800; - svga->hdisp = 800; - break; - } - } - } - } - break; - } - } else { - svga->fb_only = 0; - if (!svga->scrblank && svga->attr_palette_enable) { - if ((svga->gdcreg[6] & 1) || (svga->attrregs[0x10] & 1)) { - if ((svga->crtc[0x31] & 0x08) && ((svga->gdcreg[5] & 0x60) == 0x00)) { - if (svga->bpp == 8) { - svga->render = svga_render_8bpp_highres; /*Enhanced 4bpp mode, just like the 8bpp mode per spec.*/ - if (svga->hdisp <= 1024) - s3->width = 1024; - } - } - } else { - if (s3->chip <= S3_86C924) - s3->width = 1024; - } - } - } -} - -static void s3_trio64v_recalctimings(svga_t *svga) -{ - s3_t *s3 = (s3_t *)svga->p; - int clk_sel = (svga->miscout >> 2) & 3; - - if (!svga->scrblank && svga->attr_palette_enable) { - if ((svga->gdcreg[6] & 1) || (svga->attrregs[0x10] & 1)) { - if (svga->crtc[0x3a] & 0x10) /*256+ color register*/ - svga->gdcreg[5] |= 0x40; - } - } - svga->hdisp = svga->hdisp_old; - if (svga->crtc[0x5d] & 0x01) svga->htotal |= 0x100; - if (svga->crtc[0x5d] & 0x02) { - svga->hdisp_time |= 0x100; - svga->hdisp |= 0x100 * ((svga->seqregs[1] & 8) ? 16 : 8); - } - if (svga->crtc[0x5e] & 0x01) svga->vtotal |= 0x400; - if (svga->crtc[0x5e] & 0x02) svga->dispend |= 0x400; - if (svga->crtc[0x5e] & 0x04) svga->vblankstart |= 0x400; - if (svga->crtc[0x5e] & 0x10) svga->vsyncstart |= 0x400; - if (svga->crtc[0x5e] & 0x40) svga->split |= 0x400; - svga->interlace = svga->crtc[0x42] & 0x20; - - svga->clock = (cpuclock * (double)(1ull << 32)) / svga->getclock(clk_sel, svga->clock_gen); - - if ((svga->crtc[0x67] & 0xc) != 0xc) /*VGA mode*/ - { - svga->ma_latch |= (s3->ma_ext << 16); - if (svga->crtc[0x51] & 0x30) svga->rowoffset |= (svga->crtc[0x51] & 0x30) << 4; - else if (svga->crtc[0x43] & 0x04) svga->rowoffset |= 0x100; - if (!svga->rowoffset) svga->rowoffset = 256; - - svga->lowres = !((svga->gdcreg[5] & 0x40) && (svga->crtc[0x3a] & 0x10)); - - if ((svga->gdcreg[5] & 0x40) && (svga->crtc[0x3a] & 0x10)) { - svga->fb_only = 1; - switch (svga->bpp) { - case 8: - svga->render = svga_render_8bpp_highres; - break; - case 15: - svga->render = svga_render_15bpp_highres; - svga->hdisp >>= 1; - break; - case 16: - svga->render = svga_render_16bpp_highres; - svga->hdisp >>= 1; - break; - case 24: - svga->render = svga_render_24bpp_highres; - svga->hdisp /= 3; - break; - case 32: - svga->render = svga_render_32bpp_highres; - break; - } - } else - svga->fb_only = 0; - } - else /*Streams mode*/ - { - svga->fb_only = 1; - - if (s3->streams.buffer_ctrl & 1) - svga->ma_latch = s3->streams.pri_fb1 >> 2; - else - svga->ma_latch = s3->streams.pri_fb0 >> 2; - - svga->hdisp = s3->streams.pri_w + 1; - if (s3->streams.pri_h < svga->dispend) - svga->dispend = s3->streams.pri_h; - - svga->overlay.x = s3->streams.sec_x - s3->streams.pri_x; - svga->overlay.y = s3->streams.sec_y - s3->streams.pri_y; - svga->overlay.ysize = s3->streams.sec_h; - - if (s3->streams.buffer_ctrl & 2) - svga->overlay.addr = s3->streams.sec_fb1; - else - svga->overlay.addr = s3->streams.sec_fb0; - - svga->overlay.ena = (svga->overlay.x >= 0); - svga->overlay.v_acc = s3->streams.dda_vert_accumulator; - svga->rowoffset = s3->streams.pri_stride >> 3; - - switch ((s3->streams.pri_ctrl >> 24) & 0x7) - { - case 0: /*RGB-8 (CLUT)*/ - svga->render = svga_render_8bpp_highres; - break; - case 3: /*KRGB-16 (1.5.5.5)*/ - svga->htotal >>= 1; - svga->render = svga_render_15bpp_highres; - break; - case 5: /*RGB-16 (5.6.5)*/ - svga->htotal >>= 1; - svga->render = svga_render_16bpp_highres; - break; - case 6: /*RGB-24 (8.8.8)*/ - svga->render = svga_render_24bpp_highres; - break; - case 7: /*XRGB-32 (X.8.8.8)*/ - svga->render = svga_render_32bpp_highres; - break; - } + if (!svga->scrblank && svga->attr_palette_enable) { + if ((svga->gdcreg[6] & 1) || (svga->attrregs[0x10] & 1)) { + if (svga->crtc[0x3a] & 0x10) { /*256+ color register*/ + svga->gdcreg[5] |= 0x40; + } } + } + + svga->ma_latch |= (s3->ma_ext << 16); + if (s3->chip >= S3_86C928) { + svga->hdisp = svga->hdisp_old; + + if (svga->crtc[0x5d] & 0x01) + svga->htotal |= 0x100; + if (svga->crtc[0x5d] & 0x02) { + svga->hdisp_time |= 0x100; + svga->hdisp |= 0x100 * ((svga->seqregs[1] & 8) ? 16 : 8); + } + if (svga->crtc[0x5e] & 0x01) + svga->vtotal |= 0x400; + if (svga->crtc[0x5e] & 0x02) + svga->dispend |= 0x400; + if (svga->crtc[0x5e] & 0x04) + svga->vblankstart |= 0x400; + if (svga->crtc[0x5e] & 0x10) + svga->vsyncstart |= 0x400; + if (svga->crtc[0x5e] & 0x40) + svga->split |= 0x400; + if (s3->accel.advfunc_cntl & 0x01) + svga->split = 0x7fff; + if (svga->crtc[0x51] & 0x30) + svga->rowoffset |= (svga->crtc[0x51] & 0x30) << 4; + else if (svga->crtc[0x43] & 0x04) + svga->rowoffset |= 0x100; + } + if (!svga->rowoffset) + svga->rowoffset = 0x100; + + if ((s3->chip == S3_VISION964) || (s3->chip == S3_86C928)) { + if (s3->card_type == S3_ELSAWIN2KPROX_964) + ibm_rgb528_recalctimings(svga->ramdac, svga); + else + bt48x_recalctimings(svga->ramdac, svga); + } else if (s3->chip == S3_VISION968) { + if (s3->card_type == S3_SPEA_MERCURY_P64V || s3->card_type == S3_MIROVIDEO40SV_ERGO_968) + tvp3026_recalctimings(svga->ramdac, svga); + else + ibm_rgb528_recalctimings(svga->ramdac, svga); + } else + svga->interlace = !!(svga->crtc[0x42] & 0x20); + + if ((((svga->miscout >> 2) & 3) == 3) && s3->chip < S3_TRIO32) + clk_sel = svga->crtc[0x42] & 0x0f; + + svga->clock = (cpuclock * (double) (1ULL << 32)) / svga->getclock(clk_sel, svga->clock_gen); + + switch (svga->crtc[0x67] >> 4) { + case 3: + case 5: + case 7: + svga->clock /= 2; + break; + + default: + break; + } + + svga->lowres = !((svga->gdcreg[5] & 0x40) && (svga->crtc[0x3a] & 0x10)); + + if (s3->card_type == S3_MIROCRYSTAL10SD_805 || s3->card_type == S3_MIROCRYSTAL20SD_864 || s3->card_type == S3_MIROCRYSTAL20SV_964 || s3->card_type == S3_SPEA_MIRAGE_86C801 || s3->card_type == S3_SPEA_MIRAGE_86C805 || s3->card_type == S3_MIROCRYSTAL8S_805 || s3->card_type == S3_NUMBER9_9FX_531 || s3->card_type == S3_SPEA_MERCURY_LITE_PCI) { + if (!(svga->crtc[0x5e] & 0x04)) + svga->vblankstart = svga->dispend; + if (svga->bpp != 32) { + if (svga->crtc[0x31] & 2) /*This is needed if the pixel width gets set with delays*/ + s3->width = 2048; + else { + if (s3->card_type == S3_MIROCRYSTAL10SD_805) { + if (svga->hdisp == 1280 && s3->width == 1024) { + s3->width = 1280; + } + } + } + } else { + if (s3->card_type == S3_NUMBER9_9FX_531) { + if ((svga->hdisp == 1600) && (s3->width == 1600)) + s3->width = 800; + } + } + } else if (s3->chip == S3_86C928) { + if (svga->bpp == 15) { + if (s3->width == 800) + s3->width = 1024; + } + } + + 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 && (s3->chip <= S3_86C805)) { + s3->color_16bit = 0; + if (s3->chip <= S3_86C924) { + if (s3->accel.advfunc_cntl & 4) + s3->width = 1024; + else + s3->width = 640; + } + } + + if ((svga->gdcreg[5] & 0x40) && (svga->crtc[0x3a] & 0x10)) { + switch (svga->bpp) { + case 8: + svga->render = svga_render_8bpp_highres; + if (s3->chip != S3_VISION868) { + if (s3->chip == S3_86C928) { + if (s3->width == 2048 || s3->width == 1280 || s3->width == 1600) { + if ((s3->width != 1600) && (svga->dispend == 1024) && (svga->hdisp != 1280)) + svga->hdisp <<= 2; + else + svga->hdisp <<= 1; + } + } else if ((s3->chip != S3_86C801) && (s3->chip != S3_86C805) && (s3->chip != S3_TRIO32) && (s3->chip != S3_TRIO64) && (s3->chip != S3_VISION964) && (s3->chip != S3_VISION968)) { + if (s3->width == 1280 || s3->width == 1600) + svga->hdisp <<= 1; + } else if ((s3->card_type == S3_ELSAWIN2KPROX_964) || (s3->card_type == S3_ELSAWIN2KPROX)) { + if (s3->width == 1280 || s3->width == 1600) + svga->hdisp <<= 1; + } else if (s3->card_type == S3_SPEA_MERCURY_P64V) { + if (s3->width == 1280 || s3->width == 1600) + svga->hdisp <<= 1; + } else if (s3->card_type == S3_NUMBER9_9FX_771) + svga->hdisp <<= 1; + + if (s3->card_type == S3_MIROVIDEO40SV_ERGO_968 || s3->card_type == S3_MIROCRYSTAL20SD_864 || s3->card_type == S3_PHOENIX_VISION968 || s3->card_type == S3_SPEA_MERCURY_P64V) { + if (svga->hdisp != 1408) + svga->hdisp = s3->width; + if (s3->card_type == S3_MIROCRYSTAL20SD_864) { + if (s3->width == 2048 || s3->width == 1600 || s3->width == 800) { + switch (svga->dispend) { + case 400: + case 480: + svga->hdisp = 640; + break; + + case 576: + svga->hdisp = 768; + break; + + case 600: + if (s3->width == 1600) + s3->width = 800; + svga->hdisp = 800; + break; + + case 768: + svga->hdisp = 1024; + break; + + case 864: + svga->hdisp = 1152; + break; + + case 1024: + if (svga->vtotal == 1066) + svga->hdisp = 1280; + break; + + default: + break; + } + } + } + } + if (s3->card_type == S3_MIROCRYSTAL10SD_805 || s3->card_type == S3_MIROCRYSTAL8S_805) { + if (svga->rowoffset == 256 && ((svga->crtc[0x51] & 0x30) == 0x00 && !(svga->crtc[0x43] & 0x04))) + svga->rowoffset >>= 1; + } + } + break; + case 15: + svga->render = svga_render_15bpp_highres; + if ((s3->chip != S3_VISION964) && (s3->card_type != S3_SPEA_MIRAGE_86C801) && (s3->card_type != S3_SPEA_MIRAGE_86C805)) { + if (s3->chip == S3_86C928) + svga->hdisp <<= 1; + else if (s3->chip != S3_VISION968) + svga->hdisp >>= 1; + } + if ((s3->chip != S3_VISION868) && (s3->chip != S3_TRIO32) && (s3->chip != S3_TRIO64) && (s3->chip != S3_VISION964)) { + if (s3->width == 1280 || s3->width == 1600) + svga->hdisp <<= 1; + else if (s3->card_type == S3_NUMBER9_9FX_771) + svga->hdisp <<= 1; + } + if (s3->card_type == S3_MIROVIDEO40SV_ERGO_968 || s3->card_type == S3_PHOENIX_VISION968 || s3->card_type == S3_SPEA_MERCURY_P64V) { + if (svga->hdisp == (1408 * 2)) + svga->hdisp >>= 1; + else + svga->hdisp = s3->width; + } + + if (s3->card_type == S3_SPEA_MIRAGE_86C801 || s3->card_type == S3_SPEA_MIRAGE_86C805 || s3->card_type == S3_SPEA_MERCURY_LITE_PCI) + svga->hdisp = s3->width; + break; + case 16: + svga->render = svga_render_16bpp_highres; + if ((s3->card_type == S3_ELSAWIN2KPROX_964) || (s3->card_type == S3_ELSAWIN2KPROX)) { + if (s3->width == 1280 || s3->width == 1600) + svga->hdisp <<= 1; + } + if ((s3->chip != S3_VISION964) && (s3->card_type != S3_SPEA_MIRAGE_86C801) && (s3->card_type != S3_SPEA_MIRAGE_86C805)) { + if (s3->chip == S3_86C928) + svga->hdisp <<= 1; + else if (s3->chip != S3_VISION968) + svga->hdisp >>= 1; + } else if ((s3->card_type == S3_SPEA_MIRAGE_86C801) || (s3->card_type == S3_SPEA_MIRAGE_86C805)) + svga->hdisp >>= 1; + if ((s3->chip != S3_VISION868) && (s3->chip != S3_TRIO32) && (s3->chip != S3_TRIO64) && (s3->chip != S3_VISION964)) { + if (s3->width == 1280 || s3->width == 1600) + svga->hdisp <<= 1; + else if (s3->card_type == S3_NUMBER9_9FX_771) + svga->hdisp <<= 1; + } + if (s3->card_type == S3_MIROVIDEO40SV_ERGO_968 || s3->card_type == S3_PHOENIX_VISION968 || s3->card_type == S3_SPEA_MERCURY_P64V) { + if (svga->hdisp == (1408 * 2)) + svga->hdisp >>= 1; + else + svga->hdisp = s3->width; + } + + if (s3->card_type == S3_SPEA_MIRAGE_86C801 || s3->card_type == S3_SPEA_MIRAGE_86C805 || s3->card_type == S3_SPEA_MERCURY_LITE_PCI) + svga->hdisp = s3->width; + break; + case 24: + svga->render = svga_render_24bpp_highres; + if (s3->chip != S3_VISION968) { + if (s3->chip != S3_86C928 && s3->chip != S3_86C801 && s3->chip != S3_86C805) + svga->hdisp /= 3; + else + svga->hdisp = (svga->hdisp * 2) / 3; + + if (s3->card_type == S3_SPEA_MERCURY_LITE_PCI) { + if (s3->width == 2048) + switch (svga->dispend) { + case 480: + svga->hdisp = 640; + break; + + default: + break; + } + } + } else { + if (s3->card_type == S3_MIROVIDEO40SV_ERGO_968 || s3->card_type == S3_PHOENIX_VISION968 || s3->card_type == S3_SPEA_MERCURY_P64V) + svga->hdisp = s3->width; + } + break; + case 32: + svga->render = svga_render_32bpp_highres; + if ((s3->chip < S3_TRIO32) && (s3->chip != S3_VISION964) && (s3->chip != S3_VISION968) && (s3->chip != S3_86C928)) { + if (s3->chip == S3_VISION868) + svga->hdisp >>= 1; + else + svga->hdisp >>= 2; + } + if (s3->width == 1280 || s3->width == 1600 || (s3->card_type == S3_SPEA_MERCURY_P64V || s3->card_type == S3_NUMBER9_9FX_771)) + svga->hdisp <<= 1; + if (s3->card_type == S3_NUMBER9_9FX_771) { + if (svga->hdisp == 832) + svga->hdisp -= 32; + } + if (s3->card_type == S3_MIROVIDEO40SV_ERGO_968 || s3->card_type == S3_MIROCRYSTAL20SV_964 || s3->card_type == S3_MIROCRYSTAL20SD_864 || s3->card_type == S3_PHOENIX_VISION968 || s3->card_type == S3_SPEA_MERCURY_P64V) { + svga->hdisp = s3->width; + if (s3->card_type == S3_MIROCRYSTAL20SD_864 || s3->card_type == S3_MIROCRYSTAL20SV_964) { + if (s3->width == 800 || s3->width == 1024 || s3->width == 1600) { + switch (svga->dispend) { + case 400: + case 480: + svga->hdisp = 640; + break; + + case 576: + if (s3->width == 1600) + s3->width = 800; + svga->hdisp = 768; + break; + + case 600: + if (s3->width == 1600) + s3->width = 800; + svga->hdisp = 800; + break; + + default: + break; + } + } + } + } + break; + + default: + break; + } + } else { + if (!svga->scrblank && svga->attr_palette_enable) { + if ((svga->gdcreg[6] & 1) || (svga->attrregs[0x10] & 1)) { + if ((svga->crtc[0x31] & 0x08) && ((svga->gdcreg[5] & 0x60) == 0x00)) { + if (svga->bpp == 8) { + svga->render = svga_render_8bpp_highres; /*Enhanced 4bpp mode, just like the 8bpp mode per spec.*/ + if (svga->hdisp <= 1024) + s3->width = 1024; + } + } + } else { + if (s3->chip <= S3_86C924) + s3->width = 1024; + } + } + } +} + +static void +s3_trio64v_recalctimings(svga_t *svga) +{ + const s3_t *s3 = (s3_t *) svga->priv; + int clk_sel = (svga->miscout >> 2) & 3; + + if (!svga->scrblank && svga->attr_palette_enable) { + if ((svga->gdcreg[6] & 1) || (svga->attrregs[0x10] & 1)) { + if (svga->crtc[0x3a] & 0x10) /*256+ color register*/ + svga->gdcreg[5] |= 0x40; + } + } + svga->hdisp = svga->hdisp_old; + if (svga->crtc[0x5d] & 0x01) + svga->htotal |= 0x100; + if (svga->crtc[0x5d] & 0x02) { + svga->hdisp_time |= 0x100; + svga->hdisp |= 0x100 * ((svga->seqregs[1] & 8) ? 16 : 8); + } + if (svga->crtc[0x5e] & 0x01) + svga->vtotal |= 0x400; + if (svga->crtc[0x5e] & 0x02) + svga->dispend |= 0x400; + if (svga->crtc[0x5e] & 0x04) + svga->vblankstart |= 0x400; + if (svga->crtc[0x5e] & 0x10) + svga->vsyncstart |= 0x400; + if (svga->crtc[0x5e] & 0x40) + svga->split |= 0x400; + svga->interlace = svga->crtc[0x42] & 0x20; + + svga->clock = (cpuclock * (double) (1ULL << 32)) / svga->getclock(clk_sel, svga->clock_gen); + + if ((svga->crtc[0x67] & 0xc) != 0xc) /*VGA mode*/ + { + svga->ma_latch |= (s3->ma_ext << 16); + if (svga->crtc[0x51] & 0x30) + svga->rowoffset |= (svga->crtc[0x51] & 0x30) << 4; + else if (svga->crtc[0x43] & 0x04) + svga->rowoffset |= 0x100; + if (!svga->rowoffset) + svga->rowoffset = 256; + + svga->lowres = !((svga->gdcreg[5] & 0x40) && (svga->crtc[0x3a] & 0x10)); + + if ((svga->gdcreg[5] & 0x40) && (svga->crtc[0x3a] & 0x10)) { + switch (svga->bpp) { + case 8: + svga->render = svga_render_8bpp_highres; + break; + case 15: + svga->render = svga_render_15bpp_highres; + svga->hdisp >>= 1; + break; + case 16: + svga->render = svga_render_16bpp_highres; + svga->hdisp >>= 1; + break; + case 24: + svga->render = svga_render_24bpp_highres; + svga->hdisp /= 3; + break; + case 32: + svga->render = svga_render_32bpp_highres; + break; + + default: + break; + } + } + } else /*Streams mode*/ + { + if (s3->streams.buffer_ctrl & 1) + svga->ma_latch = s3->streams.pri_fb1 >> 2; + else + svga->ma_latch = s3->streams.pri_fb0 >> 2; + + svga->hdisp = s3->streams.pri_w + 1; + if (s3->streams.pri_h < svga->dispend) + svga->dispend = s3->streams.pri_h; + + svga->overlay.x = s3->streams.sec_x - s3->streams.pri_x; + svga->overlay.y = s3->streams.sec_y - s3->streams.pri_y; + svga->overlay.cur_ysize = s3->streams.sec_h; + + if (s3->streams.buffer_ctrl & 2) + svga->overlay.addr = s3->streams.sec_fb1; + else + svga->overlay.addr = s3->streams.sec_fb0; + + svga->overlay.ena = (svga->overlay.x >= 0); + svga->overlay.v_acc = s3->streams.dda_vert_accumulator; + svga->rowoffset = s3->streams.pri_stride >> 3; + + switch ((s3->streams.pri_ctrl >> 24) & 0x7) { + case 0: /*RGB-8 (CLUT)*/ + svga->render = svga_render_8bpp_highres; + break; + case 3: /*KRGB-16 (1.5.5.5)*/ + svga->htotal >>= 1; + svga->render = svga_render_15bpp_highres; + break; + case 5: /*RGB-16 (5.6.5)*/ + svga->htotal >>= 1; + svga->render = svga_render_16bpp_highres; + break; + case 6: /*RGB-24 (8.8.8)*/ + svga->render = svga_render_24bpp_highres; + break; + case 7: /*XRGB-32 (X.8.8.8)*/ + svga->render = svga_render_32bpp_highres; + break; + + default: + break; + } + } } static void s3_updatemapping(s3_t *s3) { - svga_t *svga = &s3->svga; + svga_t *svga = &s3->svga; - if (s3->pci && !(s3->pci_regs[PCI_REG_COMMAND] & PCI_COMMAND_MEM)) - { - mem_mapping_disable(&svga->mapping); - mem_mapping_disable(&s3->linear_mapping); - mem_mapping_disable(&s3->mmio_mapping); - mem_mapping_disable(&s3->new_mmio_mapping); - return; - } + if (s3->pci && !(s3->pci_regs[PCI_REG_COMMAND] & PCI_COMMAND_MEM)) { + mem_mapping_disable(&svga->mapping); + mem_mapping_disable(&s3->linear_mapping); + mem_mapping_disable(&s3->mmio_mapping); + mem_mapping_disable(&s3->new_mmio_mapping); + return; + } - /*Banked framebuffer*/ - if (svga->crtc[0x31] & 0x08) /*Enhanced mode mappings*/ - { - /* Enhanced mode forces 64kb at 0xa0000*/ - mem_mapping_set_addr(&svga->mapping, 0xa0000, 0x10000); - svga->banked_mask = 0xffff; - } - else switch (svga->gdcreg[6] & 0xc) /*VGA mapping*/ - { - case 0x0: /*128k at A0000*/ - mem_mapping_set_addr(&svga->mapping, 0xa0000, 0x20000); - svga->banked_mask = 0xffff; - break; - case 0x4: /*64k at A0000*/ - mem_mapping_set_addr(&svga->mapping, 0xa0000, 0x10000); - svga->banked_mask = 0xffff; - break; - case 0x8: /*32k at B0000*/ - mem_mapping_set_addr(&svga->mapping, 0xb0000, 0x08000); - svga->banked_mask = 0x7fff; - break; - case 0xC: /*32k at B8000*/ - mem_mapping_set_addr(&svga->mapping, 0xb8000, 0x08000); - svga->banked_mask = 0x7fff; - break; - } + /*Banked framebuffer*/ + if (svga->crtc[0x31] & 0x08) /*Enhanced mode mappings*/ + { + /* Enhanced mode forces 64kb at 0xa0000*/ + mem_mapping_set_addr(&svga->mapping, 0xa0000, 0x10000); + svga->banked_mask = 0xffff; + } else + switch (svga->gdcreg[6] & 0xc) { /*VGA mapping*/ + case 0x0: /*128k at A0000*/ + mem_mapping_set_addr(&svga->mapping, 0xa0000, 0x20000); + svga->banked_mask = 0xffff; + break; + case 0x4: /*64k at A0000*/ + mem_mapping_set_addr(&svga->mapping, 0xa0000, 0x10000); + svga->banked_mask = 0xffff; + break; + case 0x8: /*32k at B0000*/ + mem_mapping_set_addr(&svga->mapping, 0xb0000, 0x08000); + svga->banked_mask = 0x7fff; + break; + case 0xC: /*32k at B8000*/ + mem_mapping_set_addr(&svga->mapping, 0xb8000, 0x08000); + svga->banked_mask = 0x7fff; + break; - if (s3->chip >= S3_86C928) { - s3->linear_base = (svga->crtc[0x5a] << 16) | (svga->crtc[0x59] << 24); + default: + break; + } - if (s3->chip >= S3_86C928 && s3->chip <= S3_86C805) { - if (s3->vlb) - s3->linear_base &= 0x03ffffff; - else - s3->linear_base &= 0x00ffffff; - } + if (s3->chip >= S3_86C928) { + s3->linear_base = (svga->crtc[0x5a] << 16) | (svga->crtc[0x59] << 24); - if ((svga->crtc[0x58] & 0x10) || (s3->accel.advfunc_cntl & 0x10)) - { - /*Linear framebuffer*/ - mem_mapping_disable(&svga->mapping); + if (s3->chip >= S3_86C928 && s3->chip <= S3_86C805) { + if (s3->vlb) + s3->linear_base &= 0x03ffffff; + else + s3->linear_base &= 0x00ffffff; + } - switch (svga->crtc[0x58] & 3) - { - case 0: /*64k*/ - s3->linear_size = 0x10000; - break; - case 1: /*1mb*/ - s3->linear_size = 0x100000; - break; - case 2: /*2mb*/ - s3->linear_size = 0x200000; - break; - case 3: /*8mb*/ - switch (s3->chip) { /* Not on video cards that don't support 4MB*/ - case S3_TRIO64: - case S3_TRIO64V: - case S3_TRIO64V2: - case S3_86C928: - case S3_86C928PCI: - s3->linear_size = 0x400000; - break; - default: - s3->linear_size = 0x800000; - break; - } - break; - } - s3->linear_base &= ~(s3->linear_size - 1); - if (s3->linear_base == 0xa0000) { - mem_mapping_disable(&s3->linear_mapping); - if (!(svga->crtc[0x53] & 0x10)) { - mem_mapping_set_addr(&svga->mapping, s3->linear_base, 0x10000); - svga->banked_mask = 0xffff; - } - } else { - if (s3->chip >= S3_TRIO64V) { - s3->linear_base &= 0xfc000000; - } else if (s3->chip == S3_VISION968 || s3->chip == S3_VISION868) { - s3->linear_base &= 0xfe000000; - } - - mem_mapping_set_addr(&s3->linear_mapping, s3->linear_base, s3->linear_size); - } - } else { - mem_mapping_disable(&s3->linear_mapping); - } + if ((svga->crtc[0x58] & 0x10) || (s3->accel.advfunc_cntl & 0x10)) { + /*Linear framebuffer*/ + mem_mapping_disable(&svga->mapping); - /* Memory mapped I/O. */ - if ((svga->crtc[0x53] & 0x10) || (s3->accel.advfunc_cntl & 0x20)) { - mem_mapping_disable(&svga->mapping); - if (s3->chip >= S3_TRIO64V) { - if (svga->crtc[0x53] & 0x20) - mem_mapping_set_addr(&s3->mmio_mapping, 0xb8000, 0x8000); - else - mem_mapping_set_addr(&s3->mmio_mapping, 0xa0000, 0x10000); - } else { - mem_mapping_enable(&s3->mmio_mapping); - } - } else { - mem_mapping_disable(&s3->mmio_mapping); - } - - /* New MMIO. */ - if (svga->crtc[0x53] & 0x08) - mem_mapping_set_addr(&s3->new_mmio_mapping, s3->linear_base + 0x1000000, 0x20000); - else - mem_mapping_disable(&s3->new_mmio_mapping); - } + switch (svga->crtc[0x58] & 3) { + case 0: /*64k*/ + s3->linear_size = 0x10000; + break; + case 1: /*1mb*/ + s3->linear_size = 0x100000; + break; + case 2: /*2mb*/ + s3->linear_size = 0x200000; + break; + case 3: /*8mb*/ + switch (s3->chip) { /* Not on video cards that don't support 4MB*/ + case S3_TRIO64: + case S3_TRIO64V: + case S3_TRIO64V2: + case S3_86C928: + case S3_86C928PCI: + s3->linear_size = 0x400000; + break; + default: + s3->linear_size = 0x800000; + break; + } + break; + + default: + break; + } + s3->linear_base &= ~(s3->linear_size - 1); + if (s3->linear_base == 0xa0000) { + mem_mapping_disable(&s3->linear_mapping); + if (!(svga->crtc[0x53] & 0x10)) { + mem_mapping_set_addr(&svga->mapping, s3->linear_base, 0x10000); + svga->banked_mask = 0xffff; + } + } else { + if (s3->chip >= S3_TRIO64V) { + s3->linear_base &= 0xfc000000; + } else if (s3->chip == S3_VISION968 || s3->chip == S3_VISION868) { + s3->linear_base &= 0xfe000000; + } + + mem_mapping_set_addr(&s3->linear_mapping, s3->linear_base, s3->linear_size); + } + svga->fb_only = 1; + } else { + svga->fb_only = 0; + mem_mapping_disable(&s3->linear_mapping); + } + + /* Memory mapped I/O. */ + if ((svga->crtc[0x53] & 0x10) || (s3->accel.advfunc_cntl & 0x20)) { + mem_mapping_disable(&svga->mapping); + if (s3->chip >= S3_TRIO64V) { + if (svga->crtc[0x53] & 0x20) + mem_mapping_set_addr(&s3->mmio_mapping, 0xb8000, 0x8000); + else + mem_mapping_set_addr(&s3->mmio_mapping, 0xa0000, 0x10000); + } + mem_mapping_enable(&s3->mmio_mapping); + } else { + mem_mapping_disable(&s3->mmio_mapping); + } + + /* New MMIO. */ + if (svga->crtc[0x53] & 0x08) + mem_mapping_set_addr(&s3->new_mmio_mapping, s3->linear_base + 0x1000000, 0x20000); + else + mem_mapping_disable(&s3->new_mmio_mapping); + } } static float -s3_trio64_getclock(int clock, void *p) +s3_trio64_getclock(int clock, void *priv) { - s3_t *s3 = (s3_t *)p; - svga_t *svga = &s3->svga; - float t; - int m, n1, n2; - if (clock == 0) return 25175000.0; - if (clock == 1) return 28322000.0; - m = svga->seqregs[0x13] + 2; - n1 = (svga->seqregs[0x12] & 0x1f) + 2; - n2 = ((svga->seqregs[0x12] >> 5) & 0x07); - t = (14318184.0 * ((float)m / (float)n1)) / (float)(1 << n2); - return t; + const s3_t *s3 = (s3_t *) priv; + const svga_t *svga = &s3->svga; + float t; + int m; + int n1; + int n2; + + if (clock == 0) + return 25175000.0; + if (clock == 1) + return 28322000.0; + m = svga->seqregs[0x13] + 2; + n1 = (svga->seqregs[0x12] & 0x1f) + 2; + n2 = ((svga->seqregs[0x12] >> 5) & 0x07); + t = (14318184.0 * ((float) m / (float) n1)) / (float) (1 << n2); + return t; } static void -s3_accel_out(uint16_t port, uint8_t val, void *p) +s3_accel_out(uint16_t port, uint8_t val, void *priv) { - s3_t *s3 = (s3_t *)p; - svga_t *svga = &s3->svga; + s3_t *s3 = (s3_t *) priv; + svga_t *svga = &s3->svga; - if (port >= 0x8000) { - if (!s3->enable_8514) - return; + if (port >= 0x8000) { + if (!s3->enable_8514) + return; - if (s3_enable_fifo(s3)) - s3_queue(s3, port, val, FIFO_OUT_BYTE); - else - s3_accel_out_fifo(s3, port, val); - } else { - switch (port) - { - case 0x4148: case 0x42e8: - s3->subsys_stat &= ~val; - s3_update_irqs(s3); - break; - case 0x4149: case 0x42e9: - s3->subsys_cntl = val; - s3_update_irqs(s3); - break; - case 0x4548: case 0x46e8: - s3->accel.setup_md = val; - break; - case 0x4948: case 0x4ae8: - s3->accel.advfunc_cntl = val; - if ((s3->chip > S3_86C805) && ((svga->crtc[0x50] & 0xc1) == 0x80)) { - s3->width = (val & 4) ? 1600 : 800; - svga->fullchange = changeframecount; - svga_recalctimings(svga); - } else if (s3->chip <= S3_86C805) { - svga->fullchange = changeframecount; - svga_recalctimings(svga); - } - if (s3->chip > S3_86C924) - s3_updatemapping(s3); - break; - } - } + if (s3_enable_fifo(s3)) + s3_queue(s3, port, val, FIFO_OUT_BYTE); + else + s3_accel_out_fifo(s3, port, val); + } else { + switch (port) { + case 0x4148: + case 0x42e8: + s3->subsys_stat &= ~val; + s3_update_irqs(s3); + break; + case 0x4149: + case 0x42e9: + s3->subsys_cntl = val; + s3_update_irqs(s3); + break; + case 0x4548: + case 0x46e8: + s3->accel.setup_md = val; + break; + case 0x4948: + case 0x4ae8: + s3->accel.advfunc_cntl = val; + if ((s3->chip > S3_86C805) && ((svga->crtc[0x50] & 0xc1) == 0x80)) { + s3->width = (val & 4) ? 1600 : 800; + svga->fullchange = svga->monitor->mon_changeframecount; + svga_recalctimings(svga); + } else if (s3->chip <= S3_86C805) { + svga->fullchange = svga->monitor->mon_changeframecount; + svga_recalctimings(svga); + } + if (s3->chip > S3_86C924) + s3_updatemapping(s3); + break; + + default: + break; + } + } } static void -s3_accel_out_w(uint16_t port, uint16_t val, void *p) +s3_accel_out_w(uint16_t port, uint16_t val, void *priv) { - s3_t *s3 = (s3_t *)p; + s3_t *s3 = (s3_t *) priv; - if (!s3->enable_8514) - return; + if (!s3->enable_8514) + return; - if (s3_enable_fifo(s3)) - s3_queue(s3, port, val, FIFO_OUT_WORD); - else - s3_accel_out_fifo_w(s3, port, val); + if (s3_enable_fifo(s3)) + s3_queue(s3, port, val, FIFO_OUT_WORD); + else + s3_accel_out_fifo_w(s3, port, val); } static void -s3_accel_out_l(uint16_t port, uint32_t val, void *p) +s3_accel_out_l(uint16_t port, uint32_t val, void *priv) { - s3_t *s3 = (s3_t *)p; + s3_t *s3 = (s3_t *) priv; - if (!s3->enable_8514) - return; + if (!s3->enable_8514) + return; - if (s3_enable_fifo(s3)) - s3_queue(s3, port, val, FIFO_OUT_DWORD); - else - s3_accel_out_fifo_l(s3, port, val); + if (s3_enable_fifo(s3)) + s3_queue(s3, port, val, FIFO_OUT_DWORD); + else + s3_accel_out_fifo_l(s3, port, val); } static uint8_t -s3_accel_in(uint16_t port, void *p) +s3_accel_in(uint16_t port, void *priv) { - s3_t *s3 = (s3_t *)p; - svga_t *svga = &s3->svga; - int temp; + s3_t *s3 = (s3_t *) priv; + svga_t *svga = &s3->svga; + int temp; + uint8_t temp2; - if (!s3->enable_8514) - return 0xff; + if (!s3->enable_8514) + return 0xff; - switch (port) { - case 0x4148: case 0x42e8: - return s3->subsys_stat; - case 0x4149: case 0x42e9: - return s3->subsys_cntl; + switch (port) { + case 0x4148: + case 0x42e8: + return s3->subsys_stat; + case 0x4149: + case 0x42e9: + return s3->subsys_cntl; - case 0x8148: case 0x82e8: - if (s3_enable_fifo(s3)) - s3_wait_fifo_idle(s3); - return s3->accel.cur_y & 0xff; - case 0x8149: case 0x82e9: - if (s3_enable_fifo(s3)) - s3_wait_fifo_idle(s3); - return s3->accel.cur_y >> 8; + case 0x8148: + case 0x82e8: + if (s3_enable_fifo(s3)) + s3_wait_fifo_idle(s3); + return s3->accel.cur_y & 0xff; + case 0x8149: + case 0x82e9: + if (s3_enable_fifo(s3)) + s3_wait_fifo_idle(s3); + return s3->accel.cur_y >> 8; - case 0x8548: case 0x86e8: - if (s3_enable_fifo(s3)) - s3_wait_fifo_idle(s3); - return s3->accel.cur_x & 0xff; - case 0x8549: case 0x86e9: - if (s3_enable_fifo(s3)) - s3_wait_fifo_idle(s3); - return s3->accel.cur_x >> 8; + case 0x8548: + case 0x86e8: + if (s3_enable_fifo(s3)) + s3_wait_fifo_idle(s3); + return s3->accel.cur_x & 0xff; + case 0x8549: + case 0x86e9: + if (s3_enable_fifo(s3)) + s3_wait_fifo_idle(s3); + return s3->accel.cur_x >> 8; - case 0x8948: case 0x8ae8: - if (s3->chip >= S3_86C928) { - if (s3_enable_fifo(s3)) - s3_wait_fifo_idle(s3); - return s3->accel.desty_axstp & 0xff; - } - break; - case 0x8949: case 0x8ae9: - if (s3->chip >= S3_86C928) { - if (s3_enable_fifo(s3)) - s3_wait_fifo_idle(s3); - return s3->accel.desty_axstp >> 8; - } - break; - - case 0x8d48: case 0x8ee8: - if (s3->chip >= S3_86C928) { - if (s3_enable_fifo(s3)) - s3_wait_fifo_idle(s3); - return s3->accel.destx_distp & 0xff; - } - break; - case 0x8d49: case 0x8ee9: - if (s3->chip >= S3_86C928) { - if (s3_enable_fifo(s3)) - s3_wait_fifo_idle(s3); - return s3->accel.destx_distp >> 8; - } - break; + case 0x8948: + case 0x8ae8: + if (s3->chip >= S3_86C928) { + if (s3_enable_fifo(s3)) + s3_wait_fifo_idle(s3); + return s3->accel.desty_axstp & 0xff; + } + break; + case 0x8949: + case 0x8ae9: + if (s3->chip >= S3_86C928) { + if (s3_enable_fifo(s3)) + s3_wait_fifo_idle(s3); + return s3->accel.desty_axstp >> 8; + } + break; - case 0x9148: case 0x92e8: - if (s3_enable_fifo(s3)) - s3_wait_fifo_idle(s3); - return s3->accel.err_term & 0xff; - case 0x9149: case 0x92e9: - if (s3_enable_fifo(s3)) - s3_wait_fifo_idle(s3); - return s3->accel.err_term >> 8; + case 0x8d48: + case 0x8ee8: + if (s3->chip >= S3_86C928) { + if (s3_enable_fifo(s3)) + s3_wait_fifo_idle(s3); + return s3->accel.destx_distp & 0xff; + } + break; + case 0x8d49: + case 0x8ee9: + if (s3->chip >= S3_86C928) { + if (s3_enable_fifo(s3)) + s3_wait_fifo_idle(s3); + return s3->accel.destx_distp >> 8; + } + break; - case 0x9548: case 0x96e8: - if (s3->chip >= S3_86C928) { - return s3->accel.maj_axis_pcnt & 0xff; - } - break; - case 0x9549: case 0x96e9: - if (s3->chip >= S3_86C928) { - if (s3_enable_fifo(s3)) - s3_wait_fifo_idle(s3); - return s3->accel.maj_axis_pcnt >> 8; - } - break; + case 0x9148: + case 0x92e8: + if (s3_enable_fifo(s3)) + s3_wait_fifo_idle(s3); + return s3->accel.err_term & 0xff; + case 0x9149: + case 0x92e9: + if (s3_enable_fifo(s3)) + s3_wait_fifo_idle(s3); + return s3->accel.err_term >> 8; - case 0x8118: - case 0x9948: case 0x9ae8: - temp = 0; /* FIFO empty */ - if (s3_enable_fifo(s3)) { - if (!s3->blitter_busy) - wake_fifo_thread(s3); - if (FIFO_FULL) - temp = 0xff; - } - return temp; - case 0x8119: - case 0x9949: case 0x9ae9: - temp = 0; - if (s3_enable_fifo(s3)) { - if (!s3->blitter_busy) - wake_fifo_thread(s3); - - if (!FIFO_EMPTY || s3->force_busy) - temp |= 0x02; /*Hardware busy*/ - else - temp |= 0x04; /*FIFO empty*/ - s3->force_busy = 0; + case 0x9548: + case 0x96e8: + if (s3->chip >= S3_86C928) { + return s3->accel.maj_axis_pcnt & 0xff; + } + break; + case 0x9549: + case 0x96e9: + if (s3->chip >= S3_86C928) { + if (s3_enable_fifo(s3)) + s3_wait_fifo_idle(s3); + return s3->accel.maj_axis_pcnt >> 8; + } + break; - if (s3->chip >= S3_VISION964) { + case 0x8118: + case 0x9948: + case 0x9ae8: + temp = 0; /* FIFO empty */ + if (s3_enable_fifo(s3)) { + if (!s3->blitter_busy) + wake_fifo_thread(s3); if (FIFO_FULL) - temp |= 0xf8; /*FIFO full*/ - } + temp = 0xff; + } + return temp; + case 0x8119: + case 0x9949: + case 0x9ae9: + temp = 0; + if (s3_enable_fifo(s3)) { + if (!s3->blitter_busy) + wake_fifo_thread(s3); - if (s3->data_available) { - temp |= 0x01; /*Read Data available*/ - s3->data_available = 0; - } - } else { - if (s3->force_busy) { - temp |= 0x02; /*Hardware busy*/ - } - s3->force_busy = 0; - if (s3->data_available) { - temp |= 0x01; /*Read Data available*/ - s3->data_available = 0; - } - } - return temp; + if (!FIFO_EMPTY || s3->force_busy) + temp |= 0x02; /*Hardware busy*/ + else + temp |= 0x04; /*FIFO empty*/ + s3->force_busy = 0; - case 0x9d48: case 0x9ee8: - if (s3->chip >= S3_86C928) { - if (s3_enable_fifo(s3)) - s3_wait_fifo_idle(s3); - return s3->accel.short_stroke & 0xff; - } - break; - case 0x9d49: case 0x9ee9: - if (s3->chip >= S3_86C928) { - if (s3_enable_fifo(s3)) - s3_wait_fifo_idle(s3); - return s3->accel.short_stroke >> 8; - } - break; + if (s3->chip >= S3_VISION964) { + if (FIFO_FULL) + temp |= 0xf8; /*FIFO full*/ + } - case 0xa148: case 0xa2e8: - if (s3->chip >= S3_86C928) { - if (s3_enable_fifo(s3)) - s3_wait_fifo_idle(s3); - return s3->accel.bkgd_color & 0xff; - } - break; - case 0xa149: case 0xa2e9: - if (s3->chip >= S3_86C928) { - if (s3_enable_fifo(s3)) - s3_wait_fifo_idle(s3); - return s3->accel.bkgd_color >> 8; - } - break; - case 0xa14a: case 0xa2ea: - if (s3_enable_fifo(s3)) - s3_wait_fifo_idle(s3); - return s3->accel.bkgd_color >> 16; - case 0xa14b: case 0xa2eb: - if (s3_enable_fifo(s3)) - s3_wait_fifo_idle(s3); - return s3->accel.bkgd_color >> 24; + if (s3->data_available) { + temp |= 0x01; /*Read Data available*/ + s3->data_available = 0; + } + } else { + if (s3->force_busy) { + temp |= 0x02; /*Hardware busy*/ + } + s3->force_busy = 0; + if (s3->data_available) { + temp |= 0x01; /*Read Data available*/ + s3->data_available = 0; + } + } + return temp; - case 0xa548: case 0xa6e8: - if (s3->chip >= S3_86C928) { - if (s3_enable_fifo(s3)) - s3_wait_fifo_idle(s3); - return s3->accel.frgd_color & 0xff; - } - break; - case 0xa549: case 0xa6e9: - if (s3->chip >= S3_86C928) { - if (s3_enable_fifo(s3)) - s3_wait_fifo_idle(s3); - return s3->accel.frgd_color >> 8; - } - break; - case 0xa54a: case 0xa6ea: - if (s3_enable_fifo(s3)) - s3_wait_fifo_idle(s3); - return s3->accel.frgd_color >> 16; - case 0xa54b: case 0xa6eb: - if (s3_enable_fifo(s3)) - s3_wait_fifo_idle(s3); - return s3->accel.frgd_color >> 24; + case 0x9d48: + case 0x9ee8: + if (s3->chip >= S3_86C928) { + if (s3_enable_fifo(s3)) + s3_wait_fifo_idle(s3); + return s3->accel.short_stroke & 0xff; + } + break; + case 0x9d49: + case 0x9ee9: + if (s3->chip >= S3_86C928) { + if (s3_enable_fifo(s3)) + s3_wait_fifo_idle(s3); + return s3->accel.short_stroke >> 8; + } + break; - case 0xa948: case 0xaae8: - if (s3->chip >= S3_86C928) { - if (s3_enable_fifo(s3)) - s3_wait_fifo_idle(s3); - return s3->accel.wrt_mask & 0xff; - } - break; - case 0xa949: case 0xaae9: - if (s3->chip >= S3_86C928) { - if (s3_enable_fifo(s3)) - s3_wait_fifo_idle(s3); - return s3->accel.wrt_mask >> 8; - } - break; - case 0xa94a: case 0xaaea: - if (s3_enable_fifo(s3)) - s3_wait_fifo_idle(s3); - return s3->accel.wrt_mask >> 16; - case 0xa94b: case 0xaaeb: - if (s3_enable_fifo(s3)) - s3_wait_fifo_idle(s3); - return s3->accel.wrt_mask >> 24; + case 0xa148: + case 0xa2e8: + if (s3->chip >= S3_86C928) { + if (s3_enable_fifo(s3)) + s3_wait_fifo_idle(s3); + if ((s3->bpp == 3) && (s3->accel.multifunc[0xe] & 0x10) && !(s3->accel.multifunc[0xe] & 0x200)) + temp2 = s3->accel.bkgd_color >> 16; + else + temp2 = s3->accel.bkgd_color & 0xff; - case 0xad48: case 0xaee8: - if (s3->chip >= S3_86C928) { - if (s3_enable_fifo(s3)) - s3_wait_fifo_idle(s3); - return s3->accel.rd_mask & 0xff; - } - break; - case 0xad49: case 0xaee9: - if (s3_enable_fifo(s3)) - s3_wait_fifo_idle(s3); - return s3->accel.rd_mask >> 8; - case 0xad4a: case 0xaeea: - if (s3_enable_fifo(s3)) - s3_wait_fifo_idle(s3); - return s3->accel.rd_mask >> 16; - case 0xad4b: case 0xaeeb: - if (s3_enable_fifo(s3)) - s3_wait_fifo_idle(s3); - return s3->accel.rd_mask >> 24; + return temp2; + } + break; + case 0xa149: + case 0xa2e9: + if (s3->chip >= S3_86C928) { + if (s3_enable_fifo(s3)) + s3_wait_fifo_idle(s3); + if ((s3->bpp == 3) && (s3->accel.multifunc[0xe] & 0x10) && !(s3->accel.multifunc[0xe] & 0x200)) + temp2 = s3->accel.bkgd_color >> 24; + else + temp2 = s3->accel.bkgd_color >> 8; - case 0xb148: case 0xb2e8: - if (s3->chip >= S3_86C928) { - if (s3_enable_fifo(s3)) - s3_wait_fifo_idle(s3); - return s3->accel.color_cmp & 0xff; - } - break; - case 0xb149: case 0xb2e9: - if (s3->chip >= S3_86C928) { - if (s3_enable_fifo(s3)) - s3_wait_fifo_idle(s3); - return s3->accel.color_cmp >> 8; - } - break; - case 0xb14a: case 0xb2ea: - if (s3_enable_fifo(s3)) - s3_wait_fifo_idle(s3); - return s3->accel.color_cmp >> 16; - case 0xb14b: case 0xb2eb: - if (s3_enable_fifo(s3)) - s3_wait_fifo_idle(s3); - return s3->accel.color_cmp >> 24; + if (!(s3->accel.multifunc[0xe] & 0x200)) + s3->accel.multifunc[0xe] ^= 0x10; + return temp2; + } + break; + case 0xa14a: + case 0xa2ea: + if (s3_enable_fifo(s3)) + s3_wait_fifo_idle(s3); + if ((s3->bpp == 3) && (s3->accel.multifunc[0xe] & 0x10) && !(s3->accel.multifunc[0xe] & 0x200)) + temp2 = s3->accel.bkgd_color & 0xff; + else + temp2 = s3->accel.bkgd_color >> 16; - case 0xb548: case 0xb6e8: - if (s3->chip >= S3_86C928) { - if (s3_enable_fifo(s3)) - s3_wait_fifo_idle(s3); - return s3->accel.bkgd_mix; - } - break; + return temp2; + case 0xa14b: + case 0xa2eb: + if (s3_enable_fifo(s3)) + s3_wait_fifo_idle(s3); + if ((s3->bpp == 3) && (s3->accel.multifunc[0xe] & 0x10) && !(s3->accel.multifunc[0xe] & 0x200)) + temp2 = s3->accel.bkgd_color >> 8; + else + temp2 = s3->accel.bkgd_color >> 24; - case 0xb948: case 0xbae8: - if (s3->chip >= S3_86C928) { - if (s3_enable_fifo(s3)) - s3_wait_fifo_idle(s3); - return s3->accel.frgd_mix; - } - break; + if (!(s3->accel.multifunc[0xe] & 0x200)) + s3->accel.multifunc[0xe] ^= 0x10; + return temp2; + case 0xa548: + case 0xa6e8: + if (s3->chip >= S3_86C928) { + if (s3_enable_fifo(s3)) + s3_wait_fifo_idle(s3); + if ((s3->bpp == 3) && (s3->accel.multifunc[0xe] & 0x10) && !(s3->accel.multifunc[0xe] & 0x200)) + temp2 = s3->accel.frgd_color >> 16; + else + temp2 = s3->accel.frgd_color & 0xff; - case 0xbd48: case 0xbee8: - if (s3->chip >= S3_86C928) { - if (s3_enable_fifo(s3)) - s3_wait_fifo_idle(s3); - temp = s3->accel.multifunc[0xf] & 0xf; - switch (temp) - { - case 0x0: return s3->accel.multifunc[0x0] & 0xff; - case 0x1: return s3->accel.multifunc[0x1] & 0xff; - case 0x2: return s3->accel.multifunc[0x2] & 0xff; - case 0x3: return s3->accel.multifunc[0x3] & 0xff; - case 0x4: return s3->accel.multifunc[0x4] & 0xff; - case 0x5: return s3->accel.multifunc[0xa] & 0xff; - case 0x6: return s3->accel.multifunc[0xe] & 0xff; - case 0x7: return s3->accel.cmd & 0xff; - case 0x8: return s3->accel.subsys_cntl & 0xff; - case 0x9: return s3->accel.setup_md & 0xff; - case 0xa: return s3->accel.multifunc[0xd] & 0xff; - } - return 0xff; - } - break; - case 0xbd49: case 0xbee9: - if (s3->chip >= S3_86C928) { - if (s3_enable_fifo(s3)) - s3_wait_fifo_idle(s3); - temp = s3->accel.multifunc[0xf] & 0xf; - s3->accel.multifunc[0xf]++; - switch (temp) - { - case 0x0: return s3->accel.multifunc[0x0] >> 8; - case 0x1: return s3->accel.multifunc[0x1] >> 8; - case 0x2: return s3->accel.multifunc[0x2] >> 8; - case 0x3: return s3->accel.multifunc[0x3] >> 8; - case 0x4: return s3->accel.multifunc[0x4] >> 8; - case 0x5: return s3->accel.multifunc[0xa] >> 8; - case 0x6: return s3->accel.multifunc[0xe] >> 8; - case 0x7: return s3->accel.cmd >> 8; - case 0x8: return (s3->accel.subsys_cntl >> 8) & ~0xe000; - case 0x9: return (s3->accel.setup_md >> 8) & ~0xf000; - case 0xa: return s3->accel.multifunc[0xd] >> 8; - } - return 0xff; - } - break; + return temp2; + } + break; + case 0xa549: + case 0xa6e9: + if (s3->chip >= S3_86C928) { + if (s3_enable_fifo(s3)) + s3_wait_fifo_idle(s3); + if ((s3->bpp == 3) && (s3->accel.multifunc[0xe] & 0x10) && !(s3->accel.multifunc[0xe] & 0x200)) + temp2 = s3->accel.frgd_color >> 24; + else + temp2 = s3->accel.frgd_color >> 8; - case 0xd148: case 0xd2e8: - if (s3_enable_fifo(s3)) - s3_wait_fifo_idle(s3); - return s3->accel.ropmix & 0xff; + if (!(s3->accel.multifunc[0xe] & 0x200)) + s3->accel.multifunc[0xe] ^= 0x10; + return temp2; + } + break; + case 0xa54a: + case 0xa6ea: + if (s3_enable_fifo(s3)) + s3_wait_fifo_idle(s3); + if ((s3->bpp == 3) && (s3->accel.multifunc[0xe] & 0x10) && !(s3->accel.multifunc[0xe] & 0x200)) + temp2 = s3->accel.frgd_color & 0xff; + else + temp2 = s3->accel.frgd_color >> 16; - case 0xd149: case 0xd2e9: - if (s3_enable_fifo(s3)) - s3_wait_fifo_idle(s3); - return s3->accel.ropmix >> 8; + return temp2; + case 0xa54b: + case 0xa6eb: + if (s3_enable_fifo(s3)) + s3_wait_fifo_idle(s3); + if ((s3->bpp == 3) && (s3->accel.multifunc[0xe] & 0x10) && !(s3->accel.multifunc[0xe] & 0x200)) + temp2 = s3->accel.frgd_color >> 8; + else + temp2 = s3->accel.frgd_color >> 24; - case 0xe548: case 0xe6e8: - if (s3_enable_fifo(s3)) - s3_wait_fifo_idle(s3); - return s3->accel.pat_bg_color & 0xff; + if (!(s3->accel.multifunc[0xe] & 0x200)) + s3->accel.multifunc[0xe] ^= 0x10; + return temp2; - case 0xe549: case 0xe6e9: - if (s3_enable_fifo(s3)) - s3_wait_fifo_idle(s3); - return s3->accel.pat_bg_color >> 8; + case 0xa948: + case 0xaae8: + if (s3->chip >= S3_86C928) { + if (s3_enable_fifo(s3)) + s3_wait_fifo_idle(s3); + if ((s3->bpp == 3) && (s3->accel.multifunc[0xe] & 0x10) && !(s3->accel.multifunc[0xe] & 0x200)) + temp2 = s3->accel.wrt_mask >> 16; + else + temp2 = s3->accel.wrt_mask & 0xff; - case 0xe54a: case 0xe6ea: - if (s3_enable_fifo(s3)) - s3_wait_fifo_idle(s3); - return s3->accel.pat_bg_color >> 16; - - case 0xe54b: case 0xe6eb: - if (s3_enable_fifo(s3)) - s3_wait_fifo_idle(s3); - return s3->accel.pat_bg_color >> 24; + return temp2; + } + break; + case 0xa949: + case 0xaae9: + if (s3->chip >= S3_86C928) { + if (s3_enable_fifo(s3)) + s3_wait_fifo_idle(s3); + if ((s3->bpp == 3) && (s3->accel.multifunc[0xe] & 0x10) && !(s3->accel.multifunc[0xe] & 0x200)) + temp2 = s3->accel.wrt_mask >> 24; + else + temp2 = s3->accel.wrt_mask >> 8; - case 0xe948: case 0xeae8: - if (s3_enable_fifo(s3)) - s3_wait_fifo_idle(s3); - return s3->accel.pat_y & 0xff; + if (!(s3->accel.multifunc[0xe] & 0x200)) + s3->accel.multifunc[0xe] ^= 0x10; + return temp2; + } + break; + case 0xa94a: + case 0xaaea: + if (s3_enable_fifo(s3)) + s3_wait_fifo_idle(s3); + if ((s3->bpp == 3) && (s3->accel.multifunc[0xe] & 0x10) && !(s3->accel.multifunc[0xe] & 0x200)) + temp2 = s3->accel.wrt_mask & 0xff; + else + temp2 = s3->accel.wrt_mask >> 16; - case 0xe949: case 0xeae9: - if (s3_enable_fifo(s3)) - s3_wait_fifo_idle(s3); - return s3->accel.pat_y >> 8; - - case 0xe94a: case 0xeaea: - if (s3_enable_fifo(s3)) - s3_wait_fifo_idle(s3); - return s3->accel.pat_x & 0xff; - - case 0xe94b: case 0xeaeb: - if (s3_enable_fifo(s3)) - s3_wait_fifo_idle(s3); - return s3->accel.pat_x >> 8; + return temp2; + case 0xa94b: + case 0xaaeb: + if (s3_enable_fifo(s3)) + s3_wait_fifo_idle(s3); + if ((s3->bpp == 3) && (s3->accel.multifunc[0xe] & 0x10) && !(s3->accel.multifunc[0xe] & 0x200)) + temp2 = s3->accel.wrt_mask >> 8; + else + temp2 = s3->accel.wrt_mask >> 24; - case 0xed48: case 0xeee8: - if (s3_enable_fifo(s3)) - s3_wait_fifo_idle(s3); - return s3->accel.pat_fg_color & 0xff; + if (!(s3->accel.multifunc[0xe] & 0x200)) + s3->accel.multifunc[0xe] ^= 0x10; + return temp2; - case 0xed49: case 0xeee9: - if (s3_enable_fifo(s3)) - s3_wait_fifo_idle(s3); - return s3->accel.pat_fg_color >> 8; + case 0xad48: + case 0xaee8: + if (s3->chip >= S3_86C928) { + if (s3_enable_fifo(s3)) + s3_wait_fifo_idle(s3); + if ((s3->bpp == 3) && (s3->accel.multifunc[0xe] & 0x10) && !(s3->accel.multifunc[0xe] & 0x200)) + temp2 = s3->accel.rd_mask >> 16; + else + temp2 = s3->accel.rd_mask & 0xff; - case 0xed4a: case 0xeeea: - if (s3_enable_fifo(s3)) - s3_wait_fifo_idle(s3); - return s3->accel.pat_fg_color >> 16; - - case 0xed4b: case 0xeeeb: - if (s3_enable_fifo(s3)) - s3_wait_fifo_idle(s3); - return s3->accel.pat_fg_color >> 24; + return temp2; + } + break; + case 0xad49: + case 0xaee9: + if (s3->chip >= S3_86C928) { + if (s3_enable_fifo(s3)) + s3_wait_fifo_idle(s3); + if ((s3->bpp == 3) && (s3->accel.multifunc[0xe] & 0x10) && !(s3->accel.multifunc[0xe] & 0x200)) + temp2 = s3->accel.rd_mask >> 24; + else + temp2 = s3->accel.rd_mask >> 8; - case 0xe148: case 0xe2e8: - if (!s3_cpu_dest(s3)) - break; - READ_PIXTRANS_BYTE_IO(0) - if (s3->accel.cmd & 0x100) { - switch (s3->accel.cmd & 0x600) { - case 0x000: - if (((s3->accel.multifunc[0xa] & 0xc0) == 0x80) || (s3->accel.cmd & 2)) { - if (((s3->accel.frgd_mix & 0x60) != 0x40) || ((s3->accel.bkgd_mix & 0x60) != 0x40)) - s3_accel_start(8, 1, s3->accel.pix_trans[0], 0, s3); - else - s3_accel_start(1, 1, 0xffffffff, s3->accel.pix_trans[0], s3); - } else - s3_accel_start(1, 1, 0xffffffff, s3->accel.pix_trans[0], s3); - break; - case 0x200: - if (((s3->accel.multifunc[0xa] & 0xc0) == 0x80) || (s3->accel.cmd & 2)) { - if (((s3->accel.frgd_mix & 0x60) != 0x40) || ((s3->accel.bkgd_mix & 0x60) != 0x40)) - s3_accel_start(16, 1, s3->accel.pix_trans[0], 0, s3); - else - s3_accel_start(2, 1, 0xffffffff, s3->accel.pix_trans[0], s3); - } else { - s3_accel_start(2, 1, 0xffffffff, s3->accel.pix_trans[0], s3); - } - break; - } - } - return s3->accel.pix_trans[0]; - - case 0xe149: case 0xe2e9: - if (!s3_cpu_dest(s3)) - break; - READ_PIXTRANS_BYTE_IO(1); - if (s3->accel.cmd & 0x100) { - switch (s3->accel.cmd & 0x600) { - case 0x000: - if (((s3->accel.multifunc[0xa] & 0xc0) == 0x80) || (s3->accel.cmd & 2)) { - if (((s3->accel.frgd_mix & 0x60) != 0x40) || ((s3->accel.bkgd_mix & 0x60) != 0x40)) - s3_accel_start(8, 1, s3->accel.pix_trans[0] | (s3->accel.pix_trans[1] << 8), 0, s3); - else - s3_accel_start(1, 1, 0xffffffff, s3->accel.pix_trans[0] | (s3->accel.pix_trans[1] << 8), s3); - } else - s3_accel_start(1, 1, 0xffffffff, s3->accel.pix_trans[0] | (s3->accel.pix_trans[1] << 8), s3); - break; - case 0x200: - if (((s3->accel.multifunc[0xa] & 0xc0) == 0x80) || (s3->accel.cmd & 2)) { - if (((s3->accel.frgd_mix & 0x60) != 0x40) || ((s3->accel.bkgd_mix & 0x60) != 0x40)) { - if (s3->accel.cmd & 0x1000) - s3_accel_start(16, 1, s3->accel.pix_trans[1] | (s3->accel.pix_trans[0] << 8), 0, s3); - else - s3_accel_start(16, 1, s3->accel.pix_trans[0] | (s3->accel.pix_trans[1] << 8), 0, s3); - } else { - if (s3->accel.cmd & 0x1000) - s3_accel_start(2, 1, 0xffffffff, s3->accel.pix_trans[1] | (s3->accel.pix_trans[0] << 8), s3); - else - s3_accel_start(2, 1, 0xffffffff, s3->accel.pix_trans[0] | (s3->accel.pix_trans[1] << 8), s3); - } - } else { - if (s3->accel.cmd & 0x1000) - s3_accel_start(2, 1, 0xffffffff, s3->accel.pix_trans[1] | (s3->accel.pix_trans[0] << 8), s3); - else - s3_accel_start(2, 1, 0xffffffff, s3->accel.pix_trans[0] | (s3->accel.pix_trans[1] << 8), s3); - } - break; - } - } - return s3->accel.pix_trans[1]; - - case 0xe14a: case 0xe2ea: - if (!s3_cpu_dest(s3)) - break; - READ_PIXTRANS_BYTE_IO(2); - return s3->accel.pix_trans[2]; - - case 0xe14b: case 0xe2eb: - if (!s3_cpu_dest(s3)) - break; - READ_PIXTRANS_BYTE_IO(3) - if (s3->accel.cmd & 0x100) { - switch (s3->accel.cmd & 0x600) { - case 0x000: - if (((s3->accel.multifunc[0xa] & 0xc0) == 0x80) || (s3->accel.cmd & 2)) { - if (((s3->accel.frgd_mix & 0x60) != 0x40) || ((s3->accel.bkgd_mix & 0x60) != 0x40)) - s3_accel_start(8, 1, s3->accel.pix_trans[0] | (s3->accel.pix_trans[1] << 8) | (s3->accel.pix_trans[2] << 16) | (s3->accel.pix_trans[3] << 24), 0, s3); - else - s3_accel_start(1, 1, 0xffffffff, s3->accel.pix_trans[0] | (s3->accel.pix_trans[1] << 8) | (s3->accel.pix_trans[2] << 16) | (s3->accel.pix_trans[3] << 24), s3); - } else - s3_accel_start(1, 1, 0xffffffff, s3->accel.pix_trans[0] | (s3->accel.pix_trans[1] << 8) | (s3->accel.pix_trans[2] << 16) | (s3->accel.pix_trans[3] << 24), s3); - break; - case 0x200: - if (((s3->accel.multifunc[0xa] & 0xc0) == 0x80) || (s3->accel.cmd & 2)) { - if (((s3->accel.frgd_mix & 0x60) != 0x40) || ((s3->accel.bkgd_mix & 0x60) != 0x40)) - s3_accel_start(16, 1, s3->accel.pix_trans[0] | (s3->accel.pix_trans[1] << 8) | (s3->accel.pix_trans[2] << 16) | (s3->accel.pix_trans[3] << 24), 0, s3); - else - s3_accel_start(2, 1, 0xffffffff, s3->accel.pix_trans[0] | (s3->accel.pix_trans[1] << 8) | (s3->accel.pix_trans[2] << 16) | (s3->accel.pix_trans[3] << 24), s3); - } else - s3_accel_start(2, 1, 0xffffffff, s3->accel.pix_trans[0] | (s3->accel.pix_trans[1] << 8) | (s3->accel.pix_trans[2] << 16) | (s3->accel.pix_trans[3] << 24), s3); - break; - } - } - return s3->accel.pix_trans[3]; + if (!(s3->accel.multifunc[0xe] & 0x200)) + s3->accel.multifunc[0xe] ^= 0x10; + return temp2; + } + break; + case 0xad4a: + case 0xaeea: + if (s3_enable_fifo(s3)) + s3_wait_fifo_idle(s3); + if ((s3->bpp == 3) && (s3->accel.multifunc[0xe] & 0x10) && !(s3->accel.multifunc[0xe] & 0x200)) + temp2 = s3->accel.rd_mask & 0xff; + else + temp2 = s3->accel.rd_mask >> 16; - case 0xff20: case 0xff21: - temp = s3->serialport & ~(SERIAL_PORT_SCR | SERIAL_PORT_SDR); - if ((s3->serialport & SERIAL_PORT_SCW) && i2c_gpio_get_scl(s3->i2c)) - temp |= SERIAL_PORT_SCR; - if ((s3->serialport & SERIAL_PORT_SDW) && i2c_gpio_get_sda(s3->i2c)) - temp |= SERIAL_PORT_SDR; - return temp; - } - - return 0xff; + return temp2; + case 0xad4b: + case 0xaeeb: + if (s3_enable_fifo(s3)) + s3_wait_fifo_idle(s3); + if ((s3->bpp == 3) && (s3->accel.multifunc[0xe] & 0x10) && !(s3->accel.multifunc[0xe] & 0x200)) + temp2 = s3->accel.rd_mask >> 8; + else + temp2 = s3->accel.rd_mask >> 24; + + if (!(s3->accel.multifunc[0xe] & 0x200)) + s3->accel.multifunc[0xe] ^= 0x10; + return temp2; + + case 0xb148: + case 0xb2e8: + if (s3->chip >= S3_86C928) { + if (s3_enable_fifo(s3)) + s3_wait_fifo_idle(s3); + if ((s3->bpp == 3) && (s3->accel.multifunc[0xe] & 0x10) && !(s3->accel.multifunc[0xe] & 0x200)) + temp2 = s3->accel.color_cmp >> 16; + else + temp2 = s3->accel.color_cmp & 0xff; + + return temp2; + } + break; + case 0xb149: + case 0xb2e9: + if (s3->chip >= S3_86C928) { + if (s3_enable_fifo(s3)) + s3_wait_fifo_idle(s3); + if ((s3->bpp == 3) && (s3->accel.multifunc[0xe] & 0x10) && !(s3->accel.multifunc[0xe] & 0x200)) + temp2 = s3->accel.color_cmp >> 24; + else + temp2 = s3->accel.color_cmp >> 8; + + if (!(s3->accel.multifunc[0xe] & 0x200)) + s3->accel.multifunc[0xe] ^= 0x10; + return temp2; + } + break; + case 0xb14a: + case 0xb2ea: + if (s3_enable_fifo(s3)) + s3_wait_fifo_idle(s3); + if ((s3->bpp == 3) && (s3->accel.multifunc[0xe] & 0x10) && !(s3->accel.multifunc[0xe] & 0x200)) + temp2 = s3->accel.color_cmp & 0xff; + else + temp2 = s3->accel.color_cmp >> 16; + + return temp2; + case 0xb14b: + case 0xb2eb: + if (s3_enable_fifo(s3)) + s3_wait_fifo_idle(s3); + if ((s3->bpp == 3) && (s3->accel.multifunc[0xe] & 0x10) && !(s3->accel.multifunc[0xe] & 0x200)) + temp2 = s3->accel.color_cmp >> 8; + else + temp2 = s3->accel.color_cmp >> 24; + + if (!(s3->accel.multifunc[0xe] & 0x200)) + s3->accel.multifunc[0xe] ^= 0x10; + return temp2; + + case 0xb548: + case 0xb6e8: + if (s3->chip >= S3_86C928) { + if (s3_enable_fifo(s3)) + s3_wait_fifo_idle(s3); + return s3->accel.bkgd_mix; + } + break; + + case 0xb948: + case 0xbae8: + if (s3->chip >= S3_86C928) { + if (s3_enable_fifo(s3)) + s3_wait_fifo_idle(s3); + return s3->accel.frgd_mix; + } + break; + + case 0xbd48: + case 0xbee8: + if (s3->chip >= S3_86C928) { + if (s3_enable_fifo(s3)) + s3_wait_fifo_idle(s3); + temp = s3->accel.multifunc[0xf] & 0xf; + switch (temp) { + case 0x0: + return s3->accel.multifunc[0x0] & 0xff; + case 0x1: + return s3->accel.multifunc[0x1] & 0xff; + case 0x2: + return s3->accel.multifunc[0x2] & 0xff; + case 0x3: + return s3->accel.multifunc[0x3] & 0xff; + case 0x4: + return s3->accel.multifunc[0x4] & 0xff; + case 0x5: + return s3->accel.multifunc[0xa] & 0xff; + case 0x6: + return s3->accel.multifunc[0xe] & 0xff; + case 0x7: + return s3->accel.cmd & 0xff; + case 0x8: + return s3->accel.subsys_cntl & 0xff; + case 0x9: + return s3->accel.setup_md & 0xff; + case 0xa: + return s3->accel.multifunc[0xd] & 0xff; + + default: + break; + } + return 0xff; + } + break; + case 0xbd49: + case 0xbee9: + if (s3->chip >= S3_86C928) { + if (s3_enable_fifo(s3)) + s3_wait_fifo_idle(s3); + temp = s3->accel.multifunc[0xf] & 0xf; + s3->accel.multifunc[0xf]++; + switch (temp) { + case 0x0: + return s3->accel.multifunc[0x0] >> 8; + case 0x1: + return s3->accel.multifunc[0x1] >> 8; + case 0x2: + return s3->accel.multifunc[0x2] >> 8; + case 0x3: + return s3->accel.multifunc[0x3] >> 8; + case 0x4: + return s3->accel.multifunc[0x4] >> 8; + case 0x5: + return s3->accel.multifunc[0xa] >> 8; + case 0x6: + return s3->accel.multifunc[0xe] >> 8; + case 0x7: + return s3->accel.cmd >> 8; + case 0x8: + return (s3->accel.subsys_cntl >> 8) & ~0xe000; + case 0x9: + return (s3->accel.setup_md >> 8) & ~0xf000; + case 0xa: + return s3->accel.multifunc[0xd] >> 8; + + default: + break; + } + return 0xff; + } + break; + + case 0xd148: + case 0xd2e8: + if (s3_enable_fifo(s3)) + s3_wait_fifo_idle(s3); + return s3->accel.ropmix & 0xff; + + case 0xd149: + case 0xd2e9: + if (s3_enable_fifo(s3)) + s3_wait_fifo_idle(s3); + return s3->accel.ropmix >> 8; + + case 0xe548: + case 0xe6e8: + if (s3_enable_fifo(s3)) + s3_wait_fifo_idle(s3); + if ((s3->bpp == 3) && (s3->accel.multifunc[0xe] & 0x10) && !(s3->accel.multifunc[0xe] & 0x200)) + temp2 = s3->accel.pat_bg_color >> 16; + else + temp2 = s3->accel.pat_bg_color & 0xff; + + return temp2; + + case 0xe549: + case 0xe6e9: + if (s3_enable_fifo(s3)) + s3_wait_fifo_idle(s3); + if ((s3->bpp == 3) && (s3->accel.multifunc[0xe] & 0x10) && !(s3->accel.multifunc[0xe] & 0x200)) + temp2 = s3->accel.pat_bg_color >> 24; + else + temp2 = s3->accel.pat_bg_color >> 8; + + if (!(s3->accel.multifunc[0xe] & 0x200)) + s3->accel.multifunc[0xe] ^= 0x10; + return temp2; + + case 0xe54a: + case 0xe6ea: + if (s3_enable_fifo(s3)) + s3_wait_fifo_idle(s3); + if ((s3->bpp == 3) && (s3->accel.multifunc[0xe] & 0x10) && !(s3->accel.multifunc[0xe] & 0x200)) + temp2 = s3->accel.pat_bg_color & 0xff; + else + temp2 = s3->accel.pat_bg_color >> 16; + + return temp2; + + case 0xe54b: + case 0xe6eb: + if (s3_enable_fifo(s3)) + s3_wait_fifo_idle(s3); + if ((s3->bpp == 3) && (s3->accel.multifunc[0xe] & 0x10) && !(s3->accel.multifunc[0xe] & 0x200)) + temp2 = s3->accel.pat_bg_color >> 8; + else + temp2 = s3->accel.pat_bg_color >> 24; + + if (!(s3->accel.multifunc[0xe] & 0x200)) + s3->accel.multifunc[0xe] ^= 0x10; + return temp2; + + case 0xe948: + case 0xeae8: + if (s3_enable_fifo(s3)) + s3_wait_fifo_idle(s3); + return s3->accel.pat_y & 0xff; + + case 0xe949: + case 0xeae9: + if (s3_enable_fifo(s3)) + s3_wait_fifo_idle(s3); + return s3->accel.pat_y >> 8; + + case 0xe94a: + case 0xeaea: + if (s3_enable_fifo(s3)) + s3_wait_fifo_idle(s3); + return s3->accel.pat_x & 0xff; + + case 0xe94b: + case 0xeaeb: + if (s3_enable_fifo(s3)) + s3_wait_fifo_idle(s3); + return s3->accel.pat_x >> 8; + + case 0xed48: + case 0xeee8: + if (s3_enable_fifo(s3)) + s3_wait_fifo_idle(s3); + if ((s3->bpp == 3) && (s3->accel.multifunc[0xe] & 0x10) && !(s3->accel.multifunc[0xe] & 0x200)) + temp2 = s3->accel.pat_fg_color >> 16; + else + temp2 = s3->accel.pat_fg_color & 0xff; + + return temp2; + + case 0xed49: + case 0xeee9: + if (s3_enable_fifo(s3)) + s3_wait_fifo_idle(s3); + if ((s3->bpp == 3) && (s3->accel.multifunc[0xe] & 0x10) && !(s3->accel.multifunc[0xe] & 0x200)) + temp2 = s3->accel.pat_fg_color >> 24; + else + temp2 = s3->accel.pat_fg_color >> 8; + + if (!(s3->accel.multifunc[0xe] & 0x200)) + s3->accel.multifunc[0xe] ^= 0x10; + return temp2; + + case 0xed4a: + case 0xeeea: + if (s3_enable_fifo(s3)) + s3_wait_fifo_idle(s3); + if ((s3->bpp == 3) && (s3->accel.multifunc[0xe] & 0x10) && !(s3->accel.multifunc[0xe] & 0x200)) + temp2 = s3->accel.pat_fg_color & 0xff; + else + temp2 = s3->accel.pat_fg_color >> 16; + + return temp2; + + case 0xed4b: + case 0xeeeb: + if (s3_enable_fifo(s3)) + s3_wait_fifo_idle(s3); + if ((s3->bpp == 3) && (s3->accel.multifunc[0xe] & 0x10) && !(s3->accel.multifunc[0xe] & 0x200)) + temp2 = s3->accel.pat_fg_color >> 8; + else + temp2 = s3->accel.pat_fg_color >> 24; + + if (!(s3->accel.multifunc[0xe] & 0x200)) + s3->accel.multifunc[0xe] ^= 0x10; + return temp2; + + case 0xe148: + case 0xe2e8: + if (!s3_cpu_dest(s3)) + break; + READ_PIXTRANS_BYTE_IO(0) + if (s3->accel.cmd & 0x100) { + switch (s3->accel.cmd & 0x600) { + case 0x000: + if (((s3->accel.multifunc[0xa] & 0xc0) == 0x80) || (s3->accel.cmd & 2)) { + if (((s3->accel.frgd_mix & 0x60) != 0x40) || ((s3->accel.bkgd_mix & 0x60) != 0x40)) + s3_accel_start(8, 1, s3->accel.pix_trans[0], 0, s3); + else + s3_accel_start(1, 1, 0xffffffff, s3->accel.pix_trans[0], s3); + } else + s3_accel_start(1, 1, 0xffffffff, s3->accel.pix_trans[0], s3); + break; + case 0x200: + if (((s3->accel.multifunc[0xa] & 0xc0) == 0x80) || (s3->accel.cmd & 2)) { + if (((s3->accel.frgd_mix & 0x60) != 0x40) || ((s3->accel.bkgd_mix & 0x60) != 0x40)) + s3_accel_start(16, 1, s3->accel.pix_trans[0], 0, s3); + else + s3_accel_start(2, 1, 0xffffffff, s3->accel.pix_trans[0], s3); + } else { + s3_accel_start(2, 1, 0xffffffff, s3->accel.pix_trans[0], s3); + } + break; + + default: + break; + } + } + return s3->accel.pix_trans[0]; + + case 0xe149: + case 0xe2e9: + if (!s3_cpu_dest(s3)) + break; + READ_PIXTRANS_BYTE_IO(1); + if (s3->accel.cmd & 0x100) { + switch (s3->accel.cmd & 0x600) { + case 0x000: + if (((s3->accel.multifunc[0xa] & 0xc0) == 0x80) || (s3->accel.cmd & 2)) { + if (((s3->accel.frgd_mix & 0x60) != 0x40) || ((s3->accel.bkgd_mix & 0x60) != 0x40)) + s3_accel_start(8, 1, s3->accel.pix_trans[0] | (s3->accel.pix_trans[1] << 8), 0, s3); + else + s3_accel_start(1, 1, 0xffffffff, s3->accel.pix_trans[0] | (s3->accel.pix_trans[1] << 8), s3); + } else + s3_accel_start(1, 1, 0xffffffff, s3->accel.pix_trans[0] | (s3->accel.pix_trans[1] << 8), s3); + break; + case 0x200: + if (((s3->accel.multifunc[0xa] & 0xc0) == 0x80) || (s3->accel.cmd & 2)) { + if (((s3->accel.frgd_mix & 0x60) != 0x40) || ((s3->accel.bkgd_mix & 0x60) != 0x40)) { + if (s3->accel.cmd & 0x1000) + s3_accel_start(16, 1, s3->accel.pix_trans[1] | (s3->accel.pix_trans[0] << 8), 0, s3); + else + s3_accel_start(16, 1, s3->accel.pix_trans[0] | (s3->accel.pix_trans[1] << 8), 0, s3); + } else { + if (s3->accel.cmd & 0x1000) + s3_accel_start(2, 1, 0xffffffff, s3->accel.pix_trans[1] | (s3->accel.pix_trans[0] << 8), s3); + else + s3_accel_start(2, 1, 0xffffffff, s3->accel.pix_trans[0] | (s3->accel.pix_trans[1] << 8), s3); + } + } else { + if (s3->accel.cmd & 0x1000) + s3_accel_start(2, 1, 0xffffffff, s3->accel.pix_trans[1] | (s3->accel.pix_trans[0] << 8), s3); + else + s3_accel_start(2, 1, 0xffffffff, s3->accel.pix_trans[0] | (s3->accel.pix_trans[1] << 8), s3); + } + break; + + default: + break; + } + } + return s3->accel.pix_trans[1]; + + case 0xe14a: + case 0xe2ea: + if (!s3_cpu_dest(s3)) + break; + READ_PIXTRANS_BYTE_IO(2); + return s3->accel.pix_trans[2]; + + case 0xe14b: + case 0xe2eb: + if (!s3_cpu_dest(s3)) + break; + READ_PIXTRANS_BYTE_IO(3) + if (s3->accel.cmd & 0x100) { + switch (s3->accel.cmd & 0x600) { + case 0x000: + if (((s3->accel.multifunc[0xa] & 0xc0) == 0x80) || (s3->accel.cmd & 2)) { + if (((s3->accel.frgd_mix & 0x60) != 0x40) || ((s3->accel.bkgd_mix & 0x60) != 0x40)) + s3_accel_start(8, 1, s3->accel.pix_trans[0] | (s3->accel.pix_trans[1] << 8) | (s3->accel.pix_trans[2] << 16) | (s3->accel.pix_trans[3] << 24), 0, s3); + else + s3_accel_start(1, 1, 0xffffffff, s3->accel.pix_trans[0] | (s3->accel.pix_trans[1] << 8) | (s3->accel.pix_trans[2] << 16) | (s3->accel.pix_trans[3] << 24), s3); + } else + s3_accel_start(1, 1, 0xffffffff, s3->accel.pix_trans[0] | (s3->accel.pix_trans[1] << 8) | (s3->accel.pix_trans[2] << 16) | (s3->accel.pix_trans[3] << 24), s3); + break; + case 0x200: + if (((s3->accel.multifunc[0xa] & 0xc0) == 0x80) || (s3->accel.cmd & 2)) { + if (((s3->accel.frgd_mix & 0x60) != 0x40) || ((s3->accel.bkgd_mix & 0x60) != 0x40)) + s3_accel_start(16, 1, s3->accel.pix_trans[0] | (s3->accel.pix_trans[1] << 8) | (s3->accel.pix_trans[2] << 16) | (s3->accel.pix_trans[3] << 24), 0, s3); + else + s3_accel_start(2, 1, 0xffffffff, s3->accel.pix_trans[0] | (s3->accel.pix_trans[1] << 8) | (s3->accel.pix_trans[2] << 16) | (s3->accel.pix_trans[3] << 24), s3); + } else + s3_accel_start(2, 1, 0xffffffff, s3->accel.pix_trans[0] | (s3->accel.pix_trans[1] << 8) | (s3->accel.pix_trans[2] << 16) | (s3->accel.pix_trans[3] << 24), s3); + break; + + default: + break; + } + } + return s3->accel.pix_trans[3]; + + case 0xff20: + case 0xff21: + temp = s3->serialport & ~(SERIAL_PORT_SCR | SERIAL_PORT_SDR); + if ((s3->serialport & SERIAL_PORT_SCW) && i2c_gpio_get_scl(s3->i2c)) + temp |= SERIAL_PORT_SCR; + if ((s3->serialport & SERIAL_PORT_SDW) && i2c_gpio_get_sda(s3->i2c)) + temp |= SERIAL_PORT_SDR; + return temp; + + default: + break; + } + + return 0xff; } static uint16_t -s3_accel_in_w(uint16_t port, void *p) +s3_accel_in_w(uint16_t port, void *priv) { - s3_t *s3 = (s3_t *)p; - svga_t *svga = &s3->svga; - uint16_t temp = 0x0000; - uint16_t *vram_w = (uint16_t *)svga->vram; + s3_t *s3 = (s3_t *) priv; + svga_t *svga = &s3->svga; + uint16_t temp = 0x0000; + const uint16_t *vram_w = (uint16_t *) svga->vram; - if (!s3->enable_8514) - return 0xffff; - - if (port != 0x9ee8 && port != 0x9d48) { - if (s3_cpu_dest(s3)) { - READ_PIXTRANS_WORD + if (!s3->enable_8514) + return 0xffff; - switch (s3->accel.cmd & 0x600) { - case 0x000: - if (((s3->accel.multifunc[0xa] & 0xc0) == 0x80) || (s3->accel.cmd & 2)) { - if (((s3->accel.frgd_mix & 0x60) != 0x40) || ((s3->accel.bkgd_mix & 0x60) != 0x40)) { - if (s3->accel.cmd & 0x1000) - temp = (temp >> 8) | (temp << 8); - s3_accel_start(8, 1, temp | (temp << 16), 0, s3); - } else { - s3_accel_start(1, 1, 0xffffffff, temp | (temp << 16), s3); - } - } else { - if (s3->color_16bit) { - s3_accel_start(2, 1, 0xffffffff, temp | (temp << 16), s3); - } else { - s3_accel_start(1, 1, 0xffffffff, temp | (temp << 16), s3); - } - } - break; - case 0x200: - if (((s3->accel.multifunc[0xa] & 0xc0) == 0x80) || (s3->accel.cmd & 2)) { - if (((s3->accel.frgd_mix & 0x60) != 0x40) || ((s3->accel.bkgd_mix & 0x60) != 0x40)) { - if (s3->accel.cmd & 0x1000) - temp = (temp >> 8) | (temp << 8); - s3_accel_start(16, 1, temp | (temp << 16), 0, s3); - } else - s3_accel_start(2, 1, 0xffffffff, temp | (temp << 16), s3); - } else { - s3_accel_start(2, 1, 0xffffffff, temp | (temp << 16), s3); - } - break; - } - } - } else { - if (s3_enable_fifo(s3)) - s3_wait_fifo_idle(s3); - temp = s3->accel.short_stroke; - } + if (port != 0x9ee8 && port != 0x9d48) { + if (s3_cpu_dest(s3)) { + READ_PIXTRANS_WORD - return temp; + switch (s3->accel.cmd & 0x600) { + case 0x000: + if (((s3->accel.multifunc[0xa] & 0xc0) == 0x80) || (s3->accel.cmd & 2)) { + if (((s3->accel.frgd_mix & 0x60) != 0x40) || ((s3->accel.bkgd_mix & 0x60) != 0x40)) { + if (s3->accel.cmd & 0x1000) + temp = (temp >> 8) | (temp << 8); + s3_accel_start(8, 1, temp | (temp << 16), 0, s3); + } else { + s3_accel_start(1, 1, 0xffffffff, temp | (temp << 16), s3); + } + } else { + if (s3->color_16bit) { + s3_accel_start(2, 1, 0xffffffff, temp | (temp << 16), s3); + } else { + s3_accel_start(1, 1, 0xffffffff, temp | (temp << 16), s3); + } + } + break; + case 0x200: + if (((s3->accel.multifunc[0xa] & 0xc0) == 0x80) || (s3->accel.cmd & 2)) { + if (((s3->accel.frgd_mix & 0x60) != 0x40) || ((s3->accel.bkgd_mix & 0x60) != 0x40)) { + if (s3->accel.cmd & 0x1000) + temp = (temp >> 8) | (temp << 8); + s3_accel_start(16, 1, temp | (temp << 16), 0, s3); + } else + s3_accel_start(2, 1, 0xffffffff, temp | (temp << 16), s3); + } else { + s3_accel_start(2, 1, 0xffffffff, temp | (temp << 16), s3); + } + break; + + default: + break; + } + } + } else { + if (s3_enable_fifo(s3)) + s3_wait_fifo_idle(s3); + temp = s3->accel.short_stroke; + } + + return temp; } static uint32_t -s3_accel_in_l(uint16_t port, void *p) +s3_accel_in_l(UNUSED(uint16_t port), void *priv) { - s3_t *s3 = (s3_t *)p; - svga_t *svga = &s3->svga; - uint32_t temp = 0x00000000; - uint16_t *vram_w = (uint16_t *)svga->vram; + s3_t *s3 = (s3_t *) priv; + svga_t *svga = &s3->svga; + uint32_t temp = 0x00000000; + const uint16_t *vram_w = (uint16_t *) svga->vram; - if (!s3->enable_8514) - return 0xffffffff; + if (!s3->enable_8514) + return 0xffffffff; - if (s3_cpu_dest(s3)) { - READ_PIXTRANS_LONG + if (s3_cpu_dest(s3)) { + READ_PIXTRANS_LONG - switch (s3->accel.cmd & 0x600) { - case 0x000: - if (((s3->accel.multifunc[0xa] & 0xc0) == 0x80) || (s3->accel.cmd & 2)) { - if (((s3->accel.frgd_mix & 0x60) != 0x40) || ((s3->accel.bkgd_mix & 0x60) != 0x40)) { - if (s3->accel.cmd & 0x1000) - temp = ((temp & 0xff00ff00) >> 8) | ((temp & 0x00ff00ff) << 8); - s3_accel_start(8, 1, temp, 0, s3); - s3_accel_start(8, 1, temp >> 16, 0, s3); - } else { - s3_accel_start(1, 1, 0xffffffff, temp, s3); - s3_accel_start(1, 1, 0xffffffff, temp >> 16, s3); - } - } else { - s3_accel_start(1, 1, 0xffffffff, temp, s3); - s3_accel_start(1, 1, 0xffffffff, temp >> 16, s3); - } - break; - case 0x200: - if (((s3->accel.multifunc[0xa] & 0xc0) == 0x80) || (s3->accel.cmd & 2)) { - if (((s3->accel.frgd_mix & 0x60) != 0x40) || ((s3->accel.bkgd_mix & 0x60) != 0x40)) { - if (s3->accel.cmd & 0x1000) - temp = ((temp & 0xff00ff00) >> 8) | ((temp & 0x00ff00ff) << 8); - s3_accel_start(16, 1, temp, 0, s3); - s3_accel_start(16, 1, temp >> 16, 0, s3); - } else { - s3_accel_start(2, 1, 0xffffffff, temp, s3); - s3_accel_start(2, 1, 0xffffffff, temp >> 16, s3); - } - } else { - s3_accel_start(2, 1, 0xffffffff, temp, s3); - s3_accel_start(2, 1, 0xffffffff, temp >> 16, s3); - } - break; - } - } - - return temp; -} + switch (s3->accel.cmd & 0x600) { + case 0x000: + if (((s3->accel.multifunc[0xa] & 0xc0) == 0x80) || (s3->accel.cmd & 2)) { + if (((s3->accel.frgd_mix & 0x60) != 0x40) || ((s3->accel.bkgd_mix & 0x60) != 0x40)) { + if (s3->accel.cmd & 0x1000) + temp = ((temp & 0xff00ff00) >> 8) | ((temp & 0x00ff00ff) << 8); + s3_accel_start(8, 1, temp, 0, s3); + s3_accel_start(8, 1, temp >> 16, 0, s3); + } else { + s3_accel_start(1, 1, 0xffffffff, temp, s3); + s3_accel_start(1, 1, 0xffffffff, temp >> 16, s3); + } + } else { + s3_accel_start(1, 1, 0xffffffff, temp, s3); + s3_accel_start(1, 1, 0xffffffff, temp >> 16, s3); + } + break; + case 0x200: + if (((s3->accel.multifunc[0xa] & 0xc0) == 0x80) || (s3->accel.cmd & 2)) { + if (((s3->accel.frgd_mix & 0x60) != 0x40) || ((s3->accel.bkgd_mix & 0x60) != 0x40)) { + if (s3->accel.cmd & 0x1000) + temp = ((temp & 0xff00ff00) >> 8) | ((temp & 0x00ff00ff) << 8); + s3_accel_start(16, 1, temp, 0, s3); + s3_accel_start(16, 1, temp >> 16, 0, s3); + } else { + s3_accel_start(2, 1, 0xffffffff, temp, s3); + s3_accel_start(2, 1, 0xffffffff, temp >> 16, s3); + } + } else { + s3_accel_start(2, 1, 0xffffffff, temp, s3); + s3_accel_start(2, 1, 0xffffffff, temp >> 16, s3); + } + break; + default: + break; + } + } -static void -s3_accel_write(uint32_t addr, uint8_t val, void *p) -{ - s3_t *s3 = (s3_t *)p; - svga_t *svga = &s3->svga; - - if (!s3->enable_8514) - return; - - if (s3_enable_fifo(s3)) { - if (svga->crtc[0x53] & 0x08) - s3_queue(s3, addr & 0x1ffff, val, FIFO_WRITE_BYTE); - else - s3_queue(s3, addr & 0xffff, val, FIFO_WRITE_BYTE); - } else - s3_accel_write_fifo(s3, addr & 0xffff, val); + return temp; } static void -s3_accel_write_w(uint32_t addr, uint16_t val, void *p) +s3_accel_write(uint32_t addr, uint8_t val, void *priv) { - s3_t *s3 = (s3_t *)p; - svga_t *svga = &s3->svga; + s3_t *s3 = (s3_t *) priv; + const svga_t *svga = &s3->svga; - if (!s3->enable_8514) - return; + if (!s3->enable_8514) + return; - if (s3_enable_fifo(s3)) { - if (svga->crtc[0x53] & 0x08) - s3_queue(s3, addr & 0x1ffff, val, FIFO_WRITE_WORD); - else - s3_queue(s3, addr & 0xffff, val, FIFO_WRITE_WORD); - } else - s3_accel_write_fifo_w(s3, addr & 0xffff, val); + if (s3_enable_fifo(s3)) { + if (svga->crtc[0x53] & 0x08) + s3_queue(s3, addr & 0x1ffff, val, FIFO_WRITE_BYTE); + else + s3_queue(s3, addr & 0xffff, val, FIFO_WRITE_BYTE); + } else + s3_accel_write_fifo(s3, addr & 0xffff, val); } static void -s3_accel_write_l(uint32_t addr, uint32_t val, void *p) +s3_accel_write_w(uint32_t addr, uint16_t val, void *priv) { - s3_t *s3 = (s3_t *)p; - svga_t *svga = &s3->svga; + s3_t *s3 = (s3_t *) priv; + const svga_t *svga = &s3->svga; - if (!s3->enable_8514) - return; + if (!s3->enable_8514) + return; - if (s3_enable_fifo(s3)) { - if (svga->crtc[0x53] & 0x08) - s3_queue(s3, addr & 0x1ffff, val, FIFO_WRITE_DWORD); - else - s3_queue(s3, addr & 0xffff, val, FIFO_WRITE_DWORD); - } else - s3_accel_write_fifo_l(s3, addr & 0xffff, val); + if (s3_enable_fifo(s3)) { + if (svga->crtc[0x53] & 0x08) + s3_queue(s3, addr & 0x1ffff, val, FIFO_WRITE_WORD); + else + s3_queue(s3, addr & 0xffff, val, FIFO_WRITE_WORD); + } else + s3_accel_write_fifo_w(s3, addr & 0xffff, val); +} + +static void +s3_accel_write_l(uint32_t addr, uint32_t val, void *priv) +{ + s3_t *s3 = (s3_t *) priv; + const svga_t *svga = &s3->svga; + + if (!s3->enable_8514) + return; + + if (s3_enable_fifo(s3)) { + if (svga->crtc[0x53] & 0x08) + s3_queue(s3, addr & 0x1ffff, val, FIFO_WRITE_DWORD); + else + s3_queue(s3, addr & 0xffff, val, FIFO_WRITE_DWORD); + } else + s3_accel_write_fifo_l(s3, addr & 0xffff, val); } static uint8_t -s3_accel_read(uint32_t addr, void *p) +s3_accel_read(uint32_t addr, void *priv) { - s3_t *s3 = (s3_t *)p; + s3_t *s3 = (s3_t *) priv; svga_t *svga = &s3->svga; uint8_t temp = 0x00; - if (!s3->enable_8514) - return 0xff; + if (!s3->enable_8514) + return 0xff; if (svga->crtc[0x53] & 0x08) { - if ((addr >= 0x08000) && (addr <= 0x0803f)) - return s3_pci_read(0, addr & 0xff, s3); - switch (addr & 0x1ffff) { - case 0x83b0: case 0x83b1: case 0x83b2: case 0x83b3: - case 0x83b4: case 0x83b5: case 0x83b6: case 0x83b7: - case 0x83b8: case 0x83b9: case 0x83ba: case 0x83bb: - case 0x83bc: case 0x83bd: case 0x83be: case 0x83bf: - case 0x83c0: case 0x83c1: case 0x83c2: case 0x83c3: - case 0x83c4: case 0x83c5: case 0x83c6: case 0x83c7: - case 0x83c8: case 0x83c9: case 0x83ca: case 0x83cb: - case 0x83cc: case 0x83cd: case 0x83ce: case 0x83cf: - case 0x83d0: case 0x83d1: case 0x83d2: case 0x83d3: - case 0x83d4: case 0x83d5: case 0x83d6: case 0x83d7: - case 0x83d8: case 0x83d9: case 0x83da: case 0x83db: - case 0x83dc: case 0x83dd: case 0x83de: case 0x83df: - return s3_in(addr & 0x3ff, s3); - case 0x8504: - return s3->subsys_stat; - case 0x8505: - return s3->subsys_cntl; - default: - return s3_accel_in(addr & 0xffff, p); - } - return 0xff; + if ((addr >= 0x08000) && (addr <= 0x0803f)) + return s3_pci_read(0, addr & 0xff, s3); + switch (addr & 0x1ffff) { + case 0x83b0: + case 0x83b1: + case 0x83b2: + case 0x83b3: + case 0x83b4: + case 0x83b5: + case 0x83b6: + case 0x83b7: + case 0x83b8: + case 0x83b9: + case 0x83ba: + case 0x83bb: + case 0x83bc: + case 0x83bd: + case 0x83be: + case 0x83bf: + case 0x83c0: + case 0x83c1: + case 0x83c2: + case 0x83c3: + case 0x83c4: + case 0x83c5: + case 0x83c6: + case 0x83c7: + case 0x83c8: + case 0x83c9: + case 0x83ca: + case 0x83cb: + case 0x83cc: + case 0x83cd: + case 0x83ce: + case 0x83cf: + case 0x83d0: + case 0x83d1: + case 0x83d2: + case 0x83d3: + case 0x83d4: + case 0x83d5: + case 0x83d6: + case 0x83d7: + case 0x83d8: + case 0x83d9: + case 0x83da: + case 0x83db: + case 0x83dc: + case 0x83dd: + case 0x83de: + case 0x83df: + return s3_in(addr & 0x3ff, s3); + case 0x8504: + return s3->subsys_stat; + case 0x8505: + return s3->subsys_cntl; + default: + return s3_accel_in(addr & 0xffff, priv); + } + return 0xff; } else { - if (addr & 0x8000) { - temp = s3_accel_in(addr & 0xffff, p); - } else if (s3_cpu_dest(s3)) { - READ_PIXTRANS_BYTE_MM + if (addr & 0x8000) { + temp = s3_accel_in(addr & 0xffff, priv); + } else if (s3_cpu_dest(s3)) { + READ_PIXTRANS_BYTE_MM - switch (s3->accel.cmd & 0x600) { - case 0x000: - if (((s3->accel.multifunc[0xa] & 0xc0) == 0x80) || (s3->accel.cmd & 2)) { - if (((s3->accel.frgd_mix & 0x60) != 0x40) || ((s3->accel.bkgd_mix & 0x60) != 0x40)) - s3_accel_start(8, 1, temp | (temp << 8) | (temp << 16) | (temp << 24), 0, s3); - else - s3_accel_start(1, 1, 0xffffffff, temp | (temp << 8) | (temp << 16) | (temp << 24), s3); - } else - s3_accel_start(1, 1, 0xffffffff, temp | (temp << 8) | (temp << 16) | (temp << 24), s3); - break; - case 0x200: - if (((s3->accel.multifunc[0xa] & 0xc0) == 0x80) || (s3->accel.cmd & 2)) { - if (((s3->accel.frgd_mix & 0x60) != 0x40) || ((s3->accel.bkgd_mix & 0x60) != 0x40)) - s3_accel_start(16, 1, temp | (temp << 8) | (temp << 16) | (temp << 24), 0, s3); - else - s3_accel_start(2, 1, 0xffffffff, temp | (temp << 8) | (temp << 16) | (temp << 24), s3); - } else - s3_accel_start(2, 1, 0xffffffff, temp | (temp << 8) | (temp << 16) | (temp << 24), s3); - break; - } - } + switch (s3->accel.cmd & 0x600) { + case 0x000: + if (((s3->accel.multifunc[0xa] & 0xc0) == 0x80) || (s3->accel.cmd & 2)) { + if (((s3->accel.frgd_mix & 0x60) != 0x40) || ((s3->accel.bkgd_mix & 0x60) != 0x40)) + s3_accel_start(8, 1, temp | (temp << 8) | (temp << 16) | (temp << 24), 0, s3); + else + s3_accel_start(1, 1, 0xffffffff, temp | (temp << 8) | (temp << 16) | (temp << 24), s3); + } else + s3_accel_start(1, 1, 0xffffffff, temp | (temp << 8) | (temp << 16) | (temp << 24), s3); + break; + case 0x200: + if (((s3->accel.multifunc[0xa] & 0xc0) == 0x80) || (s3->accel.cmd & 2)) { + if (((s3->accel.frgd_mix & 0x60) != 0x40) || ((s3->accel.bkgd_mix & 0x60) != 0x40)) + s3_accel_start(16, 1, temp | (temp << 8) | (temp << 16) | (temp << 24), 0, s3); + else + s3_accel_start(2, 1, 0xffffffff, temp | (temp << 8) | (temp << 16) | (temp << 24), s3); + } else + s3_accel_start(2, 1, 0xffffffff, temp | (temp << 8) | (temp << 16) | (temp << 24), s3); + break; + + default: + break; + } + } } return temp; } static uint16_t -s3_accel_read_w(uint32_t addr, void *p) +s3_accel_read_w(uint32_t addr, void *priv) { - s3_t *s3 = (s3_t *)p; - svga_t *svga = &s3->svga; - uint16_t temp = 0x0000; - uint16_t *vram_w = (uint16_t *)svga->vram; + s3_t *s3 = (s3_t *) priv; + svga_t *svga = &s3->svga; + uint16_t temp = 0x0000; + const uint16_t *vram_w = (uint16_t *) svga->vram; + + if (!s3->enable_8514) + return 0xffff; - if (!s3->enable_8514) - return 0xffff; - if (svga->crtc[0x53] & 0x08) { - switch (addr & 0x1fffe) { - case 0x811c: - if (s3_enable_fifo(s3)) - s3_wait_fifo_idle(s3); - return s3->accel.short_stroke; - - default: - return s3_accel_read(addr, p) | - s3_accel_read(addr + 1, p) << 8; - } - return 0xffff; - } else { - if (addr & 0x8000) { - if (addr == 0x811c) { - if (s3_enable_fifo(s3)) - s3_wait_fifo_idle(s3); - temp = s3->accel.short_stroke; - } else { - temp = s3_accel_read((addr & 0xfffe), p); - temp |= s3_accel_read((addr & 0xfffe) + 1, p) << 8; - } - } else if (s3_cpu_dest(s3)) { - READ_PIXTRANS_WORD + switch (addr & 0x1fffe) { + case 0x811c: + if (s3_enable_fifo(s3)) + s3_wait_fifo_idle(s3); + return s3->accel.short_stroke; - switch (s3->accel.cmd & 0x600) { - case 0x000: - if (((s3->accel.multifunc[0xa] & 0xc0) == 0x80) || (s3->accel.cmd & 2)) { - if (((s3->accel.frgd_mix & 0x60) != 0x40) || ((s3->accel.bkgd_mix & 0x60) != 0x40)) - s3_accel_start(8, 1, temp | (temp << 16), 0, s3); - else - s3_accel_start(1, 1, 0xffffffff, temp | (temp << 16), s3); - } else - s3_accel_start(1, 1, 0xffffffff, temp | (temp << 16), s3); - break; - case 0x200: - if (((s3->accel.multifunc[0xa] & 0xc0) == 0x80) || (s3->accel.cmd & 2)) { - if (((s3->accel.frgd_mix & 0x60) != 0x40) || ((s3->accel.bkgd_mix & 0x60) != 0x40)) - s3_accel_start(16, 1, temp | (temp << 16), 0, s3); - else - s3_accel_start(2, 1, 0xffffffff, temp | (temp << 16), s3); - } else - s3_accel_start(2, 1, 0xffffffff, temp | (temp << 16), s3); - break; - } - } + default: + return s3_accel_read(addr, priv) | s3_accel_read(addr + 1, priv) << 8; + } + return 0xffff; + } else { + if (addr & 0x8000) { + if (addr == 0x811c) { + if (s3_enable_fifo(s3)) + s3_wait_fifo_idle(s3); + temp = s3->accel.short_stroke; + } else { + temp = s3_accel_read((addr & 0xfffe), priv); + temp |= s3_accel_read((addr & 0xfffe) + 1, priv) << 8; + } + } else if (s3_cpu_dest(s3)) { + READ_PIXTRANS_WORD + + switch (s3->accel.cmd & 0x600) { + case 0x000: + if (((s3->accel.multifunc[0xa] & 0xc0) == 0x80) || (s3->accel.cmd & 2)) { + if (((s3->accel.frgd_mix & 0x60) != 0x40) || ((s3->accel.bkgd_mix & 0x60) != 0x40)) + s3_accel_start(8, 1, temp | (temp << 16), 0, s3); + else + s3_accel_start(1, 1, 0xffffffff, temp | (temp << 16), s3); + } else + s3_accel_start(1, 1, 0xffffffff, temp | (temp << 16), s3); + break; + case 0x200: + if (((s3->accel.multifunc[0xa] & 0xc0) == 0x80) || (s3->accel.cmd & 2)) { + if (((s3->accel.frgd_mix & 0x60) != 0x40) || ((s3->accel.bkgd_mix & 0x60) != 0x40)) + s3_accel_start(16, 1, temp | (temp << 16), 0, s3); + else + s3_accel_start(2, 1, 0xffffffff, temp | (temp << 16), s3); + } else + s3_accel_start(2, 1, 0xffffffff, temp | (temp << 16), s3); + break; + + default: + break; + } + } } return temp; } - static uint32_t -s3_accel_read_l(uint32_t addr, void *p) +s3_accel_read_l(uint32_t addr, void *priv) { - s3_t *s3 = (s3_t *)p; - svga_t *svga = &s3->svga; - uint32_t temp = 0x00000000; - uint16_t *vram_w = (uint16_t *)svga->vram; + s3_t *s3 = (s3_t *) priv; + svga_t *svga = &s3->svga; + uint32_t temp = 0x00000000; + const uint16_t *vram_w = (uint16_t *) svga->vram; - if (!s3->enable_8514) - return 0xffffffff; + if (!s3->enable_8514) + return 0xffffffff; if (svga->crtc[0x53] & 0x08) { - switch (addr & 0x1fffc) { - case 0x8180: - temp = s3->streams.pri_ctrl; - break; - case 0x8184: - temp = s3->streams.chroma_ctrl; - break; - case 0x8190: - temp = s3->streams.sec_ctrl; - break; - case 0x8194: - temp = s3->streams.chroma_upper_bound; - break; - case 0x8198: - temp = s3->streams.sec_filter; - break; - case 0x81a0: - temp = s3->streams.blend_ctrl; - break; - case 0x81c0: - temp = s3->streams.pri_fb0; - break; - case 0x81c4: - temp = s3->streams.pri_fb1; - break; - case 0x81c8: - temp = s3->streams.pri_stride; - break; - case 0x81cc: - temp = s3->streams.buffer_ctrl; - break; - case 0x81d0: - temp = s3->streams.sec_fb0; - break; - case 0x81d4: - temp = s3->streams.sec_fb1; - break; - case 0x81d8: - temp = s3->streams.sec_stride; - break; - case 0x81dc: - temp = s3->streams.overlay_ctrl; - break; - case 0x81e0: - temp = s3->streams.k1_vert_scale; - break; - case 0x81e4: - temp = s3->streams.k2_vert_scale; - break; - case 0x81e8: - temp = s3->streams.dda_vert_accumulator; - break; - case 0x81ec: - temp = s3->streams.fifo_ctrl; - break; - case 0x81f0: - temp = s3->streams.pri_start; - break; - case 0x81f4: - temp = s3->streams.pri_size; - break; - case 0x81f8: - temp = s3->streams.sec_start; - break; - case 0x81fc: - temp = s3->streams.sec_size; - break; + switch (addr & 0x1fffc) { + case 0x8180: + temp = s3->streams.pri_ctrl; + break; + case 0x8184: + temp = s3->streams.chroma_ctrl; + break; + case 0x8190: + temp = s3->streams.sec_ctrl; + break; + case 0x8194: + temp = s3->streams.chroma_upper_bound; + break; + case 0x8198: + temp = s3->streams.sec_filter; + break; + case 0x81a0: + temp = s3->streams.blend_ctrl; + break; + case 0x81c0: + temp = s3->streams.pri_fb0; + break; + case 0x81c4: + temp = s3->streams.pri_fb1; + break; + case 0x81c8: + temp = s3->streams.pri_stride; + break; + case 0x81cc: + temp = s3->streams.buffer_ctrl; + break; + case 0x81d0: + temp = s3->streams.sec_fb0; + break; + case 0x81d4: + temp = s3->streams.sec_fb1; + break; + case 0x81d8: + temp = s3->streams.sec_stride; + break; + case 0x81dc: + temp = s3->streams.overlay_ctrl; + break; + case 0x81e0: + temp = s3->streams.k1_vert_scale; + break; + case 0x81e4: + temp = s3->streams.k2_vert_scale; + break; + case 0x81e8: + temp = s3->streams.dda_vert_accumulator; + break; + case 0x81ec: + temp = s3->streams.fifo_ctrl; + break; + case 0x81f0: + temp = s3->streams.pri_start; + break; + case 0x81f4: + temp = s3->streams.pri_size; + break; + case 0x81f8: + temp = s3->streams.sec_start; + break; + case 0x81fc: + temp = s3->streams.sec_size; + break; - case 0x18080: - if (s3_enable_fifo(s3)) - s3_wait_fifo_idle(s3); - temp = 0; - break; - case 0x18088: - if (s3_enable_fifo(s3)) - s3_wait_fifo_idle(s3); - temp = s3->videoengine.cntl; - if (s3->bpp == 1) { /*The actual bpp is decided by the guest when idf is the same as odf*/ - if (s3->videoengine.idf == 0 && s3->videoengine.odf == 0) { - if (svga->bpp == 15) - temp |= 0x600000; - else - temp |= 0x700000; - } - } else if (s3->bpp > 1) { - if (s3->videoengine.idf == 0 && s3->videoengine.odf == 0) - temp |= 0x300000; - } - break; - case 0x1808c: - if (s3_enable_fifo(s3)) - s3_wait_fifo_idle(s3); - temp = s3->videoengine.stretch_filt_const; - break; - case 0x18090: - if (s3_enable_fifo(s3)) - s3_wait_fifo_idle(s3); - temp = s3->videoengine.src_dst_step; - break; - case 0x18094: - if (s3_enable_fifo(s3)) - s3_wait_fifo_idle(s3); - temp = s3->videoengine.crop; - break; - case 0x18098: - if (s3_enable_fifo(s3)) - s3_wait_fifo_idle(s3); - temp = s3->videoengine.src_base; - break; - case 0x1809c: - if (s3_enable_fifo(s3)) - s3_wait_fifo_idle(s3); - temp = s3->videoengine.dest_base; - if (s3->videoengine.busy) { - temp |= (1 << 31); - } else { - temp &= ~(1 << 31); - } - break; + case 0x18080: + if (s3_enable_fifo(s3)) + s3_wait_fifo_idle(s3); + temp = 0; + break; + case 0x18088: + if (s3_enable_fifo(s3)) + s3_wait_fifo_idle(s3); + temp = s3->videoengine.cntl; + if (s3->bpp == 1) { /*The actual bpp is decided by the guest when idf is the same as odf*/ + if (s3->videoengine.idf == 0 && s3->videoengine.odf == 0) { + if (svga->bpp == 15) + temp |= 0x600000; + else + temp |= 0x700000; + } + } else if (s3->bpp > 1) { + if (s3->videoengine.idf == 0 && s3->videoengine.odf == 0) + temp |= 0x300000; + } + break; + case 0x1808c: + if (s3_enable_fifo(s3)) + s3_wait_fifo_idle(s3); + temp = s3->videoengine.stretch_filt_const; + break; + case 0x18090: + if (s3_enable_fifo(s3)) + s3_wait_fifo_idle(s3); + temp = s3->videoengine.src_dst_step; + break; + case 0x18094: + if (s3_enable_fifo(s3)) + s3_wait_fifo_idle(s3); + temp = s3->videoengine.crop; + break; + case 0x18098: + if (s3_enable_fifo(s3)) + s3_wait_fifo_idle(s3); + temp = s3->videoengine.src_base; + break; + case 0x1809c: + if (s3_enable_fifo(s3)) + s3_wait_fifo_idle(s3); + temp = s3->videoengine.dest_base; + if (s3->videoengine.busy) { + temp |= (1 << 31); + } else { + temp &= ~(1 << 31); + } + break; - default: - temp = s3_accel_read_w(addr, p) | (s3_accel_read_w(addr + 2, p) << 16); - break; - } + default: + temp = s3_accel_read_w(addr, priv) | (s3_accel_read_w(addr + 2, priv) << 16); + break; + } } else { - if (addr & 0x8000) { - temp = s3_accel_read((addr & 0xfffc), p); - temp |= s3_accel_read((addr & 0xfffc) + 1, p) << 8; - temp |= s3_accel_read((addr & 0xfffc) + 2, p) << 16; - temp |= s3_accel_read((addr & 0xfffc) + 3, p) << 24; - } else if (s3_cpu_dest(s3)) { - READ_PIXTRANS_LONG + if (addr & 0x8000) { + temp = s3_accel_read((addr & 0xfffc), priv); + temp |= s3_accel_read((addr & 0xfffc) + 1, priv) << 8; + temp |= s3_accel_read((addr & 0xfffc) + 2, priv) << 16; + temp |= s3_accel_read((addr & 0xfffc) + 3, priv) << 24; + } else if (s3_cpu_dest(s3)) { + READ_PIXTRANS_LONG - switch (s3->accel.cmd & 0x600) { - case 0x000: - if (((s3->accel.multifunc[0xa] & 0xc0) == 0x80) || (s3->accel.cmd & 2)) { - if (((s3->accel.frgd_mix & 0x60) != 0x40) || ((s3->accel.bkgd_mix & 0x60) != 0x40)) { - s3_accel_start(8, 1, temp, 0, s3); - s3_accel_start(8, 1, temp >> 16, 0, s3); - } else { - s3_accel_start(1, 1, 0xffffffff, temp, s3); - s3_accel_start(1, 1, 0xffffffff, temp >> 16, s3); - } - } else { - s3_accel_start(1, 1, 0xffffffff, temp, s3); - s3_accel_start(1, 1, 0xffffffff, temp >> 16, s3); - } - break; - case 0x200: - if (((s3->accel.multifunc[0xa] & 0xc0) == 0x80) || (s3->accel.cmd & 2)) { - if (((s3->accel.frgd_mix & 0x60) != 0x40) || ((s3->accel.bkgd_mix & 0x60) != 0x40)) { - s3_accel_start(16, 1, temp, 0, s3); - s3_accel_start(16, 1, temp >> 16, 0, s3); - } else { - s3_accel_start(2, 1, 0xffffffff, temp, s3); - s3_accel_start(2, 1, 0xffffffff, temp >> 16, s3); - } - } else { - s3_accel_start(2, 1, 0xffffffff, temp, s3); - s3_accel_start(2, 1, 0xffffffff, temp >> 16, s3); - } - break; - } - } + switch (s3->accel.cmd & 0x600) { + case 0x000: + if (((s3->accel.multifunc[0xa] & 0xc0) == 0x80) || (s3->accel.cmd & 2)) { + if (((s3->accel.frgd_mix & 0x60) != 0x40) || ((s3->accel.bkgd_mix & 0x60) != 0x40)) { + s3_accel_start(8, 1, temp, 0, s3); + s3_accel_start(8, 1, temp >> 16, 0, s3); + } else { + s3_accel_start(1, 1, 0xffffffff, temp, s3); + s3_accel_start(1, 1, 0xffffffff, temp >> 16, s3); + } + } else { + s3_accel_start(1, 1, 0xffffffff, temp, s3); + s3_accel_start(1, 1, 0xffffffff, temp >> 16, s3); + } + break; + case 0x200: + if (((s3->accel.multifunc[0xa] & 0xc0) == 0x80) || (s3->accel.cmd & 2)) { + if (((s3->accel.frgd_mix & 0x60) != 0x40) || ((s3->accel.bkgd_mix & 0x60) != 0x40)) { + s3_accel_start(16, 1, temp, 0, s3); + s3_accel_start(16, 1, temp >> 16, 0, s3); + } else { + s3_accel_start(2, 1, 0xffffffff, temp, s3); + s3_accel_start(2, 1, 0xffffffff, temp >> 16, s3); + } + } else { + s3_accel_start(2, 1, 0xffffffff, temp, s3); + s3_accel_start(2, 1, 0xffffffff, temp >> 16, s3); + } + break; + + default: + break; + } + } } return temp; @@ -4476,533 +4976,1088 @@ s3_accel_read_l(uint32_t addr, void *p) static void polygon_setup(s3_t *s3) { - if (s3->accel.point_1_updated) - { - int start_x = s3->accel.poly_cx; - int start_y = s3->accel.poly_cy; - int end_x = s3->accel.destx_distp << 20; - int end_y = s3->accel.desty_axstp; - - if (end_y - start_y) - s3->accel.poly_dx1 = (end_x - start_x) / (end_y - start_y); - else - s3->accel.poly_dx1 = 0; - - s3->accel.point_1_updated = 0; + if (s3->accel.point_1_updated) { + int start_x = s3->accel.poly_cx; + int start_y = s3->accel.poly_cy; + int end_x = s3->accel.destx_distp << 20; + int end_y = s3->accel.desty_axstp; - if (end_y == s3->accel.poly_cy) - { - s3->accel.poly_cx = end_x; - s3->accel.poly_x = end_x >> 20; - } - } - if (s3->accel.point_2_updated) - { - int start_x = s3->accel.poly_cx2; - int start_y = s3->accel.poly_cy2; - int end_x = s3->accel.x2 << 20; - int end_y = s3->accel.desty_axstp2; + if (end_y - start_y) + s3->accel.poly_dx1 = (end_x - start_x) / (end_y - start_y); + else + s3->accel.poly_dx1 = 0; - if (end_y - start_y) - s3->accel.poly_dx2 = (end_x - start_x) / (end_y - start_y); - else - s3->accel.poly_dx2 = 0; + s3->accel.point_1_updated = 0; - s3->accel.point_2_updated = 0; - - if (end_y == s3->accel.poly_cy) - s3->accel.poly_cx2 = end_x; - } + if (end_y == s3->accel.poly_cy) { + s3->accel.poly_cx = end_x; + s3->accel.poly_x = end_x >> 20; + } + } + if (s3->accel.point_2_updated) { + int start_x = s3->accel.poly_cx2; + int start_y = s3->accel.poly_cy2; + int end_x = s3->accel.x2 << 20; + int end_y = s3->accel.desty_axstp2; + + if (end_y - start_y) + s3->accel.poly_dx2 = (end_x - start_x) / (end_y - start_y); + else + s3->accel.poly_dx2 = 0; + + s3->accel.point_2_updated = 0; + + if (end_y == s3->accel.poly_cy) + s3->accel.poly_cx2 = end_x; + } } -#define READ(addr, dat) 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) dat = vram_w[dword_remap_w(svga, addr) & (s3->vram_mask >> 1)]; \ - else if (s3->bpp == 2) dat = svga->vram[dword_remap(svga, addr) & s3->vram_mask]; \ - else dat = vram_l[dword_remap_l(svga, addr) & (s3->vram_mask >> 2)]; +#define READ(addr, dat) \ + 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) \ + dat = vram_w[dword_remap_w(svga, addr) & (s3->vram_mask >> 1)]; \ + else if (s3->bpp == 2) \ + dat = svga->vram[dword_remap(svga, addr) & s3->vram_mask]; \ + else \ + dat = vram_l[dword_remap_l(svga, addr) & (s3->vram_mask >> 2)]; -#define MIX_READ { \ - switch ((mix_dat & mix_mask) ? (s3->accel.frgd_mix & 0xf) : (s3->accel.bkgd_mix & 0xf)) \ - { \ - case 0x0: dest_dat = ~dest_dat; break; \ - case 0x1: dest_dat = 0; break; \ - case 0x2: dest_dat = ~0; break; \ - case 0x3: dest_dat = dest_dat; break; \ - case 0x4: dest_dat = ~src_dat; break; \ - case 0x5: dest_dat = src_dat ^ dest_dat; break; \ - case 0x6: dest_dat = ~(src_dat ^ dest_dat); break; \ - case 0x7: dest_dat = src_dat; break; \ - case 0x8: dest_dat = ~(src_dat & dest_dat); break; \ - case 0x9: dest_dat = ~src_dat | dest_dat; break; \ - case 0xa: dest_dat = src_dat | ~dest_dat; break; \ - case 0xb: dest_dat = src_dat | dest_dat; break; \ - case 0xc: dest_dat = src_dat & dest_dat; break; \ - case 0xd: dest_dat = src_dat & ~dest_dat; break; \ - case 0xe: dest_dat = ~src_dat & dest_dat; break; \ - case 0xf: dest_dat = ~(src_dat | dest_dat); break; \ - } \ - } +#define MIX_READ \ + { \ + switch ((mix_dat & mix_mask) ? (s3->accel.frgd_mix & 0xf) : (s3->accel.bkgd_mix & 0xf)) { \ + case 0x0: \ + dest_dat = ~dest_dat; \ + break; \ + case 0x1: \ + dest_dat = 0; \ + break; \ + case 0x2: \ + dest_dat = ~0; \ + break; \ + case 0x3: \ + dest_dat = dest_dat; \ + break; \ + case 0x4: \ + dest_dat = ~src_dat; \ + break; \ + case 0x5: \ + dest_dat = src_dat ^ dest_dat; \ + break; \ + case 0x6: \ + dest_dat = ~(src_dat ^ dest_dat); \ + break; \ + case 0x7: \ + dest_dat = src_dat; \ + break; \ + case 0x8: \ + dest_dat = ~(src_dat & dest_dat); \ + break; \ + case 0x9: \ + dest_dat = ~src_dat | dest_dat; \ + break; \ + case 0xa: \ + dest_dat = src_dat | ~dest_dat; \ + break; \ + case 0xb: \ + dest_dat = src_dat | dest_dat; \ + break; \ + case 0xc: \ + dest_dat = src_dat & dest_dat; \ + break; \ + case 0xd: \ + dest_dat = src_dat & ~dest_dat; \ + break; \ + case 0xe: \ + dest_dat = ~src_dat & dest_dat; \ + break; \ + case 0xf: \ + dest_dat = ~(src_dat | dest_dat); \ + break; \ + } \ + } +#define MIX \ + { \ + old_dest_dat = dest_dat; \ + MIX_READ \ + dest_dat = (dest_dat & s3->accel.wrt_mask) | (old_dest_dat & ~s3->accel.wrt_mask); \ + } -#define MIX { \ - old_dest_dat = dest_dat; \ - MIX_READ \ - dest_dat = (dest_dat & s3->accel.wrt_mask) | (old_dest_dat & ~s3->accel.wrt_mask); \ - } +#define ROPMIX_READ(D, P, S) \ + { \ + switch (rop) { \ + case 0x00: \ + out = 0; \ + break; \ + case 0x01: \ + out = ~(D | (P | S)); \ + break; \ + case 0x02: \ + out = D & ~(P | S); \ + break; \ + case 0x03: \ + out = ~(P | S); \ + break; \ + case 0x04: \ + out = S & ~(D | P); \ + break; \ + case 0x05: \ + out = ~(D | P); \ + break; \ + case 0x06: \ + out = ~(P | ~(D ^ S)); \ + break; \ + case 0x07: \ + out = ~(P | (D & S)); \ + break; \ + case 0x08: \ + out = S & (D & ~P); \ + break; \ + case 0x09: \ + out = ~(P | (D ^ S)); \ + break; \ + case 0x0a: \ + out = D & ~P; \ + break; \ + case 0x0b: \ + out = ~(P | (S & ~D)); \ + break; \ + case 0x0c: \ + out = S & ~P; \ + break; \ + case 0x0d: \ + out = ~(P | (D & ~S)); \ + break; \ + case 0x0e: \ + out = ~(P | ~(D | S)); \ + break; \ + case 0x0f: \ + out = ~P; \ + break; \ + case 0x10: \ + out = P & ~(D | S); \ + break; \ + case 0x11: \ + out = ~(D | S); \ + break; \ + case 0x12: \ + out = ~(S | ~(D ^ P)); \ + break; \ + case 0x13: \ + out = ~(S | (D & P)); \ + break; \ + case 0x14: \ + out = ~(D | ~(P ^ S)); \ + break; \ + case 0x15: \ + out = ~(D | (P & S)); \ + break; \ + case 0x16: \ + out = P ^ (S ^ (D & ~(P & S))); \ + break; \ + case 0x17: \ + out = ~(S ^ ((S ^ P) & (D ^ S))); \ + break; \ + case 0x18: \ + out = (S ^ P) & (P ^ D); \ + break; \ + case 0x19: \ + out = ~(S ^ (D & ~(P & S))); \ + break; \ + case 0x1a: \ + out = P ^ (D | (S & P)); \ + break; \ + case 0x1b: \ + out = ~(S ^ (D & (P ^ S))); \ + break; \ + case 0x1c: \ + out = P ^ (S | (D & P)); \ + break; \ + case 0x1d: \ + out = ~(D ^ (S & (P ^ D))); \ + break; \ + case 0x1e: \ + out = P ^ (D | S); \ + break; \ + case 0x1f: \ + out = ~(P & (D | S)); \ + break; \ + case 0x20: \ + out = D & (P & ~S); \ + break; \ + case 0x21: \ + out = ~(S | (D ^ P)); \ + break; \ + case 0x22: \ + out = D & ~S; \ + break; \ + case 0x23: \ + out = ~(S | (P & ~D)); \ + break; \ + case 0x24: \ + out = (S ^ P) & (D ^ S); \ + break; \ + case 0x25: \ + out = ~(P ^ (D & ~(S & P))); \ + break; \ + case 0x26: \ + out = S ^ (D | (P & S)); \ + break; \ + case 0x27: \ + out = S ^ (D | ~(P ^ S)); \ + break; \ + case 0x28: \ + out = D & (P ^ S); \ + break; \ + case 0x29: \ + out = ~(P ^ (S ^ (D | (P & S)))); \ + break; \ + case 0x2a: \ + out = D & ~(P & S); \ + break; \ + case 0x2b: \ + out = ~(S ^ ((S ^ P) & (P ^ D))); \ + break; \ + case 0x2c: \ + out = S ^ (P & (D | S)); \ + break; \ + case 0x2d: \ + out = P ^ (S | ~D); \ + break; \ + case 0x2e: \ + out = P ^ (S | (D ^ P)); \ + break; \ + case 0x2f: \ + out = ~(P & (S | ~D)); \ + break; \ + case 0x30: \ + out = P & ~S; \ + break; \ + case 0x31: \ + out = ~(S | (D & ~P)); \ + break; \ + case 0x32: \ + out = S ^ (D | (P | S)); \ + break; \ + case 0x33: \ + out = ~S; \ + break; \ + case 0x34: \ + out = S ^ (P | (D & S)); \ + break; \ + case 0x35: \ + out = S ^ (P | ~(D ^ S)); \ + break; \ + case 0x36: \ + out = S ^ (D | P); \ + break; \ + case 0x37: \ + out = ~(S & (D | P)); \ + break; \ + case 0x38: \ + out = P ^ (S & (D | P)); \ + break; \ + case 0x39: \ + out = S ^ (P | ~D); \ + break; \ + case 0x3a: \ + out = S ^ (P | (D ^ S)); \ + break; \ + case 0x3b: \ + out = ~(S & (P | ~D)); \ + break; \ + case 0x3c: \ + out = P ^ S; \ + break; \ + case 0x3d: \ + out = S ^ (P | ~(D | S)); \ + break; \ + case 0x3e: \ + out = S ^ (P | (D & ~S)); \ + break; \ + case 0x3f: \ + out = ~(P & S); \ + break; \ + case 0x40: \ + out = P & (S & ~D); \ + break; \ + case 0x41: \ + out = ~(D | (P ^ S)); \ + break; \ + case 0x42: \ + out = (S ^ D) & (P ^ D); \ + break; \ + case 0x43: \ + out = ~(S ^ (P & ~(D & S))); \ + break; \ + case 0x44: \ + out = S & ~D; \ + break; \ + case 0x45: \ + out = ~(D | (P & ~S)); \ + break; \ + case 0x46: \ + out = D ^ (S | (P & D)); \ + break; \ + case 0x47: \ + out = ~(P ^ (S & (D ^ P))); \ + break; \ + case 0x48: \ + out = S & (D ^ P); \ + break; \ + case 0x49: \ + out = ~(P ^ (D ^ (S | (P & D)))); \ + break; \ + case 0x4a: \ + out = D ^ (P & (S | D)); \ + break; \ + case 0x4b: \ + out = P ^ (D | ~S); \ + break; \ + case 0x4c: \ + out = S & ~(D & P); \ + break; \ + case 0x4d: \ + out = ~(S ^ ((S ^ P) | (D ^ S))); \ + break; \ + case 0x4e: \ + out = P ^ (D | (S ^ P)); \ + break; \ + case 0x4f: \ + out = ~(P & (D | ~S)); \ + break; \ + case 0x50: \ + out = P & ~D; \ + break; \ + case 0x51: \ + out = ~(D | (S & ~P)); \ + break; \ + case 0x52: \ + out = D ^ (P | (S & D)); \ + break; \ + case 0x53: \ + out = ~(S ^ (P & (D ^ S))); \ + break; \ + case 0x54: \ + out = ~(D | ~(P | S)); \ + break; \ + case 0x55: \ + out = ~D; \ + break; \ + case 0x56: \ + out = D ^ (P | S); \ + break; \ + case 0x57: \ + out = ~(D & (P | S)); \ + break; \ + case 0x58: \ + out = P ^ (D & (S | P)); \ + break; \ + case 0x59: \ + out = D ^ (P | ~S); \ + break; \ + case 0x5a: \ + out = D ^ P; \ + break; \ + case 0x5b: \ + out = D ^ (P | ~(S | D)); \ + break; \ + case 0x5c: \ + out = D ^ (P | (S ^ D)); \ + break; \ + case 0x5d: \ + out = ~(D & (P | ~S)); \ + break; \ + case 0x5e: \ + out = D ^ (P | (S & ~D)); \ + break; \ + case 0x5f: \ + out = ~(D & P); \ + break; \ + case 0x60: \ + out = P & (D ^ S); \ + break; \ + case 0x61: \ + out = ~(D ^ (S ^ (P | (D & S)))); \ + break; \ + case 0x62: \ + out = D ^ (S & (P | D)); \ + break; \ + case 0x63: \ + out = S ^ (D | ~P); \ + break; \ + case 0x64: \ + out = S ^ (D & (P | S)); \ + break; \ + case 0x65: \ + out = D ^ (S | ~P); \ + break; \ + case 0x66: \ + out = D ^ S; \ + break; \ + case 0x67: \ + out = S ^ (D | ~(P | S)); \ + break; \ + case 0x68: \ + out = ~(D ^ (S ^ (P | ~(D | S)))); \ + break; \ + case 0x69: \ + out = ~(P ^ (D ^ S)); \ + break; \ + case 0x6a: \ + out = D ^ (P & S); \ + break; \ + case 0x6b: \ + out = ~(P ^ (S ^ (D & (P | S)))); \ + break; \ + case 0x6c: \ + out = S ^ (D & P); \ + break; \ + case 0x6d: \ + out = ~(P ^ (D ^ (S & (P | D)))); \ + break; \ + case 0x6e: \ + out = S ^ (D & (P | ~S)); \ + break; \ + case 0x6f: \ + out = ~(P & ~(D ^ S)); \ + break; \ + case 0x70: \ + out = P & ~(D & S); \ + break; \ + case 0x71: \ + out = ~(S ^ ((S ^ D) & (P ^ D))); \ + break; \ + case 0x72: \ + out = S ^ (D | (P ^ S)); \ + break; \ + case 0x73: \ + out = ~(S & (D | ~P)); \ + break; \ + case 0x74: \ + out = D ^ (S | (P ^ D)); \ + break; \ + case 0x75: \ + out = ~(D & (S | ~P)); \ + break; \ + case 0x76: \ + out = S ^ (D | (P & ~S)); \ + break; \ + case 0x77: \ + out = ~(D & S); \ + break; \ + case 0x78: \ + out = P ^ (D & S); \ + break; \ + case 0x79: \ + out = ~(D ^ (S ^ (P & (D | S)))); \ + break; \ + case 0x7a: \ + out = D ^ (P & (S | ~D)); \ + break; \ + case 0x7b: \ + out = ~(S & ~(D ^ P)); \ + break; \ + case 0x7c: \ + out = S ^ (P & (D | ~S)); \ + break; \ + case 0x7d: \ + out = ~(D & ~(P ^ S)); \ + break; \ + case 0x7e: \ + out = (S ^ P) | (D ^ S); \ + break; \ + case 0x7f: \ + out = ~(D & (P & S)); \ + break; \ + case 0x80: \ + out = D & (P & S); \ + break; \ + case 0x81: \ + out = ~((S ^ P) | (D ^ S)); \ + break; \ + case 0x82: \ + out = D & ~(P ^ S); \ + break; \ + case 0x83: \ + out = ~(S ^ (P & (D | ~S))); \ + break; \ + case 0x84: \ + out = S & ~(D ^ P); \ + break; \ + case 0x85: \ + out = ~(P ^ (D & (S | ~P))); \ + break; \ + case 0x86: \ + out = D ^ (S ^ (P & (D | S))); \ + break; \ + case 0x87: \ + out = ~(P ^ (D & S)); \ + break; \ + case 0x88: \ + out = D & S; \ + break; \ + case 0x89: \ + out = ~(S ^ (D | (P & ~S))); \ + break; \ + case 0x8a: \ + out = D & (S | ~P); \ + break; \ + case 0x8b: \ + out = ~(D ^ (S | (P ^ D))); \ + break; \ + case 0x8c: \ + out = S & (D | ~P); \ + break; \ + case 0x8d: \ + out = ~(S ^ (D | (P ^ S))); \ + break; \ + case 0x8e: \ + out = S ^ ((S ^ D) & (P ^ D)); \ + break; \ + case 0x8f: \ + out = ~(P & ~(D & S)); \ + break; \ + case 0x90: \ + out = P & ~(D ^ S); \ + break; \ + case 0x91: \ + out = ~(S ^ (D & (P | ~S))); \ + break; \ + case 0x92: \ + out = D ^ (P ^ (S & (D | P))); \ + break; \ + case 0x93: \ + out = ~(S ^ (P & D)); \ + break; \ + case 0x94: \ + out = P ^ (S ^ (D & (P | S))); \ + break; \ + case 0x95: \ + out = ~(D ^ (P & S)); \ + break; \ + case 0x96: \ + out = D ^ (P ^ S); \ + break; \ + case 0x97: \ + out = P ^ (S ^ (D | ~(P | S))); \ + break; \ + case 0x98: \ + out = ~(S ^ (D | ~(P | S))); \ + break; \ + case 0x99: \ + out = ~(D ^ S); \ + break; \ + case 0x9a: \ + out = D ^ (P & ~S); \ + break; \ + case 0x9b: \ + out = ~(S ^ (D & (P | S))); \ + break; \ + case 0x9c: \ + out = S ^ (P & ~D); \ + break; \ + case 0x9d: \ + out = ~(D ^ (S & (P | D))); \ + break; \ + case 0x9e: \ + out = D ^ (S ^ (P | (D & S))); \ + break; \ + case 0x9f: \ + out = ~(P & (D ^ S)); \ + break; \ + case 0xa0: \ + out = D & P; \ + break; \ + case 0xa1: \ + out = ~(P ^ (D | (S & ~P))); \ + break; \ + case 0xa2: \ + out = D & (P | ~S); \ + break; \ + case 0xa3: \ + out = ~(D ^ (P | (S ^ D))); \ + break; \ + case 0xa4: \ + out = ~(P ^ (D | ~(S | P))); \ + break; \ + case 0xa5: \ + out = ~(P ^ D); \ + break; \ + case 0xa6: \ + out = D ^ (S & ~P); \ + break; \ + case 0xa7: \ + out = ~(P ^ (D & (S | P))); \ + break; \ + case 0xa8: \ + out = D & (P | S); \ + break; \ + case 0xa9: \ + out = ~(D ^ (P | S)); \ + break; \ + case 0xaa: \ + out = D; \ + break; \ + case 0xab: \ + out = D | ~(P | S); \ + break; \ + case 0xac: \ + out = S ^ (P & (D ^ S)); \ + break; \ + case 0xad: \ + out = ~(D ^ (P | (S & D))); \ + break; \ + case 0xae: \ + out = D | (S & ~P); \ + break; \ + case 0xaf: \ + out = D | ~P; \ + break; \ + case 0xb0: \ + out = P & (D | ~S); \ + break; \ + case 0xb1: \ + out = ~(P ^ (D | (S ^ P))); \ + break; \ + case 0xb2: \ + out = S ^ ((S ^ P) | (D ^ S)); \ + break; \ + case 0xb3: \ + out = ~(S & ~(D & P)); \ + break; \ + case 0xb4: \ + out = P ^ (S & ~D); \ + break; \ + case 0xb5: \ + out = ~(D ^ (P & (S | D))); \ + break; \ + case 0xb6: \ + out = D ^ (P ^ (S | (D & P))); \ + break; \ + case 0xb7: \ + out = ~(S & (D ^ P)); \ + break; \ + case 0xb8: \ + out = P ^ (S & (D ^ P)); \ + break; \ + case 0xb9: \ + out = ~(D ^ (S | (P & D))); \ + break; \ + case 0xba: \ + out = D | (P & ~S); \ + break; \ + case 0xbb: \ + out = D | ~S; \ + break; \ + case 0xbc: \ + out = S ^ (P & ~(D & S)); \ + break; \ + case 0xbd: \ + out = ~((S ^ D) & (P ^ D)); \ + break; \ + case 0xbe: \ + out = D | (P ^ S); \ + break; \ + case 0xbf: \ + out = D | ~(P & S); \ + break; \ + case 0xc0: \ + out = P & S; \ + break; \ + case 0xc1: \ + out = ~(S ^ (P | (D & ~S))); \ + break; \ + case 0xc2: \ + out = ~(S ^ (P | ~(D | S))); \ + break; \ + case 0xc3: \ + out = ~(P ^ S); \ + break; \ + case 0xc4: \ + out = S & (P | ~D); \ + break; \ + case 0xc5: \ + out = ~(S ^ (P | (D ^ S))); \ + break; \ + case 0xc6: \ + out = S ^ (D & ~P); \ + break; \ + case 0xc7: \ + out = ~(P ^ (S & (D | P))); \ + break; \ + case 0xc8: \ + out = S & (D | P); \ + break; \ + case 0xc9: \ + out = ~(S ^ (P | D)); \ + break; \ + case 0xca: \ + out = D ^ (P & (S ^ D)); \ + break; \ + case 0xcb: \ + out = ~(S ^ (P | (D & S))); \ + break; \ + case 0xcc: \ + out = S; \ + break; \ + case 0xcd: \ + out = S | ~(D | P); \ + break; \ + case 0xce: \ + out = S | (D & ~P); \ + break; \ + case 0xcf: \ + out = S | ~P; \ + break; \ + case 0xd0: \ + out = P & (S | ~D); \ + break; \ + case 0xd1: \ + out = ~(P ^ (S | (D ^ P))); \ + break; \ + case 0xd2: \ + out = P ^ (D & ~S); \ + break; \ + case 0xd3: \ + out = ~(S ^ (P & (D | S))); \ + break; \ + case 0xd4: \ + out = S ^ ((S ^ P) & (P ^ D)); \ + break; \ + case 0xd5: \ + out = ~(D & ~(P & S)); \ + break; \ + case 0xd6: \ + out = P ^ (S ^ (D | (P & S))); \ + break; \ + case 0xd7: \ + out = ~(D & (P ^ S)); \ + break; \ + case 0xd8: \ + out = P ^ (D & (S ^ P)); \ + break; \ + case 0xd9: \ + out = ~(S ^ (D | (P & S))); \ + break; \ + case 0xda: \ + out = D ^ (P & ~(S & D)); \ + break; \ + case 0xdb: \ + out = ~((S ^ P) & (D ^ S)); \ + break; \ + case 0xdc: \ + out = S | (P & ~D); \ + break; \ + case 0xdd: \ + out = S | ~D; \ + break; \ + case 0xde: \ + out = S | (D ^ P); \ + break; \ + case 0xdf: \ + out = S | ~(D & P); \ + break; \ + case 0xe0: \ + out = P & (D | S); \ + break; \ + case 0xe1: \ + out = ~(P ^ (D | S)); \ + break; \ + case 0xe2: \ + out = D ^ (S & (P ^ D)); \ + break; \ + case 0xe3: \ + out = ~(P ^ (S | (D & P))); \ + break; \ + case 0xe4: \ + out = S ^ (D & (P ^ S)); \ + break; \ + case 0xe5: \ + out = ~(P ^ (D | (S & P))); \ + break; \ + case 0xe6: \ + out = S ^ (D & ~(P & S)); \ + break; \ + case 0xe7: \ + out = ~((S ^ P) & (P ^ D)); \ + break; \ + case 0xe8: \ + out = S ^ ((S ^ P) & (D ^ S)); \ + break; \ + case 0xe9: \ + out = ~(D ^ (S ^ (P & ~(D & S)))); \ + break; \ + case 0xea: \ + out = D | (P & S); \ + break; \ + case 0xeb: \ + out = D | ~(P ^ S); \ + break; \ + case 0xec: \ + out = S | (D & P); \ + break; \ + case 0xed: \ + out = S | ~(D ^ P); \ + break; \ + case 0xee: \ + out = D | S; \ + break; \ + case 0xef: \ + out = S | (D | ~P); \ + break; \ + case 0xf0: \ + out = P; \ + break; \ + case 0xf1: \ + out = P | ~(D | S); \ + break; \ + case 0xf2: \ + out = P | (D & ~S); \ + break; \ + case 0xf3: \ + out = P | ~S; \ + break; \ + case 0xf4: \ + out = P | (S & ~D); \ + break; \ + case 0xf5: \ + out = P | ~D; \ + break; \ + case 0xf6: \ + out = P | (D ^ S); \ + break; \ + case 0xf7: \ + out = P | ~(D & S); \ + break; \ + case 0xf8: \ + out = P | (D & S); \ + break; \ + case 0xf9: \ + out = P | ~(D ^ S); \ + break; \ + case 0xfa: \ + out = D | P; \ + break; \ + case 0xfb: \ + out = D | (P | ~S); \ + break; \ + case 0xfc: \ + out = P | S; \ + break; \ + case 0xfd: \ + out = P | (S | ~D); \ + break; \ + case 0xfe: \ + out = D | (P | S); \ + break; \ + case 0xff: \ + out = ~0; \ + break; \ + } \ + } +#define ROPMIX \ + { \ + old_dest_dat = dest_dat; \ + ROPMIX_READ(dest_dat, pat_dat, src_dat); \ + out = (out & s3->accel.wrt_mask) | (old_dest_dat & ~s3->accel.wrt_mask); \ + } - -#define ROPMIX_READ(D, P, S) \ - { \ - switch (rop) { \ - case 0x00: out = 0; break; \ - case 0x01: out = ~(D | (P | S)); break; \ - case 0x02: out = D & ~(P | S); break; \ - case 0x03: out = ~(P | S); break; \ - case 0x04: out = S & ~(D | P); break; \ - case 0x05: out = ~(D | P); break; \ - case 0x06: out = ~(P | ~(D ^ S)); break; \ - case 0x07: out = ~(P | (D & S)); break; \ - case 0x08: out = S & (D & ~P); break; \ - case 0x09: out = ~(P | (D ^ S)); break; \ - case 0x0a: out = D & ~P; break; \ - case 0x0b: out = ~(P | (S & ~D)); break; \ - case 0x0c: out = S & ~P; break; \ - case 0x0d: out = ~(P | (D & ~S)); break; \ - case 0x0e: out = ~(P | ~(D | S)); break; \ - case 0x0f: out = ~P; break; \ - case 0x10: out = P & ~(D | S); break; \ - case 0x11: out = ~(D | S); break; \ - case 0x12: out = ~(S | ~(D ^ P)); break; \ - case 0x13: out = ~(S | (D & P)); break; \ - case 0x14: out = ~(D | ~(P ^ S)); break; \ - case 0x15: out = ~(D | (P & S)); break; \ - case 0x16: out = P ^ (S ^ (D & ~(P & S))); break; \ - case 0x17: out = ~(S ^ ((S ^ P) & (D ^ S))); break; \ - case 0x18: out = (S ^ P) & (P ^ D); break; \ - case 0x19: out = ~(S ^ (D & ~(P & S))); break; \ - case 0x1a: out = P ^ (D | (S & P)); break; \ - case 0x1b: out = ~(S ^ (D & (P ^ S))); break; \ - case 0x1c: out = P ^ (S | (D & P)); break; \ - case 0x1d: out = ~(D ^ (S & (P ^ D))); break; \ - case 0x1e: out = P ^ (D | S); break; \ - case 0x1f: out = ~(P & (D | S)); break; \ - case 0x20: out = D & (P & ~S); break; \ - case 0x21: out = ~(S | (D ^ P)); break; \ - case 0x22: out = D & ~S; break; \ - case 0x23: out = ~(S | (P & ~D)); break; \ - case 0x24: out = (S ^ P) & (D ^ S); break; \ - case 0x25: out = ~(P ^ (D & ~(S & P))); break; \ - case 0x26: out = S ^ (D | (P & S)); break; \ - case 0x27: out = S ^ (D | ~(P ^ S)); break; \ - case 0x28: out = D & (P ^ S); break; \ - case 0x29: out = ~(P ^ (S ^ (D | (P & S)))); break; \ - case 0x2a: out = D & ~(P & S); break; \ - case 0x2b: out = ~(S ^ ((S ^ P) & (P ^ D))); break; \ - case 0x2c: out = S ^ (P & (D | S)); break; \ - case 0x2d: out = P ^ (S | ~D); break; \ - case 0x2e: out = P ^ (S | (D ^ P)); break; \ - case 0x2f: out = ~(P & (S | ~D)); break; \ - case 0x30: out = P & ~S; break; \ - case 0x31: out = ~(S | (D & ~P)); break; \ - case 0x32: out = S ^ (D | (P | S)); break; \ - case 0x33: out = ~S; break; \ - case 0x34: out = S ^ (P | (D & S)); break; \ - case 0x35: out = S ^ (P | ~(D ^ S)); break; \ - case 0x36: out = S ^ (D | P); break; \ - case 0x37: out = ~(S & (D | P)); break; \ - case 0x38: out = P ^ (S & (D | P)); break; \ - case 0x39: out = S ^ (P | ~D); break; \ - case 0x3a: out = S ^ (P | (D ^ S)); break; \ - case 0x3b: out = ~(S & (P | ~D)); break; \ - case 0x3c: out = P ^ S; break; \ - case 0x3d: out = S ^ (P | ~(D | S)); break; \ - case 0x3e: out = S ^ (P | (D & ~S)); break; \ - case 0x3f: out = ~(P & S); break; \ - case 0x40: out = P & (S & ~D); break; \ - case 0x41: out = ~(D | (P ^ S)); break; \ - case 0x42: out = (S ^ D) & (P ^ D); break; \ - case 0x43: out = ~(S ^ (P & ~(D & S))); break; \ - case 0x44: out = S & ~D; break; \ - case 0x45: out = ~(D | (P & ~S)); break; \ - case 0x46: out = D ^ (S | (P & D)); break; \ - case 0x47: out = ~(P ^ (S & (D ^ P))); break; \ - case 0x48: out = S & (D ^ P); break; \ - case 0x49: out = ~(P ^ (D ^ (S | (P & D)))); break; \ - case 0x4a: out = D ^ (P & (S | D)); break; \ - case 0x4b: out = P ^ (D | ~S); break; \ - case 0x4c: out = S & ~(D & P); break; \ - case 0x4d: out = ~(S ^ ((S ^ P) | (D ^ S))); break; \ - case 0x4e: out = P ^ (D | (S ^ P)); break; \ - case 0x4f: out = ~(P & (D | ~S)); break; \ - case 0x50: out = P & ~D; break; \ - case 0x51: out = ~(D | (S & ~P)); break; \ - case 0x52: out = D ^ (P | (S & D)); break; \ - case 0x53: out = ~(S ^ (P & (D ^ S))); break; \ - case 0x54: out = ~(D | ~(P | S)); break; \ - case 0x55: out = ~D; break; \ - case 0x56: out = D ^ (P | S); break; \ - case 0x57: out = ~(D & (P | S)); break; \ - case 0x58: out = P ^ (D & (S | P)); break; \ - case 0x59: out = D ^ (P | ~S); break; \ - case 0x5a: out = D ^ P; break; \ - case 0x5b: out = D ^ (P | ~(S | D)); break; \ - case 0x5c: out = D ^ (P | (S ^ D)); break; \ - case 0x5d: out = ~(D & (P | ~S)); break; \ - case 0x5e: out = D ^ (P | (S & ~D)); break; \ - case 0x5f: out = ~(D & P); break; \ - case 0x60: out = P & (D ^ S); break; \ - case 0x61: out = ~(D ^ (S ^ (P | (D & S)))); break; \ - case 0x62: out = D ^ (S & (P | D)); break; \ - case 0x63: out = S ^ (D | ~P); break; \ - case 0x64: out = S ^ (D & (P | S)); break; \ - case 0x65: out = D ^ (S | ~P); break; \ - case 0x66: out = D ^ S; break; \ - case 0x67: out = S ^ (D | ~(P | S)); break; \ - case 0x68: out = ~(D ^ (S ^ (P | ~(D | S)))); break; \ - case 0x69: out = ~(P ^ (D ^ S)); break; \ - case 0x6a: out = D ^ (P & S); break; \ - case 0x6b: out = ~(P ^ (S ^ (D & (P | S)))); break; \ - case 0x6c: out = S ^ (D & P); break; \ - case 0x6d: out = ~(P ^ (D ^ (S & (P | D)))); break; \ - case 0x6e: out = S ^ (D & (P | ~S)); break; \ - case 0x6f: out = ~(P & ~(D ^ S)); break; \ - case 0x70: out = P & ~(D & S); break; \ - case 0x71: out = ~(S ^ ((S ^ D) & (P ^ D))); break; \ - case 0x72: out = S ^ (D | (P ^ S)); break; \ - case 0x73: out = ~(S & (D | ~P)); break; \ - case 0x74: out = D ^ (S | (P ^ D)); break; \ - case 0x75: out = ~(D & (S | ~P)); break; \ - case 0x76: out = S ^ (D | (P & ~S)); break; \ - case 0x77: out = ~(D & S); break; \ - case 0x78: out = P ^ (D & S); break; \ - case 0x79: out = ~(D ^ (S ^ (P & (D | S)))); break; \ - case 0x7a: out = D ^ (P & (S | ~D)); break; \ - case 0x7b: out = ~(S & ~(D ^ P)); break; \ - case 0x7c: out = S ^ (P & (D | ~S)); break; \ - case 0x7d: out = ~(D & ~(P ^ S)); break; \ - case 0x7e: out = (S ^ P) | (D ^ S); break; \ - case 0x7f: out = ~(D & (P & S)); break; \ - case 0x80: out = D & (P & S); break; \ - case 0x81: out = ~((S ^ P) | (D ^ S)); break; \ - case 0x82: out = D & ~(P ^ S); break; \ - case 0x83: out = ~(S ^ (P & (D | ~S))); break; \ - case 0x84: out = S & ~(D ^ P); break; \ - case 0x85: out = ~(P ^ (D & (S | ~P))); break; \ - case 0x86: out = D ^ (S ^ (P & (D | S))); break; \ - case 0x87: out = ~(P ^ (D & S)); break; \ - case 0x88: out = D & S; break; \ - case 0x89: out = ~(S ^ (D | (P & ~S))); break; \ - case 0x8a: out = D & (S | ~P); break; \ - case 0x8b: out = ~(D ^ (S | (P ^ D))); break; \ - case 0x8c: out = S & (D | ~P); break; \ - case 0x8d: out = ~(S ^ (D | (P ^ S))); break; \ - case 0x8e: out = S ^ ((S ^ D) & (P ^ D)); break; \ - case 0x8f: out = ~(P & ~(D & S)); break; \ - case 0x90: out = P & ~(D ^ S); break; \ - case 0x91: out = ~(S ^ (D & (P | ~S))); break; \ - case 0x92: out = D ^ (P ^ (S & (D | P))); break; \ - case 0x93: out = ~(S ^ (P & D)); break; \ - case 0x94: out = P ^ (S ^ (D & (P | S))); break; \ - case 0x95: out = ~(D ^ (P & S)); break; \ - case 0x96: out = D ^ (P ^ S); break; \ - case 0x97: out = P ^ (S ^ (D | ~(P | S))); break; \ - case 0x98: out = ~(S ^ (D | ~(P | S))); break; \ - case 0x99: out = ~(D ^ S); break; \ - case 0x9a: out = D ^ (P & ~S); break; \ - case 0x9b: out = ~(S ^ (D & (P | S))); break; \ - case 0x9c: out = S ^ (P & ~D); break; \ - case 0x9d: out = ~(D ^ (S & (P | D))); break; \ - case 0x9e: out = D ^ (S ^ (P | (D & S))); break; \ - case 0x9f: out = ~(P & (D ^ S)); break; \ - case 0xa0: out = D & P; break; \ - case 0xa1: out = ~(P ^ (D | (S & ~P))); break; \ - case 0xa2: out = D & (P | ~S); break; \ - case 0xa3: out = ~(D ^ (P | (S ^ D))); break; \ - case 0xa4: out = ~(P ^ (D | ~(S | P))); break; \ - case 0xa5: out = ~(P ^ D); break; \ - case 0xa6: out = D ^ (S & ~P); break; \ - case 0xa7: out = ~(P ^ (D & (S | P))); break; \ - case 0xa8: out = D & (P | S); break; \ - case 0xa9: out = ~(D ^ (P | S)); break; \ - case 0xaa: out = D; break; \ - case 0xab: out = D | ~(P | S); break; \ - case 0xac: out = S ^ (P & (D ^ S)); break; \ - case 0xad: out = ~(D ^ (P | (S & D))); break; \ - case 0xae: out = D | (S & ~P); break; \ - case 0xaf: out = D | ~P; break; \ - case 0xb0: out = P & (D | ~S); break; \ - case 0xb1: out = ~(P ^ (D | (S ^ P))); break; \ - case 0xb2: out = S ^ ((S ^ P) | (D ^ S)); break; \ - case 0xb3: out = ~(S & ~(D & P)); break; \ - case 0xb4: out = P ^ (S & ~D); break; \ - case 0xb5: out = ~(D ^ (P & (S | D))); break; \ - case 0xb6: out = D ^ (P ^ (S | (D & P))); break; \ - case 0xb7: out = ~(S & (D ^ P)); break; \ - case 0xb8: out = P ^ (S & (D ^ P)); break; \ - case 0xb9: out = ~(D ^ (S | (P & D))); break; \ - case 0xba: out = D | (P & ~S); break; \ - case 0xbb: out = D | ~S; break; \ - case 0xbc: out = S ^ (P & ~(D & S)); break; \ - case 0xbd: out = ~((S ^ D) & (P ^ D)); break; \ - case 0xbe: out = D | (P ^ S); break; \ - case 0xbf: out = D | ~(P & S); break; \ - case 0xc0: out = P & S; break; \ - case 0xc1: out = ~(S ^ (P | (D & ~S))); break; \ - case 0xc2: out = ~(S ^ (P | ~(D | S))); break; \ - case 0xc3: out = ~(P ^ S); break; \ - case 0xc4: out = S & (P | ~D); break; \ - case 0xc5: out = ~(S ^ (P | (D ^ S))); break; \ - case 0xc6: out = S ^ (D & ~P); break; \ - case 0xc7: out = ~(P ^ (S & (D | P))); break; \ - case 0xc8: out = S & (D | P); break; \ - case 0xc9: out = ~(S ^ (P | D)); break; \ - case 0xca: out = D ^ (P & (S ^ D)); break; \ - case 0xcb: out = ~(S ^ (P | (D & S))); break; \ - case 0xcc: out = S; break; \ - case 0xcd: out = S | ~(D | P); break; \ - case 0xce: out = S | (D & ~P); break; \ - case 0xcf: out = S | ~P; break; \ - case 0xd0: out = P & (S | ~D); break; \ - case 0xd1: out = ~(P ^ (S | (D ^ P))); break; \ - case 0xd2: out = P ^ (D & ~S); break; \ - case 0xd3: out = ~(S ^ (P & (D | S))); break; \ - case 0xd4: out = S ^ ((S ^ P) & (P ^ D)); break; \ - case 0xd5: out = ~(D & ~(P & S)); break; \ - case 0xd6: out = P ^ (S ^ (D | (P & S))); break; \ - case 0xd7: out = ~(D & (P ^ S)); break; \ - case 0xd8: out = P ^ (D & (S ^ P)); break; \ - case 0xd9: out = ~(S ^ (D | (P & S))); break; \ - case 0xda: out = D ^ (P & ~(S & D)); break; \ - case 0xdb: out = ~((S ^ P) & (D ^ S)); break; \ - case 0xdc: out = S | (P & ~D); break; \ - case 0xdd: out = S | ~D; break; \ - case 0xde: out = S | (D ^ P); break; \ - case 0xdf: out = S | ~(D & P); break; \ - case 0xe0: out = P & (D | S); break; \ - case 0xe1: out = ~(P ^ (D | S)); break; \ - case 0xe2: out = D ^ (S & (P ^ D)); break; \ - case 0xe3: out = ~(P ^ (S | (D & P))); break; \ - case 0xe4: out = S ^ (D & (P ^ S)); break; \ - case 0xe5: out = ~(P ^ (D | (S & P))); break; \ - case 0xe6: out = S ^ (D & ~(P & S)); break; \ - case 0xe7: out = ~((S ^ P) & (P ^ D)); break; \ - case 0xe8: out = S ^ ((S ^ P) & (D ^ S)); break; \ - case 0xe9: out = ~(D ^ (S ^ (P & ~(D & S)))); break; \ - case 0xea: out = D | (P & S); break; \ - case 0xeb: out = D | ~(P ^ S); break; \ - case 0xec: out = S | (D & P); break; \ - case 0xed: out = S | ~(D ^ P); break; \ - case 0xee: out = D | S; break; \ - case 0xef: out = S | (D | ~P); break; \ - case 0xf0: out = P; break; \ - case 0xf1: out = P | ~(D | S); break; \ - case 0xf2: out = P | (D & ~S); break; \ - case 0xf3: out = P | ~S; break; \ - case 0xf4: out = P | (S & ~D); break; \ - case 0xf5: out = P | ~D; break; \ - case 0xf6: out = P | (D ^ S); break; \ - case 0xf7: out = P | ~(D & S); break; \ - case 0xf8: out = P | (D & S); break; \ - case 0xf9: out = P | ~(D ^ S); break; \ - case 0xfa: out = D | P; break; \ - case 0xfb: out = D | (P | ~S); break; \ - case 0xfc: out = P | S; break; \ - case 0xfd: out = P | (S | ~D); break; \ - case 0xfe: out = D | (P | S); break; \ - case 0xff: out = ~0; break; \ - } \ - } - - -#define ROPMIX { \ - old_dest_dat = dest_dat; \ - ROPMIX_READ(dest_dat, pat_dat, src_dat); \ - out = (out & s3->accel.wrt_mask) | (old_dest_dat & ~s3->accel.wrt_mask); \ - } - - -#define WRITE(addr, dat) if (s3->bpp == 0 && !s3->color_16bit) \ - { \ - svga->vram[dword_remap(svga, addr) & s3->vram_mask] = dat; \ - svga->changedvram[(dword_remap(svga, addr) & s3->vram_mask) >> 12] = changeframecount; \ - } \ - else if (s3->bpp == 1 || 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] = changeframecount; \ - } \ - else if (s3->bpp == 2) \ - { \ - svga->vram[dword_remap(svga, addr) & s3->vram_mask] = dat; \ - svga->changedvram[(dword_remap(svga, addr) & s3->vram_mask) >> 12] = changeframecount; \ - } \ - else \ - { \ - vram_l[dword_remap_l(svga, addr) & (s3->vram_mask >> 2)] = dat; \ - svga->changedvram[(dword_remap_l(svga, addr) & (s3->vram_mask >> 2)) >> 10] = changeframecount; \ - } - +#define WRITE(addr, dat) \ + 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) { \ + 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) { \ + 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 { \ + vram_l[dword_remap_l(svga, addr) & (s3->vram_mask >> 2)] = dat; \ + svga->changedvram[(dword_remap_l(svga, addr) & (s3->vram_mask >> 2)) >> 10] = svga->monitor->mon_changeframecount; \ + } static __inline void convert_to_rgb32(int idf, int is_yuv, uint32_t val, uint8_t *r, uint8_t *g, uint8_t *b, uint8_t *r2, uint8_t *g2, uint8_t *b2) { - static double dr = 0.0, dg = 0.0, db = 0.0; - static double dY1 = 0.0, dCr = 0.0, dY2 = 0.0, dCb = 0.0; - static double dU = 0.0, dV = 0.0; - + static double dr = 0.0; + static double dg = 0.0; + static double db = 0.0; + static double dY1 = 0.0; + static double dCr = 0.0; + static double dY2 = 0.0; + static double dCb = 0.0; + static double dU = 0.0; + static double dV = 0.0; + switch (idf) { - case 0: /* 8 bpp, RGB 3-3-2 */ - dr = (double) ((val >> 5) & 0x07); - dg = (double) ((val >> 2) & 0x07); - db = (double) (val & 0x03); - dr = (dr / 7.0) * 255.0; - dg = (dg / 7.0) * 255.0; - db = (db / 3.0) * 255.0; - break; - case 3: /* 32bpp, RGB 8-8-8 */ - dr = (double) ((val >> 16) & 0xff); - dg = (double) ((val >> 8) & 0xff); - db = (double) (val & 0xff); - break; - case 4: /* YCbCr */ - if (is_yuv) { - dU = ((double) (val & 0xff)) - 128.0; - dY1 = (double) ((val >> 8) & 0xff); - dY1 = (298.0 * (dY1 - 16.0)) / 256.0; - dV = ((double) ((val >> 16) & 0xff)) - 128.0; - dY2 = (double) ((val >> 24) & 0xff); - dY2 = (298.0 * (dY2 - 16.0)) / 256.0; - - dr = (309.0 * dV) / 256.0; - dg = ((100.0 * dU) + (208.0 * dV)) / 256.0; - db = (516.0 * dU) / 256.0; - } else { - dY1 = (double) (val & 0xff); - dCr = ((double) ((val >> 8) & 0xff)) - 128.0; - dY2 = (double) ((val >> 16) & 0xff); - dCb = ((double) ((val >> 24) & 0xff)) - 128.0; - - dr = (359.0 * dCr) / 256.0; - dg = ((88.0 * dCb) + (183.0 * dCr)) / 2560.0; - db = (453.0 * dCr) / 256.0; - } - - *r = (uint8_t) round(dY1 + dr); - CLAMP(*r); - *g = (uint8_t) round(dY1 - dg); - CLAMP(*g); - *b = (uint8_t) round(dY1 + db); - CLAMP(*b); - - *r2 = (uint8_t) round(dY2 + dr); - CLAMP(*r2); - *g2 = (uint8_t) round(dY2 - dg); - CLAMP(*g2); - *b2 = (uint8_t) round(dY2 + db); - CLAMP(*b2); - return; - case 5: /* 16bpp, raw */ - case 7: /* 16bpp, RGB 5-6-5 */ - dr = (double) ((val >> 11) & 0x1f); - dg = (double) ((val >> 5) & 0x03f); - db = (double) (val & 0x1f); - dr = (dr / 31.0) * 255.0; - dg = (dg / 63.0) * 255.0; - db = (db / 31.0) * 255.0; - break; - case 6: /* 15bpp, RGB 5-5-5 */ - dr = (double) ((val >> 10) & 0x1f); - dg = (double) ((val >> 5) & 0x01f); - db = (double) (val & 0x1f); - dr = (dr / 31.0) * 255.0; - dg = (dg / 31.0) * 255.0; - db = (db / 31.0) * 255.0; - break; + case 0: /* 8 bpp, RGB 3-3-2 */ + dr = (double) ((val >> 5) & 0x07); + dg = (double) ((val >> 2) & 0x07); + db = (double) (val & 0x03); + dr = (dr / 7.0) * 255.0; + dg = (dg / 7.0) * 255.0; + db = (db / 3.0) * 255.0; + break; + case 3: /* 32bpp, RGB 8-8-8 */ + dr = (double) ((val >> 16) & 0xff); + dg = (double) ((val >> 8) & 0xff); + db = (double) (val & 0xff); + break; + case 4: /* YCbCr */ + if (is_yuv) { + dU = ((double) (val & 0xff)) - 128.0; + dY1 = (double) ((val >> 8) & 0xff); + dY1 = (298.0 * (dY1 - 16.0)) / 256.0; + dV = ((double) ((val >> 16) & 0xff)) - 128.0; + dY2 = (double) ((val >> 24) & 0xff); + dY2 = (298.0 * (dY2 - 16.0)) / 256.0; + + dr = (309.0 * dV) / 256.0; + dg = ((100.0 * dU) + (208.0 * dV)) / 256.0; + db = (516.0 * dU) / 256.0; + } else { + dY1 = (double) (val & 0xff); + dCr = ((double) ((val >> 8) & 0xff)) - 128.0; + dY2 = (double) ((val >> 16) & 0xff); + dCb = ((double) ((val >> 24) & 0xff)) - 128.0; + + dr = (359.0 * dCr) / 256.0; + dg = ((88.0 * dCb) + (183.0 * dCr)) / 2560.0; + db = (453.0 * dCr) / 256.0; + } + + *r = (uint8_t) round(dY1 + dr); + CLAMP(*r); + *g = (uint8_t) round(dY1 - dg); + CLAMP(*g); + *b = (uint8_t) round(dY1 + db); + CLAMP(*b); + + *r2 = (uint8_t) round(dY2 + dr); + CLAMP(*r2); + *g2 = (uint8_t) round(dY2 - dg); + CLAMP(*g2); + *b2 = (uint8_t) round(dY2 + db); + CLAMP(*b2); + return; + case 5: /* 16bpp, raw */ + case 7: /* 16bpp, RGB 5-6-5 */ + dr = (double) ((val >> 11) & 0x1f); + dg = (double) ((val >> 5) & 0x03f); + db = (double) (val & 0x1f); + dr = (dr / 31.0) * 255.0; + dg = (dg / 63.0) * 255.0; + db = (db / 31.0) * 255.0; + break; + case 6: /* 15bpp, RGB 5-5-5 */ + dr = (double) ((val >> 10) & 0x1f); + dg = (double) ((val >> 5) & 0x01f); + db = (double) (val & 0x1f); + dr = (dr / 31.0) * 255.0; + dg = (dg / 31.0) * 255.0; + db = (db / 31.0) * 255.0; + break; + + default: + break; } - + *r = (uint8_t) round(dr); *g = (uint8_t) round(dg); *b = (uint8_t) round(db); } - - + static __inline void convert_from_rgb32(int idf, int odf, int is_yuv, uint32_t *val, uint8_t r, uint8_t g, uint8_t b, uint8_t r2, uint8_t g2, uint8_t b2) { - static double dr = 0.0, dg = 0.0, db = 0.0; - static double dr2 = 0.0, dg2 = 0.0, db2 = 0.0; - static double dY1 = 0.0, dCr = 0.0, dY2 = 0.0, dCb = 0.0; - static double dU = 0.0, dV = 0.0; - + static double dr = 0.0; + static double dg = 0.0; + static double db = 0.0; + static double dr2 = 0.0; + static double dg2 = 0.0; + static double db2 = 0.0; + static double dY1 = 0.0; + static double dCr = 0.0; + static double dY2 = 0.0; + static double dCb = 0.0; + static double dU = 0.0; + static double dV = 0.0; + dr = (double) r; dg = (double) g; db = (double) b; - + switch (odf) { - case 0: /* 8 bpp, RGB 3-3-2 */ - switch (idf) { - case 3: - *val = (((uint32_t) round(dr)) << 16) + (((uint32_t) round(dg)) << 8) + ((uint32_t) round(db)); - break; - case 5: - case 7: - dr = (dr / 255.0) * 31.0; - dg = (dg / 255.0) * 63.0; - db = (db / 255.0) * 31.0; - *val = (((uint32_t) round(dr)) << 11) + (((uint32_t) round(dg)) << 5) + ((uint32_t) round(db)); - break; - case 6: - dr = (dr / 255.0) * 31.0; - dg = (dg / 255.0) * 31.0; - db = (db / 255.0) * 31.0; - *val = (((uint32_t) round(dr)) << 10) + (((uint32_t) round(dg)) << 5) + ((uint32_t) round(db)); - break; - case 0: - default: - dr = (dr / 255.0) * 7.0; - dg = (dg / 255.0) * 7.0; - db = (db / 255.0) * 3.0; - *val = (((uint32_t) round(dr)) << 5) + (((uint32_t) round(dg)) << 2) + ((uint32_t) round(db)); - break; - } - break; - case 3: /* 32bpp, RGB 8-8-8 */ - *val = (((uint32_t) round(dr)) << 16) + (((uint32_t) round(dg)) << 8) + ((uint32_t) round(db)); - break; - case 4: /* YCbCr */ - dr2 = (double) r2; - dg2 = (double) g2; - db2 = (double) b2; - - if (is_yuv) { - dU = ((113046.0 * dg2) - (71552.0 * dr2) - (69488.0 * db2)) / 28509.0; - dV = ((3328.0 * dr2) + (800.0 * db2) - (4128.0 * dg2)) / 663.0; - dY1 = dr - ((309 * dV) / 256.0); - dY2 = dr2 - ((309 * dV) / 256.0); - - *val = ((uint32_t) round(dU)) + (((uint32_t) round(dY1)) << 8) + (((uint32_t) round(dV)) << 16) + (((uint32_t) round(dY2)) << 24); - } else { - dCr = ((128.0 * db2) - (128.0 * dr2)) / 47.0; - dCb = ((128.0 * dr2) - (128.0 * dg2) - (271.0 * dCr)) / 44.0; - dY1 = dr - ((359.0 * dCr) / 256.0); - dY2 = dr2 - ((359.0 * dCr) / 256.0); - - *val = ((uint32_t) round(dY1)) + (((uint32_t) round(dCr)) << 8) + (((uint32_t) round(dY2)) << 16) + (((uint32_t) round(dCb)) << 24); - } - return; - case 5: /* 16bpp, raw */ - case 7: /* 16bpp, RGB 5-6-5 */ - dr = (dr / 255.0) * 31.0; - dg = (dg / 255.0) * 63.0; - db = (db / 255.0) * 31.0; - *val = (((uint32_t) round(dr)) << 11) + (((uint32_t) round(dg)) << 5) + ((uint32_t) round(db)); - break; - case 6: /* 15bpp, RGB 5-5-5 */ - dr = (dr / 255.0) * 31.0; - dg = (dg / 255.0) * 31.0; - db = (db / 255.0) * 31.0; - *val = (((uint32_t) round(dr)) << 10) + (((uint32_t) round(dg)) << 5) + ((uint32_t) round(db)); - break; + case 0: /* 8 bpp, RGB 3-3-2 */ + switch (idf) { + case 3: + *val = (((uint32_t) round(dr)) << 16) + (((uint32_t) round(dg)) << 8) + ((uint32_t) round(db)); + break; + case 5: + case 7: + dr = (dr / 255.0) * 31.0; + dg = (dg / 255.0) * 63.0; + db = (db / 255.0) * 31.0; + *val = (((uint32_t) round(dr)) << 11) + (((uint32_t) round(dg)) << 5) + ((uint32_t) round(db)); + break; + case 6: + dr = (dr / 255.0) * 31.0; + dg = (dg / 255.0) * 31.0; + db = (db / 255.0) * 31.0; + *val = (((uint32_t) round(dr)) << 10) + (((uint32_t) round(dg)) << 5) + ((uint32_t) round(db)); + break; + case 0: + default: + dr = (dr / 255.0) * 7.0; + dg = (dg / 255.0) * 7.0; + db = (db / 255.0) * 3.0; + *val = (((uint32_t) round(dr)) << 5) + (((uint32_t) round(dg)) << 2) + ((uint32_t) round(db)); + break; + } + break; + case 3: /* 32bpp, RGB 8-8-8 */ + *val = (((uint32_t) round(dr)) << 16) + (((uint32_t) round(dg)) << 8) + ((uint32_t) round(db)); + break; + case 4: /* YCbCr */ + dr2 = (double) r2; + dg2 = (double) g2; + db2 = (double) b2; + + if (is_yuv) { + dU = ((113046.0 * dg2) - (71552.0 * dr2) - (69488.0 * db2)) / 28509.0; + dV = ((3328.0 * dr2) + (800.0 * db2) - (4128.0 * dg2)) / 663.0; + dY1 = dr - ((309 * dV) / 256.0); + dY2 = dr2 - ((309 * dV) / 256.0); + + *val = ((uint32_t) round(dU)) + (((uint32_t) round(dY1)) << 8) + (((uint32_t) round(dV)) << 16) + (((uint32_t) round(dY2)) << 24); + } else { + dCr = ((128.0 * db2) - (128.0 * dr2)) / 47.0; + dCb = ((128.0 * dr2) - (128.0 * dg2) - (271.0 * dCr)) / 44.0; + dY1 = dr - ((359.0 * dCr) / 256.0); + dY2 = dr2 - ((359.0 * dCr) / 256.0); + + *val = ((uint32_t) round(dY1)) + (((uint32_t) round(dCr)) << 8) + (((uint32_t) round(dY2)) << 16) + (((uint32_t) round(dCb)) << 24); + } + return; + case 5: /* 16bpp, raw */ + case 7: /* 16bpp, RGB 5-6-5 */ + dr = (dr / 255.0) * 31.0; + dg = (dg / 255.0) * 63.0; + db = (db / 255.0) * 31.0; + *val = (((uint32_t) round(dr)) << 11) + (((uint32_t) round(dg)) << 5) + ((uint32_t) round(db)); + break; + case 6: /* 15bpp, RGB 5-5-5 */ + dr = (dr / 255.0) * 31.0; + dg = (dg / 255.0) * 31.0; + db = (db / 255.0) * 31.0; + *val = (((uint32_t) round(dr)) << 10) + (((uint32_t) round(dg)) << 5) + ((uint32_t) round(db)); + break; + + default: + break; } } @@ -5010,1643 +6065,1749 @@ convert_from_rgb32(int idf, int odf, int is_yuv, uint32_t *val, uint8_t r, uint8 static void s3_visionx68_video_engine_op(uint32_t cpu_dat, s3_t *s3) { - svga_t *svga = &s3->svga; - int idf, odf, host; - int is_yuv; - uint32_t src, dest = 0x00000000; - uint8_t r = 0x00, g = 0x00, b = 0x00, r2 = 0x00, g2 = 0x00, b2 = 0x00; - uint16_t *vram_w = (uint16_t *)svga->vram; - uint32_t *vram_l = (uint32_t *)svga->vram; - uint32_t k2 = 0, dda = 0, diff = 0; - int count = -1; + svga_t *svga = &s3->svga; + int idf; + int odf; + int host; + int is_yuv; + uint32_t src; + uint32_t dest = 0x00000000; + uint8_t r = 0x00; + uint8_t g = 0x00; + uint8_t b = 0x00; + uint8_t r2 = 0x00; + uint8_t g2 = 0x00; + uint8_t b2 = 0x00; + uint16_t *vram_w = (uint16_t *) svga->vram; + uint32_t *vram_l = (uint32_t *) svga->vram; + uint32_t k2 = 0; + uint32_t dda = 0; + uint32_t diff = 0; + int count = -1; - idf = s3->videoengine.idf; - odf = s3->videoengine.odf; - is_yuv = s3->videoengine.yuv; - host = s3->videoengine.host_data; + idf = s3->videoengine.idf; + odf = s3->videoengine.odf; + is_yuv = s3->videoengine.yuv; + host = s3->videoengine.host_data; - k2 = s3->videoengine.k2 - 0x700; - dda = s3->videoengine.dda_init_accumulator - 0xf00; - diff = 0xff - k2; + k2 = s3->videoengine.k2 - 0x700; + dda = s3->videoengine.dda_init_accumulator - 0xf00; + diff = 0xff - k2; - s3->videoengine.busy = 1; - - if (host) { - if (idf == 0 && odf == 0) { - if (s3->bpp == 0) - count = 4; - else if (s3->bpp == 1) - count = 2; - else - count = 1; - } else { - if (idf == 0) - count = 4; - else if (idf == 3) - count = 1; - else - count = 2; - } - } + s3->videoengine.busy = 1; - if (s3->videoengine.input == 1) { - if (s3->videoengine.scale_down) { - if (s3->bpp > 1) { - s3->videoengine.sx = k2 - dda + diff; - s3->videoengine.sx_backup = s3->videoengine.len - s3->videoengine.start; - } else { - s3->videoengine.sx = k2 - dda + diff - 1; - s3->videoengine.sx_backup = s3->videoengine.len - s3->videoengine.start - 1; - } - s3->videoengine.sx_scale_inc = (double)((s3->videoengine.sx_backup >> 1)); - s3->videoengine.sx_scale_inc = s3->videoengine.sx_scale_inc / (double)((s3->videoengine.sx >> 1)); - } else { - s3->videoengine.sx_scale = (double)(s3->videoengine.k1 - 2); - s3->videoengine.sx_scale_dec = (s3->videoengine.sx_scale / (double)(s3->videoengine.len - s3->videoengine.start - 2)); + if (host) { + if (idf == 0 && odf == 0) { + if (s3->bpp == 0) + count = 4; + else if (s3->bpp == 1) + count = 2; + else + count = 1; + } else { + if (idf == 0) + count = 4; + else if (idf == 3) + count = 1; + else + count = 2; + } + } - if (s3->videoengine.sx_scale_dec >= 0.5) { - s3->videoengine.sx_scale++; - } - } - - if (s3->bpp == 0) { - s3->videoengine.dest = s3->videoengine.dest_base + s3->width; - s3->videoengine.src = s3->videoengine.src_base + s3->width; - } else if (s3->bpp == 1) { - s3->videoengine.dest = (s3->videoengine.dest_base >> 1) + s3->width; - s3->videoengine.src = (s3->videoengine.src_base >> 1) + s3->width; - } else { - s3->videoengine.dest = (s3->videoengine.dest_base >> 2) + s3->width; - s3->videoengine.src = (s3->videoengine.src_base >> 2) + s3->width; - } - s3->videoengine.input = 2; - s3->videoengine.cx = 0.0; - s3->videoengine.dx = 0.0; - } + if (s3->videoengine.input == 1) { + if (s3->videoengine.scale_down) { + if (s3->bpp > 1) { + s3->videoengine.sx = k2 - dda + diff; + s3->videoengine.sx_backup = s3->videoengine.len - s3->videoengine.start; + } else { + s3->videoengine.sx = k2 - dda + diff - 1; + s3->videoengine.sx_backup = s3->videoengine.len - s3->videoengine.start - 1; + } + s3->videoengine.sx_scale_inc = (double) (s3->videoengine.sx_backup >> 1); + s3->videoengine.sx_scale_inc = s3->videoengine.sx_scale_inc / (double) (s3->videoengine.sx >> 1); + } else { + s3->videoengine.sx_scale = (double) (s3->videoengine.k1 - 2); + s3->videoengine.sx_scale_dec = (s3->videoengine.sx_scale / (double) (s3->videoengine.len - s3->videoengine.start - 2)); - while (count) { - if (host) { /*Source data is CPU*/ - src = cpu_dat; - } else { /*Source data is display memory*/ - READ(s3->videoengine.src + lround(s3->videoengine.cx), src); - } - - convert_to_rgb32(idf, is_yuv, src, &r, &g, &b, &r2, &g2, &b2); + if (s3->videoengine.sx_scale_dec >= 0.5) { + s3->videoengine.sx_scale++; + } + } - convert_from_rgb32(idf, odf, is_yuv, &dest, r, g, b, r2, g2, b2); - - WRITE(s3->videoengine.dest + lround(s3->videoengine.dx), dest); - - if (s3->videoengine.scale_down) { /*Data shrink*/ - s3->videoengine.dx += s3->videoengine.sx_scale_inc; - if (!host) - s3->videoengine.cx += s3->videoengine.sx_scale_inc; + if (s3->bpp == 0) { + s3->videoengine.dest = s3->videoengine.dest_base + s3->width; + s3->videoengine.src = s3->videoengine.src_base + s3->width; + } else if (s3->bpp == 1) { + s3->videoengine.dest = (s3->videoengine.dest_base >> 1) + s3->width; + s3->videoengine.src = (s3->videoengine.src_base >> 1) + s3->width; + } else { + s3->videoengine.dest = (s3->videoengine.dest_base >> 2) + s3->width; + s3->videoengine.src = (s3->videoengine.src_base >> 2) + s3->width; + } + s3->videoengine.input = 2; + s3->videoengine.cx = 0.0; + s3->videoengine.dx = 0.0; + } - s3->videoengine.sx--; + while (count) { + if (host) { /*Source data is CPU*/ + src = cpu_dat; + } else { /*Source data is display memory*/ + READ(s3->videoengine.src + lround(s3->videoengine.cx), src); + } - if (host) { - if (s3->bpp == 0) { - cpu_dat >>= 8; - } else { - cpu_dat >>= 16; - } - count--; - } + convert_to_rgb32(idf, is_yuv, src, &r, &g, &b, &r2, &g2, &b2); - if (s3->videoengine.sx < 0) { - if (s3->bpp > 1) { - s3->videoengine.sx = k2 - dda + diff; - s3->videoengine.sx_backup = s3->videoengine.len - s3->videoengine.start; - } else { - s3->videoengine.sx = k2 - dda + diff - 1; - s3->videoengine.sx_backup = s3->videoengine.len - s3->videoengine.start - 1; - } - s3->videoengine.sx_scale_inc = (double)((s3->videoengine.sx_backup >> 1)); - s3->videoengine.sx_scale_inc = s3->videoengine.sx_scale_inc / (double)((s3->videoengine.sx >> 1)); - - s3->videoengine.cx = 0.0; - s3->videoengine.dx = 0.0; + convert_from_rgb32(idf, odf, is_yuv, &dest, r, g, b, r2, g2, b2); - if (s3->bpp == 0) { - s3->videoengine.dest = s3->videoengine.dest_base + s3->width; - s3->videoengine.src = s3->videoengine.src_base + s3->width; - } else if (s3->bpp == 1) { - s3->videoengine.dest = (s3->videoengine.dest_base >> 1) + s3->width; - s3->videoengine.src = (s3->videoengine.src_base >> 1) + s3->width; - } else { - s3->videoengine.dest = (s3->videoengine.dest_base >> 2) + s3->width; - s3->videoengine.src = (s3->videoengine.src_base >> 2) + s3->width; - } - - if (s3->videoengine.input >= 1) { - s3->videoengine.busy = 0; - return; - } - } - } else { /*Data stretch*/ - s3->videoengine.dx++; - - s3->videoengine.sx_scale -= s3->videoengine.sx_scale_dec; - s3->videoengine.sx_scale_backup = (s3->videoengine.sx_scale - s3->videoengine.sx_scale_dec); + WRITE(s3->videoengine.dest + lround(s3->videoengine.dx), dest); - s3->videoengine.sx = lround(s3->videoengine.sx_scale); - s3->videoengine.sx_scale_int = lround(s3->videoengine.sx_scale_backup); - - if (s3->videoengine.sx > s3->videoengine.sx_scale_int) { - if (host) { - if (s3->bpp == 0) - cpu_dat >>= 8; - else - cpu_dat >>= 16; - count--; - } else { - s3->videoengine.cx++; - } - } + if (s3->videoengine.scale_down) { /*Data shrink*/ + s3->videoengine.dx += s3->videoengine.sx_scale_inc; + if (!host) + s3->videoengine.cx += s3->videoengine.sx_scale_inc; - if (s3->videoengine.sx < 0) { - s3->videoengine.sx_scale = (double)(s3->videoengine.k1 - 2); - s3->videoengine.sx_scale_dec = (s3->videoengine.sx_scale / (double)(s3->videoengine.len - s3->videoengine.start - 2)); - - if (s3->videoengine.sx_scale_dec >= 0.5) { - s3->videoengine.sx_scale++; - } - - s3->videoengine.cx = 0.0; - s3->videoengine.dx = 0.0; + s3->videoengine.sx--; - if (s3->bpp == 0) { - s3->videoengine.dest = s3->videoengine.dest_base + s3->width; - s3->videoengine.src = s3->videoengine.src_base + s3->width; - } else if (s3->bpp == 1) { - s3->videoengine.dest = (s3->videoengine.dest_base >> 1) + s3->width; - s3->videoengine.src = (s3->videoengine.src_base >> 1) + s3->width; - } else { - s3->videoengine.dest = (s3->videoengine.dest_base >> 2) + s3->width; - s3->videoengine.src = (s3->videoengine.src_base >> 2) + s3->width; - } - - if (s3->videoengine.input >= 1) { - s3->videoengine.busy = 0; - return; - } - } - } - } + if (host) { + if (s3->bpp == 0) { + cpu_dat >>= 8; + } else { + cpu_dat >>= 16; + } + count--; + } + + if (s3->videoengine.sx < 0) { + if (s3->bpp > 1) { + s3->videoengine.sx = k2 - dda + diff; + s3->videoengine.sx_backup = s3->videoengine.len - s3->videoengine.start; + } else { + s3->videoengine.sx = k2 - dda + diff - 1; + s3->videoengine.sx_backup = s3->videoengine.len - s3->videoengine.start - 1; + } + s3->videoengine.sx_scale_inc = (double) (s3->videoengine.sx_backup >> 1); + s3->videoengine.sx_scale_inc = s3->videoengine.sx_scale_inc / (double) (s3->videoengine.sx >> 1); + + s3->videoengine.cx = 0.0; + s3->videoengine.dx = 0.0; + + if (s3->bpp == 0) { + s3->videoengine.dest = s3->videoengine.dest_base + s3->width; + s3->videoengine.src = s3->videoengine.src_base + s3->width; + } else if (s3->bpp == 1) { + s3->videoengine.dest = (s3->videoengine.dest_base >> 1) + s3->width; + s3->videoengine.src = (s3->videoengine.src_base >> 1) + s3->width; + } else { + s3->videoengine.dest = (s3->videoengine.dest_base >> 2) + s3->width; + s3->videoengine.src = (s3->videoengine.src_base >> 2) + s3->width; + } + + if (s3->videoengine.input >= 1) { + s3->videoengine.busy = 0; + return; + } + } + } else { /*Data stretch*/ + s3->videoengine.dx++; + + s3->videoengine.sx_scale -= s3->videoengine.sx_scale_dec; + s3->videoengine.sx_scale_backup = (s3->videoengine.sx_scale - s3->videoengine.sx_scale_dec); + + s3->videoengine.sx = lround(s3->videoengine.sx_scale); + s3->videoengine.sx_scale_int = lround(s3->videoengine.sx_scale_backup); + + if (s3->videoengine.sx > s3->videoengine.sx_scale_int) { + if (host) { + if (s3->bpp == 0) + cpu_dat >>= 8; + else + cpu_dat >>= 16; + count--; + } else { + s3->videoengine.cx++; + } + } + + if (s3->videoengine.sx < 0) { + s3->videoengine.sx_scale = (double) (s3->videoengine.k1 - 2); + s3->videoengine.sx_scale_dec = (s3->videoengine.sx_scale / (double) (s3->videoengine.len - s3->videoengine.start - 2)); + + if (s3->videoengine.sx_scale_dec >= 0.5) { + s3->videoengine.sx_scale++; + } + + s3->videoengine.cx = 0.0; + s3->videoengine.dx = 0.0; + + if (s3->bpp == 0) { + s3->videoengine.dest = s3->videoengine.dest_base + s3->width; + s3->videoengine.src = s3->videoengine.src_base + s3->width; + } else if (s3->bpp == 1) { + s3->videoengine.dest = (s3->videoengine.dest_base >> 1) + s3->width; + s3->videoengine.src = (s3->videoengine.src_base >> 1) + s3->width; + } else { + s3->videoengine.dest = (s3->videoengine.dest_base >> 2) + s3->width; + s3->videoengine.src = (s3->videoengine.src_base >> 2) + s3->width; + } + + if (s3->videoengine.input >= 1) { + s3->videoengine.busy = 0; + return; + } + } + } + } } void s3_short_stroke_start(int count, int cpu_input, uint32_t mix_dat, uint32_t cpu_dat, s3_t *s3, uint8_t ssv) -{ - if (!cpu_input) { - s3->accel.ssv_len = ssv & 0x0f; - s3->accel.ssv_dir = ssv & 0xe0; - s3->accel.ssv_draw = ssv & 0x10; +{ + if (!cpu_input) { + s3->accel.ssv_len = ssv & 0x0f; + s3->accel.ssv_dir = ssv & 0xe0; + s3->accel.ssv_draw = ssv & 0x10; - if (s3_cpu_src(s3)) { - return; /*Wait for data from CPU*/ - } - } - - s3_accel_start(count, cpu_input, mix_dat, cpu_dat, s3); + if (s3_cpu_src(s3)) { + return; /*Wait for data from CPU*/ + } + } + + s3_accel_start(count, cpu_input, mix_dat, cpu_dat, s3); } void s3_accel_start(int count, int cpu_input, uint32_t mix_dat, uint32_t cpu_dat, s3_t *s3) { - svga_t *svga = &s3->svga; - uint32_t src_dat = 0, dest_dat, old_dest_dat; - uint32_t out, pat_dat = 0; - int frgd_mix, bkgd_mix; - int clip_t = s3->accel.multifunc[1] & 0xfff; - int clip_l = s3->accel.multifunc[2] & 0xfff; - int clip_b = s3->accel.multifunc[3] & 0xfff; - int clip_r = s3->accel.multifunc[4] & 0xfff; - int vram_mask = (s3->accel.multifunc[0xa] & 0xc0) == 0xc0; - uint32_t mix_mask = 0; - uint16_t *vram_w = (uint16_t *)svga->vram; - uint32_t *vram_l = (uint32_t *)svga->vram; - uint32_t compare = s3->accel.color_cmp; - uint8_t rop = s3->accel.ropmix & 0xff; - int compare_mode = (s3->accel.multifunc[0xe] >> 7) & 3; - uint32_t rd_mask = s3->accel.rd_mask; - int cmd = s3->accel.cmd >> 13; - uint32_t srcbase, dstbase; - - if ((s3->chip >= S3_TRIO64 || s3->chip == S3_VISION968 || s3->chip == S3_VISION868) && (s3->accel.cmd & (1 << 11))) { - cmd |= 8; - } - - // SRC-BASE/DST-BASE - if ((s3->accel.multifunc[0xd] >> 4) & 7) { - srcbase = 0x100000 * ((s3->accel.multifunc[0xd] >> 4) & 3); - } else { - srcbase = 0x100000 * ((s3->accel.multifunc[0xe] >> 2) & 3); - } - if ((s3->accel.multifunc[0xd] >> 0) & 7) { - dstbase = 0x100000 * ((s3->accel.multifunc[0xd] >> 0) & 3); - } else { - dstbase = 0x100000 * ((s3->accel.multifunc[0xe] >> 0) & 3); - } - if (s3->bpp == 1) { - srcbase >>= 1; - dstbase >>= 1; - } else if (s3->bpp == 3) { - srcbase >>= 2; - dstbase >>= 2; - } - - if ((s3->accel.cmd & 0x100) && ((s3_cpu_src(s3) || (s3_cpu_dest(s3)))) && (!cpu_input || (s3_enable_fifo(s3) == 0))) { - s3->force_busy = 1; - } - - if (!cpu_input) - 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->accel.dat_count) { - cpu_dat = ((cpu_dat & 0xffff) << 16) | s3->accel.dat_buf; - count = 4; - s3->accel.dat_count = 0; - } else { - s3->accel.dat_buf = cpu_dat & 0xffff; - s3->accel.dat_count = 1; - } - } - if (s3->bpp == 1 || s3->color_16bit) - count >>= 1; - if (s3->bpp == 3) - count >>= 2; - } - - if (s3->bpp == 0 && !s3->color_16bit) - rd_mask &= 0xff; - else if (s3->bpp == 1 || s3->color_16bit) - rd_mask &= 0xffff; - - if (s3->bpp == 0 && !s3->color_16bit) compare &= 0xff; - if (s3->bpp == 1 || s3->color_16bit) compare &= 0xffff; - - switch (s3->accel.cmd & 0x600) - { - case 0x000: mix_mask = 0x80; break; - case 0x200: mix_mask = 0x8000; break; - case 0x400: mix_mask = 0x80000000; break; - case 0x600: mix_mask = (s3->chip == S3_TRIO32 || s3->chip >= S3_TRIO64V || s3->chip == S3_VISION968 || s3->chip == S3_VISION868) ? 0x80 : 0x80000000; break; - } - - /*Bit 4 of the Command register is the draw yes bit, which enables writing to memory/reading from memory when enabled. - When this bit is disabled, no writing to memory/reading from memory is allowed. (This bit is almost meaningless on - the NOP command)*/ - switch (cmd) - { - case 0: /*NOP (Short Stroke Vectors)*/ - if (s3->accel.ssv_state == 0) - break; - - frgd_mix = (s3->accel.frgd_mix >> 5) & 3; - bkgd_mix = (s3->accel.bkgd_mix >> 5) & 3; - - if (s3->accel.cmd & 8) /*Radial*/ - { - while (count-- && s3->accel.ssv_len >= 0) - { - if ((s3->accel.cx & 0xfff) >= clip_l && (s3->accel.cx & 0xfff) <= clip_r && - (s3->accel.cy & 0xfff) >= clip_t && (s3->accel.cy & 0xfff) <= clip_b) - { - switch ((mix_dat & mix_mask) ? frgd_mix : bkgd_mix) - { - case 0: src_dat = s3->accel.bkgd_color; break; - case 1: src_dat = s3->accel.frgd_color; break; - case 2: src_dat = cpu_dat; break; - case 3: src_dat = 0; break; - } - - if ((compare_mode == 2 && src_dat != compare) || - (compare_mode == 3 && src_dat == compare) || - compare_mode < 2) - { - READ((s3->accel.cy * s3->width) + s3->accel.cx, dest_dat); - - MIX - - if (s3->accel.ssv_draw) { - WRITE((s3->accel.cy * s3->width) + s3->accel.cx, dest_dat); - } - } - } - - mix_dat <<= 1; - mix_dat |= 1; - if (s3->bpp == 0) cpu_dat >>= 8; - else cpu_dat >>= 16; - if (!s3->accel.ssv_len) - break; - - switch (s3->accel.ssv_dir & 0xe0) - { - case 0x00: s3->accel.cx++; break; - case 0x20: s3->accel.cx++; s3->accel.cy--; break; - case 0x40: s3->accel.cy--; break; - case 0x60: s3->accel.cx--; s3->accel.cy--; break; - case 0x80: s3->accel.cx--; break; - case 0xa0: s3->accel.cx--; s3->accel.cy++; break; - case 0xc0: s3->accel.cy++; break; - case 0xe0: s3->accel.cx++; s3->accel.cy++; break; - } - - s3->accel.ssv_len--; - } - - s3->accel.cur_x = s3->accel.cx; - s3->accel.cur_y = s3->accel.cy; - } - break; - - case 1: /*Draw line*/ - if (!cpu_input) { - s3->accel.cx = s3->accel.cur_x; - if (s3->accel.cur_x_bit12) s3->accel.cx |= ~0xfff; - s3->accel.cy = s3->accel.cur_y; - if (s3->accel.cur_y_bit12) s3->accel.cy |= ~0xfff; - - s3->accel.sy = s3->accel.maj_axis_pcnt; - - if (s3_cpu_src(s3)) { - return; /*Wait for data from CPU*/ - } - } - frgd_mix = (s3->accel.frgd_mix >> 5) & 3; - bkgd_mix = (s3->accel.bkgd_mix >> 5) & 3; - - if (s3->accel.cmd & 8) /*Radial*/ - { - while (count-- && s3->accel.sy >= 0) - { - if ((s3->accel.cx & 0xfff) >= clip_l && (s3->accel.cx & 0xfff) <= clip_r && - (s3->accel.cy & 0xfff) >= clip_t && (s3->accel.cy & 0xfff) <= clip_b) - { - switch ((mix_dat & mix_mask) ? frgd_mix : bkgd_mix) - { - case 0: src_dat = s3->accel.bkgd_color; break; - case 1: src_dat = s3->accel.frgd_color; break; - case 2: src_dat = cpu_dat; break; - case 3: src_dat = 0; break; - } - - if ((compare_mode == 2 && src_dat != compare) || - (compare_mode == 3 && src_dat == compare) || - compare_mode < 2) - { - READ((s3->accel.cy * s3->width) + s3->accel.cx, dest_dat); - - MIX - - WRITE((s3->accel.cy * s3->width) + s3->accel.cx, dest_dat); - } - } - - mix_dat <<= 1; - mix_dat |= 1; - if (s3->bpp == 0 && !s3->color_16bit) - cpu_dat >>= 8; - else { - cpu_dat >>= 16; - } - - if (!s3->accel.sy) { - break; - } - - switch (s3->accel.cmd & 0xe0) - { - case 0x00: s3->accel.cx++; break; - case 0x20: s3->accel.cx++; s3->accel.cy--; break; - case 0x40: s3->accel.cy--; break; - case 0x60: s3->accel.cx--; s3->accel.cy--; break; - case 0x80: s3->accel.cx--; break; - case 0xa0: s3->accel.cx--; s3->accel.cy++; break; - case 0xc0: s3->accel.cy++; break; - case 0xe0: s3->accel.cx++; s3->accel.cy++; break; - } - s3->accel.sy--; - } - s3->accel.cur_x = s3->accel.cx; - s3->accel.cur_y = s3->accel.cy; - } - else /*Bresenham*/ - { - 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) { - mix_dat >>= 16; - s3->accel.temp_cnt = 16; - } - - if ((s3->accel.cx & 0xfff) >= clip_l && (s3->accel.cx & 0xfff) <= clip_r && - (s3->accel.cy & 0xfff) >= clip_t && (s3->accel.cy & 0xfff) <= clip_b) - { - switch ((mix_dat & mix_mask) ? frgd_mix : bkgd_mix) - { - case 0: src_dat = s3->accel.bkgd_color; break; - case 1: src_dat = s3->accel.frgd_color; break; - case 2: src_dat = cpu_dat; break; - case 3: src_dat = 0; break; - } - - if ((compare_mode == 2 && src_dat != compare) || - (compare_mode == 3 && src_dat == compare) || - compare_mode < 2) - { - READ((s3->accel.cy * s3->width) + s3->accel.cx, dest_dat); - - MIX - - WRITE((s3->accel.cy * s3->width) + s3->accel.cx, dest_dat); - } - } - - if (s3->accel.b2e8_pix && s3_cpu_src(s3)) { - if (s3->accel.temp_cnt > 0) { - s3->accel.temp_cnt--; - mix_dat <<= 1; - mix_dat |= 1; - } - } else { - mix_dat <<= 1; - mix_dat |= 1; - } - if (s3->bpp == 0 && !s3->color_16bit) - cpu_dat >>= 8; - else { - cpu_dat >>= 16; - } - - if (!s3->accel.sy) { - break; - } - - if (s3->accel.err_term >= s3->accel.maj_axis_pcnt) { - s3->accel.err_term += s3->accel.destx_distp; - /*Step minor axis*/ - switch (s3->accel.cmd & 0xe0) - { - case 0x00: s3->accel.cy--; break; - case 0x20: s3->accel.cy--; break; - case 0x40: s3->accel.cx--; break; - case 0x60: s3->accel.cx++; break; - case 0x80: s3->accel.cy++; break; - case 0xa0: s3->accel.cy++; break; - case 0xc0: s3->accel.cx--; break; - case 0xe0: s3->accel.cx++; break; - } - } else { - s3->accel.err_term += s3->accel.desty_axstp; - } - - /*Step major axis*/ - switch (s3->accel.cmd & 0xe0) - { - case 0x00: s3->accel.cx--; break; - case 0x20: s3->accel.cx++; break; - case 0x40: s3->accel.cy--; break; - case 0x60: s3->accel.cy--; break; - case 0x80: s3->accel.cx--; break; - case 0xa0: s3->accel.cx++; break; - case 0xc0: s3->accel.cy++; break; - case 0xe0: s3->accel.cy++; break; - } - s3->accel.sy--; - } - s3->accel.cur_x = s3->accel.cx; - s3->accel.cur_y = s3->accel.cy; - } - break; - - case 2: /*Rectangle fill*/ - if (!cpu_input) /*!cpu_input is trigger to start operation*/ - { - s3->accel.sx = s3->accel.maj_axis_pcnt & 0xfff; - s3->accel.sy = s3->accel.multifunc[0] & 0xfff; - s3->accel.cx = s3->accel.cur_x; - s3->accel.cy = s3->accel.cur_y; - - if (s3->accel.cur_x_bit12) { - if (s3->accel.cx <= 0x7ff) { - s3->accel.cx = s3->accel.cur_x_bitres & 0xfff; - } else { - s3->accel.cx |= ~0xfff; - } - } - if (s3->accel.cur_y_bit12) { - if (s3->accel.cy <= 0x7ff) { - s3->accel.cy = s3->accel.cur_y_bitres & 0xfff; - } else { - s3->accel.cy |= ~0xfff; - } - } - - s3->accel.dest = dstbase + s3->accel.cy * s3->width; - - if (s3_cpu_src(s3)) { - s3->data_available = 0; - return; /*Wait for data from CPU*/ - } else if (s3_cpu_dest(s3)) { - s3->data_available = 1; - return; - } - } - - frgd_mix = (s3->accel.frgd_mix >> 5) & 3; - bkgd_mix = (s3->accel.bkgd_mix >> 5) & 3; - - 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) { - mix_dat >>= 16; - s3->accel.temp_cnt = 16; - } - - if (((s3->accel.cx & 0xfff) >= clip_l && (s3->accel.cx & 0xfff) <= clip_r && - (s3->accel.cy & 0xfff) >= clip_t && (s3->accel.cy & 0xfff) <= clip_b)) - { - if (s3_cpu_dest(s3) && ((s3->accel.multifunc[0xa] & 0xc0) == 0x00)) { - mix_dat = mix_mask; /* Mix data = forced to foreground register. */ - } else if (s3_cpu_dest(s3) && vram_mask) { - /* Mix data = current video memory value. */ - READ(s3->accel.dest + s3->accel.cx, mix_dat); - mix_dat = ((mix_dat & rd_mask) == rd_mask); - mix_dat = mix_dat ? mix_mask : 0; - } - - if (s3_cpu_dest(s3)) { - READ(s3->accel.dest + s3->accel.cx, src_dat); - if (vram_mask) - src_dat = ((src_dat & rd_mask) == rd_mask); - } else switch ((mix_dat & mix_mask) ? frgd_mix : bkgd_mix) - { - case 0: src_dat = s3->accel.bkgd_color; break; - case 1: src_dat = s3->accel.frgd_color; break; - case 2: src_dat = cpu_dat; break; - case 3: src_dat = 0; break; - } - - if (((compare_mode == 2 && src_dat != compare) || - (compare_mode == 3 && src_dat == compare) || - compare_mode < 2)) - { - READ(s3->accel.dest + s3->accel.cx, dest_dat); - - MIX - - if (s3->accel.cmd & 0x10) { - WRITE(s3->accel.dest + s3->accel.cx, dest_dat); - } - } - } - - if (s3->accel.b2e8_pix && s3_cpu_src(s3)) { - if (s3->accel.temp_cnt > 0) { - s3->accel.temp_cnt--; - mix_dat <<= 1; - mix_dat |= 1; - } - } else { - mix_dat <<= 1; - mix_dat |= 1; - } - - if (s3->bpp == 0 && !s3->color_16bit) - cpu_dat >>= 8; - else { - cpu_dat >>= 16; - } - - if (s3->accel.cmd & 0x20) - s3->accel.cx++; - else - s3->accel.cx--; - - s3->accel.sx--; - if (s3->accel.sx < 0) - { - if (s3->accel.cmd & 0x20) - s3->accel.cx -= (s3->accel.maj_axis_pcnt & 0xfff) + 1; - else - s3->accel.cx += (s3->accel.maj_axis_pcnt & 0xfff) + 1; - s3->accel.sx = s3->accel.maj_axis_pcnt & 0xfff; - - if (s3->accel.cmd & 0x80) - s3->accel.cy++; - else - s3->accel.cy--; - - s3->accel.dest = dstbase + s3->accel.cy * s3->width; - s3->accel.sy--; - - if (cpu_input) { - if (s3->accel.b2e8_pix) { - s3->accel.cur_x = s3->accel.cx; - s3->accel.cur_y = s3->accel.cy; - } - return; - } - if (s3->accel.sy < 0) { - s3->accel.cur_x = s3->accel.cx; - s3->accel.cur_y = s3->accel.cy; - return; - } - } - } - break; - - - case 3: /*Polygon Fill Solid (Vision868/968 and Trio64 only)*/ - { - int end_y1, end_y2; - - if (s3->chip != S3_TRIO64 && s3->chip != S3_VISION968 && s3->chip != S3_VISION868) - break; - - polygon_setup(s3); - - if ((s3->accel.cmd & 0x100) && !cpu_input) return; /*Wait for data from CPU*/ - - end_y1 = s3->accel.desty_axstp; - end_y2 = s3->accel.desty_axstp2; - - frgd_mix = (s3->accel.frgd_mix >> 5) & 3; - - while ((s3->accel.poly_cy < end_y1) && (s3->accel.poly_cy2 < end_y2)) - { - int y = s3->accel.poly_cy; - int x_count = ABS((s3->accel.poly_cx2 >> 20) - s3->accel.poly_x) + 1; - - s3->accel.dest = dstbase + y * s3->width; - - while (x_count-- && count--) - { - if ((s3->accel.poly_x & 0xfff) >= clip_l && (s3->accel.poly_x & 0xfff) <= clip_r && - (s3->accel.poly_cy & 0xfff) >= clip_t && (s3->accel.poly_cy & 0xfff) <= clip_b) - { - switch (frgd_mix) - { - case 0: src_dat = s3->accel.bkgd_color; break; - case 1: src_dat = s3->accel.frgd_color; break; - case 2: src_dat = cpu_dat; break; - case 3: src_dat = 0; /*Not supported?*/ break; - } - - if (((compare_mode == 2 && src_dat != compare) || - (compare_mode == 3 && src_dat == compare) || - compare_mode < 2)) - { - READ(s3->accel.dest + s3->accel.poly_x, dest_dat); - - MIX - - if (s3->accel.cmd & 0x10) { - WRITE(s3->accel.dest + s3->accel.poly_x, dest_dat); - } - } - } - if (s3->bpp == 0) cpu_dat >>= 8; - else cpu_dat >>= 16; - - if (s3->accel.poly_x < (s3->accel.poly_cx2 >> 20)) - s3->accel.poly_x++; - else - s3->accel.poly_x--; - } - - s3->accel.poly_cx += s3->accel.poly_dx1; - s3->accel.poly_cx2 += s3->accel.poly_dx2; - s3->accel.poly_x = s3->accel.poly_cx >> 20; - - s3->accel.poly_cy++; - s3->accel.poly_cy2++; - - if (!count) - break; - } - - s3->accel.cur_x = s3->accel.poly_cx & 0xfff; - s3->accel.cur_y = s3->accel.poly_cy & 0xfff; - s3->accel.cur_x2 = s3->accel.poly_cx2 & 0xfff; - s3->accel.cur_y2 = s3->accel.poly_cy & 0xfff; - } - break; - - - case 6: /*BitBlt*/ - if (!cpu_input) /*!cpu_input is trigger to start operation*/ - { - s3->accel.sx = s3->accel.maj_axis_pcnt & 0xfff; - s3->accel.sy = s3->accel.multifunc[0] & 0xfff; - - s3->accel.dx = s3->accel.destx_distp & 0xfff; - if (s3->accel.destx_distp & 0x1000) s3->accel.dx |= ~0xfff; - s3->accel.dy = s3->accel.desty_axstp & 0xfff; - if (s3->accel.desty_axstp & 0x1000) s3->accel.dy |= ~0xfff; - - s3->accel.cx = s3->accel.cur_x; - s3->accel.cy = s3->accel.cur_y; - - if (s3->accel.destx_distp >= 0xfffff000) { /* avoid overflow */ - s3->accel.dx = s3->accel.destx_distp & 0xfff; - if (s3->accel.cur_x_bit12) { - if (s3->accel.cx <= 0x7ff) { - s3->accel.cx = s3->accel.cur_x_bitres & 0xfff; - } else { - s3->accel.cx |= ~0xfff; - } - } - if (s3->accel.cur_y_bitres > 0xfff) - s3->accel.cy = s3->accel.cur_y_bitres; - } else { - if (s3->accel.cur_x_bit12) { - if (s3->accel.cx <= 0x7ff) { /* overlap x */ - s3->accel.cx = s3->accel.cur_x_bitres & 0xfff; - } else { /* x end is negative */ - s3->accel.cx |= ~0xfff; - } - } - if (s3->accel.cur_y_bit12) { - if (s3->accel.cy <= 0x7ff) { /* overlap y */ - s3->accel.cy = s3->accel.cur_y_bitres & 0xfff; - } else { /* y end is negative */ - s3->accel.cy |= ~0xfff; - } - } - } - - s3->accel.src = srcbase + s3->accel.cy * s3->width; - s3->accel.dest = dstbase + s3->accel.dy * s3->width; - } - - if ((s3->accel.cmd & 0x100) && !cpu_input) { - return; /*Wait for data from CPU*/ - } - - frgd_mix = (s3->accel.frgd_mix >> 5) & 3; - bkgd_mix = (s3->accel.bkgd_mix >> 5) & 3; - - if (!cpu_input && frgd_mix == 3 && !vram_mask && !compare_mode && - (s3->accel.cmd & 0xa0) == 0xa0 && (s3->accel.frgd_mix & 0xf) == 7 && - (s3->accel.bkgd_mix & 0xf) == 7) - { - while (1) - { - if (((s3->accel.dx & 0xfff) >= clip_l && (s3->accel.dx & 0xfff) <= clip_r && - (s3->accel.dy & 0xfff) >= clip_t && (s3->accel.dy & 0xfff) <= clip_b)) - { - READ(s3->accel.src + s3->accel.cx, src_dat); - READ(s3->accel.dest + s3->accel.dx, dest_dat); - - dest_dat = (src_dat & s3->accel.wrt_mask) | (dest_dat & ~s3->accel.wrt_mask); - - if (s3->accel.cmd & 0x10) { - WRITE(s3->accel.dest + s3->accel.dx, dest_dat); - } - } - - s3->accel.cx++; - s3->accel.dx++; - s3->accel.sx--; - if (s3->accel.sx < 0) - { - s3->accel.cx -= (s3->accel.maj_axis_pcnt & 0xfff) + 1; - s3->accel.dx -= (s3->accel.maj_axis_pcnt & 0xfff) + 1; - s3->accel.sx = s3->accel.maj_axis_pcnt & 0xfff; - - s3->accel.cy++; - s3->accel.dy++; - - s3->accel.src = srcbase + s3->accel.cy * s3->width; - s3->accel.dest = dstbase + s3->accel.dy * s3->width; - - s3->accel.sy--; - - if (s3->accel.sy < 0) { - return; - } - } - } - } - else - { - while (count-- && s3->accel.sy >= 0) - { - /*This is almost required by OS/2's software cursor or we will risk writing/reading garbage around it.*/ - if ((s3->accel.dx) >= clip_l && (s3->accel.dx) <= clip_r && - ((s3->accel.dy) >= clip_t && (s3->accel.dy) <= clip_b)) - { - if (vram_mask && (s3->accel.cmd & 0x10)) - { - READ(s3->accel.src + s3->accel.cx, mix_dat); - mix_dat = ((mix_dat & rd_mask) == rd_mask); - mix_dat = mix_dat ? mix_mask : 0; - } - switch ((mix_dat & mix_mask) ? frgd_mix : bkgd_mix) - { - case 0: src_dat = s3->accel.bkgd_color; break; - case 1: src_dat = s3->accel.frgd_color; break; - case 2: src_dat = cpu_dat; break; - case 3: READ(s3->accel.src + s3->accel.cx, src_dat); - if (vram_mask && (s3->accel.cmd & 0x10)) - src_dat = ((src_dat & rd_mask) == rd_mask); - break; - } - - if ((((compare_mode == 2 && src_dat != compare) || - (compare_mode == 3 && src_dat == compare) || - compare_mode < 2))) - { - READ(s3->accel.dest + s3->accel.dx, dest_dat); - - MIX - - if ((!(s3->accel.cmd & 0x10) && vram_mask) || (s3->accel.cmd & 0x10)) { - WRITE(s3->accel.dest + s3->accel.dx, dest_dat); - } - } - } - - mix_dat <<= 1; - mix_dat |= 1; - - if (s3->bpp == 0 && !s3->color_16bit) - cpu_dat >>= 8; - else { - cpu_dat >>= 16; - } - - if (s3->accel.cmd & 0x20) - { - s3->accel.cx++; - s3->accel.dx++; - } - else - { - s3->accel.cx--; - s3->accel.dx--; - } - s3->accel.sx--; - if (s3->accel.sx < 0) - { - if (s3->accel.cmd & 0x20) - { - s3->accel.cx -= (s3->accel.maj_axis_pcnt & 0xfff) + 1; - s3->accel.dx -= (s3->accel.maj_axis_pcnt & 0xfff) + 1; - } - else - { - s3->accel.cx += (s3->accel.maj_axis_pcnt & 0xfff) + 1; - s3->accel.dx += (s3->accel.maj_axis_pcnt & 0xfff) + 1; - } - - s3->accel.sx = s3->accel.maj_axis_pcnt & 0xfff; - - if (s3->accel.cmd & 0x80) - { - s3->accel.cy++; - s3->accel.dy++; - } - else - { - s3->accel.cy--; - s3->accel.dy--; - } - - s3->accel.src = srcbase + s3->accel.cy * s3->width; - s3->accel.dest = dstbase + s3->accel.dy * s3->width; - - s3->accel.sy--; - - if (cpu_input) { - return; - } - - if (s3->accel.sy < 0) { - return; - } - } - } - } - break; - - case 7: /*Pattern fill - BitBlt but with source limited to 8x8*/ - if (!cpu_input) /*!cpu_input is trigger to start operation*/ - { - s3->accel.sx = s3->accel.maj_axis_pcnt & 0xfff; - s3->accel.sy = s3->accel.multifunc[0] & 0xfff; - - s3->accel.dx = s3->accel.destx_distp & 0xfff; - if (s3->accel.destx_distp & 0x1000) s3->accel.dx |= ~0xfff; - s3->accel.dy = s3->accel.desty_axstp & 0xfff; - if (s3->accel.desty_axstp & 0x1000) s3->accel.dy |= ~0xfff; - - s3->accel.cx = s3->accel.cur_x & 0xfff; - if (s3->accel.cur_x_bit12) s3->accel.cx |= ~0xfff; - s3->accel.cy = s3->accel.cur_y & 0xfff; - if (s3->accel.cur_y_bit12) s3->accel.cy |= ~0xfff; - - /*Align source with destination*/ - s3->accel.pattern = (s3->accel.cy * s3->width) + s3->accel.cx; - s3->accel.dest = dstbase + s3->accel.dy * s3->width; - - s3->accel.cx = s3->accel.dx & 7; - s3->accel.cy = s3->accel.dy & 7; - - s3->accel.src = srcbase + s3->accel.pattern + (s3->accel.cy * s3->width); - } - - if ((s3->accel.cmd & 0x100) && !cpu_input) { - return; /*Wait for data from CPU*/ - } - - frgd_mix = (s3->accel.frgd_mix >> 5) & 3; - bkgd_mix = (s3->accel.bkgd_mix >> 5) & 3; - - while (count-- && s3->accel.sy >= 0) - { - if ((s3->accel.dx & 0xfff) >= clip_l && (s3->accel.dx & 0xfff) <= clip_r && - (s3->accel.dy & 0xfff) >= clip_t && (s3->accel.dy & 0xfff) <= clip_b) - { - if (vram_mask) - { - READ(s3->accel.src + s3->accel.cx, mix_dat); - mix_dat = ((mix_dat & rd_mask) == rd_mask); - mix_dat = mix_dat ? mix_mask : 0; - } - switch ((mix_dat & mix_mask) ? frgd_mix : bkgd_mix) - { - case 0: src_dat = s3->accel.bkgd_color; break; - case 1: src_dat = s3->accel.frgd_color; break; - case 2: src_dat = cpu_dat; break; - case 3: READ(s3->accel.src + s3->accel.cx, src_dat); - if (vram_mask) - src_dat = ((src_dat & rd_mask) == rd_mask); - break; - } - - if (((compare_mode == 2 && src_dat != compare) || - (compare_mode == 3 && src_dat == compare) || - compare_mode < 2)) - { - READ(s3->accel.dest + s3->accel.dx, dest_dat); - - MIX - - if (s3->accel.cmd & 0x10) { - WRITE(s3->accel.dest + s3->accel.dx, dest_dat); - } - } - } - - mix_dat <<= 1; - mix_dat |= 1; - if (s3->bpp == 0) cpu_dat >>= 8; - else cpu_dat >>= 16; - - if (s3->accel.cmd & 0x20) - { - s3->accel.cx = ((s3->accel.cx + 1) & 7) | (s3->accel.cx & ~7); - s3->accel.dx++; - } - else - { - s3->accel.cx = ((s3->accel.cx - 1) & 7) | (s3->accel.cx & ~7); - s3->accel.dx--; - } - s3->accel.sx--; - if (s3->accel.sx < 0) - { - if (s3->accel.cmd & 0x20) - { - s3->accel.cx = ((s3->accel.cx - ((s3->accel.maj_axis_pcnt & 0xfff) + 1)) & 7) | (s3->accel.cx & ~7); - s3->accel.dx -= (s3->accel.maj_axis_pcnt & 0xfff) + 1; - } - else - { - s3->accel.cx = ((s3->accel.cx + ((s3->accel.maj_axis_pcnt & 0xfff) + 1)) & 7) | (s3->accel.cx & ~7); - s3->accel.dx += (s3->accel.maj_axis_pcnt & 0xfff) + 1; - } - s3->accel.sx = s3->accel.maj_axis_pcnt & 0xfff; - - if (s3->accel.cmd & 0x80) - { - s3->accel.cy = ((s3->accel.cy + 1) & 7) | (s3->accel.cy & ~7); - s3->accel.dy++; - } - else - { - s3->accel.cy = ((s3->accel.cy - 1) & 7) | (s3->accel.cy & ~7); - s3->accel.dy--; - } - - s3->accel.src = srcbase + s3->accel.pattern + (s3->accel.cy * s3->width); - s3->accel.dest = dstbase + s3->accel.dy * s3->width; - - s3->accel.sy--; - - if (cpu_input) { - return; - } - if (s3->accel.sy < 0) { - return; - } - } - } - break; - - case 9: /*Polyline/2-Point Line (Vision868/968 and Trio64 only)*/ - { - int error; - - if (s3->chip != S3_TRIO64 && s3->chip != S3_VISION968 && s3->chip != S3_VISION868) - break; - - if (!cpu_input) { - s3->accel.dx = ABS(s3->accel.destx_distp - s3->accel.cur_x); - if (s3->accel.destx_distp & 0x1000) - s3->accel.dx |= ~0xfff; - s3->accel.dy = ABS(s3->accel.desty_axstp - s3->accel.cur_y); - if (s3->accel.desty_axstp & 0x1000) - s3->accel.dy |= ~0xfff; - - s3->accel.cx = s3->accel.cur_x; - if (s3->accel.cur_x_bit12) - s3->accel.cx |= ~0xfff; - s3->accel.cy = s3->accel.cur_y; - if (s3->accel.cur_y_bit12) - s3->accel.cy |= ~0xfff; - } - - if ((s3->accel.cmd & 0x100) && !cpu_input) return; /*Wait for data from CPU*/ - - if (s3->accel.dx > s3->accel.dy) { - error = s3->accel.dx / 2; - while (s3->accel.cx != s3->accel.destx_distp && count--) { - if ((s3->accel.cx & 0xfff) >= clip_l && (s3->accel.cx & 0xfff) <= clip_r && - (s3->accel.cy & 0xfff) >= clip_t && (s3->accel.cy & 0xfff) <= clip_b) - { - src_dat = s3->accel.frgd_color; - - if (((compare_mode == 2 && src_dat != compare) || - (compare_mode == 3 && src_dat == compare) || - compare_mode < 2) && (s3->accel.cmd & 0x10)) - { - READ((s3->accel.cy * s3->width) + s3->accel.cx, dest_dat); - - MIX - - if (s3->accel.cmd & 0x10) { - WRITE((s3->accel.cy * s3->width) + s3->accel.cx, dest_dat); - } - } - } - - error -= s3->accel.dy; - if (error < 0) { - error += s3->accel.dx; - if (s3->accel.desty_axstp > s3->accel.cur_y) - s3->accel.cy++; - else - s3->accel.cy--; - } - - if (s3->accel.destx_distp > s3->accel.cur_x) - s3->accel.cx++; - else - s3->accel.cx--; - } - } else { - error = s3->accel.dy / 2; - while (s3->accel.cy != s3->accel.desty_axstp && count--) { - if ((s3->accel.cx & 0xfff) >= clip_l && (s3->accel.cx & 0xfff) <= clip_r && - (s3->accel.cy & 0xfff) >= clip_t && (s3->accel.cy & 0xfff) <= clip_b) - { - src_dat = s3->accel.frgd_color; - - if (((compare_mode == 2 && src_dat != compare) || - (compare_mode == 3 && src_dat == compare) || - compare_mode < 2)) - { - READ((s3->accel.cy * s3->width) + s3->accel.cx, dest_dat); - - MIX - - if (s3->accel.cmd & 0x10) { - WRITE((s3->accel.cy * s3->width) + s3->accel.cx, dest_dat); - } - } - } - - error -= s3->accel.dx; - if (error < 0) { - error += s3->accel.dy; - if (s3->accel.destx_distp > s3->accel.cur_x) - s3->accel.cx++; - else - s3->accel.cx--; - } - if (s3->accel.desty_axstp > s3->accel.cur_y) - s3->accel.cy++; - else - s3->accel.cy--; - - } - } - s3->accel.cur_x = s3->accel.cx; - s3->accel.cur_y = s3->accel.cy; - } - break; - - - case 11: /*Polygon Fill Pattern (Vision868/968 and Trio64 only)*/ - { - int end_y1, end_y2; - - if (s3->chip != S3_TRIO64 && s3->chip != S3_VISION968 && s3->chip != S3_VISION868) - break; - - polygon_setup(s3); - - if ((s3->accel.cmd & 0x100) && !cpu_input) return; /*Wait for data from CPU*/ - - end_y1 = s3->accel.desty_axstp; - end_y2 = s3->accel.desty_axstp2; - - frgd_mix = (s3->accel.frgd_mix >> 5) & 3; - bkgd_mix = (s3->accel.bkgd_mix >> 5) & 3; - - while ((s3->accel.poly_cy < end_y1) && (s3->accel.poly_cy2 < end_y2)) - { - int y = s3->accel.poly_cy; - int x_count = ABS((s3->accel.poly_cx2 >> 20) - s3->accel.poly_x) + 1; - - s3->accel.src = srcbase + s3->accel.pattern + ((y & 7) * s3->width); - s3->accel.dest = dstbase + y * s3->width; - - while (x_count-- && count--) - { - int pat_x = s3->accel.poly_x & 7; - - if ((s3->accel.poly_x & 0xfff) >= clip_l && (s3->accel.poly_x & 0xfff) <= clip_r && - (s3->accel.poly_cy & 0xfff) >= clip_t && (s3->accel.poly_cy & 0xfff) <= clip_b) - { - if (vram_mask) { - READ(s3->accel.src + pat_x, mix_dat); - mix_dat = ((mix_dat & rd_mask) == rd_mask); - mix_dat = mix_dat ? mix_mask : 0; - } - switch ((mix_dat & mix_mask) ? frgd_mix : bkgd_mix) - { - case 0: src_dat = s3->accel.bkgd_color; break; - case 1: src_dat = s3->accel.frgd_color; break; - case 2: src_dat = cpu_dat; break; - case 3: READ(s3->accel.src + pat_x, src_dat); - if (vram_mask) - src_dat = ((src_dat & rd_mask) == rd_mask); - break; - } - - if (((compare_mode == 2 && src_dat != compare) || - (compare_mode == 3 && src_dat == compare) || - compare_mode < 2)) - { - READ(s3->accel.dest + s3->accel.poly_x, dest_dat); - - MIX - - if (s3->accel.cmd & 0x10) { - WRITE(s3->accel.dest + s3->accel.poly_x, dest_dat); - } - } - } - if (s3->bpp == 0) cpu_dat >>= 8; - else cpu_dat >>= 16; - - mix_dat <<= 1; - mix_dat |= 1; - - if (s3->accel.poly_x < (s3->accel.poly_cx2 >> 20)) - s3->accel.poly_x++; - else - s3->accel.poly_x--; - } - - s3->accel.poly_cx += s3->accel.poly_dx1; - s3->accel.poly_cx2 += s3->accel.poly_dx2; - s3->accel.poly_x = s3->accel.poly_cx >> 20; - - s3->accel.poly_cy++; - s3->accel.poly_cy2++; - - if (!count) - break; - } - - s3->accel.cur_x = s3->accel.poly_cx & 0xfff; - s3->accel.cur_y = s3->accel.poly_cy & 0xfff; - s3->accel.cur_x2 = s3->accel.poly_cx2 & 0xfff; - s3->accel.cur_y2 = s3->accel.poly_cy & 0xfff; - } - break; - - case 14: /*ROPBlt (Vision868/968 only)*/ - if (s3->chip != S3_VISION968 && s3->chip != S3_VISION868) - break; - - if (!cpu_input) /*!cpu_input is trigger to start operation*/ - { - s3->accel.sx = s3->accel.maj_axis_pcnt & 0xfff; - s3->accel.sy = s3->accel.multifunc[0] & 0xfff; - - s3->accel.dx = s3->accel.destx_distp & 0xfff; - if (s3->accel.destx_distp & 0x1000) s3->accel.dx |= ~0xfff; - s3->accel.dy = s3->accel.desty_axstp & 0xfff; - if (s3->accel.desty_axstp & 0x1000) s3->accel.dy |= ~0xfff; - - s3->accel.cx = s3->accel.cur_x & 0xfff; - if (s3->accel.cur_x_bit12) s3->accel.cx |= ~0xfff; - s3->accel.cy = s3->accel.cur_y & 0xfff; - if (s3->accel.cur_y_bit12) s3->accel.cy |= ~0xfff; - - s3->accel.px = s3->accel.pat_x & 0xfff; - if (s3->accel.pat_x & 0x1000) s3->accel.px |= ~0xfff; - s3->accel.py = s3->accel.pat_y & 0xfff; - if (s3->accel.pat_y & 0x1000) s3->accel.py |= ~0xfff; - - s3->accel.dest = dstbase + (s3->accel.dy * s3->width); - s3->accel.src = srcbase + (s3->accel.cy * s3->width); - s3->accel.pattern = (s3->accel.py * s3->width); - } - - if ((s3->accel.cmd & 0x100) && !cpu_input) return; /*Wait for data from CPU*/ - - frgd_mix = (s3->accel.frgd_mix >> 5) & 3; - bkgd_mix = (s3->accel.bkgd_mix >> 5) & 3; - - while (count-- && s3->accel.sy >= 0) - { - if ((s3->accel.dx & 0xfff) >= clip_l && (s3->accel.dx & 0xfff) <= clip_r && - (s3->accel.dy & 0xfff) >= clip_t && (s3->accel.dy & 0xfff) <= clip_b) - { - switch ((mix_dat & mix_mask) ? frgd_mix : bkgd_mix) - { - case 0: src_dat = s3->accel.bkgd_color; break; - case 1: src_dat = s3->accel.frgd_color; break; - case 2: src_dat = cpu_dat; break; - case 3: READ(s3->accel.src + s3->accel.cx, src_dat); break; - } - - if (s3->accel.ropmix & 0x100) { - switch ((mix_dat & mix_mask) ? frgd_mix : bkgd_mix) - { - case 0: pat_dat = s3->accel.pat_bg_color; break; - case 1: pat_dat = s3->accel.pat_fg_color; break; - case 2: pat_dat = cpu_dat; break; - case 3: READ(s3->accel.pattern + s3->accel.px, pat_dat); break; - } - } else { - switch ((mix_dat & mix_mask) ? frgd_mix : bkgd_mix) - { - case 0: pat_dat = s3->accel.bkgd_color; break; - case 1: pat_dat = s3->accel.frgd_color; break; - case 2: pat_dat = cpu_dat; break; - case 3: READ(s3->accel.pattern + s3->accel.px, pat_dat); break; - } - } - - if (((compare_mode == 2 && src_dat != compare) || - (compare_mode == 3 && src_dat == compare) || - compare_mode < 2)) - { - READ(s3->accel.dest + s3->accel.dx, dest_dat); - - ROPMIX - - if (s3->accel.cmd & 0x10) { - WRITE(s3->accel.dest + s3->accel.dx, out); - } - } - } - - mix_dat <<= 1; - mix_dat |= 1; - if (s3->bpp == 0) cpu_dat >>= 8; - else cpu_dat >>= 16; - - if (s3->accel.cmd & 0x20) - { - s3->accel.cx++; - s3->accel.dx++; - s3->accel.px++; - } - else - { - s3->accel.cx--; - s3->accel.dx--; - s3->accel.px--; - } - s3->accel.sx--; - if (s3->accel.sx < 0) - { - if (s3->accel.cmd & 0x20) - { - s3->accel.cx -= (s3->accel.maj_axis_pcnt & 0xfff) + 1; - s3->accel.dx -= (s3->accel.maj_axis_pcnt & 0xfff) + 1; - s3->accel.px -= (s3->accel.maj_axis_pcnt & 0xfff) + 1; - } - else - { - s3->accel.cx += (s3->accel.maj_axis_pcnt & 0xfff) + 1; - s3->accel.dx += (s3->accel.maj_axis_pcnt & 0xfff) + 1; - s3->accel.px += (s3->accel.maj_axis_pcnt & 0xfff) + 1; - } - s3->accel.sx = s3->accel.maj_axis_pcnt & 0xfff; - - if (s3->accel.cmd & 0x80) - { - s3->accel.cy++; - s3->accel.dy++; - s3->accel.py++; - } - else - { - s3->accel.cy--; - s3->accel.dy--; - s3->accel.py--; - } - - s3->accel.src = srcbase + (s3->accel.cy * s3->width); - s3->accel.dest = dstbase + (s3->accel.dy * s3->width); - s3->accel.pattern = (s3->accel.py * s3->width); - - s3->accel.sy--; - - if (cpu_input/* && (s3->accel.multifunc[0xa] & 0xc0) == 0x80*/) return; - if (s3->accel.sy < 0) { - return; - } - } - } - break; - } + svga_t *svga = &s3->svga; + uint32_t src_dat = 0; + uint32_t dest_dat; + uint32_t old_dest_dat; + uint32_t out; + uint32_t pat_dat = 0; + int frgd_mix; + int bkgd_mix; + int clip_t = s3->accel.multifunc[1] & 0xfff; + int clip_l = s3->accel.multifunc[2] & 0xfff; + int clip_b = s3->accel.multifunc[3] & 0xfff; + int clip_r = s3->accel.multifunc[4] & 0xfff; + int vram_mask = (s3->accel.multifunc[0xa] & 0xc0) == 0xc0; + uint32_t mix_mask = 0; + uint16_t *vram_w = (uint16_t *) svga->vram; + uint32_t *vram_l = (uint32_t *) svga->vram; + uint32_t compare = s3->accel.color_cmp; + uint8_t rop = s3->accel.ropmix & 0xff; + int compare_mode = (s3->accel.multifunc[0xe] >> 7) & 3; + uint32_t rd_mask = s3->accel.rd_mask; + int cmd = s3->accel.cmd >> 13; + uint32_t srcbase; + uint32_t dstbase; + + if ((s3->chip >= S3_TRIO64 || s3->chip == S3_VISION968 || s3->chip == S3_VISION868) && (s3->accel.cmd & (1 << 11))) + cmd |= 8; + + // SRC-BASE/DST-BASE + if ((s3->accel.multifunc[0xd] >> 4) & 7) + srcbase = 0x100000 * ((s3->accel.multifunc[0xd] >> 4) & 3); + else + srcbase = 0x100000 * ((s3->accel.multifunc[0xe] >> 2) & 3); + + if ((s3->accel.multifunc[0xd] >> 0) & 7) + dstbase = 0x100000 * ((s3->accel.multifunc[0xd] >> 0) & 3); + else + dstbase = 0x100000 * ((s3->accel.multifunc[0xe] >> 0) & 3); + + if (s3->bpp == 1) { + srcbase >>= 1; + dstbase >>= 1; + } else if (s3->bpp == 3) { + srcbase >>= 2; + dstbase >>= 2; + } + + if ((s3->accel.cmd & 0x100) && (s3_cpu_src(s3) || (s3_cpu_dest(s3))) && (!cpu_input || (s3_enable_fifo(s3) == 0))) + s3->force_busy = 1; + + if (!cpu_input) + 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->accel.dat_count) { + cpu_dat = ((cpu_dat & 0xffff) << 16) | s3->accel.dat_buf; + count = 4; + s3->accel.dat_count = 0; + } else { + s3->accel.dat_buf = cpu_dat & 0xffff; + s3->accel.dat_count = 1; + } + } + if ((s3->bpp == 1) || s3->color_16bit) + count >>= 1; + else if (s3->bpp == 3) + count >>= 2; + } + + if ((s3->bpp == 0) && !s3->color_16bit) + rd_mask &= 0xff; + else if ((s3->bpp == 1) || s3->color_16bit) + rd_mask &= 0xffff; + + if ((s3->bpp == 0) && !s3->color_16bit) + compare &= 0xff; + else if ((s3->bpp == 1) || s3->color_16bit) + compare &= 0xffff; + + switch (s3->accel.cmd & 0x600) { + case 0x000: + mix_mask = 0x80; + break; + case 0x200: + mix_mask = 0x8000; + break; + case 0x400: + mix_mask = 0x80000000; + break; + case 0x600: + mix_mask = (s3->chip == S3_TRIO32 || s3->chip >= S3_TRIO64V || s3->chip == S3_VISION968 || s3->chip == S3_VISION868) ? 0x80 : 0x80000000; + break; + + default: + break; + } + + /*Bit 4 of the Command register is the draw yes bit, which enables writing to memory/reading from memory when enabled. + When this bit is disabled, no writing to memory/reading from memory is allowed. (This bit is almost meaningless on + the NOP command)*/ + switch (cmd) { + case 0: /*NOP (Short Stroke Vectors)*/ + if (s3->accel.ssv_state == 0) + break; + + frgd_mix = (s3->accel.frgd_mix >> 5) & 3; + bkgd_mix = (s3->accel.bkgd_mix >> 5) & 3; + + if (s3->accel.cmd & 8) /*Radial*/ + { + while (count-- && s3->accel.ssv_len >= 0) { + if ((s3->accel.cx & 0xfff) >= clip_l && (s3->accel.cx & 0xfff) <= clip_r && (s3->accel.cy & 0xfff) >= clip_t && (s3->accel.cy & 0xfff) <= clip_b) { + switch ((mix_dat & mix_mask) ? frgd_mix : bkgd_mix) { + case 0: + src_dat = s3->accel.bkgd_color; + break; + case 1: + src_dat = s3->accel.frgd_color; + break; + case 2: + src_dat = cpu_dat; + break; + case 3: + src_dat = 0; + break; + + default: + break; + } + + if ((compare_mode == 2 && src_dat != compare) || (compare_mode == 3 && src_dat == compare) || compare_mode < 2) { + READ((s3->accel.cy * s3->width) + s3->accel.cx, dest_dat); + + MIX + + if (s3->accel.ssv_draw) { + WRITE((s3->accel.cy * s3->width) + s3->accel.cx, dest_dat); + } + } + } + + mix_dat <<= 1; + mix_dat |= 1; + if (s3->bpp == 0) + cpu_dat >>= 8; + else + cpu_dat >>= 16; + + if (!s3->accel.ssv_len) + break; + + switch (s3->accel.ssv_dir & 0xe0) { + case 0x00: + s3->accel.cx++; + break; + case 0x20: + s3->accel.cx++; + s3->accel.cy--; + break; + case 0x40: + s3->accel.cy--; + break; + case 0x60: + s3->accel.cx--; + s3->accel.cy--; + break; + case 0x80: + s3->accel.cx--; + break; + case 0xa0: + s3->accel.cx--; + s3->accel.cy++; + break; + case 0xc0: + s3->accel.cy++; + break; + case 0xe0: + s3->accel.cx++; + s3->accel.cy++; + break; + + default: + break; + } + + s3->accel.ssv_len--; + s3->accel.cx &= 0xfff; + s3->accel.cy &= 0xfff; + } + + s3->accel.cur_x = s3->accel.cx; + s3->accel.cur_y = s3->accel.cy; + } + break; + + case 1: /*Draw line*/ + if (!cpu_input) { + s3->accel.cx = s3->accel.cur_x & 0xfff; + s3->accel.cy = s3->accel.cur_y & 0xfff; + s3->accel.sy = s3->accel.maj_axis_pcnt; + + if (s3_cpu_src(s3)) + return; /*Wait for data from CPU*/ + } + frgd_mix = (s3->accel.frgd_mix >> 5) & 3; + bkgd_mix = (s3->accel.bkgd_mix >> 5) & 3; + + if (s3->accel.cmd & 8) /*Radial*/ + { + while (count-- && s3->accel.sy >= 0) { + if ((s3->accel.cx & 0xfff) >= clip_l && (s3->accel.cx & 0xfff) <= clip_r && (s3->accel.cy & 0xfff) >= clip_t && (s3->accel.cy & 0xfff) <= clip_b) { + switch ((mix_dat & mix_mask) ? frgd_mix : bkgd_mix) { + case 0: + src_dat = s3->accel.bkgd_color; + break; + case 1: + src_dat = s3->accel.frgd_color; + break; + case 2: + src_dat = cpu_dat; + break; + case 3: + src_dat = 0; + break; + + default: + break; + } + + if ((compare_mode == 2 && src_dat != compare) || (compare_mode == 3 && src_dat == compare) || compare_mode < 2) { + READ((s3->accel.cy * s3->width) + s3->accel.cx, dest_dat); + + MIX + + WRITE((s3->accel.cy * s3->width) + s3->accel.cx, dest_dat); + } + } + + mix_dat <<= 1; + mix_dat |= 1; + if ((s3->bpp == 0) && !s3->color_16bit) + cpu_dat >>= 8; + else + cpu_dat >>= 16; + + if (!s3->accel.sy) + break; + + switch (s3->accel.cmd & 0xe0) { + case 0x00: + s3->accel.cx++; + break; + case 0x20: + s3->accel.cx++; + s3->accel.cy--; + break; + case 0x40: + s3->accel.cy--; + break; + case 0x60: + s3->accel.cx--; + s3->accel.cy--; + break; + case 0x80: + s3->accel.cx--; + break; + case 0xa0: + s3->accel.cx--; + s3->accel.cy++; + break; + case 0xc0: + s3->accel.cy++; + break; + case 0xe0: + s3->accel.cx++; + s3->accel.cy++; + break; + + default: + break; + } + s3->accel.sy--; + s3->accel.cx &= 0xfff; + s3->accel.cy &= 0xfff; + } + s3->accel.cur_x = s3->accel.cx; + 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*/ + 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) { + mix_dat >>= 16; + s3->accel.temp_cnt = 16; + } + + if ((s3->accel.cx & 0xfff) >= clip_l && (s3->accel.cx & 0xfff) <= clip_r && (s3->accel.cy & 0xfff) >= clip_t && (s3->accel.cy & 0xfff) <= clip_b) { + switch ((mix_dat & mix_mask) ? frgd_mix : bkgd_mix) { + case 0: + src_dat = s3->accel.bkgd_color; + break; + case 1: + src_dat = s3->accel.frgd_color; + break; + case 2: + src_dat = cpu_dat; + break; + case 3: + src_dat = 0; + break; + + default: + break; + } + + if ((compare_mode == 2 && src_dat != compare) || (compare_mode == 3 && src_dat == compare) || compare_mode < 2) { + READ((s3->accel.cy * s3->width) + s3->accel.cx, dest_dat); + + MIX + + WRITE((s3->accel.cy * s3->width) + s3->accel.cx, dest_dat); + } + } + + if (s3->accel.b2e8_pix && s3_cpu_src(s3)) { + if (s3->accel.temp_cnt > 0) { + s3->accel.temp_cnt--; + mix_dat <<= 1; + mix_dat |= 1; + } + } else { + mix_dat <<= 1; + mix_dat |= 1; + } + if (s3->bpp == 0 && !s3->color_16bit) + cpu_dat >>= 8; + else { + cpu_dat >>= 16; + } + + if (!s3->accel.sy) + break; + + if (s3->accel.err_term >= s3->accel.maj_axis_pcnt) { + s3->accel.err_term += s3->accel.destx_distp; + /*Step minor axis*/ + switch (s3->accel.cmd & 0xe0) { + case 0x00: + s3->accel.cy--; + break; + case 0x20: + s3->accel.cy--; + break; + case 0x40: + s3->accel.cx--; + break; + case 0x60: + s3->accel.cx++; + break; + case 0x80: + s3->accel.cy++; + break; + case 0xa0: + s3->accel.cy++; + break; + case 0xc0: + s3->accel.cx--; + break; + case 0xe0: + s3->accel.cx++; + break; + + default: + break; + } + } else { + s3->accel.err_term += s3->accel.desty_axstp; + } + + /*Step major axis*/ + switch (s3->accel.cmd & 0xe0) { + case 0x00: + s3->accel.cx--; + break; + case 0x20: + s3->accel.cx++; + break; + case 0x40: + s3->accel.cy--; + break; + case 0x60: + s3->accel.cy--; + break; + case 0x80: + s3->accel.cx--; + break; + case 0xa0: + s3->accel.cx++; + break; + case 0xc0: + s3->accel.cy++; + break; + case 0xe0: + s3->accel.cy++; + break; + + default: + break; + } + s3->accel.sy--; + s3->accel.cx &= 0xfff; + s3->accel.cy &= 0xfff; + } + s3->accel.cur_x = s3->accel.cx; + s3->accel.cur_y = s3->accel.cy; + } + break; + + case 2: /*Rectangle fill*/ + if (!cpu_input) /*!cpu_input is trigger to start operation*/ + { + s3->accel.sx = s3->accel.maj_axis_pcnt & 0xfff; + s3->accel.sy = s3->accel.multifunc[0] & 0xfff; + s3->accel.cx = s3->accel.cur_x & 0xfff; + s3->accel.cy = s3->accel.cur_y & 0xfff; + + s3->accel.dest = dstbase + s3->accel.cy * s3->width; + + if (s3_cpu_src(s3)) { + s3->data_available = 0; + return; /*Wait for data from CPU*/ + } else if (s3_cpu_dest(s3)) { + s3->data_available = 1; + return; + } + } + + frgd_mix = (s3->accel.frgd_mix >> 5) & 3; + bkgd_mix = (s3->accel.bkgd_mix >> 5) & 3; + + 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) { + mix_dat >>= 16; + s3->accel.temp_cnt = 16; + } + + if ((s3->accel.cx & 0xfff) >= clip_l && (s3->accel.cx & 0xfff) <= clip_r && (s3->accel.cy & 0xfff) >= clip_t && (s3->accel.cy & 0xfff) <= clip_b) { + if (s3_cpu_dest(s3) && ((s3->accel.multifunc[0xa] & 0xc0) == 0x00)) { + mix_dat = mix_mask; /* Mix data = forced to foreground register. */ + } else if (s3_cpu_dest(s3) && vram_mask) { + /* Mix data = current video memory value. */ + READ(s3->accel.dest + s3->accel.cx, mix_dat); + mix_dat = ((mix_dat & rd_mask) == rd_mask); + mix_dat = mix_dat ? mix_mask : 0; + } + + if (s3_cpu_dest(s3)) { + READ(s3->accel.dest + s3->accel.cx, src_dat); + if (vram_mask) + src_dat = ((src_dat & rd_mask) == rd_mask); + } else + switch ((mix_dat & mix_mask) ? frgd_mix : bkgd_mix) { + case 0: + src_dat = s3->accel.bkgd_color; + break; + case 1: + src_dat = s3->accel.frgd_color; + break; + case 2: + src_dat = cpu_dat; + break; + case 3: + src_dat = 0; + break; + + default: + break; + } + + if ((compare_mode == 2 && src_dat != compare) || (compare_mode == 3 && src_dat == compare) || compare_mode < 2) { + READ(s3->accel.dest + s3->accel.cx, dest_dat); + + MIX + + if (s3->accel.cmd & 0x10) { + WRITE(s3->accel.dest + s3->accel.cx, dest_dat); + } + } + } + + if (s3->accel.b2e8_pix && s3_cpu_src(s3)) { + if (s3->accel.temp_cnt > 0) { + s3->accel.temp_cnt--; + mix_dat <<= 1; + mix_dat |= 1; + } + } else { + mix_dat <<= 1; + mix_dat |= 1; + } + + if ((s3->bpp == 0) && !s3->color_16bit) + cpu_dat >>= 8; + else { + cpu_dat >>= 16; + } + + if (s3->accel.cmd & 0x20) + s3->accel.cx++; + else + s3->accel.cx--; + + s3->accel.cx &= 0xfff; + s3->accel.sx--; + if (s3->accel.sx < 0) { + if (s3->accel.cmd & 0x20) + s3->accel.cx -= (s3->accel.maj_axis_pcnt & 0xfff) + 1; + else + s3->accel.cx += (s3->accel.maj_axis_pcnt & 0xfff) + 1; + s3->accel.sx = s3->accel.maj_axis_pcnt & 0xfff; + + if (s3->accel.cmd & 0x80) + s3->accel.cy++; + else + s3->accel.cy--; + + s3->accel.cy &= 0xfff; + s3->accel.dest = dstbase + s3->accel.cy * s3->width; + s3->accel.sy--; + + if (cpu_input) { + if (s3->accel.b2e8_pix) { + s3->accel.cur_x = s3->accel.cx; + s3->accel.cur_y = s3->accel.cy; + } + return; + } + if (s3->accel.sy < 0) { + s3->accel.cur_x = s3->accel.cx; + s3->accel.cur_y = s3->accel.cy; + return; + } + } + } + break; + + case 3: /*Polygon Fill Solid (Vision868/968 and Trio64 only)*/ + { + int end_y1; + int end_y2; + + if (s3->chip != S3_TRIO64 && s3->chip != S3_VISION968 && s3->chip != S3_VISION868) + break; + + polygon_setup(s3); + + if ((s3->accel.cmd & 0x100) && !cpu_input) + return; /*Wait for data from CPU*/ + + end_y1 = s3->accel.desty_axstp; + end_y2 = s3->accel.desty_axstp2; + + frgd_mix = (s3->accel.frgd_mix >> 5) & 3; + + while ((s3->accel.poly_cy < end_y1) && (s3->accel.poly_cy2 < end_y2)) { + int y = s3->accel.poly_cy; + int x_count = ABS((s3->accel.poly_cx2 >> 20) - s3->accel.poly_x) + 1; + + s3->accel.dest = dstbase + y * s3->width; + + while (x_count-- && count--) { + if ((s3->accel.poly_x & 0xfff) >= clip_l && (s3->accel.poly_x & 0xfff) <= clip_r && (s3->accel.poly_cy & 0xfff) >= clip_t && (s3->accel.poly_cy & 0xfff) <= clip_b) { + switch (frgd_mix) { + case 0: + src_dat = s3->accel.bkgd_color; + break; + case 1: + src_dat = s3->accel.frgd_color; + break; + case 2: + src_dat = cpu_dat; + break; + case 3: + src_dat = 0; /*Not supported?*/ + break; + + default: + break; + } + + if ((compare_mode == 2 && src_dat != compare) || (compare_mode == 3 && src_dat == compare) || compare_mode < 2) { + READ(s3->accel.dest + s3->accel.poly_x, dest_dat); + + MIX + + if (s3->accel.cmd & 0x10) { + WRITE(s3->accel.dest + s3->accel.poly_x, dest_dat); + } + } + } + if (s3->bpp == 0) + cpu_dat >>= 8; + else + cpu_dat >>= 16; + + if (s3->accel.poly_x < (s3->accel.poly_cx2 >> 20)) + s3->accel.poly_x++; + else + s3->accel.poly_x--; + } + + s3->accel.poly_cx += s3->accel.poly_dx1; + s3->accel.poly_cx2 += s3->accel.poly_dx2; + s3->accel.poly_x = s3->accel.poly_cx >> 20; + + s3->accel.poly_cy++; + s3->accel.poly_cy2++; + + if (!count) + break; + } + + s3->accel.cur_x = s3->accel.poly_cx & 0xfff; + s3->accel.cur_y = s3->accel.poly_cy & 0xfff; + s3->accel.cur_x2 = s3->accel.poly_cx2 & 0xfff; + s3->accel.cur_y2 = s3->accel.poly_cy & 0xfff; + } + break; + + case 6: /*BitBlt*/ + if (!cpu_input) /*!cpu_input is trigger to start operation*/ + { + s3->accel.sx = s3->accel.maj_axis_pcnt & 0xfff; + s3->accel.sy = s3->accel.multifunc[0] & 0xfff; + + s3->accel.dx = s3->accel.destx_distp & 0x7ff; + if (s3->accel.destx_distp & 0x800) + s3->accel.dx |= ~0x7ff; + s3->accel.dy = s3->accel.desty_axstp & 0x7ff; + if (s3->accel.desty_axstp & 0x800) + s3->accel.dy |= ~0x7ff; + + s3->accel.cx = s3->accel.cur_x & 0xfff; + s3->accel.cy = s3->accel.cur_y & 0xfff; + + s3->accel.src = srcbase + s3->accel.cy * s3->width; + s3->accel.dest = dstbase + s3->accel.dy * s3->width; + } + + if ((s3->accel.cmd & 0x100) && !cpu_input) { + return; /*Wait for data from CPU*/ + } + + frgd_mix = (s3->accel.frgd_mix >> 5) & 3; + bkgd_mix = (s3->accel.bkgd_mix >> 5) & 3; + + if (!cpu_input && frgd_mix == 3 && !vram_mask && !compare_mode && (s3->accel.cmd & 0xa0) == 0xa0 && (s3->accel.frgd_mix & 0xf) == 7 && (s3->accel.bkgd_mix & 0xf) == 7) { + while (1) { + if ((s3->accel.dx & 0xfff) >= clip_l && (s3->accel.dx & 0xfff) <= clip_r && (s3->accel.dy & 0xfff) >= clip_t && (s3->accel.dy & 0xfff) <= clip_b) { + READ(s3->accel.src + s3->accel.cx, src_dat); + READ(s3->accel.dest + s3->accel.dx, dest_dat); + + dest_dat = (src_dat & s3->accel.wrt_mask) | (dest_dat & ~s3->accel.wrt_mask); + + if (s3->accel.cmd & 0x10) { + WRITE(s3->accel.dest + s3->accel.dx, dest_dat); + } + } + + s3->accel.cx++; + s3->accel.dx++; + s3->accel.sx--; + if (s3->accel.sx < 0) { + s3->accel.cx -= (s3->accel.maj_axis_pcnt & 0xfff) + 1; + s3->accel.dx -= (s3->accel.maj_axis_pcnt & 0xfff) + 1; + s3->accel.sx = s3->accel.maj_axis_pcnt & 0xfff; + + s3->accel.cy++; + s3->accel.dy++; + + s3->accel.src = srcbase + s3->accel.cy * s3->width; + s3->accel.dest = dstbase + s3->accel.dy * s3->width; + + s3->accel.sy--; + + if (s3->accel.sy < 0) { + return; + } + } + } + } else { + while (count-- && s3->accel.sy >= 0) { + if ((s3->accel.dx & 0xfff) >= clip_l && (s3->accel.dx & 0xfff) <= clip_r && ((s3->accel.dy & 0xfff) >= clip_t && (s3->accel.dy & 0xfff) <= clip_b)) { + if (vram_mask && (s3->accel.cmd & 0x10)) { + READ(s3->accel.src + s3->accel.cx, mix_dat); + mix_dat = ((mix_dat & rd_mask) == rd_mask); + mix_dat = mix_dat ? mix_mask : 0; + } + switch ((mix_dat & mix_mask) ? frgd_mix : bkgd_mix) { + case 0: + src_dat = s3->accel.bkgd_color; + break; + case 1: + src_dat = s3->accel.frgd_color; + break; + case 2: + src_dat = cpu_dat; + break; + case 3: + READ(s3->accel.src + s3->accel.cx, src_dat); + if (vram_mask && (s3->accel.cmd & 0x10)) + src_dat = ((src_dat & rd_mask) == rd_mask); + break; + + default: + break; + } + + if ((compare_mode == 2 && src_dat != compare) || (compare_mode == 3 && src_dat == compare) || compare_mode < 2) { + + READ(s3->accel.dest + s3->accel.dx, dest_dat); + + MIX + + if ((!(s3->accel.cmd & 0x10) && vram_mask) || (s3->accel.cmd & 0x10)) { + WRITE(s3->accel.dest + s3->accel.dx, dest_dat); + } + } + } + + mix_dat <<= 1; + mix_dat |= 1; + + if (s3->bpp == 0 && !s3->color_16bit) + cpu_dat >>= 8; + else { + cpu_dat >>= 16; + } + + if (s3->accel.cmd & 0x20) { + s3->accel.cx++; + s3->accel.dx++; + } else { + s3->accel.cx--; + s3->accel.dx--; + } + s3->accel.sx--; + if (s3->accel.sx < 0) { + if (s3->accel.cmd & 0x20) { + s3->accel.cx -= ((s3->accel.maj_axis_pcnt & 0xfff) + 1); + s3->accel.dx -= ((s3->accel.maj_axis_pcnt & 0xfff) + 1); + } else { + s3->accel.cx += ((s3->accel.maj_axis_pcnt & 0xfff) + 1); + s3->accel.dx += ((s3->accel.maj_axis_pcnt & 0xfff) + 1); + } + s3->accel.sx = s3->accel.maj_axis_pcnt & 0xfff; + + if (s3->accel.cmd & 0x80) { + s3->accel.cy++; + s3->accel.dy++; + } else { + s3->accel.cy--; + s3->accel.dy--; + } + s3->accel.src = srcbase + s3->accel.cy * s3->width; + s3->accel.dest = dstbase + s3->accel.dy * s3->width; + + s3->accel.sy--; + + if (cpu_input) { + return; + } + + if (s3->accel.sy < 0) { + return; + } + } + } + } + break; + + case 7: /*Pattern fill - BitBlt but with source limited to 8x8*/ + if (!cpu_input) /*!cpu_input is trigger to start operation*/ + { + s3->accel.sx = s3->accel.maj_axis_pcnt & 0xfff; + s3->accel.sy = s3->accel.multifunc[0] & 0xfff; + + s3->accel.dx = s3->accel.destx_distp & 0xfff; + if (s3->accel.destx_distp & 0x1000) + s3->accel.dx |= ~0xfff; + s3->accel.dy = s3->accel.desty_axstp & 0xfff; + if (s3->accel.desty_axstp & 0x1000) + s3->accel.dy |= ~0xfff; + + s3->accel.cx = s3->accel.cur_x & 0xfff; + s3->accel.cy = s3->accel.cur_y & 0xfff; + + /*Align source with destination*/ + s3->accel.pattern = (s3->accel.cy * s3->width) + s3->accel.cx; + s3->accel.dest = dstbase + s3->accel.dy * s3->width; + + s3->accel.cx = s3->accel.dx & 7; + s3->accel.cy = s3->accel.dy & 7; + + s3->accel.src = srcbase + s3->accel.pattern + (s3->accel.cy * s3->width); + } + + if ((s3->accel.cmd & 0x100) && !cpu_input) { + return; /*Wait for data from CPU*/ + } + + frgd_mix = (s3->accel.frgd_mix >> 5) & 3; + bkgd_mix = (s3->accel.bkgd_mix >> 5) & 3; + + while (count-- && s3->accel.sy >= 0) { + if ((s3->accel.dx & 0xfff) >= clip_l && (s3->accel.dx & 0xfff) <= clip_r && (s3->accel.dy & 0xfff) >= clip_t && (s3->accel.dy & 0xfff) <= clip_b) { + if (vram_mask) { + READ(s3->accel.src + s3->accel.cx, mix_dat); + mix_dat = ((mix_dat & rd_mask) == rd_mask); + mix_dat = mix_dat ? mix_mask : 0; + } + switch ((mix_dat & mix_mask) ? frgd_mix : bkgd_mix) { + case 0: + src_dat = s3->accel.bkgd_color; + break; + case 1: + src_dat = s3->accel.frgd_color; + break; + case 2: + src_dat = cpu_dat; + break; + case 3: + READ(s3->accel.src + s3->accel.cx, src_dat); + if (vram_mask) + src_dat = ((src_dat & rd_mask) == rd_mask); + break; + + default: + break; + } + + if ((compare_mode == 2 && src_dat != compare) || (compare_mode == 3 && src_dat == compare) || compare_mode < 2) { + READ(s3->accel.dest + s3->accel.dx, dest_dat); + + MIX + + if (s3->accel.cmd & 0x10) { + WRITE(s3->accel.dest + s3->accel.dx, dest_dat); + } + } + } + + mix_dat <<= 1; + mix_dat |= 1; + if (s3->bpp == 0) + cpu_dat >>= 8; + else + cpu_dat >>= 16; + + if (s3->accel.cmd & 0x20) { + s3->accel.cx = ((s3->accel.cx + 1) & 7) | (s3->accel.cx & ~7); + s3->accel.dx++; + } else { + s3->accel.cx = ((s3->accel.cx - 1) & 7) | (s3->accel.cx & ~7); + s3->accel.dx--; + } + s3->accel.sx--; + if (s3->accel.sx < 0) { + if (s3->accel.cmd & 0x20) { + s3->accel.cx = ((s3->accel.cx - (((s3->accel.maj_axis_pcnt & 0xfff) + 1))) & 7) | (s3->accel.cx & ~7); + s3->accel.dx -= ((s3->accel.maj_axis_pcnt & 0xfff) + 1); + } else { + s3->accel.cx = ((s3->accel.cx + (((s3->accel.maj_axis_pcnt & 0xfff) + 1))) & 7) | (s3->accel.cx & ~7); + s3->accel.dx += ((s3->accel.maj_axis_pcnt & 0xfff) + 1); + } + s3->accel.sx = s3->accel.maj_axis_pcnt & 0xfff; + + if (s3->accel.cmd & 0x80) { + s3->accel.cy = ((s3->accel.cy + 1) & 7) | (s3->accel.cy & ~7); + s3->accel.dy++; + } else { + s3->accel.cy = ((s3->accel.cy - 1) & 7) | (s3->accel.cy & ~7); + s3->accel.dy--; + } + + s3->accel.src = srcbase + s3->accel.pattern + (s3->accel.cy * s3->width); + s3->accel.dest = dstbase + s3->accel.dy * s3->width; + + s3->accel.sy--; + + if (cpu_input) { + return; + } + if (s3->accel.sy < 0) { + return; + } + } + } + break; + + case 9: /*Polyline/2-Point Line (Vision868/968 and Trio64 only)*/ + { + int error; + + if (s3->chip != S3_TRIO64 && s3->chip != S3_VISION968 && s3->chip != S3_VISION868) + break; + + if (!cpu_input) { + s3->accel.dx = ABS(s3->accel.destx_distp - s3->accel.cur_x); + if (s3->accel.destx_distp & 0x1000) + s3->accel.dx |= ~0xfff; + s3->accel.dy = ABS(s3->accel.desty_axstp - s3->accel.cur_y); + if (s3->accel.desty_axstp & 0x1000) + s3->accel.dy |= ~0xfff; + + s3->accel.cx = s3->accel.cur_x & 0xfff; + s3->accel.cy = s3->accel.cur_y & 0xfff; + } + + if ((s3->accel.cmd & 0x100) && !cpu_input) + return; /*Wait for data from CPU*/ + + if (s3->accel.dx > s3->accel.dy) { + error = s3->accel.dx / 2; + while (s3->accel.cx != s3->accel.destx_distp && count--) { + if ((s3->accel.cx & 0xfff) >= clip_l && (s3->accel.cx & 0xfff) <= clip_r && (s3->accel.cy & 0xfff) >= clip_t && (s3->accel.cy & 0xfff) <= clip_b) { + src_dat = s3->accel.frgd_color; + + if (((compare_mode == 2 && src_dat != compare) || (compare_mode == 3 && src_dat == compare) || compare_mode < 2) && (s3->accel.cmd & 0x10)) { + READ((s3->accel.cy * s3->width) + s3->accel.cx, dest_dat); + + MIX + + if (s3->accel.cmd & 0x10) { + WRITE((s3->accel.cy * s3->width) + s3->accel.cx, dest_dat); + } + } + } + + error -= s3->accel.dy; + if (error < 0) { + error += s3->accel.dx; + if (s3->accel.desty_axstp > s3->accel.cur_y) + s3->accel.cy++; + else + s3->accel.cy--; + + s3->accel.cy &= 0xfff; + } + if (s3->accel.destx_distp > s3->accel.cur_x) + s3->accel.cx++; + else + s3->accel.cx--; + + s3->accel.cx &= 0xfff; + } + } else { + error = s3->accel.dy / 2; + while (s3->accel.cy != s3->accel.desty_axstp && count--) { + if ((s3->accel.cx & 0xfff) >= clip_l && (s3->accel.cx & 0xfff) <= clip_r && (s3->accel.cy & 0xfff) >= clip_t && (s3->accel.cy & 0xfff) <= clip_b) { + src_dat = s3->accel.frgd_color; + + if ((compare_mode == 2 && src_dat != compare) || (compare_mode == 3 && src_dat == compare) || compare_mode < 2) { + READ((s3->accel.cy * s3->width) + s3->accel.cx, dest_dat); + + MIX + + if (s3->accel.cmd & 0x10) { + WRITE((s3->accel.cy * s3->width) + s3->accel.cx, dest_dat); + } + } + } + + error -= s3->accel.dx; + if (error < 0) { + error += s3->accel.dy; + if (s3->accel.destx_distp > s3->accel.cur_x) + s3->accel.cx++; + else + s3->accel.cx--; + + s3->accel.cx &= 0xfff; + } + if (s3->accel.desty_axstp > s3->accel.cur_y) + s3->accel.cy++; + else + s3->accel.cy--; + + s3->accel.cy &= 0xfff; + } + } + s3->accel.cur_x = s3->accel.cx; + s3->accel.cur_y = s3->accel.cy; + } + break; + + case 11: /*Polygon Fill Pattern (Vision868/968 and Trio64 only)*/ + { + int end_y1; + int end_y2; + + if (s3->chip != S3_TRIO64 && s3->chip != S3_VISION968 && s3->chip != S3_VISION868) + break; + + polygon_setup(s3); + + if ((s3->accel.cmd & 0x100) && !cpu_input) + return; /*Wait for data from CPU*/ + + end_y1 = s3->accel.desty_axstp; + end_y2 = s3->accel.desty_axstp2; + + frgd_mix = (s3->accel.frgd_mix >> 5) & 3; + bkgd_mix = (s3->accel.bkgd_mix >> 5) & 3; + + while ((s3->accel.poly_cy < end_y1) && (s3->accel.poly_cy2 < end_y2)) { + int y = s3->accel.poly_cy; + int x_count = ABS((s3->accel.poly_cx2 >> 20) - s3->accel.poly_x) + 1; + + s3->accel.src = srcbase + s3->accel.pattern + ((y & 7) * s3->width); + s3->accel.dest = dstbase + y * s3->width; + + while (x_count-- && count--) { + int pat_x = s3->accel.poly_x & 7; + + if ((s3->accel.poly_x & 0xfff) >= clip_l && (s3->accel.poly_x & 0xfff) <= clip_r && (s3->accel.poly_cy & 0xfff) >= clip_t && (s3->accel.poly_cy & 0xfff) <= clip_b) { + if (vram_mask) { + READ(s3->accel.src + pat_x, mix_dat); + mix_dat = ((mix_dat & rd_mask) == rd_mask); + mix_dat = mix_dat ? mix_mask : 0; + } + switch ((mix_dat & mix_mask) ? frgd_mix : bkgd_mix) { + case 0: + src_dat = s3->accel.bkgd_color; + break; + case 1: + src_dat = s3->accel.frgd_color; + break; + case 2: + src_dat = cpu_dat; + break; + case 3: + READ(s3->accel.src + pat_x, src_dat); + if (vram_mask) + src_dat = ((src_dat & rd_mask) == rd_mask); + break; + + default: + break; + } + + if ((compare_mode == 2 && src_dat != compare) || (compare_mode == 3 && src_dat == compare) || compare_mode < 2) { + READ(s3->accel.dest + s3->accel.poly_x, dest_dat); + + MIX + + if (s3->accel.cmd & 0x10) { + WRITE(s3->accel.dest + s3->accel.poly_x, dest_dat); + } + } + } + if (s3->bpp == 0) + cpu_dat >>= 8; + else + cpu_dat >>= 16; + + mix_dat <<= 1; + mix_dat |= 1; + + if (s3->accel.poly_x < (s3->accel.poly_cx2 >> 20)) + s3->accel.poly_x++; + else + s3->accel.poly_x--; + } + + s3->accel.poly_cx += s3->accel.poly_dx1; + s3->accel.poly_cx2 += s3->accel.poly_dx2; + s3->accel.poly_x = s3->accel.poly_cx >> 20; + + s3->accel.poly_cy++; + s3->accel.poly_cy2++; + + if (!count) + break; + } + + s3->accel.cur_x = s3->accel.poly_cx & 0xfff; + s3->accel.cur_y = s3->accel.poly_cy & 0xfff; + s3->accel.cur_x2 = s3->accel.poly_cx2 & 0xfff; + s3->accel.cur_y2 = s3->accel.poly_cy & 0xfff; + } + break; + + case 14: /*ROPBlt (Vision868/968 only)*/ + if (s3->chip != S3_VISION968 && s3->chip != S3_VISION868) + break; + + if (!cpu_input) /*!cpu_input is trigger to start operation*/ + { + s3->accel.sx = s3->accel.maj_axis_pcnt & 0xfff; + s3->accel.sy = s3->accel.multifunc[0] & 0xfff; + + s3->accel.dx = s3->accel.destx_distp & 0xfff; + if (s3->accel.destx_distp & 0x1000) + s3->accel.dx |= ~0xfff; + s3->accel.dy = s3->accel.desty_axstp & 0xfff; + if (s3->accel.desty_axstp & 0x1000) + s3->accel.dy |= ~0xfff; + + s3->accel.cx = s3->accel.cur_x & 0xfff; + s3->accel.cy = s3->accel.cur_y & 0xfff; + + s3->accel.px = s3->accel.pat_x & 0xfff; + s3->accel.py = s3->accel.pat_y & 0xfff; + + s3->accel.dest = dstbase + (s3->accel.dy * s3->width); + s3->accel.src = srcbase + (s3->accel.cy * s3->width); + s3->accel.pattern = (s3->accel.py * s3->width); + } + + if ((s3->accel.cmd & 0x100) && !cpu_input) + return; /*Wait for data from CPU*/ + + frgd_mix = (s3->accel.frgd_mix >> 5) & 3; + bkgd_mix = (s3->accel.bkgd_mix >> 5) & 3; + + while (count-- && s3->accel.sy >= 0) { + if ((s3->accel.dx & 0xfff) >= clip_l && (s3->accel.dx & 0xfff) <= clip_r && (s3->accel.dy & 0xfff) >= clip_t && (s3->accel.dy & 0xfff) <= clip_b) { + switch ((mix_dat & mix_mask) ? frgd_mix : bkgd_mix) { + case 0: + src_dat = s3->accel.bkgd_color; + break; + case 1: + src_dat = s3->accel.frgd_color; + break; + case 2: + src_dat = cpu_dat; + break; + case 3: + READ(s3->accel.src + s3->accel.cx, src_dat); + break; + + default: + break; + } + + if (s3->accel.ropmix & 0x100) { + switch ((mix_dat & mix_mask) ? frgd_mix : bkgd_mix) { + case 0: + pat_dat = s3->accel.pat_bg_color; + break; + case 1: + pat_dat = s3->accel.pat_fg_color; + break; + case 2: + pat_dat = cpu_dat; + break; + case 3: + READ(s3->accel.pattern + s3->accel.px, pat_dat); + break; + + default: + break; + } + } else { + switch ((mix_dat & mix_mask) ? frgd_mix : bkgd_mix) { + case 0: + pat_dat = s3->accel.bkgd_color; + break; + case 1: + pat_dat = s3->accel.frgd_color; + break; + case 2: + pat_dat = cpu_dat; + break; + case 3: + READ(s3->accel.pattern + s3->accel.px, pat_dat); + break; + + default: + break; + } + } + + if ((compare_mode == 2 && src_dat != compare) || (compare_mode == 3 && src_dat == compare) || compare_mode < 2) { + READ(s3->accel.dest + s3->accel.dx, dest_dat); + + ROPMIX + + if (s3->accel.cmd & 0x10) { + WRITE(s3->accel.dest + s3->accel.dx, out); + } + } + } + + mix_dat <<= 1; + mix_dat |= 1; + if (s3->bpp == 0) + cpu_dat >>= 8; + else + cpu_dat >>= 16; + + if (s3->accel.cmd & 0x20) { + s3->accel.cx++; + s3->accel.dx++; + s3->accel.px++; + } else { + s3->accel.cx--; + s3->accel.dx--; + s3->accel.px--; + } + s3->accel.sx--; + if (s3->accel.sx < 0) { + if (s3->accel.cmd & 0x20) { + s3->accel.cx -= ((s3->accel.maj_axis_pcnt & 0xfff) + 1); + s3->accel.dx -= ((s3->accel.maj_axis_pcnt & 0xfff) + 1); + s3->accel.px -= ((s3->accel.maj_axis_pcnt & 0xfff) + 1); + } else { + s3->accel.cx += ((s3->accel.maj_axis_pcnt & 0xfff) + 1); + s3->accel.dx += ((s3->accel.maj_axis_pcnt & 0xfff) + 1); + s3->accel.px += ((s3->accel.maj_axis_pcnt & 0xfff) + 1); + } + s3->accel.sx = s3->accel.maj_axis_pcnt & 0xfff; + + if (s3->accel.cmd & 0x80) { + s3->accel.cy++; + s3->accel.dy++; + s3->accel.py++; + } else { + s3->accel.cy--; + s3->accel.dy--; + s3->accel.py--; + } + s3->accel.src = srcbase + (s3->accel.cy * s3->width); + s3->accel.dest = dstbase + (s3->accel.dy * s3->width); + s3->accel.pattern = (s3->accel.py * s3->width); + + s3->accel.sy--; + + if (cpu_input /* && (s3->accel.multifunc[0xa] & 0xc0) == 0x80*/) + return; + if (s3->accel.sy < 0) { + return; + } + } + } + break; + + default: + break; + } } static uint8_t -s3_pci_read(int func, int addr, void *p) +s3_pci_read(UNUSED(int func), int addr, void *priv) { - s3_t *s3 = (s3_t *)p; - svga_t *svga = &s3->svga; + const s3_t *s3 = (s3_t *) priv; + const svga_t *svga = &s3->svga; - switch (addr) - { - case 0x00: return 0x33; /*'S3'*/ - case 0x01: return 0x53; - - case 0x02: return s3->id_ext_pci; - case 0x03: return (s3->chip == S3_TRIO64V2) ? 0x89 : 0x88; - - case PCI_REG_COMMAND: - if (s3->chip == S3_VISION968 || s3->chip == S3_VISION868) - return s3->pci_regs[PCI_REG_COMMAND] | 0x80; /*Respond to IO and memory accesses*/ - else - return s3->pci_regs[PCI_REG_COMMAND]; /*Respond to IO and memory accesses*/ - break; + switch (addr) { + case 0x00: + return 0x33; /*'S3'*/ + case 0x01: + return 0x53; - case 0x07: return (s3->chip == S3_TRIO64V2) ? (s3->pci_regs[0x07] & 0x36) : (1 << 1); /*Medium DEVSEL timing*/ - - case 0x08: return (s3->chip == S3_TRIO64V) ? 0x40 : 0; /*Revision ID*/ - case 0x09: return 0; /*Programming interface*/ - - case 0x0a: - if (s3->chip >= S3_TRIO32 || s3->chip == S3_VISION968 || s3->chip == S3_VISION868) - return 0x00; /*Supports VGA interface*/ - else - return 0x01; - break; - case 0x0b: - if (s3->chip >= S3_TRIO32 || s3->chip == S3_VISION968 || s3->chip == S3_VISION868) - return 0x03; - else - return 0x00; - break; - - case 0x0d: return (s3->chip == S3_TRIO64V2) ? (s3->pci_regs[0x0d] & 0xf8) : 0x00; break; - - case 0x10: return 0x00; /*Linear frame buffer address*/ - case 0x11: return 0x00; - case 0x12: - if (svga->crtc[0x53] & 0x08) - return 0x00; - else - return (svga->crtc[0x5a] & 0x80); - break; - - case 0x13: - if (svga->crtc[0x53] & 0x08) { - return (s3->chip >= S3_TRIO64V) ? (svga->crtc[0x59] & 0xfc) : (svga->crtc[0x59] & 0xfe); - } else { - return svga->crtc[0x59]; - } - break; + case 0x02: + return s3->id_ext_pci; + case 0x03: + return (s3->chip == S3_TRIO64V2) ? 0x89 : 0x88; - case 0x30: return s3->has_bios ? (s3->pci_regs[0x30] & 0x01) : 0x00; /*BIOS ROM address*/ - case 0x31: return 0x00; - case 0x32: return s3->has_bios ? s3->pci_regs[0x32] : 0x00; - case 0x33: return s3->has_bios ? s3->pci_regs[0x33] : 0x00; - - case 0x3c: return s3->int_line; - case 0x3d: return PCI_INTA; - - case 0x3e: return (s3->chip == S3_TRIO64V2) ? 0x04 : 0x00; break; - case 0x3f: return (s3->chip == S3_TRIO64V2) ? 0xff : 0x00; break; - } - return 0; + case PCI_REG_COMMAND: + if (s3->chip == S3_VISION968 || s3->chip == S3_VISION868) + return s3->pci_regs[PCI_REG_COMMAND] | 0x80; /*Respond to IO and memory accesses*/ + else + return s3->pci_regs[PCI_REG_COMMAND]; /*Respond to IO and memory accesses*/ + + case 0x07: + return (s3->chip == S3_TRIO64V2) ? (s3->pci_regs[0x07] & 0x36) : (1 << 1); /*Medium DEVSEL timing*/ + + case 0x08: + return (s3->chip == S3_TRIO64V) ? 0x40 : 0; /*Revision ID*/ + case 0x09: + return 0; /*Programming interface*/ + + case 0x0a: + if (s3->chip >= S3_TRIO32 || s3->chip == S3_VISION968 || s3->chip == S3_VISION868) + return 0x00; /*Supports VGA interface*/ + else + return 0x01; + case 0x0b: + if (s3->chip >= S3_TRIO32 || s3->chip == S3_VISION968 || s3->chip == S3_VISION868) + return 0x03; + else + return 0x00; + + case 0x0d: + return (s3->chip == S3_TRIO64V2) ? (s3->pci_regs[0x0d] & 0xf8) : 0x00; + + case 0x10: + return 0x00; /*Linear frame buffer address*/ + case 0x11: + return 0x00; + case 0x12: + if (svga->crtc[0x53] & 0x08) + return 0x00; + else + return (svga->crtc[0x5a] & 0x80); + + case 0x13: + if (svga->crtc[0x53] & 0x08) { + return (s3->chip >= S3_TRIO64V) ? (svga->crtc[0x59] & 0xfc) : (svga->crtc[0x59] & 0xfe); + } else { + return svga->crtc[0x59]; + } + + case 0x30: + return s3->has_bios ? (s3->pci_regs[0x30] & 0x01) : 0x00; /*BIOS ROM address*/ + case 0x31: + return 0x00; + case 0x32: + return s3->has_bios ? s3->pci_regs[0x32] : 0x00; + case 0x33: + return s3->has_bios ? s3->pci_regs[0x33] : 0x00; + + case 0x3c: + return s3->int_line; + case 0x3d: + return PCI_INTA; + + case 0x3e: + return (s3->chip == S3_TRIO64V2) ? 0x04 : 0x00; + case 0x3f: + return (s3->chip == S3_TRIO64V2) ? 0xff : 0x00; + + default: + break; + } + return 0; } static void -s3_pci_write(int func, int addr, uint8_t val, void *p) +s3_pci_write(UNUSED(int func), int addr, uint8_t val, void *priv) { - s3_t *s3 = (s3_t *)p; - svga_t *svga = &s3->svga; + s3_t *s3 = (s3_t *) priv; + svga_t *svga = &s3->svga; - switch (addr) - { - case 0x00: case 0x01: case 0x02: case 0x03: - case 0x08: case 0x09: case 0x0a: case 0x0b: - case 0x3d: case 0x3e: case 0x3f: - if (s3->chip == S3_TRIO64V2) - return; - break; - - case PCI_REG_COMMAND: - if (val & PCI_COMMAND_IO) - s3_io_set(s3); - else - s3_io_remove(s3); - s3->pci_regs[PCI_REG_COMMAND] = (val & 0x23); - s3_updatemapping(s3); - break; - - case 0x07: - if (s3->chip == S3_TRIO64V2) { - s3->pci_regs[0x07] = val & 0x3e; - return; - } - break; - - case 0x0d: - if (s3->chip == S3_TRIO64V2) { - s3->pci_regs[0x0d] = val & 0xf8; - return; - } - break; - - case 0x12: - if (!(svga->crtc[0x53] & 0x08)) { - svga->crtc[0x5a] = (svga->crtc[0x5a] & 0x7f) | (val & 0x80); - s3_updatemapping(s3); - } - break; - - case 0x13: - if (svga->crtc[0x53] & 0x08) { - svga->crtc[0x59] = (s3->chip >= S3_TRIO64V) ? (val & 0xfc) : (val & 0xfe); - } else { - svga->crtc[0x59] = val; - } - s3_updatemapping(s3); - break; + switch (addr) { + case 0x00: + case 0x01: + case 0x02: + case 0x03: + case 0x08: + case 0x09: + case 0x0a: + case 0x0b: + case 0x3d: + case 0x3e: + case 0x3f: + if (s3->chip == S3_TRIO64V2) + return; + break; - case 0x30: case 0x32: case 0x33: - if (!s3->has_bios) - return; - s3->pci_regs[addr] = val; - if (s3->pci_regs[0x30] & 0x01) - { - uint32_t biosaddr = (s3->pci_regs[0x32] << 16) | (s3->pci_regs[0x33] << 24); - mem_mapping_set_addr(&s3->bios_rom.mapping, biosaddr, 0x8000); - } - else - { - mem_mapping_disable(&s3->bios_rom.mapping); - } - return; - - case 0x3c: - s3->int_line = val; - return; - } + case PCI_REG_COMMAND: + if (val & PCI_COMMAND_IO) + s3_io_set(s3); + else + s3_io_remove(s3); + s3->pci_regs[PCI_REG_COMMAND] = (val & 0x23); + s3_updatemapping(s3); + break; + + case 0x07: + if (s3->chip == S3_TRIO64V2) { + s3->pci_regs[0x07] = val & 0x3e; + return; + } + break; + + case 0x0d: + if (s3->chip == S3_TRIO64V2) { + s3->pci_regs[0x0d] = val & 0xf8; + return; + } + break; + + case 0x12: + if (!(svga->crtc[0x53] & 0x08)) { + svga->crtc[0x5a] = (svga->crtc[0x5a] & 0x7f) | (val & 0x80); + s3_updatemapping(s3); + } + break; + + case 0x13: + if (svga->crtc[0x53] & 0x08) { + svga->crtc[0x59] = (s3->chip >= S3_TRIO64V) ? (val & 0xfc) : (val & 0xfe); + } else { + svga->crtc[0x59] = val; + } + s3_updatemapping(s3); + break; + + case 0x30: + case 0x32: + case 0x33: + if (!s3->has_bios) + return; + s3->pci_regs[addr] = val; + if (s3->pci_regs[0x30] & 0x01) { + uint32_t biosaddr = (s3->pci_regs[0x32] << 16) | (s3->pci_regs[0x33] << 24); + mem_mapping_set_addr(&s3->bios_rom.mapping, biosaddr, 0x8000); + } else { + mem_mapping_disable(&s3->bios_rom.mapping); + } + return; + + case 0x3c: + s3->int_line = val; + return; + + default: + break; + } } static void fifo_thread(void *param) { - s3_t *s3 = (s3_t *)param; - uint64_t start_time, end_time; - - while (s3->fifo_thread_run) { - thread_set_event(s3->fifo_not_full_event); - thread_wait_event(s3->wake_fifo_thread, -1); - thread_reset_event(s3->wake_fifo_thread); - s3->blitter_busy = 1; - while (!FIFO_EMPTY) { - start_time = plat_timer_read(); - fifo_entry_t *fifo = &s3->fifo[s3->fifo_read_idx & FIFO_MASK]; + s3_t *s3 = (s3_t *) param; + uint64_t start_time; + uint64_t end_time; - switch (fifo->addr_type & FIFO_TYPE) { - case FIFO_WRITE_BYTE: - s3_accel_write_fifo(s3, fifo->addr_type & FIFO_ADDR, fifo->val); - break; - case FIFO_WRITE_WORD: - s3_accel_write_fifo_w(s3, fifo->addr_type & FIFO_ADDR, fifo->val); - break; - case FIFO_WRITE_DWORD: - s3_accel_write_fifo_l(s3, fifo->addr_type & FIFO_ADDR, fifo->val); - break; - case FIFO_OUT_BYTE: - s3_accel_out_fifo(s3, fifo->addr_type & FIFO_ADDR, fifo->val); - break; - case FIFO_OUT_WORD: - s3_accel_out_fifo_w(s3, fifo->addr_type & FIFO_ADDR, fifo->val); - break; - case FIFO_OUT_DWORD: - s3_accel_out_fifo_l(s3, fifo->addr_type & FIFO_ADDR, fifo->val); - break; - } - - s3->fifo_read_idx++; - fifo->addr_type = FIFO_INVALID; + while (s3->fifo_thread_run) { + thread_set_event(s3->fifo_not_full_event); + thread_wait_event(s3->wake_fifo_thread, -1); + thread_reset_event(s3->wake_fifo_thread); + s3->blitter_busy = 1; + while (!FIFO_EMPTY) { + start_time = plat_timer_read(); + fifo_entry_t *fifo = &s3->fifo[s3->fifo_read_idx & FIFO_MASK]; - if (FIFO_ENTRIES > 0xe000) - thread_set_event(s3->fifo_not_full_event); + switch (fifo->addr_type & FIFO_TYPE) { + case FIFO_WRITE_BYTE: + s3_accel_write_fifo(s3, fifo->addr_type & FIFO_ADDR, fifo->val); + break; + case FIFO_WRITE_WORD: + s3_accel_write_fifo_w(s3, fifo->addr_type & FIFO_ADDR, fifo->val); + break; + case FIFO_WRITE_DWORD: + s3_accel_write_fifo_l(s3, fifo->addr_type & FIFO_ADDR, fifo->val); + break; + case FIFO_OUT_BYTE: + s3_accel_out_fifo(s3, fifo->addr_type & FIFO_ADDR, fifo->val); + break; + case FIFO_OUT_WORD: + s3_accel_out_fifo_w(s3, fifo->addr_type & FIFO_ADDR, fifo->val); + break; + case FIFO_OUT_DWORD: + s3_accel_out_fifo_l(s3, fifo->addr_type & FIFO_ADDR, fifo->val); + break; - end_time = plat_timer_read(); - s3->blitter_time += (end_time - start_time); - } - s3->blitter_busy = 0; - s3->subsys_stat |= INT_FIFO_EMP; - s3_update_irqs(s3); - } + default: + break; + } + + s3->fifo_read_idx++; + fifo->addr_type = FIFO_INVALID; + + if (FIFO_ENTRIES > 0xe000) + thread_set_event(s3->fifo_not_full_event); + + end_time = plat_timer_read(); + s3->blitter_time += (end_time - start_time); + } + s3->blitter_busy = 0; + s3->subsys_stat |= INT_FIFO_EMP; + s3_update_irqs(s3); + } } -static int vram_sizes[] = -{ - 7, /*512 kB*/ - 6, /*1 MB*/ - 4, /*2 MB*/ - 0, - 0, /*4 MB*/ - 0, - 0, /*6 MB*/ - 0, - 3 /*8 MB*/ +static int vram_sizes[] = { + 7, /*512 kB*/ + 6, /*1 MB*/ + 4, /*2 MB*/ + 0, + 0, /*4 MB*/ + 0, + 0, /*6 MB*/ + 0, + 3 /*8 MB*/ }; -static void s3_reset(void *priv) +static void +s3_reset(void *priv) { - s3_t *s3 = (s3_t *) priv; + s3_t *s3 = (s3_t *) priv; svga_t *svga = &s3->svga; memset(svga->crtc, 0x00, sizeof(svga->crtc)); - svga->crtc[0] = 63; - svga->crtc[6] = 255; - svga->dispontime = 1000ull << 32; - svga->dispofftime = 1000ull << 32; - svga->bpp = 8; + svga->crtc[0] = 63; + svga->crtc[6] = 255; + svga->dispontime = 1000ULL << 32; + svga->dispofftime = 1000ULL << 32; + svga->bpp = 8; - if (s3->pci) - svga->crtc[0x36] = 2 | (3 << 2) | (1 << 4); - else if (s3->vlb) - svga->crtc[0x36] = 1 | (3 << 2) | (1 << 4); - else - svga->crtc[0x36] = 3 | (1 << 4); + if (s3->pci) + svga->crtc[0x36] = 2 | (3 << 2) | (1 << 4); + else if (s3->vlb) + svga->crtc[0x36] = 1 | (3 << 2) | (1 << 4); + else + svga->crtc[0x36] = 3 | (1 << 4); - if (s3->chip >= S3_86C928) - svga->crtc[0x36] |= (vram_sizes[s3->vram] << 5); - else - svga->crtc[0x36] |= ((s3->vram == 1) ? 0x00 : 0x20) | 0x80; + if (s3->chip >= S3_86C928) + svga->crtc[0x36] |= (vram_sizes[s3->vram] << 5); + else + svga->crtc[0x36] |= ((s3->vram == 1) ? 0x00 : 0x20) | 0x80; - svga->crtc[0x37] = 1 | (7 << 5); + svga->crtc[0x37] = 1 | (7 << 5); - if (s3->chip >= S3_86C928) - svga->crtc[0x37] |= 0x04; + if (s3->chip >= S3_86C928) + svga->crtc[0x37] |= 0x04; s3_io_set(s3); @@ -6658,1781 +7819,1765 @@ static void s3_reset(void *priv) s3->pci_regs[0x32] = 0x0c; s3->pci_regs[0x33] = 0x00; - switch(s3->card_type) { - case S3_MIROCRYSTAL8S_805: - case S3_MIROCRYSTAL10SD_805: - svga->crtc[0x5a] = 0x0a; - svga->getclock = sdac_getclock; - break; + switch (s3->card_type) { + case S3_MIROCRYSTAL8S_805: + case S3_MIROCRYSTAL10SD_805: + svga->crtc[0x5a] = 0x0a; + svga->getclock = sdac_getclock; + break; - case S3_SPEA_MIRAGE_86C801: - case S3_SPEA_MIRAGE_86C805: - svga->crtc[0x5a] = 0x0a; - break; + case S3_SPEA_MIRAGE_86C801: + case S3_SPEA_MIRAGE_86C805: + svga->crtc[0x5a] = 0x0a; + break; - case S3_PHOENIX_86C801: - case S3_PHOENIX_86C805: - svga->crtc[0x5a] = 0x0a; - break; + case S3_PHOENIX_86C801: + case S3_PHOENIX_86C805: + svga->crtc[0x5a] = 0x0a; + break; - case S3_METHEUS_86C928: - case S3_SPEA_MERCURY_LITE_PCI: - svga->crtc[0x5a] = 0x0a; - break; + case S3_METHEUS_86C928: + case S3_SPEA_MERCURY_LITE_PCI: + svga->crtc[0x5a] = 0x0a; + break; - case S3_PARADISE_BAHAMAS64: - case S3_PHOENIX_VISION864: - case S3_MIROCRYSTAL20SD_864: - svga->crtc[0x5a] = 0x0a; - break; + case S3_PARADISE_BAHAMAS64: + case S3_PHOENIX_VISION864: + case S3_MIROCRYSTAL20SD_864: + svga->crtc[0x5a] = 0x0a; + break; - case S3_DIAMOND_STEALTH64_964: - case S3_ELSAWIN2KPROX_964: - case S3_MIROCRYSTAL20SV_964: - svga->crtc[0x5a] = 0x0a; - break; + case S3_DIAMOND_STEALTH64_964: + case S3_ELSAWIN2KPROX_964: + case S3_MIROCRYSTAL20SV_964: + svga->crtc[0x5a] = 0x0a; + break; - case S3_ELSAWIN2KPROX: - case S3_SPEA_MERCURY_P64V: - case S3_MIROVIDEO40SV_ERGO_968: - case S3_NUMBER9_9FX_771: - case S3_PHOENIX_VISION968: - if (s3->pci) { - svga->crtc[0x53] = 0x18; - svga->crtc[0x58] = 0x10; - svga->crtc[0x59] = 0x70; - svga->crtc[0x5a] = 0x00; - svga->crtc[0x6c] = 1; - } else { - svga->crtc[0x53] = 0x00; - svga->crtc[0x59] = 0x00; - svga->crtc[0x5a] = 0x0a; - } - break; + case S3_ELSAWIN2KPROX: + case S3_SPEA_MERCURY_P64V: + case S3_MIROVIDEO40SV_ERGO_968: + case S3_NUMBER9_9FX_771: + case S3_PHOENIX_VISION968: + if (s3->pci) { + svga->crtc[0x53] = 0x18; + svga->crtc[0x58] = 0x10; + svga->crtc[0x59] = 0x70; + svga->crtc[0x5a] = 0x00; + svga->crtc[0x6c] = 1; + } else { + svga->crtc[0x53] = 0x00; + svga->crtc[0x59] = 0x00; + svga->crtc[0x5a] = 0x0a; + } + break; - case S3_NUMBER9_9FX_531: - case S3_PHOENIX_VISION868: - if (s3->pci) { - svga->crtc[0x53] = 0x18; - svga->crtc[0x58] = 0x10; - svga->crtc[0x59] = 0x70; - svga->crtc[0x5a] = 0x00; - svga->crtc[0x6c] = 1; - } else { - svga->crtc[0x53] = 0x00; - svga->crtc[0x59] = 0x00; - svga->crtc[0x5a] = 0x0a; - } - break; + case S3_NUMBER9_9FX_531: + case S3_PHOENIX_VISION868: + if (s3->pci) { + svga->crtc[0x53] = 0x18; + svga->crtc[0x58] = 0x10; + svga->crtc[0x59] = 0x70; + svga->crtc[0x5a] = 0x00; + svga->crtc[0x6c] = 1; + } else { + svga->crtc[0x53] = 0x00; + svga->crtc[0x59] = 0x00; + svga->crtc[0x5a] = 0x0a; + } + break; - case S3_PHOENIX_TRIO64: - case S3_PHOENIX_TRIO64_ONBOARD: - case S3_PHOENIX_TRIO64VPLUS: - case S3_PHOENIX_TRIO64VPLUS_ONBOARD: - case S3_DIAMOND_STEALTH64_764: - case S3_SPEA_MIRAGE_P64: - case S3_NUMBER9_9FX: - if (s3->card_type == S3_PHOENIX_TRIO64VPLUS || s3->card_type == S3_PHOENIX_TRIO64VPLUS_ONBOARD) - svga->crtc[0x53] = 0x08; - break; + case S3_PHOENIX_TRIO64: + case S3_PHOENIX_TRIO64_ONBOARD: + case S3_PHOENIX_TRIO64VPLUS: + case S3_PHOENIX_TRIO64VPLUS_ONBOARD: + case S3_DIAMOND_STEALTH64_764: + case S3_SPEA_MIRAGE_P64: + case S3_NUMBER9_9FX: + if (s3->card_type == S3_PHOENIX_TRIO64VPLUS || s3->card_type == S3_PHOENIX_TRIO64VPLUS_ONBOARD) + svga->crtc[0x53] = 0x08; + break; - case S3_TRIO64V2_DX: - svga->crtc[0x53] = 0x08; - svga->crtc[0x59] = 0x70; - svga->crtc[0x5a] = 0x00; - svga->crtc[0x6c] = 1; - s3->pci_regs[0x05] = 0; - s3->pci_regs[0x06] = 0; - s3->pci_regs[0x07] = 2; - s3->pci_regs[0x3d] = 1; - s3->pci_regs[0x3e] = 4; - s3->pci_regs[0x3f] = 0xff; - break; - } + case S3_TRIO64V2_DX: + svga->crtc[0x53] = 0x08; + svga->crtc[0x59] = 0x70; + svga->crtc[0x5a] = 0x00; + svga->crtc[0x6c] = 1; + s3->pci_regs[0x05] = 0; + s3->pci_regs[0x06] = 0; + s3->pci_regs[0x07] = 2; + s3->pci_regs[0x3d] = 1; + s3->pci_regs[0x3e] = 4; + s3->pci_regs[0x3f] = 0xff; + break; - if (s3->has_bios) { - if (s3->pci) - mem_mapping_disable(&s3->bios_rom.mapping); - } + default: + break; + } - s3_updatemapping(s3); + if (s3->has_bios) { + if (s3->pci) + mem_mapping_disable(&s3->bios_rom.mapping); + } - mem_mapping_disable(&s3->mmio_mapping); - mem_mapping_disable(&s3->new_mmio_mapping); + s3_updatemapping(s3); + + mem_mapping_disable(&s3->mmio_mapping); + mem_mapping_disable(&s3->new_mmio_mapping); } - -static void *s3_init(const device_t *info) +static void * +s3_init(const device_t *info) { - const char *bios_fn; - int chip, stepping; - s3_t *s3 = malloc(sizeof(s3_t)); - svga_t *svga = &s3->svga; - int vram; - uint32_t vram_size; + const char *bios_fn; + int chip; + int stepping; + s3_t *s3 = malloc(sizeof(s3_t)); + svga_t *svga = &s3->svga; + int vram; + uint32_t vram_size; - switch(info->local) { - case S3_ORCHID_86C911: - bios_fn = ROM_ORCHID_86C911; - chip = S3_86C911; - video_inform(VIDEO_FLAG_TYPE_SPECIAL, &timing_s3_86c911); - break; - case S3_DIAMOND_STEALTH_VRAM: - bios_fn = ROM_DIAMOND_STEALTH_VRAM; - chip = S3_86C911; - video_inform(VIDEO_FLAG_TYPE_SPECIAL, &timing_s3_86c911); - break; - case S3_AMI_86C924: - bios_fn = ROM_AMI_86C924; - chip = S3_86C924; - video_inform(VIDEO_FLAG_TYPE_SPECIAL, &timing_s3_86c911); - break; - case S3_SPEA_MIRAGE_86C801: - bios_fn = ROM_SPEA_MIRAGE_86C801; - chip = S3_86C801; - video_inform(VIDEO_FLAG_TYPE_SPECIAL, &timing_s3_86c801); - break; - case S3_SPEA_MIRAGE_86C805: - bios_fn = ROM_SPEA_MIRAGE_86C805; - chip = S3_86C805; - video_inform(VIDEO_FLAG_TYPE_SPECIAL, &timing_s3_86c805); - break; - case S3_MIROCRYSTAL8S_805: - bios_fn = ROM_MIROCRYSTAL8S_805; - chip = S3_86C805; - video_inform(VIDEO_FLAG_TYPE_SPECIAL, &timing_s3_86c805); - break; - case S3_MIROCRYSTAL10SD_805: - bios_fn = ROM_MIROCRYSTAL10SD_805; - chip = S3_86C805; - video_inform(VIDEO_FLAG_TYPE_SPECIAL, &timing_s3_86c805); - break; - case S3_PHOENIX_86C801: - bios_fn = ROM_PHOENIX_86C80X; - chip = S3_86C801; - video_inform(VIDEO_FLAG_TYPE_SPECIAL, &timing_s3_86c801); - break; - case S3_PHOENIX_86C805: - bios_fn = ROM_PHOENIX_86C80X; - chip = S3_86C805; - video_inform(VIDEO_FLAG_TYPE_SPECIAL, &timing_s3_86c805); - break; - case S3_METHEUS_86C928: - bios_fn = ROM_METHEUS_86C928; - chip = S3_86C928; - if (info->flags & DEVICE_VLB) - video_inform(VIDEO_FLAG_TYPE_SPECIAL, &timing_s3_86c805); - else - video_inform(VIDEO_FLAG_TYPE_SPECIAL, &timing_s3_86c801); - break; - case S3_SPEA_MERCURY_LITE_PCI: - bios_fn = ROM_SPEA_MERCURY_LITE_PCI; - chip = S3_86C928PCI; - video_inform(VIDEO_FLAG_TYPE_SPECIAL, &timing_s3_86c928pci); - break; - case S3_MIROCRYSTAL20SD_864: - bios_fn = ROM_MIROCRYSTAL20SD_864_VLB; - chip = S3_VISION864; - video_inform(VIDEO_FLAG_TYPE_SPECIAL, &timing_s3_vision864_vlb); - break; - case S3_PARADISE_BAHAMAS64: - bios_fn = ROM_PARADISE_BAHAMAS64; - chip = S3_VISION864; - if (info->flags & DEVICE_PCI) - video_inform(VIDEO_FLAG_TYPE_SPECIAL, &timing_s3_vision864_pci); - else - video_inform(VIDEO_FLAG_TYPE_SPECIAL, &timing_s3_vision864_vlb); - break; - case S3_PHOENIX_VISION864: - bios_fn = ROM_PHOENIX_VISION864; - chip = S3_VISION864; - if (info->flags & DEVICE_PCI) - video_inform(VIDEO_FLAG_TYPE_SPECIAL, &timing_s3_vision864_pci); - else - video_inform(VIDEO_FLAG_TYPE_SPECIAL, &timing_s3_vision864_vlb); - break; - case S3_NUMBER9_9FX_531: - bios_fn = ROM_NUMBER9_9FX_531; - chip = S3_VISION868; - video_inform(VIDEO_FLAG_TYPE_SPECIAL, &timing_s3_vision868_pci); - break; - case S3_PHOENIX_VISION868: - bios_fn = ROM_PHOENIX_VISION868; - chip = S3_VISION868; - if (info->flags & DEVICE_PCI) - video_inform(VIDEO_FLAG_TYPE_SPECIAL, &timing_s3_vision868_pci); - else - video_inform(VIDEO_FLAG_TYPE_SPECIAL, &timing_s3_vision868_vlb); - break; - case S3_DIAMOND_STEALTH64_964: - bios_fn = ROM_DIAMOND_STEALTH64_964; - chip = S3_VISION964; - if (info->flags & DEVICE_PCI) - video_inform(VIDEO_FLAG_TYPE_SPECIAL, &timing_s3_vision964_pci); - else - video_inform(VIDEO_FLAG_TYPE_SPECIAL, &timing_s3_vision964_vlb); - break; - case S3_MIROCRYSTAL20SV_964: - chip = S3_VISION964; - if (info->flags & DEVICE_PCI) { - bios_fn = ROM_MIROCRYSTAL20SV_964_PCI; - video_inform(VIDEO_FLAG_TYPE_SPECIAL, &timing_s3_vision964_pci); - } else { - bios_fn = ROM_MIROCRYSTAL20SV_964_VLB; - video_inform(VIDEO_FLAG_TYPE_SPECIAL, &timing_s3_vision964_vlb); - } - break; - case S3_MIROVIDEO40SV_ERGO_968: - bios_fn = ROM_MIROVIDEO40SV_ERGO_968_PCI; - chip = S3_VISION968; - video_inform(VIDEO_FLAG_TYPE_SPECIAL, &timing_s3_vision968_pci); - break; - case S3_NUMBER9_9FX_771: - bios_fn = ROM_NUMBER9_9FX_771; - chip = S3_VISION968; - video_inform(VIDEO_FLAG_TYPE_SPECIAL, &timing_s3_vision968_pci); - break; - case S3_PHOENIX_VISION968: - bios_fn = ROM_PHOENIX_VISION968; - chip = S3_VISION968; - if (info->flags & DEVICE_PCI) - video_inform(VIDEO_FLAG_TYPE_SPECIAL, &timing_s3_vision968_pci); - else - video_inform(VIDEO_FLAG_TYPE_SPECIAL, &timing_s3_vision968_vlb); - break; - case S3_ELSAWIN2KPROX_964: - bios_fn = ROM_ELSAWIN2KPROX_964; - chip = S3_VISION964; - video_inform(VIDEO_FLAG_TYPE_SPECIAL, &timing_s3_vision964_pci); - break; - case S3_ELSAWIN2KPROX: - bios_fn = ROM_ELSAWIN2KPROX; - chip = S3_VISION968; - video_inform(VIDEO_FLAG_TYPE_SPECIAL, &timing_s3_vision968_pci); - break; - case S3_SPEA_MERCURY_P64V: - bios_fn = ROM_SPEA_MERCURY_P64V; - chip = S3_VISION968; - video_inform(VIDEO_FLAG_TYPE_SPECIAL, &timing_s3_vision968_pci); - break; - case S3_PHOENIX_TRIO32: - bios_fn = ROM_PHOENIX_TRIO32; - chip = S3_TRIO32; - if (info->flags & DEVICE_PCI) - video_inform(VIDEO_FLAG_TYPE_SPECIAL, &timing_s3_trio32_pci); - else - video_inform(VIDEO_FLAG_TYPE_SPECIAL, &timing_s3_trio32_vlb); - break; - case S3_DIAMOND_STEALTH_SE: - bios_fn = ROM_DIAMOND_STEALTH_SE; - chip = S3_TRIO32; - if (info->flags & DEVICE_PCI) - video_inform(VIDEO_FLAG_TYPE_SPECIAL, &timing_s3_trio32_pci); - else - video_inform(VIDEO_FLAG_TYPE_SPECIAL, &timing_s3_trio32_vlb); - break; - case S3_PHOENIX_TRIO64: - bios_fn = ROM_PHOENIX_TRIO64; - chip = S3_TRIO64; - if (info->flags & DEVICE_PCI) - video_inform(VIDEO_FLAG_TYPE_SPECIAL, &timing_s3_trio64_pci); - else - video_inform(VIDEO_FLAG_TYPE_SPECIAL, &timing_s3_trio64_vlb); - break; - case S3_SPEA_MIRAGE_P64: - bios_fn = ROM_SPEA_MIRAGE_P64; - chip = S3_TRIO64; - video_inform(VIDEO_FLAG_TYPE_SPECIAL, &timing_s3_trio64_vlb); - break; - case S3_PHOENIX_TRIO64_ONBOARD: - bios_fn = NULL; - chip = S3_TRIO64; - if (info->flags & DEVICE_PCI) - video_inform(VIDEO_FLAG_TYPE_SPECIAL, &timing_s3_trio64_pci); - else - video_inform(VIDEO_FLAG_TYPE_SPECIAL, &timing_s3_trio64_vlb); - break; - case S3_PHOENIX_TRIO64VPLUS: - bios_fn = ROM_PHOENIX_TRIO64VPLUS; - chip = S3_TRIO64V; - if (info->flags & DEVICE_PCI) - video_inform(VIDEO_FLAG_TYPE_SPECIAL, &timing_s3_trio64_pci); - else - video_inform(VIDEO_FLAG_TYPE_SPECIAL, &timing_s3_trio64_vlb); - break; - case S3_PHOENIX_TRIO64VPLUS_ONBOARD: - bios_fn = NULL; - chip = S3_TRIO64V; - if (info->flags & DEVICE_PCI) - video_inform(VIDEO_FLAG_TYPE_SPECIAL, &timing_s3_trio64_pci); - else - video_inform(VIDEO_FLAG_TYPE_SPECIAL, &timing_s3_trio64_vlb); - break; - case S3_DIAMOND_STEALTH64_764: - bios_fn = ROM_DIAMOND_STEALTH64_764; - chip = S3_TRIO64; - if (info->flags & DEVICE_PCI) - video_inform(VIDEO_FLAG_TYPE_SPECIAL, &timing_s3_stealth64_pci); - else - video_inform(VIDEO_FLAG_TYPE_SPECIAL, &timing_s3_stealth64_vlb); - break; - case S3_NUMBER9_9FX: - bios_fn = ROM_NUMBER9_9FX; - chip = S3_TRIO64; - if (info->flags & DEVICE_PCI) - video_inform(VIDEO_FLAG_TYPE_SPECIAL, &timing_s3_trio64_pci); - else - video_inform(VIDEO_FLAG_TYPE_SPECIAL, &timing_s3_trio64_vlb); - break; - case S3_TRIO64V2_DX: - bios_fn = ROM_TRIO64V2_DX_VBE20; - chip = S3_TRIO64V2; - video_inform(VIDEO_FLAG_TYPE_SPECIAL, &timing_s3_trio64_pci); - break; - case S3_TRIO64V2_DX_ONBOARD: - bios_fn = NULL; - chip = S3_TRIO64V2; - video_inform(VIDEO_FLAG_TYPE_SPECIAL, &timing_s3_trio64_pci); - break; - default: - free(s3); - return NULL; - } + switch (info->local) { + case S3_ORCHID_86C911: + bios_fn = ROM_ORCHID_86C911; + chip = S3_86C911; + video_inform(VIDEO_FLAG_TYPE_SPECIAL, &timing_s3_86c911); + break; + case S3_DIAMOND_STEALTH_VRAM: + bios_fn = ROM_DIAMOND_STEALTH_VRAM; + chip = S3_86C911; + video_inform(VIDEO_FLAG_TYPE_SPECIAL, &timing_s3_86c911); + break; + case S3_AMI_86C924: + bios_fn = ROM_AMI_86C924; + chip = S3_86C924; + video_inform(VIDEO_FLAG_TYPE_SPECIAL, &timing_s3_86c911); + break; + case S3_SPEA_MIRAGE_86C801: + bios_fn = ROM_SPEA_MIRAGE_86C801; + chip = S3_86C801; + video_inform(VIDEO_FLAG_TYPE_SPECIAL, &timing_s3_86c801); + break; + case S3_86C805_ONBOARD: + bios_fn = NULL; + chip = S3_86C805; + video_inform(VIDEO_FLAG_TYPE_SPECIAL, &timing_s3_86c805); + break; + case S3_SPEA_MIRAGE_86C805: + bios_fn = ROM_SPEA_MIRAGE_86C805; + chip = S3_86C805; + video_inform(VIDEO_FLAG_TYPE_SPECIAL, &timing_s3_86c805); + break; + case S3_MIROCRYSTAL8S_805: + bios_fn = ROM_MIROCRYSTAL8S_805; + chip = S3_86C805; + video_inform(VIDEO_FLAG_TYPE_SPECIAL, &timing_s3_86c805); + break; + case S3_MIROCRYSTAL10SD_805: + bios_fn = ROM_MIROCRYSTAL10SD_805; + chip = S3_86C805; + video_inform(VIDEO_FLAG_TYPE_SPECIAL, &timing_s3_86c805); + break; + case S3_PHOENIX_86C801: + bios_fn = ROM_PHOENIX_86C80X; + chip = S3_86C801; + video_inform(VIDEO_FLAG_TYPE_SPECIAL, &timing_s3_86c801); + break; + case S3_PHOENIX_86C805: + bios_fn = ROM_PHOENIX_86C80X; + chip = S3_86C805; + video_inform(VIDEO_FLAG_TYPE_SPECIAL, &timing_s3_86c805); + break; + case S3_METHEUS_86C928: + bios_fn = ROM_METHEUS_86C928; + chip = S3_86C928; + if (info->flags & DEVICE_VLB) + video_inform(VIDEO_FLAG_TYPE_SPECIAL, &timing_s3_86c805); + else + video_inform(VIDEO_FLAG_TYPE_SPECIAL, &timing_s3_86c801); + break; + case S3_SPEA_MERCURY_LITE_PCI: + bios_fn = ROM_SPEA_MERCURY_LITE_PCI; + chip = S3_86C928PCI; + video_inform(VIDEO_FLAG_TYPE_SPECIAL, &timing_s3_86c928pci); + break; + case S3_MIROCRYSTAL20SD_864: + bios_fn = ROM_MIROCRYSTAL20SD_864_VLB; + chip = S3_VISION864; + video_inform(VIDEO_FLAG_TYPE_SPECIAL, &timing_s3_vision864_vlb); + break; + case S3_PARADISE_BAHAMAS64: + bios_fn = ROM_PARADISE_BAHAMAS64; + chip = S3_VISION864; + if (info->flags & DEVICE_PCI) + video_inform(VIDEO_FLAG_TYPE_SPECIAL, &timing_s3_vision864_pci); + else + video_inform(VIDEO_FLAG_TYPE_SPECIAL, &timing_s3_vision864_vlb); + break; + case S3_PHOENIX_VISION864: + bios_fn = ROM_PHOENIX_VISION864; + chip = S3_VISION864; + if (info->flags & DEVICE_PCI) + video_inform(VIDEO_FLAG_TYPE_SPECIAL, &timing_s3_vision864_pci); + else + video_inform(VIDEO_FLAG_TYPE_SPECIAL, &timing_s3_vision864_vlb); + break; + case S3_NUMBER9_9FX_531: + bios_fn = ROM_NUMBER9_9FX_531; + chip = S3_VISION868; + video_inform(VIDEO_FLAG_TYPE_SPECIAL, &timing_s3_vision868_pci); + break; + case S3_PHOENIX_VISION868: + bios_fn = ROM_PHOENIX_VISION868; + chip = S3_VISION868; + if (info->flags & DEVICE_PCI) + video_inform(VIDEO_FLAG_TYPE_SPECIAL, &timing_s3_vision868_pci); + else + video_inform(VIDEO_FLAG_TYPE_SPECIAL, &timing_s3_vision868_vlb); + break; + case S3_DIAMOND_STEALTH64_964: + bios_fn = ROM_DIAMOND_STEALTH64_964; + chip = S3_VISION964; + if (info->flags & DEVICE_PCI) + video_inform(VIDEO_FLAG_TYPE_SPECIAL, &timing_s3_vision964_pci); + else + video_inform(VIDEO_FLAG_TYPE_SPECIAL, &timing_s3_vision964_vlb); + break; + case S3_MIROCRYSTAL20SV_964: + chip = S3_VISION964; + if (info->flags & DEVICE_PCI) { + bios_fn = ROM_MIROCRYSTAL20SV_964_PCI; + video_inform(VIDEO_FLAG_TYPE_SPECIAL, &timing_s3_vision964_pci); + } else { + bios_fn = ROM_MIROCRYSTAL20SV_964_VLB; + video_inform(VIDEO_FLAG_TYPE_SPECIAL, &timing_s3_vision964_vlb); + } + break; + case S3_MIROVIDEO40SV_ERGO_968: + bios_fn = ROM_MIROVIDEO40SV_ERGO_968_PCI; + chip = S3_VISION968; + video_inform(VIDEO_FLAG_TYPE_SPECIAL, &timing_s3_vision968_pci); + break; + case S3_NUMBER9_9FX_771: + bios_fn = ROM_NUMBER9_9FX_771; + chip = S3_VISION968; + video_inform(VIDEO_FLAG_TYPE_SPECIAL, &timing_s3_vision968_pci); + break; + case S3_PHOENIX_VISION968: + bios_fn = ROM_PHOENIX_VISION968; + chip = S3_VISION968; + if (info->flags & DEVICE_PCI) + video_inform(VIDEO_FLAG_TYPE_SPECIAL, &timing_s3_vision968_pci); + else + video_inform(VIDEO_FLAG_TYPE_SPECIAL, &timing_s3_vision968_vlb); + break; + case S3_ELSAWIN2KPROX_964: + bios_fn = ROM_ELSAWIN2KPROX_964; + chip = S3_VISION964; + video_inform(VIDEO_FLAG_TYPE_SPECIAL, &timing_s3_vision964_pci); + break; + case S3_ELSAWIN2KPROX: + bios_fn = ROM_ELSAWIN2KPROX; + chip = S3_VISION968; + video_inform(VIDEO_FLAG_TYPE_SPECIAL, &timing_s3_vision968_pci); + break; + case S3_SPEA_MERCURY_P64V: + bios_fn = ROM_SPEA_MERCURY_P64V; + chip = S3_VISION968; + video_inform(VIDEO_FLAG_TYPE_SPECIAL, &timing_s3_vision968_pci); + break; + case S3_PHOENIX_TRIO32: + bios_fn = ROM_PHOENIX_TRIO32; + chip = S3_TRIO32; + if (info->flags & DEVICE_PCI) + video_inform(VIDEO_FLAG_TYPE_SPECIAL, &timing_s3_trio32_pci); + else + video_inform(VIDEO_FLAG_TYPE_SPECIAL, &timing_s3_trio32_vlb); + break; + case S3_DIAMOND_STEALTH_SE: + bios_fn = ROM_DIAMOND_STEALTH_SE; + chip = S3_TRIO32; + if (info->flags & DEVICE_PCI) + video_inform(VIDEO_FLAG_TYPE_SPECIAL, &timing_s3_trio32_pci); + else + video_inform(VIDEO_FLAG_TYPE_SPECIAL, &timing_s3_trio32_vlb); + break; + case S3_PHOENIX_TRIO64: + bios_fn = ROM_PHOENIX_TRIO64; + chip = S3_TRIO64; + if (info->flags & DEVICE_PCI) + video_inform(VIDEO_FLAG_TYPE_SPECIAL, &timing_s3_trio64_pci); + else + video_inform(VIDEO_FLAG_TYPE_SPECIAL, &timing_s3_trio64_vlb); + break; + case S3_SPEA_MIRAGE_P64: + bios_fn = ROM_SPEA_MIRAGE_P64; + chip = S3_TRIO64; + video_inform(VIDEO_FLAG_TYPE_SPECIAL, &timing_s3_trio64_vlb); + break; + case S3_PHOENIX_TRIO64_ONBOARD: + bios_fn = NULL; + chip = S3_TRIO64; + if (info->flags & DEVICE_PCI) + video_inform(VIDEO_FLAG_TYPE_SPECIAL, &timing_s3_trio64_pci); + else + video_inform(VIDEO_FLAG_TYPE_SPECIAL, &timing_s3_trio64_vlb); + break; + case S3_PHOENIX_TRIO64VPLUS: + bios_fn = ROM_PHOENIX_TRIO64VPLUS; + chip = S3_TRIO64V; + if (info->flags & DEVICE_PCI) + video_inform(VIDEO_FLAG_TYPE_SPECIAL, &timing_s3_trio64_pci); + else + video_inform(VIDEO_FLAG_TYPE_SPECIAL, &timing_s3_trio64_vlb); + break; + case S3_PHOENIX_TRIO64VPLUS_ONBOARD: + bios_fn = NULL; + chip = S3_TRIO64V; + if (info->flags & DEVICE_PCI) + video_inform(VIDEO_FLAG_TYPE_SPECIAL, &timing_s3_trio64_pci); + else + video_inform(VIDEO_FLAG_TYPE_SPECIAL, &timing_s3_trio64_vlb); + break; + case S3_DIAMOND_STEALTH64_764: + bios_fn = ROM_DIAMOND_STEALTH64_764; + chip = S3_TRIO64; + if (info->flags & DEVICE_PCI) + video_inform(VIDEO_FLAG_TYPE_SPECIAL, &timing_s3_stealth64_pci); + else + video_inform(VIDEO_FLAG_TYPE_SPECIAL, &timing_s3_stealth64_vlb); + break; + case S3_NUMBER9_9FX: + bios_fn = ROM_NUMBER9_9FX; + chip = S3_TRIO64; + if (info->flags & DEVICE_PCI) + video_inform(VIDEO_FLAG_TYPE_SPECIAL, &timing_s3_trio64_pci); + else + video_inform(VIDEO_FLAG_TYPE_SPECIAL, &timing_s3_trio64_vlb); + break; + case S3_TRIO64V2_DX: + bios_fn = ROM_TRIO64V2_DX_VBE20; + chip = S3_TRIO64V2; + video_inform(VIDEO_FLAG_TYPE_SPECIAL, &timing_s3_trio64_pci); + break; + case S3_TRIO64V2_DX_ONBOARD: + bios_fn = NULL; + chip = S3_TRIO64V2; + video_inform(VIDEO_FLAG_TYPE_SPECIAL, &timing_s3_trio64_pci); + break; + default: + free(s3); + return NULL; + } - memset(s3, 0, sizeof(s3_t)); + memset(s3, 0, sizeof(s3_t)); - vram = device_get_config_int("memory"); - - if (vram) - vram_size = vram << 20; - else - vram_size = 512 << 10; - s3->vram_mask = vram_size - 1; - s3->vram = vram; + vram = device_get_config_int("memory"); - s3->has_bios = (bios_fn != NULL); - if (s3->has_bios) { - rom_init(&s3->bios_rom, (char *) bios_fn, 0xc0000, 0x8000, 0x7fff, 0, MEM_MAPPING_EXTERNAL); - if (info->flags & DEVICE_PCI) - mem_mapping_disable(&s3->bios_rom.mapping); - } + if (vram) + vram_size = vram << 20; + else + vram_size = 512 << 10; + s3->vram_mask = vram_size - 1; + s3->vram = vram; - s3->pci = !!(info->flags & DEVICE_PCI); - s3->vlb = !!(info->flags & DEVICE_VLB); - - mem_mapping_add(&s3->linear_mapping, 0, 0, - svga_read_linear, svga_readw_linear, svga_readl_linear, - svga_write_linear, svga_writew_linear, svga_writel_linear, - NULL, MEM_MAPPING_EXTERNAL, &s3->svga); - /*It's hardcoded to 0xa0000 before the Trio64V+ and expects so*/ - if (chip >= S3_TRIO64V) - mem_mapping_add(&s3->mmio_mapping, 0, 0, - s3_accel_read, s3_accel_read_w, s3_accel_read_l, - s3_accel_write, s3_accel_write_w, s3_accel_write_l, - NULL, MEM_MAPPING_EXTERNAL, s3); - else - mem_mapping_add(&s3->mmio_mapping, 0xa0000, 0x10000, - s3_accel_read, s3_accel_read_w, s3_accel_read_l, - s3_accel_write, s3_accel_write_w, s3_accel_write_l, - NULL, MEM_MAPPING_EXTERNAL, s3); - mem_mapping_add(&s3->new_mmio_mapping, 0, 0, - s3_accel_read, s3_accel_read_w, s3_accel_read_l, - s3_accel_write, s3_accel_write_w, s3_accel_write_l, - NULL, MEM_MAPPING_EXTERNAL, s3); - mem_mapping_disable(&s3->mmio_mapping); - mem_mapping_disable(&s3->new_mmio_mapping); - - if (chip == S3_VISION964 || chip == S3_VISION968) - svga_init(info, &s3->svga, s3, vram_size, - s3_recalctimings, - s3_in, s3_out, - NULL, - NULL); - else { - if (chip >= S3_TRIO64V) { - svga_init(info, svga, s3, vram_size, - s3_trio64v_recalctimings, - s3_in, s3_out, - s3_hwcursor_draw, - s3_trio64v_overlay_draw); - } else { - svga_init(info, svga, s3, vram_size, - s3_recalctimings, - s3_in, s3_out, - s3_hwcursor_draw, - NULL); - } - } + s3->has_bios = (bios_fn != NULL); + if (s3->has_bios) { + rom_init(&s3->bios_rom, bios_fn, 0xc0000, 0x8000, 0x7fff, 0, MEM_MAPPING_EXTERNAL); + if (info->flags & DEVICE_PCI) + mem_mapping_disable(&s3->bios_rom.mapping); + } - svga->hwcursor.ysize = 64; + s3->pci = !!(info->flags & DEVICE_PCI); + s3->vlb = !!(info->flags & DEVICE_VLB); - if (chip == S3_VISION964 && info->local != S3_ELSAWIN2KPROX_964) - svga->dac_hwcursor_draw = bt48x_hwcursor_draw; - else if ((chip == S3_VISION964 && info->local == S3_ELSAWIN2KPROX_964) || (chip == S3_VISION968 && (info->local == S3_ELSAWIN2KPROX || - info->local == S3_PHOENIX_VISION968 || info->local == S3_NUMBER9_9FX_771))) - svga->dac_hwcursor_draw = ibm_rgb528_hwcursor_draw; - else if (chip == S3_VISION968 && (info->local == S3_SPEA_MERCURY_P64V || info->local == S3_MIROVIDEO40SV_ERGO_968)) - svga->dac_hwcursor_draw = tvp3026_hwcursor_draw; + mem_mapping_add(&s3->linear_mapping, 0, 0, + svga_read_linear, svga_readw_linear, svga_readl_linear, + svga_write_linear, svga_writew_linear, svga_writel_linear, + NULL, MEM_MAPPING_EXTERNAL, &s3->svga); + /*It's hardcoded to 0xa0000 before the Trio64V+ and expects so*/ + if (chip >= S3_TRIO64V) + mem_mapping_add(&s3->mmio_mapping, 0, 0, + s3_accel_read, s3_accel_read_w, s3_accel_read_l, + s3_accel_write, s3_accel_write_w, s3_accel_write_l, + NULL, MEM_MAPPING_EXTERNAL, s3); + else + mem_mapping_add(&s3->mmio_mapping, 0xa0000, 0x10000, + s3_accel_read, s3_accel_read_w, s3_accel_read_l, + s3_accel_write, s3_accel_write_w, s3_accel_write_l, + NULL, MEM_MAPPING_EXTERNAL, s3); + mem_mapping_add(&s3->new_mmio_mapping, 0, 0, + s3_accel_read, s3_accel_read_w, s3_accel_read_l, + s3_accel_write, s3_accel_write_w, s3_accel_write_l, + NULL, MEM_MAPPING_EXTERNAL, s3); + mem_mapping_disable(&s3->mmio_mapping); + mem_mapping_disable(&s3->new_mmio_mapping); - if (chip >= S3_VISION964) { - switch (vram) { - case 0: /* 512 kB */ - svga->vram_mask = (1 << 19) - 1; - svga->vram_max = 2 << 20; - break; - case 1: /* 1 MB */ - /* VRAM in first MB, mirrored in 2nd MB, 3rd and 4th MBs are open bus. + if (chip == S3_VISION964 || chip == S3_VISION968) + svga_init(info, &s3->svga, s3, vram_size, + s3_recalctimings, + s3_in, s3_out, + NULL, + NULL); + else { + if (chip >= S3_TRIO64V) { + svga_init(info, svga, s3, vram_size, + s3_trio64v_recalctimings, + s3_in, s3_out, + s3_hwcursor_draw, + s3_trio64v_overlay_draw); + } else { + svga_init(info, svga, s3, vram_size, + s3_recalctimings, + s3_in, s3_out, + s3_hwcursor_draw, + NULL); + } + } - 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; - break; - case 2: - default: /*2 MB */ - /* VRAM in first 2 MB, 3rd and 4th MBs are open bus. */ - svga->vram_mask = (2 << 20) - 1; - svga->vram_max = 2 << 20; - break; - case 4: /*4MB*/ - svga->vram_mask = (4 << 20) - 1; - svga->vram_max = 4 << 20; - break; - case 8: /*8MB*/ - svga->vram_mask = (8 << 20) - 1; - svga->vram_max = 8 << 20; - break; - } - } - - if (s3->pci) - svga->crtc[0x36] = 2 | (3 << 2) | (1 << 4); - else if (s3->vlb) - svga->crtc[0x36] = 1 | (3 << 2) | (1 << 4); - else - svga->crtc[0x36] = 3 | (1 << 4); - - if (chip >= S3_86C928) - svga->crtc[0x36] |= (vram_sizes[vram] << 5); - else { - svga->crtc[0x36] |= ((vram == 1) ? 0x00 : 0x20) | 0x98; - svga->crtc[0x41] = (vram == 1) ? 0x10 : 0x00; - } - - svga->crtc[0x37] = 1 | (7 << 5); - - if (chip >= S3_86C928) - svga->crtc[0x37] |= 0x04; + svga->hwcursor.cur_ysize = 64; - svga->vblank_start = s3_vblank_start; + if (chip == S3_VISION964 && info->local != S3_ELSAWIN2KPROX_964) + svga->dac_hwcursor_draw = bt48x_hwcursor_draw; + else if ((chip == S3_VISION964 && info->local == S3_ELSAWIN2KPROX_964) || (chip == S3_VISION968 && (info->local == S3_ELSAWIN2KPROX || info->local == S3_PHOENIX_VISION968 || info->local == S3_NUMBER9_9FX_771))) + svga->dac_hwcursor_draw = ibm_rgb528_hwcursor_draw; + else if (chip == S3_VISION968 && (info->local == S3_SPEA_MERCURY_P64V || info->local == S3_MIROVIDEO40SV_ERGO_968)) + svga->dac_hwcursor_draw = tvp3026_hwcursor_draw; - s3_io_set(s3); - - s3->pci_regs[PCI_REG_COMMAND] = 7; + if (chip >= S3_VISION964) { + switch (vram) { + case 0: /* 512 kB */ + svga->vram_mask = (1 << 19) - 1; + 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. - s3->pci_regs[0x30] = 0x00; - s3->pci_regs[0x32] = 0x0c; - s3->pci_regs[0x33] = 0x00; + 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 = 1 << 20; + break; + case 2: + default: /*2 MB */ + /* VRAM in first 2 MB, 3rd and 4th MBs are open bus. */ + svga->vram_mask = (2 << 20) - 1; + svga->vram_max = 2 << 20; + break; + case 4: /*4MB*/ + svga->vram_mask = (4 << 20) - 1; + svga->vram_max = 4 << 20; + break; + case 8: /*8MB*/ + svga->vram_mask = (8 << 20) - 1; + svga->vram_max = 8 << 20; + break; + } + } - s3->chip = chip; + if (s3->pci) + svga->crtc[0x36] = 2 | (3 << 2) | (1 << 4); + else if (s3->vlb) + svga->crtc[0x36] = 1 | (3 << 2) | (1 << 4); + else + svga->crtc[0x36] = 3 | (1 << 4); - s3->int_line = 0; - - s3->card_type = info->local; + if (chip >= S3_86C928) + svga->crtc[0x36] |= (vram_sizes[vram] << 5); + else { + svga->crtc[0x36] |= ((vram == 1) ? 0x00 : 0x20) | 0x98; + svga->crtc[0x41] = (vram == 1) ? 0x10 : 0x00; + } - switch(s3->card_type) { - case S3_ORCHID_86C911: - case S3_DIAMOND_STEALTH_VRAM: - svga->decode_mask = (1 << 20) - 1; - stepping = 0x81; /*86C911*/ - s3->id = stepping; - s3->id_ext = stepping; - s3->id_ext_pci = 0; - s3->packed_mmio = 0; - s3->width = 1024; - - svga->ramdac = device_add(&sc11483_ramdac_device); - svga->clock_gen = device_add(&av9194_device); - svga->getclock = av9194_getclock; - break; + svga->crtc[0x37] = 1 | (7 << 5); - case S3_AMI_86C924: - svga->decode_mask = (1 << 20) - 1; - stepping = 0x82; /*86C911A/86C924*/ - s3->id = stepping; - s3->id_ext = stepping; - s3->id_ext_pci = 0; - s3->packed_mmio = 0; - s3->width = 1024; - - svga->ramdac = device_add(&sc11487_ramdac_device); - svga->clock_gen = device_add(&ics2494an_305_device); - svga->getclock = ics2494_getclock; - break; + if (chip >= S3_86C928) + svga->crtc[0x37] |= 0x04; - case S3_MIROCRYSTAL8S_805: - case S3_MIROCRYSTAL10SD_805: - svga->decode_mask = (2 << 20) - 1; - stepping = 0xa0; /*86C801/86C805*/ - s3->id = stepping; - s3->id_ext = stepping; - s3->id_ext_pci = 0; - s3->packed_mmio = 0; - svga->crtc[0x5a] = 0x0a; - - svga->ramdac = device_add(&gendac_ramdac_device); - svga->clock_gen = svga->ramdac; - svga->getclock = sdac_getclock; - break; + svga->vblank_start = s3_vblank_start; - case S3_SPEA_MIRAGE_86C801: - case S3_SPEA_MIRAGE_86C805: - svga->decode_mask = (2 << 20) - 1; - stepping = 0xa0; /*86C801/86C805*/ - s3->id = stepping; - s3->id_ext = stepping; - s3->id_ext_pci = 0; - s3->packed_mmio = 0; - svga->crtc[0x5a] = 0x0a; - - svga->ramdac = device_add(&att490_ramdac_device); - svga->clock_gen = device_add(&av9194_device); - svga->getclock = av9194_getclock; - break; + s3_io_set(s3); - case S3_PHOENIX_86C801: - case S3_PHOENIX_86C805: - svga->decode_mask = (2 << 20) - 1; - stepping = 0xa0; /*86C801/86C805*/ - s3->id = stepping; - s3->id_ext = stepping; - s3->id_ext_pci = 0; - s3->packed_mmio = 0; - svga->crtc[0x5a] = 0x0a; - - svga->ramdac = device_add(&att492_ramdac_device); - svga->clock_gen = device_add(&av9194_device); - svga->getclock = av9194_getclock; - break; - - case S3_METHEUS_86C928: - svga->decode_mask = (4 << 20) - 1; - stepping = 0x91; /*86C928*/ - s3->id = stepping; - s3->id_ext = stepping; - s3->id_ext_pci = 0; - s3->packed_mmio = 0; - svga->crtc[0x5a] = 0x0a; - svga->ramdac = device_add(&bt485_ramdac_device); - svga->clock_gen = device_add(&icd2061_device); - svga->getclock = icd2061_getclock; - break; + s3->pci_regs[PCI_REG_COMMAND] = 7; - case S3_SPEA_MERCURY_LITE_PCI: - svga->decode_mask = (4 << 20) - 1; - stepping = 0xb0; /*86C928PCI*/ - s3->id = stepping; - s3->id_ext = stepping; - s3->id_ext_pci = stepping; - s3->packed_mmio = 0; - svga->crtc[0x5a] = 0x0a; - svga->ramdac = device_add(&sc1502x_ramdac_device); - svga->clock_gen = device_add(&av9194_device); - svga->getclock = av9194_getclock; - break; - - case S3_PARADISE_BAHAMAS64: - case S3_PHOENIX_VISION864: - case S3_MIROCRYSTAL20SD_864: /*BIOS 3.xx has a SDAC ramdac.*/ - svga->decode_mask = (8 << 20) - 1; - if (info->local == S3_PARADISE_BAHAMAS64 || info->local == S3_MIROCRYSTAL20SD_864) - stepping = 0xc0; /*Vision864*/ - else - stepping = 0xc1; /*Vision864P*/ - s3->id = stepping; - s3->id_ext = s3->id_ext_pci = stepping; - s3->packed_mmio = 0; - svga->crtc[0x5a] = 0x0a; - svga->ramdac = device_add(&sdac_ramdac_device); - svga->clock_gen = svga->ramdac; - svga->getclock = sdac_getclock; - break; + s3->pci_regs[0x30] = 0x00; + s3->pci_regs[0x32] = 0x0c; + s3->pci_regs[0x33] = 0x00; - case S3_DIAMOND_STEALTH64_964: - case S3_ELSAWIN2KPROX_964: - case S3_MIROCRYSTAL20SV_964: - svga->decode_mask = (8 << 20) - 1; - stepping = 0xd0; /*Vision964*/ - s3->id = stepping; - s3->id_ext = s3->id_ext_pci = stepping; - s3->packed_mmio = 1; - svga->crtc[0x5a] = 0x0a; + s3->chip = chip; - if (info->local == S3_ELSAWIN2KPROX_964) - svga->ramdac = device_add(&ibm_rgb528_ramdac_device); - else - svga->ramdac = device_add(&bt485_ramdac_device); + s3->int_line = 0; - svga->clock_gen = device_add(&icd2061_device); - svga->getclock = icd2061_getclock; - break; + s3->card_type = info->local; - case S3_ELSAWIN2KPROX: - case S3_SPEA_MERCURY_P64V: - case S3_MIROVIDEO40SV_ERGO_968: - case S3_NUMBER9_9FX_771: - case S3_PHOENIX_VISION968: - svga->decode_mask = (8 << 20) - 1; - s3->id = 0xe1; /*Vision968*/ - s3->id_ext = s3->id_ext_pci = 0xf0; - s3->packed_mmio = 1; - if (s3->pci) { - svga->crtc[0x53] = 0x18; - svga->crtc[0x58] = 0x10; - svga->crtc[0x59] = 0x70; - svga->crtc[0x5a] = 0x00; - svga->crtc[0x6c] = 1; - } else { - svga->crtc[0x53] = 0x00; - svga->crtc[0x59] = 0x00; - svga->crtc[0x5a] = 0x0a; - } + svga->force_old_addr = 1; - if (info->local == S3_ELSAWIN2KPROX || info->local == S3_PHOENIX_VISION968 || - info->local == S3_NUMBER9_9FX_771) { - svga->ramdac = device_add(&ibm_rgb528_ramdac_device); - svga->clock_gen = device_add(&icd2061_device); - svga->getclock = icd2061_getclock; - } else { - svga->ramdac = device_add(&tvp3026_ramdac_device); - svga->clock_gen = svga->ramdac; - svga->getclock = tvp3026_getclock; - } - break; + switch (s3->card_type) { + case S3_ORCHID_86C911: + case S3_DIAMOND_STEALTH_VRAM: + svga->decode_mask = (1 << 20) - 1; + stepping = 0x81; /*86C911*/ + s3->id = stepping; + s3->id_ext = stepping; + s3->id_ext_pci = 0; + s3->packed_mmio = 0; + s3->width = 1024; - case S3_NUMBER9_9FX_531: - case S3_PHOENIX_VISION868: - svga->decode_mask = (8 << 20) - 1; - s3->id = 0xe1; /*Vision868*/ - s3->id_ext = 0x90; - s3->id_ext_pci = 0x80; - s3->packed_mmio = 1; - if (s3->pci) { - svga->crtc[0x53] = 0x18; - svga->crtc[0x58] = 0x10; - svga->crtc[0x59] = 0x70; - svga->crtc[0x5a] = 0x00; - svga->crtc[0x6c] = 1; - } else { - svga->crtc[0x53] = 0x00; - svga->crtc[0x59] = 0x00; - svga->crtc[0x5a] = 0x0a; - } - - if (info->local == S3_NUMBER9_9FX_531) { - svga->ramdac = device_add(&att498_ramdac_device); - svga->clock_gen = device_add(&icd2061_device); - svga->getclock = icd2061_getclock; - } else { - svga->ramdac = device_add(&sdac_ramdac_device); - svga->clock_gen = svga->ramdac; - svga->getclock = sdac_getclock; - } - break; + svga->ramdac = device_add(&sc11483_ramdac_device); + svga->clock_gen = device_add(&av9194_device); + svga->getclock = av9194_getclock; + break; - case S3_PHOENIX_TRIO32: - case S3_DIAMOND_STEALTH_SE: - svga->decode_mask = (4 << 20) - 1; - s3->id = 0xe1; /*Trio32*/ - s3->id_ext = 0x10; - s3->id_ext_pci = 0x11; - s3->packed_mmio = 1; + case S3_AMI_86C924: + svga->decode_mask = (1 << 20) - 1; + stepping = 0x82; /*86C911A/86C924*/ + s3->id = stepping; + s3->id_ext = stepping; + s3->id_ext_pci = 0; + s3->packed_mmio = 0; + s3->width = 1024; - svga->clock_gen = s3; - svga->getclock = s3_trio64_getclock; - break; + svga->ramdac = device_add(&sc11487_ramdac_device); + svga->clock_gen = device_add(&ics2494an_305_device); + svga->getclock = ics2494_getclock; + break; - case S3_PHOENIX_TRIO64: - case S3_PHOENIX_TRIO64_ONBOARD: - case S3_PHOENIX_TRIO64VPLUS: - case S3_PHOENIX_TRIO64VPLUS_ONBOARD: - case S3_DIAMOND_STEALTH64_764: - case S3_SPEA_MIRAGE_P64: - if (device_get_config_int("memory") == 1) - svga->vram_max = 1 << 20; /* Phoenix BIOS does not expect VRAM to be mirrored. */ - /* Fall over. */ + case S3_MIROCRYSTAL8S_805: + case S3_MIROCRYSTAL10SD_805: + svga->decode_mask = (2 << 20) - 1; + stepping = 0xa0; /*86C801/86C805*/ + s3->id = stepping; + s3->id_ext = stepping; + s3->id_ext_pci = 0; + s3->packed_mmio = 0; + svga->crtc[0x5a] = 0x0a; - case S3_NUMBER9_9FX: - svga->decode_mask = (4 << 20) - 1; - s3->id = 0xe1; /*Trio64*/ - s3->id_ext = s3->id_ext_pci = 0x11; - s3->packed_mmio = 1; + svga->ramdac = device_add(&gendac_ramdac_device); + svga->clock_gen = svga->ramdac; + svga->getclock = sdac_getclock; + break; - if (info->local == S3_PHOENIX_TRIO64VPLUS || info->local == S3_PHOENIX_TRIO64VPLUS_ONBOARD) { - svga->crtc[0x53] = 0x08; - } + case S3_SPEA_MIRAGE_86C801: + case S3_SPEA_MIRAGE_86C805: + svga->decode_mask = (2 << 20) - 1; + stepping = 0xa0; /*86C801/86C805*/ + s3->id = stepping; + s3->id_ext = stepping; + s3->id_ext_pci = 0; + s3->packed_mmio = 0; + svga->crtc[0x5a] = 0x0a; - svga->clock_gen = s3; - svga->getclock = s3_trio64_getclock; - break; + svga->ramdac = device_add(&att490_ramdac_device); + svga->clock_gen = device_add(&av9194_device); + svga->getclock = av9194_getclock; + break; - case S3_TRIO64V2_DX: - case S3_TRIO64V2_DX_ONBOARD: - svga->decode_mask = (4 << 20) - 1; - s3->id = 0xe1; /*Trio64V2*/ - s3->id_ext = s3->id_ext_pci = 0x01; - s3->packed_mmio = 1; - svga->crtc[0x53] = 0x08; - svga->crtc[0x59] = 0x70; - svga->crtc[0x5a] = 0x00; - svga->crtc[0x6c] = 1; - s3->pci_regs[0x05] = 0; - s3->pci_regs[0x06] = 0; - s3->pci_regs[0x07] = 2; - s3->pci_regs[0x3d] = 1; - s3->pci_regs[0x3e] = 4; - s3->pci_regs[0x3f] = 0xff; + case S3_86C805_ONBOARD: + svga->decode_mask = (2 << 20) - 1; + stepping = 0xa0; /*86C801/86C805*/ + s3->id = stepping; + s3->id_ext = stepping; + s3->id_ext_pci = 0; + s3->packed_mmio = 0; + svga->crtc[0x5a] = 0x0a; - svga->clock_gen = s3; - svga->getclock = s3_trio64_getclock; - break; + svga->ramdac = device_add(&att490_ramdac_device); + svga->clock_gen = device_add(&av9194_device); + svga->getclock = av9194_getclock; + break; - default: - return NULL; - } - - svga->packed_chain4 = 1; + case S3_PHOENIX_86C801: + case S3_PHOENIX_86C805: + svga->decode_mask = (2 << 20) - 1; + stepping = 0xa0; /*86C801/86C805*/ + s3->id = stepping; + s3->id_ext = stepping; + s3->id_ext_pci = 0; + s3->packed_mmio = 0; + svga->crtc[0x5a] = 0x0a; - if (s3->pci) - s3->card = pci_add_card(PCI_ADD_VIDEO, s3_pci_read, s3_pci_write, s3); + svga->ramdac = device_add(&att492_ramdac_device); + svga->clock_gen = device_add(&av9194_device); + svga->getclock = av9194_getclock; + break; - s3->i2c = i2c_gpio_init("ddc_s3"); - s3->ddc = ddc_init(i2c_gpio_get_bus(s3->i2c)); + case S3_METHEUS_86C928: + svga->decode_mask = (4 << 20) - 1; + stepping = 0x91; /*86C928*/ + s3->id = stepping; + s3->id_ext = stepping; + s3->id_ext_pci = 0; + s3->packed_mmio = 0; + svga->crtc[0x5a] = 0x0a; + svga->ramdac = device_add(&bt485_ramdac_device); + svga->clock_gen = device_add(&icd2061_device); + svga->getclock = icd2061_getclock; + break; - s3->wake_fifo_thread = thread_create_event(); - s3->fifo_not_full_event = thread_create_event(); - s3->fifo_thread_run = 1; - s3->fifo_thread = thread_create(fifo_thread, s3); + case S3_SPEA_MERCURY_LITE_PCI: + svga->decode_mask = (4 << 20) - 1; + stepping = 0xb0; /*86C928PCI*/ + s3->id = stepping; + s3->id_ext = stepping; + s3->id_ext_pci = stepping; + s3->packed_mmio = 0; + svga->crtc[0x5a] = 0x0a; + svga->ramdac = device_add(&sc1502x_ramdac_device); + svga->clock_gen = device_add(&av9194_device); + svga->getclock = av9194_getclock; + break; - return s3; + case S3_PARADISE_BAHAMAS64: + case S3_PHOENIX_VISION864: + case S3_MIROCRYSTAL20SD_864: /*BIOS 3.xx has a SDAC ramdac.*/ + svga->decode_mask = (8 << 20) - 1; + if (info->local == S3_PARADISE_BAHAMAS64 || info->local == S3_MIROCRYSTAL20SD_864) + stepping = 0xc0; /*Vision864*/ + else + stepping = 0xc1; /*Vision864P*/ + s3->id = stepping; + s3->id_ext = s3->id_ext_pci = stepping; + s3->packed_mmio = 0; + svga->crtc[0x5a] = 0x0a; + svga->ramdac = device_add(&sdac_ramdac_device); + svga->clock_gen = svga->ramdac; + svga->getclock = sdac_getclock; + break; + + case S3_DIAMOND_STEALTH64_964: + case S3_ELSAWIN2KPROX_964: + case S3_MIROCRYSTAL20SV_964: + svga->decode_mask = (8 << 20) - 1; + stepping = 0xd0; /*Vision964*/ + s3->id = stepping; + s3->id_ext = s3->id_ext_pci = stepping; + s3->packed_mmio = 1; + svga->crtc[0x5a] = 0x0a; + + if (info->local == S3_ELSAWIN2KPROX_964) + svga->ramdac = device_add(&ibm_rgb528_ramdac_device); + else + svga->ramdac = device_add(&bt485_ramdac_device); + + svga->clock_gen = device_add(&icd2061_device); + svga->getclock = icd2061_getclock; + break; + + case S3_ELSAWIN2KPROX: + case S3_SPEA_MERCURY_P64V: + case S3_MIROVIDEO40SV_ERGO_968: + case S3_NUMBER9_9FX_771: + case S3_PHOENIX_VISION968: + svga->decode_mask = (8 << 20) - 1; + s3->id = 0xe1; /*Vision968*/ + s3->id_ext = s3->id_ext_pci = 0xf0; + s3->packed_mmio = 1; + if (s3->pci) { + svga->crtc[0x53] = 0x18; + svga->crtc[0x58] = 0x10; + svga->crtc[0x59] = 0x70; + svga->crtc[0x5a] = 0x00; + svga->crtc[0x6c] = 1; + } else { + svga->crtc[0x53] = 0x00; + svga->crtc[0x59] = 0x00; + svga->crtc[0x5a] = 0x0a; + } + + if (info->local == S3_ELSAWIN2KPROX || info->local == S3_PHOENIX_VISION968 || info->local == S3_NUMBER9_9FX_771) { + svga->ramdac = device_add(&ibm_rgb528_ramdac_device); + svga->clock_gen = device_add(&icd2061_device); + svga->getclock = icd2061_getclock; + } else { + svga->ramdac = device_add(&tvp3026_ramdac_device); + svga->clock_gen = svga->ramdac; + svga->getclock = tvp3026_getclock; + } + break; + + case S3_NUMBER9_9FX_531: + case S3_PHOENIX_VISION868: + svga->decode_mask = (8 << 20) - 1; + s3->id = 0xe1; /*Vision868*/ + s3->id_ext = 0x90; + s3->id_ext_pci = 0x80; + s3->packed_mmio = 1; + if (s3->pci) { + svga->crtc[0x53] = 0x18; + svga->crtc[0x58] = 0x10; + svga->crtc[0x59] = 0x70; + svga->crtc[0x5a] = 0x00; + svga->crtc[0x6c] = 1; + } else { + svga->crtc[0x53] = 0x00; + svga->crtc[0x59] = 0x00; + svga->crtc[0x5a] = 0x0a; + } + + if (info->local == S3_NUMBER9_9FX_531) { + svga->ramdac = device_add(&att498_ramdac_device); + svga->clock_gen = device_add(&icd2061_device); + svga->getclock = icd2061_getclock; + } else { + svga->ramdac = device_add(&sdac_ramdac_device); + svga->clock_gen = svga->ramdac; + svga->getclock = sdac_getclock; + } + break; + + case S3_PHOENIX_TRIO32: + case S3_DIAMOND_STEALTH_SE: + svga->decode_mask = (4 << 20) - 1; + s3->id = 0xe1; /*Trio32*/ + s3->id_ext = 0x10; + s3->id_ext_pci = 0x11; + s3->packed_mmio = 1; + + svga->clock_gen = s3; + svga->getclock = s3_trio64_getclock; + break; + + case S3_PHOENIX_TRIO64: + case S3_PHOENIX_TRIO64_ONBOARD: + case S3_PHOENIX_TRIO64VPLUS: + case S3_PHOENIX_TRIO64VPLUS_ONBOARD: + case S3_DIAMOND_STEALTH64_764: + case S3_SPEA_MIRAGE_P64: + if (device_get_config_int("memory") == 1) + svga->vram_max = 1 << 20; /* Phoenix BIOS does not expect VRAM to be mirrored. */ + /* Fall over. */ + fallthrough; + case S3_NUMBER9_9FX: + svga->decode_mask = (4 << 20) - 1; + s3->id = 0xe1; /*Trio64*/ + s3->id_ext = s3->id_ext_pci = 0x11; + s3->packed_mmio = 1; + + if (info->local == S3_PHOENIX_TRIO64VPLUS || info->local == S3_PHOENIX_TRIO64VPLUS_ONBOARD) { + svga->crtc[0x53] = 0x08; + } + + svga->clock_gen = s3; + svga->getclock = s3_trio64_getclock; + break; + + case S3_TRIO64V2_DX: + case S3_TRIO64V2_DX_ONBOARD: + svga->decode_mask = (4 << 20) - 1; + s3->id = 0xe1; /*Trio64V2*/ + s3->id_ext = s3->id_ext_pci = 0x01; + s3->packed_mmio = 1; + svga->crtc[0x53] = 0x08; + svga->crtc[0x59] = 0x70; + svga->crtc[0x5a] = 0x00; + svga->crtc[0x6c] = 1; + s3->pci_regs[0x05] = 0; + s3->pci_regs[0x06] = 0; + s3->pci_regs[0x07] = 2; + s3->pci_regs[0x3d] = 1; + s3->pci_regs[0x3e] = 4; + s3->pci_regs[0x3f] = 0xff; + + svga->clock_gen = s3; + svga->getclock = s3_trio64_getclock; + break; + + default: + return NULL; + } + + if (s3->pci) { + if (bios_fn == NULL) + pci_add_card(PCI_ADD_VIDEO, s3_pci_read, s3_pci_write, s3, &s3->pci_slot); + else + pci_add_card(PCI_ADD_NORMAL, s3_pci_read, s3_pci_write, s3, &s3->pci_slot); + } + + s3->i2c = i2c_gpio_init("ddc_s3"); + s3->ddc = ddc_init(i2c_gpio_get_bus(s3->i2c)); + + s3->wake_fifo_thread = thread_create_event(); + s3->fifo_not_full_event = thread_create_event(); + s3->fifo_thread_run = 1; + s3->fifo_thread = thread_create(fifo_thread, s3); + + return s3; } -static int s3_orchid_86c911_available(void) +static int +s3_orchid_86c911_available(void) { - return rom_present(ROM_ORCHID_86C911); + return rom_present(ROM_ORCHID_86C911); } -static int s3_diamond_stealth_vram_available(void) +static int +s3_diamond_stealth_vram_available(void) { - return rom_present(ROM_DIAMOND_STEALTH_VRAM); + return rom_present(ROM_DIAMOND_STEALTH_VRAM); } -static int s3_ami_86c924_available(void) +static int +s3_ami_86c924_available(void) { - return rom_present(ROM_AMI_86C924); + return rom_present(ROM_AMI_86C924); } -static int s3_spea_mirage_86c801_available(void) +static int +s3_spea_mirage_86c801_available(void) { - return rom_present(ROM_SPEA_MIRAGE_86C801); + return rom_present(ROM_SPEA_MIRAGE_86C801); } -static int s3_spea_mirage_86c805_available(void) +static int +s3_spea_mirage_86c805_available(void) { - return rom_present(ROM_SPEA_MIRAGE_86C805); + return rom_present(ROM_SPEA_MIRAGE_86C805); } -static int s3_phoenix_86c80x_available(void) +static int +s3_phoenix_86c80x_available(void) { - return rom_present(ROM_PHOENIX_86C80X); + return rom_present(ROM_PHOENIX_86C80X); } -static int s3_mirocrystal_8s_805_available(void) +static int +s3_mirocrystal_8s_805_available(void) { - return rom_present(ROM_MIROCRYSTAL8S_805); + return rom_present(ROM_MIROCRYSTAL8S_805); } -static int s3_mirocrystal_10sd_805_available(void) +static int +s3_mirocrystal_10sd_805_available(void) { - return rom_present(ROM_MIROCRYSTAL10SD_805); + return rom_present(ROM_MIROCRYSTAL10SD_805); } -static int s3_metheus_86c928_available(void) +static int +s3_metheus_86c928_available(void) { - return rom_present(ROM_METHEUS_86C928); + return rom_present(ROM_METHEUS_86C928); } -static int s3_spea_mercury_lite_pci_available(void) +static int +s3_spea_mercury_lite_pci_available(void) { - return rom_present(ROM_SPEA_MERCURY_LITE_PCI); + return rom_present(ROM_SPEA_MERCURY_LITE_PCI); } -static int s3_bahamas64_available(void) +static int +s3_bahamas64_available(void) { - return rom_present(ROM_PARADISE_BAHAMAS64); + return rom_present(ROM_PARADISE_BAHAMAS64); } -static int s3_phoenix_vision864_available(void) +static int +s3_phoenix_vision864_available(void) { - return rom_present(ROM_PHOENIX_VISION864); + return rom_present(ROM_PHOENIX_VISION864); } -static int s3_9fx_531_available(void) +static int +s3_9fx_531_available(void) { - return rom_present(ROM_NUMBER9_9FX_531); + return rom_present(ROM_NUMBER9_9FX_531); } -static int s3_phoenix_vision868_available(void) +static int +s3_phoenix_vision868_available(void) { - return rom_present(ROM_PHOENIX_VISION868); + return rom_present(ROM_PHOENIX_VISION868); } -static int s3_mirocrystal_20sv_964_vlb_available(void) +static int +s3_mirocrystal_20sv_964_vlb_available(void) { - return rom_present(ROM_MIROCRYSTAL20SV_964_VLB); + return rom_present(ROM_MIROCRYSTAL20SV_964_VLB); } -static int s3_mirocrystal_20sv_964_pci_available(void) +static int +s3_mirocrystal_20sv_964_pci_available(void) { - return rom_present(ROM_MIROCRYSTAL20SV_964_PCI); + return rom_present(ROM_MIROCRYSTAL20SV_964_PCI); } -static int s3_diamond_stealth64_964_available(void) +static int +s3_diamond_stealth64_964_available(void) { - return rom_present(ROM_DIAMOND_STEALTH64_964); + return rom_present(ROM_DIAMOND_STEALTH64_964); } -static int s3_mirovideo_40sv_ergo_968_pci_available(void) +static int +s3_mirovideo_40sv_ergo_968_pci_available(void) { - return rom_present(ROM_MIROVIDEO40SV_ERGO_968_PCI); + return rom_present(ROM_MIROVIDEO40SV_ERGO_968_PCI); } -static int s3_9fx_771_available(void) +static int +s3_9fx_771_available(void) { - return rom_present(ROM_NUMBER9_9FX_771); + return rom_present(ROM_NUMBER9_9FX_771); } -static int s3_phoenix_vision968_available(void) +static int +s3_phoenix_vision968_available(void) { - return rom_present(ROM_PHOENIX_VISION968); + return rom_present(ROM_PHOENIX_VISION968); } -static int s3_mirocrystal_20sd_864_vlb_available(void) +static int +s3_mirocrystal_20sd_864_vlb_available(void) { - return rom_present(ROM_MIROCRYSTAL20SD_864_VLB); + return rom_present(ROM_MIROCRYSTAL20SD_864_VLB); } -static int s3_spea_mercury_p64v_pci_available(void) +static int +s3_spea_mercury_p64v_pci_available(void) { - return rom_present(ROM_SPEA_MERCURY_P64V); + return rom_present(ROM_SPEA_MERCURY_P64V); } -static int s3_elsa_winner2000_pro_x_964_available(void) +static int +s3_elsa_winner2000_pro_x_964_available(void) { - return rom_present(ROM_ELSAWIN2KPROX_964); + return rom_present(ROM_ELSAWIN2KPROX_964); } -static int s3_elsa_winner2000_pro_x_available(void) +static int +s3_elsa_winner2000_pro_x_available(void) { - return rom_present(ROM_ELSAWIN2KPROX); + return rom_present(ROM_ELSAWIN2KPROX); } -static int s3_phoenix_trio32_available(void) +static int +s3_phoenix_trio32_available(void) { - return rom_present(ROM_PHOENIX_TRIO32); + return rom_present(ROM_PHOENIX_TRIO32); } -static int s3_diamond_stealth_se_available(void) +static int +s3_diamond_stealth_se_available(void) { - return rom_present(ROM_DIAMOND_STEALTH_SE); + return rom_present(ROM_DIAMOND_STEALTH_SE); } -static int s3_9fx_available(void) +static int +s3_9fx_available(void) { - return rom_present(ROM_NUMBER9_9FX); + return rom_present(ROM_NUMBER9_9FX); } -static int s3_spea_mirage_p64_vlb_available(void) +static int +s3_spea_mirage_p64_vlb_available(void) { - return rom_present(ROM_SPEA_MIRAGE_P64); + return rom_present(ROM_SPEA_MIRAGE_P64); } -static int s3_phoenix_trio64_available(void) +static int +s3_phoenix_trio64_available(void) { - return rom_present(ROM_PHOENIX_TRIO64); + return rom_present(ROM_PHOENIX_TRIO64); } -static int s3_phoenix_trio64vplus_available(void) +static int +s3_phoenix_trio64vplus_available(void) { - return rom_present(ROM_PHOENIX_TRIO64VPLUS); + return rom_present(ROM_PHOENIX_TRIO64VPLUS); } -static int s3_diamond_stealth64_764_available(void) +static int +s3_diamond_stealth64_764_available(void) { - return rom_present(ROM_DIAMOND_STEALTH64_764); + return rom_present(ROM_DIAMOND_STEALTH64_764); } -static int s3_trio64v2_dx_available(void) +static int +s3_trio64v2_dx_available(void) { - return rom_present(ROM_TRIO64V2_DX_VBE20); + return rom_present(ROM_TRIO64V2_DX_VBE20); } -static void s3_close(void *p) +static void +s3_close(void *priv) { - s3_t *s3 = (s3_t *)p; + s3_t *s3 = (s3_t *) priv; - s3->fifo_thread_run = 0; - thread_set_event(s3->wake_fifo_thread); - thread_wait(s3->fifo_thread); - thread_destroy_event(s3->fifo_not_full_event); - thread_destroy_event(s3->wake_fifo_thread); + s3->fifo_thread_run = 0; + thread_set_event(s3->wake_fifo_thread); + thread_wait(s3->fifo_thread); + thread_destroy_event(s3->fifo_not_full_event); + thread_destroy_event(s3->wake_fifo_thread); - svga_close(&s3->svga); + svga_close(&s3->svga); - ddc_close(s3->ddc); - i2c_gpio_close(s3->i2c); + ddc_close(s3->ddc); + i2c_gpio_close(s3->i2c); - free(s3); + free(s3); } -static void s3_speed_changed(void *p) +static void +s3_speed_changed(void *priv) { - s3_t *s3 = (s3_t *)p; - - svga_recalctimings(&s3->svga); + s3_t *s3 = (s3_t *) priv; + + svga_recalctimings(&s3->svga); } -static void s3_force_redraw(void *p) +static void +s3_force_redraw(void *priv) { - s3_t *s3 = (s3_t *)p; + s3_t *s3 = (s3_t *) priv; - s3->svga.fullchange = changeframecount; + s3->svga.fullchange = s3->svga.monitor->mon_changeframecount; } -static const device_config_t s3_orchid_86c911_config[] = -{ - { - "memory", "Memory size", CONFIG_SELECTION, "", 1, "", { 0 }, - { - { - "512 KB", 0 - }, - { - "1 MB", 1 - }, - { - "" - } - } - }, - { - "", "", -1 - } +static const device_config_t s3_orchid_86c911_config[] = { + { .name = "memory", + .description = "Memory size", + .type = CONFIG_SELECTION, + .default_int = 1, + .selection = { + { .description = "512 KB", + .value = 0 }, + { .description = "1 MB", + .value = 1 }, + { .description = "" } } }, + { .type = CONFIG_END } }; -static const device_config_t s3_9fx_config[] = -{ - { - "memory", "Memory size", CONFIG_SELECTION, "", 2, "", { 0 }, - { - { - "1 MB", 1 - }, - { - "2 MB", 2 - }, - /*Trio64 also supports 4 MB, however the Number Nine BIOS does not*/ - { - "" - } - } - }, - { - "", "", -1 - } +static const device_config_t s3_9fx_config[] = { + { .name = "memory", + .description = "Memory size", + .type = CONFIG_SELECTION, + .default_int = 2, + .selection = { + { .description = "1 MB", + .value = 1 }, + { .description = "2 MB", + .value = 2 }, + /*Trio64 also supports 4 MB, however the Number Nine BIOS does not*/ + { + .description = "" } } }, + { .type = CONFIG_END } }; - -static const device_config_t s3_phoenix_trio32_config[] = -{ - { - "memory", "Memory size", CONFIG_SELECTION, "", 2, "", { 0 }, - { - { - "512 KB", 0 - }, - { - "1 MB", 1 - }, - { - "2 MB", 2 - }, - { - "" - } - } - }, - { - "", "", -1 - } +static const device_config_t s3_phoenix_trio32_config[] = { + { .name = "memory", + .description = "Memory size", + .type = CONFIG_SELECTION, + .default_int = 2, + .selection = { + { .description = "512 KB", + .value = 0 }, + { .description = "1 MB", + .value = 1 }, + { .description = "2 MB", + .value = 2 }, + { .description = "" } } }, + { .type = CONFIG_END } }; -static const device_config_t s3_standard_config[] = -{ - { - "memory", "Memory size", CONFIG_SELECTION, "", 4, "", { 0 }, - { - { - "1 MB", 1 - }, - { - "2 MB", 2 - }, - { - "4 MB", 4 - }, - { - "" - } - } - }, - { - "", "", -1 - } +static const device_config_t s3_standard_config[] = { + { .name = "memory", + .description = "Memory size", + .type = CONFIG_SELECTION, + .default_int = 4, + .selection = { + { .description = "1 MB", + .value = 1 }, + { .description = "2 MB", + .value = 2 }, + { .description = "4 MB", + .value = 4 }, + { .description = "" } } }, + { .type = CONFIG_END } }; -static const device_config_t s3_968_config[] = -{ - { - "memory", "Memory size", CONFIG_SELECTION, "", 4, "", { 0 }, - { - { - "1 MB", 1 - }, - { - "2 MB", 2 - }, - { - "4 MB", 4 - }, - { - "8 MB", 8 - }, - { - "" - } - } - }, - { - "", "", -1 - } +static const device_config_t s3_968_config[] = { + { .name = "memory", + .description = "Memory size", + .type = CONFIG_SELECTION, + .default_int = 4, + .selection = { + { .description = "1 MB", + .value = 1 }, + { .description = "2 MB", + .value = 2 }, + { .description = "4 MB", + .value = 4 }, + { .description = "8 MB", + .value = 8 }, + { .description = "" } } }, + { .type = CONFIG_END } }; -const device_t s3_orchid_86c911_isa_device = -{ - "S3 86c911 ISA (Orchid Fahrenheit 1280)", - "orchid_s3_911", - DEVICE_AT | DEVICE_ISA, - S3_ORCHID_86C911, - s3_init, - s3_close, - s3_reset, - { s3_orchid_86c911_available }, - s3_speed_changed, - s3_force_redraw, - s3_orchid_86c911_config +const device_t s3_orchid_86c911_isa_device = { + .name = "S3 86c911 ISA (Orchid Fahrenheit 1280)", + .internal_name = "orchid_s3_911", + .flags = DEVICE_AT | DEVICE_ISA, + .local = S3_ORCHID_86C911, + .init = s3_init, + .close = s3_close, + .reset = s3_reset, + { .available = s3_orchid_86c911_available }, + .speed_changed = s3_speed_changed, + .force_redraw = s3_force_redraw, + .config = s3_orchid_86c911_config }; -const device_t s3_diamond_stealth_vram_isa_device = -{ - "S3 86c911 ISA (Diamond Stealth VRAM)", - "stealthvram_isa", - DEVICE_AT | DEVICE_ISA, - S3_DIAMOND_STEALTH_VRAM, - s3_init, - s3_close, - s3_reset, - { s3_diamond_stealth_vram_available }, - s3_speed_changed, - s3_force_redraw, - s3_orchid_86c911_config +const device_t s3_diamond_stealth_vram_isa_device = { + .name = "S3 86c911 ISA (Diamond Stealth VRAM)", + .internal_name = "stealthvram_isa", + .flags = DEVICE_AT | DEVICE_ISA, + .local = S3_DIAMOND_STEALTH_VRAM, + .init = s3_init, + .close = s3_close, + .reset = s3_reset, + { .available = s3_diamond_stealth_vram_available }, + .speed_changed = s3_speed_changed, + .force_redraw = s3_force_redraw, + .config = s3_orchid_86c911_config }; -const device_t s3_ami_86c924_isa_device = -{ - "S3 86c924 ISA (AMI)", - "ami_s3_924", - DEVICE_AT | DEVICE_ISA, - S3_AMI_86C924, - s3_init, - s3_close, - s3_reset, - { s3_ami_86c924_available }, - s3_speed_changed, - s3_force_redraw, - s3_orchid_86c911_config +const device_t s3_ami_86c924_isa_device = { + .name = "S3 86c924 ISA (AMI)", + .internal_name = "ami_s3_924", + .flags = DEVICE_AT | DEVICE_ISA, + .local = S3_AMI_86C924, + .init = s3_init, + .close = s3_close, + .reset = s3_reset, + { .available = s3_ami_86c924_available }, + .speed_changed = s3_speed_changed, + .force_redraw = s3_force_redraw, + .config = s3_orchid_86c911_config }; -const device_t s3_spea_mirage_86c801_isa_device = -{ - "S3 86c801 ISA (SPEA Mirage ISA)", - "px_s3_v7_801_isa", - DEVICE_AT | DEVICE_ISA, - S3_SPEA_MIRAGE_86C801, - s3_init, - s3_close, - s3_reset, - { s3_spea_mirage_86c801_available }, - s3_speed_changed, - s3_force_redraw, - s3_9fx_config +const device_t s3_spea_mirage_86c801_isa_device = { + .name = "S3 86c801 ISA (SPEA Mirage ISA)", + .internal_name = "px_s3_v7_801_isa", + .flags = DEVICE_AT | DEVICE_ISA, + .local = S3_SPEA_MIRAGE_86C801, + .init = s3_init, + .close = s3_close, + .reset = s3_reset, + { .available = s3_spea_mirage_86c801_available }, + .speed_changed = s3_speed_changed, + .force_redraw = s3_force_redraw, + .config = s3_9fx_config }; -const device_t s3_spea_mirage_86c805_vlb_device = -{ - "S3 86c805 VLB (SPEA Mirage VL)", - "px_s3_v7_805_vlb", - DEVICE_VLB, - S3_SPEA_MIRAGE_86C805, - s3_init, - s3_close, - s3_reset, - { s3_spea_mirage_86c805_available }, - s3_speed_changed, - s3_force_redraw, - s3_9fx_config +const device_t s3_86c805_onboard_vlb_device = { + .name = "S3 86c805 VLB On-Board", + .internal_name = "px_s3_805_onboard_vlb", + .flags = DEVICE_VLB, + .local = S3_86C805_ONBOARD, + .init = s3_init, + .close = s3_close, + .reset = s3_reset, + { .available = NULL }, + .speed_changed = s3_speed_changed, + .force_redraw = s3_force_redraw, + .config = s3_9fx_config }; -const device_t s3_mirocrystal_8s_805_vlb_device = -{ - "S3 86c805 VLB (MiroCRYSTAL 8S)", - "mirocrystal8s_vlb", - DEVICE_VLB, - S3_MIROCRYSTAL8S_805, - s3_init, - s3_close, - s3_reset, - { s3_mirocrystal_8s_805_available }, - s3_speed_changed, - s3_force_redraw, - s3_9fx_config +const device_t s3_spea_mirage_86c805_vlb_device = { + .name = "S3 86c805 VLB (SPEA Mirage VL)", + .internal_name = "px_s3_v7_805_vlb", + .flags = DEVICE_VLB, + .local = S3_SPEA_MIRAGE_86C805, + .init = s3_init, + .close = s3_close, + .reset = s3_reset, + { .available = s3_spea_mirage_86c805_available }, + .speed_changed = s3_speed_changed, + .force_redraw = s3_force_redraw, + .config = s3_9fx_config }; - -const device_t s3_mirocrystal_10sd_805_vlb_device = -{ - "S3 86c805 VLB (MiroCRYSTAL 10SD)", - "mirocrystal10sd_vlb", - DEVICE_VLB, - S3_MIROCRYSTAL10SD_805, - s3_init, - s3_close, - s3_reset, - { s3_mirocrystal_10sd_805_available }, - s3_speed_changed, - s3_force_redraw, - s3_9fx_config +const device_t s3_mirocrystal_8s_805_vlb_device = { + .name = "S3 86c805 VLB (MiroCRYSTAL 8S)", + .internal_name = "mirocrystal8s_vlb", + .flags = DEVICE_VLB, + .local = S3_MIROCRYSTAL8S_805, + .init = s3_init, + .close = s3_close, + .reset = s3_reset, + { .available = s3_mirocrystal_8s_805_available }, + .speed_changed = s3_speed_changed, + .force_redraw = s3_force_redraw, + .config = s3_9fx_config }; -const device_t s3_phoenix_86c801_isa_device = -{ - "S3 86c801 ISA (Phoenix)", - "px_86c801_isa", - DEVICE_AT | DEVICE_ISA, - S3_PHOENIX_86C801, - s3_init, - s3_close, - s3_reset, - { s3_phoenix_86c80x_available }, - s3_speed_changed, - s3_force_redraw, - s3_9fx_config +const device_t s3_mirocrystal_10sd_805_vlb_device = { + .name = "S3 86c805 VLB (MiroCRYSTAL 10SD)", + .internal_name = "mirocrystal10sd_vlb", + .flags = DEVICE_VLB, + .local = S3_MIROCRYSTAL10SD_805, + .init = s3_init, + .close = s3_close, + .reset = s3_reset, + { .available = s3_mirocrystal_10sd_805_available }, + .speed_changed = s3_speed_changed, + .force_redraw = s3_force_redraw, + .config = s3_9fx_config }; -const device_t s3_phoenix_86c805_vlb_device = -{ - "S3 86c805 VLB (Phoenix)", - "px_86c805_vlb", - DEVICE_VLB, - S3_PHOENIX_86C805, - s3_init, - s3_close, - s3_reset, - { s3_phoenix_86c80x_available }, - s3_speed_changed, - s3_force_redraw, - s3_9fx_config +const device_t s3_phoenix_86c801_isa_device = { + .name = "S3 86c801 ISA (Phoenix)", + .internal_name = "px_86c801_isa", + .flags = DEVICE_AT | DEVICE_ISA, + .local = S3_PHOENIX_86C801, + .init = s3_init, + .close = s3_close, + .reset = s3_reset, + { .available = s3_phoenix_86c80x_available }, + .speed_changed = s3_speed_changed, + .force_redraw = s3_force_redraw, + .config = s3_9fx_config }; -const device_t s3_metheus_86c928_isa_device = -{ - "S3 86c928 ISA (Metheus Premier 928)", - "metheus928_isa", - DEVICE_AT | DEVICE_ISA, - S3_METHEUS_86C928, - s3_init, - s3_close, - s3_reset, - { s3_metheus_86c928_available }, - s3_speed_changed, - s3_force_redraw, - s3_standard_config +const device_t s3_phoenix_86c805_vlb_device = { + .name = "S3 86c805 VLB (Phoenix)", + .internal_name = "px_86c805_vlb", + .flags = DEVICE_VLB, + .local = S3_PHOENIX_86C805, + .init = s3_init, + .close = s3_close, + .reset = s3_reset, + { .available = s3_phoenix_86c80x_available }, + .speed_changed = s3_speed_changed, + .force_redraw = s3_force_redraw, + .config = s3_9fx_config }; -const device_t s3_metheus_86c928_vlb_device = -{ - "S3 86c928 VLB (Metheus Premier 928)", - "metheus928_vlb", - DEVICE_VLB, - S3_METHEUS_86C928, - s3_init, - s3_close, - s3_reset, - { s3_metheus_86c928_available }, - s3_speed_changed, - s3_force_redraw, - s3_standard_config +const device_t s3_metheus_86c928_isa_device = { + .name = "S3 86c928 ISA (Metheus Premier 928)", + .internal_name = "metheus928_isa", + .flags = DEVICE_AT | DEVICE_ISA, + .local = S3_METHEUS_86C928, + .init = s3_init, + .close = s3_close, + .reset = s3_reset, + { .available = s3_metheus_86c928_available }, + .speed_changed = s3_speed_changed, + .force_redraw = s3_force_redraw, + .config = s3_standard_config }; -const device_t s3_spea_mercury_lite_86c928_pci_device = -{ - "S3 86c928 PCI (SPEA Mercury Lite)", - "spea_mercurylite_pci", - DEVICE_PCI, - S3_SPEA_MERCURY_LITE_PCI, - s3_init, - s3_close, - s3_reset, - { s3_spea_mercury_lite_pci_available }, - s3_speed_changed, - s3_force_redraw, - s3_standard_config +const device_t s3_metheus_86c928_vlb_device = { + .name = "S3 86c928 VLB (Metheus Premier 928)", + .internal_name = "metheus928_vlb", + .flags = DEVICE_VLB, + .local = S3_METHEUS_86C928, + .init = s3_init, + .close = s3_close, + .reset = s3_reset, + { .available = s3_metheus_86c928_available }, + .speed_changed = s3_speed_changed, + .force_redraw = s3_force_redraw, + .config = s3_standard_config }; -const device_t s3_mirocrystal_20sd_864_vlb_device = -{ - "S3 Vision864 VLB (MiroCRYSTAL 20SD)", - "mirocrystal20sd_vlb", - DEVICE_VLB, - S3_MIROCRYSTAL20SD_864, - s3_init, - s3_close, - s3_reset, - { s3_mirocrystal_20sd_864_vlb_available }, - s3_speed_changed, - s3_force_redraw, - s3_9fx_config +const device_t s3_spea_mercury_lite_86c928_pci_device = { + .name = "S3 86c928 PCI (SPEA Mercury Lite)", + .internal_name = "spea_mercurylite_pci", + .flags = DEVICE_PCI, + .local = S3_SPEA_MERCURY_LITE_PCI, + .init = s3_init, + .close = s3_close, + .reset = s3_reset, + { .available = s3_spea_mercury_lite_pci_available }, + .speed_changed = s3_speed_changed, + .force_redraw = s3_force_redraw, + .config = s3_standard_config }; -const device_t s3_bahamas64_vlb_device = -{ - "S3 Vision864 VLB (Paradise Bahamas 64)", - "bahamas64_vlb", - DEVICE_VLB, - S3_PARADISE_BAHAMAS64, - s3_init, - s3_close, - s3_reset, - { s3_bahamas64_available }, - s3_speed_changed, - s3_force_redraw, - s3_9fx_config +const device_t s3_mirocrystal_20sd_864_vlb_device = { + .name = "S3 Vision864 VLB (MiroCRYSTAL 20SD)", + .internal_name = "mirocrystal20sd_vlb", + .flags = DEVICE_VLB, + .local = S3_MIROCRYSTAL20SD_864, + .init = s3_init, + .close = s3_close, + .reset = s3_reset, + { .available = s3_mirocrystal_20sd_864_vlb_available }, + .speed_changed = s3_speed_changed, + .force_redraw = s3_force_redraw, + .config = s3_9fx_config }; -const device_t s3_bahamas64_pci_device = -{ - "S3 Vision864 PCI (Paradise Bahamas 64)", - "bahamas64_pci", - DEVICE_PCI, - S3_PARADISE_BAHAMAS64, - s3_init, - s3_close, - s3_reset, - { s3_bahamas64_available }, - s3_speed_changed, - s3_force_redraw, - s3_9fx_config +const device_t s3_bahamas64_vlb_device = { + .name = "S3 Vision864 VLB (Paradise Bahamas 64)", + .internal_name = "bahamas64_vlb", + .flags = DEVICE_VLB, + .local = S3_PARADISE_BAHAMAS64, + .init = s3_init, + .close = s3_close, + .reset = s3_reset, + { .available = s3_bahamas64_available }, + .speed_changed = s3_speed_changed, + .force_redraw = s3_force_redraw, + .config = s3_9fx_config }; -const device_t s3_mirocrystal_20sv_964_vlb_device = -{ - "S3 Vision964 VLB (MiroCRYSTAL 20SV)", - "mirocrystal20sv_vlb", - DEVICE_VLB, - S3_MIROCRYSTAL20SV_964, - s3_init, - s3_close, - s3_reset, - { s3_mirocrystal_20sv_964_vlb_available }, - s3_speed_changed, - s3_force_redraw, - s3_9fx_config +const device_t s3_bahamas64_pci_device = { + .name = "S3 Vision864 PCI (Paradise Bahamas 64)", + .internal_name = "bahamas64_pci", + .flags = DEVICE_PCI, + .local = S3_PARADISE_BAHAMAS64, + .init = s3_init, + .close = s3_close, + .reset = s3_reset, + { .available = s3_bahamas64_available }, + .speed_changed = s3_speed_changed, + .force_redraw = s3_force_redraw, + .config = s3_9fx_config }; -const device_t s3_mirocrystal_20sv_964_pci_device = -{ - "S3 Vision964 PCI (MiroCRYSTAL 20SV)", - "mirocrystal20sv_pci", - DEVICE_PCI, - S3_MIROCRYSTAL20SV_964, - s3_init, - s3_close, - s3_reset, - { s3_mirocrystal_20sv_964_pci_available }, - s3_speed_changed, - s3_force_redraw, - s3_9fx_config +const device_t s3_mirocrystal_20sv_964_vlb_device = { + .name = "S3 Vision964 VLB (MiroCRYSTAL 20SV)", + .internal_name = "mirocrystal20sv_vlb", + .flags = DEVICE_VLB, + .local = S3_MIROCRYSTAL20SV_964, + .init = s3_init, + .close = s3_close, + .reset = s3_reset, + { .available = s3_mirocrystal_20sv_964_vlb_available }, + .speed_changed = s3_speed_changed, + .force_redraw = s3_force_redraw, + .config = s3_9fx_config }; - -const device_t s3_diamond_stealth64_964_vlb_device = -{ - "S3 Vision964 VLB (Diamond Stealth64 VRAM)", - "stealth64v_vlb", - DEVICE_VLB, - S3_DIAMOND_STEALTH64_964, - s3_init, - s3_close, - s3_reset, - { s3_diamond_stealth64_964_available }, - s3_speed_changed, - s3_force_redraw, - s3_standard_config +const device_t s3_mirocrystal_20sv_964_pci_device = { + .name = "S3 Vision964 PCI (MiroCRYSTAL 20SV)", + .internal_name = "mirocrystal20sv_pci", + .flags = DEVICE_PCI, + .local = S3_MIROCRYSTAL20SV_964, + .init = s3_init, + .close = s3_close, + .reset = s3_reset, + { .available = s3_mirocrystal_20sv_964_pci_available }, + .speed_changed = s3_speed_changed, + .force_redraw = s3_force_redraw, + .config = s3_9fx_config }; -const device_t s3_diamond_stealth64_964_pci_device = -{ - "S3 Vision964 PCI (Diamond Stealth64 VRAM)", - "stealth64v_pci", - DEVICE_PCI, - S3_DIAMOND_STEALTH64_964, - s3_init, - s3_close, - s3_reset, - { s3_diamond_stealth64_964_available }, - s3_speed_changed, - s3_force_redraw, - s3_standard_config +const device_t s3_diamond_stealth64_964_vlb_device = { + .name = "S3 Vision964 VLB (Diamond Stealth64 VRAM)", + .internal_name = "stealth64v_vlb", + .flags = DEVICE_VLB, + .local = S3_DIAMOND_STEALTH64_964, + .init = s3_init, + .close = s3_close, + .reset = s3_reset, + { .available = s3_diamond_stealth64_964_available }, + .speed_changed = s3_speed_changed, + .force_redraw = s3_force_redraw, + .config = s3_standard_config }; -const device_t s3_9fx_771_pci_device = -{ - "S3 Vision968 PCI (Number 9 9FX 771)", - "n9_9fx_771_pci", - DEVICE_PCI, - S3_NUMBER9_9FX_771, - s3_init, - s3_close, - s3_reset, - { s3_9fx_771_available }, - s3_speed_changed, - s3_force_redraw, - s3_standard_config +const device_t s3_diamond_stealth64_964_pci_device = { + .name = "S3 Vision964 PCI (Diamond Stealth64 VRAM)", + .internal_name = "stealth64v_pci", + .flags = DEVICE_PCI, + .local = S3_DIAMOND_STEALTH64_964, + .init = s3_init, + .close = s3_close, + .reset = s3_reset, + { .available = s3_diamond_stealth64_964_available }, + .speed_changed = s3_speed_changed, + .force_redraw = s3_force_redraw, + .config = s3_standard_config }; -const device_t s3_phoenix_vision968_pci_device = -{ - "S3 Vision968 PCI (Phoenix)", - "px_vision968_pci", - DEVICE_PCI, - S3_PHOENIX_VISION968, - s3_init, - s3_close, - s3_reset, - { s3_phoenix_vision968_available }, - s3_speed_changed, - s3_force_redraw, - s3_standard_config +const device_t s3_9fx_771_pci_device = { + .name = "S3 Vision968 PCI (Number 9 9FX 771)", + .internal_name = "n9_9fx_771_pci", + .flags = DEVICE_PCI, + .local = S3_NUMBER9_9FX_771, + .init = s3_init, + .close = s3_close, + .reset = s3_reset, + { .available = s3_9fx_771_available }, + .speed_changed = s3_speed_changed, + .force_redraw = s3_force_redraw, + .config = s3_968_config }; -const device_t s3_phoenix_vision968_vlb_device = -{ - "S3 Vision968 VLB (Phoenix)", - "px_vision968_vlb", - DEVICE_VLB, - S3_PHOENIX_VISION968, - s3_init, - s3_close, - s3_reset, - { s3_phoenix_vision968_available }, - s3_speed_changed, - s3_force_redraw, - s3_standard_config +const device_t s3_phoenix_vision968_pci_device = { + .name = "S3 Vision968 PCI (Phoenix)", + .internal_name = "px_vision968_pci", + .flags = DEVICE_PCI, + .local = S3_PHOENIX_VISION968, + .init = s3_init, + .close = s3_close, + .reset = s3_reset, + { .available = s3_phoenix_vision968_available }, + .speed_changed = s3_speed_changed, + .force_redraw = s3_force_redraw, + .config = s3_standard_config }; -const device_t s3_mirovideo_40sv_ergo_968_pci_device = -{ - "S3 Vision968 PCI (MiroVIDEO 40SV Ergo)", - "mirovideo40sv_pci", - DEVICE_PCI, - S3_MIROVIDEO40SV_ERGO_968, - s3_init, - s3_close, - s3_reset, - { s3_mirovideo_40sv_ergo_968_pci_available }, - s3_speed_changed, - s3_force_redraw, - s3_standard_config +const device_t s3_phoenix_vision968_vlb_device = { + .name = "S3 Vision968 VLB (Phoenix)", + .internal_name = "px_vision968_vlb", + .flags = DEVICE_VLB, + .local = S3_PHOENIX_VISION968, + .init = s3_init, + .close = s3_close, + .reset = s3_reset, + { .available = s3_phoenix_vision968_available }, + .speed_changed = s3_speed_changed, + .force_redraw = s3_force_redraw, + .config = s3_standard_config }; -const device_t s3_spea_mercury_p64v_pci_device = -{ - "S3 Vision968 PCI (SPEA Mercury P64V)", - "spea_mercury64p_pci", - DEVICE_PCI, - S3_SPEA_MERCURY_P64V, - s3_init, - s3_close, - s3_reset, - { s3_spea_mercury_p64v_pci_available }, - s3_speed_changed, - s3_force_redraw, - s3_standard_config +const device_t s3_mirovideo_40sv_ergo_968_pci_device = { + .name = "S3 Vision968 PCI (MiroVIDEO 40SV Ergo)", + .internal_name = "mirovideo40sv_pci", + .flags = DEVICE_PCI, + .local = S3_MIROVIDEO40SV_ERGO_968, + .init = s3_init, + .close = s3_close, + .reset = s3_reset, + { .available = s3_mirovideo_40sv_ergo_968_pci_available }, + .speed_changed = s3_speed_changed, + .force_redraw = s3_force_redraw, + .config = s3_standard_config }; -const device_t s3_9fx_vlb_device = -{ - "S3 Trio64 VLB (Number 9 9FX 330)", - "n9_9fx_vlb", - DEVICE_VLB, - S3_NUMBER9_9FX, - s3_init, - s3_close, - s3_reset, - { s3_9fx_available }, - s3_speed_changed, - s3_force_redraw, - s3_9fx_config +const device_t s3_spea_mercury_p64v_pci_device = { + .name = "S3 Vision968 PCI (SPEA Mercury P64V)", + .internal_name = "spea_mercury64p_pci", + .flags = DEVICE_PCI, + .local = S3_SPEA_MERCURY_P64V, + .init = s3_init, + .close = s3_close, + .reset = s3_reset, + { .available = s3_spea_mercury_p64v_pci_available }, + .speed_changed = s3_speed_changed, + .force_redraw = s3_force_redraw, + .config = s3_standard_config }; -const device_t s3_9fx_pci_device = -{ - "S3 Trio64 PCI (Number 9 9FX 330)", - "n9_9fx_pci", - DEVICE_PCI, - S3_NUMBER9_9FX, - s3_init, - s3_close, - s3_reset, - { s3_9fx_available }, - s3_speed_changed, - s3_force_redraw, - s3_9fx_config +const device_t s3_9fx_vlb_device = { + .name = "S3 Trio64 VLB (Number 9 9FX 330)", + .internal_name = "n9_9fx_vlb", + .flags = DEVICE_VLB, + .local = S3_NUMBER9_9FX, + .init = s3_init, + .close = s3_close, + .reset = s3_reset, + { .available = s3_9fx_available }, + .speed_changed = s3_speed_changed, + .force_redraw = s3_force_redraw, + .config = s3_9fx_config }; -const device_t s3_phoenix_trio32_vlb_device = -{ - "S3 Trio32 VLB (Phoenix)", - "px_trio32_vlb", - DEVICE_VLB, - S3_PHOENIX_TRIO32, - s3_init, - s3_close, - s3_reset, - { s3_phoenix_trio32_available }, - s3_speed_changed, - s3_force_redraw, - s3_phoenix_trio32_config +const device_t s3_9fx_pci_device = { + .name = "S3 Trio64 PCI (Number 9 9FX 330)", + .internal_name = "n9_9fx_pci", + .flags = DEVICE_PCI, + .local = S3_NUMBER9_9FX, + .init = s3_init, + .close = s3_close, + .reset = s3_reset, + { .available = s3_9fx_available }, + .speed_changed = s3_speed_changed, + .force_redraw = s3_force_redraw, + .config = s3_9fx_config }; -const device_t s3_phoenix_trio32_pci_device = -{ - "S3 Trio32 PCI (Phoenix)", - "px_trio32_pci", - DEVICE_PCI, - S3_PHOENIX_TRIO32, - s3_init, - s3_close, - s3_reset, - { s3_phoenix_trio32_available }, - s3_speed_changed, - s3_force_redraw, - s3_phoenix_trio32_config +const device_t s3_phoenix_trio32_vlb_device = { + .name = "S3 Trio32 VLB (Phoenix)", + .internal_name = "px_trio32_vlb", + .flags = DEVICE_VLB, + .local = S3_PHOENIX_TRIO32, + .init = s3_init, + .close = s3_close, + .reset = s3_reset, + { .available = s3_phoenix_trio32_available }, + .speed_changed = s3_speed_changed, + .force_redraw = s3_force_redraw, + .config = s3_phoenix_trio32_config }; -const device_t s3_diamond_stealth_se_vlb_device = -{ - "S3 Trio32 VLB (Diamond Stealth SE)", - "stealthse_vlb", - DEVICE_VLB, - S3_DIAMOND_STEALTH_SE, - s3_init, - s3_close, - s3_reset, - { s3_diamond_stealth_se_available }, - s3_speed_changed, - s3_force_redraw, - s3_phoenix_trio32_config +const device_t s3_phoenix_trio32_pci_device = { + .name = "S3 Trio32 PCI (Phoenix)", + .internal_name = "px_trio32_pci", + .flags = DEVICE_PCI, + .local = S3_PHOENIX_TRIO32, + .init = s3_init, + .close = s3_close, + .reset = s3_reset, + { .available = s3_phoenix_trio32_available }, + .speed_changed = s3_speed_changed, + .force_redraw = s3_force_redraw, + .config = s3_phoenix_trio32_config }; -const device_t s3_diamond_stealth_se_pci_device = -{ - "S3 Trio32 PCI (Diamond Stealth SE)", - "stealthse_pci", - DEVICE_PCI, - S3_DIAMOND_STEALTH_SE, - s3_init, - s3_close, - s3_reset, - { s3_diamond_stealth_se_available }, - s3_speed_changed, - s3_force_redraw, - s3_phoenix_trio32_config +const device_t s3_diamond_stealth_se_vlb_device = { + .name = "S3 Trio32 VLB (Diamond Stealth SE)", + .internal_name = "stealthse_vlb", + .flags = DEVICE_VLB, + .local = S3_DIAMOND_STEALTH_SE, + .init = s3_init, + .close = s3_close, + .reset = s3_reset, + { .available = s3_diamond_stealth_se_available }, + .speed_changed = s3_speed_changed, + .force_redraw = s3_force_redraw, + .config = s3_phoenix_trio32_config }; - -const device_t s3_phoenix_trio64_vlb_device = -{ - "S3 Trio64 VLB (Phoenix)", - "px_trio64_vlb", - DEVICE_VLB, - S3_PHOENIX_TRIO64, - s3_init, - s3_close, - s3_reset, - { s3_phoenix_trio64_available }, - s3_speed_changed, - s3_force_redraw, - s3_standard_config +const device_t s3_diamond_stealth_se_pci_device = { + .name = "S3 Trio32 PCI (Diamond Stealth SE)", + .internal_name = "stealthse_pci", + .flags = DEVICE_PCI, + .local = S3_DIAMOND_STEALTH_SE, + .init = s3_init, + .close = s3_close, + .reset = s3_reset, + { .available = s3_diamond_stealth_se_available }, + .speed_changed = s3_speed_changed, + .force_redraw = s3_force_redraw, + .config = s3_phoenix_trio32_config }; -const device_t s3_phoenix_trio64_onboard_pci_device = -{ - "S3 Trio64 PCI On-Board (Phoenix)", - "px_trio64_onboard_pci", - DEVICE_PCI, - S3_PHOENIX_TRIO64_ONBOARD, - s3_init, - s3_close, - s3_reset, - { NULL }, - s3_speed_changed, - s3_force_redraw, - s3_standard_config +const device_t s3_phoenix_trio64_vlb_device = { + .name = "S3 Trio64 VLB (Phoenix)", + .internal_name = "px_trio64_vlb", + .flags = DEVICE_VLB, + .local = S3_PHOENIX_TRIO64, + .init = s3_init, + .close = s3_close, + .reset = s3_reset, + { .available = s3_phoenix_trio64_available }, + .speed_changed = s3_speed_changed, + .force_redraw = s3_force_redraw, + .config = s3_standard_config }; -const device_t s3_phoenix_trio64_pci_device = -{ - "S3 Trio64 PCI (Phoenix)", - "px_trio64_pci", - DEVICE_PCI, - S3_PHOENIX_TRIO64, - s3_init, - s3_close, - s3_reset, - { s3_phoenix_trio64_available }, - s3_speed_changed, - s3_force_redraw, - s3_standard_config +const device_t s3_phoenix_trio64_onboard_pci_device = { + .name = "S3 Trio64 PCI On-Board (Phoenix)", + .internal_name = "px_trio64_onboard_pci", + .flags = DEVICE_PCI, + .local = S3_PHOENIX_TRIO64_ONBOARD, + .init = s3_init, + .close = s3_close, + .reset = s3_reset, + { .available = NULL }, + .speed_changed = s3_speed_changed, + .force_redraw = s3_force_redraw, + .config = s3_standard_config }; -const device_t s3_phoenix_trio64vplus_onboard_pci_device = -{ - "S3 Trio64V+ PCI On-Board (Phoenix)", - "px_trio64vplus_onboard_pci", - DEVICE_PCI, - S3_PHOENIX_TRIO64VPLUS_ONBOARD, - s3_init, - s3_close, - s3_reset, - { NULL }, - s3_speed_changed, - s3_force_redraw, - s3_standard_config +const device_t s3_phoenix_trio64_pci_device = { + .name = "S3 Trio64 PCI (Phoenix)", + .internal_name = "px_trio64_pci", + .flags = DEVICE_PCI, + .local = S3_PHOENIX_TRIO64, + .init = s3_init, + .close = s3_close, + .reset = s3_reset, + { .available = s3_phoenix_trio64_available }, + .speed_changed = s3_speed_changed, + .force_redraw = s3_force_redraw, + .config = s3_standard_config }; -const device_t s3_phoenix_trio64vplus_pci_device = -{ - "S3 Trio64V+ PCI (Phoenix)", - "px_trio64vplus_pci", - DEVICE_PCI, - S3_PHOENIX_TRIO64VPLUS, - s3_init, - s3_close, - s3_reset, - { s3_phoenix_trio64vplus_available }, - s3_speed_changed, - s3_force_redraw, - s3_standard_config +const device_t s3_phoenix_trio64vplus_onboard_pci_device = { + .name = "S3 Trio64V+ PCI On-Board (Phoenix)", + .internal_name = "px_trio64vplus_onboard_pci", + .flags = DEVICE_PCI, + .local = S3_PHOENIX_TRIO64VPLUS_ONBOARD, + .init = s3_init, + .close = s3_close, + .reset = s3_reset, + { .available = NULL }, + .speed_changed = s3_speed_changed, + .force_redraw = s3_force_redraw, + .config = s3_standard_config }; -const device_t s3_phoenix_vision864_vlb_device = -{ - "S3 Vision864 VLB (Phoenix)", - "px_vision864_vlb", - DEVICE_VLB, - S3_PHOENIX_VISION864, - s3_init, - s3_close, - s3_reset, - { s3_phoenix_vision864_available }, - s3_speed_changed, - s3_force_redraw, - s3_standard_config +const device_t s3_phoenix_trio64vplus_pci_device = { + .name = "S3 Trio64V+ PCI (Phoenix)", + .internal_name = "px_trio64vplus_pci", + .flags = DEVICE_PCI, + .local = S3_PHOENIX_TRIO64VPLUS, + .init = s3_init, + .close = s3_close, + .reset = s3_reset, + { .available = s3_phoenix_trio64vplus_available }, + .speed_changed = s3_speed_changed, + .force_redraw = s3_force_redraw, + .config = s3_standard_config }; -const device_t s3_phoenix_vision864_pci_device = -{ - "S3 Vision864 PCI (Phoenix)", - "px_vision864_pci", - DEVICE_PCI, - S3_PHOENIX_VISION864, - s3_init, - s3_close, - s3_reset, - { s3_phoenix_vision864_available }, - s3_speed_changed, - s3_force_redraw, - s3_standard_config +const device_t s3_phoenix_vision864_vlb_device = { + .name = "S3 Vision864 VLB (Phoenix)", + .internal_name = "px_vision864_vlb", + .flags = DEVICE_VLB, + .local = S3_PHOENIX_VISION864, + .init = s3_init, + .close = s3_close, + .reset = s3_reset, + { .available = s3_phoenix_vision864_available }, + .speed_changed = s3_speed_changed, + .force_redraw = s3_force_redraw, + .config = s3_standard_config }; -const device_t s3_9fx_531_pci_device = -{ - "S3 Vision868 PCI (Number 9 9FX 531)", - "n9_9fx_531_pci", - DEVICE_PCI, - S3_NUMBER9_9FX_531, - s3_init, - s3_close, - s3_reset, - { s3_9fx_531_available }, - s3_speed_changed, - s3_force_redraw, - s3_9fx_config +const device_t s3_phoenix_vision864_pci_device = { + .name = "S3 Vision864 PCI (Phoenix)", + .internal_name = "px_vision864_pci", + .flags = DEVICE_PCI, + .local = S3_PHOENIX_VISION864, + .init = s3_init, + .close = s3_close, + .reset = s3_reset, + { .available = s3_phoenix_vision864_available }, + .speed_changed = s3_speed_changed, + .force_redraw = s3_force_redraw, + .config = s3_standard_config }; -const device_t s3_phoenix_vision868_vlb_device = -{ - "S3 Vision868 VLB (Phoenix)", - "px_vision868_vlb", - DEVICE_VLB, - S3_PHOENIX_VISION868, - s3_init, - s3_close, - s3_reset, - { s3_phoenix_vision868_available }, - s3_speed_changed, - s3_force_redraw, - s3_standard_config +const device_t s3_9fx_531_pci_device = { + .name = "S3 Vision868 PCI (Number 9 9FX 531)", + .internal_name = "n9_9fx_531_pci", + .flags = DEVICE_PCI, + .local = S3_NUMBER9_9FX_531, + .init = s3_init, + .close = s3_close, + .reset = s3_reset, + { .available = s3_9fx_531_available }, + .speed_changed = s3_speed_changed, + .force_redraw = s3_force_redraw, + .config = s3_9fx_config }; -const device_t s3_phoenix_vision868_pci_device = -{ - "S3 Vision868 PCI (Phoenix)", - "px_vision868_pci", - DEVICE_PCI, - S3_PHOENIX_VISION868, - s3_init, - s3_close, - s3_reset, - { s3_phoenix_vision868_available }, - s3_speed_changed, - s3_force_redraw, - s3_standard_config +const device_t s3_phoenix_vision868_vlb_device = { + .name = "S3 Vision868 VLB (Phoenix)", + .internal_name = "px_vision868_vlb", + .flags = DEVICE_VLB, + .local = S3_PHOENIX_VISION868, + .init = s3_init, + .close = s3_close, + .reset = s3_reset, + { .available = s3_phoenix_vision868_available }, + .speed_changed = s3_speed_changed, + .force_redraw = s3_force_redraw, + .config = s3_standard_config }; -const device_t s3_diamond_stealth64_vlb_device = -{ - "S3 Trio64 VLB (Diamond Stealth64 DRAM)", - "stealth64d_vlb", - DEVICE_VLB, - S3_DIAMOND_STEALTH64_764, - s3_init, - s3_close, - s3_reset, - { s3_diamond_stealth64_764_available }, - s3_speed_changed, - s3_force_redraw, - s3_9fx_config +const device_t s3_phoenix_vision868_pci_device = { + .name = "S3 Vision868 PCI (Phoenix)", + .internal_name = "px_vision868_pci", + .flags = DEVICE_PCI, + .local = S3_PHOENIX_VISION868, + .init = s3_init, + .close = s3_close, + .reset = s3_reset, + { .available = s3_phoenix_vision868_available }, + .speed_changed = s3_speed_changed, + .force_redraw = s3_force_redraw, + .config = s3_standard_config }; -const device_t s3_diamond_stealth64_pci_device = -{ - "S3 Trio64 PCI (Diamond Stealth64 DRAM)", - "stealth64d_pci", - DEVICE_PCI, - S3_DIAMOND_STEALTH64_764, - s3_init, - s3_close, - s3_reset, - { s3_diamond_stealth64_764_available }, - s3_speed_changed, - s3_force_redraw, - s3_9fx_config +const device_t s3_diamond_stealth64_vlb_device = { + .name = "S3 Trio64 VLB (Diamond Stealth64 DRAM)", + .internal_name = "stealth64d_vlb", + .flags = DEVICE_VLB, + .local = S3_DIAMOND_STEALTH64_764, + .init = s3_init, + .close = s3_close, + .reset = s3_reset, + { .available = s3_diamond_stealth64_764_available }, + .speed_changed = s3_speed_changed, + .force_redraw = s3_force_redraw, + .config = s3_9fx_config }; -const device_t s3_spea_mirage_p64_vlb_device = -{ - "S3 Trio64 VLB (SPEA Mirage P64)", - "spea_miragep64_vlb", - DEVICE_VLB, - S3_SPEA_MIRAGE_P64, - s3_init, - s3_close, - s3_reset, - { s3_spea_mirage_p64_vlb_available }, - s3_speed_changed, - s3_force_redraw, - s3_9fx_config +const device_t s3_diamond_stealth64_pci_device = { + .name = "S3 Trio64 PCI (Diamond Stealth64 DRAM)", + .internal_name = "stealth64d_pci", + .flags = DEVICE_PCI, + .local = S3_DIAMOND_STEALTH64_764, + .init = s3_init, + .close = s3_close, + .reset = s3_reset, + { .available = s3_diamond_stealth64_764_available }, + .speed_changed = s3_speed_changed, + .force_redraw = s3_force_redraw, + .config = s3_9fx_config }; -const device_t s3_elsa_winner2000_pro_x_964_pci_device = -{ - "S3 Vision964 PCI (ELSA Winner 2000 Pro/X)", - "elsawin2kprox_964_pci", - DEVICE_PCI, - S3_ELSAWIN2KPROX_964, - s3_init, - s3_close, - s3_reset, - { s3_elsa_winner2000_pro_x_964_available }, - s3_speed_changed, - s3_force_redraw, - s3_968_config +const device_t s3_spea_mirage_p64_vlb_device = { + .name = "S3 Trio64 VLB (SPEA Mirage P64)", + .internal_name = "spea_miragep64_vlb", + .flags = DEVICE_VLB, + .local = S3_SPEA_MIRAGE_P64, + .init = s3_init, + .close = s3_close, + .reset = s3_reset, + { .available = s3_spea_mirage_p64_vlb_available }, + .speed_changed = s3_speed_changed, + .force_redraw = s3_force_redraw, + .config = s3_9fx_config }; -const device_t s3_elsa_winner2000_pro_x_pci_device = -{ - "S3 Vision968 PCI (ELSA Winner 2000 Pro/X)", - "elsawin2kprox_pci", - DEVICE_PCI, - S3_ELSAWIN2KPROX, - s3_init, - s3_close, - s3_reset, - { s3_elsa_winner2000_pro_x_available }, - s3_speed_changed, - s3_force_redraw, - s3_968_config +const device_t s3_elsa_winner2000_pro_x_964_pci_device = { + .name = "S3 Vision964 PCI (ELSA Winner 2000 Pro/X)", + .internal_name = "elsawin2kprox_964_pci", + .flags = DEVICE_PCI, + .local = S3_ELSAWIN2KPROX_964, + .init = s3_init, + .close = s3_close, + .reset = s3_reset, + { .available = s3_elsa_winner2000_pro_x_964_available }, + .speed_changed = s3_speed_changed, + .force_redraw = s3_force_redraw, + .config = s3_968_config }; -const device_t s3_trio64v2_dx_pci_device = -{ - "S3 Trio64V2/DX PCI", - "trio64v2dx_pci", - DEVICE_PCI, - S3_TRIO64V2_DX, - s3_init, - s3_close, - s3_reset, - { s3_trio64v2_dx_available }, - s3_speed_changed, - s3_force_redraw, - s3_standard_config +const device_t s3_elsa_winner2000_pro_x_pci_device = { + .name = "S3 Vision968 PCI (ELSA Winner 2000 Pro/X)", + .internal_name = "elsawin2kprox_pci", + .flags = DEVICE_PCI, + .local = S3_ELSAWIN2KPROX, + .init = s3_init, + .close = s3_close, + .reset = s3_reset, + { .available = s3_elsa_winner2000_pro_x_available }, + .speed_changed = s3_speed_changed, + .force_redraw = s3_force_redraw, + .config = s3_968_config }; - -const device_t s3_trio64v2_dx_onboard_pci_device = -{ - "S3 Trio64V2/DX On-Board PCI", - "trio64v2dx_onboard_pci", - DEVICE_PCI, - S3_TRIO64V2_DX_ONBOARD, - s3_init, - s3_close, - NULL, - { NULL }, - s3_speed_changed, - s3_force_redraw, - s3_standard_config +const device_t s3_trio64v2_dx_pci_device = { + .name = "S3 Trio64V2/DX PCI", + .internal_name = "trio64v2dx_pci", + .flags = DEVICE_PCI, + .local = S3_TRIO64V2_DX, + .init = s3_init, + .close = s3_close, + .reset = s3_reset, + { .available = s3_trio64v2_dx_available }, + .speed_changed = s3_speed_changed, + .force_redraw = s3_force_redraw, + .config = s3_standard_config +}; + +const device_t s3_trio64v2_dx_onboard_pci_device = { + .name = "S3 Trio64V2/DX On-Board PCI", + .internal_name = "trio64v2dx_onboard_pci", + .flags = DEVICE_PCI, + .local = S3_TRIO64V2_DX_ONBOARD, + .init = s3_init, + .close = s3_close, + .reset = NULL, + { .available = NULL }, + .speed_changed = s3_speed_changed, + .force_redraw = s3_force_redraw, + .config = s3_standard_config }; diff --git a/src/video/vid_s3_virge.c b/src/video/vid_s3_virge.c index f0b22805a..ce9dda100 100644 --- a/src/video/vid_s3_virge.c +++ b/src/video/vid_s3_virge.c @@ -1,20 +1,20 @@ /* - * 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. + * 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. + * This file is part of the 86Box distribution. * - * S3 ViRGE emulation. + * S3 ViRGE emulation. * * * - * Authors: Sarah Walker, - * Miran Grca, + * Authors: Sarah Walker, + * Miran Grca, * - * Copyright 2008-2018 Sarah Walker. - * Copyright 2016-2018 Miran Grca. + * Copyright 2008-2018 Sarah Walker. + * Copyright 2016-2018 Miran Grca. */ #include #include @@ -22,6 +22,7 @@ #include #include #include +#include #define HAVE_STDARG_H #include <86box/86box.h> #include <86box/io.h> @@ -32,279 +33,274 @@ #include <86box/rom.h> #include <86box/device.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> - -static int dither[4][4] = -{ - {0, 4, 1, 5}, - {6, 2, 7, 3}, - {1, 5, 0, 4}, - {7, 3, 6, 2}, +static int dither[4][4] = { + {0, 4, 1, 5}, + { 6, 2, 7, 3}, + { 1, 5, 0, 4}, + { 7, 3, 6, 2}, }; -#define RB_SIZE 256 -#define RB_MASK (RB_SIZE - 1) +#define RB_SIZE 256 +#define RB_MASK (RB_SIZE - 1) -#define RB_ENTRIES (virge->s3d_write_idx - virge->s3d_read_idx) -#define RB_FULL (RB_ENTRIES == RB_SIZE) -#define RB_EMPTY (!RB_ENTRIES) +#define RB_ENTRIES (virge->s3d_write_idx - virge->s3d_read_idx) +#define RB_FULL (RB_ENTRIES == RB_SIZE) +#define RB_EMPTY (!RB_ENTRIES) -#define FIFO_SIZE 65536 -#define FIFO_MASK (FIFO_SIZE - 1) -#define FIFO_ENTRY_SIZE (1 << 31) +#define FIFO_SIZE 65536 +#define FIFO_MASK (FIFO_SIZE - 1) +#define FIFO_ENTRY_SIZE (1 << 31) -#define FIFO_ENTRIES (virge->fifo_write_idx - virge->fifo_read_idx) -#define FIFO_FULL ((virge->fifo_write_idx - virge->fifo_read_idx) >= (FIFO_SIZE - 4)) -#define FIFO_EMPTY (virge->fifo_read_idx == virge->fifo_write_idx) +#define FIFO_ENTRIES (virge->fifo_write_idx - virge->fifo_read_idx) +#define FIFO_FULL ((virge->fifo_write_idx - virge->fifo_read_idx) >= (FIFO_SIZE - 4)) +#define FIFO_EMPTY (virge->fifo_read_idx == virge->fifo_write_idx) -#define FIFO_TYPE 0xff000000 -#define FIFO_ADDR 0x00ffffff +#define FIFO_TYPE 0xff000000 +#define FIFO_ADDR 0x00ffffff -#define ROM_VIRGE_325 "roms/video/s3virge/86c325.bin" -#define ROM_DIAMOND_STEALTH3D_2000 "roms/video/s3virge/s3virge.bin" -#define ROM_DIAMOND_STEALTH3D_3000 "roms/video/s3virge/diamondstealth3000.vbi" -#define ROM_STB_VELOCITY_3D "roms/video/s3virge/stb_velocity3d_110.BIN" -#define ROM_VIRGE_DX "roms/video/s3virge/86c375_1.bin" -#define ROM_DIAMOND_STEALTH3D_2000PRO "roms/video/s3virge/virgedxdiamond.vbi" -#define ROM_VIRGE_GX "roms/video/s3virge/86c375_4.bin" -#define ROM_VIRGE_GX2 "roms/video/s3virge/flagpoint.VBI" -#define ROM_DIAMOND_STEALTH3D_4000 "roms/video/s3virge/86c357.bin" -#define ROM_TRIO3D2X "roms/video/s3virge/TRIO3D2X_8mbsdr.VBI" +#define ROM_VIRGE_325 "roms/video/s3virge/86c325.bin" +#define ROM_DIAMOND_STEALTH3D_2000 "roms/video/s3virge/s3virge.bin" +#define ROM_DIAMOND_STEALTH3D_3000 "roms/video/s3virge/diamondstealth3000.vbi" +#define ROM_STB_VELOCITY_3D "roms/video/s3virge/stb_velocity3d_110.BIN" +#define ROM_VIRGE_DX "roms/video/s3virge/86c375_1.bin" +#define ROM_DIAMOND_STEALTH3D_2000PRO "roms/video/s3virge/virgedxdiamond.vbi" +#define ROM_VIRGE_GX "roms/video/s3virge/86c375_4.bin" +#define ROM_VIRGE_GX2 "roms/video/s3virge/flagpoint.VBI" +#define ROM_DIAMOND_STEALTH3D_4000 "roms/video/s3virge/86c357.bin" +#define ROM_TRIO3D2X "roms/video/s3virge/TRIO3D2X_8mbsdr.VBI" -enum -{ - S3_VIRGE_325, - S3_DIAMOND_STEALTH3D_2000, - S3_DIAMOND_STEALTH3D_3000, - S3_STB_VELOCITY_3D, - S3_VIRGE_DX, - S3_DIAMOND_STEALTH3D_2000PRO, - S3_VIRGE_GX, - S3_VIRGE_GX2, - S3_DIAMOND_STEALTH3D_4000, - S3_TRIO_3D2X +enum { + S3_VIRGE_325, + S3_DIAMOND_STEALTH3D_2000, + S3_DIAMOND_STEALTH3D_3000, + S3_STB_VELOCITY_3D, + S3_VIRGE_DX, + S3_DIAMOND_STEALTH3D_2000PRO, + S3_VIRGE_GX, + S3_VIRGE_GX2, + S3_DIAMOND_STEALTH3D_4000, + S3_TRIO_3D2X }; -enum -{ - S3_VIRGE, - S3_VIRGEVX, - S3_VIRGEDX, - S3_VIRGEGX2, - S3_TRIO3D2X +enum { + S3_VIRGE, + S3_VIRGEVX, + S3_VIRGEDX, + S3_VIRGEGX2, + S3_TRIO3D2X }; -enum -{ - FIFO_INVALID = (0x00 << 24), - FIFO_WRITE_BYTE = (0x01 << 24), - FIFO_WRITE_WORD = (0x02 << 24), - FIFO_WRITE_DWORD = (0x03 << 24) +enum { + FIFO_INVALID = (0x00 << 24), + FIFO_WRITE_BYTE = (0x01 << 24), + FIFO_WRITE_WORD = (0x02 << 24), + FIFO_WRITE_DWORD = (0x03 << 24) }; typedef struct { - uint32_t addr_type; - uint32_t val; + uint32_t addr_type; + uint32_t val; } fifo_entry_t; -typedef struct s3d_t -{ - uint32_t cmd_set; - int clip_l, clip_r, clip_t, clip_b; - - uint32_t dest_base; - uint32_t dest_str; - - uint32_t z_base; - uint32_t z_str; +typedef struct s3d_t { + uint32_t cmd_set; + int clip_l, clip_r, clip_t, clip_b; - uint32_t tex_base; - uint32_t tex_bdr_clr; - uint32_t tbv, tbu; - int32_t TdVdX, TdUdX; - int32_t TdVdY, TdUdY; - uint32_t tus, tvs; + uint32_t dest_base; + uint32_t dest_str; - int32_t TdZdX, TdZdY; - uint32_t tzs; + uint32_t z_base; + uint32_t z_str; - int32_t TdWdX, TdWdY; - uint32_t tws; - - int32_t TdDdX, TdDdY; - uint32_t tds; - - int16_t TdGdX, TdBdX, TdRdX, TdAdX; - int16_t TdGdY, TdBdY, TdRdY, TdAdY; - uint32_t tgs, tbs, trs, tas; - - uint32_t TdXdY12; - uint32_t txend12; - uint32_t TdXdY01; - uint32_t txend01; - uint32_t TdXdY02; - uint32_t txs; - uint32_t tys; - int ty01, ty12, tlr; + uint32_t tex_base; + uint32_t tex_bdr_clr; + uint32_t tbv, tbu; + int32_t TdVdX, TdUdX; + int32_t TdVdY, TdUdY; + uint32_t tus, tvs; - uint8_t fog_r, fog_g, fog_b; + int32_t TdZdX, TdZdY; + uint32_t tzs; + + int32_t TdWdX, TdWdY; + uint32_t tws; + + int32_t TdDdX, TdDdY; + uint32_t tds; + + int16_t TdGdX, TdBdX, TdRdX, TdAdX; + int16_t TdGdY, TdBdY, TdRdY, TdAdY; + uint32_t tgs, tbs, trs, tas; + + uint32_t TdXdY12; + uint32_t txend12; + uint32_t TdXdY01; + uint32_t txend01; + uint32_t TdXdY02; + uint32_t txs; + uint32_t tys; + int ty01, ty12, tlr; + + uint8_t fog_r, fog_g, fog_b; } s3d_t; -typedef struct virge_t -{ - mem_mapping_t linear_mapping; - mem_mapping_t mmio_mapping; - mem_mapping_t new_mmio_mapping; - - rom_t bios_rom; - - svga_t svga; +typedef struct virge_t { + mem_mapping_t linear_mapping; + mem_mapping_t mmio_mapping; + mem_mapping_t new_mmio_mapping; - uint8_t bank; - uint8_t ma_ext; - uint8_t reg6b, lfb_bios; + rom_t bios_rom; - uint8_t virge_id, virge_id_high, virge_id_low, virge_rev; + svga_t svga; - uint8_t int_line; + uint8_t bank; + uint8_t ma_ext; + uint8_t reg6b, lfb_bios; - uint32_t linear_base, linear_size; + uint8_t virge_id, virge_id_high, virge_id_low, virge_rev; - uint8_t pci_regs[256]; - int card; + uint8_t int_line; - int pci; - int chip; - int is_agp; + uint32_t linear_base, linear_size; - int bilinear_enabled; - int dithering_enabled; - uint32_t memory_size; - uint32_t vram_mask; + uint8_t pci_regs[256]; - thread_t *render_thread; - event_t *wake_render_thread; - event_t *wake_main_thread; - event_t *not_full_event; + uint8_t pci_slot; + uint8_t irq_state; - uint32_t hwc_fg_col, hwc_bg_col; - int hwc_col_stack_pos; - - struct - { - uint32_t src_base; - uint32_t dest_base; - int clip_l, clip_r, clip_t, clip_b; - int dest_str, src_str; - uint32_t mono_pat_0; - uint32_t mono_pat_1; - uint32_t pat_bg_clr; - uint32_t pat_fg_clr; - uint32_t src_bg_clr; - uint32_t src_fg_clr; - uint32_t cmd_set; - int r_width, r_height; - int rsrc_x, rsrc_y; - int rdest_x, rdest_y; - - int lxend0, lxend1; - int32_t ldx; - uint32_t lxstart, lystart; - int lycnt; - int line_dir; - - int src_x, src_y; - int dest_x, dest_y; - int w, h; - uint8_t rop; - - int data_left_count; - uint32_t data_left; - - uint32_t pattern_8[8*8]; - uint32_t pattern_16[8*8]; - uint32_t pattern_24[8*8]; - uint32_t pattern_32[8*8]; + int pci; + int chip; + int is_agp; - uint32_t prdx; - uint32_t prxstart; - uint32_t pldx; - uint32_t plxstart; - uint32_t pystart; - uint32_t pycnt; - uint32_t dest_l, dest_r; - } s3d; - - s3d_t s3d_tri; + int bilinear_enabled; + int dithering_enabled; + uint32_t memory_size; + uint32_t vram_mask; - s3d_t s3d_buffer[RB_SIZE]; - int s3d_read_idx, s3d_write_idx; - int s3d_busy; - int render_idx; - - struct - { - uint32_t pri_ctrl; - uint32_t chroma_ctrl; - uint32_t sec_ctrl; - uint32_t chroma_upper_bound; - uint32_t sec_filter; - uint32_t blend_ctrl; - uint32_t pri_fb0, pri_fb1; - uint32_t pri_stride; - uint32_t buffer_ctrl; - uint32_t sec_fb0, sec_fb1; - uint32_t sec_stride; - uint32_t overlay_ctrl; - int32_t k1_vert_scale; - int32_t k2_vert_scale; - int32_t dda_vert_accumulator; - int32_t k1_horiz_scale; - int32_t k2_horiz_scale; - int32_t dda_horiz_accumulator; - uint32_t fifo_ctrl; - uint32_t pri_start; - uint32_t pri_size; - uint32_t sec_start; - uint32_t sec_size; - - int sdif; - - int pri_x, pri_y, pri_w, pri_h; - int sec_x, sec_y, sec_w, sec_h; - } streams; + thread_t *render_thread; + event_t *wake_render_thread; + event_t *wake_main_thread; + event_t *not_full_event; - uint8_t cmd_dma; - uint32_t cmd_dma_base; - uint32_t dma_ptr; - uint64_t blitter_time; - volatile int fifo_slot; - - pc_timer_t tri_timer; + uint32_t hwc_fg_col, hwc_bg_col; + int hwc_col_stack_pos; - int virge_busy, local; + struct + { + uint32_t src_base; + uint32_t dest_base; + int clip_l, clip_r, clip_t, clip_b; + int dest_str, src_str; + uint32_t mono_pat_0; + uint32_t mono_pat_1; + uint32_t pat_bg_clr; + uint32_t pat_fg_clr; + uint32_t src_bg_clr; + uint32_t src_fg_clr; + uint32_t cmd_set; + int r_width, r_height; + int rsrc_x, rsrc_y; + int rdest_x, rdest_y; - uint8_t subsys_stat, subsys_cntl, advfunc_cntl; + int lxend0, lxend1; + int32_t ldx; + uint32_t lxstart, lystart; + int lycnt; + int line_dir; - uint8_t render_thread_run; + int src_x, src_y; + int dest_x, dest_y; + int w, h; + uint8_t rop; - uint8_t serialport; + int data_left_count; + uint32_t data_left; - void *i2c, *ddc; - - int waiting; + uint32_t pattern_8[8 * 8]; + uint32_t pattern_16[8 * 8]; + uint32_t pattern_24[8 * 8]; + uint32_t pattern_32[8 * 8]; + + uint32_t prdx; + uint32_t prxstart; + uint32_t pldx; + uint32_t plxstart; + uint32_t pystart; + uint32_t pycnt; + uint32_t dest_l, dest_r; + } s3d; + + s3d_t s3d_tri; + + s3d_t s3d_buffer[RB_SIZE]; + atomic_int s3d_read_idx, s3d_write_idx; + atomic_int s3d_busy; + + struct + { + uint32_t pri_ctrl; + uint32_t chroma_ctrl; + uint32_t sec_ctrl; + uint32_t chroma_upper_bound; + uint32_t sec_filter; + uint32_t blend_ctrl; + uint32_t pri_fb0, pri_fb1; + uint32_t pri_stride; + uint32_t buffer_ctrl; + uint32_t sec_fb0, sec_fb1; + uint32_t sec_stride; + uint32_t overlay_ctrl; + int32_t k1_vert_scale; + int32_t k2_vert_scale; + int32_t dda_vert_accumulator; + int32_t k1_horiz_scale; + int32_t k2_horiz_scale; + int32_t dda_horiz_accumulator; + uint32_t fifo_ctrl; + uint32_t pri_start; + uint32_t pri_size; + uint32_t sec_start; + uint32_t sec_size; + + int sdif; + + int pri_x, pri_y, pri_w, pri_h; + int sec_x, sec_y, sec_w, sec_h; + } streams; + + uint8_t cmd_dma; + uint32_t cmd_dma_base; + uint32_t dma_ptr; + uint64_t blitter_time; + int fifo_slots_num; + + pc_timer_t tri_timer; + + int virge_busy, local; + + uint8_t subsys_stat, subsys_cntl, advfunc_cntl; + + uint8_t render_thread_run; + + uint8_t serialport; + + void *i2c, *ddc; + + int waiting; } virge_t; -static video_timings_t timing_diamond_stealth3d_2000_pci = {VIDEO_PCI, 2, 2, 3, 28, 28, 45}; -static video_timings_t timing_diamond_stealth3d_3000_pci = {VIDEO_PCI, 2, 2, 4, 26, 26, 42}; -static video_timings_t timing_virge_dx_pci = {VIDEO_PCI, 2, 2, 3, 28, 28, 45}; -static video_timings_t timing_virge_agp = {VIDEO_AGP, 2, 2, 3, 28, 28, 45}; +static video_timings_t timing_diamond_stealth3d_2000_pci = { .type = VIDEO_PCI, .write_b = 2, .write_w = 2, .write_l = 3, .read_b = 28, .read_w = 28, .read_l = 45 }; +static video_timings_t timing_diamond_stealth3d_3000_pci = { .type = VIDEO_PCI, .write_b = 2, .write_w = 2, .write_l = 4, .read_b = 26, .read_w = 26, .read_l = 42 }; +static video_timings_t timing_virge_dx_pci = { .type = VIDEO_PCI, .write_b = 2, .write_w = 2, .write_l = 3, .read_b = 28, .read_w = 28, .read_l = 45 }; +static video_timings_t timing_virge_agp = { .type = VIDEO_AGP, .write_b = 2, .write_w = 2, .write_l = 3, .read_b = 28, .read_w = 28, .read_l = 45 }; static void s3_virge_triangle(virge_t *virge, s3d_t *s3d_tri); @@ -313,41 +309,40 @@ static void s3_virge_updatemapping(virge_t *virge); static void s3_virge_bitblt(virge_t *virge, int count, uint32_t cpu_dat); -static uint8_t s3_virge_mmio_read(uint32_t addr, void *p); -static uint16_t s3_virge_mmio_read_w(uint32_t addr, void *p); -static uint32_t s3_virge_mmio_read_l(uint32_t addr, void *p); -static void s3_virge_mmio_write(uint32_t addr, uint8_t val, void *p); -static void s3_virge_mmio_write_w(uint32_t addr, uint16_t val, void *p); -static void s3_virge_mmio_write_l(uint32_t addr, uint32_t val, void *p); +static uint8_t s3_virge_mmio_read(uint32_t addr, void *priv); +static uint16_t s3_virge_mmio_read_w(uint32_t addr, void *rivp); +static uint32_t s3_virge_mmio_read_l(uint32_t addr, void *priv); +static void s3_virge_mmio_write(uint32_t addr, uint8_t val, void *priv); +static void s3_virge_mmio_write_w(uint32_t addr, uint16_t val, void *priv); +static void s3_virge_mmio_write_l(uint32_t addr, uint32_t val, void *priv); -enum -{ - CMD_SET_AE = 1, - CMD_SET_HC = (1 << 1), - - CMD_SET_FORMAT_MASK = (7 << 2), - CMD_SET_FORMAT_8 = (0 << 2), - CMD_SET_FORMAT_16 = (1 << 2), - CMD_SET_FORMAT_24 = (2 << 2), - - CMD_SET_MS = (1 << 6), - CMD_SET_IDS = (1 << 7), - CMD_SET_MP = (1 << 8), - CMD_SET_TP = (1 << 9), - - CMD_SET_ITA_MASK = (3 << 10), - CMD_SET_ITA_BYTE = (0 << 10), - CMD_SET_ITA_WORD = (1 << 10), - CMD_SET_ITA_DWORD = (2 << 10), - - CMD_SET_ZUP = (1 << 23), - - CMD_SET_ZB_MODE = (3 << 24), +enum { + CMD_SET_AE = 1, + CMD_SET_HC = (1 << 1), - CMD_SET_XP = (1 << 25), - CMD_SET_YP = (1 << 26), - - CMD_SET_COMMAND_MASK = (15 << 27) + CMD_SET_FORMAT_MASK = (7 << 2), + CMD_SET_FORMAT_8 = (0 << 2), + CMD_SET_FORMAT_16 = (1 << 2), + CMD_SET_FORMAT_24 = (2 << 2), + + CMD_SET_MS = (1 << 6), + CMD_SET_IDS = (1 << 7), + CMD_SET_MP = (1 << 8), + CMD_SET_TP = (1 << 9), + + CMD_SET_ITA_MASK = (3 << 10), + CMD_SET_ITA_BYTE = (0 << 10), + CMD_SET_ITA_WORD = (1 << 10), + CMD_SET_ITA_DWORD = (2 << 10), + + CMD_SET_ZUP = (1 << 23), + + CMD_SET_ZB_MODE = (3 << 24), + + CMD_SET_XP = (1 << 25), + CMD_SET_YP = (1 << 26), + + CMD_SET_COMMAND_MASK = (15 << 27) }; #define CMD_SET_FE (1 << 17) @@ -355,52 +350,48 @@ enum #define CMD_SET_ABC_ENABLE (1 << 19) #define CMD_SET_TWE (1 << 26) -enum -{ - CMD_SET_COMMAND_BITBLT = (0 << 27), - CMD_SET_COMMAND_RECTFILL = (2 << 27), - CMD_SET_COMMAND_LINE = (3 << 27), - CMD_SET_COMMAND_POLY = (5 << 27), - CMD_SET_COMMAND_NOP = (15 << 27) +enum { + CMD_SET_COMMAND_BITBLT = (0 << 27), + CMD_SET_COMMAND_RECTFILL = (2 << 27), + CMD_SET_COMMAND_LINE = (3 << 27), + CMD_SET_COMMAND_POLY = (5 << 27), + CMD_SET_COMMAND_NOP = (15 << 27) }; -#define INT_VSY (1 << 0) -#define INT_S3D_DONE (1 << 1) -#define INT_FIFO_OVF (1 << 2) -#define INT_FIFO_EMP (1 << 3) -#define INT_3DF_EMP (1 << 6) -#define INT_MASK 0xff +#define INT_VSY (1 << 0) +#define INT_S3D_DONE (1 << 1) +#define INT_FIFO_OVF (1 << 2) +#define INT_FIFO_EMP (1 << 3) +#define INT_3DF_EMP (1 << 6) +#define INT_MASK 0xff #define SERIAL_PORT_SCW (1 << 0) #define SERIAL_PORT_SDW (1 << 1) #define SERIAL_PORT_SCR (1 << 2) #define SERIAL_PORT_SDR (1 << 3) - #ifdef ENABLE_S3_VIRGE_LOG int s3_virge_do_log = ENABLE_S3_VIRGE_LOG; - static void s3_virge_log(const char *fmt, ...) { va_list ap; if (s3_virge_do_log) { - va_start(ap, fmt); - pclog_ex(fmt, ap); - va_end(ap); + va_start(ap, fmt); + pclog_ex(fmt, ap); + va_end(ap); } } #else -#define s3_virge_log(fmt, ...) +# define s3_virge_log(fmt, ...) #endif - static void -s3_virge_tri_timer(void *p) +s3_virge_tri_timer(void *priv) { - virge_t *virge = (virge_t *)p; + virge_t *virge = (virge_t *) priv; thread_set_event(virge->wake_render_thread); /*Wake up FIFO thread if moving from idle*/ } @@ -408,1895 +399,2116 @@ s3_virge_tri_timer(void *p) static void queue_triangle(virge_t *virge) { - if (RB_FULL) - { - thread_reset_event(virge->not_full_event); - thread_reset_event(virge->wake_main_thread); - if (RB_FULL) { - thread_wait_event(virge->not_full_event, -1); /*Wait for room in ringbuffer*/ - thread_wait_event(virge->wake_main_thread, -1); - } - } - virge->s3d_buffer[virge->s3d_write_idx & RB_MASK] = virge->s3d_tri; - virge->s3d_write_idx++; + if (RB_FULL) { + thread_reset_event(virge->not_full_event); + thread_reset_event(virge->wake_main_thread); + if (RB_FULL) { + thread_wait_event(virge->not_full_event, -1); /*Wait for room in ringbuffer*/ + thread_wait_event(virge->wake_main_thread, -1); + } + } + virge->s3d_buffer[virge->s3d_write_idx & RB_MASK] = virge->s3d_tri; + virge->s3d_write_idx++; - if (!virge->s3d_busy) { - if (!(timer_is_enabled(&virge->tri_timer))) - timer_set_delay_u64(&virge->tri_timer, 100 * TIMER_USEC); - } + if (!virge->s3d_busy) { + if (!(timer_is_enabled(&virge->tri_timer))) + timer_set_delay_u64(&virge->tri_timer, 100 * TIMER_USEC); + } } static void s3_virge_update_irqs(virge_t *virge) { - if ((virge->svga.crtc[0x32] & 0x10) && (virge->subsys_stat & (virge->subsys_cntl & INT_MASK))) - pci_set_irq(virge->card, PCI_INTA); - else - pci_clear_irq(virge->card, PCI_INTA); + if ((virge->svga.crtc[0x32] & 0x10) && (virge->subsys_stat & (virge->subsys_cntl & INT_MASK))) + pci_set_irq(virge->pci_slot, PCI_INTA, &virge->irq_state); + else + pci_clear_irq(virge->pci_slot, PCI_INTA, &virge->irq_state); } - static void render_thread(void *param) { - virge_t *virge = (virge_t *)param; - - while (virge->render_thread_run) { - thread_wait_event(virge->wake_render_thread, -1); - thread_reset_event(virge->wake_render_thread); - virge->s3d_busy = 1; - while (!RB_EMPTY) { - s3_virge_triangle(virge, &virge->s3d_buffer[virge->s3d_read_idx & RB_MASK]); - virge->s3d_read_idx++; - if (RB_ENTRIES == RB_MASK) { - thread_set_event(virge->not_full_event); - thread_set_event(virge->wake_main_thread); - } - } - virge->s3d_busy = 0; - virge->subsys_stat |= INT_S3D_DONE; - s3_virge_update_irqs(virge); - } -} + virge_t *virge = (virge_t *) param; - -static void s3_virge_out(uint16_t addr, uint8_t val, void *p) -{ - virge_t *virge = (virge_t *)p; - svga_t *svga = &virge->svga; - uint8_t old; - uint32_t cursoraddr; - - if (((addr & 0xfff0) == 0x3d0 || (addr & 0xfff0) == 0x3b0) && !(svga->miscout & 1)) - addr ^= 0x60; - - switch (addr) - { - case 0x3c5: - if (svga->seqaddr >= 0x10) - { - svga->seqregs[svga->seqaddr & 0x1f]=val; - svga_recalctimings(svga); - return; - } - if (svga->seqaddr == 4) /*Chain-4 - update banking*/ - { - if (val & 8) - svga->write_bank = svga->read_bank = virge->bank << 16; - else - svga->write_bank = svga->read_bank = virge->bank << 14; - } else if (svga->seqaddr == 0x08) { - svga->seqregs[svga->seqaddr] = val & 0x0f; - return; - } else if ((svga->seqaddr == 0x0d) && (svga->seqregs[0x08] == 0x06)) { - svga->seqregs[svga->seqaddr] = val; - svga->dpms = (svga->seqregs[0x0d] & 0x50) || (svga->crtc[0x56] & 0x06); - svga_recalctimings(svga); - return; - } - break; - - case 0x3d4: - svga->crtcreg = val; - return; - case 0x3d5: - if ((svga->crtcreg < 7) && (svga->crtc[0x11] & 0x80)) - return; - if ((svga->crtcreg == 7) && (svga->crtc[0x11] & 0x80)) - val = (svga->crtc[7] & ~0x10) | (val & 0x10); - if ((svga->crtcreg >= 0x20) && (svga->crtcreg < 0x40) && - (svga->crtcreg != 0x36) && (svga->crtcreg != 0x38) && - (svga->crtcreg != 0x39) && ((svga->crtc[0x38] & 0xcc) != 0x48)) - return; - if ((svga->crtcreg >= 0x40) && ((svga->crtc[0x39] & 0xe0) != 0xa0)) - return; - if ((svga->crtcreg == 0x36) && (svga->crtc[0x39] != 0xa5)) - return; - if (svga->crtcreg >= 0x80) - return; - old = svga->crtc[svga->crtcreg]; - svga->crtc[svga->crtcreg] = val; - - if (svga->crtcreg > 0x18) - s3_virge_log("OUTB VGA reg = %02x, val = %02x\n", svga->crtcreg, val); - - switch (svga->crtcreg) - { - case 0x31: - virge->ma_ext = (virge->ma_ext & 0x1c) | ((val & 0x30) >> 4); - break; - case 0x32: - s3_virge_update_irqs(virge); - break; - - case 0x69: - virge->ma_ext = val & 0x1f; - break; - - case 0x35: - virge->bank = (virge->bank & 0x70) | (val & 0xf); - if (svga->chain4) - svga->write_bank = svga->read_bank = virge->bank << 16; - else - svga->write_bank = svga->read_bank = virge->bank << 14; - break; - case 0x51: - virge->bank = (virge->bank & 0x4f) | ((val & 0xc) << 2); - if (svga->chain4) - svga->write_bank = svga->read_bank = virge->bank << 16; - else - svga->write_bank = svga->read_bank = virge->bank << 14; - virge->ma_ext = (virge->ma_ext & ~0xc) | ((val & 3) << 2); - break; - case 0x6a: - virge->bank = val; - if (svga->chain4) - svga->write_bank = svga->read_bank = virge->bank << 16; - else - svga->write_bank = svga->read_bank = virge->bank << 14; - break; - - case 0x3a: - if (val & 0x10) - svga->gdcreg[5] |= 0x40; /*Horrible cheat*/ - break; - - case 0x45: - svga->hwcursor.ena = val & 1; - break; - case 0x46: case 0x47: case 0x48: case 0x49: - case 0x4c: case 0x4d: case 0x4e: case 0x4f: - svga->hwcursor.x = ((svga->crtc[0x46] << 8) | svga->crtc[0x47]) & 0x7ff; - svga->hwcursor.y = ((svga->crtc[0x48] << 8) | svga->crtc[0x49]) & 0x7ff; - svga->hwcursor.xoff = svga->crtc[0x4e] & 0x3f; - svga->hwcursor.yoff = svga->crtc[0x4f] & 0x3f; - cursoraddr = (virge->memory_size == 8) ? 0x1fff : 0x0fff; - svga->hwcursor.addr = ((((svga->crtc[0x4c] << 8) | svga->crtc[0x4d]) & cursoraddr) * 1024) + (svga->hwcursor.yoff * 16); - break; - - case 0x4a: - switch (virge->hwc_col_stack_pos) - { - case 0: - virge->hwc_fg_col = (virge->hwc_fg_col & 0xffff00) | val; - break; - case 1: - virge->hwc_fg_col = (virge->hwc_fg_col & 0xff00ff) | (val << 8); - break; - case 2: - virge->hwc_fg_col = (virge->hwc_fg_col & 0x00ffff) | (val << 16); - break; - } - virge->hwc_col_stack_pos = (virge->hwc_col_stack_pos + 1) & 3; - break; - case 0x4b: - switch (virge->hwc_col_stack_pos) - { - case 0: - virge->hwc_bg_col = (virge->hwc_bg_col & 0xffff00) | val; - break; - case 1: - virge->hwc_bg_col = (virge->hwc_bg_col & 0xff00ff) | (val << 8); - break; - case 2: - virge->hwc_bg_col = (virge->hwc_bg_col & 0x00ffff) | (val << 16); - break; - } - virge->hwc_col_stack_pos = (virge->hwc_col_stack_pos + 1) & 3; - break; - - case 0x53: - case 0x58: case 0x59: case 0x5a: - s3_virge_updatemapping(virge); - break; - - case 0x56: - svga->dpms = (svga->seqregs[0x0d] & 0x50) || (svga->crtc[0x56] & 0x06); - old = ~val; /* force recalc */ - break; - - case 0x5c: - if ((val & 0xa0) == 0x80) - i2c_gpio_set(virge->i2c, !!(val & 0x40), !!(val & 0x10)); - break; - - case 0x67: - switch (val >> 4) - { - case 2: case 3: svga->bpp = 15; break; - case 4: case 5: svga->bpp = 16; break; - case 7: svga->bpp = 24; break; - case 13: svga->bpp = (virge->chip == S3_VIRGEVX) ? 24 : 32; break; - default: svga->bpp = 8; break; - } - break; - - case 0xaa: - i2c_gpio_set(virge->i2c, !!(val & SERIAL_PORT_SCW), !!(val & SERIAL_PORT_SDW)); - break; - } - 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); - if ((svga->crtc[0x67] & 0xc) != 0xc) - svga->ma_latch |= (virge->ma_ext << 16); - } else { - svga->fullchange = changeframecount; - svga_recalctimings(svga); - } - } - } - break; + while (virge->render_thread_run) { + thread_wait_event(virge->wake_render_thread, -1); + thread_reset_event(virge->wake_render_thread); + virge->s3d_busy = 1; + while (!RB_EMPTY) { + s3_virge_triangle(virge, &virge->s3d_buffer[virge->s3d_read_idx & RB_MASK]); + virge->s3d_read_idx++; + if (RB_ENTRIES == RB_MASK) { + thread_set_event(virge->not_full_event); + thread_set_event(virge->wake_main_thread); + } } - svga_out(addr, val, svga); + virge->s3d_busy = 0; + virge->subsys_stat |= INT_S3D_DONE; + s3_virge_update_irqs(virge); + } } -static uint8_t s3_virge_in(uint16_t addr, void *p) +static void +s3_virge_out(uint16_t addr, uint8_t val, void *priv) { - virge_t *virge = (virge_t *)p; - svga_t *svga = &virge->svga; - uint8_t ret; - - if (((addr & 0xfff0) == 0x3d0 || (addr & 0xfff0) == 0x3b0) && !(svga->miscout & 1)) - addr ^= 0x60; + virge_t *virge = (virge_t *) priv; + svga_t *svga = &virge->svga; + uint8_t old; + uint32_t cursoraddr; - switch (addr) - { - case 0x3c1: - if (svga->attraddr > 0x14) - ret = 0xff; + if (((addr & 0xfff0) == 0x3d0 || (addr & 0xfff0) == 0x3b0) && !(svga->miscout & 1)) + addr ^= 0x60; + + switch (addr) { + case 0x3c5: + if (svga->seqaddr >= 0x10) { + svga->seqregs[svga->seqaddr & 0x1f] = val; + svga_recalctimings(svga); + return; + } + if (svga->seqaddr == 4) /*Chain-4 - update banking*/ + { + if (val & 8) + svga->write_bank = svga->read_bank = virge->bank << 16; else - ret = svga_in(addr, svga); - break; + svga->write_bank = svga->read_bank = virge->bank << 14; + } else if (svga->seqaddr == 0x08) { + svga->seqregs[svga->seqaddr] = val & 0x0f; + return; + } else if ((svga->seqaddr == 0x0d) && (svga->seqregs[0x08] == 0x06)) { + svga->seqregs[svga->seqaddr] = val; + svga->dpms = (svga->seqregs[0x0d] & 0x50) || (svga->crtc[0x56] & 0x06); + svga_recalctimings(svga); + return; + } + break; - case 0x3c5: - if (svga->seqaddr >= 8) - ret = svga->seqregs[svga->seqaddr & 0x1f]; - else if (svga->seqaddr <= 4) - ret = svga_in(addr, svga); - else - ret = 0xff; - break; + case 0x3d4: + svga->crtcreg = val; + return; + case 0x3d5: + if ((svga->crtcreg < 7) && (svga->crtc[0x11] & 0x80)) + return; + if ((svga->crtcreg == 7) && (svga->crtc[0x11] & 0x80)) + val = (svga->crtc[7] & ~0x10) | (val & 0x10); + if ((svga->crtcreg >= 0x20) && (svga->crtcreg < 0x40) && (svga->crtcreg != 0x36) && (svga->crtcreg != 0x38) && (svga->crtcreg != 0x39) && ((svga->crtc[0x38] & 0xcc) != 0x48)) + return; + if ((svga->crtcreg >= 0x40) && ((svga->crtc[0x39] & 0xe0) != 0xa0)) + return; + if ((svga->crtcreg == 0x36) && (svga->crtc[0x39] != 0xa5)) + return; + if (svga->crtcreg >= 0x80) + return; + old = svga->crtc[svga->crtcreg]; + svga->crtc[svga->crtcreg] = val; - case 0x3D4: - ret = svga->crtcreg; - break; - case 0x3D5: - switch (svga->crtcreg) - { - case 0x2d: ret = virge->virge_id_high; break; /*Extended chip ID*/ - case 0x2e: ret = virge->virge_id_low; break; /*New chip ID*/ - case 0x2f: ret = virge->virge_rev; break; - case 0x30: ret = virge->virge_id; break; /*Chip ID*/ - case 0x31: ret = (svga->crtc[0x31] & 0xcf) | ((virge->ma_ext & 3) << 4); break; - case 0x33: ret = (svga->crtc[0x33] | 0x04); break; - case 0x35: ret = (svga->crtc[0x35] & 0xf0) | (virge->bank & 0xf); break; - case 0x45: virge->hwc_col_stack_pos = 0; ret = svga->crtc[0x45]; break; - case 0x51: ret = (svga->crtc[0x51] & 0xf0) | ((virge->bank >> 2) & 0xc) | ((virge->ma_ext >> 2) & 3); break; - case 0x5c: /* General Output Port Register */ - ret = svga->crtc[svga->crtcreg] & 0xa0; - if (((svga->miscout >> 2) & 3) == 3) - ret |= svga->crtc[0x42] & 0x0f; - else - ret |= ((svga->miscout >> 2) & 3); - if ((ret & 0xa0) == 0xa0) { - if ((svga->crtc[0x5c] & 0x40) && i2c_gpio_get_scl(virge->i2c)) - ret |= 0x40; - if ((svga->crtc[0x5c] & 0x10) && i2c_gpio_get_sda(virge->i2c)) - ret |= 0x10; - } - break; - case 0x69: ret = virge->ma_ext; break; - case 0x6a: ret = virge->bank; break; + if (svga->crtcreg > 0x18) + s3_virge_log("OUTB VGA reg = %02x, val = %02x\n", svga->crtcreg, val); + + switch (svga->crtcreg) { + case 0x31: + virge->ma_ext = (virge->ma_ext & 0x1c) | ((val & 0x30) >> 4); + break; + case 0x32: + s3_virge_update_irqs(virge); + break; + + case 0x69: + virge->ma_ext = val & 0x1f; + break; + + case 0x35: + virge->bank = (virge->bank & 0x70) | (val & 0xf); + if (svga->chain4) + svga->write_bank = svga->read_bank = virge->bank << 16; + else + svga->write_bank = svga->read_bank = virge->bank << 14; + break; + case 0x51: + virge->bank = (virge->bank & 0x4f) | ((val & 0xc) << 2); + if (svga->chain4) + svga->write_bank = svga->read_bank = virge->bank << 16; + else + svga->write_bank = svga->read_bank = virge->bank << 14; + virge->ma_ext = (virge->ma_ext & ~0xc) | ((val & 3) << 2); + break; + case 0x6a: + virge->bank = val; + if (svga->chain4) + svga->write_bank = svga->read_bank = virge->bank << 16; + else + svga->write_bank = svga->read_bank = virge->bank << 14; + break; + + case 0x3a: + if (val & 0x10) + svga->gdcreg[5] |= 0x40; /*Horrible cheat*/ + break; + + case 0x45: + svga->hwcursor.ena = val & 1; + break; + case 0x46: + case 0x47: + case 0x48: + case 0x49: + case 0x4c: + case 0x4d: + case 0x4e: + case 0x4f: + svga->hwcursor.x = ((svga->crtc[0x46] << 8) | svga->crtc[0x47]) & 0x7ff; + svga->hwcursor.y = ((svga->crtc[0x48] << 8) | svga->crtc[0x49]) & 0x7ff; + svga->hwcursor.xoff = svga->crtc[0x4e] & 0x3f; + svga->hwcursor.yoff = svga->crtc[0x4f] & 0x3f; + cursoraddr = (virge->memory_size == 8) ? 0x1fff : 0x0fff; + svga->hwcursor.addr = ((((svga->crtc[0x4c] << 8) | svga->crtc[0x4d]) & cursoraddr) * 1024) + (svga->hwcursor.yoff * 16); + break; + + case 0x4a: + switch (virge->hwc_col_stack_pos) { + case 0: + virge->hwc_fg_col = (virge->hwc_fg_col & 0xffff00) | val; + break; + case 1: + virge->hwc_fg_col = (virge->hwc_fg_col & 0xff00ff) | (val << 8); + break; + case 2: + virge->hwc_fg_col = (virge->hwc_fg_col & 0x00ffff) | (val << 16); + break; + + default: + break; + } + virge->hwc_col_stack_pos = (virge->hwc_col_stack_pos + 1) & 3; + break; + case 0x4b: + switch (virge->hwc_col_stack_pos) { + case 0: + virge->hwc_bg_col = (virge->hwc_bg_col & 0xffff00) | val; + break; + case 1: + virge->hwc_bg_col = (virge->hwc_bg_col & 0xff00ff) | (val << 8); + break; + case 2: + virge->hwc_bg_col = (virge->hwc_bg_col & 0x00ffff) | (val << 16); + break; + + default: + break; + } + virge->hwc_col_stack_pos = (virge->hwc_col_stack_pos + 1) & 3; + break; + + case 0x53: + case 0x58: + case 0x59: + case 0x5a: + s3_virge_updatemapping(virge); + break; + + case 0x56: + svga->dpms = (svga->seqregs[0x0d] & 0x50) || (svga->crtc[0x56] & 0x06); + old = ~val; /* force recalc */ + break; + + case 0x5c: + if ((val & 0xa0) == 0x80) + i2c_gpio_set(virge->i2c, !!(val & 0x40), !!(val & 0x10)); + break; + + case 0x67: + switch (val >> 4) { + case 2: + case 3: + svga->bpp = 15; + break; + case 4: + case 5: + svga->bpp = 16; + break; + case 7: + svga->bpp = 24; + break; + case 13: + svga->bpp = (virge->chip == S3_VIRGEVX) ? 24 : 32; + break; + default: + svga->bpp = 8; + break; + } + break; + + case 0xaa: + i2c_gpio_set(virge->i2c, !!(val & SERIAL_PORT_SCW), !!(val & SERIAL_PORT_SDW)); + break; - case 0xaa: /* DDC */ - if (virge->chip >= S3_VIRGEGX2) { - ret = svga->crtc[0xaa] & ~(SERIAL_PORT_SCR | SERIAL_PORT_SDR); - if ((svga->crtc[0xaa] & SERIAL_PORT_SCW) && i2c_gpio_get_scl(virge->i2c)) - ret |= SERIAL_PORT_SCR; - if ((svga->crtc[0xaa] & SERIAL_PORT_SDW) && i2c_gpio_get_sda(virge->i2c)) - ret |= SERIAL_PORT_SDR; - break; - } else - ret = svga->crtc[0xaa]; - break; - - default: - ret = svga->crtc[svga->crtcreg]; - break; - } - break; - default: + break; + } + 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); + if ((svga->crtc[0x67] & 0xc) != 0xc) + svga->ma_latch |= (virge->ma_ext << 16); + } else { + svga->fullchange = changeframecount; + svga_recalctimings(svga); + } + } + } + break; + + default: + break; + } + svga_out(addr, val, svga); +} + +static uint8_t +s3_virge_in(uint16_t addr, void *priv) +{ + virge_t *virge = (virge_t *) priv; + svga_t *svga = &virge->svga; + uint8_t ret; + + if (((addr & 0xfff0) == 0x3d0 || (addr & 0xfff0) == 0x3b0) && !(svga->miscout & 1)) + addr ^= 0x60; + + switch (addr) { + case 0x3c1: + if (svga->attraddr > 0x14) + ret = 0xff; + else ret = svga_in(addr, svga); - break; - } - return ret; + break; + + case 0x3c5: + if (svga->seqaddr >= 8) + ret = svga->seqregs[svga->seqaddr & 0x1f]; + else if (svga->seqaddr <= 4) + ret = svga_in(addr, svga); + else + ret = 0xff; + break; + + case 0x3D4: + ret = svga->crtcreg; + break; + case 0x3D5: + switch (svga->crtcreg) { + case 0x2d: + ret = virge->virge_id_high; + break; /*Extended chip ID*/ + case 0x2e: + ret = virge->virge_id_low; + break; /*New chip ID*/ + case 0x2f: + ret = virge->virge_rev; + break; + case 0x30: + ret = virge->virge_id; + break; /*Chip ID*/ + case 0x31: + ret = (svga->crtc[0x31] & 0xcf) | ((virge->ma_ext & 3) << 4); + break; + case 0x33: + ret = (svga->crtc[0x33] | 0x04); + break; + case 0x35: + ret = (svga->crtc[0x35] & 0xf0) | (virge->bank & 0xf); + break; + case 0x45: + virge->hwc_col_stack_pos = 0; + ret = svga->crtc[0x45]; + break; + case 0x51: + ret = (svga->crtc[0x51] & 0xf0) | ((virge->bank >> 2) & 0xc) | ((virge->ma_ext >> 2) & 3); + break; + case 0x5c: /* General Output Port Register */ + ret = svga->crtc[svga->crtcreg] & 0xa0; + if (((svga->miscout >> 2) & 3) == 3) + ret |= svga->crtc[0x42] & 0x0f; + else + ret |= ((svga->miscout >> 2) & 3); + if ((ret & 0xa0) == 0xa0) { + if ((svga->crtc[0x5c] & 0x40) && i2c_gpio_get_scl(virge->i2c)) + ret |= 0x40; + if ((svga->crtc[0x5c] & 0x10) && i2c_gpio_get_sda(virge->i2c)) + ret |= 0x10; + } + break; + case 0x69: + ret = virge->ma_ext; + break; + case 0x6a: + ret = virge->bank; + break; + + case 0xaa: /* DDC */ + if (virge->chip >= S3_VIRGEGX2) { + ret = svga->crtc[0xaa] & ~(SERIAL_PORT_SCR | SERIAL_PORT_SDR); + if ((svga->crtc[0xaa] & SERIAL_PORT_SCW) && i2c_gpio_get_scl(virge->i2c)) + ret |= SERIAL_PORT_SCR; + if ((svga->crtc[0xaa] & SERIAL_PORT_SDW) && i2c_gpio_get_sda(virge->i2c)) + ret |= SERIAL_PORT_SDR; + break; + } else + ret = svga->crtc[0xaa]; + break; + + default: + ret = svga->crtc[svga->crtcreg]; + break; + } + break; + + default: + ret = svga_in(addr, svga); + break; + } + return ret; } -static void s3_virge_recalctimings(svga_t *svga) +static void +s3_virge_recalctimings(svga_t *svga) { - virge_t *virge = (virge_t *)svga->p; - - svga->hdisp = svga->hdisp_old; + const virge_t *virge = (virge_t *) svga->priv; - if (svga->crtc[0x5d] & 0x01) svga->htotal += 0x100; - if (svga->crtc[0x5d] & 0x02) { - svga->hdisp_time += 0x100; - svga->hdisp += 0x100 * ((svga->seqregs[1] & 8) ? 16 : 8); - } - if (svga->crtc[0x5e] & 0x01) svga->vtotal += 0x400; - if (svga->crtc[0x5e] & 0x02) svga->dispend += 0x400; - if (svga->crtc[0x5e] & 0x04) svga->vblankstart += 0x400; - if (svga->crtc[0x5e] & 0x10) svga->vsyncstart += 0x400; - if (svga->crtc[0x5e] & 0x40) svga->split += 0x400; - svga->interlace = svga->crtc[0x42] & 0x20; + svga->hdisp = svga->hdisp_old; - if (((svga->miscout >> 2) & 3) == 3) { - int n = svga->seqregs[0x12] & 0x1f; - int r = (svga->seqregs[0x12] >> 5); - - if (virge->chip == S3_VIRGEVX || virge->chip == S3_VIRGEDX) - r &= 7; - else if (virge->chip >= S3_VIRGEGX2) - r &= 10; - else - r &= 3; - - int m = svga->seqregs[0x13] & 0x7f; - double freq = (((double)m + 2) / (((double)n + 2) * (double)(1 << r))) * 14318184.0; + if (svga->crtc[0x5d] & 0x01) + svga->htotal += 0x100; + if (svga->crtc[0x5d] & 0x02) { + svga->hdisp_time += 0x100; + svga->hdisp += 0x100 * ((svga->seqregs[1] & 8) ? 16 : 8); + } + if (svga->crtc[0x5e] & 0x01) + svga->vtotal += 0x400; + if (svga->crtc[0x5e] & 0x02) + svga->dispend += 0x400; + if (svga->crtc[0x5e] & 0x04) + svga->vblankstart += 0x400; + if (svga->crtc[0x5e] & 0x10) + svga->vsyncstart += 0x400; + if (svga->crtc[0x5e] & 0x40) + svga->split += 0x400; + svga->interlace = svga->crtc[0x42] & 0x20; - svga->clock = (cpuclock * (float)(1ull << 32)) / freq; - } + if (((svga->miscout >> 2) & 3) == 3) { + int n = svga->seqregs[0x12] & 0x1f; + int r = (svga->seqregs[0x12] >> 5); - - if ((svga->crtc[0x67] & 0xc) != 0xc) /*VGA mode*/ - { - svga->ma_latch |= (virge->ma_ext << 16); - if (svga->crtc[0x51] & 0x30) svga->rowoffset += (svga->crtc[0x51] & 0x30) << 4; - else if (svga->crtc[0x43] & 0x04) svga->rowoffset += 0x100; - if (!svga->rowoffset) svga->rowoffset = 256; - - svga->lowres = !((svga->gdcreg[5] & 0x40) && (svga->crtc[0x3a] & 0x10)); - if ((svga->gdcreg[5] & 0x40) && (svga->crtc[0x3a] & 0x10)) { - svga->fb_only = 1; - switch (svga->bpp) { - case 8: - svga->render = svga_render_8bpp_highres; - break; - case 15: - svga->render = svga_render_15bpp_highres; - if (virge->chip != S3_VIRGEVX && virge->chip < S3_VIRGEGX2) - { - svga->htotal >>= 1; - svga->hdisp >>= 1; - } - break; - case 16: - svga->render = svga_render_16bpp_highres; - if (virge->chip != S3_VIRGEVX && virge->chip < S3_VIRGEGX2) - { - svga->htotal >>= 1; - svga->hdisp >>= 1; - } - break; - case 24: - svga->render = svga_render_24bpp_highres; - if (virge->chip != S3_VIRGEVX && virge->chip < S3_VIRGEGX2) - svga->rowoffset = (svga->rowoffset * 3) / 4; /*Hack*/ - break; - case 32: - svga->render = svga_render_32bpp_highres; - break; - } - } else - svga->fb_only = 0; - svga->vram_display_mask = (!(svga->crtc[0x31] & 0x08) && (svga->crtc[0x32] & 0x40)) ? 0x3ffff : virge->vram_mask; - s3_virge_log("VGA mode\n"); - } - else /*Streams mode*/ - { - svga->fb_only = 1; - - if (virge->streams.buffer_ctrl & 1) - svga->ma_latch = virge->streams.pri_fb1 >> 2; - else - svga->ma_latch = virge->streams.pri_fb0 >> 2; - - svga->hdisp = virge->streams.pri_w + 1; - if (virge->streams.pri_h < svga->dispend) - svga->dispend = virge->streams.pri_h; - - svga->overlay.x = virge->streams.sec_x - virge->streams.pri_x; - svga->overlay.y = virge->streams.sec_y - virge->streams.pri_y; - svga->overlay.ysize = virge->streams.sec_h; + if (virge->chip == S3_VIRGEVX || virge->chip == S3_VIRGEDX) + r &= 7; + else if (virge->chip >= S3_VIRGEGX2) + r &= 10; + else + r &= 3; - if (virge->streams.buffer_ctrl & 2) - svga->overlay.addr = virge->streams.sec_fb1; - else - svga->overlay.addr = virge->streams.sec_fb0; + int m = svga->seqregs[0x13] & 0x7f; + double freq = (((double) m + 2) / (((double) n + 2) * (double) (1 << r))) * 14318184.0; - svga->overlay.ena = (svga->overlay.x >= 0); - svga->overlay.v_acc = virge->streams.dda_vert_accumulator; - svga->rowoffset = virge->streams.pri_stride >> 3; + svga->clock = (cpuclock * (float) (1ULL << 32)) / freq; + } - switch ((virge->streams.pri_ctrl >> 24) & 0x7) - { - case 0: /*RGB-8 (CLUT)*/ - svga->render = svga_render_8bpp_highres; - break; - case 3: /*KRGB-16 (1.5.5.5)*/ + if ((svga->crtc[0x67] & 0xc) != 0xc) /*VGA mode*/ + { + svga->ma_latch |= (virge->ma_ext << 16); + if (svga->crtc[0x51] & 0x30) + svga->rowoffset += (svga->crtc[0x51] & 0x30) << 4; + else if (svga->crtc[0x43] & 0x04) + svga->rowoffset += 0x100; + if (!svga->rowoffset) + svga->rowoffset = 256; + + svga->lowres = !((svga->gdcreg[5] & 0x40) && (svga->crtc[0x3a] & 0x10)); + if ((svga->gdcreg[5] & 0x40) && (svga->crtc[0x3a] & 0x10)) { + switch (svga->bpp) { + case 8: + svga->render = svga_render_8bpp_highres; + break; + case 15: + svga->render = svga_render_15bpp_highres; + if (virge->chip != S3_VIRGEVX && virge->chip < S3_VIRGEGX2) { svga->htotal >>= 1; - svga->render = svga_render_15bpp_highres; - break; - case 5: /*RGB-16 (5.6.5)*/ + svga->hdisp >>= 1; + } + break; + case 16: + svga->render = svga_render_16bpp_highres; + if (virge->chip != S3_VIRGEVX && virge->chip < S3_VIRGEGX2) { svga->htotal >>= 1; - svga->render = svga_render_16bpp_highres; - break; - case 6: /*RGB-24 (8.8.8)*/ - svga->render = svga_render_24bpp_highres; - break; - case 7: /*XRGB-32 (X.8.8.8)*/ - svga->render = svga_render_32bpp_highres; - break; - } - svga->vram_display_mask = virge->vram_mask; + svga->hdisp >>= 1; + } + break; + case 24: + svga->render = svga_render_24bpp_highres; + if (virge->chip != S3_VIRGEVX && virge->chip < S3_VIRGEGX2) + svga->rowoffset = (svga->rowoffset * 3) / 4; /*Hack*/ + break; + case 32: + svga->render = svga_render_32bpp_highres; + break; + + default: + break; + } } + svga->vram_display_mask = (!(svga->crtc[0x31] & 0x08) && (svga->crtc[0x32] & 0x40)) ? 0x3ffff : virge->vram_mask; + s3_virge_log("VGA mode\n"); + } else /*Streams mode*/ + { + if (virge->streams.buffer_ctrl & 1) + svga->ma_latch = virge->streams.pri_fb1 >> 2; + else + svga->ma_latch = virge->streams.pri_fb0 >> 2; + + svga->hdisp = virge->streams.pri_w + 1; + if (virge->streams.pri_h < svga->dispend) + svga->dispend = virge->streams.pri_h; + + svga->overlay.x = virge->streams.sec_x - virge->streams.pri_x; + svga->overlay.y = virge->streams.sec_y - virge->streams.pri_y; + svga->overlay.cur_ysize = virge->streams.sec_h; + + if (virge->streams.buffer_ctrl & 2) + svga->overlay.addr = virge->streams.sec_fb1; + else + svga->overlay.addr = virge->streams.sec_fb0; + + svga->overlay.ena = (svga->overlay.x >= 0); + svga->overlay.v_acc = virge->streams.dda_vert_accumulator; + svga->rowoffset = virge->streams.pri_stride >> 3; + + switch ((virge->streams.pri_ctrl >> 24) & 0x7) { + case 0: /*RGB-8 (CLUT)*/ + svga->render = svga_render_8bpp_highres; + break; + case 3: /*KRGB-16 (1.5.5.5)*/ + svga->htotal >>= 1; + svga->render = svga_render_15bpp_highres; + break; + case 5: /*RGB-16 (5.6.5)*/ + svga->htotal >>= 1; + svga->render = svga_render_16bpp_highres; + break; + case 6: /*RGB-24 (8.8.8)*/ + svga->render = svga_render_24bpp_highres; + break; + case 7: /*XRGB-32 (X.8.8.8)*/ + svga->render = svga_render_32bpp_highres; + break; + + default: + break; + } + svga->vram_display_mask = virge->vram_mask; + } } -static void s3_virge_updatemapping(virge_t *virge) +static void +s3_virge_updatemapping(virge_t *virge) { - svga_t *svga = &virge->svga; + svga_t *svga = &virge->svga; - if (!(virge->pci_regs[PCI_REG_COMMAND] & PCI_COMMAND_MEM)) - { - mem_mapping_disable(&svga->mapping); - mem_mapping_disable(&virge->linear_mapping); - mem_mapping_disable(&virge->mmio_mapping); - mem_mapping_disable(&virge->new_mmio_mapping); - return; + if (!(virge->pci_regs[PCI_REG_COMMAND] & PCI_COMMAND_MEM)) { + mem_mapping_disable(&svga->mapping); + mem_mapping_disable(&virge->linear_mapping); + mem_mapping_disable(&virge->mmio_mapping); + mem_mapping_disable(&virge->new_mmio_mapping); + return; + } + + s3_virge_log("Update mapping - bank %02X ", svga->gdcreg[6] & 0xc); + /*Banked framebuffer*/ + switch (svga->gdcreg[6] & 0xc) { /*VGA mapping*/ + case 0x0: /*128k at A0000*/ + mem_mapping_set_addr(&svga->mapping, 0xa0000, 0x20000); + svga->banked_mask = 0xffff; + break; + case 0x4: /*64k at A0000*/ + mem_mapping_set_addr(&svga->mapping, 0xa0000, 0x10000); + svga->banked_mask = 0xffff; + break; + case 0x8: /*32k at B0000*/ + mem_mapping_set_addr(&svga->mapping, 0xb0000, 0x08000); + svga->banked_mask = 0x7fff; + break; + case 0xC: /*32k at B8000*/ + mem_mapping_set_addr(&svga->mapping, 0xb8000, 0x08000); + svga->banked_mask = 0x7fff; + break; + + default: + break; + } + + virge->linear_base = (svga->crtc[0x5a] << 16) | (svga->crtc[0x59] << 24); + + s3_virge_log("Linear framebuffer %02X, linear base = %08x, display mask = %08x\n", svga->crtc[0x58] & 0x17, virge->linear_base, svga->vram_display_mask); + if ((svga->crtc[0x58] & 0x10) || (virge->advfunc_cntl & 0x10)) { /*Linear framebuffer*/ + switch (svga->crtc[0x58] & 7) { + case 0: /*64k*/ + virge->linear_size = 0x10000; + break; + case 1: /*1mb*/ + virge->linear_size = 0x100000; + break; + case 2: /*2mb*/ + virge->linear_size = 0x200000; + break; + case 3: /*4mb on other than ViRGE/VX, 8mb on ViRGE/VX*/ + if (virge->chip == S3_VIRGEVX || virge->chip == S3_TRIO3D2X) + virge->linear_size = 0x800000; + else + virge->linear_size = 0x400000; + break; + case 7: + virge->linear_size = 0x800000; + break; + + default: + break; } - - s3_virge_log("Update mapping - bank %02X ", svga->gdcreg[6] & 0xc); - /*Banked framebuffer*/ - switch (svga->gdcreg[6] & 0xc) { /*VGA mapping*/ - case 0x0: /*128k at A0000*/ - mem_mapping_set_addr(&svga->mapping, 0xa0000, 0x20000); - svga->banked_mask = 0xffff; - break; - case 0x4: /*64k at A0000*/ - mem_mapping_set_addr(&svga->mapping, 0xa0000, 0x10000); - svga->banked_mask = 0xffff; - break; - case 0x8: /*32k at B0000*/ - mem_mapping_set_addr(&svga->mapping, 0xb0000, 0x08000); - svga->banked_mask = 0x7fff; - break; - case 0xC: /*32k at B8000*/ - mem_mapping_set_addr(&svga->mapping, 0xb8000, 0x08000); - svga->banked_mask = 0x7fff; - break; - } - - virge->linear_base = (svga->crtc[0x5a] << 16) | (svga->crtc[0x59] << 24); - - s3_virge_log("Linear framebuffer %02X, linear base = %08x, display mask = %08x\n", svga->crtc[0x58] & 0x17, virge->linear_base, svga->vram_display_mask); - if ((svga->crtc[0x58] & 0x10) || (virge->advfunc_cntl & 0x10)) { /*Linear framebuffer*/ - switch (svga->crtc[0x58] & 7) { - case 0: /*64k*/ - virge->linear_size = 0x10000; - break; - case 1: /*1mb*/ - virge->linear_size = 0x100000; - break; - case 2: /*2mb*/ - virge->linear_size = 0x200000; - break; - case 3: /*4mb on other than ViRGE/VX, 8mb on ViRGE/VX*/ - if (virge->chip == S3_VIRGEVX || virge->chip == S3_TRIO3D2X) - virge->linear_size = 0x800000; - else - virge->linear_size = 0x400000; - break; - case 7: - virge->linear_size = 0x800000; - break; - } - virge->linear_base &= ~(virge->linear_size - 1); - s3_virge_log("Linear framebuffer at %08X size %08X, mask = %08x, CRTC58 sel = %02x\n", virge->linear_base, virge->linear_size, virge->vram_mask, svga->crtc[0x58] & 7); - if (virge->linear_base == 0xa0000) { - mem_mapping_set_addr(&svga->mapping, 0xa0000, 0x10000); - mem_mapping_disable(&virge->linear_mapping); - } else { - if (virge->chip == S3_VIRGEVX || virge->chip == S3_TRIO3D2X) { - virge->linear_base &= 0xfe000000; - } else { - virge->linear_base &= 0xfc000000; - } - - mem_mapping_set_addr(&virge->linear_mapping, virge->linear_base, virge->linear_size); - } + virge->linear_base &= ~(virge->linear_size - 1); + s3_virge_log("Linear framebuffer at %08X size %08X, mask = %08x, CRTC58 sel = %02x\n", virge->linear_base, virge->linear_size, virge->vram_mask, svga->crtc[0x58] & 7); + if (virge->linear_base == 0xa0000) { + mem_mapping_set_addr(&svga->mapping, 0xa0000, 0x10000); + mem_mapping_disable(&virge->linear_mapping); } else { - mem_mapping_disable(&virge->linear_mapping); + if (virge->chip == S3_VIRGEVX || virge->chip == S3_TRIO3D2X) { + virge->linear_base &= 0xfe000000; + } else { + virge->linear_base &= 0xfc000000; + } + + mem_mapping_set_addr(&virge->linear_mapping, virge->linear_base, virge->linear_size); } - - s3_virge_log("Memory mapped IO %02X\n", svga->crtc[0x53] & 0x38); + svga->fb_only = 1; + } else { + mem_mapping_disable(&virge->linear_mapping); + svga->fb_only = 0; + } - /* Memory mapped I/O. */ - /* Old MMIO. */ - if ((svga->crtc[0x53] & 0x10) || (virge->advfunc_cntl & 0x20)) { - if (svga->crtc[0x53] & 0x20) - mem_mapping_set_addr(&virge->mmio_mapping, 0xb8000, 0x8000); - else - mem_mapping_set_addr(&virge->mmio_mapping, 0xa0000, 0x10000); - } else - mem_mapping_disable(&virge->mmio_mapping); + s3_virge_log("Memory mapped IO %02X\n", svga->crtc[0x53] & 0x38); - /* New MMIO. */ - if (svga->crtc[0x53] & 0x08) - mem_mapping_set_addr(&virge->new_mmio_mapping, virge->linear_base + 0x1000000, 0x10000); - else - mem_mapping_disable(&virge->new_mmio_mapping); + /* Memory mapped I/O. */ + /* Old MMIO. */ + if ((svga->crtc[0x53] & 0x10) || (virge->advfunc_cntl & 0x20)) { + if (svga->crtc[0x53] & 0x20) + mem_mapping_set_addr(&virge->mmio_mapping, 0xb8000, 0x8000); + else + mem_mapping_set_addr(&virge->mmio_mapping, 0xa0000, 0x10000); + } else + mem_mapping_disable(&virge->mmio_mapping); + + /* New MMIO. */ + if (svga->crtc[0x53] & 0x08) + mem_mapping_set_addr(&virge->new_mmio_mapping, virge->linear_base + 0x1000000, 0x10000); + else + mem_mapping_disable(&virge->new_mmio_mapping); } static void s3_virge_vblank_start(svga_t *svga) { - virge_t *virge = (virge_t *)svga->p; + virge_t *virge = (virge_t *) svga->priv; - virge->subsys_stat |= INT_VSY; - s3_virge_update_irqs(virge); + virge->subsys_stat |= INT_VSY; + s3_virge_update_irqs(virge); } - static void s3_virge_mmio_fifo_write(uint32_t addr, uint8_t val, virge_t *virge) { - if ((addr & 0xffff) < 0x8000) { - s3_virge_bitblt(virge, 8, val); - } else { - switch (addr & 0xffff) { - case 0x859c: - virge->cmd_dma = val; - break; - } - } + if ((addr & 0xffff) < 0x8000) + s3_virge_bitblt(virge, 8, val); + else { + switch (addr & 0xffff) { + case 0x859c: + virge->cmd_dma = val; + break; + + default: + break; + } + } } static void s3_virge_mmio_fifo_write_w(uint32_t addr, uint16_t val, virge_t *virge) { - if ((addr & 0xfffe) < 0x8000) { - if (virge->s3d.cmd_set & CMD_SET_MS) - s3_virge_bitblt(virge, 16, ((val >> 8) | (val << 8)) << 16); - else - s3_virge_bitblt(virge, 16, val); - } else { - if ((addr & 0xfffe) == 0x859c) - virge->cmd_dma = val; - } + if ((addr & 0xfffe) < 0x8000) { + if (virge->s3d.cmd_set & CMD_SET_MS) + s3_virge_bitblt(virge, 16, ((val >> 8) | (val << 8)) << 16); + else + s3_virge_bitblt(virge, 16, val); + } else { + if ((addr & 0xfffe) == 0x859c) + virge->cmd_dma = val; + } } static void s3_virge_mmio_fifo_write_l(uint32_t addr, uint32_t val, virge_t *virge) -{ - if ((addr & 0xfffc) < 0x8000) { - if (virge->s3d.cmd_set & CMD_SET_MS) - s3_virge_bitblt(virge, 32, ((val & 0xff000000) >> 24) | ((val & 0x00ff0000) >> 8) | ((val & 0x0000ff00) << 8) | ((val & 0x000000ff) << 24)); - else - s3_virge_bitblt(virge, 32, val); +{ + if ((addr & 0xfffc) < 0x8000) { + if (virge->s3d.cmd_set & CMD_SET_MS) + s3_virge_bitblt(virge, 32, ((val & 0xff000000) >> 24) | ((val & 0x00ff0000) >> 8) | ((val & 0x0000ff00) << 8) | ((val & 0x000000ff) << 24)); + else + s3_virge_bitblt(virge, 32, val); } else { - virge->fifo_slot++; - switch (addr & 0xfffc) { - case 0x8590: - virge->cmd_dma_base = val; - break; - - case 0x8594: - virge->dma_ptr = val; - break; + switch (addr & 0xfffc) { + case 0x8590: + virge->cmd_dma_base = val; + break; - case 0x8598: - break; + case 0x8594: + virge->dma_ptr = val; + break; - case 0x859c: - virge->cmd_dma = val; - break; - - case 0xa000: case 0xa004: case 0xa008: case 0xa00c: - case 0xa010: case 0xa014: case 0xa018: case 0xa01c: - case 0xa020: case 0xa024: case 0xa028: case 0xa02c: - case 0xa030: case 0xa034: case 0xa038: case 0xa03c: - case 0xa040: case 0xa044: case 0xa048: case 0xa04c: - case 0xa050: case 0xa054: case 0xa058: case 0xa05c: - case 0xa060: case 0xa064: case 0xa068: case 0xa06c: - case 0xa070: case 0xa074: case 0xa078: case 0xa07c: - case 0xa080: case 0xa084: case 0xa088: case 0xa08c: - case 0xa090: case 0xa094: case 0xa098: case 0xa09c: - case 0xa0a0: case 0xa0a4: case 0xa0a8: case 0xa0ac: - case 0xa0b0: case 0xa0b4: case 0xa0b8: case 0xa0bc: - case 0xa0c0: case 0xa0c4: case 0xa0c8: case 0xa0cc: - case 0xa0d0: case 0xa0d4: case 0xa0d8: case 0xa0dc: - case 0xa0e0: case 0xa0e4: case 0xa0e8: case 0xa0ec: - case 0xa0f0: case 0xa0f4: case 0xa0f8: case 0xa0fc: - case 0xa100: case 0xa104: case 0xa108: case 0xa10c: - case 0xa110: case 0xa114: case 0xa118: case 0xa11c: - case 0xa120: case 0xa124: case 0xa128: case 0xa12c: - case 0xa130: case 0xa134: case 0xa138: case 0xa13c: - case 0xa140: case 0xa144: case 0xa148: case 0xa14c: - case 0xa150: case 0xa154: case 0xa158: case 0xa15c: - case 0xa160: case 0xa164: case 0xa168: case 0xa16c: - case 0xa170: case 0xa174: case 0xa178: case 0xa17c: - case 0xa180: case 0xa184: case 0xa188: case 0xa18c: - case 0xa190: case 0xa194: case 0xa198: case 0xa19c: - case 0xa1a0: case 0xa1a4: case 0xa1a8: case 0xa1ac: - case 0xa1b0: case 0xa1b4: case 0xa1b8: case 0xa1bc: - case 0xa1c0: case 0xa1c4: case 0xa1c8: case 0xa1cc: - case 0xa1d0: case 0xa1d4: case 0xa1d8: case 0xa1dc: - case 0xa1e0: case 0xa1e4: case 0xa1e8: case 0xa1ec: - case 0xa1f0: case 0xa1f4: case 0xa1f8: case 0xa1fc: - { - int x = addr & 4; - int y = (addr >> 3) & 7; - int color, xx; - int byte; - virge->s3d.pattern_8[y*8 + x] = val & 0xff; - virge->s3d.pattern_8[y*8 + x + 1] = val >> 8; - virge->s3d.pattern_8[y*8 + x + 2] = val >> 16; - virge->s3d.pattern_8[y*8 + x + 3] = val >> 24; - - x = (addr >> 1) & 6; - y = (addr >> 4) & 7; - virge->s3d.pattern_16[y*8 + x] = val & 0xffff; - virge->s3d.pattern_16[y*8 + x + 1] = val >> 16; + case 0x8598: + break; - addr &= 0x00ff; - for (xx = 0; xx < 4; xx++) { - x = ((addr + xx) / 3) % 8; - y = ((addr + xx) / 24) % 8; - color = ((addr + xx) % 3) << 3; - byte = (xx << 3); - virge->s3d.pattern_24[y*8 + x] &= ~(0xff << color); - virge->s3d.pattern_24[y*8 + x] |= ((val >> byte) & 0xff) << color; - } + case 0x859c: + virge->cmd_dma = val; + break; - x = (addr >> 2) & 7; - y = (addr >> 5) & 7; - virge->s3d.pattern_32[y*8 + x] = val & 0xffffff; - } - break; + case 0xa000: + case 0xa004: + case 0xa008: + case 0xa00c: + case 0xa010: + case 0xa014: + case 0xa018: + case 0xa01c: + case 0xa020: + case 0xa024: + case 0xa028: + case 0xa02c: + case 0xa030: + case 0xa034: + case 0xa038: + case 0xa03c: + case 0xa040: + case 0xa044: + case 0xa048: + case 0xa04c: + case 0xa050: + case 0xa054: + case 0xa058: + case 0xa05c: + case 0xa060: + case 0xa064: + case 0xa068: + case 0xa06c: + case 0xa070: + case 0xa074: + case 0xa078: + case 0xa07c: + case 0xa080: + case 0xa084: + case 0xa088: + case 0xa08c: + case 0xa090: + case 0xa094: + case 0xa098: + case 0xa09c: + case 0xa0a0: + case 0xa0a4: + case 0xa0a8: + case 0xa0ac: + case 0xa0b0: + case 0xa0b4: + case 0xa0b8: + case 0xa0bc: + case 0xa0c0: + case 0xa0c4: + case 0xa0c8: + case 0xa0cc: + case 0xa0d0: + case 0xa0d4: + case 0xa0d8: + case 0xa0dc: + case 0xa0e0: + case 0xa0e4: + case 0xa0e8: + case 0xa0ec: + case 0xa0f0: + case 0xa0f4: + case 0xa0f8: + case 0xa0fc: + case 0xa100: + case 0xa104: + case 0xa108: + case 0xa10c: + case 0xa110: + case 0xa114: + case 0xa118: + case 0xa11c: + case 0xa120: + case 0xa124: + case 0xa128: + case 0xa12c: + case 0xa130: + case 0xa134: + case 0xa138: + case 0xa13c: + case 0xa140: + case 0xa144: + case 0xa148: + case 0xa14c: + case 0xa150: + case 0xa154: + case 0xa158: + case 0xa15c: + case 0xa160: + case 0xa164: + case 0xa168: + case 0xa16c: + case 0xa170: + case 0xa174: + case 0xa178: + case 0xa17c: + case 0xa180: + case 0xa184: + case 0xa188: + case 0xa18c: + case 0xa190: + case 0xa194: + case 0xa198: + case 0xa19c: + case 0xa1a0: + case 0xa1a4: + case 0xa1a8: + case 0xa1ac: + case 0xa1b0: + case 0xa1b4: + case 0xa1b8: + case 0xa1bc: + case 0xa1c0: + case 0xa1c4: + case 0xa1c8: + case 0xa1cc: + case 0xa1d0: + case 0xa1d4: + case 0xa1d8: + case 0xa1dc: + case 0xa1e0: + case 0xa1e4: + case 0xa1e8: + case 0xa1ec: + case 0xa1f0: + case 0xa1f4: + case 0xa1f8: + case 0xa1fc: + { + int x = addr & 4; + int y = (addr >> 3) & 7; + int color; + int byte; + virge->s3d.pattern_8[y * 8 + x] = val & 0xff; + virge->s3d.pattern_8[y * 8 + x + 1] = val >> 8; + virge->s3d.pattern_8[y * 8 + x + 2] = val >> 16; + virge->s3d.pattern_8[y * 8 + x + 3] = val >> 24; - case 0xa4d4: case 0xa8d4: - virge->s3d.src_base = (virge->memory_size == 8) ? (val & 0x7ffff8) : (val & 0x3ffff8); - s3_virge_log("PortWrite = %04x, SRC Base = %08x, memsize = %i\n", addr & 0xfffc, val, virge->memory_size); - break; - case 0xa4d8: case 0xa8d8: - virge->s3d.dest_base = (virge->memory_size == 8) ? (val & 0x7ffff8) : (val & 0x3ffff8); - s3_virge_log("PortWrite = %04x, DST Base = %08x, memsize = %i\n", addr & 0xfffc, val, virge->memory_size); - break; - case 0xa4dc: case 0xa8dc: - virge->s3d.clip_l = (val >> 16) & 0x7ff; - virge->s3d.clip_r = val & 0x7ff; - break; - case 0xa4e0: case 0xa8e0: - virge->s3d.clip_t = (val >> 16) & 0x7ff; - virge->s3d.clip_b = val & 0x7ff; - break; - case 0xa4e4: case 0xa8e4: - virge->s3d.dest_str = (val >> 16) & 0xff8; - virge->s3d.src_str = val & 0xff8; - break; - case 0xa4e8: case 0xace8: - virge->s3d.mono_pat_0 = val; - break; - case 0xa4ec: case 0xacec: - virge->s3d.mono_pat_1 = val; - break; - case 0xa4f0: case 0xacf0: - virge->s3d.pat_bg_clr = val; - break; - case 0xa4f4: case 0xa8f4: case 0xacf4: - virge->s3d.pat_fg_clr = val; - break; - case 0xa4f8: - virge->s3d.src_bg_clr = val; - break; - case 0xa4fc: - virge->s3d.src_fg_clr = val; - break; - case 0xa500: case 0xa900: - virge->s3d.cmd_set = val; - if (!(val & CMD_SET_AE)) { - s3_virge_bitblt(virge, -1, 0); - } - break; - case 0xa504: - virge->s3d.r_width = (val >> 16) & 0x7ff; - virge->s3d.r_height = val & 0x7ff; - break; - case 0xa508: - virge->s3d.rsrc_x = (val >> 16) & 0x7ff; - virge->s3d.rsrc_y = val & 0x7ff; - break; - case 0xa50c: - virge->s3d.rdest_x = (val >> 16) & 0x7ff; - virge->s3d.rdest_y = val & 0x7ff; - if (virge->s3d.cmd_set & CMD_SET_AE) { - s3_virge_bitblt(virge, -1, 0); - } - break; - case 0xa96c: - virge->s3d.lxend0 = (val >> 16) & 0x7ff; - virge->s3d.lxend1 = val & 0x7ff; - break; - case 0xa970: - virge->s3d.ldx = (int32_t)val; - break; - case 0xa974: - virge->s3d.lxstart = val; - break; - case 0xa978: - virge->s3d.lystart = val & 0x7ff; - break; - case 0xa97c: - virge->s3d.lycnt = val & 0x7ff; - virge->s3d.line_dir = val >> 31; - if (virge->s3d.cmd_set & CMD_SET_AE) - s3_virge_bitblt(virge, -1, 0); - break; + x = (addr >> 1) & 6; + y = (addr >> 4) & 7; + virge->s3d.pattern_16[y * 8 + x] = val & 0xffff; + virge->s3d.pattern_16[y * 8 + x + 1] = val >> 16; - case 0xad00: - virge->s3d.cmd_set = val; - if (!(val & CMD_SET_AE)) - s3_virge_bitblt(virge, -1, 0); - break; - case 0xad68: - virge->s3d.prdx = val; - break; - case 0xad6c: - virge->s3d.prxstart = val; - break; - case 0xad70: - virge->s3d.pldx = val; - break; - case 0xad74: - virge->s3d.plxstart = val; - break; - case 0xad78: - virge->s3d.pystart = val & 0x7ff; - break; - case 0xad7c: - virge->s3d.pycnt = val & 0x300007ff; - if (virge->s3d.cmd_set & CMD_SET_AE) - s3_virge_bitblt(virge, -1, 0); - break; - - case 0xb0f4: case 0xb4f4: - virge->s3d_tri.fog_b = val & 0xff; - virge->s3d_tri.fog_g = (val >> 8) & 0xff; - virge->s3d_tri.fog_r = (val >> 16) & 0xff; - break; - case 0xb4d4: - virge->s3d_tri.z_base = (virge->memory_size == 8) ? (val & 0x7ffff8) : (val & 0x3ffff8); - break; - case 0xb4d8: - virge->s3d_tri.dest_base = (virge->memory_size == 8) ? (val & 0x7ffff8) : (val & 0x3ffff8); - break; - case 0xb4dc: - virge->s3d_tri.clip_l = (val >> 16) & 0x7ff; - virge->s3d_tri.clip_r = val & 0x7ff; - break; - case 0xb4e0: - virge->s3d_tri.clip_t = (val >> 16) & 0x7ff; - virge->s3d_tri.clip_b = val & 0x7ff; - break; - case 0xb4e4: - virge->s3d_tri.dest_str = (val >> 16) & 0xff8; - virge->s3d.src_str = val & 0xff8; - break; - case 0xb4e8: - virge->s3d_tri.z_str = val & 0xff8; - break; - case 0xb4ec: - virge->s3d_tri.tex_base = (virge->memory_size == 8) ? (val & 0x7ffff8) : (val & 0x3ffff8); - break; - case 0xb4f0: - virge->s3d_tri.tex_bdr_clr = val & 0xffffff; - break; - case 0xb500: - virge->s3d_tri.cmd_set = val; - if (!(val & CMD_SET_AE)) - queue_triangle(virge); - break; - case 0xb504: - virge->s3d_tri.tbv = val & 0xfffff; - break; - case 0xb508: - virge->s3d_tri.tbu = val & 0xfffff; - break; - case 0xb50c: - virge->s3d_tri.TdWdX = val; - break; - case 0xb510: - virge->s3d_tri.TdWdY = val; - break; - case 0xb514: - virge->s3d_tri.tws = val; - break; - case 0xb518: - virge->s3d_tri.TdDdX = val; - break; - case 0xb51c: - virge->s3d_tri.TdVdX = val; - break; - case 0xb520: - virge->s3d_tri.TdUdX = val; - break; - case 0xb524: - virge->s3d_tri.TdDdY = val; - break; - case 0xb528: - virge->s3d_tri.TdVdY = val; - break; - case 0xb52c: - virge->s3d_tri.TdUdY = val; - break; - case 0xb530: - virge->s3d_tri.tds = val; - break; - case 0xb534: - virge->s3d_tri.tvs = val; - break; - case 0xb538: - virge->s3d_tri.tus = val; - break; - case 0xb53c: - virge->s3d_tri.TdGdX = val >> 16; - virge->s3d_tri.TdBdX = val & 0xffff; - break; - case 0xb540: - virge->s3d_tri.TdAdX = val >> 16; - virge->s3d_tri.TdRdX = val & 0xffff; - break; - case 0xb544: - virge->s3d_tri.TdGdY = val >> 16; - virge->s3d_tri.TdBdY = val & 0xffff; - break; - case 0xb548: - virge->s3d_tri.TdAdY = val >> 16; - virge->s3d_tri.TdRdY = val & 0xffff; - break; - case 0xb54c: - virge->s3d_tri.tgs = (val >> 16) & 0xffff; - virge->s3d_tri.tbs = val & 0xffff; - break; - case 0xb550: - virge->s3d_tri.tas = (val >> 16) & 0xffff; - virge->s3d_tri.trs = val & 0xffff; - break; - - case 0xb554: - virge->s3d_tri.TdZdX = val; - break; - case 0xb558: - virge->s3d_tri.TdZdY = val; - break; - case 0xb55c: - virge->s3d_tri.tzs = val; - break; - case 0xb560: - virge->s3d_tri.TdXdY12 = val; - break; - case 0xb564: - virge->s3d_tri.txend12 = val; - break; - case 0xb568: - virge->s3d_tri.TdXdY01 = val; - break; - case 0xb56c: - virge->s3d_tri.txend01 = val; - break; - case 0xb570: - virge->s3d_tri.TdXdY02 = val; - break; - case 0xb574: - virge->s3d_tri.txs = val; - break; - case 0xb578: - virge->s3d_tri.tys = val; - break; - case 0xb57c: - virge->s3d_tri.ty01 = (val >> 16) & 0x7ff; - virge->s3d_tri.ty12 = val & 0x7ff; - virge->s3d_tri.tlr = val >> 31; - if (virge->s3d_tri.cmd_set & CMD_SET_AE) { - queue_triangle(virge); - } - break; - } - } + addr &= 0x00ff; + for (uint8_t xx = 0; xx < 4; xx++) { + x = ((addr + xx) / 3) % 8; + y = ((addr + xx) / 24) % 8; + color = ((addr + xx) % 3) << 3; + byte = (xx << 3); + virge->s3d.pattern_24[y * 8 + x] &= ~(0xff << color); + virge->s3d.pattern_24[y * 8 + x] |= ((val >> byte) & 0xff) << color; + } + + x = (addr >> 2) & 7; + y = (addr >> 5) & 7; + virge->s3d.pattern_32[y * 8 + x] = val & 0xffffff; + } + break; + + case 0xa4d4: + case 0xa8d4: + virge->s3d.src_base = (virge->memory_size == 8) ? (val & 0x7ffff8) : (val & 0x3ffff8); + s3_virge_log("PortWrite = %04x, SRC Base = %08x, memsize = %i\n", addr & 0xfffc, val, virge->memory_size); + break; + case 0xa4d8: + case 0xa8d8: + virge->s3d.dest_base = (virge->memory_size == 8) ? (val & 0x7ffff8) : (val & 0x3ffff8); + s3_virge_log("PortWrite = %04x, DST Base = %08x, memsize = %i\n", addr & 0xfffc, val, virge->memory_size); + break; + case 0xa4dc: + case 0xa8dc: + virge->s3d.clip_l = (val >> 16) & 0x7ff; + virge->s3d.clip_r = val & 0x7ff; + break; + case 0xa4e0: + case 0xa8e0: + virge->s3d.clip_t = (val >> 16) & 0x7ff; + virge->s3d.clip_b = val & 0x7ff; + break; + case 0xa4e4: + case 0xa8e4: + virge->s3d.dest_str = (val >> 16) & 0xff8; + virge->s3d.src_str = val & 0xff8; + break; + case 0xa4e8: + case 0xace8: + virge->s3d.mono_pat_0 = val; + break; + case 0xa4ec: + case 0xacec: + virge->s3d.mono_pat_1 = val; + break; + case 0xa4f0: + case 0xacf0: + virge->s3d.pat_bg_clr = val; + break; + case 0xa4f4: + case 0xa8f4: + case 0xacf4: + virge->s3d.pat_fg_clr = val; + break; + case 0xa4f8: + virge->s3d.src_bg_clr = val; + break; + case 0xa4fc: + virge->s3d.src_fg_clr = val; + break; + case 0xa500: + case 0xa900: + virge->s3d.cmd_set = val; + if (!(val & CMD_SET_AE)) { + s3_virge_bitblt(virge, -1, 0); + } + break; + case 0xa504: + virge->s3d.r_width = (val >> 16) & 0x7ff; + virge->s3d.r_height = val & 0x7ff; + break; + case 0xa508: + virge->s3d.rsrc_x = (val >> 16) & 0x7ff; + virge->s3d.rsrc_y = val & 0x7ff; + break; + case 0xa50c: + virge->s3d.rdest_x = (val >> 16) & 0x7ff; + virge->s3d.rdest_y = val & 0x7ff; + if (virge->s3d.cmd_set & CMD_SET_AE) { + s3_virge_bitblt(virge, -1, 0); + } + break; + case 0xa96c: + virge->s3d.lxend0 = (val >> 16) & 0x7ff; + virge->s3d.lxend1 = val & 0x7ff; + break; + case 0xa970: + virge->s3d.ldx = (int32_t) val; + break; + case 0xa974: + virge->s3d.lxstart = val; + break; + case 0xa978: + virge->s3d.lystart = val & 0x7ff; + break; + case 0xa97c: + virge->s3d.lycnt = val & 0x7ff; + virge->s3d.line_dir = val >> 31; + if (virge->s3d.cmd_set & CMD_SET_AE) + s3_virge_bitblt(virge, -1, 0); + break; + + case 0xad00: + virge->s3d.cmd_set = val; + if (!(val & CMD_SET_AE)) + s3_virge_bitblt(virge, -1, 0); + break; + case 0xad68: + virge->s3d.prdx = val; + break; + case 0xad6c: + virge->s3d.prxstart = val; + break; + case 0xad70: + virge->s3d.pldx = val; + break; + case 0xad74: + virge->s3d.plxstart = val; + break; + case 0xad78: + virge->s3d.pystart = val & 0x7ff; + break; + case 0xad7c: + virge->s3d.pycnt = val & 0x300007ff; + if (virge->s3d.cmd_set & CMD_SET_AE) + s3_virge_bitblt(virge, -1, 0); + break; + + case 0xb0f4: + case 0xb4f4: + virge->s3d_tri.fog_b = val & 0xff; + virge->s3d_tri.fog_g = (val >> 8) & 0xff; + virge->s3d_tri.fog_r = (val >> 16) & 0xff; + break; + case 0xb4d4: + virge->s3d_tri.z_base = (virge->memory_size == 8) ? (val & 0x7ffff8) : (val & 0x3ffff8); + break; + case 0xb4d8: + virge->s3d_tri.dest_base = (virge->memory_size == 8) ? (val & 0x7ffff8) : (val & 0x3ffff8); + break; + case 0xb4dc: + virge->s3d_tri.clip_l = (val >> 16) & 0x7ff; + virge->s3d_tri.clip_r = val & 0x7ff; + break; + case 0xb4e0: + virge->s3d_tri.clip_t = (val >> 16) & 0x7ff; + virge->s3d_tri.clip_b = val & 0x7ff; + break; + case 0xb4e4: + virge->s3d_tri.dest_str = (val >> 16) & 0xff8; + virge->s3d.src_str = val & 0xff8; + break; + case 0xb4e8: + virge->s3d_tri.z_str = val & 0xff8; + break; + case 0xb4ec: + virge->s3d_tri.tex_base = (virge->memory_size == 8) ? (val & 0x7ffff8) : (val & 0x3ffff8); + break; + case 0xb4f0: + virge->s3d_tri.tex_bdr_clr = val & 0xffffff; + break; + case 0xb500: + virge->s3d_tri.cmd_set = val; + if (!(val & CMD_SET_AE)) + queue_triangle(virge); + break; + case 0xb504: + virge->s3d_tri.tbv = val & 0xfffff; + break; + case 0xb508: + virge->s3d_tri.tbu = val & 0xfffff; + break; + case 0xb50c: + virge->s3d_tri.TdWdX = val; + break; + case 0xb510: + virge->s3d_tri.TdWdY = val; + break; + case 0xb514: + virge->s3d_tri.tws = val; + break; + case 0xb518: + virge->s3d_tri.TdDdX = val; + break; + case 0xb51c: + virge->s3d_tri.TdVdX = val; + break; + case 0xb520: + virge->s3d_tri.TdUdX = val; + break; + case 0xb524: + virge->s3d_tri.TdDdY = val; + break; + case 0xb528: + virge->s3d_tri.TdVdY = val; + break; + case 0xb52c: + virge->s3d_tri.TdUdY = val; + break; + case 0xb530: + virge->s3d_tri.tds = val; + break; + case 0xb534: + virge->s3d_tri.tvs = val; + break; + case 0xb538: + virge->s3d_tri.tus = val; + break; + case 0xb53c: + virge->s3d_tri.TdGdX = val >> 16; + virge->s3d_tri.TdBdX = val & 0xffff; + break; + case 0xb540: + virge->s3d_tri.TdAdX = val >> 16; + virge->s3d_tri.TdRdX = val & 0xffff; + break; + case 0xb544: + virge->s3d_tri.TdGdY = val >> 16; + virge->s3d_tri.TdBdY = val & 0xffff; + break; + case 0xb548: + virge->s3d_tri.TdAdY = val >> 16; + virge->s3d_tri.TdRdY = val & 0xffff; + break; + case 0xb54c: + virge->s3d_tri.tgs = (val >> 16) & 0xffff; + virge->s3d_tri.tbs = val & 0xffff; + break; + case 0xb550: + virge->s3d_tri.tas = (val >> 16) & 0xffff; + virge->s3d_tri.trs = val & 0xffff; + break; + + case 0xb554: + virge->s3d_tri.TdZdX = val; + break; + case 0xb558: + virge->s3d_tri.TdZdY = val; + break; + case 0xb55c: + virge->s3d_tri.tzs = val; + break; + case 0xb560: + virge->s3d_tri.TdXdY12 = val; + break; + case 0xb564: + virge->s3d_tri.txend12 = val; + break; + case 0xb568: + virge->s3d_tri.TdXdY01 = val; + break; + case 0xb56c: + virge->s3d_tri.txend01 = val; + break; + case 0xb570: + virge->s3d_tri.TdXdY02 = val; + break; + case 0xb574: + virge->s3d_tri.txs = val; + break; + case 0xb578: + virge->s3d_tri.tys = val; + break; + case 0xb57c: + virge->s3d_tri.ty01 = (val >> 16) & 0x7ff; + virge->s3d_tri.ty12 = val & 0x7ff; + virge->s3d_tri.tlr = val >> 31; + if (virge->s3d_tri.cmd_set & CMD_SET_AE) { + queue_triangle(virge); + } + break; + + default: + break; + } + } } static uint8_t -s3_virge_mmio_read(uint32_t addr, void *p) +s3_virge_mmio_read(uint32_t addr, void *priv) { - virge_t *virge = (virge_t *)p; - uint8_t ret = 0xff; + virge_t *virge = (virge_t *) priv; + uint8_t ret = 0xff; - s3_virge_log("[%04X:%08X]: MMIO ReadB addr = %04x\n", CS, cpu_state.pc, addr & 0xffff); + s3_virge_log("[%04X:%08X]: MMIO ReadB addr = %04x\n", CS, cpu_state.pc, addr & 0xffff); - switch (addr & 0xffff) - { - case 0x8505: - ret = 0; - if (virge->s3d_busy || virge->fifo_slot) { - ret = 0x10; - } else { - ret = 0x30; - } - if (virge->fifo_slot) - virge->fifo_slot--; - return ret; - - case 0x83b0: case 0x83b1: case 0x83b2: case 0x83b3: - case 0x83b4: case 0x83b5: case 0x83b6: case 0x83b7: - case 0x83b8: case 0x83b9: case 0x83ba: case 0x83bb: - case 0x83bc: case 0x83bd: case 0x83be: case 0x83bf: - case 0x83c0: case 0x83c1: case 0x83c2: case 0x83c3: - case 0x83c4: case 0x83c5: case 0x83c6: case 0x83c7: - case 0x83c8: case 0x83c9: case 0x83ca: case 0x83cb: - case 0x83cc: case 0x83cd: case 0x83ce: case 0x83cf: - case 0x83d0: case 0x83d1: case 0x83d2: case 0x83d3: - case 0x83d4: case 0x83d5: case 0x83d6: case 0x83d7: - case 0x83d8: case 0x83d9: case 0x83da: case 0x83db: - case 0x83dc: case 0x83dd: case 0x83de: case 0x83df: - return s3_virge_in(addr & 0x3ff, virge); - - case 0x859c: - return virge->cmd_dma; - - case 0xff20: case 0xff21: - ret = virge->serialport & ~(SERIAL_PORT_SCR | SERIAL_PORT_SDR); - if ((virge->serialport & SERIAL_PORT_SCW) && i2c_gpio_get_scl(virge->i2c)) - ret |= SERIAL_PORT_SCR; - if ((virge->serialport & SERIAL_PORT_SDW) && i2c_gpio_get_sda(virge->i2c)) - ret |= SERIAL_PORT_SDR; - return ret; - } - return 0xff; + switch (addr & 0xffff) { + case 0x8504: + virge->subsys_stat |= (INT_3DF_EMP | INT_FIFO_EMP); + ret = virge->subsys_stat; + s3_virge_update_irqs(virge); + return ret; + case 0x8505: + ret = 0xd0; + if (!virge->s3d_busy) + ret |= 0x20; + return ret; + + case 0x850c: + ret = virge->advfunc_cntl & 0x3f; + ret |= virge->fifo_slots_num << 6; + ret &= 0xff; + return ret; + case 0x850d: + ret = virge->fifo_slots_num >> 2; + return ret; + + case 0x83b0: + case 0x83b1: + case 0x83b2: + case 0x83b3: + case 0x83b4: + case 0x83b5: + case 0x83b6: + case 0x83b7: + case 0x83b8: + case 0x83b9: + case 0x83ba: + case 0x83bb: + case 0x83bc: + case 0x83bd: + case 0x83be: + case 0x83bf: + case 0x83c0: + case 0x83c1: + case 0x83c2: + case 0x83c3: + case 0x83c4: + case 0x83c5: + case 0x83c6: + case 0x83c7: + case 0x83c8: + case 0x83c9: + case 0x83ca: + case 0x83cb: + case 0x83cc: + case 0x83cd: + case 0x83ce: + case 0x83cf: + case 0x83d0: + case 0x83d1: + case 0x83d2: + case 0x83d3: + case 0x83d4: + case 0x83d5: + case 0x83d6: + case 0x83d7: + case 0x83d8: + case 0x83d9: + case 0x83da: + case 0x83db: + case 0x83dc: + case 0x83dd: + case 0x83de: + case 0x83df: + return s3_virge_in(addr & 0x3ff, virge); + + case 0x859c: + return virge->cmd_dma; + + case 0xff20: + case 0xff21: + ret = virge->serialport & ~(SERIAL_PORT_SCR | SERIAL_PORT_SDR); + if ((virge->serialport & SERIAL_PORT_SCW) && i2c_gpio_get_scl(virge->i2c)) + ret |= SERIAL_PORT_SCR; + if ((virge->serialport & SERIAL_PORT_SDW) && i2c_gpio_get_sda(virge->i2c)) + ret |= SERIAL_PORT_SDR; + return ret; + + default: + break; + } + return 0xff; } static uint16_t -s3_virge_mmio_read_w(uint32_t addr, void *p) +s3_virge_mmio_read_w(uint32_t addr, void *priv) { - virge_t *virge = (virge_t *)p; - uint16_t ret = 0xffff; - - s3_virge_log("[%04X:%08X]: MMIO ReadW addr = %04x\n", CS, cpu_state.pc, addr & 0xfffe); - - switch (addr & 0xfffe) { - case 0x8504: - if (!virge->fifo_slot) - virge->subsys_stat |= INT_FIFO_EMP; - ret |= virge->subsys_stat; - if (virge->fifo_slot) - virge->fifo_slot--; - ret |= 0x30; /*A bit of a workaround at the moment.*/ - s3_virge_update_irqs(virge); - return ret; - - case 0x859c: - return virge->cmd_dma; - - default: - return s3_virge_mmio_read(addr, virge) | - (s3_virge_mmio_read(addr + 1, virge) << 8); - } + virge_t *virge = (virge_t *) priv; + uint16_t ret = 0xffff; - return 0xffff; + s3_virge_log("[%04X:%08X]: MMIO ReadW addr = %04x\n", CS, cpu_state.pc, addr & 0xfffe); + + switch (addr & 0xfffe) { + case 0x8504: + ret = 0xd000; + if (!virge->s3d_busy) + ret |= 0x2000; + virge->subsys_stat |= (INT_3DF_EMP | INT_FIFO_EMP); + ret |= virge->subsys_stat; + s3_virge_update_irqs(virge); + return ret; + + case 0x850c: + ret = virge->advfunc_cntl & 0x3f; + ret |= virge->fifo_slots_num << 6; + return ret; + + case 0x859c: + return virge->cmd_dma; + + default: + return s3_virge_mmio_read(addr, virge) | (s3_virge_mmio_read(addr + 1, virge) << 8); + } + + return 0xffff; } static uint32_t -s3_virge_mmio_read_l(uint32_t addr, void *p) +s3_virge_mmio_read_l(uint32_t addr, void *priv) { - virge_t *virge = (virge_t *)p; - uint32_t ret = 0xffffffff; + virge_t *virge = (virge_t *) priv; + uint32_t ret = 0xffffffff; - s3_virge_log("[%04X:%08X]: MMIO ReadL addr = %04x\n", CS, cpu_state.pc, addr & 0xfffc); + s3_virge_log("[%04X:%08X]: MMIO ReadL addr = %04x\n", CS, cpu_state.pc, addr & 0xfffc); - switch (addr & 0xfffc) { - case 0x8180: - ret = virge->streams.pri_ctrl; - break; - case 0x8184: - ret = virge->streams.chroma_ctrl; - break; - case 0x8190: - ret = virge->streams.sec_ctrl; - break; - case 0x8194: - ret = virge->streams.chroma_upper_bound; - break; - case 0x8198: - ret = virge->streams.sec_filter; - break; - case 0x81a0: - ret = virge->streams.blend_ctrl; - break; - case 0x81c0: - ret = virge->streams.pri_fb0; - break; - case 0x81c4: - ret = virge->streams.pri_fb1; - break; - case 0x81c8: - ret = virge->streams.pri_stride; - break; - case 0x81cc: - ret = virge->streams.buffer_ctrl; - break; - case 0x81d0: - ret = virge->streams.sec_fb0; - break; - case 0x81d4: - ret = virge->streams.sec_fb1; - break; - case 0x81d8: - ret = virge->streams.sec_stride; - break; - case 0x81dc: - ret = virge->streams.overlay_ctrl; - break; - case 0x81e0: - ret = virge->streams.k1_vert_scale; - break; - case 0x81e4: - ret = virge->streams.k2_vert_scale; - break; - case 0x81e8: - ret = virge->streams.dda_vert_accumulator; - break; - case 0x81ec: - ret = virge->streams.fifo_ctrl; - break; - case 0x81f0: - ret = virge->streams.pri_start; - break; - case 0x81f4: - ret = virge->streams.pri_size; - break; - case 0x81f8: - ret = virge->streams.sec_start; - break; - case 0x81fc: - ret = virge->streams.sec_size; - break; + switch (addr & 0xfffc) { + case 0x8180: + ret = virge->streams.pri_ctrl; + break; + case 0x8184: + ret = virge->streams.chroma_ctrl; + break; + case 0x8190: + ret = virge->streams.sec_ctrl; + break; + case 0x8194: + ret = virge->streams.chroma_upper_bound; + break; + case 0x8198: + ret = virge->streams.sec_filter; + break; + case 0x81a0: + ret = virge->streams.blend_ctrl; + break; + case 0x81c0: + ret = virge->streams.pri_fb0; + break; + case 0x81c4: + ret = virge->streams.pri_fb1; + break; + case 0x81c8: + ret = virge->streams.pri_stride; + break; + case 0x81cc: + ret = virge->streams.buffer_ctrl; + break; + case 0x81d0: + ret = virge->streams.sec_fb0; + break; + case 0x81d4: + ret = virge->streams.sec_fb1; + break; + case 0x81d8: + ret = virge->streams.sec_stride; + break; + case 0x81dc: + ret = virge->streams.overlay_ctrl; + break; + case 0x81e0: + ret = virge->streams.k1_vert_scale; + break; + case 0x81e4: + ret = virge->streams.k2_vert_scale; + break; + case 0x81e8: + ret = virge->streams.dda_vert_accumulator; + break; + case 0x81ec: + ret = virge->streams.fifo_ctrl; + break; + case 0x81f0: + ret = virge->streams.pri_start; + break; + case 0x81f4: + ret = virge->streams.pri_size; + break; + case 0x81f8: + ret = virge->streams.sec_start; + break; + case 0x81fc: + ret = virge->streams.sec_size; + break; - case 0x8504: - if (virge->s3d_busy || virge->fifo_slot) { - ret = (0x10 << 8); - } else { - ret = (0x10 << 8) | (1 << 13); - if (!virge->s3d_busy) - virge->subsys_stat |= INT_3DF_EMP; - if (!virge->fifo_slot) - virge->subsys_stat |= INT_FIFO_EMP; - } - ret |= virge->subsys_stat; - if (virge->fifo_slot) - virge->fifo_slot--; - s3_virge_update_irqs(virge); - break; - - case 0x8590: - ret = virge->cmd_dma_base; - break; - case 0x8594: - break; - case 0x8598: - ret = virge->dma_ptr; - break; - case 0x859c: - ret = virge->cmd_dma; - break; - - case 0xa4d4: - ret = virge->s3d.src_base; - break; - case 0xa4d8: - ret = virge->s3d.dest_base; - break; - case 0xa4dc: - ret = (virge->s3d.clip_l << 16) | virge->s3d.clip_r; - break; - case 0xa4e0: - ret = (virge->s3d.clip_t << 16) | virge->s3d.clip_b; - break; - case 0xa4e4: - ret = (virge->s3d.dest_str << 16) | virge->s3d.src_str; - break; - case 0xa4e8: case 0xace8: - ret = virge->s3d.mono_pat_0; - break; - case 0xa4ec: case 0xacec: - ret = virge->s3d.mono_pat_1; - break; - case 0xa4f0: - ret = virge->s3d.pat_bg_clr; - break; - case 0xa4f4: - ret = virge->s3d.pat_fg_clr; - break; - case 0xa4f8: - ret = virge->s3d.src_bg_clr; - break; - case 0xa4fc: - ret = virge->s3d.src_fg_clr; - break; - case 0xa500: - ret = virge->s3d.cmd_set; - break; - case 0xa504: - ret = (virge->s3d.r_width << 16) | virge->s3d.r_height; - break; - case 0xa508: - ret = (virge->s3d.rsrc_x << 16) | virge->s3d.rsrc_y; - break; - case 0xa50c: - ret = (virge->s3d.rdest_x << 16) | virge->s3d.rdest_y; - break; - - default: - ret = s3_virge_mmio_read(addr, virge) | - (s3_virge_mmio_read(addr + 1, virge) << 8) | - (s3_virge_mmio_read(addr + 2, virge) << 16) | - (s3_virge_mmio_read(addr + 3, virge) << 24); - break; - } + case 0x8504: + ret = 0x0000d000; + if (!virge->s3d_busy) + ret |= 0x00002000; + virge->subsys_stat |= (INT_3DF_EMP | INT_FIFO_EMP); + ret |= virge->subsys_stat; + s3_virge_update_irqs(virge); + break; - s3_virge_log("MMIO ReadL addr = %04x, val = %08x\n", addr & 0xfffc, ret); - return ret; + case 0x850c: + ret = virge->advfunc_cntl & 0x3f; + ret |= virge->fifo_slots_num << 6; + break; + + case 0x8590: + ret = virge->cmd_dma_base; + break; + case 0x8594: + break; + case 0x8598: + ret = virge->dma_ptr; + break; + case 0x859c: + ret = virge->cmd_dma; + break; + + case 0xa4d4: + ret = virge->s3d.src_base; + break; + case 0xa4d8: + ret = virge->s3d.dest_base; + break; + case 0xa4dc: + ret = (virge->s3d.clip_l << 16) | virge->s3d.clip_r; + break; + case 0xa4e0: + ret = (virge->s3d.clip_t << 16) | virge->s3d.clip_b; + break; + case 0xa4e4: + ret = (virge->s3d.dest_str << 16) | virge->s3d.src_str; + break; + case 0xa4e8: + case 0xace8: + ret = virge->s3d.mono_pat_0; + break; + case 0xa4ec: + case 0xacec: + ret = virge->s3d.mono_pat_1; + break; + case 0xa4f0: + ret = virge->s3d.pat_bg_clr; + break; + case 0xa4f4: + ret = virge->s3d.pat_fg_clr; + break; + case 0xa4f8: + ret = virge->s3d.src_bg_clr; + break; + case 0xa4fc: + ret = virge->s3d.src_fg_clr; + break; + case 0xa500: + ret = virge->s3d.cmd_set; + break; + case 0xa504: + ret = (virge->s3d.r_width << 16) | virge->s3d.r_height; + break; + case 0xa508: + ret = (virge->s3d.rsrc_x << 16) | virge->s3d.rsrc_y; + break; + case 0xa50c: + ret = (virge->s3d.rdest_x << 16) | virge->s3d.rdest_y; + break; + + default: + ret = s3_virge_mmio_read(addr, virge) | (s3_virge_mmio_read(addr + 1, virge) << 8) | (s3_virge_mmio_read(addr + 2, virge) << 16) | (s3_virge_mmio_read(addr + 3, virge) << 24); + break; + } + + s3_virge_log("MMIO ReadL addr = %04x, val = %08x\n", addr & 0xfffc, ret); + return ret; } static void -s3_virge_mmio_write(uint32_t addr, uint8_t val, void *p) +s3_virge_mmio_write(uint32_t addr, uint8_t val, void *priv) { - virge_t *virge = (virge_t *)p; - s3_virge_log("MMIO WriteB addr = %04x, val = %02x\n", addr & 0xffff, val); - if (((addr & 0xffff) >= 0x8590) || ((addr & 0xffff) < 0x8000)) { - if ((addr & 0xffff) == 0xff20) { - virge->serialport = val; - i2c_gpio_set(virge->i2c, !!(val & SERIAL_PORT_SCW), !!(val & SERIAL_PORT_SDW)); - } else - s3_virge_mmio_fifo_write(addr, val, virge); - } else { - switch (addr & 0xffff) { - case 0x83b0: case 0x83b1: case 0x83b2: case 0x83b3: - case 0x83b4: case 0x83b5: case 0x83b6: case 0x83b7: - case 0x83b8: case 0x83b9: case 0x83ba: case 0x83bb: - case 0x83bc: case 0x83bd: case 0x83be: case 0x83bf: - case 0x83c0: case 0x83c1: case 0x83c2: case 0x83c3: - case 0x83c4: case 0x83c5: case 0x83c6: case 0x83c7: - case 0x83c8: case 0x83c9: case 0x83ca: case 0x83cb: - case 0x83cc: case 0x83cd: case 0x83ce: case 0x83cf: - case 0x83d0: case 0x83d1: case 0x83d2: case 0x83d3: - case 0x83d4: case 0x83d5: case 0x83d6: case 0x83d7: - case 0x83d8: case 0x83d9: case 0x83da: case 0x83db: - case 0x83dc: case 0x83dd: case 0x83de: case 0x83df: - s3_virge_out(addr & 0x3ff, val, virge); - break; - } - } + virge_t *virge = (virge_t *) priv; + s3_virge_log("MMIO WriteB addr = %04x, val = %02x\n", addr & 0xffff, val); + if (((addr & 0xffff) >= 0x8590) || ((addr & 0xffff) < 0x8000)) { + if ((addr & 0xffff) == 0xff20) { + virge->serialport = val; + i2c_gpio_set(virge->i2c, !!(val & SERIAL_PORT_SCW), !!(val & SERIAL_PORT_SDW)); + } else + s3_virge_mmio_fifo_write(addr, val, virge); + } else { + switch (addr & 0xffff) { + case 0x83b0: + case 0x83b1: + case 0x83b2: + case 0x83b3: + case 0x83b4: + case 0x83b5: + case 0x83b6: + case 0x83b7: + case 0x83b8: + case 0x83b9: + case 0x83ba: + case 0x83bb: + case 0x83bc: + case 0x83bd: + case 0x83be: + case 0x83bf: + case 0x83c0: + case 0x83c1: + case 0x83c2: + case 0x83c3: + case 0x83c4: + case 0x83c5: + case 0x83c6: + case 0x83c7: + case 0x83c8: + case 0x83c9: + case 0x83ca: + case 0x83cb: + case 0x83cc: + case 0x83cd: + case 0x83ce: + case 0x83cf: + case 0x83d0: + case 0x83d1: + case 0x83d2: + case 0x83d3: + case 0x83d4: + case 0x83d5: + case 0x83d6: + case 0x83d7: + case 0x83d8: + case 0x83d9: + case 0x83da: + case 0x83db: + case 0x83dc: + case 0x83dd: + case 0x83de: + case 0x83df: + s3_virge_out(addr & 0x3ff, val, virge); + break; + + default: + break; + } + } } static void -s3_virge_mmio_write_w(uint32_t addr, uint16_t val, void *p) +s3_virge_mmio_write_w(uint32_t addr, uint16_t val, void *priv) { - virge_t *virge = (virge_t *)p; - s3_virge_log("[%04X:%08X]: MMIO WriteW addr = %04x, val = %04x\n", CS, cpu_state.pc, addr & 0xfffe, val); - if (((addr & 0xfffe) >= 0x8590) || ((addr & 0xfffe) < 0x8000)) - if ((addr & 0xfffe) == 0xff20) - s3_virge_mmio_write(addr, val, virge); - else - s3_virge_mmio_fifo_write_w(addr, val, virge); - else { - if ((addr & 0xfffe) == 0x83d4) { - s3_virge_mmio_write(addr, val, virge); - s3_virge_mmio_write(addr + 1, val >> 8, virge); - } - } + virge_t *virge = (virge_t *) priv; + s3_virge_log("[%04X:%08X]: MMIO WriteW addr = %04x, val = %04x\n", CS, cpu_state.pc, addr & 0xfffe, val); + if (((addr & 0xfffe) >= 0x8590) || ((addr & 0xfffe) < 0x8000)) + if ((addr & 0xfffe) == 0xff20) + s3_virge_mmio_write(addr, val, virge); + else + s3_virge_mmio_fifo_write_w(addr, val, virge); + else { + if ((addr & 0xfffe) == 0x83d4) { + s3_virge_mmio_write(addr, val, virge); + s3_virge_mmio_write(addr + 1, val >> 8, virge); + } + } } static void -s3_virge_mmio_write_l(uint32_t addr, uint32_t val, void *p) +s3_virge_mmio_write_l(uint32_t addr, uint32_t val, void *priv) { - virge_t *virge = (virge_t *)p; - svga_t *svga = &virge->svga; - - s3_virge_log("[%04X:%08X]: MMIO WriteL addr = %04x, val = %04x\n", CS, cpu_state.pc, addr & 0xfffc, val); - if (((addr & 0xfffc) >= 0x8590) || ((addr & 0xfffc) < 0x8000)) - if ((addr & 0xfffc) == 0xff20) - s3_virge_mmio_write(addr, val, virge); - else { - s3_virge_mmio_fifo_write_l(addr, val, virge); - } - else { - switch (addr & 0xfffc) { - case 0x8180: - virge->streams.pri_ctrl = val; - svga_recalctimings(svga); - svga->fullchange = changeframecount; - break; - case 0x8184: - virge->streams.chroma_ctrl = val; - break; - case 0x8190: - virge->streams.sec_ctrl = val; - virge->streams.dda_horiz_accumulator = val & 0xfff; - if (val & (1 << 11)) - virge->streams.dda_horiz_accumulator |= 0xfffff800; - virge->streams.sdif = (val >> 24) & 7; - break; - case 0x8194: - virge->streams.chroma_upper_bound = val; - break; - case 0x8198: - virge->streams.sec_filter = val; - virge->streams.k1_horiz_scale = val & 0x7ff; - if (val & (1 << 10)) - virge->streams.k1_horiz_scale |= 0xfffff800; - virge->streams.k2_horiz_scale = (val >> 16) & 0x7ff; - if ((val >> 16) & (1 << 10)) - virge->streams.k2_horiz_scale |= 0xfffff800; - break; - case 0x81a0: - virge->streams.blend_ctrl = val; - break; - case 0x81c0: - virge->streams.pri_fb0 = val & 0x7fffff; - svga_recalctimings(svga); - svga->fullchange = changeframecount; - break; - case 0x81c4: - virge->streams.pri_fb1 = val & 0x7fffff; - svga_recalctimings(svga); - svga->fullchange = changeframecount; - break; - case 0x81c8: - virge->streams.pri_stride = val & 0xfff; - svga_recalctimings(svga); - svga->fullchange = changeframecount; - break; - case 0x81cc: - virge->streams.buffer_ctrl = val; - svga_recalctimings(svga); - svga->fullchange = changeframecount; - break; - case 0x81d0: - virge->streams.sec_fb0 = val; - svga_recalctimings(svga); - svga->fullchange = changeframecount; - break; - case 0x81d4: - virge->streams.sec_fb1 = val; - svga_recalctimings(svga); - svga->fullchange = changeframecount; - break; - case 0x81d8: - virge->streams.sec_stride = val; - svga_recalctimings(svga); - svga->fullchange = changeframecount; - break; - case 0x81dc: - virge->streams.overlay_ctrl = val; - break; - case 0x81e0: - virge->streams.k1_vert_scale = val & 0x7ff; - if (val & (1 << 10)) - virge->streams.k1_vert_scale |= 0xfffff800; - break; - case 0x81e4: - virge->streams.k2_vert_scale = val & 0x7ff; - if (val & (1 << 10)) - virge->streams.k2_vert_scale |= 0xfffff800; - break; - case 0x81e8: - virge->streams.dda_vert_accumulator = val & 0xfff; - if (val & (1 << 11)) - virge->streams.dda_vert_accumulator |= 0xfffff800; - break; - case 0x81ec: - virge->streams.fifo_ctrl = val; - break; - case 0x81f0: - virge->streams.pri_start = val; - virge->streams.pri_x = (val >> 16) & 0x7ff; - virge->streams.pri_y = val & 0x7ff; - svga_recalctimings(svga); - svga->fullchange = changeframecount; - break; - case 0x81f4: - virge->streams.pri_size = val; - virge->streams.pri_w = (val >> 16) & 0x7ff; - virge->streams.pri_h = val & 0x7ff; - svga_recalctimings(svga); - svga->fullchange = changeframecount; - break; - case 0x81f8: - virge->streams.sec_start = val; - virge->streams.sec_x = (val >> 16) & 0x7ff; - virge->streams.sec_y = val & 0x7ff; - svga_recalctimings(svga); - svga->fullchange = changeframecount; - break; - case 0x81fc: - virge->streams.sec_size = val; - virge->streams.sec_w = (val >> 16) & 0x7ff; - virge->streams.sec_h = val & 0x7ff; - svga_recalctimings(svga); - svga->fullchange = changeframecount; - break; - - case 0x8504: - virge->subsys_stat &= ~(val & 0xff); - virge->subsys_cntl = (val >> 8); - s3_virge_update_irqs(virge); - break; - - case 0x850c: - virge->advfunc_cntl = val & 0xff; - s3_virge_updatemapping(virge); - break; - } - } + virge_t *virge = (virge_t *) priv; + svga_t *svga = &virge->svga; + + s3_virge_log("[%04X:%08X]: MMIO WriteL addr = %04x, val = %04x\n", CS, cpu_state.pc, addr & 0xfffc, val); + if (((addr & 0xfffc) >= 0x8590) || ((addr & 0xfffc) < 0x8000)) + if ((addr & 0xfffc) == 0xff20) + s3_virge_mmio_write(addr, val, virge); + else { + s3_virge_mmio_fifo_write_l(addr, val, virge); + } + else { + switch (addr & 0xfffc) { + case 0x8180: + virge->streams.pri_ctrl = val; + svga_recalctimings(svga); + svga->fullchange = changeframecount; + break; + case 0x8184: + virge->streams.chroma_ctrl = val; + break; + case 0x8190: + virge->streams.sec_ctrl = val; + virge->streams.dda_horiz_accumulator = val & 0xfff; + if (val & (1 << 11)) + virge->streams.dda_horiz_accumulator |= 0xfffff800; + virge->streams.sdif = (val >> 24) & 7; + break; + case 0x8194: + virge->streams.chroma_upper_bound = val; + break; + case 0x8198: + virge->streams.sec_filter = val; + virge->streams.k1_horiz_scale = val & 0x7ff; + if (val & (1 << 10)) + virge->streams.k1_horiz_scale |= 0xfffff800; + virge->streams.k2_horiz_scale = (val >> 16) & 0x7ff; + if ((val >> 16) & (1 << 10)) + virge->streams.k2_horiz_scale |= 0xfffff800; + break; + case 0x81a0: + virge->streams.blend_ctrl = val; + break; + case 0x81c0: + virge->streams.pri_fb0 = val & 0x7fffff; + svga_recalctimings(svga); + svga->fullchange = changeframecount; + break; + case 0x81c4: + virge->streams.pri_fb1 = val & 0x7fffff; + svga_recalctimings(svga); + svga->fullchange = changeframecount; + break; + case 0x81c8: + virge->streams.pri_stride = val & 0xfff; + svga_recalctimings(svga); + svga->fullchange = changeframecount; + break; + case 0x81cc: + virge->streams.buffer_ctrl = val; + svga_recalctimings(svga); + svga->fullchange = changeframecount; + break; + case 0x81d0: + virge->streams.sec_fb0 = val; + svga_recalctimings(svga); + svga->fullchange = changeframecount; + break; + case 0x81d4: + virge->streams.sec_fb1 = val; + svga_recalctimings(svga); + svga->fullchange = changeframecount; + break; + case 0x81d8: + virge->streams.sec_stride = val; + svga_recalctimings(svga); + svga->fullchange = changeframecount; + break; + case 0x81dc: + virge->streams.overlay_ctrl = val; + break; + case 0x81e0: + virge->streams.k1_vert_scale = val & 0x7ff; + if (val & (1 << 10)) + virge->streams.k1_vert_scale |= 0xfffff800; + break; + case 0x81e4: + virge->streams.k2_vert_scale = val & 0x7ff; + if (val & (1 << 10)) + virge->streams.k2_vert_scale |= 0xfffff800; + break; + case 0x81e8: + virge->streams.dda_vert_accumulator = val & 0xfff; + if (val & (1 << 11)) + virge->streams.dda_vert_accumulator |= 0xfffff800; + break; + case 0x81ec: + virge->streams.fifo_ctrl = val; + break; + case 0x81f0: + virge->streams.pri_start = val; + virge->streams.pri_x = (val >> 16) & 0x7ff; + virge->streams.pri_y = val & 0x7ff; + svga_recalctimings(svga); + svga->fullchange = changeframecount; + break; + case 0x81f4: + virge->streams.pri_size = val; + virge->streams.pri_w = (val >> 16) & 0x7ff; + virge->streams.pri_h = val & 0x7ff; + svga_recalctimings(svga); + svga->fullchange = changeframecount; + break; + case 0x81f8: + virge->streams.sec_start = val; + virge->streams.sec_x = (val >> 16) & 0x7ff; + virge->streams.sec_y = val & 0x7ff; + svga_recalctimings(svga); + svga->fullchange = changeframecount; + break; + case 0x81fc: + virge->streams.sec_size = val; + virge->streams.sec_w = (val >> 16) & 0x7ff; + virge->streams.sec_h = val & 0x7ff; + svga_recalctimings(svga); + svga->fullchange = changeframecount; + break; + + case 0x8504: + virge->subsys_stat &= ~(val & 0xff); + virge->subsys_cntl = (val >> 8); + s3_virge_update_irqs(virge); + break; + + case 0x850c: + virge->advfunc_cntl = val & 0xff; + s3_virge_updatemapping(virge); + break; + + default: + break; + } + } } -#define READ(addr, val) \ - { \ - switch (bpp) \ - { \ - case 0: /*8 bpp*/ \ - val = vram[addr & virge->vram_mask]; \ - break; \ - case 1: /*16 bpp*/ \ - val = *(uint16_t *)&vram[addr & virge->vram_mask]; \ - break; \ - case 2: /*24 bpp*/ \ - val = (*(uint32_t *)&vram[addr & virge->vram_mask]) & 0xffffff; \ - break; \ - } \ - } +#define READ(addr, val) \ + { \ + switch (bpp) { \ + case 0: /*8 bpp*/ \ + val = vram[addr & virge->vram_mask]; \ + break; \ + case 1: /*16 bpp*/ \ + val = *(uint16_t *) &vram[addr & virge->vram_mask]; \ + break; \ + case 2: /*24 bpp*/ \ + val = (*(uint32_t *) &vram[addr & virge->vram_mask]) & 0xffffff; \ + break; \ + } \ + } -#define CLIP(x, y) \ - { \ - if ((virge->s3d.cmd_set & CMD_SET_HC) && \ - (x < virge->s3d.clip_l || \ - x > virge->s3d.clip_r || \ - y < virge->s3d.clip_t || \ - y > virge->s3d.clip_b)) \ - update = 0; \ - } +#define CLIP(x, y) \ + { \ + if ((virge->s3d.cmd_set & CMD_SET_HC) && (x < virge->s3d.clip_l || x > virge->s3d.clip_r || y < virge->s3d.clip_t || y > virge->s3d.clip_b)) \ + update = 0; \ + } -#define CLIP_3D(x, y) \ - { \ - if ((s3d_tri->cmd_set & CMD_SET_HC) && \ - (x < s3d_tri->clip_l || \ - x > s3d_tri->clip_r || \ - y < s3d_tri->clip_t || \ - y > s3d_tri->clip_b)) \ - update = 0; \ - } - +#define CLIP_3D(x, y) \ + { \ + if ((s3d_tri->cmd_set & CMD_SET_HC) && (x < s3d_tri->clip_l || x > s3d_tri->clip_r || y < s3d_tri->clip_t || y > s3d_tri->clip_b)) \ + update = 0; \ + } -#define MIX() \ - { \ - int c; \ - for (c = 0; c < 24; c++) \ - { \ - int d = (dest & (1 << c)) ? 1 : 0; \ - if (source & (1 << c)) d |= 2; \ - if (pattern & (1 << c)) d |= 4; \ - if (virge->s3d.rop & (1 << d)) out |= (1 << c); \ - } \ - } +#define MIX() \ + { \ + int c; \ + for (c = 0; c < 24; c++) { \ + int d = (dest & (1 << c)) ? 1 : 0; \ + if (source & (1 << c)) \ + d |= 2; \ + if (pattern & (1 << c)) \ + d |= 4; \ + if (virge->s3d.rop & (1 << d)) \ + out |= (1 << c); \ + } \ + } -#define WRITE(addr, val) \ - { \ - switch (bpp) \ - { \ - case 0: /*8 bpp*/ \ - vram[addr & virge->vram_mask] = val; \ - svga->changedvram[(addr & virge->vram_mask) >> 12] = changeframecount; \ - break; \ - case 1: /*16 bpp*/ \ - *(uint16_t *)&vram[addr & virge->vram_mask] = val; \ - svga->changedvram[(addr & virge->vram_mask) >> 12] = changeframecount; \ - break; \ - case 2: /*24 bpp*/ \ - *(uint32_t *)&vram[addr & virge->vram_mask] = (val & 0xffffff) | \ - (vram[(addr + 3) & virge->vram_mask] << 24); \ - svga->changedvram[(addr & virge->vram_mask) >> 12] = changeframecount; \ - break; \ - } \ - } +#define WRITE(addr, val) \ + { \ + switch (bpp) { \ + case 0: /*8 bpp*/ \ + vram[addr & virge->vram_mask] = val; \ + svga->changedvram[(addr & virge->vram_mask) >> 12] = changeframecount; \ + break; \ + case 1: /*16 bpp*/ \ + *(uint16_t *) &vram[addr & virge->vram_mask] = val; \ + svga->changedvram[(addr & virge->vram_mask) >> 12] = changeframecount; \ + break; \ + case 2: /*24 bpp*/ \ + *(uint32_t *) &vram[addr & virge->vram_mask] = (val & 0xffffff) | (vram[(addr + 3) & virge->vram_mask] << 24); \ + svga->changedvram[(addr & virge->vram_mask) >> 12] = changeframecount; \ + break; \ + } \ + } -static void s3_virge_bitblt(virge_t *virge, int count, uint32_t cpu_dat) +static void +s3_virge_bitblt(virge_t *virge, int count, uint32_t cpu_dat) { - svga_t *svga = &virge->svga; - uint8_t *vram = virge->svga.vram; - uint32_t mono_pattern[64]; - int count_mask; - int x_inc = (virge->s3d.cmd_set & CMD_SET_XP) ? 1 : -1; - int y_inc = (virge->s3d.cmd_set & CMD_SET_YP) ? 1 : -1; - int bpp; - int x_mul; - int cpu_dat_shift; - uint32_t *pattern_data; - uint32_t src_fg_clr, src_bg_clr; - uint32_t src_addr; - uint32_t dest_addr; - uint32_t source = 0, dest = 0, pattern; - uint32_t out = 0; - int update; - - switch (virge->s3d.cmd_set & CMD_SET_FORMAT_MASK) - { - case CMD_SET_FORMAT_8: - bpp = 0; - x_mul = 1; - cpu_dat_shift = 8; - pattern_data = virge->s3d.pattern_8; - src_fg_clr = virge->s3d.src_fg_clr & 0xff; - src_bg_clr = virge->s3d.src_bg_clr & 0xff; - break; - case CMD_SET_FORMAT_16: - bpp = 1; - x_mul = 2; - cpu_dat_shift = 16; - pattern_data = virge->s3d.pattern_16; - src_fg_clr = virge->s3d.src_fg_clr & 0xffff; - src_bg_clr = virge->s3d.src_bg_clr & 0xffff; - break; - case CMD_SET_FORMAT_24: - default: - bpp = 2; - x_mul = 3; - cpu_dat_shift = 24; - pattern_data = virge->s3d.pattern_24; - src_fg_clr = virge->s3d.src_fg_clr; - src_bg_clr = virge->s3d.src_bg_clr; - break; + svga_t *svga = &virge->svga; + uint8_t *vram = virge->svga.vram; + uint32_t mono_pattern[64]; + int count_mask; + int x_inc = (virge->s3d.cmd_set & CMD_SET_XP) ? 1 : -1; + int y_inc = (virge->s3d.cmd_set & CMD_SET_YP) ? 1 : -1; + int bpp; + int x_mul; + int cpu_dat_shift; + const uint32_t *pattern_data; + uint32_t src_fg_clr; + uint32_t src_bg_clr; + uint32_t src_addr; + uint32_t dest_addr; + uint32_t source = 0; + uint32_t dest = 0; + uint32_t pattern; + uint32_t out = 0; + int update; + + switch (virge->s3d.cmd_set & CMD_SET_FORMAT_MASK) { + case CMD_SET_FORMAT_8: + bpp = 0; + x_mul = 1; + cpu_dat_shift = 8; + pattern_data = virge->s3d.pattern_8; + src_fg_clr = virge->s3d.src_fg_clr & 0xff; + src_bg_clr = virge->s3d.src_bg_clr & 0xff; + break; + case CMD_SET_FORMAT_16: + bpp = 1; + x_mul = 2; + cpu_dat_shift = 16; + pattern_data = virge->s3d.pattern_16; + src_fg_clr = virge->s3d.src_fg_clr & 0xffff; + src_bg_clr = virge->s3d.src_bg_clr & 0xffff; + break; + case CMD_SET_FORMAT_24: + default: + bpp = 2; + x_mul = 3; + cpu_dat_shift = 24; + pattern_data = virge->s3d.pattern_24; + src_fg_clr = virge->s3d.src_fg_clr; + src_bg_clr = virge->s3d.src_bg_clr; + break; + } + if (virge->s3d.cmd_set & CMD_SET_MP) + pattern_data = mono_pattern; + + switch (virge->s3d.cmd_set & CMD_SET_ITA_MASK) { + case CMD_SET_ITA_BYTE: + count_mask = ~0x7; + break; + case CMD_SET_ITA_WORD: + count_mask = ~0xf; + break; + case CMD_SET_ITA_DWORD: + default: + count_mask = ~0x1f; + break; + } + if (virge->s3d.cmd_set & CMD_SET_MP) { + for (uint8_t y = 0; y < 4; y++) { + for (uint8_t x = 0; x < 8; x++) { + if (virge->s3d.mono_pat_0 & (1 << (x + y * 8))) + mono_pattern[y * 8 + (7 - x)] = virge->s3d.pat_fg_clr; + else + mono_pattern[y * 8 + (7 - x)] = virge->s3d.pat_bg_clr; + if (virge->s3d.mono_pat_1 & (1 << (x + y * 8))) + mono_pattern[(y + 4) * 8 + (7 - x)] = virge->s3d.pat_fg_clr; + else + mono_pattern[(y + 4) * 8 + (7 - x)] = virge->s3d.pat_bg_clr; + } } - if (virge->s3d.cmd_set & CMD_SET_MP) - pattern_data = mono_pattern; - - switch (virge->s3d.cmd_set & CMD_SET_ITA_MASK) - { - case CMD_SET_ITA_BYTE: - count_mask = ~0x7; - break; - case CMD_SET_ITA_WORD: - count_mask = ~0xf; - break; - case CMD_SET_ITA_DWORD: - default: - count_mask = ~0x1f; - break; - } - if (virge->s3d.cmd_set & CMD_SET_MP) - { - int x, y; - for (y = 0; y < 4; y++) - { - for (x = 0; x < 8; x++) - { - if (virge->s3d.mono_pat_0 & (1 << (x + y*8))) - mono_pattern[y*8 + (7 - x)] = virge->s3d.pat_fg_clr; - else - mono_pattern[y*8 + (7 - x)] = virge->s3d.pat_bg_clr; - if (virge->s3d.mono_pat_1 & (1 << (x + y*8))) - mono_pattern[(y+4)*8 + (7 - x)] = virge->s3d.pat_fg_clr; - else - mono_pattern[(y+4)*8 + (7 - x)] = virge->s3d.pat_bg_clr; + } + switch (virge->s3d.cmd_set & CMD_SET_COMMAND_MASK) { + case CMD_SET_COMMAND_BITBLT: + if (count == -1) { + virge->s3d.src_x = virge->s3d.rsrc_x; + virge->s3d.src_y = virge->s3d.rsrc_y; + virge->s3d.dest_x = virge->s3d.rdest_x; + virge->s3d.dest_y = virge->s3d.rdest_y; + virge->s3d.w = virge->s3d.r_width; + virge->s3d.h = virge->s3d.r_height; + virge->s3d.rop = (virge->s3d.cmd_set >> 17) & 0xff; + virge->s3d.data_left_count = 0; + + s3_virge_log("BitBlt start src_x=%i,src_y=%i,dest_x=%i,dest_y=%i,w=%i,h=%i,rop=%02X,src_base=%x,dest_base=%x\n", + virge->s3d.src_x, + virge->s3d.src_y, + virge->s3d.dest_x, + virge->s3d.dest_y, + virge->s3d.w, + virge->s3d.h, + virge->s3d.rop, + virge->s3d.src_base, + virge->s3d.dest_base); + + if (virge->s3d.cmd_set & CMD_SET_IDS) + return; + } + if (!virge->s3d.h) + return; + while (count) { + src_addr = virge->s3d.src_base + (virge->s3d.src_x * x_mul) + (virge->s3d.src_y * virge->s3d.src_str); + dest_addr = virge->s3d.dest_base + (virge->s3d.dest_x * x_mul) + (virge->s3d.dest_y * virge->s3d.dest_str); + out = 0; + update = 1; + + switch (virge->s3d.cmd_set & (CMD_SET_MS | CMD_SET_IDS)) { + case 0: + case CMD_SET_MS: + READ(src_addr, source); + if ((virge->s3d.cmd_set & CMD_SET_TP) && source == src_fg_clr) + update = 0; + break; + case CMD_SET_IDS: + if (virge->s3d.data_left_count) { + /*Handle shifting for 24-bit data*/ + source = virge->s3d.data_left; + source |= ((cpu_dat << virge->s3d.data_left_count) & ~0xff000000); + cpu_dat >>= (cpu_dat_shift - virge->s3d.data_left_count); + count -= (cpu_dat_shift - virge->s3d.data_left_count); + virge->s3d.data_left_count = 0; + if (count < cpu_dat_shift) { + virge->s3d.data_left = cpu_dat; + virge->s3d.data_left_count = count; + count = 0; + } + } else { + source = cpu_dat; + cpu_dat >>= cpu_dat_shift; + count -= cpu_dat_shift; + if (count < cpu_dat_shift) { + virge->s3d.data_left = cpu_dat; + virge->s3d.data_left_count = count; + count = 0; + } } - } - } - switch (virge->s3d.cmd_set & CMD_SET_COMMAND_MASK) - { - case CMD_SET_COMMAND_BITBLT: - if (count == -1) - { - virge->s3d.src_x = virge->s3d.rsrc_x; - virge->s3d.src_y = virge->s3d.rsrc_y; - virge->s3d.dest_x = virge->s3d.rdest_x; - virge->s3d.dest_y = virge->s3d.rdest_y; - virge->s3d.w = virge->s3d.r_width; - virge->s3d.h = virge->s3d.r_height; - virge->s3d.rop = (virge->s3d.cmd_set >> 17) & 0xff; - virge->s3d.data_left_count = 0; - - s3_virge_log("BitBlt start src_x=%i,src_y=%i,dest_x=%i,dest_y=%i,w=%i,h=%i,rop=%02X,src_base=%x,dest_base=%x\n", - virge->s3d.src_x, - virge->s3d.src_y, - virge->s3d.dest_x, - virge->s3d.dest_y, - virge->s3d.w, - virge->s3d.h, - virge->s3d.rop, - virge->s3d.src_base, - virge->s3d.dest_base); - - if (virge->s3d.cmd_set & CMD_SET_IDS) - return; - } - if (!virge->s3d.h) - return; - while (count) - { - src_addr = virge->s3d.src_base + (virge->s3d.src_x * x_mul) + (virge->s3d.src_y * virge->s3d.src_str); - dest_addr = virge->s3d.dest_base + (virge->s3d.dest_x * x_mul) + (virge->s3d.dest_y * virge->s3d.dest_str); - out = 0; - update = 1; - - switch (virge->s3d.cmd_set & (CMD_SET_MS | CMD_SET_IDS)) - { - case 0: - case CMD_SET_MS: - READ(src_addr, source); - if ((virge->s3d.cmd_set & CMD_SET_TP) && source == src_fg_clr) - update = 0; - break; - case CMD_SET_IDS: - if (virge->s3d.data_left_count) - { - /*Handle shifting for 24-bit data*/ - source = virge->s3d.data_left; - source |= ((cpu_dat << virge->s3d.data_left_count) & ~0xff000000); - cpu_dat >>= (cpu_dat_shift - virge->s3d.data_left_count); - count -= (cpu_dat_shift - virge->s3d.data_left_count); - virge->s3d.data_left_count = 0; - if (count < cpu_dat_shift) - { - virge->s3d.data_left = cpu_dat; - virge->s3d.data_left_count = count; - count = 0; - } - } - else - { - source = cpu_dat; - cpu_dat >>= cpu_dat_shift; - count -= cpu_dat_shift; - if (count < cpu_dat_shift) - { - virge->s3d.data_left = cpu_dat; - virge->s3d.data_left_count = count; - count = 0; - } - } - if ((virge->s3d.cmd_set & CMD_SET_TP) && source == src_fg_clr) - update = 0; - break; - case CMD_SET_IDS | CMD_SET_MS: - source = (cpu_dat & (1 << 31)) ? src_fg_clr : src_bg_clr; - if ((virge->s3d.cmd_set & CMD_SET_TP) && !(cpu_dat & (1 << 31))) - update = 0; - cpu_dat <<= 1; - count--; - break; - } - - CLIP(virge->s3d.dest_x, virge->s3d.dest_y); - - if (update) - { - READ(dest_addr, dest); - pattern = pattern_data[(virge->s3d.dest_y & 7)*8 + (virge->s3d.dest_x & 7)]; - MIX(); - - WRITE(dest_addr, out); - } - - virge->s3d.src_x += x_inc; - virge->s3d.src_x &= 0x7ff; - virge->s3d.dest_x += x_inc; - virge->s3d.dest_x &= 0x7ff; - if (!virge->s3d.w) - { - virge->s3d.src_x = virge->s3d.rsrc_x; - virge->s3d.dest_x = virge->s3d.rdest_x; - virge->s3d.w = virge->s3d.r_width; - - virge->s3d.src_y += y_inc; - virge->s3d.dest_y += y_inc; - virge->s3d.h--; - - switch (virge->s3d.cmd_set & (CMD_SET_MS | CMD_SET_IDS)) - { - case CMD_SET_IDS: - cpu_dat >>= (count - (count & count_mask)); - count &= count_mask; - virge->s3d.data_left_count = 0; - break; - - case CMD_SET_IDS | CMD_SET_MS: - cpu_dat <<= (count - (count & count_mask)); - count &= count_mask; - break; - } - if (!virge->s3d.h) - { - return; - } - } - else - virge->s3d.w--; - } - break; - - case CMD_SET_COMMAND_RECTFILL: - /*No source, pattern = pat_fg_clr*/ - if (count == -1) - { - virge->s3d.src_x = virge->s3d.rsrc_x; - virge->s3d.src_y = virge->s3d.rsrc_y; - virge->s3d.dest_x = virge->s3d.rdest_x; - virge->s3d.dest_y = virge->s3d.rdest_y; - virge->s3d.w = virge->s3d.r_width; - virge->s3d.h = virge->s3d.r_height; - virge->s3d.rop = (virge->s3d.cmd_set >> 17) & 0xff; - - s3_virge_log("RctFll start %i,%i %i,%i %02X %08x\n", virge->s3d.dest_x, - virge->s3d.dest_y, - virge->s3d.w, - virge->s3d.h, - virge->s3d.rop, virge->s3d.dest_base); - } - - while (count && virge->s3d.h) - { - source = virge->s3d.pat_fg_clr; - dest_addr = virge->s3d.dest_base + (virge->s3d.dest_x * x_mul) + (virge->s3d.dest_y * virge->s3d.dest_str); - pattern = virge->s3d.pat_fg_clr; - out = 0; - update = 1; - - CLIP(virge->s3d.dest_x, virge->s3d.dest_y); - - if (update) - { - READ(dest_addr, dest); - - MIX(); - - WRITE(dest_addr, out); - } - - virge->s3d.src_x += x_inc; - virge->s3d.src_x &= 0x7ff; - virge->s3d.dest_x += x_inc; - virge->s3d.dest_x &= 0x7ff; - if (!virge->s3d.w) - { - virge->s3d.src_x = virge->s3d.rsrc_x; - virge->s3d.dest_x = virge->s3d.rdest_x; - virge->s3d.w = virge->s3d.r_width; - - virge->s3d.src_y += y_inc; - virge->s3d.dest_y += y_inc; - virge->s3d.h--; - if (!virge->s3d.h) - { - return; - } - } - else - virge->s3d.w--; + if ((virge->s3d.cmd_set & CMD_SET_TP) && source == src_fg_clr) + update = 0; + break; + case CMD_SET_IDS | CMD_SET_MS: + source = (cpu_dat & (1 << 31)) ? src_fg_clr : src_bg_clr; + if ((virge->s3d.cmd_set & CMD_SET_TP) && !(cpu_dat & (1 << 31))) + update = 0; + cpu_dat <<= 1; count--; + break; + + default: + break; } - break; - - case CMD_SET_COMMAND_LINE: - if (count == -1) - { - virge->s3d.dest_x = virge->s3d.lxstart; - virge->s3d.dest_y = virge->s3d.lystart; - virge->s3d.h = virge->s3d.lycnt; - virge->s3d.rop = (virge->s3d.cmd_set >> 17) & 0xff; + + CLIP(virge->s3d.dest_x, virge->s3d.dest_y); + + if (update) { + READ(dest_addr, dest); + pattern = pattern_data[(virge->s3d.dest_y & 7) * 8 + (virge->s3d.dest_x & 7)]; + MIX(); + + WRITE(dest_addr, out); } - while (virge->s3d.h) - { - int x; - int new_x; - int first_pixel = 1; - - x = virge->s3d.dest_x >> 20; - if (virge->s3d.h == virge->s3d.lycnt && - ((virge->s3d.line_dir && x > virge->s3d.lxend0) || - (!virge->s3d.line_dir && x < virge->s3d.lxend0))) - x = virge->s3d.lxend0; + virge->s3d.src_x += x_inc; + virge->s3d.src_x &= 0x7ff; + virge->s3d.dest_x += x_inc; + virge->s3d.dest_x &= 0x7ff; + if (!virge->s3d.w) { + virge->s3d.src_x = virge->s3d.rsrc_x; + virge->s3d.dest_x = virge->s3d.rdest_x; + virge->s3d.w = virge->s3d.r_width; - if (virge->s3d.h == 1) - new_x = virge->s3d.lxend1 + (virge->s3d.line_dir ? 1 : -1); - else - new_x = (virge->s3d.dest_x + virge->s3d.ldx) >> 20; + virge->s3d.src_y += y_inc; + virge->s3d.dest_y += y_inc; + virge->s3d.h--; - - if ((virge->s3d.line_dir && x > new_x) || - (!virge->s3d.line_dir && x < new_x)) - goto skip_line; - - do - { - uint32_t dest_addr = virge->s3d.dest_base + (x * x_mul) + (virge->s3d.dest_y * virge->s3d.dest_str); - uint32_t source = 0, dest = 0, pattern; - uint32_t out = 0; - int update = 1; + switch (virge->s3d.cmd_set & (CMD_SET_MS | CMD_SET_IDS)) { + case CMD_SET_IDS: + cpu_dat >>= (count - (count & count_mask)); + count &= count_mask; + virge->s3d.data_left_count = 0; + break; - if ((virge->s3d.h == virge->s3d.lycnt || !first_pixel) && - ((virge->s3d.line_dir && x < virge->s3d.lxend0) || - (!virge->s3d.line_dir && x > virge->s3d.lxend0))) - update = 0; + case CMD_SET_IDS | CMD_SET_MS: + cpu_dat <<= (count - (count & count_mask)); + count &= count_mask; + break; - if ((virge->s3d.h == 1 || !first_pixel) && - ((virge->s3d.line_dir && x > virge->s3d.lxend1) || - (!virge->s3d.line_dir && x < virge->s3d.lxend1))) - update = 0; + default: + break; + } + if (!virge->s3d.h) { + return; + } + } else + virge->s3d.w--; + } + break; - CLIP(x, virge->s3d.dest_y); + case CMD_SET_COMMAND_RECTFILL: + /*No source, pattern = pat_fg_clr*/ + if (count == -1) { + virge->s3d.src_x = virge->s3d.rsrc_x; + virge->s3d.src_y = virge->s3d.rsrc_y; + virge->s3d.dest_x = virge->s3d.rdest_x; + virge->s3d.dest_y = virge->s3d.rdest_y; + virge->s3d.w = virge->s3d.r_width; + virge->s3d.h = virge->s3d.r_height; + virge->s3d.rop = (virge->s3d.cmd_set >> 17) & 0xff; - if (update) - { - READ(dest_addr, dest); - pattern = virge->s3d.pat_fg_clr; + s3_virge_log("RctFll start %i,%i %i,%i %02X %08x\n", virge->s3d.dest_x, + virge->s3d.dest_y, + virge->s3d.w, + virge->s3d.h, + virge->s3d.rop, virge->s3d.dest_base); + } - MIX(); + while (count && virge->s3d.h) { + source = virge->s3d.pat_fg_clr; + dest_addr = virge->s3d.dest_base + (virge->s3d.dest_x * x_mul) + (virge->s3d.dest_y * virge->s3d.dest_str); + pattern = virge->s3d.pat_fg_clr; + out = 0; + update = 1; - WRITE(dest_addr, out); - } - - if (x < new_x) - x++; - else if (x > new_x) - x--; - first_pixel = 0; - } while (x != new_x); + CLIP(virge->s3d.dest_x, virge->s3d.dest_y); + + if (update) { + READ(dest_addr, dest); + + MIX(); + + WRITE(dest_addr, out); + } + + virge->s3d.src_x += x_inc; + virge->s3d.src_x &= 0x7ff; + virge->s3d.dest_x += x_inc; + virge->s3d.dest_x &= 0x7ff; + if (!virge->s3d.w) { + virge->s3d.src_x = virge->s3d.rsrc_x; + virge->s3d.dest_x = virge->s3d.rdest_x; + virge->s3d.w = virge->s3d.r_width; + + virge->s3d.src_y += y_inc; + virge->s3d.dest_y += y_inc; + virge->s3d.h--; + if (!virge->s3d.h) { + return; + } + } else + virge->s3d.w--; + count--; + } + break; + + case CMD_SET_COMMAND_LINE: + if (count == -1) { + virge->s3d.dest_x = virge->s3d.lxstart; + virge->s3d.dest_y = virge->s3d.lystart; + virge->s3d.h = virge->s3d.lycnt; + virge->s3d.rop = (virge->s3d.cmd_set >> 17) & 0xff; + } + while (virge->s3d.h) { + int x; + int new_x; + int first_pixel = 1; + + x = virge->s3d.dest_x >> 20; + + if (virge->s3d.h == virge->s3d.lycnt && ((virge->s3d.line_dir && x > virge->s3d.lxend0) || (!virge->s3d.line_dir && x < virge->s3d.lxend0))) + x = virge->s3d.lxend0; + + if (virge->s3d.h == 1) + new_x = virge->s3d.lxend1 + (virge->s3d.line_dir ? 1 : -1); + else + new_x = (virge->s3d.dest_x + virge->s3d.ldx) >> 20; + + if ((virge->s3d.line_dir && x > new_x) || (!virge->s3d.line_dir && x < new_x)) + goto skip_line; + + do { + uint32_t dest_addr = virge->s3d.dest_base + (x * x_mul) + (virge->s3d.dest_y * virge->s3d.dest_str); + uint32_t source = 0; + uint32_t dest = 0; + uint32_t pattern; + uint32_t out = 0; + int update = 1; + + if ((virge->s3d.h == virge->s3d.lycnt || !first_pixel) && ((virge->s3d.line_dir && x < virge->s3d.lxend0) || (!virge->s3d.line_dir && x > virge->s3d.lxend0))) + update = 0; + + if ((virge->s3d.h == 1 || !first_pixel) && ((virge->s3d.line_dir && x > virge->s3d.lxend1) || (!virge->s3d.line_dir && x < virge->s3d.lxend1))) + update = 0; + + CLIP(x, virge->s3d.dest_y); + + if (update) { + READ(dest_addr, dest); + pattern = virge->s3d.pat_fg_clr; + + MIX(); + + WRITE(dest_addr, out); + } + + if (x < new_x) + x++; + else if (x > new_x) + x--; + first_pixel = 0; + } while (x != new_x); skip_line: - virge->s3d.dest_x += virge->s3d.ldx; - virge->s3d.dest_y--; - virge->s3d.h--; - } - break; + virge->s3d.dest_x += virge->s3d.ldx; + virge->s3d.dest_y--; + virge->s3d.h--; + } + break; - case CMD_SET_COMMAND_POLY: - /*No source*/ - if (virge->s3d.pycnt & (1 << 28)) - virge->s3d.dest_r = virge->s3d.prxstart; - if (virge->s3d.pycnt & (1 << 29)) - virge->s3d.dest_l = virge->s3d.plxstart; - virge->s3d.h = virge->s3d.pycnt & 0x7ff; - virge->s3d.rop = (virge->s3d.cmd_set >> 17) & 0xff; - while (virge->s3d.h) - { - int x = virge->s3d.dest_l >> 20; - int xend = virge->s3d.dest_r >> 20; - int y = virge->s3d.pystart & 0x7ff; - int xdir = (x < xend) ? 1 : -1; - do - { - uint32_t dest_addr = virge->s3d.dest_base + (x * x_mul) + (y * virge->s3d.dest_str); - uint32_t source = 0, dest = 0, pattern; - uint32_t out = 0; - int update = 1; + case CMD_SET_COMMAND_POLY: + /*No source*/ + if (virge->s3d.pycnt & (1 << 28)) + virge->s3d.dest_r = virge->s3d.prxstart; + if (virge->s3d.pycnt & (1 << 29)) + virge->s3d.dest_l = virge->s3d.plxstart; + virge->s3d.h = virge->s3d.pycnt & 0x7ff; + virge->s3d.rop = (virge->s3d.cmd_set >> 17) & 0xff; + while (virge->s3d.h) { + int x = virge->s3d.dest_l >> 20; + int xend = virge->s3d.dest_r >> 20; + int y = virge->s3d.pystart & 0x7ff; + int xdir = (x < xend) ? 1 : -1; + do { + uint32_t dest_addr = virge->s3d.dest_base + (x * x_mul) + (y * virge->s3d.dest_str); + uint32_t source = 0; + uint32_t dest = 0; + uint32_t pattern; + uint32_t out = 0; + int update = 1; - CLIP(x, y); + CLIP(x, y); - if (update) - { - READ(dest_addr, dest); - pattern = pattern_data[(y & 7)*8 + (x & 7)]; - MIX(); + if (update) { + READ(dest_addr, dest); + pattern = pattern_data[(y & 7) * 8 + (x & 7)]; + MIX(); - WRITE(dest_addr, out); - } - - x = (x + xdir) & 0x7ff; - } - while (x != (xend + xdir)); + WRITE(dest_addr, out); + } - virge->s3d.dest_l += virge->s3d.pldx; - virge->s3d.dest_r += virge->s3d.prdx; - virge->s3d.h--; - virge->s3d.pystart = (virge->s3d.pystart - 1) & 0x7ff; - } - break; + x = (x + xdir) & 0x7ff; + } while (x != (xend + xdir)); - case CMD_SET_COMMAND_NOP: - break; - } + virge->s3d.dest_l += virge->s3d.pldx; + virge->s3d.dest_r += virge->s3d.prdx; + virge->s3d.h--; + virge->s3d.pystart = (virge->s3d.pystart - 1) & 0x7ff; + } + break; + + case CMD_SET_COMMAND_NOP: + break; + + default: + break; + } } -#define RGB15_TO_24(val, r, g, b) b = ((val & 0x001f) << 3) | ((val & 0x001f) >> 2); \ - g = ((val & 0x03e0) >> 2) | ((val & 0x03e0) >> 7); \ - r = ((val & 0x7c00) >> 7) | ((val & 0x7c00) >> 12); +#define RGB15_TO_24(val, r, g, b) \ + b = ((val & 0x001f) << 3) | ((val & 0x001f) >> 2); \ + g = ((val & 0x03e0) >> 2) | ((val & 0x03e0) >> 7); \ + r = ((val & 0x7c00) >> 7) | ((val & 0x7c00) >> 12); -#define RGB24_TO_24(val, r, g, b) b = val & 0xff; \ - g = (val & 0xff00) >> 8; \ - r = (val & 0xff0000) >> 16 +#define RGB24_TO_24(val, r, g, b) \ + b = val & 0xff; \ + g = (val & 0xff00) >> 8; \ + r = (val & 0xff0000) >> 16 -#define RGB15(r, g, b, dest) \ - if (virge->dithering_enabled) \ - { \ - int add = dither[_y & 3][_x & 3]; \ - int _r = (r > 248) ? 248 : r+add; \ - int _g = (g > 248) ? 248 : g+add; \ - int _b = (b > 248) ? 248 : b+add; \ - dest = ((_b >> 3) & 0x1f) | (((_g >> 3) & 0x1f) << 5) | (((_r >> 3) & 0x1f) << 10); \ - } \ - else \ - dest = ((b >> 3) & 0x1f) | (((g >> 3) & 0x1f) << 5) | (((r >> 3) & 0x1f) << 10) +#define RGB15(r, g, b, dest) \ + if (virge->dithering_enabled) { \ + int add = dither[_y & 3][_x & 3]; \ + int _r = (r > 248) ? 248 : r + add; \ + int _g = (g > 248) ? 248 : g + add; \ + int _b = (b > 248) ? 248 : b + add; \ + dest = ((_b >> 3) & 0x1f) | (((_g >> 3) & 0x1f) << 5) | (((_r >> 3) & 0x1f) << 10); \ + } else \ + dest = ((b >> 3) & 0x1f) | (((g >> 3) & 0x1f) << 5) | (((r >> 3) & 0x1f) << 10) #define RGB24(r, g, b) ((b) | ((g) << 8) | ((r) << 16)) -typedef struct rgba_t -{ - int r, g, b, a; +typedef struct rgba_t { + int r, g, b, a; } rgba_t; -typedef struct s3d_state_t -{ - int32_t r, g, b, a, u, v, d, w; +typedef struct s3d_state_t { + int32_t r, g, b, a, u, v, d, w; - int32_t base_r, base_g, base_b, base_a, base_u, base_v, base_d, base_w; - - uint32_t base_z; + int32_t base_r, base_g, base_b, base_a, base_u, base_v, base_d, base_w; - uint32_t tbu, tbv; + uint32_t base_z; - uint32_t cmd_set; - int max_d; - - uint16_t *texture[10]; - - uint32_t tex_bdr_clr; - - int32_t x1, x2; - int y; - - rgba_t dest_rgba; + uint32_t tbu, tbv; + + uint32_t cmd_set; + int max_d; + + uint16_t *texture[10]; + + uint32_t tex_bdr_clr; + + int32_t x1, x2; + int y; + + rgba_t dest_rgba; } s3d_state_t; -typedef struct s3d_texture_state_t -{ - int level; - int texture_shift; - - int32_t u, v; +typedef struct s3d_texture_state_t { + int level; + int texture_shift; + + int32_t u, v; } s3d_texture_state_t; static void (*tex_read)(s3d_state_t *state, s3d_texture_state_t *texture_state, rgba_t *out); @@ -2306,2204 +2518,2397 @@ static void (*dest_pixel)(s3d_state_t *state); #define MAX(a, b) ((a) > (b) ? (a) : (b)) #define MIN(a, b) ((a) < (b) ? (a) : (b)) -static int _x, _y; +static int _x; +static int _y; -static void tex_ARGB1555(s3d_state_t *state, s3d_texture_state_t *texture_state, rgba_t *out) +static void +tex_ARGB1555(s3d_state_t *state, s3d_texture_state_t *texture_state, rgba_t *out) { - int offset = ((texture_state->u & 0x7fc0000) >> texture_state->texture_shift) + - (((texture_state->v & 0x7fc0000) >> texture_state->texture_shift) << texture_state->level); - uint16_t val = state->texture[texture_state->level][offset]; + int offset = ((texture_state->u & 0x7fc0000) >> texture_state->texture_shift) + (((texture_state->v & 0x7fc0000) >> texture_state->texture_shift) << texture_state->level); + uint16_t val = state->texture[texture_state->level][offset]; - out->r = ((val & 0x7c00) >> 7) | ((val & 0x7000) >> 12); - out->g = ((val & 0x03e0) >> 2) | ((val & 0x0380) >> 7); - out->b = ((val & 0x001f) << 3) | ((val & 0x001c) >> 2); - out->a = (val & 0x8000) ? 0xff : 0; + out->r = ((val & 0x7c00) >> 7) | ((val & 0x7000) >> 12); + out->g = ((val & 0x03e0) >> 2) | ((val & 0x0380) >> 7); + out->b = ((val & 0x001f) << 3) | ((val & 0x001c) >> 2); + out->a = (val & 0x8000) ? 0xff : 0; } -static void tex_ARGB1555_nowrap(s3d_state_t *state, s3d_texture_state_t *texture_state, rgba_t *out) +static void +tex_ARGB1555_nowrap(s3d_state_t *state, s3d_texture_state_t *texture_state, rgba_t *out) { - int offset = ((texture_state->u & 0x7fc0000) >> texture_state->texture_shift) + - (((texture_state->v & 0x7fc0000) >> texture_state->texture_shift) << texture_state->level); - uint16_t val = state->texture[texture_state->level][offset]; + int offset = ((texture_state->u & 0x7fc0000) >> texture_state->texture_shift) + (((texture_state->v & 0x7fc0000) >> texture_state->texture_shift) << texture_state->level); + uint16_t val = state->texture[texture_state->level][offset]; - if (((texture_state->u | texture_state->v) & 0xf8000000) == 0xf8000000) - val = state->tex_bdr_clr; + if (((texture_state->u | texture_state->v) & 0xf8000000) == 0xf8000000) + val = state->tex_bdr_clr; - out->r = ((val & 0x7c00) >> 7) | ((val & 0x7000) >> 12); - out->g = ((val & 0x03e0) >> 2) | ((val & 0x0380) >> 7); - out->b = ((val & 0x001f) << 3) | ((val & 0x001c) >> 2); - out->a = (val & 0x8000) ? 0xff : 0; + out->r = ((val & 0x7c00) >> 7) | ((val & 0x7000) >> 12); + out->g = ((val & 0x03e0) >> 2) | ((val & 0x0380) >> 7); + out->b = ((val & 0x001f) << 3) | ((val & 0x001c) >> 2); + out->a = (val & 0x8000) ? 0xff : 0; } -static void tex_ARGB4444(s3d_state_t *state, s3d_texture_state_t *texture_state, rgba_t *out) +static void +tex_ARGB4444(s3d_state_t *state, s3d_texture_state_t *texture_state, rgba_t *out) { - int offset = ((texture_state->u & 0x7fc0000) >> texture_state->texture_shift) + - (((texture_state->v & 0x7fc0000) >> texture_state->texture_shift) << texture_state->level); - uint16_t val = state->texture[texture_state->level][offset]; + int offset = ((texture_state->u & 0x7fc0000) >> texture_state->texture_shift) + (((texture_state->v & 0x7fc0000) >> texture_state->texture_shift) << texture_state->level); + uint16_t val = state->texture[texture_state->level][offset]; - out->r = ((val & 0x0f00) >> 4) | ((val & 0x0f00) >> 8); - out->g = (val & 0x00f0) | ((val & 0x00f0) >> 4); - out->b = ((val & 0x000f) << 4) | (val & 0x000f); - out->a = ((val & 0xf000) >> 8) | ((val & 0xf000) >> 12); + out->r = ((val & 0x0f00) >> 4) | ((val & 0x0f00) >> 8); + out->g = (val & 0x00f0) | ((val & 0x00f0) >> 4); + out->b = ((val & 0x000f) << 4) | (val & 0x000f); + out->a = ((val & 0xf000) >> 8) | ((val & 0xf000) >> 12); } -static void tex_ARGB4444_nowrap(s3d_state_t *state, s3d_texture_state_t *texture_state, rgba_t *out) +static void +tex_ARGB4444_nowrap(s3d_state_t *state, s3d_texture_state_t *texture_state, rgba_t *out) { - int offset = ((texture_state->u & 0x7fc0000) >> texture_state->texture_shift) + - (((texture_state->v & 0x7fc0000) >> texture_state->texture_shift) << texture_state->level); - uint16_t val = state->texture[texture_state->level][offset]; + int offset = ((texture_state->u & 0x7fc0000) >> texture_state->texture_shift) + (((texture_state->v & 0x7fc0000) >> texture_state->texture_shift) << texture_state->level); + uint16_t val = state->texture[texture_state->level][offset]; - if (((texture_state->u | texture_state->v) & 0xf8000000) == 0xf8000000) - val = state->tex_bdr_clr; + if (((texture_state->u | texture_state->v) & 0xf8000000) == 0xf8000000) + val = state->tex_bdr_clr; - out->r = ((val & 0x0f00) >> 4) | ((val & 0x0f00) >> 8); - out->g = (val & 0x00f0) | ((val & 0x00f0) >> 4); - out->b = ((val & 0x000f) << 4) | (val & 0x000f); - out->a = ((val & 0xf000) >> 8) | ((val & 0xf000) >> 12); + out->r = ((val & 0x0f00) >> 4) | ((val & 0x0f00) >> 8); + out->g = (val & 0x00f0) | ((val & 0x00f0) >> 4); + out->b = ((val & 0x000f) << 4) | (val & 0x000f); + out->a = ((val & 0xf000) >> 8) | ((val & 0xf000) >> 12); } -static void tex_ARGB8888(s3d_state_t *state, s3d_texture_state_t *texture_state, rgba_t *out) +static void +tex_ARGB8888(s3d_state_t *state, s3d_texture_state_t *texture_state, rgba_t *out) { - int offset = ((texture_state->u & 0x7fc0000) >> texture_state->texture_shift) + - (((texture_state->v & 0x7fc0000) >> texture_state->texture_shift) << texture_state->level); - uint32_t val = ((uint32_t *)state->texture[texture_state->level])[offset]; + int offset = ((texture_state->u & 0x7fc0000) >> texture_state->texture_shift) + (((texture_state->v & 0x7fc0000) >> texture_state->texture_shift) << texture_state->level); + uint32_t val = ((uint32_t *) state->texture[texture_state->level])[offset]; - out->r = (val >> 16) & 0xff; - out->g = (val >> 8) & 0xff; - out->b = val & 0xff; - out->a = (val >> 24) & 0xff; + out->r = (val >> 16) & 0xff; + out->g = (val >> 8) & 0xff; + out->b = val & 0xff; + out->a = (val >> 24) & 0xff; } -static void tex_ARGB8888_nowrap(s3d_state_t *state, s3d_texture_state_t *texture_state, rgba_t *out) +static void +tex_ARGB8888_nowrap(s3d_state_t *state, s3d_texture_state_t *texture_state, rgba_t *out) { - int offset = ((texture_state->u & 0x7fc0000) >> texture_state->texture_shift) + - (((texture_state->v & 0x7fc0000) >> texture_state->texture_shift) << texture_state->level); - uint32_t val = ((uint32_t *)state->texture[texture_state->level])[offset]; + int offset = ((texture_state->u & 0x7fc0000) >> texture_state->texture_shift) + (((texture_state->v & 0x7fc0000) >> texture_state->texture_shift) << texture_state->level); + uint32_t val = ((uint32_t *) state->texture[texture_state->level])[offset]; - if (((texture_state->u | texture_state->v) & 0xf8000000) == 0xf8000000) - val = state->tex_bdr_clr; + if (((texture_state->u | texture_state->v) & 0xf8000000) == 0xf8000000) + val = state->tex_bdr_clr; - out->r = (val >> 16) & 0xff; - out->g = (val >> 8) & 0xff; - out->b = val & 0xff; - out->a = (val >> 24) & 0xff; + out->r = (val >> 16) & 0xff; + out->g = (val >> 8) & 0xff; + out->b = val & 0xff; + out->a = (val >> 24) & 0xff; } -static void tex_sample_normal(s3d_state_t *state) +static void +tex_sample_normal(s3d_state_t *state) { - s3d_texture_state_t texture_state; - - texture_state.level = state->max_d; - texture_state.texture_shift = 18 + (9 - texture_state.level); - texture_state.u = state->u + state->tbu; - texture_state.v = state->v + state->tbv; + s3d_texture_state_t texture_state; - tex_read(state, &texture_state, &state->dest_rgba); + texture_state.level = state->max_d; + texture_state.texture_shift = 18 + (9 - texture_state.level); + texture_state.u = state->u + state->tbu; + texture_state.v = state->v + state->tbv; + + tex_read(state, &texture_state, &state->dest_rgba); } -static void tex_sample_normal_filter(s3d_state_t *state) +static void +tex_sample_normal_filter(s3d_state_t *state) { - s3d_texture_state_t texture_state; - int tex_offset; - rgba_t tex_samples[4]; - int du, dv; - int d[4]; + s3d_texture_state_t texture_state; + int tex_offset; + rgba_t tex_samples[4]; + int du; + int dv; + int d[4]; - texture_state.level = state->max_d; - texture_state.texture_shift = 18 + (9 - texture_state.level); - tex_offset = 1 << texture_state.texture_shift; + texture_state.level = state->max_d; + texture_state.texture_shift = 18 + (9 - texture_state.level); + tex_offset = 1 << texture_state.texture_shift; - texture_state.u = state->u + state->tbu; - texture_state.v = state->v + state->tbv; - tex_read(state, &texture_state, &tex_samples[0]); - du = (texture_state.u >> (texture_state.texture_shift - 8)) & 0xff; - dv = (texture_state.v >> (texture_state.texture_shift - 8)) & 0xff; + texture_state.u = state->u + state->tbu; + texture_state.v = state->v + state->tbv; + tex_read(state, &texture_state, &tex_samples[0]); + du = (texture_state.u >> (texture_state.texture_shift - 8)) & 0xff; + dv = (texture_state.v >> (texture_state.texture_shift - 8)) & 0xff; - texture_state.u = state->u + state->tbu + tex_offset; - texture_state.v = state->v + state->tbv; - tex_read(state, &texture_state, &tex_samples[1]); + texture_state.u = state->u + state->tbu + tex_offset; + texture_state.v = state->v + state->tbv; + tex_read(state, &texture_state, &tex_samples[1]); - texture_state.u = state->u + state->tbu; - texture_state.v = state->v + state->tbv + tex_offset; - tex_read(state, &texture_state, &tex_samples[2]); + texture_state.u = state->u + state->tbu; + texture_state.v = state->v + state->tbv + tex_offset; + tex_read(state, &texture_state, &tex_samples[2]); - texture_state.u = state->u + state->tbu + tex_offset; - texture_state.v = state->v + state->tbv + tex_offset; - tex_read(state, &texture_state, &tex_samples[3]); - - d[0] = (256 - du) * (256 - dv); - d[1] = du * (256 - dv); - d[2] = (256 - du) * dv; - d[3] = du * dv; - - state->dest_rgba.r = (tex_samples[0].r * d[0] + tex_samples[1].r * d[1] + tex_samples[2].r * d[2] + tex_samples[3].r * d[3]) >> 16; - state->dest_rgba.g = (tex_samples[0].g * d[0] + tex_samples[1].g * d[1] + tex_samples[2].g * d[2] + tex_samples[3].g * d[3]) >> 16; - state->dest_rgba.b = (tex_samples[0].b * d[0] + tex_samples[1].b * d[1] + tex_samples[2].b * d[2] + tex_samples[3].b * d[3]) >> 16; - state->dest_rgba.a = (tex_samples[0].a * d[0] + tex_samples[1].a * d[1] + tex_samples[2].a * d[2] + tex_samples[3].a * d[3]) >> 16; + texture_state.u = state->u + state->tbu + tex_offset; + texture_state.v = state->v + state->tbv + tex_offset; + tex_read(state, &texture_state, &tex_samples[3]); + + d[0] = (256 - du) * (256 - dv); + d[1] = du * (256 - dv); + d[2] = (256 - du) * dv; + d[3] = du * dv; + + state->dest_rgba.r = (tex_samples[0].r * d[0] + tex_samples[1].r * d[1] + tex_samples[2].r * d[2] + tex_samples[3].r * d[3]) >> 16; + state->dest_rgba.g = (tex_samples[0].g * d[0] + tex_samples[1].g * d[1] + tex_samples[2].g * d[2] + tex_samples[3].g * d[3]) >> 16; + state->dest_rgba.b = (tex_samples[0].b * d[0] + tex_samples[1].b * d[1] + tex_samples[2].b * d[2] + tex_samples[3].b * d[3]) >> 16; + state->dest_rgba.a = (tex_samples[0].a * d[0] + tex_samples[1].a * d[1] + tex_samples[2].a * d[2] + tex_samples[3].a * d[3]) >> 16; } -static void tex_sample_mipmap(s3d_state_t *state) +static void +tex_sample_mipmap(s3d_state_t *state) { - s3d_texture_state_t texture_state; + s3d_texture_state_t texture_state; - texture_state.level = (state->d < 0) ? state->max_d : state->max_d - ((state->d >> 27) & 0xf); - if (texture_state.level < 0) - texture_state.level = 0; - texture_state.texture_shift = 18 + (9 - texture_state.level); - texture_state.u = state->u + state->tbu; - texture_state.v = state->v + state->tbv; + texture_state.level = (state->d < 0) ? state->max_d : state->max_d - ((state->d >> 27) & 0xf); + if (texture_state.level < 0) + texture_state.level = 0; + texture_state.texture_shift = 18 + (9 - texture_state.level); + texture_state.u = state->u + state->tbu; + texture_state.v = state->v + state->tbv; - tex_read(state, &texture_state, &state->dest_rgba); + tex_read(state, &texture_state, &state->dest_rgba); } -static void tex_sample_mipmap_filter(s3d_state_t *state) +static void +tex_sample_mipmap_filter(s3d_state_t *state) { - s3d_texture_state_t texture_state; - int tex_offset; - rgba_t tex_samples[4]; - int du, dv; - int d[4]; + s3d_texture_state_t texture_state; + int tex_offset; + rgba_t tex_samples[4]; + int du; + int dv; + int d[4]; - texture_state.level = (state->d < 0) ? state->max_d : state->max_d - ((state->d >> 27) & 0xf); - if (texture_state.level < 0) - texture_state.level = 0; - texture_state.texture_shift = 18 + (9 - texture_state.level); - tex_offset = 1 << texture_state.texture_shift; - - texture_state.u = state->u + state->tbu; - texture_state.v = state->v + state->tbv; - tex_read(state, &texture_state, &tex_samples[0]); - du = (texture_state.u >> (texture_state.texture_shift - 8)) & 0xff; - dv = (texture_state.v >> (texture_state.texture_shift - 8)) & 0xff; + texture_state.level = (state->d < 0) ? state->max_d : state->max_d - ((state->d >> 27) & 0xf); + if (texture_state.level < 0) + texture_state.level = 0; + texture_state.texture_shift = 18 + (9 - texture_state.level); + tex_offset = 1 << texture_state.texture_shift; - texture_state.u = state->u + state->tbu + tex_offset; - texture_state.v = state->v + state->tbv; - tex_read(state, &texture_state, &tex_samples[1]); + texture_state.u = state->u + state->tbu; + texture_state.v = state->v + state->tbv; + tex_read(state, &texture_state, &tex_samples[0]); + du = (texture_state.u >> (texture_state.texture_shift - 8)) & 0xff; + dv = (texture_state.v >> (texture_state.texture_shift - 8)) & 0xff; - texture_state.u = state->u + state->tbu; - texture_state.v = state->v + state->tbv + tex_offset; - tex_read(state, &texture_state, &tex_samples[2]); + texture_state.u = state->u + state->tbu + tex_offset; + texture_state.v = state->v + state->tbv; + tex_read(state, &texture_state, &tex_samples[1]); - texture_state.u = state->u + state->tbu + tex_offset; - texture_state.v = state->v + state->tbv + tex_offset; - tex_read(state, &texture_state, &tex_samples[3]); + texture_state.u = state->u + state->tbu; + texture_state.v = state->v + state->tbv + tex_offset; + tex_read(state, &texture_state, &tex_samples[2]); - d[0] = (256 - du) * (256 - dv); - d[1] = du * (256 - dv); - d[2] = (256 - du) * dv; - d[3] = du * dv; - - state->dest_rgba.r = (tex_samples[0].r * d[0] + tex_samples[1].r * d[1] + tex_samples[2].r * d[2] + tex_samples[3].r * d[3]) >> 16; - state->dest_rgba.g = (tex_samples[0].g * d[0] + tex_samples[1].g * d[1] + tex_samples[2].g * d[2] + tex_samples[3].g * d[3]) >> 16; - state->dest_rgba.b = (tex_samples[0].b * d[0] + tex_samples[1].b * d[1] + tex_samples[2].b * d[2] + tex_samples[3].b * d[3]) >> 16; - state->dest_rgba.a = (tex_samples[0].a * d[0] + tex_samples[1].a * d[1] + tex_samples[2].a * d[2] + tex_samples[3].a * d[3]) >> 16; + texture_state.u = state->u + state->tbu + tex_offset; + texture_state.v = state->v + state->tbv + tex_offset; + tex_read(state, &texture_state, &tex_samples[3]); + + d[0] = (256 - du) * (256 - dv); + d[1] = du * (256 - dv); + d[2] = (256 - du) * dv; + d[3] = du * dv; + + state->dest_rgba.r = (tex_samples[0].r * d[0] + tex_samples[1].r * d[1] + tex_samples[2].r * d[2] + tex_samples[3].r * d[3]) >> 16; + state->dest_rgba.g = (tex_samples[0].g * d[0] + tex_samples[1].g * d[1] + tex_samples[2].g * d[2] + tex_samples[3].g * d[3]) >> 16; + state->dest_rgba.b = (tex_samples[0].b * d[0] + tex_samples[1].b * d[1] + tex_samples[2].b * d[2] + tex_samples[3].b * d[3]) >> 16; + state->dest_rgba.a = (tex_samples[0].a * d[0] + tex_samples[1].a * d[1] + tex_samples[2].a * d[2] + tex_samples[3].a * d[3]) >> 16; } -static void tex_sample_persp_normal(s3d_state_t *state) +static void +tex_sample_persp_normal(s3d_state_t *state) { - s3d_texture_state_t texture_state; - int32_t w = 0; + s3d_texture_state_t texture_state; + int32_t w = 0; - if (state->w) - w = (int32_t)(((1ULL << 27) << 19) / (int64_t)state->w); - - texture_state.level = state->max_d; - texture_state.texture_shift = 18 + (9 - texture_state.level); - texture_state.u = (int32_t)(((int64_t)state->u * (int64_t)w) >> (12 + state->max_d)) + state->tbu; - texture_state.v = (int32_t)(((int64_t)state->v * (int64_t)w) >> (12 + state->max_d)) + state->tbv; + if (state->w) + w = (int32_t) (((1ULL << 27) << 19) / (int64_t) state->w); - tex_read(state, &texture_state, &state->dest_rgba); + texture_state.level = state->max_d; + texture_state.texture_shift = 18 + (9 - texture_state.level); + texture_state.u = (int32_t) (((int64_t) state->u * (int64_t) w) >> (12 + state->max_d)) + state->tbu; + texture_state.v = (int32_t) (((int64_t) state->v * (int64_t) w) >> (12 + state->max_d)) + state->tbv; + + tex_read(state, &texture_state, &state->dest_rgba); } -static void tex_sample_persp_normal_filter(s3d_state_t *state) +static void +tex_sample_persp_normal_filter(s3d_state_t *state) { - s3d_texture_state_t texture_state; - int32_t w = 0, u, v; - int tex_offset; - rgba_t tex_samples[4]; - int du, dv; - int d[4]; + s3d_texture_state_t texture_state; + int32_t w = 0; + int32_t u; + int32_t v; + int tex_offset; + rgba_t tex_samples[4]; + int du; + int dv; + int d[4]; - if (state->w) - w = (int32_t)(((1ULL << 27) << 19) / (int64_t)state->w); + if (state->w) + w = (int32_t) (((1ULL << 27) << 19) / (int64_t) state->w); - u = (int32_t)(((int64_t)state->u * (int64_t)w) >> (12 + state->max_d)) + state->tbu; - v = (int32_t)(((int64_t)state->v * (int64_t)w) >> (12 + state->max_d)) + state->tbv; + u = (int32_t) (((int64_t) state->u * (int64_t) w) >> (12 + state->max_d)) + state->tbu; + v = (int32_t) (((int64_t) state->v * (int64_t) w) >> (12 + state->max_d)) + state->tbv; - texture_state.level = state->max_d; - texture_state.texture_shift = 18 + (9 - texture_state.level); - tex_offset = 1 << texture_state.texture_shift; - - texture_state.u = u; - texture_state.v = v; - tex_read(state, &texture_state, &tex_samples[0]); - du = (u >> (texture_state.texture_shift - 8)) & 0xff; - dv = (v >> (texture_state.texture_shift - 8)) & 0xff; + texture_state.level = state->max_d; + texture_state.texture_shift = 18 + (9 - texture_state.level); + tex_offset = 1 << texture_state.texture_shift; - texture_state.u = u + tex_offset; - texture_state.v = v; - tex_read(state, &texture_state, &tex_samples[1]); + texture_state.u = u; + texture_state.v = v; + tex_read(state, &texture_state, &tex_samples[0]); + du = (u >> (texture_state.texture_shift - 8)) & 0xff; + dv = (v >> (texture_state.texture_shift - 8)) & 0xff; - texture_state.u = u; - texture_state.v = v + tex_offset; - tex_read(state, &texture_state, &tex_samples[2]); + texture_state.u = u + tex_offset; + texture_state.v = v; + tex_read(state, &texture_state, &tex_samples[1]); - texture_state.u = u + tex_offset; - texture_state.v = v + tex_offset; - tex_read(state, &texture_state, &tex_samples[3]); + texture_state.u = u; + texture_state.v = v + tex_offset; + tex_read(state, &texture_state, &tex_samples[2]); - d[0] = (256 - du) * (256 - dv); - d[1] = du * (256 - dv); - d[2] = (256 - du) * dv; - d[3] = du * dv; - - state->dest_rgba.r = (tex_samples[0].r * d[0] + tex_samples[1].r * d[1] + tex_samples[2].r * d[2] + tex_samples[3].r * d[3]) >> 16; - state->dest_rgba.g = (tex_samples[0].g * d[0] + tex_samples[1].g * d[1] + tex_samples[2].g * d[2] + tex_samples[3].g * d[3]) >> 16; - state->dest_rgba.b = (tex_samples[0].b * d[0] + tex_samples[1].b * d[1] + tex_samples[2].b * d[2] + tex_samples[3].b * d[3]) >> 16; - state->dest_rgba.a = (tex_samples[0].a * d[0] + tex_samples[1].a * d[1] + tex_samples[2].a * d[2] + tex_samples[3].a * d[3]) >> 16; + texture_state.u = u + tex_offset; + texture_state.v = v + tex_offset; + tex_read(state, &texture_state, &tex_samples[3]); + + d[0] = (256 - du) * (256 - dv); + d[1] = du * (256 - dv); + d[2] = (256 - du) * dv; + d[3] = du * dv; + + state->dest_rgba.r = (tex_samples[0].r * d[0] + tex_samples[1].r * d[1] + tex_samples[2].r * d[2] + tex_samples[3].r * d[3]) >> 16; + state->dest_rgba.g = (tex_samples[0].g * d[0] + tex_samples[1].g * d[1] + tex_samples[2].g * d[2] + tex_samples[3].g * d[3]) >> 16; + state->dest_rgba.b = (tex_samples[0].b * d[0] + tex_samples[1].b * d[1] + tex_samples[2].b * d[2] + tex_samples[3].b * d[3]) >> 16; + state->dest_rgba.a = (tex_samples[0].a * d[0] + tex_samples[1].a * d[1] + tex_samples[2].a * d[2] + tex_samples[3].a * d[3]) >> 16; } -static void tex_sample_persp_normal_375(s3d_state_t *state) +static void +tex_sample_persp_normal_375(s3d_state_t *state) { - s3d_texture_state_t texture_state; - int32_t w = 0; + s3d_texture_state_t texture_state; + int32_t w = 0; - if (state->w) - w = (int32_t)(((1ULL << 27) << 19) / (int64_t)state->w); - - texture_state.level = state->max_d; - texture_state.texture_shift = 18 + (9 - texture_state.level); - texture_state.u = (int32_t)(((int64_t)state->u * (int64_t)w) >> (8 + state->max_d)) + state->tbu; - texture_state.v = (int32_t)(((int64_t)state->v * (int64_t)w) >> (8 + state->max_d)) + state->tbv; + if (state->w) + w = (int32_t) (((1ULL << 27) << 19) / (int64_t) state->w); - tex_read(state, &texture_state, &state->dest_rgba); + texture_state.level = state->max_d; + texture_state.texture_shift = 18 + (9 - texture_state.level); + texture_state.u = (int32_t) (((int64_t) state->u * (int64_t) w) >> (8 + state->max_d)) + state->tbu; + texture_state.v = (int32_t) (((int64_t) state->v * (int64_t) w) >> (8 + state->max_d)) + state->tbv; + + tex_read(state, &texture_state, &state->dest_rgba); } -static void tex_sample_persp_normal_filter_375(s3d_state_t *state) +static void +tex_sample_persp_normal_filter_375(s3d_state_t *state) { - s3d_texture_state_t texture_state; - int32_t w = 0, u, v; - int tex_offset; - rgba_t tex_samples[4]; - int du, dv; - int d[4]; + s3d_texture_state_t texture_state; + int32_t w = 0; + int32_t u; + int32_t v; + int tex_offset; + rgba_t tex_samples[4]; + int du; + int dv; + int d[4]; - if (state->w) - w = (int32_t)(((1ULL << 27) << 19) / (int64_t)state->w); + if (state->w) + w = (int32_t) (((1ULL << 27) << 19) / (int64_t) state->w); - u = (int32_t)(((int64_t)state->u * (int64_t)w) >> (8 + state->max_d)) + state->tbu; - v = (int32_t)(((int64_t)state->v * (int64_t)w) >> (8 + state->max_d)) + state->tbv; - - texture_state.level = state->max_d; - texture_state.texture_shift = 18 + (9 - texture_state.level); - tex_offset = 1 << texture_state.texture_shift; + u = (int32_t) (((int64_t) state->u * (int64_t) w) >> (8 + state->max_d)) + state->tbu; + v = (int32_t) (((int64_t) state->v * (int64_t) w) >> (8 + state->max_d)) + state->tbv; - texture_state.u = u; - texture_state.v = v; - tex_read(state, &texture_state, &tex_samples[0]); - du = (u >> (texture_state.texture_shift - 8)) & 0xff; - dv = (v >> (texture_state.texture_shift - 8)) & 0xff; + texture_state.level = state->max_d; + texture_state.texture_shift = 18 + (9 - texture_state.level); + tex_offset = 1 << texture_state.texture_shift; - texture_state.u = u + tex_offset; - texture_state.v = v; - tex_read(state, &texture_state, &tex_samples[1]); + texture_state.u = u; + texture_state.v = v; + tex_read(state, &texture_state, &tex_samples[0]); + du = (u >> (texture_state.texture_shift - 8)) & 0xff; + dv = (v >> (texture_state.texture_shift - 8)) & 0xff; - texture_state.u = u; - texture_state.v = v + tex_offset; - tex_read(state, &texture_state, &tex_samples[2]); + texture_state.u = u + tex_offset; + texture_state.v = v; + tex_read(state, &texture_state, &tex_samples[1]); - texture_state.u = u + tex_offset; - texture_state.v = v + tex_offset; - tex_read(state, &texture_state, &tex_samples[3]); + texture_state.u = u; + texture_state.v = v + tex_offset; + tex_read(state, &texture_state, &tex_samples[2]); - d[0] = (256 - du) * (256 - dv); - d[1] = du * (256 - dv); - d[2] = (256 - du) * dv; - d[3] = du * dv; - - state->dest_rgba.r = (tex_samples[0].r * d[0] + tex_samples[1].r * d[1] + tex_samples[2].r * d[2] + tex_samples[3].r * d[3]) >> 16; - state->dest_rgba.g = (tex_samples[0].g * d[0] + tex_samples[1].g * d[1] + tex_samples[2].g * d[2] + tex_samples[3].g * d[3]) >> 16; - state->dest_rgba.b = (tex_samples[0].b * d[0] + tex_samples[1].b * d[1] + tex_samples[2].b * d[2] + tex_samples[3].b * d[3]) >> 16; - state->dest_rgba.a = (tex_samples[0].a * d[0] + tex_samples[1].a * d[1] + tex_samples[2].a * d[2] + tex_samples[3].a * d[3]) >> 16; + texture_state.u = u + tex_offset; + texture_state.v = v + tex_offset; + tex_read(state, &texture_state, &tex_samples[3]); + + d[0] = (256 - du) * (256 - dv); + d[1] = du * (256 - dv); + d[2] = (256 - du) * dv; + d[3] = du * dv; + + state->dest_rgba.r = (tex_samples[0].r * d[0] + tex_samples[1].r * d[1] + tex_samples[2].r * d[2] + tex_samples[3].r * d[3]) >> 16; + state->dest_rgba.g = (tex_samples[0].g * d[0] + tex_samples[1].g * d[1] + tex_samples[2].g * d[2] + tex_samples[3].g * d[3]) >> 16; + state->dest_rgba.b = (tex_samples[0].b * d[0] + tex_samples[1].b * d[1] + tex_samples[2].b * d[2] + tex_samples[3].b * d[3]) >> 16; + state->dest_rgba.a = (tex_samples[0].a * d[0] + tex_samples[1].a * d[1] + tex_samples[2].a * d[2] + tex_samples[3].a * d[3]) >> 16; } - -static void tex_sample_persp_mipmap(s3d_state_t *state) +static void +tex_sample_persp_mipmap(s3d_state_t *state) { - s3d_texture_state_t texture_state; - int32_t w = 0; + s3d_texture_state_t texture_state; + int32_t w = 0; - if (state->w) - w = (int32_t)(((1ULL << 27) << 19) / (int64_t)state->w); - - texture_state.level = (state->d < 0) ? state->max_d : state->max_d - ((state->d >> 27) & 0xf); - if (texture_state.level < 0) - texture_state.level = 0; - texture_state.texture_shift = 18 + (9 - texture_state.level); - texture_state.u = (int32_t)(((int64_t)state->u * (int64_t)w) >> (12 + state->max_d)) + state->tbu; - texture_state.v = (int32_t)(((int64_t)state->v * (int64_t)w) >> (12 + state->max_d)) + state->tbv; + if (state->w) + w = (int32_t) (((1ULL << 27) << 19) / (int64_t) state->w); - tex_read(state, &texture_state, &state->dest_rgba); + texture_state.level = (state->d < 0) ? state->max_d : state->max_d - ((state->d >> 27) & 0xf); + if (texture_state.level < 0) + texture_state.level = 0; + texture_state.texture_shift = 18 + (9 - texture_state.level); + texture_state.u = (int32_t) (((int64_t) state->u * (int64_t) w) >> (12 + state->max_d)) + state->tbu; + texture_state.v = (int32_t) (((int64_t) state->v * (int64_t) w) >> (12 + state->max_d)) + state->tbv; + + tex_read(state, &texture_state, &state->dest_rgba); } -static void tex_sample_persp_mipmap_filter(s3d_state_t *state) +static void +tex_sample_persp_mipmap_filter(s3d_state_t *state) { - s3d_texture_state_t texture_state; - int32_t w = 0, u, v; - int tex_offset; - rgba_t tex_samples[4]; - int du, dv; - int d[4]; + s3d_texture_state_t texture_state; + int32_t w = 0; + int32_t u; + int32_t v; + int tex_offset; + rgba_t tex_samples[4]; + int du; + int dv; + int d[4]; - if (state->w) - w = (int32_t)(((1ULL << 27) << 19) / (int64_t)state->w); + if (state->w) + w = (int32_t) (((1ULL << 27) << 19) / (int64_t) state->w); - u = (int32_t)(((int64_t)state->u * (int64_t)w) >> (12 + state->max_d)) + state->tbu; - v = (int32_t)(((int64_t)state->v * (int64_t)w) >> (12 + state->max_d)) + state->tbv; - - texture_state.level = (state->d < 0) ? state->max_d : state->max_d - ((state->d >> 27) & 0xf); - if (texture_state.level < 0) - texture_state.level = 0; - texture_state.texture_shift = 18 + (9 - texture_state.level); - tex_offset = 1 << texture_state.texture_shift; + u = (int32_t) (((int64_t) state->u * (int64_t) w) >> (12 + state->max_d)) + state->tbu; + v = (int32_t) (((int64_t) state->v * (int64_t) w) >> (12 + state->max_d)) + state->tbv; - texture_state.u = u; - texture_state.v = v; - tex_read(state, &texture_state, &tex_samples[0]); - du = (u >> (texture_state.texture_shift - 8)) & 0xff; - dv = (v >> (texture_state.texture_shift - 8)) & 0xff; + texture_state.level = (state->d < 0) ? state->max_d : state->max_d - ((state->d >> 27) & 0xf); + if (texture_state.level < 0) + texture_state.level = 0; + texture_state.texture_shift = 18 + (9 - texture_state.level); + tex_offset = 1 << texture_state.texture_shift; - texture_state.u = u + tex_offset; - texture_state.v = v; - tex_read(state, &texture_state, &tex_samples[1]); + texture_state.u = u; + texture_state.v = v; + tex_read(state, &texture_state, &tex_samples[0]); + du = (u >> (texture_state.texture_shift - 8)) & 0xff; + dv = (v >> (texture_state.texture_shift - 8)) & 0xff; - texture_state.u = u; - texture_state.v = v + tex_offset; - tex_read(state, &texture_state, &tex_samples[2]); + texture_state.u = u + tex_offset; + texture_state.v = v; + tex_read(state, &texture_state, &tex_samples[1]); - texture_state.u = u + tex_offset; - texture_state.v = v + tex_offset; - tex_read(state, &texture_state, &tex_samples[3]); + texture_state.u = u; + texture_state.v = v + tex_offset; + tex_read(state, &texture_state, &tex_samples[2]); - d[0] = (256 - du) * (256 - dv); - d[1] = du * (256 - dv); - d[2] = (256 - du) * dv; - d[3] = du * dv; - - state->dest_rgba.r = (tex_samples[0].r * d[0] + tex_samples[1].r * d[1] + tex_samples[2].r * d[2] + tex_samples[3].r * d[3]) >> 16; - state->dest_rgba.g = (tex_samples[0].g * d[0] + tex_samples[1].g * d[1] + tex_samples[2].g * d[2] + tex_samples[3].g * d[3]) >> 16; - state->dest_rgba.b = (tex_samples[0].b * d[0] + tex_samples[1].b * d[1] + tex_samples[2].b * d[2] + tex_samples[3].b * d[3]) >> 16; - state->dest_rgba.a = (tex_samples[0].a * d[0] + tex_samples[1].a * d[1] + tex_samples[2].a * d[2] + tex_samples[3].a * d[3]) >> 16; + texture_state.u = u + tex_offset; + texture_state.v = v + tex_offset; + tex_read(state, &texture_state, &tex_samples[3]); + + d[0] = (256 - du) * (256 - dv); + d[1] = du * (256 - dv); + d[2] = (256 - du) * dv; + d[3] = du * dv; + + state->dest_rgba.r = (tex_samples[0].r * d[0] + tex_samples[1].r * d[1] + tex_samples[2].r * d[2] + tex_samples[3].r * d[3]) >> 16; + state->dest_rgba.g = (tex_samples[0].g * d[0] + tex_samples[1].g * d[1] + tex_samples[2].g * d[2] + tex_samples[3].g * d[3]) >> 16; + state->dest_rgba.b = (tex_samples[0].b * d[0] + tex_samples[1].b * d[1] + tex_samples[2].b * d[2] + tex_samples[3].b * d[3]) >> 16; + state->dest_rgba.a = (tex_samples[0].a * d[0] + tex_samples[1].a * d[1] + tex_samples[2].a * d[2] + tex_samples[3].a * d[3]) >> 16; } -static void tex_sample_persp_mipmap_375(s3d_state_t *state) +static void +tex_sample_persp_mipmap_375(s3d_state_t *state) { - s3d_texture_state_t texture_state; - int32_t w = 0; + s3d_texture_state_t texture_state; + int32_t w = 0; - if (state->w) - w = (int32_t)(((1ULL << 27) << 19) / (int64_t)state->w); - - texture_state.level = (state->d < 0) ? state->max_d : state->max_d - ((state->d >> 27) & 0xf); - if (texture_state.level < 0) - texture_state.level = 0; - texture_state.texture_shift = 18 + (9 - texture_state.level); - texture_state.u = (int32_t)(((int64_t)state->u * (int64_t)w) >> (8 + state->max_d)) + state->tbu; - texture_state.v = (int32_t)(((int64_t)state->v * (int64_t)w) >> (8 + state->max_d)) + state->tbv; + if (state->w) + w = (int32_t) (((1ULL << 27) << 19) / (int64_t) state->w); - tex_read(state, &texture_state, &state->dest_rgba); + texture_state.level = (state->d < 0) ? state->max_d : state->max_d - ((state->d >> 27) & 0xf); + if (texture_state.level < 0) + texture_state.level = 0; + texture_state.texture_shift = 18 + (9 - texture_state.level); + texture_state.u = (int32_t) (((int64_t) state->u * (int64_t) w) >> (8 + state->max_d)) + state->tbu; + texture_state.v = (int32_t) (((int64_t) state->v * (int64_t) w) >> (8 + state->max_d)) + state->tbv; + + tex_read(state, &texture_state, &state->dest_rgba); } -static void tex_sample_persp_mipmap_filter_375(s3d_state_t *state) +static void +tex_sample_persp_mipmap_filter_375(s3d_state_t *state) { - s3d_texture_state_t texture_state; - int32_t w = 0, u, v; - int tex_offset; - rgba_t tex_samples[4]; - int du, dv; - int d[4]; + s3d_texture_state_t texture_state; + int32_t w = 0; + int32_t u; + int32_t v; + int tex_offset; + rgba_t tex_samples[4]; + int du; + int dv; + int d[4]; - if (state->w) - w = (int32_t)(((1ULL << 27) << 19) / (int64_t)state->w); + if (state->w) + w = (int32_t) (((1ULL << 27) << 19) / (int64_t) state->w); - u = (int32_t)(((int64_t)state->u * (int64_t)w) >> (8 + state->max_d)) + state->tbu; - v = (int32_t)(((int64_t)state->v * (int64_t)w) >> (8 + state->max_d)) + state->tbv; - - texture_state.level = (state->d < 0) ? state->max_d : state->max_d - ((state->d >> 27) & 0xf); - if (texture_state.level < 0) - texture_state.level = 0; - texture_state.texture_shift = 18 + (9 - texture_state.level); - tex_offset = 1 << texture_state.texture_shift; - - texture_state.u = u; - texture_state.v = v; - tex_read(state, &texture_state, &tex_samples[0]); - du = (u >> (texture_state.texture_shift - 8)) & 0xff; - dv = (v >> (texture_state.texture_shift - 8)) & 0xff; + u = (int32_t) (((int64_t) state->u * (int64_t) w) >> (8 + state->max_d)) + state->tbu; + v = (int32_t) (((int64_t) state->v * (int64_t) w) >> (8 + state->max_d)) + state->tbv; - texture_state.u = u + tex_offset; - texture_state.v = v; - tex_read(state, &texture_state, &tex_samples[1]); + texture_state.level = (state->d < 0) ? state->max_d : state->max_d - ((state->d >> 27) & 0xf); + if (texture_state.level < 0) + texture_state.level = 0; + texture_state.texture_shift = 18 + (9 - texture_state.level); + tex_offset = 1 << texture_state.texture_shift; - texture_state.u = u; - texture_state.v = v + tex_offset; - tex_read(state, &texture_state, &tex_samples[2]); + texture_state.u = u; + texture_state.v = v; + tex_read(state, &texture_state, &tex_samples[0]); + du = (u >> (texture_state.texture_shift - 8)) & 0xff; + dv = (v >> (texture_state.texture_shift - 8)) & 0xff; - texture_state.u = u + tex_offset; - texture_state.v = v + tex_offset; - tex_read(state, &texture_state, &tex_samples[3]); + texture_state.u = u + tex_offset; + texture_state.v = v; + tex_read(state, &texture_state, &tex_samples[1]); - d[0] = (256 - du) * (256 - dv); - d[1] = du * (256 - dv); - d[2] = (256 - du) * dv; - d[3] = du * dv; - - state->dest_rgba.r = (tex_samples[0].r * d[0] + tex_samples[1].r * d[1] + tex_samples[2].r * d[2] + tex_samples[3].r * d[3]) >> 16; - state->dest_rgba.g = (tex_samples[0].g * d[0] + tex_samples[1].g * d[1] + tex_samples[2].g * d[2] + tex_samples[3].g * d[3]) >> 16; - state->dest_rgba.b = (tex_samples[0].b * d[0] + tex_samples[1].b * d[1] + tex_samples[2].b * d[2] + tex_samples[3].b * d[3]) >> 16; - state->dest_rgba.a = (tex_samples[0].a * d[0] + tex_samples[1].a * d[1] + tex_samples[2].a * d[2] + tex_samples[3].a * d[3]) >> 16; + texture_state.u = u; + texture_state.v = v + tex_offset; + tex_read(state, &texture_state, &tex_samples[2]); + + texture_state.u = u + tex_offset; + texture_state.v = v + tex_offset; + tex_read(state, &texture_state, &tex_samples[3]); + + d[0] = (256 - du) * (256 - dv); + d[1] = du * (256 - dv); + d[2] = (256 - du) * dv; + d[3] = du * dv; + + state->dest_rgba.r = (tex_samples[0].r * d[0] + tex_samples[1].r * d[1] + tex_samples[2].r * d[2] + tex_samples[3].r * d[3]) >> 16; + state->dest_rgba.g = (tex_samples[0].g * d[0] + tex_samples[1].g * d[1] + tex_samples[2].g * d[2] + tex_samples[3].g * d[3]) >> 16; + state->dest_rgba.b = (tex_samples[0].b * d[0] + tex_samples[1].b * d[1] + tex_samples[2].b * d[2] + tex_samples[3].b * d[3]) >> 16; + state->dest_rgba.a = (tex_samples[0].a * d[0] + tex_samples[1].a * d[1] + tex_samples[2].a * d[2] + tex_samples[3].a * d[3]) >> 16; } +#define CLAMP(x) \ + do { \ + if ((x) & ~0xff) \ + x = ((x) < 0) ? 0 : 0xff; \ + } while (0) -#define CLAMP(x) do \ - { \ - if ((x) & ~0xff) \ - x = ((x) < 0) ? 0 : 0xff; \ - } \ - while (0) +#define CLAMP_RGBA(r, g, b, a) \ + if ((r) & ~0xff) \ + r = ((r) < 0) ? 0 : 0xff; \ + if ((g) & ~0xff) \ + g = ((g) < 0) ? 0 : 0xff; \ + if ((b) & ~0xff) \ + b = ((b) < 0) ? 0 : 0xff; \ + if ((a) & ~0xff) \ + a = ((a) < 0) ? 0 : 0xff; -#define CLAMP_RGBA(r, g, b, a) \ - if ((r) & ~0xff) \ - r = ((r) < 0) ? 0 : 0xff; \ - if ((g) & ~0xff) \ - g = ((g) < 0) ? 0 : 0xff; \ - if ((b) & ~0xff) \ - b = ((b) < 0) ? 0 : 0xff; \ - if ((a) & ~0xff) \ - a = ((a) < 0) ? 0 : 0xff; - -#define CLAMP_RGB(r, g, b) do \ - { \ - if ((r) < 0) \ - r = 0; \ - if ((r) > 0xff) \ - r = 0xff; \ - if ((g) < 0) \ - g = 0; \ - if ((g) > 0xff) \ - g = 0xff; \ - if ((b) < 0) \ - b = 0; \ - if ((b) > 0xff) \ - b = 0xff; \ - } \ - while (0) +#define CLAMP_RGB(r, g, b) \ + do { \ + if ((r) < 0) \ + r = 0; \ + if ((r) > 0xff) \ + r = 0xff; \ + if ((g) < 0) \ + g = 0; \ + if ((g) > 0xff) \ + g = 0xff; \ + if ((b) < 0) \ + b = 0; \ + if ((b) > 0xff) \ + b = 0xff; \ + } while (0) -static void dest_pixel_gouraud_shaded_triangle(s3d_state_t *state) +static void +dest_pixel_gouraud_shaded_triangle(s3d_state_t *state) { - state->dest_rgba.r = state->r >> 7; - CLAMP(state->dest_rgba.r); + state->dest_rgba.r = state->r >> 7; + CLAMP(state->dest_rgba.r); - state->dest_rgba.g = state->g >> 7; - CLAMP(state->dest_rgba.g); + state->dest_rgba.g = state->g >> 7; + CLAMP(state->dest_rgba.g); - state->dest_rgba.b = state->b >> 7; - CLAMP(state->dest_rgba.b); + state->dest_rgba.b = state->b >> 7; + CLAMP(state->dest_rgba.b); + state->dest_rgba.a = state->a >> 7; + CLAMP(state->dest_rgba.a); +} + +static void +dest_pixel_unlit_texture_triangle(s3d_state_t *state) +{ + tex_sample(state); + + if (state->cmd_set & CMD_SET_ABC_SRC) state->dest_rgba.a = state->a >> 7; - CLAMP(state->dest_rgba.a); } -static void dest_pixel_unlit_texture_triangle(s3d_state_t *state) +static void +dest_pixel_lit_texture_decal(s3d_state_t *state) { - tex_sample(state); + tex_sample(state); - if (state->cmd_set & CMD_SET_ABC_SRC) - state->dest_rgba.a = state->a >> 7; + if (state->cmd_set & CMD_SET_ABC_SRC) + state->dest_rgba.a = state->a >> 7; } -static void dest_pixel_lit_texture_decal(s3d_state_t *state) +static void +dest_pixel_lit_texture_reflection(s3d_state_t *state) { - tex_sample(state); + tex_sample(state); - if (state->cmd_set & CMD_SET_ABC_SRC) - state->dest_rgba.a = state->a >> 7; + state->dest_rgba.r += (state->r >> 7); + state->dest_rgba.g += (state->g >> 7); + state->dest_rgba.b += (state->b >> 7); + if (state->cmd_set & CMD_SET_ABC_SRC) + state->dest_rgba.a += (state->a >> 7); + + CLAMP_RGBA(state->dest_rgba.r, state->dest_rgba.g, state->dest_rgba.b, state->dest_rgba.a); } -static void dest_pixel_lit_texture_reflection(s3d_state_t *state) +static void +dest_pixel_lit_texture_modulate(s3d_state_t *state) { - tex_sample(state); + int r = state->r >> 7; + int g = state->g >> 7; + int b = state->b >> 7; + int a = state->a >> 7; - state->dest_rgba.r += (state->r >> 7); - state->dest_rgba.g += (state->g >> 7); - state->dest_rgba.b += (state->b >> 7); - if (state->cmd_set & CMD_SET_ABC_SRC) - state->dest_rgba.a += (state->a >> 7); + tex_sample(state); - CLAMP_RGBA(state->dest_rgba.r, state->dest_rgba.g, state->dest_rgba.b, state->dest_rgba.a); + CLAMP_RGBA(r, g, b, a); + + state->dest_rgba.r = ((state->dest_rgba.r) * r) >> 8; + state->dest_rgba.g = ((state->dest_rgba.g) * g) >> 8; + state->dest_rgba.b = ((state->dest_rgba.b) * b) >> 8; + + if (state->cmd_set & CMD_SET_ABC_SRC) + state->dest_rgba.a = a; } -static void dest_pixel_lit_texture_modulate(s3d_state_t *state) +static void +tri(virge_t *virge, s3d_t *s3d_tri, s3d_state_t *state, int yc, int32_t dx1, int32_t dx2) { - int r = state->r >> 7, g = state->g >> 7, b = state->b >> 7, a = state->a >> 7; - - tex_sample(state); - - CLAMP_RGBA(r, g, b, a); - - state->dest_rgba.r = ((state->dest_rgba.r) * r) >> 8; - state->dest_rgba.g = ((state->dest_rgba.g) * g) >> 8; - state->dest_rgba.b = ((state->dest_rgba.b) * b) >> 8; + svga_t *svga = &virge->svga; + uint8_t *vram = svga->vram; - if (state->cmd_set & CMD_SET_ABC_SRC) - state->dest_rgba.a = a; -} + int x_dir = s3d_tri->tlr ? 1 : -1; -static void tri(virge_t *virge, s3d_t *s3d_tri, s3d_state_t *state, int yc, int32_t dx1, int32_t dx2) -{ - svga_t *svga = &virge->svga; - uint8_t *vram = (uint8_t *)svga->vram; + int use_z = !(s3d_tri->cmd_set & CMD_SET_ZB_MODE); - int x_dir = s3d_tri->tlr ? 1 : -1; - - int use_z = !(s3d_tri->cmd_set & CMD_SET_ZB_MODE); + int y_count = yc; - int y_count = yc; - - int bpp = (s3d_tri->cmd_set >> 2) & 7; - - uint32_t dest_offset = 0, z_offset = 0; + int bpp = (s3d_tri->cmd_set >> 2) & 7; - uint32_t src_col; - int src_r = 0, src_g = 0, src_b = 0; + uint32_t dest_offset = 0; + uint32_t z_offset = 0; - int x; - int xe; - uint32_t z; + uint32_t src_col; + int src_r = 0; + int src_g = 0; + int src_b = 0; - uint32_t dest_addr; - uint32_t z_addr; - int dx; - int x_offset; - int xz_offset; + int x; + int xe; + uint32_t z; - int update; - uint16_t src_z = 0; - - if (s3d_tri->cmd_set & CMD_SET_HC) - { - if (state->y < s3d_tri->clip_t) - return; - if (state->y > s3d_tri->clip_b) - { - int diff_y = state->y - s3d_tri->clip_b; - - if (diff_y > y_count) - diff_y = y_count; - - state->base_u += (s3d_tri->TdUdY * diff_y); - state->base_v += (s3d_tri->TdVdY * diff_y); - state->base_z += (s3d_tri->TdZdY * diff_y); - state->base_r += (s3d_tri->TdRdY * diff_y); - state->base_g += (s3d_tri->TdGdY * diff_y); - state->base_b += (s3d_tri->TdBdY * diff_y); - state->base_a += (s3d_tri->TdAdY * diff_y); - state->base_d += (s3d_tri->TdDdY * diff_y); - state->base_w += (s3d_tri->TdWdY * diff_y); - state->x1 += (dx1 * diff_y); - state->x2 += (dx2 * diff_y); - state->y -= diff_y; - dest_offset -= s3d_tri->dest_str * diff_y; - z_offset -= s3d_tri->z_str; - y_count -= diff_y; - } - if ((state->y - y_count) < s3d_tri->clip_t) - y_count = (state->y - s3d_tri->clip_t) + 1; + uint32_t dest_addr; + uint32_t z_addr; + int dx; + int x_offset; + int xz_offset; + + int update; + uint16_t src_z = 0; + + if (s3d_tri->cmd_set & CMD_SET_HC) { + if (state->y < s3d_tri->clip_t) + return; + if (state->y > s3d_tri->clip_b) { + int diff_y = state->y - s3d_tri->clip_b; + + if (diff_y > y_count) + diff_y = y_count; + + state->base_u += (s3d_tri->TdUdY * diff_y); + state->base_v += (s3d_tri->TdVdY * diff_y); + state->base_z += (s3d_tri->TdZdY * diff_y); + state->base_r += (s3d_tri->TdRdY * diff_y); + state->base_g += (s3d_tri->TdGdY * diff_y); + state->base_b += (s3d_tri->TdBdY * diff_y); + state->base_a += (s3d_tri->TdAdY * diff_y); + state->base_d += (s3d_tri->TdDdY * diff_y); + state->base_w += (s3d_tri->TdWdY * diff_y); + state->x1 += (dx1 * diff_y); + state->x2 += (dx2 * diff_y); + state->y -= diff_y; + dest_offset -= s3d_tri->dest_str * diff_y; + z_offset -= s3d_tri->z_str; + y_count -= diff_y; + } + if ((state->y - y_count) < s3d_tri->clip_t) + y_count = (state->y - s3d_tri->clip_t) + 1; + } + + dest_offset = s3d_tri->dest_base + (state->y * s3d_tri->dest_str); + z_offset = s3d_tri->z_base + (state->y * s3d_tri->z_str); + + while (y_count > 0) { + x = (state->x1 + ((1 << 20) - 1)) >> 20; + xe = (state->x2 + ((1 << 20) - 1)) >> 20; + z = (state->base_z > 0) ? (state->base_z << 1) : 0; + if (x_dir < 0) { + x--; + xe--; } - dest_offset = s3d_tri->dest_base + (state->y * s3d_tri->dest_str); - z_offset = s3d_tri->z_base + (state->y * s3d_tri->z_str); - - while (y_count > 0) - { - x = (state->x1 + ((1 << 20) - 1)) >> 20; - xe = (state->x2 + ((1 << 20) - 1)) >> 20; - z = (state->base_z > 0) ? (state->base_z << 1) : 0; - if (x_dir < 0) - { - x--; - xe--; + if (((x != xe) && ((x_dir > 0) && (x < xe))) || ((x_dir < 0) && (x > xe))) { + dx = (x_dir > 0) ? ((31 - ((state->x1 - 1) >> 15)) & 0x1f) : (((state->x1 - 1) >> 15) & 0x1f); + x_offset = x_dir * (bpp + 1); + xz_offset = x_dir << 1; + if (x_dir > 0) + dx += 1; + state->r = state->base_r + ((s3d_tri->TdRdX * dx) >> 5); + state->g = state->base_g + ((s3d_tri->TdGdX * dx) >> 5); + state->b = state->base_b + ((s3d_tri->TdBdX * dx) >> 5); + state->a = state->base_a + ((s3d_tri->TdAdX * dx) >> 5); + state->u = state->base_u + ((s3d_tri->TdUdX * dx) >> 5); + state->v = state->base_v + ((s3d_tri->TdVdX * dx) >> 5); + state->w = state->base_w + ((s3d_tri->TdWdX * dx) >> 5); + state->d = state->base_d + ((s3d_tri->TdDdX * dx) >> 5); + z += ((s3d_tri->TdZdX * dx) >> 5); + + if (s3d_tri->cmd_set & CMD_SET_HC) { + if (x_dir > 0) { + if (x > s3d_tri->clip_r) + goto tri_skip_line; + if (xe < s3d_tri->clip_l) + goto tri_skip_line; + if (xe > s3d_tri->clip_r) + xe = s3d_tri->clip_r + 1; + if (x < s3d_tri->clip_l) { + int diff_x = s3d_tri->clip_l - x; + + z += (s3d_tri->TdZdX * diff_x); + state->u += (s3d_tri->TdUdX * diff_x); + state->v += (s3d_tri->TdVdX * diff_x); + state->r += (s3d_tri->TdRdX * diff_x); + state->g += (s3d_tri->TdGdX * diff_x); + state->b += (s3d_tri->TdBdX * diff_x); + state->a += (s3d_tri->TdAdX * diff_x); + state->d += (s3d_tri->TdDdX * diff_x); + state->w += (s3d_tri->TdWdX * diff_x); + + x = s3d_tri->clip_l; + } + } else { + if (x < s3d_tri->clip_l) + goto tri_skip_line; + if (xe > s3d_tri->clip_r) + goto tri_skip_line; + if (xe < s3d_tri->clip_l) + xe = s3d_tri->clip_l - 1; + if (x > s3d_tri->clip_r) { + int diff_x = x - s3d_tri->clip_r; + + z += (s3d_tri->TdZdX * diff_x); + state->u += (s3d_tri->TdUdX * diff_x); + state->v += (s3d_tri->TdVdX * diff_x); + state->r += (s3d_tri->TdRdX * diff_x); + state->g += (s3d_tri->TdGdX * diff_x); + state->b += (s3d_tri->TdBdX * diff_x); + state->a += (s3d_tri->TdAdX * diff_x); + state->d += (s3d_tri->TdDdX * diff_x); + state->w += (s3d_tri->TdWdX * diff_x); + + x = s3d_tri->clip_r; + } + } + } + + svga->changedvram[(dest_offset & virge->vram_mask) >> 12] = changeframecount; + + dest_addr = dest_offset + (x * (bpp + 1)); + z_addr = z_offset + (x << 1); + + x &= 0xfff; + xe &= 0xfff; + + while (x != xe) { + update = 1; + _x = x; + _y = state->y; + + if (use_z) { + src_z = *(uint16_t *) &vram[z_addr & virge->vram_mask]; + switch ((s3d_tri->cmd_set >> 20) & 7) { + case 0: + update = 0; + break; + case 1: + if ((z >> 16) > src_z) { + src_z = (z >> 16); + } else + update = 0; + break; + case 2: + if ((z >> 16) == src_z) { + src_z = (z >> 16); + } else + update = 0; + break; + case 3: + if ((z >> 16) >= src_z) { + src_z = (z >> 16); + } else + update = 0; + break; + case 4: + if ((z >> 16) < src_z) { + src_z = (z >> 16); + } else + update = 0; + break; + case 5: + if ((z >> 16) != src_z) { + src_z = (z >> 16); + } else + update = 0; + break; + case 6: + if ((z >> 16) <= src_z) { + src_z = (z >> 16); + } else + update = 0; + break; + case 7: + src_z = (z >> 16); + break; + + default: + break; + } } - if (((x != xe) && ((x_dir > 0) && (x < xe))) || ((x_dir < 0) && (x > xe))) - { - dx = (x_dir > 0) ? ((31 - ((state->x1-1) >> 15)) & 0x1f) : (((state->x1-1) >> 15) & 0x1f); - x_offset = x_dir * (bpp + 1); - xz_offset = x_dir << 1; - if (x_dir > 0) - dx += 1; - state->r = state->base_r + ((s3d_tri->TdRdX * dx) >> 5); - state->g = state->base_g + ((s3d_tri->TdGdX * dx) >> 5); - state->b = state->base_b + ((s3d_tri->TdBdX * dx) >> 5); - state->a = state->base_a + ((s3d_tri->TdAdX * dx) >> 5); - state->u = state->base_u + ((s3d_tri->TdUdX * dx) >> 5); - state->v = state->base_v + ((s3d_tri->TdVdX * dx) >> 5); - state->w = state->base_w + ((s3d_tri->TdWdX * dx) >> 5); - state->d = state->base_d + ((s3d_tri->TdDdX * dx) >> 5); - z += ((s3d_tri->TdZdX * dx) >> 5); + if (update) { + uint32_t dest_col; - if (s3d_tri->cmd_set & CMD_SET_HC) - { - if (x_dir > 0) - { - if (x > s3d_tri->clip_r) - goto tri_skip_line; - if (xe < s3d_tri->clip_l) - goto tri_skip_line; - if (xe > s3d_tri->clip_r) - xe = s3d_tri->clip_r + 1; - if (x < s3d_tri->clip_l) - { - int diff_x = s3d_tri->clip_l - x; - - z += (s3d_tri->TdZdX * diff_x); - state->u += (s3d_tri->TdUdX * diff_x); - state->v += (s3d_tri->TdVdX * diff_x); - state->r += (s3d_tri->TdRdX * diff_x); - state->g += (s3d_tri->TdGdX * diff_x); - state->b += (s3d_tri->TdBdX * diff_x); - state->a += (s3d_tri->TdAdX * diff_x); - state->d += (s3d_tri->TdDdX * diff_x); - state->w += (s3d_tri->TdWdX * diff_x); - - x = s3d_tri->clip_l; - } - } - else - { - if (x < s3d_tri->clip_l) - goto tri_skip_line; - if (xe > s3d_tri->clip_r) - goto tri_skip_line; - if (xe < s3d_tri->clip_l) - xe = s3d_tri->clip_l - 1; - if (x > s3d_tri->clip_r) - { - int diff_x = x - s3d_tri->clip_r; - - z += (s3d_tri->TdZdX * diff_x); - state->u += (s3d_tri->TdUdX * diff_x); - state->v += (s3d_tri->TdVdX * diff_x); - state->r += (s3d_tri->TdRdX * diff_x); - state->g += (s3d_tri->TdGdX * diff_x); - state->b += (s3d_tri->TdBdX * diff_x); - state->a += (s3d_tri->TdAdX * diff_x); - state->d += (s3d_tri->TdDdX * diff_x); - state->w += (s3d_tri->TdWdX * diff_x); - - x = s3d_tri->clip_r; - } - } + dest_pixel(state); + + if (s3d_tri->cmd_set & CMD_SET_FE) { + int a = state->a >> 7; + state->dest_rgba.r = ((state->dest_rgba.r * a) + (s3d_tri->fog_r * (255 - a))) / 255; + state->dest_rgba.g = ((state->dest_rgba.g * a) + (s3d_tri->fog_g * (255 - a))) / 255; + state->dest_rgba.b = ((state->dest_rgba.b * a) + (s3d_tri->fog_b * (255 - a))) / 255; + } + + if (s3d_tri->cmd_set & CMD_SET_ABC_ENABLE) { + switch (bpp) { + case 0: /*8 bpp*/ + /*TODO: Not implemented yet*/ + break; + case 1: /*16 bpp*/ + src_col = *(uint16_t *) &vram[dest_addr & virge->vram_mask]; + RGB15_TO_24(src_col, src_r, src_g, src_b); + break; + case 2: /*24 bpp*/ + src_col = (*(uint32_t *) &vram[dest_addr & virge->vram_mask]) & 0xffffff; + RGB24_TO_24(src_col, src_r, src_g, src_b); + break; + + default: + break; } - svga->changedvram[(dest_offset & virge->vram_mask) >> 12] = changeframecount; + state->dest_rgba.r = ((state->dest_rgba.r * state->dest_rgba.a) + (src_r * (255 - state->dest_rgba.a))) / 255; + state->dest_rgba.g = ((state->dest_rgba.g * state->dest_rgba.a) + (src_g * (255 - state->dest_rgba.a))) / 255; + state->dest_rgba.b = ((state->dest_rgba.b * state->dest_rgba.a) + (src_b * (255 - state->dest_rgba.a))) / 255; + } - dest_addr = dest_offset + (x * (bpp + 1)); - z_addr = z_offset + (x << 1); + switch (bpp) { + case 0: /*8 bpp*/ + /*TODO: Not implemented yet*/ + break; + case 1: /*16 bpp*/ + RGB15(state->dest_rgba.r, state->dest_rgba.g, state->dest_rgba.b, dest_col); + *(uint16_t *) &vram[dest_addr & virge->vram_mask] = dest_col; + svga->changedvram[(dest_addr & virge->vram_mask) >> 12] = changeframecount; + break; + case 2: /*24 bpp*/ + dest_col = RGB24(state->dest_rgba.r, state->dest_rgba.g, state->dest_rgba.b); + *(uint8_t *) &vram[dest_addr & virge->vram_mask] = dest_col & 0xff; + *(uint8_t *) &vram[(dest_addr + 1) & virge->vram_mask] = (dest_col >> 8) & 0xff; + *(uint8_t *) &vram[(dest_addr + 2) & virge->vram_mask] = (dest_col >> 16) & 0xff; + svga->changedvram[(dest_addr & virge->vram_mask) >> 12] = changeframecount; + break; - x &= 0xfff; - xe &= 0xfff; - - while (x != xe) { - update = 1; - _x = x; _y = state->y; - - if (use_z) - { - src_z = *(uint16_t *)&vram[z_addr & virge->vram_mask]; - switch ((s3d_tri->cmd_set >> 20) & 7) { - case 0: - update = 0; - break; - case 1: - if ((z >> 16) > src_z) { - src_z = (z >> 16); - } else - update = 0; - break; - case 2: - if ((z >> 16) == src_z) { - src_z = (z >> 16); - } else - update = 0; - break; - case 3: - if ((z >> 16) >= src_z) { - src_z = (z >> 16); - } else - update = 0; - break; - case 4: - if ((z >> 16) < src_z) { - src_z = (z >> 16); - } else - update = 0; - break; - case 5: - if ((z >> 16) != src_z) { - src_z = (z >> 16); - } else - update = 0; - break; - case 6: - if ((z >> 16) <= src_z) { - src_z = (z >> 16); - } else - update = 0; - break; - case 7: - src_z = (z >> 16); - break; - } - } - - if (update) - { - uint32_t dest_col; - - dest_pixel(state); - - if (s3d_tri->cmd_set & CMD_SET_FE) - { - int a = state->a >> 7; - state->dest_rgba.r = ((state->dest_rgba.r * a) + (s3d_tri->fog_r * (255 - a))) / 255; - state->dest_rgba.g = ((state->dest_rgba.g * a) + (s3d_tri->fog_g * (255 - a))) / 255; - state->dest_rgba.b = ((state->dest_rgba.b * a) + (s3d_tri->fog_b * (255 - a))) / 255; - } - - if (s3d_tri->cmd_set & CMD_SET_ABC_ENABLE) - { - switch (bpp) - { - case 0: /*8 bpp*/ - /*Not implemented yet*/ - break; - case 1: /*16 bpp*/ - src_col = *(uint16_t *)&vram[dest_addr & virge->vram_mask]; - RGB15_TO_24(src_col, src_r, src_g, src_b); - break; - case 2: /*24 bpp*/ - src_col = (*(uint32_t *)&vram[dest_addr & virge->vram_mask]) & 0xffffff; - RGB24_TO_24(src_col, src_r, src_g, src_b); - break; - } - - state->dest_rgba.r = ((state->dest_rgba.r * state->dest_rgba.a) + (src_r * (255 - state->dest_rgba.a))) / 255; - state->dest_rgba.g = ((state->dest_rgba.g * state->dest_rgba.a) + (src_g * (255 - state->dest_rgba.a))) / 255; - state->dest_rgba.b = ((state->dest_rgba.b * state->dest_rgba.a) + (src_b * (255 - state->dest_rgba.a))) / 255; - } - - switch (bpp) - { - case 0: /*8 bpp*/ - /*Not implemented yet*/ - break; - case 1: /*16 bpp*/ - RGB15(state->dest_rgba.r, state->dest_rgba.g, state->dest_rgba.b, dest_col); - *(uint16_t *)&vram[dest_addr & virge->vram_mask] = dest_col; - svga->changedvram[(dest_addr & virge->vram_mask) >> 12] = changeframecount; - break; - case 2: /*24 bpp*/ - dest_col = RGB24(state->dest_rgba.r, state->dest_rgba.g, state->dest_rgba.b); - *(uint8_t *)&vram[dest_addr & virge->vram_mask] = dest_col & 0xff; - *(uint8_t *)&vram[(dest_addr + 1) & virge->vram_mask] = (dest_col >> 8) & 0xff; - *(uint8_t *)&vram[(dest_addr + 2) & virge->vram_mask] = (dest_col >> 16) & 0xff; - svga->changedvram[(dest_addr & virge->vram_mask) >> 12] = changeframecount; - break; - } - } - - if (use_z && (s3d_tri->cmd_set & CMD_SET_ZUP)) { - *(uint16_t *)&vram[z_addr & virge->vram_mask] = src_z; - svga->changedvram[(z_addr & virge->vram_mask) >> 12] = changeframecount; - } - - z += s3d_tri->TdZdX; - state->u += s3d_tri->TdUdX; - state->v += s3d_tri->TdVdX; - state->r += s3d_tri->TdRdX; - state->g += s3d_tri->TdGdX; - state->b += s3d_tri->TdBdX; - state->a += s3d_tri->TdAdX; - state->d += s3d_tri->TdDdX; - state->w += s3d_tri->TdWdX; - dest_addr += x_offset; - z_addr += xz_offset; - - x = (x + x_dir) & 0xfff; - } + default: + break; + } } - y_count--; - + if (use_z && (s3d_tri->cmd_set & CMD_SET_ZUP)) { + *(uint16_t *) &vram[z_addr & virge->vram_mask] = src_z; + svga->changedvram[(z_addr & virge->vram_mask) >> 12] = changeframecount; + } + + z += s3d_tri->TdZdX; + state->u += s3d_tri->TdUdX; + state->v += s3d_tri->TdVdX; + state->r += s3d_tri->TdRdX; + state->g += s3d_tri->TdGdX; + state->b += s3d_tri->TdBdX; + state->a += s3d_tri->TdAdX; + state->d += s3d_tri->TdDdX; + state->w += s3d_tri->TdWdX; + dest_addr += x_offset; + z_addr += xz_offset; + + x = (x + x_dir) & 0xfff; + } + } + + y_count--; + tri_skip_line: - state->x1 += dx1; - state->x2 += dx2; - state->base_u += s3d_tri->TdUdY; - state->base_v += s3d_tri->TdVdY; - state->base_z += s3d_tri->TdZdY; - state->base_r += s3d_tri->TdRdY; - state->base_g += s3d_tri->TdGdY; - state->base_b += s3d_tri->TdBdY; - state->base_a += s3d_tri->TdAdY; - state->base_d += s3d_tri->TdDdY; - state->base_w += s3d_tri->TdWdY; - state->y--; - dest_offset -= s3d_tri->dest_str; - z_offset -= s3d_tri->z_str; - } + state->x1 += dx1; + state->x2 += dx2; + state->base_u += s3d_tri->TdUdY; + state->base_v += s3d_tri->TdVdY; + state->base_z += s3d_tri->TdZdY; + state->base_r += s3d_tri->TdRdY; + state->base_g += s3d_tri->TdGdY; + state->base_b += s3d_tri->TdBdY; + state->base_a += s3d_tri->TdAdY; + state->base_d += s3d_tri->TdDdY; + state->base_w += s3d_tri->TdWdY; + state->y--; + dest_offset -= s3d_tri->dest_str; + z_offset -= s3d_tri->z_str; + } } -static int tex_size[8] = -{ - 4*2, - 2*2, - 2*2, - 1*2, - 2/1, - 2/1, - 1*2, - 1*2 +static int tex_size[8] = { + 4 * 2, + 2 * 2, + 2 * 2, + 1 * 2, + 2 / 1, + 2 / 1, + 1 * 2, + 1 * 2 }; -static void s3_virge_triangle(virge_t *virge, s3d_t *s3d_tri) +static void +s3_virge_triangle(virge_t *virge, s3d_t *s3d_tri) { - s3d_state_t state; + s3d_state_t state; - uint32_t tex_base; - int c; + uint32_t tex_base; - uint64_t start_time = plat_timer_read(); - uint64_t end_time; + uint64_t start_time = plat_timer_read(); + uint64_t end_time; - state.tbu = s3d_tri->tbu << 11; - state.tbv = s3d_tri->tbv << 11; - - state.max_d = (s3d_tri->cmd_set >> 8) & 15; - - state.tex_bdr_clr = s3d_tri->tex_bdr_clr; - - state.cmd_set = s3d_tri->cmd_set; + state.tbu = s3d_tri->tbu << 11; + state.tbv = s3d_tri->tbv << 11; - state.base_u = s3d_tri->tus; - state.base_v = s3d_tri->tvs; - state.base_z = s3d_tri->tzs; - state.base_r = (int32_t)s3d_tri->trs; - state.base_g = (int32_t)s3d_tri->tgs; - state.base_b = (int32_t)s3d_tri->tbs; - state.base_a = (int32_t)s3d_tri->tas; - state.base_d = s3d_tri->tds; - state.base_w = s3d_tri->tws; - - tex_base = s3d_tri->tex_base; - for (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; - } + state.max_d = (s3d_tri->cmd_set >> 8) & 15; - switch ((s3d_tri->cmd_set >> 27) & 0xf) - { + state.tex_bdr_clr = s3d_tri->tex_bdr_clr; + + state.cmd_set = s3d_tri->cmd_set; + + state.base_u = s3d_tri->tus; + state.base_v = s3d_tri->tvs; + state.base_z = s3d_tri->tzs; + state.base_r = (int32_t) s3d_tri->trs; + state.base_g = (int32_t) s3d_tri->tgs; + state.base_b = (int32_t) s3d_tri->tbs; + state.base_a = (int32_t) s3d_tri->tas; + state.base_d = s3d_tri->tds; + state.base_w = s3d_tri->tws; + + tex_base = s3d_tri->tex_base; + 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; + } + + switch ((s3d_tri->cmd_set >> 27) & 0xf) { + case 0: + dest_pixel = dest_pixel_gouraud_shaded_triangle; + break; + case 1: + case 5: + switch ((s3d_tri->cmd_set >> 15) & 0x3) { case 0: - dest_pixel = dest_pixel_gouraud_shaded_triangle; - break; + dest_pixel = dest_pixel_lit_texture_reflection; + break; case 1: - case 5: - switch ((s3d_tri->cmd_set >> 15) & 0x3) - { - case 0: - dest_pixel = dest_pixel_lit_texture_reflection; - break; - case 1: - dest_pixel = dest_pixel_lit_texture_modulate; - break; - case 2: - dest_pixel = dest_pixel_lit_texture_decal; - break; - default: - s3_virge_log("bad triangle type %x\n", (s3d_tri->cmd_set >> 27) & 0xf); - return; - } - break; + dest_pixel = dest_pixel_lit_texture_modulate; + break; case 2: - case 6: - dest_pixel = dest_pixel_unlit_texture_triangle; - break; + dest_pixel = dest_pixel_lit_texture_decal; + break; default: - s3_virge_log("bad triangle type %x\n", (s3d_tri->cmd_set >> 27) & 0xf); - return; - } - - switch (((s3d_tri->cmd_set >> 12) & 7) | ((s3d_tri->cmd_set & (1 << 29)) ? 8 : 0)) - { - case 0: case 1: - tex_sample = tex_sample_mipmap; - break; - case 2: case 3: - tex_sample = virge->bilinear_enabled ? tex_sample_mipmap_filter : tex_sample_mipmap; - break; - case 4: case 5: - tex_sample = tex_sample_normal; - break; - case 6: case 7: - tex_sample = virge->bilinear_enabled ? tex_sample_normal_filter : tex_sample_normal; - break; - case (0 | 8): case (1 | 8): - if (virge->chip == S3_VIRGEDX || virge->chip >= S3_VIRGEGX2) - tex_sample = tex_sample_persp_mipmap_375; - else - tex_sample = tex_sample_persp_mipmap; - break; - case (2 | 8): case (3 | 8): - if (virge->chip == S3_VIRGEDX || virge->chip >= S3_VIRGEGX2) - tex_sample = virge->bilinear_enabled ? tex_sample_persp_mipmap_filter_375 : tex_sample_persp_mipmap_375; - else - tex_sample = virge->bilinear_enabled ? tex_sample_persp_mipmap_filter : tex_sample_persp_mipmap; - break; - case (4 | 8): case (5 | 8): - if (virge->chip == S3_VIRGEDX || virge->chip >= S3_VIRGEGX2) - tex_sample = tex_sample_persp_normal_375; - else - tex_sample = tex_sample_persp_normal; - break; - case (6 | 8): case (7 | 8): - if (virge->chip == S3_VIRGEDX || virge->chip >= S3_VIRGEGX2) - tex_sample = virge->bilinear_enabled ? tex_sample_persp_normal_filter_375 : tex_sample_persp_normal_375; - else - tex_sample = virge->bilinear_enabled ? tex_sample_persp_normal_filter : tex_sample_persp_normal; - break; - } - - switch ((s3d_tri->cmd_set >> 5) & 7) - { - case 0: - tex_read = (s3d_tri->cmd_set & CMD_SET_TWE) ? tex_ARGB8888 : tex_ARGB8888_nowrap; - break; - case 1: - tex_read = (s3d_tri->cmd_set & CMD_SET_TWE) ? tex_ARGB4444 : tex_ARGB4444_nowrap; - break; - case 2: - tex_read = (s3d_tri->cmd_set & CMD_SET_TWE) ? tex_ARGB1555 : tex_ARGB1555_nowrap; - break; - default: - s3_virge_log("bad texture type %i\n", (s3d_tri->cmd_set >> 5) & 7); - tex_read = (s3d_tri->cmd_set & CMD_SET_TWE) ? tex_ARGB1555 : tex_ARGB1555_nowrap; - break; - } + s3_virge_log("bad triangle type %x\n", (s3d_tri->cmd_set >> 27) & 0xf); + return; + } + break; + case 2: + case 6: + dest_pixel = dest_pixel_unlit_texture_triangle; + break; + default: + s3_virge_log("bad triangle type %x\n", (s3d_tri->cmd_set >> 27) & 0xf); + return; + } - state.y = s3d_tri->tys; - state.x1 = s3d_tri->txs; - state.x2 = s3d_tri->txend01; - tri(virge, s3d_tri, &state, s3d_tri->ty01, s3d_tri->TdXdY02, s3d_tri->TdXdY01); - state.x2 = s3d_tri->txend12; - tri(virge, s3d_tri, &state, s3d_tri->ty12, s3d_tri->TdXdY02, s3d_tri->TdXdY12); - - end_time = plat_timer_read(); - - virge->blitter_time += end_time - start_time; + switch (((s3d_tri->cmd_set >> 12) & 7) | ((s3d_tri->cmd_set & (1 << 29)) ? 8 : 0)) { + case 0: + case 1: + tex_sample = tex_sample_mipmap; + break; + case 2: + case 3: + tex_sample = virge->bilinear_enabled ? tex_sample_mipmap_filter : tex_sample_mipmap; + break; + case 4: + case 5: + tex_sample = tex_sample_normal; + break; + case 6: + case 7: + tex_sample = virge->bilinear_enabled ? tex_sample_normal_filter : tex_sample_normal; + break; + case (0 | 8): + case (1 | 8): + if (virge->chip == S3_VIRGEDX || virge->chip >= S3_VIRGEGX2) + tex_sample = tex_sample_persp_mipmap_375; + else + tex_sample = tex_sample_persp_mipmap; + break; + case (2 | 8): + case (3 | 8): + if (virge->chip == S3_VIRGEDX || virge->chip >= S3_VIRGEGX2) + tex_sample = virge->bilinear_enabled ? tex_sample_persp_mipmap_filter_375 : tex_sample_persp_mipmap_375; + else + tex_sample = virge->bilinear_enabled ? tex_sample_persp_mipmap_filter : tex_sample_persp_mipmap; + break; + case (4 | 8): + case (5 | 8): + if (virge->chip == S3_VIRGEDX || virge->chip >= S3_VIRGEGX2) + tex_sample = tex_sample_persp_normal_375; + else + tex_sample = tex_sample_persp_normal; + break; + case (6 | 8): + case (7 | 8): + if (virge->chip == S3_VIRGEDX || virge->chip >= S3_VIRGEGX2) + tex_sample = virge->bilinear_enabled ? tex_sample_persp_normal_filter_375 : tex_sample_persp_normal_375; + else + tex_sample = virge->bilinear_enabled ? tex_sample_persp_normal_filter : tex_sample_persp_normal; + break; + + default: + break; + } + + switch ((s3d_tri->cmd_set >> 5) & 7) { + case 0: + tex_read = (s3d_tri->cmd_set & CMD_SET_TWE) ? tex_ARGB8888 : tex_ARGB8888_nowrap; + break; + case 1: + tex_read = (s3d_tri->cmd_set & CMD_SET_TWE) ? tex_ARGB4444 : tex_ARGB4444_nowrap; + break; + case 2: + tex_read = (s3d_tri->cmd_set & CMD_SET_TWE) ? tex_ARGB1555 : tex_ARGB1555_nowrap; + break; + default: + s3_virge_log("bad texture type %i\n", (s3d_tri->cmd_set >> 5) & 7); + tex_read = (s3d_tri->cmd_set & CMD_SET_TWE) ? tex_ARGB1555 : tex_ARGB1555_nowrap; + break; + } + + state.y = s3d_tri->tys; + state.x1 = s3d_tri->txs; + state.x2 = s3d_tri->txend01; + tri(virge, s3d_tri, &state, s3d_tri->ty01, s3d_tri->TdXdY02, s3d_tri->TdXdY01); + state.x2 = s3d_tri->txend12; + tri(virge, s3d_tri, &state, s3d_tri->ty12, s3d_tri->TdXdY02, s3d_tri->TdXdY12); + + end_time = plat_timer_read(); + + virge->blitter_time += end_time - start_time; } -static void s3_virge_hwcursor_draw(svga_t *svga, int displine) +static void +s3_virge_hwcursor_draw(svga_t *svga, int displine) { - virge_t *virge = (virge_t *)svga->p; - int x; - uint16_t dat[2]; - int xx; - int offset = svga->hwcursor_latch.x - svga->hwcursor_latch.xoff; - uint32_t fg, bg; - uint32_t vram_mask = virge->vram_mask; + const virge_t *virge = (virge_t *) svga->priv; + uint16_t dat[2]; + int xx; + int offset = svga->hwcursor_latch.x - svga->hwcursor_latch.xoff; + uint32_t fg; + uint32_t bg; + uint32_t vram_mask = virge->vram_mask; - if (svga->interlace && svga->hwcursor_oddeven) - svga->hwcursor_latch.addr += 16; + if (svga->interlace && svga->hwcursor_oddeven) + svga->hwcursor_latch.addr += 16; - switch (svga->bpp) - { - case 15: - fg = video_15to32[virge->hwc_fg_col & 0xffff]; - bg = video_15to32[virge->hwc_bg_col & 0xffff]; - break; - - case 16: - fg = video_16to32[virge->hwc_fg_col & 0xffff]; - bg = video_16to32[virge->hwc_bg_col & 0xffff]; - break; - - case 24: case 32: - fg = virge->hwc_fg_col; - bg = virge->hwc_bg_col; - break; - - default: + switch (svga->bpp) { + default: + if (virge->chip != S3_VIRGEGX2) { fg = svga->pallook[virge->hwc_fg_col & 0xff]; bg = svga->pallook[virge->hwc_bg_col & 0xff]; break; - } + } + fallthrough; - for (x = 0; x < 64; x += 16) - { - dat[0] = (svga->vram[svga->hwcursor_latch.addr & vram_mask] << 8) | svga->vram[(svga->hwcursor_latch.addr + 1) & vram_mask]; - dat[1] = (svga->vram[(svga->hwcursor_latch.addr + 2) & vram_mask] << 8) | svga->vram[(svga->hwcursor_latch.addr + 3) & vram_mask]; - if (svga->crtc[0x55] & 0x10) - { - /*X11*/ - for (xx = 0; xx < 16; xx++) - { - if (offset >= 0) - { - if (dat[0] & 0x8000) - buffer32->line[displine][offset + svga->x_add] = (dat[1] & 0x8000) ? fg : bg; - } - - offset++; - dat[0] <<= 1; - dat[1] <<= 1; - } + case 15: + if (virge->chip != S3_VIRGEGX2) { + fg = video_15to32[virge->hwc_fg_col & 0xffff]; + bg = video_15to32[virge->hwc_bg_col & 0xffff]; + break; + } + fallthrough; + + case 16: + if (virge->chip != S3_VIRGEGX2) { + fg = video_16to32[virge->hwc_fg_col & 0xffff]; + bg = video_16to32[virge->hwc_bg_col & 0xffff]; + break; + } + fallthrough; + + case 24: + case 32: + fg = virge->hwc_fg_col; + bg = virge->hwc_bg_col; + break; + } + + for (uint8_t x = 0; x < 64; x += 16) { + dat[0] = (svga->vram[svga->hwcursor_latch.addr & vram_mask] << 8) | svga->vram[(svga->hwcursor_latch.addr + 1) & vram_mask]; + dat[1] = (svga->vram[(svga->hwcursor_latch.addr + 2) & vram_mask] << 8) | svga->vram[(svga->hwcursor_latch.addr + 3) & vram_mask]; + if (svga->crtc[0x55] & 0x10) { + /*X11*/ + for (xx = 0; xx < 16; xx++) { + if (offset >= 0) { + if (virge->chip == S3_VIRGEGX2) + dat[0] ^= 0x8000; + + if (dat[0] & 0x8000) + buffer32->line[displine][offset + svga->x_add] = (dat[1] & 0x8000) ? fg : bg; } - else - { - /*Windows*/ - for (xx = 0; xx < 16; xx++) - { - if (offset >= 0) - { - if (!(dat[0] & 0x8000)) - buffer32->line[displine][offset + svga->x_add] = (dat[1] & 0x8000) ? fg : bg; - else if (dat[1] & 0x8000) - buffer32->line[displine][offset + svga->x_add] ^= 0xffffff; - } - - offset++; - dat[0] <<= 1; - dat[1] <<= 1; - } + + offset++; + dat[0] <<= 1; + dat[1] <<= 1; + } + } else { + /*Windows*/ + for (xx = 0; xx < 16; xx++) { + if (offset >= 0) { + if (!(dat[0] & 0x8000)) + buffer32->line[displine][offset + svga->x_add] = (dat[1] & 0x8000) ? fg : bg; + else if (dat[1] & 0x8000) + buffer32->line[displine][offset + svga->x_add] ^= 0xffffff; } - svga->hwcursor_latch.addr += 4; + + offset++; + dat[0] <<= 1; + dat[1] <<= 1; + } } - if (svga->interlace && !svga->hwcursor_oddeven) - svga->hwcursor_latch.addr += 16; + svga->hwcursor_latch.addr += 4; + } + if (svga->interlace && !svga->hwcursor_oddeven) + svga->hwcursor_latch.addr += 16; } -#define DECODE_YCbCr() \ - do \ - { \ - int c; \ - \ - for (c = 0; c < 2; c++) \ - { \ - uint8_t y1, y2; \ - int8_t Cr, Cb; \ - int dR, dG, dB; \ - \ - y1 = src[0]; \ - Cr = src[1] - 0x80; \ - y2 = src[2]; \ - Cb = src[3] - 0x80; \ - src += 4; \ - \ - dR = (359*Cr) >> 8; \ - dG = (88*Cb + 183*Cr) >> 8; \ - dB = (453*Cb) >> 8; \ - \ - r[x_write] = y1 + dR; \ - CLAMP(r[x_write]); \ - g[x_write] = y1 - dG; \ - CLAMP(g[x_write]); \ - b[x_write] = y1 + dB; \ - CLAMP(b[x_write]); \ - \ - r[x_write+1] = y2 + dR; \ - CLAMP(r[x_write+1]); \ - g[x_write+1] = y2 - dG; \ - CLAMP(g[x_write+1]); \ - b[x_write+1] = y2 + dB; \ - CLAMP(b[x_write+1]); \ - \ - x_write = (x_write + 2) & 7; \ - } \ - } while (0) +#define DECODE_YCbCr() \ + do { \ + int c; \ + \ + for (c = 0; c < 2; c++) { \ + uint8_t y1, y2; \ + int8_t Cr, Cb; \ + int dR, dG, dB; \ + \ + y1 = src[0]; \ + Cr = src[1] - 0x80; \ + y2 = src[2]; \ + Cb = src[3] - 0x80; \ + src += 4; \ + \ + dR = (359 * Cr) >> 8; \ + dG = (88 * Cb + 183 * Cr) >> 8; \ + dB = (453 * Cb) >> 8; \ + \ + r[x_write] = y1 + dR; \ + CLAMP(r[x_write]); \ + g[x_write] = y1 - dG; \ + CLAMP(g[x_write]); \ + b[x_write] = y1 + dB; \ + CLAMP(b[x_write]); \ + \ + r[x_write + 1] = y2 + dR; \ + CLAMP(r[x_write + 1]); \ + g[x_write + 1] = y2 - dG; \ + CLAMP(g[x_write + 1]); \ + b[x_write + 1] = y2 + dB; \ + CLAMP(b[x_write + 1]); \ + \ + x_write = (x_write + 2) & 7; \ + } \ + } while (0) /*Both YUV formats are untested*/ -#define DECODE_YUV211() \ - do \ - { \ - uint8_t y1, y2, y3, y4; \ - int8_t U, V; \ - int dR, dG, dB; \ - \ - U = src[0] - 0x80; \ - y1 = (298 * (src[1] - 16)) >> 8; \ - y2 = (298 * (src[2] - 16)) >> 8; \ - V = src[3] - 0x80; \ - y3 = (298 * (src[4] - 16)) >> 8; \ - y4 = (298 * (src[5] - 16)) >> 8; \ - src += 6; \ - \ - dR = (309*V) >> 8; \ - dG = (100*U + 208*V) >> 8; \ - dB = (516*U) >> 8; \ - \ - r[x_write] = y1 + dR; \ - CLAMP(r[x_write]); \ - g[x_write] = y1 - dG; \ - CLAMP(g[x_write]); \ - b[x_write] = y1 + dB; \ - CLAMP(b[x_write]); \ - \ - r[x_write+1] = y2 + dR; \ - CLAMP(r[x_write+1]); \ - g[x_write+1] = y2 - dG; \ - CLAMP(g[x_write+1]); \ - b[x_write+1] = y2 + dB; \ - CLAMP(b[x_write+1]); \ - \ - r[x_write+2] = y3 + dR; \ - CLAMP(r[x_write+2]); \ - g[x_write+2] = y3 - dG; \ - CLAMP(g[x_write+2]); \ - b[x_write+2] = y3 + dB; \ - CLAMP(b[x_write+2]); \ - \ - r[x_write+3] = y4 + dR; \ - CLAMP(r[x_write+3]); \ - g[x_write+3] = y4 - dG; \ - CLAMP(g[x_write+3]); \ - b[x_write+3] = y4 + dB; \ - CLAMP(b[x_write+3]); \ - \ - x_write = (x_write + 4) & 7; \ - } while (0) +#define DECODE_YUV211() \ + do { \ + uint8_t y1, y2, y3, y4; \ + int8_t U, V; \ + int dR, dG, dB; \ + \ + U = src[0] - 0x80; \ + y1 = (298 * (src[1] - 16)) >> 8; \ + y2 = (298 * (src[2] - 16)) >> 8; \ + V = src[3] - 0x80; \ + y3 = (298 * (src[4] - 16)) >> 8; \ + y4 = (298 * (src[5] - 16)) >> 8; \ + src += 6; \ + \ + dR = (309 * V) >> 8; \ + dG = (100 * U + 208 * V) >> 8; \ + dB = (516 * U) >> 8; \ + \ + r[x_write] = y1 + dR; \ + CLAMP(r[x_write]); \ + g[x_write] = y1 - dG; \ + CLAMP(g[x_write]); \ + b[x_write] = y1 + dB; \ + CLAMP(b[x_write]); \ + \ + r[x_write + 1] = y2 + dR; \ + CLAMP(r[x_write + 1]); \ + g[x_write + 1] = y2 - dG; \ + CLAMP(g[x_write + 1]); \ + b[x_write + 1] = y2 + dB; \ + CLAMP(b[x_write + 1]); \ + \ + r[x_write + 2] = y3 + dR; \ + CLAMP(r[x_write + 2]); \ + g[x_write + 2] = y3 - dG; \ + CLAMP(g[x_write + 2]); \ + b[x_write + 2] = y3 + dB; \ + CLAMP(b[x_write + 2]); \ + \ + r[x_write + 3] = y4 + dR; \ + CLAMP(r[x_write + 3]); \ + g[x_write + 3] = y4 - dG; \ + CLAMP(g[x_write + 3]); \ + b[x_write + 3] = y4 + dB; \ + CLAMP(b[x_write + 3]); \ + \ + x_write = (x_write + 4) & 7; \ + } while (0) -#define DECODE_YUV422() \ - do \ - { \ - int c; \ - \ - for (c = 0; c < 2; c++) \ - { \ - uint8_t y1, y2; \ - int8_t U, V; \ - int dR, dG, dB; \ - \ - U = src[0] - 0x80; \ - y1 = (298 * (src[1] - 16)) >> 8; \ - V = src[2] - 0x80; \ - y2 = (298 * (src[3] - 16)) >> 8; \ - src += 4; \ - \ - dR = (309*V) >> 8; \ - dG = (100*U + 208*V) >> 8; \ - dB = (516*U) >> 8; \ - \ - r[x_write] = y1 + dR; \ - CLAMP(r[x_write]); \ - g[x_write] = y1 - dG; \ - CLAMP(g[x_write]); \ - b[x_write] = y1 + dB; \ - CLAMP(b[x_write]); \ - \ - r[x_write+1] = y2 + dR; \ - CLAMP(r[x_write+1]); \ - g[x_write+1] = y2 - dG; \ - CLAMP(g[x_write+1]); \ - b[x_write+1] = y2 + dB; \ - CLAMP(b[x_write+1]); \ - \ - x_write = (x_write + 2) & 7; \ - } \ - } while (0) +#define DECODE_YUV422() \ + do { \ + int c; \ + \ + for (c = 0; c < 2; c++) { \ + uint8_t y1, y2; \ + int8_t U, V; \ + int dR, dG, dB; \ + \ + U = src[0] - 0x80; \ + y1 = (298 * (src[1] - 16)) >> 8; \ + V = src[2] - 0x80; \ + y2 = (298 * (src[3] - 16)) >> 8; \ + src += 4; \ + \ + dR = (309 * V) >> 8; \ + dG = (100 * U + 208 * V) >> 8; \ + dB = (516 * U) >> 8; \ + \ + r[x_write] = y1 + dR; \ + CLAMP(r[x_write]); \ + g[x_write] = y1 - dG; \ + CLAMP(g[x_write]); \ + b[x_write] = y1 + dB; \ + CLAMP(b[x_write]); \ + \ + r[x_write + 1] = y2 + dR; \ + CLAMP(r[x_write + 1]); \ + g[x_write + 1] = y2 - dG; \ + CLAMP(g[x_write + 1]); \ + b[x_write + 1] = y2 + dB; \ + CLAMP(b[x_write + 1]); \ + \ + x_write = (x_write + 2) & 7; \ + } \ + } while (0) -#define DECODE_RGB555() \ - do \ - { \ - int c; \ - \ - for (c = 0; c < 4; c++) \ - { \ - uint16_t dat; \ - \ - dat = *(uint16_t *)src; \ - src += 2; \ - \ - r[x_write + c] = ((dat & 0x001f) << 3) | ((dat & 0x001f) >> 2); \ - g[x_write + c] = ((dat & 0x03e0) >> 2) | ((dat & 0x03e0) >> 7); \ - b[x_write + c] = ((dat & 0x7c00) >> 7) | ((dat & 0x7c00) >> 12); \ - } \ - x_write = (x_write + 4) & 7; \ - } while (0) +#define DECODE_RGB555() \ + do { \ + int c; \ + \ + for (c = 0; c < 4; c++) { \ + uint16_t dat; \ + \ + dat = *(uint16_t *) src; \ + src += 2; \ + \ + r[x_write + c] = ((dat & 0x001f) << 3) | ((dat & 0x001f) >> 2); \ + g[x_write + c] = ((dat & 0x03e0) >> 2) | ((dat & 0x03e0) >> 7); \ + b[x_write + c] = ((dat & 0x7c00) >> 7) | ((dat & 0x7c00) >> 12); \ + } \ + x_write = (x_write + 4) & 7; \ + } while (0) -#define DECODE_RGB565() \ - do \ - { \ - int c; \ - \ - for (c = 0; c < 4; c++) \ - { \ - uint16_t dat; \ - \ - dat = *(uint16_t *)src; \ - src += 2; \ - \ - r[x_write + c] = ((dat & 0x001f) << 3) | ((dat & 0x001f) >> 2); \ - g[x_write + c] = ((dat & 0x07e0) >> 3) | ((dat & 0x07e0) >> 9); \ - b[x_write + c] = ((dat & 0xf800) >> 8) | ((dat & 0xf800) >> 13); \ - } \ - x_write = (x_write + 4) & 7; \ - } while (0) +#define DECODE_RGB565() \ + do { \ + int c; \ + \ + for (c = 0; c < 4; c++) { \ + uint16_t dat; \ + \ + dat = *(uint16_t *) src; \ + src += 2; \ + \ + r[x_write + c] = ((dat & 0x001f) << 3) | ((dat & 0x001f) >> 2); \ + g[x_write + c] = ((dat & 0x07e0) >> 3) | ((dat & 0x07e0) >> 9); \ + b[x_write + c] = ((dat & 0xf800) >> 8) | ((dat & 0xf800) >> 13); \ + } \ + x_write = (x_write + 4) & 7; \ + } while (0) -#define DECODE_RGB888() \ - do \ - { \ - int c; \ - \ - for (c = 0; c < 4; c++) \ - { \ - r[x_write + c] = src[0]; \ - g[x_write + c] = src[1]; \ - b[x_write + c] = src[2]; \ - src += 3; \ - } \ - x_write = (x_write + 4) & 7; \ - } while (0) +#define DECODE_RGB888() \ + do { \ + int c; \ + \ + for (c = 0; c < 4; c++) { \ + r[x_write + c] = src[0]; \ + g[x_write + c] = src[1]; \ + b[x_write + c] = src[2]; \ + src += 3; \ + } \ + x_write = (x_write + 4) & 7; \ + } while (0) -#define DECODE_XRGB8888() \ - do \ - { \ - int c; \ - \ - for (c = 0; c < 4; c++) \ - { \ - r[x_write + c] = src[0]; \ - g[x_write + c] = src[1]; \ - b[x_write + c] = src[2]; \ - src += 4; \ - } \ - x_write = (x_write + 4) & 7; \ - } while (0) +#define DECODE_XRGB8888() \ + do { \ + int c; \ + \ + for (c = 0; c < 4; c++) { \ + r[x_write + c] = src[0]; \ + g[x_write + c] = src[1]; \ + b[x_write + c] = src[2]; \ + src += 4; \ + } \ + x_write = (x_write + 4) & 7; \ + } while (0) -#define OVERLAY_SAMPLE() \ - do \ - { \ - switch (virge->streams.sdif) \ - { \ - case 1: \ - DECODE_YCbCr(); \ - break; \ - case 2: \ - DECODE_YUV422(); \ - break; \ - case 3: \ - DECODE_RGB555(); \ - break; \ - case 4: \ - DECODE_YUV211(); \ - break; \ - case 5: \ - DECODE_RGB565(); \ - break; \ - case 6: \ - DECODE_RGB888(); \ - break; \ - case 7: \ - default: \ - DECODE_XRGB8888(); \ - break; \ - } \ - } while (0) +#define OVERLAY_SAMPLE() \ + do { \ + switch (virge->streams.sdif) { \ + case 1: \ + DECODE_YCbCr(); \ + break; \ + case 2: \ + DECODE_YUV422(); \ + break; \ + case 3: \ + DECODE_RGB555(); \ + break; \ + case 4: \ + DECODE_YUV211(); \ + break; \ + case 5: \ + DECODE_RGB565(); \ + break; \ + case 6: \ + DECODE_RGB888(); \ + break; \ + case 7: \ + default: \ + DECODE_XRGB8888(); \ + break; \ + } \ + } while (0) -static void s3_virge_overlay_draw(svga_t *svga, int displine) +static void +s3_virge_overlay_draw(svga_t *svga, int displine) { - virge_t *virge = (virge_t *)svga->p; - int offset = (virge->streams.sec_x - virge->streams.pri_x) + 1; - int h_acc = virge->streams.dda_horiz_accumulator; - int r[8], g[8], b[8]; - int x_size, x_read = 4, x_write = 4; - int x; - uint32_t *p; - uint8_t *src = &svga->vram[svga->overlay_latch.addr]; - - p = &(buffer32->line[displine][offset + svga->x_add]); + const virge_t *virge = (virge_t *) svga->priv; + int offset = (virge->streams.sec_x - virge->streams.pri_x) + 1; + int h_acc = virge->streams.dda_horiz_accumulator; + int r[8]; + int g[8]; + int b[8]; + int x_size; + int x_read = 4; + int x_write = 4; + uint32_t *p; + uint8_t *src = &svga->vram[svga->overlay_latch.addr]; - if ((offset + virge->streams.sec_w) > virge->streams.pri_w) - x_size = (virge->streams.pri_w - virge->streams.sec_x) + 1; - else - x_size = virge->streams.sec_w + 1; + p = &(buffer32->line[displine][offset + svga->x_add]); - OVERLAY_SAMPLE(); - - for (x = 0; x < x_size; x++) - { - *p++ = r[x_read] | (g[x_read] << 8) | (b[x_read] << 16); + if ((offset + virge->streams.sec_w) > virge->streams.pri_w) + x_size = (virge->streams.pri_w - virge->streams.sec_x) + 1; + else + x_size = virge->streams.sec_w + 1; - h_acc += virge->streams.k1_horiz_scale; - if (h_acc >= 0) - { - if ((x_read ^ (x_read + 1)) & ~3) - OVERLAY_SAMPLE(); - x_read = (x_read + 1) & 7; + OVERLAY_SAMPLE(); - h_acc += (virge->streams.k2_horiz_scale - virge->streams.k1_horiz_scale); - } + for (int x = 0; x < x_size; x++) { + *p++ = r[x_read] | (g[x_read] << 8) | (b[x_read] << 16); + + h_acc += virge->streams.k1_horiz_scale; + if (h_acc >= 0) { + if ((x_read ^ (x_read + 1)) & ~3) + OVERLAY_SAMPLE(); + x_read = (x_read + 1) & 7; + + h_acc += (virge->streams.k2_horiz_scale - virge->streams.k1_horiz_scale); } + } - svga->overlay_latch.v_acc += virge->streams.k1_vert_scale; - if (svga->overlay_latch.v_acc >= 0) - { - svga->overlay_latch.v_acc += (virge->streams.k2_vert_scale - virge->streams.k1_vert_scale); - svga->overlay_latch.addr += virge->streams.sec_stride; - } + svga->overlay_latch.v_acc += virge->streams.k1_vert_scale; + if (svga->overlay_latch.v_acc >= 0) { + svga->overlay_latch.v_acc += (virge->streams.k2_vert_scale - virge->streams.k1_vert_scale); + svga->overlay_latch.addr += virge->streams.sec_stride; + } } -static uint8_t s3_virge_pci_read(int func, int addr, void *p) +static uint8_t +s3_virge_pci_read(UNUSED(int func), int addr, void *priv) { - virge_t *virge = (virge_t *)p; - svga_t *svga = &virge->svga; - uint8_t ret = 0; + const virge_t *virge = (virge_t *) priv; + const svga_t *svga = &virge->svga; + uint8_t ret = 0; - switch (addr) { - case 0x00: ret = 0x33; break; /*'S3'*/ - case 0x01: ret = 0x53; break; - - case 0x02: ret = virge->virge_id_low; break; - case 0x03: ret = virge->virge_id_high; break; + switch (addr) { + case 0x00: + ret = 0x33; + break; /*'S3'*/ + case 0x01: + ret = 0x53; + break; - case PCI_REG_COMMAND: ret = virge->pci_regs[PCI_REG_COMMAND] & 0x27; break; - - case 0x07: ret = virge->pci_regs[0x07] & 0x36; break; - - case 0x08: ret = virge->virge_rev; break; /*Revision ID*/ - case 0x09: ret = 0; break; /*Programming interface*/ - - case 0x0a: ret = 0x00; break; /*Supports VGA interface*/ - case 0x0b: ret = 0x03; break; + case 0x02: + ret = virge->virge_id_low; + break; + case 0x03: + ret = virge->virge_id_high; + break; - case 0x0d: ret = virge->pci_regs[0x0d] & 0xf8; break; - - case 0x10: ret = 0x00; break;/*Linear frame buffer address*/ - case 0x11: ret = 0x00; break; - case 0x12: ret = 0x00; break; - case 0x13: ret = (virge->chip == S3_VIRGEVX || virge->chip == S3_TRIO3D2X) ? (svga->crtc[0x59] & 0xfe) : (svga->crtc[0x59] & 0xfc); break; + case PCI_REG_COMMAND: + ret = virge->pci_regs[PCI_REG_COMMAND] & 0x27; + break; - case 0x2c: ret = 0x33; break; /* Subsystem vendor ID */ - case 0x2d: ret = 0x53; break; - case 0x2e: ret = virge->virge_id_low; break; - case 0x2f: ret = virge->virge_id_high; break; + case 0x07: + ret = virge->pci_regs[0x07] & 0x36; + break; - case 0x30: ret = virge->pci_regs[0x30] & 0x01; break; /*BIOS ROM address*/ - case 0x31: ret = 0x00; break; - case 0x32: ret = virge->pci_regs[0x32]; break; - case 0x33: ret = virge->pci_regs[0x33]; break; + case 0x08: + ret = virge->virge_rev; + break; /*Revision ID*/ + case 0x09: + ret = 0; + break; /*Programming interface*/ - case 0x34: ret = (virge->chip >= S3_VIRGEGX2) ? 0xdc : 0x00; break; + case 0x0a: + ret = 0x00; + break; /*Supports VGA interface*/ + case 0x0b: + ret = 0x03; + break; - case 0x3c: ret = virge->pci_regs[0x3c]; break; - - case 0x3d: ret = PCI_INTA; break; /*INTA*/ - - case 0x3e: ret = 0x04; break; - case 0x3f: ret = 0xff; break; - - case 0x80: ret = 0x02; break; /* AGP capability */ - case 0x81: ret = 0x00; break; - case 0x82: ret = 0x10; break; /* assumed AGP 1.0 */ + case 0x0d: + ret = virge->pci_regs[0x0d] & 0xf8; + break; - case 0x84: ret = (virge->chip >= S3_TRIO3D2X) ? 0x03 : 0x01; break; - case 0x87: ret = 0x1f; break; + case 0x10: + ret = 0x00; + break; /*Linear frame buffer address*/ + case 0x11: + ret = 0x00; + break; + case 0x12: + ret = 0x00; + break; + case 0x13: + ret = (virge->chip == S3_VIRGEVX || virge->chip == S3_TRIO3D2X) ? (svga->crtc[0x59] & 0xfe) : (svga->crtc[0x59] & 0xfc); + break; - case 0x88: ret = virge->pci_regs[0x88]; break; - case 0x89: ret = virge->pci_regs[0x89]; break; - case 0x8a: ret = virge->pci_regs[0x8a]; break; - case 0x8b: ret = virge->pci_regs[0x8b]; break; + case 0x2c: + ret = 0x33; + break; /* Subsystem vendor ID */ + case 0x2d: + ret = 0x53; + break; + case 0x2e: + ret = virge->virge_id_low; + break; + case 0x2f: + ret = virge->virge_id_high; + break; - case 0xdc: ret = 0x01; break; /* PCI Power Management capability */ - case 0xdd: ret = virge->is_agp ? 0x80 : 0x00; break; - case 0xde: ret = 0x21; break; + case 0x30: + ret = virge->pci_regs[0x30] & 0x01; + break; /*BIOS ROM address*/ + case 0x31: + ret = 0x00; + break; + case 0x32: + ret = virge->pci_regs[0x32]; + break; + case 0x33: + ret = virge->pci_regs[0x33]; + break; - case 0xe0: ret = virge->pci_regs[0xe0]; break; - case 0xe1: ret = virge->pci_regs[0xe1]; break; - case 0xe2: ret = virge->pci_regs[0xe2]; break; - case 0xe3: ret = virge->pci_regs[0xe3]; break; - } - return ret; + case 0x34: + ret = (virge->chip >= S3_VIRGEGX2) ? 0xdc : 0x00; + break; + + case 0x3c: + ret = virge->pci_regs[0x3c]; + break; + + case 0x3d: + ret = PCI_INTA; + break; /*INTA*/ + + case 0x3e: + ret = 0x04; + break; + case 0x3f: + ret = 0xff; + break; + + case 0x80: + ret = 0x02; + break; /* AGP capability */ + case 0x81: + ret = 0x00; + break; + case 0x82: + ret = 0x10; + break; /* assumed AGP 1.0 */ + + case 0x84: + ret = (virge->chip >= S3_TRIO3D2X) ? 0x03 : 0x01; + break; + case 0x87: + ret = 0x1f; + break; + + case 0x88: + ret = virge->pci_regs[0x88]; + break; + case 0x89: + ret = virge->pci_regs[0x89]; + break; + case 0x8a: + ret = virge->pci_regs[0x8a]; + break; + case 0x8b: + ret = virge->pci_regs[0x8b]; + break; + + case 0xdc: + ret = 0x01; + break; /* PCI Power Management capability */ + case 0xdd: + ret = virge->is_agp ? 0x80 : 0x00; + break; + case 0xde: + ret = 0x21; + break; + + case 0xe0: + ret = virge->pci_regs[0xe0]; + break; + case 0xe1: + ret = virge->pci_regs[0xe1]; + break; + case 0xe2: + ret = virge->pci_regs[0xe2]; + break; + case 0xe3: + ret = virge->pci_regs[0xe3]; + break; + + default: + break; + } + return ret; } -static void s3_virge_pci_write(int func, int addr, uint8_t val, void *p) +static void +s3_virge_pci_write(UNUSED(int func), int addr, uint8_t val, void *priv) { - virge_t *virge = (virge_t *)p; - svga_t *svga = &virge->svga; - switch (addr) - { - case 0x00: case 0x01: case 0x02: case 0x03: - case 0x08: case 0x09: case 0x0a: case 0x0b: - case 0x3d: case 0x3e: case 0x3f: - return; - - case PCI_REG_COMMAND: - if (val & PCI_COMMAND_IO) - { - io_removehandler(0x03c0, 0x0020, s3_virge_in, NULL, NULL, s3_virge_out, NULL, NULL, virge); - io_sethandler(0x03c0, 0x0020, s3_virge_in, NULL, NULL, s3_virge_out, NULL, NULL, virge); - } + virge_t *virge = (virge_t *) priv; + svga_t *svga = &virge->svga; + switch (addr) { + case 0x00: + case 0x01: + case 0x02: + case 0x03: + case 0x08: + case 0x09: + case 0x0a: + case 0x0b: + case 0x3d: + case 0x3e: + case 0x3f: + return; + + case PCI_REG_COMMAND: + if (val & PCI_COMMAND_IO) { + io_removehandler(0x03c0, 0x0020, s3_virge_in, NULL, NULL, s3_virge_out, NULL, NULL, virge); + io_sethandler(0x03c0, 0x0020, s3_virge_in, NULL, NULL, s3_virge_out, NULL, NULL, virge); + } else + io_removehandler(0x03c0, 0x0020, s3_virge_in, NULL, NULL, s3_virge_out, NULL, NULL, virge); + virge->pci_regs[PCI_REG_COMMAND] = val & 0x27; + s3_virge_updatemapping(virge); + return; + case 0x07: + virge->pci_regs[0x07] = val & 0x3e; + return; + case 0x0d: + virge->pci_regs[0x0d] = val & 0xf8; + return; + + case 0x13: + svga->crtc[0x59] = (virge->chip == S3_VIRGEVX || virge->chip == S3_TRIO3D2X) ? (val & 0xfe) : (val & 0xfc); + s3_virge_updatemapping(virge); + return; + + case 0x30: + case 0x32: + case 0x33: + virge->pci_regs[addr] = val; + if (virge->pci_regs[0x30] & 0x01) { + uint32_t biosaddr = (virge->pci_regs[0x32] << 16) | (virge->pci_regs[0x33] << 24); + if (virge->chip == S3_VIRGEGX2) + mem_mapping_set_addr(&virge->bios_rom.mapping, biosaddr, 0x10000); else - io_removehandler(0x03c0, 0x0020, s3_virge_in, NULL, NULL, s3_virge_out, NULL, NULL, virge); - virge->pci_regs[PCI_REG_COMMAND] = val & 0x27; - s3_virge_updatemapping(virge); - return; - case 0x07: - virge->pci_regs[0x07] = val & 0x3e; - return; - case 0x0d: - virge->pci_regs[0x0d] = val & 0xf8; - return; + mem_mapping_set_addr(&virge->bios_rom.mapping, biosaddr, 0x8000); + } else { + mem_mapping_disable(&virge->bios_rom.mapping); + } + return; + case 0x3c: + virge->pci_regs[0x3c] = val; + return; - case 0x13: - svga->crtc[0x59] = (virge->chip == S3_VIRGEVX || virge->chip == S3_TRIO3D2X) ? (val & 0xfe) : (val & 0xfc); - s3_virge_updatemapping(virge); - return; + case 0x88: + virge->pci_regs[0x88] = val & 0x27; + return; - case 0x30: case 0x32: case 0x33: - virge->pci_regs[addr] = val; - if (virge->pci_regs[0x30] & 0x01) - { - uint32_t biosaddr = (virge->pci_regs[0x32] << 16) | (virge->pci_regs[0x33] << 24); - if (virge->chip == S3_VIRGEGX2) - mem_mapping_set_addr(&virge->bios_rom.mapping, biosaddr, 0x10000); - else - mem_mapping_set_addr(&virge->bios_rom.mapping, biosaddr, 0x8000); - } - else - { - mem_mapping_disable(&virge->bios_rom.mapping); - } - return; - case 0x3c: - virge->pci_regs[0x3c] = val; - return; + case 0x89: + virge->pci_regs[0x89] = val & 0x03; + return; - case 0x88: - virge->pci_regs[0x88] = val & 0x27; - return; + case 0x8b: + case 0xe1: + case 0xe3: + virge->pci_regs[addr] = val; + return; - case 0x89: - virge->pci_regs[0x89] = val & 0x03; - return; + case 0xe0: + virge->pci_regs[0xe0] = val & 0x03; + return; - case 0x8b: case 0xe1: case 0xe3: - virge->pci_regs[addr] = val; - return; + case 0xe2: + virge->pci_regs[0xe2] = val & 0xc0; + return; - case 0xe0: - virge->pci_regs[0xe0] = val & 0x03; - return; - - case 0xe2: - virge->pci_regs[0xe2] = val & 0xc0; - return; - } + default: + break; + } } -static void s3_virge_reset(void *priv) +static void +s3_virge_reset(void *priv) { - virge_t *virge = (virge_t *) priv; - svga_t *svga = &virge->svga; + virge_t *virge = (virge_t *) priv; + svga_t *svga = &virge->svga; memset(svga->crtc, 0x00, sizeof(svga->crtc)); - svga->crtc[0] = 63; - svga->crtc[6] = 255; - svga->dispontime = 1000ull << 32; - svga->dispofftime = 1000ull << 32; - svga->bpp = 8; + svga->crtc[0] = 63; + svga->crtc[6] = 255; + svga->dispontime = 1000ULL << 32; + svga->dispofftime = 1000ULL << 32; + svga->bpp = 8; io_removehandler(0x03c0, 0x0020, s3_virge_in, NULL, NULL, s3_virge_out, NULL, NULL, virge); io_sethandler(0x03c0, 0x0020, s3_virge_in, NULL, NULL, s3_virge_out, NULL, NULL, virge); memset(virge->pci_regs, 0x00, 256); - virge->pci_regs[PCI_REG_COMMAND] = 3; - virge->pci_regs[0x05] = 0; - virge->pci_regs[0x06] = 0; - virge->pci_regs[0x07] = 2; - virge->pci_regs[0x32] = 0x0c; - virge->pci_regs[0x3d] = 1; - virge->pci_regs[0x3e] = 4; - virge->pci_regs[0x3f] = 0xff; + virge->pci_regs[PCI_REG_COMMAND] = 3; + virge->pci_regs[0x05] = 0; + virge->pci_regs[0x06] = 0; + virge->pci_regs[0x07] = 2; + virge->pci_regs[0x32] = 0x0c; + virge->pci_regs[0x3d] = 1; + virge->pci_regs[0x3e] = 4; + virge->pci_regs[0x3f] = 0xff; - switch(virge->local) { - case S3_VIRGE_325: - case S3_DIAMOND_STEALTH3D_2000: - virge->svga.crtc[0x59] = 0x70; - break; - case S3_DIAMOND_STEALTH3D_3000: - case S3_STB_VELOCITY_3D: - virge->svga.crtc[0x59] = 0x70; - break; - case S3_VIRGE_GX2: - case S3_DIAMOND_STEALTH3D_4000: - virge->svga.crtc[0x6c] = 1; - virge->svga.crtc[0x59] = 0x70; - break; + switch (virge->local) { + case S3_VIRGE_325: + case S3_DIAMOND_STEALTH3D_2000: + virge->fifo_slots_num = 8; + virge->svga.crtc[0x59] = 0x70; + break; + case S3_DIAMOND_STEALTH3D_3000: + case S3_STB_VELOCITY_3D: + virge->fifo_slots_num = 8; + virge->svga.crtc[0x59] = 0x70; + break; + case S3_VIRGE_GX2: + case S3_DIAMOND_STEALTH3D_4000: + virge->fifo_slots_num = 16; + virge->svga.crtc[0x6c] = 1; + virge->svga.crtc[0x59] = 0x70; + break; - case S3_TRIO_3D2X: - virge->svga.crtc[0x6c] = 1; - virge->svga.crtc[0x59] = 0x70; - break; + case S3_TRIO_3D2X: + virge->fifo_slots_num = 16; + virge->svga.crtc[0x6c] = 1; + virge->svga.crtc[0x59] = 0x70; + break; - default: - virge->svga.crtc[0x6c] = 1; - virge->svga.crtc[0x59] = 0x70; - break; - } + default: + virge->fifo_slots_num = 8; + virge->svga.crtc[0x6c] = 1; + virge->svga.crtc[0x59] = 0x70; + break; + } - if (virge->chip == S3_VIRGEGX2) - virge->svga.crtc[0x36] = 2 | (2 << 2) | (1 << 4) | (1 << 5); - else { - switch (virge->memory_size) { - case 2: - if (virge->chip == S3_VIRGEVX) { - virge->svga.crtc[0x36] = (0 << 5); - } else - virge->svga.crtc[0x36] = 2 | (0 << 2) | (1 << 4) | (4 << 5); - break; - case 8: - if (virge->chip == S3_TRIO3D2X) - virge->svga.crtc[0x36] = 2 | (2 << 2) | (1 << 4) | (0 << 5); - else - virge->svga.crtc[0x36] = (3 << 5); - break; - case 4: - if (virge->chip == S3_VIRGEVX) - virge->svga.crtc[0x36] = (1 << 5); - else if (virge->chip == S3_TRIO3D2X) - virge->svga.crtc[0x36] = 2 | (2 << 2) | (1 << 4) | (2 << 5); - else - virge->svga.crtc[0x36] = 2 | (0 << 2) | (1 << 4) | (0 << 5); - break; - } - if (virge->local == S3_VIRGE_GX) - virge->svga.crtc[0x36] |= (1 << 2); - } + if (virge->chip == S3_VIRGEGX2) + virge->svga.crtc[0x36] = 2 | (2 << 2) | (1 << 4) | (1 << 5); + else { + switch (virge->memory_size) { + case 2: + if (virge->chip == S3_VIRGEVX) { + virge->svga.crtc[0x36] = (0 << 5); + } else + virge->svga.crtc[0x36] = 2 | (0 << 2) | (1 << 4) | (4 << 5); + break; + case 8: + if (virge->chip == S3_TRIO3D2X) + virge->svga.crtc[0x36] = 2 | (2 << 2) | (1 << 4) | (0 << 5); + else + virge->svga.crtc[0x36] = (3 << 5); + break; + case 4: + if (virge->chip == S3_VIRGEVX) + virge->svga.crtc[0x36] = (1 << 5); + else if (virge->chip == S3_TRIO3D2X) + virge->svga.crtc[0x36] = 2 | (2 << 2) | (1 << 4) | (2 << 5); + else + virge->svga.crtc[0x36] = 2 | (0 << 2) | (1 << 4) | (0 << 5); + break; - virge->svga.crtc[0x37] = 1 | (7 << 5); - virge->svga.crtc[0x53] = 8; + default: + break; + } + if (virge->local == S3_VIRGE_GX) + virge->svga.crtc[0x36] |= (1 << 2); + } + + virge->svga.crtc[0x37] = 1 | (7 << 5); + virge->svga.crtc[0x53] = 8; mem_mapping_disable(&virge->bios_rom.mapping); s3_virge_updatemapping(virge); - mem_mapping_disable(&virge->mmio_mapping); - mem_mapping_disable(&virge->new_mmio_mapping); + mem_mapping_disable(&virge->mmio_mapping); + mem_mapping_disable(&virge->new_mmio_mapping); } -static void *s3_virge_init(const device_t *info) +static void * +s3_virge_init(const device_t *info) { - const char *bios_fn; - virge_t *virge = malloc(sizeof(virge_t)); + const char *bios_fn; + virge_t *virge = malloc(sizeof(virge_t)); - memset(virge, 0, sizeof(virge_t)); + memset(virge, 0, sizeof(virge_t)); - virge->bilinear_enabled = device_get_config_int("bilinear"); - virge->dithering_enabled = device_get_config_int("dithering"); - if (info->local >= S3_VIRGE_GX2) - virge->memory_size = 4; - else - virge->memory_size = device_get_config_int("memory"); - - - switch(info->local) { - case S3_VIRGE_325: - bios_fn = ROM_VIRGE_325; - break; - case S3_DIAMOND_STEALTH3D_2000: - bios_fn = ROM_DIAMOND_STEALTH3D_2000; - break; - case S3_DIAMOND_STEALTH3D_3000: - bios_fn = ROM_DIAMOND_STEALTH3D_3000; - break; - case S3_STB_VELOCITY_3D: - bios_fn = ROM_STB_VELOCITY_3D; - break; - case S3_VIRGE_DX: - bios_fn = ROM_VIRGE_DX; - break; - case S3_DIAMOND_STEALTH3D_2000PRO: - bios_fn = ROM_DIAMOND_STEALTH3D_2000PRO; - break; - case S3_VIRGE_GX: - bios_fn = ROM_VIRGE_GX; - break; - case S3_VIRGE_GX2: - bios_fn = ROM_VIRGE_GX2; - break; - case S3_DIAMOND_STEALTH3D_4000: - bios_fn = ROM_DIAMOND_STEALTH3D_4000; - break; - case S3_TRIO_3D2X: - bios_fn = ROM_TRIO3D2X; - break; - default: - free(virge); - return NULL; - } + virge->bilinear_enabled = device_get_config_int("bilinear"); + virge->dithering_enabled = device_get_config_int("dithering"); + if (info->local >= S3_VIRGE_GX2) + virge->memory_size = 4; + else + virge->memory_size = device_get_config_int("memory"); - svga_init(info, &virge->svga, virge, virge->memory_size << 20, - s3_virge_recalctimings, - s3_virge_in, s3_virge_out, - s3_virge_hwcursor_draw, - s3_virge_overlay_draw); - virge->svga.hwcursor.ysize = 64; + switch (info->local) { + case S3_VIRGE_325: + bios_fn = ROM_VIRGE_325; + break; + case S3_DIAMOND_STEALTH3D_2000: + bios_fn = ROM_DIAMOND_STEALTH3D_2000; + break; + case S3_DIAMOND_STEALTH3D_3000: + bios_fn = ROM_DIAMOND_STEALTH3D_3000; + break; + case S3_STB_VELOCITY_3D: + bios_fn = ROM_STB_VELOCITY_3D; + break; + case S3_VIRGE_DX: + bios_fn = ROM_VIRGE_DX; + break; + case S3_DIAMOND_STEALTH3D_2000PRO: + bios_fn = ROM_DIAMOND_STEALTH3D_2000PRO; + break; + case S3_VIRGE_GX: + bios_fn = ROM_VIRGE_GX; + break; + case S3_VIRGE_GX2: + bios_fn = ROM_VIRGE_GX2; + break; + case S3_DIAMOND_STEALTH3D_4000: + bios_fn = ROM_DIAMOND_STEALTH3D_4000; + break; + case S3_TRIO_3D2X: + bios_fn = ROM_TRIO3D2X; + break; + default: + free(virge); + return NULL; + } - if (info->local == S3_VIRGE_GX2) - rom_init(&virge->bios_rom, (char *) bios_fn, 0xc0000, 0x10000, 0xffff, 0, MEM_MAPPING_EXTERNAL); - else - rom_init(&virge->bios_rom, (char *) bios_fn, 0xc0000, 0x8000, 0x7fff, 0, MEM_MAPPING_EXTERNAL); - - mem_mapping_disable(&virge->bios_rom.mapping); + svga_init(info, &virge->svga, virge, virge->memory_size << 20, + s3_virge_recalctimings, + s3_virge_in, s3_virge_out, + s3_virge_hwcursor_draw, + s3_virge_overlay_draw); + virge->svga.hwcursor.cur_ysize = 64; - mem_mapping_add(&virge->linear_mapping, 0, 0, svga_read_linear, - svga_readw_linear, - svga_readl_linear, - svga_write_linear, - svga_writew_linear, - svga_writel_linear, - NULL, - MEM_MAPPING_EXTERNAL, - &virge->svga); - mem_mapping_add(&virge->mmio_mapping, 0, 0, s3_virge_mmio_read, - s3_virge_mmio_read_w, - s3_virge_mmio_read_l, - s3_virge_mmio_write, - s3_virge_mmio_write_w, - s3_virge_mmio_write_l, - NULL, - MEM_MAPPING_EXTERNAL, - virge); - mem_mapping_add(&virge->new_mmio_mapping, 0, 0, s3_virge_mmio_read, - s3_virge_mmio_read_w, - s3_virge_mmio_read_l, - s3_virge_mmio_write, - s3_virge_mmio_write_w, - s3_virge_mmio_write_l, - NULL, - MEM_MAPPING_EXTERNAL, - virge); + if (bios_fn != NULL) { + if (info->local == S3_VIRGE_GX2) + rom_init(&virge->bios_rom, bios_fn, 0xc0000, 0x10000, 0xffff, 0, MEM_MAPPING_EXTERNAL); + else + rom_init(&virge->bios_rom, bios_fn, 0xc0000, 0x8000, 0x7fff, 0, MEM_MAPPING_EXTERNAL); + } - io_sethandler(0x03c0, 0x0020, s3_virge_in, NULL, NULL, s3_virge_out, NULL, NULL, virge); + mem_mapping_disable(&virge->bios_rom.mapping); - virge->pci_regs[PCI_REG_COMMAND] = 3; - virge->pci_regs[0x05] = 0; - virge->pci_regs[0x06] = 0; - virge->pci_regs[0x07] = 2; - virge->pci_regs[0x32] = 0x0c; - virge->pci_regs[0x3d] = 1; - virge->pci_regs[0x3e] = 4; - virge->pci_regs[0x3f] = 0xff; - - virge->virge_rev = 0; - virge->virge_id = 0xe1; - virge->is_agp = !!(info->flags & DEVICE_AGP); + mem_mapping_add(&virge->linear_mapping, 0, 0, svga_read_linear, + svga_readw_linear, + svga_readl_linear, + svga_write_linear, + svga_writew_linear, + svga_writel_linear, + NULL, + MEM_MAPPING_EXTERNAL, + &virge->svga); + mem_mapping_add(&virge->mmio_mapping, 0, 0, s3_virge_mmio_read, + s3_virge_mmio_read_w, + s3_virge_mmio_read_l, + s3_virge_mmio_write, + s3_virge_mmio_write_w, + s3_virge_mmio_write_l, + NULL, + MEM_MAPPING_EXTERNAL, + virge); + mem_mapping_add(&virge->new_mmio_mapping, 0, 0, s3_virge_mmio_read, + s3_virge_mmio_read_w, + s3_virge_mmio_read_l, + s3_virge_mmio_write, + s3_virge_mmio_write_w, + s3_virge_mmio_write_l, + NULL, + MEM_MAPPING_EXTERNAL, + virge); - switch(info->local) { - case S3_VIRGE_325: - case S3_DIAMOND_STEALTH3D_2000: - virge->svga.decode_mask = (4 << 20) - 1; - virge->virge_id_high = 0x56; - virge->virge_id_low = 0x31; - virge->svga.crtc[0x59] = 0x70; - virge->chip = S3_VIRGE; - video_inform(VIDEO_FLAG_TYPE_SPECIAL, &timing_diamond_stealth3d_2000_pci); - break; - case S3_DIAMOND_STEALTH3D_3000: - case S3_STB_VELOCITY_3D: - virge->svga.decode_mask = (8 << 20) - 1; - virge->virge_id_high = 0x88; - virge->virge_id_low = 0x3d; - virge->svga.crtc[0x59] = 0x70; - virge->chip = S3_VIRGEVX; - video_inform(VIDEO_FLAG_TYPE_SPECIAL, &timing_diamond_stealth3d_3000_pci); - break; - case S3_VIRGE_GX2: - case S3_DIAMOND_STEALTH3D_4000: - virge->svga.decode_mask = (4 << 20) - 1; - virge->virge_id_high = 0x8a; - virge->virge_id_low = 0x10; - virge->svga.crtc[0x6c] = 1; - virge->svga.crtc[0x59] = 0x70; - virge->svga.vblank_start = s3_virge_vblank_start; - virge->chip = S3_VIRGEGX2; - video_inform(VIDEO_FLAG_TYPE_SPECIAL, virge->is_agp ? &timing_virge_agp : &timing_virge_dx_pci); - break; + io_sethandler(0x03c0, 0x0020, s3_virge_in, NULL, NULL, s3_virge_out, NULL, NULL, virge); - case S3_TRIO_3D2X: - virge->svga.decode_mask = (8 << 20) - 1; - virge->virge_id_high = 0x8a; - virge->virge_id_low = 0x13; - virge->virge_rev = 0x01; - virge->svga.crtc[0x6c] = 1; - virge->svga.crtc[0x59] = 0x70; - virge->svga.vblank_start = s3_virge_vblank_start; - virge->chip = S3_TRIO3D2X; - video_inform(VIDEO_FLAG_TYPE_SPECIAL, virge->is_agp ? &timing_virge_agp : &timing_virge_dx_pci); - break; + virge->pci_regs[PCI_REG_COMMAND] = 3; + virge->pci_regs[0x05] = 0; + virge->pci_regs[0x06] = 0; + virge->pci_regs[0x07] = 2; + virge->pci_regs[0x32] = 0x0c; + virge->pci_regs[0x3d] = 1; + virge->pci_regs[0x3e] = 4; + virge->pci_regs[0x3f] = 0xff; - case S3_VIRGE_GX: - virge->virge_rev = 0x01; - /*FALLTHROUGH*/ - default: - virge->svga.decode_mask = (4 << 20) - 1; - virge->virge_id_high = 0x8a; - virge->virge_id_low = 0x01; - virge->svga.crtc[0x6c] = 1; - virge->svga.crtc[0x59] = 0x70; - virge->svga.vblank_start = s3_virge_vblank_start; - virge->chip = S3_VIRGEDX; - video_inform(VIDEO_FLAG_TYPE_SPECIAL, &timing_virge_dx_pci); - break; - } + virge->virge_rev = 0; + virge->virge_id = 0xe1; + virge->is_agp = !!(info->flags & DEVICE_AGP); - if (virge->chip == S3_VIRGEGX2) { - virge->vram_mask = (4 << 20) - 1; - virge->svga.vram_mask = (4 << 20) - 1; - virge->svga.vram_max = 4 << 20; - virge->svga.crtc[0x36] = 2 | (2 << 2) | (1 << 4) | (1 << 5); - } else { - switch (virge->memory_size) { - case 2: - virge->vram_mask = (2 << 20) - 1; - virge->svga.vram_mask = (2 << 20) - 1; - virge->svga.vram_max = 2 << 20; - if (virge->chip == S3_VIRGEVX) { - virge->svga.crtc[0x36] = (0 << 5); - } else - virge->svga.crtc[0x36] = 2 | (0 << 2) | (1 << 4) | (4 << 5); - break; - case 8: - virge->vram_mask = (8 << 20) - 1; - virge->svga.vram_mask = (8 << 20) - 1; - virge->svga.vram_max = 8 << 20; - if (virge->chip == S3_TRIO3D2X) - virge->svga.crtc[0x36] = 2 | (2 << 2) | (1 << 4) | (0 << 5); - else - virge->svga.crtc[0x36] = (3 << 5); - break; - case 4: - virge->vram_mask = (4 << 20) - 1; - virge->svga.vram_mask = (4 << 20) - 1; - virge->svga.vram_max = 4 << 20; - if (virge->chip == S3_VIRGEVX) - virge->svga.crtc[0x36] = (1 << 5); - else if (virge->chip == S3_TRIO3D2X) - virge->svga.crtc[0x36] = 2 | (2 << 2) | (1 << 4) | (2 << 5); - else - virge->svga.crtc[0x36] = 2 | (0 << 2) | (1 << 4) | (0 << 5); - break; - } - if (info->local == S3_VIRGE_GX) - virge->svga.crtc[0x36] |= (1 << 2); - } - - virge->svga.crtc[0x37] = 1 | (7 << 5); - virge->svga.crtc[0x53] = 8; + switch (info->local) { + case S3_VIRGE_325: + case S3_DIAMOND_STEALTH3D_2000: + virge->fifo_slots_num = 8; + virge->svga.decode_mask = (4 << 20) - 1; + virge->virge_id_high = 0x56; + virge->virge_id_low = 0x31; + virge->svga.crtc[0x59] = 0x70; + virge->chip = S3_VIRGE; + video_inform(VIDEO_FLAG_TYPE_SPECIAL, &timing_diamond_stealth3d_2000_pci); + break; + case S3_DIAMOND_STEALTH3D_3000: + case S3_STB_VELOCITY_3D: + virge->fifo_slots_num = 8; + virge->svga.decode_mask = (8 << 20) - 1; + virge->virge_id_high = 0x88; + virge->virge_id_low = 0x3d; + virge->svga.crtc[0x59] = 0x70; + virge->chip = S3_VIRGEVX; + video_inform(VIDEO_FLAG_TYPE_SPECIAL, &timing_diamond_stealth3d_3000_pci); + break; + case S3_VIRGE_GX2: + case S3_DIAMOND_STEALTH3D_4000: + virge->fifo_slots_num = 16; + virge->svga.decode_mask = (4 << 20) - 1; + virge->virge_id_high = 0x8a; + virge->virge_id_low = 0x10; + virge->svga.crtc[0x6c] = 1; + virge->svga.crtc[0x59] = 0x70; + virge->svga.vblank_start = s3_virge_vblank_start; + virge->chip = S3_VIRGEGX2; + video_inform(VIDEO_FLAG_TYPE_SPECIAL, virge->is_agp ? &timing_virge_agp : &timing_virge_dx_pci); + break; - virge->card = pci_add_card(virge->is_agp ? PCI_ADD_AGP : PCI_ADD_VIDEO, s3_virge_pci_read, s3_virge_pci_write, virge); + case S3_TRIO_3D2X: + virge->fifo_slots_num = 16; + virge->svga.decode_mask = (8 << 20) - 1; + virge->virge_id_high = 0x8a; + virge->virge_id_low = 0x13; + virge->virge_rev = 0x01; + virge->svga.crtc[0x6c] = 1; + virge->svga.crtc[0x59] = 0x70; + virge->svga.vblank_start = s3_virge_vblank_start; + virge->chip = S3_TRIO3D2X; + video_inform(VIDEO_FLAG_TYPE_SPECIAL, virge->is_agp ? &timing_virge_agp : &timing_virge_dx_pci); + break; - virge->i2c = i2c_gpio_init("ddc_s3_virge"); - virge->ddc = ddc_init(i2c_gpio_get_bus(virge->i2c)); - - virge->svga.packed_chain4 = 1; + case S3_VIRGE_GX: + virge->virge_rev = 0x01; + fallthrough; - virge->wake_render_thread = thread_create_event(); - virge->wake_main_thread = thread_create_event(); - virge->not_full_event = thread_create_event(); - virge->render_thread_run = 1; - virge->render_thread = thread_create(render_thread, virge); + default: + virge->fifo_slots_num = 8; + virge->svga.decode_mask = (4 << 20) - 1; + virge->virge_id_high = 0x8a; + virge->virge_id_low = 0x01; + virge->svga.crtc[0x6c] = 1; + virge->svga.crtc[0x59] = 0x70; + virge->svga.vblank_start = s3_virge_vblank_start; + virge->chip = S3_VIRGEDX; + video_inform(VIDEO_FLAG_TYPE_SPECIAL, &timing_virge_dx_pci); + break; + } - timer_add(&virge->tri_timer, s3_virge_tri_timer, virge, 0); - - virge->local = info->local; - - return virge; -} + if (virge->chip == S3_VIRGEGX2) { + virge->vram_mask = (4 << 20) - 1; + virge->svga.vram_mask = (4 << 20) - 1; + virge->svga.vram_max = 4 << 20; + virge->svga.crtc[0x36] = 2 | (2 << 2) | (1 << 4) | (1 << 5); + } else { + switch (virge->memory_size) { + case 2: + virge->vram_mask = (2 << 20) - 1; + virge->svga.vram_mask = (2 << 20) - 1; + virge->svga.vram_max = 2 << 20; + if (virge->chip == S3_VIRGEVX) { + virge->svga.crtc[0x36] = (0 << 5); + } else + virge->svga.crtc[0x36] = 2 | (0 << 2) | (1 << 4) | (4 << 5); + break; + case 8: + virge->vram_mask = (8 << 20) - 1; + virge->svga.vram_mask = (8 << 20) - 1; + virge->svga.vram_max = 8 << 20; + if (virge->chip == S3_TRIO3D2X) + virge->svga.crtc[0x36] = 2 | (2 << 2) | (1 << 4) | (0 << 5); + else + virge->svga.crtc[0x36] = (3 << 5); + break; + case 4: + virge->vram_mask = (4 << 20) - 1; + virge->svga.vram_mask = (4 << 20) - 1; + virge->svga.vram_max = 4 << 20; + if (virge->chip == S3_VIRGEVX) + virge->svga.crtc[0x36] = (1 << 5); + else if (virge->chip == S3_TRIO3D2X) + virge->svga.crtc[0x36] = 2 | (2 << 2) | (1 << 4) | (2 << 5); + else + virge->svga.crtc[0x36] = 2 | (0 << 2) | (1 << 4) | (0 << 5); + break; -static void s3_virge_close(void *p) -{ - virge_t *virge = (virge_t *)p; - - virge->render_thread_run = 0; - thread_set_event(virge->wake_render_thread); - thread_wait(virge->render_thread); - thread_destroy_event(virge->not_full_event); - thread_destroy_event(virge->wake_main_thread); - thread_destroy_event(virge->wake_render_thread); - - svga_close(&virge->svga); - - ddc_close(virge->ddc); - i2c_gpio_close(virge->i2c); - - free(virge); -} - -static int s3_virge_325_diamond_available(void) -{ - return rom_present(ROM_DIAMOND_STEALTH3D_2000); -} - -static int s3_virge_325_available(void) -{ - return rom_present(ROM_VIRGE_325); -} - -static int s3_virge_988_diamond_available(void) -{ - return rom_present(ROM_DIAMOND_STEALTH3D_3000); -} - -static int s3_virge_988_stb_available(void) -{ - return rom_present(ROM_STB_VELOCITY_3D); -} - -static int s3_virge_375_available(void) -{ - return rom_present(ROM_VIRGE_DX); -} - -static int s3_virge_375_diamond_available(void) -{ - return rom_present(ROM_DIAMOND_STEALTH3D_2000PRO); -} - -static int s3_virge_385_available(void) -{ - return rom_present(ROM_VIRGE_GX); -} - -static int s3_virge_357_available(void) -{ - return rom_present(ROM_VIRGE_GX2); -} - -static int s3_virge_357_diamond_available(void) -{ - return rom_present(ROM_DIAMOND_STEALTH3D_4000); -} - -static int s3_trio3d2x_available(void) -{ - return rom_present(ROM_TRIO3D2X); -} - -static void s3_virge_speed_changed(void *p) -{ - virge_t *virge = (virge_t *)p; - - svga_recalctimings(&virge->svga); -} - -static void s3_virge_force_redraw(void *p) -{ - virge_t *virge = (virge_t *)p; - - virge->svga.fullchange = changeframecount; -} - -static const device_config_t s3_virge_config[] = -{ - { - "memory", "Memory size", CONFIG_SELECTION, "", 4, "", { 0 }, - { - { - "2 MB", 2 - }, - { - "4 MB", 4 - }, - { - "" - } - } - }, - { - "bilinear", "Bilinear filtering", CONFIG_BINARY, "", 1 - }, - { - "dithering", "Dithering", CONFIG_BINARY, "", 1 - }, - { - "", "", -1 + default: + break; } -}; + if (info->local == S3_VIRGE_GX) + virge->svga.crtc[0x36] |= (1 << 2); + } -static const device_config_t s3_virge_stb_config[] = + virge->svga.crtc[0x37] = 1 | (7 << 5); + virge->svga.crtc[0x53] = 8; + + if (bios_fn == NULL) + pci_add_card(virge->is_agp ? PCI_ADD_AGP : PCI_ADD_VIDEO, s3_virge_pci_read, s3_virge_pci_write, virge, &virge->pci_slot); + else + pci_add_card(virge->is_agp ? PCI_ADD_AGP : PCI_ADD_NORMAL, s3_virge_pci_read, s3_virge_pci_write, virge, &virge->pci_slot); + + virge->i2c = i2c_gpio_init("ddc_s3_virge"); + virge->ddc = ddc_init(i2c_gpio_get_bus(virge->i2c)); + + virge->svga.force_old_addr = 1; + + virge->wake_render_thread = thread_create_event(); + virge->wake_main_thread = thread_create_event(); + virge->not_full_event = thread_create_event(); + virge->render_thread_run = 1; + virge->render_thread = thread_create(render_thread, virge); + + timer_add(&virge->tri_timer, s3_virge_tri_timer, virge, 0); + + virge->local = info->local; + + return virge; +} + +static void +s3_virge_close(void *priv) { - { - "memory", "Memory size", CONFIG_SELECTION, "", 4, "", { 0 }, - { - { - "2 MB", 2 - }, - { - "4 MB", 4 - }, - { - "8 MB", 8 - }, - { - "" - } - } - }, - { - "bilinear", "Bilinear filtering", CONFIG_BINARY, "", 1 - }, - { - "dithering", "Dithering", CONFIG_BINARY, "", 1 - }, - { - "", "", -1 + virge_t *virge = (virge_t *) priv; + + virge->render_thread_run = 0; + thread_set_event(virge->wake_render_thread); + thread_wait(virge->render_thread); + thread_destroy_event(virge->not_full_event); + thread_destroy_event(virge->wake_main_thread); + thread_destroy_event(virge->wake_render_thread); + + svga_close(&virge->svga); + + ddc_close(virge->ddc); + i2c_gpio_close(virge->i2c); + + free(virge); +} + +static int +s3_virge_325_diamond_available(void) +{ + return rom_present(ROM_DIAMOND_STEALTH3D_2000); +} + +static int +s3_virge_325_available(void) +{ + return rom_present(ROM_VIRGE_325); +} + +static int +s3_virge_988_diamond_available(void) +{ + return rom_present(ROM_DIAMOND_STEALTH3D_3000); +} + +static int +s3_virge_988_stb_available(void) +{ + return rom_present(ROM_STB_VELOCITY_3D); +} + +static int +s3_virge_375_available(void) +{ + return rom_present(ROM_VIRGE_DX); +} + +static int +s3_virge_375_diamond_available(void) +{ + return rom_present(ROM_DIAMOND_STEALTH3D_2000PRO); +} + +static int +s3_virge_385_available(void) +{ + return rom_present(ROM_VIRGE_GX); +} + +static int +s3_virge_357_available(void) +{ + return rom_present(ROM_VIRGE_GX2); +} + +static int +s3_virge_357_diamond_available(void) +{ + return rom_present(ROM_DIAMOND_STEALTH3D_4000); +} + +static int +s3_trio3d2x_available(void) +{ + return rom_present(ROM_TRIO3D2X); +} + +static void +s3_virge_speed_changed(void *priv) +{ + virge_t *virge = (virge_t *) priv; + + svga_recalctimings(&virge->svga); +} + +static void +s3_virge_force_redraw(void *priv) +{ + virge_t *virge = (virge_t *) priv; + + virge->svga.fullchange = changeframecount; +} + +static const device_config_t s3_virge_config[] = { + // clang-format off + { + .name = "memory", + .description = "Memory size", + .type = CONFIG_SELECTION, + .default_int = 4, + .selection = { + { + .description = "2 MB", + .value = 2 + }, + { + .description = "4 MB", + .value = 4 + }, + { + .description = "" + } } + }, + { + .name = "bilinear", + .description = "Bilinear filtering", + .type = CONFIG_BINARY, + .default_int = 1 + }, + { + .name = "dithering", + .description = "Dithering", + .type = CONFIG_BINARY, + .default_int = 1 + }, + { + .type = CONFIG_END + } + // clang-format on }; -static const device_config_t s3_virge_357_config[] = -{ - { - "bilinear", "Bilinear filtering", CONFIG_BINARY, "", 1 - }, - { - "dithering", "Dithering", CONFIG_BINARY, "", 1 - }, - { - "", "", -1 +static const device_config_t s3_virge_stb_config[] = { + // clang-format off + { + .name = "memory", + .description = "Memory size", + .type = CONFIG_SELECTION, + .default_int = 4, + .selection = { + { + .description = "2 MB", + .value = 2 + }, + { + .description = "4 MB", + .value = 4 + }, + { + .description = "8 MB", + .value = 8 + }, + { + .description = "" + } } + }, + { + .name = "bilinear", + .description = "Bilinear filtering", + .type = CONFIG_BINARY, + .default_int = 1 + }, + { + .name = "dithering", + .description = "Dithering", + .type = CONFIG_BINARY, + .default_int = 1 + }, + { + .type = CONFIG_END + } + // clang-format on }; -static const device_config_t s3_trio3d2x_config[] = -{ - { - "memory", "Memory size", CONFIG_SELECTION, "", 4, "", { 0 }, - { - { - "4 MB", 4 - }, - { - "8 MB", 8 - }, - { - "" - } - } - }, - { - "bilinear", "Bilinear filtering", CONFIG_BINARY, "", 1 - }, - { - "dithering", "Dithering", CONFIG_BINARY, "", 1 - }, - { - "", "", -1 +static const device_config_t s3_virge_357_config[] = { + // clang-format off + { + .name = "bilinear", + .description = "Bilinear filtering", + .type = CONFIG_BINARY, + .default_int = 1 + }, + { + .name = "dithering", + .description = "Dithering", + .type = CONFIG_BINARY, + .default_int = 1 + }, + { + .type = CONFIG_END + } + // clang-format on +}; + +static const device_config_t s3_trio3d2x_config[] = { + // clang-format off + { + .name = "memory", + .description = "Memory size", + .type = CONFIG_SELECTION, + .default_int = 4, + .selection = { + { + .description = "4 MB", + .value = 4 + }, + { + .description = "8 MB", + .value = 8 + }, + { + .description = "" + } } + }, + { + .name = "bilinear", + .description = "Bilinear filtering", + .type = CONFIG_BINARY, + .default_int = 1 + }, + { + .name = "dithering", + .description = "Dithering", + .type = CONFIG_BINARY, + .default_int = 1 + }, + { + .type = CONFIG_END + } + // clang-format on }; -const device_t s3_virge_325_pci_device = -{ - "S3 ViRGE (325) PCI", - "virge325_pci", - DEVICE_PCI, - S3_VIRGE_325, - s3_virge_init, - s3_virge_close, - s3_virge_reset, - { s3_virge_325_available }, - s3_virge_speed_changed, - s3_virge_force_redraw, - s3_virge_config +const device_t s3_virge_325_pci_device = { + .name = "S3 ViRGE (325) PCI", + .internal_name = "virge325_pci", + .flags = DEVICE_PCI, + .local = S3_VIRGE_325, + .init = s3_virge_init, + .close = s3_virge_close, + .reset = s3_virge_reset, + { .available = s3_virge_325_available }, + .speed_changed = s3_virge_speed_changed, + .force_redraw = s3_virge_force_redraw, + .config = s3_virge_config }; -const device_t s3_diamond_stealth_2000_pci_device = -{ - "S3 ViRGE (Diamond Stealth 3D 2000) PCI", - "stealth3d_2000_pci", - DEVICE_PCI, - S3_DIAMOND_STEALTH3D_2000, - s3_virge_init, - s3_virge_close, - s3_virge_reset, - { s3_virge_325_diamond_available }, - s3_virge_speed_changed, - s3_virge_force_redraw, - s3_virge_config +const device_t s3_diamond_stealth_2000_pci_device = { + .name = "S3 ViRGE (Diamond Stealth 3D 2000) PCI", + .internal_name = "stealth3d_2000_pci", + .flags = DEVICE_PCI, + .local = S3_DIAMOND_STEALTH3D_2000, + .init = s3_virge_init, + .close = s3_virge_close, + .reset = s3_virge_reset, + { .available = s3_virge_325_diamond_available }, + .speed_changed = s3_virge_speed_changed, + .force_redraw = s3_virge_force_redraw, + .config = s3_virge_config }; -const device_t s3_diamond_stealth_3000_pci_device = -{ - "S3 ViRGE/VX (Diamond Stealth 3D 3000) PCI", - "stealth3d_3000_pci", - DEVICE_PCI, - S3_DIAMOND_STEALTH3D_3000, - s3_virge_init, - s3_virge_close, - s3_virge_reset, - { s3_virge_988_diamond_available }, - s3_virge_speed_changed, - s3_virge_force_redraw, - s3_virge_stb_config +const device_t s3_diamond_stealth_3000_pci_device = { + .name = "S3 ViRGE/VX (Diamond Stealth 3D 3000) PCI", + .internal_name = "stealth3d_3000_pci", + .flags = DEVICE_PCI, + .local = S3_DIAMOND_STEALTH3D_3000, + .init = s3_virge_init, + .close = s3_virge_close, + .reset = s3_virge_reset, + { .available = s3_virge_988_diamond_available }, + .speed_changed = s3_virge_speed_changed, + .force_redraw = s3_virge_force_redraw, + .config = s3_virge_stb_config }; -const device_t s3_stb_velocity_3d_pci_device = -{ - "S3 ViRGE/VX (STB Velocity 3D) PCI", - "stb_velocity3d_pci", - DEVICE_PCI, - S3_STB_VELOCITY_3D, - s3_virge_init, - s3_virge_close, - s3_virge_reset, - { s3_virge_988_stb_available }, - s3_virge_speed_changed, - s3_virge_force_redraw, - s3_virge_stb_config +const device_t s3_stb_velocity_3d_pci_device = { + .name = "S3 ViRGE/VX (STB Velocity 3D) PCI", + .internal_name = "stb_velocity3d_pci", + .flags = DEVICE_PCI, + .local = S3_STB_VELOCITY_3D, + .init = s3_virge_init, + .close = s3_virge_close, + .reset = s3_virge_reset, + { .available = s3_virge_988_stb_available }, + .speed_changed = s3_virge_speed_changed, + .force_redraw = s3_virge_force_redraw, + .config = s3_virge_stb_config }; -const device_t s3_virge_375_pci_device = -{ - "S3 ViRGE/DX (375) PCI", - "virge375_pci", - DEVICE_PCI, - S3_VIRGE_DX, - s3_virge_init, - s3_virge_close, - s3_virge_reset, - { s3_virge_375_available }, - s3_virge_speed_changed, - s3_virge_force_redraw, - s3_virge_config +const device_t s3_virge_375_pci_device = { + .name = "S3 ViRGE/DX (375) PCI", + .internal_name = "virge375_pci", + .flags = DEVICE_PCI, + .local = S3_VIRGE_DX, + .init = s3_virge_init, + .close = s3_virge_close, + .reset = s3_virge_reset, + { .available = s3_virge_375_available }, + .speed_changed = s3_virge_speed_changed, + .force_redraw = s3_virge_force_redraw, + .config = s3_virge_config }; -const device_t s3_diamond_stealth_2000pro_pci_device = -{ - "S3 ViRGE/DX (Diamond Stealth 3D 2000 Pro) PCI", - "stealth3d_2000pro_pci", - DEVICE_PCI, - S3_DIAMOND_STEALTH3D_2000PRO, - s3_virge_init, - s3_virge_close, - s3_virge_reset, - { s3_virge_375_diamond_available }, - s3_virge_speed_changed, - s3_virge_force_redraw, - s3_virge_config +const device_t s3_diamond_stealth_2000pro_pci_device = { + .name = "S3 ViRGE/DX (Diamond Stealth 3D 2000 Pro) PCI", + .internal_name = "stealth3d_2000pro_pci", + .flags = DEVICE_PCI, + .local = S3_DIAMOND_STEALTH3D_2000PRO, + .init = s3_virge_init, + .close = s3_virge_close, + .reset = s3_virge_reset, + { .available = s3_virge_375_diamond_available }, + .speed_changed = s3_virge_speed_changed, + .force_redraw = s3_virge_force_redraw, + .config = s3_virge_config }; -const device_t s3_virge_385_pci_device = -{ - "S3 ViRGE/GX (385) PCI", - "virge385_pci", - DEVICE_PCI, - S3_VIRGE_GX, - s3_virge_init, - s3_virge_close, - s3_virge_reset, - { s3_virge_385_available }, - s3_virge_speed_changed, - s3_virge_force_redraw, - s3_virge_config +const device_t s3_virge_385_pci_device = { + .name = "S3 ViRGE/GX (385) PCI", + .internal_name = "virge385_pci", + .flags = DEVICE_PCI, + .local = S3_VIRGE_GX, + .init = s3_virge_init, + .close = s3_virge_close, + .reset = s3_virge_reset, + { .available = s3_virge_385_available }, + .speed_changed = s3_virge_speed_changed, + .force_redraw = s3_virge_force_redraw, + .config = s3_virge_config }; -const device_t s3_virge_357_pci_device = -{ - "S3 ViRGE/GX2 (357) PCI", - "virge357_pci", - DEVICE_PCI, - S3_VIRGE_GX2, - s3_virge_init, - s3_virge_close, - s3_virge_reset, - { s3_virge_357_available }, - s3_virge_speed_changed, - s3_virge_force_redraw, - s3_virge_357_config +const device_t s3_virge_357_pci_device = { + .name = "S3 ViRGE/GX2 (357) PCI", + .internal_name = "virge357_pci", + .flags = DEVICE_PCI, + .local = S3_VIRGE_GX2, + .init = s3_virge_init, + .close = s3_virge_close, + .reset = s3_virge_reset, + { .available = s3_virge_357_available }, + .speed_changed = s3_virge_speed_changed, + .force_redraw = s3_virge_force_redraw, + .config = s3_virge_357_config }; -const device_t s3_virge_357_agp_device = -{ - "S3 ViRGE/GX2 (357) AGP", - "virge357_agp", - DEVICE_AGP, - S3_VIRGE_GX2, - s3_virge_init, - s3_virge_close, - s3_virge_reset, - { s3_virge_357_available }, - s3_virge_speed_changed, - s3_virge_force_redraw, - s3_virge_357_config +const device_t s3_virge_357_agp_device = { + .name = "S3 ViRGE/GX2 (357) AGP", + .internal_name = "virge357_agp", + .flags = DEVICE_AGP, + .local = S3_VIRGE_GX2, + .init = s3_virge_init, + .close = s3_virge_close, + .reset = s3_virge_reset, + { .available = s3_virge_357_available }, + .speed_changed = s3_virge_speed_changed, + .force_redraw = s3_virge_force_redraw, + .config = s3_virge_357_config }; -const device_t s3_diamond_stealth_4000_pci_device = -{ - "S3 ViRGE/GX2 (Diamond Stealth 3D 4000) PCI", - "stealth3d_4000_pci", - DEVICE_PCI, - S3_DIAMOND_STEALTH3D_4000, - s3_virge_init, - s3_virge_close, - s3_virge_reset, - { s3_virge_357_diamond_available }, - s3_virge_speed_changed, - s3_virge_force_redraw, - s3_virge_357_config +const device_t s3_diamond_stealth_4000_pci_device = { + .name = "S3 ViRGE/GX2 (Diamond Stealth 3D 4000) PCI", + .internal_name = "stealth3d_4000_pci", + .flags = DEVICE_PCI, + .local = S3_DIAMOND_STEALTH3D_4000, + .init = s3_virge_init, + .close = s3_virge_close, + .reset = s3_virge_reset, + { .available = s3_virge_357_diamond_available }, + .speed_changed = s3_virge_speed_changed, + .force_redraw = s3_virge_force_redraw, + .config = s3_virge_357_config }; -const device_t s3_diamond_stealth_4000_agp_device = -{ - "S3 ViRGE/GX2 (Diamond Stealth 3D 4000) AGP", - "stealth3d_4000_agp", - DEVICE_AGP, - S3_DIAMOND_STEALTH3D_4000, - s3_virge_init, - s3_virge_close, - s3_virge_reset, - { s3_virge_357_diamond_available }, - s3_virge_speed_changed, - s3_virge_force_redraw, - s3_virge_357_config +const device_t s3_diamond_stealth_4000_agp_device = { + .name = "S3 ViRGE/GX2 (Diamond Stealth 3D 4000) AGP", + .internal_name = "stealth3d_4000_agp", + .flags = DEVICE_AGP, + .local = S3_DIAMOND_STEALTH3D_4000, + .init = s3_virge_init, + .close = s3_virge_close, + .reset = s3_virge_reset, + { .available = s3_virge_357_diamond_available }, + .speed_changed = s3_virge_speed_changed, + .force_redraw = s3_virge_force_redraw, + .config = s3_virge_357_config }; -const device_t s3_trio3d2x_pci_device = -{ - "S3 Trio3D/2X (362) PCI", - "trio3d2x", - DEVICE_PCI, - S3_TRIO_3D2X, - s3_virge_init, - s3_virge_close, - s3_virge_reset, - { s3_trio3d2x_available }, - s3_virge_speed_changed, - s3_virge_force_redraw, - s3_trio3d2x_config +const device_t s3_trio3d2x_pci_device = { + .name = "S3 Trio3D/2X (362) PCI", + .internal_name = "trio3d2x", + .flags = DEVICE_PCI, + .local = S3_TRIO_3D2X, + .init = s3_virge_init, + .close = s3_virge_close, + .reset = s3_virge_reset, + { .available = s3_trio3d2x_available }, + .speed_changed = s3_virge_speed_changed, + .force_redraw = s3_virge_force_redraw, + .config = s3_trio3d2x_config }; -const device_t s3_trio3d2x_agp_device = -{ - "S3 Trio3D/2X (362) AGP", - "trio3d2x_agp", - DEVICE_AGP, - S3_TRIO_3D2X, - s3_virge_init, - s3_virge_close, - s3_virge_reset, - { s3_trio3d2x_available }, - s3_virge_speed_changed, - s3_virge_force_redraw, - s3_trio3d2x_config +const device_t s3_trio3d2x_agp_device = { + .name = "S3 Trio3D/2X (362) AGP", + .internal_name = "trio3d2x_agp", + .flags = DEVICE_AGP, + .local = S3_TRIO_3D2X, + .init = s3_virge_init, + .close = s3_virge_close, + .reset = s3_virge_reset, + { .available = s3_trio3d2x_available }, + .speed_changed = s3_virge_speed_changed, + .force_redraw = s3_virge_force_redraw, + .config = s3_trio3d2x_config }; diff --git a/src/video/vid_sc1148x_ramdac.c b/src/video/vid_sc1148x_ramdac.c index 0134c31d7..24ca4aeec 100644 --- a/src/video/vid_sc1148x_ramdac.c +++ b/src/video/vid_sc1148x_ramdac.c @@ -1,20 +1,20 @@ /* - * 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. + * 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. + * This file is part of the 86Box distribution. * - * Emulation of Sierra SC1148x RAMDACs and clones (e.g.: Winbond). + * Emulation of Sierra SC1148x RAMDACs and clones (e.g.: Winbond). * - * Used by the S3 911 and 924 chips. + * Used by the S3 911 and 924 chips. * * * - * Authors: TheCollector1995, + * Authors: TheCollector1995, * - * Copyright 2020 TheCollector1995. + * Copyright 2020 TheCollector1995. */ #include #include @@ -28,109 +28,106 @@ #include <86box/video.h> #include <86box/vid_svga.h> - -typedef struct -{ - int type; - int state; - int rs2; +typedef struct sc1148x_ramdac_t { + int type; + int state; + int rs2; uint8_t ctrl; } sc1148x_ramdac_t; - void -sc1148x_ramdac_out(uint16_t addr, int rs2, uint8_t val, void *p, svga_t *svga) +sc1148x_ramdac_out(uint16_t addr, int rs2, uint8_t val, void *priv, svga_t *svga) { - sc1148x_ramdac_t *ramdac = (sc1148x_ramdac_t *) p; - uint8_t rs = (addr & 0x03); - rs |= ((!!rs2) << 2); - int oldbpp = 0; + sc1148x_ramdac_t *ramdac = (sc1148x_ramdac_t *) priv; + uint8_t rs = (addr & 0x03) | ((!!rs2) << 2); + int oldbpp = 0; - switch (addr) { - case 0x3c6: - switch (ramdac->state) { - case 4: - ramdac->state = 0; - if (val == 0xff) - break; - ramdac->ctrl = val; - ramdac->ctrl = (ramdac->ctrl & ~1) | ((((val >> 2) ^ val) & (val & 0x20)) >> 5); - oldbpp = svga->bpp; - switch (ramdac->type) { - case 0: /* Sierra Mark 2 (11483)*/ - case 2: /* Sierra Mark 2 (11484)*/ - case 3: /* Sierra Mark 1 (11486)*/ - if (val & 0xa0) { - svga->bpp = 15; - } else if (val == 0x00) - svga->bpp = 8; - break; - case 1: /* Sierra Mark 3 (11487)*/ - if (val & 0xa0) { - if (val & 0x40) - svga->bpp = 16; - else - svga->bpp = 15; - } else if (val == 0x00) - svga->bpp = 8; - break; - } - if (oldbpp != svga->bpp) - svga_recalctimings(svga); - return; - default: - svga_out(addr, val, svga); - break; - } - break; + switch (rs) { + case 2: + case 6: + switch (ramdac->state) { + case 4: + ramdac->state = 0; + if (val == 0xff) + break; + ramdac->ctrl = val; + ramdac->ctrl = (ramdac->ctrl & ~1) | ((((val >> 2) ^ val) & (val & 0x20)) >> 5); + oldbpp = svga->bpp; + switch (ramdac->type) { + case 0: /* Sierra Mark 2 (11483)*/ + case 2: /* Sierra Mark 2 (11484)*/ + case 3: /* Sierra Mark 1 (11486)*/ + if (val & 0xa0) { + svga->bpp = 15; + } else if (val == 0x00) + svga->bpp = 8; + break; + case 1: /* Sierra Mark 3 (11487)*/ + if (val & 0xa0) { + if (val & 0x40) + svga->bpp = 16; + else + svga->bpp = 15; + } else if (val == 0x00) + svga->bpp = 8; + break; - case 0x3c7: case 0x3c8: - case 0x3c9: - ramdac->state = 0; - svga_out(addr, val, svga); - break; + default: + break; + } + if (oldbpp != svga->bpp) + svga_recalctimings(svga); + return; + default: + svga_out(addr, val, svga); + break; + } + break; + + default: + ramdac->state = 0; + svga_out(addr, val, svga); + break; } } - uint8_t -sc1148x_ramdac_in(uint16_t addr, int rs2, void *p, svga_t *svga) +sc1148x_ramdac_in(uint16_t addr, int rs2, void *priv, svga_t *svga) { - sc1148x_ramdac_t *ramdac = (sc1148x_ramdac_t *) p; - uint8_t ret = 0xff; - uint8_t rs = (addr & 0x03); - rs |= ((!!rs2) << 2); + sc1148x_ramdac_t *ramdac = (sc1148x_ramdac_t *) priv; + uint8_t ret = 0xff; + uint8_t rs = (addr & 0x03) | ((!!rs2) << 2); - switch (addr) { - case 0x3c6: - switch (ramdac->state) { - case 1: - case 2: case 3: - ret = 0x00; - ramdac->state++; - break; - case 4: - ret = ramdac->ctrl; - ret = (ret & ~0x18) | (svga->dac_mask & 0x18); - break; - default: - ret = svga_in(addr, svga); - ramdac->state++; - break; - } - break; + switch (rs) { + case 2: + case 6: + switch (ramdac->state) { + case 1: + case 2: + case 3: + ret = 0x00; + ramdac->state++; + break; + case 4: + ret = ramdac->ctrl; + ret = (ret & ~0x18) | (svga->dac_mask & 0x18); + break; + default: + ret = svga_in(addr, svga); + ramdac->state++; + break; + } + break; - case 0x3c7: case 0x3c8: - case 0x3c9: - ret = svga_in(addr, svga); - ramdac->state = 0; - break; + default: + ret = svga_in(addr, svga); + ramdac->state = 0; + break; } return ret; } - static void * sc1148x_ramdac_init(const device_t *info) { @@ -142,48 +139,67 @@ sc1148x_ramdac_init(const device_t *info) return ramdac; } - static void sc1148x_ramdac_close(void *priv) { sc1148x_ramdac_t *ramdac = (sc1148x_ramdac_t *) priv; if (ramdac) - free(ramdac); + free(ramdac); } -const device_t sc11483_ramdac_device = -{ - "Sierra SC11483 RAMDAC", - "sc11483_ramdac", - 0, 0, - sc1148x_ramdac_init, sc1148x_ramdac_close, - NULL, { NULL }, NULL, NULL +const device_t sc11483_ramdac_device = { + .name = "Sierra SC11483 RAMDAC", + .internal_name = "sc11483_ramdac", + .flags = 0, + .local = 0, + .init = sc1148x_ramdac_init, + .close = sc1148x_ramdac_close, + .reset = NULL, + { .available = NULL }, + .speed_changed = NULL, + .force_redraw = NULL, + .config = NULL }; -const device_t sc11487_ramdac_device = -{ - "Sierra SC11487 RAMDAC", - "sc11487_ramdac", - 0, 1, - sc1148x_ramdac_init, sc1148x_ramdac_close, - NULL, { NULL }, NULL, NULL +const device_t sc11487_ramdac_device = { + .name = "Sierra SC11487 RAMDAC", + .internal_name = "sc11487_ramdac", + .flags = 0, + .local = 1, + .init = sc1148x_ramdac_init, + .close = sc1148x_ramdac_close, + .reset = NULL, + { .available = NULL }, + .speed_changed = NULL, + .force_redraw = NULL, + .config = NULL }; -const device_t sc11484_nors2_ramdac_device = -{ - "Sierra SC11484 RAMDAC (no RS2 signal)", - "sc11484_nors2_ramdac", - 0, 2, - sc1148x_ramdac_init, sc1148x_ramdac_close, - NULL, { NULL }, NULL, NULL +const device_t sc11484_nors2_ramdac_device = { + .name = "Sierra SC11484 RAMDAC (no RS2 signal)", + .internal_name = "sc11484_nors2_ramdac", + .flags = 0, + .local = 2, + .init = sc1148x_ramdac_init, + .close = sc1148x_ramdac_close, + .reset = NULL, + { .available = NULL }, + .speed_changed = NULL, + .force_redraw = NULL, + .config = NULL }; -const device_t sc11486_ramdac_device = -{ - "Sierra SC11486 RAMDAC", - "sc11486_ramdac", - 0, 3, - sc1148x_ramdac_init, sc1148x_ramdac_close, - NULL, { NULL }, NULL, NULL -}; \ No newline at end of file +const device_t sc11486_ramdac_device = { + .name = "Sierra SC11486 RAMDAC", + .internal_name = "sc11486_ramdac", + .flags = 0, + .local = 3, + .init = sc1148x_ramdac_init, + .close = sc1148x_ramdac_close, + .reset = NULL, + { .available = NULL }, + .speed_changed = NULL, + .force_redraw = NULL, + .config = NULL +}; diff --git a/src/video/vid_sc1502x_ramdac.c b/src/video/vid_sc1502x_ramdac.c index 655524a58..7cbcaf05d 100644 --- a/src/video/vid_sc1502x_ramdac.c +++ b/src/video/vid_sc1502x_ramdac.c @@ -1,22 +1,22 @@ /* - * 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. + * 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. + * This file is part of the 86Box distribution. * - * Emulation of a Sierra SC1502X RAMDAC. + * Emulation of a Sierra SC1502X RAMDAC. * - * Used by the TLIVESA1 driver for ET4000. + * Used by the TLIVESA1 driver for ET4000. * * * - * Authors: Sarah Walker, - * Miran Grca, + * Authors: Sarah Walker, + * Miran Grca, * - * Copyright 2008-2018 Sarah Walker. - * Copyright 2016-2018 Miran Grca. + * Copyright 2008-2018 Sarah Walker. + * Copyright 2016-2018 Miran Grca. */ #include #include @@ -29,113 +29,122 @@ #include <86box/timer.h> #include <86box/video.h> #include <86box/vid_svga.h> +#include <86box/plat_unused.h> - -typedef struct -{ - int state; +typedef struct sc1502x_ramdac_t { + int state; uint8_t ctrl; } sc1502x_ramdac_t; - void -sc1502x_ramdac_out(uint16_t addr, uint8_t val, void *p, svga_t *svga) +sc1502x_ramdac_out(uint16_t addr, uint8_t val, void *priv, svga_t *svga) { - sc1502x_ramdac_t *ramdac = (sc1502x_ramdac_t *) p; - int oldbpp = 0; + sc1502x_ramdac_t *ramdac = (sc1502x_ramdac_t *) priv; + int oldbpp = 0; switch (addr) { - case 0x3C6: - if (ramdac->state == 4) { - ramdac->state = 0; - if (val == 0xFF) - break; - ramdac->ctrl = val; - oldbpp = svga->bpp; - switch ((val & 1) | ((val & 0xc0) >> 5)) { - case 0: - svga->bpp = 8; - break; - case 2: - case 3: - switch (val & 0x20) { - case 0x00: - svga->bpp = 32; - break; - case 0x20: - svga->bpp = 24; - break; - } - break; - case 4: - case 5: - svga->bpp = 15; - break; - case 6: - svga->bpp = 16; - break; - case 7: - if (val & 4) { - switch (val & 0x20) { - case 0x00: - svga->bpp = 32; - break; - case 0x20: - svga->bpp = 24; - break; - } - break; - } else { - svga->bpp = 16; - break; - } - break; - } - if (oldbpp != svga->bpp) - svga_recalctimings(svga); - return; - } - ramdac->state = 0; - break; - case 0x3C7: - case 0x3C8: - case 0x3C9: - ramdac->state = 0; - break; + case 0x3C6: + if (ramdac->state == 4) { + ramdac->state = 0; + if (val == 0xFF) + break; + ramdac->ctrl = val; + oldbpp = svga->bpp; + switch ((val & 1) | ((val & 0xc0) >> 5)) { + case 0: + svga->bpp = 8; + break; + case 2: + case 3: + switch (val & 0x20) { + case 0x00: + svga->bpp = 32; + break; + case 0x20: + svga->bpp = 24; + break; + + default: + break; + } + break; + case 4: + case 5: + svga->bpp = 15; + break; + case 6: + svga->bpp = 16; + break; + case 7: + if (val & 4) { + switch (val & 0x20) { + case 0x00: + svga->bpp = 32; + break; + case 0x20: + svga->bpp = 24; + break; + + default: + break; + } + } else { + svga->bpp = 16; + } + break; + + default: + break; + } + if (oldbpp != svga->bpp) + svga_recalctimings(svga); + return; + } + ramdac->state = 0; + break; + case 0x3C7: + case 0x3C8: + case 0x3C9: + ramdac->state = 0; + break; + + default: + break; } svga_out(addr, val, svga); } - uint8_t -sc1502x_ramdac_in(uint16_t addr, void *p, svga_t *svga) +sc1502x_ramdac_in(uint16_t addr, void *priv, svga_t *svga) { - sc1502x_ramdac_t *ramdac = (sc1502x_ramdac_t *) p; - uint8_t temp = svga_in(addr, svga); + sc1502x_ramdac_t *ramdac = (sc1502x_ramdac_t *) priv; + uint8_t temp = svga_in(addr, svga); switch (addr) { - case 0x3C6: - if (ramdac->state == 4) { - ramdac->state = 0; - temp = ramdac->ctrl; - break; - } - ramdac->state++; - break; - case 0x3C7: - case 0x3C8: - case 0x3C9: - ramdac->state = 0; - break; + case 0x3C6: + if (ramdac->state == 4) { + ramdac->state = 0; + temp = ramdac->ctrl; + break; + } + ramdac->state++; + break; + case 0x3C7: + case 0x3C8: + case 0x3C9: + ramdac->state = 0; + break; + + default: + break; } return temp; } - static void * -sc1502x_ramdac_init(const device_t *info) +sc1502x_ramdac_init(UNUSED(const device_t *info)) { sc1502x_ramdac_t *ramdac = (sc1502x_ramdac_t *) malloc(sizeof(sc1502x_ramdac_t)); memset(ramdac, 0, sizeof(sc1502x_ramdac_t)); @@ -143,22 +152,25 @@ sc1502x_ramdac_init(const device_t *info) return ramdac; } - static void sc1502x_ramdac_close(void *priv) { sc1502x_ramdac_t *ramdac = (sc1502x_ramdac_t *) priv; if (ramdac) - free(ramdac); + free(ramdac); } - -const device_t sc1502x_ramdac_device = -{ - "Sierra SC1502x RAMDAC", - "sc1502x_ramdac", - 0, 0, - sc1502x_ramdac_init, sc1502x_ramdac_close, - NULL, { NULL }, NULL, NULL +const device_t sc1502x_ramdac_device = { + .name = "Sierra SC1502x RAMDAC", + .internal_name = "sc1502x_ramdac", + .flags = 0, + .local = 0, + .init = sc1502x_ramdac_init, + .close = sc1502x_ramdac_close, + .reset = NULL, + { .available = NULL }, + .speed_changed = NULL, + .force_redraw = NULL, + .config = NULL }; diff --git a/src/video/vid_sdac_ramdac.c b/src/video/vid_sdac_ramdac.c index e1026bf25..83796506e 100644 --- a/src/video/vid_sdac_ramdac.c +++ b/src/video/vid_sdac_ramdac.c @@ -1,20 +1,20 @@ /* - * 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. + * 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. + * This file is part of the 86Box distribution. * - * 87C716 'SDAC' true colour RAMDAC emulation. + * 87C716 'SDAC' true colour RAMDAC emulation. * * * - * Authors: Sarah Walker, - * Miran Grca, + * Authors: Sarah Walker, + * Miran Grca, * - * Copyright 2008-2019 Sarah Walker. - * Copyright 2016-2019 Miran Grca. + * Copyright 2008-2019 Sarah Walker. + * Copyright 2016-2019 Miran Grca. */ #include #include @@ -28,9 +28,7 @@ #include <86box/video.h> #include <86box/vid_svga.h> - -enum -{ +enum { ICS_5300 = 0, ICS_5301, ICS_5340, @@ -38,247 +36,252 @@ enum ICS_5342 }; +#define ICS_S3_MASK 7 +#define ICS_S3 8 -#define ICS_S3_MASK 7 -#define ICS_S3 8 +#define S3_86C708 (ICS_5300 | ICS_S3) +#define S3_86C716 (ICS_5342 | ICS_S3) -#define S3_86C708 (ICS_5300 | ICS_S3) -#define S3_86C716 (ICS_5342 | ICS_S3) - - -typedef struct sdac_ramdac_t -{ +typedef struct sdac_ramdac_t { uint16_t regs[256]; - int magic_count, - windex, rindex, - reg_ff, rs2; - uint8_t type, command; + int magic_count; + int windex; + int rindex; + int reg_ff; + int rs2; + uint8_t type; + uint8_t command; } sdac_ramdac_t; - static void sdac_control_write(sdac_ramdac_t *ramdac, svga_t *svga, uint8_t val) { ramdac->command = val; switch (ramdac->type & ICS_S3_MASK) { - case ICS_5300: - case ICS_5301: - switch (val >> 5) { - case 0x00: - default: - svga->bpp = 8; - break; - case 0x01: - case 0x04: - case 0x05: - svga->bpp = 15; - break; - case 0x03: - case 0x06: - svga->bpp = 16; - break; - case 0x02: - case 0x07: - svga->bpp = 24; - break; - } - break; - case ICS_5340: - case ICS_5341: - case ICS_5342: - switch (val >> 4) { - case 0x00: - case 0x01: /* This is actually 8bpp with two pixels read at a time. */ - default: - svga->bpp = 8; - break; - case 0x02: - case 0x03: - case 0x08: - case 0x0a: - svga->bpp = 15; - break; - case 0x05: - case 0x06: - case 0x0c: - svga->bpp = 16; - break; - case 0x04: - case 0x09: - case 0x0e: - svga->bpp = 24; - break; - case 0x07: - svga->bpp = 32; - break; - } - break; + case ICS_5300: + case ICS_5301: + switch (val >> 5) { + default: + case 0x00: + svga->bpp = 8; + break; + case 0x01: + case 0x04: + case 0x05: + svga->bpp = 15; + break; + case 0x03: + case 0x06: + svga->bpp = 16; + break; + case 0x02: + case 0x07: + svga->bpp = 24; + break; + } + break; + case ICS_5340: + case ICS_5341: + case ICS_5342: + switch (val >> 4) { + default: + case 0x00: + case 0x01: /* This is actually 8bpp with two pixels read at a time. */ + svga->bpp = 8; + break; + case 0x02: + case 0x03: + case 0x08: + case 0x0a: + svga->bpp = 15; + break; + case 0x05: + case 0x06: + case 0x0c: + svga->bpp = 16; + break; + case 0x04: + case 0x09: + case 0x0e: + svga->bpp = 24; + break; + case 0x07: + svga->bpp = 32; + break; + } + break; + + default: + break; } svga_recalctimings(svga); } - static void sdac_reg_write(sdac_ramdac_t *ramdac, int reg, uint8_t val) { if ((reg >= 2 && reg <= 7) || (reg == 0xa) || (reg == 0xe)) { - if (!ramdac->reg_ff) - ramdac->regs[reg] = (ramdac->regs[reg] & 0xff00) | val; - else - ramdac->regs[reg] = (ramdac->regs[reg] & 0x00ff) | (val << 8); + if (!ramdac->reg_ff) + ramdac->regs[reg] = (ramdac->regs[reg] & 0xff00) | val; + else + ramdac->regs[reg] = (ramdac->regs[reg] & 0x00ff) | (val << 8); } ramdac->reg_ff = !ramdac->reg_ff; if (!ramdac->reg_ff) - ramdac->windex++; + ramdac->windex++; } - static uint8_t sdac_reg_read(sdac_ramdac_t *ramdac, int reg) { uint8_t temp; if (!ramdac->reg_ff) - temp = ramdac->regs[reg] & 0xff; + temp = ramdac->regs[reg] & 0xff; else - temp = ramdac->regs[reg] >> 8; + temp = ramdac->regs[reg] >> 8; ramdac->reg_ff = !ramdac->reg_ff; if (!ramdac->reg_ff) - ramdac->rindex++; + ramdac->rindex++; return temp; } - void -sdac_ramdac_out(uint16_t addr, int rs2, uint8_t val, void *p, svga_t *svga) +sdac_ramdac_out(uint16_t addr, int rs2, uint8_t val, void *priv, svga_t *svga) { - sdac_ramdac_t *ramdac = (sdac_ramdac_t *) p; - uint8_t rs = (addr & 0x03); + sdac_ramdac_t *ramdac = (sdac_ramdac_t *) priv; + uint8_t rs = (addr & 0x03); rs |= ((!!rs2) << 2); if (rs != 0x02) - ramdac->magic_count = 0; + ramdac->magic_count = 0; switch (rs) { - case 0x02: - switch (ramdac->magic_count) { - case 4: - sdac_control_write(ramdac, svga, val); - ramdac->magic_count = 0; - break; - default: - svga_out(addr, val, svga); - break; - } - break; - case 0x00: - case 0x01: - case 0x03: - svga_out(addr, val, svga); - break; - case 0x04: - ramdac->windex = val; - ramdac->reg_ff = 0; - break; - case 0x05: - sdac_reg_write(ramdac, ramdac->windex & 0xff, val); - break; - case 0x06: - sdac_control_write(ramdac, svga, val); - break; - case 0x07: - ramdac->rindex = val; - ramdac->reg_ff = 0; - break; + case 0x02: + switch (ramdac->magic_count) { + case 4: + sdac_control_write(ramdac, svga, val); + ramdac->magic_count = 0; + break; + default: + svga_out(addr, val, svga); + break; + } + break; + case 0x00: + case 0x01: + case 0x03: + svga_out(addr, val, svga); + break; + case 0x04: + ramdac->windex = val; + ramdac->reg_ff = 0; + break; + case 0x05: + sdac_reg_write(ramdac, ramdac->windex & 0xff, val); + break; + case 0x06: + sdac_control_write(ramdac, svga, val); + break; + case 0x07: + ramdac->rindex = val; + ramdac->reg_ff = 0; + break; + + default: + break; } } - uint8_t -sdac_ramdac_in(uint16_t addr, int rs2, void *p, svga_t *svga) +sdac_ramdac_in(uint16_t addr, int rs2, void *priv, svga_t *svga) { - sdac_ramdac_t *ramdac = (sdac_ramdac_t *) p; - uint8_t temp = 0xff; - uint8_t rs = (addr & 0x03); + sdac_ramdac_t *ramdac = (sdac_ramdac_t *) priv; + uint8_t temp = 0xff; + uint8_t rs = (addr & 0x03); rs |= ((!!rs2) << 2); if (rs != 0x02) - ramdac->magic_count = 0; + ramdac->magic_count = 0; switch (rs) { - case 0x02: - switch (ramdac->magic_count) { - case 1: case 2: - temp = 0x00; - ramdac->magic_count++; - break; - case 3: - temp = (ramdac->type & ICS_S3) ? 0x70 : 0x00; - ramdac->magic_count++; - break; - case 4: - temp = ramdac->command; - ramdac->magic_count = 0; - break; - default: - temp = svga_in(addr, svga); - ramdac->magic_count++; - break; - } - break; - case 0x00: - case 0x01: - case 0x03: - temp = svga_in(addr, svga); - break; - case 0x04: - temp = ramdac->windex; - break; - case 0x05: - temp = sdac_reg_read(ramdac, ramdac->rindex & 0xff); - break; - case 0x06: - temp = ramdac->command; - break; - case 0x07: - temp = ramdac->rindex; - break; + case 0x02: + switch (ramdac->magic_count) { + case 1: + case 2: + temp = 0x00; + ramdac->magic_count++; + break; + case 3: + temp = (ramdac->type & ICS_S3) ? 0x70 : 0x00; + ramdac->magic_count++; + break; + case 4: + temp = ramdac->command; + ramdac->magic_count = 0; + break; + default: + temp = svga_in(addr, svga); + ramdac->magic_count++; + break; + } + break; + case 0x00: + case 0x01: + case 0x03: + temp = svga_in(addr, svga); + break; + case 0x04: + temp = ramdac->windex; + break; + case 0x05: + temp = sdac_reg_read(ramdac, ramdac->rindex & 0xff); + break; + case 0x06: + temp = ramdac->command; + break; + case 0x07: + temp = ramdac->rindex; + break; + + default: + break; } return temp; } - float -sdac_getclock(int clock, void *p) +sdac_getclock(int clock, void *priv) { - sdac_ramdac_t *ramdac = (sdac_ramdac_t *)p; - float t; - int m, n1, n2; + const sdac_ramdac_t *ramdac = (sdac_ramdac_t *) priv; + float t; + int m; + int n1; + int n2; if (ramdac->regs[0xe] & (1 << 5)) - clock = ramdac->regs[0xe] & 7; + clock = ramdac->regs[0xe] & 7; clock &= 7; if (clock == 0) - return 25175000.0; + return 25175000.0; if (clock == 1) - return 28322000.0; + return 28322000.0; - m = (ramdac->regs[clock] & 0x7f) + 2; - n1 = ((ramdac->regs[clock] >> 8) & 0x1f) + 2; + m = (ramdac->regs[clock] & 0x7f) + 2; + n1 = ((ramdac->regs[clock] >> 8) & 0x1f) + 2; n2 = ((ramdac->regs[clock] >> 13) & 0x07); n2 = (1 << n2); - t = (14318184.0f * (float)m) / (float)(n1 * n2); + t = (14318184.0f * (float) m) / (float) (n1 * n2); return t; } - void * sdac_ramdac_init(const device_t *info) { @@ -293,49 +296,67 @@ sdac_ramdac_init(const device_t *info) return ramdac; } - static void sdac_ramdac_close(void *priv) { sdac_ramdac_t *ramdac = (sdac_ramdac_t *) priv; if (ramdac) - free(ramdac); + free(ramdac); } - -const device_t gendac_ramdac_device = -{ - "S3 GENDAC 86c708 RAMDAC", - "gendac_ramdac", - 0, S3_86C708, - sdac_ramdac_init, sdac_ramdac_close, - NULL, { NULL }, NULL, NULL +const device_t gendac_ramdac_device = { + .name = "S3 GENDAC 86c708 RAMDAC", + .internal_name = "gendac_ramdac", + .flags = 0, + .local = S3_86C708, + .init = sdac_ramdac_init, + .close = sdac_ramdac_close, + .reset = NULL, + { .available = NULL }, + .speed_changed = NULL, + .force_redraw = NULL, + .config = NULL }; -const device_t tseng_ics5301_ramdac_device = -{ - "Tseng ICS5301 GENDAC RAMDAC", - "tseng_ics5301_ramdac", - 0, ICS_5301, - sdac_ramdac_init, sdac_ramdac_close, - NULL, { NULL }, NULL, NULL +const device_t tseng_ics5301_ramdac_device = { + .name = "Tseng ICS5301 GENDAC RAMDAC", + .internal_name = "tseng_ics5301_ramdac", + .flags = 0, + .local = ICS_5301, + .init = sdac_ramdac_init, + .close = sdac_ramdac_close, + .reset = NULL, + { .available = NULL }, + .speed_changed = NULL, + .force_redraw = NULL, + .config = NULL }; -const device_t tseng_ics5341_ramdac_device = -{ - "Tseng ICS5341 GENDAC RAMDAC", - "tseng_ics5341_ramdac", - 0, ICS_5341, - sdac_ramdac_init, sdac_ramdac_close, - NULL, { NULL }, NULL, NULL +const device_t tseng_ics5341_ramdac_device = { + .name = "Tseng ICS5341 GENDAC RAMDAC", + .internal_name = "tseng_ics5341_ramdac", + .flags = 0, + .local = ICS_5341, + .init = sdac_ramdac_init, + .close = sdac_ramdac_close, + .reset = NULL, + { .available = NULL }, + .speed_changed = NULL, + .force_redraw = NULL, + .config = NULL }; -const device_t sdac_ramdac_device = -{ - "S3 SDAC 86c716 RAMDAC", - "sdac_ramdac", - 0, S3_86C716, - sdac_ramdac_init, sdac_ramdac_close, - NULL, { NULL }, NULL, NULL +const device_t sdac_ramdac_device = { + .name = "S3 SDAC 86c716 RAMDAC", + .internal_name = "sdac_ramdac", + .flags = 0, + .local = S3_86C716, + .init = sdac_ramdac_init, + .close = sdac_ramdac_close, + .reset = NULL, + { .available = NULL }, + .speed_changed = NULL, + .force_redraw = NULL, + .config = NULL }; diff --git a/src/video/vid_sigma.c b/src/video/vid_sigma.c index 08ac011d3..56f8b99aa 100644 --- a/src/video/vid_sigma.c +++ b/src/video/vid_sigma.c @@ -1,18 +1,18 @@ /* - * 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. + * 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. + * This file is part of the 86Box distribution. * - * Sigma Color 400 emulation. + * Sigma Color 400 emulation. * * * - * Authors: John Elliott, + * Authors: John Elliott, * - * Copyright 2018 John Elliott. + * Copyright 2018 John Elliott. */ #include #include @@ -29,37 +29,37 @@ #include <86box/rom.h> #include <86box/device.h> #include <86box/video.h> +#include <86box/plat_unused.h> - -#define ROM_SIGMA_FONT "roms/video/sigma/sigma400_font.rom" -#define ROM_SIGMA_BIOS "roms/video/sigma/sigma400_bios.rom" +#define ROM_SIGMA_FONT "roms/video/sigma/sigma400_font.rom" +#define ROM_SIGMA_BIOS "roms/video/sigma/sigma400_bios.rom" /* The Sigma Designs Color 400 is a video card from 1985, presumably intended * as an EGA competitor. - * - * The hardware seems to have gone through various iterations; I've seen + * + * The hardware seems to have gone through various iterations; I've seen * pictures of full-length and half-length versions. - * TH99 describes the jumpers / switches: + * TH99 describes the jumpers / switches: * * - * The card is CGA-compatible at BIOS level, but to improve compatibility - * attempts to write to the CGA I/O ports at 0x3D0-0x3DF trigger an NMI. The + * The card is CGA-compatible at BIOS level, but to improve compatibility + * attempts to write to the CGA I/O ports at 0x3D0-0x3DF trigger an NMI. The * card's BIOS handles the NMI and translates the CGA writes into commands * to its own hardware at 0x2D0-0x2DF. (DIP switches on the card allow the * base address to be changed, but since the BIOS dump I have doesn't support * this I haven't emulated it. Likewise the BIOS ROM address can be changed, * but I'm going with the default of 0xC0000). * - * The BIOS still functions if the NMI system isn't operational. There + * The BIOS still functions if the NMI system isn't operational. There * doesn't seem to be a jumper or DIP switch to lock it out, but at startup * the BIOS tests for its presence and configures itself to work or not * as required. I've therefore added a configuration option to handle this. * - * The card's real CRTC at 0x2D0/0x2D1 appears to be a 6845. One oddity is - * that all its horizontal counts are halved compared to what a real CGA - * uses; 40-column modes have a width of 20, and 80-column modes have a + * The card's real CRTC at 0x2D0/0x2D1 appears to be a 6845. One oddity is + * that all its horizontal counts are halved compared to what a real CGA + * uses; 40-column modes have a width of 20, and 80-column modes have a * width of 40. This means that the CRTC cursor position (registers 14/15) can - * only address even-numbered columns, so the top bit of the control + * only address even-numbered columns, so the top bit of the control * register at 0x2D9 is used to adjust the position. * * Apart from the CRTC, registers are: @@ -72,46 +72,46 @@ * Graphics 320x200: 0x0F * Graphics 640x200: 0x1F * Graphics 640x400: 0x7F - * + * * I have assumed this is a bitmap with the following meaning: */ -#define MODE_80COLS 0x01 /* For text modes, 80 columns across */ -#define MODE_GRAPHICS 0x02 /* Graphics mode */ -#define MODE_NOBLINK 0x04 /* Disable blink? */ -#define MODE_ENABLE 0x08 /* Enable display */ -#define MODE_HRGFX 0x10 /* For graphics modes, 640 pixels across */ -#define MODE_640x400 0x40 /* 400-line graphics mode */ -#define MODE_FONT16 0x80 /* Use 16-pixel high font */ +#define MODE_80COLS 0x01 /* For text modes, 80 columns across */ +#define MODE_GRAPHICS 0x02 /* Graphics mode */ +#define MODE_NOBLINK 0x04 /* Disable blink? */ +#define MODE_ENABLE 0x08 /* Enable display */ +#define MODE_HRGFX 0x10 /* For graphics modes, 640 pixels across */ +#define MODE_640x400 0x40 /* 400-line graphics mode */ +#define MODE_FONT16 0x80 /* Use 16-pixel high font */ /* * 0x2D9: Control register, with the following bits: */ -#define CTL_CURSOR 0x80 /* Low bit of cursor position */ -#define CTL_NMI 0x20 /* Writes to 0x3D0-0x3DF trigger NMI */ -#define CTL_CLEAR_LPEN 0x08 /* Strobe 0 to clear lightpen latch */ -#define CTL_SET_LPEN 0x04 /* Strobe 0 to set lightpen latch */ -#define CTL_PALETTE 0x01 /* 0x2DE writes to palette (1) or plane (0) */ +#define CTL_CURSOR 0x80 /* Low bit of cursor position */ +#define CTL_NMI 0x20 /* Writes to 0x3D0-0x3DF trigger NMI */ +#define CTL_CLEAR_LPEN 0x08 /* Strobe 0 to clear lightpen latch */ +#define CTL_SET_LPEN 0x04 /* Strobe 0 to set lightpen latch */ +#define CTL_PALETTE 0x01 /* 0x2DE writes to palette (1) or plane (0) */ /* - * The card BIOS seems to support two variants of the hardware: One where + * The card BIOS seems to support two variants of the hardware: One where * bits 2 and 3 are normally 1 and are set to 0 to set/clear the latch, and * one where they are normally 0 and are set to 1. Behaviour is selected by * whether the byte at C000:17FFh is greater than 2Fh. * * 0x2DA: Status register. */ -#define STATUS_CURSOR 0x80 /* Last value written to bit 7 of 0x2D9 */ -#define STATUS_NMI 0x20 /* Last value written to bit 5 of 0x2D9 */ -#define STATUS_RETR_V 0x10 /* Vertical retrace */ -#define STATUS_LPEN_T 0x04 /* Lightpen switch is off */ -#define STATUS_LPEN_A 0x02 /* Edge from lightpen has set trigger */ -#define STATUS_RETR_H 0x01 /* Horizontal retrace */ +#define STATUS_CURSOR 0x80 /* Last value written to bit 7 of 0x2D9 */ +#define STATUS_NMI 0x20 /* Last value written to bit 5 of 0x2D9 */ +#define STATUS_RETR_V 0x10 /* Vertical retrace */ +#define STATUS_LPEN_T 0x04 /* Lightpen switch is off */ +#define STATUS_LPEN_A 0x02 /* Edge from lightpen has set trigger */ +#define STATUS_RETR_H 0x01 /* Horizontal retrace */ /* - * 0x2DB: On read: Byte written to the card that triggered NMI + * 0x2DB: On read: Byte written to the card that triggered NMI * 0x2DB: On write: Resets the 'card raised NMI' flag. - * 0x2DC: On read: Bit 7 set if the card raised NMI. If so, bits 0-3 + * 0x2DC: On read: Bit 7 set if the card raised NMI. If so, bits 0-3 * give the low 4 bits of the I/O port address. * 0x2DC: On write: Resets the NMI. * 0x2DD: Memory paging. The memory from 0xC1800 to 0xC1FFF can be either: * - * > ROM: A 128 character 8x16 font for use in graphics modes - * > RAM: Use by the video BIOS to hold its settings. + * > ROM: A 128 character 8x16 font for use in graphics modes + * > RAM: Use by the video BIOS to hold its settings. * * Reading port 2DD switches to ROM. Bit 7 of the value read gives the * previous paging state: bit 7 set if ROM was paged, clear if RAM was @@ -120,42 +120,40 @@ * Writing port 2DD switches to RAM. * * 0x2DE: Meaning depends on bottom bit of value written to port 0x2D9. - * Bit 0 set: Write to palette. High 4 bits of value = register, + * Bit 0 set: Write to palette. High 4 bits of value = register, * low 4 bits = RGBI values (active low) * Bit 0 clear: Write to plane select. Low 2 bits of value select - * plane 0-3 + * plane 0-3 */ - -typedef struct sigma_t -{ +typedef struct sigma_t { mem_mapping_t mapping, bios_ram; - rom_t bios_rom; + rom_t bios_rom; - uint8_t crtc[32]; /* CRTC: Real values */ + uint8_t crtc[32]; /* CRTC: Real values */ - uint8_t lastport; /* Last I/O port written */ - uint8_t lastwrite; /* Value written to that port */ - uint8_t sigma_ctl; /* Controls register: - * Bit 7 is low bit of cursor position - * Bit 5 set if writes to CGA ports trigger NMI - * Bit 3 clears lightpen latch - * Bit 2 sets lightpen latch - * Bit 1 controls meaning of port 2DE - */ - uint8_t enable_nmi; /* Enable the NMI mechanism for CGA emulation?*/ - uint8_t rom_paged; /* Is ROM paged in at 0xC1800? */ + uint8_t lastport; /* Last I/O port written */ + uint8_t lastwrite; /* Value written to that port */ + uint8_t sigma_ctl; /* Controls register: + * Bit 7 is low bit of cursor position + * Bit 5 set if writes to CGA ports trigger NMI + * Bit 3 clears lightpen latch + * Bit 2 sets lightpen latch + * Bit 1 controls meaning of port 2DE + */ + uint8_t enable_nmi; /* Enable the NMI mechanism for CGA emulation?*/ + uint8_t rom_paged; /* Is ROM paged in at 0xC1800? */ - uint8_t crtc_value; /* Value to return from a CRTC register read */ + uint8_t crtc_value; /* Value to return from a CRTC register read */ - uint8_t sigmastat, /* Status register [0x2DA] */ - fake_stat; /* see sigma_in() for comment */ + uint8_t sigmastat, /* Status register [0x2DA] */ + fake_stat; /* see sigma_in() for comment */ - uint8_t sigmamode; /* Mode control register [0x2D8] */ + uint8_t sigmamode; /* Mode control register [0x2D8] */ uint16_t ma, maback; - int crtcreg; /* CRTC: Real selected register */ + int crtcreg; /* CRTC: Real selected register */ int linepos, displine; int sc, vc; @@ -173,376 +171,368 @@ typedef struct sigma_t pc_timer_t timer; uint8_t *vram; - uint8_t bram[2048]; + uint8_t bram[2048]; uint8_t palette[16]; int plane; int revision; + int fullchange; } sigma_t; #define COMPOSITE_OLD 0 #define COMPOSITE_NEW 1 -static uint8_t 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 uint8_t 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 video_timings_t timing_sigma = {VIDEO_ISA, 8, 16, 32, 8, 16, 32}; +static video_timings_t timing_sigma = { .type = VIDEO_ISA, .write_b = 8, .write_w = 16, .write_l = 32, .read_b = 8, .read_w = 16, .read_l = 32 }; - -static void sigma_recalctimings(sigma_t *cga); +static void sigma_recalctimings(sigma_t *cga); static void -sigma_out(uint16_t addr, uint8_t val, void *p) +sigma_out(uint16_t addr, uint8_t val, void *priv) { - sigma_t *sigma = (sigma_t *)p; - uint8_t old; + sigma_t *sigma = (sigma_t *) priv; + uint8_t old; if (addr >= 0x3D0 && addr < 0x3E0) { - sigma->lastport = addr & 0x0F; - sigma->lastwrite = val; - /* If set to NMI on video I/O... */ - if (sigma->enable_nmi && (sigma->sigma_ctl & CTL_NMI)) { - sigma->lastport |= 0x80; /* Card raised NMI */ - nmi = 1; - } - /* For CRTC emulation, the card BIOS sets the value to be - * read from port 0x3D1 like this */ - if (addr == 0x3D1) - sigma->crtc_value = val; - } else switch (addr) { - case 0x2D0: - case 0x2D2: - case 0x2D4: - case 0x2D6: - sigma->crtcreg = val & 31; - return; - case 0x2D1: - case 0x2D3: - case 0x2D5: - case 0x2D7: - old = sigma->crtc[sigma->crtcreg]; - sigma->crtc[sigma->crtcreg] = val & crtcmask[sigma->crtcreg]; - if (old != val) { - if (sigma->crtcreg < 0xe || sigma->crtcreg > 0x10) { - fullchange = changeframecount; - sigma_recalctimings(sigma); - } - } - return; + sigma->lastport = addr & 0x0F; + sigma->lastwrite = val; + /* If set to NMI on video I/O... */ + if (sigma->enable_nmi && (sigma->sigma_ctl & CTL_NMI)) { + sigma->lastport |= 0x80; /* Card raised NMI */ + nmi_raise(); + } + /* For CRTC emulation, the card BIOS sets the value to be + * read from port 0x3D1 like this */ + if (addr == 0x3D1) + sigma->crtc_value = val; + } else + switch (addr) { + case 0x2D0: + case 0x2D2: + case 0x2D4: + case 0x2D6: + sigma->crtcreg = val & 31; + return; + case 0x2D1: + case 0x2D3: + case 0x2D5: + case 0x2D7: + old = sigma->crtc[sigma->crtcreg]; + sigma->crtc[sigma->crtcreg] = val & crtcmask[sigma->crtcreg]; + if (old != val) { + if (sigma->crtcreg < 0xe || sigma->crtcreg > 0x10) { + sigma->fullchange = changeframecount; + sigma_recalctimings(sigma); + } + } + return; - case 0x2D8: - sigma->sigmamode = val; - return; - case 0x2D9: - sigma->sigma_ctl = val; - return; - case 0x2DB: - sigma->lastport &= 0x7F; - return; - case 0x2DC: /* Reset NMI */ - nmi = 0; - sigma->lastport &= 0x7F; - return; - case 0x2DD: /* Page in RAM at 0xC1800 */ - if (sigma->rom_paged != 0) - mmu_invalidate(0xC0000); - sigma->rom_paged = 0x00; - return; + case 0x2D8: + sigma->sigmamode = val; + return; + case 0x2D9: + sigma->sigma_ctl = val; + return; + case 0x2DB: + sigma->lastport &= 0x7F; + return; + case 0x2DC: /* Reset NMI */ + nmi = 0; + sigma->lastport &= 0x7F; + return; + case 0x2DD: /* Page in RAM at 0xC1800 */ + if (sigma->rom_paged != 0) + flushmmucache_nopc(); + sigma->rom_paged = 0x00; + return; - case 0x2DE: - if (sigma->sigma_ctl & CTL_PALETTE) - sigma->palette[val >> 4] = (val & 0x0F) ^ 0x0F; - else - sigma->plane = val & 3; - return; - } + case 0x2DE: + if (sigma->sigma_ctl & CTL_PALETTE) + sigma->palette[val >> 4] = (val & 0x0F) ^ 0x0F; + else + sigma->plane = val & 3; + return; + + default: + break; + } } - static uint8_t -sigma_in(uint16_t addr, void *p) +sigma_in(uint16_t addr, void *priv) { - uint8_t result = 0xFF; - sigma_t *sigma = (sigma_t *)p; + uint8_t result = 0xFF; + sigma_t *sigma = (sigma_t *) priv; switch (addr) { - case 0x2D0: - case 0x2D2: - case 0x2D4: - case 0x2D6: - result = sigma->crtcreg; - break; - case 0x2D1: - case 0x2D3: - case 0x2D5: - case 0x2D7: - result = sigma->crtc[sigma->crtcreg & 0x1F]; - break; - case 0x2DA: - result = (sigma->sigma_ctl & 0xE0) | - (sigma->sigmastat & 0x1F); - break; - case 0x2DB: - result = sigma->lastwrite; /* Value that triggered NMI */ - break; - case 0x2DC: - result = sigma->lastport; /* Port that triggered NMI */ - break; - case 0x2DD: /* Page in ROM at 0xC1800 */ - result = (sigma->rom_paged ? 0x80 : 0); - if (sigma->rom_paged != 0x80) - mmu_invalidate(0xC0000); - sigma->rom_paged = 0x80; - break; - case 0x3D1: - case 0x3D3: - case 0x3D5: - case 0x3D7: - result = sigma->crtc_value; - break; - /* For CGA compatibility we have to return something palatable on this port. - On a real card this functionality can be turned on or off with SW1/6 */ - case 0x3DA: - if (sigma->sigmamode & MODE_ENABLE) { - result = sigma->sigmastat & 0x07; - if (sigma->sigmastat & STATUS_RETR_V) - result |= 0x08; - } else { - /* - * The card is not running yet, and someone - * (probably the system BIOS) is trying to - * read our status in CGA mode. - * - * One of the systems that do this, is the - * DTK XT (PIM-10TB-Z board) with ERSO 2.42 - * BIOS. If this test fails (i.e. it doesnt - * see valid HS and VS bits alternate) it - * will generate lots of annoying beeps.. - * - * So, the trick here is to just send it - * some alternating bits, making it think - * the CGA circuitry is operational. - */ - sigma->fake_stat ^= (0x08 | 0x01); - result = sigma->fake_stat; - } - break; + case 0x2D0: + case 0x2D2: + case 0x2D4: + case 0x2D6: + result = sigma->crtcreg; + break; + case 0x2D1: + case 0x2D3: + case 0x2D5: + case 0x2D7: + result = sigma->crtc[sigma->crtcreg & 0x1F]; + break; + case 0x2DA: + result = (sigma->sigma_ctl & 0xE0) | (sigma->sigmastat & 0x1F); + break; + case 0x2DB: + result = sigma->lastwrite; /* Value that triggered NMI */ + break; + case 0x2DC: + result = sigma->lastport; /* Port that triggered NMI */ + break; + case 0x2DD: /* Page in ROM at 0xC1800 */ + result = (sigma->rom_paged ? 0x80 : 0); + if (sigma->rom_paged != 0x80) + flushmmucache_nopc(); + sigma->rom_paged = 0x80; + break; + case 0x3D1: + case 0x3D3: + case 0x3D5: + case 0x3D7: + result = sigma->crtc_value; + break; + /* For CGA compatibility we have to return something palatable on this port. + On a real card this functionality can be turned on or off with SW1/6 */ + case 0x3DA: + if (sigma->sigmamode & MODE_ENABLE) { + result = sigma->sigmastat & 0x07; + if (sigma->sigmastat & STATUS_RETR_V) + result |= 0x08; + } else { + /* + * The card is not running yet, and someone + * (probably the system BIOS) is trying to + * read our status in CGA mode. + * + * One of the systems that do this, is the + * DTK XT (PIM-10TB-Z board) with ERSO 2.42 + * BIOS. If this test fails (i.e. it doesnt + * see valid HS and VS bits alternate) it + * will generate lots of annoying beeps.. + * + * So, the trick here is to just send it + * some alternating bits, making it think + * the CGA circuitry is operational. + */ + sigma->fake_stat ^= (0x08 | 0x01); + result = sigma->fake_stat; + } + break; + + default: + break; } return result; } - static void -sigma_write(uint32_t addr, uint8_t val, void *p) +sigma_write(uint32_t addr, uint8_t val, void *priv) { - sigma_t *sigma = (sigma_t *)p; + sigma_t *sigma = (sigma_t *) priv; sigma->vram[sigma->plane * 0x8000 + (addr & 0x7fff)] = val; cycles -= 4; } - static uint8_t -sigma_read(uint32_t addr, void *p) +sigma_read(uint32_t addr, void *priv) { - sigma_t *sigma = (sigma_t *)p; + const sigma_t *sigma = (sigma_t *) priv; cycles -= 4; + return sigma->vram[sigma->plane * 0x8000 + (addr & 0x7fff)]; } - static void -sigma_bwrite(uint32_t addr, uint8_t val, void *p) +sigma_bwrite(uint32_t addr, uint8_t val, void *priv) { - sigma_t *sigma = (sigma_t *)p; + sigma_t *sigma = (sigma_t *) priv; addr &= 0x3FFF; if ((addr < 0x1800) || sigma->rom_paged || (addr >= 0x2000)) - ; + ; else - sigma->bram[addr & 0x7FF] = val; + sigma->bram[addr & 0x7FF] = val; } - static uint8_t -sigma_bread(uint32_t addr, void *p) +sigma_bread(uint32_t addr, void *priv) { - sigma_t *sigma = (sigma_t *)p; - uint8_t result; + const sigma_t *sigma = (sigma_t *) priv; + uint8_t result; addr &= 0x3FFF; if (addr >= 0x2000) - return 0xFF; + return 0xFF; if (addr < 0x1800 || sigma->rom_paged) - result = sigma->bios_rom.rom[addr & 0x1FFF]; + result = sigma->bios_rom.rom[addr & 0x1FFF]; else - result = sigma->bram[addr & 0x7FF]; + result = sigma->bram[addr & 0x7FF]; return result; } - static void sigma_recalctimings(sigma_t *sigma) { double disptime; - double _dispontime, _dispofftime; + double _dispontime; + double _dispofftime; if (sigma->sigmamode & MODE_80COLS) { - disptime = (sigma->crtc[0] + 1) << 1; - _dispontime = (sigma->crtc[1]) << 1; + disptime = (sigma->crtc[0] + 1) << 1; + _dispontime = (sigma->crtc[1]) << 1; } else { - disptime = (sigma->crtc[0] + 1) << 2; - _dispontime = sigma->crtc[1] << 2; + disptime = (sigma->crtc[0] + 1) << 2; + _dispontime = sigma->crtc[1] << 2; } _dispofftime = disptime - _dispontime; _dispontime *= CGACONST; _dispofftime *= CGACONST; - sigma->dispontime = (uint64_t)(_dispontime); - sigma->dispofftime = (uint64_t)(_dispofftime); + sigma->dispontime = (uint64_t) (_dispontime); + sigma->dispofftime = (uint64_t) (_dispofftime); } - /* Render a line in 80-column text mode */ -static void sigma_text80(sigma_t *sigma) +static void +sigma_text80(sigma_t *sigma) { - int x, c; - uint8_t chr, attr; - uint16_t ca = (sigma->crtc[15] | (sigma->crtc[14] << 8)); - uint16_t ma = ((sigma->ma & 0x3FFF) << 1); - int drawcursor; - uint32_t cols[4]; - uint8_t *vram = sigma->vram + (ma << 1); + uint8_t chr; + uint8_t attr; + uint16_t ca = (sigma->crtc[15] | (sigma->crtc[14] << 8)); + uint16_t ma = ((sigma->ma & 0x3FFF) << 1); + int drawcursor; + uint32_t cols[4]; + const uint8_t *vram = sigma->vram + (ma << 1); ca = ca << 1; if (sigma->sigma_ctl & CTL_CURSOR) - ++ca; + ++ca; ca &= 0x3fff; /* The Sigma 400 seems to use screen widths stated in words (40 for 80-column, 20 for 40-column) */ - for (x = 0; x < (sigma->crtc[1] << 1); x++) { - chr = vram[x << 1]; - attr = vram[(x << 1) + 1]; - drawcursor = ((ma == ca) && sigma->con && sigma->cursoron); + for (uint32_t x = 0; x < (sigma->crtc[1] << 1); x++) { + chr = vram[x << 1]; + attr = vram[(x << 1) + 1]; + drawcursor = ((ma == ca) && sigma->con && sigma->cursoron); - if (!(sigma->sigmamode & MODE_NOBLINK)) { - cols[1] = (attr & 15) | 16; - cols[0] = ((attr >> 4) & 7) | 16; - if ((sigma->cgablink & 8) && (attr & 0x80) && !sigma->drawcursor) - cols[1] = cols[0]; - } else { /* No blink */ - cols[1] = (attr & 15) | 16; - cols[0] = (attr >> 4) | 16; - } + if (!(sigma->sigmamode & MODE_NOBLINK)) { + cols[1] = (attr & 15) | 16; + cols[0] = ((attr >> 4) & 7) | 16; + if ((sigma->cgablink & 8) && (attr & 0x80) && !sigma->drawcursor) + cols[1] = cols[0]; + } else { /* No blink */ + cols[1] = (attr & 15) | 16; + cols[0] = (attr >> 4) | 16; + } - if (drawcursor) { - for (c = 0; c < 8; c++) { - if (sigma->sigmamode & MODE_FONT16) - buffer32->line[sigma->displine][(x << 3) + c + 8] = cols[(fontdatm[chr][sigma->sc & 15] & (1 << (c ^ 7))) ? 1 : 0] ^ 0xf; - else - buffer32->line[sigma->displine][(x << 3) + c + 8] = cols[(fontdat[chr][sigma->sc & 7] & (1 << (c ^ 7))) ? 1 : 0] ^ 0xf; - } - } else { - for (c = 0; c < 8; c++) { - if (sigma->sigmamode & MODE_FONT16) - buffer32->line[sigma->displine][(x << 3) + c + 8] = cols[(fontdatm[chr][sigma->sc & 15] & (1 << (c ^ 7))) ? 1 : 0]; - else - buffer32->line[sigma->displine][(x << 3) + c + 8] = cols[(fontdat[chr][sigma->sc & 7] & (1 << (c ^ 7))) ? 1 : 0]; - } - } - ++ma; + if (drawcursor) { + for (uint8_t c = 0; c < 8; c++) { + if (sigma->sigmamode & MODE_FONT16) + buffer32->line[sigma->displine][(x << 3) + c + 8] = cols[(fontdatm[chr][sigma->sc & 15] & (1 << (c ^ 7))) ? 1 : 0] ^ 0xf; + else + buffer32->line[sigma->displine][(x << 3) + c + 8] = cols[(fontdat[chr][sigma->sc & 7] & (1 << (c ^ 7))) ? 1 : 0] ^ 0xf; + } + } else { + for (uint8_t c = 0; c < 8; c++) { + if (sigma->sigmamode & MODE_FONT16) + buffer32->line[sigma->displine][(x << 3) + c + 8] = cols[(fontdatm[chr][sigma->sc & 15] & (1 << (c ^ 7))) ? 1 : 0]; + else + buffer32->line[sigma->displine][(x << 3) + c + 8] = cols[(fontdat[chr][sigma->sc & 7] & (1 << (c ^ 7))) ? 1 : 0]; + } + } + ++ma; } sigma->ma += sigma->crtc[1]; } - /* Render a line in 40-column text mode */ static void sigma_text40(sigma_t *sigma) { - int x, c; - uint8_t chr, attr; - uint16_t ca = (sigma->crtc[15] | (sigma->crtc[14] << 8)); - uint16_t ma = ((sigma->ma & 0x3FFF) << 1); - int drawcursor; - uint32_t cols[4]; - uint8_t *vram = sigma->vram + ((ma << 1) & 0x3FFF); + uint8_t chr; + uint8_t attr; + uint16_t ca = (sigma->crtc[15] | (sigma->crtc[14] << 8)); + uint16_t ma = ((sigma->ma & 0x3FFF) << 1); + int drawcursor; + uint32_t cols[4]; + const uint8_t *vram = sigma->vram + ((ma << 1) & 0x3FFF); ca = ca << 1; if (sigma->sigma_ctl & CTL_CURSOR) - ++ca; + ++ca; ca &= 0x3fff; /* The Sigma 400 seems to use screen widths stated in words (40 for 80-column, 20 for 40-column) */ - for (x = 0; x < (sigma->crtc[1] << 1); x++) { - chr = vram[x << 1]; - attr = vram[(x << 1) + 1]; - drawcursor = ((ma == ca) && sigma->con && sigma->cursoron); + for (uint32_t x = 0; x < (sigma->crtc[1] << 1); x++) { + chr = vram[x << 1]; + attr = vram[(x << 1) + 1]; + drawcursor = ((ma == ca) && sigma->con && sigma->cursoron); - if (!(sigma->sigmamode & MODE_NOBLINK)) { - cols[1] = (attr & 15) | 16; - cols[0] = ((attr >> 4) & 7) | 16; - if ((sigma->cgablink & 8) && (attr & 0x80) && !sigma->drawcursor) - cols[1] = cols[0]; - } else { /* No blink */ - cols[1] = (attr & 15) | 16; - cols[0] = (attr >> 4) | 16; - } + if (!(sigma->sigmamode & MODE_NOBLINK)) { + cols[1] = (attr & 15) | 16; + cols[0] = ((attr >> 4) & 7) | 16; + if ((sigma->cgablink & 8) && (attr & 0x80) && !sigma->drawcursor) + cols[1] = cols[0]; + } else { /* No blink */ + cols[1] = (attr & 15) | 16; + cols[0] = (attr >> 4) | 16; + } - if (drawcursor) { - for (c = 0; c < 8; c++) { - buffer32->line[sigma->displine][(x << 4) + 2*c + 8] = - buffer32->line[sigma->displine][(x << 4) + 2*c + 9] = cols[(fontdatm[chr][sigma->sc & 15] & (1 << (c ^ 7))) ? 1 : 0] ^ 0xf; - } - } else { - for (c = 0; c < 8; c++) { - buffer32->line[sigma->displine][(x << 4) + 2*c + 8] = - buffer32->line[sigma->displine][(x << 4) + 2*c + 9] = cols[(fontdatm[chr][sigma->sc & 15] & (1 << (c ^ 7))) ? 1 : 0]; - } - } - ma++; + if (drawcursor) { + for (uint8_t c = 0; c < 8; c++) { + buffer32->line[sigma->displine][(x << 4) + 2 * c + 8] = buffer32->line[sigma->displine][(x << 4) + 2 * c + 9] = cols[(fontdatm[chr][sigma->sc & 15] & (1 << (c ^ 7))) ? 1 : 0] ^ 0xf; + } + } else { + for (uint8_t c = 0; c < 8; c++) { + buffer32->line[sigma->displine][(x << 4) + 2 * c + 8] = buffer32->line[sigma->displine][(x << 4) + 2 * c + 9] = cols[(fontdatm[chr][sigma->sc & 15] & (1 << (c ^ 7))) ? 1 : 0]; + } + } + ma++; } sigma->ma += sigma->crtc[1]; } - /* Draw a line in the 640x400 graphics mode */ static void sigma_gfx400(sigma_t *sigma) { - int x; - unsigned char *vram = &sigma->vram[((sigma->ma << 1) & 0x1FFF) + - (sigma->sc & 3) * 0x2000]; - uint8_t plane[4]; - uint8_t mask, col, c; + const uint8_t *vram = &sigma->vram[((sigma->ma << 1) & 0x1FFF) + (sigma->sc & 3) * 0x2000]; + uint8_t plane[4]; + uint8_t col; - for (x = 0; x < (sigma->crtc[1] << 1); x++) { - plane[0] = vram[x]; - plane[1] = vram[0x8000 + x]; - plane[2] = vram[0x10000 + x]; - plane[3] = vram[0x18000 + x]; + for (uint32_t x = 0; x < (sigma->crtc[1] << 1); x++) { + plane[0] = vram[x]; + plane[1] = vram[0x8000 + x]; + plane[2] = vram[0x10000 + x]; + plane[3] = vram[0x18000 + x]; - for (c = 0, mask = 0x80; c < 8; c++, mask >>= 1) { - col = ((plane[3] & mask) ? 8 : 0) | - ((plane[2] & mask) ? 4 : 0) | - ((plane[1] & mask) ? 2 : 0) | - ((plane[0] & mask) ? 1 : 0); - col |= 16; - buffer32->line[sigma->displine][(x << 3) + c + 8] = col; - } - if (x & 1) - ++sigma->ma; + for (uint8_t c = 0, mask = 0x80; c < 8; c++, mask >>= 1) { + col = ((plane[3] & mask) ? 8 : 0) | ((plane[2] & mask) ? 4 : 0) | ((plane[1] & mask) ? 2 : 0) | ((plane[0] & mask) ? 1 : 0); + col |= 16; + buffer32->line[sigma->displine][(x << 3) + c + 8] = col; + } + if (x & 1) + ++sigma->ma; } } @@ -554,258 +544,248 @@ sigma_gfx400(sigma_t *sigma) static void sigma_gfx200(sigma_t *sigma) { - int x; - unsigned char *vram = &sigma->vram[((sigma->ma << 1) & 0x1FFF) + - (sigma->sc & 2) * 0x1000]; - uint8_t plane[4]; - uint8_t mask, col, c; + const uint8_t *vram = &sigma->vram[((sigma->ma << 1) & 0x1FFF) + (sigma->sc & 2) * 0x1000]; + uint8_t plane[4]; + uint8_t col; - for (x = 0; x < (sigma->crtc[1] << 1); x++) { - plane[0] = vram[x]; - plane[1] = vram[0x8000 + x]; - plane[2] = vram[0x10000 + x]; - plane[3] = vram[0x18000 + x]; + for (uint32_t x = 0; x < (sigma->crtc[1] << 1); x++) { + plane[0] = vram[x]; + plane[1] = vram[0x8000 + x]; + plane[2] = vram[0x10000 + x]; + plane[3] = vram[0x18000 + x]; - for (c = 0, mask = 0x80; c < 8; c++, mask >>= 1) { - col = ((plane[3] & mask) ? 8 : 0) | - ((plane[2] & mask) ? 4 : 0) | - ((plane[1] & mask) ? 2 : 0) | - ((plane[0] & mask) ? 1 : 0); - col |= 16; - buffer32->line[sigma->displine][(x << 3) + c + 8] = col; - } + for (uint8_t c = 0, mask = 0x80; c < 8; c++, mask >>= 1) { + col = ((plane[3] & mask) ? 8 : 0) | ((plane[2] & mask) ? 4 : 0) | ((plane[1] & mask) ? 2 : 0) | ((plane[0] & mask) ? 1 : 0); + col |= 16; + buffer32->line[sigma->displine][(x << 3) + c + 8] = col; + } - if (x & 1) - ++sigma->ma; + if (x & 1) + ++sigma->ma; } } - /* Draw a line in the 320x200 graphics mode */ static void sigma_gfx4col(sigma_t *sigma) { - int x; - unsigned char *vram = &sigma->vram[((sigma->ma << 1) & 0x1FFF) + - (sigma->sc & 2) * 0x1000]; - uint8_t plane[4]; - uint8_t mask, col, c; + const uint8_t *vram = &sigma->vram[((sigma->ma << 1) & 0x1FFF) + (sigma->sc & 2) * 0x1000]; + uint8_t plane[4]; + uint8_t mask; + uint8_t col; - for (x = 0; x < (sigma->crtc[1] << 1); x++) { - plane[0] = vram[x]; - plane[1] = vram[0x8000 + x]; - plane[2] = vram[0x10000 + x]; - plane[3] = vram[0x18000 + x]; + for (uint32_t x = 0; x < (sigma->crtc[1] << 1); x++) { + plane[0] = vram[x]; + plane[1] = vram[0x8000 + x]; + plane[2] = vram[0x10000 + x]; + plane[3] = vram[0x18000 + x]; - mask = 0x80; - for (c = 0; c < 4; c++) { - col = ((plane[3] & mask) ? 2 : 0) | - ((plane[2] & mask) ? 1 : 0); - mask = mask >> 1; - col |= ((plane[3] & mask) ? 8 : 0) | - ((plane[2] & mask) ? 4 : 0); - col |= 16; - mask = mask >> 1; + mask = 0x80; + for (uint8_t c = 0; c < 4; c++) { + col = ((plane[3] & mask) ? 2 : 0) | ((plane[2] & mask) ? 1 : 0); + mask = mask >> 1; + col |= ((plane[3] & mask) ? 8 : 0) | ((plane[2] & mask) ? 4 : 0); + col |= 16; + mask = mask >> 1; - buffer32->line[sigma->displine][(x << 3) + (c << 1) + 8] = - buffer32->line[sigma->displine][(x << 3) + (c << 1) + 9] = col; - } + buffer32->line[sigma->displine][(x << 3) + (c << 1) + 8] = buffer32->line[sigma->displine][(x << 3) + (c << 1) + 9] = col; + } - if (x & 1) - ++sigma->ma; + if (x & 1) + ++sigma->ma; } } - static void -sigma_poll(void *p) +sigma_poll(void *priv) { - sigma_t *sigma = (sigma_t *)p; - int x, c; - int oldvc; + sigma_t *sigma = (sigma_t *) priv; + int x; + int c; + int oldvc; uint32_t cols[4]; - int oldsc; + int oldsc; if (!sigma->linepos) { - timer_advance_u64(&sigma->timer, sigma->dispofftime); - sigma->sigmastat |= STATUS_RETR_H; - sigma->linepos = 1; - oldsc = sigma->sc; - if ((sigma->crtc[8] & 3) == 3) - sigma->sc = ((sigma->sc << 1) + sigma->oddeven) & 7; - if (sigma->cgadispon) { - if (sigma->displine < sigma->firstline) { - sigma->firstline = sigma->displine; - video_wait_for_buffer(); - } - sigma->lastline = sigma->displine; + timer_advance_u64(&sigma->timer, sigma->dispofftime); + sigma->sigmastat |= STATUS_RETR_H; + sigma->linepos = 1; + oldsc = sigma->sc; + if ((sigma->crtc[8] & 3) == 3) + sigma->sc = ((sigma->sc << 1) + sigma->oddeven) & 7; + if (sigma->cgadispon) { + if (sigma->displine < sigma->firstline) { + sigma->firstline = sigma->displine; + video_wait_for_buffer(); + } + sigma->lastline = sigma->displine; - cols[0] = 16; - /* Left overscan */ - for (c = 0; c < 8; c++) { - buffer32->line[sigma->displine][c] = cols[0]; - if (sigma->sigmamode & MODE_80COLS) - buffer32->line[sigma->displine][c + (sigma->crtc[1] << 4) + 8] = cols[0]; - else - buffer32->line[sigma->displine][c + (sigma->crtc[1] << 5) + 8] = cols[0]; - } - if (sigma->sigmamode & MODE_GRAPHICS) { - if (sigma->sigmamode & MODE_640x400) - sigma_gfx400(sigma); - else if (sigma->sigmamode & MODE_HRGFX) - sigma_gfx200(sigma); - else - sigma_gfx4col(sigma); - } else { /* Text modes */ - if (sigma->sigmamode & MODE_80COLS) - sigma_text80(sigma); - else - sigma_text40(sigma); - } - } else { - cols[0] = 16; - if (sigma->sigmamode & MODE_80COLS) - hline(buffer32, 0, sigma->displine, (sigma->crtc[1] << 4) + 16, cols[0]); - else - hline(buffer32, 0, sigma->displine, (sigma->crtc[1] << 5) + 16, cols[0]); - } + cols[0] = 16; + /* Left overscan */ + for (c = 0; c < 8; c++) { + buffer32->line[sigma->displine][c] = cols[0]; + if (sigma->sigmamode & MODE_80COLS) + buffer32->line[sigma->displine][c + (sigma->crtc[1] << 4) + 8] = cols[0]; + else + buffer32->line[sigma->displine][c + (sigma->crtc[1] << 5) + 8] = cols[0]; + } + if (sigma->sigmamode & MODE_GRAPHICS) { + if (sigma->sigmamode & MODE_640x400) + sigma_gfx400(sigma); + else if (sigma->sigmamode & MODE_HRGFX) + sigma_gfx200(sigma); + else + sigma_gfx4col(sigma); + } else { /* Text modes */ + if (sigma->sigmamode & MODE_80COLS) + sigma_text80(sigma); + else + sigma_text40(sigma); + } + } else { + cols[0] = 16; + if (sigma->sigmamode & MODE_80COLS) + hline(buffer32, 0, sigma->displine, (sigma->crtc[1] << 4) + 16, cols[0]); + else + hline(buffer32, 0, sigma->displine, (sigma->crtc[1] << 5) + 16, cols[0]); + } - if (sigma->sigmamode & MODE_80COLS) - x = (sigma->crtc[1] << 4) + 16; - else - x = (sigma->crtc[1] << 5) + 16; + if (sigma->sigmamode & MODE_80COLS) + x = (sigma->crtc[1] << 4) + 16; + else + x = (sigma->crtc[1] << 5) + 16; - for (c = 0; c < x; c++) - buffer32->line[sigma->displine][c] = sigma->palette[buffer32->line[sigma->displine][c] & 0xf] | 16; + for (c = 0; c < x; c++) + buffer32->line[sigma->displine][c] = sigma->palette[buffer32->line[sigma->displine][c] & 0xf] | 16; - sigma->sc = oldsc; - if (sigma->vc == sigma->crtc[7] && !sigma->sc) - sigma->sigmastat |= STATUS_RETR_V; - sigma->displine++; - if (sigma->displine >= 560) - sigma->displine = 0; + video_process_8(x, sigma->displine); + + sigma->sc = oldsc; + if (sigma->vc == sigma->crtc[7] && !sigma->sc) + sigma->sigmastat |= STATUS_RETR_V; + sigma->displine++; + if (sigma->displine >= 560) + sigma->displine = 0; } else { - timer_advance_u64(&sigma->timer, sigma->dispontime); - sigma->linepos = 0; - if (sigma->vsynctime) { - sigma->vsynctime--; - if (!sigma->vsynctime) - sigma->sigmastat &= ~STATUS_RETR_V; - } - if (sigma->sc == (sigma->crtc[11] & 31) || - ((sigma->crtc[8] & 3) == 3 && sigma->sc == ((sigma->crtc[11] & 31) >> 1))) { - sigma->con = 0; - sigma->coff = 1; - } - if ((sigma->crtc[8] & 3) == 3 && sigma->sc == (sigma->crtc[9] >> 1)) - sigma->maback = sigma->ma; - if (sigma->vadj) { - sigma->sc++; - sigma->sc &= 31; - sigma->ma = sigma->maback; - sigma->vadj--; - if (!sigma->vadj) { - sigma->cgadispon = 1; - sigma->ma = sigma->maback = (sigma->crtc[13] | (sigma->crtc[12] << 8)) & 0x3fff; - sigma->sc = 0; - } - } else if (sigma->sc == sigma->crtc[9]) { - sigma->maback = sigma->ma; - sigma->sc = 0; - oldvc = sigma->vc; - sigma->vc++; - sigma->vc &= 127; + timer_advance_u64(&sigma->timer, sigma->dispontime); + sigma->linepos = 0; + if (sigma->vsynctime) { + sigma->vsynctime--; + if (!sigma->vsynctime) + sigma->sigmastat &= ~STATUS_RETR_V; + } + if (sigma->sc == (sigma->crtc[11] & 31) || ((sigma->crtc[8] & 3) == 3 && sigma->sc == ((sigma->crtc[11] & 31) >> 1))) { + sigma->con = 0; + sigma->coff = 1; + } + if ((sigma->crtc[8] & 3) == 3 && sigma->sc == (sigma->crtc[9] >> 1)) + sigma->maback = sigma->ma; + if (sigma->vadj) { + sigma->sc++; + sigma->sc &= 31; + sigma->ma = sigma->maback; + sigma->vadj--; + if (!sigma->vadj) { + sigma->cgadispon = 1; + sigma->ma = sigma->maback = (sigma->crtc[13] | (sigma->crtc[12] << 8)) & 0x3fff; + sigma->sc = 0; + } + } else if (sigma->sc == sigma->crtc[9]) { + sigma->maback = sigma->ma; + sigma->sc = 0; + oldvc = sigma->vc; + sigma->vc++; + sigma->vc &= 127; - if (sigma->vc == sigma->crtc[6]) - sigma->cgadispon = 0; + if (sigma->vc == sigma->crtc[6]) + sigma->cgadispon = 0; - if (oldvc == sigma->crtc[4]) { - sigma->vc = 0; - sigma->vadj = sigma->crtc[5]; - if (!sigma->vadj) sigma->cgadispon = 1; - if (!sigma->vadj) - sigma->ma = sigma->maback = (sigma->crtc[13] | (sigma->crtc[12] << 8)) & 0x3fff; - if ((sigma->crtc[10] & 0x60) == 0x20) - sigma->cursoron = 0; - else - sigma->cursoron = sigma->cgablink & 8; - } + if (oldvc == sigma->crtc[4]) { + sigma->vc = 0; + sigma->vadj = sigma->crtc[5]; + if (!sigma->vadj) + sigma->cgadispon = 1; + if (!sigma->vadj) + sigma->ma = sigma->maback = (sigma->crtc[13] | (sigma->crtc[12] << 8)) & 0x3fff; + if ((sigma->crtc[10] & 0x60) == 0x20) + sigma->cursoron = 0; + else + sigma->cursoron = sigma->cgablink & 8; + } - if (sigma->vc == sigma->crtc[7]) { - sigma->cgadispon = 0; - sigma->displine = 0; - sigma->vsynctime = 16; - if (sigma->crtc[7]) { - if (sigma->sigmamode & MODE_80COLS) - x = (sigma->crtc[1] << 4) + 16; - else - x = (sigma->crtc[1] << 5) + 16; - sigma->lastline++; - if ((x != xsize) || ((sigma->lastline - sigma->firstline) != ysize) || - video_force_resize_get()) { - xsize = x; - ysize = sigma->lastline - sigma->firstline; - if (xsize < 64) - xsize = 656; - if (ysize < 32) - ysize = 200; - if (ysize <= 250) - set_screen_size(xsize, (ysize << 1) + 16); - else - set_screen_size(xsize, ysize + 8); + if (sigma->vc == sigma->crtc[7]) { + sigma->cgadispon = 0; + sigma->displine = 0; + sigma->vsynctime = 16; + if (sigma->crtc[7]) { + if (sigma->sigmamode & MODE_80COLS) + x = (sigma->crtc[1] << 4) + 16; + else + x = (sigma->crtc[1] << 5) + 16; + sigma->lastline++; + if ((x != xsize) || ((sigma->lastline - sigma->firstline) != ysize) || video_force_resize_get()) { + xsize = x; + ysize = sigma->lastline - sigma->firstline; + if (xsize < 64) + xsize = 656; + if (ysize < 32) + ysize = 200; + if (ysize <= 250) + set_screen_size(xsize, (ysize << 1) + 16); + else + set_screen_size(xsize, ysize + 8); - if (video_force_resize_get()) - video_force_resize_set(0); - } + if (video_force_resize_get()) + video_force_resize_set(0); + } - video_blit_memtoscreen_8(0, sigma->firstline - 4, xsize, (sigma->lastline - sigma->firstline) + 8); - frames++; + video_blit_memtoscreen(0, sigma->firstline - 4, xsize, (sigma->lastline - sigma->firstline) + 8); + frames++; - video_res_x = xsize - 16; - video_res_y = ysize; - if (sigma->sigmamode & MODE_GRAPHICS) { - if (sigma->sigmamode & (MODE_HRGFX | MODE_640x400)) - video_bpp = 1; - else { - video_res_x /= 2; - video_bpp = 2; - } - } else if (sigma->sigmamode & MODE_80COLS) { - /* 80-column text */ - video_res_x /= 8; - video_res_y /= sigma->crtc[9] + 1; - video_bpp = 0; - } else { - /* 40-column text */ - video_res_x /= 16; - video_res_y /= sigma->crtc[9] + 1; - video_bpp = 0; - } - } - sigma->firstline = 1000; - sigma->lastline = 0; - sigma->cgablink++; - sigma->oddeven ^= 1; - } - } else { - sigma->sc++; - sigma->sc &= 31; - sigma->ma = sigma->maback; - } - if (sigma->cgadispon) - sigma->sigmastat &= ~STATUS_RETR_H; - if ((sigma->sc == (sigma->crtc[10] & 31) || - ((sigma->crtc[8] & 3) == 3 && sigma->sc == ((sigma->crtc[10] & 31) >> 1)))) - sigma->con = 1; + video_res_x = xsize - 16; + video_res_y = ysize; + if (sigma->sigmamode & MODE_GRAPHICS) { + if (sigma->sigmamode & (MODE_HRGFX | MODE_640x400)) + video_bpp = 1; + else { + video_res_x /= 2; + video_bpp = 2; + } + } else if (sigma->sigmamode & MODE_80COLS) { + /* 80-column text */ + video_res_x /= 8; + video_res_y /= sigma->crtc[9] + 1; + video_bpp = 0; + } else { + /* 40-column text */ + video_res_x /= 16; + video_res_y /= sigma->crtc[9] + 1; + video_bpp = 0; + } + } + sigma->firstline = 1000; + sigma->lastline = 0; + sigma->cgablink++; + sigma->oddeven ^= 1; + } + } else { + sigma->sc++; + sigma->sc &= 31; + sigma->ma = sigma->maback; + } + if (sigma->cgadispon) + sigma->sigmastat &= ~STATUS_RETR_H; + if (sigma->sc == (sigma->crtc[10] & 31) || ((sigma->crtc[8] & 3) == 3 && sigma->sc == ((sigma->crtc[10] & 31) >> 1))) + sigma->con = 1; } } - -static void -*sigma_init(const device_t *info) +static void * +sigma_init(UNUSED(const device_t *info)) { - int bios_addr; + int bios_addr; sigma_t *sigma = malloc(sizeof(sigma_t)); + memset(sigma, 0, sizeof(sigma_t)); bios_addr = device_get_config_hex20("bios_addr"); @@ -815,8 +795,8 @@ static void sigma->enable_nmi = device_get_config_int("enable_nmi"); loadfont(ROM_SIGMA_FONT, 7); - rom_init(&sigma->bios_rom, ROM_SIGMA_BIOS, bios_addr, 0x2000, - 0x1FFF, 0, MEM_MAPPING_EXTERNAL); + rom_init(&sigma->bios_rom, ROM_SIGMA_BIOS, bios_addr, 0x2000, + 0x1FFF, 0, MEM_MAPPING_EXTERNAL); /* The BIOS ROM is overlaid by RAM, so remove its default mapping and access it through sigma_bread() / sigma_bwrite() below */ mem_mapping_disable(&sigma->bios_rom.mapping); @@ -825,146 +805,168 @@ static void sigma->vram = malloc(0x8000 * 4); timer_add(&sigma->timer, sigma_poll, sigma, 1); - mem_mapping_add(&sigma->mapping, 0xb8000, 0x08000, - sigma_read, NULL, NULL, - sigma_write, NULL, NULL, - NULL, MEM_MAPPING_EXTERNAL, sigma); + mem_mapping_add(&sigma->mapping, 0xb8000, 0x08000, + sigma_read, NULL, NULL, + sigma_write, NULL, NULL, + NULL, MEM_MAPPING_EXTERNAL, sigma); mem_mapping_add(&sigma->bios_ram, bios_addr, 0x2000, - sigma_bread, NULL, NULL, - sigma_bwrite, NULL, NULL, - sigma->bios_rom.rom, MEM_MAPPING_EXTERNAL, sigma); - io_sethandler(0x03d0, 0x0010, - sigma_in, NULL, NULL, - sigma_out, NULL, NULL, sigma); - io_sethandler(0x02d0, 0x0010, - sigma_in, NULL, NULL, - sigma_out, NULL, NULL, sigma); + sigma_bread, NULL, NULL, + sigma_bwrite, NULL, NULL, + sigma->bios_rom.rom, MEM_MAPPING_EXTERNAL, sigma); + io_sethandler(0x03d0, 0x0010, + sigma_in, NULL, NULL, + sigma_out, NULL, NULL, sigma); + io_sethandler(0x02d0, 0x0010, + sigma_in, NULL, NULL, + sigma_out, NULL, NULL, sigma); /* Start with ROM paged in, BIOS RAM paged out */ sigma->rom_paged = 0x80; cga_palette = device_get_config_int("rgb_type") << 1; if (cga_palette > 6) - cga_palette = 0; + cga_palette = 0; cgapal_rebuild(); if (sigma->enable_nmi) - sigma->sigmastat = STATUS_LPEN_T; + sigma->sigmastat = STATUS_LPEN_T; return sigma; } - static int sigma_available(void) { - return((rom_present(ROM_SIGMA_FONT) && rom_present(ROM_SIGMA_BIOS))); + return (rom_present(ROM_SIGMA_FONT) && rom_present(ROM_SIGMA_BIOS)); } - static void -sigma_close(void *p) +sigma_close(void *priv) { - sigma_t *sigma = (sigma_t *)p; + sigma_t *sigma = (sigma_t *) priv; free(sigma->vram); free(sigma); } - void -sigma_speed_changed(void *p) +sigma_speed_changed(void *priv) { - sigma_t *sigma = (sigma_t *)p; + sigma_t *sigma = (sigma_t *) priv; sigma_recalctimings(sigma); } - -device_config_t sigma_config[] = -{ +device_config_t sigma_config[] = { + // clang-format off { - "rgb_type", "RGB type", CONFIG_SELECTION, "", 0, "", { 0 }, - { - { - "Color", 0 - }, - { - "Green Monochrome", 1 - }, - { - "Amber Monochrome", 2 - }, - { - "Gray Monochrome", 3 - }, - { - "Color (no brown)", 4 - }, - { - "" - } - } + .name = "rgb_type", + .description = "RGB type", + .type = CONFIG_SELECTION, + .default_int = 0, + .selection = { + { + .description = "Color", + .value = 0 + }, + { + .description = "Green Monochrome", + .value = 1 + }, + { + .description = "Amber Monochrome", + .value = 2 + }, + { + .description = "Gray Monochrome", + .value = 3 + }, + { + .description = "Color (no brown)", + .value = 4 + }, + { + .description = "" + } + } }, { - "enable_nmi", "Enable NMI for CGA emulation", CONFIG_BINARY, "", 1 + .name = "enable_nmi", + .description = "Enable NMI for CGA emulation", + .type = CONFIG_BINARY, + .default_int = 1 }, { - "bios_addr", "BIOS Address", CONFIG_HEX20, "", 0xc0000, "", { 0 }, - { - { - "C000H", 0xc0000 - }, - { - "C800H", 0xc8000 - }, - { - "CC00H", 0xcc000 - }, - { - "D000H", 0xd0000 - }, - { - "D400H", 0xd4000 - }, - { - "D800H", 0xd8000 - }, - { - "DC00H", 0xdc000 - }, - { - "E000H", 0xe0000 - }, - { - "E400H", 0xe4000 - }, - { - "E800H", 0xe8000 - }, - { - "EC00H", 0xec000 - }, - { - "" - } - }, + .name = "bios_addr", + .description = "BIOS Address", + .type = CONFIG_HEX20, + .default_int = 0xc0000, + .selection = { + { + .description = "C000H", + .value = 0xc0000 + }, + { + .description = "C800H", + .value = 0xc8000 + }, + { + .description = "CC00H", + .value = 0xcc000 + }, + { + .description = "D000H", + .value = 0xd0000 + }, + { + .description = "D400H", + .value = 0xd4000 + }, + { + .description = "D800H", + .value = 0xd8000 + }, + { + .description = "DC00H", + .value = 0xdc000 + }, + { + .description = "E000H", + .value = 0xe0000 + }, + { + .description = "E400H", + .value = 0xe4000 + }, + { + .description = "E800H", + .value = 0xe8000 + }, + { + .description = "EC00H", + .value = 0xec000 + }, + { + .description = "" + } + }, }, { - "", "", -1 + .type = CONFIG_END } + // clang-format on }; -const device_t sigma_device = -{ - "Sigma Color 400", - "sigma400", - DEVICE_ISA, 0, - sigma_init, - sigma_close, - NULL, - { sigma_available }, - sigma_speed_changed, - NULL, - sigma_config +const device_t sigma_device = { + .name = "Sigma Color 400", + .internal_name = "sigma400", + .flags = DEVICE_ISA, + .local = 0, + .init = sigma_init, + .close = sigma_close, + .reset = NULL, + { .available = sigma_available }, + .speed_changed = sigma_speed_changed, + .force_redraw = NULL, + .config = sigma_config }; diff --git a/src/video/vid_stg_ramdac.c b/src/video/vid_stg_ramdac.c index 9f216056b..187139b3b 100644 --- a/src/video/vid_stg_ramdac.c +++ b/src/video/vid_stg_ramdac.c @@ -1,20 +1,20 @@ /* - * 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. + * 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. + * This file is part of the 86Box distribution. * - * STG1702 true colour RAMDAC emulation. + * STG1702 true colour RAMDAC emulation. * * * - * Authors: Sarah Walker, - * Miran Grca, + * Authors: Sarah Walker, + * Miran Grca, * - * Copyright 2008-2018 Sarah Walker. - * Copyright 2016-2018 Miran Grca. + * Copyright 2008-2018 Sarah Walker. + * Copyright 2016-2018 Miran Grca. */ #include #include @@ -27,208 +27,218 @@ #include <86box/timer.h> #include <86box/video.h> #include <86box/vid_svga.h> +#include <86box/plat_unused.h> - -typedef struct stg_ramdac_t -{ - int magic_count, index; +typedef struct stg_ramdac_t { + int magic_count, index; uint8_t regs[256]; uint8_t command; } stg_ramdac_t; - - -static int stg_state_read[2][8] = {{1,2,3,4,0,0,0,0}, {1,2,3,4,5,6,7,7}}; -static int stg_state_write[8] = {0,0,0,0,0,6,7,7}; - +static int stg_state_read[2][8] = { + {1, 2, 3, 4, 0, 0, 0, 0}, + { 1, 2, 3, 4, 5, 6, 7, 7} +}; +static int stg_state_write[8] = { 0, 0, 0, 0, 0, 6, 7, 7 }; void stg_ramdac_set_bpp(svga_t *svga, stg_ramdac_t *ramdac) { if (ramdac->command & 0x8) { switch (ramdac->regs[3]) { - case 0: - case 5: - case 7: - default: - svga->bpp = 8; - break; - case 1: - case 2: - case 8: - svga->bpp = 15; - break; - case 3: - case 6: - svga->bpp = 16; - break; - case 4: - case 9: - svga->bpp = 24; - break; - } + default: + case 0: + case 5: + case 7: + svga->bpp = 8; + break; + case 1: + case 2: + case 8: + svga->bpp = 15; + break; + case 3: + case 6: + svga->bpp = 16; + break; + case 4: + case 9: + svga->bpp = 24; + break; + } } else { - switch (ramdac->command >> 5) { - case 0: - default: - svga->bpp = 8; - break; - case 5: - svga->bpp = 15; - break; - case 6: - svga->bpp = 16; - break; - case 7: - svga->bpp = 24; - break; - } + switch (ramdac->command >> 5) { + default: + case 0: + svga->bpp = 8; + break; + case 5: + svga->bpp = 15; + break; + case 6: + svga->bpp = 16; + break; + case 7: + svga->bpp = 24; + break; + } } svga_recalctimings(svga); } - void -stg_ramdac_out(uint16_t addr, uint8_t val, void *p, svga_t *svga) +stg_ramdac_out(uint16_t addr, uint8_t val, void *priv, svga_t *svga) { - stg_ramdac_t *ramdac = (stg_ramdac_t *) p; - int didwrite, old; + stg_ramdac_t *ramdac = (stg_ramdac_t *) priv; + int didwrite; + int old; switch (addr) { - case 0x3c6: - switch (ramdac->magic_count) { - /* 0 = PEL mask register */ - case 0: - case 1: - case 2: - case 3: - break; - case 4: /* REG06 */ - old = ramdac->command; - ramdac->command = val; - if ((old ^ val) & 8) - stg_ramdac_set_bpp(svga, ramdac); - else { - if ((old ^ val) & 0xE0) - stg_ramdac_set_bpp(svga, ramdac); - } - break; - case 5: - ramdac->index = (ramdac->index & 0xff00) | val; - break; - case 6: - ramdac->index = (ramdac->index & 0xff) | (val << 8); - break; - case 7: - if (ramdac->index < 0x100) - ramdac->regs[ramdac->index] = val; - if ((ramdac->index == 3) && (ramdac->command & 8)) - stg_ramdac_set_bpp(svga, ramdac); - ramdac->index++; - break; - } - didwrite = (ramdac->magic_count >= 4); - ramdac->magic_count = stg_state_write[ramdac->magic_count & 7]; - if (didwrite) - return; - break; - case 0x3c7: - case 0x3c8: - case 0x3c9: - ramdac->magic_count=0; - break; + case 0x3c6: + switch (ramdac->magic_count) { + /* 0 = PEL mask register */ + case 0: + case 1: + case 2: + case 3: + break; + case 4: /* REG06 */ + old = ramdac->command; + ramdac->command = val; + if ((old ^ val) & 8) + stg_ramdac_set_bpp(svga, ramdac); + else { + if ((old ^ val) & 0xE0) + stg_ramdac_set_bpp(svga, ramdac); + } + break; + case 5: + ramdac->index = (ramdac->index & 0xff00) | val; + break; + case 6: + ramdac->index = (ramdac->index & 0xff) | (val << 8); + break; + case 7: + if (ramdac->index < 0x100) + ramdac->regs[ramdac->index] = val; + if ((ramdac->index == 3) && (ramdac->command & 8)) + stg_ramdac_set_bpp(svga, ramdac); + ramdac->index++; + break; + + default: + break; + } + didwrite = (ramdac->magic_count >= 4); + ramdac->magic_count = stg_state_write[ramdac->magic_count & 7]; + if (didwrite) + return; + break; + case 0x3c7: + case 0x3c8: + case 0x3c9: + ramdac->magic_count = 0; + break; + + default: + break; } svga_out(addr, val, svga); } - uint8_t -stg_ramdac_in(uint16_t addr, void *p, svga_t *svga) +stg_ramdac_in(uint16_t addr, void *priv, svga_t *svga) { - stg_ramdac_t *ramdac = (stg_ramdac_t *) p; - uint8_t temp = 0xff; + stg_ramdac_t *ramdac = (stg_ramdac_t *) priv; + uint8_t temp = 0xff; switch (addr) { - case 0x3c6: - switch (ramdac->magic_count) { - case 0: - case 1: - case 2: - case 3: - temp = 0xff; - break; - case 4: - temp = ramdac->command; - break; - case 5: - temp = ramdac->index & 0xff; - break; - case 6: - temp = ramdac->index >> 8; - break; - case 7: - switch (ramdac->index) { - case 0: - temp = 0x44; - break; - case 1: - temp = 0x03; - break; - case 7: - temp = 0x88; - break; - default: - if (ramdac->index < 0x100) - temp = ramdac->regs[ramdac->index]; - else - temp = 0xff; - break; - } - ramdac->index++; - break; - } - ramdac->magic_count = stg_state_read[(ramdac->command & 0x10) ? 1 : 0][ramdac->magic_count & 7]; - return temp; - case 0x3c7: - case 0x3c8: - case 0x3c9: - ramdac->magic_count=0; - break; + case 0x3c6: + switch (ramdac->magic_count) { + case 0: + case 1: + case 2: + case 3: + temp = 0xff; + break; + case 4: + temp = ramdac->command; + break; + case 5: + temp = ramdac->index & 0xff; + break; + case 6: + temp = ramdac->index >> 8; + break; + case 7: + switch (ramdac->index) { + case 0: + temp = 0x44; + break; + case 1: + temp = 0x03; + break; + case 7: + temp = 0x88; + break; + default: + if (ramdac->index < 0x100) + temp = ramdac->regs[ramdac->index]; + else + temp = 0xff; + break; + } + ramdac->index++; + break; + + default: + break; + } + ramdac->magic_count = stg_state_read[(ramdac->command & 0x10) ? 1 : 0][ramdac->magic_count & 7]; + return temp; + case 0x3c7: + case 0x3c8: + case 0x3c9: + ramdac->magic_count = 0; + break; + + default: + break; } return svga_in(addr, svga); } - float -stg_getclock(int clock, void *p) +stg_getclock(int clock, void *priv) { - stg_ramdac_t *ramdac = (stg_ramdac_t *)p; - float t; - int m, n, n2; - uint16_t *c; + stg_ramdac_t *ramdac = (stg_ramdac_t *) priv; + float t; + int m; + int n; + int n2; + const uint16_t *c; if (clock == 0) - return 25175000.0; + return 25175000.0; if (clock == 1) - return 28322000.0; + return 28322000.0; - clock ^= 1; /*Clocks 2 and 3 seem to be reversed*/ - c = (uint16_t *) &ramdac->regs[0x20 + (clock << 1)]; - m = (*c & 0xff) + 2; /* B+2 */ - n = ((*c >> 8) & 0x1f) + 2; /* N1+2 */ - n2 = ((*c >> 13) & 0x07); /* D */ + clock ^= 1; /*Clocks 2 and 3 seem to be reversed*/ + c = (uint16_t *) &ramdac->regs[0x20 + (clock << 1)]; + m = (*c & 0xff) + 2; /* B+2 */ + n = ((*c >> 8) & 0x1f) + 2; /* N1+2 */ + n2 = ((*c >> 13) & 0x07); /* D */ n2 = (1 << n2); - t = (14318184.0f * (float)m) / (float)(n * n2); + t = (14318184.0f * (float) m) / (float) (n * n2); return t; } - static void * -stg_ramdac_init(const device_t *info) +stg_ramdac_init(UNUSED(const device_t *info)) { stg_ramdac_t *ramdac = (stg_ramdac_t *) malloc(sizeof(stg_ramdac_t)); memset(ramdac, 0, sizeof(stg_ramdac_t)); @@ -236,22 +246,25 @@ stg_ramdac_init(const device_t *info) return ramdac; } - static void stg_ramdac_close(void *priv) { stg_ramdac_t *ramdac = (stg_ramdac_t *) priv; if (ramdac) - free(ramdac); + free(ramdac); } - -const device_t stg_ramdac_device = -{ - "SGS-Thompson STG170x RAMDAC", - "stg_ramdac", - 0, 0, - stg_ramdac_init, stg_ramdac_close, - NULL, { NULL }, NULL, NULL +const device_t stg_ramdac_device = { + .name = "SGS-Thompson STG170x RAMDAC", + .internal_name = "stg_ramdac", + .flags = 0, + .local = 0, + .init = stg_ramdac_init, + .close = stg_ramdac_close, + .reset = NULL, + { .available = NULL }, + .speed_changed = NULL, + .force_redraw = NULL, + .config = NULL }; diff --git a/src/video/vid_svga.c b/src/video/vid_svga.c index c5ff2ed43..8ec645016 100644 --- a/src/video/vid_svga.c +++ b/src/video/vid_svga.c @@ -1,30 +1,32 @@ /* - * 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. + * 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. + * This file is part of the 86Box distribution. * - * Generic SVGA handling. + * Generic SVGA handling. * - * This is intended to be used by another SVGA driver, - * and not as a card in it's own right. + * This is intended to be used by another SVGA driver, + * and not as a card in its own right. * * * - * Authors: Sarah Walker, - * Miran Grca, + * Authors: Sarah Walker, + * Miran Grca, * - * Copyright 2008-2019 Sarah Walker. - * Copyright 2016-2019 Miran Grca. + * Copyright 2008-2019 Sarah Walker. + * Copyright 2016-2019 Miran Grca. */ #include +#include #include #include -#include #include +#include #include +#define HAVE_STDARG_H #include <86box/86box.h> #include "cpu.h" #include <86box/device.h> @@ -37,412 +39,571 @@ #include <86box/plat.h> #include <86box/ui.h> #include <86box/video.h> +#include <86box/vid_8514a.h> +#include <86box/vid_xga.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); -extern int cyc_total; -extern uint8_t edatlookup[4][4]; +svga_t *svga_8514; -uint8_t svga_rotate[8][256]; +extern int cyc_total; +extern uint8_t edatlookup[4][4]; + +uint8_t svga_rotate[8][256]; /*Primary SVGA device. As multiple video cards are not yet supported this is the only SVGA device.*/ -static svga_t *svga_pri; +static svga_t *svga_pri; +int vga_on; +#ifdef ENABLE_SVGA_LOG +int svga_do_log = ENABLE_SVGA_LOG; -svga_t -*svga_get_pri() +static void +svga_log(const char *fmt, ...) +{ + va_list ap; + + if (svga_do_log) { + va_start(ap, fmt); + pclog_ex(fmt, ap); + va_end(ap); + } +} +#else +# define svga_log(fmt, ...) +#endif + +svga_t * +svga_get_pri(void) { return svga_pri; } - void svga_set_override(svga_t *svga, int val) { if (svga->override && !val) - svga->fullchange = changeframecount; + svga->fullchange = svga->monitor->mon_changeframecount; svga->override = val; if (!val) { - /* Override turned off, restore overscan X and Y per the CRTC. */ - if (enable_overscan) { - overscan_y = (svga->rowcount + 1) << 1; + /* Override turned off, restore overscan X and Y per the CRTC. */ + if (enable_overscan) { + svga->monitor->mon_overscan_y = (svga->rowcount + 1) << 1; - if (overscan_y < 16) - overscan_y = 16; - } + if (svga->monitor->mon_overscan_y < 16) + svga->monitor->mon_overscan_y = 16; + } - overscan_x = (svga->seqregs[1] & 1) ? 16 : 18; + svga->monitor->mon_overscan_x = (svga->seqregs[1] & 1) ? 16 : 18; - if (svga->seqregs[1] & 8) - overscan_x <<= 1; + if (svga->seqregs[1] & 8) + svga->monitor->mon_overscan_x <<= 1; } else - overscan_x = overscan_y = 16; - /* Override turned off, fix overcan X and Y to 16. */ + svga->monitor->mon_overscan_x = svga->monitor->mon_overscan_y = 16; + /* Override turned off, fix overcan X and Y to 16. */ } - void -svga_out(uint16_t addr, uint8_t val, void *p) +svga_out(uint16_t addr, uint8_t val, void *priv) { - svga_t *svga = (svga_t *)p; - int c; - uint8_t o, index; + svga_t *svga = (svga_t *) priv; + ibm8514_t *dev = (ibm8514_t *) svga->dev8514; + xga_t *xga = (xga_t *) svga->xga; + uint8_t o; + uint8_t index; + + if (!dev && (addr >= 0x2ea) && (addr <= 0x2ed)) + return; switch (addr) { - case 0x3c0: - case 0x3c1: - if (!svga->attrff) { - svga->attraddr = val & 31; - if ((val & 0x20) != svga->attr_palette_enable) { - svga->fullchange = 3; - svga->attr_palette_enable = val & 0x20; - svga_recalctimings(svga); - } - } else { - if ((svga->attraddr == 0x13) && (svga->attrregs[0x13] != val)) - svga->fullchange = changeframecount; - o = svga->attrregs[svga->attraddr & 31]; - svga->attrregs[svga->attraddr & 31] = val; - if (svga->attraddr < 16) - svga->fullchange = changeframecount; - if (svga->attraddr == 0x10 || svga->attraddr == 0x14 || svga->attraddr < 0x10) { - for (c = 0; c < 16; c++) { - if (svga->attrregs[0x10] & 0x80) { - svga->egapal[c] = (svga->attrregs[c] & 0xf) | - ((svga->attrregs[0x14] & 0xf) << 4); - } else { - svga->egapal[c] = (svga->attrregs[c] & 0x3f) | - ((svga->attrregs[0x14] & 0xc) << 4); - } - } - svga->fullchange = changeframecount; - } - /* Recalculate timings on change of attribute register 0x11 - (overscan border color) too. */ - if (svga->attraddr == 0x10) { - if (o != val) - svga_recalctimings(svga); - } else if (svga->attraddr == 0x11) { - svga->overscan_color = svga->pallook[svga->attrregs[0x11]]; - if (o != val) - svga_recalctimings(svga); - } else if (svga->attraddr == 0x12) { - if ((val & 0xf) != svga->plane_mask) - svga->fullchange = changeframecount; - svga->plane_mask = val & 0xf; - } - } - svga->attrff ^= 1; - break; - case 0x3c2: - svga->miscout = val; - svga->vidclock = val & 4; - io_removehandler(0x03a0, 0x0020, svga->video_in, NULL, NULL, svga->video_out, NULL, NULL, svga->p); - if (!(val & 1)) - io_sethandler(0x03a0, 0x0020, svga->video_in, NULL, NULL, svga->video_out, NULL, NULL, svga->p); - svga_recalctimings(svga); - break; - case 0x3c4: - svga->seqaddr = val; - break; - case 0x3c5: - if (svga->seqaddr > 0xf) - return; - o = svga->seqregs[svga->seqaddr & 0xf]; - svga->seqregs[svga->seqaddr & 0xf] = val; - if (o != val && (svga->seqaddr & 0xf) == 1) - svga_recalctimings(svga); - switch (svga->seqaddr & 0xf) { - case 1: - if (svga->scrblank && !(val & 0x20)) - svga->fullchange = 3; - svga->scrblank = (svga->scrblank & ~0x20) | (val & 0x20); - svga_recalctimings(svga); - break; - case 2: - svga->writemask = val & 0xf; - break; - case 3: - svga->charsetb = (((val >> 2) & 3) * 0x10000) + 2; - svga->charseta = ((val & 3) * 0x10000) + 2; - if (val & 0x10) - svga->charseta += 0x8000; - if (val & 0x20) - svga->charsetb += 0x8000; - break; - case 4: - svga->chain2_write = !(val & 4); - svga->chain4 = val & 8; - svga->fast = (svga->gdcreg[8] == 0xff && !(svga->gdcreg[3] & 0x18) && - !svga->gdcreg[1]) && ((svga->chain4 && svga->packed_chain4) || svga->fb_only) && !(svga->adv_flags & FLAG_ADDR_BY8); - break; - } - break; - case 0x3c6: - svga->dac_mask = val; - break; - case 0x3c7: - case 0x3c8: - svga->dac_pos = 0; - svga->dac_status = addr & 0x03; - svga->dac_addr = (val + (addr & 0x01)) & 255; - break; - case 0x3c9: - if (svga->adv_flags & FLAG_RAMDAC_SHIFT) - val <<= 2; - svga->fullchange = changeframecount; - switch (svga->dac_pos) { - case 0: - svga->dac_r = val; - svga->dac_pos++; - break; - case 1: - svga->dac_g = val; - svga->dac_pos++; - break; - case 2: - index = svga->dac_addr & 255; - svga->vgapal[index].r = svga->dac_r; - svga->vgapal[index].g = svga->dac_g; - svga->vgapal[index].b = val; - if (svga->ramdac_type == RAMDAC_8BIT) - svga->pallook[index] = makecol32(svga->vgapal[index].r, svga->vgapal[index].g, svga->vgapal[index].b); - else - svga->pallook[index] = makecol32(video_6to8[svga->vgapal[index].r & 0x3f], video_6to8[svga->vgapal[index].g & 0x3f], video_6to8[svga->vgapal[index].b & 0x3f]); - svga->dac_pos = 0; - svga->dac_addr = (svga->dac_addr + 1) & 255; - break; - } - break; - case 0x3ce: - svga->gdcaddr = val; - break; - case 0x3cf: - o = svga->gdcreg[svga->gdcaddr & 15]; - switch (svga->gdcaddr & 15) { - case 2: - svga->colourcompare = val; - break; - case 4: - svga->readplane = val & 3; - break; - case 5: - svga->writemode = val & 3; - svga->readmode = val & 8; - svga->chain2_read = val & 0x10; - break; - case 6: - if ((svga->gdcreg[6] & 0xc) != (val & 0xc)) { - switch (val&0xC) { - 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; - } - } - break; - case 7: - svga->colournocare = val; - break; - } - svga->gdcreg[svga->gdcaddr & 15] = val; - svga->fast = (svga->gdcreg[8] == 0xff && !(svga->gdcreg[3] & 0x18) && - !svga->gdcreg[1]) && ((svga->chain4 && svga->packed_chain4) || svga->fb_only); - if (((svga->gdcaddr & 15) == 5 && (val ^ o) & 0x70) || - ((svga->gdcaddr & 15) == 6 && (val ^ o) & 1)) - svga_recalctimings(svga); - break; + case 0x2ea: + dev->dac_mask = val; + break; + case 0x2eb: + case 0x2ec: + dev->dac_pos = 0; + dev->dac_status = addr & 0x03; + dev->dac_addr = (val + (addr & 0x01)) & 0xff; + break; + case 0x2ed: + svga->fullchange = svga->monitor->mon_changeframecount; + switch (dev->dac_pos) { + case 0: + dev->dac_r = val; + dev->dac_pos++; + break; + case 1: + dev->dac_g = val; + dev->dac_pos++; + break; + case 2: + index = dev->dac_addr & 0xff; + dev->dac_b = val; + svga->vgapal[index].r = dev->dac_r; + svga->vgapal[index].g = dev->dac_g; + svga->vgapal[index].b = dev->dac_b; + if (svga->ramdac_type == RAMDAC_8BIT) + dev->pallook[index] = makecol32(svga->vgapal[index].r, svga->vgapal[index].g, svga->vgapal[index].b); + else + dev->pallook[index] = makecol32(video_6to8[svga->vgapal[index].r & 0x3f], video_6to8[svga->vgapal[index].g & 0x3f], video_6to8[svga->vgapal[index].b & 0x3f]); + dev->dac_pos = 0; + dev->dac_addr = (dev->dac_addr + 1) & 0xff; + break; + + default: + break; + } + break; + + case 0x3c0: + case 0x3c1: + if (!svga->attrff) { + svga->attraddr = val & 31; + if ((val & 0x20) != svga->attr_palette_enable) { + svga->fullchange = 3; + svga->attr_palette_enable = val & 0x20; + svga_recalctimings(svga); + } + } else { + if ((svga->attraddr == 0x13) && (svga->attrregs[0x13] != val)) + svga->fullchange = svga->monitor->mon_changeframecount; + o = svga->attrregs[svga->attraddr & 31]; + svga->attrregs[svga->attraddr & 31] = val; + if (svga->attraddr < 16) + svga->fullchange = svga->monitor->mon_changeframecount; + if (svga->attraddr == 0x10 || svga->attraddr == 0x14 || svga->attraddr < 0x10) { + 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 { + svga->egapal[c] = (svga->attrregs[c] & 0x3f) | ((svga->attrregs[0x14] & 0xc) << 4); + } + } + svga->fullchange = svga->monitor->mon_changeframecount; + } + /* Recalculate timings on change of attribute register 0x11 + (overscan border color) too. */ + if (svga->attraddr == 0x10) { + if (o != val) + svga_recalctimings(svga); + } else if (svga->attraddr == 0x11) { + svga->overscan_color = svga->pallook[svga->attrregs[0x11]]; + if (o != val) + svga_recalctimings(svga); + } else if (svga->attraddr == 0x12) { + if ((val & 0xf) != svga->plane_mask) + svga->fullchange = svga->monitor->mon_changeframecount; + svga->plane_mask = val & 0xf; + } + } + svga->attrff ^= 1; + break; + case 0x3c2: + svga->miscout = val; + svga->vidclock = val & 4; + io_removehandler(0x03a0, 0x0020, svga->video_in, NULL, NULL, svga->video_out, NULL, NULL, svga->priv); + if (!(val & 1)) + io_sethandler(0x03a0, 0x0020, svga->video_in, NULL, NULL, svga->video_out, NULL, NULL, svga->priv); + svga_recalctimings(svga); + break; + case 0x3c3: + if (xga_active) + xga->on = (val & 0x01) ? 0 : 1; + if (ibm8514_active) + dev->on = (val & 0x01) ? 0 : 1; + + svga_log("3C3: XGA ON = %d.\n", xga->on); + vga_on = val & 0x01; + break; + case 0x3c4: + svga->seqaddr = val; + break; + case 0x3c5: + if (svga->seqaddr > 0xf) + return; + o = svga->seqregs[svga->seqaddr & 0xf]; + svga->seqregs[svga->seqaddr & 0xf] = val; + if (o != val && (svga->seqaddr & 0xf) == 1) + svga_recalctimings(svga); + switch (svga->seqaddr & 0xf) { + case 1: + if (svga->scrblank && !(val & 0x20)) + svga->fullchange = 3; + svga->scrblank = (svga->scrblank & ~0x20) | (val & 0x20); + svga_recalctimings(svga); + break; + case 2: + svga->writemask = val & 0xf; + break; + case 3: + svga->charsetb = (((val >> 2) & 3) * 0x10000) + 2; + svga->charseta = ((val & 3) * 0x10000) + 2; + if (val & 0x10) + svga->charseta += 0x8000; + if (val & 0x20) + svga->charsetb += 0x8000; + break; + case 4: + svga->chain2_write = !(val & 4); + svga->chain4 = val & 8; + svga->fast = (svga->gdcreg[8] == 0xff && !(svga->gdcreg[3] & 0x18) && !svga->gdcreg[1]) && ((svga->chain4 && (svga->packed_chain4 || svga->force_old_addr)) || svga->fb_only) && !(svga->adv_flags & FLAG_ADDR_BY8); + break; + + default: + break; + } + break; + case 0x3c6: + svga->dac_mask = val; + break; + case 0x3c7: + case 0x3c8: + svga->dac_pos = 0; + svga->dac_status = addr & 0x03; + svga->dac_addr = (val + (addr & 0x01)) & 255; + break; + case 0x3c9: + if (svga->adv_flags & FLAG_RAMDAC_SHIFT) + val <<= 2; + svga->fullchange = svga->monitor->mon_changeframecount; + switch (svga->dac_pos) { + case 0: + svga->dac_r = val; + svga->dac_pos++; + break; + case 1: + svga->dac_g = val; + svga->dac_pos++; + break; + case 2: + index = svga->dac_addr & 255; + svga->dac_b = val; + svga->vgapal[index].r = svga->dac_r; + svga->vgapal[index].g = svga->dac_g; + svga->vgapal[index].b = svga->dac_b; + if (svga->ramdac_type == RAMDAC_8BIT) + svga->pallook[index] = makecol32(svga->vgapal[index].r, svga->vgapal[index].g, svga->vgapal[index].b); + else + svga->pallook[index] = makecol32(video_6to8[svga->vgapal[index].r & 0x3f], video_6to8[svga->vgapal[index].g & 0x3f], video_6to8[svga->vgapal[index].b & 0x3f]); + svga->dac_pos = 0; + svga->dac_addr = (svga->dac_addr + 1) & 255; + break; + + default: + break; + } + break; + case 0x3ce: + svga->gdcaddr = val; + break; + case 0x3cf: + o = svga->gdcreg[svga->gdcaddr & 15]; + switch (svga->gdcaddr & 15) { + case 2: + svga->colourcompare = val; + break; + case 4: + svga->readplane = val & 3; + break; + case 5: + svga->writemode = val & 3; + svga->readmode = val & 8; + svga->chain2_read = val & 0x10; + break; + case 6: + if ((svga->gdcreg[6] & 0xc) != (val & 0xc)) { + switch (val & 0xc) { + 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; + + default: + break; + } + } + break; + case 7: + svga->colournocare = val; + break; + + default: + break; + } + svga->gdcreg[svga->gdcaddr & 15] = val; + svga->fast = (svga->gdcreg[8] == 0xff && !(svga->gdcreg[3] & 0x18) && !svga->gdcreg[1]) && ((svga->chain4 && (svga->packed_chain4 || svga->force_old_addr)) || svga->fb_only); + if (((svga->gdcaddr & 15) == 5 && (val ^ o) & 0x70) || ((svga->gdcaddr & 15) == 6 && (val ^ o) & 1)) + svga_recalctimings(svga); + break; + + default: + break; } } - uint8_t -svga_in(uint16_t addr, void *p) +svga_in(uint16_t addr, void *priv) { - svga_t *svga = (svga_t *)p; - uint8_t index, ret = 0xff; + svga_t *svga = (svga_t *) priv; + ibm8514_t *dev = (ibm8514_t *) svga->dev8514; + uint8_t index; + uint8_t ret = 0xff; + + if (!dev && (addr >= 0x2ea) && (addr <= 0x2ed)) + return ret; switch (addr) { - case 0x3c0: - ret = svga->attraddr | svga->attr_palette_enable; - break; - case 0x3c1: - ret = svga->attrregs[svga->attraddr]; - break; - case 0x3c2: - if ((svga->vgapal[0].r + svga->vgapal[0].g + svga->vgapal[0].b) >= 0x4e) - ret = 0; - else - ret = 0x10; - break; - case 0x3c4: - ret = svga->seqaddr; - break; - case 0x3c5: - ret = svga->seqregs[svga->seqaddr & 0x0f]; - break; - case 0x3c6: - ret = svga->dac_mask; - break; - case 0x3c7: - ret = svga->dac_status; - break; - case 0x3c8: - ret = svga->dac_addr; - break; - case 0x3c9: - index = (svga->dac_addr - 1) & 255; - switch (svga->dac_pos) { - case 0: - svga->dac_pos++; - if (svga->ramdac_type == RAMDAC_8BIT) - ret = svga->vgapal[index].r; - else - ret = svga->vgapal[index].r & 0x3f; - break; - case 1: - svga->dac_pos++; - if (svga->ramdac_type == RAMDAC_8BIT) - ret = svga->vgapal[index].g; - else - ret = svga->vgapal[index].g & 0x3f; - break; - case 2: - svga->dac_pos=0; - svga->dac_addr = (svga->dac_addr + 1) & 255; - if (svga->ramdac_type == RAMDAC_8BIT) - ret = svga->vgapal[index].b; - else - ret = svga->vgapal[index].b & 0x3f; - break; - } - if (svga->adv_flags & FLAG_RAMDAC_SHIFT) - ret >>= 2; - break; - case 0x3cc: - ret = svga->miscout; - break; - case 0x3ce: - ret = svga->gdcaddr; - break; - case 0x3cf: - /* The spec says GDC addresses 0xF8 to 0xFB return the latch. */ - switch(svga->gdcaddr) { - case 0xf8: - ret = svga->latch.b[0]; - break; - case 0xf9: - ret = svga->latch.b[1]; - break; - case 0xfa: - ret = svga->latch.b[2]; - break; - case 0xfb: - ret = svga->latch.b[3]; - break; - default: - ret = svga->gdcreg[svga->gdcaddr & 0xf]; - break; - } - break; - case 0x3da: - svga->attrff = 0; + case 0x2ea: + ret = dev->dac_mask; + break; + case 0x2eb: + ret = dev->dac_status; + break; + case 0x2ec: + ret = dev->dac_addr; + break; + case 0x2ed: + index = (dev->dac_addr - 1) & 0xff; + switch (dev->dac_pos) { + case 0: + dev->dac_pos++; + if (svga->ramdac_type == RAMDAC_8BIT) + ret = svga->vgapal[index].r; + else + ret = svga->vgapal[index].r & 0x3f; + break; + case 1: + dev->dac_pos++; + if (svga->ramdac_type == RAMDAC_8BIT) + ret = svga->vgapal[index].g; + else + ret = svga->vgapal[index].g & 0x3f; + break; + case 2: + dev->dac_pos = 0; + dev->dac_addr = (dev->dac_addr + 1) & 0xff; + if (svga->ramdac_type == RAMDAC_8BIT) + ret = svga->vgapal[index].b; + else + ret = svga->vgapal[index].b & 0x3f; + break; - if (svga->cgastat & 0x01) - svga->cgastat &= ~0x30; - else - svga->cgastat ^= 0x30; - ret = svga->cgastat; - break; + default: + break; + } + break; + + case 0x3c0: + ret = svga->attraddr | svga->attr_palette_enable; + break; + case 0x3c1: + ret = svga->attrregs[svga->attraddr]; + break; + case 0x3c2: + if ((svga->vgapal[0].r + svga->vgapal[0].g + svga->vgapal[0].b) >= 0x4e) + ret = 0; + else + ret = 0x10; + break; + case 0x3c3: + ret = vga_on; + break; + case 0x3c4: + ret = svga->seqaddr; + break; + case 0x3c5: + ret = svga->seqregs[svga->seqaddr & 0x0f]; + break; + case 0x3c6: + ret = svga->dac_mask; + break; + case 0x3c7: + ret = svga->dac_status; + break; + case 0x3c8: + ret = svga->dac_addr; + break; + case 0x3c9: + index = (svga->dac_addr - 1) & 255; + switch (svga->dac_pos) { + case 0: + svga->dac_pos++; + if (svga->ramdac_type == RAMDAC_8BIT) + ret = svga->vgapal[index].r; + else + ret = svga->vgapal[index].r & 0x3f; + break; + case 1: + svga->dac_pos++; + if (svga->ramdac_type == RAMDAC_8BIT) + ret = svga->vgapal[index].g; + else + ret = svga->vgapal[index].g & 0x3f; + break; + case 2: + svga->dac_pos = 0; + svga->dac_addr = (svga->dac_addr + 1) & 255; + if (svga->ramdac_type == RAMDAC_8BIT) + ret = svga->vgapal[index].b; + else + ret = svga->vgapal[index].b & 0x3f; + break; + + default: + break; + } + if (svga->adv_flags & FLAG_RAMDAC_SHIFT) + ret >>= 2; + break; + case 0x3cc: + ret = svga->miscout; + break; + case 0x3ce: + ret = svga->gdcaddr; + break; + case 0x3cf: + /* The spec says GDC addresses 0xF8 to 0xFB return the latch. */ + switch (svga->gdcaddr) { + case 0xf8: + ret = svga->latch.b[0]; + break; + case 0xf9: + ret = svga->latch.b[1]; + break; + case 0xfa: + ret = svga->latch.b[2]; + break; + case 0xfb: + ret = svga->latch.b[3]; + break; + default: + ret = svga->gdcreg[svga->gdcaddr & 0xf]; + break; + } + break; + case 0x3da: + svga->attrff = 0; + + if (svga->cgastat & 0x01) + svga->cgastat &= ~0x30; + else + svga->cgastat ^= 0x30; + + ret = svga->cgastat; + + break; + + default: + break; } - return(ret); + return ret; } - void svga_set_ramdac_type(svga_t *svga, int type) { - int c; + ibm8514_t *dev = (ibm8514_t *) svga->dev8514; + xga_t *xga = (xga_t *) svga->xga; if (svga->ramdac_type != type) { - svga->ramdac_type = type; + svga->ramdac_type = type; - for (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 - svga->pallook[c] = makecol32((svga->vgapal[c].r & 0x3f) * 4, - (svga->vgapal[c].g & 0x3f) * 4, - (svga->vgapal[c].b & 0x3f) * 4); - } + for (int c = 0; c < 256; c++) { + if (ibm8514_active) { + if (svga->ramdac_type == RAMDAC_8BIT) + dev->pallook[c] = makecol32(svga->vgapal[c].r, svga->vgapal[c].g, svga->vgapal[c].b); + else + dev->pallook[c] = makecol32((svga->vgapal[c].r & 0x3f) * 4, + (svga->vgapal[c].g & 0x3f) * 4, + (svga->vgapal[c].b & 0x3f) * 4); + } + if (xga_active) { + if (svga->ramdac_type == RAMDAC_8BIT) + xga->pallook[c] = makecol32(svga->vgapal[c].r, svga->vgapal[c].g, svga->vgapal[c].b); + else + xga->pallook[c] = makecol32((svga->vgapal[c].r & 0x3f) * 4, + (svga->vgapal[c].g & 0x3f) * 4, + (svga->vgapal[c].b & 0x3f) * 4); + } + if (svga->ramdac_type == RAMDAC_8BIT) + svga->pallook[c] = makecol32(svga->vgapal[c].r, svga->vgapal[c].g, svga->vgapal[c].b); + else + svga->pallook[c] = makecol32((svga->vgapal[c].r & 0x3f) * 4, + (svga->vgapal[c].g & 0x3f) * 4, + (svga->vgapal[c].b & 0x3f) * 4); + } } } - void svga_recalctimings(svga_t *svga) { - double crtcconst, _dispontime, _dispofftime, disptime; + const ibm8514_t *dev = (ibm8514_t *) svga->dev8514; + double crtcconst; + double _dispontime; + double _dispofftime; + double disptime; - svga->vtotal = svga->crtc[6]; - svga->dispend = svga->crtc[0x12]; - svga->vsyncstart = svga->crtc[0x10]; - svga->split = svga->crtc[0x18]; + svga->vtotal = svga->crtc[6]; + svga->dispend = svga->crtc[0x12]; + svga->vsyncstart = svga->crtc[0x10]; + svga->split = svga->crtc[0x18]; svga->vblankstart = svga->crtc[0x15]; if (svga->crtc[7] & 1) - svga->vtotal |= 0x100; + svga->vtotal |= 0x100; if (svga->crtc[7] & 32) - svga->vtotal |= 0x200; + svga->vtotal |= 0x200; svga->vtotal += 2; if (svga->crtc[7] & 2) - svga->dispend |= 0x100; + svga->dispend |= 0x100; if (svga->crtc[7] & 64) - svga->dispend |= 0x200; + svga->dispend |= 0x200; svga->dispend++; if (svga->crtc[7] & 4) - svga->vsyncstart |= 0x100; + svga->vsyncstart |= 0x100; if (svga->crtc[7] & 128) - svga->vsyncstart |= 0x200; + svga->vsyncstart |= 0x200; svga->vsyncstart++; if (svga->crtc[7] & 0x10) - svga->split|=0x100; + svga->split |= 0x100; if (svga->crtc[9] & 0x40) - svga->split|=0x200; + svga->split |= 0x200; svga->split++; if (svga->crtc[7] & 0x08) - svga->vblankstart |= 0x100; + svga->vblankstart |= 0x100; if (svga->crtc[9] & 0x20) - svga->vblankstart |= 0x200; + svga->vblankstart |= 0x200; svga->vblankstart++; svga->hdisp = svga->crtc[1] - ((svga->crtc[5] & 0x60) >> 5); svga->hdisp++; svga->htotal = svga->crtc[0]; - svga->htotal += 6; /*+6 is required for Tyrian*/ + /* +5 has been verified by Sergi to be correct - +6 must have been an off by one error. */ + svga->htotal += 5; /*+5 is required for Tyrian*/ svga->rowoffset = svga->crtc[0x13]; @@ -453,522 +614,561 @@ svga_recalctimings(svga_t *svga) svga->interlace = 0; svga->ma_latch = ((svga->crtc[0xc] << 8) | svga->crtc[0xd]) + ((svga->crtc[8] & 0x60) >> 5); - svga->ca_adj = 0; - - svga->rowcount = svga->crtc[9] & 31; + svga->ca_adj = 0; + + svga->rowcount = svga->crtc[9] & 31; svga->hdisp_time = svga->hdisp; - svga->render = svga_render_blank; - if (!svga->scrblank && svga->attr_palette_enable) { - if (!(svga->gdcreg[6] & 1) && !(svga->attrregs[0x10] & 1)) { /*Text mode*/ - if (svga->seqregs[1] & 8) /*40 column*/ { - svga->render = svga_render_text_40; - svga->hdisp *= (svga->seqregs[1] & 1) ? 16 : 18; - /* Character clock is off by 1 now in 40-line modes, on all cards. */ - svga->ma_latch--; - svga->hdisp += (svga->seqregs[1] & 1) ? 16 : 18; - } else { - svga->render = svga_render_text_80; - svga->hdisp *= (svga->seqregs[1] & 1) ? 8 : 9; - } - svga->hdisp_old = svga->hdisp; - } else { - svga->hdisp *= (svga->seqregs[1] & 8) ? 16 : 8; - svga->hdisp_old = svga->hdisp; + svga->render = svga_render_blank; + if (!svga->scrblank && (svga->crtc[0x17] & 0x80) && svga->attr_palette_enable) { + if (!(svga->gdcreg[6] & 1) && !(svga->attrregs[0x10] & 1)) { /*Text mode*/ + if (svga->seqregs[1] & 8) { /*40 column*/ + svga->render = svga_render_text_40; + svga->hdisp *= (svga->seqregs[1] & 1) ? 16 : 18; + /* Character clock is off by 1 now in 40-line modes, on all cards. */ + svga->ma_latch--; + svga->hdisp += (svga->seqregs[1] & 1) ? 16 : 18; + } else { + svga->render = svga_render_text_80; + svga->hdisp *= (svga->seqregs[1] & 1) ? 8 : 9; + } + svga->hdisp_old = svga->hdisp; + } else { + svga->hdisp *= (svga->seqregs[1] & 8) ? 16 : 8; + svga->hdisp_old = svga->hdisp; - 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; - break; - case 15: - if (svga->lowres) - svga->render = svga_render_15bpp_lowres; - else - svga->render = svga_render_15bpp_highres; - break; - case 16: - if (svga->lowres) - svga->render = svga_render_16bpp_lowres; - else - svga->render = svga_render_16bpp_highres; - break; - case 17: - if (svga->lowres) - svga->render = svga_render_15bpp_mix_lowres; - else - svga->render = svga_render_15bpp_mix_highres; - break; - case 24: - if (svga->lowres) - svga->render = svga_render_24bpp_lowres; - else - svga->render = svga_render_24bpp_highres; - break; - case 32: - if (svga->lowres) - svga->render = svga_render_32bpp_lowres; - else - svga->render = svga_render_32bpp_highres; - break; - } - break; - } - } + 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; + break; + case 15: + if (svga->lowres) + svga->render = svga_render_15bpp_lowres; + else + svga->render = svga_render_15bpp_highres; + break; + case 16: + if (svga->lowres) + svga->render = svga_render_16bpp_lowres; + else + svga->render = svga_render_16bpp_highres; + break; + case 17: + if (svga->lowres) + svga->render = svga_render_15bpp_mix_lowres; + else + svga->render = svga_render_15bpp_mix_highres; + break; + case 24: + if (svga->lowres) + svga->render = svga_render_24bpp_lowres; + else + svga->render = svga_render_24bpp_highres; + break; + case 32: + if (svga->lowres) + svga->render = svga_render_32bpp_lowres; + else + svga->render = svga_render_32bpp_highres; + break; + + default: + break; + } + break; + + default: + break; + } + } } - svga->linedbl = svga->crtc[9] & 0x80; - svga->char_width = (svga->seqregs[1] & 1) ? 8 : 9; + svga->linedbl = svga->crtc[9] & 0x80; + svga->char_width = (svga->seqregs[1] & 1) ? 8 : 9; if (enable_overscan) { - overscan_y = (svga->rowcount + 1) << 1; + svga->monitor->mon_overscan_y = (svga->rowcount + 1) << 1; - if (overscan_y < 16) - overscan_y = 16; + if (svga->monitor->mon_overscan_y < 16) + svga->monitor->mon_overscan_y = 16; } if (!(svga->gdcreg[6] & 1) && !(svga->attrregs[0x10] & 1)) { - overscan_x = (svga->seqregs[1] & 1) ? 16 : 18; + svga->monitor->mon_overscan_x = (svga->seqregs[1] & 1) ? 16 : 18; - if (svga->seqregs[1] & 8) - overscan_x <<= 1; + if (svga->seqregs[1] & 8) + svga->monitor->mon_overscan_x <<= 1; } else - overscan_x = 16; + svga->monitor->mon_overscan_x = 16; - if (svga->recalctimings_ex) - svga->recalctimings_ex(svga); + if (svga->recalctimings_ex) { + svga->recalctimings_ex(svga); + } - svga->y_add = (overscan_y >> 1) - (svga->crtc[8] & 0x1f); - svga->x_add = (overscan_x >> 1); + if (ibm8514_active && (svga->dev8514 != NULL)) { + if (!dev->local) + ibm8514_recalctimings(svga); + } + + if (xga_active && (svga->xga != NULL)) + xga_recalctimings(svga); + + if (svga->hdisp >= 2048) + svga->monitor->mon_overscan_x = 0; + + svga->y_add = (svga->monitor->mon_overscan_y >> 1) - (svga->crtc[8] & 0x1f); + svga->x_add = (svga->monitor->mon_overscan_x >> 1); if (svga->vblankstart < svga->dispend) - svga->dispend = svga->vblankstart; + svga->dispend = svga->vblankstart; crtcconst = svga->clock * svga->char_width; - disptime = svga->htotal; + disptime = svga->htotal; _dispontime = svga->hdisp_time; if (svga->seqregs[1] & 8) { - disptime *= 2; - _dispontime *= 2; + disptime *= 2; + _dispontime *= 2; } _dispofftime = disptime - _dispontime; _dispontime *= crtcconst; _dispofftime *= crtcconst; - svga->dispontime = (uint64_t)(_dispontime); - svga->dispofftime = (uint64_t)(_dispofftime); + svga->dispontime = (uint64_t) (_dispontime); + svga->dispofftime = (uint64_t) (_dispofftime); if (svga->dispontime < TIMER_USEC) - svga->dispontime = TIMER_USEC; + svga->dispontime = TIMER_USEC; if (svga->dispofftime < TIMER_USEC) - svga->dispofftime = TIMER_USEC; + svga->dispofftime = TIMER_USEC; - svga_recalc_remap_func(svga); + if (!svga->force_old_addr) + svga_recalc_remap_func(svga); /* Inform the user interface of any DPMS mode changes. */ if (svga->dpms) { - if (!svga->dpms_ui) { - svga->dpms_ui = 1; - ui_sb_set_text_w(plat_get_string(IDS_2142)); - } + if (!svga->dpms_ui) { + svga->dpms_ui = 1; + ui_sb_set_text_w(plat_get_string(IDS_2143)); + } } else if (svga->dpms_ui) { - svga->dpms_ui = 0; - ui_sb_set_text_w(NULL); + svga->dpms_ui = 0; + ui_sb_set_text_w(NULL); } } - static void svga_do_render(svga_t *svga) { /* Always render a blank screen and nothing else while in DPMS mode. */ if (svga->dpms) { - svga_render_blank(svga); - return; + svga_render_blank(svga); + return; } if (!svga->override) { - svga->render(svga); + svga->render(svga); - svga->x_add = (overscan_x >> 1); - svga_render_overscan_left(svga); - svga_render_overscan_right(svga); - svga->x_add = (overscan_x >> 1) - svga->scrollcache; + svga->x_add = (svga->monitor->mon_overscan_x >> 1); + svga_render_overscan_left(svga); + svga_render_overscan_right(svga); + svga->x_add = (svga->monitor->mon_overscan_x >> 1) - svga->scrollcache; } if (svga->overlay_on) { - if (!svga->override && svga->overlay_draw) - svga->overlay_draw(svga, svga->displine + svga->y_add); - svga->overlay_on--; - if (svga->overlay_on && svga->interlace) - svga->overlay_on--; + if (!svga->override && svga->overlay_draw) + svga->overlay_draw(svga, svga->displine + svga->y_add); + svga->overlay_on--; + if (svga->overlay_on && svga->interlace) + svga->overlay_on--; } if (svga->dac_hwcursor_on) { - if (!svga->override && svga->dac_hwcursor_draw) - svga->dac_hwcursor_draw(svga, svga->displine + svga->y_add); - svga->dac_hwcursor_on--; - if (svga->dac_hwcursor_on && svga->interlace) - svga->dac_hwcursor_on--; + if (!svga->override && svga->dac_hwcursor_draw) + svga->dac_hwcursor_draw(svga, svga->displine + svga->y_add); + svga->dac_hwcursor_on--; + if (svga->dac_hwcursor_on && svga->interlace) + svga->dac_hwcursor_on--; } if (svga->hwcursor_on) { - if (!svga->override && svga->hwcursor_draw) - svga->hwcursor_draw(svga, svga->displine + svga->y_add); - svga->hwcursor_on--; - if (svga->hwcursor_on && svga->interlace) - svga->hwcursor_on--; + if (!svga->override && svga->hwcursor_draw) + svga->hwcursor_draw(svga, svga->displine + svga->y_add); + svga->hwcursor_on--; + if (svga->hwcursor_on && svga->interlace) + svga->hwcursor_on--; } } - void -svga_poll(void *p) +svga_poll(void *priv) { - svga_t *svga = (svga_t *)p; - uint32_t x, blink_delay; - int wx, wy; - int ret, old_ma; + svga_t *svga = (svga_t *) priv; + ibm8514_t *dev = (ibm8514_t *) svga->dev8514; + xga_t *xga = (xga_t *) svga->xga; + uint32_t x; + uint32_t blink_delay; + int wx; + int wy; + int ret; + int old_ma; + + if (!svga->override) { + if (ibm8514_active && dev->on) { + ibm8514_poll(dev, svga); + return; + } + if (xga_active && xga->on) { + if ((xga->disp_cntl_2 & 7) >= 2) { + xga_poll(xga, svga); + return; + } + } + } if (!svga->linepos) { - if (svga->displine == svga->hwcursor_latch.y && svga->hwcursor_latch.ena) { - svga->hwcursor_on = svga->hwcursor.ysize - svga->hwcursor_latch.yoff; - svga->hwcursor_oddeven = 0; - } + if (svga->displine == svga->hwcursor_latch.y && svga->hwcursor_latch.ena) { + 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.ysize - (svga->hwcursor_latch.yoff + 1); - svga->hwcursor_oddeven = 1; - } + if (svga->displine == (svga->hwcursor_latch.y + 1) && svga->hwcursor_latch.ena && svga->interlace) { + 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.ysize - svga->dac_hwcursor_latch.yoff; - svga->dac_hwcursor_oddeven = 0; - } + if (svga->displine == svga->dac_hwcursor_latch.y && svga->dac_hwcursor_latch.ena) { + 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.ysize - (svga->dac_hwcursor_latch.yoff + 1); - svga->dac_hwcursor_oddeven = 1; - } + if (svga->displine == (svga->dac_hwcursor_latch.y + 1) && svga->dac_hwcursor_latch.ena && svga->interlace) { + svga->dac_hwcursor_on = svga->dac_hwcursor_latch.cur_ysize - (svga->dac_hwcursor_latch.yoff + 1); + svga->dac_hwcursor_oddeven = 1; + } - if (svga->displine == svga->overlay_latch.y && svga->overlay_latch.ena) { - svga->overlay_on = svga->overlay_latch.ysize - svga->overlay_latch.yoff; - svga->overlay_oddeven = 0; - } + if (svga->displine == svga->overlay_latch.y && svga->overlay_latch.ena) { + svga->overlay_on = svga->overlay_latch.cur_ysize - svga->overlay_latch.yoff; + svga->overlay_oddeven = 0; + } - if (svga->displine == svga->overlay_latch.y+1 && svga->overlay_latch.ena && svga->interlace) { - svga->overlay_on = svga->overlay_latch.ysize - svga->overlay_latch.yoff; - svga->overlay_oddeven = 1; - } + if (svga->displine == svga->overlay_latch.y + 1 && svga->overlay_latch.ena && svga->interlace) { + svga->overlay_on = svga->overlay_latch.cur_ysize - svga->overlay_latch.yoff; + svga->overlay_oddeven = 1; + } - timer_advance_u64(&svga->timer, svga->dispofftime); - svga->cgastat |= 1; - svga->linepos = 1; + timer_advance_u64(&svga->timer, svga->dispofftime); + svga->cgastat |= 1; + svga->linepos = 1; - if (svga->dispon) { - svga->hdisp_on = 1; + if (svga->dispon) { + svga->hdisp_on = 1; - svga->ma &= svga->vram_display_mask; - if (svga->firstline == 2000) { - svga->firstline = svga->displine; - video_wait_for_buffer(); - } + svga->ma &= svga->vram_display_mask; + if (svga->firstline == 2000) { + svga->firstline = svga->displine; + video_wait_for_buffer_monitor(svga->monitor_index); + } - if (svga->hwcursor_on || svga->dac_hwcursor_on || svga->overlay_on) { - svga->changedvram[svga->ma >> 12] = svga->changedvram[(svga->ma >> 12) + 1] = - svga->interlace ? 3 : 2; - } + if (svga->hwcursor_on || svga->dac_hwcursor_on || svga->overlay_on) { + svga->changedvram[svga->ma >> 12] = svga->changedvram[(svga->ma >> 12) + 1] = svga->interlace ? 3 : 2; + } - if (svga->vertical_linedbl) { - old_ma = svga->ma; + if (svga->vertical_linedbl) { + old_ma = svga->ma; - svga->displine <<= 1; - svga->y_add <<= 1; + svga->displine <<= 1; + svga->y_add <<= 1; - svga_do_render(svga); + svga_do_render(svga); - svga->displine++; + svga->displine++; - svga->ma = old_ma; + svga->ma = old_ma; - svga_do_render(svga); + svga_do_render(svga); - svga->y_add >>= 1; - svga->displine >>= 1; - } else - svga_do_render(svga); + svga->y_add >>= 1; + svga->displine >>= 1; + } else + svga_do_render(svga); - if (svga->lastline < svga->displine) - svga->lastline = svga->displine; - } + if (svga->lastline < svga->displine) + svga->lastline = svga->displine; + } - svga->displine++; - if (svga->interlace) - svga->displine++; - if ((svga->cgastat & 8) && ((svga->displine & 15) == (svga->crtc[0x11] & 15)) && svga->vslines) - svga->cgastat &= ~8; - svga->vslines++; - if (svga->displine > 1500) - svga->displine = 0; + svga->displine++; + if (svga->interlace) + svga->displine++; + if ((svga->cgastat & 8) && ((svga->displine & 15) == (svga->crtc[0x11] & 15)) && svga->vslines) + svga->cgastat &= ~8; + svga->vslines++; + if (svga->displine > 2000) + svga->displine = 0; } else { - timer_advance_u64(&svga->timer, svga->dispontime); + timer_advance_u64(&svga->timer, svga->dispontime); - if (svga->dispon) - svga->cgastat &= ~1; - svga->hdisp_on = 0; + if (svga->dispon) + svga->cgastat &= ~1; + svga->hdisp_on = 0; - svga->linepos = 0; - 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; - svga->ma = svga->maback; - } else if (svga->sc == svga->rowcount) { - svga->linecountff = 0; - svga->sc = 0; + svga->linepos = 0; + 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; + svga->ma = svga->maback; + } else if (svga->sc == svga->rowcount) { + svga->linecountff = 0; + svga->sc = 0; - 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->ma = svga->maback; - } - } + svga->maback += (svga->rowoffset << 3); + if (svga->interlace) + svga->maback += (svga->rowoffset << 3); - svga->hsync_divisor = !svga->hsync_divisor; + svga->maback &= svga->vram_display_mask; + svga->ma = svga->maback; + } else { + svga->linecountff = 0; + svga->sc++; + svga->sc &= 0x1f; + svga->ma = svga->maback; + } + } - if (svga->hsync_divisor && (svga->crtc[0x17] & 4)) - return; + svga->hsync_divisor ^= 1; - svga->vc++; - svga->vc &= 2047; + if (svga->hsync_divisor && (svga->crtc[0x17] & 4)) + return; - if (svga->vc == svga->split) { - ret = 1; - - if (svga->line_compare) - ret = svga->line_compare(svga); - - if (ret) { - if (svga->interlace && svga->oddeven) - svga->ma = svga->maback = (svga->rowoffset << 1) + ((svga->crtc[5] & 0x60) >> 5); - else - svga->ma = svga->maback = ((svga->crtc[5] & 0x60) >> 5); - svga->ma = (svga->ma << 2); - svga->maback = (svga->maback << 2); - svga->sc = 0; - if (svga->attrregs[0x10] & 0x20) { - svga->scrollcache = 0; - svga->x_add = (overscan_x >> 1); - } - } - } - 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) - svga->cursoron = 0; - else if (blink_delay == 2) - svga->cursoron = ((svga->blink % 96) >= 48); - else - svga->cursoron = svga->blink & (16 + (16 * blink_delay)); + svga->vc++; + svga->vc &= 0x7ff; - if (!(svga->gdcreg[6] & 1) && !(svga->blink & 15)) - svga->fullchange = 2; - svga->blink = (svga->blink + 1) & 0x7f; + if (svga->vc == svga->split) { + ret = 1; - for (x = 0; x < ((svga->vram_mask + 1) >> 12); x++) { - if (svga->changedvram[x]) - svga->changedvram[x]--; - } - if (svga->fullchange) - svga->fullchange--; - } - if (svga->vc == svga->vsyncstart) { - svga->dispon = 0; - svga->cgastat |= 8; - x = svga->hdisp; + if (svga->line_compare) + ret = svga->line_compare(svga); - if (svga->interlace && !svga->oddeven) - svga->lastline++; - if (svga->interlace && svga->oddeven) - svga->firstline--; + if (ret) { + if (svga->interlace && svga->oddeven) + svga->ma = svga->maback = (svga->rowoffset << 1) + ((svga->crtc[5] & 0x60) >> 5); + else + svga->ma = svga->maback = ((svga->crtc[5] & 0x60) >> 5); + svga->ma = (svga->ma << 2); + svga->maback = (svga->maback << 2); - wx = x; + svga->sc = 0; + if (svga->attrregs[0x10] & 0x20) { + svga->scrollcache = 0; + svga->x_add = (svga->monitor->mon_overscan_x >> 1); + } + } + } + if (svga->vc == svga->dispend) { + if (svga->vblank_start) + svga->vblank_start(svga); - if (!svga->override) { - if (svga->vertical_linedbl) { - wy = (svga->lastline - svga->firstline) << 1; - svga_doblit(wx, wy, svga); - } else { - wy = svga->lastline - svga->firstline; - svga_doblit(wx, wy, svga); - } - } + svga->dispon = 0; + blink_delay = (svga->crtc[11] & 0x60) >> 5; + if (svga->crtc[10] & 0x20) + svga->cursoron = 0; + else if (blink_delay == 2) + svga->cursoron = ((svga->blink % 96) >= 48); + else + svga->cursoron = svga->blink & (16 + (16 * blink_delay)); - svga->firstline = 2000; - svga->lastline = 0; + if (!(svga->gdcreg[6] & 1) && !(svga->blink & 15)) + svga->fullchange = 2; - svga->firstline_draw = 2000; - svga->lastline_draw = 0; + svga->blink = (svga->blink + 1) & 0x7f; - svga->oddeven ^= 1; + for (x = 0; x < ((svga->vram_mask + 1) >> 12); x++) { + if (svga->changedvram[x]) + svga->changedvram[x]--; + } + if (svga->fullchange) + svga->fullchange--; + } + if (svga->vc == svga->vsyncstart) { + svga->dispon = 0; + svga->cgastat |= 8; + x = svga->hdisp; - changeframecount = svga->interlace ? 3 : 2; - svga->vslines = 0; + if (svga->interlace && !svga->oddeven) + svga->lastline++; + if (svga->interlace && svga->oddeven) + svga->firstline--; - 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); - svga->ca = ((svga->crtc[0xe] << 8) | svga->crtc[0xf]) + ((svga->crtc[0xb] & 0x60) >> 5) + svga->ca_adj; + wx = x; - svga->ma = (svga->ma << 2); - svga->maback = (svga->maback << 2); - svga->ca = (svga->ca << 2); + if (!svga->override) { + if (svga->vertical_linedbl) { + wy = (svga->lastline - svga->firstline) << 1; + svga_doblit(wx, wy, svga); + } else { + wy = svga->lastline - svga->firstline; + svga_doblit(wx, wy, svga); + } + } - if (svga->vsync_callback) - svga->vsync_callback(svga); - } - if (svga->vc == svga->vtotal) { - svga->vc = 0; - svga->sc = 0; - svga->dispon = 1; - svga->displine = (svga->interlace && svga->oddeven) ? 1 : 0; + svga->firstline = 2000; + svga->lastline = 0; - svga->scrollcache = (svga->attrregs[0x13] & 0x0f); - if (!(svga->gdcreg[6] & 1) && !(svga->attrregs[0x10] & 1)) { /*Text mode*/ - if (svga->seqregs[1] & 1) - svga->scrollcache &= 0x07; - else { - svga->scrollcache++; - if (svga->scrollcache > 8) - svga->scrollcache = 0; - } - } else if ((svga->render == svga_render_2bpp_lowres) || (svga->render == svga_render_2bpp_highres) || - (svga->render == svga_render_4bpp_lowres) || (svga->render == svga_render_4bpp_highres)) - svga->scrollcache &= 0x07; - else - svga->scrollcache = (svga->scrollcache & 0x06) >> 1; + svga->firstline_draw = 2000; + svga->lastline_draw = 0; - if ((svga->seqregs[1] & 8) || (svga->render == svga_render_8bpp_lowres)) - svga->scrollcache <<= 1; + svga->oddeven ^= 1; - svga->x_add = (overscan_x >> 1) - svga->scrollcache; + svga->monitor->mon_changeframecount = svga->interlace ? 3 : 2; + svga->vslines = 0; - svga->linecountff = 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); - svga->hwcursor_on = 0; - svga->hwcursor_latch = svga->hwcursor; + 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); - svga->dac_hwcursor_on = 0; - svga->dac_hwcursor_latch = svga->dac_hwcursor; + if (svga->vsync_callback) + svga->vsync_callback(svga); + } + if (svga->vc == svga->vtotal) { + svga->vc = 0; + svga->sc = 0; + svga->dispon = 1; + svga->displine = (svga->interlace && svga->oddeven) ? 1 : 0; - svga->overlay_on = 0; - svga->overlay_latch = svga->overlay; - } - if (svga->sc == (svga->crtc[10] & 31)) - svga->con = 1; + svga->scrollcache = (svga->attrregs[0x13] & 0x0f); + if (!(svga->gdcreg[6] & 1) && !(svga->attrregs[0x10] & 1)) { /*Text mode*/ + if (svga->seqregs[1] & 1) + svga->scrollcache &= 0x07; + else { + svga->scrollcache++; + if (svga->scrollcache > 8) + svga->scrollcache = 0; + } + } else if ((svga->render == svga_render_2bpp_lowres) || (svga->render == svga_render_2bpp_highres) || (svga->render == svga_render_4bpp_lowres) || (svga->render == svga_render_4bpp_highres)) + svga->scrollcache &= 0x07; + else + svga->scrollcache = (svga->scrollcache & 0x06) >> 1; + + if ((svga->seqregs[1] & 8) || (svga->render == svga_render_8bpp_lowres)) + svga->scrollcache <<= 1; + + svga->x_add = (svga->monitor->mon_overscan_x >> 1) - svga->scrollcache; + + svga->linecountff = 0; + + svga->hwcursor_on = 0; + svga->hwcursor_latch = svga->hwcursor; + + svga->dac_hwcursor_on = 0; + svga->dac_hwcursor_latch = svga->dac_hwcursor; + + svga->overlay_on = 0; + svga->overlay_latch = svga->overlay; + } + if (svga->sc == (svga->crtc[10] & 31)) + svga->con = 1; } } - int -svga_init(const device_t *info, svga_t *svga, void *p, int memsize, - void (*recalctimings_ex)(struct svga_t *svga), - uint8_t (*video_in) (uint16_t addr, void *p), - void (*video_out)(uint16_t addr, uint8_t val, void *p), - void (*hwcursor_draw)(struct svga_t *svga, int displine), - void (*overlay_draw)(struct svga_t *svga, int displine)) +svga_init(const device_t *info, svga_t *svga, void *priv, int memsize, + void (*recalctimings_ex)(struct svga_t *svga), + uint8_t (*video_in)(uint16_t addr, void *priv), + void (*video_out)(uint16_t addr, uint8_t val, void *priv), + void (*hwcursor_draw)(struct svga_t *svga, int displine), + void (*overlay_draw)(struct svga_t *svga, int displine)) { - int c, d, e; + int e; - svga->p = p; + svga->priv = priv; + svga->monitor_index = monitor_index_global; + svga->monitor = &monitors[svga->monitor_index]; - for (c = 0; c < 256; c++) { - e = c; - for (d = 0; d < 8; d++) { - svga_rotate[d][c] = e; - e = (e >> 1) | ((e & 1) ? 0x80 : 0); - } + for (int c = 0; c < 256; c++) { + e = c; + for (int d = 0; d < 8; d++) { + svga_rotate[d][c] = e; + e = (e >> 1) | ((e & 1) ? 0x80 : 0); + } } svga->readmode = 0; svga->attrregs[0x11] = 0; svga->overscan_color = 0x000000; - overscan_x = 16; - overscan_y = 32; - svga->x_add = 8; - svga->y_add = 16; + svga->monitor->mon_overscan_x = 16; + svga->monitor->mon_overscan_y = 32; + svga->x_add = 8; + svga->y_add = 16; - svga->crtc[0] = 63; - svga->crtc[6] = 255; - svga->dispontime = 1000ull << 32; - svga->dispofftime = 1000ull << 32; - svga->bpp = 8; - svga->vram = malloc(memsize); - svga->vram_max = memsize; + svga->crtc[0] = 63; + svga->crtc[6] = 255; + svga->dispontime = 1000ULL << 32; + svga->dispofftime = 1000ULL << 32; + svga->bpp = 8; + svga->vram = calloc(memsize, 1); + svga->vram_max = memsize; svga->vram_display_mask = svga->vram_mask = memsize - 1; - svga->decode_mask = 0x7fffff; - svga->changedvram = malloc(memsize >> 12); - svga->recalctimings_ex = recalctimings_ex; - svga->video_in = video_in; - svga->video_out = video_out; - svga->hwcursor_draw = hwcursor_draw; - svga->overlay_draw = overlay_draw; + svga->decode_mask = 0x7fffff; + svga->changedvram = calloc(memsize >> 12, 1); + svga->recalctimings_ex = recalctimings_ex; + svga->video_in = video_in; + svga->video_out = video_out; + svga->hwcursor_draw = hwcursor_draw; + svga->overlay_draw = overlay_draw; - svga->hwcursor.xsize = svga->hwcursor.ysize = 32; + svga->hwcursor.cur_xsize = svga->hwcursor.cur_ysize = 32; - svga->dac_hwcursor.xsize = svga->dac_hwcursor.ysize = 32; - - svga->translate_address = NULL; - svga->ksc5601_english_font_type = 0; + svga->dac_hwcursor.cur_xsize = svga->dac_hwcursor.cur_ysize = 32; + + svga->translate_address = NULL; + svga->ksc5601_english_font_type = 0; + + vga_on = 1; if ((info->flags & DEVICE_PCI) || (info->flags & DEVICE_VLB) || (info->flags & DEVICE_MCA)) { - mem_mapping_add(&svga->mapping, 0xa0000, 0x20000, - svga_read, svga_readw, svga_readl, - svga_write, svga_writew, svga_writel, - NULL, MEM_MAPPING_EXTERNAL, svga); + mem_mapping_add(&svga->mapping, 0xa0000, 0x20000, + svga_read, svga_readw, svga_readl, + svga_write, svga_writew, svga_writel, + NULL, MEM_MAPPING_EXTERNAL, svga); } else if ((info->flags & DEVICE_ISA) && (info->flags & DEVICE_AT)) { - mem_mapping_add(&svga->mapping, 0xa0000, 0x20000, - svga_read, svga_readw, NULL, - svga_write, svga_writew, NULL, - NULL, MEM_MAPPING_EXTERNAL, svga); + mem_mapping_add(&svga->mapping, 0xa0000, 0x20000, + svga_read, svga_readw, NULL, + svga_write, svga_writew, NULL, + NULL, MEM_MAPPING_EXTERNAL, svga); } else { - mem_mapping_add(&svga->mapping, 0xa0000, 0x20000, - svga_read, NULL, NULL, - svga_write, NULL, NULL, - NULL, MEM_MAPPING_EXTERNAL, svga); + mem_mapping_add(&svga->mapping, 0xa0000, 0x20000, + svga_read, NULL, NULL, + svga_write, NULL, NULL, + NULL, MEM_MAPPING_EXTERNAL, svga); } timer_add(&svga->timer, svga_poll, svga, 1); @@ -982,7 +1182,6 @@ svga_init(const device_t *info, svga_t *svga, void *p, int memsize, return 0; } - void svga_close(svga_t *svga) { @@ -990,12 +1189,11 @@ svga_close(svga_t *svga) free(svga->vram); if (svga->dpms_ui) - ui_sb_set_text_w(NULL); + ui_sb_set_text_w(NULL); svga_pri = NULL; } - static uint32_t svga_decode_addr(svga_t *svga, uint32_t addr, int write) { @@ -1004,692 +1202,754 @@ svga_decode_addr(svga_t *svga, uint32_t addr, int write) addr &= 0x1ffff; switch (memory_map_mode) { - case 0: - break; - case 1: - if (addr >= 0x10000) - return 0xffffffff; - break; - case 2: - addr -= 0x10000; - if (addr >= 0x8000) - return 0xffffffff; - break; - default: - case 3: - addr -= 0x18000; - if (addr >= 0x8000) - return 0xffffffff; - break; + case 0: + break; + case 1: + if (addr >= 0x10000) + return 0xffffffff; + break; + case 2: + addr -= 0x10000; + if (addr >= 0x8000) + return 0xffffffff; + break; + default: + case 3: + addr -= 0x18000; + if (addr >= 0x8000) + return 0xffffffff; + break; } if (memory_map_mode <= 1) { - if (svga->adv_flags & FLAG_EXTRA_BANKS) - addr = (addr & 0x17fff) + svga->extra_banks[(addr >> 15) & 1]; - else { - if (write) - addr += svga->write_bank; - else - addr += svga->read_bank; - } + if (svga->adv_flags & FLAG_EXTRA_BANKS) + addr = (addr & 0x17fff) + svga->extra_banks[(addr >> 15) & 1]; + else { + if (write) + addr += svga->write_bank; + else + addr += svga->read_bank; + } } return addr; } - static __inline void -svga_write_common(uint32_t addr, uint8_t val, uint8_t linear, void *p) +svga_write_common(uint32_t addr, uint8_t val, uint8_t linear, void *priv) { - svga_t *svga = (svga_t *)p; - - int writemask2 = svga->writemask, reset_wm = 0; + svga_t *svga = (svga_t *) priv; + xga_t *xga = (xga_t *) svga->xga; + int writemask2 = svga->writemask; + int reset_wm = 0; latch_t vall; - uint8_t wm = svga->writemask; - uint8_t count, i; + uint8_t wm = svga->writemask; + uint8_t count; + uint8_t i; if (svga->adv_flags & FLAG_ADDR_BY8) - writemask2 = svga->seqregs[2]; + writemask2 = svga->seqregs[2]; - cycles -= video_timing_write_b; + cycles -= svga->monitor->mon_video_timing_write_b; if (!linear) { - addr = svga_decode_addr(svga, addr, 1); + if (xga_active) { + if (((xga->op_mode & 7) >= 4) && (xga->aperture_cntl >= 1)) { + if (val == 0xa5) { /*Memory size test of XGA*/ + xga->test = val; + if (addr == 0xa0001) + xga->a5_test = 1; + else if (addr == 0xafffe) + xga->a5_test = 2; - if (addr == 0xffffffff) - return; + xga->on = 0; + vga_on = 1; + xga->disp_cntl_2 = 0; + svga_log("XGA test1 addr = %05x.\n", addr); + return; + } else if (val == 0x5a) { + xga->test = val; + xga->on = 0; + vga_on = 1; + xga->disp_cntl_2 = 0; + svga_log("XGA test2 addr = %05x.\n", addr); + return; + } else if ((addr == 0xa0000) || (addr == 0xa0010)) { + addr += xga->write_bank; + xga->vram[addr & xga->vram_mask] = val; + svga_log("XGA Linear endian reverse write, val = %02x, addr = %05x, banked mask = %04x.\n", val, addr, svga->banked_mask); + if (!xga->a5_test) + xga->linear_endian_reverse = 1; + return; + } + } else { + xga->on = 0; + vga_on = 1; + } + } + addr = svga_decode_addr(svga, addr, 1); + + if (addr == 0xffffffff) + return; } if (!(svga->gdcreg[6] & 1)) - svga->fullchange = 2; + svga->fullchange = 2; - if ((svga->adv_flags & FLAG_ADDR_BY16) && (svga->writemode == 4 || svga->writemode == 5)) - addr <<= 4; + if ((svga->adv_flags & FLAG_ADDR_BY16) && (svga->writemode == 4 || svga->writemode == 5)) + addr <<= 4; else if ((svga->adv_flags & FLAG_ADDR_BY8) && (svga->writemode < 4)) - addr <<= 3; - else if (((svga->chain4 && svga->packed_chain4) || svga->fb_only) && (svga->writemode < 4)) { - writemask2 = 1 << (addr & 3); - addr &= ~3; - } else if (svga->chain4 && (svga->writemode < 4)) { - writemask2 = 1 << (addr & 3); - if (!linear) - addr &= ~3; - addr = ((addr & 0xfffc) << 2) | ((addr & 0x30000) >> 14) | (addr & ~0x3ffff); + addr <<= 3; + else if (((svga->chain4 && (svga->packed_chain4 || svga->force_old_addr)) || svga->fb_only) && (svga->writemode < 4)) { + writemask2 = 1 << (addr & 3); + addr &= ~3; + } else if (svga->chain4 && (svga->writemode < 4)) { + writemask2 = 1 << (addr & 3); + if (!linear) + addr &= ~3; + addr = ((addr & 0xfffc) << 2) | ((addr & 0x30000) >> 14) | (addr & ~0x3ffff); } else if (svga->chain2_write) { - writemask2 &= ~0xa; - if (addr & 1) - writemask2 <<= 1; - addr &= ~1; - addr <<= 2; + writemask2 &= ~0xa; + if (addr & 1) + writemask2 <<= 1; + addr &= ~1; + addr <<= 2; } else - addr <<= 2; + addr <<= 2; addr &= svga->decode_mask; if (svga->translate_address) - addr = svga->translate_address(addr, p); + addr = svga->translate_address(addr, priv); if (addr >= svga->vram_max) - return; + return; addr &= svga->vram_mask; - svga->changedvram[addr >> 12] = changeframecount; + svga->changedvram[addr >> 12] = svga->monitor->mon_changeframecount; count = 4; if (svga->adv_flags & FLAG_LATCH8) - count = 8; + count = 8; /* Undocumented Cirrus Logic behavior: The datasheet says that, with EXT_WRITE and FLAG_ADDR_BY8, the write mask only changes meaning in write modes 4 and 5, as well as write mode 1. In reality, however, all other write modes are also affected, as proven by the Windows 3.1 CL-GD 5422/4 drivers in 8bpp modes. */ switch (svga->writemode) { - case 0: - val = ((val >> (svga->gdcreg[3] & 7)) | (val << (8 - (svga->gdcreg[3] & 7)))); - if ((svga->gdcreg[8] == 0xff) && !(svga->gdcreg[3] & 0x18) && (!svga->gdcreg[1] || svga->set_reset_disabled)) { - for (i = 0; i < count; i++) { - if ((svga->adv_flags & FLAG_EXT_WRITE) && (svga->adv_flags & FLAG_ADDR_BY8)) { - if (writemask2 & (0x80 >> i)) - svga->vram[addr | i] = val; - } else { - if (writemask2 & (1 << i)) - svga->vram[addr | i] = val; - } - } - return; - } else { - for (i = 0; i < count; i++) { - if (svga->gdcreg[1] & (1 << i)) - vall.b[i] = !!(svga->gdcreg[0] & (1 << i)) * 0xff; - else - vall.b[i] = val; - } - } - break; - case 1: - for (i = 0; i < count; i++) { - if ((svga->adv_flags & FLAG_EXT_WRITE) && (svga->adv_flags & FLAG_ADDR_BY8)) { - if (writemask2 & (0x80 >> i)) - svga->vram[addr | i] = svga->latch.b[i]; - } else { - if (writemask2 & (1 << i)) - svga->vram[addr | i] = svga->latch.b[i]; - } - } - return; - case 2: - for (i = 0; i < count; i++) - vall.b[i] = !!(val & (1 << i)) * 0xff; + case 0: + val = ((val >> (svga->gdcreg[3] & 7)) | (val << (8 - (svga->gdcreg[3] & 7)))); + if ((svga->gdcreg[8] == 0xff) && !(svga->gdcreg[3] & 0x18) && (!svga->gdcreg[1] || svga->set_reset_disabled)) { + for (i = 0; i < count; i++) { + if ((svga->adv_flags & FLAG_EXT_WRITE) && (svga->adv_flags & FLAG_ADDR_BY8)) { + if (writemask2 & (0x80 >> i)) + svga->vram[addr | i] = val; + } else { + if (writemask2 & (1 << i)) + svga->vram[addr | i] = val; + } + } + return; + } else { + for (i = 0; i < count; i++) { + if (svga->gdcreg[1] & (1 << i)) + vall.b[i] = !!(svga->gdcreg[0] & (1 << i)) * 0xff; + else + vall.b[i] = val; + } + } + break; + case 1: + for (i = 0; i < count; i++) { + if ((svga->adv_flags & FLAG_EXT_WRITE) && (svga->adv_flags & FLAG_ADDR_BY8)) { + if (writemask2 & (0x80 >> i)) + svga->vram[addr | i] = svga->latch.b[i]; + } else { + if (writemask2 & (1 << i)) + svga->vram[addr | i] = svga->latch.b[i]; + } + } + return; + case 2: + for (i = 0; i < count; i++) + vall.b[i] = !!(val & (1 << i)) * 0xff; - if (!(svga->gdcreg[3] & 0x18) && (!svga->gdcreg[1] || svga->set_reset_disabled)) { - for (i = 0; i < count; i++) { - if ((svga->adv_flags & FLAG_EXT_WRITE) && (svga->adv_flags & FLAG_ADDR_BY8)) { - if (writemask2 & (0x80 >> i)) - svga->vram[addr | i] = (vall.b[i] & svga->gdcreg[8]) | (svga->latch.b[i] & ~svga->gdcreg[8]); - } else { - if (writemask2 & (1 << i)) - svga->vram[addr | i] = (vall.b[i] & svga->gdcreg[8]) | (svga->latch.b[i] & ~svga->gdcreg[8]); - } - } - return; - } - break; - case 3: - val = ((val >> (svga->gdcreg[3] & 7)) | (val << (8 - (svga->gdcreg[3] & 7)))); - wm = svga->gdcreg[8]; - svga->gdcreg[8] &= val; + if (!(svga->gdcreg[3] & 0x18) && (!svga->gdcreg[1] || svga->set_reset_disabled)) { + for (i = 0; i < count; i++) { + if ((svga->adv_flags & FLAG_EXT_WRITE) && (svga->adv_flags & FLAG_ADDR_BY8)) { + if (writemask2 & (0x80 >> i)) + svga->vram[addr | i] = (vall.b[i] & svga->gdcreg[8]) | (svga->latch.b[i] & ~svga->gdcreg[8]); + } else { + if (writemask2 & (1 << i)) + svga->vram[addr | i] = (vall.b[i] & svga->gdcreg[8]) | (svga->latch.b[i] & ~svga->gdcreg[8]); + } + } + return; + } + break; + case 3: + val = ((val >> (svga->gdcreg[3] & 7)) | (val << (8 - (svga->gdcreg[3] & 7)))); + wm = svga->gdcreg[8]; + svga->gdcreg[8] &= val; - for (i = 0; i < count; i++) - vall.b[i] = !!(svga->gdcreg[0] & (1 << i)) * 0xff; + for (i = 0; i < count; i++) + vall.b[i] = !!(svga->gdcreg[0] & (1 << i)) * 0xff; - reset_wm = 1; - break; - default: - if (svga->ven_write) - svga->ven_write(svga, val, addr); - return; + reset_wm = 1; + break; + default: + if (svga->ven_write) + svga->ven_write(svga, val, addr); + return; } switch (svga->gdcreg[3] & 0x18) { - case 0x00: /* Set */ - for (i = 0; i < count; i++) { - if ((svga->adv_flags & FLAG_EXT_WRITE) && (svga->adv_flags & FLAG_ADDR_BY8)) { - if (writemask2 & (0x80 >> i)) - svga->vram[addr | i] = (vall.b[i] & svga->gdcreg[8]) | (svga->latch.b[i] & ~svga->gdcreg[8]); - } else { - if (writemask2 & (1 << i)) - svga->vram[addr | i] = (vall.b[i] & svga->gdcreg[8]) | (svga->latch.b[i] & ~svga->gdcreg[8]); - } - } - break; - case 0x08: /* AND */ - for (i = 0; i < count; i++) { - if ((svga->adv_flags & FLAG_EXT_WRITE) && (svga->adv_flags & FLAG_ADDR_BY8)) { - if (writemask2 & (0x80 >> i)) - svga->vram[addr | i] = (vall.b[i] | ~svga->gdcreg[8]) & svga->latch.b[i]; - } else { - if (writemask2 & (1 << i)) - svga->vram[addr | i] = (vall.b[i] | ~svga->gdcreg[8]) & svga->latch.b[i]; - } - } - break; - case 0x10: /* OR */ - for (i = 0; i < count; i++) { - if ((svga->adv_flags & FLAG_EXT_WRITE) && (svga->adv_flags & FLAG_ADDR_BY8)) { - if (writemask2 & (0x80 >> i)) - svga->vram[addr | i] = (vall.b[i] & svga->gdcreg[8]) | svga->latch.b[i]; - } else { - if (writemask2 & (1 << i)) - svga->vram[addr | i] = (vall.b[i] & svga->gdcreg[8]) | svga->latch.b[i]; - } - } - break; - case 0x18: /* XOR */ - for (i = 0; i < count; i++) { - if ((svga->adv_flags & FLAG_EXT_WRITE) && (svga->adv_flags & FLAG_ADDR_BY8)) { - if (writemask2 & (0x80 >> i)) - svga->vram[addr | i] = (vall.b[i] & svga->gdcreg[8]) ^ svga->latch.b[i]; - } else { - if (writemask2 & (1 << i)) - svga->vram[addr | i] = (vall.b[i] & svga->gdcreg[8]) ^ svga->latch.b[i]; - } - } - break; + case 0x00: /* Set */ + for (i = 0; i < count; i++) { + if ((svga->adv_flags & FLAG_EXT_WRITE) && (svga->adv_flags & FLAG_ADDR_BY8)) { + if (writemask2 & (0x80 >> i)) + svga->vram[addr | i] = (vall.b[i] & svga->gdcreg[8]) | (svga->latch.b[i] & ~svga->gdcreg[8]); + } else { + if (writemask2 & (1 << i)) + svga->vram[addr | i] = (vall.b[i] & svga->gdcreg[8]) | (svga->latch.b[i] & ~svga->gdcreg[8]); + } + } + break; + case 0x08: /* AND */ + for (i = 0; i < count; i++) { + if ((svga->adv_flags & FLAG_EXT_WRITE) && (svga->adv_flags & FLAG_ADDR_BY8)) { + if (writemask2 & (0x80 >> i)) + svga->vram[addr | i] = (vall.b[i] | ~svga->gdcreg[8]) & svga->latch.b[i]; + } else { + if (writemask2 & (1 << i)) + svga->vram[addr | i] = (vall.b[i] | ~svga->gdcreg[8]) & svga->latch.b[i]; + } + } + break; + case 0x10: /* OR */ + for (i = 0; i < count; i++) { + if ((svga->adv_flags & FLAG_EXT_WRITE) && (svga->adv_flags & FLAG_ADDR_BY8)) { + if (writemask2 & (0x80 >> i)) + svga->vram[addr | i] = (vall.b[i] & svga->gdcreg[8]) | svga->latch.b[i]; + } else { + if (writemask2 & (1 << i)) + svga->vram[addr | i] = (vall.b[i] & svga->gdcreg[8]) | svga->latch.b[i]; + } + } + break; + case 0x18: /* XOR */ + for (i = 0; i < count; i++) { + if ((svga->adv_flags & FLAG_EXT_WRITE) && (svga->adv_flags & FLAG_ADDR_BY8)) { + if (writemask2 & (0x80 >> i)) + svga->vram[addr | i] = (vall.b[i] & svga->gdcreg[8]) ^ svga->latch.b[i]; + } else { + if (writemask2 & (1 << i)) + svga->vram[addr | i] = (vall.b[i] & svga->gdcreg[8]) ^ svga->latch.b[i]; + } + } + break; + + default: + break; } if (reset_wm) - svga->gdcreg[8] = wm; + svga->gdcreg[8] = wm; } - static __inline uint8_t -svga_read_common(uint32_t addr, uint8_t linear, void *p) +svga_read_common(uint32_t addr, uint8_t linear, void *priv) { - svga_t *svga = (svga_t *)p; + svga_t *svga = (svga_t *) priv; + xga_t *xga = (xga_t *) svga->xga; uint32_t latch_addr = 0; - int readplane = svga->readplane; - uint8_t count, i; - uint8_t plane, pixel; - uint8_t temp, ret; + int readplane = svga->readplane; + uint8_t count; + uint8_t temp; + uint8_t ret; if (svga->adv_flags & FLAG_ADDR_BY8) - readplane = svga->gdcreg[4] & 7; + readplane = svga->gdcreg[4] & 7; - cycles -= video_timing_read_b; + cycles -= svga->monitor->mon_video_timing_read_b; if (!linear) { - addr = svga_decode_addr(svga, addr, 0); + if (xga_active) { + if (((xga->op_mode & 7) >= 4) && (xga->aperture_cntl >= 1)) { + if (xga->test == 0xa5) { /*Memory size test of XGA*/ + if (addr == 0xa0001) { + ret = xga->test; + xga->on = 1; + vga_on = 0; + } else if ((addr == 0xa0000) && (xga->a5_test == 1)) { /*This is required by XGAKIT to pass the memory test*/ + svga_log("A5 test bank = %x.\n", addr); + addr += xga->read_bank; + ret = xga->vram[addr & xga->vram_mask]; + } else { + ret = xga->test; + xga->on = 1; + vga_on = 0; + } + svga_log("A5 read: XGA ON = %d, addr = %05x, ret = %02x, test1 = %x.\n", xga->on, addr, ret, xga->a5_test); + return ret; + } else if (xga->test == 0x5a) { + ret = xga->test; + xga->on = 1; + vga_on = 0; + svga_log("5A read: XGA ON = %d.\n", xga->on); + return ret; + } else if ((addr == 0xa0000) || (addr == 0xa0010)) { + addr += xga->read_bank; + return xga->vram[addr & xga->vram_mask]; + } + } else { + xga->on = 0; + vga_on = 1; + } + } + addr = svga_decode_addr(svga, addr, 0); - if (addr == 0xffffffff) - return 0xff; + if (addr == 0xffffffff) + return 0xff; } count = 2; if (svga->adv_flags & FLAG_LATCH8) - count = 3; + count = 3; latch_addr = (addr << count) & svga->decode_mask; - count = (1 << count); + count = (1 << count); - if (svga->adv_flags & FLAG_ADDR_BY16) - addr <<= 4; + if (svga->adv_flags & FLAG_ADDR_BY16) + addr <<= 4; else if (svga->adv_flags & FLAG_ADDR_BY8) - addr <<= 3; - else if ((svga->chain4 && svga->packed_chain4) || svga->fb_only) { - addr &= svga->decode_mask; - if (svga->translate_address) - addr = svga->translate_address(addr, p); - if (addr >= svga->vram_max) - return 0xff; - latch_addr = (addr & svga->vram_mask) & ~3; - for (i = 0; i < count; i++) - svga->latch.b[i] = svga->vram[latch_addr | i]; - return svga->vram[addr & svga->vram_mask]; - } else if (svga->chain4) { - readplane = addr & 3; - addr = ((addr & 0xfffc) << 2) | ((addr & 0x30000) >> 14) | (addr & ~0x3ffff); + addr <<= 3; + else if ((svga->chain4 && (svga->packed_chain4 || svga->force_old_addr)) || svga->fb_only) { + addr &= svga->decode_mask; + if (svga->translate_address) + addr = svga->translate_address(addr, priv); + 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 if (svga->chain4 && !svga->force_old_addr) { + readplane = addr & 3; + addr = ((addr & 0xfffc) << 2) | ((addr & 0x30000) >> 14) | (addr & ~0x3ffff); } else if (svga->chain2_read) { - readplane = (readplane & 2) | (addr & 1); - addr &= ~1; - addr <<= 2; + readplane = (readplane & 2) | (addr & 1); + addr &= ~1; + addr <<= 2; } else - addr <<= 2; + addr <<= 2; addr &= svga->decode_mask; + if (svga->translate_address) { - latch_addr = svga->translate_address(latch_addr, p); - addr = svga->translate_address(addr, p); + latch_addr = svga->translate_address(latch_addr, priv); + addr = svga->translate_address(addr, priv); } /* standard VGA latched access */ if (latch_addr >= svga->vram_max) { - for (i = 0; i < count; i++) - svga->latch.b[i] = 0xff; + for (uint8_t i = 0; i < count; i++) + svga->latch.b[i] = 0xff; } else { - latch_addr &= svga->vram_mask; + latch_addr &= svga->vram_mask; - for (i = 0; i < count; i++) - svga->latch.b[i] = svga->vram[latch_addr | i]; + for (uint8_t i = 0; i < count; i++) + svga->latch.b[i] = svga->vram[latch_addr | i]; } if (addr >= svga->vram_max) - return 0xff; + return 0xff; addr &= svga->vram_mask; if (svga->readmode) { - temp = 0xff; + temp = 0xff; - for (pixel = 0; pixel < 8; pixel++) { - for (plane = 0; plane < count; plane++) { - if (svga->colournocare & (1 << plane)) { - /* If we care about a plane, and the pixel has a mismatch on it, clear its bit. */ - if (((svga->latch.b[plane] >> pixel) & 1) != ((svga->colourcompare >> plane) & 1)) - temp &= ~(1 << pixel); - } - } - } + for (uint8_t pixel = 0; pixel < 8; pixel++) { + for (uint8_t plane = 0; plane < count; plane++) { + if (svga->colournocare & (1 << plane)) { + /* If we care about a plane, and the pixel has a mismatch on it, clear its bit. */ + if (((svga->latch.b[plane] >> pixel) & 1) != ((svga->colourcompare >> plane) & 1)) + temp &= ~(1 << pixel); + } + } + } - ret = temp; + ret = temp; } else - ret = svga->vram[addr | readplane]; + ret = svga->vram[addr | readplane]; return ret; } +void +svga_write(uint32_t addr, uint8_t val, void *priv) +{ + svga_write_common(addr, val, 0, priv); +} void -svga_write(uint32_t addr, uint8_t val, void *p) +svga_write_linear(uint32_t addr, uint8_t val, void *priv) { - svga_write_common(addr, val, 0, p); + svga_write_common(addr, val, 1, priv); } - -void -svga_write_linear(uint32_t addr, uint8_t val, void *p) -{ - svga_write_common(addr, val, 1, p); -} - - uint8_t -svga_read(uint32_t addr, void *p) +svga_read(uint32_t addr, void *priv) { - return svga_read_common(addr, 0, p); + return svga_read_common(addr, 0, priv); } - uint8_t -svga_read_linear(uint32_t addr, void *p) +svga_read_linear(uint32_t addr, void *priv) { - return svga_read_common(addr, 1, p); + return svga_read_common(addr, 1, priv); } - void svga_doblit(int wx, int wy, svga_t *svga) { - int y_add, x_add, y_start, x_start, bottom; + int y_add; + int x_add; + int y_start; + int x_start; + int bottom; uint32_t *p; - int i, j; - int xs_temp, ys_temp; + int i; + int j; + int xs_temp; + int ys_temp; - y_add = (enable_overscan) ? overscan_y : 0; - x_add = (enable_overscan) ? overscan_x : 0; - y_start = (enable_overscan) ? 0 : (overscan_y >> 1); - x_start = (enable_overscan) ? 0 : (overscan_x >> 1); - bottom = (overscan_y >> 1) + (svga->crtc[8] & 0x1f); + y_add = enable_overscan ? svga->monitor->mon_overscan_y : 0; + x_add = enable_overscan ? svga->monitor->mon_overscan_x : 0; + y_start = enable_overscan ? 0 : (svga->monitor->mon_overscan_y >> 1); + x_start = enable_overscan ? 0 : (svga->monitor->mon_overscan_x >> 1); + bottom = (svga->monitor->mon_overscan_y >> 1) + (svga->crtc[8] & 0x1f); if (svga->vertical_linedbl) { - y_add <<= 1; - y_start <<= 1; - bottom <<= 1; + y_add <<= 1; + y_start <<= 1; + bottom <<= 1; } if ((wx <= 0) || (wy <= 0)) - return; + return; if (svga->vertical_linedbl) - svga->y_add <<= 1; + svga->y_add <<= 1; xs_temp = wx; ys_temp = wy + 1; if (svga->vertical_linedbl) - ys_temp++; + ys_temp++; if (xs_temp < 64) - xs_temp = 640; + xs_temp = 640; if (ys_temp < 32) - ys_temp = 200; + ys_temp = 200; - if ((svga->crtc[0x17] & 0x80) && ((xs_temp != xsize) || (ys_temp != ysize) || video_force_resize_get())) { - /* Screen res has changed.. fix up, and let them know. */ - xsize = xs_temp; - ysize = ys_temp; + if ((svga->crtc[0x17] & 0x80) && ((xs_temp != svga->monitor->mon_xsize) || (ys_temp != svga->monitor->mon_ysize) || video_force_resize_get_monitor(svga->monitor_index))) { + /* Screen res has changed.. fix up, and let them know. */ + svga->monitor->mon_xsize = xs_temp; + svga->monitor->mon_ysize = ys_temp; - if ((xsize > 1984) || (ysize > 2016)) { - /* 2048x2048 is the biggest safe render texture, to account for overscan, - we suppress overscan starting from x 1984 and y 2016. */ - x_add = 0; - y_add = 0; - suppress_overscan = 1; - } else - suppress_overscan = 0; + if ((svga->monitor->mon_xsize > 1984) || (svga->monitor->mon_ysize > 2016)) { + /* 2048x2048 is the biggest safe render texture, to account for overscan, + we suppress overscan starting from x 1984 and y 2016. */ + x_add = 0; + y_add = 0; + suppress_overscan = 1; + } else + suppress_overscan = 0; - /* Block resolution changes while in DPMS mode to avoid getting a bogus - screen width (320). We're already rendering a blank screen anyway. */ - if (!svga->dpms) - set_screen_size(xsize + x_add, ysize + y_add); + /* Block resolution changes while in DPMS mode to avoid getting a bogus + screen width (320). We're already rendering a blank screen anyway. */ + if (!svga->dpms) + set_screen_size_monitor(svga->monitor->mon_xsize + x_add, svga->monitor->mon_ysize + y_add, svga->monitor_index); - if (video_force_resize_get()) - video_force_resize_set(0); + if (video_force_resize_get_monitor(svga->monitor_index)) + video_force_resize_set_monitor(0, svga->monitor_index); } if ((wx >= 160) && ((wy + 1) >= 120)) { - /* Draw (overscan_size - scroll size) lines of overscan on top and bottom. */ - for (i = 0; i < svga->y_add; i++) { - p = &buffer32->line[i & 0x7ff][0]; + /* Draw (overscan_size - scroll size) lines of overscan on top and bottom. */ + for (i = 0; i < svga->y_add; i++) { + p = &svga->monitor->target_buffer->line[i & 0x7ff][0]; - for (j = 0; j < (xsize + x_add); j++) - p[j] = svga->overscan_color; - } + for (j = 0; j < (svga->monitor->mon_xsize + x_add); j++) + p[j] = svga->overscan_color; + } - for (i = 0; i < bottom; i++) { - p = &buffer32->line[(ysize + svga->y_add + i) & 0x7ff][0]; + for (i = 0; i < bottom; i++) { + p = &svga->monitor->target_buffer->line[(svga->monitor->mon_ysize + svga->y_add + i) & 0x7ff][0]; - for (j = 0; j < (xsize + x_add); j++) - p[j] = svga->overscan_color; - } + for (j = 0; j < (svga->monitor->mon_xsize + x_add); j++) + p[j] = svga->overscan_color; + } } - video_blit_memtoscreen(x_start, y_start, xsize + x_add, ysize + y_add); + video_blit_memtoscreen_monitor(x_start, y_start, svga->monitor->mon_xsize + x_add, svga->monitor->mon_ysize + y_add, svga->monitor_index); if (svga->vertical_linedbl) - svga->vertical_linedbl >>= 1; + svga->vertical_linedbl >>= 1; } - void -svga_writeb_linear(uint32_t addr, uint8_t val, void *p) +svga_writeb_linear(uint32_t addr, uint8_t val, void *priv) { - svga_t *svga = (svga_t *)p; + svga_t *svga = (svga_t *) priv; if (!svga->fast) { - svga_write_linear(addr, val, p); - return; + svga_write_linear(addr, val, priv); + return; } addr &= svga->decode_mask; if (addr >= svga->vram_max) - return; + return; addr &= svga->vram_mask; - svga->changedvram[addr >> 12] = changeframecount; - *(uint8_t *)&svga->vram[addr] = val; + svga->changedvram[addr >> 12] = svga->monitor->mon_changeframecount; + svga->vram[addr] = val; } - void -svga_writew_common(uint32_t addr, uint16_t val, uint8_t linear, void *p) +svga_writew_common(uint32_t addr, uint16_t val, uint8_t linear, void *priv) { - svga_t *svga = (svga_t *)p; + svga_t *svga = (svga_t *) priv; if (!svga->fast) { - svga_write_common(addr, val, linear, p); - svga_write_common(addr + 1, val >> 8, linear, p); - return; + svga_write_common(addr, val, linear, priv); + svga_write_common(addr + 1, val >> 8, linear, priv); + return; } - cycles -= video_timing_write_w; + cycles -= svga->monitor->mon_video_timing_write_w; if (!linear) { - addr = svga_decode_addr(svga, addr, 1); + addr = svga_decode_addr(svga, addr, 1); - if (addr == 0xffffffff) - return; - } - - addr &= svga->decode_mask; - if(svga->translate_address) { - uint32_t addr2 = svga->translate_address(addr, p); - if (addr2 < svga->vram_max) { - svga->vram[addr2 & svga->vram_mask] = val & 0xff; - svga->changedvram[addr2 >> 12] = changeframecount; - } - addr2 = svga->translate_address(addr+1, p); - if (addr2 < svga->vram_max) { - svga->vram[addr2 & svga->vram_mask] = (val >> 8) & 0xff; - svga->changedvram[addr2 >> 12] = changeframecount; - } - return; - } - if (addr >= svga->vram_max) - return; - addr &= svga->vram_mask; - - svga->changedvram[addr >> 12] = changeframecount; - *(uint16_t *)&svga->vram[addr] = val; -} - - -void -svga_writew(uint32_t addr, uint16_t val, void *p) -{ - svga_writew_common(addr, val, 0, p); -} - - -void -svga_writew_linear(uint32_t addr, uint16_t val, void *p) -{ - svga_writew_common(addr, val, 1, p); -} - - -void -svga_writel_common(uint32_t addr, uint32_t val, uint8_t linear, void *p) -{ - svga_t *svga = (svga_t *)p; - - if (!svga->fast) { - svga_write_common(addr, val, linear, p); - svga_write_common(addr + 1, val >> 8, linear, p); - svga_write_common(addr + 2, val >> 16, linear, p); - svga_write_common(addr + 3, val >> 24, linear, p); - return; - } - - cycles -= video_timing_write_l; - - if (!linear) { - addr = svga_decode_addr(svga, addr, 1); - - if (addr == 0xffffffff) - return; + if (addr == 0xffffffff) + return; } addr &= svga->decode_mask; if (svga->translate_address) { - uint32_t addr2 = svga->translate_address(addr, p); - if (addr2 < svga->vram_max) { - svga->vram[addr2 & svga->vram_mask] = val & 0xff; - svga->changedvram[addr2 >> 12] = changeframecount; - } - addr2 = svga->translate_address(addr+1, p); - if (addr2 < svga->vram_max) { - svga->vram[addr2 & svga->vram_mask] = (val >> 8) & 0xff; - svga->changedvram[addr2 >> 12] = changeframecount; - } - addr2 = svga->translate_address(addr+2, p); - if (addr2 < svga->vram_max) { - svga->vram[addr2 & svga->vram_mask] = (val >> 16) & 0xff; - svga->changedvram[addr2 >> 12] = changeframecount; - } - addr2 = svga->translate_address(addr+3, p); - if (addr2 < svga->vram_max) { - svga->vram[addr2 & svga->vram_mask] = (val >> 24) & 0xff; - svga->changedvram[addr2 >> 12] = changeframecount; - } - return; + uint32_t addr2 = svga->translate_address(addr, priv); + if (addr2 < svga->vram_max) { + svga->vram[addr2 & svga->vram_mask] = val & 0xff; + svga->changedvram[addr2 >> 12] = svga->monitor->mon_changeframecount; + } + addr2 = svga->translate_address(addr + 1, priv); + if (addr2 < svga->vram_max) { + svga->vram[addr2 & svga->vram_mask] = (val >> 8) & 0xff; + svga->changedvram[addr2 >> 12] = svga->monitor->mon_changeframecount; + } + return; } if (addr >= svga->vram_max) - return; + return; addr &= svga->vram_mask; - svga->changedvram[addr >> 12] = changeframecount; - *(uint32_t *)&svga->vram[addr] = val; + svga->changedvram[addr >> 12] = svga->monitor->mon_changeframecount; + *(uint16_t *) &svga->vram[addr] = val; } - void -svga_writel(uint32_t addr, uint32_t val, void *p) +svga_writew(uint32_t addr, uint16_t val, void *priv) { - svga_writel_common(addr, val, 0, p); + svga_writew_common(addr, val, 0, priv); } - void -svga_writel_linear(uint32_t addr, uint32_t val, void *p) +svga_writew_linear(uint32_t addr, uint16_t val, void *priv) { - svga_writel_common(addr, val, 1, p); + svga_writew_common(addr, val, 1, priv); } +void +svga_writel_common(uint32_t addr, uint32_t val, uint8_t linear, void *priv) +{ + svga_t *svga = (svga_t *) priv; + + if (!svga->fast) { + svga_write_common(addr, val, linear, priv); + svga_write_common(addr + 1, val >> 8, linear, priv); + svga_write_common(addr + 2, val >> 16, linear, priv); + svga_write_common(addr + 3, val >> 24, linear, priv); + return; + } + + cycles -= svga->monitor->mon_video_timing_write_l; + + if (!linear) { + addr = svga_decode_addr(svga, addr, 1); + + if (addr == 0xffffffff) + return; + } + + addr &= svga->decode_mask; + if (svga->translate_address) { + uint32_t addr2 = svga->translate_address(addr, priv); + if (addr2 < svga->vram_max) { + svga->vram[addr2 & svga->vram_mask] = val & 0xff; + svga->changedvram[addr2 >> 12] = svga->monitor->mon_changeframecount; + } + addr2 = svga->translate_address(addr + 1, priv); + if (addr2 < svga->vram_max) { + svga->vram[addr2 & svga->vram_mask] = (val >> 8) & 0xff; + svga->changedvram[addr2 >> 12] = svga->monitor->mon_changeframecount; + } + addr2 = svga->translate_address(addr + 2, priv); + if (addr2 < svga->vram_max) { + svga->vram[addr2 & svga->vram_mask] = (val >> 16) & 0xff; + svga->changedvram[addr2 >> 12] = svga->monitor->mon_changeframecount; + } + addr2 = svga->translate_address(addr + 3, priv); + if (addr2 < svga->vram_max) { + svga->vram[addr2 & svga->vram_mask] = (val >> 24) & 0xff; + svga->changedvram[addr2 >> 12] = svga->monitor->mon_changeframecount; + } + return; + } + if (addr >= svga->vram_max) + return; + addr &= svga->vram_mask; + + svga->changedvram[addr >> 12] = svga->monitor->mon_changeframecount; + *(uint32_t *) &svga->vram[addr] = val; +} + +void +svga_writel(uint32_t addr, uint32_t val, void *priv) +{ + svga_writel_common(addr, val, 0, priv); +} + +void +svga_writel_linear(uint32_t addr, uint32_t val, void *priv) +{ + svga_writel_common(addr, val, 1, priv); +} uint8_t -svga_readb_linear(uint32_t addr, void *p) +svga_readb_linear(uint32_t addr, void *priv) { - svga_t *svga = (svga_t *)p; + const svga_t *svga = (svga_t *) priv; if (!svga->fast) - return svga_read_linear(addr, p); + return svga_read_linear(addr, priv); addr &= svga->decode_mask; if (addr >= svga->vram_max) - return 0xff; + return 0xff; - return *(uint8_t *)&svga->vram[addr & svga->vram_mask]; + return svga->vram[addr & svga->vram_mask]; } - uint16_t -svga_readw_common(uint32_t addr, uint8_t linear, void *p) +svga_readw_common(uint32_t addr, uint8_t linear, void *priv) { - svga_t *svga = (svga_t *)p; + svga_t *svga = (svga_t *) priv; if (!svga->fast) - return svga_read_common(addr, linear, p) | (svga_read_common(addr + 1, linear, p) << 8); + return svga_read_common(addr, linear, priv) | (svga_read_common(addr + 1, linear, priv) << 8); - cycles -= video_timing_read_w; + cycles -= svga->monitor->mon_video_timing_read_w; if (!linear) { - addr = svga_decode_addr(svga, addr, 0); + addr = svga_decode_addr(svga, addr, 0); - if (addr == 0xffffffff) - return 0xffff; + if (addr == 0xffffffff) + return 0xffff; } addr &= svga->decode_mask; if (svga->translate_address) { - uint8_t val1 = 0xff, val2 = 0xff; - uint32_t addr2 = svga->translate_address(addr, p); - if (addr2 < svga->vram_max) - val1 = svga->vram[addr2 & svga->vram_mask]; - addr2 = svga->translate_address(addr+1, p); - if (addr2 < svga->vram_max) - val2 = svga->vram[addr2 & svga->vram_mask]; - return (val2 << 8) | val1; + uint8_t val1 = 0xff; + uint8_t val2 = 0xff; + uint32_t addr2 = svga->translate_address(addr, priv); + if (addr2 < svga->vram_max) + val1 = svga->vram[addr2 & svga->vram_mask]; + addr2 = svga->translate_address(addr + 1, priv); + if (addr2 < svga->vram_max) + val2 = svga->vram[addr2 & svga->vram_mask]; + return (val2 << 8) | val1; } if (addr >= svga->vram_max) - return 0xffff; + return 0xffff; - return *(uint16_t *)&svga->vram[addr & svga->vram_mask]; + return *(uint16_t *) &svga->vram[addr & svga->vram_mask]; } - uint16_t -svga_readw(uint32_t addr, void *p) +svga_readw(uint32_t addr, void *priv) { - return svga_readw_common(addr, 0, p); + return svga_readw_common(addr, 0, priv); } - uint16_t -svga_readw_linear(uint32_t addr, void *p) +svga_readw_linear(uint32_t addr, void *priv) { - return svga_readw_common(addr, 1, p); + return svga_readw_common(addr, 1, priv); } - uint32_t -svga_readl_common(uint32_t addr, uint8_t linear, void *p) +svga_readl_common(uint32_t addr, uint8_t linear, void *priv) { - svga_t *svga = (svga_t *)p; + svga_t *svga = (svga_t *) priv; if (!svga->fast) { - return svga_read_common(addr, linear, p) | (svga_read_common(addr + 1, linear, p) << 8) | - (svga_read_common(addr + 2, linear, p) << 16) | (svga_read_common(addr + 3, linear, p) << 24); + return svga_read_common(addr, linear, priv) | (svga_read_common(addr + 1, linear, priv) << 8) | (svga_read_common(addr + 2, linear, priv) << 16) | (svga_read_common(addr + 3, linear, priv) << 24); } - cycles -= video_timing_read_l; + cycles -= svga->monitor->mon_video_timing_read_l; if (!linear) { - addr = svga_decode_addr(svga, addr, 0); + addr = svga_decode_addr(svga, addr, 0); - if (addr == 0xffffffff) - return 0xffffffff; + if (addr == 0xffffffff) + return 0xffffffff; } addr &= svga->decode_mask; if (svga->translate_address) { - uint8_t val1 = 0xff, val2 = 0xff, val3 = 0xff, val4 = 0xff; - uint32_t addr2 = svga->translate_address(addr, p); - if (addr2 < svga->vram_max) - val1 = svga->vram[addr2 & svga->vram_mask]; - addr2 = svga->translate_address(addr+1, p); - if (addr2 < svga->vram_max) - val2 = svga->vram[addr2 & svga->vram_mask]; - addr2 = svga->translate_address(addr+2, p); - if (addr2 < svga->vram_max) - val3 = svga->vram[addr2 & svga->vram_mask]; - addr2 = svga->translate_address(addr+3, p); - if (addr2 < svga->vram_max) - val4 = svga->vram[addr2 & svga->vram_mask]; - return (val4 << 24) | (val3 << 16) | (val2 << 8) | val1; + uint8_t val1 = 0xff; + uint8_t val2 = 0xff; + uint8_t val3 = 0xff; + uint8_t val4 = 0xff; + uint32_t addr2 = svga->translate_address(addr, priv); + if (addr2 < svga->vram_max) + val1 = svga->vram[addr2 & svga->vram_mask]; + addr2 = svga->translate_address(addr + 1, priv); + if (addr2 < svga->vram_max) + val2 = svga->vram[addr2 & svga->vram_mask]; + addr2 = svga->translate_address(addr + 2, priv); + if (addr2 < svga->vram_max) + val3 = svga->vram[addr2 & svga->vram_mask]; + addr2 = svga->translate_address(addr + 3, priv); + if (addr2 < svga->vram_max) + val4 = svga->vram[addr2 & svga->vram_mask]; + return (val4 << 24) | (val3 << 16) | (val2 << 8) | val1; } if (addr >= svga->vram_max) - return 0xffffffff; + return 0xffffffff; - return *(uint32_t *)&svga->vram[addr & svga->vram_mask]; + return *(uint32_t *) &svga->vram[addr & svga->vram_mask]; } - uint32_t -svga_readl(uint32_t addr, void *p) +svga_readl(uint32_t addr, void *priv) { - return svga_readl_common(addr, 0, p); + return svga_readl_common(addr, 0, priv); } - uint32_t -svga_readl_linear(uint32_t addr, void *p) +svga_readl_linear(uint32_t addr, void *priv) { - return svga_readl_common(addr, 1, p); + return svga_readl_common(addr, 1, priv); } diff --git a/src/video/vid_svga_render.c b/src/video/vid_svga_render.c index 7cd9fa8b1..c9369f09c 100644 --- a/src/video/vid_svga_render.c +++ b/src/video/vid_svga_render.c @@ -1,20 +1,20 @@ /* - * 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. + * 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. + * This file is part of the 86Box distribution. * - * SVGA renderers. + * SVGA renderers. * * * - * Authors: Sarah Walker, - * Miran Grca, + * Authors: Sarah Walker, + * Miran Grca, * - * Copyright 2008-2019 Sarah Walker. - * Copyright 2016-2019 Miran Grca. + * Copyright 2008-2019 Sarah Walker. + * Copyright 2016-2019 Miran Grca. */ #include #include @@ -33,1450 +33,1846 @@ void svga_render_null(svga_t *svga) { if ((svga->displine + svga->y_add) < 0) - return; + return; - if (svga->firstline_draw == 2000) - svga->firstline_draw = svga->displine; - svga->lastline_draw = svga->displine; + if (svga->firstline_draw == 2000) + svga->firstline_draw = svga->displine; + svga->lastline_draw = svga->displine; } void svga_render_blank(svga_t *svga) { - int x, xx; - if ((svga->displine + svga->y_add) < 0) - return; + return; - if (svga->firstline_draw == 2000) - svga->firstline_draw = svga->displine; + if (svga->firstline_draw == 2000) + svga->firstline_draw = svga->displine; svga->lastline_draw = svga->displine; - for (x = 0; x < (svga->hdisp + svga->scrollcache); x++) { - switch (svga->seqregs[1] & 9) { - case 0: - for (xx = 0; xx < 9; xx++) - buffer32->line[svga->displine + svga->y_add][svga->x_add + (x * 9) + xx] = 0x00000000; - break; - case 1: - for (xx = 0; xx < 8; xx++) - buffer32->line[svga->displine + svga->y_add][svga->x_add + (x * 8) + xx] = 0x00000000; - break; - case 8: - for (xx = 0; xx < 18; xx++) - buffer32->line[svga->displine + svga->y_add][svga->x_add + (x * 18) + xx] = 0x00000000; - break; - case 9: - for (xx = 0; xx < 16; xx++) - buffer32->line[svga->displine + svga->y_add][svga->x_add + (x * 16) + xx] = 0x00000000; - break; - } - } -} + uint32_t char_width = 0; + switch (svga->seqregs[1] & 9) { + case 0: + char_width = 9; + break; + case 1: + char_width = 8; + break; + case 8: + char_width = 18; + break; + case 9: + char_width = 16; + break; + + default: + break; + } + + uint32_t *line_ptr = &svga->monitor->target_buffer->line[svga->displine + svga->y_add][svga->x_add]; + uint32_t line_width = (uint32_t) (svga->hdisp + svga->scrollcache) * char_width * sizeof(uint32_t); + memset(line_ptr, 0, line_width); +} void svga_render_overscan_left(svga_t *svga) { - int i; - if ((svga->displine + svga->y_add) < 0) - return; + return; if (svga->scrblank || (svga->hdisp == 0)) - return; + return; - for (i = 0; i < svga->x_add; i++) - buffer32->line[svga->displine + svga->y_add][i] = svga->overscan_color; + uint32_t *line_ptr = svga->monitor->target_buffer->line[svga->displine + svga->y_add]; + for (int i = 0; i < svga->x_add; i++) + *line_ptr++ = svga->overscan_color; } - void svga_render_overscan_right(svga_t *svga) { - int i, right; + int right; if ((svga->displine + svga->y_add) < 0) - return; + return; if (svga->scrblank || (svga->hdisp == 0)) - return; + return; - right = (overscan_x >> 1); - for (i = 0; i < right; i++) - buffer32->line[svga->displine + svga->y_add][svga->x_add + svga->hdisp + i] = svga->overscan_color; + uint32_t *line_ptr = &svga->monitor->target_buffer->line[svga->displine + svga->y_add][svga->x_add + svga->hdisp]; + right = (overscan_x >> 1); + for (int i = 0; i < right; i++) + *line_ptr++ = svga->overscan_color; } - void svga_render_text_40(svga_t *svga) -{ +{ uint32_t *p; - int x, xx; - int drawcursor, xinc; - uint8_t chr, attr, dat; - uint32_t charaddr; - int fg, bg; + int xx; + int drawcursor; + int xinc; + uint8_t chr; + uint8_t attr; + uint8_t dat; + uint32_t charaddr; + int fg; + int bg; + uint32_t addr = 0; if ((svga->displine + svga->y_add) < 0) - return; + return; - if (svga->firstline_draw == 2000) - svga->firstline_draw = svga->displine; + if (svga->firstline_draw == 2000) + svga->firstline_draw = svga->displine; svga->lastline_draw = svga->displine; if (svga->fullchange) { - p = &buffer32->line[svga->displine + svga->y_add][svga->x_add]; - xinc = (svga->seqregs[1] & 1) ? 16 : 18; + p = &svga->monitor->target_buffer->line[svga->displine + svga->y_add][svga->x_add]; + xinc = (svga->seqregs[1] & 1) ? 16 : 18; - for (x = 0; x < (svga->hdisp + svga->scrollcache); x += xinc) { - uint32_t addr = svga->remap_func(svga, svga->ma) & svga->vram_display_mask; - - drawcursor = ((svga->ma == svga->ca) && svga->con && svga->cursoron); + for (int x = 0; x < (svga->hdisp + svga->scrollcache); x += xinc) { + if (!svga->force_old_addr) + addr = svga->remap_func(svga, svga->ma) & svga->vram_display_mask; - if (svga->crtc[0x17] & 0x80) { - chr = svga->vram[addr]; - attr = svga->vram[addr+1]; - } else - chr = attr = 0; + drawcursor = ((svga->ma == svga->ca) && svga->con && svga->cursoron); - if (attr & 8) charaddr = svga->charsetb + (chr * 128); - else charaddr = svga->charseta + (chr * 128); + if (svga->force_old_addr) { + chr = svga->vram[(svga->ma << 1) & svga->vram_display_mask]; + attr = svga->vram[((svga->ma << 1) + 1) & svga->vram_display_mask]; + } else { + chr = svga->vram[addr]; + attr = svga->vram[addr + 1]; + } - if (drawcursor) { - bg = svga->pallook[svga->egapal[attr & 15]]; - fg = svga->pallook[svga->egapal[attr >> 4]]; - } else { - fg = svga->pallook[svga->egapal[attr & 15]]; - bg = svga->pallook[svga->egapal[attr >> 4]]; + if (attr & 8) + charaddr = svga->charsetb + (chr * 128); + else + charaddr = svga->charseta + (chr * 128); - if (attr & 0x80 && svga->attrregs[0x10] & 8) { - bg = svga->pallook[svga->egapal[(attr >> 4) & 7]]; - if (svga->blink & 16) - fg = bg; - } - } + if (drawcursor) { + bg = svga->pallook[svga->egapal[attr & 15]]; + fg = svga->pallook[svga->egapal[attr >> 4]]; + } else { + fg = svga->pallook[svga->egapal[attr & 15]]; + bg = svga->pallook[svga->egapal[attr >> 4]]; - dat = svga->vram[charaddr + (svga->sc << 2)]; - if (svga->seqregs[1] & 1) { - for (xx = 0; xx < 16; xx += 2) - p[xx] = p[xx + 1] = (dat & (0x80 >> (xx >> 1))) ? fg : bg; - } else { - for (xx = 0; xx < 16; xx += 2) - p[xx] = p[xx + 1] = (dat & (0x80 >> (xx >> 1))) ? fg : bg; - if ((chr & ~0x1f) != 0xc0 || !(svga->attrregs[0x10] & 4)) - p[16] = p[17] = bg; - else - p[16] = p[17] = (dat & 1) ? fg : bg; - } - svga->ma += 4; - p += xinc; - } - svga->ma &= svga->vram_display_mask; + if (attr & 0x80 && svga->attrregs[0x10] & 8) { + bg = svga->pallook[svga->egapal[(attr >> 4) & 7]]; + if (svga->blink & 16) + fg = bg; + } + } + + dat = svga->vram[charaddr + (svga->sc << 2)]; + if (svga->seqregs[1] & 1) { + for (xx = 0; xx < 16; xx += 2) + p[xx] = p[xx + 1] = (dat & (0x80 >> (xx >> 1))) ? fg : bg; + } else { + for (xx = 0; xx < 16; xx += 2) + p[xx] = p[xx + 1] = (dat & (0x80 >> (xx >> 1))) ? fg : bg; + if ((chr & ~0x1f) != 0xc0 || !(svga->attrregs[0x10] & 4)) + p[16] = p[17] = bg; + else + p[16] = p[17] = (dat & 1) ? fg : bg; + } + svga->ma += 4; + p += xinc; + } + svga->ma &= svga->vram_display_mask; } } - void svga_render_text_80(svga_t *svga) { uint32_t *p; - int x, xx; - int drawcursor, xinc; - uint8_t chr, attr, dat; - uint32_t charaddr; - int fg, bg; + int xx; + int drawcursor; + int xinc; + uint8_t chr; + uint8_t attr; + uint8_t dat; + uint32_t charaddr; + int fg; + int bg; + uint32_t addr = 0; if ((svga->displine + svga->y_add) < 0) - return; + return; - if (svga->firstline_draw == 2000) - svga->firstline_draw = svga->displine; + if (svga->firstline_draw == 2000) + svga->firstline_draw = svga->displine; svga->lastline_draw = svga->displine; if (svga->fullchange) { - p = &buffer32->line[svga->displine + svga->y_add][svga->x_add]; - xinc = (svga->seqregs[1] & 1) ? 8 : 9; + p = &svga->monitor->target_buffer->line[svga->displine + svga->y_add][svga->x_add]; + xinc = (svga->seqregs[1] & 1) ? 8 : 9; - for (x = 0; x < (svga->hdisp + svga->scrollcache); x += xinc) { - uint32_t addr = svga->remap_func(svga, svga->ma) & svga->vram_display_mask; - - drawcursor = ((svga->ma == svga->ca) && svga->con && svga->cursoron); + for (int x = 0; x < (svga->hdisp + svga->scrollcache); x += xinc) { + if (!svga->force_old_addr) + addr = svga->remap_func(svga, svga->ma) & svga->vram_display_mask; - if (svga->crtc[0x17] & 0x80) { - chr = svga->vram[addr]; - attr = svga->vram[addr+1]; - } else - chr = attr = 0; + drawcursor = ((svga->ma == svga->ca) && svga->con && svga->cursoron); - if (attr & 8) charaddr = svga->charsetb + (chr * 128); - else charaddr = svga->charseta + (chr * 128); + if (svga->force_old_addr) { + chr = svga->vram[(svga->ma << 1) & svga->vram_display_mask]; + attr = svga->vram[((svga->ma << 1) + 1) & svga->vram_display_mask]; + } else { + chr = svga->vram[addr]; + attr = svga->vram[addr + 1]; + } - if (drawcursor) { - bg = svga->pallook[svga->egapal[attr & 15]]; - fg = svga->pallook[svga->egapal[attr >> 4]]; - } else { - fg = svga->pallook[svga->egapal[attr & 15]]; - bg = svga->pallook[svga->egapal[attr >> 4]]; - if (attr & 0x80 && svga->attrregs[0x10] & 8) { - bg = svga->pallook[svga->egapal[(attr >> 4) & 7]]; - if (svga->blink & 16) - fg = bg; - } - } + if (attr & 8) + charaddr = svga->charsetb + (chr * 128); + else + charaddr = svga->charseta + (chr * 128); - dat = svga->vram[charaddr + (svga->sc << 2)]; - if (svga->seqregs[1] & 1) { - for (xx = 0; xx < 8; xx++) - p[xx] = (dat & (0x80 >> xx)) ? fg : bg; - } else { - for (xx = 0; xx < 8; xx++) - p[xx] = (dat & (0x80 >> xx)) ? fg : bg; - if ((chr & ~0x1F) != 0xC0 || !(svga->attrregs[0x10] & 4)) - p[8] = bg; - else - p[8] = (dat & 1) ? fg : bg; - } - svga->ma += 4; - p += xinc; - } - svga->ma &= svga->vram_display_mask; + if (drawcursor) { + bg = svga->pallook[svga->egapal[attr & 15]]; + fg = svga->pallook[svga->egapal[attr >> 4]]; + } else { + fg = svga->pallook[svga->egapal[attr & 15]]; + bg = svga->pallook[svga->egapal[attr >> 4]]; + if (attr & 0x80 && svga->attrregs[0x10] & 8) { + bg = svga->pallook[svga->egapal[(attr >> 4) & 7]]; + if (svga->blink & 16) + fg = bg; + } + } + + dat = svga->vram[charaddr + (svga->sc << 2)]; + if (svga->seqregs[1] & 1) { + for (xx = 0; xx < 8; xx++) + p[xx] = (dat & (0x80 >> xx)) ? fg : bg; + } else { + for (xx = 0; xx < 8; xx++) + p[xx] = (dat & (0x80 >> xx)) ? fg : bg; + if ((chr & ~0x1F) != 0xC0 || !(svga->attrregs[0x10] & 4)) + p[8] = bg; + else + p[8] = (dat & 1) ? fg : bg; + } + svga->ma += 4; + p += xinc; + } + svga->ma &= svga->vram_display_mask; } } - +/*Not available on most generic cards.*/ void svga_render_text_80_ksc5601(svga_t *svga) { uint32_t *p; - int x, xx; - int drawcursor, xinc; - uint8_t chr, attr, dat, nextchr; - uint32_t charaddr; - int fg, bg; + int xx; + int drawcursor; + int xinc; + uint8_t chr; + uint8_t attr; + uint8_t dat; + uint8_t nextchr; + uint32_t charaddr; + int fg; + int bg; if ((svga->displine + svga->y_add) < 0) - return; + return; - if (svga->firstline_draw == 2000) - svga->firstline_draw = svga->displine; + if (svga->firstline_draw == 2000) + svga->firstline_draw = svga->displine; svga->lastline_draw = svga->displine; if (svga->fullchange) { - p = &buffer32->line[svga->displine + svga->y_add][svga->x_add]; + p = &svga->monitor->target_buffer->line[svga->displine + svga->y_add][svga->x_add]; - xinc = (svga->seqregs[1] & 1) ? 8 : 9; + xinc = (svga->seqregs[1] & 1) ? 8 : 9; - for (x = 0; x < (svga->hdisp + svga->scrollcache); x += xinc) { - uint32_t addr = svga->remap_func(svga, svga->ma) & svga->vram_display_mask; - drawcursor = ((svga->ma == svga->ca) && svga->con && svga->cursoron); - chr = svga->vram[addr]; - nextchr = svga->vram[addr + 8]; - if (svga->crtc[0x17] & 0x80) - attr = svga->vram[addr + 1]; - else - attr = 0; + for (int x = 0; x < (svga->hdisp + svga->scrollcache); x += xinc) { + uint32_t addr = svga->remap_func(svga, svga->ma) & svga->vram_display_mask; + drawcursor = ((svga->ma == svga->ca) && svga->con && svga->cursoron); + chr = svga->vram[addr]; + nextchr = svga->vram[addr + 8]; + attr = svga->vram[addr + 1]; - if (drawcursor) { - bg = svga->pallook[svga->egapal[attr & 15]]; - fg = svga->pallook[svga->egapal[attr >> 4]]; - } else { - fg = svga->pallook[svga->egapal[attr & 15]]; - bg = svga->pallook[svga->egapal[attr >> 4]]; - if (attr & 0x80 && svga->attrregs[0x10] & 8) { - bg = svga->pallook[svga->egapal[(attr >> 4) & 7]]; - if (svga->blink & 16) - fg = bg; - } - } + if (drawcursor) { + bg = svga->pallook[svga->egapal[attr & 15]]; + fg = svga->pallook[svga->egapal[attr >> 4]]; + } else { + fg = svga->pallook[svga->egapal[attr & 15]]; + bg = svga->pallook[svga->egapal[attr >> 4]]; + if (attr & 0x80 && svga->attrregs[0x10] & 8) { + bg = svga->pallook[svga->egapal[(attr >> 4) & 7]]; + if (svga->blink & 16) + fg = bg; + } + } - if ((x + xinc) < svga->hdisp && (chr & (nextchr | svga->ksc5601_sbyte_mask) & 0x80)) { - if ((chr == svga->ksc5601_udc_area_msb[0] || chr == svga->ksc5601_udc_area_msb[1]) && (nextchr > 0xa0 && nextchr < 0xff)) - dat = fontdatksc5601_user[(chr == svga->ksc5601_udc_area_msb[1] ? 96 : 0) + (nextchr & 0x7F) - 0x20].chr[svga->sc]; - else if (nextchr & 0x80) { - if (svga->ksc5601_swap_mode == 1 && (nextchr > 0xa0 && nextchr < 0xff)) { - if(chr >= 0x80 && chr < 0x99) chr += 0x30; - else if(chr >= 0xB0 && chr < 0xC9) chr -= 0x30; - } - dat = fontdatksc5601[((chr & 0x7F) << 7) | (nextchr & 0x7F)].chr[svga->sc]; - } else - dat = 0xff; - } else { - if (attr & 8) charaddr = svga->charsetb + (chr * 128); - else charaddr = svga->charseta + (chr * 128); + if ((x + xinc) < svga->hdisp && (chr & (nextchr | svga->ksc5601_sbyte_mask) & 0x80)) { + if ((chr == svga->ksc5601_udc_area_msb[0] || chr == svga->ksc5601_udc_area_msb[1]) && (nextchr > 0xa0 && nextchr < 0xff)) + dat = fontdatksc5601_user[(chr == svga->ksc5601_udc_area_msb[1] ? 96 : 0) + (nextchr & 0x7F) - 0x20].chr[svga->sc]; + else if (nextchr & 0x80) { + if (svga->ksc5601_swap_mode == 1 && (nextchr > 0xa0 && nextchr < 0xff)) { + if (chr >= 0x80 && chr < 0x99) + chr += 0x30; + else if (chr >= 0xB0 && chr < 0xC9) + chr -= 0x30; + } + dat = fontdatksc5601[((chr & 0x7F) << 7) | (nextchr & 0x7F)].chr[svga->sc]; + } else + dat = 0xff; + } else { + if (attr & 8) + charaddr = svga->charsetb + (chr * 128); + else + charaddr = svga->charseta + (chr * 128); - if ((svga->ksc5601_english_font_type >> 8) == 1) - dat = fontdatksc5601[((svga->ksc5601_english_font_type & 0x7F) << 7) | (chr >> 1)].chr[((chr & 1) << 4) | svga->sc]; - else - dat = svga->vram[charaddr + (svga->sc << 2)]; - } + if ((svga->ksc5601_english_font_type >> 8) == 1) + dat = fontdatksc5601[((svga->ksc5601_english_font_type & 0x7F) << 7) | (chr >> 1)].chr[((chr & 1) << 4) | svga->sc]; + else + dat = svga->vram[charaddr + (svga->sc << 2)]; + } - if (svga->seqregs[1] & 1) { - for (xx = 0; xx < 8; xx++) - p[xx] = (dat & (0x80 >> xx)) ? fg : bg; - } else { - for (xx = 0; xx < 8; xx++) - p[xx] = (dat & (0x80 >> xx)) ? fg : bg; - if (((chr & ~0x1f) != 0xc0) || !(svga->attrregs[0x10] & 4)) - p[8] = bg; - else - p[8] = (dat & 1) ? fg : bg; - } - svga->ma += 4; - p += xinc; + if (svga->seqregs[1] & 1) { + for (xx = 0; xx < 8; xx++) + p[xx] = (dat & (0x80 >> xx)) ? fg : bg; + } else { + for (xx = 0; xx < 8; xx++) + p[xx] = (dat & (0x80 >> xx)) ? fg : bg; + if (((chr & ~0x1f) != 0xc0) || !(svga->attrregs[0x10] & 4)) + p[8] = bg; + else + p[8] = (dat & 1) ? fg : bg; + } + svga->ma += 4; + p += xinc; - if ((x + xinc) < svga->hdisp && (chr & (nextchr | svga->ksc5601_sbyte_mask) & 0x80)) { - attr = svga->vram[((svga->ma << 1) + 1) & svga->vram_display_mask]; + if ((x + xinc) < svga->hdisp && (chr & (nextchr | svga->ksc5601_sbyte_mask) & 0x80)) { + attr = svga->vram[((svga->ma << 1) + 1) & svga->vram_display_mask]; - if (drawcursor) { - bg = svga->pallook[svga->egapal[attr & 15]]; - fg = svga->pallook[svga->egapal[attr >> 4]]; - } else { - fg = svga->pallook[svga->egapal[attr & 15]]; - bg = svga->pallook[svga->egapal[attr >> 4]]; - if (attr & 0x80 && svga->attrregs[0x10] & 8) { - bg = svga->pallook[svga->egapal[(attr >> 4) & 7]]; - if (svga->blink & 16) - fg = bg; - } - } + if (drawcursor) { + bg = svga->pallook[svga->egapal[attr & 15]]; + fg = svga->pallook[svga->egapal[attr >> 4]]; + } else { + fg = svga->pallook[svga->egapal[attr & 15]]; + bg = svga->pallook[svga->egapal[attr >> 4]]; + if (attr & 0x80 && svga->attrregs[0x10] & 8) { + bg = svga->pallook[svga->egapal[(attr >> 4) & 7]]; + if (svga->blink & 16) + fg = bg; + } + } - if ((chr == svga->ksc5601_udc_area_msb[0] || chr == svga->ksc5601_udc_area_msb[1]) && (nextchr > 0xa0 && nextchr < 0xff)) - dat = fontdatksc5601_user[(chr == svga->ksc5601_udc_area_msb[1] ? 96 : 0) + (nextchr & 0x7F) - 0x20].chr[svga->sc + 16]; - else if(nextchr & 0x80) - dat = fontdatksc5601[((chr & 0x7f) << 7) | (nextchr & 0x7F)].chr[svga->sc + 16]; - else - dat = 0xff; + if ((chr == svga->ksc5601_udc_area_msb[0] || chr == svga->ksc5601_udc_area_msb[1]) && (nextchr > 0xa0 && nextchr < 0xff)) + dat = fontdatksc5601_user[(chr == svga->ksc5601_udc_area_msb[1] ? 96 : 0) + (nextchr & 0x7F) - 0x20].chr[svga->sc + 16]; + else if (nextchr & 0x80) + dat = fontdatksc5601[((chr & 0x7f) << 7) | (nextchr & 0x7F)].chr[svga->sc + 16]; + else + dat = 0xff; - if (svga->seqregs[1] & 1) { - for (xx = 0; xx < 8; xx++) - p[xx] = (dat & (0x80 >> xx)) ? fg : bg; - } else { - for (xx = 0; xx < 8; xx++) - p[xx] = (dat & (0x80 >> xx)) ? fg : bg; - if (((chr & ~0x1f) != 0xc0) || !(svga->attrregs[0x10] & 4)) - p[8] = bg; - else - p[8] = (dat & 1) ? fg : bg; - } + if (svga->seqregs[1] & 1) { + for (xx = 0; xx < 8; xx++) + p[xx] = (dat & (0x80 >> xx)) ? fg : bg; + } else { + for (xx = 0; xx < 8; xx++) + p[xx] = (dat & (0x80 >> xx)) ? fg : bg; + if (((chr & ~0x1f) != 0xc0) || !(svga->attrregs[0x10] & 4)) + p[8] = bg; + else + p[8] = (dat & 1) ? fg : bg; + } - svga->ma += 4; - p += xinc; - x += xinc; - } - } - svga->ma &= svga->vram_display_mask; + svga->ma += 4; + p += xinc; + x += xinc; + } + } + svga->ma &= svga->vram_display_mask; } } - void svga_render_2bpp_lowres(svga_t *svga) { - int x; - uint8_t dat[2]; - uint32_t addr, *p; - uint32_t changed_addr; + int changed_offset; + int x; + uint8_t dat[2]; + uint32_t addr; + uint32_t *p; + uint32_t changed_addr; if ((svga->displine + svga->y_add) < 0) - return; + return; - changed_addr = svga->remap_func(svga, svga->ma); + if (svga->force_old_addr) { + changed_offset = ((svga->ma << 1) + (svga->sc & ~svga->crtc[0x17] & 3) * 0x8000) >> 12; - if (svga->changedvram[changed_addr >> 12] || svga->changedvram[(changed_addr >> 12) + 1] || svga->fullchange) { - p = &buffer32->line[svga->displine + svga->y_add][svga->x_add]; + if (svga->changedvram[changed_offset] || svga->changedvram[changed_offset + 1] || svga->fullchange) { + p = &svga->monitor->target_buffer->line[svga->displine + svga->y_add][svga->x_add]; - if (svga->firstline_draw == 2000) - svga->firstline_draw = svga->displine; - svga->lastline_draw = svga->displine; + if (svga->firstline_draw == 2000) + svga->firstline_draw = svga->displine; + svga->lastline_draw = svga->displine; - for (x = 0; x <= (svga->hdisp + svga->scrollcache); x += 16) { - addr = svga->remap_func(svga, svga->ma); + for (x = 0; x <= (svga->hdisp + svga->scrollcache); x += 16) { + addr = svga->ma; - dat[0] = svga->vram[addr]; - dat[1] = svga->vram[addr | 0x1]; - if (svga->seqregs[1] & 4) - svga->ma += 2; - else - svga->ma += 4; + if (!(svga->crtc[0x17] & 0x40)) { + addr = (addr << 1) & svga->vram_mask; + addr &= ~7; - svga->ma &= svga->vram_mask; + if ((svga->crtc[0x17] & 0x20) && (svga->ma & 0x20000)) + addr |= 4; - if (svga->crtc[0x17] & 0x80) { - p[0] = p[1] = svga->pallook[svga->egapal[(dat[0] >> 6) & 3]]; - p[2] = p[3] = svga->pallook[svga->egapal[(dat[0] >> 4) & 3]]; - p[4] = p[5] = svga->pallook[svga->egapal[(dat[0] >> 2) & 3]]; - p[6] = p[7] = svga->pallook[svga->egapal[dat[0] & 3]]; - p[8] = p[9] = svga->pallook[svga->egapal[(dat[1] >> 6) & 3]]; - p[10] = p[11] = svga->pallook[svga->egapal[(dat[1] >> 4) & 3]]; - p[12] = p[13] = svga->pallook[svga->egapal[(dat[1] >> 2) & 3]]; - p[14] = p[15] = svga->pallook[svga->egapal[dat[1] & 3]]; - } else - memset(p, 0x00, 16 * sizeof(uint32_t)); + if (!(svga->crtc[0x17] & 0x20) && (svga->ma & 0x8000)) + addr |= 4; + } - p += 16; - } + if (!(svga->crtc[0x17] & 0x01)) + addr = (addr & ~0x8000) | ((svga->sc & 1) ? 0x8000 : 0); + + if (!(svga->crtc[0x17] & 0x02)) + addr = (addr & ~0x10000) | ((svga->sc & 2) ? 0x10000 : 0); + + dat[0] = svga->vram[addr]; + dat[1] = svga->vram[addr | 0x1]; + if (svga->seqregs[1] & 4) + svga->ma += 2; + else + svga->ma += 4; + svga->ma &= svga->vram_mask; + p[0] = p[1] = svga->pallook[svga->egapal[(dat[0] >> 6) & 3]]; + p[2] = p[3] = svga->pallook[svga->egapal[(dat[0] >> 4) & 3]]; + p[4] = p[5] = svga->pallook[svga->egapal[(dat[0] >> 2) & 3]]; + p[6] = p[7] = svga->pallook[svga->egapal[dat[0] & 3]]; + p[8] = p[9] = svga->pallook[svga->egapal[(dat[1] >> 6) & 3]]; + p[10] = p[11] = svga->pallook[svga->egapal[(dat[1] >> 4) & 3]]; + p[12] = p[13] = svga->pallook[svga->egapal[(dat[1] >> 2) & 3]]; + p[14] = p[15] = svga->pallook[svga->egapal[dat[1] & 3]]; + p += 16; + } + } + } else { + changed_addr = svga->remap_func(svga, svga->ma); + + if (svga->changedvram[changed_addr >> 12] || svga->changedvram[(changed_addr >> 12) + 1] || svga->fullchange) { + p = &svga->monitor->target_buffer->line[svga->displine + svga->y_add][svga->x_add]; + + if (svga->firstline_draw == 2000) + svga->firstline_draw = svga->displine; + svga->lastline_draw = svga->displine; + + for (x = 0; x <= (svga->hdisp + svga->scrollcache); x += 16) { + addr = svga->remap_func(svga, svga->ma); + + dat[0] = svga->vram[addr]; + dat[1] = svga->vram[addr | 0x1]; + if (svga->seqregs[1] & 4) + svga->ma += 2; + else + svga->ma += 4; + + svga->ma &= svga->vram_mask; + + p[0] = p[1] = svga->pallook[svga->egapal[(dat[0] >> 6) & 3]]; + p[2] = p[3] = svga->pallook[svga->egapal[(dat[0] >> 4) & 3]]; + p[4] = p[5] = svga->pallook[svga->egapal[(dat[0] >> 2) & 3]]; + p[6] = p[7] = svga->pallook[svga->egapal[dat[0] & 3]]; + p[8] = p[9] = svga->pallook[svga->egapal[(dat[1] >> 6) & 3]]; + p[10] = p[11] = svga->pallook[svga->egapal[(dat[1] >> 4) & 3]]; + p[12] = p[13] = svga->pallook[svga->egapal[(dat[1] >> 2) & 3]]; + p[14] = p[15] = svga->pallook[svga->egapal[dat[1] & 3]]; + + p += 16; + } + } } } - void svga_render_2bpp_highres(svga_t *svga) { - int x; - uint8_t dat[2]; - uint32_t addr, *p; - uint32_t changed_addr; + int changed_offset; + int x; + uint8_t dat[2]; + uint32_t addr; + uint32_t *p; + uint32_t changed_addr; if ((svga->displine + svga->y_add) < 0) - return; + return; - changed_addr = svga->remap_func(svga, svga->ma); + if (svga->force_old_addr) { + changed_offset = ((svga->ma << 1) + (svga->sc & ~svga->crtc[0x17] & 3) * 0x8000) >> 12; - if (svga->changedvram[changed_addr >> 12] || svga->changedvram[(changed_addr >> 12) + 1] || svga->fullchange) { - p = &buffer32->line[svga->displine + svga->y_add][svga->x_add]; + if (svga->changedvram[changed_offset] || svga->changedvram[changed_offset + 1] || svga->fullchange) { + p = &svga->monitor->target_buffer->line[svga->displine + svga->y_add][svga->x_add]; - if (svga->firstline_draw == 2000) - svga->firstline_draw = svga->displine; - svga->lastline_draw = svga->displine; + if (svga->firstline_draw == 2000) + svga->firstline_draw = svga->displine; + svga->lastline_draw = svga->displine; - for (x = 0; x <= (svga->hdisp + svga->scrollcache); x += 8) { - addr = svga->remap_func(svga, svga->ma); + for (x = 0; x <= (svga->hdisp + svga->scrollcache); x += 8) { + addr = svga->ma; - dat[0] = svga->vram[addr]; - dat[1] = svga->vram[addr | 0x1]; - if (svga->seqregs[1] & 4) - svga->ma += 2; - else - svga->ma += 4; + if (!(svga->crtc[0x17] & 0x40)) { + addr = (addr << 1) & svga->vram_mask; + addr &= ~7; - svga->ma &= svga->vram_mask; + if ((svga->crtc[0x17] & 0x20) && (svga->ma & 0x20000)) + addr |= 4; - if (svga->crtc[0x17] & 0x80) { - p[0] = svga->pallook[svga->egapal[(dat[0] >> 6) & 3]]; - p[1] = svga->pallook[svga->egapal[(dat[0] >> 4) & 3]]; - p[2] = svga->pallook[svga->egapal[(dat[0] >> 2) & 3]]; - p[3] = svga->pallook[svga->egapal[dat[0] & 3]]; - p[4] = svga->pallook[svga->egapal[(dat[1] >> 6) & 3]]; - p[5] = svga->pallook[svga->egapal[(dat[1] >> 4) & 3]]; - p[6] = svga->pallook[svga->egapal[(dat[1] >> 2) & 3]]; - p[7] = svga->pallook[svga->egapal[dat[1] & 3]]; - } else - memset(p, 0x00, 8 * sizeof(uint32_t)); + if (!(svga->crtc[0x17] & 0x20) && (svga->ma & 0x8000)) + addr |= 4; + } - p += 8; - } + if (!(svga->crtc[0x17] & 0x01)) + addr = (addr & ~0x8000) | ((svga->sc & 1) ? 0x8000 : 0); + + if (!(svga->crtc[0x17] & 0x02)) + addr = (addr & ~0x10000) | ((svga->sc & 2) ? 0x10000 : 0); + + dat[0] = svga->vram[addr]; + dat[1] = svga->vram[addr | 0x1]; + if (svga->seqregs[1] & 4) + svga->ma += 2; + else + svga->ma += 4; + svga->ma &= svga->vram_mask; + p[0] = svga->pallook[svga->egapal[(dat[0] >> 6) & 3]]; + p[1] = svga->pallook[svga->egapal[(dat[0] >> 4) & 3]]; + p[2] = svga->pallook[svga->egapal[(dat[0] >> 2) & 3]]; + p[3] = svga->pallook[svga->egapal[dat[0] & 3]]; + p[4] = svga->pallook[svga->egapal[(dat[1] >> 6) & 3]]; + p[5] = svga->pallook[svga->egapal[(dat[1] >> 4) & 3]]; + p[6] = svga->pallook[svga->egapal[(dat[1] >> 2) & 3]]; + p[7] = svga->pallook[svga->egapal[dat[1] & 3]]; + p += 8; + } + } + } else { + changed_addr = svga->remap_func(svga, svga->ma); + + if (svga->changedvram[changed_addr >> 12] || svga->changedvram[(changed_addr >> 12) + 1] || svga->fullchange) { + p = &svga->monitor->target_buffer->line[svga->displine + svga->y_add][svga->x_add]; + + if (svga->firstline_draw == 2000) + svga->firstline_draw = svga->displine; + svga->lastline_draw = svga->displine; + + for (x = 0; x <= (svga->hdisp + svga->scrollcache); x += 8) { + addr = svga->remap_func(svga, svga->ma); + + dat[0] = svga->vram[addr]; + dat[1] = svga->vram[addr | 0x1]; + if (svga->seqregs[1] & 4) + svga->ma += 2; + else + svga->ma += 4; + + svga->ma &= svga->vram_mask; + + p[0] = svga->pallook[svga->egapal[(dat[0] >> 6) & 3]]; + p[1] = svga->pallook[svga->egapal[(dat[0] >> 4) & 3]]; + p[2] = svga->pallook[svga->egapal[(dat[0] >> 2) & 3]]; + p[3] = svga->pallook[svga->egapal[dat[0] & 3]]; + p[4] = svga->pallook[svga->egapal[(dat[1] >> 6) & 3]]; + p[5] = svga->pallook[svga->egapal[(dat[1] >> 4) & 3]]; + p[6] = svga->pallook[svga->egapal[(dat[1] >> 2) & 3]]; + p[7] = svga->pallook[svga->egapal[dat[1] & 3]]; + + p += 8; + } + } } } - void svga_render_2bpp_headland_highres(svga_t *svga) { - int x; - int oddeven; - uint32_t addr, *p; - uint8_t edat[4]; - uint8_t dat; - uint32_t changed_addr; + int oddeven; + uint32_t addr; + uint32_t *p; + uint8_t edat[4]; + uint8_t dat; + uint32_t changed_addr; if ((svga->displine + svga->y_add) < 0) - return; + return; changed_addr = svga->remap_func(svga, svga->ma); - if (svga->changedvram[changed_addr >> 12] || svga->changedvram[(changed_addr >> 12) + 1] || svga->fullchange) { - p = &buffer32->line[svga->displine + svga->y_add][svga->x_add]; + if (svga->changedvram[changed_addr >> 12] || svga->changedvram[(changed_addr >> 12) + 1] || svga->fullchange) { + p = &svga->monitor->target_buffer->line[svga->displine + svga->y_add][svga->x_add]; - if (svga->firstline_draw == 2000) - svga->firstline_draw = svga->displine; - svga->lastline_draw = svga->displine; + if (svga->firstline_draw == 2000) + svga->firstline_draw = svga->displine; + svga->lastline_draw = svga->displine; - for (x = 0; x <= (svga->hdisp + svga->scrollcache); x += 8) { - addr = svga->remap_func(svga, svga->ma); - oddeven = 0; + for (int x = 0; x <= (svga->hdisp + svga->scrollcache); x += 8) { + addr = svga->remap_func(svga, svga->ma); + oddeven = 0; - if (svga->seqregs[1] & 4) { - oddeven = (addr & 4) ? 1 : 0; - edat[0] = svga->vram[addr | oddeven]; - edat[2] = svga->vram[addr | oddeven | 0x2]; - edat[1] = edat[3] = 0; - } else { - *(uint32_t *)(&edat[0]) = *(uint32_t *)(&svga->vram[addr]); - } - svga->ma += 4; - svga->ma &= svga->vram_mask; + if (svga->seqregs[1] & 4) { + oddeven = (addr & 4) ? 1 : 0; + edat[0] = svga->vram[addr | oddeven]; + edat[2] = svga->vram[addr | oddeven | 0x2]; + edat[1] = edat[3] = 0; + } else { + *(uint32_t *) (&edat[0]) = *(uint32_t *) (&svga->vram[addr]); + } + svga->ma += 4; + svga->ma &= svga->vram_mask; - if (svga->crtc[0x17] & 0x80) { - dat = edatlookup[edat[0] >> 6][edat[1] >> 6] | (edatlookup[edat[2] >> 6][edat[3] >> 6] << 2); - p[0] = svga->pallook[svga->egapal[(dat >> 4) & svga->plane_mask]]; - p[1] = svga->pallook[svga->egapal[dat & svga->plane_mask]]; - dat = edatlookup[(edat[0] >> 4) & 3][(edat[1] >> 4) & 3] | (edatlookup[(edat[2] >> 4) & 3][(edat[3] >> 4) & 3] << 2); - p[2] = svga->pallook[svga->egapal[(dat >> 4) & svga->plane_mask]]; - p[3] = svga->pallook[svga->egapal[dat & svga->plane_mask]]; - dat = edatlookup[(edat[0] >> 2) & 3][(edat[1] >> 2) & 3] | (edatlookup[(edat[2] >> 2) & 3][(edat[3] >> 2) & 3] << 2); - p[4] = svga->pallook[svga->egapal[(dat >> 4) & svga->plane_mask]]; - p[5] = svga->pallook[svga->egapal[dat & svga->plane_mask]]; - dat = edatlookup[edat[0] & 3][edat[1] & 3] | (edatlookup[edat[2] & 3][edat[3] & 3] << 2); - p[6] = svga->pallook[svga->egapal[(dat >> 4) & svga->plane_mask]]; - p[7] = svga->pallook[svga->egapal[dat & svga->plane_mask]]; - } else - memset(p, 0x00, 8 * sizeof(uint32_t)); + dat = edatlookup[edat[0] >> 6][edat[1] >> 6] | (edatlookup[edat[2] >> 6][edat[3] >> 6] << 2); + p[0] = svga->pallook[svga->egapal[(dat >> 4) & svga->plane_mask]]; + p[1] = svga->pallook[svga->egapal[dat & svga->plane_mask]]; + dat = edatlookup[(edat[0] >> 4) & 3][(edat[1] >> 4) & 3] | (edatlookup[(edat[2] >> 4) & 3][(edat[3] >> 4) & 3] << 2); + p[2] = svga->pallook[svga->egapal[(dat >> 4) & svga->plane_mask]]; + p[3] = svga->pallook[svga->egapal[dat & svga->plane_mask]]; + dat = edatlookup[(edat[0] >> 2) & 3][(edat[1] >> 2) & 3] | (edatlookup[(edat[2] >> 2) & 3][(edat[3] >> 2) & 3] << 2); + p[4] = svga->pallook[svga->egapal[(dat >> 4) & svga->plane_mask]]; + p[5] = svga->pallook[svga->egapal[dat & svga->plane_mask]]; + dat = edatlookup[edat[0] & 3][edat[1] & 3] | (edatlookup[edat[2] & 3][edat[3] & 3] << 2); + p[6] = svga->pallook[svga->egapal[(dat >> 4) & svga->plane_mask]]; + p[7] = svga->pallook[svga->egapal[dat & svga->plane_mask]]; - p += 8; - } + p += 8; + } } } void svga_render_4bpp_lowres(svga_t *svga) { - int x, oddeven; - uint32_t addr, *p; - uint8_t edat[4]; - uint8_t dat; - uint32_t changed_addr; + int x; + int oddeven; + uint32_t addr; + uint32_t *p; + uint8_t edat[4]; + uint8_t dat; + uint32_t changed_addr; if ((svga->displine + svga->y_add) < 0) - return; + return; - changed_addr = svga->remap_func(svga, svga->ma); + if (svga->force_old_addr) { + if (svga->changedvram[svga->ma >> 12] || svga->changedvram[(svga->ma >> 12) + 1] || svga->fullchange) { + p = &svga->monitor->target_buffer->line[svga->displine + svga->y_add][svga->x_add]; - if (svga->changedvram[changed_addr >> 12] || svga->changedvram[(changed_addr >> 12) + 1] || svga->fullchange) { - p = &buffer32->line[svga->displine + svga->y_add][svga->x_add]; + if (svga->firstline_draw == 2000) + svga->firstline_draw = svga->displine; + svga->lastline_draw = svga->displine; - if (svga->firstline_draw == 2000) - svga->firstline_draw = svga->displine; - svga->lastline_draw = svga->displine; + for (x = 0; x <= (svga->hdisp + svga->scrollcache); x += 16) { + addr = svga->ma; + oddeven = 0; - for (x = 0; x <= (svga->hdisp + svga->scrollcache); x += 16) { - addr = svga->remap_func(svga, svga->ma); - oddeven = 0; + if (!(svga->crtc[0x17] & 0x40)) { + addr = (addr << 1) & svga->vram_mask; - if (svga->seqregs[1] & 4) { - oddeven = (addr & 4) ? 1 : 0; - edat[0] = svga->vram[addr | oddeven]; - edat[2] = svga->vram[addr | oddeven | 0x2]; - edat[1] = edat[3] = 0; - svga->ma += 2; - } else { - *(uint32_t *)(&edat[0]) = *(uint32_t *)(&svga->vram[addr]); - svga->ma += 4; - } - svga->ma &= svga->vram_mask; + if (svga->seqregs[1] & 4) + oddeven = (addr & 4) ? 1 : 0; - if (svga->crtc[0x17] & 0x80) { - dat = edatlookup[edat[0] >> 6][edat[1] >> 6] | (edatlookup[edat[2] >> 6][edat[3] >> 6] << 2); - p[0] = p[1] = svga->pallook[svga->egapal[(dat >> 4) & svga->plane_mask]]; - p[2] = p[3] = svga->pallook[svga->egapal[dat & svga->plane_mask]]; - dat = edatlookup[(edat[0] >> 4) & 3][(edat[1] >> 4) & 3] | (edatlookup[(edat[2] >> 4) & 3][(edat[3] >> 4) & 3] << 2); - p[4] = p[5] = svga->pallook[svga->egapal[(dat >> 4) & svga->plane_mask]]; - p[6] = p[7] = svga->pallook[svga->egapal[dat & svga->plane_mask]]; - dat = edatlookup[(edat[0] >> 2) & 3][(edat[1] >> 2) & 3] | (edatlookup[(edat[2] >> 2) & 3][(edat[3] >> 2) & 3] << 2); - p[8] = p[9] = svga->pallook[svga->egapal[(dat >> 4) & svga->plane_mask]]; - p[10] = p[11] = svga->pallook[svga->egapal[dat & svga->plane_mask]]; - dat = edatlookup[edat[0] & 3][edat[1] & 3] | (edatlookup[edat[2] & 3][edat[3] & 3] << 2); - p[12] = p[13] = svga->pallook[svga->egapal[(dat >> 4) & svga->plane_mask]]; - p[14] = p[15] = svga->pallook[svga->egapal[dat & svga->plane_mask]]; - } else - memset(p, 0x00, 16 * sizeof(uint32_t)); + addr &= ~7; - p += 16; - } + if ((svga->crtc[0x17] & 0x20) && (svga->ma & 0x20000)) + addr |= 4; + if (!(svga->crtc[0x17] & 0x20) && (svga->ma & 0x8000)) + addr |= 4; + } + + if (!(svga->crtc[0x17] & 0x01)) + addr = (addr & ~0x8000) | ((svga->sc & 1) ? 0x8000 : 0); + if (!(svga->crtc[0x17] & 0x02)) + addr = (addr & ~0x10000) | ((svga->sc & 2) ? 0x10000 : 0); + + if (svga->seqregs[1] & 4) { + edat[0] = svga->vram[addr | oddeven]; + edat[2] = svga->vram[addr | oddeven | 0x2]; + edat[1] = edat[3] = 0; + svga->ma += 2; + } else { + *(uint32_t *) (&edat[0]) = *(uint32_t *) (&svga->vram[addr]); + svga->ma += 4; + } + svga->ma &= svga->vram_mask; + + dat = edatlookup[edat[0] >> 6][edat[1] >> 6] | (edatlookup[edat[2] >> 6][edat[3] >> 6] << 2); + p[0] = p[1] = svga->pallook[svga->egapal[(dat >> 4) & svga->plane_mask]]; + p[2] = p[3] = svga->pallook[svga->egapal[dat & svga->plane_mask]]; + dat = edatlookup[(edat[0] >> 4) & 3][(edat[1] >> 4) & 3] | (edatlookup[(edat[2] >> 4) & 3][(edat[3] >> 4) & 3] << 2); + p[4] = p[5] = svga->pallook[svga->egapal[(dat >> 4) & svga->plane_mask]]; + p[6] = p[7] = svga->pallook[svga->egapal[dat & svga->plane_mask]]; + dat = edatlookup[(edat[0] >> 2) & 3][(edat[1] >> 2) & 3] | (edatlookup[(edat[2] >> 2) & 3][(edat[3] >> 2) & 3] << 2); + p[8] = p[9] = svga->pallook[svga->egapal[(dat >> 4) & svga->plane_mask]]; + p[10] = p[11] = svga->pallook[svga->egapal[dat & svga->plane_mask]]; + dat = edatlookup[edat[0] & 3][edat[1] & 3] | (edatlookup[edat[2] & 3][edat[3] & 3] << 2); + p[12] = p[13] = svga->pallook[svga->egapal[(dat >> 4) & svga->plane_mask]]; + p[14] = p[15] = svga->pallook[svga->egapal[dat & svga->plane_mask]]; + + p += 16; + } + } + } else { + changed_addr = svga->remap_func(svga, svga->ma); + + if (svga->changedvram[changed_addr >> 12] || svga->changedvram[(changed_addr >> 12) + 1] || svga->fullchange) { + p = &svga->monitor->target_buffer->line[svga->displine + svga->y_add][svga->x_add]; + + if (svga->firstline_draw == 2000) + svga->firstline_draw = svga->displine; + svga->lastline_draw = svga->displine; + + for (x = 0; x <= (svga->hdisp + svga->scrollcache); x += 16) { + addr = svga->remap_func(svga, svga->ma); + oddeven = 0; + + if (svga->seqregs[1] & 4) { + oddeven = (addr & 4) ? 1 : 0; + edat[0] = svga->vram[addr | oddeven]; + edat[2] = svga->vram[addr | oddeven | 0x2]; + edat[1] = edat[3] = 0; + svga->ma += 2; + } else { + *(uint32_t *) (&edat[0]) = *(uint32_t *) (&svga->vram[addr]); + svga->ma += 4; + } + svga->ma &= svga->vram_mask; + + dat = edatlookup[edat[0] >> 6][edat[1] >> 6] | (edatlookup[edat[2] >> 6][edat[3] >> 6] << 2); + p[0] = p[1] = svga->pallook[svga->egapal[(dat >> 4) & svga->plane_mask]]; + p[2] = p[3] = svga->pallook[svga->egapal[dat & svga->plane_mask]]; + dat = edatlookup[(edat[0] >> 4) & 3][(edat[1] >> 4) & 3] | (edatlookup[(edat[2] >> 4) & 3][(edat[3] >> 4) & 3] << 2); + p[4] = p[5] = svga->pallook[svga->egapal[(dat >> 4) & svga->plane_mask]]; + p[6] = p[7] = svga->pallook[svga->egapal[dat & svga->plane_mask]]; + dat = edatlookup[(edat[0] >> 2) & 3][(edat[1] >> 2) & 3] | (edatlookup[(edat[2] >> 2) & 3][(edat[3] >> 2) & 3] << 2); + p[8] = p[9] = svga->pallook[svga->egapal[(dat >> 4) & svga->plane_mask]]; + p[10] = p[11] = svga->pallook[svga->egapal[dat & svga->plane_mask]]; + dat = edatlookup[edat[0] & 3][edat[1] & 3] | (edatlookup[edat[2] & 3][edat[3] & 3] << 2); + p[12] = p[13] = svga->pallook[svga->egapal[(dat >> 4) & svga->plane_mask]]; + p[14] = p[15] = svga->pallook[svga->egapal[dat & svga->plane_mask]]; + + p += 16; + } + } } } - void svga_render_4bpp_highres(svga_t *svga) { - int x, oddeven; - uint32_t addr, *p; - uint8_t edat[4]; - uint8_t dat; - uint32_t changed_addr; + int changed_offset; + int x; + int oddeven; + uint32_t addr; + uint32_t *p; + uint8_t edat[4]; + uint8_t dat; + uint32_t changed_addr; if ((svga->displine + svga->y_add) < 0) - return; + return; - changed_addr = svga->remap_func(svga, svga->ma); + if (svga->force_old_addr) { + changed_offset = (svga->ma + (svga->sc & ~svga->crtc[0x17] & 3) * 0x8000) >> 12; - if (svga->changedvram[changed_addr >> 12] || svga->changedvram[(changed_addr >> 12) + 1] || svga->fullchange) { - p = &buffer32->line[svga->displine + svga->y_add][svga->x_add]; + if (svga->changedvram[changed_offset] || svga->changedvram[changed_offset + 1] || svga->fullchange) { + p = &svga->monitor->target_buffer->line[svga->displine + svga->y_add][svga->x_add]; - if (svga->firstline_draw == 2000) - svga->firstline_draw = svga->displine; - svga->lastline_draw = svga->displine; + if (svga->firstline_draw == 2000) + svga->firstline_draw = svga->displine; + svga->lastline_draw = svga->displine; - for (x = 0; x <= (svga->hdisp + svga->scrollcache); x += 8) { - addr = svga->remap_func(svga, svga->ma); - oddeven = 0; + for (x = 0; x <= (svga->hdisp + svga->scrollcache); x += 8) { + addr = svga->ma; + oddeven = 0; - if (svga->seqregs[1] & 4) { - oddeven = (addr & 4) ? 1 : 0; - edat[0] = svga->vram[addr | oddeven]; - edat[2] = svga->vram[addr | oddeven | 0x2]; - edat[1] = edat[3] = 0; - svga->ma += 2; - } else { - *(uint32_t *)(&edat[0]) = *(uint32_t *)(&svga->vram[addr]); - svga->ma += 4; - } - svga->ma &= svga->vram_mask; + if (!(svga->crtc[0x17] & 0x40)) { + addr = (addr << 1) & svga->vram_mask; - if (svga->crtc[0x17] & 0x80) { - dat = edatlookup[edat[0] >> 6][edat[1] >> 6] | (edatlookup[edat[2] >> 6][edat[3] >> 6] << 2); - p[0] = svga->pallook[svga->egapal[(dat >> 4) & svga->plane_mask]]; - p[1] = svga->pallook[svga->egapal[dat & svga->plane_mask]]; - dat = edatlookup[(edat[0] >> 4) & 3][(edat[1] >> 4) & 3] | (edatlookup[(edat[2] >> 4) & 3][(edat[3] >> 4) & 3] << 2); - p[2] = svga->pallook[svga->egapal[(dat >> 4) & svga->plane_mask]]; - p[3] = svga->pallook[svga->egapal[dat & svga->plane_mask]]; - dat = edatlookup[(edat[0] >> 2) & 3][(edat[1] >> 2) & 3] | (edatlookup[(edat[2] >> 2) & 3][(edat[3] >> 2) & 3] << 2); - p[4] = svga->pallook[svga->egapal[(dat >> 4) & svga->plane_mask]]; - p[5] = svga->pallook[svga->egapal[dat & svga->plane_mask]]; - dat = edatlookup[edat[0] & 3][edat[1] & 3] | (edatlookup[edat[2] & 3][edat[3] & 3] << 2); - p[6] = svga->pallook[svga->egapal[(dat >> 4) & svga->plane_mask]]; - p[7] = svga->pallook[svga->egapal[dat & svga->plane_mask]]; - } else - memset(p, 0x00, 8 * sizeof(uint32_t)); + if (svga->seqregs[1] & 4) + oddeven = (addr & 4) ? 1 : 0; - p += 8; - } + addr &= ~7; + + if ((svga->crtc[0x17] & 0x20) && (svga->ma & 0x20000)) + addr |= 4; + if (!(svga->crtc[0x17] & 0x20) && (svga->ma & 0x8000)) + addr |= 4; + } + + if (!(svga->crtc[0x17] & 0x01)) + addr = (addr & ~0x8000) | ((svga->sc & 1) ? 0x8000 : 0); + if (!(svga->crtc[0x17] & 0x02)) + addr = (addr & ~0x10000) | ((svga->sc & 2) ? 0x10000 : 0); + + if (svga->seqregs[1] & 4) { + edat[0] = svga->vram[addr | oddeven]; + edat[2] = svga->vram[addr | oddeven | 0x2]; + edat[1] = edat[3] = 0; + svga->ma += 2; + } else { + *(uint32_t *) (&edat[0]) = *(uint32_t *) (&svga->vram[addr]); + svga->ma += 4; + } + svga->ma &= svga->vram_mask; + + dat = edatlookup[edat[0] >> 6][edat[1] >> 6] | (edatlookup[edat[2] >> 6][edat[3] >> 6] << 2); + p[0] = svga->pallook[svga->egapal[(dat >> 4) & svga->plane_mask]]; + p[1] = svga->pallook[svga->egapal[dat & svga->plane_mask]]; + dat = edatlookup[(edat[0] >> 4) & 3][(edat[1] >> 4) & 3] | (edatlookup[(edat[2] >> 4) & 3][(edat[3] >> 4) & 3] << 2); + p[2] = svga->pallook[svga->egapal[(dat >> 4) & svga->plane_mask]]; + p[3] = svga->pallook[svga->egapal[dat & svga->plane_mask]]; + dat = edatlookup[(edat[0] >> 2) & 3][(edat[1] >> 2) & 3] | (edatlookup[(edat[2] >> 2) & 3][(edat[3] >> 2) & 3] << 2); + p[4] = svga->pallook[svga->egapal[(dat >> 4) & svga->plane_mask]]; + p[5] = svga->pallook[svga->egapal[dat & svga->plane_mask]]; + dat = edatlookup[edat[0] & 3][edat[1] & 3] | (edatlookup[edat[2] & 3][edat[3] & 3] << 2); + p[6] = svga->pallook[svga->egapal[(dat >> 4) & svga->plane_mask]]; + p[7] = svga->pallook[svga->egapal[dat & svga->plane_mask]]; + + p += 8; + } + } + } else { + changed_addr = svga->remap_func(svga, svga->ma); + + if (svga->changedvram[changed_addr >> 12] || svga->changedvram[(changed_addr >> 12) + 1] || svga->fullchange) { + p = &svga->monitor->target_buffer->line[svga->displine + svga->y_add][svga->x_add]; + + if (svga->firstline_draw == 2000) + svga->firstline_draw = svga->displine; + svga->lastline_draw = svga->displine; + + for (x = 0; x <= (svga->hdisp + svga->scrollcache); x += 8) { + addr = svga->remap_func(svga, svga->ma); + oddeven = 0; + + if (svga->seqregs[1] & 4) { + oddeven = (addr & 4) ? 1 : 0; + edat[0] = svga->vram[addr | oddeven]; + edat[2] = svga->vram[addr | oddeven | 0x2]; + edat[1] = edat[3] = 0; + svga->ma += 2; + } else { + *(uint32_t *) (&edat[0]) = *(uint32_t *) (&svga->vram[addr]); + svga->ma += 4; + } + svga->ma &= svga->vram_mask; + + dat = edatlookup[edat[0] >> 6][edat[1] >> 6] | (edatlookup[edat[2] >> 6][edat[3] >> 6] << 2); + p[0] = svga->pallook[svga->egapal[(dat >> 4) & svga->plane_mask]]; + p[1] = svga->pallook[svga->egapal[dat & svga->plane_mask]]; + dat = edatlookup[(edat[0] >> 4) & 3][(edat[1] >> 4) & 3] | (edatlookup[(edat[2] >> 4) & 3][(edat[3] >> 4) & 3] << 2); + p[2] = svga->pallook[svga->egapal[(dat >> 4) & svga->plane_mask]]; + p[3] = svga->pallook[svga->egapal[dat & svga->plane_mask]]; + dat = edatlookup[(edat[0] >> 2) & 3][(edat[1] >> 2) & 3] | (edatlookup[(edat[2] >> 2) & 3][(edat[3] >> 2) & 3] << 2); + p[4] = svga->pallook[svga->egapal[(dat >> 4) & svga->plane_mask]]; + p[5] = svga->pallook[svga->egapal[dat & svga->plane_mask]]; + dat = edatlookup[edat[0] & 3][edat[1] & 3] | (edatlookup[edat[2] & 3][edat[3] & 3] << 2); + p[6] = svga->pallook[svga->egapal[(dat >> 4) & svga->plane_mask]]; + p[7] = svga->pallook[svga->egapal[dat & svga->plane_mask]]; + + p += 8; + } + } } } - void svga_render_8bpp_lowres(svga_t *svga) { - int x; + int x; uint32_t *p; - uint32_t dat; - uint32_t changed_addr; - uint32_t addr; + uint32_t dat; + uint32_t changed_addr; + uint32_t addr; if ((svga->displine + svga->y_add) < 0) - return; + return; - changed_addr = svga->remap_func(svga, svga->ma); + if (svga->force_old_addr) { + if (svga->changedvram[svga->ma >> 12] || svga->changedvram[(svga->ma >> 12) + 1] || svga->fullchange) { + p = &svga->monitor->target_buffer->line[svga->displine + svga->y_add][svga->x_add]; - if (svga->changedvram[changed_addr >> 12] || svga->changedvram[(changed_addr >> 12) + 1] || svga->fullchange) { - p = &buffer32->line[svga->displine + svga->y_add][svga->x_add]; + if (svga->firstline_draw == 2000) + svga->firstline_draw = svga->displine; + svga->lastline_draw = svga->displine; - if (svga->firstline_draw == 2000) - svga->firstline_draw = svga->displine; - svga->lastline_draw = svga->displine; - - if (!svga->remap_required) { - for (x = 0; x <= (svga->hdisp + svga->scrollcache); x += 8) { - dat = *(uint32_t *)(&svga->vram[svga->ma & svga->vram_display_mask]); - p[0] = p[1] = svga->map8[dat & 0xff]; - p[2] = p[3] = svga->map8[(dat >> 8) & 0xff]; - p[4] = p[5] = svga->map8[(dat >> 16) & 0xff]; - p[6] = p[7] = svga->map8[(dat >> 24) & 0xff]; + for (x = 0; x <= (svga->hdisp + svga->scrollcache); x += 8) { + dat = *(uint32_t *) (&svga->vram[svga->ma & svga->vram_display_mask]); - svga->ma += 4; - p += 8; - } - } else { - for (x = 0; x <= (svga->hdisp + svga->scrollcache); x += 8) { - addr = svga->remap_func(svga, svga->ma); - dat = *(uint32_t *)(&svga->vram[addr & svga->vram_display_mask]); - p[0] = p[1] = svga->map8[dat & 0xff]; - p[2] = p[3] = svga->map8[(dat >> 8) & 0xff]; - p[4] = p[5] = svga->map8[(dat >> 16) & 0xff]; - p[6] = p[7] = svga->map8[(dat >> 24) & 0xff]; + p[0] = p[1] = svga->map8[dat & 0xff]; + p[2] = p[3] = svga->map8[(dat >> 8) & 0xff]; + p[4] = p[5] = svga->map8[(dat >> 16) & 0xff]; + p[6] = p[7] = svga->map8[(dat >> 24) & 0xff]; - svga->ma += 4; - p += 8; - } - } - svga->ma &= svga->vram_display_mask; + svga->ma += 4; + p += 8; + } + svga->ma &= svga->vram_display_mask; + } + } else { + changed_addr = svga->remap_func(svga, svga->ma); + + if (svga->changedvram[changed_addr >> 12] || svga->changedvram[(changed_addr >> 12) + 1] || svga->fullchange) { + p = &svga->monitor->target_buffer->line[svga->displine + svga->y_add][svga->x_add]; + + if (svga->firstline_draw == 2000) + svga->firstline_draw = svga->displine; + svga->lastline_draw = svga->displine; + + if (!svga->remap_required) { + for (x = 0; x <= (svga->hdisp + svga->scrollcache); x += 8) { + dat = *(uint32_t *) (&svga->vram[svga->ma & svga->vram_display_mask]); + p[0] = p[1] = svga->map8[dat & 0xff]; + p[2] = p[3] = svga->map8[(dat >> 8) & 0xff]; + p[4] = p[5] = svga->map8[(dat >> 16) & 0xff]; + p[6] = p[7] = svga->map8[(dat >> 24) & 0xff]; + + svga->ma += 4; + p += 8; + } + } else { + for (x = 0; x <= (svga->hdisp + svga->scrollcache); x += 8) { + addr = svga->remap_func(svga, svga->ma); + dat = *(uint32_t *) (&svga->vram[addr & svga->vram_display_mask]); + p[0] = p[1] = svga->map8[dat & 0xff]; + p[2] = p[3] = svga->map8[(dat >> 8) & 0xff]; + p[4] = p[5] = svga->map8[(dat >> 16) & 0xff]; + p[6] = p[7] = svga->map8[(dat >> 24) & 0xff]; + + svga->ma += 4; + p += 8; + } + } + svga->ma &= svga->vram_display_mask; + } } } - void svga_render_8bpp_highres(svga_t *svga) { - int x; + int x; uint32_t *p; - uint32_t dat; - uint32_t changed_addr; - uint32_t addr; + uint32_t dat; + uint32_t changed_addr; + uint32_t addr; if ((svga->displine + svga->y_add) < 0) - return; + return; - changed_addr = svga->remap_func(svga, svga->ma); + if (svga->force_old_addr) { + if (svga->changedvram[svga->ma >> 12] || svga->changedvram[(svga->ma >> 12) + 1] || svga->fullchange) { + p = &svga->monitor->target_buffer->line[svga->displine + svga->y_add][svga->x_add]; - if (svga->changedvram[changed_addr >> 12] || svga->changedvram[(changed_addr >> 12) + 1] || svga->fullchange) { - p = &buffer32->line[svga->displine + svga->y_add][svga->x_add]; + if (svga->firstline_draw == 2000) + svga->firstline_draw = svga->displine; + svga->lastline_draw = svga->displine; - if (svga->firstline_draw == 2000) - svga->firstline_draw = svga->displine; - svga->lastline_draw = svga->displine; - - if (!svga->remap_required) { - for (x = 0; x <= (svga->hdisp/* + svga->scrollcache*/); x += 8) { - dat = *(uint32_t *)(&svga->vram[svga->ma & svga->vram_display_mask]); - p[0] = svga->map8[dat & 0xff]; - p[1] = svga->map8[(dat >> 8) & 0xff]; - p[2] = svga->map8[(dat >> 16) & 0xff]; - p[3] = svga->map8[(dat >> 24) & 0xff]; + for (x = 0; x <= (svga->hdisp /* + svga->scrollcache*/); x += 8) { + dat = *(uint32_t *) (&svga->vram[svga->ma & svga->vram_display_mask]); + p[0] = svga->map8[dat & 0xff]; + p[1] = svga->map8[(dat >> 8) & 0xff]; + p[2] = svga->map8[(dat >> 16) & 0xff]; + p[3] = svga->map8[(dat >> 24) & 0xff]; - dat = *(uint32_t *)(&svga->vram[(svga->ma + 4) & svga->vram_display_mask]); - p[4] = svga->map8[dat & 0xff]; - p[5] = svga->map8[(dat >> 8) & 0xff]; - p[6] = svga->map8[(dat >> 16) & 0xff]; - p[7] = svga->map8[(dat >> 24) & 0xff]; + dat = *(uint32_t *) (&svga->vram[(svga->ma + 4) & svga->vram_display_mask]); + p[4] = svga->map8[dat & 0xff]; + p[5] = svga->map8[(dat >> 8) & 0xff]; + p[6] = svga->map8[(dat >> 16) & 0xff]; + p[7] = svga->map8[(dat >> 24) & 0xff]; - svga->ma += 8; - p += 8; - } - } else { - for (x = 0; x <= (svga->hdisp/* + svga->scrollcache*/); x += 4) { - addr = svga->remap_func(svga, svga->ma); - dat = *(uint32_t *)(&svga->vram[addr & svga->vram_display_mask]); - p[0] = svga->map8[dat & 0xff]; - p[1] = svga->map8[(dat >> 8) & 0xff]; - p[2] = svga->map8[(dat >> 16) & 0xff]; - p[3] = svga->map8[(dat >> 24) & 0xff]; + svga->ma += 8; + p += 8; + } + svga->ma &= svga->vram_display_mask; + } + } else { + changed_addr = svga->remap_func(svga, svga->ma); - svga->ma += 4; - p += 4; - } - } - svga->ma &= svga->vram_display_mask; + if (svga->changedvram[changed_addr >> 12] || svga->changedvram[(changed_addr >> 12) + 1] || svga->fullchange) { + p = &svga->monitor->target_buffer->line[svga->displine + svga->y_add][svga->x_add]; + + if (svga->firstline_draw == 2000) + svga->firstline_draw = svga->displine; + svga->lastline_draw = svga->displine; + + if (!svga->remap_required) { + for (x = 0; x <= (svga->hdisp /* + svga->scrollcache*/); x += 8) { + dat = *(uint32_t *) (&svga->vram[svga->ma & svga->vram_display_mask]); + p[0] = svga->map8[dat & 0xff]; + p[1] = svga->map8[(dat >> 8) & 0xff]; + p[2] = svga->map8[(dat >> 16) & 0xff]; + p[3] = svga->map8[(dat >> 24) & 0xff]; + + dat = *(uint32_t *) (&svga->vram[(svga->ma + 4) & svga->vram_display_mask]); + p[4] = svga->map8[dat & 0xff]; + p[5] = svga->map8[(dat >> 8) & 0xff]; + p[6] = svga->map8[(dat >> 16) & 0xff]; + p[7] = svga->map8[(dat >> 24) & 0xff]; + + svga->ma += 8; + p += 8; + } + } else { + for (x = 0; x <= (svga->hdisp /* + svga->scrollcache*/); x += 4) { + addr = svga->remap_func(svga, svga->ma); + dat = *(uint32_t *) (&svga->vram[addr & svga->vram_display_mask]); + p[0] = svga->map8[dat & 0xff]; + p[1] = svga->map8[(dat >> 8) & 0xff]; + p[2] = svga->map8[(dat >> 16) & 0xff]; + p[3] = svga->map8[(dat >> 24) & 0xff]; + + svga->ma += 4; + p += 4; + } + } + svga->ma &= svga->vram_display_mask; + } } } void svga_render_8bpp_tseng_lowres(svga_t *svga) { - int x; uint32_t *p; - uint32_t dat; + uint32_t dat; if ((svga->displine + svga->y_add) < 0) - return; + return; if (svga->changedvram[svga->ma >> 12] || svga->changedvram[(svga->ma >> 12) + 1] || svga->fullchange) { - p = &buffer32->line[svga->displine + svga->y_add][svga->x_add]; + p = &svga->monitor->target_buffer->line[svga->displine + svga->y_add][svga->x_add]; - if (svga->firstline_draw == 2000) - svga->firstline_draw = svga->displine; - svga->lastline_draw = svga->displine; + if (svga->firstline_draw == 2000) + svga->firstline_draw = svga->displine; + svga->lastline_draw = svga->displine; - for (x = 0; x <= (svga->hdisp + svga->scrollcache); x += 8) { - if (svga->crtc[0x17] & 0x80) { - dat = *(uint32_t *)(&svga->vram[svga->ma & svga->vram_display_mask]); - if (svga->attrregs[0x10] & 0x80) - dat = (dat & ~0xf0) | ((svga->attrregs[0x14] & 0x0f) << 4); - p[0] = p[1] = svga->map8[dat & 0xff]; - dat >>= 8; - if (svga->attrregs[0x10] & 0x80) - dat = (dat & ~0xf0) | ((svga->attrregs[0x14] & 0x0f) << 4); - p[2] = p[3] = svga->map8[dat & 0xff]; - dat >>= 8; - if (svga->attrregs[0x10] & 0x80) - dat = (dat & ~0xf0) | ((svga->attrregs[0x14] & 0x0f) << 4); - p[4] = p[5] = svga->map8[dat & 0xff]; - dat >>= 8; - if (svga->attrregs[0x10] & 0x80) - dat = (dat & ~0xf0) | ((svga->attrregs[0x14] & 0x0f) << 4); - p[6] = p[7] = svga->map8[dat & 0xff]; - } else - memset(p, 0x00, 8 * sizeof(uint32_t)); + for (int x = 0; x <= (svga->hdisp + svga->scrollcache); x += 8) { + dat = *(uint32_t *) (&svga->vram[svga->ma & svga->vram_display_mask]); + if (svga->attrregs[0x10] & 0x80) + dat = (dat & ~0xf0) | ((svga->attrregs[0x14] & 0x0f) << 4); + p[0] = p[1] = svga->map8[dat & 0xff]; + dat >>= 8; + if (svga->attrregs[0x10] & 0x80) + dat = (dat & ~0xf0) | ((svga->attrregs[0x14] & 0x0f) << 4); + p[2] = p[3] = svga->map8[dat & 0xff]; + dat >>= 8; + if (svga->attrregs[0x10] & 0x80) + dat = (dat & ~0xf0) | ((svga->attrregs[0x14] & 0x0f) << 4); + p[4] = p[5] = svga->map8[dat & 0xff]; + dat >>= 8; + if (svga->attrregs[0x10] & 0x80) + dat = (dat & ~0xf0) | ((svga->attrregs[0x14] & 0x0f) << 4); + p[6] = p[7] = svga->map8[dat & 0xff]; - svga->ma += 4; - p += 8; - } - svga->ma &= svga->vram_display_mask; + svga->ma += 4; + p += 8; + } + svga->ma &= svga->vram_display_mask; } } - void svga_render_8bpp_tseng_highres(svga_t *svga) { - int x; uint32_t *p; - uint32_t dat; + uint32_t dat; if ((svga->displine + svga->y_add) < 0) - return; + return; if (svga->changedvram[svga->ma >> 12] || svga->changedvram[(svga->ma >> 12) + 1] || svga->fullchange) { - p = &buffer32->line[svga->displine + svga->y_add][svga->x_add]; + p = &svga->monitor->target_buffer->line[svga->displine + svga->y_add][svga->x_add]; - if (svga->firstline_draw == 2000) - svga->firstline_draw = svga->displine; - svga->lastline_draw = svga->displine; + if (svga->firstline_draw == 2000) + svga->firstline_draw = svga->displine; + svga->lastline_draw = svga->displine; - for (x = 0; x <= (svga->hdisp/* + svga->scrollcache*/); x += 8) { - if (svga->crtc[0x17] & 0x80) { - dat = *(uint32_t *)(&svga->vram[svga->ma & svga->vram_display_mask]); - if (svga->attrregs[0x10] & 0x80) - dat = (dat & ~0xf0) | ((svga->attrregs[0x14] & 0x0f) << 4); - p[0] = svga->map8[dat & 0xff]; - dat >>= 8; - if (svga->attrregs[0x10] & 0x80) - dat = (dat & ~0xf0) | ((svga->attrregs[0x14] & 0x0f) << 4); - p[1] = svga->map8[dat & 0xff]; - dat >>= 8; - if (svga->attrregs[0x10] & 0x80) - dat = (dat & ~0xf0) | ((svga->attrregs[0x14] & 0x0f) << 4); - p[2] = svga->map8[dat & 0xff]; - dat >>= 8; - if (svga->attrregs[0x10] & 0x80) - dat = (dat & ~0xf0) | ((svga->attrregs[0x14] & 0x0f) << 4); - p[3] = svga->map8[dat & 0xff]; + for (int x = 0; x <= (svga->hdisp /* + svga->scrollcache*/); x += 8) { + dat = *(uint32_t *) (&svga->vram[svga->ma & svga->vram_display_mask]); + if (svga->attrregs[0x10] & 0x80) + dat = (dat & ~0xf0) | ((svga->attrregs[0x14] & 0x0f) << 4); + p[0] = svga->map8[dat & 0xff]; + dat >>= 8; + if (svga->attrregs[0x10] & 0x80) + dat = (dat & ~0xf0) | ((svga->attrregs[0x14] & 0x0f) << 4); + p[1] = svga->map8[dat & 0xff]; + dat >>= 8; + if (svga->attrregs[0x10] & 0x80) + dat = (dat & ~0xf0) | ((svga->attrregs[0x14] & 0x0f) << 4); + p[2] = svga->map8[dat & 0xff]; + dat >>= 8; + if (svga->attrregs[0x10] & 0x80) + dat = (dat & ~0xf0) | ((svga->attrregs[0x14] & 0x0f) << 4); + p[3] = svga->map8[dat & 0xff]; - dat = *(uint32_t *)(&svga->vram[(svga->ma + 4) & svga->vram_display_mask]); - if (svga->attrregs[0x10] & 0x80) - dat = (dat & ~0xf0) | ((svga->attrregs[0x14] & 0x0f) << 4); - p[4] = svga->map8[dat & 0xff]; - dat >>= 8; - if (svga->attrregs[0x10] & 0x80) - dat = (dat & ~0xf0) | ((svga->attrregs[0x14] & 0x0f) << 4); - p[5] = svga->map8[dat & 0xff]; - dat >>= 8; - if (svga->attrregs[0x10] & 0x80) - dat = (dat & ~0xf0) | ((svga->attrregs[0x14] & 0x0f) << 4); - p[6] = svga->map8[dat & 0xff]; - dat >>= 8; - if (svga->attrregs[0x10] & 0x80) - dat = (dat & ~0xf0) | ((svga->attrregs[0x14] & 0x0f) << 4); - p[7] = svga->map8[dat & 0xff]; - } else - memset(p, 0x00, 8 * sizeof(uint32_t)); + dat = *(uint32_t *) (&svga->vram[(svga->ma + 4) & svga->vram_display_mask]); + if (svga->attrregs[0x10] & 0x80) + dat = (dat & ~0xf0) | ((svga->attrregs[0x14] & 0x0f) << 4); + p[4] = svga->map8[dat & 0xff]; + dat >>= 8; + if (svga->attrregs[0x10] & 0x80) + dat = (dat & ~0xf0) | ((svga->attrregs[0x14] & 0x0f) << 4); + p[5] = svga->map8[dat & 0xff]; + dat >>= 8; + if (svga->attrregs[0x10] & 0x80) + dat = (dat & ~0xf0) | ((svga->attrregs[0x14] & 0x0f) << 4); + p[6] = svga->map8[dat & 0xff]; + dat >>= 8; + if (svga->attrregs[0x10] & 0x80) + dat = (dat & ~0xf0) | ((svga->attrregs[0x14] & 0x0f) << 4); + p[7] = svga->map8[dat & 0xff]; - svga->ma += 8; - p += 8; - } - svga->ma &= svga->vram_display_mask; + svga->ma += 8; + p += 8; + } + svga->ma &= svga->vram_display_mask; } } - void svga_render_15bpp_lowres(svga_t *svga) { - int x; + int x; uint32_t *p; - uint32_t dat; - uint32_t changed_addr, addr; + uint32_t dat; + uint32_t changed_addr; + uint32_t addr; if ((svga->displine + svga->y_add) < 0) - return; + return; - changed_addr = svga->remap_func(svga, svga->ma); + if (svga->force_old_addr) { + if (svga->changedvram[svga->ma >> 12] || svga->changedvram[(svga->ma >> 12) + 1] || svga->fullchange) { + p = &svga->monitor->target_buffer->line[svga->displine + svga->y_add][svga->x_add]; - if (svga->changedvram[changed_addr >> 12] || svga->changedvram[(changed_addr >> 12) + 1] || svga->fullchange) { - p = &buffer32->line[svga->displine + svga->y_add][svga->x_add]; + if (svga->firstline_draw == 2000) + svga->firstline_draw = svga->displine; + svga->lastline_draw = svga->displine; - if (svga->firstline_draw == 2000) - svga->firstline_draw = svga->displine; - svga->lastline_draw = svga->displine; - - if (!svga->remap_required) { - for (x = 0; x <= (svga->hdisp + svga->scrollcache); x += 4) { - if (svga->crtc[0x17] & 0x80) { - dat = *(uint32_t *)(&svga->vram[(svga->ma + (x << 1)) & svga->vram_display_mask]); + for (x = 0; x <= (svga->hdisp + svga->scrollcache); x += 4) { + dat = *(uint32_t *) (&svga->vram[(svga->ma + (x << 1)) & svga->vram_display_mask]); - *p++ = video_15to32[dat & 0xffff]; - *p++ = video_15to32[dat >> 16]; + p[x << 1] = p[(x << 1) + 1] = video_15to32[dat & 0xffff]; + p[(x << 1) + 2] = p[(x << 1) + 3] = video_15to32[dat >> 16]; - dat = *(uint32_t *)(&svga->vram[(svga->ma + (x << 1) + 4) & svga->vram_display_mask]); + dat = *(uint32_t *) (&svga->vram[(svga->ma + (x << 1) + 4) & svga->vram_display_mask]); - *p++ = video_15to32[dat & 0xffff]; - *p++ = video_15to32[dat >> 16]; - } else - memset(&(p[(x << 1)]), 0x00, 8 * sizeof(uint32_t)); - } - svga->ma += x << 1; - } else { - for (x = 0; x <= (svga->hdisp + svga->scrollcache); x += 2) { - if (svga->crtc[0x17] & 0x80) { - addr = svga->remap_func(svga, svga->ma); - dat = *(uint32_t *)(&svga->vram[addr & svga->vram_display_mask]); + p[(x << 1) + 4] = p[(x << 1) + 5] = video_15to32[dat & 0xffff]; + p[(x << 1) + 6] = p[(x << 1) + 7] = video_15to32[dat >> 16]; + } + svga->ma += x << 1; + svga->ma &= svga->vram_display_mask; + } + } else { + changed_addr = svga->remap_func(svga, svga->ma); - *p++ = video_15to32[dat & 0xffff]; - *p++ = video_15to32[dat >> 16]; - } else - memset(&(p[x]), 0x00, 2 * sizeof(uint32_t)); - svga->ma += 4; - } - } - svga->ma &= svga->vram_display_mask; + if (svga->changedvram[changed_addr >> 12] || svga->changedvram[(changed_addr >> 12) + 1] || svga->fullchange) { + p = &svga->monitor->target_buffer->line[svga->displine + svga->y_add][svga->x_add]; + + if (svga->firstline_draw == 2000) + svga->firstline_draw = svga->displine; + svga->lastline_draw = svga->displine; + + if (!svga->remap_required) { + for (x = 0; x <= (svga->hdisp + svga->scrollcache); x += 4) { + dat = *(uint32_t *) (&svga->vram[(svga->ma + (x << 1)) & svga->vram_display_mask]); + + *p++ = video_15to32[dat & 0xffff]; + *p++ = video_15to32[dat >> 16]; + + dat = *(uint32_t *) (&svga->vram[(svga->ma + (x << 1) + 4) & svga->vram_display_mask]); + + *p++ = video_15to32[dat & 0xffff]; + *p++ = video_15to32[dat >> 16]; + } + svga->ma += x << 1; + } else { + for (x = 0; x <= (svga->hdisp + svga->scrollcache); x += 2) { + addr = svga->remap_func(svga, svga->ma); + dat = *(uint32_t *) (&svga->vram[addr & svga->vram_display_mask]); + + *p++ = video_15to32[dat & 0xffff]; + *p++ = video_15to32[dat >> 16]; + svga->ma += 4; + } + } + svga->ma &= svga->vram_display_mask; + } } } - void svga_render_15bpp_highres(svga_t *svga) { - int x; + int x; uint32_t *p; - uint32_t dat; - uint32_t changed_addr, addr; + uint32_t dat; + uint32_t changed_addr; + uint32_t addr; if ((svga->displine + svga->y_add) < 0) - return; + return; - changed_addr = svga->remap_func(svga, svga->ma); + if (svga->force_old_addr) { + if (svga->changedvram[svga->ma >> 12] || svga->changedvram[(svga->ma >> 12) + 1] || svga->fullchange) { + p = &svga->monitor->target_buffer->line[svga->displine + svga->y_add][svga->x_add]; - if (svga->changedvram[changed_addr >> 12] || svga->changedvram[(changed_addr >> 12) + 1] || svga->fullchange) { - p = &buffer32->line[svga->displine + svga->y_add][svga->x_add]; + if (svga->firstline_draw == 2000) + svga->firstline_draw = svga->displine; + svga->lastline_draw = svga->displine; - if (svga->firstline_draw == 2000) - svga->firstline_draw = svga->displine; - svga->lastline_draw = svga->displine; - - if (!svga->remap_required) { - for (x = 0; x <= (svga->hdisp + svga->scrollcache); x += 8) { - if (svga->crtc[0x17] & 0x80) { - dat = *(uint32_t *)(&svga->vram[(svga->ma + (x << 1)) & svga->vram_display_mask]); - *p++ = video_15to32[dat & 0xffff]; - *p++ = video_15to32[dat >> 16]; + for (x = 0; x <= (svga->hdisp + svga->scrollcache); x += 8) { + dat = *(uint32_t *) (&svga->vram[(svga->ma + (x << 1)) & svga->vram_display_mask]); + p[x] = video_15to32[dat & 0xffff]; + p[x + 1] = video_15to32[dat >> 16]; - dat = *(uint32_t *)(&svga->vram[(svga->ma + (x << 1) + 4) & svga->vram_display_mask]); - *p++ = video_15to32[dat & 0xffff]; - *p++ = video_15to32[dat >> 16]; + dat = *(uint32_t *) (&svga->vram[(svga->ma + (x << 1) + 4) & svga->vram_display_mask]); + p[x + 2] = video_15to32[dat & 0xffff]; + p[x + 3] = video_15to32[dat >> 16]; - dat = *(uint32_t *)(&svga->vram[(svga->ma + (x << 1) + 8) & svga->vram_display_mask]); - *p++ = video_15to32[dat & 0xffff]; - *p++ = video_15to32[dat >> 16]; + dat = *(uint32_t *) (&svga->vram[(svga->ma + (x << 1) + 8) & svga->vram_display_mask]); + p[x + 4] = video_15to32[dat & 0xffff]; + p[x + 5] = video_15to32[dat >> 16]; - dat = *(uint32_t *)(&svga->vram[(svga->ma + (x << 1) + 12) & svga->vram_display_mask]); - *p++ = video_15to32[dat & 0xffff]; - *p++ = video_15to32[dat >> 16]; - } else - memset(&(p[x]), 0x00, 8 * sizeof(uint32_t)); - } - svga->ma += x << 1; - } else { - for (x = 0; x <= (svga->hdisp + svga->scrollcache); x += 2) { - if (svga->crtc[0x17] & 0x80) { - addr = svga->remap_func(svga, svga->ma); - dat = *(uint32_t *)(&svga->vram[addr & svga->vram_display_mask]); + dat = *(uint32_t *) (&svga->vram[(svga->ma + (x << 1) + 12) & svga->vram_display_mask]); + p[x + 6] = video_15to32[dat & 0xffff]; + p[x + 7] = video_15to32[dat >> 16]; + } + svga->ma += x << 1; + svga->ma &= svga->vram_display_mask; + } + } else { + changed_addr = svga->remap_func(svga, svga->ma); - *p++ = video_15to32[dat & 0xffff]; - *p++ = video_15to32[dat >> 16]; - } else - memset(&(p[x]), 0x00, 2 * sizeof(uint32_t)); - svga->ma += 4; - } - } - svga->ma &= svga->vram_display_mask; + if (svga->changedvram[changed_addr >> 12] || svga->changedvram[(changed_addr >> 12) + 1] || svga->fullchange) { + p = &svga->monitor->target_buffer->line[svga->displine + svga->y_add][svga->x_add]; + + if (svga->firstline_draw == 2000) + svga->firstline_draw = svga->displine; + svga->lastline_draw = svga->displine; + + if (!svga->remap_required) { + for (x = 0; x <= (svga->hdisp + svga->scrollcache); x += 8) { + dat = *(uint32_t *) (&svga->vram[(svga->ma + (x << 1)) & svga->vram_display_mask]); + *p++ = video_15to32[dat & 0xffff]; + *p++ = video_15to32[dat >> 16]; + + dat = *(uint32_t *) (&svga->vram[(svga->ma + (x << 1) + 4) & svga->vram_display_mask]); + *p++ = video_15to32[dat & 0xffff]; + *p++ = video_15to32[dat >> 16]; + + dat = *(uint32_t *) (&svga->vram[(svga->ma + (x << 1) + 8) & svga->vram_display_mask]); + *p++ = video_15to32[dat & 0xffff]; + *p++ = video_15to32[dat >> 16]; + + dat = *(uint32_t *) (&svga->vram[(svga->ma + (x << 1) + 12) & svga->vram_display_mask]); + *p++ = video_15to32[dat & 0xffff]; + *p++ = video_15to32[dat >> 16]; + } + svga->ma += x << 1; + } else { + for (x = 0; x <= (svga->hdisp + svga->scrollcache); x += 2) { + addr = svga->remap_func(svga, svga->ma); + dat = *(uint32_t *) (&svga->vram[addr & svga->vram_display_mask]); + + *p++ = video_15to32[dat & 0xffff]; + *p++ = video_15to32[dat >> 16]; + svga->ma += 4; + } + } + svga->ma &= svga->vram_display_mask; + } } } - void svga_render_15bpp_mix_lowres(svga_t *svga) { - int x; + int x; uint32_t *p; - uint32_t dat; + uint32_t dat; if ((svga->displine + svga->y_add) < 0) - return; + return; if (svga->changedvram[svga->ma >> 12] || svga->changedvram[(svga->ma >> 12) + 1] || svga->fullchange) { - p = &buffer32->line[svga->displine + svga->y_add][svga->x_add]; + p = &svga->monitor->target_buffer->line[svga->displine + svga->y_add][svga->x_add]; - if (svga->firstline_draw == 2000) - svga->firstline_draw = svga->displine; - svga->lastline_draw = svga->displine; + if (svga->firstline_draw == 2000) + svga->firstline_draw = svga->displine; + svga->lastline_draw = svga->displine; - for (x = 0; x <= (svga->hdisp + svga->scrollcache); x += 4) { - if (svga->crtc[0x17] & 0x80) { - dat = *(uint32_t *)(&svga->vram[(svga->ma + (x << 1)) & svga->vram_display_mask]); - p[(x << 1)] = p[(x << 1) + 1] = (dat & 0x00008000) ? svga->pallook[dat & 0xff] : video_15to32[dat & 0xffff]; + for (x = 0; x <= (svga->hdisp + svga->scrollcache); x += 4) { + dat = *(uint32_t *) (&svga->vram[(svga->ma + (x << 1)) & svga->vram_display_mask]); + p[x << 1] = p[(x << 1) + 1] = (dat & 0x00008000) ? svga->pallook[dat & 0xff] : video_15to32[dat & 0xffff]; - dat >>= 16; - p[(x << 1) + 2] = p[(x << 1) + 3] = (dat & 0x00008000) ? svga->pallook[dat & 0xff] : video_15to32[dat & 0xffff]; + dat >>= 16; + p[(x << 1) + 2] = p[(x << 1) + 3] = (dat & 0x00008000) ? svga->pallook[dat & 0xff] : video_15to32[dat & 0xffff]; - dat = *(uint32_t *)(&svga->vram[(svga->ma + (x << 1) + 4) & svga->vram_display_mask]); - p[(x << 1) + 4] = p[(x << 1) + 5] = (dat & 0x00008000) ? svga->pallook[dat & 0xff] : video_15to32[dat & 0xffff]; + dat = *(uint32_t *) (&svga->vram[(svga->ma + (x << 1) + 4) & svga->vram_display_mask]); + p[(x << 1) + 4] = p[(x << 1) + 5] = (dat & 0x00008000) ? svga->pallook[dat & 0xff] : video_15to32[dat & 0xffff]; - dat >>= 16; - p[(x << 1) + 6] = p[(x << 1) + 7] = (dat & 0x00008000) ? svga->pallook[dat & 0xff] : video_15to32[dat & 0xffff]; - } else - memset(&(p[(x << 1)]), 0x00, 8 * sizeof(uint32_t)); - } - svga->ma += x << 1; - svga->ma &= svga->vram_display_mask; + dat >>= 16; + p[(x << 1) + 6] = p[(x << 1) + 7] = (dat & 0x00008000) ? svga->pallook[dat & 0xff] : video_15to32[dat & 0xffff]; + } + svga->ma += x << 1; + svga->ma &= svga->vram_display_mask; } } - void svga_render_15bpp_mix_highres(svga_t *svga) { - int x; + int x; uint32_t *p; - uint32_t dat; + uint32_t dat; if ((svga->displine + svga->y_add) < 0) - return; + return; if (svga->changedvram[svga->ma >> 12] || svga->changedvram[(svga->ma >> 12) + 1] || svga->fullchange) { - p = &buffer32->line[svga->displine + svga->y_add][svga->x_add]; + p = &svga->monitor->target_buffer->line[svga->displine + svga->y_add][svga->x_add]; - if (svga->firstline_draw == 2000) - svga->firstline_draw = svga->displine; - svga->lastline_draw = svga->displine; + if (svga->firstline_draw == 2000) + svga->firstline_draw = svga->displine; + svga->lastline_draw = svga->displine; - for (x = 0; x <= (svga->hdisp + svga->scrollcache); x += 8) { - if (svga->crtc[0x17] & 0x80) { - dat = *(uint32_t *)(&svga->vram[(svga->ma + (x << 1)) & svga->vram_display_mask]); - p[x] = (dat & 0x00008000) ? svga->pallook[dat & 0xff] : video_15to32[dat & 0xffff]; - dat >>= 16; - p[x + 1] = (dat & 0x00008000) ? svga->pallook[dat & 0xff] : video_15to32[dat & 0xffff]; + for (x = 0; x <= (svga->hdisp + svga->scrollcache); x += 8) { + dat = *(uint32_t *) (&svga->vram[(svga->ma + (x << 1)) & svga->vram_display_mask]); + p[x] = (dat & 0x00008000) ? svga->pallook[dat & 0xff] : video_15to32[dat & 0xffff]; + dat >>= 16; + p[x + 1] = (dat & 0x00008000) ? svga->pallook[dat & 0xff] : video_15to32[dat & 0xffff]; - dat = *(uint32_t *)(&svga->vram[(svga->ma + (x << 1) + 4) & svga->vram_display_mask]); - p[x + 2] = (dat & 0x00008000) ? svga->pallook[dat & 0xff] : video_15to32[dat & 0xffff]; - dat >>= 16; - p[x + 3] = (dat & 0x00008000) ? svga->pallook[dat & 0xff] : video_15to32[dat & 0xffff]; + dat = *(uint32_t *) (&svga->vram[(svga->ma + (x << 1) + 4) & svga->vram_display_mask]); + p[x + 2] = (dat & 0x00008000) ? svga->pallook[dat & 0xff] : video_15to32[dat & 0xffff]; + dat >>= 16; + p[x + 3] = (dat & 0x00008000) ? svga->pallook[dat & 0xff] : video_15to32[dat & 0xffff]; - dat = *(uint32_t *)(&svga->vram[(svga->ma + (x << 1) + 8) & svga->vram_display_mask]); - p[x + 4] = (dat & 0x00008000) ? svga->pallook[dat & 0xff] : video_15to32[dat & 0xffff]; - dat >>= 16; - p[x + 5] = (dat & 0x00008000) ? svga->pallook[dat & 0xff] : video_15to32[dat & 0xffff]; + dat = *(uint32_t *) (&svga->vram[(svga->ma + (x << 1) + 8) & svga->vram_display_mask]); + p[x + 4] = (dat & 0x00008000) ? svga->pallook[dat & 0xff] : video_15to32[dat & 0xffff]; + dat >>= 16; + p[x + 5] = (dat & 0x00008000) ? svga->pallook[dat & 0xff] : video_15to32[dat & 0xffff]; - dat = *(uint32_t *)(&svga->vram[(svga->ma + (x << 1) + 12) & svga->vram_display_mask]); - p[x + 6] = (dat & 0x00008000) ? svga->pallook[dat & 0xff] : video_15to32[dat & 0xffff]; - dat >>= 16; - p[x + 7] = (dat & 0x00008000) ? svga->pallook[dat & 0xff] : video_15to32[dat & 0xffff]; - } else - memset(&(p[x]), 0x00, 8 * sizeof(uint32_t)); - } - svga->ma += x << 1; - svga->ma &= svga->vram_display_mask; + dat = *(uint32_t *) (&svga->vram[(svga->ma + (x << 1) + 12) & svga->vram_display_mask]); + p[x + 6] = (dat & 0x00008000) ? svga->pallook[dat & 0xff] : video_15to32[dat & 0xffff]; + dat >>= 16; + p[x + 7] = (dat & 0x00008000) ? svga->pallook[dat & 0xff] : video_15to32[dat & 0xffff]; + } + svga->ma += x << 1; + svga->ma &= svga->vram_display_mask; } } - void svga_render_16bpp_lowres(svga_t *svga) { - int x; + int x; uint32_t *p; - uint32_t dat; - uint32_t changed_addr, addr; + uint32_t dat; + uint32_t changed_addr; + uint32_t addr; if ((svga->displine + svga->y_add) < 0) - return; + return; - changed_addr = svga->remap_func(svga, svga->ma); + if (svga->force_old_addr) { + if (svga->changedvram[svga->ma >> 12] || svga->changedvram[(svga->ma >> 12) + 1] || svga->fullchange) { + p = &svga->monitor->target_buffer->line[svga->displine + svga->y_add][svga->x_add]; - if (svga->changedvram[changed_addr >> 12] || svga->changedvram[(changed_addr >> 12) + 1] || svga->fullchange) { - p = &buffer32->line[svga->displine + svga->y_add][svga->x_add]; + if (svga->firstline_draw == 2000) + svga->firstline_draw = svga->displine; + svga->lastline_draw = svga->displine; - if (svga->firstline_draw == 2000) - svga->firstline_draw = svga->displine; - svga->lastline_draw = svga->displine; - - if (!svga->remap_required) { - for (x = 0; x <= (svga->hdisp + svga->scrollcache); x += 4) { - if (svga->crtc[0x17] & 0x80) { - dat = *(uint32_t *)(&svga->vram[(svga->ma + (x << 1)) & svga->vram_display_mask]); + for (x = 0; x <= (svga->hdisp + svga->scrollcache); x += 4) { + dat = *(uint32_t *) (&svga->vram[(svga->ma + (x << 1)) & svga->vram_display_mask]); + p[x << 1] = p[(x << 1) + 1] = video_16to32[dat & 0xffff]; + p[(x << 1) + 2] = p[(x << 1) + 3] = video_16to32[dat >> 16]; - *p++ = video_16to32[dat & 0xffff]; - *p++ = video_16to32[dat >> 16]; + dat = *(uint32_t *) (&svga->vram[(svga->ma + (x << 1) + 4) & svga->vram_display_mask]); + p[(x << 1) + 4] = p[(x << 1) + 5] = video_16to32[dat & 0xffff]; + p[(x << 1) + 6] = p[(x << 1) + 7] = video_16to32[dat >> 16]; + } + svga->ma += x << 1; + svga->ma &= svga->vram_display_mask; + } + } else { + changed_addr = svga->remap_func(svga, svga->ma); - dat = *(uint32_t *)(&svga->vram[(svga->ma + (x << 1) + 4) & svga->vram_display_mask]); + if (svga->changedvram[changed_addr >> 12] || svga->changedvram[(changed_addr >> 12) + 1] || svga->fullchange) { + p = &svga->monitor->target_buffer->line[svga->displine + svga->y_add][svga->x_add]; - *p++ = video_16to32[dat & 0xffff]; - *p++ = video_16to32[dat >> 16]; - } else - memset(&(p[(x << 1)]), 0x00, 8 * sizeof(uint32_t)); - } - svga->ma += x << 1; - } else { - for (x = 0; x <= (svga->hdisp + svga->scrollcache); x += 2) { - if (svga->crtc[0x17] & 0x80) { - addr = svga->remap_func(svga, svga->ma); - dat = *(uint32_t *)(&svga->vram[addr & svga->vram_display_mask]); + if (svga->firstline_draw == 2000) + svga->firstline_draw = svga->displine; + svga->lastline_draw = svga->displine; - *p++ = video_16to32[dat & 0xffff]; - *p++ = video_16to32[dat >> 16]; - } else - memset(&(p[x]), 0x00, 2 * sizeof(uint32_t)); - } - svga->ma += 4; - } - svga->ma &= svga->vram_display_mask; + if (!svga->remap_required) { + for (x = 0; x <= (svga->hdisp + svga->scrollcache); x += 4) { + dat = *(uint32_t *) (&svga->vram[(svga->ma + (x << 1)) & svga->vram_display_mask]); + + *p++ = video_16to32[dat & 0xffff]; + *p++ = video_16to32[dat >> 16]; + + dat = *(uint32_t *) (&svga->vram[(svga->ma + (x << 1) + 4) & svga->vram_display_mask]); + + *p++ = video_16to32[dat & 0xffff]; + *p++ = video_16to32[dat >> 16]; + } + svga->ma += x << 1; + } else { + for (x = 0; x <= (svga->hdisp + svga->scrollcache); x += 2) { + addr = svga->remap_func(svga, svga->ma); + dat = *(uint32_t *) (&svga->vram[addr & svga->vram_display_mask]); + + *p++ = video_16to32[dat & 0xffff]; + *p++ = video_16to32[dat >> 16]; + } + svga->ma += 4; + } + svga->ma &= svga->vram_display_mask; + } } } - void svga_render_16bpp_highres(svga_t *svga) { - int x; + int x; uint32_t *p; - uint32_t dat; - uint32_t changed_addr, addr; + uint32_t dat; + uint32_t changed_addr; + uint32_t addr; if ((svga->displine + svga->y_add) < 0) - return; + return; - changed_addr = svga->remap_func(svga, svga->ma); + if (svga->force_old_addr) { + if (svga->changedvram[svga->ma >> 12] || svga->changedvram[(svga->ma >> 12) + 1] || svga->fullchange) { + p = &svga->monitor->target_buffer->line[svga->displine + svga->y_add][svga->x_add]; - if (svga->changedvram[changed_addr >> 12] || svga->changedvram[(changed_addr >> 12) + 1] || svga->fullchange) { - p = &buffer32->line[svga->displine + svga->y_add][svga->x_add]; + if (svga->firstline_draw == 2000) + svga->firstline_draw = svga->displine; + svga->lastline_draw = svga->displine; - if (svga->firstline_draw == 2000) - svga->firstline_draw = svga->displine; - svga->lastline_draw = svga->displine; - - if (!svga->remap_required) { - for (x = 0; x <= (svga->hdisp + svga->scrollcache); x += 8) { - if (svga->crtc[0x17] & 0x80) { - dat = *(uint32_t *)(&svga->vram[(svga->ma + (x << 1)) & svga->vram_display_mask]); - *p++ = video_16to32[dat & 0xffff]; - *p++ = video_16to32[dat >> 16]; + for (x = 0; x <= (svga->hdisp + svga->scrollcache); x += 8) { + uint32_t dat = *(uint32_t *) (&svga->vram[(svga->ma + (x << 1)) & svga->vram_display_mask]); + p[x] = video_16to32[dat & 0xffff]; + p[x + 1] = video_16to32[dat >> 16]; - dat = *(uint32_t *)(&svga->vram[(svga->ma + (x << 1) + 4) & svga->vram_display_mask]); - *p++ = video_16to32[dat & 0xffff]; - *p++ = video_16to32[dat >> 16]; + dat = *(uint32_t *) (&svga->vram[(svga->ma + (x << 1) + 4) & svga->vram_display_mask]); + p[x + 2] = video_16to32[dat & 0xffff]; + p[x + 3] = video_16to32[dat >> 16]; - dat = *(uint32_t *)(&svga->vram[(svga->ma + (x << 1) + 8) & svga->vram_display_mask]); - *p++ = video_16to32[dat & 0xffff]; - *p++ = video_16to32[dat >> 16]; + dat = *(uint32_t *) (&svga->vram[(svga->ma + (x << 1) + 8) & svga->vram_display_mask]); + p[x + 4] = video_16to32[dat & 0xffff]; + p[x + 5] = video_16to32[dat >> 16]; - dat = *(uint32_t *)(&svga->vram[(svga->ma + (x << 1) + 12) & svga->vram_display_mask]); - *p++ = video_16to32[dat & 0xffff]; - *p++ = video_16to32[dat >> 16]; - } else - memset(&(p[x]), 0x00, 8 * sizeof(uint32_t)); - } - svga->ma += x << 1; - } else { - for (x = 0; x <= (svga->hdisp + svga->scrollcache); x += 2) { - if (svga->crtc[0x17] & 0x80) { - addr = svga->remap_func(svga, svga->ma); - dat = *(uint32_t *)(&svga->vram[addr & svga->vram_display_mask]); + dat = *(uint32_t *) (&svga->vram[(svga->ma + (x << 1) + 12) & svga->vram_display_mask]); + p[x + 6] = video_16to32[dat & 0xffff]; + p[x + 7] = video_16to32[dat >> 16]; + } + svga->ma += x << 1; + svga->ma &= svga->vram_display_mask; + } + } else { + changed_addr = svga->remap_func(svga, svga->ma); - *p++ = video_16to32[dat & 0xffff]; - *p++ = video_16to32[dat >> 16]; - } else - memset(&(p[x]), 0x00, 2 * sizeof(uint32_t)); - - svga->ma += 4; - } - } - svga->ma &= svga->vram_display_mask; + if (svga->changedvram[changed_addr >> 12] || svga->changedvram[(changed_addr >> 12) + 1] || svga->fullchange) { + p = &svga->monitor->target_buffer->line[svga->displine + svga->y_add][svga->x_add]; + + if (svga->firstline_draw == 2000) + svga->firstline_draw = svga->displine; + svga->lastline_draw = svga->displine; + + if (!svga->remap_required) { + for (x = 0; x <= (svga->hdisp + svga->scrollcache); x += 8) { + dat = *(uint32_t *) (&svga->vram[(svga->ma + (x << 1)) & svga->vram_display_mask]); + *p++ = video_16to32[dat & 0xffff]; + *p++ = video_16to32[dat >> 16]; + + dat = *(uint32_t *) (&svga->vram[(svga->ma + (x << 1) + 4) & svga->vram_display_mask]); + *p++ = video_16to32[dat & 0xffff]; + *p++ = video_16to32[dat >> 16]; + + dat = *(uint32_t *) (&svga->vram[(svga->ma + (x << 1) + 8) & svga->vram_display_mask]); + *p++ = video_16to32[dat & 0xffff]; + *p++ = video_16to32[dat >> 16]; + + dat = *(uint32_t *) (&svga->vram[(svga->ma + (x << 1) + 12) & svga->vram_display_mask]); + *p++ = video_16to32[dat & 0xffff]; + *p++ = video_16to32[dat >> 16]; + } + svga->ma += x << 1; + } else { + for (x = 0; x <= (svga->hdisp + svga->scrollcache); x += 2) { + addr = svga->remap_func(svga, svga->ma); + dat = *(uint32_t *) (&svga->vram[addr & svga->vram_display_mask]); + + *p++ = video_16to32[dat & 0xffff]; + *p++ = video_16to32[dat >> 16]; + + svga->ma += 4; + } + } + svga->ma &= svga->vram_display_mask; + } } } - void svga_render_24bpp_lowres(svga_t *svga) { - int x; + int x; uint32_t *p; - uint32_t changed_addr, addr; - uint32_t dat0, dat1, dat2; + uint32_t changed_addr; + uint32_t addr; + uint32_t dat0; + uint32_t dat1; + uint32_t dat2; + uint32_t fg; if ((svga->displine + svga->y_add) < 0) - return; + return; - changed_addr = svga->remap_func(svga, svga->ma); - - if (svga->changedvram[changed_addr >> 12] || svga->changedvram[(changed_addr >> 12) + 1] || svga->fullchange) { - p = &buffer32->line[svga->displine + svga->y_add][svga->x_add]; + if (svga->force_old_addr) { + if ((svga->displine + svga->y_add) < 0) + return; - if (svga->firstline_draw == 2000) - svga->firstline_draw = svga->displine; - svga->lastline_draw = svga->displine; - - if (!svga->remap_required) { - for (x = 0; x <= (svga->hdisp + svga->scrollcache); x++) { - if (svga->crtc[0x17] & 0x80) { - dat0 = *(uint32_t *)(&svga->vram[svga->ma & svga->vram_display_mask]); - dat1 = *(uint32_t *)(&svga->vram[(svga->ma + 4) & svga->vram_display_mask]); - dat2 = *(uint32_t *)(&svga->vram[(svga->ma + 8) & svga->vram_display_mask]); - } else - dat0 = dat1 = dat2 = 0x00000000; + if (svga->changedvram[svga->ma >> 12] || svga->changedvram[(svga->ma >> 12) + 1] || svga->fullchange) { + if (svga->firstline_draw == 2000) + svga->firstline_draw = svga->displine; + svga->lastline_draw = svga->displine; - p[0] = p[1] = dat0 & 0xffffff; - p[2] = p[3] = (dat0 >> 24) | ((dat1 & 0xffff) << 8); - p[4] = p[5] = (dat1 >> 16) | ((dat2 & 0xff) << 16); - p[6] = p[7] = dat2 >> 8; - - svga->ma += 12; - } + for (x = 0; x <= (svga->hdisp + svga->scrollcache); x++) { + fg = svga->vram[svga->ma] | (svga->vram[svga->ma + 1] << 8) | (svga->vram[svga->ma + 2] << 16); + svga->ma += 3; + svga->ma &= svga->vram_display_mask; + svga->monitor->target_buffer->line[svga->displine + svga->y_add][(x << 1) + svga->x_add] = svga->monitor->target_buffer->line[svga->displine + svga->y_add][(x << 1) + 1 + svga->x_add] = fg; + } + } } else { - for (x = 0; x <= (svga->hdisp + svga->scrollcache); x += 4) { - if (svga->crtc[0x17] & 0x80) { - addr = svga->remap_func(svga, svga->ma); - dat0 = *(uint32_t *)(&svga->vram[addr & svga->vram_display_mask]); - addr = svga->remap_func(svga, svga->ma + 4); - dat1 = *(uint32_t *)(&svga->vram[addr & svga->vram_display_mask]); - addr = svga->remap_func(svga, svga->ma + 8); - dat2 = *(uint32_t *)(&svga->vram[addr & svga->vram_display_mask]); - } else - dat0 = dat1 = dat2 = 0x00000000; + changed_addr = svga->remap_func(svga, svga->ma); - p[0] = p[1] = dat0 & 0xffffff; - p[2] = p[3] = (dat0 >> 24) | ((dat1 & 0xffff) << 8); - p[4] = p[5] = (dat1 >> 16) | ((dat2 & 0xff) << 16); - p[6] = p[7] = dat2 >> 8; - - svga->ma += 12; - } - } - svga->ma &= svga->vram_display_mask; - } + if (svga->changedvram[changed_addr >> 12] || svga->changedvram[(changed_addr >> 12) + 1] || svga->fullchange) { + p = &svga->monitor->target_buffer->line[svga->displine + svga->y_add][svga->x_add]; + + if (svga->firstline_draw == 2000) + svga->firstline_draw = svga->displine; + svga->lastline_draw = svga->displine; + + if (!svga->remap_required) { + for (x = 0; x <= (svga->hdisp + svga->scrollcache); x++) { + dat0 = *(uint32_t *) (&svga->vram[svga->ma & svga->vram_display_mask]); + dat1 = *(uint32_t *) (&svga->vram[(svga->ma + 4) & svga->vram_display_mask]); + dat2 = *(uint32_t *) (&svga->vram[(svga->ma + 8) & svga->vram_display_mask]); + + p[0] = p[1] = dat0 & 0xffffff; + p[2] = p[3] = (dat0 >> 24) | ((dat1 & 0xffff) << 8); + p[4] = p[5] = (dat1 >> 16) | ((dat2 & 0xff) << 16); + p[6] = p[7] = dat2 >> 8; + + svga->ma += 12; + } + } else { + for (x = 0; x <= (svga->hdisp + svga->scrollcache); x += 4) { + addr = svga->remap_func(svga, svga->ma); + dat0 = *(uint32_t *) (&svga->vram[addr & svga->vram_display_mask]); + addr = svga->remap_func(svga, svga->ma + 4); + dat1 = *(uint32_t *) (&svga->vram[addr & svga->vram_display_mask]); + addr = svga->remap_func(svga, svga->ma + 8); + dat2 = *(uint32_t *) (&svga->vram[addr & svga->vram_display_mask]); + + p[0] = p[1] = dat0 & 0xffffff; + p[2] = p[3] = (dat0 >> 24) | ((dat1 & 0xffff) << 8); + p[4] = p[5] = (dat1 >> 16) | ((dat2 & 0xff) << 16); + p[6] = p[7] = dat2 >> 8; + + svga->ma += 12; + } + } + svga->ma &= svga->vram_display_mask; + } + } } - void svga_render_24bpp_highres(svga_t *svga) { - int x; + int x; uint32_t *p; - uint32_t changed_addr, addr; - uint32_t dat0, dat1, dat2; + uint32_t changed_addr; + uint8_t addr; + uint32_t dat0; + uint32_t dat1; + uint32_t dat2; + uint32_t dat; if ((svga->displine + svga->y_add) < 0) - return; + return; - changed_addr = svga->remap_func(svga, svga->ma); + if (svga->force_old_addr) { + if (svga->changedvram[svga->ma >> 12] || svga->changedvram[(svga->ma >> 12) + 1] || svga->fullchange) { + p = &svga->monitor->target_buffer->line[svga->displine + svga->y_add][svga->x_add]; - if (svga->changedvram[changed_addr >> 12] || svga->changedvram[(changed_addr >> 12) + 1] || svga->fullchange) { - p = &buffer32->line[svga->displine + svga->y_add][svga->x_add]; + if (svga->firstline_draw == 2000) + svga->firstline_draw = svga->displine; + svga->lastline_draw = svga->displine; - if (svga->firstline_draw == 2000) - svga->firstline_draw = svga->displine; - svga->lastline_draw = svga->displine; - - if (!svga->remap_required) { - for (x = 0; x <= (svga->hdisp + svga->scrollcache); x += 4) { - if (svga->crtc[0x17] & 0x80) { - dat0 = *(uint32_t *)(&svga->vram[svga->ma & svga->vram_display_mask]); - dat1 = *(uint32_t *)(&svga->vram[(svga->ma + 4) & svga->vram_display_mask]); - dat2 = *(uint32_t *)(&svga->vram[(svga->ma + 8) & svga->vram_display_mask]); + for (x = 0; x <= (svga->hdisp + svga->scrollcache); x += 4) { + dat = *(uint32_t *) (&svga->vram[svga->ma & svga->vram_display_mask]); + p[x] = dat & 0xffffff; - *p++ = dat0 & 0xffffff; - *p++ = (dat0 >> 24) | ((dat1 & 0xffff) << 8); - *p++ = (dat1 >> 16) | ((dat2 & 0xff) << 16); - *p++ = dat2 >> 8; - } else - memset(&(p[x]), 0x0, 4 * sizeof(uint32_t)); + dat = *(uint32_t *) (&svga->vram[(svga->ma + 3) & svga->vram_display_mask]); + p[x + 1] = dat & 0xffffff; - svga->ma += 12; - } - } else { - for (x = 0; x <= (svga->hdisp + svga->scrollcache); x += 4) { - if (svga->crtc[0x17] & 0x80) { - addr = svga->remap_func(svga, svga->ma); - dat0 = *(uint32_t *)(&svga->vram[addr & svga->vram_display_mask]); - addr = svga->remap_func(svga, svga->ma + 4); - dat1 = *(uint32_t *)(&svga->vram[addr & svga->vram_display_mask]); - addr = svga->remap_func(svga, svga->ma + 8); - dat2 = *(uint32_t *)(&svga->vram[addr & svga->vram_display_mask]); + dat = *(uint32_t *) (&svga->vram[(svga->ma + 6) & svga->vram_display_mask]); + p[x + 2] = dat & 0xffffff; - *p++ = dat0 & 0xffffff; - *p++ = (dat0 >> 24) | ((dat1 & 0xffff) << 8); - *p++ = (dat1 >> 16) | ((dat2 & 0xff) << 16); - *p++ = dat2 >> 8; - } else - memset(&(p[x]), 0x0, 4 * sizeof(uint32_t)); + dat = *(uint32_t *) (&svga->vram[(svga->ma + 9) & svga->vram_display_mask]); + p[x + 3] = dat & 0xffffff; - svga->ma += 12; - } - } - svga->ma &= svga->vram_display_mask; + svga->ma += 12; + } + svga->ma &= svga->vram_display_mask; + } + } else { + changed_addr = svga->remap_func(svga, svga->ma); + + if (svga->changedvram[changed_addr >> 12] || svga->changedvram[(changed_addr >> 12) + 1] || svga->fullchange) { + p = &svga->monitor->target_buffer->line[svga->displine + svga->y_add][svga->x_add]; + + if (svga->firstline_draw == 2000) + svga->firstline_draw = svga->displine; + svga->lastline_draw = svga->displine; + + if (!svga->remap_required) { + for (x = 0; x <= (svga->hdisp + svga->scrollcache); x += 4) { + dat0 = *(uint32_t *) (&svga->vram[svga->ma & svga->vram_display_mask]); + dat1 = *(uint32_t *) (&svga->vram[(svga->ma + 4) & svga->vram_display_mask]); + dat2 = *(uint32_t *) (&svga->vram[(svga->ma + 8) & svga->vram_display_mask]); + + *p++ = dat0 & 0xffffff; + *p++ = (dat0 >> 24) | ((dat1 & 0xffff) << 8); + *p++ = (dat1 >> 16) | ((dat2 & 0xff) << 16); + *p++ = dat2 >> 8; + + svga->ma += 12; + } + } else { + for (x = 0; x <= (svga->hdisp + svga->scrollcache); x += 4) { + addr = svga->remap_func(svga, svga->ma); + dat0 = *(uint32_t *) (&svga->vram[addr & svga->vram_display_mask]); + addr = svga->remap_func(svga, svga->ma + 4); + dat1 = *(uint32_t *) (&svga->vram[addr & svga->vram_display_mask]); + addr = svga->remap_func(svga, svga->ma + 8); + dat2 = *(uint32_t *) (&svga->vram[addr & svga->vram_display_mask]); + + *p++ = dat0 & 0xffffff; + *p++ = (dat0 >> 24) | ((dat1 & 0xffff) << 8); + *p++ = (dat1 >> 16) | ((dat2 & 0xff) << 16); + *p++ = dat2 >> 8; + + svga->ma += 12; + } + } + svga->ma &= svga->vram_display_mask; + } } } - void svga_render_32bpp_lowres(svga_t *svga) { - int x; - uint32_t *p; - uint32_t dat; - uint32_t changed_addr, addr; + int x; + uint32_t *p; + uint32_t dat; + uint32_t changed_addr; + uint32_t addr; if ((svga->displine + svga->y_add) < 0) - return; + return; - changed_addr = svga->remap_func(svga, svga->ma); + if (svga->force_old_addr) { + if (svga->changedvram[svga->ma >> 12] || svga->changedvram[(svga->ma >> 12) + 1] || svga->fullchange) { + if (svga->firstline_draw == 2000) + svga->firstline_draw = svga->displine; + svga->lastline_draw = svga->displine; - if (svga->changedvram[changed_addr >> 12] || svga->changedvram[(changed_addr >> 12) + 1] || svga->fullchange) { - p = &buffer32->line[svga->displine + svga->y_add][svga->x_add]; - - if (svga->firstline_draw == 2000) - svga->firstline_draw = svga->displine; - svga->lastline_draw = svga->displine; - - if (!svga->remap_required) { - for (x = 0; x <= (svga->hdisp + svga->scrollcache); x++) { - if (svga->crtc[0x17] & 0x80) - dat = *(uint32_t *)(&svga->vram[(svga->ma + (x << 2)) & svga->vram_display_mask]); - else - dat = 0x00000000; - *p++ = dat & 0xffffff; - *p++ = dat & 0xffffff; - } - svga->ma += (x * 4); - } else { - for (x = 0; x <= (svga->hdisp + svga->scrollcache); x++) { - if (svga->crtc[0x17] & 0x80) { - addr = svga->remap_func(svga, svga->ma); - dat = *(uint32_t *)(&svga->vram[addr & svga->vram_display_mask]); - } else - dat = 0x00000000; - *p++ = dat & 0xffffff; - *p++ = dat & 0xffffff; - svga->ma += 4; - } - svga->ma &= svga->vram_display_mask; - } + for (x = 0; x <= (svga->hdisp + svga->scrollcache); x++) { + dat = svga->vram[svga->ma] | (svga->vram[svga->ma + 1] << 8) | (svga->vram[svga->ma + 2] << 16); + svga->ma += 4; + svga->ma &= svga->vram_display_mask; + svga->monitor->target_buffer->line[svga->displine + svga->y_add][(x << 1) + svga->x_add] = svga->monitor->target_buffer->line[svga->displine + svga->y_add][(x << 1) + 1 + svga->x_add] = dat; + } + } + } else { + changed_addr = svga->remap_func(svga, svga->ma); + + if (svga->changedvram[changed_addr >> 12] || svga->changedvram[(changed_addr >> 12) + 1] || svga->fullchange) { + p = &svga->monitor->target_buffer->line[svga->displine + svga->y_add][svga->x_add]; + + if (svga->firstline_draw == 2000) + svga->firstline_draw = svga->displine; + svga->lastline_draw = svga->displine; + + if (!svga->remap_required) { + for (x = 0; x <= (svga->hdisp + svga->scrollcache); x++) { + dat = *(uint32_t *) (&svga->vram[(svga->ma + (x << 2)) & svga->vram_display_mask]); + *p++ = dat & 0xffffff; + *p++ = dat & 0xffffff; + } + svga->ma += (x * 4); + } else { + for (x = 0; x <= (svga->hdisp + svga->scrollcache); x++) { + addr = svga->remap_func(svga, svga->ma); + dat = *(uint32_t *) (&svga->vram[addr & svga->vram_display_mask]); + *p++ = dat & 0xffffff; + *p++ = dat & 0xffffff; + svga->ma += 4; + } + svga->ma &= svga->vram_display_mask; + } + } } } - void svga_render_32bpp_highres(svga_t *svga) { - int x; + int x; uint32_t *p; - uint32_t dat; - uint32_t changed_addr, addr; + uint32_t dat; + uint32_t changed_addr; + uint32_t addr; if ((svga->displine + svga->y_add) < 0) - return; + return; - changed_addr = svga->remap_func(svga, svga->ma); + if (svga->force_old_addr) { + if (svga->changedvram[svga->ma >> 12] || svga->changedvram[(svga->ma >> 12) + 1] || svga->changedvram[(svga->ma >> 12) + 2] || svga->fullchange) { + p = &svga->monitor->target_buffer->line[svga->displine + svga->y_add][svga->x_add]; - if (svga->changedvram[changed_addr >> 12] || svga->changedvram[(changed_addr >> 12) + 1] || svga->fullchange) { - p = &buffer32->line[svga->displine + svga->y_add][svga->x_add]; - - if (svga->firstline_draw == 2000) - svga->firstline_draw = svga->displine; - svga->lastline_draw = svga->displine; - - if (!svga->remap_required) { - for (x = 0; x <= (svga->hdisp + svga->scrollcache); x++) { - if (svga->crtc[0x17] & 0x80) { - dat = *(uint32_t *)(&svga->vram[(svga->ma + (x << 2)) & svga->vram_display_mask]); - *p++ = dat & 0xffffff; - } else - memset(&(p[x]), 0x0, 1 * sizeof(uint32_t)); - } - svga->ma += (x * 4); - } else { - for (x = 0; x <= (svga->hdisp + svga->scrollcache); x++) { - if (svga->crtc[0x17] & 0x80) { - addr = svga->remap_func(svga, svga->ma); - dat = *(uint32_t *)(&svga->vram[addr & svga->vram_display_mask]); - *p++ = dat & 0xffffff; - } else - memset(&(p[x]), 0x0, 1 * sizeof(uint32_t)); + if (svga->firstline_draw == 2000) + svga->firstline_draw = svga->displine; + svga->lastline_draw = svga->displine; - svga->ma += 4; - } - } - svga->ma &= svga->vram_display_mask; + for (x = 0; x <= (svga->hdisp + svga->scrollcache); x++) { + dat = *(uint32_t *) (&svga->vram[(svga->ma + (x << 2)) & svga->vram_display_mask]); + p[x] = dat & 0xffffff; + } + svga->ma += 4; + svga->ma &= svga->vram_display_mask; + } + } else { + changed_addr = svga->remap_func(svga, svga->ma); + + if (svga->changedvram[changed_addr >> 12] || svga->changedvram[(changed_addr >> 12) + 1] || svga->fullchange) { + p = &svga->monitor->target_buffer->line[svga->displine + svga->y_add][svga->x_add]; + + if (svga->firstline_draw == 2000) + svga->firstline_draw = svga->displine; + svga->lastline_draw = svga->displine; + + if (!svga->remap_required) { + for (x = 0; x <= (svga->hdisp + svga->scrollcache); x++) { + dat = *(uint32_t *) (&svga->vram[(svga->ma + (x << 2)) & svga->vram_display_mask]); + *p++ = dat & 0xffffff; + } + svga->ma += (x * 4); + } else { + for (x = 0; x <= (svga->hdisp + svga->scrollcache); x++) { + addr = svga->remap_func(svga, svga->ma); + dat = *(uint32_t *) (&svga->vram[addr & svga->vram_display_mask]); + *p++ = dat & 0xffffff; + + svga->ma += 4; + } + } + svga->ma &= svga->vram_display_mask; + } } } - void svga_render_ABGR8888_highres(svga_t *svga) { - int x; + int x; uint32_t *p; - uint32_t dat; - uint32_t changed_addr, addr; + uint32_t dat; + uint32_t changed_addr; + uint32_t addr; if ((svga->displine + svga->y_add) < 0) - return; + return; - changed_addr = svga->remap_func(svga, svga->ma); + changed_addr = svga->remap_func(svga, svga->ma); if (svga->changedvram[changed_addr >> 12] || svga->changedvram[(changed_addr >> 12) + 1] || svga->fullchange) { - p = &buffer32->line[svga->displine + svga->y_add][svga->x_add]; - - if (svga->firstline_draw == 2000) - svga->firstline_draw = svga->displine; - svga->lastline_draw = svga->displine; - - if (!svga->remap_required) { - for (x = 0; x <= (svga->hdisp + svga->scrollcache); x++) { - if (svga->crtc[0x17] & 0x80) { - dat = *(uint32_t *)(&svga->vram[(svga->ma + (x << 2)) & svga->vram_display_mask]); - *p++ = ((dat & 0xff0000) >> 16) | (dat & 0x00ff00) | ((dat & 0x0000ff) << 16); - } else - memset(&(p[x]), 0x0, 1 * sizeof(uint32_t)); - } - svga->ma += x*4; - } else { - for (x = 0; x <= (svga->hdisp + svga->scrollcache); x++) { - if (svga->crtc[0x17] & 0x80) { - addr = svga->remap_func(svga, svga->ma); - dat = *(uint32_t *)(&svga->vram[addr & svga->vram_display_mask]); - *p++ = ((dat & 0xff0000) >> 16) | (dat & 0x00ff00) | ((dat & 0x0000ff) << 16); - } else - memset(&(p[x]), 0x0, 1 * sizeof(uint32_t)); - - svga->ma += 4; - } - } - svga->ma &= svga->vram_display_mask; + p = &svga->monitor->target_buffer->line[svga->displine + svga->y_add][svga->x_add]; + + if (svga->firstline_draw == 2000) + svga->firstline_draw = svga->displine; + svga->lastline_draw = svga->displine; + + if (!svga->remap_required) { + for (x = 0; x <= (svga->hdisp + svga->scrollcache); x++) { + dat = *(uint32_t *) (&svga->vram[(svga->ma + (x << 2)) & svga->vram_display_mask]); + *p++ = ((dat & 0xff0000) >> 16) | (dat & 0x00ff00) | ((dat & 0x0000ff) << 16); + } + svga->ma += x * 4; + } else { + for (x = 0; x <= (svga->hdisp + svga->scrollcache); x++) { + addr = svga->remap_func(svga, svga->ma); + dat = *(uint32_t *) (&svga->vram[addr & svga->vram_display_mask]); + *p++ = ((dat & 0xff0000) >> 16) | (dat & 0x00ff00) | ((dat & 0x0000ff) << 16); + + svga->ma += 4; + } + } + svga->ma &= svga->vram_display_mask; } } - void svga_render_RGBA8888_highres(svga_t *svga) { - int x; + int x; uint32_t *p; - uint32_t dat; - uint32_t changed_addr, addr; + uint32_t dat; + uint32_t changed_addr; + uint32_t addr; if ((svga->displine + svga->y_add) < 0) - return; + return; - changed_addr = svga->remap_func(svga, svga->ma); + changed_addr = svga->remap_func(svga, svga->ma); if (svga->changedvram[changed_addr >> 12] || svga->changedvram[(changed_addr >> 12) + 1] || svga->fullchange) { - p = &buffer32->line[svga->displine + svga->y_add][svga->x_add]; - - if (svga->firstline_draw == 2000) - svga->firstline_draw = svga->displine; - svga->lastline_draw = svga->displine; - - if (!svga->remap_required) { - for (x = 0; x <= (svga->hdisp + svga->scrollcache); x++) { - if (svga->crtc[0x17] & 0x80) { - dat = *(uint32_t *)(&svga->vram[(svga->ma + (x << 2)) & svga->vram_display_mask]); - *p++ = dat >> 8; - } else - memset(&(p[x]), 0x0, 1 * sizeof(uint32_t)); - } - svga->ma += (x * 4); - } else { - for (x = 0; x <= (svga->hdisp + svga->scrollcache); x++) { - if (svga->crtc[0x17] & 0x80) { - addr = svga->remap_func(svga, svga->ma); - dat = *(uint32_t *)(&svga->vram[addr & svga->vram_display_mask]); - *p++ = dat >> 8; - } else - memset(&(p[x]), 0x0, 1 * sizeof(uint32_t)); + p = &svga->monitor->target_buffer->line[svga->displine + svga->y_add][svga->x_add]; - svga->ma += 4; - } - } - svga->ma &= svga->vram_display_mask; + if (svga->firstline_draw == 2000) + svga->firstline_draw = svga->displine; + svga->lastline_draw = svga->displine; + + if (!svga->remap_required) { + for (x = 0; x <= (svga->hdisp + svga->scrollcache); x++) { + dat = *(uint32_t *) (&svga->vram[(svga->ma + (x << 2)) & svga->vram_display_mask]); + *p++ = dat >> 8; + } + svga->ma += (x * 4); + } else { + for (x = 0; x <= (svga->hdisp + svga->scrollcache); x++) { + addr = svga->remap_func(svga, svga->ma); + dat = *(uint32_t *) (&svga->vram[addr & svga->vram_display_mask]); + *p++ = dat >> 8; + + svga->ma += 4; + } + } + svga->ma &= svga->vram_display_mask; } } diff --git a/src/video/vid_table.c b/src/video/vid_table.c index db09d7757..b4198eefd 100644 --- a/src/video/vid_table.c +++ b/src/video/vid_table.c @@ -1,20 +1,20 @@ /* - * 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. + * 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. + * This file is part of the 86Box distribution. * - * Define all known video cards. + * Define all known video cards. * * * - * Authors: Miran Grca, - * Fred N. van Kempen, + * Authors: Miran Grca, + * Fred N. van Kempen, * - * Copyright 2016-2020 Miran Grca. - * Copyright 2017-2020 Fred N. van Kempen. + * Copyright 2016-2020 Miran Grca. + * Copyright 2017-2020 Fred N. van Kempen. */ #include #include @@ -36,363 +36,444 @@ #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; +typedef struct video_card_t { + const device_t *device; + int flags; } VIDEO_CARD; - -static video_timings_t timing_default = {VIDEO_ISA, 8, 16, 32, 8, 16, 32}; +static video_timings_t timing_default = { .type = VIDEO_ISA, .write_b = 8, .write_w = 16, .write_l = 32, .read_b = 8, .read_w = 16, .read_l = 32 }; static int was_reset = 0; - static const device_t vid_none_device = { - "None", - "none", - 0, 0, - NULL, NULL, NULL, - { NULL }, NULL, NULL, - NULL + .name = "None", + .internal_name = "none", + .flags = 0, + .local = 0, + .init = NULL, + .close = NULL, + .reset = NULL, + { .available = NULL }, + .speed_changed = NULL, + .force_redraw = NULL, + .config = NULL }; static const device_t vid_internal_device = { - "Internal", - "internal", - 0, 0, - NULL, NULL, NULL, - { NULL }, NULL, NULL, - NULL + .name = "Internal", + .internal_name = "internal", + .flags = 0, + .local = 0, + .init = NULL, + .close = NULL, + .reset = NULL, + { .available = NULL }, + .speed_changed = NULL, + .force_redraw = NULL, + .config = NULL }; static const VIDEO_CARD video_cards[] = { - { &vid_none_device }, - { &vid_internal_device }, - { &atiega_device }, - { &mach64gx_isa_device }, - { &ati28800k_device }, - { &ati18800_vga88_device }, - { &ati28800_device }, - { &compaq_ati28800_device }, + // clang-format off + { &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 }, + { &ati28800_device }, + { &compaq_ati28800_device }, #if defined(DEV_BRANCH) && defined(USE_XL24) - { &ati28800_wonderxl24_device }, + { &ati28800_wonderxl24_device }, #endif - { &ati18800_device }, + { &ati18800_device }, #if defined(DEV_BRANCH) && defined(USE_VGAWONDER) - { &ati18800_wonder_device }, + { &ati18800_wonder_device }, #endif - { &cga_device }, - { &sega_device }, - { &gd5401_isa_device }, - { &gd5402_isa_device }, - { &gd5420_isa_device }, - { &gd5422_isa_device }, - { &gd5426_isa_device }, - { &gd5426_diamond_speedstar_pro_a1_isa_device }, - { &gd5428_isa_device }, - { &gd5429_isa_device }, - { &gd5434_isa_device }, - { &gd5434_diamond_speedstar_64_a3_isa_device }, - { &compaq_cga_device }, - { &compaq_cga_2_device }, - { &cpqega_device }, - { &ega_device }, - { &g2_gc205_device }, - { &hercules_device }, - { &herculesplus_device }, - { &incolor_device }, - { &im1024_device }, - { &iskra_ega_device }, - { &et4000_kasan_isa_device }, - { &mda_device }, - { &genius_device }, - { &nga_device }, - { &ogc_device }, - { &oti037c_device }, - { &oti067_device }, - { &oti077_device }, - { ¶dise_pvga1a_device }, - { ¶dise_wd90c11_device }, - { ¶dise_wd90c30_device }, - { &colorplus_device }, - { &pgc_device }, - { &radius_svga_multiview_isa_device }, - { &realtek_rtg3106_device }, - { &s3_diamond_stealth_vram_isa_device }, - { &s3_orchid_86c911_isa_device }, - { &s3_ami_86c924_isa_device }, - { &s3_metheus_86c928_isa_device }, - { &s3_phoenix_86c801_isa_device }, - { &s3_spea_mirage_86c801_isa_device }, - { &sigma_device }, - { &tvga8900b_device }, - { &tvga8900d_device }, - { &tvga9000b_device }, - { &et4000k_isa_device }, - { &et2000_device }, - { &et4000_isa_device }, - { &et4000w32_device }, - { &et4000w32i_isa_device }, - { &vga_device }, - { &v7_vga_1024i_device }, - { &wy700_device }, - { &gd5428_mca_device }, - { &et4000_mca_device }, - { &radius_svga_multiview_mca_device }, - { &mach64gx_pci_device }, - { &mach64vt2_device }, - { &et4000w32p_revc_pci_device }, - { &et4000w32p_cardex_pci_device }, - { &et4000w32p_noncardex_pci_device }, - { &gd5430_pci_device, }, - { &gd5434_pci_device }, - { &gd5436_pci_device }, - { &gd5440_pci_device }, - { &gd5446_pci_device }, - { &gd5446_stb_pci_device }, - { &gd5480_pci_device }, - { &creative_voodoo_banshee_device }, - { &et4000w32p_pci_device }, - { &s3_spea_mercury_lite_86c928_pci_device }, - { &s3_diamond_stealth64_964_pci_device }, - { &s3_elsa_winner2000_pro_x_964_pci_device }, - { &s3_mirocrystal_20sv_964_pci_device }, - { &s3_bahamas64_pci_device }, - { &s3_phoenix_vision864_pci_device }, - { &s3_diamond_stealth_se_pci_device }, - { &s3_phoenix_trio32_pci_device }, - { &s3_diamond_stealth64_pci_device }, - { &s3_9fx_pci_device }, - { &s3_phoenix_trio64_pci_device }, - { &s3_elsa_winner2000_pro_x_pci_device }, - { &s3_mirovideo_40sv_ergo_968_pci_device }, - { &s3_9fx_771_pci_device }, - { &s3_phoenix_vision968_pci_device }, - { &s3_spea_mercury_p64v_pci_device }, - { &s3_9fx_531_pci_device }, - { &s3_phoenix_vision868_pci_device }, - { &s3_phoenix_trio64vplus_pci_device }, - { &s3_trio64v2_dx_pci_device }, - { &s3_virge_325_pci_device }, - { &s3_diamond_stealth_2000_pci_device }, - { &s3_diamond_stealth_3000_pci_device }, - { &s3_stb_velocity_3d_pci_device }, - { &s3_virge_375_pci_device }, - { &s3_diamond_stealth_2000pro_pci_device }, - { &s3_virge_385_pci_device }, - { &s3_virge_357_pci_device }, - { &s3_diamond_stealth_4000_pci_device }, - { &s3_trio3d2x_pci_device }, + { &cga_device }, + { &sega_device }, + { &gd5401_isa_device }, + { &gd5402_isa_device }, + { &gd5420_isa_device }, + { &gd5422_isa_device }, + { &gd5426_isa_device }, + { &gd5426_diamond_speedstar_pro_a1_isa_device }, + { &gd5428_boca_isa_device }, + { &gd5428_isa_device }, + { &gd5429_isa_device }, + { &gd5434_isa_device }, + { &gd5434_diamond_speedstar_64_a3_isa_device }, + { &compaq_cga_device }, + { &compaq_cga_2_device }, + { &cpqega_device }, + { &ega_device }, + { &g2_gc205_device }, + { &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 }, + { &mda_device, VIDEO_FLAG_TYPE_MDA }, + { &genius_device }, + { &nga_device }, + { &ogc_device }, + { &oti037c_device }, + { &oti067_device }, + { &oti077_device }, + { ¶dise_pvga1a_device }, + { ¶dise_wd90c11_device }, + { ¶dise_wd90c30_device }, + { &colorplus_device }, + { &pgc_device }, + { &cga_pravetz_device }, + { &radius_svga_multiview_isa_device }, + { &realtek_rtg3106_device }, + { &s3_diamond_stealth_vram_isa_device }, + { &s3_orchid_86c911_isa_device }, + { &s3_ami_86c924_isa_device }, + { &s3_metheus_86c928_isa_device }, + { &s3_phoenix_86c801_isa_device }, + { &s3_spea_mirage_86c801_isa_device }, + { &sigma_device }, + { &tvga8900b_device }, + { &tvga8900d_device }, + { &tvga9000b_device }, + { &nec_sv9000_device }, + { &et4000k_isa_device }, + { &et2000_device }, + { &et3000_isa_device }, + { &et4000_isa_device }, + { &et4000w32_device }, + { &et4000w32i_isa_device }, + { &vga_device }, + { &v7_vga_1024i_device }, + { &wy700_device }, + { &mach32_mca_device, VIDEO_FLAG_TYPE_8514 }, + { &gd5426_mca_device }, + { &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 }, + { &et4000w32p_revc_pci_device }, + { &et4000w32p_cardex_pci_device }, + { &et4000w32p_noncardex_pci_device }, + { &et4000w32p_pci_device }, + { &gd5430_pci_device, }, + { &gd5434_pci_device }, + { &gd5436_pci_device, VIDEO_FLAG_TYPE_SPECIAL }, + { &gd5440_pci_device }, + { &gd5446_pci_device, VIDEO_FLAG_TYPE_SPECIAL }, + { &gd5446_stb_pci_device,VIDEO_FLAG_TYPE_SPECIAL }, + { &gd5480_pci_device }, + { &s3_spea_mercury_lite_86c928_pci_device }, + { &s3_diamond_stealth64_964_pci_device }, + { &s3_elsa_winner2000_pro_x_964_pci_device }, + { &s3_mirocrystal_20sv_964_pci_device }, + { &s3_bahamas64_pci_device }, + { &s3_phoenix_vision864_pci_device }, + { &s3_diamond_stealth_se_pci_device }, + { &s3_phoenix_trio32_pci_device }, + { &s3_diamond_stealth64_pci_device }, + { &s3_9fx_pci_device }, + { &s3_phoenix_trio64_pci_device }, + { &s3_elsa_winner2000_pro_x_pci_device }, + { &s3_mirovideo_40sv_ergo_968_pci_device }, + { &s3_9fx_771_pci_device }, + { &s3_phoenix_vision968_pci_device }, + { &s3_spea_mercury_p64v_pci_device }, + { &s3_9fx_531_pci_device }, + { &s3_phoenix_vision868_pci_device }, + { &s3_phoenix_trio64vplus_pci_device }, + { &s3_trio64v2_dx_pci_device }, + { &s3_virge_325_pci_device }, + { &s3_diamond_stealth_2000_pci_device }, + { &s3_diamond_stealth_3000_pci_device }, + { &s3_stb_velocity_3d_pci_device }, + { &s3_virge_375_pci_device }, + { &s3_diamond_stealth_2000pro_pci_device }, + { &s3_virge_385_pci_device }, + { &s3_virge_357_pci_device }, + { &s3_diamond_stealth_4000_pci_device }, + { &s3_trio3d2x_pci_device }, #if defined(DEV_BRANCH) && defined(USE_MGA) - { &millennium_device }, - { &mystique_device }, - { &mystique_220_device }, + { &millennium_device, VIDEO_FLAG_TYPE_SPECIAL }, + { &mystique_device }, + { &mystique_220_device }, #endif - { &tgui9440_pci_device }, - { &tgui9660_pci_device }, - { &tgui9680_pci_device }, - { &voodoo_banshee_device }, - { &voodoo_3_2000_device }, - { &voodoo_3_3000_device }, - { &mach64gx_vlb_device }, - { &et4000w32i_vlb_device }, - { &et4000w32p_revc_vlb_device }, - { &et4000w32p_cardex_vlb_device }, - { &et4000w32p_vlb_device }, - { &et4000w32p_noncardex_vlb_device }, - { &gd5424_vlb_device }, - { &gd5426_vlb_device }, - { &gd5428_vlb_device }, - { &gd5428_diamond_speedstar_pro_b1_vlb_device }, - { &gd5429_vlb_device }, - { &gd5430_diamond_speedstar_pro_se_a8_vlb_device }, - { &gd5434_vlb_device }, - { &s3_metheus_86c928_vlb_device }, - { &s3_mirocrystal_8s_805_vlb_device }, - { &s3_mirocrystal_10sd_805_vlb_device }, - { &s3_phoenix_86c805_vlb_device }, - { &s3_spea_mirage_86c805_vlb_device }, - { &s3_diamond_stealth64_964_vlb_device }, - { &s3_mirocrystal_20sv_964_vlb_device }, - { &s3_mirocrystal_20sd_864_vlb_device }, - { &s3_bahamas64_vlb_device }, - { &s3_phoenix_vision864_vlb_device }, - { &s3_diamond_stealth_se_vlb_device }, - { &s3_phoenix_trio32_vlb_device }, - { &s3_diamond_stealth64_vlb_device }, - { &s3_9fx_vlb_device }, - { &s3_phoenix_trio64_vlb_device }, - { &s3_spea_mirage_p64_vlb_device }, - { &s3_phoenix_vision968_vlb_device }, - { &s3_phoenix_vision868_vlb_device }, - { &ht216_32_standalone_device }, - { &tgui9400cxi_device }, - { &tgui9440_vlb_device }, - { &s3_virge_357_agp_device }, - { &s3_diamond_stealth_4000_agp_device }, - { &s3_trio3d2x_agp_device }, - { &velocity_100_agp_device }, - { &voodoo_3_2000_agp_device }, - { &voodoo_3_3000_agp_device }, - { NULL } + { &tgui9440_pci_device }, + { &tgui9660_pci_device }, + { &tgui9680_pci_device }, + { &voodoo_banshee_device }, + { &creative_voodoo_banshee_device }, + { &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 }, + { &et4000w32p_revc_vlb_device }, + { &et4000w32p_cardex_vlb_device }, + { &et4000w32p_vlb_device }, + { &et4000w32p_noncardex_vlb_device }, + { &gd5424_vlb_device }, + { &gd5426_vlb_device }, + { &gd5428_vlb_device }, + { &gd5428_diamond_speedstar_pro_b1_vlb_device }, + { &gd5429_vlb_device }, + { &gd5430_diamond_speedstar_pro_se_a8_vlb_device }, + { &gd5430_vlb_device }, + { &gd5434_vlb_device }, + { &s3_metheus_86c928_vlb_device }, + { &s3_mirocrystal_8s_805_vlb_device }, + { &s3_mirocrystal_10sd_805_vlb_device }, + { &s3_phoenix_86c805_vlb_device }, + { &s3_spea_mirage_86c805_vlb_device }, + { &s3_diamond_stealth64_964_vlb_device }, + { &s3_mirocrystal_20sv_964_vlb_device }, + { &s3_mirocrystal_20sd_864_vlb_device }, + { &s3_bahamas64_vlb_device }, + { &s3_phoenix_vision864_vlb_device }, + { &s3_diamond_stealth_se_vlb_device }, + { &s3_phoenix_trio32_vlb_device }, + { &s3_diamond_stealth64_vlb_device }, + { &s3_9fx_vlb_device }, + { &s3_phoenix_trio64_vlb_device }, + { &s3_spea_mirage_p64_vlb_device }, + { &s3_phoenix_vision968_vlb_device }, + { &s3_phoenix_vision868_vlb_device }, + { &ht216_32_standalone_device }, + { &tgui9400cxi_device }, + { &tgui9440_vlb_device }, + { &s3_virge_357_agp_device }, + { &s3_diamond_stealth_4000_agp_device }, + { &s3_trio3d2x_agp_device }, + { &velocity_100_agp_device }, + { &velocity_200_agp_device }, + { &voodoo_3_1000_agp_device }, + { &voodoo_3_2000_agp_device }, + { &voodoo_3_3000_agp_device }, + { &voodoo_3_3500_agp_ntsc_device }, + { &voodoo_3_3500_agp_pal_device }, + { &compaq_voodoo_3_3500_agp_device }, + { &voodoo_3_3500_se_agp_device }, + { &voodoo_3_3500_si_agp_device }, + { NULL } + // clang-format on }; - #ifdef ENABLE_VID_TABLE_LOG int vid_table_do_log = ENABLE_VID_TABLE_LOG; - static void vid_table_log(const char *fmt, ...) { va_list ap; if (vid_table_do_log) { - va_start(ap, fmt); - pclog_ex(fmt, ap); - va_end(ap); + va_start(ap, fmt); + pclog_ex(fmt, ap); + va_end(ap); } } #else -#define vid_table_log(fmt, ...) +# define vid_table_log(fmt, ...) #endif - void video_reset_close(void) { + for (int i = 1; i < MONITORS_NUM; i++) + video_monitor_close(i); + + monitor_index_global = 0; video_inform(VIDEO_FLAG_TYPE_NONE, &timing_default); was_reset = 0; } - static void video_prepare(void) { /* Reset (deallocate) the video font arrays. */ if (fontdatksc5601) { - free(fontdatksc5601); - fontdatksc5601 = NULL; + free(fontdatksc5601); + fontdatksc5601 = NULL; } - /* Reset the CGA palette. */ - cga_palette = 0; - cgapal_rebuild(); - /* Reset the blend. */ herc_blend = 0; - /* Do an inform on the default values, so that that there's some sane values initialized - even if the device init function does not do an inform of its own. */ - video_inform(VIDEO_FLAG_TYPE_SPECIAL, &timing_default); -} + for (int i = 0; i < MONITORS_NUM; i++) { + /* Reset the CGA palette. */ + if (monitors[i].mon_cga_palette) + *monitors[i].mon_cga_palette = 0; + cgapal_rebuild_monitor(i); + /* Do an inform on the default values, so that that there's some sane values initialized + even if the device init function does not do an inform of its own. */ + video_inform_monitor(VIDEO_FLAG_TYPE_SPECIAL, &timing_default, i); + } +} void video_pre_reset(int card) { - if ((card == VID_NONE) || \ - (card == VID_INTERNAL) || machine_has_flags(machine, MACHINE_VIDEO_ONLY)) - video_prepare(); + if ((card == VID_NONE) || (card == VID_INTERNAL) || machine_has_flags(machine, MACHINE_VIDEO_ONLY)) + video_prepare(); } - void video_reset(int card) { /* This is needed to avoid duplicate resets. */ if ((video_get_type() != VIDEO_FLAG_TYPE_NONE) && was_reset) - return; + return; - vid_table_log("VIDEO: reset (gfxcard=%d, internal=%d)\n", - card, machine_has_flags(machine, MACHINE_VIDEO) ? 1 : 0); + vid_table_log("VIDEO: reset (gfxcard[0]=%d, internal=%d)\n", + card, machine_has_flags(machine, MACHINE_VIDEO) ? 1 : 0); + monitor_index_global = 0; loadfont("roms/video/mda/mda.rom", 0); - /* Do not initialize internal cards here. */ - if (!(card == VID_NONE) && \ - !(card == VID_INTERNAL) && !machine_has_flags(machine, MACHINE_VIDEO_ONLY)) { - vid_table_log("VIDEO: initializing '%s'\n", video_cards[card].name); - - video_prepare(); - - /* Initialize the video card. */ - device_add(video_cards[card].device); + if ((card != VID_NONE) && !machine_has_flags(machine, MACHINE_VIDEO_ONLY) && + (gfxcard[1] > VID_INTERNAL) && device_is_valid(video_card_getdevice(gfxcard[1]), machine)) { + video_monitor_init(1); + monitor_index_global = 1; + device_add(video_cards[gfxcard[1]].device); + monitor_index_global = 0; } - /* Enable the Voodoo if configured. */ - if (voodoo_enabled) - device_add(&voodoo_device); + /* Do not initialize internal cards here. */ + if ((card > VID_INTERNAL) && !machine_has_flags(machine, MACHINE_VIDEO_ONLY)) { + vid_table_log("VIDEO: initializing '%s'\n", video_cards[card].device->name); + + video_prepare(); + + /* Initialize the video card. */ + device_add(video_cards[card].device); + } was_reset = 1; } +void +video_post_reset(void) +{ + int ibm8514_has_vga = 0; + if (gfxcard[0] == VID_INTERNAL) + ibm8514_has_vga = (video_get_type_monitor(0) == VIDEO_FLAG_TYPE_8514); + else if (gfxcard[0] != VID_NONE) + ibm8514_has_vga = (video_card_get_flags(gfxcard[0]) == VIDEO_FLAG_TYPE_8514); + else + ibm8514_has_vga = 0; + + if (ibm8514_has_vga) + ibm8514_active = 1; + + if (ibm8514_standalone_enabled) + ibm8514_device_add(); + + if (xga_standalone_enabled) + xga_device_add(); + + /* Reset the graphics card (or do nothing if it was already done + by the machine's init function). */ + video_reset(gfxcard[0]); +} + +void +video_voodoo_init(void) +{ + /* Enable the Voodoo if configured. */ + if (voodoo_enabled) + device_add(&voodoo_device); +} int video_card_available(int card) { if (video_cards[card].device) - return(device_available(video_cards[card].device)); + return (device_available(video_cards[card].device)); - return(1); + return 1; } +int +video_card_get_flags(int card) +{ + return video_cards[card].flags; +} const device_t * video_card_getdevice(int card) { - return(video_cards[card].device); + return (video_cards[card].device); } - int video_card_has_config(int card) { - if (video_cards[card].device == NULL) return(0); + if (video_cards[card].device == NULL) + return 0; - return(video_cards[card].device->config ? 1 : 0); + return (device_has_config(video_cards[card].device) ? 1 : 0); } - -char * +const char * video_get_internal_name(int card) { return device_get_internal_name(video_cards[card].device); } - int video_get_video_from_internal_name(char *s) { int c = 0; while (video_cards[c].device != NULL) { - if (!strcmp((char *) video_cards[c].device->internal_name, s)) - return(c); - c++; + if (!strcmp(video_cards[c].device->internal_name, s)) + return c; + c++; } - return(0); + return 0; } - int video_is_mda(void) { return (video_get_type() == VIDEO_FLAG_TYPE_MDA); } - int video_is_cga(void) { return (video_get_type() == VIDEO_FLAG_TYPE_CGA); } - int 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_tgui9440.c b/src/video/vid_tgui9440.c index 529cc6460..0b5e99c4c 100644 --- a/src/video/vid_tgui9440.c +++ b/src/video/vid_tgui9440.c @@ -1,59 +1,59 @@ /* - * 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. + * 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. + * This file is part of the 86Box distribution. * - * Trident TGUI9400CXi and TGUI9440 emulation. + * Trident TGUI9400CXi and TGUI9440/96x0 emulation. * - * TGUI9400CXi has extended write modes, controlled by extended - * GDC registers : + * TGUI9400CXi has extended write modes, controlled by extended + * GDC registers : * - * GDC[0x10] - Control - * bit 0 - pixel width (1 = 16 bit, 0 = 8 bit) - * bit 1 - mono->colour expansion (1 = enabled, - * 0 = disabled) - * bit 2 - mono->colour expansion transparency - * (1 = transparent, 0 = opaque) - * bit 3 - extended latch copy - * GDC[0x11] - Background colour (low byte) - * GDC[0x12] - Background colour (high byte) - * GDC[0x14] - Foreground colour (low byte) - * GDC[0x15] - Foreground colour (high byte) - * GDC[0x17] - Write mask (low byte) - * GDC[0x18] - Write mask (high byte) + * GDC[0x10] - Control + * bit 0 - pixel width (1 = 16 bit, 0 = 8 bit) + * bit 1 - mono->colour expansion (1 = enabled, + * 0 = disabled) + * bit 2 - mono->colour expansion transparency + * (1 = transparent, 0 = opaque) + * bit 3 - extended latch copy + * GDC[0x11] - Background colour (low byte) + * GDC[0x12] - Background colour (high byte) + * GDC[0x14] - Foreground colour (low byte) + * GDC[0x15] - Foreground colour (high byte) + * GDC[0x17] - Write mask (low byte) + * GDC[0x18] - Write mask (high byte) * - * Mono->colour expansion will expand written data 8:1 to 8/16 - * consecutive bytes. - * MSB is processed first. On word writes, low byte is processed - * first. 1 bits write foreground colour, 0 bits write background - * colour unless transparency is enabled. - * If the relevant bit is clear in the write mask then the data - * is not written. + * Mono->colour expansion will expand written data 8:1 to 8/16 + * consecutive bytes. + * MSB is processed first. On word writes, low byte is processed + * first. 1 bits write foreground colour, 0 bits write background + * colour unless transparency is enabled. + * If the relevant bit is clear in the write mask then the data + * is not written. * - * With 16-bit pixel width, each bit still expands to one byte, - * so the TGUI driver doubles up monochrome data. + * With 16-bit pixel width, each bit still expands to one byte, + * so the TGUI driver doubles up monochrome data. * - * While there is room in the register map for three byte colours, - * I don't believe 24-bit colour is supported. The TGUI9440 - * blitter has the same limitation. + * While there is room in the register map for three byte colours, + * I don't believe 24-bit colour is supported. The TGUI9440 + * blitter has the same limitation. * - * I don't think double word writes are supported. + * I don't think double word writes are supported. * - * Extended latch copy uses an internal 16 byte latch. Reads load - * the latch, writing writes out 16 bytes. I don't think the - * access size or host data has any affect, but the Windows 3.1 - * driver always reads bytes and write words of 0xffff. + * Extended latch copy uses an internal 16 byte latch. Reads load + * the latch, writing writes out 16 bytes. I don't think the + * access size or host data has any affect, but the Windows 3.1 + * driver always reads bytes and write words of 0xffff. * * * - * Authors: Sarah Walker, - * Miran Grca, + * Authors: Sarah Walker, + * Miran Grca, * - * Copyright 2008-2019 Sarah Walker. - * Copyright 2016-2019 Miran Grca. + * Copyright 2008-2019 Sarah Walker. + * Copyright 2016-2019 Miran Grca. */ #include #include @@ -75,115 +75,117 @@ #include <86box/vid_svga.h> #include <86box/vid_svga_render.h> -#define ROM_TGUI_9400CXI "roms/video/tgui9440/9400CXI.VBI" -#define ROM_TGUI_9440 "roms/video/tgui9440/BIOS.BIN" -#define ROM_TGUI_96xx "roms/video/tgui9660/Union.VBI" +#define ROM_TGUI_9400CXI "roms/video/tgui9440/9400CXI.VBI" +#define ROM_TGUI_9440 "roms/video/tgui9440/BIOS.BIN" +#define ROM_TGUI_96xx "roms/video/tgui9660/Union.VBI" #define EXT_CTRL_16BIT 0x01 #define EXT_CTRL_MONO_EXPANSION 0x02 #define EXT_CTRL_MONO_TRANSPARENT 0x04 #define EXT_CTRL_LATCH_COPY 0x08 -enum -{ - TGUI_9400CXI = 0, - TGUI_9440, - TGUI_9660, - TGUI_9680 +enum { + TGUI_9400CXI = 0, + TGUI_9440, + TGUI_9660, + TGUI_9680 }; -#define ONBOARD 0x0100 +#define ONBOARD 0x0100 -typedef struct tgui_t -{ - mem_mapping_t linear_mapping; - mem_mapping_t accel_mapping; - mem_mapping_t mmio_mapping; +typedef struct tgui_t { + mem_mapping_t linear_mapping; + mem_mapping_t accel_mapping; + mem_mapping_t mmio_mapping; - rom_t bios_rom; - - svga_t svga; - int pci; - - int type, card; - - uint8_t int_line; - uint8_t pci_regs[256]; + rom_t bios_rom; - struct - { - int16_t src_x, src_y; - int16_t src_x_clip, src_y_clip; - int16_t dst_x, dst_y; - int16_t dst_y_clip, dst_x_clip; - int16_t size_x, size_y; - uint16_t sv_size_y; - uint16_t patloc; - uint32_t fg_col, bg_col; - uint32_t style, ckey; - uint8_t rop; - uint32_t flags; - uint8_t pattern[0x80]; - int command; - int offset; - uint16_t ger22; - - int16_t err, top, left, bottom, right; - int x, y, dx, dy; - uint32_t src, dst, src_old, dst_old; - int pat_x, pat_y; - int use_src; - - int pitch, bpp; - uint32_t fill_pattern[8*8]; - uint32_t mono_pattern[8*8]; - uint32_t pattern_8[8*8]; - uint32_t pattern_16[8*8]; - uint32_t pattern_32[8*8]; - } accel; + svga_t svga; + int pci; - uint8_t ext_gdc_regs[16]; /*TGUI9400CXi only*/ - uint8_t copy_latch[16]; + uint8_t pci_slot; + uint8_t irq_state; - uint8_t tgui_3d8, tgui_3d9; - int oldmode; - uint8_t oldctrl1, newctrl1; - uint8_t oldctrl2, newctrl2; - uint8_t oldgr0e, newgr0e; + int type; - uint32_t linear_base, linear_size, ge_base, - mmio_base; - uint32_t hwc_fg_col, hwc_bg_col; - - int ramdac_state; - uint8_t ramdac_ctrl; - - int clock_m, clock_n, clock_k; - - uint32_t vram_size, vram_mask; - - volatile int write_blitter; - void *i2c, *ddc; + uint8_t int_line; + uint8_t pci_regs[256]; - int has_bios; + struct + { + int16_t src_x, src_y; + int16_t src_x_clip, src_y_clip; + int16_t dst_x, dst_y; + int16_t dst_y_clip, dst_x_clip; + int16_t size_x, size_y; + uint16_t sv_size_y; + uint16_t patloc; + uint32_t fg_col, bg_col; + uint32_t style, ckey; + uint8_t rop; + uint32_t flags; + uint8_t pattern[0x80]; + int command; + int offset; + uint16_t ger22; + + int16_t err; + int16_t top, left, bottom, right; + int16_t x, y, cx, cy, dx, dy; + uint32_t src, dst, src_old, dst_old; + int pat_x, pat_y; + int use_src; + + int pitch, bpp; + uint32_t fill_pattern[8 * 8]; + uint32_t mono_pattern[8 * 8]; + uint32_t pattern_8[8 * 8]; + uint32_t pattern_16[8 * 8]; + uint32_t pattern_32[8 * 8]; + } accel; + + uint8_t ext_gdc_regs[16]; /*TGUI9400CXi only*/ + uint8_t copy_latch[16]; + + uint8_t tgui_3d8, tgui_3d9; + int oldmode; + uint8_t oldctrl1, newctrl1; + uint8_t oldctrl2, newctrl2; + uint8_t oldgr0e, newgr0e; + + uint32_t linear_base, linear_size, ge_base, + mmio_base; + uint32_t hwc_fg_col, hwc_bg_col; + + int ramdac_state; + uint8_t ramdac_ctrl; + + int clock_m, clock_n, clock_k; + + uint32_t vram_size, vram_mask; + + volatile int write_blitter; + void *i2c, *ddc; + + int has_bios; } tgui_t; -video_timings_t timing_tgui_vlb = {VIDEO_BUS, 4, 8, 16, 4, 8, 16}; -video_timings_t timing_tgui_pci = {VIDEO_PCI, 4, 8, 16, 4, 8, 16}; +video_timings_t timing_tgui_vlb = { .type = VIDEO_BUS, .write_b = 4, .write_w = 8, .write_l = 16, .read_b = 4, .read_w = 8, .read_l = 16 }; +video_timings_t timing_tgui_pci = { .type = VIDEO_PCI, .write_b = 4, .write_w = 8, .write_l = 16, .read_b = 4, .read_w = 8, .read_l = 16 }; -static void tgui_out(uint16_t addr, uint8_t val, void *p); -static uint8_t tgui_in(uint16_t addr, void *p); +static void tgui_out(uint16_t addr, uint8_t val, void *priv); +static uint8_t tgui_in(uint16_t addr, void *priv); static void tgui_recalcmapping(tgui_t *tgui); -static void tgui_accel_out(uint16_t addr, uint8_t val, void *p); -static void tgui_accel_out_w(uint16_t addr, uint16_t val, void *p); -static void tgui_accel_out_l(uint16_t addr, uint32_t val, void *p); -static uint8_t tgui_accel_in(uint16_t addr, void *p); -static uint16_t tgui_accel_in_w(uint16_t addr, void *p); -static uint32_t tgui_accel_in_l(uint16_t addr, void *p); +static void tgui_accel_out(uint16_t addr, uint8_t val, void *priv); +static void tgui_accel_out_w(uint16_t addr, uint16_t val, void *priv); +static void tgui_accel_out_l(uint16_t addr, uint32_t val, void *priv); +static uint8_t tgui_accel_in(uint16_t addr, void *priv); +static uint16_t tgui_accel_in_w(uint16_t addr, void *priv); +static uint32_t tgui_accel_in_l(uint16_t addr, void *priv); -static uint8_t tgui_accel_read(uint32_t addr, void *priv); +static uint8_t tgui_accel_read(uint32_t addr, void *priv); static uint16_t tgui_accel_read_w(uint32_t addr, void *priv); static uint32_t tgui_accel_read_l(uint32_t addr, void *priv); @@ -195,3127 +197,3205 @@ static void tgui_accel_write_fb_b(uint32_t addr, uint8_t val, void *priv); static void tgui_accel_write_fb_w(uint32_t addr, uint16_t val, void *priv); static void tgui_accel_write_fb_l(uint32_t addr, uint32_t val, void *priv); -static uint8_t tgui_ext_linear_read(uint32_t addr, void *p); -static void tgui_ext_linear_write(uint32_t addr, uint8_t val, void *p); -static void tgui_ext_linear_writew(uint32_t addr, uint16_t val, void *p); -static void tgui_ext_linear_writel(uint32_t addr, uint32_t val, void *p); - -static uint8_t tgui_ext_read(uint32_t addr, void *p); -static void tgui_ext_write(uint32_t addr, uint8_t val, void *p); -static void tgui_ext_writew(uint32_t addr, uint16_t val, void *p); -static void tgui_ext_writel(uint32_t addr, uint32_t val, void *p); +static uint8_t tgui_ext_linear_read(uint32_t addr, void *priv); +static void tgui_ext_linear_write(uint32_t addr, uint8_t val, void *priv); +static void tgui_ext_linear_writew(uint32_t addr, uint16_t val, void *priv); +static void tgui_ext_linear_writel(uint32_t addr, uint32_t val, void *priv); +static uint8_t tgui_ext_read(uint32_t addr, void *priv); +static void tgui_ext_write(uint32_t addr, uint8_t val, void *priv); +static void tgui_ext_writew(uint32_t addr, uint16_t val, void *priv); +static void tgui_ext_writel(uint32_t addr, uint32_t val, void *priv); /*Remap address for chain-4/doubleword style layout*/ static __inline uint32_t dword_remap(svga_t *svga, uint32_t in_addr) { - if (svga->packed_chain4) - return in_addr; - - return ((in_addr << 2) & 0x3fff0) | - ((in_addr >> 14) & 0xc) | - (in_addr & ~0x3fffc); + if (svga->packed_chain4) + return in_addr; + + return ((in_addr << 2) & 0x3fff0) | ((in_addr >> 14) & 0xc) | (in_addr & ~0x3fffc); } static void tgui_update_irqs(tgui_t *tgui) { - if (!tgui->pci) - return; - - if (!(tgui->oldctrl1 & 0x40)) { - pci_set_irq(tgui->card, PCI_INTA); - } else { - pci_clear_irq(tgui->card, PCI_INTA); - } + if (!tgui->pci) + return; + + if (!(tgui->oldctrl1 & 0x40)) + pci_set_irq(tgui->pci_slot, PCI_INTA, &tgui->irq_state); + else + pci_clear_irq(tgui->pci_slot, PCI_INTA, &tgui->irq_state); } static void tgui_remove_io(tgui_t *tgui) { - io_removehandler(0x03c0, 0x0020, tgui_in, NULL, NULL, tgui_out, NULL, NULL, tgui); - if (tgui->type >= TGUI_9440) { - io_removehandler(0x43c6, 0x0004, tgui_in, NULL, NULL, tgui_out, NULL, NULL, tgui); - io_removehandler(0x83c6, 0x0003, tgui_in, NULL, NULL, tgui_out, NULL, NULL, tgui); - io_removehandler(0x2120, 0x0001, tgui_accel_in, tgui_accel_in_w, tgui_accel_in_l, tgui_accel_out, tgui_accel_out_w, tgui_accel_out_l, tgui); - io_removehandler(0x2122, 0x0002, tgui_accel_in, tgui_accel_in_w, tgui_accel_in_l, tgui_accel_out, tgui_accel_out_w, tgui_accel_out_l, tgui); - io_removehandler(0x2124, 0x0001, tgui_accel_in, tgui_accel_in_w, tgui_accel_in_l, tgui_accel_out, tgui_accel_out_w, tgui_accel_out_l, tgui); - io_removehandler(0x2127, 0x0001, tgui_accel_in, tgui_accel_in_w, tgui_accel_in_l, tgui_accel_out, tgui_accel_out_w, tgui_accel_out_l, tgui); - io_removehandler(0x2128, 0x0004, tgui_accel_in, tgui_accel_in_w, tgui_accel_in_l, tgui_accel_out, tgui_accel_out_w, tgui_accel_out_l, tgui); - io_removehandler(0x212c, 0x0004, tgui_accel_in, tgui_accel_in_w, tgui_accel_in_l, tgui_accel_out, tgui_accel_out_w, tgui_accel_out_l, tgui); - io_removehandler(0x2130, 0x0004, tgui_accel_in, tgui_accel_in_w, tgui_accel_in_l, tgui_accel_out, tgui_accel_out_w, tgui_accel_out_l, tgui); - io_removehandler(0x2134, 0x0002, tgui_accel_in, tgui_accel_in_w, tgui_accel_in_l, tgui_accel_out, tgui_accel_out_w, tgui_accel_out_l, tgui); - io_removehandler(0x2138, 0x0002, tgui_accel_in, tgui_accel_in_w, tgui_accel_in_l, tgui_accel_out, tgui_accel_out_w, tgui_accel_out_l, tgui); - io_removehandler(0x213a, 0x0002, tgui_accel_in, tgui_accel_in_w, tgui_accel_in_l, tgui_accel_out, tgui_accel_out_w, tgui_accel_out_l, tgui); - io_removehandler(0x213c, 0x0002, tgui_accel_in, tgui_accel_in_w, tgui_accel_in_l, tgui_accel_out, tgui_accel_out_w, tgui_accel_out_l, tgui); - io_removehandler(0x213e, 0x0002, tgui_accel_in, tgui_accel_in_w, tgui_accel_in_l, tgui_accel_out, tgui_accel_out_w, tgui_accel_out_l, tgui); - io_removehandler(0x2140, 0x0002, tgui_accel_in, tgui_accel_in_w, tgui_accel_in_l, tgui_accel_out, tgui_accel_out_w, tgui_accel_out_l, tgui); - io_removehandler(0x2142, 0x0002, tgui_accel_in, tgui_accel_in_w, tgui_accel_in_l, tgui_accel_out, tgui_accel_out_w, tgui_accel_out_l, tgui); - io_removehandler(0x2144, 0x0004, tgui_accel_in, tgui_accel_in_w, tgui_accel_in_l, tgui_accel_out, tgui_accel_out_w, tgui_accel_out_l, tgui); - io_removehandler(0x2148, 0x0004, tgui_accel_in, tgui_accel_in_w, tgui_accel_in_l, tgui_accel_out, tgui_accel_out_w, tgui_accel_out_l, tgui); - io_removehandler(0x2168, 0x0004, tgui_accel_in, tgui_accel_in_w, tgui_accel_in_l, tgui_accel_out, tgui_accel_out_w, tgui_accel_out_l, tgui); - io_removehandler(0x2178, 0x0004, tgui_accel_in, tgui_accel_in_w, tgui_accel_in_l, tgui_accel_out, tgui_accel_out_w, tgui_accel_out_l, tgui); - io_removehandler(0x217c, 0x0004, tgui_accel_in, tgui_accel_in_w, tgui_accel_in_l, tgui_accel_out, tgui_accel_out_w, tgui_accel_out_l, tgui); - io_removehandler(0x2180, 0x0080, tgui_accel_in, tgui_accel_in_w, tgui_accel_in_l, tgui_accel_out, tgui_accel_out_w, tgui_accel_out_l, tgui); - } + io_removehandler(0x03c0, 0x0020, tgui_in, NULL, NULL, tgui_out, NULL, NULL, tgui); + if (tgui->type >= TGUI_9440) { + io_removehandler(0x43c6, 0x0004, tgui_in, NULL, NULL, tgui_out, NULL, NULL, tgui); + io_removehandler(0x83c6, 0x0003, tgui_in, NULL, NULL, tgui_out, NULL, NULL, tgui); + io_removehandler(0x2120, 0x0001, tgui_accel_in, tgui_accel_in_w, tgui_accel_in_l, tgui_accel_out, tgui_accel_out_w, tgui_accel_out_l, tgui); + io_removehandler(0x2122, 0x0002, tgui_accel_in, tgui_accel_in_w, tgui_accel_in_l, tgui_accel_out, tgui_accel_out_w, tgui_accel_out_l, tgui); + io_removehandler(0x2124, 0x0001, tgui_accel_in, tgui_accel_in_w, tgui_accel_in_l, tgui_accel_out, tgui_accel_out_w, tgui_accel_out_l, tgui); + io_removehandler(0x2127, 0x0001, tgui_accel_in, tgui_accel_in_w, tgui_accel_in_l, tgui_accel_out, tgui_accel_out_w, tgui_accel_out_l, tgui); + io_removehandler(0x2128, 0x0004, tgui_accel_in, tgui_accel_in_w, tgui_accel_in_l, tgui_accel_out, tgui_accel_out_w, tgui_accel_out_l, tgui); + io_removehandler(0x212c, 0x0004, tgui_accel_in, tgui_accel_in_w, tgui_accel_in_l, tgui_accel_out, tgui_accel_out_w, tgui_accel_out_l, tgui); + io_removehandler(0x2130, 0x0004, tgui_accel_in, tgui_accel_in_w, tgui_accel_in_l, tgui_accel_out, tgui_accel_out_w, tgui_accel_out_l, tgui); + io_removehandler(0x2134, 0x0002, tgui_accel_in, tgui_accel_in_w, tgui_accel_in_l, tgui_accel_out, tgui_accel_out_w, tgui_accel_out_l, tgui); + io_removehandler(0x2138, 0x0002, tgui_accel_in, tgui_accel_in_w, tgui_accel_in_l, tgui_accel_out, tgui_accel_out_w, tgui_accel_out_l, tgui); + io_removehandler(0x213a, 0x0002, tgui_accel_in, tgui_accel_in_w, tgui_accel_in_l, tgui_accel_out, tgui_accel_out_w, tgui_accel_out_l, tgui); + io_removehandler(0x213c, 0x0002, tgui_accel_in, tgui_accel_in_w, tgui_accel_in_l, tgui_accel_out, tgui_accel_out_w, tgui_accel_out_l, tgui); + io_removehandler(0x213e, 0x0002, tgui_accel_in, tgui_accel_in_w, tgui_accel_in_l, tgui_accel_out, tgui_accel_out_w, tgui_accel_out_l, tgui); + io_removehandler(0x2140, 0x0002, tgui_accel_in, tgui_accel_in_w, tgui_accel_in_l, tgui_accel_out, tgui_accel_out_w, tgui_accel_out_l, tgui); + io_removehandler(0x2142, 0x0002, tgui_accel_in, tgui_accel_in_w, tgui_accel_in_l, tgui_accel_out, tgui_accel_out_w, tgui_accel_out_l, tgui); + io_removehandler(0x2144, 0x0004, tgui_accel_in, tgui_accel_in_w, tgui_accel_in_l, tgui_accel_out, tgui_accel_out_w, tgui_accel_out_l, tgui); + io_removehandler(0x2148, 0x0004, tgui_accel_in, tgui_accel_in_w, tgui_accel_in_l, tgui_accel_out, tgui_accel_out_w, tgui_accel_out_l, tgui); + io_removehandler(0x2168, 0x0004, tgui_accel_in, tgui_accel_in_w, tgui_accel_in_l, tgui_accel_out, tgui_accel_out_w, tgui_accel_out_l, tgui); + io_removehandler(0x2178, 0x0004, tgui_accel_in, tgui_accel_in_w, tgui_accel_in_l, tgui_accel_out, tgui_accel_out_w, tgui_accel_out_l, tgui); + io_removehandler(0x217c, 0x0004, tgui_accel_in, tgui_accel_in_w, tgui_accel_in_l, tgui_accel_out, tgui_accel_out_w, tgui_accel_out_l, tgui); + io_removehandler(0x2180, 0x0080, tgui_accel_in, tgui_accel_in_w, tgui_accel_in_l, tgui_accel_out, tgui_accel_out_w, tgui_accel_out_l, tgui); + } } static void tgui_set_io(tgui_t *tgui) { - tgui_remove_io(tgui); - - io_sethandler(0x03c0, 0x0020, tgui_in, NULL, NULL, tgui_out, NULL, NULL, tgui); - if (tgui->type >= TGUI_9440) { - io_sethandler(0x43c6, 0x0004, tgui_in, NULL, NULL, tgui_out, NULL, NULL, tgui); - io_sethandler(0x83c6, 0x0003, tgui_in, NULL, NULL, tgui_out, NULL, NULL, tgui); - io_sethandler(0x2120, 0x0001, tgui_accel_in, tgui_accel_in_w, tgui_accel_in_l, tgui_accel_out, tgui_accel_out_w, tgui_accel_out_l, tgui); - io_sethandler(0x2122, 0x0002, tgui_accel_in, tgui_accel_in_w, tgui_accel_in_l, tgui_accel_out, tgui_accel_out_w, tgui_accel_out_l, tgui); - io_sethandler(0x2124, 0x0001, tgui_accel_in, tgui_accel_in_w, tgui_accel_in_l, tgui_accel_out, tgui_accel_out_w, tgui_accel_out_l, tgui); - io_sethandler(0x2127, 0x0001, tgui_accel_in, tgui_accel_in_w, tgui_accel_in_l, tgui_accel_out, tgui_accel_out_w, tgui_accel_out_l, tgui); - io_sethandler(0x2128, 0x0004, tgui_accel_in, tgui_accel_in_w, tgui_accel_in_l, tgui_accel_out, tgui_accel_out_w, tgui_accel_out_l, tgui); - io_sethandler(0x212c, 0x0004, tgui_accel_in, tgui_accel_in_w, tgui_accel_in_l, tgui_accel_out, tgui_accel_out_w, tgui_accel_out_l, tgui); - io_sethandler(0x2130, 0x0004, tgui_accel_in, tgui_accel_in_w, tgui_accel_in_l, tgui_accel_out, tgui_accel_out_w, tgui_accel_out_l, tgui); - io_sethandler(0x2134, 0x0002, tgui_accel_in, tgui_accel_in_w, tgui_accel_in_l, tgui_accel_out, tgui_accel_out_w, tgui_accel_out_l, tgui); - io_sethandler(0x2138, 0x0002, tgui_accel_in, tgui_accel_in_w, tgui_accel_in_l, tgui_accel_out, tgui_accel_out_w, tgui_accel_out_l, tgui); - io_sethandler(0x213a, 0x0002, tgui_accel_in, tgui_accel_in_w, tgui_accel_in_l, tgui_accel_out, tgui_accel_out_w, tgui_accel_out_l, tgui); - io_sethandler(0x213c, 0x0002, tgui_accel_in, tgui_accel_in_w, tgui_accel_in_l, tgui_accel_out, tgui_accel_out_w, tgui_accel_out_l, tgui); - io_sethandler(0x213e, 0x0002, tgui_accel_in, tgui_accel_in_w, tgui_accel_in_l, tgui_accel_out, tgui_accel_out_w, tgui_accel_out_l, tgui); - io_sethandler(0x2140, 0x0002, tgui_accel_in, tgui_accel_in_w, tgui_accel_in_l, tgui_accel_out, tgui_accel_out_w, tgui_accel_out_l, tgui); - io_sethandler(0x2142, 0x0002, tgui_accel_in, tgui_accel_in_w, tgui_accel_in_l, tgui_accel_out, tgui_accel_out_w, tgui_accel_out_l, tgui); - io_sethandler(0x2144, 0x0004, tgui_accel_in, tgui_accel_in_w, tgui_accel_in_l, tgui_accel_out, tgui_accel_out_w, tgui_accel_out_l, tgui); - io_sethandler(0x2148, 0x0004, tgui_accel_in, tgui_accel_in_w, tgui_accel_in_l, tgui_accel_out, tgui_accel_out_w, tgui_accel_out_l, tgui); - io_sethandler(0x2168, 0x0004, tgui_accel_in, tgui_accel_in_w, tgui_accel_in_l, tgui_accel_out, tgui_accel_out_w, tgui_accel_out_l, tgui); - io_sethandler(0x2178, 0x0004, tgui_accel_in, tgui_accel_in_w, tgui_accel_in_l, tgui_accel_out, tgui_accel_out_w, tgui_accel_out_l, tgui); - io_sethandler(0x217c, 0x0004, tgui_accel_in, tgui_accel_in_w, tgui_accel_in_l, tgui_accel_out, tgui_accel_out_w, tgui_accel_out_l, tgui); - io_sethandler(0x2180, 0x0080, tgui_accel_in, tgui_accel_in_w, tgui_accel_in_l, tgui_accel_out, tgui_accel_out_w, tgui_accel_out_l, tgui); - } + tgui_remove_io(tgui); + + io_sethandler(0x03c0, 0x0020, tgui_in, NULL, NULL, tgui_out, NULL, NULL, tgui); + if (tgui->type >= TGUI_9440) { + io_sethandler(0x43c6, 0x0004, tgui_in, NULL, NULL, tgui_out, NULL, NULL, tgui); + io_sethandler(0x83c6, 0x0003, tgui_in, NULL, NULL, tgui_out, NULL, NULL, tgui); + io_sethandler(0x2120, 0x0001, tgui_accel_in, tgui_accel_in_w, tgui_accel_in_l, tgui_accel_out, tgui_accel_out_w, tgui_accel_out_l, tgui); + io_sethandler(0x2122, 0x0002, tgui_accel_in, tgui_accel_in_w, tgui_accel_in_l, tgui_accel_out, tgui_accel_out_w, tgui_accel_out_l, tgui); + io_sethandler(0x2124, 0x0001, tgui_accel_in, tgui_accel_in_w, tgui_accel_in_l, tgui_accel_out, tgui_accel_out_w, tgui_accel_out_l, tgui); + io_sethandler(0x2127, 0x0001, tgui_accel_in, tgui_accel_in_w, tgui_accel_in_l, tgui_accel_out, tgui_accel_out_w, tgui_accel_out_l, tgui); + io_sethandler(0x2128, 0x0004, tgui_accel_in, tgui_accel_in_w, tgui_accel_in_l, tgui_accel_out, tgui_accel_out_w, tgui_accel_out_l, tgui); + io_sethandler(0x212c, 0x0004, tgui_accel_in, tgui_accel_in_w, tgui_accel_in_l, tgui_accel_out, tgui_accel_out_w, tgui_accel_out_l, tgui); + io_sethandler(0x2130, 0x0004, tgui_accel_in, tgui_accel_in_w, tgui_accel_in_l, tgui_accel_out, tgui_accel_out_w, tgui_accel_out_l, tgui); + io_sethandler(0x2134, 0x0002, tgui_accel_in, tgui_accel_in_w, tgui_accel_in_l, tgui_accel_out, tgui_accel_out_w, tgui_accel_out_l, tgui); + io_sethandler(0x2138, 0x0002, tgui_accel_in, tgui_accel_in_w, tgui_accel_in_l, tgui_accel_out, tgui_accel_out_w, tgui_accel_out_l, tgui); + io_sethandler(0x213a, 0x0002, tgui_accel_in, tgui_accel_in_w, tgui_accel_in_l, tgui_accel_out, tgui_accel_out_w, tgui_accel_out_l, tgui); + io_sethandler(0x213c, 0x0002, tgui_accel_in, tgui_accel_in_w, tgui_accel_in_l, tgui_accel_out, tgui_accel_out_w, tgui_accel_out_l, tgui); + io_sethandler(0x213e, 0x0002, tgui_accel_in, tgui_accel_in_w, tgui_accel_in_l, tgui_accel_out, tgui_accel_out_w, tgui_accel_out_l, tgui); + io_sethandler(0x2140, 0x0002, tgui_accel_in, tgui_accel_in_w, tgui_accel_in_l, tgui_accel_out, tgui_accel_out_w, tgui_accel_out_l, tgui); + io_sethandler(0x2142, 0x0002, tgui_accel_in, tgui_accel_in_w, tgui_accel_in_l, tgui_accel_out, tgui_accel_out_w, tgui_accel_out_l, tgui); + io_sethandler(0x2144, 0x0004, tgui_accel_in, tgui_accel_in_w, tgui_accel_in_l, tgui_accel_out, tgui_accel_out_w, tgui_accel_out_l, tgui); + io_sethandler(0x2148, 0x0004, tgui_accel_in, tgui_accel_in_w, tgui_accel_in_l, tgui_accel_out, tgui_accel_out_w, tgui_accel_out_l, tgui); + io_sethandler(0x2168, 0x0004, tgui_accel_in, tgui_accel_in_w, tgui_accel_in_l, tgui_accel_out, tgui_accel_out_w, tgui_accel_out_l, tgui); + io_sethandler(0x2178, 0x0004, tgui_accel_in, tgui_accel_in_w, tgui_accel_in_l, tgui_accel_out, tgui_accel_out_w, tgui_accel_out_l, tgui); + io_sethandler(0x217c, 0x0004, tgui_accel_in, tgui_accel_in_w, tgui_accel_in_l, tgui_accel_out, tgui_accel_out_w, tgui_accel_out_l, tgui); + io_sethandler(0x2180, 0x0080, tgui_accel_in, tgui_accel_in_w, tgui_accel_in_l, tgui_accel_out, tgui_accel_out_w, tgui_accel_out_l, tgui); + } } static void -tgui_out(uint16_t addr, uint8_t val, void *p) +tgui_out(uint16_t addr, uint8_t val, void *priv) { - tgui_t *tgui = (tgui_t *)p; - svga_t *svga = &tgui->svga; - uint8_t old; + tgui_t *tgui = (tgui_t *) priv; + svga_t *svga = &tgui->svga; + uint8_t old; - if (((addr&0xFFF0) == 0x3D0 || (addr&0xFFF0) == 0x3B0) && !(svga->miscout & 1)) addr ^= 0x60; + if (((addr & 0xFFF0) == 0x3D0 || (addr & 0xFFF0) == 0x3B0) && !(svga->miscout & 1)) + addr ^= 0x60; - switch (addr) - { - case 0x3C5: - switch (svga->seqaddr) - { - case 0xB: - tgui->oldmode = 1; + switch (addr) { + case 0x3C5: + switch (svga->seqaddr) { + case 0xB: + tgui->oldmode = 1; + break; + case 0xC: + if (svga->seqregs[0x0e] & 0x80) + svga->seqregs[0x0c] = val; + break; + case 0xd: + if (tgui->oldmode) + tgui->oldctrl2 = val; + else + tgui->newctrl2 = val; + break; + case 0xE: + if (tgui->oldmode) { + tgui->oldctrl1 = val; + tgui_update_irqs(tgui); + svga->write_bank = (tgui->oldctrl1) * 65536; + } else { + svga->seqregs[0xe] = val ^ 2; + svga->write_bank = (svga->seqregs[0xe]) * 65536; + } + if (!(svga->gdcreg[0xf] & 1)) + svga->read_bank = svga->write_bank; + return; + + default: + break; + } + break; + + case 0x3C6: + if (tgui->type == TGUI_9400CXI) { + tkd8001_ramdac_out(addr, val, svga->ramdac, svga); + return; + } + if (tgui->ramdac_state == 4) { + tgui->ramdac_state = 0; + tgui->ramdac_ctrl = val; + switch ((tgui->ramdac_ctrl >> 4) & 0x0f) { + case 1: + svga->bpp = 15; break; - case 0xC: - if (svga->seqregs[0x0e] & 0x80) - svga->seqregs[0x0c] = val; + case 3: + svga->bpp = 16; break; - case 0xd: + case 0x0d: + svga->bpp = (tgui->type >= TGUI_9660) ? 32 : 24; + break; + default: + svga->bpp = 8; + break; + } + svga_recalctimings(svga); + return; + } + break; + + case 0x3C7: + case 0x3C8: + case 0x3C9: + if (tgui->type == TGUI_9400CXI) { + tkd8001_ramdac_out(addr, val, svga->ramdac, svga); + return; + } + tgui->ramdac_state = 0; + break; + + case 0x3CF: + if (svga->gdcaddr == 0x23) { + svga->dpms = !!(val & 0x03); + svga_recalctimings(svga); + } + if (tgui->type == TGUI_9400CXI && svga->gdcaddr >= 16 && svga->gdcaddr < 32) { + old = tgui->ext_gdc_regs[svga->gdcaddr & 15]; + tgui->ext_gdc_regs[svga->gdcaddr & 15] = val; + if (svga->gdcaddr == 16) + tgui_recalcmapping(tgui); + return; + } + switch (svga->gdcaddr) { + case 0x6: + if (svga->gdcreg[6] != val) { + svga->gdcreg[6] = val; + tgui_recalcmapping(tgui); + } + return; + + case 0x0e: + svga->gdcreg[0xe] = val ^ 2; + if ((svga->gdcreg[0xf] & 1) == 1) + svga->read_bank = (svga->gdcreg[0xe]) * 65536; + break; + case 0x0f: + if (val & 1) + svga->read_bank = (svga->gdcreg[0xe]) * 65536; + else { if (tgui->oldmode) - tgui->oldctrl2 = val; - else - tgui->newctrl2 = val; - break; - case 0xE: - if (tgui->oldmode) { - tgui->oldctrl1 = val; - tgui_update_irqs(tgui); - svga->write_bank = (tgui->oldctrl1) * 65536; - } else { - svga->seqregs[0xe] = val ^ 2; - svga->write_bank = (svga->seqregs[0xe]) * 65536; - } - if (!(svga->gdcreg[0xf] & 1)) - svga->read_bank = svga->write_bank; - return; - } - break; - - case 0x3C6: - if (tgui->type == TGUI_9400CXI) - { - tkd8001_ramdac_out(addr, val, svga->ramdac, svga); - return; - } - if (tgui->ramdac_state == 4) - { - tgui->ramdac_state = 0; - tgui->ramdac_ctrl = val; - switch ((tgui->ramdac_ctrl >> 4) & 0x0f) - { - case 1: - svga->bpp = 15; - break; - case 3: - svga->bpp = 16; - break; - case 0x0d: - svga->bpp = (tgui->type >= TGUI_9660) ? 32 : 24; - break; - default: - svga->bpp = 8; - break; - } - svga_recalctimings(svga); - return; - } - break; - - case 0x3C7: case 0x3C8: case 0x3C9: - if (tgui->type == TGUI_9400CXI) - { - tkd8001_ramdac_out(addr, val, svga->ramdac, svga); - return; - } - tgui->ramdac_state = 0; - break; + svga->read_bank = (tgui->oldctrl1) * 65536; + else + svga->read_bank = (svga->seqregs[0xe]) * 65536; + } - case 0x3CF: - if (svga->gdcaddr == 0x23) - { - svga->dpms = !!(val & 0x03); + if (tgui->oldmode) + svga->write_bank = (tgui->oldctrl1) * 65536; + else + svga->write_bank = (svga->seqregs[0xe]) * 65536; + break; + + case 0x5a: + case 0x5b: + case 0x5c: + case 0x5d: + case 0x5e: + case 0x5f: + svga->gdcreg[svga->gdcaddr] = val; + break; + + default: + break; + } + break; + case 0x3D4: + svga->crtcreg = val; + 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; + switch (svga->crtcreg) { + case 0x1e: + svga->vram_display_mask = (val & 0x80) ? tgui->vram_mask : 0x3ffff; + break; + + case 0x21: + if (!tgui->pci) { + tgui->linear_base = ((val & 0xc0) << 18) | ((val & 0x0f) << 20); + tgui->linear_size = (val & 0x10) ? 0x200000 : 0x100000; + svga->decode_mask = (val & 0x10) ? 0x1fffff : 0xfffff; + } + tgui_recalcmapping(tgui); + break; + + case 0x34: + case 0x35: + if (tgui->type >= TGUI_9440) { + tgui->ge_base = ((svga->crtc[0x35] << 0x18) | (svga->crtc[0x34] << 0x10)); + tgui_recalcmapping(tgui); + } + break; + + case 0x36: + case 0x39: + tgui_recalcmapping(tgui); + break; + + case 0x37: + if (tgui->type >= TGUI_9440) + i2c_gpio_set(tgui->i2c, (val & 0x02) || !(val & 0x04), (val & 0x01) || !(val & 0x08)); + break; + + case 0x40: + case 0x41: + case 0x42: + case 0x43: + case 0x44: + case 0x45: + case 0x46: + case 0x47: + if (tgui->type >= TGUI_9440) { + svga->hwcursor.x = (svga->crtc[0x40] | (svga->crtc[0x41] << 8)) & 0x7ff; + svga->hwcursor.y = (svga->crtc[0x42] | (svga->crtc[0x43] << 8)) & 0x7ff; + + if ((tgui->accel.ger22 & 0xff) == 8) { + if (svga->bpp != 24) + svga->hwcursor.x <<= 1; + } + + svga->hwcursor.xoff = svga->crtc[0x46] & 0x3f; + svga->hwcursor.yoff = svga->crtc[0x47] & 0x3f; + svga->hwcursor.addr = (svga->crtc[0x44] << 10) | ((svga->crtc[0x45] & 0x0f) << 18) | (svga->hwcursor.yoff * 8); + } + break; + + case 0x50: + if (tgui->type >= TGUI_9440) { + svga->hwcursor.ena = !!(val & 0x80); + svga->hwcursor.cur_xsize = svga->hwcursor.cur_ysize = ((val & 1) ? 64 : 32); + } + break; + + default: + break; + } + + 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 = svga->monitor->mon_changeframecount; svga_recalctimings(svga); + } } - if (tgui->type == TGUI_9400CXI && svga->gdcaddr >= 16 && svga->gdcaddr < 32) - { - old = tgui->ext_gdc_regs[svga->gdcaddr & 15]; - tgui->ext_gdc_regs[svga->gdcaddr & 15] = val; - if (svga->gdcaddr == 16) - tgui_recalcmapping(tgui); - return; + } + return; + + case 0x3D8: + tgui->tgui_3d8 = val; + if (svga->gdcreg[0xf] & 4) { + svga->write_bank = (val & 0x3f) * 65536; + if (!(svga->gdcreg[0xf] & 1)) { + svga->read_bank = (val & 0x3f) * 65536; } - switch (svga->gdcaddr) - { - case 0x6: - if (svga->gdcreg[6] != val) - { - svga->gdcreg[6] = val; - tgui_recalcmapping(tgui); - } - return; - - case 0x0e: - svga->gdcreg[0xe] = val ^ 2; - if ((svga->gdcreg[0xf] & 1) == 1) - svga->read_bank = (svga->gdcreg[0xe]) * 65536; - break; - case 0x0f: - if (val & 1) - svga->read_bank = (svga->gdcreg[0xe]) * 65536; - else { - if (tgui->oldmode) - svga->read_bank = (tgui->oldctrl1) * 65536; - else - svga->read_bank = (svga->seqregs[0xe]) * 65536; - } - - if (tgui->oldmode) - svga->write_bank = (tgui->oldctrl1) * 65536; - else - svga->write_bank = (svga->seqregs[0xe]) * 65536; - break; - - case 0x5a: - case 0x5b: - case 0x5c: - case 0x5d: - case 0x5e: - case 0x5f: - svga->gdcreg[svga->gdcaddr] = val; - break; - } - break; - case 0x3D4: - svga->crtcreg = val; - 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); - } - } - } - switch (svga->crtcreg) { - case 0x1e: - svga->vram_display_mask = (val & 0x80) ? tgui->vram_mask : 0x3ffff; - break; + } + return; + case 0x3D9: + tgui->tgui_3d9 = val; + if ((svga->gdcreg[0xf] & 5) == 5) + svga->read_bank = (val & 0x3f) * 65536; + return; - case 0x21: - if (old != val) { - if (!tgui->pci) { - tgui->linear_base = ((val & 0xf) | ((val >> 2) & 0x30)) << 20; - tgui->linear_size = (val & 0x10) ? 0x200000 : 0x100000; - svga->decode_mask = (val & 0x10) ? 0x1fffff : 0xfffff; - } - tgui_recalcmapping(tgui); - } - break; + case 0x43c8: + tgui->clock_n = val & 0x7f; + tgui->clock_m = (tgui->clock_m & ~1) | (val >> 7); + break; + case 0x43c9: + tgui->clock_m = (tgui->clock_m & ~0x1e) | ((val << 1) & 0x1e); + tgui->clock_k = (val & 0x10) >> 4; + break; - case 0x34: - case 0x35: - if (tgui->type >= TGUI_9440) { - tgui->ge_base = ((svga->crtc[0x35] << 0x18) | (svga->crtc[0x34] << 0x10)); - tgui_recalcmapping(tgui); - } - break; - - case 0x36: - case 0x39: - tgui_recalcmapping(tgui); - break; - - case 0x37: - i2c_gpio_set(tgui->i2c, (val & 0x02) || !(val & 0x04), (val & 0x01) || !(val & 0x08)); - break; - - case 0x40: case 0x41: case 0x42: case 0x43: - case 0x44: case 0x45: case 0x46: case 0x47: - if (tgui->type >= TGUI_9440) { - svga->hwcursor.x = (svga->crtc[0x40] | (svga->crtc[0x41] << 8)) & 0x7ff; - svga->hwcursor.y = (svga->crtc[0x42] | (svga->crtc[0x43] << 8)) & 0x7ff; - if (tgui->type >= TGUI_9660 && (tgui->accel.ger22 & 0xff) == 8) { - svga->hwcursor.x <<= 1; - } - svga->hwcursor.xoff = svga->crtc[0x46] & 0x3f; - svga->hwcursor.yoff = svga->crtc[0x47] & 0x3f; - svga->hwcursor.addr = (svga->crtc[0x44] << 10) | ((svga->crtc[0x45] & 0x0f) << 18) | (svga->hwcursor.yoff * 8); - } - break; - - case 0x50: - if (tgui->type >= TGUI_9440) { - svga->hwcursor.ena = !!(val & 0x80); - svga->hwcursor.xsize = svga->hwcursor.ysize = ((val & 1) ? 64 : 32); - } - break; - } - return; - - case 0x3D8: - tgui->tgui_3d8 = val; - if (svga->gdcreg[0xf] & 4) { - svga->write_bank = (val & 0x3f) * 65536; - if (!(svga->gdcreg[0xf] & 1)) { - svga->read_bank = (val & 0x3f) * 65536; - } - } - return; - case 0x3D9: - tgui->tgui_3d9 = val; - if ((svga->gdcreg[0xf] & 5) == 5) - svga->read_bank = (val & 0x3f) * 65536; - return; - - case 0x43c8: - tgui->clock_n = val & 0x7f; - tgui->clock_m = (tgui->clock_m & ~1) | (val >> 7); - break; - case 0x43c9: - tgui->clock_m = (tgui->clock_m & ~0x1e) | ((val << 1) & 0x1e); - tgui->clock_k = (val & 0x10) >> 4; - break; - } - svga_out(addr, val, svga); + default: + break; + } + svga_out(addr, val, svga); } static uint8_t -tgui_in(uint16_t addr, void *p) +tgui_in(uint16_t addr, void *priv) { - tgui_t *tgui = (tgui_t *)p; - svga_t *svga = &tgui->svga; - uint8_t temp; + tgui_t *tgui = (tgui_t *) priv; + svga_t *svga = &tgui->svga; + uint8_t temp; - if (((addr&0xFFF0) == 0x3D0 || (addr&0xFFF0) == 0x3B0) && !(svga->miscout & 1)) addr ^= 0x60; - - switch (addr) - { - case 0x3C5: - if (svga->seqaddr == 9) { - if (tgui->type == TGUI_9680) - return 0x01; /*TGUI9680XGi*/ - } - if (svga->seqaddr == 0x0b) - { - tgui->oldmode = 0; - switch (tgui->type) - { - case TGUI_9400CXI: - return 0x93; /*TGUI9400CXi*/ - case TGUI_9440: - return 0xe3; /*TGUI9440AGi*/ - case TGUI_9660: - case TGUI_9680: - return 0xd3; /*TGUI9660XGi*/ - } - } - if (svga->seqaddr == 0x0d) - { - if (tgui->oldmode) - return tgui->oldctrl2; - return tgui->newctrl2; - } - if (svga->seqaddr == 0x0c) - { - if (svga->seqregs[0x0e] & 0x80) - return svga->seqregs[0x0c]; - } - if (svga->seqaddr == 0x0e) - { - if (tgui->oldmode) - return tgui->oldctrl1 | 0x88; - return svga->seqregs[0x0e]; - } - break; + if (((addr & 0xFFF0) == 0x3D0 || (addr & 0xFFF0) == 0x3B0) && !(svga->miscout & 1)) + addr ^= 0x60; - case 0x3C6: - if (tgui->type == TGUI_9400CXI) - return tkd8001_ramdac_in(addr, svga->ramdac, svga); - if (tgui->ramdac_state == 4) - return tgui->ramdac_ctrl; - tgui->ramdac_state++; - break; + switch (addr) { + case 0x3C5: + if (svga->seqaddr == 9) { + if (tgui->type == TGUI_9680) + return 0x01; /*TGUI9680XGi*/ + } + if (svga->seqaddr == 0x0b) { + tgui->oldmode = 0; + switch (tgui->type) { + case TGUI_9400CXI: + return 0x93; /*TGUI9400CXi*/ + case TGUI_9440: + return 0xe3; /*TGUI9440AGi*/ + case TGUI_9660: + case TGUI_9680: + return 0xd3; /*TGUI9660XGi*/ - case 0x3C7: case 0x3C8: case 0x3C9: - if (tgui->type == TGUI_9400CXI) - return tkd8001_ramdac_in(addr, svga->ramdac, svga); - tgui->ramdac_state = 0; - break; - - case 0x3CF: - if (tgui->type == TGUI_9400CXI && svga->gdcaddr >= 16 && svga->gdcaddr < 32) - return tgui->ext_gdc_regs[svga->gdcaddr & 15]; - if (svga->gdcaddr >= 0x5a && svga->gdcaddr <= 0x5f) - return svga->gdcreg[svga->gdcaddr]; - break; - case 0x3D4: - return svga->crtcreg; - case 0x3D5: - temp = svga->crtc[svga->crtcreg]; - if (svga->crtcreg == 0x37) { - if (!(temp & 0x04)) { - temp &= ~0x02; - if (i2c_gpio_get_scl(tgui->i2c)) - temp |= 0x02; - } - if (!(temp & 0x08)) { - temp &= ~0x01; - if (i2c_gpio_get_sda(tgui->i2c)) - temp |= 0x01; - } + default: + break; } - return temp; - case 0x3d8: - return tgui->tgui_3d8; - case 0x3d9: - return tgui->tgui_3d9; - } - return svga_in(addr, svga); + } + if (svga->seqaddr == 0x0d) { + if (tgui->oldmode) + return tgui->oldctrl2; + return tgui->newctrl2; + } + if (svga->seqaddr == 0x0c) { + if (svga->seqregs[0x0e] & 0x80) + return svga->seqregs[0x0c]; + } + if (svga->seqaddr == 0x0e) { + if (tgui->oldmode) + return tgui->oldctrl1 | 0x88; + return svga->seqregs[0x0e]; + } + break; + + case 0x3C6: + if (tgui->type == TGUI_9400CXI) + return tkd8001_ramdac_in(addr, svga->ramdac, svga); + if (tgui->ramdac_state == 4) + return tgui->ramdac_ctrl; + tgui->ramdac_state++; + break; + + case 0x3C7: + case 0x3C8: + case 0x3C9: + if (tgui->type == TGUI_9400CXI) + return tkd8001_ramdac_in(addr, svga->ramdac, svga); + tgui->ramdac_state = 0; + break; + + case 0x3CF: + if (tgui->type == TGUI_9400CXI && svga->gdcaddr >= 16 && svga->gdcaddr < 32) + return tgui->ext_gdc_regs[svga->gdcaddr & 15]; + if (svga->gdcaddr >= 0x5a && svga->gdcaddr <= 0x5f) + return svga->gdcreg[svga->gdcaddr]; + break; + case 0x3D4: + return svga->crtcreg; + case 0x3D5: + temp = svga->crtc[svga->crtcreg]; + if ((svga->crtcreg == 0x37) && (tgui->type >= TGUI_9440)) { + if (!(temp & 0x04)) { + temp &= ~0x02; + if (i2c_gpio_get_scl(tgui->i2c)) + temp |= 0x02; + } + if (!(temp & 0x08)) { + temp &= ~0x01; + if (i2c_gpio_get_sda(tgui->i2c)) + temp |= 0x01; + } + } + return temp; + case 0x3d8: + return tgui->tgui_3d8; + case 0x3d9: + return tgui->tgui_3d9; + + default: + break; + } + return svga_in(addr, svga); } -void tgui_recalctimings(svga_t *svga) +void +tgui_recalctimings(svga_t *svga) { - tgui_t *tgui = (tgui_t *)svga->p; + const tgui_t *tgui = (tgui_t *) svga->priv; + uint8_t ger22lower = (tgui->accel.ger22 & 0xff); + uint8_t ger22upper = (tgui->accel.ger22 >> 8); - if (!svga->rowoffset) - svga->rowoffset = 0x100; + if (!svga->rowoffset) + svga->rowoffset = 0x100; - if (svga->crtc[0x29] & 0x10) - svga->rowoffset |= 0x100; + if (svga->crtc[0x29] & 0x10) + svga->rowoffset |= 0x100; - if (tgui->type >= TGUI_9440 && svga->bpp >= 24) { - if ((tgui->accel.bpp == 0) && (tgui->accel.ger22 & 0xff) != 14 && (svga->bpp == 24)) - svga->hdisp = (svga->crtc[1] + 1) * 8; - if (tgui->accel.bpp == 3 && (tgui->accel.ger22 & 0xff) == 14 && (svga->bpp == 32) && (tgui->type == TGUI_9440)) - svga->rowoffset <<= 1; - } + if ((tgui->type >= TGUI_9440) && (svga->bpp >= 24)) + svga->hdisp = (svga->crtc[1] + 1) * 8; - + if ((svga->crtc[0x1e] & 0xA0) == 0xA0) + svga->ma_latch |= 0x10000; + if ((svga->crtc[0x27] & 0x01) == 0x01) + svga->ma_latch |= 0x20000; + if ((svga->crtc[0x27] & 0x02) == 0x02) + svga->ma_latch |= 0x40000; + if ((svga->crtc[0x27] & 0x04) == 0x04) + svga->ma_latch |= 0x80000; - if ((svga->crtc[0x1e] & 0xA0) == 0xA0) - svga->ma_latch |= 0x10000; - if ((svga->crtc[0x27] & 0x01) == 0x01) - svga->ma_latch |= 0x20000; - if ((svga->crtc[0x27] & 0x02) == 0x02) - svga->ma_latch |= 0x40000; - if ((svga->crtc[0x27] & 0x04) == 0x04) - svga->ma_latch |= 0x80000; - - if (svga->crtc[0x27] & 0x08) - svga->split |= 0x400; - if (svga->crtc[0x27] & 0x10) - svga->dispend |= 0x400; - if (svga->crtc[0x27] & 0x20) - svga->vsyncstart |= 0x400; - if (svga->crtc[0x27] & 0x40) - svga->vblankstart |= 0x400; - if (svga->crtc[0x27] & 0x80) - svga->vtotal |= 0x400; + if (svga->crtc[0x27] & 0x08) + svga->split |= 0x400; + if (svga->crtc[0x27] & 0x10) + svga->dispend |= 0x400; + if (svga->crtc[0x27] & 0x20) + svga->vsyncstart |= 0x400; + if (svga->crtc[0x27] & 0x40) + svga->vblankstart |= 0x400; + if (svga->crtc[0x27] & 0x80) + svga->vtotal |= 0x400; - if (tgui->oldctrl2 & 0x10) { - svga->rowoffset <<= 1; - svga->lowres = 0; - } - - if ((tgui->oldctrl2 & 0x10) || (svga->crtc[0x2a] & 0x40)) - svga->ma_latch <<= 1; + if (tgui->oldctrl2 & 0x10) { + svga->rowoffset <<= 1; + svga->lowres = 0; + } - svga->lowres = !(svga->crtc[0x2a] & 0x40); + if ((tgui->oldctrl2 & 0x10) || (svga->crtc[0x2a] & 0x40)) + svga->ma_latch <<= 1; - svga->interlace = !!(svga->crtc[0x1e] & 4); - if (svga->interlace && tgui->type < TGUI_9440) - svga->rowoffset >>= 1; - - if (tgui->type >= TGUI_9440) - { - if (svga->miscout & 8) - svga->clock = (cpuclock * (double)(1ull << 32)) / (((tgui->clock_n + 8) * 14318180.0) / ((tgui->clock_m + 2) * (1 << tgui->clock_k))); - - if (svga->gdcreg[0xf] & 0x08) - svga->clock *= 2; - else if (svga->gdcreg[0xf] & 0x40) - svga->clock *= 3; + svga->lowres = !(svga->crtc[0x2a] & 0x40); + + svga->interlace = !!(svga->crtc[0x1e] & 4); + if (svga->interlace && (tgui->type < TGUI_9440)) + svga->rowoffset >>= 1; + + if (tgui->type >= TGUI_9440) { + if (svga->miscout & 8) + svga->clock = (cpuclock * (double) (1ULL << 32)) / (((tgui->clock_n + 8) * 14318180.0) / ((tgui->clock_m + 2) * (1 << tgui->clock_k))); + + if (svga->gdcreg[0xf] & 0x08) + svga->clock *= 2; + else if (svga->gdcreg[0xf] & 0x40) + svga->clock *= 3; + } else { + switch (((svga->miscout >> 2) & 3) | ((tgui->newctrl2 << 2) & 4) | ((tgui->newctrl2 >> 3) & 8)) { + case 0x02: + svga->clock = (cpuclock * (double) (1ULL << 32)) / 44900000.0; + break; + case 0x03: + svga->clock = (cpuclock * (double) (1ULL << 32)) / 36000000.0; + break; + case 0x04: + svga->clock = (cpuclock * (double) (1ULL << 32)) / 57272000.0; + break; + case 0x05: + svga->clock = (cpuclock * (double) (1ULL << 32)) / 65000000.0; + break; + case 0x06: + svga->clock = (cpuclock * (double) (1ULL << 32)) / 50350000.0; + break; + case 0x07: + svga->clock = (cpuclock * (double) (1ULL << 32)) / 40000000.0; + break; + case 0x08: + svga->clock = (cpuclock * (double) (1ULL << 32)) / 88000000.0; + break; + case 0x09: + svga->clock = (cpuclock * (double) (1ULL << 32)) / 98000000.0; + break; + case 0x0a: + svga->clock = (cpuclock * (double) (1ULL << 32)) / 118800000.0; + break; + case 0x0b: + svga->clock = (cpuclock * (double) (1ULL << 32)) / 108000000.0; + break; + case 0x0c: + svga->clock = (cpuclock * (double) (1ULL << 32)) / 72000000.0; + break; + case 0x0d: + svga->clock = (cpuclock * (double) (1ULL << 32)) / 77000000.0; + break; + case 0x0e: + svga->clock = (cpuclock * (double) (1ULL << 32)) / 80000000.0; + break; + case 0x0f: + svga->clock = (cpuclock * (double) (1ULL << 32)) / 75000000.0; + break; + + default: + break; } - else - { - switch (((svga->miscout >> 2) & 3) | ((tgui->newctrl2 << 2) & 4) | ((tgui->newctrl2 >> 3) & 8)) - { - case 0x02: svga->clock = (cpuclock * (double)(1ull << 32)) / 44900000.0; break; - case 0x03: svga->clock = (cpuclock * (double)(1ull << 32)) / 36000000.0; break; - case 0x04: svga->clock = (cpuclock * (double)(1ull << 32)) / 57272000.0; break; - case 0x05: svga->clock = (cpuclock * (double)(1ull << 32)) / 65000000.0; break; - case 0x06: svga->clock = (cpuclock * (double)(1ull << 32)) / 50350000.0; break; - case 0x07: svga->clock = (cpuclock * (double)(1ull << 32)) / 40000000.0; break; - case 0x08: svga->clock = (cpuclock * (double)(1ull << 32)) / 88000000.0; break; - case 0x09: svga->clock = (cpuclock * (double)(1ull << 32)) / 98000000.0; break; - case 0x0a: svga->clock = (cpuclock * (double)(1ull << 32)) /118800000.0; break; - case 0x0b: svga->clock = (cpuclock * (double)(1ull << 32)) /108000000.0; break; - case 0x0c: svga->clock = (cpuclock * (double)(1ull << 32)) / 72000000.0; break; - case 0x0d: svga->clock = (cpuclock * (double)(1ull << 32)) / 77000000.0; break; - case 0x0e: svga->clock = (cpuclock * (double)(1ull << 32)) / 80000000.0; break; - case 0x0f: svga->clock = (cpuclock * (double)(1ull << 32)) / 75000000.0; break; - } - if (svga->gdcreg[0xf] & 0x08) - { + if (svga->gdcreg[0xf] & 0x08) { + svga->htotal <<= 1; + svga->hdisp <<= 1; + svga->hdisp_time <<= 1; + } + } + + if ((tgui->oldctrl2 & 0x10) || (svga->crtc[0x2a] & 0x40)) { + switch (svga->bpp) { + case 8: + svga->render = svga_render_8bpp_highres; + if (tgui->type >= TGUI_9660) { + if (svga->dispend == ((1024 >> 1) - 2)) + svga->dispend += 2; + if (svga->dispend == (1024 >> 1)) + svga->hdisp <<= 1; + else if ((svga->hdisp == (1600 >> 1)) && (svga->dispend == (1200 >> 1)) && svga->interlace) + svga->hdisp <<= 1; + else if (svga->hdisp == (1024 >> 1)) { + if (svga->interlace && (svga->dispend == (768 >> 1))) + svga->hdisp <<= 1; + else if (!svga->interlace && (svga->dispend == 768)) + svga->hdisp <<= 1; + } + + if (ger22upper & 0x80) { svga->htotal <<= 1; svga->hdisp <<= 1; svga->hdisp_time <<= 1; + } + switch (svga->hdisp) { + case 640: + if (!ger22lower) + svga->rowoffset = 80; + break; + + default: + break; + } } - } - - if ((tgui->oldctrl2 & 0x10) || (svga->crtc[0x2a] & 0x40)) - { - switch (svga->bpp) - { - case 8: - svga->render = svga_render_8bpp_highres; - if (tgui->type >= TGUI_9660) { - if (svga->dispend == 512) - svga->hdisp = 1280; - else if (svga->dispend == 600 && svga->hdisp == 800 && svga->vtotal == 651) - svga->hdisp = 1600; - } - break; - case 15: - svga->render = svga_render_15bpp_highres; - if (tgui->type < TGUI_9440) - svga->hdisp >>= 1; - break; - case 16: - svga->render = svga_render_16bpp_highres; - if (tgui->type < TGUI_9440) - svga->hdisp >>= 1; - break; - case 24: - svga->render = svga_render_24bpp_highres; - if (tgui->type < TGUI_9440) - svga->hdisp = (svga->hdisp << 1) / 3; - break; - case 32: - svga->render = svga_render_32bpp_highres; - if (tgui->type >= TGUI_9660) { - if (svga->hdisp == 1024) { - svga->rowoffset <<= 1; - } - } - break; + break; + case 15: + svga->render = svga_render_15bpp_highres; + if (tgui->type < TGUI_9440) + svga->hdisp >>= 1; + break; + case 16: + svga->render = svga_render_16bpp_highres; + if (tgui->type < TGUI_9440) + svga->hdisp >>= 1; + break; + case 24: + svga->render = svga_render_24bpp_highres; + if (tgui->type < TGUI_9440) + svga->hdisp = (svga->hdisp << 1) / 3; + break; + case 32: + svga->render = svga_render_32bpp_highres; + if (tgui->type >= TGUI_9660) { + if (!ger22upper) + svga->rowoffset <<= 1; } + break; + + default: + break; } + } } static void tgui_recalcmapping(tgui_t *tgui) { - svga_t *svga = &tgui->svga; + svga_t *svga = &tgui->svga; - if (tgui->type == TGUI_9400CXI) - { - if (tgui->ext_gdc_regs[0] & EXT_CTRL_LATCH_COPY) - { - mem_mapping_set_handler(&tgui->linear_mapping, - tgui_ext_linear_read, NULL, NULL, - tgui_ext_linear_write, tgui_ext_linear_writew, tgui_ext_linear_writel); - mem_mapping_set_handler(&svga->mapping, - tgui_ext_read, NULL, NULL, - tgui_ext_write, tgui_ext_writew, tgui_ext_writel); - } - else if (tgui->ext_gdc_regs[0] & EXT_CTRL_MONO_EXPANSION) - { - mem_mapping_set_handler(&tgui->linear_mapping, - svga_read_linear, svga_readw_linear, svga_readl_linear, - tgui_ext_linear_write, tgui_ext_linear_writew, tgui_ext_linear_writel); - mem_mapping_set_handler(&svga->mapping, - svga_read, svga_readw, svga_readl, - tgui_ext_write, tgui_ext_writew, tgui_ext_writel); - } - else - { - mem_mapping_set_handler(&tgui->linear_mapping, - svga_read_linear, svga_readw_linear, svga_readl_linear, - svga_write_linear, svga_writew_linear, svga_writel_linear); - mem_mapping_set_handler(&svga->mapping, - svga_read, svga_readw, svga_readl, - svga_write, svga_writew, svga_writel); - } + if (tgui->type == TGUI_9400CXI) { + if (tgui->ext_gdc_regs[0] & EXT_CTRL_LATCH_COPY) { + mem_mapping_set_handler(&tgui->linear_mapping, + tgui_ext_linear_read, NULL, NULL, + tgui_ext_linear_write, tgui_ext_linear_writew, tgui_ext_linear_writel); + mem_mapping_set_handler(&svga->mapping, + tgui_ext_read, NULL, NULL, + tgui_ext_write, tgui_ext_writew, tgui_ext_writel); + } else if (tgui->ext_gdc_regs[0] & EXT_CTRL_MONO_EXPANSION) { + mem_mapping_set_handler(&tgui->linear_mapping, + svga_read_linear, svga_readw_linear, svga_readl_linear, + tgui_ext_linear_write, tgui_ext_linear_writew, tgui_ext_linear_writel); + mem_mapping_set_handler(&svga->mapping, + svga_read, svga_readw, svga_readl, + tgui_ext_write, tgui_ext_writew, tgui_ext_writel); + } else { + mem_mapping_set_handler(&tgui->linear_mapping, + svga_read_linear, svga_readw_linear, svga_readl_linear, + svga_write_linear, svga_writew_linear, svga_writel_linear); + mem_mapping_set_handler(&svga->mapping, + svga_read, svga_readw, svga_readl, + svga_write, svga_writew, svga_writel); } - - if (tgui->pci && !(tgui->pci_regs[PCI_REG_COMMAND] & PCI_COMMAND_MEM)) - { - mem_mapping_disable(&svga->mapping); - mem_mapping_disable(&tgui->linear_mapping); - mem_mapping_disable(&tgui->accel_mapping); - mem_mapping_disable(&tgui->mmio_mapping); - return; - } - - if (svga->crtc[0x21] & 0x20) - { - mem_mapping_disable(&svga->mapping); - mem_mapping_set_addr(&tgui->linear_mapping, tgui->linear_base, tgui->linear_size); - if (tgui->type >= TGUI_9440) - { - if ((svga->crtc[0x36] & 0x03) == 0x01) - mem_mapping_set_addr(&tgui->accel_mapping, 0xb4000, 0x4000); - else if ((svga->crtc[0x36] & 0x03) == 0x02) - mem_mapping_set_addr(&tgui->accel_mapping, 0xbc000, 0x4000); - else if ((svga->crtc[0x36] & 0x03) == 0x03) - mem_mapping_set_addr(&tgui->accel_mapping, tgui->ge_base, 0x4000); - mem_mapping_disable(&svga->mapping); - } - else - { - switch (svga->gdcreg[6] & 0xC) - { - 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; - } - } - } - else - { - mem_mapping_disable(&tgui->linear_mapping); - mem_mapping_disable(&tgui->accel_mapping); - switch (svga->gdcreg[6] & 0xC) - { - 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); - if ((svga->crtc[0x36] & 0x03) == 0x01) - mem_mapping_set_addr(&tgui->accel_mapping, 0xb4000, 0x4000); - else if ((svga->crtc[0x36] & 0x03) == 0x02) - mem_mapping_set_addr(&tgui->accel_mapping, 0xbc000, 0x4000); - else if ((svga->crtc[0x36] & 0x03) == 0x03) - mem_mapping_set_addr(&tgui->accel_mapping, tgui->ge_base, 0x4000); - svga->banked_mask = 0xffff; - break; - case 0x8: /*32k at B0000*/ - mem_mapping_set_addr(&svga->mapping, 0xb0000, 0x08000); - svga->banked_mask = 0x7fff; - break; - case 0xC: /*32k at B8000*/ - mem_mapping_set_addr(&svga->mapping, 0xb8000, 0x08000); - svga->banked_mask = 0x7fff; - break; - } } - - if (tgui->type >= TGUI_9440) { - if ((tgui->mmio_base != 0x00000000) && (svga->crtc[0x39] & 1)) - mem_mapping_set_addr(&tgui->mmio_mapping, tgui->mmio_base, 0x10000); - else - mem_mapping_disable(&tgui->mmio_mapping); - } + + if (tgui->pci && !(tgui->pci_regs[PCI_REG_COMMAND] & PCI_COMMAND_MEM)) { + mem_mapping_disable(&svga->mapping); + mem_mapping_disable(&tgui->linear_mapping); + mem_mapping_disable(&tgui->accel_mapping); + mem_mapping_disable(&tgui->mmio_mapping); + return; + } + + if (svga->crtc[0x21] & 0x20) { + mem_mapping_disable(&svga->mapping); + mem_mapping_set_addr(&tgui->linear_mapping, tgui->linear_base, tgui->linear_size); + if (tgui->type >= TGUI_9440) { + if ((svga->crtc[0x36] & 0x03) == 0x01) + mem_mapping_set_addr(&tgui->accel_mapping, 0xb4000, 0x4000); + else if ((svga->crtc[0x36] & 0x03) == 0x02) + mem_mapping_set_addr(&tgui->accel_mapping, 0xbc000, 0x4000); + else if ((svga->crtc[0x36] & 0x03) == 0x03) + mem_mapping_set_addr(&tgui->accel_mapping, tgui->ge_base, 0x4000); + } else { + switch (svga->gdcreg[6] & 0xC) { + 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; + + default: + break; + } + } + } else { + mem_mapping_disable(&tgui->linear_mapping); + mem_mapping_disable(&tgui->accel_mapping); + switch (svga->gdcreg[6] & 0xC) { + 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); + if ((svga->crtc[0x36] & 0x03) == 0x01) + mem_mapping_set_addr(&tgui->accel_mapping, 0xb4000, 0x4000); + else if ((svga->crtc[0x36] & 0x03) == 0x02) + mem_mapping_set_addr(&tgui->accel_mapping, 0xbc000, 0x4000); + else if ((svga->crtc[0x36] & 0x03) == 0x03) + mem_mapping_set_addr(&tgui->accel_mapping, tgui->ge_base, 0x4000); + 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; + + default: + break; + } + } + + if (tgui->type >= TGUI_9440) { + if ((tgui->mmio_base != 0x00000000) && (svga->crtc[0x39] & 1)) + mem_mapping_set_addr(&tgui->mmio_mapping, tgui->mmio_base, 0x10000); + else + mem_mapping_disable(&tgui->mmio_mapping); + } } static void tgui_hwcursor_draw(svga_t *svga, int displine) { - uint32_t dat[2]; - int xx; - int offset = svga->hwcursor_latch.x + svga->hwcursor_latch.xoff; - int pitch = (svga->hwcursor_latch.xsize == 64) ? 16 : 8; + uint32_t dat[2]; + int offset = svga->hwcursor_latch.x + svga->hwcursor_latch.xoff; + int pitch = (svga->hwcursor_latch.cur_xsize == 64) ? 16 : 8; - if (svga->interlace && svga->hwcursor_oddeven) - svga->hwcursor_latch.addr += pitch; + if (svga->interlace && svga->hwcursor_oddeven) + svga->hwcursor_latch.addr += pitch; - dat[0] = (svga->vram[svga->hwcursor_latch.addr] << 24) | (svga->vram[svga->hwcursor_latch.addr + 1] << 16) | (svga->vram[svga->hwcursor_latch.addr + 2] << 8) | svga->vram[svga->hwcursor_latch.addr + 3]; - dat[1] = (svga->vram[svga->hwcursor_latch.addr + 4] << 24) | (svga->vram[svga->hwcursor_latch.addr + 5] << 16) | (svga->vram[svga->hwcursor_latch.addr + 6] << 8) | svga->vram[svga->hwcursor_latch.addr + 7]; - for (xx = 0; xx < 32; xx++) { - if (svga->crtc[0x50] & 0x40) { - if (offset >= svga->hwcursor_latch.x) - { - if (dat[0] & 0x80000000) - ((uint32_t *)buffer32->line[displine])[svga->x_add + offset] = (dat[1] & 0x80000000) ? 0xffffff : 0; - } - } else { - if (offset >= svga->hwcursor_latch.x) - { - if (!(dat[0] & 0x80000000)) - ((uint32_t *)buffer32->line[displine])[svga->x_add + offset] = (dat[1] & 0x80000000) ? 0xffffff : 0; - else if (dat[1] & 0x80000000) - ((uint32_t *)buffer32->line[displine])[svga->x_add + offset] ^= 0xffffff; - } - } - offset++; - dat[0] <<= 1; - dat[1] <<= 1; - } - svga->hwcursor_latch.addr += pitch; - - if (svga->interlace && !svga->hwcursor_oddeven) - svga->hwcursor_latch.addr += pitch; -} - -uint8_t tgui_pci_read(int func, int addr, void *p) -{ - tgui_t *tgui = (tgui_t *)p; - - switch (addr) - { - case 0x00: return 0x23; /*Trident*/ - case 0x01: return 0x10; - - case 0x02: return (tgui->type == TGUI_9440) ? 0x40 : 0x60; /*TGUI9440AGi or TGUI9660XGi*/ - case 0x03: return (tgui->type == TGUI_9440) ? 0x94 : 0x96; - - case PCI_REG_COMMAND: return tgui->pci_regs[PCI_REG_COMMAND]; /*Respond to IO and memory accesses*/ - - case 0x07: return 1 << 1; /*Medium DEVSEL timing*/ - - case 0x08: return 0; /*Revision ID*/ - case 0x09: return 0; /*Programming interface*/ - - case 0x0a: return 0x01; /*Supports VGA interface, XGA compatible*/ - case 0x0b: return 0x03; - - case 0x10: return 0x00; /*Linear frame buffer address*/ - case 0x11: return 0x00; - case 0x12: return tgui->linear_base >> 16; - case 0x13: return tgui->linear_base >> 24; - - case 0x14: return 0x00; /*MMIO address*/ - case 0x15: return 0x00; - case 0x16: return tgui->mmio_base >> 16; - case 0x17: return tgui->mmio_base >> 24; - - case 0x30: return tgui->has_bios ? (tgui->pci_regs[0x30] & 0x01) : 0x00; /*BIOS ROM address*/ - case 0x31: return 0x00; - case 0x32: return tgui->has_bios ? tgui->pci_regs[0x32] : 0x00; - case 0x33: return tgui->has_bios ? tgui->pci_regs[0x33] : 0x00; - - case 0x3c: return tgui->int_line; - case 0x3d: return PCI_INTA; + dat[0] = (svga->vram[svga->hwcursor_latch.addr] << 24) | (svga->vram[svga->hwcursor_latch.addr + 1] << 16) | (svga->vram[svga->hwcursor_latch.addr + 2] << 8) | svga->vram[svga->hwcursor_latch.addr + 3]; + dat[1] = (svga->vram[svga->hwcursor_latch.addr + 4] << 24) | (svga->vram[svga->hwcursor_latch.addr + 5] << 16) | (svga->vram[svga->hwcursor_latch.addr + 6] << 8) | svga->vram[svga->hwcursor_latch.addr + 7]; + for (uint8_t xx = 0; xx < 32; xx++) { + if (svga->crtc[0x50] & 0x40) { + if (offset >= svga->hwcursor_latch.x) { + if (dat[0] & 0x80000000) + (buffer32->line[displine])[svga->x_add + offset] = (dat[1] & 0x80000000) ? 0xffffff : 0; + } + } else { + if (offset >= svga->hwcursor_latch.x) { + if (!(dat[0] & 0x80000000)) + (buffer32->line[displine])[svga->x_add + offset] = (dat[1] & 0x80000000) ? 0xffffff : 0; + else if (dat[1] & 0x80000000) + (buffer32->line[displine])[svga->x_add + offset] ^= 0xffffff; + } } - return 0; + offset++; + dat[0] <<= 1; + dat[1] <<= 1; + } + svga->hwcursor_latch.addr += pitch; + + if (svga->interlace && !svga->hwcursor_oddeven) + svga->hwcursor_latch.addr += pitch; } -void tgui_pci_write(int func, int addr, uint8_t val, void *p) +uint8_t +tgui_pci_read(UNUSED(int func), int addr, void *priv) { - tgui_t *tgui = (tgui_t *)p; - svga_t *svga = &tgui->svga; + const tgui_t *tgui = (tgui_t *) priv; - switch (addr) - { - case PCI_REG_COMMAND: - tgui->pci_regs[PCI_REG_COMMAND] = (val & 0x23); - if (val & PCI_COMMAND_IO) { - tgui_set_io(tgui); - } else - tgui_remove_io(tgui); - tgui_recalcmapping(tgui); - break; - - case 0x12: - if (tgui->type >= TGUI_9660) - tgui->linear_base = (tgui->linear_base & 0xff000000) | ((val & 0xc0) << 16); - else - tgui->linear_base = (tgui->linear_base & 0xff000000) | ((val & 0xe0) << 16); - tgui->linear_size = tgui->vram_size; - svga->decode_mask = tgui->vram_mask; - tgui_recalcmapping(tgui); - break; - case 0x13: - if (tgui->type >= TGUI_9660) - tgui->linear_base = (tgui->linear_base & 0xc00000) | (val << 24); - else - tgui->linear_base = (tgui->linear_base & 0xe00000) | (val << 24); - tgui->linear_size = tgui->vram_size; - svga->decode_mask = tgui->vram_mask; - tgui_recalcmapping(tgui); - break; + switch (addr) { + case 0x00: + return 0x23; /*Trident*/ + case 0x01: + return 0x10; - case 0x16: - if (tgui->type >= TGUI_9660) - tgui->mmio_base = (tgui->mmio_base & 0xff000000) | ((val & 0xc0) << 16); - else - tgui->mmio_base = (tgui->mmio_base & 0xff000000) | ((val & 0xe0) << 16); - tgui_recalcmapping(tgui); - break; - case 0x17: - if (tgui->type >= TGUI_9660) - tgui->mmio_base = (tgui->mmio_base & 0x00c00000) | (val << 24); - else - tgui->mmio_base = (tgui->mmio_base & 0x00e00000) | (val << 24); - tgui_recalcmapping(tgui); - break; + case 0x02: + return (tgui->type == TGUI_9440) ? 0x40 : 0x60; /*TGUI9440AGi or TGUI96x0XGi*/ + case 0x03: + return (tgui->type == TGUI_9440) ? 0x94 : 0x96; - case 0x30: case 0x32: case 0x33: - if (tgui->has_bios) { - tgui->pci_regs[addr] = val; - if (tgui->pci_regs[0x30] & 0x01) - { - uint32_t biosaddr = (tgui->pci_regs[0x32] << 16) | (tgui->pci_regs[0x33] << 24); - mem_mapping_set_addr(&tgui->bios_rom.mapping, biosaddr, 0x8000); - } - else - { - mem_mapping_disable(&tgui->bios_rom.mapping); - } - } - return; + case PCI_REG_COMMAND: + return tgui->pci_regs[PCI_REG_COMMAND]; /*Respond to IO and memory accesses*/ - case 0x3c: - tgui->int_line = val; - return; + case 0x07: + return 1 << 1; /*Medium DEVSEL timing*/ + + case 0x08: + return 0; /*Revision ID*/ + case 0x09: + return 0; /*Programming interface*/ + + case 0x0a: + return 0x01; /*Supports VGA interface, XGA compatible*/ + case 0x0b: + return 0x03; + + case 0x10: + return 0x00; /*Linear frame buffer address*/ + case 0x11: + return 0x00; + case 0x12: + return tgui->linear_base >> 16; + case 0x13: + return tgui->linear_base >> 24; + + case 0x14: + return 0x00; /*MMIO address*/ + case 0x15: + return 0x00; + case 0x16: + return tgui->mmio_base >> 16; + case 0x17: + return tgui->mmio_base >> 24; + + case 0x30: + return tgui->has_bios ? (tgui->pci_regs[0x30] & 0x01) : 0x00; /*BIOS ROM address*/ + case 0x31: + return 0x00; + case 0x32: + return tgui->has_bios ? tgui->pci_regs[0x32] : 0x00; + case 0x33: + return tgui->has_bios ? tgui->pci_regs[0x33] : 0x00; + + case 0x3c: + return tgui->int_line; + case 0x3d: + return PCI_INTA; + + default: + break; + } + return 0; +} + +void +tgui_pci_write(UNUSED(int func), int addr, uint8_t val, void *priv) +{ + tgui_t *tgui = (tgui_t *) priv; + svga_t *svga = &tgui->svga; + + switch (addr) { + case PCI_REG_COMMAND: + tgui->pci_regs[PCI_REG_COMMAND] = (val & 0x23); + if (val & PCI_COMMAND_IO) { + tgui_set_io(tgui); + } else + tgui_remove_io(tgui); + tgui_recalcmapping(tgui); + break; + + case 0x12: + if (tgui->type >= TGUI_9660) + tgui->linear_base = (tgui->linear_base & 0xff000000) | ((val & 0xc0) << 16); + else + tgui->linear_base = (tgui->linear_base & 0xff000000) | ((val & 0xe0) << 16); + tgui->linear_size = tgui->vram_size; + svga->decode_mask = tgui->vram_mask; + tgui_recalcmapping(tgui); + break; + case 0x13: + if (tgui->type >= TGUI_9660) + tgui->linear_base = (tgui->linear_base & 0xc00000) | (val << 24); + else + tgui->linear_base = (tgui->linear_base & 0xe00000) | (val << 24); + tgui->linear_size = tgui->vram_size; + svga->decode_mask = tgui->vram_mask; + tgui_recalcmapping(tgui); + break; + + case 0x16: + if (tgui->type >= TGUI_9660) + tgui->mmio_base = (tgui->mmio_base & 0xff000000) | ((val & 0xc0) << 16); + else + tgui->mmio_base = (tgui->mmio_base & 0xff000000) | ((val & 0xe0) << 16); + tgui_recalcmapping(tgui); + break; + case 0x17: + if (tgui->type >= TGUI_9660) + tgui->mmio_base = (tgui->mmio_base & 0x00c00000) | (val << 24); + else + tgui->mmio_base = (tgui->mmio_base & 0x00e00000) | (val << 24); + tgui_recalcmapping(tgui); + break; + + case 0x30: + case 0x32: + case 0x33: + if (tgui->has_bios) { + tgui->pci_regs[addr] = val; + if (tgui->pci_regs[0x30] & 0x01) { + uint32_t biosaddr = (tgui->pci_regs[0x32] << 16) | (tgui->pci_regs[0x33] << 24); + mem_mapping_set_addr(&tgui->bios_rom.mapping, biosaddr, 0x8000); + } else { + mem_mapping_disable(&tgui->bios_rom.mapping); + } + } + return; + + case 0x3c: + tgui->int_line = val; + return; + + default: + break; + } +} + +static uint8_t +tgui_ext_linear_read(uint32_t addr, void *priv) +{ + svga_t *svga = (svga_t *) priv; + tgui_t *tgui = (tgui_t *) svga->priv; + + cycles -= video_timing_read_b; + + addr &= svga->decode_mask; + if (addr >= svga->vram_max) + return 0xff; + + addr &= svga->vram_mask; + addr &= (tgui->ext_gdc_regs[0] & EXT_CTRL_LATCH_COPY) ? ~0x0f : ~0x07; + addr = dword_remap(svga, addr); + + if (tgui->ext_gdc_regs[0] & EXT_CTRL_LATCH_COPY) { + for (int c = 0; c < 16; c++) { + tgui->copy_latch[c] = svga->vram[addr]; + addr += (c & 3) ? 1 : 13; + addr &= svga->vram_mask; } + return svga->vram[addr]; + } + + return svga_read_linear(addr, svga); } -static uint8_t tgui_ext_linear_read(uint32_t addr, void *p) +static uint8_t +tgui_ext_read(uint32_t addr, void *priv) { - svga_t *svga = (svga_t *)p; - tgui_t *tgui = (tgui_t *)svga->p; - int c; + svga_t *svga = (svga_t *) priv; - cycles -= video_timing_read_b; + addr = (addr & svga->banked_mask) + svga->read_bank; - addr &= svga->decode_mask; - if (addr >= svga->vram_max) - return 0xff; - - addr &= ~0xf; - addr = dword_remap(svga, addr); + return tgui_ext_linear_read(addr, svga); +} +static void +tgui_ext_linear_write(uint32_t addr, uint8_t val, void *priv) +{ + svga_t *svga = (svga_t *) priv; + const tgui_t *tgui = (tgui_t *) svga->priv; + int c; + int bpp = (tgui->ext_gdc_regs[0] & EXT_CTRL_16BIT); + uint8_t fg[2] = { tgui->ext_gdc_regs[4], tgui->ext_gdc_regs[5] }; + uint8_t bg[2] = { tgui->ext_gdc_regs[1], tgui->ext_gdc_regs[2] }; + uint8_t mask = tgui->ext_gdc_regs[7]; + + cycles -= video_timing_write_b; + + addr &= svga->decode_mask; + if (addr >= svga->vram_max) + return; + addr &= svga->vram_mask; + addr &= (tgui->ext_gdc_regs[0] & EXT_CTRL_LATCH_COPY) ? ~0x0f : ~0x07; + + addr = dword_remap(svga, addr); + svga->changedvram[addr >> 12] = svga->monitor->mon_changeframecount; + + if (tgui->ext_gdc_regs[0] & EXT_CTRL_LATCH_COPY) { for (c = 0; c < 16; c++) { - tgui->copy_latch[c] = svga->vram[addr+c]; - addr += ((c & 3) == 3) ? 13 : 1; - } - - return svga->vram[addr & svga->vram_mask]; -} - -static uint8_t tgui_ext_read(uint32_t addr, void *p) -{ - svga_t *svga = (svga_t *)p; - - addr = (addr & svga->banked_mask) + svga->read_bank; - - return tgui_ext_linear_read(addr, svga); -} - -static void tgui_ext_linear_write(uint32_t addr, uint8_t val, void *p) -{ - svga_t *svga = (svga_t *)p; - tgui_t *tgui = (tgui_t *)svga->p; - int c; - uint8_t fg[2] = {tgui->ext_gdc_regs[4], tgui->ext_gdc_regs[5]}; - uint8_t bg[2] = {tgui->ext_gdc_regs[1], tgui->ext_gdc_regs[2]}; - uint8_t mask = tgui->ext_gdc_regs[7]; - - cycles -= video_timing_write_b; - - addr &= svga->decode_mask; - if (addr >= svga->vram_max) - return; - addr &= svga->vram_mask; - addr &= (tgui->ext_gdc_regs[0] & 8) ? ~0xf : ~0x7; - - addr = dword_remap(svga, addr); - svga->changedvram[addr >> 12] = changeframecount; - - switch (tgui->ext_gdc_regs[0] & 0xf) - { - /*8-bit mono->colour expansion, unmasked*/ - case 2: - for (c = 7; c >= 0; c--) - { - if (mask & (1 << c)) - *(uint8_t *)&svga->vram[addr] = (val & (1 << c)) ? fg[0] : bg[0]; - addr += (c == 4) ? 13 : 1; - } - break; - - /*16-bit mono->colour expansion, unmasked*/ - case 3: - for (c = 7; c >= 0; c--) - { - if (mask & (1 << c)) - *(uint8_t *)&svga->vram[addr] = (val & (1 << c)) ? fg[(c & 1) ^ 1] : bg[(c & 1) ^ 1]; - addr += (c == 4) ? 13 : 1; - } - break; - - /*8-bit mono->colour expansion, masked*/ - case 6: - for (c = 7; c >= 0; c--) - { - if ((val & mask) & (1 << c)) - *(uint8_t *)&svga->vram[addr] = fg[0]; - addr += (c == 4) ? 13 : 1; - } - break; - - /*16-bit mono->colour expansion, masked*/ - case 7: - for (c = 7; c >= 0; c--) - { - if ((val & mask) & (1 << c)) - *(uint8_t *)&svga->vram[addr] = fg[(c & 1) ^ 1]; - addr += (c == 4) ? 13 : 1; - } - break; - - case 0x8: case 0x9: case 0xa: case 0xb: - case 0xc: case 0xd: case 0xe: case 0xf: - for (c = 0; c < 16; c++) { - *(uint8_t *)&svga->vram[addr] = tgui->copy_latch[c]; - addr += ((c & 3) == 3) ? 13 : 1; - } - break; + svga->vram[addr] = tgui->copy_latch[c]; + addr += ((c & 3) == 3) ? 13 : 1; + addr &= svga->vram_mask; } -} - -static void tgui_ext_linear_writew(uint32_t addr, uint16_t val, void *p) -{ - svga_t *svga = (svga_t *)p; - tgui_t *tgui = (tgui_t *)svga->p; - int c; - uint8_t fg[2] = {tgui->ext_gdc_regs[4], tgui->ext_gdc_regs[5]}; - uint8_t bg[2] = {tgui->ext_gdc_regs[1], tgui->ext_gdc_regs[2]}; - uint16_t mask = (tgui->ext_gdc_regs[7] << 8) | tgui->ext_gdc_regs[8]; - - cycles -= video_timing_write_w; - - addr &= svga->decode_mask; - if (addr >= svga->vram_max) - return; - addr &= svga->vram_mask; - addr &= ~0xf; - - addr = dword_remap(svga, addr); - svga->changedvram[addr >> 12] = changeframecount; - - val = (val >> 8) | (val << 8); - - switch (tgui->ext_gdc_regs[0] & 0xf) - { - /*8-bit mono->colour expansion, unmasked*/ - case 2: - for (c = 15; c >= 0; c--) - { - if (mask & (1 << c)) - *(uint8_t *)&svga->vram[addr] = (val & (1 << c)) ? fg[0] : bg[0]; - addr += (c & 3) ? 1 : 13; + } else if (tgui->ext_gdc_regs[0] & (EXT_CTRL_MONO_EXPANSION | EXT_CTRL_MONO_TRANSPARENT)) { + if (tgui->ext_gdc_regs[0] & EXT_CTRL_MONO_TRANSPARENT) { + if (bpp) { + for (c = 7; c >= 0; c--) { + if ((val & mask) & (1 << c)) + svga->vram[addr] = fg[(c & 1) ^ 1]; + addr += (c & 3) ? 1 : 13; + addr &= svga->vram_mask; } - break; - - /*16-bit mono->colour expansion, unmasked*/ - case 3: - for (c = 15; c >= 0; c--) - { - if (mask & (1 << c)) - *(uint8_t *)&svga->vram[addr] = (val & (1 << c)) ? fg[(c & 1) ^ 1] : bg[(c & 1) ^ 1]; - addr += (c & 3) ? 1 : 13; + } else { + for (c = 7; c >= 0; c--) { + if ((val & mask) & (1 << c)) + svga->vram[addr] = tgui->ext_gdc_regs[4]; + addr += (c == 4) ? 13 : 1; + addr &= svga->vram_mask; } - break; - - /*8-bit mono->colour expansion, masked*/ - case 6: - for (c = 15; c >= 0; c--) - { - if ((val & mask) & (1 << c)) - *(uint8_t *)&svga->vram[addr] = fg[0]; - addr += (c & 3) ? 1 : 13; + } + } else { + if (bpp) { + for (c = 7; c >= 0; c--) { + if (mask & (1 << c)) + svga->vram[addr] = (val & (1 << c)) ? fg[(c & 1) ^ 1] : bg[(c & 1) ^ 1]; + addr += (c & 3) ? 1 : 13; + addr &= svga->vram_mask; } - break; - - /*16-bit mono->colour expansion, masked*/ - case 7: - for (c = 15; c >= 0; c--) - { - if ((val & mask) & (1 << c)) - *(uint8_t *)&svga->vram[addr] = fg[(c & 1) ^ 1]; - addr += (c & 3) ? 1 : 13; + } else { + for (c = 7; c >= 0; c--) { + if (mask & (1 << c)) + svga->vram[addr] = (val & (1 << c)) ? tgui->ext_gdc_regs[4] : tgui->ext_gdc_regs[1]; + addr += (c == 4) ? 13 : 1; + addr &= svga->vram_mask; } - break; - - case 0x8: case 0x9: case 0xa: case 0xb: - case 0xc: case 0xd: case 0xe: case 0xf: - for (c = 0; c < 16; c++) { - *(uint8_t *)&svga->vram[addr+c] = tgui->copy_latch[c]; - addr += ((c & 3) == 3) ? 13 : 1; - } - break; + } } + } else + svga_write_linear(addr, val, svga); } -static void tgui_ext_linear_writel(uint32_t addr, uint32_t val, void *p) +static void +tgui_ext_linear_writew(uint32_t addr, uint16_t val, void *priv) { - tgui_ext_linear_writew(addr, val, p); + svga_t *svga = (svga_t *) priv; + const tgui_t *tgui = (tgui_t *) svga->priv; + int c; + int bpp = (tgui->ext_gdc_regs[0] & EXT_CTRL_16BIT); + uint8_t fg[2] = { tgui->ext_gdc_regs[4], tgui->ext_gdc_regs[5] }; + uint8_t bg[2] = { tgui->ext_gdc_regs[1], tgui->ext_gdc_regs[2] }; + uint16_t mask = (tgui->ext_gdc_regs[7] << 8) | tgui->ext_gdc_regs[8]; + + cycles -= video_timing_write_w; + + addr &= svga->decode_mask; + if (addr >= svga->vram_max) + return; + addr &= svga->vram_mask; + addr &= (tgui->ext_gdc_regs[0] & EXT_CTRL_LATCH_COPY) ? ~0x0f : ~0x07; + + addr = dword_remap(svga, addr); + svga->changedvram[addr >> 12] = svga->monitor->mon_changeframecount; + + val = (val >> 8) | (val << 8); + + if (tgui->ext_gdc_regs[0] & EXT_CTRL_LATCH_COPY) { + for (c = 0; c < 16; c++) { + svga->vram[addr] = tgui->copy_latch[c]; + addr += (c & 3) ? 1 : 13; + addr &= svga->vram_mask; + } + } else if (tgui->ext_gdc_regs[0] & (EXT_CTRL_MONO_EXPANSION | EXT_CTRL_MONO_TRANSPARENT)) { + if (tgui->ext_gdc_regs[0] & EXT_CTRL_MONO_TRANSPARENT) { + if (bpp) { + for (c = 15; c >= 0; c--) { + if ((val & mask) & (1 << c)) + svga->vram[addr] = fg[(c & 1) ^ 1]; + addr += (c & 3) ? 1 : 13; + addr &= svga->vram_mask; + } + } else { + for (c = 15; c >= 0; c--) { + if ((val & mask) & (1 << c)) + svga->vram[addr] = tgui->ext_gdc_regs[4]; + + addr += (c & 3) ? 1 : 13; + addr &= svga->vram_mask; + } + } + } else { + if (bpp) { + for (c = 15; c >= 0; c--) { + if (mask & (1 << c)) + svga->vram[addr] = (val & (1 << c)) ? fg[(c & 1) ^ 1] : bg[(c & 1) ^ 1]; + addr += (c & 3) ? 1 : 13; + addr &= svga->vram_mask; + } + } else { + for (c = 15; c >= 0; c--) { + if (mask & (1 << c)) + svga->vram[addr] = (val & (1 << c)) ? tgui->ext_gdc_regs[4] : tgui->ext_gdc_regs[1]; + + addr += (c & 3) ? 1 : 13; + addr &= svga->vram_mask; + } + } + } + } else + svga_writew_linear(addr, val, svga); } - -static void tgui_ext_write(uint32_t addr, uint8_t val, void *p) +static void +tgui_ext_linear_writel(uint32_t addr, uint32_t val, void *priv) { - svga_t *svga = (svga_t *)p; - - addr = (addr & svga->banked_mask) + svga->read_bank; + svga_t *svga = (svga_t *) priv; + const tgui_t *tgui = (tgui_t *) svga->priv; - tgui_ext_linear_write(addr, val, svga); -} -static void tgui_ext_writew(uint32_t addr, uint16_t val, void *p) -{ - svga_t *svga = (svga_t *)p; - - addr = (addr & svga->banked_mask) + svga->read_bank; + cycles -= video_timing_write_l; - tgui_ext_linear_writew(addr, val, svga); -} -static void tgui_ext_writel(uint32_t addr, uint32_t val, void *p) -{ - svga_t *svga = (svga_t *)p; - - addr = (addr & svga->banked_mask) + svga->read_bank; + addr &= svga->decode_mask; + if (addr >= svga->vram_max) + return; + addr &= svga->vram_mask; + addr &= (tgui->ext_gdc_regs[0] & EXT_CTRL_LATCH_COPY) ? ~0x0f : ~0x07; - tgui_ext_linear_writel(addr, val, svga); + addr = dword_remap(svga, addr); + svga->changedvram[addr >> 12] = svga->monitor->mon_changeframecount; + + if (tgui->ext_gdc_regs[0] & (EXT_CTRL_MONO_EXPANSION | EXT_CTRL_MONO_TRANSPARENT | EXT_CTRL_LATCH_COPY)) { + tgui_ext_linear_writew(addr, val & 0xffff, priv); + tgui_ext_linear_writew(addr + 2, val >> 16, priv); + } else { + svga_writel_linear(addr, val, svga); + } } - -enum +static void +tgui_ext_write(uint32_t addr, uint8_t val, void *priv) { - TGUI_BITBLT = 1, - TGUI_SCANLINE = 3, - TGUI_BRESENHAMLINE = 4, - TGUI_SHORTVECTOR = 5, - TGUI_FASTLINE = 6 + svga_t *svga = (svga_t *) priv; + + addr = (addr & svga->banked_mask) + svga->write_bank; + + tgui_ext_linear_write(addr, val, svga); +} +static void +tgui_ext_writew(uint32_t addr, uint16_t val, void *priv) +{ + svga_t *svga = (svga_t *) priv; + + addr = (addr & svga->banked_mask) + svga->write_bank; + + tgui_ext_linear_writew(addr, val, svga); +} +static void +tgui_ext_writel(uint32_t addr, uint32_t val, void *priv) +{ + svga_t *svga = (svga_t *) priv; + + addr = (addr & svga->banked_mask) + svga->write_bank; + + tgui_ext_linear_writel(addr, val, svga); +} + +enum { + TGUI_BITBLT = 1, + TGUI_SCANLINE = 3, + TGUI_BRESENHAMLINE = 4, + TGUI_SHORTVECTOR = 5, + TGUI_FASTLINE = 6 }; -enum -{ - TGUI_SRCCPU = 0, - TGUI_SRCPAT = 0x02, /*Source is from pattern*/ - TGUI_SRCDISP = 0x04, /*Source is from display*/ - TGUI_PATMONO = 0x20, /*Pattern is monochrome and needs expansion*/ - TGUI_SRCMONO = 0x40, /*Source is monochrome from CPU and needs expansion*/ - TGUI_TRANSENA = 0x1000, /*Transparent (no draw when source == bg col)*/ - TGUI_TRANSREV = 0x2000, /*Reverse fg/bg for transparent*/ - TGUI_SOLIDFILL = 0x4000, /*Pattern set to foreground color*/ - TGUI_STENCIL = 0x8000 /*Stencil*/ +enum { + TGUI_SRCCPU = 0, + TGUI_SRCPAT = 0x02, /*Source is from pattern*/ + TGUI_SRCDISP = 0x04, /*Source is from display*/ + TGUI_PATMONO = 0x20, /*Pattern is monochrome and needs expansion*/ + TGUI_SRCMONO = 0x40, /*Source is monochrome from CPU and needs expansion*/ + TGUI_TRANSENA = 0x1000, /*Transparent (no draw when source == bg col)*/ + TGUI_TRANSREV = 0x2000, /*Reverse fg/bg for transparent*/ + TGUI_SOLIDFILL = 0x4000, /*Pattern set to foreground color*/ + TGUI_STENCIL = 0x8000 /*Stencil*/ }; -#define READ(addr, dat) if (tgui->accel.bpp == 0) dat = svga->vram[(addr) & tgui->vram_mask]; \ - else if (tgui->accel.bpp == 1) dat = vram_w[(addr) & (tgui->vram_mask >> 1)]; \ - else dat = vram_l[(addr) & (tgui->vram_mask >> 2)]; \ - -#define MIX() do \ - { \ - out = 0; \ - for (c=0;c<32;c++) \ - { \ - d=(dst_dat & (1<accel.rop & (1<accel.bpp == 0) \ + dat = svga->vram[(addr) &tgui->vram_mask]; \ + else if (tgui->accel.bpp == 1) \ + dat = vram_w[(addr) & (tgui->vram_mask >> 1)]; \ + else \ + dat = vram_l[(addr) & (tgui->vram_mask >> 2)]; + +#define MIX() \ + do { \ + out = 0; \ + for (c = 0; c < 32; c++) { \ + d = (dst_dat & (1 << c)) ? 1 : 0; \ + if (src_dat & (1 << c)) \ + d |= 2; \ + if (pat_dat & (1 << c)) \ + d |= 4; \ + if (tgui->accel.rop & (1 << d)) \ + out |= (1 << c); \ + } \ + } while (0) + +#define WRITE(addr, dat) \ + if (tgui->accel.bpp == 0) { \ + svga->vram[(addr) &tgui->vram_mask] = dat; \ + svga->changedvram[((addr) & (tgui->vram_mask)) >> 12] = svga->monitor->mon_changeframecount; \ + } else if (tgui->accel.bpp == 1) { \ + vram_w[(addr) & (tgui->vram_mask >> 1)] = dat; \ + svga->changedvram[((addr) & (tgui->vram_mask >> 1)) >> 11] = svga->monitor->mon_changeframecount; \ + } else { \ + vram_l[(addr) & (tgui->vram_mask >> 2)] = dat; \ + svga->changedvram[((addr) & (tgui->vram_mask >> 2)) >> 10] = svga->monitor->mon_changeframecount; \ + } -#define WRITE(addr, dat) if (tgui->accel.bpp == 0) \ - { \ - svga->vram[(addr) & tgui->vram_mask] = dat; \ - svga->changedvram[((addr) & (tgui->vram_mask)) >> 12] = changeframecount; \ - } \ - else if (tgui->accel.bpp == 1) \ - { \ - vram_w[(addr) & (tgui->vram_mask >> 1)] = dat; \ - svga->changedvram[((addr) & (tgui->vram_mask >> 1)) >> 11] = changeframecount; \ - } \ - else \ - { \ - vram_l[(addr) & (tgui->vram_mask >> 2)] = dat; \ - svga->changedvram[((addr) & (tgui->vram_mask >> 2)) >> 10] = changeframecount; \ - } - static void tgui_accel_command(int count, uint32_t cpu_dat, tgui_t *tgui) { + svga_t *svga = &tgui->svga; + const uint32_t *pattern_data; + int x; + int y; + int c; + int d; + uint32_t out; + uint32_t src_dat = 0; + uint32_t dst_dat; + uint32_t pat_dat; + int xdir = (tgui->accel.flags & 0x200) ? -1 : 1; + int ydir = (tgui->accel.flags & 0x100) ? -1 : 1; + uint32_t trans_col = (tgui->accel.flags & TGUI_TRANSREV) ? tgui->accel.fg_col : tgui->accel.bg_col; + uint16_t *vram_w = (uint16_t *) svga->vram; + uint32_t *vram_l = (uint32_t *) svga->vram; + + if (tgui->accel.bpp == 0) { + trans_col &= 0xff; + } else if (tgui->accel.bpp == 1) { + trans_col &= 0xffff; + } + + if ((count != -1) && !tgui->accel.x && (tgui->accel.flags & TGUI_SRCMONO)) { + count -= (tgui->accel.flags >> 24) & 7; + cpu_dat <<= (tgui->accel.flags >> 24) & 7; + } + + if (count == -1) + tgui->accel.x = tgui->accel.y = 0; + + if (tgui->accel.flags & TGUI_SOLIDFILL) { + for (y = 0; y < 8; y++) { + for (x = 0; x < 8; x++) { + tgui->accel.fill_pattern[(y * 8) + (7 - x)] = tgui->accel.fg_col; + } + } + pattern_data = tgui->accel.fill_pattern; + } else if (tgui->accel.flags & TGUI_PATMONO) { + for (y = 0; y < 8; y++) { + for (x = 0; x < 8; x++) { + tgui->accel.mono_pattern[(y * 8) + (7 - x)] = (tgui->accel.pattern[y] & (1 << x)) ? tgui->accel.fg_col : tgui->accel.bg_col; + } + } + pattern_data = tgui->accel.mono_pattern; + } else { + if (tgui->accel.bpp == 0) { + for (y = 0; y < 8; y++) { + for (x = 0; x < 8; x++) { + tgui->accel.pattern_8[(y * 8) + (7 - x)] = tgui->accel.pattern[x + y * 8]; + } + } + pattern_data = tgui->accel.pattern_8; + } else if (tgui->accel.bpp == 1) { + for (y = 0; y < 8; y++) { + for (x = 0; x < 8; x++) { + tgui->accel.pattern_16[(y * 8) + (7 - x)] = tgui->accel.pattern[x * 2 + y * 16] | (tgui->accel.pattern[x * 2 + y * 16 + 1] << 8); + } + } + pattern_data = tgui->accel.pattern_16; + } else { + for (y = 0; y < 4; y++) { + for (x = 0; x < 8; x++) { + tgui->accel.pattern_32[(y * 8) + (7 - x)] = tgui->accel.pattern[x * 4 + y * 32] | (tgui->accel.pattern[x * 4 + y * 32 + 1] << 8) | (tgui->accel.pattern[x * 4 + y * 32 + 2] << 16) | (tgui->accel.pattern[x * 4 + y * 32 + 3] << 24); + tgui->accel.pattern_32[((y + 4) * 8) + (7 - x)] = tgui->accel.pattern[x * 4 + y * 32] | (tgui->accel.pattern[x * 4 + y * 32 + 1] << 8) | (tgui->accel.pattern[x * 4 + y * 32 + 2] << 16) | (tgui->accel.pattern[x * 4 + y * 32 + 3] << 24); + } + } + pattern_data = tgui->accel.pattern_32; + } + } + + /*See this: https://android.googlesource.com/kernel/tegra/+/android-tegra-flounder-3.10-lollipop-release/drivers/video/tridentfb.c for the pitch*/ + tgui->accel.pitch = svga->rowoffset; + + switch (svga->bpp) { + case 8: + case 24: + tgui->accel.pitch <<= 3; + break; + case 15: + case 16: + tgui->accel.pitch <<= 2; + break; + case 32: + tgui->accel.pitch <<= 1; + break; + } +#if 0 + pclog("TGUI accel command = %x, ger22 = %04x, hdisp = %d, dispend = %d, vtotal = %d, rowoffset = %d, svgabpp = %d, interlace = %d, accelbpp = %d, pitch = %d.\n", tgui->accel.command, tgui->accel.ger22, svga->hdisp, svga->dispend, svga->vtotal, svga->rowoffset, svga->bpp, svga->interlace, tgui->accel.bpp, tgui->accel.pitch); +#endif + + switch (tgui->accel.command) { + case TGUI_BITBLT: + if (count == -1) { + tgui->accel.src_old = tgui->accel.src_x + (tgui->accel.src_y * tgui->accel.pitch); + tgui->accel.src = tgui->accel.src_old; + + tgui->accel.dst_old = tgui->accel.dst_x + (tgui->accel.dst_y * tgui->accel.pitch); + tgui->accel.dst = tgui->accel.dst_old; + + tgui->accel.pat_x = tgui->accel.dst_x; + tgui->accel.pat_y = tgui->accel.dst_y; + + tgui->accel.dx = tgui->accel.dst_x & 0xfff; + tgui->accel.dy = tgui->accel.dst_y & 0xfff; + + tgui->accel.left = tgui->accel.src_x_clip & 0xfff; + tgui->accel.right = tgui->accel.dst_x_clip & 0xfff; + tgui->accel.top = tgui->accel.src_y_clip & 0xfff; + tgui->accel.bottom = tgui->accel.dst_y_clip & 0xfff; + + if (tgui->accel.bpp == 1) { + tgui->accel.left >>= 1; + tgui->accel.right >>= 1; + } else if (tgui->accel.bpp == 3) { + tgui->accel.left >>= 2; + tgui->accel.right >>= 2; + } + } + + switch (tgui->accel.flags & (TGUI_SRCMONO | TGUI_SRCDISP)) { + case TGUI_SRCCPU: + if (count == -1) { + if (svga->crtc[0x21] & 0x20) + tgui->write_blitter = 1; + if (tgui->accel.use_src) + return; + } else + count >>= 3; + + while (count) { + if ((tgui->type == TGUI_9440) || ((tgui->type >= TGUI_9660) && tgui->accel.dx >= tgui->accel.left && tgui->accel.dx <= tgui->accel.right && tgui->accel.dy >= tgui->accel.top && tgui->accel.dy <= tgui->accel.bottom)) { + if (tgui->accel.bpp == 0) { + src_dat = cpu_dat >> 24; + cpu_dat <<= 8; + } else if (tgui->accel.bpp == 1) { + src_dat = (cpu_dat >> 24) | ((cpu_dat >> 8) & 0xff00); + cpu_dat <<= 16; + count--; + } else { + src_dat = (cpu_dat >> 24) | ((cpu_dat >> 8) & 0x0000ff00) | ((cpu_dat << 8) & 0x00ff0000); + cpu_dat <<= 16; + count -= 3; + } + + READ(tgui->accel.dst, dst_dat); + + pat_dat = pattern_data[((tgui->accel.pat_y & 7) * 8) + (tgui->accel.pat_x & 7)]; + + if (tgui->accel.bpp == 0) + pat_dat &= 0xff; + else if (tgui->accel.bpp == 1) + pat_dat &= 0xffff; + + if ((((tgui->accel.flags & (TGUI_PATMONO | TGUI_TRANSENA)) == (TGUI_TRANSENA | TGUI_PATMONO)) && (pat_dat != trans_col)) || !(tgui->accel.flags & TGUI_PATMONO) || ((tgui->accel.flags & (TGUI_PATMONO | TGUI_TRANSENA)) == TGUI_PATMONO) || (tgui->accel.ger22 & 0x200)) { + MIX(); + + WRITE(tgui->accel.dst, out); + } + } + + tgui->accel.src += xdir; + tgui->accel.dst += xdir; + tgui->accel.pat_x += xdir; + if (tgui->type >= TGUI_9660) + tgui->accel.dx += xdir; + + tgui->accel.x++; + if (tgui->accel.x > tgui->accel.size_x) { + tgui->accel.x = 0; + + tgui->accel.pat_x = tgui->accel.dst_x; + tgui->accel.pat_y += ydir; + + if (tgui->type >= TGUI_9660) { + tgui->accel.dx = tgui->accel.dst_x & 0xfff; + tgui->accel.dy += ydir; + } + + tgui->accel.src_old += (ydir * tgui->accel.pitch); + tgui->accel.dst_old += (ydir * tgui->accel.pitch); + + tgui->accel.src = tgui->accel.src_old; + tgui->accel.dst = tgui->accel.dst_old; + + tgui->accel.y++; + + if (tgui->accel.y > tgui->accel.size_y) { + if (svga->crtc[0x21] & 0x20) + tgui->write_blitter = 0; + return; + } + if (tgui->accel.use_src) + return; + } + count--; + } + break; + + case TGUI_SRCMONO | TGUI_SRCCPU: + if (count == -1) { + if (svga->crtc[0x21] & 0x20) + tgui->write_blitter = 1; + if (tgui->accel.use_src) + return; + } + + while (count--) { + if ((tgui->type == TGUI_9440) || ((tgui->type >= TGUI_9660) && tgui->accel.dx >= tgui->accel.left && tgui->accel.dx <= tgui->accel.right && tgui->accel.dy >= tgui->accel.top && tgui->accel.dy <= tgui->accel.bottom)) { + src_dat = ((cpu_dat >> 31) ? tgui->accel.fg_col : tgui->accel.bg_col); + if (tgui->accel.bpp == 0) + src_dat &= 0xff; + else if (tgui->accel.bpp == 1) + src_dat &= 0xffff; + + READ(tgui->accel.dst, dst_dat); + + pat_dat = pattern_data[((tgui->accel.pat_y & 7) * 8) + (tgui->accel.pat_x & 7)]; + + if (tgui->accel.bpp == 0) + pat_dat &= 0xff; + else if (tgui->accel.bpp == 1) + pat_dat &= 0xffff; + + if (!(tgui->accel.flags & TGUI_TRANSENA) || (src_dat != trans_col)) { + MIX(); + + WRITE(tgui->accel.dst, out); + } + } + + cpu_dat <<= 1; + tgui->accel.src += xdir; + tgui->accel.dst += xdir; + tgui->accel.pat_x += xdir; + if (tgui->type >= TGUI_9660) + tgui->accel.dx += xdir; + + tgui->accel.x++; + if (tgui->accel.x > tgui->accel.size_x) { + tgui->accel.x = 0; + + tgui->accel.pat_x = tgui->accel.dst_x; + tgui->accel.pat_y += ydir; + + if (tgui->type >= TGUI_9660) { + tgui->accel.dx = tgui->accel.dst_x & 0xfff; + tgui->accel.dy += ydir; + } + + tgui->accel.src = tgui->accel.src_old = tgui->accel.src_old + (ydir * tgui->accel.pitch); + tgui->accel.dst = tgui->accel.dst_old = tgui->accel.dst_old + (ydir * tgui->accel.pitch); + + tgui->accel.y++; + + if (tgui->accel.y > tgui->accel.size_y) { + if (svga->crtc[0x21] & 0x20) + tgui->write_blitter = 0; + return; + } + if (tgui->accel.use_src) + return; + } + } + break; + + default: + while (count--) { + READ(tgui->accel.src, src_dat); + READ(tgui->accel.dst, dst_dat); + + pat_dat = pattern_data[((tgui->accel.pat_y & 7) * 8) + (tgui->accel.pat_x & 7)]; + + if (tgui->accel.bpp == 0) + pat_dat &= 0xff; + else if (tgui->accel.bpp == 1) + pat_dat &= 0xffff; + + if (!(tgui->accel.flags & TGUI_TRANSENA) || (src_dat != trans_col)) { + MIX(); + + WRITE(tgui->accel.dst, out); + } + + tgui->accel.src += xdir; + tgui->accel.dst += xdir; + tgui->accel.pat_x += xdir; + + tgui->accel.x++; + if (tgui->accel.x > tgui->accel.size_x) { + tgui->accel.x = 0; + tgui->accel.y++; + + tgui->accel.pat_x = tgui->accel.dst_x; + tgui->accel.pat_y += ydir; + + tgui->accel.src = tgui->accel.src_old = tgui->accel.src_old + (ydir * tgui->accel.pitch); + tgui->accel.dst = tgui->accel.dst_old = tgui->accel.dst_old + (ydir * tgui->accel.pitch); + + if (tgui->accel.y > tgui->accel.size_y) + return; + } + } + break; + } + break; + + case TGUI_SCANLINE: + if (count == -1) { + tgui->accel.src_old = tgui->accel.src_x + (tgui->accel.src_y * tgui->accel.pitch); + tgui->accel.src = tgui->accel.src_old; + + tgui->accel.dst_old = tgui->accel.dst_x + (tgui->accel.dst_y * tgui->accel.pitch); + tgui->accel.dst = tgui->accel.dst_old; + + tgui->accel.pat_x = tgui->accel.dst_x; + tgui->accel.pat_y = tgui->accel.dst_y; + } + + while (count--) { + READ(tgui->accel.src, src_dat); + READ(tgui->accel.dst, dst_dat); + + pat_dat = pattern_data[((tgui->accel.pat_y & 7) * 8) + (tgui->accel.pat_x & 7)]; + + if (tgui->accel.bpp == 0) + pat_dat &= 0xff; + else if (tgui->accel.bpp == 1) + pat_dat &= 0xffff; + + if (!(tgui->accel.flags & TGUI_TRANSENA) || (src_dat != trans_col)) { + MIX(); + + WRITE(tgui->accel.dst, out); + } + + tgui->accel.src += xdir; + tgui->accel.dst += xdir; + tgui->accel.pat_x += xdir; + + tgui->accel.x++; + if (tgui->accel.x > tgui->accel.size_x) { + tgui->accel.x = 0; + + tgui->accel.pat_x = tgui->accel.dst_x; + tgui->accel.src = tgui->accel.src_old = tgui->accel.src_old + (ydir * tgui->accel.pitch); + tgui->accel.dst = tgui->accel.dst_old = tgui->accel.dst_old + (ydir * tgui->accel.pitch); + tgui->accel.pat_y += ydir; + return; + } + } + break; + + case TGUI_BRESENHAMLINE: + if (count == -1) { + tgui->accel.dx = tgui->accel.dst_x & 0xfff; + tgui->accel.dy = tgui->accel.dst_y & 0xfff; + tgui->accel.y = tgui->accel.size_y; + + tgui->accel.left = tgui->accel.src_x_clip & 0xfff; + tgui->accel.right = tgui->accel.dst_x_clip & 0xfff; + tgui->accel.top = tgui->accel.src_y_clip & 0xfff; + tgui->accel.bottom = tgui->accel.dst_y_clip & 0xfff; + + if (tgui->accel.bpp == 1) { + tgui->accel.left >>= 1; + tgui->accel.right >>= 1; + } else if (tgui->accel.bpp == 3) { + tgui->accel.left >>= 2; + tgui->accel.right >>= 2; + } + } + + while (count--) { + /*Note by TC1995: I suppose the x/y clipping max is always more than 0 in the TGUI 96xx, but the TGUI 9440 lacks clipping*/ + if ((tgui->type == TGUI_9440) || ((tgui->type >= TGUI_9660) && ((tgui->accel.dx & 0xfff) >= tgui->accel.left) && ((tgui->accel.dx & 0xfff) <= tgui->accel.right) && ((tgui->accel.dy & 0xfff) >= tgui->accel.top) && ((tgui->accel.dy & 0xfff) <= tgui->accel.bottom))) { + READ(tgui->accel.dx + (tgui->accel.dy * tgui->accel.pitch), dst_dat); + + pat_dat = tgui->accel.fg_col; + + MIX(); + + WRITE(tgui->accel.dx + (tgui->accel.dy * tgui->accel.pitch), out); + } + + if (!tgui->accel.y) + break; + + if (tgui->accel.size_x >= 0) { + tgui->accel.size_x += tgui->accel.src_x; + /*Step minor axis*/ + switch ((tgui->accel.flags >> 8) & 7) { + case 0: + case 2: + tgui->accel.dy++; + break; + case 1: + case 3: + tgui->accel.dy--; + break; + case 4: + case 5: + tgui->accel.dx++; + break; + case 6: + case 7: + tgui->accel.dx--; + break; + + default: + break; + } + } else + tgui->accel.size_x += tgui->accel.src_y; + + /*Step major axis*/ + switch ((tgui->accel.flags >> 8) & 7) { + case 0: + case 1: + tgui->accel.dx++; + break; + case 2: + case 3: + tgui->accel.dx--; + break; + case 4: + case 6: + tgui->accel.dy++; + break; + case 5: + case 7: + tgui->accel.dy--; + break; + + default: + break; + } + + tgui->accel.y--; + tgui->accel.dx &= 0xfff; + tgui->accel.dy &= 0xfff; + } + break; + + case TGUI_SHORTVECTOR: + if (count == -1) { + tgui->accel.dx = tgui->accel.dst_x & 0xfff; + tgui->accel.dy = tgui->accel.dst_y & 0xfff; + tgui->accel.y = tgui->accel.sv_size_y & 0xfff; + + tgui->accel.left = tgui->accel.src_x_clip & 0xfff; + tgui->accel.right = tgui->accel.dst_x_clip & 0xfff; + tgui->accel.top = tgui->accel.src_y_clip & 0xfff; + tgui->accel.bottom = tgui->accel.dst_y_clip & 0xfff; + + if (tgui->accel.bpp == 1) { + tgui->accel.left >>= 1; + tgui->accel.right >>= 1; + } else if (tgui->accel.bpp == 3) { + tgui->accel.left >>= 2; + tgui->accel.right >>= 2; + } + } + + while (count--) { + /*Note by TC1995: I suppose the x/y clipping max is always more than 0 in the TGUI 96xx, but the TGUI 9440 lacks clipping*/ + if ((tgui->type == TGUI_9440) || ((tgui->type >= TGUI_9660) && ((tgui->accel.dx & 0xfff) >= tgui->accel.left) && ((tgui->accel.dx & 0xfff) <= tgui->accel.right) && ((tgui->accel.dy & 0xfff) >= tgui->accel.top) && ((tgui->accel.dy & 0xfff) <= tgui->accel.bottom))) { + READ(tgui->accel.dx + (tgui->accel.dy * tgui->accel.pitch), dst_dat); + + pat_dat = tgui->accel.fg_col; + + MIX(); + + WRITE(tgui->accel.dx + (tgui->accel.dy * tgui->accel.pitch), out); + } + + if (!tgui->accel.y) + break; + + switch ((tgui->accel.sv_size_y >> 8) & 0xe0) { + case 0x00: + tgui->accel.dx++; + break; + case 0x20: + tgui->accel.dx++; + tgui->accel.dy--; + break; + case 0x40: + tgui->accel.dy--; + break; + case 0x60: + tgui->accel.dx--; + tgui->accel.dy--; + break; + case 0x80: + tgui->accel.dx--; + break; + case 0xa0: + tgui->accel.dx--; + tgui->accel.dy++; + break; + case 0xc0: + tgui->accel.dy++; + break; + case 0xe0: + tgui->accel.dx++; + tgui->accel.dy++; + break; + + default: + break; + } + + tgui->accel.y--; + tgui->accel.dx &= 0xfff; + tgui->accel.dy &= 0xfff; + } + break; + + case TGUI_FASTLINE: + if (tgui->type < TGUI_9660) + break; + + if (count == -1) { + tgui->accel.dx = tgui->accel.dst_x & 0xfff; + tgui->accel.dy = tgui->accel.dst_y & 0xfff; + tgui->accel.y = tgui->accel.size_y; + + tgui->accel.left = tgui->accel.src_x_clip & 0xfff; + tgui->accel.right = tgui->accel.dst_x_clip & 0xfff; + tgui->accel.top = tgui->accel.src_y_clip & 0xfff; + tgui->accel.bottom = tgui->accel.dst_y_clip & 0xfff; + + if (tgui->accel.bpp == 1) { + tgui->accel.left >>= 1; + tgui->accel.right >>= 1; + } else if (tgui->accel.bpp == 3) { + tgui->accel.left >>= 2; + tgui->accel.right >>= 2; + } + } + + while (count--) { + /*Note by TC1995: I suppose the x/y clipping max is always more than 0 in the TGUI 96xx, but the TGUI 9440 lacks clipping*/ + if ((tgui->type == TGUI_9440) || ((tgui->type >= TGUI_9660) && ((tgui->accel.dx & 0xfff) >= tgui->accel.left) && ((tgui->accel.dx & 0xfff) <= tgui->accel.right) && ((tgui->accel.dy & 0xfff) >= tgui->accel.top) && ((tgui->accel.dy & 0xfff) <= tgui->accel.bottom))) { + READ(tgui->accel.dx + (tgui->accel.dy * tgui->accel.pitch), dst_dat); + + pat_dat = tgui->accel.fg_col; + + MIX(); + + WRITE(tgui->accel.dx + (tgui->accel.dy * tgui->accel.pitch), out); + } + + if (!tgui->accel.y) + break; + + switch ((tgui->accel.size_y >> 8) & 0xe0) { + case 0x00: + tgui->accel.dx++; + break; + case 0x20: + tgui->accel.dx++; + tgui->accel.dy--; + break; + case 0x40: + tgui->accel.dy--; + break; + case 0x60: + tgui->accel.dx--; + tgui->accel.dy--; + break; + case 0x80: + tgui->accel.dx--; + break; + case 0xa0: + tgui->accel.dx--; + tgui->accel.dy++; + break; + case 0xc0: + tgui->accel.dy++; + break; + case 0xe0: + tgui->accel.dx++; + tgui->accel.dy++; + break; + + default: + break; + } + + tgui->accel.y--; + tgui->accel.dx &= 0xfff; + tgui->accel.dy &= 0xfff; + } + break; + + default: + break; + } +} + +static void +tgui_accel_out(uint16_t addr, uint8_t val, void *priv) +{ + tgui_t *tgui = (tgui_t *) priv; svga_t *svga = &tgui->svga; - uint32_t *pattern_data; - int x, y; - int c, d; - uint32_t out; - uint32_t src_dat = 0, dst_dat, pat_dat; - int xdir = (tgui->accel.flags & 0x200) ? -1 : 1; - int ydir = (tgui->accel.flags & 0x100) ? -1 : 1; - uint32_t trans_col = (tgui->accel.flags & TGUI_TRANSREV) ? tgui->accel.fg_col : tgui->accel.bg_col; - uint16_t *vram_w = (uint16_t *)svga->vram; - uint32_t *vram_l = (uint32_t *)svga->vram; - if (tgui->accel.bpp == 0) { - trans_col &= 0xff; - } else if (tgui->accel.bpp == 1) { - trans_col &= 0xffff; - } + switch (addr) { + case 0x2122: + tgui->accel.ger22 = (tgui->accel.ger22 & 0xff00) | val; + switch (svga->bpp) { + case 8: + case 24: + tgui->accel.bpp = 0; + break; + case 15: + case 16: + tgui->accel.bpp = 1; + break; + case 32: + tgui->accel.bpp = 3; + break; - if (count != -1 && !tgui->accel.x && (tgui->accel.flags & TGUI_SRCMONO)) - { - count -= (tgui->accel.flags >> 24) & 7; - cpu_dat <<= (tgui->accel.flags >> 24) & 7; - } - - if (count == -1) - tgui->accel.x = tgui->accel.y = 0; - - if (tgui->accel.flags & TGUI_SOLIDFILL) { - for (y = 0; y < 8; y++) - { - for (x = 0; x < 8; x++) - { - tgui->accel.fill_pattern[(y*8) + (7 - x)] = tgui->accel.fg_col; - } - } - pattern_data = tgui->accel.fill_pattern; - } else if (tgui->accel.flags & TGUI_PATMONO) { - for (y = 0; y < 8; y++) - { - for (x = 0; x < 8; x++) - { - tgui->accel.mono_pattern[(y*8) + (7 - x)] = (tgui->accel.pattern[y] & (1 << x)) ? tgui->accel.fg_col : tgui->accel.bg_col; - } - } - pattern_data = tgui->accel.mono_pattern; - } else { - if (tgui->accel.bpp == 0) { - for (y = 0; y < 8; y++) - { - for (x = 0; x < 8; x++) - { - tgui->accel.pattern_8[(y*8) + (7 - x)] = tgui->accel.pattern[x + y*8]; - } - } - pattern_data = tgui->accel.pattern_8; - } else if (tgui->accel.bpp == 1) { - for (y = 0; y < 8; y++) - { - for (x = 0; x < 8; x++) - { - tgui->accel.pattern_16[(y*8) + (7 - x)] = tgui->accel.pattern[x*2 + y*16] | (tgui->accel.pattern[x*2 + y*16 + 1] << 8); - } - } - pattern_data = tgui->accel.pattern_16; - } else { - for (y = 0; y < 4; y++) - { - for (x = 0; x < 8; x++) - { - tgui->accel.pattern_32[(y*8) + (7 - x)] = tgui->accel.pattern[x*4 + y*32] | (tgui->accel.pattern[x*4 + y*32 + 1] << 8) | (tgui->accel.pattern[x*4 + y*32 + 2] << 16) | (tgui->accel.pattern[x*4 + y*32 + 3] << 24); - tgui->accel.pattern_32[((y+4)*8) + (7 - x)] = tgui->accel.pattern[x*4 + y*32] | (tgui->accel.pattern[x*4 + y*32 + 1] << 8) | (tgui->accel.pattern[x*4 + y*32 + 2] << 16) | (tgui->accel.pattern[x*4 + y*32 + 3] << 24); - } - } - pattern_data = tgui->accel.pattern_32; - } - } + default: + break; + } + break; - /*Other than mode stuff, this bit is undocumented*/ - switch (tgui->accel.ger22 & 0xff) { - case 0: - switch (tgui->accel.ger22 >> 8) { - case 0x41: - tgui->accel.pitch = 640; - break; - } - break; - - case 4: - switch (tgui->accel.ger22 >> 8) { - case 0: - tgui->accel.pitch = 1024; - break; - case 0x40: - tgui->accel.pitch = 640; - break; - case 0x50: - tgui->accel.pitch = 832; - break; - } - break; - case 8: - switch (tgui->accel.ger22 >> 8) { - case 0: - tgui->accel.pitch = 2048; - break; - case 0x60: - tgui->accel.pitch = 1280; - break; - } - break; - case 9: - switch (tgui->accel.ger22 >> 8) { - case 0: - tgui->accel.pitch = svga->hdisp; - if (tgui->type == TGUI_9440) - tgui->accel.pitch = 1024; - break; - case 0x40: - tgui->accel.pitch = 640; - break; - case 0x50: - tgui->accel.pitch = 832; - break; - } - break; - case 13: - switch (tgui->accel.ger22 >> 8) { - case 0x60: - tgui->accel.pitch = 2048; - if (tgui->type >= TGUI_9660) { - if (svga->hdisp == 1280) - tgui->accel.pitch = svga->hdisp; - } - break; - } - break; - case 14: - switch (tgui->accel.ger22 >> 8) { - case 0: - tgui->accel.pitch = 1024; - break; - case 0x40: - tgui->accel.pitch = 640; - break; - case 0x50: - tgui->accel.pitch = 832; - break; - } - break; - } + case 0x2123: + tgui->accel.ger22 = (tgui->accel.ger22 & 0xff) | (val << 8); + //pclog("Pitch IO23: val = %02x, rowoffset = %x.\n", tgui->accel.ger22, svga->crtc[0x13]); + switch (svga->bpp) { + case 8: + case 24: + tgui->accel.bpp = 0; + break; + case 15: + case 16: + tgui->accel.bpp = 1; + break; + case 32: + tgui->accel.bpp = 3; + break; + } + break; - switch (tgui->accel.command) - { - case TGUI_BITBLT: - if (count == -1) { - tgui->accel.src_old = tgui->accel.src_x + (tgui->accel.src_y * tgui->accel.pitch); - tgui->accel.src = tgui->accel.src_old; - - tgui->accel.dst_old = tgui->accel.dst_x + (tgui->accel.dst_y * tgui->accel.pitch); - tgui->accel.dst = tgui->accel.dst_old; - - tgui->accel.pat_x = tgui->accel.dst_x; - tgui->accel.pat_y = tgui->accel.dst_y; - - tgui->accel.dx = tgui->accel.dst_x & 0xfff; - tgui->accel.dy = tgui->accel.dst_y & 0xfff; - - tgui->accel.left = tgui->accel.src_x_clip & 0xfff; - tgui->accel.right = tgui->accel.dst_x_clip & 0xfff; - tgui->accel.top = tgui->accel.src_y_clip & 0xfff; - tgui->accel.bottom = tgui->accel.dst_y_clip & 0xfff; - - if (tgui->accel.bpp == 1) { - tgui->accel.left >>= 1; - tgui->accel.right >>= 1; - } else if (tgui->accel.bpp == 3) { - tgui->accel.left >>= 2; - tgui->accel.right >>= 2; - } - } - - switch (tgui->accel.flags & (TGUI_SRCMONO|TGUI_SRCDISP)) - { - case TGUI_SRCCPU: - if (count == -1) { - if (svga->crtc[0x21] & 0x20) - tgui->write_blitter = 1; - if (tgui->accel.use_src) - return; - } else - count >>= 3; + case 0x2124: /*Command*/ + tgui->accel.command = val; + tgui_accel_command(-1, 0, tgui); + break; - while (count) { - if ((tgui->type == TGUI_9440) || ((tgui->type >= TGUI_9660) && tgui->accel.dx >= tgui->accel.left && tgui->accel.dx <= tgui->accel.right && - tgui->accel.dy >= tgui->accel.top && tgui->accel.dy <= tgui->accel.bottom)) { - if (tgui->accel.bpp == 0) { - src_dat = cpu_dat >> 24; - cpu_dat <<= 8; - } else if (tgui->accel.bpp == 1) { - src_dat = (cpu_dat >> 24) | ((cpu_dat >> 8) & 0xff00); - cpu_dat <<= 16; - count--; - } else { - src_dat = (cpu_dat >> 24) | ((cpu_dat >> 8) & 0x0000ff00) | ((cpu_dat << 8) & 0x00ff0000); - cpu_dat <<= 16; - count -= 3; - } - - READ(tgui->accel.dst, dst_dat); + case 0x2127: /*ROP*/ + tgui->accel.rop = val; + tgui->accel.use_src = (val & 0x33) ^ ((val >> 2) & 0x33); + break; - pat_dat = pattern_data[((tgui->accel.pat_y & 7)*8) + (tgui->accel.pat_x & 7)]; - - if (tgui->accel.bpp == 0) - pat_dat &= 0xff; - else if (tgui->accel.bpp == 1) - pat_dat &= 0xffff; - - if ((((tgui->accel.flags & (TGUI_PATMONO|TGUI_TRANSENA)) == (TGUI_TRANSENA|TGUI_PATMONO)) && (pat_dat != trans_col)) || !(tgui->accel.flags & TGUI_PATMONO) || - ((tgui->accel.flags & (TGUI_PATMONO|TGUI_TRANSENA)) == TGUI_PATMONO) || (tgui->accel.ger22 & 0x200)) { - MIX(); + case 0x2128: /*Flags*/ + tgui->accel.flags = (tgui->accel.flags & 0xffffff00) | val; + break; + case 0x2129: /*Flags*/ + tgui->accel.flags = (tgui->accel.flags & 0xffff00ff) | (val << 8); + break; + case 0x212a: /*Flags*/ + tgui->accel.flags = (tgui->accel.flags & 0xff00ffff) | (val << 16); + break; + case 0x212b: /*Flags*/ + tgui->accel.flags = (tgui->accel.flags & 0x0000ffff) | (val << 24); + break; - WRITE(tgui->accel.dst, out); - } - } + case 0x212c: /*Foreground colour*/ + case 0x2178: + tgui->accel.fg_col = (tgui->accel.fg_col & 0xffffff00) | val; + break; + case 0x212d: /*Foreground colour*/ + case 0x2179: + tgui->accel.fg_col = (tgui->accel.fg_col & 0xffff00ff) | (val << 8); + break; + case 0x212e: /*Foreground colour*/ + case 0x217a: + tgui->accel.fg_col = (tgui->accel.fg_col & 0xff00ffff) | (val << 16); + break; + case 0x212f: /*Foreground colour*/ + case 0x217b: + tgui->accel.fg_col = (tgui->accel.fg_col & 0x00ffffff) | (val << 24); + break; - tgui->accel.src += xdir; - tgui->accel.dst += xdir; - tgui->accel.pat_x += xdir; - if (tgui->type >= TGUI_9660) - tgui->accel.dx += xdir; - - tgui->accel.x++; - if (tgui->accel.x > tgui->accel.size_x) { - tgui->accel.x = 0; - - tgui->accel.pat_x = tgui->accel.dst_x; - tgui->accel.pat_y += ydir; - - if (tgui->type >= TGUI_9660) { - tgui->accel.dx = tgui->accel.dst_x & 0xfff; - tgui->accel.dy += ydir; - } + case 0x2130: /*Background colour*/ + case 0x217c: + tgui->accel.bg_col = (tgui->accel.bg_col & 0xffffff00) | val; + break; + case 0x2131: /*Background colour*/ + case 0x217d: + tgui->accel.bg_col = (tgui->accel.bg_col & 0xffff00ff) | (val << 8); + break; + case 0x2132: /*Background colour*/ + case 0x217e: + tgui->accel.bg_col = (tgui->accel.bg_col & 0xff00ffff) | (val << 16); + break; + case 0x2133: /*Background colour*/ + case 0x217f: + tgui->accel.bg_col = (tgui->accel.bg_col & 0x00ffffff) | (val << 24); + break; - tgui->accel.src_old += (ydir * tgui->accel.pitch); - tgui->accel.dst_old += (ydir * tgui->accel.pitch); - - tgui->accel.src = tgui->accel.src_old; - tgui->accel.dst = tgui->accel.dst_old; - - tgui->accel.y++; - - if (tgui->accel.y > tgui->accel.size_y) { - if (svga->crtc[0x21] & 0x20) - tgui->write_blitter = 0; - return; - } - if (tgui->accel.use_src) - return; - } - count--; - } - break; - - case TGUI_SRCMONO | TGUI_SRCCPU: - if (count == -1) { - if (svga->crtc[0x21] & 0x20) - tgui->write_blitter = 1; - if (tgui->accel.use_src) - return; - } + case 0x2134: /*Pattern location*/ + tgui->accel.patloc = (tgui->accel.patloc & 0xff00) | val; + break; + case 0x2135: /*Pattern location*/ + tgui->accel.patloc = (tgui->accel.patloc & 0xff) | (val << 8); + break; - while (count--) { - if ((tgui->type == TGUI_9440) || ((tgui->type >= TGUI_9660) && tgui->accel.dx >= tgui->accel.left && tgui->accel.dx <= tgui->accel.right && - tgui->accel.dy >= tgui->accel.top && tgui->accel.dy <= tgui->accel.bottom)) { - src_dat = ((cpu_dat >> 31) ? tgui->accel.fg_col : tgui->accel.bg_col); - if (tgui->accel.bpp == 0) - src_dat &= 0xff; - else if (tgui->accel.bpp == 1) - src_dat &= 0xffff; + case 0x2138: /*Dest X*/ + tgui->accel.dst_x = (tgui->accel.dst_x & 0xff00) | val; + break; + case 0x2139: /*Dest X*/ + tgui->accel.dst_x = (tgui->accel.dst_x & 0xff) | (val << 8); + break; + case 0x213a: /*Dest Y*/ + tgui->accel.dst_y = (tgui->accel.dst_y & 0xff00) | val; + break; + case 0x213b: /*Dest Y*/ + tgui->accel.dst_y = (tgui->accel.dst_y & 0xff) | (val << 8); + break; - READ(tgui->accel.dst, dst_dat); + case 0x213c: /*Src X, Diagonal Step Constant*/ + tgui->accel.src_x = (tgui->accel.src_x & 0x3f00) | val; + break; + case 0x213d: /*Src X, Diagonal Step Constant*/ + tgui->accel.src_x = (tgui->accel.src_x & 0xff) | ((val & 0x3f) << 8); + if (val & 0x20) + tgui->accel.src_x |= ~0x3fff; + break; + case 0x213e: /*Src Y, Axial Step Constant*/ + tgui->accel.src_y = (tgui->accel.src_y & 0x3f00) | val; + break; + case 0x213f: /*Src Y, Axial Step Constant*/ + tgui->accel.src_y = (tgui->accel.src_y & 0xff) | ((val & 0x3f) << 8); + if (val & 0x20) + tgui->accel.src_y |= ~0x3fff; + break; - pat_dat = pattern_data[((tgui->accel.pat_y & 7)*8) + (tgui->accel.pat_x & 7)]; + case 0x2140: /*Size X, Line Error Term*/ + tgui->accel.size_x = (tgui->accel.size_x & 0x3f00) | val; + break; + case 0x2141: /*Size X, Line Error Term*/ + tgui->accel.size_x = (tgui->accel.size_x & 0xff) | ((val & 0x3f) << 8); + if (val & 0x20) + tgui->accel.size_x |= ~0x1fff; + break; + case 0x2142: /*Size Y, Major Axis Pixel Count*/ + tgui->accel.size_y = (tgui->accel.size_y & 0xf00) | val; + tgui->accel.sv_size_y = (tgui->accel.sv_size_y & 0xff00) | val; + break; + case 0x2143: /*Size Y, Major Axis Pixel Count*/ + tgui->accel.size_y = (tgui->accel.size_y & 0xff) | ((val & 0x0f) << 8); + tgui->accel.sv_size_y = (tgui->accel.sv_size_y & 0xff) | (val << 8); + break; - if (tgui->accel.bpp == 0) - pat_dat &= 0xff; - else if (tgui->accel.bpp == 1) - pat_dat &= 0xffff; + case 0x2144: /*Style*/ + tgui->accel.style = (tgui->accel.style & 0xffffff00) | val; + break; + case 0x2145: /*Style*/ + tgui->accel.style = (tgui->accel.style & 0xffff00ff) | (val << 8); + break; + case 0x2146: /*Style*/ + tgui->accel.style = (tgui->accel.style & 0xff00ffff) | (val << 16); + break; + case 0x2147: /*Style*/ + tgui->accel.style = (tgui->accel.style & 0x00ffffff) | (val << 24); + break; - if (!(tgui->accel.flags & TGUI_TRANSENA) || (src_dat != trans_col)) { - MIX(); + case 0x2148: /*Clip Src X*/ + tgui->accel.src_x_clip = (tgui->accel.src_x_clip & 0xff00) | val; + break; + case 0x2149: /*Clip Src X*/ + tgui->accel.src_x_clip = (tgui->accel.src_x_clip & 0xff) | (val << 8); + break; + case 0x214a: /*Clip Src Y*/ + tgui->accel.src_y_clip = (tgui->accel.src_y_clip & 0xff00) | val; + break; + case 0x214b: /*Clip Src Y*/ + tgui->accel.src_y_clip = (tgui->accel.src_y_clip & 0xff) | (val << 8); + break; - WRITE(tgui->accel.dst, out); - } - } + case 0x214c: /*Clip Dest X*/ + tgui->accel.dst_x_clip = (tgui->accel.dst_x_clip & 0xff00) | val; + break; + case 0x214d: /*Clip Dest X*/ + tgui->accel.dst_x_clip = (tgui->accel.dst_x_clip & 0xff) | (val << 8); + break; + case 0x214e: /*Clip Dest Y*/ + tgui->accel.dst_y_clip = (tgui->accel.dst_y_clip & 0xff00) | val; + break; + case 0x214f: /*Clip Dest Y*/ + tgui->accel.dst_y_clip = (tgui->accel.dst_y_clip & 0xff) | (val << 8); + break; - cpu_dat <<= 1; - tgui->accel.src += xdir; - tgui->accel.dst += xdir; - tgui->accel.pat_x += xdir; - if (tgui->type >= TGUI_9660) - tgui->accel.dx += xdir; - - tgui->accel.x++; - if (tgui->accel.x > tgui->accel.size_x) { - tgui->accel.x = 0; + case 0x2168: /*CKey*/ + tgui->accel.ckey = (tgui->accel.ckey & 0xffffff00) | val; + break; + case 0x2169: /*CKey*/ + tgui->accel.ckey = (tgui->accel.ckey & 0xffff00ff) | (val << 8); + break; + case 0x216a: /*CKey*/ + tgui->accel.ckey = (tgui->accel.ckey & 0xff00ffff) | (val << 16); + break; + case 0x216b: /*CKey*/ + tgui->accel.ckey = (tgui->accel.ckey & 0x00ffffff) | (val << 24); + break; - tgui->accel.pat_x = tgui->accel.dst_x; - tgui->accel.pat_y += ydir; + case 0x2180: + case 0x2181: + case 0x2182: + case 0x2183: + case 0x2184: + case 0x2185: + case 0x2186: + case 0x2187: + case 0x2188: + case 0x2189: + case 0x218a: + case 0x218b: + case 0x218c: + case 0x218d: + case 0x218e: + case 0x218f: + case 0x2190: + case 0x2191: + case 0x2192: + case 0x2193: + case 0x2194: + case 0x2195: + case 0x2196: + case 0x2197: + case 0x2198: + case 0x2199: + case 0x219a: + case 0x219b: + case 0x219c: + case 0x219d: + case 0x219e: + case 0x219f: + case 0x21a0: + case 0x21a1: + case 0x21a2: + case 0x21a3: + case 0x21a4: + case 0x21a5: + case 0x21a6: + case 0x21a7: + case 0x21a8: + case 0x21a9: + case 0x21aa: + case 0x21ab: + case 0x21ac: + case 0x21ad: + case 0x21ae: + case 0x21af: + case 0x21b0: + case 0x21b1: + case 0x21b2: + case 0x21b3: + case 0x21b4: + case 0x21b5: + case 0x21b6: + case 0x21b7: + case 0x21b8: + case 0x21b9: + case 0x21ba: + case 0x21bb: + case 0x21bc: + case 0x21bd: + case 0x21be: + case 0x21bf: + case 0x21c0: + case 0x21c1: + case 0x21c2: + case 0x21c3: + case 0x21c4: + case 0x21c5: + case 0x21c6: + case 0x21c7: + case 0x21c8: + case 0x21c9: + case 0x21ca: + case 0x21cb: + case 0x21cc: + case 0x21cd: + case 0x21ce: + case 0x21cf: + case 0x21d0: + case 0x21d1: + case 0x21d2: + case 0x21d3: + case 0x21d4: + case 0x21d5: + case 0x21d6: + case 0x21d7: + case 0x21d8: + case 0x21d9: + case 0x21da: + case 0x21db: + case 0x21dc: + case 0x21dd: + case 0x21de: + case 0x21df: + case 0x21e0: + case 0x21e1: + case 0x21e2: + case 0x21e3: + case 0x21e4: + case 0x21e5: + case 0x21e6: + case 0x21e7: + case 0x21e8: + case 0x21e9: + case 0x21ea: + case 0x21eb: + case 0x21ec: + case 0x21ed: + case 0x21ee: + case 0x21ef: + case 0x21f0: + case 0x21f1: + case 0x21f2: + case 0x21f3: + case 0x21f4: + case 0x21f5: + case 0x21f6: + case 0x21f7: + case 0x21f8: + case 0x21f9: + case 0x21fa: + case 0x21fb: + case 0x21fc: + case 0x21fd: + case 0x21fe: + case 0x21ff: + tgui->accel.pattern[addr & 0x7f] = val; + break; - if (tgui->type >= TGUI_9660) { - tgui->accel.dx = tgui->accel.dst_x & 0xfff; - tgui->accel.dy += ydir; - } - - tgui->accel.src = tgui->accel.src_old = tgui->accel.src_old + (ydir * tgui->accel.pitch); - tgui->accel.dst = tgui->accel.dst_old = tgui->accel.dst_old + (ydir * tgui->accel.pitch); - - tgui->accel.y++; - - if (tgui->accel.y > tgui->accel.size_y) { - if (svga->crtc[0x21] & 0x20) - tgui->write_blitter = 0; - return; - } - if (tgui->accel.use_src) - return; - } - } - break; - - default: - while (count--) { - READ(tgui->accel.src, src_dat); - READ(tgui->accel.dst, dst_dat); - - pat_dat = pattern_data[((tgui->accel.pat_y & 7)*8) + (tgui->accel.pat_x & 7)]; - - if (tgui->accel.bpp == 0) - pat_dat &= 0xff; - else if (tgui->accel.bpp == 1) - pat_dat &= 0xffff; - - if (!(tgui->accel.flags & TGUI_TRANSENA) || (src_dat != trans_col)) { - MIX(); - - WRITE(tgui->accel.dst, out); - } - - tgui->accel.src += xdir; - tgui->accel.dst += xdir; - tgui->accel.pat_x += xdir; - - tgui->accel.x++; - if (tgui->accel.x > tgui->accel.size_x) - { - tgui->accel.x = 0; - tgui->accel.y++; - - tgui->accel.pat_x = tgui->accel.dst_x; - tgui->accel.pat_y += ydir; - - tgui->accel.src = tgui->accel.src_old = tgui->accel.src_old + (ydir * tgui->accel.pitch); - tgui->accel.dst = tgui->accel.dst_old = tgui->accel.dst_old + (ydir * tgui->accel.pitch); - - if (tgui->accel.y > tgui->accel.size_y) - return; - } - } - break; - } - break; - - case TGUI_SCANLINE: - { - if (count == -1) { - tgui->accel.src_old = tgui->accel.src_x + (tgui->accel.src_y * tgui->accel.pitch); - tgui->accel.src = tgui->accel.src_old; - - tgui->accel.dst_old = tgui->accel.dst_x + (tgui->accel.dst_y * tgui->accel.pitch); - tgui->accel.dst = tgui->accel.dst_old; - - tgui->accel.pat_x = tgui->accel.dst_x; - tgui->accel.pat_y = tgui->accel.dst_y; - } - - while (count--) { - READ(tgui->accel.src, src_dat); - READ(tgui->accel.dst, dst_dat); - - pat_dat = pattern_data[((tgui->accel.pat_y & 7)*8) + (tgui->accel.pat_x & 7)]; - - if (tgui->accel.bpp == 0) - pat_dat &= 0xff; - else if (tgui->accel.bpp == 1) - pat_dat &= 0xffff; - - if (!(tgui->accel.flags & TGUI_TRANSENA) || (src_dat != trans_col)) { - MIX(); - - WRITE(tgui->accel.dst, out); - } - - tgui->accel.src += xdir; - tgui->accel.dst += xdir; - tgui->accel.pat_x += xdir; - - tgui->accel.x++; - if (tgui->accel.x > tgui->accel.size_x) - { - tgui->accel.x = 0; - - tgui->accel.pat_x = tgui->accel.dst_x; - tgui->accel.src = tgui->accel.src_old = tgui->accel.src_old + (ydir * tgui->accel.pitch); - tgui->accel.dst = tgui->accel.dst_old = tgui->accel.dst_old + (ydir * tgui->accel.pitch); - tgui->accel.pat_y += ydir; - return; - } - } - } - break; - - case TGUI_BRESENHAMLINE: - { - int steep = 1; - int16_t dminor, dmajor, destxtmp, tmpswap; - int16_t cx, cy, dx, dy, err; - -#define SWAP(a,b) tmpswap = a; a = b; b = tmpswap; - - dminor = tgui->accel.src_y; - if (tgui->accel.src_y & 0x1000) - dminor |= ~0xfff; - dminor >>= 1; - - destxtmp = tgui->accel.src_x; - if (tgui->accel.src_x & 0x1000) - destxtmp |= ~0xfff; - - dmajor = -(destxtmp - (dminor << 1)) >> 1; - - cx = dmajor; - cy = dminor; - - dx = tgui->accel.dst_x & 0xfff; - dy = tgui->accel.dst_y & 0xfff; - - tgui->accel.left = tgui->accel.src_x_clip & 0xfff; - tgui->accel.right = tgui->accel.dst_x_clip & 0xfff; - tgui->accel.top = tgui->accel.src_y_clip & 0xfff; - tgui->accel.bottom = tgui->accel.dst_y_clip & 0xfff; - - if (tgui->accel.bpp == 1) { - tgui->accel.left >>= 1; - tgui->accel.right >>= 1; - } else if (tgui->accel.bpp == 3) { - tgui->accel.left >>= 2; - tgui->accel.right >>= 2; - } - - err = tgui->accel.size_x + tgui->accel.src_y; - if ((tgui->accel.size_x + tgui->accel.src_y) & 0x1000) - err |= ~0xfff; - - if (tgui->accel.flags & 0x400) { - steep = 0; - SWAP(dx, dy); - SWAP(xdir, ydir); - } - - while (count--) { - READ(tgui->accel.src_x + (tgui->accel.src_y * tgui->accel.pitch), src_dat); - - /*Note by TC1995: I suppose the x/y clipping max is always more than 0 in the TGUI 96xx, but the TGUI 9440 lacks clipping*/ - if (steep) { - if ((tgui->type == TGUI_9440) || ((tgui->type >= TGUI_9660) && dx >= tgui->accel.left && dx <= tgui->accel.right && - dy >= tgui->accel.top && dy <= tgui->accel.bottom)) { - READ(dx + (dy * tgui->accel.pitch), dst_dat); - - pat_dat = tgui->accel.fg_col; - - if (tgui->accel.bpp == 0) - pat_dat &= 0xff; - else if (tgui->accel.bpp == 1) - pat_dat &= 0xffff; - - MIX(); - - WRITE(dx + (dy * tgui->accel.pitch), out); - } - } else { - if ((tgui->type == TGUI_9440) || ((tgui->type >= TGUI_9660) && dy >= tgui->accel.left && dy <= tgui->accel.right && - dx >= tgui->accel.top && dx <= tgui->accel.bottom)) { - READ(dy + (dx * tgui->accel.pitch), dst_dat); - - pat_dat = tgui->accel.fg_col; - - if (tgui->accel.bpp == 0) - pat_dat &= 0xff; - else if (tgui->accel.bpp == 1) - pat_dat &= 0xffff; - - MIX(); - - WRITE(dy + (dx * tgui->accel.pitch), out); - } - } - - if (tgui->accel.y == tgui->accel.size_y) - break; - - while (err > 0) { - dy += ydir; - err -= (cx << 1); - } - dx += xdir; - err += (cy << 1); - - tgui->accel.y++; - } - } - break; - - case TGUI_SHORTVECTOR: - { - int16_t dx, dy; - - dx = tgui->accel.dst_x & 0xfff; - dy = tgui->accel.dst_y & 0xfff; - - tgui->accel.left = tgui->accel.src_x_clip & 0xfff; - tgui->accel.right = tgui->accel.dst_x_clip & 0xfff; - tgui->accel.top = tgui->accel.src_y_clip & 0xfff; - tgui->accel.bottom = tgui->accel.dst_y_clip & 0xfff; - - if (tgui->accel.bpp == 1) { - tgui->accel.left >>= 1; - tgui->accel.right >>= 1; - } else if (tgui->accel.bpp == 3) { - tgui->accel.left >>= 2; - tgui->accel.right >>= 2; - } - - while (count--) { - READ(tgui->accel.src_x + (tgui->accel.src_y * tgui->accel.pitch), src_dat); - - /*Note by TC1995: I suppose the x/y clipping max is always more than 0 in the TGUI 96xx, but the TGUI 9440 lacks clipping*/ - if ((tgui->type == TGUI_9440) || ((tgui->type >= TGUI_9660) && dx >= tgui->accel.left && dx <= tgui->accel.right && - dy >= tgui->accel.top && dy <= tgui->accel.bottom)) { - READ(dx + (dy * tgui->accel.pitch), dst_dat); - - pat_dat = tgui->accel.fg_col; - - if (tgui->accel.bpp == 0) - pat_dat &= 0xff; - else if (tgui->accel.bpp == 1) - pat_dat &= 0xffff; - - MIX(); - - WRITE(dx + (dy * tgui->accel.pitch), out); - } - - if (tgui->accel.y == (tgui->accel.sv_size_y & 0xfff)) - break; - - switch ((tgui->accel.sv_size_y >> 8) & 0xe0) { - case 0x00: - dx++; - break; - case 0x20: - dx++; - dy--; - break; - case 0x40: - dy--; - break; - case 0x60: - dx--; - dy--; - break; - case 0x80: - dx--; - break; - case 0xa0: - dx--; - dy++; - break; - case 0xc0: - dy++; - break; - case 0xe0: - dx++; - dy++; - break; - } - - tgui->accel.y++; - } - } - break; - - case TGUI_FASTLINE: - { - if (tgui->type < TGUI_9660) - break; - - int16_t dx, dy; - - dx = tgui->accel.dst_x & 0xfff; - dy = tgui->accel.dst_y & 0xfff; - - tgui->accel.left = tgui->accel.src_x_clip & 0xfff; - tgui->accel.right = tgui->accel.dst_x_clip & 0xfff; - tgui->accel.top = tgui->accel.src_y_clip & 0xfff; - tgui->accel.bottom = tgui->accel.dst_y_clip & 0xfff; - - if (tgui->accel.bpp == 1) { - tgui->accel.left >>= 1; - tgui->accel.right >>= 1; - } else if (tgui->accel.bpp == 3) { - tgui->accel.left >>= 2; - tgui->accel.right >>= 2; - } - - while (count--) { - READ(tgui->accel.src_x + (tgui->accel.src_y * tgui->accel.pitch), src_dat); - - /*Note by TC1995: I suppose the x/y clipping max is always more than 0 in the TGUI 96xx, but the TGUI 9440 lacks clipping*/ - if ((tgui->type == TGUI_9440) || ((tgui->type >= TGUI_9660) && dx >= tgui->accel.left && dx <= tgui->accel.right && - dy >= tgui->accel.top && dy <= tgui->accel.bottom)) { - READ(dx + (dy * tgui->accel.pitch), dst_dat); - - pat_dat = tgui->accel.fg_col; - - if (tgui->accel.bpp == 0) - pat_dat &= 0xff; - else if (tgui->accel.bpp == 1) - pat_dat &= 0xffff; - - MIX(); - - WRITE(dx + (dy * tgui->accel.pitch), out); - } - - if (tgui->accel.y == (tgui->accel.size_y & 0xfff)) - break; - - switch ((tgui->accel.size_y >> 8) & 0xe0) { - case 0x00: - dx++; - break; - case 0x20: - dx++; - dy--; - break; - case 0x40: - dy--; - break; - case 0x60: - dx--; - dy--; - break; - case 0x80: - dx--; - break; - case 0xa0: - dx--; - dy++; - break; - case 0xc0: - dy++; - break; - case 0xe0: - dx++; - dy++; - break; - } - - tgui->accel.y++; - } - } - break; - } + default: + break; + } } static void -tgui_accel_out(uint16_t addr, uint8_t val, void *p) +tgui_accel_out_w(uint16_t addr, uint16_t val, void *priv) { - tgui_t *tgui = (tgui_t *)p; - - switch (addr) - { - case 0x2122: - tgui->accel.ger22 = (tgui->accel.ger22 & 0xff00) | val; - switch (val & 0xff) { - case 4: - case 8: - tgui->accel.bpp = 0; - break; - - case 9: - tgui->accel.bpp = 1; - break; - - case 13: - case 14: - switch (tgui->svga.bpp) { - case 15: - case 16: - tgui->accel.bpp = 1; - break; - - case 24: - tgui->accel.bpp = 0; - break; - - case 32: - tgui->accel.bpp = 3; - break; - } - break; - } - break; - - case 0x2123: - tgui->accel.ger22 = (tgui->accel.ger22 & 0xff) | (val << 8); - break; - - case 0x2124: /*Command*/ - tgui->accel.command = val; - tgui_accel_command(-1, 0, tgui); - break; - - case 0x2127: /*ROP*/ - tgui->accel.rop = val; - tgui->accel.use_src = (val & 0x33) ^ ((val >> 2) & 0x33); - break; - - case 0x2128: /*Flags*/ - tgui->accel.flags = (tgui->accel.flags & 0xffffff00) | val; - break; - case 0x2129: /*Flags*/ - tgui->accel.flags = (tgui->accel.flags & 0xffff00ff) | (val << 8); - break; - case 0x212a: /*Flags*/ - tgui->accel.flags = (tgui->accel.flags & 0xff00ffff) | (val << 16); - break; - case 0x212b: /*Flags*/ - tgui->accel.flags = (tgui->accel.flags & 0x0000ffff) | (val << 24); - break; - - case 0x212c: /*Foreground colour*/ - case 0x2178: - tgui->accel.fg_col = (tgui->accel.fg_col & 0xffffff00) | val; - break; - case 0x212d: /*Foreground colour*/ - case 0x2179: - tgui->accel.fg_col = (tgui->accel.fg_col & 0xffff00ff) | (val << 8); - break; - case 0x212e: /*Foreground colour*/ - case 0x217a: - tgui->accel.fg_col = (tgui->accel.fg_col & 0xff00ffff) | (val << 16); - break; - case 0x212f: /*Foreground colour*/ - case 0x217b: - tgui->accel.fg_col = (tgui->accel.fg_col & 0x00ffffff) | (val << 24); - break; - - case 0x2130: /*Background colour*/ - case 0x217c: - tgui->accel.bg_col = (tgui->accel.bg_col & 0xffffff00) | val; - break; - case 0x2131: /*Background colour*/ - case 0x217d: - tgui->accel.bg_col = (tgui->accel.bg_col & 0xffff00ff) | (val << 8); - break; - case 0x2132: /*Background colour*/ - case 0x217e: - tgui->accel.bg_col = (tgui->accel.bg_col & 0xff00ffff) | (val << 16); - break; - case 0x2133: /*Background colour*/ - case 0x217f: - tgui->accel.bg_col = (tgui->accel.bg_col & 0x00ffffff) | (val << 24); - break; - - case 0x2134: /*Pattern location*/ - tgui->accel.patloc = (tgui->accel.patloc & 0xff00) | val; - break; - case 0x2135: /*Pattern location*/ - tgui->accel.patloc = (tgui->accel.patloc & 0xff) | (val << 8); - break; - - case 0x2138: /*Dest X*/ - tgui->accel.dst_x = (tgui->accel.dst_x & 0xff00) | val; - break; - case 0x2139: /*Dest X*/ - tgui->accel.dst_x = (tgui->accel.dst_x & 0xff) | (val << 8); - break; - case 0x213a: /*Dest Y*/ - tgui->accel.dst_y = (tgui->accel.dst_y & 0xff00) | val; - break; - case 0x213b: /*Dest Y*/ - tgui->accel.dst_y = (tgui->accel.dst_y & 0xff) | (val << 8); - break; - - case 0x213c: /*Src X*/ - tgui->accel.src_x = (tgui->accel.src_x & 0xff00) | val; - break; - case 0x213d: /*Src X*/ - tgui->accel.src_x = (tgui->accel.src_x & 0xff) | (val << 8); - break; - case 0x213e: /*Src Y*/ - tgui->accel.src_y = (tgui->accel.src_y & 0xff00) | val; - break; - case 0x213f: /*Src Y*/ - tgui->accel.src_y = (tgui->accel.src_y & 0xff) | (val << 8); - break; - - case 0x2140: /*Size X*/ - tgui->accel.size_x = (tgui->accel.size_x & 0xff00) | val; - break; - case 0x2141: /*Size X*/ - tgui->accel.size_x = (tgui->accel.size_x & 0xff) | (val << 8); - break; - case 0x2142: /*Size Y*/ - tgui->accel.size_y = (tgui->accel.size_y & 0xff00) | val; - tgui->accel.sv_size_y = (tgui->accel.sv_size_y & 0xff00) | val; - break; - case 0x2143: /*Size Y*/ - tgui->accel.size_y = (tgui->accel.size_y & 0xff) | (val << 8); - tgui->accel.sv_size_y = (tgui->accel.sv_size_y & 0xff) | (val << 8); - break; - - case 0x2144: /*Style*/ - tgui->accel.style = (tgui->accel.style & 0xffffff00) | val; - break; - case 0x2145: /*Style*/ - tgui->accel.style = (tgui->accel.style & 0xffff00ff) | (val << 8); - break; - case 0x2146: /*Style*/ - tgui->accel.style = (tgui->accel.style & 0xff00ffff) | (val << 16); - break; - case 0x2147: /*Style*/ - tgui->accel.style = (tgui->accel.style & 0x00ffffff) | (val << 24); - break; - - case 0x2148: /*Clip Src X*/ - tgui->accel.src_x_clip = (tgui->accel.src_x_clip & 0xff00) | val; - break; - case 0x2149: /*Clip Src X*/ - tgui->accel.src_x_clip = (tgui->accel.src_x_clip & 0xff) | (val << 8); - break; - case 0x214a: /*Clip Src Y*/ - tgui->accel.src_y_clip = (tgui->accel.src_y_clip & 0xff00) | val; - break; - case 0x214b: /*Clip Src Y*/ - tgui->accel.src_y_clip = (tgui->accel.src_y_clip & 0xff) | (val << 8); - break; - - case 0x214c: /*Clip Dest X*/ - tgui->accel.dst_x_clip = (tgui->accel.dst_x_clip & 0xff00) | val; - break; - case 0x214d: /*Clip Dest X*/ - tgui->accel.dst_x_clip = (tgui->accel.dst_x_clip & 0xff) | (val << 8); - break; - case 0x214e: /*Clip Dest Y*/ - tgui->accel.dst_y_clip = (tgui->accel.dst_y_clip & 0xff00) | val; - break; - case 0x214f: /*Clip Dest Y*/ - tgui->accel.dst_y_clip = (tgui->accel.dst_y_clip & 0xff) | (val << 8); - break; - - case 0x2168: /*CKey*/ - tgui->accel.ckey = (tgui->accel.ckey & 0xffffff00) | val; - break; - case 0x2169: /*CKey*/ - tgui->accel.ckey = (tgui->accel.ckey & 0xffff00ff) | (val << 8); - break; - case 0x216a: /*CKey*/ - tgui->accel.ckey = (tgui->accel.ckey & 0xff00ffff) | (val << 16); - break; - case 0x216b: /*CKey*/ - tgui->accel.ckey = (tgui->accel.ckey & 0x00ffffff) | (val << 24); - break; - - case 0x2180: case 0x2181: case 0x2182: case 0x2183: - case 0x2184: case 0x2185: case 0x2186: case 0x2187: - case 0x2188: case 0x2189: case 0x218a: case 0x218b: - case 0x218c: case 0x218d: case 0x218e: case 0x218f: - case 0x2190: case 0x2191: case 0x2192: case 0x2193: - case 0x2194: case 0x2195: case 0x2196: case 0x2197: - case 0x2198: case 0x2199: case 0x219a: case 0x219b: - case 0x219c: case 0x219d: case 0x219e: case 0x219f: - case 0x21a0: case 0x21a1: case 0x21a2: case 0x21a3: - case 0x21a4: case 0x21a5: case 0x21a6: case 0x21a7: - case 0x21a8: case 0x21a9: case 0x21aa: case 0x21ab: - case 0x21ac: case 0x21ad: case 0x21ae: case 0x21af: - case 0x21b0: case 0x21b1: case 0x21b2: case 0x21b3: - case 0x21b4: case 0x21b5: case 0x21b6: case 0x21b7: - case 0x21b8: case 0x21b9: case 0x21ba: case 0x21bb: - case 0x21bc: case 0x21bd: case 0x21be: case 0x21bf: - case 0x21c0: case 0x21c1: case 0x21c2: case 0x21c3: - case 0x21c4: case 0x21c5: case 0x21c6: case 0x21c7: - case 0x21c8: case 0x21c9: case 0x21ca: case 0x21cb: - case 0x21cc: case 0x21cd: case 0x21ce: case 0x21cf: - case 0x21d0: case 0x21d1: case 0x21d2: case 0x21d3: - case 0x21d4: case 0x21d5: case 0x21d6: case 0x21d7: - case 0x21d8: case 0x21d9: case 0x21da: case 0x21db: - case 0x21dc: case 0x21dd: case 0x21de: case 0x21df: - case 0x21e0: case 0x21e1: case 0x21e2: case 0x21e3: - case 0x21e4: case 0x21e5: case 0x21e6: case 0x21e7: - case 0x21e8: case 0x21e9: case 0x21ea: case 0x21eb: - case 0x21ec: case 0x21ed: case 0x21ee: case 0x21ef: - case 0x21f0: case 0x21f1: case 0x21f2: case 0x21f3: - case 0x21f4: case 0x21f5: case 0x21f6: case 0x21f7: - case 0x21f8: case 0x21f9: case 0x21fa: case 0x21fb: - case 0x21fc: case 0x21fd: case 0x21fe: case 0x21ff: - tgui->accel.pattern[addr & 0x7f] = val; - break; - } + tgui_t *tgui = (tgui_t *) priv; + tgui_accel_out(addr, val, tgui); + tgui_accel_out(addr + 1, val >> 8, tgui); } static void -tgui_accel_out_w(uint16_t addr, uint16_t val, void *p) +tgui_accel_out_l(uint16_t addr, uint32_t val, void *priv) { - tgui_t *tgui = (tgui_t *)p; - tgui_accel_out(addr, val, tgui); - tgui_accel_out(addr + 1, val >> 8, tgui); -} + tgui_t *tgui = (tgui_t *) priv; -static void -tgui_accel_out_l(uint16_t addr, uint32_t val, void *p) -{ - tgui_t *tgui = (tgui_t *)p; - - switch (addr) { - case 0x2124: /*Long version of Command and ROP together*/ - tgui->accel.command = val & 0xff; - tgui->accel.rop = val >> 24; - tgui->accel.use_src = (tgui->accel.rop & 0x33) ^ ((tgui->accel.rop >> 2) & 0x33); - tgui_accel_command(-1, 0, tgui); - break; - - default: - tgui_accel_out(addr, val, tgui); - tgui_accel_out(addr + 1, val >> 8, tgui); - tgui_accel_out(addr + 2, val >> 16, tgui); - tgui_accel_out(addr + 3, val >> 24, tgui); - break; - } + switch (addr) { + case 0x2124: /*Long version of Command and ROP together*/ + tgui->accel.command = val & 0xff; + tgui->accel.rop = val >> 24; + tgui->accel.use_src = (tgui->accel.rop & 0x33) ^ ((tgui->accel.rop >> 2) & 0x33); + tgui_accel_command(-1, 0, tgui); + break; + + default: + tgui_accel_out(addr, val, tgui); + tgui_accel_out(addr + 1, val >> 8, tgui); + tgui_accel_out(addr + 2, val >> 16, tgui); + tgui_accel_out(addr + 3, val >> 24, tgui); + break; + } } static uint8_t -tgui_accel_in(uint16_t addr, void *p) +tgui_accel_in(uint16_t addr, void *priv) { - tgui_t *tgui = (tgui_t *)p; + const tgui_t *tgui = (tgui_t *) priv; - switch (addr) - { - case 0x2120: /*Status*/ - return 0; - - case 0x2122: - return tgui->accel.ger22 & 0xff; - - case 0x2123: - return tgui->accel.ger22 >> 8; - - case 0x2127: /*ROP*/ - return tgui->accel.rop; - - case 0x2128: /*Flags*/ - return tgui->accel.flags & 0xff; - case 0x2129: /*Flags*/ - return tgui->accel.flags >> 8; - case 0x212a: /*Flags*/ - return tgui->accel.flags >> 16; - case 0x212b: - return tgui->accel.flags >> 24; - - case 0x212c: /*Foreground colour*/ - case 0x2178: - return tgui->accel.fg_col & 0xff; - case 0x212d: /*Foreground colour*/ - case 0x2179: - return tgui->accel.fg_col >> 8; - case 0x212e: /*Foreground colour*/ - case 0x217a: - return tgui->accel.fg_col >> 16; - case 0x212f: /*Foreground colour*/ - case 0x217b: - return tgui->accel.fg_col >> 24; + switch (addr) { + case 0x2120: /*Status*/ + return 0; - case 0x2130: /*Background colour*/ - case 0x217c: - return tgui->accel.bg_col & 0xff; - case 0x2131: /*Background colour*/ - case 0x217d: - return tgui->accel.bg_col >> 8; - case 0x2132: /*Background colour*/ - case 0x217e: - return tgui->accel.bg_col >> 16; - case 0x2133: /*Background colour*/ - case 0x217f: - return tgui->accel.bg_col >> 24; + case 0x2122: + return tgui->accel.ger22 & 0xff; + case 0x2123: + return tgui->accel.ger22 >> 8; - case 0x2134: /*Pattern location*/ - return tgui->accel.patloc & 0xff; - case 0x2135: /*Pattern location*/ - return tgui->accel.patloc >> 8; + case 0x2127: /*ROP*/ + return tgui->accel.rop; - case 0x2138: /*Dest X*/ - return tgui->accel.dst_x & 0xff; - case 0x2139: /*Dest X*/ - return tgui->accel.dst_x >> 8; - case 0x213a: /*Dest Y*/ - return tgui->accel.dst_y & 0xff; - case 0x213b: /*Dest Y*/ - return tgui->accel.dst_y >> 8; + case 0x2128: /*Flags*/ + return tgui->accel.flags & 0xff; + case 0x2129: /*Flags*/ + return tgui->accel.flags >> 8; + case 0x212a: /*Flags*/ + return tgui->accel.flags >> 16; + case 0x212b: + return tgui->accel.flags >> 24; - case 0x213c: /*Src X*/ - return tgui->accel.src_x & 0xff; - case 0x213d: /*Src X*/ - return tgui->accel.src_x >> 8; - case 0x213e: /*Src Y*/ - return tgui->accel.src_y & 0xff; - case 0x213f: /*Src Y*/ - return tgui->accel.src_y >> 8; + case 0x212c: /*Foreground colour*/ + case 0x2178: + return tgui->accel.fg_col & 0xff; + case 0x212d: /*Foreground colour*/ + case 0x2179: + return tgui->accel.fg_col >> 8; + case 0x212e: /*Foreground colour*/ + case 0x217a: + return tgui->accel.fg_col >> 16; + case 0x212f: /*Foreground colour*/ + case 0x217b: + return tgui->accel.fg_col >> 24; - case 0x2140: /*Size X*/ - return tgui->accel.size_x & 0xff; - case 0x2141: /*Size X*/ - return tgui->accel.size_x >> 8; - case 0x2142: /*Size Y*/ - return tgui->accel.size_y & 0xff; - case 0x2143: /*Size Y*/ - return tgui->accel.size_y >> 8; + case 0x2130: /*Background colour*/ + case 0x217c: + return tgui->accel.bg_col & 0xff; + case 0x2131: /*Background colour*/ + case 0x217d: + return tgui->accel.bg_col >> 8; + case 0x2132: /*Background colour*/ + case 0x217e: + return tgui->accel.bg_col >> 16; + case 0x2133: /*Background colour*/ + case 0x217f: + return tgui->accel.bg_col >> 24; - case 0x2144: /*Style*/ - return tgui->accel.style & 0xff; - case 0x2145: /*Style*/ - return tgui->accel.style >> 8; - case 0x2146: /*Style*/ - return tgui->accel.style >> 16; - case 0x2147: /*Style*/ - return tgui->accel.style >> 24; + case 0x2134: /*Pattern location*/ + return tgui->accel.patloc & 0xff; + case 0x2135: /*Pattern location*/ + return tgui->accel.patloc >> 8; - case 0x2148: /*Clip Src X*/ - return tgui->accel.src_x_clip & 0xff; - case 0x2149: /*Clip Src X*/ - return tgui->accel.src_x_clip >> 8; - case 0x214a: /*Clip Src Y*/ - return tgui->accel.src_y_clip & 0xff; - case 0x214b: /*Clip Src Y*/ - return tgui->accel.src_y_clip >> 8; + case 0x2138: /*Dest X*/ + return tgui->accel.dst_x & 0xff; + case 0x2139: /*Dest X*/ + return tgui->accel.dst_x >> 8; + case 0x213a: /*Dest Y*/ + return tgui->accel.dst_y & 0xff; + case 0x213b: /*Dest Y*/ + return tgui->accel.dst_y >> 8; - case 0x214c: /*Clip Dest X*/ - return tgui->accel.dst_x_clip & 0xff; - case 0x214d: /*Clip Dest X*/ - return tgui->accel.dst_x_clip >> 8; - case 0x214e: /*Clip Dest Y*/ - return tgui->accel.dst_y_clip & 0xff; - case 0x214f: /*Clip Dest Y*/ - return tgui->accel.dst_y_clip >> 8; + case 0x213c: /*Src X*/ + return tgui->accel.src_x & 0xff; + case 0x213d: /*Src X*/ + return tgui->accel.src_x >> 8; + case 0x213e: /*Src Y*/ + return tgui->accel.src_y & 0xff; + case 0x213f: /*Src Y*/ + return tgui->accel.src_y >> 8; - case 0x2168: /*CKey*/ - return tgui->accel.ckey & 0xff; - case 0x2169: /*CKey*/ - return tgui->accel.ckey >> 8; - case 0x216a: /*CKey*/ - return tgui->accel.ckey >> 16; - case 0x216b: /*CKey*/ - return tgui->accel.ckey >> 24; + case 0x2140: /*Size X*/ + return tgui->accel.size_x & 0xff; + case 0x2141: /*Size X*/ + return tgui->accel.size_x >> 8; + case 0x2142: /*Size Y*/ + return tgui->accel.size_y & 0xff; + case 0x2143: /*Size Y*/ + return tgui->accel.size_y >> 8; - case 0x2180: case 0x2181: case 0x2182: case 0x2183: - case 0x2184: case 0x2185: case 0x2186: case 0x2187: - case 0x2188: case 0x2189: case 0x218a: case 0x218b: - case 0x218c: case 0x218d: case 0x218e: case 0x218f: - case 0x2190: case 0x2191: case 0x2192: case 0x2193: - case 0x2194: case 0x2195: case 0x2196: case 0x2197: - case 0x2198: case 0x2199: case 0x219a: case 0x219b: - case 0x219c: case 0x219d: case 0x219e: case 0x219f: - case 0x21a0: case 0x21a1: case 0x21a2: case 0x21a3: - case 0x21a4: case 0x21a5: case 0x21a6: case 0x21a7: - case 0x21a8: case 0x21a9: case 0x21aa: case 0x21ab: - case 0x21ac: case 0x21ad: case 0x21ae: case 0x21af: - case 0x21b0: case 0x21b1: case 0x21b2: case 0x21b3: - case 0x21b4: case 0x21b5: case 0x21b6: case 0x21b7: - case 0x21b8: case 0x21b9: case 0x21ba: case 0x21bb: - case 0x21bc: case 0x21bd: case 0x21be: case 0x21bf: - case 0x21c0: case 0x21c1: case 0x21c2: case 0x21c3: - case 0x21c4: case 0x21c5: case 0x21c6: case 0x21c7: - case 0x21c8: case 0x21c9: case 0x21ca: case 0x21cb: - case 0x21cc: case 0x21cd: case 0x21ce: case 0x21cf: - case 0x21d0: case 0x21d1: case 0x21d2: case 0x21d3: - case 0x21d4: case 0x21d5: case 0x21d6: case 0x21d7: - case 0x21d8: case 0x21d9: case 0x21da: case 0x21db: - case 0x21dc: case 0x21dd: case 0x21de: case 0x21df: - case 0x21e0: case 0x21e1: case 0x21e2: case 0x21e3: - case 0x21e4: case 0x21e5: case 0x21e6: case 0x21e7: - case 0x21e8: case 0x21e9: case 0x21ea: case 0x21eb: - case 0x21ec: case 0x21ed: case 0x21ee: case 0x21ef: - case 0x21f0: case 0x21f1: case 0x21f2: case 0x21f3: - case 0x21f4: case 0x21f5: case 0x21f6: case 0x21f7: - case 0x21f8: case 0x21f9: case 0x21fa: case 0x21fb: - case 0x21fc: case 0x21fd: case 0x21fe: case 0x21ff: - return tgui->accel.pattern[addr & 0x7f]; - } - return 0; + case 0x2144: /*Style*/ + return tgui->accel.style & 0xff; + case 0x2145: /*Style*/ + return tgui->accel.style >> 8; + case 0x2146: /*Style*/ + return tgui->accel.style >> 16; + case 0x2147: /*Style*/ + return tgui->accel.style >> 24; + + case 0x2148: /*Clip Src X*/ + return tgui->accel.src_x_clip & 0xff; + case 0x2149: /*Clip Src X*/ + return tgui->accel.src_x_clip >> 8; + case 0x214a: /*Clip Src Y*/ + return tgui->accel.src_y_clip & 0xff; + case 0x214b: /*Clip Src Y*/ + return tgui->accel.src_y_clip >> 8; + + case 0x214c: /*Clip Dest X*/ + return tgui->accel.dst_x_clip & 0xff; + case 0x214d: /*Clip Dest X*/ + return tgui->accel.dst_x_clip >> 8; + case 0x214e: /*Clip Dest Y*/ + return tgui->accel.dst_y_clip & 0xff; + case 0x214f: /*Clip Dest Y*/ + return tgui->accel.dst_y_clip >> 8; + + case 0x2168: /*CKey*/ + return tgui->accel.ckey & 0xff; + case 0x2169: /*CKey*/ + return tgui->accel.ckey >> 8; + case 0x216a: /*CKey*/ + return tgui->accel.ckey >> 16; + case 0x216b: /*CKey*/ + return tgui->accel.ckey >> 24; + + case 0x2180: + case 0x2181: + case 0x2182: + case 0x2183: + case 0x2184: + case 0x2185: + case 0x2186: + case 0x2187: + case 0x2188: + case 0x2189: + case 0x218a: + case 0x218b: + case 0x218c: + case 0x218d: + case 0x218e: + case 0x218f: + case 0x2190: + case 0x2191: + case 0x2192: + case 0x2193: + case 0x2194: + case 0x2195: + case 0x2196: + case 0x2197: + case 0x2198: + case 0x2199: + case 0x219a: + case 0x219b: + case 0x219c: + case 0x219d: + case 0x219e: + case 0x219f: + case 0x21a0: + case 0x21a1: + case 0x21a2: + case 0x21a3: + case 0x21a4: + case 0x21a5: + case 0x21a6: + case 0x21a7: + case 0x21a8: + case 0x21a9: + case 0x21aa: + case 0x21ab: + case 0x21ac: + case 0x21ad: + case 0x21ae: + case 0x21af: + case 0x21b0: + case 0x21b1: + case 0x21b2: + case 0x21b3: + case 0x21b4: + case 0x21b5: + case 0x21b6: + case 0x21b7: + case 0x21b8: + case 0x21b9: + case 0x21ba: + case 0x21bb: + case 0x21bc: + case 0x21bd: + case 0x21be: + case 0x21bf: + case 0x21c0: + case 0x21c1: + case 0x21c2: + case 0x21c3: + case 0x21c4: + case 0x21c5: + case 0x21c6: + case 0x21c7: + case 0x21c8: + case 0x21c9: + case 0x21ca: + case 0x21cb: + case 0x21cc: + case 0x21cd: + case 0x21ce: + case 0x21cf: + case 0x21d0: + case 0x21d1: + case 0x21d2: + case 0x21d3: + case 0x21d4: + case 0x21d5: + case 0x21d6: + case 0x21d7: + case 0x21d8: + case 0x21d9: + case 0x21da: + case 0x21db: + case 0x21dc: + case 0x21dd: + case 0x21de: + case 0x21df: + case 0x21e0: + case 0x21e1: + case 0x21e2: + case 0x21e3: + case 0x21e4: + case 0x21e5: + case 0x21e6: + case 0x21e7: + case 0x21e8: + case 0x21e9: + case 0x21ea: + case 0x21eb: + case 0x21ec: + case 0x21ed: + case 0x21ee: + case 0x21ef: + case 0x21f0: + case 0x21f1: + case 0x21f2: + case 0x21f3: + case 0x21f4: + case 0x21f5: + case 0x21f6: + case 0x21f7: + case 0x21f8: + case 0x21f9: + case 0x21fa: + case 0x21fb: + case 0x21fc: + case 0x21fd: + case 0x21fe: + case 0x21ff: + return tgui->accel.pattern[addr & 0x7f]; + + default: + break; + } + return 0; } static uint16_t -tgui_accel_in_w(uint16_t addr, void *p) +tgui_accel_in_w(uint16_t addr, void *priv) { - tgui_t *tgui = (tgui_t *)p; - return tgui_accel_in(addr, tgui) | (tgui_accel_in(addr + 1, tgui) << 8); + tgui_t *tgui = (tgui_t *) priv; + return tgui_accel_in(addr, tgui) | (tgui_accel_in(addr + 1, tgui) << 8); } static uint32_t -tgui_accel_in_l(uint16_t addr, void *p) +tgui_accel_in_l(uint16_t addr, void *priv) { - tgui_t *tgui = (tgui_t *)p; - return tgui_accel_in_w(addr, tgui) | (tgui_accel_in_w(addr + 2, tgui) << 16); -} - - -static void -tgui_accel_write(uint32_t addr, uint8_t val, void *p) -{ - tgui_t *tgui = (tgui_t *)p; - svga_t *svga = &tgui->svga; - - if ((svga->crtc[0x36] & 0x03) == 0x02) { - if ((addr & ~0xff) != 0xbff00) - return; - } else if ((svga->crtc[0x36] & 0x03) == 0x01) { - if ((addr & ~0xff) != 0xb7f00) - return; - } - - switch (addr & 0xff) - { - case 0x22: - tgui->accel.ger22 = (tgui->accel.ger22 & 0xff00) | val; - switch (val & 0xff) { - case 4: - case 8: - tgui->accel.bpp = 0; - break; - - case 9: - tgui->accel.bpp = 1; - break; - - case 13: - case 14: - switch (tgui->svga.bpp) { - case 15: - case 16: - tgui->accel.bpp = 1; - break; - - case 24: - tgui->accel.bpp = 0; - break; - - case 32: - tgui->accel.bpp = 3; - break; - } - break; - } - break; - - case 0x23: - tgui->accel.ger22 = (tgui->accel.ger22 & 0xff) | (val << 8); - break; - - case 0x24: /*Command*/ - tgui->accel.command = val; - tgui_accel_command(-1, 0, tgui); - break; - - case 0x27: /*ROP*/ - tgui->accel.rop = val; - tgui->accel.use_src = (val & 0x33) ^ ((val >> 2) & 0x33); - break; - - case 0x28: /*Flags*/ - tgui->accel.flags = (tgui->accel.flags & 0xffffff00) | val; - break; - case 0x29: /*Flags*/ - tgui->accel.flags = (tgui->accel.flags & 0xffff00ff) | (val << 8); - break; - case 0x2a: /*Flags*/ - tgui->accel.flags = (tgui->accel.flags & 0xff00ffff) | (val << 16); - break; - case 0x2b: /*Flags*/ - tgui->accel.flags = (tgui->accel.flags & 0x0000ffff) | (val << 24); - break; - - case 0x2c: /*Foreground colour*/ - case 0x78: - tgui->accel.fg_col = (tgui->accel.fg_col & 0xffffff00) | val; - break; - case 0x2d: /*Foreground colour*/ - case 0x79: - tgui->accel.fg_col = (tgui->accel.fg_col & 0xffff00ff) | (val << 8); - break; - case 0x2e: /*Foreground colour*/ - case 0x7a: - tgui->accel.fg_col = (tgui->accel.fg_col & 0xff00ffff) | (val << 16); - break; - case 0x2f: /*Foreground colour*/ - case 0x7b: - tgui->accel.fg_col = (tgui->accel.fg_col & 0x00ffffff) | (val << 24); - break; - - case 0x30: /*Background colour*/ - case 0x7c: - tgui->accel.bg_col = (tgui->accel.bg_col & 0xffffff00) | val; - break; - case 0x31: /*Background colour*/ - case 0x7d: - tgui->accel.bg_col = (tgui->accel.bg_col & 0xffff00ff) | (val << 8); - break; - case 0x32: /*Background colour*/ - case 0x7e: - tgui->accel.bg_col = (tgui->accel.bg_col & 0xff00ffff) | (val << 16); - break; - case 0x33: /*Background colour*/ - case 0x7f: - tgui->accel.bg_col = (tgui->accel.bg_col & 0x00ffffff) | (val << 24); - break; - - case 0x34: /*Pattern location*/ - tgui->accel.patloc = (tgui->accel.patloc & 0xff00) | val; - break; - case 0x35: /*Pattern location*/ - tgui->accel.patloc = (tgui->accel.patloc & 0xff) | (val << 8); - break; - - case 0x38: /*Dest X*/ - tgui->accel.dst_x = (tgui->accel.dst_x & 0xff00) | val; - break; - case 0x39: /*Dest X*/ - tgui->accel.dst_x = (tgui->accel.dst_x & 0xff) | (val << 8); - break; - case 0x3a: /*Dest Y*/ - tgui->accel.dst_y = (tgui->accel.dst_y & 0xff00) | val; - break; - case 0x3b: /*Dest Y*/ - tgui->accel.dst_y = (tgui->accel.dst_y & 0xff) | (val << 8); - break; - - case 0x3c: /*Src X*/ - tgui->accel.src_x = (tgui->accel.src_x & 0xff00) | val; - break; - case 0x3d: /*Src X*/ - tgui->accel.src_x = (tgui->accel.src_x & 0xff) | (val << 8); - break; - case 0x3e: /*Src Y*/ - tgui->accel.src_y = (tgui->accel.src_y & 0xff00) | val; - break; - case 0x3f: /*Src Y*/ - tgui->accel.src_y = (tgui->accel.src_y & 0xff) | (val << 8); - break; - - case 0x40: /*Size X*/ - tgui->accel.size_x = (tgui->accel.size_x & 0xff00) | val; - break; - case 0x41: /*Size X*/ - tgui->accel.size_x = (tgui->accel.size_x & 0xff) | (val << 8); - break; - case 0x42: /*Size Y*/ - tgui->accel.size_y = (tgui->accel.size_y & 0xff00) | val; - tgui->accel.sv_size_y = (tgui->accel.sv_size_y & 0xff00) | val; - break; - case 0x43: /*Size Y*/ - tgui->accel.size_y = (tgui->accel.size_y & 0xff) | (val << 8); - tgui->accel.sv_size_y = (tgui->accel.sv_size_y & 0xff) | (val << 8); - break; - - case 0x44: /*Style*/ - tgui->accel.style = (tgui->accel.style & 0xffffff00) | val; - break; - case 0x45: /*Style*/ - tgui->accel.style = (tgui->accel.style & 0xffff00ff) | (val << 8); - break; - case 0x46: /*Style*/ - tgui->accel.style = (tgui->accel.style & 0xff00ffff) | (val << 16); - break; - case 0x47: /*Style*/ - tgui->accel.style = (tgui->accel.style & 0x00ffffff) | (val << 24); - break; - - case 0x48: /*Clip Src X*/ - tgui->accel.src_x_clip = (tgui->accel.src_x_clip & 0xff00) | val; - break; - case 0x49: /*Clip Src X*/ - tgui->accel.src_x_clip = (tgui->accel.src_x_clip & 0xff) | (val << 8); - break; - case 0x4a: /*Clip Src Y*/ - tgui->accel.src_y_clip = (tgui->accel.src_y_clip & 0xff00) | val; - break; - case 0x4b: /*Clip Src Y*/ - tgui->accel.src_y_clip = (tgui->accel.src_y_clip & 0xff) | (val << 8); - break; - - case 0x4c: /*Clip Dest X*/ - tgui->accel.dst_x_clip = (tgui->accel.dst_x_clip & 0xff00) | val; - break; - case 0x4d: /*Clip Dest X*/ - tgui->accel.dst_x_clip = (tgui->accel.dst_x_clip & 0xff) | (val << 8); - break; - case 0x4e: /*Clip Dest Y*/ - tgui->accel.dst_y_clip = (tgui->accel.dst_y_clip & 0xff00) | val; - break; - case 0x4f: /*Clip Dest Y*/ - tgui->accel.dst_y_clip = (tgui->accel.dst_y_clip & 0xff) | (val << 8); - break; - - case 0x68: /*CKey*/ - tgui->accel.ckey = (tgui->accel.ckey & 0xffffff00) | val; - break; - case 0x69: /*CKey*/ - tgui->accel.ckey = (tgui->accel.ckey & 0xffff00ff) | (val << 8); - break; - case 0x6a: /*CKey*/ - tgui->accel.ckey = (tgui->accel.ckey & 0xff00ffff) | (val << 16); - break; - case 0x6b: /*CKey*/ - tgui->accel.ckey = (tgui->accel.ckey & 0x00ffffff) | (val << 24); - break; - - case 0x80: case 0x81: case 0x82: case 0x83: - case 0x84: case 0x85: case 0x86: case 0x87: - case 0x88: case 0x89: case 0x8a: case 0x8b: - case 0x8c: case 0x8d: case 0x8e: case 0x8f: - case 0x90: case 0x91: case 0x92: case 0x93: - case 0x94: case 0x95: case 0x96: case 0x97: - case 0x98: case 0x99: case 0x9a: case 0x9b: - case 0x9c: case 0x9d: case 0x9e: case 0x9f: - case 0xa0: case 0xa1: case 0xa2: case 0xa3: - case 0xa4: case 0xa5: case 0xa6: case 0xa7: - case 0xa8: case 0xa9: case 0xaa: case 0xab: - case 0xac: case 0xad: case 0xae: case 0xaf: - case 0xb0: case 0xb1: case 0xb2: case 0xb3: - case 0xb4: case 0xb5: case 0xb6: case 0xb7: - case 0xb8: case 0xb9: case 0xba: case 0xbb: - case 0xbc: case 0xbd: case 0xbe: case 0xbf: - case 0xc0: case 0xc1: case 0xc2: case 0xc3: - case 0xc4: case 0xc5: case 0xc6: case 0xc7: - case 0xc8: case 0xc9: case 0xca: case 0xcb: - case 0xcc: case 0xcd: case 0xce: case 0xcf: - case 0xd0: case 0xd1: case 0xd2: case 0xd3: - case 0xd4: case 0xd5: case 0xd6: case 0xd7: - case 0xd8: case 0xd9: case 0xda: case 0xdb: - case 0xdc: case 0xdd: case 0xde: case 0xdf: - case 0xe0: case 0xe1: case 0xe2: case 0xe3: - case 0xe4: case 0xe5: case 0xe6: case 0xe7: - case 0xe8: case 0xe9: case 0xea: case 0xeb: - case 0xec: case 0xed: case 0xee: case 0xef: - case 0xf0: case 0xf1: case 0xf2: case 0xf3: - case 0xf4: case 0xf5: case 0xf6: case 0xf7: - case 0xf8: case 0xf9: case 0xfa: case 0xfb: - case 0xfc: case 0xfd: case 0xfe: case 0xff: - tgui->accel.pattern[addr & 0x7f] = val; - break; - } + tgui_t *tgui = (tgui_t *) priv; + return tgui_accel_in_w(addr, tgui) | (tgui_accel_in_w(addr + 2, tgui) << 16); } static void -tgui_accel_write_w(uint32_t addr, uint16_t val, void *p) +tgui_accel_write(uint32_t addr, uint8_t val, void *priv) { - tgui_t *tgui = (tgui_t *)p; + tgui_t *tgui = (tgui_t *) priv; + svga_t *svga = &tgui->svga; - tgui_accel_write(addr, val, tgui); - tgui_accel_write(addr + 1, val >> 8, tgui); + if ((svga->crtc[0x36] & 0x03) == 0x02) { + if ((addr & ~0xff) != 0xbff00) + return; + } else if ((svga->crtc[0x36] & 0x03) == 0x01) { + if ((addr & ~0xff) != 0xb7f00) + return; + } + + tgui_accel_out((addr & 0xff) + 0x2100, val, tgui); } static void -tgui_accel_write_l(uint32_t addr, uint32_t val, void *p) +tgui_accel_write_w(uint32_t addr, uint16_t val, void *priv) { - tgui_t *tgui = (tgui_t *)p; - svga_t *svga = &tgui->svga; + tgui_t *tgui = (tgui_t *) priv; - switch (addr & 0xff) { - case 0x24: /*Long version of Command and ROP together*/ - if ((svga->crtc[0x36] & 0x03) == 0x02) { - if ((addr & ~0xff) != 0xbff00) - return; - } else if ((svga->crtc[0x36] & 0x03) == 0x01) { - if ((addr & ~0xff) != 0xb7f00) - return; - } - tgui->accel.command = val & 0xff; - tgui->accel.rop = val >> 24; - tgui->accel.use_src = ((val >> 24) & 0x33) ^ (((val >> 24) >> 2) & 0x33); - tgui_accel_command(-1, 0, tgui); - break; - - default: - tgui_accel_write_w(addr, val, tgui); - tgui_accel_write_w(addr + 2, val >> 16, tgui); - break; - } + tgui_accel_write(addr, val, tgui); + tgui_accel_write(addr + 1, val >> 8, tgui); +} + +static void +tgui_accel_write_l(uint32_t addr, uint32_t val, void *priv) +{ + tgui_t *tgui = (tgui_t *) priv; + const svga_t *svga = &tgui->svga; + + switch (addr & 0xff) { + case 0x24: /*Long version of Command and ROP together*/ + if ((svga->crtc[0x36] & 0x03) == 0x02) { + if ((addr & ~0xff) != 0xbff00) + return; + } else if ((svga->crtc[0x36] & 0x03) == 0x01) { + if ((addr & ~0xff) != 0xb7f00) + return; + } + tgui->accel.command = val & 0xff; + tgui->accel.rop = val >> 24; + tgui->accel.use_src = ((val >> 24) & 0x33) ^ (((val >> 24) >> 2) & 0x33); + tgui_accel_command(-1, 0, tgui); + break; + + default: + tgui_accel_write_w(addr, val, tgui); + tgui_accel_write_w(addr + 2, val >> 16, tgui); + break; + } } static uint8_t -tgui_accel_read(uint32_t addr, void *p) +tgui_accel_read(uint32_t addr, void *priv) { - tgui_t *tgui = (tgui_t *)p; - svga_t *svga = &tgui->svga; + const tgui_t *tgui = (tgui_t *) priv; + const svga_t *svga = &tgui->svga; - if ((svga->crtc[0x36] & 0x03) == 0x02) { - if ((addr & ~0xff) != 0xbff00) - return 0xff; - } else if ((svga->crtc[0x36] & 0x03) == 0x01) { - if ((addr & ~0xff) != 0xb7f00) - return 0xff; - } - - switch (addr & 0xff) - { - case 0x20: /*Status*/ - return 0; - - case 0x22: - return tgui->accel.ger22 & 0xff; - - case 0x23: - return tgui->accel.ger22 >> 8; - - case 0x27: /*ROP*/ - return tgui->accel.rop; - - case 0x28: /*Flags*/ - return tgui->accel.flags & 0xff; - case 0x29: /*Flags*/ - return tgui->accel.flags >> 8; - case 0x2a: /*Flags*/ - return tgui->accel.flags >> 16; - case 0x2b: - return tgui->accel.flags >> 24; - - case 0x2c: /*Foreground colour*/ - case 0x78: - return tgui->accel.fg_col & 0xff; - case 0x2d: /*Foreground colour*/ - case 0x79: - return tgui->accel.fg_col >> 8; - case 0x2e: /*Foreground colour*/ - case 0x7a: - return tgui->accel.fg_col >> 16; - case 0x2f: /*Foreground colour*/ - case 0x7b: - return tgui->accel.fg_col >> 24; + if ((svga->crtc[0x36] & 0x03) == 0x02) { + if ((addr & ~0xff) != 0xbff00) + return 0xff; + } else if ((svga->crtc[0x36] & 0x03) == 0x01) { + if ((addr & ~0xff) != 0xb7f00) + return 0xff; + } - case 0x30: /*Background colour*/ - case 0x7c: - return tgui->accel.bg_col & 0xff; - case 0x31: /*Background colour*/ - case 0x7d: - return tgui->accel.bg_col >> 8; - case 0x32: /*Background colour*/ - case 0x7e: - return tgui->accel.bg_col >> 16; - case 0x33: /*Background colour*/ - case 0x7f: - return tgui->accel.bg_col >> 24; + switch (addr & 0xff) { + case 0x20: /*Status*/ + return 0; - case 0x34: /*Pattern location*/ - return tgui->accel.patloc & 0xff; - case 0x35: /*Pattern location*/ - return tgui->accel.patloc >> 8; + case 0x22: + return tgui->accel.ger22 & 0xff; + case 0x23: + return tgui->accel.ger22 >> 8; - case 0x38: /*Dest X*/ - return tgui->accel.dst_x & 0xff; - case 0x39: /*Dest X*/ - return tgui->accel.dst_x >> 8; - case 0x3a: /*Dest Y*/ - return tgui->accel.dst_y & 0xff; - case 0x3b: /*Dest Y*/ - return tgui->accel.dst_y >> 8; + case 0x27: /*ROP*/ + return tgui->accel.rop; - case 0x3c: /*Src X*/ - return tgui->accel.src_x & 0xff; - case 0x3d: /*Src X*/ - return tgui->accel.src_x >> 8; - case 0x3e: /*Src Y*/ - return tgui->accel.src_y & 0xff; - case 0x3f: /*Src Y*/ - return tgui->accel.src_y >> 8; + case 0x28: /*Flags*/ + return tgui->accel.flags & 0xff; + case 0x29: /*Flags*/ + return tgui->accel.flags >> 8; + case 0x2a: /*Flags*/ + return tgui->accel.flags >> 16; + case 0x2b: + return tgui->accel.flags >> 24; - case 0x40: /*Size X*/ - return tgui->accel.size_x & 0xff; - case 0x41: /*Size X*/ - return tgui->accel.size_x >> 8; - case 0x42: /*Size Y*/ - return tgui->accel.size_y & 0xff; - case 0x43: /*Size Y*/ - return tgui->accel.size_y >> 8; + case 0x2c: /*Foreground colour*/ + case 0x78: + return tgui->accel.fg_col & 0xff; + case 0x2d: /*Foreground colour*/ + case 0x79: + return tgui->accel.fg_col >> 8; + case 0x2e: /*Foreground colour*/ + case 0x7a: + return tgui->accel.fg_col >> 16; + case 0x2f: /*Foreground colour*/ + case 0x7b: + return tgui->accel.fg_col >> 24; - case 0x44: /*Style*/ - return tgui->accel.style & 0xff; - case 0x45: /*Style*/ - return tgui->accel.style >> 8; - case 0x46: /*Style*/ - return tgui->accel.style >> 16; - case 0x47: /*Style*/ - return tgui->accel.style >> 24; + case 0x30: /*Background colour*/ + case 0x7c: + return tgui->accel.bg_col & 0xff; + case 0x31: /*Background colour*/ + case 0x7d: + return tgui->accel.bg_col >> 8; + case 0x32: /*Background colour*/ + case 0x7e: + return tgui->accel.bg_col >> 16; + case 0x33: /*Background colour*/ + case 0x7f: + return tgui->accel.bg_col >> 24; - case 0x48: /*Clip Src X*/ - return tgui->accel.src_x_clip & 0xff; - case 0x49: /*Clip Src X*/ - return tgui->accel.src_x_clip >> 8; - case 0x4a: /*Clip Src Y*/ - return tgui->accel.src_y_clip & 0xff; - case 0x4b: /*Clip Src Y*/ - return tgui->accel.src_y_clip >> 8; + case 0x34: /*Pattern location*/ + return tgui->accel.patloc & 0xff; + case 0x35: /*Pattern location*/ + return tgui->accel.patloc >> 8; - case 0x4c: /*Clip Dest X*/ - return tgui->accel.dst_x_clip & 0xff; - case 0x4d: /*Clip Dest X*/ - return tgui->accel.dst_x_clip >> 8; - case 0x4e: /*Clip Dest Y*/ - return tgui->accel.dst_y_clip & 0xff; - case 0x4f: /*Clip Dest Y*/ - return tgui->accel.dst_y_clip >> 8; + case 0x38: /*Dest X*/ + return tgui->accel.dst_x & 0xff; + case 0x39: /*Dest X*/ + return tgui->accel.dst_x >> 8; + case 0x3a: /*Dest Y*/ + return tgui->accel.dst_y & 0xff; + case 0x3b: /*Dest Y*/ + return tgui->accel.dst_y >> 8; - case 0x68: /*CKey*/ - return tgui->accel.ckey & 0xff; - case 0x69: /*CKey*/ - return tgui->accel.ckey >> 8; - case 0x6a: /*CKey*/ - return tgui->accel.ckey >> 16; - case 0x6b: /*CKey*/ - return tgui->accel.ckey >> 24; + case 0x3c: /*Src X*/ + return tgui->accel.src_x & 0xff; + case 0x3d: /*Src X*/ + return tgui->accel.src_x >> 8; + case 0x3e: /*Src Y*/ + return tgui->accel.src_y & 0xff; + case 0x3f: /*Src Y*/ + return tgui->accel.src_y >> 8; - case 0x80: case 0x81: case 0x82: case 0x83: - case 0x84: case 0x85: case 0x86: case 0x87: - case 0x88: case 0x89: case 0x8a: case 0x8b: - case 0x8c: case 0x8d: case 0x8e: case 0x8f: - case 0x90: case 0x91: case 0x92: case 0x93: - case 0x94: case 0x95: case 0x96: case 0x97: - case 0x98: case 0x99: case 0x9a: case 0x9b: - case 0x9c: case 0x9d: case 0x9e: case 0x9f: - case 0xa0: case 0xa1: case 0xa2: case 0xa3: - case 0xa4: case 0xa5: case 0xa6: case 0xa7: - case 0xa8: case 0xa9: case 0xaa: case 0xab: - case 0xac: case 0xad: case 0xae: case 0xaf: - case 0xb0: case 0xb1: case 0xb2: case 0xb3: - case 0xb4: case 0xb5: case 0xb6: case 0xb7: - case 0xb8: case 0xb9: case 0xba: case 0xbb: - case 0xbc: case 0xbd: case 0xbe: case 0xbf: - case 0xc0: case 0xc1: case 0xc2: case 0xc3: - case 0xc4: case 0xc5: case 0xc6: case 0xc7: - case 0xc8: case 0xc9: case 0xca: case 0xcb: - case 0xcc: case 0xcd: case 0xce: case 0xcf: - case 0xd0: case 0xd1: case 0xd2: case 0xd3: - case 0xd4: case 0xd5: case 0xd6: case 0xd7: - case 0xd8: case 0xd9: case 0xda: case 0xdb: - case 0xdc: case 0xdd: case 0xde: case 0xdf: - case 0xe0: case 0xe1: case 0xe2: case 0xe3: - case 0xe4: case 0xe5: case 0xe6: case 0xe7: - case 0xe8: case 0xe9: case 0xea: case 0xeb: - case 0xec: case 0xed: case 0xee: case 0xef: - case 0xf0: case 0xf1: case 0xf2: case 0xf3: - case 0xf4: case 0xf5: case 0xf6: case 0xf7: - case 0xf8: case 0xf9: case 0xfa: case 0xfb: - case 0xfc: case 0xfd: case 0xfe: case 0xff: - return tgui->accel.pattern[addr & 0x7f]; - } - return 0xff; + case 0x40: /*Size X*/ + return tgui->accel.size_x & 0xff; + case 0x41: /*Size X*/ + return tgui->accel.size_x >> 8; + case 0x42: /*Size Y*/ + return tgui->accel.size_y & 0xff; + case 0x43: /*Size Y*/ + return tgui->accel.size_y >> 8; + + case 0x44: /*Style*/ + return tgui->accel.style & 0xff; + case 0x45: /*Style*/ + return tgui->accel.style >> 8; + case 0x46: /*Style*/ + return tgui->accel.style >> 16; + case 0x47: /*Style*/ + return tgui->accel.style >> 24; + + case 0x48: /*Clip Src X*/ + return tgui->accel.src_x_clip & 0xff; + case 0x49: /*Clip Src X*/ + return tgui->accel.src_x_clip >> 8; + case 0x4a: /*Clip Src Y*/ + return tgui->accel.src_y_clip & 0xff; + case 0x4b: /*Clip Src Y*/ + return tgui->accel.src_y_clip >> 8; + + case 0x4c: /*Clip Dest X*/ + return tgui->accel.dst_x_clip & 0xff; + case 0x4d: /*Clip Dest X*/ + return tgui->accel.dst_x_clip >> 8; + case 0x4e: /*Clip Dest Y*/ + return tgui->accel.dst_y_clip & 0xff; + case 0x4f: /*Clip Dest Y*/ + return tgui->accel.dst_y_clip >> 8; + + case 0x68: /*CKey*/ + return tgui->accel.ckey & 0xff; + case 0x69: /*CKey*/ + return tgui->accel.ckey >> 8; + case 0x6a: /*CKey*/ + return tgui->accel.ckey >> 16; + case 0x6b: /*CKey*/ + return tgui->accel.ckey >> 24; + + case 0x80: + case 0x81: + case 0x82: + case 0x83: + case 0x84: + case 0x85: + case 0x86: + case 0x87: + case 0x88: + case 0x89: + case 0x8a: + case 0x8b: + case 0x8c: + case 0x8d: + case 0x8e: + case 0x8f: + case 0x90: + case 0x91: + case 0x92: + case 0x93: + case 0x94: + case 0x95: + case 0x96: + case 0x97: + case 0x98: + case 0x99: + case 0x9a: + case 0x9b: + case 0x9c: + case 0x9d: + case 0x9e: + case 0x9f: + case 0xa0: + case 0xa1: + case 0xa2: + case 0xa3: + case 0xa4: + case 0xa5: + case 0xa6: + case 0xa7: + case 0xa8: + case 0xa9: + case 0xaa: + case 0xab: + case 0xac: + case 0xad: + case 0xae: + case 0xaf: + case 0xb0: + case 0xb1: + case 0xb2: + case 0xb3: + case 0xb4: + case 0xb5: + case 0xb6: + case 0xb7: + case 0xb8: + case 0xb9: + case 0xba: + case 0xbb: + case 0xbc: + case 0xbd: + case 0xbe: + case 0xbf: + case 0xc0: + case 0xc1: + case 0xc2: + case 0xc3: + case 0xc4: + case 0xc5: + case 0xc6: + case 0xc7: + case 0xc8: + case 0xc9: + case 0xca: + case 0xcb: + case 0xcc: + case 0xcd: + case 0xce: + case 0xcf: + case 0xd0: + case 0xd1: + case 0xd2: + case 0xd3: + case 0xd4: + case 0xd5: + case 0xd6: + case 0xd7: + case 0xd8: + case 0xd9: + case 0xda: + case 0xdb: + case 0xdc: + case 0xdd: + case 0xde: + case 0xdf: + case 0xe0: + case 0xe1: + case 0xe2: + case 0xe3: + case 0xe4: + case 0xe5: + case 0xe6: + case 0xe7: + case 0xe8: + case 0xe9: + case 0xea: + case 0xeb: + case 0xec: + case 0xed: + case 0xee: + case 0xef: + case 0xf0: + case 0xf1: + case 0xf2: + case 0xf3: + case 0xf4: + case 0xf5: + case 0xf6: + case 0xf7: + case 0xf8: + case 0xf9: + case 0xfa: + case 0xfb: + case 0xfc: + case 0xfd: + case 0xfe: + case 0xff: + return tgui->accel.pattern[addr & 0x7f]; + + default: + break; + } + return 0xff; } static uint16_t -tgui_accel_read_w(uint32_t addr, void *p) +tgui_accel_read_w(uint32_t addr, void *priv) { - tgui_t *tgui = (tgui_t *)p; - return tgui_accel_read(addr, tgui) | (tgui_accel_read(addr + 1, tgui) << 8); + tgui_t *tgui = (tgui_t *) priv; + + return tgui_accel_read(addr, tgui) | (tgui_accel_read(addr + 1, tgui) << 8); } static uint32_t -tgui_accel_read_l(uint32_t addr, void *p) +tgui_accel_read_l(uint32_t addr, void *priv) { - tgui_t *tgui = (tgui_t *)p; - return tgui_accel_read_w(addr, tgui) | (tgui_accel_read_w(addr + 2, tgui) << 16); -} + tgui_t *tgui = (tgui_t *) priv; -static void -tgui_accel_write_fb_b(uint32_t addr, uint8_t val, void *p) -{ - svga_t *svga = (svga_t *)p; - tgui_t *tgui = (tgui_t *)svga->p; - - if (tgui->write_blitter) { - tgui_accel_command(8, val << 24, tgui); - } else - svga_write_linear(addr, val, svga); + return tgui_accel_read_w(addr, tgui) | (tgui_accel_read_w(addr + 2, tgui) << 16); } static void -tgui_accel_write_fb_w(uint32_t addr, uint16_t val, void *p) +tgui_accel_write_fb_b(uint32_t addr, uint8_t val, void *priv) { - svga_t *svga = (svga_t *)p; - tgui_t *tgui = (tgui_t *)svga->p; + svga_t *svga = (svga_t *) priv; + tgui_t *tgui = (tgui_t *) svga->priv; - if (tgui->write_blitter) - tgui_accel_command(16, (((val & 0xff00) >> 8) | ((val & 0x00ff) << 8)) << 16, tgui); - else - svga_writew_linear(addr, val, svga); + if (tgui->write_blitter) { + tgui_accel_command(8, val << 24, tgui); + } else + svga_write_linear(addr, val, svga); } static void -tgui_accel_write_fb_l(uint32_t addr, uint32_t val, void *p) +tgui_accel_write_fb_w(uint32_t addr, uint16_t val, void *priv) { - svga_t *svga = (svga_t *)p; - tgui_t *tgui = (tgui_t *)svga->p; + svga_t *svga = (svga_t *) priv; + tgui_t *tgui = (tgui_t *) svga->priv; - if (tgui->write_blitter) - tgui_accel_command(32, ((val & 0xff000000) >> 24) | ((val & 0x00ff0000) >> 8) | ((val & 0x0000ff00) << 8) | ((val & 0x000000ff) << 24), tgui); - else - svga_writel_linear(addr, val, svga); + if (tgui->write_blitter) + tgui_accel_command(16, (((val & 0xff00) >> 8) | ((val & 0x00ff) << 8)) << 16, tgui); + else + svga_writew_linear(addr, val, svga); } static void -tgui_mmio_write(uint32_t addr, uint8_t val, void *p) +tgui_accel_write_fb_l(uint32_t addr, uint32_t val, void *priv) { - tgui_t *tgui = (tgui_t *)p; - svga_t *svga = &tgui->svga; - - addr &= 0x0000ffff; + svga_t *svga = (svga_t *) priv; + tgui_t *tgui = (tgui_t *) svga->priv; + + if (tgui->write_blitter) + tgui_accel_command(32, ((val & 0xff000000) >> 24) | ((val & 0x00ff0000) >> 8) | ((val & 0x0000ff00) << 8) | ((val & 0x000000ff) << 24), tgui); + else + svga_writel_linear(addr, val, svga); +} + +static void +tgui_mmio_write(uint32_t addr, uint8_t val, void *priv) +{ + const tgui_t *tgui = (tgui_t *) priv; + const svga_t *svga = &tgui->svga; + + addr &= 0x0000ffff; if (((svga->crtc[0x36] & 0x03) == 0x00) && (addr >= 0x2100 && addr <= 0x21ff)) - tgui_accel_out(addr, val, p); - else if (((svga->crtc[0x36] & 0x03) > 0x00) && (addr <= 0xff)) - tgui_accel_write(addr, val, p); - else - tgui_out(addr, val, p); + tgui_accel_out(addr, val, priv); + else if (((svga->crtc[0x36] & 0x03) > 0x00) && (addr <= 0xff)) + tgui_accel_write(addr, val, priv); + else + tgui_out(addr, val, priv); } - static void -tgui_mmio_write_w(uint32_t addr, uint16_t val, void *p) +tgui_mmio_write_w(uint32_t addr, uint16_t val, void *priv) { - tgui_t *tgui = (tgui_t *)p; - svga_t *svga = &tgui->svga; - - addr &= 0x0000ffff; - - if (((svga->crtc[0x36] & 0x03) == 0x00) && (addr >= 0x2100 && addr <= 0x21ff)) - tgui_accel_out_w(addr, val, p); - else if (((svga->crtc[0x36] & 0x03) > 0x00) && (addr <= 0xff)) - tgui_accel_write_w(addr, val, p); - else { - tgui_out(addr, val & 0xff, p); - tgui_out(addr + 1, val >> 8, p); - } -} + const tgui_t *tgui = (tgui_t *) priv; + const svga_t *svga = &tgui->svga; + addr &= 0x0000ffff; + + if (((svga->crtc[0x36] & 0x03) == 0x00) && (addr >= 0x2100 && addr <= 0x21ff)) + tgui_accel_out_w(addr, val, priv); + else if (((svga->crtc[0x36] & 0x03) > 0x00) && (addr <= 0xff)) + tgui_accel_write_w(addr, val, priv); + else { + tgui_out(addr, val & 0xff, priv); + tgui_out(addr + 1, val >> 8, priv); + } +} static void -tgui_mmio_write_l(uint32_t addr, uint32_t val, void *p) +tgui_mmio_write_l(uint32_t addr, uint32_t val, void *priv) { - tgui_t *tgui = (tgui_t *)p; - svga_t *svga = &tgui->svga; - - addr &= 0x0000ffff; + const tgui_t *tgui = (tgui_t *) priv; + const svga_t *svga = &tgui->svga; + + addr &= 0x0000ffff; if (((svga->crtc[0x36] & 0x03) == 0x00) && (addr >= 0x2100 && addr <= 0x21ff)) - tgui_accel_out_l(addr, val, p); - else if (((svga->crtc[0x36] & 0x03) > 0x00) && (addr <= 0xff)) - tgui_accel_write_l(addr, val, p); - else { - tgui_out(addr, val & 0xff, p); - tgui_out(addr + 1, val >> 8, p); - tgui_out(addr + 2, val >> 16, p); - tgui_out(addr + 3, val >> 24, p); - } + tgui_accel_out_l(addr, val, priv); + else if (((svga->crtc[0x36] & 0x03) > 0x00) && (addr <= 0xff)) + tgui_accel_write_l(addr, val, priv); + else { + tgui_out(addr, val & 0xff, priv); + tgui_out(addr + 1, val >> 8, priv); + tgui_out(addr + 2, val >> 16, priv); + tgui_out(addr + 3, val >> 24, priv); + } } - static uint8_t -tgui_mmio_read(uint32_t addr, void *p) +tgui_mmio_read(uint32_t addr, void *priv) { - tgui_t *tgui = (tgui_t *)p; - svga_t *svga = &tgui->svga; - + const tgui_t *tgui = (tgui_t *) priv; + const svga_t *svga = &tgui->svga; + uint8_t ret = 0xff; - addr &= 0x0000ffff; + addr &= 0x0000ffff; if (((svga->crtc[0x36] & 0x03) == 0x00) && (addr >= 0x2100 && addr <= 0x21ff)) - ret = tgui_accel_in(addr, p); - else if (((svga->crtc[0x36] & 0x03) > 0x00) && (addr <= 0xff)) - ret = tgui_accel_read(addr, p); - else - ret = tgui_in(addr, p); + ret = tgui_accel_in(addr, priv); + else if (((svga->crtc[0x36] & 0x03) > 0x00) && (addr <= 0xff)) + ret = tgui_accel_read(addr, priv); + else + ret = tgui_in(addr, priv); return ret; } - static uint16_t -tgui_mmio_read_w(uint32_t addr, void *p) +tgui_mmio_read_w(uint32_t addr, void *priv) { - tgui_t *tgui = (tgui_t *)p; - svga_t *svga = &tgui->svga; - uint16_t ret = 0xffff; + const tgui_t *tgui = (tgui_t *) priv; + const svga_t *svga = &tgui->svga; + uint16_t ret = 0xffff; - addr &= 0x0000ffff; + addr &= 0x0000ffff; if (((svga->crtc[0x36] & 0x03) == 0x00) && (addr >= 0x2100 && addr <= 0x21ff)) - ret = tgui_accel_in_w(addr, p); - else if (((svga->crtc[0x36] & 0x03) > 0x00) && (addr <= 0xff)) - ret = tgui_accel_read_w(addr, p); - else - ret = tgui_in(addr, p) | (tgui_in(addr + 1, p) << 8); + ret = tgui_accel_in_w(addr, priv); + else if (((svga->crtc[0x36] & 0x03) > 0x00) && (addr <= 0xff)) + ret = tgui_accel_read_w(addr, priv); + else + ret = tgui_in(addr, priv) | (tgui_in(addr + 1, priv) << 8); return ret; } - static uint32_t -tgui_mmio_read_l(uint32_t addr, void *p) +tgui_mmio_read_l(uint32_t addr, void *priv) { - tgui_t *tgui = (tgui_t *)p; - svga_t *svga = &tgui->svga; - uint32_t ret = 0xffffffff; + const tgui_t *tgui = (tgui_t *) priv; + const svga_t *svga = &tgui->svga; + uint32_t ret = 0xffffffff; - addr &= 0x0000ffff; + addr &= 0x0000ffff; if (((svga->crtc[0x36] & 0x03) == 0x00) && (addr >= 0x2100 && addr <= 0x21ff)) - ret = tgui_accel_in_l(addr, p); - else if (((svga->crtc[0x36] & 0x03) > 0x00) && (addr <= 0xff)) - ret = tgui_accel_read_l(addr, p); - else - ret = tgui_in(addr, p) | (tgui_in(addr + 1, p) << 8) | (tgui_in(addr + 2, p) << 16) | (tgui_in(addr + 3, p) << 24); + ret = tgui_accel_in_l(addr, priv); + else if (((svga->crtc[0x36] & 0x03) > 0x00) && (addr <= 0xff)) + ret = tgui_accel_read_l(addr, priv); + else + ret = tgui_in(addr, priv) | (tgui_in(addr + 1, priv) << 8) | (tgui_in(addr + 2, priv) << 16) | (tgui_in(addr + 3, priv) << 24); return ret; } -static void *tgui_init(const device_t *info) +static void * +tgui_init(const device_t *info) { - const char *bios_fn; + const char *bios_fn; - tgui_t *tgui = malloc(sizeof(tgui_t)); - svga_t *svga = &tgui->svga; - memset(tgui, 0, sizeof(tgui_t)); - - tgui->vram_size = device_get_config_int("memory") << 20; - tgui->vram_mask = tgui->vram_size - 1; - - tgui->type = info->local & 0xff; + tgui_t *tgui = malloc(sizeof(tgui_t)); + svga_t *svga = &tgui->svga; + memset(tgui, 0, sizeof(tgui_t)); - tgui->pci = !!(info->flags & DEVICE_PCI); + tgui->vram_size = device_get_config_int("memory") << 20; + tgui->vram_mask = tgui->vram_size - 1; - switch(tgui->type) { - case TGUI_9400CXI: - bios_fn = ROM_TGUI_9400CXI; - break; - case TGUI_9440: - bios_fn = (info->local & ONBOARD) ? NULL : ROM_TGUI_9440; - break; - case TGUI_9660: - case TGUI_9680: - bios_fn = ROM_TGUI_96xx; - break; - default: - free(tgui); - return NULL; - } + tgui->type = info->local & 0xff; - tgui->has_bios = (bios_fn != NULL); + tgui->pci = !!(info->flags & DEVICE_PCI); - if (tgui->has_bios) - rom_init(&tgui->bios_rom, (char *) bios_fn, 0xc0000, 0x8000, 0x7fff, 0, MEM_MAPPING_EXTERNAL); + switch (tgui->type) { + case TGUI_9400CXI: + bios_fn = ROM_TGUI_9400CXI; + break; + case TGUI_9440: + bios_fn = (info->local & ONBOARD) ? NULL : ROM_TGUI_9440; + break; + case TGUI_9660: + case TGUI_9680: + bios_fn = ROM_TGUI_96xx; + break; + default: + free(tgui); + return NULL; + } - if (tgui->pci) - video_inform(VIDEO_FLAG_TYPE_SPECIAL, &timing_tgui_pci); - else - video_inform(VIDEO_FLAG_TYPE_SPECIAL, &timing_tgui_vlb); + tgui->has_bios = (bios_fn != NULL); - svga_init(info, svga, tgui, tgui->vram_size, - tgui_recalctimings, - tgui_in, tgui_out, - tgui_hwcursor_draw, - NULL); + if (tgui->has_bios) { + rom_init(&tgui->bios_rom, bios_fn, 0xc0000, 0x8000, 0x7fff, 0, MEM_MAPPING_EXTERNAL); + if (tgui->pci) + mem_mapping_disable(&tgui->bios_rom.mapping); + } - if (tgui->type == TGUI_9400CXI) - svga->ramdac = device_add(&tkd8001_ramdac_device); + if (tgui->pci) + video_inform(VIDEO_FLAG_TYPE_SPECIAL, &timing_tgui_pci); + else + video_inform(VIDEO_FLAG_TYPE_SPECIAL, &timing_tgui_vlb); - mem_mapping_add(&tgui->linear_mapping, 0, 0, svga_read_linear, svga_readw_linear, svga_readl_linear, tgui_accel_write_fb_b, tgui_accel_write_fb_w, tgui_accel_write_fb_l, NULL, MEM_MAPPING_EXTERNAL, svga); - mem_mapping_add(&tgui->accel_mapping, 0, 0, tgui_accel_read, tgui_accel_read_w, tgui_accel_read_l, tgui_accel_write, tgui_accel_write_w, tgui_accel_write_l, NULL, MEM_MAPPING_EXTERNAL, tgui); - if (tgui->type >= TGUI_9440) - mem_mapping_add(&tgui->mmio_mapping, 0, 0, tgui_mmio_read, tgui_mmio_read_w, tgui_mmio_read_l, tgui_mmio_write, tgui_mmio_write_w, tgui_mmio_write_l, NULL, MEM_MAPPING_EXTERNAL, tgui); - mem_mapping_disable(&tgui->accel_mapping); - mem_mapping_disable(&tgui->mmio_mapping); + svga_init(info, svga, tgui, tgui->vram_size, + tgui_recalctimings, + tgui_in, tgui_out, + tgui_hwcursor_draw, + NULL); - tgui_set_io(tgui); + if (tgui->type == TGUI_9400CXI) + svga->ramdac = device_add(&tkd8001_ramdac_device); - if (tgui->pci && (tgui->type >= TGUI_9440)) { - if (tgui->has_bios) - tgui->card = pci_add_card(PCI_ADD_VIDEO, tgui_pci_read, tgui_pci_write, tgui); - else - tgui->card = pci_add_card(PCI_ADD_VIDEO | PCI_ADD_STRICT, tgui_pci_read, tgui_pci_write, tgui); - } + mem_mapping_add(&tgui->linear_mapping, 0, 0, svga_read_linear, svga_readw_linear, svga_readl_linear, tgui_accel_write_fb_b, tgui_accel_write_fb_w, tgui_accel_write_fb_l, NULL, MEM_MAPPING_EXTERNAL, svga); + mem_mapping_add(&tgui->accel_mapping, 0, 0, tgui_accel_read, tgui_accel_read_w, tgui_accel_read_l, tgui_accel_write, tgui_accel_write_w, tgui_accel_write_l, NULL, MEM_MAPPING_EXTERNAL, tgui); + if (tgui->type >= TGUI_9440) + mem_mapping_add(&tgui->mmio_mapping, 0, 0, tgui_mmio_read, tgui_mmio_read_w, tgui_mmio_read_l, tgui_mmio_write, tgui_mmio_write_w, tgui_mmio_write_l, NULL, MEM_MAPPING_EXTERNAL, tgui); + mem_mapping_disable(&tgui->accel_mapping); + mem_mapping_disable(&tgui->mmio_mapping); - tgui->pci_regs[PCI_REG_COMMAND] = 7; + if (tgui->vram_size == (2 << 20)) + svga->crtc[0x21] |= 0x10; - if (tgui->has_bios) { - tgui->pci_regs[0x30] = 0x00; - tgui->pci_regs[0x32] = 0x0c; - tgui->pci_regs[0x33] = 0x00; - } + tgui_set_io(tgui); - if (tgui->type >= TGUI_9440) { - svga->packed_chain4 = 1; + if (tgui->pci && (tgui->type >= TGUI_9440)) { + if (tgui->has_bios) + pci_add_card(PCI_ADD_NORMAL, tgui_pci_read, tgui_pci_write, tgui, &tgui->pci_slot); + else + pci_add_card(PCI_ADD_VIDEO | PCI_ADD_STRICT, tgui_pci_read, tgui_pci_write, tgui, &tgui->pci_slot); + } - tgui->i2c = i2c_gpio_init("ddc_tgui"); - tgui->ddc = ddc_init(i2c_gpio_get_bus(tgui->i2c)); - } + tgui->pci_regs[PCI_REG_COMMAND] = 7; - return tgui; + if (tgui->has_bios) { + tgui->pci_regs[0x30] = 0x00; + tgui->pci_regs[0x32] = 0x0c; + tgui->pci_regs[0x33] = 0x00; + } + + if (tgui->type >= TGUI_9440) { + svga->packed_chain4 = 1; + + tgui->i2c = i2c_gpio_init("ddc_tgui"); + tgui->ddc = ddc_init(i2c_gpio_get_bus(tgui->i2c)); + } + + return tgui; } -static int tgui9400cxi_available(void) +static int +tgui9400cxi_available(void) { - return rom_present(ROM_TGUI_9400CXI); + return rom_present(ROM_TGUI_9400CXI); } -static int tgui9440_available(void) +static int +tgui9440_available(void) { - return rom_present(ROM_TGUI_9440); + return rom_present(ROM_TGUI_9440); } -static int tgui96xx_available(void) +static int +tgui96xx_available(void) { - return rom_present(ROM_TGUI_96xx); + return rom_present(ROM_TGUI_96xx); } -void tgui_close(void *p) +void +tgui_close(void *priv) { - tgui_t *tgui = (tgui_t *)p; - - svga_close(&tgui->svga); + tgui_t *tgui = (tgui_t *) priv; + svga_close(&tgui->svga); + + if (tgui->type >= TGUI_9440) { ddc_close(tgui->ddc); i2c_gpio_close(tgui->i2c); + } - free(tgui); + free(tgui); } -void tgui_speed_changed(void *p) +void +tgui_speed_changed(void *priv) { - tgui_t *tgui = (tgui_t *)p; - - svga_recalctimings(&tgui->svga); + tgui_t *tgui = (tgui_t *) priv; + + svga_recalctimings(&tgui->svga); } -void tgui_force_redraw(void *p) +void +tgui_force_redraw(void *priv) { - tgui_t *tgui = (tgui_t *)p; + tgui_t *tgui = (tgui_t *) priv; - tgui->svga.fullchange = changeframecount; + tgui->svga.fullchange = tgui->svga.monitor->mon_changeframecount; } - -static const device_config_t tgui9440_config[] = -{ - { - .name = "memory", - .description = "Memory size", - .type = CONFIG_SELECTION, - .selection = - { - { - .description = "1 MB", - .value = 1 - }, - { - .description = "2 MB", - .value = 2 - }, - { - .description = "" - } - }, - .default_int = 2 +// clang-format off +static const device_config_t tgui9440_config[] = { + { + .name = "memory", + .description = "Memory size", + .type = CONFIG_SELECTION, + .selection = { + { + .description = "1 MB", + .value = 1 + }, + { + .description = "2 MB", + .value = 2 + }, + { + .description = "" + } }, - { - .type = -1 - } + .default_int = 2 + }, + { + .type = CONFIG_END + } }; -static const device_config_t tgui96xx_config[] = -{ - { - .name = "memory", - .description = "Memory size", - .type = CONFIG_SELECTION, - .selection = - { - { - .description = "1 MB", - .value = 1 - }, - { - .description = "2 MB", - .value = 2 - }, - { - .description = "4 MB", - .value = 4 - }, - { - .description = "" - } - }, - .default_int = 4 +static const device_config_t tgui96xx_config[] = { + { + .name = "memory", + .description = "Memory size", + .type = CONFIG_SELECTION, + .selection = { + { + .description = "1 MB", + .value = 1 + }, + { + .description = "2 MB", + .value = 2 + }, + { + .description = "4 MB", + .value = 4 + }, + { + .description = "" + } }, - { - .type = -1 - } + .default_int = 4 + }, + { + .type = CONFIG_END + } +}; +// clang-format on + +const device_t tgui9400cxi_device = { + .name = "Trident TGUI 9400CXi", + .internal_name = "tgui9400cxi_vlb", + .flags = DEVICE_VLB, + .local = TGUI_9400CXI, + .init = tgui_init, + .close = tgui_close, + .reset = NULL, + { .available = tgui9400cxi_available }, + .speed_changed = tgui_speed_changed, + .force_redraw = tgui_force_redraw, + .config = tgui9440_config }; -const device_t tgui9400cxi_device = -{ - "Trident TGUI 9400CXi", - "tgui9400cxi_vlb", - DEVICE_VLB, - TGUI_9400CXI, - tgui_init, - tgui_close, - NULL, - { tgui9400cxi_available }, - tgui_speed_changed, - tgui_force_redraw, - tgui9440_config +const device_t tgui9440_vlb_device = { + .name = "Trident TGUI 9440AGi VLB", + .internal_name = "tgui9440_vlb", + .flags = DEVICE_VLB, + .local = TGUI_9440, + .init = tgui_init, + .close = tgui_close, + .reset = NULL, + { .available = tgui9440_available }, + .speed_changed = tgui_speed_changed, + .force_redraw = tgui_force_redraw, + .config = tgui9440_config }; -const device_t tgui9440_vlb_device = -{ - "Trident TGUI 9440AGi VLB", - "tgui9440_vlb", - DEVICE_VLB, - TGUI_9440, - tgui_init, - tgui_close, - NULL, - { tgui9440_available }, - tgui_speed_changed, - tgui_force_redraw, - tgui9440_config +const device_t tgui9440_pci_device = { + .name = "Trident TGUI 9440AGi PCI", + .internal_name = "tgui9440_pci", + .flags = DEVICE_PCI, + .local = TGUI_9440, + .init = tgui_init, + .close = tgui_close, + .reset = NULL, + { .available = tgui9440_available }, + .speed_changed = tgui_speed_changed, + .force_redraw = tgui_force_redraw, + .config = tgui9440_config }; -const device_t tgui9440_pci_device = -{ - "Trident TGUI 9440AGi PCI", - "tgui9440_pci", - DEVICE_PCI, - TGUI_9440, - tgui_init, - tgui_close, - NULL, - { tgui9440_available }, - tgui_speed_changed, - tgui_force_redraw, - tgui9440_config +const device_t tgui9440_onboard_pci_device = { + .name = "Trident TGUI 9440AGi On-Board PCI", + .internal_name = "tgui9440_onboard_pci", + .flags = DEVICE_PCI, + .local = TGUI_9440 | ONBOARD, + .init = tgui_init, + .close = tgui_close, + .reset = NULL, + { .available = NULL }, + .speed_changed = tgui_speed_changed, + .force_redraw = tgui_force_redraw, + .config = tgui9440_config }; -const device_t tgui9440_onboard_pci_device = -{ - "Trident TGUI 9440AGi On-Board PCI", - "tgui9440_onboard_pci", - DEVICE_PCI, - TGUI_9440 | ONBOARD, - tgui_init, - tgui_close, - NULL, - { NULL }, - tgui_speed_changed, - tgui_force_redraw, - tgui9440_config +const device_t tgui9660_pci_device = { + .name = "Trident TGUI 9660XGi PCI", + .internal_name = "tgui9660_pci", + .flags = DEVICE_PCI, + .local = TGUI_9660, + .init = tgui_init, + .close = tgui_close, + .reset = NULL, + { .available = tgui96xx_available }, + .speed_changed = tgui_speed_changed, + .force_redraw = tgui_force_redraw, + .config = tgui96xx_config }; -const device_t tgui9660_pci_device = -{ - "Trident TGUI 9660XGi PCI", - "tgui9660_pci", - DEVICE_PCI, - TGUI_9660, - tgui_init, - tgui_close, - NULL, - { tgui96xx_available }, - tgui_speed_changed, - tgui_force_redraw, - tgui96xx_config -}; - -const device_t tgui9680_pci_device = -{ - "Trident TGUI 9680XGi PCI", - "tgui9680_pci", - DEVICE_PCI, - TGUI_9680, - tgui_init, - tgui_close, - NULL, - { tgui96xx_available }, - tgui_speed_changed, - tgui_force_redraw, - tgui96xx_config +const device_t tgui9680_pci_device = { + .name = "Trident TGUI 9680XGi PCI", + .internal_name = "tgui9680_pci", + .flags = DEVICE_PCI, + .local = TGUI_9680, + .init = tgui_init, + .close = tgui_close, + .reset = NULL, + { .available = tgui96xx_available }, + .speed_changed = tgui_speed_changed, + .force_redraw = tgui_force_redraw, + .config = tgui96xx_config }; diff --git a/src/video/vid_ti_cf62011.c b/src/video/vid_ti_cf62011.c index f9f499ce1..f23cb7396 100644 --- a/src/video/vid_ti_cf62011.c +++ b/src/video/vid_ti_cf62011.c @@ -1,56 +1,56 @@ -/* - * 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. +/* + * 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. + * This file is part of the 86Box distribution. * - * Emulation of the TI CF62011 SVGA chip. + * Emulation of the TI CF62011 SVGA chip. * - * This chip was used in several of IBM's later machines, such - * as the PS/1 Model 2121, and a number of PS/2 models. As noted - * in an article on Usenet: + * This chip was used in several of IBM's later machines, such + * as the PS/1 Model 2121, and a number of PS/2 models. As noted + * in an article on Usenet: * - * "In the early 90s IBM looked for some cheap VGA card to - * substitute the (relatively) expensive XGA-2 adapter for - * *servers*, where the primary purpose is supervision of the - * machine rather than real *work* with it in Hi-Res. It was - * just to supply a base video, where a XGA-2 were a waste of - * potential. They had a contract with TI for some DSPs in - * multimedia already (the MWave for instance is based on - * TI-DSPs as well as many Thinkpad internal chipsets) and TI - * offered them a rather cheap – and inexpensive – chipset - * and combined it with a cheap clock oscillator and an Inmos - * RAMDAC. That chipset was already pretty much outdated at - * that time but IBM decided it would suffice for that low - * end purpose. + * "In the early 90s IBM looked for some cheap VGA card to + * substitute the (relatively) expensive XGA-2 adapter for + * *servers*, where the primary purpose is supervision of the + * machine rather than real *work* with it in Hi-Res. It was + * just to supply a base video, where a XGA-2 were a waste of + * potential. They had a contract with TI for some DSPs in + * multimedia already (the MWave for instance is based on + * TI-DSPs as well as many Thinkpad internal chipsets) and TI + * offered them a rather cheap – and inexpensive – chipset + * and combined it with a cheap clock oscillator and an Inmos + * RAMDAC. That chipset was already pretty much outdated at + * that time but IBM decided it would suffice for that low + * end purpose. * - * Driver support was given under DOS and OS/2 only for base - * functions like selection of the vertical refresh and few - * different modes only. Not even the Win 3.x support has - * been finalized. Technically the adapter could do better - * than VGA, but its video BIOS is largely undocumented and - * intentionally crippled down to a few functions." + * Driver support was given under DOS and OS/2 only for base + * functions like selection of the vertical refresh and few + * different modes only. Not even the Win 3.x support has + * been finalized. Technically the adapter could do better + * than VGA, but its video BIOS is largely undocumented and + * intentionally crippled down to a few functions." * - * This chip is reportedly the same one as used in the MCA - * IBM SVGA Adapter/A (ID 090EEh), which mostly had faster - * VRAM and RAMDAC. The VESA DOS graphics driver for that - * card can be used: m95svga.exe + * This chip is reportedly the same one as used in the MCA + * IBM SVGA Adapter/A (ID 090EEh), which mostly had faster + * VRAM and RAMDAC. The VESA DOS graphics driver for that + * card can be used: m95svga.exe * - * The controller responds at ports in the range 0x2100-0x210F, - * which are the same as the XGA. It supports up to 1MB of VRAM, - * but we lock it down to 512K. The PS/1 2122 had 256K. + * The controller responds at ports in the range 0x2100-0x210F, + * which are the same as the XGA. It supports up to 1MB of VRAM, + * but we lock it down to 512K. The PS/1 2122 had 256K. * * * - * Authors: Sarah Walker, - * Miran Grca, - * Fred N. van Kempen, + * Authors: Sarah Walker, + * Miran Grca, + * Fred N. van Kempen, * - * Copyright 2008-2018 Sarah Walker. - * Copyright 2016-2018 Miran Grca. - * Copyright 2017,2018 Fred N. van Kempen. + * Copyright 2008-2018 Sarah Walker. + * Copyright 2016-2018 Miran Grca. + * Copyright 2017-2018 Fred N. van Kempen. */ #include #include @@ -66,211 +66,208 @@ #include <86box/video.h> #include <86box/vid_svga.h> - typedef struct { - svga_t svga; + svga_t svga; - rom_t bios_rom; + rom_t bios_rom; - int enabled; + int enabled; - uint32_t vram_size; + uint32_t vram_size; - uint8_t banking; - uint8_t reg_2100; - uint8_t reg_210a; + uint8_t banking; + uint8_t reg_2100; + uint8_t reg_210a; } tivga_t; -static video_timings_t timing_ti_cf62011 = {VIDEO_ISA, 6, 8,16, 6, 8,16}; - +static video_timings_t timing_ti_cf62011 = { .type = VIDEO_ISA, .write_b = 6, .write_w = 8, .write_l = 16, .read_b = 6, .read_w = 8, .read_l = 16 }; static void vid_out(uint16_t addr, uint8_t val, void *priv) { - tivga_t *ti = (tivga_t *)priv; - svga_t *svga = &ti->svga; - uint8_t old; + tivga_t *ti = (tivga_t *) priv; + svga_t *svga = &ti->svga; + uint8_t old; #if 0 if (((addr & 0xfff0) == 0x03d0 || (addr & 0xfff0) == 0x03b0) && - !(svga->miscout & 1)) addr ^= 0x60; + !(svga->miscout & 1)) addr ^= 0x60; #endif switch (addr) { - case 0x0102: - ti->enabled = (val & 0x01); - return; + case 0x0102: + ti->enabled = (val & 0x01); + return; - case 0x03d4: - svga->crtcreg = val & 0x3f; - return; + case 0x03d4: + svga->crtcreg = val & 0x3f; + return; - case 0x03d5: - 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) { - svga->fullchange = changeframecount; - svga_recalctimings(svga); - } - } - break; + case 0x03d5: + 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) { + svga->fullchange = changeframecount; + svga_recalctimings(svga); + } + } + break; - case 0x2100: - ti->reg_2100 = val; - if ((val & 7) < 4) - svga->read_bank = svga->write_bank = 0; - else - svga->read_bank = svga->write_bank = (ti->banking & 0x7) * 0x10000; - break; + case 0x2100: + ti->reg_2100 = val; + if ((val & 7) < 4) + svga->read_bank = svga->write_bank = 0; + else + svga->read_bank = svga->write_bank = (ti->banking & 0x7) * 0x10000; + break; - case 0x2108: - if ((ti->reg_2100 & 7) >= 4) - svga->read_bank = svga->write_bank = (val & 0x7) * 0x10000; - ti->banking = val; - break; + case 0x2108: + if ((ti->reg_2100 & 7) >= 4) + svga->read_bank = svga->write_bank = (val & 0x7) * 0x10000; + ti->banking = val; + break; - case 0x210a: - ti->reg_210a = val; - break; + case 0x210a: + ti->reg_210a = val; + break; + + default: + break; } svga_out(addr, val, svga); } - static uint8_t vid_in(uint16_t addr, void *priv) { - tivga_t *ti = (tivga_t *)priv; - svga_t *svga = &ti->svga; - uint8_t ret; + tivga_t *ti = (tivga_t *) priv; + svga_t *svga = &ti->svga; + uint8_t ret; #if 0 if (((addr & 0xfff0) == 0x03d0 || (addr & 0xfff0) == 0x03b0) && - !(svga->miscout & 1)) addr ^= 0x60; + !(svga->miscout & 1)) addr ^= 0x60; #endif switch (addr) { - case 0x0100: - ret = 0xfe; - break; + case 0x0100: + ret = 0xfe; + break; - case 0x0101: - ret = 0xe8; - break; + case 0x0101: + ret = 0xe8; + break; - case 0x0102: - ret = ti->enabled; - break; + case 0x0102: + ret = ti->enabled; + break; - case 0x03d4: - ret = svga->crtcreg; - break; + case 0x03d4: + ret = svga->crtcreg; + break; - case 0x03d5: - if (svga->crtcreg & 0x20) - ret = 0xff; - else - ret = svga->crtc[svga->crtcreg]; - break; + case 0x03d5: + if (svga->crtcreg & 0x20) + ret = 0xff; + else + ret = svga->crtc[svga->crtcreg]; + break; - case 0x2100: - ret = ti->reg_2100; - break; + case 0x2100: + ret = ti->reg_2100; + break; - case 0x2108: - ret = ti->banking; - break; + case 0x2108: + ret = ti->banking; + break; - case 0x210a: - ret = ti->reg_210a; - break; + case 0x210a: + ret = ti->reg_210a; + break; - default: - ret = svga_in(addr, svga); - break; + default: + ret = svga_in(addr, svga); + break; } - return(ret); + return ret; } - static void vid_speed_changed(void *priv) { - tivga_t *ti = (tivga_t *)priv; + tivga_t *ti = (tivga_t *) priv; svga_recalctimings(&ti->svga); } - static void vid_force_redraw(void *priv) { - tivga_t *ti = (tivga_t *)priv; + tivga_t *ti = (tivga_t *) priv; ti->svga.fullchange = changeframecount; } - static void vid_close(void *priv) { - tivga_t *ti = (tivga_t *)priv; + tivga_t *ti = (tivga_t *) priv; svga_close(&ti->svga); free(ti); } - static void * vid_init(const device_t *info) { tivga_t *ti; /* Allocate control block and initialize. */ - ti = (tivga_t *)malloc(sizeof(tivga_t)); + ti = (tivga_t *) malloc(sizeof(tivga_t)); memset(ti, 0x00, sizeof(tivga_t)); /* Set amount of VRAM in KB. */ if (info->local == 0) - ti->vram_size = device_get_config_int("vram_size"); + ti->vram_size = device_get_config_int("vram_size"); else - ti->vram_size = info->local; + ti->vram_size = info->local; video_inform(VIDEO_FLAG_TYPE_SPECIAL, &timing_ti_cf62011); svga_init(info, &ti->svga, ti, - ti->vram_size<<10, - NULL, vid_in, vid_out, NULL, NULL); + ti->vram_size << 10, + NULL, vid_in, vid_out, NULL, NULL); io_sethandler(0x0100, 2, vid_in, NULL, NULL, NULL, NULL, NULL, ti); io_sethandler(0x03c0, 32, vid_in, NULL, NULL, vid_out, NULL, NULL, ti); io_sethandler(0x2100, 16, vid_in, NULL, NULL, vid_out, NULL, NULL, ti); - ti->svga.bpp = 8; + ti->svga.bpp = 8; ti->svga.miscout = 1; - return(ti); + return ti; } - const device_t ibm_ps1_2121_device = { - "IBM PS/1 Model 2121 SVGA", - "ibm_ps1_2121", - DEVICE_ISA, - 512, - vid_init, vid_close, NULL, - { NULL }, - vid_speed_changed, - vid_force_redraw, - NULL + .name = "IBM PS/1 Model 2121 SVGA", + .internal_name = "ibm_ps1_2121", + .flags = DEVICE_ISA, + .local = 512, + .init = vid_init, + .close = vid_close, + .reset = NULL, + { .available = NULL }, + .speed_changed = vid_speed_changed, + .force_redraw = vid_force_redraw, + .config = NULL }; diff --git a/src/video/vid_tkd8001_ramdac.c b/src/video/vid_tkd8001_ramdac.c index f11319eeb..4108b9a4e 100644 --- a/src/video/vid_tkd8001_ramdac.c +++ b/src/video/vid_tkd8001_ramdac.c @@ -1,20 +1,20 @@ /* - * 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. + * 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. + * This file is part of the 86Box distribution. * - * Trident TKD8001 RAMDAC emulation. + * Trident TKD8001 RAMDAC emulation. * * * - * Authors: Sarah Walker, - * Miran Grca, + * Authors: Sarah Walker, + * Miran Grca, * - * Copyright 2008-2018 Sarah Walker. - * Copyright 2016-2018 Miran Grca. + * Copyright 2008-2018 Sarah Walker. + * Copyright 2016-2018 Miran Grca. */ #include #include @@ -27,79 +27,84 @@ #include <86box/mem.h> #include <86box/video.h> #include <86box/vid_svga.h> +#include <86box/plat_unused.h> - -typedef struct tkd8001_ramdac_t -{ - int state; +typedef struct tkd8001_ramdac_t { + int state; uint8_t ctrl; } tkd8001_ramdac_t; - void -tkd8001_ramdac_out(uint16_t addr, uint8_t val, void *p, svga_t *svga) +tkd8001_ramdac_out(uint16_t addr, uint8_t val, void *priv, svga_t *svga) { - tkd8001_ramdac_t *ramdac = (tkd8001_ramdac_t *) p; + tkd8001_ramdac_t *ramdac = (tkd8001_ramdac_t *) priv; switch (addr) { - case 0x3C6: - if (ramdac->state == 4) { - ramdac->state = 0; - ramdac->ctrl = val; - switch (val >> 5) { - case 0: - case 1: - case 2: - case 3: - svga->bpp = 8; - break; - case 5: - svga->bpp = 15; - break; - case 6: - svga->bpp = 24; - break; - case 7: - svga->bpp = 16; - break; - } - return; - } - break; - case 0x3C7: - case 0x3C8: - case 0x3C9: - ramdac->state = 0; - break; + case 0x3C6: + if (ramdac->state == 4) { + ramdac->state = 0; + ramdac->ctrl = val; + switch (val >> 5) { + case 0: + case 1: + case 2: + case 3: + svga->bpp = 8; + break; + case 5: + svga->bpp = 15; + break; + case 6: + svga->bpp = 24; + break; + case 7: + svga->bpp = 16; + break; + + default: + break; + } + return; + } + break; + case 0x3C7: + case 0x3C8: + case 0x3C9: + ramdac->state = 0; + break; + + default: + break; } svga_out(addr, val, svga); } - uint8_t -tkd8001_ramdac_in(uint16_t addr, void *p, svga_t *svga) +tkd8001_ramdac_in(uint16_t addr, void *priv, svga_t *svga) { - tkd8001_ramdac_t *ramdac = (tkd8001_ramdac_t *) p; + tkd8001_ramdac_t *ramdac = (tkd8001_ramdac_t *) priv; switch (addr) { - case 0x3C6: - if (ramdac->state == 4) - return ramdac->ctrl; - ramdac->state++; - break; - case 0x3C7: - case 0x3C8: - case 0x3C9: - ramdac->state = 0; - break; + case 0x3C6: + if (ramdac->state == 4) + return ramdac->ctrl; + ramdac->state++; + break; + case 0x3C7: + case 0x3C8: + case 0x3C9: + ramdac->state = 0; + break; + + default: + break; } return svga_in(addr, svga); } - static void * -tkd8001_ramdac_init(const device_t *info) +tkd8001_ramdac_init(UNUSED(const device_t *info)) { tkd8001_ramdac_t *ramdac = (tkd8001_ramdac_t *) malloc(sizeof(tkd8001_ramdac_t)); memset(ramdac, 0, sizeof(tkd8001_ramdac_t)); @@ -107,22 +112,25 @@ tkd8001_ramdac_init(const device_t *info) return ramdac; } - static void tkd8001_ramdac_close(void *priv) { tkd8001_ramdac_t *ramdac = (tkd8001_ramdac_t *) priv; if (ramdac) - free(ramdac); + free(ramdac); } - -const device_t tkd8001_ramdac_device = -{ - "Trident TKD8001 RAMDAC", - "tkd8001_ramdac", - 0, 0, - tkd8001_ramdac_init, tkd8001_ramdac_close, - NULL, { NULL }, NULL, NULL +const device_t tkd8001_ramdac_device = { + .name = "Trident TKD8001 RAMDAC", + .internal_name = "tkd8001_ramdac", + .flags = 0, + .local = 0, + .init = tkd8001_ramdac_init, + .close = tkd8001_ramdac_close, + .reset = NULL, + { .available = NULL }, + .speed_changed = NULL, + .force_redraw = NULL, + .config = NULL }; diff --git a/src/video/vid_tvga.c b/src/video/vid_tvga.c index 55dccf9c6..591851016 100644 --- a/src/video/vid_tvga.c +++ b/src/video/vid_tvga.c @@ -1,20 +1,20 @@ /* - * 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. + * 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. + * This file is part of the 86Box distribution. * - * Trident TVGA (8900D) emulation. + * Trident TVGA (8900D) emulation. * * * - * Authors: Sarah Walker, - * Miran Grca, + * Authors: Sarah Walker, + * Miran Grca, * - * Copyright 2008-2018 Sarah Walker. - * Copyright 2016-2018 Miran Grca. + * Copyright 2008-2018 Sarah Walker. + * Copyright 2016-2018 Miran Grca. */ #include #include @@ -31,484 +31,563 @@ #include <86box/vid_svga.h> #include <86box/vid_svga_render.h> -#define TVGA8900B_ID 0x03 -#define TVGA9000B_ID 0x23 -#define TVGA8900CLD_ID 0x33 +#define TVGA8900B_ID 0x03 +#define TVGA9000B_ID 0x23 +#define TVGA8900CLD_ID 0x33 -#define ROM_TVGA_8900B "roms/video/tvga/tvga8900b.vbi" -#define ROM_TVGA_8900CLD "roms/video/tvga/trident.bin" -#define ROM_TVGA_9000B "roms/video/tvga/tvga9000b.bin" +#define ROM_TVGA_8900B "roms/video/tvga/tvga8900b.vbi" +#define ROM_TVGA_8900CLD "roms/video/tvga/trident.bin" +#define ROM_TVGA_9000B "roms/video/tvga/tvga9000b.bin" +#define ROM_TVGA_9000B_NEC_SV9000 "roms/video/tvga/SV9000.VBI" -typedef struct tvga_t -{ - mem_mapping_t linear_mapping; - mem_mapping_t accel_mapping; +typedef struct tvga_t { + mem_mapping_t linear_mapping; + mem_mapping_t accel_mapping; - svga_t svga; + svga_t svga; - rom_t bios_rom; - uint8_t card_id; + rom_t bios_rom; + uint8_t card_id; - uint8_t tvga_3d8, tvga_3d9; - int oldmode; - uint8_t oldctrl1; - uint8_t oldctrl2, newctrl2; - - int vram_size; - uint32_t vram_mask; + uint8_t tvga_3d8, tvga_3d9; + int oldmode; + uint8_t oldctrl1; + uint8_t oldctrl2, newctrl2; + + int vram_size; + uint32_t vram_mask; } tvga_t; -video_timings_t timing_tvga8900 = {VIDEO_ISA, 3, 3, 6, 8, 8, 12}; -video_timings_t timing_tvga9000 = {VIDEO_ISA, 7, 7, 12, 7, 7, 12}; +video_timings_t timing_tvga8900 = { .type = VIDEO_ISA, .write_b = 3, .write_w = 3, .write_l = 6, .read_b = 8, .read_w = 8, .read_l = 12 }; +video_timings_t timing_tvga9000 = { .type = VIDEO_ISA, .write_b = 7, .write_w = 7, .write_l = 12, .read_b = 7, .read_w = 7, .read_l = 12 }; -static uint8_t crtc_mask[0x40] = -{ - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0x7f, 0xff, 0x3f, 0x7f, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0x7f, 0xff, 0xff, 0xef, - 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, - 0x7f, 0x00, 0x00, 0x2f, 0x00, 0x00, 0x00, 0x03, - 0x00, 0x13, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 +static uint8_t crtc_mask[0x40] = { + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0x7f, 0xff, 0x3f, 0x7f, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0x7f, 0xff, 0xff, 0xef, + 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, + 0x7f, 0x00, 0x00, 0x2f, 0x00, 0x00, 0x00, 0x03, + 0x00, 0x13, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }; static void tvga_recalcbanking(tvga_t *tvga); -void tvga_out(uint16_t addr, uint8_t val, void *p) +void +tvga_out(uint16_t addr, uint8_t val, void *priv) { - tvga_t *tvga = (tvga_t *)p; - svga_t *svga = &tvga->svga; + tvga_t *tvga = (tvga_t *) priv; + svga_t *svga = &tvga->svga; - uint8_t old; + uint8_t old; - if (((addr&0xFFF0) == 0x3D0 || (addr&0xFFF0) == 0x3B0) && !(svga->miscout & 1)) addr ^= 0x60; + if (((addr & 0xFFF0) == 0x3D0 || (addr & 0xFFF0) == 0x3B0) && !(svga->miscout & 1)) + addr ^= 0x60; - switch (addr) - { - case 0x3C5: - switch (svga->seqaddr & 0xf) - { - case 0xB: - tvga->oldmode=1; - break; - case 0xC: - if (svga->seqregs[0xe] & 0x80) - svga->seqregs[0xc] = val; - break; - case 0xd: - if (tvga->oldmode) - tvga->oldctrl2 = val; - else - { - tvga->newctrl2 = val; - svga_recalctimings(svga); - } - break; - case 0xE: - if (tvga->oldmode) - tvga->oldctrl1 = val; - else - { - svga->seqregs[0xe] = val ^ 2; - tvga->tvga_3d8 = svga->seqregs[0xe] & 0xf; - tvga_recalcbanking(tvga); - } - return; - } - break; - - case 0x3C6: case 0x3C7: case 0x3C8: case 0x3C9: - if (tvga->card_id != TVGA9000B_ID) { - tkd8001_ramdac_out(addr, val, svga->ramdac, svga); - return; - } - break; - - case 0x3CF: - switch (svga->gdcaddr & 15) - { - case 0x6: - old = svga->gdcreg[6]; - svga_out(addr, val, svga); - if ((old & 0xc) != 0 && (val & 0xc) == 0) - { - /*override mask - TVGA supports linear 128k at A0000*/ - svga->banked_mask = 0x1ffff; - } - return; - case 0xE: - svga->gdcreg[0xe] = val ^ 2; - tvga->tvga_3d9 = svga->gdcreg[0xe] & 0xf; - tvga_recalcbanking(tvga); - break; - case 0xF: - svga->gdcreg[0xf] = val; - tvga_recalcbanking(tvga); - break; - } - 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]; - val &= crtc_mask[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); - } - } - } - switch (svga->crtcreg) { - case 0x1e: - svga->vram_display_mask = (val & 0x80) ? tvga->vram_mask : 0x3ffff; - break; - } - return; - case 0x3D8: - if (svga->gdcreg[0xf] & 4) { - tvga->tvga_3d8 = val; - tvga_recalcbanking(tvga); - } - return; - case 0x3D9: - if (svga->gdcreg[0xf] & 4) { - tvga->tvga_3d9 = val; - tvga_recalcbanking(tvga); - } - return; - case 0x3DB: - if (tvga->card_id != TVGA9000B_ID) { - /*3db appears to be a 4 bit clock select register on 8900D*/ - svga->miscout = (svga->miscout & ~0x0c) | ((val & 3) << 2); - tvga->newctrl2 = (tvga->newctrl2 & ~0x01) | ((val & 4) >> 2); - tvga->oldctrl1 = (tvga->oldctrl1 & ~0x10) | ((val & 8) << 1); + switch (addr) { + case 0x3C5: + switch (svga->seqaddr & 0xf) { + case 0xB: + tvga->oldmode = 1; + break; + case 0xC: + if (svga->seqregs[0xe] & 0x80) + svga->seqregs[0xc] = val; + break; + case 0xd: + if (tvga->oldmode) + tvga->oldctrl2 = val; + else { + tvga->newctrl2 = val; svga_recalctimings(svga); + } + break; + case 0xE: + if (tvga->oldmode) + tvga->oldctrl1 = val; + else { + svga->seqregs[0xe] = val ^ 2; + tvga->tvga_3d8 = svga->seqregs[0xe] & 0xf; + tvga_recalcbanking(tvga); + } + return; + + default: + break; + } + break; + + case 0x3C6: + case 0x3C7: + case 0x3C8: + case 0x3C9: + if (tvga->card_id != TVGA9000B_ID) { + tkd8001_ramdac_out(addr, val, svga->ramdac, svga); + return; + } + break; + + case 0x3CF: + switch (svga->gdcaddr & 15) { + case 0x6: + old = svga->gdcreg[6]; + svga_out(addr, val, svga); + if ((old & 0xc) != 0 && (val & 0xc) == 0) { + /*override mask - TVGA supports linear 128k at A0000*/ + svga->banked_mask = 0x1ffff; + } + return; + case 0xE: + svga->gdcreg[0xe] = val ^ 2; + tvga->tvga_3d9 = svga->gdcreg[0xe] & 0xf; + tvga_recalcbanking(tvga); + break; + case 0xF: + svga->gdcreg[0xf] = val; + tvga_recalcbanking(tvga); + break; + + default: + break; + } + 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]; + val &= crtc_mask[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); + } + switch (svga->crtcreg) { + case 0x1e: + svga->vram_display_mask = (val & 0x80) ? tvga->vram_mask : 0x3ffff; + break; + + default: + break; + } + return; + case 0x3D8: + if (svga->gdcreg[0xf] & 4) { + tvga->tvga_3d8 = val; + tvga_recalcbanking(tvga); + } + return; + case 0x3D9: + if (svga->gdcreg[0xf] & 4) { + tvga->tvga_3d9 = val; + tvga_recalcbanking(tvga); + } + return; + case 0x3DB: + if (tvga->card_id != TVGA9000B_ID) { + /*3db appears to be a 4 bit clock select register on 8900D*/ + svga->miscout = (svga->miscout & ~0x0c) | ((val & 3) << 2); + tvga->newctrl2 = (tvga->newctrl2 & ~0x01) | ((val & 4) >> 2); + tvga->oldctrl1 = (tvga->oldctrl1 & ~0x10) | ((val & 8) << 1); + svga_recalctimings(svga); + } + break; + + default: + break; + } + svga_out(addr, val, svga); } -uint8_t tvga_in(uint16_t addr, void *p) +uint8_t +tvga_in(uint16_t addr, void *priv) { - tvga_t *tvga = (tvga_t *)p; - svga_t *svga = &tvga->svga; + tvga_t *tvga = (tvga_t *) priv; + svga_t *svga = &tvga->svga; - if (((addr&0xFFF0) == 0x3D0 || (addr&0xFFF0) == 0x3B0) && !(svga->miscout & 1)) addr ^= 0x60; - - switch (addr) - { - case 0x3C5: - if ((svga->seqaddr & 0xf) == 0xb) - { - tvga->oldmode = 0; - return tvga->card_id; /*Must be at least a TVGA8900*/ - } - if ((svga->seqaddr & 0xf) == 0xd) - { - if (tvga->oldmode) return tvga->oldctrl2; - return tvga->newctrl2; - } - if ((svga->seqaddr & 0xf) == 0xe) - { - if (tvga->oldmode) - return tvga->oldctrl1; - } - break; - case 0x3C6: case 0x3C7: case 0x3C8: case 0x3C9: - if (tvga->card_id != TVGA9000B_ID) { - return tkd8001_ramdac_in(addr, svga->ramdac, svga); - } - break; - case 0x3D4: - return svga->crtcreg; - case 0x3D5: - if (svga->crtcreg > 0x18 && svga->crtcreg < 0x1e) - return 0xff; - return svga->crtc[svga->crtcreg]; - case 0x3d8: - return tvga->tvga_3d8; - case 0x3d9: - return tvga->tvga_3d9; - } - return svga_in(addr, svga); + if (((addr & 0xFFF0) == 0x3D0 || (addr & 0xFFF0) == 0x3B0) && !(svga->miscout & 1)) + addr ^= 0x60; + + switch (addr) { + case 0x3C5: + if ((svga->seqaddr & 0xf) == 0xb) { + tvga->oldmode = 0; + return tvga->card_id; /*Must be at least a TVGA8900*/ + } + if ((svga->seqaddr & 0xf) == 0xd) { + if (tvga->oldmode) + return tvga->oldctrl2; + return tvga->newctrl2; + } + if ((svga->seqaddr & 0xf) == 0xe) { + if (tvga->oldmode) + return tvga->oldctrl1; + } + break; + case 0x3C6: + case 0x3C7: + case 0x3C8: + case 0x3C9: + if (tvga->card_id != TVGA9000B_ID) { + return tkd8001_ramdac_in(addr, svga->ramdac, svga); + } + break; + case 0x3D4: + return svga->crtcreg; + case 0x3D5: + if (svga->crtcreg > 0x18 && svga->crtcreg < 0x1e) + return 0xff; + return svga->crtc[svga->crtcreg]; + case 0x3d8: + return tvga->tvga_3d8; + case 0x3d9: + return tvga->tvga_3d9; + + default: + break; + } + return svga_in(addr, svga); } -static void tvga_recalcbanking(tvga_t *tvga) +static void +tvga_recalcbanking(tvga_t *tvga) { - svga_t *svga = &tvga->svga; - - svga->write_bank = (tvga->tvga_3d8 & 0x1f) * 65536; + svga_t *svga = &tvga->svga; - if (svga->gdcreg[0xf] & 1) - svga->read_bank = (tvga->tvga_3d9 & 0x1f) * 65536; - else - svga->read_bank = svga->write_bank; + svga->write_bank = (tvga->tvga_3d8 & 0x1f) * 65536; + + if (svga->gdcreg[0xf] & 1) + svga->read_bank = (tvga->tvga_3d9 & 0x1f) * 65536; + else + svga->read_bank = svga->write_bank; } -void tvga_recalctimings(svga_t *svga) +void +tvga_recalctimings(svga_t *svga) { - tvga_t *tvga = (tvga_t *)svga->p; - int clksel; - int high_res_256 = 0; - - if (!svga->rowoffset) svga->rowoffset = 0x100; /*This is the only sensible way I can see this being handled, - given that TVGA8900D has no overflow bits. - Some sort of overflow is required for 320x200x24 and 1024x768x16*/ - if (svga->crtc[0x29] & 0x10) - svga->rowoffset += 0x100; + const tvga_t *tvga = (tvga_t *) svga->priv; + int clksel; + int high_res_256 = 0; - if (svga->bpp == 24) - svga->hdisp = (svga->crtc[1] + 1) * 8; - - if ((svga->crtc[0x1e] & 0xA0) == 0xA0) svga->ma_latch |= 0x10000; - if ((svga->crtc[0x27] & 0x01) == 0x01) svga->ma_latch |= 0x20000; - if ((svga->crtc[0x27] & 0x02) == 0x02) svga->ma_latch |= 0x40000; - - if (tvga->oldctrl2 & 0x10) - { - svga->rowoffset <<= 1; - svga->ma_latch <<= 1; - } - - if (svga->gdcreg[0xf] & 0x08) - { - svga->htotal *= 2; - svga->hdisp *= 2; - svga->hdisp_time *= 2; - } - - svga->interlace = (svga->crtc[0x1e] & 4); - + if (!svga->rowoffset) + svga->rowoffset = 0x100; /*This is the only sensible way I can see this being handled, + given that TVGA8900D has no overflow bits. + Some sort of overflow is required for 320x200x24 and 1024x768x16*/ + if (svga->crtc[0x29] & 0x10) + svga->rowoffset += 0x100; + + if (svga->bpp == 24) + svga->hdisp = (svga->crtc[1] + 1) * 8; + + if ((svga->crtc[0x1e] & 0xA0) == 0xA0) + svga->ma_latch |= 0x10000; + if ((svga->crtc[0x27] & 0x01) == 0x01) + svga->ma_latch |= 0x20000; + if ((svga->crtc[0x27] & 0x02) == 0x02) + svga->ma_latch |= 0x40000; + + if (tvga->oldctrl2 & 0x10) { + svga->rowoffset <<= 1; + svga->ma_latch <<= 1; + } + + if (svga->gdcreg[0xf] & 0x08) { + svga->htotal *= 2; + svga->hdisp *= 2; + svga->hdisp_time *= 2; + } + + svga->interlace = (svga->crtc[0x1e] & 4); + + if (svga->interlace) + svga->rowoffset >>= 1; + + if (tvga->card_id == TVGA8900CLD_ID) + clksel = ((svga->miscout >> 2) & 3) | ((tvga->newctrl2 & 0x01) << 2) | ((tvga->oldctrl1 & 0x10) >> 1); + else + clksel = ((svga->miscout >> 2) & 3) | ((tvga->newctrl2 & 0x01) << 2) | ((tvga->newctrl2 & 0x40) >> 3); + + switch (clksel) { + case 0x2: + svga->clock = (cpuclock * (double) (1ULL << 32)) / 44900000.0; + break; + case 0x3: + svga->clock = (cpuclock * (double) (1ULL << 32)) / 36000000.0; + break; + case 0x4: + svga->clock = (cpuclock * (double) (1ULL << 32)) / 57272000.0; + break; + case 0x5: + svga->clock = (cpuclock * (double) (1ULL << 32)) / 65000000.0; + break; + case 0x6: + svga->clock = (cpuclock * (double) (1ULL << 32)) / 50350000.0; + break; + case 0x7: + svga->clock = (cpuclock * (double) (1ULL << 32)) / 40000000.0; + break; + case 0x8: + svga->clock = (cpuclock * (double) (1ULL << 32)) / 88000000.0; + break; + case 0x9: + svga->clock = (cpuclock * (double) (1ULL << 32)) / 98000000.0; + break; + case 0xa: + svga->clock = (cpuclock * (double) (1ULL << 32)) / 118800000.0; + break; + case 0xb: + svga->clock = (cpuclock * (double) (1ULL << 32)) / 108000000.0; + break; + case 0xc: + svga->clock = (cpuclock * (double) (1ULL << 32)) / 72000000.0; + break; + case 0xd: + svga->clock = (cpuclock * (double) (1ULL << 32)) / 77000000.0; + break; + case 0xe: + svga->clock = (cpuclock * (double) (1ULL << 32)) / 80000000.0; + break; + case 0xf: + svga->clock = (cpuclock * (double) (1ULL << 32)) / 75000000.0; + break; + + default: + break; + } + + if (tvga->card_id != TVGA8900CLD_ID) { + /*TVGA9000 doesn't seem to have support for a 'high res' 256 colour mode + (without the VGA pixel doubling). Instead it implements these modes by + doubling the horizontal pixel count and pixel clock. Hence we use a + basic heuristic to detect this*/ if (svga->interlace) - svga->rowoffset >>= 1; + high_res_256 = (svga->htotal * 8) > (svga->vtotal * 4); + else + high_res_256 = (svga->htotal * 8) > (svga->vtotal * 2); + } - if (tvga->card_id == TVGA8900CLD_ID) - clksel = ((svga->miscout >> 2) & 3) | ((tvga->newctrl2 & 0x01) << 2) | ((tvga->oldctrl1 & 0x10) >> 1); - else - clksel = ((svga->miscout >> 2) & 3) | ((tvga->newctrl2 & 0x01) << 2) | ((tvga->newctrl2 & 0x40) >> 3); + if ((tvga->oldctrl2 & 0x10) || high_res_256) { + if (high_res_256) + svga->hdisp /= 2; + switch (svga->bpp) { + case 8: + svga->render = svga_render_8bpp_highres; + break; + case 15: + svga->render = svga_render_15bpp_highres; + svga->hdisp /= 2; + break; + case 16: + svga->render = svga_render_16bpp_highres; + svga->hdisp /= 2; + break; + case 24: + svga->render = svga_render_24bpp_highres; + svga->hdisp /= 3; + break; - switch (clksel) { - case 0x2: svga->clock = (cpuclock * (double)(1ull << 32)) / 44900000.0; break; - case 0x3: svga->clock = (cpuclock * (double)(1ull << 32)) / 36000000.0; break; - case 0x4: svga->clock = (cpuclock * (double)(1ull << 32)) / 57272000.0; break; - case 0x5: svga->clock = (cpuclock * (double)(1ull << 32)) / 65000000.0; break; - case 0x6: svga->clock = (cpuclock * (double)(1ull << 32)) / 50350000.0; break; - case 0x7: svga->clock = (cpuclock * (double)(1ull << 32)) / 40000000.0; break; - case 0x8: svga->clock = (cpuclock * (double)(1ull << 32)) / 88000000.0; break; - case 0x9: svga->clock = (cpuclock * (double)(1ull << 32)) / 98000000.0; break; - case 0xa: svga->clock = (cpuclock * (double)(1ull << 32)) / 118800000.0; break; - case 0xb: svga->clock = (cpuclock * (double)(1ull << 32)) / 108000000.0; break; - case 0xc: svga->clock = (cpuclock * (double)(1ull << 32)) / 72000000.0; break; - case 0xd: svga->clock = (cpuclock * (double)(1ull << 32)) / 77000000.0; break; - case 0xe: svga->clock = (cpuclock * (double)(1ull << 32)) / 80000000.0; break; - case 0xf: svga->clock = (cpuclock * (double)(1ull << 32)) / 75000000.0; break; + default: + break; } + svga->lowres = 0; + } +} - if (tvga->card_id != TVGA8900CLD_ID) { - /*TVGA9000 doesn't seem to have support for a 'high res' 256 colour mode - (without the VGA pixel doubling). Instead it implements these modes by - doubling the horizontal pixel count and pixel clock. Hence we use a - basic heuristic to detect this*/ - if (svga->interlace) - high_res_256 = (svga->htotal * 8) > (svga->vtotal * 4); - else - high_res_256 = (svga->htotal * 8) > (svga->vtotal * 2); - } +static void * +tvga_init(const device_t *info) +{ + const char *bios_fn; + tvga_t *tvga = malloc(sizeof(tvga_t)); + memset(tvga, 0, sizeof(tvga_t)); - if ((tvga->oldctrl2 & 0x10) || high_res_256) - { - if (high_res_256) - svga->hdisp /= 2; - switch (svga->bpp) - { - case 8: - svga->render = svga_render_8bpp_highres; - break; - case 15: - svga->render = svga_render_15bpp_highres; - svga->hdisp /= 2; - break; - case 16: - svga->render = svga_render_16bpp_highres; - svga->hdisp /= 2; - break; - case 24: - svga->render = svga_render_24bpp_highres; - svga->hdisp /= 3; - break; - } - svga->lowres = 0; - } -} - - -static void *tvga_init(const device_t *info) -{ - const char *bios_fn; - tvga_t *tvga = malloc(sizeof(tvga_t)); - memset(tvga, 0, sizeof(tvga_t)); - - if (info->local == TVGA9000B_ID) { - video_inform(VIDEO_FLAG_TYPE_SPECIAL, &timing_tvga9000); - tvga->vram_size = 512 << 10; - } else { - video_inform(VIDEO_FLAG_TYPE_SPECIAL, &timing_tvga8900); - tvga->vram_size = device_get_config_int("memory") << 10; - } - - tvga->vram_mask = tvga->vram_size - 1; - - tvga->card_id = info->local; - - switch (info->local) - { - case TVGA8900B_ID: - bios_fn = ROM_TVGA_8900B; - break; - case TVGA8900CLD_ID: - bios_fn = ROM_TVGA_8900CLD; - break; - case TVGA9000B_ID: - bios_fn = ROM_TVGA_9000B; - break; - default: - free(tvga); - return NULL; - } - - rom_init(&tvga->bios_rom, (char *) bios_fn, 0xc0000, 0x8000, 0x7fff, 0, MEM_MAPPING_EXTERNAL); - - svga_init(info, &tvga->svga, tvga, tvga->vram_size, - tvga_recalctimings, - tvga_in, tvga_out, - NULL, - NULL); - - if (info->local != TVGA9000B_ID) - tvga->svga.ramdac = device_add(&tkd8001_ramdac_device); - - io_sethandler(0x03c0, 0x0020, tvga_in, NULL, NULL, tvga_out, NULL, NULL, tvga); - - return tvga; -} - -static int tvga8900b_available(void) -{ - return rom_present(ROM_TVGA_8900B); -} - -static int tvga8900d_available(void) -{ - return rom_present(ROM_TVGA_8900CLD); -} - -static int tvga9000b_available(void) -{ - return rom_present(ROM_TVGA_9000B); -} - -void tvga_close(void *p) -{ - tvga_t *tvga = (tvga_t *)p; - - svga_close(&tvga->svga); - - free(tvga); -} - -void tvga_speed_changed(void *p) -{ - tvga_t *tvga = (tvga_t *)p; - - svga_recalctimings(&tvga->svga); -} - -void tvga_force_redraw(void *p) -{ - tvga_t *tvga = (tvga_t *)p; - - tvga->svga.fullchange = changeframecount; -} - -static const device_config_t tvga_config[] = -{ - { - "memory", "Memory size", CONFIG_SELECTION, "", 1024, "", { 0 }, - { - { - "256 kB", 256 - }, - { - "512 kB", 512 - }, - { - "1 MB", 1024 - }, - /*Chip supports 2mb, but drivers are buggy*/ - { - "" - } - } - }, - { - "", "", -1 + tvga->card_id = info->local & 0xFF; + + if (tvga->card_id == TVGA9000B_ID) { + video_inform(VIDEO_FLAG_TYPE_SPECIAL, &timing_tvga9000); + tvga->vram_size = 512 << 10; + } else { + video_inform(VIDEO_FLAG_TYPE_SPECIAL, &timing_tvga8900); + tvga->vram_size = device_get_config_int("memory") << 10; + } + + tvga->vram_mask = tvga->vram_size - 1; + + switch (tvga->card_id) { + case TVGA8900B_ID: + bios_fn = ROM_TVGA_8900B; + break; + case TVGA8900CLD_ID: + bios_fn = ROM_TVGA_8900CLD; + break; + case TVGA9000B_ID: + bios_fn = (info->local & 0x100) ? ROM_TVGA_9000B_NEC_SV9000 : ROM_TVGA_9000B; + break; + default: + free(tvga); + return NULL; + } + + rom_init(&tvga->bios_rom, bios_fn, 0xc0000, 0x8000, 0x7fff, 0, MEM_MAPPING_EXTERNAL); + + svga_init(info, &tvga->svga, tvga, tvga->vram_size, + tvga_recalctimings, + tvga_in, tvga_out, + NULL, + NULL); + + if (tvga->card_id != TVGA9000B_ID) + tvga->svga.ramdac = device_add(&tkd8001_ramdac_device); + + io_sethandler(0x03c0, 0x0020, tvga_in, NULL, NULL, tvga_out, NULL, NULL, tvga); + + return tvga; +} + +static int +tvga8900b_available(void) +{ + return rom_present(ROM_TVGA_8900B); +} + +static int +tvga8900d_available(void) +{ + return rom_present(ROM_TVGA_8900CLD); +} + +static int +tvga9000b_available(void) +{ + return rom_present(ROM_TVGA_9000B); +} + +static int +tvga9000b_nec_sv9000_available(void) +{ + return rom_present(ROM_TVGA_9000B_NEC_SV9000); +} + +void +tvga_close(void *priv) +{ + tvga_t *tvga = (tvga_t *) priv; + + svga_close(&tvga->svga); + + free(tvga); +} + +void +tvga_speed_changed(void *priv) +{ + tvga_t *tvga = (tvga_t *) priv; + + svga_recalctimings(&tvga->svga); +} + +void +tvga_force_redraw(void *priv) +{ + tvga_t *tvga = (tvga_t *) priv; + + tvga->svga.fullchange = changeframecount; +} + +static const device_config_t tvga_config[] = { + // clang-format off + { + .name = "memory", + .description = "Memory size", + .type = CONFIG_SELECTION, + .default_int = 1024, + .selection = { + { + .description = "256 kB", + .value = 256 + }, + { + .description = "512 kB", + .value = 512 + }, + { + .description = "1 MB", + .value = 1024 + }, + /*Chip supports 2mb, but drivers are buggy*/ + { + .description = "" + } } + }, + { + .type = CONFIG_END + } +// clang-format off }; -const device_t tvga8900b_device = -{ - "Trident TVGA 8900B", - "tvga8900b", - DEVICE_ISA, - TVGA8900B_ID, - tvga_init, - tvga_close, - NULL, - { tvga8900b_available }, - tvga_speed_changed, - tvga_force_redraw, - tvga_config +const device_t tvga8900b_device = { + .name = "Trident TVGA 8900B", + .internal_name = "tvga8900b", + .flags = DEVICE_ISA, + .local = TVGA8900B_ID, + .init = tvga_init, + .close = tvga_close, + .reset = NULL, + { .available = tvga8900b_available }, + .speed_changed = tvga_speed_changed, + .force_redraw = tvga_force_redraw, + .config = tvga_config }; -const device_t tvga8900d_device = -{ - "Trident TVGA 8900D", - "tvga8900d", - DEVICE_ISA, - TVGA8900CLD_ID, - tvga_init, - tvga_close, - NULL, - { tvga8900d_available }, - tvga_speed_changed, - tvga_force_redraw, - tvga_config +const device_t tvga8900d_device = { + .name = "Trident TVGA 8900D", + .internal_name = "tvga8900d", + .flags = DEVICE_ISA, + .local = TVGA8900CLD_ID, + .init = tvga_init, + .close = tvga_close, + .reset = NULL, + { .available = tvga8900d_available }, + .speed_changed = tvga_speed_changed, + .force_redraw = tvga_force_redraw, + .config = tvga_config }; -const device_t tvga9000b_device = -{ - "Trident TVGA 9000B", - "tvga9000b", - DEVICE_ISA, - TVGA9000B_ID, - tvga_init, - tvga_close, - NULL, - { tvga9000b_available }, - tvga_speed_changed, - tvga_force_redraw, - NULL +const device_t tvga9000b_device = { + .name = "Trident TVGA 9000B", + .internal_name = "tvga9000b", + .flags = DEVICE_ISA, + .local = TVGA9000B_ID, + .init = tvga_init, + .close = tvga_close, + .reset = NULL, + { .available = tvga9000b_available }, + .speed_changed = tvga_speed_changed, + .force_redraw = tvga_force_redraw, + .config = NULL +}; + +const device_t nec_sv9000_device = { + .name = "NEC SV9000 (Trident TVGA 9000B)", + .internal_name = "nec_sv9000", + .flags = DEVICE_ISA, + .local = TVGA9000B_ID | 0x100, + .init = tvga_init, + .close = tvga_close, + .reset = NULL, + { .available = tvga9000b_nec_sv9000_available }, + .speed_changed = tvga_speed_changed, + .force_redraw = tvga_force_redraw, + .config = NULL }; diff --git a/src/video/vid_tvp3026_ramdac.c b/src/video/vid_tvp3026_ramdac.c index ace0792e0..15215c45d 100644 --- a/src/video/vid_tvp3026_ramdac.c +++ b/src/video/vid_tvp3026_ramdac.c @@ -1,20 +1,20 @@ /* - * 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. + * 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. + * This file is part of the 86Box distribution. * - * Emulation of the Texas Instruments TVP3026 true colour RAMDAC - * family. + * Emulation of the Texas Instruments TVP3026 true colour RAMDAC + * family. * * - * TODO: Clock and other parts. + * TODO: Clock and other parts. * - * Authors: TheCollector1995, + * Authors: TheCollector1995, * - * Copyright 2021 TheCollector1995. + * Copyright 2021 TheCollector1995. */ #include #include @@ -27,434 +27,489 @@ #include <86box/timer.h> #include <86box/video.h> #include <86box/vid_svga.h> +#include <86box/plat_fallthrough.h> - -typedef struct -{ - PALETTE extpal; - uint32_t extpallook[256]; - uint8_t cursor64_data[1024]; - int hwc_y, hwc_x; - uint8_t ind_idx; - uint8_t dcc, dc_init; - uint8_t ccr; - uint8_t true_color; - uint8_t latch_cntl; - uint8_t mcr; - uint8_t ppr; - uint8_t general_cntl; - uint8_t mclk; - uint8_t misc; - uint8_t type; - uint8_t mode; - uint8_t pll_addr; - uint8_t clock_sel; - struct - { - uint8_t m, n, p; - } pix, mem, loop; +typedef struct tvp3026_ramdac_t { + PALETTE extpal; + uint32_t extpallook[256]; + uint8_t cursor64_data[1024]; + int hwc_y; + int hwc_x; + uint8_t ind_idx; + uint8_t dcc; + uint8_t dc_init; + uint8_t ccr; + uint8_t true_color; + uint8_t latch_cntl; + uint8_t mcr; + uint8_t ppr; + uint8_t general_cntl; + uint8_t mclk; + uint8_t misc; + uint8_t type; + uint8_t mode; + uint8_t pll_addr; + uint8_t clock_sel; + struct { + uint8_t m; + uint8_t n; + uint8_t p; + } pix, mem, loop; } tvp3026_ramdac_t; static void tvp3026_set_bpp(tvp3026_ramdac_t *ramdac, svga_t *svga) { - if ((ramdac->true_color & 0x80) == 0x80) { - if (ramdac->mcr & 0x08) - svga->bpp = 8; - else - svga->bpp = 4; - } else { - switch (ramdac->true_color & 0x0f) { - case 0x01: - case 0x03: - case 0x05: - svga->bpp = 16; - break; - case 0x04: - svga->bpp = 15; - break; - case 0x06: - case 0x07: - if (ramdac->true_color & 0x10) - svga->bpp = 24; - else - svga->bpp = 32; - break; - case 0x0e: - case 0x0f: - svga->bpp = 24; - break; - } - } + if ((ramdac->true_color & 0x80) == 0x80) { + if (ramdac->mcr & 0x08) + svga->bpp = 8; + else + svga->bpp = 4; + } else { + switch (ramdac->true_color & 0x0f) { + case 0x01: + case 0x03: + case 0x05: + svga->bpp = 16; + break; + case 0x04: + svga->bpp = 15; + break; + case 0x06: + case 0x07: + if (ramdac->true_color & 0x10) + svga->bpp = 24; + else + svga->bpp = 32; + break; + case 0x0e: + case 0x0f: + svga->bpp = 24; + break; + + default: + break; + } + } svga_recalctimings(svga); } - void -tvp3026_ramdac_out(uint16_t addr, int rs2, int rs3, uint8_t val, void *p, svga_t *svga) +tvp3026_ramdac_out(uint16_t addr, int rs2, int rs3, uint8_t val, void *priv, svga_t *svga) { - tvp3026_ramdac_t *ramdac = (tvp3026_ramdac_t *) p; - uint32_t o32; - uint8_t *cd; - uint16_t index; - uint8_t rs = (addr & 0x03); - uint16_t da_mask = 0x03ff; + tvp3026_ramdac_t *ramdac = (tvp3026_ramdac_t *) priv; + uint32_t o32; + uint8_t *cd; + uint16_t index; + uint8_t rs = (addr & 0x03); + uint16_t da_mask = 0x03ff; rs |= (!!rs2 << 2); rs |= (!!rs3 << 3); switch (rs) { - case 0x00: /* Palette Write Index Register (RS value = 0000) */ - ramdac->ind_idx = val; - case 0x04: /* Ext Palette Write Index Register (RS value = 0100) */ - case 0x03: - case 0x07: /* Ext Palette Read Index Register (RS value = 0111) */ - svga->dac_pos = 0; - svga->dac_status = addr & 0x03; - svga->dac_addr = val; - if (svga->dac_status) - svga->dac_addr = (svga->dac_addr + 1) & da_mask; - break; - case 0x01: /* Palette Data Register (RS value = 0001) */ - case 0x02: /* Pixel Read Mask Register (RS value = 0010) */ - svga_out(addr, val, svga); - break; - case 0x05: /* Ext Palette Data Register (RS value = 0101) */ - svga->dac_status = 0; - svga->fullchange = changeframecount; - switch (svga->dac_pos) { - case 0: - svga->dac_r = val; - svga->dac_pos++; - break; - case 1: - svga->dac_g = val; - svga->dac_pos++; - break; - case 2: - index = svga->dac_addr & 3; - ramdac->extpal[index].r = svga->dac_r; - ramdac->extpal[index].g = svga->dac_g; - ramdac->extpal[index].b = val; - if (svga->ramdac_type == RAMDAC_8BIT) - ramdac->extpallook[index] = makecol32(ramdac->extpal[index].r, ramdac->extpal[index].g, ramdac->extpal[index].b); - else - ramdac->extpallook[index] = makecol32(video_6to8[ramdac->extpal[index].r & 0x3f], video_6to8[ramdac->extpal[index].g & 0x3f], video_6to8[ramdac->extpal[index].b & 0x3f]); + case 0x00: /* Palette Write Index Register (RS value = 0000) */ + ramdac->ind_idx = val; + fallthrough; + case 0x04: /* Ext Palette Write Index Register (RS value = 0100) */ + case 0x03: + case 0x07: /* Ext Palette Read Index Register (RS value = 0111) */ + svga->dac_pos = 0; + svga->dac_status = addr & 0x03; + svga->dac_addr = val; + if (svga->dac_status) + svga->dac_addr = (svga->dac_addr + 1) & da_mask; + break; + case 0x01: /* Palette Data Register (RS value = 0001) */ + case 0x02: /* Pixel Read Mask Register (RS value = 0010) */ + svga_out(addr, val, svga); + break; + case 0x05: /* Ext Palette Data Register (RS value = 0101) */ + svga->dac_status = 0; + svga->fullchange = changeframecount; + switch (svga->dac_pos) { + case 0: + svga->dac_r = val; + svga->dac_pos++; + break; + case 1: + svga->dac_g = val; + svga->dac_pos++; + break; + case 2: + index = svga->dac_addr & 3; + ramdac->extpal[index].r = svga->dac_r; + ramdac->extpal[index].g = svga->dac_g; + ramdac->extpal[index].b = val; + if (svga->ramdac_type == RAMDAC_8BIT) + ramdac->extpallook[index] = makecol32(ramdac->extpal[index].r, ramdac->extpal[index].g, ramdac->extpal[index].b); + else + ramdac->extpallook[index] = makecol32(video_6to8[ramdac->extpal[index].r & 0x3f], video_6to8[ramdac->extpal[index].g & 0x3f], video_6to8[ramdac->extpal[index].b & 0x3f]); - if (svga->ext_overscan && !index) { - o32 = svga->overscan_color; - svga->overscan_color = ramdac->extpallook[0]; - if (o32 != svga->overscan_color) - svga_recalctimings(svga); - } - svga->dac_addr = (svga->dac_addr + 1) & 0xff; - svga->dac_pos = 0; - break; - } - break; - case 0x09: /* Direct Cursor Control (RS value = 1001) */ - ramdac->dcc = val; - if (ramdac->ccr & 0x80) { - svga->dac_hwcursor.xsize = svga->dac_hwcursor.ysize = 64; - svga->dac_hwcursor.x = ramdac->hwc_x - svga->dac_hwcursor.xsize; - svga->dac_hwcursor.y = ramdac->hwc_y - svga->dac_hwcursor.ysize; - svga->dac_hwcursor.ena = !!(val & 0x03); - ramdac->mode = val & 0x03; - } - break; - case 0x0a: /* Indexed Data (RS value = 1010) */ - switch (ramdac->ind_idx) { - case 0x06: /* Indirect Cursor Control */ - ramdac->ccr = val; - svga->dac_hwcursor.xsize = svga->dac_hwcursor.ysize = 64; - svga->dac_hwcursor.x = ramdac->hwc_x - svga->dac_hwcursor.xsize; - svga->dac_hwcursor.y = ramdac->hwc_y - svga->dac_hwcursor.ysize; - svga->dac_hwcursor.ena = !!(val & 0x03); - ramdac->mode = val & 0x03; - break; - case 0x0f: /* Latch Control */ - ramdac->latch_cntl = val; - break; - case 0x18: /* True Color Control */ - ramdac->true_color = val; - tvp3026_set_bpp(ramdac, svga); - break; - case 0x19: /* Multiplex Control */ - ramdac->mcr = val; - tvp3026_set_bpp(ramdac, svga); - break; - case 0x1a: /* Clock Selection */ - ramdac->clock_sel = val; - break; - case 0x1c: /* Palette-Page Register */ - ramdac->ppr = val; - break; - case 0x1d: /* General Control Register */ - ramdac->general_cntl = val; - break; - case 0x1e: /* Miscellaneous Control */ - ramdac->misc = val; - svga->ramdac_type = (val & 0x08) ? RAMDAC_8BIT : RAMDAC_6BIT; - break; - case 0x2c: /* PLL Address */ - ramdac->pll_addr = val; - break; - case 0x2d: /* Pixel clock PLL data */ - switch (ramdac->pll_addr & 3) { - case 0: - ramdac->pix.n = val; - break; - case 1: - ramdac->pix.m = val; - break; - case 2: - ramdac->pix.p = val; - break; - } - ramdac->pll_addr = ((ramdac->pll_addr + 1) & 3) | (ramdac->pll_addr & 0xfc); - break; - case 0x2e: /* Memory Clock PLL Data */ - switch ((ramdac->pll_addr >> 2) & 3) { - case 0: - ramdac->mem.n = val; - break; - case 1: - ramdac->mem.m = val; - break; - case 2: - ramdac->mem.p = val; - break; - } - ramdac->pll_addr = ((ramdac->pll_addr + 4) & 0x0c) | (ramdac->pll_addr & 0xf3); - break; - case 0x2f: /* Loop Clock PLL Data */ - switch ((ramdac->pll_addr >> 4) & 3) { - case 0: - ramdac->loop.n = val; - break; - case 1: - ramdac->loop.m = val; - break; - case 2: - ramdac->loop.p = val; - break; - } - ramdac->pll_addr = ((ramdac->pll_addr + 0x10) & 0x30) | (ramdac->pll_addr & 0xcf); - break; - case 0x39: /* MCLK/Loop Clock Control */ - ramdac->mclk = val; - break; - - } - break; - case 0x0b: /* Cursor RAM Data Register (RS value = 1011) */ - index = svga->dac_addr & da_mask; - cd = (uint8_t *) ramdac->cursor64_data; - cd[index] = val; - svga->dac_addr = (svga->dac_addr + 1) & da_mask; - break; - case 0x0c: /* Cursor X Low Register (RS value = 1100) */ - ramdac->hwc_x = (ramdac->hwc_x & 0x0f00) | val; - svga->dac_hwcursor.x = ramdac->hwc_x - svga->dac_hwcursor.xsize; - break; - case 0x0d: /* Cursor X High Register (RS value = 1101) */ - ramdac->hwc_x = (ramdac->hwc_x & 0x00ff) | ((val & 0x0f) << 8); - svga->dac_hwcursor.x = ramdac->hwc_x - svga->dac_hwcursor.xsize; - break; - case 0x0e: /* Cursor Y Low Register (RS value = 1110) */ - ramdac->hwc_y = (ramdac->hwc_y & 0x0f00) | val; - svga->dac_hwcursor.y = ramdac->hwc_y - svga->dac_hwcursor.ysize; - break; - case 0x0f: /* Cursor Y High Register (RS value = 1111) */ - ramdac->hwc_y = (ramdac->hwc_y & 0x00ff) | ((val & 0x0f) << 8); - svga->dac_hwcursor.y = ramdac->hwc_y - svga->dac_hwcursor.ysize; - break; + if (svga->ext_overscan && !index) { + o32 = svga->overscan_color; + svga->overscan_color = ramdac->extpallook[0]; + if (o32 != svga->overscan_color) + svga_recalctimings(svga); + } + svga->dac_addr = (svga->dac_addr + 1) & 0xff; + svga->dac_pos = 0; + break; + + default: + break; + } + break; + case 0x09: /* Direct Cursor Control (RS value = 1001) */ + ramdac->dcc = val; + if (ramdac->ccr & 0x80) { + svga->dac_hwcursor.cur_xsize = svga->dac_hwcursor.cur_ysize = 64; + svga->dac_hwcursor.x = ramdac->hwc_x - svga->dac_hwcursor.cur_xsize; + svga->dac_hwcursor.y = ramdac->hwc_y - svga->dac_hwcursor.cur_ysize; + svga->dac_hwcursor.ena = !!(val & 0x03); + ramdac->mode = val & 0x03; + } + break; + case 0x0a: /* Indexed Data (RS value = 1010) */ + switch (ramdac->ind_idx) { + case 0x06: /* Indirect Cursor Control */ + ramdac->ccr = val; + if (!(ramdac->ccr & 0x80)) { + svga->dac_hwcursor.cur_xsize = svga->dac_hwcursor.cur_ysize = 64; + svga->dac_hwcursor.x = ramdac->hwc_x - svga->dac_hwcursor.cur_xsize; + svga->dac_hwcursor.y = ramdac->hwc_y - svga->dac_hwcursor.cur_ysize; + svga->dac_hwcursor.ena = !!(val & 0x03); + ramdac->mode = val & 0x03; + } else { + svga->dac_hwcursor.cur_xsize = svga->dac_hwcursor.cur_ysize = 64; + svga->dac_hwcursor.x = ramdac->hwc_x - svga->dac_hwcursor.cur_xsize; + svga->dac_hwcursor.y = ramdac->hwc_y - svga->dac_hwcursor.cur_ysize; + svga->dac_hwcursor.ena = !!(ramdac->dcc & 0x03); + ramdac->mode = ramdac->dcc & 0x03; + } + break; + case 0x0f: /* Latch Control */ + ramdac->latch_cntl = val; + break; + case 0x18: /* True Color Control */ + ramdac->true_color = val; + tvp3026_set_bpp(ramdac, svga); + break; + case 0x19: /* Multiplex Control */ + ramdac->mcr = val; + tvp3026_set_bpp(ramdac, svga); + break; + case 0x1a: /* Clock Selection */ + ramdac->clock_sel = val; + break; + case 0x1c: /* Palette-Page Register */ + ramdac->ppr = val; + break; + case 0x1d: /* General Control Register */ + ramdac->general_cntl = val; + break; + case 0x1e: /* Miscellaneous Control */ + ramdac->misc = val; + svga->ramdac_type = (val & 0x08) ? RAMDAC_8BIT : RAMDAC_6BIT; + break; + case 0x2c: /* PLL Address */ + ramdac->pll_addr = val; + break; + case 0x2d: /* Pixel clock PLL data */ + switch (ramdac->pll_addr & 3) { + case 0: + ramdac->pix.n = val; + break; + case 1: + ramdac->pix.m = val; + break; + case 2: + ramdac->pix.p = val; + break; + + default: + break; + } + ramdac->pll_addr = ((ramdac->pll_addr + 1) & 3) | (ramdac->pll_addr & 0xfc); + break; + case 0x2e: /* Memory Clock PLL Data */ + switch ((ramdac->pll_addr >> 2) & 3) { + case 0: + ramdac->mem.n = val; + break; + case 1: + ramdac->mem.m = val; + break; + case 2: + ramdac->mem.p = val; + break; + + default: + break; + } + ramdac->pll_addr = ((ramdac->pll_addr + 4) & 0x0c) | (ramdac->pll_addr & 0xf3); + break; + case 0x2f: /* Loop Clock PLL Data */ + switch ((ramdac->pll_addr >> 4) & 3) { + case 0: + ramdac->loop.n = val; + break; + case 1: + ramdac->loop.m = val; + break; + case 2: + ramdac->loop.p = val; + break; + + default: + break; + } + ramdac->pll_addr = ((ramdac->pll_addr + 0x10) & 0x30) | (ramdac->pll_addr & 0xcf); + break; + case 0x39: /* MCLK/Loop Clock Control */ + ramdac->mclk = val; + break; + + default: + break; + } + break; + case 0x0b: /* Cursor RAM Data Register (RS value = 1011) */ + index = (svga->dac_addr & da_mask) | ((ramdac->ccr & 0x0c) << 6); + cd = (uint8_t *) ramdac->cursor64_data; + cd[index] = val; + svga->dac_addr = (svga->dac_addr + 1) & da_mask; + break; + case 0x0c: /* Cursor X Low Register (RS value = 1100) */ + ramdac->hwc_x = (ramdac->hwc_x & 0x0f00) | val; + svga->dac_hwcursor.x = ramdac->hwc_x - svga->dac_hwcursor.cur_xsize; + break; + case 0x0d: /* Cursor X High Register (RS value = 1101) */ + ramdac->hwc_x = (ramdac->hwc_x & 0x00ff) | ((val & 0x0f) << 8); + svga->dac_hwcursor.x = ramdac->hwc_x - svga->dac_hwcursor.cur_xsize; + break; + case 0x0e: /* Cursor Y Low Register (RS value = 1110) */ + ramdac->hwc_y = (ramdac->hwc_y & 0x0f00) | val; + svga->dac_hwcursor.y = ramdac->hwc_y - svga->dac_hwcursor.cur_ysize; + break; + case 0x0f: /* Cursor Y High Register (RS value = 1111) */ + ramdac->hwc_y = (ramdac->hwc_y & 0x00ff) | ((val & 0x0f) << 8); + svga->dac_hwcursor.y = ramdac->hwc_y - svga->dac_hwcursor.cur_ysize; + break; + + default: + break; } return; } - uint8_t -tvp3026_ramdac_in(uint16_t addr, int rs2, int rs3, void *p, svga_t *svga) +tvp3026_ramdac_in(uint16_t addr, int rs2, int rs3, void *priv, svga_t *svga) { - tvp3026_ramdac_t *ramdac = (tvp3026_ramdac_t *) p; - uint8_t temp = 0xff; - uint8_t *cd; - uint16_t index; - uint8_t rs = (addr & 0x03); - uint16_t da_mask = 0x03ff; + tvp3026_ramdac_t *ramdac = (tvp3026_ramdac_t *) priv; + uint8_t temp = 0xff; + const uint8_t *cd; + uint16_t index; + uint8_t rs = (addr & 0x03); + uint16_t da_mask = 0x03ff; rs |= (!!rs2 << 2); rs |= (!!rs3 << 3); switch (rs) { - case 0x00: /* Palette Write Index Register (RS value = 0000) */ - case 0x01: /* Palette Data Register (RS value = 0001) */ - case 0x02: /* Pixel Read Mask Register (RS value = 0010) */ - case 0x04: /* Ext Palette Write Index Register (RS value = 0100) */ - temp = svga_in(addr, svga); - break; - case 0x03: /* Palette Read Index Register (RS value = 0011) */ - case 0x07: /* Ext Palette Read Index Register (RS value = 0111) */ - temp = svga->dac_addr & 0xff; - break; - case 0x05: /* Ext Palette Data Register (RS value = 0101) */ - index = (svga->dac_addr - 1) & 3; - svga->dac_status = 3; - switch (svga->dac_pos) { - case 0: - svga->dac_pos++; - if (svga->ramdac_type == RAMDAC_8BIT) - temp = ramdac->extpal[index].r; - else - temp = ramdac->extpal[index].r & 0x3f; - break; - case 1: - svga->dac_pos++; - if (svga->ramdac_type == RAMDAC_8BIT) - temp = ramdac->extpal[index].g; - else - temp = ramdac->extpal[index].g & 0x3f; - break; - case 2: - svga->dac_pos=0; - svga->dac_addr = svga->dac_addr + 1; - if (svga->ramdac_type == RAMDAC_8BIT) - temp = ramdac->extpal[index].b; - else - temp = ramdac->extpal[index].b & 0x3f; - break; - } - break; - case 0x09: /* Direct Cursor Control (RS value = 1001) */ - temp = ramdac->dcc; - break; - case 0x0a: /* Indexed Data (RS value = 1010) */ - switch (ramdac->ind_idx) { - case 0x01: /* Silicon Revision */ - temp = 0x00; - break; - case 0x06: /* Indirect Cursor Control */ - temp = ramdac->ccr; - break; - case 0x0f: /* Latch Control */ - temp = ramdac->latch_cntl; - break; - case 0x18: /* True Color Control */ - temp = ramdac->true_color; - break; - case 0x19: /* Multiplex Control */ - temp = ramdac->mcr; - break; - case 0x1a: /* Clock Selection */ - temp = ramdac->clock_sel; - break; - case 0x1c: /* Palette-Page Register */ - temp = ramdac->ppr; - break; - case 0x1d: /* General Control Register */ - temp = ramdac->general_cntl; - break; - case 0x1e: /* Miscellaneous Control */ - temp = ramdac->misc; - break; - case 0x2c: /* PLL Address */ - temp = ramdac->pll_addr; - break; - case 0x2d: /* Pixel clock PLL data */ - switch (ramdac->pll_addr & 3) { - case 0: - temp = ramdac->pix.n; - break; - case 1: - temp = ramdac->pix.m; - break; - case 2: - temp = ramdac->pix.p; - break; - case 3: - temp = 0x40; /*PLL locked to frequency*/ - break; - } - break; - case 0x2e: /* Memory Clock PLL Data */ - switch ((ramdac->pll_addr >> 2) & 3) { - case 0: - temp = ramdac->mem.n; - break; - case 1: - temp = ramdac->mem.m; - break; - case 2: - temp = ramdac->mem.p; - break; - case 3: - temp = 0x40; /*PLL locked to frequency*/ - break; - } - break; - case 0x2f: /* Loop Clock PLL Data */ - switch ((ramdac->pll_addr >> 4) & 3) { - case 0: - temp = ramdac->loop.n; - break; - case 1: - temp = ramdac->loop.m; - break; - case 2: - temp = ramdac->loop.p; - break; - } - break; - case 0x39: /* MCLK/Loop Clock Control */ - temp = ramdac->mclk; - break; - case 0x3f: /* ID */ - temp = 0x26; - break; - } - break; - case 0x0b: /* Cursor RAM Data Register (RS value = 1011) */ - index = (svga->dac_addr - 1) & da_mask; - cd = (uint8_t *) ramdac->cursor64_data; - temp = cd[index]; + case 0x00: /* Palette Write Index Register (RS value = 0000) */ + case 0x01: /* Palette Data Register (RS value = 0001) */ + case 0x02: /* Pixel Read Mask Register (RS value = 0010) */ + case 0x04: /* Ext Palette Write Index Register (RS value = 0100) */ + temp = svga_in(addr, svga); + break; + case 0x03: /* Palette Read Index Register (RS value = 0011) */ + case 0x07: /* Ext Palette Read Index Register (RS value = 0111) */ + temp = svga->dac_addr & 0xff; + break; + case 0x05: /* Ext Palette Data Register (RS value = 0101) */ + index = (svga->dac_addr - 1) & 3; + svga->dac_status = 3; + switch (svga->dac_pos) { + case 0: + svga->dac_pos++; + if (svga->ramdac_type == RAMDAC_8BIT) + temp = ramdac->extpal[index].r; + else + temp = ramdac->extpal[index].r & 0x3f; + break; + case 1: + svga->dac_pos++; + if (svga->ramdac_type == RAMDAC_8BIT) + temp = ramdac->extpal[index].g; + else + temp = ramdac->extpal[index].g & 0x3f; + break; + case 2: + svga->dac_pos = 0; + svga->dac_addr = svga->dac_addr + 1; + if (svga->ramdac_type == RAMDAC_8BIT) + temp = ramdac->extpal[index].b; + else + temp = ramdac->extpal[index].b & 0x3f; + break; - svga->dac_addr = (svga->dac_addr + 1) & da_mask; - break; - case 0x0c: /* Cursor X Low Register (RS value = 1100) */ - temp = ramdac->hwc_x & 0xff; - break; - case 0x0d: /* Cursor X High Register (RS value = 1101) */ - temp = (ramdac->hwc_x >> 8) & 0xff; - break; - case 0x0e: /* Cursor Y Low Register (RS value = 1110) */ - temp = ramdac->hwc_y & 0xff; - break; - case 0x0f: /* Cursor Y High Register (RS value = 1111) */ - temp = (ramdac->hwc_y >> 8) & 0xff; - break; + default: + break; + } + break; + case 0x09: /* Direct Cursor Control (RS value = 1001) */ + temp = ramdac->dcc; + break; + case 0x0a: /* Indexed Data (RS value = 1010) */ + switch (ramdac->ind_idx) { + case 0x01: /* Silicon Revision */ + temp = 0x00; + break; + case 0x06: /* Indirect Cursor Control */ + temp = ramdac->ccr; + break; + case 0x0f: /* Latch Control */ + temp = ramdac->latch_cntl; + break; + case 0x18: /* True Color Control */ + temp = ramdac->true_color; + break; + case 0x19: /* Multiplex Control */ + temp = ramdac->mcr; + break; + case 0x1a: /* Clock Selection */ + temp = ramdac->clock_sel; + break; + case 0x1c: /* Palette-Page Register */ + temp = ramdac->ppr; + break; + case 0x1d: /* General Control Register */ + temp = ramdac->general_cntl; + break; + case 0x1e: /* Miscellaneous Control */ + temp = ramdac->misc; + break; + case 0x2c: /* PLL Address */ + temp = ramdac->pll_addr; + break; + case 0x2d: /* Pixel clock PLL data */ + switch (ramdac->pll_addr & 3) { + case 0: + temp = ramdac->pix.n; + break; + case 1: + temp = ramdac->pix.m; + break; + case 2: + temp = ramdac->pix.p; + break; + case 3: + temp = 0x40; /*PLL locked to frequency*/ + break; + + default: + break; + } + break; + case 0x2e: /* Memory Clock PLL Data */ + switch ((ramdac->pll_addr >> 2) & 3) { + case 0: + temp = ramdac->mem.n; + break; + case 1: + temp = ramdac->mem.m; + break; + case 2: + temp = ramdac->mem.p; + break; + case 3: + temp = 0x40; /*PLL locked to frequency*/ + break; + + default: + break; + } + break; + case 0x2f: /* Loop Clock PLL Data */ + switch ((ramdac->pll_addr >> 4) & 3) { + case 0: + temp = ramdac->loop.n; + break; + case 1: + temp = ramdac->loop.m; + break; + case 2: + temp = ramdac->loop.p; + break; + + default: + break; + } + break; + case 0x39: /* MCLK/Loop Clock Control */ + temp = ramdac->mclk; + break; + case 0x3f: /* ID */ + temp = 0x26; + break; + + default: + break; + } + break; + case 0x0b: /* Cursor RAM Data Register (RS value = 1011) */ + index = ((svga->dac_addr - 1) & da_mask) | ((ramdac->ccr & 0x0c) << 6); + cd = (uint8_t *) ramdac->cursor64_data; + temp = cd[index]; + + svga->dac_addr = (svga->dac_addr + 1) & da_mask; + break; + case 0x0c: /* Cursor X Low Register (RS value = 1100) */ + temp = ramdac->hwc_x & 0xff; + break; + case 0x0d: /* Cursor X High Register (RS value = 1101) */ + temp = (ramdac->hwc_x >> 8) & 0xff; + break; + case 0x0e: /* Cursor Y Low Register (RS value = 1110) */ + temp = ramdac->hwc_y & 0xff; + break; + case 0x0f: /* Cursor Y High Register (RS value = 1111) */ + temp = (ramdac->hwc_y >> 8) & 0xff; + break; + + default: + break; } return temp; } void -tvp3026_recalctimings(void *p, svga_t *svga) +tvp3026_recalctimings(void *priv, svga_t *svga) { - tvp3026_ramdac_t *ramdac = (tvp3026_ramdac_t *) p; + const tvp3026_ramdac_t *ramdac = (tvp3026_ramdac_t *) priv; svga->interlace = (ramdac->ccr & 0x40); } - void tvp3026_hwcursor_draw(svga_t *svga, int displine) { - int x, xx, comb, b0, b1; - uint16_t dat[2]; - int offset = svga->dac_hwcursor_latch.x + svga->dac_hwcursor_latch.xoff; - int pitch, bppl, mode, x_pos, y_pos; - uint32_t clr1, clr2, clr3, *p; - uint8_t *cd; + int comb; + int b0; + int b1; + uint16_t dat[2]; + int offset = svga->dac_hwcursor_latch.x + svga->dac_hwcursor_latch.xoff; + int pitch; + int bppl; + int mode; + int x_pos; + int y_pos; + uint32_t clr1; + uint32_t clr2; + uint32_t clr3; + uint32_t *p; + const uint8_t *cd; tvp3026_ramdac_t *ramdac = (tvp3026_ramdac_t *) svga->ramdac; clr1 = ramdac->extpallook[1]; @@ -464,101 +519,113 @@ tvp3026_hwcursor_draw(svga_t *svga, int displine) /* The planes come in two parts, and each plane is 1bpp, so a 32x32 cursor has 4 bytes per line, and a 64x64 cursor has 8 bytes per line. */ - pitch = (svga->dac_hwcursor_latch.xsize >> 3); /* Bytes per line. */ + pitch = (svga->dac_hwcursor_latch.cur_xsize >> 3); /* Bytes per line. */ /* A 32x32 cursor has 128 bytes per line, and a 64x64 cursor has 512 bytes per line. */ - bppl = (pitch * svga->dac_hwcursor_latch.ysize); /* Bytes per plane. */ + bppl = (pitch * svga->dac_hwcursor_latch.cur_ysize); /* Bytes per plane. */ mode = ramdac->mode; if (svga->interlace && svga->dac_hwcursor_oddeven) - svga->dac_hwcursor_latch.addr += pitch; + svga->dac_hwcursor_latch.addr += pitch; - cd = (uint8_t *) ramdac->cursor64_data; - - for (x = 0; x < svga->dac_hwcursor_latch.xsize; x += 16) { - dat[0] = (cd[svga->dac_hwcursor_latch.addr] << 8) | - cd[svga->dac_hwcursor_latch.addr + 1]; - dat[1] = (cd[svga->dac_hwcursor_latch.addr + bppl] << 8) | - cd[svga->dac_hwcursor_latch.addr + bppl + 1]; + cd = (uint8_t *) ramdac->cursor64_data; - for (xx = 0; xx < 16; xx++) { - b0 = (dat[0] >> (15 - xx)) & 1; - b1 = (dat[1] >> (15 - xx)) & 1; - comb = (b0 | (b1 << 1)); + for (int x = 0; x < svga->dac_hwcursor_latch.cur_xsize; x += 16) { + dat[0] = (cd[svga->dac_hwcursor_latch.addr] << 8) | cd[svga->dac_hwcursor_latch.addr + 1]; + dat[1] = (cd[svga->dac_hwcursor_latch.addr + bppl] << 8) | cd[svga->dac_hwcursor_latch.addr + bppl + 1]; - y_pos = displine; - x_pos = offset + svga->x_add; - p = buffer32->line[y_pos]; + for (uint8_t xx = 0; xx < 16; xx++) { + b0 = (dat[0] >> (15 - xx)) & 1; + b1 = (dat[1] >> (15 - xx)) & 1; + comb = (b0 | (b1 << 1)); - if (offset >= svga->dac_hwcursor_latch.x) { - switch (mode) { - case 1: /* Three Color */ - switch (comb) { - case 1: - p[x_pos] = clr1; - break; - case 2: - p[x_pos] = clr2; - break; - case 3: - p[x_pos] = clr3; - break; - } - break; - case 2: /* XGA */ - switch (comb) { - case 0: - p[x_pos] = clr1; - break; - case 1: - p[x_pos] = clr2; - break; - case 3: - p[x_pos] ^= 0xffffff; - break; - } - break; - case 3: /* X-Windows */ - switch (comb) { - case 2: - p[x_pos] = clr1; - break; - case 3: - p[x_pos] = clr2; - break; - } - break; - } - } - offset++; - } - svga->dac_hwcursor_latch.addr += 2; + y_pos = displine; + x_pos = offset + svga->x_add; + p = svga->monitor->target_buffer->line[y_pos]; + + if (offset >= svga->dac_hwcursor_latch.x) { + switch (mode) { + case 1: /* Three Color */ + switch (comb) { + case 1: + p[x_pos] = clr1; + break; + case 2: + p[x_pos] = clr2; + break; + case 3: + p[x_pos] = clr3; + break; + + default: + break; + } + break; + case 2: /* XGA */ + switch (comb) { + case 0: + p[x_pos] = clr1; + break; + case 1: + p[x_pos] = clr2; + break; + case 3: + p[x_pos] ^= 0xffffff; + break; + + default: + break; + } + break; + case 3: /* X-Windows */ + switch (comb) { + case 2: + p[x_pos] = clr1; + break; + case 3: + p[x_pos] = clr2; + break; + + default: + break; + } + break; + + default: + break; + } + } + offset++; + } + svga->dac_hwcursor_latch.addr += 2; } if (svga->interlace && !svga->dac_hwcursor_oddeven) - svga->dac_hwcursor_latch.addr += pitch; + svga->dac_hwcursor_latch.addr += pitch; } - -float -tvp3026_getclock(int clock, void *p) +float +tvp3026_getclock(int clock, void *priv) { - tvp3026_ramdac_t *ramdac = (tvp3026_ramdac_t *) p; - int n, m, pl; - float f_vco, f_pll; - + const tvp3026_ramdac_t *ramdac = (tvp3026_ramdac_t *) priv; + int n; + int m; + int pl; + float f_vco; + float f_pll; + if (clock == 0) - return 25175000.0; + return 25175000.0; if (clock == 1) - return 28322000.0; - -/*Fvco = 8 x Fref x (65 - M) / (65 - N)*/ -/*Fpll = Fvco / 2^P*/ - n = ramdac->pix.n & 0x3f; - m = ramdac->pix.m & 0x3f; - pl = ramdac->pix.p & 0x03; - f_vco = 8.0 * 14318184 * (float)(65 - m) / (float)(65 - n); - f_pll = f_vco / (float)(1 << pl); + return 28322000.0; + + /*Fvco = 8 x Fref x (65 - M) / (65 - N)*/ + /*Fpll = Fvco / 2^P*/ + n = ramdac->pix.n & 0x3f; + m = ramdac->pix.m & 0x3f; + pl = ramdac->pix.p & 0x03; + f_vco = 8.0f * 14318184 * (float) (65 - m) / (float) (65 - n); + f_pll = f_vco / (float) (1 << pl); return f_pll; } @@ -571,31 +638,34 @@ tvp3026_ramdac_init(const device_t *info) ramdac->type = info->local; - ramdac->latch_cntl = 0x06; - ramdac->true_color = 0x80; - ramdac->mcr = 0x98; - ramdac->clock_sel = 0x07; - ramdac->mclk = 0x18; + ramdac->latch_cntl = 0x06; + ramdac->true_color = 0x80; + ramdac->mcr = 0x98; + ramdac->clock_sel = 0x07; + ramdac->mclk = 0x18; return ramdac; } - static void tvp3026_ramdac_close(void *priv) { tvp3026_ramdac_t *ramdac = (tvp3026_ramdac_t *) priv; if (ramdac) - free(ramdac); + free(ramdac); } - -const device_t tvp3026_ramdac_device = -{ - "TI TVP3026 RAMDAC", - "tvp3026_ramdac", - 0, 0, - tvp3026_ramdac_init, tvp3026_ramdac_close, - NULL, { NULL }, NULL, NULL +const device_t tvp3026_ramdac_device = { + .name = "TI TVP3026 RAMDAC", + .internal_name = "tvp3026_ramdac", + .flags = 0, + .local = 0, + .init = tvp3026_ramdac_init, + .close = tvp3026_ramdac_close, + .reset = NULL, + { .available = NULL }, + .speed_changed = NULL, + .force_redraw = NULL, + .config = NULL }; diff --git a/src/video/vid_vga.c b/src/video/vid_vga.c index c4cffef03..43b8a2750 100644 --- a/src/video/vid_vga.c +++ b/src/video/vid_vga.c @@ -1,20 +1,20 @@ /* - * 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. + * 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. + * This file is part of the 86Box distribution. * - * IBM VGA emulation. + * IBM VGA emulation. * * * - * Authors: Sarah Walker, - * Miran Grca, + * Authors: Sarah Walker, + * Miran Grca, * - * Copyright 2008-2018 Sarah Walker. - * Copyright 2016-2018 Miran Grca. + * Copyright 2008-2018 Sarah Walker. + * Copyright 2016-2018 Miran Grca. */ #include #include @@ -31,197 +31,198 @@ #include <86box/vid_svga.h> #include <86box/vid_vga.h> +static video_timings_t timing_ps1_svga_isa = { .type = VIDEO_ISA, .write_b = 6, .write_w = 8, .write_l = 16, .read_b = 6, .read_w = 8, .read_l = 16 }; +static video_timings_t timing_ps1_svga_mca = { .type = VIDEO_MCA, .write_b = 6, .write_w = 8, .write_l = 16, .read_b = 6, .read_w = 8, .read_l = 16 }; -static video_timings_t timing_ps1_svga_isa = {VIDEO_ISA, 6, 8, 16, 6, 8, 16}; -static video_timings_t timing_ps1_svga_mca = {VIDEO_MCA, 6, 8, 16, 6, 8, 16}; - -void vga_out(uint16_t addr, uint8_t val, void *p) +void +vga_out(uint16_t addr, uint8_t val, void *priv) { - vga_t *vga = (vga_t *)p; - svga_t *svga = &vga->svga; - uint8_t old; + vga_t *vga = (vga_t *) priv; + svga_t *svga = &vga->svga; + uint8_t old; - if (((addr & 0xfff0) == 0x3d0 || (addr & 0xfff0) == 0x3b0) && !(svga->miscout & 1)) - addr ^= 0x60; + if (((addr & 0xfff0) == 0x3d0 || (addr & 0xfff0) == 0x3b0) && !(svga->miscout & 1)) + addr ^= 0x60; - switch (addr) - { - case 0x3D4: - svga->crtcreg = val & 0x3f; + switch (addr) { + case 0x3D4: + svga->crtcreg = val & 0x3f; + return; + case 0x3D5: + if (svga->crtcreg & 0x20) 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); - } - } + 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); + } + break; + + default: + break; + } + svga_out(addr, val, svga); } -uint8_t vga_in(uint16_t addr, void *p) +uint8_t +vga_in(uint16_t addr, void *priv) { - vga_t *vga = (vga_t *)p; - svga_t *svga = &vga->svga; - uint8_t temp; + vga_t *vga = (vga_t *) priv; + svga_t *svga = &vga->svga; + 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; + 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; } - -static void *vga_init(const device_t *info) +static void * +vga_init(const device_t *info) { - vga_t *vga = malloc(sizeof(vga_t)); - memset(vga, 0, sizeof(vga_t)); + vga_t *vga = malloc(sizeof(vga_t)); + memset(vga, 0, sizeof(vga_t)); - rom_init(&vga->bios_rom, "roms/video/vga/ibm_vga.bin", 0xc0000, 0x8000, 0x7fff, 0x2000, MEM_MAPPING_EXTERNAL); + rom_init(&vga->bios_rom, "roms/video/vga/ibm_vga.bin", 0xc0000, 0x8000, 0x7fff, 0x2000, MEM_MAPPING_EXTERNAL); - video_inform(VIDEO_FLAG_TYPE_SPECIAL, &timing_vga); + video_inform(VIDEO_FLAG_TYPE_SPECIAL, &timing_vga); - svga_init(info, &vga->svga, vga, 1 << 18, /*256kb*/ - NULL, - vga_in, vga_out, - NULL, - NULL); + svga_init(info, &vga->svga, vga, 1 << 18, /*256kb*/ + NULL, + vga_in, vga_out, + NULL, + NULL); - io_sethandler(0x03c0, 0x0020, vga_in, NULL, NULL, vga_out, NULL, NULL, vga); + io_sethandler(0x03c0, 0x0020, vga_in, NULL, NULL, vga_out, NULL, NULL, vga); - vga->svga.bpp = 8; - vga->svga.miscout = 1; - - return vga; + vga->svga.bpp = 8; + vga->svga.miscout = 1; + + return vga; } - /*PS/1 uses a standard VGA controller, but with no option ROM*/ -void *ps1vga_init(const device_t *info) +void * +ps1vga_init(const device_t *info) { - vga_t *vga = malloc(sizeof(vga_t)); - memset(vga, 0, sizeof(vga_t)); - - if (info->flags & DEVICE_MCA) - video_inform(VIDEO_FLAG_TYPE_SPECIAL, &timing_ps1_svga_mca); - else - video_inform(VIDEO_FLAG_TYPE_SPECIAL, &timing_ps1_svga_isa); + vga_t *vga = malloc(sizeof(vga_t)); + memset(vga, 0, sizeof(vga_t)); - svga_init(info, &vga->svga, vga, 1 << 18, /*256kb*/ - NULL, - vga_in, vga_out, - NULL, - NULL); + if (info->flags & DEVICE_MCA) + video_inform(VIDEO_FLAG_TYPE_SPECIAL, &timing_ps1_svga_mca); + else + video_inform(VIDEO_FLAG_TYPE_SPECIAL, &timing_ps1_svga_isa); - io_sethandler(0x03c0, 0x0020, vga_in, NULL, NULL, vga_out, NULL, NULL, vga); + svga_init(info, &vga->svga, vga, 1 << 18, /*256kb*/ + NULL, + vga_in, vga_out, + NULL, + NULL); - vga->svga.bpp = 8; - vga->svga.miscout = 1; - - return vga; + io_sethandler(0x03c0, 0x0020, vga_in, NULL, NULL, vga_out, NULL, NULL, vga); + + vga->svga.bpp = 8; + vga->svga.miscout = 1; + + return vga; } -static int vga_available(void) +static int +vga_available(void) { - return rom_present("roms/video/vga/ibm_vga.bin"); + return rom_present("roms/video/vga/ibm_vga.bin"); } -void vga_close(void *p) +void +vga_close(void *priv) { - vga_t *vga = (vga_t *)p; + vga_t *vga = (vga_t *) priv; - svga_close(&vga->svga); - - free(vga); + svga_close(&vga->svga); + + free(vga); } -void vga_speed_changed(void *p) +void +vga_speed_changed(void *priv) { - vga_t *vga = (vga_t *)p; - - svga_recalctimings(&vga->svga); + vga_t *vga = (vga_t *) priv; + + svga_recalctimings(&vga->svga); } -void vga_force_redraw(void *p) +void +vga_force_redraw(void *priv) { - vga_t *vga = (vga_t *)p; + vga_t *vga = (vga_t *) priv; - vga->svga.fullchange = changeframecount; + vga->svga.fullchange = changeframecount; } -const device_t vga_device = -{ - "VGA", - "vga", - DEVICE_ISA, - 0, - vga_init, - vga_close, - NULL, - { vga_available }, - vga_speed_changed, - vga_force_redraw, - NULL +const device_t vga_device = { + .name = "VGA", + .internal_name = "vga", + .flags = DEVICE_ISA, + .local = 0, + .init = vga_init, + .close = vga_close, + .reset = NULL, + { .available = vga_available }, + .speed_changed = vga_speed_changed, + .force_redraw = vga_force_redraw, + .config = NULL }; -const device_t ps1vga_device = -{ - "PS/1 VGA", - "ps1vga", - DEVICE_ISA, - 0, - ps1vga_init, - vga_close, - NULL, - { vga_available }, - vga_speed_changed, - vga_force_redraw, - NULL +const device_t ps1vga_device = { + .name = "PS/1 VGA", + .internal_name = "ps1vga", + .flags = DEVICE_ISA, + .local = 0, + .init = ps1vga_init, + .close = vga_close, + .reset = NULL, + { .available = vga_available }, + .speed_changed = vga_speed_changed, + .force_redraw = vga_force_redraw, + .config = NULL }; -const device_t ps1vga_mca_device = -{ - "PS/1 VGA", - "ps1vga_mca", - DEVICE_MCA, - 0, - ps1vga_init, - vga_close, - NULL, - { vga_available }, - vga_speed_changed, - vga_force_redraw, - NULL +const device_t ps1vga_mca_device = { + .name = "PS/1 VGA", + .internal_name = "ps1vga_mca", + .flags = DEVICE_MCA, + .local = 0, + .init = ps1vga_init, + .close = vga_close, + .reset = NULL, + { .available = vga_available }, + .speed_changed = vga_speed_changed, + .force_redraw = vga_force_redraw, + .config = NULL }; diff --git a/src/video/vid_voodoo.c b/src/video/vid_voodoo.c index d9c5dc437..a34f26503 100644 --- a/src/video/vid_voodoo.c +++ b/src/video/vid_voodoo.c @@ -1,20 +1,21 @@ /* - * 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. + * 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. + * This file is part of the 86Box distribution. * - * Voodoo Graphics, 2, Banshee, 3 emulation. + * Voodoo Graphics, 2, Banshee, 3 emulation. * * * - * Authors: Sarah Walker, - * leilei + * Authors: Sarah Walker, + * leilei * - * Copyright 2008-2020 Sarah Walker. + * Copyright 2008-2020 Sarah Walker. */ +#include #include #include #include @@ -22,6 +23,7 @@ #include #include #include +#define HAVE_STDARG_H #include <86box/86box.h> #include "cpu.h" #include <86box/machine.h> @@ -32,6 +34,7 @@ #include <86box/timer.h> #include <86box/device.h> #include <86box/plat.h> +#include <86box/thread.h> #include <86box/video.h> #include <86box/vid_svga.h> #include <86box/vid_voodoo_common.h> @@ -45,1398 +48,1394 @@ #include <86box/vid_voodoo_render.h> #include <86box/vid_voodoo_texture.h> -rgba8_t rgb332[0x100], ai44[0x100], rgb565[0x10000], argb1555[0x10000], argb4444[0x10000], ai88[0x10000]; +rgba8_t rgb332[0x100]; +rgba8_t ai44[0x100]; +rgba8_t rgb565[0x10000]; +rgba8_t argb1555[0x10000]; +rgba8_t argb4444[0x10000]; +rgba8_t ai88[0x10000]; int tris = 0; #ifdef ENABLE_VOODOO_LOG int voodoo_do_log = ENABLE_VOODOO_LOG; - static void voodoo_log(const char *fmt, ...) { va_list ap; if (voodoo_do_log) { - va_start(ap, fmt); - pclog_ex(fmt, ap); - va_end(ap); + va_start(ap, fmt); + pclog_ex(fmt, ap); + va_end(ap); } } #else -#define voodoo_log(fmt, ...) +# define voodoo_log(fmt, ...) #endif - -void voodoo_recalc(voodoo_t *voodoo) +void +voodoo_recalc(voodoo_t *voodoo) { - uint32_t buffer_offset = ((voodoo->fbiInit2 >> 11) & 511) * 4096; + uint32_t buffer_offset = ((voodoo->fbiInit2 >> 11) & 511) * 4096; - if (voodoo->type >= VOODOO_BANSHEE) - return; + if (voodoo->type >= VOODOO_BANSHEE) + return; - voodoo->params.front_offset = voodoo->disp_buffer*buffer_offset; - voodoo->back_offset = voodoo->draw_buffer*buffer_offset; + voodoo->params.front_offset = voodoo->disp_buffer * buffer_offset; + voodoo->back_offset = voodoo->draw_buffer * buffer_offset; - voodoo->buffer_cutoff = TRIPLE_BUFFER ? (buffer_offset * 4) : (buffer_offset * 3); - if (TRIPLE_BUFFER) - voodoo->params.aux_offset = buffer_offset * 3; - else - voodoo->params.aux_offset = buffer_offset * 2; + voodoo->buffer_cutoff = TRIPLE_BUFFER ? (buffer_offset * 4) : (buffer_offset * 3); + if (TRIPLE_BUFFER) + voodoo->params.aux_offset = buffer_offset * 3; + else + voodoo->params.aux_offset = buffer_offset * 2; - switch (voodoo->lfbMode & LFB_WRITE_MASK) - { - case LFB_WRITE_FRONT: - voodoo->fb_write_offset = voodoo->params.front_offset; - voodoo->fb_write_buffer = voodoo->disp_buffer; - break; - case LFB_WRITE_BACK: - voodoo->fb_write_offset = voodoo->back_offset; - voodoo->fb_write_buffer = voodoo->draw_buffer; - break; + switch (voodoo->lfbMode & LFB_WRITE_MASK) { + case LFB_WRITE_FRONT: + voodoo->fb_write_offset = voodoo->params.front_offset; + voodoo->fb_write_buffer = voodoo->disp_buffer; + break; + case LFB_WRITE_BACK: + voodoo->fb_write_offset = voodoo->back_offset; + voodoo->fb_write_buffer = voodoo->draw_buffer; + break; - default: - /*BreakNeck sets invalid LFB write buffer select*/ - voodoo->fb_write_offset = voodoo->params.front_offset; - break; - } + default: + /*BreakNeck sets invalid LFB write buffer select*/ + voodoo->fb_write_offset = voodoo->params.front_offset; + break; + } - switch (voodoo->lfbMode & LFB_READ_MASK) - { - case LFB_READ_FRONT: - voodoo->fb_read_offset = voodoo->params.front_offset; - break; - case LFB_READ_BACK: - voodoo->fb_read_offset = voodoo->back_offset; - break; - case LFB_READ_AUX: - voodoo->fb_read_offset = voodoo->params.aux_offset; - break; + switch (voodoo->lfbMode & LFB_READ_MASK) { + case LFB_READ_FRONT: + voodoo->fb_read_offset = voodoo->params.front_offset; + break; + case LFB_READ_BACK: + voodoo->fb_read_offset = voodoo->back_offset; + break; + case LFB_READ_AUX: + voodoo->fb_read_offset = voodoo->params.aux_offset; + break; - default: - fatal("voodoo_recalc : unknown lfb source\n"); - } + default: + fatal("voodoo_recalc : unknown lfb source\n"); + } - switch (voodoo->params.fbzMode & FBZ_DRAW_MASK) - { - case FBZ_DRAW_FRONT: - voodoo->params.draw_offset = voodoo->params.front_offset; - voodoo->fb_draw_buffer = voodoo->disp_buffer; - break; - case FBZ_DRAW_BACK: - voodoo->params.draw_offset = voodoo->back_offset; - voodoo->fb_draw_buffer = voodoo->draw_buffer; - break; + switch (voodoo->params.fbzMode & FBZ_DRAW_MASK) { + case FBZ_DRAW_FRONT: + voodoo->params.draw_offset = voodoo->params.front_offset; + voodoo->fb_draw_buffer = voodoo->disp_buffer; + break; + case FBZ_DRAW_BACK: + voodoo->params.draw_offset = voodoo->back_offset; + voodoo->fb_draw_buffer = voodoo->draw_buffer; + break; - default: - fatal("voodoo_recalc : unknown draw buffer\n"); - } + default: + fatal("voodoo_recalc : unknown draw buffer\n"); + } - voodoo->block_width = ((voodoo->fbiInit1 >> 4) & 15) * 2; - if (voodoo->fbiInit6 & (1 << 30)) - voodoo->block_width += 1; - if (voodoo->fbiInit1 & (1 << 24)) - voodoo->block_width += 32; - voodoo->row_width = voodoo->block_width * 32 * 2; - voodoo->params.row_width = voodoo->row_width; - voodoo->aux_row_width = voodoo->row_width; - voodoo->params.aux_row_width = voodoo->aux_row_width; + voodoo->block_width = ((voodoo->fbiInit1 >> 4) & 15) * 2; + if (voodoo->fbiInit6 & (1 << 30)) + voodoo->block_width += 1; + if (voodoo->fbiInit1 & (1 << 24)) + voodoo->block_width += 32; + voodoo->row_width = voodoo->block_width * 32 * 2; + voodoo->params.row_width = voodoo->row_width; + voodoo->aux_row_width = voodoo->row_width; + voodoo->params.aux_row_width = voodoo->aux_row_width; } - -static uint16_t voodoo_readw(uint32_t addr, void *p) +static uint16_t +voodoo_readw(uint32_t addr, void *priv) { - voodoo_t *voodoo = (voodoo_t *)p; - - addr &= 0xffffff; + voodoo_t *voodoo = (voodoo_t *) priv; - cycles -= voodoo->read_time; - - if ((addr & 0xc00000) == 0x400000) /*Framebuffer*/ - { - if (SLI_ENABLED) - { - voodoo_set_t *set = voodoo->set; - int y = (addr >> 11) & 0x3ff; - - if (y & 1) - voodoo = set->voodoos[1]; - else - voodoo = set->voodoos[0]; - } + addr &= 0xffffff; - voodoo->flush = 1; - while (!FIFO_EMPTY) - { - voodoo_wake_fifo_thread_now(voodoo); - thread_wait_event(voodoo->fifo_not_full_event, 1); - } - voodoo_wait_for_render_thread_idle(voodoo); - voodoo->flush = 0; - - return voodoo_fb_readw(addr, voodoo); + cycles -= voodoo->read_time; + + if ((addr & 0xc00000) == 0x400000) /*Framebuffer*/ + { + if (SLI_ENABLED) { + const voodoo_set_t *set = voodoo->set; + int y = (addr >> 11) & 0x3ff; + + if (y & 1) + voodoo = set->voodoos[1]; + else + voodoo = set->voodoos[0]; } - return 0xffff; + voodoo->flush = 1; + while (!FIFO_EMPTY) { + voodoo_wake_fifo_thread_now(voodoo); + thread_wait_event(voodoo->fifo_not_full_event, 1); + } + voodoo_wait_for_render_thread_idle(voodoo); + voodoo->flush = 0; + + return voodoo_fb_readw(addr, voodoo); + } + + return 0xffff; } - -static uint32_t voodoo_readl(uint32_t addr, void *p) +static uint32_t +voodoo_readl(uint32_t addr, void *priv) { - voodoo_t *voodoo = (voodoo_t *)p; - uint32_t temp = 0xffffffff; - int fifo_size; - voodoo->rd_count++; - addr &= 0xffffff; - - cycles -= voodoo->read_time; + voodoo_t *voodoo = (voodoo_t *) priv; + uint32_t temp = 0xffffffff; + int fifo_size; + voodoo->rd_count++; + addr &= 0xffffff; - if (addr & 0x800000) /*Texture*/ - { + cycles -= voodoo->read_time; + + if (addr & 0x800000) { /*Texture*/ + } else if (addr & 0x400000) /*Framebuffer*/ + { + if (SLI_ENABLED) { + const voodoo_set_t *set = voodoo->set; + int y = (addr >> 11) & 0x3ff; + + if (y & 1) + voodoo = set->voodoos[1]; + else + voodoo = set->voodoos[0]; } - else if (addr & 0x400000) /*Framebuffer*/ - { - if (SLI_ENABLED) - { - voodoo_set_t *set = voodoo->set; - int y = (addr >> 11) & 0x3ff; - - if (y & 1) - voodoo = set->voodoos[1]; - else - voodoo = set->voodoos[0]; - } - voodoo->flush = 1; - while (!FIFO_EMPTY) - { - voodoo_wake_fifo_thread_now(voodoo); - thread_wait_event(voodoo->fifo_not_full_event, 1); - } - voodoo_wait_for_render_thread_idle(voodoo); - voodoo->flush = 0; - - temp = voodoo_fb_readl(addr, voodoo); + voodoo->flush = 1; + while (!FIFO_EMPTY) { + voodoo_wake_fifo_thread_now(voodoo); + thread_wait_event(voodoo->fifo_not_full_event, 1); } - else switch (addr & 0x3fc) - { - case SST_status: + voodoo_wait_for_render_thread_idle(voodoo); + voodoo->flush = 0; + + temp = voodoo_fb_readl(addr, voodoo); + } else + switch (addr & 0x3fc) { + case SST_status: { - int fifo_entries = FIFO_ENTRIES; - int swap_count = voodoo->swap_count; - int written = voodoo->cmd_written + voodoo->cmd_written_fifo; - int busy = (written - voodoo->cmd_read) || (voodoo->cmdfifo_depth_rd != voodoo->cmdfifo_depth_wr); + int fifo_entries = FIFO_ENTRIES; + int swap_count = voodoo->swap_count; + int written = voodoo->cmd_written + voodoo->cmd_written_fifo; + int busy = (written - voodoo->cmd_read) || (voodoo->cmdfifo_depth_rd != voodoo->cmdfifo_depth_wr); - if (SLI_ENABLED && voodoo->type != VOODOO_2) - { - voodoo_t *voodoo_other = (voodoo == voodoo->set->voodoos[0]) ? voodoo->set->voodoos[1] : voodoo->set->voodoos[0]; - int other_written = voodoo_other->cmd_written + voodoo_other->cmd_written_fifo; - - if (voodoo_other->swap_count > swap_count) - swap_count = voodoo_other->swap_count; - if ((voodoo_other->fifo_write_idx - voodoo_other->fifo_read_idx) > fifo_entries) - fifo_entries = voodoo_other->fifo_write_idx - voodoo_other->fifo_read_idx; - if ((other_written - voodoo_other->cmd_read) || - (voodoo_other->cmdfifo_depth_rd != voodoo_other->cmdfifo_depth_wr)) - busy = 1; - if (!voodoo_other->voodoo_busy) - voodoo_wake_fifo_thread(voodoo_other); - } - - fifo_size = 0xffff - fifo_entries; - temp = fifo_size << 12; - if (fifo_size < 0x40) - temp |= fifo_size; - else - temp |= 0x3f; - if (swap_count < 7) - temp |= (swap_count << 28); - else - temp |= (7 << 28); - if (!voodoo->v_retrace) - temp |= 0x40; + if (SLI_ENABLED && voodoo->type != VOODOO_2) { + voodoo_t *voodoo_other = (voodoo == voodoo->set->voodoos[0]) ? voodoo->set->voodoos[1] : voodoo->set->voodoos[0]; + int other_written = voodoo_other->cmd_written + voodoo_other->cmd_written_fifo; - if (busy) - temp |= 0x380; /*Busy*/ + if (voodoo_other->swap_count > swap_count) + swap_count = voodoo_other->swap_count; + if ((voodoo_other->fifo_write_idx - voodoo_other->fifo_read_idx) > fifo_entries) + fifo_entries = voodoo_other->fifo_write_idx - voodoo_other->fifo_read_idx; + if ((other_written - voodoo_other->cmd_read) || (voodoo_other->cmdfifo_depth_rd != voodoo_other->cmdfifo_depth_wr)) + busy = 1; + if (!voodoo_other->voodoo_busy) + voodoo_wake_fifo_thread(voodoo_other); + } - if (!voodoo->voodoo_busy) - voodoo_wake_fifo_thread(voodoo); + fifo_size = 0xffff - fifo_entries; + temp = fifo_size << 12; + if (fifo_size < 0x40) + temp |= fifo_size; + else + temp |= 0x3f; + if (swap_count < 7) + temp |= (swap_count << 28); + else + temp |= (7 << 28); + if (!voodoo->v_retrace) + temp |= 0x40; + + if (busy) + temp |= 0x380; /*Busy*/ + + if (!voodoo->voodoo_busy) + voodoo_wake_fifo_thread(voodoo); } break; - case SST_fbzColorPath: + case SST_fbzColorPath: voodoo_flush(voodoo); temp = voodoo->params.fbzColorPath; break; - case SST_fogMode: + case SST_fogMode: voodoo_flush(voodoo); temp = voodoo->params.fogMode; break; - case SST_alphaMode: + case SST_alphaMode: voodoo_flush(voodoo); temp = voodoo->params.alphaMode; break; - case SST_fbzMode: + case SST_fbzMode: voodoo_flush(voodoo); temp = voodoo->params.fbzMode; - break; - case SST_lfbMode: + break; + case SST_lfbMode: voodoo_flush(voodoo); temp = voodoo->lfbMode; break; - case SST_clipLeftRight: + case SST_clipLeftRight: voodoo_flush(voodoo); temp = voodoo->params.clipRight | (voodoo->params.clipLeft << 16); break; - case SST_clipLowYHighY: + case SST_clipLowYHighY: voodoo_flush(voodoo); temp = voodoo->params.clipHighY | (voodoo->params.clipLowY << 16); break; - case SST_stipple: + case SST_stipple: voodoo_flush(voodoo); temp = voodoo->params.stipple; break; - case SST_color0: + case SST_color0: voodoo_flush(voodoo); temp = voodoo->params.color0; break; - case SST_color1: + case SST_color1: voodoo_flush(voodoo); temp = voodoo->params.color1; break; - - case SST_fbiPixelsIn: + + case SST_fbiPixelsIn: temp = voodoo->fbiPixelsIn & 0xffffff; break; - case SST_fbiChromaFail: + case SST_fbiChromaFail: temp = voodoo->fbiChromaFail & 0xffffff; break; - case SST_fbiZFuncFail: + case SST_fbiZFuncFail: temp = voodoo->fbiZFuncFail & 0xffffff; break; - case SST_fbiAFuncFail: + case SST_fbiAFuncFail: temp = voodoo->fbiAFuncFail & 0xffffff; break; - case SST_fbiPixelsOut: + case SST_fbiPixelsOut: temp = voodoo->fbiPixelsOut & 0xffffff; break; - case SST_fbiInit4: + case SST_fbiInit4: temp = voodoo->fbiInit4; break; - case SST_fbiInit0: + case SST_fbiInit0: temp = voodoo->fbiInit0; break; - case SST_fbiInit1: + case SST_fbiInit1: temp = voodoo->fbiInit1; - break; - case SST_fbiInit2: - if (voodoo->initEnable & 0x04) - temp = voodoo->dac_readdata; - else - temp = voodoo->fbiInit2; break; - case SST_fbiInit3: + case SST_fbiInit2: + if (voodoo->initEnable & 0x04) + temp = voodoo->dac_readdata; + else + temp = voodoo->fbiInit2; + break; + case SST_fbiInit3: temp = voodoo->fbiInit3 | (1 << 10) | (2 << 8); break; - case SST_vRetrace: + case SST_vRetrace: temp = voodoo->line & 0x1fff; break; - case SST_hvRetrace: + case SST_hvRetrace: { - uint32_t line_time = (uint32_t)(voodoo->line_time >> 32); - uint32_t diff = (timer_get_ts_int(&voodoo->timer) > (tsc & 0xffffffff)) ? (timer_get_ts_int(&voodoo->timer) - (tsc & 0xffffffff)) : 0; - uint32_t pre_div = diff * voodoo->h_total; - uint32_t post_div = pre_div / line_time; - uint32_t h_pos = (voodoo->h_total - 1) - post_div; - - if (h_pos >= voodoo->h_total) - h_pos = 0; - - temp = voodoo->line & 0x1fff; - temp |= (h_pos << 16); + uint32_t line_time = (uint32_t) (voodoo->line_time >> 32); + uint32_t diff = (timer_get_ts_int(&voodoo->timer) > (tsc & 0xffffffff)) ? (timer_get_ts_int(&voodoo->timer) - (tsc & 0xffffffff)) : 0; + uint32_t pre_div = diff * voodoo->h_total; + uint32_t post_div = pre_div / line_time; + uint32_t h_pos = (voodoo->h_total - 1) - post_div; + + if (h_pos >= voodoo->h_total) + h_pos = 0; + + temp = voodoo->line & 0x1fff; + temp |= (h_pos << 16); } break; - case SST_fbiInit5: + case SST_fbiInit5: temp = voodoo->fbiInit5 & ~0x1ff; break; - case SST_fbiInit6: + case SST_fbiInit6: temp = voodoo->fbiInit6; break; - case SST_fbiInit7: + case SST_fbiInit7: temp = voodoo->fbiInit7 & ~0xff; break; - case SST_cmdFifoBaseAddr: + case SST_cmdFifoBaseAddr: temp = voodoo->cmdfifo_base >> 12; temp |= (voodoo->cmdfifo_end >> 12) << 16; break; - - case SST_cmdFifoRdPtr: + + case SST_cmdFifoRdPtr: temp = voodoo->cmdfifo_rp; break; - case SST_cmdFifoAMin: + case SST_cmdFifoAMin: temp = voodoo->cmdfifo_amin; break; - case SST_cmdFifoAMax: + case SST_cmdFifoAMax: temp = voodoo->cmdfifo_amax; break; - case SST_cmdFifoDepth: + case SST_cmdFifoDepth: temp = voodoo->cmdfifo_depth_wr - voodoo->cmdfifo_depth_rd; break; - - default: + + default: voodoo_log("voodoo_readl : bad addr %08X\n", addr); temp = 0xffffffff; } - - return temp; + + return temp; } -static void voodoo_writew(uint32_t addr, uint16_t val, void *p) +static void +voodoo_writew(uint32_t addr, uint16_t val, void *priv) { - voodoo_t *voodoo = (voodoo_t *)p; - voodoo->wr_count++; - addr &= 0xffffff; - + voodoo_t *voodoo = (voodoo_t *) priv; + voodoo->wr_count++; + addr &= 0xffffff; + + cycles -= voodoo->write_time; + + if ((addr & 0xc00000) == 0x400000) /*Framebuffer*/ + voodoo_queue_command(voodoo, addr | FIFO_WRITEW_FB, val); +} + +static void +voodoo_writel(uint32_t addr, uint32_t val, void *priv) +{ + voodoo_t *voodoo = (voodoo_t *) priv; + + voodoo->wr_count++; + + addr &= 0xffffff; + + if (addr == voodoo->last_write_addr + 4) + cycles -= voodoo->burst_time; + else cycles -= voodoo->write_time; + voodoo->last_write_addr = addr; - if ((addr & 0xc00000) == 0x400000) /*Framebuffer*/ - voodoo_queue_command(voodoo, addr | FIFO_WRITEW_FB, val); -} - -static void voodoo_writel(uint32_t addr, uint32_t val, void *p) -{ - voodoo_t *voodoo = (voodoo_t *)p; - - voodoo->wr_count++; - - addr &= 0xffffff; - - if (addr == voodoo->last_write_addr+4) - cycles -= voodoo->burst_time; - else - cycles -= voodoo->write_time; - voodoo->last_write_addr = addr; - - if (addr & 0x800000) /*Texture*/ - { - voodoo->tex_count++; - voodoo_queue_command(voodoo, addr | FIFO_WRITEL_TEX, val); - } - else if (addr & 0x400000) /*Framebuffer*/ - { - voodoo_queue_command(voodoo, addr | FIFO_WRITEL_FB, val); - } - else if ((addr & 0x200000) && (voodoo->fbiInit7 & FBIINIT7_CMDFIFO_ENABLE)) - { -// voodoo_log("Write CMDFIFO %08x(%08x) %08x %08x\n", addr, voodoo->cmdfifo_base + (addr & 0x3fffc), val, (voodoo->cmdfifo_base + (addr & 0x3fffc)) & voodoo->fb_mask); - *(uint32_t *)&voodoo->fb_mem[(voodoo->cmdfifo_base + (addr & 0x3fffc)) & voodoo->fb_mask] = val; - voodoo->cmdfifo_depth_wr++; - if ((voodoo->cmdfifo_depth_wr - voodoo->cmdfifo_depth_rd) < 20) - voodoo_wake_fifo_thread(voodoo); - } - else switch (addr & 0x3fc) - { - case SST_intrCtrl: + if (addr & 0x800000) /*Texture*/ + { + voodoo->tex_count++; + voodoo_queue_command(voodoo, addr | FIFO_WRITEL_TEX, val); + } else if (addr & 0x400000) /*Framebuffer*/ + { + voodoo_queue_command(voodoo, addr | FIFO_WRITEL_FB, val); + } else if ((addr & 0x200000) && (voodoo->fbiInit7 & FBIINIT7_CMDFIFO_ENABLE)) { +#if 0 + voodoo_log("Write CMDFIFO %08x(%08x) %08x %08x\n", addr, voodoo->cmdfifo_base + (addr & 0x3fffc), val, (voodoo->cmdfifo_base + (addr & 0x3fffc)) & voodoo->fb_mask); +#endif + *(uint32_t *) &voodoo->fb_mem[(voodoo->cmdfifo_base + (addr & 0x3fffc)) & voodoo->fb_mask] = val; + voodoo->cmdfifo_depth_wr++; + if ((voodoo->cmdfifo_depth_wr - voodoo->cmdfifo_depth_rd) < 20) + voodoo_wake_fifo_thread(voodoo); + } else + switch (addr & 0x3fc) { + case SST_intrCtrl: fatal("intrCtrl write %08x\n", val); break; - case SST_userIntrCMD: + case SST_userIntrCMD: fatal("userIntrCMD write %08x\n", val); break; - - case SST_swapbufferCMD: + + case SST_swapbufferCMD: voodoo->cmd_written++; thread_wait_mutex(voodoo->swap_mutex); voodoo->swap_count++; thread_release_mutex(voodoo->swap_mutex); if (voodoo->fbiInit7 & FBIINIT7_CMDFIFO_ENABLE) - return; + return; voodoo_queue_command(voodoo, addr | FIFO_WRITEL_REG, val); if (!voodoo->voodoo_busy) - voodoo_wake_fifo_threads(voodoo->set, voodoo); + voodoo_wake_fifo_threads(voodoo->set, voodoo); break; - case SST_triangleCMD: + case SST_triangleCMD: if (voodoo->fbiInit7 & FBIINIT7_CMDFIFO_ENABLE) - return; + return; voodoo->cmd_written++; voodoo_queue_command(voodoo, addr | FIFO_WRITEL_REG, val); if (!voodoo->voodoo_busy) - voodoo_wake_fifo_threads(voodoo->set, voodoo); + voodoo_wake_fifo_threads(voodoo->set, voodoo); break; - case SST_ftriangleCMD: + case SST_ftriangleCMD: if (voodoo->fbiInit7 & FBIINIT7_CMDFIFO_ENABLE) - return; + return; voodoo->cmd_written++; voodoo_queue_command(voodoo, addr | FIFO_WRITEL_REG, val); if (!voodoo->voodoo_busy) - voodoo_wake_fifo_threads(voodoo->set, voodoo); + voodoo_wake_fifo_threads(voodoo->set, voodoo); break; - case SST_fastfillCMD: + case SST_fastfillCMD: if (voodoo->fbiInit7 & FBIINIT7_CMDFIFO_ENABLE) - return; + return; voodoo->cmd_written++; voodoo_queue_command(voodoo, addr | FIFO_WRITEL_REG, val); if (!voodoo->voodoo_busy) - voodoo_wake_fifo_threads(voodoo->set, voodoo); + voodoo_wake_fifo_threads(voodoo->set, voodoo); break; - case SST_nopCMD: + case SST_nopCMD: if (voodoo->fbiInit7 & FBIINIT7_CMDFIFO_ENABLE) - return; + return; voodoo->cmd_written++; voodoo_queue_command(voodoo, addr | FIFO_WRITEL_REG, val); if (!voodoo->voodoo_busy) - voodoo_wake_fifo_threads(voodoo->set, voodoo); + voodoo_wake_fifo_threads(voodoo->set, voodoo); break; - - case SST_fbiInit4: - if (voodoo->initEnable & 0x01) - { - voodoo->fbiInit4 = val; - voodoo->read_time = pci_nonburst_time + pci_burst_time * ((voodoo->fbiInit4 & 1) ? 2 : 1); -// voodoo_log("fbiInit4 write %08x - read_time=%i\n", val, voodoo->read_time); + + case SST_fbiInit4: + if (voodoo->initEnable & 0x01) { + voodoo->fbiInit4 = val; + voodoo->read_time = pci_nonburst_time + pci_burst_time * ((voodoo->fbiInit4 & 1) ? 2 : 1); +#if 0 + voodoo_log("fbiInit4 write %08x - read_time=%i\n", val, voodoo->read_time); +#endif } break; - case SST_backPorch: + case SST_backPorch: voodoo->backPorch = val; break; - case SST_videoDimensions: + case SST_videoDimensions: voodoo->videoDimensions = val; - voodoo->h_disp = (val & 0xfff) + 1; - voodoo->v_disp = (val >> 16) & 0xfff; + voodoo->h_disp = (val & 0xfff) + 1; + voodoo->v_disp = (val >> 16) & 0xfff; break; - case SST_fbiInit0: - if (voodoo->initEnable & 0x01) - { - voodoo->fbiInit0 = val; - thread_wait_mutex(voodoo->force_blit_mutex); - voodoo->can_blit = (voodoo->fbiInit0 & FBIINIT0_VGA_PASS) ? 1 : 0; - if (!voodoo->can_blit) - voodoo->force_blit_count = 0; - thread_release_mutex(voodoo->force_blit_mutex); + case SST_fbiInit0: + if (voodoo->initEnable & 0x01) { + voodoo->fbiInit0 = val; + thread_wait_mutex(voodoo->force_blit_mutex); + voodoo->can_blit = (voodoo->fbiInit0 & FBIINIT0_VGA_PASS) ? 1 : 0; + if (!voodoo->can_blit) + voodoo->force_blit_count = 0; + thread_release_mutex(voodoo->force_blit_mutex); - if (voodoo->set->nr_cards == 2) - svga_set_override(voodoo->svga, (voodoo->set->voodoos[0]->fbiInit0 | voodoo->set->voodoos[1]->fbiInit0) & 1); - else - svga_set_override(voodoo->svga, val & 1); - if (val & FBIINIT0_GRAPHICS_RESET) - { - /*Reset display/draw buffer selection. This may not actually - happen here on a real Voodoo*/ - voodoo->disp_buffer = 0; - voodoo->draw_buffer = 1; - voodoo_recalc(voodoo); - voodoo->front_offset = voodoo->params.front_offset; - } - } - break; - case SST_fbiInit1: - if (voodoo->initEnable & 0x01) - { - if ((voodoo->fbiInit1 & FBIINIT1_VIDEO_RESET) && !(val & FBIINIT1_VIDEO_RESET)) - { - voodoo->line = 0; - thread_wait_mutex(voodoo->swap_mutex); - voodoo->swap_count = 0; - thread_release_mutex(voodoo->swap_mutex); - voodoo->retrace_count = 0; - } - voodoo->fbiInit1 = (val & ~5) | (voodoo->fbiInit1 & 5); - voodoo->write_time = pci_nonburst_time + pci_burst_time * ((voodoo->fbiInit1 & 2) ? 1 : 0); - voodoo->burst_time = pci_burst_time * ((voodoo->fbiInit1 & 2) ? 2 : 1); -// voodoo_log("fbiInit1 write %08x - write_time=%i burst_time=%i\n", val, voodoo->write_time, voodoo->burst_time); - } - break; - case SST_fbiInit2: - if (voodoo->initEnable & 0x01) - { - voodoo->fbiInit2 = val; + if (voodoo->set->nr_cards == 2) + svga_set_override(voodoo->svga, (voodoo->set->voodoos[0]->fbiInit0 | voodoo->set->voodoos[1]->fbiInit0) & 1); + else + svga_set_override(voodoo->svga, val & 1); + if (val & FBIINIT0_GRAPHICS_RESET) { + /*Reset display/draw buffer selection. This may not actually + happen here on a real Voodoo*/ + voodoo->disp_buffer = 0; + voodoo->draw_buffer = 1; voodoo_recalc(voodoo); + voodoo->front_offset = voodoo->params.front_offset; + } } break; - case SST_fbiInit3: + case SST_fbiInit1: + if (voodoo->initEnable & 0x01) { + if ((voodoo->fbiInit1 & FBIINIT1_VIDEO_RESET) && !(val & FBIINIT1_VIDEO_RESET)) { + voodoo->line = 0; + thread_wait_mutex(voodoo->swap_mutex); + voodoo->swap_count = 0; + thread_release_mutex(voodoo->swap_mutex); + voodoo->retrace_count = 0; + } + voodoo->fbiInit1 = (val & ~5) | (voodoo->fbiInit1 & 5); + voodoo->write_time = pci_nonburst_time + pci_burst_time * ((voodoo->fbiInit1 & 2) ? 1 : 0); + voodoo->burst_time = pci_burst_time * ((voodoo->fbiInit1 & 2) ? 2 : 1); +#if 0 + voodoo_log("fbiInit1 write %08x - write_time=%i burst_time=%i\n", val, voodoo->write_time, voodoo->burst_time); +#endif + } + break; + case SST_fbiInit2: + if (voodoo->initEnable & 0x01) { + voodoo->fbiInit2 = val; + voodoo_recalc(voodoo); + } + break; + case SST_fbiInit3: if (voodoo->initEnable & 0x01) - voodoo->fbiInit3 = val; + voodoo->fbiInit3 = val; break; - case SST_hSync: - voodoo->hSync = val; + case SST_hSync: + voodoo->hSync = val; voodoo->h_total = (val & 0xffff) + (val >> 16); voodoo_pixelclock_update(voodoo); break; - case SST_vSync: - voodoo->vSync = val; + case SST_vSync: + voodoo->vSync = val; voodoo->v_total = (val & 0xffff) + (val >> 16); break; - - case SST_clutData: + + case SST_clutData: voodoo->clutData[(val >> 24) & 0x3f].b = val & 0xff; voodoo->clutData[(val >> 24) & 0x3f].g = (val >> 8) & 0xff; voodoo->clutData[(val >> 24) & 0x3f].r = (val >> 16) & 0xff; - if (val & 0x20000000) - { - voodoo->clutData[(val >> 24) & 0x3f].b = 255; - voodoo->clutData[(val >> 24) & 0x3f].g = 255; - voodoo->clutData[(val >> 24) & 0x3f].r = 255; + if (val & 0x20000000) { + voodoo->clutData[(val >> 24) & 0x3f].b = 255; + voodoo->clutData[(val >> 24) & 0x3f].g = 255; + voodoo->clutData[(val >> 24) & 0x3f].r = 255; } voodoo->clutData_dirty = 1; break; - case SST_dacData: - voodoo->dac_reg = (val >> 8) & 7; + case SST_dacData: + voodoo->dac_reg = (val >> 8) & 7; voodoo->dac_readdata = 0xff; - if (val & 0x800) - { -// voodoo_log(" dacData read %i %02X\n", voodoo->dac_reg, voodoo->dac_data[7]); - if (voodoo->dac_reg == 5) - { - switch (voodoo->dac_data[7]) - { - case 0x01: voodoo->dac_readdata = 0x55; break; - case 0x07: voodoo->dac_readdata = 0x71; break; - case 0x0b: voodoo->dac_readdata = 0x79; break; - } + if (val & 0x800) { + // voodoo_log(" dacData read %i %02X\n", voodoo->dac_reg, voodoo->dac_data[7]); + if (voodoo->dac_reg == 5) { + switch (voodoo->dac_data[7]) { + case 0x01: + voodoo->dac_readdata = 0x55; + break; + case 0x07: + voodoo->dac_readdata = 0x71; + break; + case 0x0b: + voodoo->dac_readdata = 0x79; + break; + + default: + break; } + } else + voodoo->dac_readdata = voodoo->dac_data[voodoo->dac_readdata & 7]; + } else { + if (voodoo->dac_reg == 5) { + if (!voodoo->dac_reg_ff) + voodoo->dac_pll_regs[voodoo->dac_data[4] & 0xf] = (voodoo->dac_pll_regs[voodoo->dac_data[4] & 0xf] & 0xff00) | val; else - voodoo->dac_readdata = voodoo->dac_data[voodoo->dac_readdata & 7]; - } - else - { - if (voodoo->dac_reg == 5) - { - if (!voodoo->dac_reg_ff) - voodoo->dac_pll_regs[voodoo->dac_data[4] & 0xf] = (voodoo->dac_pll_regs[voodoo->dac_data[4] & 0xf] & 0xff00) | val; - else - voodoo->dac_pll_regs[voodoo->dac_data[4] & 0xf] = (voodoo->dac_pll_regs[voodoo->dac_data[4] & 0xf] & 0xff) | (val << 8); -// voodoo_log("Write PLL reg %x %04x\n", voodoo->dac_data[4] & 0xf, voodoo->dac_pll_regs[voodoo->dac_data[4] & 0xf]); - voodoo->dac_reg_ff = !voodoo->dac_reg_ff; - if (!voodoo->dac_reg_ff) - voodoo->dac_data[4]++; + voodoo->dac_pll_regs[voodoo->dac_data[4] & 0xf] = (voodoo->dac_pll_regs[voodoo->dac_data[4] & 0xf] & 0xff) | (val << 8); +#if 0 + voodoo_log("Write PLL reg %x %04x\n", voodoo->dac_data[4] & 0xf, voodoo->dac_pll_regs[voodoo->dac_data[4] & 0xf]); +#endif + voodoo->dac_reg_ff = !voodoo->dac_reg_ff; + if (!voodoo->dac_reg_ff) + voodoo->dac_data[4]++; - } - else - { - voodoo->dac_data[voodoo->dac_reg] = val & 0xff; - voodoo->dac_reg_ff = 0; - } - voodoo_pixelclock_update(voodoo); + } else { + voodoo->dac_data[voodoo->dac_reg] = val & 0xff; + voodoo->dac_reg_ff = 0; + } + voodoo_pixelclock_update(voodoo); } break; - case SST_scrFilter: - if (voodoo->initEnable & 0x01) - { - voodoo->scrfilterEnabled = 1; - voodoo->scrfilterThreshold = val; /* update the threshold values and generate a new lookup table if necessary */ - - if (val < 1) - voodoo->scrfilterEnabled = 0; - voodoo_threshold_check(voodoo); - voodoo_log("Voodoo Filter: %06x\n", val); - } - break; + case SST_scrFilter: + if (voodoo->initEnable & 0x01) { + voodoo->scrfilterEnabled = 1; + voodoo->scrfilterThreshold = val; /* update the threshold values and generate a new lookup table if necessary */ - case SST_fbiInit5: - if (voodoo->initEnable & 0x01) - voodoo->fbiInit5 = (val & ~0x41e6) | (voodoo->fbiInit5 & 0x41e6); - break; - case SST_fbiInit6: - if (voodoo->initEnable & 0x01) - voodoo->fbiInit6 = val; - break; - case SST_fbiInit7: - if (voodoo->initEnable & 0x01) - { - voodoo->fbiInit7 = val; - voodoo->cmdfifo_enabled = val & 0x100; + if (val < 1) + voodoo->scrfilterEnabled = 0; + voodoo_threshold_check(voodoo); + voodoo_log("Voodoo Filter: %06x\n", val); } break; - case SST_cmdFifoBaseAddr: + case SST_fbiInit5: + if (voodoo->initEnable & 0x01) + voodoo->fbiInit5 = (val & ~0x41e6) | (voodoo->fbiInit5 & 0x41e6); + break; + case SST_fbiInit6: + if (voodoo->initEnable & 0x01) + voodoo->fbiInit6 = val; + break; + case SST_fbiInit7: + if (voodoo->initEnable & 0x01) { + voodoo->fbiInit7 = val; + voodoo->cmdfifo_enabled = val & 0x100; + } + break; + + case SST_cmdFifoBaseAddr: voodoo->cmdfifo_base = (val & 0x3ff) << 12; - voodoo->cmdfifo_end = ((val >> 16) & 0x3ff) << 12; -// voodoo_log("CMDFIFO base=%08x end=%08x\n", voodoo->cmdfifo_base, voodoo->cmdfifo_end); + voodoo->cmdfifo_end = ((val >> 16) & 0x3ff) << 12; +#if 0 + voodoo_log("CMDFIFO base=%08x end=%08x\n", voodoo->cmdfifo_base, voodoo->cmdfifo_end); +#endif break; - case SST_cmdFifoRdPtr: + case SST_cmdFifoRdPtr: voodoo->cmdfifo_rp = val; break; - case SST_cmdFifoAMin: + case SST_cmdFifoAMin: voodoo->cmdfifo_amin = val; break; - case SST_cmdFifoAMax: + case SST_cmdFifoAMax: voodoo->cmdfifo_amax = val; break; - case SST_cmdFifoDepth: + case SST_cmdFifoDepth: voodoo->cmdfifo_depth_rd = 0; voodoo->cmdfifo_depth_wr = val & 0xffff; break; - default: - if (voodoo->fbiInit7 & FBIINIT7_CMDFIFO_ENABLE) - { - voodoo_log("Unknown register write in CMDFIFO mode %08x %08x\n", addr, val); - } - else - { - voodoo_queue_command(voodoo, addr | FIFO_WRITEL_REG, val); + default: + if (voodoo->fbiInit7 & FBIINIT7_CMDFIFO_ENABLE) { + voodoo_log("Unknown register write in CMDFIFO mode %08x %08x\n", addr, val); + } else { + voodoo_queue_command(voodoo, addr | FIFO_WRITEL_REG, val); } break; } } -static uint16_t voodoo_snoop_readw(uint32_t addr, void *p) +static uint16_t +voodoo_snoop_readw(uint32_t addr, void *priv) { - voodoo_set_t *set = (voodoo_set_t *)p; - - return voodoo_readw(addr, set->voodoos[0]); + const voodoo_set_t *set = (voodoo_set_t *) priv; + + return voodoo_readw(addr, set->voodoos[0]); } -static uint32_t voodoo_snoop_readl(uint32_t addr, void *p) +static uint32_t +voodoo_snoop_readl(uint32_t addr, void *priv) { - voodoo_set_t *set = (voodoo_set_t *)p; - - return voodoo_readl(addr, set->voodoos[0]); + const voodoo_set_t *set = (voodoo_set_t *) priv; + + return voodoo_readl(addr, set->voodoos[0]); } -static void voodoo_snoop_writew(uint32_t addr, uint16_t val, void *p) +static void +voodoo_snoop_writew(uint32_t addr, uint16_t val, void *priv) { - voodoo_set_t *set = (voodoo_set_t *)p; + const voodoo_set_t *set = (voodoo_set_t *) priv; - voodoo_writew(addr, val, set->voodoos[0]); - voodoo_writew(addr, val, set->voodoos[1]); + voodoo_writew(addr, val, set->voodoos[0]); + voodoo_writew(addr, val, set->voodoos[1]); } -static void voodoo_snoop_writel(uint32_t addr, uint32_t val, void *p) +static void +voodoo_snoop_writel(uint32_t addr, uint32_t val, void *priv) { - voodoo_set_t *set = (voodoo_set_t *)p; + const voodoo_set_t *set = (voodoo_set_t *) priv; - voodoo_writel(addr, val, set->voodoos[0]); - voodoo_writel(addr, val, set->voodoos[1]); + voodoo_writel(addr, val, set->voodoos[0]); + voodoo_writel(addr, val, set->voodoos[1]); } -static void voodoo_recalcmapping(voodoo_set_t *set) +static void +voodoo_recalcmapping(voodoo_set_t *set) { - if (set->nr_cards == 2) - { - if (set->voodoos[0]->pci_enable && set->voodoos[0]->memBaseAddr) - { - if (set->voodoos[0]->type == VOODOO_2 && set->voodoos[1]->initEnable & (1 << 23)) - { - voodoo_log("voodoo_recalcmapping (pri) with snoop : memBaseAddr %08X\n", set->voodoos[0]->memBaseAddr); - mem_mapping_disable(&set->voodoos[0]->mapping); - mem_mapping_set_addr(&set->snoop_mapping, set->voodoos[0]->memBaseAddr, 0x01000000); - } - else if (set->voodoos[1]->pci_enable && (set->voodoos[0]->memBaseAddr == set->voodoos[1]->memBaseAddr)) - { - voodoo_log("voodoo_recalcmapping (pri) (sec) same addr : memBaseAddr %08X\n", set->voodoos[0]->memBaseAddr); - mem_mapping_disable(&set->voodoos[0]->mapping); - mem_mapping_disable(&set->voodoos[1]->mapping); - mem_mapping_set_addr(&set->snoop_mapping, set->voodoos[0]->memBaseAddr, 0x01000000); - return; - } - else - { - voodoo_log("voodoo_recalcmapping (pri) : memBaseAddr %08X\n", set->voodoos[0]->memBaseAddr); - mem_mapping_disable(&set->snoop_mapping); - mem_mapping_set_addr(&set->voodoos[0]->mapping, set->voodoos[0]->memBaseAddr, 0x01000000); - } - } - else - { - voodoo_log("voodoo_recalcmapping (pri) : disabled\n"); - mem_mapping_disable(&set->voodoos[0]->mapping); - } - - if (set->voodoos[1]->pci_enable && set->voodoos[1]->memBaseAddr) - { - voodoo_log("voodoo_recalcmapping (sec) : memBaseAddr %08X\n", set->voodoos[1]->memBaseAddr); - mem_mapping_set_addr(&set->voodoos[1]->mapping, set->voodoos[1]->memBaseAddr, 0x01000000); - } - else - { - voodoo_log("voodoo_recalcmapping (sec) : disabled\n"); - mem_mapping_disable(&set->voodoos[1]->mapping); - } - } - else - { - voodoo_t *voodoo = set->voodoos[0]; - - if (voodoo->pci_enable && voodoo->memBaseAddr) - { - voodoo_log("voodoo_recalcmapping : memBaseAddr %08X\n", voodoo->memBaseAddr); - mem_mapping_set_addr(&voodoo->mapping, voodoo->memBaseAddr, 0x01000000); - } - else - { - voodoo_log("voodoo_recalcmapping : disabled\n"); - mem_mapping_disable(&voodoo->mapping); - } - } -} - -uint8_t voodoo_pci_read(int func, int addr, void *p) -{ - voodoo_t *voodoo = (voodoo_t *)p; - - if (func) - return 0; - -// voodoo_log("Voodoo PCI read %08X PC=%08x\n", addr, cpu_state.pc); - - switch (addr) - { - case 0x00: return 0x1a; /*3dfx*/ - case 0x01: return 0x12; - - case 0x02: - if (voodoo->type == VOODOO_2) - return 0x02; /*Voodoo 2*/ - else - return 0x01; /*SST-1 (Voodoo Graphics)*/ - case 0x03: return 0x00; - - case 0x04: return voodoo->pci_enable ? 0x02 : 0x00; /*Respond to memory accesses*/ - - case 0x08: return 2; /*Revision ID*/ - case 0x09: return 0; /*Programming interface*/ - case 0x0a: return 0; - case 0x0b: return 0x04; - - case 0x10: return 0x00; /*memBaseAddr*/ - case 0x11: return 0x00; - case 0x12: return 0x00; - case 0x13: return voodoo->memBaseAddr >> 24; - - case 0x40: - return voodoo->initEnable & 0xff; - case 0x41: - if (voodoo->type == VOODOO_2) - return 0x50 | ((voodoo->initEnable >> 8) & 0x0f); - return (voodoo->initEnable >> 8) & 0x0f; - case 0x42: - return (voodoo->initEnable >> 16) & 0xff; - case 0x43: - return (voodoo->initEnable >> 24) & 0xff; - } - return 0; -} - -void voodoo_pci_write(int func, int addr, uint8_t val, void *p) -{ - voodoo_t *voodoo = (voodoo_t *)p; - - if (func) + if (set->nr_cards == 2) { + if (set->voodoos[0]->pci_enable && set->voodoos[0]->memBaseAddr) { + if (set->voodoos[0]->type == VOODOO_2 && set->voodoos[1]->initEnable & (1 << 23)) { + voodoo_log("voodoo_recalcmapping (pri) with snoop : memBaseAddr %08X\n", set->voodoos[0]->memBaseAddr); + mem_mapping_disable(&set->voodoos[0]->mapping); + mem_mapping_set_addr(&set->snoop_mapping, set->voodoos[0]->memBaseAddr, 0x01000000); + } else if (set->voodoos[1]->pci_enable && (set->voodoos[0]->memBaseAddr == set->voodoos[1]->memBaseAddr)) { + voodoo_log("voodoo_recalcmapping (pri) (sec) same addr : memBaseAddr %08X\n", set->voodoos[0]->memBaseAddr); + mem_mapping_disable(&set->voodoos[0]->mapping); + mem_mapping_disable(&set->voodoos[1]->mapping); + mem_mapping_set_addr(&set->snoop_mapping, set->voodoos[0]->memBaseAddr, 0x01000000); return; - -// voodoo_log("Voodoo PCI write %04X %02X PC=%08x\n", addr, val, cpu_state.pc); - - switch (addr) - { - case 0x04: - voodoo->pci_enable = val & 2; - voodoo_recalcmapping(voodoo->set); - break; - - case 0x13: - voodoo->memBaseAddr = val << 24; - voodoo_recalcmapping(voodoo->set); - break; - - case 0x40: - voodoo->initEnable = (voodoo->initEnable & ~0x000000ff) | val; - break; - case 0x41: - voodoo->initEnable = (voodoo->initEnable & ~0x0000ff00) | (val << 8); - break; - case 0x42: - voodoo->initEnable = (voodoo->initEnable & ~0x00ff0000) | (val << 16); - voodoo_recalcmapping(voodoo->set); - break; - case 0x43: - voodoo->initEnable = (voodoo->initEnable & ~0xff000000) | (val << 24); - voodoo_recalcmapping(voodoo->set); - break; - } -} - - -static void voodoo_speed_changed(void *p) -{ - voodoo_set_t *voodoo_set = (voodoo_set_t *)p; - - voodoo_pixelclock_update(voodoo_set->voodoos[0]); - voodoo_set->voodoos[0]->read_time = pci_nonburst_time + pci_burst_time * ((voodoo_set->voodoos[0]->fbiInit4 & 1) ? 2 : 1); - voodoo_set->voodoos[0]->write_time = pci_nonburst_time + pci_burst_time * ((voodoo_set->voodoos[0]->fbiInit1 & 2) ? 1 : 0); - voodoo_set->voodoos[0]->burst_time = pci_burst_time * ((voodoo_set->voodoos[0]->fbiInit1 & 2) ? 2 : 1); - if (voodoo_set->nr_cards == 2) - { - voodoo_pixelclock_update(voodoo_set->voodoos[1]); - voodoo_set->voodoos[1]->read_time = pci_nonburst_time + pci_burst_time * ((voodoo_set->voodoos[1]->fbiInit4 & 1) ? 2 : 1); - voodoo_set->voodoos[1]->write_time = pci_nonburst_time + pci_burst_time * ((voodoo_set->voodoos[1]->fbiInit1 & 2) ? 1 : 0); - voodoo_set->voodoos[1]->burst_time = pci_burst_time * ((voodoo_set->voodoos[1]->fbiInit1 & 2) ? 2 : 1); - } -// voodoo_log("Voodoo read_time=%i write_time=%i burst_time=%i %08x %08x\n", voodoo->read_time, voodoo->write_time, voodoo->burst_time, voodoo->fbiInit1, voodoo->fbiInit4); -} - -static void voodoo_force_blit(void *p) -{ - voodoo_set_t *voodoo_set = (voodoo_set_t *)p; - - thread_wait_mutex(voodoo_set->voodoos[0]->force_blit_mutex); - if(voodoo_set->voodoos[0]->can_blit) { - voodoo_set->voodoos[0]->force_blit_count++; - } - thread_release_mutex(voodoo_set->voodoos[0]->force_blit_mutex); - if(voodoo_set->nr_cards == 2) { - thread_wait_mutex(voodoo_set->voodoos[1]->force_blit_mutex); - if(voodoo_set->voodoos[1]->can_blit) { - voodoo_set->voodoos[1]->force_blit_count++; + } else { + voodoo_log("voodoo_recalcmapping (pri) : memBaseAddr %08X\n", set->voodoos[0]->memBaseAddr); + mem_mapping_disable(&set->snoop_mapping); + mem_mapping_set_addr(&set->voodoos[0]->mapping, set->voodoos[0]->memBaseAddr, 0x01000000); } - thread_release_mutex(voodoo_set->voodoos[1]->force_blit_mutex); + } else { + voodoo_log("voodoo_recalcmapping (pri) : disabled\n"); + mem_mapping_disable(&set->voodoos[0]->mapping); } + + if (set->voodoos[1]->pci_enable && set->voodoos[1]->memBaseAddr) { + voodoo_log("voodoo_recalcmapping (sec) : memBaseAddr %08X\n", set->voodoos[1]->memBaseAddr); + mem_mapping_set_addr(&set->voodoos[1]->mapping, set->voodoos[1]->memBaseAddr, 0x01000000); + } else { + voodoo_log("voodoo_recalcmapping (sec) : disabled\n"); + mem_mapping_disable(&set->voodoos[1]->mapping); + } + } else { + voodoo_t *voodoo = set->voodoos[0]; + + if (voodoo->pci_enable && voodoo->memBaseAddr) { + voodoo_log("voodoo_recalcmapping : memBaseAddr %08X\n", voodoo->memBaseAddr); + mem_mapping_set_addr(&voodoo->mapping, voodoo->memBaseAddr, 0x01000000); + } else { + voodoo_log("voodoo_recalcmapping : disabled\n"); + mem_mapping_disable(&voodoo->mapping); + } + } } -void *voodoo_card_init() +uint8_t +voodoo_pci_read(int func, int addr, void *priv) { - int c; - voodoo_t *voodoo = malloc(sizeof(voodoo_t)); - memset(voodoo, 0, sizeof(voodoo_t)); + const voodoo_t *voodoo = (voodoo_t *) priv; - voodoo->bilinear_enabled = device_get_config_int("bilinear"); - voodoo->dithersub_enabled = device_get_config_int("dithersub"); - voodoo->scrfilter = device_get_config_int("dacfilter"); - voodoo->texture_size = device_get_config_int("texture_memory"); - voodoo->texture_mask = (voodoo->texture_size << 20) - 1; - voodoo->fb_size = device_get_config_int("framebuffer_memory"); - voodoo->fb_mask = (voodoo->fb_size << 20) - 1; - voodoo->render_threads = device_get_config_int("render_threads"); - voodoo->odd_even_mask = voodoo->render_threads - 1; -#ifndef NO_CODEGEN - voodoo->use_recompiler = device_get_config_int("recompiler"); -#endif - voodoo->type = device_get_config_int("type"); - switch (voodoo->type) { - case VOODOO_1: - voodoo->dual_tmus = 0; - break; - case VOODOO_SB50: - voodoo->dual_tmus = 1; - break; - case VOODOO_2: - voodoo->dual_tmus = 1; - break; - } - - if (voodoo->type == VOODOO_2) /*generate filter lookup tables*/ - voodoo_generate_filter_v2(voodoo); - else - voodoo_generate_filter_v1(voodoo); - - pci_add_card(PCI_ADD_NORMAL, voodoo_pci_read, voodoo_pci_write, voodoo); + if (func) + return 0; - mem_mapping_add(&voodoo->mapping, 0, 0, NULL, voodoo_readw, voodoo_readl, NULL, voodoo_writew, voodoo_writel, NULL, MEM_MAPPING_EXTERNAL, voodoo); - - voodoo->fb_mem = malloc(4 * 1024 * 1024); - voodoo->tex_mem[0] = malloc(voodoo->texture_size * 1024 * 1024); - if (voodoo->dual_tmus) - voodoo->tex_mem[1] = malloc(voodoo->texture_size * 1024 * 1024); - voodoo->tex_mem_w[0] = (uint16_t *)voodoo->tex_mem[0]; - voodoo->tex_mem_w[1] = (uint16_t *)voodoo->tex_mem[1]; - - for (c = 0; c < TEX_CACHE_MAX; c++) { - voodoo->texture_cache[0][c].data = malloc((256*256 + 256*256 + 128*128 + 64*64 + 32*32 + 16*16 + 8*8 + 4*4 + 2*2) * 4); - voodoo->texture_cache[0][c].base = -1; /*invalid*/ - voodoo->texture_cache[0][c].refcount = 0; - if (voodoo->dual_tmus) - { - voodoo->texture_cache[1][c].data = malloc((256*256 + 256*256 + 128*128 + 64*64 + 32*32 + 16*16 + 8*8 + 4*4 + 2*2) * 4); - voodoo->texture_cache[1][c].base = -1; /*invalid*/ - voodoo->texture_cache[1][c].refcount = 0; - } - } - - timer_add(&voodoo->timer, voodoo_callback, voodoo, 1); - - voodoo->svga = svga_get_pri(); - voodoo->fbiInit0 = 0; - - voodoo->wake_fifo_thread = thread_create_event(); - voodoo->wake_render_thread[0] = thread_create_event(); - voodoo->wake_render_thread[1] = thread_create_event(); - voodoo->wake_render_thread[2] = thread_create_event(); - voodoo->wake_render_thread[3] = thread_create_event(); - voodoo->wake_main_thread = thread_create_event(); - voodoo->fifo_not_full_event = thread_create_event(); - voodoo->render_not_full_event[0] = thread_create_event(); - voodoo->render_not_full_event[1] = thread_create_event(); - voodoo->render_not_full_event[2] = thread_create_event(); - voodoo->render_not_full_event[3] = thread_create_event(); - voodoo->fifo_thread_run = 1; - voodoo->fifo_thread = thread_create(voodoo_fifo_thread, voodoo); - voodoo->render_thread_run[0] = 1; - voodoo->render_thread[0] = thread_create(voodoo_render_thread_1, voodoo); - if (voodoo->render_threads >= 2) { - voodoo->render_thread_run[1] = 1; - voodoo->render_thread[1] = thread_create(voodoo_render_thread_2, voodoo); - } - if (voodoo->render_threads == 4) { - voodoo->render_thread_run[2] = 1; - voodoo->render_thread[2] = thread_create(voodoo_render_thread_3, voodoo); - voodoo->render_thread_run[3] = 1; - voodoo->render_thread[3] = thread_create(voodoo_render_thread_4, voodoo); - } - voodoo->swap_mutex = thread_create_mutex(); - timer_add(&voodoo->wake_timer, voodoo_wake_timer, (void *)voodoo, 0); - - for (c = 0; c < 0x100; c++) { - rgb332[c].r = c & 0xe0; - rgb332[c].g = (c << 3) & 0xe0; - rgb332[c].b = (c << 6) & 0xc0; - rgb332[c].r = rgb332[c].r | (rgb332[c].r >> 3) | (rgb332[c].r >> 6); - rgb332[c].g = rgb332[c].g | (rgb332[c].g >> 3) | (rgb332[c].g >> 6); - rgb332[c].b = rgb332[c].b | (rgb332[c].b >> 2); - rgb332[c].b = rgb332[c].b | (rgb332[c].b >> 4); - rgb332[c].a = 0xff; - - ai44[c].a = (c & 0xf0) | ((c & 0xf0) >> 4); - ai44[c].r = (c & 0x0f) | ((c & 0x0f) << 4); - ai44[c].g = ai44[c].b = ai44[c].r; - } - - for (c = 0; c < 0x10000; c++) { - rgb565[c].r = (c >> 8) & 0xf8; - rgb565[c].g = (c >> 3) & 0xfc; - rgb565[c].b = (c << 3) & 0xf8; - rgb565[c].r |= (rgb565[c].r >> 5); - rgb565[c].g |= (rgb565[c].g >> 6); - rgb565[c].b |= (rgb565[c].b >> 5); - rgb565[c].a = 0xff; - - argb1555[c].r = (c >> 7) & 0xf8; - argb1555[c].g = (c >> 2) & 0xf8; - argb1555[c].b = (c << 3) & 0xf8; - argb1555[c].r |= (argb1555[c].r >> 5); - argb1555[c].g |= (argb1555[c].g >> 5); - argb1555[c].b |= (argb1555[c].b >> 5); - argb1555[c].a = (c & 0x8000) ? 0xff : 0; - - argb4444[c].a = (c >> 8) & 0xf0; - argb4444[c].r = (c >> 4) & 0xf0; - argb4444[c].g = c & 0xf0; - argb4444[c].b = (c << 4) & 0xf0; - argb4444[c].a |= (argb4444[c].a >> 4); - argb4444[c].r |= (argb4444[c].r >> 4); - argb4444[c].g |= (argb4444[c].g >> 4); - argb4444[c].b |= (argb4444[c].b >> 4); - - ai88[c].a = (c >> 8); - ai88[c].r = c & 0xff; - ai88[c].g = c & 0xff; - ai88[c].b = c & 0xff; - } -#ifndef NO_CODEGEN - voodoo_codegen_init(voodoo); +#if 0 + voodoo_log("Voodoo PCI read %08X PC=%08x\n", addr, cpu_state.pc); #endif - voodoo->disp_buffer = 0; - voodoo->draw_buffer = 1; + switch (addr) { + case 0x00: + return 0x1a; /*3dfx*/ + case 0x01: + return 0x12; - voodoo->force_blit_count = 0; - voodoo->can_blit = 0; - voodoo->force_blit_mutex = thread_create_mutex(); - - return voodoo; + case 0x02: + if (voodoo->type == VOODOO_2) + return 0x02; /*Voodoo 2*/ + else + return 0x01; /*SST-1 (Voodoo Graphics)*/ + case 0x03: + return 0x00; + + case 0x04: + return voodoo->pci_enable ? 0x02 : 0x00; /*Respond to memory accesses*/ + + case 0x08: + return 2; /*Revision ID*/ + case 0x09: + return 0; /*Programming interface*/ + case 0x0a: + return 0; + case 0x0b: + return 0x04; + + case 0x10: + return 0x00; /*memBaseAddr*/ + case 0x11: + return 0x00; + case 0x12: + return 0x00; + case 0x13: + return voodoo->memBaseAddr >> 24; + + case 0x40: + return voodoo->initEnable & 0xff; + case 0x41: + if (voodoo->type == VOODOO_2) + return 0x50 | ((voodoo->initEnable >> 8) & 0x0f); + return (voodoo->initEnable >> 8) & 0x0f; + case 0x42: + return (voodoo->initEnable >> 16) & 0xff; + case 0x43: + return (voodoo->initEnable >> 24) & 0xff; + + default: + break; + } + return 0; } -void *voodoo_2d3d_card_init(int type) +void +voodoo_pci_write(int func, int addr, uint8_t val, void *priv) { - int c; - voodoo_t *voodoo = malloc(sizeof(voodoo_t)); - memset(voodoo, 0, sizeof(voodoo_t)); + voodoo_t *voodoo = (voodoo_t *) priv; - voodoo->bilinear_enabled = device_get_config_int("bilinear"); - voodoo->dithersub_enabled = device_get_config_int("dithersub"); - voodoo->scrfilter = device_get_config_int("dacfilter"); - voodoo->render_threads = device_get_config_int("render_threads"); - voodoo->odd_even_mask = voodoo->render_threads - 1; -#ifndef NO_CODEGEN - voodoo->use_recompiler = device_get_config_int("recompiler"); -#endif - voodoo->type = type; - voodoo->dual_tmus = (type == VOODOO_3) ? 1 : 0; + if (func) + return; - /*generate filter lookup tables*/ - voodoo_generate_filter_v2(voodoo); - - for (c = 0; c < TEX_CACHE_MAX; c++) { - voodoo->texture_cache[0][c].data = malloc((256*256 + 256*256 + 128*128 + 64*64 + 32*32 + 16*16 + 8*8 + 4*4 + 2*2) * 4); - voodoo->texture_cache[0][c].base = -1; /*invalid*/ - voodoo->texture_cache[0][c].refcount = 0; - if (voodoo->dual_tmus) - { - voodoo->texture_cache[1][c].data = malloc((256*256 + 256*256 + 128*128 + 64*64 + 32*32 + 16*16 + 8*8 + 4*4 + 2*2) * 4); - voodoo->texture_cache[1][c].base = -1; /*invalid*/ - voodoo->texture_cache[1][c].refcount = 0; - } - } - - timer_add(&voodoo->timer, voodoo_callback, voodoo, 1); - - voodoo->fbiInit0 = 0; - - voodoo->wake_fifo_thread = thread_create_event(); - voodoo->wake_render_thread[0] = thread_create_event(); - voodoo->wake_render_thread[1] = thread_create_event(); - voodoo->wake_render_thread[2] = thread_create_event(); - voodoo->wake_render_thread[3] = thread_create_event(); - voodoo->wake_main_thread = thread_create_event(); - voodoo->fifo_not_full_event = thread_create_event(); - voodoo->render_not_full_event[0] = thread_create_event(); - voodoo->render_not_full_event[1] = thread_create_event(); - voodoo->render_not_full_event[2] = thread_create_event(); - voodoo->render_not_full_event[3] = thread_create_event(); - voodoo->fifo_thread_run = 1; - voodoo->fifo_thread = thread_create(voodoo_fifo_thread, voodoo); - voodoo->render_thread_run[0] = 1; - voodoo->render_thread[0] = thread_create(voodoo_render_thread_1, voodoo); - if (voodoo->render_threads >= 2) { - voodoo->render_thread_run[1] = 1; - voodoo->render_thread[1] = thread_create(voodoo_render_thread_2, voodoo); - } - if (voodoo->render_threads == 4) { - voodoo->render_thread_run[2] = 1; - voodoo->render_thread[2] = thread_create(voodoo_render_thread_3, voodoo); - voodoo->render_thread_run[3] = 1; - voodoo->render_thread[3] = thread_create(voodoo_render_thread_4, voodoo); - } - voodoo->swap_mutex = thread_create_mutex(); - timer_add(&voodoo->wake_timer, voodoo_wake_timer, (void *)voodoo, 0); - - for (c = 0; c < 0x100; c++) { - rgb332[c].r = c & 0xe0; - rgb332[c].g = (c << 3) & 0xe0; - rgb332[c].b = (c << 6) & 0xc0; - rgb332[c].r = rgb332[c].r | (rgb332[c].r >> 3) | (rgb332[c].r >> 6); - rgb332[c].g = rgb332[c].g | (rgb332[c].g >> 3) | (rgb332[c].g >> 6); - rgb332[c].b = rgb332[c].b | (rgb332[c].b >> 2); - rgb332[c].b = rgb332[c].b | (rgb332[c].b >> 4); - rgb332[c].a = 0xff; - - ai44[c].a = (c & 0xf0) | ((c & 0xf0) >> 4); - ai44[c].r = (c & 0x0f) | ((c & 0x0f) << 4); - ai44[c].g = ai44[c].b = ai44[c].r; - } - - for (c = 0; c < 0x10000; c++) { - rgb565[c].r = (c >> 8) & 0xf8; - rgb565[c].g = (c >> 3) & 0xfc; - rgb565[c].b = (c << 3) & 0xf8; - rgb565[c].r |= (rgb565[c].r >> 5); - rgb565[c].g |= (rgb565[c].g >> 6); - rgb565[c].b |= (rgb565[c].b >> 5); - rgb565[c].a = 0xff; - - argb1555[c].r = (c >> 7) & 0xf8; - argb1555[c].g = (c >> 2) & 0xf8; - argb1555[c].b = (c << 3) & 0xf8; - argb1555[c].r |= (argb1555[c].r >> 5); - argb1555[c].g |= (argb1555[c].g >> 5); - argb1555[c].b |= (argb1555[c].b >> 5); - argb1555[c].a = (c & 0x8000) ? 0xff : 0; - - argb4444[c].a = (c >> 8) & 0xf0; - argb4444[c].r = (c >> 4) & 0xf0; - argb4444[c].g = c & 0xf0; - argb4444[c].b = (c << 4) & 0xf0; - argb4444[c].a |= (argb4444[c].a >> 4); - argb4444[c].r |= (argb4444[c].r >> 4); - argb4444[c].g |= (argb4444[c].g >> 4); - argb4444[c].b |= (argb4444[c].b >> 4); - - ai88[c].a = (c >> 8); - ai88[c].r = c & 0xff; - ai88[c].g = c & 0xff; - ai88[c].b = c & 0xff; - } -#ifndef NO_CODEGEN - voodoo_codegen_init(voodoo); +#if 0 + voodoo_log("Voodoo PCI write %04X %02X PC=%08x\n", addr, val, cpu_state.pc); #endif - voodoo->disp_buffer = 0; - voodoo->draw_buffer = 1; + switch (addr) { + case 0x04: + voodoo->pci_enable = val & 2; + voodoo_recalcmapping(voodoo->set); + break; - voodoo->force_blit_count = 0; - voodoo->can_blit = 0; - voodoo->force_blit_mutex = thread_create_mutex(); + case 0x13: + voodoo->memBaseAddr = val << 24; + voodoo_recalcmapping(voodoo->set); + break; - return voodoo; + case 0x40: + voodoo->initEnable = (voodoo->initEnable & ~0x000000ff) | val; + break; + case 0x41: + voodoo->initEnable = (voodoo->initEnable & ~0x0000ff00) | (val << 8); + break; + case 0x42: + voodoo->initEnable = (voodoo->initEnable & ~0x00ff0000) | (val << 16); + voodoo_recalcmapping(voodoo->set); + break; + case 0x43: + voodoo->initEnable = (voodoo->initEnable & ~0xff000000) | (val << 24); + voodoo_recalcmapping(voodoo->set); + break; + + default: + break; + } } -void *voodoo_init() +static void +voodoo_speed_changed(void *priv) { - voodoo_set_t *voodoo_set = malloc(sizeof(voodoo_set_t)); - uint32_t tmuConfig = 1; - int type; - memset(voodoo_set, 0, sizeof(voodoo_set_t)); - - type = device_get_config_int("type"); - - voodoo_set->nr_cards = device_get_config_int("sli") ? 2 : 1; - voodoo_set->voodoos[0] = voodoo_card_init(); - voodoo_set->voodoos[0]->set = voodoo_set; - if (voodoo_set->nr_cards == 2) - { - voodoo_set->voodoos[1] = voodoo_card_init(); - - voodoo_set->voodoos[1]->set = voodoo_set; + const voodoo_set_t *voodoo_set = (voodoo_set_t *) priv; - if (type == VOODOO_2) - { - voodoo_set->voodoos[0]->fbiInit5 |= FBIINIT5_MULTI_CVG; - voodoo_set->voodoos[1]->fbiInit5 |= FBIINIT5_MULTI_CVG; - } - else - { - voodoo_set->voodoos[0]->fbiInit1 |= FBIINIT1_MULTI_SST; - voodoo_set->voodoos[1]->fbiInit1 |= FBIINIT1_MULTI_SST; - } + voodoo_pixelclock_update(voodoo_set->voodoos[0]); + voodoo_set->voodoos[0]->read_time = pci_nonburst_time + pci_burst_time * ((voodoo_set->voodoos[0]->fbiInit4 & 1) ? 2 : 1); + voodoo_set->voodoos[0]->write_time = pci_nonburst_time + pci_burst_time * ((voodoo_set->voodoos[0]->fbiInit1 & 2) ? 1 : 0); + voodoo_set->voodoos[0]->burst_time = pci_burst_time * ((voodoo_set->voodoos[0]->fbiInit1 & 2) ? 2 : 1); + if (voodoo_set->nr_cards == 2) { + voodoo_pixelclock_update(voodoo_set->voodoos[1]); + voodoo_set->voodoos[1]->read_time = pci_nonburst_time + pci_burst_time * ((voodoo_set->voodoos[1]->fbiInit4 & 1) ? 2 : 1); + voodoo_set->voodoos[1]->write_time = pci_nonburst_time + pci_burst_time * ((voodoo_set->voodoos[1]->fbiInit1 & 2) ? 1 : 0); + voodoo_set->voodoos[1]->burst_time = pci_burst_time * ((voodoo_set->voodoos[1]->fbiInit1 & 2) ? 2 : 1); + } +#if 0 + voodoo_log("Voodoo read_time=%i write_time=%i burst_time=%i %08x %08x\n", voodoo->read_time, voodoo->write_time, voodoo->burst_time, voodoo->fbiInit1, voodoo->fbiInit4); +#endif +} + +static void +voodoo_force_blit(void *priv) +{ + const voodoo_set_t *voodoo_set = (voodoo_set_t *) priv; + + thread_wait_mutex(voodoo_set->voodoos[0]->force_blit_mutex); + if (voodoo_set->voodoos[0]->can_blit) { + voodoo_set->voodoos[0]->force_blit_count++; + } + thread_release_mutex(voodoo_set->voodoos[0]->force_blit_mutex); + if (voodoo_set->nr_cards == 2) { + thread_wait_mutex(voodoo_set->voodoos[1]->force_blit_mutex); + if (voodoo_set->voodoos[1]->can_blit) { + voodoo_set->voodoos[1]->force_blit_count++; } + thread_release_mutex(voodoo_set->voodoos[1]->force_blit_mutex); + } +} - switch (type) - { - case VOODOO_1: - if (voodoo_set->nr_cards == 2) - tmuConfig = 1 | (3 << 3); - else - tmuConfig = 1; - break; - case VOODOO_SB50: - if (voodoo_set->nr_cards == 2) - tmuConfig = 1 | (3 << 3) | (3 << 6) | (2 << 9); - else - tmuConfig = 1 | (3 << 6); - break; - case VOODOO_2: +void * +voodoo_card_init(void) +{ + int c; + voodoo_t *voodoo = malloc(sizeof(voodoo_t)); + memset(voodoo, 0, sizeof(voodoo_t)); + + voodoo->bilinear_enabled = device_get_config_int("bilinear"); + voodoo->dithersub_enabled = device_get_config_int("dithersub"); + voodoo->scrfilter = device_get_config_int("dacfilter"); + voodoo->texture_size = device_get_config_int("texture_memory"); + voodoo->texture_mask = (voodoo->texture_size << 20) - 1; + voodoo->fb_size = device_get_config_int("framebuffer_memory"); + voodoo->fb_mask = (voodoo->fb_size << 20) - 1; + voodoo->render_threads = device_get_config_int("render_threads"); + voodoo->odd_even_mask = voodoo->render_threads - 1; +#ifndef NO_CODEGEN + voodoo->use_recompiler = device_get_config_int("recompiler"); +#endif + voodoo->type = device_get_config_int("type"); + switch (voodoo->type) { + case VOODOO_1: + voodoo->dual_tmus = 0; + break; + case VOODOO_SB50: + voodoo->dual_tmus = 1; + break; + case VOODOO_2: + voodoo->dual_tmus = 1; + break; + + default: + break; + } + + if (voodoo->type == VOODOO_2) /*generate filter lookup tables*/ + voodoo_generate_filter_v2(voodoo); + else + voodoo_generate_filter_v1(voodoo); + + pci_add_card(PCI_ADD_NORMAL, voodoo_pci_read, voodoo_pci_write, voodoo, &voodoo->pci_slot); + + mem_mapping_add(&voodoo->mapping, 0, 0, NULL, voodoo_readw, voodoo_readl, NULL, voodoo_writew, voodoo_writel, NULL, MEM_MAPPING_EXTERNAL, voodoo); + + voodoo->fb_mem = malloc(4 * 1024 * 1024); + voodoo->tex_mem[0] = malloc(voodoo->texture_size * 1024 * 1024); + if (voodoo->dual_tmus) + voodoo->tex_mem[1] = malloc(voodoo->texture_size * 1024 * 1024); + voodoo->tex_mem_w[0] = (uint16_t *) voodoo->tex_mem[0]; + voodoo->tex_mem_w[1] = (uint16_t *) voodoo->tex_mem[1]; + + for (c = 0; c < TEX_CACHE_MAX; c++) { + voodoo->texture_cache[0][c].data = malloc((256 * 256 + 256 * 256 + 128 * 128 + 64 * 64 + 32 * 32 + 16 * 16 + 8 * 8 + 4 * 4 + 2 * 2) * 4); + voodoo->texture_cache[0][c].base = -1; /*invalid*/ + voodoo->texture_cache[0][c].refcount = 0; + if (voodoo->dual_tmus) { + voodoo->texture_cache[1][c].data = malloc((256 * 256 + 256 * 256 + 128 * 128 + 64 * 64 + 32 * 32 + 16 * 16 + 8 * 8 + 4 * 4 + 2 * 2) * 4); + voodoo->texture_cache[1][c].base = -1; /*invalid*/ + voodoo->texture_cache[1][c].refcount = 0; + } + } + + timer_add(&voodoo->timer, voodoo_callback, voodoo, 1); + + voodoo->svga = svga_get_pri(); + voodoo->fbiInit0 = 0; + + voodoo->wake_fifo_thread = thread_create_event(); + voodoo->wake_render_thread[0] = thread_create_event(); + voodoo->wake_render_thread[1] = thread_create_event(); + voodoo->wake_render_thread[2] = thread_create_event(); + voodoo->wake_render_thread[3] = thread_create_event(); + voodoo->wake_main_thread = thread_create_event(); + voodoo->fifo_not_full_event = thread_create_event(); + voodoo->render_not_full_event[0] = thread_create_event(); + voodoo->render_not_full_event[1] = thread_create_event(); + voodoo->render_not_full_event[2] = thread_create_event(); + voodoo->render_not_full_event[3] = thread_create_event(); + voodoo->fifo_thread_run = 1; + voodoo->fifo_thread = thread_create(voodoo_fifo_thread, voodoo); + voodoo->render_thread_run[0] = 1; + voodoo->render_thread[0] = thread_create(voodoo_render_thread_1, voodoo); + if (voodoo->render_threads >= 2) { + voodoo->render_thread_run[1] = 1; + voodoo->render_thread[1] = thread_create(voodoo_render_thread_2, voodoo); + } + if (voodoo->render_threads == 4) { + voodoo->render_thread_run[2] = 1; + voodoo->render_thread[2] = thread_create(voodoo_render_thread_3, voodoo); + voodoo->render_thread_run[3] = 1; + voodoo->render_thread[3] = thread_create(voodoo_render_thread_4, voodoo); + } + voodoo->swap_mutex = thread_create_mutex(); + timer_add(&voodoo->wake_timer, voodoo_wake_timer, (void *) voodoo, 0); + + for (c = 0; c < 0x100; c++) { + rgb332[c].r = c & 0xe0; + rgb332[c].g = (c << 3) & 0xe0; + rgb332[c].b = (c << 6) & 0xc0; + rgb332[c].r = rgb332[c].r | (rgb332[c].r >> 3) | (rgb332[c].r >> 6); + rgb332[c].g = rgb332[c].g | (rgb332[c].g >> 3) | (rgb332[c].g >> 6); + rgb332[c].b = rgb332[c].b | (rgb332[c].b >> 2); + rgb332[c].b = rgb332[c].b | (rgb332[c].b >> 4); + rgb332[c].a = 0xff; + + ai44[c].a = (c & 0xf0) | ((c & 0xf0) >> 4); + ai44[c].r = (c & 0x0f) | ((c & 0x0f) << 4); + ai44[c].g = ai44[c].b = ai44[c].r; + } + + for (c = 0; c < 0x10000; c++) { + rgb565[c].r = (c >> 8) & 0xf8; + rgb565[c].g = (c >> 3) & 0xfc; + rgb565[c].b = (c << 3) & 0xf8; + rgb565[c].r |= (rgb565[c].r >> 5); + rgb565[c].g |= (rgb565[c].g >> 6); + rgb565[c].b |= (rgb565[c].b >> 5); + rgb565[c].a = 0xff; + + argb1555[c].r = (c >> 7) & 0xf8; + argb1555[c].g = (c >> 2) & 0xf8; + argb1555[c].b = (c << 3) & 0xf8; + argb1555[c].r |= (argb1555[c].r >> 5); + argb1555[c].g |= (argb1555[c].g >> 5); + argb1555[c].b |= (argb1555[c].b >> 5); + argb1555[c].a = (c & 0x8000) ? 0xff : 0; + + argb4444[c].a = (c >> 8) & 0xf0; + argb4444[c].r = (c >> 4) & 0xf0; + argb4444[c].g = c & 0xf0; + argb4444[c].b = (c << 4) & 0xf0; + argb4444[c].a |= (argb4444[c].a >> 4); + argb4444[c].r |= (argb4444[c].r >> 4); + argb4444[c].g |= (argb4444[c].g >> 4); + argb4444[c].b |= (argb4444[c].b >> 4); + + ai88[c].a = (c >> 8); + ai88[c].r = c & 0xff; + ai88[c].g = c & 0xff; + ai88[c].b = c & 0xff; + } +#ifndef NO_CODEGEN + voodoo_codegen_init(voodoo); +#endif + + voodoo->disp_buffer = 0; + voodoo->draw_buffer = 1; + + voodoo->force_blit_count = 0; + voodoo->can_blit = 0; + voodoo->force_blit_mutex = thread_create_mutex(); + + return voodoo; +} + +void * +voodoo_2d3d_card_init(int type) +{ + int c; + voodoo_t *voodoo = malloc(sizeof(voodoo_t)); + memset(voodoo, 0, sizeof(voodoo_t)); + + voodoo->bilinear_enabled = device_get_config_int("bilinear"); + voodoo->dithersub_enabled = device_get_config_int("dithersub"); + voodoo->scrfilter = device_get_config_int("dacfilter"); + voodoo->render_threads = device_get_config_int("render_threads"); + voodoo->odd_even_mask = voodoo->render_threads - 1; +#ifndef NO_CODEGEN + voodoo->use_recompiler = device_get_config_int("recompiler"); +#endif + voodoo->type = type; + voodoo->dual_tmus = (type == VOODOO_3) ? 1 : 0; + + /*generate filter lookup tables*/ + voodoo_generate_filter_v2(voodoo); + + for (c = 0; c < TEX_CACHE_MAX; c++) { + voodoo->texture_cache[0][c].data = malloc((256 * 256 + 256 * 256 + 128 * 128 + 64 * 64 + 32 * 32 + 16 * 16 + 8 * 8 + 4 * 4 + 2 * 2) * 4); + voodoo->texture_cache[0][c].base = -1; /*invalid*/ + voodoo->texture_cache[0][c].refcount = 0; + if (voodoo->dual_tmus) { + voodoo->texture_cache[1][c].data = malloc((256 * 256 + 256 * 256 + 128 * 128 + 64 * 64 + 32 * 32 + 16 * 16 + 8 * 8 + 4 * 4 + 2 * 2) * 4); + voodoo->texture_cache[1][c].base = -1; /*invalid*/ + voodoo->texture_cache[1][c].refcount = 0; + } + } + + timer_add(&voodoo->timer, voodoo_callback, voodoo, 1); + + voodoo->fbiInit0 = 0; + + voodoo->wake_fifo_thread = thread_create_event(); + voodoo->wake_render_thread[0] = thread_create_event(); + voodoo->wake_render_thread[1] = thread_create_event(); + voodoo->wake_render_thread[2] = thread_create_event(); + voodoo->wake_render_thread[3] = thread_create_event(); + voodoo->wake_main_thread = thread_create_event(); + voodoo->fifo_not_full_event = thread_create_event(); + voodoo->render_not_full_event[0] = thread_create_event(); + voodoo->render_not_full_event[1] = thread_create_event(); + voodoo->render_not_full_event[2] = thread_create_event(); + voodoo->render_not_full_event[3] = thread_create_event(); + voodoo->fifo_thread_run = 1; + voodoo->fifo_thread = thread_create(voodoo_fifo_thread, voodoo); + voodoo->render_thread_run[0] = 1; + voodoo->render_thread[0] = thread_create(voodoo_render_thread_1, voodoo); + if (voodoo->render_threads >= 2) { + voodoo->render_thread_run[1] = 1; + voodoo->render_thread[1] = thread_create(voodoo_render_thread_2, voodoo); + } + if (voodoo->render_threads == 4) { + voodoo->render_thread_run[2] = 1; + voodoo->render_thread[2] = thread_create(voodoo_render_thread_3, voodoo); + voodoo->render_thread_run[3] = 1; + voodoo->render_thread[3] = thread_create(voodoo_render_thread_4, voodoo); + } + voodoo->swap_mutex = thread_create_mutex(); + timer_add(&voodoo->wake_timer, voodoo_wake_timer, (void *) voodoo, 0); + + for (c = 0; c < 0x100; c++) { + rgb332[c].r = c & 0xe0; + rgb332[c].g = (c << 3) & 0xe0; + rgb332[c].b = (c << 6) & 0xc0; + rgb332[c].r = rgb332[c].r | (rgb332[c].r >> 3) | (rgb332[c].r >> 6); + rgb332[c].g = rgb332[c].g | (rgb332[c].g >> 3) | (rgb332[c].g >> 6); + rgb332[c].b = rgb332[c].b | (rgb332[c].b >> 2); + rgb332[c].b = rgb332[c].b | (rgb332[c].b >> 4); + rgb332[c].a = 0xff; + + ai44[c].a = (c & 0xf0) | ((c & 0xf0) >> 4); + ai44[c].r = (c & 0x0f) | ((c & 0x0f) << 4); + ai44[c].g = ai44[c].b = ai44[c].r; + } + + for (c = 0; c < 0x10000; c++) { + rgb565[c].r = (c >> 8) & 0xf8; + rgb565[c].g = (c >> 3) & 0xfc; + rgb565[c].b = (c << 3) & 0xf8; + rgb565[c].r |= (rgb565[c].r >> 5); + rgb565[c].g |= (rgb565[c].g >> 6); + rgb565[c].b |= (rgb565[c].b >> 5); + rgb565[c].a = 0xff; + + argb1555[c].r = (c >> 7) & 0xf8; + argb1555[c].g = (c >> 2) & 0xf8; + argb1555[c].b = (c << 3) & 0xf8; + argb1555[c].r |= (argb1555[c].r >> 5); + argb1555[c].g |= (argb1555[c].g >> 5); + argb1555[c].b |= (argb1555[c].b >> 5); + argb1555[c].a = (c & 0x8000) ? 0xff : 0; + + argb4444[c].a = (c >> 8) & 0xf0; + argb4444[c].r = (c >> 4) & 0xf0; + argb4444[c].g = c & 0xf0; + argb4444[c].b = (c << 4) & 0xf0; + argb4444[c].a |= (argb4444[c].a >> 4); + argb4444[c].r |= (argb4444[c].r >> 4); + argb4444[c].g |= (argb4444[c].g >> 4); + argb4444[c].b |= (argb4444[c].b >> 4); + + ai88[c].a = (c >> 8); + ai88[c].r = c & 0xff; + ai88[c].g = c & 0xff; + ai88[c].b = c & 0xff; + } +#ifndef NO_CODEGEN + voodoo_codegen_init(voodoo); +#endif + + voodoo->disp_buffer = 0; + voodoo->draw_buffer = 1; + + voodoo->force_blit_count = 0; + voodoo->can_blit = 0; + voodoo->force_blit_mutex = thread_create_mutex(); + + return voodoo; +} + +void * +voodoo_init(UNUSED(const device_t *info)) +{ + voodoo_set_t *voodoo_set = malloc(sizeof(voodoo_set_t)); + uint32_t tmuConfig = 1; + int type; + memset(voodoo_set, 0, sizeof(voodoo_set_t)); + + type = device_get_config_int("type"); + + voodoo_set->nr_cards = device_get_config_int("sli") ? 2 : 1; + voodoo_set->voodoos[0] = voodoo_card_init(); + voodoo_set->voodoos[0]->set = voodoo_set; + if (voodoo_set->nr_cards == 2) { + voodoo_set->voodoos[1] = voodoo_card_init(); + + voodoo_set->voodoos[1]->set = voodoo_set; + + if (type == VOODOO_2) { + voodoo_set->voodoos[0]->fbiInit5 |= FBIINIT5_MULTI_CVG; + voodoo_set->voodoos[1]->fbiInit5 |= FBIINIT5_MULTI_CVG; + } else { + voodoo_set->voodoos[0]->fbiInit1 |= FBIINIT1_MULTI_SST; + voodoo_set->voodoos[1]->fbiInit1 |= FBIINIT1_MULTI_SST; + } + } + + switch (type) { + case VOODOO_1: + if (voodoo_set->nr_cards == 2) + tmuConfig = 1 | (3 << 3); + else + tmuConfig = 1; + break; + case VOODOO_SB50: + if (voodoo_set->nr_cards == 2) + tmuConfig = 1 | (3 << 3) | (3 << 6) | (2 << 9); + else tmuConfig = 1 | (3 << 6); - break; - } - - voodoo_set->voodoos[0]->tmuConfig = tmuConfig; - if (voodoo_set->nr_cards == 2) - voodoo_set->voodoos[1]->tmuConfig = tmuConfig; + break; + case VOODOO_2: + tmuConfig = 1 | (3 << 6); + break; - mem_mapping_add(&voodoo_set->snoop_mapping, 0, 0, NULL, voodoo_snoop_readw, voodoo_snoop_readl, NULL, voodoo_snoop_writew, voodoo_snoop_writel, NULL, MEM_MAPPING_EXTERNAL, voodoo_set); - - return voodoo_set; + default: + break; + } + + voodoo_set->voodoos[0]->tmuConfig = tmuConfig; + if (voodoo_set->nr_cards == 2) + voodoo_set->voodoos[1]->tmuConfig = tmuConfig; + + mem_mapping_add(&voodoo_set->snoop_mapping, 0, 0, NULL, voodoo_snoop_readw, voodoo_snoop_readl, NULL, voodoo_snoop_writew, voodoo_snoop_writel, NULL, MEM_MAPPING_EXTERNAL, voodoo_set); + + return voodoo_set; } -void voodoo_card_close(voodoo_t *voodoo) +void +voodoo_card_close(voodoo_t *voodoo) { - int c; + voodoo->fifo_thread_run = 0; + thread_set_event(voodoo->wake_fifo_thread); + thread_wait(voodoo->fifo_thread); + voodoo->render_thread_run[0] = 0; + thread_set_event(voodoo->wake_render_thread[0]); + thread_wait(voodoo->render_thread[0]); + if (voodoo->render_threads >= 2) { + voodoo->render_thread_run[1] = 0; + thread_set_event(voodoo->wake_render_thread[1]); + thread_wait(voodoo->render_thread[1]); + } + if (voodoo->render_threads == 4) { + voodoo->render_thread_run[2] = 0; + thread_set_event(voodoo->wake_render_thread[2]); + thread_wait(voodoo->render_thread[2]); + voodoo->render_thread_run[3] = 0; + thread_set_event(voodoo->wake_render_thread[3]); + thread_wait(voodoo->render_thread[3]); + } + thread_destroy_event(voodoo->fifo_not_full_event); + thread_destroy_event(voodoo->wake_main_thread); + thread_destroy_event(voodoo->wake_fifo_thread); + thread_destroy_event(voodoo->wake_render_thread[0]); + thread_destroy_event(voodoo->wake_render_thread[1]); + thread_destroy_event(voodoo->render_not_full_event[0]); + thread_destroy_event(voodoo->render_not_full_event[1]); - voodoo->fifo_thread_run = 0; - thread_set_event(voodoo->wake_fifo_thread); - thread_wait(voodoo->fifo_thread); - voodoo->render_thread_run[0] = 0; - thread_set_event(voodoo->wake_render_thread[0]); - thread_wait(voodoo->render_thread[0]); - if (voodoo->render_threads >= 2) { - voodoo->render_thread_run[1] = 0; - thread_set_event(voodoo->wake_render_thread[1]); - thread_wait(voodoo->render_thread[1]); - } - if (voodoo->render_threads == 4) { - voodoo->render_thread_run[2] = 0; - thread_set_event(voodoo->wake_render_thread[2]); - thread_wait(voodoo->render_thread[2]); - voodoo->render_thread_run[3] = 0; - thread_set_event(voodoo->wake_render_thread[3]); - thread_wait(voodoo->render_thread[3]); - } - thread_destroy_event(voodoo->fifo_not_full_event); - thread_destroy_event(voodoo->wake_main_thread); - thread_destroy_event(voodoo->wake_fifo_thread); - thread_destroy_event(voodoo->wake_render_thread[0]); - thread_destroy_event(voodoo->wake_render_thread[1]); - thread_destroy_event(voodoo->render_not_full_event[0]); - thread_destroy_event(voodoo->render_not_full_event[1]); - - for (c = 0; c < TEX_CACHE_MAX; c++) - { - if (voodoo->dual_tmus) - free(voodoo->texture_cache[1][c].data); - free(voodoo->texture_cache[0][c].data); - } + for (uint8_t c = 0; c < TEX_CACHE_MAX; c++) { + if (voodoo->dual_tmus) + free(voodoo->texture_cache[1][c].data); + free(voodoo->texture_cache[0][c].data); + } #ifndef NO_CODEGEN - voodoo_codegen_close(voodoo); + voodoo_codegen_close(voodoo); #endif - if (voodoo->type < VOODOO_BANSHEE && voodoo->fb_mem) - { - free(voodoo->fb_mem); - if (voodoo->dual_tmus) - free(voodoo->tex_mem[1]); - free(voodoo->tex_mem[0]); - } + if (voodoo->type < VOODOO_BANSHEE && voodoo->fb_mem) { + free(voodoo->fb_mem); + if (voodoo->dual_tmus) + free(voodoo->tex_mem[1]); + free(voodoo->tex_mem[0]); + } - thread_close_mutex(voodoo->force_blit_mutex); + thread_close_mutex(voodoo->force_blit_mutex); - free(voodoo); + free(voodoo); } -void voodoo_close(void *p) +void +voodoo_close(void *priv) { - voodoo_set_t *voodoo_set = (voodoo_set_t *)p; - - if (voodoo_set->nr_cards == 2) - voodoo_card_close(voodoo_set->voodoos[1]); - voodoo_card_close(voodoo_set->voodoos[0]); - - free(voodoo_set); + voodoo_set_t *voodoo_set = (voodoo_set_t *) priv; + + if (voodoo_set->nr_cards == 2) + voodoo_card_close(voodoo_set->voodoos[1]); + voodoo_card_close(voodoo_set->voodoos[0]); + + free(voodoo_set); } -static const device_config_t voodoo_config[] = -{ - { - .name = "type", - .description = "Voodoo type", - .type = CONFIG_SELECTION, - .selection = - { - { - .description = "Voodoo Graphics", - .value = VOODOO_1 - }, - { - .description = "Obsidian SB50 + Amethyst (2 TMUs)", - .value = VOODOO_SB50 - }, - { - .description = "Voodoo 2", - .value = VOODOO_2 - }, - { - .description = "" - } - }, - .default_int = 0 +static const device_config_t voodoo_config[] = { + // clang-format off + { + .name = "type", + .description = "Voodoo type", + .type = CONFIG_SELECTION, + .selection = { + { + .description = "Voodoo Graphics", + .value = VOODOO_1 + }, + { + .description = "Obsidian SB50 + Amethyst (2 TMUs)", + .value = VOODOO_SB50 + }, + { + .description = "Voodoo 2", + .value = VOODOO_2 + }, + { + .description = "" + } }, - { - .name = "framebuffer_memory", - .description = "Framebuffer memory size", - .type = CONFIG_SELECTION, - .selection = - { - { - .description = "2 MB", - .value = 2 - }, - { - .description = "4 MB", - .value = 4 - }, - { - .description = "" - } - }, - .default_int = 2 + .default_int = 0 + }, + { + .name = "framebuffer_memory", + .description = "Framebuffer memory size", + .type = CONFIG_SELECTION, + .selection = { + { + .description = "2 MB", + .value = 2 + }, + { + .description = "4 MB", + .value = 4 + }, + { + .description = "" + } }, - { - .name = "texture_memory", - .description = "Texture memory size", - .type = CONFIG_SELECTION, - .selection = - { - { - .description = "2 MB", - .value = 2 - }, - { - .description = "4 MB", - .value = 4 - }, - { - .description = "" - } - }, - .default_int = 2 + .default_int = 2 + }, + { + .name = "texture_memory", + .description = "Texture memory size", + .type = CONFIG_SELECTION, + .selection = { + { + .description = "2 MB", + .value = 2 + }, + { + .description = "4 MB", + .value = 4 + }, + { + .description = "" + } }, - { - .name = "bilinear", - .description = "Bilinear filtering", - .type = CONFIG_BINARY, - .default_int = 1 - }, - { - .name = "dithersub", - .description = "Dither subtraction", - .type = CONFIG_BINARY, - .default_int = 1 - }, - { - .name = "dacfilter", - .description = "Screen Filter", - .type = CONFIG_BINARY, - .default_int = 0 - }, - { - .name = "render_threads", - .description = "Render threads", - .type = CONFIG_SELECTION, - .selection = - { - { - .description = "1", - .value = 1 - }, - { - .description = "2", - .value = 2 - }, - { - .description = "4", - .value = 4 - }, - { - .description = "" - } - }, - .default_int = 2 - }, - { - .name = "sli", - .description = "SLI", - .type = CONFIG_BINARY, - .default_int = 0 + .default_int = 2 + }, + { + .name = "bilinear", + .description = "Bilinear filtering", + .type = CONFIG_BINARY, + .default_int = 1 + }, + { + .name = "dithersub", + .description = "Dither subtraction", + .type = CONFIG_BINARY, + .default_int = 1 + }, + { + .name = "dacfilter", + .description = "Screen Filter", + .type = CONFIG_BINARY, + .default_int = 0 + }, + { + .name = "render_threads", + .description = "Render threads", + .type = CONFIG_SELECTION, + .selection = { + { + .description = "1", + .value = 1 + }, + { + .description = "2", + .value = 2 + }, + { + .description = "4", + .value = 4 + }, + { + .description = "" + } }, + .default_int = 2 + }, + { + .name = "sli", + .description = "SLI", + .type = CONFIG_BINARY, + .default_int = 0 + }, #ifndef NO_CODEGEN - { - .name = "recompiler", - .description = "Recompiler", - .type = CONFIG_BINARY, - .default_int = 1 - }, + { + .name = "recompiler", + .description = "Recompiler", + .type = CONFIG_BINARY, + .default_int = 1 + }, #endif - { - .type = -1 - } + { + .type = CONFIG_END + } + // clang-format on }; -const device_t voodoo_device = -{ - "3DFX Voodoo Graphics", - "voodoo", - DEVICE_PCI, - 0, - voodoo_init, - voodoo_close, - NULL, - { NULL }, - voodoo_speed_changed, - voodoo_force_blit, - voodoo_config +const device_t voodoo_device = { + .name = "3DFX Voodoo Graphics", + .internal_name = "voodoo", + .flags = DEVICE_PCI, + .local = 0, + .init = voodoo_init, + .close = voodoo_close, + .reset = NULL, + { .available = NULL }, + .speed_changed = voodoo_speed_changed, + .force_redraw = voodoo_force_blit, + .config = voodoo_config }; diff --git a/src/video/vid_voodoo_banshee.c b/src/video/vid_voodoo_banshee.c index 64f2b2b1b..37c795b59 100644 --- a/src/video/vid_voodoo_banshee.c +++ b/src/video/vid_voodoo_banshee.c @@ -1,19 +1,21 @@ /* - * 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. + * 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. + * This file is part of the 86Box distribution. * - * Voodoo Banshee and 3 specific emulation. + * Voodoo Banshee and 3 specific emulation. * * * - * Authors: Sarah Walker, + * Authors: Sarah Walker, * - * Copyright 2008-2020 Sarah Walker. + * Copyright 2008-2020 Sarah Walker. */ +#include +#include #include #include #include @@ -21,6 +23,7 @@ #include #include #include +#define HAVE_STDARG_H #include <86box/86box.h> #include "cpu.h" #include <86box/machine.h> @@ -32,6 +35,7 @@ #include <86box/timer.h> #include <86box/device.h> #include <86box/plat.h> +#include <86box/thread.h> #include <86box/video.h> #include <86box/i2c.h> #include <86box/vid_ddc.h> @@ -43,3035 +47,3648 @@ #include <86box/vid_voodoo_regs.h> #include <86box/vid_voodoo_render.h> +#define ROM_BANSHEE "roms/video/voodoo/Pci_sg.rom" +#define ROM_CREATIVE_BANSHEE "roms/video/voodoo/BlasterPCI.rom" +#define ROM_VOODOO3_1000 "roms/video/voodoo/1k11sg.rom" +#define ROM_VOODOO3_2000 "roms/video/voodoo/2k11sd.rom" +#define ROM_VOODOO3_3000 "roms/video/voodoo/3k12sd.rom" +#define ROM_VOODOO3_3500_AGP_NTSC "roms/video/voodoo/35k05n.rom" +#define ROM_VOODOO3_3500_AGP_PAL "roms/video/voodoo/35k05p.rom" +#define ROM_VOODOO3_3500_AGP_COMPAQ "roms/video/voodoo/V3_3500_AGP_SD_2.15.05_Compaq.rom" +#define ROM_VOODOO3_3500_SE_AGP "roms/video/voodoo/V3_3500_AGP_SD_2.15.06_NTSC_Falcon_Northwest.rom" +#define ROM_VOODOO3_3500_SI_AGP "roms/video/voodoo/V3_3500_AGP_SD_2.15.07_PAL_3500TV-SI.rom" +#define ROM_VELOCITY_100 "roms/video/voodoo/Velocity100.VBI" +#define ROM_VELOCITY_200 "roms/video/voodoo/Velocity200sg.rom" -static video_timings_t timing_banshee = {VIDEO_PCI, 2, 2, 1, 20, 20, 21}; -static video_timings_t timing_banshee_agp = {VIDEO_AGP, 2, 2, 1, 20, 20, 21}; - +static video_timings_t timing_banshee = { .type = VIDEO_PCI, .write_b = 2, .write_w = 2, .write_l = 1, .read_b = 20, .read_w = 20, .read_l = 21 }; +static video_timings_t timing_banshee_agp = { .type = VIDEO_AGP, .write_b = 2, .write_w = 2, .write_l = 1, .read_b = 20, .read_w = 20, .read_l = 21 }; #ifdef CLAMP -#undef CLAMP +# undef CLAMP #endif static uint8_t vb_filter_v1_rb[256][256]; -static uint8_t vb_filter_v1_g [256][256]; +static uint8_t vb_filter_v1_g[256][256]; static uint8_t vb_filter_bx_rb[256][256]; -static uint8_t vb_filter_bx_g [256][256]; +static uint8_t vb_filter_bx_g[256][256]; -enum -{ - TYPE_BANSHEE = 0, - TYPE_V3_2000, - TYPE_V3_3000, - TYPE_VELOCITY100 +enum { + TYPE_BANSHEE = 0, + TYPE_V3_1000, + TYPE_V3_2000, + TYPE_V3_3000, + TYPE_V3_3500, + TYPE_V3_3500_COMPAQ, + TYPE_V3_3500_SI, + TYPE_VELOCITY100, + TYPE_VELOCITY200 }; -typedef struct banshee_t -{ - svga_t svga; - - rom_t bios_rom; - - uint8_t pci_regs[256]; - - uint32_t memBaseAddr0; - uint32_t memBaseAddr1; - uint32_t ioBaseAddr; +typedef struct banshee_t { + svga_t svga; - uint32_t agpInit0; - uint32_t dramInit0, dramInit1; - uint32_t lfbMemoryConfig; - uint32_t miscInit0, miscInit1; - uint32_t pciInit0; - uint32_t vgaInit0, vgaInit1; - - uint32_t command_2d; - uint32_t srcBaseAddr_2d; - - uint32_t pllCtrl0, pllCtrl1, pllCtrl2; - - uint32_t dacMode; - int dacAddr; + rom_t bios_rom; - uint32_t vidDesktopOverlayStride; - uint32_t vidDesktopStartAddr; - uint32_t vidProcCfg; - uint32_t vidScreenSize; - uint32_t vidSerialParallelPort; - - int overlay_pix_fmt; - - uint32_t hwCurPatAddr, hwCurLoc, hwCurC0, hwCurC1; + uint8_t pci_regs[256]; - uint32_t intrCtrl; - - uint32_t overlay_buffer[2][4096]; + uint32_t memBaseAddr0; + uint32_t memBaseAddr1; + uint32_t ioBaseAddr; - mem_mapping_t linear_mapping; + uint32_t agpInit0; + uint32_t dramInit0, dramInit1; + uint32_t lfbMemoryConfig; + uint32_t miscInit0, miscInit1; + uint32_t pciInit0; + uint32_t vgaInit0, vgaInit1; - mem_mapping_t reg_mapping_low; /*0000000-07fffff*/ - mem_mapping_t reg_mapping_high; /*0c00000-1ffffff - Windows 2000 puts the BIOS ROM in between these two areas*/ - - voodoo_t *voodoo; - - uint32_t desktop_addr; - int desktop_y; - uint32_t desktop_stride_tiled; + uint32_t command_2d; + uint32_t srcBaseAddr_2d; - int type, card, agp, has_bios; - int vblank_irq; + uint32_t pllCtrl0, pllCtrl1, pllCtrl2; - void *i2c, *i2c_ddc, *ddc; + uint32_t dacMode; + int dacAddr; + + uint32_t vidDesktopOverlayStride; + uint32_t vidDesktopStartAddr; + uint32_t vidProcCfg; + uint32_t vidScreenSize; + uint32_t vidSerialParallelPort; + + uint32_t agpReqSize; + uint32_t agpHostAddressHigh; + uint32_t agpHostAddressLow; + uint32_t agpGraphicsAddress; + uint32_t agpGraphicsStride; + + int overlay_pix_fmt; + + uint32_t hwCurPatAddr, hwCurLoc, hwCurC0, hwCurC1; + + uint32_t intrCtrl; + + uint32_t overlay_buffer[2][4096]; + + mem_mapping_t linear_mapping; + + mem_mapping_t reg_mapping_low; /*0000000-07fffff*/ + mem_mapping_t reg_mapping_high; /*0c00000-1ffffff - Windows 2000 puts the BIOS ROM in between these two areas*/ + + voodoo_t *voodoo; + + uint32_t desktop_addr; + int desktop_y; + uint32_t desktop_stride_tiled; + + int type, agp; + int has_bios, vblank_irq; + + uint8_t pci_slot; + uint8_t irq_state; + + void *i2c, *i2c_ddc, *ddc; } banshee_t; -enum -{ - Init_status = 0x00, - Init_pciInit0 = 0x04, - Init_lfbMemoryConfig = 0x0c, - Init_miscInit0 = 0x10, - Init_miscInit1 = 0x14, - Init_dramInit0 = 0x18, - Init_dramInit1 = 0x1c, - Init_agpInit0 = 0x20, - Init_vgaInit0 = 0x28, - Init_vgaInit1 = 0x2c, - Init_2dCommand = 0x30, - Init_2dSrcBaseAddr = 0x34, - Init_strapInfo = 0x38, - - PLL_pllCtrl0 = 0x40, - PLL_pllCtrl1 = 0x44, - PLL_pllCtrl2 = 0x48, - - DAC_dacMode = 0x4c, - DAC_dacAddr = 0x50, - DAC_dacData = 0x54, - - Video_vidProcCfg = 0x5c, - Video_maxRgbDelta = 0x58, - Video_hwCurPatAddr = 0x60, - Video_hwCurLoc = 0x64, - Video_hwCurC0 = 0x68, - Video_hwCurC1 = 0x6c, - Video_vidSerialParallelPort = 0x78, - Video_vidScreenSize = 0x98, - Video_vidOverlayStartCoords = 0x9c, - Video_vidOverlayEndScreenCoords = 0xa0, - Video_vidOverlayDudx = 0xa4, - Video_vidOverlayDudxOffsetSrcWidth = 0xa8, - Video_vidOverlayDvdy = 0xac, - Video_vidOverlayDvdyOffset = 0xe0, - Video_vidDesktopStartAddr = 0xe4, - Video_vidDesktopOverlayStride = 0xe8 +enum { + Init_status = 0x00, + Init_pciInit0 = 0x04, + Init_lfbMemoryConfig = 0x0c, + Init_miscInit0 = 0x10, + Init_miscInit1 = 0x14, + Init_dramInit0 = 0x18, + Init_dramInit1 = 0x1c, + Init_agpInit0 = 0x20, + Init_vgaInit0 = 0x28, + Init_vgaInit1 = 0x2c, + Init_2dCommand = 0x30, + Init_2dSrcBaseAddr = 0x34, + Init_strapInfo = 0x38, + + PLL_pllCtrl0 = 0x40, + PLL_pllCtrl1 = 0x44, + PLL_pllCtrl2 = 0x48, + + DAC_dacMode = 0x4c, + DAC_dacAddr = 0x50, + DAC_dacData = 0x54, + + Video_vidProcCfg = 0x5c, + Video_maxRgbDelta = 0x58, + Video_hwCurPatAddr = 0x60, + Video_hwCurLoc = 0x64, + Video_hwCurC0 = 0x68, + Video_hwCurC1 = 0x6c, + Video_vidSerialParallelPort = 0x78, + Video_vidScreenSize = 0x98, + Video_vidOverlayStartCoords = 0x9c, + Video_vidOverlayEndScreenCoords = 0xa0, + Video_vidOverlayDudx = 0xa4, + Video_vidOverlayDudxOffsetSrcWidth = 0xa8, + Video_vidOverlayDvdy = 0xac, + Video_vidOverlayDvdyOffset = 0xe0, + Video_vidDesktopStartAddr = 0xe4, + Video_vidDesktopOverlayStride = 0xe8, }; -enum -{ - cmdBaseAddr0 = 0x20, - cmdBaseSize0 = 0x24, - cmdBump0 = 0x28, - cmdRdPtrL0 = 0x2c, - cmdRdPtrH0 = 0x30, - cmdAMin0 = 0x34, - cmdAMax0 = 0x3c, - cmdFifoDepth0 = 0x44, - cmdHoleCnt0 = 0x48 +enum { + cmdBaseAddr0 = 0x20, + cmdBaseSize0 = 0x24, + cmdBump0 = 0x28, + cmdRdPtrL0 = 0x2c, + cmdRdPtrH0 = 0x30, + cmdAMin0 = 0x34, + cmdAMax0 = 0x3c, + cmdStatus0 = 0x40, + cmdFifoDepth0 = 0x44, + cmdHoleCnt0 = 0x48, + + Agp_agpReqSize = 0x00, + Agp_agpHostAddressLow = 0x04, + Agp_agpHostAddressHigh = 0x08, + Agp_agpGraphicsAddress = 0x0C, + Agp_agpGraphicsStride = 0x10, }; -#define VGAINIT0_EXTENDED_SHIFT_OUT (1 << 12) +#define VGAINIT0_EXTENDED_SHIFT_OUT (1 << 12) -#define VIDPROCCFG_VIDPROC_ENABLE (1 << 0) -#define VIDPROCCFG_CURSOR_MODE (1 << 1) -#define VIDPROCCFG_INTERLACE (1 << 3) -#define VIDPROCCFG_HALF_MODE (1 << 4) -#define VIDPROCCFG_OVERLAY_ENABLE (1 << 8) -#define VIDPROCCFG_OVERLAY_CLUT_BYPASS (1 << 11) -#define VIDPROCCFG_OVERLAY_CLUT_SEL (1 << 13) -#define VIDPROCCFG_H_SCALE_ENABLE (1 << 14) -#define VIDPROCCFG_V_SCALE_ENABLE (1 << 15) -#define VIDPROCCFG_FILTER_MODE_MASK (3 << 16) -#define VIDPROCCFG_FILTER_MODE_POINT (0 << 16) -#define VIDPROCCFG_FILTER_MODE_DITHER_2X2 (1 << 16) -#define VIDPROCCFG_FILTER_MODE_DITHER_4X4 (2 << 16) -#define VIDPROCCFG_FILTER_MODE_BILINEAR (3 << 16) -#define VIDPROCCFG_DESKTOP_PIX_FORMAT ((banshee->vidProcCfg >> 18) & 7) -#define VIDPROCCFG_OVERLAY_PIX_FORMAT ((banshee->vidProcCfg >> 21) & 7) +#define VIDPROCCFG_VIDPROC_ENABLE (1 << 0) +#define VIDPROCCFG_CURSOR_MODE (1 << 1) +#define VIDPROCCFG_INTERLACE (1 << 3) +#define VIDPROCCFG_HALF_MODE (1 << 4) +#define VIDPROCCFG_OVERLAY_ENABLE (1 << 8) +#define VIDPROCCFG_OVERLAY_CLUT_BYPASS (1 << 11) +#define VIDPROCCFG_OVERLAY_CLUT_SEL (1 << 13) +#define VIDPROCCFG_H_SCALE_ENABLE (1 << 14) +#define VIDPROCCFG_V_SCALE_ENABLE (1 << 15) +#define VIDPROCCFG_FILTER_MODE_MASK (3 << 16) +#define VIDPROCCFG_FILTER_MODE_POINT (0 << 16) +#define VIDPROCCFG_FILTER_MODE_DITHER_2X2 (1 << 16) +#define VIDPROCCFG_FILTER_MODE_DITHER_4X4 (2 << 16) +#define VIDPROCCFG_FILTER_MODE_BILINEAR (3 << 16) +#define VIDPROCCFG_DESKTOP_PIX_FORMAT ((banshee->vidProcCfg >> 18) & 7) +#define VIDPROCCFG_OVERLAY_PIX_FORMAT ((banshee->vidProcCfg >> 21) & 7) #define VIDPROCCFG_OVERLAY_PIX_FORMAT_SHIFT (21) -#define VIDPROCCFG_OVERLAY_PIX_FORMAT_MASK (7 << VIDPROCCFG_OVERLAY_PIX_FORMAT_SHIFT) -#define VIDPROCCFG_DESKTOP_TILE (1 << 24) -#define VIDPROCCFG_OVERLAY_TILE (1 << 25) -#define VIDPROCCFG_2X_MODE (1 << 26) -#define VIDPROCCFG_HWCURSOR_ENA (1 << 27) +#define VIDPROCCFG_OVERLAY_PIX_FORMAT_MASK (7 << VIDPROCCFG_OVERLAY_PIX_FORMAT_SHIFT) +#define VIDPROCCFG_DESKTOP_TILE (1 << 24) +#define VIDPROCCFG_OVERLAY_TILE (1 << 25) +#define VIDPROCCFG_2X_MODE (1 << 26) +#define VIDPROCCFG_HWCURSOR_ENA (1 << 27) -#define OVERLAY_FMT_565 (1) -#define OVERLAY_FMT_YUYV422 (5) -#define OVERLAY_FMT_UYVY422 (6) -#define OVERLAY_FMT_565_DITHER (7) +#define OVERLAY_FMT_565 (1) +#define OVERLAY_FMT_YUYV422 (5) +#define OVERLAY_FMT_UYVY422 (6) +#define OVERLAY_FMT_565_DITHER (7) -#define OVERLAY_START_X_MASK (0xfff) -#define OVERLAY_START_Y_SHIFT (12) -#define OVERLAY_START_Y_MASK (0xfff << OVERLAY_START_Y_SHIFT) +#define OVERLAY_START_X_MASK (0xfff) +#define OVERLAY_START_Y_SHIFT (12) +#define OVERLAY_START_Y_MASK (0xfff << OVERLAY_START_Y_SHIFT) -#define OVERLAY_END_X_MASK (0xfff) -#define OVERLAY_END_Y_SHIFT (12) -#define OVERLAY_END_Y_MASK (0xfff << OVERLAY_END_Y_SHIFT) +#define OVERLAY_END_X_MASK (0xfff) +#define OVERLAY_END_Y_SHIFT (12) +#define OVERLAY_END_Y_MASK (0xfff << OVERLAY_END_Y_SHIFT) -#define OVERLAY_SRC_WIDTH_SHIFT (19) -#define OVERLAY_SRC_WIDTH_MASK (0x1fff << OVERLAY_SRC_WIDTH_SHIFT) +#define OVERLAY_SRC_WIDTH_SHIFT (19) +#define OVERLAY_SRC_WIDTH_MASK (0x1fff << OVERLAY_SRC_WIDTH_SHIFT) -#define VID_STRIDE_OVERLAY_SHIFT (16) -#define VID_STRIDE_OVERLAY_MASK (0x7fff << VID_STRIDE_OVERLAY_SHIFT) +#define VID_STRIDE_OVERLAY_SHIFT (16) +#define VID_STRIDE_OVERLAY_MASK (0x7fff << VID_STRIDE_OVERLAY_SHIFT) -#define VID_DUDX_MASK (0xffffff) -#define VID_DVDY_MASK (0xffffff) +#define VID_DUDX_MASK (0xffffff) +#define VID_DVDY_MASK (0xffffff) -#define PIX_FORMAT_8 0 -#define PIX_FORMAT_RGB565 1 -#define PIX_FORMAT_RGB24 2 -#define PIX_FORMAT_RGB32 3 +#define PIX_FORMAT_8 0 +#define PIX_FORMAT_RGB565 1 +#define PIX_FORMAT_RGB24 2 +#define PIX_FORMAT_RGB32 3 -#define VIDSERIAL_DDC_EN (1 << 18) -#define VIDSERIAL_DDC_DCK_W (1 << 19) -#define VIDSERIAL_DDC_DDA_W (1 << 20) -#define VIDSERIAL_DDC_DCK_R (1 << 21) -#define VIDSERIAL_DDC_DDA_R (1 << 22) -#define VIDSERIAL_I2C_EN (1 << 23) -#define VIDSERIAL_I2C_SCK_W (1 << 24) -#define VIDSERIAL_I2C_SDA_W (1 << 25) -#define VIDSERIAL_I2C_SCK_R (1 << 26) -#define VIDSERIAL_I2C_SDA_R (1 << 27) +#define VIDSERIAL_DDC_EN (1 << 18) +#define VIDSERIAL_DDC_DCK_W (1 << 19) +#define VIDSERIAL_DDC_DDA_W (1 << 20) +#define VIDSERIAL_DDC_DCK_R (1 << 21) +#define VIDSERIAL_DDC_DDA_R (1 << 22) +#define VIDSERIAL_I2C_EN (1 << 23) +#define VIDSERIAL_I2C_SCK_W (1 << 24) +#define VIDSERIAL_I2C_SDA_W (1 << 25) +#define VIDSERIAL_I2C_SCK_R (1 << 26) +#define VIDSERIAL_I2C_SDA_R (1 << 27) -#define MISCINIT0_Y_ORIGIN_SWAP_SHIFT (18) -#define MISCINIT0_Y_ORIGIN_SWAP_MASK (0xfff << MISCINIT0_Y_ORIGIN_SWAP_SHIFT) +#define MISCINIT0_Y_ORIGIN_SWAP_SHIFT (18) +#define MISCINIT0_Y_ORIGIN_SWAP_MASK (0xfff << MISCINIT0_Y_ORIGIN_SWAP_SHIFT) #ifdef ENABLE_BANSHEE_LOG int banshee_do_log = ENABLE_BANSHEE_LOG; - static void banshee_log(const char *fmt, ...) { va_list ap; if (banshee_do_log) { - va_start(ap, fmt); - pclog_ex(fmt, ap); - va_end(ap); + va_start(ap, fmt); + pclog_ex(fmt, ap); + va_end(ap); } } #else -#define banshee_log(fmt, ...) +# define banshee_log(fmt, ...) #endif static uint32_t banshee_status(banshee_t *banshee); -static int banshee_vga_vsync_enabled(banshee_t *banshee) +static int +banshee_vga_vsync_enabled(banshee_t *banshee) { if (!(banshee->svga.crtc[0x11] & 0x20) && (banshee->svga.crtc[0x11] & 0x10) && ((banshee->pciInit0 >> 18) & 1) != 0) return 1; return 0; } -static void banshee_update_irqs(banshee_t *banshee) +static void +banshee_update_irqs(banshee_t *banshee) { if (banshee->vblank_irq > 0 && banshee_vga_vsync_enabled(banshee)) { - pci_set_irq(banshee->card, PCI_INTA); + pci_set_irq(banshee->pci_slot, PCI_INTA, &banshee->irq_state); } else { - pci_clear_irq(banshee->card, PCI_INTA); + pci_clear_irq(banshee->pci_slot, PCI_INTA, &banshee->irq_state); } } -static void banshee_vblank_start(svga_t* svga) +static void +banshee_vblank_start(svga_t *svga) { - banshee_t *banshee = (banshee_t*)svga->p; + banshee_t *banshee = (banshee_t *) svga->priv; if (banshee->vblank_irq >= 0) { banshee->vblank_irq = 1; banshee_update_irqs(banshee); } } - -static void banshee_out(uint16_t addr, uint8_t val, void *p) +static void +banshee_out(uint16_t addr, uint8_t val, void *priv) { - banshee_t *banshee = (banshee_t *)p; - svga_t *svga = &banshee->svga; - uint8_t old; - -// /*if (addr != 0x3c9) */banshee_log("banshee_out : %04X %02X %04X:%04X\n", addr, val, CS,cpu_state.pc); - - if (((addr & 0xfff0) == 0x3d0 || (addr & 0xfff0) == 0x3b0) && !(svga->miscout & 1)) - addr ^= 0x60; + banshee_t *banshee = (banshee_t *) priv; + svga_t *svga = &banshee->svga; + uint8_t old; - switch (addr) - { - case 0x3D4: - svga->crtcreg = val & 0x3f; +#if 0 + if (addr != 0x3c9) + banshee_log("banshee_out : %04X %02X %04X:%04X\n", addr, val, CS,cpu_state.pc); +#endif + 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 < 7) && (svga->crtc[0x11] & 0x80)) 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 == 0x11) { - if (!(val & 0x10)) { - if (banshee->vblank_irq > 0) - banshee->vblank_irq = -1; - } else if (banshee->vblank_irq < 0) { - banshee->vblank_irq = 0; - } - banshee_update_irqs(banshee); - if ((val & ~0x30) == (old & ~0x30)) - old = val; - } - if (svga->crtcreg < 0xe || svga->crtcreg > 0x11 || (svga->crtcreg == 0x11 && old != val)) - { - 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); - } - } + 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 == 0x11) { + if (!(val & 0x10)) { + if (banshee->vblank_irq > 0) + banshee->vblank_irq = -1; + } else if (banshee->vblank_irq < 0) { + banshee->vblank_irq = 0; + } + banshee_update_irqs(banshee); + if ((val & ~0x30) == (old & ~0x30)) + old = val; } - break; - } - svga_out(addr, val, svga); + if (svga->crtcreg < 0xe || svga->crtcreg > 0x11 || (svga->crtcreg == 0x11 && old != val)) { + 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; + + default: + break; + } + svga_out(addr, val, svga); } -static uint8_t banshee_in(uint16_t addr, void *p) +static uint8_t +banshee_in(uint16_t addr, void *priv) { - banshee_t *banshee = (banshee_t *)p; - svga_t *svga = &banshee->svga; - uint8_t temp; + banshee_t *banshee = (banshee_t *) priv; + svga_t *svga = &banshee->svga; + uint8_t temp; -// if (addr != 0x3da) banshee_log("banshee_in : %04X ", addr); - - if (((addr & 0xfff0) == 0x3d0 || (addr & 0xfff0) == 0x3b0) && !(svga->miscout & 1)) - addr ^= 0x60; - - switch (addr) - { - case 0x3c2: - if ((svga->vgapal[0].r + svga->vgapal[0].g + svga->vgapal[0].b) >= 0x40) - temp = 0; - else - temp = 0x10; - if (banshee->vblank_irq > 0) - temp |= 0x80; +#if 0 + if (addr != 0x3da) + banshee_log("banshee_in : %04X ", addr); +#endif + + if (((addr & 0xfff0) == 0x3d0 || (addr & 0xfff0) == 0x3b0) && !(svga->miscout & 1)) + addr ^= 0x60; + + switch (addr) { + case 0x3c2: + if ((svga->vgapal[0].r + svga->vgapal[0].g + svga->vgapal[0].b) >= 0x40) + temp = 0; + else + temp = 0x10; + if (banshee->vblank_irq > 0) + temp |= 0x80; + break; + case 0x3D4: + temp = svga->crtcreg; + break; + case 0x3D5: + temp = svga->crtc[svga->crtcreg]; + break; + default: + temp = svga_in(addr, svga); + break; + } +#if 0 + if (addr != 0x3da) + banshee_log("%02X %04X:%04X %i\n", temp, CS,cpu_state.pc, ins); +#endif + return temp; +} + +static void +banshee_updatemapping(banshee_t *banshee) +{ + svga_t *svga = &banshee->svga; + + if (!(banshee->pci_regs[PCI_REG_COMMAND] & PCI_COMMAND_MEM)) { + // banshee_log("Update mapping - PCI disabled\n"); + mem_mapping_disable(&svga->mapping); + mem_mapping_disable(&banshee->linear_mapping); + mem_mapping_disable(&banshee->reg_mapping_low); + mem_mapping_disable(&banshee->reg_mapping_high); + return; + } + + banshee_log("Update mapping - bank %02X ", svga->gdcreg[6] & 0xc); + switch (svga->gdcreg[6] & 0xc) { /*Banked framebuffer*/ + 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; + + default: + break; + } + + banshee_log("Linear framebuffer %08X ", banshee->memBaseAddr1); + mem_mapping_set_addr(&banshee->linear_mapping, banshee->memBaseAddr1, 32 << 20); + banshee_log("registers %08X\n", banshee->memBaseAddr0); + mem_mapping_set_addr(&banshee->reg_mapping_low, banshee->memBaseAddr0, 8 << 20); + mem_mapping_set_addr(&banshee->reg_mapping_high, banshee->memBaseAddr0 + 0xc00000, 20 << 20); +} + +static void +banshee_render_16bpp_tiled(svga_t *svga) +{ + banshee_t *banshee = (banshee_t *) svga->priv; + uint32_t *p = &(svga->monitor->target_buffer->line[svga->displine + svga->y_add])[svga->x_add]; + uint32_t addr; + int drawn = 0; + + if ((svga->displine + svga->y_add) < 0) + return; + + if (banshee->vidProcCfg & VIDPROCCFG_HALF_MODE) + addr = banshee->desktop_addr + ((banshee->desktop_y >> 1) & 31) * 128 + ((banshee->desktop_y >> 6) * banshee->desktop_stride_tiled); + else + addr = banshee->desktop_addr + (banshee->desktop_y & 31) * 128 + ((banshee->desktop_y >> 5) * banshee->desktop_stride_tiled); + + for (int x = 0; x <= svga->hdisp; x += 64) { + if (svga->hwcursor_on || svga->overlay_on) + svga->changedvram[addr >> 12] = 2; + if (svga->changedvram[addr >> 12] || svga->fullchange) { + const uint16_t *vram_p = (uint16_t *) &svga->vram[addr & svga->vram_display_mask]; + + for (uint8_t xx = 0; xx < 64; xx++) + *p++ = video_16to32[*vram_p++]; + + drawn = 1; + } else + p += 64; + addr += 128 * 32; + } + + if (drawn) { + if (svga->firstline_draw == 2000) + svga->firstline_draw = svga->displine; + svga->lastline_draw = svga->displine; + } + + banshee->desktop_y++; +} + +static void +banshee_recalctimings(svga_t *svga) +{ + banshee_t *banshee = (banshee_t *) svga->priv; + const voodoo_t *voodoo = banshee->voodoo; + + /*7 R/W Horizontal Retrace End bit 5. - + 6 R/W Horizontal Retrace Start bit 8 0x4 + 5 R/W Horizontal Blank End bit 6. - + 4 R/W Horizontal Blank Start bit 8. 0x3 + 3 R/W Reserved. - + 2 R/W Horizontal Display Enable End bit 8. 0x1 + 1 R/W Reserved. - + 0 R/W Horizontal Total bit 8. 0x0*/ + if (svga->crtc[0x1a] & 0x01) + svga->htotal += 0x100; + if (svga->crtc[0x1a] & 0x04) + svga->hdisp += 0x100; + /*6 R/W Vertical Retrace Start bit 10 0x10 + 5 R/W Reserved. - + 4 R/W Vertical Blank Start bit 10. 0x15 + 3 R/W Reserved. - + 2 R/W Vertical Display Enable End bit 10 0x12 + 1 R/W Reserved. - + 0 R/W Vertical Total bit 10. 0x6*/ + if (svga->crtc[0x1b] & 0x01) + svga->vtotal += 0x400; + if (svga->crtc[0x1b] & 0x04) + svga->dispend += 0x400; + if (svga->crtc[0x1b] & 0x10) + svga->vblankstart += 0x400; + if (svga->crtc[0x1b] & 0x40) + svga->vsyncstart += 0x400; +#if 0 + banshee_log("svga->hdisp=%i\n", svga->hdisp); +#endif + + svga->interlace = 0; + + if (banshee->vgaInit0 & VGAINIT0_EXTENDED_SHIFT_OUT) { + switch (VIDPROCCFG_DESKTOP_PIX_FORMAT) { + case PIX_FORMAT_8: + svga->render = svga_render_8bpp_highres; + svga->bpp = 8; break; - case 0x3D4: - temp = svga->crtcreg; + case PIX_FORMAT_RGB565: + svga->render = (banshee->vidProcCfg & VIDPROCCFG_DESKTOP_TILE) ? banshee_render_16bpp_tiled : svga_render_16bpp_highres; + svga->bpp = 16; break; - case 0x3D5: - temp = svga->crtc[svga->crtcreg]; + case PIX_FORMAT_RGB24: + svga->render = svga_render_24bpp_highres; + svga->bpp = 24; break; + case PIX_FORMAT_RGB32: + svga->render = svga_render_32bpp_highres; + svga->bpp = 32; + break; + default: + fatal("Unknown pixel format %08x (vgaInit0=%08x)\n", VIDPROCCFG_DESKTOP_PIX_FORMAT, banshee->vgaInit0); + } + if (!(banshee->vidProcCfg & VIDPROCCFG_DESKTOP_TILE) && (banshee->vidProcCfg & VIDPROCCFG_HALF_MODE)) + svga->rowcount = 1; + else + svga->rowcount = 0; + if (banshee->vidProcCfg & VIDPROCCFG_DESKTOP_TILE) + svga->rowoffset = ((banshee->vidDesktopOverlayStride & 0x3fff) * 128) >> 3; + else + svga->rowoffset = (banshee->vidDesktopOverlayStride & 0x3fff) >> 3; + svga->ma_latch = banshee->vidDesktopStartAddr >> 2; + banshee->desktop_stride_tiled = (banshee->vidDesktopOverlayStride & 0x3fff) * 128 * 32; +#if 0 + banshee_log("Extended shift out %i rowoffset=%i %02x\n", VIDPROCCFG_DESKTOP_PIX_FORMAT, svga->rowoffset, svga->crtc[1]); +#endif + + svga->char_width = 8; + svga->split = 99999; + + if (banshee->vidProcCfg & VIDPROCCFG_2X_MODE) { + svga->hdisp *= 2; + svga->htotal *= 2; + } + + svga->interlace = !!(banshee->vidProcCfg & VIDPROCCFG_INTERLACE); + + svga->overlay.ena = banshee->vidProcCfg & VIDPROCCFG_OVERLAY_ENABLE; + + svga->overlay.x = voodoo->overlay.start_x; + svga->overlay.y = voodoo->overlay.start_y; + svga->overlay.cur_xsize = voodoo->overlay.size_x; + svga->overlay.cur_ysize = voodoo->overlay.size_y; + svga->overlay.pitch = (banshee->vidDesktopOverlayStride & VID_STRIDE_OVERLAY_MASK) >> VID_STRIDE_OVERLAY_SHIFT; + if (banshee->vidProcCfg & VIDPROCCFG_OVERLAY_TILE) + svga->overlay.pitch *= 128 * 32; + if (svga->overlay.cur_xsize <= 0 || svga->overlay.cur_ysize <= 0) + svga->overlay.ena = 0; + if (svga->overlay.ena) { +#if 0 + banshee_log("Overlay enabled : start=%i,%i end=%i,%i size=%i,%i pitch=%x\n", + voodoo->overlay.start_x, voodoo->overlay.start_y, + voodoo->overlay.end_x, voodoo->overlay.end_y, + voodoo->overlay.size_x, voodoo->overlay.size_y, + svga->overlay.pitch); +#endif + if (!voodoo->overlay.start_x && !voodoo->overlay.start_y && svga->hdisp == voodoo->overlay.size_x && svga->dispend == voodoo->overlay.size_y) { + /*Overlay is full screen, so don't bother rendering the desktop + behind it*/ + svga->render = svga_render_null; + svga->bpp = 0; + } + } + } else { +#if 0 + banshee_log("Normal shift out\n"); +#endif + svga->bpp = 8; + } + + svga->fb_only = (banshee->vidProcCfg & VIDPROCCFG_VIDPROC_ENABLE); + + if (((svga->miscout >> 2) & 3) == 3) { + int k = banshee->pllCtrl0 & 3; + int m = (banshee->pllCtrl0 >> 2) & 0x3f; + int n = (banshee->pllCtrl0 >> 8) & 0xff; + double freq = (((double) n + 2) / (((double) m + 2) * (double) (1 << k))) * 14318184.0; + + svga->clock = (cpuclock * (float) (1ULL << 32)) / freq; +#if 0 + svga->clock = cpuclock / freq; +#endif + +#if 0 + banshee_log("svga->clock = %g %g m=%i k=%i n=%i\n", freq, freq / 1000000.0, m, k, n); +#endif + } +} + +static void +banshee_ext_out(uint16_t addr, uint8_t val, void *priv) +{ +#if 0 + banshee_t *banshee = (banshee_t *)priv; + svga_t *svga = &banshee->svga; +#endif + +#if 0 + banshee_log("banshee_ext_out: addr=%04x val=%02x\n", addr, val); +#endif + + switch (addr & 0xff) { + case 0xb0: + case 0xb1: + case 0xb2: + case 0xb3: + case 0xb4: + case 0xb5: + case 0xb6: + case 0xb7: + case 0xb8: + case 0xb9: + case 0xba: + case 0xbb: + case 0xbc: + case 0xbd: + case 0xbe: + case 0xbf: + case 0xc0: + case 0xc1: + case 0xc2: + case 0xc3: + case 0xc4: + case 0xc5: + case 0xc6: + case 0xc7: + case 0xc8: + case 0xc9: + case 0xca: + case 0xcb: + case 0xcc: + case 0xcd: + case 0xce: + case 0xcf: + case 0xd0: + case 0xd1: + case 0xd2: + case 0xd3: + case 0xd4: + case 0xd5: + case 0xd6: + case 0xd7: + case 0xd8: + case 0xd9: + case 0xda: + case 0xdb: + case 0xdc: + case 0xdd: + case 0xde: + case 0xdf: + banshee_out((addr & 0xff) + 0x300, val, priv); + break; + + default: + banshee_log("bad banshee_ext_out: addr=%04x val=%02x\n", addr, val); + } +} +static void +banshee_ext_outl(uint16_t addr, uint32_t val, void *priv) +{ + banshee_t *banshee = (banshee_t *) priv; + voodoo_t *voodoo = banshee->voodoo; + svga_t *svga = &banshee->svga; + +#if 0 + banshee_log("banshee_ext_outl: addr=%04x val=%08x %04x(%08x):%08x\n", addr, val, CS,cs,cpu_state.pc); +#endif + + switch (addr & 0xff) { + case Init_pciInit0: + banshee->pciInit0 = val; + voodoo->read_time = (banshee->agp ? agp_nonburst_time : pci_nonburst_time) + (banshee->agp ? agp_burst_time : pci_burst_time) * ((val & 0x100) ? 2 : 1); + voodoo->burst_time = (banshee->agp ? agp_burst_time : pci_burst_time) * ((val & 0x200) ? 1 : 0); + voodoo->write_time = (banshee->agp ? agp_nonburst_time : pci_nonburst_time) + voodoo->burst_time; + break; + + case Init_lfbMemoryConfig: + banshee->lfbMemoryConfig = val; +#if 0 + banshee_log("lfbMemoryConfig=%08x\n", val); +#endif + voodoo->tile_base = (val & 0x1fff) << 12; + voodoo->tile_stride = 1024 << ((val >> 13) & 7); + voodoo->tile_stride_shift = 10 + ((val >> 13) & 7); + voodoo->tile_x = ((val >> 16) & 0x7f) * 128; + voodoo->tile_x_real = ((val >> 16) & 0x7f) * 128 * 32; + break; + + case Init_miscInit0: + banshee->miscInit0 = val; + voodoo->y_origin_swap = (val & MISCINIT0_Y_ORIGIN_SWAP_MASK) >> MISCINIT0_Y_ORIGIN_SWAP_SHIFT; + break; + case Init_miscInit1: + banshee->miscInit1 = val; + break; + case Init_dramInit0: + banshee->dramInit0 = val; + break; + case Init_dramInit1: + banshee->dramInit1 = val; + break; + case Init_agpInit0: + banshee->agpInit0 = val; + break; + + case Init_2dCommand: + banshee->command_2d = val; + break; + case Init_2dSrcBaseAddr: + banshee->srcBaseAddr_2d = val; + break; + case Init_vgaInit0: + banshee->vgaInit0 = val; + break; + case Init_vgaInit1: + banshee->vgaInit1 = val; + svga->write_bank = (val & 0x3ff) << 15; + svga->read_bank = ((val >> 10) & 0x3ff) << 15; + svga->packed_chain4 = !!(val & 0x00100000); + break; + + case PLL_pllCtrl0: + banshee->pllCtrl0 = val; + break; + case PLL_pllCtrl1: + banshee->pllCtrl1 = val; + break; + case PLL_pllCtrl2: + banshee->pllCtrl2 = val; + break; + + case DAC_dacMode: + banshee->dacMode = val; + svga->dpms = !!(val & 0x0a); + svga_recalctimings(svga); + break; + case DAC_dacAddr: + banshee->dacAddr = val & 0x1ff; + break; + case DAC_dacData: + svga->pallook[banshee->dacAddr] = val & 0xffffff; + svga->fullchange = changeframecount; + break; + + case Video_vidProcCfg: + banshee->vidProcCfg = val; +#if 0 + banshee_log("vidProcCfg=%08x\n", val); +#endif + banshee->overlay_pix_fmt = (val & VIDPROCCFG_OVERLAY_PIX_FORMAT_MASK) >> VIDPROCCFG_OVERLAY_PIX_FORMAT_SHIFT; + svga->hwcursor.ena = val & VIDPROCCFG_HWCURSOR_ENA; + svga->fullchange = changeframecount; + svga_recalctimings(svga); + break; + + case Video_maxRgbDelta: + banshee->voodoo->scrfilterThreshold = val; + if (val > 0x00) + banshee->voodoo->scrfilterEnabled = 1; + else + banshee->voodoo->scrfilterEnabled = 0; + voodoo_threshold_check(banshee->voodoo); + banshee_log("Banshee Filter: %06x\n", val); + break; + + case Video_hwCurPatAddr: + banshee->hwCurPatAddr = val; + svga->hwcursor.addr = (val & 0xfffff0) + (svga->hwcursor.yoff * 16); + break; + case Video_hwCurLoc: + banshee->hwCurLoc = val; + svga->hwcursor.x = (val & 0x7ff) - 64; + svga->hwcursor.y = ((val >> 16) & 0x7ff) - 64; + if (svga->hwcursor.y < 0) { + svga->hwcursor.yoff = -svga->hwcursor.y; + svga->hwcursor.y = 0; + } else + svga->hwcursor.yoff = 0; + svga->hwcursor.addr = (banshee->hwCurPatAddr & 0xfffff0) + (svga->hwcursor.yoff * 16); + svga->hwcursor.cur_xsize = 64; + svga->hwcursor.cur_ysize = 64; +#if 0 + banshee_log("hwCurLoc %08x %i\n", val, svga->hwcursor.y); +#endif + break; + case Video_hwCurC0: + banshee->hwCurC0 = val; + break; + case Video_hwCurC1: + banshee->hwCurC1 = val; + break; + + case Video_vidSerialParallelPort: + banshee->vidSerialParallelPort = val; +#if 0 + banshee_log("vidSerialParallelPort: write %08x %08x %04x(%08x):%08x\n", val, val & (VIDSERIAL_DDC_DCK_W | VIDSERIAL_DDC_DDA_W), CS,cs,cpu_state.pc); +#endif + i2c_gpio_set(banshee->i2c_ddc, !!(val & VIDSERIAL_DDC_DCK_W), !!(val & VIDSERIAL_DDC_DDA_W)); + i2c_gpio_set(banshee->i2c, !!(val & VIDSERIAL_I2C_SCK_W), !!(val & VIDSERIAL_I2C_SDA_W)); + break; + + case Video_vidScreenSize: + banshee->vidScreenSize = val; + voodoo->h_disp = (val & 0xfff) + 1; + voodoo->v_disp = (val >> 12) & 0xfff; + break; + case Video_vidOverlayStartCoords: + voodoo->overlay.vidOverlayStartCoords = val; + voodoo->overlay.start_x = val & OVERLAY_START_X_MASK; + voodoo->overlay.start_y = (val & OVERLAY_START_Y_MASK) >> OVERLAY_START_Y_SHIFT; + voodoo->overlay.size_x = voodoo->overlay.end_x - voodoo->overlay.start_x; + voodoo->overlay.size_y = voodoo->overlay.end_y - voodoo->overlay.start_y; + svga_recalctimings(svga); + break; + case Video_vidOverlayEndScreenCoords: + voodoo->overlay.vidOverlayEndScreenCoords = val; + voodoo->overlay.end_x = val & OVERLAY_END_X_MASK; + voodoo->overlay.end_y = (val & OVERLAY_END_Y_MASK) >> OVERLAY_END_Y_SHIFT; + voodoo->overlay.size_x = (voodoo->overlay.end_x - voodoo->overlay.start_x) + 1; + voodoo->overlay.size_y = (voodoo->overlay.end_y - voodoo->overlay.start_y) + 1; + svga_recalctimings(svga); + break; + case Video_vidOverlayDudx: + voodoo->overlay.vidOverlayDudx = val & VID_DUDX_MASK; +#if 0 + banshee_log("vidOverlayDudx=%08x\n", val); +#endif + break; + case Video_vidOverlayDudxOffsetSrcWidth: + voodoo->overlay.vidOverlayDudxOffsetSrcWidth = val; + voodoo->overlay.overlay_bytes = (val & OVERLAY_SRC_WIDTH_MASK) >> OVERLAY_SRC_WIDTH_SHIFT; +#if 0 + banshee_log("vidOverlayDudxOffsetSrcWidth=%08x\n", val); +#endif + break; + case Video_vidOverlayDvdy: + voodoo->overlay.vidOverlayDvdy = val & VID_DVDY_MASK; +#if 0 + banshee_log("vidOverlayDvdy=%08x\n", val); +#endif + break; + case Video_vidOverlayDvdyOffset: + voodoo->overlay.vidOverlayDvdyOffset = val; + break; + + case Video_vidDesktopStartAddr: + banshee->vidDesktopStartAddr = val & 0xffffff; +#if 0 + banshee_log("vidDesktopStartAddr=%08x\n", val); +#endif + svga->fullchange = changeframecount; + svga_recalctimings(svga); + break; + case Video_vidDesktopOverlayStride: + banshee->vidDesktopOverlayStride = val; +#if 0 + banshee_log("vidDesktopOverlayStride=%08x\n", val); +#endif + svga->fullchange = changeframecount; + svga_recalctimings(svga); + break; + default: +#if 0 + fatal("bad banshee_ext_outl: addr=%04x val=%08x\n", addr, val); +#endif + break; + } +} + +static uint8_t +banshee_ext_in(uint16_t addr, void *priv) +{ + banshee_t *banshee = (banshee_t *) priv; +#if 0 + svga_t *svga = &banshee->svga; +#endif + uint8_t ret = 0xff; + + switch (addr & 0xff) { + case Init_status: + case Init_status + 1: + case Init_status + 2: + case Init_status + 3: + ret = (banshee_status(banshee) >> ((addr & 3) * 8)) & 0xff; +#if 0 + banshee_log("Read status reg! %04x(%08x):%08x\n", CS, cs, cpu_state.pc); +#endif + break; + + case 0xb0: + case 0xb1: + case 0xb2: + case 0xb3: + case 0xb4: + case 0xb5: + case 0xb6: + case 0xb7: + case 0xb8: + case 0xb9: + case 0xba: + case 0xbb: + case 0xbc: + case 0xbd: + case 0xbe: + case 0xbf: + case 0xc0: + case 0xc1: + case 0xc2: + case 0xc3: + case 0xc4: + case 0xc5: + case 0xc6: + case 0xc7: + case 0xc8: + case 0xc9: + case 0xca: + case 0xcb: + case 0xcc: + case 0xcd: + case 0xce: + case 0xcf: + case 0xd0: + case 0xd1: + case 0xd2: + case 0xd3: + case 0xd4: + case 0xd5: + case 0xd6: + case 0xd7: + case 0xd8: + case 0xd9: + case 0xda: + case 0xdb: + case 0xdc: + case 0xdd: + case 0xde: + case 0xdf: + ret = banshee_in((addr & 0xff) + 0x300, priv); + break; + + default: + banshee_log("bad banshee_ext_in: addr=%04x\n", addr); + break; + } + + // banshee_log("banshee_ext_in: addr=%04x val=%02x\n", addr, ret); + + return ret; +} + +static uint32_t +banshee_status(banshee_t *banshee) +{ + voodoo_t *voodoo = banshee->voodoo; + const svga_t *svga = &banshee->svga; + int fifo_entries = FIFO_ENTRIES; + int swap_count = voodoo->swap_count; + int written = voodoo->cmd_written + voodoo->cmd_written_fifo; + int busy = (written - voodoo->cmd_read) || (voodoo->cmdfifo_depth_rd != voodoo->cmdfifo_depth_wr) || voodoo->render_voodoo_busy[0] || voodoo->render_voodoo_busy[1] || voodoo->render_voodoo_busy[2] || voodoo->render_voodoo_busy[3] || voodoo->voodoo_busy; + uint32_t ret = 0; + + if (fifo_entries < 0x20) + ret |= 0x1f - fifo_entries; + else + ret |= 0x1f; + if (fifo_entries) + ret |= 0x20; + if (swap_count < 7) + ret |= (swap_count << 28); + else + ret |= (7 << 28); + if (!(svga->cgastat & 8)) + ret |= 0x40; + + if (busy) + ret |= 0x780; /*Busy*/ + + if (voodoo->cmdfifo_depth_rd != voodoo->cmdfifo_depth_wr) + ret |= (1 << 11); + + if (!voodoo->voodoo_busy) + voodoo_wake_fifo_thread(voodoo); + +#if 0 + banshee_log("banshee_status: busy %i %i (%i %i) %i %i %i %04x(%08x):%08x %08x\n", busy, written, voodoo->cmd_written, voodoo->cmd_written_fifo, voodoo->cmd_read, voodoo->cmdfifo_depth_rd, voodoo->cmdfifo_depth_wr, CS,cs,cpu_state.pc, ret); +#endif + + return ret; +} + +static uint32_t +banshee_ext_inl(uint16_t addr, void *priv) +{ + banshee_t *banshee = (banshee_t *) priv; + const voodoo_t *voodoo = banshee->voodoo; + const svga_t *svga = &banshee->svga; + uint32_t ret = 0xffffffff; + + cycles -= voodoo->read_time; + + switch (addr & 0xff) { + case Init_status: + ret = banshee_status(banshee); +#if 0 + banshee_log("Read status reg! %04x(%08x):%08x\n", CS, cs, cpu_state.pc); +#endif + break; + case Init_pciInit0: + ret = banshee->pciInit0; + break; + case Init_lfbMemoryConfig: + ret = banshee->lfbMemoryConfig; + break; + + case Init_miscInit0: + ret = banshee->miscInit0; + break; + case Init_miscInit1: + ret = banshee->miscInit1; + break; + case Init_dramInit0: + ret = banshee->dramInit0; + break; + case Init_dramInit1: + ret = banshee->dramInit1; + break; + case Init_agpInit0: + ret = banshee->agpInit0; + break; + + case Init_vgaInit0: + ret = banshee->vgaInit0; + break; + case Init_vgaInit1: + ret = banshee->vgaInit1; + break; + + case Init_2dCommand: + ret = banshee->command_2d; + break; + case Init_2dSrcBaseAddr: + ret = banshee->srcBaseAddr_2d; + break; + case Init_strapInfo: + ret = 0x00000040; /*8 MB SGRAM, PCI, IRQ enabled, 32kB BIOS*/ + break; + + case PLL_pllCtrl0: + ret = banshee->pllCtrl0; + break; + case PLL_pllCtrl1: + ret = banshee->pllCtrl1; + break; + case PLL_pllCtrl2: + ret = banshee->pllCtrl2; + break; + + case DAC_dacMode: + ret = banshee->dacMode; + break; + case DAC_dacAddr: + ret = banshee->dacAddr; + break; + case DAC_dacData: + ret = svga->pallook[banshee->dacAddr]; + break; + + case Video_vidProcCfg: + ret = banshee->vidProcCfg; + break; + + case Video_hwCurPatAddr: + ret = banshee->hwCurPatAddr; + break; + case Video_hwCurLoc: + ret = banshee->hwCurLoc; + break; + case Video_hwCurC0: + ret = banshee->hwCurC0; + break; + case Video_hwCurC1: + ret = banshee->hwCurC1; + break; + + case Video_vidSerialParallelPort: + ret = banshee->vidSerialParallelPort & ~(VIDSERIAL_DDC_DCK_R | VIDSERIAL_DDC_DDA_R | VIDSERIAL_I2C_SCK_R | VIDSERIAL_I2C_SDA_R); + if (banshee->vidSerialParallelPort & VIDSERIAL_DDC_EN) { + if (i2c_gpio_get_scl(banshee->i2c_ddc)) + ret |= VIDSERIAL_DDC_DCK_R; + if (i2c_gpio_get_sda(banshee->i2c_ddc)) + ret |= VIDSERIAL_DDC_DDA_R; + } + if (banshee->vidSerialParallelPort & VIDSERIAL_I2C_EN) { + if (i2c_gpio_get_scl(banshee->i2c)) + ret |= VIDSERIAL_I2C_SCK_R; + if (i2c_gpio_get_sda(banshee->i2c)) + ret |= VIDSERIAL_I2C_SDA_R; + } +#if 0 + banshee_log("vidSerialParallelPort: read %08x %08x %04x(%08x):%08x\n", ret, ret & (VIDSERIAL_DDC_DCK_R | VIDSERIAL_DDC_DDA_R), CS,cs,cpu_state.pc); +#endif + break; + + case Video_vidScreenSize: + ret = banshee->vidScreenSize; + break; + case Video_vidOverlayStartCoords: + ret = voodoo->overlay.vidOverlayStartCoords; + break; + case Video_vidOverlayEndScreenCoords: + ret = voodoo->overlay.vidOverlayEndScreenCoords; + break; + case Video_vidOverlayDudx: + ret = voodoo->overlay.vidOverlayDudx; + break; + case Video_vidOverlayDudxOffsetSrcWidth: + ret = voodoo->overlay.vidOverlayDudxOffsetSrcWidth; + break; + case Video_vidOverlayDvdy: + ret = voodoo->overlay.vidOverlayDvdy; + break; + case Video_vidOverlayDvdyOffset: + ret = voodoo->overlay.vidOverlayDvdyOffset; + break; + + case Video_vidDesktopStartAddr: + ret = banshee->vidDesktopStartAddr; + break; + case Video_vidDesktopOverlayStride: + ret = banshee->vidDesktopOverlayStride; + break; + + default: + // fatal("bad banshee_ext_inl: addr=%04x\n", addr); + break; + } + +#if 0 + if (addr) + banshee_log("banshee_ext_inl: addr=%04x val=%08x\n", addr, ret); +#endif + + return ret; +} + +static uint32_t banshee_reg_readl(uint32_t addr, void *priv); + +static uint8_t +banshee_reg_read(uint32_t addr, void *priv) +{ +#if 0 + banshee_log("banshee_reg_read: addr=%08x\n", addr); +#endif + return banshee_reg_readl(addr & ~3, priv) >> (8 * (addr & 3)); +} + +static uint16_t +banshee_reg_readw(uint32_t addr, void *priv) +{ +#if 0 + banshee_log("banshee_reg_readw: addr=%08x\n", addr); +#endif + return banshee_reg_readl(addr & ~3, priv) >> (8 * (addr & 2)); +} + +static uint32_t +banshee_cmd_read(banshee_t *banshee, uint32_t addr) +{ + const voodoo_t *voodoo = banshee->voodoo; + uint32_t ret = 0xffffffff; + + switch (addr & 0x1fc) { + case Agp_agpHostAddressLow: + ret = banshee->agpHostAddressLow; + break; + + case Agp_agpHostAddressHigh: + ret = banshee->agpHostAddressHigh; + break; + + case Agp_agpGraphicsAddress: + ret = banshee->agpGraphicsAddress; + break; + + case Agp_agpGraphicsStride: + ret = banshee->agpGraphicsStride; + break; + + case Agp_agpReqSize: + ret = banshee->agpReqSize; + break; + + case cmdBaseAddr0: + ret = voodoo->cmdfifo_base >> 12; + // banshee_log("Read cmdfifo_base %08x\n", ret); + break; + + case cmdRdPtrL0: + ret = voodoo->cmdfifo_rp; + // banshee_log("Read cmdfifo_rp %08x\n", ret); + break; + + case cmdFifoDepth0: + ret = voodoo->cmdfifo_depth_wr - voodoo->cmdfifo_depth_rd; + // banshee_log("Read cmdfifo_depth %08x\n", ret); + break; + + case cmdStatus0: + ret = voodoo->cmd_status; + break; + + case cmdBaseSize0: + ret = voodoo->cmdfifo_size; + break; + + case 0x108: + break; + + default: + fatal("Unknown banshee_cmd_read 0x%08x (reg 0x%03x)\n", addr, addr & 0x1fc); + } + + return ret; +} + +static uint32_t +banshee_reg_readl(uint32_t addr, void *priv) +{ + banshee_t *banshee = (banshee_t *) priv; + voodoo_t *voodoo = banshee->voodoo; + uint32_t ret = 0xffffffff; + + cycles -= voodoo->read_time; + + switch (addr & 0x1f00000) { + case 0x0000000: /*IO remap*/ + if (!(addr & 0x80000)) + ret = banshee_ext_inl(addr & 0xff, banshee); + else + ret = banshee_cmd_read(banshee, addr); + break; + + case 0x0100000: /*2D registers*/ + voodoo_flush(voodoo); + switch (addr & 0x1fc) { + case SST_status: + ret = banshee_status(banshee); + break; + + case SST_intrCtrl: + ret = banshee->intrCtrl & 0x0030003f; + break; + + case 0x08: + ret = voodoo->banshee_blt.clip0Min; + break; + case 0x0c: + ret = voodoo->banshee_blt.clip0Max; + break; + case 0x10: + ret = voodoo->banshee_blt.dstBaseAddr; + break; + case 0x14: + ret = voodoo->banshee_blt.dstFormat; + break; + case 0x34: + ret = voodoo->banshee_blt.srcBaseAddr; + break; + case 0x38: + ret = voodoo->banshee_blt.commandExtra; + break; + case 0x5c: + ret = voodoo->banshee_blt.srcXY; + break; + case 0x60: + ret = voodoo->banshee_blt.colorBack; + break; + case 0x64: + ret = voodoo->banshee_blt.colorFore; + break; + case 0x68: + ret = voodoo->banshee_blt.dstSize; + break; + case 0x6c: + ret = voodoo->banshee_blt.dstXY; + break; + case 0x70: + ret = voodoo->banshee_blt.command; + break; default: - temp = svga_in(addr, svga); - break; - } -// if (addr != 0x3da) banshee_log("%02X %04X:%04X %i\n", temp, CS,cpu_state.pc, ins); - return temp; + banshee_log("banshee_reg_readl: addr=%08x\n", addr); + } + break; + + case 0x0200000: + case 0x0300000: + case 0x0400000: + case 0x0500000: /*3D registers*/ + switch (addr & 0x3fc) { + case SST_status: + ret = banshee_status(banshee); + break; + + case SST_intrCtrl: + ret = banshee->intrCtrl & 0x0030003f; + break; + + case SST_fbzColorPath: + voodoo_flush(voodoo); + ret = voodoo->params.fbzColorPath; + break; + case SST_fogMode: + voodoo_flush(voodoo); + ret = voodoo->params.fogMode; + break; + case SST_alphaMode: + voodoo_flush(voodoo); + ret = voodoo->params.alphaMode; + break; + case SST_fbzMode: + voodoo_flush(voodoo); + ret = voodoo->params.fbzMode; + break; + case SST_lfbMode: + voodoo_flush(voodoo); + ret = voodoo->lfbMode; + break; + case SST_clipLeftRight: + ret = voodoo->params.clipRight | (voodoo->params.clipLeft << 16); + break; + case SST_clipLowYHighY: + ret = voodoo->params.clipHighY | (voodoo->params.clipLowY << 16); + break; + + case SST_clipLeftRight1: + ret = voodoo->params.clipRight1 | (voodoo->params.clipLeft1 << 16); + break; + case SST_clipTopBottom1: + ret = voodoo->params.clipHighY1 | (voodoo->params.clipLowY1 << 16); + break; + + case SST_stipple: + voodoo_flush(voodoo); + ret = voodoo->params.stipple; + break; + case SST_color0: + voodoo_flush(voodoo); + ret = voodoo->params.color0; + break; + case SST_color1: + voodoo_flush(voodoo); + ret = voodoo->params.color1; + break; + + case SST_fbiPixelsIn: + ret = voodoo->fbiPixelsIn & 0xffffff; + break; + case SST_fbiChromaFail: + ret = voodoo->fbiChromaFail & 0xffffff; + break; + case SST_fbiZFuncFail: + ret = voodoo->fbiZFuncFail & 0xffffff; + break; + case SST_fbiAFuncFail: + ret = voodoo->fbiAFuncFail & 0xffffff; + break; + case SST_fbiPixelsOut: + ret = voodoo->fbiPixelsOut & 0xffffff; + break; + + default: + banshee_log("banshee_reg_readl: 3D addr=%08x\n", addr); + break; + } + break; + + default: + break; + } + +#if 0 + if (addr != 0xe0000000) + banshee_log("banshee_reg_readl: addr=%08x ret=%08x %04x(%08x):%08x\n", addr, ret, CS,cs,cpu_state.pc); +#endif + + return ret; } -static void banshee_updatemapping(banshee_t *banshee) +static void +banshee_reg_write(UNUSED(uint32_t addr), UNUSED(uint8_t val), UNUSED(void *priv)) { - svga_t *svga = &banshee->svga; - - if (!(banshee->pci_regs[PCI_REG_COMMAND] & PCI_COMMAND_MEM)) - { -// banshee_log("Update mapping - PCI disabled\n"); - mem_mapping_disable(&svga->mapping); - mem_mapping_disable(&banshee->linear_mapping); - mem_mapping_disable(&banshee->reg_mapping_low); - mem_mapping_disable(&banshee->reg_mapping_high); - return; - } - - banshee_log("Update mapping - bank %02X ", svga->gdcreg[6] & 0xc); - switch (svga->gdcreg[6] & 0xc) /*Banked framebuffer*/ - { - 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; - } - - banshee_log("Linear framebuffer %08X ", banshee->memBaseAddr1); - mem_mapping_set_addr(&banshee->linear_mapping, banshee->memBaseAddr1, 32 << 20); - banshee_log("registers %08X\n", banshee->memBaseAddr0); - mem_mapping_set_addr(&banshee->reg_mapping_low, banshee->memBaseAddr0, 8 << 20); - mem_mapping_set_addr(&banshee->reg_mapping_high, banshee->memBaseAddr0 + 0xc00000, 20 << 20); +#if 0 + banshee_log("banshee_reg_writeb: addr=%08x val=%02x\n", addr, val); +#endif } -static void banshee_render_16bpp_tiled(svga_t *svga) +static void +banshee_reg_writew(uint32_t addr, uint16_t val, void *priv) { - banshee_t *banshee = (banshee_t *)svga->p; + banshee_t *banshee = (banshee_t *) priv; + voodoo_t *voodoo = banshee->voodoo; + + cycles -= voodoo->write_time; + +#if 0 + banshee_log("banshee_reg_writew: addr=%08x val=%04x\n", addr, val); +#endif + switch (addr & 0x1f00000) { + case 0x1000000: + case 0x1100000: + case 0x1200000: + case 0x1300000: /*3D LFB*/ + case 0x1400000: + case 0x1500000: + case 0x1600000: + case 0x1700000: + case 0x1800000: + case 0x1900000: + case 0x1a00000: + case 0x1b00000: + case 0x1c00000: + case 0x1d00000: + case 0x1e00000: + case 0x1f00000: + voodoo_queue_command(voodoo, (addr & 0xffffff) | FIFO_WRITEW_FB, val); + break; + + default: + break; + } +} + +static void +banshee_cmd_write(banshee_t *banshee, uint32_t addr, uint32_t val) +{ + voodoo_t *voodoo = banshee->voodoo; +#if 0 + banshee_log("banshee_cmd_write: addr=%03x val=%08x\n", addr & 0x1fc, val); +#endif + switch (addr & 0x1fc) { + case Agp_agpHostAddressLow: + banshee->agpHostAddressLow = val; + break; + + case Agp_agpHostAddressHigh: + banshee->agpHostAddressHigh = val; + break; + + case Agp_agpGraphicsAddress: + banshee->agpGraphicsAddress = val; + break; + + case Agp_agpGraphicsStride: + banshee->agpGraphicsStride = val; + break; + + case Agp_agpReqSize: + banshee->agpReqSize = val; + break; + + case cmdBaseAddr0: + voodoo->cmdfifo_base = (val & 0xfff) << 12; + voodoo->cmdfifo_end = voodoo->cmdfifo_base + (((voodoo->cmdfifo_size & 0xff) + 1) << 12); +#if 0 + banshee_log("cmdfifo_base=%08x cmdfifo_end=%08x %08x\n", voodoo->cmdfifo_base, voodoo->cmdfifo_end, val); +#endif + break; + + case cmdBaseSize0: + voodoo->cmdfifo_size = val; + voodoo->cmdfifo_end = voodoo->cmdfifo_base + (((voodoo->cmdfifo_size & 0xff) + 1) << 12); + voodoo->cmdfifo_enabled = val & 0x100; + if (!voodoo->cmdfifo_enabled) + voodoo->cmdfifo_in_sub = 0; /*Not sure exactly when this should be reset*/ +#if 0 + banshee_log("cmdfifo_base=%08x cmdfifo_end=%08x\n", voodoo->cmdfifo_base, voodoo->cmdfifo_end); +#endif + break; + +#if 0 + voodoo->cmdfifo_end = ((val >> 16) & 0x3ff) << 12; + banshee_log("CMDFIFO base=%08x end=%08x\n", voodoo->cmdfifo_base, voodoo->cmdfifo_end); + break; +#endif + + case cmdRdPtrL0: + voodoo->cmdfifo_rp = val; + break; + case cmdAMin0: + voodoo->cmdfifo_amin = val; + break; + case cmdAMax0: + voodoo->cmdfifo_amax = val; + break; + case cmdFifoDepth0: + voodoo->cmdfifo_depth_rd = 0; + voodoo->cmdfifo_depth_wr = val & 0xffff; + break; + + default: + banshee_log("Unknown banshee_cmd_write: addr=%08x val=%08x reg=0x%03x\n", addr, val, addr & 0x1fc); + break; + } + +#if 0 + cmdBaseSize0 = 0x24, + cmdBump0 = 0x28, + cmdRdPtrL0 = 0x2c, + cmdRdPtrH0 = 0x30, + cmdAMin0 = 0x34, + cmdAMax0 = 0x3c, + cmdFifoDepth0 = 0x44, + cmdHoleCnt0 = 0x48 + } +#endif +} + +static void +banshee_reg_writel(uint32_t addr, uint32_t val, void *priv) +{ + banshee_t *banshee = (banshee_t *) priv; + voodoo_t *voodoo = banshee->voodoo; + + if (addr == voodoo->last_write_addr + 4) + cycles -= voodoo->burst_time; + else + cycles -= voodoo->write_time; + voodoo->last_write_addr = addr; + +#if 0 + banshee_log("banshee_reg_writel: addr=%08x val=%08x\n", addr, val); +#endif + + switch (addr & 0x1f00000) { + case 0x0000000: /*IO remap*/ + if (!(addr & 0x80000)) + banshee_ext_outl(addr & 0xff, val, banshee); + else + banshee_cmd_write(banshee, addr, val); +#if 0 + banshee_log("CMD!!! write %08x %08x\n", addr, val); +#endif + break; + + case 0x0100000: /*2D registers*/ + if ((addr & 0x3fc) == SST_intrCtrl) { + banshee->intrCtrl = val & 0x0030003f; + } else { + voodoo_queue_command(voodoo, (addr & 0x1fc) | FIFO_WRITEL_2DREG, val); + } + break; + + case 0x0200000: + case 0x0300000: + case 0x0400000: + case 0x0500000: /*3D registers*/ + switch (addr & 0x3fc) { + case SST_intrCtrl: + banshee->intrCtrl = val & 0x0030003f; +#if 0 + banshee_log("intrCtrl=%08x\n", val); +#endif + break; + + case SST_userIntrCMD: + fatal("userIntrCMD write %08x\n", val); + break; + + case SST_swapbufferCMD: + voodoo->cmd_written++; + voodoo_queue_command(voodoo, (addr & 0x3fc) | FIFO_WRITEL_REG, val); + if (!voodoo->voodoo_busy) + voodoo_wake_fifo_threads(voodoo->set, voodoo); +#if 0 + banshee_log("SST_swapbufferCMD write: %i %i\n", voodoo->cmd_written, voodoo->cmd_written_fifo); +#endif + break; + case SST_triangleCMD: + voodoo->cmd_written++; + voodoo_queue_command(voodoo, (addr & 0x3fc) | FIFO_WRITEL_REG, val); + if (!voodoo->voodoo_busy) + voodoo_wake_fifo_threads(voodoo->set, voodoo); + break; + case SST_ftriangleCMD: + voodoo->cmd_written++; + voodoo_queue_command(voodoo, (addr & 0x3fc) | FIFO_WRITEL_REG, val); + if (!voodoo->voodoo_busy) + voodoo_wake_fifo_threads(voodoo->set, voodoo); + break; + case SST_fastfillCMD: + voodoo->cmd_written++; + voodoo_queue_command(voodoo, (addr & 0x3fc) | FIFO_WRITEL_REG, val); + if (!voodoo->voodoo_busy) + voodoo_wake_fifo_threads(voodoo->set, voodoo); + break; + case SST_nopCMD: + voodoo->cmd_written++; + voodoo_queue_command(voodoo, (addr & 0x3fc) | FIFO_WRITEL_REG, val); + if (!voodoo->voodoo_busy) + voodoo_wake_fifo_threads(voodoo->set, voodoo); + break; + + case SST_swapPending: + thread_wait_mutex(voodoo->swap_mutex); + voodoo->swap_count++; + thread_release_mutex(voodoo->swap_mutex); +#if 0 + voodoo->cmd_written++; +#endif + break; + + default: + voodoo_queue_command(voodoo, (addr & 0x3ffffc) | FIFO_WRITEL_REG, val); + break; + } + break; + + case 0x0600000: + case 0x0700000: /*TMU0 Texture download*/ + voodoo->tex_count++; + voodoo_queue_command(voodoo, (addr & 0x1ffffc) | FIFO_WRITEL_TEX, val); + break; + + case 0x1000000: + case 0x1100000: + case 0x1200000: + case 0x1300000: /*3D LFB*/ + case 0x1400000: + case 0x1500000: + case 0x1600000: + case 0x1700000: + case 0x1800000: + case 0x1900000: + case 0x1a00000: + case 0x1b00000: + case 0x1c00000: + case 0x1d00000: + case 0x1e00000: + case 0x1f00000: + voodoo_queue_command(voodoo, (addr & 0xfffffc) | FIFO_WRITEL_FB, val); + break; + + default: + break; + } +} + +static uint8_t +banshee_read_linear(uint32_t addr, void *priv) +{ + banshee_t *banshee = (banshee_t *) priv; + const voodoo_t *voodoo = banshee->voodoo; + const svga_t *svga = &banshee->svga; + + cycles -= voodoo->read_time; + + if ((banshee->pci_regs[0x30] & 0x01) && addr >= banshee->bios_rom.mapping.base && addr < (banshee->bios_rom.mapping.base + banshee->bios_rom.sz)) { + return rom_read(addr & (banshee->bios_rom.sz - 1), &banshee->bios_rom); + } + addr &= svga->decode_mask; + if (addr >= voodoo->tile_base) { int x; - uint32_t *p = &((uint32_t *)buffer32->line[svga->displine + svga->y_add])[svga->x_add]; - uint32_t addr; - int drawn = 0; + int y; - if ((svga->displine + svga->y_add) < 0) - return; + addr -= voodoo->tile_base; + x = addr & (voodoo->tile_stride - 1); + y = addr >> voodoo->tile_stride_shift; - if (banshee->vidProcCfg & VIDPROCCFG_HALF_MODE) - addr = banshee->desktop_addr + ((banshee->desktop_y >> 1) & 31) * 128 + ((banshee->desktop_y >> 6) * banshee->desktop_stride_tiled); - else - addr = banshee->desktop_addr + (banshee->desktop_y & 31) * 128 + ((banshee->desktop_y >> 5) * banshee->desktop_stride_tiled); + addr = voodoo->tile_base + (x & 127) + ((x >> 7) * 128 * 32) + ((y & 31) * 128) + (y >> 5) * voodoo->tile_x_real; +#if 0 + banshee_log(" Tile rb %08x->%08x %i %i\n", old_addr, addr, x, y); +#endif + } + if (addr >= svga->vram_max) + return 0xff; - for (x = 0; x <= svga->hdisp; x += 64) - { - if (svga->hwcursor_on || svga->overlay_on) - svga->changedvram[addr >> 12] = 2; - if (svga->changedvram[addr >> 12] || svga->fullchange) - { - uint16_t *vram_p = (uint16_t *)&svga->vram[addr & svga->vram_display_mask]; - int xx; + cycles -= svga->monitor->mon_video_timing_read_b; - for (xx = 0; xx < 64; xx++) - *p++ = video_16to32[*vram_p++]; +#if 0 + banshee_log("read_linear: addr=%08x val=%02x\n", addr, svga->vram[addr & svga->vram_mask]); +#endif - drawn = 1; - } - else - p += 64; - addr += 128*32; - } - - if (drawn) - { - if (svga->firstline_draw == 2000) - svga->firstline_draw = svga->displine; - svga->lastline_draw = svga->displine; - } - - banshee->desktop_y++; + return svga->vram[addr & svga->vram_mask]; } -static void banshee_recalctimings(svga_t *svga) +static uint16_t +banshee_read_linear_w(uint32_t addr, void *priv) { - banshee_t *banshee = (banshee_t *)svga->p; - voodoo_t *voodoo = banshee->voodoo; - -/*7 R/W Horizontal Retrace End bit 5. - - 6 R/W Horizontal Retrace Start bit 8 0x4 - 5 R/W Horizontal Blank End bit 6. - - 4 R/W Horizontal Blank Start bit 8. 0x3 - 3 R/W Reserved. - - 2 R/W Horizontal Display Enable End bit 8. 0x1 - 1 R/W Reserved. - - 0 R/W Horizontal Total bit 8. 0x0*/ - if (svga->crtc[0x1a] & 0x01) svga->htotal += 0x100; - if (svga->crtc[0x1a] & 0x04) svga->hdisp += 0x100; -/*6 R/W Vertical Retrace Start bit 10 0x10 - 5 R/W Reserved. - - 4 R/W Vertical Blank Start bit 10. 0x15 - 3 R/W Reserved. - - 2 R/W Vertical Display Enable End bit 10 0x12 - 1 R/W Reserved. - - 0 R/W Vertical Total bit 10. 0x6*/ - if (svga->crtc[0x1b] & 0x01) svga->vtotal += 0x400; - if (svga->crtc[0x1b] & 0x04) svga->dispend += 0x400; - if (svga->crtc[0x1b] & 0x10) svga->vblankstart += 0x400; - if (svga->crtc[0x1b] & 0x40) svga->vsyncstart += 0x400; -// banshee_log("svga->hdisp=%i\n", svga->hdisp); + banshee_t *banshee = (banshee_t *) priv; + const voodoo_t *voodoo = banshee->voodoo; + svga_t *svga = &banshee->svga; - svga->interlace = 0; + if (addr & 1) + return banshee_read_linear(addr, priv) | (banshee_read_linear(addr + 1, priv) << 8); - if (banshee->vgaInit0 & VGAINIT0_EXTENDED_SHIFT_OUT) - { - switch (VIDPROCCFG_DESKTOP_PIX_FORMAT) - { - case PIX_FORMAT_8: - svga->render = svga_render_8bpp_highres; - svga->bpp = 8; - break; - case PIX_FORMAT_RGB565: - svga->render = (banshee->vidProcCfg & VIDPROCCFG_DESKTOP_TILE) ? banshee_render_16bpp_tiled : svga_render_16bpp_highres; - svga->bpp = 16; - break; - case PIX_FORMAT_RGB24: - svga->render = svga_render_24bpp_highres; - svga->bpp = 24; - break; - case PIX_FORMAT_RGB32: - svga->render = svga_render_32bpp_highres; - svga->bpp = 32; - break; - default: - fatal("Unknown pixel format %08x\n", banshee->vgaInit0); - } - if (!(banshee->vidProcCfg & VIDPROCCFG_DESKTOP_TILE) && (banshee->vidProcCfg & VIDPROCCFG_HALF_MODE)) - svga->rowcount = 1; - else - svga->rowcount = 0; - if (banshee->vidProcCfg & VIDPROCCFG_DESKTOP_TILE) - svga->rowoffset = ((banshee->vidDesktopOverlayStride & 0x3fff) * 128) >> 3; - else - svga->rowoffset = (banshee->vidDesktopOverlayStride & 0x3fff) >> 3; - svga->ma_latch = banshee->vidDesktopStartAddr >> 2; - banshee->desktop_stride_tiled = (banshee->vidDesktopOverlayStride & 0x3fff) * 128 * 32; -// banshee_log("Extended shift out %i rowoffset=%i %02x\n", VIDPROCCFG_DESKTOP_PIX_FORMAT, svga->rowoffset, svga->crtc[1]); + cycles -= voodoo->read_time; + if ((banshee->pci_regs[0x30] & 0x01) && addr >= banshee->bios_rom.mapping.base && addr < (banshee->bios_rom.mapping.base + banshee->bios_rom.sz)) { + return rom_readw(addr & (banshee->bios_rom.sz - 1), &banshee->bios_rom); + } + addr &= svga->decode_mask; + if (addr >= voodoo->tile_base) { + int x; + int y; - svga->char_width = 8; - svga->split = 99999; + addr -= voodoo->tile_base; + x = addr & (voodoo->tile_stride - 1); + y = addr >> voodoo->tile_stride_shift; - if (banshee->vidProcCfg & VIDPROCCFG_2X_MODE) - { - svga->hdisp *= 2; - svga->htotal *= 2; - } + addr = voodoo->tile_base + (x & 127) + ((x >> 7) * 128 * 32) + ((y & 31) * 128) + (y >> 5) * voodoo->tile_x_real; +#if 0 + banshee_log(" Tile rb %08x->%08x %i %i\n", old_addr, addr, x, y); +#endif + } + if (addr >= svga->vram_max) + return 0xff; - svga->interlace = !!(banshee->vidProcCfg & VIDPROCCFG_INTERLACE); + cycles -= svga->monitor->mon_video_timing_read_w; - svga->overlay.ena = banshee->vidProcCfg & VIDPROCCFG_OVERLAY_ENABLE; +#if 0 + banshee_log("read_linear: addr=%08x val=%02x\n", addr, svga->vram[addr & svga->vram_mask]); +#endif - svga->overlay.x = voodoo->overlay.start_x; - svga->overlay.y = voodoo->overlay.start_y; - svga->overlay.xsize = voodoo->overlay.size_x; - svga->overlay.ysize = voodoo->overlay.size_y; - svga->overlay.pitch = (banshee->vidDesktopOverlayStride & VID_STRIDE_OVERLAY_MASK) >> VID_STRIDE_OVERLAY_SHIFT; - if (banshee->vidProcCfg & VIDPROCCFG_OVERLAY_TILE) - svga->overlay.pitch *= 128*32; - if (svga->overlay.xsize <= 0 || svga->overlay.ysize <= 0) - svga->overlay.ena = 0; - if (svga->overlay.ena) - { -/* banshee_log("Overlay enabled : start=%i,%i end=%i,%i size=%i,%i pitch=%x\n", - voodoo->overlay.start_x, voodoo->overlay.start_y, - voodoo->overlay.end_x, voodoo->overlay.end_y, - voodoo->overlay.size_x, voodoo->overlay.size_y, - svga->overlay.pitch);*/ - if (!voodoo->overlay.start_x && !voodoo->overlay.start_y && - svga->hdisp == voodoo->overlay.size_x && svga->dispend == voodoo->overlay.size_y) - { - /*Overlay is full screen, so don't bother rendering the desktop - behind it*/ - svga->render = svga_render_null; - svga->bpp = 0; - } - } - } - else - { -// banshee_log("Normal shift out\n"); - svga->bpp = 8; - } - - svga->fb_only = (banshee->vidProcCfg & VIDPROCCFG_VIDPROC_ENABLE); - - if (((svga->miscout >> 2) & 3) == 3) - { - int k = banshee->pllCtrl0 & 3; - int m = (banshee->pllCtrl0 >> 2) & 0x3f; - int n = (banshee->pllCtrl0 >> 8) & 0xff; - double freq = (((double)n + 2) / (((double)m + 2) * (double)(1 << k))) * 14318184.0; - - svga->clock = (cpuclock * (float)(1ull << 32)) / freq; -// svga->clock = cpuclock / freq; - -// banshee_log("svga->clock = %g %g m=%i k=%i n=%i\n", freq, freq / 1000000.0, m, k, n); - } + return *(uint16_t *) &svga->vram[addr & svga->vram_mask]; } -static void banshee_ext_out(uint16_t addr, uint8_t val, void *p) +static uint32_t +banshee_read_linear_l(uint32_t addr, void *priv) { -// banshee_t *banshee = (banshee_t *)p; -// svga_t *svga = &banshee->svga; + banshee_t *banshee = (banshee_t *) priv; + const voodoo_t *voodoo = banshee->voodoo; + svga_t *svga = &banshee->svga; -// banshee_log("banshee_ext_out: addr=%04x val=%02x\n", addr, val); - - switch (addr & 0xff) - { - case 0xb0: case 0xb1: case 0xb2: case 0xb3: - case 0xb4: case 0xb5: case 0xb6: case 0xb7: - case 0xb8: case 0xb9: case 0xba: case 0xbb: - case 0xbc: case 0xbd: case 0xbe: case 0xbf: - case 0xc0: case 0xc1: case 0xc2: case 0xc3: - case 0xc4: case 0xc5: case 0xc6: case 0xc7: - case 0xc8: case 0xc9: case 0xca: case 0xcb: - case 0xcc: case 0xcd: case 0xce: case 0xcf: - case 0xd0: case 0xd1: case 0xd2: case 0xd3: - case 0xd4: case 0xd5: case 0xd6: case 0xd7: - case 0xd8: case 0xd9: case 0xda: case 0xdb: - case 0xdc: case 0xdd: case 0xde: case 0xdf: - banshee_out((addr & 0xff)+0x300, val, p); - break; - - default: - banshee_log("bad banshee_ext_out: addr=%04x val=%02x\n", addr, val); - } -} -static void banshee_ext_outl(uint16_t addr, uint32_t val, void *p) -{ - banshee_t *banshee = (banshee_t *)p; - voodoo_t *voodoo = banshee->voodoo; - svga_t *svga = &banshee->svga; + if (addr & 3) + return banshee_read_linear_w(addr, priv) | (banshee_read_linear_w(addr + 2, priv) << 16); -// banshee_log("banshee_ext_outl: addr=%04x val=%08x %04x(%08x):%08x\n", addr, val, CS,cs,cpu_state.pc); - - switch (addr & 0xff) - { - case Init_pciInit0: - banshee->pciInit0 = val; - voodoo->read_time = (banshee->agp ? agp_nonburst_time : pci_nonburst_time) + (banshee->agp ? agp_burst_time : pci_burst_time) * ((val & 0x100) ? 2 : 1); - voodoo->burst_time = (banshee->agp ? agp_burst_time : pci_burst_time) * ((val & 0x200) ? 1 : 0); - voodoo->write_time = (banshee->agp ? agp_nonburst_time : pci_nonburst_time) + voodoo->burst_time; - break; - - case Init_lfbMemoryConfig: - banshee->lfbMemoryConfig = val; -// banshee_log("lfbMemoryConfig=%08x\n", val); - voodoo->tile_base = (val & 0x1fff) << 12; - voodoo->tile_stride = 1024 << ((val >> 13) & 7); - voodoo->tile_stride_shift = 10 + ((val >> 13) & 7); - voodoo->tile_x = ((val >> 16) & 0x7f) * 128; - voodoo->tile_x_real = ((val >> 16) & 0x7f) * 128*32; - break; + cycles -= voodoo->read_time; - case Init_miscInit0: - banshee->miscInit0 = val; - voodoo->y_origin_swap = (val & MISCINIT0_Y_ORIGIN_SWAP_MASK) >> MISCINIT0_Y_ORIGIN_SWAP_SHIFT; - break; - case Init_miscInit1: - banshee->miscInit1 = val; - break; - case Init_dramInit0: - banshee->dramInit0 = val; - break; - case Init_dramInit1: - banshee->dramInit1 = val; - break; - case Init_agpInit0: - banshee->agpInit0 = val; - break; + if ((banshee->pci_regs[0x30] & 0x01) && addr >= banshee->bios_rom.mapping.base && addr < (banshee->bios_rom.mapping.base + banshee->bios_rom.sz)) { + return rom_readl(addr & (banshee->bios_rom.sz - 1), &banshee->bios_rom); + } + addr &= svga->decode_mask; + if (addr >= voodoo->tile_base) { + int x; + int y; - case Init_2dCommand: - banshee->command_2d = val; - break; - case Init_2dSrcBaseAddr: - banshee->srcBaseAddr_2d = val; - break; - case Init_vgaInit0: - banshee->vgaInit0 = val; - break; - case Init_vgaInit1: - banshee->vgaInit1 = val; - svga->write_bank = (val & 0x3ff) << 15; - svga->read_bank = ((val >> 10) & 0x3ff) << 15; - svga->packed_chain4 = !!(val & 0x00100000); - break; + addr -= voodoo->tile_base; + x = addr & (voodoo->tile_stride - 1); + y = addr >> voodoo->tile_stride_shift; - case PLL_pllCtrl0: - banshee->pllCtrl0 = val; - break; - case PLL_pllCtrl1: - banshee->pllCtrl1 = val; - break; - case PLL_pllCtrl2: - banshee->pllCtrl2 = val; - break; + addr = voodoo->tile_base + (x & 127) + ((x >> 7) * 128 * 32) + ((y & 31) * 128) + (y >> 5) * voodoo->tile_x_real; +#if 0 + banshee_log(" Tile rb %08x->%08x %i %i\n", old_addr, addr, x, y); +#endif + } + if (addr >= svga->vram_max) + return 0xff; - case DAC_dacMode: - banshee->dacMode = val; - svga->dpms = !!(val & 0x0a); - svga_recalctimings(svga); - break; - case DAC_dacAddr: - banshee->dacAddr = val & 0x1ff; - break; - case DAC_dacData: - svga->pallook[banshee->dacAddr] = val & 0xffffff; - svga->fullchange = changeframecount; - break; + cycles -= svga->monitor->mon_video_timing_read_l; - case Video_vidProcCfg: - banshee->vidProcCfg = val; -// banshee_log("vidProcCfg=%08x\n", val); - banshee->overlay_pix_fmt = (val & VIDPROCCFG_OVERLAY_PIX_FORMAT_MASK) >> VIDPROCCFG_OVERLAY_PIX_FORMAT_SHIFT; - svga->hwcursor.ena = val & VIDPROCCFG_HWCURSOR_ENA; - svga->fullchange = changeframecount; - svga_recalctimings(svga); - break; +#if 0 + banshee_log("read_linear: addr=%08x val=%02x\n", addr, svga->vram[addr & svga->vram_mask]); +#endif - case Video_maxRgbDelta: - banshee->voodoo->scrfilterThreshold = val; - if (val > 0x00) - banshee->voodoo->scrfilterEnabled = 1; - else - banshee->voodoo->scrfilterEnabled = 0; - voodoo_threshold_check(banshee->voodoo); - banshee_log("Banshee Filter: %06x\n", val); - break; - - case Video_hwCurPatAddr: - banshee->hwCurPatAddr = val; - svga->hwcursor.addr = (val & 0xfffff0) + (svga->hwcursor.yoff * 16); - break; - case Video_hwCurLoc: - banshee->hwCurLoc = val; - svga->hwcursor.x = (val & 0x7ff) - 64; - svga->hwcursor.y = ((val >> 16) & 0x7ff) - 64; - if (svga->hwcursor.y < 0) - { - svga->hwcursor.yoff = -svga->hwcursor.y; - svga->hwcursor.y = 0; - } - else - svga->hwcursor.yoff = 0; - svga->hwcursor.addr = (banshee->hwCurPatAddr & 0xfffff0) + (svga->hwcursor.yoff * 16); - svga->hwcursor.xsize = 64; - svga->hwcursor.ysize = 64; -// banshee_log("hwCurLoc %08x %i\n", val, svga->hwcursor.y); - break; - case Video_hwCurC0: - banshee->hwCurC0 = val; - break; - case Video_hwCurC1: - banshee->hwCurC1 = val; - break; - - case Video_vidSerialParallelPort: - banshee->vidSerialParallelPort = val; -// banshee_log("vidSerialParallelPort: write %08x %08x %04x(%08x):%08x\n", val, val & (VIDSERIAL_DDC_DCK_W | VIDSERIAL_DDC_DDA_W), CS,cs,cpu_state.pc); - i2c_gpio_set(banshee->i2c_ddc, !!(val & VIDSERIAL_DDC_DCK_W), !!(val & VIDSERIAL_DDC_DDA_W)); - i2c_gpio_set(banshee->i2c, !!(val & VIDSERIAL_I2C_SCK_W), !!(val & VIDSERIAL_I2C_SDA_W)); - break; - - case Video_vidScreenSize: - banshee->vidScreenSize = val; - voodoo->h_disp = (val & 0xfff) + 1; - voodoo->v_disp = (val >> 12) & 0xfff; - break; - case Video_vidOverlayStartCoords: - voodoo->overlay.vidOverlayStartCoords = val; - voodoo->overlay.start_x = val & OVERLAY_START_X_MASK; - voodoo->overlay.start_y = (val & OVERLAY_START_Y_MASK) >> OVERLAY_START_Y_SHIFT; - voodoo->overlay.size_x = voodoo->overlay.end_x - voodoo->overlay.start_x; - voodoo->overlay.size_y = voodoo->overlay.end_y - voodoo->overlay.start_y; - svga_recalctimings(svga); - break; - case Video_vidOverlayEndScreenCoords: - voodoo->overlay.vidOverlayEndScreenCoords = val; - voodoo->overlay.end_x = val & OVERLAY_END_X_MASK; - voodoo->overlay.end_y = (val & OVERLAY_END_Y_MASK) >> OVERLAY_END_Y_SHIFT; - voodoo->overlay.size_x = (voodoo->overlay.end_x - voodoo->overlay.start_x) + 1; - voodoo->overlay.size_y = (voodoo->overlay.end_y - voodoo->overlay.start_y) + 1; - svga_recalctimings(svga); - break; - case Video_vidOverlayDudx: - voodoo->overlay.vidOverlayDudx = val & VID_DUDX_MASK; -// banshee_log("vidOverlayDudx=%08x\n", val); - break; - case Video_vidOverlayDudxOffsetSrcWidth: - voodoo->overlay.vidOverlayDudxOffsetSrcWidth = val; - voodoo->overlay.overlay_bytes = (val & OVERLAY_SRC_WIDTH_MASK) >> OVERLAY_SRC_WIDTH_SHIFT; -// banshee_log("vidOverlayDudxOffsetSrcWidth=%08x\n", val); - break; - case Video_vidOverlayDvdy: - voodoo->overlay.vidOverlayDvdy = val & VID_DVDY_MASK; -// banshee_log("vidOverlayDvdy=%08x\n", val); - break; - case Video_vidOverlayDvdyOffset: - voodoo->overlay.vidOverlayDvdyOffset = val; - break; - - - case Video_vidDesktopStartAddr: - banshee->vidDesktopStartAddr = val & 0xffffff; -// banshee_log("vidDesktopStartAddr=%08x\n", val); - svga->fullchange = changeframecount; - svga_recalctimings(svga); - break; - case Video_vidDesktopOverlayStride: - banshee->vidDesktopOverlayStride = val; -// banshee_log("vidDesktopOverlayStride=%08x\n", val); - svga->fullchange = changeframecount; - svga_recalctimings(svga); - break; -// default: -// fatal("bad banshee_ext_outl: addr=%04x val=%08x\n", addr, val); - } + return *(uint32_t *) &svga->vram[addr & svga->vram_mask]; } -static uint8_t banshee_ext_in(uint16_t addr, void *p) +static void +banshee_write_linear(uint32_t addr, uint8_t val, void *priv) { - banshee_t *banshee = (banshee_t *)p; -// svga_t *svga = &banshee->svga; - uint8_t ret = 0xff; - - switch (addr & 0xff) - { - case Init_status: case Init_status+1: case Init_status+2: case Init_status+3: - ret = (banshee_status(banshee) >> ((addr & 3) * 8)) & 0xff; -// banshee_log("Read status reg! %04x(%08x):%08x\n", CS, cs, cpu_state.pc); - break; + banshee_t *banshee = (banshee_t *) priv; + const voodoo_t *voodoo = banshee->voodoo; + svga_t *svga = &banshee->svga; - case 0xb0: case 0xb1: case 0xb2: case 0xb3: - case 0xb4: case 0xb5: case 0xb6: case 0xb7: - case 0xb8: case 0xb9: case 0xba: case 0xbb: - case 0xbc: case 0xbd: case 0xbe: case 0xbf: - case 0xc0: case 0xc1: case 0xc2: case 0xc3: - case 0xc4: case 0xc5: case 0xc6: case 0xc7: - case 0xc8: case 0xc9: case 0xca: case 0xcb: - case 0xcc: case 0xcd: case 0xce: case 0xcf: - case 0xd0: case 0xd1: case 0xd2: case 0xd3: - case 0xd4: case 0xd5: case 0xd6: case 0xd7: - case 0xd8: case 0xd9: case 0xda: case 0xdb: - case 0xdc: case 0xdd: case 0xde: case 0xdf: - ret = banshee_in((addr & 0xff)+0x300, p); - break; + cycles -= voodoo->write_time; - default: - banshee_log("bad banshee_ext_in: addr=%04x\n", addr); - break; - } +#if 0 + banshee_log("write_linear: addr=%08x val=%02x\n", addr, val); +#endif + addr &= svga->decode_mask; + if (addr >= voodoo->tile_base) { + int x; + int y; -// banshee_log("banshee_ext_in: addr=%04x val=%02x\n", addr, ret); - - return ret; + addr -= voodoo->tile_base; + x = addr & (voodoo->tile_stride - 1); + y = addr >> voodoo->tile_stride_shift; + + addr = voodoo->tile_base + (x & 127) + ((x >> 7) * 128 * 32) + ((y & 31) * 128) + (y >> 5) * voodoo->tile_x_real; +#if 0 + banshee_log(" Tile b %08x->%08x %i %i\n", old_addr, addr, x, y); +#endif + } + if (addr >= svga->vram_max) + return; + + cycles -= svga->monitor->mon_video_timing_write_b; + + svga->changedvram[addr >> 12] = changeframecount; + svga->vram[addr & svga->vram_mask] = val; } -static uint32_t banshee_status(banshee_t *banshee) +static void +banshee_write_linear_w(uint32_t addr, uint16_t val, void *priv) { - voodoo_t *voodoo = banshee->voodoo; - svga_t *svga = &banshee->svga; - int fifo_entries = FIFO_ENTRIES; - int swap_count = voodoo->swap_count; - int written = voodoo->cmd_written + voodoo->cmd_written_fifo; - int busy = (written - voodoo->cmd_read) || (voodoo->cmdfifo_depth_rd != voodoo->cmdfifo_depth_wr) || - voodoo->render_voodoo_busy[0] || voodoo->render_voodoo_busy[1] || - voodoo->render_voodoo_busy[2] || voodoo->render_voodoo_busy[3] || - voodoo->voodoo_busy; - uint32_t ret; + banshee_t *banshee = (banshee_t *) priv; + const voodoo_t *voodoo = banshee->voodoo; + svga_t *svga = &banshee->svga; - ret = 0; - if (fifo_entries < 0x20) - ret |= 0x1f - fifo_entries; - else - ret |= 0x1f; - if (fifo_entries) - ret |= 0x20; - if (swap_count < 7) - ret |= (swap_count << 28); - else - ret |= (7 << 28); - if (!(svga->cgastat & 8)) - ret |= 0x40; + if (addr & 1) { + banshee_write_linear(addr, val, priv); + banshee_write_linear(addr + 1, val >> 8, priv); + return; + } - if (busy) - ret |= 0x780; /*Busy*/ + cycles -= voodoo->write_time; +#if 0 + banshee_log("write_linear: addr=%08x val=%02x\n", addr, val); +#endif + addr &= svga->decode_mask; + if (addr >= voodoo->tile_base) { + int x; + int y; - if (voodoo->cmdfifo_depth_rd != voodoo->cmdfifo_depth_wr) - ret |= (1 << 11); + addr -= voodoo->tile_base; + x = addr & (voodoo->tile_stride - 1); + y = addr >> voodoo->tile_stride_shift; - if (!voodoo->voodoo_busy) + addr = voodoo->tile_base + (x & 127) + ((x >> 7) * 128 * 32) + ((y & 31) * 128) + (y >> 5) * voodoo->tile_x_real; +#if 0 + banshee_log(" Tile b %08x->%08x %i %i\n", old_addr, addr, x, y); +#endif + } + if (addr >= svga->vram_max) + return; + + cycles -= svga->monitor->mon_video_timing_write_w; + + svga->changedvram[addr >> 12] = changeframecount; + *(uint16_t *) &svga->vram[addr & svga->vram_mask] = val; +} + +static void +banshee_write_linear_l(uint32_t addr, uint32_t val, void *priv) +{ + banshee_t *banshee = (banshee_t *) priv; + voodoo_t *voodoo = banshee->voodoo; + svga_t *svga = &banshee->svga; + int timing; + + if (addr & 3) { + banshee_write_linear_w(addr, val, priv); + banshee_write_linear_w(addr + 2, val >> 16, priv); + return; + } + + if (addr == voodoo->last_write_addr + 4) + timing = voodoo->burst_time; + else + timing = voodoo->write_time; + cycles -= timing; + voodoo->last_write_addr = addr; + +#if 0 + if (val) + banshee_log("write_linear_l: addr=%08x val=%08x %08x\n", addr, val, voodoo->tile_base); +#endif + addr &= svga->decode_mask; + if (addr >= voodoo->tile_base) { + int x; + int y; + + addr -= voodoo->tile_base; + x = addr & (voodoo->tile_stride - 1); + y = addr >> voodoo->tile_stride_shift; + + addr = voodoo->tile_base + (x & 127) + ((x >> 7) * 128 * 32) + ((y & 31) * 128) + (y >> 5) * voodoo->tile_x_real; +#if 0 + banshee_log(" Tile %08x->%08x->%08x->%08x %i %i tile_x=%i\n", old_addr, addr_off, addr2, addr, x, y, voodoo->tile_x_real); +#endif + } + + if (addr >= svga->vram_max) + return; + + cycles -= svga->monitor->mon_video_timing_write_l; + + svga->changedvram[addr >> 12] = changeframecount; + *(uint32_t *) &svga->vram[addr & svga->vram_mask] = val; + if (voodoo->cmdfifo_enabled && addr >= voodoo->cmdfifo_base && addr < voodoo->cmdfifo_end) { +#if 0 + banshee_log("CMDFIFO write %08x %08x old amin=%08x amax=%08x hlcnt=%i depth_wr=%i rp=%08x\n", addr, val, voodoo->cmdfifo_amin, voodoo->cmdfifo_amax, voodoo->cmdfifo_holecount, voodoo->cmdfifo_depth_wr, voodoo->cmdfifo_rp); +#endif + if (addr == voodoo->cmdfifo_base && !voodoo->cmdfifo_holecount) { +#if 0 + if (voodoo->cmdfifo_holecount) + fatal("CMDFIFO reset pointers while outstanding holes\n"); +#endif + /*Reset pointers*/ + voodoo->cmdfifo_amin = voodoo->cmdfifo_base; + voodoo->cmdfifo_amax = voodoo->cmdfifo_base; + voodoo->cmdfifo_depth_wr++; + voodoo_wake_fifo_thread(voodoo); + } else if (voodoo->cmdfifo_holecount) { +#if 0 + if ((addr <= voodoo->cmdfifo_amin && voodoo->cmdfifo_amin != -4) || addr >= voodoo->cmdfifo_amax) + fatal("CMDFIFO holecount write outside of amin/amax - amin=%08x amax=%08x holecount=%i\n", voodoo->cmdfifo_amin, voodoo->cmdfifo_amax, voodoo->cmdfifo_holecount); + banshee_log("holecount %i\n", voodoo->cmdfifo_holecount); +#endif + voodoo->cmdfifo_holecount--; + if (!voodoo->cmdfifo_holecount) { + /*Filled in holes, resume normal operation*/ + voodoo->cmdfifo_depth_wr += ((voodoo->cmdfifo_amax - voodoo->cmdfifo_amin) >> 2); + voodoo->cmdfifo_amin = voodoo->cmdfifo_amax; voodoo_wake_fifo_thread(voodoo); - -// banshee_log("banshee_status: busy %i %i (%i %i) %i %i %i %04x(%08x):%08x %08x\n", busy, written, voodoo->cmd_written, voodoo->cmd_written_fifo, voodoo->cmd_read, voodoo->cmdfifo_depth_rd, voodoo->cmdfifo_depth_wr, CS,cs,cpu_state.pc, ret); - - return ret; +#if 0 + banshee_log("hole filled! amin=%08x amax=%08x added %i words\n", voodoo->cmdfifo_amin, voodoo->cmdfifo_amax, words_to_add); +#endif + } + } else if (addr == voodoo->cmdfifo_amax + 4) { + /*In-order write*/ + voodoo->cmdfifo_amin = addr; + voodoo->cmdfifo_amax = addr; + voodoo->cmdfifo_depth_wr++; + voodoo_wake_fifo_thread(voodoo); + } else { + /*Out-of-order write*/ + if (addr < voodoo->cmdfifo_amin) { + /*Reset back to start. Note that write is still out of order!*/ + voodoo->cmdfifo_amin = voodoo->cmdfifo_base - 4; + } +#if 0 + else if (addr < voodoo->cmdfifo_amax) + fatal("Out-of-order write really out of order\n"); +#endif + voodoo->cmdfifo_amax = addr; + voodoo->cmdfifo_holecount = ((voodoo->cmdfifo_amax - voodoo->cmdfifo_amin) >> 2) - 1; +#if 0 + banshee_log("CMDFIFO out of order: amin=%08x amax=%08x holecount=%i\n", voodoo->cmdfifo_amin, voodoo->cmdfifo_amax, voodoo->cmdfifo_holecount); +#endif + } + } } -static uint32_t banshee_ext_inl(uint16_t addr, void *p) +void +banshee_hwcursor_draw(svga_t *svga, int displine) { - banshee_t *banshee = (banshee_t *)p; - voodoo_t *voodoo = banshee->voodoo; - svga_t *svga = &banshee->svga; - uint32_t ret = 0xffffffff; + const banshee_t *banshee = (banshee_t *) svga->priv; + int x; + int x_off; + int xx; + uint32_t col0 = banshee->hwCurC0; + uint32_t col1 = banshee->hwCurC1; + uint8_t plane0[8]; + uint8_t plane1[8]; - cycles -= voodoo->read_time; - - switch (addr & 0xff) - { - case Init_status: - ret = banshee_status(banshee); -// banshee_log("Read status reg! %04x(%08x):%08x\n", CS, cs, cpu_state.pc); - break; - case Init_pciInit0: - ret = banshee->pciInit0; - break; - case Init_lfbMemoryConfig: - ret = banshee->lfbMemoryConfig; - break; - - case Init_miscInit0: - ret = banshee->miscInit0; - break; - case Init_miscInit1: - ret = banshee->miscInit1; - break; - case Init_dramInit0: - ret = banshee->dramInit0; - break; - case Init_dramInit1: - ret = banshee->dramInit1; - break; - case Init_agpInit0: - ret = banshee->agpInit0; - break; + for (uint8_t c = 0; c < 8; c++) + plane0[c] = svga->vram[svga->hwcursor_latch.addr + c]; + for (uint8_t c = 0; c < 8; c++) + plane1[c] = svga->vram[svga->hwcursor_latch.addr + c + 8]; + svga->hwcursor_latch.addr += 16; - case Init_vgaInit0: - ret = banshee->vgaInit0; - break; - case Init_vgaInit1: - ret = banshee->vgaInit1; - break; + x_off = svga->hwcursor_latch.x; - case Init_2dCommand: - ret = banshee->command_2d; - break; - case Init_2dSrcBaseAddr: - ret = banshee->srcBaseAddr_2d; - break; - case Init_strapInfo: - ret = 0x00000040; /*8 MB SGRAM, PCI, IRQ enabled, 32kB BIOS*/ - break; + if (banshee->vidProcCfg & VIDPROCCFG_CURSOR_MODE) { + /*X11 mode*/ + for (x = 0; x < 64; x += 8) { + if (x_off > -8) { + for (xx = 0; xx < 8; xx++) { + if (plane0[x >> 3] & (1 << 7)) + (svga->monitor->target_buffer->line[displine])[x_off + xx + svga->x_add] = (plane1[x >> 3] & (1 << 7)) ? col1 : col0; - case PLL_pllCtrl0: - ret = banshee->pllCtrl0; - break; - case PLL_pllCtrl1: - ret = banshee->pllCtrl1; - break; - case PLL_pllCtrl2: - ret = banshee->pllCtrl2; - break; - - case DAC_dacMode: - ret = banshee->dacMode; - break; - case DAC_dacAddr: - ret = banshee->dacAddr; - break; - case DAC_dacData: - ret = svga->pallook[banshee->dacAddr]; - break; - - case Video_vidProcCfg: - ret = banshee->vidProcCfg; - break; - - case Video_hwCurPatAddr: - ret = banshee->hwCurPatAddr; - break; - case Video_hwCurLoc: - ret = banshee->hwCurLoc; - break; - case Video_hwCurC0: - ret = banshee->hwCurC0; - break; - case Video_hwCurC1: - ret = banshee->hwCurC1; - break; - - case Video_vidSerialParallelPort: - ret = banshee->vidSerialParallelPort & ~(VIDSERIAL_DDC_DCK_R | VIDSERIAL_DDC_DDA_R | VIDSERIAL_I2C_SCK_R | VIDSERIAL_I2C_SDA_R); - if (banshee->vidSerialParallelPort & VIDSERIAL_DDC_EN) { - if (i2c_gpio_get_scl(banshee->i2c_ddc)) - ret |= VIDSERIAL_DDC_DCK_R; - if (i2c_gpio_get_sda(banshee->i2c_ddc)) - ret |= VIDSERIAL_DDC_DDA_R; + plane0[x >> 3] <<= 1; + plane1[x >> 3] <<= 1; } - if (banshee->vidSerialParallelPort & VIDSERIAL_I2C_EN) { - if (i2c_gpio_get_scl(banshee->i2c)) - ret |= VIDSERIAL_I2C_SCK_R; - if (i2c_gpio_get_sda(banshee->i2c)) - ret |= VIDSERIAL_I2C_SDA_R; + } + + x_off += 8; + } + } else { + /*Windows mode*/ + for (x = 0; x < 64; x += 8) { + if (x_off > -8) { + for (xx = 0; xx < 8; xx++) { + if (!(plane0[x >> 3] & (1 << 7))) + (svga->monitor->target_buffer->line[displine])[x_off + xx + svga->x_add] = (plane1[x >> 3] & (1 << 7)) ? col1 : col0; + else if (plane1[x >> 3] & (1 << 7)) + (svga->monitor->target_buffer->line[displine])[x_off + xx + svga->x_add] ^= 0xffffff; + + plane0[x >> 3] <<= 1; + plane1[x >> 3] <<= 1; } -// banshee_log("vidSerialParallelPort: read %08x %08x %04x(%08x):%08x\n", ret, ret & (VIDSERIAL_DDC_DCK_R | VIDSERIAL_DDC_DDA_R), CS,cs,cpu_state.pc); - break; + } - case Video_vidScreenSize: - ret = banshee->vidScreenSize; - break; - case Video_vidOverlayStartCoords: - ret = voodoo->overlay.vidOverlayStartCoords; - break; - case Video_vidOverlayEndScreenCoords: - ret = voodoo->overlay.vidOverlayEndScreenCoords; - break; - case Video_vidOverlayDudx: - ret = voodoo->overlay.vidOverlayDudx; - break; - case Video_vidOverlayDudxOffsetSrcWidth: - ret = voodoo->overlay.vidOverlayDudxOffsetSrcWidth; - break; - case Video_vidOverlayDvdy: - ret = voodoo->overlay.vidOverlayDvdy; - break; - case Video_vidOverlayDvdyOffset: - ret = voodoo->overlay.vidOverlayDvdyOffset; - break; - - case Video_vidDesktopStartAddr: - ret = banshee->vidDesktopStartAddr; - break; - case Video_vidDesktopOverlayStride: - ret = banshee->vidDesktopOverlayStride; - break; - - default: -// fatal("bad banshee_ext_inl: addr=%04x\n", addr); - break; + x_off += 8; } - -// /*if (addr) */banshee_log("banshee_ext_inl: addr=%04x val=%08x\n", addr, ret); - - return ret; + } } - -static uint32_t banshee_reg_readl(uint32_t addr, void *p); - -static uint8_t banshee_reg_read(uint32_t addr, void *p) -{ -// banshee_log("banshee_reg_read: addr=%08x\n", addr); - return banshee_reg_readl(addr & ~3, p) >> (8*(addr & 3)); -} - -static uint16_t banshee_reg_readw(uint32_t addr, void *p) -{ -// banshee_log("banshee_reg_readw: addr=%08x\n", addr); - return banshee_reg_readl(addr & ~3, p) >> (8*(addr & 2)); -} - -static uint32_t banshee_cmd_read(banshee_t *banshee, uint32_t addr) -{ - voodoo_t *voodoo = banshee->voodoo; - uint32_t ret = 0xffffffff; - - switch (addr & 0x1fc) - { - case cmdBaseAddr0: - ret = voodoo->cmdfifo_base >> 12; -// banshee_log("Read cmdfifo_base %08x\n", ret); - break; - - case cmdRdPtrL0: - ret = voodoo->cmdfifo_rp; -// banshee_log("Read cmdfifo_rp %08x\n", ret); - break; - - case cmdFifoDepth0: - ret = voodoo->cmdfifo_depth_wr - voodoo->cmdfifo_depth_rd; -// banshee_log("Read cmdfifo_depth %08x\n", ret); - break; - - case 0x108: - break; - - default: - fatal("Unknown banshee_cmd_read %08x\n", addr); - } - - return ret; -} - -static uint32_t banshee_reg_readl(uint32_t addr, void *p) -{ - banshee_t *banshee = (banshee_t *)p; - voodoo_t *voodoo = banshee->voodoo; - uint32_t ret = 0xffffffff; - - cycles -= voodoo->read_time; - - switch (addr & 0x1f00000) - { - case 0x0000000: /*IO remap*/ - if (!(addr & 0x80000)) - ret = banshee_ext_inl(addr & 0xff, banshee); - else - ret = banshee_cmd_read(banshee, addr); - break; - - case 0x0100000: /*2D registers*/ - voodoo_flush(voodoo); - switch (addr & 0x1fc) - { - case SST_status: - ret = banshee_status(banshee); - break; - - case SST_intrCtrl: - ret = banshee->intrCtrl & 0x0030003f; - break; - - case 0x08: - ret = voodoo->banshee_blt.clip0Min; - break; - case 0x0c: - ret = voodoo->banshee_blt.clip0Max; - break; - case 0x10: - ret = voodoo->banshee_blt.dstBaseAddr; - break; - case 0x14: - ret = voodoo->banshee_blt.dstFormat; - break; - case 0x34: - ret = voodoo->banshee_blt.srcBaseAddr; - break; - case 0x38: - ret = voodoo->banshee_blt.commandExtra; - break; - case 0x5c: - ret = voodoo->banshee_blt.srcXY; - break; - case 0x60: - ret = voodoo->banshee_blt.colorBack; - break; - case 0x64: - ret = voodoo->banshee_blt.colorFore; - break; - case 0x68: - ret = voodoo->banshee_blt.dstSize; - break; - case 0x6c: - ret = voodoo->banshee_blt.dstXY; - break; - case 0x70: - ret = voodoo->banshee_blt.command; - break; - default: - banshee_log("banshee_reg_readl: addr=%08x\n", addr); - } - break; - - case 0x0200000: case 0x0300000: case 0x0400000: case 0x0500000: /*3D registers*/ - switch (addr & 0x3fc) - { - case SST_status: - ret = banshee_status(banshee); - break; - - case SST_intrCtrl: - ret = banshee->intrCtrl & 0x0030003f; - break; - - case SST_fbzColorPath: - voodoo_flush(voodoo); - ret = voodoo->params.fbzColorPath; - break; - case SST_fogMode: - voodoo_flush(voodoo); - ret = voodoo->params.fogMode; - break; - case SST_alphaMode: - voodoo_flush(voodoo); - ret = voodoo->params.alphaMode; - break; - case SST_fbzMode: - voodoo_flush(voodoo); - ret = voodoo->params.fbzMode; - break; - case SST_lfbMode: - voodoo_flush(voodoo); - ret = voodoo->lfbMode; - break; - case SST_clipLeftRight: - ret = voodoo->params.clipRight | (voodoo->params.clipLeft << 16); - break; - case SST_clipLowYHighY: - ret = voodoo->params.clipHighY | (voodoo->params.clipLowY << 16); - break; - - case SST_clipLeftRight1: - ret = voodoo->params.clipRight1 | (voodoo->params.clipLeft1 << 16); - break; - case SST_clipTopBottom1: - ret = voodoo->params.clipHighY1 | (voodoo->params.clipLowY1 << 16); - break; - - case SST_stipple: - voodoo_flush(voodoo); - ret = voodoo->params.stipple; - break; - case SST_color0: - voodoo_flush(voodoo); - ret = voodoo->params.color0; - break; - case SST_color1: - voodoo_flush(voodoo); - ret = voodoo->params.color1; - break; - - case SST_fbiPixelsIn: - ret = voodoo->fbiPixelsIn & 0xffffff; - break; - case SST_fbiChromaFail: - ret = voodoo->fbiChromaFail & 0xffffff; - break; - case SST_fbiZFuncFail: - ret = voodoo->fbiZFuncFail & 0xffffff; - break; - case SST_fbiAFuncFail: - ret = voodoo->fbiAFuncFail & 0xffffff; - break; - case SST_fbiPixelsOut: - ret = voodoo->fbiPixelsOut & 0xffffff; - break; - - default: - banshee_log("banshee_reg_readl: 3D addr=%08x\n", addr); - break; - } - break; - } - -// /*if (addr != 0xe0000000) */banshee_log("banshee_reg_readl: addr=%08x ret=%08x %04x(%08x):%08x\n", addr, ret, CS,cs,cpu_state.pc); - - return ret; -} - -static void banshee_reg_write(uint32_t addr, uint8_t val, void *p) -{ -// banshee_log("banshee_reg_writeb: addr=%08x val=%02x\n", addr, val); -} - -static void banshee_reg_writew(uint32_t addr, uint16_t val, void *p) -{ - banshee_t *banshee = (banshee_t *)p; - voodoo_t *voodoo = banshee->voodoo; - - cycles -= voodoo->write_time; - -// banshee_log("banshee_reg_writew: addr=%08x val=%04x\n", addr, val); - switch (addr & 0x1f00000) - { - case 0x1000000: case 0x1100000: case 0x1200000: case 0x1300000: /*3D LFB*/ - case 0x1400000: case 0x1500000: case 0x1600000: case 0x1700000: - case 0x1800000: case 0x1900000: case 0x1a00000: case 0x1b00000: - case 0x1c00000: case 0x1d00000: case 0x1e00000: case 0x1f00000: - voodoo_queue_command(voodoo, (addr & 0xffffff) | FIFO_WRITEW_FB, val); - break; - } -} - -static void banshee_cmd_write(banshee_t *banshee, uint32_t addr, uint32_t val) -{ - voodoo_t *voodoo = banshee->voodoo; -// banshee_log("banshee_cmd_write: addr=%03x val=%08x\n", addr & 0x1fc, val); - switch (addr & 0x1fc) - { - case cmdBaseAddr0: - voodoo->cmdfifo_base = (val & 0xfff) << 12; - voodoo->cmdfifo_end = voodoo->cmdfifo_base + (((voodoo->cmdfifo_size & 0xff) + 1) << 12); -// banshee_log("cmdfifo_base=%08x cmdfifo_end=%08x %08x\n", voodoo->cmdfifo_base, voodoo->cmdfifo_end, val); - break; - - case cmdBaseSize0: - voodoo->cmdfifo_size = val; - voodoo->cmdfifo_end = voodoo->cmdfifo_base + (((voodoo->cmdfifo_size & 0xff) + 1) << 12); - voodoo->cmdfifo_enabled = val & 0x100; - if (!voodoo->cmdfifo_enabled) - voodoo->cmdfifo_in_sub = 0; /*Not sure exactly when this should be reset*/ -// banshee_log("cmdfifo_base=%08x cmdfifo_end=%08x\n", voodoo->cmdfifo_base, voodoo->cmdfifo_end); - break; - -// voodoo->cmdfifo_end = ((val >> 16) & 0x3ff) << 12; -// banshee_log("CMDFIFO base=%08x end=%08x\n", voodoo->cmdfifo_base, voodoo->cmdfifo_end); -// break; - - case cmdRdPtrL0: - voodoo->cmdfifo_rp = val; - break; - case cmdAMin0: - voodoo->cmdfifo_amin = val; - break; - case cmdAMax0: - voodoo->cmdfifo_amax = val; - break; - case cmdFifoDepth0: - voodoo->cmdfifo_depth_rd = 0; - voodoo->cmdfifo_depth_wr = val & 0xffff; - break; - - default: - banshee_log("Unknown banshee_cmd_write: addr=%08x val=%08x\n", addr, val); - break; - } - -/* cmdBaseSize0 = 0x24, - cmdBump0 = 0x28, - cmdRdPtrL0 = 0x2c, - cmdRdPtrH0 = 0x30, - cmdAMin0 = 0x34, - cmdAMax0 = 0x3c, - cmdFifoDepth0 = 0x44, - cmdHoleCnt0 = 0x48 - }*/ -} - -static void banshee_reg_writel(uint32_t addr, uint32_t val, void *p) -{ - banshee_t *banshee = (banshee_t *)p; - voodoo_t *voodoo = banshee->voodoo; - - if (addr == voodoo->last_write_addr+4) - cycles -= voodoo->burst_time; - else - cycles -= voodoo->write_time; - voodoo->last_write_addr = addr; - -// banshee_log("banshee_reg_writel: addr=%08x val=%08x\n", addr, val); - - switch (addr & 0x1f00000) - { - case 0x0000000: /*IO remap*/ - if (!(addr & 0x80000)) - banshee_ext_outl(addr & 0xff, val, banshee); - else - banshee_cmd_write(banshee, addr, val); -// banshee_log("CMD!!! write %08x %08x\n", addr, val); - break; - - case 0x0100000: /*2D registers*/ - if ((addr & 0x3fc) == SST_intrCtrl) { - banshee->intrCtrl = val & 0x0030003f; - } else { - voodoo_queue_command(voodoo, (addr & 0x1fc) | FIFO_WRITEL_2DREG, val); - } - break; - - case 0x0200000: case 0x0300000: case 0x0400000: case 0x0500000: /*3D registers*/ - switch (addr & 0x3fc) - { - case SST_intrCtrl: - banshee->intrCtrl = val & 0x0030003f; -// banshee_log("intrCtrl=%08x\n", val); - break; - - case SST_userIntrCMD: - fatal("userIntrCMD write %08x\n", val); - break; - - case SST_swapbufferCMD: - voodoo->cmd_written++; - voodoo_queue_command(voodoo, (addr & 0x3fc) | FIFO_WRITEL_REG, val); - if (!voodoo->voodoo_busy) - voodoo_wake_fifo_threads(voodoo->set, voodoo); -// banshee_log("SST_swapbufferCMD write: %i %i\n", voodoo->cmd_written, voodoo->cmd_written_fifo); - break; - case SST_triangleCMD: - voodoo->cmd_written++; - voodoo_queue_command(voodoo, (addr & 0x3fc) | FIFO_WRITEL_REG, val); - if (!voodoo->voodoo_busy) - voodoo_wake_fifo_threads(voodoo->set, voodoo); - break; - case SST_ftriangleCMD: - voodoo->cmd_written++; - voodoo_queue_command(voodoo, (addr & 0x3fc) | FIFO_WRITEL_REG, val); - if (!voodoo->voodoo_busy) - voodoo_wake_fifo_threads(voodoo->set, voodoo); - break; - case SST_fastfillCMD: - voodoo->cmd_written++; - voodoo_queue_command(voodoo, (addr & 0x3fc) | FIFO_WRITEL_REG, val); - if (!voodoo->voodoo_busy) - voodoo_wake_fifo_threads(voodoo->set, voodoo); - break; - case SST_nopCMD: - voodoo->cmd_written++; - voodoo_queue_command(voodoo, (addr & 0x3fc) | FIFO_WRITEL_REG, val); - if (!voodoo->voodoo_busy) - voodoo_wake_fifo_threads(voodoo->set, voodoo); - break; - - case SST_swapPending: - thread_wait_mutex(voodoo->swap_mutex); - voodoo->swap_count++; - thread_release_mutex(voodoo->swap_mutex); -// voodoo->cmd_written++; - break; - - default: - voodoo_queue_command(voodoo, (addr & 0x3ffffc) | FIFO_WRITEL_REG, val); - break; - } - break; - - case 0x0600000: case 0x0700000: /*Texture download*/ - voodoo->tex_count++; - voodoo_queue_command(voodoo, (addr & 0x1ffffc) | FIFO_WRITEL_TEX, val); - break; - - case 0x1000000: case 0x1100000: case 0x1200000: case 0x1300000: /*3D LFB*/ - case 0x1400000: case 0x1500000: case 0x1600000: case 0x1700000: - case 0x1800000: case 0x1900000: case 0x1a00000: case 0x1b00000: - case 0x1c00000: case 0x1d00000: case 0x1e00000: case 0x1f00000: - voodoo_queue_command(voodoo, (addr & 0xfffffc) | FIFO_WRITEL_FB, val); - break; - } -} - -static uint8_t banshee_read_linear(uint32_t addr, void *p) -{ - banshee_t *banshee = (banshee_t *)p; - voodoo_t *voodoo = banshee->voodoo; - svga_t *svga = &banshee->svga; - - cycles -= voodoo->read_time; - - addr &= svga->decode_mask; - if (addr >= voodoo->tile_base) - { - int x, y; - - addr -= voodoo->tile_base; - x = addr & (voodoo->tile_stride-1); - y = addr >> voodoo->tile_stride_shift; - - addr = voodoo->tile_base + (x & 127) + ((x >> 7) * 128*32) + ((y & 31) * 128) + (y >> 5)*voodoo->tile_x_real; -// banshee_log(" Tile rb %08x->%08x %i %i\n", old_addr, addr, x, y); - } - if (addr >= svga->vram_max) - return 0xff; - - cycles -= video_timing_read_b; - -// banshee_log("read_linear: addr=%08x val=%02x\n", addr, svga->vram[addr & svga->vram_mask]); - - return svga->vram[addr & svga->vram_mask]; -} - -static uint16_t banshee_read_linear_w(uint32_t addr, void *p) -{ - banshee_t *banshee = (banshee_t *)p; - voodoo_t *voodoo = banshee->voodoo; - svga_t *svga = &banshee->svga; - - if (addr & 1) - return banshee_read_linear(addr, p) | (banshee_read_linear(addr+1, p) << 8); - - cycles -= voodoo->read_time; - addr &= svga->decode_mask; - if (addr >= voodoo->tile_base) - { - int x, y; - - addr -= voodoo->tile_base; - x = addr & (voodoo->tile_stride-1); - y = addr >> voodoo->tile_stride_shift; - - addr = voodoo->tile_base + (x & 127) + ((x >> 7) * 128*32) + ((y & 31) * 128) + (y >> 5)*voodoo->tile_x_real; -// banshee_log(" Tile rb %08x->%08x %i %i\n", old_addr, addr, x, y); - } - if (addr >= svga->vram_max) - return 0xff; - - cycles -= video_timing_read_w; - -// banshee_log("read_linear: addr=%08x val=%02x\n", addr, svga->vram[addr & svga->vram_mask]); - - return *(uint16_t *)&svga->vram[addr & svga->vram_mask]; -} - -static uint32_t banshee_read_linear_l(uint32_t addr, void *p) -{ - banshee_t *banshee = (banshee_t *)p; - voodoo_t *voodoo = banshee->voodoo; - svga_t *svga = &banshee->svga; - - if (addr & 3) - return banshee_read_linear_w(addr, p) | (banshee_read_linear_w(addr+2, p) << 16); - - cycles -= voodoo->read_time; - - addr &= svga->decode_mask; - if (addr >= voodoo->tile_base) - { - int x, y; - - addr -= voodoo->tile_base; - x = addr & (voodoo->tile_stride-1); - y = addr >> voodoo->tile_stride_shift; - - addr = voodoo->tile_base + (x & 127) + ((x >> 7) * 128*32) + ((y & 31) * 128) + (y >> 5)*voodoo->tile_x_real; -// banshee_log(" Tile rb %08x->%08x %i %i\n", old_addr, addr, x, y); - } - if (addr >= svga->vram_max) - return 0xff; - - cycles -= video_timing_read_l; - -// banshee_log("read_linear: addr=%08x val=%02x\n", addr, svga->vram[addr & svga->vram_mask]); - - return *(uint32_t *)&svga->vram[addr & svga->vram_mask]; -} - -static void banshee_write_linear(uint32_t addr, uint8_t val, void *p) -{ - banshee_t *banshee = (banshee_t *)p; - voodoo_t *voodoo = banshee->voodoo; - svga_t *svga = &banshee->svga; - - cycles -= voodoo->write_time; - -// banshee_log("write_linear: addr=%08x val=%02x\n", addr, val); - addr &= svga->decode_mask; - if (addr >= voodoo->tile_base) - { - int x, y; - - addr -= voodoo->tile_base; - x = addr & (voodoo->tile_stride-1); - y = addr >> voodoo->tile_stride_shift; - - addr = voodoo->tile_base + (x & 127) + ((x >> 7) * 128*32) + ((y & 31) * 128) + (y >> 5)*voodoo->tile_x_real; -// banshee_log(" Tile b %08x->%08x %i %i\n", old_addr, addr, x, y); - } - if (addr >= svga->vram_max) - return; - - cycles -= video_timing_write_b; - - svga->changedvram[addr >> 12] = changeframecount; - svga->vram[addr & svga->vram_mask] = val; -} - -static void banshee_write_linear_w(uint32_t addr, uint16_t val, void *p) -{ - banshee_t *banshee = (banshee_t *)p; - voodoo_t *voodoo = banshee->voodoo; - svga_t *svga = &banshee->svga; - - if (addr & 1) - { - banshee_write_linear(addr, val, p); - banshee_write_linear(addr + 1, val >> 8, p); - return; - } - - cycles -= voodoo->write_time; -// banshee_log("write_linear: addr=%08x val=%02x\n", addr, val); - addr &= svga->decode_mask; - if (addr >= voodoo->tile_base) - { - int x, y; - - addr -= voodoo->tile_base; - x = addr & (voodoo->tile_stride-1); - y = addr >> voodoo->tile_stride_shift; - - addr = voodoo->tile_base + (x & 127) + ((x >> 7) * 128*32) + ((y & 31) * 128) + (y >> 5)*voodoo->tile_x_real; -// banshee_log(" Tile b %08x->%08x %i %i\n", old_addr, addr, x, y); - } - if (addr >= svga->vram_max) - return; - - cycles -= video_timing_write_w; - - svga->changedvram[addr >> 12] = changeframecount; - *(uint16_t *)&svga->vram[addr & svga->vram_mask] = val; -} - -static void banshee_write_linear_l(uint32_t addr, uint32_t val, void *p) -{ - banshee_t *banshee = (banshee_t *)p; - voodoo_t *voodoo = banshee->voodoo; - svga_t *svga = &banshee->svga; - int timing; - - if (addr & 3) - { - banshee_write_linear_w(addr, val, p); - banshee_write_linear_w(addr + 2, val >> 16, p); - return; - } - - if (addr == voodoo->last_write_addr+4) - timing = voodoo->burst_time; - else - timing = voodoo->write_time; - cycles -= timing; - voodoo->last_write_addr = addr; - -// /*if (val) */banshee_log("write_linear_l: addr=%08x val=%08x %08x\n", addr, val, voodoo->tile_base); - addr &= svga->decode_mask; - if (addr >= voodoo->tile_base) - { - int x, y; - - addr -= voodoo->tile_base; - x = addr & (voodoo->tile_stride-1); - y = addr >> voodoo->tile_stride_shift; - - addr = voodoo->tile_base + (x & 127) + ((x >> 7) * 128*32) + ((y & 31) * 128) + (y >> 5)*voodoo->tile_x_real; -// banshee_log(" Tile %08x->%08x->%08x->%08x %i %i tile_x=%i\n", old_addr, addr_off, addr2, addr, x, y, voodoo->tile_x_real); - } - - if (addr >= svga->vram_max) - return; - - cycles -= video_timing_write_l; - - svga->changedvram[addr >> 12] = changeframecount; - *(uint32_t *)&svga->vram[addr & svga->vram_mask] = val; - if (voodoo->cmdfifo_enabled && addr >= voodoo->cmdfifo_base && addr < voodoo->cmdfifo_end) - { -// banshee_log("CMDFIFO write %08x %08x old amin=%08x amax=%08x hlcnt=%i depth_wr=%i rp=%08x\n", addr, val, voodoo->cmdfifo_amin, voodoo->cmdfifo_amax, voodoo->cmdfifo_holecount, voodoo->cmdfifo_depth_wr, voodoo->cmdfifo_rp); - if (addr == voodoo->cmdfifo_base && !voodoo->cmdfifo_holecount) - { -// if (voodoo->cmdfifo_holecount) -// fatal("CMDFIFO reset pointers while outstanding holes\n"); - /*Reset pointers*/ - voodoo->cmdfifo_amin = voodoo->cmdfifo_base; - voodoo->cmdfifo_amax = voodoo->cmdfifo_base; - voodoo->cmdfifo_depth_wr++; - voodoo_wake_fifo_thread(voodoo); - } - else if (voodoo->cmdfifo_holecount) - { -// if ((addr <= voodoo->cmdfifo_amin && voodoo->cmdfifo_amin != -4) || addr >= voodoo->cmdfifo_amax) -// fatal("CMDFIFO holecount write outside of amin/amax - amin=%08x amax=%08x holecount=%i\n", voodoo->cmdfifo_amin, voodoo->cmdfifo_amax, voodoo->cmdfifo_holecount); -// banshee_log("holecount %i\n", voodoo->cmdfifo_holecount); - voodoo->cmdfifo_holecount--; - if (!voodoo->cmdfifo_holecount) - { - /*Filled in holes, resume normal operation*/ - voodoo->cmdfifo_depth_wr += ((voodoo->cmdfifo_amax - voodoo->cmdfifo_amin) >> 2); - voodoo->cmdfifo_amin = voodoo->cmdfifo_amax; - voodoo_wake_fifo_thread(voodoo); -// banshee_log("hole filled! amin=%08x amax=%08x added %i words\n", voodoo->cmdfifo_amin, voodoo->cmdfifo_amax, words_to_add); - } - } - else if (addr == voodoo->cmdfifo_amax+4) - { - /*In-order write*/ - voodoo->cmdfifo_amin = addr; - voodoo->cmdfifo_amax = addr; - voodoo->cmdfifo_depth_wr++; - voodoo_wake_fifo_thread(voodoo); - } - else - { - /*Out-of-order write*/ - if (addr < voodoo->cmdfifo_amin) - { - /*Reset back to start. Note that write is still out of order!*/ - voodoo->cmdfifo_amin = voodoo->cmdfifo_base-4; - - } -// else if (addr < voodoo->cmdfifo_amax) -// fatal("Out-of-order write really out of order\n"); - voodoo->cmdfifo_amax = addr; - voodoo->cmdfifo_holecount = ((voodoo->cmdfifo_amax - voodoo->cmdfifo_amin) >> 2) - 1; -// banshee_log("CMDFIFO out of order: amin=%08x amax=%08x holecount=%i\n", voodoo->cmdfifo_amin, voodoo->cmdfifo_amax, voodoo->cmdfifo_holecount); - } - } -} - -void banshee_hwcursor_draw(svga_t *svga, int displine) -{ - banshee_t *banshee = (banshee_t *)svga->p; - int x, c; - int x_off; - int xx; - uint32_t col0 = banshee->hwCurC0; - uint32_t col1 = banshee->hwCurC1; - uint8_t plane0[8], plane1[8]; - - for (c = 0; c < 8; c++) - plane0[c] = svga->vram[svga->hwcursor_latch.addr + c]; - for (c = 0; c < 8; c++) - plane1[c] = svga->vram[svga->hwcursor_latch.addr + c + 8]; - svga->hwcursor_latch.addr += 16; - - x_off = svga->hwcursor_latch.x; - - if (banshee->vidProcCfg & VIDPROCCFG_CURSOR_MODE) - { - /*X11 mode*/ - for (x = 0; x < 64; x += 8) - { - if (x_off > -8) - { - for (xx = 0; xx < 8; xx++) - { - if (plane0[x >> 3] & (1 << 7)) - ((uint32_t *)buffer32->line[displine])[x_off + xx + svga->x_add] = (plane1[x >> 3] & (1 << 7)) ? col1 : col0; - - plane0[x >> 3] <<= 1; - plane1[x >> 3] <<= 1; - } - } - - x_off += 8; - } - } - else - { - /*Windows mode*/ - for (x = 0; x < 64; x += 8) - { - if (x_off > -8) - { - for (xx = 0; xx < 8; xx++) - { - if (!(plane0[x >> 3] & (1 << 7))) - ((uint32_t *)buffer32->line[displine])[x_off + xx + svga->x_add] = (plane1[x >> 3] & (1 << 7)) ? col1 : col0; - else if (plane1[x >> 3] & (1 << 7)) - ((uint32_t *)buffer32->line[displine])[x_off + xx + svga->x_add] ^= 0xffffff; - - plane0[x >> 3] <<= 1; - plane1[x >> 3] <<= 1; - } - } - - x_off += 8; - } - } -} - -#define CLAMP(x) do \ - { \ - if ((x) & ~0xff) \ - x = ((x) < 0) ? 0 : 0xff; \ - } \ - while (0) - -#define DECODE_RGB565(buf) \ - do \ - { \ - int c; \ - int wp = 0; \ - \ - for (c = 0; c < voodoo->overlay.overlay_bytes; c += 2) \ - { \ - uint16_t data = *(uint16_t *)src; \ - int r = data & 0x1f; \ - int g = (data >> 5) & 0x3f; \ - int b = data >> 11; \ - \ - if (banshee->vidProcCfg & VIDPROCCFG_OVERLAY_CLUT_BYPASS) \ - buf[wp++] = (r << 3) | (g << 10) | (b << 19); \ - else \ - buf[wp++] = (clut[r << 3] & 0x0000ff) | \ - (clut[g << 2] & 0x00ff00) | \ - (clut[b << 3] & 0xff0000); \ - src += 2; \ - } \ - } while (0) - -#define DECODE_RGB565_TILED(buf) \ - do \ - { \ - int c; \ - int wp = 0; \ - uint32_t base_addr = (buf == banshee->overlay_buffer[1]) ? src_addr2 : src_addr; \ - \ - for (c = 0; c < voodoo->overlay.overlay_bytes; c += 2) \ - { \ - uint16_t data = *(uint16_t *)&svga->vram[(base_addr + (c & 127) + (c >> 7)*128*32) & svga->vram_mask]; \ - int r = data & 0x1f; \ - int g = (data >> 5) & 0x3f; \ - int b = data >> 11; \ - \ - if (banshee->vidProcCfg & VIDPROCCFG_OVERLAY_CLUT_BYPASS) \ - buf[wp++] = (r << 3) | (g << 10) | (b << 19); \ - else \ - buf[wp++] = (clut[r << 3] & 0x0000ff) | \ - (clut[g << 2] & 0x00ff00) | \ - (clut[b << 3] & 0xff0000); \ - } \ - } while (0) - -#define DECODE_YUYV422(buf) \ - do \ - { \ - int c; \ - int wp = 0; \ - \ - for (c = 0; c < voodoo->overlay.overlay_bytes; c += 4) \ - { \ - uint8_t y1, y2; \ - int8_t Cr, Cb; \ - int dR, dG, dB; \ - int r, g, b; \ - \ - y1 = src[0]; \ - Cr = src[1] - 0x80; \ - y2 = src[2]; \ - Cb = src[3] - 0x80; \ - src += 4; \ - \ - dR = (359*Cr) >> 8; \ - dG = (88*Cb + 183*Cr) >> 8; \ - dB = (453*Cb) >> 8; \ - \ - r = y1 + dR; \ - CLAMP(r); \ - g = y1 - dG; \ - CLAMP(g); \ - b = y1 + dB; \ - CLAMP(b); \ - buf[wp++] = r | (g << 8) | (b << 16); \ - \ - r = y2 + dR; \ - CLAMP(r); \ - g = y2 - dG; \ - CLAMP(g); \ - b = y2 + dB; \ - CLAMP(b); \ - buf[wp++] = r | (g << 8) | (b << 16); \ - } \ - } while (0) - -#define DECODE_UYUV422(buf) \ - do \ - { \ - int c; \ - int wp = 0; \ - \ - for (c = 0; c < voodoo->overlay.overlay_bytes; c += 4) \ - { \ - uint8_t y1, y2; \ - int8_t Cr, Cb; \ - int dR, dG, dB; \ - int r, g, b; \ - \ - Cr = src[0] - 0x80; \ - y1 = src[1]; \ - Cb = src[2] - 0x80; \ - y2 = src[3]; \ - src += 4; \ - \ - dR = (359*Cr) >> 8; \ - dG = (88*Cb + 183*Cr) >> 8; \ - dB = (453*Cb) >> 8; \ - \ - r = y1 + dR; \ - CLAMP(r); \ - g = y1 - dG; \ - CLAMP(g); \ - b = y1 + dB; \ - CLAMP(b); \ - buf[wp++] = r | (g << 8) | (b << 16); \ - \ - r = y2 + dR; \ - CLAMP(r); \ - g = y2 - dG; \ - CLAMP(g); \ - b = y2 + dB; \ - CLAMP(b); \ - buf[wp++] = r | (g << 8) | (b << 16); \ - } \ - } while (0) - - -#define OVERLAY_SAMPLE(buf) \ - do \ - { \ - switch (banshee->overlay_pix_fmt) \ - { \ - case 0: \ - break; \ - \ - case OVERLAY_FMT_YUYV422: \ - DECODE_YUYV422(buf); \ - break; \ - \ - case OVERLAY_FMT_UYVY422: \ - DECODE_UYUV422(buf); \ - break; \ - \ - case OVERLAY_FMT_565: \ - case OVERLAY_FMT_565_DITHER: \ - if (banshee->vidProcCfg & VIDPROCCFG_OVERLAY_TILE) \ - DECODE_RGB565_TILED(buf); \ - else \ - DECODE_RGB565(buf); \ - break; \ - \ - default: \ - fatal("Unknown overlay pix fmt %i\n", banshee->overlay_pix_fmt); \ - } \ - } while (0) +#define CLAMP(x) \ + do { \ + if ((x) & ~0xff) \ + x = ((x) < 0) ? 0 : 0xff; \ + } while (0) + +#define DECODE_RGB565(buf) \ + do { \ + int c; \ + int wp = 0; \ + \ + for (c = 0; c < voodoo->overlay.overlay_bytes; c += 2) { \ + uint16_t data = *(uint16_t *) src; \ + int r = data & 0x1f; \ + int g = (data >> 5) & 0x3f; \ + int b = data >> 11; \ + \ + if (banshee->vidProcCfg & VIDPROCCFG_OVERLAY_CLUT_BYPASS) \ + buf[wp++] = (r << 3) | (g << 10) | (b << 19); \ + else \ + buf[wp++] = (clut[r << 3] & 0x0000ff) | (clut[g << 2] & 0x00ff00) | (clut[b << 3] & 0xff0000); \ + src += 2; \ + } \ + } while (0) + +#define DECODE_RGB565_TILED(buf) \ + do { \ + int c; \ + int wp = 0; \ + uint32_t base_addr = (buf == banshee->overlay_buffer[1]) ? src_addr2 : src_addr; \ + \ + for (c = 0; c < voodoo->overlay.overlay_bytes; c += 2) { \ + uint16_t data = *(uint16_t *) &svga->vram[(base_addr + (c & 127) + (c >> 7) * 128 * 32) & svga->vram_mask]; \ + int r = data & 0x1f; \ + int g = (data >> 5) & 0x3f; \ + int b = data >> 11; \ + \ + if (banshee->vidProcCfg & VIDPROCCFG_OVERLAY_CLUT_BYPASS) \ + buf[wp++] = (r << 3) | (g << 10) | (b << 19); \ + else \ + buf[wp++] = (clut[r << 3] & 0x0000ff) | (clut[g << 2] & 0x00ff00) | (clut[b << 3] & 0xff0000); \ + } \ + } while (0) + +#define DECODE_YUYV422(buf) \ + do { \ + int c; \ + int wp = 0; \ + \ + for (c = 0; c < voodoo->overlay.overlay_bytes; c += 4) { \ + uint8_t y1, y2; \ + int8_t Cr, Cb; \ + int dR, dG, dB; \ + int r, g, b; \ + \ + y1 = src[0]; \ + Cr = src[1] - 0x80; \ + y2 = src[2]; \ + Cb = src[3] - 0x80; \ + src += 4; \ + \ + dR = (359 * Cr) >> 8; \ + dG = (88 * Cb + 183 * Cr) >> 8; \ + dB = (453 * Cb) >> 8; \ + \ + r = y1 + dR; \ + CLAMP(r); \ + g = y1 - dG; \ + CLAMP(g); \ + b = y1 + dB; \ + CLAMP(b); \ + buf[wp++] = r | (g << 8) | (b << 16); \ + \ + r = y2 + dR; \ + CLAMP(r); \ + g = y2 - dG; \ + CLAMP(g); \ + b = y2 + dB; \ + CLAMP(b); \ + buf[wp++] = r | (g << 8) | (b << 16); \ + } \ + } while (0) + +#define DECODE_UYUV422(buf) \ + do { \ + int c; \ + int wp = 0; \ + \ + for (c = 0; c < voodoo->overlay.overlay_bytes; c += 4) { \ + uint8_t y1, y2; \ + int8_t Cr, Cb; \ + int dR, dG, dB; \ + int r, g, b; \ + \ + Cr = src[0] - 0x80; \ + y1 = src[1]; \ + Cb = src[2] - 0x80; \ + y2 = src[3]; \ + src += 4; \ + \ + dR = (359 * Cr) >> 8; \ + dG = (88 * Cb + 183 * Cr) >> 8; \ + dB = (453 * Cb) >> 8; \ + \ + r = y1 + dR; \ + CLAMP(r); \ + g = y1 - dG; \ + CLAMP(g); \ + b = y1 + dB; \ + CLAMP(b); \ + buf[wp++] = r | (g << 8) | (b << 16); \ + \ + r = y2 + dR; \ + CLAMP(r); \ + g = y2 - dG; \ + CLAMP(g); \ + b = y2 + dB; \ + CLAMP(b); \ + buf[wp++] = r | (g << 8) | (b << 16); \ + } \ + } while (0) + +#define OVERLAY_SAMPLE(buf) \ + do { \ + switch (banshee->overlay_pix_fmt) { \ + case 0: \ + break; \ + \ + case OVERLAY_FMT_YUYV422: \ + DECODE_YUYV422(buf); \ + break; \ + \ + case OVERLAY_FMT_UYVY422: \ + DECODE_UYUV422(buf); \ + break; \ + \ + case OVERLAY_FMT_565: \ + case OVERLAY_FMT_565_DITHER: \ + if (banshee->vidProcCfg & VIDPROCCFG_OVERLAY_TILE) \ + DECODE_RGB565_TILED(buf); \ + else \ + DECODE_RGB565(buf); \ + break; \ + \ + default: \ + fatal("Unknown overlay pix fmt %i\n", banshee->overlay_pix_fmt); \ + } \ + } while (0) /* generate both filters for the static table here */ -void voodoo_generate_vb_filters(voodoo_t *voodoo, int fcr, int fcg) +void +voodoo_generate_vb_filters(voodoo_t *voodoo, int fcr, int fcg) { - int g, h; - float difference, diffg; - float thiscol, thiscolg; - float clr, clg = 0; - float hack = 1.0f; - // pre-clamping + float difference; + float diffg; + float thiscol; + float thiscolg; + float clr; + float clg = 0; + float hack = 1.0f; + // pre-clamping - fcr *= hack; - fcg *= hack; + fcr *= hack; + fcg *= hack; + /* box prefilter */ + for (uint16_t g = 0; g < 256; g++) { // pixel 1 - our target pixel we want to bleed into + for (uint16_t h = 0; h < 256; h++) { // pixel 2 - our main pixel + float avg; + float avgdiff; - /* box prefilter */ - for (g=0;g<256;g++) // pixel 1 - our target pixel we want to bleed into - { - for (h=0;h<256;h++) // pixel 2 - our main pixel - { - float avg; - float avgdiff; + difference = (float) (g - h); + avg = g; + avgdiff = avg - h; - difference = (float)(g - h); - avg = g; - avgdiff = avg - h; + avgdiff = avgdiff * 0.75f; + if (avgdiff < 0) + avgdiff *= -1; + if (difference < 0) + difference *= -1; - avgdiff = avgdiff * 0.75f; - if (avgdiff < 0) avgdiff *= -1; - if (difference < 0) difference *= -1; + thiscol = thiscolg = g; - thiscol = thiscolg = g; + if (h > g) { + clr = clg = avgdiff; - if (h > g) - { - clr = clg = avgdiff; + if (clr > fcr) + clr = fcr; + if (clg > fcg) + clg = fcg; - if (clr>fcr) clr=fcr; - if (clg>fcg) clg=fcg; + thiscol = g; + thiscolg = g; - thiscol = g; - thiscolg = g; + if (thiscol > g + fcr) + thiscol = g + fcr; + if (thiscolg > g + fcg) + thiscolg = g + fcg; - if (thiscol>g+fcr) - thiscol=g+fcr; - if (thiscolg>g+fcg) - thiscolg=g+fcg; + if (thiscol > g + difference) + thiscol = g + difference; + if (thiscolg > g + difference) + thiscolg = g + difference; - if (thiscol>g+difference) - thiscol=g+difference; - if (thiscolg>g+difference) - thiscolg=g+difference; + // hmm this might not be working out.. + int ugh = g - h; + if (ugh < fcr) + thiscol = h; + if (ugh < fcg) + thiscolg = h; + } - // hmm this might not be working out.. - int ugh = g - h; - if (ugh < fcr) - thiscol = h; - if (ugh < fcg) - thiscolg = h; - } + if (difference > fcr) + thiscol = g; + if (difference > fcg) + thiscolg = g; - if (difference > fcr) - thiscol = g; - if (difference > fcg) - thiscolg = g; + // clamp + if (thiscol < 0) + thiscol = 0; + if (thiscolg < 0) + thiscolg = 0; - // clamp - if (thiscol < 0) thiscol = 0; - if (thiscolg < 0) thiscolg = 0; + if (thiscol > 255) + thiscol = 255; + if (thiscolg > 255) + thiscolg = 255; - if (thiscol > 255) thiscol = 255; - if (thiscolg > 255) thiscolg = 255; - - vb_filter_bx_rb[g][h] = (thiscol); - vb_filter_bx_g [g][h] = (thiscolg); - - } - float lined = g + 4; - if (lined > 255) - lined = 255; - voodoo->purpleline[g][0] = lined; - voodoo->purpleline[g][2] = lined; - - lined = g + 0; - if (lined > 255) - lined = 255; - voodoo->purpleline[g][1] = lined; + vb_filter_bx_rb[g][h] = thiscol; + vb_filter_bx_g[g][h] = thiscolg; } + float lined = g + 4; + if (lined > 255) + lined = 255; + voodoo->purpleline[g][0] = lined; + voodoo->purpleline[g][2] = lined; - /* 4x1 and 2x2 filter */ - //fcr *= 5; - //fcg *= 6; + lined = g + 0; + if (lined > 255) + lined = 255; + voodoo->purpleline[g][1] = lined; + } - for (g=0;g<256;g++) // pixel 1 - { - for (h=0;h<256;h++) // pixel 2 - { - difference = (float)(h - g); - diffg = difference; + /* 4x1 and 2x2 filter */ +#if 0 + fcr *= 5; + fcg *= 6; +#endif - thiscol = thiscolg = g; + for (uint16_t g = 0; g < 256; g++) { // pixel 1 + for (uint16_t h = 0; h < 256; h++) { // pixel 2 + difference = (float) (h - g); + diffg = difference; - if (difference > fcr) - difference = fcr; - if (difference < -fcr) - difference = -fcr; + thiscol = thiscolg = g; - if (diffg > fcg) - diffg = fcg; - if (diffg < -fcg) - diffg = -fcg; + if (difference > fcr) + difference = fcr; + if (difference < -fcr) + difference = -fcr; - if ((difference < fcr) || (-difference > -fcr)) - thiscol = g + (difference / 2); - if ((diffg < fcg) || (-diffg > -fcg)) - thiscolg = g + (diffg / 2); + if (diffg > fcg) + diffg = fcg; + if (diffg < -fcg) + diffg = -fcg; - if (thiscol < 0) - thiscol = 0; - if (thiscol > 255) - thiscol = 255; + if ((difference < fcr) || (-difference > -fcr)) + thiscol = g + (difference / 2); + if ((diffg < fcg) || (-diffg > -fcg)) + thiscolg = g + (diffg / 2); - if (thiscolg < 0) - thiscolg = 0; - if (thiscolg > 255) - thiscolg = 255; + if (thiscol < 0) + thiscol = 0; + if (thiscol > 255) + thiscol = 255; - vb_filter_v1_rb[g][h] = thiscol; - vb_filter_v1_g [g][h] = thiscolg; + if (thiscolg < 0) + thiscolg = 0; + if (thiscolg > 255) + thiscolg = 255; - } + vb_filter_v1_rb[g][h] = thiscol; + vb_filter_v1_g[g][h] = thiscolg; } - + } } - -static void banshee_overlay_draw(svga_t *svga, int displine) +static void +banshee_overlay_draw(svga_t *svga, int displine) { - banshee_t *banshee = (banshee_t *)svga->p; - voodoo_t *voodoo = banshee->voodoo; - uint32_t *p; - int x; - int y = voodoo->overlay.src_y >> 20; - uint32_t src_addr = svga->overlay_latch.addr + ((banshee->vidProcCfg & VIDPROCCFG_OVERLAY_TILE) ? - ((y & 31) * 128 + (y >> 5) * svga->overlay_latch.pitch) : - y * svga->overlay_latch.pitch); - uint32_t src_addr2 = svga->overlay_latch.addr + ((banshee->vidProcCfg & VIDPROCCFG_OVERLAY_TILE) ? - (((y + 1) & 31) * 128 + ((y + 1) >> 5) * svga->overlay_latch.pitch) : - (y + 1) * svga->overlay_latch.pitch); - uint8_t *src = &svga->vram[src_addr & svga->vram_mask]; - uint32_t src_x = 0; - unsigned int y_coeff = (voodoo->overlay.src_y & 0xfffff) >> 4; - int skip_filtering; - uint32_t *clut = &svga->pallook[(banshee->vidProcCfg & VIDPROCCFG_OVERLAY_CLUT_SEL) ? 256 : 0]; + banshee_t *banshee = (banshee_t *) svga->priv; + voodoo_t *voodoo = banshee->voodoo; + uint32_t *p; + int x; + int y = voodoo->overlay.src_y >> 20; + uint32_t src_addr = svga->overlay_latch.addr + ((banshee->vidProcCfg & VIDPROCCFG_OVERLAY_TILE) ? ((y & 31) * 128 + (y >> 5) * svga->overlay_latch.pitch) : y * svga->overlay_latch.pitch); + uint32_t src_addr2 = svga->overlay_latch.addr + ((banshee->vidProcCfg & VIDPROCCFG_OVERLAY_TILE) ? (((y + 1) & 31) * 128 + ((y + 1) >> 5) * svga->overlay_latch.pitch) : (y + 1) * svga->overlay_latch.pitch); + uint8_t *src = &svga->vram[src_addr & svga->vram_mask]; + uint32_t src_x = 0; + unsigned int y_coeff = (voodoo->overlay.src_y & 0xfffff) >> 4; + int skip_filtering; + const uint32_t *clut = &svga->pallook[(banshee->vidProcCfg & VIDPROCCFG_OVERLAY_CLUT_SEL) ? 256 : 0]; - if (svga->render == svga_render_null && - !svga->changedvram[src_addr >> 12] && !svga->changedvram[src_addr2 >> 12] && - !svga->fullchange && - ((voodoo->overlay.src_y >> 20) < 2048 && !voodoo->dirty_line[voodoo->overlay.src_y >> 20]) && - !(banshee->vidProcCfg & VIDPROCCFG_V_SCALE_ENABLE)) - { - voodoo->overlay.src_y += (1 << 20); - return; - } + if (svga->render == svga_render_null && !svga->changedvram[src_addr >> 12] && !svga->changedvram[src_addr2 >> 12] && !svga->fullchange && ((voodoo->overlay.src_y >> 20) < 2048 && !voodoo->dirty_line[voodoo->overlay.src_y >> 20]) && !(banshee->vidProcCfg & VIDPROCCFG_V_SCALE_ENABLE)) { + voodoo->overlay.src_y += (1 << 20); + return; + } - if ((voodoo->overlay.src_y >> 20) < 2048) - voodoo->dirty_line[voodoo->overlay.src_y >> 20] = 0; -// pclog("displine=%i addr=%08x %08x %08x %08x\n", displine, svga->overlay_latch.addr, src_addr, voodoo->overlay.vidOverlayDvdy, *(uint32_t *)src); -// if (src_addr >= 0x800000) -// fatal("overlay out of range!\n"); - p = &((uint32_t *)buffer32->line[displine])[svga->overlay_latch.x + svga->x_add]; + if ((voodoo->overlay.src_y >> 20) < 2048) + voodoo->dirty_line[voodoo->overlay.src_y >> 20] = 0; +#if 0 + pclog("displine=%i addr=%08x %08x %08x %08x\n", displine, svga->overlay_latch.addr, src_addr, voodoo->overlay.vidOverlayDvdy, *(uint32_t *)src); + if (src_addr >= 0x800000) + fatal("overlay out of range!\n"); +#endif + p = &(svga->monitor->target_buffer->line[displine])[svga->overlay_latch.x + svga->x_add]; - if (banshee->voodoo->scrfilter && banshee->voodoo->scrfilterEnabled) - skip_filtering = ((banshee->vidProcCfg & VIDPROCCFG_FILTER_MODE_MASK) != VIDPROCCFG_FILTER_MODE_BILINEAR && - !(banshee->vidProcCfg & VIDPROCCFG_H_SCALE_ENABLE) && !(banshee->vidProcCfg & VIDPROCCFG_FILTER_MODE_DITHER_4X4) && - !(banshee->vidProcCfg & VIDPROCCFG_FILTER_MODE_DITHER_2X2)); - else - skip_filtering = ((banshee->vidProcCfg & VIDPROCCFG_FILTER_MODE_MASK) != VIDPROCCFG_FILTER_MODE_BILINEAR && - !(banshee->vidProcCfg & VIDPROCCFG_H_SCALE_ENABLE)); + if (banshee->voodoo->scrfilter && banshee->voodoo->scrfilterEnabled) + skip_filtering = ((banshee->vidProcCfg & VIDPROCCFG_FILTER_MODE_MASK) != VIDPROCCFG_FILTER_MODE_BILINEAR && !(banshee->vidProcCfg & VIDPROCCFG_H_SCALE_ENABLE) && !(banshee->vidProcCfg & VIDPROCCFG_FILTER_MODE_DITHER_4X4) && !(banshee->vidProcCfg & VIDPROCCFG_FILTER_MODE_DITHER_2X2)); + else + skip_filtering = ((banshee->vidProcCfg & VIDPROCCFG_FILTER_MODE_MASK) != VIDPROCCFG_FILTER_MODE_BILINEAR && !(banshee->vidProcCfg & VIDPROCCFG_H_SCALE_ENABLE)); - if (skip_filtering) - { - /*No scaling or filtering required, just write straight to output buffer*/ - OVERLAY_SAMPLE(p); - } - else - { - OVERLAY_SAMPLE(banshee->overlay_buffer[0]); + if (skip_filtering) { + /*No scaling or filtering required, just write straight to output buffer*/ + OVERLAY_SAMPLE(p); + } else { + OVERLAY_SAMPLE(banshee->overlay_buffer[0]); - switch (banshee->vidProcCfg & VIDPROCCFG_FILTER_MODE_MASK) - { - case VIDPROCCFG_FILTER_MODE_BILINEAR: - src = &svga->vram[src_addr2 & svga->vram_mask]; - OVERLAY_SAMPLE(banshee->overlay_buffer[1]); - if (banshee->vidProcCfg & VIDPROCCFG_H_SCALE_ENABLE) - { - for (x = 0; x < svga->overlay_latch.xsize; x++) - { - unsigned int x_coeff = (src_x & 0xfffff) >> 4; - unsigned int coeffs[4] = { - ((0x10000 - x_coeff) * (0x10000 - y_coeff)) >> 16, - ( x_coeff * (0x10000 - y_coeff)) >> 16, - ((0x10000 - x_coeff) * y_coeff) >> 16, - ( x_coeff * y_coeff) >> 16 - }; - uint32_t samp0 = banshee->overlay_buffer[0][src_x >> 20]; - uint32_t samp1 = banshee->overlay_buffer[0][(src_x >> 20) + 1]; - uint32_t samp2 = banshee->overlay_buffer[1][src_x >> 20]; - uint32_t samp3 = banshee->overlay_buffer[1][(src_x >> 20) + 1]; - int r = (((samp0 >> 16) & 0xff) * coeffs[0] + - ((samp1 >> 16) & 0xff) * coeffs[1] + - ((samp2 >> 16) & 0xff) * coeffs[2] + - ((samp3 >> 16) & 0xff) * coeffs[3]) >> 16; - int g = (((samp0 >> 8) & 0xff) * coeffs[0] + - ((samp1 >> 8) & 0xff) * coeffs[1] + - ((samp2 >> 8) & 0xff) * coeffs[2] + - ((samp3 >> 8) & 0xff) * coeffs[3]) >> 16; - int b = ((samp0 & 0xff) * coeffs[0] + - (samp1 & 0xff) * coeffs[1] + - (samp2 & 0xff) * coeffs[2] + - (samp3 & 0xff) * coeffs[3]) >> 16; - p[x] = (r << 16) | (g << 8) | b; + switch (banshee->vidProcCfg & VIDPROCCFG_FILTER_MODE_MASK) { + case VIDPROCCFG_FILTER_MODE_BILINEAR: + src = &svga->vram[src_addr2 & svga->vram_mask]; + OVERLAY_SAMPLE(banshee->overlay_buffer[1]); + if (banshee->vidProcCfg & VIDPROCCFG_H_SCALE_ENABLE) { + for (x = 0; x < svga->overlay_latch.cur_xsize; x++) { + unsigned int x_coeff = (src_x & 0xfffff) >> 4; + unsigned int coeffs[4] = { + ((0x10000 - x_coeff) * (0x10000 - y_coeff)) >> 16, + (x_coeff * (0x10000 - y_coeff)) >> 16, + ((0x10000 - x_coeff) * y_coeff) >> 16, + (x_coeff * y_coeff) >> 16 + }; + uint32_t samp0 = banshee->overlay_buffer[0][src_x >> 20]; + uint32_t samp1 = banshee->overlay_buffer[0][(src_x >> 20) + 1]; + uint32_t samp2 = banshee->overlay_buffer[1][src_x >> 20]; + uint32_t samp3 = banshee->overlay_buffer[1][(src_x >> 20) + 1]; + int r = (((samp0 >> 16) & 0xff) * coeffs[0] + ((samp1 >> 16) & 0xff) * coeffs[1] + ((samp2 >> 16) & 0xff) * coeffs[2] + ((samp3 >> 16) & 0xff) * coeffs[3]) >> 16; + int g = (((samp0 >> 8) & 0xff) * coeffs[0] + ((samp1 >> 8) & 0xff) * coeffs[1] + ((samp2 >> 8) & 0xff) * coeffs[2] + ((samp3 >> 8) & 0xff) * coeffs[3]) >> 16; + int b = ((samp0 & 0xff) * coeffs[0] + (samp1 & 0xff) * coeffs[1] + (samp2 & 0xff) * coeffs[2] + (samp3 & 0xff) * coeffs[3]) >> 16; + p[x] = (r << 16) | (g << 8) | b; - src_x += voodoo->overlay.vidOverlayDudx; - } - } - else - { - for (x = 0; x < svga->overlay_latch.xsize; x++) - { - uint32_t samp0 = banshee->overlay_buffer[0][src_x >> 20]; - uint32_t samp1 = banshee->overlay_buffer[1][src_x >> 20]; - int r = (((samp0 >> 16) & 0xff) * (0x10000 - y_coeff) + - ((samp1 >> 16) & 0xff) * y_coeff) >> 16; - int g = (((samp0 >> 8) & 0xff) * (0x10000 - y_coeff) + - ((samp1 >> 8) & 0xff) * y_coeff) >> 16; - int b = ((samp0 & 0xff) * (0x10000 - y_coeff) + - (samp1 & 0xff) * y_coeff) >> 16; - p[x] = (r << 16) | (g << 8) | b; - } - } - break; - - case VIDPROCCFG_FILTER_MODE_DITHER_4X4: - if (banshee->voodoo->scrfilter && banshee->voodoo->scrfilterEnabled) - { - uint8_t *fil = malloc((svga->overlay_latch.xsize) * 3); - uint8_t *fil3 = malloc((svga->overlay_latch.xsize) * 3); - - if (banshee->vidProcCfg & VIDPROCCFG_H_SCALE_ENABLE) /* leilei HACK - don't know of real 4x1 hscaled behavior yet, double for now */ - { - for (x=0; xoverlay_latch.xsize;x++) - { - fil[x*3] = ((banshee->overlay_buffer[0][src_x >> 20])); - fil[x*3+1] = ((banshee->overlay_buffer[0][src_x >> 20] >> 8)); - fil[x*3+2] = ((banshee->overlay_buffer[0][src_x >> 20] >> 16)); - fil3[x*3+0] = fil[x*3+0]; - fil3[x*3+1] = fil[x*3+1]; - fil3[x*3+2] = fil[x*3+2]; - src_x += voodoo->overlay.vidOverlayDudx; - } - } - else - { - for (x=0; xoverlay_latch.xsize;x++) - { - fil[x*3] = ((banshee->overlay_buffer[0][x])); - fil[x*3+1] = ((banshee->overlay_buffer[0][x] >> 8)); - fil[x*3+2] = ((banshee->overlay_buffer[0][x] >> 16)); - fil3[x*3+0] = fil[x*3+0]; - fil3[x*3+1] = fil[x*3+1]; - fil3[x*3+2] = fil[x*3+2]; - } - } - if (y % 2 == 0) - { - for (x=0; xoverlay_latch.xsize;x++) - { - fil[x*3] = banshee->voodoo->purpleline[fil[x*3+0]][0]; - fil[x*3+1] = banshee->voodoo->purpleline[fil[x*3+1]][1]; - fil[x*3+2] = banshee->voodoo->purpleline[fil[x*3+2]][2]; - } - } - - for (x=1; xoverlay_latch.xsize;x++) - { - fil3[(x)*3] = vb_filter_v1_rb [fil[x*3]] [fil[(x-1) *3]]; - fil3[(x)*3+1] = vb_filter_v1_g [fil[x*3+1]][fil[(x-1) *3+1]]; - fil3[(x)*3+2] = vb_filter_v1_rb [fil[x*3+2]] [fil[(x-1) *3+2]]; - } - for (x=1; xoverlay_latch.xsize;x++) - { - fil[(x)*3] = vb_filter_v1_rb [fil[x*3]] [fil3[(x-1) *3]]; - fil[(x)*3+1] = vb_filter_v1_g [fil[x*3+1]][fil3[(x-1) *3+1]]; - fil[(x)*3+2] = vb_filter_v1_rb [fil[x*3+2]] [fil3[(x-1) *3+2]]; - } - for (x=1; xoverlay_latch.xsize;x++) - { - fil3[(x)*3] = vb_filter_v1_rb [fil[x*3]] [fil[(x-1) *3]]; - fil3[(x)*3+1] = vb_filter_v1_g [fil[x*3+1]][fil[(x-1) *3+1]]; - fil3[(x)*3+2] = vb_filter_v1_rb [fil[x*3+2]] [fil[(x-1) *3+2]]; - } - for (x=0; xoverlay_latch.xsize;x++) - { - fil[(x)*3] = vb_filter_v1_rb [fil[x*3]] [fil3[(x+1) *3]]; - fil[(x)*3+1] = vb_filter_v1_g [fil[x*3+1]][fil3[(x+1) *3+1]]; - fil[(x)*3+2] = vb_filter_v1_rb [fil[x*3+2]] [fil3[(x+1) *3+2]]; - p[x] = (fil[x*3+2] << 16) | (fil[x*3+1] << 8) | fil[x*3]; - } - - free(fil); - free(fil3); - } - else /* filter disabled by emulator option */ - { - if (banshee->vidProcCfg & VIDPROCCFG_H_SCALE_ENABLE) - { - for (x = 0; x < svga->overlay_latch.xsize; x++) - { - p[x] = banshee->overlay_buffer[0][src_x >> 20]; - src_x += voodoo->overlay.vidOverlayDudx; - } - } - else - { - for (x = 0; x < svga->overlay_latch.xsize; x++) - p[x] = banshee->overlay_buffer[0][x]; - } - } - break; - - case VIDPROCCFG_FILTER_MODE_DITHER_2X2: - if (banshee->voodoo->scrfilter && banshee->voodoo->scrfilterEnabled) - { - uint8_t *fil = malloc((svga->overlay_latch.xsize) * 3); - uint8_t *soak = malloc((svga->overlay_latch.xsize) * 3); - uint8_t *soak2 = malloc((svga->overlay_latch.xsize) * 3); - - uint8_t *samp1 = malloc((svga->overlay_latch.xsize) * 3); - uint8_t *samp2 = malloc((svga->overlay_latch.xsize) * 3); - uint8_t *samp3 = malloc((svga->overlay_latch.xsize) * 3); - uint8_t *samp4 = malloc((svga->overlay_latch.xsize) * 3); - - src = &svga->vram[src_addr2 & svga->vram_mask]; - OVERLAY_SAMPLE(banshee->overlay_buffer[1]); - for (x=0; xoverlay_latch.xsize;x++) - { - samp1[x*3] = ((banshee->overlay_buffer[0][x])); - samp1[x*3+1] = ((banshee->overlay_buffer[0][x] >> 8)); - samp1[x*3+2] = ((banshee->overlay_buffer[0][x] >> 16)); - - samp2[x*3+0] = ((banshee->overlay_buffer[0][x+1])); - samp2[x*3+1] = ((banshee->overlay_buffer[0][x+1] >> 8)); - samp2[x*3+2] = ((banshee->overlay_buffer[0][x+1] >> 16)); - - samp3[x*3+0] = ((banshee->overlay_buffer[1][x])); - samp3[x*3+1] = ((banshee->overlay_buffer[1][x] >> 8)); - samp3[x*3+2] = ((banshee->overlay_buffer[1][x] >> 16)); - - samp4[x*3+0] = ((banshee->overlay_buffer[1][x+1])); - samp4[x*3+1] = ((banshee->overlay_buffer[1][x+1] >> 8)); - samp4[x*3+2] = ((banshee->overlay_buffer[1][x+1] >> 16)); - - /* sample two lines */ - - soak[x*3+0] = vb_filter_bx_rb [samp1[x*3+0]] [samp2[x*3+0]]; - soak[x*3+1] = vb_filter_bx_g [samp1[x*3+1]] [samp2[x*3+1]]; - soak[x*3+2] = vb_filter_bx_rb [samp1[x*3+2]] [samp2[x*3+2]]; - - soak2[x*3+0] = vb_filter_bx_rb[samp3[x*3+0]] [samp4[x*3+0]]; - soak2[x*3+1] = vb_filter_bx_g [samp3[x*3+1]] [samp4[x*3+1]]; - soak2[x*3+2] = vb_filter_bx_rb[samp3[x*3+2]] [samp4[x*3+2]]; - - /* then pour it on the rest */ - - fil[x*3+0] = vb_filter_v1_rb[soak[x*3+0]] [soak2[x*3+0]]; - fil[x*3+1] = vb_filter_v1_g [soak[x*3+1]] [soak2[x*3+1]]; - fil[x*3+2] = vb_filter_v1_rb[soak[x*3+2]] [soak2[x*3+2]]; - } - - if (banshee->vidProcCfg & VIDPROCCFG_H_SCALE_ENABLE) /* 2x2 on a scaled low res */ - { - for (x=0; xoverlay_latch.xsize;x++) - { - p[x] = (fil[(src_x >> 20)*3+2] << 16) | (fil[(src_x >> 20)*3+1] << 8) | fil[(src_x >> 20)*3]; - src_x += voodoo->overlay.vidOverlayDudx; - } - } - else - { - for (x=0; xoverlay_latch.xsize;x++) - { - p[x] = (fil[x*3+2] << 16) | (fil[x*3+1] << 8) | fil[x*3]; - } - } - - free(fil); - free(soak); - free(soak2); - free(samp1); - free(samp2); - free(samp3); - free(samp4); - } - else /* filter disabled by emulator option */ - { - if (banshee->vidProcCfg & VIDPROCCFG_H_SCALE_ENABLE) - { - for (x = 0; x < svga->overlay_latch.xsize; x++) - { - p[x] = banshee->overlay_buffer[0][src_x >> 20]; - - src_x += voodoo->overlay.vidOverlayDudx; - } - } - else - { - for (x = 0; x < svga->overlay_latch.xsize; x++) - p[x] = banshee->overlay_buffer[0][x]; - } - } - break; - - case VIDPROCCFG_FILTER_MODE_POINT: - default: - if (banshee->vidProcCfg & VIDPROCCFG_H_SCALE_ENABLE) - { - for (x = 0; x < svga->overlay_latch.xsize; x++) - { - p[x] = banshee->overlay_buffer[0][src_x >> 20]; - - src_x += voodoo->overlay.vidOverlayDudx; - } - } - else - { - for (x = 0; x < svga->overlay_latch.xsize; x++) - p[x] = banshee->overlay_buffer[0][x]; - } - break; + src_x += voodoo->overlay.vidOverlayDudx; + } + } else { + for (x = 0; x < svga->overlay_latch.cur_xsize; x++) { + uint32_t samp0 = banshee->overlay_buffer[0][src_x >> 20]; + uint32_t samp1 = banshee->overlay_buffer[1][src_x >> 20]; + int r = (((samp0 >> 16) & 0xff) * (0x10000 - y_coeff) + ((samp1 >> 16) & 0xff) * y_coeff) >> 16; + int g = (((samp0 >> 8) & 0xff) * (0x10000 - y_coeff) + ((samp1 >> 8) & 0xff) * y_coeff) >> 16; + int b = ((samp0 & 0xff) * (0x10000 - y_coeff) + (samp1 & 0xff) * y_coeff) >> 16; + p[x] = (r << 16) | (g << 8) | b; + } } + break; + + case VIDPROCCFG_FILTER_MODE_DITHER_4X4: + if (banshee->voodoo->scrfilter && banshee->voodoo->scrfilterEnabled) { + uint8_t fil[2048 * 3]; + uint8_t fil3[2048 * 3]; + + if (banshee->vidProcCfg & VIDPROCCFG_H_SCALE_ENABLE) /* leilei HACK - don't know of real 4x1 hscaled behavior yet, double for now */ + { + for (x = 0; x < svga->overlay_latch.cur_xsize; x++) { + fil[x * 3] = (banshee->overlay_buffer[0][src_x >> 20]); + fil[x * 3 + 1] = (banshee->overlay_buffer[0][src_x >> 20] >> 8); + fil[x * 3 + 2] = (banshee->overlay_buffer[0][src_x >> 20] >> 16); + fil3[x * 3 + 0] = fil[x * 3 + 0]; + fil3[x * 3 + 1] = fil[x * 3 + 1]; + fil3[x * 3 + 2] = fil[x * 3 + 2]; + src_x += voodoo->overlay.vidOverlayDudx; + } + } else { + for (x = 0; x < svga->overlay_latch.cur_xsize; x++) { + fil[x * 3] = (banshee->overlay_buffer[0][x]); + fil[x * 3 + 1] = (banshee->overlay_buffer[0][x] >> 8); + fil[x * 3 + 2] = (banshee->overlay_buffer[0][x] >> 16); + fil3[x * 3 + 0] = fil[x * 3 + 0]; + fil3[x * 3 + 1] = fil[x * 3 + 1]; + fil3[x * 3 + 2] = fil[x * 3 + 2]; + } + } + if (y % 2 == 0) { + for (x = 0; x < svga->overlay_latch.cur_xsize; x++) { + fil[x * 3] = banshee->voodoo->purpleline[fil[x * 3 + 0]][0]; + fil[x * 3 + 1] = banshee->voodoo->purpleline[fil[x * 3 + 1]][1]; + fil[x * 3 + 2] = banshee->voodoo->purpleline[fil[x * 3 + 2]][2]; + } + } + + for (x = 1; x < svga->overlay_latch.cur_xsize; x++) { + fil3[x * 3] = vb_filter_v1_rb[fil[x * 3]][fil[(x - 1) * 3]]; + fil3[x * 3 + 1] = vb_filter_v1_g[fil[x * 3 + 1]][fil[(x - 1) * 3 + 1]]; + fil3[x * 3 + 2] = vb_filter_v1_rb[fil[x * 3 + 2]][fil[(x - 1) * 3 + 2]]; + } + for (x = 1; x < svga->overlay_latch.cur_xsize; x++) { + fil[x * 3] = vb_filter_v1_rb[fil[x * 3]][fil3[(x - 1) * 3]]; + fil[x * 3 + 1] = vb_filter_v1_g[fil[x * 3 + 1]][fil3[(x - 1) * 3 + 1]]; + fil[x * 3 + 2] = vb_filter_v1_rb[fil[x * 3 + 2]][fil3[(x - 1) * 3 + 2]]; + } + for (x = 1; x < svga->overlay_latch.cur_xsize; x++) { + fil3[x * 3] = vb_filter_v1_rb[fil[x * 3]][fil[(x - 1) * 3]]; + fil3[x * 3 + 1] = vb_filter_v1_g[fil[x * 3 + 1]][fil[(x - 1) * 3 + 1]]; + fil3[x * 3 + 2] = vb_filter_v1_rb[fil[x * 3 + 2]][fil[(x - 1) * 3 + 2]]; + } + for (x = 0; x < svga->overlay_latch.cur_xsize; x++) { + fil[x * 3] = vb_filter_v1_rb[fil[x * 3]][fil3[(x + 1) * 3]]; + fil[x * 3 + 1] = vb_filter_v1_g[fil[x * 3 + 1]][fil3[(x + 1) * 3 + 1]]; + fil[x * 3 + 2] = vb_filter_v1_rb[fil[x * 3 + 2]][fil3[(x + 1) * 3 + 2]]; + p[x] = (fil[x * 3 + 2] << 16) | (fil[x * 3 + 1] << 8) | fil[x * 3]; + } + } else /* filter disabled by emulator option */ + { + if (banshee->vidProcCfg & VIDPROCCFG_H_SCALE_ENABLE) { + for (x = 0; x < svga->overlay_latch.cur_xsize; x++) { + p[x] = banshee->overlay_buffer[0][src_x >> 20]; + src_x += voodoo->overlay.vidOverlayDudx; + } + } else { + for (x = 0; x < svga->overlay_latch.cur_xsize; x++) + p[x] = banshee->overlay_buffer[0][x]; + } + } + break; + + case VIDPROCCFG_FILTER_MODE_DITHER_2X2: + if (banshee->voodoo->scrfilter && banshee->voodoo->scrfilterEnabled) { + uint8_t fil[2048 * 3]; + uint8_t soak[2048 * 3]; + uint8_t soak2[2048 * 3]; + + uint8_t samp1[2048 * 3]; + uint8_t samp2[2048 * 3]; + uint8_t samp3[2048 * 3]; + uint8_t samp4[2048 * 3]; + + src = &svga->vram[src_addr2 & svga->vram_mask]; + OVERLAY_SAMPLE(banshee->overlay_buffer[1]); + for (x = 0; x < svga->overlay_latch.cur_xsize; x++) { + samp1[x * 3] = (banshee->overlay_buffer[0][x]); + samp1[x * 3 + 1] = (banshee->overlay_buffer[0][x] >> 8); + samp1[x * 3 + 2] = (banshee->overlay_buffer[0][x] >> 16); + + samp2[x * 3 + 0] = (banshee->overlay_buffer[0][x + 1]); + samp2[x * 3 + 1] = (banshee->overlay_buffer[0][x + 1] >> 8); + samp2[x * 3 + 2] = (banshee->overlay_buffer[0][x + 1] >> 16); + + samp3[x * 3 + 0] = (banshee->overlay_buffer[1][x]); + samp3[x * 3 + 1] = (banshee->overlay_buffer[1][x] >> 8); + samp3[x * 3 + 2] = (banshee->overlay_buffer[1][x] >> 16); + + samp4[x * 3 + 0] = (banshee->overlay_buffer[1][x + 1]); + samp4[x * 3 + 1] = (banshee->overlay_buffer[1][x + 1] >> 8); + samp4[x * 3 + 2] = (banshee->overlay_buffer[1][x + 1] >> 16); + + /* sample two lines */ + + soak[x * 3 + 0] = vb_filter_bx_rb[samp1[x * 3 + 0]][samp2[x * 3 + 0]]; + soak[x * 3 + 1] = vb_filter_bx_g[samp1[x * 3 + 1]][samp2[x * 3 + 1]]; + soak[x * 3 + 2] = vb_filter_bx_rb[samp1[x * 3 + 2]][samp2[x * 3 + 2]]; + + soak2[x * 3 + 0] = vb_filter_bx_rb[samp3[x * 3 + 0]][samp4[x * 3 + 0]]; + soak2[x * 3 + 1] = vb_filter_bx_g[samp3[x * 3 + 1]][samp4[x * 3 + 1]]; + soak2[x * 3 + 2] = vb_filter_bx_rb[samp3[x * 3 + 2]][samp4[x * 3 + 2]]; + + /* then pour it on the rest */ + + fil[x * 3 + 0] = vb_filter_v1_rb[soak[x * 3 + 0]][soak2[x * 3 + 0]]; + fil[x * 3 + 1] = vb_filter_v1_g[soak[x * 3 + 1]][soak2[x * 3 + 1]]; + fil[x * 3 + 2] = vb_filter_v1_rb[soak[x * 3 + 2]][soak2[x * 3 + 2]]; + } + + if (banshee->vidProcCfg & VIDPROCCFG_H_SCALE_ENABLE) /* 2x2 on a scaled low res */ + { + for (x = 0; x < svga->overlay_latch.cur_xsize; x++) { + p[x] = (fil[(src_x >> 20) * 3 + 2] << 16) | (fil[(src_x >> 20) * 3 + 1] << 8) | fil[(src_x >> 20) * 3]; + src_x += voodoo->overlay.vidOverlayDudx; + } + } else { + for (x = 0; x < svga->overlay_latch.cur_xsize; x++) { + p[x] = (fil[x * 3 + 2] << 16) | (fil[x * 3 + 1] << 8) | fil[x * 3]; + } + } + } else /* filter disabled by emulator option */ + { + if (banshee->vidProcCfg & VIDPROCCFG_H_SCALE_ENABLE) { + for (x = 0; x < svga->overlay_latch.cur_xsize; x++) { + p[x] = banshee->overlay_buffer[0][src_x >> 20]; + + src_x += voodoo->overlay.vidOverlayDudx; + } + } else { + for (x = 0; x < svga->overlay_latch.cur_xsize; x++) + p[x] = banshee->overlay_buffer[0][x]; + } + } + break; + + case VIDPROCCFG_FILTER_MODE_POINT: + default: + if (banshee->vidProcCfg & VIDPROCCFG_H_SCALE_ENABLE) { + for (x = 0; x < svga->overlay_latch.cur_xsize; x++) { + p[x] = banshee->overlay_buffer[0][src_x >> 20]; + + src_x += voodoo->overlay.vidOverlayDudx; + } + } else { + for (x = 0; x < svga->overlay_latch.cur_xsize; x++) + p[x] = banshee->overlay_buffer[0][x]; + } + break; } - - if (banshee->vidProcCfg & VIDPROCCFG_V_SCALE_ENABLE) - voodoo->overlay.src_y += voodoo->overlay.vidOverlayDvdy; - else - voodoo->overlay.src_y += (1 << 20); + } + + if (banshee->vidProcCfg & VIDPROCCFG_V_SCALE_ENABLE) + voodoo->overlay.src_y += voodoo->overlay.vidOverlayDvdy; + else + voodoo->overlay.src_y += (1 << 20); } -void banshee_set_overlay_addr(void *p, uint32_t addr) +void +banshee_set_overlay_addr(void *priv, UNUSED(uint32_t addr)) { - banshee_t *banshee = (banshee_t *)p; - voodoo_t *voodoo = banshee->voodoo; - - banshee->svga.overlay.addr = banshee->voodoo->leftOverlayBuf & 0xfffffff; - banshee->svga.overlay_latch.addr = banshee->voodoo->leftOverlayBuf & 0xfffffff; + banshee_t *banshee = (banshee_t *) priv; + voodoo_t *voodoo = banshee->voodoo; + + banshee->svga.overlay.addr = banshee->voodoo->leftOverlayBuf & 0xfffffff; + banshee->svga.overlay_latch.addr = banshee->voodoo->leftOverlayBuf & 0xfffffff; + memset(voodoo->dirty_line, 1, sizeof(voodoo->dirty_line)); +} + +static void +banshee_vsync_callback(svga_t *svga) +{ + banshee_t *banshee = (banshee_t *) svga->priv; + voodoo_t *voodoo = banshee->voodoo; + + voodoo->retrace_count++; + thread_wait_mutex(voodoo->swap_mutex); + if (voodoo->swap_pending && (voodoo->retrace_count > voodoo->swap_interval)) { + if (voodoo->swap_count > 0) + voodoo->swap_count--; + voodoo->swap_pending = 0; + thread_release_mutex(voodoo->swap_mutex); + memset(voodoo->dirty_line, 1, sizeof(voodoo->dirty_line)); + voodoo->retrace_count = 0; + banshee_set_overlay_addr(banshee, voodoo->swap_offset); + thread_set_event(voodoo->wake_fifo_thread); + voodoo->frame_count++; + } else + thread_release_mutex(voodoo->swap_mutex); + + voodoo->overlay.src_y = 0; + banshee->desktop_addr = banshee->vidDesktopStartAddr; + banshee->desktop_y = 0; } -static void banshee_vsync_callback(svga_t *svga) +static uint8_t +banshee_pci_read(int func, int addr, void *priv) { - banshee_t *banshee = (banshee_t *)svga->p; - voodoo_t *voodoo = banshee->voodoo; - - voodoo->retrace_count++; - thread_wait_mutex(voodoo->swap_mutex); - if (voodoo->swap_pending && (voodoo->retrace_count > voodoo->swap_interval)) - { - if (voodoo->swap_count > 0) - voodoo->swap_count--; - voodoo->swap_pending = 0; - thread_release_mutex(voodoo->swap_mutex); - - memset(voodoo->dirty_line, 1, sizeof(voodoo->dirty_line)); - voodoo->retrace_count = 0; - banshee_set_overlay_addr(banshee, voodoo->swap_offset); - thread_set_event(voodoo->wake_fifo_thread); - voodoo->frame_count++; - } - else - thread_release_mutex(voodoo->swap_mutex); - - voodoo->overlay.src_y = 0; - banshee->desktop_addr = banshee->vidDesktopStartAddr; - banshee->desktop_y = 0; -} - -static uint8_t banshee_pci_read(int func, int addr, void *p) -{ - banshee_t *banshee = (banshee_t *)p; -// svga_t *svga = &banshee->svga; - uint8_t ret = 0; - - if (func) - return 0xff; -// banshee_log("Banshee PCI read %08X ", addr); - switch (addr) - { - case 0x00: ret = 0x1a; break; /*3DFX*/ - case 0x01: ret = 0x12; break; - - case 0x02: ret = (banshee->type == TYPE_BANSHEE) ? 0x03 : 0x05; break; - case 0x03: ret = 0x00; break; - - case 0x04: ret = banshee->pci_regs[0x04] & 0x27; break; - - case 0x07: ret = banshee->pci_regs[0x07] & 0x36; break; - - case 0x08: ret = (banshee->type == TYPE_BANSHEE) ? 3 : 1; break; /*Revision ID*/ - case 0x09: ret = 0; break; /*Programming interface*/ - - case 0x0a: ret = 0x00; break; /*Supports VGA interface*/ - case 0x0b: ret = 0x03; break; - - case 0x0d: ret = banshee->pci_regs[0x0d] & 0xf8; break; - - case 0x10: ret = 0x00; break; /*memBaseAddr0*/ - case 0x11: ret = 0x00; break; - case 0x12: ret = 0x00; break; - case 0x13: ret = banshee->memBaseAddr0 >> 24; break; - - case 0x14: ret = 0x00; break; /*memBaseAddr1*/ - case 0x15: ret = 0x00; break; - case 0x16: ret = 0x00; break; - case 0x17: ret = banshee->memBaseAddr1 >> 24; break; - - case 0x18: ret = 0x01; break; /*ioBaseAddr*/ - case 0x19: ret = banshee->ioBaseAddr >> 8; break; - case 0x1a: ret = banshee->ioBaseAddr >> 16; break; - case 0x1b: ret = banshee->ioBaseAddr >> 24; break; - - /*Subsystem vendor ID*/ - case 0x2c: ret = banshee->pci_regs[0x2c]; break; - case 0x2d: ret = banshee->pci_regs[0x2d]; break; - case 0x2e: ret = banshee->pci_regs[0x2e]; break; - case 0x2f: ret = banshee->pci_regs[0x2f]; break; - - case 0x30: ret = banshee->pci_regs[0x30] & 0x01; break; /*BIOS ROM address*/ - case 0x31: ret = 0x00; break; - case 0x32: ret = banshee->pci_regs[0x32]; break; - case 0x33: ret = banshee->pci_regs[0x33]; break; - - case 0x34: ret = banshee->agp ? 0x54 : 0x60; break; - - case 0x3c: ret = banshee->pci_regs[0x3c]; break; - - case 0x3d: ret = 0x01; break; /*INTA*/ - - case 0x3e: ret = 0x04; break; - case 0x3f: ret = 0xff; break; - - case 0x40: ret = 0x01; break; - - case 0x50: ret = banshee->pci_regs[0x50]; break; - - case 0x54: ret = 0x02; break; - case 0x55: ret = 0x60; break; - case 0x56: ret = 0x10; break; /* assumed AGP 1.0 */ - - case 0x58: ret = (banshee->type == TYPE_BANSHEE) ? 0x21 : 0x23; break; - case 0x59: ret = 0x02; break; - case 0x5b: ret = 0x07; break; - - case 0x5c: ret = banshee->pci_regs[0x5c]; break; - case 0x5d: ret = banshee->pci_regs[0x5d]; break; - case 0x5e: ret = banshee->pci_regs[0x5e]; break; - case 0x5f: ret = banshee->pci_regs[0x5f]; break; - - case 0x60: ret = 0x01; break; - case 0x62: ret = 0x21; break; - - case 0x64: ret = banshee->pci_regs[0x64]; break; - case 0x65: ret = banshee->pci_regs[0x65]; break; - case 0x66: ret = banshee->pci_regs[0x66]; break; - case 0x67: ret = banshee->pci_regs[0x67]; break; - } -// banshee_log("%02X\n", ret); - return ret; -} - -static void banshee_pci_write(int func, int addr, uint8_t val, void *p) -{ - banshee_t *banshee = (banshee_t *)p; -// svga_t *svga = &banshee->svga; - - if (func) - return; -// banshee_log("Banshee write %08X %02X %04X:%08X\n", addr, val, CS, cpu_state.pc); - switch (addr) - { - case 0x00: case 0x01: case 0x02: case 0x03: - case 0x08: case 0x09: case 0x0a: case 0x0b: - case 0x3d: case 0x3e: case 0x3f: - return; - - case PCI_REG_COMMAND: - if (val & PCI_COMMAND_IO) - { - io_removehandler(0x03c0, 0x0020, banshee_in, NULL, NULL, banshee_out, NULL, NULL, banshee); - if (banshee->ioBaseAddr) - io_removehandler(banshee->ioBaseAddr, 0x0100, banshee_ext_in, NULL, banshee_ext_inl, banshee_ext_out, NULL, banshee_ext_outl, banshee); - - io_sethandler(0x03c0, 0x0020, banshee_in, NULL, NULL, banshee_out, NULL, NULL, banshee); - if (banshee->ioBaseAddr) - io_sethandler(banshee->ioBaseAddr, 0x0100, banshee_ext_in, NULL, banshee_ext_inl, banshee_ext_out, NULL, banshee_ext_outl, banshee); - } - else - { - io_removehandler(0x03c0, 0x0020, banshee_in, NULL, NULL, banshee_out, NULL, NULL, banshee); - io_removehandler(banshee->ioBaseAddr, 0x0100, banshee_ext_in, NULL, banshee_ext_inl, banshee_ext_out, NULL, banshee_ext_outl, banshee); - } - banshee->pci_regs[PCI_REG_COMMAND] = val & 0x27; - banshee_updatemapping(banshee); - return; - case 0x07: - banshee->pci_regs[0x07] = val & 0x3e; - return; - case 0x0d: - banshee->pci_regs[0x0d] = val & 0xf8; - return; - - case 0x13: - banshee->memBaseAddr0 = (val & 0xfe) << 24; - banshee_updatemapping(banshee); - return; - - case 0x17: - banshee->memBaseAddr1 = (val & 0xfe) << 24; - banshee_updatemapping(banshee); - return; - - case 0x19: - if (banshee->pci_regs[PCI_REG_COMMAND] & PCI_COMMAND_IO) - io_removehandler(banshee->ioBaseAddr, 0x0100, banshee_ext_in, NULL, banshee_ext_inl, banshee_ext_out, NULL, banshee_ext_outl, banshee); - banshee->ioBaseAddr &= 0xffff00ff; - banshee->ioBaseAddr |= val << 8; - if ((banshee->pci_regs[PCI_REG_COMMAND] & PCI_COMMAND_IO) && banshee->ioBaseAddr) - io_sethandler(banshee->ioBaseAddr, 0x0100, banshee_ext_in, NULL, banshee_ext_inl, banshee_ext_out, NULL, banshee_ext_outl, banshee); - banshee_log("Banshee ioBaseAddr=%08x\n", banshee->ioBaseAddr); - return; - - case 0x1a: - banshee->ioBaseAddr &= 0xff00ffff; - banshee->ioBaseAddr |= val << 16; - break; - - case 0x1b: - banshee->ioBaseAddr &= 0x00ffffff; - banshee->ioBaseAddr |= val << 24; - break; - - case 0x30: case 0x32: case 0x33: - if (!banshee->has_bios) - return; - banshee->pci_regs[addr] = val; - if (banshee->pci_regs[0x30] & 0x01) - { - uint32_t biosaddr = (banshee->pci_regs[0x32] << 16) | (banshee->pci_regs[0x33] << 24); - banshee_log("Banshee bios_rom enabled at %08x\n", biosaddr); - mem_mapping_set_addr(&banshee->bios_rom.mapping, biosaddr, 0x10000); - mem_mapping_enable(&banshee->bios_rom.mapping); - } - else - { - banshee_log("Banshee bios_rom disabled\n"); - mem_mapping_disable(&banshee->bios_rom.mapping); - } - return; - case 0x3c: case 0x50: case 0x65: case 0x67: - banshee->pci_regs[addr] = val; - return; - - case 0x5c: - banshee->pci_regs[0x5c] = val & 0x27; - return; - - case 0x5d: - banshee->pci_regs[0x5d] = val & 0x03; - return; - - case 0x5f: - banshee->pci_regs[0x5e] = val; - return; - - case 0x64: - banshee->pci_regs[0x64] = val & 0x03; - return; - - case 0x66: - banshee->pci_regs[0x66] = val & 0xc0; - return; - } -} - -static const device_config_t banshee_sgram_config[] = -{ - { - .name = "memory", - .description = "Memory size", - .type = CONFIG_SELECTION, - .selection = - { - { - .description = "8 MB", - .value = 8 - }, - { - .description = "16 MB", - .value = 16 - }, - { - .description = "" - } - }, - .default_int = 16 - }, - { - .name = "bilinear", - .description = "Bilinear filtering", - .type = CONFIG_BINARY, - .default_int = 1 - }, - { - .name = "dithersub", - .description = "Dither subtraction", - .type = CONFIG_BINARY, - .default_int = 1 - }, - { - .name = "dacfilter", - .description = "Screen Filter", - .type = CONFIG_BINARY, - .default_int = 0 - }, - { - .name = "render_threads", - .description = "Render threads", - .type = CONFIG_SELECTION, - .selection = - { - { - .description = "1", - .value = 1 - }, - { - .description = "2", - .value = 2 - }, - { - .description = "4", - .value = 4 - }, - { - .description = "" - } - }, - .default_int = 2 - }, -#ifndef NO_CODEGEN - { - .name = "recompiler", - .description = "Recompiler", - .type = CONFIG_BINARY, - .default_int = 1 - }, + const banshee_t *banshee = (banshee_t *) priv; +#if 0 + svga_t *svga = &banshee->svga; #endif - { - .type = -1 - } -}; + uint8_t ret = 0; -static const device_config_t banshee_sdram_config[] = -{ - { - .name = "bilinear", - .description = "Bilinear filtering", - .type = CONFIG_BINARY, - .default_int = 1 - }, - { - .name = "dithersub", - .description = "Dither subtraction", - .type = CONFIG_BINARY, - .default_int = 1 - }, - { - .name = "dacfilter", - .description = "Screen Filter", - .type = CONFIG_BINARY, - .default_int = 0 - }, - { - .name = "render_threads", - .description = "Render threads", - .type = CONFIG_SELECTION, - .selection = - { - { - .description = "1", - .value = 1 - }, - { - .description = "2", - .value = 2 - }, - { - .description = "4", - .value = 4 - }, - { - .description = "" - } - }, - .default_int = 2 - }, -#ifndef NO_CODEGEN - { - .name = "recompiler", - .description = "Recompiler", - .type = CONFIG_BINARY, - .default_int = 1 - }, + if (func) + return 0xff; + // banshee_log("Banshee PCI read %08X ", addr); + switch (addr) { + case 0x00: + ret = 0x1a; + break; /*3DFX*/ + case 0x01: + ret = 0x12; + break; + + case 0x02: + ret = (banshee->type == TYPE_BANSHEE) ? 0x03 : 0x05; + break; + case 0x03: + ret = 0x00; + break; + + case 0x04: + ret = banshee->pci_regs[0x04] & 0x27; + break; + + case 0x07: + ret = banshee->pci_regs[0x07] & 0x36; + break; + + case 0x08: + ret = (banshee->type == TYPE_BANSHEE) ? 3 : 1; + break; /*Revision ID*/ + case 0x09: + ret = 0; + break; /*Programming interface*/ + + case 0x0a: + ret = 0x00; + break; /*Supports VGA interface*/ + case 0x0b: + ret = 0x03; + break; + + case 0x0d: + ret = banshee->pci_regs[0x0d] & 0xf8; + break; + + case 0x10: + ret = 0x00; + break; /*memBaseAddr0*/ + case 0x11: + ret = 0x00; + break; + case 0x12: + ret = 0x00; + break; + case 0x13: + ret = banshee->memBaseAddr0 >> 24; + break; + + case 0x14: + ret = 0x00; + break; /*memBaseAddr1*/ + case 0x15: + ret = 0x00; + break; + case 0x16: + ret = 0x00; + break; + case 0x17: + ret = banshee->memBaseAddr1 >> 24; + break; + + case 0x18: + ret = 0x01; + break; /*ioBaseAddr*/ + case 0x19: + ret = banshee->ioBaseAddr >> 8; + break; + case 0x1a: + ret = banshee->ioBaseAddr >> 16; + break; + case 0x1b: + ret = banshee->ioBaseAddr >> 24; + break; + + /*Subsystem vendor ID*/ + case 0x2c: + ret = banshee->pci_regs[0x2c]; + break; + case 0x2d: + ret = banshee->pci_regs[0x2d]; + break; + case 0x2e: + ret = banshee->pci_regs[0x2e]; + break; + case 0x2f: + ret = banshee->pci_regs[0x2f]; + break; + + case 0x30: + ret = banshee->pci_regs[0x30] & 0x01; + break; /*BIOS ROM address*/ + case 0x31: + ret = 0x00; + break; + case 0x32: + ret = banshee->pci_regs[0x32]; + break; + case 0x33: + ret = banshee->pci_regs[0x33]; + break; + + case 0x34: + ret = banshee->agp ? 0x54 : 0x60; + break; + + case 0x3c: + ret = banshee->pci_regs[0x3c]; + break; + + case 0x3d: + ret = 0x01; + break; /*INTA*/ + + case 0x3e: + ret = 0x04; + break; + case 0x3f: + ret = 0xff; + break; + + case 0x40: + ret = 0x01; + break; + + case 0x50: + ret = banshee->pci_regs[0x50]; + break; + + case 0x54: + ret = 0x02; + break; + case 0x55: + ret = 0x60; + break; + case 0x56: + ret = 0x10; + break; /* assumed AGP 1.0 */ + + case 0x58: + ret = (banshee->type == TYPE_BANSHEE) ? 0x21 : 0x23; + break; + case 0x59: + ret = 0x02; + break; + case 0x5b: + ret = 0x07; + break; + + case 0x5c: + ret = banshee->pci_regs[0x5c]; + break; + case 0x5d: + ret = banshee->pci_regs[0x5d]; + break; + case 0x5e: + ret = banshee->pci_regs[0x5e]; + break; + case 0x5f: + ret = banshee->pci_regs[0x5f]; + break; + + case 0x60: + ret = 0x01; + break; + case 0x62: + ret = 0x21; + break; + + case 0x64: + ret = banshee->pci_regs[0x64]; + break; + case 0x65: + ret = banshee->pci_regs[0x65]; + break; + case 0x66: + ret = banshee->pci_regs[0x66]; + break; + case 0x67: + ret = banshee->pci_regs[0x67]; + break; + + default: + break; + } +#if 0 + banshee_log("%02X\n", ret); #endif - { - .type = -1 - } -}; + return ret; +} -static void *banshee_init_common(const device_t *info, char *fn, int has_sgram, int type, int voodoo_type, int agp) +static void +banshee_pci_write(int func, int addr, uint8_t val, void *priv) { - int mem_size; - banshee_t *banshee = malloc(sizeof(banshee_t)); - memset(banshee, 0, sizeof(banshee_t)); - - banshee->type = type; - banshee->agp = agp; - banshee->has_bios = !!fn; + banshee_t *banshee = (banshee_t *) priv; +#if 0 + svga_t *svga = &banshee->svga; +#endif - if (banshee->has_bios) { - rom_init(&banshee->bios_rom, fn, 0xc0000, 0x10000, 0xffff, 0, MEM_MAPPING_EXTERNAL); + if (func) + return; +#if 0 + banshee_log("Banshee write %08X %02X %04X:%08X\n", addr, val, CS, cpu_state.pc); +#endif + switch (addr) { + case 0x00: + case 0x01: + case 0x02: + case 0x03: + case 0x08: + case 0x09: + case 0x0a: + case 0x0b: + case 0x3d: + case 0x3e: + case 0x3f: + return; + + case PCI_REG_COMMAND: + if (val & PCI_COMMAND_IO) { + io_removehandler(0x03c0, 0x0020, banshee_in, NULL, NULL, banshee_out, NULL, NULL, banshee); + if (banshee->ioBaseAddr) + io_removehandler(banshee->ioBaseAddr, 0x0100, banshee_ext_in, NULL, banshee_ext_inl, banshee_ext_out, NULL, banshee_ext_outl, banshee); + + io_sethandler(0x03c0, 0x0020, banshee_in, NULL, NULL, banshee_out, NULL, NULL, banshee); + if (banshee->ioBaseAddr) + io_sethandler(banshee->ioBaseAddr, 0x0100, banshee_ext_in, NULL, banshee_ext_inl, banshee_ext_out, NULL, banshee_ext_outl, banshee); + } else { + io_removehandler(0x03c0, 0x0020, banshee_in, NULL, NULL, banshee_out, NULL, NULL, banshee); + io_removehandler(banshee->ioBaseAddr, 0x0100, banshee_ext_in, NULL, banshee_ext_inl, banshee_ext_out, NULL, banshee_ext_outl, banshee); + } + banshee->pci_regs[PCI_REG_COMMAND] = val & 0x27; + banshee_updatemapping(banshee); + return; + case 0x07: + banshee->pci_regs[0x07] = val & 0x3e; + return; + case 0x0d: + banshee->pci_regs[0x0d] = val & 0xf8; + return; + + case 0x13: + banshee->memBaseAddr0 = (val & 0xfe) << 24; + banshee_updatemapping(banshee); + return; + + case 0x17: + banshee->memBaseAddr1 = (val & 0xfe) << 24; + banshee_updatemapping(banshee); + return; + + case 0x19: + if (banshee->pci_regs[PCI_REG_COMMAND] & PCI_COMMAND_IO) + io_removehandler(banshee->ioBaseAddr, 0x0100, banshee_ext_in, NULL, banshee_ext_inl, banshee_ext_out, NULL, banshee_ext_outl, banshee); + banshee->ioBaseAddr &= 0xffff00ff; + banshee->ioBaseAddr |= val << 8; + if ((banshee->pci_regs[PCI_REG_COMMAND] & PCI_COMMAND_IO) && banshee->ioBaseAddr) + io_sethandler(banshee->ioBaseAddr, 0x0100, banshee_ext_in, NULL, banshee_ext_inl, banshee_ext_out, NULL, banshee_ext_outl, banshee); + banshee_log("Banshee ioBaseAddr=%08x\n", banshee->ioBaseAddr); + return; + + case 0x1a: + banshee->ioBaseAddr &= 0xff00ffff; + banshee->ioBaseAddr |= val << 16; + break; + + case 0x1b: + banshee->ioBaseAddr &= 0x00ffffff; + banshee->ioBaseAddr |= val << 24; + break; + + case 0x30: + case 0x32: + case 0x33: + if (!banshee->has_bios) + return; + banshee->pci_regs[addr] = val; + if (banshee->pci_regs[0x30] & 0x01) { + uint32_t biosaddr = (banshee->pci_regs[0x32] << 16) | (banshee->pci_regs[0x33] << 24); + banshee_log("Banshee bios_rom enabled at %08x\n", biosaddr); + mem_mapping_set_addr(&banshee->bios_rom.mapping, biosaddr, 0x10000); + mem_mapping_enable(&banshee->bios_rom.mapping); + } else { + banshee_log("Banshee bios_rom disabled\n"); mem_mapping_disable(&banshee->bios_rom.mapping); - } + } + return; + case 0x3c: + case 0x50: + case 0x65: + case 0x67: + banshee->pci_regs[addr] = val; + return; - if (!banshee->has_bios) - mem_size = info->local; /* fixed size for on-board chips */ - else if (has_sgram) { - if (banshee->type == TYPE_VELOCITY100) - mem_size = 8; /* Velocity 100 only supports 8 MB */ - else - mem_size = device_get_config_int("memory"); - } else - mem_size = 16; /* SDRAM Banshee only supports 16 MB */ + case 0x5c: + banshee->pci_regs[0x5c] = val & 0x27; + return; - svga_init(info, &banshee->svga, banshee, mem_size << 20, - banshee_recalctimings, - banshee_in, banshee_out, - banshee_hwcursor_draw, - banshee_overlay_draw); - banshee->svga.vsync_callback = banshee_vsync_callback; + case 0x5d: + banshee->pci_regs[0x5d] = val & 0x03; + return; - mem_mapping_add(&banshee->linear_mapping, 0, 0, banshee_read_linear, - banshee_read_linear_w, - banshee_read_linear_l, - banshee_write_linear, - banshee_write_linear_w, - banshee_write_linear_l, - NULL, - MEM_MAPPING_EXTERNAL, - &banshee->svga); - mem_mapping_add(&banshee->reg_mapping_low, 0, 0,banshee_reg_read, - banshee_reg_readw, - banshee_reg_readl, - banshee_reg_write, - banshee_reg_writew, - banshee_reg_writel, - NULL, - MEM_MAPPING_EXTERNAL, - banshee); - mem_mapping_add(&banshee->reg_mapping_high, 0,0,banshee_reg_read, - banshee_reg_readw, - banshee_reg_readl, - banshee_reg_write, - banshee_reg_writew, - banshee_reg_writel, - NULL, - MEM_MAPPING_EXTERNAL, - banshee); + case 0x5f: + banshee->pci_regs[0x5e] = val; + return; - banshee->svga.vblank_start = banshee_vblank_start; + case 0x64: + banshee->pci_regs[0x64] = val & 0x03; + return; -// io_sethandler(0x03c0, 0x0020, banshee_in, NULL, NULL, banshee_out, NULL, NULL, banshee); + case 0x66: + banshee->pci_regs[0x66] = val & 0xc0; + return; - banshee->svga.bpp = 8; - banshee->svga.miscout = 1; - - banshee->dramInit0 = 1 << 27; - if (has_sgram && mem_size == 16) - banshee->dramInit0 |= (1 << 26); /*2xSGRAM = 16 MB*/ - if (!has_sgram) - banshee->dramInit1 = 1 << 30; /*SDRAM*/ - banshee->svga.decode_mask = 0x1ffffff; - - banshee->card = pci_add_card(banshee->agp ? PCI_ADD_AGP : PCI_ADD_VIDEO, banshee_pci_read, banshee_pci_write, banshee); - - banshee->voodoo = voodoo_2d3d_card_init(voodoo_type); - banshee->voodoo->p = banshee; - banshee->voodoo->vram = banshee->svga.vram; - banshee->voodoo->changedvram = banshee->svga.changedvram; - banshee->voodoo->fb_mem = banshee->svga.vram; - banshee->voodoo->fb_mask = banshee->svga.vram_mask; - banshee->voodoo->tex_mem[0] = banshee->svga.vram; - banshee->voodoo->tex_mem_w[0] = (uint16_t *)banshee->svga.vram; - banshee->voodoo->tex_mem[1] = banshee->svga.vram; - banshee->voodoo->tex_mem_w[1] = (uint16_t *)banshee->svga.vram; - banshee->voodoo->texture_mask = banshee->svga.vram_mask; - voodoo_generate_filter_v1(banshee->voodoo); - - banshee->vidSerialParallelPort = VIDSERIAL_DDC_DCK_W | VIDSERIAL_DDC_DDA_W; - - banshee->i2c = i2c_gpio_init("i2c_voodoo_banshee"); - banshee->i2c_ddc = i2c_gpio_init("ddc_voodoo_banshee"); - banshee->ddc = ddc_init(i2c_gpio_get_bus(banshee->i2c_ddc)); - - switch (type) - { - case TYPE_BANSHEE: - if (has_sgram) { - banshee->pci_regs[0x2c] = 0x1a; - banshee->pci_regs[0x2d] = 0x12; - banshee->pci_regs[0x2e] = 0x04; - banshee->pci_regs[0x2f] = 0x00; - } else { - banshee->pci_regs[0x2c] = 0x02; - banshee->pci_regs[0x2d] = 0x11; - banshee->pci_regs[0x2e] = 0x17; - banshee->pci_regs[0x2f] = 0x10; - } - break; - - case TYPE_V3_2000: - banshee->pci_regs[0x2c] = 0x1a; - banshee->pci_regs[0x2d] = 0x12; - banshee->pci_regs[0x2e] = 0x30; - banshee->pci_regs[0x2f] = 0x00; - break; - - case TYPE_V3_3000: - banshee->pci_regs[0x2c] = 0x1a; - banshee->pci_regs[0x2d] = 0x12; - banshee->pci_regs[0x2e] = 0x3a; - banshee->pci_regs[0x2f] = 0x00; - break; - - case TYPE_VELOCITY100: - banshee->pci_regs[0x2c] = 0x1a; - banshee->pci_regs[0x2d] = 0x12; - banshee->pci_regs[0x2e] = 0x4b; - banshee->pci_regs[0x2f] = 0x00; - break; - } - - video_inform(VIDEO_FLAG_TYPE_SPECIAL, banshee->agp ? &timing_banshee_agp : &timing_banshee); - - return banshee; + default: + break; + } } -static void *banshee_init(const device_t *info) +// clang-format off +static const device_config_t banshee_sgram_config[] = { + { + .name = "memory", + .description = "Memory size", + .type = CONFIG_SELECTION, + .selection = { + { + .description = "8 MB", + .value = 8 + }, + { + .description = "16 MB", + .value = 16 + }, + { + .description = "" + } + }, + .default_int = 16 + }, + { + .name = "bilinear", + .description = "Bilinear filtering", + .type = CONFIG_BINARY, + .default_int = 1 + }, + { + .name = "dithersub", + .description = "Dither subtraction", + .type = CONFIG_BINARY, + .default_int = 1 + }, + { + .name = "dacfilter", + .description = "Screen Filter", + .type = CONFIG_BINARY, + .default_int = 0 + }, + { + .name = "render_threads", + .description = "Render threads", + .type = CONFIG_SELECTION, + .selection = { + { + .description = "1", + .value = 1 + }, + { + .description = "2", + .value = 2 + }, + { + .description = "4", + .value = 4 + }, + { + .description = "" + } + }, + .default_int = 2 + }, +#ifndef NO_CODEGEN + { + .name = "recompiler", + .description = "Recompiler", + .type = CONFIG_BINARY, + .default_int = 1 + }, +#endif + { + .type = CONFIG_END + } +}; + +static const device_config_t banshee_sdram_config[] = { + { + .name = "bilinear", + .description = "Bilinear filtering", + .type = CONFIG_BINARY, + .default_int = 1 + }, + { + .name = "dithersub", + .description = "Dither subtraction", + .type = CONFIG_BINARY, + .default_int = 1 + }, + { + .name = "dacfilter", + .description = "Screen Filter", + .type = CONFIG_BINARY, + .default_int = 0 + }, + { + .name = "render_threads", + .description = "Render threads", + .type = CONFIG_SELECTION, + .selection = { + { + .description = "1", + .value = 1 + }, + { + .description = "2", + .value = 2 + }, + { + .description = "4", + .value = 4 + }, + { + .description = "" + } + }, + .default_int = 2 + }, +#ifndef NO_CODEGEN + { + .name = "recompiler", + .description = "Recompiler", + .type = CONFIG_BINARY, + .default_int = 1 + }, +#endif + { + .type = CONFIG_END + } +}; +// clang-format on + +static void * +banshee_init_common(const device_t *info, char *fn, int has_sgram, int type, int voodoo_type, int agp) { - return banshee_init_common(info, "roms/video/voodoo/Pci_sg.rom", 1, TYPE_BANSHEE, VOODOO_BANSHEE, 0); -} -static void *creative_banshee_init(const device_t *info) -{ - return banshee_init_common(info, "roms/video/voodoo/BlasterPCI.rom", 0, TYPE_BANSHEE, VOODOO_BANSHEE, 0); -} -static void *v3_2000_init(const device_t *info) -{ - return banshee_init_common(info, "roms/video/voodoo/2k11sd.rom", 0, TYPE_V3_2000, VOODOO_3, 0); -} -static void *v3_2000_agp_init(const device_t *info) -{ - return banshee_init_common(info, "roms/video/voodoo/2k11sd.rom", 0, TYPE_V3_2000, VOODOO_3, 1); -} -static void *v3_2000_agp_onboard_init(const device_t *info) -{ - return banshee_init_common(info, NULL, 0, TYPE_V3_2000, VOODOO_3, 1); -} -static void *v3_3000_init(const device_t *info) -{ - return banshee_init_common(info, "roms/video/voodoo/3k12sd.rom", 0, TYPE_V3_3000, VOODOO_3, 0); -} -static void *v3_3000_agp_init(const device_t *info) -{ - return banshee_init_common(info, "roms/video/voodoo/3k12sd.rom", 0, TYPE_V3_3000, VOODOO_3, 1); -} -static void *velocity_100_agp_init(const device_t *info) -{ - return banshee_init_common(info, "roms/video/voodoo/Velocity100.VBI", 1, TYPE_VELOCITY100, VOODOO_3, 1); + int mem_size; + banshee_t *banshee = malloc(sizeof(banshee_t)); + memset(banshee, 0, sizeof(banshee_t)); + + banshee->type = type; + banshee->agp = agp; + banshee->has_bios = !!fn; + + if (banshee->has_bios) { + rom_init(&banshee->bios_rom, fn, 0xc0000, 0x10000, 0xffff, 0, MEM_MAPPING_EXTERNAL); + mem_mapping_disable(&banshee->bios_rom.mapping); + } + + if (!banshee->has_bios) +#if 0 + mem_size = info->local; /* fixed size for on-board chips */ +#endif + mem_size = device_get_config_int("memory"); /* MS-6168 / Bora Pro can do both 8 and 16 MB. */ + else if (has_sgram) { + if (banshee->type == TYPE_VELOCITY100) + mem_size = 8; /* Velocity 100 only supports 8 MB */ + else + mem_size = device_get_config_int("memory"); + } else + mem_size = 16; /* SDRAM Banshee only supports 16 MB */ + + svga_init(info, &banshee->svga, banshee, mem_size << 20, + banshee_recalctimings, + banshee_in, banshee_out, + banshee_hwcursor_draw, + banshee_overlay_draw); + banshee->svga.vsync_callback = banshee_vsync_callback; + + mem_mapping_add(&banshee->linear_mapping, 0, 0, banshee_read_linear, + banshee_read_linear_w, + banshee_read_linear_l, + banshee_write_linear, + banshee_write_linear_w, + banshee_write_linear_l, + NULL, + MEM_MAPPING_EXTERNAL, + &banshee->svga); + mem_mapping_add(&banshee->reg_mapping_low, 0, 0, banshee_reg_read, + banshee_reg_readw, + banshee_reg_readl, + banshee_reg_write, + banshee_reg_writew, + banshee_reg_writel, + NULL, + MEM_MAPPING_EXTERNAL, + banshee); + mem_mapping_add(&banshee->reg_mapping_high, 0, 0, banshee_reg_read, + banshee_reg_readw, + banshee_reg_readl, + banshee_reg_write, + banshee_reg_writew, + banshee_reg_writel, + NULL, + MEM_MAPPING_EXTERNAL, + banshee); + + banshee->svga.vblank_start = banshee_vblank_start; + +#if 0 + io_sethandler(0x03c0, 0x0020, banshee_in, NULL, NULL, banshee_out, NULL, NULL, banshee); +#endif + + banshee->svga.bpp = 8; + banshee->svga.miscout = 1; + + banshee->dramInit0 = 1 << 27; + if (has_sgram && mem_size == 16) + banshee->dramInit0 |= (1 << 26); /*2xSGRAM = 16 MB*/ + if (!has_sgram) + banshee->dramInit1 = 1 << 30; /*SDRAM*/ + banshee->svga.decode_mask = 0x1ffffff; + + if (banshee->has_bios) + pci_add_card(banshee->agp ? PCI_ADD_AGP : PCI_ADD_NORMAL, banshee_pci_read, banshee_pci_write, banshee, &banshee->pci_slot); + else + pci_add_card(banshee->agp ? PCI_ADD_AGP : PCI_ADD_VIDEO, banshee_pci_read, banshee_pci_write, banshee, &banshee->pci_slot); + + banshee->voodoo = voodoo_2d3d_card_init(voodoo_type); + banshee->voodoo->priv = banshee; + banshee->voodoo->vram = banshee->svga.vram; + banshee->voodoo->changedvram = banshee->svga.changedvram; + banshee->voodoo->fb_mem = banshee->svga.vram; + banshee->voodoo->fb_mask = banshee->svga.vram_mask; + banshee->voodoo->tex_mem[0] = banshee->svga.vram; + banshee->voodoo->tex_mem_w[0] = (uint16_t *) banshee->svga.vram; + banshee->voodoo->tex_mem[1] = banshee->svga.vram; + banshee->voodoo->tex_mem_w[1] = (uint16_t *) banshee->svga.vram; + banshee->voodoo->texture_mask = banshee->svga.vram_mask; + banshee->voodoo->cmd_status = (1 << 28); + voodoo_generate_filter_v1(banshee->voodoo); + + banshee->vidSerialParallelPort = VIDSERIAL_DDC_DCK_W | VIDSERIAL_DDC_DDA_W; + + banshee->i2c = i2c_gpio_init("i2c_voodoo_banshee"); + banshee->i2c_ddc = i2c_gpio_init("ddc_voodoo_banshee"); + banshee->ddc = ddc_init(i2c_gpio_get_bus(banshee->i2c_ddc)); + + switch (type) { + case TYPE_BANSHEE: + if (has_sgram) { + banshee->pci_regs[0x2c] = 0x1a; + banshee->pci_regs[0x2d] = 0x12; + banshee->pci_regs[0x2e] = 0x04; + banshee->pci_regs[0x2f] = 0x00; + } else { + banshee->pci_regs[0x2c] = 0x02; + banshee->pci_regs[0x2d] = 0x11; + banshee->pci_regs[0x2e] = 0x17; + banshee->pci_regs[0x2f] = 0x10; + } + break; + + case TYPE_V3_1000: + banshee->pci_regs[0x2c] = 0x1a; + banshee->pci_regs[0x2d] = 0x12; + banshee->pci_regs[0x2e] = 0x52; + banshee->pci_regs[0x2f] = 0x00; + break; + + case TYPE_V3_2000: + banshee->pci_regs[0x2c] = 0x1a; + banshee->pci_regs[0x2d] = 0x12; + banshee->pci_regs[0x2e] = 0x30; + banshee->pci_regs[0x2f] = 0x00; + break; + + case TYPE_V3_3000: + banshee->pci_regs[0x2c] = 0x1a; + banshee->pci_regs[0x2d] = 0x12; + banshee->pci_regs[0x2e] = 0x3a; + banshee->pci_regs[0x2f] = 0x00; + break; + + case TYPE_V3_3500: + banshee->pci_regs[0x2c] = 0x1a; + banshee->pci_regs[0x2d] = 0x12; + banshee->pci_regs[0x2e] = 0x60; + banshee->pci_regs[0x2f] = 0x00; + break; + + case TYPE_V3_3500_COMPAQ: + banshee->pci_regs[0x2c] = 0x1a; + banshee->pci_regs[0x2d] = 0x12; + banshee->pci_regs[0x2e] = 0x4f; + banshee->pci_regs[0x2f] = 0x12; + break; + + case TYPE_V3_3500_SI: + banshee->pci_regs[0x2c] = 0x1a; + banshee->pci_regs[0x2d] = 0x12; + banshee->pci_regs[0x2e] = 0x61; + banshee->pci_regs[0x2f] = 0x00; + break; + + case TYPE_VELOCITY100: + banshee->pci_regs[0x2c] = 0x1a; + banshee->pci_regs[0x2d] = 0x12; + banshee->pci_regs[0x2e] = 0x4b; + banshee->pci_regs[0x2f] = 0x00; + break; + + case TYPE_VELOCITY200: + banshee->pci_regs[0x2c] = 0x1a; + banshee->pci_regs[0x2d] = 0x12; + banshee->pci_regs[0x2e] = 0x54; + banshee->pci_regs[0x2f] = 0x00; + break; + + default: + break; + } + + video_inform(VIDEO_FLAG_TYPE_SPECIAL, banshee->agp ? &timing_banshee_agp : &timing_banshee); + + return banshee; } -static int banshee_available(void) +static void * +banshee_init(const device_t *info) { - return rom_present("roms/video/voodoo/Pci_sg.rom"); + return banshee_init_common(info, ROM_BANSHEE, 1, TYPE_BANSHEE, VOODOO_BANSHEE, 0); } -static int creative_banshee_available(void) + +static void * +creative_banshee_init(const device_t *info) { - return rom_present("roms/video/voodoo/BlasterPCI.rom"); + return banshee_init_common(info, ROM_CREATIVE_BANSHEE, 0, TYPE_BANSHEE, VOODOO_BANSHEE, 0); } -static int v3_2000_available(void) + +static void * +v3_1000_init(const device_t *info) { - return rom_present("roms/video/voodoo/2k11sd.rom"); + return banshee_init_common(info, ROM_VOODOO3_1000, 1, TYPE_V3_1000, VOODOO_3, 0); +} + +static void * +v3_1000_agp_init(const device_t *info) +{ + return banshee_init_common(info, ROM_VOODOO3_1000, 1, TYPE_V3_1000, VOODOO_3, 1); +} + +static void * +v3_2000_init(const device_t *info) +{ + return banshee_init_common(info, ROM_VOODOO3_2000, 0, TYPE_V3_2000, VOODOO_3, 0); +} + +static void * +v3_2000_agp_init(const device_t *info) +{ + return banshee_init_common(info, ROM_VOODOO3_2000, 0, TYPE_V3_2000, VOODOO_3, 1); +} + +static void * +v3_2000_agp_onboard_init(const device_t *info) +{ + return banshee_init_common(info, NULL, 1, TYPE_V3_2000, VOODOO_3, 1); +} + +static void * +v3_3000_init(const device_t *info) +{ + return banshee_init_common(info, ROM_VOODOO3_3000, 0, TYPE_V3_3000, VOODOO_3, 0); +} + +static void * +v3_3000_agp_init(const device_t *info) +{ + return banshee_init_common(info, ROM_VOODOO3_3000, 0, TYPE_V3_3000, VOODOO_3, 1); +} + +static void * +v3_3500_agp_ntsc_init(const device_t *info) +{ + return banshee_init_common(info, ROM_VOODOO3_3500_AGP_NTSC, 0, TYPE_V3_3500, VOODOO_3, 1); +} + +static void * +v3_3500_agp_pal_init(const device_t *info) +{ + return banshee_init_common(info, ROM_VOODOO3_3500_AGP_PAL, 0, TYPE_V3_3500, VOODOO_3, 1); +} + +static void * +compaq_v3_3500_agp_init(const device_t *info) +{ + return banshee_init_common(info, ROM_VOODOO3_3500_AGP_COMPAQ, 0, TYPE_V3_3500_COMPAQ, VOODOO_3, 1); +} + +static void * +v3_3500_se_agp_init(const device_t *info) +{ + return banshee_init_common(info, ROM_VOODOO3_3500_SE_AGP, 0, TYPE_V3_3500, VOODOO_3, 1); +} + +static void * +v3_3500_si_agp_init(const device_t *info) +{ + return banshee_init_common(info, ROM_VOODOO3_3500_SI_AGP, 0, TYPE_V3_3500_SI, VOODOO_3, 1); +} + +static void * +velocity_100_agp_init(const device_t *info) +{ + return banshee_init_common(info, ROM_VELOCITY_100, 1, TYPE_VELOCITY100, VOODOO_3, 1); +} + +static void * +velocity_200_agp_init(const device_t *info) +{ + return banshee_init_common(info, ROM_VELOCITY_200, 1, TYPE_VELOCITY200, VOODOO_3, 1); +} + +static int +banshee_available(void) +{ + return rom_present(ROM_BANSHEE); +} + +static int +creative_banshee_available(void) +{ + return rom_present(ROM_CREATIVE_BANSHEE); +} + +static int +v3_1000_available(void) +{ + return rom_present(ROM_VOODOO3_1000); +} +#define v3_1000_agp_available v3_1000_available + +static int +v3_2000_available(void) +{ + return rom_present(ROM_VOODOO3_2000); } #define v3_2000_agp_available v3_2000_available -static int v3_3000_available(void) + +static int +v3_3000_available(void) { - return rom_present("roms/video/voodoo/3k12sd.rom"); + return rom_present(ROM_VOODOO3_3000); } #define v3_3000_agp_available v3_3000_available -static int velocity_100_available(void) + +static int +v3_3500_agp_ntsc_available(void) { - return rom_present("roms/video/voodoo/Velocity100.VBI"); + return rom_present(ROM_VOODOO3_3500_AGP_NTSC); } -static void banshee_close(void *p) +static int +v3_3500_agp_pal_available(void) { - banshee_t *banshee = (banshee_t *)p; - - voodoo_card_close(banshee->voodoo); - svga_close(&banshee->svga); - ddc_close(banshee->ddc); - i2c_gpio_close(banshee->i2c_ddc); - i2c_gpio_close(banshee->i2c); - - free(banshee); + return rom_present(ROM_VOODOO3_3500_AGP_PAL); } -static void banshee_speed_changed(void *p) +static int +compaq_v3_3500_agp_available(void) { - banshee_t *banshee = (banshee_t *)p; - - svga_recalctimings(&banshee->svga); + return rom_present(ROM_VOODOO3_3500_AGP_COMPAQ); } -static void banshee_force_redraw(void *p) +static int +v3_3500_se_agp_available(void) { - banshee_t *banshee = (banshee_t *)p; - - banshee->svga.fullchange = changeframecount; + return rom_present(ROM_VOODOO3_3500_SE_AGP); } - -const device_t voodoo_banshee_device = +static int +v3_3500_si_agp_available(void) { - "3dfx Voodoo Banshee", - "voodoo_banshee_pci", - DEVICE_PCI, - 0, - banshee_init, - banshee_close, - NULL, - { banshee_available }, - banshee_speed_changed, - banshee_force_redraw, - banshee_sgram_config + return rom_present(ROM_VOODOO3_3500_SI_AGP); +} + +static int +velocity_100_available(void) +{ + return rom_present(ROM_VELOCITY_100); +} + +static int +velocity_200_available(void) +{ + return rom_present(ROM_VELOCITY_200); +} + +static void +banshee_close(void *priv) +{ + banshee_t *banshee = (banshee_t *) priv; + + voodoo_card_close(banshee->voodoo); + svga_close(&banshee->svga); + ddc_close(banshee->ddc); + i2c_gpio_close(banshee->i2c_ddc); + i2c_gpio_close(banshee->i2c); + + free(banshee); +} + +static void +banshee_speed_changed(void *priv) +{ + banshee_t *banshee = (banshee_t *) priv; + + svga_recalctimings(&banshee->svga); +} + +static void +banshee_force_redraw(void *priv) +{ + banshee_t *banshee = (banshee_t *) priv; + + banshee->svga.fullchange = changeframecount; +} + +const device_t voodoo_banshee_device = { + .name = "3dfx Voodoo Banshee", + .internal_name = "voodoo_banshee_pci", + .flags = DEVICE_PCI, + .local = 0, + .init = banshee_init, + .close = banshee_close, + .reset = NULL, + { .available = banshee_available }, + .speed_changed = banshee_speed_changed, + .force_redraw = banshee_force_redraw, + .config = banshee_sgram_config }; -const device_t creative_voodoo_banshee_device = -{ - "Creative 3D Blaster Banshee", - "ctl3d_banshee_pci", - DEVICE_PCI, - 0, - creative_banshee_init, - banshee_close, - NULL, - { creative_banshee_available }, - banshee_speed_changed, - banshee_force_redraw, - banshee_sdram_config +const device_t creative_voodoo_banshee_device = { + .name = "Creative 3D Blaster Banshee", + .internal_name = "ctl3d_banshee_pci", + .flags = DEVICE_PCI, + .local = 0, + .init = creative_banshee_init, + .close = banshee_close, + .reset = NULL, + { .available = creative_banshee_available }, + .speed_changed = banshee_speed_changed, + .force_redraw = banshee_force_redraw, + .config = banshee_sdram_config }; -const device_t voodoo_3_2000_device = -{ - "3dfx Voodoo3 2000", - "voodoo3_2k_pci", - DEVICE_PCI, - 0, - v3_2000_init, - banshee_close, - NULL, - { v3_2000_available }, - banshee_speed_changed, - banshee_force_redraw, - banshee_sdram_config +const device_t voodoo_3_1000_device = { + .name = "3dfx Voodoo3 1000", + .internal_name = "voodoo3_1k_pci", + .flags = DEVICE_PCI, + .local = 0, + .init = v3_1000_init, + .close = banshee_close, + .reset = NULL, + { .available = v3_1000_available }, + .speed_changed = banshee_speed_changed, + .force_redraw = banshee_force_redraw, + .config = banshee_sgram_config }; -const device_t voodoo_3_2000_agp_device = -{ - "3dfx Voodoo3 2000", - "voodoo3_2k_agp", - DEVICE_AGP, - 0, - v3_2000_agp_init, - banshee_close, - NULL, - { v3_2000_agp_available }, - banshee_speed_changed, - banshee_force_redraw, - banshee_sdram_config +const device_t voodoo_3_1000_agp_device = { + .name = "3dfx Voodoo3 1000", + .internal_name = "voodoo3_1k_agp", + .flags = DEVICE_AGP, + .local = 0, + .init = v3_1000_agp_init, + .close = banshee_close, + .reset = NULL, + { .available = v3_1000_agp_available }, + .speed_changed = banshee_speed_changed, + .force_redraw = banshee_force_redraw, + .config = banshee_sgram_config }; -const device_t voodoo_3_2000_agp_onboard_8m_device = -{ - "3dfx Voodoo3 2000 (On-Board 8MB SGRAM)", - "voodoo3_2k_agp_onboard_8m", - DEVICE_AGP, - 8, - v3_2000_agp_onboard_init, - banshee_close, - NULL, - { NULL }, - banshee_speed_changed, - banshee_force_redraw, - banshee_sdram_config +const device_t voodoo_3_2000_device = { + .name = "3dfx Voodoo3 2000", + .internal_name = "voodoo3_2k_pci", + .flags = DEVICE_PCI, + .local = 0, + .init = v3_2000_init, + .close = banshee_close, + .reset = NULL, + { .available = v3_2000_available }, + .speed_changed = banshee_speed_changed, + .force_redraw = banshee_force_redraw, + .config = banshee_sdram_config }; -const device_t voodoo_3_3000_device = -{ - "3dfx Voodoo3 3000", - "voodoo3_3k_pci", - DEVICE_PCI, - 0, - v3_3000_init, - banshee_close, - NULL, - { v3_3000_available }, - banshee_speed_changed, - banshee_force_redraw, - banshee_sdram_config +const device_t voodoo_3_2000_agp_device = { + .name = "3dfx Voodoo3 2000", + .internal_name = "voodoo3_2k_agp", + .flags = DEVICE_AGP, + .local = 0, + .init = v3_2000_agp_init, + .close = banshee_close, + .reset = NULL, + { .available = v3_2000_agp_available }, + .speed_changed = banshee_speed_changed, + .force_redraw = banshee_force_redraw, + .config = banshee_sdram_config }; -const device_t voodoo_3_3000_agp_device = -{ - "3dfx Voodoo3 3000", - "voodoo3_3k_agp", - DEVICE_AGP, - 0, - v3_3000_agp_init, - banshee_close, - NULL, - { v3_3000_agp_available }, - banshee_speed_changed, - banshee_force_redraw, - banshee_sdram_config +const device_t voodoo_3_2000_agp_onboard_8m_device = { + .name = "3dfx Voodoo3 2000 (On-Board 8MB SGRAM)", + .internal_name = "voodoo3_2k_agp_onboard_8m", + .flags = DEVICE_AGP, + .local = 8, + .init = v3_2000_agp_onboard_init, + .close = banshee_close, + .reset = NULL, + { .available = NULL }, + .speed_changed = banshee_speed_changed, + .force_redraw = banshee_force_redraw, + .config = banshee_sgram_config }; -const device_t velocity_100_agp_device = -{ - "3dfx Velocity 100", - "velocity100_agp", - DEVICE_AGP, - 0, - velocity_100_agp_init, - banshee_close, - NULL, - { velocity_100_available }, - banshee_speed_changed, - banshee_force_redraw, - banshee_sdram_config -}; \ No newline at end of file +const device_t voodoo_3_3000_device = { + .name = "3dfx Voodoo3 3000", + .internal_name = "voodoo3_3k_pci", + .flags = DEVICE_PCI, + .local = 0, + .init = v3_3000_init, + .close = banshee_close, + .reset = NULL, + { .available = v3_3000_available }, + .speed_changed = banshee_speed_changed, + .force_redraw = banshee_force_redraw, + .config = banshee_sdram_config +}; + +const device_t voodoo_3_3000_agp_device = { + .name = "3dfx Voodoo3 3000", + .internal_name = "voodoo3_3k_agp", + .flags = DEVICE_AGP, + .local = 0, + .init = v3_3000_agp_init, + .close = banshee_close, + .reset = NULL, + { .available = v3_3000_agp_available }, + .speed_changed = banshee_speed_changed, + .force_redraw = banshee_force_redraw, + .config = banshee_sdram_config +}; + +const device_t voodoo_3_3500_agp_ntsc_device = { + .name = "3dfx Voodoo3 3500 TV (NTSC)", + .internal_name = "voodoo3_3500_agp_ntsc", + .flags = DEVICE_AGP, + .local = 0, + .init = v3_3500_agp_ntsc_init, + .close = banshee_close, + .reset = NULL, + { .available = v3_3500_agp_ntsc_available }, + .speed_changed = banshee_speed_changed, + .force_redraw = banshee_force_redraw, + .config = banshee_sdram_config +}; + +const device_t voodoo_3_3500_agp_pal_device = { + .name = "3dfx Voodoo3 3500 TV (PAL)", + .internal_name = "voodoo3_3500_agp_pal", + .flags = DEVICE_AGP, + .local = 0, + .init = v3_3500_agp_pal_init, + .close = banshee_close, + .reset = NULL, + { .available = v3_3500_agp_pal_available }, + .speed_changed = banshee_speed_changed, + .force_redraw = banshee_force_redraw, + .config = banshee_sdram_config +}; + +const device_t compaq_voodoo_3_3500_agp_device = { + .name = "Compaq Voodoo3 3500 TV", + .internal_name = "compaq_voodoo3_3500_agp", + .flags = DEVICE_AGP, + .local = 0, + .init = compaq_v3_3500_agp_init, + .close = banshee_close, + .reset = NULL, + { .available = compaq_v3_3500_agp_available }, + .speed_changed = banshee_speed_changed, + .force_redraw = banshee_force_redraw, + .config = banshee_sdram_config +}; + +const device_t voodoo_3_3500_se_agp_device = { + .name = "Falcon Northwest Voodoo3 3500 SE", + .internal_name = "voodoo3_3500_se_agp", + .flags = DEVICE_AGP, + .local = 0, + .init = v3_3500_se_agp_init, + .close = banshee_close, + .reset = NULL, + { .available = v3_3500_se_agp_available }, + .speed_changed = banshee_speed_changed, + .force_redraw = banshee_force_redraw, + .config = banshee_sdram_config +}; + +const device_t voodoo_3_3500_si_agp_device = { + .name = "3dfx Voodoo3 3500 SI", + .internal_name = "voodoo3_3500_si_agp", + .flags = DEVICE_AGP, + .local = 0, + .init = v3_3500_si_agp_init, + .close = banshee_close, + .reset = NULL, + { .available = v3_3500_si_agp_available }, + .speed_changed = banshee_speed_changed, + .force_redraw = banshee_force_redraw, + .config = banshee_sdram_config +}; + +const device_t velocity_100_agp_device = { + .name = "3dfx Velocity 100", + .internal_name = "velocity100_agp", + .flags = DEVICE_AGP, + .local = 0, + .init = velocity_100_agp_init, + .close = banshee_close, + .reset = NULL, + { .available = velocity_100_available }, + .speed_changed = banshee_speed_changed, + .force_redraw = banshee_force_redraw, + .config = banshee_sdram_config +}; + +const device_t velocity_200_agp_device = { + .name = "3dfx Velocity 200", + .internal_name = "velocity200_agp", + .flags = DEVICE_AGP, + .local = 0, + .init = velocity_200_agp_init, + .close = banshee_close, + .reset = NULL, + { .available = velocity_200_available }, + .speed_changed = banshee_speed_changed, + .force_redraw = banshee_force_redraw, + .config = banshee_sgram_config +}; diff --git a/src/video/vid_voodoo_banshee_blitter.c b/src/video/vid_voodoo_banshee_blitter.c index 13ed8edbd..33ee602b5 100644 --- a/src/video/vid_voodoo_banshee_blitter.c +++ b/src/video/vid_voodoo_banshee_blitter.c @@ -1,6 +1,6 @@ /*Current issues : - missing screen->screen scaled blits with format conversion - - missing YUV blits + - missing YUV blits (YUV -> 32-bit, 24-bit, or 16-bit RGB now done) - missing linestyle - missing wait for vsync - missing reversible lines @@ -9,6 +9,7 @@ - 16 bpp runs with tiled framebuffer - to aid 3D? 8 and 32 bpp use linear */ +#include #include #include #include @@ -16,6 +17,7 @@ #include #include #include +#define HAVE_STDARG_H #include <86box/86box.h> #include "cpu.h" #include <86box/machine.h> @@ -24,6 +26,7 @@ #include <86box/timer.h> #include <86box/device.h> #include <86box/plat.h> +#include <86box/thread.h> #include <86box/video.h> #include <86box/vid_svga.h> #include <86box/vid_voodoo_common.h> @@ -40,56 +43,55 @@ #define COMMAND_CMD_LINE (6 << 0) #define COMMAND_CMD_POLYLINE (7 << 0) #define COMMAND_CMD_POLYFILL (8 << 0) -#define COMMAND_INITIATE (1 << 8) -#define COMMAND_INC_X_START (1 << 10) -#define COMMAND_INC_Y_START (1 << 11) -#define COMMAND_STIPPLE_LINE (1 << 12) -#define COMMAND_PATTERN_MONO (1 << 13) -#define COMMAND_DX (1 << 14) -#define COMMAND_DY (1 << 15) -#define COMMAND_TRANS_MONO (1 << 16) -#define COMMAND_PATOFF_X_MASK (7 << 17) -#define COMMAND_PATOFF_X_SHIFT (17) -#define COMMAND_PATOFF_Y_MASK (7 << 20) -#define COMMAND_PATOFF_Y_SHIFT (20) -#define COMMAND_CLIP_SEL (1 << 23) +#define COMMAND_INITIATE (1 << 8) +#define COMMAND_INC_X_START (1 << 10) +#define COMMAND_INC_Y_START (1 << 11) +#define COMMAND_STIPPLE_LINE (1 << 12) +#define COMMAND_PATTERN_MONO (1 << 13) +#define COMMAND_DX (1 << 14) +#define COMMAND_DY (1 << 15) +#define COMMAND_TRANS_MONO (1 << 16) +#define COMMAND_PATOFF_X_MASK (7 << 17) +#define COMMAND_PATOFF_X_SHIFT (17) +#define COMMAND_PATOFF_Y_MASK (7 << 20) +#define COMMAND_PATOFF_Y_SHIFT (20) +#define COMMAND_CLIP_SEL (1 << 23) -#define CMDEXTRA_SRC_COLORKEY (1 << 0) -#define CMDEXTRA_DST_COLORKEY (1 << 1) -#define CMDEXTRA_FORCE_PAT_ROW0 (1 << 3) +#define CMDEXTRA_SRC_COLORKEY (1 << 0) +#define CMDEXTRA_DST_COLORKEY (1 << 1) +#define CMDEXTRA_FORCE_PAT_ROW0 (1 << 3) -#define SRC_FORMAT_STRIDE_MASK (0x1fff) -#define SRC_FORMAT_COL_MASK (0xf << 16) -#define SRC_FORMAT_COL_1_BPP (0 << 16) -#define SRC_FORMAT_COL_8_BPP (1 << 16) -#define SRC_FORMAT_COL_16_BPP (3 << 16) -#define SRC_FORMAT_COL_24_BPP (4 << 16) -#define SRC_FORMAT_COL_32_BPP (5 << 16) -#define SRC_FORMAT_COL_YUYV (8 << 16) -#define SRC_FORMAT_COL_UYVY (9 << 16) -#define SRC_FORMAT_BYTE_SWIZZLE (1 << 20) -#define SRC_FORMAT_WORD_SWIZZLE (1 << 21) -#define SRC_FORMAT_PACKING_MASK (3 << 22) -#define SRC_FORMAT_PACKING_STRIDE (0 << 22) -#define SRC_FORMAT_PACKING_BYTE (1 << 22) -#define SRC_FORMAT_PACKING_WORD (2 << 22) -#define SRC_FORMAT_PACKING_DWORD (3 << 22) +#define SRC_FORMAT_STRIDE_MASK (0x1fff) +#define SRC_FORMAT_COL_MASK (0xf << 16) +#define SRC_FORMAT_COL_1_BPP (0 << 16) +#define SRC_FORMAT_COL_8_BPP (1 << 16) +#define SRC_FORMAT_COL_16_BPP (3 << 16) +#define SRC_FORMAT_COL_24_BPP (4 << 16) +#define SRC_FORMAT_COL_32_BPP (5 << 16) +#define SRC_FORMAT_COL_YUYV (8 << 16) +#define SRC_FORMAT_COL_UYVY (9 << 16) +#define SRC_FORMAT_BYTE_SWIZZLE (1 << 20) +#define SRC_FORMAT_WORD_SWIZZLE (1 << 21) +#define SRC_FORMAT_PACKING_MASK (3 << 22) +#define SRC_FORMAT_PACKING_STRIDE (0 << 22) +#define SRC_FORMAT_PACKING_BYTE (1 << 22) +#define SRC_FORMAT_PACKING_WORD (2 << 22) +#define SRC_FORMAT_PACKING_DWORD (3 << 22) -#define DST_FORMAT_STRIDE_MASK (0x1fff) -#define DST_FORMAT_COL_MASK (0xf << 16) -#define DST_FORMAT_COL_8_BPP (1 << 16) -#define DST_FORMAT_COL_16_BPP (3 << 16) -#define DST_FORMAT_COL_24_BPP (4 << 16) -#define DST_FORMAT_COL_32_BPP (5 << 16) +#define DST_FORMAT_STRIDE_MASK (0x1fff) +#define DST_FORMAT_COL_MASK (0xf << 16) +#define DST_FORMAT_COL_8_BPP (1 << 16) +#define DST_FORMAT_COL_16_BPP (3 << 16) +#define DST_FORMAT_COL_24_BPP (4 << 16) +#define DST_FORMAT_COL_32_BPP (5 << 16) -#define BRES_ERROR_MASK (0xffff) -#define BRES_ERROR_USE (1 << 31) +#define BRES_ERROR_MASK (0xffff) +#define BRES_ERROR_USE (1 << 31) -enum -{ - COLORKEY_8, - COLORKEY_16, - COLORKEY_32 +enum { + COLORKEY_8, + COLORKEY_16, + COLORKEY_32 }; #ifdef ENABLE_BANSHEEBLT_LOG @@ -101,1371 +103,1623 @@ bansheeblt_log(const char *fmt, ...) va_list ap; if (bansheeblt_do_log) { - va_start(ap, fmt); - pclog_ex(fmt, ap); - va_end(ap); + va_start(ap, fmt); + pclog_ex(fmt, ap); + va_end(ap); } } #else -#define banshee_log(fmt, ...) +# define bansheeblt_log(fmt, ...) #endif -static int colorkey(voodoo_t *voodoo, uint32_t src, int src_notdst, int color_format) +static int +colorkey(voodoo_t *voodoo, uint32_t src, int src_notdst, int color_format) { - uint32_t min = src_notdst ? voodoo->banshee_blt.srcColorkeyMin : voodoo->banshee_blt.dstColorkeyMin; - uint32_t max = src_notdst ? voodoo->banshee_blt.srcColorkeyMax : voodoo->banshee_blt.dstColorkeyMax; - - if (!(voodoo->banshee_blt.commandExtra & (src_notdst ? CMDEXTRA_SRC_COLORKEY : CMDEXTRA_DST_COLORKEY))) - return 0; - - switch (color_format) - { - case COLORKEY_8: - return ((src & 0xff) >= (min & 0xff)) && ((src & 0xff) <= (max & 0xff)); - - case COLORKEY_16: - { - int r = (src >> 11) & 0x1f, r_min = (min >> 11) & 0x1f, r_max = (max >> 11) & 0x1f; - int g = (src >> 5) & 0x3f, g_min = (min >> 5) & 0x3f, g_max = (max >> 5) & 0x3f; - int b = src & 0x1f, b_min = min & 0x1f, b_max = max & 0x1f; - - return (r >= r_min) && (r <= r_max) && (g >= g_min) && (g <= g_max) && - (b >= b_min) && (b <= b_max); - } + uint32_t min = src_notdst ? voodoo->banshee_blt.srcColorkeyMin : voodoo->banshee_blt.dstColorkeyMin; + uint32_t max = src_notdst ? voodoo->banshee_blt.srcColorkeyMax : voodoo->banshee_blt.dstColorkeyMax; - case COLORKEY_32: - { - int r = (src >> 16) & 0xff, r_min = (min >> 16) & 0xff, r_max = (max >> 16) & 0xff; - int g = (src >> 8) & 0xff, g_min = (min >> 8) & 0xff, g_max = (max >> 8) & 0xff; - int b = src & 0xff, b_min = min & 0xff, b_max = max & 0xff; - - return (r >= r_min) && (r <= r_max) && (g >= g_min) && (g <= g_max) && - (b >= b_min) && (b <= b_max); - } - - default: - return 0; - } + if (!(voodoo->banshee_blt.commandExtra & (src_notdst ? CMDEXTRA_SRC_COLORKEY : CMDEXTRA_DST_COLORKEY))) + return 0; + + switch (color_format) { + case COLORKEY_8: + return ((src & 0xff) >= (min & 0xff)) && ((src & 0xff) <= (max & 0xff)); + + case COLORKEY_16: + { + int r = (src >> 11) & 0x1f; + int r_min = (min >> 11) & 0x1f; + int r_max = (max >> 11) & 0x1f; + int g = (src >> 5) & 0x3f; + int g_min = (min >> 5) & 0x3f; + int g_max = (max >> 5) & 0x3f; + int b = src & 0x1f; + int b_min = min & 0x1f; + int b_max = max & 0x1f; + + return (r >= r_min) && (r <= r_max) && (g >= g_min) && (g <= g_max) && (b >= b_min) && (b <= b_max); + } + + case COLORKEY_32: + { + int r = (src >> 16) & 0xff; + int r_min = (min >> 16) & 0xff; + int r_max = (max >> 16) & 0xff; + int g = (src >> 8) & 0xff; + int g_min = (min >> 8) & 0xff; + int g_max = (max >> 8) & 0xff; + int b = src & 0xff; + int b_min = min & 0xff; + int b_max = max & 0xff; + + return (r >= r_min) && (r <= r_max) && (g >= g_min) && (g <= g_max) && (b >= b_min) && (b <= b_max); + } + + default: + return 0; + } } -static uint32_t MIX(voodoo_t *voodoo, uint32_t dest, uint32_t src, uint32_t pattern, int colour_format_src, int colour_format_dest) +static uint32_t +MIX(voodoo_t *voodoo, uint32_t dest, uint32_t src, uint32_t pattern, int colour_format_src, int colour_format_dest) { - int rop_nr = 0; - uint32_t result = 0; - uint32_t rop; - - if (colorkey(voodoo, src, 1, colour_format_src)) - rop_nr |= 2; - if (colorkey(voodoo, dest, 0, colour_format_dest)) - rop_nr |= 1; - - rop = voodoo->banshee_blt.rops[rop_nr]; + int rop_nr = 0; + uint32_t result = 0; + uint32_t rop; - if (rop & 0x01) - result |= (~pattern & ~src & ~dest); - if (rop & 0x02) - result |= (~pattern & ~src & dest); - if (rop & 0x04) - result |= (~pattern & src & ~dest); - if (rop & 0x08) - result |= (~pattern & src & dest); - if (rop & 0x10) - result |= ( pattern & ~src & ~dest); - if (rop & 0x20) - result |= ( pattern & ~src & dest); - if (rop & 0x40) - result |= ( pattern & src & ~dest); - if (rop & 0x80) - result |= ( pattern & src & dest); + if (colorkey(voodoo, src, 1, colour_format_src)) + rop_nr |= 2; + if (colorkey(voodoo, dest, 0, colour_format_dest)) + rop_nr |= 1; - return result; + rop = voodoo->banshee_blt.rops[rop_nr]; + + if (rop & 0x01) + result |= (~pattern & ~src & ~dest); + if (rop & 0x02) + result |= (~pattern & ~src & dest); + if (rop & 0x04) + result |= (~pattern & src & ~dest); + if (rop & 0x08) + result |= (~pattern & src & dest); + if (rop & 0x10) + result |= (pattern & ~src & ~dest); + if (rop & 0x20) + result |= (pattern & ~src & dest); + if (rop & 0x40) + result |= (pattern & src & ~dest); + if (rop & 0x80) + result |= (pattern & src & dest); + + return result; } -static uint32_t get_addr(voodoo_t *voodoo, int x, int y, int src_notdst, uint32_t src_stride) +static uint32_t +get_addr(voodoo_t *voodoo, int x, int y, int src_notdst, uint32_t src_stride) { - uint32_t stride = src_notdst ? src_stride : voodoo->banshee_blt.dst_stride; - uint32_t base_addr = src_notdst ? voodoo->banshee_blt.srcBaseAddr : voodoo->banshee_blt.dstBaseAddr; - - if (src_notdst ? voodoo->banshee_blt.srcBaseAddr_tiled : voodoo->banshee_blt.dstBaseAddr_tiled) - return (base_addr + (x & 127) + ((x >> 7) * 128*32) + ((y & 31) * 128) + (y >> 5)*stride) & voodoo->fb_mask; - else - return (base_addr + x + y*stride) & voodoo->fb_mask; + uint32_t stride = src_notdst ? src_stride : voodoo->banshee_blt.dst_stride; + uint32_t base_addr = src_notdst ? voodoo->banshee_blt.srcBaseAddr : voodoo->banshee_blt.dstBaseAddr; + + if (src_notdst ? voodoo->banshee_blt.srcBaseAddr_tiled : voodoo->banshee_blt.dstBaseAddr_tiled) + return (base_addr + (x & 127) + ((x >> 7) * 128 * 32) + ((y & 31) * 128) + (y >> 5) * stride) & voodoo->fb_mask; + else + return (base_addr + x + y * stride) & voodoo->fb_mask; } -static void PLOT(voodoo_t *voodoo, int x, int y, int pat_x, int pat_y, uint8_t pattern_mask, uint8_t rop, uint32_t src, int src_colorkey) +static void +PLOT(voodoo_t *voodoo, int x, int y, int pat_x, int pat_y, uint8_t pattern_mask, UNUSED(uint8_t rop), uint32_t src, int src_colorkey) { - switch (voodoo->banshee_blt.dstFormat & DST_FORMAT_COL_MASK) - { - case DST_FORMAT_COL_8_BPP: - { - uint32_t addr = get_addr(voodoo, x, y, 0, 0);//(voodoo->banshee_blt.dstBaseAddr + x + y*voodoo->banshee_blt.dst_stride) & voodoo->fb_mask; - uint32_t dest = voodoo->vram[addr]; - uint32_t pattern = (voodoo->banshee_blt.command & COMMAND_PATTERN_MONO) ? - ((pattern_mask & (1 << (7-(pat_x & 7)))) ? voodoo->banshee_blt.colorFore : voodoo->banshee_blt.colorBack) : - voodoo->banshee_blt.colorPattern8[(pat_x & 7) + (pat_y & 7)*8]; + switch (voodoo->banshee_blt.dstFormat & DST_FORMAT_COL_MASK) { + case DST_FORMAT_COL_8_BPP: + { + uint32_t addr = get_addr(voodoo, x, y, 0, 0); //(voodoo->banshee_blt.dstBaseAddr + x + y*voodoo->banshee_blt.dst_stride) & voodoo->fb_mask; + uint32_t dest = voodoo->vram[addr]; + uint32_t pattern = (voodoo->banshee_blt.command & COMMAND_PATTERN_MONO) ? ((pattern_mask & (1 << (7 - (pat_x & 7)))) ? voodoo->banshee_blt.colorFore : voodoo->banshee_blt.colorBack) : voodoo->banshee_blt.colorPattern8[(pat_x & 7) + (pat_y & 7) * 8]; - voodoo->vram[addr] = MIX(voodoo, dest, src, pattern, src_colorkey, COLORKEY_8); - voodoo->changedvram[addr >> 12] = changeframecount; - break; - } - case DST_FORMAT_COL_16_BPP: - { - uint32_t addr = get_addr(voodoo, x*2, y, 0, 0);//(voodoo->banshee_blt.dstBaseAddr + x*2 + y*voodoo->banshee_blt.dst_stride) & voodoo->fb_mask; - uint32_t dest = *(uint16_t *)&voodoo->vram[addr]; - uint32_t pattern = (voodoo->banshee_blt.command & COMMAND_PATTERN_MONO) ? - ((pattern_mask & (1 << (7-(pat_x & 7)))) ? voodoo->banshee_blt.colorFore : voodoo->banshee_blt.colorBack) : - voodoo->banshee_blt.colorPattern16[(pat_x & 7) + (pat_y & 7)*8]; + voodoo->vram[addr] = MIX(voodoo, dest, src, pattern, src_colorkey, COLORKEY_8); + voodoo->changedvram[addr >> 12] = changeframecount; + break; + } + case DST_FORMAT_COL_16_BPP: + { + uint32_t addr = get_addr(voodoo, x * 2, y, 0, 0); //(voodoo->banshee_blt.dstBaseAddr + x*2 + y*voodoo->banshee_blt.dst_stride) & voodoo->fb_mask; + uint32_t dest = *(uint16_t *) &voodoo->vram[addr]; + uint32_t pattern = (voodoo->banshee_blt.command & COMMAND_PATTERN_MONO) ? ((pattern_mask & (1 << (7 - (pat_x & 7)))) ? voodoo->banshee_blt.colorFore : voodoo->banshee_blt.colorBack) : voodoo->banshee_blt.colorPattern16[(pat_x & 7) + (pat_y & 7) * 8]; - *(uint16_t *)&voodoo->vram[addr] = MIX(voodoo, dest, src, pattern, src_colorkey, COLORKEY_16); - voodoo->changedvram[addr >> 12] = changeframecount; - break; - } - case DST_FORMAT_COL_24_BPP: - { - uint32_t addr = get_addr(voodoo, x*3, y, 0, 0);//(voodoo->banshee_blt.dstBaseAddr + x*3 + y*voodoo->banshee_blt.dst_stride) & voodoo->fb_mask; - uint32_t dest = *(uint32_t *)&voodoo->vram[addr]; - uint32_t pattern = (voodoo->banshee_blt.command & COMMAND_PATTERN_MONO) ? - ((pattern_mask & (1 << (7-(pat_x & 7)))) ? voodoo->banshee_blt.colorFore : voodoo->banshee_blt.colorBack) : - voodoo->banshee_blt.colorPattern24[(pat_x & 7) + (pat_y & 7)*8]; + *(uint16_t *) &voodoo->vram[addr] = MIX(voodoo, dest, src, pattern, src_colorkey, COLORKEY_16); + voodoo->changedvram[addr >> 12] = changeframecount; + break; + } + case DST_FORMAT_COL_24_BPP: + { + uint32_t addr = get_addr(voodoo, x * 3, y, 0, 0); //(voodoo->banshee_blt.dstBaseAddr + x*3 + y*voodoo->banshee_blt.dst_stride) & voodoo->fb_mask; + uint32_t dest = *(uint32_t *) &voodoo->vram[addr]; + uint32_t pattern = (voodoo->banshee_blt.command & COMMAND_PATTERN_MONO) ? ((pattern_mask & (1 << (7 - (pat_x & 7)))) ? voodoo->banshee_blt.colorFore : voodoo->banshee_blt.colorBack) : voodoo->banshee_blt.colorPattern24[(pat_x & 7) + (pat_y & 7) * 8]; - *(uint32_t *)&voodoo->vram[addr] = (MIX(voodoo, dest, src, pattern, src_colorkey, COLORKEY_32) & 0xffffff) | (dest & 0xff000000); - voodoo->changedvram[addr >> 12] = changeframecount; - break; - } - case DST_FORMAT_COL_32_BPP: - { - uint32_t addr = get_addr(voodoo, x*4, y, 0, 0);//(voodoo->banshee_blt.dstBaseAddr + x*4 + y*voodoo->banshee_blt.dst_stride) & voodoo->fb_mask; - uint32_t dest = *(uint32_t *)&voodoo->vram[addr]; - uint32_t pattern = (voodoo->banshee_blt.command & COMMAND_PATTERN_MONO) ? - ((pattern_mask & (1 << (7-(pat_x & 7)))) ? voodoo->banshee_blt.colorFore : voodoo->banshee_blt.colorBack) : - voodoo->banshee_blt.colorPattern[(pat_x & 7) + (pat_y & 7)*8]; + *(uint32_t *) &voodoo->vram[addr] = (MIX(voodoo, dest, src, pattern, src_colorkey, COLORKEY_32) & 0xffffff) | (dest & 0xff000000); + voodoo->changedvram[addr >> 12] = changeframecount; + break; + } + case DST_FORMAT_COL_32_BPP: + { + uint32_t addr = get_addr(voodoo, x * 4, y, 0, 0); //(voodoo->banshee_blt.dstBaseAddr + x*4 + y*voodoo->banshee_blt.dst_stride) & voodoo->fb_mask; + uint32_t dest = *(uint32_t *) &voodoo->vram[addr]; + uint32_t pattern = (voodoo->banshee_blt.command & COMMAND_PATTERN_MONO) ? ((pattern_mask & (1 << (7 - (pat_x & 7)))) ? voodoo->banshee_blt.colorFore : voodoo->banshee_blt.colorBack) : voodoo->banshee_blt.colorPattern[(pat_x & 7) + (pat_y & 7) * 8]; - *(uint32_t *)&voodoo->vram[addr] = MIX(voodoo, dest, src, pattern, src_colorkey, COLORKEY_32); - voodoo->changedvram[addr >> 12] = changeframecount; - break; - } - } + *(uint32_t *) &voodoo->vram[addr] = MIX(voodoo, dest, src, pattern, src_colorkey, COLORKEY_32); + voodoo->changedvram[addr >> 12] = changeframecount; + break; + } + + default: + break; + } } -static void PLOT_LINE(voodoo_t *voodoo, int x, int y, uint8_t rop, uint32_t pattern, int src_colorkey) +static void +PLOT_LINE(voodoo_t *voodoo, int x, int y, UNUSED(uint8_t rop), uint32_t pattern, int src_colorkey) { - switch (voodoo->banshee_blt.dstFormat & DST_FORMAT_COL_MASK) - { - case DST_FORMAT_COL_8_BPP: - { - uint32_t addr = get_addr(voodoo, x, y, 0, 0);//(voodoo->banshee_blt.dstBaseAddr + x + y*voodoo->banshee_blt.dst_stride) & voodoo->fb_mask; - uint32_t dest = voodoo->vram[addr]; + switch (voodoo->banshee_blt.dstFormat & DST_FORMAT_COL_MASK) { + case DST_FORMAT_COL_8_BPP: + { + uint32_t addr = get_addr(voodoo, x, y, 0, 0); //(voodoo->banshee_blt.dstBaseAddr + x + y*voodoo->banshee_blt.dst_stride) & voodoo->fb_mask; + uint32_t dest = voodoo->vram[addr]; - voodoo->vram[addr] = MIX(voodoo, dest, voodoo->banshee_blt.colorFore, pattern, src_colorkey, COLORKEY_8); - voodoo->changedvram[addr >> 12] = changeframecount; - break; - } - case DST_FORMAT_COL_16_BPP: - { - uint32_t addr = get_addr(voodoo, x*2, y, 0, 0);//(voodoo->banshee_blt.dstBaseAddr + x*2 + y*voodoo->banshee_blt.dst_stride) & voodoo->fb_mask; - uint32_t dest = *(uint16_t *)&voodoo->vram[addr]; + voodoo->vram[addr] = MIX(voodoo, dest, voodoo->banshee_blt.colorFore, pattern, src_colorkey, COLORKEY_8); + voodoo->changedvram[addr >> 12] = changeframecount; + break; + } + case DST_FORMAT_COL_16_BPP: + { + uint32_t addr = get_addr(voodoo, x * 2, y, 0, 0); //(voodoo->banshee_blt.dstBaseAddr + x*2 + y*voodoo->banshee_blt.dst_stride) & voodoo->fb_mask; + uint32_t dest = *(uint16_t *) &voodoo->vram[addr]; - *(uint16_t *)&voodoo->vram[addr] = MIX(voodoo, dest, voodoo->banshee_blt.colorFore, pattern, src_colorkey, COLORKEY_16); - voodoo->changedvram[addr >> 12] = changeframecount; - break; - } - case DST_FORMAT_COL_24_BPP: - { - uint32_t addr = get_addr(voodoo, x*3, y, 0, 0);//(voodoo->banshee_blt.dstBaseAddr + x*3 + y*voodoo->banshee_blt.dst_stride) & voodoo->fb_mask; - uint32_t dest = *(uint32_t *)&voodoo->vram[addr]; + *(uint16_t *) &voodoo->vram[addr] = MIX(voodoo, dest, voodoo->banshee_blt.colorFore, pattern, src_colorkey, COLORKEY_16); + voodoo->changedvram[addr >> 12] = changeframecount; + break; + } + case DST_FORMAT_COL_24_BPP: + { + uint32_t addr = get_addr(voodoo, x * 3, y, 0, 0); //(voodoo->banshee_blt.dstBaseAddr + x*3 + y*voodoo->banshee_blt.dst_stride) & voodoo->fb_mask; + uint32_t dest = *(uint32_t *) &voodoo->vram[addr]; - *(uint32_t *)&voodoo->vram[addr] = (MIX(voodoo, dest, voodoo->banshee_blt.colorFore, pattern, src_colorkey, COLORKEY_32) & 0xffffff) | (dest & 0xff000000); - voodoo->changedvram[addr >> 12] = changeframecount; - break; - } - case DST_FORMAT_COL_32_BPP: - { - uint32_t addr = get_addr(voodoo, x*4, y, 0, 0);//(voodoo->banshee_blt.dstBaseAddr + x*4 + y*voodoo->banshee_blt.dst_stride) & voodoo->fb_mask; - uint32_t dest = *(uint32_t *)&voodoo->vram[addr]; + *(uint32_t *) &voodoo->vram[addr] = (MIX(voodoo, dest, voodoo->banshee_blt.colorFore, pattern, src_colorkey, COLORKEY_32) & 0xffffff) | (dest & 0xff000000); + voodoo->changedvram[addr >> 12] = changeframecount; + break; + } + case DST_FORMAT_COL_32_BPP: + { + uint32_t addr = get_addr(voodoo, x * 4, y, 0, 0); //(voodoo->banshee_blt.dstBaseAddr + x*4 + y*voodoo->banshee_blt.dst_stride) & voodoo->fb_mask; + uint32_t dest = *(uint32_t *) &voodoo->vram[addr]; - *(uint32_t *)&voodoo->vram[addr] = MIX(voodoo, dest, voodoo->banshee_blt.colorFore, pattern, src_colorkey, COLORKEY_32); - voodoo->changedvram[addr >> 12] = changeframecount; - break; - } - } + *(uint32_t *) &voodoo->vram[addr] = MIX(voodoo, dest, voodoo->banshee_blt.colorFore, pattern, src_colorkey, COLORKEY_32); + voodoo->changedvram[addr >> 12] = changeframecount; + break; + } + + default: + break; + } } - -static void update_src_stride(voodoo_t *voodoo) +static void +update_src_stride(voodoo_t *voodoo) { - int bpp; + int bpp; - switch (voodoo->banshee_blt.srcFormat & SRC_FORMAT_COL_MASK) - { - case SRC_FORMAT_COL_1_BPP: - bpp = 1; - break; - case SRC_FORMAT_COL_8_BPP: - bpp = 8; - break; - case SRC_FORMAT_COL_16_BPP: - bpp = 16; - break; - case SRC_FORMAT_COL_24_BPP: - bpp = 24; - break; - case SRC_FORMAT_COL_32_BPP: - bpp = 32; - break; + switch (voodoo->banshee_blt.srcFormat & SRC_FORMAT_COL_MASK) { + case SRC_FORMAT_COL_1_BPP: + bpp = 1; + break; + case SRC_FORMAT_COL_8_BPP: + bpp = 8; + break; + case SRC_FORMAT_COL_16_BPP: + bpp = 16; + break; + case SRC_FORMAT_COL_24_BPP: + bpp = 24; + break; + case SRC_FORMAT_COL_32_BPP: + case SRC_FORMAT_COL_YUYV: + bpp = 32; + break; - default: - bpp = 16; - break; - } + default: + bpp = 16; + break; + } - switch (voodoo->banshee_blt.srcFormat & SRC_FORMAT_PACKING_MASK) - { - case SRC_FORMAT_PACKING_STRIDE: - voodoo->banshee_blt.src_stride_src = voodoo->banshee_blt.src_stride; //voodoo->banshee_blt.srcFormat & SRC_FORMAT_STRIDE_MASK; - voodoo->banshee_blt.src_stride_dest = voodoo->banshee_blt.src_stride; //voodoo->banshee_blt.srcFormat & SRC_FORMAT_STRIDE_MASK; - voodoo->banshee_blt.host_data_size_src = (voodoo->banshee_blt.srcSizeX * bpp + 7) >> 3; - voodoo->banshee_blt.host_data_size_dest = (voodoo->banshee_blt.dstSizeX * bpp + 7) >> 3; -// bansheeblt_log("Stride packing %08x %08x bpp=%i dstSizeX=%i\n", voodoo->banshee_blt.src_stride_dest, voodoo->banshee_blt.host_data_size_dest, bpp, voodoo->banshee_blt.dstSizeX); - break; + switch (voodoo->banshee_blt.srcFormat & SRC_FORMAT_PACKING_MASK) { + case SRC_FORMAT_PACKING_STRIDE: + voodoo->banshee_blt.src_stride_src = voodoo->banshee_blt.src_stride; // voodoo->banshee_blt.srcFormat & SRC_FORMAT_STRIDE_MASK; + voodoo->banshee_blt.src_stride_dest = voodoo->banshee_blt.src_stride; // voodoo->banshee_blt.srcFormat & SRC_FORMAT_STRIDE_MASK; + voodoo->banshee_blt.host_data_size_src = (voodoo->banshee_blt.srcSizeX * bpp + 7) >> 3; + voodoo->banshee_blt.host_data_size_dest = (voodoo->banshee_blt.dstSizeX * bpp + 7) >> 3; +#if 0 + bansheeblt_log("Stride packing %08x %08x bpp=%i dstSizeX=%i\n", voodoo->banshee_blt.src_stride_dest, voodoo->banshee_blt.host_data_size_dest, bpp, voodoo->banshee_blt.dstSizeX); +#endif + break; - case SRC_FORMAT_PACKING_BYTE: - voodoo->banshee_blt.src_stride_src = (voodoo->banshee_blt.srcSizeX * bpp + 7) >> 3; - voodoo->banshee_blt.src_stride_dest = (voodoo->banshee_blt.dstSizeX * bpp + 7) >> 3; - voodoo->banshee_blt.host_data_size_src = voodoo->banshee_blt.src_stride_src; - voodoo->banshee_blt.host_data_size_dest = voodoo->banshee_blt.src_stride_dest; -// bansheeblt_log("Byte packing %08x %08x\n", voodoo->banshee_blt.src_stride_dest, voodoo->banshee_blt.host_data_size_dest); - break; + case SRC_FORMAT_PACKING_BYTE: + voodoo->banshee_blt.src_stride_src = (voodoo->banshee_blt.srcSizeX * bpp + 7) >> 3; + voodoo->banshee_blt.src_stride_dest = (voodoo->banshee_blt.dstSizeX * bpp + 7) >> 3; + voodoo->banshee_blt.host_data_size_src = voodoo->banshee_blt.src_stride_src; + voodoo->banshee_blt.host_data_size_dest = voodoo->banshee_blt.src_stride_dest; +#if 0 + bansheeblt_log("Byte packing %08x %08x\n", voodoo->banshee_blt.src_stride_dest, voodoo->banshee_blt.host_data_size_dest); +#endif + break; - case SRC_FORMAT_PACKING_WORD: - voodoo->banshee_blt.src_stride_src = ((voodoo->banshee_blt.srcSizeX * bpp + 15) >> 4) * 2; - voodoo->banshee_blt.src_stride_dest = ((voodoo->banshee_blt.dstSizeX * bpp + 15) >> 4) * 2; - voodoo->banshee_blt.host_data_size_src = voodoo->banshee_blt.src_stride_src; - voodoo->banshee_blt.host_data_size_dest = voodoo->banshee_blt.src_stride_dest; -// bansheeblt_log("Word packing %08x %08x\n", voodoo->banshee_blt.src_stride_dest, voodoo->banshee_blt.host_data_size_dest); - break; + case SRC_FORMAT_PACKING_WORD: + voodoo->banshee_blt.src_stride_src = ((voodoo->banshee_blt.srcSizeX * bpp + 15) >> 4) * 2; + voodoo->banshee_blt.src_stride_dest = ((voodoo->banshee_blt.dstSizeX * bpp + 15) >> 4) * 2; + voodoo->banshee_blt.host_data_size_src = voodoo->banshee_blt.src_stride_src; + voodoo->banshee_blt.host_data_size_dest = voodoo->banshee_blt.src_stride_dest; +#if 0 + bansheeblt_log("Word packing %08x %08x\n", voodoo->banshee_blt.src_stride_dest, voodoo->banshee_blt.host_data_size_dest); +#endif + break; - case SRC_FORMAT_PACKING_DWORD: - voodoo->banshee_blt.src_stride_src = ((voodoo->banshee_blt.srcSizeX * bpp + 31) >> 5) * 4; - voodoo->banshee_blt.src_stride_dest = ((voodoo->banshee_blt.dstSizeX * bpp + 31) >> 5) * 4; - voodoo->banshee_blt.host_data_size_src = voodoo->banshee_blt.src_stride_src; - voodoo->banshee_blt.host_data_size_dest = voodoo->banshee_blt.src_stride_dest; -// bansheeblt_log("Dword packing %08x %08x\n", voodoo->banshee_blt.src_stride_dest, voodoo->banshee_blt.host_data_size_dest); - break; - } + case SRC_FORMAT_PACKING_DWORD: + voodoo->banshee_blt.src_stride_src = ((voodoo->banshee_blt.srcSizeX * bpp + 31) >> 5) * 4; + voodoo->banshee_blt.src_stride_dest = ((voodoo->banshee_blt.dstSizeX * bpp + 31) >> 5) * 4; + voodoo->banshee_blt.host_data_size_src = voodoo->banshee_blt.src_stride_src; + voodoo->banshee_blt.host_data_size_dest = voodoo->banshee_blt.src_stride_dest; +#if 0 + bansheeblt_log("Dword packing %08x %08x\n", voodoo->banshee_blt.src_stride_dest, voodoo->banshee_blt.host_data_size_dest); +#endif + break; + + default: + break; + } } -static void end_command(voodoo_t *voodoo) +static void +end_command(voodoo_t *voodoo) { - /*Update dest coordinates if required*/ - if (voodoo->banshee_blt.command & COMMAND_INC_X_START) - { - voodoo->banshee_blt.dstXY &= ~0x0000ffff; - voodoo->banshee_blt.dstXY |= (voodoo->banshee_blt.dstX & 0xffff); - } + /*Update dest coordinates if required*/ + if (voodoo->banshee_blt.command & COMMAND_INC_X_START) { + voodoo->banshee_blt.dstXY &= ~0x0000ffff; + voodoo->banshee_blt.dstXY |= (voodoo->banshee_blt.dstX & 0xffff); + } - if (voodoo->banshee_blt.command & COMMAND_INC_Y_START) - { - voodoo->banshee_blt.dstXY &= ~0xffff0000; - voodoo->banshee_blt.dstXY |= (voodoo->banshee_blt.dstY << 16); - } + if (voodoo->banshee_blt.command & COMMAND_INC_Y_START) { + voodoo->banshee_blt.dstXY &= ~0xffff0000; + voodoo->banshee_blt.dstXY |= (voodoo->banshee_blt.dstY << 16); + } } -static void banshee_do_rectfill(voodoo_t *voodoo) +static void +banshee_do_rectfill(voodoo_t *voodoo) { - clip_t *clip = &voodoo->banshee_blt.clip[(voodoo->banshee_blt.command & COMMAND_CLIP_SEL) ? 1 : 0]; - int dst_y = voodoo->banshee_blt.dstY; - uint8_t *pattern_mono = (uint8_t *)voodoo->banshee_blt.colorPattern; - int pat_y = (voodoo->banshee_blt.commandExtra & CMDEXTRA_FORCE_PAT_ROW0) ? 0 : (voodoo->banshee_blt.patoff_y + voodoo->banshee_blt.dstY); - int use_pattern_trans = (voodoo->banshee_blt.command & (COMMAND_PATTERN_MONO | COMMAND_TRANS_MONO)) == - (COMMAND_PATTERN_MONO | COMMAND_TRANS_MONO); - uint8_t rop = voodoo->banshee_blt.command >> 24; + const clip_t *clip = &voodoo->banshee_blt.clip[(voodoo->banshee_blt.command & COMMAND_CLIP_SEL) ? 1 : 0]; + int dst_y = voodoo->banshee_blt.dstY; + const uint8_t *pattern_mono = (uint8_t *) voodoo->banshee_blt.colorPattern; + int pat_y = (voodoo->banshee_blt.commandExtra & CMDEXTRA_FORCE_PAT_ROW0) ? 0 : (voodoo->banshee_blt.patoff_y + voodoo->banshee_blt.dstY); + int use_pattern_trans = (voodoo->banshee_blt.command & (COMMAND_PATTERN_MONO | COMMAND_TRANS_MONO)) == (COMMAND_PATTERN_MONO | COMMAND_TRANS_MONO); + uint8_t rop = voodoo->banshee_blt.command >> 24; -// bansheeblt_log("banshee_do_rectfill: size=%i,%i dst=%i,%i\n", voodoo->banshee_blt.dstSizeX, voodoo->banshee_blt.dstSizeY, voodoo->banshee_blt.dstX, voodoo->banshee_blt.dstY); -// bansheeblt_log("clipping: %i,%i -> %i,%i\n", clip->x_min, clip->y_min, clip->x_max, clip->y_max); -// bansheeblt_log("colorFore=%08x\n", voodoo->banshee_blt.colorFore); - for (voodoo->banshee_blt.cur_y = 0; voodoo->banshee_blt.cur_y < voodoo->banshee_blt.dstSizeY; voodoo->banshee_blt.cur_y++) - { - int dst_x = voodoo->banshee_blt.dstX; +#if 0 + bansheeblt_log("banshee_do_rectfill: size=%i,%i dst=%i,%i\n", voodoo->banshee_blt.dstSizeX, voodoo->banshee_blt.dstSizeY, voodoo->banshee_blt.dstX, voodoo->banshee_blt.dstY); + bansheeblt_log("clipping: %i,%i -> %i,%i\n", clip->x_min, clip->y_min, clip->x_max, clip->y_max); + bansheeblt_log("colorFore=%08x\n", voodoo->banshee_blt.colorFore); +#endif + for (voodoo->banshee_blt.cur_y = 0; voodoo->banshee_blt.cur_y < voodoo->banshee_blt.dstSizeY; voodoo->banshee_blt.cur_y++) { + int dst_x = voodoo->banshee_blt.dstX; - if (dst_y >= clip->y_min && dst_y < clip->y_max) - { - int pat_x = voodoo->banshee_blt.patoff_x + voodoo->banshee_blt.dstX; - uint8_t pattern_mask = pattern_mono[pat_y & 7]; - - for (voodoo->banshee_blt.cur_x = 0; voodoo->banshee_blt.cur_x < voodoo->banshee_blt.dstSizeX; voodoo->banshee_blt.cur_x++) - { - int pattern_trans = use_pattern_trans ? (pattern_mask & (1 << (7-(pat_x & 7)))) : 1; + if (dst_y >= clip->y_min && dst_y < clip->y_max) { + int pat_x = voodoo->banshee_blt.patoff_x + voodoo->banshee_blt.dstX; + uint8_t pattern_mask = pattern_mono[pat_y & 7]; - if (dst_x >= clip->x_min && dst_x < clip->x_max && pattern_trans) - PLOT(voodoo, dst_x, dst_y, pat_x, pat_y, pattern_mask, rop, voodoo->banshee_blt.colorFore, COLORKEY_32); + for (voodoo->banshee_blt.cur_x = 0; voodoo->banshee_blt.cur_x < voodoo->banshee_blt.dstSizeX; voodoo->banshee_blt.cur_x++) { + int pattern_trans = use_pattern_trans ? (pattern_mask & (1 << (7 - (pat_x & 7)))) : 1; - dst_x += (voodoo->banshee_blt.command & COMMAND_DX) ? -1 : 1; - pat_x += (voodoo->banshee_blt.command & COMMAND_DX) ? -1 : 1; - } - } - dst_y += (voodoo->banshee_blt.command & COMMAND_DY) ? -1 : 1; - if (!(voodoo->banshee_blt.commandExtra & CMDEXTRA_FORCE_PAT_ROW0)) - pat_y += (voodoo->banshee_blt.command & COMMAND_DY) ? -1 : 1; + if (dst_x >= clip->x_min && dst_x < clip->x_max && pattern_trans) + PLOT(voodoo, dst_x, dst_y, pat_x, pat_y, pattern_mask, rop, voodoo->banshee_blt.colorFore, COLORKEY_32); + + dst_x += (voodoo->banshee_blt.command & COMMAND_DX) ? -1 : 1; + pat_x += (voodoo->banshee_blt.command & COMMAND_DX) ? -1 : 1; + } } + dst_y += (voodoo->banshee_blt.command & COMMAND_DY) ? -1 : 1; + if (!(voodoo->banshee_blt.commandExtra & CMDEXTRA_FORCE_PAT_ROW0)) + pat_y += (voodoo->banshee_blt.command & COMMAND_DY) ? -1 : 1; + } - end_command(voodoo); + end_command(voodoo); } -static void do_screen_to_screen_line(voodoo_t *voodoo, uint8_t *src_p, int use_x_dir, int src_x, int src_tiled) +void +DECODE_YUYV422(uint32_t *buf, uint8_t *src) { - clip_t *clip = &voodoo->banshee_blt.clip[(voodoo->banshee_blt.command & COMMAND_CLIP_SEL) ? 1 : 0]; - int dst_y = voodoo->banshee_blt.dstY; - int pat_y = (voodoo->banshee_blt.commandExtra & CMDEXTRA_FORCE_PAT_ROW0) ? 0 : (voodoo->banshee_blt.patoff_y + voodoo->banshee_blt.dstY); - uint8_t *pattern_mono = (uint8_t *)voodoo->banshee_blt.colorPattern; - int use_pattern_trans = (voodoo->banshee_blt.command & (COMMAND_PATTERN_MONO | COMMAND_TRANS_MONO)) == - (COMMAND_PATTERN_MONO | COMMAND_TRANS_MONO); - uint8_t rop = voodoo->banshee_blt.command >> 24; - int src_colorkey; - - switch (voodoo->banshee_blt.srcFormat & SRC_FORMAT_COL_MASK) - { - case SRC_FORMAT_COL_8_BPP: - src_colorkey = COLORKEY_8; - break; - case SRC_FORMAT_COL_16_BPP: - src_colorkey = COLORKEY_16; - break; - default: - src_colorkey = COLORKEY_32; - break; - } -// bansheeblt_log("do_screen_to_screen_line: srcFormat=%08x dst=%08x\n", voodoo->banshee_blt.srcFormat, voodoo->banshee_blt.dstFormat); - if ((voodoo->banshee_blt.srcFormat & SRC_FORMAT_COL_MASK) == - (voodoo->banshee_blt.dstFormat & DST_FORMAT_COL_MASK)) - { - /*No conversion required*/ - if (dst_y >= clip->y_min && dst_y < clip->y_max) - { - int dst_x = voodoo->banshee_blt.dstX; - int pat_x = voodoo->banshee_blt.patoff_x + voodoo->banshee_blt.dstX; - uint8_t pattern_mask = pattern_mono[pat_y & 7]; + do { + int wp = 0; - for (voodoo->banshee_blt.cur_x = 0; voodoo->banshee_blt.cur_x < voodoo->banshee_blt.dstSizeX; voodoo->banshee_blt.cur_x++) - { - int pattern_trans = use_pattern_trans ? (pattern_mask & (1 << (7-(pat_x & 7)))) : 1; - int src_x_real = (src_x * voodoo->banshee_blt.src_bpp) >> 3; - - if (src_tiled) - src_x_real = (src_x_real & 127) + ((src_x_real >> 7) * 128*32); + uint8_t y1; + uint8_t y2; + int8_t Cr; + int8_t Cb; + int dR; + int dG; + int dB; + int r; + int g; + int b; - if (dst_x >= clip->x_min && dst_x < clip->x_max && pattern_trans) - { - switch (voodoo->banshee_blt.dstFormat & DST_FORMAT_COL_MASK) - { - case DST_FORMAT_COL_8_BPP: - { - uint32_t dst_addr = get_addr(voodoo, dst_x, dst_y, 0, 0);//(voodoo->banshee_blt.dstBaseAddr + dst_x + dst_y*voodoo->banshee_blt.dst_stride) & voodoo->fb_mask; - uint32_t src = src_p[src_x_real]; - uint32_t dest = voodoo->vram[dst_addr]; - uint32_t pattern = (voodoo->banshee_blt.command & COMMAND_PATTERN_MONO) ? - ((pattern_mask & (1 << (7-(pat_x & 7)))) ? voodoo->banshee_blt.colorFore : voodoo->banshee_blt.colorBack) : - voodoo->banshee_blt.colorPattern8[(pat_x & 7) + (pat_y & 7)*8]; + y1 = src[0]; + Cr = src[1] - 0x80; + y2 = src[2]; + Cb = src[3] - 0x80; - voodoo->vram[dst_addr] = MIX(voodoo, dest, src, pattern, COLORKEY_8, COLORKEY_8); - voodoo->changedvram[dst_addr >> 12] = changeframecount; - break; - } - case DST_FORMAT_COL_16_BPP: - { - uint32_t dst_addr = get_addr(voodoo, dst_x*2, dst_y, 0, 0);//dst_addr = (voodoo->banshee_blt.dstBaseAddr + dst_x*2 + dst_y*voodoo->banshee_blt.dst_stride) & voodoo->fb_mask; - uint32_t src = *(uint16_t *)&src_p[src_x_real]; - uint32_t dest = *(uint16_t *)&voodoo->vram[dst_addr]; - uint32_t pattern = (voodoo->banshee_blt.command & COMMAND_PATTERN_MONO) ? - ((pattern_mask & (1 << (7-(pat_x & 7)))) ? voodoo->banshee_blt.colorFore : voodoo->banshee_blt.colorBack) : - voodoo->banshee_blt.colorPattern16[(pat_x & 7) + (pat_y & 7)*8]; + dR = (359 * Cr) >> 8; + dG = (88 * Cb + 183 * Cr) >> 8; + dB = (453 * Cb) >> 8; - *(uint16_t *)&voodoo->vram[dst_addr] = MIX(voodoo, dest, src, pattern, COLORKEY_16, COLORKEY_16); - voodoo->changedvram[dst_addr >> 12] = changeframecount; - break; - } - case DST_FORMAT_COL_24_BPP: - { - uint32_t dst_addr = get_addr(voodoo, dst_x*3, dst_y, 0, 0);//dst_addr = (voodoo->banshee_blt.dstBaseAddr + dst_x*3 + dst_y*voodoo->banshee_blt.dst_stride) & voodoo->fb_mask; - uint32_t src = *(uint32_t *)&src_p[src_x_real]; - uint32_t dest = *(uint32_t *)&voodoo->vram[dst_addr]; - uint32_t pattern = (voodoo->banshee_blt.command & COMMAND_PATTERN_MONO) ? - ((pattern_mask & (1 << (7-(pat_x & 7)))) ? voodoo->banshee_blt.colorFore : voodoo->banshee_blt.colorBack) : - voodoo->banshee_blt.colorPattern24[(pat_x & 7) + (pat_y & 7)*8]; + r = y1 + dR; + r = CLAMP(r); + g = y1 - dG; + g = CLAMP(g); + b = y1 + dB; + b = CLAMP(b); + buf[wp++] = r | (g << 8) | (b << 16); - *(uint32_t *)&voodoo->vram[dst_addr] = (MIX(voodoo, dest, src, pattern, COLORKEY_32, COLORKEY_32) & 0xffffff) | (dest & 0xff000000); - voodoo->changedvram[dst_addr >> 12] = changeframecount; - break; - } - case DST_FORMAT_COL_32_BPP: - { - uint32_t dst_addr = get_addr(voodoo, dst_x*4, dst_y, 0, 0);//dst_addr = (voodoo->banshee_blt.dstBaseAddr + dst_x*4 + dst_y*voodoo->banshee_blt.dst_stride) & voodoo->fb_mask; - uint32_t src = *(uint32_t *)&src_p[src_x_real]; - uint32_t dest = *(uint32_t *)&voodoo->vram[dst_addr]; - uint32_t pattern = (voodoo->banshee_blt.command & COMMAND_PATTERN_MONO) ? - ((pattern_mask & (1 << (7-(pat_x & 7)))) ? voodoo->banshee_blt.colorFore : voodoo->banshee_blt.colorBack) : - voodoo->banshee_blt.colorPattern[(pat_x & 7) + (pat_y & 7)*8]; - - *(uint32_t *)&voodoo->vram[dst_addr] = MIX(voodoo, dest, src, pattern, COLORKEY_32, COLORKEY_32); - voodoo->changedvram[dst_addr >> 12] = changeframecount; - break; - } - } - } - if (use_x_dir) - { - src_x += (voodoo->banshee_blt.command & COMMAND_DX) ? -1 : 1; - dst_x += (voodoo->banshee_blt.command & COMMAND_DX) ? -1 : 1; - pat_x += (voodoo->banshee_blt.command & COMMAND_DX) ? -1 : 1; - } - else - { - src_x++; - dst_x++; - pat_x++; - } - } - } - voodoo->banshee_blt.srcY += (voodoo->banshee_blt.command & COMMAND_DY) ? -1 : 1; - voodoo->banshee_blt.dstY += (voodoo->banshee_blt.command & COMMAND_DY) ? -1 : 1; - } - else - { - /*Conversion required*/ - if (dst_y >= clip->y_min && dst_y < clip->y_max) - { -// int src_x = voodoo->banshee_blt.srcX; - int dst_x = voodoo->banshee_blt.dstX; - int pat_x = voodoo->banshee_blt.patoff_x + voodoo->banshee_blt.dstX; - uint8_t pattern_mask = pattern_mono[pat_y & 7]; - - for (voodoo->banshee_blt.cur_x = 0; voodoo->banshee_blt.cur_x < voodoo->banshee_blt.dstSizeX; voodoo->banshee_blt.cur_x++) - { - int pattern_trans = use_pattern_trans ? (pattern_mask & (1 << (7-(pat_x & 7)))) : 1; - int src_x_real = (src_x * voodoo->banshee_blt.src_bpp) >> 3; - - if (src_tiled) - src_x_real = (src_x_real & 127) + ((src_x_real >> 7) * 128*32); - - if (dst_x >= clip->x_min && dst_x < clip->x_max && pattern_trans) - { - uint32_t src_data = 0; - int transparent = 0; - - switch (voodoo->banshee_blt.srcFormat & SRC_FORMAT_COL_MASK) - { - case SRC_FORMAT_COL_1_BPP: - { - uint8_t src_byte = src_p[src_x_real]; - src_data = (src_byte & (0x80 >> (src_x & 7))) ? voodoo->banshee_blt.colorFore : voodoo->banshee_blt.colorBack; - if (voodoo->banshee_blt.command & COMMAND_TRANS_MONO) - transparent = !(src_byte & (0x80 >> (src_x & 7))); -// bansheeblt_log(" 1bpp src_byte=%02x src_x=%i src_data=%x transparent=%i\n", src_byte, src_x, src_data, transparent); - break; - } - case SRC_FORMAT_COL_8_BPP: - { - src_data = src_p[src_x_real]; - break; - } - case SRC_FORMAT_COL_16_BPP: - { - uint16_t src_16 = *(uint16_t *)&src_p[src_x_real]; - int r = (src_16 >> 11); - int g = (src_16 >> 5) & 0x3f; - int b = src_16 & 0x1f; - - r = (r << 3) | (r >> 2); - g = (g << 2) | (g >> 4); - b = (b << 3) | (b >> 2); - src_data = (r << 16) | (g << 8) | b; - break; - } - case SRC_FORMAT_COL_24_BPP: - { - src_data = *(uint32_t *)&src_p[src_x_real]; - break; - } - case SRC_FORMAT_COL_32_BPP: - { - src_data = *(uint32_t *)&src_p[src_x_real]; - break; - } - - default: - fatal("banshee_do_screen_to_screen_blt: unknown srcFormat %08x\n", voodoo->banshee_blt.srcFormat); - } - - if ((voodoo->banshee_blt.dstFormat & DST_FORMAT_COL_MASK) == DST_FORMAT_COL_16_BPP && - (voodoo->banshee_blt.srcFormat & SRC_FORMAT_COL_MASK) != SRC_FORMAT_COL_1_BPP) - { - int r = src_data >> 16; - int g = (src_data >> 8) & 0xff; - int b = src_data & 0xff; - - src_data = (b >> 3) | ((g >> 2) << 5) | ((r >> 3) << 11); - } - - if (!transparent) - PLOT(voodoo, dst_x, dst_y, pat_x, pat_y, pattern_mask, rop, src_data, src_colorkey); - } - if (use_x_dir) - { - src_x += (voodoo->banshee_blt.command & COMMAND_DX) ? -1 : 1; - dst_x += (voodoo->banshee_blt.command & COMMAND_DX) ? -1 : 1; - pat_x += (voodoo->banshee_blt.command & COMMAND_DX) ? -1 : 1; - } - else - { - src_x++; - dst_x++; - pat_x++; - } - } - } - voodoo->banshee_blt.srcY += (voodoo->banshee_blt.command & COMMAND_DY) ? -1 : 1; - voodoo->banshee_blt.dstY += (voodoo->banshee_blt.command & COMMAND_DY) ? -1 : 1; - } + r = y2 + dR; + r = CLAMP(r); + g = y2 - dG; + g = CLAMP(g); + b = y2 + dB; + b = CLAMP(b); + buf[wp++] = r | (g << 8) | (b << 16); + } while (0); } -static void banshee_do_screen_to_screen_blt(voodoo_t *voodoo) +void +DECODE_YUYV422_16BPP(uint16_t *buf, uint8_t *src) { -// bansheeblt_log("screen_to_screen: %08x %08x %08x\n", voodoo->banshee_blt.srcFormat, voodoo->banshee_blt.src_stride, voodoo->banshee_blt.src_stride_dest); -// return; - for (voodoo->banshee_blt.cur_y = 0; voodoo->banshee_blt.cur_y < voodoo->banshee_blt.dstSizeY; voodoo->banshee_blt.cur_y++) - { - uint32_t src_addr = get_addr(voodoo, 0, voodoo->banshee_blt.srcY, 1, voodoo->banshee_blt.src_stride_dest); -// if ((voodoo->banshee_blt.srcFormat & SRC_FORMAT_COL_MASK) == SRC_FORMAT_COL_1_BPP) -// bansheeblt_log(" srcY=%i src_addr=%08x\n", voodoo->banshee_blt.srcY, src_addr); - do_screen_to_screen_line(voodoo, &voodoo->vram[src_addr], 1, voodoo->banshee_blt.srcX, voodoo->banshee_blt.srcBaseAddr_tiled); - } - end_command(voodoo); + do { + int wp = 0; + + uint8_t y1; + uint8_t y2; + int8_t Cr; + int8_t Cb; + int dR; + int dG; + int dB; + int r; + int g; + int b; + + y1 = src[0]; + Cr = src[1] - 0x80; + y2 = src[2]; + Cb = src[3] - 0x80; + + dR = (359 * Cr) >> 8; + dG = (88 * Cb + 183 * Cr) >> 8; + dB = (453 * Cb) >> 8; + + r = y1 + dR; + r = CLAMP(r); + r >>= 3; + g = y1 - dG; + g = CLAMP(g); + g >>= 2; + b = y1 + dB; + b = CLAMP(b); + b >>= 3; + buf[wp++] = r | (g << 5) | (b << 11); + + r = y2 + dR; + r = CLAMP(r); + r >>= 3; + g = y2 - dG; + g = CLAMP(g); + g >>= 2; + b = y2 + dB; + b = CLAMP(b); + b >>= 3; + buf[wp++] = r | (g << 5) | (b << 11); + } while (0); } -static void banshee_do_host_to_screen_blt(voodoo_t *voodoo, int count, uint32_t data) +static void +do_screen_to_screen_line(voodoo_t *voodoo, uint8_t *src_p, int use_x_dir, int src_x, int src_tiled) { -// if (voodoo->banshee_blt.dstBaseAddr == 0xee5194) -// bansheeblt_log("banshee_do_host_to_screen_blt: data=%08x host_data_count=%i src_stride_dest=%i host_data_size_dest=%i\n", data, voodoo->banshee_blt.host_data_count, voodoo->banshee_blt.src_stride_dest, voodoo->banshee_blt.host_data_size_dest); + const clip_t *clip = &voodoo->banshee_blt.clip[(voodoo->banshee_blt.command & COMMAND_CLIP_SEL) ? 1 : 0]; + int dst_y = voodoo->banshee_blt.dstY; + int pat_y = (voodoo->banshee_blt.commandExtra & CMDEXTRA_FORCE_PAT_ROW0) ? 0 : (voodoo->banshee_blt.patoff_y + voodoo->banshee_blt.dstY); + const uint8_t *pattern_mono = (uint8_t *) voodoo->banshee_blt.colorPattern; + int use_pattern_trans = (voodoo->banshee_blt.command & (COMMAND_PATTERN_MONO | COMMAND_TRANS_MONO)) == (COMMAND_PATTERN_MONO | COMMAND_TRANS_MONO); + uint8_t rop = voodoo->banshee_blt.command >> 24; + int src_colorkey; - if (voodoo->banshee_blt.srcFormat & SRC_FORMAT_BYTE_SWIZZLE) - data = (data >> 24) | ((data >> 8) & 0xff00) | ((data << 8) & 0xff0000) | (data << 24); - if (voodoo->banshee_blt.srcFormat & SRC_FORMAT_WORD_SWIZZLE) - data = (data >> 16) | (data << 16); + switch (voodoo->banshee_blt.srcFormat & SRC_FORMAT_COL_MASK) { + case SRC_FORMAT_COL_8_BPP: + src_colorkey = COLORKEY_8; + break; + case SRC_FORMAT_COL_16_BPP: + src_colorkey = COLORKEY_16; + break; + default: + src_colorkey = COLORKEY_32; + break; + } +#if 0 + bansheeblt_log("do_screen_to_screen_line: srcFormat=%08x dst=%08x\n", voodoo->banshee_blt.srcFormat, voodoo->banshee_blt.dstFormat); +#endif + if ((voodoo->banshee_blt.srcFormat & SRC_FORMAT_COL_MASK) == (voodoo->banshee_blt.dstFormat & DST_FORMAT_COL_MASK)) { + /*No conversion required*/ + if (dst_y >= clip->y_min && dst_y < clip->y_max) { + int dst_x = voodoo->banshee_blt.dstX; + int pat_x = voodoo->banshee_blt.patoff_x + voodoo->banshee_blt.dstX; + uint8_t pattern_mask = pattern_mono[pat_y & 7]; - if ((voodoo->banshee_blt.srcFormat & SRC_FORMAT_PACKING_MASK) == SRC_FORMAT_PACKING_STRIDE) - { - int last_byte; + for (voodoo->banshee_blt.cur_x = 0; voodoo->banshee_blt.cur_x < voodoo->banshee_blt.dstSizeX; voodoo->banshee_blt.cur_x++) { + int pattern_trans = use_pattern_trans ? (pattern_mask & (1 << (7 - (pat_x & 7)))) : 1; + int src_x_real = (src_x * voodoo->banshee_blt.src_bpp) >> 3; - if ((voodoo->banshee_blt.srcFormat & SRC_FORMAT_COL_MASK) == SRC_FORMAT_COL_1_BPP) - last_byte = ((voodoo->banshee_blt.srcX & 31) + voodoo->banshee_blt.dstSizeX + 7) >> 3; - else - last_byte = (voodoo->banshee_blt.srcX & 3) + voodoo->banshee_blt.host_data_size_dest; + if (src_tiled) + src_x_real = (src_x_real & 127) + ((src_x_real >> 7) * 128 * 32); - *(uint32_t *)&voodoo->banshee_blt.host_data[voodoo->banshee_blt.host_data_count] = data; - voodoo->banshee_blt.host_data_count += 4; - if (voodoo->banshee_blt.host_data_count >= last_byte) - { -// bansheeblt_log(" %i %i srcX=%i srcFormat=%08x\n", voodoo->banshee_blt.cur_y, voodoo->banshee_blt.dstSizeY, voodoo->banshee_blt.srcX); - if (voodoo->banshee_blt.cur_y < voodoo->banshee_blt.dstSizeY) - { - if ((voodoo->banshee_blt.srcFormat & SRC_FORMAT_COL_MASK) == SRC_FORMAT_COL_1_BPP) - do_screen_to_screen_line(voodoo, &voodoo->banshee_blt.host_data[(voodoo->banshee_blt.srcX >> 3) & 3], 0, voodoo->banshee_blt.srcX & 7, 0); - else - do_screen_to_screen_line(voodoo, &voodoo->banshee_blt.host_data[voodoo->banshee_blt.srcX & 3], 0, 0, 0); - voodoo->banshee_blt.cur_y++; - if (voodoo->banshee_blt.cur_y == voodoo->banshee_blt.dstSizeY) - end_command(voodoo); - } - - if ((voodoo->banshee_blt.srcFormat & SRC_FORMAT_COL_MASK) == SRC_FORMAT_COL_1_BPP) - voodoo->banshee_blt.srcX += (voodoo->banshee_blt.srcFormat & SRC_FORMAT_STRIDE_MASK) << 3; - else - voodoo->banshee_blt.srcX += (voodoo->banshee_blt.srcFormat & SRC_FORMAT_STRIDE_MASK); - - voodoo->banshee_blt.host_data_count = 0; + if (dst_x >= clip->x_min && dst_x < clip->x_max && pattern_trans) { + switch (voodoo->banshee_blt.dstFormat & DST_FORMAT_COL_MASK) { + case DST_FORMAT_COL_8_BPP: + { + uint32_t dst_addr = get_addr(voodoo, dst_x, dst_y, 0, 0); //(voodoo->banshee_blt.dstBaseAddr + dst_x + dst_y*voodoo->banshee_blt.dst_stride) & voodoo->fb_mask; + uint32_t src = src_p[src_x_real]; + uint32_t dest = voodoo->vram[dst_addr]; + uint32_t pattern = (voodoo->banshee_blt.command & COMMAND_PATTERN_MONO) ? ((pattern_mask & (1 << (7 - (pat_x & 7)))) ? voodoo->banshee_blt.colorFore : voodoo->banshee_blt.colorBack) : voodoo->banshee_blt.colorPattern8[(pat_x & 7) + (pat_y & 7) * 8]; + + voodoo->vram[dst_addr] = MIX(voodoo, dest, src, pattern, COLORKEY_8, COLORKEY_8); + voodoo->changedvram[dst_addr >> 12] = changeframecount; + break; + } + case DST_FORMAT_COL_16_BPP: + { + uint32_t dst_addr = get_addr(voodoo, dst_x * 2, dst_y, 0, 0); // dst_addr = (voodoo->banshee_blt.dstBaseAddr + dst_x*2 + dst_y*voodoo->banshee_blt.dst_stride) & voodoo->fb_mask; + uint32_t src = *(uint16_t *) &src_p[src_x_real]; + uint32_t dest = *(uint16_t *) &voodoo->vram[dst_addr]; + uint32_t pattern = (voodoo->banshee_blt.command & COMMAND_PATTERN_MONO) ? ((pattern_mask & (1 << (7 - (pat_x & 7)))) ? voodoo->banshee_blt.colorFore : voodoo->banshee_blt.colorBack) : voodoo->banshee_blt.colorPattern16[(pat_x & 7) + (pat_y & 7) * 8]; + + *(uint16_t *) &voodoo->vram[dst_addr] = MIX(voodoo, dest, src, pattern, COLORKEY_16, COLORKEY_16); + voodoo->changedvram[dst_addr >> 12] = changeframecount; + break; + } + case DST_FORMAT_COL_24_BPP: + { + uint32_t dst_addr = get_addr(voodoo, dst_x * 3, dst_y, 0, 0); // dst_addr = (voodoo->banshee_blt.dstBaseAddr + dst_x*3 + dst_y*voodoo->banshee_blt.dst_stride) & voodoo->fb_mask; + uint32_t src = *(uint32_t *) &src_p[src_x_real]; + uint32_t dest = *(uint32_t *) &voodoo->vram[dst_addr]; + uint32_t pattern = (voodoo->banshee_blt.command & COMMAND_PATTERN_MONO) ? ((pattern_mask & (1 << (7 - (pat_x & 7)))) ? voodoo->banshee_blt.colorFore : voodoo->banshee_blt.colorBack) : voodoo->banshee_blt.colorPattern24[(pat_x & 7) + (pat_y & 7) * 8]; + + *(uint32_t *) &voodoo->vram[dst_addr] = (MIX(voodoo, dest, src, pattern, COLORKEY_32, COLORKEY_32) & 0xffffff) | (dest & 0xff000000); + voodoo->changedvram[dst_addr >> 12] = changeframecount; + break; + } + case DST_FORMAT_COL_32_BPP: + { + uint32_t dst_addr = get_addr(voodoo, dst_x * 4, dst_y, 0, 0); // dst_addr = (voodoo->banshee_blt.dstBaseAddr + dst_x*4 + dst_y*voodoo->banshee_blt.dst_stride) & voodoo->fb_mask; + uint32_t src = *(uint32_t *) &src_p[src_x_real]; + uint32_t dest = *(uint32_t *) &voodoo->vram[dst_addr]; + uint32_t pattern = (voodoo->banshee_blt.command & COMMAND_PATTERN_MONO) ? ((pattern_mask & (1 << (7 - (pat_x & 7)))) ? voodoo->banshee_blt.colorFore : voodoo->banshee_blt.colorBack) : voodoo->banshee_blt.colorPattern[(pat_x & 7) + (pat_y & 7) * 8]; + + *(uint32_t *) &voodoo->vram[dst_addr] = MIX(voodoo, dest, src, pattern, COLORKEY_32, COLORKEY_32); + voodoo->changedvram[dst_addr >> 12] = changeframecount; + break; + } + + default: + break; + } } - } - else - { - *(uint32_t *)&voodoo->banshee_blt.host_data[voodoo->banshee_blt.host_data_count] = data; - voodoo->banshee_blt.host_data_count += 4; - while (voodoo->banshee_blt.host_data_count >= voodoo->banshee_blt.src_stride_dest) - { - voodoo->banshee_blt.host_data_count -= voodoo->banshee_blt.src_stride_dest; - -// bansheeblt_log(" %i %i\n", voodoo->banshee_blt.cur_y, voodoo->banshee_blt.dstSizeY); - if (voodoo->banshee_blt.cur_y < voodoo->banshee_blt.dstSizeY) - { - do_screen_to_screen_line(voodoo, voodoo->banshee_blt.host_data, 0, 0, 0); - voodoo->banshee_blt.cur_y++; - if (voodoo->banshee_blt.cur_y == voodoo->banshee_blt.dstSizeY) - end_command(voodoo); - } - - if (voodoo->banshee_blt.host_data_count) - { -// bansheeblt_log(" remaining=%i\n", voodoo->banshee_blt.host_data_count); - *(uint32_t *)&voodoo->banshee_blt.host_data[0] = data >> (4-voodoo->banshee_blt.host_data_count)*8; - } + if (use_x_dir) { + src_x += (voodoo->banshee_blt.command & COMMAND_DX) ? -1 : 1; + dst_x += (voodoo->banshee_blt.command & COMMAND_DX) ? -1 : 1; + pat_x += (voodoo->banshee_blt.command & COMMAND_DX) ? -1 : 1; + } else { + src_x++; + dst_x++; + pat_x++; } + } } -} - -static void do_screen_to_screen_stretch_line(voodoo_t *voodoo,uint8_t *src_p, int src_x, int *src_y) -{ - clip_t *clip = &voodoo->banshee_blt.clip[(voodoo->banshee_blt.command & COMMAND_CLIP_SEL) ? 1 : 0]; -// int src_y = voodoo->banshee_blt.srcY; - int dst_y = voodoo->banshee_blt.dstY; - int pat_y = (voodoo->banshee_blt.commandExtra & CMDEXTRA_FORCE_PAT_ROW0) ? 0 : (voodoo->banshee_blt.patoff_y + voodoo->banshee_blt.dstY); - uint8_t *pattern_mono = (uint8_t *)voodoo->banshee_blt.colorPattern; - int use_pattern_trans = (voodoo->banshee_blt.command & (COMMAND_PATTERN_MONO | COMMAND_TRANS_MONO)) == - (COMMAND_PATTERN_MONO | COMMAND_TRANS_MONO); - uint32_t *colorPattern = voodoo->banshee_blt.colorPattern; - - //int error_y = voodoo->banshee_blt.dstSizeY / 2; - -/* bansheeblt_log("banshee_do_screen_to_screen_stretch_blt:\n"); - bansheeblt_log(" srcXY=%i,%i srcsizeXY=%i,%i\n", voodoo->banshee_blt.srcX, voodoo->banshee_blt.srcY, voodoo->banshee_blt.srcSizeX, voodoo->banshee_blt.srcSizeY); - bansheeblt_log(" dstXY=%i,%i dstsizeXY=%i,%i\n", voodoo->banshee_blt.dstX, voodoo->banshee_blt.dstY, voodoo->banshee_blt.dstSizeX, voodoo->banshee_blt.dstSizeY);*/ - if (dst_y >= clip->y_min && dst_y < clip->y_max) - { -// int src_x = voodoo->banshee_blt.srcX; - int dst_x = voodoo->banshee_blt.dstX; - int pat_x = voodoo->banshee_blt.patoff_x + voodoo->banshee_blt.dstX; - uint8_t pattern_mask = pattern_mono[pat_y & 7]; - int error_x = voodoo->banshee_blt.dstSizeX / 2; - -// bansheeblt_log(" Plot dest line %03i : src line %03i\n", dst_y, src_y); - for (voodoo->banshee_blt.cur_x = 0; voodoo->banshee_blt.cur_x < voodoo->banshee_blt.dstSizeX; voodoo->banshee_blt.cur_x++) - { - int pattern_trans = use_pattern_trans ? (pattern_mask & (1 << (7-(pat_x & 7)))) : 1; - - if (dst_x >= clip->x_min && dst_x < clip->x_max && pattern_trans) - { - switch (voodoo->banshee_blt.dstFormat & DST_FORMAT_COL_MASK) - { - case DST_FORMAT_COL_8_BPP: - { - uint32_t dst_addr = get_addr(voodoo, dst_x, dst_y, 0, 0);//(voodoo->banshee_blt.dstBaseAddr + dst_x + dst_y*voodoo->banshee_blt.dst_stride) & voodoo->fb_mask; - uint32_t src = src_p[src_x]; - uint32_t dest = voodoo->vram[dst_addr]; - uint32_t pattern = (voodoo->banshee_blt.command & COMMAND_PATTERN_MONO) ? - ((pattern_mask & (1 << (7-(pat_x & 7)))) ? voodoo->banshee_blt.colorFore : voodoo->banshee_blt.colorBack) : - colorPattern[(pat_x & 7) + (pat_y & 7)*8]; - - voodoo->vram[dst_addr] = MIX(voodoo, dest, src, pattern, COLORKEY_8, COLORKEY_8); -// bansheeblt_log("%i,%i : sdp=%02x,%02x,%02x res=%02x\n", voodoo->banshee_blt.cur_x, voodoo->banshee_blt.cur_y, src, dest, pattern, voodoo->vram[dst_addr]); - voodoo->changedvram[dst_addr >> 12] = changeframecount; - break; - } - case DST_FORMAT_COL_16_BPP: - { - uint32_t dst_addr = get_addr(voodoo, dst_x*2, dst_y, 0, 0);//(voodoo->banshee_blt.dstBaseAddr + dst_x*2 + dst_y*voodoo->banshee_blt.dst_stride) & voodoo->fb_mask; - uint32_t src = *(uint16_t *)&src_p[src_x*2]; - uint32_t dest = *(uint16_t *)&voodoo->vram[dst_addr]; - uint32_t pattern = (voodoo->banshee_blt.command & COMMAND_PATTERN_MONO) ? - ((pattern_mask & (1 << (7-(pat_x & 7)))) ? voodoo->banshee_blt.colorFore : voodoo->banshee_blt.colorBack) : - colorPattern[(pat_x & 7) + (pat_y & 7)*8]; - - *(uint16_t *)&voodoo->vram[dst_addr] = MIX(voodoo, dest, src, pattern, COLORKEY_16, COLORKEY_16); -// bansheeblt_log("%i,%i : sdp=%02x,%02x,%02x res=%02x\n", voodoo->banshee_blt.cur_x, voodoo->banshee_blt.cur_y, src, dest, pattern, *(uint16_t *)&voodoo->vram[dst_addr]); - voodoo->changedvram[dst_addr >> 12] = changeframecount; - break; - } - case DST_FORMAT_COL_24_BPP: - { - uint32_t dst_addr = get_addr(voodoo, dst_x*3, dst_y, 0, 0);//(voodoo->banshee_blt.dstBaseAddr + dst_x*3 + dst_y*voodoo->banshee_blt.dst_stride) & voodoo->fb_mask; - uint32_t src = *(uint32_t *)&src_p[src_x*3]; - uint32_t dest = *(uint32_t *)&voodoo->vram[dst_addr]; - uint32_t pattern = (voodoo->banshee_blt.command & COMMAND_PATTERN_MONO) ? - ((pattern_mask & (1 << (7-(pat_x & 7)))) ? voodoo->banshee_blt.colorFore : voodoo->banshee_blt.colorBack) : - colorPattern[(pat_x & 7) + (pat_y & 7)*8]; - - *(uint32_t *)&voodoo->vram[dst_addr] = (MIX(voodoo, dest, src, pattern, COLORKEY_32, COLORKEY_32) & 0xffffff) | (*(uint32_t *)&voodoo->vram[dst_addr] & 0xff000000); -// bansheeblt_log("%i,%i : sdp=%02x,%02x,%02x res=%02x\n", voodoo->banshee_blt.cur_x, voodoo->banshee_blt.cur_y, src, dest, pattern, voodoo->vram[dst_addr]); - voodoo->changedvram[dst_addr >> 12] = changeframecount; - break; - } - case DST_FORMAT_COL_32_BPP: - { - uint32_t dst_addr = get_addr(voodoo, dst_x*4, dst_y, 0, 0);//(voodoo->banshee_blt.dstBaseAddr + dst_x*4 + dst_y*voodoo->banshee_blt.dst_stride) & voodoo->fb_mask; - uint32_t src = *(uint32_t *)&src_p[src_x*4]; - uint32_t dest = *(uint32_t *)&voodoo->vram[dst_addr]; - uint32_t pattern = (voodoo->banshee_blt.command & COMMAND_PATTERN_MONO) ? - ((pattern_mask & (1 << (7-(pat_x & 7)))) ? voodoo->banshee_blt.colorFore : voodoo->banshee_blt.colorBack) : - colorPattern[(pat_x & 7) + (pat_y & 7)*8]; - - *(uint32_t *)&voodoo->vram[dst_addr] = MIX(voodoo, dest, src, pattern, COLORKEY_32, COLORKEY_32); -// bansheeblt_log("%i,%i : sdp=%02x,%02x,%02x res=%02x\n", voodoo->banshee_blt.cur_x, voodoo->banshee_blt.cur_y, src, dest, pattern, voodoo->vram[dst_addr]); - voodoo->changedvram[dst_addr >> 12] = changeframecount; - break; - } - } - } - - error_x -= voodoo->banshee_blt.srcSizeX; - while (error_x < 0) - { - error_x += voodoo->banshee_blt.dstSizeX; - src_x++; - } - dst_x++; - pat_x++; - } - } - - voodoo->banshee_blt.bres_error_0 -= voodoo->banshee_blt.srcSizeY; - while (voodoo->banshee_blt.bres_error_0 < 0) - { - voodoo->banshee_blt.bres_error_0 += voodoo->banshee_blt.dstSizeY; - if (src_y) - (*src_y) += (voodoo->banshee_blt.command & COMMAND_DY) ? -1 : 1; - } + voodoo->banshee_blt.srcY += (voodoo->banshee_blt.command & COMMAND_DY) ? -1 : 1; voodoo->banshee_blt.dstY += (voodoo->banshee_blt.command & COMMAND_DY) ? -1 : 1; -// pat_y += (voodoo->banshee_blt.command & COMMAND_DY) ? -1 : 1; -} + } else { + /*Conversion required*/ + if (dst_y >= clip->y_min && dst_y < clip->y_max) { +#if 0 + int src_x = voodoo->banshee_blt.srcX; +#endif + int dst_x = voodoo->banshee_blt.dstX; + int pat_x = voodoo->banshee_blt.patoff_x + voodoo->banshee_blt.dstX; + uint8_t pattern_mask = pattern_mono[pat_y & 7]; -static void banshee_do_screen_to_screen_stretch_blt(voodoo_t *voodoo) -{ -// bansheeblt_log("screen_to_screen: %08x %08x %08x\n", voodoo->banshee_blt.srcFormat, voodoo->banshee_blt.src_stride, voodoo->banshee_blt.src_stride_dest); -// return; - for (voodoo->banshee_blt.cur_y = 0; voodoo->banshee_blt.cur_y < voodoo->banshee_blt.dstSizeY; voodoo->banshee_blt.cur_y++) - { - uint32_t src_addr = get_addr(voodoo, 0, voodoo->banshee_blt.srcY, 1, voodoo->banshee_blt.src_stride_src);//(voodoo->banshee_blt.srcBaseAddr + voodoo->banshee_blt.srcY*voodoo->banshee_blt.src_stride_src) & voodoo->fb_mask; -// bansheeblt_log("scale_blit %i %08x %08x\n", voodoo->banshee_blt.cur_y, src_addr, voodoo->banshee_blt.command); -// if ((voodoo->banshee_blt.srcFormat & SRC_FORMAT_COL_MASK) == SRC_FORMAT_COL_1_BPP) -// bansheeblt_log(" srcY=%i src_addr=%08x\n", voodoo->banshee_blt.srcY, src_addr); - do_screen_to_screen_stretch_line(voodoo, &voodoo->vram[src_addr], voodoo->banshee_blt.srcX, &voodoo->banshee_blt.srcY); - } - end_command(voodoo); -} + for (voodoo->banshee_blt.cur_x = 0; voodoo->banshee_blt.cur_x < voodoo->banshee_blt.dstSizeX; voodoo->banshee_blt.cur_x++) { + int pattern_trans = use_pattern_trans ? (pattern_mask & (1 << (7 - (pat_x & 7)))) : 1; + int src_x_real = (src_x * voodoo->banshee_blt.src_bpp) >> 3; -static void banshee_do_host_to_screen_stretch_blt(voodoo_t *voodoo, int count, uint32_t data) -{ -// if (voodoo->banshee_blt.dstBaseAddr == 0xee5194) -// bansheeblt_log("banshee_do_host_to_screen_blt: data=%08x host_data_count=%i src_stride_dest=%i host_data_size_dest=%i\n", data, voodoo->banshee_blt.host_data_count, voodoo->banshee_blt.src_stride_dest, voodoo->banshee_blt.host_data_size_dest); + if (src_tiled) + src_x_real = (src_x_real & 127) + ((src_x_real >> 7) * 128 * 32); - if (voodoo->banshee_blt.srcFormat & SRC_FORMAT_BYTE_SWIZZLE) - data = (data >> 24) | ((data >> 8) & 0xff00) | ((data << 8) & 0xff0000) | (data << 24); - if (voodoo->banshee_blt.srcFormat & SRC_FORMAT_WORD_SWIZZLE) - data = (data >> 16) | (data << 16); + if (dst_x >= clip->x_min && dst_x < clip->x_max && pattern_trans) { + uint32_t src_data = 0; + uint32_t src_data_yuv = 0; /* Used in YUYV-to-RGB convesions. */ + int transparent = 0; - if ((voodoo->banshee_blt.srcFormat & SRC_FORMAT_PACKING_MASK) == SRC_FORMAT_PACKING_STRIDE) - { - int last_byte = (voodoo->banshee_blt.srcX & 3) + voodoo->banshee_blt.host_data_size_src; + switch (voodoo->banshee_blt.srcFormat & SRC_FORMAT_COL_MASK) { + case SRC_FORMAT_COL_1_BPP: + { + uint8_t src_byte = src_p[src_x_real]; + src_data = (src_byte & (0x80 >> (src_x & 7))) ? voodoo->banshee_blt.colorFore : voodoo->banshee_blt.colorBack; + if (voodoo->banshee_blt.command & COMMAND_TRANS_MONO) + transparent = !(src_byte & (0x80 >> (src_x & 7))); +#if 0 + bansheeblt_log(" 1bpp src_byte=%02x src_x=%i src_data=%x transparent=%i\n", src_byte, src_x, src_data, transparent); +#endif + break; + } + case SRC_FORMAT_COL_8_BPP: + { + src_data = src_p[src_x_real]; + break; + } + case SRC_FORMAT_COL_16_BPP: + { + uint16_t src_16 = *(uint16_t *) &src_p[src_x_real]; + int r = (src_16 >> 11); + int g = (src_16 >> 5) & 0x3f; + int b = src_16 & 0x1f; - *(uint32_t *)&voodoo->banshee_blt.host_data[voodoo->banshee_blt.host_data_count] = data; - voodoo->banshee_blt.host_data_count += 4; - if (voodoo->banshee_blt.host_data_count >= last_byte) - { -// bansheeblt_log(" %i %i srcX=%i srcFormat=%08x\n", voodoo->banshee_blt.cur_y, voodoo->banshee_blt.dstSizeY, voodoo->banshee_blt.srcX); - if (voodoo->banshee_blt.cur_y < voodoo->banshee_blt.dstSizeY) - { - if ((voodoo->banshee_blt.srcFormat & SRC_FORMAT_COL_MASK) == SRC_FORMAT_COL_1_BPP) - do_screen_to_screen_stretch_line(voodoo, &voodoo->banshee_blt.host_data[(voodoo->banshee_blt.srcX >> 3) & 3], voodoo->banshee_blt.srcX & 7, NULL); - else - do_screen_to_screen_stretch_line(voodoo, &voodoo->banshee_blt.host_data[voodoo->banshee_blt.srcX & 3], 0, NULL); - voodoo->banshee_blt.cur_y++; - if (voodoo->banshee_blt.cur_y == voodoo->banshee_blt.dstSizeY) - end_command(voodoo); - } + r = (r << 3) | (r >> 2); + g = (g << 2) | (g >> 4); + b = (b << 3) | (b >> 2); + src_data = (r << 16) | (g << 8) | b; + break; + } + case SRC_FORMAT_COL_24_BPP: + { + src_data = *(uint32_t *) &src_p[src_x_real]; + break; + } + case SRC_FORMAT_COL_32_BPP: + { + src_data = *(uint32_t *) &src_p[src_x_real]; + break; + } + case SRC_FORMAT_COL_YUYV: + { + src_data_yuv = *(uint32_t *) &src_p[src_x_real]; + break; + } - if ((voodoo->banshee_blt.srcFormat & SRC_FORMAT_COL_MASK) == SRC_FORMAT_COL_1_BPP) - voodoo->banshee_blt.srcX += (voodoo->banshee_blt.srcFormat & SRC_FORMAT_STRIDE_MASK) << 3; - else - voodoo->banshee_blt.srcX += (voodoo->banshee_blt.srcFormat & SRC_FORMAT_STRIDE_MASK); + default: + fatal("banshee_do_screen_to_screen_blt: unknown srcFormat %08x\n", voodoo->banshee_blt.srcFormat); + } - voodoo->banshee_blt.host_data_count = 0; + if ((voodoo->banshee_blt.dstFormat & DST_FORMAT_COL_MASK) == DST_FORMAT_COL_16_BPP && (voodoo->banshee_blt.srcFormat & SRC_FORMAT_COL_MASK) != SRC_FORMAT_COL_1_BPP) { + int r = src_data >> 16; + int g = (src_data >> 8) & 0xff; + int b = src_data & 0xff; + + src_data = (b >> 3) | ((g >> 2) << 5) | ((r >> 3) << 11); + } + + if ((voodoo->banshee_blt.srcFormat & SRC_FORMAT_COL_MASK) == SRC_FORMAT_COL_YUYV) { + if (((voodoo->banshee_blt.dstFormat & DST_FORMAT_COL_MASK) == DST_FORMAT_COL_24_BPP) || + ((voodoo->banshee_blt.dstFormat & DST_FORMAT_COL_MASK) == DST_FORMAT_COL_32_BPP)) { + uint32_t rgbcol[2] = { 0, 0 }; + DECODE_YUYV422(rgbcol, (uint8_t *) &src_data_yuv); + + bansheeblt_log("YUV -> 24 bpp or 32 bpp\n"); + + if (!transparent) { + PLOT(voodoo, dst_x, dst_y, pat_x, pat_y, pattern_mask, rop, rgbcol[0], src_colorkey); + } + + if (use_x_dir) { + dst_x += (voodoo->banshee_blt.command & COMMAND_DX) ? -1 : 1; + } else { + dst_x++; + } + + if (!transparent) { + PLOT(voodoo, dst_x, dst_y, pat_x, pat_y, pattern_mask, rop, rgbcol[1], src_colorkey); + } + } else if ((voodoo->banshee_blt.dstFormat & DST_FORMAT_COL_MASK) == DST_FORMAT_COL_16_BPP) { + uint32_t rgbcol = 0; + DECODE_YUYV422_16BPP((uint16_t *) &rgbcol, (uint8_t *) &src_data_yuv); + + bansheeblt_log("YUV -> 16 bpp\n"); + + if (!transparent) { + PLOT(voodoo, dst_x, dst_y, pat_x, pat_y, pattern_mask, rop, rgbcol & 0xffff, src_colorkey); + } + + if (use_x_dir) { + dst_x += (voodoo->banshee_blt.command & COMMAND_DX) ? -1 : 1; + } else { + dst_x++; + } + + if (!transparent) { + PLOT(voodoo, dst_x, dst_y, pat_x, pat_y, pattern_mask, rop, rgbcol >> 16, src_colorkey); + } + } else + fatal("banshee_do_screen_to_screen_blt: unknown dstFormat %08x\n", voodoo->banshee_blt.dstFormat); + } else { + if (!transparent) + PLOT(voodoo, dst_x, dst_y, pat_x, pat_y, pattern_mask, rop, src_data, src_colorkey); + } } + + if (use_x_dir) { + src_x += (voodoo->banshee_blt.command & COMMAND_DX) ? -1 : 1; + dst_x += (voodoo->banshee_blt.command & COMMAND_DX) ? -1 : 1; + pat_x += (voodoo->banshee_blt.command & COMMAND_DX) ? -1 : 1; + } else { + src_x++; + dst_x++; + pat_x++; + } + } } + voodoo->banshee_blt.srcY += (voodoo->banshee_blt.command & COMMAND_DY) ? -1 : 1; + voodoo->banshee_blt.dstY += (voodoo->banshee_blt.command & COMMAND_DY) ? -1 : 1; + } +} + +static void +banshee_do_screen_to_screen_blt(voodoo_t *voodoo) +{ +#if 0 + bansheeblt_log("screen_to_screen: %08x %08x %08x\n", voodoo->banshee_blt.srcFormat, voodoo->banshee_blt.src_stride, voodoo->banshee_blt.src_stride_dest); + return; +#endif + for (voodoo->banshee_blt.cur_y = 0; voodoo->banshee_blt.cur_y < voodoo->banshee_blt.dstSizeY; voodoo->banshee_blt.cur_y++) { + uint32_t src_addr = get_addr(voodoo, 0, voodoo->banshee_blt.srcY, 1, voodoo->banshee_blt.src_stride_dest); +#if 0 + if ((voodoo->banshee_blt.srcFormat & SRC_FORMAT_COL_MASK) == SRC_FORMAT_COL_1_BPP) + bansheeblt_log(" srcY=%i src_addr=%08x\n", voodoo->banshee_blt.srcY, src_addr); +#endif + do_screen_to_screen_line(voodoo, &voodoo->vram[src_addr], 1, voodoo->banshee_blt.srcX, voodoo->banshee_blt.srcBaseAddr_tiled); + } + end_command(voodoo); +} + +static void +banshee_do_host_to_screen_blt(voodoo_t *voodoo, UNUSED(int count), uint32_t data) +{ +#if 0 + if (voodoo->banshee_blt.dstBaseAddr == 0xee5194) + bansheeblt_log("banshee_do_host_to_screen_blt: data=%08x host_data_count=%i src_stride_dest=%i host_data_size_dest=%i\n", data, voodoo->banshee_blt.host_data_count, voodoo->banshee_blt.src_stride_dest, voodoo->banshee_blt.host_data_size_dest); +#endif + + if (voodoo->banshee_blt.srcFormat & SRC_FORMAT_BYTE_SWIZZLE) + data = (data >> 24) | ((data >> 8) & 0xff00) | ((data << 8) & 0xff0000) | (data << 24); + if (voodoo->banshee_blt.srcFormat & SRC_FORMAT_WORD_SWIZZLE) + data = (data >> 16) | (data << 16); + + if ((voodoo->banshee_blt.srcFormat & SRC_FORMAT_PACKING_MASK) == SRC_FORMAT_PACKING_STRIDE) { + int last_byte; + + if ((voodoo->banshee_blt.srcFormat & SRC_FORMAT_COL_MASK) == SRC_FORMAT_COL_1_BPP) + last_byte = ((voodoo->banshee_blt.srcX & 31) + voodoo->banshee_blt.dstSizeX + 7) >> 3; else - { - *(uint32_t *)&voodoo->banshee_blt.host_data[voodoo->banshee_blt.host_data_count] = data; - voodoo->banshee_blt.host_data_count += 4; - while (voodoo->banshee_blt.host_data_count >= voodoo->banshee_blt.src_stride_src) - { - voodoo->banshee_blt.host_data_count -= voodoo->banshee_blt.src_stride_src; + last_byte = (voodoo->banshee_blt.srcX & 3) + voodoo->banshee_blt.host_data_size_dest; -// bansheeblt_log(" %i %i\n", voodoo->banshee_blt.cur_y, voodoo->banshee_blt.dstSizeY); - if (voodoo->banshee_blt.cur_y < voodoo->banshee_blt.dstSizeY) - { - do_screen_to_screen_stretch_line(voodoo, voodoo->banshee_blt.host_data, 0, NULL); - voodoo->banshee_blt.cur_y++; - if (voodoo->banshee_blt.cur_y == voodoo->banshee_blt.dstSizeY) - end_command(voodoo); - } - - if (voodoo->banshee_blt.host_data_count) - { -// bansheeblt_log(" remaining=%i\n", voodoo->banshee_blt.host_data_count); - *(uint32_t *)&voodoo->banshee_blt.host_data[0] = data >> (4-voodoo->banshee_blt.host_data_count)*8; - } - } - } -} - -static void step_line(voodoo_t *voodoo) -{ - if (voodoo->banshee_blt.line_pix_pos == voodoo->banshee_blt.line_rep_cnt) - { - voodoo->banshee_blt.line_pix_pos = 0; - if (voodoo->banshee_blt.line_bit_pos == voodoo->banshee_blt.line_bit_mask_size) - voodoo->banshee_blt.line_bit_pos = 0; + *(uint32_t *) &voodoo->banshee_blt.host_data[voodoo->banshee_blt.host_data_count] = data; + voodoo->banshee_blt.host_data_count += 4; + if (voodoo->banshee_blt.host_data_count >= last_byte) { +#if 0 + bansheeblt_log(" %i %i srcX=%i srcFormat=%08x\n", voodoo->banshee_blt.cur_y, voodoo->banshee_blt.dstSizeY, voodoo->banshee_blt.srcX); +#endif + if (voodoo->banshee_blt.cur_y < voodoo->banshee_blt.dstSizeY) { + if ((voodoo->banshee_blt.srcFormat & SRC_FORMAT_COL_MASK) == SRC_FORMAT_COL_1_BPP) + do_screen_to_screen_line(voodoo, &voodoo->banshee_blt.host_data[(voodoo->banshee_blt.srcX >> 3) & 3], 0, voodoo->banshee_blt.srcX & 7, 0); else - voodoo->banshee_blt.line_bit_pos++; + do_screen_to_screen_line(voodoo, &voodoo->banshee_blt.host_data[voodoo->banshee_blt.srcX & 3], 0, 0, 0); + voodoo->banshee_blt.cur_y++; + if (voodoo->banshee_blt.cur_y == voodoo->banshee_blt.dstSizeY) + end_command(voodoo); + } + + if ((voodoo->banshee_blt.srcFormat & SRC_FORMAT_COL_MASK) == SRC_FORMAT_COL_1_BPP) + voodoo->banshee_blt.srcX += (voodoo->banshee_blt.srcFormat & SRC_FORMAT_STRIDE_MASK) << 3; + else + voodoo->banshee_blt.srcX += (voodoo->banshee_blt.srcFormat & SRC_FORMAT_STRIDE_MASK); + + voodoo->banshee_blt.host_data_count = 0; } - else - voodoo->banshee_blt.line_pix_pos++; + } else { + *(uint32_t *) &voodoo->banshee_blt.host_data[voodoo->banshee_blt.host_data_count] = data; + voodoo->banshee_blt.host_data_count += 4; + while (voodoo->banshee_blt.host_data_count >= voodoo->banshee_blt.src_stride_dest) { + voodoo->banshee_blt.host_data_count -= voodoo->banshee_blt.src_stride_dest; + +#if 0 + bansheeblt_log(" %i %i\n", voodoo->banshee_blt.cur_y, voodoo->banshee_blt.dstSizeY); +#endif + if (voodoo->banshee_blt.cur_y < voodoo->banshee_blt.dstSizeY) { + do_screen_to_screen_line(voodoo, voodoo->banshee_blt.host_data, 0, 0, 0); + voodoo->banshee_blt.cur_y++; + if (voodoo->banshee_blt.cur_y == voodoo->banshee_blt.dstSizeY) + end_command(voodoo); + } + + if (voodoo->banshee_blt.host_data_count) { +#if 0 + bansheeblt_log(" remaining=%i\n", voodoo->banshee_blt.host_data_count); +#endif + *(uint32_t *) &voodoo->banshee_blt.host_data[0] = data >> (4 - voodoo->banshee_blt.host_data_count) * 8; + } + } + } } - -static void banshee_do_line(voodoo_t *voodoo, int draw_last_pixel) +static void +do_screen_to_screen_stretch_line(voodoo_t *voodoo, uint8_t *src_p, int src_x, int *src_y) { - clip_t *clip = &voodoo->banshee_blt.clip[(voodoo->banshee_blt.command & COMMAND_CLIP_SEL) ? 1 : 0]; - uint8_t rop = voodoo->banshee_blt.command >> 24; - int dx = ABS(voodoo->banshee_blt.dstX - voodoo->banshee_blt.srcX); - int dy = ABS(voodoo->banshee_blt.dstY - voodoo->banshee_blt.srcY); - int x_inc = (voodoo->banshee_blt.dstX > voodoo->banshee_blt.srcX) ? 1 : -1; - int y_inc = (voodoo->banshee_blt.dstY > voodoo->banshee_blt.srcY) ? 1 : -1; - int x = voodoo->banshee_blt.srcX; - int y = voodoo->banshee_blt.srcY; - int error; - uint32_t stipple = (voodoo->banshee_blt.command & COMMAND_STIPPLE_LINE) ? - voodoo->banshee_blt.lineStipple : ~0; + const clip_t *clip = &voodoo->banshee_blt.clip[(voodoo->banshee_blt.command & COMMAND_CLIP_SEL) ? 1 : 0]; +#if 0 + int src_y = voodoo->banshee_blt.srcY; +#endif + int dst_y = voodoo->banshee_blt.dstY; + int pat_y = (voodoo->banshee_blt.commandExtra & CMDEXTRA_FORCE_PAT_ROW0) ? 0 : (voodoo->banshee_blt.patoff_y + voodoo->banshee_blt.dstY); + const uint8_t *pattern_mono = (uint8_t *) voodoo->banshee_blt.colorPattern; + int use_pattern_trans = (voodoo->banshee_blt.command & (COMMAND_PATTERN_MONO | COMMAND_TRANS_MONO)) == (COMMAND_PATTERN_MONO | COMMAND_TRANS_MONO); + const uint32_t *colorPattern = voodoo->banshee_blt.colorPattern; - if (dx > dy) /*X major*/ - { - error = dx/2; - while (x != voodoo->banshee_blt.dstX) - { - int mask = stipple & (1 << voodoo->banshee_blt.line_bit_pos); - int pattern_trans = (voodoo->banshee_blt.command & COMMAND_TRANS_MONO) ? mask : 1; - - if (y >= clip->y_min && y < clip->y_max && x >= clip->x_min && x < clip->x_max && pattern_trans) - PLOT_LINE(voodoo, x, y, rop, mask ? voodoo->banshee_blt.colorFore : voodoo->banshee_blt.colorBack, COLORKEY_32); +#if 0 + int error_y = voodoo->banshee_blt.dstSizeY / 2; - error -= dy; - if (error < 0) + bansheeblt_log("banshee_do_screen_to_screen_stretch_blt:\n"); + bansheeblt_log(" srcXY=%i,%i srcsizeXY=%i,%i\n", voodoo->banshee_blt.srcX, voodoo->banshee_blt.srcY, voodoo->banshee_blt.srcSizeX, voodoo->banshee_blt.srcSizeY); + bansheeblt_log(" dstXY=%i,%i dstsizeXY=%i,%i\n", voodoo->banshee_blt.dstX, voodoo->banshee_blt.dstY, voodoo->banshee_blt.dstSizeX, voodoo->banshee_blt.dstSizeY);*/ +#endif + if (dst_y >= clip->y_min && dst_y < clip->y_max) { +#if 0 + int src_x = voodoo->banshee_blt.srcX; +#endif + int dst_x = voodoo->banshee_blt.dstX; + int pat_x = voodoo->banshee_blt.patoff_x + voodoo->banshee_blt.dstX; + uint8_t pattern_mask = pattern_mono[pat_y & 7]; + int error_x = voodoo->banshee_blt.dstSizeX / 2; + +#if 0 + bansheeblt_log(" Plot dest line %03i : src line %03i\n", dst_y, src_y); +#endif + for (voodoo->banshee_blt.cur_x = 0; voodoo->banshee_blt.cur_x < voodoo->banshee_blt.dstSizeX; voodoo->banshee_blt.cur_x++) { + int pattern_trans = use_pattern_trans ? (pattern_mask & (1 << (7 - (pat_x & 7)))) : 1; + + if (dst_x >= clip->x_min && dst_x < clip->x_max && pattern_trans) { + switch (voodoo->banshee_blt.dstFormat & DST_FORMAT_COL_MASK) { + case DST_FORMAT_COL_8_BPP: { - error += dx; - y += y_inc; + uint32_t dst_addr = get_addr(voodoo, dst_x, dst_y, 0, 0); //(voodoo->banshee_blt.dstBaseAddr + dst_x + dst_y*voodoo->banshee_blt.dst_stride) & voodoo->fb_mask; + uint32_t src = src_p[src_x]; + uint32_t dest = voodoo->vram[dst_addr]; + uint32_t pattern = (voodoo->banshee_blt.command & COMMAND_PATTERN_MONO) ? ((pattern_mask & (1 << (7 - (pat_x & 7)))) ? voodoo->banshee_blt.colorFore : voodoo->banshee_blt.colorBack) : colorPattern[(pat_x & 7) + (pat_y & 7) * 8]; + + voodoo->vram[dst_addr] = MIX(voodoo, dest, src, pattern, COLORKEY_8, COLORKEY_8); +#if 0 + bansheeblt_log("%i,%i : sdp=%02x,%02x,%02x res=%02x\n", voodoo->banshee_blt.cur_x, voodoo->banshee_blt.cur_y, src, dest, pattern, voodoo->vram[dst_addr]); +#endif + voodoo->changedvram[dst_addr >> 12] = changeframecount; + break; } - x += x_inc; - step_line(voodoo); - } - } - else /*Y major*/ - { - error = dy/2; - while (y != voodoo->banshee_blt.dstY) - { - int mask = stipple & (1 << voodoo->banshee_blt.line_bit_pos); - int pattern_trans = (voodoo->banshee_blt.command & COMMAND_TRANS_MONO) ? mask : 1; - - if (y >= clip->y_min && y < clip->y_max && x >= clip->x_min && x < clip->x_max && pattern_trans) - PLOT_LINE(voodoo, x, y, rop, mask ? voodoo->banshee_blt.colorFore : voodoo->banshee_blt.colorBack, COLORKEY_32); - - error -= dx; - if (error < 0) + case DST_FORMAT_COL_16_BPP: { - error += dy; - x += x_inc; + uint32_t dst_addr = get_addr(voodoo, dst_x * 2, dst_y, 0, 0); //(voodoo->banshee_blt.dstBaseAddr + dst_x*2 + dst_y*voodoo->banshee_blt.dst_stride) & voodoo->fb_mask; + uint32_t src = *(uint16_t *) &src_p[src_x * 2]; + uint32_t dest = *(uint16_t *) &voodoo->vram[dst_addr]; + uint32_t pattern = (voodoo->banshee_blt.command & COMMAND_PATTERN_MONO) ? ((pattern_mask & (1 << (7 - (pat_x & 7)))) ? voodoo->banshee_blt.colorFore : voodoo->banshee_blt.colorBack) : colorPattern[(pat_x & 7) + (pat_y & 7) * 8]; + + *(uint16_t *) &voodoo->vram[dst_addr] = MIX(voodoo, dest, src, pattern, COLORKEY_16, COLORKEY_16); +#if 0 + bansheeblt_log("%i,%i : sdp=%02x,%02x,%02x res=%02x\n", voodoo->banshee_blt.cur_x, voodoo->banshee_blt.cur_y, src, dest, pattern, *(uint16_t *)&voodoo->vram[dst_addr]); +#endif + voodoo->changedvram[dst_addr >> 12] = changeframecount; + break; } - y += y_inc; - step_line(voodoo); - } - } - - if (draw_last_pixel) - { - int mask = stipple & (1 << voodoo->banshee_blt.line_bit_pos); - int pattern_trans = (voodoo->banshee_blt.command & COMMAND_TRANS_MONO) ? mask : 1; - - if (y >= clip->y_min && y < clip->y_max && x >= clip->x_min && x < clip->x_max && pattern_trans) - PLOT_LINE(voodoo, x, y, rop, mask ? voodoo->banshee_blt.colorFore : voodoo->banshee_blt.colorBack, COLORKEY_32); - } - - voodoo->banshee_blt.srcXY = (x & 0xffff) | (y << 16); - voodoo->banshee_blt.srcX = x; - voodoo->banshee_blt.srcY = y; -} - -static void banshee_polyfill_start(voodoo_t *voodoo) -{ - voodoo->banshee_blt.lx[0] = voodoo->banshee_blt.srcX; - voodoo->banshee_blt.ly[0] = voodoo->banshee_blt.srcY; - voodoo->banshee_blt.rx[0] = voodoo->banshee_blt.dstX; - voodoo->banshee_blt.ry[0] = voodoo->banshee_blt.dstY; - voodoo->banshee_blt.lx[1] = voodoo->banshee_blt.srcX; - voodoo->banshee_blt.ly[1] = voodoo->banshee_blt.srcY; - voodoo->banshee_blt.rx[1] = voodoo->banshee_blt.dstX; - voodoo->banshee_blt.ry[1] = voodoo->banshee_blt.dstY; - voodoo->banshee_blt.lx_cur = voodoo->banshee_blt.srcX; - voodoo->banshee_blt.rx_cur = voodoo->banshee_blt.dstX; -} - -static void banshee_polyfill_continue(voodoo_t *voodoo, uint32_t data) -{ - clip_t *clip = &voodoo->banshee_blt.clip[(voodoo->banshee_blt.command & COMMAND_CLIP_SEL) ? 1 : 0]; - uint8_t *pattern_mono = (uint8_t *)voodoo->banshee_blt.colorPattern; - int use_pattern_trans = (voodoo->banshee_blt.command & (COMMAND_PATTERN_MONO | COMMAND_TRANS_MONO)) == - (COMMAND_PATTERN_MONO | COMMAND_TRANS_MONO); - uint8_t rop = voodoo->banshee_blt.command >> 24; - int y = MAX(voodoo->banshee_blt.ly[0], voodoo->banshee_blt.ry[0]); - int y_end; - -// bansheeblt_log("Polyfill : data %08x\n", data); - - /*if r1.y>=l1.y, next vertex is left*/ - if (voodoo->banshee_blt.ry[1] >= voodoo->banshee_blt.ly[1]) - { - voodoo->banshee_blt.lx[1] = ((int32_t)(data << 19)) >> 19; - voodoo->banshee_blt.ly[1] = ((int32_t)(data << 3)) >> 19; - voodoo->banshee_blt.dx[0] = ABS(voodoo->banshee_blt.lx[1] - voodoo->banshee_blt.lx[0]); - voodoo->banshee_blt.dy[0] = ABS(voodoo->banshee_blt.ly[1] - voodoo->banshee_blt.ly[0]); - voodoo->banshee_blt.x_inc[0] = (voodoo->banshee_blt.lx[1] > voodoo->banshee_blt.lx[0]) ? 1 : -1; - voodoo->banshee_blt.error[0] = voodoo->banshee_blt.dy[0] / 2; - } - else - { - voodoo->banshee_blt.rx[1] = ((int32_t)(data << 19)) >> 19; - voodoo->banshee_blt.ry[1] = ((int32_t)(data << 3)) >> 19; - voodoo->banshee_blt.dx[1] = ABS(voodoo->banshee_blt.rx[1] - voodoo->banshee_blt.rx[0]); - voodoo->banshee_blt.dy[1] = ABS(voodoo->banshee_blt.ry[1] - voodoo->banshee_blt.ry[0]); - voodoo->banshee_blt.x_inc[1] = (voodoo->banshee_blt.rx[1] > voodoo->banshee_blt.rx[0]) ? 1 : -1; - voodoo->banshee_blt.error[1] = voodoo->banshee_blt.dy[1] / 2; - } - -/* bansheeblt_log(" verts now : %03i,%03i %03i,%03i\n", voodoo->banshee_blt.lx[0], voodoo->banshee_blt.ly[0], voodoo->banshee_blt.rx[0], voodoo->banshee_blt.ry[0]); - bansheeblt_log(" %03i,%03i %03i,%03i\n", voodoo->banshee_blt.lx[1], voodoo->banshee_blt.ly[1], voodoo->banshee_blt.rx[1], voodoo->banshee_blt.ry[1]); - bansheeblt_log(" left dx=%i dy=%i x_inc=%i error=%i\n", voodoo->banshee_blt.dx[0],voodoo->banshee_blt.dy[0],voodoo->banshee_blt.x_inc[0],voodoo->banshee_blt.error[0]); - bansheeblt_log(" right dx=%i dy=%i x_inc=%i error=%i\n", voodoo->banshee_blt.dx[1],voodoo->banshee_blt.dy[1],voodoo->banshee_blt.x_inc[1],voodoo->banshee_blt.error[1]);*/ - y_end = MIN(voodoo->banshee_blt.ly[1], voodoo->banshee_blt.ry[1]); -// bansheeblt_log("Polyfill : draw spans from %i-%i\n", y, y_end); - for (; y < y_end; y++) - { -// bansheeblt_log(" %i: %i %i\n", y, voodoo->banshee_blt.lx_cur, voodoo->banshee_blt.rx_cur); - /*Draw span from lx_cur to rx_cur*/ - if (y >= clip->y_min && y < clip->y_max) - { - int pat_y = (voodoo->banshee_blt.commandExtra & CMDEXTRA_FORCE_PAT_ROW0) ? 0 : (voodoo->banshee_blt.patoff_y + y); - uint8_t pattern_mask = pattern_mono[pat_y & 7]; - int x; - - for (x = voodoo->banshee_blt.lx_cur; x < voodoo->banshee_blt.rx_cur; x++) + case DST_FORMAT_COL_24_BPP: { - int pat_x = voodoo->banshee_blt.patoff_x + x; - int pattern_trans = use_pattern_trans ? (pattern_mask & (1 << (7-(pat_x & 7)))) : 1; + uint32_t dst_addr = get_addr(voodoo, dst_x * 3, dst_y, 0, 0); //(voodoo->banshee_blt.dstBaseAddr + dst_x*3 + dst_y*voodoo->banshee_blt.dst_stride) & voodoo->fb_mask; + uint32_t src = *(uint32_t *) &src_p[src_x * 3]; + uint32_t dest = *(uint32_t *) &voodoo->vram[dst_addr]; + uint32_t pattern = (voodoo->banshee_blt.command & COMMAND_PATTERN_MONO) ? ((pattern_mask & (1 << (7 - (pat_x & 7)))) ? voodoo->banshee_blt.colorFore : voodoo->banshee_blt.colorBack) : colorPattern[(pat_x & 7) + (pat_y & 7) * 8]; - if (x >= clip->x_min && x < clip->x_max && pattern_trans) - PLOT(voodoo, x, y, pat_x, pat_y, pattern_mask, rop, voodoo->banshee_blt.colorFore, COLORKEY_32); + *(uint32_t *) &voodoo->vram[dst_addr] = (MIX(voodoo, dest, src, pattern, COLORKEY_32, COLORKEY_32) & 0xffffff) | (*(uint32_t *) &voodoo->vram[dst_addr] & 0xff000000); +#if 0 + bansheeblt_log("%i,%i : sdp=%02x,%02x,%02x res=%02x\n", voodoo->banshee_blt.cur_x, voodoo->banshee_blt.cur_y, src, dest, pattern, voodoo->vram[dst_addr]); +#endif + voodoo->changedvram[dst_addr >> 12] = changeframecount; + break; } - } - - voodoo->banshee_blt.error[0] -= voodoo->banshee_blt.dx[0]; - while (voodoo->banshee_blt.error[0] < 0) - { - voodoo->banshee_blt.error[0] += voodoo->banshee_blt.dy[0]; - voodoo->banshee_blt.lx_cur += voodoo->banshee_blt.x_inc[0]; - } - voodoo->banshee_blt.error[1] -= voodoo->banshee_blt.dx[1]; - while (voodoo->banshee_blt.error[1] < 0) - { - voodoo->banshee_blt.error[1] += voodoo->banshee_blt.dy[1]; - voodoo->banshee_blt.rx_cur += voodoo->banshee_blt.x_inc[1]; - } - } + case DST_FORMAT_COL_32_BPP: + { + uint32_t dst_addr = get_addr(voodoo, dst_x * 4, dst_y, 0, 0); //(voodoo->banshee_blt.dstBaseAddr + dst_x*4 + dst_y*voodoo->banshee_blt.dst_stride) & voodoo->fb_mask; + uint32_t src = *(uint32_t *) &src_p[src_x * 4]; + uint32_t dest = *(uint32_t *) &voodoo->vram[dst_addr]; + uint32_t pattern = (voodoo->banshee_blt.command & COMMAND_PATTERN_MONO) ? ((pattern_mask & (1 << (7 - (pat_x & 7)))) ? voodoo->banshee_blt.colorFore : voodoo->banshee_blt.colorBack) : colorPattern[(pat_x & 7) + (pat_y & 7) * 8]; - if (voodoo->banshee_blt.ry[1] == voodoo->banshee_blt.ly[1]) - { - voodoo->banshee_blt.lx[0] = voodoo->banshee_blt.lx[1]; - voodoo->banshee_blt.ly[0] = voodoo->banshee_blt.ly[1]; - voodoo->banshee_blt.rx[0] = voodoo->banshee_blt.rx[1]; - voodoo->banshee_blt.ry[0] = voodoo->banshee_blt.ry[1]; - } - else if (voodoo->banshee_blt.ry[1] >= voodoo->banshee_blt.ly[1]) - { - voodoo->banshee_blt.lx[0] = voodoo->banshee_blt.lx[1]; - voodoo->banshee_blt.ly[0] = voodoo->banshee_blt.ly[1]; - } - else - { - voodoo->banshee_blt.rx[0] = voodoo->banshee_blt.rx[1]; - voodoo->banshee_blt.ry[0] = voodoo->banshee_blt.ry[1]; + *(uint32_t *) &voodoo->vram[dst_addr] = MIX(voodoo, dest, src, pattern, COLORKEY_32, COLORKEY_32); +#if 0 + bansheeblt_log("%i,%i : sdp=%02x,%02x,%02x res=%02x\n", voodoo->banshee_blt.cur_x, voodoo->banshee_blt.cur_y, src, dest, pattern, voodoo->vram[dst_addr]); +#endif + voodoo->changedvram[dst_addr >> 12] = changeframecount; + break; + } + + default: + break; + } + } + + error_x -= voodoo->banshee_blt.srcSizeX; + while (error_x < 0) { + error_x += voodoo->banshee_blt.dstSizeX; + src_x++; + } + dst_x++; + pat_x++; } + } + + voodoo->banshee_blt.bres_error_0 -= voodoo->banshee_blt.srcSizeY; + while (voodoo->banshee_blt.bres_error_0 < 0) { + voodoo->banshee_blt.bres_error_0 += voodoo->banshee_blt.dstSizeY; + if (src_y) + (*src_y) += (voodoo->banshee_blt.command & COMMAND_DY) ? -1 : 1; + } + voodoo->banshee_blt.dstY += (voodoo->banshee_blt.command & COMMAND_DY) ? -1 : 1; +#if 0 + pat_y += (voodoo->banshee_blt.command & COMMAND_DY) ? -1 : 1; +#endif + } -static void banshee_do_2d_blit(voodoo_t *voodoo, int count, uint32_t data) +static void +banshee_do_screen_to_screen_stretch_blt(voodoo_t *voodoo) { - switch (voodoo->banshee_blt.command & COMMAND_CMD_MASK) - { - case COMMAND_CMD_NOP: - break; - - case COMMAND_CMD_SCREEN_TO_SCREEN_BLT: - banshee_do_screen_to_screen_blt(voodoo); - break; - +#if 0 + bansheeblt_log("screen_to_screen: %08x %08x %08x\n", voodoo->banshee_blt.srcFormat, voodoo->banshee_blt.src_stride, voodoo->banshee_blt.src_stride_dest); + return; +#endif + for (voodoo->banshee_blt.cur_y = 0; voodoo->banshee_blt.cur_y < voodoo->banshee_blt.dstSizeY; voodoo->banshee_blt.cur_y++) { + uint32_t src_addr = get_addr(voodoo, 0, voodoo->banshee_blt.srcY, 1, voodoo->banshee_blt.src_stride_src); //(voodoo->banshee_blt.srcBaseAddr + voodoo->banshee_blt.srcY*voodoo->banshee_blt.src_stride_src) & voodoo->fb_mask; +#if 0 + + bansheeblt_log("scale_blit %i %08x %08x\n", voodoo->banshee_blt.cur_y, src_addr, voodoo->banshee_blt.command); + if ((voodoo->banshee_blt.srcFormat & SRC_FORMAT_COL_MASK) == SRC_FORMAT_COL_1_BPP) + bansheeblt_log(" srcY=%i src_addr=%08x\n", voodoo->banshee_blt.srcY, src_addr); +#endif + do_screen_to_screen_stretch_line(voodoo, &voodoo->vram[src_addr], voodoo->banshee_blt.srcX, &voodoo->banshee_blt.srcY); + } + end_command(voodoo); +} + +static void +banshee_do_host_to_screen_stretch_blt(voodoo_t *voodoo, UNUSED(int count), uint32_t data) +{ +#if 0 + if (voodoo->banshee_blt.dstBaseAddr == 0xee5194) + bansheeblt_log("banshee_do_host_to_screen_blt: data=%08x host_data_count=%i src_stride_dest=%i host_data_size_dest=%i\n", data, voodoo->banshee_blt.host_data_count, voodoo->banshee_blt.src_stride_dest, voodoo->banshee_blt.host_data_size_dest); +#endif + if (voodoo->banshee_blt.srcFormat & SRC_FORMAT_BYTE_SWIZZLE) + data = (data >> 24) | ((data >> 8) & 0xff00) | ((data << 8) & 0xff0000) | (data << 24); + if (voodoo->banshee_blt.srcFormat & SRC_FORMAT_WORD_SWIZZLE) + data = (data >> 16) | (data << 16); + + if ((voodoo->banshee_blt.srcFormat & SRC_FORMAT_PACKING_MASK) == SRC_FORMAT_PACKING_STRIDE) { + int last_byte = (voodoo->banshee_blt.srcX & 3) + voodoo->banshee_blt.host_data_size_src; + + *(uint32_t *) &voodoo->banshee_blt.host_data[voodoo->banshee_blt.host_data_count] = data; + voodoo->banshee_blt.host_data_count += 4; + if (voodoo->banshee_blt.host_data_count >= last_byte) { +#if 0 + bansheeblt_log(" %i %i srcX=%i srcFormat=%08x\n", voodoo->banshee_blt.cur_y, voodoo->banshee_blt.dstSizeY, voodoo->banshee_blt.srcX); +#endif + if (voodoo->banshee_blt.cur_y < voodoo->banshee_blt.dstSizeY) { + if ((voodoo->banshee_blt.srcFormat & SRC_FORMAT_COL_MASK) == SRC_FORMAT_COL_1_BPP) + do_screen_to_screen_stretch_line(voodoo, &voodoo->banshee_blt.host_data[(voodoo->banshee_blt.srcX >> 3) & 3], voodoo->banshee_blt.srcX & 7, NULL); + else + do_screen_to_screen_stretch_line(voodoo, &voodoo->banshee_blt.host_data[voodoo->banshee_blt.srcX & 3], 0, NULL); + voodoo->banshee_blt.cur_y++; + if (voodoo->banshee_blt.cur_y == voodoo->banshee_blt.dstSizeY) + end_command(voodoo); + } + + if ((voodoo->banshee_blt.srcFormat & SRC_FORMAT_COL_MASK) == SRC_FORMAT_COL_1_BPP) + voodoo->banshee_blt.srcX += (voodoo->banshee_blt.srcFormat & SRC_FORMAT_STRIDE_MASK) << 3; + else + voodoo->banshee_blt.srcX += (voodoo->banshee_blt.srcFormat & SRC_FORMAT_STRIDE_MASK); + + voodoo->banshee_blt.host_data_count = 0; + } + } else { + *(uint32_t *) &voodoo->banshee_blt.host_data[voodoo->banshee_blt.host_data_count] = data; + voodoo->banshee_blt.host_data_count += 4; + while (voodoo->banshee_blt.host_data_count >= voodoo->banshee_blt.src_stride_src) { + voodoo->banshee_blt.host_data_count -= voodoo->banshee_blt.src_stride_src; + +#if 0 + bansheeblt_log(" %i %i\n", voodoo->banshee_blt.cur_y, voodoo->banshee_blt.dstSizeY); +#endif + if (voodoo->banshee_blt.cur_y < voodoo->banshee_blt.dstSizeY) { + do_screen_to_screen_stretch_line(voodoo, voodoo->banshee_blt.host_data, 0, NULL); + voodoo->banshee_blt.cur_y++; + if (voodoo->banshee_blt.cur_y == voodoo->banshee_blt.dstSizeY) + end_command(voodoo); + } + + if (voodoo->banshee_blt.host_data_count) { +#if 0 + bansheeblt_log(" remaining=%i\n", voodoo->banshee_blt.host_data_count); +#endif + *(uint32_t *) &voodoo->banshee_blt.host_data[0] = data >> (4 - voodoo->banshee_blt.host_data_count) * 8; + } + } + } +} + +static void +step_line(voodoo_t *voodoo) +{ + if (voodoo->banshee_blt.line_pix_pos == voodoo->banshee_blt.line_rep_cnt) { + voodoo->banshee_blt.line_pix_pos = 0; + if (voodoo->banshee_blt.line_bit_pos == voodoo->banshee_blt.line_bit_mask_size) + voodoo->banshee_blt.line_bit_pos = 0; + else + voodoo->banshee_blt.line_bit_pos++; + } else + voodoo->banshee_blt.line_pix_pos++; +} + +static void +banshee_do_line(voodoo_t *voodoo, int draw_last_pixel) +{ + const clip_t *clip = &voodoo->banshee_blt.clip[(voodoo->banshee_blt.command & COMMAND_CLIP_SEL) ? 1 : 0]; + uint8_t rop = voodoo->banshee_blt.command >> 24; + int dx = ABS(voodoo->banshee_blt.dstX - voodoo->banshee_blt.srcX); + int dy = ABS(voodoo->banshee_blt.dstY - voodoo->banshee_blt.srcY); + int x_inc = (voodoo->banshee_blt.dstX > voodoo->banshee_blt.srcX) ? 1 : -1; + int y_inc = (voodoo->banshee_blt.dstY > voodoo->banshee_blt.srcY) ? 1 : -1; + int x = voodoo->banshee_blt.srcX; + int y = voodoo->banshee_blt.srcY; + int error; + uint32_t stipple = (voodoo->banshee_blt.command & COMMAND_STIPPLE_LINE) ? voodoo->banshee_blt.lineStipple : ~0; + + if (dx > dy) /*X major*/ + { + error = dx / 2; + while (x != voodoo->banshee_blt.dstX) { + int mask = stipple & (1 << voodoo->banshee_blt.line_bit_pos); + int pattern_trans = (voodoo->banshee_blt.command & COMMAND_TRANS_MONO) ? mask : 1; + + if (y >= clip->y_min && y < clip->y_max && x >= clip->x_min && x < clip->x_max && pattern_trans) + PLOT_LINE(voodoo, x, y, rop, mask ? voodoo->banshee_blt.colorFore : voodoo->banshee_blt.colorBack, COLORKEY_32); + + error -= dy; + if (error < 0) { + error += dx; + y += y_inc; + } + x += x_inc; + step_line(voodoo); + } + } else /*Y major*/ + { + error = dy / 2; + while (y != voodoo->banshee_blt.dstY) { + int mask = stipple & (1 << voodoo->banshee_blt.line_bit_pos); + int pattern_trans = (voodoo->banshee_blt.command & COMMAND_TRANS_MONO) ? mask : 1; + + if (y >= clip->y_min && y < clip->y_max && x >= clip->x_min && x < clip->x_max && pattern_trans) + PLOT_LINE(voodoo, x, y, rop, mask ? voodoo->banshee_blt.colorFore : voodoo->banshee_blt.colorBack, COLORKEY_32); + + error -= dx; + if (error < 0) { + error += dy; + x += x_inc; + } + y += y_inc; + step_line(voodoo); + } + } + + if (draw_last_pixel) { + int mask = stipple & (1 << voodoo->banshee_blt.line_bit_pos); + int pattern_trans = (voodoo->banshee_blt.command & COMMAND_TRANS_MONO) ? mask : 1; + + if (y >= clip->y_min && y < clip->y_max && x >= clip->x_min && x < clip->x_max && pattern_trans) + PLOT_LINE(voodoo, x, y, rop, mask ? voodoo->banshee_blt.colorFore : voodoo->banshee_blt.colorBack, COLORKEY_32); + } + + voodoo->banshee_blt.srcXY = (x & 0xffff) | (y << 16); + voodoo->banshee_blt.srcX = x; + voodoo->banshee_blt.srcY = y; +} + +static void +banshee_polyfill_start(voodoo_t *voodoo) +{ + voodoo->banshee_blt.lx[0] = voodoo->banshee_blt.srcX; + voodoo->banshee_blt.ly[0] = voodoo->banshee_blt.srcY; + voodoo->banshee_blt.rx[0] = voodoo->banshee_blt.dstX; + voodoo->banshee_blt.ry[0] = voodoo->banshee_blt.dstY; + voodoo->banshee_blt.lx[1] = voodoo->banshee_blt.srcX; + voodoo->banshee_blt.ly[1] = voodoo->banshee_blt.srcY; + voodoo->banshee_blt.rx[1] = voodoo->banshee_blt.dstX; + voodoo->banshee_blt.ry[1] = voodoo->banshee_blt.dstY; + voodoo->banshee_blt.lx_cur = voodoo->banshee_blt.srcX; + voodoo->banshee_blt.rx_cur = voodoo->banshee_blt.dstX; +} + +static void +banshee_polyfill_continue(voodoo_t *voodoo, uint32_t data) +{ + const clip_t *clip = &voodoo->banshee_blt.clip[(voodoo->banshee_blt.command & COMMAND_CLIP_SEL) ? 1 : 0]; + const uint8_t *pattern_mono = (uint8_t *) voodoo->banshee_blt.colorPattern; + int use_pattern_trans = (voodoo->banshee_blt.command & (COMMAND_PATTERN_MONO | COMMAND_TRANS_MONO)) == (COMMAND_PATTERN_MONO | COMMAND_TRANS_MONO); + uint8_t rop = voodoo->banshee_blt.command >> 24; + int y = MAX(voodoo->banshee_blt.ly[0], voodoo->banshee_blt.ry[0]); + int y_end; + +#if 0 + bansheeblt_log("Polyfill : data %08x\n", data); +#endif + /*if r1.y>=l1.y, next vertex is left*/ + if (voodoo->banshee_blt.ry[1] >= voodoo->banshee_blt.ly[1]) { + voodoo->banshee_blt.lx[1] = ((int32_t) (data << 19)) >> 19; + voodoo->banshee_blt.ly[1] = ((int32_t) (data << 3)) >> 19; + voodoo->banshee_blt.dx[0] = ABS(voodoo->banshee_blt.lx[1] - voodoo->banshee_blt.lx[0]); + voodoo->banshee_blt.dy[0] = ABS(voodoo->banshee_blt.ly[1] - voodoo->banshee_blt.ly[0]); + voodoo->banshee_blt.x_inc[0] = (voodoo->banshee_blt.lx[1] > voodoo->banshee_blt.lx[0]) ? 1 : -1; + voodoo->banshee_blt.error[0] = voodoo->banshee_blt.dy[0] / 2; + } else { + voodoo->banshee_blt.rx[1] = ((int32_t) (data << 19)) >> 19; + voodoo->banshee_blt.ry[1] = ((int32_t) (data << 3)) >> 19; + voodoo->banshee_blt.dx[1] = ABS(voodoo->banshee_blt.rx[1] - voodoo->banshee_blt.rx[0]); + voodoo->banshee_blt.dy[1] = ABS(voodoo->banshee_blt.ry[1] - voodoo->banshee_blt.ry[0]); + voodoo->banshee_blt.x_inc[1] = (voodoo->banshee_blt.rx[1] > voodoo->banshee_blt.rx[0]) ? 1 : -1; + voodoo->banshee_blt.error[1] = voodoo->banshee_blt.dy[1] / 2; + } + +#if 0 + bansheeblt_log(" verts now : %03i,%03i %03i,%03i\n", voodoo->banshee_blt.lx[0], voodoo->banshee_blt.ly[0], voodoo->banshee_blt.rx[0], voodoo->banshee_blt.ry[0]); + bansheeblt_log(" %03i,%03i %03i,%03i\n", voodoo->banshee_blt.lx[1], voodoo->banshee_blt.ly[1], voodoo->banshee_blt.rx[1], voodoo->banshee_blt.ry[1]); + bansheeblt_log(" left dx=%i dy=%i x_inc=%i error=%i\n", voodoo->banshee_blt.dx[0],voodoo->banshee_blt.dy[0],voodoo->banshee_blt.x_inc[0],voodoo->banshee_blt.error[0]); + bansheeblt_log(" right dx=%i dy=%i x_inc=%i error=%i\n", voodoo->banshee_blt.dx[1],voodoo->banshee_blt.dy[1],voodoo->banshee_blt.x_inc[1],voodoo->banshee_blt.error[1]); +#endif + y_end = MIN(voodoo->banshee_blt.ly[1], voodoo->banshee_blt.ry[1]); +#if 0 + bansheeblt_log("Polyfill : draw spans from %i-%i\n", y, y_end); +#endif + for (; y < y_end; y++) { +#if 0 + bansheeblt_log(" %i: %i %i\n", y, voodoo->banshee_blt.lx_cur, voodoo->banshee_blt.rx_cur); +#endif + /*Draw span from lx_cur to rx_cur*/ + if (y >= clip->y_min && y < clip->y_max) { + int pat_y = (voodoo->banshee_blt.commandExtra & CMDEXTRA_FORCE_PAT_ROW0) ? 0 : (voodoo->banshee_blt.patoff_y + y); + uint8_t pattern_mask = pattern_mono[pat_y & 7]; + + for (int x = voodoo->banshee_blt.lx_cur; x < voodoo->banshee_blt.rx_cur; x++) { + int pat_x = voodoo->banshee_blt.patoff_x + x; + int pattern_trans = use_pattern_trans ? (pattern_mask & (1 << (7 - (pat_x & 7)))) : 1; + + if (x >= clip->x_min && x < clip->x_max && pattern_trans) + PLOT(voodoo, x, y, pat_x, pat_y, pattern_mask, rop, voodoo->banshee_blt.colorFore, COLORKEY_32); + } + } + + voodoo->banshee_blt.error[0] -= voodoo->banshee_blt.dx[0]; + while (voodoo->banshee_blt.error[0] < 0) { + voodoo->banshee_blt.error[0] += voodoo->banshee_blt.dy[0]; + voodoo->banshee_blt.lx_cur += voodoo->banshee_blt.x_inc[0]; + } + voodoo->banshee_blt.error[1] -= voodoo->banshee_blt.dx[1]; + while (voodoo->banshee_blt.error[1] < 0) { + voodoo->banshee_blt.error[1] += voodoo->banshee_blt.dy[1]; + voodoo->banshee_blt.rx_cur += voodoo->banshee_blt.x_inc[1]; + } + } + + if (voodoo->banshee_blt.ry[1] == voodoo->banshee_blt.ly[1]) { + voodoo->banshee_blt.lx[0] = voodoo->banshee_blt.lx[1]; + voodoo->banshee_blt.ly[0] = voodoo->banshee_blt.ly[1]; + voodoo->banshee_blt.rx[0] = voodoo->banshee_blt.rx[1]; + voodoo->banshee_blt.ry[0] = voodoo->banshee_blt.ry[1]; + } else if (voodoo->banshee_blt.ry[1] >= voodoo->banshee_blt.ly[1]) { + voodoo->banshee_blt.lx[0] = voodoo->banshee_blt.lx[1]; + voodoo->banshee_blt.ly[0] = voodoo->banshee_blt.ly[1]; + } else { + voodoo->banshee_blt.rx[0] = voodoo->banshee_blt.rx[1]; + voodoo->banshee_blt.ry[0] = voodoo->banshee_blt.ry[1]; + } +} + +static void +banshee_do_2d_blit(voodoo_t *voodoo, int count, uint32_t data) +{ + switch (voodoo->banshee_blt.command & COMMAND_CMD_MASK) { + case COMMAND_CMD_NOP: + break; + + case COMMAND_CMD_SCREEN_TO_SCREEN_BLT: + banshee_do_screen_to_screen_blt(voodoo); + break; + + case COMMAND_CMD_SCREEN_TO_SCREEN_STRETCH_BLT: + banshee_do_screen_to_screen_stretch_blt(voodoo); + break; + + case COMMAND_CMD_HOST_TO_SCREEN_BLT: + banshee_do_host_to_screen_blt(voodoo, count, data); + break; + + case COMMAND_CMD_HOST_TO_SCREEN_STRETCH_BLT: + banshee_do_host_to_screen_stretch_blt(voodoo, count, data); + break; + + case COMMAND_CMD_RECTFILL: + banshee_do_rectfill(voodoo); + break; + + case COMMAND_CMD_LINE: + banshee_do_line(voodoo, 1); + break; + + case COMMAND_CMD_POLYLINE: + banshee_do_line(voodoo, 0); + break; + + default: + fatal("banshee_do_2d_blit: unknown command=%08x\n", voodoo->banshee_blt.command); + } +} + +void +voodoo_2d_reg_writel(voodoo_t *voodoo, uint32_t addr, uint32_t val) +{ +#if 0 + if ((addr & 0x1fc) != 0x80) + bansheeblt_log("2D reg write %03x %08x\n", addr & 0x1fc, val); +#endif + + switch (addr & 0x1fc) { + case 0x08: + voodoo->banshee_blt.clip0Min = val; + voodoo->banshee_blt.clip[0].x_min = val & 0xfff; + voodoo->banshee_blt.clip[0].y_min = (val >> 16) & 0xfff; + break; + case 0x0c: + voodoo->banshee_blt.clip0Max = val; + voodoo->banshee_blt.clip[0].x_max = val & 0xfff; + voodoo->banshee_blt.clip[0].y_max = (val >> 16) & 0xfff; + break; + case 0x10: + voodoo->banshee_blt.dstBaseAddr = val & 0xffffff; + voodoo->banshee_blt.dstBaseAddr_tiled = val & 0x80000000; + if (voodoo->banshee_blt.dstBaseAddr_tiled) + voodoo->banshee_blt.dst_stride = (voodoo->banshee_blt.dstFormat & DST_FORMAT_STRIDE_MASK) * 128 * 32; + else + voodoo->banshee_blt.dst_stride = voodoo->banshee_blt.dstFormat & DST_FORMAT_STRIDE_MASK; +#if 0 + bansheeblt_log("dstBaseAddr=%08x\n", val); +#endif + break; + case 0x14: + voodoo->banshee_blt.dstFormat = val; + if (voodoo->banshee_blt.dstBaseAddr_tiled) + voodoo->banshee_blt.dst_stride = (voodoo->banshee_blt.dstFormat & DST_FORMAT_STRIDE_MASK) * 128 * 32; + else + voodoo->banshee_blt.dst_stride = voodoo->banshee_blt.dstFormat & DST_FORMAT_STRIDE_MASK; +#if 0 + bansheeblt_log("dstFormat=%08x\n", val); +#endif + break; + + case 0x18: + voodoo->banshee_blt.srcColorkeyMin = val & 0xffffff; + break; + case 0x1c: + voodoo->banshee_blt.srcColorkeyMax = val & 0xffffff; + break; + case 0x20: + voodoo->banshee_blt.dstColorkeyMin = val & 0xffffff; + break; + case 0x24: + voodoo->banshee_blt.dstColorkeyMax = val & 0xffffff; + break; + + case 0x28: + voodoo->banshee_blt.bresError0 = val; + voodoo->banshee_blt.bres_error_0 = val & 0xffff; + break; + case 0x2c: + voodoo->banshee_blt.bresError1 = val; + voodoo->banshee_blt.bres_error_1 = val & 0xffff; + break; + + case 0x30: + voodoo->banshee_blt.rop = val; + voodoo->banshee_blt.rops[1] = val & 0xff; + voodoo->banshee_blt.rops[2] = (val >> 8) & 0xff; + voodoo->banshee_blt.rops[3] = (val >> 16) & 0xff; +#if 0 + bansheeblt_log("rop=%08x\n", val); +#endif + break; + case 0x34: + voodoo->banshee_blt.srcBaseAddr = val & 0xffffff; + voodoo->banshee_blt.srcBaseAddr_tiled = val & 0x80000000; + if (voodoo->banshee_blt.srcBaseAddr_tiled) + voodoo->banshee_blt.src_stride = (voodoo->banshee_blt.srcFormat & SRC_FORMAT_STRIDE_MASK) * 128 * 32; + else + voodoo->banshee_blt.src_stride = voodoo->banshee_blt.srcFormat & SRC_FORMAT_STRIDE_MASK; + update_src_stride(voodoo); +#if 0 + bansheeblt_log("srcBaseAddr=%08x\n", val); +#endif + break; + case 0x38: + voodoo->banshee_blt.commandExtra = val; +#if 0 + bansheeblt_log("commandExtra=%08x\n", val); +#endif + break; + case 0x3c: + voodoo->banshee_blt.lineStipple = val; + break; + case 0x40: + voodoo->banshee_blt.lineStyle = val; + voodoo->banshee_blt.line_rep_cnt = val & 0xff; + voodoo->banshee_blt.line_bit_mask_size = (val >> 8) & 0x1f; + voodoo->banshee_blt.line_pix_pos = (val >> 16) & 0xff; + voodoo->banshee_blt.line_bit_pos = (val >> 24) & 0x1f; + break; + case 0x44: + voodoo->banshee_blt.colorPattern[0] = val; +#if 0 + bansheeblt_log("colorPattern0=%08x\n", val); +#endif + voodoo->banshee_blt.colorPattern24[0] = val & 0xffffff; + voodoo->banshee_blt.colorPattern24[1] = (voodoo->banshee_blt.colorPattern24[1] & 0xffff00) | (val >> 24); + voodoo->banshee_blt.colorPattern16[0] = val & 0xffff; + voodoo->banshee_blt.colorPattern16[1] = (val >> 16) & 0xffff; + voodoo->banshee_blt.colorPattern8[0] = val & 0xff; + voodoo->banshee_blt.colorPattern8[1] = (val >> 8) & 0xff; + voodoo->banshee_blt.colorPattern8[2] = (val >> 16) & 0xff; + voodoo->banshee_blt.colorPattern8[3] = (val >> 24) & 0xff; + break; + case 0x48: + voodoo->banshee_blt.colorPattern[1] = val; +#if 0 + bansheeblt_log("colorPattern1=%08x\n", val); +#endif + voodoo->banshee_blt.colorPattern24[1] = (voodoo->banshee_blt.colorPattern24[1] & 0xff) | ((val & 0xffff) << 8); + voodoo->banshee_blt.colorPattern24[2] = (voodoo->banshee_blt.colorPattern24[2] & 0xff0000) | (val >> 16); + voodoo->banshee_blt.colorPattern16[2] = val & 0xffff; + voodoo->banshee_blt.colorPattern16[3] = (val >> 16) & 0xffff; + voodoo->banshee_blt.colorPattern8[4] = val & 0xff; + voodoo->banshee_blt.colorPattern8[5] = (val >> 8) & 0xff; + voodoo->banshee_blt.colorPattern8[6] = (val >> 16) & 0xff; + voodoo->banshee_blt.colorPattern8[7] = (val >> 24) & 0xff; + break; + case 0x4c: + voodoo->banshee_blt.clip1Min = val; + voodoo->banshee_blt.clip[1].x_min = val & 0xfff; + voodoo->banshee_blt.clip[1].y_min = (val >> 16) & 0xfff; + break; + case 0x50: + voodoo->banshee_blt.clip1Max = val; + voodoo->banshee_blt.clip[1].x_max = val & 0xfff; + voodoo->banshee_blt.clip[1].y_max = (val >> 16) & 0xfff; + break; + case 0x54: + voodoo->banshee_blt.srcFormat = val; + if (voodoo->banshee_blt.srcBaseAddr_tiled) + voodoo->banshee_blt.src_stride = (voodoo->banshee_blt.srcFormat & SRC_FORMAT_STRIDE_MASK) * 128 * 32; + else + voodoo->banshee_blt.src_stride = voodoo->banshee_blt.srcFormat & SRC_FORMAT_STRIDE_MASK; + update_src_stride(voodoo); + switch (voodoo->banshee_blt.srcFormat & SRC_FORMAT_COL_MASK) { + case SRC_FORMAT_COL_1_BPP: + voodoo->banshee_blt.src_bpp = 1; + break; + case SRC_FORMAT_COL_8_BPP: + voodoo->banshee_blt.src_bpp = 8; + break; + case SRC_FORMAT_COL_24_BPP: + voodoo->banshee_blt.src_bpp = 24; + break; + case SRC_FORMAT_COL_32_BPP: + case SRC_FORMAT_COL_YUYV: + voodoo->banshee_blt.src_bpp = 32; + break; + case SRC_FORMAT_COL_16_BPP: + default: + voodoo->banshee_blt.src_bpp = 16; + break; + } +#if 0 + bansheeblt_log("srcFormat=%08x\n", val); +#endif + break; + case 0x58: + voodoo->banshee_blt.srcSize = val; + voodoo->banshee_blt.srcSizeX = voodoo->banshee_blt.srcSize & 0x1fff; + voodoo->banshee_blt.srcSizeY = (voodoo->banshee_blt.srcSize >> 16) & 0x1fff; + update_src_stride(voodoo); +#if 0 + bansheeblt_log("srcSize=%08x\n", val); +#endif + break; + case 0x5c: + voodoo->banshee_blt.srcXY = val; + voodoo->banshee_blt.srcX = ((int32_t) (val << 19)) >> 19; + voodoo->banshee_blt.srcY = ((int32_t) (val << 3)) >> 19; + update_src_stride(voodoo); +#if 0 + bansheeblt_log("srcXY=%08x\n", val); +#endif + break; + case 0x60: + voodoo->banshee_blt.colorBack = val; + break; + case 0x64: + voodoo->banshee_blt.colorFore = val; + break; + case 0x68: + voodoo->banshee_blt.dstSize = val; + voodoo->banshee_blt.dstSizeX = voodoo->banshee_blt.dstSize & 0x1fff; + voodoo->banshee_blt.dstSizeY = (voodoo->banshee_blt.dstSize >> 16) & 0x1fff; + update_src_stride(voodoo); +#if 0 + bansheeblt_log("dstSize=%08x\n", val); +#endif + break; + case 0x6c: + voodoo->banshee_blt.dstXY = val; + voodoo->banshee_blt.dstX = ((int32_t) (val << 19)) >> 19; + voodoo->banshee_blt.dstY = ((int32_t) (val << 3)) >> 19; +#if 0 + bansheeblt_log("dstXY=%08x\n", val); +#endif + break; + case 0x70: + voodoo_wait_for_render_thread_idle(voodoo); + voodoo->banshee_blt.command = val; + voodoo->banshee_blt.rops[0] = val >> 24; +#if 0 + bansheeblt_log("command=%x %08x\n", voodoo->banshee_blt.command & COMMAND_CMD_MASK, val); +#endif + voodoo->banshee_blt.patoff_x = (val & COMMAND_PATOFF_X_MASK) >> COMMAND_PATOFF_X_SHIFT; + voodoo->banshee_blt.patoff_y = (val & COMMAND_PATOFF_Y_MASK) >> COMMAND_PATOFF_Y_SHIFT; + voodoo->banshee_blt.cur_x = 0; + voodoo->banshee_blt.cur_y = 0; + voodoo->banshee_blt.dstX = ((int32_t) (voodoo->banshee_blt.dstXY << 19)) >> 19; + voodoo->banshee_blt.dstY = ((int32_t) (voodoo->banshee_blt.dstXY << 3)) >> 19; + voodoo->banshee_blt.srcX = ((int32_t) (voodoo->banshee_blt.srcXY << 19)) >> 19; + voodoo->banshee_blt.srcY = ((int32_t) (voodoo->banshee_blt.srcXY << 3)) >> 19; + voodoo->banshee_blt.old_srcX = voodoo->banshee_blt.srcX; + voodoo->banshee_blt.host_data_remainder = 0; + voodoo->banshee_blt.host_data_count = 0; + switch (voodoo->banshee_blt.command & COMMAND_CMD_MASK) { + +#if 0 case COMMAND_CMD_SCREEN_TO_SCREEN_STRETCH_BLT: - banshee_do_screen_to_screen_stretch_blt(voodoo); - break; + if (voodoo->banshee_blt.bresError0 & BRES_ERROR_USE) + voodoo->banshee_blt.bres_error_0 = (int32_t)(int16_t)(voodoo->banshee_blt.bresError0 & BRES_ERROR_MASK); + else + voodoo->banshee_blt.bres_error_0 = voodoo->banshee_blt.dstSizeY / 2; + if (voodoo->banshee_blt.bresError1 & BRES_ERROR_USE) + voodoo->banshee_blt.bres_error_1 = (int32_t)(int16_t)(voodoo->banshee_blt.bresError1 & BRES_ERROR_MASK); + else + voodoo->banshee_blt.bres_error_1 = voodoo->banshee_blt.dstSizeX / 2; + + if (val & COMMAND_INITIATE) + banshee_do_2d_blit(voodoo, -1, 0); + break;*/ +#endif + + case COMMAND_CMD_POLYFILL: + if (val & COMMAND_INITIATE) { + voodoo->banshee_blt.dstXY = voodoo->banshee_blt.srcXY; + voodoo->banshee_blt.dstX = voodoo->banshee_blt.srcX; + voodoo->banshee_blt.dstY = voodoo->banshee_blt.srcY; + } + banshee_polyfill_start(voodoo); + break; + + default: + if (val & COMMAND_INITIATE) { + banshee_do_2d_blit(voodoo, -1, 0); +#if 0 + fatal("Initiate command!\n"); +#endif + } + break; + } + break; + + case 0x80: + case 0x84: + case 0x88: + case 0x8c: + case 0x90: + case 0x94: + case 0x98: + case 0x9c: + case 0xa0: + case 0xa4: + case 0xa8: + case 0xac: + case 0xb0: + case 0xb4: + case 0xb8: + case 0xbc: + case 0xc0: + case 0xc4: + case 0xc8: + case 0xcc: + case 0xd0: + case 0xd4: + case 0xd8: + case 0xdc: + case 0xe0: + case 0xe4: + case 0xe8: + case 0xec: + case 0xf0: + case 0xf4: + case 0xf8: + case 0xfc: +#if 0 + bansheeblt_log("launch %08x %08x %08x %08x\n", voodoo->banshee_blt.command, voodoo->banshee_blt.commandExtra, voodoo->banshee_blt.srcColorkeyMin, voodoo->banshee_blt.srcColorkeyMax); +#endif + switch (voodoo->banshee_blt.command & COMMAND_CMD_MASK) { + case COMMAND_CMD_SCREEN_TO_SCREEN_BLT: + voodoo->banshee_blt.srcXY = val; + voodoo->banshee_blt.srcX = ((int32_t) (val << 19)) >> 19; + voodoo->banshee_blt.srcY = ((int32_t) (val << 3)) >> 19; + banshee_do_screen_to_screen_blt(voodoo); + break; case COMMAND_CMD_HOST_TO_SCREEN_BLT: - banshee_do_host_to_screen_blt(voodoo, count, data); - break; - + banshee_do_2d_blit(voodoo, 32, val); + break; + case COMMAND_CMD_HOST_TO_SCREEN_STRETCH_BLT: - banshee_do_host_to_screen_stretch_blt(voodoo, count, data); - break; + banshee_do_2d_blit(voodoo, 32, val); + break; case COMMAND_CMD_RECTFILL: - banshee_do_rectfill(voodoo); - break; + voodoo->banshee_blt.dstXY = val; + voodoo->banshee_blt.dstX = ((int32_t) (val << 19)) >> 19; + voodoo->banshee_blt.dstY = ((int32_t) (val << 3)) >> 19; + banshee_do_rectfill(voodoo); + break; case COMMAND_CMD_LINE: - banshee_do_line(voodoo, 1); - break; + voodoo->banshee_blt.dstXY = val; + voodoo->banshee_blt.dstX = ((int32_t) (val << 19)) >> 19; + voodoo->banshee_blt.dstY = ((int32_t) (val << 3)) >> 19; + banshee_do_line(voodoo, 1); + break; case COMMAND_CMD_POLYLINE: - banshee_do_line(voodoo, 0); - break; + voodoo->banshee_blt.dstXY = val; + voodoo->banshee_blt.dstX = ((int32_t) (val << 19)) >> 19; + voodoo->banshee_blt.dstY = ((int32_t) (val << 3)) >> 19; + banshee_do_line(voodoo, 0); + break; + + case COMMAND_CMD_POLYFILL: + banshee_polyfill_continue(voodoo, val); + break; default: - fatal("banshee_do_2d_blit: unknown command=%08x\n", voodoo->banshee_blt.command); - } -} - -void voodoo_2d_reg_writel(voodoo_t *voodoo, uint32_t addr, uint32_t val) -{ -// /*if ((addr & 0x1fc) != 0x80) */bansheeblt_log("2D reg write %03x %08x\n", addr & 0x1fc, val); - switch (addr & 0x1fc) - { - case 0x08: - voodoo->banshee_blt.clip0Min = val; - voodoo->banshee_blt.clip[0].x_min = val & 0xfff; - voodoo->banshee_blt.clip[0].y_min = (val >> 16) & 0xfff; - break; - case 0x0c: - voodoo->banshee_blt.clip0Max = val; - voodoo->banshee_blt.clip[0].x_max = val & 0xfff; - voodoo->banshee_blt.clip[0].y_max = (val >> 16) & 0xfff; - break; - case 0x10: - voodoo->banshee_blt.dstBaseAddr = val & 0xffffff; - voodoo->banshee_blt.dstBaseAddr_tiled = val & 0x80000000; - if (voodoo->banshee_blt.dstBaseAddr_tiled) - voodoo->banshee_blt.dst_stride = (voodoo->banshee_blt.dstFormat & DST_FORMAT_STRIDE_MASK) * 128*32; - else - voodoo->banshee_blt.dst_stride = voodoo->banshee_blt.dstFormat & DST_FORMAT_STRIDE_MASK; -// bansheeblt_log("dstBaseAddr=%08x\n", val); - break; - case 0x14: - voodoo->banshee_blt.dstFormat = val; - if (voodoo->banshee_blt.dstBaseAddr_tiled) - voodoo->banshee_blt.dst_stride = (voodoo->banshee_blt.dstFormat & DST_FORMAT_STRIDE_MASK) * 128*32; - else - voodoo->banshee_blt.dst_stride = voodoo->banshee_blt.dstFormat & DST_FORMAT_STRIDE_MASK; -// bansheeblt_log("dstFormat=%08x\n", val); - break; - - case 0x18: - voodoo->banshee_blt.srcColorkeyMin = val & 0xffffff; - break; - case 0x1c: - voodoo->banshee_blt.srcColorkeyMax = val & 0xffffff; - break; - case 0x20: - voodoo->banshee_blt.dstColorkeyMin = val & 0xffffff; - break; - case 0x24: - voodoo->banshee_blt.dstColorkeyMax = val & 0xffffff; - break; - - case 0x28: - voodoo->banshee_blt.bresError0 = val; - voodoo->banshee_blt.bres_error_0 = val & 0xffff; - break; - case 0x2c: - voodoo->banshee_blt.bresError1 = val; - voodoo->banshee_blt.bres_error_1 = val & 0xffff; - break; - - case 0x30: - voodoo->banshee_blt.rop = val; - voodoo->banshee_blt.rops[1] = val & 0xff; - voodoo->banshee_blt.rops[2] = (val >> 8) & 0xff; - voodoo->banshee_blt.rops[3] = (val >> 16) & 0xff; -// bansheeblt_log("rop=%08x\n", val); - break; - case 0x34: - voodoo->banshee_blt.srcBaseAddr = val & 0xffffff; - voodoo->banshee_blt.srcBaseAddr_tiled = val & 0x80000000; - if (voodoo->banshee_blt.srcBaseAddr_tiled) - voodoo->banshee_blt.src_stride = (voodoo->banshee_blt.srcFormat & SRC_FORMAT_STRIDE_MASK) * 128*32; - else - voodoo->banshee_blt.src_stride = voodoo->banshee_blt.srcFormat & SRC_FORMAT_STRIDE_MASK; - update_src_stride(voodoo); -// bansheeblt_log("srcBaseAddr=%08x\n", val); - break; - case 0x38: - voodoo->banshee_blt.commandExtra = val; -// bansheeblt_log("commandExtra=%08x\n", val); - break; - case 0x3c: - voodoo->banshee_blt.lineStipple = val; - break; - case 0x40: - voodoo->banshee_blt.lineStyle = val; - voodoo->banshee_blt.line_rep_cnt = val & 0xff; - voodoo->banshee_blt.line_bit_mask_size = (val >> 8) & 0x1f; - voodoo->banshee_blt.line_pix_pos = (val >> 16) & 0xff; - voodoo->banshee_blt.line_bit_pos = (val >> 24) & 0x1f; - break; - case 0x44: - voodoo->banshee_blt.colorPattern[0] = val; -// bansheeblt_log("colorPattern0=%08x\n", val); - voodoo->banshee_blt.colorPattern24[0] = val & 0xffffff; - voodoo->banshee_blt.colorPattern24[1] = (voodoo->banshee_blt.colorPattern24[1] & 0xffff00) | (val >> 24); - voodoo->banshee_blt.colorPattern16[0] = val & 0xffff; - voodoo->banshee_blt.colorPattern16[1] = (val >> 16) & 0xffff; - voodoo->banshee_blt.colorPattern8[0] = val & 0xff; - voodoo->banshee_blt.colorPattern8[1] = (val >> 8) & 0xff; - voodoo->banshee_blt.colorPattern8[2] = (val >> 16) & 0xff; - voodoo->banshee_blt.colorPattern8[3] = (val >> 24) & 0xff; - break; - case 0x48: - voodoo->banshee_blt.colorPattern[1] = val; -// bansheeblt_log("colorPattern1=%08x\n", val); - voodoo->banshee_blt.colorPattern24[1] = (voodoo->banshee_blt.colorPattern24[1] & 0xff) | ((val & 0xffff) << 8); - voodoo->banshee_blt.colorPattern24[2] = (voodoo->banshee_blt.colorPattern24[2] & 0xff0000) | (val >> 16); - voodoo->banshee_blt.colorPattern16[2] = val & 0xffff; - voodoo->banshee_blt.colorPattern16[3] = (val >> 16) & 0xffff; - voodoo->banshee_blt.colorPattern8[4] = val & 0xff; - voodoo->banshee_blt.colorPattern8[5] = (val >> 8) & 0xff; - voodoo->banshee_blt.colorPattern8[6] = (val >> 16) & 0xff; - voodoo->banshee_blt.colorPattern8[7] = (val >> 24) & 0xff; - break; - case 0x4c: - voodoo->banshee_blt.clip1Min = val; - voodoo->banshee_blt.clip[1].x_min = val & 0xfff; - voodoo->banshee_blt.clip[1].y_min = (val >> 16) & 0xfff; - break; - case 0x50: - voodoo->banshee_blt.clip1Max = val; - voodoo->banshee_blt.clip[1].x_max = val & 0xfff; - voodoo->banshee_blt.clip[1].y_max = (val >> 16) & 0xfff; - break; - case 0x54: - voodoo->banshee_blt.srcFormat = val; - if (voodoo->banshee_blt.srcBaseAddr_tiled) - voodoo->banshee_blt.src_stride = (voodoo->banshee_blt.srcFormat & SRC_FORMAT_STRIDE_MASK) * 128*32; - else - voodoo->banshee_blt.src_stride = voodoo->banshee_blt.srcFormat & SRC_FORMAT_STRIDE_MASK; - update_src_stride(voodoo); - switch (voodoo->banshee_blt.srcFormat & SRC_FORMAT_COL_MASK) - { - case SRC_FORMAT_COL_1_BPP: - voodoo->banshee_blt.src_bpp = 1; - break; - case SRC_FORMAT_COL_8_BPP: - voodoo->banshee_blt.src_bpp = 8; - break; - case SRC_FORMAT_COL_24_BPP: - voodoo->banshee_blt.src_bpp = 24; - break; - case SRC_FORMAT_COL_32_BPP: - voodoo->banshee_blt.src_bpp = 32; - break; - case SRC_FORMAT_COL_16_BPP: default: - voodoo->banshee_blt.src_bpp = 16; - break; - } -// bansheeblt_log("srcFormat=%08x\n", val); - break; - case 0x58: - voodoo->banshee_blt.srcSize = val; - voodoo->banshee_blt.srcSizeX = voodoo->banshee_blt.srcSize & 0x1fff; - voodoo->banshee_blt.srcSizeY = (voodoo->banshee_blt.srcSize >> 16) & 0x1fff; - update_src_stride(voodoo); -// bansheeblt_log("srcSize=%08x\n", val); - break; - case 0x5c: - voodoo->banshee_blt.srcXY = val; - voodoo->banshee_blt.srcX = ((int32_t)(val << 19)) >> 19; - voodoo->banshee_blt.srcY = ((int32_t)(val << 3)) >> 19; - update_src_stride(voodoo); -// bansheeblt_log("srcXY=%08x\n", val); - break; - case 0x60: - voodoo->banshee_blt.colorBack = val; - break; - case 0x64: - voodoo->banshee_blt.colorFore = val; - break; - case 0x68: - voodoo->banshee_blt.dstSize = val; - voodoo->banshee_blt.dstSizeX = voodoo->banshee_blt.dstSize & 0x1fff; - voodoo->banshee_blt.dstSizeY = (voodoo->banshee_blt.dstSize >> 16) & 0x1fff; - update_src_stride(voodoo); -// bansheeblt_log("dstSize=%08x\n", val); - break; - case 0x6c: - voodoo->banshee_blt.dstXY = val; - voodoo->banshee_blt.dstX = ((int32_t)(val << 19)) >> 19; - voodoo->banshee_blt.dstY = ((int32_t)(val << 3)) >> 19; -// bansheeblt_log("dstXY=%08x\n", val); - break; - case 0x70: - voodoo_wait_for_render_thread_idle(voodoo); - voodoo->banshee_blt.command = val; - voodoo->banshee_blt.rops[0] = val >> 24; -// bansheeblt_log("command=%x %08x\n", voodoo->banshee_blt.command & COMMAND_CMD_MASK, val); - voodoo->banshee_blt.patoff_x = (val & COMMAND_PATOFF_X_MASK) >> COMMAND_PATOFF_X_SHIFT; - voodoo->banshee_blt.patoff_y = (val & COMMAND_PATOFF_Y_MASK) >> COMMAND_PATOFF_Y_SHIFT; - voodoo->banshee_blt.cur_x = 0; - voodoo->banshee_blt.cur_y = 0; - voodoo->banshee_blt.dstX = ((int32_t)(voodoo->banshee_blt.dstXY << 19)) >> 19; - voodoo->banshee_blt.dstY = ((int32_t)(voodoo->banshee_blt.dstXY << 3)) >> 19; - voodoo->banshee_blt.srcX = ((int32_t)(voodoo->banshee_blt.srcXY << 19)) >> 19; - voodoo->banshee_blt.srcY = ((int32_t)(voodoo->banshee_blt.srcXY << 3)) >> 19; - voodoo->banshee_blt.old_srcX = voodoo->banshee_blt.srcX; - voodoo->banshee_blt.host_data_remainder = 0; - voodoo->banshee_blt.host_data_count = 0; - switch (voodoo->banshee_blt.command & COMMAND_CMD_MASK) - { -/* case COMMAND_CMD_SCREEN_TO_SCREEN_STRETCH_BLT: - if (voodoo->banshee_blt.bresError0 & BRES_ERROR_USE) - voodoo->banshee_blt.bres_error_0 = (int32_t)(int16_t)(voodoo->banshee_blt.bresError0 & BRES_ERROR_MASK); - else - voodoo->banshee_blt.bres_error_0 = voodoo->banshee_blt.dstSizeY / 2; - if (voodoo->banshee_blt.bresError1 & BRES_ERROR_USE) - voodoo->banshee_blt.bres_error_1 = (int32_t)(int16_t)(voodoo->banshee_blt.bresError1 & BRES_ERROR_MASK); - else - voodoo->banshee_blt.bres_error_1 = voodoo->banshee_blt.dstSizeX / 2; - - if (val & COMMAND_INITIATE) - banshee_do_2d_blit(voodoo, -1, 0); - break;*/ - - case COMMAND_CMD_POLYFILL: - if (val & COMMAND_INITIATE) - { - voodoo->banshee_blt.dstXY = voodoo->banshee_blt.srcXY; - voodoo->banshee_blt.dstX = voodoo->banshee_blt.srcX; - voodoo->banshee_blt.dstY = voodoo->banshee_blt.srcY; - } - banshee_polyfill_start(voodoo); - break; - - default: - if (val & COMMAND_INITIATE) - { - banshee_do_2d_blit(voodoo, -1, 0); - // fatal("Initiate command!\n"); - } - break; - } - break; - - case 0x80: case 0x84: case 0x88: case 0x8c: - case 0x90: case 0x94: case 0x98: case 0x9c: - case 0xa0: case 0xa4: case 0xa8: case 0xac: - case 0xb0: case 0xb4: case 0xb8: case 0xbc: - case 0xc0: case 0xc4: case 0xc8: case 0xcc: - case 0xd0: case 0xd4: case 0xd8: case 0xdc: - case 0xe0: case 0xe4: case 0xe8: case 0xec: - case 0xf0: case 0xf4: case 0xf8: case 0xfc: -// bansheeblt_log("launch %08x %08x %08x %08x\n", voodoo->banshee_blt.command, voodoo->banshee_blt.commandExtra, voodoo->banshee_blt.srcColorkeyMin, voodoo->banshee_blt.srcColorkeyMax); - switch (voodoo->banshee_blt.command & COMMAND_CMD_MASK) - { - case COMMAND_CMD_SCREEN_TO_SCREEN_BLT: - voodoo->banshee_blt.srcXY = val; - voodoo->banshee_blt.srcX = ((int32_t)(val << 19)) >> 19; - voodoo->banshee_blt.srcY = ((int32_t)(val << 3)) >> 19; - banshee_do_screen_to_screen_blt(voodoo); - break; - - case COMMAND_CMD_HOST_TO_SCREEN_BLT: - banshee_do_2d_blit(voodoo, 32, val); - break; - - case COMMAND_CMD_HOST_TO_SCREEN_STRETCH_BLT: - banshee_do_2d_blit(voodoo, 32, val); - break; - - case COMMAND_CMD_RECTFILL: - voodoo->banshee_blt.dstXY = val; - voodoo->banshee_blt.dstX = ((int32_t)(val << 19)) >> 19; - voodoo->banshee_blt.dstY = ((int32_t)(val << 3)) >> 19; - banshee_do_rectfill(voodoo); - break; - - case COMMAND_CMD_LINE: - voodoo->banshee_blt.dstXY = val; - voodoo->banshee_blt.dstX = ((int32_t)(val << 19)) >> 19; - voodoo->banshee_blt.dstY = ((int32_t)(val << 3)) >> 19; - banshee_do_line(voodoo, 1); - break; - - case COMMAND_CMD_POLYLINE: - voodoo->banshee_blt.dstXY = val; - voodoo->banshee_blt.dstX = ((int32_t)(val << 19)) >> 19; - voodoo->banshee_blt.dstY = ((int32_t)(val << 3)) >> 19; - banshee_do_line(voodoo, 0); - break; - - case COMMAND_CMD_POLYFILL: - banshee_polyfill_continue(voodoo, val); - break; - - default: - fatal("launch area write, command=%08x\n", voodoo->banshee_blt.command); - } - break; - - case 0x100: case 0x104: case 0x108: case 0x10c: - case 0x110: case 0x114: case 0x118: case 0x11c: - case 0x120: case 0x124: case 0x128: case 0x12c: - case 0x130: case 0x134: case 0x138: case 0x13c: - case 0x140: case 0x144: case 0x148: case 0x14c: - case 0x150: case 0x154: case 0x158: case 0x15c: - case 0x160: case 0x164: case 0x168: case 0x16c: - case 0x170: case 0x174: case 0x178: case 0x17c: - case 0x180: case 0x184: case 0x188: case 0x18c: - case 0x190: case 0x194: case 0x198: case 0x19c: - case 0x1a0: case 0x1a4: case 0x1a8: case 0x1ac: - case 0x1b0: case 0x1b4: case 0x1b8: case 0x1bc: - case 0x1c0: case 0x1c4: case 0x1c8: case 0x1cc: - case 0x1d0: case 0x1d4: case 0x1d8: case 0x1dc: - case 0x1e0: case 0x1e4: case 0x1e8: case 0x1ec: - case 0x1f0: case 0x1f4: case 0x1f8: case 0x1fc: - voodoo->banshee_blt.colorPattern[(addr >> 2) & 63] = val; - if ((addr & 0x1fc) < 0x1c0) - { - int base_addr = (addr & 0xfc) / 0xc; - uintptr_t src_p = (uintptr_t)&voodoo->banshee_blt.colorPattern[base_addr * 3]; - int col24 = base_addr * 4; - - voodoo->banshee_blt.colorPattern24[col24] = *(uint32_t *)src_p & 0xffffff; - voodoo->banshee_blt.colorPattern24[col24 + 1] = *(uint32_t *)(src_p + 3) & 0xffffff; - voodoo->banshee_blt.colorPattern24[col24 + 2] = *(uint32_t *)(src_p + 6) & 0xffffff; - voodoo->banshee_blt.colorPattern24[col24 + 3] = *(uint32_t *)(src_p + 9) & 0xffffff; - } - if ((addr & 0x1fc) < 0x180) - { - voodoo->banshee_blt.colorPattern16[(addr >> 1) & 62] = val & 0xffff; - voodoo->banshee_blt.colorPattern16[((addr >> 1) & 62) + 1] = (val >> 16) & 0xffff; - } - if ((addr & 0x1fc) < 0x140) - { - voodoo->banshee_blt.colorPattern8[addr & 60] = val & 0xff; - voodoo->banshee_blt.colorPattern8[(addr & 60) + 1] = (val >> 8) & 0xff; - voodoo->banshee_blt.colorPattern8[(addr & 60) + 2] = (val >> 16) & 0xff; - voodoo->banshee_blt.colorPattern8[(addr & 60) + 3] = (val >> 24) & 0xff; - } -// bansheeblt_log("colorPattern%02x=%08x\n", (addr >> 2) & 63, val); - break; - - default: - fatal("Unknown 2D reg write %03x %08x\n", addr & 0x1fc, val); - } + fatal("launch area write, command=%08x\n", voodoo->banshee_blt.command); + } + break; + + case 0x100: + case 0x104: + case 0x108: + case 0x10c: + case 0x110: + case 0x114: + case 0x118: + case 0x11c: + case 0x120: + case 0x124: + case 0x128: + case 0x12c: + case 0x130: + case 0x134: + case 0x138: + case 0x13c: + case 0x140: + case 0x144: + case 0x148: + case 0x14c: + case 0x150: + case 0x154: + case 0x158: + case 0x15c: + case 0x160: + case 0x164: + case 0x168: + case 0x16c: + case 0x170: + case 0x174: + case 0x178: + case 0x17c: + case 0x180: + case 0x184: + case 0x188: + case 0x18c: + case 0x190: + case 0x194: + case 0x198: + case 0x19c: + case 0x1a0: + case 0x1a4: + case 0x1a8: + case 0x1ac: + case 0x1b0: + case 0x1b4: + case 0x1b8: + case 0x1bc: + case 0x1c0: + case 0x1c4: + case 0x1c8: + case 0x1cc: + case 0x1d0: + case 0x1d4: + case 0x1d8: + case 0x1dc: + case 0x1e0: + case 0x1e4: + case 0x1e8: + case 0x1ec: + case 0x1f0: + case 0x1f4: + case 0x1f8: + case 0x1fc: + voodoo->banshee_blt.colorPattern[(addr >> 2) & 63] = val; + if ((addr & 0x1fc) < 0x1c0) { + int base_addr = (addr & 0xfc) / 0xc; + uintptr_t src_p = (uintptr_t) &voodoo->banshee_blt.colorPattern[base_addr * 3]; + int col24 = base_addr * 4; + + voodoo->banshee_blt.colorPattern24[col24] = *(uint32_t *) src_p & 0xffffff; + voodoo->banshee_blt.colorPattern24[col24 + 1] = *(uint32_t *) (src_p + 3) & 0xffffff; + voodoo->banshee_blt.colorPattern24[col24 + 2] = *(uint32_t *) (src_p + 6) & 0xffffff; + voodoo->banshee_blt.colorPattern24[col24 + 3] = *(uint32_t *) (src_p + 9) & 0xffffff; + } + if ((addr & 0x1fc) < 0x180) { + voodoo->banshee_blt.colorPattern16[(addr >> 1) & 62] = val & 0xffff; + voodoo->banshee_blt.colorPattern16[((addr >> 1) & 62) + 1] = (val >> 16) & 0xffff; + } + if ((addr & 0x1fc) < 0x140) { + voodoo->banshee_blt.colorPattern8[addr & 60] = val & 0xff; + voodoo->banshee_blt.colorPattern8[(addr & 60) + 1] = (val >> 8) & 0xff; + voodoo->banshee_blt.colorPattern8[(addr & 60) + 2] = (val >> 16) & 0xff; + voodoo->banshee_blt.colorPattern8[(addr & 60) + 3] = (val >> 24) & 0xff; + } +#if 0 + bansheeblt_log("colorPattern%02x=%08x\n", (addr >> 2) & 63, val); +#endif + break; + + default: + fatal("Unknown 2D reg write %03x %08x\n", addr & 0x1fc, val); + } } diff --git a/src/video/vid_voodoo_blitter.c b/src/video/vid_voodoo_blitter.c index f60ed2c0b..6ea2edcc3 100644 --- a/src/video/vid_voodoo_blitter.c +++ b/src/video/vid_voodoo_blitter.c @@ -1,19 +1,20 @@ /* - * 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. + * 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. + * This file is part of the 86Box distribution. * - * 3DFX Voodoo emulation. + * 3DFX Voodoo emulation. * * * - * Authors: Sarah Walker, + * Authors: Sarah Walker, * - * Copyright 2008-2020 Sarah Walker. + * Copyright 2008-2020 Sarah Walker. */ +#include #include #include #include @@ -21,6 +22,7 @@ #include #include #include +#define HAVE_STDARG_H #include <86box/86box.h> #include "cpu.h" #include <86box/machine.h> @@ -30,6 +32,7 @@ #include <86box/timer.h> #include <86box/device.h> #include <86box/plat.h> +#include <86box/thread.h> #include <86box/video.h> #include <86box/vid_svga.h> #include <86box/vid_voodoo_common.h> @@ -38,519 +41,495 @@ #include <86box/vid_voodoo_regs.h> #include <86box/vid_voodoo_render.h> - -enum -{ - BLIT_COMMAND_SCREEN_TO_SCREEN = 0, - BLIT_COMMAND_CPU_TO_SCREEN = 1, - BLIT_COMMAND_RECT_FILL = 2, - BLIT_COMMAND_SGRAM_FILL = 3 +enum { + BLIT_COMMAND_SCREEN_TO_SCREEN = 0, + BLIT_COMMAND_CPU_TO_SCREEN = 1, + BLIT_COMMAND_RECT_FILL = 2, + BLIT_COMMAND_SGRAM_FILL = 3 }; -enum -{ - BLIT_SRC_1BPP = (0 << 3), - BLIT_SRC_1BPP_BYTE_PACKED = (1 << 3), - BLIT_SRC_16BPP = (2 << 3), - BLIT_SRC_24BPP = (3 << 3), - BLIT_SRC_24BPP_DITHER_2X2 = (4 << 3), - BLIT_SRC_24BPP_DITHER_4X4 = (5 << 3) +enum { + BLIT_SRC_1BPP = (0 << 3), + BLIT_SRC_1BPP_BYTE_PACKED = (1 << 3), + BLIT_SRC_16BPP = (2 << 3), + BLIT_SRC_24BPP = (3 << 3), + BLIT_SRC_24BPP_DITHER_2X2 = (4 << 3), + BLIT_SRC_24BPP_DITHER_4X4 = (5 << 3) }; -enum -{ - BLIT_SRC_RGB_ARGB = (0 << 6), - BLIT_SRC_RGB_ABGR = (1 << 6), - BLIT_SRC_RGB_RGBA = (2 << 6), - BLIT_SRC_RGB_BGRA = (3 << 6) +enum { + BLIT_SRC_RGB_ARGB = (0 << 6), + BLIT_SRC_RGB_ABGR = (1 << 6), + BLIT_SRC_RGB_RGBA = (2 << 6), + BLIT_SRC_RGB_BGRA = (3 << 6) }; -enum -{ - BLIT_COMMAND_MASK = 7, - BLIT_SRC_FORMAT = (7 << 3), - BLIT_SRC_RGB_FORMAT = (3 << 6), - BLIT_SRC_CHROMA = (1 << 10), - BLIT_DST_CHROMA = (1 << 12), - BLIT_CLIPPING_ENABLED = (1 << 16) +enum { + BLIT_COMMAND_MASK = 7, + BLIT_SRC_FORMAT = (7 << 3), + BLIT_SRC_RGB_FORMAT = (3 << 6), + BLIT_SRC_CHROMA = (1 << 10), + BLIT_DST_CHROMA = (1 << 12), + BLIT_CLIPPING_ENABLED = (1 << 16) }; -enum -{ - BLIT_ROP_DST_PASS = (1 << 0), - BLIT_ROP_SRC_PASS = (1 << 1) +enum { + BLIT_ROP_DST_PASS = (1 << 0), + BLIT_ROP_SRC_PASS = (1 << 1) }; - #ifdef ENABLE_VOODOOBLT_LOG int voodooblt_do_log = ENABLE_VOODOOBLT_LOG; - static void voodooblt_log(const char *fmt, ...) { va_list ap; if (voodooblt_do_log) { - va_start(ap, fmt); - pclog_ex(fmt, ap); - va_end(ap); + va_start(ap, fmt); + pclog_ex(fmt, ap); + va_end(ap); } } #else -#define voodooblt_log(fmt, ...) +# define voodooblt_log(fmt, ...) #endif +#define MIX(src_dat, dst_dat, rop) \ + switch (rop) { \ + case 0x0: \ + dst_dat = 0; \ + break; \ + case 0x1: \ + dst_dat = ~(src_dat | dst_dat); \ + break; \ + case 0x2: \ + dst_dat = ~src_dat & dst_dat; \ + break; \ + case 0x3: \ + dst_dat = ~src_dat; \ + break; \ + case 0x4: \ + dst_dat = src_dat & ~dst_dat; \ + break; \ + case 0x5: \ + dst_dat = ~dst_dat; \ + break; \ + case 0x6: \ + dst_dat = src_dat ^ dst_dat; \ + break; \ + case 0x7: \ + dst_dat = ~(src_dat & dst_dat); \ + break; \ + case 0x8: \ + dst_dat = src_dat & dst_dat; \ + break; \ + case 0x9: \ + dst_dat = ~(src_dat ^ dst_dat); \ + break; \ + case 0xa: \ + dst_dat = dst_dat; \ + break; \ + case 0xb: \ + dst_dat = ~src_dat | dst_dat; \ + break; \ + case 0xc: \ + dst_dat = src_dat; \ + break; \ + case 0xd: \ + dst_dat = src_dat | ~dst_dat; \ + break; \ + case 0xe: \ + dst_dat = src_dat | dst_dat; \ + break; \ + case 0xf: \ + dst_dat = 0xffff; \ + break; \ + } -#define MIX(src_dat, dst_dat, rop) \ - switch (rop) \ - { \ - case 0x0: dst_dat = 0; break; \ - case 0x1: dst_dat = ~(src_dat | dst_dat); break; \ - case 0x2: dst_dat = ~src_dat & dst_dat; break; \ - case 0x3: dst_dat = ~src_dat; break; \ - case 0x4: dst_dat = src_dat & ~dst_dat; break; \ - case 0x5: dst_dat = ~dst_dat; break; \ - case 0x6: dst_dat = src_dat ^ dst_dat; break; \ - case 0x7: dst_dat = ~(src_dat & dst_dat); break; \ - case 0x8: dst_dat = src_dat & dst_dat; break; \ - case 0x9: dst_dat = ~(src_dat ^ dst_dat); break; \ - case 0xa: dst_dat = dst_dat; break; \ - case 0xb: dst_dat = ~src_dat | dst_dat; break; \ - case 0xc: dst_dat = src_dat; break; \ - case 0xd: dst_dat = src_dat | ~dst_dat; break; \ - case 0xe: dst_dat = src_dat | dst_dat; break; \ - case 0xf: dst_dat = 0xffff; break; \ - } - -void voodoo_v2_blit_start(voodoo_t *voodoo) +void +voodoo_v2_blit_start(voodoo_t *voodoo) { - uint64_t dat64; - int size_x = ABS(voodoo->bltSizeX), size_y = ABS(voodoo->bltSizeY); - int x_dir = (voodoo->bltSizeX > 0) ? 1 : -1; - int y_dir = (voodoo->bltSizeY > 0) ? 1 : -1; - int dst_x; - int src_y = voodoo->bltSrcY & 0x7ff, dst_y = voodoo->bltDstY & 0x7ff; - int src_stride = (voodoo->bltCommand & BLTCMD_SRC_TILED) ? ((voodoo->bltSrcXYStride & 0x3f) * 32*2) : (voodoo->bltSrcXYStride & 0xff8); - int dst_stride = (voodoo->bltCommand & BLTCMD_DST_TILED) ? ((voodoo->bltDstXYStride & 0x3f) * 32*2) : (voodoo->bltDstXYStride & 0xff8); - uint32_t src_base_addr = (voodoo->bltCommand & BLTCMD_SRC_TILED) ? ((voodoo->bltSrcBaseAddr & 0x3ff) << 12) : (voodoo->bltSrcBaseAddr & 0x3ffff8); - uint32_t dst_base_addr = (voodoo->bltCommand & BLTCMD_DST_TILED) ? ((voodoo->bltDstBaseAddr & 0x3ff) << 12) : (voodoo->bltDstBaseAddr & 0x3ffff8); - int x, y; + uint64_t dat64; + int size_x = ABS(voodoo->bltSizeX); + int size_y = ABS(voodoo->bltSizeY); + int x_dir = (voodoo->bltSizeX > 0) ? 1 : -1; + int y_dir = (voodoo->bltSizeY > 0) ? 1 : -1; + int dst_x; + int src_y = voodoo->bltSrcY & 0x7ff; + int dst_y = voodoo->bltDstY & 0x7ff; + int src_stride = (voodoo->bltCommand & BLTCMD_SRC_TILED) ? ((voodoo->bltSrcXYStride & 0x3f) * 32 * 2) : (voodoo->bltSrcXYStride & 0xff8); + int dst_stride = (voodoo->bltCommand & BLTCMD_DST_TILED) ? ((voodoo->bltDstXYStride & 0x3f) * 32 * 2) : (voodoo->bltDstXYStride & 0xff8); + uint32_t src_base_addr = (voodoo->bltCommand & BLTCMD_SRC_TILED) ? ((voodoo->bltSrcBaseAddr & 0x3ff) << 12) : (voodoo->bltSrcBaseAddr & 0x3ffff8); + uint32_t dst_base_addr = (voodoo->bltCommand & BLTCMD_DST_TILED) ? ((voodoo->bltDstBaseAddr & 0x3ff) << 12) : (voodoo->bltDstBaseAddr & 0x3ffff8); -/* voodooblt_log("blit_start: command=%08x srcX=%i srcY=%i dstX=%i dstY=%i sizeX=%i sizeY=%i color=%04x,%04x\n", - voodoo->bltCommand, voodoo->bltSrcX, voodoo->bltSrcY, voodoo->bltDstX, voodoo->bltDstY, voodoo->bltSizeX, voodoo->bltSizeY, voodoo->bltColorFg, voodoo->bltColorBg);*/ +#if 0 + voodooblt_log("blit_start: command=%08x srcX=%i srcY=%i dstX=%i dstY=%i sizeX=%i sizeY=%i color=%04x,%04x\n", + voodoo->bltCommand, voodoo->bltSrcX, voodoo->bltSrcY, voodoo->bltDstX, voodoo->bltDstY, voodoo->bltSizeX, voodoo->bltSizeY, voodoo->bltColorFg, voodoo->bltColorBg); +#endif - voodoo_wait_for_render_thread_idle(voodoo); + voodoo_wait_for_render_thread_idle(voodoo); - switch (voodoo->bltCommand & BLIT_COMMAND_MASK) - { - case BLIT_COMMAND_SCREEN_TO_SCREEN: - for (y = 0; y <= size_y; y++) - { - uint16_t *src = (uint16_t *)&voodoo->fb_mem[src_base_addr + src_y*src_stride]; - uint16_t *dst = (uint16_t *)&voodoo->fb_mem[dst_base_addr + dst_y*dst_stride]; - int src_x = voodoo->bltSrcX, dst_x = voodoo->bltDstX; + switch (voodoo->bltCommand & BLIT_COMMAND_MASK) { + case BLIT_COMMAND_SCREEN_TO_SCREEN: + for (int y = 0; y <= size_y; y++) { + const uint16_t *src = (uint16_t *) &voodoo->fb_mem[src_base_addr + src_y * src_stride]; + uint16_t *dst = (uint16_t *) &voodoo->fb_mem[dst_base_addr + dst_y * dst_stride]; + int src_x = voodoo->bltSrcX; + int dst_x = voodoo->bltDstX; - for (x = 0; x <= size_x; x++) - { - uint16_t src_dat = src[src_x]; - uint16_t dst_dat = dst[dst_x]; - int rop = 0; + for (int x = 0; x <= size_x; x++) { + uint16_t src_dat = src[src_x]; + uint16_t dst_dat = dst[dst_x]; + int rop = 0; - if (voodoo->bltCommand & BLIT_CLIPPING_ENABLED) - { - if (dst_x < voodoo->bltClipLeft || dst_x >= voodoo->bltClipRight || - dst_y < voodoo->bltClipLowY || dst_y >= voodoo->bltClipHighY) - goto skip_pixel_blit; - } + if (voodoo->bltCommand & BLIT_CLIPPING_ENABLED) { + if (dst_x < voodoo->bltClipLeft || dst_x >= voodoo->bltClipRight || dst_y < voodoo->bltClipLowY || dst_y >= voodoo->bltClipHighY) + goto skip_pixel_blit; + } - if (voodoo->bltCommand & BLIT_SRC_CHROMA) - { - int r = (src_dat >> 11); - int g = (src_dat >> 5) & 0x3f; - int b = src_dat & 0x1f; + if (voodoo->bltCommand & BLIT_SRC_CHROMA) { + int r = (src_dat >> 11); + int g = (src_dat >> 5) & 0x3f; + int b = src_dat & 0x1f; - if (r >= voodoo->bltSrcChromaMinR && r <= voodoo->bltSrcChromaMaxR && - g >= voodoo->bltSrcChromaMinG && g <= voodoo->bltSrcChromaMaxG && - b >= voodoo->bltSrcChromaMinB && b <= voodoo->bltSrcChromaMaxB) - rop |= BLIT_ROP_SRC_PASS; - } - if (voodoo->bltCommand & BLIT_DST_CHROMA) - { - int r = (dst_dat >> 11); - int g = (dst_dat >> 5) & 0x3f; - int b = dst_dat & 0x1f; + if (r >= voodoo->bltSrcChromaMinR && r <= voodoo->bltSrcChromaMaxR && g >= voodoo->bltSrcChromaMinG && g <= voodoo->bltSrcChromaMaxG && b >= voodoo->bltSrcChromaMinB && b <= voodoo->bltSrcChromaMaxB) + rop |= BLIT_ROP_SRC_PASS; + } + if (voodoo->bltCommand & BLIT_DST_CHROMA) { + int r = (dst_dat >> 11); + int g = (dst_dat >> 5) & 0x3f; + int b = dst_dat & 0x1f; - if (r >= voodoo->bltDstChromaMinR && r <= voodoo->bltDstChromaMaxR && - g >= voodoo->bltDstChromaMinG && g <= voodoo->bltDstChromaMaxG && - b >= voodoo->bltDstChromaMinB && b <= voodoo->bltDstChromaMaxB) - rop |= BLIT_ROP_DST_PASS; - } + if (r >= voodoo->bltDstChromaMinR && r <= voodoo->bltDstChromaMaxR && g >= voodoo->bltDstChromaMinG && g <= voodoo->bltDstChromaMaxG && b >= voodoo->bltDstChromaMinB && b <= voodoo->bltDstChromaMaxB) + rop |= BLIT_ROP_DST_PASS; + } - MIX(src_dat, dst_dat, voodoo->bltRop[rop]); + MIX(src_dat, dst_dat, voodoo->bltRop[rop]); - dst[dst_x] = dst_dat; + dst[dst_x] = dst_dat; skip_pixel_blit: - src_x += x_dir; - dst_x += x_dir; - } - - src_y += y_dir; - dst_y += y_dir; + src_x += x_dir; + dst_x += x_dir; } - break; - case BLIT_COMMAND_CPU_TO_SCREEN: - voodoo->blt.dst_x = voodoo->bltDstX; - voodoo->blt.dst_y = voodoo->bltDstY; - voodoo->blt.cur_x = 0; - voodoo->blt.size_x = size_x; - voodoo->blt.size_y = size_y; - voodoo->blt.x_dir = x_dir; - voodoo->blt.y_dir = y_dir; - voodoo->blt.dst_stride = (voodoo->bltCommand & BLTCMD_DST_TILED) ? ((voodoo->bltDstXYStride & 0x3f) * 32*2) : (voodoo->bltDstXYStride & 0xff8); - break; + src_y += y_dir; + dst_y += y_dir; + } + break; - case BLIT_COMMAND_RECT_FILL: - for (y = 0; y <= size_y; y++) - { - uint16_t *dst; - int dst_x = voodoo->bltDstX; + case BLIT_COMMAND_CPU_TO_SCREEN: + voodoo->blt.dst_x = voodoo->bltDstX; + voodoo->blt.dst_y = voodoo->bltDstY; + voodoo->blt.cur_x = 0; + voodoo->blt.size_x = size_x; + voodoo->blt.size_y = size_y; + voodoo->blt.x_dir = x_dir; + voodoo->blt.y_dir = y_dir; + voodoo->blt.dst_stride = (voodoo->bltCommand & BLTCMD_DST_TILED) ? ((voodoo->bltDstXYStride & 0x3f) * 32 * 2) : (voodoo->bltDstXYStride & 0xff8); + break; - if (SLI_ENABLED) - { - if ((!(voodoo->initEnable & INITENABLE_SLI_MASTER_SLAVE) && (voodoo->blt.dst_y & 1)) || - ((voodoo->initEnable & INITENABLE_SLI_MASTER_SLAVE) && !(voodoo->blt.dst_y & 1))) - goto skip_line_fill; - dst = (uint16_t *)&voodoo->fb_mem[dst_base_addr + (dst_y >> 1) * dst_stride]; - } - else - dst = (uint16_t *)&voodoo->fb_mem[dst_base_addr + dst_y*dst_stride]; + case BLIT_COMMAND_RECT_FILL: + for (int y = 0; y <= size_y; y++) { + uint16_t *dst; + int dst_x = voodoo->bltDstX; - for (x = 0; x <= size_x; x++) - { - if (voodoo->bltCommand & BLIT_CLIPPING_ENABLED) - { - if (dst_x < voodoo->bltClipLeft || dst_x >= voodoo->bltClipRight || - dst_y < voodoo->bltClipLowY || dst_y >= voodoo->bltClipHighY) - goto skip_pixel_fill; - } + if (SLI_ENABLED) { + if ((!(voodoo->initEnable & INITENABLE_SLI_MASTER_SLAVE) && (voodoo->blt.dst_y & 1)) || ((voodoo->initEnable & INITENABLE_SLI_MASTER_SLAVE) && !(voodoo->blt.dst_y & 1))) + goto skip_line_fill; + dst = (uint16_t *) &voodoo->fb_mem[dst_base_addr + (dst_y >> 1) * dst_stride]; + } else + dst = (uint16_t *) &voodoo->fb_mem[dst_base_addr + dst_y * dst_stride]; - dst[dst_x] = voodoo->bltColorFg; + for (int x = 0; x <= size_x; x++) { + if (voodoo->bltCommand & BLIT_CLIPPING_ENABLED) { + if (dst_x < voodoo->bltClipLeft || dst_x >= voodoo->bltClipRight || dst_y < voodoo->bltClipLowY || dst_y >= voodoo->bltClipHighY) + goto skip_pixel_fill; + } + + dst[dst_x] = voodoo->bltColorFg; skip_pixel_fill: - dst_x += x_dir; - } + dst_x += x_dir; + } skip_line_fill: - dst_y += y_dir; + dst_y += y_dir; + } + break; + + case BLIT_COMMAND_SGRAM_FILL: + /*32x32 tiles - 2kb*/ + dst_y = voodoo->bltDstY & 0x3ff; + size_x = voodoo->bltSizeX & 0x1ff; // 512*8 = 4kb + size_y = voodoo->bltSizeY & 0x3ff; + + dat64 = voodoo->bltColorFg | ((uint64_t) voodoo->bltColorFg << 16) | ((uint64_t) voodoo->bltColorFg << 32) | ((uint64_t) voodoo->bltColorFg << 48); + + for (int y = 0; y <= size_y; y++) { + uint64_t *dst; + + /*This may be wrong*/ + if (!y) { + dst_x = voodoo->bltDstX & 0x1ff; + size_x = 511 - dst_x; + } else if (y < size_y) { + dst_x = 0; + size_x = 511; + } else { + dst_x = 0; + size_x = voodoo->bltSizeX & 0x1ff; } - break; - case BLIT_COMMAND_SGRAM_FILL: - /*32x32 tiles - 2kb*/ - dst_y = voodoo->bltDstY & 0x3ff; - size_x = voodoo->bltSizeX & 0x1ff; //512*8 = 4kb - size_y = voodoo->bltSizeY & 0x3ff; + dst = (uint64_t *) &voodoo->fb_mem[(dst_y * 512 * 8 + dst_x * 8) & voodoo->fb_mask]; - dat64 = voodoo->bltColorFg | ((uint64_t)voodoo->bltColorFg << 16) | - ((uint64_t)voodoo->bltColorFg << 32) | ((uint64_t)voodoo->bltColorFg << 48); + for (int x = 0; x <= size_x; x++) + dst[x] = dat64; - for (y = 0; y <= size_y; y++) - { - uint64_t *dst; + dst_y++; + } + break; - /*This may be wrong*/ - if (!y) - { - dst_x = voodoo->bltDstX & 0x1ff; - size_x = 511 - dst_x; - } - else if (y < size_y) - { - dst_x = 0; - size_x = 511; - } - else - { - dst_x = 0; - size_x = voodoo->bltSizeX & 0x1ff; - } - - dst = (uint64_t *)&voodoo->fb_mem[(dst_y*512*8 + dst_x*8) & voodoo->fb_mask]; - - for (x = 0; x <= size_x; x++) - dst[x] = dat64; - - dst_y++; - } - break; - - default: - fatal("bad blit command %08x\n", voodoo->bltCommand); - } + default: + fatal("bad blit command %08x\n", voodoo->bltCommand); + } } -void voodoo_v2_blit_data(voodoo_t *voodoo, uint32_t data) +void +voodoo_v2_blit_data(voodoo_t *voodoo, uint32_t data) { - int src_bits = 32; - uint32_t base_addr = (voodoo->bltCommand & BLTCMD_DST_TILED) ? ((voodoo->bltDstBaseAddr & 0x3ff) << 12) : (voodoo->bltDstBaseAddr & 0x3ffff8); - uint32_t addr; - uint16_t *dst; + int src_bits = 32; + uint32_t base_addr = (voodoo->bltCommand & BLTCMD_DST_TILED) ? ((voodoo->bltDstBaseAddr & 0x3ff) << 12) : (voodoo->bltDstBaseAddr & 0x3ffff8); + uint32_t addr; + uint16_t *dst; - if ((voodoo->bltCommand & BLIT_COMMAND_MASK) != BLIT_COMMAND_CPU_TO_SCREEN) - return; + if ((voodoo->bltCommand & BLIT_COMMAND_MASK) != BLIT_COMMAND_CPU_TO_SCREEN) + return; - if (SLI_ENABLED) - { - addr = base_addr + (voodoo->blt.dst_y >> 1) * voodoo->blt.dst_stride; - dst = (uint16_t *)&voodoo->fb_mem[addr]; - } - else - { - addr = base_addr + voodoo->blt.dst_y*voodoo->blt.dst_stride; - dst = (uint16_t *)&voodoo->fb_mem[addr]; - } + if (SLI_ENABLED) { + addr = base_addr + (voodoo->blt.dst_y >> 1) * voodoo->blt.dst_stride; + dst = (uint16_t *) &voodoo->fb_mem[addr]; + } else { + addr = base_addr + voodoo->blt.dst_y * voodoo->blt.dst_stride; + dst = (uint16_t *) &voodoo->fb_mem[addr]; + } - if (addr >= voodoo->front_offset && voodoo->row_width) - { - int y = (addr - voodoo->front_offset) / voodoo->row_width; - if (y < voodoo->v_disp) - voodoo->dirty_line[y] = 2; - } + if (addr >= voodoo->front_offset && voodoo->row_width) { + int y = (addr - voodoo->front_offset) / voodoo->row_width; + if (y < voodoo->v_disp) + voodoo->dirty_line[y] = 2; + } - while (src_bits && voodoo->blt.cur_x <= voodoo->blt.size_x) - { - int r = 0, g = 0, b = 0; - uint16_t src_dat = 0, dst_dat; - int x = (voodoo->blt.x_dir > 0) ? (voodoo->blt.dst_x + voodoo->blt.cur_x) : (voodoo->blt.dst_x - voodoo->blt.cur_x); - int rop = 0; + while (src_bits && voodoo->blt.cur_x <= voodoo->blt.size_x) { + int r = 0; + int g = 0; + int b = 0; + uint16_t src_dat = 0; + uint16_t dst_dat; + int x = (voodoo->blt.x_dir > 0) ? (voodoo->blt.dst_x + voodoo->blt.cur_x) : (voodoo->blt.dst_x - voodoo->blt.cur_x); + int rop = 0; - switch (voodoo->bltCommand & BLIT_SRC_FORMAT) - { - case BLIT_SRC_1BPP: case BLIT_SRC_1BPP_BYTE_PACKED: - src_dat = (data & 1) ? voodoo->bltColorFg : voodoo->bltColorBg; - data >>= 1; - src_bits--; + switch (voodoo->bltCommand & BLIT_SRC_FORMAT) { + case BLIT_SRC_1BPP: + case BLIT_SRC_1BPP_BYTE_PACKED: + src_dat = (data & 1) ? voodoo->bltColorFg : voodoo->bltColorBg; + data >>= 1; + src_bits--; + break; + case BLIT_SRC_16BPP: + switch (voodoo->bltCommand & BLIT_SRC_RGB_FORMAT) { + case BLIT_SRC_RGB_ARGB: + case BLIT_SRC_RGB_RGBA: + src_dat = data & 0xffff; break; - case BLIT_SRC_16BPP: - switch (voodoo->bltCommand & BLIT_SRC_RGB_FORMAT) - { - case BLIT_SRC_RGB_ARGB: case BLIT_SRC_RGB_RGBA: - src_dat = data & 0xffff; - break; - case BLIT_SRC_RGB_ABGR: case BLIT_SRC_RGB_BGRA: - src_dat = ((data & 0xf800) >> 11) | (data & 0x07c0) | ((data & 0x0038) << 11); - break; - } - data >>= 16; - src_bits -= 16; + case BLIT_SRC_RGB_ABGR: + case BLIT_SRC_RGB_BGRA: + src_dat = ((data & 0xf800) >> 11) | (data & 0x07c0) | ((data & 0x0038) << 11); break; - case BLIT_SRC_24BPP: case BLIT_SRC_24BPP_DITHER_2X2: case BLIT_SRC_24BPP_DITHER_4X4: - switch (voodoo->bltCommand & BLIT_SRC_RGB_FORMAT) - { - case BLIT_SRC_RGB_ARGB: - r = (data >> 16) & 0xff; - g = (data >> 8) & 0xff; - b = data & 0xff; - break; - case BLIT_SRC_RGB_ABGR: - r = data & 0xff; - g = (data >> 8) & 0xff; - b = (data >> 16) & 0xff; - break; - case BLIT_SRC_RGB_RGBA: - r = (data >> 24) & 0xff; - g = (data >> 16) & 0xff; - b = (data >> 8) & 0xff; - break; - case BLIT_SRC_RGB_BGRA: - r = (data >> 8) & 0xff; - g = (data >> 16) & 0xff; - b = (data >> 24) & 0xff; - break; - } - switch (voodoo->bltCommand & BLIT_SRC_FORMAT) - { - case BLIT_SRC_24BPP: - src_dat = (b >> 3) | ((g & 0xfc) << 3) | ((r & 0xf8) << 8); - break; - case BLIT_SRC_24BPP_DITHER_2X2: - r = dither_rb2x2[r][voodoo->blt.dst_y & 1][x & 1]; - g = dither_g2x2[g][voodoo->blt.dst_y & 1][x & 1]; - b = dither_rb2x2[b][voodoo->blt.dst_y & 1][x & 1]; - src_dat = (b >> 3) | ((g & 0xfc) << 3) | ((r & 0xf8) << 8); - break; - case BLIT_SRC_24BPP_DITHER_4X4: - r = dither_rb[r][voodoo->blt.dst_y & 3][x & 3]; - g = dither_g[g][voodoo->blt.dst_y & 3][x & 3]; - b = dither_rb[b][voodoo->blt.dst_y & 3][x & 3]; - src_dat = (b >> 3) | ((g & 0xfc) << 3) | ((r & 0xf8) << 8); - break; - } - src_bits = 0; + + default: break; } + data >>= 16; + src_bits -= 16; + break; + case BLIT_SRC_24BPP: + case BLIT_SRC_24BPP_DITHER_2X2: + case BLIT_SRC_24BPP_DITHER_4X4: + switch (voodoo->bltCommand & BLIT_SRC_RGB_FORMAT) { + case BLIT_SRC_RGB_ARGB: + r = (data >> 16) & 0xff; + g = (data >> 8) & 0xff; + b = data & 0xff; + break; + case BLIT_SRC_RGB_ABGR: + r = data & 0xff; + g = (data >> 8) & 0xff; + b = (data >> 16) & 0xff; + break; + case BLIT_SRC_RGB_RGBA: + r = (data >> 24) & 0xff; + g = (data >> 16) & 0xff; + b = (data >> 8) & 0xff; + break; + case BLIT_SRC_RGB_BGRA: + r = (data >> 8) & 0xff; + g = (data >> 16) & 0xff; + b = (data >> 24) & 0xff; + break; - if (SLI_ENABLED) - { - if ((!(voodoo->initEnable & INITENABLE_SLI_MASTER_SLAVE) && (voodoo->blt.dst_y & 1)) || - ((voodoo->initEnable & INITENABLE_SLI_MASTER_SLAVE) && !(voodoo->blt.dst_y & 1))) - goto skip_pixel; + default: + break; } + switch (voodoo->bltCommand & BLIT_SRC_FORMAT) { + case BLIT_SRC_24BPP: + src_dat = (b >> 3) | ((g & 0xfc) << 3) | ((r & 0xf8) << 8); + break; + case BLIT_SRC_24BPP_DITHER_2X2: + r = dither_rb2x2[r][voodoo->blt.dst_y & 1][x & 1]; + g = dither_g2x2[g][voodoo->blt.dst_y & 1][x & 1]; + b = dither_rb2x2[b][voodoo->blt.dst_y & 1][x & 1]; + src_dat = (b >> 3) | ((g & 0xfc) << 3) | ((r & 0xf8) << 8); + break; + case BLIT_SRC_24BPP_DITHER_4X4: + r = dither_rb[r][voodoo->blt.dst_y & 3][x & 3]; + g = dither_g[g][voodoo->blt.dst_y & 3][x & 3]; + b = dither_rb[b][voodoo->blt.dst_y & 3][x & 3]; + src_dat = (b >> 3) | ((g & 0xfc) << 3) | ((r & 0xf8) << 8); + break; - if (voodoo->bltCommand & BLIT_CLIPPING_ENABLED) - { - if (x < voodoo->bltClipLeft || x >= voodoo->bltClipRight || - voodoo->blt.dst_y < voodoo->bltClipLowY || voodoo->blt.dst_y >= voodoo->bltClipHighY) - goto skip_pixel; + default: + break; } + src_bits = 0; + break; - dst_dat = dst[x]; + default: + break; + } - if (voodoo->bltCommand & BLIT_SRC_CHROMA) - { - r = (src_dat >> 11); - g = (src_dat >> 5) & 0x3f; - b = src_dat & 0x1f; + if (SLI_ENABLED) { + if ((!(voodoo->initEnable & INITENABLE_SLI_MASTER_SLAVE) && (voodoo->blt.dst_y & 1)) || ((voodoo->initEnable & INITENABLE_SLI_MASTER_SLAVE) && !(voodoo->blt.dst_y & 1))) + goto skip_pixel; + } - if (r >= voodoo->bltSrcChromaMinR && r <= voodoo->bltSrcChromaMaxR && - g >= voodoo->bltSrcChromaMinG && g <= voodoo->bltSrcChromaMaxG && - b >= voodoo->bltSrcChromaMinB && b <= voodoo->bltSrcChromaMaxB) - rop |= BLIT_ROP_SRC_PASS; - } - if (voodoo->bltCommand & BLIT_DST_CHROMA) - { - r = (dst_dat >> 11); - g = (dst_dat >> 5) & 0x3f; - b = dst_dat & 0x1f; + if (voodoo->bltCommand & BLIT_CLIPPING_ENABLED) { + if (x < voodoo->bltClipLeft || x >= voodoo->bltClipRight || voodoo->blt.dst_y < voodoo->bltClipLowY || voodoo->blt.dst_y >= voodoo->bltClipHighY) + goto skip_pixel; + } - if (r >= voodoo->bltDstChromaMinR && r <= voodoo->bltDstChromaMaxR && - g >= voodoo->bltDstChromaMinG && g <= voodoo->bltDstChromaMaxG && - b >= voodoo->bltDstChromaMinB && b <= voodoo->bltDstChromaMaxB) - rop |= BLIT_ROP_DST_PASS; - } + dst_dat = dst[x]; - MIX(src_dat, dst_dat, voodoo->bltRop[rop]); + if (voodoo->bltCommand & BLIT_SRC_CHROMA) { + r = (src_dat >> 11); + g = (src_dat >> 5) & 0x3f; + b = src_dat & 0x1f; - dst[x] = dst_dat; + if (r >= voodoo->bltSrcChromaMinR && r <= voodoo->bltSrcChromaMaxR && g >= voodoo->bltSrcChromaMinG && g <= voodoo->bltSrcChromaMaxG && b >= voodoo->bltSrcChromaMinB && b <= voodoo->bltSrcChromaMaxB) + rop |= BLIT_ROP_SRC_PASS; + } + if (voodoo->bltCommand & BLIT_DST_CHROMA) { + r = (dst_dat >> 11); + g = (dst_dat >> 5) & 0x3f; + b = dst_dat & 0x1f; + + if (r >= voodoo->bltDstChromaMinR && r <= voodoo->bltDstChromaMaxR && g >= voodoo->bltDstChromaMinG && g <= voodoo->bltDstChromaMaxG && b >= voodoo->bltDstChromaMinB && b <= voodoo->bltDstChromaMaxB) + rop |= BLIT_ROP_DST_PASS; + } + + MIX(src_dat, dst_dat, voodoo->bltRop[rop]); + + dst[x] = dst_dat; skip_pixel: - voodoo->blt.cur_x++; - } + voodoo->blt.cur_x++; + } - if (voodoo->blt.cur_x > voodoo->blt.size_x) - { - voodoo->blt.size_y--; - if (voodoo->blt.size_y >= 0) - { - voodoo->blt.cur_x = 0; - voodoo->blt.dst_y += voodoo->blt.y_dir; - } + if (voodoo->blt.cur_x > voodoo->blt.size_x) { + voodoo->blt.size_y--; + if (voodoo->blt.size_y >= 0) { + voodoo->blt.cur_x = 0; + voodoo->blt.dst_y += voodoo->blt.y_dir; } + } } - -void voodoo_fastfill(voodoo_t *voodoo, voodoo_params_t *params) +void +voodoo_fastfill(voodoo_t *voodoo, voodoo_params_t *params) { - int y; - int low_y, high_y; + int y; + int low_y; + int high_y; - if (params->fbzMode & (1 << 17)) - { - int y_origin = (voodoo->type >= VOODOO_BANSHEE) ? (voodoo->y_origin_swap+1) : voodoo->v_disp; + if (params->fbzMode & (1 << 17)) { + int y_origin = (voodoo->type >= VOODOO_BANSHEE) ? (voodoo->y_origin_swap + 1) : voodoo->v_disp; - high_y = y_origin - params->clipLowY; - low_y = y_origin - params->clipHighY; - } - else - { - low_y = params->clipLowY; - high_y = params->clipHighY; - } + high_y = y_origin - params->clipLowY; + low_y = y_origin - params->clipHighY; + } else { + low_y = params->clipLowY; + high_y = params->clipHighY; + } - if (params->fbzMode & FBZ_RGB_WMASK) - { - int r, g, b; - uint16_t col; + if (params->fbzMode & FBZ_RGB_WMASK) { + int r; + int g; + int b; + uint16_t col; - r = ((params->color1 >> 16) >> 3) & 0x1f; - g = ((params->color1 >> 8) >> 2) & 0x3f; - b = (params->color1 >> 3) & 0x1f; - col = b | (g << 5) | (r << 11); + r = ((params->color1 >> 16) >> 3) & 0x1f; + g = ((params->color1 >> 8) >> 2) & 0x3f; + b = (params->color1 >> 3) & 0x1f; + col = b | (g << 5) | (r << 11); - if (SLI_ENABLED) - { - for (y = low_y; y < high_y; y += 2) - { - uint16_t *cbuf = (uint16_t *)&voodoo->fb_mem[(params->draw_offset + (y >> 1) * voodoo->row_width) & voodoo->fb_mask]; - int x; + if (SLI_ENABLED) { + for (y = low_y; y < high_y; y += 2) { + uint16_t *cbuf = (uint16_t *) &voodoo->fb_mem[(params->draw_offset + (y >> 1) * voodoo->row_width) & voodoo->fb_mask]; - for (x = params->clipLeft; x < params->clipRight; x++) - cbuf[x] = col; - } - } - else - { - for (y = low_y; y < high_y; y++) - { - if (voodoo->col_tiled) - { - uint16_t *cbuf = (uint16_t *)&voodoo->fb_mem[(params->draw_offset + (y >> 5) * voodoo->row_width + (y & 31) * 128) & voodoo->fb_mask]; - int x; - - for (x = params->clipLeft; x < params->clipRight; x++) - { - int x2 = (x & 63) | ((x >> 6) * 128*32/2); - cbuf[x2] = col; - } - } - else - { - uint16_t *cbuf = (uint16_t *)&voodoo->fb_mem[(params->draw_offset + y * voodoo->row_width) & voodoo->fb_mask]; - int x; - - for (x = params->clipLeft; x < params->clipRight; x++) - cbuf[x] = col; - } - } + for (int x = params->clipLeft; x < params->clipRight; x++) + cbuf[x] = col; + } + } else { + for (y = low_y; y < high_y; y++) { + if (voodoo->col_tiled) { + uint16_t *cbuf = (uint16_t *) &voodoo->fb_mem[(params->draw_offset + (y >> 5) * voodoo->row_width + (y & 31) * 128) & voodoo->fb_mask]; + + for (int x = params->clipLeft; x < params->clipRight; x++) { + int x2 = (x & 63) | ((x >> 6) * 128 * 32 / 2); + cbuf[x2] = col; + } + } else { + uint16_t *cbuf = (uint16_t *) &voodoo->fb_mem[(params->draw_offset + y * voodoo->row_width) & voodoo->fb_mask]; + + for (int x = params->clipLeft; x < params->clipRight; x++) + cbuf[x] = col; } + } } - if (params->fbzMode & FBZ_DEPTH_WMASK) - { - if (SLI_ENABLED) - { - for (y = low_y; y < high_y; y += 2) - { - uint16_t *abuf = (uint16_t *)&voodoo->fb_mem[(params->aux_offset + (y >> 1) * voodoo->row_width) & voodoo->fb_mask]; - int x; + } + if (params->fbzMode & FBZ_DEPTH_WMASK) { + if (SLI_ENABLED) { + for (y = low_y; y < high_y; y += 2) { + uint16_t *abuf = (uint16_t *) &voodoo->fb_mem[(params->aux_offset + (y >> 1) * voodoo->row_width) & voodoo->fb_mask]; - for (x = params->clipLeft; x < params->clipRight; x++) - abuf[x] = params->zaColor & 0xffff; - } - } - else - { - for (y = low_y; y < high_y; y++) - { - if (voodoo->aux_tiled) - { - uint16_t *abuf = (uint16_t *)&voodoo->fb_mem[(params->aux_offset + (y >> 5) * voodoo->aux_row_width + (y & 31) * 128) & voodoo->fb_mask]; - int x; - - for (x = params->clipLeft; x < params->clipRight; x++) - { - int x2 = (x & 63) | ((x >> 6) * 128*32/2); - abuf[x2] = params->zaColor & 0xffff; - } - } - else - { - uint16_t *abuf = (uint16_t *)&voodoo->fb_mem[(params->aux_offset + y * voodoo->aux_row_width) & voodoo->fb_mask]; - int x; - - for (x = params->clipLeft; x < params->clipRight; x++) - abuf[x] = params->zaColor & 0xffff; - } - } + for (int x = params->clipLeft; x < params->clipRight; x++) + abuf[x] = params->zaColor & 0xffff; + } + } else { + for (y = low_y; y < high_y; y++) { + if (voodoo->aux_tiled) { + uint16_t *abuf = (uint16_t *) &voodoo->fb_mem[(params->aux_offset + (y >> 5) * voodoo->aux_row_width + (y & 31) * 128) & voodoo->fb_mask]; + + for (int x = params->clipLeft; x < params->clipRight; x++) { + int x2 = (x & 63) | ((x >> 6) * 128 * 32 / 2); + abuf[x2] = params->zaColor & 0xffff; + } + } else { + uint16_t *abuf = (uint16_t *) &voodoo->fb_mem[(params->aux_offset + y * voodoo->aux_row_width) & voodoo->fb_mask]; + + for (int x = params->clipLeft; x < params->clipRight; x++) + abuf[x] = params->zaColor & 0xffff; } + } } + } } diff --git a/src/video/vid_voodoo_display.c b/src/video/vid_voodoo_display.c index a52249bee..e6cf13674 100644 --- a/src/video/vid_voodoo_display.c +++ b/src/video/vid_voodoo_display.c @@ -1,19 +1,21 @@ /* - * 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. + * 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. + * This file is part of the 86Box distribution. * - * 3DFX Voodoo emulation. + * 3DFX Voodoo emulation. * * * - * Authors: Sarah Walker, + * Authors: Sarah Walker, * - * Copyright 2008-2020 Sarah Walker. + * Copyright 2008-2020 Sarah Walker. */ +#include +#include #include #include #include @@ -21,6 +23,7 @@ #include #include #include +#define HAVE_STDARG_H #include <86box/86box.h> #include "cpu.h" #include <86box/machine.h> @@ -29,6 +32,7 @@ #include <86box/timer.h> #include <86box/device.h> #include <86box/plat.h> +#include <86box/thread.h> #include <86box/video.h> #include <86box/vid_svga.h> #include <86box/vid_voodoo_common.h> @@ -36,643 +40,625 @@ #include <86box/vid_voodoo_regs.h> #include <86box/vid_voodoo_render.h> - #ifdef ENABLE_VOODOODISP_LOG int voodoodisp_do_log = ENABLE_VOODOODISP_LOG; - static void voodoodisp_log(const char *fmt, ...) { va_list ap; if (voodoodisp_do_log) { - va_start(ap, fmt); - pclog_ex(fmt, ap); - va_end(ap); + va_start(ap, fmt); + pclog_ex(fmt, ap); + va_end(ap); } } #else -#define voodoodisp_log(fmt, ...) +# define voodoodisp_log(fmt, ...) #endif -void voodoo_update_ncc(voodoo_t *voodoo, int tmu) +void +voodoo_update_ncc(voodoo_t *voodoo, int tmu) { - int tbl; + for (uint8_t tbl = 0; tbl < 2; tbl++) { + for (uint16_t col = 0; col < 256; col++) { + int y = (col >> 4); + int i = (col >> 2) & 3; + int q = col & 3; + int i_r; + int i_g; + int i_b; + int q_r; + int q_g; + int q_b; - for (tbl = 0; tbl < 2; tbl++) - { - int col; + y = (voodoo->nccTable[tmu][tbl].y[y >> 2] >> ((y & 3) * 8)) & 0xff; - for (col = 0; col < 256; col++) - { - int y = (col >> 4), i = (col >> 2) & 3, q = col & 3; - int i_r, i_g, i_b; - int q_r, q_g, q_b; + i_r = (voodoo->nccTable[tmu][tbl].i[i] >> 18) & 0x1ff; + if (i_r & 0x100) + i_r |= 0xfffffe00; + i_g = (voodoo->nccTable[tmu][tbl].i[i] >> 9) & 0x1ff; + if (i_g & 0x100) + i_g |= 0xfffffe00; + i_b = voodoo->nccTable[tmu][tbl].i[i] & 0x1ff; + if (i_b & 0x100) + i_b |= 0xfffffe00; - y = (voodoo->nccTable[tmu][tbl].y[y >> 2] >> ((y & 3) * 8)) & 0xff; + q_r = (voodoo->nccTable[tmu][tbl].q[q] >> 18) & 0x1ff; + if (q_r & 0x100) + q_r |= 0xfffffe00; + q_g = (voodoo->nccTable[tmu][tbl].q[q] >> 9) & 0x1ff; + if (q_g & 0x100) + q_g |= 0xfffffe00; + q_b = voodoo->nccTable[tmu][tbl].q[q] & 0x1ff; + if (q_b & 0x100) + q_b |= 0xfffffe00; - i_r = (voodoo->nccTable[tmu][tbl].i[i] >> 18) & 0x1ff; - if (i_r & 0x100) - i_r |= 0xfffffe00; - i_g = (voodoo->nccTable[tmu][tbl].i[i] >> 9) & 0x1ff; - if (i_g & 0x100) - i_g |= 0xfffffe00; - i_b = voodoo->nccTable[tmu][tbl].i[i] & 0x1ff; - if (i_b & 0x100) - i_b |= 0xfffffe00; - - q_r = (voodoo->nccTable[tmu][tbl].q[q] >> 18) & 0x1ff; - if (q_r & 0x100) - q_r |= 0xfffffe00; - q_g = (voodoo->nccTable[tmu][tbl].q[q] >> 9) & 0x1ff; - if (q_g & 0x100) - q_g |= 0xfffffe00; - q_b = voodoo->nccTable[tmu][tbl].q[q] & 0x1ff; - if (q_b & 0x100) - q_b |= 0xfffffe00; - - voodoo->ncc_lookup[tmu][tbl][col].rgba.r = CLAMP(y + i_r + q_r); - voodoo->ncc_lookup[tmu][tbl][col].rgba.g = CLAMP(y + i_g + q_g); - voodoo->ncc_lookup[tmu][tbl][col].rgba.b = CLAMP(y + i_b + q_b); - voodoo->ncc_lookup[tmu][tbl][col].rgba.a = 0xff; - } + voodoo->ncc_lookup[tmu][tbl][col].rgba.r = CLAMP(y + i_r + q_r); + voodoo->ncc_lookup[tmu][tbl][col].rgba.g = CLAMP(y + i_g + q_g); + voodoo->ncc_lookup[tmu][tbl][col].rgba.b = CLAMP(y + i_b + q_b); + voodoo->ncc_lookup[tmu][tbl][col].rgba.a = 0xff; } + } } -void voodoo_pixelclock_update(voodoo_t *voodoo) +void +voodoo_pixelclock_update(voodoo_t *voodoo) { - int m = (voodoo->dac_pll_regs[0] & 0x7f) + 2; - int n1 = ((voodoo->dac_pll_regs[0] >> 8) & 0x1f) + 2; - int n2 = ((voodoo->dac_pll_regs[0] >> 13) & 0x07); - float t = (14318184.0 * ((float)m / (float)n1)) / (float)(1 << n2); - double clock_const; - int line_length; + int m = (voodoo->dac_pll_regs[0] & 0x7f) + 2; + int n1 = ((voodoo->dac_pll_regs[0] >> 8) & 0x1f) + 2; + int n2 = ((voodoo->dac_pll_regs[0] >> 13) & 0x07); + float t = (14318184.0 * ((float) m / (float) n1)) / (float) (1 << n2); + double clock_const; + int line_length; - if ((voodoo->dac_data[6] & 0xf0) == 0x20 || - (voodoo->dac_data[6] & 0xf0) == 0x60 || - (voodoo->dac_data[6] & 0xf0) == 0x70) - t /= 2.0f; + if ((voodoo->dac_data[6] & 0xf0) == 0x20 || (voodoo->dac_data[6] & 0xf0) == 0x60 || (voodoo->dac_data[6] & 0xf0) == 0x70) + t /= 2.0f; - line_length = (voodoo->hSync & 0xff) + ((voodoo->hSync >> 16) & 0x3ff); + line_length = (voodoo->hSync & 0xff) + ((voodoo->hSync >> 16) & 0x3ff); -// voodoodisp_log("Pixel clock %f MHz hsync %08x line_length %d\n", t, voodoo->hSync, line_length); + // voodoodisp_log("Pixel clock %f MHz hsync %08x line_length %d\n", t, voodoo->hSync, line_length); - voodoo->pixel_clock = t; + voodoo->pixel_clock = t; - clock_const = cpuclock / t; - voodoo->line_time = (uint64_t)((double)line_length * clock_const * (double)(1ull << 32)); + clock_const = cpuclock / t; + voodoo->line_time = (uint64_t) ((double) line_length * clock_const * (double) (1ULL << 32)); } -static void voodoo_calc_clutData(voodoo_t *voodoo) +static void +voodoo_calc_clutData(voodoo_t *voodoo) { - int c; + int c; - for (c = 0; c < 256; c++) - { - voodoo->clutData256[c].r = (voodoo->clutData[c >> 3].r*(8-(c & 7)) + - voodoo->clutData[(c >> 3)+1].r*(c & 7)) >> 3; - voodoo->clutData256[c].g = (voodoo->clutData[c >> 3].g*(8-(c & 7)) + - voodoo->clutData[(c >> 3)+1].g*(c & 7)) >> 3; - voodoo->clutData256[c].b = (voodoo->clutData[c >> 3].b*(8-(c & 7)) + - voodoo->clutData[(c >> 3)+1].b*(c & 7)) >> 3; - } + for (c = 0; c < 256; c++) { + voodoo->clutData256[c].r = (voodoo->clutData[c >> 3].r * (8 - (c & 7)) + voodoo->clutData[(c >> 3) + 1].r * (c & 7)) >> 3; + voodoo->clutData256[c].g = (voodoo->clutData[c >> 3].g * (8 - (c & 7)) + voodoo->clutData[(c >> 3) + 1].g * (c & 7)) >> 3; + voodoo->clutData256[c].b = (voodoo->clutData[c >> 3].b * (8 - (c & 7)) + voodoo->clutData[(c >> 3) + 1].b * (c & 7)) >> 3; + } - for (c = 0; c < 65536; c++) - { - int r = (c >> 8) & 0xf8; - int g = (c >> 3) & 0xfc; - int b = (c << 3) & 0xf8; -// r |= (r >> 5); -// g |= (g >> 6); -// b |= (b >> 5); - - voodoo->video_16to32[c] = (voodoo->clutData256[r].r << 16) | (voodoo->clutData256[g].g << 8) | voodoo->clutData256[b].b; - } + for (c = 0; c < 65536; c++) { + int r = (c >> 8) & 0xf8; + int g = (c >> 3) & 0xfc; + int b = (c << 3) & 0xf8; +#if 0 + r |= (r >> 5); + g |= (g >> 6); + b |= (b >> 5); +#endif + voodoo->video_16to32[c] = (voodoo->clutData256[r].r << 16) | (voodoo->clutData256[g].g << 8) | voodoo->clutData256[b].b; + } } - - #define FILTDIV 256 -static int FILTCAP, FILTCAPG, FILTCAPB = 0; /* color filter threshold values */ +static int FILTCAP; +static int FILTCAPG; +static int FILTCAPB = 0; /* color filter threshold values */ -void voodoo_generate_filter_v1(voodoo_t *voodoo) +void +voodoo_generate_filter_v1(voodoo_t *voodoo) { - int g, h; - float difference, diffg, diffb; - float thiscol, thiscolg, thiscolb, lined; - float fcr, fcg, fcb; + float difference; + float diffg; + float diffb; + float thiscol; + float thiscolg; + float thiscolb; + float lined; + float fcr; + float fcg; + float fcb; - fcr = FILTCAP * 5; - fcg = FILTCAPG * 6; - fcb = FILTCAPB * 5; + fcr = FILTCAP * 5; + fcg = FILTCAPG * 6; + fcb = FILTCAPB * 5; - for (g=0;g FILTCAP) - difference = FILTCAP; - if (difference < -FILTCAP) - difference = -FILTCAP; + if (difference > FILTCAP) + difference = FILTCAP; + if (difference < -FILTCAP) + difference = -FILTCAP; - if (diffg > FILTCAPG) - diffg = FILTCAPG; - if (diffg < -FILTCAPG) - diffg = -FILTCAPG; + if (diffg > FILTCAPG) + diffg = FILTCAPG; + if (diffg < -FILTCAPG) + diffg = -FILTCAPG; - if (diffb > FILTCAPB) - diffb = FILTCAPB; - if (diffb < -FILTCAPB) - diffb = -FILTCAPB; + if (diffb > FILTCAPB) + diffb = FILTCAPB; + if (diffb < -FILTCAPB) + diffb = -FILTCAPB; - // hack - to make it not bleed onto black - //if (g == 0){ - //difference = diffg = diffb = 0; - //} + // hack - to make it not bleed onto black + // if (g == 0){ + // difference = diffg = diffb = 0; + //} - if ((difference < fcr) || (-difference > -fcr)) - thiscol = g + (difference / 2); - if ((diffg < fcg) || (-diffg > -fcg)) - thiscolg = g + (diffg / 2); /* need these divides so we can actually undither! */ - if ((diffb < fcb) || (-diffb > -fcb)) - thiscolb = g + (diffb / 2); + if ((difference < fcr) || (-difference > -fcr)) + thiscol = g + (difference / 2); + if ((diffg < fcg) || (-diffg > -fcg)) + thiscolg = g + (diffg / 2); /* need these divides so we can actually undither! */ + if ((diffb < fcb) || (-diffb > -fcb)) + thiscolb = g + (diffb / 2); - if (thiscol < 0) - thiscol = 0; - if (thiscol > FILTDIV-1) - thiscol = FILTDIV-1; + if (thiscol < 0) + thiscol = 0; + if (thiscol > FILTDIV - 1) + thiscol = FILTDIV - 1; - if (thiscolg < 0) - thiscolg = 0; - if (thiscolg > FILTDIV-1) - thiscolg = FILTDIV-1; + if (thiscolg < 0) + thiscolg = 0; + if (thiscolg > FILTDIV - 1) + thiscolg = FILTDIV - 1; - if (thiscolb < 0) - thiscolb = 0; - if (thiscolb > FILTDIV-1) - thiscolb = FILTDIV-1; + if (thiscolb < 0) + thiscolb = 0; + if (thiscolb > FILTDIV - 1) + thiscolb = FILTDIV - 1; - voodoo->thefilter[g][h] = thiscol; - voodoo->thefilterg[g][h] = thiscolg; - voodoo->thefilterb[g][h] = thiscolb; - } - - lined = g + 4; - if (lined > 255) - lined = 255; - voodoo->purpleline[g][0] = lined; - voodoo->purpleline[g][2] = lined; - - lined = g + 0; - if (lined > 255) - lined = 255; - voodoo->purpleline[g][1] = lined; + voodoo->thefilter[g][h] = thiscol; + voodoo->thefilterg[g][h] = thiscolg; + voodoo->thefilterb[g][h] = thiscolb; } + + lined = g + 4; + if (lined > 255) + lined = 255; + voodoo->purpleline[g][0] = lined; + voodoo->purpleline[g][2] = lined; + + lined = g + 0; + if (lined > 255) + lined = 255; + voodoo->purpleline[g][1] = lined; + } } -void voodoo_generate_filter_v2(voodoo_t *voodoo) +void +voodoo_generate_filter_v2(voodoo_t *voodoo) { - int g, h; - float difference; - float thiscol, thiscolg, thiscolb; - float clr, clg, clb = 0; - float fcr, fcg, fcb = 0; + float difference; + float thiscol; + float thiscolg; + float thiscolb; + float clr; + float clg; + float clb = 0; + float fcr; + float fcg; + float fcb = 0; - // pre-clamping + // pre-clamping - fcr = FILTCAP; - fcg = FILTCAPG; - fcb = FILTCAPB; + fcr = FILTCAP; + fcg = FILTCAPG; + fcb = FILTCAPB; - if (fcr > 32) fcr = 32; - if (fcg > 32) fcg = 32; - if (fcb > 32) fcb = 32; + if (fcr > 32) + fcr = 32; + if (fcg > 32) + fcg = 32; + if (fcb > 32) + fcb = 32; - for (g=0;g<256;g++) // pixel 1 - our target pixel we want to bleed into + for (uint16_t g = 0; g < 256; g++) // pixel 1 - our target pixel we want to bleed into + { + for (uint16_t h = 0; h < 256; h++) // pixel 2 - our main pixel { - for (h=0;h<256;h++) // pixel 2 - our main pixel - { - float avg; - float avgdiff; + float avg; + float avgdiff; - difference = (float)(g - h); - avg = (float)((g + g + g + g + h) / 5); - avgdiff = avg - (float)((g + h + h + h + h) / 5); - if (avgdiff < 0) avgdiff *= -1; - if (difference < 0) difference *= -1; + difference = (float) (g - h); + avg = (float) ((g + g + g + g + h) / 5); + avgdiff = avg - (float) ((g + h + h + h + h) / 5); + if (avgdiff < 0) + avgdiff *= -1; + if (difference < 0) + difference *= -1; - thiscol = thiscolg = thiscolb = g; + thiscol = thiscolg = thiscolb = g; - // try lighten - if (h > g) - { - clr = clg = clb = avgdiff; + // try lighten + if (h > g) { + clr = clg = clb = avgdiff; - if (clr>fcr) clr=fcr; - if (clg>fcg) clg=fcg; - if (clb>fcb) clb=fcb; + if (clr > fcr) + clr = fcr; + if (clg > fcg) + clg = fcg; + if (clb > fcb) + clb = fcb; + thiscol = g + clr; + thiscolg = g + clg; + thiscolb = g + clb; - thiscol = g + clr; - thiscolg = g + clg; - thiscolb = g + clb; + if (thiscol > g + FILTCAP) + thiscol = g + FILTCAP; + if (thiscolg > g + FILTCAPG) + thiscolg = g + FILTCAPG; + if (thiscolb > g + FILTCAPB) + thiscolb = g + FILTCAPB; - if (thiscol>g+FILTCAP) - thiscol=g+FILTCAP; - if (thiscolg>g+FILTCAPG) - thiscolg=g+FILTCAPG; - if (thiscolb>g+FILTCAPB) - thiscolb=g+FILTCAPB; + if (thiscol > g + avgdiff) + thiscol = g + avgdiff; + if (thiscolg > g + avgdiff) + thiscolg = g + avgdiff; + if (thiscolb > g + avgdiff) + thiscolb = g + avgdiff; + } + if (difference > FILTCAP) + thiscol = g; + if (difference > FILTCAPG) + thiscolg = g; + if (difference > FILTCAPB) + thiscolb = g; - if (thiscol>g+avgdiff) - thiscol=g+avgdiff; - if (thiscolg>g+avgdiff) - thiscolg=g+avgdiff; - if (thiscolb>g+avgdiff) - thiscolb=g+avgdiff; + // clamp + if (thiscol < 0) + thiscol = 0; + if (thiscolg < 0) + thiscolg = 0; + if (thiscolb < 0) + thiscolb = 0; - } + if (thiscol > 255) + thiscol = 255; + if (thiscolg > 255) + thiscolg = 255; + if (thiscolb > 255) + thiscolb = 255; - if (difference > FILTCAP) - thiscol = g; - if (difference > FILTCAPG) - thiscolg = g; - if (difference > FILTCAPB) - thiscolb = g; - - // clamp - if (thiscol < 0) thiscol = 0; - if (thiscolg < 0) thiscolg = 0; - if (thiscolb < 0) thiscolb = 0; - - if (thiscol > 255) thiscol = 255; - if (thiscolg > 255) thiscolg = 255; - if (thiscolb > 255) thiscolb = 255; - - // add to the table - voodoo->thefilter[g][h] = (thiscol); - voodoo->thefilterg[g][h] = (thiscolg); - voodoo->thefilterb[g][h] = (thiscolb); - - // debug the ones that don't give us much of a difference - //if (difference < FILTCAP) - //voodoodisp_log("Voodoofilter: %ix%i - %f difference, %f average difference, R=%f, G=%f, B=%f\n", g, h, difference, avgdiff, thiscol, thiscolg, thiscolb); - } + // add to the table + voodoo->thefilter[g][h] = thiscol; + voodoo->thefilterg[g][h] = thiscolg; + voodoo->thefilterb[g][h] = thiscolb; + // debug the ones that don't give us much of a difference + // if (difference < FILTCAP) + // voodoodisp_log("Voodoofilter: %ix%i - %f difference, %f average difference, R=%f, G=%f, B=%f\n", g, h, difference, avgdiff, thiscol, thiscolg, thiscolb); } + } } -void voodoo_threshold_check(voodoo_t *voodoo) +void +voodoo_threshold_check(voodoo_t *voodoo) { - int r, g, b; + int r; + int g; + int b; - if (!voodoo->scrfilterEnabled) - return; /* considered disabled; don't check and generate */ + if (!voodoo->scrfilterEnabled) + return; /* considered disabled; don't check and generate */ - /* Check for changes, to generate anew table */ - if (voodoo->scrfilterThreshold != voodoo->scrfilterThresholdOld) - { - r = (voodoo->scrfilterThreshold >> 16) & 0xFF; - g = (voodoo->scrfilterThreshold >> 8 ) & 0xFF; - b = voodoo->scrfilterThreshold & 0xFF; + /* Check for changes, to generate anew table */ + if (voodoo->scrfilterThreshold != voodoo->scrfilterThresholdOld) { + r = (voodoo->scrfilterThreshold >> 16) & 0xFF; + g = (voodoo->scrfilterThreshold >> 8) & 0xFF; + b = voodoo->scrfilterThreshold & 0xFF; - FILTCAP = r; - FILTCAPG = g; - FILTCAPB = b; + FILTCAP = r; + FILTCAPG = g; + FILTCAPB = b; - voodoodisp_log("Voodoo Filter Threshold Check: %06x - RED %i GREEN %i BLUE %i\n", voodoo->scrfilterThreshold, r, g, b); + voodoodisp_log("Voodoo Filter Threshold Check: %06x - RED %i GREEN %i BLUE %i\n", voodoo->scrfilterThreshold, r, g, b); - voodoo->scrfilterThresholdOld = voodoo->scrfilterThreshold; + voodoo->scrfilterThresholdOld = voodoo->scrfilterThreshold; - if (voodoo->type == VOODOO_2) - voodoo_generate_filter_v2(voodoo); - else - voodoo_generate_filter_v1(voodoo); - - if (voodoo->type >= VOODOO_BANSHEE) - voodoo_generate_vb_filters(voodoo, FILTCAP, FILTCAPG); - } -} - -static void voodoo_filterline_v1(voodoo_t *voodoo, uint8_t *fil, int column, uint16_t *src, int line) -{ - int x; - - // Scratchpad for avoiding feedback streaks - uint8_t *fil3 = malloc((voodoo->h_disp) * 3); - - /* 16 to 32-bit */ - for (x=0; x> 5) & 63) << 2); - fil[x*3+2] = (((src[x] >> 11) & 31) << 3); - - // Copy to our scratchpads - fil3[x*3+0] = fil[x*3+0]; - fil3[x*3+1] = fil[x*3+1]; - fil3[x*3+2] = fil[x*3+2]; - } - - - /* lines */ - - if (line & 1) - { - for (x=0; xpurpleline[fil[x*3]][0]; - fil[x*3+1] = voodoo->purpleline[fil[x*3+1]][1]; - fil[x*3+2] = voodoo->purpleline[fil[x*3+2]][2]; - } - } - - - /* filtering time */ - - for (x=1; xthefilterb[fil[x*3]][fil[ (x-1) *3]]; - fil3[(x)*3+1] = voodoo->thefilterg[fil[x*3+1]][fil[ (x-1) *3+1]]; - fil3[(x)*3+2] = voodoo->thefilter[fil[x*3+2]][fil[ (x-1) *3+2]]; - } - - for (x=1; xthefilterb[fil3[x*3]][fil3[ (x-1) *3]]; - fil[(x)*3+1] = voodoo->thefilterg[fil3[x*3+1]][fil3[ (x-1) *3+1]]; - fil[(x)*3+2] = voodoo->thefilter[fil3[x*3+2]][fil3[ (x-1) *3+2]]; - } - - for (x=1; xthefilterb[fil[x*3]][fil[ (x-1) *3]]; - fil3[(x)*3+1] = voodoo->thefilterg[fil[x*3+1]][fil[ (x-1) *3+1]]; - fil3[(x)*3+2] = voodoo->thefilter[fil[x*3+2]][fil[ (x-1) *3+2]]; - } - - for (x=0; xthefilterb[fil3[x*3]][fil3[ (x+1) *3]]; - fil[(x)*3+1] = voodoo->thefilterg[fil3[x*3+1]][fil3[ (x+1) *3+1]]; - fil[(x)*3+2] = voodoo->thefilter[fil3[x*3+2]][fil3[ (x+1) *3+2]]; - } - - free(fil3); -} - - -static void voodoo_filterline_v2(voodoo_t *voodoo, uint8_t *fil, int column, uint16_t *src, int line) -{ - int x; - - // Scratchpad for blending filter - uint8_t *fil3 = malloc((voodoo->h_disp) * 3); - - /* 16 to 32-bit */ - for (x=0; x> 5) & 63) << 2); - fil3[x*3+2] = fil[x*3+2] = (((src[x] >> 11) & 31) << 3); - } - - /* filtering time */ - - for (x=1; xthefilterb [((src[x+3] & 31) << 3)] [((src[x] & 31) << 3)]; - fil3[(x+3)*3+1] = voodoo->thefilterg [(((src[x+3] >> 5) & 63) << 2)] [(((src[x] >> 5) & 63) << 2)]; - fil3[(x+3)*3+2] = voodoo->thefilter [(((src[x+3] >> 11) & 31) << 3)] [(((src[x] >> 11) & 31) << 3)]; - - fil[(x+2)*3] = voodoo->thefilterb [fil3[(x+2)*3]][((src[x] & 31) << 3)]; - fil[(x+2)*3+1] = voodoo->thefilterg [fil3[(x+2)*3+1]][(((src[x] >> 5) & 63) << 2)]; - fil[(x+2)*3+2] = voodoo->thefilter [fil3[(x+2)*3+2]][(((src[x] >> 11) & 31) << 3)]; - - fil3[(x+1)*3] = voodoo->thefilterb [fil[(x+1)*3]][((src[x] & 31) << 3)]; - fil3[(x+1)*3+1] = voodoo->thefilterg [fil[(x+1)*3+1]][(((src[x] >> 5) & 63) << 2)]; - fil3[(x+1)*3+2] = voodoo->thefilter [fil[(x+1)*3+2]][(((src[x] >> 11) & 31) << 3)]; - - fil[(x-1)*3] = voodoo->thefilterb [fil3[(x-1)*3]][((src[x] & 31) << 3)]; - fil[(x-1)*3+1] = voodoo->thefilterg [fil3[(x-1)*3+1]][(((src[x] >> 5) & 63) << 2)]; - fil[(x-1)*3+2] = voodoo->thefilter [fil3[(x-1)*3+2]][(((src[x] >> 11) & 31) << 3)]; - } - - // unroll for edge cases - - fil3[(column-3)*3] = voodoo->thefilterb [((src[column-3] & 31) << 3)] [((src[column] & 31) << 3)]; - fil3[(column-3)*3+1] = voodoo->thefilterg [(((src[column-3] >> 5) & 63) << 2)] [(((src[column] >> 5) & 63) << 2)]; - fil3[(column-3)*3+2] = voodoo->thefilter [(((src[column-3] >> 11) & 31) << 3)] [(((src[column] >> 11) & 31) << 3)]; - - fil3[(column-2)*3] = voodoo->thefilterb [((src[column-2] & 31) << 3)] [((src[column] & 31) << 3)]; - fil3[(column-2)*3+1] = voodoo->thefilterg [(((src[column-2] >> 5) & 63) << 2)] [(((src[column] >> 5) & 63) << 2)]; - fil3[(column-2)*3+2] = voodoo->thefilter [(((src[column-2] >> 11) & 31) << 3)] [(((src[column] >> 11) & 31) << 3)]; - - fil3[(column-1)*3] = voodoo->thefilterb [((src[column-1] & 31) << 3)] [((src[column] & 31) << 3)]; - fil3[(column-1)*3+1] = voodoo->thefilterg [(((src[column-1] >> 5) & 63) << 2)] [(((src[column] >> 5) & 63) << 2)]; - fil3[(column-1)*3+2] = voodoo->thefilter [(((src[column-1] >> 11) & 31) << 3)] [(((src[column] >> 11) & 31) << 3)]; - - fil[(column-2)*3] = voodoo->thefilterb [fil3[(column-2)*3]][((src[column] & 31) << 3)]; - fil[(column-2)*3+1] = voodoo->thefilterg [fil3[(column-2)*3+1]][(((src[column] >> 5) & 63) << 2)]; - fil[(column-2)*3+2] = voodoo->thefilter [fil3[(column-2)*3+2]][(((src[column] >> 11) & 31) << 3)]; - - fil[(column-1)*3] = voodoo->thefilterb [fil3[(column-1)*3]][((src[column] & 31) << 3)]; - fil[(column-1)*3+1] = voodoo->thefilterg [fil3[(column-1)*3+1]][(((src[column] >> 5) & 63) << 2)]; - fil[(column-1)*3+2] = voodoo->thefilter [fil3[(column-1)*3+2]][(((src[column] >> 11) & 31) << 3)]; - - fil3[(column-1)*3] = voodoo->thefilterb [fil[(column-1)*3]][((src[column] & 31) << 3)]; - fil3[(column-1)*3+1] = voodoo->thefilterg [fil[(column-1)*3+1]][(((src[column] >> 5) & 63) << 2)]; - fil3[(column-1)*3+2] = voodoo->thefilter [fil[(column-1)*3+2]][(((src[column] >> 11) & 31) << 3)]; - - free(fil3); -} - -void voodoo_callback(void *p) -{ - voodoo_t *voodoo = (voodoo_t *)p; - - if (voodoo->fbiInit0 & FBIINIT0_VGA_PASS) - { - if (voodoo->line < voodoo->v_disp) - { - voodoo_t *draw_voodoo; - int draw_line; - - if (SLI_ENABLED) - { - if (voodoo == voodoo->set->voodoos[1]) - goto skip_draw; - - if (((voodoo->initEnable & INITENABLE_SLI_MASTER_SLAVE) ? 1 : 0) == (voodoo->line & 1)) - draw_voodoo = voodoo; - else - draw_voodoo = voodoo->set->voodoos[1]; - draw_line = voodoo->line >> 1; - } - else - { - if (!(voodoo->fbiInit0 & 1)) - goto skip_draw; - draw_voodoo = voodoo; - draw_line = voodoo->line; - } - - if (draw_voodoo->dirty_line[draw_line]) - { - uint32_t *p = &buffer32->line[voodoo->line + 8][8]; - uint16_t *src = (uint16_t *)&draw_voodoo->fb_mem[draw_voodoo->front_offset + draw_line*draw_voodoo->row_width]; - int x; - - draw_voodoo->dirty_line[draw_line] = 0; - - if (voodoo->line < voodoo->dirty_line_low) - { - voodoo->dirty_line_low = voodoo->line; - video_wait_for_buffer(); - } - if (voodoo->line > voodoo->dirty_line_high) - voodoo->dirty_line_high = voodoo->line; - - /* Draw left overscan. */ - for (x = 0; x < 8; x++) - buffer32->line[voodoo->line + 8][x] = 0x00000000; - - if (voodoo->scrfilter && voodoo->scrfilterEnabled) - { - uint8_t *fil = malloc((voodoo->h_disp) * 3); /* interleaved 24-bit RGB */ - - if (voodoo->type == VOODOO_2) - voodoo_filterline_v2(voodoo, fil, voodoo->h_disp, src, voodoo->line); - else - voodoo_filterline_v1(voodoo, fil, voodoo->h_disp, src, voodoo->line); - - for (x = 0; x < voodoo->h_disp; x++) - { - p[x] = (voodoo->clutData256[fil[x*3]].b << 0 | voodoo->clutData256[fil[x*3+1]].g << 8 | voodoo->clutData256[fil[x*3+2]].r << 16); - } - - free(fil); - } - else - { - for (x = 0; x < voodoo->h_disp; x++) - { - p[x] = draw_voodoo->video_16to32[src[x]]; - } - } - - /* Draw right overscan. */ - for (x = 0; x < 8; x++) - buffer32->line[voodoo->line + 8][voodoo->h_disp + x + 8] = 0x00000000; - } - } - } -skip_draw: - if (voodoo->line == voodoo->v_disp) - { -// voodoodisp_log("retrace %i %i %08x %i\n", voodoo->retrace_count, voodoo->swap_interval, voodoo->swap_offset, voodoo->swap_pending); - voodoo->retrace_count++; - if (SLI_ENABLED && (voodoo->fbiInit2 & FBIINIT2_SWAP_ALGORITHM_MASK) == FBIINIT2_SWAP_ALGORITHM_SLI_SYNC) - { - if (voodoo == voodoo->set->voodoos[0]) - { - voodoo_t *voodoo_1 = voodoo->set->voodoos[1]; - - thread_wait_mutex(voodoo->swap_mutex); - /*Only swap if both Voodoos are waiting for buffer swap*/ - if (voodoo->swap_pending && (voodoo->retrace_count > voodoo->swap_interval) && - voodoo_1->swap_pending && (voodoo_1->retrace_count > voodoo_1->swap_interval)) - { - memset(voodoo->dirty_line, 1, 1024); - voodoo->retrace_count = 0; - voodoo->front_offset = voodoo->swap_offset; - if (voodoo->swap_count > 0) - voodoo->swap_count--; - voodoo->swap_pending = 0; - - memset(voodoo_1->dirty_line, 1, 1024); - voodoo_1->retrace_count = 0; - voodoo_1->front_offset = voodoo_1->swap_offset; - if (voodoo_1->swap_count > 0) - voodoo_1->swap_count--; - voodoo_1->swap_pending = 0; - thread_release_mutex(voodoo->swap_mutex); - - thread_set_event(voodoo->wake_fifo_thread); - thread_set_event(voodoo_1->wake_fifo_thread); - - voodoo->frame_count++; - voodoo_1->frame_count++; - } - else - thread_release_mutex(voodoo->swap_mutex); - } - } - else - { - thread_wait_mutex(voodoo->swap_mutex); - if (voodoo->swap_pending && (voodoo->retrace_count > voodoo->swap_interval)) - { - voodoo->front_offset = voodoo->swap_offset; - if (voodoo->swap_count > 0) - voodoo->swap_count--; - voodoo->swap_pending = 0; - thread_release_mutex(voodoo->swap_mutex); - - memset(voodoo->dirty_line, 1, 1024); - voodoo->retrace_count = 0; - thread_set_event(voodoo->wake_fifo_thread); - voodoo->frame_count++; - } - else - thread_release_mutex(voodoo->swap_mutex); - } - voodoo->v_retrace = 1; - } - voodoo->line++; - - if (voodoo->fbiInit0 & FBIINIT0_VGA_PASS) - { - if (voodoo->line == voodoo->v_disp) - { - int force_blit = 0; - thread_wait_mutex(voodoo->force_blit_mutex); - if(voodoo->force_blit_count) { - force_blit = 1; - if(--voodoo->force_blit_count < 0) - voodoo->force_blit_count = 0; - } - thread_release_mutex(voodoo->force_blit_mutex); - - if (voodoo->dirty_line_high > voodoo->dirty_line_low || force_blit) - svga_doblit(voodoo->h_disp, voodoo->v_disp-1, voodoo->svga); - if (voodoo->clutData_dirty) - { - voodoo->clutData_dirty = 0; - voodoo_calc_clutData(voodoo); - } - voodoo->dirty_line_high = -1; - voodoo->dirty_line_low = 2000; - } - } - - if (voodoo->line >= voodoo->v_total) - { - voodoo->line = 0; - voodoo->v_retrace = 0; - } - if (voodoo->line_time) - timer_advance_u64(&voodoo->timer, voodoo->line_time); + if (voodoo->type == VOODOO_2) + voodoo_generate_filter_v2(voodoo); else - timer_advance_u64(&voodoo->timer, TIMER_USEC * 32); + voodoo_generate_filter_v1(voodoo); + + if (voodoo->type >= VOODOO_BANSHEE) + voodoo_generate_vb_filters(voodoo, FILTCAP, FILTCAPG); + } +} + +static void +voodoo_filterline_v1(voodoo_t *voodoo, uint8_t *fil, int column, uint16_t *src, int line) +{ + // Scratchpad for avoiding feedback streaks + uint8_t fil3[4096 * 3]; + + assert(voodoo->h_disp <= 4096); + /* 16 to 32-bit */ + for (int x = 0; x < column; x++) { + fil[x * 3] = ((src[x] & 31) << 3); + fil[x * 3 + 1] = (((src[x] >> 5) & 63) << 2); + fil[x * 3 + 2] = (((src[x] >> 11) & 31) << 3); + + // Copy to our scratchpads + fil3[x * 3 + 0] = fil[x * 3 + 0]; + fil3[x * 3 + 1] = fil[x * 3 + 1]; + fil3[x * 3 + 2] = fil[x * 3 + 2]; + } + + /* lines */ + + if (line & 1) { + for (int x = 0; x < column; x++) { + fil[x * 3] = voodoo->purpleline[fil[x * 3]][0]; + fil[x * 3 + 1] = voodoo->purpleline[fil[x * 3 + 1]][1]; + fil[x * 3 + 2] = voodoo->purpleline[fil[x * 3 + 2]][2]; + } + } + + /* filtering time */ + + for (int x = 1; x < column; x++) { + fil3[x * 3] = voodoo->thefilterb[fil[x * 3]][fil[(x - 1) * 3]]; + fil3[x * 3 + 1] = voodoo->thefilterg[fil[x * 3 + 1]][fil[(x - 1) * 3 + 1]]; + fil3[x * 3 + 2] = voodoo->thefilter[fil[x * 3 + 2]][fil[(x - 1) * 3 + 2]]; + } + + for (int x = 1; x < column; x++) { + fil[x * 3] = voodoo->thefilterb[fil3[x * 3]][fil3[(x - 1) * 3]]; + fil[x * 3 + 1] = voodoo->thefilterg[fil3[x * 3 + 1]][fil3[(x - 1) * 3 + 1]]; + fil[x * 3 + 2] = voodoo->thefilter[fil3[x * 3 + 2]][fil3[(x - 1) * 3 + 2]]; + } + + for (int x = 1; x < column; x++) { + fil3[x * 3] = voodoo->thefilterb[fil[x * 3]][fil[(x - 1) * 3]]; + fil3[x * 3 + 1] = voodoo->thefilterg[fil[x * 3 + 1]][fil[(x - 1) * 3 + 1]]; + fil3[x * 3 + 2] = voodoo->thefilter[fil[x * 3 + 2]][fil[(x - 1) * 3 + 2]]; + } + + for (int x = 0; x < column - 1; x++) { + fil[x * 3] = voodoo->thefilterb[fil3[x * 3]][fil3[(x + 1) * 3]]; + fil[x * 3 + 1] = voodoo->thefilterg[fil3[x * 3 + 1]][fil3[(x + 1) * 3 + 1]]; + fil[x * 3 + 2] = voodoo->thefilter[fil3[x * 3 + 2]][fil3[(x + 1) * 3 + 2]]; + } +} + +static void +voodoo_filterline_v2(voodoo_t *voodoo, uint8_t *fil, int column, uint16_t *src, UNUSED(int line)) +{ + int x; + + // Scratchpad for blending filter + uint8_t fil3[4096 * 3]; + + assert(voodoo->h_disp <= 4096); + /* 16 to 32-bit */ + for (x = 0; x < column; x++) { + // Blank scratchpads + fil3[x * 3 + 0] = fil[x * 3 + 0] = ((src[x] & 31) << 3); + fil3[x * 3 + 1] = fil[x * 3 + 1] = (((src[x] >> 5) & 63) << 2); + fil3[x * 3 + 2] = fil[x * 3 + 2] = (((src[x] >> 11) & 31) << 3); + } + + /* filtering time */ + + for (x = 1; x < column - 3; x++) { + fil3[(x + 3) * 3] = voodoo->thefilterb[(src[x + 3] & 31) << 3][(src[x] & 31) << 3]; + fil3[(x + 3) * 3 + 1] = voodoo->thefilterg[((src[x + 3] >> 5) & 63) << 2][((src[x] >> 5) & 63) << 2]; + fil3[(x + 3) * 3 + 2] = voodoo->thefilter[((src[x + 3] >> 11) & 31) << 3][((src[x] >> 11) & 31) << 3]; + + fil[(x + 2) * 3] = voodoo->thefilterb[fil3[(x + 2) * 3]][(src[x] & 31) << 3]; + fil[(x + 2) * 3 + 1] = voodoo->thefilterg[fil3[(x + 2) * 3 + 1]][((src[x] >> 5) & 63) << 2]; + fil[(x + 2) * 3 + 2] = voodoo->thefilter[fil3[(x + 2) * 3 + 2]][((src[x] >> 11) & 31) << 3]; + + fil3[(x + 1) * 3] = voodoo->thefilterb[fil[(x + 1) * 3]][(src[x] & 31) << 3]; + fil3[(x + 1) * 3 + 1] = voodoo->thefilterg[fil[(x + 1) * 3 + 1]][((src[x] >> 5) & 63) << 2]; + fil3[(x + 1) * 3 + 2] = voodoo->thefilter[fil[(x + 1) * 3 + 2]][((src[x] >> 11) & 31) << 3]; + + fil[(x - 1) * 3] = voodoo->thefilterb[fil3[(x - 1) * 3]][(src[x] & 31) << 3]; + fil[(x - 1) * 3 + 1] = voodoo->thefilterg[fil3[(x - 1) * 3 + 1]][((src[x] >> 5) & 63) << 2]; + fil[(x - 1) * 3 + 2] = voodoo->thefilter[fil3[(x - 1) * 3 + 2]][((src[x] >> 11) & 31) << 3]; + } + + // unroll for edge cases + + fil3[(column - 3) * 3] = voodoo->thefilterb[(src[column - 3] & 31) << 3][(src[column] & 31) << 3]; + fil3[(column - 3) * 3 + 1] = voodoo->thefilterg[((src[column - 3] >> 5) & 63) << 2][((src[column] >> 5) & 63) << 2]; + fil3[(column - 3) * 3 + 2] = voodoo->thefilter[((src[column - 3] >> 11) & 31) << 3][((src[column] >> 11) & 31) << 3]; + + fil3[(column - 2) * 3] = voodoo->thefilterb[(src[column - 2] & 31) << 3][(src[column] & 31) << 3]; + fil3[(column - 2) * 3 + 1] = voodoo->thefilterg[((src[column - 2] >> 5) & 63) << 2][((src[column] >> 5) & 63) << 2]; + fil3[(column - 2) * 3 + 2] = voodoo->thefilter[((src[column - 2] >> 11) & 31) << 3][((src[column] >> 11) & 31) << 3]; + + fil3[(column - 1) * 3] = voodoo->thefilterb[(src[column - 1] & 31) << 3][(src[column] & 31) << 3]; + fil3[(column - 1) * 3 + 1] = voodoo->thefilterg[((src[column - 1] >> 5) & 63) << 2][((src[column] >> 5) & 63) << 2]; + fil3[(column - 1) * 3 + 2] = voodoo->thefilter[((src[column - 1] >> 11) & 31) << 3][((src[column] >> 11) & 31) << 3]; + + fil[(column - 2) * 3] = voodoo->thefilterb[fil3[(column - 2) * 3]][(src[column] & 31) << 3]; + fil[(column - 2) * 3 + 1] = voodoo->thefilterg[fil3[(column - 2) * 3 + 1]][((src[column] >> 5) & 63) << 2]; + fil[(column - 2) * 3 + 2] = voodoo->thefilter[fil3[(column - 2) * 3 + 2]][((src[column] >> 11) & 31) << 3]; + + fil[(column - 1) * 3] = voodoo->thefilterb[fil3[(column - 1) * 3]][(src[column] & 31) << 3]; + fil[(column - 1) * 3 + 1] = voodoo->thefilterg[fil3[(column - 1) * 3 + 1]][((src[column] >> 5) & 63) << 2]; + fil[(column - 1) * 3 + 2] = voodoo->thefilter[fil3[(column - 1) * 3 + 2]][((src[column] >> 11) & 31) << 3]; + + fil3[(column - 1) * 3] = voodoo->thefilterb[fil[(column - 1) * 3]][(src[column] & 31) << 3]; + fil3[(column - 1) * 3 + 1] = voodoo->thefilterg[fil[(column - 1) * 3 + 1]][((src[column] >> 5) & 63) << 2]; + fil3[(column - 1) * 3 + 2] = voodoo->thefilter[fil[(column - 1) * 3 + 2]][((src[column] >> 11) & 31) << 3]; +} + +void +voodoo_callback(void *priv) +{ + voodoo_t *voodoo = (voodoo_t *) priv; + const monitor_t *monitor = &monitors[voodoo->monitor_index]; + + if (voodoo->fbiInit0 & FBIINIT0_VGA_PASS) { + if (voodoo->line < voodoo->v_disp) { + voodoo_t *draw_voodoo; + int draw_line; + + if (SLI_ENABLED) { + if (voodoo == voodoo->set->voodoos[1]) + goto skip_draw; + + if (((voodoo->initEnable & INITENABLE_SLI_MASTER_SLAVE) ? 1 : 0) == (voodoo->line & 1)) + draw_voodoo = voodoo; + else + draw_voodoo = voodoo->set->voodoos[1]; + draw_line = voodoo->line >> 1; + } else { + if (!(voodoo->fbiInit0 & 1)) + goto skip_draw; + draw_voodoo = voodoo; + draw_line = voodoo->line; + } + + if (draw_voodoo->dirty_line[draw_line]) { + uint32_t *p = &monitor->target_buffer->line[voodoo->line + 8][8]; + uint16_t *src = (uint16_t *) &draw_voodoo->fb_mem[draw_voodoo->front_offset + draw_line * draw_voodoo->row_width]; + int x; + + draw_voodoo->dirty_line[draw_line] = 0; + + if (voodoo->line < voodoo->dirty_line_low) { + voodoo->dirty_line_low = voodoo->line; + video_wait_for_buffer_monitor(voodoo->monitor_index); + } + if (voodoo->line > voodoo->dirty_line_high) + voodoo->dirty_line_high = voodoo->line; + + /* Draw left overscan. */ + for (x = 0; x < 8; x++) + monitor->target_buffer->line[voodoo->line + 8][x] = 0x00000000; + + if (voodoo->scrfilter && voodoo->scrfilterEnabled) { + uint8_t fil[4096 * 3]; /* interleaved 24-bit RGB */ + + assert(voodoo->h_disp <= 4096); + if (voodoo->type == VOODOO_2) + voodoo_filterline_v2(voodoo, fil, voodoo->h_disp, src, voodoo->line); + else + voodoo_filterline_v1(voodoo, fil, voodoo->h_disp, src, voodoo->line); + + for (x = 0; x < voodoo->h_disp; x++) { + p[x] = (voodoo->clutData256[fil[x * 3]].b << 0 | voodoo->clutData256[fil[x * 3 + 1]].g << 8 | voodoo->clutData256[fil[x * 3 + 2]].r << 16); + } + } else { + for (x = 0; x < voodoo->h_disp; x++) { + p[x] = draw_voodoo->video_16to32[src[x]]; + } + } + + /* Draw right overscan. */ + for (x = 0; x < 8; x++) + monitor->target_buffer->line[voodoo->line + 8][voodoo->h_disp + x + 8] = 0x00000000; + } + } + } +skip_draw: + if (voodoo->line == voodoo->v_disp) { +#if 0 + voodoodisp_log("retrace %i %i %08x %i\n", voodoo->retrace_count, voodoo->swap_interval, voodoo->swap_offset, voodoo->swap_pending); +#endif + voodoo->retrace_count++; + if (SLI_ENABLED && (voodoo->fbiInit2 & FBIINIT2_SWAP_ALGORITHM_MASK) == FBIINIT2_SWAP_ALGORITHM_SLI_SYNC) { + if (voodoo == voodoo->set->voodoos[0]) { + voodoo_t *voodoo_1 = voodoo->set->voodoos[1]; + + thread_wait_mutex(voodoo->swap_mutex); + /*Only swap if both Voodoos are waiting for buffer swap*/ + if (voodoo->swap_pending && (voodoo->retrace_count > voodoo->swap_interval) && voodoo_1->swap_pending && (voodoo_1->retrace_count > voodoo_1->swap_interval)) { + memset(voodoo->dirty_line, 1, 1024); + voodoo->retrace_count = 0; + voodoo->front_offset = voodoo->swap_offset; + if (voodoo->swap_count > 0) + voodoo->swap_count--; + voodoo->swap_pending = 0; + + memset(voodoo_1->dirty_line, 1, 1024); + voodoo_1->retrace_count = 0; + voodoo_1->front_offset = voodoo_1->swap_offset; + if (voodoo_1->swap_count > 0) + voodoo_1->swap_count--; + voodoo_1->swap_pending = 0; + thread_release_mutex(voodoo->swap_mutex); + + thread_set_event(voodoo->wake_fifo_thread); + thread_set_event(voodoo_1->wake_fifo_thread); + + voodoo->frame_count++; + voodoo_1->frame_count++; + } else + thread_release_mutex(voodoo->swap_mutex); + } + } else { + thread_wait_mutex(voodoo->swap_mutex); + if (voodoo->swap_pending && (voodoo->retrace_count > voodoo->swap_interval)) { + voodoo->front_offset = voodoo->swap_offset; + if (voodoo->swap_count > 0) + voodoo->swap_count--; + voodoo->swap_pending = 0; + thread_release_mutex(voodoo->swap_mutex); + + memset(voodoo->dirty_line, 1, 1024); + voodoo->retrace_count = 0; + thread_set_event(voodoo->wake_fifo_thread); + voodoo->frame_count++; + } else + thread_release_mutex(voodoo->swap_mutex); + } + voodoo->v_retrace = 1; + } + voodoo->line++; + + if (voodoo->fbiInit0 & FBIINIT0_VGA_PASS) { + if (voodoo->line == voodoo->v_disp) { + int force_blit = 0; + thread_wait_mutex(voodoo->force_blit_mutex); + if (voodoo->force_blit_count) { + force_blit = 1; + if (--voodoo->force_blit_count < 0) + voodoo->force_blit_count = 0; + } + thread_release_mutex(voodoo->force_blit_mutex); + + if (voodoo->dirty_line_high > voodoo->dirty_line_low || force_blit) + svga_doblit(voodoo->h_disp, voodoo->v_disp - 1, voodoo->svga); + if (voodoo->clutData_dirty) { + voodoo->clutData_dirty = 0; + voodoo_calc_clutData(voodoo); + } + voodoo->dirty_line_high = -1; + voodoo->dirty_line_low = 2000; + } + } + + if (voodoo->line >= voodoo->v_total) { + voodoo->line = 0; + voodoo->v_retrace = 0; + } + if (voodoo->line_time) + timer_advance_u64(&voodoo->timer, voodoo->line_time); + else + timer_advance_u64(&voodoo->timer, TIMER_USEC * 32); } diff --git a/src/video/vid_voodoo_fb.c b/src/video/vid_voodoo_fb.c index b9ccad399..94394e115 100644 --- a/src/video/vid_voodoo_fb.c +++ b/src/video/vid_voodoo_fb.c @@ -1,19 +1,20 @@ /* - * 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. + * 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. + * This file is part of the 86Box distribution. * - * 3DFX Voodoo emulation. + * 3DFX Voodoo emulation. * * * - * Authors: Sarah Walker, + * Authors: Sarah Walker, * - * Copyright 2008-2020 Sarah Walker. + * Copyright 2008-2020 Sarah Walker. */ +#include #include #include #include @@ -21,6 +22,7 @@ #include #include #include +#define HAVE_STDARG_H #include <86box/86box.h> #include "cpu.h" #include <86box/machine.h> @@ -29,6 +31,7 @@ #include <86box/timer.h> #include <86box/device.h> #include <86box/plat.h> +#include <86box/thread.h> #include <86box/video.h> #include <86box/vid_svga.h> #include <86box/vid_voodoo_common.h> @@ -37,7 +40,6 @@ #include <86box/vid_voodoo_render.h> #include <86box/vid_voodoo_fb.h> - #ifdef ENABLE_VOODOO_FB_LOG int voodoo_fb_do_log = ENABLE_VOODOO_FB_LOG; @@ -47,447 +49,423 @@ voodoo_fb_log(const char *fmt, ...) va_list ap; if (voodoo_fb_do_log) { - va_start(ap, fmt); - pclog_ex(fmt, ap); - va_end(ap); + va_start(ap, fmt); + pclog_ex(fmt, ap); + va_end(ap); } } #else -#define voodoo_fb_log(fmt, ...) +# define voodoo_fb_log(fmt, ...) #endif - -uint16_t voodoo_fb_readw(uint32_t addr, void *p) +uint16_t +voodoo_fb_readw(uint32_t addr, void *priv) { - voodoo_t *voodoo = (voodoo_t *)p; - int x, y; - uint32_t read_addr; - uint16_t temp; + voodoo_t *voodoo = (voodoo_t *) priv; + int x; + int y; + uint32_t read_addr; + uint16_t temp; - if (voodoo->type >= VOODOO_BANSHEE) - { - x = addr & 0xffe; - y = (addr >> 12) & 0x3ff; - } + if (voodoo->type >= VOODOO_BANSHEE) { + x = addr & 0xffe; + y = (addr >> 12) & 0x3ff; + } else { + x = addr & 0x7fe; + y = (addr >> 11) & 0x3ff; + } + + if (SLI_ENABLED) { + const voodoo_set_t *set = voodoo->set; + + if (y & 1) + voodoo = set->voodoos[1]; else - { - x = addr & 0x7fe; - y = (addr >> 11) & 0x3ff; - } + voodoo = set->voodoos[0]; - if (SLI_ENABLED) - { - voodoo_set_t *set = voodoo->set; + y >>= 1; + } - if (y & 1) - voodoo = set->voodoos[1]; - else - voodoo = set->voodoos[0]; + if (voodoo->col_tiled) + read_addr = voodoo->fb_read_offset + (x & 127) + (x >> 7) * 128 * 32 + (y & 31) * 128 + (y >> 5) * voodoo->row_width; + else + read_addr = voodoo->fb_read_offset + x + (y * voodoo->row_width); - y >>= 1; - } + if (read_addr > voodoo->fb_mask) + return 0xffff; - if (voodoo->col_tiled) - read_addr = voodoo->fb_read_offset + (x & 127) + (x >> 7) * 128*32 + (y & 31) * 128 + (y >> 5) * voodoo->row_width; - else - read_addr = voodoo->fb_read_offset + x + (y * voodoo->row_width); + temp = *(uint16_t *) (&voodoo->fb_mem[read_addr & voodoo->fb_mask]); - if (read_addr > voodoo->fb_mask) - return 0xffff; - - temp = *(uint16_t *)(&voodoo->fb_mem[read_addr & voodoo->fb_mask]); - -// voodoo_fb_log("voodoo_fb_readw : %08X %08X %i %i %08X %08X %08x:%08x %i\n", addr, temp, x, y, read_addr, *(uint32_t *)(&voodoo->fb_mem[4]), cs, pc, fb_reads++); - return temp; + // voodoo_fb_log("voodoo_fb_readw : %08X %08X %i %i %08X %08X %08x:%08x %i\n", addr, temp, x, y, read_addr, *(uint32_t *)(&voodoo->fb_mem[4]), cs, pc, fb_reads++); + return temp; } -uint32_t voodoo_fb_readl(uint32_t addr, void *p) +uint32_t +voodoo_fb_readl(uint32_t addr, void *priv) { - voodoo_t *voodoo = (voodoo_t *)p; - int x, y; - uint32_t read_addr; - uint32_t temp; + voodoo_t *voodoo = (voodoo_t *) priv; + int x; + int y; + uint32_t read_addr; + uint32_t temp; - if (voodoo->type >= VOODOO_BANSHEE) - { - x = addr & 0xffe; - y = (addr >> 12) & 0x3ff; - } + if (voodoo->type >= VOODOO_BANSHEE) { + x = addr & 0xffe; + y = (addr >> 12) & 0x3ff; + } else { + x = addr & 0x7fe; + y = (addr >> 11) & 0x3ff; + } + + if (SLI_ENABLED) { + const voodoo_set_t *set = voodoo->set; + + if (y & 1) + voodoo = set->voodoos[1]; else - { - x = addr & 0x7fe; - y = (addr >> 11) & 0x3ff; - } + voodoo = set->voodoos[0]; - if (SLI_ENABLED) - { - voodoo_set_t *set = voodoo->set; + y >>= 1; + } - if (y & 1) - voodoo = set->voodoos[1]; - else - voodoo = set->voodoos[0]; + if (voodoo->col_tiled) + read_addr = voodoo->fb_read_offset + (x & 127) + (x >> 7) * 128 * 32 + (y & 31) * 128 + (y >> 5) * voodoo->row_width; + else + read_addr = voodoo->fb_read_offset + x + (y * voodoo->row_width); - y >>= 1; - } + if (read_addr > voodoo->fb_mask) + return 0xffffffff; - if (voodoo->col_tiled) - read_addr = voodoo->fb_read_offset + (x & 127) + (x >> 7) * 128*32 + (y & 31) * 128 + (y >> 5) * voodoo->row_width; - else - read_addr = voodoo->fb_read_offset + x + (y * voodoo->row_width); + temp = *(uint32_t *) (&voodoo->fb_mem[read_addr & voodoo->fb_mask]); - if (read_addr > voodoo->fb_mask) - return 0xffffffff; - - temp = *(uint32_t *)(&voodoo->fb_mem[read_addr & voodoo->fb_mask]); - -// voodoo_fb_log("voodoo_fb_readl : %08X %08x %08X x=%i y=%i %08X %08X %08x:%08x %i ro=%08x rw=%i\n", addr, read_addr, temp, x, y, read_addr, *(uint32_t *)(&voodoo->fb_mem[4]), cs, pc, fb_reads++, voodoo->fb_read_offset, voodoo->row_width); - return temp; + // voodoo_fb_log("voodoo_fb_readl : %08X %08x %08X x=%i y=%i %08X %08X %08x:%08x %i ro=%08x rw=%i\n", addr, read_addr, temp, x, y, read_addr, *(uint32_t *)(&voodoo->fb_mem[4]), cs, pc, fb_reads++, voodoo->fb_read_offset, voodoo->row_width); + return temp; } -static inline uint16_t do_dither(voodoo_params_t *params, rgba8_t col, int x, int y) +static inline uint16_t +do_dither(voodoo_params_t *params, rgba8_t col, int x, int y) { - int r, g, b; + int r; + int g; + int b; - if (dither) - { - if (dither2x2) - { - r = dither_rb2x2[col.r][y & 1][x & 1]; - g = dither_g2x2[col.g][y & 1][x & 1]; - b = dither_rb2x2[col.b][y & 1][x & 1]; - } - else - { - r = dither_rb[col.r][y & 3][x & 3]; - g = dither_g[col.g][y & 3][x & 3]; - b = dither_rb[col.b][y & 3][x & 3]; - } - } - else - { - r = col.r >> 3; - g = col.g >> 2; - b = col.b >> 3; + if (dither) { + if (dither2x2) { + r = dither_rb2x2[col.r][y & 1][x & 1]; + g = dither_g2x2[col.g][y & 1][x & 1]; + b = dither_rb2x2[col.b][y & 1][x & 1]; + } else { + r = dither_rb[col.r][y & 3][x & 3]; + g = dither_g[col.g][y & 3][x & 3]; + b = dither_rb[col.b][y & 3][x & 3]; } + } else { + r = col.r >> 3; + g = col.g >> 2; + b = col.b >> 3; + } - return b | (g << 5) | (r << 11); + return b | (g << 5) | (r << 11); } -void voodoo_fb_writew(uint32_t addr, uint16_t val, void *p) +void +voodoo_fb_writew(uint32_t addr, uint16_t val, void *priv) { - voodoo_t *voodoo = (voodoo_t *)p; - voodoo_params_t *params = &voodoo->params; - int x, y; - uint32_t write_addr, write_addr_aux; - rgba8_t colour_data; - uint16_t depth_data; - uint8_t alpha_data; - int write_mask = 0; + voodoo_t *voodoo = (voodoo_t *) priv; + const voodoo_params_t *params = &voodoo->params; + int x; + int y; + uint32_t write_addr; + uint32_t write_addr_aux; + rgba8_t colour_data; + uint16_t depth_data; + uint8_t alpha_data; + int write_mask = 0; - colour_data.r = colour_data.g = colour_data.b = colour_data.a = 0; + colour_data.r = colour_data.g = colour_data.b = colour_data.a = 0; - depth_data = voodoo->params.zaColor & 0xffff; - alpha_data = voodoo->params.zaColor >> 24; + depth_data = voodoo->params.zaColor & 0xffff; + alpha_data = voodoo->params.zaColor >> 24; -// while (!RB_EMPTY) -// thread_reset_event(voodoo->not_full_event); +#if 0 + while (!RB_EMPTY) + thread_reset_event(voodoo->not_full_event); +#endif -// voodoo_fb_log("voodoo_fb_writew : %08X %04X\n", addr, val); +#if 0 + voodoo_fb_log("voodoo_fb_writew : %08X %04X\n", addr, val); +#endif + switch (voodoo->lfbMode & LFB_FORMAT_MASK) { + case LFB_FORMAT_RGB565: + colour_data = rgb565[val]; + alpha_data = 0xff; + write_mask = LFB_WRITE_COLOUR; + break; + case LFB_FORMAT_RGB555: + colour_data = argb1555[val]; + alpha_data = 0xff; + write_mask = LFB_WRITE_COLOUR; + break; + case LFB_FORMAT_ARGB1555: + colour_data = argb1555[val]; + alpha_data = colour_data.a; + write_mask = LFB_WRITE_COLOUR; + break; + case LFB_FORMAT_DEPTH: + depth_data = val; + write_mask = LFB_WRITE_DEPTH; + break; - switch (voodoo->lfbMode & LFB_FORMAT_MASK) + default: + fatal("voodoo_fb_writew : bad LFB format %08X\n", voodoo->lfbMode); + } + + if (voodoo->type >= VOODOO_BANSHEE) { + x = addr & 0xffe; + y = (addr >> 12) & 0x3ff; + } else { + x = addr & 0x7fe; + y = (addr >> 11) & 0x3ff; + } + + if (SLI_ENABLED) { + if ((!(voodoo->initEnable & INITENABLE_SLI_MASTER_SLAVE) && (y & 1)) || ((voodoo->initEnable & INITENABLE_SLI_MASTER_SLAVE) && !(y & 1))) + return; + y >>= 1; + } + + if (voodoo->fb_write_offset == voodoo->params.front_offset && y < 2048) + voodoo->dirty_line[y] = 1; + + if (voodoo->col_tiled) + write_addr = voodoo->fb_write_offset + (x & 127) + (x >> 7) * 128 * 32 + (y & 31) * 128 + (y >> 5) * voodoo->row_width; + else + write_addr = voodoo->fb_write_offset + x + (y * voodoo->row_width); + if (voodoo->aux_tiled) + write_addr_aux = voodoo->params.aux_offset + (x & 127) + (x >> 7) * 128 * 32 + (y & 31) * 128 + (y >> 5) * voodoo->row_width; + else + write_addr_aux = voodoo->params.aux_offset + x + (y * voodoo->row_width); + + // voodoo_fb_log("fb_writew %08x %i %i %i %08x\n", addr, x, y, voodoo->row_width, write_addr); + + if (voodoo->lfbMode & 0x100) { { - case LFB_FORMAT_RGB565: - colour_data = rgb565[val]; - alpha_data = 0xff; - write_mask = LFB_WRITE_COLOUR; - break; - case LFB_FORMAT_RGB555: - colour_data = argb1555[val]; - alpha_data = 0xff; - write_mask = LFB_WRITE_COLOUR; - break; - case LFB_FORMAT_ARGB1555: - colour_data = argb1555[val]; - alpha_data = colour_data.a; - write_mask = LFB_WRITE_COLOUR; - break; - case LFB_FORMAT_DEPTH: - depth_data = val; - write_mask = LFB_WRITE_DEPTH; - break; + rgba8_t write_data = colour_data; + uint16_t new_depth = depth_data; - default: - fatal("voodoo_fb_writew : bad LFB format %08X\n", voodoo->lfbMode); - } + if (params->fbzMode & FBZ_DEPTH_ENABLE) { + uint16_t old_depth = *(uint16_t *) (&voodoo->fb_mem[write_addr_aux & voodoo->fb_mask]); - if (voodoo->type >= VOODOO_BANSHEE) - { - x = addr & 0xffe; - y = (addr >> 12) & 0x3ff; - } - else - { - x = addr & 0x7fe; - y = (addr >> 11) & 0x3ff; - } + DEPTH_TEST(new_depth); + } - if (SLI_ENABLED) - { - if ((!(voodoo->initEnable & INITENABLE_SLI_MASTER_SLAVE) && (y & 1)) || - ((voodoo->initEnable & INITENABLE_SLI_MASTER_SLAVE) && !(y & 1))) - return; - y >>= 1; - } + if ((params->fbzMode & FBZ_CHROMAKEY) && write_data.r == params->chromaKey_r && write_data.g == params->chromaKey_g && write_data.b == params->chromaKey_b) + goto skip_pixel; + if (params->fogMode & FOG_ENABLE) { + int32_t z = new_depth << 12; + int64_t w_depth = (int64_t) (int32_t) new_depth; + int32_t ia = alpha_data << 12; - if (voodoo->fb_write_offset == voodoo->params.front_offset && y < 2048) - voodoo->dirty_line[y] = 1; + APPLY_FOG(write_data.r, write_data.g, write_data.b, z, ia, w_depth); + } - if (voodoo->col_tiled) - write_addr = voodoo->fb_write_offset + (x & 127) + (x >> 7) * 128*32 + (y & 31) * 128 + (y >> 5) * voodoo->row_width; - else - write_addr = voodoo->fb_write_offset + x + (y * voodoo->row_width); - if (voodoo->aux_tiled) - write_addr_aux = voodoo->params.aux_offset + (x & 127) + (x >> 7) * 128*32 + (y & 31) * 128 + (y >> 5) * voodoo->row_width; - else - write_addr_aux = voodoo->params.aux_offset + x + (y * voodoo->row_width); + if (params->alphaMode & 1) + ALPHA_TEST(alpha_data); -// voodoo_fb_log("fb_writew %08x %i %i %i %08x\n", addr, x, y, voodoo->row_width, write_addr); + if (params->alphaMode & (1 << 4)) { + uint16_t dat = *(uint16_t *) (&voodoo->fb_mem[write_addr & voodoo->fb_mask]); + int dest_r; + int dest_g; + int dest_b; + int dest_a; - if (voodoo->lfbMode & 0x100) - { - { - rgba8_t write_data = colour_data; - uint16_t new_depth = depth_data; + dest_r = (dat >> 8) & 0xf8; + dest_g = (dat >> 3) & 0xfc; + dest_b = (dat << 3) & 0xf8; + dest_r |= (dest_r >> 5); + dest_g |= (dest_g >> 6); + dest_b |= (dest_b >> 5); + dest_a = 0xff; - if (params->fbzMode & FBZ_DEPTH_ENABLE) - { - uint16_t old_depth = *(uint16_t *)(&voodoo->fb_mem[write_addr_aux & voodoo->fb_mask]); + ALPHA_BLEND(write_data.r, write_data.g, write_data.b, alpha_data); + } - DEPTH_TEST(new_depth); - } - - if ((params->fbzMode & FBZ_CHROMAKEY) && - write_data.r == params->chromaKey_r && - write_data.g == params->chromaKey_g && - write_data.b == params->chromaKey_b) - goto skip_pixel; - - if (params->fogMode & FOG_ENABLE) - { - int32_t z = new_depth << 12; - int64_t w_depth = (int64_t)(int32_t)new_depth; - int32_t ia = alpha_data << 12; - - APPLY_FOG(write_data.r, write_data.g, write_data.b, z, ia, w_depth); - } - - if (params->alphaMode & 1) - ALPHA_TEST(alpha_data); - - if (params->alphaMode & (1 << 4)) - { - uint16_t dat = *(uint16_t *)(&voodoo->fb_mem[write_addr & voodoo->fb_mask]); - int dest_r, dest_g, dest_b, dest_a; - - dest_r = (dat >> 8) & 0xf8; - dest_g = (dat >> 3) & 0xfc; - dest_b = (dat << 3) & 0xf8; - dest_r |= (dest_r >> 5); - dest_g |= (dest_g >> 6); - dest_b |= (dest_b >> 5); - dest_a = 0xff; - - ALPHA_BLEND(write_data.r, write_data.g, write_data.b, alpha_data); - } - - if (params->fbzMode & FBZ_RGB_WMASK) - *(uint16_t *)(&voodoo->fb_mem[write_addr & voodoo->fb_mask]) = do_dither(&voodoo->params, write_data, x >> 1, y); - if (params->fbzMode & FBZ_DEPTH_WMASK) - *(uint16_t *)(&voodoo->fb_mem[write_addr_aux & voodoo->fb_mask]) = new_depth; + if (params->fbzMode & FBZ_RGB_WMASK) + *(uint16_t *) (&voodoo->fb_mem[write_addr & voodoo->fb_mask]) = do_dither(&voodoo->params, write_data, x >> 1, y); + if (params->fbzMode & FBZ_DEPTH_WMASK) + *(uint16_t *) (&voodoo->fb_mem[write_addr_aux & voodoo->fb_mask]) = new_depth; skip_pixel: - return; - } - } - else - { - if (write_mask & LFB_WRITE_COLOUR) - *(uint16_t *)(&voodoo->fb_mem[write_addr & voodoo->fb_mask]) = do_dither(&voodoo->params, colour_data, x >> 1, y); - if (write_mask & LFB_WRITE_DEPTH) - *(uint16_t *)(&voodoo->fb_mem[write_addr_aux & voodoo->fb_mask]) = depth_data; + return; } + } else { + if (write_mask & LFB_WRITE_COLOUR) + *(uint16_t *) (&voodoo->fb_mem[write_addr & voodoo->fb_mask]) = do_dither(&voodoo->params, colour_data, x >> 1, y); + if (write_mask & LFB_WRITE_DEPTH) + *(uint16_t *) (&voodoo->fb_mem[write_addr_aux & voodoo->fb_mask]) = depth_data; + } } - -void voodoo_fb_writel(uint32_t addr, uint32_t val, void *p) +void +voodoo_fb_writel(uint32_t addr, uint32_t val, void *priv) { - voodoo_t *voodoo = (voodoo_t *)p; - voodoo_params_t *params = &voodoo->params; - int x, y; - uint32_t write_addr, write_addr_aux; - rgba8_t colour_data[2]; - uint16_t depth_data[2]; - uint8_t alpha_data[2]; - int write_mask = 0, count = 1; + voodoo_t *voodoo = (voodoo_t *) priv; + const voodoo_params_t *params = &voodoo->params; + int x; + int y; + uint32_t write_addr; + uint32_t write_addr_aux; + rgba8_t colour_data[2]; + uint16_t depth_data[2]; + uint8_t alpha_data[2]; + int write_mask = 0; + int count = 1; - depth_data[0] = depth_data[1] = voodoo->params.zaColor & 0xffff; - alpha_data[0] = alpha_data[1] = voodoo->params.zaColor >> 24; -// while (!RB_EMPTY) -// thread_reset_event(voodoo->not_full_event); + depth_data[0] = depth_data[1] = voodoo->params.zaColor & 0xffff; + alpha_data[0] = alpha_data[1] = voodoo->params.zaColor >> 24; +#if 0 + while (!RB_EMPTY) + thread_reset_event(voodoo->not_full_event); +#endif -// voodoo_fb_log("voodoo_fb_writel : %08X %08X\n", addr, val); +#if 0 + voodoo_fb_log("voodoo_fb_writel : %08X %08X\n", addr, val); +#endif - switch (voodoo->lfbMode & LFB_FORMAT_MASK) - { - case LFB_FORMAT_RGB565: - colour_data[0] = rgb565[val & 0xffff]; - colour_data[1] = rgb565[val >> 16]; - write_mask = LFB_WRITE_COLOUR; - count = 2; - break; - case LFB_FORMAT_RGB555: - colour_data[0] = argb1555[val & 0xffff]; - colour_data[1] = argb1555[val >> 16]; - write_mask = LFB_WRITE_COLOUR; - count = 2; - break; - case LFB_FORMAT_ARGB1555: - colour_data[0] = argb1555[val & 0xffff]; - alpha_data[0] = colour_data[0].a; - colour_data[1] = argb1555[val >> 16]; - alpha_data[1] = colour_data[1].a; - write_mask = LFB_WRITE_COLOUR; - count = 2; - break; + switch (voodoo->lfbMode & LFB_FORMAT_MASK) { + case LFB_FORMAT_RGB565: + colour_data[0] = rgb565[val & 0xffff]; + colour_data[1] = rgb565[val >> 16]; + write_mask = LFB_WRITE_COLOUR; + count = 2; + break; + case LFB_FORMAT_RGB555: + colour_data[0] = argb1555[val & 0xffff]; + colour_data[1] = argb1555[val >> 16]; + write_mask = LFB_WRITE_COLOUR; + count = 2; + break; + case LFB_FORMAT_ARGB1555: + colour_data[0] = argb1555[val & 0xffff]; + alpha_data[0] = colour_data[0].a; + colour_data[1] = argb1555[val >> 16]; + alpha_data[1] = colour_data[1].a; + write_mask = LFB_WRITE_COLOUR; + count = 2; + break; - case LFB_FORMAT_ARGB8888: - colour_data[0].b = val & 0xff; - colour_data[0].g = (val >> 8) & 0xff; - colour_data[0].r = (val >> 16) & 0xff; - alpha_data[0] = (val >> 24) & 0xff; - write_mask = LFB_WRITE_COLOUR; - addr >>= 1; - break; + case LFB_FORMAT_ARGB8888: + colour_data[0].b = val & 0xff; + colour_data[0].g = (val >> 8) & 0xff; + colour_data[0].r = (val >> 16) & 0xff; + alpha_data[0] = (val >> 24) & 0xff; + write_mask = LFB_WRITE_COLOUR; + addr >>= 1; + break; - case LFB_FORMAT_DEPTH: - depth_data[0] = val; - depth_data[1] = val >> 16; - write_mask = LFB_WRITE_DEPTH; - count = 2; - break; + case LFB_FORMAT_DEPTH: + depth_data[0] = val; + depth_data[1] = val >> 16; + write_mask = LFB_WRITE_DEPTH; + count = 2; + break; - default: - fatal("voodoo_fb_writel : bad LFB format %08X\n", voodoo->lfbMode); - } + default: + fatal("voodoo_fb_writel : bad LFB format %08X\n", voodoo->lfbMode); + } - if (voodoo->type >= VOODOO_BANSHEE) - { - x = addr & 0xffe; - y = (addr >> 12) & 0x3ff; - } - else - { - x = addr & 0x7fe; - y = (addr >> 11) & 0x3ff; - } + if (voodoo->type >= VOODOO_BANSHEE) { + x = addr & 0xffe; + y = (addr >> 12) & 0x3ff; + } else { + x = addr & 0x7fe; + y = (addr >> 11) & 0x3ff; + } - if (SLI_ENABLED) - { - if ((!(voodoo->initEnable & INITENABLE_SLI_MASTER_SLAVE) && (y & 1)) || - ((voodoo->initEnable & INITENABLE_SLI_MASTER_SLAVE) && !(y & 1))) - return; - y >>= 1; - } + if (SLI_ENABLED) { + if ((!(voodoo->initEnable & INITENABLE_SLI_MASTER_SLAVE) && (y & 1)) || ((voodoo->initEnable & INITENABLE_SLI_MASTER_SLAVE) && !(y & 1))) + return; + y >>= 1; + } - if (voodoo->fb_write_offset == voodoo->params.front_offset && y < 2048) - voodoo->dirty_line[y] = 1; + if (voodoo->fb_write_offset == voodoo->params.front_offset && y < 2048) + voodoo->dirty_line[y] = 1; - if (voodoo->col_tiled) - write_addr = voodoo->fb_write_offset + (x & 127) + (x >> 7) * 128*32 + (y & 31) * 128 + (y >> 5) * voodoo->row_width; - else - write_addr = voodoo->fb_write_offset + x + (y * voodoo->row_width); - if (voodoo->aux_tiled) - write_addr_aux = voodoo->params.aux_offset + (x & 127) + (x >> 7) * 128*32 + (y & 31) * 128 + (y >> 5) * voodoo->row_width; - else - write_addr_aux = voodoo->params.aux_offset + x + (y * voodoo->row_width); + if (voodoo->col_tiled) + write_addr = voodoo->fb_write_offset + (x & 127) + (x >> 7) * 128 * 32 + (y & 31) * 128 + (y >> 5) * voodoo->row_width; + else + write_addr = voodoo->fb_write_offset + x + (y * voodoo->row_width); + if (voodoo->aux_tiled) + write_addr_aux = voodoo->params.aux_offset + (x & 127) + (x >> 7) * 128 * 32 + (y & 31) * 128 + (y >> 5) * voodoo->row_width; + else + write_addr_aux = voodoo->params.aux_offset + x + (y * voodoo->row_width); -// voodoo_fb_log("fb_writel %08x x=%i y=%i rw=%i %08x wo=%08x\n", addr, x, y, voodoo->row_width, write_addr, voodoo->fb_write_offset); +#if 0 + voodoo_fb_log("fb_writel %08x x=%i y=%i rw=%i %08x wo=%08x\n", addr, x, y, voodoo->row_width, write_addr, voodoo->fb_write_offset); +#endif - if (voodoo->lfbMode & 0x100) - { - int c; + if (voodoo->lfbMode & 0x100) { + for (int c = 0; c < count; c++) { + rgba8_t write_data = colour_data[c]; + uint16_t new_depth = depth_data[c]; - for (c = 0; c < count; c++) - { - rgba8_t write_data = colour_data[c]; - uint16_t new_depth = depth_data[c]; + if (params->fbzMode & FBZ_DEPTH_ENABLE) { + uint16_t old_depth = *(uint16_t *) (&voodoo->fb_mem[write_addr_aux & voodoo->fb_mask]); - if (params->fbzMode & FBZ_DEPTH_ENABLE) - { - uint16_t old_depth = *(uint16_t *)(&voodoo->fb_mem[write_addr_aux & voodoo->fb_mask]); + DEPTH_TEST(new_depth); + } - DEPTH_TEST(new_depth); - } + if ((params->fbzMode & FBZ_CHROMAKEY) && write_data.r == params->chromaKey_r && write_data.g == params->chromaKey_g && write_data.b == params->chromaKey_b) + goto skip_pixel; - if ((params->fbzMode & FBZ_CHROMAKEY) && - write_data.r == params->chromaKey_r && - write_data.g == params->chromaKey_g && - write_data.b == params->chromaKey_b) - goto skip_pixel; + if (params->fogMode & FOG_ENABLE) { + int32_t z = new_depth << 12; + int64_t w_depth = new_depth; + int32_t ia = alpha_data[c] << 12; - if (params->fogMode & FOG_ENABLE) - { - int32_t z = new_depth << 12; - int64_t w_depth = new_depth; - int32_t ia = alpha_data[c] << 12; + APPLY_FOG(write_data.r, write_data.g, write_data.b, z, ia, w_depth); + } - APPLY_FOG(write_data.r, write_data.g, write_data.b, z, ia, w_depth); - } + if (params->alphaMode & 1) + ALPHA_TEST(alpha_data[c]); - if (params->alphaMode & 1) - ALPHA_TEST(alpha_data[c]); + if (params->alphaMode & (1 << 4)) { + uint16_t dat = *(uint16_t *) (&voodoo->fb_mem[write_addr & voodoo->fb_mask]); + int dest_r; + int dest_g; + int dest_b; + int dest_a; - if (params->alphaMode & (1 << 4)) - { - uint16_t dat = *(uint16_t *)(&voodoo->fb_mem[write_addr & voodoo->fb_mask]); - int dest_r, dest_g, dest_b, dest_a; + dest_r = (dat >> 8) & 0xf8; + dest_g = (dat >> 3) & 0xfc; + dest_b = (dat << 3) & 0xf8; + dest_r |= (dest_r >> 5); + dest_g |= (dest_g >> 6); + dest_b |= (dest_b >> 5); + dest_a = 0xff; - dest_r = (dat >> 8) & 0xf8; - dest_g = (dat >> 3) & 0xfc; - dest_b = (dat << 3) & 0xf8; - dest_r |= (dest_r >> 5); - dest_g |= (dest_g >> 6); - dest_b |= (dest_b >> 5); - dest_a = 0xff; + ALPHA_BLEND(write_data.r, write_data.g, write_data.b, alpha_data[c]); + } - ALPHA_BLEND(write_data.r, write_data.g, write_data.b, alpha_data[c]); - } - - if (params->fbzMode & FBZ_RGB_WMASK) - *(uint16_t *)(&voodoo->fb_mem[write_addr & voodoo->fb_mask]) = do_dither(&voodoo->params, write_data, (x >> 1) + c, y); - if (params->fbzMode & FBZ_DEPTH_WMASK) - *(uint16_t *)(&voodoo->fb_mem[write_addr_aux & voodoo->fb_mask]) = new_depth; + if (params->fbzMode & FBZ_RGB_WMASK) + *(uint16_t *) (&voodoo->fb_mem[write_addr & voodoo->fb_mask]) = do_dither(&voodoo->params, write_data, (x >> 1) + c, y); + if (params->fbzMode & FBZ_DEPTH_WMASK) + *(uint16_t *) (&voodoo->fb_mem[write_addr_aux & voodoo->fb_mask]) = new_depth; skip_pixel: - write_addr += 2; - write_addr_aux += 2; - } + write_addr += 2; + write_addr_aux += 2; } - else - { - int c; + } else { + for (int c = 0; c < count; c++) { + if (write_mask & LFB_WRITE_COLOUR) + *(uint16_t *) (&voodoo->fb_mem[write_addr & voodoo->fb_mask]) = do_dither(&voodoo->params, colour_data[c], (x >> 1) + c, y); + if (write_mask & LFB_WRITE_DEPTH) + *(uint16_t *) (&voodoo->fb_mem[write_addr_aux & voodoo->fb_mask]) = depth_data[c]; - for (c = 0; c < count; c++) - { - if (write_mask & LFB_WRITE_COLOUR) - *(uint16_t *)(&voodoo->fb_mem[write_addr & voodoo->fb_mask]) = do_dither(&voodoo->params, colour_data[c], (x >> 1) + c, y); - if (write_mask & LFB_WRITE_DEPTH) - *(uint16_t *)(&voodoo->fb_mem[write_addr_aux & voodoo->fb_mask]) = depth_data[c]; - - write_addr += 2; - write_addr_aux += 2; - } + write_addr += 2; + write_addr_aux += 2; } + } } diff --git a/src/video/vid_voodoo_fifo.c b/src/video/vid_voodoo_fifo.c index f36bd18d4..8a84dabe4 100644 --- a/src/video/vid_voodoo_fifo.c +++ b/src/video/vid_voodoo_fifo.c @@ -1,19 +1,20 @@ /* - * 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. + * 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. + * This file is part of the 86Box distribution. * - * 3DFX Voodoo emulation. + * 3DFX Voodoo emulation. * * * - * Authors: Sarah Walker, + * Authors: Sarah Walker, * - * Copyright 2008-2020 Sarah Walker. + * Copyright 2008-2020 Sarah Walker. */ +#include #include #include #include @@ -21,6 +22,7 @@ #include #include #include +#define HAVE_STDARG_H #include <86box/86box.h> #include "cpu.h" #include <86box/machine.h> @@ -29,6 +31,7 @@ #include <86box/timer.h> #include <86box/device.h> #include <86box/plat.h> +#include <86box/thread.h> #include <86box/video.h> #include <86box/vid_svga.h> #include <86box/vid_voodoo_common.h> @@ -40,7 +43,6 @@ #include <86box/vid_voodoo_render.h> #include <86box/vid_voodoo_texture.h> - #ifdef ENABLE_VOODOO_FIFO_LOG int voodoo_fifo_do_log = ENABLE_VOODOO_FIFO_LOG; @@ -50,496 +52,499 @@ voodoo_fifo_log(const char *fmt, ...) va_list ap; if (voodoo_fifo_do_log) { - va_start(ap, fmt); - pclog_ex(fmt, ap); - va_end(ap); + va_start(ap, fmt); + pclog_ex(fmt, ap); + va_end(ap); } } #else -#define voodoo_fifo_log(fmt, ...) +# define voodoo_fifo_log(fmt, ...) #endif #define WAKE_DELAY (TIMER_USEC * 100) -void voodoo_wake_fifo_thread(voodoo_t *voodoo) +void +voodoo_wake_fifo_thread(voodoo_t *voodoo) { - if (!timer_is_enabled(&voodoo->wake_timer)) - { - /*Don't wake FIFO thread immediately - if we do that it will probably - process one word and go back to sleep, requiring it to be woken on - almost every write. Instead, wait a short while so that the CPU - emulation writes more data so we have more batched-up work.*/ - timer_set_delay_u64(&voodoo->wake_timer, WAKE_DELAY); - } + if (!timer_is_enabled(&voodoo->wake_timer)) { + /*Don't wake FIFO thread immediately - if we do that it will probably + process one word and go back to sleep, requiring it to be woken on + almost every write. Instead, wait a short while so that the CPU + emulation writes more data so we have more batched-up work.*/ + timer_set_delay_u64(&voodoo->wake_timer, WAKE_DELAY); + } } -void voodoo_wake_fifo_thread_now(voodoo_t *voodoo) +void +voodoo_wake_fifo_thread_now(voodoo_t *voodoo) { - thread_set_event(voodoo->wake_fifo_thread); /*Wake up FIFO thread if moving from idle*/ + thread_set_event(voodoo->wake_fifo_thread); /*Wake up FIFO thread if moving from idle*/ } -void voodoo_wake_timer(void *p) +void +voodoo_wake_timer(void *priv) { - voodoo_t *voodoo = (voodoo_t *)p; + voodoo_t *voodoo = (voodoo_t *) priv; - thread_set_event(voodoo->wake_fifo_thread); /*Wake up FIFO thread if moving from idle*/ + thread_set_event(voodoo->wake_fifo_thread); /*Wake up FIFO thread if moving from idle*/ } -void voodoo_queue_command(voodoo_t *voodoo, uint32_t addr_type, uint32_t val) +void +voodoo_queue_command(voodoo_t *voodoo, uint32_t addr_type, uint32_t val) { - fifo_entry_t *fifo = &voodoo->fifo[voodoo->fifo_write_idx & FIFO_MASK]; + fifo_entry_t *fifo = &voodoo->fifo[voodoo->fifo_write_idx & FIFO_MASK]; - while (FIFO_FULL) - { - thread_reset_event(voodoo->fifo_not_full_event); - if (FIFO_FULL) - { - thread_wait_event(voodoo->fifo_not_full_event, 1); /*Wait for room in ringbuffer*/ - if (FIFO_FULL) - voodoo_wake_fifo_thread_now(voodoo); - } - } - - fifo->val = val; - fifo->addr_type = addr_type; - - voodoo->fifo_write_idx++; - - if (FIFO_ENTRIES > 0xe000) - voodoo_wake_fifo_thread(voodoo); -} - -void voodoo_flush(voodoo_t *voodoo) -{ - voodoo->flush = 1; - while (!FIFO_EMPTY) - { + while (FIFO_FULL) { + thread_reset_event(voodoo->fifo_not_full_event); + if (FIFO_FULL) { + thread_wait_event(voodoo->fifo_not_full_event, 1); /*Wait for room in ringbuffer*/ + if (FIFO_FULL) voodoo_wake_fifo_thread_now(voodoo); - thread_wait_event(voodoo->fifo_not_full_event, 1); } - voodoo_wait_for_render_thread_idle(voodoo); - voodoo->flush = 0; -} + } -void voodoo_wake_fifo_threads(voodoo_set_t *set, voodoo_t *voodoo) -{ + fifo->val = val; + fifo->addr_type = addr_type; + + voodoo->fifo_write_idx++; + voodoo->cmd_status &= ~(1 << 24); + + if (FIFO_ENTRIES > 0xe000) voodoo_wake_fifo_thread(voodoo); - if (SLI_ENABLED && voodoo->type != VOODOO_2 && set->voodoos[0] == voodoo) - voodoo_wake_fifo_thread(set->voodoos[1]); } -void voodoo_wait_for_swap_complete(voodoo_t *voodoo) +void +voodoo_flush(voodoo_t *voodoo) { - while (voodoo->swap_pending) - { - thread_wait_event(voodoo->wake_fifo_thread, -1); - thread_reset_event(voodoo->wake_fifo_thread); + voodoo->flush = 1; + while (!FIFO_EMPTY) { + voodoo_wake_fifo_thread_now(voodoo); + thread_wait_event(voodoo->fifo_not_full_event, 1); + } + voodoo_wait_for_render_thread_idle(voodoo); + voodoo->flush = 0; +} - thread_wait_mutex(voodoo->swap_mutex); - if ((voodoo->swap_pending && voodoo->flush) || FIFO_FULL) - { - /*Main thread is waiting for FIFO to empty, so skip vsync wait and just swap*/ - memset(voodoo->dirty_line, 1, sizeof(voodoo->dirty_line)); - voodoo->front_offset = voodoo->params.front_offset; - if (voodoo->swap_count > 0) - voodoo->swap_count--; - voodoo->swap_pending = 0; - thread_release_mutex(voodoo->swap_mutex);; - break; - } - else - thread_release_mutex(voodoo->swap_mutex);; +void +voodoo_wake_fifo_threads(voodoo_set_t *set, voodoo_t *voodoo) +{ + voodoo_wake_fifo_thread(voodoo); + if (SLI_ENABLED && voodoo->type != VOODOO_2 && set->voodoos[0] == voodoo) + voodoo_wake_fifo_thread(set->voodoos[1]); +} + +void +voodoo_wait_for_swap_complete(voodoo_t *voodoo) +{ + while (voodoo->swap_pending) { + thread_wait_event(voodoo->wake_fifo_thread, -1); + thread_reset_event(voodoo->wake_fifo_thread); + + thread_wait_mutex(voodoo->swap_mutex); + if ((voodoo->swap_pending && voodoo->flush) || FIFO_FULL) { + /*Main thread is waiting for FIFO to empty, so skip vsync wait and just swap*/ + memset(voodoo->dirty_line, 1, sizeof(voodoo->dirty_line)); + voodoo->front_offset = voodoo->params.front_offset; + if (voodoo->swap_count > 0) + voodoo->swap_count--; + voodoo->swap_pending = 0; + thread_release_mutex(voodoo->swap_mutex); + break; + } else + thread_release_mutex(voodoo->swap_mutex); + } +} + +static uint32_t +cmdfifo_get(voodoo_t *voodoo) +{ + uint32_t val; + + if (!voodoo->cmdfifo_in_sub) { + while (voodoo->cmdfifo_depth_rd == voodoo->cmdfifo_depth_wr) { + thread_wait_event(voodoo->wake_fifo_thread, -1); + thread_reset_event(voodoo->wake_fifo_thread); } + } + + val = *(uint32_t *) &voodoo->fb_mem[voodoo->cmdfifo_rp & voodoo->fb_mask]; + + if (!voodoo->cmdfifo_in_sub) + voodoo->cmdfifo_depth_rd++; + voodoo->cmdfifo_rp += 4; + + // voodoo_fifo_log(" CMDFIFO get %08x\n", val); + return val; } - -static uint32_t cmdfifo_get(voodoo_t *voodoo) +static inline float +cmdfifo_get_f(voodoo_t *voodoo) { - uint32_t val; - - if (!voodoo->cmdfifo_in_sub) { - while (voodoo->cmdfifo_depth_rd == voodoo->cmdfifo_depth_wr) - { - thread_wait_event(voodoo->wake_fifo_thread, -1); - thread_reset_event(voodoo->wake_fifo_thread); - } - } + union { + uint32_t i; + float f; + } tempif; - val = *(uint32_t *)&voodoo->fb_mem[voodoo->cmdfifo_rp & voodoo->fb_mask]; - - if (!voodoo->cmdfifo_in_sub) - voodoo->cmdfifo_depth_rd++; - voodoo->cmdfifo_rp += 4; - -// voodoo_fifo_log(" CMDFIFO get %08x\n", val); - return val; + tempif.i = cmdfifo_get(voodoo); + return tempif.f; } -static inline float cmdfifo_get_f(voodoo_t *voodoo) -{ - union - { - uint32_t i; - float f; - } tempif; +enum { + CMDFIFO3_PC_MASK_RGB = (1 << 10), + CMDFIFO3_PC_MASK_ALPHA = (1 << 11), + CMDFIFO3_PC_MASK_Z = (1 << 12), + CMDFIFO3_PC_MASK_Wb = (1 << 13), + CMDFIFO3_PC_MASK_W0 = (1 << 14), + CMDFIFO3_PC_MASK_S0_T0 = (1 << 15), + CMDFIFO3_PC_MASK_W1 = (1 << 16), + CMDFIFO3_PC_MASK_S1_T1 = (1 << 17), - tempif.i = cmdfifo_get(voodoo); - return tempif.f; -} - -enum -{ - CMDFIFO3_PC_MASK_RGB = (1 << 10), - CMDFIFO3_PC_MASK_ALPHA = (1 << 11), - CMDFIFO3_PC_MASK_Z = (1 << 12), - CMDFIFO3_PC_MASK_Wb = (1 << 13), - CMDFIFO3_PC_MASK_W0 = (1 << 14), - CMDFIFO3_PC_MASK_S0_T0 = (1 << 15), - CMDFIFO3_PC_MASK_W1 = (1 << 16), - CMDFIFO3_PC_MASK_S1_T1 = (1 << 17), - - CMDFIFO3_PC = (1 << 28) + CMDFIFO3_PC = (1 << 28) }; -void voodoo_fifo_thread(void *param) +void +voodoo_fifo_thread(void *param) { - voodoo_t *voodoo = (voodoo_t *)param; + voodoo_t *voodoo = (voodoo_t *) param; - while (voodoo->fifo_thread_run) - { + while (voodoo->fifo_thread_run) { + thread_set_event(voodoo->fifo_not_full_event); + thread_wait_event(voodoo->wake_fifo_thread, -1); + thread_reset_event(voodoo->wake_fifo_thread); + voodoo->voodoo_busy = 1; + while (!FIFO_EMPTY) { + uint64_t start_time = plat_timer_read(); + uint64_t end_time; + fifo_entry_t *fifo = &voodoo->fifo[voodoo->fifo_read_idx & FIFO_MASK]; + + switch (fifo->addr_type & FIFO_TYPE) { + case FIFO_WRITEL_REG: + while ((fifo->addr_type & FIFO_TYPE) == FIFO_WRITEL_REG) { + voodoo_reg_writel(fifo->addr_type & FIFO_ADDR, fifo->val, voodoo); + fifo->addr_type = FIFO_INVALID; + voodoo->fifo_read_idx++; + if (FIFO_EMPTY) + break; + fifo = &voodoo->fifo[voodoo->fifo_read_idx & FIFO_MASK]; + } + break; + case FIFO_WRITEW_FB: + voodoo_wait_for_render_thread_idle(voodoo); + while ((fifo->addr_type & FIFO_TYPE) == FIFO_WRITEW_FB) { + voodoo_fb_writew(fifo->addr_type & FIFO_ADDR, fifo->val, voodoo); + fifo->addr_type = FIFO_INVALID; + voodoo->fifo_read_idx++; + if (FIFO_EMPTY) + break; + fifo = &voodoo->fifo[voodoo->fifo_read_idx & FIFO_MASK]; + } + break; + case FIFO_WRITEL_FB: + voodoo_wait_for_render_thread_idle(voodoo); + while ((fifo->addr_type & FIFO_TYPE) == FIFO_WRITEL_FB) { + voodoo_fb_writel(fifo->addr_type & FIFO_ADDR, fifo->val, voodoo); + fifo->addr_type = FIFO_INVALID; + voodoo->fifo_read_idx++; + if (FIFO_EMPTY) + break; + fifo = &voodoo->fifo[voodoo->fifo_read_idx & FIFO_MASK]; + } + break; + case FIFO_WRITEL_TEX: + while ((fifo->addr_type & FIFO_TYPE) == FIFO_WRITEL_TEX) { + if (!(fifo->addr_type & 0x400000)) + voodoo_tex_writel(fifo->addr_type & FIFO_ADDR, fifo->val, voodoo); + fifo->addr_type = FIFO_INVALID; + voodoo->fifo_read_idx++; + if (FIFO_EMPTY) + break; + fifo = &voodoo->fifo[voodoo->fifo_read_idx & FIFO_MASK]; + } + break; + case FIFO_WRITEL_2DREG: + while ((fifo->addr_type & FIFO_TYPE) == FIFO_WRITEL_2DREG) { + voodoo_2d_reg_writel(voodoo, fifo->addr_type & FIFO_ADDR, fifo->val); + fifo->addr_type = FIFO_INVALID; + voodoo->fifo_read_idx++; + if (FIFO_EMPTY) + break; + fifo = &voodoo->fifo[voodoo->fifo_read_idx & FIFO_MASK]; + } + break; + + default: + fatal("Unknown fifo entry %08x\n", fifo->addr_type); + } + + if (FIFO_ENTRIES > 0xe000) thread_set_event(voodoo->fifo_not_full_event); - thread_wait_event(voodoo->wake_fifo_thread, -1); - thread_reset_event(voodoo->wake_fifo_thread); - voodoo->voodoo_busy = 1; - while (!FIFO_EMPTY) - { - uint64_t start_time = plat_timer_read(); - uint64_t end_time; - fifo_entry_t *fifo = &voodoo->fifo[voodoo->fifo_read_idx & FIFO_MASK]; - switch (fifo->addr_type & FIFO_TYPE) - { - case FIFO_WRITEL_REG: - while ((fifo->addr_type & FIFO_TYPE) == FIFO_WRITEL_REG) - { - voodoo_reg_writel(fifo->addr_type & FIFO_ADDR, fifo->val, voodoo); - fifo->addr_type = FIFO_INVALID; - voodoo->fifo_read_idx++; - if (FIFO_EMPTY) - break; - fifo = &voodoo->fifo[voodoo->fifo_read_idx & FIFO_MASK]; - } - break; - case FIFO_WRITEW_FB: - voodoo_wait_for_render_thread_idle(voodoo); - while ((fifo->addr_type & FIFO_TYPE) == FIFO_WRITEW_FB) - { - voodoo_fb_writew(fifo->addr_type & FIFO_ADDR, fifo->val, voodoo); - fifo->addr_type = FIFO_INVALID; - voodoo->fifo_read_idx++; - if (FIFO_EMPTY) - break; - fifo = &voodoo->fifo[voodoo->fifo_read_idx & FIFO_MASK]; - } - break; - case FIFO_WRITEL_FB: - voodoo_wait_for_render_thread_idle(voodoo); - while ((fifo->addr_type & FIFO_TYPE) == FIFO_WRITEL_FB) - { - voodoo_fb_writel(fifo->addr_type & FIFO_ADDR, fifo->val, voodoo); - fifo->addr_type = FIFO_INVALID; - voodoo->fifo_read_idx++; - if (FIFO_EMPTY) - break; - fifo = &voodoo->fifo[voodoo->fifo_read_idx & FIFO_MASK]; - } - break; - case FIFO_WRITEL_TEX: - while ((fifo->addr_type & FIFO_TYPE) == FIFO_WRITEL_TEX) - { - if (!(fifo->addr_type & 0x400000)) - voodoo_tex_writel(fifo->addr_type & FIFO_ADDR, fifo->val, voodoo); - fifo->addr_type = FIFO_INVALID; - voodoo->fifo_read_idx++; - if (FIFO_EMPTY) - break; - fifo = &voodoo->fifo[voodoo->fifo_read_idx & FIFO_MASK]; - } - break; - case FIFO_WRITEL_2DREG: - while ((fifo->addr_type & FIFO_TYPE) == FIFO_WRITEL_2DREG) - { - voodoo_2d_reg_writel(voodoo, fifo->addr_type & FIFO_ADDR, fifo->val); - fifo->addr_type = FIFO_INVALID; - voodoo->fifo_read_idx++; - if (FIFO_EMPTY) - break; - fifo = &voodoo->fifo[voodoo->fifo_read_idx & FIFO_MASK]; - } - break; - - default: - fatal("Unknown fifo entry %08x\n", fifo->addr_type); - } - - if (FIFO_ENTRIES > 0xe000) - thread_set_event(voodoo->fifo_not_full_event); - - end_time = plat_timer_read(); - voodoo->time += end_time - start_time; - } - - while (voodoo->cmdfifo_enabled && (voodoo->cmdfifo_depth_rd != voodoo->cmdfifo_depth_wr || voodoo->cmdfifo_in_sub)) - { - uint64_t start_time = plat_timer_read(); - uint64_t end_time; - uint32_t header = cmdfifo_get(voodoo); - uint32_t addr; - uint32_t mask; - int smode; - int num; - int num_verticies; - int v_num; - -// voodoo_fifo_log(" CMDFIFO header %08x at %08x\n", header, voodoo->cmdfifo_rp); - - switch (header & 7) - { - case 0: -// voodoo_fifo_log("CMDFIFO0\n"); - switch ((header >> 3) & 7) - { - case 0: /*NOP*/ - break; - - case 1: /*JSR*/ -// voodoo_fifo_log("JSR %08x\n", (header >> 4) & 0xfffffc); - voodoo->cmdfifo_ret_addr = voodoo->cmdfifo_rp; - voodoo->cmdfifo_rp = (header >> 4) & 0xfffffc; - voodoo->cmdfifo_in_sub = 1; - break; - - case 2: /*RET*/ - voodoo->cmdfifo_rp = voodoo->cmdfifo_ret_addr; - voodoo->cmdfifo_in_sub = 0; - break; - - case 3: /*JMP local frame buffer*/ - voodoo->cmdfifo_rp = (header >> 4) & 0xfffffc; -// voodoo_fifo_log("JMP to %08x %04x\n", voodoo->cmdfifo_rp, header); - break; - - default: - fatal("Bad CMDFIFO0 %08x\n", header); - } - break; - - case 1: - num = header >> 16; - addr = (header & 0x7ff8) >> 1; -// voodoo_fifo_log("CMDFIFO1 addr=%08x\n",addr); - while (num--) - { - uint32_t val = cmdfifo_get(voodoo); - if ((addr & (1 << 13)) && voodoo->type >= VOODOO_BANSHEE) - { -// if (voodoo->type != VOODOO_BANSHEE) -// fatal("CMDFIFO1: Not Banshee\n"); -// voodoo_fifo_log("CMDFIFO1: write %08x %08x\n", addr, val); - voodoo_2d_reg_writel(voodoo, addr, val); - } - else - { - if ((addr & 0x3ff) == SST_triangleCMD || (addr & 0x3ff) == SST_ftriangleCMD || - (addr & 0x3ff) == SST_fastfillCMD || (addr & 0x3ff) == SST_nopCMD) - voodoo->cmd_written_fifo++; - - if (voodoo->type >= VOODOO_BANSHEE && (addr & 0x3ff) == SST_swapbufferCMD) - voodoo->cmd_written_fifo++; - voodoo_reg_writel(addr, val, voodoo); - } - - if (header & (1 << 15)) - addr += 4; - } - break; - - case 2: - if (voodoo->type < VOODOO_BANSHEE) - fatal("CMDFIFO2: Not Banshee\n"); - mask = (header >> 3); - addr = 8; - while (mask) - { - if (mask & 1) - { - uint32_t val = cmdfifo_get(voodoo); - - voodoo_2d_reg_writel(voodoo, addr, val); - } - - addr += 4; - mask >>= 1; - } - break; - - case 3: - num = (header >> 29) & 7; - mask = header;//(header >> 10) & 0xff; - smode = (header >> 22) & 0xf; - voodoo_reg_writel(SST_sSetupMode, ((header >> 10) & 0xff) | (smode << 16), voodoo); - num_verticies = (header >> 6) & 0xf; - v_num = 0; - if (((header >> 3) & 7) == 2) - v_num = 1; -// voodoo_fifo_log("CMDFIFO3: num=%i verts=%i mask=%02x\n", num, num_verticies, (header >> 10) & 0xff); -// voodoo_fifo_log("CMDFIFO3 %02x %i\n", (header >> 10), (header >> 3) & 7); - - while (num_verticies--) - { - voodoo->verts[3].sVx = cmdfifo_get_f(voodoo); - voodoo->verts[3].sVy = cmdfifo_get_f(voodoo); - if (mask & CMDFIFO3_PC_MASK_RGB) - { - if (header & CMDFIFO3_PC) - { - uint32_t val = cmdfifo_get(voodoo); - voodoo->verts[3].sBlue = (float)(val & 0xff); - voodoo->verts[3].sGreen = (float)((val >> 8) & 0xff); - voodoo->verts[3].sRed = (float)((val >> 16) & 0xff); - voodoo->verts[3].sAlpha = (float)((val >> 24) & 0xff); - } - else - { - voodoo->verts[3].sRed = cmdfifo_get_f(voodoo); - voodoo->verts[3].sGreen = cmdfifo_get_f(voodoo); - voodoo->verts[3].sBlue = cmdfifo_get_f(voodoo); - } - } - if ((mask & CMDFIFO3_PC_MASK_ALPHA) && !(header & CMDFIFO3_PC)) - voodoo->verts[3].sAlpha = cmdfifo_get_f(voodoo); - if (mask & CMDFIFO3_PC_MASK_Z) - voodoo->verts[3].sVz = cmdfifo_get_f(voodoo); - if (mask & CMDFIFO3_PC_MASK_Wb) - voodoo->verts[3].sWb = cmdfifo_get_f(voodoo); - if (mask & CMDFIFO3_PC_MASK_W0) - voodoo->verts[3].sW0 = cmdfifo_get_f(voodoo); - if (mask & CMDFIFO3_PC_MASK_S0_T0) - { - voodoo->verts[3].sS0 = cmdfifo_get_f(voodoo); - voodoo->verts[3].sT0 = cmdfifo_get_f(voodoo); - } - if (mask & CMDFIFO3_PC_MASK_W1) - voodoo->verts[3].sW1 = cmdfifo_get_f(voodoo); - if (mask & CMDFIFO3_PC_MASK_S1_T1) - { - voodoo->verts[3].sS1 = cmdfifo_get_f(voodoo); - voodoo->verts[3].sT1 = cmdfifo_get_f(voodoo); - } - if (v_num) - voodoo_reg_writel(SST_sDrawTriCMD, 0, voodoo); - else - voodoo_reg_writel(SST_sBeginTriCMD, 0, voodoo); - v_num++; - if (v_num == 3 && ((header >> 3) & 7) == 0) - v_num = 0; - } - break; - - case 4: - num = (header >> 29) & 7; - mask = (header >> 15) & 0x3fff; - addr = (header & 0x7ff8) >> 1; -// voodoo_fifo_log("CMDFIFO4 addr=%08x\n",addr); - while (mask) - { - if (mask & 1) - { - uint32_t val = cmdfifo_get(voodoo); - - if ((addr & (1 << 13)) && voodoo->type >= VOODOO_BANSHEE) - { - if (voodoo->type < VOODOO_BANSHEE) - fatal("CMDFIFO1: Not Banshee\n"); -// voodoo_fifo_log("CMDFIFO1: write %08x %08x\n", addr, val); - voodoo_2d_reg_writel(voodoo, addr, val); - } - else - { - if ((addr & 0x3ff) == SST_triangleCMD || (addr & 0x3ff) == SST_ftriangleCMD || - (addr & 0x3ff) == SST_fastfillCMD || (addr & 0x3ff) == SST_nopCMD) - voodoo->cmd_written_fifo++; - - if (voodoo->type >= VOODOO_BANSHEE && (addr & 0x3ff) == SST_swapbufferCMD) - voodoo->cmd_written_fifo++; - voodoo_reg_writel(addr, val, voodoo); - } - } - - addr += 4; - mask >>= 1; - } - while (num--) - cmdfifo_get(voodoo); - break; - - case 5: -// if (header & 0x3fc00000) -// fatal("CMDFIFO packet 5 has byte disables set %08x\n", header); - num = (header >> 3) & 0x7ffff; - addr = cmdfifo_get(voodoo) & 0xffffff; - if (!num) - num = 1; -// voodoo_fifo_log("CMDFIFO5 addr=%08x num=%i\n", addr, num); - switch (header >> 30) - { - case 0: /*Linear framebuffer (Banshee)*/ - if (voodoo->texture_present[0][(addr & voodoo->texture_mask) >> TEX_DIRTY_SHIFT]) - { -// voodoo_fifo_log("texture_present at %08x %i\n", addr, (addr & voodoo->texture_mask) >> TEX_DIRTY_SHIFT); - flush_texture_cache(voodoo, addr & voodoo->texture_mask, 0); - } - if (voodoo->texture_present[1][(addr & voodoo->texture_mask) >> TEX_DIRTY_SHIFT]) - { -// voodoo_fifo_log("texture_present at %08x %i\n", addr, (addr & voodoo->texture_mask) >> TEX_DIRTY_SHIFT); - flush_texture_cache(voodoo, addr & voodoo->texture_mask, 1); - } - while (num--) - { - uint32_t val = cmdfifo_get(voodoo); - if (addr <= voodoo->fb_mask) - *(uint32_t *)&voodoo->fb_mem[addr] = val; - addr += 4; - } - break; - case 2: /*Framebuffer*/ - while (num--) - { - uint32_t val = cmdfifo_get(voodoo); - voodoo_fb_writel(addr, val, voodoo); - addr += 4; - } - break; - case 3: /*Texture*/ - while (num--) - { - uint32_t val = cmdfifo_get(voodoo); - voodoo_tex_writel(addr, val, voodoo); - addr += 4; - } - break; - - default: - fatal("CMDFIFO packet 5 bad space %08x %08x\n", header, voodoo->cmdfifo_rp); - } - break; - - default: - fatal("Bad CMDFIFO packet %08x %08x\n", header, voodoo->cmdfifo_rp); - } - - end_time = plat_timer_read(); - voodoo->time += end_time - start_time; - } - voodoo->voodoo_busy = 0; + end_time = plat_timer_read(); + voodoo->time += end_time - start_time; } + + voodoo->cmd_status |= (1 << 24); + + while (voodoo->cmdfifo_enabled && (voodoo->cmdfifo_depth_rd != voodoo->cmdfifo_depth_wr || voodoo->cmdfifo_in_sub)) { + uint64_t start_time = plat_timer_read(); + uint64_t end_time; + uint32_t header = cmdfifo_get(voodoo); + uint32_t addr; + uint32_t mask; + int smode; + int num; + int num_verticies; + int v_num; + +#if 0 + voodoo_fifo_log(" CMDFIFO header %08x at %08x\n", header, voodoo->cmdfifo_rp); +#endif + + voodoo->cmd_status &= ~7; + voodoo->cmd_status |= (header & 7); + voodoo->cmd_status |= (1 << 11); + switch (header & 7) { + case 0: +#if 0 + voodoo_fifo_log("CMDFIFO0\n"); +#endif + voodoo->cmd_status = (voodoo->cmd_status & 0xffff8fff) | (((header >> 3) & 7) << 12); + switch ((header >> 3) & 7) { + case 0: /*NOP*/ + break; + + case 1: /*JSR*/ +#if 0 + voodoo_fifo_log("JSR %08x\n", (header >> 4) & 0xfffffc); +#endif + voodoo->cmdfifo_ret_addr = voodoo->cmdfifo_rp; + voodoo->cmdfifo_rp = (header >> 4) & 0xfffffc; + voodoo->cmdfifo_in_sub = 1; + break; + + case 2: /*RET*/ + voodoo->cmdfifo_rp = voodoo->cmdfifo_ret_addr; + voodoo->cmdfifo_in_sub = 0; + break; + + case 3: /*JMP local frame buffer*/ + voodoo->cmdfifo_rp = (header >> 4) & 0xfffffc; +#if 0 + voodoo_fifo_log("JMP to %08x %04x\n", voodoo->cmdfifo_rp, header); +#endif + break; + + default: + fatal("Bad CMDFIFO0 %08x\n", header); + } + voodoo->cmd_status = (voodoo->cmd_status & ~(1 << 27)) | (voodoo->cmdfifo_in_sub << 27); + break; + + case 1: + num = header >> 16; + addr = (header & 0x7ff8) >> 1; +#if 0 + voodoo_fifo_log("CMDFIFO1 addr=%08x\n",addr); +#endif + while (num--) { + uint32_t val = cmdfifo_get(voodoo); + if ((addr & (1 << 13)) && voodoo->type >= VOODOO_BANSHEE) { +#if 0 + if (voodoo->type != VOODOO_BANSHEE) + fatal("CMDFIFO1: Not Banshee\n"); +#endif + +#if 0 + voodoo_fifo_log("CMDFIFO1: write %08x %08x\n", addr, val); +#endif + voodoo_2d_reg_writel(voodoo, addr, val); + } else { + if ((addr & 0x3ff) == SST_triangleCMD || (addr & 0x3ff) == SST_ftriangleCMD || (addr & 0x3ff) == SST_fastfillCMD || (addr & 0x3ff) == SST_nopCMD) + voodoo->cmd_written_fifo++; + + if (voodoo->type >= VOODOO_BANSHEE && (addr & 0x3ff) == SST_swapbufferCMD) + voodoo->cmd_written_fifo++; + voodoo_reg_writel(addr, val, voodoo); + } + + if (header & (1 << 15)) + addr += 4; + } + break; + + case 2: + if (voodoo->type < VOODOO_2) + fatal("CMDFIFO2: Not Voodoo 2\n"); + mask = (header >> 3); + addr = 8; + while (mask) { + if (mask & 1) { + uint32_t val = cmdfifo_get(voodoo); + + voodoo_2d_reg_writel(voodoo, addr, val); + } + + addr += 4; + mask >>= 1; + } + break; + + case 3: + num = (header >> 29) & 7; + mask = header; //(header >> 10) & 0xff; + smode = (header >> 22) & 0xf; + voodoo_reg_writel(SST_sSetupMode, ((header >> 10) & 0xff) | (smode << 16), voodoo); + num_verticies = (header >> 6) & 0xf; + v_num = 0; + if (((header >> 3) & 7) == 2) + v_num = 1; +#if 0 + voodoo_fifo_log("CMDFIFO3: num=%i verts=%i mask=%02x\n", num, num_verticies, (header >> 10) & 0xff); + voodoo_fifo_log("CMDFIFO3 %02x %i\n", (header >> 10), (header >> 3) & 7); +#endif + + while (num_verticies--) { + voodoo->verts[3].sVx = cmdfifo_get_f(voodoo); + voodoo->verts[3].sVy = cmdfifo_get_f(voodoo); + if (mask & CMDFIFO3_PC_MASK_RGB) { + if (header & CMDFIFO3_PC) { + uint32_t val = cmdfifo_get(voodoo); + voodoo->verts[3].sBlue = (float) (val & 0xff); + voodoo->verts[3].sGreen = (float) ((val >> 8) & 0xff); + voodoo->verts[3].sRed = (float) ((val >> 16) & 0xff); + voodoo->verts[3].sAlpha = (float) ((val >> 24) & 0xff); + } else { + voodoo->verts[3].sRed = cmdfifo_get_f(voodoo); + voodoo->verts[3].sGreen = cmdfifo_get_f(voodoo); + voodoo->verts[3].sBlue = cmdfifo_get_f(voodoo); + } + } + if ((mask & CMDFIFO3_PC_MASK_ALPHA) && !(header & CMDFIFO3_PC)) + voodoo->verts[3].sAlpha = cmdfifo_get_f(voodoo); + if (mask & CMDFIFO3_PC_MASK_Z) + voodoo->verts[3].sVz = cmdfifo_get_f(voodoo); + if (mask & CMDFIFO3_PC_MASK_Wb) + voodoo->verts[3].sWb = cmdfifo_get_f(voodoo); + if (mask & CMDFIFO3_PC_MASK_W0) + voodoo->verts[3].sW0 = cmdfifo_get_f(voodoo); + if (mask & CMDFIFO3_PC_MASK_S0_T0) { + voodoo->verts[3].sS0 = cmdfifo_get_f(voodoo); + voodoo->verts[3].sT0 = cmdfifo_get_f(voodoo); + } + if (mask & CMDFIFO3_PC_MASK_W1) + voodoo->verts[3].sW1 = cmdfifo_get_f(voodoo); + if (mask & CMDFIFO3_PC_MASK_S1_T1) { + voodoo->verts[3].sS1 = cmdfifo_get_f(voodoo); + voodoo->verts[3].sT1 = cmdfifo_get_f(voodoo); + } + if (v_num) + voodoo_reg_writel(SST_sDrawTriCMD, 0, voodoo); + else + voodoo_reg_writel(SST_sBeginTriCMD, 0, voodoo); + v_num++; + if (v_num == 3 && ((header >> 3) & 7) == 0) + v_num = 0; + } + while (num--) + cmdfifo_get(voodoo); + break; + + case 4: + num = (header >> 29) & 7; + mask = (header >> 15) & 0x3fff; + addr = (header & 0x7ff8) >> 1; +#if 0 + voodoo_fifo_log("CMDFIFO4 addr=%08x\n",addr); +#endif + while (mask) { + if (mask & 1) { + uint32_t val = cmdfifo_get(voodoo); + + if ((addr & (1 << 13)) && voodoo->type >= VOODOO_BANSHEE) { + if (voodoo->type < VOODOO_BANSHEE) + fatal("CMDFIFO1: Not Banshee\n"); +#if 0 + voodoo_fifo_log("CMDFIFO1: write %08x %08x\n", addr, val); +#endif + + voodoo_2d_reg_writel(voodoo, addr, val); + } else { + if ((addr & 0x3ff) == SST_triangleCMD || (addr & 0x3ff) == SST_ftriangleCMD || (addr & 0x3ff) == SST_fastfillCMD || (addr & 0x3ff) == SST_nopCMD) + voodoo->cmd_written_fifo++; + + if (voodoo->type >= VOODOO_BANSHEE && (addr & 0x3ff) == SST_swapbufferCMD) + voodoo->cmd_written_fifo++; + voodoo_reg_writel(addr, val, voodoo); + } + } + + addr += 4; + mask >>= 1; + } + while (num--) + cmdfifo_get(voodoo); + break; + + case 5: +#if 0 + if (header & 0x3fc00000) + fatal("CMDFIFO packet 5 has byte disables set %08x\n", header); +#endif + num = (header >> 3) & 0x7ffff; + addr = cmdfifo_get(voodoo) & 0xffffff; + if (!num) + num = 1; +#if 0 + voodoo_fifo_log("CMDFIFO5 addr=%08x num=%i\n", addr, num); +#endif + switch (header >> 30) { + case 0: /*Linear framebuffer (Banshee)*/ + case 1: /*Planar YUV*/ + if (voodoo->texture_present[0][(addr & voodoo->texture_mask) >> TEX_DIRTY_SHIFT]) { +#if 0 + voodoo_fifo_log("texture_present at %08x %i\n", addr, (addr & voodoo->texture_mask) >> TEX_DIRTY_SHIFT); +#endif + flush_texture_cache(voodoo, addr & voodoo->texture_mask, 0); + } + if (voodoo->texture_present[1][(addr & voodoo->texture_mask) >> TEX_DIRTY_SHIFT]) { +#if 0 + voodoo_fifo_log("texture_present at %08x %i\n", addr, (addr & voodoo->texture_mask) >> TEX_DIRTY_SHIFT); +#endif + flush_texture_cache(voodoo, addr & voodoo->texture_mask, 1); + } + while (num--) { + uint32_t val = cmdfifo_get(voodoo); + if (addr <= voodoo->fb_mask) + *(uint32_t *) &voodoo->fb_mem[addr] = val; + addr += 4; + } + break; + case 2: /*Framebuffer*/ + while (num--) { + uint32_t val = cmdfifo_get(voodoo); + voodoo_fb_writel(addr, val, voodoo); + addr += 4; + } + break; + case 3: /*Texture*/ + while (num--) { + uint32_t val = cmdfifo_get(voodoo); + voodoo_tex_writel(addr, val, voodoo); + addr += 4; + } + break; + + default: + fatal("CMDFIFO packet 5 bad space %08x %08x\n", header, voodoo->cmdfifo_rp); + } + break; + + default: + fatal("Bad CMDFIFO packet %08x %08x\n", header, voodoo->cmdfifo_rp); + } + + end_time = plat_timer_read(); + voodoo->time += end_time - start_time; + } + voodoo->voodoo_busy = 0; + } } diff --git a/src/video/vid_voodoo_reg.c b/src/video/vid_voodoo_reg.c index 2f3460e65..ce3ee6064 100644 --- a/src/video/vid_voodoo_reg.c +++ b/src/video/vid_voodoo_reg.c @@ -1,19 +1,20 @@ /* - * 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. + * 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. + * This file is part of the 86Box distribution. * - * 3DFX Voodoo emulation. + * 3DFX Voodoo emulation. * * * - * Authors: Sarah Walker, + * Authors: Sarah Walker, * - * Copyright 2008-2020 Sarah Walker. + * Copyright 2008-2020 Sarah Walker. */ +#include #include #include #include @@ -21,6 +22,7 @@ #include #include #include +#define HAVE_STDARG_H #include <86box/86box.h> #include "cpu.h" #include <86box/machine.h> @@ -29,6 +31,7 @@ #include <86box/timer.h> #include <86box/device.h> #include <86box/plat.h> +#include <86box/thread.h> #include <86box/video.h> #include <86box/vid_svga.h> #include <86box/vid_voodoo_common.h> @@ -41,16 +44,13 @@ #include <86box/vid_voodoo_setup.h> #include <86box/vid_voodoo_texture.h> - -enum -{ - CHIP_FBI = 0x1, - CHIP_TREX0 = 0x2, - CHIP_TREX1 = 0x4, - CHIP_TREX2 = 0x8 +enum { + CHIP_FBI = 0x1, + CHIP_TREX0 = 0x2, + CHIP_TREX1 = 0x4, + CHIP_TREX2 = 0x8 }; - #ifdef ENABLE_VOODOO_REG_LOG int voodoo_reg_do_log = ENABLE_VOODOO_REG_LOG; @@ -60,1306 +60,1308 @@ voodoo_reg_log(const char *fmt, ...) va_list ap; if (voodoo_reg_do_log) { - va_start(ap, fmt); - pclog_ex(fmt, ap); - va_end(ap); + va_start(ap, fmt); + pclog_ex(fmt, ap); + va_end(ap); } } #else -#define voodoo_reg_log(fmt, ...) +# define voodoo_reg_log(fmt, ...) #endif - -void voodoo_reg_writel(uint32_t addr, uint32_t val, void *p) +void +voodoo_reg_writel(uint32_t addr, uint32_t val, void *priv) { - voodoo_t *voodoo = (voodoo_t *)p; - union - { - uint32_t i; - float f; - } tempif; - int ad21 = addr & (1 << 21); - int chip = (addr >> 10) & 0xf; - if (!chip) - chip = 0xf; + voodoo_t *voodoo = (voodoo_t *) priv; + void (*voodoo_recalc_tex)(voodoo_t * voodoo, int tmu) = NULL; + union { + uint32_t i; + float f; + } tempif; + int ad21 = addr & (1 << 21); + int chip = (addr >> 10) & 0xf; + if (!chip) + chip = 0xf; - tempif.i = val; -//voodoo_reg_log("voodoo_reg_write_l: addr=%08x val=%08x(%f) chip=%x\n", addr, val, tempif.f, chip); - addr &= 0x3fc; + if (voodoo->type == VOODOO_3) + voodoo_recalc_tex = voodoo_recalc_tex3; + else + voodoo_recalc_tex = voodoo_recalc_tex12; - if ((voodoo->fbiInit3 & FBIINIT3_REMAP) && addr < 0x100 && ad21) - addr |= 0x400; - switch (addr) - { - case SST_swapbufferCMD: - if (voodoo->type >= VOODOO_BANSHEE) - { -// voodoo_reg_log("swapbufferCMD %08x %08x\n", val, voodoo->leftOverlayBuf); + tempif.i = val; +#if 0 + voodoo_reg_log("voodoo_reg_write_l: addr=%08x val=%08x(%f) chip=%x\n", addr, val, tempif.f, chip); +#endif + addr &= 0x3fc; - voodoo_wait_for_render_thread_idle(voodoo); - if (!(val & 1)) - { - banshee_set_overlay_addr(voodoo->p, voodoo->leftOverlayBuf); - thread_wait_mutex(voodoo->swap_mutex); - if (voodoo->swap_count > 0) - voodoo->swap_count--; - thread_release_mutex(voodoo->swap_mutex); - voodoo->frame_count++; - } - else if (TRIPLE_BUFFER) - { - if (voodoo->swap_pending) - voodoo_wait_for_swap_complete(voodoo); - voodoo->swap_interval = (val >> 1) & 0xff; - voodoo->swap_offset = voodoo->leftOverlayBuf; - voodoo->swap_pending = 1; - } - else - { - voodoo->swap_interval = (val >> 1) & 0xff; - voodoo->swap_offset = voodoo->leftOverlayBuf; - voodoo->swap_pending = 1; + if ((voodoo->fbiInit3 & FBIINIT3_REMAP) && addr < 0x100 && ad21) + addr |= 0x400; + switch (addr) { + case SST_swapbufferCMD: + if (voodoo->type >= VOODOO_BANSHEE) { +#if 0 + voodoo_reg_log("swapbufferCMD %08x %08x\n", val, voodoo->leftOverlayBuf); +#endif - voodoo_wait_for_swap_complete(voodoo); - } - - voodoo->cmd_read++; - break; - } - - if (TRIPLE_BUFFER) - { - voodoo->disp_buffer = (voodoo->disp_buffer + 1) % 3; - voodoo->draw_buffer = (voodoo->draw_buffer + 1) % 3; - } - else - { - voodoo->disp_buffer = !voodoo->disp_buffer; - voodoo->draw_buffer = !voodoo->draw_buffer; - } - voodoo_recalc(voodoo); - - voodoo->params.swapbufferCMD = val; - -// voodoo_reg_log("Swap buffer %08x %d %p %i\n", val, voodoo->swap_count, &voodoo->swap_count, (voodoo == voodoo->set->voodoos[1]) ? 1 : 0); -// voodoo->front_offset = params->front_offset; voodoo_wait_for_render_thread_idle(voodoo); - if (!(val & 1)) - { - memset(voodoo->dirty_line, 1, sizeof(voodoo->dirty_line)); - voodoo->front_offset = voodoo->params.front_offset; - thread_wait_mutex(voodoo->swap_mutex); - if (voodoo->swap_count > 0) - voodoo->swap_count--; - thread_release_mutex(voodoo->swap_mutex); - } - else if (TRIPLE_BUFFER) - { - if (voodoo->swap_pending) - voodoo_wait_for_swap_complete(voodoo); - - voodoo->swap_interval = (val >> 1) & 0xff; - voodoo->swap_offset = voodoo->params.front_offset; - voodoo->swap_pending = 1; - } - else - { - voodoo->swap_interval = (val >> 1) & 0xff; - voodoo->swap_offset = voodoo->params.front_offset; - voodoo->swap_pending = 1; - + if (!(val & 1)) { + banshee_set_overlay_addr(voodoo->priv, voodoo->leftOverlayBuf); + thread_wait_mutex(voodoo->swap_mutex); + if (voodoo->swap_count > 0) + voodoo->swap_count--; + thread_release_mutex(voodoo->swap_mutex); + voodoo->frame_count++; + } else if (TRIPLE_BUFFER) { + if (voodoo->swap_pending) voodoo_wait_for_swap_complete(voodoo); + voodoo->swap_interval = (val >> 1) & 0xff; + voodoo->swap_offset = voodoo->leftOverlayBuf; + voodoo->swap_pending = 1; + } else { + voodoo->swap_interval = (val >> 1) & 0xff; + voodoo->swap_offset = voodoo->leftOverlayBuf; + voodoo->swap_pending = 1; + + voodoo_wait_for_swap_complete(voodoo); } - voodoo->cmd_read++; - break; - - case SST_vertexAx: case SST_remap_vertexAx: - voodoo->params.vertexAx = val & 0xffff; - break; - case SST_vertexAy: case SST_remap_vertexAy: - voodoo->params.vertexAy = val & 0xffff; - break; - case SST_vertexBx: case SST_remap_vertexBx: - voodoo->params.vertexBx = val & 0xffff; - break; - case SST_vertexBy: case SST_remap_vertexBy: - voodoo->params.vertexBy = val & 0xffff; - break; - case SST_vertexCx: case SST_remap_vertexCx: - voodoo->params.vertexCx = val & 0xffff; - break; - case SST_vertexCy: case SST_remap_vertexCy: - voodoo->params.vertexCy = val & 0xffff; - break; - - case SST_startR: case SST_remap_startR: - voodoo->params.startR = val & 0xffffff; - break; - case SST_startG: case SST_remap_startG: - voodoo->params.startG = val & 0xffffff; - break; - case SST_startB: case SST_remap_startB: - voodoo->params.startB = val & 0xffffff; - break; - case SST_startZ: case SST_remap_startZ: - voodoo->params.startZ = val; - break; - case SST_startA: case SST_remap_startA: - voodoo->params.startA = val & 0xffffff; - break; - case SST_startS: case SST_remap_startS: - if (chip & CHIP_TREX0) - voodoo->params.tmu[0].startS = ((int64_t)(int32_t)val) << 14; - if (chip & CHIP_TREX1) - voodoo->params.tmu[1].startS = ((int64_t)(int32_t)val) << 14; - break; - case SST_startT: case SST_remap_startT: - if (chip & CHIP_TREX0) - voodoo->params.tmu[0].startT = ((int64_t)(int32_t)val) << 14; - if (chip & CHIP_TREX1) - voodoo->params.tmu[1].startT = ((int64_t)(int32_t)val) << 14; - break; - case SST_startW: case SST_remap_startW: - if (chip & CHIP_FBI) - voodoo->params.startW = (int64_t)(int32_t)val << 2; - if (chip & CHIP_TREX0) - voodoo->params.tmu[0].startW = (int64_t)(int32_t)val << 2; - if (chip & CHIP_TREX1) - voodoo->params.tmu[1].startW = (int64_t)(int32_t)val << 2; - break; - - case SST_dRdX: case SST_remap_dRdX: - voodoo->params.dRdX = (val & 0xffffff) | ((val & 0x800000) ? 0xff000000 : 0); - break; - case SST_dGdX: case SST_remap_dGdX: - voodoo->params.dGdX = (val & 0xffffff) | ((val & 0x800000) ? 0xff000000 : 0); - break; - case SST_dBdX: case SST_remap_dBdX: - voodoo->params.dBdX = (val & 0xffffff) | ((val & 0x800000) ? 0xff000000 : 0); - break; - case SST_dZdX: case SST_remap_dZdX: - voodoo->params.dZdX = val; - break; - case SST_dAdX: case SST_remap_dAdX: - voodoo->params.dAdX = (val & 0xffffff) | ((val & 0x800000) ? 0xff000000 : 0); - break; - case SST_dSdX: case SST_remap_dSdX: - if (chip & CHIP_TREX0) - voodoo->params.tmu[0].dSdX = ((int64_t)(int32_t)val) << 14; - if (chip & CHIP_TREX1) - voodoo->params.tmu[1].dSdX = ((int64_t)(int32_t)val) << 14; - break; - case SST_dTdX: case SST_remap_dTdX: - if (chip & CHIP_TREX0) - voodoo->params.tmu[0].dTdX = ((int64_t)(int32_t)val) << 14; - if (chip & CHIP_TREX1) - voodoo->params.tmu[1].dTdX = ((int64_t)(int32_t)val) << 14; - break; - case SST_dWdX: case SST_remap_dWdX: - if (chip & CHIP_TREX0) - voodoo->params.tmu[0].dWdX = (int64_t)(int32_t)val << 2; - if (chip & CHIP_TREX1) - voodoo->params.tmu[1].dWdX = (int64_t)(int32_t)val << 2; - if (chip & CHIP_FBI) - voodoo->params.dWdX = (int64_t)(int32_t)val << 2; - break; - - case SST_dRdY: case SST_remap_dRdY: - voodoo->params.dRdY = (val & 0xffffff) | ((val & 0x800000) ? 0xff000000 : 0); - break; - case SST_dGdY: case SST_remap_dGdY: - voodoo->params.dGdY = (val & 0xffffff) | ((val & 0x800000) ? 0xff000000 : 0); - break; - case SST_dBdY: case SST_remap_dBdY: - voodoo->params.dBdY = (val & 0xffffff) | ((val & 0x800000) ? 0xff000000 : 0); - break; - case SST_dZdY: case SST_remap_dZdY: - voodoo->params.dZdY = val; - break; - case SST_dAdY: case SST_remap_dAdY: - voodoo->params.dAdY = (val & 0xffffff) | ((val & 0x800000) ? 0xff000000 : 0); - break; - case SST_dSdY: case SST_remap_dSdY: - if (chip & CHIP_TREX0) - voodoo->params.tmu[0].dSdY = ((int64_t)(int32_t)val) << 14; - if (chip & CHIP_TREX1) - voodoo->params.tmu[1].dSdY = ((int64_t)(int32_t)val) << 14; - break; - case SST_dTdY: case SST_remap_dTdY: - if (chip & CHIP_TREX0) - voodoo->params.tmu[0].dTdY = ((int64_t)(int32_t)val) << 14; - if (chip & CHIP_TREX1) - voodoo->params.tmu[1].dTdY = ((int64_t)(int32_t)val) << 14; - break; - case SST_dWdY: case SST_remap_dWdY: - if (chip & CHIP_TREX0) - voodoo->params.tmu[0].dWdY = (int64_t)(int32_t)val << 2; - if (chip & CHIP_TREX1) - voodoo->params.tmu[1].dWdY = (int64_t)(int32_t)val << 2; - if (chip & CHIP_FBI) - voodoo->params.dWdY = (int64_t)(int32_t)val << 2; - break; - - case SST_triangleCMD: case SST_remap_triangleCMD: - voodoo->params.sign = val & (1 << 31); - - if (voodoo->ncc_dirty[0]) - voodoo_update_ncc(voodoo, 0); - if (voodoo->ncc_dirty[1]) - voodoo_update_ncc(voodoo, 1); - voodoo->ncc_dirty[0] = voodoo->ncc_dirty[1] = 0; - - voodoo_queue_triangle(voodoo, &voodoo->params); voodoo->cmd_read++; break; + } - case SST_fvertexAx: case SST_remap_fvertexAx: - voodoo->fvertexAx.i = val; - voodoo->params.vertexAx = (int32_t)(int16_t)(int32_t)(voodoo->fvertexAx.f * 16.0f) & 0xffff; - break; - case SST_fvertexAy: case SST_remap_fvertexAy: - voodoo->fvertexAy.i = val; - voodoo->params.vertexAy = (int32_t)(int16_t)(int32_t)(voodoo->fvertexAy.f * 16.0f) & 0xffff; - break; - case SST_fvertexBx: case SST_remap_fvertexBx: - voodoo->fvertexBx.i = val; - voodoo->params.vertexBx = (int32_t)(int16_t)(int32_t)(voodoo->fvertexBx.f * 16.0f) & 0xffff; - break; - case SST_fvertexBy: case SST_remap_fvertexBy: - voodoo->fvertexBy.i = val; - voodoo->params.vertexBy = (int32_t)(int16_t)(int32_t)(voodoo->fvertexBy.f * 16.0f) & 0xffff; - break; - case SST_fvertexCx: case SST_remap_fvertexCx: - voodoo->fvertexCx.i = val; - voodoo->params.vertexCx = (int32_t)(int16_t)(int32_t)(voodoo->fvertexCx.f * 16.0f) & 0xffff; - break; - case SST_fvertexCy: case SST_remap_fvertexCy: - voodoo->fvertexCy.i = val; - voodoo->params.vertexCy = (int32_t)(int16_t)(int32_t)(voodoo->fvertexCy.f * 16.0f) & 0xffff; - break; + if (TRIPLE_BUFFER) { + voodoo->disp_buffer = (voodoo->disp_buffer + 1) % 3; + voodoo->draw_buffer = (voodoo->draw_buffer + 1) % 3; + } else { + voodoo->disp_buffer = !voodoo->disp_buffer; + voodoo->draw_buffer = !voodoo->draw_buffer; + } + voodoo_recalc(voodoo); - case SST_fstartR: case SST_remap_fstartR: - tempif.i = val; - voodoo->params.startR = (int32_t)(tempif.f * 4096.0f); - break; - case SST_fstartG: case SST_remap_fstartG: - tempif.i = val; - voodoo->params.startG = (int32_t)(tempif.f * 4096.0f); - break; - case SST_fstartB: case SST_remap_fstartB: - tempif.i = val; - voodoo->params.startB = (int32_t)(tempif.f * 4096.0f); - break; - case SST_fstartZ: case SST_remap_fstartZ: - tempif.i = val; - voodoo->params.startZ = (int32_t)(tempif.f * 4096.0f); - break; - case SST_fstartA: case SST_remap_fstartA: - tempif.i = val; - voodoo->params.startA = (int32_t)(tempif.f * 4096.0f); - break; - case SST_fstartS: case SST_remap_fstartS: - tempif.i = val; - if (chip & CHIP_TREX0) - voodoo->params.tmu[0].startS = (int64_t)(tempif.f * 4294967296.0f); - if (chip & CHIP_TREX1) - voodoo->params.tmu[1].startS = (int64_t)(tempif.f * 4294967296.0f); - break; - case SST_fstartT: case SST_remap_fstartT: - tempif.i = val; - if (chip & CHIP_TREX0) - voodoo->params.tmu[0].startT = (int64_t)(tempif.f * 4294967296.0f); - if (chip & CHIP_TREX1) - voodoo->params.tmu[1].startT = (int64_t)(tempif.f * 4294967296.0f); - break; - case SST_fstartW: case SST_remap_fstartW: - tempif.i = val; - if (chip & CHIP_TREX0) - voodoo->params.tmu[0].startW = (int64_t)(tempif.f * 4294967296.0f); - if (chip & CHIP_TREX1) - voodoo->params.tmu[1].startW = (int64_t)(tempif.f * 4294967296.0f); - if (chip & CHIP_FBI) - voodoo->params.startW = (int64_t)(tempif.f * 4294967296.0f); - break; + voodoo->params.swapbufferCMD = val; - case SST_fdRdX: case SST_remap_fdRdX: - tempif.i = val; - voodoo->params.dRdX = (int32_t)(tempif.f * 4096.0f); - break; - case SST_fdGdX: case SST_remap_fdGdX: - tempif.i = val; - voodoo->params.dGdX = (int32_t)(tempif.f * 4096.0f); - break; - case SST_fdBdX: case SST_remap_fdBdX: - tempif.i = val; - voodoo->params.dBdX = (int32_t)(tempif.f * 4096.0f); - break; - case SST_fdZdX: case SST_remap_fdZdX: - tempif.i = val; - voodoo->params.dZdX = (int32_t)(tempif.f * 4096.0f); - break; - case SST_fdAdX: case SST_remap_fdAdX: - tempif.i = val; - voodoo->params.dAdX = (int32_t)(tempif.f * 4096.0f); - break; - case SST_fdSdX: case SST_remap_fdSdX: - tempif.i = val; - if (chip & CHIP_TREX0) - voodoo->params.tmu[0].dSdX = (int64_t)(tempif.f * 4294967296.0f); - if (chip & CHIP_TREX1) - voodoo->params.tmu[1].dSdX = (int64_t)(tempif.f * 4294967296.0f); - break; - case SST_fdTdX: case SST_remap_fdTdX: - tempif.i = val; - if (chip & CHIP_TREX0) - voodoo->params.tmu[0].dTdX = (int64_t)(tempif.f * 4294967296.0f); - if (chip & CHIP_TREX1) - voodoo->params.tmu[1].dTdX = (int64_t)(tempif.f * 4294967296.0f); - break; - case SST_fdWdX: case SST_remap_fdWdX: - tempif.i = val; - if (chip & CHIP_TREX0) - voodoo->params.tmu[0].dWdX = (int64_t)(tempif.f * 4294967296.0f); - if (chip & CHIP_TREX1) - voodoo->params.tmu[1].dWdX = (int64_t)(tempif.f * 4294967296.0f); - if (chip & CHIP_FBI) - voodoo->params.dWdX = (int64_t)(tempif.f * 4294967296.0f); - break; +#if 0 + voodoo_reg_log("Swap buffer %08x %d %p %i\n", val, voodoo->swap_count, &voodoo->swap_count, (voodoo == voodoo->set->voodoos[1]) ? 1 : 0); + voodoo->front_offset = params->front_offset; +#endif + voodoo_wait_for_render_thread_idle(voodoo); + if (!(val & 1)) { + memset(voodoo->dirty_line, 1, sizeof(voodoo->dirty_line)); + voodoo->front_offset = voodoo->params.front_offset; + thread_wait_mutex(voodoo->swap_mutex); + if (voodoo->swap_count > 0) + voodoo->swap_count--; + thread_release_mutex(voodoo->swap_mutex); + } else if (TRIPLE_BUFFER) { + if (voodoo->swap_pending) + voodoo_wait_for_swap_complete(voodoo); - case SST_fdRdY: case SST_remap_fdRdY: - tempif.i = val; - voodoo->params.dRdY = (int32_t)(tempif.f * 4096.0f); - break; - case SST_fdGdY: case SST_remap_fdGdY: - tempif.i = val; - voodoo->params.dGdY = (int32_t)(tempif.f * 4096.0f); - break; - case SST_fdBdY: case SST_remap_fdBdY: - tempif.i = val; - voodoo->params.dBdY = (int32_t)(tempif.f * 4096.0f); - break; - case SST_fdZdY: case SST_remap_fdZdY: - tempif.i = val; - voodoo->params.dZdY = (int32_t)(tempif.f * 4096.0f); - break; - case SST_fdAdY: case SST_remap_fdAdY: - tempif.i = val; - voodoo->params.dAdY = (int32_t)(tempif.f * 4096.0f); - break; - case SST_fdSdY: case SST_remap_fdSdY: - tempif.i = val; - if (chip & CHIP_TREX0) - voodoo->params.tmu[0].dSdY = (int64_t)(tempif.f * 4294967296.0f); - if (chip & CHIP_TREX1) - voodoo->params.tmu[1].dSdY = (int64_t)(tempif.f * 4294967296.0f); - break; - case SST_fdTdY: case SST_remap_fdTdY: - tempif.i = val; - if (chip & CHIP_TREX0) - voodoo->params.tmu[0].dTdY = (int64_t)(tempif.f * 4294967296.0f); - if (chip & CHIP_TREX1) - voodoo->params.tmu[1].dTdY = (int64_t)(tempif.f * 4294967296.0f); - break; - case SST_fdWdY: case SST_remap_fdWdY: - tempif.i = val; - if (chip & CHIP_TREX0) - voodoo->params.tmu[0].dWdY = (int64_t)(tempif.f * 4294967296.0f); - if (chip & CHIP_TREX1) - voodoo->params.tmu[1].dWdY = (int64_t)(tempif.f * 4294967296.0f); - if (chip & CHIP_FBI) - voodoo->params.dWdY = (int64_t)(tempif.f * 4294967296.0f); - break; + voodoo->swap_interval = (val >> 1) & 0xff; + voodoo->swap_offset = voodoo->params.front_offset; + voodoo->swap_pending = 1; + } else { + voodoo->swap_interval = (val >> 1) & 0xff; + voodoo->swap_offset = voodoo->params.front_offset; + voodoo->swap_pending = 1; - case SST_ftriangleCMD: - voodoo->params.sign = val & (1 << 31); + voodoo_wait_for_swap_complete(voodoo); + } + voodoo->cmd_read++; + break; - if (voodoo->ncc_dirty[0]) - voodoo_update_ncc(voodoo, 0); - if (voodoo->ncc_dirty[1]) - voodoo_update_ncc(voodoo, 1); - voodoo->ncc_dirty[0] = voodoo->ncc_dirty[1] = 0; + case SST_vertexAx: + case SST_remap_vertexAx: + voodoo->params.vertexAx = val & 0xffff; + break; + case SST_vertexAy: + case SST_remap_vertexAy: + voodoo->params.vertexAy = val & 0xffff; + break; + case SST_vertexBx: + case SST_remap_vertexBx: + voodoo->params.vertexBx = val & 0xffff; + break; + case SST_vertexBy: + case SST_remap_vertexBy: + voodoo->params.vertexBy = val & 0xffff; + break; + case SST_vertexCx: + case SST_remap_vertexCx: + voodoo->params.vertexCx = val & 0xffff; + break; + case SST_vertexCy: + case SST_remap_vertexCy: + voodoo->params.vertexCy = val & 0xffff; + break; - voodoo_queue_triangle(voodoo, &voodoo->params); + case SST_startR: + case SST_remap_startR: + voodoo->params.startR = val & 0xffffff; + break; + case SST_startG: + case SST_remap_startG: + voodoo->params.startG = val & 0xffffff; + break; + case SST_startB: + case SST_remap_startB: + voodoo->params.startB = val & 0xffffff; + break; + case SST_startZ: + case SST_remap_startZ: + voodoo->params.startZ = val; + break; + case SST_startA: + case SST_remap_startA: + voodoo->params.startA = val & 0xffffff; + break; + case SST_startS: + case SST_remap_startS: + if (chip & CHIP_TREX0) + voodoo->params.tmu[0].startS = ((int64_t) (int32_t) val) << 14; + if (chip & CHIP_TREX1) + voodoo->params.tmu[1].startS = ((int64_t) (int32_t) val) << 14; + break; + case SST_startT: + case SST_remap_startT: + if (chip & CHIP_TREX0) + voodoo->params.tmu[0].startT = ((int64_t) (int32_t) val) << 14; + if (chip & CHIP_TREX1) + voodoo->params.tmu[1].startT = ((int64_t) (int32_t) val) << 14; + break; + case SST_startW: + case SST_remap_startW: + if (chip & CHIP_FBI) + voodoo->params.startW = (int64_t) (int32_t) val << 2; + if (chip & CHIP_TREX0) + voodoo->params.tmu[0].startW = (int64_t) (int32_t) val << 2; + if (chip & CHIP_TREX1) + voodoo->params.tmu[1].startW = (int64_t) (int32_t) val << 2; + break; - voodoo->cmd_read++; - break; + case SST_dRdX: + case SST_remap_dRdX: + voodoo->params.dRdX = (val & 0xffffff) | ((val & 0x800000) ? 0xff000000 : 0); + break; + case SST_dGdX: + case SST_remap_dGdX: + voodoo->params.dGdX = (val & 0xffffff) | ((val & 0x800000) ? 0xff000000 : 0); + break; + case SST_dBdX: + case SST_remap_dBdX: + voodoo->params.dBdX = (val & 0xffffff) | ((val & 0x800000) ? 0xff000000 : 0); + break; + case SST_dZdX: + case SST_remap_dZdX: + voodoo->params.dZdX = val; + break; + case SST_dAdX: + case SST_remap_dAdX: + voodoo->params.dAdX = (val & 0xffffff) | ((val & 0x800000) ? 0xff000000 : 0); + break; + case SST_dSdX: + case SST_remap_dSdX: + if (chip & CHIP_TREX0) + voodoo->params.tmu[0].dSdX = ((int64_t) (int32_t) val) << 14; + if (chip & CHIP_TREX1) + voodoo->params.tmu[1].dSdX = ((int64_t) (int32_t) val) << 14; + break; + case SST_dTdX: + case SST_remap_dTdX: + if (chip & CHIP_TREX0) + voodoo->params.tmu[0].dTdX = ((int64_t) (int32_t) val) << 14; + if (chip & CHIP_TREX1) + voodoo->params.tmu[1].dTdX = ((int64_t) (int32_t) val) << 14; + break; + case SST_dWdX: + case SST_remap_dWdX: + if (chip & CHIP_TREX0) + voodoo->params.tmu[0].dWdX = (int64_t) (int32_t) val << 2; + if (chip & CHIP_TREX1) + voodoo->params.tmu[1].dWdX = (int64_t) (int32_t) val << 2; + if (chip & CHIP_FBI) + voodoo->params.dWdX = (int64_t) (int32_t) val << 2; + break; - case SST_fbzColorPath: - voodoo->params.fbzColorPath = val; - voodoo->rgb_sel = val & 3; - break; + case SST_dRdY: + case SST_remap_dRdY: + voodoo->params.dRdY = (val & 0xffffff) | ((val & 0x800000) ? 0xff000000 : 0); + break; + case SST_dGdY: + case SST_remap_dGdY: + voodoo->params.dGdY = (val & 0xffffff) | ((val & 0x800000) ? 0xff000000 : 0); + break; + case SST_dBdY: + case SST_remap_dBdY: + voodoo->params.dBdY = (val & 0xffffff) | ((val & 0x800000) ? 0xff000000 : 0); + break; + case SST_dZdY: + case SST_remap_dZdY: + voodoo->params.dZdY = val; + break; + case SST_dAdY: + case SST_remap_dAdY: + voodoo->params.dAdY = (val & 0xffffff) | ((val & 0x800000) ? 0xff000000 : 0); + break; + case SST_dSdY: + case SST_remap_dSdY: + if (chip & CHIP_TREX0) + voodoo->params.tmu[0].dSdY = ((int64_t) (int32_t) val) << 14; + if (chip & CHIP_TREX1) + voodoo->params.tmu[1].dSdY = ((int64_t) (int32_t) val) << 14; + break; + case SST_dTdY: + case SST_remap_dTdY: + if (chip & CHIP_TREX0) + voodoo->params.tmu[0].dTdY = ((int64_t) (int32_t) val) << 14; + if (chip & CHIP_TREX1) + voodoo->params.tmu[1].dTdY = ((int64_t) (int32_t) val) << 14; + break; + case SST_dWdY: + case SST_remap_dWdY: + if (chip & CHIP_TREX0) + voodoo->params.tmu[0].dWdY = (int64_t) (int32_t) val << 2; + if (chip & CHIP_TREX1) + voodoo->params.tmu[1].dWdY = (int64_t) (int32_t) val << 2; + if (chip & CHIP_FBI) + voodoo->params.dWdY = (int64_t) (int32_t) val << 2; + break; - case SST_fogMode: - voodoo->params.fogMode = val; - break; - case SST_alphaMode: - voodoo->params.alphaMode = val; - break; - case SST_fbzMode: - voodoo->params.fbzMode = val; - voodoo_recalc(voodoo); - break; - case SST_lfbMode: - voodoo->lfbMode = val; - voodoo_recalc(voodoo); - break; + case SST_triangleCMD: + case SST_remap_triangleCMD: + voodoo->params.sign = val & (1 << 31); - case SST_clipLeftRight: - if (voodoo->type >= VOODOO_2) - { - voodoo->params.clipRight = val & 0xfff; - voodoo->params.clipLeft = (val >> 16) & 0xfff; + if (voodoo->ncc_dirty[0]) + voodoo_update_ncc(voodoo, 0); + if (voodoo->ncc_dirty[1]) + voodoo_update_ncc(voodoo, 1); + voodoo->ncc_dirty[0] = voodoo->ncc_dirty[1] = 0; + + voodoo_queue_triangle(voodoo, &voodoo->params); + + voodoo->cmd_read++; + break; + + case SST_fvertexAx: + case SST_remap_fvertexAx: + voodoo->fvertexAx.i = val; + voodoo->params.vertexAx = (int32_t) (int16_t) (int32_t) (voodoo->fvertexAx.f * 16.0f) & 0xffff; + break; + case SST_fvertexAy: + case SST_remap_fvertexAy: + voodoo->fvertexAy.i = val; + voodoo->params.vertexAy = (int32_t) (int16_t) (int32_t) (voodoo->fvertexAy.f * 16.0f) & 0xffff; + break; + case SST_fvertexBx: + case SST_remap_fvertexBx: + voodoo->fvertexBx.i = val; + voodoo->params.vertexBx = (int32_t) (int16_t) (int32_t) (voodoo->fvertexBx.f * 16.0f) & 0xffff; + break; + case SST_fvertexBy: + case SST_remap_fvertexBy: + voodoo->fvertexBy.i = val; + voodoo->params.vertexBy = (int32_t) (int16_t) (int32_t) (voodoo->fvertexBy.f * 16.0f) & 0xffff; + break; + case SST_fvertexCx: + case SST_remap_fvertexCx: + voodoo->fvertexCx.i = val; + voodoo->params.vertexCx = (int32_t) (int16_t) (int32_t) (voodoo->fvertexCx.f * 16.0f) & 0xffff; + break; + case SST_fvertexCy: + case SST_remap_fvertexCy: + voodoo->fvertexCy.i = val; + voodoo->params.vertexCy = (int32_t) (int16_t) (int32_t) (voodoo->fvertexCy.f * 16.0f) & 0xffff; + break; + + case SST_fstartR: + case SST_remap_fstartR: + tempif.i = val; + voodoo->params.startR = (int32_t) (tempif.f * 4096.0f); + break; + case SST_fstartG: + case SST_remap_fstartG: + tempif.i = val; + voodoo->params.startG = (int32_t) (tempif.f * 4096.0f); + break; + case SST_fstartB: + case SST_remap_fstartB: + tempif.i = val; + voodoo->params.startB = (int32_t) (tempif.f * 4096.0f); + break; + case SST_fstartZ: + case SST_remap_fstartZ: + tempif.i = val; + voodoo->params.startZ = (int32_t) (tempif.f * 4096.0f); + break; + case SST_fstartA: + case SST_remap_fstartA: + tempif.i = val; + voodoo->params.startA = (int32_t) (tempif.f * 4096.0f); + break; + case SST_fstartS: + case SST_remap_fstartS: + tempif.i = val; + if (chip & CHIP_TREX0) + voodoo->params.tmu[0].startS = (int64_t) (tempif.f * 4294967296.0f); + if (chip & CHIP_TREX1) + voodoo->params.tmu[1].startS = (int64_t) (tempif.f * 4294967296.0f); + break; + case SST_fstartT: + case SST_remap_fstartT: + tempif.i = val; + if (chip & CHIP_TREX0) + voodoo->params.tmu[0].startT = (int64_t) (tempif.f * 4294967296.0f); + if (chip & CHIP_TREX1) + voodoo->params.tmu[1].startT = (int64_t) (tempif.f * 4294967296.0f); + break; + case SST_fstartW: + case SST_remap_fstartW: + tempif.i = val; + if (chip & CHIP_TREX0) + voodoo->params.tmu[0].startW = (int64_t) (tempif.f * 4294967296.0f); + if (chip & CHIP_TREX1) + voodoo->params.tmu[1].startW = (int64_t) (tempif.f * 4294967296.0f); + if (chip & CHIP_FBI) + voodoo->params.startW = (int64_t) (tempif.f * 4294967296.0f); + break; + + case SST_fdRdX: + case SST_remap_fdRdX: + tempif.i = val; + voodoo->params.dRdX = (int32_t) (tempif.f * 4096.0f); + break; + case SST_fdGdX: + case SST_remap_fdGdX: + tempif.i = val; + voodoo->params.dGdX = (int32_t) (tempif.f * 4096.0f); + break; + case SST_fdBdX: + case SST_remap_fdBdX: + tempif.i = val; + voodoo->params.dBdX = (int32_t) (tempif.f * 4096.0f); + break; + case SST_fdZdX: + case SST_remap_fdZdX: + tempif.i = val; + voodoo->params.dZdX = (int32_t) (tempif.f * 4096.0f); + break; + case SST_fdAdX: + case SST_remap_fdAdX: + tempif.i = val; + voodoo->params.dAdX = (int32_t) (tempif.f * 4096.0f); + break; + case SST_fdSdX: + case SST_remap_fdSdX: + tempif.i = val; + if (chip & CHIP_TREX0) + voodoo->params.tmu[0].dSdX = (int64_t) (tempif.f * 4294967296.0f); + if (chip & CHIP_TREX1) + voodoo->params.tmu[1].dSdX = (int64_t) (tempif.f * 4294967296.0f); + break; + case SST_fdTdX: + case SST_remap_fdTdX: + tempif.i = val; + if (chip & CHIP_TREX0) + voodoo->params.tmu[0].dTdX = (int64_t) (tempif.f * 4294967296.0f); + if (chip & CHIP_TREX1) + voodoo->params.tmu[1].dTdX = (int64_t) (tempif.f * 4294967296.0f); + break; + case SST_fdWdX: + case SST_remap_fdWdX: + tempif.i = val; + if (chip & CHIP_TREX0) + voodoo->params.tmu[0].dWdX = (int64_t) (tempif.f * 4294967296.0f); + if (chip & CHIP_TREX1) + voodoo->params.tmu[1].dWdX = (int64_t) (tempif.f * 4294967296.0f); + if (chip & CHIP_FBI) + voodoo->params.dWdX = (int64_t) (tempif.f * 4294967296.0f); + break; + + case SST_fdRdY: + case SST_remap_fdRdY: + tempif.i = val; + voodoo->params.dRdY = (int32_t) (tempif.f * 4096.0f); + break; + case SST_fdGdY: + case SST_remap_fdGdY: + tempif.i = val; + voodoo->params.dGdY = (int32_t) (tempif.f * 4096.0f); + break; + case SST_fdBdY: + case SST_remap_fdBdY: + tempif.i = val; + voodoo->params.dBdY = (int32_t) (tempif.f * 4096.0f); + break; + case SST_fdZdY: + case SST_remap_fdZdY: + tempif.i = val; + voodoo->params.dZdY = (int32_t) (tempif.f * 4096.0f); + break; + case SST_fdAdY: + case SST_remap_fdAdY: + tempif.i = val; + voodoo->params.dAdY = (int32_t) (tempif.f * 4096.0f); + break; + case SST_fdSdY: + case SST_remap_fdSdY: + tempif.i = val; + if (chip & CHIP_TREX0) + voodoo->params.tmu[0].dSdY = (int64_t) (tempif.f * 4294967296.0f); + if (chip & CHIP_TREX1) + voodoo->params.tmu[1].dSdY = (int64_t) (tempif.f * 4294967296.0f); + break; + case SST_fdTdY: + case SST_remap_fdTdY: + tempif.i = val; + if (chip & CHIP_TREX0) + voodoo->params.tmu[0].dTdY = (int64_t) (tempif.f * 4294967296.0f); + if (chip & CHIP_TREX1) + voodoo->params.tmu[1].dTdY = (int64_t) (tempif.f * 4294967296.0f); + break; + case SST_fdWdY: + case SST_remap_fdWdY: + tempif.i = val; + if (chip & CHIP_TREX0) + voodoo->params.tmu[0].dWdY = (int64_t) (tempif.f * 4294967296.0f); + if (chip & CHIP_TREX1) + voodoo->params.tmu[1].dWdY = (int64_t) (tempif.f * 4294967296.0f); + if (chip & CHIP_FBI) + voodoo->params.dWdY = (int64_t) (tempif.f * 4294967296.0f); + break; + + case SST_ftriangleCMD: + voodoo->params.sign = val & (1 << 31); + + if (voodoo->ncc_dirty[0]) + voodoo_update_ncc(voodoo, 0); + if (voodoo->ncc_dirty[1]) + voodoo_update_ncc(voodoo, 1); + voodoo->ncc_dirty[0] = voodoo->ncc_dirty[1] = 0; + + voodoo_queue_triangle(voodoo, &voodoo->params); + + voodoo->cmd_read++; + break; + + case SST_fbzColorPath: + voodoo->params.fbzColorPath = val; + voodoo->rgb_sel = val & 3; + break; + + case SST_fogMode: + voodoo->params.fogMode = val; + break; + case SST_alphaMode: + voodoo->params.alphaMode = val; + break; + case SST_fbzMode: + voodoo->params.fbzMode = val; + voodoo_recalc(voodoo); + break; + case SST_lfbMode: + voodoo->lfbMode = val; + voodoo_recalc(voodoo); + break; + + case SST_clipLeftRight: + if (voodoo->type >= VOODOO_2) { + voodoo->params.clipRight = val & 0xfff; + voodoo->params.clipLeft = (val >> 16) & 0xfff; + } else { + voodoo->params.clipRight = val & 0x3ff; + voodoo->params.clipLeft = (val >> 16) & 0x3ff; + } + break; + case SST_clipLowYHighY: + if (voodoo->type >= VOODOO_2) { + voodoo->params.clipHighY = val & 0xfff; + voodoo->params.clipLowY = (val >> 16) & 0xfff; + } else { + voodoo->params.clipHighY = val & 0x3ff; + voodoo->params.clipLowY = (val >> 16) & 0x3ff; + } + break; + + case SST_nopCMD: + voodoo->cmd_read++; + voodoo->fbiPixelsIn = 0; + voodoo->fbiChromaFail = 0; + voodoo->fbiZFuncFail = 0; + voodoo->fbiAFuncFail = 0; + voodoo->fbiPixelsOut = 0; + break; + case SST_fastfillCMD: + voodoo_wait_for_render_thread_idle(voodoo); + voodoo_fastfill(voodoo, &voodoo->params); + voodoo->cmd_read++; + break; + + case SST_fogColor: + voodoo->params.fogColor.r = (val >> 16) & 0xff; + voodoo->params.fogColor.g = (val >> 8) & 0xff; + voodoo->params.fogColor.b = val & 0xff; + break; + + case SST_zaColor: + voodoo->params.zaColor = val; + break; + case SST_chromaKey: + voodoo->params.chromaKey_r = (val >> 16) & 0xff; + voodoo->params.chromaKey_g = (val >> 8) & 0xff; + voodoo->params.chromaKey_b = val & 0xff; + voodoo->params.chromaKey = val & 0xffffff; + break; + case SST_stipple: + voodoo->params.stipple = val; + break; + case SST_color0: + voodoo->params.color0 = val; + break; + case SST_color1: + voodoo->params.color1 = val; + break; + + case SST_fogTable00: + case SST_fogTable01: + case SST_fogTable02: + case SST_fogTable03: + case SST_fogTable04: + case SST_fogTable05: + case SST_fogTable06: + case SST_fogTable07: + case SST_fogTable08: + case SST_fogTable09: + case SST_fogTable0a: + case SST_fogTable0b: + case SST_fogTable0c: + case SST_fogTable0d: + case SST_fogTable0e: + case SST_fogTable0f: + case SST_fogTable10: + case SST_fogTable11: + case SST_fogTable12: + case SST_fogTable13: + case SST_fogTable14: + case SST_fogTable15: + case SST_fogTable16: + case SST_fogTable17: + case SST_fogTable18: + case SST_fogTable19: + case SST_fogTable1a: + case SST_fogTable1b: + case SST_fogTable1c: + case SST_fogTable1d: + case SST_fogTable1e: + case SST_fogTable1f: + addr = (addr - SST_fogTable00) >> 1; + voodoo->params.fogTable[addr].dfog = val & 0xff; + voodoo->params.fogTable[addr].fog = (val >> 8) & 0xff; + voodoo->params.fogTable[addr + 1].dfog = (val >> 16) & 0xff; + voodoo->params.fogTable[addr + 1].fog = (val >> 24) & 0xff; + break; + + case SST_clipLeftRight1: + if (voodoo->type >= VOODOO_BANSHEE) { + voodoo->params.clipRight1 = val & 0xfff; + voodoo->params.clipLeft1 = (val >> 16) & 0xfff; + } + break; + case SST_clipTopBottom1: + if (voodoo->type >= VOODOO_BANSHEE) { + voodoo->params.clipHighY1 = val & 0xfff; + voodoo->params.clipLowY1 = (val >> 16) & 0xfff; + } + break; + + case SST_colBufferAddr: + if (voodoo->type >= VOODOO_BANSHEE) { + voodoo->params.draw_offset = val & 0xfffff0; + voodoo->fb_write_offset = voodoo->params.draw_offset; +#if 0 + voodoo_reg_log("colorBufferAddr=%06x\n", voodoo->params.draw_offset); +#endif + } + break; + case SST_colBufferStride: + if (voodoo->type >= VOODOO_BANSHEE) { + voodoo->col_tiled = val & (1 << 15); + voodoo->params.col_tiled = voodoo->col_tiled; + if (voodoo->col_tiled) { + voodoo->row_width = (val & 0x7f) * 128 * 32; +#if 0 + voodoo_reg_log("colBufferStride tiled = %i bytes, tiled %08x\n", voodoo->row_width, val); +#endif + } else { + voodoo->row_width = val & 0x3fff; +#if 0 + voodoo_reg_log("colBufferStride linear = %i bytes, linear\n", voodoo->row_width); +#endif } + voodoo->params.row_width = voodoo->row_width; + } + break; + case SST_auxBufferAddr: + if (voodoo->type >= VOODOO_BANSHEE) { + voodoo->params.aux_offset = val & 0xfffff0; +#if 0 + pclog("auxBufferAddr=%06x\n", voodoo->params.aux_offset); +#endif + } + break; + case SST_auxBufferStride: + if (voodoo->type >= VOODOO_BANSHEE) { + voodoo->aux_tiled = val & (1 << 15); + voodoo->params.aux_tiled = voodoo->aux_tiled; + if (voodoo->aux_tiled) { + voodoo->aux_row_width = (val & 0x7f) * 128 * 32; +#if 0 + voodoo_reg_log("auxBufferStride tiled = %i bytes, tiled\n", voodoo->aux_row_width); +#endif + } else { + voodoo->aux_row_width = val & 0x3fff; +#if 0 + voodoo_reg_log("auxBufferStride linear = %i bytes, linear\n", voodoo->aux_row_width); +#endif + } + voodoo->params.aux_row_width = voodoo->aux_row_width; + } + break; + + case SST_clutData: + voodoo->clutData[(val >> 24) & 0x3f].b = val & 0xff; + voodoo->clutData[(val >> 24) & 0x3f].g = (val >> 8) & 0xff; + voodoo->clutData[(val >> 24) & 0x3f].r = (val >> 16) & 0xff; + if (val & 0x20000000) { + voodoo->clutData[(val >> 24) & 0x3f].b = 255; + voodoo->clutData[(val >> 24) & 0x3f].g = 255; + voodoo->clutData[(val >> 24) & 0x3f].r = 255; + } + voodoo->clutData_dirty = 1; + break; + + case SST_sSetupMode: + voodoo->sSetupMode = val; + break; + case SST_sVx: + tempif.i = val; + voodoo->verts[3].sVx = tempif.f; +#if 0 + voodoo_reg_log("sVx[%i]=%f\n", voodoo->vertex_num, tempif.f); +#endif + break; + case SST_sVy: + tempif.i = val; + voodoo->verts[3].sVy = tempif.f; +#if 0 + voodoo_reg_log("sVy[%i]=%f\n", voodoo->vertex_num, tempif.f); +#endif + break; + case SST_sARGB: + voodoo->verts[3].sBlue = (float) (val & 0xff); + voodoo->verts[3].sGreen = (float) ((val >> 8) & 0xff); + voodoo->verts[3].sRed = (float) ((val >> 16) & 0xff); + voodoo->verts[3].sAlpha = (float) ((val >> 24) & 0xff); + break; + case SST_sRed: + tempif.i = val; + voodoo->verts[3].sRed = tempif.f; + break; + case SST_sGreen: + tempif.i = val; + voodoo->verts[3].sGreen = tempif.f; + break; + case SST_sBlue: + tempif.i = val; + voodoo->verts[3].sBlue = tempif.f; + break; + case SST_sAlpha: + tempif.i = val; + voodoo->verts[3].sAlpha = tempif.f; + break; + case SST_sVz: + tempif.i = val; + voodoo->verts[3].sVz = tempif.f; + break; + case SST_sWb: + tempif.i = val; + voodoo->verts[3].sWb = tempif.f; + break; + case SST_sW0: + tempif.i = val; + voodoo->verts[3].sW0 = tempif.f; + break; + case SST_sS0: + tempif.i = val; + voodoo->verts[3].sS0 = tempif.f; + break; + case SST_sT0: + tempif.i = val; + voodoo->verts[3].sT0 = tempif.f; + break; + case SST_sW1: + tempif.i = val; + voodoo->verts[3].sW1 = tempif.f; + break; + case SST_sS1: + tempif.i = val; + voodoo->verts[3].sS1 = tempif.f; + break; + case SST_sT1: + tempif.i = val; + voodoo->verts[3].sT1 = tempif.f; + break; + + case SST_sBeginTriCMD: +#if 0 + voodoo_reg_log("sBeginTriCMD %i %f\n", voodoo->vertex_num, voodoo->verts[4].sVx); +#endif + voodoo->verts[0] = voodoo->verts[3]; + voodoo->verts[1] = voodoo->verts[3]; + voodoo->verts[2] = voodoo->verts[3]; + voodoo->vertex_next_age = 0; + voodoo->vertex_ages[0] = voodoo->vertex_next_age++; + + voodoo->num_verticies = 1; + voodoo->cull_pingpong = 0; + break; + case SST_sDrawTriCMD: +#if 0 + voodoo_reg_log("sDrawTriCMD %i %i\n", voodoo->num_verticies, voodoo->sSetupMode & SETUPMODE_STRIP_MODE); +#endif + /*I'm not sure this is the vertex selection algorithm actually used in the 3dfx + chips, but this works with a number of games that switch between strip and fan + mode in the middle of a run (eg Black & White, Viper Racing)*/ + if (voodoo->vertex_next_age < 3) { + /*Fewer than three vertices already written, store in next slot*/ + int vertex_nr = voodoo->vertex_next_age; + + voodoo->verts[vertex_nr] = voodoo->verts[3]; + voodoo->vertex_ages[vertex_nr] = voodoo->vertex_next_age++; + } else { + int vertex_nr = 0; + + if (!(voodoo->sSetupMode & SETUPMODE_STRIP_MODE)) { + /*Strip - find oldest vertex*/ + if ((voodoo->vertex_ages[0] < voodoo->vertex_ages[1]) && (voodoo->vertex_ages[0] < voodoo->vertex_ages[2])) + vertex_nr = 0; + else if ((voodoo->vertex_ages[1] < voodoo->vertex_ages[0]) && (voodoo->vertex_ages[1] < voodoo->vertex_ages[2])) + vertex_nr = 1; + else + vertex_nr = 2; + } else { + /*Fan - find second oldest vertex (ie pivot around oldest)*/ + if ((voodoo->vertex_ages[1] < voodoo->vertex_ages[0]) && (voodoo->vertex_ages[0] < voodoo->vertex_ages[2])) + vertex_nr = 0; + else if ((voodoo->vertex_ages[2] < voodoo->vertex_ages[0]) && (voodoo->vertex_ages[0] < voodoo->vertex_ages[1])) + vertex_nr = 0; + else if ((voodoo->vertex_ages[0] < voodoo->vertex_ages[1]) && (voodoo->vertex_ages[1] < voodoo->vertex_ages[2])) + vertex_nr = 1; + else if ((voodoo->vertex_ages[2] < voodoo->vertex_ages[1]) && (voodoo->vertex_ages[1] < voodoo->vertex_ages[0])) + vertex_nr = 1; + else + vertex_nr = 2; + } + voodoo->verts[vertex_nr] = voodoo->verts[3]; + voodoo->vertex_ages[vertex_nr] = voodoo->vertex_next_age++; + } + + voodoo->num_verticies++; + if (voodoo->num_verticies == 3) { +#if 0 + voodoo_reg_log("triangle_setup\n"); +#endif + voodoo_triangle_setup(voodoo); + voodoo->cull_pingpong = !voodoo->cull_pingpong; + + voodoo->num_verticies = 2; + } + break; + + case SST_bltSrcBaseAddr: + voodoo->bltSrcBaseAddr = val & 0x3fffff; + break; + case SST_bltDstBaseAddr: +#if 0 + voodoo_reg_log("Write bltDstBaseAddr %08x\n", val); +#endif + voodoo->bltDstBaseAddr = val & 0x3fffff; + break; + case SST_bltXYStrides: + voodoo->bltSrcXYStride = val & 0xfff; + voodoo->bltDstXYStride = (val >> 16) & 0xfff; + // voodoo_reg_log("Write bltXYStrides %08x\n", val); + break; + case SST_bltSrcChromaRange: + voodoo->bltSrcChromaRange = val; + voodoo->bltSrcChromaMinB = val & 0x1f; + voodoo->bltSrcChromaMinG = (val >> 5) & 0x3f; + voodoo->bltSrcChromaMinR = (val >> 11) & 0x1f; + voodoo->bltSrcChromaMaxB = (val >> 16) & 0x1f; + voodoo->bltSrcChromaMaxG = (val >> 21) & 0x3f; + voodoo->bltSrcChromaMaxR = (val >> 27) & 0x1f; + break; + case SST_bltDstChromaRange: + voodoo->bltDstChromaRange = val; + voodoo->bltDstChromaMinB = val & 0x1f; + voodoo->bltDstChromaMinG = (val >> 5) & 0x3f; + voodoo->bltDstChromaMinR = (val >> 11) & 0x1f; + voodoo->bltDstChromaMaxB = (val >> 16) & 0x1f; + voodoo->bltDstChromaMaxG = (val >> 21) & 0x3f; + voodoo->bltDstChromaMaxR = (val >> 27) & 0x1f; + break; + case SST_bltClipX: + voodoo->bltClipRight = val & 0xfff; + voodoo->bltClipLeft = (val >> 16) & 0xfff; + break; + case SST_bltClipY: + voodoo->bltClipHighY = val & 0xfff; + voodoo->bltClipLowY = (val >> 16) & 0xfff; + break; + + case SST_bltSrcXY: + voodoo->bltSrcX = val & 0x7ff; + voodoo->bltSrcY = (val >> 16) & 0x7ff; + break; + case SST_bltDstXY: + // voodoo_reg_log("Write bltDstXY %08x\n", val); + voodoo->bltDstX = val & 0x7ff; + voodoo->bltDstY = (val >> 16) & 0x7ff; + if (val & (1 << 31)) + voodoo_v2_blit_start(voodoo); + break; + case SST_bltSize: + // voodoo_reg_log("Write bltSize %08x\n", val); + voodoo->bltSizeX = val & 0xfff; + if (voodoo->bltSizeX & 0x800) + voodoo->bltSizeX |= 0xfffff000; + voodoo->bltSizeY = (val >> 16) & 0xfff; + if (voodoo->bltSizeY & 0x800) + voodoo->bltSizeY |= 0xfffff000; + if (val & (1 << 31)) + voodoo_v2_blit_start(voodoo); + break; + case SST_bltRop: + voodoo->bltRop[0] = val & 0xf; + voodoo->bltRop[1] = (val >> 4) & 0xf; + voodoo->bltRop[2] = (val >> 8) & 0xf; + voodoo->bltRop[3] = (val >> 12) & 0xf; + break; + case SST_bltColor: + // voodoo_reg_log("Write bltColor %08x\n", val); + voodoo->bltColorFg = val & 0xffff; + voodoo->bltColorBg = (val >> 16) & 0xffff; + break; + + case SST_bltCommand: + voodoo->bltCommand = val; + // voodoo_reg_log("Write bltCommand %08x\n", val); + if (val & (1 << 31)) + voodoo_v2_blit_start(voodoo); + break; + case SST_bltData: + voodoo_v2_blit_data(voodoo, val); + break; + + case SST_textureMode: + if (chip & CHIP_TREX0) { + voodoo->params.textureMode[0] = val; + voodoo->params.tformat[0] = (val >> 8) & 0xf; + } + if (chip & CHIP_TREX1) { + voodoo->params.textureMode[1] = val; + voodoo->params.tformat[1] = (val >> 8) & 0xf; + } + break; + case SST_tLOD: + if (chip & CHIP_TREX0) { + voodoo->params.tLOD[0] = val; + voodoo_recalc_tex(voodoo, 0); + } + if (chip & CHIP_TREX1) { + voodoo->params.tLOD[1] = val; + voodoo_recalc_tex(voodoo, 1); + } + break; + case SST_tDetail: + if (chip & CHIP_TREX0) { + voodoo->params.detail_max[0] = val & 0xff; + voodoo->params.detail_bias[0] = (val >> 8) & 0x3f; + voodoo->params.detail_scale[0] = (val >> 14) & 7; + } + if (chip & CHIP_TREX1) { + voodoo->params.detail_max[1] = val & 0xff; + voodoo->params.detail_bias[1] = (val >> 8) & 0x3f; + voodoo->params.detail_scale[1] = (val >> 14) & 7; + } + break; + case SST_texBaseAddr: + if (chip & CHIP_TREX0) { + if (voodoo->type >= VOODOO_BANSHEE) + voodoo->params.texBaseAddr[0] = val & 0xfffff0; else - { - voodoo->params.clipRight = val & 0x3ff; - voodoo->params.clipLeft = (val >> 16) & 0x3ff; - } - break; - case SST_clipLowYHighY: - if (voodoo->type >= VOODOO_2) - { - voodoo->params.clipHighY = val & 0xfff; - voodoo->params.clipLowY = (val >> 16) & 0xfff; - } + voodoo->params.texBaseAddr[0] = (val & 0x7ffff) << 3; +#if 0 + voodoo_reg_log("texBaseAddr = %08x %08x\n", voodoo->params.texBaseAddr[0], val); +#endif + voodoo_recalc_tex(voodoo, 0); + } + if (chip & CHIP_TREX1) { + if (voodoo->type >= VOODOO_BANSHEE) + voodoo->params.texBaseAddr[1] = val & 0xfffff0; else - { - voodoo->params.clipHighY = val & 0x3ff; - voodoo->params.clipLowY = (val >> 16) & 0x3ff; - } - break; - - case SST_nopCMD: - voodoo->cmd_read++; - voodoo->fbiPixelsIn = 0; - voodoo->fbiChromaFail = 0; - voodoo->fbiZFuncFail = 0; - voodoo->fbiAFuncFail = 0; - voodoo->fbiPixelsOut = 0; - break; - case SST_fastfillCMD: - voodoo_wait_for_render_thread_idle(voodoo); - voodoo_fastfill(voodoo, &voodoo->params); - voodoo->cmd_read++; - break; - - case SST_fogColor: - voodoo->params.fogColor.r = (val >> 16) & 0xff; - voodoo->params.fogColor.g = (val >> 8) & 0xff; - voodoo->params.fogColor.b = val & 0xff; - break; - - case SST_zaColor: - voodoo->params.zaColor = val; - break; - case SST_chromaKey: - voodoo->params.chromaKey_r = (val >> 16) & 0xff; - voodoo->params.chromaKey_g = (val >> 8) & 0xff; - voodoo->params.chromaKey_b = val & 0xff; - voodoo->params.chromaKey = val & 0xffffff; - break; - case SST_stipple: - voodoo->params.stipple = val; - break; - case SST_color0: - voodoo->params.color0 = val; - break; - case SST_color1: - voodoo->params.color1 = val; - break; - - case SST_fogTable00: case SST_fogTable01: case SST_fogTable02: case SST_fogTable03: - case SST_fogTable04: case SST_fogTable05: case SST_fogTable06: case SST_fogTable07: - case SST_fogTable08: case SST_fogTable09: case SST_fogTable0a: case SST_fogTable0b: - case SST_fogTable0c: case SST_fogTable0d: case SST_fogTable0e: case SST_fogTable0f: - case SST_fogTable10: case SST_fogTable11: case SST_fogTable12: case SST_fogTable13: - case SST_fogTable14: case SST_fogTable15: case SST_fogTable16: case SST_fogTable17: - case SST_fogTable18: case SST_fogTable19: case SST_fogTable1a: case SST_fogTable1b: - case SST_fogTable1c: case SST_fogTable1d: case SST_fogTable1e: case SST_fogTable1f: - addr = (addr - SST_fogTable00) >> 1; - voodoo->params.fogTable[addr].dfog = val & 0xff; - voodoo->params.fogTable[addr].fog = (val >> 8) & 0xff; - voodoo->params.fogTable[addr+1].dfog = (val >> 16) & 0xff; - voodoo->params.fogTable[addr+1].fog = (val >> 24) & 0xff; - break; - - case SST_clipLeftRight1: + voodoo->params.texBaseAddr[1] = (val & 0x7ffff) << 3; + voodoo_recalc_tex(voodoo, 1); + } + break; + case SST_texBaseAddr1: + if (chip & CHIP_TREX0) { if (voodoo->type >= VOODOO_BANSHEE) - { - voodoo->params.clipRight1 = val & 0xfff; - voodoo->params.clipLeft1 = (val >> 16) & 0xfff; - } - break; - case SST_clipTopBottom1: - if (voodoo->type >= VOODOO_BANSHEE) - { - voodoo->params.clipHighY1 = val & 0xfff; - voodoo->params.clipLowY1 = (val >> 16) & 0xfff; - } - break; - - case SST_colBufferAddr: - if (voodoo->type >= VOODOO_BANSHEE) - { - voodoo->params.draw_offset = val & 0xfffff0; - voodoo->fb_write_offset = voodoo->params.draw_offset; -// voodoo_reg_log("colorBufferAddr=%06x\n", voodoo->params.draw_offset); - } - break; - case SST_colBufferStride: - if (voodoo->type >= VOODOO_BANSHEE) - { - voodoo->col_tiled = val & (1 << 15); - voodoo->params.col_tiled = voodoo->col_tiled; - if (voodoo->col_tiled) - { - voodoo->row_width = (val & 0x7f) * 128*32; -// voodoo_reg_log("colBufferStride tiled = %i bytes, tiled %08x\n", voodoo->row_width, val); - } - else - { - voodoo->row_width = val & 0x3fff; -// voodoo_reg_log("colBufferStride linear = %i bytes, linear\n", voodoo->row_width); - } - voodoo->params.row_width = voodoo->row_width; - } - break; - case SST_auxBufferAddr: - if (voodoo->type >= VOODOO_BANSHEE) - { - voodoo->params.aux_offset = val & 0xfffff0; -// pclog("auxBufferAddr=%06x\n", voodoo->params.aux_offset); - } - break; - case SST_auxBufferStride: - if (voodoo->type >= VOODOO_BANSHEE) - { - voodoo->aux_tiled = val & (1 << 15); - voodoo->params.aux_tiled = voodoo->aux_tiled; - if (voodoo->aux_tiled) - { - voodoo->aux_row_width = (val & 0x7f) * 128*32; -// voodoo_reg_log("auxBufferStride tiled = %i bytes, tiled\n", voodoo->aux_row_width); - } - else - { - voodoo->aux_row_width = val & 0x3fff; -// voodoo_reg_log("auxBufferStride linear = %i bytes, linear\n", voodoo->aux_row_width); - } - voodoo->params.aux_row_width = voodoo->aux_row_width; - } - break; - - case SST_clutData: - voodoo->clutData[(val >> 24) & 0x3f].b = val & 0xff; - voodoo->clutData[(val >> 24) & 0x3f].g = (val >> 8) & 0xff; - voodoo->clutData[(val >> 24) & 0x3f].r = (val >> 16) & 0xff; - if (val & 0x20000000) - { - voodoo->clutData[(val >> 24) & 0x3f].b = 255; - voodoo->clutData[(val >> 24) & 0x3f].g = 255; - voodoo->clutData[(val >> 24) & 0x3f].r = 255; - } - voodoo->clutData_dirty = 1; - break; - - case SST_sSetupMode: - voodoo->sSetupMode = val; - break; - case SST_sVx: - tempif.i = val; - voodoo->verts[3].sVx = tempif.f; -// voodoo_reg_log("sVx[%i]=%f\n", voodoo->vertex_num, tempif.f); - break; - case SST_sVy: - tempif.i = val; - voodoo->verts[3].sVy = tempif.f; -// voodoo_reg_log("sVy[%i]=%f\n", voodoo->vertex_num, tempif.f); - break; - case SST_sARGB: - voodoo->verts[3].sBlue = (float)(val & 0xff); - voodoo->verts[3].sGreen = (float)((val >> 8) & 0xff); - voodoo->verts[3].sRed = (float)((val >> 16) & 0xff); - voodoo->verts[3].sAlpha = (float)((val >> 24) & 0xff); - break; - case SST_sRed: - tempif.i = val; - voodoo->verts[3].sRed = tempif.f; - break; - case SST_sGreen: - tempif.i = val; - voodoo->verts[3].sGreen = tempif.f; - break; - case SST_sBlue: - tempif.i = val; - voodoo->verts[3].sBlue = tempif.f; - break; - case SST_sAlpha: - tempif.i = val; - voodoo->verts[3].sAlpha = tempif.f; - break; - case SST_sVz: - tempif.i = val; - voodoo->verts[3].sVz = tempif.f; - break; - case SST_sWb: - tempif.i = val; - voodoo->verts[3].sWb = tempif.f; - break; - case SST_sW0: - tempif.i = val; - voodoo->verts[3].sW0 = tempif.f; - break; - case SST_sS0: - tempif.i = val; - voodoo->verts[3].sS0 = tempif.f; - break; - case SST_sT0: - tempif.i = val; - voodoo->verts[3].sT0 = tempif.f; - break; - case SST_sW1: - tempif.i = val; - voodoo->verts[3].sW1 = tempif.f; - break; - case SST_sS1: - tempif.i = val; - voodoo->verts[3].sS1 = tempif.f; - break; - case SST_sT1: - tempif.i = val; - voodoo->verts[3].sT1 = tempif.f; - break; - - case SST_sBeginTriCMD: -// voodoo_reg_log("sBeginTriCMD %i %f\n", voodoo->vertex_num, voodoo->verts[4].sVx); - voodoo->verts[0] = voodoo->verts[3]; - voodoo->verts[1] = voodoo->verts[3]; - voodoo->verts[2] = voodoo->verts[3]; - voodoo->vertex_next_age = 0; - voodoo->vertex_ages[0] = voodoo->vertex_next_age++; - - voodoo->num_verticies = 1; - voodoo->cull_pingpong = 0; - break; - case SST_sDrawTriCMD: -// voodoo_reg_log("sDrawTriCMD %i %i\n", voodoo->num_verticies, voodoo->sSetupMode & SETUPMODE_STRIP_MODE); - /*I'm not sure this is the vertex selection algorithm actually used in the 3dfx - chips, but this works with a number of games that switch between strip and fan - mode in the middle of a run (eg Black & White, Viper Racing)*/ - if (voodoo->vertex_next_age < 3) - { - /*Fewer than three vertices already written, store in next slot*/ - int vertex_nr = voodoo->vertex_next_age; - - voodoo->verts[vertex_nr] = voodoo->verts[3]; - voodoo->vertex_ages[vertex_nr] = voodoo->vertex_next_age++; - } + voodoo->params.texBaseAddr1[0] = val & 0xfffff0; else - { - int vertex_nr = 0; + voodoo->params.texBaseAddr1[0] = (val & 0x7ffff) << 3; + voodoo_recalc_tex(voodoo, 0); + } + if (chip & CHIP_TREX1) { + if (voodoo->type >= VOODOO_BANSHEE) + voodoo->params.texBaseAddr1[1] = val & 0xfffff0; + else + voodoo->params.texBaseAddr1[1] = (val & 0x7ffff) << 3; + voodoo_recalc_tex(voodoo, 1); + } + break; + case SST_texBaseAddr2: + if (chip & CHIP_TREX0) { + if (voodoo->type >= VOODOO_BANSHEE) + voodoo->params.texBaseAddr2[0] = val & 0xfffff0; + else + voodoo->params.texBaseAddr2[0] = (val & 0x7ffff) << 3; + voodoo_recalc_tex(voodoo, 0); + } + if (chip & CHIP_TREX1) { + if (voodoo->type >= VOODOO_BANSHEE) + voodoo->params.texBaseAddr2[1] = val & 0xfffff0; + else + voodoo->params.texBaseAddr2[1] = (val & 0x7ffff) << 3; + voodoo_recalc_tex(voodoo, 1); + } + break; + case SST_texBaseAddr38: + if (chip & CHIP_TREX0) { + if (voodoo->type >= VOODOO_BANSHEE) + voodoo->params.texBaseAddr38[0] = val & 0xfffff0; + else + voodoo->params.texBaseAddr38[0] = (val & 0x7ffff) << 3; + voodoo_recalc_tex(voodoo, 0); + } + if (chip & CHIP_TREX1) { + if (voodoo->type >= VOODOO_BANSHEE) + voodoo->params.texBaseAddr38[1] = val & 0xfffff0; + else + voodoo->params.texBaseAddr38[1] = (val & 0x7ffff) << 3; + voodoo_recalc_tex(voodoo, 1); + } + break; - if (!(voodoo->sSetupMode & SETUPMODE_STRIP_MODE)) - { - /*Strip - find oldest vertex*/ - if ((voodoo->vertex_ages[0] < voodoo->vertex_ages[1]) && - (voodoo->vertex_ages[0] < voodoo->vertex_ages[2])) - vertex_nr = 0; - else if ((voodoo->vertex_ages[1] < voodoo->vertex_ages[0]) && - (voodoo->vertex_ages[1] < voodoo->vertex_ages[2])) - vertex_nr = 1; - else - vertex_nr = 2; - } - else - { - /*Fan - find second oldest vertex (ie pivot around oldest)*/ - if ((voodoo->vertex_ages[1] < voodoo->vertex_ages[0]) && - (voodoo->vertex_ages[0] < voodoo->vertex_ages[2])) - vertex_nr = 0; - else if ((voodoo->vertex_ages[2] < voodoo->vertex_ages[0]) && - (voodoo->vertex_ages[0] < voodoo->vertex_ages[1])) - vertex_nr = 0; - else if ((voodoo->vertex_ages[0] < voodoo->vertex_ages[1]) && - (voodoo->vertex_ages[1] < voodoo->vertex_ages[2])) - vertex_nr = 1; - else if ((voodoo->vertex_ages[2] < voodoo->vertex_ages[1]) && - (voodoo->vertex_ages[1] < voodoo->vertex_ages[0])) - vertex_nr = 1; - else - vertex_nr = 2; - } - voodoo->verts[vertex_nr] = voodoo->verts[3]; - voodoo->vertex_ages[vertex_nr] = voodoo->vertex_next_age++; - } + case SST_trexInit1: + if (chip & CHIP_TREX0) + voodoo->trexInit1[0] = val; + if (chip & CHIP_TREX1) + voodoo->trexInit1[1] = val; + break; - voodoo->num_verticies++; - if (voodoo->num_verticies == 3) - { -// voodoo_reg_log("triangle_setup\n"); - voodoo_triangle_setup(voodoo); - voodoo->cull_pingpong = !voodoo->cull_pingpong; + case SST_nccTable0_Y0: + if (chip & CHIP_TREX0) { + voodoo->nccTable[0][0].y[0] = val; + voodoo->ncc_dirty[0] = 1; + } + if (chip & CHIP_TREX1) { + voodoo->nccTable[1][0].y[0] = val; + voodoo->ncc_dirty[1] = 1; + } + break; + case SST_nccTable0_Y1: + if (chip & CHIP_TREX0) { + voodoo->nccTable[0][0].y[1] = val; + voodoo->ncc_dirty[0] = 1; + } + if (chip & CHIP_TREX1) { + voodoo->nccTable[1][0].y[1] = val; + voodoo->ncc_dirty[1] = 1; + } + break; + case SST_nccTable0_Y2: + if (chip & CHIP_TREX0) { + voodoo->nccTable[0][0].y[2] = val; + voodoo->ncc_dirty[0] = 1; + } + if (chip & CHIP_TREX1) { + voodoo->nccTable[1][0].y[2] = val; + voodoo->ncc_dirty[1] = 1; + } + break; + case SST_nccTable0_Y3: + if (chip & CHIP_TREX0) { + voodoo->nccTable[0][0].y[3] = val; + voodoo->ncc_dirty[0] = 1; + } + if (chip & CHIP_TREX1) { + voodoo->nccTable[1][0].y[3] = val; + voodoo->ncc_dirty[1] = 1; + } + break; - voodoo->num_verticies = 2; + case SST_nccTable0_I0: + if (!(val & (1 << 31))) { + if (chip & CHIP_TREX0) { + voodoo->nccTable[0][0].i[0] = val; + voodoo->ncc_dirty[0] = 1; + } + if (chip & CHIP_TREX1) { + voodoo->nccTable[1][0].i[0] = val; + voodoo->ncc_dirty[1] = 1; } break; + } + fallthrough; + case SST_nccTable0_I2: + if (!(val & (1 << 31))) { + if (chip & CHIP_TREX0) { + voodoo->nccTable[0][0].i[2] = val; + voodoo->ncc_dirty[0] = 1; + } + if (chip & CHIP_TREX1) { + voodoo->nccTable[1][0].i[2] = val; + voodoo->ncc_dirty[1] = 1; + } + break; + } + case SST_nccTable0_Q0: + if (!(val & (1 << 31))) { + if (chip & CHIP_TREX0) { + voodoo->nccTable[0][0].q[0] = val; + voodoo->ncc_dirty[0] = 1; + } + if (chip & CHIP_TREX1) { + voodoo->nccTable[1][0].q[0] = val; + voodoo->ncc_dirty[1] = 1; + } + break; + } + case SST_nccTable0_Q2: + if (!(val & (1 << 31))) { + if (chip & CHIP_TREX0) { + voodoo->nccTable[0][0].i[2] = val; + voodoo->ncc_dirty[0] = 1; + } + if (chip & CHIP_TREX1) { + voodoo->nccTable[1][0].i[2] = val; + voodoo->ncc_dirty[1] = 1; + } + break; + } + if (val & (1 << 31)) { + int p = (val >> 23) & 0xfe; + if (chip & CHIP_TREX0) { + voodoo->palette[0][p].u = val | 0xff000000; + voodoo->palette_dirty[0] = 1; + } + if (chip & CHIP_TREX1) { + voodoo->palette[1][p].u = val | 0xff000000; + voodoo->palette_dirty[1] = 1; + } + } + break; - case SST_bltSrcBaseAddr: - voodoo->bltSrcBaseAddr = val & 0x3fffff; + case SST_nccTable0_I1: + if (!(val & (1 << 31))) { + if (chip & CHIP_TREX0) { + voodoo->nccTable[0][0].i[1] = val; + voodoo->ncc_dirty[0] = 1; + } + if (chip & CHIP_TREX1) { + voodoo->nccTable[1][0].i[1] = val; + voodoo->ncc_dirty[1] = 1; + } break; - case SST_bltDstBaseAddr: -// voodoo_reg_log("Write bltDstBaseAddr %08x\n", val); - voodoo->bltDstBaseAddr = val & 0x3fffff; + } + case SST_nccTable0_I3: + if (!(val & (1 << 31))) { + if (chip & CHIP_TREX0) { + voodoo->nccTable[0][0].i[3] = val; + voodoo->ncc_dirty[0] = 1; + } + if (chip & CHIP_TREX1) { + voodoo->nccTable[1][0].i[3] = val; + voodoo->ncc_dirty[1] = 1; + } break; - case SST_bltXYStrides: - voodoo->bltSrcXYStride = val & 0xfff; - voodoo->bltDstXYStride = (val >> 16) & 0xfff; -// voodoo_reg_log("Write bltXYStrides %08x\n", val); + } + case SST_nccTable0_Q1: + if (!(val & (1 << 31))) { + if (chip & CHIP_TREX0) { + voodoo->nccTable[0][0].q[1] = val; + voodoo->ncc_dirty[0] = 1; + } + if (chip & CHIP_TREX1) { + voodoo->nccTable[1][0].q[1] = val; + voodoo->ncc_dirty[1] = 1; + } break; - case SST_bltSrcChromaRange: - voodoo->bltSrcChromaRange = val; - voodoo->bltSrcChromaMinB = val & 0x1f; - voodoo->bltSrcChromaMinG = (val >> 5) & 0x3f; - voodoo->bltSrcChromaMinR = (val >> 11) & 0x1f; - voodoo->bltSrcChromaMaxB = (val >> 16) & 0x1f; - voodoo->bltSrcChromaMaxG = (val >> 21) & 0x3f; - voodoo->bltSrcChromaMaxR = (val >> 27) & 0x1f; - break; - case SST_bltDstChromaRange: - voodoo->bltDstChromaRange = val; - voodoo->bltDstChromaMinB = val & 0x1f; - voodoo->bltDstChromaMinG = (val >> 5) & 0x3f; - voodoo->bltDstChromaMinR = (val >> 11) & 0x1f; - voodoo->bltDstChromaMaxB = (val >> 16) & 0x1f; - voodoo->bltDstChromaMaxG = (val >> 21) & 0x3f; - voodoo->bltDstChromaMaxR = (val >> 27) & 0x1f; - break; - case SST_bltClipX: - voodoo->bltClipRight = val & 0xfff; - voodoo->bltClipLeft = (val >> 16) & 0xfff; - break; - case SST_bltClipY: - voodoo->bltClipHighY = val & 0xfff; - voodoo->bltClipLowY = (val >> 16) & 0xfff; + } + case SST_nccTable0_Q3: + if (!(val & (1 << 31))) { + if (chip & CHIP_TREX0) { + voodoo->nccTable[0][0].q[3] = val; + voodoo->ncc_dirty[0] = 1; + } + if (chip & CHIP_TREX1) { + voodoo->nccTable[1][0].q[3] = val; + voodoo->ncc_dirty[1] = 1; + } break; + } + if (val & (1 << 31)) { + int p = ((val >> 23) & 0xfe) | 0x01; + if (chip & CHIP_TREX0) { + voodoo->palette[0][p].u = val | 0xff000000; + voodoo->palette_dirty[0] = 1; + } + if (chip & CHIP_TREX1) { + voodoo->palette[1][p].u = val | 0xff000000; + voodoo->palette_dirty[1] = 1; + } + } + break; - case SST_bltSrcXY: - voodoo->bltSrcX = val & 0x7ff; - voodoo->bltSrcY = (val >> 16) & 0x7ff; - break; - case SST_bltDstXY: -// voodoo_reg_log("Write bltDstXY %08x\n", val); - voodoo->bltDstX = val & 0x7ff; - voodoo->bltDstY = (val >> 16) & 0x7ff; - if (val & (1 << 31)) - voodoo_v2_blit_start(voodoo); - break; - case SST_bltSize: -// voodoo_reg_log("Write bltSize %08x\n", val); - voodoo->bltSizeX = val & 0xfff; - if (voodoo->bltSizeX & 0x800) - voodoo->bltSizeX |= 0xfffff000; - voodoo->bltSizeY = (val >> 16) & 0xfff; - if (voodoo->bltSizeY & 0x800) - voodoo->bltSizeY |= 0xfffff000; - if (val & (1 << 31)) - voodoo_v2_blit_start(voodoo); - break; - case SST_bltRop: - voodoo->bltRop[0] = val & 0xf; - voodoo->bltRop[1] = (val >> 4) & 0xf; - voodoo->bltRop[2] = (val >> 8) & 0xf; - voodoo->bltRop[3] = (val >> 12) & 0xf; - break; - case SST_bltColor: -// voodoo_reg_log("Write bltColor %08x\n", val); - voodoo->bltColorFg = val & 0xffff; - voodoo->bltColorBg = (val >> 16) & 0xffff; - break; + case SST_nccTable1_Y0: + if (chip & CHIP_TREX0) { + voodoo->nccTable[0][1].y[0] = val; + voodoo->ncc_dirty[0] = 1; + } + if (chip & CHIP_TREX1) { + voodoo->nccTable[1][1].y[0] = val; + voodoo->ncc_dirty[1] = 1; + } + break; + case SST_nccTable1_Y1: + if (chip & CHIP_TREX0) { + voodoo->nccTable[0][1].y[1] = val; + voodoo->ncc_dirty[0] = 1; + } + if (chip & CHIP_TREX1) { + voodoo->nccTable[1][1].y[1] = val; + voodoo->ncc_dirty[1] = 1; + } + break; + case SST_nccTable1_Y2: + if (chip & CHIP_TREX0) { + voodoo->nccTable[0][1].y[2] = val; + voodoo->ncc_dirty[0] = 1; + } + if (chip & CHIP_TREX1) { + voodoo->nccTable[1][1].y[2] = val; + voodoo->ncc_dirty[1] = 1; + } + break; + case SST_nccTable1_Y3: + if (chip & CHIP_TREX0) { + voodoo->nccTable[0][1].y[3] = val; + voodoo->ncc_dirty[0] = 1; + } + if (chip & CHIP_TREX1) { + voodoo->nccTable[1][1].y[3] = val; + voodoo->ncc_dirty[1] = 1; + } + break; + case SST_nccTable1_I0: + if (chip & CHIP_TREX0) { + voodoo->nccTable[0][1].i[0] = val; + voodoo->ncc_dirty[0] = 1; + } + if (chip & CHIP_TREX1) { + voodoo->nccTable[1][1].i[0] = val; + voodoo->ncc_dirty[1] = 1; + } + break; + case SST_nccTable1_I1: + if (chip & CHIP_TREX0) { + voodoo->nccTable[0][1].i[1] = val; + voodoo->ncc_dirty[0] = 1; + } + if (chip & CHIP_TREX1) { + voodoo->nccTable[1][1].i[1] = val; + voodoo->ncc_dirty[1] = 1; + } + break; + case SST_nccTable1_I2: + if (chip & CHIP_TREX0) { + voodoo->nccTable[0][1].i[2] = val; + voodoo->ncc_dirty[0] = 1; + } + if (chip & CHIP_TREX1) { + voodoo->nccTable[1][1].i[2] = val; + voodoo->ncc_dirty[1] = 1; + } + break; + case SST_nccTable1_I3: + if (chip & CHIP_TREX0) { + voodoo->nccTable[0][1].i[3] = val; + voodoo->ncc_dirty[0] = 1; + } + if (chip & CHIP_TREX1) { + voodoo->nccTable[1][1].i[3] = val; + voodoo->ncc_dirty[1] = 1; + } + break; + case SST_nccTable1_Q0: + if (chip & CHIP_TREX0) { + voodoo->nccTable[0][1].q[0] = val; + voodoo->ncc_dirty[0] = 1; + } + if (chip & CHIP_TREX1) { + voodoo->nccTable[1][1].q[0] = val; + voodoo->ncc_dirty[1] = 1; + } + break; + case SST_nccTable1_Q1: + if (chip & CHIP_TREX0) { + voodoo->nccTable[0][1].q[1] = val; + voodoo->ncc_dirty[0] = 1; + } + if (chip & CHIP_TREX1) { + voodoo->nccTable[1][1].q[1] = val; + voodoo->ncc_dirty[1] = 1; + } + break; + case SST_nccTable1_Q2: + if (chip & CHIP_TREX0) { + voodoo->nccTable[0][1].q[2] = val; + voodoo->ncc_dirty[0] = 1; + } + if (chip & CHIP_TREX1) { + voodoo->nccTable[1][1].q[2] = val; + voodoo->ncc_dirty[1] = 1; + } + break; + case SST_nccTable1_Q3: + if (chip & CHIP_TREX0) { + voodoo->nccTable[0][1].q[3] = val; + voodoo->ncc_dirty[0] = 1; + } + if (chip & CHIP_TREX1) { + voodoo->nccTable[1][1].q[3] = val; + voodoo->ncc_dirty[1] = 1; + } + break; - case SST_bltCommand: - voodoo->bltCommand = val; -// voodoo_reg_log("Write bltCommand %08x\n", val); - if (val & (1 << 31)) - voodoo_v2_blit_start(voodoo); - break; - case SST_bltData: - voodoo_v2_blit_data(voodoo, val); - break; + case SST_userIntrCMD: + fatal("userIntrCMD write %08x from FIFO\n", val); + break; - case SST_textureMode: - if (chip & CHIP_TREX0) - { - voodoo->params.textureMode[0] = val; - voodoo->params.tformat[0] = (val >> 8) & 0xf; - } - if (chip & CHIP_TREX1) - { - voodoo->params.textureMode[1] = val; - voodoo->params.tformat[1] = (val >> 8) & 0xf; - } - break; - case SST_tLOD: - if (chip & CHIP_TREX0) - { - voodoo->params.tLOD[0] = val; - voodoo_recalc_tex(voodoo, 0); - } - if (chip & CHIP_TREX1) - { - voodoo->params.tLOD[1] = val; - voodoo_recalc_tex(voodoo, 1); - } - break; - case SST_tDetail: - if (chip & CHIP_TREX0) - { - voodoo->params.detail_max[0] = val & 0xff; - voodoo->params.detail_bias[0] = (val >> 8) & 0x3f; - voodoo->params.detail_scale[0] = (val >> 14) & 7; - } - if (chip & CHIP_TREX1) - { - voodoo->params.detail_max[1] = val & 0xff; - voodoo->params.detail_bias[1] = (val >> 8) & 0x3f; - voodoo->params.detail_scale[1] = (val >> 14) & 7; - } - break; - case SST_texBaseAddr: - if (chip & CHIP_TREX0) - { - if (voodoo->type >= VOODOO_BANSHEE) - voodoo->params.texBaseAddr[0] = val & 0xfffff0; - else - voodoo->params.texBaseAddr[0] = (val & 0x7ffff) << 3; -// voodoo_reg_log("texBaseAddr = %08x %08x\n", voodoo->params.texBaseAddr[0], val); - voodoo_recalc_tex(voodoo, 0); - } - if (chip & CHIP_TREX1) - { - if (voodoo->type >= VOODOO_BANSHEE) - voodoo->params.texBaseAddr[1] = val & 0xfffff0; - else - voodoo->params.texBaseAddr[1] = (val & 0x7ffff) << 3; - voodoo_recalc_tex(voodoo, 1); - } - break; - case SST_texBaseAddr1: - if (chip & CHIP_TREX0) - { - if (voodoo->type >= VOODOO_BANSHEE) - voodoo->params.texBaseAddr1[0] = val & 0xfffff0; - else - voodoo->params.texBaseAddr1[0] = (val & 0x7ffff) << 3; - voodoo_recalc_tex(voodoo, 0); - } - if (chip & CHIP_TREX1) - { - if (voodoo->type >= VOODOO_BANSHEE) - voodoo->params.texBaseAddr1[1] = val & 0xfffff0; - else - voodoo->params.texBaseAddr1[1] = (val & 0x7ffff) << 3; - voodoo_recalc_tex(voodoo, 1); - } - break; - case SST_texBaseAddr2: - if (chip & CHIP_TREX0) - { - if (voodoo->type >= VOODOO_BANSHEE) - voodoo->params.texBaseAddr2[0] = val & 0xfffff0; - else - voodoo->params.texBaseAddr2[0] = (val & 0x7ffff) << 3; - voodoo_recalc_tex(voodoo, 0); - } - if (chip & CHIP_TREX1) - { - if (voodoo->type >= VOODOO_BANSHEE) - voodoo->params.texBaseAddr2[1] = val & 0xfffff0; - else - voodoo->params.texBaseAddr2[1] = (val & 0x7ffff) << 3; - voodoo_recalc_tex(voodoo, 1); - } - break; - case SST_texBaseAddr38: - if (chip & CHIP_TREX0) - { - if (voodoo->type >= VOODOO_BANSHEE) - voodoo->params.texBaseAddr38[0] = val & 0xfffff0; - else - voodoo->params.texBaseAddr38[0] = (val & 0x7ffff) << 3; - voodoo_recalc_tex(voodoo, 0); - } - if (chip & CHIP_TREX1) - { - if (voodoo->type >= VOODOO_BANSHEE) - voodoo->params.texBaseAddr38[1] = val & 0xfffff0; - else - voodoo->params.texBaseAddr38[1] = (val & 0x7ffff) << 3; - voodoo_recalc_tex(voodoo, 1); - } - break; + case SST_leftOverlayBuf: + voodoo->leftOverlayBuf = val; + break; - case SST_trexInit1: - if (chip & CHIP_TREX0) - voodoo->trexInit1[0] = val; - if (chip & CHIP_TREX1) - voodoo->trexInit1[1] = val; - break; - - case SST_nccTable0_Y0: - if (chip & CHIP_TREX0) - { - voodoo->nccTable[0][0].y[0] = val; - voodoo->ncc_dirty[0] = 1; - } - if (chip & CHIP_TREX1) - { - voodoo->nccTable[1][0].y[0] = val; - voodoo->ncc_dirty[1] = 1; - } - break; - case SST_nccTable0_Y1: - if (chip & CHIP_TREX0) - { - voodoo->nccTable[0][0].y[1] = val; - voodoo->ncc_dirty[0] = 1; - } - if (chip & CHIP_TREX1) - { - voodoo->nccTable[1][0].y[1] = val; - voodoo->ncc_dirty[1] = 1; - } - break; - case SST_nccTable0_Y2: - if (chip & CHIP_TREX0) - { - voodoo->nccTable[0][0].y[2] = val; - voodoo->ncc_dirty[0] = 1; - } - if (chip & CHIP_TREX1) - { - voodoo->nccTable[1][0].y[2] = val; - voodoo->ncc_dirty[1] = 1; - } - break; - case SST_nccTable0_Y3: - if (chip & CHIP_TREX0) - { - voodoo->nccTable[0][0].y[3] = val; - voodoo->ncc_dirty[0] = 1; - } - if (chip & CHIP_TREX1) - { - voodoo->nccTable[1][0].y[3] = val; - voodoo->ncc_dirty[1] = 1; - } - break; - - case SST_nccTable0_I0: - if (!(val & (1 << 31))) - { - if (chip & CHIP_TREX0) - { - voodoo->nccTable[0][0].i[0] = val; - voodoo->ncc_dirty[0] = 1; - } - if (chip & CHIP_TREX1) - { - voodoo->nccTable[1][0].i[0] = val; - voodoo->ncc_dirty[1] = 1; - } - break; - } - case SST_nccTable0_I2: - if (!(val & (1 << 31))) - { - if (chip & CHIP_TREX0) - { - voodoo->nccTable[0][0].i[2] = val; - voodoo->ncc_dirty[0] = 1; - } - if (chip & CHIP_TREX1) - { - voodoo->nccTable[1][0].i[2] = val; - voodoo->ncc_dirty[1] = 1; - } - break; - } - case SST_nccTable0_Q0: - if (!(val & (1 << 31))) - { - if (chip & CHIP_TREX0) - { - voodoo->nccTable[0][0].q[0] = val; - voodoo->ncc_dirty[0] = 1; - } - if (chip & CHIP_TREX1) - { - voodoo->nccTable[1][0].q[0] = val; - voodoo->ncc_dirty[1] = 1; - } - break; - } - case SST_nccTable0_Q2: - if (!(val & (1 << 31))) - { - if (chip & CHIP_TREX0) - { - voodoo->nccTable[0][0].i[2] = val; - voodoo->ncc_dirty[0] = 1; - } - if (chip & CHIP_TREX1) - { - voodoo->nccTable[1][0].i[2] = val; - voodoo->ncc_dirty[1] = 1; - } - break; - } - if (val & (1 << 31)) - { - int p = (val >> 23) & 0xfe; - if (chip & CHIP_TREX0) - { - voodoo->palette[0][p].u = val | 0xff000000; - voodoo->palette_dirty[0] = 1; - } - if (chip & CHIP_TREX1) - { - voodoo->palette[1][p].u = val | 0xff000000; - voodoo->palette_dirty[1] = 1; - } - } - break; - - case SST_nccTable0_I1: - if (!(val & (1 << 31))) - { - if (chip & CHIP_TREX0) - { - voodoo->nccTable[0][0].i[1] = val; - voodoo->ncc_dirty[0] = 1; - } - if (chip & CHIP_TREX1) - { - voodoo->nccTable[1][0].i[1] = val; - voodoo->ncc_dirty[1] = 1; - } - break; - } - case SST_nccTable0_I3: - if (!(val & (1 << 31))) - { - if (chip & CHIP_TREX0) - { - voodoo->nccTable[0][0].i[3] = val; - voodoo->ncc_dirty[0] = 1; - } - if (chip & CHIP_TREX1) - { - voodoo->nccTable[1][0].i[3] = val; - voodoo->ncc_dirty[1] = 1; - } - break; - } - case SST_nccTable0_Q1: - if (!(val & (1 << 31))) - { - if (chip & CHIP_TREX0) - { - voodoo->nccTable[0][0].q[1] = val; - voodoo->ncc_dirty[0] = 1; - } - if (chip & CHIP_TREX1) - { - voodoo->nccTable[1][0].q[1] = val; - voodoo->ncc_dirty[1] = 1; - } - break; - } - case SST_nccTable0_Q3: - if (!(val & (1 << 31))) - { - if (chip & CHIP_TREX0) - { - voodoo->nccTable[0][0].q[3] = val; - voodoo->ncc_dirty[0] = 1; - } - if (chip & CHIP_TREX1) - { - voodoo->nccTable[1][0].q[3] = val; - voodoo->ncc_dirty[1] = 1; - } - break; - } - if (val & (1 << 31)) - { - int p = ((val >> 23) & 0xfe) | 0x01; - if (chip & CHIP_TREX0) - { - voodoo->palette[0][p].u = val | 0xff000000; - voodoo->palette_dirty[0] = 1; - } - if (chip & CHIP_TREX1) - { - voodoo->palette[1][p].u = val | 0xff000000; - voodoo->palette_dirty[1] = 1; - } - } - break; - - case SST_nccTable1_Y0: - if (chip & CHIP_TREX0) - { - voodoo->nccTable[0][1].y[0] = val; - voodoo->ncc_dirty[0] = 1; - } - if (chip & CHIP_TREX1) - { - voodoo->nccTable[1][1].y[0] = val; - voodoo->ncc_dirty[1] = 1; - } - break; - case SST_nccTable1_Y1: - if (chip & CHIP_TREX0) - { - voodoo->nccTable[0][1].y[1] = val; - voodoo->ncc_dirty[0] = 1; - } - if (chip & CHIP_TREX1) - { - voodoo->nccTable[1][1].y[1] = val; - voodoo->ncc_dirty[1] = 1; - } - break; - case SST_nccTable1_Y2: - if (chip & CHIP_TREX0) - { - voodoo->nccTable[0][1].y[2] = val; - voodoo->ncc_dirty[0] = 1; - } - if (chip & CHIP_TREX1) - { - voodoo->nccTable[1][1].y[2] = val; - voodoo->ncc_dirty[1] = 1; - } - break; - case SST_nccTable1_Y3: - if (chip & CHIP_TREX0) - { - voodoo->nccTable[0][1].y[3] = val; - voodoo->ncc_dirty[0] = 1; - } - if (chip & CHIP_TREX1) - { - voodoo->nccTable[1][1].y[3] = val; - voodoo->ncc_dirty[1] = 1; - } - break; - case SST_nccTable1_I0: - if (chip & CHIP_TREX0) - { - voodoo->nccTable[0][1].i[0] = val; - voodoo->ncc_dirty[0] = 1; - } - if (chip & CHIP_TREX1) - { - voodoo->nccTable[1][1].i[0] = val; - voodoo->ncc_dirty[1] = 1; - } - break; - case SST_nccTable1_I1: - if (chip & CHIP_TREX0) - { - voodoo->nccTable[0][1].i[1] = val; - voodoo->ncc_dirty[0] = 1; - } - if (chip & CHIP_TREX1) - { - voodoo->nccTable[1][1].i[1] = val; - voodoo->ncc_dirty[1] = 1; - } - break; - case SST_nccTable1_I2: - if (chip & CHIP_TREX0) - { - voodoo->nccTable[0][1].i[2] = val; - voodoo->ncc_dirty[0] = 1; - } - if (chip & CHIP_TREX1) - { - voodoo->nccTable[1][1].i[2] = val; - voodoo->ncc_dirty[1] = 1; - } - break; - case SST_nccTable1_I3: - if (chip & CHIP_TREX0) - { - voodoo->nccTable[0][1].i[3] = val; - voodoo->ncc_dirty[0] = 1; - } - if (chip & CHIP_TREX1) - { - voodoo->nccTable[1][1].i[3] = val; - voodoo->ncc_dirty[1] = 1; - } - break; - case SST_nccTable1_Q0: - if (chip & CHIP_TREX0) - { - voodoo->nccTable[0][1].q[0] = val; - voodoo->ncc_dirty[0] = 1; - } - if (chip & CHIP_TREX1) - { - voodoo->nccTable[1][1].q[0] = val; - voodoo->ncc_dirty[1] = 1; - } - break; - case SST_nccTable1_Q1: - if (chip & CHIP_TREX0) - { - voodoo->nccTable[0][1].q[1] = val; - voodoo->ncc_dirty[0] = 1; - } - if (chip & CHIP_TREX1) - { - voodoo->nccTable[1][1].q[1] = val; - voodoo->ncc_dirty[1] = 1; - } - break; - case SST_nccTable1_Q2: - if (chip & CHIP_TREX0) - { - voodoo->nccTable[0][1].q[2] = val; - voodoo->ncc_dirty[0] = 1; - } - if (chip & CHIP_TREX1) - { - voodoo->nccTable[1][1].q[2] = val; - voodoo->ncc_dirty[1] = 1; - } - break; - case SST_nccTable1_Q3: - if (chip & CHIP_TREX0) - { - voodoo->nccTable[0][1].q[3] = val; - voodoo->ncc_dirty[0] = 1; - } - if (chip & CHIP_TREX1) - { - voodoo->nccTable[1][1].q[3] = val; - voodoo->ncc_dirty[1] = 1; - } - break; - - case SST_userIntrCMD: - fatal("userIntrCMD write %08x from FIFO\n", val); - break; - - - case SST_leftOverlayBuf: - voodoo->leftOverlayBuf = val; - break; - } + default: + break; + } } diff --git a/src/video/vid_voodoo_render.c b/src/video/vid_voodoo_render.c index 751c91d09..42426744a 100644 --- a/src/video/vid_voodoo_render.c +++ b/src/video/vid_voodoo_render.c @@ -1,19 +1,20 @@ /* - * 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. + * 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. + * This file is part of the 86Box distribution. * - * 3DFX Voodoo emulation. + * 3DFX Voodoo emulation. * * * - * Authors: Sarah Walker, + * Authors: Sarah Walker, * - * Copyright 2008-2020 Sarah Walker. + * Copyright 2008-2020 Sarah Walker. */ +#include #include #include #include @@ -21,6 +22,7 @@ #include #include #include +#define HAVE_STDARG_H #include <86box/86box.h> #include "cpu.h" #include <86box/machine.h> @@ -29,6 +31,7 @@ #include <86box/timer.h> #include <86box/device.h> #include <86box/plat.h> +#include <86box/thread.h> #include <86box/video.h> #include <86box/vid_svga.h> #include <86box/vid_voodoo_common.h> @@ -37,59 +40,57 @@ #include <86box/vid_voodoo_render.h> #include <86box/vid_voodoo_texture.h> +typedef struct voodoo_state_t { + int xstart, xend, xdir; + uint32_t base_r, base_g, base_b, base_a, base_z; + struct + { + int64_t base_s, base_t, base_w; + int lod; + } tmu[2]; + int64_t base_w; + int lod; + int lod_min[2], lod_max[2]; + int dx1, dx2; + int y, yend, ydir; + int32_t dxAB, dxAC, dxBC; + int tex_b[2], tex_g[2], tex_r[2], tex_a[2]; + int tex_s, tex_t; + int clamp_s[2], clamp_t[2]; -typedef struct voodoo_state_t -{ - int xstart, xend, xdir; - uint32_t base_r, base_g, base_b, base_a, base_z; - struct - { - int64_t base_s, base_t, base_w; - int lod; - } tmu[2]; - int64_t base_w; - int lod; - int lod_min[2], lod_max[2]; - int dx1, dx2; - int y, yend, ydir; - int32_t dxAB, dxAC, dxBC; - int tex_b[2], tex_g[2], tex_r[2], tex_a[2]; - int tex_s, tex_t; - int clamp_s[2], clamp_t[2]; + int32_t vertexAx, vertexAy, vertexBx, vertexBy, vertexCx, vertexCy; - int32_t vertexAx, vertexAy, vertexBx, vertexBy, vertexCx, vertexCy; + uint32_t *tex[2][LOD_MAX + 1]; + int tformat; - uint32_t *tex[2][LOD_MAX+1]; - int tformat; + int *tex_w_mask[2]; + int *tex_h_mask[2]; + int *tex_shift[2]; + int *tex_lod[2]; - int *tex_w_mask[2]; - int *tex_h_mask[2]; - int *tex_shift[2]; - int *tex_lod[2]; + uint16_t *fb_mem, *aux_mem; - uint16_t *fb_mem, *aux_mem; + int32_t ib, ig, ir, ia; + int32_t z; - int32_t ib, ig, ir, ia; - int32_t z; + int32_t new_depth; - int32_t new_depth; + int64_t tmu0_s, tmu0_t; + int64_t tmu0_w; + int64_t tmu1_s, tmu1_t; + int64_t tmu1_w; + int64_t w; - int64_t tmu0_s, tmu0_t; - int64_t tmu0_w; - int64_t tmu1_s, tmu1_t; - int64_t tmu1_w; - int64_t w; + int pixel_count, texel_count; + int x, x2, x_tiled; - int pixel_count, texel_count; - int x, x2, x_tiled; + uint32_t w_depth; - uint32_t w_depth; + float log_temp; + uint32_t ebp_store; + uint32_t texBaseAddr; - float log_temp; - uint32_t ebp_store; - uint32_t texBaseAddr; - - int lod_frac[2]; + int lod_frac[2]; } voodoo_state_t; #ifdef ENABLE_VOODOO_RENDER_LOG @@ -101,1589 +102,1524 @@ voodoo_render_log(const char *fmt, ...) va_list ap; if (voodoo_render_do_log) { - va_start(ap, fmt); - pclog_ex(fmt, ap); - va_end(ap); + va_start(ap, fmt); + pclog_ex(fmt, ap); + va_end(ap); } } #else -#define voodoo_render_log(fmt, ...) +# define voodoo_render_log(fmt, ...) #endif - -static uint8_t logtable[256] = -{ - 0x00,0x01,0x02,0x04,0x05,0x07,0x08,0x09,0x0b,0x0c,0x0e,0x0f,0x10,0x12,0x13,0x15, - 0x16,0x17,0x19,0x1a,0x1b,0x1d,0x1e,0x1f,0x21,0x22,0x23,0x25,0x26,0x27,0x28,0x2a, - 0x2b,0x2c,0x2e,0x2f,0x30,0x31,0x33,0x34,0x35,0x36,0x38,0x39,0x3a,0x3b,0x3d,0x3e, - 0x3f,0x40,0x41,0x43,0x44,0x45,0x46,0x47,0x49,0x4a,0x4b,0x4c,0x4d,0x4e,0x50,0x51, - 0x52,0x53,0x54,0x55,0x57,0x58,0x59,0x5a,0x5b,0x5c,0x5d,0x5e,0x60,0x61,0x62,0x63, - 0x64,0x65,0x66,0x67,0x68,0x69,0x6a,0x6c,0x6d,0x6e,0x6f,0x70,0x71,0x72,0x73,0x74, - 0x75,0x76,0x77,0x78,0x79,0x7a,0x7b,0x7c,0x7d,0x7e,0x7f,0x80,0x81,0x83,0x84,0x85, - 0x86,0x87,0x88,0x89,0x8a,0x8b,0x8c,0x8c,0x8d,0x8e,0x8f,0x90,0x91,0x92,0x93,0x94, - 0x95,0x96,0x97,0x98,0x99,0x9a,0x9b,0x9c,0x9d,0x9e,0x9f,0xa0,0xa1,0xa2,0xa2,0xa3, - 0xa4,0xa5,0xa6,0xa7,0xa8,0xa9,0xaa,0xab,0xac,0xad,0xad,0xae,0xaf,0xb0,0xb1,0xb2, - 0xb3,0xb4,0xb5,0xb5,0xb6,0xb7,0xb8,0xb9,0xba,0xbb,0xbc,0xbc,0xbd,0xbe,0xbf,0xc0, - 0xc1,0xc2,0xc2,0xc3,0xc4,0xc5,0xc6,0xc7,0xc8,0xc8,0xc9,0xca,0xcb,0xcc,0xcd,0xcd, - 0xce,0xcf,0xd0,0xd1,0xd1,0xd2,0xd3,0xd4,0xd5,0xd6,0xd6,0xd7,0xd8,0xd9,0xda,0xda, - 0xdb,0xdc,0xdd,0xde,0xde,0xdf,0xe0,0xe1,0xe1,0xe2,0xe3,0xe4,0xe5,0xe5,0xe6,0xe7, - 0xe8,0xe8,0xe9,0xea,0xeb,0xeb,0xec,0xed,0xee,0xef,0xef,0xf0,0xf1,0xf2,0xf2,0xf3, - 0xf4,0xf5,0xf5,0xf6,0xf7,0xf7,0xf8,0xf9,0xfa,0xfa,0xfb,0xfc,0xfd,0xfd,0xfe,0xff +static uint8_t logtable[256] = { + 0x00, 0x01, 0x02, 0x04, 0x05, 0x07, 0x08, 0x09, 0x0b, 0x0c, 0x0e, 0x0f, 0x10, 0x12, 0x13, 0x15, + 0x16, 0x17, 0x19, 0x1a, 0x1b, 0x1d, 0x1e, 0x1f, 0x21, 0x22, 0x23, 0x25, 0x26, 0x27, 0x28, 0x2a, + 0x2b, 0x2c, 0x2e, 0x2f, 0x30, 0x31, 0x33, 0x34, 0x35, 0x36, 0x38, 0x39, 0x3a, 0x3b, 0x3d, 0x3e, + 0x3f, 0x40, 0x41, 0x43, 0x44, 0x45, 0x46, 0x47, 0x49, 0x4a, 0x4b, 0x4c, 0x4d, 0x4e, 0x50, 0x51, + 0x52, 0x53, 0x54, 0x55, 0x57, 0x58, 0x59, 0x5a, 0x5b, 0x5c, 0x5d, 0x5e, 0x60, 0x61, 0x62, 0x63, + 0x64, 0x65, 0x66, 0x67, 0x68, 0x69, 0x6a, 0x6c, 0x6d, 0x6e, 0x6f, 0x70, 0x71, 0x72, 0x73, 0x74, + 0x75, 0x76, 0x77, 0x78, 0x79, 0x7a, 0x7b, 0x7c, 0x7d, 0x7e, 0x7f, 0x80, 0x81, 0x83, 0x84, 0x85, + 0x86, 0x87, 0x88, 0x89, 0x8a, 0x8b, 0x8c, 0x8c, 0x8d, 0x8e, 0x8f, 0x90, 0x91, 0x92, 0x93, 0x94, + 0x95, 0x96, 0x97, 0x98, 0x99, 0x9a, 0x9b, 0x9c, 0x9d, 0x9e, 0x9f, 0xa0, 0xa1, 0xa2, 0xa2, 0xa3, + 0xa4, 0xa5, 0xa6, 0xa7, 0xa8, 0xa9, 0xaa, 0xab, 0xac, 0xad, 0xad, 0xae, 0xaf, 0xb0, 0xb1, 0xb2, + 0xb3, 0xb4, 0xb5, 0xb5, 0xb6, 0xb7, 0xb8, 0xb9, 0xba, 0xbb, 0xbc, 0xbc, 0xbd, 0xbe, 0xbf, 0xc0, + 0xc1, 0xc2, 0xc2, 0xc3, 0xc4, 0xc5, 0xc6, 0xc7, 0xc8, 0xc8, 0xc9, 0xca, 0xcb, 0xcc, 0xcd, 0xcd, + 0xce, 0xcf, 0xd0, 0xd1, 0xd1, 0xd2, 0xd3, 0xd4, 0xd5, 0xd6, 0xd6, 0xd7, 0xd8, 0xd9, 0xda, 0xda, + 0xdb, 0xdc, 0xdd, 0xde, 0xde, 0xdf, 0xe0, 0xe1, 0xe1, 0xe2, 0xe3, 0xe4, 0xe5, 0xe5, 0xe6, 0xe7, + 0xe8, 0xe8, 0xe9, 0xea, 0xeb, 0xeb, 0xec, 0xed, 0xee, 0xef, 0xef, 0xf0, 0xf1, 0xf2, 0xf2, 0xf3, + 0xf4, 0xf5, 0xf5, 0xf6, 0xf7, 0xf7, 0xf8, 0xf9, 0xfa, 0xfa, 0xfb, 0xfc, 0xfd, 0xfd, 0xfe, 0xff }; -static __inline int fastlog(uint64_t val) +static __inline int +fastlog(uint64_t val) { - uint64_t oldval = val; - int exp = 63; - int frac; + uint64_t oldval = val; + int exp = 63; + int frac; - if (!val || val & (1ULL << 63)) - return 0x80000000; + if (!val || val & (1ULL << 63)) + return 0x80000000; - if (!(val & 0xffffffff00000000)) - { - exp -= 32; - val <<= 32; - } - if (!(val & 0xffff000000000000)) - { - exp -= 16; - val <<= 16; - } - if (!(val & 0xff00000000000000)) - { - exp -= 8; - val <<= 8; - } - if (!(val & 0xf000000000000000)) - { - exp -= 4; - val <<= 4; - } - if (!(val & 0xc000000000000000)) - { - exp -= 2; - val <<= 2; - } - if (!(val & 0x8000000000000000)) - { - exp -= 1; - val <<= 1; - } + if (!(val & 0xffffffff00000000)) { + exp -= 32; + val <<= 32; + } + if (!(val & 0xffff000000000000)) { + exp -= 16; + val <<= 16; + } + if (!(val & 0xff00000000000000)) { + exp -= 8; + val <<= 8; + } + if (!(val & 0xf000000000000000)) { + exp -= 4; + val <<= 4; + } + if (!(val & 0xc000000000000000)) { + exp -= 2; + val <<= 2; + } + if (!(val & 0x8000000000000000)) { + exp -= 1; + val <<= 1; + } - if (exp >= 8) - frac = (oldval >> (exp - 8)) & 0xff; - else - frac = (oldval << (8 - exp)) & 0xff; + if (exp >= 8) + frac = (oldval >> (exp - 8)) & 0xff; + else + frac = (oldval << (8 - exp)) & 0xff; - return (exp << 8) | logtable[frac]; + return (exp << 8) | logtable[frac]; } -static inline int voodoo_fls(uint16_t val) +static inline int +voodoo_fls(uint16_t val) { - int num = 0; + int num = 0; -//voodoo_render_log("fls(%04x) = ", val); - if (!(val & 0xff00)) - { - num += 8; - val <<= 8; - } - if (!(val & 0xf000)) - { - num += 4; - val <<= 4; - } - if (!(val & 0xc000)) - { - num += 2; - val <<= 2; - } - if (!(val & 0x8000)) - { - num += 1; - val <<= 1; - } -//voodoo_render_log("%i %04x\n", num, val); - return num; +#if 0 + voodoo_render_log("fls(%04x) = ", val); +#endif + if (!(val & 0xff00)) { + num += 8; + val <<= 8; + } + if (!(val & 0xf000)) { + num += 4; + val <<= 4; + } + if (!(val & 0xc000)) { + num += 2; + val <<= 2; + } + if (!(val & 0x8000)) { + num += 1; + val <<= 1; + } +#if 0 + voodoo_render_log("%i %04x\n", num, val); +#endif + return num; } -typedef struct voodoo_texture_state_t -{ - int s, t; - int w_mask, h_mask; - int tex_shift; +typedef struct voodoo_texture_state_t { + int s, t; + int w_mask, h_mask; + int tex_shift; } voodoo_texture_state_t; -static inline void tex_read(voodoo_state_t *state, voodoo_texture_state_t *texture_state, int tmu) +static inline void +tex_read(voodoo_state_t *state, voodoo_texture_state_t *texture_state, int tmu) { - uint32_t dat; + uint32_t dat; - if (texture_state->s & ~texture_state->w_mask) - { - if (state->clamp_s[tmu]) - { - if (texture_state->s < 0) - texture_state->s = 0; - if (texture_state->s > texture_state->w_mask) - texture_state->s = texture_state->w_mask; - } - else - texture_state->s &= texture_state->w_mask; - } - if (texture_state->t & ~texture_state->h_mask) - { - if (state->clamp_t[tmu]) - { - if (texture_state->t < 0) - texture_state->t = 0; - if (texture_state->t > texture_state->h_mask) - texture_state->t = texture_state->h_mask; - } - else - texture_state->t &= texture_state->h_mask; - } + if (texture_state->s & ~texture_state->w_mask) { + if (state->clamp_s[tmu]) { + if (texture_state->s < 0) + texture_state->s = 0; + if (texture_state->s > texture_state->w_mask) + texture_state->s = texture_state->w_mask; + } else + texture_state->s &= texture_state->w_mask; + } + if (texture_state->t & ~texture_state->h_mask) { + if (state->clamp_t[tmu]) { + if (texture_state->t < 0) + texture_state->t = 0; + if (texture_state->t > texture_state->h_mask) + texture_state->t = texture_state->h_mask; + } else + texture_state->t &= texture_state->h_mask; + } - dat = state->tex[tmu][state->lod][texture_state->s + (texture_state->t << texture_state->tex_shift)]; + dat = state->tex[tmu][state->lod][texture_state->s + (texture_state->t << texture_state->tex_shift)]; - state->tex_b[tmu] = dat & 0xff; - state->tex_g[tmu] = (dat >> 8) & 0xff; - state->tex_r[tmu] = (dat >> 16) & 0xff; - state->tex_a[tmu] = (dat >> 24) & 0xff; + state->tex_b[tmu] = dat & 0xff; + state->tex_g[tmu] = (dat >> 8) & 0xff; + state->tex_r[tmu] = (dat >> 16) & 0xff; + state->tex_a[tmu] = (dat >> 24) & 0xff; } #define LOW4(x) ((x & 0x0f) | ((x & 0x0f) << 4)) #define HIGH4(x) ((x & 0xf0) | ((x & 0xf0) >> 4)) -static inline void tex_read_4(voodoo_state_t *state, voodoo_texture_state_t *texture_state, int s, int t, int *d, int tmu, int x) +static inline void +tex_read_4(voodoo_state_t *state, voodoo_texture_state_t *texture_state, int s, int t, int *d, int tmu, UNUSED(int x)) { - rgba_u dat[4]; + rgba_u dat[4]; - if (((s | (s + 1)) & ~texture_state->w_mask) || ((t | (t + 1)) & ~texture_state->h_mask)) - { - int c; - for (c = 0; c < 4; c++) - { - int _s = s + (c & 1); - int _t = t + ((c & 2) >> 1); + if (((s | (s + 1)) & ~texture_state->w_mask) || ((t | (t + 1)) & ~texture_state->h_mask)) { + for (uint8_t c = 0; c < 4; c++) { + int _s = s + (c & 1); + int _t = t + ((c & 2) >> 1); - if (_s & ~texture_state->w_mask) - { - if (state->clamp_s[tmu]) - { - if (_s < 0) - _s = 0; - if (_s > texture_state->w_mask) - _s = texture_state->w_mask; - } - else - _s &= texture_state->w_mask; - } - if (_t & ~texture_state->h_mask) - { - if (state->clamp_t[tmu]) - { - if (_t < 0) - _t = 0; - if (_t > texture_state->h_mask) - _t = texture_state->h_mask; - } - else - _t &= texture_state->h_mask; - } - dat[c].u = state->tex[tmu][state->lod][_s + (_t << texture_state->tex_shift)]; - } - } - else - { - dat[0].u = state->tex[tmu][state->lod][s + (t << texture_state->tex_shift)]; - dat[1].u = state->tex[tmu][state->lod][s + 1 + (t << texture_state->tex_shift)]; - dat[2].u = state->tex[tmu][state->lod][s + ((t + 1) << texture_state->tex_shift)]; - dat[3].u = state->tex[tmu][state->lod][s + 1 + ((t + 1) << texture_state->tex_shift)]; + if (_s & ~texture_state->w_mask) { + if (state->clamp_s[tmu]) { + if (_s < 0) + _s = 0; + if (_s > texture_state->w_mask) + _s = texture_state->w_mask; + } else + _s &= texture_state->w_mask; + } + if (_t & ~texture_state->h_mask) { + if (state->clamp_t[tmu]) { + if (_t < 0) + _t = 0; + if (_t > texture_state->h_mask) + _t = texture_state->h_mask; + } else + _t &= texture_state->h_mask; + } + dat[c].u = state->tex[tmu][state->lod][_s + (_t << texture_state->tex_shift)]; } + } else { + dat[0].u = state->tex[tmu][state->lod][s + (t << texture_state->tex_shift)]; + dat[1].u = state->tex[tmu][state->lod][s + 1 + (t << texture_state->tex_shift)]; + dat[2].u = state->tex[tmu][state->lod][s + ((t + 1) << texture_state->tex_shift)]; + dat[3].u = state->tex[tmu][state->lod][s + 1 + ((t + 1) << texture_state->tex_shift)]; + } - state->tex_r[tmu] = (dat[0].rgba.r * d[0] + dat[1].rgba.r * d[1] + dat[2].rgba.r * d[2] + dat[3].rgba.r * d[3]) >> 8; - state->tex_g[tmu] = (dat[0].rgba.g * d[0] + dat[1].rgba.g * d[1] + dat[2].rgba.g * d[2] + dat[3].rgba.g * d[3]) >> 8; - state->tex_b[tmu] = (dat[0].rgba.b * d[0] + dat[1].rgba.b * d[1] + dat[2].rgba.b * d[2] + dat[3].rgba.b * d[3]) >> 8; - state->tex_a[tmu] = (dat[0].rgba.a * d[0] + dat[1].rgba.a * d[1] + dat[2].rgba.a * d[2] + dat[3].rgba.a * d[3]) >> 8; + state->tex_r[tmu] = (dat[0].rgba.r * d[0] + dat[1].rgba.r * d[1] + dat[2].rgba.r * d[2] + dat[3].rgba.r * d[3]) >> 8; + state->tex_g[tmu] = (dat[0].rgba.g * d[0] + dat[1].rgba.g * d[1] + dat[2].rgba.g * d[2] + dat[3].rgba.g * d[3]) >> 8; + state->tex_b[tmu] = (dat[0].rgba.b * d[0] + dat[1].rgba.b * d[1] + dat[2].rgba.b * d[2] + dat[3].rgba.b * d[3]) >> 8; + state->tex_a[tmu] = (dat[0].rgba.a * d[0] + dat[1].rgba.a * d[1] + dat[2].rgba.a * d[2] + dat[3].rgba.a * d[3]) >> 8; } -static inline void voodoo_get_texture(voodoo_t *voodoo, voodoo_params_t *params, voodoo_state_t *state, int tmu, int x) +static inline void +voodoo_get_texture(voodoo_t *voodoo, voodoo_params_t *params, voodoo_state_t *state, int tmu, int x) { + voodoo_texture_state_t texture_state; + int d[4]; + int s; + int t; + int tex_lod = state->tex_lod[tmu][state->lod]; + + texture_state.w_mask = state->tex_w_mask[tmu][state->lod]; + texture_state.h_mask = state->tex_h_mask[tmu][state->lod]; + texture_state.tex_shift = 8 - tex_lod; + + if (params->tLOD[tmu] & LOD_TMIRROR_S) { + if (state->tex_s & 0x1000) + state->tex_s = ~state->tex_s; + } + if (params->tLOD[tmu] & LOD_TMIRROR_T) { + if (state->tex_t & 0x1000) + state->tex_t = ~state->tex_t; + } + + if (voodoo->bilinear_enabled && params->textureMode[tmu] & 6) { + int _ds; + int dt; + + state->tex_s -= 1 << (3 + tex_lod); + state->tex_t -= 1 << (3 + tex_lod); + + s = state->tex_s >> tex_lod; + t = state->tex_t >> tex_lod; + + _ds = s & 0xf; + dt = t & 0xf; + + s >>= 4; + t >>= 4; +#if 0 + if (x == 80) + if (voodoo_output) + voodoo_render_log("s=%08x t=%08x _ds=%02x _dt=%02x\n", s, t, _ds, dt); +#endif + d[0] = (16 - _ds) * (16 - dt); + d[1] = _ds * (16 - dt); + d[2] = (16 - _ds) * dt; + d[3] = _ds * dt; + +#if 0 + texture_state.s = s; + texture_state.t = t; +#endif + tex_read_4(state, &texture_state, s, t, d, tmu, x); + +#if 0 + state->tex_r = (tex_samples[0].rgba.r * d[0] + tex_samples[1].rgba.r * d[1] + tex_samples[2].rgba.r * d[2] + tex_samples[3].rgba.r * d[3]) >> 8; + state->tex_g = (tex_samples[0].rgba.g * d[0] + tex_samples[1].rgba.g * d[1] + tex_samples[2].rgba.g * d[2] + tex_samples[3].rgba.g * d[3]) >> 8; + state->tex_b = (tex_samples[0].rgba.b * d[0] + tex_samples[1].rgba.b * d[1] + tex_samples[2].rgba.b * d[2] + tex_samples[3].rgba.b * d[3]) >> 8; + state->tex_a = (tex_samples[0].rgba.a * d[0] + tex_samples[1].rgba.a * d[1] + tex_samples[2].rgba.a * d[2] + tex_samples[3].rgba.a * d[3]) >> 8;*/ +#endif +#if 0 + state->tex_r = tex_samples[0].r; + state->tex_g = tex_samples[0].g; + state->tex_b = tex_samples[0].b; + state->tex_a = tex_samples[0].a; +#endif + } else { +#if 0 + rgba_t tex_samples; voodoo_texture_state_t texture_state; - int d[4]; - int s, t; - int tex_lod = state->tex_lod[tmu][state->lod]; + int s = state->tex_s >> (18+state->lod); + int t = state->tex_t >> (18+state->lod); - texture_state.w_mask = state->tex_w_mask[tmu][state->lod]; - texture_state.h_mask = state->tex_h_mask[tmu][state->lod]; - texture_state.tex_shift = 8 - tex_lod; + state->tex_s -= 1 << (17+state->lod); + state->tex_t -= 1 << (17+state->lod); +#endif + s = state->tex_s >> (4 + tex_lod); + t = state->tex_t >> (4 + tex_lod); - if (params->tLOD[tmu] & LOD_TMIRROR_S) - { - if (state->tex_s & 0x1000) - state->tex_s = ~state->tex_s; - } - if (params->tLOD[tmu] & LOD_TMIRROR_T) - { - if (state->tex_t & 0x1000) - state->tex_t = ~state->tex_t; - } + texture_state.s = s; + texture_state.t = t; + tex_read(state, &texture_state, tmu); - if (voodoo->bilinear_enabled && params->textureMode[tmu] & 6) - { - int _ds, dt; - - state->tex_s -= 1 << (3+tex_lod); - state->tex_t -= 1 << (3+tex_lod); - - s = state->tex_s >> tex_lod; - t = state->tex_t >> tex_lod; - - _ds = s & 0xf; - dt = t & 0xf; - - s >>= 4; - t >>= 4; -//if (x == 80) -//if (voodoo_output) -// voodoo_render_log("s=%08x t=%08x _ds=%02x _dt=%02x\n", s, t, _ds, dt); - d[0] = (16 - _ds) * (16 - dt); - d[1] = _ds * (16 - dt); - d[2] = (16 - _ds) * dt; - d[3] = _ds * dt; - -// texture_state.s = s; -// texture_state.t = t; - tex_read_4(state, &texture_state, s, t, d, tmu, x); - - -/* state->tex_r = (tex_samples[0].rgba.r * d[0] + tex_samples[1].rgba.r * d[1] + tex_samples[2].rgba.r * d[2] + tex_samples[3].rgba.r * d[3]) >> 8; - state->tex_g = (tex_samples[0].rgba.g * d[0] + tex_samples[1].rgba.g * d[1] + tex_samples[2].rgba.g * d[2] + tex_samples[3].rgba.g * d[3]) >> 8; - state->tex_b = (tex_samples[0].rgba.b * d[0] + tex_samples[1].rgba.b * d[1] + tex_samples[2].rgba.b * d[2] + tex_samples[3].rgba.b * d[3]) >> 8; - state->tex_a = (tex_samples[0].rgba.a * d[0] + tex_samples[1].rgba.a * d[1] + tex_samples[2].rgba.a * d[2] + tex_samples[3].rgba.a * d[3]) >> 8;*/ -/* state->tex_r = tex_samples[0].r; - state->tex_g = tex_samples[0].g; - state->tex_b = tex_samples[0].b; - state->tex_a = tex_samples[0].a;*/ - } - else - { - // rgba_t tex_samples; - // voodoo_texture_state_t texture_state; -// int s = state->tex_s >> (18+state->lod); -// int t = state->tex_t >> (18+state->lod); - // int s, t; - -// state->tex_s -= 1 << (17+state->lod); -// state->tex_t -= 1 << (17+state->lod); - - s = state->tex_s >> (4+tex_lod); - t = state->tex_t >> (4+tex_lod); - - texture_state.s = s; - texture_state.t = t; - tex_read(state, &texture_state, tmu); - -/* state->tex_r = tex_samples[0].rgba.r; - state->tex_g = tex_samples[0].rgba.g; - state->tex_b = tex_samples[0].rgba.b; - state->tex_a = tex_samples[0].rgba.a;*/ - } +#if 0 + state->tex_r = tex_samples[0].rgba.r; + state->tex_g = tex_samples[0].rgba.g; + state->tex_b = tex_samples[0].rgba.b; + state->tex_a = tex_samples[0].rgba.a; +#endif + } } -static inline void voodoo_tmu_fetch(voodoo_t *voodoo, voodoo_params_t *params, voodoo_state_t *state, int tmu, int x) +static inline void +voodoo_tmu_fetch(voodoo_t *voodoo, voodoo_params_t *params, voodoo_state_t *state, int tmu, int x) { - if (params->textureMode[tmu] & 1) - { - int64_t _w = 0; + if (params->textureMode[tmu] & 1) { + int64_t _w = 0; - if (tmu) - { - if (state->tmu1_w) - _w = (int64_t)((1ULL << 48) / state->tmu1_w); - state->tex_s = (int32_t)(((((state->tmu1_s + (1 << 13)) >> 14) * _w) + (1 << 29)) >> 30); - state->tex_t = (int32_t)(((((state->tmu1_t + (1 << 13)) >> 14) * _w) + (1 << 29)) >> 30); - } - else - { - if (state->tmu0_w) - _w = (int64_t)((1ULL << 48) / state->tmu0_w); - state->tex_s = (int32_t)(((((state->tmu0_s + (1 << 13)) >> 14) * _w) + (1 << 29)) >> 30); - state->tex_t = (int32_t)(((((state->tmu0_t + (1 << 13)) >> 14) * _w) + (1 << 29)) >> 30); - } - - state->lod = state->tmu[tmu].lod + (fastlog(_w) - (19 << 8)); - } - else - { - if (tmu) - { - state->tex_s = (int32_t)(state->tmu1_s >> (14+14)); - state->tex_t = (int32_t)(state->tmu1_t >> (14+14)); - } - else - { - state->tex_s = (int32_t)(state->tmu0_s >> (14+14)); - state->tex_t = (int32_t)(state->tmu0_t >> (14+14)); - } - state->lod = state->tmu[tmu].lod; + if (tmu) { + if (state->tmu1_w) + _w = (int64_t) ((1ULL << 48) / state->tmu1_w); + state->tex_s = (int32_t) (((((state->tmu1_s + (1 << 13)) >> 14) * _w) + (1 << 29)) >> 30); + state->tex_t = (int32_t) (((((state->tmu1_t + (1 << 13)) >> 14) * _w) + (1 << 29)) >> 30); + } else { + if (state->tmu0_w) + _w = (int64_t) ((1ULL << 48) / state->tmu0_w); + state->tex_s = (int32_t) (((((state->tmu0_s + (1 << 13)) >> 14) * _w) + (1 << 29)) >> 30); + state->tex_t = (int32_t) (((((state->tmu0_t + (1 << 13)) >> 14) * _w) + (1 << 29)) >> 30); } - if (state->lod < state->lod_min[tmu]) - state->lod = state->lod_min[tmu]; - else if (state->lod > state->lod_max[tmu]) - state->lod = state->lod_max[tmu]; - state->lod_frac[tmu] = state->lod & 0xff; - state->lod >>= 8; + state->lod = state->tmu[tmu].lod + (fastlog(_w) - (19 << 8)); + } else { + if (tmu) { + state->tex_s = (int32_t) (state->tmu1_s >> (14 + 14)); + state->tex_t = (int32_t) (state->tmu1_t >> (14 + 14)); + } else { + state->tex_s = (int32_t) (state->tmu0_s >> (14 + 14)); + state->tex_t = (int32_t) (state->tmu0_t >> (14 + 14)); + } + state->lod = state->tmu[tmu].lod; + } - voodoo_get_texture(voodoo, params, state, tmu, x); + if (state->lod < state->lod_min[tmu]) + state->lod = state->lod_min[tmu]; + else if (state->lod > state->lod_max[tmu]) + state->lod = state->lod_max[tmu]; + state->lod_frac[tmu] = state->lod & 0xff; + state->lod >>= 8; + + voodoo_get_texture(voodoo, params, state, tmu, x); } - /*Perform texture fetch and blending for both TMUs*/ -static inline void voodoo_tmu_fetch_and_blend(voodoo_t *voodoo, voodoo_params_t *params, voodoo_state_t *state, int x) +static inline void +voodoo_tmu_fetch_and_blend(voodoo_t *voodoo, voodoo_params_t *params, voodoo_state_t *state, int x) { - int r,g,b,a; - int c_reverse, a_reverse; -// int c_reverse1, a_reverse1; - int factor_r = 0, factor_g = 0, factor_b = 0, factor_a = 0; + int r; + int g; + int b; + int a; + int c_reverse; + int a_reverse; +#if 0 + int c_reverse1; + int a_reverse1; +#endif + int factor_r = 0; + int factor_g = 0; + int factor_b = 0; + int factor_a = 0; - voodoo_tmu_fetch(voodoo, params, state, 1, x); + voodoo_tmu_fetch(voodoo, params, state, 1, x); - if ((params->textureMode[1] & TEXTUREMODE_TRILINEAR) && (state->lod & 1)) - { - c_reverse = tc_reverse_blend; - a_reverse = tca_reverse_blend; - } - else - { - c_reverse = !tc_reverse_blend; - a_reverse = !tca_reverse_blend; - } -/* c_reverse1 = c_reverse; - a_reverse1 = a_reverse;*/ - if (tc_sub_clocal_1) - { - switch (tc_mselect_1) - { - case TC_MSELECT_ZERO: - factor_r = factor_g = factor_b = 0; - break; - case TC_MSELECT_CLOCAL: - factor_r = state->tex_r[1]; - factor_g = state->tex_g[1]; - factor_b = state->tex_b[1]; - break; - case TC_MSELECT_AOTHER: - factor_r = factor_g = factor_b = 0; - break; - case TC_MSELECT_ALOCAL: - factor_r = factor_g = factor_b = state->tex_a[1]; - break; - case TC_MSELECT_DETAIL: - factor_r = (params->detail_bias[1] - state->lod) << params->detail_scale[1]; - if (factor_r > params->detail_max[1]) - factor_r = params->detail_max[1]; - factor_g = factor_b = factor_r; - break; - case TC_MSELECT_LOD_FRAC: - factor_r = factor_g = factor_b = state->lod_frac[1]; - break; - } - if (!c_reverse) - { - r = (-state->tex_r[1] * (factor_r + 1)) >> 8; - g = (-state->tex_g[1] * (factor_g + 1)) >> 8; - b = (-state->tex_b[1] * (factor_b + 1)) >> 8; - } - else - { - r = (-state->tex_r[1] * ((factor_r^0xff) + 1)) >> 8; - g = (-state->tex_g[1] * ((factor_g^0xff) + 1)) >> 8; - b = (-state->tex_b[1] * ((factor_b^0xff) + 1)) >> 8; - } - if (tc_add_clocal_1) - { - r += state->tex_r[1]; - g += state->tex_g[1]; - b += state->tex_b[1]; - } - else if (tc_add_alocal_1) - { - r += state->tex_a[1]; - g += state->tex_a[1]; - b += state->tex_a[1]; - } - state->tex_r[1] = CLAMP(r); - state->tex_g[1] = CLAMP(g); - state->tex_b[1] = CLAMP(b); - } - if (tca_sub_clocal_1) - { - switch (tca_mselect_1) - { - case TCA_MSELECT_ZERO: - factor_a = 0; - break; - case TCA_MSELECT_CLOCAL: - factor_a = state->tex_a[1]; - break; - case TCA_MSELECT_AOTHER: - factor_a = 0; - break; - case TCA_MSELECT_ALOCAL: - factor_a = state->tex_a[1]; - break; - case TCA_MSELECT_DETAIL: - factor_a = (params->detail_bias[1] - state->lod) << params->detail_scale[1]; - if (factor_a > params->detail_max[1]) - factor_a = params->detail_max[1]; - break; - case TCA_MSELECT_LOD_FRAC: - factor_a = state->lod_frac[1]; - break; - } - if (!a_reverse) - a = (-state->tex_a[1] * ((factor_a ^ 0xff) + 1)) >> 8; - else - a = (-state->tex_a[1] * (factor_a + 1)) >> 8; - if (tca_add_clocal_1 || tca_add_alocal_1) - a += state->tex_a[1]; - state->tex_a[1] = CLAMP(a); - } - - - voodoo_tmu_fetch(voodoo, params, state, 0, x); - - if ((params->textureMode[0] & TEXTUREMODE_TRILINEAR) && (state->lod & 1)) - { - c_reverse = tc_reverse_blend; - a_reverse = tca_reverse_blend; - } - else - { - c_reverse = !tc_reverse_blend; - a_reverse = !tca_reverse_blend; - } - - if (!tc_zero_other) - { - r = state->tex_r[1]; - g = state->tex_g[1]; - b = state->tex_b[1]; - } - else - r = g = b = 0; - if (tc_sub_clocal) - { - r -= state->tex_r[0]; - g -= state->tex_g[0]; - b -= state->tex_b[0]; - } - switch (tc_mselect) - { - case TC_MSELECT_ZERO: + if ((params->textureMode[1] & TEXTUREMODE_TRILINEAR) && (state->lod & 1)) { + c_reverse = tc_reverse_blend; + a_reverse = tca_reverse_blend; + } else { + c_reverse = !tc_reverse_blend; + a_reverse = !tca_reverse_blend; + } +#if 0 + c_reverse1 = c_reverse; + a_reverse1 = a_reverse; +#endif + if (tc_sub_clocal_1) { + switch (tc_mselect_1) { + case TC_MSELECT_ZERO: factor_r = factor_g = factor_b = 0; break; - case TC_MSELECT_CLOCAL: - factor_r = state->tex_r[0]; - factor_g = state->tex_g[0]; - factor_b = state->tex_b[0]; + case TC_MSELECT_CLOCAL: + factor_r = state->tex_r[1]; + factor_g = state->tex_g[1]; + factor_b = state->tex_b[1]; break; - case TC_MSELECT_AOTHER: + case TC_MSELECT_AOTHER: + factor_r = factor_g = factor_b = 0; + break; + case TC_MSELECT_ALOCAL: factor_r = factor_g = factor_b = state->tex_a[1]; break; - case TC_MSELECT_ALOCAL: - factor_r = factor_g = factor_b = state->tex_a[0]; - break; - case TC_MSELECT_DETAIL: - factor_r = (params->detail_bias[0] - state->lod) << params->detail_scale[0]; - if (factor_r > params->detail_max[0]) - factor_r = params->detail_max[0]; + case TC_MSELECT_DETAIL: + factor_r = (params->detail_bias[1] - state->lod) << params->detail_scale[1]; + if (factor_r > params->detail_max[1]) + factor_r = params->detail_max[1]; factor_g = factor_b = factor_r; break; - case TC_MSELECT_LOD_FRAC: - factor_r = factor_g = factor_b = state->lod_frac[0]; + case TC_MSELECT_LOD_FRAC: + factor_r = factor_g = factor_b = state->lod_frac[1]; + break; + + default: break; } - if (!c_reverse) - { - r = (r * (factor_r + 1)) >> 8; - g = (g * (factor_g + 1)) >> 8; - b = (b * (factor_b + 1)) >> 8; + if (!c_reverse) { + r = (-state->tex_r[1] * (factor_r + 1)) >> 8; + g = (-state->tex_g[1] * (factor_g + 1)) >> 8; + b = (-state->tex_b[1] * (factor_b + 1)) >> 8; + } else { + r = (-state->tex_r[1] * ((factor_r ^ 0xff) + 1)) >> 8; + g = (-state->tex_g[1] * ((factor_g ^ 0xff) + 1)) >> 8; + b = (-state->tex_b[1] * ((factor_b ^ 0xff) + 1)) >> 8; } - else - { - r = (r * ((factor_r^0xff) + 1)) >> 8; - g = (g * ((factor_g^0xff) + 1)) >> 8; - b = (b * ((factor_b^0xff) + 1)) >> 8; + if (tc_add_clocal_1) { + r += state->tex_r[1]; + g += state->tex_g[1]; + b += state->tex_b[1]; + } else if (tc_add_alocal_1) { + r += state->tex_a[1]; + g += state->tex_a[1]; + b += state->tex_a[1]; } - if (tc_add_clocal) - { - r += state->tex_r[0]; - g += state->tex_g[0]; - b += state->tex_b[0]; - } - else if (tc_add_alocal) - { - r += state->tex_a[0]; - g += state->tex_a[0]; - b += state->tex_a[0]; - } - - if (!tca_zero_other) - a = state->tex_a[1]; - else - a = 0; - if (tca_sub_clocal) - a -= state->tex_a[0]; - switch (tca_mselect) - { - case TCA_MSELECT_ZERO: + state->tex_r[1] = CLAMP(r); + state->tex_g[1] = CLAMP(g); + state->tex_b[1] = CLAMP(b); + } + if (tca_sub_clocal_1) { + switch (tca_mselect_1) { + case TCA_MSELECT_ZERO: factor_a = 0; break; - case TCA_MSELECT_CLOCAL: - factor_a = state->tex_a[0]; - break; - case TCA_MSELECT_AOTHER: + case TCA_MSELECT_CLOCAL: factor_a = state->tex_a[1]; break; - case TCA_MSELECT_ALOCAL: - factor_a = state->tex_a[0]; + case TCA_MSELECT_AOTHER: + factor_a = 0; break; - case TCA_MSELECT_DETAIL: - factor_a = (params->detail_bias[0] - state->lod) << params->detail_scale[0]; - if (factor_a > params->detail_max[0]) - factor_a = params->detail_max[0]; + case TCA_MSELECT_ALOCAL: + factor_a = state->tex_a[1]; break; - case TCA_MSELECT_LOD_FRAC: - factor_a = state->lod_frac[0]; + case TCA_MSELECT_DETAIL: + factor_a = (params->detail_bias[1] - state->lod) << params->detail_scale[1]; + if (factor_a > params->detail_max[1]) + factor_a = params->detail_max[1]; + break; + case TCA_MSELECT_LOD_FRAC: + factor_a = state->lod_frac[1]; + break; + + default: break; } - if (a_reverse) - a = (a * ((factor_a ^ 0xff) + 1)) >> 8; + if (!a_reverse) + a = (-state->tex_a[1] * ((factor_a ^ 0xff) + 1)) >> 8; else - a = (a * (factor_a + 1)) >> 8; - if (tca_add_clocal || tca_add_alocal) - a += state->tex_a[0]; + a = (-state->tex_a[1] * (factor_a + 1)) >> 8; + if (tca_add_clocal_1 || tca_add_alocal_1) + a += state->tex_a[1]; + state->tex_a[1] = CLAMP(a); + } + voodoo_tmu_fetch(voodoo, params, state, 0, x); - state->tex_r[0] = CLAMP(r); - state->tex_g[0] = CLAMP(g); - state->tex_b[0] = CLAMP(b); - state->tex_a[0] = CLAMP(a); + if ((params->textureMode[0] & TEXTUREMODE_TRILINEAR) && (state->lod & 1)) { + c_reverse = tc_reverse_blend; + a_reverse = tca_reverse_blend; + } else { + c_reverse = !tc_reverse_blend; + a_reverse = !tca_reverse_blend; + } - if (tc_invert_output) - { - state->tex_r[0] ^= 0xff; - state->tex_g[0] ^= 0xff; - state->tex_b[0] ^= 0xff; - } - if (tca_invert_output) - state->tex_a[0] ^= 0xff; + if (!tc_zero_other) { + r = state->tex_r[1]; + g = state->tex_g[1]; + b = state->tex_b[1]; + } else + r = g = b = 0; + if (tc_sub_clocal) { + r -= state->tex_r[0]; + g -= state->tex_g[0]; + b -= state->tex_b[0]; + } + switch (tc_mselect) { + case TC_MSELECT_ZERO: + factor_r = factor_g = factor_b = 0; + break; + case TC_MSELECT_CLOCAL: + factor_r = state->tex_r[0]; + factor_g = state->tex_g[0]; + factor_b = state->tex_b[0]; + break; + case TC_MSELECT_AOTHER: + factor_r = factor_g = factor_b = state->tex_a[1]; + break; + case TC_MSELECT_ALOCAL: + factor_r = factor_g = factor_b = state->tex_a[0]; + break; + case TC_MSELECT_DETAIL: + factor_r = (params->detail_bias[0] - state->lod) << params->detail_scale[0]; + if (factor_r > params->detail_max[0]) + factor_r = params->detail_max[0]; + factor_g = factor_b = factor_r; + break; + case TC_MSELECT_LOD_FRAC: + factor_r = factor_g = factor_b = state->lod_frac[0]; + break; + + default: + break; + } + if (!c_reverse) { + r = (r * (factor_r + 1)) >> 8; + g = (g * (factor_g + 1)) >> 8; + b = (b * (factor_b + 1)) >> 8; + } else { + r = (r * ((factor_r ^ 0xff) + 1)) >> 8; + g = (g * ((factor_g ^ 0xff) + 1)) >> 8; + b = (b * ((factor_b ^ 0xff) + 1)) >> 8; + } + if (tc_add_clocal) { + r += state->tex_r[0]; + g += state->tex_g[0]; + b += state->tex_b[0]; + } else if (tc_add_alocal) { + r += state->tex_a[0]; + g += state->tex_a[0]; + b += state->tex_a[0]; + } + + if (!tca_zero_other) + a = state->tex_a[1]; + else + a = 0; + if (tca_sub_clocal) + a -= state->tex_a[0]; + switch (tca_mselect) { + case TCA_MSELECT_ZERO: + factor_a = 0; + break; + case TCA_MSELECT_CLOCAL: + factor_a = state->tex_a[0]; + break; + case TCA_MSELECT_AOTHER: + factor_a = state->tex_a[1]; + break; + case TCA_MSELECT_ALOCAL: + factor_a = state->tex_a[0]; + break; + case TCA_MSELECT_DETAIL: + factor_a = (params->detail_bias[0] - state->lod) << params->detail_scale[0]; + if (factor_a > params->detail_max[0]) + factor_a = params->detail_max[0]; + break; + case TCA_MSELECT_LOD_FRAC: + factor_a = state->lod_frac[0]; + break; + + default: + break; + } + if (a_reverse) + a = (a * ((factor_a ^ 0xff) + 1)) >> 8; + else + a = (a * (factor_a + 1)) >> 8; + if (tca_add_clocal || tca_add_alocal) + a += state->tex_a[0]; + + state->tex_r[0] = CLAMP(r); + state->tex_g[0] = CLAMP(g); + state->tex_b[0] = CLAMP(b); + state->tex_a[0] = CLAMP(a); + + if (tc_invert_output) { + state->tex_r[0] ^= 0xff; + state->tex_g[0] ^= 0xff; + state->tex_b[0] ^= 0xff; + } + if (tca_invert_output) + state->tex_a[0] ^= 0xff; } #if (defined i386 || defined __i386 || defined __i386__ || defined _X86_ || defined _M_IX86) && !(defined __amd64__ || defined _M_X64) -#include <86box/vid_voodoo_codegen_x86.h> +# include <86box/vid_voodoo_codegen_x86.h> #elif (defined __amd64__ || defined _M_X64) -#include <86box/vid_voodoo_codegen_x86-64.h> +# include <86box/vid_voodoo_codegen_x86-64.h> #else int voodoo_recomp = 0; #endif -static void voodoo_half_triangle(voodoo_t *voodoo, voodoo_params_t *params, voodoo_state_t *state, int ystart, int yend, int odd_even) +static void +voodoo_half_triangle(voodoo_t *voodoo, voodoo_params_t *params, voodoo_state_t *state, int ystart, int yend, int odd_even) { -/* int rgb_sel = params->fbzColorPath & 3; - int a_sel = (params->fbzColorPath >> 2) & 3; - int cc_localselect = params->fbzColorPath & (1 << 4); - int cca_localselect = (params->fbzColorPath >> 5) & 3; - int cc_localselect_override = params->fbzColorPath & (1 << 7); - int cc_zero_other = params->fbzColorPath & (1 << 8); - int cc_sub_clocal = params->fbzColorPath & (1 << 9); - int cc_mselect = (params->fbzColorPath >> 10) & 7; - int cc_reverse_blend = params->fbzColorPath & (1 << 13); - int cc_add = (params->fbzColorPath >> 14) & 3; - int cc_add_alocal = params->fbzColorPath & (1 << 15); - int cc_invert_output = params->fbzColorPath & (1 << 16); - int cca_zero_other = params->fbzColorPath & (1 << 17); - int cca_sub_clocal = params->fbzColorPath & (1 << 18); - int cca_mselect = (params->fbzColorPath >> 19) & 7; - int cca_reverse_blend = params->fbzColorPath & (1 << 22); - int cca_add = (params->fbzColorPath >> 23) & 3; - int cca_invert_output = params->fbzColorPath & (1 << 25); - int src_afunc = (params->alphaMode >> 8) & 0xf; - int dest_afunc = (params->alphaMode >> 12) & 0xf; - int alpha_func = (params->alphaMode >> 1) & 7; - int a_ref = params->alphaMode >> 24; - int depth_op = (params->fbzMode >> 5) & 7; - int dither = params->fbzMode & FBZ_DITHER;*/ - int texels; - int c; -#ifndef NO_CODEGEN - uint8_t (*voodoo_draw)(voodoo_state_t *state, voodoo_params_t *params, int x, int real_y); +#if 0 + int rgb_sel = params->fbzColorPath & 3; + int a_sel = (params->fbzColorPath >> 2) & 3; + int cc_localselect = params->fbzColorPath & (1 << 4); + int cca_localselect = (params->fbzColorPath >> 5) & 3; + int cc_localselect_override = params->fbzColorPath & (1 << 7); + int cc_zero_other = params->fbzColorPath & (1 << 8); + int cc_sub_clocal = params->fbzColorPath & (1 << 9); + int cc_mselect = (params->fbzColorPath >> 10) & 7; + int cc_reverse_blend = params->fbzColorPath & (1 << 13); + int cc_add = (params->fbzColorPath >> 14) & 3; + int cc_add_alocal = params->fbzColorPath & (1 << 15); + int cc_invert_output = params->fbzColorPath & (1 << 16); + int cca_zero_other = params->fbzColorPath & (1 << 17); + int cca_sub_clocal = params->fbzColorPath & (1 << 18); + int cca_mselect = (params->fbzColorPath >> 19) & 7; + int cca_reverse_blend = params->fbzColorPath & (1 << 22); + int cca_add = (params->fbzColorPath >> 23) & 3; + int cca_invert_output = params->fbzColorPath & (1 << 25); + int src_afunc = (params->alphaMode >> 8) & 0xf; + int dest_afunc = (params->alphaMode >> 12) & 0xf; + int alpha_func = (params->alphaMode >> 1) & 7; + int a_ref = params->alphaMode >> 24; + int depth_op = (params->fbzMode >> 5) & 7; + int dither = params->fbzMode & FBZ_DITHER;*/ #endif - int y_diff = SLI_ENABLED ? 2 : 1; - int y_origin = (voodoo->type >= VOODOO_BANSHEE) ? voodoo->y_origin_swap : (voodoo->v_disp-1); + int texels; +#ifndef NO_CODEGEN + uint8_t (*voodoo_draw)(voodoo_state_t * state, voodoo_params_t * params, int x, int real_y); +#endif + int y_diff = SLI_ENABLED ? 2 : 1; + int y_origin = (voodoo->type >= VOODOO_BANSHEE) ? voodoo->y_origin_swap : (voodoo->v_disp - 1); - if ((params->textureMode[0] & TEXTUREMODE_MASK) == TEXTUREMODE_PASSTHROUGH || - (params->textureMode[0] & TEXTUREMODE_LOCAL_MASK) == TEXTUREMODE_LOCAL) - texels = 1; + if ((params->textureMode[0] & TEXTUREMODE_MASK) == TEXTUREMODE_PASSTHROUGH || (params->textureMode[0] & TEXTUREMODE_LOCAL_MASK) == TEXTUREMODE_LOCAL) + texels = 1; + else + texels = 2; + + state->clamp_s[0] = params->textureMode[0] & TEXTUREMODE_TCLAMPS; + state->clamp_t[0] = params->textureMode[0] & TEXTUREMODE_TCLAMPT; + state->clamp_s[1] = params->textureMode[1] & TEXTUREMODE_TCLAMPS; + state->clamp_t[1] = params->textureMode[1] & TEXTUREMODE_TCLAMPT; + // int last_x; + // voodoo_render_log("voodoo_triangle : bottom-half %X %X %X %X %X %i %i %i %i\n", xstart, xend, dx1, dx2, dx2 * 36, xdir, y, yend, ydir); + + for (uint8_t c = 0; c <= LOD_MAX; c++) { + state->tex[0][c] = &voodoo->texture_cache[0][params->tex_entry[0]].data[texture_offset[c]]; + state->tex[1][c] = &voodoo->texture_cache[1][params->tex_entry[1]].data[texture_offset[c]]; + } + + state->tformat = params->tformat[0]; + + state->tex_w_mask[0] = params->tex_w_mask[0]; + state->tex_h_mask[0] = params->tex_h_mask[0]; + state->tex_shift[0] = params->tex_shift[0]; + state->tex_lod[0] = params->tex_lod[0]; + state->tex_w_mask[1] = params->tex_w_mask[1]; + state->tex_h_mask[1] = params->tex_h_mask[1]; + state->tex_shift[1] = params->tex_shift[1]; + state->tex_lod[1] = params->tex_lod[1]; + + if ((params->fbzMode & 1) && (ystart < params->clipLowY)) { + int dy = params->clipLowY - ystart; + + state->base_r += params->dRdY * dy; + state->base_g += params->dGdY * dy; + state->base_b += params->dBdY * dy; + state->base_a += params->dAdY * dy; + state->base_z += params->dZdY * dy; + state->tmu[0].base_s += params->tmu[0].dSdY * dy; + state->tmu[0].base_t += params->tmu[0].dTdY * dy; + state->tmu[0].base_w += params->tmu[0].dWdY * dy; + state->tmu[1].base_s += params->tmu[1].dSdY * dy; + state->tmu[1].base_t += params->tmu[1].dTdY * dy; + state->tmu[1].base_w += params->tmu[1].dWdY * dy; + state->base_w += params->dWdY * dy; + state->xstart += state->dx1 * dy; + state->xend += state->dx2 * dy; + + ystart = params->clipLowY; + } + + if ((params->fbzMode & 1) && (yend >= params->clipHighY)) + yend = params->clipHighY; + + state->y = ystart; +#if 0 + yend--; +#endif + + if (SLI_ENABLED) { + int test_y; + + if (params->fbzMode & (1 << 17)) + test_y = y_origin - state->y; else - texels = 2; + test_y = state->y; - state->clamp_s[0] = params->textureMode[0] & TEXTUREMODE_TCLAMPS; - state->clamp_t[0] = params->textureMode[0] & TEXTUREMODE_TCLAMPT; - state->clamp_s[1] = params->textureMode[1] & TEXTUREMODE_TCLAMPS; - state->clamp_t[1] = params->textureMode[1] & TEXTUREMODE_TCLAMPT; -// int last_x; -// voodoo_render_log("voodoo_triangle : bottom-half %X %X %X %X %X %i %i %i %i\n", xstart, xend, dx1, dx2, dx2 * 36, xdir, y, yend, ydir); + if ((!(voodoo->initEnable & INITENABLE_SLI_MASTER_SLAVE) && (test_y & 1)) || ((voodoo->initEnable & INITENABLE_SLI_MASTER_SLAVE) && !(test_y & 1))) { + state->y++; - for (c = 0; c <= LOD_MAX; c++) - { - state->tex[0][c] = &voodoo->texture_cache[0][params->tex_entry[0]].data[texture_offset[c]]; - state->tex[1][c] = &voodoo->texture_cache[1][params->tex_entry[1]].data[texture_offset[c]]; - } - - state->tformat = params->tformat[0]; - - state->tex_w_mask[0] = params->tex_w_mask[0]; - state->tex_h_mask[0] = params->tex_h_mask[0]; - state->tex_shift[0] = params->tex_shift[0]; - state->tex_lod[0] = params->tex_lod[0]; - state->tex_w_mask[1] = params->tex_w_mask[1]; - state->tex_h_mask[1] = params->tex_h_mask[1]; - state->tex_shift[1] = params->tex_shift[1]; - state->tex_lod[1] = params->tex_lod[1]; - - if ((params->fbzMode & 1) && (ystart < params->clipLowY)) - { - int dy = params->clipLowY - ystart; - - state->base_r += params->dRdY*dy; - state->base_g += params->dGdY*dy; - state->base_b += params->dBdY*dy; - state->base_a += params->dAdY*dy; - state->base_z += params->dZdY*dy; - state->tmu[0].base_s += params->tmu[0].dSdY*dy; - state->tmu[0].base_t += params->tmu[0].dTdY*dy; - state->tmu[0].base_w += params->tmu[0].dWdY*dy; - state->tmu[1].base_s += params->tmu[1].dSdY*dy; - state->tmu[1].base_t += params->tmu[1].dTdY*dy; - state->tmu[1].base_w += params->tmu[1].dWdY*dy; - state->base_w += params->dWdY*dy; - state->xstart += state->dx1*dy; - state->xend += state->dx2*dy; - - ystart = params->clipLowY; - } - - if ((params->fbzMode & 1) && (yend >= params->clipHighY)) - yend = params->clipHighY; - - state->y = ystart; -// yend--; - - if (SLI_ENABLED) - { - int test_y; - - if (params->fbzMode & (1 << 17)) - test_y = y_origin - state->y; - else - test_y = state->y; - - if ((!(voodoo->initEnable & INITENABLE_SLI_MASTER_SLAVE) && (test_y & 1)) || - ((voodoo->initEnable & INITENABLE_SLI_MASTER_SLAVE) && !(test_y & 1))) - { - state->y++; - - state->base_r += params->dRdY; - state->base_g += params->dGdY; - state->base_b += params->dBdY; - state->base_a += params->dAdY; - state->base_z += params->dZdY; - state->tmu[0].base_s += params->tmu[0].dSdY; - state->tmu[0].base_t += params->tmu[0].dTdY; - state->tmu[0].base_w += params->tmu[0].dWdY; - state->tmu[1].base_s += params->tmu[1].dSdY; - state->tmu[1].base_t += params->tmu[1].dTdY; - state->tmu[1].base_w += params->tmu[1].dWdY; - state->base_w += params->dWdY; - state->xstart += state->dx1; - state->xend += state->dx2; - } + state->base_r += params->dRdY; + state->base_g += params->dGdY; + state->base_b += params->dBdY; + state->base_a += params->dAdY; + state->base_z += params->dZdY; + state->tmu[0].base_s += params->tmu[0].dSdY; + state->tmu[0].base_t += params->tmu[0].dTdY; + state->tmu[0].base_w += params->tmu[0].dWdY; + state->tmu[1].base_s += params->tmu[1].dSdY; + state->tmu[1].base_t += params->tmu[1].dTdY; + state->tmu[1].base_w += params->tmu[1].dWdY; + state->base_w += params->dWdY; + state->xstart += state->dx1; + state->xend += state->dx2; } + } #ifndef NO_CODEGEN - if (voodoo->use_recompiler) - voodoo_draw = voodoo_get_block(voodoo, params, state, odd_even); + if (voodoo->use_recompiler) + voodoo_draw = voodoo_get_block(voodoo, params, state, odd_even); + else + voodoo_draw = NULL; +#endif + + voodoo_render_log("dxAB=%08x dxBC=%08x dxAC=%08x\n", state->dxAB, state->dxBC, state->dxAC); +#if 0 + voodoo_render_log("Start %i %i\n", ystart, voodoo->fbzMode & (1 << 17)); +#endif + + for (; state->y < yend; state->y += y_diff) { + int x; + int x2; + int real_y = (state->y << 4) + 8; + int start_x; + int dx; + uint16_t *fb_mem; + uint16_t *aux_mem; + + state->ir = state->base_r; + state->ig = state->base_g; + state->ib = state->base_b; + state->ia = state->base_a; + state->z = state->base_z; + state->tmu0_s = state->tmu[0].base_s; + state->tmu0_t = state->tmu[0].base_t; + state->tmu0_w = state->tmu[0].base_w; + state->tmu1_s = state->tmu[1].base_s; + state->tmu1_t = state->tmu[1].base_t; + state->tmu1_w = state->tmu[1].base_w; + state->w = state->base_w; + + x = (state->vertexAx << 12) + ((state->dxAC * (real_y - state->vertexAy)) >> 4); + + if (real_y < state->vertexBy) + x2 = (state->vertexAx << 12) + ((state->dxAB * (real_y - state->vertexAy)) >> 4); else - voodoo_draw = NULL; -#endif + x2 = (state->vertexBx << 12) + ((state->dxBC * (real_y - state->vertexBy)) >> 4); - voodoo_render_log("dxAB=%08x dxBC=%08x dxAC=%08x\n", state->dxAB, state->dxBC, state->dxAC); -// voodoo_render_log("Start %i %i\n", ystart, voodoo->fbzMode & (1 << 17)); + if (params->fbzMode & (1 << 17)) + real_y = y_origin - (real_y >> 4); + else + real_y >>= 4; - for (; state->y < yend; state->y += y_diff) - { - int x, x2; - int real_y = (state->y << 4) + 8; - int start_x; - int dx; - uint16_t *fb_mem, *aux_mem; + if (SLI_ENABLED) { + if (((real_y >> 1) & voodoo->odd_even_mask) != odd_even) + goto next_line; + } else { + if ((real_y & voodoo->odd_even_mask) != odd_even) + goto next_line; + } - state->ir = state->base_r; - state->ig = state->base_g; - state->ib = state->base_b; - state->ia = state->base_a; - state->z = state->base_z; - state->tmu0_s = state->tmu[0].base_s; - state->tmu0_t = state->tmu[0].base_t; - state->tmu0_w = state->tmu[0].base_w; - state->tmu1_s = state->tmu[1].base_s; - state->tmu1_t = state->tmu[1].base_t; - state->tmu1_w = state->tmu[1].base_w; - state->w = state->base_w; + start_x = x; - x = (state->vertexAx << 12) + ((state->dxAC * (real_y - state->vertexAy)) >> 4); + if (state->xdir > 0) + x2 -= (1 << 16); + else + x -= (1 << 16); + dx = ((x + 0x7000) >> 16) - (((state->vertexAx << 12) + 0x7000) >> 16); + x = (x + 0x7000) >> 16; + x2 = (x2 + 0x7000) >> 16; - if (real_y < state->vertexBy) - x2 = (state->vertexAx << 12) + ((state->dxAB * (real_y - state->vertexAy)) >> 4); - else - x2 = (state->vertexBx << 12) + ((state->dxBC * (real_y - state->vertexBy)) >> 4); + voodoo_render_log("%03i:%03i : Ax=%08x start_x=%08x dSdX=%016llx dx=%08x s=%08x -> ", x, state->y, state->vertexAx << 8, start_x, params->tmu[0].dTdX, dx, state->tmu0_t); - if (params->fbzMode & (1 << 17)) - real_y = y_origin - (real_y >> 4); - else - real_y >>= 4; + state->ir += (params->dRdX * dx); + state->ig += (params->dGdX * dx); + state->ib += (params->dBdX * dx); + state->ia += (params->dAdX * dx); + state->z += (params->dZdX * dx); + state->tmu0_s += (params->tmu[0].dSdX * dx); + state->tmu0_t += (params->tmu[0].dTdX * dx); + state->tmu0_w += (params->tmu[0].dWdX * dx); + state->tmu1_s += (params->tmu[1].dSdX * dx); + state->tmu1_t += (params->tmu[1].dTdX * dx); + state->tmu1_w += (params->tmu[1].dWdX * dx); + state->w += (params->dWdX * dx); - if (SLI_ENABLED) - { - if (((real_y >> 1) & voodoo->odd_even_mask) != odd_even) - goto next_line; + voodoo_render_log("%08llx %lli %lli\n", state->tmu0_t, state->tmu0_t >> (18 + state->lod), (state->tmu0_t + (1 << (17 + state->lod))) >> (18 + state->lod)); + + if (params->fbzMode & 1) { + if (state->xdir > 0) { + if (x < params->clipLeft) { + int dx = params->clipLeft - x; + + state->ir += params->dRdX * dx; + state->ig += params->dGdX * dx; + state->ib += params->dBdX * dx; + state->ia += params->dAdX * dx; + state->z += params->dZdX * dx; + state->tmu0_s += params->tmu[0].dSdX * dx; + state->tmu0_t += params->tmu[0].dTdX * dx; + state->tmu0_w += params->tmu[0].dWdX * dx; + state->tmu1_s += params->tmu[1].dSdX * dx; + state->tmu1_t += params->tmu[1].dTdX * dx; + state->tmu1_w += params->tmu[1].dWdX * dx; + state->w += params->dWdX * dx; + + x = params->clipLeft; } - else - { - if ((real_y & voodoo->odd_even_mask) != odd_even) - goto next_line; + if (x2 >= params->clipRight) + x2 = params->clipRight - 1; + } else { + if (x >= params->clipRight) { + int dx = (params->clipRight - 1) - x; + + state->ir += params->dRdX * dx; + state->ig += params->dGdX * dx; + state->ib += params->dBdX * dx; + state->ia += params->dAdX * dx; + state->z += params->dZdX * dx; + state->tmu0_s += params->tmu[0].dSdX * dx; + state->tmu0_t += params->tmu[0].dTdX * dx; + state->tmu0_w += params->tmu[0].dWdX * dx; + state->tmu1_s += params->tmu[1].dSdX * dx; + state->tmu1_t += params->tmu[1].dTdX * dx; + state->tmu1_w += params->tmu[1].dWdX * dx; + state->w += params->dWdX * dx; + + x = params->clipRight - 1; } + if (x2 < params->clipLeft) + x2 = params->clipLeft; + } + } - start_x = x; + if (x2 < x && state->xdir > 0) + goto next_line; + if (x2 > x && state->xdir < 0) + goto next_line; - if (state->xdir > 0) - x2 -= (1 << 16); - else - x -= (1 << 16); - dx = ((x + 0x7000) >> 16) - (((state->vertexAx << 12) + 0x7000) >> 16); - x = (x + 0x7000) >> 16; - x2 = (x2 + 0x7000) >> 16; + if (SLI_ENABLED) { + state->fb_mem = fb_mem = (uint16_t *) &voodoo->fb_mem[params->draw_offset + ((real_y >> 1) * params->row_width)]; + state->aux_mem = aux_mem = (uint16_t *) &voodoo->fb_mem[(params->aux_offset + ((real_y >> 1) * params->row_width)) & voodoo->fb_mask]; + } else { + if (params->col_tiled) + state->fb_mem = fb_mem = (uint16_t *) &voodoo->fb_mem[params->draw_offset + (real_y >> 5) * params->row_width + (real_y & 31) * 128]; + else + state->fb_mem = fb_mem = (uint16_t *) &voodoo->fb_mem[params->draw_offset + (real_y * params->row_width)]; + if (params->aux_tiled) + state->aux_mem = aux_mem = (uint16_t *) &voodoo->fb_mem[(params->aux_offset + (real_y >> 5) * params->aux_row_width + (real_y & 31) * 128) & voodoo->fb_mask]; + else + state->aux_mem = aux_mem = (uint16_t *) &voodoo->fb_mem[(params->aux_offset + (real_y * params->row_width)) & voodoo->fb_mask]; + } - voodoo_render_log("%03i:%03i : Ax=%08x start_x=%08x dSdX=%016llx dx=%08x s=%08x -> ", x, state->y, state->vertexAx << 8, start_x, params->tmu[0].dTdX, dx, state->tmu0_t); + voodoo_render_log("%03i: x=%08x x2=%08x xstart=%08x xend=%08x dx=%08x\n", state->y, x, x2, state->xstart, state->xend, dx); - state->ir += (params->dRdX * dx); - state->ig += (params->dGdX * dx); - state->ib += (params->dBdX * dx); - state->ia += (params->dAdX * dx); - state->z += (params->dZdX * dx); - state->tmu0_s += (params->tmu[0].dSdX * dx); - state->tmu0_t += (params->tmu[0].dTdX * dx); - state->tmu0_w += (params->tmu[0].dWdX * dx); - state->tmu1_s += (params->tmu[1].dSdX * dx); - state->tmu1_t += (params->tmu[1].dTdX * dx); - state->tmu1_w += (params->tmu[1].dWdX * dx); - state->w += (params->dWdX * dx); - - voodoo_render_log("%08llx %lli %lli\n", state->tmu0_t, state->tmu0_t >> (18+state->lod), (state->tmu0_t + (1 << (17+state->lod))) >> (18+state->lod)); - - if (params->fbzMode & 1) - { - if (state->xdir > 0) - { - if (x < params->clipLeft) - { - int dx = params->clipLeft - x; - - state->ir += params->dRdX*dx; - state->ig += params->dGdX*dx; - state->ib += params->dBdX*dx; - state->ia += params->dAdX*dx; - state->z += params->dZdX*dx; - state->tmu0_s += params->tmu[0].dSdX*dx; - state->tmu0_t += params->tmu[0].dTdX*dx; - state->tmu0_w += params->tmu[0].dWdX*dx; - state->tmu1_s += params->tmu[1].dSdX*dx; - state->tmu1_t += params->tmu[1].dTdX*dx; - state->tmu1_w += params->tmu[1].dWdX*dx; - state->w += params->dWdX*dx; - - x = params->clipLeft; - } - if (x2 >= params->clipRight) - x2 = params->clipRight-1; - } - else - { - if (x >= params->clipRight) - { - int dx = (params->clipRight-1) - x; - - state->ir += params->dRdX*dx; - state->ig += params->dGdX*dx; - state->ib += params->dBdX*dx; - state->ia += params->dAdX*dx; - state->z += params->dZdX*dx; - state->tmu0_s += params->tmu[0].dSdX*dx; - state->tmu0_t += params->tmu[0].dTdX*dx; - state->tmu0_w += params->tmu[0].dWdX*dx; - state->tmu1_s += params->tmu[1].dSdX*dx; - state->tmu1_t += params->tmu[1].dTdX*dx; - state->tmu1_w += params->tmu[1].dWdX*dx; - state->w += params->dWdX*dx; - - x = params->clipRight-1; - } - if (x2 < params->clipLeft) - x2 = params->clipLeft; - } - } - - if (x2 < x && state->xdir > 0) - goto next_line; - if (x2 > x && state->xdir < 0) - goto next_line; - - if (SLI_ENABLED) - { - state->fb_mem = fb_mem = (uint16_t *)&voodoo->fb_mem[params->draw_offset + ((real_y >> 1) * params->row_width)]; - state->aux_mem = aux_mem = (uint16_t *)&voodoo->fb_mem[(params->aux_offset + ((real_y >> 1) * params->row_width)) & voodoo->fb_mask]; - } - else - { - if (params->col_tiled) - state->fb_mem = fb_mem = (uint16_t *)&voodoo->fb_mem[params->draw_offset + (real_y >> 5) * params->row_width + (real_y & 31) * 128]; - else - state->fb_mem = fb_mem = (uint16_t *)&voodoo->fb_mem[params->draw_offset + (real_y * params->row_width)]; - if (params->aux_tiled) - state->aux_mem = aux_mem = (uint16_t *)&voodoo->fb_mem[(params->aux_offset + (real_y >> 5) * params->aux_row_width + (real_y & 31) * 128) & voodoo->fb_mask]; - else - state->aux_mem = aux_mem = (uint16_t *)&voodoo->fb_mem[(params->aux_offset + (real_y * params->row_width)) & voodoo->fb_mask]; - } - - voodoo_render_log("%03i: x=%08x x2=%08x xstart=%08x xend=%08x dx=%08x\n", state->y, x, x2, state->xstart, state->xend, dx); - - state->pixel_count = 0; - state->texel_count = 0; - state->x = x; - state->x2 = x2; + state->pixel_count = 0; + state->texel_count = 0; + state->x = x; + state->x2 = x2; #ifndef NO_CODEGEN - if (voodoo->use_recompiler) - { - voodoo_draw(state, params, x, real_y); - } - else + if (voodoo->use_recompiler) { + voodoo_draw(state, params, x, real_y); + } else +#endif + do { + int x_tiled = (x & 63) | ((x >> 6) * 128 * 32 / 2); + start_x = x; + state->x = x; + voodoo->pixel_count[odd_even]++; + voodoo->texel_count[odd_even] += texels; + voodoo->fbiPixelsIn++; + + voodoo_render_log(" X=%03i T=%08x\n", x, state->tmu0_t); +#if 0 + if (voodoo->fbzMode & FBZ_RGB_WMASK) #endif - do { - int x_tiled = (x & 63) | ((x >> 6) * 128*32/2); - start_x = x; - state->x = x; - voodoo->pixel_count[odd_even]++; - voodoo->texel_count[odd_even] += texels; - voodoo->fbiPixelsIn++; + int update = 1; + uint8_t cother_r = 0; + uint8_t cother_g = 0; + uint8_t cother_b = 0; + uint8_t aother; + uint8_t clocal_r; + uint8_t clocal_g; + uint8_t clocal_b; + uint8_t alocal; + int src_r = 0; + int src_g = 0; + int src_b = 0; + int src_a = 0; + int msel_r; + int msel_g; + int msel_b; + int msel_a; + uint8_t dest_r; + uint8_t dest_g; + uint8_t dest_b; + uint8_t dest_a; + uint16_t dat; + int sel; + int32_t new_depth; + int32_t w_depth; - voodoo_render_log(" X=%03i T=%08x\n", x, state->tmu0_t); -// if (voodoo->fbzMode & FBZ_RGB_WMASK) - { - int update = 1; - uint8_t cother_r = 0, cother_g = 0, cother_b = 0, aother; - uint8_t clocal_r, clocal_g, clocal_b, alocal; - int src_r = 0, src_g = 0, src_b = 0, src_a = 0; - int msel_r, msel_g, msel_b, msel_a; - uint8_t dest_r, dest_g, dest_b, dest_a; - uint16_t dat; - int sel; - int32_t new_depth, w_depth; + if (state->w & 0xffff00000000) + w_depth = 0; + else if (!(state->w & 0xffff0000)) + w_depth = 0xf001; + else { + int exp = voodoo_fls((uint16_t) ((uint32_t) state->w >> 16)); + int mant = (~(uint32_t) state->w >> (19 - exp)) & 0xfff; + w_depth = (exp << 12) + mant + 1; + if (w_depth > 0xffff) + w_depth = 0xffff; + } - if (state->w & 0xffff00000000) - w_depth = 0; - else if (!(state->w & 0xffff0000)) - w_depth = 0xf001; - else - { - int exp = voodoo_fls((uint16_t)((uint32_t)state->w >> 16)); - int mant = ((~(uint32_t)state->w >> (19 - exp))) & 0xfff; - w_depth = (exp << 12) + mant + 1; - if (w_depth > 0xffff) - w_depth = 0xffff; - } +#if 0 + w_depth = CLAMP16(w_depth); +#endif -// w_depth = CLAMP16(w_depth); + if (params->fbzMode & FBZ_W_BUFFER) + new_depth = w_depth; + else + new_depth = CLAMP16(state->z >> 12); - if (params->fbzMode & FBZ_W_BUFFER) - new_depth = w_depth; - else - new_depth = CLAMP16(state->z >> 12); + if (params->fbzMode & FBZ_DEPTH_BIAS) + new_depth = CLAMP16(new_depth + (int16_t) params->zaColor); - if (params->fbzMode & FBZ_DEPTH_BIAS) - new_depth = CLAMP16(new_depth + (int16_t)params->zaColor); + if (params->fbzMode & FBZ_DEPTH_ENABLE) { + uint16_t old_depth = voodoo->params.aux_tiled ? aux_mem[x_tiled] : aux_mem[x]; - if (params->fbzMode & FBZ_DEPTH_ENABLE) - { - uint16_t old_depth = voodoo->params.aux_tiled ? aux_mem[x_tiled] : aux_mem[x]; + DEPTH_TEST((params->fbzMode & FBZ_DEPTH_SOURCE) ? (params->zaColor & 0xffff) : new_depth); + } - DEPTH_TEST((params->fbzMode & FBZ_DEPTH_SOURCE) ? (params->zaColor & 0xffff) : new_depth); - } + dat = voodoo->params.col_tiled ? fb_mem[x_tiled] : fb_mem[x]; + dest_r = (dat >> 8) & 0xf8; + dest_g = (dat >> 3) & 0xfc; + dest_b = (dat << 3) & 0xf8; + dest_r |= (dest_r >> 5); + dest_g |= (dest_g >> 6); + dest_b |= (dest_b >> 5); + dest_a = 0xff; - dat = voodoo->params.col_tiled ? fb_mem[x_tiled] : fb_mem[x]; - dest_r = (dat >> 8) & 0xf8; - dest_g = (dat >> 3) & 0xfc; - dest_b = (dat << 3) & 0xf8; - dest_r |= (dest_r >> 5); - dest_g |= (dest_g >> 6); - dest_b |= (dest_b >> 5); - dest_a = 0xff; + if (params->fbzColorPath & FBZCP_TEXTURE_ENABLED) { + if ((params->textureMode[0] & TEXTUREMODE_LOCAL_MASK) == TEXTUREMODE_LOCAL || !voodoo->dual_tmus) { + /*TMU0 only sampling local colour or only one TMU, only sample TMU0*/ + voodoo_tmu_fetch(voodoo, params, state, 0, x); + } else if ((params->textureMode[0] & TEXTUREMODE_MASK) == TEXTUREMODE_PASSTHROUGH) { + /*TMU0 in pass-through mode, only sample TMU1*/ + voodoo_tmu_fetch(voodoo, params, state, 1, x); - if (params->fbzColorPath & FBZCP_TEXTURE_ENABLED) - { - if ((params->textureMode[0] & TEXTUREMODE_LOCAL_MASK) == TEXTUREMODE_LOCAL || !voodoo->dual_tmus) - { - /*TMU0 only sampling local colour or only one TMU, only sample TMU0*/ - voodoo_tmu_fetch(voodoo, params, state, 0, x); - } - else if ((params->textureMode[0] & TEXTUREMODE_MASK) == TEXTUREMODE_PASSTHROUGH) - { - /*TMU0 in pass-through mode, only sample TMU1*/ - voodoo_tmu_fetch(voodoo, params, state, 1, x); - - state->tex_r[0] = state->tex_r[1]; - state->tex_g[0] = state->tex_g[1]; - state->tex_b[0] = state->tex_b[1]; - state->tex_a[0] = state->tex_a[1]; - } - else - { - voodoo_tmu_fetch_and_blend(voodoo, params, state, x); - } - - if ((params->fbzMode & FBZ_CHROMAKEY) && - state->tex_r[0] == params->chromaKey_r && - state->tex_g[0] == params->chromaKey_g && - state->tex_b[0] == params->chromaKey_b) - { - voodoo->fbiChromaFail++; - goto skip_pixel; - } - } - - if (voodoo->trexInit1[0] & (1 << 18)) - { - state->tex_r[0] = state->tex_g[0] = 0; - state->tex_b[0] = voodoo->tmuConfig; - } - - if (cc_localselect_override) - sel = (state->tex_a[0] & 0x80) ? 1 : 0; - else - sel = cc_localselect; - - if (sel) - { - clocal_r = (params->color0 >> 16) & 0xff; - clocal_g = (params->color0 >> 8) & 0xff; - clocal_b = params->color0 & 0xff; - } - else - { - clocal_r = CLAMP(state->ir >> 12); - clocal_g = CLAMP(state->ig >> 12); - clocal_b = CLAMP(state->ib >> 12); - } - - switch (_rgb_sel) - { - case CC_LOCALSELECT_ITER_RGB: /*Iterated RGB*/ - cother_r = CLAMP(state->ir >> 12); - cother_g = CLAMP(state->ig >> 12); - cother_b = CLAMP(state->ib >> 12); - break; - - case CC_LOCALSELECT_TEX: /*TREX Color Output*/ - cother_r = state->tex_r[0]; - cother_g = state->tex_g[0]; - cother_b = state->tex_b[0]; - break; - - case CC_LOCALSELECT_COLOR1: /*Color1 RGB*/ - cother_r = (params->color1 >> 16) & 0xff; - cother_g = (params->color1 >> 8) & 0xff; - cother_b = params->color1 & 0xff; - break; - - case CC_LOCALSELECT_LFB: /*Linear Frame Buffer*/ - cother_r = src_r; - cother_g = src_g; - cother_b = src_b; - break; - } - - switch (cca_localselect) - { - case CCA_LOCALSELECT_ITER_A: - alocal = CLAMP(state->ia >> 12); - break; - - case CCA_LOCALSELECT_COLOR0: - alocal = (params->color0 >> 24) & 0xff; - break; - - case CCA_LOCALSELECT_ITER_Z: - alocal = CLAMP(state->z >> 20); - break; - - default: - fatal("Bad cca_localselect %i\n", cca_localselect); - alocal = 0xff; - break; - } - - switch (a_sel) - { - case A_SEL_ITER_A: - aother = CLAMP(state->ia >> 12); - break; - case A_SEL_TEX: - aother = state->tex_a[0]; - break; - case A_SEL_COLOR1: - aother = (params->color1 >> 24) & 0xff; - break; - default: - fatal("Bad a_sel %i\n", a_sel); - aother = 0; - break; - } - - if (cc_zero_other) - { - src_r = 0; - src_g = 0; - src_b = 0; - } - else - { - src_r = cother_r; - src_g = cother_g; - src_b = cother_b; - } - - if (cca_zero_other) - src_a = 0; - else - src_a = aother; - - if (cc_sub_clocal) - { - src_r -= clocal_r; - src_g -= clocal_g; - src_b -= clocal_b; - } - - if (cca_sub_clocal) - src_a -= alocal; - - switch (cc_mselect) - { - case CC_MSELECT_ZERO: - msel_r = 0; - msel_g = 0; - msel_b = 0; - break; - case CC_MSELECT_CLOCAL: - msel_r = clocal_r; - msel_g = clocal_g; - msel_b = clocal_b; - break; - case CC_MSELECT_AOTHER: - msel_r = aother; - msel_g = aother; - msel_b = aother; - break; - case CC_MSELECT_ALOCAL: - msel_r = alocal; - msel_g = alocal; - msel_b = alocal; - break; - case CC_MSELECT_TEX: - msel_r = state->tex_a[0]; - msel_g = state->tex_a[0]; - msel_b = state->tex_a[0]; - break; - case CC_MSELECT_TEXRGB: - msel_r = state->tex_r[0]; - msel_g = state->tex_g[0]; - msel_b = state->tex_b[0]; - break; - - default: - fatal("Bad cc_mselect %i\n", cc_mselect); - msel_r = 0; - msel_g = 0; - msel_b = 0; - break; - } - - switch (cca_mselect) - { - case CCA_MSELECT_ZERO: - msel_a = 0; - break; - case CCA_MSELECT_ALOCAL: - msel_a = alocal; - break; - case CCA_MSELECT_AOTHER: - msel_a = aother; - break; - case CCA_MSELECT_ALOCAL2: - msel_a = alocal; - break; - case CCA_MSELECT_TEX: - msel_a = state->tex_a[0]; - break; - - default: - fatal("Bad cca_mselect %i\n", cca_mselect); - msel_a = 0; - break; - } - - if (!cc_reverse_blend) - { - msel_r ^= 0xff; - msel_g ^= 0xff; - msel_b ^= 0xff; - } - msel_r++; - msel_g++; - msel_b++; - - if (!cca_reverse_blend) - msel_a ^= 0xff; - msel_a++; - - src_r = (src_r * msel_r) >> 8; - src_g = (src_g * msel_g) >> 8; - src_b = (src_b * msel_b) >> 8; - src_a = (src_a * msel_a) >> 8; - - switch (cc_add) - { - case CC_ADD_CLOCAL: - src_r += clocal_r; - src_g += clocal_g; - src_b += clocal_b; - break; - case CC_ADD_ALOCAL: - src_r += alocal; - src_g += alocal; - src_b += alocal; - break; - case 0: - break; - default: - fatal("Bad cc_add %i\n", cc_add); - } - - if (cca_add) - src_a += alocal; - - src_r = CLAMP(src_r); - src_g = CLAMP(src_g); - src_b = CLAMP(src_b); - src_a = CLAMP(src_a); - - if (cc_invert_output) - { - src_r ^= 0xff; - src_g ^= 0xff; - src_b ^= 0xff; - } - if (cca_invert_output) - src_a ^= 0xff; - - if (params->fogMode & FOG_ENABLE) - APPLY_FOG(src_r, src_g, src_b, state->z, state->ia, state->w); - - if (params->alphaMode & 1) - ALPHA_TEST(src_a); - - if (params->alphaMode & (1 << 4)) { - if (dithersub && !dither2x2 && voodoo->dithersub_enabled) - { - dest_r = dithersub_rb[dest_r][real_y & 3][x & 3]; - dest_g = dithersub_g [dest_g][real_y & 3][x & 3]; - dest_b = dithersub_rb[dest_b][real_y & 3][x & 3]; - } - if (dithersub && dither2x2 && voodoo->dithersub_enabled) - { - dest_r = dithersub_rb2x2[dest_r][real_y & 1][x & 1]; - dest_g = dithersub_g2x2 [dest_g][real_y & 1][x & 1]; - dest_b = dithersub_rb2x2[dest_b][real_y & 1][x & 1]; - } - ALPHA_BLEND(src_r, src_g, src_b, src_a); - } - - if (update) - { - if (dither) - { - if (dither2x2) - { - src_r = dither_rb2x2[src_r][real_y & 1][x & 1]; - src_g = dither_g2x2[src_g][real_y & 1][x & 1]; - src_b = dither_rb2x2[src_b][real_y & 1][x & 1]; - } - else - { - src_r = dither_rb[src_r][real_y & 3][x & 3]; - src_g = dither_g[src_g][real_y & 3][x & 3]; - src_b = dither_rb[src_b][real_y & 3][x & 3]; - } - } - else - { - src_r >>= 3; - src_g >>= 2; - src_b >>= 3; - } - - if (params->fbzMode & FBZ_RGB_WMASK) - { - if (voodoo->params.col_tiled) - fb_mem[x_tiled] = src_b | (src_g << 5) | (src_r << 11); - else - fb_mem[x] = src_b | (src_g << 5) | (src_r << 11); - } - if ((params->fbzMode & (FBZ_DEPTH_WMASK | FBZ_DEPTH_ENABLE)) == (FBZ_DEPTH_WMASK | FBZ_DEPTH_ENABLE)) - { - if (voodoo->params.aux_tiled) - aux_mem[x_tiled] = new_depth; - else - aux_mem[x] = new_depth; - } - } + state->tex_r[0] = state->tex_r[1]; + state->tex_g[0] = state->tex_g[1]; + state->tex_b[0] = state->tex_b[1]; + state->tex_a[0] = state->tex_a[1]; + } else { + voodoo_tmu_fetch_and_blend(voodoo, params, state, x); } - voodoo->fbiPixelsOut++; + + if ((params->fbzMode & FBZ_CHROMAKEY) && state->tex_r[0] == params->chromaKey_r && state->tex_g[0] == params->chromaKey_g && state->tex_b[0] == params->chromaKey_b) { + voodoo->fbiChromaFail++; + goto skip_pixel; + } + } + + if (voodoo->trexInit1[0] & (1 << 18)) { + state->tex_r[0] = state->tex_g[0] = 0; + state->tex_b[0] = voodoo->tmuConfig; + } + + if (cc_localselect_override) + sel = (state->tex_a[0] & 0x80) ? 1 : 0; + else + sel = cc_localselect; + + if (sel) { + clocal_r = (params->color0 >> 16) & 0xff; + clocal_g = (params->color0 >> 8) & 0xff; + clocal_b = params->color0 & 0xff; + } else { + clocal_r = CLAMP(state->ir >> 12); + clocal_g = CLAMP(state->ig >> 12); + clocal_b = CLAMP(state->ib >> 12); + } + + switch (_rgb_sel) { + case CC_LOCALSELECT_ITER_RGB: /*Iterated RGB*/ + cother_r = CLAMP(state->ir >> 12); + cother_g = CLAMP(state->ig >> 12); + cother_b = CLAMP(state->ib >> 12); + break; + + case CC_LOCALSELECT_TEX: /*TREX Color Output*/ + cother_r = state->tex_r[0]; + cother_g = state->tex_g[0]; + cother_b = state->tex_b[0]; + break; + + case CC_LOCALSELECT_COLOR1: /*Color1 RGB*/ + cother_r = (params->color1 >> 16) & 0xff; + cother_g = (params->color1 >> 8) & 0xff; + cother_b = params->color1 & 0xff; + break; + + case CC_LOCALSELECT_LFB: /*Linear Frame Buffer*/ + cother_r = src_r; + cother_g = src_g; + cother_b = src_b; + break; + + default: + break; + } + + switch (cca_localselect) { + case CCA_LOCALSELECT_ITER_A: + alocal = CLAMP(state->ia >> 12); + break; + + case CCA_LOCALSELECT_COLOR0: + alocal = (params->color0 >> 24) & 0xff; + break; + + case CCA_LOCALSELECT_ITER_Z: + alocal = CLAMP(state->z >> 20); + break; + + default: + fatal("Bad cca_localselect %i\n", cca_localselect); + alocal = 0xff; + break; + } + + switch (a_sel) { + case A_SEL_ITER_A: + aother = CLAMP(state->ia >> 12); + break; + case A_SEL_TEX: + aother = state->tex_a[0]; + break; + case A_SEL_COLOR1: + aother = (params->color1 >> 24) & 0xff; + break; + default: + fatal("Bad a_sel %i\n", a_sel); + aother = 0; + break; + } + + if (cc_zero_other) { + src_r = 0; + src_g = 0; + src_b = 0; + } else { + src_r = cother_r; + src_g = cother_g; + src_b = cother_b; + } + + if (cca_zero_other) + src_a = 0; + else + src_a = aother; + + if (cc_sub_clocal) { + src_r -= clocal_r; + src_g -= clocal_g; + src_b -= clocal_b; + } + + if (cca_sub_clocal) + src_a -= alocal; + + switch (cc_mselect) { + case CC_MSELECT_ZERO: + msel_r = 0; + msel_g = 0; + msel_b = 0; + break; + case CC_MSELECT_CLOCAL: + msel_r = clocal_r; + msel_g = clocal_g; + msel_b = clocal_b; + break; + case CC_MSELECT_AOTHER: + msel_r = aother; + msel_g = aother; + msel_b = aother; + break; + case CC_MSELECT_ALOCAL: + msel_r = alocal; + msel_g = alocal; + msel_b = alocal; + break; + case CC_MSELECT_TEX: + msel_r = state->tex_a[0]; + msel_g = state->tex_a[0]; + msel_b = state->tex_a[0]; + break; + case CC_MSELECT_TEXRGB: + msel_r = state->tex_r[0]; + msel_g = state->tex_g[0]; + msel_b = state->tex_b[0]; + break; + + default: + fatal("Bad cc_mselect %i\n", cc_mselect); + msel_r = 0; + msel_g = 0; + msel_b = 0; + break; + } + + switch (cca_mselect) { + case CCA_MSELECT_ZERO: + msel_a = 0; + break; + case CCA_MSELECT_ALOCAL: + msel_a = alocal; + break; + case CCA_MSELECT_AOTHER: + msel_a = aother; + break; + case CCA_MSELECT_ALOCAL2: + msel_a = alocal; + break; + case CCA_MSELECT_TEX: + msel_a = state->tex_a[0]; + break; + + default: + fatal("Bad cca_mselect %i\n", cca_mselect); + msel_a = 0; + break; + } + + if (!cc_reverse_blend) { + msel_r ^= 0xff; + msel_g ^= 0xff; + msel_b ^= 0xff; + } + msel_r++; + msel_g++; + msel_b++; + + if (!cca_reverse_blend) + msel_a ^= 0xff; + msel_a++; + + src_r = (src_r * msel_r) >> 8; + src_g = (src_g * msel_g) >> 8; + src_b = (src_b * msel_b) >> 8; + src_a = (src_a * msel_a) >> 8; + + switch (cc_add) { + case CC_ADD_CLOCAL: + src_r += clocal_r; + src_g += clocal_g; + src_b += clocal_b; + break; + case CC_ADD_ALOCAL: + src_r += alocal; + src_g += alocal; + src_b += alocal; + break; + case 0: + break; + default: + fatal("Bad cc_add %i\n", cc_add); + } + + if (cca_add) + src_a += alocal; + + src_r = CLAMP(src_r); + src_g = CLAMP(src_g); + src_b = CLAMP(src_b); + src_a = CLAMP(src_a); + + if (cc_invert_output) { + src_r ^= 0xff; + src_g ^= 0xff; + src_b ^= 0xff; + } + if (cca_invert_output) + src_a ^= 0xff; + + if (params->fogMode & FOG_ENABLE) + APPLY_FOG(src_r, src_g, src_b, state->z, state->ia, state->w); + + if (params->alphaMode & 1) + ALPHA_TEST(src_a); + + if (params->alphaMode & (1 << 4)) { + if (dithersub && !dither2x2 && voodoo->dithersub_enabled) { + dest_r = dithersub_rb[dest_r][real_y & 3][x & 3]; + dest_g = dithersub_g[dest_g][real_y & 3][x & 3]; + dest_b = dithersub_rb[dest_b][real_y & 3][x & 3]; + } + if (dithersub && dither2x2 && voodoo->dithersub_enabled) { + dest_r = dithersub_rb2x2[dest_r][real_y & 1][x & 1]; + dest_g = dithersub_g2x2[dest_g][real_y & 1][x & 1]; + dest_b = dithersub_rb2x2[dest_b][real_y & 1][x & 1]; + } + ALPHA_BLEND(src_r, src_g, src_b, src_a); + } + + if (update) { + if (dither) { + if (dither2x2) { + src_r = dither_rb2x2[src_r][real_y & 1][x & 1]; + src_g = dither_g2x2[src_g][real_y & 1][x & 1]; + src_b = dither_rb2x2[src_b][real_y & 1][x & 1]; + } else { + src_r = dither_rb[src_r][real_y & 3][x & 3]; + src_g = dither_g[src_g][real_y & 3][x & 3]; + src_b = dither_rb[src_b][real_y & 3][x & 3]; + } + } else { + src_r >>= 3; + src_g >>= 2; + src_b >>= 3; + } + + if (params->fbzMode & FBZ_RGB_WMASK) { + if (voodoo->params.col_tiled) + fb_mem[x_tiled] = src_b | (src_g << 5) | (src_r << 11); + else + fb_mem[x] = src_b | (src_g << 5) | (src_r << 11); + } + if ((params->fbzMode & (FBZ_DEPTH_WMASK | FBZ_DEPTH_ENABLE)) == (FBZ_DEPTH_WMASK | FBZ_DEPTH_ENABLE)) { + if (voodoo->params.aux_tiled) + aux_mem[x_tiled] = new_depth; + else + aux_mem[x] = new_depth; + } + } + } + voodoo->fbiPixelsOut++; skip_pixel: - if (state->xdir > 0) - { - state->ir += params->dRdX; - state->ig += params->dGdX; - state->ib += params->dBdX; - state->ia += params->dAdX; - state->z += params->dZdX; - state->tmu0_s += params->tmu[0].dSdX; - state->tmu0_t += params->tmu[0].dTdX; - state->tmu0_w += params->tmu[0].dWdX; - state->tmu1_s += params->tmu[1].dSdX; - state->tmu1_t += params->tmu[1].dTdX; - state->tmu1_w += params->tmu[1].dWdX; - state->w += params->dWdX; - } - else - { - state->ir -= params->dRdX; - state->ig -= params->dGdX; - state->ib -= params->dBdX; - state->ia -= params->dAdX; - state->z -= params->dZdX; - state->tmu0_s -= params->tmu[0].dSdX; - state->tmu0_t -= params->tmu[0].dTdX; - state->tmu0_w -= params->tmu[0].dWdX; - state->tmu1_s -= params->tmu[1].dSdX; - state->tmu1_t -= params->tmu[1].dTdX; - state->tmu1_w -= params->tmu[1].dWdX; - state->w -= params->dWdX; - } + if (state->xdir > 0) { + state->ir += params->dRdX; + state->ig += params->dGdX; + state->ib += params->dBdX; + state->ia += params->dAdX; + state->z += params->dZdX; + state->tmu0_s += params->tmu[0].dSdX; + state->tmu0_t += params->tmu[0].dTdX; + state->tmu0_w += params->tmu[0].dWdX; + state->tmu1_s += params->tmu[1].dSdX; + state->tmu1_t += params->tmu[1].dTdX; + state->tmu1_w += params->tmu[1].dWdX; + state->w += params->dWdX; + } else { + state->ir -= params->dRdX; + state->ig -= params->dGdX; + state->ib -= params->dBdX; + state->ia -= params->dAdX; + state->z -= params->dZdX; + state->tmu0_s -= params->tmu[0].dSdX; + state->tmu0_t -= params->tmu[0].dTdX; + state->tmu0_w -= params->tmu[0].dWdX; + state->tmu1_s -= params->tmu[1].dSdX; + state->tmu1_t -= params->tmu[1].dTdX; + state->tmu1_w -= params->tmu[1].dWdX; + state->w -= params->dWdX; + } - x += state->xdir; - } while (start_x != x2); + x += state->xdir; + } while (start_x != x2); - voodoo->pixel_count[odd_even] += state->pixel_count; - voodoo->texel_count[odd_even] += state->texel_count; - voodoo->fbiPixelsIn += state->pixel_count; + voodoo->pixel_count[odd_even] += state->pixel_count; + voodoo->texel_count[odd_even] += state->texel_count; + voodoo->fbiPixelsIn += state->pixel_count; - if (voodoo->params.draw_offset == voodoo->params.front_offset && (real_y >> 1) < 2048) - voodoo->dirty_line[real_y >> 1] = 1; + if (voodoo->params.draw_offset == voodoo->params.front_offset && (real_y >> 1) < 2048) + voodoo->dirty_line[real_y >> 1] = 1; next_line: - if (SLI_ENABLED) - { - state->base_r += params->dRdY; - state->base_g += params->dGdY; - state->base_b += params->dBdY; - state->base_a += params->dAdY; - state->base_z += params->dZdY; - state->tmu[0].base_s += params->tmu[0].dSdY; - state->tmu[0].base_t += params->tmu[0].dTdY; - state->tmu[0].base_w += params->tmu[0].dWdY; - state->tmu[1].base_s += params->tmu[1].dSdY; - state->tmu[1].base_t += params->tmu[1].dTdY; - state->tmu[1].base_w += params->tmu[1].dWdY; - state->base_w += params->dWdY; - state->xstart += state->dx1; - state->xend += state->dx2; - } - state->base_r += params->dRdY; - state->base_g += params->dGdY; - state->base_b += params->dBdY; - state->base_a += params->dAdY; - state->base_z += params->dZdY; - state->tmu[0].base_s += params->tmu[0].dSdY; - state->tmu[0].base_t += params->tmu[0].dTdY; - state->tmu[0].base_w += params->tmu[0].dWdY; - state->tmu[1].base_s += params->tmu[1].dSdY; - state->tmu[1].base_t += params->tmu[1].dTdY; - state->tmu[1].base_w += params->tmu[1].dWdY; - state->base_w += params->dWdY; - state->xstart += state->dx1; - state->xend += state->dx2; + if (SLI_ENABLED) { + state->base_r += params->dRdY; + state->base_g += params->dGdY; + state->base_b += params->dBdY; + state->base_a += params->dAdY; + state->base_z += params->dZdY; + state->tmu[0].base_s += params->tmu[0].dSdY; + state->tmu[0].base_t += params->tmu[0].dTdY; + state->tmu[0].base_w += params->tmu[0].dWdY; + state->tmu[1].base_s += params->tmu[1].dSdY; + state->tmu[1].base_t += params->tmu[1].dTdY; + state->tmu[1].base_w += params->tmu[1].dWdY; + state->base_w += params->dWdY; + state->xstart += state->dx1; + state->xend += state->dx2; } + state->base_r += params->dRdY; + state->base_g += params->dGdY; + state->base_b += params->dBdY; + state->base_a += params->dAdY; + state->base_z += params->dZdY; + state->tmu[0].base_s += params->tmu[0].dSdY; + state->tmu[0].base_t += params->tmu[0].dTdY; + state->tmu[0].base_w += params->tmu[0].dWdY; + state->tmu[1].base_s += params->tmu[1].dSdY; + state->tmu[1].base_t += params->tmu[1].dTdY; + state->tmu[1].base_w += params->tmu[1].dWdY; + state->base_w += params->dWdY; + state->xstart += state->dx1; + state->xend += state->dx2; + } - voodoo->texture_cache[0][params->tex_entry[0]].refcount_r[odd_even]++; - voodoo->texture_cache[1][params->tex_entry[1]].refcount_r[odd_even]++; + voodoo->texture_cache[0][params->tex_entry[0]].refcount_r[odd_even]++; + voodoo->texture_cache[1][params->tex_entry[1]].refcount_r[odd_even]++; } -void voodoo_triangle(voodoo_t *voodoo, voodoo_params_t *params, int odd_even) +void +voodoo_triangle(voodoo_t *voodoo, voodoo_params_t *params, int odd_even) { - voodoo_state_t state; - int vertexAy_adjusted; - int vertexCy_adjusted; - int dx, dy; + voodoo_state_t state; + int vertexAy_adjusted; + int vertexCy_adjusted; + int dx; + int dy; - uint64_t tempdx, tempdy; - uint64_t tempLOD; - int LOD; - int lodbias; + uint64_t tempdx; + uint64_t tempdy; + uint64_t tempLOD; + int LOD; + int lodbias; - voodoo->tri_count++; + voodoo->tri_count++; - dx = 8 - (params->vertexAx & 0xf); - if ((params->vertexAx & 0xf) > 8) - dx += 16; - dy = 8 - (params->vertexAy & 0xf); - if ((params->vertexAy & 0xf) > 8) - dy += 16; + dx = 8 - (params->vertexAx & 0xf); + if ((params->vertexAx & 0xf) > 8) + dx += 16; + dy = 8 - (params->vertexAy & 0xf); + if ((params->vertexAy & 0xf) > 8) + dy += 16; -/* voodoo_render_log("voodoo_triangle %i %i %i : vA %f, %f vB %f, %f vC %f, %f f %i,%i %08x %08x %08x,%08x tex=%i,%i fogMode=%08x\n", odd_even, voodoo->params_read_idx[odd_even], voodoo->params_read_idx[odd_even] & PARAM_MASK, (float)params->vertexAx / 16.0, (float)params->vertexAy / 16.0, - (float)params->vertexBx / 16.0, (float)params->vertexBy / 16.0, - (float)params->vertexCx / 16.0, (float)params->vertexCy / 16.0, - (params->fbzColorPath & FBZCP_TEXTURE_ENABLED) ? params->tformat[0] : 0, - (params->fbzColorPath & FBZCP_TEXTURE_ENABLED) ? params->tformat[1] : 0, params->fbzColorPath, params->alphaMode, params->textureMode[0],params->textureMode[1], params->tex_entry[0],params->tex_entry[1], params->fogMode);*/ + /* voodoo_render_log("voodoo_triangle %i %i %i : vA %f, %f vB %f, %f vC %f, %f f %i,%i %08x %08x %08x,%08x tex=%i,%i fogMode=%08x\n", odd_even, voodoo->params_read_idx[odd_even], voodoo->params_read_idx[odd_even] & PARAM_MASK, (float)params->vertexAx / 16.0, (float)params->vertexAy / 16.0, + (float)params->vertexBx / 16.0, (float)params->vertexBy / 16.0, + (float)params->vertexCx / 16.0, (float)params->vertexCy / 16.0, + (params->fbzColorPath & FBZCP_TEXTURE_ENABLED) ? params->tformat[0] : 0, + (params->fbzColorPath & FBZCP_TEXTURE_ENABLED) ? params->tformat[1] : 0, params->fbzColorPath, params->alphaMode, params->textureMode[0],params->textureMode[1], params->tex_entry[0],params->tex_entry[1], params->fogMode);*/ - state.base_r = params->startR; - state.base_g = params->startG; - state.base_b = params->startB; - state.base_a = params->startA; - state.base_z = params->startZ; - state.tmu[0].base_s = params->tmu[0].startS; - state.tmu[0].base_t = params->tmu[0].startT; - state.tmu[0].base_w = params->tmu[0].startW; - state.tmu[1].base_s = params->tmu[1].startS; - state.tmu[1].base_t = params->tmu[1].startT; - state.tmu[1].base_w = params->tmu[1].startW; - state.base_w = params->startW; + state.base_r = params->startR; + state.base_g = params->startG; + state.base_b = params->startB; + state.base_a = params->startA; + state.base_z = params->startZ; + state.tmu[0].base_s = params->tmu[0].startS; + state.tmu[0].base_t = params->tmu[0].startT; + state.tmu[0].base_w = params->tmu[0].startW; + state.tmu[1].base_s = params->tmu[1].startS; + state.tmu[1].base_t = params->tmu[1].startT; + state.tmu[1].base_w = params->tmu[1].startW; + state.base_w = params->startW; - if (params->fbzColorPath & FBZ_PARAM_ADJUST) - { - state.base_r += (dx*params->dRdX + dy*params->dRdY) >> 4; - state.base_g += (dx*params->dGdX + dy*params->dGdY) >> 4; - state.base_b += (dx*params->dBdX + dy*params->dBdY) >> 4; - state.base_a += (dx*params->dAdX + dy*params->dAdY) >> 4; - state.base_z += (dx*params->dZdX + dy*params->dZdY) >> 4; - state.tmu[0].base_s += (dx*params->tmu[0].dSdX + dy*params->tmu[0].dSdY) >> 4; - state.tmu[0].base_t += (dx*params->tmu[0].dTdX + dy*params->tmu[0].dTdY) >> 4; - state.tmu[0].base_w += (dx*params->tmu[0].dWdX + dy*params->tmu[0].dWdY) >> 4; - state.tmu[1].base_s += (dx*params->tmu[1].dSdX + dy*params->tmu[1].dSdY) >> 4; - state.tmu[1].base_t += (dx*params->tmu[1].dTdX + dy*params->tmu[1].dTdY) >> 4; - state.tmu[1].base_w += (dx*params->tmu[1].dWdX + dy*params->tmu[1].dWdY) >> 4; - state.base_w += (dx*params->dWdX + dy*params->dWdY) >> 4; - } + if (params->fbzColorPath & FBZ_PARAM_ADJUST) { + state.base_r += (dx * params->dRdX + dy * params->dRdY) >> 4; + state.base_g += (dx * params->dGdX + dy * params->dGdY) >> 4; + state.base_b += (dx * params->dBdX + dy * params->dBdY) >> 4; + state.base_a += (dx * params->dAdX + dy * params->dAdY) >> 4; + state.base_z += (dx * params->dZdX + dy * params->dZdY) >> 4; + state.tmu[0].base_s += (dx * params->tmu[0].dSdX + dy * params->tmu[0].dSdY) >> 4; + state.tmu[0].base_t += (dx * params->tmu[0].dTdX + dy * params->tmu[0].dTdY) >> 4; + state.tmu[0].base_w += (dx * params->tmu[0].dWdX + dy * params->tmu[0].dWdY) >> 4; + state.tmu[1].base_s += (dx * params->tmu[1].dSdX + dy * params->tmu[1].dSdY) >> 4; + state.tmu[1].base_t += (dx * params->tmu[1].dTdX + dy * params->tmu[1].dTdY) >> 4; + state.tmu[1].base_w += (dx * params->tmu[1].dWdX + dy * params->tmu[1].dWdY) >> 4; + state.base_w += (dx * params->dWdX + dy * params->dWdY) >> 4; + } - tris++; + tris++; - state.vertexAy = params->vertexAy & ~0xffff0000; - if (state.vertexAy & 0x8000) - state.vertexAy |= 0xffff0000; - state.vertexBy = params->vertexBy & ~0xffff0000; - if (state.vertexBy & 0x8000) - state.vertexBy |= 0xffff0000; - state.vertexCy = params->vertexCy & ~0xffff0000; - if (state.vertexCy & 0x8000) - state.vertexCy |= 0xffff0000; + state.vertexAy = params->vertexAy & ~0xffff0000; + if (state.vertexAy & 0x8000) + state.vertexAy |= 0xffff0000; + state.vertexBy = params->vertexBy & ~0xffff0000; + if (state.vertexBy & 0x8000) + state.vertexBy |= 0xffff0000; + state.vertexCy = params->vertexCy & ~0xffff0000; + if (state.vertexCy & 0x8000) + state.vertexCy |= 0xffff0000; - state.vertexAx = params->vertexAx & ~0xffff0000; - if (state.vertexAx & 0x8000) - state.vertexAx |= 0xffff0000; - state.vertexBx = params->vertexBx & ~0xffff0000; - if (state.vertexBx & 0x8000) - state.vertexBx |= 0xffff0000; - state.vertexCx = params->vertexCx & ~0xffff0000; - if (state.vertexCx & 0x8000) - state.vertexCx |= 0xffff0000; + state.vertexAx = params->vertexAx & ~0xffff0000; + if (state.vertexAx & 0x8000) + state.vertexAx |= 0xffff0000; + state.vertexBx = params->vertexBx & ~0xffff0000; + if (state.vertexBx & 0x8000) + state.vertexBx |= 0xffff0000; + state.vertexCx = params->vertexCx & ~0xffff0000; + if (state.vertexCx & 0x8000) + state.vertexCx |= 0xffff0000; - vertexAy_adjusted = (state.vertexAy+7) >> 4; - vertexCy_adjusted = (state.vertexCy+7) >> 4; + vertexAy_adjusted = (state.vertexAy + 7) >> 4; + vertexCy_adjusted = (state.vertexCy + 7) >> 4; - if (state.vertexBy - state.vertexAy) - state.dxAB = (int)((((int64_t)state.vertexBx << 12) - ((int64_t)state.vertexAx << 12)) << 4) / (int)(state.vertexBy - state.vertexAy); - else - state.dxAB = 0; - if (state.vertexCy - state.vertexAy) - state.dxAC = (int)((((int64_t)state.vertexCx << 12) - ((int64_t)state.vertexAx << 12)) << 4) / (int)(state.vertexCy - state.vertexAy); - else - state.dxAC = 0; - if (state.vertexCy - state.vertexBy) - state.dxBC = (int)((((int64_t)state.vertexCx << 12) - ((int64_t)state.vertexBx << 12)) << 4) / (int)(state.vertexCy - state.vertexBy); - else - state.dxBC = 0; + if (state.vertexBy - state.vertexAy) + state.dxAB = (int) ((((int64_t) state.vertexBx << 12) - ((int64_t) state.vertexAx << 12)) << 4) / (state.vertexBy - state.vertexAy); + else + state.dxAB = 0; + if (state.vertexCy - state.vertexAy) + state.dxAC = (int) ((((int64_t) state.vertexCx << 12) - ((int64_t) state.vertexAx << 12)) << 4) / (state.vertexCy - state.vertexAy); + else + state.dxAC = 0; + if (state.vertexCy - state.vertexBy) + state.dxBC = (int) ((((int64_t) state.vertexCx << 12) - ((int64_t) state.vertexBx << 12)) << 4) / (state.vertexCy - state.vertexBy); + else + state.dxBC = 0; - state.lod_min[0] = (params->tLOD[0] & 0x3f) << 6; - state.lod_max[0] = ((params->tLOD[0] >> 6) & 0x3f) << 6; - if (state.lod_max[0] > 0x800) - state.lod_max[0] = 0x800; - state.lod_min[1] = (params->tLOD[1] & 0x3f) << 6; - state.lod_max[1] = ((params->tLOD[1] >> 6) & 0x3f) << 6; - if (state.lod_max[1] > 0x800) - state.lod_max[1] = 0x800; + state.lod_min[0] = (params->tLOD[0] & 0x3f) << 6; + state.lod_max[0] = ((params->tLOD[0] >> 6) & 0x3f) << 6; + if (state.lod_max[0] > 0x800) + state.lod_max[0] = 0x800; + state.lod_min[1] = (params->tLOD[1] & 0x3f) << 6; + state.lod_max[1] = ((params->tLOD[1] >> 6) & 0x3f) << 6; + if (state.lod_max[1] > 0x800) + state.lod_max[1] = 0x800; - state.xstart = state.xend = state.vertexAx << 8; - state.xdir = params->sign ? -1 : 1; + state.xstart = state.xend = state.vertexAx << 8; + state.xdir = params->sign ? -1 : 1; - state.y = (state.vertexAy + 8) >> 4; - state.ydir = 1; + state.y = (state.vertexAy + 8) >> 4; + state.ydir = 1; + tempdx = (params->tmu[0].dSdX >> 14) * (params->tmu[0].dSdX >> 14) + (params->tmu[0].dTdX >> 14) * (params->tmu[0].dTdX >> 14); + tempdy = (params->tmu[0].dSdY >> 14) * (params->tmu[0].dSdY >> 14) + (params->tmu[0].dTdY >> 14) * (params->tmu[0].dTdY >> 14); - tempdx = (params->tmu[0].dSdX >> 14) * (params->tmu[0].dSdX >> 14) + (params->tmu[0].dTdX >> 14) * (params->tmu[0].dTdX >> 14); - tempdy = (params->tmu[0].dSdY >> 14) * (params->tmu[0].dSdY >> 14) + (params->tmu[0].dTdY >> 14) * (params->tmu[0].dTdY >> 14); + if (tempdx > tempdy) + tempLOD = tempdx; + else + tempLOD = tempdy; - if (tempdx > tempdy) - tempLOD = tempdx; - else - tempLOD = tempdy; + LOD = (int) (log2((double) tempLOD / (double) (1ULL << 36)) * 256); + LOD >>= 2; - LOD = (int)(log2((double)tempLOD / (double)(1ULL << 36)) * 256); - LOD >>= 2; + lodbias = (params->tLOD[0] >> 12) & 0x3f; + if (lodbias & 0x20) + lodbias |= ~0x3f; + state.tmu[0].lod = LOD + (lodbias << 6); - lodbias = (params->tLOD[0] >> 12) & 0x3f; - if (lodbias & 0x20) - lodbias |= ~0x3f; - state.tmu[0].lod = LOD + (lodbias << 6); + tempdx = (params->tmu[1].dSdX >> 14) * (params->tmu[1].dSdX >> 14) + (params->tmu[1].dTdX >> 14) * (params->tmu[1].dTdX >> 14); + tempdy = (params->tmu[1].dSdY >> 14) * (params->tmu[1].dSdY >> 14) + (params->tmu[1].dTdY >> 14) * (params->tmu[1].dTdY >> 14); + if (tempdx > tempdy) + tempLOD = tempdx; + else + tempLOD = tempdy; - tempdx = (params->tmu[1].dSdX >> 14) * (params->tmu[1].dSdX >> 14) + (params->tmu[1].dTdX >> 14) * (params->tmu[1].dTdX >> 14); - tempdy = (params->tmu[1].dSdY >> 14) * (params->tmu[1].dSdY >> 14) + (params->tmu[1].dTdY >> 14) * (params->tmu[1].dTdY >> 14); + LOD = (int) (log2((double) tempLOD / (double) (1ULL << 36)) * 256); + LOD >>= 2; - if (tempdx > tempdy) - tempLOD = tempdx; - else - tempLOD = tempdy; + lodbias = (params->tLOD[1] >> 12) & 0x3f; + if (lodbias & 0x20) + lodbias |= ~0x3f; + state.tmu[1].lod = LOD + (lodbias << 6); - LOD = (int)(log2((double)tempLOD / (double)(1ULL << 36)) * 256); - LOD >>= 2; - - lodbias = (params->tLOD[1] >> 12) & 0x3f; - if (lodbias & 0x20) - lodbias |= ~0x3f; - state.tmu[1].lod = LOD + (lodbias << 6); - - - voodoo_half_triangle(voodoo, params, &state, vertexAy_adjusted, vertexCy_adjusted, odd_even); + voodoo_half_triangle(voodoo, params, &state, vertexAy_adjusted, vertexCy_adjusted, odd_even); } - -static void render_thread(void *param, int odd_even) +static void +render_thread(void *param, int odd_even) { - voodoo_t *voodoo = (voodoo_t *)param; + voodoo_t *voodoo = (voodoo_t *) param; - while (voodoo->render_thread_run[odd_even]) - { + while (voodoo->render_thread_run[odd_even]) { + thread_set_event(voodoo->render_not_full_event[odd_even]); + thread_wait_event(voodoo->wake_render_thread[odd_even], -1); + thread_reset_event(voodoo->wake_render_thread[odd_even]); + voodoo->render_voodoo_busy[odd_even] = 1; + + while (!PARAM_EMPTY(odd_even)) { + uint64_t start_time = plat_timer_read(); + uint64_t end_time; + voodoo_params_t *params = &voodoo->params_buffer[voodoo->params_read_idx[odd_even] & PARAM_MASK]; + + voodoo_triangle(voodoo, params, odd_even); + + voodoo->params_read_idx[odd_even]++; + + if (PARAM_ENTRIES(odd_even) > (PARAM_SIZE - 10)) thread_set_event(voodoo->render_not_full_event[odd_even]); - thread_wait_event(voodoo->wake_render_thread[odd_even], -1); - thread_reset_event(voodoo->wake_render_thread[odd_even]); - voodoo->render_voodoo_busy[odd_even] = 1; - while (!PARAM_EMPTY(odd_even)) - { - uint64_t start_time = plat_timer_read(); - uint64_t end_time; - voodoo_params_t *params = &voodoo->params_buffer[voodoo->params_read_idx[odd_even] & PARAM_MASK]; - - voodoo_triangle(voodoo, params, odd_even); - - voodoo->params_read_idx[odd_even]++; - - if (PARAM_ENTRIES(odd_even) > (PARAM_SIZE - 10)) - thread_set_event(voodoo->render_not_full_event[odd_even]); - - end_time = plat_timer_read(); - voodoo->render_time[odd_even] += end_time - start_time; - } - - voodoo->render_voodoo_busy[odd_even] = 0; - } -} - -void voodoo_render_thread_1(void *param) -{ - render_thread(param, 0); -} -void voodoo_render_thread_2(void *param) -{ - render_thread(param, 1); -} -void voodoo_render_thread_3(void *param) -{ - render_thread(param, 2); -} -void voodoo_render_thread_4(void *param) -{ - render_thread(param, 3); -} - -void voodoo_queue_triangle(voodoo_t *voodoo, voodoo_params_t *params) -{ - voodoo_params_t *params_new = &voodoo->params_buffer[voodoo->params_write_idx & PARAM_MASK]; - - while (PARAM_FULL(0) || (voodoo->render_threads >= 2 && PARAM_FULL(1)) || - (voodoo->render_threads == 4 && (PARAM_FULL(2) || PARAM_FULL(3)))) - { - thread_reset_event(voodoo->render_not_full_event[0]); - if (voodoo->render_threads >= 2) - thread_reset_event(voodoo->render_not_full_event[1]); - if (voodoo->render_threads == 4) - { - thread_reset_event(voodoo->render_not_full_event[2]); - thread_reset_event(voodoo->render_not_full_event[3]); - } - if (PARAM_FULL(0)) - thread_wait_event(voodoo->render_not_full_event[0], -1); /*Wait for room in ringbuffer*/ - if (voodoo->render_threads >= 2 && PARAM_FULL(1)) - thread_wait_event(voodoo->render_not_full_event[1], -1); /*Wait for room in ringbuffer*/ - if (voodoo->render_threads == 4 && PARAM_FULL(2)) - thread_wait_event(voodoo->render_not_full_event[2], -1); /*Wait for room in ringbuffer*/ - if (voodoo->render_threads == 4 && PARAM_FULL(3)) - thread_wait_event(voodoo->render_not_full_event[3], -1); /*Wait for room in ringbuffer*/ + end_time = plat_timer_read(); + voodoo->render_time[odd_even] += end_time - start_time; } - voodoo_use_texture(voodoo, params, 0); - if (voodoo->dual_tmus) - voodoo_use_texture(voodoo, params, 1); - - memcpy(params_new, params, sizeof(voodoo_params_t)); - - voodoo->params_write_idx++; - - if (PARAM_ENTRIES(0) < 4 || (voodoo->render_threads >= 2 && PARAM_ENTRIES(1) < 4) || - (voodoo->render_threads == 4 && (PARAM_ENTRIES(2) < 4 || PARAM_ENTRIES(3) < 4))) - voodoo_wake_render_thread(voodoo); + voodoo->render_voodoo_busy[odd_even] = 0; + } +} + +void +voodoo_render_thread_1(void *param) +{ + render_thread(param, 0); +} +void +voodoo_render_thread_2(void *param) +{ + render_thread(param, 1); +} +void +voodoo_render_thread_3(void *param) +{ + render_thread(param, 2); +} +void +voodoo_render_thread_4(void *param) +{ + render_thread(param, 3); +} + +void +voodoo_queue_triangle(voodoo_t *voodoo, voodoo_params_t *params) +{ + voodoo_params_t *params_new = &voodoo->params_buffer[voodoo->params_write_idx & PARAM_MASK]; + + while (PARAM_FULL(0) || (voodoo->render_threads >= 2 && PARAM_FULL(1)) || (voodoo->render_threads == 4 && (PARAM_FULL(2) || PARAM_FULL(3)))) { + thread_reset_event(voodoo->render_not_full_event[0]); + if (voodoo->render_threads >= 2) + thread_reset_event(voodoo->render_not_full_event[1]); + if (voodoo->render_threads == 4) { + thread_reset_event(voodoo->render_not_full_event[2]); + thread_reset_event(voodoo->render_not_full_event[3]); + } + if (PARAM_FULL(0)) + thread_wait_event(voodoo->render_not_full_event[0], -1); /*Wait for room in ringbuffer*/ + if (voodoo->render_threads >= 2 && PARAM_FULL(1)) + thread_wait_event(voodoo->render_not_full_event[1], -1); /*Wait for room in ringbuffer*/ + if (voodoo->render_threads == 4 && PARAM_FULL(2)) + thread_wait_event(voodoo->render_not_full_event[2], -1); /*Wait for room in ringbuffer*/ + if (voodoo->render_threads == 4 && PARAM_FULL(3)) + thread_wait_event(voodoo->render_not_full_event[3], -1); /*Wait for room in ringbuffer*/ + } + + voodoo_use_texture(voodoo, params, 0); + if (voodoo->dual_tmus) + voodoo_use_texture(voodoo, params, 1); + + memcpy(params_new, params, sizeof(voodoo_params_t)); + + voodoo->params_write_idx++; + + if (PARAM_ENTRIES(0) < 4 || (voodoo->render_threads >= 2 && PARAM_ENTRIES(1) < 4) || (voodoo->render_threads == 4 && (PARAM_ENTRIES(2) < 4 || PARAM_ENTRIES(3) < 4))) + voodoo_wake_render_thread(voodoo); } diff --git a/src/video/vid_voodoo_setup.c b/src/video/vid_voodoo_setup.c index 74f312fd4..e1d13ba35 100644 --- a/src/video/vid_voodoo_setup.c +++ b/src/video/vid_voodoo_setup.c @@ -1,19 +1,20 @@ /* - * 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. + * 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. + * This file is part of the 86Box distribution. * - * 3DFX Voodoo emulation. + * 3DFX Voodoo emulation. * * * - * Authors: Sarah Walker, + * Authors: Sarah Walker, * - * Copyright 2008-2020 Sarah Walker. + * Copyright 2008-2020 Sarah Walker. */ +#include #include #include #include @@ -21,6 +22,7 @@ #include #include #include +#define HAVE_STDARG_H #include <86box/86box.h> #include "cpu.h" #include <86box/machine.h> @@ -29,6 +31,7 @@ #include <86box/timer.h> #include <86box/device.h> #include <86box/plat.h> +#include <86box/thread.h> #include <86box/video.h> #include <86box/vid_svga.h> #include <86box/vid_voodoo_common.h> @@ -45,216 +48,195 @@ voodoo_setup_log(const char *fmt, ...) va_list ap; if (voodoo_setup_do_log) { - va_start(ap, fmt); - pclog_ex(fmt, ap); - va_end(ap); + va_start(ap, fmt); + pclog_ex(fmt, ap); + va_end(ap); } } #else -#define voodoo_setup_log(fmt, ...) +# define voodoo_setup_log(fmt, ...) #endif - -void voodoo_triangle_setup(voodoo_t *voodoo) +void +voodoo_triangle_setup(voodoo_t *voodoo) { - float dxAB, dxBC, dyAB, dyBC; - float area; - int va = 0, vb = 1, vc = 2; - vert_t verts[3]; + float dxAB; + float dxBC; + float dyAB; + float dyBC; + float area; + int va = 0; + int vb = 1; + int vc = 2; + vert_t verts[3]; - verts[0] = voodoo->verts[0]; - verts[1] = voodoo->verts[1]; - verts[2] = voodoo->verts[2]; + verts[0] = voodoo->verts[0]; + verts[1] = voodoo->verts[1]; + verts[2] = voodoo->verts[2]; - if (verts[0].sVy < verts[1].sVy) - { - if (verts[1].sVy < verts[2].sVy) - { - /* V1>V0, V2>V1, V2>V1>V0*/ - va = 0; /*OK*/ - vb = 1; - vc = 2; - } - else - { - /* V1>V0, V1>V2*/ - if (verts[0].sVy < verts[2].sVy) - { - /* V1>V0, V1>V2, V2>V0, V1>V2>V0*/ - va = 0; - vb = 2; - vc = 1; - } - else - { - /* V1>V0, V1>V2, V0>V2, V1>V0>V2*/ - va = 2; - vb = 0; - vc = 1; - } - } + if (verts[0].sVy < verts[1].sVy) { + if (verts[1].sVy < verts[2].sVy) { + /* V1>V0, V2>V1, V2>V1>V0*/ + va = 0; /*OK*/ + vb = 1; + vc = 2; + } else { + /* V1>V0, V1>V2*/ + if (verts[0].sVy < verts[2].sVy) { + /* V1>V0, V1>V2, V2>V0, V1>V2>V0*/ + va = 0; + vb = 2; + vc = 1; + } else { + /* V1>V0, V1>V2, V0>V2, V1>V0>V2*/ + va = 2; + vb = 0; + vc = 1; + } } - else - { - if (verts[1].sVy < verts[2].sVy) - { - /* V0>V1, V2>V1*/ - if (verts[0].sVy < verts[2].sVy) - { - /* V0>V1, V2>V1, V2>V0, V2>V0>V1*/ - va = 1; - vb = 0; - vc = 2; - } - else - { - /* V0>V1, V2>V1, V0>V2, V0>V2>V1*/ - va = 1; - vb = 2; - vc = 0; - } - } - else - { - /*V0>V1>V2*/ - va = 2; - vb = 1; - vc = 0; - } + } else { + if (verts[1].sVy < verts[2].sVy) { + /* V0>V1, V2>V1*/ + if (verts[0].sVy < verts[2].sVy) { + /* V0>V1, V2>V1, V2>V0, V2>V0>V1*/ + va = 1; + vb = 0; + vc = 2; + } else { + /* V0>V1, V2>V1, V0>V2, V0>V2>V1*/ + va = 1; + vb = 2; + vc = 0; + } + } else { + /*V0>V1>V2*/ + va = 2; + vb = 1; + vc = 0; } + } - dxAB = verts[0].sVx - verts[1].sVx; - dxBC = verts[1].sVx - verts[2].sVx; - dyAB = verts[0].sVy - verts[1].sVy; - dyBC = verts[1].sVy - verts[2].sVy; + dxAB = verts[0].sVx - verts[1].sVx; + dxBC = verts[1].sVx - verts[2].sVx; + dyAB = verts[0].sVy - verts[1].sVy; + dyBC = verts[1].sVy - verts[2].sVy; - area = dxAB * dyBC - dxBC * dyAB; + area = dxAB * dyBC - dxBC * dyAB; - if (area == 0.0) - return; + if (area == 0.0) + return; - if (voodoo->sSetupMode & SETUPMODE_CULLING_ENABLE) - { - int cull_sign = voodoo->sSetupMode & SETUPMODE_CULLING_SIGN; - int sign = (area < 0.0); - - if ((voodoo->sSetupMode & (SETUPMODE_CULLING_ENABLE | SETUPMODE_DISABLE_PINGPONG)) - == SETUPMODE_CULLING_ENABLE && voodoo->cull_pingpong) - cull_sign = !cull_sign; + if (voodoo->sSetupMode & SETUPMODE_CULLING_ENABLE) { + int cull_sign = voodoo->sSetupMode & SETUPMODE_CULLING_SIGN; + int sign = (area < 0.0); - if (cull_sign && sign) - return; - if (!cull_sign && !sign) - return; - } + if ((voodoo->sSetupMode & (SETUPMODE_CULLING_ENABLE | SETUPMODE_DISABLE_PINGPONG)) + == SETUPMODE_CULLING_ENABLE + && voodoo->cull_pingpong) + cull_sign = !cull_sign; + if (cull_sign && sign) + return; + if (!cull_sign && !sign) + return; + } - dxAB = verts[va].sVx - verts[vb].sVx; - dxBC = verts[vb].sVx - verts[vc].sVx; - dyAB = verts[va].sVy - verts[vb].sVy; - dyBC = verts[vb].sVy - verts[vc].sVy; + dxAB = verts[va].sVx - verts[vb].sVx; + dxBC = verts[vb].sVx - verts[vc].sVx; + dyAB = verts[va].sVy - verts[vb].sVy; + dyBC = verts[vb].sVy - verts[vc].sVy; - area = dxAB * dyBC - dxBC * dyAB; + area = dxAB * dyBC - dxBC * dyAB; - dxAB /= area; - dxBC /= area; - dyAB /= area; - dyBC /= area; + dxAB /= area; + dxBC /= area; + dyAB /= area; + dyBC /= area; + voodoo->params.vertexAx = (int32_t) (int16_t) ((int32_t) (verts[va].sVx * 16.0f) & 0xffff); + voodoo->params.vertexAy = (int32_t) (int16_t) ((int32_t) (verts[va].sVy * 16.0f) & 0xffff); + voodoo->params.vertexBx = (int32_t) (int16_t) ((int32_t) (verts[vb].sVx * 16.0f) & 0xffff); + voodoo->params.vertexBy = (int32_t) (int16_t) ((int32_t) (verts[vb].sVy * 16.0f) & 0xffff); + voodoo->params.vertexCx = (int32_t) (int16_t) ((int32_t) (verts[vc].sVx * 16.0f) & 0xffff); + voodoo->params.vertexCy = (int32_t) (int16_t) ((int32_t) (verts[vc].sVy * 16.0f) & 0xffff); + if (voodoo->params.vertexAy > voodoo->params.vertexBy || voodoo->params.vertexBy > voodoo->params.vertexCy) { + voodoo_setup_log("triangle_setup wrong order %d %d %d\n", voodoo->params.vertexAy, voodoo->params.vertexBy, voodoo->params.vertexCy); + return; + } - voodoo->params.vertexAx = (int32_t)(int16_t)((int32_t)(verts[va].sVx * 16.0f) & 0xffff); - voodoo->params.vertexAy = (int32_t)(int16_t)((int32_t)(verts[va].sVy * 16.0f) & 0xffff); - voodoo->params.vertexBx = (int32_t)(int16_t)((int32_t)(verts[vb].sVx * 16.0f) & 0xffff); - voodoo->params.vertexBy = (int32_t)(int16_t)((int32_t)(verts[vb].sVy * 16.0f) & 0xffff); - voodoo->params.vertexCx = (int32_t)(int16_t)((int32_t)(verts[vc].sVx * 16.0f) & 0xffff); - voodoo->params.vertexCy = (int32_t)(int16_t)((int32_t)(verts[vc].sVy * 16.0f) & 0xffff); + if (voodoo->sSetupMode & SETUPMODE_RGB) { + voodoo->params.startR = (int32_t) (verts[va].sRed * 4096.0f); + voodoo->params.dRdX = (int32_t) (((verts[va].sRed - verts[vb].sRed) * dyBC - (verts[vb].sRed - verts[vc].sRed) * dyAB) * 4096.0f); + voodoo->params.dRdY = (int32_t) (((verts[vb].sRed - verts[vc].sRed) * dxAB - (verts[va].sRed - verts[vb].sRed) * dxBC) * 4096.0f); + voodoo->params.startG = (int32_t) (verts[va].sGreen * 4096.0f); + voodoo->params.dGdX = (int32_t) (((verts[va].sGreen - verts[vb].sGreen) * dyBC - (verts[vb].sGreen - verts[vc].sGreen) * dyAB) * 4096.0f); + voodoo->params.dGdY = (int32_t) (((verts[vb].sGreen - verts[vc].sGreen) * dxAB - (verts[va].sGreen - verts[vb].sGreen) * dxBC) * 4096.0f); + voodoo->params.startB = (int32_t) (verts[va].sBlue * 4096.0f); + voodoo->params.dBdX = (int32_t) (((verts[va].sBlue - verts[vb].sBlue) * dyBC - (verts[vb].sBlue - verts[vc].sBlue) * dyAB) * 4096.0f); + voodoo->params.dBdY = (int32_t) (((verts[vb].sBlue - verts[vc].sBlue) * dxAB - (verts[va].sBlue - verts[vb].sBlue) * dxBC) * 4096.0f); + } + if (voodoo->sSetupMode & SETUPMODE_ALPHA) { + voodoo->params.startA = (int32_t) (verts[va].sAlpha * 4096.0f); + voodoo->params.dAdX = (int32_t) (((verts[va].sAlpha - verts[vb].sAlpha) * dyBC - (verts[vb].sAlpha - verts[vc].sAlpha) * dyAB) * 4096.0f); + voodoo->params.dAdY = (int32_t) (((verts[vb].sAlpha - verts[vc].sAlpha) * dxAB - (verts[va].sAlpha - verts[vb].sAlpha) * dxBC) * 4096.0f); + } + if (voodoo->sSetupMode & SETUPMODE_Z) { + voodoo->params.startZ = (int32_t) (verts[va].sVz * 4096.0f); + voodoo->params.dZdX = (int32_t) (((verts[va].sVz - verts[vb].sVz) * dyBC - (verts[vb].sVz - verts[vc].sVz) * dyAB) * 4096.0f); + voodoo->params.dZdY = (int32_t) (((verts[vb].sVz - verts[vc].sVz) * dxAB - (verts[va].sVz - verts[vb].sVz) * dxBC) * 4096.0f); + } + if (voodoo->sSetupMode & SETUPMODE_Wb) { + voodoo->params.startW = (int64_t) (verts[va].sWb * 4294967296.0f); + voodoo->params.dWdX = (int64_t) (((verts[va].sWb - verts[vb].sWb) * dyBC - (verts[vb].sWb - verts[vc].sWb) * dyAB) * 4294967296.0f); + voodoo->params.dWdY = (int64_t) (((verts[vb].sWb - verts[vc].sWb) * dxAB - (verts[va].sWb - verts[vb].sWb) * dxBC) * 4294967296.0f); + voodoo->params.tmu[0].startW = voodoo->params.tmu[1].startW = voodoo->params.startW; + voodoo->params.tmu[0].dWdX = voodoo->params.tmu[1].dWdX = voodoo->params.dWdX; + voodoo->params.tmu[0].dWdY = voodoo->params.tmu[1].dWdY = voodoo->params.dWdY; + } + if (voodoo->sSetupMode & SETUPMODE_W0) { + voodoo->params.tmu[0].startW = (int64_t) (verts[va].sW0 * 4294967296.0f); + voodoo->params.tmu[0].dWdX = (int64_t) (((verts[va].sW0 - verts[vb].sW0) * dyBC - (verts[vb].sW0 - verts[vc].sW0) * dyAB) * 4294967296.0f); + voodoo->params.tmu[0].dWdY = (int64_t) (((verts[vb].sW0 - verts[vc].sW0) * dxAB - (verts[va].sW0 - verts[vb].sW0) * dxBC) * 4294967296.0f); + voodoo->params.tmu[1].startW = voodoo->params.tmu[0].startW; + voodoo->params.tmu[1].dWdX = voodoo->params.tmu[0].dWdX; + voodoo->params.tmu[1].dWdY = voodoo->params.tmu[0].dWdY; + } + if (voodoo->sSetupMode & SETUPMODE_S0_T0) { + voodoo->params.tmu[0].startS = (int64_t) (verts[va].sS0 * 4294967296.0f); + voodoo->params.tmu[0].dSdX = (int64_t) (((verts[va].sS0 - verts[vb].sS0) * dyBC - (verts[vb].sS0 - verts[vc].sS0) * dyAB) * 4294967296.0f); + voodoo->params.tmu[0].dSdY = (int64_t) (((verts[vb].sS0 - verts[vc].sS0) * dxAB - (verts[va].sS0 - verts[vb].sS0) * dxBC) * 4294967296.0f); + voodoo->params.tmu[0].startT = (int64_t) (verts[va].sT0 * 4294967296.0f); + voodoo->params.tmu[0].dTdX = (int64_t) (((verts[va].sT0 - verts[vb].sT0) * dyBC - (verts[vb].sT0 - verts[vc].sT0) * dyAB) * 4294967296.0f); + voodoo->params.tmu[0].dTdY = (int64_t) (((verts[vb].sT0 - verts[vc].sT0) * dxAB - (verts[va].sT0 - verts[vb].sT0) * dxBC) * 4294967296.0f); + voodoo->params.tmu[1].startS = voodoo->params.tmu[0].startS; + voodoo->params.tmu[1].dSdX = voodoo->params.tmu[0].dSdX; + voodoo->params.tmu[1].dSdY = voodoo->params.tmu[0].dSdY; + voodoo->params.tmu[1].startT = voodoo->params.tmu[0].startT; + voodoo->params.tmu[1].dTdX = voodoo->params.tmu[0].dTdX; + voodoo->params.tmu[1].dTdY = voodoo->params.tmu[0].dTdY; + } + if (voodoo->sSetupMode & SETUPMODE_W1) { + voodoo->params.tmu[1].startW = (int64_t) (verts[va].sW1 * 4294967296.0f); + voodoo->params.tmu[1].dWdX = (int64_t) (((verts[va].sW1 - verts[vb].sW1) * dyBC - (verts[vb].sW1 - verts[vc].sW1) * dyAB) * 4294967296.0f); + voodoo->params.tmu[1].dWdY = (int64_t) (((verts[vb].sW1 - verts[vc].sW1) * dxAB - (verts[va].sW1 - verts[vb].sW1) * dxBC) * 4294967296.0f); + } + if (voodoo->sSetupMode & SETUPMODE_S1_T1) { + voodoo->params.tmu[1].startS = (int64_t) (verts[va].sS1 * 4294967296.0f); + voodoo->params.tmu[1].dSdX = (int64_t) (((verts[va].sS1 - verts[vb].sS1) * dyBC - (verts[vb].sS1 - verts[vc].sS1) * dyAB) * 4294967296.0f); + voodoo->params.tmu[1].dSdY = (int64_t) (((verts[vb].sS1 - verts[vc].sS1) * dxAB - (verts[va].sS1 - verts[vb].sS1) * dxBC) * 4294967296.0f); + voodoo->params.tmu[1].startT = (int64_t) (verts[va].sT1 * 4294967296.0f); + voodoo->params.tmu[1].dTdX = (int64_t) (((verts[va].sT1 - verts[vb].sT1) * dyBC - (verts[vb].sT1 - verts[vc].sT1) * dyAB) * 4294967296.0f); + voodoo->params.tmu[1].dTdY = (int64_t) (((verts[vb].sT1 - verts[vc].sT1) * dxAB - (verts[va].sT1 - verts[vb].sT1) * dxBC) * 4294967296.0f); + } - if (voodoo->params.vertexAy > voodoo->params.vertexBy || voodoo->params.vertexBy > voodoo->params.vertexCy) { - voodoo_setup_log("triangle_setup wrong order %d %d %d\n", voodoo->params.vertexAy, voodoo->params.vertexBy, voodoo->params.vertexCy); - return; - } + voodoo->params.sign = (area < 0.0); - if (voodoo->sSetupMode & SETUPMODE_RGB) - { - voodoo->params.startR = (int32_t)(verts[va].sRed * 4096.0f); - voodoo->params.dRdX = (int32_t)(((verts[va].sRed - verts[vb].sRed) * dyBC - (verts[vb].sRed - verts[vc].sRed) * dyAB) * 4096.0f); - voodoo->params.dRdY = (int32_t)(((verts[vb].sRed - verts[vc].sRed) * dxAB - (verts[va].sRed - verts[vb].sRed) * dxBC) * 4096.0f); - voodoo->params.startG = (int32_t)(verts[va].sGreen * 4096.0f); - voodoo->params.dGdX = (int32_t)(((verts[va].sGreen - verts[vb].sGreen) * dyBC - (verts[vb].sGreen - verts[vc].sGreen) * dyAB) * 4096.0f); - voodoo->params.dGdY = (int32_t)(((verts[vb].sGreen - verts[vc].sGreen) * dxAB - (verts[va].sGreen - verts[vb].sGreen) * dxBC) * 4096.0f); - voodoo->params.startB = (int32_t)(verts[va].sBlue * 4096.0f); - voodoo->params.dBdX = (int32_t)(((verts[va].sBlue - verts[vb].sBlue) * dyBC - (verts[vb].sBlue - verts[vc].sBlue) * dyAB) * 4096.0f); - voodoo->params.dBdY = (int32_t)(((verts[vb].sBlue - verts[vc].sBlue) * dxAB - (verts[va].sBlue - verts[vb].sBlue) * dxBC) * 4096.0f); - } - if (voodoo->sSetupMode & SETUPMODE_ALPHA) - { - voodoo->params.startA = (int32_t)(verts[va].sAlpha * 4096.0f); - voodoo->params.dAdX = (int32_t)(((verts[va].sAlpha - verts[vb].sAlpha) * dyBC - (verts[vb].sAlpha - verts[vc].sAlpha) * dyAB) * 4096.0f); - voodoo->params.dAdY = (int32_t)(((verts[vb].sAlpha - verts[vc].sAlpha) * dxAB - (verts[va].sAlpha - verts[vb].sAlpha) * dxBC) * 4096.0f); - } - if (voodoo->sSetupMode & SETUPMODE_Z) - { - voodoo->params.startZ = (int32_t)(verts[va].sVz * 4096.0f); - voodoo->params.dZdX = (int32_t)(((verts[va].sVz - verts[vb].sVz) * dyBC - (verts[vb].sVz - verts[vc].sVz) * dyAB) * 4096.0f); - voodoo->params.dZdY = (int32_t)(((verts[vb].sVz - verts[vc].sVz) * dxAB - (verts[va].sVz - verts[vb].sVz) * dxBC) * 4096.0f); - } - if (voodoo->sSetupMode & SETUPMODE_Wb) - { - voodoo->params.startW = (int64_t)(verts[va].sWb * 4294967296.0f); - voodoo->params.dWdX = (int64_t)(((verts[va].sWb - verts[vb].sWb) * dyBC - (verts[vb].sWb - verts[vc].sWb) * dyAB) * 4294967296.0f); - voodoo->params.dWdY = (int64_t)(((verts[vb].sWb - verts[vc].sWb) * dxAB - (verts[va].sWb - verts[vb].sWb) * dxBC) * 4294967296.0f); - voodoo->params.tmu[0].startW = voodoo->params.tmu[1].startW = voodoo->params.startW; - voodoo->params.tmu[0].dWdX = voodoo->params.tmu[1].dWdX = voodoo->params.dWdX; - voodoo->params.tmu[0].dWdY = voodoo->params.tmu[1].dWdY = voodoo->params.dWdY; - } - if (voodoo->sSetupMode & SETUPMODE_W0) - { - voodoo->params.tmu[0].startW = (int64_t)(verts[va].sW0 * 4294967296.0f); - voodoo->params.tmu[0].dWdX = (int64_t)(((verts[va].sW0 - verts[vb].sW0) * dyBC - (verts[vb].sW0 - verts[vc].sW0) * dyAB) * 4294967296.0f); - voodoo->params.tmu[0].dWdY = (int64_t)(((verts[vb].sW0 - verts[vc].sW0) * dxAB - (verts[va].sW0 - verts[vb].sW0) * dxBC) * 4294967296.0f); - voodoo->params.tmu[1].startW = voodoo->params.tmu[0].startW; - voodoo->params.tmu[1].dWdX = voodoo->params.tmu[0].dWdX; - voodoo->params.tmu[1].dWdY = voodoo->params.tmu[0].dWdY; - } - if (voodoo->sSetupMode & SETUPMODE_S0_T0) - { - voodoo->params.tmu[0].startS = (int64_t)(verts[va].sS0 * 4294967296.0f); - voodoo->params.tmu[0].dSdX = (int64_t)(((verts[va].sS0 - verts[vb].sS0) * dyBC - (verts[vb].sS0 - verts[vc].sS0) * dyAB) * 4294967296.0f); - voodoo->params.tmu[0].dSdY = (int64_t)(((verts[vb].sS0 - verts[vc].sS0) * dxAB - (verts[va].sS0 - verts[vb].sS0) * dxBC) * 4294967296.0f); - voodoo->params.tmu[0].startT = (int64_t)(verts[va].sT0 * 4294967296.0f); - voodoo->params.tmu[0].dTdX = (int64_t)(((verts[va].sT0 - verts[vb].sT0) * dyBC - (verts[vb].sT0 - verts[vc].sT0) * dyAB) * 4294967296.0f); - voodoo->params.tmu[0].dTdY = (int64_t)(((verts[vb].sT0 - verts[vc].sT0) * dxAB - (verts[va].sT0 - verts[vb].sT0) * dxBC) * 4294967296.0f); - voodoo->params.tmu[1].startS = voodoo->params.tmu[0].startS; - voodoo->params.tmu[1].dSdX = voodoo->params.tmu[0].dSdX; - voodoo->params.tmu[1].dSdY = voodoo->params.tmu[0].dSdY; - voodoo->params.tmu[1].startT = voodoo->params.tmu[0].startT; - voodoo->params.tmu[1].dTdX = voodoo->params.tmu[0].dTdX; - voodoo->params.tmu[1].dTdY = voodoo->params.tmu[0].dTdY; - } - if (voodoo->sSetupMode & SETUPMODE_W1) - { - voodoo->params.tmu[1].startW = (int64_t)(verts[va].sW1 * 4294967296.0f); - voodoo->params.tmu[1].dWdX = (int64_t)(((verts[va].sW1 - verts[vb].sW1) * dyBC - (verts[vb].sW1 - verts[vc].sW1) * dyAB) * 4294967296.0f); - voodoo->params.tmu[1].dWdY = (int64_t)(((verts[vb].sW1 - verts[vc].sW1) * dxAB - (verts[va].sW1 - verts[vb].sW1) * dxBC) * 4294967296.0f); - } - if (voodoo->sSetupMode & SETUPMODE_S1_T1) - { - voodoo->params.tmu[1].startS = (int64_t)(verts[va].sS1 * 4294967296.0f); - voodoo->params.tmu[1].dSdX = (int64_t)(((verts[va].sS1 - verts[vb].sS1) * dyBC - (verts[vb].sS1 - verts[vc].sS1) * dyAB) * 4294967296.0f); - voodoo->params.tmu[1].dSdY = (int64_t)(((verts[vb].sS1 - verts[vc].sS1) * dxAB - (verts[va].sS1 - verts[vb].sS1) * dxBC) * 4294967296.0f); - voodoo->params.tmu[1].startT = (int64_t)(verts[va].sT1 * 4294967296.0f); - voodoo->params.tmu[1].dTdX = (int64_t)(((verts[va].sT1 - verts[vb].sT1) * dyBC - (verts[vb].sT1 - verts[vc].sT1) * dyAB) * 4294967296.0f); - voodoo->params.tmu[1].dTdY = (int64_t)(((verts[vb].sT1 - verts[vc].sT1) * dxAB - (verts[va].sT1 - verts[vb].sT1) * dxBC) * 4294967296.0f); - } + if (voodoo->ncc_dirty[0]) + voodoo_update_ncc(voodoo, 0); + if (voodoo->ncc_dirty[1]) + voodoo_update_ncc(voodoo, 1); + voodoo->ncc_dirty[0] = voodoo->ncc_dirty[1] = 0; - voodoo->params.sign = (area < 0.0); - - if (voodoo->ncc_dirty[0]) - voodoo_update_ncc(voodoo, 0); - if (voodoo->ncc_dirty[1]) - voodoo_update_ncc(voodoo, 1); - voodoo->ncc_dirty[0] = voodoo->ncc_dirty[1] = 0; - - voodoo_queue_triangle(voodoo, &voodoo->params); + voodoo_queue_triangle(voodoo, &voodoo->params); } diff --git a/src/video/vid_voodoo_texture.c b/src/video/vid_voodoo_texture.c index 9f6e59b33..3939db3cd 100644 --- a/src/video/vid_voodoo_texture.c +++ b/src/video/vid_voodoo_texture.c @@ -1,19 +1,20 @@ /* - * 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. + * 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. + * This file is part of the 86Box distribution. * - * 3DFX Voodoo emulation. + * 3DFX Voodoo emulation. * * * - * Authors: Sarah Walker, + * Authors: Sarah Walker, * - * Copyright 2008-2020 Sarah Walker. + * Copyright 2008-2020 Sarah Walker. */ +#include #include #include #include @@ -21,6 +22,7 @@ #include #include #include +#define HAVE_STDARG_H #include <86box/86box.h> #include "cpu.h" #include <86box/machine.h> @@ -29,6 +31,7 @@ #include <86box/timer.h> #include <86box/device.h> #include <86box/plat.h> +#include <86box/thread.h> #include <86box/video.h> #include <86box/vid_svga.h> #include <86box/vid_voodoo_common.h> @@ -37,7 +40,6 @@ #include <86box/vid_voodoo_render.h> #include <86box/vid_voodoo_texture.h> - #ifdef ENABLE_VOODOO_TEXTURE_LOG int voodoo_texture_do_log = ENABLE_VOODOO_TEXTURE_LOG; @@ -47,581 +49,608 @@ voodoo_texture_log(const char *fmt, ...) va_list ap; if (voodoo_texture_do_log) { - va_start(ap, fmt); - pclog_ex(fmt, ap); - va_end(ap); + va_start(ap, fmt); + pclog_ex(fmt, ap); + va_end(ap); } } #else -#define voodoo_texture_log(fmt, ...) +# define voodoo_texture_log(fmt, ...) #endif - -void voodoo_recalc_tex(voodoo_t *voodoo, int tmu) +void +voodoo_recalc_tex12(voodoo_t *voodoo, int tmu) { - int aspect = (voodoo->params.tLOD[tmu] >> 21) & 3; - int width = 256, height = 256; - int shift = 8; - int lod; - uint32_t base = voodoo->params.texBaseAddr[tmu]; - uint32_t offset = 0; - int tex_lod = 0; - uint32_t offsets[LOD_MAX+3]; - int widths[LOD_MAX+3], heights[LOD_MAX+3], shifts[LOD_MAX+3]; + int aspect = (voodoo->params.tLOD[tmu] >> 21) & 3; + int width = 256; + int height = 256; + int shift = 8; + uint32_t base = voodoo->params.texBaseAddr[tmu]; + uint32_t offset = 0; + int tex_lod = 0; - if (voodoo->params.tLOD[tmu] & LOD_S_IS_WIDER) - height >>= aspect; + if (voodoo->params.tLOD[tmu] & LOD_S_IS_WIDER) + height >>= aspect; + else { + width >>= aspect; + shift -= aspect; + } + + if ((voodoo->params.tLOD[tmu] & LOD_SPLIT) && (voodoo->params.tLOD[tmu] & LOD_ODD)) { + width >>= 1; + height >>= 1; + shift--; + tex_lod++; + if (voodoo->params.tLOD[tmu] & LOD_TMULTIBASEADDR) + base = voodoo->params.texBaseAddr1[tmu]; + } + + for (uint8_t lod = 0; lod <= LOD_MAX + 1; lod++) { + if (!width) + width = 1; + if (!height) + height = 1; + if (shift < 0) + shift = 0; + voodoo->params.tex_base[tmu][lod] = base + offset; + if (voodoo->params.tformat[tmu] & 8) + voodoo->params.tex_end[tmu][lod] = base + offset + (width * height * 2); else - { - width >>= aspect; - shift -= aspect; - } + voodoo->params.tex_end[tmu][lod] = base + offset + (width * height); + voodoo->params.tex_w_mask[tmu][lod] = width - 1; + voodoo->params.tex_w_nmask[tmu][lod] = ~(width - 1); + voodoo->params.tex_h_mask[tmu][lod] = height - 1; + voodoo->params.tex_shift[tmu][lod] = shift; + voodoo->params.tex_lod[tmu][lod] = tex_lod; - for (lod = 0; lod <= LOD_MAX + 2; lod++) - { - offsets[lod] = offset; - widths[lod] = width >> lod; - heights[lod] = height >> lod; - shifts[lod] = shift - lod; - - if (!widths[lod]) - widths[lod] = 1; - if (!heights[lod]) - heights[lod] = 1; - if (shifts[lod] < 0) - shifts[lod] = 0; - - if (!(voodoo->params.tLOD[tmu] & LOD_SPLIT) || - ((lod & 1) && (voodoo->params.tLOD[tmu] & LOD_ODD)) || - (!(lod & 1) && !(voodoo->params.tLOD[tmu] & LOD_ODD))) - { - if (voodoo->params.tformat[tmu] & 8) - offset += (width >> lod) * (height >> lod) * 2; - else - offset += (width >> lod) * (height >> lod); - } - } - - - if ((voodoo->params.textureMode[tmu] & TEXTUREMODE_TRILINEAR) && (voodoo->params.tLOD[tmu] & LOD_ODD)) - tex_lod++; /*Skip LOD 0*/ - -// voodoo_texture_log("TMU %i: %08x\n", tmu, voodoo->params.textureMode[tmu]); - for (lod = 0; lod <= LOD_MAX+1; lod++) - { - if (voodoo->params.tLOD[tmu] & LOD_TMULTIBASEADDR) - { - switch (tex_lod) - { - case 0: - base = voodoo->params.texBaseAddr[tmu]; - break; - case 1: - base = voodoo->params.texBaseAddr1[tmu]; - break; - case 2: - base = voodoo->params.texBaseAddr2[tmu]; - break; - default: - base = voodoo->params.texBaseAddr38[tmu]; - break; - } - } - - voodoo->params.tex_base[tmu][lod] = base + offsets[tex_lod]; + if (!(voodoo->params.tLOD[tmu] & LOD_SPLIT) || ((lod & 1) && (voodoo->params.tLOD[tmu] & LOD_ODD)) || (!(lod & 1) && !(voodoo->params.tLOD[tmu] & LOD_ODD))) { + if (!(voodoo->params.tLOD[tmu] & LOD_ODD) || lod != 0) { if (voodoo->params.tformat[tmu] & 8) - voodoo->params.tex_end[tmu][lod] = base + offsets[tex_lod] + (widths[tex_lod] * heights[tex_lod] * 2); + offset += width * height * 2; else - voodoo->params.tex_end[tmu][lod] = base + offsets[tex_lod] + (widths[tex_lod] * heights[tex_lod]); - voodoo->params.tex_w_mask[tmu][lod] = widths[tex_lod] - 1; - voodoo->params.tex_w_nmask[tmu][lod] = ~(widths[tex_lod] - 1); - voodoo->params.tex_h_mask[tmu][lod] = heights[tex_lod] - 1; - voodoo->params.tex_shift[tmu][lod] = shifts[tex_lod]; - voodoo->params.tex_lod[tmu][lod] = tex_lod; + offset += width * height; - if (!(voodoo->params.textureMode[tmu] & TEXTUREMODE_TRILINEAR) || - ((lod & 1) && (voodoo->params.tLOD[tmu] & LOD_ODD)) || - (!(lod & 1) && !(voodoo->params.tLOD[tmu] & LOD_ODD))) - { - if (!(voodoo->params.tLOD[tmu] & LOD_ODD) || lod != 0) - { - if (voodoo->params.textureMode[tmu] & TEXTUREMODE_TRILINEAR) - tex_lod += 2; - else - tex_lod++; - } + if (voodoo->params.tLOD[tmu] & LOD_SPLIT) { + width >>= 2; + height >>= 2; + shift -= 2; + tex_lod += 2; + } else { + width >>= 1; + height >>= 1; + shift--; + tex_lod++; } - } - - voodoo->params.tex_width[tmu] = width; -} - -#define makergba(r, g, b, a) ((b) | ((g) << 8) | ((r) << 16) | ((a) << 24)) - -void voodoo_use_texture(voodoo_t *voodoo, voodoo_params_t *params, int tmu) -{ - int c, d; - int lod; - int lod_min, lod_max; - uint32_t addr = 0, addr_end; - uint32_t palette_checksum; - - lod_min = (params->tLOD[tmu] >> 2) & 15; - lod_max = (params->tLOD[tmu] >> 8) & 15; - - if (params->tformat[tmu] == TEX_PAL8 || params->tformat[tmu] == TEX_APAL8 || params->tformat[tmu] == TEX_APAL88) - { - if (voodoo->palette_dirty[tmu]) - { - palette_checksum = 0; - - for (c = 0; c < 256; c++) - palette_checksum ^= voodoo->palette[tmu][c].u; - - voodoo->palette_checksum[tmu] = palette_checksum; - voodoo->palette_dirty[tmu] = 0; - } - else - palette_checksum = voodoo->palette_checksum[tmu]; - } - else - palette_checksum = 0; - - if ((voodoo->params.tLOD[tmu] & LOD_SPLIT) && (voodoo->params.tLOD[tmu] & LOD_ODD) && (voodoo->params.tLOD[tmu] & LOD_TMULTIBASEADDR)) - addr = params->texBaseAddr1[tmu]; - else - addr = params->texBaseAddr[tmu]; - - /*Try to find texture in cache*/ - for (c = 0; c < TEX_CACHE_MAX; c++) - { - if (voodoo->texture_cache[tmu][c].base == addr && - voodoo->texture_cache[tmu][c].tLOD == (params->tLOD[tmu] & 0xf00fff) && - voodoo->texture_cache[tmu][c].palette_checksum == palette_checksum) - { - params->tex_entry[tmu] = c; - voodoo->texture_cache[tmu][c].refcount++; - return; - } - } - - /*Texture not found, search for unused texture*/ - do - { - for (c = 0; c < TEX_CACHE_MAX; c++) - { - voodoo->texture_last_removed++; - voodoo->texture_last_removed &= (TEX_CACHE_MAX-1); - if (voodoo->texture_cache[tmu][voodoo->texture_last_removed].refcount == voodoo->texture_cache[tmu][voodoo->texture_last_removed].refcount_r[0] && - (voodoo->render_threads == 1 || voodoo->texture_cache[tmu][voodoo->texture_last_removed].refcount == voodoo->texture_cache[tmu][voodoo->texture_last_removed].refcount_r[1])) - break; - } - if (c == TEX_CACHE_MAX) - voodoo_wait_for_render_thread_idle(voodoo); - } while (c == TEX_CACHE_MAX); - if (c == TEX_CACHE_MAX) - fatal("Texture cache full!\n"); - - c = voodoo->texture_last_removed; - - - if ((voodoo->params.tLOD[tmu] & LOD_SPLIT) && (voodoo->params.tLOD[tmu] & LOD_ODD) && (voodoo->params.tLOD[tmu] & LOD_TMULTIBASEADDR)) - voodoo->texture_cache[tmu][c].base = params->texBaseAddr1[tmu]; - else - voodoo->texture_cache[tmu][c].base = params->texBaseAddr[tmu]; - voodoo->texture_cache[tmu][c].tLOD = params->tLOD[tmu] & 0xf00fff; - - lod_min = (params->tLOD[tmu] >> 2) & 15; - lod_max = (params->tLOD[tmu] >> 8) & 15; -// voodoo_texture_log(" add new texture to %i tformat=%i %08x LOD=%i-%i tmu=%i\n", c, voodoo->params.tformat[tmu], params->texBaseAddr[tmu], lod_min, lod_max, tmu); - lod_min = MIN(lod_min, 8); - lod_max = MIN(lod_max, 8); - for (lod = lod_min; lod <= lod_max; lod++) - { - uint32_t *base = &voodoo->texture_cache[tmu][c].data[texture_offset[lod]]; - uint32_t tex_addr = params->tex_base[tmu][lod] & voodoo->texture_mask; - int x, y; - int shift = 8 - params->tex_lod[tmu][lod]; - rgba_u *pal; - - //voodoo_texture_log(" LOD %i : %08x - %08x %i %i,%i\n", lod, params->tex_base[tmu][lod] & voodoo->texture_mask, addr, voodoo->params.tformat[tmu], voodoo->params.tex_w_mask[tmu][lod],voodoo->params.tex_h_mask[tmu][lod]); - - - switch (params->tformat[tmu]) - { - case TEX_RGB332: - for (y = 0; y < voodoo->params.tex_h_mask[tmu][lod]+1; y++) - { - for (x = 0; x < voodoo->params.tex_w_mask[tmu][lod]+1; x++) - { - uint8_t dat = voodoo->tex_mem[tmu][(tex_addr+x) & voodoo->texture_mask]; - - base[x] = makergba(rgb332[dat].r, rgb332[dat].g, rgb332[dat].b, 0xff); - } - tex_addr += (1 << voodoo->params.tex_shift[tmu][lod]); - base += (1 << shift); - } - break; - - case TEX_Y4I2Q2: - pal = voodoo->ncc_lookup[tmu][(voodoo->params.textureMode[tmu] & TEXTUREMODE_NCC_SEL) ? 1 : 0]; - for (y = 0; y < voodoo->params.tex_h_mask[tmu][lod]+1; y++) - { - for (x = 0; x < voodoo->params.tex_w_mask[tmu][lod]+1; x++) - { - uint8_t dat = voodoo->tex_mem[tmu][(tex_addr+x) & voodoo->texture_mask]; - - base[x] = makergba(pal[dat].rgba.r, pal[dat].rgba.g, pal[dat].rgba.b, 0xff); - } - tex_addr += (1 << voodoo->params.tex_shift[tmu][lod]); - base += (1 << shift); - } - break; - - case TEX_A8: - for (y = 0; y < voodoo->params.tex_h_mask[tmu][lod]+1; y++) - { - for (x = 0; x < voodoo->params.tex_w_mask[tmu][lod]+1; x++) - { - uint8_t dat = voodoo->tex_mem[tmu][(tex_addr+x) & voodoo->texture_mask]; - - base[x] = makergba(dat, dat, dat, dat); - } - tex_addr += (1 << voodoo->params.tex_shift[tmu][lod]); - base += (1 << shift); - } - break; - - case TEX_I8: - for (y = 0; y < voodoo->params.tex_h_mask[tmu][lod]+1; y++) - { - for (x = 0; x < voodoo->params.tex_w_mask[tmu][lod]+1; x++) - { - uint8_t dat = voodoo->tex_mem[tmu][(tex_addr+x) & voodoo->texture_mask]; - - base[x] = makergba(dat, dat, dat, 0xff); - } - tex_addr += (1 << voodoo->params.tex_shift[tmu][lod]); - base += (1 << shift); - } - break; - - case TEX_AI8: - for (y = 0; y < voodoo->params.tex_h_mask[tmu][lod]+1; y++) - { - for (x = 0; x < voodoo->params.tex_w_mask[tmu][lod]+1; x++) - { - uint8_t dat = voodoo->tex_mem[tmu][(tex_addr+x) & voodoo->texture_mask]; - - base[x] = makergba((dat & 0x0f) | ((dat << 4) & 0xf0), (dat & 0x0f) | ((dat << 4) & 0xf0), (dat & 0x0f) | ((dat << 4) & 0xf0), (dat & 0xf0) | ((dat >> 4) & 0x0f)); - } - tex_addr += (1 << voodoo->params.tex_shift[tmu][lod]); - base += (1 << shift); - } - break; - - case TEX_PAL8: - pal = voodoo->palette[tmu]; - for (y = 0; y < voodoo->params.tex_h_mask[tmu][lod]+1; y++) - { - for (x = 0; x < voodoo->params.tex_w_mask[tmu][lod]+1; x++) - { - uint8_t dat = voodoo->tex_mem[tmu][(tex_addr+x) & voodoo->texture_mask]; - - base[x] = makergba(pal[dat].rgba.r, pal[dat].rgba.g, pal[dat].rgba.b, 0xff); - } - tex_addr += (1 << voodoo->params.tex_shift[tmu][lod]); - base += (1 << shift); - } - break; - - case TEX_APAL8: - pal = voodoo->palette[tmu]; - for (y = 0; y < voodoo->params.tex_h_mask[tmu][lod]+1; y++) - { - for (x = 0; x < voodoo->params.tex_w_mask[tmu][lod]+1; x++) - { - uint8_t dat = voodoo->tex_mem[tmu][(tex_addr+x) & voodoo->texture_mask]; - - int r = ((pal[dat].rgba.r & 3) << 6) | ((pal[dat].rgba.g & 0xf0) >> 2) | (pal[dat].rgba.r & 3); - int g = ((pal[dat].rgba.g & 0xf) << 4) | ((pal[dat].rgba.b & 0xc0) >> 4) | ((pal[dat].rgba.g & 0xf) >> 2); - int b = ((pal[dat].rgba.b & 0x3f) << 2) | ((pal[dat].rgba.b & 0x30) >> 4); - int a = (pal[dat].rgba.r & 0xfc) | ((pal[dat].rgba.r & 0xc0) >> 6); - - base[x] = makergba(r, g, b, a); - } - tex_addr += (1 << voodoo->params.tex_shift[tmu][lod]); - base += (1 << shift); - } - break; - - case TEX_ARGB8332: - for (y = 0; y < voodoo->params.tex_h_mask[tmu][lod]+1; y++) - { - for (x = 0; x < voodoo->params.tex_w_mask[tmu][lod]+1; x++) - { - uint16_t dat = *(uint16_t *)&voodoo->tex_mem[tmu][(tex_addr + x*2) & voodoo->texture_mask]; - - base[x] = makergba(rgb332[dat & 0xff].r, rgb332[dat & 0xff].g, rgb332[dat & 0xff].b, dat >> 8); - } - tex_addr += (1 << (voodoo->params.tex_shift[tmu][lod]+1)); - base += (1 << shift); - } - break; - - case TEX_A8Y4I2Q2: - pal = voodoo->ncc_lookup[tmu][(voodoo->params.textureMode[tmu] & TEXTUREMODE_NCC_SEL) ? 1 : 0]; - for (y = 0; y < voodoo->params.tex_h_mask[tmu][lod]+1; y++) - { - for (x = 0; x < voodoo->params.tex_w_mask[tmu][lod]+1; x++) - { - uint16_t dat = *(uint16_t *)&voodoo->tex_mem[tmu][(tex_addr + x*2) & voodoo->texture_mask]; - - base[x] = makergba(pal[dat & 0xff].rgba.r, pal[dat & 0xff].rgba.g, pal[dat & 0xff].rgba.b, dat >> 8); - } - tex_addr += (1 << (voodoo->params.tex_shift[tmu][lod]+1)); - base += (1 << shift); - } - break; - - case TEX_R5G6B5: - for (y = 0; y < voodoo->params.tex_h_mask[tmu][lod]+1; y++) - { - for (x = 0; x < voodoo->params.tex_w_mask[tmu][lod]+1; x++) - { - uint16_t dat = *(uint16_t *)&voodoo->tex_mem[tmu][(tex_addr + x*2) & voodoo->texture_mask]; - - base[x] = makergba(rgb565[dat].r, rgb565[dat].g, rgb565[dat].b, 0xff); - } - tex_addr += (1 << (voodoo->params.tex_shift[tmu][lod]+1)); - base += (1 << shift); - } - break; - - case TEX_ARGB1555: - for (y = 0; y < voodoo->params.tex_h_mask[tmu][lod]+1; y++) - { - for (x = 0; x < voodoo->params.tex_w_mask[tmu][lod]+1; x++) - { - uint16_t dat = *(uint16_t *)&voodoo->tex_mem[tmu][(tex_addr + x*2) & voodoo->texture_mask]; - - base[x] = makergba(argb1555[dat].r, argb1555[dat].g, argb1555[dat].b, argb1555[dat].a); - } - tex_addr += (1 << (voodoo->params.tex_shift[tmu][lod]+1)); - base += (1 << shift); - } - break; - - case TEX_ARGB4444: - for (y = 0; y < voodoo->params.tex_h_mask[tmu][lod]+1; y++) - { - for (x = 0; x < voodoo->params.tex_w_mask[tmu][lod]+1; x++) - { - uint16_t dat = *(uint16_t *)&voodoo->tex_mem[tmu][(tex_addr + x*2) & voodoo->texture_mask]; - - base[x] = makergba(argb4444[dat].r, argb4444[dat].g, argb4444[dat].b, argb4444[dat].a); - } - tex_addr += (1 << (voodoo->params.tex_shift[tmu][lod]+1)); - base += (1 << shift); - } - break; - - case TEX_A8I8: - for (y = 0; y < voodoo->params.tex_h_mask[tmu][lod]+1; y++) - { - for (x = 0; x < voodoo->params.tex_w_mask[tmu][lod]+1; x++) - { - uint16_t dat = *(uint16_t *)&voodoo->tex_mem[tmu][(tex_addr + x*2) & voodoo->texture_mask]; - - base[x] = makergba(dat & 0xff, dat & 0xff, dat & 0xff, dat >> 8); - } - tex_addr += (1 << (voodoo->params.tex_shift[tmu][lod]+1)); - base += (1 << shift); - } - break; - - case TEX_APAL88: - pal = voodoo->palette[tmu]; - for (y = 0; y < voodoo->params.tex_h_mask[tmu][lod]+1; y++) - { - for (x = 0; x < voodoo->params.tex_w_mask[tmu][lod]+1; x++) - { - uint16_t dat = *(uint16_t *)&voodoo->tex_mem[tmu][(tex_addr + x*2) & voodoo->texture_mask]; - - base[x] = makergba(pal[dat & 0xff].rgba.r, pal[dat & 0xff].rgba.g, pal[dat & 0xff].rgba.b, dat >> 8); - } - tex_addr += (1 << (voodoo->params.tex_shift[tmu][lod]+1)); - base += (1 << shift); - } - break; + if (voodoo->params.tLOD[tmu] & LOD_TMULTIBASEADDR) { + switch (tex_lod) { + case 0: + base = voodoo->params.texBaseAddr[tmu]; + break; + case 1: + base = voodoo->params.texBaseAddr1[tmu]; + break; + case 2: + base = voodoo->params.texBaseAddr2[tmu]; + break; default: - fatal("Unknown texture format %i\n", params->tformat[tmu]); + base = voodoo->params.texBaseAddr38[tmu]; + break; + } } + } } + } - voodoo->texture_cache[tmu][c].is16 = voodoo->params.tformat[tmu] & 8; - - if (params->tformat[tmu] == TEX_PAL8 || params->tformat[tmu] == TEX_APAL8 || params->tformat[tmu] == TEX_APAL88) - voodoo->texture_cache[tmu][c].palette_checksum = palette_checksum; - else - voodoo->texture_cache[tmu][c].palette_checksum = 0; - - if (lod_min == 0) - { - voodoo->texture_cache[tmu][c].addr_start[0] = voodoo->params.tex_base[tmu][0]; - voodoo->texture_cache[tmu][c].addr_end[0] = voodoo->params.tex_end[tmu][0]; - } - else - voodoo->texture_cache[tmu][c].addr_start[0] = voodoo->texture_cache[tmu][c].addr_end[0] = 0; - - if (lod_min <= 1 && lod_max >= 1) - { - voodoo->texture_cache[tmu][c].addr_start[1] = voodoo->params.tex_base[tmu][1]; - voodoo->texture_cache[tmu][c].addr_end[1] = voodoo->params.tex_end[tmu][1]; - } - else - voodoo->texture_cache[tmu][c].addr_start[1] = voodoo->texture_cache[tmu][c].addr_end[1] = 0; - - if (lod_min <= 2 && lod_max >= 2) - { - voodoo->texture_cache[tmu][c].addr_start[2] = voodoo->params.tex_base[tmu][2]; - voodoo->texture_cache[tmu][c].addr_end[2] = voodoo->params.tex_end[tmu][2]; - } - else - voodoo->texture_cache[tmu][c].addr_start[2] = voodoo->texture_cache[tmu][c].addr_end[2] = 0; - - if (lod_max >= 3) - { - voodoo->texture_cache[tmu][c].addr_start[3] = voodoo->params.tex_base[tmu][(lod_min > 3) ? lod_min : 3]; - voodoo->texture_cache[tmu][c].addr_end[3] = voodoo->params.tex_end[tmu][(lod_max < 8) ? lod_max : 8]; - } - else - voodoo->texture_cache[tmu][c].addr_start[3] = voodoo->texture_cache[tmu][c].addr_end[3] = 0; - - - for (d = 0; d < 4; d++) - { - addr = voodoo->texture_cache[tmu][c].addr_start[d]; - addr_end = voodoo->texture_cache[tmu][c].addr_end[d]; - - if (addr_end != 0) - { - for (; addr <= addr_end; addr += (1 << TEX_DIRTY_SHIFT)) - voodoo->texture_present[tmu][(addr & voodoo->texture_mask) >> TEX_DIRTY_SHIFT] = 1; - } - } - - params->tex_entry[tmu] = c; - voodoo->texture_cache[tmu][c].refcount++; + voodoo->params.tex_width[tmu] = width; } -void flush_texture_cache(voodoo_t *voodoo, uint32_t dirty_addr, int tmu) +void +voodoo_recalc_tex3(voodoo_t *voodoo, int tmu) { - int wait_for_idle = 0; - int c; + int aspect = (voodoo->params.tLOD[tmu] >> 21) & 3; + int width = 256; + int height = 256; + int shift = 8; + int lod; + uint32_t base = voodoo->params.texBaseAddr[tmu]; + uint32_t offset = 0; + int tex_lod = 0; + uint32_t offsets[LOD_MAX + 3]; + int widths[LOD_MAX + 3]; + int heights[LOD_MAX + 3]; + int shifts[LOD_MAX + 3]; - memset(voodoo->texture_present[tmu], 0, sizeof(voodoo->texture_present[0])); -// voodoo_texture_log("Evict %08x %i\n", dirty_addr, sizeof(voodoo->texture_present)); - for (c = 0; c < TEX_CACHE_MAX; c++) - { - if (voodoo->texture_cache[tmu][c].base != -1) - { - int d; + if (voodoo->params.tLOD[tmu] & LOD_S_IS_WIDER) + height >>= aspect; + else { + width >>= aspect; + shift -= aspect; + } - for (d = 0; d < 4; d++) - { - int addr_start = voodoo->texture_cache[tmu][c].addr_start[d]; - int addr_end = voodoo->texture_cache[tmu][c].addr_end[d]; + for (lod = 0; lod <= LOD_MAX + 2; lod++) { + offsets[lod] = offset; + widths[lod] = width >> lod; + heights[lod] = height >> lod; + shifts[lod] = shift - lod; - if (addr_end != 0) - { - int addr_start_masked = addr_start & voodoo->texture_mask & ~0x3ff; - int addr_end_masked = ((addr_end & voodoo->texture_mask) + 0x3ff) & ~0x3ff; + if (!widths[lod]) + widths[lod] = 1; + if (!heights[lod]) + heights[lod] = 1; + if (shifts[lod] < 0) + shifts[lod] = 0; - if (addr_end_masked < addr_start_masked) - addr_end_masked = voodoo->texture_mask+1; - if (dirty_addr >= addr_start_masked && dirty_addr < addr_end_masked) - { -// voodoo_texture_log(" Evict texture %i %08x\n", c, voodoo->texture_cache[tmu][c].base); - - if (voodoo->texture_cache[tmu][c].refcount != voodoo->texture_cache[tmu][c].refcount_r[0] || - (voodoo->render_threads == 2 && voodoo->texture_cache[tmu][c].refcount != voodoo->texture_cache[tmu][c].refcount_r[1])) - wait_for_idle = 1; - - voodoo->texture_cache[tmu][c].base = -1; - } - else - { - for (; addr_start <= addr_end; addr_start += (1 << TEX_DIRTY_SHIFT)) - voodoo->texture_present[tmu][(addr_start & voodoo->texture_mask) >> TEX_DIRTY_SHIFT] = 1; - } - } - } - } + if (!(voodoo->params.tLOD[tmu] & LOD_SPLIT) || ((lod & 1) && (voodoo->params.tLOD[tmu] & LOD_ODD)) || (!(lod & 1) && !(voodoo->params.tLOD[tmu] & LOD_ODD))) { + if (voodoo->params.tformat[tmu] & 8) + offset += (width >> lod) * (height >> lod) * 2; + else + offset += (width >> lod) * (height >> lod); } - if (wait_for_idle) - voodoo_wait_for_render_thread_idle(voodoo); -} + } -void voodoo_tex_writel(uint32_t addr, uint32_t val, void *p) -{ - int lod, s, t; - voodoo_t *voodoo = (voodoo_t *)p; - int tmu; + if ((voodoo->params.textureMode[tmu] & TEXTUREMODE_TRILINEAR) && (voodoo->params.tLOD[tmu] & LOD_ODD)) + tex_lod++; /*Skip LOD 0*/ - if (addr & 0x400000) - return; /*TREX != 0*/ - - tmu = (addr & 0x200000) ? 1 : 0; - - if (tmu && !voodoo->dual_tmus) - return; - - if (voodoo->type < VOODOO_BANSHEE) - { - if (!(voodoo->params.tformat[tmu] & 8) && voodoo->type >= VOODOO_BANSHEE) - { - lod = (addr >> 16) & 0xf; - t = (addr >> 8) & 0xff; - } - else - { - lod = (addr >> 17) & 0xf; - t = (addr >> 9) & 0xff; - } - if (voodoo->params.tformat[tmu] & 8) - s = (addr >> 1) & 0xfe; - else - { - if ((voodoo->params.textureMode[tmu] & (1 << 31)) || voodoo->type >= VOODOO_BANSHEE) - s = addr & 0xfc; - else - s = (addr >> 1) & 0xfc; - } - if (lod > LOD_MAX) - return; - -// if (addr >= 0x200000) -// return; - - if (voodoo->params.tformat[tmu] & 8) - addr = voodoo->params.tex_base[tmu][lod] + s*2 + (t << voodoo->params.tex_shift[tmu][lod])*2; - else - addr = voodoo->params.tex_base[tmu][lod] + s + (t << voodoo->params.tex_shift[tmu][lod]); +#if 0 + voodoo_texture_log("TMU %i: %08x\n", tmu, voodoo->params.textureMode[tmu]); +#endif + for (lod = 0; lod <= LOD_MAX + 1; lod++) { + if (voodoo->params.tLOD[tmu] & LOD_TMULTIBASEADDR) { + switch (tex_lod) { + case 0: + base = voodoo->params.texBaseAddr[tmu]; + break; + case 1: + base = voodoo->params.texBaseAddr1[tmu]; + break; + case 2: + base = voodoo->params.texBaseAddr2[tmu]; + break; + default: + base = voodoo->params.texBaseAddr38[tmu]; + break; + } } + + voodoo->params.tex_base[tmu][lod] = base + offsets[tex_lod]; + if (voodoo->params.tformat[tmu] & 8) + voodoo->params.tex_end[tmu][lod] = base + offsets[tex_lod] + (widths[tex_lod] * heights[tex_lod] * 2); else - addr = (addr & 0x1ffffc) + voodoo->params.tex_base[tmu][0]; + voodoo->params.tex_end[tmu][lod] = base + offsets[tex_lod] + (widths[tex_lod] * heights[tex_lod]); + voodoo->params.tex_w_mask[tmu][lod] = widths[tex_lod] - 1; + voodoo->params.tex_w_nmask[tmu][lod] = ~(widths[tex_lod] - 1); + voodoo->params.tex_h_mask[tmu][lod] = heights[tex_lod] - 1; + voodoo->params.tex_shift[tmu][lod] = shifts[tex_lod]; + voodoo->params.tex_lod[tmu][lod] = tex_lod; - if (voodoo->texture_present[tmu][(addr & voodoo->texture_mask) >> TEX_DIRTY_SHIFT]) - { -// voodoo_texture_log("texture_present at %08x %i\n", addr, (addr & voodoo->texture_mask) >> TEX_DIRTY_SHIFT); - flush_texture_cache(voodoo, addr & voodoo->texture_mask, tmu); + if (!(voodoo->params.textureMode[tmu] & TEXTUREMODE_TRILINEAR) || ((lod & 1) && (voodoo->params.tLOD[tmu] & LOD_ODD)) || (!(lod & 1) && !(voodoo->params.tLOD[tmu] & LOD_ODD))) { + if (!(voodoo->params.tLOD[tmu] & LOD_ODD) || lod != 0) { + if (voodoo->params.textureMode[tmu] & TEXTUREMODE_TRILINEAR) + tex_lod += 2; + else + tex_lod++; + } } - if (voodoo->type == VOODOO_3 && voodoo->texture_present[tmu^1][(addr & voodoo->texture_mask) >> TEX_DIRTY_SHIFT]) - { -// voodoo_texture_log("texture_present at %08x %i\n", addr, (addr & voodoo->texture_mask) >> TEX_DIRTY_SHIFT); - flush_texture_cache(voodoo, addr & voodoo->texture_mask, tmu^1); - } - *(uint32_t *)(&voodoo->tex_mem[tmu][addr & voodoo->texture_mask]) = val; + } + + voodoo->params.tex_width[tmu] = width; +} + +#define makergba(r, g, b, a) ((b) | ((g) << 8) | ((r) << 16) | ((a) << 24)) + +void +voodoo_use_texture(voodoo_t *voodoo, voodoo_params_t *params, int tmu) +{ + int c; + int lod_min; + int lod_max; + uint32_t addr = 0; + uint32_t addr_end; + uint32_t palette_checksum; + + lod_min = (params->tLOD[tmu] >> 2) & 15; + lod_max = (params->tLOD[tmu] >> 8) & 15; + + if (params->tformat[tmu] == TEX_PAL8 || params->tformat[tmu] == TEX_APAL8 || params->tformat[tmu] == TEX_APAL88) { + if (voodoo->palette_dirty[tmu]) { + palette_checksum = 0; + + for (c = 0; c < 256; c++) + palette_checksum ^= voodoo->palette[tmu][c].u; + + voodoo->palette_checksum[tmu] = palette_checksum; + voodoo->palette_dirty[tmu] = 0; + } else + palette_checksum = voodoo->palette_checksum[tmu]; + } else + palette_checksum = 0; + + if ((voodoo->params.tLOD[tmu] & LOD_SPLIT) && (voodoo->params.tLOD[tmu] & LOD_ODD) && (voodoo->params.tLOD[tmu] & LOD_TMULTIBASEADDR)) + addr = params->texBaseAddr1[tmu]; + else + addr = params->texBaseAddr[tmu]; + + /*Try to find texture in cache*/ + for (c = 0; c < TEX_CACHE_MAX; c++) { + if (voodoo->texture_cache[tmu][c].base == addr && voodoo->texture_cache[tmu][c].tLOD == (params->tLOD[tmu] & 0xf00fff) && voodoo->texture_cache[tmu][c].palette_checksum == palette_checksum) { + params->tex_entry[tmu] = c; + voodoo->texture_cache[tmu][c].refcount++; + return; + } + } + + /*Texture not found, search for unused texture*/ + do { + for (c = 0; c < TEX_CACHE_MAX; c++) { + voodoo->texture_last_removed++; + voodoo->texture_last_removed &= (TEX_CACHE_MAX - 1); + if (voodoo->texture_cache[tmu][voodoo->texture_last_removed].refcount == voodoo->texture_cache[tmu][voodoo->texture_last_removed].refcount_r[0] && (voodoo->render_threads == 1 || voodoo->texture_cache[tmu][voodoo->texture_last_removed].refcount == voodoo->texture_cache[tmu][voodoo->texture_last_removed].refcount_r[1])) + break; + } + if (c == TEX_CACHE_MAX) + voodoo_wait_for_render_thread_idle(voodoo); + } while (c == TEX_CACHE_MAX); + if (c == TEX_CACHE_MAX) + fatal("Texture cache full!\n"); + + c = voodoo->texture_last_removed; + + if ((voodoo->params.tLOD[tmu] & LOD_SPLIT) && (voodoo->params.tLOD[tmu] & LOD_ODD) && (voodoo->params.tLOD[tmu] & LOD_TMULTIBASEADDR)) + voodoo->texture_cache[tmu][c].base = params->texBaseAddr1[tmu]; + else + voodoo->texture_cache[tmu][c].base = params->texBaseAddr[tmu]; + voodoo->texture_cache[tmu][c].tLOD = params->tLOD[tmu] & 0xf00fff; + + lod_min = (params->tLOD[tmu] >> 2) & 15; + lod_max = (params->tLOD[tmu] >> 8) & 15; +#if 0 + voodoo_texture_log(" add new texture to %i tformat=%i %08x LOD=%i-%i tmu=%i\n", c, voodoo->params.tformat[tmu], params->texBaseAddr[tmu], lod_min, lod_max, tmu); +#endif + lod_min = MIN(lod_min, 8); + lod_max = MIN(lod_max, 8); + for (int lod = lod_min; lod <= lod_max; lod++) { + uint32_t *base = &voodoo->texture_cache[tmu][c].data[texture_offset[lod]]; + uint32_t tex_addr = params->tex_base[tmu][lod] & voodoo->texture_mask; + int x; + int y; + int shift = 8 - params->tex_lod[tmu][lod]; + const rgba_u *pal; + +#if 0 + voodoo_texture_log(" LOD %i : %08x - %08x %i %i,%i\n", lod, params->tex_base[tmu][lod] & voodoo->texture_mask, addr, voodoo->params.tformat[tmu], voodoo->params.tex_w_mask[tmu][lod],voodoo->params.tex_h_mask[tmu][lod]); +#endif + + switch (params->tformat[tmu]) { + case TEX_RGB332: + for (y = 0; y < voodoo->params.tex_h_mask[tmu][lod] + 1; y++) { + for (x = 0; x < voodoo->params.tex_w_mask[tmu][lod] + 1; x++) { + uint8_t dat = voodoo->tex_mem[tmu][(tex_addr + x) & voodoo->texture_mask]; + + base[x] = makergba(rgb332[dat].r, rgb332[dat].g, rgb332[dat].b, 0xff); + } + tex_addr += (1 << voodoo->params.tex_shift[tmu][lod]); + base += (1 << shift); + } + break; + + case TEX_Y4I2Q2: + pal = voodoo->ncc_lookup[tmu][(voodoo->params.textureMode[tmu] & TEXTUREMODE_NCC_SEL) ? 1 : 0]; + for (y = 0; y < voodoo->params.tex_h_mask[tmu][lod] + 1; y++) { + for (x = 0; x < voodoo->params.tex_w_mask[tmu][lod] + 1; x++) { + uint8_t dat = voodoo->tex_mem[tmu][(tex_addr + x) & voodoo->texture_mask]; + + base[x] = makergba(pal[dat].rgba.r, pal[dat].rgba.g, pal[dat].rgba.b, 0xff); + } + tex_addr += (1 << voodoo->params.tex_shift[tmu][lod]); + base += (1 << shift); + } + break; + + case TEX_A8: + for (y = 0; y < voodoo->params.tex_h_mask[tmu][lod] + 1; y++) { + for (x = 0; x < voodoo->params.tex_w_mask[tmu][lod] + 1; x++) { + uint8_t dat = voodoo->tex_mem[tmu][(tex_addr + x) & voodoo->texture_mask]; + + base[x] = makergba(dat, dat, dat, dat); + } + tex_addr += (1 << voodoo->params.tex_shift[tmu][lod]); + base += (1 << shift); + } + break; + + case TEX_I8: + for (y = 0; y < voodoo->params.tex_h_mask[tmu][lod] + 1; y++) { + for (x = 0; x < voodoo->params.tex_w_mask[tmu][lod] + 1; x++) { + uint8_t dat = voodoo->tex_mem[tmu][(tex_addr + x) & voodoo->texture_mask]; + + base[x] = makergba(dat, dat, dat, 0xff); + } + tex_addr += (1 << voodoo->params.tex_shift[tmu][lod]); + base += (1 << shift); + } + break; + + case TEX_AI8: + for (y = 0; y < voodoo->params.tex_h_mask[tmu][lod] + 1; y++) { + for (x = 0; x < voodoo->params.tex_w_mask[tmu][lod] + 1; x++) { + uint8_t dat = voodoo->tex_mem[tmu][(tex_addr + x) & voodoo->texture_mask]; + + base[x] = makergba((dat & 0x0f) | ((dat << 4) & 0xf0), (dat & 0x0f) | ((dat << 4) & 0xf0), (dat & 0x0f) | ((dat << 4) & 0xf0), (dat & 0xf0) | ((dat >> 4) & 0x0f)); + } + tex_addr += (1 << voodoo->params.tex_shift[tmu][lod]); + base += (1 << shift); + } + break; + + case TEX_PAL8: + pal = voodoo->palette[tmu]; + for (y = 0; y < voodoo->params.tex_h_mask[tmu][lod] + 1; y++) { + for (x = 0; x < voodoo->params.tex_w_mask[tmu][lod] + 1; x++) { + uint8_t dat = voodoo->tex_mem[tmu][(tex_addr + x) & voodoo->texture_mask]; + + base[x] = makergba(pal[dat].rgba.r, pal[dat].rgba.g, pal[dat].rgba.b, 0xff); + } + tex_addr += (1 << voodoo->params.tex_shift[tmu][lod]); + base += (1 << shift); + } + break; + + case TEX_APAL8: + pal = voodoo->palette[tmu]; + for (y = 0; y < voodoo->params.tex_h_mask[tmu][lod] + 1; y++) { + for (x = 0; x < voodoo->params.tex_w_mask[tmu][lod] + 1; x++) { + uint8_t dat = voodoo->tex_mem[tmu][(tex_addr + x) & voodoo->texture_mask]; + + int r = ((pal[dat].rgba.r & 3) << 6) | ((pal[dat].rgba.g & 0xf0) >> 2) | (pal[dat].rgba.r & 3); + int g = ((pal[dat].rgba.g & 0xf) << 4) | ((pal[dat].rgba.b & 0xc0) >> 4) | ((pal[dat].rgba.g & 0xf) >> 2); + int b = ((pal[dat].rgba.b & 0x3f) << 2) | ((pal[dat].rgba.b & 0x30) >> 4); + int a = (pal[dat].rgba.r & 0xfc) | ((pal[dat].rgba.r & 0xc0) >> 6); + + base[x] = makergba(r, g, b, a); + } + tex_addr += (1 << voodoo->params.tex_shift[tmu][lod]); + base += (1 << shift); + } + break; + + case TEX_ARGB8332: + for (y = 0; y < voodoo->params.tex_h_mask[tmu][lod] + 1; y++) { + for (x = 0; x < voodoo->params.tex_w_mask[tmu][lod] + 1; x++) { + uint16_t dat = *(uint16_t *) &voodoo->tex_mem[tmu][(tex_addr + x * 2) & voodoo->texture_mask]; + + base[x] = makergba(rgb332[dat & 0xff].r, rgb332[dat & 0xff].g, rgb332[dat & 0xff].b, dat >> 8); + } + tex_addr += (1 << (voodoo->params.tex_shift[tmu][lod] + 1)); + base += (1 << shift); + } + break; + + case TEX_A8Y4I2Q2: + pal = voodoo->ncc_lookup[tmu][(voodoo->params.textureMode[tmu] & TEXTUREMODE_NCC_SEL) ? 1 : 0]; + for (y = 0; y < voodoo->params.tex_h_mask[tmu][lod] + 1; y++) { + for (x = 0; x < voodoo->params.tex_w_mask[tmu][lod] + 1; x++) { + uint16_t dat = *(uint16_t *) &voodoo->tex_mem[tmu][(tex_addr + x * 2) & voodoo->texture_mask]; + + base[x] = makergba(pal[dat & 0xff].rgba.r, pal[dat & 0xff].rgba.g, pal[dat & 0xff].rgba.b, dat >> 8); + } + tex_addr += (1 << (voodoo->params.tex_shift[tmu][lod] + 1)); + base += (1 << shift); + } + break; + + case TEX_R5G6B5: + for (y = 0; y < voodoo->params.tex_h_mask[tmu][lod] + 1; y++) { + for (x = 0; x < voodoo->params.tex_w_mask[tmu][lod] + 1; x++) { + uint16_t dat = *(uint16_t *) &voodoo->tex_mem[tmu][(tex_addr + x * 2) & voodoo->texture_mask]; + + base[x] = makergba(rgb565[dat].r, rgb565[dat].g, rgb565[dat].b, 0xff); + } + tex_addr += (1 << (voodoo->params.tex_shift[tmu][lod] + 1)); + base += (1 << shift); + } + break; + + case TEX_ARGB1555: + for (y = 0; y < voodoo->params.tex_h_mask[tmu][lod] + 1; y++) { + for (x = 0; x < voodoo->params.tex_w_mask[tmu][lod] + 1; x++) { + uint16_t dat = *(uint16_t *) &voodoo->tex_mem[tmu][(tex_addr + x * 2) & voodoo->texture_mask]; + + base[x] = makergba(argb1555[dat].r, argb1555[dat].g, argb1555[dat].b, argb1555[dat].a); + } + tex_addr += (1 << (voodoo->params.tex_shift[tmu][lod] + 1)); + base += (1 << shift); + } + break; + + case TEX_ARGB4444: + for (y = 0; y < voodoo->params.tex_h_mask[tmu][lod] + 1; y++) { + for (x = 0; x < voodoo->params.tex_w_mask[tmu][lod] + 1; x++) { + uint16_t dat = *(uint16_t *) &voodoo->tex_mem[tmu][(tex_addr + x * 2) & voodoo->texture_mask]; + + base[x] = makergba(argb4444[dat].r, argb4444[dat].g, argb4444[dat].b, argb4444[dat].a); + } + tex_addr += (1 << (voodoo->params.tex_shift[tmu][lod] + 1)); + base += (1 << shift); + } + break; + + case TEX_A8I8: + for (y = 0; y < voodoo->params.tex_h_mask[tmu][lod] + 1; y++) { + for (x = 0; x < voodoo->params.tex_w_mask[tmu][lod] + 1; x++) { + uint16_t dat = *(uint16_t *) &voodoo->tex_mem[tmu][(tex_addr + x * 2) & voodoo->texture_mask]; + + base[x] = makergba(dat & 0xff, dat & 0xff, dat & 0xff, dat >> 8); + } + tex_addr += (1 << (voodoo->params.tex_shift[tmu][lod] + 1)); + base += (1 << shift); + } + break; + + case TEX_APAL88: + pal = voodoo->palette[tmu]; + for (y = 0; y < voodoo->params.tex_h_mask[tmu][lod] + 1; y++) { + for (x = 0; x < voodoo->params.tex_w_mask[tmu][lod] + 1; x++) { + uint16_t dat = *(uint16_t *) &voodoo->tex_mem[tmu][(tex_addr + x * 2) & voodoo->texture_mask]; + + base[x] = makergba(pal[dat & 0xff].rgba.r, pal[dat & 0xff].rgba.g, pal[dat & 0xff].rgba.b, dat >> 8); + } + tex_addr += (1 << (voodoo->params.tex_shift[tmu][lod] + 1)); + base += (1 << shift); + } + break; + + default: + fatal("Unknown texture format %i\n", params->tformat[tmu]); + } + } + + voodoo->texture_cache[tmu][c].is16 = voodoo->params.tformat[tmu] & 8; + + if (params->tformat[tmu] == TEX_PAL8 || params->tformat[tmu] == TEX_APAL8 || params->tformat[tmu] == TEX_APAL88) + voodoo->texture_cache[tmu][c].palette_checksum = palette_checksum; + else + voodoo->texture_cache[tmu][c].palette_checksum = 0; + + if (lod_min == 0) { + voodoo->texture_cache[tmu][c].addr_start[0] = voodoo->params.tex_base[tmu][0]; + voodoo->texture_cache[tmu][c].addr_end[0] = voodoo->params.tex_end[tmu][0]; + } else + voodoo->texture_cache[tmu][c].addr_start[0] = voodoo->texture_cache[tmu][c].addr_end[0] = 0; + + if (lod_min <= 1 && lod_max >= 1) { + voodoo->texture_cache[tmu][c].addr_start[1] = voodoo->params.tex_base[tmu][1]; + voodoo->texture_cache[tmu][c].addr_end[1] = voodoo->params.tex_end[tmu][1]; + } else + voodoo->texture_cache[tmu][c].addr_start[1] = voodoo->texture_cache[tmu][c].addr_end[1] = 0; + + if (lod_min <= 2 && lod_max >= 2) { + voodoo->texture_cache[tmu][c].addr_start[2] = voodoo->params.tex_base[tmu][2]; + voodoo->texture_cache[tmu][c].addr_end[2] = voodoo->params.tex_end[tmu][2]; + } else + voodoo->texture_cache[tmu][c].addr_start[2] = voodoo->texture_cache[tmu][c].addr_end[2] = 0; + + if (lod_max >= 3) { + voodoo->texture_cache[tmu][c].addr_start[3] = voodoo->params.tex_base[tmu][(lod_min > 3) ? lod_min : 3]; + voodoo->texture_cache[tmu][c].addr_end[3] = voodoo->params.tex_end[tmu][(lod_max < 8) ? lod_max : 8]; + } else + voodoo->texture_cache[tmu][c].addr_start[3] = voodoo->texture_cache[tmu][c].addr_end[3] = 0; + + for (uint8_t d = 0; d < 4; d++) { + addr = voodoo->texture_cache[tmu][c].addr_start[d]; + addr_end = voodoo->texture_cache[tmu][c].addr_end[d]; + + if (addr_end != 0) { + for (; addr <= addr_end; addr += (1 << TEX_DIRTY_SHIFT)) + voodoo->texture_present[tmu][(addr & voodoo->texture_mask) >> TEX_DIRTY_SHIFT] = 1; + } + } + + params->tex_entry[tmu] = c; + voodoo->texture_cache[tmu][c].refcount++; +} + +void +flush_texture_cache(voodoo_t *voodoo, uint32_t dirty_addr, int tmu) +{ + int wait_for_idle = 0; + + memset(voodoo->texture_present[tmu], 0, sizeof(voodoo->texture_present[0])); +#if 0 + voodoo_texture_log("Evict %08x %i\n", dirty_addr, sizeof(voodoo->texture_present)); +#endif + for (uint8_t c = 0; c < TEX_CACHE_MAX; c++) { + if (voodoo->texture_cache[tmu][c].base != -1) { + for (uint8_t d = 0; d < 4; d++) { + int addr_start = voodoo->texture_cache[tmu][c].addr_start[d]; + int addr_end = voodoo->texture_cache[tmu][c].addr_end[d]; + + if (addr_end != 0) { + int addr_start_masked = addr_start & voodoo->texture_mask & ~0x3ff; + int addr_end_masked = ((addr_end & voodoo->texture_mask) + 0x3ff) & ~0x3ff; + + if (addr_end_masked < addr_start_masked) + addr_end_masked = voodoo->texture_mask + 1; + if (dirty_addr >= addr_start_masked && dirty_addr < addr_end_masked) { +#if 0 + voodoo_texture_log(" Evict texture %i %08x\n", c, voodoo->texture_cache[tmu][c].base); +#endif + + if (voodoo->texture_cache[tmu][c].refcount != voodoo->texture_cache[tmu][c].refcount_r[0] || (voodoo->render_threads == 2 && voodoo->texture_cache[tmu][c].refcount != voodoo->texture_cache[tmu][c].refcount_r[1])) + wait_for_idle = 1; + + voodoo->texture_cache[tmu][c].base = -1; + } else { + for (; addr_start <= addr_end; addr_start += (1 << TEX_DIRTY_SHIFT)) + voodoo->texture_present[tmu][(addr_start & voodoo->texture_mask) >> TEX_DIRTY_SHIFT] = 1; + } + } + } + } + } + if (wait_for_idle) + voodoo_wait_for_render_thread_idle(voodoo); +} + +void +voodoo_tex_writel(uint32_t addr, uint32_t val, void *priv) +{ + int lod; + int s; + int t; + voodoo_t *voodoo = (voodoo_t *) priv; + int tmu; + + if (addr & 0x400000) + return; /*TREX != 0*/ + + tmu = (addr & 0x200000) ? 1 : 0; + + if (tmu && !voodoo->dual_tmus) + return; + + if (voodoo->type < VOODOO_BANSHEE) { + if (!(voodoo->params.tformat[tmu] & 8) && voodoo->type >= VOODOO_BANSHEE) { + lod = (addr >> 16) & 0xf; + t = (addr >> 8) & 0xff; + } else { + lod = (addr >> 17) & 0xf; + t = (addr >> 9) & 0xff; + } + if (voodoo->params.tformat[tmu] & 8) + s = (addr >> 1) & 0xfe; + else { + if ((voodoo->params.textureMode[tmu] & (1 << 31)) || voodoo->type >= VOODOO_BANSHEE) + s = addr & 0xfc; + else + s = (addr >> 1) & 0xfc; + } + if (lod > LOD_MAX) + return; + +#if 0 + if (addr >= 0x200000) + return; +#endif + + if (voodoo->params.tformat[tmu] & 8) + addr = voodoo->params.tex_base[tmu][lod] + s * 2 + (t << voodoo->params.tex_shift[tmu][lod]) * 2; + else + addr = voodoo->params.tex_base[tmu][lod] + s + (t << voodoo->params.tex_shift[tmu][lod]); + } else + addr = (addr & 0x1ffffc) + voodoo->params.tex_base[tmu][0]; + + if (voodoo->texture_present[tmu][(addr & voodoo->texture_mask) >> TEX_DIRTY_SHIFT]) { +#if 0 + voodoo_texture_log("texture_present at %08x %i\n", addr, (addr & voodoo->texture_mask) >> TEX_DIRTY_SHIFT); +#endif + flush_texture_cache(voodoo, addr & voodoo->texture_mask, tmu); + } + if (voodoo->type == VOODOO_3 && voodoo->texture_present[tmu ^ 1][(addr & voodoo->texture_mask) >> TEX_DIRTY_SHIFT]) { +#if 0 + voodoo_texture_log("texture_present at %08x %i\n", addr, (addr & voodoo->texture_mask) >> TEX_DIRTY_SHIFT); +#endif + flush_texture_cache(voodoo, addr & voodoo->texture_mask, tmu ^ 1); + } + *(uint32_t *) (&voodoo->tex_mem[tmu][addr & voodoo->texture_mask]) = val; } diff --git a/src/video/vid_wy700.c b/src/video/vid_wy700.c index 0b5f1dd83..600fa21a8 100644 --- a/src/video/vid_wy700.c +++ b/src/video/vid_wy700.c @@ -1,20 +1,20 @@ /* - * 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. + * 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. + * This file is part of the 86Box distribution. * - * Wyse-700 emulation. + * Wyse-700 emulation. * * * - * Authors: Sarah Walker, - * Miran Grca, + * Authors: Sarah Walker, + * Miran Grca, * - * Copyright 2008-2018 Sarah Walker. - * Copyright 2016-2018 Miran Grca. + * Copyright 2008-2018 Sarah Walker. + * Copyright 2016-2018 Miran Grca. */ #include #include @@ -28,27 +28,25 @@ #include <86box/mem.h> #include <86box/device.h> #include <86box/video.h> - +#include <86box/plat_unused.h> #define WY700_XSIZE 1280 #define WY700_YSIZE 800 - void updatewindowsize(int x, int y); - /* The Wyse 700 is an unusual video card. Though it has an MC6845 CRTC, this * is not exposed directly to the host PC. Instead, the CRTC is controlled by - * an MC68705P3 microcontroller. + * an MC68705P3 microcontroller. * - * Rather than emulate the real CRTC, I'm writing this as more or less a + * Rather than emulate the real CRTC, I'm writing this as more or less a * fixed-frequency card with a 1280x800 display, and scaling its selection * of modes to that window. * - * By default, the card responds to both the CGA and MDA I/O and memory + * By default, the card responds to both the CGA and MDA I/O and memory * ranges. Either range can be disabled by means of jumpers; this allows - * the Wy700 to coexist with a CGA or MDA. - * + * the Wy700 to coexist with a CGA or MDA. + * * wy700->wy700_mode indicates which of the supported video modes is in use: * * 0x00: 40x 25 text (CGA compatible) [32x32 character cell] @@ -67,9 +65,9 @@ void updatewindowsize(int x, int y); /* What works (or appears to) : * MDA/CGA 80x25 text mode - * CGA 40x25 text mode - * CGA 640x200 graphics mode - * CGA 320x200 graphics mode + * CGA 40x25 text mode + * CGA 640x200 graphics mode + * CGA 320x200 graphics mode * Hi-res graphics modes * Font selection * Display enable / disable @@ -81,145 +79,136 @@ void updatewindowsize(int x, int y); * - Cursor detach (commands 4 and 5) */ - /* The microcontroller sets up the real CRTC with one of five fixed mode - * definitions. As written, this is a fairly simplistic emulation that - * doesn't attempt to closely follow the actual working of the CRTC; but I've + * definitions. As written, this is a fairly simplistic emulation that + * doesn't attempt to closely follow the actual working of the CRTC; but I've * included the definitions here for information. */ -static uint8_t mode_1280x800[] = -{ - 0x31, /* Horizontal total */ - 0x28, /* Horizontal displayed */ - 0x29, /* Horizontal sync position */ - 0x06, /* Horizontal sync width */ - 0x1b, /* Vertical total */ - 0x00, /* Vertical total adjust */ - 0x19, /* Vertical displayed */ - 0x1a, /* Vsync position */ - 0x03, /* Interlace and skew */ - 0x0f, /* Maximum raster address */ +static uint8_t mode_1280x800[] = { + 0x31, /* Horizontal total */ + 0x28, /* Horizontal displayed */ + 0x29, /* Horizontal sync position */ + 0x06, /* Horizontal sync width */ + 0x1b, /* Vertical total */ + 0x00, /* Vertical total adjust */ + 0x19, /* Vertical displayed */ + 0x1a, /* Vsync position */ + 0x03, /* Interlace and skew */ + 0x0f, /* Maximum raster address */ }; -static uint8_t mode_1280x400[] = -{ - 0x31, /* Horizontal total */ - 0x28, /* Horizontal displayed */ - 0x29, /* Horizontal sync position */ - 0x06, /* Horizontal sync width */ - 0x1b, /* Vertical total */ - 0x00, /* Vertical total adjust */ - 0x19, /* Vertical displayed */ - 0x1a, /* Vsync position */ - 0x01, /* Interlace and skew */ - 0x0f, /* Maximum raster address */ +static uint8_t mode_1280x400[] = { + 0x31, /* Horizontal total */ + 0x28, /* Horizontal displayed */ + 0x29, /* Horizontal sync position */ + 0x06, /* Horizontal sync width */ + 0x1b, /* Vertical total */ + 0x00, /* Vertical total adjust */ + 0x19, /* Vertical displayed */ + 0x1a, /* Vsync position */ + 0x01, /* Interlace and skew */ + 0x0f, /* Maximum raster address */ }; -static uint8_t mode_640x400[] = -{ - 0x18, /* Horizontal total */ - 0x14, /* Horizontal displayed */ - 0x14, /* Horizontal sync position */ - 0x03, /* Horizontal sync width */ - 0x1b, /* Vertical total */ - 0x00, /* Vertical total adjust */ - 0x19, /* Vertical displayed */ - 0x1a, /* Vsync position */ - 0x01, /* Interlace and skew */ - 0x0f, /* Maximum raster address */ +static uint8_t mode_640x400[] = { + 0x18, /* Horizontal total */ + 0x14, /* Horizontal displayed */ + 0x14, /* Horizontal sync position */ + 0x03, /* Horizontal sync width */ + 0x1b, /* Vertical total */ + 0x00, /* Vertical total adjust */ + 0x19, /* Vertical displayed */ + 0x1a, /* Vsync position */ + 0x01, /* Interlace and skew */ + 0x0f, /* Maximum raster address */ }; -static uint8_t mode_640x200[] = -{ - 0x18, /* Horizontal total */ - 0x14, /* Horizontal displayed */ - 0x14, /* Horizontal sync position */ - 0xff, /* Horizontal sync width */ - 0x37, /* Vertical total */ - 0x00, /* Vertical total adjust */ - 0x32, /* Vertical displayed */ - 0x34, /* Vsync position */ - 0x03, /* Interlace and skew */ - 0x07, /* Maximum raster address */ +static uint8_t mode_640x200[] = { + 0x18, /* Horizontal total */ + 0x14, /* Horizontal displayed */ + 0x14, /* Horizontal sync position */ + 0xff, /* Horizontal sync width */ + 0x37, /* Vertical total */ + 0x00, /* Vertical total adjust */ + 0x32, /* Vertical displayed */ + 0x34, /* Vsync position */ + 0x03, /* Interlace and skew */ + 0x07, /* Maximum raster address */ }; -static uint8_t mode_80x24[] = -{ - 0x31, /* Horizontal total */ - 0x28, /* Horizontal displayed */ - 0x2A, /* Horizontal sync position */ - 0xff, /* Horizontal sync width */ - 0x1b, /* Vertical total */ - 0x00, /* Vertical total adjust */ - 0x19, /* Vertical displayed */ - 0x1a, /* Vsync position */ - 0x01, /* Interlace and skew */ - 0x0f, /* Maximum raster address */ +static uint8_t mode_80x24[] = { + 0x31, /* Horizontal total */ + 0x28, /* Horizontal displayed */ + 0x2A, /* Horizontal sync position */ + 0xff, /* Horizontal sync width */ + 0x1b, /* Vertical total */ + 0x00, /* Vertical total adjust */ + 0x19, /* Vertical displayed */ + 0x1a, /* Vsync position */ + 0x01, /* Interlace and skew */ + 0x0f, /* Maximum raster address */ }; -static uint8_t mode_40x24[] = -{ - 0x18, /* Horizontal total */ - 0x14, /* Horizontal displayed */ - 0x15, /* Horizontal sync position */ - 0xff, /* Horizontal sync width */ - 0x1b, /* Vertical total */ - 0x00, /* Vertical total adjust */ - 0x19, /* Vertical displayed */ - 0x1a, /* Vsync position */ - 0x01, /* Interlace and skew */ - 0x0f, /* Maximum raster address */ +static uint8_t mode_40x24[] = { + 0x18, /* Horizontal total */ + 0x14, /* Horizontal displayed */ + 0x15, /* Horizontal sync position */ + 0xff, /* Horizontal sync width */ + 0x1b, /* Vertical total */ + 0x00, /* Vertical total adjust */ + 0x19, /* Vertical displayed */ + 0x1a, /* Vsync position */ + 0x01, /* Interlace and skew */ + 0x0f, /* Maximum raster address */ }; - /* Font ROM: Two fonts, each containing 256 characters, 16x16 pixels */ extern uint8_t fontdatw[512][32]; -typedef struct wy700_t -{ - mem_mapping_t mapping; +typedef struct wy700_t { + mem_mapping_t mapping; - /* The microcontroller works by watching four ports: - * 0x3D8 / 0x3B8 (mode control register) - * 0x3DD (top scanline address) - * 0x3DF (Wy700 control register) - * CRTC reg 14 (cursor location high) - * - * It will do nothing until one of these registers is touched. When - * one is, it then reconfigures the internal 6845 based on what it - * sees. - */ - uint8_t last_03D8; /* Copies of values written to the listed */ - uint8_t last_03DD; /* I/O ports */ - uint8_t last_03DF; - uint8_t last_crtc_0E; + /* The microcontroller works by watching four ports: + * 0x3D8 / 0x3B8 (mode control register) + * 0x3DD (top scanline address) + * 0x3DF (Wy700 control register) + * CRTC reg 14 (cursor location high) + * + * It will do nothing until one of these registers is touched. When + * one is, it then reconfigures the internal 6845 based on what it + * sees. + */ + uint8_t last_03D8; /* Copies of values written to the listed */ + uint8_t last_03DD; /* I/O ports */ + uint8_t last_03DF; + uint8_t last_crtc_0E; - uint8_t cga_crtc[32]; /* The 'CRTC' as the host PC sees it */ - uint8_t real_crtc[32]; /* The internal CRTC as the microcontroller */ - /* sees it */ - int cga_crtcreg; /* Current CRTC register */ - uint16_t wy700_base; /* Framebuffer base address (native modes) */ - uint8_t wy700_control; /* Native control / command register */ - uint8_t wy700_mode; /* Current mode (see list at top of file) */ - uint8_t cga_ctrl; /* Emulated MDA/CGA control register */ - uint8_t cga_colour; /* Emulated CGA colour register (ignored) */ + uint8_t cga_crtc[32]; /* The 'CRTC' as the host PC sees it */ + uint8_t real_crtc[32]; /* The internal CRTC as the microcontroller */ + /* sees it */ + int cga_crtcreg; /* Current CRTC register */ + uint16_t wy700_base; /* Framebuffer base address (native modes) */ + uint8_t wy700_control; /* Native control / command register */ + uint8_t wy700_mode; /* Current mode (see list at top of file) */ + uint8_t cga_ctrl; /* Emulated MDA/CGA control register */ + uint8_t cga_colour; /* Emulated CGA colour register (ignored) */ - uint8_t mda_stat; /* MDA status (IN 0x3BA) */ - uint8_t cga_stat; /* CGA status (IN 0x3DA) */ + uint8_t mda_stat; /* MDA status (IN 0x3BA) */ + uint8_t cga_stat; /* CGA status (IN 0x3DA) */ - int font; /* Current font, 0 or 1 */ - int enabled; /* Display enabled, 0 or 1 */ - int detach; /* Detach cursor, 0 or 1 */ + int font; /* Current font, 0 or 1 */ + int enabled; /* Display enabled, 0 or 1 */ + int detach; /* Detach cursor, 0 or 1 */ - uint64_t dispontime, dispofftime; - pc_timer_t timer; - - int linepos, displine; - int vc; - int dispon, blink; - int vsynctime; + uint64_t dispontime, dispofftime; + pc_timer_t timer; - uint8_t *vram; + int linepos, displine; + int vc; + int dispon, blink; + int vsynctime; + + uint8_t *vram; } wy700_t; /* Mapping of attributes to colours, in CGA emulation... */ @@ -227,796 +216,796 @@ static int cgacols[256][2][2]; /* ... and MDA emulation. */ static int mdacols[256][2][2]; -void wy700_recalctimings(wy700_t *wy700); -void wy700_write(uint32_t addr, uint8_t val, void *p); -uint8_t wy700_read(uint32_t addr, void *p); -void wy700_checkchanges(wy700_t *wy700); +void wy700_recalctimings(wy700_t *wy700); +void wy700_write(uint32_t addr, uint8_t val, void *priv); +uint8_t wy700_read(uint32_t addr, void *priv); +void wy700_checkchanges(wy700_t *wy700); -static video_timings_t timing_wy700 = {VIDEO_ISA, 8, 16, 32, 8, 16, 32}; +static video_timings_t timing_wy700 = { .type = VIDEO_ISA, .write_b = 8, .write_w = 16, .write_l = 32, .read_b = 8, .read_w = 16, .read_l = 32 }; - -void wy700_out(uint16_t addr, uint8_t val, void *p) +void +wy700_out(uint16_t addr, uint8_t val, void *priv) { - wy700_t *wy700 = (wy700_t *)p; - switch (addr) - { - /* These three registers are only mapped in the 3Dx range, - * not the 3Bx range. */ - case 0x3DD: /* Base address (low) */ - wy700->wy700_base &= 0xFF00; - wy700->wy700_base |= val; - wy700_checkchanges(wy700); - break; + wy700_t *wy700 = (wy700_t *) priv; + switch (addr) { + /* These three registers are only mapped in the 3Dx range, + * not the 3Bx range. */ + case 0x3DD: /* Base address (low) */ + wy700->wy700_base &= 0xFF00; + wy700->wy700_base |= val; + wy700_checkchanges(wy700); + break; - case 0x3DE: /* Base address (high) */ - wy700->wy700_base &= 0xFF; - wy700->wy700_base |= ((uint16_t)val) << 8; - wy700_checkchanges(wy700); - break; + case 0x3DE: /* Base address (high) */ + wy700->wy700_base &= 0xFF; + wy700->wy700_base |= ((uint16_t) val) << 8; + wy700_checkchanges(wy700); + break; - case 0x3DF: /* Command / control register */ - wy700->wy700_control = val; - wy700_checkchanges(wy700); - break; - - /* Emulated CRTC, register select */ - case 0x3b0: case 0x3b2: case 0x3b4: case 0x3b6: - case 0x3d0: case 0x3d2: case 0x3d4: case 0x3d6: - wy700->cga_crtcreg = val & 31; + case 0x3DF: /* Command / control register */ + wy700->wy700_control = val; + wy700_checkchanges(wy700); + break; + + /* Emulated CRTC, register select */ + case 0x3b0: + case 0x3b2: + case 0x3b4: + case 0x3b6: + case 0x3d0: + case 0x3d2: + case 0x3d4: + case 0x3d6: + wy700->cga_crtcreg = val & 31; + break; + + /* Emulated CRTC, value */ + case 0x3b1: + case 0x3b3: + case 0x3b5: + case 0x3b7: + case 0x3d1: + case 0x3d3: + case 0x3d5: + case 0x3d7: + wy700->cga_crtc[wy700->cga_crtcreg] = val; + + wy700_checkchanges(wy700); + wy700_recalctimings(wy700); + return; + + /* Emulated MDA / CGA control register */ + case 0x3b8: + case 0x3D8: + wy700->cga_ctrl = val; + wy700_checkchanges(wy700); + return; + /* Emulated CGA colour register */ + case 0x3D9: + wy700->cga_colour = val; + return; + + default: + break; + } +} + +uint8_t +wy700_in(uint16_t addr, void *priv) +{ + const wy700_t *wy700 = (wy700_t *) priv; + + switch (addr) { + case 0x3b0: + case 0x3b2: + case 0x3b4: + case 0x3b6: + case 0x3d0: + case 0x3d2: + case 0x3d4: + case 0x3d6: + return wy700->cga_crtcreg; + case 0x3b1: + case 0x3b3: + case 0x3b5: + case 0x3b7: + case 0x3d1: + case 0x3d3: + case 0x3d5: + case 0x3d7: + return wy700->cga_crtc[wy700->cga_crtcreg]; + case 0x3b8: + case 0x3d8: + return wy700->cga_ctrl; + case 0x3d9: + return wy700->cga_colour; + case 0x3ba: + return wy700->mda_stat; + case 0x3da: + return wy700->cga_stat; + + default: + break; + } + return 0xff; +} + +/* Check if any of the four key registers has changed. If so, check for a + * mode change or cursor size change */ +void +wy700_checkchanges(wy700_t *wy700) +{ + uint8_t curstart; + uint8_t curend; + + if (wy700->last_03D8 == wy700->cga_ctrl && wy700->last_03DD == (wy700->wy700_base & 0xFF) && wy700->last_03DF == wy700->wy700_control && wy700->last_crtc_0E == wy700->cga_crtc[0x0E]) { + return; /* Nothing changed */ + } + /* Check for control register changes */ + if (wy700->last_03DF != wy700->wy700_control) { + wy700->last_03DF = wy700->wy700_control; + + /* Values 1-7 are commands. */ + switch (wy700->wy700_control) { + case 1: /* Reset */ + wy700->font = 0; + wy700->enabled = 1; + wy700->detach = 0; break; - /* Emulated CRTC, value */ - case 0x3b1: case 0x3b3: case 0x3b5: case 0x3b7: - case 0x3d1: case 0x3d3: case 0x3d5: case 0x3d7: - wy700->cga_crtc[wy700->cga_crtcreg] = val; + case 2: /* Font 1 */ + wy700->font = 0; + break; - wy700_checkchanges(wy700); - wy700_recalctimings(wy700); - return; + case 3: /* Font 2 */ + wy700->font = 1; + break; - /* Emulated MDA / CGA control register */ - case 0x3b8: case 0x3D8: - wy700->cga_ctrl = val; - wy700_checkchanges(wy700); - return; - /* Emulated CGA colour register */ - case 0x3D9: - wy700->cga_colour = val; - return; + /* Even with the microprogram from an original card, I can't really work out + * what commands 4 and 5 (which I've called 'cursor detach' / 'cursor attach') + * do. Command 4 sets a flag in microcontroller RAM, and command 5 clears + * it. When the flag is set, the real cursor doesn't track the cursor in the + * emulated CRTC, and its blink rate increases. Possibly it's a self-test + * function of some kind. + * + * The card documentation doesn't cover these commands. + */ + + case 4: /* Detach cursor */ + wy700->detach = 1; + break; + + case 5: /* Attach cursor */ + wy700->detach = 0; + break; + + case 6: /* Disable display */ + wy700->enabled = 0; + break; + + case 7: /* Enable display */ + wy700->enabled = 1; + break; + + default: + break; } -} + /* A control write with the top bit set selects graphics mode */ + if (wy700->wy700_control & 0x80) { + /* Select hi-res graphics mode; map framebuffer at A0000 */ + mem_mapping_set_addr(&wy700->mapping, 0xa0000, 0x20000); + wy700->wy700_mode = wy700->wy700_control; -uint8_t wy700_in(uint16_t addr, void *p) -{ - wy700_t *wy700 = (wy700_t *)p; - switch (addr) + /* Select appropriate preset timings */ + if (wy700->wy700_mode & 0x40) { + memcpy(wy700->real_crtc, mode_1280x800, + sizeof(mode_1280x800)); + } else if (wy700->wy700_mode & 0x20) { + memcpy(wy700->real_crtc, mode_1280x400, + sizeof(mode_1280x400)); + } else { + memcpy(wy700->real_crtc, mode_640x400, + sizeof(mode_640x400)); + } + } + } + /* An attempt to program the CGA / MDA selects low-res mode */ + else if (wy700->last_03D8 != wy700->cga_ctrl) { + wy700->last_03D8 = wy700->cga_ctrl; + /* Set lo-res text or graphics mode. + * (Strictly speaking, when not in hi-res mode the card + * should be mapped at B0000-B3FFF and B8000-BBFFF, leaving + * a 16k hole between the two ranges) */ + mem_mapping_set_addr(&wy700->mapping, 0xb0000, 0x0C000); + if (wy700->cga_ctrl & 2) /* Graphics mode */ { - case 0x3b0: case 0x3b2: case 0x3b4: case 0x3b6: - case 0x3d0: case 0x3d2: case 0x3d4: case 0x3d6: - return wy700->cga_crtcreg; - case 0x3b1: case 0x3b3: case 0x3b5: case 0x3b7: - case 0x3d1: case 0x3d3: case 0x3d5: case 0x3d7: - return wy700->cga_crtc[wy700->cga_crtcreg]; - case 0x3b8: case 0x3d8: - return wy700->cga_ctrl; - case 0x3d9: - return wy700->cga_colour; - case 0x3ba: - return wy700->mda_stat; - case 0x3da: - return wy700->cga_stat; + wy700->wy700_mode = (wy700->cga_ctrl & 0x10) ? 6 : 4; + memcpy(wy700->real_crtc, mode_640x200, + sizeof(mode_640x200)); + } else if (wy700->cga_ctrl & 1) /* Text mode 80x24 */ + { + wy700->wy700_mode = 2; + memcpy(wy700->real_crtc, mode_80x24, sizeof(mode_80x24)); + } else /* Text mode 40x24 */ + { + wy700->wy700_mode = 0; + memcpy(wy700->real_crtc, mode_40x24, sizeof(mode_40x24)); } - return 0xff; + } + /* Convert the cursor sizes from the ones used by the CGA or MDA + * to native */ + + if (wy700->cga_crtc[9] == 13) /* MDA scaling */ + { + curstart = wy700->cga_crtc[10] & 0x1F; + wy700->real_crtc[10] = ((curstart + 5) >> 3) + curstart; + if (wy700->real_crtc[10] > 31) + wy700->real_crtc[10] = 31; + /* And bring 'cursor disabled' flag across */ + if ((wy700->cga_crtc[10] & 0x60) == 0x20) { + wy700->real_crtc[10] |= 0x20; + } + curend = wy700->cga_crtc[11] & 0x1F; + wy700->real_crtc[11] = ((curend + 5) >> 3) + curend; + if (wy700->real_crtc[11] > 31) + wy700->real_crtc[11] = 31; + } else /* CGA scaling */ + { + curstart = wy700->cga_crtc[10] & 0x1F; + wy700->real_crtc[10] = curstart << 1; + if (wy700->real_crtc[10] > 31) + wy700->real_crtc[10] = 31; + /* And bring 'cursor disabled' flag across */ + if ((wy700->cga_crtc[10] & 0x60) == 0x20) { + wy700->real_crtc[10] |= 0x20; + } + curend = wy700->cga_crtc[11] & 0x1F; + wy700->real_crtc[11] = curend << 1; + if (wy700->real_crtc[11] > 31) + wy700->real_crtc[11] = 31; + } } - -/* Check if any of the four key registers has changed. If so, check for a - * mode change or cursor size change */ -void wy700_checkchanges(wy700_t *wy700) +void +wy700_write(uint32_t addr, uint8_t val, void *priv) { - uint8_t curstart, curend; + wy700_t *wy700 = (wy700_t *) priv; - if (wy700->last_03D8 == wy700->cga_ctrl && - wy700->last_03DD == (wy700->wy700_base & 0xFF) && - wy700->last_03DF == wy700->wy700_control && - wy700->last_crtc_0E == wy700->cga_crtc[0x0E]) - { - return; /* Nothing changed */ - } - /* Check for control register changes */ - if (wy700->last_03DF != wy700->wy700_control) - { - wy700->last_03DF = wy700->wy700_control; - - /* Values 1-7 are commands. */ - switch (wy700->wy700_control) - { - case 1: /* Reset */ - wy700->font = 0; - wy700->enabled = 1; - wy700->detach = 0; - break; - - case 2: /* Font 1 */ - wy700->font = 0; - break; - - case 3: /* Font 2 */ - wy700->font = 1; - break; - -/* Even with the microprogram from an original card, I can't really work out - * what commands 4 and 5 (which I've called 'cursor detach' / 'cursor attach') - * do. Command 4 sets a flag in microcontroller RAM, and command 5 clears - * it. When the flag is set, the real cursor doesn't track the cursor in the - * emulated CRTC, and its blink rate increases. Possibly it's a self-test - * function of some kind. - * - * The card documentation doesn't cover these commands. - */ - - case 4: /* Detach cursor */ - wy700->detach = 1; - break; - - case 5: /* Attach cursor */ - wy700->detach = 0; - break; - - case 6: /* Disable display */ - wy700->enabled = 0; - break; - - case 7: /* Enable display */ - wy700->enabled = 1; - break; - } - /* A control write with the top bit set selects graphics mode */ - if (wy700->wy700_control & 0x80) - { - /* Select hi-res graphics mode; map framebuffer at A0000 */ - mem_mapping_set_addr(&wy700->mapping, 0xa0000, 0x20000); - wy700->wy700_mode = wy700->wy700_control; - - /* Select appropriate preset timings */ - if (wy700->wy700_mode & 0x40) - { - memcpy(wy700->real_crtc, mode_1280x800, - sizeof(mode_1280x800)); - } - else if (wy700->wy700_mode & 0x20) - { - memcpy(wy700->real_crtc, mode_1280x400, - sizeof(mode_1280x400)); - } - else - { - memcpy(wy700->real_crtc, mode_640x400, - sizeof(mode_640x400)); - } - } - } - /* An attempt to program the CGA / MDA selects low-res mode */ - else if (wy700->last_03D8 != wy700->cga_ctrl) - { - wy700->last_03D8 = wy700->cga_ctrl; - /* Set lo-res text or graphics mode. - * (Strictly speaking, when not in hi-res mode the card - * should be mapped at B0000-B3FFF and B8000-BBFFF, leaving - * a 16k hole between the two ranges) */ - mem_mapping_set_addr(&wy700->mapping, 0xb0000, 0x0C000); - if (wy700->cga_ctrl & 2) /* Graphics mode */ - { - wy700->wy700_mode = (wy700->cga_ctrl & 0x10) ? 6 : 4; - memcpy(wy700->real_crtc, mode_640x200, - sizeof(mode_640x200)); - } - else if (wy700->cga_ctrl & 1) /* Text mode 80x24 */ - { - wy700->wy700_mode = 2; - memcpy(wy700->real_crtc, mode_80x24, sizeof(mode_80x24)); - } - else /* Text mode 40x24 */ - { - wy700->wy700_mode = 0; - memcpy(wy700->real_crtc, mode_40x24, sizeof(mode_40x24)); - } - } - /* Convert the cursor sizes from the ones used by the CGA or MDA - * to native */ - - if (wy700->cga_crtc[9] == 13) /* MDA scaling */ - { - curstart = wy700->cga_crtc[10] & 0x1F; - wy700->real_crtc[10] = ((curstart + 5) >> 3) + curstart; - if (wy700->real_crtc[10] > 31) wy700->real_crtc[10] = 31; - /* And bring 'cursor disabled' flag across */ - if ((wy700->cga_crtc[10] & 0x60) == 0x20) - { - wy700->real_crtc[10] |= 0x20; - } - curend = wy700->cga_crtc[11] & 0x1F; - wy700->real_crtc[11] = ((curend + 5) >> 3) + curend; - if (wy700->real_crtc[11] > 31) wy700->real_crtc[11] = 31; - } - else /* CGA scaling */ - { - curstart = wy700->cga_crtc[10] & 0x1F; - wy700->real_crtc[10] = curstart << 1; - if (wy700->real_crtc[10] > 31) wy700->real_crtc[10] = 31; - /* And bring 'cursor disabled' flag across */ - if ((wy700->cga_crtc[10] & 0x60) == 0x20) - { - wy700->real_crtc[10] |= 0x20; - } - curend = wy700->cga_crtc[11] & 0x1F; - wy700->real_crtc[11] = curend << 1; - if (wy700->real_crtc[11] > 31) wy700->real_crtc[11] = 31; - } + if (wy700->wy700_mode & 0x80) /* High-res mode. */ + { + addr &= 0xFFFF; + /* In 800-line modes, bit 1 of the control register sets the high bit of the + * write address. */ + if ((wy700->wy700_mode & 0x42) == 0x42) { + addr |= 0x10000; + } + wy700->vram[addr] = val; + } else { + wy700->vram[addr & 0x3fff] = val; + } } - -void wy700_write(uint32_t addr, uint8_t val, void *p) +uint8_t +wy700_read(uint32_t addr, void *priv) { - wy700_t *wy700 = (wy700_t *)p; + const wy700_t *wy700 = (wy700_t *) priv; - if (wy700->wy700_mode & 0x80) /* High-res mode. */ - { - addr &= 0xFFFF; -/* In 800-line modes, bit 1 of the control register sets the high bit of the - * write address. */ - if ((wy700->wy700_mode & 0x42) == 0x42) - { - addr |= 0x10000; - } - wy700->vram[addr] = val; - } - else - { - wy700->vram[addr & 0x3fff] = val; - } + if (wy700->wy700_mode & 0x80) { /* High-res mode. */ + addr &= 0xFFFF; + /* In 800-line modes, bit 0 of the control register sets the high bit of the + * read address. */ + if ((wy700->wy700_mode & 0x41) == 0x41) { + addr |= 0x10000; + } + return wy700->vram[addr]; + } else { + return wy700->vram[addr & 0x3fff]; + } } - - -uint8_t wy700_read(uint32_t addr, void *p) +void +wy700_recalctimings(wy700_t *wy700) { - wy700_t *wy700 = (wy700_t *)p; - if (wy700->wy700_mode & 0x80) /* High-res mode. */ - { - addr &= 0xFFFF; -/* In 800-line modes, bit 0 of the control register sets the high bit of the - * read address. */ - if ((wy700->wy700_mode & 0x41) == 0x41) - { - addr |= 0x10000; - } - return wy700->vram[addr]; - } - else - { - return wy700->vram[addr & 0x3fff]; - } + double disptime; + double _dispontime; + double _dispofftime; + + disptime = wy700->real_crtc[0] + 1; + _dispontime = wy700->real_crtc[1]; + _dispofftime = disptime - _dispontime; + _dispontime *= MDACONST; + _dispofftime *= MDACONST; + wy700->dispontime = (uint64_t) (_dispontime); + wy700->dispofftime = (uint64_t) (_dispofftime); } - - -void wy700_recalctimings(wy700_t *wy700) -{ - double disptime; - double _dispontime, _dispofftime; - - disptime = wy700->real_crtc[0] + 1; - _dispontime = wy700->real_crtc[1]; - _dispofftime = disptime - _dispontime; - _dispontime *= MDACONST; - _dispofftime *= MDACONST; - wy700->dispontime = (uint64_t)(_dispontime); - wy700->dispofftime = (uint64_t)(_dispofftime); -} - - /* Draw a single line of the screen in either text mode */ -void wy700_textline(wy700_t *wy700) +void +wy700_textline(wy700_t *wy700) { - int x; - int w = (wy700->wy700_mode == 0) ? 40 : 80; - int cw = (wy700->wy700_mode == 0) ? 32 : 16; - uint8_t chr, attr; - uint8_t bitmap[2]; - uint8_t *fontbase = &fontdatw[0][0]; - int blink, c; - int drawcursor, cursorline; - int mda = 0; - uint16_t addr; - uint8_t sc; - uint16_t ma = (wy700->cga_crtc[13] | (wy700->cga_crtc[12] << 8)) & 0x3fff; - uint16_t ca = (wy700->cga_crtc[15] | (wy700->cga_crtc[14] << 8)) & 0x3fff; + int w = (wy700->wy700_mode == 0) ? 40 : 80; + int cw = (wy700->wy700_mode == 0) ? 32 : 16; + uint8_t chr; + uint8_t attr; + uint8_t bitmap[2]; + const uint8_t *fontbase = &fontdatw[0][0]; + int blink; + int c; + int drawcursor; + int cursorline; + int mda = 0; + uint16_t addr; + uint8_t sc; + uint16_t ma = (wy700->cga_crtc[13] | (wy700->cga_crtc[12] << 8)) & 0x3fff; + uint16_t ca = (wy700->cga_crtc[15] | (wy700->cga_crtc[14] << 8)) & 0x3fff; + /* The fake CRTC character height register selects whether MDA or CGA + * attributes are used */ + if (wy700->cga_crtc[9] == 0 || wy700->cga_crtc[9] == 13) { + mda = 1; + } -/* The fake CRTC character height register selects whether MDA or CGA - * attributes are used */ - if (wy700->cga_crtc[9] == 0 || wy700->cga_crtc[9] == 13) - { - mda = 1; - } + if (wy700->font) { + fontbase += 256 * 32; + } + addr = ((ma & ~1) + (wy700->displine >> 5) * w) * 2; + sc = (wy700->displine >> 1) & 15; - if (wy700->font) - { - fontbase += 256*32; - } - addr = ((ma & ~1) + (wy700->displine >> 5) * w) * 2; - sc = (wy700->displine >> 1) & 15; + ma += ((wy700->displine >> 5) * w); - ma += ((wy700->displine >> 5) * w); + if ((wy700->real_crtc[10] & 0x60) == 0x20) { + cursorline = 0; + } else { + cursorline = ((wy700->real_crtc[10] & 0x1F) <= sc) && ((wy700->real_crtc[11] & 0x1F) >= sc); + } - if ((wy700->real_crtc[10] & 0x60) == 0x20) - { - cursorline = 0; - } - else - { - cursorline = ((wy700->real_crtc[10] & 0x1F) <= sc) && - ((wy700->real_crtc[11] & 0x1F) >= sc); - } + for (int x = 0; x < w; x++) { + chr = wy700->vram[(addr + 2 * x) & 0x3FFF]; + attr = wy700->vram[(addr + 2 * x + 1) & 0x3FFF]; + drawcursor = ((ma == ca) && cursorline && wy700->enabled && (wy700->cga_ctrl & 8) && (wy700->blink & 16)); + blink = ((wy700->blink & 16) && (wy700->cga_ctrl & 0x20) && (attr & 0x80) && !drawcursor); - for (x = 0; x < w; x++) - { - chr = wy700->vram[(addr + 2 * x) & 0x3FFF]; - attr = wy700->vram[(addr + 2 * x + 1) & 0x3FFF]; - drawcursor = ((ma == ca) && cursorline && wy700->enabled && - (wy700->cga_ctrl & 8) && (wy700->blink & 16)); - blink = ((wy700->blink & 16) && - (wy700->cga_ctrl & 0x20) && - (attr & 0x80) && !drawcursor); + if (wy700->cga_ctrl & 0x20) + attr &= 0x7F; + /* MDA underline */ + if (sc == 14 && mda && ((attr & 7) == 1)) { + for (c = 0; c < cw; c++) + buffer32->line[wy700->displine][(x * cw) + c] = mdacols[attr][blink][1]; + } else /* Draw 16 pixels of character */ + { + bitmap[0] = fontbase[chr * 32 + 2 * sc]; + bitmap[1] = fontbase[chr * 32 + 2 * sc + 1]; + for (c = 0; c < 16; c++) { + int col; + if (c < 8) + col = (mda ? mdacols : cgacols)[attr][blink][(bitmap[0] & (1 << (c ^ 7))) ? 1 : 0]; + else + col = (mda ? mdacols : cgacols)[attr][blink][(bitmap[1] & (1 << ((c & 7) ^ 7))) ? 1 : 0]; + if (!(wy700->enabled) || !(wy700->cga_ctrl & 8)) + col = mdacols[0][0][0]; + if (w == 40) { + buffer32->line[wy700->displine][(x * cw) + 2 * c] = col; + buffer32->line[wy700->displine][(x * cw) + 2 * c + 1] = col; + } else + buffer32->line[wy700->displine][(x * cw) + c] = col; + } - if (wy700->cga_ctrl & 0x20) attr &= 0x7F; - /* MDA underline */ - if (sc == 14 && mda && ((attr & 7) == 1)) - { - for (c = 0; c < cw; c++) - buffer32->line[wy700->displine][(x * cw) + c] = - mdacols[attr][blink][1]; - } - else /* Draw 16 pixels of character */ - { - bitmap[0] = fontbase[chr * 32 + 2 * sc]; - bitmap[1] = fontbase[chr * 32 + 2 * sc + 1]; - for (c = 0; c < 16; c++) - { - int col; - if (c < 8) - col = (mda ? mdacols : cgacols)[attr][blink][(bitmap[0] & (1 << (c ^ 7))) ? 1 : 0]; - else col = (mda ? mdacols : cgacols)[attr][blink][(bitmap[1] & (1 << ((c & 7) ^ 7))) ? 1 : 0]; - if (!(wy700->enabled) || !(wy700->cga_ctrl & 8)) - col = mdacols[0][0][0]; - if (w == 40) - { - buffer32->line[wy700->displine][(x * cw) + 2*c] = col; - buffer32->line[wy700->displine][(x * cw) + 2*c + 1] = col; - } - else buffer32->line[wy700->displine][(x * cw) + c] = col; - } - - if (drawcursor) - { - for (c = 0; c < cw; c++) - buffer32->line[wy700->displine][(x * cw) + c] ^= (mda ? mdacols : cgacols)[attr][0][1]; - } - ++ma; - } - } + if (drawcursor) { + for (c = 0; c < cw; c++) + buffer32->line[wy700->displine][(x * cw) + c] ^= (mda ? mdacols : cgacols)[attr][0][1]; + } + ++ma; + } + } } - /* Draw a line in either of the CGA graphics modes (320x200 or 640x200) */ -void wy700_cgaline(wy700_t *wy700) +void +wy700_cgaline(wy700_t *wy700) { - int x, c; - uint32_t dat; - uint8_t ink = 0; - uint16_t addr; + int c; + uint32_t dat; + uint8_t ink = 0; + uint16_t addr; - uint16_t ma = (wy700->cga_crtc[13] | (wy700->cga_crtc[12] << 8)) & 0x3fff; - addr = ((wy700->displine >> 2) & 1) * 0x2000 + - (wy700->displine >> 3) * 80 + - ((ma & ~1) << 1); + uint16_t ma = (wy700->cga_crtc[13] | (wy700->cga_crtc[12] << 8)) & 0x3fff; + addr = ((wy700->displine >> 2) & 1) * 0x2000 + (wy700->displine >> 3) * 80 + ((ma & ~1) << 1); - /* The fixed mode setting here programs the real CRTC with a screen - * width to 20, so draw in 20 fixed chunks of 4 bytes each */ - for (x = 0; x < 20; x++) - { - dat = ((wy700->vram[addr & 0x3FFF] << 24) | - (wy700->vram[(addr+1) & 0x3FFF] << 16) | - (wy700->vram[(addr+2) & 0x3FFF] << 8) | - (wy700->vram[(addr+3) & 0x3FFF])); - addr += 4; + /* The fixed mode setting here programs the real CRTC with a screen + * width to 20, so draw in 20 fixed chunks of 4 bytes each */ + for (uint8_t x = 0; x < 20; x++) { + dat = ((wy700->vram[addr & 0x3FFF] << 24) | (wy700->vram[(addr + 1) & 0x3FFF] << 16) | (wy700->vram[(addr + 2) & 0x3FFF] << 8) | (wy700->vram[(addr + 3) & 0x3FFF])); + addr += 4; - if (wy700->wy700_mode == 6) - { - for (c = 0; c < 32; c++) - { - ink = (dat & 0x80000000) ? 16 + 15: 16 + 0; - if (!(wy700->enabled) || !(wy700->cga_ctrl & 8)) - ink = 16; - buffer32->line[wy700->displine][x*64 + 2*c] = - buffer32->line[wy700->displine][x*64 + 2*c+1] = - ink; - dat = dat << 1; - } - } - else - { - for (c = 0; c < 16; c++) - { - switch ((dat >> 30) & 3) - { - case 0: ink = 16 + 0; break; - case 1: ink = 16 + 8; break; - case 2: ink = 16 + 7; break; - case 3: ink = 16 + 15; break; - } - if (!(wy700->enabled) || !(wy700->cga_ctrl & 8)) - ink = 16; - buffer32->line[wy700->displine][x*64 + 4*c] = - buffer32->line[wy700->displine][x*64 + 4*c+1] = - buffer32->line[wy700->displine][x*64 + 4*c+2] = - buffer32->line[wy700->displine][x*64 + 4*c+3] = - ink; - dat = dat << 2; - } - } - } + if (wy700->wy700_mode == 6) { + for (c = 0; c < 32; c++) { + ink = (dat & 0x80000000) ? 16 + 15 : 16 + 0; + if (!(wy700->enabled) || !(wy700->cga_ctrl & 8)) + ink = 16; + buffer32->line[wy700->displine][x * 64 + 2 * c] = buffer32->line[wy700->displine][x * 64 + 2 * c + 1] = ink; + dat = dat << 1; + } + } else { + for (c = 0; c < 16; c++) { + switch ((dat >> 30) & 3) { + case 0: + ink = 16 + 0; + break; + case 1: + ink = 16 + 8; + break; + case 2: + ink = 16 + 7; + break; + case 3: + ink = 16 + 15; + break; + + default: + break; + } + if (!(wy700->enabled) || !(wy700->cga_ctrl & 8)) + ink = 16; + buffer32->line[wy700->displine][x * 64 + 4 * c] = buffer32->line[wy700->displine][x * 64 + 4 * c + 1] = buffer32->line[wy700->displine][x * 64 + 4 * c + 2] = buffer32->line[wy700->displine][x * 64 + 4 * c + 3] = ink; + dat = dat << 2; + } + } + } } /* Draw a line in the medium-resolution graphics modes (640x400 or 320x400) */ -void wy700_medresline(wy700_t *wy700) +void +wy700_medresline(wy700_t *wy700) { - int x, c; - uint32_t dat; - uint8_t ink = 0; - uint32_t addr; + int c; + uint32_t dat; + uint8_t ink = 0; + uint32_t addr; - addr = (wy700->displine >> 1) * 80 + 4 * wy700->wy700_base; + addr = (wy700->displine >> 1) * 80 + 4 * wy700->wy700_base; - for (x = 0; x < 20; x++) - { - dat = ((wy700->vram[addr & 0x1FFFF] << 24) | - (wy700->vram[(addr+1) & 0x1FFFF] << 16) | - (wy700->vram[(addr+2) & 0x1FFFF] << 8) | - (wy700->vram[(addr+3) & 0x1FFFF])); - addr += 4; + for (uint8_t x = 0; x < 20; x++) { + dat = ((wy700->vram[addr & 0x1FFFF] << 24) | (wy700->vram[(addr + 1) & 0x1FFFF] << 16) | (wy700->vram[(addr + 2) & 0x1FFFF] << 8) | (wy700->vram[(addr + 3) & 0x1FFFF])); + addr += 4; - if (wy700->wy700_mode & 0x10) - { - for (c = 0; c < 16; c++) - { - switch ((dat >> 30) & 3) - { - case 0: ink = 16 + 0; break; - case 1: ink = 16 + 8; break; - case 2: ink = 16 + 7; break; - case 3: ink = 16 + 15; break; - } - /* Display disabled? */ - if (!(wy700->wy700_mode & 8)) ink = 16; - buffer32->line[wy700->displine][x*64 + 4*c] = - buffer32->line[wy700->displine][x*64 + 4*c+1] = - buffer32->line[wy700->displine][x*64 + 4*c+2] = - buffer32->line[wy700->displine][x*64 + 4*c+3] = - ink; - dat = dat << 2; - } - } - else - { - for (c = 0; c < 32; c++) - { - ink = (dat & 0x80000000) ? 16 + 15: 16 + 0; - /* Display disabled? */ - if (!(wy700->wy700_mode & 8)) ink = 16; - buffer32->line[wy700->displine][x*64 + 2*c] = - buffer32->line[wy700->displine][x*64 + 2*c+1] = - ink; - dat = dat << 1; - } - } - } + if (wy700->wy700_mode & 0x10) { + for (c = 0; c < 16; c++) { + switch ((dat >> 30) & 3) { + case 0: + ink = 16 + 0; + break; + case 1: + ink = 16 + 8; + break; + case 2: + ink = 16 + 7; + break; + case 3: + ink = 16 + 15; + break; + + default: + break; + } + /* Display disabled? */ + if (!(wy700->wy700_mode & 8)) + ink = 16; + buffer32->line[wy700->displine][x * 64 + 4 * c] = buffer32->line[wy700->displine][x * 64 + 4 * c + 1] = buffer32->line[wy700->displine][x * 64 + 4 * c + 2] = buffer32->line[wy700->displine][x * 64 + 4 * c + 3] = ink; + dat = dat << 2; + } + } else { + for (c = 0; c < 32; c++) { + ink = (dat & 0x80000000) ? 16 + 15 : 16 + 0; + /* Display disabled? */ + if (!(wy700->wy700_mode & 8)) + ink = 16; + buffer32->line[wy700->displine][x * 64 + 2 * c] = buffer32->line[wy700->displine][x * 64 + 2 * c + 1] = ink; + dat = dat << 1; + } + } + } } - - - /* Draw a line in one of the high-resolution modes */ -void wy700_hiresline(wy700_t *wy700) +void +wy700_hiresline(wy700_t *wy700) { - int x, c; - uint32_t dat; - uint8_t ink = 0; - uint32_t addr; + int c; + uint32_t dat; + uint8_t ink = 0; + uint32_t addr; - addr = (wy700->displine >> 1) * 160 + 4 * wy700->wy700_base; + addr = (wy700->displine >> 1) * 160 + 4 * wy700->wy700_base; - if (wy700->wy700_mode & 0x40) /* 800-line interleaved modes */ - { - if (wy700->displine & 1) addr += 0x10000; - } - for (x = 0; x < 40; x++) - { - dat = ((wy700->vram[addr & 0x1FFFF] << 24) | - (wy700->vram[(addr+1) & 0x1FFFF] << 16) | - (wy700->vram[(addr+2) & 0x1FFFF] << 8) | - (wy700->vram[(addr+3) & 0x1FFFF])); - addr += 4; + if (wy700->wy700_mode & 0x40) /* 800-line interleaved modes */ + { + if (wy700->displine & 1) + addr += 0x10000; + } + for (uint8_t x = 0; x < 40; x++) { + dat = ((wy700->vram[addr & 0x1FFFF] << 24) | (wy700->vram[(addr + 1) & 0x1FFFF] << 16) | (wy700->vram[(addr + 2) & 0x1FFFF] << 8) | (wy700->vram[(addr + 3) & 0x1FFFF])); + addr += 4; - if (wy700->wy700_mode & 0x10) - { - for (c = 0; c < 16; c++) - { - switch ((dat >> 30) & 3) - { - case 0: ink = 16 + 0; break; - case 1: ink = 16 + 8; break; - case 2: ink = 16 + 7; break; - case 3: ink = 16 + 15; break; - } - /* Display disabled? */ - if (!(wy700->wy700_mode & 8)) ink = 16; - buffer32->line[wy700->displine][x*32 + 2*c] = - buffer32->line[wy700->displine][x*32 + 2*c+1] = - ink; - dat = dat << 2; - } - } - else - { - for (c = 0; c < 32; c++) - { - ink = (dat & 0x80000000) ? 16 + 15: 16 + 0; - /* Display disabled? */ - if (!(wy700->wy700_mode & 8)) ink = 16; - buffer32->line[wy700->displine][x*32 + c] = ink; - dat = dat << 1; - } - } - } + if (wy700->wy700_mode & 0x10) { + for (c = 0; c < 16; c++) { + switch ((dat >> 30) & 3) { + case 0: + ink = 16 + 0; + break; + case 1: + ink = 16 + 8; + break; + case 2: + ink = 16 + 7; + break; + case 3: + ink = 16 + 15; + break; + + default: + break; + } + /* Display disabled? */ + if (!(wy700->wy700_mode & 8)) + ink = 16; + buffer32->line[wy700->displine][x * 32 + 2 * c] = buffer32->line[wy700->displine][x * 32 + 2 * c + 1] = ink; + dat = dat << 2; + } + } else { + for (c = 0; c < 32; c++) { + ink = (dat & 0x80000000) ? 16 + 15 : 16 + 0; + /* Display disabled? */ + if (!(wy700->wy700_mode & 8)) + ink = 16; + buffer32->line[wy700->displine][x * 32 + c] = ink; + dat = dat << 1; + } + } + } } - - - -void wy700_poll(void *p) +void +wy700_poll(void *priv) { - wy700_t *wy700 = (wy700_t *)p; - int mode; + wy700_t *wy700 = (wy700_t *) priv; + int mode; - if (!wy700->linepos) - { - timer_advance_u64(&wy700->timer, wy700->dispofftime); - wy700->cga_stat |= 1; - wy700->mda_stat |= 1; - wy700->linepos = 1; - if (wy700->dispon) - { - if (wy700->displine == 0) - { - video_wait_for_buffer(); - } - - if (wy700->wy700_mode & 0x80) - mode = wy700->wy700_mode & 0xF0; - else mode = wy700->wy700_mode & 0x0F; + if (!wy700->linepos) { + timer_advance_u64(&wy700->timer, wy700->dispofftime); + wy700->cga_stat |= 1; + wy700->mda_stat |= 1; + wy700->linepos = 1; + if (wy700->dispon) { + if (wy700->displine == 0) { + video_wait_for_buffer(); + } - switch (mode) - { - default: - case 0x00: - case 0x02: - wy700_textline(wy700); - break; - case 0x04: - case 0x06: - wy700_cgaline(wy700); - break; - case 0x80: - case 0x90: - wy700_medresline(wy700); - break; - case 0xA0: - case 0xB0: - case 0xC0: - case 0xD0: - case 0xE0: - case 0xF0: - wy700_hiresline(wy700); - break; - } - } - wy700->displine++; - /* Hardcode a fixed refresh rate and VSYNC timing */ - if (wy700->displine == 800) /* Start of VSYNC */ - { - wy700->cga_stat |= 8; - wy700->dispon = 0; - } - if (wy700->displine == 832) /* End of VSYNC */ - { - wy700->displine = 0; - wy700->cga_stat &= ~8; - wy700->dispon = 1; - } + if (wy700->wy700_mode & 0x80) + mode = wy700->wy700_mode & 0xF0; + else + mode = wy700->wy700_mode & 0x0F; + + switch (mode) { + default: + case 0x00: + case 0x02: + wy700_textline(wy700); + break; + case 0x04: + case 0x06: + wy700_cgaline(wy700); + break; + case 0x80: + case 0x90: + wy700_medresline(wy700); + break; + case 0xA0: + case 0xB0: + case 0xC0: + case 0xD0: + case 0xE0: + case 0xF0: + wy700_hiresline(wy700); + break; + } } + video_process_8(WY700_XSIZE, wy700->displine); + wy700->displine++; + /* Hardcode a fixed refresh rate and VSYNC timing */ + if (wy700->displine == 800) /* Start of VSYNC */ + { + wy700->cga_stat |= 8; + wy700->dispon = 0; + } + if (wy700->displine == 832) /* End of VSYNC */ + { + wy700->displine = 0; + wy700->cga_stat &= ~8; + wy700->dispon = 1; + } + } else { + if (wy700->dispon) { + wy700->cga_stat &= ~1; + wy700->mda_stat &= ~1; + } + timer_advance_u64(&wy700->timer, wy700->dispontime); + wy700->linepos = 0; + + if (wy700->displine == 800) { + /* Hardcode 1280x800 window size */ + if ((WY700_XSIZE != xsize) || (WY700_YSIZE != ysize) || video_force_resize_get()) { + xsize = WY700_XSIZE; + ysize = WY700_YSIZE; + if (xsize < 64) + xsize = 656; + if (ysize < 32) + ysize = 200; + set_screen_size(xsize, ysize); + + if (video_force_resize_get()) + video_force_resize_set(0); + } + video_blit_memtoscreen(0, 0, xsize, ysize); + + frames++; + /* Fixed 1280x800 resolution */ + video_res_x = WY700_XSIZE; + video_res_y = WY700_YSIZE; + if (wy700->wy700_mode & 0x80) + mode = wy700->wy700_mode & 0xF0; + else + mode = wy700->wy700_mode & 0x0F; + switch (mode) { + case 0x00: + case 0x02: + video_bpp = 0; + break; + case 0x04: + case 0x90: + case 0xB0: + case 0xD0: + case 0xF0: + video_bpp = 2; + break; + default: + video_bpp = 1; + break; + } + wy700->blink++; + } + } +} + +void * +wy700_init(UNUSED(const device_t *info)) +{ + int c; + wy700_t *wy700 = malloc(sizeof(wy700_t)); + + memset(wy700, 0, sizeof(wy700_t)); + video_inform(VIDEO_FLAG_TYPE_CGA, &timing_wy700); + + /* 128k video RAM */ + wy700->vram = malloc(0x20000); + + loadfont("roms/video/wyse700/wy700.rom", 3); + + timer_add(&wy700->timer, wy700_poll, wy700, 1); + + /* Occupy memory between 0xB0000 and 0xBFFFF (moves to 0xA0000 in + * high-resolution modes) */ + mem_mapping_add(&wy700->mapping, 0xb0000, 0x10000, wy700_read, NULL, NULL, wy700_write, NULL, NULL, NULL, MEM_MAPPING_EXTERNAL, wy700); + /* Respond to both MDA and CGA I/O ports */ + io_sethandler(0x03b0, 0x000C, wy700_in, NULL, NULL, wy700_out, NULL, NULL, wy700); + io_sethandler(0x03d0, 0x0010, wy700_in, NULL, NULL, wy700_out, NULL, NULL, wy700); + + /* Set up the emulated attributes. + * CGA is done in four groups: 00-0F, 10-7F, 80-8F, 90-FF */ + for (c = 0; c < 0x10; c++) { + cgacols[c][0][0] = cgacols[c][1][0] = cgacols[c][1][1] = 16; + if (c & 8) + cgacols[c][0][1] = 15 + 16; else - { - if (wy700->dispon) - { - wy700->cga_stat &= ~1; - wy700->mda_stat &= ~1; - } - timer_advance_u64(&wy700->timer, wy700->dispontime); - wy700->linepos = 0; + cgacols[c][0][1] = 7 + 16; + } + for (c = 0x10; c < 0x80; c++) { + cgacols[c][0][0] = cgacols[c][1][0] = cgacols[c][1][1] = 16 + 7; + if (c & 8) + cgacols[c][0][1] = 15 + 16; + else + cgacols[c][0][1] = 0 + 16; - if (wy700->displine == 800) - { -/* Hardcode 1280x800 window size */ - if ((WY700_XSIZE != xsize) || (WY700_YSIZE != ysize) || video_force_resize_get()) - { - xsize = WY700_XSIZE; - ysize = WY700_YSIZE; - if (xsize < 64) xsize = 656; - if (ysize < 32) ysize = 200; - set_screen_size(xsize, ysize); + if ((c & 0x0F) == 8) + cgacols[c][0][1] = 8 + 16; + } + /* With special cases for 00, 11, 22, ... 77 */ + cgacols[0x00][0][1] = cgacols[0x00][1][1] = 16; + for (c = 0x11; c <= 0x77; c += 0x11) { + cgacols[c][0][1] = cgacols[c][1][1] = 16 + 7; + } + for (c = 0x80; c < 0x90; c++) { + cgacols[c][0][0] = 16 + 8; + if (c & 8) + cgacols[c][0][1] = 15 + 16; + else + cgacols[c][0][1] = 7 + 16; + cgacols[c][1][0] = cgacols[c][1][1] = cgacols[c - 0x80][0][0]; + } + for (c = 0x90; c < 0x100; c++) { + cgacols[c][0][0] = 16 + 15; + if (c & 8) + cgacols[c][0][1] = 8 + 16; + else + cgacols[c][0][1] = 7 + 16; + if ((c & 0x0F) == 0) + cgacols[c][0][1] = 16; + cgacols[c][1][0] = cgacols[c][1][1] = cgacols[c - 0x80][0][0]; + } + /* Also special cases for 99, AA, ..., FF */ + for (c = 0x99; c <= 0xFF; c += 0x11) { + cgacols[c][0][1] = 16 + 15; + } + /* Special cases for 08, 80 and 88 */ + cgacols[0x08][0][1] = 16 + 8; + cgacols[0x80][0][1] = 16; + cgacols[0x88][0][1] = 16 + 8; - if (video_force_resize_get()) - video_force_resize_set(0); - } - video_blit_memtoscreen_8(0, 0, xsize, ysize); + /* MDA attributes */ + for (c = 0; c < 256; c++) { + mdacols[c][0][0] = mdacols[c][1][0] = mdacols[c][1][1] = 16; + if (c & 8) + mdacols[c][0][1] = 15 + 16; + else + mdacols[c][0][1] = 7 + 16; + } + mdacols[0x70][0][1] = 16; + mdacols[0x70][0][0] = mdacols[0x70][1][0] = mdacols[0x70][1][1] = 16 + 15; + mdacols[0xF0][0][1] = 16; + mdacols[0xF0][0][0] = mdacols[0xF0][1][0] = mdacols[0xF0][1][1] = 16 + 15; + mdacols[0x78][0][1] = 16 + 7; + mdacols[0x78][0][0] = mdacols[0x78][1][0] = mdacols[0x78][1][1] = 16 + 15; + mdacols[0xF8][0][1] = 16 + 7; + mdacols[0xF8][0][0] = mdacols[0xF8][1][0] = mdacols[0xF8][1][1] = 16 + 15; + mdacols[0x00][0][1] = mdacols[0x00][1][1] = 16; + mdacols[0x08][0][1] = mdacols[0x08][1][1] = 16; + mdacols[0x80][0][1] = mdacols[0x80][1][1] = 16; + mdacols[0x88][0][1] = mdacols[0x88][1][1] = 16; - frames++; - /* Fixed 1280x800 resolution */ - video_res_x = WY700_XSIZE; - video_res_y = WY700_YSIZE; - if (wy700->wy700_mode & 0x80) - mode = wy700->wy700_mode & 0xF0; - else mode = wy700->wy700_mode & 0x0F; - switch(mode) - { - case 0x00: - case 0x02: video_bpp = 0; break; - case 0x04: - case 0x90: - case 0xB0: - case 0xD0: - case 0xF0: video_bpp = 2; break; - default: video_bpp = 1; break; - } - wy700->blink++; - } - } + /* Start off in 80x25 text mode */ + wy700->cga_stat = 0xF4; + wy700->wy700_mode = 2; + wy700->enabled = 1; + memcpy(wy700->real_crtc, mode_80x24, sizeof(mode_80x24)); + return wy700; } - -void *wy700_init(const device_t *info) +void +wy700_close(void *priv) { - int c; - wy700_t *wy700 = malloc(sizeof(wy700_t)); - memset(wy700, 0, sizeof(wy700_t)); - video_inform(VIDEO_FLAG_TYPE_CGA, &timing_wy700); + wy700_t *wy700 = (wy700_t *) priv; - /* 128k video RAM */ - wy700->vram = malloc(0x20000); - - loadfont("roms/video/wyse700/wy700.rom", 3); - - timer_add(&wy700->timer, wy700_poll, wy700, 1); - - /* Occupy memory between 0xB0000 and 0xBFFFF (moves to 0xA0000 in - * high-resolution modes) */ - mem_mapping_add(&wy700->mapping, 0xb0000, 0x10000, wy700_read, NULL, NULL, wy700_write, NULL, NULL, NULL, MEM_MAPPING_EXTERNAL, wy700); - /* Respond to both MDA and CGA I/O ports */ - io_sethandler(0x03b0, 0x000C, wy700_in, NULL, NULL, wy700_out, NULL, NULL, wy700); - io_sethandler(0x03d0, 0x0010, wy700_in, NULL, NULL, wy700_out, NULL, NULL, wy700); - - /* Set up the emulated attributes. - * CGA is done in four groups: 00-0F, 10-7F, 80-8F, 90-FF */ - for (c = 0; c < 0x10; c++) - { - cgacols[c][0][0] = cgacols[c][1][0] = cgacols[c][1][1] = 16; - if (c & 8) cgacols[c][0][1] = 15 + 16; - else cgacols[c][0][1] = 7 + 16; - } - for (c = 0x10; c < 0x80; c++) - { - cgacols[c][0][0] = cgacols[c][1][0] = cgacols[c][1][1] = 16 + 7; - if (c & 8) cgacols[c][0][1] = 15 + 16; - else cgacols[c][0][1] = 0 + 16; - - if ((c & 0x0F) == 8) cgacols[c][0][1] = 8 + 16; - } - /* With special cases for 00, 11, 22, ... 77 */ - cgacols[0x00][0][1] = cgacols[0x00][1][1] = 16; - for (c = 0x11; c <= 0x77; c += 0x11) - { - cgacols[c][0][1] = cgacols[c][1][1] = 16 + 7; - } - for (c = 0x80; c < 0x90; c++) - { - cgacols[c][0][0] = 16 + 8; - if (c & 8) cgacols[c][0][1] = 15 + 16; - else cgacols[c][0][1] = 7 + 16; - cgacols[c][1][0] = cgacols[c][1][1] = cgacols[c-0x80][0][0]; - } - for (c = 0x90; c < 0x100; c++) - { - cgacols[c][0][0] = 16 + 15; - if (c & 8) cgacols[c][0][1] = 8 + 16; - else cgacols[c][0][1] = 7 + 16; - if ((c & 0x0F) == 0) cgacols[c][0][1] = 16; - cgacols[c][1][0] = cgacols[c][1][1] = cgacols[c-0x80][0][0]; - } - /* Also special cases for 99, AA, ..., FF */ - for (c = 0x99; c <= 0xFF; c += 0x11) - { - cgacols[c][0][1] = 16 + 15; - } - /* Special cases for 08, 80 and 88 */ - cgacols[0x08][0][1] = 16 + 8; - cgacols[0x80][0][1] = 16; - cgacols[0x88][0][1] = 16 + 8; - - /* MDA attributes */ - for (c = 0; c < 256; c++) - { - mdacols[c][0][0] = mdacols[c][1][0] = mdacols[c][1][1] = 16; - if (c & 8) mdacols[c][0][1] = 15 + 16; - else mdacols[c][0][1] = 7 + 16; - } - mdacols[0x70][0][1] = 16; - mdacols[0x70][0][0] = mdacols[0x70][1][0] = mdacols[0x70][1][1] = 16 + 15; - mdacols[0xF0][0][1] = 16; - mdacols[0xF0][0][0] = mdacols[0xF0][1][0] = mdacols[0xF0][1][1] = 16 + 15; - mdacols[0x78][0][1] = 16 + 7; - mdacols[0x78][0][0] = mdacols[0x78][1][0] = mdacols[0x78][1][1] = 16 + 15; - mdacols[0xF8][0][1] = 16 + 7; - mdacols[0xF8][0][0] = mdacols[0xF8][1][0] = mdacols[0xF8][1][1] = 16 + 15; - mdacols[0x00][0][1] = mdacols[0x00][1][1] = 16; - mdacols[0x08][0][1] = mdacols[0x08][1][1] = 16; - mdacols[0x80][0][1] = mdacols[0x80][1][1] = 16; - mdacols[0x88][0][1] = mdacols[0x88][1][1] = 16; - -/* Start off in 80x25 text mode */ - wy700->cga_stat = 0xF4; - wy700->wy700_mode = 2; - wy700->enabled = 1; - memcpy(wy700->real_crtc, mode_80x24, sizeof(mode_80x24)); - return wy700; + free(wy700->vram); + free(wy700); } -void wy700_close(void *p) +void +wy700_speed_changed(void *priv) { - wy700_t *wy700 = (wy700_t *)p; + wy700_t *wy700 = (wy700_t *) priv; - free(wy700->vram); - free(wy700); + wy700_recalctimings(wy700); } -void wy700_speed_changed(void *p) -{ - wy700_t *wy700 = (wy700_t *)p; - - wy700_recalctimings(wy700); -} - -const device_t wy700_device = -{ - "Wyse 700", - "wy700", - DEVICE_ISA, 0, - wy700_init, - wy700_close, - NULL, - { NULL }, - wy700_speed_changed, - NULL, - NULL +const device_t wy700_device = { + .name = "Wyse 700", + .internal_name = "wy700", + .flags = DEVICE_ISA, + .local = 0, + .init = wy700_init, + .close = wy700_close, + .reset = NULL, + { .available = NULL }, + .speed_changed = wy700_speed_changed, + .force_redraw = NULL, + .config = NULL }; diff --git a/src/video/vid_xga.c b/src/video/vid_xga.c new file mode 100644 index 000000000..f53ba9bb4 --- /dev/null +++ b/src/video/vid_xga.c @@ -0,0 +1,3653 @@ +/* + * 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. + * + * IBM XGA emulation. + * + * + * + * Authors: TheCollector1995. + * + * Copyright 2022 TheCollector1995. + */ +#include +#include +#include +#include +#include +#include <86box/bswap.h> +#include <86box/86box.h> +#include <86box/io.h> +#include <86box/machine.h> +#include <86box/mem.h> +#include <86box/dma.h> +#include <86box/rom.h> +#include <86box/mca.h> +#include <86box/device.h> +#include <86box/timer.h> +#include <86box/video.h> +#include <86box/vid_xga.h> +#include <86box/vid_svga.h> +#include <86box/vid_svga_render.h> +#include <86box/vid_xga_device.h> +#include "cpu.h" +#include <86box/plat_unused.h> + +#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 }; + +static void xga_ext_outb(uint16_t addr, uint8_t val, void *priv); +static uint8_t xga_ext_inb(uint16_t addr, void *priv); + +static void xga_writew(uint32_t addr, uint16_t val, void *priv); +static uint16_t xga_readw(uint32_t addr, void *priv); + +static void xga_render_4bpp(svga_t *svga); +static void xga_render_8bpp(svga_t *svga); +static void xga_render_16bpp(svga_t *svga); + +int xga_active = 0; + +#ifdef ENABLE_XGA_LOG +int xga_do_log = ENABLE_XGA_LOG; + +static void +xga_log(const char *fmt, ...) +{ + va_list ap; + + if (xga_do_log) { + va_start(ap, fmt); + pclog_ex(fmt, ap); + va_end(ap); + } +} +#else +# define xga_log(fmt, ...) +#endif + +void +svga_xga_out(uint16_t addr, uint8_t val, void *priv) +{ + svga_t *svga = (svga_t *) priv; + 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; + + default: + break; + } + svga_out(addr, val, svga); +} + +uint8_t +svga_xga_in(uint16_t addr, void *priv) +{ + svga_t *svga = (svga_t *) priv; + 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 = (xga_t *) svga->xga; + + xga_log("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) || (xga->aperture_cntl == 2)) { + 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) + mem_mapping_disable(&xga->linear_mapping); + } else if (xga->aperture_cntl == 0) { + mem_mapping_set_addr(&xga->video_mapping, 0xa0000, 0x10000); + mem_mapping_enable(&xga->video_mapping); + xga->banked_mask = 0xffff; + 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->a5_test && (xga->access_mode & 8) && !xga->linear_endian_reverse) { + xga->on = 0; + vga_on = 1; + xga_log("A5 test valid.\n"); + } + } + + xga_log("XGA opmode (extended) = %d, disp mode = %d, aperture = %d.\n", xga->op_mode & 7, + xga->disp_cntl_2 & 7, xga->aperture_cntl); + } + xga_log("VGA on = %d, map = %02x.\n", vga_on, svga->gdcreg[6] & 0x0c); +} + +void +xga_recalctimings(svga_t *svga) +{ + xga_t *xga = (xga_t *) svga->xga; + + if (xga->on) { + xga->v_total = xga->vtotal + 1; + xga->dispend = xga->vdispend + 1; + xga->v_syncstart = xga->vsyncstart + 1; + xga->split = xga->linecmp + 1; + xga->v_blankstart = xga->vblankstart + 1; + + xga->h_disp = (xga->hdisp + 1) << 3; + + xga->rowoffset = (xga->hdisp + 1); + + xga->interlace = !!(xga->disp_cntl_1 & 0x08); + xga->rowcount = (xga->disp_cntl_2 & 0xc0) >> 6; + + if (xga->interlace) { + xga->v_total >>= 1; + xga->dispend >>= 1; + xga->v_syncstart >>= 1; + xga->split >>= 1; + xga->v_blankstart >>= 1; + } + + xga->ma_latch = xga->disp_start_addr; + + xga_log("XGA ClkSel1 = %d, ClkSel2 = %02x.\n", (xga->clk_sel_1 >> 2) & 3, xga->clk_sel_2 & 0x80); + switch ((xga->clk_sel_1 >> 2) & 3) { + case 0: + xga_log("HDISP VGA0 = %d, XGA = %d.\n", svga->hdisp, xga->h_disp); + if (xga->clk_sel_2 & 0x80) + svga->clock = (cpuclock * (double) (1ULL << 32)) / 41539000.0; + else + svga->clock = (cpuclock * (double) (1ULL << 32)) / 25175000.0; + break; + case 1: + xga_log("HDISP VGA1 = %d, XGA = %d.\n", svga->hdisp, xga->h_disp); + svga->clock = (cpuclock * (double) (1ULL << 32)) / 28322000.0; + break; + case 3: + svga->clock = (cpuclock * (double) (1ULL << 32)) / 44900000.0; + break; + + default: + break; + } + } +} + +static void +xga_ext_out_reg(xga_t *xga, svga_t *svga, uint8_t idx, uint8_t val) +{ + uint8_t index; + + switch (idx) { + case 0x10: + xga->htotal = (xga->htotal & 0xff00) | val; + break; + case 0x11: + xga->htotal = (xga->htotal & 0xff) | (val << 8); + svga_recalctimings(svga); + break; + + case 0x12: + xga->hdisp = (xga->hdisp & 0xff00) | val; + break; + case 0x13: + xga->hdisp = (xga->hdisp & 0xff) | (val << 8); + svga_recalctimings(svga); + break; + + case 0x20: + xga->vtotal = (xga->vtotal & 0xff00) | val; + break; + case 0x21: + xga->vtotal = (xga->vtotal & 0xff) | (val << 8); + svga_recalctimings(svga); + break; + + case 0x22: + xga->vdispend = (xga->vdispend & 0xff00) | val; + break; + case 0x23: + xga->vdispend = (xga->vdispend & 0xff) | (val << 8); + svga_recalctimings(svga); + break; + + case 0x24: + xga->vblankstart = (xga->vblankstart & 0xff00) | val; + break; + case 0x25: + xga->vblankstart = (xga->vblankstart & 0xff) | (val << 8); + svga_recalctimings(svga); + break; + + case 0x28: + xga->vsyncstart = (xga->vsyncstart & 0xff00) | val; + break; + case 0x29: + xga->vsyncstart = (xga->vsyncstart & 0xff) | (val << 8); + svga_recalctimings(svga); + break; + + case 0x2c: + xga->linecmp = (xga->linecmp & 0xff00) | val; + break; + case 0x2d: + xga->linecmp = (xga->linecmp & 0xff) | (val << 8); + svga_recalctimings(svga); + break; + + case 0x30: + xga->hwc_pos_x = (xga->hwc_pos_x & 0x0700) | val; + xga->hwcursor.x = xga->hwc_pos_x; + break; + case 0x31: + xga->hwc_pos_x = (xga->hwc_pos_x & 0xff) | ((val & 0x07) << 8); + xga->hwcursor.x = xga->hwc_pos_x; + break; + + case 0x32: + xga->hwc_hotspot_x = val & 0x3f; + xga->hwcursor.xoff = val & 0x3f; + break; + + case 0x33: + xga->hwc_pos_y = (xga->hwc_pos_y & 0x0700) | val; + xga->hwcursor.y = xga->hwc_pos_y; + break; + case 0x34: + xga->hwc_pos_y = (xga->hwc_pos_y & 0xff) | ((val & 0x07) << 8); + xga->hwcursor.y = xga->hwc_pos_y; + break; + + case 0x35: + xga->hwc_hotspot_y = val & 0x3f; + xga->hwcursor.yoff = val & 0x3f; + break; + + case 0x36: + xga->hwc_control = val; + xga->hwcursor.ena = xga->hwc_control & 1; + break; + + case 0x38: + xga->hwc_color0 = (xga->hwc_color0 & 0xffff00) | val; + break; + case 0x39: + xga->hwc_color0 = (xga->hwc_color0 & 0xff00ff) | (val << 8); + break; + case 0x3a: + xga->hwc_color0 = (xga->hwc_color0 & 0x00ffff) | (val << 16); + break; + + case 0x3b: + xga->hwc_color1 = (xga->hwc_color1 & 0xffff00) | val; + break; + case 0x3c: + xga->hwc_color1 = (xga->hwc_color1 & 0xff00ff) | (val << 8); + break; + case 0x3d: + xga->hwc_color1 = (xga->hwc_color1 & 0x00ffff) | (val << 16); + break; + + case 0x40: + xga->disp_start_addr = (xga->disp_start_addr & 0x7ff00) | val; + break; + case 0x41: + xga->disp_start_addr = (xga->disp_start_addr & 0x700ff) | (val << 8); + break; + case 0x42: + xga->disp_start_addr = (xga->disp_start_addr & 0x0ffff) | ((val & 0x07) << 16); + svga_recalctimings(svga); + break; + + case 0x43: + xga->pix_map_width = (xga->pix_map_width & 0x700) | val; + break; + case 0x44: + xga->pix_map_width = (xga->pix_map_width & 0xff) | ((val & 0x07) << 8); + break; + + case 0x50: + xga_log("Reg50 write = %02x.\n", val); + xga->disp_cntl_1 = val; + svga_recalctimings(svga); + break; + + case 0x51: + xga_log("Reg51 write = %02x.\n", val); + xga->disp_cntl_2 = val; + xga->on = ((val & 7) >= 2); + vga_on = !xga->on; + svga_recalctimings(svga); + break; + + case 0x54: + xga_log("Reg54 write = %02x.\n", val); + xga->clk_sel_1 = val; + svga_recalctimings(svga); + break; + + case 0x55: + xga->border_color = val; + break; + + case 0x59: + xga->direct_color = val; + break; + + case 0x60: + xga->sprite_pal_addr_idx = (xga->sprite_pal_addr_idx & 0x3f00) | val; + svga->dac_pos = 0; + svga->dac_addr = val & 0xff; + break; + case 0x61: + xga->sprite_pal_addr_idx = (xga->sprite_pal_addr_idx & 0xff) | ((val & 0x3f) << 8); + xga->sprite_pos = xga->sprite_pal_addr_idx & 0x1ff; + 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) || (((xga->disp_cntl_2 & 7) == 2) || (xga->disp_cntl_2 & 7) == 4)) + xga->cursor_data_on = 1; + else if (xga->aperture_cntl == 0) { + if (xga->linear_endian_reverse && !(xga->access_mode & 8)) + xga->cursor_data_on = 0; + } + } + + if ((xga->sprite_pos > 16) && (xga->sprite_pos <= 0x1ff)) { + if (xga->aperture_cntl) { + if (xga->sprite_pos & 0x0f) + xga->cursor_data_on = 1; + else + xga->cursor_data_on = 0; + } else { + xga->cursor_data_on = 0; + } + } + + xga_log("Sprite POS = %d, data on = %d, idx = %d, apcntl = %d\n", xga->sprite_pos, + xga->cursor_data_on, xga->sprite_pal_addr_idx, xga->aperture_cntl); + break; + + case 0x62: + xga->sprite_pal_addr_idx_prefetch = (xga->sprite_pal_addr_idx_prefetch & 0x3f00) | val; + svga->dac_pos = 0; + svga->dac_addr = val & 0xff; + break; + case 0x63: + xga->sprite_pal_addr_idx_prefetch = (xga->sprite_pal_addr_idx_prefetch & 0xff) | ((val & 0x3f) << 8); + xga->sprite_pos_prefetch = xga->sprite_pal_addr_idx_prefetch & 0x1ff; + break; + + case 0x64: + svga->dac_mask = val; + break; + + case 0x65: + svga->fullchange = svga->monitor->mon_changeframecount; + switch (svga->dac_pos) { + case 0: + svga->dac_r = val; + svga->dac_pos++; + break; + case 1: + svga->dac_g = val; + svga->dac_pos++; + break; + case 2: + xga->pal_b = val; + index = svga->dac_addr & 0xff; + svga->vgapal[index].r = svga->dac_r; + svga->vgapal[index].g = svga->dac_g; + svga->vgapal[index].b = xga->pal_b; + xga->pallook[index] = makecol32(svga->vgapal[index].r, svga->vgapal[index].g, svga->vgapal[index].b); + svga->dac_pos = 0; + svga->dac_addr = (svga->dac_addr + 1) & 0xff; + break; + + default: + break; + } + break; + + case 0x66: + xga->pal_seq = val; + break; + + case 0x67: + svga->dac_r = val; + break; + case 0x68: + xga->pal_b = val; + break; + case 0x69: + svga->dac_g = val; + break; + + case 0x6a: + xga->sprite_data[xga->sprite_pos] = val; + xga->sprite_pos = (xga->sprite_pos + 1) & 0x3ff; + break; + + case 0x70: + xga_log("Reg70 write = %02x.\n", val); + xga->clk_sel_2 = val; + svga_recalctimings(svga); + break; + + default: + break; + } +} + +static void +xga_ext_outb(uint16_t addr, uint8_t val, void *priv) +{ + svga_t *svga = (svga_t *) priv; + xga_t *xga = (xga_t *) svga->xga; + + xga_log("[%04X:%08X]: EXT OUTB = %02x, val = %02x\n", CS, cpu_state.pc, addr, val); + + switch (addr & 0x0f) { + case 0: + xga->op_mode = val; + break; + case 1: + xga->aperture_cntl = val; + xga_updatemapping(svga); + break; + case 4: + xga->access_mode &= ~8; + if ((xga->disp_cntl_2 & 7) == 4) + xga->aperture_cntl = 0; + break; + case 8: + xga->ap_idx = val; + xga_log("Aperture CNTL = %d, val = %02x, up to bit6 = %02x\n", xga->aperture_cntl, + val, val & 0x3f); + if ((xga->op_mode & 7) < 4) { + xga->write_bank = xga->read_bank = 0; + } else { + if (xga->base_addr_1mb) { + if (xga->aperture_cntl) { + xga->write_bank = (xga->ap_idx & 0x3f) << 16; + xga->read_bank = xga->write_bank; + } else { + xga->write_bank = (xga->ap_idx & 0x30) << 16; + xga->read_bank = xga->write_bank; + } + } else { + xga->write_bank = (xga->ap_idx & 0x3f) << 16; + xga->read_bank = xga->write_bank; + } + } + break; + case 9: + xga->access_mode = val; + break; + case 0x0a: + xga->regs_idx = val; + break; + case 0x0b: + case 0x0c: + case 0x0d: + case 0x0e: + case 0x0f: + xga->regs[xga->regs_idx] = val; + xga_ext_out_reg(xga, svga, xga->regs_idx, xga->regs[xga->regs_idx]); + break; + + default: + break; + } +} + +static uint8_t +xga_ext_inb(uint16_t addr, void *priv) +{ + svga_t *svga = (svga_t *) priv; + xga_t *xga = (xga_t *) svga->xga; + uint8_t ret = 0; + uint8_t index; + + switch (addr & 0x0f) { + case 0: + ret = xga->op_mode; + break; + case 1: + ret = xga->aperture_cntl; + break; + case 8: + ret = xga->ap_idx; + break; + case 9: + ret = xga->access_mode; + break; + case 0x0a: + ret = xga->regs_idx; + break; + case 0x0b: + case 0x0c: + case 0x0d: + case 0x0e: + case 0x0f: + switch (xga->regs_idx) { + case 4: + if (xga->bus & DEVICE_MCA) + ret = 0x01; /*32-bit MCA*/ + else + ret = 0x10; /*16-bit ISA*/ + break; + case 0x10: + ret = xga->htotal & 0xff; + break; + case 0x11: + ret = xga->htotal >> 8; + break; + case 0x12: + ret = xga->hdisp & 0xff; + break; + case 0x13: + ret = xga->hdisp >> 8; + break; + case 0x20: + ret = xga->vtotal & 0xff; + break; + case 0x21: + ret = xga->vtotal >> 8; + break; + case 0x22: + ret = xga->vdispend & 0xff; + break; + case 0x23: + ret = xga->vdispend >> 8; + break; + case 0x24: + ret = xga->vblankstart & 0xff; + break; + case 0x25: + ret = xga->vblankstart >> 8; + break; + case 0x28: + ret = xga->vsyncstart & 0xff; + break; + case 0x29: + ret = xga->vsyncstart >> 8; + break; + case 0x2c: + ret = xga->linecmp & 0xff; + break; + case 0x2d: + ret = xga->linecmp >> 8; + break; + case 0x30: + ret = xga->hwc_pos_x & 0xff; + break; + case 0x31: + ret = xga->hwc_pos_x >> 8; + break; + case 0x32: + ret = xga->hwc_hotspot_x; + break; + case 0x33: + ret = xga->hwc_pos_y & 0xff; + break; + case 0x34: + ret = xga->hwc_pos_y >> 8; + break; + case 0x35: + ret = xga->hwc_hotspot_y; + break; + case 0x36: + ret = xga->hwc_control; + break; + case 0x38: + ret = xga->hwc_color0 & 0xff; + break; + case 0x39: + ret = xga->hwc_color0 >> 8; + break; + case 0x3a: + ret = xga->hwc_color0 >> 16; + break; + case 0x3b: + ret = xga->hwc_color1 & 0xff; + break; + case 0x3c: + ret = xga->hwc_color1 >> 8; + break; + case 0x3d: + ret = xga->hwc_color1 >> 16; + break; + case 0x40: + ret = xga->disp_start_addr & 0xff; + break; + case 0x41: + ret = xga->disp_start_addr >> 8; + break; + case 0x42: + ret = xga->disp_start_addr >> 16; + break; + case 0x43: + ret = xga->pix_map_width & 0xff; + break; + case 0x44: + ret = xga->pix_map_width >> 8; + break; + case 0x50: + ret = xga->disp_cntl_1 | 0x20; + break; + case 0x51: + ret = xga->disp_cntl_2; + break; + case 0x52: + ret = xga->type ? 0xfa : 0xea; + break; + case 0x53: + ret = xga->type ? 0x53 : 0x30; + break; + case 0x54: + ret = xga->clk_sel_1; + break; + case 0x55: + ret = xga->border_color; + break; + + case 0x59: + ret = xga->direct_color; + break; + + case 0x60: + ret = xga->sprite_pal_addr_idx & 0xff; + break; + case 0x61: + ret = xga->sprite_pal_addr_idx >> 8; + break; + + case 0x62: + ret = xga->sprite_pal_addr_idx_prefetch & 0xff; + break; + case 0x63: + ret = xga->sprite_pal_addr_idx_prefetch >> 8; + break; + + case 0x64: + ret = svga->dac_mask; + break; + + case 0x65: + index = svga->dac_addr & 0xff; + switch (svga->dac_pos) { + case 0: + svga->dac_pos++; + ret = svga->vgapal[index].r; + break; + case 1: + svga->dac_pos++; + ret = svga->vgapal[index].g; + break; + case 2: + svga->dac_pos = 0; + svga->dac_addr = (svga->dac_addr + 1) & 0xff; + ret = svga->vgapal[index].b; + break; + + default: + break; + } + break; + + case 0x66: + ret = xga->pal_seq; + break; + + case 0x67: + ret = svga->dac_r; + break; + case 0x68: + ret = xga->pal_b; + break; + case 0x69: + ret = svga->dac_g; + break; + + case 0x6a: + xga_log("Sprite POS Read = %d, addr idx = %04x\n", xga->sprite_pos, + xga->sprite_pal_addr_idx_prefetch); + ret = xga->sprite_data[xga->sprite_pos_prefetch]; + xga->sprite_pos_prefetch = (xga->sprite_pos_prefetch + 1) & 0x3ff; + break; + + case 0x70: + 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; + } + break; + + default: + break; + } + + xga_log("[%04X:%08X]: EXT INB = %02x, ret = %02x\n", CS, cpu_state.pc, addr, ret); + + return ret; +} + +#define READ(addr, dat) \ + dat = xga->vram[(addr) & (xga->vram_mask)]; + +#define WRITE(addr, dat) \ + xga->vram[((addr)) & (xga->vram_mask)] = dat; \ + xga->changedvram[(((addr)) & (xga->vram_mask)) >> 12] = svga->monitor->mon_changeframecount; + +#define READW(addr, dat) \ + dat = *(uint16_t *) &xga->vram[(addr) & (xga->vram_mask)]; + +#define READW_INV(addr, dat) \ + dat = xga->vram[(addr + 1) & (xga->vram_mask)]; \ + dat |= (xga->vram[(addr) & (xga->vram_mask)] << 8); + +#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 WRITEW_INV(addr, dat) \ + xga->vram[((addr + 1)) & (xga->vram_mask)] = dat & 0xff; \ + xga->vram[((addr)) & (xga->vram_mask)] = dat >> 8; \ + 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)) { \ + case 0x00: \ + d = 0; \ + break; \ + case 0x01: \ + d = s & d; \ + break; \ + case 0x02: \ + d = s & ~d; \ + break; \ + case 0x03: \ + d = s; \ + break; \ + case 0x04: \ + d = ~s & d; \ + break; \ + case 0x05: \ + d = d; \ + break; \ + case 0x06: \ + d = s ^ d; \ + break; \ + case 0x07: \ + d = s | d; \ + break; \ + case 0x08: \ + d = ~s & ~d; \ + break; \ + case 0x09: \ + d = s ^ ~d; \ + break; \ + case 0x0a: \ + d = ~d; \ + break; \ + case 0x0b: \ + d = s | ~d; \ + break; \ + case 0x0c: \ + d = ~s; \ + break; \ + case 0x0d: \ + d = ~s | d; \ + break; \ + case 0x0e: \ + d = ~s | ~d; \ + break; \ + case 0x0f: \ + d = ~0; \ + break; \ + case 0x10: \ + d = MAX(s, d); \ + break; \ + case 0x11: \ + d = MIN(s, d); \ + break; \ + case 0x12: \ + d = MIN(~0, s + d); \ + break; \ + case 0x13: \ + d = MAX(0, d - s); \ + break; \ + case 0x14: \ + d = MAX(0, s - d); \ + break; \ + case 0x15: \ + d = (s + d) >> 1; \ + break; \ + } \ + } + +static uint32_t +xga_accel_read_pattern_map_pixel(svga_t *svga, int x, int y, int map, uint32_t base, int width) +{ + const xga_t *xga = (xga_t *) svga->xga; + uint32_t addr = base; + int bits; + uint8_t byte; + uint8_t px; + int skip = 0; + + if (xga->base_addr_1mb) { + if (addr < xga->base_addr_1mb || (addr > (xga->base_addr_1mb + 0xfffff))) + skip = 1; + } else { + if (addr < xga->linear_base || (addr > (xga->linear_base + 0xfffff))) + skip = 1; + } + + addr += (y * (width >> 3)); + addr += (x >> 3); + if (!skip) { + READ(addr, byte); + } else { + byte = mem_readb_phys(addr); + } + if (xga->linear_endian_reverse) { + bits = 7 - (x & 7); + } else { + if ((xga->accel.px_map_format[map] & 8) && !(xga->access_mode & 8)) + bits = (x & 7); + else { + bits = 7 - (x & 7); + } + } + px = (byte >> bits) & 1; + return px; +} + +static uint32_t +xga_accel_read_map_pixel(svga_t *svga, int x, int y, int map, uint32_t base, int width, UNUSED(int usesrc)) +{ + xga_t *xga = (xga_t *) svga->xga; + uint32_t addr = base; + int bits; + uint32_t byte; + uint8_t px; + int skip = 0; + + if (xga->base_addr_1mb) { + if (addr < xga->base_addr_1mb || (addr > (xga->base_addr_1mb + 0xfffff))) + skip = 1; + } else { + if (addr < xga->linear_base || (addr > (xga->linear_base + 0xfffff))) + skip = 1; + } + + switch (xga->accel.px_map_format[map] & 7) { + case 0: /*1-bit*/ + addr += (y * (width >> 3)); + addr += (x >> 3); + if (!skip) { + READ(addr, byte); + } else { + byte = mem_readb_phys(addr); + } + if (xga->linear_endian_reverse) { + bits = 7 - (x & 7); + } else { + if ((xga->accel.px_map_format[map] & 8) && !(xga->access_mode & 8)) + bits = (x & 7); + else { + bits = 7 - (x & 7); + } + } + px = (byte >> bits) & 1; + return px; + case 2: /*4-bit*/ + addr += (y * (width >> 1)); + addr += (x >> 1); + if (!skip) { + READ(addr, byte); + } else { + byte = mem_readb_phys(addr); + } + return byte; + case 3: /*8-bit*/ + addr += (y * width); + addr += x; + if (!skip) { + READ(addr, byte); + } else { + byte = mem_readb_phys(addr); + } + return byte; + case 4: /*16-bit*/ + addr += (y * (width << 1)); + addr += (x << 1); + if (xga->linear_endian_reverse) { + byte = mem_readw_phys(addr); + if ((xga->access_mode & 7) == 4) + byte = ((byte & 0xff00) >> 8) | ((byte & 0x00ff) << 8); + else if (xga->access_mode & 8) + byte = ((byte & 0xff00) >> 8) | ((byte & 0x00ff) << 8); + } else { + if (!skip) { + READW(addr, byte); + } else { + byte = mem_readb_phys(addr) | (mem_readb_phys(addr + 1) << 8); + } + } + return byte; + + default: + break; + } + return 0; +} + +static void +xga_accel_write_map_pixel(svga_t *svga, int x, int y, int map, uint32_t base, uint32_t pixel, int width) +{ + xga_t *xga = (xga_t *) svga->xga; + uint32_t addr = base; + uint8_t byte; + uint8_t mask; + int skip = 0; + + if (xga->base_addr_1mb) { + if (addr < xga->base_addr_1mb || (addr > (xga->base_addr_1mb + 0xfffff))) + skip = 1; + } else { + if (addr < xga->linear_base || (addr > (xga->linear_base + 0xfffff))) + skip = 1; + } + + switch (xga->accel.px_map_format[map] & 7) { + case 0: /*1-bit*/ + addr += (y * (width >> 3)); + addr += (x >> 3); + if (!skip) { + READ(addr, byte); + } else { + byte = mem_readb_phys(addr); + } + if (xga->linear_endian_reverse) { + mask = 1 << (7 - (x & 7)); + } else { + if ((xga->accel.px_map_format[map] & 8) && !(xga->access_mode & 8)) { + mask = 1 << (x & 7); + } else { + mask = 1 << (7 - (x & 7)); + } + } + byte = (byte & ~mask) | ((pixel ? 0xff : 0) & mask); + if (pixel & 1) { + if (!skip) { + xga->vram[addr & (xga->vram_mask)] |= mask; + xga->changedvram[(addr & (xga->vram_mask)) >> 12] = svga->monitor->mon_changeframecount; + } + } else { + if (!skip) { + xga->vram[addr & (xga->vram_mask)] &= ~mask; + xga->changedvram[(addr & (xga->vram_mask)) >> 12] = svga->monitor->mon_changeframecount; + } + } + mem_writeb_phys(addr, byte); + break; + case 2: /*4-bit*/ + addr += (y * (width >> 1)); + addr += (x >> 1); + if (!skip) { + READ(addr, byte); + } else { + byte = mem_readb_phys(addr); + } + if (xga->linear_endian_reverse) { + mask = 0x0f << ((1 - (x & 1)) << 2); + } else { + if ((xga->accel.px_map_format[map] & 8) && !(xga->access_mode & 8)) { + mask = 0x0f << ((x & 1) << 2); + } else { + mask = 0x0f << ((1 - (x & 1)) << 2); + } + } + byte = (byte & ~mask) | (pixel & mask); + if (!skip) { + WRITE(addr, byte); + } + mem_writeb_phys(addr, byte); + break; + case 3: /*8-bit*/ + addr += (y * width); + addr += x; + if (!skip) { + WRITE(addr, pixel & 0xff); + } + mem_writeb_phys(addr, pixel & 0xff); + break; + case 4: /*16-bit*/ + addr += (y * width << 1); + addr += (x << 1); + if (xga->linear_endian_reverse) { + if ((xga->access_mode & 7) == 4) + pixel = ((pixel & 0xff00) >> 8) | ((pixel & 0x00ff) << 8); + else if (xga->access_mode & 8) + pixel = ((pixel & 0xff00) >> 8) | ((pixel & 0x00ff) << 8); + } else { + if (!skip) { + WRITEW(addr, pixel); + } + } + mem_writew_phys(addr, pixel); + break; + + default: + break; + } +} + +static void +xga_short_stroke(svga_t *svga, uint8_t ssv) +{ + xga_t *xga = (xga_t *) svga->xga; + uint32_t src_dat; + uint32_t dest_dat; + uint32_t old_dest_dat; + uint32_t color_cmp = xga->accel.color_cmp; + uint32_t plane_mask = xga->accel.plane_mask; + uint32_t dstbase = xga->accel.px_map_base[xga->accel.dst_map]; + uint32_t srcbase = xga->accel.px_map_base[xga->accel.src_map]; + int y = ssv & 0x0f; + int x = 0; + int dx; + int dy; + int dirx = 0; + int diry = 0; + + dx = xga->accel.dst_map_x & 0x1fff; + if (xga->accel.dst_map_x >= 0x1800) + dx |= ~0x17ff; + + dy = xga->accel.dst_map_y & 0x1fff; + if (xga->accel.dst_map_y >= 0x1800) + dy |= ~0x17ff; + + switch ((ssv >> 5) & 7) { + case 0: + dirx = 1; + diry = 0; + break; + case 1: + dirx = 1; + diry = -1; + break; + case 2: + dirx = 0; + diry = -1; + break; + case 3: + dirx = -1; + diry = -1; + break; + case 4: + dirx = -1; + diry = 0; + break; + case 5: + dirx = -1; + diry = 1; + break; + case 6: + dirx = 0; + diry = 1; + break; + case 7: + dirx = 1; + diry = 1; + break; + + default: + break; + } + + if (xga->accel.pat_src == 8) { + while (y >= 0) { + if (xga->accel.command & 0xc0) { + if ((dx >= xga->accel.mask_map_origin_x_off) && (dx <= ((xga->accel.px_map_width[0] & 0xfff) + xga->accel.mask_map_origin_x_off)) && (dy >= xga->accel.mask_map_origin_y_off) && (dy <= ((xga->accel.px_map_height[0] & 0xfff) + xga->accel.mask_map_origin_y_off))) { + src_dat = (((xga->accel.command >> 28) & 3) == 2) ? xga_accel_read_map_pixel(svga, xga->accel.src_map_x & 0xfff, xga->accel.src_map_y & 0xfff, xga->accel.src_map, srcbase, xga->accel.px_map_width[xga->accel.src_map] + 1, 1) : xga->accel.frgd_color; + dest_dat = xga_accel_read_map_pixel(svga, dx, dy, xga->accel.dst_map, dstbase, xga->accel.px_map_width[xga->accel.dst_map] + 1, 0); + + if ((xga->accel.cc_cond == 4) || ((xga->accel.cc_cond == 1) && (dest_dat > color_cmp)) || ((xga->accel.cc_cond == 2) && (dest_dat == color_cmp)) || ((xga->accel.cc_cond == 3) && (dest_dat < color_cmp)) || ((xga->accel.cc_cond == 5) && (dest_dat >= color_cmp)) || ((xga->accel.cc_cond == 6) && (dest_dat != color_cmp)) || ((xga->accel.cc_cond == 7) && (dest_dat <= color_cmp))) { + old_dest_dat = dest_dat; + ROP(1, dest_dat, src_dat); + dest_dat = (dest_dat & plane_mask) | (old_dest_dat & ~plane_mask); + if ((xga->accel.command & 0x30) == 0) { + if (ssv & 0x10) + xga_accel_write_map_pixel(svga, dx, dy, xga->accel.dst_map, dstbase, dest_dat, xga->accel.px_map_width[xga->accel.dst_map] + 1); + } else if (((xga->accel.command & 0x30) == 0x10) && x) { + if (ssv & 0x10) + xga_accel_write_map_pixel(svga, dx, dy, xga->accel.dst_map, dstbase, dest_dat, xga->accel.px_map_width[xga->accel.dst_map] + 1); + } else if (((xga->accel.command & 0x30) == 0x20) && y) { + if (ssv & 0x10) + xga_accel_write_map_pixel(svga, dx, dy, xga->accel.dst_map, dstbase, dest_dat, xga->accel.px_map_width[xga->accel.dst_map] + 1); + } + } + } + } else { + src_dat = (((xga->accel.command >> 28) & 3) == 2) ? xga_accel_read_map_pixel(svga, xga->accel.src_map_x & 0xfff, xga->accel.src_map_y & 0xfff, xga->accel.src_map, srcbase, xga->accel.px_map_width[xga->accel.src_map] + 1, 1) : xga->accel.frgd_color; + dest_dat = xga_accel_read_map_pixel(svga, dx, dy, xga->accel.dst_map, dstbase, xga->accel.px_map_width[xga->accel.dst_map] + 1, 0); + + if ((xga->accel.cc_cond == 4) || ((xga->accel.cc_cond == 1) && (dest_dat > color_cmp)) || ((xga->accel.cc_cond == 2) && (dest_dat == color_cmp)) || ((xga->accel.cc_cond == 3) && (dest_dat < color_cmp)) || ((xga->accel.cc_cond == 5) && (dest_dat >= color_cmp)) || ((xga->accel.cc_cond == 6) && (dest_dat != color_cmp)) || ((xga->accel.cc_cond == 7) && (dest_dat <= color_cmp))) { + old_dest_dat = dest_dat; + ROP(1, dest_dat, src_dat); + dest_dat = (dest_dat & plane_mask) | (old_dest_dat & ~plane_mask); + if ((xga->accel.command & 0x30) == 0) { + if (ssv & 0x10) + xga_accel_write_map_pixel(svga, dx, dy, xga->accel.dst_map, dstbase, dest_dat, xga->accel.px_map_width[xga->accel.dst_map] + 1); + } else if (((xga->accel.command & 0x30) == 0x10) && x) { + if (ssv & 0x10) + xga_accel_write_map_pixel(svga, dx, dy, xga->accel.dst_map, dstbase, dest_dat, xga->accel.px_map_width[xga->accel.dst_map] + 1); + } else if (((xga->accel.command & 0x30) == 0x20) && y) { + if (ssv & 0x10) + xga_accel_write_map_pixel(svga, dx, dy, xga->accel.dst_map, dstbase, dest_dat, xga->accel.px_map_width[xga->accel.dst_map] + 1); + } + } + } + + if (!y) { + break; + } + + dx += dirx; + dy += diry; + + x++; + y--; + } + } + + xga->accel.dst_map_x = dx; + xga->accel.dst_map_y = dy; +} + +#define SWAP(a, b) \ + tmpswap = a; \ + a = b; \ + b = tmpswap; + +static void +xga_line_draw_write(svga_t *svga) +{ + xga_t *xga = (xga_t *) svga->xga; + uint32_t src_dat; + uint32_t dest_dat; + uint32_t old_dest_dat; + uint32_t color_cmp = xga->accel.color_cmp; + uint32_t plane_mask = xga->accel.plane_mask; + uint32_t dstbase = xga->accel.px_map_base[xga->accel.dst_map]; + uint32_t srcbase = xga->accel.px_map_base[xga->accel.src_map]; + int dminor; + int destxtmp; + int dmajor; + int err; + int tmpswap; + int steep = 1; + int xdir; + int ydir; + int y = xga->accel.blt_width; + int x = 0; + int dx; + int dy; + int draw_pixel; + + dminor = (xga->accel.bres_k1); + if (xga->accel.bres_k1 & 0x2000) + dminor |= ~0x1fff; + dminor >>= 1; + + destxtmp = (xga->accel.bres_k2); + if (xga->accel.bres_k2 & 0x2000) + destxtmp |= ~0x1fff; + + dmajor = -(destxtmp - (dminor << 1)) >> 1; + + err = (xga->accel.bres_err_term); + if (xga->accel.bres_err_term & 0x2000) + err |= ~0x1fff; + + if (xga->accel.octant & 0x02) { + ydir = -1; + } else { + ydir = 1; + } + + if (xga->accel.octant & 0x04) { + xdir = -1; + } else { + xdir = 1; + } + + dx = xga->accel.dst_map_x & 0x1fff; + if (xga->accel.dst_map_x >= 0x1800) + dx |= ~0x17ff; + + dy = xga->accel.dst_map_y & 0x1fff; + if (xga->accel.dst_map_y >= 0x1800) + dy |= ~0x17ff; + + if ((xga->accel.command & 0x30) == 0x30) + xga_log("Line Draw Write: BLTWIDTH=%d, BLTHEIGHT=%d, FRGDCOLOR=%04x, XDIR=%i, YDIR=%i, steep=%s, ERR=%04x.\n", xga->accel.blt_width, xga->accel.blt_height, xga->accel.frgd_color & 0xffff, xdir, ydir, (xga->accel.octant & 0x01) ? "0" : "1", err); + + if (xga->accel.octant & 0x01) { + steep = 0; + SWAP(dx, dy); + SWAP(xdir, ydir); + } + + if (xga->accel.pat_src == 8) { + while (y >= 0) { + draw_pixel = 1; + if (xga->accel.command & 0xc0) { + if (steep) { + if ((dx >= xga->accel.mask_map_origin_x_off) && (dx <= ((xga->accel.px_map_width[0] & 0xfff) + xga->accel.mask_map_origin_x_off)) && (dy >= xga->accel.mask_map_origin_y_off) && (dy <= ((xga->accel.px_map_height[0] & 0xfff) + xga->accel.mask_map_origin_y_off))) { + src_dat = (((xga->accel.command >> 28) & 3) == 2) ? xga_accel_read_map_pixel(svga, xga->accel.src_map_x & 0xfff, xga->accel.src_map_y & 0xfff, xga->accel.src_map, srcbase, xga->accel.px_map_width[xga->accel.src_map] + 1, 1) : xga->accel.frgd_color; + dest_dat = xga_accel_read_map_pixel(svga, dx, dy, xga->accel.dst_map, dstbase, xga->accel.px_map_width[xga->accel.dst_map] + 1, 0); + + if ((xga->accel.cc_cond == 4) || ((xga->accel.cc_cond == 1) && (dest_dat > color_cmp)) || ((xga->accel.cc_cond == 2) && (dest_dat == color_cmp)) || ((xga->accel.cc_cond == 3) && (dest_dat < color_cmp)) || ((xga->accel.cc_cond == 5) && (dest_dat >= color_cmp)) || ((xga->accel.cc_cond == 6) && (dest_dat != color_cmp)) || ((xga->accel.cc_cond == 7) && (dest_dat <= color_cmp))) { + old_dest_dat = dest_dat; + ROP(1, dest_dat, src_dat); + dest_dat = (dest_dat & plane_mask) | (old_dest_dat & ~plane_mask); + if ((xga->accel.command & 0x30) == 0) + xga_accel_write_map_pixel(svga, dx, dy, xga->accel.dst_map, dstbase, dest_dat, xga->accel.px_map_width[xga->accel.dst_map] + 1); + else if (((xga->accel.command & 0x30) == 0x10) && x) + xga_accel_write_map_pixel(svga, dx, dy, xga->accel.dst_map, dstbase, dest_dat, xga->accel.px_map_width[xga->accel.dst_map] + 1); + else if (((xga->accel.command & 0x30) == 0x20) && y) + xga_accel_write_map_pixel(svga, dx, dy, xga->accel.dst_map, dstbase, dest_dat, xga->accel.px_map_width[xga->accel.dst_map] + 1); + else if ((xga->accel.command & 0x30) == 0x30) { + if (err < 0) + draw_pixel = 0; + else { + if (ydir == -1) { /*Bottom-to-Top*/ + if (!x) + draw_pixel = 0; + } else { /*Top-to-Bottom*/ + if (!y) + draw_pixel = 0; + } + } + if (draw_pixel) + xga_accel_write_map_pixel(svga, dx, dy, xga->accel.dst_map, dstbase, dest_dat, xga->accel.px_map_width[xga->accel.dst_map] + 1); + } + } + } + } else { + if ((dy >= xga->accel.mask_map_origin_x_off) && (dy <= ((xga->accel.px_map_width[0] & 0xfff) + xga->accel.mask_map_origin_x_off)) && (dx >= xga->accel.mask_map_origin_y_off) && (dx <= ((xga->accel.px_map_height[0] & 0xfff) + xga->accel.mask_map_origin_y_off))) { + src_dat = (((xga->accel.command >> 28) & 3) == 2) ? xga_accel_read_map_pixel(svga, xga->accel.src_map_x & 0xfff, xga->accel.src_map_y & 0xfff, xga->accel.src_map, srcbase, xga->accel.px_map_width[xga->accel.src_map] + 1, 1) : xga->accel.frgd_color; + dest_dat = xga_accel_read_map_pixel(svga, dy, dx, xga->accel.dst_map, dstbase, xga->accel.px_map_width[xga->accel.dst_map] + 1, 0); + + if ((xga->accel.cc_cond == 4) || ((xga->accel.cc_cond == 1) && (dest_dat > color_cmp)) || ((xga->accel.cc_cond == 2) && (dest_dat == color_cmp)) || ((xga->accel.cc_cond == 3) && (dest_dat < color_cmp)) || ((xga->accel.cc_cond == 5) && (dest_dat >= color_cmp)) || ((xga->accel.cc_cond == 6) && (dest_dat != color_cmp)) || ((xga->accel.cc_cond == 7) && (dest_dat <= color_cmp))) { + old_dest_dat = dest_dat; + ROP(1, dest_dat, src_dat); + dest_dat = (dest_dat & plane_mask) | (old_dest_dat & ~plane_mask); + if ((xga->accel.command & 0x30) == 0) + xga_accel_write_map_pixel(svga, dy, dx, xga->accel.dst_map, dstbase, dest_dat, xga->accel.px_map_width[xga->accel.dst_map] + 1); + else if (((xga->accel.command & 0x30) == 0x10) && x) + xga_accel_write_map_pixel(svga, dy, dx, xga->accel.dst_map, dstbase, dest_dat, xga->accel.px_map_width[xga->accel.dst_map] + 1); + else if (((xga->accel.command & 0x30) == 0x20) && y) + xga_accel_write_map_pixel(svga, dy, dx, xga->accel.dst_map, dstbase, dest_dat, xga->accel.px_map_width[xga->accel.dst_map] + 1); + else if ((xga->accel.command & 0x30) == 0x30) { + if (xdir == -1) { /*Bottom-to-Top*/ + if (!x) + draw_pixel = 0; + } else { /*Top-to-Bottom*/ + if (!y) + draw_pixel = 0; + } + if (draw_pixel) + xga_accel_write_map_pixel(svga, dy, dx, xga->accel.dst_map, dstbase, dest_dat, xga->accel.px_map_width[xga->accel.dst_map] + 1); + } + } + } + } + } else { + if (steep) { + src_dat = (((xga->accel.command >> 28) & 3) == 2) ? xga_accel_read_map_pixel(svga, xga->accel.src_map_x & 0xfff, xga->accel.src_map_y & 0xfff, xga->accel.src_map, srcbase, xga->accel.px_map_width[xga->accel.src_map] + 1, 1) : xga->accel.frgd_color; + dest_dat = xga_accel_read_map_pixel(svga, dx, dy, xga->accel.dst_map, dstbase, xga->accel.px_map_width[xga->accel.dst_map] + 1, 0); + + if ((xga->accel.cc_cond == 4) || ((xga->accel.cc_cond == 1) && (dest_dat > color_cmp)) || ((xga->accel.cc_cond == 2) && (dest_dat == color_cmp)) || ((xga->accel.cc_cond == 3) && (dest_dat < color_cmp)) || ((xga->accel.cc_cond == 5) && (dest_dat >= color_cmp)) || ((xga->accel.cc_cond == 6) && (dest_dat != color_cmp)) || ((xga->accel.cc_cond == 7) && (dest_dat <= color_cmp))) { + old_dest_dat = dest_dat; + ROP(1, dest_dat, src_dat); + dest_dat = (dest_dat & plane_mask) | (old_dest_dat & ~plane_mask); + if ((xga->accel.command & 0x30) == 0) + xga_accel_write_map_pixel(svga, dx, dy, xga->accel.dst_map, dstbase, dest_dat, xga->accel.px_map_width[xga->accel.dst_map] + 1); + else if (((xga->accel.command & 0x30) == 0x10) && x) + xga_accel_write_map_pixel(svga, dx, dy, xga->accel.dst_map, dstbase, dest_dat, xga->accel.px_map_width[xga->accel.dst_map] + 1); + else if (((xga->accel.command & 0x30) == 0x20) && y) + xga_accel_write_map_pixel(svga, dx, dy, xga->accel.dst_map, dstbase, dest_dat, xga->accel.px_map_width[xga->accel.dst_map] + 1); + else if ((xga->accel.command & 0x30) == 0x30) { + if (err < 0) + draw_pixel = 0; + else { + if (ydir == -1) { /*Bottom-to-Top*/ + if (!x) + draw_pixel = 0; + } else { /*Top-to-Bottom*/ + if (!y) + draw_pixel = 0; + } + } + if (draw_pixel) + xga_accel_write_map_pixel(svga, dx, dy, xga->accel.dst_map, dstbase, dest_dat, xga->accel.px_map_width[xga->accel.dst_map] + 1); + } + } + } else { + src_dat = (((xga->accel.command >> 28) & 3) == 2) ? xga_accel_read_map_pixel(svga, xga->accel.src_map_x & 0xfff, xga->accel.src_map_y & 0xfff, xga->accel.src_map, srcbase, xga->accel.px_map_width[xga->accel.src_map] + 1, 1) : xga->accel.frgd_color; + dest_dat = xga_accel_read_map_pixel(svga, dy, dx, xga->accel.dst_map, dstbase, xga->accel.px_map_width[xga->accel.dst_map] + 1, 0); + + if ((xga->accel.cc_cond == 4) || ((xga->accel.cc_cond == 1) && (dest_dat > color_cmp)) || ((xga->accel.cc_cond == 2) && (dest_dat == color_cmp)) || ((xga->accel.cc_cond == 3) && (dest_dat < color_cmp)) || ((xga->accel.cc_cond == 5) && (dest_dat >= color_cmp)) || ((xga->accel.cc_cond == 6) && (dest_dat != color_cmp)) || ((xga->accel.cc_cond == 7) && (dest_dat <= color_cmp))) { + old_dest_dat = dest_dat; + ROP(1, dest_dat, src_dat); + dest_dat = (dest_dat & plane_mask) | (old_dest_dat & ~plane_mask); + if ((xga->accel.command & 0x30) == 0) + xga_accel_write_map_pixel(svga, dy, dx, xga->accel.dst_map, dstbase, dest_dat, xga->accel.px_map_width[xga->accel.dst_map] + 1); + else if (((xga->accel.command & 0x30) == 0x10) && x) + xga_accel_write_map_pixel(svga, dy, dx, xga->accel.dst_map, dstbase, dest_dat, xga->accel.px_map_width[xga->accel.dst_map] + 1); + else if (((xga->accel.command & 0x30) == 0x20) && y) + xga_accel_write_map_pixel(svga, dy, dx, xga->accel.dst_map, dstbase, dest_dat, xga->accel.px_map_width[xga->accel.dst_map] + 1); + else if ((xga->accel.command & 0x30) == 0x30) { + if (xdir == -1) { /*Bottom-to-Top*/ + if (!x) + draw_pixel = 0; + } else { /*Top-to-Bottom*/ + if (!y) + draw_pixel = 0; + } + if (draw_pixel) + xga_accel_write_map_pixel(svga, dy, dx, xga->accel.dst_map, dstbase, dest_dat, xga->accel.px_map_width[xga->accel.dst_map] + 1); + } + } + } + } + + if (!y) { + break; + } + + while (err >= 0) { + dy += ydir; + err -= (dmajor << 1); + } + + dx += xdir; + err += (dminor << 1); + + x++; + y--; + } + } + + if (steep) { + xga->accel.dst_map_x = dx; + xga->accel.dst_map_y = dy; + } else { + xga->accel.dst_map_x = dy; + xga->accel.dst_map_y = dx; + } +} + +#undef SWAP + +static void +xga_bitblt(svga_t *svga) +{ + xga_t *xga = (xga_t *) svga->xga; + uint8_t area_state = 0; + uint32_t src_dat; + uint32_t dest_dat; + uint32_t old_dest_dat; + uint32_t color_cmp = xga->accel.color_cmp; + uint32_t plane_mask = xga->accel.plane_mask; + uint32_t patbase = xga->accel.px_map_base[xga->accel.pat_src]; + uint32_t dstbase = xga->accel.px_map_base[xga->accel.dst_map]; + uint32_t srcbase = xga->accel.px_map_base[xga->accel.src_map]; + uint32_t patwidth = xga->accel.px_map_width[xga->accel.pat_src]; + uint32_t dstwidth = xga->accel.px_map_width[xga->accel.dst_map]; + uint32_t srcwidth = xga->accel.px_map_width[xga->accel.src_map]; + uint32_t patheight = xga->accel.px_map_height[xga->accel.pat_src]; + uint32_t srcheight = xga->accel.px_map_height[xga->accel.src_map]; +#if 0 + uint32_t dstheight = xga->accel.px_map_height[xga->accel.dst_map]; +#endif + uint32_t frgdcol = xga->accel.frgd_color; + uint32_t bkgdcol = xga->accel.bkgd_color; + int mix = 0; + int xdir; + int ydir; + + if (xga->accel.octant & 0x02) { + ydir = -1; + } else { + ydir = 1; + } + + if (xga->accel.octant & 0x04) { + xdir = -1; + } else { + xdir = 1; + } + + xga->accel.x = xga->accel.blt_width & 0xfff; + xga->accel.y = xga->accel.blt_height & 0xfff; + + xga->accel.sx = xga->accel.src_map_x & 0xfff; + xga->accel.sy = xga->accel.src_map_y & 0xfff; + xga->accel.px = xga->accel.pat_map_x & 0xfff; + xga->accel.py = xga->accel.pat_map_y & 0xfff; + xga->accel.dx = xga->accel.dst_map_x & 0x1fff; + if (xga->accel.dst_map_x >= 0x1800) + xga->accel.dx |= ~0x17ff; + xga->accel.dy = xga->accel.dst_map_y & 0x1fff; + if (xga->accel.dst_map_y >= 0x1800) + xga->accel.dy |= ~0x17ff; + + xga->accel.pattern = 0; + + xga_log("XGA bitblt linear endian reverse=%d, access_mode=%x, octanty=%d, src command = %08x, " + "pxsrcmap=%x, pxpatmap=%x, pxdstmap=%x, srcmap=%d, patmap=%d, dstmap=%d, " + "usesrcvramfr=%d, usevrambk=%d.\n", + xga->linear_endian_reverse, xga->access_mode & 0x0f, ydir, xga->accel.command, + xga->accel.px_map_format[xga->accel.src_map] & 0x0f, + xga->accel.px_map_format[xga->accel.pat_src] & 0x0f, + xga->accel.px_map_format[xga->accel.dst_map] & 0x0f, + xga->accel.src_map, xga->accel.pat_src, + xga->accel.dst_map, ((xga->accel.command >> 28) & 3), ((xga->accel.command >> 30) & 3)); + + if (xga->accel.pat_src == 8) { + if (srcheight == 7) + xga->accel.pattern = 1; + else { + if ((dstwidth == (xga->h_disp - 1)) && (srcwidth == 1)) { + if ((xga->accel.dst_map == 1) && (xga->accel.src_map == 2) && xga->linear_endian_reverse) { + if ((xga->accel.px_map_format[xga->accel.dst_map] >= 0x0b) && (xga->accel.px_map_format[xga->accel.src_map] >= 0x0b)) { + xga->accel.pattern = 1; + } + } + } + } + + xga_log("Pattern Map = 8: CMD = %08x: SRCBase = %08x, DSTBase = %08x, from/to vram dir = %d, " + "cmd dir = %06x\n", xga->accel.command, srcbase, dstbase, xga->from_to_vram, + xga->accel.dir_cmd); + xga_log("CMD = %08x: Y = %d, X = %d, patsrc = %02x, srcmap = %d, dstmap = %d, py = %d, " + "sy = %d, dy = %d, width0 = %d, width1 = %d, width2 = %d, width3 = %d\n", + xga->accel.command, xga->accel.y, xga->accel.x, xga->accel.pat_src, xga->accel.src_map, + xga->accel.dst_map, xga->accel.py, xga->accel.sy, xga->accel.dy, + xga->accel.px_map_width[0], xga->accel.px_map_width[1], + xga->accel.px_map_width[2], xga->accel.px_map_width[3]); + + while (xga->accel.y >= 0) { + if (xga->accel.command & 0xc0) { + if ((xga->accel.dx >= xga->accel.mask_map_origin_x_off) && (xga->accel.dx <= ((xga->accel.px_map_width[0] & 0xfff) + xga->accel.mask_map_origin_x_off)) && (xga->accel.dy >= xga->accel.mask_map_origin_y_off) && (xga->accel.dy <= ((xga->accel.px_map_height[0] & 0xfff) + xga->accel.mask_map_origin_y_off))) { + src_dat = (((xga->accel.command >> 28) & 3) == 2) ? xga_accel_read_map_pixel(svga, xga->accel.sx, xga->accel.sy, xga->accel.src_map, srcbase, srcwidth + 1, 1) : frgdcol; + dest_dat = xga_accel_read_map_pixel(svga, xga->accel.dx, xga->accel.dy, xga->accel.dst_map, dstbase, dstwidth + 1, 0); + if ((xga->accel.cc_cond == 4) || ((xga->accel.cc_cond == 1) && (dest_dat > color_cmp)) || ((xga->accel.cc_cond == 2) && (dest_dat == color_cmp)) || ((xga->accel.cc_cond == 3) && (dest_dat < color_cmp)) || ((xga->accel.cc_cond == 5) && (dest_dat >= color_cmp)) || ((xga->accel.cc_cond == 6) && (dest_dat != color_cmp)) || ((xga->accel.cc_cond == 7) && (dest_dat <= color_cmp))) { + old_dest_dat = dest_dat; + ROP(1, dest_dat, src_dat); + dest_dat = (dest_dat & plane_mask) | (old_dest_dat & ~plane_mask); + xga_accel_write_map_pixel(svga, xga->accel.dx, xga->accel.dy, xga->accel.dst_map, dstbase, dest_dat, dstwidth + 1); + } + } + } else { + src_dat = (((xga->accel.command >> 28) & 3) == 2) ? xga_accel_read_map_pixel(svga, xga->accel.sx, xga->accel.sy, xga->accel.src_map, srcbase, srcwidth + 1, 1) : frgdcol; + dest_dat = xga_accel_read_map_pixel(svga, xga->accel.dx, xga->accel.dy, xga->accel.dst_map, dstbase, dstwidth + 1, 0); + if ((xga->accel.cc_cond == 4) || ((xga->accel.cc_cond == 1) && (dest_dat > color_cmp)) || ((xga->accel.cc_cond == 2) && (dest_dat == color_cmp)) || ((xga->accel.cc_cond == 3) && (dest_dat < color_cmp)) || ((xga->accel.cc_cond == 5) && (dest_dat >= color_cmp)) || ((xga->accel.cc_cond == 6) && (dest_dat != color_cmp)) || ((xga->accel.cc_cond == 7) && (dest_dat <= color_cmp))) { + old_dest_dat = dest_dat; + ROP(1, dest_dat, src_dat); + dest_dat = (dest_dat & plane_mask) | (old_dest_dat & ~plane_mask); + xga_accel_write_map_pixel(svga, xga->accel.dx, xga->accel.dy, xga->accel.dst_map, dstbase, dest_dat, dstwidth + 1); + } + } + + if (xga->accel.pattern) + xga->accel.sx = ((xga->accel.sx + xdir) & srcwidth) | (xga->accel.sx & ~srcwidth); + else + xga->accel.sx += xdir; + xga->accel.dx += xdir; + xga->accel.x--; + if (xga->accel.x < 0) { + xga->accel.x = (xga->accel.blt_width & 0xfff); + + xga->accel.dx = xga->accel.dst_map_x & 0x1fff; + if (xga->accel.dst_map_x >= 0x1800) + xga->accel.dx |= ~0x17ff; + xga->accel.sx = xga->accel.src_map_x & 0xfff; + + xga->accel.dy += ydir; + if (xga->accel.pattern) + xga->accel.sy = ((xga->accel.sy + ydir) & srcheight) | (xga->accel.sy & ~srcheight); + else + xga->accel.sy += ydir; + + xga->accel.y--; + + if (xga->accel.y < 0) { + xga->accel.dst_map_x = xga->accel.dx; + xga->accel.dst_map_y = xga->accel.dy; + return; + } + } + } + } else if (xga->accel.pat_src >= 1) { + if (patheight == 7) + xga->accel.pattern = 1; + else { + if (dstwidth == (xga->h_disp - 1)) { + if (srcwidth == (xga->h_disp - 1)) { + if ((xga->accel.src_map == 1) && (xga->accel.dst_map == 1) && (xga->accel.pat_src == 2) && xga->linear_endian_reverse) { + if ((xga->accel.px_map_format[xga->accel.dst_map] >= 0x0b) && (xga->accel.px <= 7) && (xga->accel.py <= 3)) { + xga->accel.pattern = 1; + } + } + } else { + if (!xga->accel.src_map && (xga->accel.dst_map == 1) && (xga->accel.pat_src == 2) && xga->linear_endian_reverse) { + if ((xga->accel.px_map_format[xga->accel.dst_map] >= 0x0b) && (xga->accel.px <= 7) && (xga->accel.py <= 3)) { + if ((patwidth >= 7) && ((xga->accel.command & 0xc0) == 0x40)) + xga->accel.pattern = 0; + else + xga->accel.pattern = 1; + } + } + } + } + } + + xga_log("XGA bitblt linear endian reverse=%d, octanty=%d, src command = %08x, pxsrcmap=%x, " + "pxdstmap=%x, srcmap=%d, patmap=%d, dstmap=%d, dstwidth=%d, dstheight=%d, srcwidth=%d, " + "srcheight=%d, dstbase=%08x, srcbase=%08x.\n", xga->linear_endian_reverse, ydir, + xga->accel.command, xga->accel.px_map_format[xga->accel.src_map] & 0x0f, + xga->accel.px_map_format[xga->accel.dst_map] & 0x0f, xga->accel.src_map, + xga->accel.pat_src, xga->accel.dst_map, dstwidth, dstheight, srcwidth, srcheight, + dstbase, srcbase); + xga_log("Pattern Map = %d: CMD = %08x: PATBase = %08x, SRCBase = %08x, DSTBase = %08x\n", + xga->accel.pat_src, xga->accel.command, patbase, srcbase, dstbase); + xga_log("CMD = %08x: Y = %d, X = %d, patsrc = %02x, srcmap = %d, dstmap = %d, py = %d, " + "sy = %d, dy = %d, width0 = %d, width1 = %d, width2 = %d, width3 = %d, bkgdcol = %02x\n", + xga->accel.command, xga->accel.y, xga->accel.x, xga->accel.pat_src, + xga->accel.src_map, xga->accel.dst_map, xga->accel.py, xga->accel.sy, xga->accel.dy, + xga->accel.px_map_width[0], xga->accel.px_map_width[1], + xga->accel.px_map_width[2], xga->accel.px_map_width[3], bkgdcol); + + if (((xga->accel.command >> 24) & 0x0f) == 0x0a) { + while (xga->accel.y >= 0) { + mix = xga_accel_read_pattern_map_pixel(svga, xga->accel.px, xga->accel.py, xga->accel.pat_src, patbase, patwidth + 1); + if (mix) + area_state ^= 1; + + if (xga->accel.command & 0xc0) { + if ((xga->accel.dx >= xga->accel.mask_map_origin_x_off) && (xga->accel.dx <= ((xga->accel.px_map_width[0] & 0xfff) + xga->accel.mask_map_origin_x_off)) && (xga->accel.dy >= xga->accel.mask_map_origin_y_off) && (xga->accel.dy <= ((xga->accel.px_map_height[0] & 0xfff) + xga->accel.mask_map_origin_y_off))) { + if (area_state) + src_dat = (((xga->accel.command >> 28) & 3) == 2) ? xga_accel_read_map_pixel(svga, xga->accel.sx, xga->accel.sy, xga->accel.src_map, srcbase, srcwidth + 1, 1) : frgdcol; + else + src_dat = (((xga->accel.command >> 30) & 3) == 2) ? xga_accel_read_map_pixel(svga, xga->accel.sx, xga->accel.sy, xga->accel.src_map, srcbase, srcwidth + 1, 1) : bkgdcol; + + if ((xga->accel.px_map_format[xga->accel.dst_map] & 7) <= 3) + src_dat &= 0xff; + + dest_dat = xga_accel_read_map_pixel(svga, xga->accel.dx, xga->accel.dy, xga->accel.dst_map, dstbase, dstwidth + 1, 0); + if ((xga->accel.cc_cond == 4) || ((xga->accel.cc_cond == 1) && (dest_dat > color_cmp)) || ((xga->accel.cc_cond == 2) && (dest_dat == color_cmp)) || ((xga->accel.cc_cond == 3) && (dest_dat < color_cmp)) || ((xga->accel.cc_cond == 5) && (dest_dat >= color_cmp)) || ((xga->accel.cc_cond == 6) && (dest_dat != color_cmp)) || ((xga->accel.cc_cond == 7) && (dest_dat <= color_cmp))) { + old_dest_dat = dest_dat; + ROP(area_state, dest_dat, src_dat); + dest_dat = (dest_dat & plane_mask) | (old_dest_dat & ~plane_mask); + xga_log("1SRCDat=%02x, DSTDat=%02x, Old=%02x, MIX=%d.\n", src_dat, dest_dat, old_dest_dat, area_state); + xga_accel_write_map_pixel(svga, xga->accel.dx, xga->accel.dy, xga->accel.dst_map, dstbase, dest_dat, dstwidth + 1); + } + } + } else { + if (area_state) + src_dat = (((xga->accel.command >> 28) & 3) == 2) ? xga_accel_read_map_pixel(svga, xga->accel.sx, xga->accel.sy, xga->accel.src_map, srcbase, srcwidth + 1, 1) : frgdcol; + else + src_dat = (((xga->accel.command >> 30) & 3) == 2) ? xga_accel_read_map_pixel(svga, xga->accel.sx, xga->accel.sy, xga->accel.src_map, srcbase, srcwidth + 1, 1) : bkgdcol; + + if ((xga->accel.px_map_format[xga->accel.dst_map] & 7) <= 3) + src_dat &= 0xff; + + dest_dat = xga_accel_read_map_pixel(svga, xga->accel.dx, xga->accel.dy, xga->accel.dst_map, dstbase, dstwidth + 1, 0); + if ((xga->accel.cc_cond == 4) || ((xga->accel.cc_cond == 1) && (dest_dat > color_cmp)) || ((xga->accel.cc_cond == 2) && (dest_dat == color_cmp)) || ((xga->accel.cc_cond == 3) && (dest_dat < color_cmp)) || ((xga->accel.cc_cond == 5) && (dest_dat >= color_cmp)) || ((xga->accel.cc_cond == 6) && (dest_dat != color_cmp)) || ((xga->accel.cc_cond == 7) && (dest_dat <= color_cmp))) { + old_dest_dat = dest_dat; + ROP(area_state, dest_dat, src_dat); + dest_dat = (dest_dat & plane_mask) | (old_dest_dat & ~plane_mask); + xga_log("2Fill: NumXY(%d,%d): DXY(%d,%d): SRCDat=%02x, DSTDat=%02x, Old=%02x, frgdcol=%02x, bkgdcol=%02x, MIX=%d, frgdmix=%02x, bkgdmix=%02x, dstmapfmt=%02x, srcmapfmt=%02x, srcmapnum=%d.\n", x, y, xga->accel.dx, xga->accel.dy, src_dat, dest_dat, old_dest_dat, frgdcol, bkgdcol, area_state, xga->accel.frgd_mix & 0x1f, xga->accel.bkgd_mix & 0x1f, xga->accel.px_map_format[xga->accel.dst_map] & 0x0f, xga->accel.px_map_format[xga->accel.src_map] & 0x0f, xga->accel.src_map); + xga_accel_write_map_pixel(svga, xga->accel.dx, xga->accel.dy, xga->accel.dst_map, dstbase, dest_dat, dstwidth + 1); + } + } + + xga->accel.sx = ((xga->accel.sx + 1) & srcwidth) | (xga->accel.sx & ~srcwidth); + xga->accel.px = ((xga->accel.px + 1) & patwidth) | (xga->accel.px & ~patwidth); + xga->accel.dx++; + xga->accel.x--; + if (xga->accel.x < 0) { + area_state = 0; + xga->accel.y--; + xga->accel.x = xga->accel.blt_width & 0xfff; + + xga->accel.dx = xga->accel.dst_map_x & 0x1fff; + if (xga->accel.dst_map_x >= 0x1800) + xga->accel.dx |= ~0x17ff; + xga->accel.sx = xga->accel.src_map_x & 0xfff; + xga->accel.px = xga->accel.pat_map_x & 0xfff; + + xga->accel.sy = ((xga->accel.sy + ydir) & srcheight) | (xga->accel.sy & ~srcheight); + xga->accel.py += ydir; + xga->accel.dy += ydir; + + if (xga->accel.y < 0) { + xga->accel.dst_map_x = xga->accel.dx; + xga->accel.dst_map_y = xga->accel.dy; + return; + } + } + } + } else { + while (xga->accel.y >= 0) { + mix = xga_accel_read_pattern_map_pixel(svga, xga->accel.px, xga->accel.py, xga->accel.pat_src, patbase, patwidth + 1); + + if (xga->accel.command & 0xc0) { + if ((xga->accel.dx >= xga->accel.mask_map_origin_x_off) && (xga->accel.dx <= ((xga->accel.px_map_width[0] & 0xfff) + xga->accel.mask_map_origin_x_off)) && (xga->accel.dy >= xga->accel.mask_map_origin_y_off) && (xga->accel.dy <= ((xga->accel.px_map_height[0] & 0xfff) + xga->accel.mask_map_origin_y_off))) { + if (mix) { + src_dat = (((xga->accel.command >> 28) & 3) == 2) ? xga_accel_read_map_pixel(svga, xga->accel.sx, xga->accel.sy, xga->accel.src_map, srcbase, srcwidth + 1, 1) : frgdcol; + } else { + src_dat = (((xga->accel.command >> 30) & 3) == 2) ? xga_accel_read_map_pixel(svga, xga->accel.sx, xga->accel.sy, xga->accel.src_map, srcbase, srcwidth + 1, 1) : bkgdcol; + } + dest_dat = xga_accel_read_map_pixel(svga, xga->accel.dx, xga->accel.dy, xga->accel.dst_map, dstbase, dstwidth + 1, 0); + if ((xga->accel.cc_cond == 4) || ((xga->accel.cc_cond == 1) && (dest_dat > color_cmp)) || ((xga->accel.cc_cond == 2) && (dest_dat == color_cmp)) || ((xga->accel.cc_cond == 3) && (dest_dat < color_cmp)) || ((xga->accel.cc_cond == 5) && (dest_dat >= color_cmp)) || ((xga->accel.cc_cond == 6) && (dest_dat != color_cmp)) || ((xga->accel.cc_cond == 7) && (dest_dat <= color_cmp))) { + old_dest_dat = dest_dat; + ROP(mix, dest_dat, src_dat); + dest_dat = (dest_dat & plane_mask) | (old_dest_dat & ~plane_mask); + xga_accel_write_map_pixel(svga, xga->accel.dx, xga->accel.dy, xga->accel.dst_map, dstbase, dest_dat, dstwidth + 1); + } + } + } else { + if (mix) { + src_dat = (((xga->accel.command >> 28) & 3) == 2) ? xga_accel_read_map_pixel(svga, xga->accel.sx, xga->accel.sy, xga->accel.src_map, srcbase, srcwidth + 1, 1) : frgdcol; + } else { + src_dat = (((xga->accel.command >> 30) & 3) == 2) ? xga_accel_read_map_pixel(svga, xga->accel.sx, xga->accel.sy, xga->accel.src_map, srcbase, srcwidth + 1, 1) : bkgdcol; + } + dest_dat = xga_accel_read_map_pixel(svga, xga->accel.dx, xga->accel.dy, xga->accel.dst_map, dstbase, dstwidth + 1, 0); + if ((xga->accel.cc_cond == 4) || ((xga->accel.cc_cond == 1) && (dest_dat > color_cmp)) || ((xga->accel.cc_cond == 2) && (dest_dat == color_cmp)) || ((xga->accel.cc_cond == 3) && (dest_dat < color_cmp)) || ((xga->accel.cc_cond == 5) && (dest_dat >= color_cmp)) || ((xga->accel.cc_cond == 6) && (dest_dat != color_cmp)) || ((xga->accel.cc_cond == 7) && (dest_dat <= color_cmp))) { + old_dest_dat = dest_dat; + ROP(mix, dest_dat, src_dat); + dest_dat = (dest_dat & plane_mask) | (old_dest_dat & ~plane_mask); + xga_accel_write_map_pixel(svga, xga->accel.dx, xga->accel.dy, xga->accel.dst_map, dstbase, dest_dat, dstwidth + 1); + } + } + + xga->accel.sx += xdir; + if (xga->accel.pattern) + xga->accel.px = ((xga->accel.px + xdir) & patwidth) | (xga->accel.px & ~patwidth); + else + xga->accel.px += xdir; + xga->accel.dx += xdir; + xga->accel.x--; + if (xga->accel.x < 0) { + xga->accel.y--; + xga->accel.x = (xga->accel.blt_width & 0xfff); + + xga->accel.dx = xga->accel.dst_map_x & 0x1fff; + if (xga->accel.dst_map_x >= 0x1800) + xga->accel.dx |= ~0x17ff; + xga->accel.sx = xga->accel.src_map_x & 0xfff; + xga->accel.px = xga->accel.pat_map_x & 0xfff; + + xga->accel.sy += ydir; + if (xga->accel.pattern) + xga->accel.py = ((xga->accel.py + ydir) & patheight) | (xga->accel.py & ~patheight); + else + xga->accel.py += ydir; + xga->accel.dy += ydir; + + if (xga->accel.y < 0) { + xga->accel.dst_map_x = xga->accel.dx; + xga->accel.dst_map_y = xga->accel.dy; + return; + } + } + } + } + } +} + +static void +xga_mem_write(uint32_t addr, uint32_t val, xga_t *xga, svga_t *svga, int len) +{ + addr &= 0x1fff; + + if (addr >= 0x1800) { + switch (addr & 0x7f) { + case 0x11: + xga->accel.control = val; + break; + + case 0x12: + xga->accel.px_map_idx = val & 3; + break; + + case 0x14: + if (len == 4) + xga->accel.px_map_base[xga->accel.px_map_idx] = val; + else if (len == 2) + xga->accel.px_map_base[xga->accel.px_map_idx] = (xga->accel.px_map_base[xga->accel.px_map_idx] & 0xffff0000) | val; + else + xga->accel.px_map_base[xga->accel.px_map_idx] = (xga->accel.px_map_base[xga->accel.px_map_idx] & 0xffffff00) | val; + break; + case 0x15: + if (len == 1) + xga->accel.px_map_base[xga->accel.px_map_idx] = (xga->accel.px_map_base[xga->accel.px_map_idx] & 0xffff00ff) | (val << 8); + break; + case 0x16: + if (len == 2) + xga->accel.px_map_base[xga->accel.px_map_idx] = (xga->accel.px_map_base[xga->accel.px_map_idx] & 0x0000ffff) | (val << 16); + else + xga->accel.px_map_base[xga->accel.px_map_idx] = (xga->accel.px_map_base[xga->accel.px_map_idx] & 0xff00ffff) | (val << 16); + break; + case 0x17: + if (len == 1) + xga->accel.px_map_base[xga->accel.px_map_idx] = (xga->accel.px_map_base[xga->accel.px_map_idx] & 0x00ffffff) | (val << 24); + break; + + case 0x18: + if (len == 4) { + xga->accel.px_map_width[xga->accel.px_map_idx] = val & 0xffff; + xga->accel.px_map_height[xga->accel.px_map_idx] = (val >> 16) & 0xffff; + } else if (len == 2) { + xga->accel.px_map_width[xga->accel.px_map_idx] = val & 0xffff; + } else + xga->accel.px_map_width[xga->accel.px_map_idx] = (xga->accel.px_map_width[xga->accel.px_map_idx] & 0xff00) | val; + break; + case 0x19: + if (len == 1) + xga->accel.px_map_width[xga->accel.px_map_idx] = (xga->accel.px_map_width[xga->accel.px_map_idx] & 0xff) | (val << 8); + break; + + case 0x1a: + if (len == 2) + xga->accel.px_map_height[xga->accel.px_map_idx] = val & 0xffff; + else + xga->accel.px_map_height[xga->accel.px_map_idx] = (xga->accel.px_map_height[xga->accel.px_map_idx] & 0xff00) | val; + break; + case 0x1b: + if (len == 1) + xga->accel.px_map_height[xga->accel.px_map_idx] = (xga->accel.px_map_height[xga->accel.px_map_idx] & 0xff) | (val << 8); + break; + + case 0x1c: + xga->accel.px_map_format[xga->accel.px_map_idx] = val; + break; + + case 0x20: + if (len >= 2) { + xga->accel.bres_err_term = val & 0x3fff; + if (val & 0x2000) + xga->accel.bres_err_term |= ~0x3fff; + } else + xga->accel.bres_err_term = (xga->accel.bres_err_term & 0x3f00) | val; + break; + case 0x21: + if (len == 1) { + xga->accel.bres_err_term = (xga->accel.bres_err_term & 0xff) | ((val & 0x3f) << 8); + if (val & 0x20) + xga->accel.bres_err_term |= ~0x3fff; + } + break; + + case 0x24: + if (len >= 2) { + xga->accel.bres_k1 = val & 0x3fff; + if (val & 0x2000) + xga->accel.bres_k1 |= ~0x3fff; + } else + xga->accel.bres_k1 = (xga->accel.bres_k1 & 0x3f00) | val; + break; + case 0x25: + if (len == 1) { + xga->accel.bres_k1 = (xga->accel.bres_k1 & 0xff) | ((val & 0x3f) << 8); + if (val & 0x20) + xga->accel.bres_k1 |= ~0x3fff; + } + break; + + case 0x28: + if (len >= 2) { + xga->accel.bres_k2 = val & 0x3fff; + if (val & 0x2000) + xga->accel.bres_k2 |= ~0x3fff; + } else + xga->accel.bres_k2 = (xga->accel.bres_k2 & 0x3f00) | val; + break; + case 0x29: + if (len == 1) { + xga->accel.bres_k2 = (xga->accel.bres_k2 & 0xff) | ((val & 0x3f) << 8); + if (val & 0x20) + xga->accel.bres_k2 |= ~0x3fff; + } + break; + + case 0x2c: + if (len == 4) { + xga->accel.short_stroke = val; + xga->accel.short_stroke_vector1 = xga->accel.short_stroke & 0xff; + xga->accel.short_stroke_vector2 = (xga->accel.short_stroke >> 8) & 0xff; + xga->accel.short_stroke_vector3 = (xga->accel.short_stroke >> 16) & 0xff; + xga->accel.short_stroke_vector4 = (xga->accel.short_stroke >> 24) & 0xff; + + xga_log("1Vector = %02x, 2Vector = %02x, 3Vector = %02x, 4Vector = %02x\n", + xga->accel.short_stroke_vector1, xga->accel.short_stroke_vector2, + xga->accel.short_stroke_vector3, xga->accel.short_stroke_vector4); + + xga_short_stroke(svga, xga->accel.short_stroke_vector1); + xga_short_stroke(svga, xga->accel.short_stroke_vector2); + xga_short_stroke(svga, xga->accel.short_stroke_vector3); + xga_short_stroke(svga, xga->accel.short_stroke_vector4); + } else if (len == 2) + xga->accel.short_stroke = (xga->accel.short_stroke & 0xffff0000) | val; + else + xga->accel.short_stroke = (xga->accel.short_stroke & 0xffffff00) | val; + break; + case 0x2d: + if (len == 1) + xga->accel.short_stroke = (xga->accel.short_stroke & 0xffff00ff) | (val << 8); + break; + case 0x2e: + if (len == 2) { + xga->accel.short_stroke = (xga->accel.short_stroke & 0x0000ffff) | (val << 16); + } else + xga->accel.short_stroke = (xga->accel.short_stroke & 0xff00ffff) | (val << 16); + break; + case 0x2f: + if (len == 1) { + xga->accel.short_stroke = (xga->accel.short_stroke & 0x00ffffff) | (val << 24); + } + break; + + case 0x48: + xga->accel.frgd_mix = val & 0xff; + if (len == 4) { + xga->accel.bkgd_mix = (val >> 8) & 0xff; + xga->accel.cc_cond = (val >> 16) & 0x07; + } else if (len == 2) { + xga->accel.bkgd_mix = (val >> 8) & 0xff; + } + break; + + case 0x49: + xga->accel.bkgd_mix = val & 0xff; + break; + + case 0x4a: + xga->accel.cc_cond = val & 0x07; + break; + + case 0x4c: + if (len == 4) + xga->accel.color_cmp = val; + else if (len == 2) + xga->accel.color_cmp = (xga->accel.color_cmp & 0xffff0000) | val; + else + xga->accel.color_cmp = (xga->accel.color_cmp & 0xffffff00) | val; + break; + case 0x4d: + if (len == 1) + xga->accel.color_cmp = (xga->accel.color_cmp & 0xffff00ff) | (val << 8); + break; + case 0x4e: + if (len == 2) + xga->accel.color_cmp = (xga->accel.color_cmp & 0x0000ffff) | (val << 16); + else + xga->accel.color_cmp = (xga->accel.color_cmp & 0xff00ffff) | (val << 16); + break; + case 0x4f: + if (len == 1) + xga->accel.color_cmp = (xga->accel.color_cmp & 0x00ffffff) | (val << 24); + break; + + case 0x50: + if (len == 4) + xga->accel.plane_mask = val; + else if (len == 2) + xga->accel.plane_mask = (xga->accel.plane_mask & 0xffff0000) | val; + else + xga->accel.plane_mask = (xga->accel.plane_mask & 0xffffff00) | val; + break; + case 0x51: + if (len == 1) + xga->accel.plane_mask = (xga->accel.plane_mask & 0xffff00ff) | (val << 8); + break; + case 0x52: + if (len == 2) + xga->accel.plane_mask = (xga->accel.plane_mask & 0x0000ffff) | (val << 16); + else + xga->accel.plane_mask = (xga->accel.plane_mask & 0xff00ffff) | (val << 16); + break; + case 0x53: + if (len == 1) + xga->accel.plane_mask = (xga->accel.plane_mask & 0x00ffffff) | (val << 24); + break; + + case 0x58: + if (len == 4) + xga->accel.frgd_color = val; + else if (len == 2) + xga->accel.frgd_color = (xga->accel.frgd_color & 0xffff0000) | val; + else + xga->accel.frgd_color = (xga->accel.frgd_color & 0xffffff00) | val; + break; + case 0x59: + if (len == 1) + xga->accel.frgd_color = (xga->accel.frgd_color & 0xffff00ff) | (val << 8); + break; + case 0x5a: + if (len == 2) + xga->accel.frgd_color = (xga->accel.frgd_color & 0x0000ffff) | (val << 16); + else + xga->accel.frgd_color = (xga->accel.frgd_color & 0xff00ffff) | (val << 16); + break; + case 0x5b: + if (len == 1) + xga->accel.frgd_color = (xga->accel.frgd_color & 0x00ffffff) | (val << 24); + break; + + case 0x5c: + if (len == 4) + xga->accel.bkgd_color = val; + else if (len == 2) + xga->accel.bkgd_color = (xga->accel.bkgd_color & 0xffff0000) | val; + else + xga->accel.bkgd_color = (xga->accel.bkgd_color & 0xffffff00) | val; + break; + case 0x5d: + if (len == 1) + xga->accel.bkgd_color = (xga->accel.bkgd_color & 0xffff00ff) | (val << 8); + break; + case 0x5e: + if (len == 2) + xga->accel.bkgd_color = (xga->accel.bkgd_color & 0x0000ffff) | (val << 16); + else + xga->accel.bkgd_color = (xga->accel.bkgd_color & 0xff00ffff) | (val << 16); + break; + case 0x5f: + if (len == 1) + xga->accel.bkgd_color = (xga->accel.bkgd_color & 0x00ffffff) | (val << 24); + break; + + case 0x60: + if (len == 4) { + xga->accel.blt_width = val & 0xffff; + xga->accel.blt_height = (val >> 16) & 0xffff; + } else if (len == 2) { + xga->accel.blt_width = val; + } else + xga->accel.blt_width = (xga->accel.blt_width & 0xff00) | val; + break; + case 0x61: + if (len == 1) + xga->accel.blt_width = (xga->accel.blt_width & 0xff) | (val << 8); + break; + + case 0x62: + if (len == 2) + xga->accel.blt_height = val; + else + xga->accel.blt_height = (xga->accel.blt_height & 0xff00) | val; + break; + case 0x63: + if (len == 1) + xga->accel.blt_height = (xga->accel.blt_height & 0xff) | (val << 8); + break; + + case 0x6c: + if (len == 4) { + xga->accel.mask_map_origin_x_off = val & 0xffff; + xga->accel.mask_map_origin_y_off = (val >> 16) & 0xffff; + } else if (len == 2) { + xga->accel.mask_map_origin_x_off = val; + } else + xga->accel.mask_map_origin_x_off = (xga->accel.mask_map_origin_x_off & 0xff00) | val; + break; + case 0x6d: + if (len == 1) + xga->accel.mask_map_origin_x_off = (xga->accel.mask_map_origin_x_off & 0xff) | (val << 8); + break; + + case 0x6e: + if (len == 2) + xga->accel.mask_map_origin_y_off = val; + else + xga->accel.mask_map_origin_y_off = (xga->accel.mask_map_origin_y_off & 0xff00) | val; + break; + case 0x6f: + if (len == 1) + xga->accel.mask_map_origin_y_off = (xga->accel.mask_map_origin_y_off & 0xff) | (val << 8); + break; + + case 0x70: + if (len == 4) { + xga->accel.src_map_x = val & 0xffff; + xga->accel.src_map_y = (val >> 16) & 0xffff; + } else if (len == 2) + xga->accel.src_map_x = val; + else + xga->accel.src_map_x = (xga->accel.src_map_x & 0xff00) | val; + break; + case 0x71: + if (len == 1) + xga->accel.src_map_x = (xga->accel.src_map_x & 0xff) | (val << 8); + break; + + case 0x72: + if (len == 2) + xga->accel.src_map_y = val; + else + xga->accel.src_map_y = (xga->accel.src_map_y & 0xff00) | val; + break; + case 0x73: + if (len == 1) + xga->accel.src_map_y = (xga->accel.src_map_y & 0xff) | (val << 8); + break; + + case 0x74: + if (len == 4) { + xga->accel.pat_map_x = val & 0xffff; + xga->accel.pat_map_y = (val >> 16) & 0xffff; + } else if (len == 2) + xga->accel.pat_map_x = val; + else + xga->accel.pat_map_x = (xga->accel.pat_map_x & 0xff00) | val; + break; + case 0x75: + if (len == 1) + xga->accel.pat_map_x = (xga->accel.pat_map_x & 0xff) | (val << 8); + break; + + case 0x76: + if (len == 2) + xga->accel.pat_map_y = val; + else + xga->accel.pat_map_y = (xga->accel.pat_map_y & 0xff00) | val; + break; + case 0x77: + if (len == 1) + xga->accel.pat_map_y = (xga->accel.pat_map_y & 0xff) | (val << 8); + break; + + case 0x78: + if (len == 4) { + xga->accel.dst_map_x = val & 0xffff; + xga->accel.dst_map_y = (val >> 16) & 0xffff; + } else if (len == 2) + xga->accel.dst_map_x = val; + else + xga->accel.dst_map_x = (xga->accel.dst_map_x & 0xff00) | val; + break; + case 0x79: + if (len == 1) + xga->accel.dst_map_x = (xga->accel.dst_map_x & 0xff) | (val << 8); + break; + + case 0x7a: + if (len == 2) + xga->accel.dst_map_y = val; + else + xga->accel.dst_map_y = (xga->accel.dst_map_y & 0xff00) | val; + break; + case 0x7b: + if (len == 1) + xga->accel.dst_map_y = (xga->accel.dst_map_y & 0xff) | (val << 8); + break; + + case 0x7c: + if (len == 4) { + xga->accel.command = val; +exec_command: + xga->accel.octant = xga->accel.command & 0x07; + xga->accel.draw_mode = xga->accel.command & 0x30; + xga->accel.pat_src = ((xga->accel.command >> 12) & 0x0f); + xga->accel.dst_map = ((xga->accel.command >> 16) & 0x0f); + xga->accel.src_map = ((xga->accel.command >> 20) & 0x0f); + +#ifdef ENABLE_XGA_LOG + if (xga->accel.pat_src) + xga_log("[%04X:%08X]: Accel Command = %02x, full = %08x, patwidth = %d, " + "dstwidth = %d, srcwidth = %d, patheight = %d, dstheight = %d, " + "srcheight = %d, px = %d, py = %d, dx = %d, dy = %d, sx = %d, " + "sy = %d, patsrc = %d, dstmap = %d, srcmap = %d, dstbase = %08x, " + "srcbase = %08x, patbase = %08x, dstformat = %x, srcformat = %x, " + "planemask = %08x\n\n", + CS, cpu_state.pc, ((xga->accel.command >> 24) & 0x0f), + xga->accel.command, xga->accel.px_map_width[xga->accel.pat_src], + xga->accel.px_map_width[xga->accel.dst_map], + xga->accel.px_map_width[xga->accel.src_map], + xga->accel.px_map_height[xga->accel.pat_src], + xga->accel.px_map_height[xga->accel.dst_map], + xga->accel.px_map_height[xga->accel.src_map], + xga->accel.pat_map_x, xga->accel.pat_map_y, + xga->accel.dst_map_x, xga->accel.dst_map_y, + xga->accel.src_map_x, xga->accel.src_map_y, + xga->accel.pat_src, xga->accel.dst_map, + xga->accel.src_map, xga->accel.px_map_base[xga->accel.dst_map], + xga->accel.px_map_base[xga->accel.src_map], + xga->accel.px_map_base[xga->accel.pat_src], + xga->accel.px_map_format[xga->accel.dst_map] & 0x0f, + xga->accel.px_map_format[xga->accel.src_map] & 0x0f, + xga->accel.plane_mask); +#endif + + switch ((xga->accel.command >> 24) & 0x0f) { + case 2: /*Short Stroke Vectors Read */ + xga_log("Short Stroke Vectors Read.\n"); + break; + case 3: /*Bresenham Line Draw Read*/ + xga_log("Line Draw Read\n"); + break; + case 4: /*Short Stroke Vectors Write*/ + xga_log("Short Stroke Vectors Write.\n"); + break; + case 5: /*Bresenham Line Draw Write*/ + xga_log("Line Draw Write.\n"); + xga_line_draw_write(svga); + break; + case 8: /*BitBLT*/ + xga_log("BitBLT.\n"); + xga_bitblt(svga); + break; + case 9: /*Inverting BitBLT*/ + xga_log("Inverting BitBLT\n"); + break; + case 0x0a: /*Area Fill*/ + xga_log("Area Fill BitBLT.\n"); + xga_bitblt(svga); + break; + + default: + break; + } + } else if (len == 2) { + xga->accel.command = (xga->accel.command & 0xffff0000) | val; + } else + xga->accel.command = (xga->accel.command & 0xffffff00) | val; + break; + case 0x7d: + if (len == 1) + xga->accel.command = (xga->accel.command & 0xffff00ff) | (val << 8); + break; + case 0x7e: + if (len == 2) { + xga->accel.command = (xga->accel.command & 0x0000ffff) | (val << 16); + goto exec_command; + } else + xga->accel.command = (xga->accel.command & 0xff00ffff) | (val << 16); + break; + case 0x7f: + if (len == 1) { + xga->accel.command = (xga->accel.command & 0x00ffffff) | (val << 24); + goto exec_command; + } + break; + + default: + break; + } + } +} + +static void +xga_memio_writeb(uint32_t addr, uint8_t val, void *priv) +{ + svga_t *svga = (svga_t *) priv; + xga_t *xga = (xga_t *) svga->xga; + + xga_mem_write(addr, val, xga, svga, 1); + + xga_log("Write MEMIOB = %04x, val = %02x\n", addr & 0x7f, val); +} + +static void +xga_memio_writew(uint32_t addr, uint16_t val, void *priv) +{ + svga_t *svga = (svga_t *) priv; + xga_t *xga = (xga_t *) svga->xga; + + xga_mem_write(addr, val, xga, svga, 2); + + xga_log("Write MEMIOW = %04x, val = %04x\n", addr & 0x7f, val); +} + +static void +xga_memio_writel(uint32_t addr, uint32_t val, void *priv) +{ + svga_t *svga = (svga_t *) priv; + xga_t *xga = (xga_t *) svga->xga; + + xga_mem_write(addr, val, xga, svga, 4); + + xga_log("Write MEMIOL = %04x, val = %08x\n", addr & 0x7f, val); +} + +static uint8_t +xga_mem_read(uint32_t addr, xga_t *xga, UNUSED(svga_t *svga)) +{ + uint8_t temp = 0; + + addr &= 0x1fff; + if (addr < 0x1800) { + if (xga_standalone_enabled) + 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; + case 0x21: + temp = xga->accel.bres_err_term >> 8; + break; + case 0x22: + temp = xga->accel.bres_err_term >> 16; + break; + case 0x23: + temp = xga->accel.bres_err_term >> 24; + break; + + case 0x70: + temp = xga->accel.src_map_x & 0xff; + break; + case 0x71: + temp = xga->accel.src_map_x >> 8; + break; + + case 0x72: + temp = xga->accel.src_map_y & 0xff; + break; + case 0x73: + temp = xga->accel.src_map_y >> 8; + break; + + case 0x74: + temp = xga->accel.pat_map_x & 0xff; + break; + case 0x75: + temp = xga->accel.pat_map_x >> 8; + break; + + case 0x76: + temp = xga->accel.pat_map_y & 0xff; + break; + case 0x77: + temp = xga->accel.pat_map_y >> 8; + break; + + case 0x78: + temp = xga->accel.dst_map_x & 0xff; + break; + case 0x79: + temp = xga->accel.dst_map_x >> 8; + break; + + case 0x7a: + temp = xga->accel.dst_map_y & 0xff; + break; + case 0x7b: + temp = xga->accel.dst_map_y >> 8; + break; + + default: + break; + } + } + + return temp; +} + +static uint8_t +xga_memio_readb(uint32_t addr, void *priv) +{ + svga_t *svga = (svga_t *) priv; + xga_t *xga = (xga_t *) svga->xga; + uint8_t temp; + + temp = xga_mem_read(addr, xga, svga); + + xga_log("[%04X:%08X]: Read MEMIOB = %04x, temp = %02x\n", CS, cpu_state.pc, addr, temp); + + return temp; +} + +static uint16_t +xga_memio_readw(uint32_t addr, void *priv) +{ + svga_t *svga = (svga_t *) priv; + xga_t *xga = (xga_t *) svga->xga; + uint16_t temp; + + temp = xga_mem_read(addr, xga, svga); + temp |= (xga_mem_read(addr + 1, xga, svga) << 8); + + xga_log("[%04X:%08X]: Read MEMIOW = %04x, temp = %04x\n", CS, cpu_state.pc, addr, temp); + + return temp; +} + +static uint32_t +xga_memio_readl(uint32_t addr, void *priv) +{ + svga_t *svga = (svga_t *) priv; + xga_t *xga = (xga_t *) svga->xga; + uint32_t temp; + + temp = xga_mem_read(addr, xga, svga); + temp |= (xga_mem_read(addr + 1, xga, svga) << 8); + temp |= (xga_mem_read(addr + 2, xga, svga) << 16); + temp |= (xga_mem_read(addr + 3, xga, svga) << 24); + + xga_log("Read MEMIOL = %04x, temp = %08x\n", addr, temp); + + return temp; +} + +static void +xga_hwcursor_draw(svga_t *svga, int displine) +{ + xga_t *xga = (xga_t *) svga->xga; + uint8_t dat = 0; + int offset = xga->hwcursor_latch.x - xga->hwcursor_latch.xoff; + int x_pos; + int y_pos; + int comb = 0; + uint32_t *p; + int idx = (xga->cursor_data_on) ? 32 : 0; + + if (xga->interlace && xga->hwcursor_oddeven) + xga->hwcursor_latch.addr += 16; + + y_pos = displine; + x_pos = offset + svga->x_add; + p = buffer32->line[y_pos]; + + for (int x = 0; x < xga->hwcursor_latch.cur_xsize; x++) { + if (x >= idx) { + if (!(x & 0x03)) + dat = xga->sprite_data[xga->hwcursor_latch.addr & 0x3ff]; + + comb = (dat >> ((x & 0x03) << 1)) & 0x03; + + x_pos = offset + svga->x_add + x; + + switch (comb) { + case 0x00: + /* Cursor Color 1 */ + p[x_pos] = xga->hwc_color0; + break; + case 0x01: + /* Cursor Color 2 */ + p[x_pos] = xga->hwc_color1; + break; + case 0x03: + /* Complement */ + p[x_pos] ^= 0xffffff; + break; + + default: + break; + } + } + + if ((x & 0x03) == 0x03) + xga->hwcursor_latch.addr++; + } + + if (xga->interlace && !xga->hwcursor_oddeven) + xga->hwcursor_latch.addr += 16; +} + +static void +xga_render_overscan_left(xga_t *xga, svga_t *svga) +{ + if ((xga->displine + svga->y_add) < 0) + return; + + 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++) + *line_ptr++ = svga->overscan_color; +} + +static void +xga_render_overscan_right(xga_t *xga, svga_t *svga) +{ + int right; + + if ((xga->displine + svga->y_add) < 0) + return; + + if (svga->scrblank || (xga->h_disp == 0)) + return; + + 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++) + *line_ptr++ = svga->overscan_color; +} + +static void +xga_render_4bpp(svga_t *svga) +{ + xga_t *xga = (xga_t *) svga->xga; + uint32_t *p; + uint32_t dat; + + if ((xga->displine + svga->y_add) < 0) + return; + + if (xga->changedvram[xga->ma >> 12] || xga->changedvram[(xga->ma >> 12) + 1] || svga->fullchange) { + p = &svga->monitor->target_buffer->line[xga->displine + svga->y_add][svga->x_add]; + + if (xga->firstline_draw == 2000) + xga->firstline_draw = xga->displine; + xga->lastline_draw = xga->displine; + + for (int x = 0; x <= xga->h_disp; x += 16) { + dat = *(uint32_t *) (&xga->vram[xga->ma & xga->vram_mask]); + p[0] = xga->pallook[(dat >> 4) & 0x0f]; + p[1] = xga->pallook[dat & 0x0f]; + p[2] = xga->pallook[(dat >> 12) & 0x0f]; + p[3] = xga->pallook[(dat >> 8) & 0x0f]; + p[4] = xga->pallook[(dat >> 20) & 0x0f]; + p[5] = xga->pallook[(dat >> 16) & 0x0f]; + p[6] = xga->pallook[(dat >> 28) & 0x0f]; + p[7] = xga->pallook[(dat >> 24) & 0x0f]; + + dat = *(uint32_t *) (&xga->vram[(xga->ma + 4) & xga->vram_mask]); + p[9] = xga->pallook[dat & 0x0f]; + p[11] = xga->pallook[(dat >> 8) & 0x0f]; + p[13] = xga->pallook[(dat >> 16) & 0x0f]; + p[15] = xga->pallook[(dat >> 24) & 0x0f]; + + xga->ma += 8; + p += 16; + } + xga->ma &= xga->vram_mask; + } +} + +static void +xga_render_8bpp(svga_t *svga) +{ + xga_t *xga = (xga_t *) svga->xga; + uint32_t *p; + uint32_t dat; + + if ((xga->displine + svga->y_add) < 0) + return; + + if (xga->changedvram[xga->ma >> 12] || xga->changedvram[(xga->ma >> 12) + 1] || svga->fullchange) { + p = &svga->monitor->target_buffer->line[xga->displine + svga->y_add][svga->x_add]; + + if (xga->firstline_draw == 2000) + xga->firstline_draw = xga->displine; + xga->lastline_draw = xga->displine; + + for (int x = 0; x <= xga->h_disp; x += 8) { + dat = *(uint32_t *) (&xga->vram[xga->ma & xga->vram_mask]); + p[0] = xga->pallook[dat & 0xff]; + p[1] = xga->pallook[(dat >> 8) & 0xff]; + p[2] = xga->pallook[(dat >> 16) & 0xff]; + p[3] = xga->pallook[(dat >> 24) & 0xff]; + + dat = *(uint32_t *) (&xga->vram[(xga->ma + 4) & xga->vram_mask]); + p[4] = xga->pallook[dat & 0xff]; + p[5] = xga->pallook[(dat >> 8) & 0xff]; + p[6] = xga->pallook[(dat >> 16) & 0xff]; + p[7] = xga->pallook[(dat >> 24) & 0xff]; + + xga->ma += 8; + p += 8; + } + xga->ma &= xga->vram_mask; + } +} + +static void +xga_render_16bpp(svga_t *svga) +{ + xga_t *xga = (xga_t *) svga->xga; + int x; + uint32_t *p; + uint32_t dat; + + if ((xga->displine + svga->y_add) < 0) + return; + + if (xga->changedvram[xga->ma >> 12] || xga->changedvram[(xga->ma >> 12) + 1] || svga->fullchange) { + p = &svga->monitor->target_buffer->line[xga->displine + svga->y_add][svga->x_add]; + + if (xga->firstline_draw == 2000) + xga->firstline_draw = xga->displine; + xga->lastline_draw = xga->displine; + + for (x = 0; x <= (xga->h_disp); x += 8) { + dat = *(uint32_t *) (&xga->vram[(xga->ma + (x << 1)) & xga->vram_mask]); + p[x] = video_16to32[dat & 0xffff]; + p[x + 1] = video_16to32[dat >> 16]; + + dat = *(uint32_t *) (&xga->vram[(xga->ma + (x << 1) + 4) & xga->vram_mask]); + p[x + 2] = video_16to32[dat & 0xffff]; + p[x + 3] = video_16to32[dat >> 16]; + + dat = *(uint32_t *) (&xga->vram[(xga->ma + (x << 1) + 8) & xga->vram_mask]); + p[x + 4] = video_16to32[dat & 0xffff]; + p[x + 5] = video_16to32[dat >> 16]; + + dat = *(uint32_t *) (&xga->vram[(xga->ma + (x << 1) + 12) & xga->vram_mask]); + p[x + 6] = video_16to32[dat & 0xffff]; + p[x + 7] = video_16to32[dat >> 16]; + } + xga->ma += x << 1; + xga->ma &= xga->vram_mask; + } +} + +static void +xga_write(uint32_t addr, uint8_t val, void *priv) +{ + svga_t *svga = (svga_t *) priv; + xga_t *xga = (xga_t *) svga->xga; + + if (!xga->on) { + svga_write(addr, val, svga); + return; + } + + addr &= xga->banked_mask; + addr += xga->write_bank; + + if (addr >= xga->vram_size) + return; + + cycles -= svga->monitor->mon_video_timing_write_b; + + if (xga->access_mode & 8) { + if ((xga->access_mode & 7) == 4) + addr ^= 1; + } + + xga->changedvram[(addr & xga->vram_mask) >> 12] = svga->monitor->mon_changeframecount; + xga->vram[addr & xga->vram_mask] = val; +} + +static void +xga_writew(uint32_t addr, uint16_t val, void *priv) +{ + svga_t *svga = (svga_t *) priv; + xga_t *xga = (xga_t *) svga->xga; + + if (!xga->on) { + svga_writew(addr, val, svga); + return; + } + + xga_write(addr, val & 0xff, svga); + xga_write(addr + 1, val >> 8, svga); +} + +static void +xga_writel(uint32_t addr, uint32_t val, void *priv) +{ + svga_t *svga = (svga_t *) priv; + xga_t *xga = (xga_t *) svga->xga; + + if (!xga->on) { + svga_writel(addr, val, svga); + return; + } + + xga_write(addr, val & 0xff, svga); + xga_write(addr + 1, (val >> 8) & 0xff, svga); + xga_write(addr + 2, (val >> 16) & 0xff, svga); + xga_write(addr + 3, (val >> 24) & 0xff, svga); +} + +static uint8_t +xga_read(uint32_t addr, void *priv) +{ + svga_t *svga = (svga_t *) priv; + xga_t *xga = (xga_t *) svga->xga; + uint8_t ret = 0xff; + + if (!xga->on) { + ret = svga_read(addr, svga); + return ret; + } + + addr &= xga->banked_mask; + addr += xga->read_bank; + + if (addr >= xga->vram_size) + return ret; + + cycles -= svga->monitor->mon_video_timing_read_b; + + if (xga->access_mode & 8) { + if ((xga->access_mode & 7) == 4) + addr ^= 1; + } + + ret = xga->vram[addr & xga->vram_mask]; + + return ret; +} + +static uint16_t +xga_readw(uint32_t addr, void *priv) +{ + svga_t *svga = (svga_t *) priv; + xga_t *xga = (xga_t *) svga->xga; + uint16_t ret = 0xffff; + + if (!xga->on) { + ret = svga_readw(addr, svga); + return ret; + } + + ret = xga_read(addr, svga); + ret |= (xga_read(addr + 1, svga) << 8); + + return ret; +} + +static uint32_t +xga_readl(uint32_t addr, void *priv) +{ + svga_t *svga = (svga_t *) priv; + xga_t *xga = (xga_t *) svga->xga; + uint32_t ret = 0xffffffff; + + if (!xga->on) { + ret = svga_readl(addr, svga); + return ret; + } + + ret = xga_read(addr, svga); + ret |= (xga_read(addr + 1, svga) << 8); + ret |= (xga_read(addr + 2, svga) << 16); + ret |= (xga_read(addr + 3, svga) << 24); + + return ret; +} + +static void +xga_write_linear(uint32_t addr, uint8_t val, void *priv) +{ + svga_t *svga = (svga_t *) priv; + xga_t *xga = (xga_t *) svga->xga; + + if (!xga->on) { + svga_write_linear(addr, val, svga); + return; + } + + addr &= svga->decode_mask; + + if (addr >= xga->vram_size) + return; + + cycles -= svga->monitor->mon_video_timing_write_b; + + if (xga->linear_endian_reverse) { + if ((xga->access_mode & 7) == 4) { + if ((xga->accel.px_map_format[xga->accel.dst_map] & 7) == 4) + addr ^= 1; + } else if (xga->access_mode & 8) { + if ((xga->accel.px_map_format[xga->accel.dst_map] & 7) == 4) + addr ^= 1; + } + } + + xga->changedvram[(addr & xga->vram_mask) >> 12] = svga->monitor->mon_changeframecount; + xga->vram[addr & xga->vram_mask] = val; +} + +static void +xga_writew_linear(uint32_t addr, uint16_t val, void *priv) +{ + svga_t *svga = (svga_t *) priv; + const xga_t *xga = (xga_t *) svga->xga; + + if (!xga->on) { + svga_writew_linear(addr, val, svga); + return; + } + + xga_write_linear(addr, val, priv); + xga_write_linear(addr + 1, val >> 8, priv); +} + +static void +xga_writel_linear(uint32_t addr, uint32_t val, void *priv) +{ + svga_t *svga = (svga_t *) priv; + const xga_t *xga = (xga_t *) svga->xga; + + if (!xga->on) { + svga_writel_linear(addr, val, svga); + return; + } + + xga_write_linear(addr, val, priv); + xga_write_linear(addr + 1, val >> 8, priv); + xga_write_linear(addr + 2, val >> 16, priv); + xga_write_linear(addr + 3, val >> 24, priv); +} + +static uint8_t +xga_read_linear(uint32_t addr, void *priv) +{ + svga_t *svga = (svga_t *) priv; + const xga_t *xga = (xga_t *) svga->xga; + uint8_t ret = 0xff; + + if (!xga->on) + return svga_read_linear(addr, svga); + + addr &= svga->decode_mask; + + if (addr >= xga->vram_size) + return ret; + + cycles -= svga->monitor->mon_video_timing_read_b; + + if (xga->linear_endian_reverse) { + if ((xga->access_mode & 7) == 4) { + if ((xga->accel.px_map_format[xga->accel.dst_map] & 7) == 4) + addr ^= 1; + } else if (xga->access_mode & 8) { + if ((xga->accel.px_map_format[xga->accel.dst_map] & 7) == 4) + addr ^= 1; + } + } + + return xga->vram[addr & xga->vram_mask]; +} + +static uint16_t +xga_readw_linear(uint32_t addr, void *priv) +{ + svga_t *svga = (svga_t *) priv; + const xga_t *xga = (xga_t *) svga->xga; + uint16_t ret; + + if (!xga->on) + return svga_readw_linear(addr, svga); + + ret = xga_read_linear(addr, svga); + ret |= (xga_read_linear(addr + 1, svga) << 8); + + return ret; +} + +static uint32_t +xga_readl_linear(uint32_t addr, void *priv) +{ + svga_t *svga = (svga_t *) priv; + const xga_t *xga = (xga_t *) svga->xga; + uint32_t ret; + + if (!xga->on) + return svga_readl_linear(addr, svga); + + ret = xga_read_linear(addr, svga); + ret |= (xga_read_linear(addr + 1, svga) << 8); + ret |= (xga_read_linear(addr + 2, svga) << 16); + ret |= (xga_read_linear(addr + 3, svga) << 24); + + return ret; +} + +static void +xga_do_render(svga_t *svga) +{ + xga_t *xga = (xga_t *) svga->xga; + + xga_log("DISPCNTL = %d, vga = %d.\n", xga->disp_cntl_2 & 7, vga_on); + switch (xga->disp_cntl_2 & 7) { + case 2: + xga_render_4bpp(svga); + break; + case 3: + xga_render_8bpp(svga); + break; + case 4: + xga_render_16bpp(svga); + break; + default: + break; + } + + svga->x_add = (overscan_x >> 1); + xga_render_overscan_left(xga, svga); + xga_render_overscan_right(xga, svga); + svga->x_add = (overscan_x >> 1); + + if (xga->hwcursor_on) { + xga_hwcursor_draw(svga, xga->displine + svga->y_add); + xga->hwcursor_on--; + if (xga->hwcursor_on && xga->interlace) + xga->hwcursor_on--; + } +} + +void +xga_poll(void *priv, svga_t *svga) +{ + xga_t *xga = (xga_t *) priv; + uint32_t x; + int wx; + int wy; + + if (!xga->linepos) { + if (xga->displine == xga->hwcursor_latch.y && xga->hwcursor_latch.ena) { + xga->hwcursor_on = xga->hwcursor_latch.cur_ysize - (xga->cursor_data_on ? 32 : 0); + xga->hwcursor_oddeven = 0; + } + + if (xga->displine == (xga->hwcursor_latch.y + 1) && xga->hwcursor_latch.ena && xga->interlace) { + xga->hwcursor_on = xga->hwcursor_latch.cur_ysize - (xga->cursor_data_on ? 33 : 1); + xga->hwcursor_oddeven = 1; + } + + timer_advance_u64(&svga->timer, svga->dispofftime); + xga->linepos = 1; + + if (xga->dispon) { + xga->h_disp_on = 1; + + xga->ma &= xga->vram_mask; + + if (xga->firstline == 2000) { + xga->firstline = xga->displine; + video_wait_for_buffer_monitor(svga->monitor_index); + } + + if (xga->hwcursor_on) { + xga->changedvram[xga->ma >> 12] = xga->changedvram[(xga->ma >> 12) + 1] = xga->interlace ? 3 : 2; + } + + xga_do_render(svga); + + if (xga->lastline < xga->displine) + xga->lastline = xga->displine; + } + + xga->displine++; + if (xga->interlace) + xga->displine++; + if (xga->displine > 1500) + xga->displine = 0; + } else { + timer_advance_u64(&svga->timer, svga->dispontime); + xga->h_disp_on = 0; + + xga->linepos = 0; + if (xga->dispon) { + if (xga->sc == xga->rowcount) { + xga->sc = 0; + + xga->maback += (xga->rowoffset << (xga->disp_cntl_2 & 7)); + if (xga->interlace) + xga->maback += (xga->rowoffset << (xga->disp_cntl_2 & 7)); + xga->maback &= xga->vram_mask; + xga->ma = xga->maback; + } else { + xga->sc++; + xga->sc &= 0x1f; + xga->ma = xga->maback; + } + } + + xga->vc++; + xga->vc &= 0x7ff; + + if (xga->vc == xga->split) { + if (xga->interlace && xga->oddeven) + xga->ma = xga->maback = (xga->rowoffset << 1); + else + xga->ma = xga->maback = 0; + xga->ma = (xga->ma << 2); + xga->maback = (xga->maback << 2); + + xga->sc = 0; + } + if (xga->vc == xga->dispend) { + xga->dispon = 0; + + for (x = 0; x < ((xga->vram_mask + 1) >> 12); x++) { + if (xga->changedvram[x]) + xga->changedvram[x]--; + } + if (svga->fullchange) + svga->fullchange--; + } + if (xga->vc == xga->v_syncstart) { + xga->dispon = 0; + x = xga->h_disp; + + if (xga->interlace && !xga->oddeven) + xga->lastline++; + if (xga->interlace && xga->oddeven) + xga->firstline--; + + wx = x; + + wy = xga->lastline - xga->firstline; + svga_doblit(wx, wy, svga); + + xga->firstline = 2000; + xga->lastline = 0; + + xga->firstline_draw = 2000; + xga->lastline_draw = 0; + + xga->oddeven ^= 1; + + svga->monitor->mon_changeframecount = xga->interlace ? 3 : 2; + + if (xga->interlace && xga->oddeven) + xga->ma = xga->maback = xga->ma_latch + (xga->rowoffset << 1); + else + xga->ma = xga->maback = xga->ma_latch; + + xga->ma = (xga->ma << 2); + xga->maback = (xga->maback << 2); + } + if (xga->vc == xga->v_total) { + xga->vc = 0; + xga->sc = 0; + xga->dispon = 1; + xga->displine = (xga->interlace && xga->oddeven) ? 1 : 0; + + svga->x_add = (overscan_x >> 1); + + xga->hwcursor_on = 0; + xga->hwcursor_latch = xga->hwcursor; + } + } +} + +static uint8_t +xga_mca_read(int port, void *priv) +{ + const svga_t *svga = (svga_t *) priv; + const xga_t *xga = (xga_t *) svga->xga; + uint8_t ret = xga->pos_regs[port & 7]; + + if (((port & 7) == 3) && !(ret & 1)) /*Always enable the mapping.*/ + ret |= 1; + + xga_log("[%04X:%08X]: POS Read Port = %x, val = %02x\n", CS, cpu_state.pc, + port & 7, xga->pos_regs[port & 7]); + + return ret; +} + +static void +xga_mca_write(int port, uint8_t val, void *priv) +{ + svga_t *svga = (svga_t *) priv; + xga_t *xga = (xga_t *) svga->xga; + + /* MCA does not write registers below 0x0100. */ + if (port < 0x0102) + return; + + io_removehandler(0x2100 + (xga->instance << 4), 0x0010, xga_ext_inb, NULL, NULL, xga_ext_outb, NULL, NULL, svga); + mem_mapping_disable(&xga->bios_rom.mapping); + mem_mapping_disable(&xga->memio_mapping); + xga->on = 0; + vga_on = 1; + xga->linear_endian_reverse = 0; + xga->a5_test = 0; + + /* Save the MCA register value. */ + xga->pos_regs[port & 7] = val; + if (!(xga->pos_regs[4] & 1) && (mem_size >= 16384)) /*MCA 4MB addressing on systems with more than 16MB of memory*/ + xga->pos_regs[4] |= 1; + + if (xga->pos_regs[2] & 1) { + xga->instance = (xga->pos_regs[2] & 0x0e) >> 1; + xga->base_addr_1mb = (xga->pos_regs[5] & 0x0f) << 20; + xga->linear_base = ((xga->pos_regs[4] & 0xfe) * 0x1000000) + (xga->instance << 22); + xga->rom_addr = 0xc0000 + (((xga->pos_regs[2] & 0xf0) >> 4) * 0x2000); + + io_sethandler(0x2100 + (xga->instance << 4), 0x0010, xga_ext_inb, NULL, NULL, xga_ext_outb, NULL, NULL, svga); + + if (xga->pos_regs[3] & 1) + mem_mapping_set_addr(&xga->bios_rom.mapping, xga->rom_addr, 0x2000); + else + mem_mapping_set_addr(&xga->memio_mapping, xga->rom_addr + 0x1c00 + (xga->instance * 0x80), 0x80); + } + + xga_log("[%04X:%08X]: POS Write Port = %x, val = %02x, linear base = %08x, instance = %d, " + "rom addr = %05x\n", CS, cpu_state.pc, port & 7, val, xga->linear_base, + xga->instance, xga->rom_addr); +} + +static uint8_t +xga_mca_feedb(void *priv) +{ + const svga_t *svga = (svga_t *) priv; + const xga_t *xga = (xga_t *) svga->xga; + + return xga->pos_regs[2] & 1; +} + +static void +xga_mca_reset(void *priv) +{ + svga_t *svga = (svga_t *) priv; + xga_t *xga = (xga_t *) svga->xga; + + mem_mapping_disable(&xga->bios_rom.mapping); + mem_mapping_disable(&xga->memio_mapping); + xga->on = 0; + vga_on = 1; + xga_mca_write(0x102, 0, svga); +} + +static void +xga_reset(void *priv) +{ + svga_t *svga = (svga_t *) priv; + xga_t *xga = (xga_t *) svga->xga; + + mem_mapping_disable(&xga->bios_rom.mapping); + mem_mapping_disable(&xga->memio_mapping); + xga->on = 0; + vga_on = 1; + xga->linear_endian_reverse = 0; + xga->a5_test = 0; +} + +static uint8_t +xga_pos_in(uint16_t addr, void *priv) +{ + svga_t *svga = (svga_t *) priv; + xga_t *xga = (xga_t *) svga->xga; + uint8_t ret = 0xff; + + if (!xga_standalone_enabled) { + 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; + + xga_log("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; + + default: + break; + } + + xga_log("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; + + default: + 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; + + default: + 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 = (xga_t *) svga->xga; + + if (!xga_standalone_enabled) { + switch (addr) { + case 0x0106: + xga->pos_idx = (xga->pos_idx & 0x00ff) | (val << 8); + break; + case 0x0107: + xga->pos_idx = (xga->pos_idx & 0xff00) | val; + xga_log("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; + + default: + 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; + + default: + break; + } + } +} + +static void * +xga_init(const device_t *info) +{ + if (svga_get_pri() == NULL) + return NULL; + + svga_t *svga = svga_get_pri(); + xga_t *xga = (xga_t *) calloc(1, sizeof(xga_t)); + FILE *fp; + uint8_t *rom = NULL; + + svga->xga = xga; + + 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); + xga->vram_mask = xga->vram_size - 1; + xga->vram = calloc(xga->vram_size, 1); + xga->changedvram = calloc(xga->vram_size >> 12, 1); + xga->on = 0; + xga->hwcursor.cur_xsize = 64; + xga->hwcursor.cur_ysize = 64; + xga->bios_rom.sz = 0x2000; + xga->linear_endian_reverse = 0; + xga->a5_test = 0; + + fp = rom_fopen(xga->type ? XGA2_BIOS_PATH : XGA_BIOS_PATH, "rb"); + (void) fseek(fp, 0L, SEEK_END); + (void) fseek(fp, 0L, SEEK_SET); + + rom = malloc(xga->bios_rom.sz); + memset(rom, 0xff, xga->bios_rom.sz); + (void) !fread(rom, xga->bios_rom.sz, 1, fp); + (void) fclose(fp); + + xga->bios_rom.rom = rom; + xga->bios_rom.mask = xga->bios_rom.sz - 1; + if (fp != NULL) { + free(rom); + } + + xga->base_addr_1mb = 0; + if (info->flags & DEVICE_MCA) { + video_inform(VIDEO_FLAG_TYPE_SPECIAL, &timing_xga_mca); + xga->linear_base = 0; + xga->instance = 0; + 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 { + if (!xga_standalone_enabled) + 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); + } + + mem_mapping_add(&xga->video_mapping, 0, 0, xga_read, xga_readw, xga_readl, + xga_write, xga_writew, xga_writel, + NULL, MEM_MAPPING_EXTERNAL, svga); + mem_mapping_add(&xga->linear_mapping, 0, 0, xga_read_linear, xga_readw_linear, xga_readl_linear, + xga_write_linear, xga_writew_linear, xga_writel_linear, + 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_standalone_enabled ? xga->vga_bios_rom.rom : xga->bios_rom.rom, MEM_MAPPING_EXTERNAL, svga); + + mem_mapping_disable(&xga->linear_mapping); + mem_mapping_disable(&xga->memio_mapping); + + xga->pos_regs[0] = xga->type ? 0xda : 0xdb; + xga->pos_regs[1] = 0x8f; + + if (xga->bus & DEVICE_MCA) { + 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_standalone_enabled) + 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 = (svga_t *) calloc(1, 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_active = 1; + + return xga_init(info); +} + +static void +xga_close(void *priv) +{ + svga_t *svga = (svga_t *) priv; + xga_t *xga = (xga_t *) svga->xga; + + if (svga) { + free(xga->vram); + free(xga->changedvram); + + free(xga); + } +} + +static int +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 *priv) +{ + svga_t *svga = (svga_t *) priv; + + svga_recalctimings(svga); +} + +static void +xga_force_redraw(void *priv) +{ + svga_t *svga = (svga_t *) priv; + + svga->fullchange = svga->monitor->mon_changeframecount; +} + +static const device_config_t xga_mca_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 = "", .description = "", .type = CONFIG_END } + // 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", + .flags = DEVICE_MCA, + .local = 0, + .init = xga_init, + .close = xga_close, + .reset = xga_reset, + { .available = xga_available }, + .speed_changed = xga_speed_changed, + .force_redraw = xga_force_redraw, + .config = xga_mca_configuration +}; + +const device_t xga_isa_device = { + .name = "XGA (ISA)", + .internal_name = "xga_isa", + .flags = DEVICE_ISA | DEVICE_AT, + .local = 0, + .init = xga_init, + .close = xga_close, + .reset = xga_reset, + { .available = xga_available }, + .speed_changed = xga_speed_changed, + .force_redraw = xga_force_redraw, + .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_standalone_enabled) + return; + + if (machine_has_bus(machine, MACHINE_BUS_MCA)) + device_add(&xga_device); + else + device_add(&xga_isa_device); +} diff --git a/src/video/video.c b/src/video/video.c index 532995cb3..34e602e39 100644 --- a/src/video/video.c +++ b/src/video/video.c @@ -1,53 +1,54 @@ /* - * 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. + * 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. + * This file is part of the 86Box distribution. * - * Main video-rendering module. + * Main video-rendering module. * - * Video timing settings - + * Video timing settings - * - * 8-bit - 1mb/sec - * B = 8 ISA clocks - * W = 16 ISA clocks - * L = 32 ISA clocks + * 8-bit - 1mb/sec + * B = 8 ISA clocks + * W = 16 ISA clocks + * L = 32 ISA clocks * - * Slow 16-bit - 2mb/sec - * B = 6 ISA clocks - * W = 8 ISA clocks - * L = 16 ISA clocks + * Slow 16-bit - 2mb/sec + * B = 6 ISA clocks + * W = 8 ISA clocks + * L = 16 ISA clocks * - * Fast 16-bit - 4mb/sec - * B = 3 ISA clocks - * W = 3 ISA clocks - * L = 6 ISA clocks + * Fast 16-bit - 4mb/sec + * B = 3 ISA clocks + * W = 3 ISA clocks + * L = 6 ISA clocks * - * Slow VLB/PCI - 8mb/sec (ish) - * B = 4 bus clocks - * W = 8 bus clocks - * L = 16 bus clocks + * Slow VLB/PCI - 8mb/sec (ish) + * B = 4 bus clocks + * W = 8 bus clocks + * L = 16 bus clocks * - * Mid VLB/PCI - - * B = 4 bus clocks - * W = 5 bus clocks - * L = 10 bus clocks + * Mid VLB/PCI - + * B = 4 bus clocks + * W = 5 bus clocks + * L = 10 bus clocks * - * Fast VLB/PCI - - * B = 3 bus clocks - * W = 3 bus clocks - * L = 4 bus clocks + * Fast VLB/PCI - + * B = 3 bus clocks + * W = 3 bus clocks + * L = 4 bus clocks * * * - * Authors: Sarah Walker, - * Miran Grca, + * Authors: Sarah Walker, + * Miran Grca, * - * Copyright 2008-2019 Sarah Walker. - * Copyright 2016-2019 Miran Grca. + * Copyright 2008-2019 Sarah Walker. + * Copyright 2016-2019 Miran Grca. */ +#include #define PNG_DEBUG 0 #include #include @@ -66,62 +67,48 @@ #include <86box/rom.h> #include <86box/config.h> #include <86box/timer.h> +#include <86box/path.h> #include <86box/plat.h> +#include <86box/ui.h> +#include <86box/thread.h> #include <86box/video.h> #include <86box/vid_svga.h> #include -volatile int screenshots = 0; -bitmap_t *buffer32 = NULL; -uint8_t fontdat[2048][8]; /* IBM CGA font */ -uint8_t fontdatm[2048][16]; /* IBM MDA font */ -uint8_t fontdatw[512][32]; /* Wyse700 font */ -uint8_t fontdat8x12[256][16]; /* MDSI Genius font */ -uint8_t fontdat12x18[256][36]; /* IM1024 font */ -dbcs_font_t *fontdatksc5601 = NULL; /* Korean KSC-5601 font */ -dbcs_font_t *fontdatksc5601_user = NULL; /* Korean KSC-5601 user defined font */ -uint32_t pal_lookup[256]; -int xsize = 1, - ysize = 1; -int cga_palette = 0, - herc_blend = 0; -uint32_t *video_6to8 = NULL, - *video_8togs = NULL, - *video_8to32 = NULL, - *video_15to32 = NULL, - *video_16to32 = NULL; -int changeframecount = 2; -int frames = 0; -int fullchange = 0; -uint8_t edatlookup[4][4]; -int overscan_x = 0, - overscan_y = 0; -int video_timing_read_b = 0, - video_timing_read_w = 0, - video_timing_read_l = 0; -int video_timing_write_b = 0, - video_timing_write_w = 0, - video_timing_write_l = 0; -int video_res_x = 0, - video_res_y = 0, - video_bpp = 0; -static int video_force_resize; -int video_grayscale = 0; -int video_graytype = 0; -static int vid_type; -static const video_timings_t *vid_timings; -static uint32_t cga_2_table[16]; -static uint8_t thread_run = 0; +volatile int screenshots = 0; +uint8_t edatlookup[4][4]; +uint8_t fontdat[2048][8]; /* IBM CGA font */ +uint8_t fontdatm[2048][16]; /* IBM MDA font */ +uint8_t fontdat2[2048][8]; /* IBM CGA 2nd instance font */ +uint8_t fontdatm2[2048][16]; /* IBM MDA 2nd instance font */ +uint8_t fontdatw[512][32]; /* Wyse700 font */ +uint8_t fontdat8x12[256][16]; /* MDSI Genius font */ +uint8_t fontdat12x18[256][36]; /* IM1024 font */ +dbcs_font_t *fontdatksc5601 = NULL; /* Korean KSC-5601 font */ +dbcs_font_t *fontdatksc5601_user = NULL; /* Korean KSC-5601 user defined font */ +int herc_blend = 0; +int frames = 0; +int fullchange = 0; +int video_grayscale = 0; +int video_graytype = 0; +int monitor_index_global = 0; +uint32_t *video_6to8 = NULL; +uint32_t *video_8togs = NULL; +uint32_t *video_8to32 = NULL; +uint32_t *video_15to32 = NULL; +uint32_t *video_16to32 = NULL; +monitor_t monitors[MONITORS_NUM]; +monitor_settings_t monitor_settings[MONITORS_NUM]; +atomic_bool doresize_monitors[MONITORS_NUM]; #ifdef _WIN32 -void * __cdecl (*video_copy)(void *_Dst, const void *_Src, size_t _Size) = memcpy; +void *__cdecl (*video_copy)(void *_Dst, const void *_Src, size_t _Size) = memcpy; #else -void * (*video_copy)(void *__restrict, const void *__restrict, size_t); +void *(*video_copy)(void *__restrict, const void *__restrict, size_t); #endif - -PALETTE cgapal = { +PALETTE cgapal = { {0,0,0}, {0,42,0}, {42,0,0}, {42,21,0}, {0,0,0}, {0,42,42}, {42,0,42}, {42,42,42}, {0,0,0}, {21,63,21}, {63,21,21}, {63,63,21}, @@ -136,137 +123,135 @@ PALETTE cgapal = { {42,0,21}, {21,10,21}, {42,0,42}, {42,0,63}, {21,21,21}, {21,63,21}, {42,21,42}, {21,63,63}, {63,0,0}, {42,42,0}, {63,21,42}, {41,41,41}, - + {0,0,0}, {0,42,42}, {42,0,0}, {42,42,42}, {0,0,0}, {0,42,42}, {42,0,0}, {42,42,42}, {0,0,0}, {0,63,63}, {63,0,0}, {63,63,63}, {0,0,0}, {0,63,63}, {63,0,0}, {63,63,63}, }; -PALETTE cgapal_mono[6] = { - { /* 0 - green, 4-color-optimized contrast. */ - {0x00,0x00,0x00},{0x00,0x0d,0x03},{0x01,0x17,0x05}, - {0x01,0x1a,0x06},{0x02,0x28,0x09},{0x02,0x2c,0x0a}, - {0x03,0x39,0x0d},{0x03,0x3c,0x0e},{0x00,0x07,0x01}, - {0x01,0x13,0x04},{0x01,0x1f,0x07},{0x01,0x23,0x08}, - {0x02,0x31,0x0b},{0x02,0x35,0x0c},{0x05,0x3f,0x11},{0x0d,0x3f,0x17}, +PALETTE cgapal_mono[6] = { + { /* 0 - green, 4-color-optimized contrast. */ + {0x00,0x00,0x00},{0x00,0x0d,0x03},{0x01,0x17,0x05}, + {0x01,0x1a,0x06},{0x02,0x28,0x09},{0x02,0x2c,0x0a}, + {0x03,0x39,0x0d},{0x03,0x3c,0x0e},{0x00,0x07,0x01}, + {0x01,0x13,0x04},{0x01,0x1f,0x07},{0x01,0x23,0x08}, + {0x02,0x31,0x0b},{0x02,0x35,0x0c},{0x05,0x3f,0x11},{0x0d,0x3f,0x17}, }, - { /* 1 - green, 16-color-optimized contrast. */ - {0x00,0x00,0x00},{0x00,0x0d,0x03},{0x01,0x15,0x05}, - {0x01,0x17,0x05},{0x01,0x21,0x08},{0x01,0x24,0x08}, - {0x02,0x2e,0x0b},{0x02,0x31,0x0b},{0x01,0x22,0x08}, - {0x02,0x28,0x09},{0x02,0x30,0x0b},{0x02,0x32,0x0c}, - {0x03,0x39,0x0d},{0x03,0x3b,0x0e},{0x09,0x3f,0x14},{0x0d,0x3f,0x17}, + { /* 1 - green, 16-color-optimized contrast. */ + {0x00,0x00,0x00},{0x00,0x0d,0x03},{0x01,0x15,0x05}, + {0x01,0x17,0x05},{0x01,0x21,0x08},{0x01,0x24,0x08}, + {0x02,0x2e,0x0b},{0x02,0x31,0x0b},{0x01,0x22,0x08}, + {0x02,0x28,0x09},{0x02,0x30,0x0b},{0x02,0x32,0x0c}, + {0x03,0x39,0x0d},{0x03,0x3b,0x0e},{0x09,0x3f,0x14},{0x0d,0x3f,0x17}, }, - { /* 2 - amber, 4-color-optimized contrast. */ - {0x00,0x00,0x00},{0x15,0x05,0x00},{0x20,0x0b,0x00}, - {0x24,0x0d,0x00},{0x33,0x18,0x00},{0x37,0x1b,0x00}, - {0x3f,0x26,0x01},{0x3f,0x2b,0x06},{0x0b,0x02,0x00}, - {0x1b,0x08,0x00},{0x29,0x11,0x00},{0x2e,0x14,0x00}, - {0x3b,0x1e,0x00},{0x3e,0x21,0x00},{0x3f,0x32,0x0a},{0x3f,0x38,0x0d}, + { /* 2 - amber, 4-color-optimized contrast. */ + {0x00,0x00,0x00},{0x15,0x05,0x00},{0x20,0x0b,0x00}, + {0x24,0x0d,0x00},{0x33,0x18,0x00},{0x37,0x1b,0x00}, + {0x3f,0x26,0x01},{0x3f,0x2b,0x06},{0x0b,0x02,0x00}, + {0x1b,0x08,0x00},{0x29,0x11,0x00},{0x2e,0x14,0x00}, + {0x3b,0x1e,0x00},{0x3e,0x21,0x00},{0x3f,0x32,0x0a},{0x3f,0x38,0x0d}, }, - { /* 3 - amber, 16-color-optimized contrast. */ - {0x00,0x00,0x00},{0x15,0x05,0x00},{0x1e,0x09,0x00}, - {0x21,0x0b,0x00},{0x2b,0x12,0x00},{0x2f,0x15,0x00}, - {0x38,0x1c,0x00},{0x3b,0x1e,0x00},{0x2c,0x13,0x00}, - {0x32,0x17,0x00},{0x3a,0x1e,0x00},{0x3c,0x1f,0x00}, - {0x3f,0x27,0x01},{0x3f,0x2a,0x04},{0x3f,0x36,0x0c},{0x3f,0x38,0x0d}, + { /* 3 - amber, 16-color-optimized contrast. */ + {0x00,0x00,0x00},{0x15,0x05,0x00},{0x1e,0x09,0x00}, + {0x21,0x0b,0x00},{0x2b,0x12,0x00},{0x2f,0x15,0x00}, + {0x38,0x1c,0x00},{0x3b,0x1e,0x00},{0x2c,0x13,0x00}, + {0x32,0x17,0x00},{0x3a,0x1e,0x00},{0x3c,0x1f,0x00}, + {0x3f,0x27,0x01},{0x3f,0x2a,0x04},{0x3f,0x36,0x0c},{0x3f,0x38,0x0d}, }, - { /* 4 - grey, 4-color-optimized contrast. */ - {0x00,0x00,0x00},{0x0e,0x0f,0x10},{0x15,0x17,0x18}, - {0x18,0x1a,0x1b},{0x24,0x25,0x25},{0x27,0x28,0x28}, - {0x33,0x34,0x32},{0x37,0x38,0x35},{0x09,0x0a,0x0b}, - {0x11,0x12,0x13},{0x1c,0x1e,0x1e},{0x20,0x22,0x22}, - {0x2c,0x2d,0x2c},{0x2f,0x30,0x2f},{0x3c,0x3c,0x38},{0x3f,0x3f,0x3b}, + { /* 4 - grey, 4-color-optimized contrast. */ + {0x00,0x00,0x00},{0x0e,0x0f,0x10},{0x15,0x17,0x18}, + {0x18,0x1a,0x1b},{0x24,0x25,0x25},{0x27,0x28,0x28}, + {0x33,0x34,0x32},{0x37,0x38,0x35},{0x09,0x0a,0x0b}, + {0x11,0x12,0x13},{0x1c,0x1e,0x1e},{0x20,0x22,0x22}, + {0x2c,0x2d,0x2c},{0x2f,0x30,0x2f},{0x3c,0x3c,0x38},{0x3f,0x3f,0x3b}, }, - { /* 5 - grey, 16-color-optimized contrast. */ - {0x00,0x00,0x00},{0x0e,0x0f,0x10},{0x13,0x14,0x15}, - {0x15,0x17,0x18},{0x1e,0x20,0x20},{0x20,0x22,0x22}, - {0x29,0x2a,0x2a},{0x2c,0x2d,0x2c},{0x1f,0x21,0x21}, - {0x23,0x25,0x25},{0x2b,0x2c,0x2b},{0x2d,0x2e,0x2d}, - {0x34,0x35,0x33},{0x37,0x37,0x34},{0x3e,0x3e,0x3a},{0x3f,0x3f,0x3b}, + { /* 5 - grey, 16-color-optimized contrast. */ + {0x00,0x00,0x00},{0x0e,0x0f,0x10},{0x13,0x14,0x15}, + {0x15,0x17,0x18},{0x1e,0x20,0x20},{0x20,0x22,0x22}, + {0x29,0x2a,0x2a},{0x2c,0x2d,0x2c},{0x1f,0x21,0x21}, + {0x23,0x25,0x25},{0x2b,0x2c,0x2b},{0x2d,0x2e,0x2d}, + {0x34,0x35,0x33},{0x37,0x37,0x34},{0x3e,0x3e,0x3a},{0x3f,0x3f,0x3b}, } }; - -const uint32_t shade[5][256] = -{ - {0}, // RGB Color (unused) - {0}, // RGB Grayscale (unused) - { // Amber monitor - 0x000000, 0x060000, 0x090000, 0x0d0000, 0x100000, 0x120100, 0x150100, 0x170100, 0x1a0100, 0x1c0100, 0x1e0200, 0x210200, 0x230200, 0x250300, 0x270300, 0x290300, - 0x2b0400, 0x2d0400, 0x2f0400, 0x300500, 0x320500, 0x340500, 0x360600, 0x380600, 0x390700, 0x3b0700, 0x3d0700, 0x3f0800, 0x400800, 0x420900, 0x440900, 0x450a00, - 0x470a00, 0x480b00, 0x4a0b00, 0x4c0c00, 0x4d0c00, 0x4f0d00, 0x500d00, 0x520e00, 0x530e00, 0x550f00, 0x560f00, 0x581000, 0x591000, 0x5b1100, 0x5c1200, 0x5e1200, - 0x5f1300, 0x601300, 0x621400, 0x631500, 0x651500, 0x661600, 0x671600, 0x691700, 0x6a1800, 0x6c1800, 0x6d1900, 0x6e1a00, 0x701a00, 0x711b00, 0x721c00, 0x741c00, - 0x751d00, 0x761e00, 0x781e00, 0x791f00, 0x7a2000, 0x7c2000, 0x7d2100, 0x7e2200, 0x7f2300, 0x812300, 0x822400, 0x832500, 0x842600, 0x862600, 0x872700, 0x882800, - 0x8a2900, 0x8b2900, 0x8c2a00, 0x8d2b00, 0x8e2c00, 0x902c00, 0x912d00, 0x922e00, 0x932f00, 0x953000, 0x963000, 0x973100, 0x983200, 0x993300, 0x9b3400, 0x9c3400, - 0x9d3500, 0x9e3600, 0x9f3700, 0xa03800, 0xa23900, 0xa33a00, 0xa43a00, 0xa53b00, 0xa63c00, 0xa73d00, 0xa93e00, 0xaa3f00, 0xab4000, 0xac4000, 0xad4100, 0xae4200, - 0xaf4300, 0xb14400, 0xb24500, 0xb34600, 0xb44700, 0xb54800, 0xb64900, 0xb74a00, 0xb94a00, 0xba4b00, 0xbb4c00, 0xbc4d00, 0xbd4e00, 0xbe4f00, 0xbf5000, 0xc05100, - 0xc15200, 0xc25300, 0xc45400, 0xc55500, 0xc65600, 0xc75700, 0xc85800, 0xc95900, 0xca5a00, 0xcb5b00, 0xcc5c00, 0xcd5d00, 0xce5e00, 0xcf5f00, 0xd06000, 0xd26101, - 0xd36201, 0xd46301, 0xd56401, 0xd66501, 0xd76601, 0xd86701, 0xd96801, 0xda6901, 0xdb6a01, 0xdc6b01, 0xdd6c01, 0xde6d01, 0xdf6e01, 0xe06f01, 0xe17001, 0xe27201, - 0xe37301, 0xe47401, 0xe57501, 0xe67602, 0xe77702, 0xe87802, 0xe97902, 0xeb7a02, 0xec7b02, 0xed7c02, 0xee7e02, 0xef7f02, 0xf08002, 0xf18103, 0xf28203, 0xf38303, - 0xf48403, 0xf58503, 0xf68703, 0xf78803, 0xf88903, 0xf98a04, 0xfa8b04, 0xfb8c04, 0xfc8d04, 0xfd8f04, 0xfe9005, 0xff9105, 0xff9205, 0xff9305, 0xff9405, 0xff9606, - 0xff9706, 0xff9806, 0xff9906, 0xff9a07, 0xff9b07, 0xff9d07, 0xff9e08, 0xff9f08, 0xffa008, 0xffa109, 0xffa309, 0xffa409, 0xffa50a, 0xffa60a, 0xffa80a, 0xffa90b, - 0xffaa0b, 0xffab0c, 0xffac0c, 0xffae0d, 0xffaf0d, 0xffb00e, 0xffb10e, 0xffb30f, 0xffb40f, 0xffb510, 0xffb610, 0xffb811, 0xffb912, 0xffba12, 0xffbb13, 0xffbd14, - 0xffbe14, 0xffbf15, 0xffc016, 0xffc217, 0xffc317, 0xffc418, 0xffc619, 0xffc71a, 0xffc81b, 0xffca1c, 0xffcb1d, 0xffcc1e, 0xffcd1f, 0xffcf20, 0xffd021, 0xffd122, - 0xffd323, 0xffd424, 0xffd526, 0xffd727, 0xffd828, 0xffd92a, 0xffdb2b, 0xffdc2c, 0xffdd2e, 0xffdf2f, 0xffe031, 0xffe133, 0xffe334, 0xffe436, 0xffe538, 0xffe739 - }, - { // Green monitor - 0x000000, 0x000400, 0x000700, 0x000900, 0x000b00, 0x000d00, 0x000f00, 0x001100, 0x001300, 0x001500, 0x001600, 0x001800, 0x001a00, 0x001b00, 0x001d00, 0x001e00, - 0x002000, 0x002100, 0x002300, 0x002400, 0x002601, 0x002701, 0x002901, 0x002a01, 0x002b01, 0x002d01, 0x002e01, 0x002f01, 0x003101, 0x003201, 0x003301, 0x003401, - 0x003601, 0x003702, 0x003802, 0x003902, 0x003b02, 0x003c02, 0x003d02, 0x003e02, 0x004002, 0x004102, 0x004203, 0x004303, 0x004403, 0x004503, 0x004703, 0x004803, - 0x004903, 0x004a03, 0x004b04, 0x004c04, 0x004d04, 0x004e04, 0x005004, 0x005104, 0x005205, 0x005305, 0x005405, 0x005505, 0x005605, 0x005705, 0x005806, 0x005906, - 0x005a06, 0x005b06, 0x005d06, 0x005e07, 0x005f07, 0x006007, 0x006107, 0x006207, 0x006308, 0x006408, 0x006508, 0x006608, 0x006708, 0x006809, 0x006909, 0x006a09, - 0x006b09, 0x016c0a, 0x016d0a, 0x016e0a, 0x016f0a, 0x01700b, 0x01710b, 0x01720b, 0x01730b, 0x01740c, 0x01750c, 0x01760c, 0x01770c, 0x01780d, 0x01790d, 0x017a0d, - 0x017b0d, 0x017b0e, 0x017c0e, 0x017d0e, 0x017e0f, 0x017f0f, 0x01800f, 0x018110, 0x028210, 0x028310, 0x028410, 0x028511, 0x028611, 0x028711, 0x028812, 0x028912, - 0x028a12, 0x028a13, 0x028b13, 0x028c13, 0x028d14, 0x028e14, 0x038f14, 0x039015, 0x039115, 0x039215, 0x039316, 0x039416, 0x039417, 0x039517, 0x039617, 0x039718, - 0x049818, 0x049918, 0x049a19, 0x049b19, 0x049c19, 0x049c1a, 0x049d1a, 0x049e1b, 0x059f1b, 0x05a01b, 0x05a11c, 0x05a21c, 0x05a31c, 0x05a31d, 0x05a41d, 0x06a51e, - 0x06a61e, 0x06a71f, 0x06a81f, 0x06a920, 0x06aa20, 0x07aa21, 0x07ab21, 0x07ac21, 0x07ad22, 0x07ae22, 0x08af23, 0x08b023, 0x08b024, 0x08b124, 0x08b225, 0x09b325, - 0x09b426, 0x09b526, 0x09b527, 0x0ab627, 0x0ab728, 0x0ab828, 0x0ab929, 0x0bba29, 0x0bba2a, 0x0bbb2a, 0x0bbc2b, 0x0cbd2b, 0x0cbe2c, 0x0cbf2c, 0x0dbf2d, 0x0dc02d, - 0x0dc12e, 0x0ec22e, 0x0ec32f, 0x0ec42f, 0x0fc430, 0x0fc530, 0x0fc631, 0x10c731, 0x10c832, 0x10c932, 0x11c933, 0x11ca33, 0x11cb34, 0x12cc35, 0x12cd35, 0x12cd36, - 0x13ce36, 0x13cf37, 0x13d037, 0x14d138, 0x14d139, 0x14d239, 0x15d33a, 0x15d43a, 0x16d43b, 0x16d53b, 0x17d63c, 0x17d73d, 0x17d83d, 0x18d83e, 0x18d93e, 0x19da3f, - 0x19db40, 0x1adc40, 0x1adc41, 0x1bdd41, 0x1bde42, 0x1cdf43, 0x1ce043, 0x1de044, 0x1ee145, 0x1ee245, 0x1fe346, 0x1fe446, 0x20e447, 0x20e548, 0x21e648, 0x22e749, - 0x22e74a, 0x23e84a, 0x23e94b, 0x24ea4c, 0x25ea4c, 0x25eb4d, 0x26ec4e, 0x27ed4e, 0x27ee4f, 0x28ee50, 0x29ef50, 0x29f051, 0x2af152, 0x2bf153, 0x2cf253, 0x2cf354, - 0x2df455, 0x2ef455, 0x2ff556, 0x2ff657, 0x30f758, 0x31f758, 0x32f859, 0x32f95a, 0x33fa5a, 0x34fa5b, 0x35fb5c, 0x36fc5d, 0x37fd5d, 0x38fd5e, 0x38fe5f, 0x39ff60 - }, - { // White monitor - 0x000000, 0x010102, 0x020203, 0x020304, 0x030406, 0x040507, 0x050608, 0x060709, 0x07080a, 0x08090c, 0x080a0d, 0x090b0e, 0x0a0c0f, 0x0b0d10, 0x0c0e11, 0x0d0f12, - 0x0e1013, 0x0f1115, 0x101216, 0x111317, 0x121418, 0x121519, 0x13161a, 0x14171b, 0x15181c, 0x16191d, 0x171a1e, 0x181b1f, 0x191c20, 0x1a1d21, 0x1b1e22, 0x1c1f23, - 0x1d2024, 0x1e2125, 0x1f2226, 0x202327, 0x212428, 0x222529, 0x22262b, 0x23272c, 0x24282d, 0x25292e, 0x262a2f, 0x272b30, 0x282c30, 0x292d31, 0x2a2e32, 0x2b2f33, - 0x2c3034, 0x2d3035, 0x2e3136, 0x2f3237, 0x303338, 0x313439, 0x32353a, 0x33363b, 0x34373c, 0x35383d, 0x36393e, 0x373a3f, 0x383b40, 0x393c41, 0x3a3d42, 0x3b3e43, - 0x3c3f44, 0x3d4045, 0x3e4146, 0x3f4247, 0x404348, 0x414449, 0x42454a, 0x43464b, 0x44474c, 0x45484d, 0x46494d, 0x474a4e, 0x484b4f, 0x484c50, 0x494d51, 0x4a4e52, - 0x4b4f53, 0x4c5054, 0x4d5155, 0x4e5256, 0x4f5357, 0x505458, 0x515559, 0x52565a, 0x53575b, 0x54585b, 0x55595c, 0x565a5d, 0x575b5e, 0x585c5f, 0x595d60, 0x5a5e61, - 0x5b5f62, 0x5c6063, 0x5d6164, 0x5e6265, 0x5f6366, 0x606466, 0x616567, 0x626668, 0x636769, 0x64686a, 0x65696b, 0x666a6c, 0x676b6d, 0x686c6e, 0x696d6f, 0x6a6e70, - 0x6b6f70, 0x6c7071, 0x6d7172, 0x6f7273, 0x707374, 0x707475, 0x717576, 0x727677, 0x747778, 0x757879, 0x767979, 0x777a7a, 0x787b7b, 0x797c7c, 0x7a7d7d, 0x7b7e7e, - 0x7c7f7f, 0x7d8080, 0x7e8181, 0x7f8281, 0x808382, 0x818483, 0x828584, 0x838685, 0x848786, 0x858887, 0x868988, 0x878a89, 0x888b89, 0x898c8a, 0x8a8d8b, 0x8b8e8c, - 0x8c8f8d, 0x8d8f8e, 0x8e908f, 0x8f9190, 0x909290, 0x919391, 0x929492, 0x939593, 0x949694, 0x959795, 0x969896, 0x979997, 0x989a98, 0x999b98, 0x9a9c99, 0x9b9d9a, - 0x9c9e9b, 0x9d9f9c, 0x9ea09d, 0x9fa19e, 0xa0a29f, 0xa1a39f, 0xa2a4a0, 0xa3a5a1, 0xa4a6a2, 0xa6a7a3, 0xa7a8a4, 0xa8a9a5, 0xa9aaa5, 0xaaaba6, 0xabaca7, 0xacada8, - 0xadaea9, 0xaeafaa, 0xafb0ab, 0xb0b1ac, 0xb1b2ac, 0xb2b3ad, 0xb3b4ae, 0xb4b5af, 0xb5b6b0, 0xb6b7b1, 0xb7b8b2, 0xb8b9b2, 0xb9bab3, 0xbabbb4, 0xbbbcb5, 0xbcbdb6, - 0xbdbeb7, 0xbebfb8, 0xbfc0b8, 0xc0c1b9, 0xc1c2ba, 0xc2c3bb, 0xc3c4bc, 0xc5c5bd, 0xc6c6be, 0xc7c7be, 0xc8c8bf, 0xc9c9c0, 0xcacac1, 0xcbcbc2, 0xccccc3, 0xcdcdc3, - 0xcecec4, 0xcfcfc5, 0xd0d0c6, 0xd1d1c7, 0xd2d2c8, 0xd3d3c9, 0xd4d4c9, 0xd5d5ca, 0xd6d6cb, 0xd7d7cc, 0xd8d8cd, 0xd9d9ce, 0xdadacf, 0xdbdbcf, 0xdcdcd0, 0xdeddd1, - 0xdfded2, 0xe0dfd3, 0xe1e0d4, 0xe2e1d4, 0xe3e2d5, 0xe4e3d6, 0xe5e4d7, 0xe6e5d8, 0xe7e6d9, 0xe8e7d9, 0xe9e8da, 0xeae9db, 0xebeadc, 0xecebdd, 0xedecde, 0xeeeddf, - 0xefeedf, 0xf0efe0, 0xf1f0e1, 0xf2f1e2, 0xf3f2e3, 0xf4f3e3, 0xf6f3e4, 0xf7f4e5, 0xf8f5e6, 0xf9f6e7, 0xfaf7e8, 0xfbf8e9, 0xfcf9e9, 0xfdfaea, 0xfefbeb, 0xfffcec - } +const uint32_t shade[5][256] = { + {0}, // RGB Color (unused) + {0}, // RGB Grayscale (unused) + { // Amber monitor + 0x000000, 0x060000, 0x090000, 0x0d0000, 0x100000, 0x120100, 0x150100, 0x170100, 0x1a0100, 0x1c0100, 0x1e0200, 0x210200, 0x230200, 0x250300, 0x270300, 0x290300, + 0x2b0400, 0x2d0400, 0x2f0400, 0x300500, 0x320500, 0x340500, 0x360600, 0x380600, 0x390700, 0x3b0700, 0x3d0700, 0x3f0800, 0x400800, 0x420900, 0x440900, 0x450a00, + 0x470a00, 0x480b00, 0x4a0b00, 0x4c0c00, 0x4d0c00, 0x4f0d00, 0x500d00, 0x520e00, 0x530e00, 0x550f00, 0x560f00, 0x581000, 0x591000, 0x5b1100, 0x5c1200, 0x5e1200, + 0x5f1300, 0x601300, 0x621400, 0x631500, 0x651500, 0x661600, 0x671600, 0x691700, 0x6a1800, 0x6c1800, 0x6d1900, 0x6e1a00, 0x701a00, 0x711b00, 0x721c00, 0x741c00, + 0x751d00, 0x761e00, 0x781e00, 0x791f00, 0x7a2000, 0x7c2000, 0x7d2100, 0x7e2200, 0x7f2300, 0x812300, 0x822400, 0x832500, 0x842600, 0x862600, 0x872700, 0x882800, + 0x8a2900, 0x8b2900, 0x8c2a00, 0x8d2b00, 0x8e2c00, 0x902c00, 0x912d00, 0x922e00, 0x932f00, 0x953000, 0x963000, 0x973100, 0x983200, 0x993300, 0x9b3400, 0x9c3400, + 0x9d3500, 0x9e3600, 0x9f3700, 0xa03800, 0xa23900, 0xa33a00, 0xa43a00, 0xa53b00, 0xa63c00, 0xa73d00, 0xa93e00, 0xaa3f00, 0xab4000, 0xac4000, 0xad4100, 0xae4200, + 0xaf4300, 0xb14400, 0xb24500, 0xb34600, 0xb44700, 0xb54800, 0xb64900, 0xb74a00, 0xb94a00, 0xba4b00, 0xbb4c00, 0xbc4d00, 0xbd4e00, 0xbe4f00, 0xbf5000, 0xc05100, + 0xc15200, 0xc25300, 0xc45400, 0xc55500, 0xc65600, 0xc75700, 0xc85800, 0xc95900, 0xca5a00, 0xcb5b00, 0xcc5c00, 0xcd5d00, 0xce5e00, 0xcf5f00, 0xd06000, 0xd26101, + 0xd36201, 0xd46301, 0xd56401, 0xd66501, 0xd76601, 0xd86701, 0xd96801, 0xda6901, 0xdb6a01, 0xdc6b01, 0xdd6c01, 0xde6d01, 0xdf6e01, 0xe06f01, 0xe17001, 0xe27201, + 0xe37301, 0xe47401, 0xe57501, 0xe67602, 0xe77702, 0xe87802, 0xe97902, 0xeb7a02, 0xec7b02, 0xed7c02, 0xee7e02, 0xef7f02, 0xf08002, 0xf18103, 0xf28203, 0xf38303, + 0xf48403, 0xf58503, 0xf68703, 0xf78803, 0xf88903, 0xf98a04, 0xfa8b04, 0xfb8c04, 0xfc8d04, 0xfd8f04, 0xfe9005, 0xff9105, 0xff9205, 0xff9305, 0xff9405, 0xff9606, + 0xff9706, 0xff9806, 0xff9906, 0xff9a07, 0xff9b07, 0xff9d07, 0xff9e08, 0xff9f08, 0xffa008, 0xffa109, 0xffa309, 0xffa409, 0xffa50a, 0xffa60a, 0xffa80a, 0xffa90b, + 0xffaa0b, 0xffab0c, 0xffac0c, 0xffae0d, 0xffaf0d, 0xffb00e, 0xffb10e, 0xffb30f, 0xffb40f, 0xffb510, 0xffb610, 0xffb811, 0xffb912, 0xffba12, 0xffbb13, 0xffbd14, + 0xffbe14, 0xffbf15, 0xffc016, 0xffc217, 0xffc317, 0xffc418, 0xffc619, 0xffc71a, 0xffc81b, 0xffca1c, 0xffcb1d, 0xffcc1e, 0xffcd1f, 0xffcf20, 0xffd021, 0xffd122, + 0xffd323, 0xffd424, 0xffd526, 0xffd727, 0xffd828, 0xffd92a, 0xffdb2b, 0xffdc2c, 0xffdd2e, 0xffdf2f, 0xffe031, 0xffe133, 0xffe334, 0xffe436, 0xffe538, 0xffe739 + }, + { // Green monitor + 0x000000, 0x000400, 0x000700, 0x000900, 0x000b00, 0x000d00, 0x000f00, 0x001100, 0x001300, 0x001500, 0x001600, 0x001800, 0x001a00, 0x001b00, 0x001d00, 0x001e00, + 0x002000, 0x002100, 0x002300, 0x002400, 0x002601, 0x002701, 0x002901, 0x002a01, 0x002b01, 0x002d01, 0x002e01, 0x002f01, 0x003101, 0x003201, 0x003301, 0x003401, + 0x003601, 0x003702, 0x003802, 0x003902, 0x003b02, 0x003c02, 0x003d02, 0x003e02, 0x004002, 0x004102, 0x004203, 0x004303, 0x004403, 0x004503, 0x004703, 0x004803, + 0x004903, 0x004a03, 0x004b04, 0x004c04, 0x004d04, 0x004e04, 0x005004, 0x005104, 0x005205, 0x005305, 0x005405, 0x005505, 0x005605, 0x005705, 0x005806, 0x005906, + 0x005a06, 0x005b06, 0x005d06, 0x005e07, 0x005f07, 0x006007, 0x006107, 0x006207, 0x006308, 0x006408, 0x006508, 0x006608, 0x006708, 0x006809, 0x006909, 0x006a09, + 0x006b09, 0x016c0a, 0x016d0a, 0x016e0a, 0x016f0a, 0x01700b, 0x01710b, 0x01720b, 0x01730b, 0x01740c, 0x01750c, 0x01760c, 0x01770c, 0x01780d, 0x01790d, 0x017a0d, + 0x017b0d, 0x017b0e, 0x017c0e, 0x017d0e, 0x017e0f, 0x017f0f, 0x01800f, 0x018110, 0x028210, 0x028310, 0x028410, 0x028511, 0x028611, 0x028711, 0x028812, 0x028912, + 0x028a12, 0x028a13, 0x028b13, 0x028c13, 0x028d14, 0x028e14, 0x038f14, 0x039015, 0x039115, 0x039215, 0x039316, 0x039416, 0x039417, 0x039517, 0x039617, 0x039718, + 0x049818, 0x049918, 0x049a19, 0x049b19, 0x049c19, 0x049c1a, 0x049d1a, 0x049e1b, 0x059f1b, 0x05a01b, 0x05a11c, 0x05a21c, 0x05a31c, 0x05a31d, 0x05a41d, 0x06a51e, + 0x06a61e, 0x06a71f, 0x06a81f, 0x06a920, 0x06aa20, 0x07aa21, 0x07ab21, 0x07ac21, 0x07ad22, 0x07ae22, 0x08af23, 0x08b023, 0x08b024, 0x08b124, 0x08b225, 0x09b325, + 0x09b426, 0x09b526, 0x09b527, 0x0ab627, 0x0ab728, 0x0ab828, 0x0ab929, 0x0bba29, 0x0bba2a, 0x0bbb2a, 0x0bbc2b, 0x0cbd2b, 0x0cbe2c, 0x0cbf2c, 0x0dbf2d, 0x0dc02d, + 0x0dc12e, 0x0ec22e, 0x0ec32f, 0x0ec42f, 0x0fc430, 0x0fc530, 0x0fc631, 0x10c731, 0x10c832, 0x10c932, 0x11c933, 0x11ca33, 0x11cb34, 0x12cc35, 0x12cd35, 0x12cd36, + 0x13ce36, 0x13cf37, 0x13d037, 0x14d138, 0x14d139, 0x14d239, 0x15d33a, 0x15d43a, 0x16d43b, 0x16d53b, 0x17d63c, 0x17d73d, 0x17d83d, 0x18d83e, 0x18d93e, 0x19da3f, + 0x19db40, 0x1adc40, 0x1adc41, 0x1bdd41, 0x1bde42, 0x1cdf43, 0x1ce043, 0x1de044, 0x1ee145, 0x1ee245, 0x1fe346, 0x1fe446, 0x20e447, 0x20e548, 0x21e648, 0x22e749, + 0x22e74a, 0x23e84a, 0x23e94b, 0x24ea4c, 0x25ea4c, 0x25eb4d, 0x26ec4e, 0x27ed4e, 0x27ee4f, 0x28ee50, 0x29ef50, 0x29f051, 0x2af152, 0x2bf153, 0x2cf253, 0x2cf354, + 0x2df455, 0x2ef455, 0x2ff556, 0x2ff657, 0x30f758, 0x31f758, 0x32f859, 0x32f95a, 0x33fa5a, 0x34fa5b, 0x35fb5c, 0x36fc5d, 0x37fd5d, 0x38fd5e, 0x38fe5f, 0x39ff60 + }, + { // White monitor + 0x000000, 0x010102, 0x020203, 0x020304, 0x030406, 0x040507, 0x050608, 0x060709, 0x07080a, 0x08090c, 0x080a0d, 0x090b0e, 0x0a0c0f, 0x0b0d10, 0x0c0e11, 0x0d0f12, + 0x0e1013, 0x0f1115, 0x101216, 0x111317, 0x121418, 0x121519, 0x13161a, 0x14171b, 0x15181c, 0x16191d, 0x171a1e, 0x181b1f, 0x191c20, 0x1a1d21, 0x1b1e22, 0x1c1f23, + 0x1d2024, 0x1e2125, 0x1f2226, 0x202327, 0x212428, 0x222529, 0x22262b, 0x23272c, 0x24282d, 0x25292e, 0x262a2f, 0x272b30, 0x282c30, 0x292d31, 0x2a2e32, 0x2b2f33, + 0x2c3034, 0x2d3035, 0x2e3136, 0x2f3237, 0x303338, 0x313439, 0x32353a, 0x33363b, 0x34373c, 0x35383d, 0x36393e, 0x373a3f, 0x383b40, 0x393c41, 0x3a3d42, 0x3b3e43, + 0x3c3f44, 0x3d4045, 0x3e4146, 0x3f4247, 0x404348, 0x414449, 0x42454a, 0x43464b, 0x44474c, 0x45484d, 0x46494d, 0x474a4e, 0x484b4f, 0x484c50, 0x494d51, 0x4a4e52, + 0x4b4f53, 0x4c5054, 0x4d5155, 0x4e5256, 0x4f5357, 0x505458, 0x515559, 0x52565a, 0x53575b, 0x54585b, 0x55595c, 0x565a5d, 0x575b5e, 0x585c5f, 0x595d60, 0x5a5e61, + 0x5b5f62, 0x5c6063, 0x5d6164, 0x5e6265, 0x5f6366, 0x606466, 0x616567, 0x626668, 0x636769, 0x64686a, 0x65696b, 0x666a6c, 0x676b6d, 0x686c6e, 0x696d6f, 0x6a6e70, + 0x6b6f70, 0x6c7071, 0x6d7172, 0x6f7273, 0x707374, 0x707475, 0x717576, 0x727677, 0x747778, 0x757879, 0x767979, 0x777a7a, 0x787b7b, 0x797c7c, 0x7a7d7d, 0x7b7e7e, + 0x7c7f7f, 0x7d8080, 0x7e8181, 0x7f8281, 0x808382, 0x818483, 0x828584, 0x838685, 0x848786, 0x858887, 0x868988, 0x878a89, 0x888b89, 0x898c8a, 0x8a8d8b, 0x8b8e8c, + 0x8c8f8d, 0x8d8f8e, 0x8e908f, 0x8f9190, 0x909290, 0x919391, 0x929492, 0x939593, 0x949694, 0x959795, 0x969896, 0x979997, 0x989a98, 0x999b98, 0x9a9c99, 0x9b9d9a, + 0x9c9e9b, 0x9d9f9c, 0x9ea09d, 0x9fa19e, 0xa0a29f, 0xa1a39f, 0xa2a4a0, 0xa3a5a1, 0xa4a6a2, 0xa6a7a3, 0xa7a8a4, 0xa8a9a5, 0xa9aaa5, 0xaaaba6, 0xabaca7, 0xacada8, + 0xadaea9, 0xaeafaa, 0xafb0ab, 0xb0b1ac, 0xb1b2ac, 0xb2b3ad, 0xb3b4ae, 0xb4b5af, 0xb5b6b0, 0xb6b7b1, 0xb7b8b2, 0xb8b9b2, 0xb9bab3, 0xbabbb4, 0xbbbcb5, 0xbcbdb6, + 0xbdbeb7, 0xbebfb8, 0xbfc0b8, 0xc0c1b9, 0xc1c2ba, 0xc2c3bb, 0xc3c4bc, 0xc5c5bd, 0xc6c6be, 0xc7c7be, 0xc8c8bf, 0xc9c9c0, 0xcacac1, 0xcbcbc2, 0xccccc3, 0xcdcdc3, + 0xcecec4, 0xcfcfc5, 0xd0d0c6, 0xd1d1c7, 0xd2d2c8, 0xd3d3c9, 0xd4d4c9, 0xd5d5ca, 0xd6d6cb, 0xd7d7cc, 0xd8d8cd, 0xd9d9ce, 0xdadacf, 0xdbdbcf, 0xdcdcd0, 0xdeddd1, + 0xdfded2, 0xe0dfd3, 0xe1e0d4, 0xe2e1d4, 0xe3e2d5, 0xe4e3d6, 0xe5e4d7, 0xe6e5d8, 0xe7e6d9, 0xe8e7d9, 0xe9e8da, 0xeae9db, 0xebeadc, 0xecebdd, 0xedecde, 0xeeeddf, + 0xefeedf, 0xf0efe0, 0xf1f0e1, 0xf2f1e2, 0xf3f2e3, 0xf4f3e3, 0xf6f3e4, 0xf7f4e5, 0xf8f5e6, 0xf9f6e7, 0xfaf7e8, 0xfbf8e9, 0xfcf9e9, 0xfdfaea, 0xfefbeb, 0xfffcec + } }; +typedef struct blit_data_struct { + int x, y, w, h; + int busy; + int buffer_in_use; + int thread_run; + int monitor_index; -static struct { - int x, y, w, h; - int busy; - int buffer_in_use; + thread_t *blit_thread; + event_t *wake_blit_thread; + event_t *blit_complete; + event_t *buffer_not_in_use; +} blit_data_t; - thread_t *blit_thread; - event_t *wake_blit_thread; - event_t *blit_complete; - event_t *buffer_not_in_use; -} blit_data; - - -static void (*blit_func)(int x, int y, int w, int h); +static uint32_t cga_2_table[16]; +static void (*blit_func)(int x, int y, int w, int h, int monitor_index); #ifdef ENABLE_VIDEO_LOG -int sdl_do_log = ENABLE_VIDEO_LOG; - +int video_do_log = ENABLE_VIDEO_LOG; static void video_log(const char *fmt, ...) @@ -274,625 +259,690 @@ video_log(const char *fmt, ...) va_list ap; if (video_do_log) { - va_start(ap, fmt); - pclog_ex(fmt, ap); - va_end(ap); + va_start(ap, fmt); + pclog_ex(fmt, ap); + va_end(ap); } } #else -#define video_log(fmt, ...) +# define video_log(fmt, ...) #endif - void -video_setblit(void(*blit)(int,int,int,int)) +video_setblit(void (*blit)(int, int, int, int, int)) { blit_func = blit; } - void -video_blit_complete(void) +video_blit_complete_monitor(int monitor_index) { - blit_data.buffer_in_use = 0; + blit_data_t *blit_data_ptr = monitors[monitor_index].mon_blit_data_ptr; + blit_data_ptr->buffer_in_use = 0; - thread_set_event(blit_data.buffer_not_in_use); + thread_set_event(blit_data_ptr->buffer_not_in_use); } - void -video_wait_for_blit(void) +video_wait_for_blit_monitor(int monitor_index) { - while (blit_data.busy) - thread_wait_event(blit_data.blit_complete, -1); - thread_reset_event(blit_data.blit_complete); + blit_data_t *blit_data_ptr = monitors[monitor_index].mon_blit_data_ptr; + + while (blit_data_ptr->busy) + thread_wait_event(blit_data_ptr->blit_complete, -1); + thread_reset_event(blit_data_ptr->blit_complete); } - void -video_wait_for_buffer(void) +video_wait_for_buffer_monitor(int monitor_index) { - while (blit_data.buffer_in_use) - thread_wait_event(blit_data.buffer_not_in_use, -1); - thread_reset_event(blit_data.buffer_not_in_use); + blit_data_t *blit_data_ptr = monitors[monitor_index].mon_blit_data_ptr; + + while (blit_data_ptr->buffer_in_use) + thread_wait_event(blit_data_ptr->buffer_not_in_use, -1); + thread_reset_event(blit_data_ptr->buffer_not_in_use); } - -static png_structp png_ptr; -static png_infop info_ptr; - +static png_structp png_ptr[MONITORS_NUM]; +static png_infop info_ptr[MONITORS_NUM]; static void -video_take_screenshot(const char *fn, uint32_t *buf, int start_x, int start_y, int row_len) +video_take_screenshot_monitor(const char *fn, uint32_t *buf, int start_x, int start_y, int row_len, int monitor_index) { - int i, x, y; - png_bytep *b_rgb = NULL; - FILE *fp = NULL; - uint32_t temp = 0x00000000; + png_bytep *b_rgb = NULL; + FILE *fp = NULL; + uint32_t temp = 0x00000000; + const blit_data_t *blit_data_ptr = monitors[monitor_index].mon_blit_data_ptr; /* create file */ - fp = plat_fopen((char *) fn, (char *) "wb"); + fp = plat_fopen(fn, (const char *) "wb"); if (!fp) { - video_log("[video_take_screenshot] File %s could not be opened for writing", fn); - return; + video_log("[video_take_screenshot] File %s could not be opened for writing", fn); + return; } /* initialize stuff */ - png_ptr = png_create_write_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL); + png_ptr[monitor_index] = png_create_write_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL); - if (!png_ptr) { - video_log("[video_take_screenshot] png_create_write_struct failed"); - fclose(fp); - return; + if (!png_ptr[monitor_index]) { + video_log("[video_take_screenshot] png_create_write_struct failed"); + fclose(fp); + return; } - info_ptr = png_create_info_struct(png_ptr); - if (!info_ptr) { - video_log("[video_take_screenshot] png_create_info_struct failed"); - fclose(fp); - return; + info_ptr[monitor_index] = png_create_info_struct(png_ptr[monitor_index]); + if (!info_ptr[monitor_index]) { + video_log("[video_take_screenshot] png_create_info_struct failed"); + fclose(fp); + return; } - png_init_io(png_ptr, fp); + png_init_io(png_ptr[monitor_index], fp); - png_set_IHDR(png_ptr, info_ptr, blit_data.w, blit_data.h, - 8, PNG_COLOR_TYPE_RGB, PNG_INTERLACE_NONE, - PNG_COMPRESSION_TYPE_BASE, PNG_FILTER_TYPE_BASE); + png_set_IHDR(png_ptr[monitor_index], info_ptr[monitor_index], blit_data_ptr->w, blit_data_ptr->h, + 8, PNG_COLOR_TYPE_RGB, PNG_INTERLACE_NONE, + PNG_COMPRESSION_TYPE_BASE, PNG_FILTER_TYPE_BASE); - b_rgb = (png_bytep *) malloc(sizeof(png_bytep) * blit_data.h); + b_rgb = (png_bytep *) malloc(sizeof(png_bytep) * blit_data_ptr->h); if (b_rgb == NULL) { - video_log("[video_take_screenshot] Unable to Allocate RGB Bitmap Memory"); - fclose(fp); - return; + video_log("[video_take_screenshot] Unable to Allocate RGB Bitmap Memory"); + fclose(fp); + return; } - for (y = 0; y < blit_data.h; ++y) { - b_rgb[y] = (png_byte *) malloc(png_get_rowbytes(png_ptr, info_ptr)); - for (x = 0; x < blit_data.w; ++x) { - if (buf == NULL) - memset(&(b_rgb[y][x * 3]), 0x00, 3); - else { - temp = buf[((start_y + y) * row_len) + start_x + x]; - b_rgb[y][x * 3] = (temp >> 16) & 0xff; - b_rgb[y][(x * 3) + 1] = (temp >> 8) & 0xff; - b_rgb[y][(x * 3) + 2] = temp & 0xff; - } - } + for (int y = 0; y < blit_data_ptr->h; ++y) { + b_rgb[y] = (png_byte *) malloc(png_get_rowbytes(png_ptr[monitor_index], info_ptr[monitor_index])); + for (int x = 0; x < blit_data_ptr->w; ++x) { + if (buf == NULL) + memset(&(b_rgb[y][x * 3]), 0x00, 3); + else { + temp = buf[((start_y + y) * row_len) + start_x + x]; + b_rgb[y][x * 3] = (temp >> 16) & 0xff; + b_rgb[y][(x * 3) + 1] = (temp >> 8) & 0xff; + b_rgb[y][(x * 3) + 2] = temp & 0xff; + } + } } - png_write_info(png_ptr, info_ptr); + png_write_info(png_ptr[monitor_index], info_ptr[monitor_index]); - png_write_image(png_ptr, b_rgb); + png_write_image(png_ptr[monitor_index], b_rgb); - png_write_end(png_ptr, NULL); + png_write_end(png_ptr[monitor_index], NULL); /* cleanup heap allocation */ - for (i = 0; i < blit_data.h; i++) - if (b_rgb[i]) free(b_rgb[i]); + for (int i = 0; i < blit_data_ptr->h; i++) + if (b_rgb[i]) + free(b_rgb[i]); - if (b_rgb) free(b_rgb); + if (b_rgb) + free(b_rgb); - if (fp) fclose(fp); + if (fp) + fclose(fp); } - void -video_screenshot(uint32_t *buf, int start_x, int start_y, int row_len) +video_screenshot_monitor(uint32_t *buf, int start_x, int start_y, int row_len, int monitor_index) { - char path[1024], fn[128]; + char path[1024]; + char fn[256]; memset(fn, 0, sizeof(fn)); memset(path, 0, sizeof(path)); - plat_append_filename(path, usr_path, SCREENSHOT_PATH); + path_append_filename(path, usr_path, SCREENSHOT_PATH); - if (! plat_dir_check(path)) - plat_dir_create(path); + if (!plat_dir_check(path)) + plat_dir_create(path); - plat_path_slash(path); + path_slash(path); + strcat(path, "Monitor_"); + snprintf(&path[strlen(path)], 42, "%d_", monitor_index + 1); plat_tempfile(fn, NULL, ".png"); strcat(path, fn); video_log("taking screenshot to: %s\n", path); - video_take_screenshot((const char *) path, buf, start_x, start_y, row_len); - png_destroy_write_struct(&png_ptr, &info_ptr); + video_take_screenshot_monitor((const char *) path, buf, start_x, start_y, row_len, monitor_index); + png_destroy_write_struct(&png_ptr[monitor_index], &info_ptr[monitor_index]); - screenshots--; + atomic_fetch_sub(&monitors[monitor_index].mon_screenshots, 1); } +void +video_screenshot(uint32_t *buf, int start_x, int start_y, int row_len) +{ + video_screenshot_monitor(buf, start_x, start_y, row_len, 0); +} #ifdef _WIN32 -void * __cdecl -video_transform_copy(void *_Dst, const void *_Src, size_t _Size) +void *__cdecl video_transform_copy(void *_Dst, const void *_Src, size_t _Size) #else void * video_transform_copy(void *__restrict _Dst, const void *__restrict _Src, size_t _Size) #endif { - int i; - uint32_t *dest_ex = (uint32_t *) _Dst; - uint32_t *src_ex = (uint32_t *) _Src; + uint32_t *dest_ex = (uint32_t *) _Dst; + const uint32_t *src_ex = (const uint32_t *) _Src; _Size /= sizeof(uint32_t); if ((dest_ex != NULL) && (src_ex != NULL)) { - for (i = 0; i < _Size; i++) { - *dest_ex = video_color_transform(*src_ex); - dest_ex++; - src_ex++; - } + for (size_t i = 0; i < _Size; i++) { + *dest_ex = video_color_transform(*src_ex); + dest_ex++; + src_ex++; + } } return _Dst; } - -static -void blit_thread(void *param) +static void +blit_thread(void *param) { - while (thread_run) { - thread_wait_event(blit_data.wake_blit_thread, -1); - thread_reset_event(blit_data.wake_blit_thread); - MTR_BEGIN("video", "blit_thread"); + blit_data_t *data = param; + while (data->thread_run) { + thread_wait_event(data->wake_blit_thread, -1); + thread_reset_event(data->wake_blit_thread); + MTR_BEGIN("video", "blit_thread"); - if (blit_func) - blit_func(blit_data.x, blit_data.y, blit_data.w, blit_data.h); + if (blit_func) + blit_func(data->x, data->y, data->w, data->h, data->monitor_index); - blit_data.busy = 0; + data->busy = 0; - MTR_END("video", "blit_thread"); - thread_set_event(blit_data.blit_complete); + MTR_END("video", "blit_thread"); + thread_set_event(data->blit_complete); } } - void -video_blit_memtoscreen(int x, int y, int w, int h) +video_blit_memtoscreen_monitor(int x, int y, int w, int h, int monitor_index) { MTR_BEGIN("video", "video_blit_memtoscreen"); if ((w <= 0) || (h <= 0)) - return; + return; - video_wait_for_blit(); + video_wait_for_blit_monitor(monitor_index); - blit_data.busy = 1; - blit_data.buffer_in_use = 1; - blit_data.x = x; - blit_data.y = y; - blit_data.w = w; - blit_data.h = h; + monitors[monitor_index].mon_blit_data_ptr->busy = 1; + monitors[monitor_index].mon_blit_data_ptr->buffer_in_use = 1; + monitors[monitor_index].mon_blit_data_ptr->x = x; + monitors[monitor_index].mon_blit_data_ptr->y = y; + monitors[monitor_index].mon_blit_data_ptr->w = w; + monitors[monitor_index].mon_blit_data_ptr->h = h; - thread_set_event(blit_data.wake_blit_thread); + thread_set_event(monitors[monitor_index].mon_blit_data_ptr->wake_blit_thread); MTR_END("video", "video_blit_memtoscreen"); } - -uint8_t pixels8(uint32_t *pixels) +uint8_t +pixels8(uint32_t *pixels) { - int i; uint8_t temp = 0; - for (i = 0; i < 8; i++) - temp |= (!!*(pixels + i) << (i ^ 7)); + for (uint8_t i = 0; i < 8; i++) + temp |= (!!*(pixels + i) << (i ^ 7)); return temp; } - -uint32_t pixel_to_color(uint8_t *pixels32, uint8_t pos) +uint32_t +pixel_to_color(uint8_t *pixels32, uint8_t pos) { uint32_t temp; temp = *(pixels32 + pos) & 0x03; switch (temp) { - case 0: - default: - return 0x00; - case 1: - return 0x07; - case 2: - return 0x0f; + default: + case 0: + return 0x00; + case 1: + return 0x07; + case 2: + return 0x0f; } } - void -video_blend(int x, int y) +video_blend_monitor(int x, int y, int monitor_index) { - int xx; - uint32_t pixels32_1, pixels32_2; - unsigned int val1, val2; + uint32_t pixels32_1; + uint32_t pixels32_2; + unsigned int val1; + unsigned int val2; static unsigned int carry = 0; if (!herc_blend) - return; + return; if (!x) - carry = 0; + carry = 0; - val1 = pixels8(&(buffer32->line[y][x])); - val2 = (val1 >> 1) + carry; - carry = (val1 & 1) << 7; + val1 = pixels8(&(monitors[monitor_index].target_buffer->line[y][x])); + val2 = (val1 >> 1) + carry; + carry = (val1 & 1) << 7; pixels32_1 = cga_2_table[val1 >> 4] + cga_2_table[val2 >> 4]; pixels32_2 = cga_2_table[val1 & 0xf] + cga_2_table[val2 & 0xf]; - for (xx = 0; xx < 4; xx++) { - buffer32->line[y][x + xx] = pixel_to_color((uint8_t *) &pixels32_1, xx); - buffer32->line[y][x + (xx | 4)] = pixel_to_color((uint8_t *) &pixels32_2, xx); + for (uint8_t xx = 0; xx < 4; xx++) { + monitors[monitor_index].target_buffer->line[y][x + xx] = pixel_to_color((uint8_t *) &pixels32_1, xx); + monitors[monitor_index].target_buffer->line[y][x + (xx | 4)] = pixel_to_color((uint8_t *) &pixels32_2, xx); } } - void -video_blit_memtoscreen_8(int x, int y, int w, int h) +video_process_8_monitor(int x, int y, int monitor_index) { - int yy, xx; - - if ((w > 0) && (h > 0)) { - for (yy = 0; yy < h; yy++) { - if ((y + yy) >= 0 && (y + yy) < buffer32->h) { - for (xx = 0; xx < w; xx++) { - if (buffer32->line[y + yy][x + xx] <= 0xff) - buffer32->line[y + yy][x + xx] = pal_lookup[buffer32->line[y + yy][x + xx]]; - else - buffer32->line[y + yy][x + xx] = 0x00000000; - } - } - } + for (int xx = 0; xx < x; xx++) { + if (monitors[monitor_index].target_buffer->line[y][xx] <= 0xff) + monitors[monitor_index].target_buffer->line[y][xx] = monitors[monitor_index].mon_pal_lookup[monitors[monitor_index].target_buffer->line[y][xx]]; + else + monitors[monitor_index].target_buffer->line[y][xx] = 0x00000000; } - - video_blit_memtoscreen(x, y, w, h); } - void -cgapal_rebuild(void) +cgapal_rebuild_monitor(int monitor_index) { - int c; + int c; + uint32_t *palette_lookup = monitors[monitor_index].mon_pal_lookup; + int cga_palette_monitor = 0; /* We cannot do this (yet) if we have not been enabled yet. */ - if (video_6to8 == NULL) return; + if (video_6to8 == NULL) + return; - for (c=0; c<256; c++) { - pal_lookup[c] = makecol(video_6to8[cgapal[c].r], - video_6to8[cgapal[c].g], - video_6to8[cgapal[c].b]); + if (monitors[monitor_index].target_buffer == NULL || monitors[monitor_index].mon_cga_palette == NULL) + return; + + cga_palette_monitor = *monitors[monitor_index].mon_cga_palette; + + for (c = 0; c < 256; c++) { + palette_lookup[c] = makecol(video_6to8[cgapal[c].r], + video_6to8[cgapal[c].g], + video_6to8[cgapal[c].b]); } - if ((cga_palette > 1) && (cga_palette < 7)) { - if (vid_cga_contrast != 0) { - for (c = 0; c < 16; c++) { - pal_lookup[c] = makecol(video_6to8[cgapal_mono[cga_palette - 2][c].r], - video_6to8[cgapal_mono[cga_palette - 2][c].g], - video_6to8[cgapal_mono[cga_palette - 2][c].b]); - pal_lookup[c+16] = makecol(video_6to8[cgapal_mono[cga_palette - 2][c].r], - video_6to8[cgapal_mono[cga_palette - 2][c].g], - video_6to8[cgapal_mono[cga_palette - 2][c].b]); - pal_lookup[c+32] = makecol(video_6to8[cgapal_mono[cga_palette - 2][c].r], - video_6to8[cgapal_mono[cga_palette - 2][c].g], - video_6to8[cgapal_mono[cga_palette - 2][c].b]); - pal_lookup[c+48] = makecol(video_6to8[cgapal_mono[cga_palette - 2][c].r], - video_6to8[cgapal_mono[cga_palette - 2][c].g], - video_6to8[cgapal_mono[cga_palette - 2][c].b]); - } - } else { - for (c = 0; c < 16; c++) { - pal_lookup[c] = makecol(video_6to8[cgapal_mono[cga_palette - 1][c].r], - video_6to8[cgapal_mono[cga_palette - 1][c].g], - video_6to8[cgapal_mono[cga_palette - 1][c].b]); - pal_lookup[c+16] = makecol(video_6to8[cgapal_mono[cga_palette - 1][c].r], - video_6to8[cgapal_mono[cga_palette - 1][c].g], - video_6to8[cgapal_mono[cga_palette - 1][c].b]); - pal_lookup[c+32] = makecol(video_6to8[cgapal_mono[cga_palette - 1][c].r], - video_6to8[cgapal_mono[cga_palette - 1][c].g], - video_6to8[cgapal_mono[cga_palette - 1][c].b]); - pal_lookup[c+48] = makecol(video_6to8[cgapal_mono[cga_palette - 1][c].r], - video_6to8[cgapal_mono[cga_palette - 1][c].g], - video_6to8[cgapal_mono[cga_palette - 1][c].b]); - } - } + if ((cga_palette_monitor > 1) && (cga_palette_monitor < 7)) { + if (vid_cga_contrast != 0) { + for (c = 0; c < 16; c++) { + palette_lookup[c] = makecol(video_6to8[cgapal_mono[cga_palette_monitor - 2][c].r], + video_6to8[cgapal_mono[cga_palette_monitor - 2][c].g], + video_6to8[cgapal_mono[cga_palette_monitor - 2][c].b]); + palette_lookup[c + 16] = makecol(video_6to8[cgapal_mono[cga_palette_monitor - 2][c].r], + video_6to8[cgapal_mono[cga_palette_monitor - 2][c].g], + video_6to8[cgapal_mono[cga_palette_monitor - 2][c].b]); + palette_lookup[c + 32] = makecol(video_6to8[cgapal_mono[cga_palette_monitor - 2][c].r], + video_6to8[cgapal_mono[cga_palette_monitor - 2][c].g], + video_6to8[cgapal_mono[cga_palette_monitor - 2][c].b]); + palette_lookup[c + 48] = makecol(video_6to8[cgapal_mono[cga_palette_monitor - 2][c].r], + video_6to8[cgapal_mono[cga_palette_monitor - 2][c].g], + video_6to8[cgapal_mono[cga_palette_monitor - 2][c].b]); + } + } else { + for (c = 0; c < 16; c++) { + palette_lookup[c] = makecol(video_6to8[cgapal_mono[cga_palette_monitor - 1][c].r], + video_6to8[cgapal_mono[cga_palette_monitor - 1][c].g], + video_6to8[cgapal_mono[cga_palette_monitor - 1][c].b]); + palette_lookup[c + 16] = makecol(video_6to8[cgapal_mono[cga_palette_monitor - 1][c].r], + video_6to8[cgapal_mono[cga_palette_monitor - 1][c].g], + video_6to8[cgapal_mono[cga_palette_monitor - 1][c].b]); + palette_lookup[c + 32] = makecol(video_6to8[cgapal_mono[cga_palette_monitor - 1][c].r], + video_6to8[cgapal_mono[cga_palette_monitor - 1][c].g], + video_6to8[cgapal_mono[cga_palette_monitor - 1][c].b]); + palette_lookup[c + 48] = makecol(video_6to8[cgapal_mono[cga_palette_monitor - 1][c].r], + video_6to8[cgapal_mono[cga_palette_monitor - 1][c].g], + video_6to8[cgapal_mono[cga_palette_monitor - 1][c].b]); + } + } } - if (cga_palette == 7) - pal_lookup[0x16] = makecol(video_6to8[42],video_6to8[42],video_6to8[0]); + if (cga_palette_monitor == 7) + palette_lookup[0x16] = makecol(video_6to8[42], video_6to8[42], video_6to8[0]); } - void -video_inform(int type, const video_timings_t *ptr) +video_inform_monitor(int type, const video_timings_t *ptr, int monitor_index) { - vid_type = type; - vid_timings = ptr; + monitor_t *monitor = &monitors[monitor_index]; + monitor->mon_vid_type = type; + monitor->mon_vid_timings = ptr; } - int -video_get_type(void) +video_get_type_monitor(int monitor_index) { - return vid_type; + return monitors[monitor_index].mon_vid_type; } - void video_update_timing(void) { - if (!vid_timings) - return; + const video_timings_t *monitor_vid_timings = NULL; + int *vid_timing_read_b = NULL; + int *vid_timing_read_l = NULL; + int *vid_timing_read_w = NULL; + int *vid_timing_write_b = NULL; + int *vid_timing_write_l = NULL; + int *vid_timing_write_w = NULL; - if (vid_timings->type == VIDEO_ISA) { - video_timing_read_b = ISA_CYCLES(vid_timings->read_b); - video_timing_read_w = ISA_CYCLES(vid_timings->read_w); - video_timing_read_l = ISA_CYCLES(vid_timings->read_l); - video_timing_write_b = ISA_CYCLES(vid_timings->write_b); - video_timing_write_w = ISA_CYCLES(vid_timings->write_w); - video_timing_write_l = ISA_CYCLES(vid_timings->write_l); - } else if (vid_timings->type == VIDEO_PCI) { - video_timing_read_b = (int)(pci_timing * vid_timings->read_b); - video_timing_read_w = (int)(pci_timing * vid_timings->read_w); - video_timing_read_l = (int)(pci_timing * vid_timings->read_l); - video_timing_write_b = (int)(pci_timing * vid_timings->write_b); - video_timing_write_w = (int)(pci_timing * vid_timings->write_w); - video_timing_write_l = (int)(pci_timing * vid_timings->write_l); - } else if (vid_timings->type == VIDEO_AGP) { - video_timing_read_b = (int)(agp_timing * vid_timings->read_b); - video_timing_read_w = (int)(agp_timing * vid_timings->read_w); - video_timing_read_l = (int)(agp_timing * vid_timings->read_l); - video_timing_write_b = (int)(agp_timing * vid_timings->write_b); - video_timing_write_w = (int)(agp_timing * vid_timings->write_w); - video_timing_write_l = (int)(agp_timing * vid_timings->write_l); - } else { - video_timing_read_b = (int)(bus_timing * vid_timings->read_b); - video_timing_read_w = (int)(bus_timing * vid_timings->read_w); - video_timing_read_l = (int)(bus_timing * vid_timings->read_l); - video_timing_write_b = (int)(bus_timing * vid_timings->write_b); - video_timing_write_w = (int)(bus_timing * vid_timings->write_w); - video_timing_write_l = (int)(bus_timing * vid_timings->write_l); - } + for (uint8_t i = 0; i < MONITORS_NUM; i++) { + monitor_vid_timings = monitors[i].mon_vid_timings; + if (!monitor_vid_timings) + continue; + vid_timing_read_b = &monitors[i].mon_video_timing_read_b; + vid_timing_read_l = &monitors[i].mon_video_timing_read_l; + vid_timing_read_w = &monitors[i].mon_video_timing_read_w; + vid_timing_write_b = &monitors[i].mon_video_timing_write_b; + vid_timing_write_l = &monitors[i].mon_video_timing_write_l; + vid_timing_write_w = &monitors[i].mon_video_timing_write_w; - if (cpu_16bitbus) { - video_timing_read_l = video_timing_read_w * 2; - video_timing_write_l = video_timing_write_w * 2; + if (monitor_vid_timings->type == VIDEO_ISA) { + *vid_timing_read_b = ISA_CYCLES(monitor_vid_timings->read_b); + *vid_timing_read_w = ISA_CYCLES(monitor_vid_timings->read_w); + *vid_timing_read_l = ISA_CYCLES(monitor_vid_timings->read_l); + *vid_timing_write_b = ISA_CYCLES(monitor_vid_timings->write_b); + *vid_timing_write_w = ISA_CYCLES(monitor_vid_timings->write_w); + *vid_timing_write_l = ISA_CYCLES(monitor_vid_timings->write_l); + } else if (monitor_vid_timings->type == VIDEO_PCI) { + *vid_timing_read_b = (int) (pci_timing * monitor_vid_timings->read_b); + *vid_timing_read_w = (int) (pci_timing * monitor_vid_timings->read_w); + *vid_timing_read_l = (int) (pci_timing * monitor_vid_timings->read_l); + *vid_timing_write_b = (int) (pci_timing * monitor_vid_timings->write_b); + *vid_timing_write_w = (int) (pci_timing * monitor_vid_timings->write_w); + *vid_timing_write_l = (int) (pci_timing * monitor_vid_timings->write_l); + } else if (monitor_vid_timings->type == VIDEO_AGP) { + *vid_timing_read_b = (int) (agp_timing * monitor_vid_timings->read_b); + *vid_timing_read_w = (int) (agp_timing * monitor_vid_timings->read_w); + *vid_timing_read_l = (int) (agp_timing * monitor_vid_timings->read_l); + *vid_timing_write_b = (int) (agp_timing * monitor_vid_timings->write_b); + *vid_timing_write_w = (int) (agp_timing * monitor_vid_timings->write_w); + *vid_timing_write_l = (int) (agp_timing * monitor_vid_timings->write_l); + } else { + *vid_timing_read_b = (int) (bus_timing * monitor_vid_timings->read_b); + *vid_timing_read_w = (int) (bus_timing * monitor_vid_timings->read_w); + *vid_timing_read_l = (int) (bus_timing * monitor_vid_timings->read_l); + *vid_timing_write_b = (int) (bus_timing * monitor_vid_timings->write_b); + *vid_timing_write_w = (int) (bus_timing * monitor_vid_timings->write_w); + *vid_timing_write_l = (int) (bus_timing * monitor_vid_timings->write_l); + } + + if (cpu_16bitbus) { + *vid_timing_read_l = *vid_timing_read_w * 2; + *vid_timing_write_l = *vid_timing_write_w * 2; + } } } - int calc_6to8(int c) { - int ic, i8; + int ic; + int i8; double d8; ic = c; if (ic == 64) - ic = 63; - else - ic &= 0x3f; + ic = 63; + else + ic &= 0x3f; d8 = (ic / 63.0) * 255.0; i8 = (int) d8; - return(i8 & 0xff); + return (i8 & 0xff); } - int calc_8to32(int c) { - int b, g, r; - double db, dg, dr; + int b; + int g; + int r; + double db; + double dg; + double dr; - b = (c & 3); - g = ((c >> 2) & 7); - r = ((c >> 5) & 7); - db = (((double) b) / 3.0) * 255.0; - dg = (((double) g) / 7.0) * 255.0; - dr = (((double) r) / 7.0) * 255.0; - b = (int) db; - g = ((int) dg) << 8; - r = ((int) dr) << 16; + b = (c & 3); + g = ((c >> 2) & 7); + r = ((c >> 5) & 7); + db = (((double) b) / 3.0) * 255.0; + dg = (((double) g) / 7.0) * 255.0; + dr = (((double) r) / 7.0) * 255.0; + b = (int) db; + g = ((int) dg) << 8; + r = ((int) dr) << 16; - return(b | g | r); + return (b | g | r); } - int calc_15to32(int c) { - int b, g, r; - double db, dg, dr; + int b; + int g; + int r; + double db; + double dg; + double dr; - b = (c & 31); - g = ((c >> 5) & 31); - r = ((c >> 10) & 31); + b = (c & 31); + g = ((c >> 5) & 31); + r = ((c >> 10) & 31); db = (((double) b) / 31.0) * 255.0; dg = (((double) g) / 31.0) * 255.0; dr = (((double) r) / 31.0) * 255.0; - b = (int) db; - g = ((int) dg) << 8; - r = ((int) dr) << 16; + b = (int) db; + g = ((int) dg) << 8; + r = ((int) dr) << 16; - return(b | g | r); + return (b | g | r); } - int calc_16to32(int c) { - int b, g, r; - double db, dg, dr; + int b; + int g; + int r; + double db; + double dg; + double dr; - b = (c & 31); - g = ((c >> 5) & 63); - r = ((c >> 11) & 31); + b = (c & 31); + g = ((c >> 5) & 63); + r = ((c >> 11) & 31); db = (((double) b) / 31.0) * 255.0; dg = (((double) g) / 63.0) * 255.0; dr = (((double) r) / 31.0) * 255.0; - b = (int) db; - g = ((int) dg) << 8; - r = ((int) dr) << 16; + b = (int) db; + g = ((int) dg) << 8; + r = ((int) dr) << 16; - return(b | g | r); + return (b | g | r); } - void hline(bitmap_t *b, int x1, int y, int x2, uint32_t col) { - int x; + if (y < 0 || y >= b->h) + return; - if (y < 0 || y >= buffer32->h) - return; - - for (x = x1; x < x2; x++) - b->line[y][x] = col; + for (int x = x1; x < x2; x++) + b->line[y][x] = col; } - void -blit(bitmap_t *src, bitmap_t *dst, int x1, int y1, int x2, int y2, int xs, int ys) +blit(UNUSED(bitmap_t *src), UNUSED(bitmap_t *dst), UNUSED(int x1), UNUSED(int y1), UNUSED(int x2), UNUSED(int y2), UNUSED(int xs), UNUSED(int ys)) { + // } - void -stretch_blit(bitmap_t *src, bitmap_t *dst, int x1, int y1, int xs1, int ys1, int x2, int y2, int xs2, int ys2) +stretch_blit(UNUSED(bitmap_t *src), UNUSED(bitmap_t *dst), UNUSED(int x1), UNUSED(int y1), UNUSED(int xs1), UNUSED(int ys1), UNUSED(int x2), UNUSED(int y2), UNUSED(int xs2), UNUSED(int ys2)) { + // } - void -rectfill(bitmap_t *b, int x1, int y1, int x2, int y2, uint32_t col) +rectfill(UNUSED(bitmap_t *b), UNUSED(int x1), UNUSED(int y1), UNUSED(int x2), UNUSED(int y2), UNUSED(uint32_t col)) { + // } - void -set_palette(PALETTE p) +set_palette(UNUSED(PALETTE p)) { + // } - void destroy_bitmap(bitmap_t *b) { if ((b != NULL) && (b->dat != NULL)) - free(b->dat); + free(b->dat); if (b != NULL) - free(b); + free(b); } - bitmap_t * create_bitmap(int x, int y) { bitmap_t *b = malloc(sizeof(bitmap_t) + (y * sizeof(uint32_t *))); - int c; - b->dat = malloc(x * y * 4); - for (c = 0; c < y; c++) - b->line[c] = &(b->dat[c * x]); + b->dat = malloc((size_t) x * y * 4); + for (int c = 0; c < y; c++) + b->line[c] = &(b->dat[c * x]); b->w = x; b->h = y; - return(b); + return b; } +void +video_monitor_init(int index) +{ + memset(&monitors[index], 0, sizeof(monitor_t)); + monitors[index].mon_xsize = 640; + monitors[index].mon_ysize = 480; + monitors[index].mon_res_x = 640; + monitors[index].mon_res_y = 480; + monitors[index].mon_scrnsz_x = 640; + monitors[index].mon_scrnsz_y = 480; + monitors[index].mon_efscrnsz_y = 480; + monitors[index].mon_unscaled_size_x = 480; + monitors[index].mon_unscaled_size_y = 480; + monitors[index].mon_bpp = 8; + monitors[index].mon_changeframecount = 2; + monitors[index].target_buffer = create_bitmap(2048, 2048); + monitors[index].mon_blit_data_ptr = calloc(1, sizeof(blit_data_t)); + monitors[index].mon_blit_data_ptr->wake_blit_thread = thread_create_event(); + monitors[index].mon_blit_data_ptr->blit_complete = thread_create_event(); + monitors[index].mon_blit_data_ptr->buffer_not_in_use = thread_create_event(); + monitors[index].mon_blit_data_ptr->thread_run = 1; + monitors[index].mon_blit_data_ptr->monitor_index = index; + monitors[index].mon_pal_lookup = calloc(sizeof(uint32_t), 256); + monitors[index].mon_cga_palette = calloc(1, sizeof(int)); + monitors[index].mon_force_resize = 1; + monitors[index].mon_vid_type = VIDEO_FLAG_TYPE_NONE; + atomic_init(&doresize_monitors[index], 0); + atomic_init(&monitors[index].mon_screenshots, 0); + if (index >= 1) + ui_init_monitor(index); + monitors[index].mon_blit_data_ptr->blit_thread = thread_create(blit_thread, monitors[index].mon_blit_data_ptr); +} + +void +video_monitor_close(int monitor_index) +{ + if (monitors[monitor_index].target_buffer == NULL) { + return; + } + monitors[monitor_index].mon_blit_data_ptr->thread_run = 0; + thread_set_event(monitors[monitor_index].mon_blit_data_ptr->wake_blit_thread); + thread_wait(monitors[monitor_index].mon_blit_data_ptr->blit_thread); + if (monitor_index >= 1) + ui_deinit_monitor(monitor_index); + thread_destroy_event(monitors[monitor_index].mon_blit_data_ptr->buffer_not_in_use); + thread_destroy_event(monitors[monitor_index].mon_blit_data_ptr->blit_complete); + thread_destroy_event(monitors[monitor_index].mon_blit_data_ptr->wake_blit_thread); + free(monitors[monitor_index].mon_blit_data_ptr); + if (!monitors[monitor_index].mon_pal_lookup_static) + free(monitors[monitor_index].mon_pal_lookup); + if (!monitors[monitor_index].mon_cga_palette_static) + free(monitors[monitor_index].mon_cga_palette); + destroy_bitmap(monitors[monitor_index].target_buffer); + monitors[monitor_index].target_buffer = NULL; + memset(&monitors[monitor_index], 0, sizeof(monitor_t)); +} void video_init(void) { - int c, d; uint8_t total[2] = { 0, 1 }; - for (c = 0; c < 16; c++) { - cga_2_table[c] = (total[(c >> 3) & 1] << 0 ) | (total[(c >> 2) & 1] << 8 ) | - (total[(c >> 1) & 1] << 16) | (total[(c >> 0) & 1] << 24); + for (uint8_t c = 0; c < 16; c++) { + cga_2_table[c] = (total[(c >> 3) & 1] << 0) | (total[(c >> 2) & 1] << 8) | (total[(c >> 1) & 1] << 16) | (total[(c >> 0) & 1] << 24); } - /* Account for overscan. */ - buffer32 = create_bitmap(2048, 2048); - - for (c = 0; c < 64; c++) { - cgapal[c + 64].r = (((c & 4) ? 2 : 0) | ((c & 0x10) ? 1 : 0)) * 21; - cgapal[c + 64].g = (((c & 2) ? 2 : 0) | ((c & 0x10) ? 1 : 0)) * 21; - cgapal[c + 64].b = (((c & 1) ? 2 : 0) | ((c & 0x10) ? 1 : 0)) * 21; - if ((c & 0x17) == 6) - cgapal[c + 64].g >>= 1; + for (uint8_t c = 0; c < 64; c++) { + cgapal[c + 64].r = (((c & 4) ? 2 : 0) | ((c & 0x10) ? 1 : 0)) * 21; + cgapal[c + 64].g = (((c & 2) ? 2 : 0) | ((c & 0x10) ? 1 : 0)) * 21; + cgapal[c + 64].b = (((c & 1) ? 2 : 0) | ((c & 0x10) ? 1 : 0)) * 21; + if ((c & 0x17) == 6) + cgapal[c + 64].g >>= 1; } - for (c = 0; c < 64; c++) { - cgapal[c + 128].r = (((c & 4) ? 2 : 0) | ((c & 0x20) ? 1 : 0)) * 21; - cgapal[c + 128].g = (((c & 2) ? 2 : 0) | ((c & 0x10) ? 1 : 0)) * 21; - cgapal[c + 128].b = (((c & 1) ? 2 : 0) | ((c & 0x08) ? 1 : 0)) * 21; + for (uint8_t c = 0; c < 64; c++) { + cgapal[c + 128].r = (((c & 4) ? 2 : 0) | ((c & 0x20) ? 1 : 0)) * 21; + cgapal[c + 128].g = (((c & 2) ? 2 : 0) | ((c & 0x10) ? 1 : 0)) * 21; + cgapal[c + 128].b = (((c & 1) ? 2 : 0) | ((c & 0x08) ? 1 : 0)) * 21; } - for (c = 0; c < 4; c++) { - for (d = 0; d < 4; d++) { - edatlookup[c][d] = 0; - if (c & 1) edatlookup[c][d] |= 1; - if (d & 1) edatlookup[c][d] |= 2; - if (c & 2) edatlookup[c][d] |= 0x10; - if (d & 2) edatlookup[c][d] |= 0x20; - } + for (uint8_t c = 0; c < 4; c++) { + for (uint8_t d = 0; d < 4; d++) { + edatlookup[c][d] = 0; + if (c & 1) + edatlookup[c][d] |= 1; + if (d & 1) + edatlookup[c][d] |= 2; + if (c & 2) + edatlookup[c][d] |= 0x10; + if (d & 2) + edatlookup[c][d] |= 0x20; + } } video_6to8 = malloc(4 * 256); - for (c = 0; c < 256; c++) - video_6to8[c] = calc_6to8(c); + for (uint16_t c = 0; c < 256; c++) + video_6to8[c] = calc_6to8(c); video_8togs = malloc(4 * 256); - for (c = 0; c < 256; c++) - video_8togs[c] = c | (c << 16) | (c << 24); + for (uint16_t c = 0; c < 256; c++) + video_8togs[c] = c | (c << 16) | (c << 24); video_8to32 = malloc(4 * 256); - for (c = 0; c < 256; c++) - video_8to32[c] = calc_8to32(c); + for (uint16_t c = 0; c < 256; c++) + video_8to32[c] = calc_8to32(c); video_15to32 = malloc(4 * 65536); - for (c = 0; c < 65536; c++) - video_15to32[c] = calc_15to32(c & 0x7fff); + for (uint32_t c = 0; c < 65536; c++) + video_15to32[c] = calc_15to32(c & 0x7fff); video_16to32 = malloc(4 * 65536); - for (c = 0; c < 65536; c++) - video_16to32[c] = calc_16to32(c); + for (uint32_t c = 0; c < 65536; c++) + video_16to32[c] = calc_16to32(c); - blit_data.wake_blit_thread = thread_create_event(); - blit_data.blit_complete = thread_create_event(); - blit_data.buffer_not_in_use = thread_create_event(); - thread_run = 1; - blit_data.blit_thread = thread_create(blit_thread, NULL); + memset(monitors, 0, sizeof(monitors)); + video_monitor_init(0); } - void video_close(void) { - thread_run = 0; - thread_set_event(blit_data.wake_blit_thread); - thread_wait(blit_data.blit_thread); - thread_destroy_event(blit_data.buffer_not_in_use); - thread_destroy_event(blit_data.blit_complete); - thread_destroy_event(blit_data.wake_blit_thread); + video_monitor_close(0); free(video_16to32); free(video_15to32); @@ -900,169 +950,175 @@ video_close(void) free(video_8togs); free(video_6to8); - destroy_bitmap(buffer32); - if (fontdatksc5601) { - free(fontdatksc5601); - fontdatksc5601 = NULL; + free(fontdatksc5601); + fontdatksc5601 = NULL; } if (fontdatksc5601_user) { - free(fontdatksc5601_user); - fontdatksc5601_user = NULL; + free(fontdatksc5601_user); + fontdatksc5601_user = NULL; } } - uint8_t -video_force_resize_get(void) +video_force_resize_get_monitor(int monitor_index) { - return video_force_resize; + return monitors[monitor_index].mon_force_resize; } - void -video_force_resize_set(uint8_t res) +video_force_resize_set_monitor(uint8_t res, int monitor_index) { - video_force_resize = res; + monitors[monitor_index].mon_force_resize = res; } void loadfont_common(FILE *f, int format) { - int c, d; - - switch (format) { - case 0: /* MDA */ - for (c=0; c<256; c++) - for (d=0; d<8; d++) - fontdatm[c][d] = fgetc(f) & 0xff; - for (c=0; c<256; c++) - for (d=0; d<8; d++) - fontdatm[c][d+8] = fgetc(f) & 0xff; - (void)fseek(f, 4096+2048, SEEK_SET); - for (c=0; c<256; c++) - for (d=0; d<8; d++) - fontdat[c][d] = fgetc(f) & 0xff; - break; + int c; + int d; - case 1: /* PC200 */ - for (d = 0; d < 4; d++) { - /* There are 4 fonts in the ROM */ - for (c = 0; c < 256; c++) /* 8x14 MDA in 8x16 cell */ - fread(&fontdatm[256*d + c][0], 1, 16, f); - for (c = 0; c < 256; c++) { /* 8x8 CGA in 8x16 cell */ - fread(&fontdat[256*d + c][0], 1, 8, f); - fseek(f, 8, SEEK_CUR); - } - } - break; + switch (format) { + case 0: /* MDA */ + for (c = 0; c < 256; c++) + for (d = 0; d < 8; d++) + fontdatm[c][d] = fgetc(f) & 0xff; + for (c = 0; c < 256; c++) + for (d = 0; d < 8; d++) + fontdatm[c][d + 8] = fgetc(f) & 0xff; + (void) fseek(f, 4096 + 2048, SEEK_SET); + for (c = 0; c < 256; c++) + for (d = 0; d < 8; d++) + fontdat[c][d] = fgetc(f) & 0xff; + break; - default: - case 2: /* CGA */ - for (c=0; c<256; c++) - for (d=0; d<8; d++) - fontdat[c][d] = fgetc(f) & 0xff; - break; + case 1: /* PC200 */ + for (d = 0; d < 4; d++) { + /* There are 4 fonts in the ROM */ + for (c = 0; c < 256; c++) /* 8x14 MDA in 8x16 cell */ + (void) !fread(&fontdatm[256 * d + c][0], 1, 16, f); + for (c = 0; c < 256; c++) { /* 8x8 CGA in 8x16 cell */ + (void) !fread(&fontdat[256 * d + c][0], 1, 8, f); + fseek(f, 8, SEEK_CUR); + } + } + break; - case 3: /* Wyse 700 */ - for (c=0; c<512; c++) - for (d=0; d<32; d++) - fontdatw[c][d] = fgetc(f) & 0xff; - break; + default: + case 2: /* CGA */ + for (c = 0; c < 256; c++) + for (d = 0; d < 8; d++) + fontdat[c][d] = fgetc(f) & 0xff; + break; - case 4: /* MDSI Genius */ - for (c=0; c<256; c++) - for (d=0; d<16; d++) - fontdat8x12[c][d] = fgetc(f) & 0xff; - break; + case 3: /* Wyse 700 */ + for (c = 0; c < 512; c++) + for (d = 0; d < 32; d++) + fontdatw[c][d] = fgetc(f) & 0xff; + break; - case 5: /* Toshiba 3100e */ - for (d = 0; d < 2048; d += 512) /* Four languages... */ - { - for (c = d; c < d+256; c++) - { - fread(&fontdatm[c][8], 1, 8, f); - } - for (c = d+256; c < d+512; c++) - { - fread(&fontdatm[c][8], 1, 8, f); - } - for (c = d; c < d+256; c++) - { - fread(&fontdatm[c][0], 1, 8, f); - } - for (c = d+256; c < d+512; c++) - { - fread(&fontdatm[c][0], 1, 8, f); - } - fseek(f, 4096, SEEK_CUR); /* Skip blank section */ - for (c = d; c < d+256; c++) - { - fread(&fontdat[c][0], 1, 8, f); - } - for (c = d+256; c < d+512; c++) - { - fread(&fontdat[c][0], 1, 8, f); - } - } - break; + case 4: /* MDSI Genius */ + for (c = 0; c < 256; c++) + for (d = 0; d < 16; d++) + fontdat8x12[c][d] = fgetc(f) & 0xff; + break; - case 6: /* Korean KSC-5601 */ - if (!fontdatksc5601) - fontdatksc5601 = malloc(16384 * sizeof(dbcs_font_t)); + case 5: /* Toshiba 3100e */ + for (d = 0; d < 2048; d += 512) { /* Four languages... */ + for (c = d; c < d + 256; c++) { + (void) !fread(&fontdatm[c][8], 1, 8, f); + } + for (c = d + 256; c < d + 512; c++) { + (void) !fread(&fontdatm[c][8], 1, 8, f); + } + for (c = d; c < d + 256; c++) { + (void) !fread(&fontdatm[c][0], 1, 8, f); + } + for (c = d + 256; c < d + 512; c++) { + (void) !fread(&fontdatm[c][0], 1, 8, f); + } + fseek(f, 4096, SEEK_CUR); /* Skip blank section */ + for (c = d; c < d + 256; c++) { + (void) !fread(&fontdat[c][0], 1, 8, f); + } + for (c = d + 256; c < d + 512; c++) { + (void) !fread(&fontdat[c][0], 1, 8, f); + } + } + break; - if (!fontdatksc5601_user) - fontdatksc5601_user = malloc(192 * sizeof(dbcs_font_t)); + case 6: /* Korean KSC-5601 */ + if (!fontdatksc5601) + fontdatksc5601 = malloc(16384 * sizeof(dbcs_font_t)); - for (c = 0; c < 16384; c++) - { - for (d = 0; d < 32; d++) - fontdatksc5601[c].chr[d]=fgetc(f) & 0xff; - } - break; + if (!fontdatksc5601_user) + fontdatksc5601_user = malloc(192 * sizeof(dbcs_font_t)); - case 7: /* Sigma Color 400 */ - /* The first 4k of the character ROM holds an 8x8 font */ - for (c = 0; c < 256; c++) { - fread(&fontdat[c][0], 1, 8, f); - fseek(f, 8, SEEK_CUR); - } - /* The second 4k holds an 8x16 font */ - for (c = 0; c < 256; c++) { - if (fread(&fontdatm[c][0], 1, 16, f) != 16) - fatal("loadfont(): Error reading 8x16 font in Sigma Color 400 mode, c = %i\n", c); - } - break; + for (c = 0; c < 16384; c++) { + for (d = 0; d < 32; d++) + fontdatksc5601[c].chr[d] = fgetc(f) & 0xff; + } + break; - case 8: /* Amstrad PC1512, Toshiba T1000/T1200 */ - for (c = 0; c < 2048; c++) /* Allow up to 2048 chars */ - for (d=0; d<8; d++) - fontdat[c][d] = fgetc(f) & 0xff; - break; + case 7: /* Sigma Color 400 */ + /* The first 4k of the character ROM holds an 8x8 font */ + for (c = 0; c < 256; c++) { + (void) !fread(&fontdat[c][0], 1, 8, f); + fseek(f, 8, SEEK_CUR); + } + /* The second 4k holds an 8x16 font */ + for (c = 0; c < 256; c++) { + if (fread(&fontdatm[c][0], 1, 16, f) != 16) + fatal("loadfont(): Error reading 8x16 font in Sigma Color 400 mode, c = %i\n", c); + } + break; - case 9: /* Image Manager 1024 native font */ - for (c = 0; c < 256; c++) - fread(&fontdat12x18[c][0], 1, 36, f); - break; - - } + case 8: /* Amstrad PC1512, Toshiba T1000/T1200 */ + for (c = 0; c < 2048; c++) /* Allow up to 2048 chars */ + for (d = 0; d < 8; d++) + fontdat[c][d] = fgetc(f) & 0xff; + break; - (void)fclose(f); + case 9: /* Image Manager 1024 native font */ + for (c = 0; c < 256; c++) + (void) !fread(&fontdat12x18[c][0], 1, 36, f); + break; + + case 10: /* Pravetz */ + for (c = 0; c < 1024; c++) /* Allow up to 1024 chars */ + for (d = 0; d < 8; d++) + fontdat[c][d] = fgetc(f) & 0xff; + break; + + + case 11: /* PC200 */ + for (d = 0; d < 4; d++) { + /* There are 4 fonts in the ROM */ + for (c = 0; c < 256; c++) /* 8x14 MDA in 8x16 cell */ + (void) !fread(&fontdatm2[256 * d + c][0], 1, 16, f); + for (c = 0; c < 256; c++) { /* 8x8 CGA in 8x16 cell */ + (void) !fread(&fontdat2[256 * d + c][0], 1, 8, f); + fseek(f, 8, SEEK_CUR); + } + } + break; + } + + (void) fclose(f); } void loadfont_ex(char *s, int format, int offset) { - FILE *f; - - f = rom_fopen(s, "rb"); - if (f == NULL) - return; + FILE *fp; - fseek(f, offset, SEEK_SET); - loadfont_common(f, format); + fp = rom_fopen(s, "rb"); + if (fp == NULL) + return; + fseek(fp, offset, SEEK_SET); + loadfont_common(fp, format); } void @@ -1075,28 +1131,32 @@ uint32_t video_color_transform(uint32_t color) { uint8_t *clr8 = (uint8_t *) &color; - /* if (!video_grayscale && !invert_display) - return color; */ +#if 0 + if (!video_grayscale && !invert_display) + return color; +#endif if (video_grayscale) { - if (video_graytype) { - if (video_graytype == 1) - color = ((54 * (uint32_t)clr8[2]) + (183 * (uint32_t)clr8[1]) + (18 * (uint32_t)clr8[0])) / 255; - else - color = ((uint32_t)clr8[2] + (uint32_t)clr8[1] + (uint32_t)clr8[0]) / 3; - } else - color = ((76 * (uint32_t)clr8[2]) + (150 * (uint32_t)clr8[1]) + (29 * (uint32_t)clr8[0])) / 255; - switch (video_grayscale) { - case 2: case 3: case 4: - color = (uint32_t) shade[video_grayscale][color]; - break; - default: - clr8[3] = 0; - clr8[0] = color; - clr8[1] = clr8[2] = clr8[0]; - break; - } + if (video_graytype) { + if (video_graytype == 1) + color = ((54 * (uint32_t) clr8[2]) + (183 * (uint32_t) clr8[1]) + (18 * (uint32_t) clr8[0])) / 255; + else + color = ((uint32_t) clr8[2] + (uint32_t) clr8[1] + (uint32_t) clr8[0]) / 3; + } else + color = ((76 * (uint32_t) clr8[2]) + (150 * (uint32_t) clr8[1]) + (29 * (uint32_t) clr8[0])) / 255; + switch (video_grayscale) { + case 2: + case 3: + case 4: + color = shade[video_grayscale][color]; + break; + default: + clr8[3] = 0; + clr8[0] = color; + clr8[1] = clr8[2] = clr8[0]; + break; + } } if (invert_display) - color ^= 0x00ffffff; + color ^= 0x00ffffff; return color; } diff --git a/src/vnc.c b/src/vnc.c index 440542652..7b4b1f7b0 100644 --- a/src/vnc.c +++ b/src/vnc.c @@ -1,19 +1,19 @@ /* - * 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. + * 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. + * This file is part of the 86Box distribution. * - * Implement the VNC remote renderer with LibVNCServer. + * Implement the VNC remote renderer with LibVNCServer. * * * - * Authors: Fred N. van Kempen, - * Based on raw code by RichardG, + * Authors: Fred N. van Kempen, + * Based on raw code by RichardG, * - * Copyright 2017-2019 Fred N. van Kempen. + * Copyright 2017-2019 Fred N. van Kempen. */ #include #include @@ -32,97 +32,105 @@ #include <86box/ui.h> #include <86box/vnc.h> +#define VNC_MIN_X 320 +#define VNC_MAX_X 2048 +#define VNC_MIN_Y 200 +#define VNC_MAX_Y 2048 -#define VNC_MIN_X 320 -#define VNC_MAX_X 2048 -#define VNC_MIN_Y 200 -#define VNC_MAX_Y 2048 - - -static rfbScreenInfoPtr rfb = NULL; -static int clients; -static int updatingSize; -static int allowedX, - allowedY; -static int ptr_x, ptr_y, ptr_but; - +static rfbScreenInfoPtr rfb = NULL; +static int clients; +static int updatingSize; +static int allowedX; +static int allowedY; +static int ptr_x; +static int ptr_y; +static int ptr_but; #ifdef ENABLE_VNC_LOG int vnc_do_log = ENABLE_VNC_LOG; - static void vnc_log(const char *fmt, ...) { va_list ap; if (vnc_do_log) { - va_start(ap, fmt); - pclog_ex(fmt, ap); - va_end(ap); + va_start(ap, fmt); + pclog_ex(fmt, ap); + va_end(ap); } } #else -#define vnc_log(fmt, ...) +# define vnc_log(fmt, ...) #endif - static void vnc_kbdevent(rfbBool down, rfbKeySym k, rfbClientPtr cl) { - (void)cl; + (void) cl; /* Handle it through the lookup tables. */ - vnc_kbinput(down?1:0, (int)k); + vnc_kbinput(down ? 1 : 0, (int) k); } - static void vnc_ptrevent(int but, int x, int y, rfbClientPtr cl) { - if (x>=0 && x=0 && y 1.0) mouse_x_abs = 1.0; + if (mouse_y_abs > 1.0) mouse_y_abs = 1.0; + if (mouse_x_abs < 0.0) mouse_x_abs = 0.0; + if (mouse_y_abs < 0.0) mouse_y_abs = 0.0; + + rfbDefaultPtrAddEvent(but, x, y, cl); } - static void -vnc_clientgone(rfbClientPtr cl) +vnc_clientgone(UNUSED(rfbClientPtr cl)) { vnc_log("VNC: client disconnected: %s\n", cl->host); if (clients > 0) - clients--; + clients--; if (clients == 0) { - /* No more clients, pause the emulator. */ - vnc_log("VNC: no clients, pausing..\n"); + /* No more clients, pause the emulator. */ + vnc_log("VNC: no clients, pausing..\n"); - /* Disable the mouse. */ - plat_mouse_capture(0); + /* Disable the mouse. */ +#if 0 + plat_mouse_capture(0); +#endif + mouse_set_poll_ex(NULL); - plat_pause(1); + plat_pause(1); } } - static enum rfbNewClientAction vnc_newclient(rfbClientPtr cl) { @@ -131,113 +139,109 @@ vnc_newclient(rfbClientPtr cl) vnc_log("VNC: new client: %s\n", cl->host); if (++clients == 1) { - /* Reset the mouse. */ - ptr_x = allowedX/2; - ptr_y = allowedY/2; - mouse_x = mouse_y = mouse_z = 0; - mouse_buttons = 0x00; + /* Reset the mouse. */ + ptr_x = allowedX / 2; + ptr_y = allowedY / 2; + mouse_clear_coords(); + mouse_clear_buttons(); - /* We now have clients, un-pause the emulator if needed. */ - vnc_log("VNC: unpausing..\n"); + /* We now have clients, un-pause the emulator if needed. */ + vnc_log("VNC: unpausing..\n"); - /* Enable the mouse. */ - plat_mouse_capture(1); + /* Enable the mouse. */ +#if 0 + plat_mouse_capture(1); +#endif + mouse_set_poll_ex(vnc_mouse_poll); - plat_pause(0); + plat_pause(0); } /* For now, we always accept clients. */ - return(RFB_CLIENT_ACCEPT); + return RFB_CLIENT_ACCEPT; } - static void vnc_display(rfbClientPtr cl) { /* Avoid race condition between resize and update. */ if (!updatingSize && cl->newFBSizePending) { - updatingSize = 1; + updatingSize = 1; } else if (updatingSize && !cl->newFBSizePending) { - updatingSize = 0; + updatingSize = 0; - allowedX = rfb->width; - allowedY = rfb->height; + allowedX = rfb->width; + allowedY = rfb->height; } } - static void -vnc_blit(int x, int y, int w, int h) +vnc_blit(int x, int y, int w, int h, int monitor_index) { - uint32_t *p; - int yy; - - if ((x < 0) || (y < 0) || (w <= 0) || (h <= 0) || (w > 2048) || (h > 2048) || (buffer32 == NULL)) - return; - - for (yy=0; yyframeBuffer)[yy*VNC_MAX_X]); - - if ((y+yy) >= 0 && (y+yy) < VNC_MAX_Y) - video_copy(p, &(buffer32->line[yy]), w*sizeof(uint32_t)); + if (monitor_index || (x < 0) || (y < 0) || (w < VNC_MIN_X) || (h < VNC_MIN_Y) || (w > VNC_MAX_X) || (h > VNC_MAX_Y) || (buffer32 == NULL)) { + video_blit_complete_monitor(monitor_index); + return; } + for (int row = 0; row < h; ++row) + video_copy(&(((uint8_t *) rfb->frameBuffer)[row * 2048 * sizeof(uint32_t)]), &(buffer32->line[y + row][x]), w * sizeof(uint32_t)); + if (screenshots) - video_screenshot((uint32_t *) rfb->frameBuffer, 0, 0, VNC_MAX_X); - - video_blit_complete(); + video_screenshot((uint32_t *) rfb->frameBuffer, 0, 0, VNC_MAX_X); - if (! updatingSize) - rfbMarkRectAsModified(rfb, 0,0, allowedX,allowedY); + video_blit_complete_monitor(monitor_index); + + if (!updatingSize) + rfbMarkRectAsModified(rfb, 0, 0, allowedX, allowedY); } - /* Initialize VNC for operation. */ int vnc_init(UNUSED(void *arg)) { - static char title[128]; + static char title[128]; rfbPixelFormat rpf = { - /* - * Screen format: - * 32bpp; 32 depth; - * little endian; - * true color; - * max 255 R/G/B; - * red shift 16; green shift 8; blue shift 0; - * padding - */ - 32, 32, 0, 1, 255,255,255, 16, 8, 0, 0, 0 + /* + * Screen format: + * 32bpp; 32 depth; + * little endian; + * true color; + * max 255 R/G/B; + * red shift 16; green shift 8; blue shift 0; + * padding + */ + 32, 32, 0, 1, 255, 255, 255, 16, 8, 0, 0, 0 }; - cgapal_rebuild(); + plat_pause(1); + cgapal_rebuild_monitor(0); if (rfb == NULL) { - wcstombs(title, ui_window_title(NULL), sizeof(title)); - updatingSize = 0; - allowedX = scrnsz_x; - allowedY = scrnsz_y; - - rfb = rfbGetScreen(0, NULL, VNC_MAX_X, VNC_MAX_Y, 8, 3, 4); - rfb->desktopName = title; - rfb->frameBuffer = (char *)malloc(VNC_MAX_X*VNC_MAX_Y*4); + wcstombs(title, ui_window_title(NULL), sizeof(title)); + updatingSize = 0; + allowedX = scrnsz_x; + allowedY = scrnsz_y; - rfb->serverFormat = rpf; - rfb->alwaysShared = TRUE; - rfb->displayHook = vnc_display; - rfb->ptrAddEvent = vnc_ptrevent; - rfb->kbdAddEvent = vnc_kbdevent; - rfb->newClientHook = vnc_newclient; - - /* Set up our current resolution. */ - rfb->width = allowedX; - rfb->height = allowedY; - - rfbInitServer(rfb); + rfb = rfbGetScreen(0, NULL, VNC_MAX_X, VNC_MAX_Y, 8, 3, 4); + rfb->desktopName = title; + rfb->frameBuffer = (char *) malloc(VNC_MAX_X * VNC_MAX_Y * 4); - rfbRunEventLoop(rfb, -1, TRUE); + rfb->serverFormat = rpf; + rfb->alwaysShared = TRUE; + rfb->displayHook = vnc_display; + rfb->ptrAddEvent = vnc_ptrevent; + rfb->kbdAddEvent = vnc_kbdevent; + rfb->newClientHook = vnc_newclient; + + /* Set up our current resolution. */ + rfb->width = allowedX; + rfb->height = allowedY; + + rfbInitServer(rfb); + + rfbRunEventLoop(rfb, -1, TRUE); } - + /* Set up our BLIT handlers. */ video_setblit(vnc_blit); @@ -245,68 +249,65 @@ vnc_init(UNUSED(void *arg)) vnc_log("VNC: init complete.\n"); - return(1); + return 1; } - void vnc_close(void) { video_setblit(NULL); if (rfb != NULL) { - free(rfb->frameBuffer); + free(rfb->frameBuffer); - rfbScreenCleanup(rfb); + rfbScreenCleanup(rfb); - rfb = NULL; + rfb = NULL; } } - void vnc_resize(int x, int y) { rfbClientIteratorPtr iterator; - rfbClientPtr cl; + rfbClientPtr cl; - if (rfb == NULL) return; + if (rfb == NULL) + return; /* TightVNC doesn't like certain sizes.. */ - if (x < VNC_MIN_X || x > VNC_MAX_X || y < VNC_MIN_Y || y > VNC_MAX_Y) { - vnc_log("VNC: invalid resoltion %dx%d requested!\n", x, y); - return; + if ((x < VNC_MIN_X) || (x > VNC_MAX_X) || (y < VNC_MIN_Y) || (y > VNC_MAX_Y)) { + vnc_log("VNC: invalid resoltion %dx%d requested!\n", x, y); + return; } if ((x != rfb->width || y != rfb->height) && x > 160 && y > 0) { - vnc_log("VNC: updating resolution: %dx%d\n", x, y); - - allowedX = (rfb->width < x) ? rfb->width : x; - allowedY = (rfb->width < y) ? rfb->width : y; - - rfb->width = x; - rfb->height = y; - - iterator = rfbGetClientIterator(rfb); - while ((cl = rfbClientIteratorNext(iterator)) != NULL) { - LOCK(cl->updateMutex); - cl->newFBSizePending = 1; - UNLOCK(cl->updateMutex); - } + vnc_log("VNC: updating resolution: %dx%d\n", x, y); + + allowedX = (rfb->width < x) ? rfb->width : x; + allowedY = (rfb->width < y) ? rfb->width : y; + + rfb->width = x; + rfb->height = y; + + iterator = rfbGetClientIterator(rfb); + while ((cl = rfbClientIteratorNext(iterator)) != NULL) { + LOCK(cl->updateMutex); + cl->newFBSizePending = 1; + UNLOCK(cl->updateMutex); + } } } - /* Tell them to pause if we have no clients. */ int vnc_pause(void) { - return((clients > 0) ? 0 : 1); + return ((clients > 0) ? 0 : 1); } - void -vnc_take_screenshot(wchar_t *fn) +vnc_take_screenshot(UNUSED(wchar_t *fn)) { vnc_log("VNC: take_screenshot\n"); } diff --git a/src/vnc_keymap.c b/src/vnc_keymap.c index fd9769de9..599ba1d9b 100644 --- a/src/vnc_keymap.c +++ b/src/vnc_keymap.c @@ -1,33 +1,33 @@ /* - * 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. + * 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. + * This file is part of the 86Box distribution. * - * Define the XKBD to ScanCode translation tables for VNC. + * Define the XKBD to ScanCode translation tables for VNC. * - * VNC uses the XKBD key code definitions to transport keystroke - * information, so we just need some tables to translate those - * into PC-ready scan codes. + * VNC uses the XKBD key code definitions to transport keystroke + * information, so we just need some tables to translate those + * into PC-ready scan codes. * - * We only support XKBD pages 0 (Latin-1) and 255 (special keys) - * in these tables, other pages (languages) not [yet] supported. + * We only support XKBD pages 0 (Latin-1) and 255 (special keys) + * in these tables, other pages (languages) not [yet] supported. * - * The tables define up to two keystrokes.. the upper byte is - * the first keystroke, and the lower byte the second. If value - * is 0x00, the keystroke is not sent. + * The tables define up to two keystrokes.. the upper byte is + * the first keystroke, and the lower byte the second. If value + * is 0x00, the keystroke is not sent. * - * NOTE: The values are as defined in the Microsoft document named - * "Keyboard Scan Code Specification", version 1.3a of 2000/03/16. + * NOTE: The values are as defined in the Microsoft document named + * "Keyboard Scan Code Specification", version 1.3a of 2000/03/16. * * * - * Authors: Fred N. van Kempen, - * Based on raw code by RichardG, + * Authors: Fred N. van Kempen, + * Based on raw code by RichardG, * - * Copyright 2017-2019 Fred N. van Kempen. + * Copyright 2017-2019 Fred N. van Kempen. */ #include #include @@ -41,9 +41,8 @@ #include <86box/plat.h> #include <86box/vnc.h> - static int keysyms_00[] = { - 0x0000, /* 0x00 */ + 0x0000, /* 0x00 */ 0x0000, 0x0000, 0x0000, @@ -52,7 +51,7 @@ static int keysyms_00[] = { 0x0000, 0x0000, - 0x0000, /* 0x08 */ + 0x0000, /* 0x08 */ 0x0000, 0x0000, 0x0000, @@ -61,7 +60,7 @@ static int keysyms_00[] = { 0x0000, 0x0000, - 0x0000, /* 0x10 */ + 0x0000, /* 0x10 */ 0x0000, 0x0000, 0x0000, @@ -70,7 +69,7 @@ static int keysyms_00[] = { 0x0000, 0x0000, - 0x0000, /* 0x18 */ + 0x0000, /* 0x18 */ 0x0000, 0x0000, 0x0000, @@ -79,115 +78,115 @@ static int keysyms_00[] = { 0x0000, 0x0000, - 0x0039, /* 0x20 (XK_space) */ - 0x2a02, /* 0x21 (XK_exclam) */ - 0x2a28, /* 0x22 (XK_quotedbl) */ - 0x2a04, /* 0x23 (XK_numbersign) */ - 0x2a05, /* 0x24 (XK_dollar) */ - 0x2a06, /* 0x25 (XK_percent) */ - 0x2a08, /* 0x26 (XK_ampersand) */ - 0x0028, /* 0x27 (XK_apostrophe) */ + 0x0039, /* 0x20 (XK_space) */ + 0x2a02, /* 0x21 (XK_exclam) */ + 0x2a28, /* 0x22 (XK_quotedbl) */ + 0x2a04, /* 0x23 (XK_numbersign) */ + 0x2a05, /* 0x24 (XK_dollar) */ + 0x2a06, /* 0x25 (XK_percent) */ + 0x2a08, /* 0x26 (XK_ampersand) */ + 0x0028, /* 0x27 (XK_apostrophe) */ - 0x2a0a, /* 0x28 (XK_parenleft) */ - 0x2a0b, /* 0x29 (XK_parenright) */ - 0x2a09, /* 0x2a (XK_asterisk) */ - 0x2a0d, /* 0x2b (XK_plus) */ - 0x0033, /* 0x2c (XK_comma) */ - 0x000c, /* 0x2d (XK_minus) */ - 0x0034, /* 0x2e (XK_period) */ - 0x0035, /* 0x2f (XK_slash) */ + 0x2a0a, /* 0x28 (XK_parenleft) */ + 0x2a0b, /* 0x29 (XK_parenright) */ + 0x2a09, /* 0x2a (XK_asterisk) */ + 0x2a0d, /* 0x2b (XK_plus) */ + 0x0033, /* 0x2c (XK_comma) */ + 0x000c, /* 0x2d (XK_minus) */ + 0x0034, /* 0x2e (XK_period) */ + 0x0035, /* 0x2f (XK_slash) */ - 0x000b, /* 0x30 (XK_0) */ - 0x0002, /* 0x31 (XK_1) */ - 0x0003, /* 0x32 (XK_2) */ - 0x0004, /* 0x33 (XK_3) */ - 0x0005, /* 0x34 (XK_4) */ - 0x0006, /* 0x35 (XK_5) */ - 0x0007, /* 0x36 (XK_6) */ - 0x0008, /* 0x37 (XK_7) */ + 0x000b, /* 0x30 (XK_0) */ + 0x0002, /* 0x31 (XK_1) */ + 0x0003, /* 0x32 (XK_2) */ + 0x0004, /* 0x33 (XK_3) */ + 0x0005, /* 0x34 (XK_4) */ + 0x0006, /* 0x35 (XK_5) */ + 0x0007, /* 0x36 (XK_6) */ + 0x0008, /* 0x37 (XK_7) */ - 0x0009, /* 0x38 (XK_8) */ - 0x000a, /* 0x39 (XK_9) */ - 0x2a27, /* 0x3a (XK_colon) */ - 0x0027, /* 0x3b (XK_semicolon) */ - 0x2a33, /* 0x3c (XK_less) */ - 0x000d, /* 0x3d (XK_equal) */ - 0x2a34, /* 0x3e (XK_greater) */ - 0x2a35, /* 0x3f (XK_question) */ + 0x0009, /* 0x38 (XK_8) */ + 0x000a, /* 0x39 (XK_9) */ + 0x2a27, /* 0x3a (XK_colon) */ + 0x0027, /* 0x3b (XK_semicolon) */ + 0x2a33, /* 0x3c (XK_less) */ + 0x000d, /* 0x3d (XK_equal) */ + 0x2a34, /* 0x3e (XK_greater) */ + 0x2a35, /* 0x3f (XK_question) */ - 0x2a03, /* 0x40 (XK_at) */ - 0x2a1e, /* 0x41 (XK_A) */ - 0x2a30, /* 0x42 (XK_B) */ - 0x2a2e, /* 0x43 (XK_C) */ - 0x2a20, /* 0x44 (XK_D) */ - 0x2a12, /* 0x45 (XK_E) */ - 0x2a21, /* 0x46 (XK_F) */ - 0x2a22, /* 0x47 (XK_G) */ + 0x2a03, /* 0x40 (XK_at) */ + 0x2a1e, /* 0x41 (XK_A) */ + 0x2a30, /* 0x42 (XK_B) */ + 0x2a2e, /* 0x43 (XK_C) */ + 0x2a20, /* 0x44 (XK_D) */ + 0x2a12, /* 0x45 (XK_E) */ + 0x2a21, /* 0x46 (XK_F) */ + 0x2a22, /* 0x47 (XK_G) */ - 0x2a23, /* 0x48 (XK_H) */ - 0x2a17, /* 0x49 (XK_I) */ - 0x2a24, /* 0x4a (XK_J) */ - 0x2a25, /* 0x4b (XK_K) */ - 0x2a26, /* 0x4c (XK_L) */ - 0x2a32, /* 0x4d (XK_M) */ - 0x2a31, /* 0x4e (XK_N) */ - 0x2a18, /* 0x4f (XK_O) */ + 0x2a23, /* 0x48 (XK_H) */ + 0x2a17, /* 0x49 (XK_I) */ + 0x2a24, /* 0x4a (XK_J) */ + 0x2a25, /* 0x4b (XK_K) */ + 0x2a26, /* 0x4c (XK_L) */ + 0x2a32, /* 0x4d (XK_M) */ + 0x2a31, /* 0x4e (XK_N) */ + 0x2a18, /* 0x4f (XK_O) */ - 0x2a19, /* 0x50 (XK_P) */ - 0x2a10, /* 0x51 (XK_Q) */ - 0x2a13, /* 0x52 (XK_R) */ - 0x2a1f, /* 0x53 (XK_S) */ - 0x2a14, /* 0x54 (XK_T) */ - 0x2a16, /* 0x55 (XK_U) */ - 0x2a2f, /* 0x56 (XK_V) */ - 0x2a11, /* 0x57 (XK_W) */ + 0x2a19, /* 0x50 (XK_P) */ + 0x2a10, /* 0x51 (XK_Q) */ + 0x2a13, /* 0x52 (XK_R) */ + 0x2a1f, /* 0x53 (XK_S) */ + 0x2a14, /* 0x54 (XK_T) */ + 0x2a16, /* 0x55 (XK_U) */ + 0x2a2f, /* 0x56 (XK_V) */ + 0x2a11, /* 0x57 (XK_W) */ - 0x2a2d, /* 0x58 (XK_X) */ - 0x2a15, /* 0x59 (XK_Y) */ - 0x2a2c, /* 0x5a (XK_Z) */ - 0x001a, /* 0x5b (XK_bracketleft) */ - 0x002b, /* 0x5c (XK_backslash) */ - 0x001b, /* 0x5d (XK_bracketright) */ - 0x2a07, /* 0x5e (XK_asciicircum) */ - 0x2a0c, /* 0x5f (XK_underscore) */ + 0x2a2d, /* 0x58 (XK_X) */ + 0x2a15, /* 0x59 (XK_Y) */ + 0x2a2c, /* 0x5a (XK_Z) */ + 0x001a, /* 0x5b (XK_bracketleft) */ + 0x002b, /* 0x5c (XK_backslash) */ + 0x001b, /* 0x5d (XK_bracketright) */ + 0x2a07, /* 0x5e (XK_asciicircum) */ + 0x2a0c, /* 0x5f (XK_underscore) */ - 0x0029, /* 0x60 (XK_grave) */ - 0x001e, /* 0x61 (XK_a) */ - 0x0030, /* 0x62 (XK_b) */ - 0x002e, /* 0x63 (XK_c) */ - 0x0020, /* 0x64 (XK_d) */ - 0x0012, /* 0x65 (XK_e) */ - 0x0021, /* 0x66 (XK_f) */ - 0x0022, /* 0x67 (XK_g) */ + 0x0029, /* 0x60 (XK_grave) */ + 0x001e, /* 0x61 (XK_a) */ + 0x0030, /* 0x62 (XK_b) */ + 0x002e, /* 0x63 (XK_c) */ + 0x0020, /* 0x64 (XK_d) */ + 0x0012, /* 0x65 (XK_e) */ + 0x0021, /* 0x66 (XK_f) */ + 0x0022, /* 0x67 (XK_g) */ - 0x0023, /* 0x68 (XK_h) */ - 0x0017, /* 0x69 (XK_i) */ - 0x0024, /* 0x6a (XK_j) */ - 0x0025, /* 0x6b (XK_k) */ - 0x0026, /* 0x6c (XK_l) */ - 0x0032, /* 0x6d (XK_m) */ - 0x0031, /* 0x6e (XK_n) */ - 0x0018, /* 0x6f (XK_o) */ + 0x0023, /* 0x68 (XK_h) */ + 0x0017, /* 0x69 (XK_i) */ + 0x0024, /* 0x6a (XK_j) */ + 0x0025, /* 0x6b (XK_k) */ + 0x0026, /* 0x6c (XK_l) */ + 0x0032, /* 0x6d (XK_m) */ + 0x0031, /* 0x6e (XK_n) */ + 0x0018, /* 0x6f (XK_o) */ - 0x0019, /* 0x70 (XK_p) */ - 0x0010, /* 0x71 (XK_q) */ - 0x0013, /* 0x72 (XK_r) */ - 0x001f, /* 0x73 (XK_s) */ - 0x0014, /* 0x74 (XK_t) */ - 0x0016, /* 0x75 (XK_u) */ - 0x002f, /* 0x76 (XK_v) */ - 0x0011, /* 0x77 (XK_w) */ + 0x0019, /* 0x70 (XK_p) */ + 0x0010, /* 0x71 (XK_q) */ + 0x0013, /* 0x72 (XK_r) */ + 0x001f, /* 0x73 (XK_s) */ + 0x0014, /* 0x74 (XK_t) */ + 0x0016, /* 0x75 (XK_u) */ + 0x002f, /* 0x76 (XK_v) */ + 0x0011, /* 0x77 (XK_w) */ - 0x002d, /* 0x78 (XK_x) */ - 0x0015, /* 0x79 (XK_y) */ - 0x002c, /* 0x7a (XK_z) */ - 0x2a1a, /* 0x7b (XK_braceleft) */ - 0x2a2b, /* 0x7c (XK_bar) */ - 0x2a1b, /* 0x7d (XK_braceright) */ - 0x2a29, /* 0x7e (XK_asciitilde) */ - 0x0053, /* 0x7f (XK_delete) */ + 0x002d, /* 0x78 (XK_x) */ + 0x0015, /* 0x79 (XK_y) */ + 0x002c, /* 0x7a (XK_z) */ + 0x2a1a, /* 0x7b (XK_braceleft) */ + 0x2a2b, /* 0x7c (XK_bar) */ + 0x2a1b, /* 0x7d (XK_braceright) */ + 0x2a29, /* 0x7e (XK_asciitilde) */ + 0x0053, /* 0x7f (XK_delete) */ - 0x0000, /* 0x80 */ + 0x0000, /* 0x80 */ 0x0000, 0x0000, 0x0000, @@ -196,7 +195,7 @@ static int keysyms_00[] = { 0x0000, 0x0000, - 0x0000, /* 0x88 */ + 0x0000, /* 0x88 */ 0x0000, 0x0000, 0x0000, @@ -205,7 +204,7 @@ static int keysyms_00[] = { 0x0000, 0x0000, - 0x0000, /* 0x90 */ + 0x0000, /* 0x90 */ 0x0000, 0x0000, 0x0000, @@ -214,7 +213,7 @@ static int keysyms_00[] = { 0x0000, 0x0000, - 0x0000, /* 0x98 */ + 0x0000, /* 0x98 */ 0x0000, 0x0000, 0x0000, @@ -223,117 +222,117 @@ static int keysyms_00[] = { 0x0000, 0x0000, - 0x0000, /* 0xa0 (XK_nobreakspace) */ - 0x0000, /* 0xa1 (XK_exclamdown) */ - 0x0000, /* 0xa2 (XK_cent) */ - 0x0000, /* 0xa3 (XK_sterling) */ - 0x0000, /* 0xa4 (XK_currency) */ - 0x0000, /* 0xa5 (XK_yen) */ - 0x0000, /* 0xa6 (XK_brokenbar) */ - 0x0000, /* 0xa7 (XK_section) */ + 0x0000, /* 0xa0 (XK_nobreakspace) */ + 0x0000, /* 0xa1 (XK_exclamdown) */ + 0x0000, /* 0xa2 (XK_cent) */ + 0x0000, /* 0xa3 (XK_sterling) */ + 0x0000, /* 0xa4 (XK_currency) */ + 0x0000, /* 0xa5 (XK_yen) */ + 0x0000, /* 0xa6 (XK_brokenbar) */ + 0x0000, /* 0xa7 (XK_section) */ - 0x0000, /* 0xa8 (XK_diaeresis) */ - 0x0000, /* 0xa9 (XK_copyright) */ - 0x0000, /* 0xaa (XK_ordfeminine) */ - 0x0000, /* 0xab (XK_guillemotleft) */ - 0x0000, /* 0xac (XK_notsign) */ - 0x0000, /* 0xad (XK_hyphen) */ - 0x0000, /* 0xae (XK_registered) */ - 0x0000, /* 0xaf (XK_macron) */ + 0x0000, /* 0xa8 (XK_diaeresis) */ + 0x0000, /* 0xa9 (XK_copyright) */ + 0x0000, /* 0xaa (XK_ordfeminine) */ + 0x0000, /* 0xab (XK_guillemotleft) */ + 0x0000, /* 0xac (XK_notsign) */ + 0x0000, /* 0xad (XK_hyphen) */ + 0x0000, /* 0xae (XK_registered) */ + 0x0000, /* 0xaf (XK_macron) */ - 0x0000, /* 0xb0 (XK_degree) */ - 0x0000, /* 0xb1 (XK_plusminus) */ - 0x0000, /* 0xb2 (XK_twosuperior) */ - 0x0000, /* 0xb3 (XK_threesuperior) */ - 0x0000, /* 0xb4 (XK_acute) */ - 0x0000, /* 0xb5 (XK_mu) */ - 0x0000, /* 0xb6 (XK_paragraph) */ - 0x0000, /* 0xb7 (XK_periodcentered) */ + 0x0000, /* 0xb0 (XK_degree) */ + 0x0000, /* 0xb1 (XK_plusminus) */ + 0x0000, /* 0xb2 (XK_twosuperior) */ + 0x0000, /* 0xb3 (XK_threesuperior) */ + 0x0000, /* 0xb4 (XK_acute) */ + 0x0000, /* 0xb5 (XK_mu) */ + 0x0000, /* 0xb6 (XK_paragraph) */ + 0x0000, /* 0xb7 (XK_periodcentered) */ - 0x0000, /* 0xb8 (XK_cedilla) */ - 0x0000, /* 0xb9 (XK_onesuperior) */ - 0x0000, /* 0xba (XK_masculine) */ - 0x0000, /* 0xbb (XK_guillemotright) */ - 0x0000, /* 0xbc (XK_onequarter) */ - 0x0000, /* 0xbd (XK_onehalf) */ - 0x0000, /* 0xbe (XK_threequarters) */ - 0x0000, /* 0xbf (XK_questiondown) */ + 0x0000, /* 0xb8 (XK_cedilla) */ + 0x0000, /* 0xb9 (XK_onesuperior) */ + 0x0000, /* 0xba (XK_masculine) */ + 0x0000, /* 0xbb (XK_guillemotright) */ + 0x0000, /* 0xbc (XK_onequarter) */ + 0x0000, /* 0xbd (XK_onehalf) */ + 0x0000, /* 0xbe (XK_threequarters) */ + 0x0000, /* 0xbf (XK_questiondown) */ - 0x0000, /* 0xc0 (XK_Agrave) */ - 0x0000, /* 0xc1 (XK_Aacute) */ - 0x0000, /* 0xc2 (XK_Acircumflex) */ - 0x0000, /* 0xc3 (XK_Atilde) */ - 0x0000, /* 0xc4 (XK_Adiaeresis) */ - 0x0000, /* 0xc5 (XK_Aring) */ - 0x0000, /* 0xc6 (XK_AE) */ - 0x0000, /* 0xc7 (XK_Ccedilla) */ + 0x0000, /* 0xc0 (XK_Agrave) */ + 0x0000, /* 0xc1 (XK_Aacute) */ + 0x0000, /* 0xc2 (XK_Acircumflex) */ + 0x0000, /* 0xc3 (XK_Atilde) */ + 0x0000, /* 0xc4 (XK_Adiaeresis) */ + 0x0000, /* 0xc5 (XK_Aring) */ + 0x0000, /* 0xc6 (XK_AE) */ + 0x0000, /* 0xc7 (XK_Ccedilla) */ - 0x0000, /* 0xc8 (XK_Egrave) */ - 0x0000, /* 0xc9 (XK_Eacute) */ - 0x0000, /* 0xca (XK_Ecircumflex) */ - 0x0000, /* 0xcb (XK_Ediaeresis) */ - 0x0000, /* 0xcc (XK_Igrave) */ - 0x0000, /* 0xcd (XK_Iacute) */ - 0x0000, /* 0xce (XK_Icircumflex) */ - 0x0000, /* 0xcf (XK_Idiaeresis) */ + 0x0000, /* 0xc8 (XK_Egrave) */ + 0x0000, /* 0xc9 (XK_Eacute) */ + 0x0000, /* 0xca (XK_Ecircumflex) */ + 0x0000, /* 0xcb (XK_Ediaeresis) */ + 0x0000, /* 0xcc (XK_Igrave) */ + 0x0000, /* 0xcd (XK_Iacute) */ + 0x0000, /* 0xce (XK_Icircumflex) */ + 0x0000, /* 0xcf (XK_Idiaeresis) */ - 0x0000, /* 0xd0 (XK_ETH, also XK_Eth) */ - 0x0000, /* 0xd1 (XK_Ntilde) */ - 0x0000, /* 0xd2 (XK_Ograve) */ - 0x0000, /* 0xd3 (XK_Oacute) */ - 0x0000, /* 0xd4 (XK_Ocircumflex) */ - 0x0000, /* 0xd5 (XK_Otilde) */ - 0x0000, /* 0xd6 (XK_Odiaeresis) */ - 0x0000, /* 0xd7 (XK_multiply) */ + 0x0000, /* 0xd0 (XK_ETH, also XK_Eth) */ + 0x0000, /* 0xd1 (XK_Ntilde) */ + 0x0000, /* 0xd2 (XK_Ograve) */ + 0x0000, /* 0xd3 (XK_Oacute) */ + 0x0000, /* 0xd4 (XK_Ocircumflex) */ + 0x0000, /* 0xd5 (XK_Otilde) */ + 0x0000, /* 0xd6 (XK_Odiaeresis) */ + 0x0000, /* 0xd7 (XK_multiply) */ - 0x0000, /* 0xd8 (XK_Ooblique) */ - 0x0000, /* 0xd9 (XK_Ugrave) */ - 0x0000, /* 0xda (XK_Uacute) */ - 0x0000, /* 0xdb (XK_Ucircumflex) */ - 0x0000, /* 0xdc (XK_Udiaeresis) */ - 0x0000, /* 0xdd (XK_Yacute) */ - 0x0000, /* 0xde (XK_THORN) */ - 0x0000, /* 0xdf (XK_ssharp) */ + 0x0000, /* 0xd8 (XK_Ooblique) */ + 0x0000, /* 0xd9 (XK_Ugrave) */ + 0x0000, /* 0xda (XK_Uacute) */ + 0x0000, /* 0xdb (XK_Ucircumflex) */ + 0x0000, /* 0xdc (XK_Udiaeresis) */ + 0x0000, /* 0xdd (XK_Yacute) */ + 0x0000, /* 0xde (XK_THORN) */ + 0x0000, /* 0xdf (XK_ssharp) */ - 0x0000, /* 0xe0 (XK_agrave) */ - 0x0000, /* 0xe1 (XK_aacute) */ - 0x0000, /* 0xe2 (XK_acircumflex) */ - 0x0000, /* 0xe3 (XK_atilde) */ - 0x0000, /* 0xe4 (XK_adiaeresis) */ - 0x0000, /* 0xe5 (XK_aring) */ - 0x0000, /* 0xe6 (XK_ae) */ - 0x0000, /* 0xe7 (XK_ccedilla) */ + 0x0000, /* 0xe0 (XK_agrave) */ + 0x0000, /* 0xe1 (XK_aacute) */ + 0x0000, /* 0xe2 (XK_acircumflex) */ + 0x0000, /* 0xe3 (XK_atilde) */ + 0x0000, /* 0xe4 (XK_adiaeresis) */ + 0x0000, /* 0xe5 (XK_aring) */ + 0x0000, /* 0xe6 (XK_ae) */ + 0x0000, /* 0xe7 (XK_ccedilla) */ - 0x0000, /* 0xe8 (XK_egrave) */ - 0x0000, /* 0xe9 (XK_eacute) */ - 0x0000, /* 0xea (XK_ecircumflex) */ - 0x0000, /* 0xeb (XK_ediaeresis) */ - 0x0000, /* 0xec (XK_igrave) */ - 0x0000, /* 0xed (XK_iacute) */ - 0x0000, /* 0xee (XK_icircumflex) */ - 0x0000, /* 0xef (XK_idiaeresis) */ + 0x0000, /* 0xe8 (XK_egrave) */ + 0x0000, /* 0xe9 (XK_eacute) */ + 0x0000, /* 0xea (XK_ecircumflex) */ + 0x0000, /* 0xeb (XK_ediaeresis) */ + 0x0000, /* 0xec (XK_igrave) */ + 0x0000, /* 0xed (XK_iacute) */ + 0x0000, /* 0xee (XK_icircumflex) */ + 0x0000, /* 0xef (XK_idiaeresis) */ - 0x0000, /* 0xf0 (XK_eth) */ - 0x0000, /* 0xf1 (XK_ntilde) */ - 0x0000, /* 0xf2 (XK_ograve) */ - 0x0000, /* 0xf3 (XK_oacute) */ - 0x0000, /* 0xf4 (XK_ocircumflex) */ - 0x0000, /* 0xf5 (XK_otilde) */ - 0x0000, /* 0xf6 (XK_odiaeresis) */ - 0x0000, /* 0xf7 (XK_division) */ + 0x0000, /* 0xf0 (XK_eth) */ + 0x0000, /* 0xf1 (XK_ntilde) */ + 0x0000, /* 0xf2 (XK_ograve) */ + 0x0000, /* 0xf3 (XK_oacute) */ + 0x0000, /* 0xf4 (XK_ocircumflex) */ + 0x0000, /* 0xf5 (XK_otilde) */ + 0x0000, /* 0xf6 (XK_odiaeresis) */ + 0x0000, /* 0xf7 (XK_division) */ - 0x0000, /* 0xf8 (XK_oslash) */ - 0x0000, /* 0xf9 (XK_ugrave) */ - 0x0000, /* 0xfa (XK_uacute) */ - 0x0000, /* 0xfb (XK_ucircumflex) */ - 0x0000, /* 0xfc (XK_udiaeresis) */ - 0x0000, /* 0xfd (XK_yacute) */ - 0x0000, /* 0xfe (XK_thorn) */ - 0x0000 /* 0xff (XK_ydiaeresis) */ + 0x0000, /* 0xf8 (XK_oslash) */ + 0x0000, /* 0xf9 (XK_ugrave) */ + 0x0000, /* 0xfa (XK_uacute) */ + 0x0000, /* 0xfb (XK_ucircumflex) */ + 0x0000, /* 0xfc (XK_udiaeresis) */ + 0x0000, /* 0xfd (XK_yacute) */ + 0x0000, /* 0xfe (XK_thorn) */ + 0x0000 /* 0xff (XK_ydiaeresis) */ }; static int keysyms_ff[] = { - 0x0000, /* 0x00 */ + 0x0000, /* 0x00 */ 0x0000, 0x0000, 0x0000, @@ -342,52 +341,52 @@ static int keysyms_ff[] = { 0x0000, 0x0000, - 0x000e, /* 0x08 (XK_BackSpace) */ - 0x000f, /* 0x09 (XK_Tab) */ - 0x0000, /* 0x0a (XK_Linefeed) */ - 0x004c, /* 0x0b (XK_Clear) */ + 0x000e, /* 0x08 (XK_BackSpace) */ + 0x000f, /* 0x09 (XK_Tab) */ + 0x0000, /* 0x0a (XK_Linefeed) */ + 0x004c, /* 0x0b (XK_Clear) */ 0x0000, - 0x001c, /* 0x0d (XK_Return) */ + 0x001c, /* 0x0d (XK_Return) */ 0x0000, 0x0000, - 0x0000, /* 0x10 */ + 0x0000, /* 0x10 */ 0x0000, 0x0000, - 0xff45, /* 0x13 (XK_Pause) */ - 0x0000, /* 0x14 (XK_Scroll_Lock) */ - 0x0000, /* 0x15 (XK_Sys_Req) */ + 0xff45, /* 0x13 (XK_Pause) */ + 0x0000, /* 0x14 (XK_Scroll_Lock) */ + 0x0000, /* 0x15 (XK_Sys_Req) */ 0x0000, 0x0000, - 0x0000, /* 0x18 */ + 0x0000, /* 0x18 */ 0x0000, 0x0000, - 0x0001, /* 0x1b (XK_Escape) */ + 0x0001, /* 0x1b (XK_Escape) */ 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, /* 0x20 (XK_Multi_key) */ - 0x0000, /* 0x21 (XK_Kanji; Kanji, Kanji convert) */ - 0x0000, /* 0x22 (XK_Muhenkan; Cancel Conversion) */ - 0x0000, /* 0x23 (XK_Henkan_Mode; Start/Stop Conversion) */ - 0x0000, /* 0x24 (XK_Romaji; to Romaji) */ - 0x0000, /* 0x25 (XK_Hiragana; to Hiragana) */ - 0x0000, /* 0x26 (XK_Katakana; to Katakana) */ - 0x0000, /* 0x27 (XK_Hiragana_Katakana; Hiragana/Katakana toggle) */ + 0x0000, /* 0x20 (XK_Multi_key) */ + 0x0000, /* 0x21 (XK_Kanji; Kanji, Kanji convert) */ + 0x0000, /* 0x22 (XK_Muhenkan; Cancel Conversion) */ + 0x0000, /* 0x23 (XK_Henkan_Mode; Start/Stop Conversion) */ + 0x0000, /* 0x24 (XK_Romaji; to Romaji) */ + 0x0000, /* 0x25 (XK_Hiragana; to Hiragana) */ + 0x0000, /* 0x26 (XK_Katakana; to Katakana) */ + 0x0000, /* 0x27 (XK_Hiragana_Katakana; Hiragana/Katakana toggle) */ - 0x0000, /* 0x28 (XK_Zenkaku; to Zenkaku) */ - 0x0000, /* 0x29 (XK_Hankaku; to Hankaku */ - 0x0000, /* 0x2a (XK_Zenkaku_Hankaku; Zenkaku/Hankaku toggle) */ - 0x0000, /* 0x2b (XK_Touroku; Add to Dictionary) */ - 0x0000, /* 0x2c (XK_Massyo; Delete from Dictionary) */ - 0x0000, /* 0x2d (XK_Kana_Lock; Kana Lock) */ - 0x0000, /* 0x2e (XK_Kana_Shift; Kana Shift) */ - 0x0000, /* 0x2f (XK_Eisu_Shift; Alphanumeric Shift) */ + 0x0000, /* 0x28 (XK_Zenkaku; to Zenkaku) */ + 0x0000, /* 0x29 (XK_Hankaku; to Hankaku */ + 0x0000, /* 0x2a (XK_Zenkaku_Hankaku; Zenkaku/Hankaku toggle) */ + 0x0000, /* 0x2b (XK_Touroku; Add to Dictionary) */ + 0x0000, /* 0x2c (XK_Massyo; Delete from Dictionary) */ + 0x0000, /* 0x2d (XK_Kana_Lock; Kana Lock) */ + 0x0000, /* 0x2e (XK_Kana_Shift; Kana Shift) */ + 0x0000, /* 0x2f (XK_Eisu_Shift; Alphanumeric Shift) */ - 0x0000, /* 0x30 (XK_Eisu_toggle; Alphanumeric toggle) */ + 0x0000, /* 0x30 (XK_Eisu_toggle; Alphanumeric toggle) */ 0x0000, 0x0000, 0x0000, @@ -396,16 +395,16 @@ static int keysyms_ff[] = { 0x0000, 0x0000, - 0x0000, /* 0x38 */ + 0x0000, /* 0x38 */ 0x0000, 0x0000, 0x0000, - 0x0000, /* 0x3c (XK_SingleCandidate) */ - 0x0000, /* 0x3d (XK_MultipleCandidate/XK_Zen_Koho) */ - 0x0000, /* 0x3e (XK_PreviousCandidate/XK_Mae_Koho) */ + 0x0000, /* 0x3c (XK_SingleCandidate) */ + 0x0000, /* 0x3d (XK_MultipleCandidate/XK_Zen_Koho) */ + 0x0000, /* 0x3e (XK_PreviousCandidate/XK_Mae_Koho) */ 0x0000, - 0x0000, /* 0x40 */ + 0x0000, /* 0x40 */ 0x0000, 0x0000, 0x0000, @@ -414,7 +413,7 @@ static int keysyms_ff[] = { 0x0000, 0x0000, - 0x0000, /* 0x48 */ + 0x0000, /* 0x48 */ 0x0000, 0x0000, 0x0000, @@ -423,16 +422,16 @@ static int keysyms_ff[] = { 0x0000, 0x0000, - 0xe047, /* 0x50 (XK_Home) */ - 0xe04b, /* 0x51 (XK_Left) */ - 0xe048, /* 0x52 (XK_Up) */ - 0xe04d, /* 0x53 (XK_Right) */ - 0xe050, /* 0x54 (XK_Down) */ - 0xe049, /* 0x55 (XK_Prior, XK_Page_Up) */ - 0xe051, /* 0x56 (XK_Next, XK_Page_Down) */ - 0xe04f, /* 0x57 (XK_End) */ + 0xe047, /* 0x50 (XK_Home) */ + 0xe04b, /* 0x51 (XK_Left) */ + 0xe048, /* 0x52 (XK_Up) */ + 0xe04d, /* 0x53 (XK_Right) */ + 0xe050, /* 0x54 (XK_Down) */ + 0xe049, /* 0x55 (XK_Prior, XK_Page_Up) */ + 0xe051, /* 0x56 (XK_Next, XK_Page_Down) */ + 0xe04f, /* 0x57 (XK_End) */ - 0x0000, /* 0x58 (XK_Begin) */ + 0x0000, /* 0x58 (XK_Begin) */ 0x0000, 0x0000, 0x0000, @@ -441,25 +440,25 @@ static int keysyms_ff[] = { 0x0000, 0x0000, - 0x0000, /* 0x60 (XK_Select) */ - 0x0000, /* 0x61 (XK_Print) */ - 0x0000, /* 0x62 (XK_Execute) */ - 0xe052, /* 0x63 (XK_Insert) */ + 0x0000, /* 0x60 (XK_Select) */ + 0x0000, /* 0x61 (XK_Print) */ + 0x0000, /* 0x62 (XK_Execute) */ + 0xe052, /* 0x63 (XK_Insert) */ 0x0000, - 0x0000, /* 0x65 (XK_Undo) */ - 0x0000, /* 0x66 (XK_Redo) */ - 0xe05d, /* 0x67 (XK_Menu) */ + 0x0000, /* 0x65 (XK_Undo) */ + 0x0000, /* 0x66 (XK_Redo) */ + 0xe05d, /* 0x67 (XK_Menu) */ - 0x0000, /* 0x68 (XK_Find) */ - 0x0000, /* 0x69 (XK_Cancel) */ - 0x0000, /* 0x6a (XK_Help) */ - 0x0000, /* 0x6b (XK_Break) */ + 0x0000, /* 0x68 (XK_Find) */ + 0x0000, /* 0x69 (XK_Cancel) */ + 0x0000, /* 0x6a (XK_Help) */ + 0x0000, /* 0x6b (XK_Break) */ 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, /* 0x70 */ + 0x0000, /* 0x70 */ 0x0000, 0x0000, 0x0000, @@ -468,16 +467,16 @@ static int keysyms_ff[] = { 0x0000, 0x0000, - 0x0000, /* 0x78 */ + 0x0000, /* 0x78 */ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, /* 0x7e (XK_Mode_switch,XK_script_switch) */ - 0x0045, /* 0x7f (XK_Num_Lock) */ + 0x0000, /* 0x7e (XK_Mode_switch,XK_script_switch) */ + 0x0045, /* 0x7f (XK_Num_Lock) */ - 0x0039, /* 0x80 (XK_KP_Space) */ + 0x0039, /* 0x80 (XK_KP_Space) */ 0x0000, 0x0000, 0x0000, @@ -486,34 +485,34 @@ static int keysyms_ff[] = { 0x0000, 0x0000, - 0x0000, /* 0x88 */ - 0x000f, /* 0x89 (XK_KP_Tab) */ + 0x0000, /* 0x88 */ + 0x000f, /* 0x89 (XK_KP_Tab) */ 0x0000, 0x0000, 0x0000, - 0xe01c, /* 0x8d (XK_KP_Enter) */ + 0xe01c, /* 0x8d (XK_KP_Enter) */ 0x0000, 0x0000, - 0x0000, /* 0x90 */ - 0x0000, /* 0x91 (XK_KP_F1) */ - 0x0000, /* 0x92 (XK_KP_F2) */ - 0x0000, /* 0x93 (XK_KP_F3) */ - 0x0000, /* 0x94 (XK_KP_F4) */ - 0x0047, /* 0x95 (XK_KP_Home) */ - 0x004b, /* 0x96 (XK_KP_Left) */ - 0x0048, /* 0x97 (XK_KP_Up) */ + 0x0000, /* 0x90 */ + 0x0000, /* 0x91 (XK_KP_F1) */ + 0x0000, /* 0x92 (XK_KP_F2) */ + 0x0000, /* 0x93 (XK_KP_F3) */ + 0x0000, /* 0x94 (XK_KP_F4) */ + 0x0047, /* 0x95 (XK_KP_Home) */ + 0x004b, /* 0x96 (XK_KP_Left) */ + 0x0048, /* 0x97 (XK_KP_Up) */ - 0x004d, /* 0x98 (XK_KP_Right) */ - 0x0050, /* 0x99 (XK_KP_Down) */ - 0x0049, /* 0x9a (XK_KP_Prior,XK_KP_Page_Up) */ - 0x0051, /* 0x9b (XK_KP_Next,XK_KP_Page_Down) */ - 0x004f, /* 0x9c (XK_KP_End) */ - 0x0000, /* 0x9d (XK_KP_Begin) */ - 0x0052, /* 0x9e (XK_KP_Insert) */ - 0x0053, /* 0x9f (XK_KP_Delete) */ + 0x004d, /* 0x98 (XK_KP_Right) */ + 0x0050, /* 0x99 (XK_KP_Down) */ + 0x0049, /* 0x9a (XK_KP_Prior,XK_KP_Page_Up) */ + 0x0051, /* 0x9b (XK_KP_Next,XK_KP_Page_Down) */ + 0x004f, /* 0x9c (XK_KP_End) */ + 0x0000, /* 0x9d (XK_KP_Begin) */ + 0x0052, /* 0x9e (XK_KP_Insert) */ + 0x0053, /* 0x9f (XK_KP_Delete) */ - 0x0000, /* 0xa0 */ + 0x0000, /* 0xa0 */ 0x0000, 0x0000, 0x0000, @@ -522,88 +521,88 @@ static int keysyms_ff[] = { 0x0000, 0x0000, - 0x0000, /* 0xa8 */ + 0x0000, /* 0xa8 */ 0x0000, - 0x0037, /* 0xaa (XK_KP_Multiply) */ - 0x004e, /* 0xab (XK_KP_Add) */ - 0x0000, /* 0xac (XK_KP_Separator) */ - 0x004a, /* 0xad (XK_KP_Subtract) */ - 0x0000, /* 0xae (XK_KP_Decimal) */ - 0x0035, /* 0xaf (XK_KP_Divide) */ + 0x0037, /* 0xaa (XK_KP_Multiply) */ + 0x004e, /* 0xab (XK_KP_Add) */ + 0x0000, /* 0xac (XK_KP_Separator) */ + 0x004a, /* 0xad (XK_KP_Subtract) */ + 0x0000, /* 0xae (XK_KP_Decimal) */ + 0x0035, /* 0xaf (XK_KP_Divide) */ - 0x0052, /* 0xb0 (XK_KP_0) */ - 0x004f, /* 0xb1 (XK_KP_1) */ - 0x0050, /* 0xb2 (XK_KP_2) */ - 0x0051, /* 0xb3 (XK_KP_3) */ - 0x004b, /* 0xb4 (XK_KP_4) */ - 0x004c, /* 0xb5 (XK_KP_5) */ - 0x004d, /* 0xb6 (XK_KP_6) */ - 0x0047, /* 0xb7 (XK_KP_7) */ + 0x0052, /* 0xb0 (XK_KP_0) */ + 0x004f, /* 0xb1 (XK_KP_1) */ + 0x0050, /* 0xb2 (XK_KP_2) */ + 0x0051, /* 0xb3 (XK_KP_3) */ + 0x004b, /* 0xb4 (XK_KP_4) */ + 0x004c, /* 0xb5 (XK_KP_5) */ + 0x004d, /* 0xb6 (XK_KP_6) */ + 0x0047, /* 0xb7 (XK_KP_7) */ - 0x0048, /* 0xb8 (XK_KP_8) */ - 0x0049, /* 0xb9 (XK_KP_9) */ + 0x0048, /* 0xb8 (XK_KP_8) */ + 0x0049, /* 0xb9 (XK_KP_9) */ 0x0000, 0x0000, 0x0000, - 0x000d, /* 0xbd (XK_KP_Equal) */ - 0x003b, /* 0xbe (XK_F1) */ - 0x003c, /* 0xbf (XK_F2) */ + 0x000d, /* 0xbd (XK_KP_Equal) */ + 0x003b, /* 0xbe (XK_F1) */ + 0x003c, /* 0xbf (XK_F2) */ - 0x003d, /* 0xc0 (XK_F3) */ - 0x003e, /* 0xc1 (XK_F4) */ - 0x003f, /* 0xc2 (XK_F5) */ - 0x0040, /* 0xc3 (XK_F6) */ - 0x0041, /* 0xc4 (XK_F7) */ - 0x0042, /* 0xc5 (XK_F8) */ - 0x0043, /* 0xc6 (XK_F9) */ - 0x0044, /* 0xc7 (XK_F10) */ + 0x003d, /* 0xc0 (XK_F3) */ + 0x003e, /* 0xc1 (XK_F4) */ + 0x003f, /* 0xc2 (XK_F5) */ + 0x0040, /* 0xc3 (XK_F6) */ + 0x0041, /* 0xc4 (XK_F7) */ + 0x0042, /* 0xc5 (XK_F8) */ + 0x0043, /* 0xc6 (XK_F9) */ + 0x0044, /* 0xc7 (XK_F10) */ - 0x0057, /* 0xc8 (XK_F11,XK_L1) */ - 0x0058, /* 0xc9 (XK_F12,XK_L2) */ - 0x0000, /* 0xca (XK_F13,XK_L3) */ - 0x0000, /* 0xcb (XK_F14,XK_L4) */ - 0x0000, /* 0xcc (XK_F15,XK_L5) */ - 0x0000, /* 0xcd (XK_F16,XK_L6) */ - 0x0000, /* 0xce (XK_F17,XK_L7) */ - 0x0000, /* 0xcf (XK_F18,XK_L8) */ + 0x0057, /* 0xc8 (XK_F11,XK_L1) */ + 0x0058, /* 0xc9 (XK_F12,XK_L2) */ + 0x0000, /* 0xca (XK_F13,XK_L3) */ + 0x0000, /* 0xcb (XK_F14,XK_L4) */ + 0x0000, /* 0xcc (XK_F15,XK_L5) */ + 0x0000, /* 0xcd (XK_F16,XK_L6) */ + 0x0000, /* 0xce (XK_F17,XK_L7) */ + 0x0000, /* 0xcf (XK_F18,XK_L8) */ - 0x0000, /* 0xd0 (XK_F19,XK_L9) */ - 0x0000, /* 0xd1 (XK_F20,XK_L10) */ - 0x0000, /* 0xd2 (XK_F21,XK_R1) */ - 0x0000, /* 0xd3 (XK_F22,XK_R2) */ - 0x0000, /* 0xd4 (XK_F23,XK_R3) */ - 0x0000, /* 0xd5 (XK_F24,XK_R4) */ - 0x0000, /* 0xd6 (XK_F25,XK_R5) */ - 0x0000, /* 0xd7 (XK_F26,XK_R6) */ + 0x0000, /* 0xd0 (XK_F19,XK_L9) */ + 0x0000, /* 0xd1 (XK_F20,XK_L10) */ + 0x0000, /* 0xd2 (XK_F21,XK_R1) */ + 0x0000, /* 0xd3 (XK_F22,XK_R2) */ + 0x0000, /* 0xd4 (XK_F23,XK_R3) */ + 0x0000, /* 0xd5 (XK_F24,XK_R4) */ + 0x0000, /* 0xd6 (XK_F25,XK_R5) */ + 0x0000, /* 0xd7 (XK_F26,XK_R6) */ - 0x0000, /* 0xd8 (XK_F27,XK_R7) */ - 0x0000, /* 0xd9 (XK_F28,XK_R8) */ - 0x0000, /* 0xda (XK_F29,XK_R9) */ - 0x0000, /* 0xdb (XK_F30,XK_R10) */ - 0x0000, /* 0xdc (XK_F31,XK_R11) */ - 0x0000, /* 0xdd (XK_F32,XK_R12) */ - 0x0000, /* 0xde (XK_F33,XK_R13) */ - 0x0000, /* 0xdf (XK_F34,XK_R14) */ + 0x0000, /* 0xd8 (XK_F27,XK_R7) */ + 0x0000, /* 0xd9 (XK_F28,XK_R8) */ + 0x0000, /* 0xda (XK_F29,XK_R9) */ + 0x0000, /* 0xdb (XK_F30,XK_R10) */ + 0x0000, /* 0xdc (XK_F31,XK_R11) */ + 0x0000, /* 0xdd (XK_F32,XK_R12) */ + 0x0000, /* 0xde (XK_F33,XK_R13) */ + 0x0000, /* 0xdf (XK_F34,XK_R14) */ - 0x0000, /* 0xe0 (XK_F35,XK_R15) */ - 0x002a, /* 0xe1 (XK_Shift_L) */ - 0x0036, /* 0xe2 (XK_Shift_R) */ - 0x001d, /* 0xe3 (XK_Control_L) */ - 0xe01d, /* 0xe4 (XK_Control_R) */ - 0x003a, /* 0xe5 (XK_Caps_Lock) */ - 0x003a, /* 0xe6 (XK_Shift_Lock) */ - 0xe05b, /* 0xe7 (XK_Meta_L) */ + 0x0000, /* 0xe0 (XK_F35,XK_R15) */ + 0x002a, /* 0xe1 (XK_Shift_L) */ + 0x0036, /* 0xe2 (XK_Shift_R) */ + 0x001d, /* 0xe3 (XK_Control_L) */ + 0xe01d, /* 0xe4 (XK_Control_R) */ + 0x003a, /* 0xe5 (XK_Caps_Lock) */ + 0x003a, /* 0xe6 (XK_Shift_Lock) */ + 0xe05b, /* 0xe7 (XK_Meta_L) */ - 0xe05c, /* 0xe8 (XK_Meta_R) */ - 0x0038, /* 0xe9 (XK_Alt_L) */ - 0xe038, /* 0xea (XK_Alt_R) */ - 0x0000, /* 0xeb (XK_Super_L) */ - 0x0000, /* 0xec (XK_Super_R) */ - 0x0000, /* 0xed (XK_Hyper_L) */ - 0x0000, /* 0xee (XK_Hyper_R) */ + 0xe05c, /* 0xe8 (XK_Meta_R) */ + 0x0038, /* 0xe9 (XK_Alt_L) */ + 0xe038, /* 0xea (XK_Alt_R) */ + 0x0000, /* 0xeb (XK_Super_L) */ + 0x0000, /* 0xec (XK_Super_R) */ + 0x0000, /* 0xed (XK_Hyper_L) */ + 0x0000, /* 0xee (XK_Hyper_R) */ 0x0000, - 0x0000, /* 0xf0 */ + 0x0000, /* 0xf0 */ 0x0000, 0x0000, 0x0000, @@ -612,86 +611,83 @@ static int keysyms_ff[] = { 0x0000, 0x0000, - 0x0000, /* 0xf8 */ + 0x0000, /* 0xf8 */ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0xe053 /* 0xff (XK_Delete) */ + 0xe053 /* 0xff (XK_Delete) */ }; - #ifdef ENABLE_VNC_KEYMAP_LOG int vnc_keymap_do_log = ENABLE_VNC_KEYMAP_LOG; -#endif - static void -vnc_keymap_log(const char *format, ...) +vnc_keymap_log(const char *fmt, ...) { -#ifdef ENABLE_VNC_KEYMAP_LOG va_list ap; if (vnc_keymap_do_log) { - va_start(ap, format); - pclog_ex(format, ap); - va_end(ap); + va_start(ap, fmt); + pclog_ex(fmt, ap); + va_end(ap); } -#endif } - +#else +# define vnc_keymap_log(fmt, ...) +#endif void vnc_kbinput(int down, int k) { uint16_t scan; - switch(k >> 8) { - case 0x00: /* page 00, Latin-1 */ - scan = keysyms_00[k & 0xff]; - break; + switch (k >> 8) { + case 0x00: /* page 00, Latin-1 */ + scan = keysyms_00[k & 0xff]; + break; - case 0xff: /* page FF, Special */ - scan = keysyms_ff[k & 0xff]; - break; + case 0xff: /* page FF, Special */ + scan = keysyms_ff[k & 0xff]; + break; - default: - vnc_keymap_log("VNC: unhandled Xkbd page: %02x\n", k>>8); - return; + default: + vnc_keymap_log("VNC: unhandled Xkbd page: %02x\n", k >> 8); + return; } if (scan == 0x0000) { - vnc_keymap_log("VNC: unhandled Xkbd key: %d (%04x)\n", k, k); - return; + vnc_keymap_log("VNC: unhandled Xkbd key: %d (%04x)\n", k, k); + return; } /* Send this scancode sequence to the PC keyboard. */ switch (scan >> 8) { - case 0x00: - default: - if (scan & 0xff) - keyboard_input(down, scan & 0xff); - break; - case 0x2a: - if (scan & 0xff) { - if (down) { - keyboard_input(down, 0x2a); - keyboard_input(down, scan & 0xff); - } else { - keyboard_input(down, scan & 0xff); - keyboard_input(down, 0x2a); - } - } - break; - case 0xe0: - if (scan & 0xff) - keyboard_input(down, (scan & 0xff) | 0x100); - break; - case 0xe1: - if (scan == 0x1d) - keyboard_input(down, 0x100); - break; + default: + case 0x00: + if (scan & 0xff) + keyboard_input(down, scan & 0xff); + break; + case 0x2a: + if (scan & 0xff) { + if (down) { + keyboard_input(down, 0x2a); + keyboard_input(down, scan & 0xff); + } else { + keyboard_input(down, scan & 0xff); + keyboard_input(down, 0x2a); + } + } + break; + case 0xe0: + if (scan & 0xff) + keyboard_input(down, (scan & 0xff) | 0x100); + break; + case 0xe1: + if (scan == 0x1d) + keyboard_input(down, 0x100); + break; } } diff --git a/src/win/86Box-qt.rc b/src/win/86Box-qt.rc index 0d4d8158f..3a92439d8 100644 --- a/src/win/86Box-qt.rc +++ b/src/win/86Box-qt.rc @@ -1,20 +1,22 @@ /* - * 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. + * 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. + * This file is part of the 86Box distribution. * - * Application resource script for Windows. + * Application resource script for Windows. * - * Authors: Miran Grca, - * Fred N. van Kempen, - * David HrdliÄka, * - * Copyright 2016-2019 Miran Grca. - * Copyright 2018,2019 David HrdliÄka. - * Copyright 2021 Laci bá' + * + * Authors: Miran Grca, + * Fred N. van Kempen, + * David HrdliÄka, + * + * Copyright 2016-2019 Miran Grca. + * Copyright 2018-2019 David HrdliÄka. + * Copyright 2021 Laci bá' */ #define IN_RESOURCE_H #include <86box/version.h> diff --git a/src/win/86Box.manifest b/src/win/86Box.manifest index 045e12dbf..4a2941845 100644 --- a/src/win/86Box.manifest +++ b/src/win/86Box.manifest @@ -34,7 +34,7 @@ - + @@ -43,7 +43,7 @@ - + diff --git a/src/win/86Box.rc b/src/win/86Box.rc index 342870d62..2932b7d62 100644 --- a/src/win/86Box.rc +++ b/src/win/86Box.rc @@ -1,20 +1,22 @@ /* - * 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. + * 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. + * This file is part of the 86Box distribution. * - * Application resource script for Windows. + * Application resource script for Windows. * - * Authors: Miran Grca, - * Fred N. van Kempen, - * David HrdliÄka, * - * Copyright 2016-2019 Miran Grca. - * Copyright 2018,2019 David HrdliÄka. - * Copyright 2021 Laci bá' + * + * Authors: Miran Grca, + * Fred N. van Kempen, + * David HrdliÄka, + * + * Copyright 2016-2019 Miran Grca. + * Copyright 2018-2019 David HrdliÄka. + * Copyright 2021 Laci bá' */ #define IN_RESOURCE_H #include <86box/resource.h> @@ -40,7 +42,7 @@ BEGIN #ifdef MTR_ENABLED "T", IDM_ACTION_TRACE, CONTROL, VIRTKEY #endif - VK_PRIOR,IDM_VID_FULLSCREEN, VIRTKEY, CONTROL , ALT + // VK_PRIOR,IDM_VID_FULLSCREEN, VIRTKEY, CONTROL , ALT VK_F11, IDM_ACTION_SCREENSHOT, VIRTKEY, CONTROL VK_F12, IDM_ACTION_RESET_CAD, VIRTKEY, CONTROL VK_PAUSE,IDM_ACTION_PAUSE, VIRTKEY @@ -360,3 +362,4 @@ END #include "languages/es-ES.rc" #include "languages/tr-TR.rc" #include "languages/uk-UA.rc" +#include "languages/zh-TW.rc" diff --git a/src/win/CMakeLists.txt b/src/win/CMakeLists.txt index 89631d209..604ba9bb0 100644 --- a/src/win/CMakeLists.txt +++ b/src/win/CMakeLists.txt @@ -1,22 +1,23 @@ # -# 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. +# 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. +# This file is part of the 86Box distribution. # -# CMake build script. +# CMake build script. # -# Authors: David HrdliÄka, +# Authors: David HrdliÄka, # -# Copyright 2020,2021 David HrdliÄka. +# Copyright 2020,2021 David HrdliÄka. +# Copyright 2021-2022 Jasmine Iwanek. # enable_language(RC) add_library(plat OBJECT win.c win_dynld.c win_cdrom.c win_keyboard.c - win_crashdump.c win_mouse.c) + win_mouse.c win_serial_passthrough.c) add_library(ui OBJECT win_ui.c win_icon.c win_stbar.c win_sdl.c win_dialog.c win_about.c win_settings.c win_devconf.c win_snd_gain.c win_specify_dim.c win_new_floppy.c @@ -27,6 +28,10 @@ if(NOT CPPTHREADS) target_sources(plat PRIVATE win_thread.c) endif() +if(RTMIDI) + target_compile_definitions(ui PRIVATE USE_RTMIDI) +endif() + # CMake 3.22 messed this up for clang/clang++ # See https://gitlab.kitware.com/cmake/cmake/-/issues/23066 if(MSVC OR (NOT MINGW AND CMAKE_VERSION VERSION_GREATER_EQUAL 3.22)) diff --git a/src/win/Makefile.mingw b/src/win/Makefile.mingw index 3f0b3a3b6..e02b9c25c 100644 --- a/src/win/Makefile.mingw +++ b/src/win/Makefile.mingw @@ -1,46 +1,56 @@ # -# 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. +# 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. # -# Makefile for Win32 (MinGW32) environment. +# This file is part of the 86Box distribution. # -# Authors: Miran Grca, -# Fred N. van Kempen, +# Makefile for Win32 (MinGW32) environment. +# +# Authors: Miran Grca, +# Fred N. van Kempen, # # Various compile-time options. ifndef STUFF -STUFF := + STUFF := endif # Add feature selections here. ifndef EXTRAS -EXTRAS := + EXTRAS := endif ifndef DEV_BUILD -DEV_BUILD := n + DEV_BUILD := n endif ifeq ($(DEV_BUILD), y) ifndef DEBUG - DEBUG := y + DEBUG := y + endif + ifndef GDBSTUB + GDBSTUB := n endif ifndef DEV_BRANCH - DEV_BRANCH := y + DEV_BRANCH := y endif ifndef AMD_K5 - AMD_K5 := y + AMD_K5 := y + endif + ifndef AN430TX + AN430TX := y endif ifndef CYRIX_6X86 - CYRIX_6X86 := y + CYRIX_6X86 := y + endif + ifndef DESKPRO386 + DESKPRO386 := y endif ifndef GUSMAX - GUSMAX := y + GUSMAX := y endif ifndef ISAMEM_RAMPAGE ISAMEM_RAMPAGE := y @@ -52,56 +62,59 @@ ifeq ($(DEV_BUILD), y) ISAMEM_BRAT := y endif ifndef LASERXT - LASERXT := y + LASERXT := y endif ifndef MGA - MGA := y - endif - ifndef NO_SIO - NO_SIO := y - endif - ifndef OPEN_AT - OPEN_AT := y - endif - ifndef PAS16 - PAS16 := n - endif - ifndef SIO_DETECT - SIO_DETECT := y - endif - ifndef VGAWONDER - VGAWONDER := y - endif - ifndef TANDY_ISA - TANDY_ISA := y - endif - ifndef VNC - VNC := y - endif - ifndef XL24 - XL24 := y + MGA := y endif ifndef OLIVETTI - OLIVETTI := y + OLIVETTI := y + endif + ifndef OPEN_AT + OPEN_AT := y + endif + ifndef PAS16 + PAS16 := y + endif + ifndef PCI_DUMMY + PCI_DUMMY := y + endif + ifndef SIO_DETECT + SIO_DETECT := y + endif + ifndef VGAWONDER + VGAWONDER := y + endif + ifndef XL24 + XL24 := y endif ifndef NEW_KBC - NEW_KBC := n + NEW_KBC := n endif else ifndef DEBUG - DEBUG := n + DEBUG := n + endif + ifndef GDBSTUB + GDBSTUB := n endif ifndef DEV_BRANCH - DEV_BRANCH := n + DEV_BRANCH := n endif ifndef AMD_K5 - AMD_K5 := n + AMD_K5 := n + endif + ifndef AN430TX + AN430TX := n endif ifndef CYRIX_6X86 - CYRIX_6X86 := n + CYRIX_6X86 := n + endif + ifndef DESKPRO386 + DESKPRO386 := n endif ifndef GUSMAX - GUSMAX := n + GUSMAX := n endif ifndef ISAMEM_RAMPAGE ISAMEM_RAMPAGE := n @@ -113,92 +126,101 @@ else ISAMEM_BRAT := n endif ifndef LASERXT - LASERXT := n + LASERXT := n endif ifndef MGA - MGA := n - endif - ifndef NO_SIO - NO_SIO := n - endif - ifndef OPEN_AT - OPEN_AT := n - endif - ifndef PAS16 - PAS16 := n - endif - ifndef SIO_DETECT - SIO_DETECT := n - endif - ifndef VGAWONDER - VGAWONDER := n - endif - ifndef TANDY_ISA - TANDY_ISA := n - endif - ifndef VNC - VNC := n - endif - ifndef XL24 - XL24 := n + MGA := n endif ifndef OLIVETTI - OLIVETTI := n + OLIVETTI := n + endif + ifndef OPEN_AT + OPEN_AT := n + endif + ifndef PAS16 + PAS16 := n + endif + ifndef PCI_DUMMY + PCI_DUMMY := n + endif + ifndef SIO_DETECT + SIO_DETECT := n + endif + ifndef VGAWONDER + VGAWONDER := n + endif + ifndef XL24 + XL24 := n endif ifndef NEW_KBC - NEW_KBC := n + NEW_KBC := n endif endif # Defaults for several build options (possibly defined in a chained file.) ifndef AUTODEP -AUTODEP := n + AUTODEP := n endif ifndef OPTIM -OPTIM := n + OPTIM := n endif ifndef RELEASE -RELEASE := n + RELEASE := n endif ifndef X64 -X64 := n + X64 := n endif ifndef ARM -ARM := n + ARM := n endif ifndef ARM64 -ARM64 := n + ARM64 := n endif ifndef DINPUT - DINPUT := n + DINPUT := n +endif +ifndef FAUDIO + FAUDIO := n endif ifndef OPENAL -OPENAL := y + OPENAL := y endif ifndef FLUIDSYNTH -FLUIDSYNTH := y + FLUIDSYNTH := y endif ifndef MUNT -MUNT := y + MUNT := y +endif +ifndef VNC + VNC := n endif ifndef NEW_DYNAREC - NEW_DYNAREC := n + NEW_DYNAREC := n endif ifndef DYNAREC - DYNAREC := y + DYNAREC := y endif ifndef CPPTHREADS - CPPTHREADS := y + CPPTHREADS := y +endif +ifndef RTMIDI + RTMIDI := y +endif +ifndef MINITRACE + MINITRACE := n +endif +ifndef AVX + AVX := n endif ifeq ($(DYNAREC), y) ifeq ($(ARM), y) ifeq ($(NEW_DYNAREC), n) - DYNAREC := n + DYNAREC := n endif endif ifeq ($(ARM64), y) ifeq ($(NEW_DYNAREC), n) - DYNAREC := n + DYNAREC := n endif endif endif @@ -206,602 +228,679 @@ endif # Path to the dynamic recompiler code. ifeq ($(NEW_DYNAREC), y) - CODEGEN := codegen_new + CODEGEN := codegen_new else - CODEGEN := codegen + CODEGEN := codegen endif # Name of the executable. -PROG := 86Box +PROG := 86Box ######################################################################### -# Nothing should need changing from here on.. # +# Nothing should need changing from here on.. # ######################################################################### -VPATH := $(EXPATH) . $(CODEGEN) minitrace cpu \ - cdrom chipset device disk disk/minivhd floppy \ - game machine mem printer \ - sio sound \ - sound/munt sound/munt/c_interface sound/munt/sha1 \ - sound/munt/srchelper sound/munt/srchelper/srctools/src \ - sound/resid-fp \ - scsi video network network/slirp win +VPATH := $(EXPATH) . $(CODEGEN) minitrace cpu cpu/softfloat \ + cpu/808x cdrom chipset device disk disk/minivhd floppy \ + game machine mem printer \ + sio sound \ + sound/munt sound/munt/c_interface sound/munt/sha1 \ + sound/munt/srchelper sound/munt/srchelper/srctools/src \ + sound/resid-fp sound/ymfm \ + scsi video network win + +WINDRES := windres +STRIP := strip ifeq ($(X64), y) -TOOL_PREFIX := x86_64-w64-mingw32- + TOOL_PREFIX := x86_64-w64-mingw32- else -TOOL_PREFIX := i686-w64-mingw32- -endif -WINDRES := windres -STRIP := strip -ifeq ($(ARM64), y) -WINDRES := aarch64-w64-mingw32-windres -STRIP := aarch64-w64-mingw32-strip -endif -ifeq ($(ARM), y) -WINDRES := armv7-w64-mingw32-windres -STRIP := armv7-w64-mingw32-strip + ifeq ($(ARM64), y) + TOOL_PREFIX := aarch64-w64-mingw32- + WINDRES := ${TOOL_PREFIX}windres + STRIP := ${TOOL_PREFIX}strip + endif + ifeq ($(ARM), y) + TOOL_PREFIX := armv7-w64-mingw32- + WINDRES := ${TOOL_PREFIX}windres + STRIP := ${TOOL_PREFIX}strip + endif + TOOL_PREFIX := i686-w64-mingw32- endif + ifeq ($(CLANG), y) -CPP := clang++ -CC := clang -ifeq ($(ARM64), y) -CPP := aarch64-w64-mingw32-clang++ -CC := aarch64-w64-mingw32-clang -endif -ifeq ($(ARM), y) -CPP := armv7-w64-mingw32-clang++ -CC := armv7-w64-mingw32-clang -endif + CPP := clang++ + CC := clang else -CPP := ${TOOL_PREFIX}g++ -CC := ${TOOL_PREFIX}gcc -ifeq ($(ARM64), y) -CPP := aarch64-w64-mingw32-g++ -CC := aarch64-w64-mingw32-gcc + CPP := ${TOOL_PREFIX}g++ + CC := ${TOOL_PREFIX}gcc endif -ifeq ($(ARM), y) -CPP := armv7-w64-mingw32-g++ -CC := armv7-w64-mingw32-gcc -endif -endif -DEPS = -MMD -MF $*.d -c $< -DEPFILE := win/.depends + +DEPS = -MMD -MF $*.d -c $< +DEPFILE := win/.depends # Set up the correct toolchain flags. -OPTS := $(EXTRAS) $(STUFF) -OPTS += -Iinclude -Iinclude_make \ - -iquote $(CODEGEN) -iquote cpu +OPTS := $(EXTRAS) $(STUFF) +OPTS += -Iinclude -Iinclude_make \ + -iquote $(CODEGEN) -iquote cpu ifdef EXFLAGS -OPTS += $(EXFLAGS) + OPTS += $(EXFLAGS) endif ifdef EXINC -OPTS += -I$(EXINC) + OPTS += -I$(EXINC) endif ifeq ($(OPTIM), y) - DFLAGS := -march=native + DFLAGS := -march=native else ifeq ($(X64), y) - DFLAGS := + DFLAGS := else - DFLAGS := -march=i686 + DFLAGS := -march=i686 endif endif ifeq ($(DEBUG), y) - DFLAGS += -ggdb -DDEBUG -DUSE_ACYCS - AOPTIM := + DFLAGS += -ggdb -DDEBUG + AOPTIM := ifndef COPTIM - COPTIM := -Og + COPTIM := -Og + endif + ifndef CXXOPTIM + ifeq ($(CLANG), y) + CXXOPTIM := -Os + else + CXXOPTIM := -Og + endif endif else - DFLAGS += -g0 + DFLAGS += -g0 ifeq ($(OPTIM), y) - AOPTIM := -mtune=native + AOPTIM := -mtune=native ifndef COPTIM - COPTIM := -O3 -ffp-contract=fast -flto + CXXOPTIM := -O3 -ffp-contract=fast -flto + endif + ifndef CXXOPTIM + ifeq ($(CLANG), y) + CXXOPTIM := -Os -ffp-contract=fast -flto + else + CXXOPTIM := -O3 -ffp-contract=fast -flto + endif endif else ifndef COPTIM - COPTIM := -O3 + COPTIM := -O3 + endif + ifndef CXXOPTIM + ifeq ($(CLANG), y) + CXXOPTIM := -Os + else + CXXOPTIM := -O3 + endif endif endif endif -AFLAGS := -msse2 -mfpmath=sse +ifeq ($(AVX), y) + AFLAGS := -msse2 -msse3 -mssse3 -msse4 -msse4a -mavx -mavx2 -mfpmath=sse +else + AFLAGS := -msse2 -mfpmath=sse +endif ifeq ($(ARM), y) - DFLAGS := -march=armv7-a - AOPTIM := - AFLAGS := -mfloat-abi=hard + DFLAGS := -march=armv7-a + AOPTIM := + AFLAGS := -mfloat-abi=hard endif ifeq ($(ARM64), y) - DFLAGS := -march=armv8-a - AOPTIM := - AFLAGS := -mfloat-abi=hard + DFLAGS := -march=armv8-a + AOPTIM := + AFLAGS := -mfloat-abi=hard endif -RFLAGS := --input-format=rc -O coff -Iinclude -Iinclude_make +RFLAGS := --input-format=rc -O coff -Iinclude -Iinclude_make ifeq ($(RELEASE), y) -OPTS += -DRELEASE_BUILD -RFLAGS += -DRELEASE_BUILD + OPTS += -DRELEASE_BUILD + RFLAGS += -DRELEASE_BUILD endif # Optional modules. ifeq ($(DYNAREC), y) -OPTS += -DUSE_DYNAREC -RFLAGS += -DUSE_DYNAREC + OPTS += -DUSE_DYNAREC + RFLAGS += -DUSE_DYNAREC ifeq ($(NEW_DYNAREC), y) - OPTS += -DUSE_NEW_DYNAREC - RFLAGS += -DUSE_NEW_DYNAREC + OPTS += -DUSE_NEW_DYNAREC + RFLAGS += -DUSE_NEW_DYNAREC ifeq ($(X64), y) - PLATCG := codegen_backend_x86-64.o codegen_backend_x86-64_ops.o codegen_backend_x86-64_ops_sse.o \ - codegen_backend_x86-64_uops.o + PLATCG := codegen_backend_x86-64.o codegen_backend_x86-64_ops.o codegen_backend_x86-64_ops_sse.o \ + codegen_backend_x86-64_uops.o else ifeq ($(ARM64), y) - PLATCG := codegen_backend_arm64.o codegen_backend_arm64_ops.o codegen_backend_arm64_uops.o \ - codegen_backend_arm64_imm.o + PLATCG := codegen_backend_arm64.o codegen_backend_arm64_ops.o codegen_backend_arm64_uops.o \ + codegen_backend_arm64_imm.o else ifeq ($(ARM), y) - PLATCG := codegen_backend_arm.o codegen_backend_arm_ops.o codegen_backend_arm_uops.o + PLATCG := codegen_backend_arm.o codegen_backend_arm_ops.o codegen_backend_arm_uops.o else - PLATCG := codegen_backend_x86.o codegen_backend_x86_ops.o codegen_backend_x86_ops_fpu.o \ - codegen_backend_x86_ops_sse.o codegen_backend_x86_uops.o + PLATCG := codegen_backend_x86.o codegen_backend_x86_ops.o codegen_backend_x86_ops_fpu.o \ + codegen_backend_x86_ops_sse.o codegen_backend_x86_uops.o endif - DYNARECOBJ := codegen.o codegen_accumulate.o codegen_allocator.o codegen_block.o codegen_ir.o codegen_ops.o \ - codegen_ops_3dnow.o codegen_ops_branch.o codegen_ops_arith.o codegen_ops_fpu_arith.o \ - codegen_ops_fpu_constant.o codegen_ops_fpu_loadstore.o codegen_ops_fpu_misc.o codegen_ops_helpers.o \ - codegen_ops_jump.o codegen_ops_logic.o codegen_ops_misc.o codegen_ops_mmx_arith.o codegen_ops_mmx_cmp.o \ - codegen_ops_mmx_loadstore.o codegen_ops_mmx_logic.o codegen_ops_mmx_pack.o codegen_ops_mmx_shift.o \ - codegen_ops_mov.o codegen_ops_shift.o codegen_ops_stack.o codegen_reg.o $(PLATCG) + DYNARECOBJ := codegen.o codegen_accumulate.o codegen_allocator.o codegen_block.o codegen_ir.o codegen_ops.o \ + codegen_ops_3dnow.o codegen_ops_branch.o codegen_ops_arith.o codegen_ops_fpu_arith.o \ + codegen_ops_fpu_constant.o codegen_ops_fpu_loadstore.o codegen_ops_fpu_misc.o codegen_ops_helpers.o \ + codegen_ops_jump.o codegen_ops_logic.o codegen_ops_misc.o codegen_ops_mmx_arith.o codegen_ops_mmx_cmp.o \ + codegen_ops_mmx_loadstore.o codegen_ops_mmx_logic.o codegen_ops_mmx_pack.o codegen_ops_mmx_shift.o \ + codegen_ops_mov.o codegen_ops_shift.o codegen_ops_stack.o codegen_reg.o $(PLATCG) else ifeq ($(X64), y) - PLATCG := codegen_x86-64.o codegen_accumulate_x86-64.o + PLATCG := codegen_x86-64.o codegen_accumulate_x86-64.o else - PLATCG := codegen_x86.o codegen_accumulate_x86.o + PLATCG := codegen_x86.o codegen_accumulate_x86.o endif - DYNARECOBJ := codegen.o \ - codegen_ops.o $(PLATCG) + DYNARECOBJ := codegen.o \ + codegen_ops.o $(PLATCG) endif - CGTOBJ := codegen_timing_486.o \ - codegen_timing_686.o codegen_timing_common.o codegen_timing_k6.o codegen_timing_pentium.o \ - codegen_timing_p6.o codegen_timing_winchip.o codegen_timing_winchip2.o + CGTOBJ := codegen_timing_486.o \ + codegen_timing_686.o codegen_timing_common.o codegen_timing_k6.o codegen_timing_pentium.o \ + codegen_timing_p6.o codegen_timing_winchip.o codegen_timing_winchip2.o else ifeq ($(NEW_DYNAREC), y) - OPTS += -DUSE_NEW_DYNAREC - RFLAGS += -DUSE_NEW_DYNAREC + OPTS += -DUSE_NEW_DYNAREC + RFLAGS += -DUSE_NEW_DYNAREC endif endif -ifeq ($(OPENAL), y) -OPTS += -DUSE_OPENAL -endif ifeq ($(FLUIDSYNTH), y) -OPTS += -DUSE_FLUIDSYNTH -FSYNTHOBJ := midi_fluidsynth.o + OPTS += -DUSE_FLUIDSYNTH + FSYNTHOBJ := midi_fluidsynth.o endif ifeq ($(MUNT), y) -OPTS += -DUSE_MUNT -MUNTOBJ := midi_mt32.o \ - Analog.o BReverbModel.o File.o FileStream.o LA32Ramp.o \ - LA32FloatWaveGenerator.o LA32WaveGenerator.o \ - MidiStreamParser.o Part.o Partial.o PartialManager.o \ - Poly.o ROMInfo.o SampleRateConverter.o \ - FIRResampler.o IIR2xResampler.o LinearResampler.o ResamplerModel.o \ - SincResampler.o InternalResampler.o \ - Synth.o Tables.o TVA.o TVF.o TVP.o sha1.o c_interface.o + OPTS += -DUSE_MUNT + MUNTOBJ := midi_mt32.o \ + Analog.o BReverbModel.o Display.o File.o FileStream.o LA32Ramp.o \ + LA32FloatWaveGenerator.o LA32WaveGenerator.o \ + MidiStreamParser.o Part.o Partial.o PartialManager.o \ + Poly.o ROMInfo.o SampleRateConverter.o \ + FIRResampler.o IIR2xResampler.o LinearResampler.o ResamplerModel.o \ + SincResampler.o InternalResampler.o \ + Synth.o Tables.o TVA.o TVF.o TVP.o sha1.o c_interface.o endif ifeq ($(CPPTHREADS), y) -THREADOBJ := thread.o + THREADOBJ := thread.o else -THREADOBJ := win_thread.o + THREADOBJ := win_thread.o endif ifeq ($(VNC), y) -OPTS += -DUSE_VNC -RFLAGS += -DUSE_VNC + OPTS += -DUSE_VNC + RFLAGS += -DUSE_VNC ifneq ($(VNC_PATH), ) - OPTS += -I$(VNC_PATH)\INCLUDE - VNCLIB := -L$(VNC_PATH)\LIB + OPTS += -I$(VNC_PATH)\INCLUDE + VNCLIB := -L$(VNC_PATH)\LIB endif -VNCLIB += -lvncserver -VNCOBJ := vnc.o vnc_keymap.o + VNCLIB += -lvncserver.dll + VNCOBJ := vnc.o vnc_keymap.o endif ifeq ($(MINITRACE), y) -OPTS += -DMTR_ENABLED -RFLAGS += -DMTR_ENABLED -MINITRACEOBJ := minitrace.o + OPTS += -DMTR_ENABLED + RFLAGS += -DMTR_ENABLED + MINITRACEOBJ := minitrace.o +endif + +ifeq ($(FAUDIO), y) + OPTS += -DUSE_FAUDIO endif # Options for the DEV branch. ifeq ($(DEV_BRANCH), y) -OPTS += -DDEV_BRANCH -RFLAGS += -DDEV_BRANCH -DEVBROBJ := + OPTS += -DDEV_BRANCH + RFLAGS += -DDEV_BRANCH + DEVBROBJ := -ifeq ($(AMD_K5), y) -OPTS += -DUSE_AMD_K5 + ifeq ($(AMD_K5), y) + OPTS += -DUSE_AMD_K5 + endif + + ifeq ($(AN430TX), y) + OPTS += -DUSE_AN430TX + endif + + ifeq ($(CYRIX_6X86), y) + OPTS += -DUSE_CYRIX_6X86 + endif + + ifeq ($(DESKPRO386), y) + OPTS += -DUSE_DESKPRO386 + endif + + ifeq ($(GUSMAX), y) + OPTS += -DUSE_GUSMAX + endif + + ifeq ($(ISAMEM_RAMPAGE), y) + OPTS += -DUSE_ISAMEM_RAMPAGE + endif + + ifeq ($(ISAMEM_IAB), y) + OPTS += -DUSE_ISAMEM_IAB + endif + + ifeq ($(ISAMEM_BRAT), y) + OPTS += -DUSE_ISAMEM_BRAT + endif + + ifeq ($(LASERXT), y) + OPTS += -DUSE_LASERXT + DEVBROBJ += m_xt_laserxt.o + endif + + ifeq ($(MGA), y) + OPTS += -DUSE_MGA + DEVBROBJ += vid_mga.o + endif + + ifeq ($(OPEN_AT), y) + OPTS += -DUSE_OPEN_AT + endif + + ifeq ($(PAS16), y) + OPTS += -DUSE_PAS16 + DEVBROBJ += snd_pas16.o + endif + + ifeq ($(PCI_DUMMY), y) + OPTS += -DUSE_PCI_DUMMY + DEVBROBJ += pci_dummy.o + endif + + ifeq ($(SIO_DETECT), y) + OPTS += -DUSE_SIO_DETECT + DEVBROBJ += sio_detect.o + endif + + ifeq ($(VGAWONDER), y) + OPTS += -DUSE_VGAWONDER + endif + + ifeq ($(XL24), y) + OPTS += -DUSE_XL24 + endif + + ifeq ($(OLIVETTI), y) + OPTS += -DUSE_OLIVETTI + DEVBROBJ += olivetti_eva.o + endif + + ifeq ($(GDBSTUB), y) + OPTS += -DUSE_GDBSTUB + DEVBROBJ += gdbstub.o + endif endif -ifeq ($(CYRIX_6X86), y) -OPTS += -DUSE_CYRIX_6X86 -endif - -ifeq ($(GUSMAX), y) -OPTS += -DUSE_GUSMAX -endif - -ifeq ($(ISAMEM_RAMPAGE), y) -OPTS += -DUSE_ISAMEM_RAMPAGE -endif - -ifeq ($(ISAMEM_IAB), y) -OPTS += -DUSE_ISAMEM_IAB -endif - -ifeq ($(ISAMEM_BRAT), y) -OPTS += -DUSE_ISAMEM_BRAT -endif - -ifeq ($(LASERXT), y) -OPTS += -DUSE_LASERXT -DEVBROBJ += m_xt_laserxt.o -endif - -ifeq ($(MGA), y) -OPTS += -DUSE_MGA -DEVBROBJ += vid_mga.o -endif - -ifeq ($(NO_SIO), y) -OPTS += -DNO_SIO -endif - -ifeq ($(OPEN_AT), y) -OPTS += -DUSE_OPEN_AT -endif - -ifeq ($(PAS16), y) -OPTS += -DUSE_PAS16 -DEVBROBJ += snd_pas16.o -endif - -ifeq ($(SIO_DETECT), y) -OPTS += -DUSE_SIO_DETECT -DEVBROBJ += sio_detect.o -endif - -ifeq ($(TANDY_ISA), y) -OPTS += -DUSE_TANDY_ISA -endif - -ifeq ($(VGAWONDER), y) -OPTS += -DUSE_VGAWONDER -endif - -ifeq ($(XL24), y) -OPTS += -DUSE_XL24 -endif - -ifeq ($(OLIVETTI), y) -OPTS += -DUSE_OLIVETTI -DEVBROBJ += olivetti_eva.o -endif - - +ifeq ($(RTMIDI), y) + OPTS += -DUSE_RTMIDI endif # Final versions of the toolchain flags. -CFLAGS := $(OPTS) $(DFLAGS) $(COPTIM) $(AOPTIM) \ - $(AFLAGS) -fomit-frame-pointer -mstackrealign -Wall \ - -fno-strict-aliasing +CFLAGS := $(OPTS) $(DFLAGS) $(COPTIM) $(AOPTIM) \ + $(AFLAGS) -fomit-frame-pointer -mstackrealign -Wall \ + -fno-strict-aliasing # Add freetyp2 references through pkgconfig -CFLAGS := $(CFLAGS) `pkg-config --cflags freetype2` +CFLAGS := $(CFLAGS) `pkg-config --cflags freetype2` -CXXFLAGS := $(CFLAGS) +CXXFLAGS := $(OPTS) $(DFLAGS) $(CXXOPTIM) $(AOPTIM) \ + $(AFLAGS) -fomit-frame-pointer -mstackrealign -Wall \ + -fno-strict-aliasing + +CFLAGS += -Werror=implicit-int -Werror=implicit-function-declaration \ + -Werror=int-conversion -Werror=strict-prototypes -Werror=old-style-definition ######################################################################### -# Create the (final) list of objects to build. # +# Create the (final) list of objects to build. # ######################################################################### -MAINOBJ := 86box.o config.o log.o random.o timer.o io.o acpi.o apm.o dma.o ddma.o \ - nmi.o pic.o pit.o port_6x.o port_92.o ppi.o pci.o mca.o fifo8.o \ - usb.o device.o nvr.o nvr_at.o nvr_ps2.o \ - $(VNCOBJ) +MAINOBJ := 86box.o config.o log.o random.o timer.o io.o acpi.o apm.o dma.o ddma.o \ + nmi.o pic.o pit.o pit_fast.o port_6x.o port_92.o ppi.o pci.o mca.o fifo.o \ + fifo8.o usb.o device.o nvr.o nvr_at.o nvr_ps2.o machine_status.o ini.o \ + $(VNCOBJ) -MEMOBJ := catalyst_flash.o i2c_eeprom.o intel_flash.o mem.o rom.o smram.o spd.o sst_flash.o +MEMOBJ := catalyst_flash.o i2c_eeprom.o intel_flash.o mem.o mmu_2386.o rom.o row.o \ + smram.o spd.o sst_flash.o -CPUOBJ := $(DYNARECOBJ) \ - $(CGTOBJ) \ - cpu.o cpu_table.o fpu.o x86.o \ - 808x.o 386.o 386_common.o 386_dynarec.o 386_dynarec_ops.o \ - x86seg.o x87.o x87_timings.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 \ + x86_ops_mmx.o x86seg_common.o x86seg_2386.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 -CHIPSETOBJ := 82c100.o acc2168.o \ - contaq_82c59x.o \ - cs4031.o cs8230.o \ - ali1429.o ali1489.o ali1531.o ali1541.o ali1543.o ali1621.o ali6117.o \ - gc100.o headland.o \ - ims8848.o intel_82335.o intel_420ex.o intel_4x0.o intel_i450kx.o intel_sio.o intel_piix.o \ - ioapic.o \ - neat.o \ - opti283.o opti291.o opti391.o opti495.o opti822.o opti895.o opti5x7.o \ - scamp.o scat.o \ - stpc.o \ - wd76c10.o vl82c480.o \ - umc_8886.o umc_hb4.o \ - via_vt82c49x.o via_vt82c505.o via_apollo.o via_pipc.o \ - sis_85c310.o sis_85c4xx.o sis_85c496.o sis_85c50x.o sis_5511.o sis_5571.o +CHIPSETOBJ := 82c100.o acc2168.o \ + compaq_386.o \ + contaq_82c59x.o \ + cs4031.o cs8230.o \ + ali1429.o ali1435.o ali1489.o ali1531.o ali1541.o ali1543.o ali1621.o ali6117.o \ + gc100.o headland.o \ + ims8848.o intel_82335.o intel_420ex.o intel_4x0.o intel_i450kx.o intel_sio.o intel_piix.o \ + ioapic.o \ + neat.o \ + opti283.o opti291.o opti391.o opti495.o opti602.o opti822.o opti895.o opti5x7.o \ + scamp.o scat.o \ + stpc.o \ + wd76c10.o vl82c480.o \ + umc_8886.o umc_hb4.o \ + via_vt82c49x.o via_vt82c505.o via_apollo.o via_pipc.o \ + sis_85c310.o sis_85c4xx.o sis_85c496.o sis_85c50x.o sis_5511.o sis_5571.o -MCHOBJ := machine.o machine_table.o \ - m_xt.o m_xt_compaq.o \ - m_xt_philips.o \ - m_xt_t1000.o m_xt_t1000_vid.o \ - m_xt_xi8088.o m_xt_zenith.o \ - m_pcjr.o \ - m_amstrad.o m_europc.o \ - m_xt_olivetti.o m_tandy.o m_v86p.o \ - m_at.o m_at_commodore.o \ - m_at_t3100e.o m_at_t3100e_vid.o \ - m_ps1.o m_ps1_hdc.o \ - m_ps2_isa.o m_ps2_mca.o \ - m_at_compaq.o \ - m_at_286_386sx.o m_at_386dx_486.o \ - m_at_socket4.o m_at_socket5.o m_at_socket7_3v.o m_at_socket7.o m_at_sockets7.o \ - m_at_socket8.o m_at_slot1.o m_at_slot2.o m_at_socket370.o \ - m_at_misc.o +MCHOBJ := machine.o machine_table.o \ + m_xt.o m_xt_compaq.o \ + m_xt_philips.o \ + m_xt_t1000.o m_xt_t1000_vid.o \ + m_xt_xi8088.o m_xt_zenith.o \ + m_pcjr.o \ + m_amstrad.o m_europc.o \ + m_elt.o \ + m_xt_olivetti.o m_tandy.o m_v86p.o \ + m_at.o m_at_commodore.o \ + m_at_t3100e.o m_at_t3100e_vid.o \ + m_ps1.o m_ps1_hdc.o \ + m_ps2_isa.o m_ps2_mca.o \ + m_at_compaq.o \ + m_at_286_386sx.o m_at_386dx_486.o \ + m_at_socket4.o m_at_socket5.o m_at_socket7_3v.o m_at_socket7.o m_at_sockets7.o \ + m_at_socket8.o m_at_slot1.o m_at_slot2.o m_at_socket370.o \ + m_at_misc.o -ifeq ($(NEW_KBC), y) -DEVOBJ := bugger.o cartridge.o cassette.o hasp.o hwm.o hwm_lm75.o hwm_lm78.o hwm_gl518sm.o hwm_vt82c686.o \ - ibm_5161.o isamem.o isartc.o lpt.o pci_bridge.o postcard.o serial.o \ - clock_ics9xxx.o isapnp.o \ - i2c.o i2c_gpio.o smbus_ali7101.o smbus_piix4.o \ - keyboard.o \ - keyboard_xt.o kbc_at.o kbd_at.o \ - mouse.o \ - mouse_bus.o \ - mouse_serial.o mouse_ps2.o \ - phoenix_486_jumper.o -else -DEVOBJ := bugger.o cartridge.o cassette.o hasp.o hwm.o hwm_lm75.o hwm_lm78.o hwm_gl518sm.o hwm_vt82c686.o \ - ibm_5161.o isamem.o isartc.o lpt.o pci_bridge.o postcard.o serial.o \ - clock_ics9xxx.o isapnp.o \ - i2c.o i2c_gpio.o smbus_ali7101.o smbus_piix4.o \ - keyboard.o \ - keyboard_xt.o keyboard_at.o \ - mouse.o \ - mouse_bus.o \ - mouse_serial.o mouse_ps2.o \ - phoenix_486_jumper.o -endif +KBCOBJ := kbc_at.o kbc_at_dev.o \ + keyboard_at.o -SIOOBJ := sio_acc3221.o \ - sio_f82c710.o sio_82091aa.o sio_fdc37c6xx.o \ - sio_fdc37c67x.o sio_fdc37c669.o sio_fdc37c93x.o sio_fdc37m60x.o \ - sio_it8661f.o \ - sio_pc87306.o sio_pc87307.o sio_pc87309.o sio_pc87310.o sio_pc87311.o sio_pc87332.o \ - sio_prime3b.o sio_prime3c.o \ - sio_w83787f.o \ - sio_w83877f.o sio_w83977f.o \ - sio_um8669f.o \ - sio_vt82c686.o +DEVOBJ := bugger.o cartridge.o cassette.o hasp.o hwm.o hwm_lm75.o hwm_lm78.o hwm_gl518sm.o hwm_vt82c686.o \ + ibm_5161.o isamem.o isartc.o lpt.o pci_bridge.o postcard.o serial.o \ + clock_ics9xxx.o isapnp.o \ + i2c.o i2c_gpio.o smbus_ali7101.o smbus_piix4.o \ + keyboard.o \ + keyboard_xt.o $(KBCOBJ) \ + mouse.o \ + mouse_bus.o \ + mouse_serial.o mouse_ps2.o \ + mouse_wacom_tablet.o \ + phoenix_486_jumper.o serial_passthrough.o -FDDOBJ := fdd.o fdc.o fdc_magitronic.o fdc_pii15xb.o \ - fdi2raw.o \ - fdd_common.o fdd_86f.o \ - fdd_fdi.o fdd_imd.o fdd_img.o fdd_json.o \ - fdd_mfm.o fdd_td0.o +SIOOBJ := sio_acc3221.o sio_ali5123.o \ + sio_f82c710.o sio_82091aa.o sio_fdc37c6xx.o \ + sio_fdc37c67x.o sio_fdc37c669.o sio_fdc37c93x.o sio_fdc37m60x.o \ + sio_it8661f.o \ + sio_pc87306.o sio_pc87307.o sio_pc87309.o sio_pc87310.o sio_pc87311.o sio_pc87332.o \ + sio_prime3b.o sio_prime3c.o \ + sio_w83787f.o \ + sio_w83877f.o sio_w83977f.o \ + sio_um8669f.o \ + sio_vt82c686.o -GAMEOBJ := gameport.o \ - joystick_standard.o joystick_ch_flightstick_pro.o \ - joystick_sw_pad.o joystick_tm_fcs.o +FDDOBJ := fdd.o fdc.o fdc_magitronic.o fdc_monster.o fdc_pii15xb.o \ + fdi2raw.o \ + fdd_common.o fdd_86f.o \ + fdd_fdi.o fdd_imd.o fdd_img.o fdd_json.o \ + fdd_mfm.o fdd_td0.o -HDDOBJ := hdd.o \ - hdd_image.o hdd_table.o \ - hdc.o \ - hdc_st506_xt.o hdc_st506_at.o \ - hdc_xta.o \ - hdc_esdi_at.o hdc_esdi_mca.o \ - hdc_xtide.o hdc_ide.o \ - hdc_ide_opti611.o \ - hdc_ide_cmd640.o hdc_ide_cmd646.o \ - hdc_ide_sff8038i.o +GAMEOBJ := gameport.o \ + joystick_standard.o joystick_ch_flightstick_pro.o \ + joystick_sw_pad.o joystick_tm_fcs.o -MINIVHDOBJ := cwalk.o libxml2_encoding.o minivhd_convert.o \ - minivhd_create.o minivhd_io.o minivhd_manage.o \ - minivhd_struct_rw.o minivhd_util.o +HDDOBJ := hdd.o \ + hdd_image.o hdd_table.o \ + hdc.o \ + hdc_st506_xt.o hdc_st506_at.o \ + hdc_xta.o \ + hdc_esdi_at.o hdc_esdi_mca.o \ + hdc_xtide.o hdc_ide.o \ + hdc_ide_opti611.o \ + hdc_ide_cmd640.o hdc_ide_cmd646.o \ + hdc_ide_sff8038i.o -CDROMOBJ := cdrom.o \ - cdrom_image_backend.o cdrom_image.o +MINIVHDOBJ := cwalk.o xml2_encoding.o convert.o \ + create.o minivhd_io.o manage.o struct_rw.o minivhd_util.o -ZIPOBJ := zip.o +CDROMOBJ := cdrom.o \ + cdrom_image_backend.o cdrom_image_viso.o cdrom_image.o cdrom_mitsumi.o -MOOBJ := mo.o +ZIPOBJ := zip.o -SCSIOBJ := scsi.o scsi_device.o \ - scsi_cdrom.o scsi_disk.o \ - scsi_x54x.o \ - scsi_aha154x.o scsi_buslogic.o \ - scsi_ncr5380.o scsi_ncr53c8xx.o \ - scsi_pcscsi.o scsi_spock.o +MOOBJ := mo.o -NETOBJ := network.o \ - net_pcap.o \ - net_slirp.o tinyglib.o \ - arp_table.o bootp.o cksum.o dnssearch.o if.o ip_icmp.o ip_input.o \ - ip_output.o mbuf.o misc.o sbuf.o slirp.o socket.o tcp_input.o \ - tcp_output.o tcp_subr.o tcp_timer.o udp.o util.o version.o \ - net_dp8390.o \ - net_3c503.o net_ne2000.o \ - net_pcnet.o net_wd8003.o \ - net_plip.o +SCSIOBJ := scsi.o scsi_device.o \ + scsi_cdrom.o scsi_disk.o \ + scsi_x54x.o \ + scsi_aha154x.o scsi_buslogic.o \ + scsi_ncr5380.o scsi_ncr53c8xx.o \ + scsi_pcscsi.o scsi_spock.o -PRINTOBJ := png.o prt_cpmap.o \ - prt_escp.o prt_text.o prt_ps.o +NETOBJ := network.o \ + net_pcap.o \ + net_slirp.o \ + net_dp8390.o net_3c501.o \ + net_3c503.o net_ne2000.o \ + net_pcnet.o net_wd8003.o \ + net_plip.o net_event.o \ + net_null.o -SNDOBJ := sound.o \ - openal.o \ - snd_opl.o snd_opl_nuked.o \ - snd_resid.o \ - convolve.o convolve-sse.o envelope.o extfilt.o \ - filter.o pot.o sid.o voice.o wave6581__ST.o \ - wave6581_P_T.o wave6581_PS_.o wave6581_PST.o \ - wave8580__ST.o wave8580_P_T.o wave8580_PS_.o \ - wave8580_PST.o wave.o \ - midi.o midi_rtmidi.o \ - snd_speaker.o \ - snd_pssj.o \ - snd_ps1.o \ - snd_lpt_dac.o snd_lpt_dss.o \ - snd_adlib.o snd_adlibgold.o snd_ad1848.o snd_audiopci.o \ - snd_ac97_codec.o snd_ac97_via.o \ - snd_azt2316a.o snd_cs423x.o \ - snd_cms.o \ - snd_gus.o \ - snd_sb.o snd_sb_dsp.o \ - snd_emu8k.o snd_mpu401.o \ - snd_sn76489.o snd_ssi2001.o \ - snd_wss.o \ - snd_ym7128.o +PRINTOBJ := png.o prt_cpmap.o \ + prt_escp.o prt_text.o prt_ps.o -VIDOBJ := agpgart.o video.o \ - vid_table.o \ - vid_cga.o vid_cga_comp.o \ - vid_compaq_cga.o \ - vid_mda.o \ - vid_hercules.o vid_herculesplus.o vid_incolor.o \ - vid_colorplus.o \ - vid_genius.o \ - vid_pgc.o vid_im1024.o \ - vid_sigma.o \ - vid_wy700.o \ - vid_ega.o vid_ega_render.o \ - vid_svga.o vid_svga_render.o \ - vid_ddc.o \ - vid_vga.o \ - vid_ati_eeprom.o \ - vid_ati18800.o vid_ati28800.o \ - vid_ati_mach64.o vid_ati68860_ramdac.o \ - vid_bt48x_ramdac.o \ - vid_av9194.o vid_icd2061.o vid_ics2494.o vid_ics2595.o \ - vid_cl54xx.o \ - vid_et4000.o vid_sc1148x_ramdac.o \ - vid_sc1502x_ramdac.o \ - vid_et4000w32.o vid_stg_ramdac.o \ - vid_ht216.o \ - vid_oak_oti.o \ - vid_paradise.o \ - vid_rtg310x.o \ - vid_ti_cf62011.o \ - vid_f82c425.o \ - vid_tvga.o \ - vid_tgui9440.o vid_tkd8001_ramdac.o \ - vid_att20c49x_ramdac.o \ - vid_att2xc498_ramdac.o \ - vid_s3.o vid_s3_virge.o \ - vid_ibm_rgb528_ramdac.o vid_sdac_ramdac.o \ - vid_ogc.o \ - vid_nga.o \ - vid_tvp3026_ramdac.o +SNDOBJ := sound.o \ + snd_opl.o snd_opl_nuked.o snd_opl_ymfm.o \ + ymfm_adpcm.o ymfm_misc.o ymfm_opl.o ymfm_opm.o \ + ymfm_opn.o ymfm_opq.o ymfm_opz.o ymfm_pcm.o ymfm_ssg.o \ + snd_resid.o \ + convolve.o convolve-sse.o envelope.o extfilt.o \ + filter.o pot.o sid.o voice.o wave6581__ST.o \ + wave6581_P_T.o wave6581_PS_.o wave6581_PST.o \ + wave8580__ST.o wave8580_P_T.o wave8580_PS_.o \ + wave8580_PST.o wave.o \ + midi.o \ + snd_speaker.o \ + snd_pssj.o \ + snd_ps1.o \ + snd_lpt_dac.o snd_lpt_dss.o \ + snd_adlib.o snd_adlibgold.o snd_ad1848.o snd_audiopci.o \ + snd_ac97_codec.o snd_ac97_via.o \ + snd_azt2316a.o snd_cs423x.o \ + snd_optimc.o snd_cmi8x38.o \ + snd_cms.o \ + snd_gus.o \ + snd_sb.o snd_sb_dsp.o \ + snd_emu8k.o snd_mpu401.o \ + snd_sn76489.o snd_ssi2001.o \ + snd_wss.o \ + snd_ym7128.o -VOODOOOBJ := vid_voodoo.o vid_voodoo_banshee.o \ - vid_voodoo_banshee_blitter.o \ - vid_voodoo_blitter.o \ - vid_voodoo_display.o vid_voodoo_fb.o \ - vid_voodoo_fifo.o vid_voodoo_reg.o \ - vid_voodoo_render.o vid_voodoo_setup.o \ - vid_voodoo_texture.o +VIDOBJ := agpgart.o video.o \ + vid_table.o \ + vid_cga.o vid_cga_comp.o \ + vid_compaq_cga.o \ + vid_mda.o \ + vid_hercules.o vid_herculesplus.o vid_incolor.o \ + vid_colorplus.o \ + vid_genius.o \ + vid_pgc.o vid_im1024.o \ + vid_sigma.o \ + vid_wy700.o \ + vid_ega.o vid_ega_render.o \ + vid_svga.o vid_svga_render.o \ + vid_8514a.o \ + vid_ddc.o \ + vid_vga.o \ + vid_ati_eeprom.o \ + vid_ati18800.o vid_ati28800.o \ + vid_ati_mach8.o \ + vid_ati68875_ramdac.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 \ + vid_cl54xx.o \ + vid_et3000.o \ + vid_et4000.o vid_sc1148x_ramdac.o \ + vid_sc1502x_ramdac.o \ + vid_et4000w32.o vid_stg_ramdac.o \ + vid_ht216.o \ + vid_oak_oti.o \ + vid_paradise.o \ + vid_rtg310x.o \ + vid_ti_cf62011.o \ + vid_f82c425.o \ + vid_tvga.o \ + vid_tgui9440.o vid_tkd8001_ramdac.o \ + vid_att20c49x_ramdac.o \ + vid_att2xc498_ramdac.o \ + vid_s3.o vid_s3_virge.o \ + vid_ibm_rgb528_ramdac.o vid_sdac_ramdac.o \ + vid_ogc.o \ + vid_nga.o \ + vid_tvp3026_ramdac.o \ + vid_xga.o -PLATOBJ := win.o \ - win_dynld.o \ - win_cdrom.o win_keyboard.o \ - win_crashdump.o \ - win_mouse.o +VOODOOOBJ := vid_voodoo.o vid_voodoo_banshee.o \ + vid_voodoo_banshee_blitter.o \ + vid_voodoo_blitter.o \ + vid_voodoo_display.o vid_voodoo_fb.o \ + vid_voodoo_fifo.o vid_voodoo_reg.o \ + vid_voodoo_render.o vid_voodoo_setup.o \ + vid_voodoo_texture.o -UIOBJ := win_ui.o win_icon.o win_stbar.o discord.o \ - win_sdl.o win_opengl.o win_opengl_glslp.o glad.o \ - win_dialog.o win_about.o \ - win_settings.o win_devconf.o win_snd_gain.o win_specify_dim.o win_preferences.o \ - win_new_floppy.o win_jsconf.o \ - win_media_menu.o win_toolbar.o +PLATOBJ := win.o \ + win_dynld.o \ + win_cdrom.o win_keyboard.o \ + win_mouse.o win_serial_passthrough.o + +UIOBJ := win_ui.o win_icon.o win_stbar.o discord.o \ + win_sdl.o win_opengl.o win_opengl_glslp.o glad.o \ + win_dialog.o win_about.o \ + win_settings.o win_devconf.o win_snd_gain.o win_specify_dim.o win_preferences.o \ + win_new_floppy.o win_jsconf.o \ + win_media_menu.o win_toolbar.o ifeq ($(DINPUT), y) - PLATOBJ += win_joystick.o + PLATOBJ += win_joystick.o else - PLATOBJ += win_joystick_rawinput.o + PLATOBJ += win_joystick_rawinput.o endif -OBJ := $(MAINOBJ) $(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) +ifeq ($(OPENAL), y) + SNDOBJ += openal.o +else + SNDOBJ += xaudio2.o +endif + +ifeq ($(RTMIDI), y) + SNDOBJ += midi_rtmidi.o +endif + +OBJ := $(MAINOBJ) $(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) ifdef EXOBJ -OBJ += $(EXOBJ) + OBJ += $(EXOBJ) endif -LIBS := -mwindows -lcomctl32 \ - -lopenal -lole32 +ifeq ($(LOG), y) + MWIN := -lcomdlg32 +else + MWIN := -mwindows +endif + +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 +else + ifeq ($(FAUDIO), y) + 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 + endif +endif + +ifeq ($(RTMIDI), y) + ifeq ($(CLANG), y) + LIBS += -lrtmidi.dll -lwinmm + else + LIBS += -lrtmidi -lwinmm + endif +endif ifeq ($(VNC), y) -LIBS += $(VNCLIB) -lws2_32 + LIBS += $(VNCLIB) -lws2_32 +endif +ifeq ($(CLANG), y) + LIBS += -lpng -lz -lwsock32 -liphlpapi -lpsapi -lhid -lsetupapi -luxtheme -static -lstdc++.dll +else + LIBS += -lpng -lz -lwsock32 -liphlpapi -lpsapi -lhid -lsetupapi -luxtheme -static -lstdc++ endif -LIBS += -lpng -lz -lwsock32 -lshell32 -liphlpapi -lpsapi -lSDL2 -limm32 -lhid -lsetupapi -loleaut32 -luxtheme -lversion -lrtmidi -lwinmm -static -lstdc++ ifneq ($(X64), y) -ifneq ($(ARM64), y) -LIBS += -Wl,--large-address-aware -endif + ifneq ($(ARM64), y) + LIBS += -Wl,--large-address-aware + endif endif ifeq ($(ARM64), y) -LIBS += -lgcc + LIBS += -lgcc endif ifeq ($(DINPUT), y) - LIBS += -ldinput8 + LIBS += -ldinput8 endif -LIBS += -static +LIBS += -static # Build module rules. ifeq ($(AUTODEP), y) -%.o: %.c - @echo $< - @$(CC) $(CFLAGS) $(DEPS) -c $< +%.o: %.c + @echo $< + @$(CC) $(CFLAGS) $(DEPS) -c $< -%.o: %.cc - @echo $< - @$(CPP) $(CXXFLAGS) $(DEPS) -c $< +%.o: %.cc + @echo $< + @$(CPP) $(CXXFLAGS) $(DEPS) -c $< -%.o: %.cpp - @echo $< - @$(CPP) $(CXXFLAGS) $(DEPS) -c $< +%.o: %.cpp + @echo $< + @$(CPP) $(CXXFLAGS) $(DEPS) -c $< else -%.o: %.c - @echo $< - @$(CC) $(CFLAGS) -c $< +%.o: %.c + @echo $< + @$(CC) $(CFLAGS) -c $< -%.o: %.cc - @echo $< - @$(CPP) $(CXXFLAGS) -c $< +%.o: %.cc + @echo $< + @$(CPP) $(CXXFLAGS) -c $< -%.o: %.cpp - @echo $< - @$(CPP) $(CXXFLAGS) -c $< +%.o: %.cpp + @echo $< + @$(CPP) $(CXXFLAGS) -c $< -%.d: %.c $(wildcard $*.d) - @echo $< - @$(CC) $(CFLAGS) $(DEPS) -E $< >/dev/null +%.d: %.c $(wildcard $*.d) + @echo $< + @$(CC) $(CFLAGS) $(DEPS) -E $< >/dev/null -%.d: %.cc $(wildcard $*.d) - @echo $< - @$(CPP) $(CXXFLAGS) $(DEPS) -E $< >/dev/null +%.d: %.cc $(wildcard $*.d) + @echo $< + @$(CPP) $(CXXFLAGS) $(DEPS) -E $< >/dev/null -%.d: %.cpp $(wildcard $*.d) - @echo $< - @$(CPP) $(CXXFLAGS) $(DEPS) -E $< >/dev/null +%.d: %.cpp $(wildcard $*.d) + @echo $< + @$(CPP) $(CXXFLAGS) $(DEPS) -E $< >/dev/null endif # Suppress false positive warnings in vid_voodoo_codegen_x86[-64].h @@ -810,59 +909,59 @@ ifneq ($(CLANG), y) $(VOODOOOBJ): CFLAGS += -Wstringop-overflow=0 endif -all: $(PROG).exe +all: $(PROG).exe -86Box.res: 86Box.rc - @echo Processing $< - @$(WINDRES) $(RFLAGS) $(EXTRAS) -i $< -o 86Box.res +86Box.res: 86Box.rc + @echo Processing $< + @$(WINDRES) -v $(RFLAGS) $(EXTRAS) -i $< -o 86Box.res -$(PROG).exe: $(OBJ) 86Box.res - @echo Linking $(PROG).exe .. - @$(CC) $(LDFLAGS) -o $(PROG).exe $(OBJ) 86Box.res $(LIBS) -pipe +$(PROG).exe: $(OBJ) 86Box.res + @echo Linking $(PROG).exe .. + @$(CC) $(LDFLAGS) -o $(PROG).exe $(OBJ) 86Box.res $(LIBS) -pipe ifneq ($(DEBUG), y) - @$(STRIP) $(PROG).exe + @$(STRIP) $(PROG).exe endif -pcap_if.res: pcap_if.rc - @echo Processing $< - @$(WINDRES) $(RFLAGS) -i $< -o pcap_if.res +pcap_if.res: pcap_if.rc + @echo Processing $< + @$(WINDRES) $(RFLAGS) -i $< -o pcap_if.res -pcap_if.exe: pcap_if.o win_dynld.o pcap_if.res - @echo Linking pcap_if.exe .. - @$(CC) $(LDFLAGS) -o pcap_if.exe pcap_if.o win_dynld.o pcap_if.res +pcap_if.exe: pcap_if.o win_dynld.o pcap_if.res + @echo Linking pcap_if.exe .. + @$(CC) $(LDFLAGS) -o pcap_if.exe pcap_if.o win_dynld.o pcap_if.res ifneq ($(DEBUG), y) - @$(STRIP) pcap_if.exe + @$(STRIP) pcap_if.exe endif -hello.exe: hello.o - $(CXX) $(LDFLAGS) -o hello.exe hello.o $(LIBS) +hello.exe: hello.o + $(CXX) $(LDFLAGS) -o hello.exe hello.o $(LIBS) ifneq ($(DEBUG), y) - @$(STRIP) hello.exe + @$(STRIP) hello.exe endif clean: - @echo Cleaning objects.. - @-rm -f *.o 2>/dev/null - @-rm -f *.res 2>/dev/null + @echo Cleaning objects.. + @-rm -f *.o 2>/dev/null + @-rm -f *.res 2>/dev/null -clobber: clean - @echo Cleaning executables.. - @-rm -f *.d 2>/dev/null - @-rm -f *.exe 2>/dev/null -# @-rm -f $(DEPFILE) 2>/dev/null +clobber: clean + @echo Cleaning executables.. + @-rm -f *.d 2>/dev/null + @-rm -f *.exe 2>/dev/null +# @-rm -f $(DEPFILE) 2>/dev/null ifneq ($(AUTODEP), y) depclean: - @-rm -f $(DEPFILE) 2>/dev/null - @echo Creating dependencies.. - @echo # Run "make depends" to re-create this file. >$(DEPFILE) + @-rm -f $(DEPFILE) 2>/dev/null + @echo Creating dependencies.. + @echo # Run "make depends" to re-create this file. >$(DEPFILE) -depends: DEPOBJ=$(OBJ:%.o=%.d) -depends: depclean $(OBJ:%.o=%.d) - @-cat $(DEPOBJ) >>$(DEPFILE) - @-rm -f $(DEPOBJ) +depends: DEPOBJ=$(OBJ:%.o=%.d) +depends: depclean $(OBJ:%.o=%.d) + @-cat $(DEPOBJ) >>$(DEPFILE) + @-rm -f $(DEPOBJ) $(DEPFILE): endif diff --git a/src/win/glad.c b/src/win/glad.c index 8e2e4ce13..7c282ebee 100644 --- a/src/win/glad.c +++ b/src/win/glad.c @@ -1,6 +1,6 @@ /* - OpenGL loader generated by glad 0.1.34 on Sat Dec 4 18:46:02 2021. + OpenGL loader generated by glad 0.1.36 on Sat Jan 7 18:24:33 2023. Language/Generator: C/C++ Specification: gl @@ -26,119 +26,125 @@ #include #include -static void* get_proc(const char *namez); +static void *get_proc(const char *namez); #if defined(_WIN32) || defined(__CYGWIN__) -#ifndef _WINDOWS_ -#undef APIENTRY -#endif -#include +# ifndef _WINDOWS_ +# undef APIENTRY +# endif +# include static HMODULE libGL; -typedef void* (APIENTRYP PFNWGLGETPROCADDRESSPROC_PRIVATE)(const char*); +typedef void *(APIENTRYP PFNWGLGETPROCADDRESSPROC_PRIVATE)(const char *); static PFNWGLGETPROCADDRESSPROC_PRIVATE gladGetProcAddressPtr; -#ifdef _MSC_VER -#ifdef __has_include - #if __has_include() - #define HAVE_WINAPIFAMILY 1 - #endif -#elif _MSC_VER >= 1700 && !_USING_V110_SDK71_ - #define HAVE_WINAPIFAMILY 1 -#endif -#endif +# ifdef _MSC_VER +# ifdef __has_include +# if __has_include() +# define HAVE_WINAPIFAMILY 1 +# endif +# elif _MSC_VER >= 1700 && !_USING_V110_SDK71_ +# define HAVE_WINAPIFAMILY 1 +# endif +# endif -#ifdef HAVE_WINAPIFAMILY - #include - #if !WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_DESKTOP) && WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_APP) - #define IS_UWP 1 - #endif -#endif +# ifdef HAVE_WINAPIFAMILY +# include +# if !WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_DESKTOP) && WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_APP) +# define IS_UWP 1 +# endif +# endif -static -int open_gl(void) { -#ifndef IS_UWP +static int +open_gl(void) +{ +# ifndef IS_UWP libGL = LoadLibraryW(L"opengl32.dll"); - if(libGL != NULL) { - void (* tmp)(void); - tmp = (void(*)(void)) GetProcAddress(libGL, "wglGetProcAddress"); + if (libGL != NULL) { + void (*tmp)(void); + tmp = (void (*)(void)) GetProcAddress(libGL, "wglGetProcAddress"); gladGetProcAddressPtr = (PFNWGLGETPROCADDRESSPROC_PRIVATE) tmp; return gladGetProcAddressPtr != NULL; } -#endif +# endif return 0; } -static -void close_gl(void) { - if(libGL != NULL) { +static void +close_gl(void) +{ + if (libGL != NULL) { FreeLibrary((HMODULE) libGL); libGL = NULL; } } #else -#include -static void* libGL; +# include +static void *libGL; -#if !defined(__APPLE__) && !defined(__HAIKU__) -typedef void* (APIENTRYP PFNGLXGETPROCADDRESSPROC_PRIVATE)(const char*); +# if !defined(__APPLE__) && !defined(__HAIKU__) +typedef void *(APIENTRYP PFNGLXGETPROCADDRESSPROC_PRIVATE)(const char *); static PFNGLXGETPROCADDRESSPROC_PRIVATE gladGetProcAddressPtr; -#endif +# endif -static -int open_gl(void) { -#ifdef __APPLE__ +static int +open_gl(void) +{ +# ifdef __APPLE__ static const char *NAMES[] = { "../Frameworks/OpenGL.framework/OpenGL", "/Library/Frameworks/OpenGL.framework/OpenGL", "/System/Library/Frameworks/OpenGL.framework/OpenGL", "/System/Library/Frameworks/OpenGL.framework/Versions/Current/OpenGL" }; -#else - static const char *NAMES[] = {"libGL.so.1", "libGL.so"}; -#endif +# else + static const char *NAMES[] = { "libGL.so.1", "libGL.so" }; +# endif unsigned int index = 0; - for(index = 0; index < (sizeof(NAMES) / sizeof(NAMES[0])); index++) { + for (index = 0; index < (sizeof(NAMES) / sizeof(NAMES[0])); index++) { libGL = dlopen(NAMES[index], RTLD_NOW | RTLD_GLOBAL); - if(libGL != NULL) { -#if defined(__APPLE__) || defined(__HAIKU__) + if (libGL != NULL) { +# if defined(__APPLE__) || defined(__HAIKU__) return 1; -#else - gladGetProcAddressPtr = (PFNGLXGETPROCADDRESSPROC_PRIVATE)dlsym(libGL, - "glXGetProcAddressARB"); +# else + gladGetProcAddressPtr = (PFNGLXGETPROCADDRESSPROC_PRIVATE) dlsym(libGL, + "glXGetProcAddressARB"); return gladGetProcAddressPtr != NULL; -#endif +# endif } } return 0; } -static -void close_gl(void) { - if(libGL != NULL) { +static void +close_gl(void) +{ + if (libGL != NULL) { dlclose(libGL); libGL = NULL; } } #endif -static -void* get_proc(const char *namez) { - void* result = NULL; - if(libGL == NULL) return NULL; +static void * +get_proc(const char *namez) +{ + void *result = NULL; + if (libGL == NULL) + return NULL; #if !defined(__APPLE__) && !defined(__HAIKU__) - if(gladGetProcAddressPtr != NULL) { + if (gladGetProcAddressPtr != NULL) { result = gladGetProcAddressPtr(namez); } #endif - if(result == NULL) { + if (result == NULL) { #if defined(_WIN32) || defined(__CYGWIN__) - result = (void*)GetProcAddress((HMODULE) libGL, namez); + result = (void *) GetProcAddress((HMODULE) libGL, namez); #else result = dlsym(libGL, namez); #endif @@ -147,10 +153,12 @@ void* get_proc(const char *namez) { return result; } -int gladLoadGL(void) { +int +gladLoadGL(void) +{ int status = 0; - if(open_gl()) { + if (open_gl()) { status = gladLoadGLLoader(&get_proc); close_gl(); } @@ -161,21 +169,23 @@ int gladLoadGL(void) { struct gladGLversionStruct GLVersion = { 0, 0 }; #if defined(GL_ES_VERSION_3_0) || defined(GL_VERSION_3_0) -#define _GLAD_IS_SOME_NEW_VERSION 1 +# define _GLAD_IS_SOME_NEW_VERSION 1 #endif static int max_loaded_major; static int max_loaded_minor; -static const char *exts = NULL; -static int num_exts_i = 0; -static char **exts_i = NULL; +static const char *exts = NULL; +static int num_exts_i = 0; +static char **exts_i = NULL; -static int get_exts(void) { +static int +get_exts(void) +{ #ifdef _GLAD_IS_SOME_NEW_VERSION - if(max_loaded_major < 3) { + if (max_loaded_major < 3) { #endif - exts = (const char *)glGetString(GL_EXTENSIONS); + exts = (const char *) glGetString(GL_EXTENSIONS); #ifdef _GLAD_IS_SOME_NEW_VERSION } else { unsigned int index; @@ -183,20 +193,20 @@ static int get_exts(void) { num_exts_i = 0; glGetIntegerv(GL_NUM_EXTENSIONS, &num_exts_i); if (num_exts_i > 0) { - exts_i = (char **)malloc((size_t)num_exts_i * (sizeof *exts_i)); + exts_i = (char **) malloc((size_t) num_exts_i * (sizeof *exts_i)); } if (exts_i == NULL) { return 0; } - for(index = 0; index < (unsigned)num_exts_i; index++) { - const char *gl_str_tmp = (const char*)glGetStringi(GL_EXTENSIONS, index); - size_t len = strlen(gl_str_tmp); + for (index = 0; index < (unsigned) num_exts_i; index++) { + const char *gl_str_tmp = (const char *) glGetStringi(GL_EXTENSIONS, index); + size_t len = strlen(gl_str_tmp); - char *local_str = (char*)malloc((len+1) * sizeof(char)); - if(local_str != NULL) { - memcpy(local_str, gl_str_tmp, (len+1) * sizeof(char)); + char *local_str = (char *) malloc((len + 1) * sizeof(char)); + if (local_str != NULL) { + memcpy(local_str, gl_str_tmp, (len + 1) * sizeof(char)); } exts_i[index] = local_str; } @@ -205,38 +215,41 @@ static int get_exts(void) { return 1; } -static void free_exts(void) { +static void +free_exts(void) +{ if (exts_i != NULL) { int index; - for(index = 0; index < num_exts_i; index++) { - free((char *)exts_i[index]); + for (index = 0; index < num_exts_i; index++) { + free((char *) exts_i[index]); } - free((void *)exts_i); + free((void *) exts_i); exts_i = NULL; } } -static int has_ext(const char *ext) { +static int +has_ext(const char *ext) +{ #ifdef _GLAD_IS_SOME_NEW_VERSION - if(max_loaded_major < 3) { + if (max_loaded_major < 3) { #endif const char *extensions; const char *loc; const char *terminator; extensions = exts; - if(extensions == NULL || ext == NULL) { + if (extensions == NULL || ext == NULL) { return 0; } - while(1) { + while (1) { loc = strstr(extensions, ext); - if(loc == NULL) { + if (loc == NULL) { return 0; } terminator = loc + strlen(ext); - if((loc == extensions || *(loc - 1) == ' ') && - (*terminator == ' ' || *terminator == '\0')) { + if ((loc == extensions || *(loc - 1) == ' ') && (*terminator == ' ' || *terminator == '\0')) { return 1; } extensions = terminator; @@ -244,11 +257,12 @@ static int has_ext(const char *ext) { #ifdef _GLAD_IS_SOME_NEW_VERSION } else { int index; - if(exts_i == NULL) return 0; - for(index = 0; index < num_exts_i; index++) { + if (exts_i == NULL) + return 0; + for (index = 0; index < num_exts_i; index++) { const char *e = exts_i[index]; - if(exts_i[index] != NULL && strcmp(e, ext) == 0) { + if (exts_i[index] != NULL && strcmp(e, ext) == 0) { return 1; } } @@ -257,658 +271,699 @@ static int has_ext(const char *ext) { return 0; } -int GLAD_GL_VERSION_1_0 = 0; -int GLAD_GL_VERSION_1_1 = 0; -int GLAD_GL_VERSION_1_2 = 0; -int GLAD_GL_VERSION_1_3 = 0; -int GLAD_GL_VERSION_1_4 = 0; -int GLAD_GL_VERSION_1_5 = 0; -int GLAD_GL_VERSION_2_0 = 0; -int GLAD_GL_VERSION_2_1 = 0; -int GLAD_GL_VERSION_3_0 = 0; -PFNGLACTIVETEXTUREPROC glad_glActiveTexture = NULL; -PFNGLATTACHSHADERPROC glad_glAttachShader = NULL; -PFNGLBEGINCONDITIONALRENDERPROC glad_glBeginConditionalRender = NULL; -PFNGLBEGINQUERYPROC glad_glBeginQuery = NULL; -PFNGLBEGINTRANSFORMFEEDBACKPROC glad_glBeginTransformFeedback = NULL; -PFNGLBINDATTRIBLOCATIONPROC glad_glBindAttribLocation = NULL; -PFNGLBINDBUFFERPROC glad_glBindBuffer = NULL; -PFNGLBINDBUFFERBASEPROC glad_glBindBufferBase = NULL; -PFNGLBINDBUFFERRANGEPROC glad_glBindBufferRange = NULL; -PFNGLBINDFRAGDATALOCATIONPROC glad_glBindFragDataLocation = NULL; -PFNGLBINDFRAMEBUFFERPROC glad_glBindFramebuffer = NULL; -PFNGLBINDRENDERBUFFERPROC glad_glBindRenderbuffer = NULL; -PFNGLBINDTEXTUREPROC glad_glBindTexture = NULL; -PFNGLBINDVERTEXARRAYPROC glad_glBindVertexArray = NULL; -PFNGLBLENDCOLORPROC glad_glBlendColor = NULL; -PFNGLBLENDEQUATIONPROC glad_glBlendEquation = NULL; -PFNGLBLENDEQUATIONSEPARATEPROC glad_glBlendEquationSeparate = NULL; -PFNGLBLENDFUNCPROC glad_glBlendFunc = NULL; -PFNGLBLENDFUNCSEPARATEPROC glad_glBlendFuncSeparate = NULL; -PFNGLBLITFRAMEBUFFERPROC glad_glBlitFramebuffer = NULL; -PFNGLBUFFERDATAPROC glad_glBufferData = NULL; -PFNGLBUFFERSUBDATAPROC glad_glBufferSubData = NULL; -PFNGLCHECKFRAMEBUFFERSTATUSPROC glad_glCheckFramebufferStatus = NULL; -PFNGLCLAMPCOLORPROC glad_glClampColor = NULL; -PFNGLCLEARPROC glad_glClear = NULL; -PFNGLCLEARBUFFERFIPROC glad_glClearBufferfi = NULL; -PFNGLCLEARBUFFERFVPROC glad_glClearBufferfv = NULL; -PFNGLCLEARBUFFERIVPROC glad_glClearBufferiv = NULL; -PFNGLCLEARBUFFERUIVPROC glad_glClearBufferuiv = NULL; -PFNGLCLEARCOLORPROC glad_glClearColor = NULL; -PFNGLCLEARDEPTHPROC glad_glClearDepth = NULL; -PFNGLCLEARSTENCILPROC glad_glClearStencil = NULL; -PFNGLCOLORMASKPROC glad_glColorMask = NULL; -PFNGLCOLORMASKIPROC glad_glColorMaski = NULL; -PFNGLCOMPILESHADERPROC glad_glCompileShader = NULL; -PFNGLCOMPRESSEDTEXIMAGE1DPROC glad_glCompressedTexImage1D = NULL; -PFNGLCOMPRESSEDTEXIMAGE2DPROC glad_glCompressedTexImage2D = NULL; -PFNGLCOMPRESSEDTEXIMAGE3DPROC glad_glCompressedTexImage3D = NULL; -PFNGLCOMPRESSEDTEXSUBIMAGE1DPROC glad_glCompressedTexSubImage1D = NULL; -PFNGLCOMPRESSEDTEXSUBIMAGE2DPROC glad_glCompressedTexSubImage2D = NULL; -PFNGLCOMPRESSEDTEXSUBIMAGE3DPROC glad_glCompressedTexSubImage3D = NULL; -PFNGLCOPYTEXIMAGE1DPROC glad_glCopyTexImage1D = NULL; -PFNGLCOPYTEXIMAGE2DPROC glad_glCopyTexImage2D = NULL; -PFNGLCOPYTEXSUBIMAGE1DPROC glad_glCopyTexSubImage1D = NULL; -PFNGLCOPYTEXSUBIMAGE2DPROC glad_glCopyTexSubImage2D = NULL; -PFNGLCOPYTEXSUBIMAGE3DPROC glad_glCopyTexSubImage3D = NULL; -PFNGLCREATEPROGRAMPROC glad_glCreateProgram = NULL; -PFNGLCREATESHADERPROC glad_glCreateShader = NULL; -PFNGLCULLFACEPROC glad_glCullFace = NULL; -PFNGLDELETEBUFFERSPROC glad_glDeleteBuffers = NULL; -PFNGLDELETEFRAMEBUFFERSPROC glad_glDeleteFramebuffers = NULL; -PFNGLDELETEPROGRAMPROC glad_glDeleteProgram = NULL; -PFNGLDELETEQUERIESPROC glad_glDeleteQueries = NULL; -PFNGLDELETERENDERBUFFERSPROC glad_glDeleteRenderbuffers = NULL; -PFNGLDELETESHADERPROC glad_glDeleteShader = NULL; -PFNGLDELETETEXTURESPROC glad_glDeleteTextures = NULL; -PFNGLDELETEVERTEXARRAYSPROC glad_glDeleteVertexArrays = NULL; -PFNGLDEPTHFUNCPROC glad_glDepthFunc = NULL; -PFNGLDEPTHMASKPROC glad_glDepthMask = NULL; -PFNGLDEPTHRANGEPROC glad_glDepthRange = NULL; -PFNGLDETACHSHADERPROC glad_glDetachShader = NULL; -PFNGLDISABLEPROC glad_glDisable = NULL; -PFNGLDISABLEVERTEXATTRIBARRAYPROC glad_glDisableVertexAttribArray = NULL; -PFNGLDISABLEIPROC glad_glDisablei = NULL; -PFNGLDRAWARRAYSPROC glad_glDrawArrays = NULL; -PFNGLDRAWBUFFERPROC glad_glDrawBuffer = NULL; -PFNGLDRAWBUFFERSPROC glad_glDrawBuffers = NULL; -PFNGLDRAWELEMENTSPROC glad_glDrawElements = NULL; -PFNGLDRAWRANGEELEMENTSPROC glad_glDrawRangeElements = NULL; -PFNGLENABLEPROC glad_glEnable = NULL; -PFNGLENABLEVERTEXATTRIBARRAYPROC glad_glEnableVertexAttribArray = NULL; -PFNGLENABLEIPROC glad_glEnablei = NULL; -PFNGLENDCONDITIONALRENDERPROC glad_glEndConditionalRender = NULL; -PFNGLENDQUERYPROC glad_glEndQuery = NULL; -PFNGLENDTRANSFORMFEEDBACKPROC glad_glEndTransformFeedback = NULL; -PFNGLFINISHPROC glad_glFinish = NULL; -PFNGLFLUSHPROC glad_glFlush = NULL; -PFNGLFLUSHMAPPEDBUFFERRANGEPROC glad_glFlushMappedBufferRange = NULL; -PFNGLFRAMEBUFFERRENDERBUFFERPROC glad_glFramebufferRenderbuffer = NULL; -PFNGLFRAMEBUFFERTEXTURE1DPROC glad_glFramebufferTexture1D = NULL; -PFNGLFRAMEBUFFERTEXTURE2DPROC glad_glFramebufferTexture2D = NULL; -PFNGLFRAMEBUFFERTEXTURE3DPROC glad_glFramebufferTexture3D = NULL; -PFNGLFRAMEBUFFERTEXTURELAYERPROC glad_glFramebufferTextureLayer = NULL; -PFNGLFRONTFACEPROC glad_glFrontFace = NULL; -PFNGLGENBUFFERSPROC glad_glGenBuffers = NULL; -PFNGLGENFRAMEBUFFERSPROC glad_glGenFramebuffers = NULL; -PFNGLGENQUERIESPROC glad_glGenQueries = NULL; -PFNGLGENRENDERBUFFERSPROC glad_glGenRenderbuffers = NULL; -PFNGLGENTEXTURESPROC glad_glGenTextures = NULL; -PFNGLGENVERTEXARRAYSPROC glad_glGenVertexArrays = NULL; -PFNGLGENERATEMIPMAPPROC glad_glGenerateMipmap = NULL; -PFNGLGETACTIVEATTRIBPROC glad_glGetActiveAttrib = NULL; -PFNGLGETACTIVEUNIFORMPROC glad_glGetActiveUniform = NULL; -PFNGLGETATTACHEDSHADERSPROC glad_glGetAttachedShaders = NULL; -PFNGLGETATTRIBLOCATIONPROC glad_glGetAttribLocation = NULL; -PFNGLGETBOOLEANI_VPROC glad_glGetBooleani_v = NULL; -PFNGLGETBOOLEANVPROC glad_glGetBooleanv = NULL; -PFNGLGETBUFFERPARAMETERIVPROC glad_glGetBufferParameteriv = NULL; -PFNGLGETBUFFERPOINTERVPROC glad_glGetBufferPointerv = NULL; -PFNGLGETBUFFERSUBDATAPROC glad_glGetBufferSubData = NULL; -PFNGLGETCOMPRESSEDTEXIMAGEPROC glad_glGetCompressedTexImage = NULL; -PFNGLGETDOUBLEVPROC glad_glGetDoublev = NULL; -PFNGLGETERRORPROC glad_glGetError = NULL; -PFNGLGETFLOATVPROC glad_glGetFloatv = NULL; -PFNGLGETFRAGDATALOCATIONPROC glad_glGetFragDataLocation = NULL; +int GLAD_GL_VERSION_1_0 = 0; +int GLAD_GL_VERSION_1_1 = 0; +int GLAD_GL_VERSION_1_2 = 0; +int GLAD_GL_VERSION_1_3 = 0; +int GLAD_GL_VERSION_1_4 = 0; +int GLAD_GL_VERSION_1_5 = 0; +int GLAD_GL_VERSION_2_0 = 0; +int GLAD_GL_VERSION_2_1 = 0; +int GLAD_GL_VERSION_3_0 = 0; +PFNGLACTIVETEXTUREPROC glad_glActiveTexture = NULL; +PFNGLATTACHSHADERPROC glad_glAttachShader = NULL; +PFNGLBEGINCONDITIONALRENDERPROC glad_glBeginConditionalRender = NULL; +PFNGLBEGINQUERYPROC glad_glBeginQuery = NULL; +PFNGLBEGINTRANSFORMFEEDBACKPROC glad_glBeginTransformFeedback = NULL; +PFNGLBINDATTRIBLOCATIONPROC glad_glBindAttribLocation = NULL; +PFNGLBINDBUFFERPROC glad_glBindBuffer = NULL; +PFNGLBINDBUFFERBASEPROC glad_glBindBufferBase = NULL; +PFNGLBINDBUFFERRANGEPROC glad_glBindBufferRange = NULL; +PFNGLBINDFRAGDATALOCATIONPROC glad_glBindFragDataLocation = NULL; +PFNGLBINDFRAMEBUFFERPROC glad_glBindFramebuffer = NULL; +PFNGLBINDRENDERBUFFERPROC glad_glBindRenderbuffer = NULL; +PFNGLBINDTEXTUREPROC glad_glBindTexture = NULL; +PFNGLBINDVERTEXARRAYPROC glad_glBindVertexArray = NULL; +PFNGLBLENDCOLORPROC glad_glBlendColor = NULL; +PFNGLBLENDEQUATIONPROC glad_glBlendEquation = NULL; +PFNGLBLENDEQUATIONSEPARATEPROC glad_glBlendEquationSeparate = NULL; +PFNGLBLENDFUNCPROC glad_glBlendFunc = NULL; +PFNGLBLENDFUNCSEPARATEPROC glad_glBlendFuncSeparate = NULL; +PFNGLBLITFRAMEBUFFERPROC glad_glBlitFramebuffer = NULL; +PFNGLBUFFERDATAPROC glad_glBufferData = NULL; +PFNGLBUFFERSUBDATAPROC glad_glBufferSubData = NULL; +PFNGLCHECKFRAMEBUFFERSTATUSPROC glad_glCheckFramebufferStatus = NULL; +PFNGLCLAMPCOLORPROC glad_glClampColor = NULL; +PFNGLCLEARPROC glad_glClear = NULL; +PFNGLCLEARBUFFERFIPROC glad_glClearBufferfi = NULL; +PFNGLCLEARBUFFERFVPROC glad_glClearBufferfv = NULL; +PFNGLCLEARBUFFERIVPROC glad_glClearBufferiv = NULL; +PFNGLCLEARBUFFERUIVPROC glad_glClearBufferuiv = NULL; +PFNGLCLEARCOLORPROC glad_glClearColor = NULL; +PFNGLCLEARDEPTHPROC glad_glClearDepth = NULL; +PFNGLCLEARSTENCILPROC glad_glClearStencil = NULL; +PFNGLCOLORMASKPROC glad_glColorMask = NULL; +PFNGLCOLORMASKIPROC glad_glColorMaski = NULL; +PFNGLCOMPILESHADERPROC glad_glCompileShader = NULL; +PFNGLCOMPRESSEDTEXIMAGE1DPROC glad_glCompressedTexImage1D = NULL; +PFNGLCOMPRESSEDTEXIMAGE2DPROC glad_glCompressedTexImage2D = NULL; +PFNGLCOMPRESSEDTEXIMAGE3DPROC glad_glCompressedTexImage3D = NULL; +PFNGLCOMPRESSEDTEXSUBIMAGE1DPROC glad_glCompressedTexSubImage1D = NULL; +PFNGLCOMPRESSEDTEXSUBIMAGE2DPROC glad_glCompressedTexSubImage2D = NULL; +PFNGLCOMPRESSEDTEXSUBIMAGE3DPROC glad_glCompressedTexSubImage3D = NULL; +PFNGLCOPYTEXIMAGE1DPROC glad_glCopyTexImage1D = NULL; +PFNGLCOPYTEXIMAGE2DPROC glad_glCopyTexImage2D = NULL; +PFNGLCOPYTEXSUBIMAGE1DPROC glad_glCopyTexSubImage1D = NULL; +PFNGLCOPYTEXSUBIMAGE2DPROC glad_glCopyTexSubImage2D = NULL; +PFNGLCOPYTEXSUBIMAGE3DPROC glad_glCopyTexSubImage3D = NULL; +PFNGLCREATEPROGRAMPROC glad_glCreateProgram = NULL; +PFNGLCREATESHADERPROC glad_glCreateShader = NULL; +PFNGLCULLFACEPROC glad_glCullFace = NULL; +PFNGLDELETEBUFFERSPROC glad_glDeleteBuffers = NULL; +PFNGLDELETEFRAMEBUFFERSPROC glad_glDeleteFramebuffers = NULL; +PFNGLDELETEPROGRAMPROC glad_glDeleteProgram = NULL; +PFNGLDELETEQUERIESPROC glad_glDeleteQueries = NULL; +PFNGLDELETERENDERBUFFERSPROC glad_glDeleteRenderbuffers = NULL; +PFNGLDELETESHADERPROC glad_glDeleteShader = NULL; +PFNGLDELETETEXTURESPROC glad_glDeleteTextures = NULL; +PFNGLDELETEVERTEXARRAYSPROC glad_glDeleteVertexArrays = NULL; +PFNGLDEPTHFUNCPROC glad_glDepthFunc = NULL; +PFNGLDEPTHMASKPROC glad_glDepthMask = NULL; +PFNGLDEPTHRANGEPROC glad_glDepthRange = NULL; +PFNGLDETACHSHADERPROC glad_glDetachShader = NULL; +PFNGLDISABLEPROC glad_glDisable = NULL; +PFNGLDISABLEVERTEXATTRIBARRAYPROC glad_glDisableVertexAttribArray = NULL; +PFNGLDISABLEIPROC glad_glDisablei = NULL; +PFNGLDRAWARRAYSPROC glad_glDrawArrays = NULL; +PFNGLDRAWBUFFERPROC glad_glDrawBuffer = NULL; +PFNGLDRAWBUFFERSPROC glad_glDrawBuffers = NULL; +PFNGLDRAWELEMENTSPROC glad_glDrawElements = NULL; +PFNGLDRAWRANGEELEMENTSPROC glad_glDrawRangeElements = NULL; +PFNGLENABLEPROC glad_glEnable = NULL; +PFNGLENABLEVERTEXATTRIBARRAYPROC glad_glEnableVertexAttribArray = NULL; +PFNGLENABLEIPROC glad_glEnablei = NULL; +PFNGLENDCONDITIONALRENDERPROC glad_glEndConditionalRender = NULL; +PFNGLENDQUERYPROC glad_glEndQuery = NULL; +PFNGLENDTRANSFORMFEEDBACKPROC glad_glEndTransformFeedback = NULL; +PFNGLFINISHPROC glad_glFinish = NULL; +PFNGLFLUSHPROC glad_glFlush = NULL; +PFNGLFLUSHMAPPEDBUFFERRANGEPROC glad_glFlushMappedBufferRange = NULL; +PFNGLFRAMEBUFFERRENDERBUFFERPROC glad_glFramebufferRenderbuffer = NULL; +PFNGLFRAMEBUFFERTEXTURE1DPROC glad_glFramebufferTexture1D = NULL; +PFNGLFRAMEBUFFERTEXTURE2DPROC glad_glFramebufferTexture2D = NULL; +PFNGLFRAMEBUFFERTEXTURE3DPROC glad_glFramebufferTexture3D = NULL; +PFNGLFRAMEBUFFERTEXTURELAYERPROC glad_glFramebufferTextureLayer = NULL; +PFNGLFRONTFACEPROC glad_glFrontFace = NULL; +PFNGLGENBUFFERSPROC glad_glGenBuffers = NULL; +PFNGLGENFRAMEBUFFERSPROC glad_glGenFramebuffers = NULL; +PFNGLGENQUERIESPROC glad_glGenQueries = NULL; +PFNGLGENRENDERBUFFERSPROC glad_glGenRenderbuffers = NULL; +PFNGLGENTEXTURESPROC glad_glGenTextures = NULL; +PFNGLGENVERTEXARRAYSPROC glad_glGenVertexArrays = NULL; +PFNGLGENERATEMIPMAPPROC glad_glGenerateMipmap = NULL; +PFNGLGETACTIVEATTRIBPROC glad_glGetActiveAttrib = NULL; +PFNGLGETACTIVEUNIFORMPROC glad_glGetActiveUniform = NULL; +PFNGLGETATTACHEDSHADERSPROC glad_glGetAttachedShaders = NULL; +PFNGLGETATTRIBLOCATIONPROC glad_glGetAttribLocation = NULL; +PFNGLGETBOOLEANI_VPROC glad_glGetBooleani_v = NULL; +PFNGLGETBOOLEANVPROC glad_glGetBooleanv = NULL; +PFNGLGETBUFFERPARAMETERIVPROC glad_glGetBufferParameteriv = NULL; +PFNGLGETBUFFERPOINTERVPROC glad_glGetBufferPointerv = NULL; +PFNGLGETBUFFERSUBDATAPROC glad_glGetBufferSubData = NULL; +PFNGLGETCOMPRESSEDTEXIMAGEPROC glad_glGetCompressedTexImage = NULL; +PFNGLGETDOUBLEVPROC glad_glGetDoublev = NULL; +PFNGLGETERRORPROC glad_glGetError = NULL; +PFNGLGETFLOATVPROC glad_glGetFloatv = NULL; +PFNGLGETFRAGDATALOCATIONPROC glad_glGetFragDataLocation = NULL; PFNGLGETFRAMEBUFFERATTACHMENTPARAMETERIVPROC glad_glGetFramebufferAttachmentParameteriv = NULL; -PFNGLGETINTEGERI_VPROC glad_glGetIntegeri_v = NULL; -PFNGLGETINTEGERVPROC glad_glGetIntegerv = NULL; -PFNGLGETPROGRAMINFOLOGPROC glad_glGetProgramInfoLog = NULL; -PFNGLGETPROGRAMIVPROC glad_glGetProgramiv = NULL; -PFNGLGETQUERYOBJECTIVPROC glad_glGetQueryObjectiv = NULL; -PFNGLGETQUERYOBJECTUIVPROC glad_glGetQueryObjectuiv = NULL; -PFNGLGETQUERYIVPROC glad_glGetQueryiv = NULL; -PFNGLGETRENDERBUFFERPARAMETERIVPROC glad_glGetRenderbufferParameteriv = NULL; -PFNGLGETSHADERINFOLOGPROC glad_glGetShaderInfoLog = NULL; -PFNGLGETSHADERSOURCEPROC glad_glGetShaderSource = NULL; -PFNGLGETSHADERIVPROC glad_glGetShaderiv = NULL; -PFNGLGETSTRINGPROC glad_glGetString = NULL; -PFNGLGETSTRINGIPROC glad_glGetStringi = NULL; -PFNGLGETTEXIMAGEPROC glad_glGetTexImage = NULL; -PFNGLGETTEXLEVELPARAMETERFVPROC glad_glGetTexLevelParameterfv = NULL; -PFNGLGETTEXLEVELPARAMETERIVPROC glad_glGetTexLevelParameteriv = NULL; -PFNGLGETTEXPARAMETERIIVPROC glad_glGetTexParameterIiv = NULL; -PFNGLGETTEXPARAMETERIUIVPROC glad_glGetTexParameterIuiv = NULL; -PFNGLGETTEXPARAMETERFVPROC glad_glGetTexParameterfv = NULL; -PFNGLGETTEXPARAMETERIVPROC glad_glGetTexParameteriv = NULL; -PFNGLGETTRANSFORMFEEDBACKVARYINGPROC glad_glGetTransformFeedbackVarying = NULL; -PFNGLGETUNIFORMLOCATIONPROC glad_glGetUniformLocation = NULL; -PFNGLGETUNIFORMFVPROC glad_glGetUniformfv = NULL; -PFNGLGETUNIFORMIVPROC glad_glGetUniformiv = NULL; -PFNGLGETUNIFORMUIVPROC glad_glGetUniformuiv = NULL; -PFNGLGETVERTEXATTRIBIIVPROC glad_glGetVertexAttribIiv = NULL; -PFNGLGETVERTEXATTRIBIUIVPROC glad_glGetVertexAttribIuiv = NULL; -PFNGLGETVERTEXATTRIBPOINTERVPROC glad_glGetVertexAttribPointerv = NULL; -PFNGLGETVERTEXATTRIBDVPROC glad_glGetVertexAttribdv = NULL; -PFNGLGETVERTEXATTRIBFVPROC glad_glGetVertexAttribfv = NULL; -PFNGLGETVERTEXATTRIBIVPROC glad_glGetVertexAttribiv = NULL; -PFNGLHINTPROC glad_glHint = NULL; -PFNGLISBUFFERPROC glad_glIsBuffer = NULL; -PFNGLISENABLEDPROC glad_glIsEnabled = NULL; -PFNGLISENABLEDIPROC glad_glIsEnabledi = NULL; -PFNGLISFRAMEBUFFERPROC glad_glIsFramebuffer = NULL; -PFNGLISPROGRAMPROC glad_glIsProgram = NULL; -PFNGLISQUERYPROC glad_glIsQuery = NULL; -PFNGLISRENDERBUFFERPROC glad_glIsRenderbuffer = NULL; -PFNGLISSHADERPROC glad_glIsShader = NULL; -PFNGLISTEXTUREPROC glad_glIsTexture = NULL; -PFNGLISVERTEXARRAYPROC glad_glIsVertexArray = NULL; -PFNGLLINEWIDTHPROC glad_glLineWidth = NULL; -PFNGLLINKPROGRAMPROC glad_glLinkProgram = NULL; -PFNGLLOGICOPPROC glad_glLogicOp = NULL; -PFNGLMAPBUFFERPROC glad_glMapBuffer = NULL; -PFNGLMAPBUFFERRANGEPROC glad_glMapBufferRange = NULL; -PFNGLMULTIDRAWARRAYSPROC glad_glMultiDrawArrays = NULL; -PFNGLMULTIDRAWELEMENTSPROC glad_glMultiDrawElements = NULL; -PFNGLPIXELSTOREFPROC glad_glPixelStoref = NULL; -PFNGLPIXELSTOREIPROC glad_glPixelStorei = NULL; -PFNGLPOINTPARAMETERFPROC glad_glPointParameterf = NULL; -PFNGLPOINTPARAMETERFVPROC glad_glPointParameterfv = NULL; -PFNGLPOINTPARAMETERIPROC glad_glPointParameteri = NULL; -PFNGLPOINTPARAMETERIVPROC glad_glPointParameteriv = NULL; -PFNGLPOINTSIZEPROC glad_glPointSize = NULL; -PFNGLPOLYGONMODEPROC glad_glPolygonMode = NULL; -PFNGLPOLYGONOFFSETPROC glad_glPolygonOffset = NULL; -PFNGLREADBUFFERPROC glad_glReadBuffer = NULL; -PFNGLREADPIXELSPROC glad_glReadPixels = NULL; -PFNGLRENDERBUFFERSTORAGEPROC glad_glRenderbufferStorage = NULL; -PFNGLRENDERBUFFERSTORAGEMULTISAMPLEPROC glad_glRenderbufferStorageMultisample = NULL; -PFNGLSAMPLECOVERAGEPROC glad_glSampleCoverage = NULL; -PFNGLSCISSORPROC glad_glScissor = NULL; -PFNGLSHADERSOURCEPROC glad_glShaderSource = NULL; -PFNGLSTENCILFUNCPROC glad_glStencilFunc = NULL; -PFNGLSTENCILFUNCSEPARATEPROC glad_glStencilFuncSeparate = NULL; -PFNGLSTENCILMASKPROC glad_glStencilMask = NULL; -PFNGLSTENCILMASKSEPARATEPROC glad_glStencilMaskSeparate = NULL; -PFNGLSTENCILOPPROC glad_glStencilOp = NULL; -PFNGLSTENCILOPSEPARATEPROC glad_glStencilOpSeparate = NULL; -PFNGLTEXIMAGE1DPROC glad_glTexImage1D = NULL; -PFNGLTEXIMAGE2DPROC glad_glTexImage2D = NULL; -PFNGLTEXIMAGE3DPROC glad_glTexImage3D = NULL; -PFNGLTEXPARAMETERIIVPROC glad_glTexParameterIiv = NULL; -PFNGLTEXPARAMETERIUIVPROC glad_glTexParameterIuiv = NULL; -PFNGLTEXPARAMETERFPROC glad_glTexParameterf = NULL; -PFNGLTEXPARAMETERFVPROC glad_glTexParameterfv = NULL; -PFNGLTEXPARAMETERIPROC glad_glTexParameteri = NULL; -PFNGLTEXPARAMETERIVPROC glad_glTexParameteriv = NULL; -PFNGLTEXSUBIMAGE1DPROC glad_glTexSubImage1D = NULL; -PFNGLTEXSUBIMAGE2DPROC glad_glTexSubImage2D = NULL; -PFNGLTEXSUBIMAGE3DPROC glad_glTexSubImage3D = NULL; -PFNGLTRANSFORMFEEDBACKVARYINGSPROC glad_glTransformFeedbackVaryings = NULL; -PFNGLUNIFORM1FPROC glad_glUniform1f = NULL; -PFNGLUNIFORM1FVPROC glad_glUniform1fv = NULL; -PFNGLUNIFORM1IPROC glad_glUniform1i = NULL; -PFNGLUNIFORM1IVPROC glad_glUniform1iv = NULL; -PFNGLUNIFORM1UIPROC glad_glUniform1ui = NULL; -PFNGLUNIFORM1UIVPROC glad_glUniform1uiv = NULL; -PFNGLUNIFORM2FPROC glad_glUniform2f = NULL; -PFNGLUNIFORM2FVPROC glad_glUniform2fv = NULL; -PFNGLUNIFORM2IPROC glad_glUniform2i = NULL; -PFNGLUNIFORM2IVPROC glad_glUniform2iv = NULL; -PFNGLUNIFORM2UIPROC glad_glUniform2ui = NULL; -PFNGLUNIFORM2UIVPROC glad_glUniform2uiv = NULL; -PFNGLUNIFORM3FPROC glad_glUniform3f = NULL; -PFNGLUNIFORM3FVPROC glad_glUniform3fv = NULL; -PFNGLUNIFORM3IPROC glad_glUniform3i = NULL; -PFNGLUNIFORM3IVPROC glad_glUniform3iv = NULL; -PFNGLUNIFORM3UIPROC glad_glUniform3ui = NULL; -PFNGLUNIFORM3UIVPROC glad_glUniform3uiv = NULL; -PFNGLUNIFORM4FPROC glad_glUniform4f = NULL; -PFNGLUNIFORM4FVPROC glad_glUniform4fv = NULL; -PFNGLUNIFORM4IPROC glad_glUniform4i = NULL; -PFNGLUNIFORM4IVPROC glad_glUniform4iv = NULL; -PFNGLUNIFORM4UIPROC glad_glUniform4ui = NULL; -PFNGLUNIFORM4UIVPROC glad_glUniform4uiv = NULL; -PFNGLUNIFORMMATRIX2FVPROC glad_glUniformMatrix2fv = NULL; -PFNGLUNIFORMMATRIX2X3FVPROC glad_glUniformMatrix2x3fv = NULL; -PFNGLUNIFORMMATRIX2X4FVPROC glad_glUniformMatrix2x4fv = NULL; -PFNGLUNIFORMMATRIX3FVPROC glad_glUniformMatrix3fv = NULL; -PFNGLUNIFORMMATRIX3X2FVPROC glad_glUniformMatrix3x2fv = NULL; -PFNGLUNIFORMMATRIX3X4FVPROC glad_glUniformMatrix3x4fv = NULL; -PFNGLUNIFORMMATRIX4FVPROC glad_glUniformMatrix4fv = NULL; -PFNGLUNIFORMMATRIX4X2FVPROC glad_glUniformMatrix4x2fv = NULL; -PFNGLUNIFORMMATRIX4X3FVPROC glad_glUniformMatrix4x3fv = NULL; -PFNGLUNMAPBUFFERPROC glad_glUnmapBuffer = NULL; -PFNGLUSEPROGRAMPROC glad_glUseProgram = NULL; -PFNGLVALIDATEPROGRAMPROC glad_glValidateProgram = NULL; -PFNGLVERTEXATTRIB1DPROC glad_glVertexAttrib1d = NULL; -PFNGLVERTEXATTRIB1DVPROC glad_glVertexAttrib1dv = NULL; -PFNGLVERTEXATTRIB1FPROC glad_glVertexAttrib1f = NULL; -PFNGLVERTEXATTRIB1FVPROC glad_glVertexAttrib1fv = NULL; -PFNGLVERTEXATTRIB1SPROC glad_glVertexAttrib1s = NULL; -PFNGLVERTEXATTRIB1SVPROC glad_glVertexAttrib1sv = NULL; -PFNGLVERTEXATTRIB2DPROC glad_glVertexAttrib2d = NULL; -PFNGLVERTEXATTRIB2DVPROC glad_glVertexAttrib2dv = NULL; -PFNGLVERTEXATTRIB2FPROC glad_glVertexAttrib2f = NULL; -PFNGLVERTEXATTRIB2FVPROC glad_glVertexAttrib2fv = NULL; -PFNGLVERTEXATTRIB2SPROC glad_glVertexAttrib2s = NULL; -PFNGLVERTEXATTRIB2SVPROC glad_glVertexAttrib2sv = NULL; -PFNGLVERTEXATTRIB3DPROC glad_glVertexAttrib3d = NULL; -PFNGLVERTEXATTRIB3DVPROC glad_glVertexAttrib3dv = NULL; -PFNGLVERTEXATTRIB3FPROC glad_glVertexAttrib3f = NULL; -PFNGLVERTEXATTRIB3FVPROC glad_glVertexAttrib3fv = NULL; -PFNGLVERTEXATTRIB3SPROC glad_glVertexAttrib3s = NULL; -PFNGLVERTEXATTRIB3SVPROC glad_glVertexAttrib3sv = NULL; -PFNGLVERTEXATTRIB4NBVPROC glad_glVertexAttrib4Nbv = NULL; -PFNGLVERTEXATTRIB4NIVPROC glad_glVertexAttrib4Niv = NULL; -PFNGLVERTEXATTRIB4NSVPROC glad_glVertexAttrib4Nsv = NULL; -PFNGLVERTEXATTRIB4NUBPROC glad_glVertexAttrib4Nub = NULL; -PFNGLVERTEXATTRIB4NUBVPROC glad_glVertexAttrib4Nubv = NULL; -PFNGLVERTEXATTRIB4NUIVPROC glad_glVertexAttrib4Nuiv = NULL; -PFNGLVERTEXATTRIB4NUSVPROC glad_glVertexAttrib4Nusv = NULL; -PFNGLVERTEXATTRIB4BVPROC glad_glVertexAttrib4bv = NULL; -PFNGLVERTEXATTRIB4DPROC glad_glVertexAttrib4d = NULL; -PFNGLVERTEXATTRIB4DVPROC glad_glVertexAttrib4dv = NULL; -PFNGLVERTEXATTRIB4FPROC glad_glVertexAttrib4f = NULL; -PFNGLVERTEXATTRIB4FVPROC glad_glVertexAttrib4fv = NULL; -PFNGLVERTEXATTRIB4IVPROC glad_glVertexAttrib4iv = NULL; -PFNGLVERTEXATTRIB4SPROC glad_glVertexAttrib4s = NULL; -PFNGLVERTEXATTRIB4SVPROC glad_glVertexAttrib4sv = NULL; -PFNGLVERTEXATTRIB4UBVPROC glad_glVertexAttrib4ubv = NULL; -PFNGLVERTEXATTRIB4UIVPROC glad_glVertexAttrib4uiv = NULL; -PFNGLVERTEXATTRIB4USVPROC glad_glVertexAttrib4usv = NULL; -PFNGLVERTEXATTRIBI1IPROC glad_glVertexAttribI1i = NULL; -PFNGLVERTEXATTRIBI1IVPROC glad_glVertexAttribI1iv = NULL; -PFNGLVERTEXATTRIBI1UIPROC glad_glVertexAttribI1ui = NULL; -PFNGLVERTEXATTRIBI1UIVPROC glad_glVertexAttribI1uiv = NULL; -PFNGLVERTEXATTRIBI2IPROC glad_glVertexAttribI2i = NULL; -PFNGLVERTEXATTRIBI2IVPROC glad_glVertexAttribI2iv = NULL; -PFNGLVERTEXATTRIBI2UIPROC glad_glVertexAttribI2ui = NULL; -PFNGLVERTEXATTRIBI2UIVPROC glad_glVertexAttribI2uiv = NULL; -PFNGLVERTEXATTRIBI3IPROC glad_glVertexAttribI3i = NULL; -PFNGLVERTEXATTRIBI3IVPROC glad_glVertexAttribI3iv = NULL; -PFNGLVERTEXATTRIBI3UIPROC glad_glVertexAttribI3ui = NULL; -PFNGLVERTEXATTRIBI3UIVPROC glad_glVertexAttribI3uiv = NULL; -PFNGLVERTEXATTRIBI4BVPROC glad_glVertexAttribI4bv = NULL; -PFNGLVERTEXATTRIBI4IPROC glad_glVertexAttribI4i = NULL; -PFNGLVERTEXATTRIBI4IVPROC glad_glVertexAttribI4iv = NULL; -PFNGLVERTEXATTRIBI4SVPROC glad_glVertexAttribI4sv = NULL; -PFNGLVERTEXATTRIBI4UBVPROC glad_glVertexAttribI4ubv = NULL; -PFNGLVERTEXATTRIBI4UIPROC glad_glVertexAttribI4ui = NULL; -PFNGLVERTEXATTRIBI4UIVPROC glad_glVertexAttribI4uiv = NULL; -PFNGLVERTEXATTRIBI4USVPROC glad_glVertexAttribI4usv = NULL; -PFNGLVERTEXATTRIBIPOINTERPROC glad_glVertexAttribIPointer = NULL; -PFNGLVERTEXATTRIBPOINTERPROC glad_glVertexAttribPointer = NULL; -PFNGLVIEWPORTPROC glad_glViewport = NULL; -int GLAD_GL_ARB_buffer_storage = 0; -int GLAD_GL_ARB_debug_output = 0; -int GLAD_GL_ARB_sync = 0; -PFNGLBUFFERSTORAGEPROC glad_glBufferStorage = NULL; -PFNGLDEBUGMESSAGECONTROLARBPROC glad_glDebugMessageControlARB = NULL; -PFNGLDEBUGMESSAGEINSERTARBPROC glad_glDebugMessageInsertARB = NULL; -PFNGLDEBUGMESSAGECALLBACKARBPROC glad_glDebugMessageCallbackARB = NULL; -PFNGLGETDEBUGMESSAGELOGARBPROC glad_glGetDebugMessageLogARB = NULL; -PFNGLFENCESYNCPROC glad_glFenceSync = NULL; -PFNGLISSYNCPROC glad_glIsSync = NULL; -PFNGLDELETESYNCPROC glad_glDeleteSync = NULL; -PFNGLCLIENTWAITSYNCPROC glad_glClientWaitSync = NULL; -PFNGLWAITSYNCPROC glad_glWaitSync = NULL; -PFNGLGETINTEGER64VPROC glad_glGetInteger64v = NULL; -PFNGLGETSYNCIVPROC glad_glGetSynciv = NULL; -static void load_GL_VERSION_1_0(GLADloadproc load) { - if(!GLAD_GL_VERSION_1_0) return; - glad_glCullFace = (PFNGLCULLFACEPROC)load("glCullFace"); - glad_glFrontFace = (PFNGLFRONTFACEPROC)load("glFrontFace"); - glad_glHint = (PFNGLHINTPROC)load("glHint"); - glad_glLineWidth = (PFNGLLINEWIDTHPROC)load("glLineWidth"); - glad_glPointSize = (PFNGLPOINTSIZEPROC)load("glPointSize"); - glad_glPolygonMode = (PFNGLPOLYGONMODEPROC)load("glPolygonMode"); - glad_glScissor = (PFNGLSCISSORPROC)load("glScissor"); - glad_glTexParameterf = (PFNGLTEXPARAMETERFPROC)load("glTexParameterf"); - glad_glTexParameterfv = (PFNGLTEXPARAMETERFVPROC)load("glTexParameterfv"); - glad_glTexParameteri = (PFNGLTEXPARAMETERIPROC)load("glTexParameteri"); - glad_glTexParameteriv = (PFNGLTEXPARAMETERIVPROC)load("glTexParameteriv"); - glad_glTexImage1D = (PFNGLTEXIMAGE1DPROC)load("glTexImage1D"); - glad_glTexImage2D = (PFNGLTEXIMAGE2DPROC)load("glTexImage2D"); - glad_glDrawBuffer = (PFNGLDRAWBUFFERPROC)load("glDrawBuffer"); - glad_glClear = (PFNGLCLEARPROC)load("glClear"); - glad_glClearColor = (PFNGLCLEARCOLORPROC)load("glClearColor"); - glad_glClearStencil = (PFNGLCLEARSTENCILPROC)load("glClearStencil"); - glad_glClearDepth = (PFNGLCLEARDEPTHPROC)load("glClearDepth"); - glad_glStencilMask = (PFNGLSTENCILMASKPROC)load("glStencilMask"); - glad_glColorMask = (PFNGLCOLORMASKPROC)load("glColorMask"); - glad_glDepthMask = (PFNGLDEPTHMASKPROC)load("glDepthMask"); - glad_glDisable = (PFNGLDISABLEPROC)load("glDisable"); - glad_glEnable = (PFNGLENABLEPROC)load("glEnable"); - glad_glFinish = (PFNGLFINISHPROC)load("glFinish"); - glad_glFlush = (PFNGLFLUSHPROC)load("glFlush"); - glad_glBlendFunc = (PFNGLBLENDFUNCPROC)load("glBlendFunc"); - glad_glLogicOp = (PFNGLLOGICOPPROC)load("glLogicOp"); - glad_glStencilFunc = (PFNGLSTENCILFUNCPROC)load("glStencilFunc"); - glad_glStencilOp = (PFNGLSTENCILOPPROC)load("glStencilOp"); - glad_glDepthFunc = (PFNGLDEPTHFUNCPROC)load("glDepthFunc"); - glad_glPixelStoref = (PFNGLPIXELSTOREFPROC)load("glPixelStoref"); - glad_glPixelStorei = (PFNGLPIXELSTOREIPROC)load("glPixelStorei"); - glad_glReadBuffer = (PFNGLREADBUFFERPROC)load("glReadBuffer"); - glad_glReadPixels = (PFNGLREADPIXELSPROC)load("glReadPixels"); - glad_glGetBooleanv = (PFNGLGETBOOLEANVPROC)load("glGetBooleanv"); - glad_glGetDoublev = (PFNGLGETDOUBLEVPROC)load("glGetDoublev"); - glad_glGetError = (PFNGLGETERRORPROC)load("glGetError"); - glad_glGetFloatv = (PFNGLGETFLOATVPROC)load("glGetFloatv"); - glad_glGetIntegerv = (PFNGLGETINTEGERVPROC)load("glGetIntegerv"); - glad_glGetString = (PFNGLGETSTRINGPROC)load("glGetString"); - glad_glGetTexImage = (PFNGLGETTEXIMAGEPROC)load("glGetTexImage"); - glad_glGetTexParameterfv = (PFNGLGETTEXPARAMETERFVPROC)load("glGetTexParameterfv"); - glad_glGetTexParameteriv = (PFNGLGETTEXPARAMETERIVPROC)load("glGetTexParameteriv"); - glad_glGetTexLevelParameterfv = (PFNGLGETTEXLEVELPARAMETERFVPROC)load("glGetTexLevelParameterfv"); - glad_glGetTexLevelParameteriv = (PFNGLGETTEXLEVELPARAMETERIVPROC)load("glGetTexLevelParameteriv"); - glad_glIsEnabled = (PFNGLISENABLEDPROC)load("glIsEnabled"); - glad_glDepthRange = (PFNGLDEPTHRANGEPROC)load("glDepthRange"); - glad_glViewport = (PFNGLVIEWPORTPROC)load("glViewport"); +PFNGLGETINTEGERI_VPROC glad_glGetIntegeri_v = NULL; +PFNGLGETINTEGERVPROC glad_glGetIntegerv = NULL; +PFNGLGETPROGRAMINFOLOGPROC glad_glGetProgramInfoLog = NULL; +PFNGLGETPROGRAMIVPROC glad_glGetProgramiv = NULL; +PFNGLGETQUERYOBJECTIVPROC glad_glGetQueryObjectiv = NULL; +PFNGLGETQUERYOBJECTUIVPROC glad_glGetQueryObjectuiv = NULL; +PFNGLGETQUERYIVPROC glad_glGetQueryiv = NULL; +PFNGLGETRENDERBUFFERPARAMETERIVPROC glad_glGetRenderbufferParameteriv = NULL; +PFNGLGETSHADERINFOLOGPROC glad_glGetShaderInfoLog = NULL; +PFNGLGETSHADERSOURCEPROC glad_glGetShaderSource = NULL; +PFNGLGETSHADERIVPROC glad_glGetShaderiv = NULL; +PFNGLGETSTRINGPROC glad_glGetString = NULL; +PFNGLGETSTRINGIPROC glad_glGetStringi = NULL; +PFNGLGETTEXIMAGEPROC glad_glGetTexImage = NULL; +PFNGLGETTEXLEVELPARAMETERFVPROC glad_glGetTexLevelParameterfv = NULL; +PFNGLGETTEXLEVELPARAMETERIVPROC glad_glGetTexLevelParameteriv = NULL; +PFNGLGETTEXPARAMETERIIVPROC glad_glGetTexParameterIiv = NULL; +PFNGLGETTEXPARAMETERIUIVPROC glad_glGetTexParameterIuiv = NULL; +PFNGLGETTEXPARAMETERFVPROC glad_glGetTexParameterfv = NULL; +PFNGLGETTEXPARAMETERIVPROC glad_glGetTexParameteriv = NULL; +PFNGLGETTRANSFORMFEEDBACKVARYINGPROC glad_glGetTransformFeedbackVarying = NULL; +PFNGLGETUNIFORMLOCATIONPROC glad_glGetUniformLocation = NULL; +PFNGLGETUNIFORMFVPROC glad_glGetUniformfv = NULL; +PFNGLGETUNIFORMIVPROC glad_glGetUniformiv = NULL; +PFNGLGETUNIFORMUIVPROC glad_glGetUniformuiv = NULL; +PFNGLGETVERTEXATTRIBIIVPROC glad_glGetVertexAttribIiv = NULL; +PFNGLGETVERTEXATTRIBIUIVPROC glad_glGetVertexAttribIuiv = NULL; +PFNGLGETVERTEXATTRIBPOINTERVPROC glad_glGetVertexAttribPointerv = NULL; +PFNGLGETVERTEXATTRIBDVPROC glad_glGetVertexAttribdv = NULL; +PFNGLGETVERTEXATTRIBFVPROC glad_glGetVertexAttribfv = NULL; +PFNGLGETVERTEXATTRIBIVPROC glad_glGetVertexAttribiv = NULL; +PFNGLHINTPROC glad_glHint = NULL; +PFNGLISBUFFERPROC glad_glIsBuffer = NULL; +PFNGLISENABLEDPROC glad_glIsEnabled = NULL; +PFNGLISENABLEDIPROC glad_glIsEnabledi = NULL; +PFNGLISFRAMEBUFFERPROC glad_glIsFramebuffer = NULL; +PFNGLISPROGRAMPROC glad_glIsProgram = NULL; +PFNGLISQUERYPROC glad_glIsQuery = NULL; +PFNGLISRENDERBUFFERPROC glad_glIsRenderbuffer = NULL; +PFNGLISSHADERPROC glad_glIsShader = NULL; +PFNGLISTEXTUREPROC glad_glIsTexture = NULL; +PFNGLISVERTEXARRAYPROC glad_glIsVertexArray = NULL; +PFNGLLINEWIDTHPROC glad_glLineWidth = NULL; +PFNGLLINKPROGRAMPROC glad_glLinkProgram = NULL; +PFNGLLOGICOPPROC glad_glLogicOp = NULL; +PFNGLMAPBUFFERPROC glad_glMapBuffer = NULL; +PFNGLMAPBUFFERRANGEPROC glad_glMapBufferRange = NULL; +PFNGLMULTIDRAWARRAYSPROC glad_glMultiDrawArrays = NULL; +PFNGLMULTIDRAWELEMENTSPROC glad_glMultiDrawElements = NULL; +PFNGLPIXELSTOREFPROC glad_glPixelStoref = NULL; +PFNGLPIXELSTOREIPROC glad_glPixelStorei = NULL; +PFNGLPOINTPARAMETERFPROC glad_glPointParameterf = NULL; +PFNGLPOINTPARAMETERFVPROC glad_glPointParameterfv = NULL; +PFNGLPOINTPARAMETERIPROC glad_glPointParameteri = NULL; +PFNGLPOINTPARAMETERIVPROC glad_glPointParameteriv = NULL; +PFNGLPOINTSIZEPROC glad_glPointSize = NULL; +PFNGLPOLYGONMODEPROC glad_glPolygonMode = NULL; +PFNGLPOLYGONOFFSETPROC glad_glPolygonOffset = NULL; +PFNGLREADBUFFERPROC glad_glReadBuffer = NULL; +PFNGLREADPIXELSPROC glad_glReadPixels = NULL; +PFNGLRENDERBUFFERSTORAGEPROC glad_glRenderbufferStorage = NULL; +PFNGLRENDERBUFFERSTORAGEMULTISAMPLEPROC glad_glRenderbufferStorageMultisample = NULL; +PFNGLSAMPLECOVERAGEPROC glad_glSampleCoverage = NULL; +PFNGLSCISSORPROC glad_glScissor = NULL; +PFNGLSHADERSOURCEPROC glad_glShaderSource = NULL; +PFNGLSTENCILFUNCPROC glad_glStencilFunc = NULL; +PFNGLSTENCILFUNCSEPARATEPROC glad_glStencilFuncSeparate = NULL; +PFNGLSTENCILMASKPROC glad_glStencilMask = NULL; +PFNGLSTENCILMASKSEPARATEPROC glad_glStencilMaskSeparate = NULL; +PFNGLSTENCILOPPROC glad_glStencilOp = NULL; +PFNGLSTENCILOPSEPARATEPROC glad_glStencilOpSeparate = NULL; +PFNGLTEXIMAGE1DPROC glad_glTexImage1D = NULL; +PFNGLTEXIMAGE2DPROC glad_glTexImage2D = NULL; +PFNGLTEXIMAGE3DPROC glad_glTexImage3D = NULL; +PFNGLTEXPARAMETERIIVPROC glad_glTexParameterIiv = NULL; +PFNGLTEXPARAMETERIUIVPROC glad_glTexParameterIuiv = NULL; +PFNGLTEXPARAMETERFPROC glad_glTexParameterf = NULL; +PFNGLTEXPARAMETERFVPROC glad_glTexParameterfv = NULL; +PFNGLTEXPARAMETERIPROC glad_glTexParameteri = NULL; +PFNGLTEXPARAMETERIVPROC glad_glTexParameteriv = NULL; +PFNGLTEXSUBIMAGE1DPROC glad_glTexSubImage1D = NULL; +PFNGLTEXSUBIMAGE2DPROC glad_glTexSubImage2D = NULL; +PFNGLTEXSUBIMAGE3DPROC glad_glTexSubImage3D = NULL; +PFNGLTRANSFORMFEEDBACKVARYINGSPROC glad_glTransformFeedbackVaryings = NULL; +PFNGLUNIFORM1FPROC glad_glUniform1f = NULL; +PFNGLUNIFORM1FVPROC glad_glUniform1fv = NULL; +PFNGLUNIFORM1IPROC glad_glUniform1i = NULL; +PFNGLUNIFORM1IVPROC glad_glUniform1iv = NULL; +PFNGLUNIFORM1UIPROC glad_glUniform1ui = NULL; +PFNGLUNIFORM1UIVPROC glad_glUniform1uiv = NULL; +PFNGLUNIFORM2FPROC glad_glUniform2f = NULL; +PFNGLUNIFORM2FVPROC glad_glUniform2fv = NULL; +PFNGLUNIFORM2IPROC glad_glUniform2i = NULL; +PFNGLUNIFORM2IVPROC glad_glUniform2iv = NULL; +PFNGLUNIFORM2UIPROC glad_glUniform2ui = NULL; +PFNGLUNIFORM2UIVPROC glad_glUniform2uiv = NULL; +PFNGLUNIFORM3FPROC glad_glUniform3f = NULL; +PFNGLUNIFORM3FVPROC glad_glUniform3fv = NULL; +PFNGLUNIFORM3IPROC glad_glUniform3i = NULL; +PFNGLUNIFORM3IVPROC glad_glUniform3iv = NULL; +PFNGLUNIFORM3UIPROC glad_glUniform3ui = NULL; +PFNGLUNIFORM3UIVPROC glad_glUniform3uiv = NULL; +PFNGLUNIFORM4FPROC glad_glUniform4f = NULL; +PFNGLUNIFORM4FVPROC glad_glUniform4fv = NULL; +PFNGLUNIFORM4IPROC glad_glUniform4i = NULL; +PFNGLUNIFORM4IVPROC glad_glUniform4iv = NULL; +PFNGLUNIFORM4UIPROC glad_glUniform4ui = NULL; +PFNGLUNIFORM4UIVPROC glad_glUniform4uiv = NULL; +PFNGLUNIFORMMATRIX2FVPROC glad_glUniformMatrix2fv = NULL; +PFNGLUNIFORMMATRIX2X3FVPROC glad_glUniformMatrix2x3fv = NULL; +PFNGLUNIFORMMATRIX2X4FVPROC glad_glUniformMatrix2x4fv = NULL; +PFNGLUNIFORMMATRIX3FVPROC glad_glUniformMatrix3fv = NULL; +PFNGLUNIFORMMATRIX3X2FVPROC glad_glUniformMatrix3x2fv = NULL; +PFNGLUNIFORMMATRIX3X4FVPROC glad_glUniformMatrix3x4fv = NULL; +PFNGLUNIFORMMATRIX4FVPROC glad_glUniformMatrix4fv = NULL; +PFNGLUNIFORMMATRIX4X2FVPROC glad_glUniformMatrix4x2fv = NULL; +PFNGLUNIFORMMATRIX4X3FVPROC glad_glUniformMatrix4x3fv = NULL; +PFNGLUNMAPBUFFERPROC glad_glUnmapBuffer = NULL; +PFNGLUSEPROGRAMPROC glad_glUseProgram = NULL; +PFNGLVALIDATEPROGRAMPROC glad_glValidateProgram = NULL; +PFNGLVERTEXATTRIB1DPROC glad_glVertexAttrib1d = NULL; +PFNGLVERTEXATTRIB1DVPROC glad_glVertexAttrib1dv = NULL; +PFNGLVERTEXATTRIB1FPROC glad_glVertexAttrib1f = NULL; +PFNGLVERTEXATTRIB1FVPROC glad_glVertexAttrib1fv = NULL; +PFNGLVERTEXATTRIB1SPROC glad_glVertexAttrib1s = NULL; +PFNGLVERTEXATTRIB1SVPROC glad_glVertexAttrib1sv = NULL; +PFNGLVERTEXATTRIB2DPROC glad_glVertexAttrib2d = NULL; +PFNGLVERTEXATTRIB2DVPROC glad_glVertexAttrib2dv = NULL; +PFNGLVERTEXATTRIB2FPROC glad_glVertexAttrib2f = NULL; +PFNGLVERTEXATTRIB2FVPROC glad_glVertexAttrib2fv = NULL; +PFNGLVERTEXATTRIB2SPROC glad_glVertexAttrib2s = NULL; +PFNGLVERTEXATTRIB2SVPROC glad_glVertexAttrib2sv = NULL; +PFNGLVERTEXATTRIB3DPROC glad_glVertexAttrib3d = NULL; +PFNGLVERTEXATTRIB3DVPROC glad_glVertexAttrib3dv = NULL; +PFNGLVERTEXATTRIB3FPROC glad_glVertexAttrib3f = NULL; +PFNGLVERTEXATTRIB3FVPROC glad_glVertexAttrib3fv = NULL; +PFNGLVERTEXATTRIB3SPROC glad_glVertexAttrib3s = NULL; +PFNGLVERTEXATTRIB3SVPROC glad_glVertexAttrib3sv = NULL; +PFNGLVERTEXATTRIB4NBVPROC glad_glVertexAttrib4Nbv = NULL; +PFNGLVERTEXATTRIB4NIVPROC glad_glVertexAttrib4Niv = NULL; +PFNGLVERTEXATTRIB4NSVPROC glad_glVertexAttrib4Nsv = NULL; +PFNGLVERTEXATTRIB4NUBPROC glad_glVertexAttrib4Nub = NULL; +PFNGLVERTEXATTRIB4NUBVPROC glad_glVertexAttrib4Nubv = NULL; +PFNGLVERTEXATTRIB4NUIVPROC glad_glVertexAttrib4Nuiv = NULL; +PFNGLVERTEXATTRIB4NUSVPROC glad_glVertexAttrib4Nusv = NULL; +PFNGLVERTEXATTRIB4BVPROC glad_glVertexAttrib4bv = NULL; +PFNGLVERTEXATTRIB4DPROC glad_glVertexAttrib4d = NULL; +PFNGLVERTEXATTRIB4DVPROC glad_glVertexAttrib4dv = NULL; +PFNGLVERTEXATTRIB4FPROC glad_glVertexAttrib4f = NULL; +PFNGLVERTEXATTRIB4FVPROC glad_glVertexAttrib4fv = NULL; +PFNGLVERTEXATTRIB4IVPROC glad_glVertexAttrib4iv = NULL; +PFNGLVERTEXATTRIB4SPROC glad_glVertexAttrib4s = NULL; +PFNGLVERTEXATTRIB4SVPROC glad_glVertexAttrib4sv = NULL; +PFNGLVERTEXATTRIB4UBVPROC glad_glVertexAttrib4ubv = NULL; +PFNGLVERTEXATTRIB4UIVPROC glad_glVertexAttrib4uiv = NULL; +PFNGLVERTEXATTRIB4USVPROC glad_glVertexAttrib4usv = NULL; +PFNGLVERTEXATTRIBI1IPROC glad_glVertexAttribI1i = NULL; +PFNGLVERTEXATTRIBI1IVPROC glad_glVertexAttribI1iv = NULL; +PFNGLVERTEXATTRIBI1UIPROC glad_glVertexAttribI1ui = NULL; +PFNGLVERTEXATTRIBI1UIVPROC glad_glVertexAttribI1uiv = NULL; +PFNGLVERTEXATTRIBI2IPROC glad_glVertexAttribI2i = NULL; +PFNGLVERTEXATTRIBI2IVPROC glad_glVertexAttribI2iv = NULL; +PFNGLVERTEXATTRIBI2UIPROC glad_glVertexAttribI2ui = NULL; +PFNGLVERTEXATTRIBI2UIVPROC glad_glVertexAttribI2uiv = NULL; +PFNGLVERTEXATTRIBI3IPROC glad_glVertexAttribI3i = NULL; +PFNGLVERTEXATTRIBI3IVPROC glad_glVertexAttribI3iv = NULL; +PFNGLVERTEXATTRIBI3UIPROC glad_glVertexAttribI3ui = NULL; +PFNGLVERTEXATTRIBI3UIVPROC glad_glVertexAttribI3uiv = NULL; +PFNGLVERTEXATTRIBI4BVPROC glad_glVertexAttribI4bv = NULL; +PFNGLVERTEXATTRIBI4IPROC glad_glVertexAttribI4i = NULL; +PFNGLVERTEXATTRIBI4IVPROC glad_glVertexAttribI4iv = NULL; +PFNGLVERTEXATTRIBI4SVPROC glad_glVertexAttribI4sv = NULL; +PFNGLVERTEXATTRIBI4UBVPROC glad_glVertexAttribI4ubv = NULL; +PFNGLVERTEXATTRIBI4UIPROC glad_glVertexAttribI4ui = NULL; +PFNGLVERTEXATTRIBI4UIVPROC glad_glVertexAttribI4uiv = NULL; +PFNGLVERTEXATTRIBI4USVPROC glad_glVertexAttribI4usv = NULL; +PFNGLVERTEXATTRIBIPOINTERPROC glad_glVertexAttribIPointer = NULL; +PFNGLVERTEXATTRIBPOINTERPROC glad_glVertexAttribPointer = NULL; +PFNGLVIEWPORTPROC glad_glViewport = NULL; +int GLAD_GL_ARB_buffer_storage = 0; +int GLAD_GL_ARB_debug_output = 0; +int GLAD_GL_ARB_sync = 0; +PFNGLBUFFERSTORAGEPROC glad_glBufferStorage = NULL; +PFNGLDEBUGMESSAGECONTROLARBPROC glad_glDebugMessageControlARB = NULL; +PFNGLDEBUGMESSAGEINSERTARBPROC glad_glDebugMessageInsertARB = NULL; +PFNGLDEBUGMESSAGECALLBACKARBPROC glad_glDebugMessageCallbackARB = NULL; +PFNGLGETDEBUGMESSAGELOGARBPROC glad_glGetDebugMessageLogARB = NULL; +PFNGLFENCESYNCPROC glad_glFenceSync = NULL; +PFNGLISSYNCPROC glad_glIsSync = NULL; +PFNGLDELETESYNCPROC glad_glDeleteSync = NULL; +PFNGLCLIENTWAITSYNCPROC glad_glClientWaitSync = NULL; +PFNGLWAITSYNCPROC glad_glWaitSync = NULL; +PFNGLGETINTEGER64VPROC glad_glGetInteger64v = NULL; +PFNGLGETSYNCIVPROC glad_glGetSynciv = NULL; +static void +load_GL_VERSION_1_0(GLADloadproc load) +{ + if (!GLAD_GL_VERSION_1_0) + return; + glad_glCullFace = (PFNGLCULLFACEPROC) load("glCullFace"); + glad_glFrontFace = (PFNGLFRONTFACEPROC) load("glFrontFace"); + glad_glHint = (PFNGLHINTPROC) load("glHint"); + glad_glLineWidth = (PFNGLLINEWIDTHPROC) load("glLineWidth"); + glad_glPointSize = (PFNGLPOINTSIZEPROC) load("glPointSize"); + glad_glPolygonMode = (PFNGLPOLYGONMODEPROC) load("glPolygonMode"); + glad_glScissor = (PFNGLSCISSORPROC) load("glScissor"); + glad_glTexParameterf = (PFNGLTEXPARAMETERFPROC) load("glTexParameterf"); + glad_glTexParameterfv = (PFNGLTEXPARAMETERFVPROC) load("glTexParameterfv"); + glad_glTexParameteri = (PFNGLTEXPARAMETERIPROC) load("glTexParameteri"); + glad_glTexParameteriv = (PFNGLTEXPARAMETERIVPROC) load("glTexParameteriv"); + glad_glTexImage1D = (PFNGLTEXIMAGE1DPROC) load("glTexImage1D"); + glad_glTexImage2D = (PFNGLTEXIMAGE2DPROC) load("glTexImage2D"); + glad_glDrawBuffer = (PFNGLDRAWBUFFERPROC) load("glDrawBuffer"); + glad_glClear = (PFNGLCLEARPROC) load("glClear"); + glad_glClearColor = (PFNGLCLEARCOLORPROC) load("glClearColor"); + glad_glClearStencil = (PFNGLCLEARSTENCILPROC) load("glClearStencil"); + glad_glClearDepth = (PFNGLCLEARDEPTHPROC) load("glClearDepth"); + glad_glStencilMask = (PFNGLSTENCILMASKPROC) load("glStencilMask"); + glad_glColorMask = (PFNGLCOLORMASKPROC) load("glColorMask"); + glad_glDepthMask = (PFNGLDEPTHMASKPROC) load("glDepthMask"); + glad_glDisable = (PFNGLDISABLEPROC) load("glDisable"); + glad_glEnable = (PFNGLENABLEPROC) load("glEnable"); + glad_glFinish = (PFNGLFINISHPROC) load("glFinish"); + glad_glFlush = (PFNGLFLUSHPROC) load("glFlush"); + glad_glBlendFunc = (PFNGLBLENDFUNCPROC) load("glBlendFunc"); + glad_glLogicOp = (PFNGLLOGICOPPROC) load("glLogicOp"); + glad_glStencilFunc = (PFNGLSTENCILFUNCPROC) load("glStencilFunc"); + glad_glStencilOp = (PFNGLSTENCILOPPROC) load("glStencilOp"); + glad_glDepthFunc = (PFNGLDEPTHFUNCPROC) load("glDepthFunc"); + glad_glPixelStoref = (PFNGLPIXELSTOREFPROC) load("glPixelStoref"); + glad_glPixelStorei = (PFNGLPIXELSTOREIPROC) load("glPixelStorei"); + glad_glReadBuffer = (PFNGLREADBUFFERPROC) load("glReadBuffer"); + glad_glReadPixels = (PFNGLREADPIXELSPROC) load("glReadPixels"); + glad_glGetBooleanv = (PFNGLGETBOOLEANVPROC) load("glGetBooleanv"); + glad_glGetDoublev = (PFNGLGETDOUBLEVPROC) load("glGetDoublev"); + glad_glGetError = (PFNGLGETERRORPROC) load("glGetError"); + glad_glGetFloatv = (PFNGLGETFLOATVPROC) load("glGetFloatv"); + glad_glGetIntegerv = (PFNGLGETINTEGERVPROC) load("glGetIntegerv"); + glad_glGetString = (PFNGLGETSTRINGPROC) load("glGetString"); + glad_glGetTexImage = (PFNGLGETTEXIMAGEPROC) load("glGetTexImage"); + glad_glGetTexParameterfv = (PFNGLGETTEXPARAMETERFVPROC) load("glGetTexParameterfv"); + glad_glGetTexParameteriv = (PFNGLGETTEXPARAMETERIVPROC) load("glGetTexParameteriv"); + glad_glGetTexLevelParameterfv = (PFNGLGETTEXLEVELPARAMETERFVPROC) load("glGetTexLevelParameterfv"); + glad_glGetTexLevelParameteriv = (PFNGLGETTEXLEVELPARAMETERIVPROC) load("glGetTexLevelParameteriv"); + glad_glIsEnabled = (PFNGLISENABLEDPROC) load("glIsEnabled"); + glad_glDepthRange = (PFNGLDEPTHRANGEPROC) load("glDepthRange"); + glad_glViewport = (PFNGLVIEWPORTPROC) load("glViewport"); } -static void load_GL_VERSION_1_1(GLADloadproc load) { - if(!GLAD_GL_VERSION_1_1) return; - glad_glDrawArrays = (PFNGLDRAWARRAYSPROC)load("glDrawArrays"); - glad_glDrawElements = (PFNGLDRAWELEMENTSPROC)load("glDrawElements"); - glad_glPolygonOffset = (PFNGLPOLYGONOFFSETPROC)load("glPolygonOffset"); - glad_glCopyTexImage1D = (PFNGLCOPYTEXIMAGE1DPROC)load("glCopyTexImage1D"); - glad_glCopyTexImage2D = (PFNGLCOPYTEXIMAGE2DPROC)load("glCopyTexImage2D"); - glad_glCopyTexSubImage1D = (PFNGLCOPYTEXSUBIMAGE1DPROC)load("glCopyTexSubImage1D"); - glad_glCopyTexSubImage2D = (PFNGLCOPYTEXSUBIMAGE2DPROC)load("glCopyTexSubImage2D"); - glad_glTexSubImage1D = (PFNGLTEXSUBIMAGE1DPROC)load("glTexSubImage1D"); - glad_glTexSubImage2D = (PFNGLTEXSUBIMAGE2DPROC)load("glTexSubImage2D"); - glad_glBindTexture = (PFNGLBINDTEXTUREPROC)load("glBindTexture"); - glad_glDeleteTextures = (PFNGLDELETETEXTURESPROC)load("glDeleteTextures"); - glad_glGenTextures = (PFNGLGENTEXTURESPROC)load("glGenTextures"); - glad_glIsTexture = (PFNGLISTEXTUREPROC)load("glIsTexture"); +static void +load_GL_VERSION_1_1(GLADloadproc load) +{ + if (!GLAD_GL_VERSION_1_1) + return; + glad_glDrawArrays = (PFNGLDRAWARRAYSPROC) load("glDrawArrays"); + glad_glDrawElements = (PFNGLDRAWELEMENTSPROC) load("glDrawElements"); + glad_glPolygonOffset = (PFNGLPOLYGONOFFSETPROC) load("glPolygonOffset"); + glad_glCopyTexImage1D = (PFNGLCOPYTEXIMAGE1DPROC) load("glCopyTexImage1D"); + glad_glCopyTexImage2D = (PFNGLCOPYTEXIMAGE2DPROC) load("glCopyTexImage2D"); + glad_glCopyTexSubImage1D = (PFNGLCOPYTEXSUBIMAGE1DPROC) load("glCopyTexSubImage1D"); + glad_glCopyTexSubImage2D = (PFNGLCOPYTEXSUBIMAGE2DPROC) load("glCopyTexSubImage2D"); + glad_glTexSubImage1D = (PFNGLTEXSUBIMAGE1DPROC) load("glTexSubImage1D"); + glad_glTexSubImage2D = (PFNGLTEXSUBIMAGE2DPROC) load("glTexSubImage2D"); + glad_glBindTexture = (PFNGLBINDTEXTUREPROC) load("glBindTexture"); + glad_glDeleteTextures = (PFNGLDELETETEXTURESPROC) load("glDeleteTextures"); + glad_glGenTextures = (PFNGLGENTEXTURESPROC) load("glGenTextures"); + glad_glIsTexture = (PFNGLISTEXTUREPROC) load("glIsTexture"); } -static void load_GL_VERSION_1_2(GLADloadproc load) { - if(!GLAD_GL_VERSION_1_2) return; - glad_glDrawRangeElements = (PFNGLDRAWRANGEELEMENTSPROC)load("glDrawRangeElements"); - glad_glTexImage3D = (PFNGLTEXIMAGE3DPROC)load("glTexImage3D"); - glad_glTexSubImage3D = (PFNGLTEXSUBIMAGE3DPROC)load("glTexSubImage3D"); - glad_glCopyTexSubImage3D = (PFNGLCOPYTEXSUBIMAGE3DPROC)load("glCopyTexSubImage3D"); +static void +load_GL_VERSION_1_2(GLADloadproc load) +{ + if (!GLAD_GL_VERSION_1_2) + return; + glad_glDrawRangeElements = (PFNGLDRAWRANGEELEMENTSPROC) load("glDrawRangeElements"); + glad_glTexImage3D = (PFNGLTEXIMAGE3DPROC) load("glTexImage3D"); + glad_glTexSubImage3D = (PFNGLTEXSUBIMAGE3DPROC) load("glTexSubImage3D"); + glad_glCopyTexSubImage3D = (PFNGLCOPYTEXSUBIMAGE3DPROC) load("glCopyTexSubImage3D"); } -static void load_GL_VERSION_1_3(GLADloadproc load) { - if(!GLAD_GL_VERSION_1_3) return; - glad_glActiveTexture = (PFNGLACTIVETEXTUREPROC)load("glActiveTexture"); - glad_glSampleCoverage = (PFNGLSAMPLECOVERAGEPROC)load("glSampleCoverage"); - glad_glCompressedTexImage3D = (PFNGLCOMPRESSEDTEXIMAGE3DPROC)load("glCompressedTexImage3D"); - glad_glCompressedTexImage2D = (PFNGLCOMPRESSEDTEXIMAGE2DPROC)load("glCompressedTexImage2D"); - glad_glCompressedTexImage1D = (PFNGLCOMPRESSEDTEXIMAGE1DPROC)load("glCompressedTexImage1D"); - glad_glCompressedTexSubImage3D = (PFNGLCOMPRESSEDTEXSUBIMAGE3DPROC)load("glCompressedTexSubImage3D"); - glad_glCompressedTexSubImage2D = (PFNGLCOMPRESSEDTEXSUBIMAGE2DPROC)load("glCompressedTexSubImage2D"); - glad_glCompressedTexSubImage1D = (PFNGLCOMPRESSEDTEXSUBIMAGE1DPROC)load("glCompressedTexSubImage1D"); - glad_glGetCompressedTexImage = (PFNGLGETCOMPRESSEDTEXIMAGEPROC)load("glGetCompressedTexImage"); +static void +load_GL_VERSION_1_3(GLADloadproc load) +{ + if (!GLAD_GL_VERSION_1_3) + return; + glad_glActiveTexture = (PFNGLACTIVETEXTUREPROC) load("glActiveTexture"); + glad_glSampleCoverage = (PFNGLSAMPLECOVERAGEPROC) load("glSampleCoverage"); + glad_glCompressedTexImage3D = (PFNGLCOMPRESSEDTEXIMAGE3DPROC) load("glCompressedTexImage3D"); + glad_glCompressedTexImage2D = (PFNGLCOMPRESSEDTEXIMAGE2DPROC) load("glCompressedTexImage2D"); + glad_glCompressedTexImage1D = (PFNGLCOMPRESSEDTEXIMAGE1DPROC) load("glCompressedTexImage1D"); + glad_glCompressedTexSubImage3D = (PFNGLCOMPRESSEDTEXSUBIMAGE3DPROC) load("glCompressedTexSubImage3D"); + glad_glCompressedTexSubImage2D = (PFNGLCOMPRESSEDTEXSUBIMAGE2DPROC) load("glCompressedTexSubImage2D"); + glad_glCompressedTexSubImage1D = (PFNGLCOMPRESSEDTEXSUBIMAGE1DPROC) load("glCompressedTexSubImage1D"); + glad_glGetCompressedTexImage = (PFNGLGETCOMPRESSEDTEXIMAGEPROC) load("glGetCompressedTexImage"); } -static void load_GL_VERSION_1_4(GLADloadproc load) { - if(!GLAD_GL_VERSION_1_4) return; - glad_glBlendFuncSeparate = (PFNGLBLENDFUNCSEPARATEPROC)load("glBlendFuncSeparate"); - glad_glMultiDrawArrays = (PFNGLMULTIDRAWARRAYSPROC)load("glMultiDrawArrays"); - glad_glMultiDrawElements = (PFNGLMULTIDRAWELEMENTSPROC)load("glMultiDrawElements"); - glad_glPointParameterf = (PFNGLPOINTPARAMETERFPROC)load("glPointParameterf"); - glad_glPointParameterfv = (PFNGLPOINTPARAMETERFVPROC)load("glPointParameterfv"); - glad_glPointParameteri = (PFNGLPOINTPARAMETERIPROC)load("glPointParameteri"); - glad_glPointParameteriv = (PFNGLPOINTPARAMETERIVPROC)load("glPointParameteriv"); - glad_glBlendColor = (PFNGLBLENDCOLORPROC)load("glBlendColor"); - glad_glBlendEquation = (PFNGLBLENDEQUATIONPROC)load("glBlendEquation"); +static void +load_GL_VERSION_1_4(GLADloadproc load) +{ + if (!GLAD_GL_VERSION_1_4) + return; + glad_glBlendFuncSeparate = (PFNGLBLENDFUNCSEPARATEPROC) load("glBlendFuncSeparate"); + glad_glMultiDrawArrays = (PFNGLMULTIDRAWARRAYSPROC) load("glMultiDrawArrays"); + glad_glMultiDrawElements = (PFNGLMULTIDRAWELEMENTSPROC) load("glMultiDrawElements"); + glad_glPointParameterf = (PFNGLPOINTPARAMETERFPROC) load("glPointParameterf"); + glad_glPointParameterfv = (PFNGLPOINTPARAMETERFVPROC) load("glPointParameterfv"); + glad_glPointParameteri = (PFNGLPOINTPARAMETERIPROC) load("glPointParameteri"); + glad_glPointParameteriv = (PFNGLPOINTPARAMETERIVPROC) load("glPointParameteriv"); + glad_glBlendColor = (PFNGLBLENDCOLORPROC) load("glBlendColor"); + glad_glBlendEquation = (PFNGLBLENDEQUATIONPROC) load("glBlendEquation"); } -static void load_GL_VERSION_1_5(GLADloadproc load) { - if(!GLAD_GL_VERSION_1_5) return; - glad_glGenQueries = (PFNGLGENQUERIESPROC)load("glGenQueries"); - glad_glDeleteQueries = (PFNGLDELETEQUERIESPROC)load("glDeleteQueries"); - glad_glIsQuery = (PFNGLISQUERYPROC)load("glIsQuery"); - glad_glBeginQuery = (PFNGLBEGINQUERYPROC)load("glBeginQuery"); - glad_glEndQuery = (PFNGLENDQUERYPROC)load("glEndQuery"); - glad_glGetQueryiv = (PFNGLGETQUERYIVPROC)load("glGetQueryiv"); - glad_glGetQueryObjectiv = (PFNGLGETQUERYOBJECTIVPROC)load("glGetQueryObjectiv"); - glad_glGetQueryObjectuiv = (PFNGLGETQUERYOBJECTUIVPROC)load("glGetQueryObjectuiv"); - glad_glBindBuffer = (PFNGLBINDBUFFERPROC)load("glBindBuffer"); - glad_glDeleteBuffers = (PFNGLDELETEBUFFERSPROC)load("glDeleteBuffers"); - glad_glGenBuffers = (PFNGLGENBUFFERSPROC)load("glGenBuffers"); - glad_glIsBuffer = (PFNGLISBUFFERPROC)load("glIsBuffer"); - glad_glBufferData = (PFNGLBUFFERDATAPROC)load("glBufferData"); - glad_glBufferSubData = (PFNGLBUFFERSUBDATAPROC)load("glBufferSubData"); - glad_glGetBufferSubData = (PFNGLGETBUFFERSUBDATAPROC)load("glGetBufferSubData"); - glad_glMapBuffer = (PFNGLMAPBUFFERPROC)load("glMapBuffer"); - glad_glUnmapBuffer = (PFNGLUNMAPBUFFERPROC)load("glUnmapBuffer"); - glad_glGetBufferParameteriv = (PFNGLGETBUFFERPARAMETERIVPROC)load("glGetBufferParameteriv"); - glad_glGetBufferPointerv = (PFNGLGETBUFFERPOINTERVPROC)load("glGetBufferPointerv"); +static void +load_GL_VERSION_1_5(GLADloadproc load) +{ + if (!GLAD_GL_VERSION_1_5) + return; + glad_glGenQueries = (PFNGLGENQUERIESPROC) load("glGenQueries"); + glad_glDeleteQueries = (PFNGLDELETEQUERIESPROC) load("glDeleteQueries"); + glad_glIsQuery = (PFNGLISQUERYPROC) load("glIsQuery"); + glad_glBeginQuery = (PFNGLBEGINQUERYPROC) load("glBeginQuery"); + glad_glEndQuery = (PFNGLENDQUERYPROC) load("glEndQuery"); + glad_glGetQueryiv = (PFNGLGETQUERYIVPROC) load("glGetQueryiv"); + glad_glGetQueryObjectiv = (PFNGLGETQUERYOBJECTIVPROC) load("glGetQueryObjectiv"); + glad_glGetQueryObjectuiv = (PFNGLGETQUERYOBJECTUIVPROC) load("glGetQueryObjectuiv"); + glad_glBindBuffer = (PFNGLBINDBUFFERPROC) load("glBindBuffer"); + glad_glDeleteBuffers = (PFNGLDELETEBUFFERSPROC) load("glDeleteBuffers"); + glad_glGenBuffers = (PFNGLGENBUFFERSPROC) load("glGenBuffers"); + glad_glIsBuffer = (PFNGLISBUFFERPROC) load("glIsBuffer"); + glad_glBufferData = (PFNGLBUFFERDATAPROC) load("glBufferData"); + glad_glBufferSubData = (PFNGLBUFFERSUBDATAPROC) load("glBufferSubData"); + glad_glGetBufferSubData = (PFNGLGETBUFFERSUBDATAPROC) load("glGetBufferSubData"); + glad_glMapBuffer = (PFNGLMAPBUFFERPROC) load("glMapBuffer"); + glad_glUnmapBuffer = (PFNGLUNMAPBUFFERPROC) load("glUnmapBuffer"); + glad_glGetBufferParameteriv = (PFNGLGETBUFFERPARAMETERIVPROC) load("glGetBufferParameteriv"); + glad_glGetBufferPointerv = (PFNGLGETBUFFERPOINTERVPROC) load("glGetBufferPointerv"); } -static void load_GL_VERSION_2_0(GLADloadproc load) { - if(!GLAD_GL_VERSION_2_0) return; - glad_glBlendEquationSeparate = (PFNGLBLENDEQUATIONSEPARATEPROC)load("glBlendEquationSeparate"); - glad_glDrawBuffers = (PFNGLDRAWBUFFERSPROC)load("glDrawBuffers"); - glad_glStencilOpSeparate = (PFNGLSTENCILOPSEPARATEPROC)load("glStencilOpSeparate"); - glad_glStencilFuncSeparate = (PFNGLSTENCILFUNCSEPARATEPROC)load("glStencilFuncSeparate"); - glad_glStencilMaskSeparate = (PFNGLSTENCILMASKSEPARATEPROC)load("glStencilMaskSeparate"); - glad_glAttachShader = (PFNGLATTACHSHADERPROC)load("glAttachShader"); - glad_glBindAttribLocation = (PFNGLBINDATTRIBLOCATIONPROC)load("glBindAttribLocation"); - glad_glCompileShader = (PFNGLCOMPILESHADERPROC)load("glCompileShader"); - glad_glCreateProgram = (PFNGLCREATEPROGRAMPROC)load("glCreateProgram"); - glad_glCreateShader = (PFNGLCREATESHADERPROC)load("glCreateShader"); - glad_glDeleteProgram = (PFNGLDELETEPROGRAMPROC)load("glDeleteProgram"); - glad_glDeleteShader = (PFNGLDELETESHADERPROC)load("glDeleteShader"); - glad_glDetachShader = (PFNGLDETACHSHADERPROC)load("glDetachShader"); - glad_glDisableVertexAttribArray = (PFNGLDISABLEVERTEXATTRIBARRAYPROC)load("glDisableVertexAttribArray"); - glad_glEnableVertexAttribArray = (PFNGLENABLEVERTEXATTRIBARRAYPROC)load("glEnableVertexAttribArray"); - glad_glGetActiveAttrib = (PFNGLGETACTIVEATTRIBPROC)load("glGetActiveAttrib"); - glad_glGetActiveUniform = (PFNGLGETACTIVEUNIFORMPROC)load("glGetActiveUniform"); - glad_glGetAttachedShaders = (PFNGLGETATTACHEDSHADERSPROC)load("glGetAttachedShaders"); - glad_glGetAttribLocation = (PFNGLGETATTRIBLOCATIONPROC)load("glGetAttribLocation"); - glad_glGetProgramiv = (PFNGLGETPROGRAMIVPROC)load("glGetProgramiv"); - glad_glGetProgramInfoLog = (PFNGLGETPROGRAMINFOLOGPROC)load("glGetProgramInfoLog"); - glad_glGetShaderiv = (PFNGLGETSHADERIVPROC)load("glGetShaderiv"); - glad_glGetShaderInfoLog = (PFNGLGETSHADERINFOLOGPROC)load("glGetShaderInfoLog"); - glad_glGetShaderSource = (PFNGLGETSHADERSOURCEPROC)load("glGetShaderSource"); - glad_glGetUniformLocation = (PFNGLGETUNIFORMLOCATIONPROC)load("glGetUniformLocation"); - glad_glGetUniformfv = (PFNGLGETUNIFORMFVPROC)load("glGetUniformfv"); - glad_glGetUniformiv = (PFNGLGETUNIFORMIVPROC)load("glGetUniformiv"); - glad_glGetVertexAttribdv = (PFNGLGETVERTEXATTRIBDVPROC)load("glGetVertexAttribdv"); - glad_glGetVertexAttribfv = (PFNGLGETVERTEXATTRIBFVPROC)load("glGetVertexAttribfv"); - glad_glGetVertexAttribiv = (PFNGLGETVERTEXATTRIBIVPROC)load("glGetVertexAttribiv"); - glad_glGetVertexAttribPointerv = (PFNGLGETVERTEXATTRIBPOINTERVPROC)load("glGetVertexAttribPointerv"); - glad_glIsProgram = (PFNGLISPROGRAMPROC)load("glIsProgram"); - glad_glIsShader = (PFNGLISSHADERPROC)load("glIsShader"); - glad_glLinkProgram = (PFNGLLINKPROGRAMPROC)load("glLinkProgram"); - glad_glShaderSource = (PFNGLSHADERSOURCEPROC)load("glShaderSource"); - glad_glUseProgram = (PFNGLUSEPROGRAMPROC)load("glUseProgram"); - glad_glUniform1f = (PFNGLUNIFORM1FPROC)load("glUniform1f"); - glad_glUniform2f = (PFNGLUNIFORM2FPROC)load("glUniform2f"); - glad_glUniform3f = (PFNGLUNIFORM3FPROC)load("glUniform3f"); - glad_glUniform4f = (PFNGLUNIFORM4FPROC)load("glUniform4f"); - glad_glUniform1i = (PFNGLUNIFORM1IPROC)load("glUniform1i"); - glad_glUniform2i = (PFNGLUNIFORM2IPROC)load("glUniform2i"); - glad_glUniform3i = (PFNGLUNIFORM3IPROC)load("glUniform3i"); - glad_glUniform4i = (PFNGLUNIFORM4IPROC)load("glUniform4i"); - glad_glUniform1fv = (PFNGLUNIFORM1FVPROC)load("glUniform1fv"); - glad_glUniform2fv = (PFNGLUNIFORM2FVPROC)load("glUniform2fv"); - glad_glUniform3fv = (PFNGLUNIFORM3FVPROC)load("glUniform3fv"); - glad_glUniform4fv = (PFNGLUNIFORM4FVPROC)load("glUniform4fv"); - glad_glUniform1iv = (PFNGLUNIFORM1IVPROC)load("glUniform1iv"); - glad_glUniform2iv = (PFNGLUNIFORM2IVPROC)load("glUniform2iv"); - glad_glUniform3iv = (PFNGLUNIFORM3IVPROC)load("glUniform3iv"); - glad_glUniform4iv = (PFNGLUNIFORM4IVPROC)load("glUniform4iv"); - glad_glUniformMatrix2fv = (PFNGLUNIFORMMATRIX2FVPROC)load("glUniformMatrix2fv"); - glad_glUniformMatrix3fv = (PFNGLUNIFORMMATRIX3FVPROC)load("glUniformMatrix3fv"); - glad_glUniformMatrix4fv = (PFNGLUNIFORMMATRIX4FVPROC)load("glUniformMatrix4fv"); - glad_glValidateProgram = (PFNGLVALIDATEPROGRAMPROC)load("glValidateProgram"); - glad_glVertexAttrib1d = (PFNGLVERTEXATTRIB1DPROC)load("glVertexAttrib1d"); - glad_glVertexAttrib1dv = (PFNGLVERTEXATTRIB1DVPROC)load("glVertexAttrib1dv"); - glad_glVertexAttrib1f = (PFNGLVERTEXATTRIB1FPROC)load("glVertexAttrib1f"); - glad_glVertexAttrib1fv = (PFNGLVERTEXATTRIB1FVPROC)load("glVertexAttrib1fv"); - glad_glVertexAttrib1s = (PFNGLVERTEXATTRIB1SPROC)load("glVertexAttrib1s"); - glad_glVertexAttrib1sv = (PFNGLVERTEXATTRIB1SVPROC)load("glVertexAttrib1sv"); - glad_glVertexAttrib2d = (PFNGLVERTEXATTRIB2DPROC)load("glVertexAttrib2d"); - glad_glVertexAttrib2dv = (PFNGLVERTEXATTRIB2DVPROC)load("glVertexAttrib2dv"); - glad_glVertexAttrib2f = (PFNGLVERTEXATTRIB2FPROC)load("glVertexAttrib2f"); - glad_glVertexAttrib2fv = (PFNGLVERTEXATTRIB2FVPROC)load("glVertexAttrib2fv"); - glad_glVertexAttrib2s = (PFNGLVERTEXATTRIB2SPROC)load("glVertexAttrib2s"); - glad_glVertexAttrib2sv = (PFNGLVERTEXATTRIB2SVPROC)load("glVertexAttrib2sv"); - glad_glVertexAttrib3d = (PFNGLVERTEXATTRIB3DPROC)load("glVertexAttrib3d"); - glad_glVertexAttrib3dv = (PFNGLVERTEXATTRIB3DVPROC)load("glVertexAttrib3dv"); - glad_glVertexAttrib3f = (PFNGLVERTEXATTRIB3FPROC)load("glVertexAttrib3f"); - glad_glVertexAttrib3fv = (PFNGLVERTEXATTRIB3FVPROC)load("glVertexAttrib3fv"); - glad_glVertexAttrib3s = (PFNGLVERTEXATTRIB3SPROC)load("glVertexAttrib3s"); - glad_glVertexAttrib3sv = (PFNGLVERTEXATTRIB3SVPROC)load("glVertexAttrib3sv"); - glad_glVertexAttrib4Nbv = (PFNGLVERTEXATTRIB4NBVPROC)load("glVertexAttrib4Nbv"); - glad_glVertexAttrib4Niv = (PFNGLVERTEXATTRIB4NIVPROC)load("glVertexAttrib4Niv"); - glad_glVertexAttrib4Nsv = (PFNGLVERTEXATTRIB4NSVPROC)load("glVertexAttrib4Nsv"); - glad_glVertexAttrib4Nub = (PFNGLVERTEXATTRIB4NUBPROC)load("glVertexAttrib4Nub"); - glad_glVertexAttrib4Nubv = (PFNGLVERTEXATTRIB4NUBVPROC)load("glVertexAttrib4Nubv"); - glad_glVertexAttrib4Nuiv = (PFNGLVERTEXATTRIB4NUIVPROC)load("glVertexAttrib4Nuiv"); - glad_glVertexAttrib4Nusv = (PFNGLVERTEXATTRIB4NUSVPROC)load("glVertexAttrib4Nusv"); - glad_glVertexAttrib4bv = (PFNGLVERTEXATTRIB4BVPROC)load("glVertexAttrib4bv"); - glad_glVertexAttrib4d = (PFNGLVERTEXATTRIB4DPROC)load("glVertexAttrib4d"); - glad_glVertexAttrib4dv = (PFNGLVERTEXATTRIB4DVPROC)load("glVertexAttrib4dv"); - glad_glVertexAttrib4f = (PFNGLVERTEXATTRIB4FPROC)load("glVertexAttrib4f"); - glad_glVertexAttrib4fv = (PFNGLVERTEXATTRIB4FVPROC)load("glVertexAttrib4fv"); - glad_glVertexAttrib4iv = (PFNGLVERTEXATTRIB4IVPROC)load("glVertexAttrib4iv"); - glad_glVertexAttrib4s = (PFNGLVERTEXATTRIB4SPROC)load("glVertexAttrib4s"); - glad_glVertexAttrib4sv = (PFNGLVERTEXATTRIB4SVPROC)load("glVertexAttrib4sv"); - glad_glVertexAttrib4ubv = (PFNGLVERTEXATTRIB4UBVPROC)load("glVertexAttrib4ubv"); - glad_glVertexAttrib4uiv = (PFNGLVERTEXATTRIB4UIVPROC)load("glVertexAttrib4uiv"); - glad_glVertexAttrib4usv = (PFNGLVERTEXATTRIB4USVPROC)load("glVertexAttrib4usv"); - glad_glVertexAttribPointer = (PFNGLVERTEXATTRIBPOINTERPROC)load("glVertexAttribPointer"); +static void +load_GL_VERSION_2_0(GLADloadproc load) +{ + if (!GLAD_GL_VERSION_2_0) + return; + glad_glBlendEquationSeparate = (PFNGLBLENDEQUATIONSEPARATEPROC) load("glBlendEquationSeparate"); + glad_glDrawBuffers = (PFNGLDRAWBUFFERSPROC) load("glDrawBuffers"); + glad_glStencilOpSeparate = (PFNGLSTENCILOPSEPARATEPROC) load("glStencilOpSeparate"); + glad_glStencilFuncSeparate = (PFNGLSTENCILFUNCSEPARATEPROC) load("glStencilFuncSeparate"); + glad_glStencilMaskSeparate = (PFNGLSTENCILMASKSEPARATEPROC) load("glStencilMaskSeparate"); + glad_glAttachShader = (PFNGLATTACHSHADERPROC) load("glAttachShader"); + glad_glBindAttribLocation = (PFNGLBINDATTRIBLOCATIONPROC) load("glBindAttribLocation"); + glad_glCompileShader = (PFNGLCOMPILESHADERPROC) load("glCompileShader"); + glad_glCreateProgram = (PFNGLCREATEPROGRAMPROC) load("glCreateProgram"); + glad_glCreateShader = (PFNGLCREATESHADERPROC) load("glCreateShader"); + glad_glDeleteProgram = (PFNGLDELETEPROGRAMPROC) load("glDeleteProgram"); + glad_glDeleteShader = (PFNGLDELETESHADERPROC) load("glDeleteShader"); + glad_glDetachShader = (PFNGLDETACHSHADERPROC) load("glDetachShader"); + glad_glDisableVertexAttribArray = (PFNGLDISABLEVERTEXATTRIBARRAYPROC) load("glDisableVertexAttribArray"); + glad_glEnableVertexAttribArray = (PFNGLENABLEVERTEXATTRIBARRAYPROC) load("glEnableVertexAttribArray"); + glad_glGetActiveAttrib = (PFNGLGETACTIVEATTRIBPROC) load("glGetActiveAttrib"); + glad_glGetActiveUniform = (PFNGLGETACTIVEUNIFORMPROC) load("glGetActiveUniform"); + glad_glGetAttachedShaders = (PFNGLGETATTACHEDSHADERSPROC) load("glGetAttachedShaders"); + glad_glGetAttribLocation = (PFNGLGETATTRIBLOCATIONPROC) load("glGetAttribLocation"); + glad_glGetProgramiv = (PFNGLGETPROGRAMIVPROC) load("glGetProgramiv"); + glad_glGetProgramInfoLog = (PFNGLGETPROGRAMINFOLOGPROC) load("glGetProgramInfoLog"); + glad_glGetShaderiv = (PFNGLGETSHADERIVPROC) load("glGetShaderiv"); + glad_glGetShaderInfoLog = (PFNGLGETSHADERINFOLOGPROC) load("glGetShaderInfoLog"); + glad_glGetShaderSource = (PFNGLGETSHADERSOURCEPROC) load("glGetShaderSource"); + glad_glGetUniformLocation = (PFNGLGETUNIFORMLOCATIONPROC) load("glGetUniformLocation"); + glad_glGetUniformfv = (PFNGLGETUNIFORMFVPROC) load("glGetUniformfv"); + glad_glGetUniformiv = (PFNGLGETUNIFORMIVPROC) load("glGetUniformiv"); + glad_glGetVertexAttribdv = (PFNGLGETVERTEXATTRIBDVPROC) load("glGetVertexAttribdv"); + glad_glGetVertexAttribfv = (PFNGLGETVERTEXATTRIBFVPROC) load("glGetVertexAttribfv"); + glad_glGetVertexAttribiv = (PFNGLGETVERTEXATTRIBIVPROC) load("glGetVertexAttribiv"); + glad_glGetVertexAttribPointerv = (PFNGLGETVERTEXATTRIBPOINTERVPROC) load("glGetVertexAttribPointerv"); + glad_glIsProgram = (PFNGLISPROGRAMPROC) load("glIsProgram"); + glad_glIsShader = (PFNGLISSHADERPROC) load("glIsShader"); + glad_glLinkProgram = (PFNGLLINKPROGRAMPROC) load("glLinkProgram"); + glad_glShaderSource = (PFNGLSHADERSOURCEPROC) load("glShaderSource"); + glad_glUseProgram = (PFNGLUSEPROGRAMPROC) load("glUseProgram"); + glad_glUniform1f = (PFNGLUNIFORM1FPROC) load("glUniform1f"); + glad_glUniform2f = (PFNGLUNIFORM2FPROC) load("glUniform2f"); + glad_glUniform3f = (PFNGLUNIFORM3FPROC) load("glUniform3f"); + glad_glUniform4f = (PFNGLUNIFORM4FPROC) load("glUniform4f"); + glad_glUniform1i = (PFNGLUNIFORM1IPROC) load("glUniform1i"); + glad_glUniform2i = (PFNGLUNIFORM2IPROC) load("glUniform2i"); + glad_glUniform3i = (PFNGLUNIFORM3IPROC) load("glUniform3i"); + glad_glUniform4i = (PFNGLUNIFORM4IPROC) load("glUniform4i"); + glad_glUniform1fv = (PFNGLUNIFORM1FVPROC) load("glUniform1fv"); + glad_glUniform2fv = (PFNGLUNIFORM2FVPROC) load("glUniform2fv"); + glad_glUniform3fv = (PFNGLUNIFORM3FVPROC) load("glUniform3fv"); + glad_glUniform4fv = (PFNGLUNIFORM4FVPROC) load("glUniform4fv"); + glad_glUniform1iv = (PFNGLUNIFORM1IVPROC) load("glUniform1iv"); + glad_glUniform2iv = (PFNGLUNIFORM2IVPROC) load("glUniform2iv"); + glad_glUniform3iv = (PFNGLUNIFORM3IVPROC) load("glUniform3iv"); + glad_glUniform4iv = (PFNGLUNIFORM4IVPROC) load("glUniform4iv"); + glad_glUniformMatrix2fv = (PFNGLUNIFORMMATRIX2FVPROC) load("glUniformMatrix2fv"); + glad_glUniformMatrix3fv = (PFNGLUNIFORMMATRIX3FVPROC) load("glUniformMatrix3fv"); + glad_glUniformMatrix4fv = (PFNGLUNIFORMMATRIX4FVPROC) load("glUniformMatrix4fv"); + glad_glValidateProgram = (PFNGLVALIDATEPROGRAMPROC) load("glValidateProgram"); + glad_glVertexAttrib1d = (PFNGLVERTEXATTRIB1DPROC) load("glVertexAttrib1d"); + glad_glVertexAttrib1dv = (PFNGLVERTEXATTRIB1DVPROC) load("glVertexAttrib1dv"); + glad_glVertexAttrib1f = (PFNGLVERTEXATTRIB1FPROC) load("glVertexAttrib1f"); + glad_glVertexAttrib1fv = (PFNGLVERTEXATTRIB1FVPROC) load("glVertexAttrib1fv"); + glad_glVertexAttrib1s = (PFNGLVERTEXATTRIB1SPROC) load("glVertexAttrib1s"); + glad_glVertexAttrib1sv = (PFNGLVERTEXATTRIB1SVPROC) load("glVertexAttrib1sv"); + glad_glVertexAttrib2d = (PFNGLVERTEXATTRIB2DPROC) load("glVertexAttrib2d"); + glad_glVertexAttrib2dv = (PFNGLVERTEXATTRIB2DVPROC) load("glVertexAttrib2dv"); + glad_glVertexAttrib2f = (PFNGLVERTEXATTRIB2FPROC) load("glVertexAttrib2f"); + glad_glVertexAttrib2fv = (PFNGLVERTEXATTRIB2FVPROC) load("glVertexAttrib2fv"); + glad_glVertexAttrib2s = (PFNGLVERTEXATTRIB2SPROC) load("glVertexAttrib2s"); + glad_glVertexAttrib2sv = (PFNGLVERTEXATTRIB2SVPROC) load("glVertexAttrib2sv"); + glad_glVertexAttrib3d = (PFNGLVERTEXATTRIB3DPROC) load("glVertexAttrib3d"); + glad_glVertexAttrib3dv = (PFNGLVERTEXATTRIB3DVPROC) load("glVertexAttrib3dv"); + glad_glVertexAttrib3f = (PFNGLVERTEXATTRIB3FPROC) load("glVertexAttrib3f"); + glad_glVertexAttrib3fv = (PFNGLVERTEXATTRIB3FVPROC) load("glVertexAttrib3fv"); + glad_glVertexAttrib3s = (PFNGLVERTEXATTRIB3SPROC) load("glVertexAttrib3s"); + glad_glVertexAttrib3sv = (PFNGLVERTEXATTRIB3SVPROC) load("glVertexAttrib3sv"); + glad_glVertexAttrib4Nbv = (PFNGLVERTEXATTRIB4NBVPROC) load("glVertexAttrib4Nbv"); + glad_glVertexAttrib4Niv = (PFNGLVERTEXATTRIB4NIVPROC) load("glVertexAttrib4Niv"); + glad_glVertexAttrib4Nsv = (PFNGLVERTEXATTRIB4NSVPROC) load("glVertexAttrib4Nsv"); + glad_glVertexAttrib4Nub = (PFNGLVERTEXATTRIB4NUBPROC) load("glVertexAttrib4Nub"); + glad_glVertexAttrib4Nubv = (PFNGLVERTEXATTRIB4NUBVPROC) load("glVertexAttrib4Nubv"); + glad_glVertexAttrib4Nuiv = (PFNGLVERTEXATTRIB4NUIVPROC) load("glVertexAttrib4Nuiv"); + glad_glVertexAttrib4Nusv = (PFNGLVERTEXATTRIB4NUSVPROC) load("glVertexAttrib4Nusv"); + glad_glVertexAttrib4bv = (PFNGLVERTEXATTRIB4BVPROC) load("glVertexAttrib4bv"); + glad_glVertexAttrib4d = (PFNGLVERTEXATTRIB4DPROC) load("glVertexAttrib4d"); + glad_glVertexAttrib4dv = (PFNGLVERTEXATTRIB4DVPROC) load("glVertexAttrib4dv"); + glad_glVertexAttrib4f = (PFNGLVERTEXATTRIB4FPROC) load("glVertexAttrib4f"); + glad_glVertexAttrib4fv = (PFNGLVERTEXATTRIB4FVPROC) load("glVertexAttrib4fv"); + glad_glVertexAttrib4iv = (PFNGLVERTEXATTRIB4IVPROC) load("glVertexAttrib4iv"); + glad_glVertexAttrib4s = (PFNGLVERTEXATTRIB4SPROC) load("glVertexAttrib4s"); + glad_glVertexAttrib4sv = (PFNGLVERTEXATTRIB4SVPROC) load("glVertexAttrib4sv"); + glad_glVertexAttrib4ubv = (PFNGLVERTEXATTRIB4UBVPROC) load("glVertexAttrib4ubv"); + glad_glVertexAttrib4uiv = (PFNGLVERTEXATTRIB4UIVPROC) load("glVertexAttrib4uiv"); + glad_glVertexAttrib4usv = (PFNGLVERTEXATTRIB4USVPROC) load("glVertexAttrib4usv"); + glad_glVertexAttribPointer = (PFNGLVERTEXATTRIBPOINTERPROC) load("glVertexAttribPointer"); } -static void load_GL_VERSION_2_1(GLADloadproc load) { - if(!GLAD_GL_VERSION_2_1) return; - glad_glUniformMatrix2x3fv = (PFNGLUNIFORMMATRIX2X3FVPROC)load("glUniformMatrix2x3fv"); - glad_glUniformMatrix3x2fv = (PFNGLUNIFORMMATRIX3X2FVPROC)load("glUniformMatrix3x2fv"); - glad_glUniformMatrix2x4fv = (PFNGLUNIFORMMATRIX2X4FVPROC)load("glUniformMatrix2x4fv"); - glad_glUniformMatrix4x2fv = (PFNGLUNIFORMMATRIX4X2FVPROC)load("glUniformMatrix4x2fv"); - glad_glUniformMatrix3x4fv = (PFNGLUNIFORMMATRIX3X4FVPROC)load("glUniformMatrix3x4fv"); - glad_glUniformMatrix4x3fv = (PFNGLUNIFORMMATRIX4X3FVPROC)load("glUniformMatrix4x3fv"); +static void +load_GL_VERSION_2_1(GLADloadproc load) +{ + if (!GLAD_GL_VERSION_2_1) + return; + glad_glUniformMatrix2x3fv = (PFNGLUNIFORMMATRIX2X3FVPROC) load("glUniformMatrix2x3fv"); + glad_glUniformMatrix3x2fv = (PFNGLUNIFORMMATRIX3X2FVPROC) load("glUniformMatrix3x2fv"); + glad_glUniformMatrix2x4fv = (PFNGLUNIFORMMATRIX2X4FVPROC) load("glUniformMatrix2x4fv"); + glad_glUniformMatrix4x2fv = (PFNGLUNIFORMMATRIX4X2FVPROC) load("glUniformMatrix4x2fv"); + glad_glUniformMatrix3x4fv = (PFNGLUNIFORMMATRIX3X4FVPROC) load("glUniformMatrix3x4fv"); + glad_glUniformMatrix4x3fv = (PFNGLUNIFORMMATRIX4X3FVPROC) load("glUniformMatrix4x3fv"); } -static void load_GL_VERSION_3_0(GLADloadproc load) { - if(!GLAD_GL_VERSION_3_0) return; - glad_glColorMaski = (PFNGLCOLORMASKIPROC)load("glColorMaski"); - glad_glGetBooleani_v = (PFNGLGETBOOLEANI_VPROC)load("glGetBooleani_v"); - glad_glGetIntegeri_v = (PFNGLGETINTEGERI_VPROC)load("glGetIntegeri_v"); - glad_glEnablei = (PFNGLENABLEIPROC)load("glEnablei"); - glad_glDisablei = (PFNGLDISABLEIPROC)load("glDisablei"); - glad_glIsEnabledi = (PFNGLISENABLEDIPROC)load("glIsEnabledi"); - glad_glBeginTransformFeedback = (PFNGLBEGINTRANSFORMFEEDBACKPROC)load("glBeginTransformFeedback"); - glad_glEndTransformFeedback = (PFNGLENDTRANSFORMFEEDBACKPROC)load("glEndTransformFeedback"); - glad_glBindBufferRange = (PFNGLBINDBUFFERRANGEPROC)load("glBindBufferRange"); - glad_glBindBufferBase = (PFNGLBINDBUFFERBASEPROC)load("glBindBufferBase"); - glad_glTransformFeedbackVaryings = (PFNGLTRANSFORMFEEDBACKVARYINGSPROC)load("glTransformFeedbackVaryings"); - glad_glGetTransformFeedbackVarying = (PFNGLGETTRANSFORMFEEDBACKVARYINGPROC)load("glGetTransformFeedbackVarying"); - glad_glClampColor = (PFNGLCLAMPCOLORPROC)load("glClampColor"); - glad_glBeginConditionalRender = (PFNGLBEGINCONDITIONALRENDERPROC)load("glBeginConditionalRender"); - glad_glEndConditionalRender = (PFNGLENDCONDITIONALRENDERPROC)load("glEndConditionalRender"); - glad_glVertexAttribIPointer = (PFNGLVERTEXATTRIBIPOINTERPROC)load("glVertexAttribIPointer"); - glad_glGetVertexAttribIiv = (PFNGLGETVERTEXATTRIBIIVPROC)load("glGetVertexAttribIiv"); - glad_glGetVertexAttribIuiv = (PFNGLGETVERTEXATTRIBIUIVPROC)load("glGetVertexAttribIuiv"); - glad_glVertexAttribI1i = (PFNGLVERTEXATTRIBI1IPROC)load("glVertexAttribI1i"); - glad_glVertexAttribI2i = (PFNGLVERTEXATTRIBI2IPROC)load("glVertexAttribI2i"); - glad_glVertexAttribI3i = (PFNGLVERTEXATTRIBI3IPROC)load("glVertexAttribI3i"); - glad_glVertexAttribI4i = (PFNGLVERTEXATTRIBI4IPROC)load("glVertexAttribI4i"); - glad_glVertexAttribI1ui = (PFNGLVERTEXATTRIBI1UIPROC)load("glVertexAttribI1ui"); - glad_glVertexAttribI2ui = (PFNGLVERTEXATTRIBI2UIPROC)load("glVertexAttribI2ui"); - glad_glVertexAttribI3ui = (PFNGLVERTEXATTRIBI3UIPROC)load("glVertexAttribI3ui"); - glad_glVertexAttribI4ui = (PFNGLVERTEXATTRIBI4UIPROC)load("glVertexAttribI4ui"); - glad_glVertexAttribI1iv = (PFNGLVERTEXATTRIBI1IVPROC)load("glVertexAttribI1iv"); - glad_glVertexAttribI2iv = (PFNGLVERTEXATTRIBI2IVPROC)load("glVertexAttribI2iv"); - glad_glVertexAttribI3iv = (PFNGLVERTEXATTRIBI3IVPROC)load("glVertexAttribI3iv"); - glad_glVertexAttribI4iv = (PFNGLVERTEXATTRIBI4IVPROC)load("glVertexAttribI4iv"); - glad_glVertexAttribI1uiv = (PFNGLVERTEXATTRIBI1UIVPROC)load("glVertexAttribI1uiv"); - glad_glVertexAttribI2uiv = (PFNGLVERTEXATTRIBI2UIVPROC)load("glVertexAttribI2uiv"); - glad_glVertexAttribI3uiv = (PFNGLVERTEXATTRIBI3UIVPROC)load("glVertexAttribI3uiv"); - glad_glVertexAttribI4uiv = (PFNGLVERTEXATTRIBI4UIVPROC)load("glVertexAttribI4uiv"); - glad_glVertexAttribI4bv = (PFNGLVERTEXATTRIBI4BVPROC)load("glVertexAttribI4bv"); - glad_glVertexAttribI4sv = (PFNGLVERTEXATTRIBI4SVPROC)load("glVertexAttribI4sv"); - glad_glVertexAttribI4ubv = (PFNGLVERTEXATTRIBI4UBVPROC)load("glVertexAttribI4ubv"); - glad_glVertexAttribI4usv = (PFNGLVERTEXATTRIBI4USVPROC)load("glVertexAttribI4usv"); - glad_glGetUniformuiv = (PFNGLGETUNIFORMUIVPROC)load("glGetUniformuiv"); - glad_glBindFragDataLocation = (PFNGLBINDFRAGDATALOCATIONPROC)load("glBindFragDataLocation"); - glad_glGetFragDataLocation = (PFNGLGETFRAGDATALOCATIONPROC)load("glGetFragDataLocation"); - glad_glUniform1ui = (PFNGLUNIFORM1UIPROC)load("glUniform1ui"); - glad_glUniform2ui = (PFNGLUNIFORM2UIPROC)load("glUniform2ui"); - glad_glUniform3ui = (PFNGLUNIFORM3UIPROC)load("glUniform3ui"); - glad_glUniform4ui = (PFNGLUNIFORM4UIPROC)load("glUniform4ui"); - glad_glUniform1uiv = (PFNGLUNIFORM1UIVPROC)load("glUniform1uiv"); - glad_glUniform2uiv = (PFNGLUNIFORM2UIVPROC)load("glUniform2uiv"); - glad_glUniform3uiv = (PFNGLUNIFORM3UIVPROC)load("glUniform3uiv"); - glad_glUniform4uiv = (PFNGLUNIFORM4UIVPROC)load("glUniform4uiv"); - glad_glTexParameterIiv = (PFNGLTEXPARAMETERIIVPROC)load("glTexParameterIiv"); - glad_glTexParameterIuiv = (PFNGLTEXPARAMETERIUIVPROC)load("glTexParameterIuiv"); - glad_glGetTexParameterIiv = (PFNGLGETTEXPARAMETERIIVPROC)load("glGetTexParameterIiv"); - glad_glGetTexParameterIuiv = (PFNGLGETTEXPARAMETERIUIVPROC)load("glGetTexParameterIuiv"); - glad_glClearBufferiv = (PFNGLCLEARBUFFERIVPROC)load("glClearBufferiv"); - glad_glClearBufferuiv = (PFNGLCLEARBUFFERUIVPROC)load("glClearBufferuiv"); - glad_glClearBufferfv = (PFNGLCLEARBUFFERFVPROC)load("glClearBufferfv"); - glad_glClearBufferfi = (PFNGLCLEARBUFFERFIPROC)load("glClearBufferfi"); - glad_glGetStringi = (PFNGLGETSTRINGIPROC)load("glGetStringi"); - glad_glIsRenderbuffer = (PFNGLISRENDERBUFFERPROC)load("glIsRenderbuffer"); - glad_glBindRenderbuffer = (PFNGLBINDRENDERBUFFERPROC)load("glBindRenderbuffer"); - glad_glDeleteRenderbuffers = (PFNGLDELETERENDERBUFFERSPROC)load("glDeleteRenderbuffers"); - glad_glGenRenderbuffers = (PFNGLGENRENDERBUFFERSPROC)load("glGenRenderbuffers"); - glad_glRenderbufferStorage = (PFNGLRENDERBUFFERSTORAGEPROC)load("glRenderbufferStorage"); - glad_glGetRenderbufferParameteriv = (PFNGLGETRENDERBUFFERPARAMETERIVPROC)load("glGetRenderbufferParameteriv"); - glad_glIsFramebuffer = (PFNGLISFRAMEBUFFERPROC)load("glIsFramebuffer"); - glad_glBindFramebuffer = (PFNGLBINDFRAMEBUFFERPROC)load("glBindFramebuffer"); - glad_glDeleteFramebuffers = (PFNGLDELETEFRAMEBUFFERSPROC)load("glDeleteFramebuffers"); - glad_glGenFramebuffers = (PFNGLGENFRAMEBUFFERSPROC)load("glGenFramebuffers"); - glad_glCheckFramebufferStatus = (PFNGLCHECKFRAMEBUFFERSTATUSPROC)load("glCheckFramebufferStatus"); - glad_glFramebufferTexture1D = (PFNGLFRAMEBUFFERTEXTURE1DPROC)load("glFramebufferTexture1D"); - glad_glFramebufferTexture2D = (PFNGLFRAMEBUFFERTEXTURE2DPROC)load("glFramebufferTexture2D"); - glad_glFramebufferTexture3D = (PFNGLFRAMEBUFFERTEXTURE3DPROC)load("glFramebufferTexture3D"); - glad_glFramebufferRenderbuffer = (PFNGLFRAMEBUFFERRENDERBUFFERPROC)load("glFramebufferRenderbuffer"); - glad_glGetFramebufferAttachmentParameteriv = (PFNGLGETFRAMEBUFFERATTACHMENTPARAMETERIVPROC)load("glGetFramebufferAttachmentParameteriv"); - glad_glGenerateMipmap = (PFNGLGENERATEMIPMAPPROC)load("glGenerateMipmap"); - glad_glBlitFramebuffer = (PFNGLBLITFRAMEBUFFERPROC)load("glBlitFramebuffer"); - glad_glRenderbufferStorageMultisample = (PFNGLRENDERBUFFERSTORAGEMULTISAMPLEPROC)load("glRenderbufferStorageMultisample"); - glad_glFramebufferTextureLayer = (PFNGLFRAMEBUFFERTEXTURELAYERPROC)load("glFramebufferTextureLayer"); - glad_glMapBufferRange = (PFNGLMAPBUFFERRANGEPROC)load("glMapBufferRange"); - glad_glFlushMappedBufferRange = (PFNGLFLUSHMAPPEDBUFFERRANGEPROC)load("glFlushMappedBufferRange"); - glad_glBindVertexArray = (PFNGLBINDVERTEXARRAYPROC)load("glBindVertexArray"); - glad_glDeleteVertexArrays = (PFNGLDELETEVERTEXARRAYSPROC)load("glDeleteVertexArrays"); - glad_glGenVertexArrays = (PFNGLGENVERTEXARRAYSPROC)load("glGenVertexArrays"); - glad_glIsVertexArray = (PFNGLISVERTEXARRAYPROC)load("glIsVertexArray"); +static void +load_GL_VERSION_3_0(GLADloadproc load) +{ + if (!GLAD_GL_VERSION_3_0) + return; + glad_glColorMaski = (PFNGLCOLORMASKIPROC) load("glColorMaski"); + glad_glGetBooleani_v = (PFNGLGETBOOLEANI_VPROC) load("glGetBooleani_v"); + glad_glGetIntegeri_v = (PFNGLGETINTEGERI_VPROC) load("glGetIntegeri_v"); + glad_glEnablei = (PFNGLENABLEIPROC) load("glEnablei"); + glad_glDisablei = (PFNGLDISABLEIPROC) load("glDisablei"); + glad_glIsEnabledi = (PFNGLISENABLEDIPROC) load("glIsEnabledi"); + glad_glBeginTransformFeedback = (PFNGLBEGINTRANSFORMFEEDBACKPROC) load("glBeginTransformFeedback"); + glad_glEndTransformFeedback = (PFNGLENDTRANSFORMFEEDBACKPROC) load("glEndTransformFeedback"); + glad_glBindBufferRange = (PFNGLBINDBUFFERRANGEPROC) load("glBindBufferRange"); + glad_glBindBufferBase = (PFNGLBINDBUFFERBASEPROC) load("glBindBufferBase"); + glad_glTransformFeedbackVaryings = (PFNGLTRANSFORMFEEDBACKVARYINGSPROC) load("glTransformFeedbackVaryings"); + glad_glGetTransformFeedbackVarying = (PFNGLGETTRANSFORMFEEDBACKVARYINGPROC) load("glGetTransformFeedbackVarying"); + glad_glClampColor = (PFNGLCLAMPCOLORPROC) load("glClampColor"); + glad_glBeginConditionalRender = (PFNGLBEGINCONDITIONALRENDERPROC) load("glBeginConditionalRender"); + glad_glEndConditionalRender = (PFNGLENDCONDITIONALRENDERPROC) load("glEndConditionalRender"); + glad_glVertexAttribIPointer = (PFNGLVERTEXATTRIBIPOINTERPROC) load("glVertexAttribIPointer"); + glad_glGetVertexAttribIiv = (PFNGLGETVERTEXATTRIBIIVPROC) load("glGetVertexAttribIiv"); + glad_glGetVertexAttribIuiv = (PFNGLGETVERTEXATTRIBIUIVPROC) load("glGetVertexAttribIuiv"); + glad_glVertexAttribI1i = (PFNGLVERTEXATTRIBI1IPROC) load("glVertexAttribI1i"); + glad_glVertexAttribI2i = (PFNGLVERTEXATTRIBI2IPROC) load("glVertexAttribI2i"); + glad_glVertexAttribI3i = (PFNGLVERTEXATTRIBI3IPROC) load("glVertexAttribI3i"); + glad_glVertexAttribI4i = (PFNGLVERTEXATTRIBI4IPROC) load("glVertexAttribI4i"); + glad_glVertexAttribI1ui = (PFNGLVERTEXATTRIBI1UIPROC) load("glVertexAttribI1ui"); + glad_glVertexAttribI2ui = (PFNGLVERTEXATTRIBI2UIPROC) load("glVertexAttribI2ui"); + glad_glVertexAttribI3ui = (PFNGLVERTEXATTRIBI3UIPROC) load("glVertexAttribI3ui"); + glad_glVertexAttribI4ui = (PFNGLVERTEXATTRIBI4UIPROC) load("glVertexAttribI4ui"); + glad_glVertexAttribI1iv = (PFNGLVERTEXATTRIBI1IVPROC) load("glVertexAttribI1iv"); + glad_glVertexAttribI2iv = (PFNGLVERTEXATTRIBI2IVPROC) load("glVertexAttribI2iv"); + glad_glVertexAttribI3iv = (PFNGLVERTEXATTRIBI3IVPROC) load("glVertexAttribI3iv"); + glad_glVertexAttribI4iv = (PFNGLVERTEXATTRIBI4IVPROC) load("glVertexAttribI4iv"); + glad_glVertexAttribI1uiv = (PFNGLVERTEXATTRIBI1UIVPROC) load("glVertexAttribI1uiv"); + glad_glVertexAttribI2uiv = (PFNGLVERTEXATTRIBI2UIVPROC) load("glVertexAttribI2uiv"); + glad_glVertexAttribI3uiv = (PFNGLVERTEXATTRIBI3UIVPROC) load("glVertexAttribI3uiv"); + glad_glVertexAttribI4uiv = (PFNGLVERTEXATTRIBI4UIVPROC) load("glVertexAttribI4uiv"); + glad_glVertexAttribI4bv = (PFNGLVERTEXATTRIBI4BVPROC) load("glVertexAttribI4bv"); + glad_glVertexAttribI4sv = (PFNGLVERTEXATTRIBI4SVPROC) load("glVertexAttribI4sv"); + glad_glVertexAttribI4ubv = (PFNGLVERTEXATTRIBI4UBVPROC) load("glVertexAttribI4ubv"); + glad_glVertexAttribI4usv = (PFNGLVERTEXATTRIBI4USVPROC) load("glVertexAttribI4usv"); + glad_glGetUniformuiv = (PFNGLGETUNIFORMUIVPROC) load("glGetUniformuiv"); + glad_glBindFragDataLocation = (PFNGLBINDFRAGDATALOCATIONPROC) load("glBindFragDataLocation"); + glad_glGetFragDataLocation = (PFNGLGETFRAGDATALOCATIONPROC) load("glGetFragDataLocation"); + glad_glUniform1ui = (PFNGLUNIFORM1UIPROC) load("glUniform1ui"); + glad_glUniform2ui = (PFNGLUNIFORM2UIPROC) load("glUniform2ui"); + glad_glUniform3ui = (PFNGLUNIFORM3UIPROC) load("glUniform3ui"); + glad_glUniform4ui = (PFNGLUNIFORM4UIPROC) load("glUniform4ui"); + glad_glUniform1uiv = (PFNGLUNIFORM1UIVPROC) load("glUniform1uiv"); + glad_glUniform2uiv = (PFNGLUNIFORM2UIVPROC) load("glUniform2uiv"); + glad_glUniform3uiv = (PFNGLUNIFORM3UIVPROC) load("glUniform3uiv"); + glad_glUniform4uiv = (PFNGLUNIFORM4UIVPROC) load("glUniform4uiv"); + glad_glTexParameterIiv = (PFNGLTEXPARAMETERIIVPROC) load("glTexParameterIiv"); + glad_glTexParameterIuiv = (PFNGLTEXPARAMETERIUIVPROC) load("glTexParameterIuiv"); + glad_glGetTexParameterIiv = (PFNGLGETTEXPARAMETERIIVPROC) load("glGetTexParameterIiv"); + glad_glGetTexParameterIuiv = (PFNGLGETTEXPARAMETERIUIVPROC) load("glGetTexParameterIuiv"); + glad_glClearBufferiv = (PFNGLCLEARBUFFERIVPROC) load("glClearBufferiv"); + glad_glClearBufferuiv = (PFNGLCLEARBUFFERUIVPROC) load("glClearBufferuiv"); + glad_glClearBufferfv = (PFNGLCLEARBUFFERFVPROC) load("glClearBufferfv"); + glad_glClearBufferfi = (PFNGLCLEARBUFFERFIPROC) load("glClearBufferfi"); + glad_glGetStringi = (PFNGLGETSTRINGIPROC) load("glGetStringi"); + glad_glIsRenderbuffer = (PFNGLISRENDERBUFFERPROC) load("glIsRenderbuffer"); + glad_glBindRenderbuffer = (PFNGLBINDRENDERBUFFERPROC) load("glBindRenderbuffer"); + glad_glDeleteRenderbuffers = (PFNGLDELETERENDERBUFFERSPROC) load("glDeleteRenderbuffers"); + glad_glGenRenderbuffers = (PFNGLGENRENDERBUFFERSPROC) load("glGenRenderbuffers"); + glad_glRenderbufferStorage = (PFNGLRENDERBUFFERSTORAGEPROC) load("glRenderbufferStorage"); + glad_glGetRenderbufferParameteriv = (PFNGLGETRENDERBUFFERPARAMETERIVPROC) load("glGetRenderbufferParameteriv"); + glad_glIsFramebuffer = (PFNGLISFRAMEBUFFERPROC) load("glIsFramebuffer"); + glad_glBindFramebuffer = (PFNGLBINDFRAMEBUFFERPROC) load("glBindFramebuffer"); + glad_glDeleteFramebuffers = (PFNGLDELETEFRAMEBUFFERSPROC) load("glDeleteFramebuffers"); + glad_glGenFramebuffers = (PFNGLGENFRAMEBUFFERSPROC) load("glGenFramebuffers"); + glad_glCheckFramebufferStatus = (PFNGLCHECKFRAMEBUFFERSTATUSPROC) load("glCheckFramebufferStatus"); + glad_glFramebufferTexture1D = (PFNGLFRAMEBUFFERTEXTURE1DPROC) load("glFramebufferTexture1D"); + glad_glFramebufferTexture2D = (PFNGLFRAMEBUFFERTEXTURE2DPROC) load("glFramebufferTexture2D"); + glad_glFramebufferTexture3D = (PFNGLFRAMEBUFFERTEXTURE3DPROC) load("glFramebufferTexture3D"); + glad_glFramebufferRenderbuffer = (PFNGLFRAMEBUFFERRENDERBUFFERPROC) load("glFramebufferRenderbuffer"); + glad_glGetFramebufferAttachmentParameteriv = (PFNGLGETFRAMEBUFFERATTACHMENTPARAMETERIVPROC) load("glGetFramebufferAttachmentParameteriv"); + glad_glGenerateMipmap = (PFNGLGENERATEMIPMAPPROC) load("glGenerateMipmap"); + glad_glBlitFramebuffer = (PFNGLBLITFRAMEBUFFERPROC) load("glBlitFramebuffer"); + glad_glRenderbufferStorageMultisample = (PFNGLRENDERBUFFERSTORAGEMULTISAMPLEPROC) load("glRenderbufferStorageMultisample"); + glad_glFramebufferTextureLayer = (PFNGLFRAMEBUFFERTEXTURELAYERPROC) load("glFramebufferTextureLayer"); + glad_glMapBufferRange = (PFNGLMAPBUFFERRANGEPROC) load("glMapBufferRange"); + glad_glFlushMappedBufferRange = (PFNGLFLUSHMAPPEDBUFFERRANGEPROC) load("glFlushMappedBufferRange"); + glad_glBindVertexArray = (PFNGLBINDVERTEXARRAYPROC) load("glBindVertexArray"); + glad_glDeleteVertexArrays = (PFNGLDELETEVERTEXARRAYSPROC) load("glDeleteVertexArrays"); + glad_glGenVertexArrays = (PFNGLGENVERTEXARRAYSPROC) load("glGenVertexArrays"); + glad_glIsVertexArray = (PFNGLISVERTEXARRAYPROC) load("glIsVertexArray"); } -static void load_GL_ARB_buffer_storage(GLADloadproc load) { - if(!GLAD_GL_ARB_buffer_storage) return; - glad_glBufferStorage = (PFNGLBUFFERSTORAGEPROC)load("glBufferStorage"); +static void +load_GL_ARB_buffer_storage(GLADloadproc load) +{ + if (!GLAD_GL_ARB_buffer_storage) + return; + glad_glBufferStorage = (PFNGLBUFFERSTORAGEPROC) load("glBufferStorage"); } -static void load_GL_ARB_debug_output(GLADloadproc load) { - if(!GLAD_GL_ARB_debug_output) return; - glad_glDebugMessageControlARB = (PFNGLDEBUGMESSAGECONTROLARBPROC)load("glDebugMessageControlARB"); - glad_glDebugMessageInsertARB = (PFNGLDEBUGMESSAGEINSERTARBPROC)load("glDebugMessageInsertARB"); - glad_glDebugMessageCallbackARB = (PFNGLDEBUGMESSAGECALLBACKARBPROC)load("glDebugMessageCallbackARB"); - glad_glGetDebugMessageLogARB = (PFNGLGETDEBUGMESSAGELOGARBPROC)load("glGetDebugMessageLogARB"); +static void +load_GL_ARB_debug_output(GLADloadproc load) +{ + if (!GLAD_GL_ARB_debug_output) + return; + glad_glDebugMessageControlARB = (PFNGLDEBUGMESSAGECONTROLARBPROC) load("glDebugMessageControlARB"); + glad_glDebugMessageInsertARB = (PFNGLDEBUGMESSAGEINSERTARBPROC) load("glDebugMessageInsertARB"); + glad_glDebugMessageCallbackARB = (PFNGLDEBUGMESSAGECALLBACKARBPROC) load("glDebugMessageCallbackARB"); + glad_glGetDebugMessageLogARB = (PFNGLGETDEBUGMESSAGELOGARBPROC) load("glGetDebugMessageLogARB"); } -static void load_GL_ARB_sync(GLADloadproc load) { - if(!GLAD_GL_ARB_sync) return; - glad_glFenceSync = (PFNGLFENCESYNCPROC)load("glFenceSync"); - glad_glIsSync = (PFNGLISSYNCPROC)load("glIsSync"); - glad_glDeleteSync = (PFNGLDELETESYNCPROC)load("glDeleteSync"); - glad_glClientWaitSync = (PFNGLCLIENTWAITSYNCPROC)load("glClientWaitSync"); - glad_glWaitSync = (PFNGLWAITSYNCPROC)load("glWaitSync"); - glad_glGetInteger64v = (PFNGLGETINTEGER64VPROC)load("glGetInteger64v"); - glad_glGetSynciv = (PFNGLGETSYNCIVPROC)load("glGetSynciv"); +static void +load_GL_ARB_sync(GLADloadproc load) +{ + if (!GLAD_GL_ARB_sync) + return; + glad_glFenceSync = (PFNGLFENCESYNCPROC) load("glFenceSync"); + glad_glIsSync = (PFNGLISSYNCPROC) load("glIsSync"); + glad_glDeleteSync = (PFNGLDELETESYNCPROC) load("glDeleteSync"); + glad_glClientWaitSync = (PFNGLCLIENTWAITSYNCPROC) load("glClientWaitSync"); + glad_glWaitSync = (PFNGLWAITSYNCPROC) load("glWaitSync"); + glad_glGetInteger64v = (PFNGLGETINTEGER64VPROC) load("glGetInteger64v"); + glad_glGetSynciv = (PFNGLGETSYNCIVPROC) load("glGetSynciv"); } -static int find_extensionsGL(void) { - if (!get_exts()) return 0; - GLAD_GL_ARB_buffer_storage = has_ext("GL_ARB_buffer_storage"); - GLAD_GL_ARB_debug_output = has_ext("GL_ARB_debug_output"); - GLAD_GL_ARB_sync = has_ext("GL_ARB_sync"); - free_exts(); - return 1; +static int +find_extensionsGL(void) +{ + if (!get_exts()) + return 0; + GLAD_GL_ARB_buffer_storage = has_ext("GL_ARB_buffer_storage"); + GLAD_GL_ARB_debug_output = has_ext("GL_ARB_debug_output"); + GLAD_GL_ARB_sync = has_ext("GL_ARB_sync"); + free_exts(); + return 1; } -static void find_coreGL(void) { +static void +find_coreGL(void) +{ /* Thank you @elmindreda * https://github.com/elmindreda/greg/blob/master/templates/greg.c.in#L176 @@ -916,18 +971,19 @@ static void find_coreGL(void) { */ int i, major, minor; - const char* version; - const char* prefixes[] = { + const char *version; + const char *prefixes[] = { "OpenGL ES-CM ", "OpenGL ES-CL ", "OpenGL ES ", NULL }; - version = (const char*) glGetString(GL_VERSION); - if (!version) return; + version = (const char *) glGetString(GL_VERSION); + if (!version) + return; - for (i = 0; prefixes[i]; i++) { + for (i = 0; prefixes[i]; i++) { const size_t length = strlen(prefixes[i]); if (strncmp(version, prefixes[i], length) == 0) { version += length; @@ -942,43 +998,50 @@ static void find_coreGL(void) { sscanf(version, "%d.%d", &major, &minor); #endif - GLVersion.major = major; GLVersion.minor = minor; - max_loaded_major = major; max_loaded_minor = minor; - GLAD_GL_VERSION_1_0 = (major == 1 && minor >= 0) || major > 1; - GLAD_GL_VERSION_1_1 = (major == 1 && minor >= 1) || major > 1; - GLAD_GL_VERSION_1_2 = (major == 1 && minor >= 2) || major > 1; - GLAD_GL_VERSION_1_3 = (major == 1 && minor >= 3) || major > 1; - GLAD_GL_VERSION_1_4 = (major == 1 && minor >= 4) || major > 1; - GLAD_GL_VERSION_1_5 = (major == 1 && minor >= 5) || major > 1; - GLAD_GL_VERSION_2_0 = (major == 2 && minor >= 0) || major > 2; - GLAD_GL_VERSION_2_1 = (major == 2 && minor >= 1) || major > 2; - GLAD_GL_VERSION_3_0 = (major == 3 && minor >= 0) || major > 3; - if (GLVersion.major > 3 || (GLVersion.major >= 3 && GLVersion.minor >= 0)) { - max_loaded_major = 3; - max_loaded_minor = 0; - } + GLVersion.major = major; + GLVersion.minor = minor; + max_loaded_major = major; + max_loaded_minor = minor; + GLAD_GL_VERSION_1_0 = (major == 1 && minor >= 0) || major > 1; + GLAD_GL_VERSION_1_1 = (major == 1 && minor >= 1) || major > 1; + GLAD_GL_VERSION_1_2 = (major == 1 && minor >= 2) || major > 1; + GLAD_GL_VERSION_1_3 = (major == 1 && minor >= 3) || major > 1; + GLAD_GL_VERSION_1_4 = (major == 1 && minor >= 4) || major > 1; + GLAD_GL_VERSION_1_5 = (major == 1 && minor >= 5) || major > 1; + GLAD_GL_VERSION_2_0 = (major == 2 && minor >= 0) || major > 2; + GLAD_GL_VERSION_2_1 = (major == 2 && minor >= 1) || major > 2; + GLAD_GL_VERSION_3_0 = (major == 3 && minor >= 0) || major > 3; + if (GLVersion.major > 3 || (GLVersion.major >= 3 && GLVersion.minor >= 0)) { + max_loaded_major = 3; + max_loaded_minor = 0; + } } -int gladLoadGLLoader(GLADloadproc load) { - GLVersion.major = 0; GLVersion.minor = 0; - glGetString = (PFNGLGETSTRINGPROC)load("glGetString"); - if(glGetString == NULL) return 0; - if(glGetString(GL_VERSION) == NULL) return 0; - find_coreGL(); - load_GL_VERSION_1_0(load); - load_GL_VERSION_1_1(load); - load_GL_VERSION_1_2(load); - load_GL_VERSION_1_3(load); - load_GL_VERSION_1_4(load); - load_GL_VERSION_1_5(load); - load_GL_VERSION_2_0(load); - load_GL_VERSION_2_1(load); - load_GL_VERSION_3_0(load); +int +gladLoadGLLoader(GLADloadproc load) +{ + GLVersion.major = 0; + GLVersion.minor = 0; + glGetString = (PFNGLGETSTRINGPROC) load("glGetString"); + if (glGetString == NULL) + return 0; + if (glGetString(GL_VERSION) == NULL) + return 0; + find_coreGL(); + load_GL_VERSION_1_0(load); + load_GL_VERSION_1_1(load); + load_GL_VERSION_1_2(load); + load_GL_VERSION_1_3(load); + load_GL_VERSION_1_4(load); + load_GL_VERSION_1_5(load); + load_GL_VERSION_2_0(load); + load_GL_VERSION_2_1(load); + load_GL_VERSION_3_0(load); - if (!find_extensionsGL()) return 0; - load_GL_ARB_buffer_storage(load); - load_GL_ARB_debug_output(load); - load_GL_ARB_sync(load); - return GLVersion.major != 0 || GLVersion.minor != 0; + if (!find_extensionsGL()) + return 0; + load_GL_ARB_buffer_storage(load); + load_GL_ARB_debug_output(load); + load_GL_ARB_sync(load); + return GLVersion.major != 0 || GLVersion.minor != 0; } - diff --git a/src/win/icons/network_empty.ico b/src/win/icons/network_empty.ico new file mode 100644 index 000000000..4a1a10284 Binary files /dev/null and b/src/win/icons/network_empty.ico differ diff --git a/src/win/languages/cs-CZ.rc b/src/win/languages/cs-CZ.rc index 530a706c9..6c0982c5c 100644 --- a/src/win/languages/cs-CZ.rc +++ b/src/win/languages/cs-CZ.rc @@ -13,113 +13,122 @@ LANGUAGE LANG_CZECH, SUBLANG_DEFAULT // Menu // -MainMenu MENU DISCARDABLE +MainMenu MENU DISCARDABLE BEGIN POPUP "&Akce" BEGIN - MENUITEM "&Klávesnice vyžaduje zábÄ›r", IDM_ACTION_KBD_REQ_CAPTURE - MENUITEM "&Pravý Ctrl je levý Alt", IDM_ACTION_RCTRL_IS_LALT + MENUITEM "&Klávesnice vyžaduje zábÄ›r", IDM_ACTION_KBD_REQ_CAPTURE + MENUITEM "&Pravý Ctrl je levý Alt", IDM_ACTION_RCTRL_IS_LALT MENUITEM SEPARATOR - MENUITEM "&Resetovat", IDM_ACTION_HRESET - MENUITEM "&Ctrl+Alt+Del\tCtrl+F12", IDM_ACTION_RESET_CAD + MENUITEM "&Resetovat", IDM_ACTION_HRESET + MENUITEM "&Ctrl+Alt+Del\tCtrl+F12", IDM_ACTION_RESET_CAD MENUITEM SEPARATOR - MENUITEM "Ctrl+Alt+&Esc", IDM_ACTION_CTRL_ALT_ESC + MENUITEM "Ctrl+Alt+&Esc", IDM_ACTION_CTRL_ALT_ESC MENUITEM SEPARATOR - MENUITEM "P&ozastavit", IDM_ACTION_PAUSE + MENUITEM "P&ozastavit", IDM_ACTION_PAUSE MENUITEM SEPARATOR - MENUITEM "&UkonÄit", IDM_ACTION_EXIT + MENUITEM "&UkonÄit", IDM_ACTION_EXIT END POPUP "&Zobrazení" BEGIN - MENUITEM "&Schovat stavový řádek", IDM_VID_HIDE_STATUS_BAR - MENUITEM "Schovat panel &nástrojů", IDM_VID_HIDE_TOOLBAR + MENUITEM "&Schovat stavový řádek", IDM_VID_HIDE_STATUS_BAR + MENUITEM "Schovat panel &nástrojů", IDM_VID_HIDE_TOOLBAR MENUITEM SEPARATOR - MENUITEM "&MÄ›nitelná velikost okna", IDM_VID_RESIZE - MENUITEM "&Pamatovat velikost a pozici", IDM_VID_REMEMBER + MENUITEM "&Show non-primary monitors", IDM_VID_MONITORS + MENUITEM "&MÄ›nitelná velikost okna", IDM_VID_RESIZE + MENUITEM "&Pamatovat velikost a pozici", IDM_VID_REMEMBER MENUITEM SEPARATOR POPUP "&Renderer" BEGIN - MENUITEM "&SDL (Software)", IDM_VID_SDL_SW - MENUITEM "SDL (&Hardware)", IDM_VID_SDL_HW - MENUITEM "SDL (&OpenGL)", IDM_VID_SDL_OPENGL - MENUITEM "Open&GL (3.0 Core)", IDM_VID_OPENGL_CORE + MENUITEM "&SDL (Software)", IDM_VID_SDL_SW + MENUITEM "SDL (&Hardware)", IDM_VID_SDL_HW + MENUITEM "SDL (&OpenGL)", IDM_VID_SDL_OPENGL + MENUITEM "Open&GL (3.0 Core)", IDM_VID_OPENGL_CORE #ifdef USE_VNC - MENUITEM "&VNC", IDM_VID_VNC + MENUITEM "&VNC", IDM_VID_VNC #endif END MENUITEM SEPARATOR - MENUITEM "&Zadat velikost...", IDM_VID_SPECIFY_DIM - MENUITEM "&Dodržovat pomÄ›r stran 4:3", IDM_VID_FORCE43 + MENUITEM "&Zadat velikost...", IDM_VID_SPECIFY_DIM + MENUITEM "&Dodržovat pomÄ›r stran 4:3", IDM_VID_FORCE43 POPUP "&Násobek zvÄ›tÅ¡ení okna" BEGIN - MENUITEM "&0.5x", IDM_VID_SCALE_1X - MENUITEM "&1x", IDM_VID_SCALE_2X - MENUITEM "1.&5x", IDM_VID_SCALE_3X - MENUITEM "&2x", IDM_VID_SCALE_4X + MENUITEM "&0.5x", IDM_VID_SCALE_1X + MENUITEM "&1x", IDM_VID_SCALE_2X + MENUITEM "1.&5x", IDM_VID_SCALE_3X + MENUITEM "&2x", IDM_VID_SCALE_4X + MENUITEM "&3x", IDM_VID_SCALE_5X + MENUITEM "&4x", IDM_VID_SCALE_6X + MENUITEM "&5x", IDM_VID_SCALE_7X + MENUITEM "&6x", IDM_VID_SCALE_8X + MENUITEM "&7x", IDM_VID_SCALE_9X + MENUITEM "&8x", IDM_VID_SCALE_10X END POPUP "Metoda &filtrování" BEGIN - MENUITEM "&Nejbližší", IDM_VID_FILTER_NEAREST - MENUITEM "&Lineární", IDM_VID_FILTER_LINEAR + MENUITEM "&Nejbližší", IDM_VID_FILTER_NEAREST + MENUITEM "&Lineární", IDM_VID_FILTER_LINEAR END - MENUITEM "Å &kálování HiDPI", IDM_VID_HIDPI + MENUITEM "Å &kálování HiDPI", IDM_VID_HIDPI MENUITEM SEPARATOR - MENUITEM "&Celá obrazovka\tCtrl+Alt+PgUp", IDM_VID_FULLSCREEN + MENUITEM "&Celá obrazovka\tCtrl+Alt+PgUp", IDM_VID_FULLSCREEN POPUP "Režím roztá&hnutí pÅ™i celé obrazovce" BEGIN - MENUITEM "&Roztáhnout", IDM_VID_FS_FULL - MENUITEM "&4:3", IDM_VID_FS_43 - MENUITEM "&Zachovat pomÄ›r stran", IDM_VID_FS_KEEPRATIO - MENUITEM "&CeloÄíselné Å¡kálování", IDM_VID_FS_INT + MENUITEM "&Roztáhnout", IDM_VID_FS_FULL + MENUITEM "&4:3", IDM_VID_FS_43 + MENUITEM "&Zachovat pomÄ›r stran", IDM_VID_FS_KEEPRATIO + MENUITEM "&CeloÄíselné Å¡kálování", IDM_VID_FS_INT END POPUP "Nastavení pro E&GA a (S)VGA" BEGIN - MENUITEM "&PÅ™evrátit barvy", IDM_VID_INVERT + MENUITEM "&PÅ™evrátit barvy", IDM_VID_INVERT POPUP "&Typ VGA monitoru" BEGIN - MENUITEM "RGB &barevný", IDM_VID_GRAY_RGB - MENUITEM "&Odstíny Å¡edi", IDM_VID_GRAY_MONO - MENUITEM "&Jantarová obrazovka", IDM_VID_GRAY_AMBER - MENUITEM "&Zelená obrazovka", IDM_VID_GRAY_GREEN - MENUITEM "&Bílá obrazovka", IDM_VID_GRAY_WHITE + MENUITEM "RGB &barevný", IDM_VID_GRAY_RGB + MENUITEM "&Odstíny Å¡edi", IDM_VID_GRAY_MONO + MENUITEM "&Jantarová obrazovka", IDM_VID_GRAY_AMBER + MENUITEM "&Zelená obrazovka", IDM_VID_GRAY_GREEN + MENUITEM "&Bílá obrazovka", IDM_VID_GRAY_WHITE END POPUP "PÅ™evod na &odstíny Å¡edi" BEGIN - MENUITEM "BT&601 (NTSC/PAL)", IDM_VID_GRAYCT_601 - MENUITEM "BT&709 (HDTV)", IDM_VID_GRAYCT_709 - MENUITEM "&PrůmÄ›r", IDM_VID_GRAYCT_AVE + MENUITEM "BT&601 (NTSC/PAL)", IDM_VID_GRAYCT_601 + MENUITEM "BT&709 (HDTV)", IDM_VID_GRAYCT_709 + MENUITEM "&PrůmÄ›r", IDM_VID_GRAYCT_AVE END END MENUITEM SEPARATOR - MENUITEM "PÅ™esah obrazu CGA/PCjr/Tandy/E&GA/(S)VGA", IDM_VID_OVERSCAN - MENUITEM "&Upravit kontrast Äernobílé obrazovky", IDM_VID_CGACON + MENUITEM "PÅ™esah obrazu CGA/PCjr/Tandy/E&GA/(S)VGA", IDM_VID_OVERSCAN + MENUITEM "&Upravit kontrast Äernobílé obrazovky", IDM_VID_CGACON END - MENUITEM "&Média", IDM_MEDIA + MENUITEM "&Média", IDM_MEDIA POPUP "&Nástroje" BEGIN - MENUITEM "&Nastavení...", IDM_CONFIG - MENUITEM "&Aktualizovat ikony stavového řádku", IDM_UPDATE_ICONS + MENUITEM "&Nastavení...", IDM_CONFIG + MENUITEM "&Aktualizovat ikony stavového řádku", IDM_UPDATE_ICONS MENUITEM SEPARATOR - MENUITEM "Pořídit &screenshot\tCtrl+F11", IDM_ACTION_SCREENSHOT + MENUITEM "Pořídit &screenshot\tCtrl+F11", IDM_ACTION_SCREENSHOT MENUITEM SEPARATOR - MENUITEM "&PÅ™edvolby...", IDM_PREFERENCES - MENUITEM "Povolit integraci s &Discordem", IDM_DISCORD + MENUITEM "&PÅ™edvolby...", IDM_PREFERENCES +#ifdef DISCORD + MENUITEM "Povolit integraci s &Discordem", IDM_DISCORD +#endif MENUITEM SEPARATOR - MENUITEM "&Zesílení zvuku", IDM_SND_GAIN + MENUITEM "&Zesílení zvuku", IDM_SND_GAIN #ifdef MTR_ENABLED MENUITEM SEPARATOR - MENUITEM "ZaÄít trace\tCtrl+T", IDM_ACTION_BEGIN_TRACE - MENUITEM "Zastavit trace\tCtrl+T", IDM_ACTION_END_TRACE + MENUITEM "ZaÄít trace\tCtrl+T", IDM_ACTION_BEGIN_TRACE + MENUITEM "Zastavit trace\tCtrl+T", IDM_ACTION_END_TRACE #endif END POPUP "Ná&povÄ›da" BEGIN - MENUITEM "&Dokumentace", IDM_DOCS - MENUITEM "&O programu 86Box", IDM_ABOUT + MENUITEM "&Dokumentace", IDM_DOCS + MENUITEM "&O programu 86Box", IDM_ABOUT END END -StatusBarMenu MENU DISCARDABLE +StatusBarMenu MENU DISCARDABLE BEGIN MENUITEM SEPARATOR END @@ -128,17 +137,17 @@ CassetteSubmenu MENU DISCARDABLE BEGIN POPUP "" BEGIN - MENUITEM "&Nový obraz...", IDM_CASSETTE_IMAGE_NEW + MENUITEM "&Nový obraz...", IDM_CASSETTE_IMAGE_NEW MENUITEM SEPARATOR - MENUITEM "&Existující obraz...", IDM_CASSETTE_IMAGE_EXISTING - MENUITEM "Existující obraz (&ochrana proti zápisu)...", IDM_CASSETTE_IMAGE_EXISTING_WP + MENUITEM "&Existující obraz...", IDM_CASSETTE_IMAGE_EXISTING + MENUITEM "Existující obraz (&ochrana proti zápisu)...", IDM_CASSETTE_IMAGE_EXISTING_WP MENUITEM SEPARATOR - MENUITEM "&Nahrávat", IDM_CASSETTE_RECORD - MENUITEM "&PÅ™ehrát", IDM_CASSETTE_PLAY - MENUITEM "PÅ™etoÄit na &zaÄátek", IDM_CASSETTE_REWIND - MENUITEM "PÅ™etoÄit na &konec", IDM_CASSETTE_FAST_FORWARD + MENUITEM "&Nahrávat", IDM_CASSETTE_RECORD + MENUITEM "&PÅ™ehrát", IDM_CASSETTE_PLAY + MENUITEM "PÅ™etoÄit na &zaÄátek", IDM_CASSETTE_REWIND + MENUITEM "PÅ™etoÄit na &konec", IDM_CASSETTE_FAST_FORWARD MENUITEM SEPARATOR - MENUITEM "&Vyjmout", IDM_CASSETTE_EJECT + MENUITEM "&Vyjmout", IDM_CASSETTE_EJECT END END @@ -146,9 +155,9 @@ CartridgeSubmenu MENU DISCARDABLE BEGIN POPUP "" BEGIN - MENUITEM "&Obraz...", IDM_CARTRIDGE_IMAGE + MENUITEM "&Obraz...", IDM_CARTRIDGE_IMAGE MENUITEM SEPARATOR - MENUITEM "&Vyjmout", IDM_CARTRIDGE_EJECT + MENUITEM "&Vyjmout", IDM_CARTRIDGE_EJECT END END @@ -156,14 +165,14 @@ FloppySubmenu MENU DISCARDABLE BEGIN POPUP "" BEGIN - MENUITEM "&Nový obraz...", IDM_FLOPPY_IMAGE_NEW + MENUITEM "&Nový obraz...", IDM_FLOPPY_IMAGE_NEW MENUITEM SEPARATOR - MENUITEM "&Existující obraz...", IDM_FLOPPY_IMAGE_EXISTING - MENUITEM "Existující obraz (&ochrana proti zápisu)...", IDM_FLOPPY_IMAGE_EXISTING_WP + MENUITEM "&Existující obraz...", IDM_FLOPPY_IMAGE_EXISTING + MENUITEM "Existující obraz (&ochrana proti zápisu)...", IDM_FLOPPY_IMAGE_EXISTING_WP MENUITEM SEPARATOR - MENUITEM "E&xportovat do 86F...", IDM_FLOPPY_EXPORT_TO_86F + MENUITEM "E&xportovat do 86F...", IDM_FLOPPY_EXPORT_TO_86F MENUITEM SEPARATOR - MENUITEM "&Vyjmout", IDM_FLOPPY_EJECT + MENUITEM "&Vyjmout", IDM_FLOPPY_EJECT END END @@ -171,12 +180,13 @@ CdromSubmenu MENU DISCARDABLE BEGIN POPUP "" BEGIN - MENUITEM "&ZtiÅ¡it", IDM_CDROM_MUTE + MENUITEM "&ZtiÅ¡it", IDM_CDROM_MUTE MENUITEM SEPARATOR - MENUITEM "&Vyjmout", IDM_CDROM_EMPTY - MENUITEM "&NaÄíst znova pÅ™edchozí obraz", IDM_CDROM_RELOAD + MENUITEM "&Vyjmout", IDM_CDROM_EMPTY + MENUITEM "&NaÄíst znova pÅ™edchozí obraz", IDM_CDROM_RELOAD MENUITEM SEPARATOR - MENUITEM "&Obraz...", IDM_CDROM_IMAGE + MENUITEM "&Obraz...", IDM_CDROM_IMAGE + MENUITEM "&Složka...", IDM_CDROM_DIR END END @@ -184,13 +194,13 @@ ZIPSubmenu MENU DISCARDABLE BEGIN POPUP "" BEGIN - MENUITEM "&Nový obraz...", IDM_ZIP_IMAGE_NEW + MENUITEM "&Nový obraz...", IDM_ZIP_IMAGE_NEW MENUITEM SEPARATOR - MENUITEM "&Existující obraz...", IDM_ZIP_IMAGE_EXISTING - MENUITEM "Existující obraz (&ochrana proti zápisu)...", IDM_ZIP_IMAGE_EXISTING_WP + MENUITEM "&Existující obraz...", IDM_ZIP_IMAGE_EXISTING + MENUITEM "Existující obraz (&ochrana proti zápisu)...", IDM_ZIP_IMAGE_EXISTING_WP MENUITEM SEPARATOR - MENUITEM "&Vyjmout", IDM_ZIP_EJECT - MENUITEM "&NaÄíst znova pÅ™edchozí obraz", IDM_ZIP_RELOAD + MENUITEM "&Vyjmout", IDM_ZIP_EJECT + MENUITEM "&NaÄíst znova pÅ™edchozí obraz", IDM_ZIP_RELOAD END END @@ -198,13 +208,13 @@ MOSubmenu MENU DISCARDABLE BEGIN POPUP "" BEGIN - MENUITEM "&Nový obraz...", IDM_MO_IMAGE_NEW + MENUITEM "&Nový obraz...", IDM_MO_IMAGE_NEW MENUITEM SEPARATOR - MENUITEM "&Existující obraz...", IDM_MO_IMAGE_EXISTING - MENUITEM "Existující obraz (&ochrana proti zápisu)...", IDM_MO_IMAGE_EXISTING_WP + MENUITEM "&Existující obraz...", IDM_MO_IMAGE_EXISTING + MENUITEM "Existující obraz (&ochrana proti zápisu)...", IDM_MO_IMAGE_EXISTING_WP MENUITEM SEPARATOR - MENUITEM "&Vyjmout", IDM_MO_EJECT - MENUITEM "&NaÄíst znova pÅ™edchozí obraz", IDM_MO_RELOAD + MENUITEM "&Vyjmout", IDM_MO_EJECT + MENUITEM "&NaÄíst znova pÅ™edchozí obraz", IDM_MO_RELOAD END END @@ -230,134 +240,150 @@ END // Dialog // -#define STR_PREFERENCES "PÅ™edvolby" -#define STR_SND_GAIN "Zesílení zvuku" -#define STR_NEW_FLOPPY "Nový obraz" -#define STR_CONFIG "Nastavení" -#define STR_SPECIFY_DIM "Zadat rozmÄ›ry hlavního okna" +#define STR_PREFERENCES "PÅ™edvolby" +#define STR_SND_GAIN "Zesílení zvuku" +#define STR_NEW_FLOPPY "Nový obraz" +#define STR_CONFIG "Nastavení" +#define STR_SPECIFY_DIM "Zadat rozmÄ›ry hlavního okna" -#define STR_OK "OK" -#define STR_CANCEL "Storno" -#define STR_GLOBAL "Uložit toto nastavení jako &globální výchozí stav" -#define STR_DEFAULT "&Výchozí" -#define STR_LANGUAGE "Jazyk:" -#define STR_ICONSET "Sada ikon:" +#define STR_OK "OK" +#define STR_CANCEL "Storno" +#define STR_GLOBAL "Uložit toto nastavení jako &globální výchozí stav" +#define STR_DEFAULT "&Výchozí" +#define STR_LANGUAGE "Jazyk:" +#define STR_ICONSET "Sada ikon:" -#define STR_GAIN "Zesílení" +#define STR_GAIN "Zesílení" -#define STR_FILE_NAME "Název souboru:" -#define STR_DISK_SIZE "Velikost disku:" -#define STR_RPM_MODE "Režím ot./m:" -#define STR_PROGRESS "PrůbÄ›h:" +#define STR_FILE_NAME "Název souboru:" +#define STR_DISK_SIZE "Velikost disku:" +#define STR_RPM_MODE "Režím ot./m:" +#define STR_PROGRESS "PrůbÄ›h:" -#define STR_WIDTH "Šířka:" -#define STR_HEIGHT "Výška:" -#define STR_LOCK_TO_SIZE "Uzamknout na tyto rozmÄ›ry" +#define STR_WIDTH "Šířka:" +#define STR_HEIGHT "Výška:" +#define STR_LOCK_TO_SIZE "Uzamknout na tyto rozmÄ›ry" -#define STR_MACHINE_TYPE "Typ poÄítaÄe:" -#define STR_MACHINE "PoÄítaÄ:" -#define STR_CONFIGURE "Nastavit" -#define STR_CPU_TYPE "Procesor:" -#define STR_CPU_SPEED "Rychlost:" -#define STR_FPU "Koprocesor:" -#define STR_WAIT_STATES "ÄŒekací stavy:" -#define STR_MB "MB" -#define STR_MEMORY "PamÄ›t:" -#define STR_TIME_SYNC "Synchronizace Äasu" -#define STR_DISABLED "Vypnuta" -#define STR_ENABLED_LOCAL "Zapnuta (místní Äas)" -#define STR_ENABLED_UTC "Zapnuta (UTC)" -#define STR_DYNAREC "Dynamický pÅ™ekladaÄ" +#define STR_MACHINE_TYPE "Typ poÄítaÄe:" +#define STR_MACHINE "PoÄítaÄ:" +#define STR_CONFIGURE "Nastavit" +#define STR_CPU_TYPE "Procesor:" +#define STR_CPU_SPEED "Rychlost:" +#define STR_FPU "Koprocesor:" +#define STR_WAIT_STATES "ÄŒekací stavy:" +#define STR_MB "MB" +#define STR_MEMORY "PamÄ›t:" +#define STR_TIME_SYNC "Synchronizace Äasu" +#define STR_DISABLED "Vypnuta" +#define STR_ENABLED_LOCAL "Zapnuta (místní Äas)" +#define STR_ENABLED_UTC "Zapnuta (UTC)" +#define STR_DYNAREC "Dynamický pÅ™ekladaÄ" +#define STR_SOFTFLOAT "Softfloat FPU" -#define STR_VIDEO "Grafika:" -#define STR_VOODOO "Použít grafický akcelerátor Voodoo" +#define STR_VIDEO "Grafika:" +#define STR_VIDEO_2 "Grafika 2:" +#define STR_VOODOO "Použít grafický akcelerátor Voodoo" +#define STR_IBM8514 "Grafika IBM 8514/a" +#define STR_XGA "Grafika XGA" -#define STR_MOUSE "MyÅ¡:" -#define STR_JOYSTICK "Joystick:" -#define STR_JOY1 "Joystick 1..." -#define STR_JOY2 "Joystick 2..." -#define STR_JOY3 "Joystick 3..." -#define STR_JOY4 "Joystick 4..." +#define STR_MOUSE "MyÅ¡:" +#define STR_JOYSTICK "Joystick:" +#define STR_JOY1 "Joystick 1..." +#define STR_JOY2 "Joystick 2..." +#define STR_JOY3 "Joystick 3..." +#define STR_JOY4 "Joystick 4..." -#define STR_SOUND "Zvuková karta:" -#define STR_MIDI_OUT "MIDI výstup:" -#define STR_MIDI_IN "MIDI vstup:" -#define STR_MPU401 "Samostatný MPU-401" -#define STR_SSI "Innovation SSI-2001" -#define STR_CMS "CMS / Game Blaster" -#define STR_GUS "Gravis Ultrasound" -#define STR_FLOAT "Použít zvuk FLOAT32" +#define STR_SOUND1 "Zvuková karta 1:" +#define STR_SOUND2 "Zvuková karta 2:" +#define STR_SOUND3 "Zvuková karta 3:" +#define STR_SOUND4 "Zvuková karta 4:" +#define STR_MIDI_OUT "MIDI výstup:" +#define STR_MIDI_IN "MIDI vstup:" +#define STR_MPU401 "Samostatný MPU-401" +#define STR_FLOAT "Použít zvuk FLOAT32" +#define STR_FM_DRIVER "FM synth driver" +#define STR_FM_DRV_NUKED "Nuked (pÅ™esnÄ›jší)" +#define STR_FM_DRV_YMFM "YMFM (rychlejší)" -#define STR_NET_TYPE "Druh sítÄ›:" -#define STR_PCAP "PCap zařízení:" -#define STR_NET "Síťový adaptér:" +#define STR_NET_TYPE "Druh sítÄ›:" +#define STR_PCAP "PCap zařízení:" +#define STR_NET "Síťový adaptér:" +#define STR_NET1 "Network card 1:" +#define STR_NET2 "Network card 2:" +#define STR_NET3 "Network card 3:" +#define STR_NET4 "Network card 4:" -#define STR_COM1 "Zařízení na COM1:" -#define STR_COM2 "Zařízení na COM2:" -#define STR_COM3 "Zařízení na COM3:" -#define STR_COM4 "Zařízení na COM4:" -#define STR_LPT1 "Zařízení na LPT1:" -#define STR_LPT2 "Zařízení na LPT2:" -#define STR_LPT3 "Zařízení na LPT3:" -#define STR_LPT4 "Zařízení na LPT4:" -#define STR_SERIAL1 "Povolit port COM1" -#define STR_SERIAL2 "Povolit port COM2" -#define STR_SERIAL3 "Povolit port COM3" -#define STR_SERIAL4 "Povolit port COM4" -#define STR_PARALLEL1 "Povolit port LPT1" -#define STR_PARALLEL2 "Povolit port LPT2" -#define STR_PARALLEL3 "Povolit port LPT3" -#define STR_PARALLEL4 "Povolit port LPT4" +#define STR_COM1 "Zařízení na COM1:" +#define STR_COM2 "Zařízení na COM2:" +#define STR_COM3 "Zařízení na COM3:" +#define STR_COM4 "Zařízení na COM4:" +#define STR_LPT1 "Zařízení na LPT1:" +#define STR_LPT2 "Zařízení na LPT2:" +#define STR_LPT3 "Zařízení na LPT3:" +#define STR_LPT4 "Zařízení na LPT4:" +#define STR_SERIAL1 "Povolit port COM1" +#define STR_SERIAL2 "Povolit port COM2" +#define STR_SERIAL3 "Povolit port COM3" +#define STR_SERIAL4 "Povolit port COM4" +#define STR_PARALLEL1 "Povolit port LPT1" +#define STR_PARALLEL2 "Povolit port LPT2" +#define STR_PARALLEL3 "Povolit port LPT3" +#define STR_PARALLEL4 "Povolit port LPT4" +#define STR_SERIAL_PASS1 "Serial port passthrough 1" +#define STR_SERIAL_PASS2 "Serial port passthrough 2" +#define STR_SERIAL_PASS3 "Serial port passthrough 3" +#define STR_SERIAL_PASS4 "Serial port passthrough 4" -#define STR_HDC "ŘadiÄ disku:" -#define STR_FDC "Disketový Å™adiÄ:" -#define STR_IDE_TER "TÅ™etí Å™adiÄ IDE" -#define STR_IDE_QUA "ÄŒtvrtý Å™adiÄ IDE" -#define STR_SCSI "SCSI" -#define STR_SCSI_1 "ŘadiÄ 1:" -#define STR_SCSI_2 "ŘadiÄ 2:" -#define STR_SCSI_3 "ŘadiÄ 3:" -#define STR_SCSI_4 "ŘadiÄ 4:" -#define STR_CASSETTE "Kazeta" +#define STR_HDC "ŘadiÄ disku:" +#define STR_FDC "Disketový Å™adiÄ:" +#define STR_IDE_TER "TÅ™etí Å™adiÄ IDE" +#define STR_IDE_QUA "ÄŒtvrtý Å™adiÄ IDE" +#define STR_SCSI "SCSI" +#define STR_SCSI_1 "ŘadiÄ 1:" +#define STR_SCSI_2 "ŘadiÄ 2:" +#define STR_SCSI_3 "ŘadiÄ 3:" +#define STR_SCSI_4 "ŘadiÄ 4:" +#define STR_CASSETTE "Kazeta" -#define STR_HDD "Pevné disky:" -#define STR_NEW "&Nový..." -#define STR_EXISTING "&Existující..." -#define STR_REMOVE "&Odebrat" -#define STR_BUS "SbÄ›rnice:" -#define STR_CHANNEL "Kanál:" -#define STR_ID "ID:" +#define STR_HDD "Pevné disky:" +#define STR_NEW "&Nový..." +#define STR_EXISTING "&Existující..." +#define STR_REMOVE "&Odebrat" +#define STR_BUS "SbÄ›rnice:" +#define STR_CHANNEL "Kanál:" +#define STR_ID "ID:" +#define STR_SPEED "Speed:" -#define STR_SPECIFY "&Zadat..." -#define STR_SECTORS "Sektory:" -#define STR_HEADS "Hlavy:" -#define STR_CYLS "Cylindry:" -#define STR_SIZE_MB "Velikost (MB):" -#define STR_TYPE "Typ:" -#define STR_IMG_FORMAT "Formát obrazu:" -#define STR_BLOCK_SIZE "Velikost bloků:" +#define STR_SPECIFY "&Zadat..." +#define STR_SECTORS "Sektory:" +#define STR_HEADS "Hlavy:" +#define STR_CYLS "Cylindry:" +#define STR_SIZE_MB "Velikost (MB):" +#define STR_TYPE "Typ:" +#define STR_IMG_FORMAT "Formát obrazu:" +#define STR_BLOCK_SIZE "Velikost bloků:" -#define STR_FLOPPY_DRIVES "Disketové mechaniky:" -#define STR_TURBO "Turbo Äasování" -#define STR_CHECKBPB "Kontrola BPB" -#define STR_CDROM_DRIVES "Mechaniky CD-ROM:" -#define STR_CD_SPEED "Rychlost:" +#define STR_FLOPPY_DRIVES "Disketové mechaniky:" +#define STR_TURBO "Turbo Äasování" +#define STR_CHECKBPB "Kontrola BPB" +#define STR_CDROM_DRIVES "Mechaniky CD-ROM:" +#define STR_CD_SPEED "Rychlost:" -#define STR_MO_DRIVES "Magnetooptické mechaniky:" -#define STR_ZIP_DRIVES "Mechaniky ZIP:" -#define STR_250 "ZIP 250" +#define STR_MO_DRIVES "Magnetooptické mechaniky:" +#define STR_ZIP_DRIVES "Mechaniky ZIP:" +#define STR_250 "ZIP 250" -#define STR_ISARTC "ISA hodiny:" -#define STR_ISAMEM "ISA rozšíření pamÄ›ti" -#define STR_ISAMEM_1 "Karta 1:" -#define STR_ISAMEM_2 "Karta 2:" -#define STR_ISAMEM_3 "Karta 3:" -#define STR_ISAMEM_4 "Karta 4:" -#define STR_BUGGER "Zařízení ISABugger" -#define STR_POSTCARD "Karta pro kódy POST" +#define STR_ISARTC "ISA hodiny:" +#define STR_ISAMEM "ISA rozšíření pamÄ›ti" +#define STR_ISAMEM_1 "Karta 1:" +#define STR_ISAMEM_2 "Karta 2:" +#define STR_ISAMEM_3 "Karta 3:" +#define STR_ISAMEM_4 "Karta 4:" +#define STR_BUGGER "Zařízení ISABugger" +#define STR_POSTCARD "Karta pro kódy POST" -#define FONT_SIZE 9 -#define FONT_NAME "Segoe UI" +#define FONT_SIZE 9 +#define FONT_NAME "Segoe UI" #include "dialogs.rc" @@ -366,194 +392,188 @@ END // String Table // -STRINGTABLE DISCARDABLE +STRINGTABLE DISCARDABLE BEGIN - 2048 "86Box" - IDS_2049 "Chyba" - IDS_2050 "Kritická chyba" - IDS_2051 " - PAUSED" - IDS_2052 "StisknÄ›te Ctrl+Alt+PgDn pro návrat z režimu celé obrazovky." - IDS_2053 "Rychlost" - IDS_2054 "ZIP %03i %i (%s): %ls" - IDS_2055 "Obrazy ZIP disků (*.IM?;*.ZDI)\0*.IM?;*.ZDI\0" - IDS_2056 "86Box nenalezl žádné použitelné image pamÄ›tí ROM.\n\nStáhnÄ›te sadu obrazů ROM a extrahujte ji do složky ""roms""." - IDS_2057 "(prázdné)" - IDS_2058 "Obrazy ZIP disků (*.IM?;*.ZDI)\0*.IM?;*.ZDI\0All files (*.*)\0*.*\0" - IDS_2059 "Turbo" - IDS_2060 "Zap." - IDS_2061 "Vyp." - IDS_2062 "VÅ¡echny obrazy disků (*.86F;*.DSK;*.FLP;*.IM?;*.*FD?)\0*.86F;*.DSK;*.FLP;*.IM?;*.*FD?\0Základní sektorové obrazy (*.DSK;*.FLP;*.IM?;*.*FD?)\0*.DSK;*.FLP;*.IM?;*.IMG;*.*FD?\0Obrazy povrchu (*.86F)\0*.86F\0" - IDS_2063 "PoÄítaÄ ""%hs"" není dostupný, jelikož chybí obraz jeho pamÄ›ti ROM ve složce ""roms/machines"". Konfigurace se pÅ™epne na jiný dostupný poÄítaÄ." + 2048 "86Box" + IDS_2049 "Chyba" + IDS_2050 "Kritická chyba" + IDS_2051 " - PAUSED" + IDS_2052 "StisknÄ›te Ctrl+Alt+PgDn pro návrat z režimu celé obrazovky." + IDS_2053 "Rychlost" + IDS_2054 "ZIP %03i %i (%s): %ls" + IDS_2055 "Obrazy ZIP disků (*.IM?;*.ZDI)\0*.IM?;*.ZDI\0" + IDS_2056 "86Box nenalezl žádné použitelné image pamÄ›tí ROM.\n\nStáhnÄ›te sadu obrazů ROM a extrahujte ji do složky ""roms""." + IDS_2057 "(prázdné)" + IDS_2058 "Obrazy ZIP disků (*.IM?;*.ZDI)\0*.IM?;*.ZDI\0All files (*.*)\0*.*\0" + IDS_2059 "Turbo" + IDS_2060 "Zap." + IDS_2061 "Vyp." + IDS_2062 "VÅ¡echny obrazy disků (*.86F;*.DSK;*.FLP;*.IM?;*.*FD?)\0*.86F;*.DSK;*.FLP;*.IM?;*.*FD?\0Základní sektorové obrazy (*.DSK;*.FLP;*.IM?;*.*FD?)\0*.DSK;*.FLP;*.IM?;*.IMG;*.*FD?\0Obrazy povrchu (*.86F)\0*.86F\0" + IDS_2063 "PoÄítaÄ ""%hs"" není dostupný, jelikož chybí obraz jeho pamÄ›ti ROM ve složce ""roms/machines"". Konfigurace se pÅ™epne na jiný dostupný poÄítaÄ." END -STRINGTABLE DISCARDABLE +STRINGTABLE DISCARDABLE BEGIN - IDS_2064 "Video adaptér ""%hs"" není dostupný, jelikož chybí obraz jeho pamÄ›ti ROM ve složce ""roms/video"". Konfigurace se pÅ™epne na jiný dostupný adaptér." - IDS_2065 "PoÄítaÄ" - IDS_2066 "Obraz" - IDS_2067 "Vstupní zařízení" - IDS_2068 "Zvuk" - IDS_2069 "Síť" - IDS_2070 "COM a LPT porty" - IDS_2071 "ŘadiÄe úložiÅ¡tÄ›" - IDS_2072 "Pevné disky" - IDS_2073 "Disketové a CD-ROM mechaniky" - IDS_2074 "Další vymÄ›nitelná zařízení" - IDS_2075 "Jiné přísluÅ¡enství" - IDS_2076 "Obrazy povrchu (*.86F)\0*.86F\0" - IDS_2077 "KliknÄ›te pro zabraní myÅ¡i" - IDS_2078 "StisknÄ›te F8+F12 pro uvolnÄ›ní myÅ¡i" - IDS_2079 "StisknÄ›te F8+F12 nebo prostÅ™ední tlaÄítko pro uvolnÄ›ní myÅ¡i" + IDS_2064 "Video adaptér ""%hs"" není dostupný, jelikož chybí obraz jeho pamÄ›ti ROM ve složce ""roms/video"". Konfigurace se pÅ™epne na jiný dostupný adaptér." + IDS_2065 "PoÄítaÄ" + IDS_2066 "Obraz" + IDS_2067 "Vstupní zařízení" + IDS_2068 "Zvuk" + IDS_2069 "Síť" + IDS_2070 "COM a LPT porty" + IDS_2071 "ŘadiÄe úložiÅ¡tÄ›" + IDS_2072 "Pevné disky" + IDS_2073 "Disketové a CD-ROM mechaniky" + IDS_2074 "Další vymÄ›nitelná zařízení" + IDS_2075 "Jiné přísluÅ¡enství" + IDS_2076 "Obrazy povrchu (*.86F)\0*.86F\0" + IDS_2077 "KliknÄ›te pro zabraní myÅ¡i" + IDS_2078 "StisknÄ›te F8+F12 pro uvolnÄ›ní myÅ¡i" + IDS_2079 "StisknÄ›te F8+F12 nebo prostÅ™ední tlaÄítko pro uvolnÄ›ní myÅ¡i" END -STRINGTABLE DISCARDABLE +STRINGTABLE DISCARDABLE BEGIN - IDS_2080 "Nastala chyba pÅ™i inicializaci knihovny FluidSynth." - IDS_2081 "SbÄ›rnice" - IDS_2082 "Soubor" - IDS_2083 "C" - IDS_2084 "H" - IDS_2085 "S" - IDS_2086 "MB" - IDS_2087 "Kontrola BPB" - IDS_2088 "KB" - IDS_2089 "Nastala chyba pÅ™i inicializaci video rendereru." - IDS_2090 "Výchozí" - IDS_2091 "%i Äekací stav(y)" - IDS_2092 "Typ" - IDS_2093 "Nastala chyba pÅ™i inicializaci knihovny PCap" - IDS_2094 "Nebyla nalezena žádná PCap zařízení" - IDS_2095 "Neplatné PCap zařízení" - IDS_2096 "Standardní 2tlaÄítkový joystick" - IDS_2097 "Standardní 4tlaÄítkový joystick" - IDS_2098 "Standardní 6tlaÄítkový joystick" - IDS_2099 "Standardní 8tlaÄítkový joystick" - IDS_2100 "CH Flightstick Pro" - IDS_2101 "Microsoft SideWinder Pad" - IDS_2102 "Thrustmaster Flight Control System" - IDS_2103 "Žadné" - IDS_2104 "Nebylo možné nahrát klávesnicové zkratky." - IDS_2105 "Nebylo možné zaregistrovat raw input." - IDS_2106 "%u" - IDS_2107 "%u MB (CHS: %i, %i, %i)" - IDS_2108 "Disketová mechanika %i (%s): %ls" - IDS_2109 "VÅ¡echny obrazy (*.0??;*.1??;*.??0;*.86F;*.BIN;*.CQ?;*.D??;*.FLP;*.HDM;*.IM?;*.JSON;*.TD0;*.*FD?;*.MFM;*.XDF)\0*.0??;*.1??;*.??0;*.86F;*.BIN;*.CQ?;*.D??;*.FLP;*.HDM;*.IM?;*.JSON;*.TD0;*.*FD?;*.MFM;*.XDF\0Rozšířené sektorové obrazy (*.IMD;*.JSON;*.TD0)\0*.IMD;*.JSON;*.TD0\0Základní sektorové obrazy (*.0??;*.1??;*.??0;*.BIN;*.CQ?;*.D??;*.FLP;*.HDM;*.IM?;*.XDF;*.*FD?)\0*.0??;*.1??;*.??0;*.BIN;*.CQ?;*.D??;*.FLP;*.HDM;*.IM?;*.XDF;*.*FD?\0Obrazy magnetického toku (*.FDI)\0*.FDI\0Obrazy povrchu (*.86F;*.MFM)\0*.86F;*.MFM\0VÅ¡echny soubory (*.*)\0*.*\0" - IDS_2110 "Nastala chyba pÅ™i inicializaci knihovny FreeType" - IDS_2111 "Nastala chyba pÅ™i inicializaci knihovny SDL, je potÅ™eba SDL2.dll" - IDS_2112 "Opravdu chcete resetovat emulovaný poÄítaÄ?" - IDS_2113 "Opravdu chcete ukonÄit 86Box?" - IDS_2114 "Nastala chyba pÅ™i inicializaci knihovny Ghostscript" - IDS_2115 "MO %i (%ls): %ls" - IDS_2116 "Obrazy MO (*.IM?;*.MDI)\0*.IM?;*.MDI\0VÅ¡echny soubory (*.*)\0*.*\0" - IDS_2117 "Vítejte v programu 86Box!" - IDS_2118 "VestavÄ›ný Å™adiÄ" - IDS_2119 "UkonÄit" - IDS_2120 "Nebyly nalezeny žádné obrazy ROM" - IDS_2121 "Chcete uložit nastavení?" - IDS_2122 "PokraÄováním se resetuje emulovaný poÄítaÄ." - IDS_2123 "Uložit" - IDS_2124 "O programu 86Box" - IDS_2125 "86Box v" EMU_VERSION + IDS_2081 "SbÄ›rnice" + IDS_2082 "Soubor" + IDS_2083 "C" + IDS_2084 "H" + IDS_2085 "S" + IDS_2086 "MB" + IDS_2087 "Speed" + IDS_2088 "Kontrola BPB" + IDS_2089 "KB" + IDS_2090 "Nastala chyba pÅ™i inicializaci video rendereru." + IDS_2091 "Výchozí" + IDS_2092 "%i Äekací stav(y)" + IDS_2093 "Typ" + IDS_2094 "Nastala chyba pÅ™i inicializaci knihovny PCap" + IDS_2095 "Nebyla nalezena žádná PCap zařízení" + IDS_2096 "Neplatné PCap zařízení" + IDS_2097 "Standardní 2tlaÄítkový joystick" + IDS_2098 "Standardní 4tlaÄítkový joystick" + IDS_2099 "Standardní 6tlaÄítkový joystick" + IDS_2100 "Standardní 8tlaÄítkový joystick" + IDS_2101 "CH Flightstick Pro" + IDS_2102 "Microsoft SideWinder Pad" + IDS_2103 "Thrustmaster Flight Control System" + IDS_2104 "Žadné" + IDS_2105 "Nebylo možné nahrát klávesnicové zkratky." + IDS_2106 "Nebylo možné zaregistrovat raw input." + IDS_2107 "%u" + IDS_2108 "%u MB (CHS: %i, %i, %i)" + IDS_2109 "Disketová mechanika %i (%s): %ls" + IDS_2110 "VÅ¡echny obrazy (*.0??;*.1??;*.??0;*.86F;*.BIN;*.CQ?;*.D??;*.FLP;*.HDM;*.IM?;*.JSON;*.TD0;*.*FD?;*.MFM;*.XDF)\0*.0??;*.1??;*.??0;*.86F;*.BIN;*.CQ?;*.D??;*.FLP;*.HDM;*.IM?;*.JSON;*.TD0;*.*FD?;*.MFM;*.XDF\0Rozšířené sektorové obrazy (*.IMD;*.JSON;*.TD0)\0*.IMD;*.JSON;*.TD0\0Základní sektorové obrazy (*.0??;*.1??;*.??0;*.BIN;*.CQ?;*.D??;*.FLP;*.HDM;*.IM?;*.XDF;*.*FD?)\0*.0??;*.1??;*.??0;*.BIN;*.CQ?;*.D??;*.FLP;*.HDM;*.IM?;*.XDF;*.*FD?\0Obrazy magnetického toku (*.FDI)\0*.FDI\0Obrazy povrchu (*.86F;*.MFM)\0*.86F;*.MFM\0VÅ¡echny soubory (*.*)\0*.*\0" + IDS_2112 "Nastala chyba pÅ™i inicializaci knihovny SDL, je potÅ™eba SDL2.dll" + IDS_2113 "Opravdu chcete resetovat emulovaný poÄítaÄ?" + IDS_2114 "Opravdu chcete ukonÄit 86Box?" + IDS_2115 "Nastala chyba pÅ™i inicializaci knihovny Ghostscript" + IDS_2116 "MO %i (%ls): %ls" + IDS_2117 "Obrazy MO (*.IM?;*.MDI)\0*.IM?;*.MDI\0VÅ¡echny soubory (*.*)\0*.*\0" + IDS_2118 "Vítejte v programu 86Box!" + IDS_2119 "VestavÄ›ný Å™adiÄ" + IDS_2120 "UkonÄit" + IDS_2121 "Nebyly nalezeny žádné obrazy ROM" + IDS_2122 "Chcete uložit nastavení?" + IDS_2123 "PokraÄováním se resetuje emulovaný poÄítaÄ." + IDS_2124 "Uložit" + IDS_2125 "O programu 86Box" + IDS_2126 "86Box v" EMU_VERSION - IDS_2126 "Emulátor starých poÄítaÄů\n\nAutoÅ™i: Sarah Walker, Miran Grca, Fred N. van Kempen (waltje), SA1988, Tiseno100, reenigne, leilei, JohnElliott, greatpsycho, and others.\n\nZveÅ™ejnÄ›no pod licencí GNU General Public License verze 2 nebo novÄ›jší. Viz soubor LICENSE pro více informací." - IDS_2127 "OK" - IDS_2128 "Hardware není dostupný" + IDS_2127 "Emulátor starých poÄítaÄů\n\nAutoÅ™i: Miran GrÄa (OBattler), RichardG867, Jasmine Iwanek, TC1995, coldbrewed, Teemu Korhonen (Manaatti), Joakim L. Gilje, Adrien Moulin (elyosh), Daniel Balsom (gloriouscow), Cacodemon345, Fred N. van Kempen (waltje), Tiseno100, reenigne, and others.\n\nWith previous core contributions from Sarah Walker, leilei, JohnElliott, greatpsycho, and others.\n\nZveÅ™ejnÄ›no pod licencí GNU General Public License verze 2 nebo novÄ›jší. Viz soubor LICENSE pro více informací." + IDS_2128 "OK" + IDS_2129 "Hardware není dostupný" #ifdef _WIN32 #define LIB_NAME_PCAP "WinPcap" #else #define LIB_NAME_PCAP "libpcap" #endif - IDS_2129 "UjistÄ›te se, že je nainstalován " LIB_NAME_PCAP " a používáte síťové pÅ™ipojení s ním kompatibilní." - IDS_2130 "Neplatná konfigurace" -#ifdef _WIN32 -#define LIB_NAME_FREETYPE "freetype.dll" -#else -#define LIB_NAME_FREETYPE "libfreetype" -#endif - IDS_2131 LIB_NAME_FREETYPE " je potÅ™eba pro emulaci ESC/P tiskáren." + IDS_2130 "UjistÄ›te se, že je nainstalován " LIB_NAME_PCAP " a používáte síťové pÅ™ipojení s ním kompatibilní." + IDS_2131 "Neplatná konfigurace" #ifdef _WIN32 #define LIB_NAME_GS "gsdll32.dll" #else #define LIB_NAME_GS "libgs" #endif - IDS_2132 LIB_NAME_GS " je potÅ™eba pro automatický pÅ™evod PostScript dokumentů do PDF.\n\nJakékoliv dokumenty vytisknuté pÅ™es obecnou PostScriptovou tiskárnu budou uloženy jako PostScript (.ps) soubory." -#ifdef _WIN32 -#define LIB_NAME_FLUIDSYNTH "libfluidsynth.dll" -#else -#define LIB_NAME_FLUIDSYNTH "libfluidsynth" -#endif - IDS_2133 LIB_NAME_FLUIDSYNTH " je potÅ™eba pro MIDI výstup pÅ™es knihovnu FluidSynth." - IDS_2134 "Vstup do režimu celé obrazovky" - IDS_2135 "Nezobrazovat dále tuto zprávu" - IDS_2136 "NeukonÄovat" - IDS_2137 "Resetovat" - IDS_2138 "Neresetovat" - IDS_2139 "Obraz magnetooptického disku (*.IM?;*.MDI)\0*.IM?;*.MDI\0VÅ¡echny soubory (*.*)\0*.*\0" - IDS_2140 "Obraz CD-ROM disku (*.ISO;*.CUE)\0*.ISO;*.CUE\0VÅ¡echny soubory (*.*)\0*.*\0" - IDS_2141 "Konfigurace zařízení %hs" - IDS_2142 "Monitor je v režimu spánku" - IDS_2143 "Shadery OpenGL (*.GLSL)\0*.GLSL\0All files (*.*)\0*.*\0" - IDS_2144 "Možnosti OpenGL" - IDS_2145 "Pokoušíte se spustit nepodporovanou konfiguraci" - IDS_2146 "Pro tuto konfiguraci bylo vypnuto filtrování procesorů podle zvoleného poÄítaÄe.\n\nToto umožňuje zvolit procesor, který by jinak se zvoleným poÄítaÄem nebyl kompatibilní. Můžou vÅ¡ak nastat potíže s BIOSem nebo jiným softwarem.\n\nPovolení tohoto nastavení není oficiálnÄ› podporováno a jakákoliv hlášení o chybách mohou být uzavÅ™eny jako neplatné." - IDS_2147 "PokraÄovat" - IDS_2148 "Kazeta: %s" - IDS_2149 "Kazetové nahrávky (*.PCM;*.RAW;*.WAV;*.CAS)\0*.PCM;*.RAW;*.WAV;*.CAS\0VÅ¡echny soubory (*.*)\0*.*\0" - IDS_2150 "Cartridge %i: %ls" - IDS_2151 "Obrazy cartridge (*.A;*.B;*.JRC)\0*.A;*.B;*.JRC\0VÅ¡echny soubory (*.*)\0*.*\0" - IDS_2152 "Error initializing renderer" - IDS_2153 "OpenGL (3.0 Core) renderer could not be initialized. Use another renderer." - IDS_2154 "Obnovit" - IDS_2155 "Pozastavit" - IDS_2156 "Stisknout Ctrl+Alt+Delete" - IDS_2157 "Stisknout Ctrl+Alt+Esc" - IDS_2158 "Resetovat" - IDS_2159 "Vypnout skrze rozhraní ACPI" - IDS_2160 "Nastavení" + IDS_2133 LIB_NAME_GS " je potÅ™eba pro automatický pÅ™evod PostScript dokumentů do PDF.\n\nJakékoliv dokumenty vytisknuté pÅ™es obecnou PostScriptovou tiskárnu budou uloženy jako PostScript (.ps) soubory." + IDS_2135 "Vstup do režimu celé obrazovky" + IDS_2136 "Nezobrazovat dále tuto zprávu" + IDS_2137 "NeukonÄovat" + IDS_2138 "Resetovat" + IDS_2139 "Neresetovat" + IDS_2140 "Obraz magnetooptického disku (*.IM?;*.MDI)\0*.IM?;*.MDI\0VÅ¡echny soubory (*.*)\0*.*\0" + IDS_2141 "Obraz CD-ROM disku (*.ISO;*.CUE)\0*.ISO;*.CUE\0VÅ¡echny soubory (*.*)\0*.*\0" + IDS_2142 "Konfigurace zařízení %hs" + IDS_2143 "Monitor je v režimu spánku" + IDS_2144 "Shadery OpenGL (*.GLSL)\0*.GLSL\0All files (*.*)\0*.*\0" + IDS_2145 "Možnosti OpenGL" + IDS_2146 "Pokoušíte se spustit nepodporovanou konfiguraci" + IDS_2147 "Pro tuto konfiguraci bylo vypnuto filtrování procesorů podle zvoleného poÄítaÄe.\n\nToto umožňuje zvolit procesor, který by jinak se zvoleným poÄítaÄem nebyl kompatibilní. Můžou vÅ¡ak nastat potíže s BIOSem nebo jiným softwarem.\n\nPovolení tohoto nastavení není oficiálnÄ› podporováno a jakákoliv hlášení o chybách mohou být uzavÅ™eny jako neplatné." + IDS_2148 "PokraÄovat" + IDS_2149 "Kazeta: %s" + IDS_2150 "Kazetové nahrávky (*.PCM;*.RAW;*.WAV;*.CAS)\0*.PCM;*.RAW;*.WAV;*.CAS\0VÅ¡echny soubory (*.*)\0*.*\0" + IDS_2151 "Cartridge %i: %ls" + IDS_2152 "Obrazy cartridge (*.A;*.B;*.JRC)\0*.A;*.B;*.JRC\0VÅ¡echny soubory (*.*)\0*.*\0" + IDS_2153 "Error initializing renderer" + IDS_2154 "OpenGL (3.0 Core) renderer could not be initialized. Use another renderer." + IDS_2155 "Obnovit" + IDS_2156 "Pozastavit" + IDS_2157 "Stisknout Ctrl+Alt+Delete" + IDS_2158 "Stisknout Ctrl+Alt+Esc" + IDS_2159 "Resetovat" + IDS_2160 "Vypnout skrze rozhraní ACPI" + IDS_2161 "Nastavení" + IDS_2162 "Type" + IDS_2163 "No Dynarec" + IDS_2164 "Old Dynarec" + IDS_2165 "New Dynarec" + IDS_2166 "Video card #2 ""%hs"" is not available due to missing ROMs in the roms/video directory. Disabling the second video card." + IDS_2167 "Failed to initialize network driver" + IDS_2168 "The network configuration will be switched to the null driver" END -STRINGTABLE DISCARDABLE +STRINGTABLE DISCARDABLE BEGIN IDS_4096 "Pevný disk (%s)" - IDS_4097 "%01i:%01i" - IDS_4098 "%01i" - IDS_4099 "CD-ROM mechaniky pro rozhraní MFM/RLL nebo ESDI nikdy neexistovaly" - IDS_4100 "Vlastní..." - IDS_4101 "Vlastní (velký)..." - IDS_4102 "PÅ™idat nový pevný disk" - IDS_4103 "PÅ™idat existující pevný disk" - IDS_4104 "Obraz disku formátu HDI nemůžou být vÄ›tší než 4 GB." - IDS_4105 "Obraz disku nemůžou být vÄ›tší než 127 GB." - IDS_4106 "Obrazy pevného disku (*.HD?;*.IM?;*.VHD)\0*.HD?;*.IM?;*.VHD\0VÅ¡echny soubory (*.*)\0*.*\0" - IDS_4107 "Nebylo možné pÅ™eÄíst soubor" - IDS_4108 "Nebylo možné zapisovat do souboru" - IDS_4109 "Obraz disku ve formátu HDI nebo HDX s velikostí sektoru jinou než 512 bajtů nejsou podporovány." - IDS_4110 "USB zatím není podporováno." - IDS_4111 "Soubor obrazu disku již existuje" - IDS_4112 "Zadejte platný název souboru." - IDS_4113 "Obraz disku byl vytvoÅ™en" - IDS_4114 "UjistÄ›te se, že soubor existuje a lze jej pÅ™eÄíst." - IDS_4115 "UjistÄ›te se, že se do složky, kde se má soubor uložit, dá zapisovat." - IDS_4116 "Obraz disku je příliÅ¡ velký" - IDS_4117 "Nezapomeňte novÄ› vytvoÅ™ený disk rozdÄ›lit a naformátovat." - IDS_4118 "Zvolený soubor bude pÅ™epsán. Opravdu jej chcete použít?" - IDS_4119 "Nepodporovaný obraz disku" - IDS_4120 "PÅ™epsat" - IDS_4121 "NepÅ™episovat" - IDS_4122 "Surový obraz (.img)" - IDS_4123 "HDI obraz (.hdi)" - IDS_4124 "HDX obraz (.hdx)" - IDS_4125 "VHD s pevnou velikostí (.vhd)" - IDS_4126 "VHD s dynamickou velikostí (.vhd)" - IDS_4127 "Rozdílový VHD (.vhd)" - IDS_4128 "Velké bloky (2 MB)" - IDS_4129 "Malé bloky (512 KB)" - IDS_4130 "Soubory VHD (*.VHD)\0*.VHD\0VÅ¡echny soubory (*.*)\0*.*\0" - IDS_4131 "Vyberte nadÅ™azený virtuální disk" - IDS_4132 "To může znamenat, že se obsahy nadÅ™azeného disku zmÄ›nily po vytvoÅ™ení rozdílového disku.\n\nTato chyba také může nastat, pokud byl obraz disku kopírován nebo pÅ™esunut, nebo kvůli chybÄ› v programu, který jej vytvoÅ™il.\n\nChcete Äasová razítka opravit?" - IDS_4133 "ÄŒasová razítka nadÅ™azeného a podÅ™azeného disku nesouhlasí" - IDS_4134 "Nebylo možné opravit Äasové razítko VHD." - IDS_4135 "%01i:%02i" + IDS_4097 "%01i:%01i" + IDS_4098 "%01i" + IDS_4099 "CD-ROM mechaniky pro rozhraní MFM/RLL nebo ESDI nikdy neexistovaly" + IDS_4100 "Vlastní..." + IDS_4101 "Vlastní (velký)..." + IDS_4102 "PÅ™idat nový pevný disk" + IDS_4103 "PÅ™idat existující pevný disk" + IDS_4104 "Obraz disku formátu HDI nemůžou být vÄ›tší než 4 GB." + IDS_4105 "Obraz disku nemůžou být vÄ›tší než 127 GB." + IDS_4106 "Obrazy pevného disku (*.HD?;*.IM?;*.VHD)\0*.HD?;*.IM?;*.VHD\0VÅ¡echny soubory (*.*)\0*.*\0" + IDS_4107 "Nebylo možné pÅ™eÄíst soubor" + IDS_4108 "Nebylo možné zapisovat do souboru" + IDS_4109 "Obraz disku ve formátu HDI nebo HDX s velikostí sektoru jinou než 512 bajtů nejsou podporovány." + IDS_4110 "USB zatím není podporováno." + IDS_4111 "Soubor obrazu disku již existuje" + IDS_4112 "Zadejte platný název souboru." + IDS_4113 "Obraz disku byl vytvoÅ™en" + IDS_4114 "UjistÄ›te se, že soubor existuje a lze jej pÅ™eÄíst." + IDS_4115 "UjistÄ›te se, že se do složky, kde se má soubor uložit, dá zapisovat." + IDS_4116 "Obraz disku je příliÅ¡ velký" + IDS_4117 "Nezapomeňte novÄ› vytvoÅ™ený disk rozdÄ›lit a naformátovat." + IDS_4118 "Zvolený soubor bude pÅ™epsán. Opravdu jej chcete použít?" + IDS_4119 "Nepodporovaný obraz disku" + IDS_4120 "PÅ™epsat" + IDS_4121 "NepÅ™episovat" + IDS_4122 "Surový obraz (.img)" + IDS_4123 "HDI obraz (.hdi)" + IDS_4124 "HDX obraz (.hdx)" + IDS_4125 "VHD s pevnou velikostí (.vhd)" + IDS_4126 "VHD s dynamickou velikostí (.vhd)" + IDS_4127 "Rozdílový VHD (.vhd)" + IDS_4128 "Velké bloky (2 MB)" + IDS_4129 "Malé bloky (512 KB)" + IDS_4130 "Soubory VHD (*.VHD)\0*.VHD\0VÅ¡echny soubory (*.*)\0*.*\0" + IDS_4131 "Vyberte nadÅ™azený virtuální disk" + IDS_4132 "To může znamenat, že se obsahy nadÅ™azeného disku zmÄ›nily po vytvoÅ™ení rozdílového disku.\n\nTato chyba také může nastat, pokud byl obraz disku kopírován nebo pÅ™esunut, nebo kvůli chybÄ› v programu, který jej vytvoÅ™il.\n\nChcete Äasová razítka opravit?" + IDS_4133 "ÄŒasová razítka nadÅ™azeného a podÅ™azeného disku nesouhlasí" + IDS_4134 "Nebylo možné opravit Äasové razítko VHD." + IDS_4135 "%01i:%02i" IDS_4352 "MFM/RLL" IDS_4353 "XTA" @@ -562,56 +582,56 @@ BEGIN IDS_4356 "ATAPI" IDS_4357 "SCSI" - IDS_4608 "MFM/RLL (%01i:%01i)" - IDS_4609 "XTA (%01i:%01i)" - IDS_4610 "ESDI (%01i:%01i)" - IDS_4611 "IDE (%01i:%01i)" - IDS_4612 "ATAPI (%01i:%01i)" - IDS_4613 "SCSI (%01i:%02i)" + IDS_4608 "MFM/RLL (%01i:%01i)" + IDS_4609 "XTA (%01i:%01i)" + IDS_4610 "ESDI (%01i:%01i)" + IDS_4611 "IDE (%01i:%01i)" + IDS_4612 "ATAPI (%01i:%01i)" + IDS_4613 "SCSI (%01i:%02i)" - IDS_5120 "CD-ROM %i (%s): %s" + IDS_5120 "CD-ROM %i (%s): %s" - IDS_5376 "Vypnuto" - IDS_5381 "ATAPI" + IDS_5376 "Vypnuto" + IDS_5381 "ATAPI" IDS_5382 "SCSI" - IDS_5632 "Vypnuto" - IDS_5637 "ATAPI (%01i:%01i)" + IDS_5632 "Vypnuto" + IDS_5637 "ATAPI (%01i:%01i)" IDS_5638 "SCSI (%01i:%02i)" - IDS_5888 "160 kB" - IDS_5889 "180 kB" - IDS_5890 "320 kB" - IDS_5891 "360 kB" - IDS_5892 "640 kB" - IDS_5893 "720 kB" - IDS_5894 "1.2 MB" - IDS_5895 "1.25 MB" - IDS_5896 "1.44 MB" - IDS_5897 "DMF (cluster 1024)" - IDS_5898 "DMF (cluster 2048)" - IDS_5899 "2.88 MB" - IDS_5900 "ZIP 100" - IDS_5901 "ZIP 250" - IDS_5902 "3.5"" 128 MB (ISO 10090)" - IDS_5903 "3.5"" 230 MB (ISO 13963)" - IDS_5904 "3.5"" 540 MB (ISO 15498)" - IDS_5905 "3.5"" 640 MB (ISO 15498)" - IDS_5906 "3.5"" 1.3 GB (GigaMO)" - IDS_5907 "3.5"" 2.3 GB (GigaMO 2)" - IDS_5908 "5.25"" 600 MB" - IDS_5909 "5.25"" 650 MB" - IDS_5910 "5.25"" 1 GB" - IDS_5911 "5.25"" 1.3 GB" + IDS_5888 "160 kB" + IDS_5889 "180 kB" + IDS_5890 "320 kB" + IDS_5891 "360 kB" + IDS_5892 "640 kB" + IDS_5893 "720 kB" + IDS_5894 "1.2 MB" + IDS_5895 "1.25 MB" + IDS_5896 "1.44 MB" + IDS_5897 "DMF (cluster 1024)" + IDS_5898 "DMF (cluster 2048)" + IDS_5899 "2.88 MB" + IDS_5900 "ZIP 100" + IDS_5901 "ZIP 250" + IDS_5902 "3.5"" 128 MB (ISO 10090)" + IDS_5903 "3.5"" 230 MB (ISO 13963)" + IDS_5904 "3.5"" 540 MB (ISO 15498)" + IDS_5905 "3.5"" 640 MB (ISO 15498)" + IDS_5906 "3.5"" 1.3 GB (GigaMO)" + IDS_5907 "3.5"" 2.3 GB (GigaMO 2)" + IDS_5908 "5.25"" 600 MB" + IDS_5909 "5.25"" 650 MB" + IDS_5910 "5.25"" 1 GB" + IDS_5911 "5.25"" 1.3 GB" - IDS_6144 "Dokonalé otáÄky za minutu" - IDS_6145 "1% pod dokonalými ot./m" - IDS_6146 "1.5% pod dokonalými ot./m" - IDS_6147 "2% pod dokonalými ot./m" + IDS_6144 "Dokonalé otáÄky za minutu" + IDS_6145 "1% pod dokonalými ot./m" + IDS_6146 "1.5% pod dokonalými ot./m" + IDS_6147 "2% pod dokonalými ot./m" - IDS_7168 "(Výchozí nastavení systému)" + IDS_7168 "(Výchozí nastavení systému)" END -#define IDS_LANG_ENUS IDS_7168 +#define IDS_LANG_ENUS IDS_7168 // Czech (Czech Republic) resources ///////////////////////////////////////////////////////////////////////////// diff --git a/src/win/languages/de-DE.rc b/src/win/languages/de-DE.rc index f348d5c97..031f935cd 100644 --- a/src/win/languages/de-DE.rc +++ b/src/win/languages/de-DE.rc @@ -13,113 +13,122 @@ LANGUAGE LANG_GERMAN, SUBLANG_DEFAULT // Menu // -MainMenu MENU DISCARDABLE +MainMenu MENU DISCARDABLE BEGIN POPUP "&Aktionen" BEGIN - MENUITEM "&Tastatur benötigt das Einfangen des Mauszeigers", IDM_ACTION_KBD_REQ_CAPTURE - MENUITEM "&Die rechte Strg-Taste ist die Linke Alt-Taste", IDM_ACTION_RCTRL_IS_LALT + MENUITEM "&Tastatur benötigt das Einfangen des Mauszeigers", IDM_ACTION_KBD_REQ_CAPTURE + MENUITEM "&Die rechte Strg-Taste ist die Linke Alt-Taste", IDM_ACTION_RCTRL_IS_LALT MENUITEM SEPARATOR - MENUITEM "&Hard-Reset...", IDM_ACTION_HRESET - MENUITEM "&Strg+Alt+Entf\tStrg+F12", IDM_ACTION_RESET_CAD + MENUITEM "&Hard-Reset...", IDM_ACTION_HRESET + MENUITEM "&Strg+Alt+Entf\tStrg+F12", IDM_ACTION_RESET_CAD MENUITEM SEPARATOR - MENUITEM "Strg+Alt+&Esc", IDM_ACTION_CTRL_ALT_ESC + MENUITEM "Strg+Alt+&Esc", IDM_ACTION_CTRL_ALT_ESC MENUITEM SEPARATOR - MENUITEM "&Pause", IDM_ACTION_PAUSE + MENUITEM "&Pause", IDM_ACTION_PAUSE MENUITEM SEPARATOR - MENUITEM "Be&enden...", IDM_ACTION_EXIT + MENUITEM "Be&enden...", IDM_ACTION_EXIT END POPUP "&Ansicht" BEGIN - MENUITEM "&Statusleiste ausblenden", IDM_VID_HIDE_STATUS_BAR - MENUITEM "&Werkzeugleiste ausblenden", IDM_VID_HIDE_TOOLBAR + MENUITEM "&Statusleiste ausblenden", IDM_VID_HIDE_STATUS_BAR + MENUITEM "&Werkzeugleiste ausblenden", IDM_VID_HIDE_TOOLBAR MENUITEM SEPARATOR - MENUITEM "&Größenverstellbares Fenster", IDM_VID_RESIZE + MENUITEM "&Show non-primary monitors", IDM_VID_MONITORS + MENUITEM "&Größenverstellbares Fenster", IDM_VID_RESIZE MENUITEM "&Größe && Position merken", IDM_VID_REMEMBER MENUITEM SEPARATOR POPUP "Re&nderer" BEGIN - MENUITEM "&SDL (Software)", IDM_VID_SDL_SW - MENUITEM "SDL (&Hardware)", IDM_VID_SDL_HW - MENUITEM "SDL (&OpenGL)", IDM_VID_SDL_OPENGL - MENUITEM "Open&GL (3.0-Kern)", IDM_VID_OPENGL_CORE + MENUITEM "&SDL (Software)", IDM_VID_SDL_SW + MENUITEM "SDL (&Hardware)", IDM_VID_SDL_HW + MENUITEM "SDL (&OpenGL)", IDM_VID_SDL_OPENGL + MENUITEM "Open&GL (3.0-Kern)", IDM_VID_OPENGL_CORE #ifdef USE_VNC - MENUITEM "&VNC", IDM_VID_VNC + MENUITEM "&VNC", IDM_VID_VNC #endif END MENUITEM SEPARATOR - MENUITEM "Fenstergröße einstellen...", IDM_VID_SPECIFY_DIM - MENUITEM "&4:3-Seitenverhältnis erzwingen", IDM_VID_FORCE43 + MENUITEM "Fenstergröße einstellen...", IDM_VID_SPECIFY_DIM + MENUITEM "&4:3-Seitenverhältnis erzwingen", IDM_VID_FORCE43 POPUP "&Fensterskalierungsfaktor" BEGIN - MENUITEM "&0,5x", IDM_VID_SCALE_1X - MENUITEM "&1x", IDM_VID_SCALE_2X - MENUITEM "1,&5x", IDM_VID_SCALE_3X - MENUITEM "&2x", IDM_VID_SCALE_4X + MENUITEM "&0,5x", IDM_VID_SCALE_1X + MENUITEM "&1x", IDM_VID_SCALE_2X + MENUITEM "1,&5x", IDM_VID_SCALE_3X + MENUITEM "&2x", IDM_VID_SCALE_4X + MENUITEM "&3x", IDM_VID_SCALE_5X + MENUITEM "&4x", IDM_VID_SCALE_6X + MENUITEM "&5x", IDM_VID_SCALE_7X + MENUITEM "&6x", IDM_VID_SCALE_8X + MENUITEM "&7x", IDM_VID_SCALE_9X + MENUITEM "&8x", IDM_VID_SCALE_10X END POPUP "Filteringmethode" BEGIN - MENUITEM "&Nearest", IDM_VID_FILTER_NEAREST - MENUITEM "&Linear", IDM_VID_FILTER_LINEAR + MENUITEM "&Nearest", IDM_VID_FILTER_NEAREST + MENUITEM "&Linear", IDM_VID_FILTER_LINEAR END - MENUITEM "Hi&DPI-Skalierung", IDM_VID_HIDPI + MENUITEM "Hi&DPI-Skalierung", IDM_VID_HIDPI MENUITEM SEPARATOR - MENUITEM "&Vollbild\tStrg+Alt+Bild auf", IDM_VID_FULLSCREEN + MENUITEM "&Vollbild\tStrg+Alt+Bild auf", IDM_VID_FULLSCREEN POPUP "&Stretching-Modus im Vollbildmodus" BEGIN - MENUITEM "&Vollbild-Stretching", IDM_VID_FS_FULL - MENUITEM "&4:3-Seitenverhältnis erzwingen", IDM_VID_FS_43 + MENUITEM "&Vollbild-Stretching", IDM_VID_FS_FULL + MENUITEM "&4:3-Seitenverhältnis erzwingen", IDM_VID_FS_43 MENUITEM "&Quadratische Pixel (Seitenverhältnis beibehalten)", IDM_VID_FS_KEEPRATIO - MENUITEM "&Integer-Skalierung", IDM_VID_FS_INT + MENUITEM "&Integer-Skalierung", IDM_VID_FS_INT END POPUP "E&GA/(S)VGA-Einstellungen" BEGIN - MENUITEM "&Invertierte VGA-Anzeige", IDM_VID_INVERT + MENUITEM "&Invertierte VGA-Anzeige", IDM_VID_INVERT POPUP "&VGA-Bildschirmtyp" BEGIN - MENUITEM "&RGB-Farbe", IDM_VID_GRAY_RGB - MENUITEM "&RGB-Graustufen", IDM_VID_GRAY_MONO - MENUITEM "&Bernstein-Monitor", IDM_VID_GRAY_AMBER - MENUITEM "&Grüner Monitor", IDM_VID_GRAY_GREEN - MENUITEM "&Weißer Monitor", IDM_VID_GRAY_WHITE + MENUITEM "&RGB-Farbe", IDM_VID_GRAY_RGB + MENUITEM "&RGB-Graustufen", IDM_VID_GRAY_MONO + MENUITEM "&Bernstein-Monitor", IDM_VID_GRAY_AMBER + MENUITEM "&Grüner Monitor", IDM_VID_GRAY_GREEN + MENUITEM "&Weißer Monitor", IDM_VID_GRAY_WHITE END POPUP "Methode zur &Graustufenkonversion" BEGIN - MENUITEM "BT&601 (NTSC/PAL)", IDM_VID_GRAYCT_601 - MENUITEM "BT&709 (HDTV)", IDM_VID_GRAYCT_709 - MENUITEM "&Durchschnittsmethode", IDM_VID_GRAYCT_AVE + MENUITEM "BT&601 (NTSC/PAL)", IDM_VID_GRAYCT_601 + MENUITEM "BT&709 (HDTV)", IDM_VID_GRAYCT_709 + MENUITEM "&Durchschnittsmethode", IDM_VID_GRAYCT_AVE END END MENUITEM SEPARATOR - MENUITEM "Overscan für CGA/PCjr/Tandy/E&GA/(S)VGA-Displays", IDM_VID_OVERSCAN + MENUITEM "Overscan für CGA/PCjr/Tandy/E&GA/(S)VGA-Displays", IDM_VID_OVERSCAN MENUITEM "Kontrast für &monochrome Displays ändern", IDM_VID_CGACON END - MENUITEM "&Medien", IDM_MEDIA + MENUITEM "&Medien", IDM_MEDIA POPUP "&Werkzeuge" BEGIN - MENUITEM "&Optionen...", IDM_CONFIG - MENUITEM "&Statusleistenicons aktualisieren", IDM_UPDATE_ICONS + MENUITEM "&Optionen...", IDM_CONFIG + MENUITEM "&Statusleistenicons aktualisieren", IDM_UPDATE_ICONS MENUITEM SEPARATOR - MENUITEM "S&creenshot aufnehmen\tStrg+F11", IDM_ACTION_SCREENSHOT + MENUITEM "S&creenshot aufnehmen\tStrg+F11", IDM_ACTION_SCREENSHOT MENUITEM SEPARATOR - MENUITEM "&Einstellungen...", IDM_PREFERENCES + MENUITEM "&Einstellungen...", IDM_PREFERENCES +#ifdef DISCORD MENUITEM "&Discord-Integration aktivieren", IDM_DISCORD +#endif MENUITEM SEPARATOR - MENUITEM "&Klangverstärkung...", IDM_SND_GAIN + MENUITEM "&Klangverstärkung...", IDM_SND_GAIN #ifdef MTR_ENABLED MENUITEM SEPARATOR - MENUITEM "Tracing starten\tStrg+T", IDM_ACTION_BEGIN_TRACE - MENUITEM "Tracing beenden\tStrg+T", IDM_ACTION_END_TRACE + MENUITEM "Tracing starten\tStrg+T", IDM_ACTION_BEGIN_TRACE + MENUITEM "Tracing beenden\tStrg+T", IDM_ACTION_END_TRACE #endif END POPUP "&Hilfe" BEGIN - MENUITEM "&Dokumentation...", IDM_DOCS - MENUITEM "&Über 86Box...", IDM_ABOUT + MENUITEM "&Dokumentation...", IDM_DOCS + MENUITEM "&Über 86Box...", IDM_ABOUT END END -StatusBarMenu MENU DISCARDABLE +StatusBarMenu MENU DISCARDABLE BEGIN MENUITEM SEPARATOR END @@ -128,17 +137,17 @@ CassetteSubmenu MENU DISCARDABLE BEGIN POPUP "" BEGIN - MENUITEM "&Neues Image...", IDM_CASSETTE_IMAGE_NEW + MENUITEM "&Neues Image...", IDM_CASSETTE_IMAGE_NEW MENUITEM SEPARATOR - MENUITEM "&Bestehendes Image...", IDM_CASSETTE_IMAGE_EXISTING - MENUITEM "Bestehendes Image (&schreibgeschützt)...", IDM_CASSETTE_IMAGE_EXISTING_WP + MENUITEM "&Bestehendes Image...", IDM_CASSETTE_IMAGE_EXISTING + MENUITEM "Bestehendes Image (&schreibgeschützt)...", IDM_CASSETTE_IMAGE_EXISTING_WP MENUITEM SEPARATOR - MENUITEM "&Aufnehmen", IDM_CASSETTE_RECORD - MENUITEM "&Abspielen", IDM_CASSETTE_PLAY - MENUITEM "&An den Anfang zurückspulen", IDM_CASSETTE_REWIND - MENUITEM "&An das Ende vorspulen", IDM_CASSETTE_FAST_FORWARD + MENUITEM "&Aufnehmen", IDM_CASSETTE_RECORD + MENUITEM "&Abspielen", IDM_CASSETTE_PLAY + MENUITEM "&An den Anfang zurückspulen", IDM_CASSETTE_REWIND + MENUITEM "&An das Ende vorspulen", IDM_CASSETTE_FAST_FORWARD MENUITEM SEPARATOR - MENUITEM "A&uswerfen", IDM_CASSETTE_EJECT + MENUITEM "A&uswerfen", IDM_CASSETTE_EJECT END END @@ -146,9 +155,9 @@ CartridgeSubmenu MENU DISCARDABLE BEGIN POPUP "" BEGIN - MENUITEM "&Cartridgeimage...", IDM_CARTRIDGE_IMAGE + MENUITEM "&Cartridgeimage...", IDM_CARTRIDGE_IMAGE MENUITEM SEPARATOR - MENUITEM "A&uswerfen", IDM_CARTRIDGE_EJECT + MENUITEM "A&uswerfen", IDM_CARTRIDGE_EJECT END END @@ -156,14 +165,14 @@ FloppySubmenu MENU DISCARDABLE BEGIN POPUP "" BEGIN - MENUITEM "&Neues Image...", IDM_FLOPPY_IMAGE_NEW + MENUITEM "&Neues Image...", IDM_FLOPPY_IMAGE_NEW MENUITEM SEPARATOR - MENUITEM "&Bestehendes Image...", IDM_FLOPPY_IMAGE_EXISTING - MENUITEM "Bestehendes Image (&schreibgeschützt)...", IDM_FLOPPY_IMAGE_EXISTING_WP + MENUITEM "&Bestehendes Image...", IDM_FLOPPY_IMAGE_EXISTING + MENUITEM "Bestehendes Image (&schreibgeschützt)...", IDM_FLOPPY_IMAGE_EXISTING_WP MENUITEM SEPARATOR - MENUITEM "&In das 86F-Format e&xportieren...", IDM_FLOPPY_EXPORT_TO_86F + MENUITEM "&In das 86F-Format e&xportieren...", IDM_FLOPPY_EXPORT_TO_86F MENUITEM SEPARATOR - MENUITEM "&Auswerfen", IDM_FLOPPY_EJECT + MENUITEM "&Auswerfen", IDM_FLOPPY_EJECT END END @@ -171,12 +180,13 @@ CdromSubmenu MENU DISCARDABLE BEGIN POPUP "" BEGIN - MENUITEM "&Stummschalten", IDM_CDROM_MUTE + MENUITEM "&Stummschalten", IDM_CDROM_MUTE MENUITEM SEPARATOR - MENUITEM "L&eer", IDM_CDROM_EMPTY - MENUITEM "&Voriges Image neu laden", IDM_CDROM_RELOAD + MENUITEM "L&eer", IDM_CDROM_EMPTY + MENUITEM "&Voriges Image neu laden", IDM_CDROM_RELOAD MENUITEM SEPARATOR - MENUITEM "&Image", IDM_CDROM_IMAGE + MENUITEM "&Image...", IDM_CDROM_IMAGE + MENUITEM "&Verzeichnis...", IDM_CDROM_DIR END END @@ -184,13 +194,13 @@ ZIPSubmenu MENU DISCARDABLE BEGIN POPUP "" BEGIN - MENUITEM "&Neues Image...", IDM_ZIP_IMAGE_NEW + MENUITEM "&Neues Image...", IDM_ZIP_IMAGE_NEW MENUITEM SEPARATOR - MENUITEM "&Bestehendes Image...", IDM_ZIP_IMAGE_EXISTING - MENUITEM "Bestehendes Image (&schreibgeschützt)...", IDM_ZIP_IMAGE_EXISTING_WP + MENUITEM "&Bestehendes Image...", IDM_ZIP_IMAGE_EXISTING + MENUITEM "Bestehendes Image (&schreibgeschützt)...", IDM_ZIP_IMAGE_EXISTING_WP MENUITEM SEPARATOR - MENUITEM "A&uswerfen", IDM_ZIP_EJECT - MENUITEM "&Voriges Image neu laden", IDM_ZIP_RELOAD + MENUITEM "A&uswerfen", IDM_ZIP_EJECT + MENUITEM "&Voriges Image neu laden", IDM_ZIP_RELOAD END END @@ -198,13 +208,13 @@ MOSubmenu MENU DISCARDABLE BEGIN POPUP "" BEGIN - MENUITEM "&Neues Image...", IDM_MO_IMAGE_NEW + MENUITEM "&Neues Image...", IDM_MO_IMAGE_NEW MENUITEM SEPARATOR - MENUITEM "&Bestehendes Image...", IDM_MO_IMAGE_EXISTING - MENUITEM "Bestehendes Image (&schreibgeschützt)...", IDM_MO_IMAGE_EXISTING_WP + MENUITEM "&Bestehendes Image...", IDM_MO_IMAGE_EXISTING + MENUITEM "Bestehendes Image (&schreibgeschützt)...", IDM_MO_IMAGE_EXISTING_WP MENUITEM SEPARATOR - MENUITEM "&Auswerfen", IDM_MO_EJECT - MENUITEM "&Bestehendes Image erneut laden", IDM_MO_RELOAD + MENUITEM "&Auswerfen", IDM_MO_EJECT + MENUITEM "&Bestehendes Image erneut laden", IDM_MO_RELOAD END END @@ -230,134 +240,150 @@ END // Dialog // -#define STR_PREFERENCES "Einstellungen" -#define STR_SND_GAIN "Klangverstärkung" -#define STR_NEW_FLOPPY "Neues Image" -#define STR_CONFIG "Optionen" -#define STR_SPECIFY_DIM "Fenstergröße einstellen" +#define STR_PREFERENCES "Einstellungen" +#define STR_SND_GAIN "Klangverstärkung" +#define STR_NEW_FLOPPY "Neues Image" +#define STR_CONFIG "Optionen" +#define STR_SPECIFY_DIM "Fenstergröße einstellen" -#define STR_OK "OK" -#define STR_CANCEL "Abbrechen" -#define STR_GLOBAL "Einstellungen als &globalen Standard speichern" -#define STR_DEFAULT "&Standard" -#define STR_LANGUAGE "Sprache:" -#define STR_ICONSET "Icon-Satz:" +#define STR_OK "OK" +#define STR_CANCEL "Abbrechen" +#define STR_GLOBAL "Einstellungen als &globalen Standard speichern" +#define STR_DEFAULT "&Standard" +#define STR_LANGUAGE "Sprache:" +#define STR_ICONSET "Icon-Satz:" -#define STR_GAIN "Verstärkung" +#define STR_GAIN "Verstärkung" -#define STR_FILE_NAME "Dateiname:" -#define STR_DISK_SIZE "Plattengröße:" -#define STR_RPM_MODE "Drehzahlmodus:" -#define STR_PROGRESS "Fortschritt:" +#define STR_FILE_NAME "Dateiname:" +#define STR_DISK_SIZE "Plattengröße:" +#define STR_RPM_MODE "Drehzahlmodus:" +#define STR_PROGRESS "Fortschritt:" -#define STR_WIDTH "Breite:" -#define STR_HEIGHT "Höhe:" -#define STR_LOCK_TO_SIZE "Feste Größe" +#define STR_WIDTH "Breite:" +#define STR_HEIGHT "Höhe:" +#define STR_LOCK_TO_SIZE "Feste Größe" -#define STR_MACHINE_TYPE "Systemtyp:" -#define STR_MACHINE "System:" -#define STR_CONFIGURE "Einstellen" -#define STR_CPU_TYPE "CPU-Typ:" -#define STR_CPU_SPEED "Takt:" -#define STR_FPU "FPU-Einheit:" -#define STR_WAIT_STATES "Wartezustände:" -#define STR_MB "MB" -#define STR_MEMORY "Hauptspeicher:" -#define STR_TIME_SYNC "Zeitsynchronisierung" -#define STR_DISABLED "Deaktiviert" -#define STR_ENABLED_LOCAL "Aktiviert (Lokale Uhrzeit)" -#define STR_ENABLED_UTC "Aktiviert (UTC)" -#define STR_DYNAREC "Dynamischer Recompiler" +#define STR_MACHINE_TYPE "Systemtyp:" +#define STR_MACHINE "System:" +#define STR_CONFIGURE "Einstellen" +#define STR_CPU_TYPE "CPU-Typ:" +#define STR_CPU_SPEED "Takt:" +#define STR_FPU "FPU-Einheit:" +#define STR_WAIT_STATES "Wartezustände:" +#define STR_MB "MB" +#define STR_MEMORY "Hauptspeicher:" +#define STR_TIME_SYNC "Zeitsynchronisierung" +#define STR_DISABLED "Deaktiviert" +#define STR_ENABLED_LOCAL "Aktiviert (Lokale Uhrzeit)" +#define STR_ENABLED_UTC "Aktiviert (UTC)" +#define STR_DYNAREC "Dynamischer Recompiler" +#define STR_SOFTFLOAT "Softfloat FPU" -#define STR_VIDEO "Videokarte:" -#define STR_VOODOO "Voodoo-Grafik" +#define STR_VIDEO "Videokarte:" +#define STR_VIDEO_2 "Videokarte 2:" +#define STR_VOODOO "Voodoo-Grafik" +#define STR_IBM8514 "IBM 8514/a-Grafik" +#define STR_XGA "XGA-Grafik" -#define STR_MOUSE "Maus:" -#define STR_JOYSTICK "Joystick:" -#define STR_JOY1 "Joystick 1..." -#define STR_JOY2 "Joystick 2..." -#define STR_JOY3 "Joystick 3..." -#define STR_JOY4 "Joystick 4..." +#define STR_MOUSE "Maus:" +#define STR_JOYSTICK "Joystick:" +#define STR_JOY1 "Joystick 1..." +#define STR_JOY2 "Joystick 2..." +#define STR_JOY3 "Joystick 3..." +#define STR_JOY4 "Joystick 4..." -#define STR_SOUND "Soundkarte:" -#define STR_MIDI_OUT "MIDI Out-Gerät:" -#define STR_MIDI_IN "MIDI In-Gerät:" -#define STR_MPU401 "Standalone-MPU-401-Gerät" -#define STR_SSI "Innovation SSI-2001" -#define STR_CMS "CMS / Game Blaster" -#define STR_GUS "Gravis Ultrasound" -#define STR_FLOAT "FLOAT32-Wiedergabe benutzen" +#define STR_SOUND1 "Soundkarte 1:" +#define STR_SOUND2 "Soundkarte 2:" +#define STR_SOUND3 "Soundkarte 3:" +#define STR_SOUND4 "Soundkarte 4:" +#define STR_MIDI_OUT "MIDI Out-Gerät:" +#define STR_MIDI_IN "MIDI In-Gerät:" +#define STR_MPU401 "Standalone-MPU-401-Gerät" +#define STR_FLOAT "FLOAT32-Wiedergabe benutzen" +#define STR_FM_DRIVER "FM-Synth-Treiber" +#define STR_FM_DRV_NUKED "Nuked (genauer)" +#define STR_FM_DRV_YMFM "YMFM (schneller)" -#define STR_NET_TYPE "Netzwerktyp:" -#define STR_PCAP "PCap-Gerät:" -#define STR_NET "Netzwerkadapter:" +#define STR_NET_TYPE "Netzwerktyp:" +#define STR_PCAP "PCap-Gerät:" +#define STR_NET "Netzwerkadapter:" +#define STR_NET1 "Network card 1:" +#define STR_NET2 "Network card 2:" +#define STR_NET3 "Network card 3:" +#define STR_NET4 "Network card 4:" -#define STR_COM1 "COM1-Gerät:" -#define STR_COM2 "COM2-Gerät:" -#define STR_COM3 "COM3-Gerät:" -#define STR_COM4 "COM4-Gerät:" -#define STR_LPT1 "LPT1-Gerät:" -#define STR_LPT2 "LPT2-Gerät:" -#define STR_LPT3 "LPT3-Gerät:" -#define STR_LPT4 "LPT4-Gerät:" -#define STR_SERIAL1 "Serielle Schnittstelle 1" -#define STR_SERIAL2 "Serielle Schnittstelle 2" -#define STR_SERIAL3 "Serielle Schnittstelle 3" -#define STR_SERIAL4 "Serielle Schnittstelle 4" -#define STR_PARALLEL1 "Parallelport 1" -#define STR_PARALLEL2 "Parallelport 2" -#define STR_PARALLEL3 "Parallelport 3" -#define STR_PARALLEL4 "Parallelport 4" +#define STR_COM1 "COM1-Gerät:" +#define STR_COM2 "COM2-Gerät:" +#define STR_COM3 "COM3-Gerät:" +#define STR_COM4 "COM4-Gerät:" +#define STR_LPT1 "LPT1-Gerät:" +#define STR_LPT2 "LPT2-Gerät:" +#define STR_LPT3 "LPT3-Gerät:" +#define STR_LPT4 "LPT4-Gerät:" +#define STR_SERIAL1 "Serielle Schnittstelle 1" +#define STR_SERIAL2 "Serielle Schnittstelle 2" +#define STR_SERIAL3 "Serielle Schnittstelle 3" +#define STR_SERIAL4 "Serielle Schnittstelle 4" +#define STR_PARALLEL1 "Parallelport 1" +#define STR_PARALLEL2 "Parallelport 2" +#define STR_PARALLEL3 "Parallelport 3" +#define STR_PARALLEL4 "Parallelport 4" +#define STR_SERIAL_PASS1 "Serial port passthrough 1" +#define STR_SERIAL_PASS2 "Serial port passthrough 2" +#define STR_SERIAL_PASS3 "Serial port passthrough 3" +#define STR_SERIAL_PASS4 "Serial port passthrough 4" -#define STR_HDC "HDD-Controller:" -#define STR_FDC "FD-Controller:" -#define STR_IDE_TER "Tertiärer IDE-Controller" -#define STR_IDE_QUA "Quartärer IDE-Controller" -#define STR_SCSI "SCSI" -#define STR_SCSI_1 "Controller 1:" -#define STR_SCSI_2 "Controller 2:" -#define STR_SCSI_3 "Controller 3:" -#define STR_SCSI_4 "Controller 4:" -#define STR_CASSETTE "Kassette" +#define STR_HDC "HDD-Controller:" +#define STR_FDC "FD-Controller:" +#define STR_IDE_TER "Tertiärer IDE-Controller" +#define STR_IDE_QUA "Quartärer IDE-Controller" +#define STR_SCSI "SCSI" +#define STR_SCSI_1 "Controller 1:" +#define STR_SCSI_2 "Controller 2:" +#define STR_SCSI_3 "Controller 3:" +#define STR_SCSI_4 "Controller 4:" +#define STR_CASSETTE "Kassette" -#define STR_HDD "Festplatten:" -#define STR_NEW "&Neu..." -#define STR_EXISTING "&Vorhanden..." -#define STR_REMOVE "&Entfernen" -#define STR_BUS "Bus:" -#define STR_CHANNEL "Kanal:" -#define STR_ID "ID:" +#define STR_HDD "Festplatten:" +#define STR_NEW "&Neu..." +#define STR_EXISTING "&Vorhanden..." +#define STR_REMOVE "&Entfernen" +#define STR_BUS "Bus:" +#define STR_CHANNEL "Kanal:" +#define STR_ID "ID:" +#define STR_SPEED "Speed:" -#define STR_SPECIFY "&Festlegen..." -#define STR_SECTORS "Sektoren:" -#define STR_HEADS "Köpfe:" -#define STR_CYLS "Zylinder:" -#define STR_SIZE_MB "Größe (MB):" -#define STR_TYPE "Typ:" -#define STR_IMG_FORMAT "Imageformat:" -#define STR_BLOCK_SIZE "Blockgröße:" +#define STR_SPECIFY "&Festlegen..." +#define STR_SECTORS "Sektoren:" +#define STR_HEADS "Köpfe:" +#define STR_CYLS "Zylinder:" +#define STR_SIZE_MB "Größe (MB):" +#define STR_TYPE "Typ:" +#define STR_IMG_FORMAT "Imageformat:" +#define STR_BLOCK_SIZE "Blockgröße:" -#define STR_FLOPPY_DRIVES "Diskettenlaufwerke:" -#define STR_TURBO "Turbo-Timings" -#define STR_CHECKBPB "BPB überprüfen" -#define STR_CDROM_DRIVES "CD-ROM-Laufwerke:" -#define STR_CD_SPEED "Takt:" +#define STR_FLOPPY_DRIVES "Diskettenlaufwerke:" +#define STR_TURBO "Turbo-Timings" +#define STR_CHECKBPB "BPB überprüfen" +#define STR_CDROM_DRIVES "CD-ROM-Laufwerke:" +#define STR_CD_SPEED "Geschwindigkeit:" -#define STR_MO_DRIVES "MO-Laufwerke:" -#define STR_ZIP_DRIVES "ZIP-Laufwerke:" -#define STR_250 "ZIP 250" +#define STR_MO_DRIVES "MO-Laufwerke:" +#define STR_ZIP_DRIVES "ZIP-Laufwerke:" +#define STR_250 "ZIP 250" -#define STR_ISARTC "ISA-Echtzeituhr:" -#define STR_ISAMEM "ISA-Speichererweiterung:" -#define STR_ISAMEM_1 "Steckkarte 1:" -#define STR_ISAMEM_2 "Steckkarte 2:" -#define STR_ISAMEM_3 "Steckkarte 3:" -#define STR_ISAMEM_4 "Steckkarte 4:" -#define STR_BUGGER "ISABugger-Gerät" -#define STR_POSTCARD "POST-Code-Karte" +#define STR_ISARTC "ISA-Echtzeituhr:" +#define STR_ISAMEM "ISA-Speichererweiterung:" +#define STR_ISAMEM_1 "Steckkarte 1:" +#define STR_ISAMEM_2 "Steckkarte 2:" +#define STR_ISAMEM_3 "Steckkarte 3:" +#define STR_ISAMEM_4 "Steckkarte 4:" +#define STR_BUGGER "ISABugger-Gerät" +#define STR_POSTCARD "POST-Code-Karte" -#define FONT_SIZE 9 -#define FONT_NAME "Segoe UI" +#define FONT_SIZE 9 +#define FONT_NAME "Segoe UI" #include "dialogs.rc" @@ -366,194 +392,188 @@ END // String Table // -STRINGTABLE DISCARDABLE +STRINGTABLE DISCARDABLE BEGIN - 2048 "86Box" - IDS_2049 "Fehler" - IDS_2050 "Fataler Fehler" - IDS_2051 " - PAUSED" - IDS_2052 "Bitte Strg+Alt+Bild ab zur Rückkehr in den Fenstermodus drücken." - IDS_2053 "Geschwindigkeit" - IDS_2054 "ZIP %03i %i (%s): %ls" - IDS_2055 "ZIP-Images (*.IM?;*.ZDI)\0*.IM?;*.ZDI\0" - IDS_2056 "86Box konnte keine nutzbaren ROM-Dateien finden.\n\nBitte besuchen Sie download, laden ein ROM-Set herunter und extrahieren dies in das ""roms""-Verzeichnis." - IDS_2057 "(leer)" - IDS_2058 "ZIP-Images (*.IM?;*.ZDI)\0*.IM?;*.ZDI\0Alle Dateien (*.*)\0*.*\0" - IDS_2059 "Turbo" - IDS_2060 "An" - IDS_2061 "Aus" - IDS_2062 "Alle Images (*.86F;*.DSK;*.FLP;*.IM?;*.*FD?)\0*.86F;*.DSK;*.FLP;*.IM?;*.*FD?\0Basissektorimages (*.DSK;*.FLP;*.IM?;*.*FD?)\0*.DSK;*.FLP;*.IM?;*.IMG;*.*FD?\0Oberflächenimages (*.86F)\0*.86F\0" - IDS_2063 "Das System ""%hs"" ist aufgrund von fehlenden ROMs im Verzeichnis roms/machines nicht verfügbar. Es wird auf ein verfügbares System gewechselt." + 2048 "86Box" + IDS_2049 "Fehler" + IDS_2050 "Fataler Fehler" + IDS_2051 " - PAUSED" + IDS_2052 "Bitte Strg+Alt+Bild ab zur Rückkehr in den Fenstermodus drücken." + IDS_2053 "Geschwindigkeit" + IDS_2054 "ZIP %03i %i (%s): %ls" + IDS_2055 "ZIP-Images (*.IM?;*.ZDI)\0*.IM?;*.ZDI\0" + IDS_2056 "86Box konnte keine nutzbaren ROM-Dateien finden.\n\nBitte besuchen Sie download, laden ein ROM-Set herunter und extrahieren dies in das ""roms""-Verzeichnis." + IDS_2057 "(leer)" + IDS_2058 "ZIP-Images (*.IM?;*.ZDI)\0*.IM?;*.ZDI\0Alle Dateien (*.*)\0*.*\0" + IDS_2059 "Turbo" + IDS_2060 "An" + IDS_2061 "Aus" + IDS_2062 "Alle Images (*.86F;*.DSK;*.FLP;*.IM?;*.*FD?)\0*.86F;*.DSK;*.FLP;*.IM?;*.*FD?\0Basissektorimages (*.DSK;*.FLP;*.IM?;*.*FD?)\0*.DSK;*.FLP;*.IM?;*.IMG;*.*FD?\0Oberflächenimages (*.86F)\0*.86F\0" + IDS_2063 "Das System ""%hs"" ist aufgrund von fehlenden ROMs im Verzeichnis roms/machines nicht verfügbar. Es wird auf ein verfügbares System gewechselt." END -STRINGTABLE DISCARDABLE +STRINGTABLE DISCARDABLE BEGIN - IDS_2064 "Die Videokarte ""%hs"" ist aufgrund von fehlenden ROMs im Verzeichnis roms/video nicht verfügbar. Es wird auf eine verfügbare Videokarte gewechselt." - IDS_2065 "System" - IDS_2066 "Anzeige" - IDS_2067 "Eingabegeräte" - IDS_2068 "Multimedia" - IDS_2069 "Netzwerk" - IDS_2070 "Anschlüsse (COM & LPT)" - IDS_2071 "Speichercontroller" - IDS_2072 "Festplatten" - IDS_2073 "Disketten- & CD-ROM-Laufwerke" - IDS_2074 "Andere Wechsellaufwerke" - IDS_2075 "Andere Peripheriegeräte" - IDS_2076 "Oberflächenimages (*.86F)\0*.86F\0" - IDS_2077 "Zum Einfangen des Mauszeigers bitte klicken" - IDS_2078 "Bitte F8+F12 zur Mausfreigabe drücken" - IDS_2079 "Bitte F8+F12 oder die mittlere Maustaste zur Mausfreigabe drücken" + IDS_2064 "Die Videokarte ""%hs"" ist aufgrund von fehlenden ROMs im Verzeichnis roms/video nicht verfügbar. Es wird auf eine verfügbare Videokarte gewechselt." + IDS_2065 "System" + IDS_2066 "Anzeige" + IDS_2067 "Eingabegeräte" + IDS_2068 "Multimedia" + IDS_2069 "Netzwerk" + IDS_2070 "Anschlüsse (COM & LPT)" + IDS_2071 "Speichercontroller" + IDS_2072 "Festplatten" + IDS_2073 "Disketten- & CD-ROM-Laufwerke" + IDS_2074 "Andere Wechsellaufwerke" + IDS_2075 "Andere Peripheriegeräte" + IDS_2076 "Oberflächenimages (*.86F)\0*.86F\0" + IDS_2077 "Zum Einfangen des Mauszeigers bitte klicken" + IDS_2078 "Bitte F8+F12 zur Mausfreigabe drücken" + IDS_2079 "Bitte F8+F12 oder die mittlere Maustaste zur Mausfreigabe drücken" END -STRINGTABLE DISCARDABLE +STRINGTABLE DISCARDABLE BEGIN - IDS_2080 "FluidSynth konnte nicht initialisiert werden" - IDS_2081 "Bus" - IDS_2082 "Datei" - IDS_2083 "C" - IDS_2084 "H" - IDS_2085 "S" - IDS_2086 "MB" - IDS_2087 "BPB prüfen" - IDS_2088 "KB" - IDS_2089 "Der Videorenderer konnte nicht initialisiert werden." - IDS_2090 "Standard" - IDS_2091 "%i Wartezustände" - IDS_2092 "Typ" - IDS_2093 "PCap konnte nicht eingerichtet werden" - IDS_2094 "Keine PCap-Geräte gefunden" - IDS_2095 "Ungültiges PCap-Gerät" - IDS_2096 "Standard 2-Tasten-Joystick(s)" - IDS_2097 "Standard 4-Tasten-Joystick" - IDS_2098 "Standard 6-Tasten-Joystick" - IDS_2099 "Standard 8-Tasten-Joystick" - IDS_2100 "CH Flightstick Pro" - IDS_2101 "Microsoft SideWinder Pad" - IDS_2102 "Thrustmaster Flight Control System" - IDS_2103 "Ohne" - IDS_2104 "Tastaturbeschleuniger konnten nicht geladen werden." - IDS_2105 "Roheingaben konnten nicht registriert werden." - IDS_2106 "%u" - IDS_2107 "%u MB (CHS: %i, %i, %i)" - IDS_2108 "Diskette %i (%s): %ls" - IDS_2109 "Alle Images (*.0??;*.1??;*.??0;*.86F;*.BIN;*.CQ?;*.D??;*.FLP;*.HDM;*.IM?;*.JSON;*.TD0;*.*FD?;*.MFM;*.XDF)\0*.0??;*.1??;*.??0;*.86F;*.BIN;*.CQ?;*.D??;*.FLP;*.HDM;*.IM?;*.JSON;*.TD0;*.*FD?;*.MFM;*.XDF\0Fortgeschrittene Sektorimages (*.IMD;*.JSON;*.TD0)\0*.IMD;*.JSON;*.TD0\0Basissektorimages (*.0??;*.1??;*.??0;*.BIN;*.CQ?;*.D??;*.FLP;*.HDM;*.IM?;*.XDF;*.*FD?)\0*.0??;*.1??;*.??0;*.BIN;*.CQ?;*.D??;*.FLP;*.HDM;*.IM?;*.XDF;*.*FD?\0Fluximages (*.FDI)\0*.FDI\0Oberflächenimages (*.86F;*.MFM)\0*.86F;*.MFM\0Alle Dateien (*.*)\0*.*\0" - IDS_2110 "FreeType konnte nicht initialisiert werden" - IDS_2111 "SDL konnte nicht initialisiert werden, die Datei SDL2.dll wird benötigt" - IDS_2112 "Sind Sie sich sicher, dass Sie einen Hard-Reset für das emulierte System durchführen wollen?" - IDS_2113 "Sind Sie sich sicher, dass Sie 86Box beenden wollen?" - IDS_2114 "Ghostscript konnte nicht initialisiert werden" - IDS_2115 "MO %i (%ls): %ls" - IDS_2116 "MO-Images (*.IM?;*.MDI)\0*.IM?;*.MDI\0Alle Dateien (*.*)\0*.*\0" - IDS_2117 "Willkommen bei 86Box!" - IDS_2118 "Interner Controller" - IDS_2119 "Beenden" - IDS_2120 "Keine ROMs gefunden" - IDS_2121 "Möchten Sie die Einstellungen speichern?" - IDS_2122 "Dies wird zu einem Hard-Reset des emulierten Systems führen." - IDS_2123 "Speichern" - IDS_2124 "Über 86Box" - IDS_2125 "86Box Version " EMU_VERSION + IDS_2081 "Bus" + IDS_2082 "Datei" + IDS_2083 "C" + IDS_2084 "H" + IDS_2085 "S" + IDS_2086 "MB" + IDS_2087 "Speed" + IDS_2088 "BPB prüfen" + IDS_2089 "KB" + IDS_2090 "Der Videorenderer konnte nicht initialisiert werden." + IDS_2091 "Standard" + IDS_2092 "%i Wartezustände" + IDS_2093 "Typ" + IDS_2094 "PCap konnte nicht eingerichtet werden" + IDS_2095 "Keine PCap-Geräte gefunden" + IDS_2096 "Ungültiges PCap-Gerät" + IDS_2097 "Standard 2-Tasten-Joystick(s)" + IDS_2098 "Standard 4-Tasten-Joystick" + IDS_2099 "Standard 6-Tasten-Joystick" + IDS_2100 "Standard 8-Tasten-Joystick" + IDS_2101 "CH Flightstick Pro" + IDS_2102 "Microsoft SideWinder Pad" + IDS_2103 "Thrustmaster Flight Control System" + IDS_2104 "Ohne" + IDS_2105 "Tastaturbeschleuniger konnten nicht geladen werden." + IDS_2106 "Roheingaben konnten nicht registriert werden." + IDS_2107 "%u" + IDS_2108 "%u MB (CHS: %i, %i, %i)" + IDS_2109 "Diskette %i (%s): %ls" + IDS_2110 "Alle Images (*.0??;*.1??;*.??0;*.86F;*.BIN;*.CQ?;*.D??;*.FLP;*.HDM;*.IM?;*.JSON;*.TD0;*.*FD?;*.MFM;*.XDF)\0*.0??;*.1??;*.??0;*.86F;*.BIN;*.CQ?;*.D??;*.FLP;*.HDM;*.IM?;*.JSON;*.TD0;*.*FD?;*.MFM;*.XDF\0Fortgeschrittene Sektorimages (*.IMD;*.JSON;*.TD0)\0*.IMD;*.JSON;*.TD0\0Basissektorimages (*.0??;*.1??;*.??0;*.BIN;*.CQ?;*.D??;*.FLP;*.HDM;*.IM?;*.XDF;*.*FD?)\0*.0??;*.1??;*.??0;*.BIN;*.CQ?;*.D??;*.FLP;*.HDM;*.IM?;*.XDF;*.*FD?\0Fluximages (*.FDI)\0*.FDI\0Oberflächenimages (*.86F;*.MFM)\0*.86F;*.MFM\0Alle Dateien (*.*)\0*.*\0" + IDS_2112 "SDL konnte nicht initialisiert werden, die Datei SDL2.dll wird benötigt" + IDS_2113 "Sind Sie sich sicher, dass Sie einen Hard-Reset für das emulierte System durchführen wollen?" + IDS_2114 "Sind Sie sich sicher, dass Sie 86Box beenden wollen?" + IDS_2115 "Ghostscript konnte nicht initialisiert werden" + IDS_2116 "MO %i (%ls): %ls" + IDS_2117 "MO-Images (*.IM?;*.MDI)\0*.IM?;*.MDI\0Alle Dateien (*.*)\0*.*\0" + IDS_2118 "Willkommen bei 86Box!" + IDS_2119 "Interner Controller" + IDS_2120 "Beenden" + IDS_2121 "Keine ROMs gefunden" + IDS_2122 "Möchten Sie die Einstellungen speichern?" + IDS_2123 "Dies wird zu einem Hard-Reset des emulierten Systems führen." + IDS_2124 "Speichern" + IDS_2125 "Über 86Box" + IDS_2126 "86Box Version " EMU_VERSION - IDS_2126 "Ein Emulator für alte Computer\n\nAutoren: Sarah Walker, Miran GrÄa, Fred N. van Kempen (waltje), SA1988, Tiseno100, reenigne, leilei, JohnElliott, greatpsycho sowie andere.\n\nÜbersetzt von: dob205\n\nVeröffentlicht unter der GNU General Public License in der Version 2 oder neuer. Siehe LICENSE für mehr Informationen." - IDS_2127 "OK" - IDS_2128 "Hardware nicht verfügbar" + IDS_2127 "Ein Emulator für alte Computer\n\nAutoren: Miran GrÄa (OBattler), RichardG867, Jasmine Iwanek, TC1995, coldbrewed, Teemu Korhonen (Manaatti), Joakim L. Gilje, Adrien Moulin (elyosh), Daniel Balsom (gloriouscow), Cacodemon345, Fred N. van Kempen (waltje), Tiseno100, reenigne sowie andere.\n\nWith previous core contributions from Sarah Walker, leilei, JohnElliott, greatpsycho sowie andere.\n\nÜbersetzt von: dob205\n\nVeröffentlicht unter der GNU General Public License in der Version 2 oder neuer. Siehe LICENSE für mehr Informationen." + IDS_2128 "OK" + IDS_2129 "Hardware nicht verfügbar" #ifdef _WIN32 #define LIB_NAME_PCAP "WinPcap" #else #define LIB_NAME_PCAP "libpcap" #endif - IDS_2129 "Bitte stellen Sie sicher, dass " LIB_NAME_PCAP " installiert ist und sie eine " LIB_NAME_PCAP "-kompatible Netzwerkverbindung nutzen." - IDS_2130 "Ungültige Konfiguration" -#ifdef _WIN32 -#define LIB_NAME_FREETYPE "freetype.dll" -#else -#define LIB_NAME_FREETYPE "libfreetype" -#endif - IDS_2131 LIB_NAME_FREETYPE " wird für die ESC/P-Druckeremulation benötigt." + IDS_2130 "Bitte stellen Sie sicher, dass " LIB_NAME_PCAP " installiert ist und sie eine " LIB_NAME_PCAP "-kompatible Netzwerkverbindung nutzen." + IDS_2131 "Ungültige Konfiguration" #ifdef _WIN32 #define LIB_NAME_GS "gsdll32.dll" #else #define LIB_NAME_GS "libgs" #endif - IDS_2132 LIB_NAME_GS " wird zur automatischen Konversion von PostScript-Dateien in das PDF-Format benötigt.\n\nSämtliche an den generischen PostScript-Drucker gesendete Dateien werden als PostScript (.ps)-Dateien gesichert." -#ifdef _WIN32 -#define LIB_NAME_FLUIDSYNTH "libfluidsynth.dll" -#else -#define LIB_NAME_FLUIDSYNTH "libfluidsynth" -#endif - IDS_2133 LIB_NAME_FLUIDSYNTH " wird für die FluidSynth-MIDI-Ausgabe benötigt." - IDS_2134 "Vollbildmodus wird aktiviert" - IDS_2135 "Diese Nachricht nicht mehr anzeigen" - IDS_2136 "Nicht beenden" - IDS_2137 "Zurücksetzen" - IDS_2138 "Nicht zurücksetzen" - IDS_2139 "MO-Images (*.IM?;*.MDI)\0*.IM?;*.MDI\0Alle Dateien (*.*)\0*.*\0" - IDS_2140 "CD-ROM-Images (*.ISO;*.CUE)\0*.ISO;*.CUE\0Alle Dateien (*.*)\0*.*\0" - IDS_2141 "%hs-Gerätekonfiguration" - IDS_2142 "Monitor im Standbymodus" - IDS_2143 "OpenGL-Shader (*.GLSL)\0*.GLSL\0Alle Dateien (*.*)\0*.*\0" - IDS_2144 "OpenGL-Optionen" - IDS_2145 "Sie laden gerade eine nicht unterstützte Konfiguration" - IDS_2146 "Das Filtern der CPU-Typen basierend auf dem ausgewählten System ist für dieses System deaktiviert.\n\nDies ermöglicht es, dass man eine sonst nicht mit dem ausgewählten System inkompatible CPU auswählen kann. Allerdings kann dies zu Inkompatiblilitäten mit dem BIOS des Systems oder anderen Programmen kommen.\n\nDas Aktivieren dieser Einstellung wird nicht unterstützt und sämtliche Bugreports können als ""invalid"" geschlossen werden." - IDS_2147 "Fortfahren" - IDS_2148 "Kassette: %s" - IDS_2149 "Kassettenimages (*.PCM;*.RAW;*.WAV;*.CAS)\0*.PCM;*.RAW;*.WAV;*.CAS\0Alle Dateien (*.*)\0*.*\0" - IDS_2150 "Cartridge %i: %ls" - IDS_2151 "Cartridgeimages (*.A;*.B;*.JRC)\0*.A;*.B;*.JRC\0Alle Dateien (*.*)\0*.*\0" - IDS_2152 "Fehler bei der Rendererinitialisierung" - IDS_2153 "Der OpenGL (3.0-Kern)-Renderer konnte nicht initialisiert werden. Bitte benutzen Sie einen anderen Renderer." - IDS_2154 "Fortsetzen" - IDS_2155 "Pausieren" - IDS_2156 "Strg+Alt+Entf drücken" - IDS_2157 "Strg+Alt+Esc drücken" - IDS_2158 "Hard-Reset" - IDS_2159 "ACPI-basiertes Herunterfahren" - IDS_2160 "Optionen" + IDS_2133 LIB_NAME_GS " wird zur automatischen Konversion von PostScript-Dateien in das PDF-Format benötigt.\n\nSämtliche an den generischen PostScript-Drucker gesendete Dateien werden als PostScript (.ps)-Dateien gesichert." + IDS_2135 "Vollbildmodus wird aktiviert" + IDS_2136 "Diese Nachricht nicht mehr anzeigen" + IDS_2137 "Nicht beenden" + IDS_2138 "Zurücksetzen" + IDS_2139 "Nicht zurücksetzen" + IDS_2140 "MO-Images (*.IM?;*.MDI)\0*.IM?;*.MDI\0Alle Dateien (*.*)\0*.*\0" + IDS_2141 "CD-ROM-Images (*.ISO;*.CUE)\0*.ISO;*.CUE\0Alle Dateien (*.*)\0*.*\0" + IDS_2142 "%hs-Gerätekonfiguration" + IDS_2143 "Monitor im Standbymodus" + IDS_2144 "OpenGL-Shader (*.GLSL)\0*.GLSL\0Alle Dateien (*.*)\0*.*\0" + IDS_2145 "OpenGL-Optionen" + IDS_2146 "Sie laden gerade eine nicht unterstützte Konfiguration" + IDS_2147 "Das Filtern der CPU-Typen basierend auf dem ausgewählten System ist für dieses System deaktiviert.\n\nDies ermöglicht es, dass man eine sonst nicht mit dem ausgewählten System inkompatible CPU auswählen kann. Allerdings kann dies zu Inkompatiblilitäten mit dem BIOS des Systems oder anderen Programmen kommen.\n\nDas Aktivieren dieser Einstellung wird nicht unterstützt und sämtliche Bugreports können als ""invalid"" geschlossen werden." + IDS_2148 "Fortfahren" + IDS_2149 "Kassette: %s" + IDS_2150 "Kassettenimages (*.PCM;*.RAW;*.WAV;*.CAS)\0*.PCM;*.RAW;*.WAV;*.CAS\0Alle Dateien (*.*)\0*.*\0" + IDS_2151 "Cartridge %i: %ls" + IDS_2152 "Cartridgeimages (*.A;*.B;*.JRC)\0*.A;*.B;*.JRC\0Alle Dateien (*.*)\0*.*\0" + IDS_2153 "Fehler bei der Rendererinitialisierung" + IDS_2154 "Der OpenGL (3.0-Kern)-Renderer konnte nicht initialisiert werden. Bitte benutzen Sie einen anderen Renderer." + IDS_2155 "Fortsetzen" + IDS_2156 "Pausieren" + IDS_2157 "Strg+Alt+Entf drücken" + IDS_2158 "Strg+Alt+Esc drücken" + IDS_2159 "Hard-Reset" + IDS_2160 "ACPI-basiertes Herunterfahren" + IDS_2161 "Optionen" + IDS_2162 "Type" + IDS_2163 "No Dynarec" + IDS_2164 "Old Dynarec" + IDS_2165 "New Dynarec" + IDS_2166 "Video card #2 ""%hs"" is not available due to missing ROMs in the roms/video directory. Disabling the second video card." + IDS_2167 "Failed to initialize network driver" + IDS_2168 "The network configuration will be switched to the null driver" END -STRINGTABLE DISCARDABLE +STRINGTABLE DISCARDABLE BEGIN IDS_4096 "Festplatte (%s)" - IDS_4097 "%01i:%01i" - IDS_4098 "%01i" - IDS_4099 "MFM/RLL- oder ESDI CD-ROM-Laufwerke hat es niemals gegeben" - IDS_4100 "Angepasst..." - IDS_4101 "Angepasst (Groß)..." - IDS_4102 "Neue Festplatte hinzufügen" - IDS_4103 "Bestehende Festplatte hinzufügen" - IDS_4104 "HDI-Diskimages können nicht größer als 4 GB groß sein." - IDS_4105 "Festplattenimages können nicht größer als 127 GB groß sein." - IDS_4106 "Festplattenimages (*.HD?;*.IM?;*.VHD)\0*.HD?;*.IM?;*.VHD\0Alle Dateien (*.*)\0*.*\0" - IDS_4107 "Die Datei konnte nicht gelesen werden" - IDS_4108 "Die Datei konnte nicht beschrieben werden" - IDS_4109 "HDI- oder HDX-Images mit einer Sektorgröße größer als 512 kB werden nicht unterstützt." - IDS_4110 "USB wird noch nicht unterstützt" - IDS_4111 "Die Festplattenimagedatei existiert bereits" - IDS_4112 "Bitte geben Sie einen gültigen Dateinamen ein." - IDS_4113 "Disk-Image wurde erstellt" - IDS_4114 "Bitte stellen Sie sicher, dass die Datei existiert und lesbar ist." - IDS_4115 "Bitte stellen Sie sicher, dass die Datei in ein Verzeichnis mit Schreibberechtigungen gespeichert wird." - IDS_4116 "Festplattenimage ist zu groß" - IDS_4117 "Bitte denken Sie an das Partitionieren und Formatieren des neu erstellten Laufwerks." - IDS_4118 "Die ausgewählte Datei wird überschrieben. Möchten Sie diese Datei nutzen?" - IDS_4119 "Nicht unterstütztes Festplattenimage" - IDS_4120 "Überschreiben" - IDS_4121 "Nicht überschreiben" - IDS_4122 "Rohdatenimages (.img)" - IDS_4123 "HDI-Images (.hdi)" - IDS_4124 "HDX-Images (.hdx)" - IDS_4125 "VHD mit fester Größe (.vhd)" - IDS_4126 "VHD mit dynamischer Größe (.vhd)" - IDS_4127 "Differenzierende VHD (.vhd)" - IDS_4128 "Große Blöcke (2 MB)" - IDS_4129 "Kleine Blöcke (512 KB)" - IDS_4130 "VHD-Dateien (*.VHD)\0*.VHD\0Alle Dateien (*.*)\0*.*\0" - IDS_4131 "Eltern-VHD-Datei bitte auswählen" - IDS_4132 "Dies bedeutet, dass das Elternimage nach der Erstellung des differenzierenden Images erzeugt wurde.\n\nDies kann auch passieren, falls die Image-Dateien verschoben oder kopiert wurden. Ebenso kann auch dies durch einen Bug im Programm, welches das Image erstellt hat, passieren.\n\nMöchten Sie die Zeitstempel korrigieren?" - IDS_4133 "Die Zeitstempel der Eltern- und der Kindesplatte stimmen nicht überein" - IDS_4134 "Der Zeitstempel der VHD konnte nicht korrigiert werden." - IDS_4135 "%01i:%02i" + IDS_4097 "%01i:%01i" + IDS_4098 "%01i" + IDS_4099 "MFM/RLL- oder ESDI CD-ROM-Laufwerke hat es niemals gegeben" + IDS_4100 "Angepasst..." + IDS_4101 "Angepasst (Groß)..." + IDS_4102 "Neue Festplatte hinzufügen" + IDS_4103 "Bestehende Festplatte hinzufügen" + IDS_4104 "HDI-Diskimages können nicht größer als 4 GB groß sein." + IDS_4105 "Festplattenimages können nicht größer als 127 GB groß sein." + IDS_4106 "Festplattenimages (*.HD?;*.IM?;*.VHD)\0*.HD?;*.IM?;*.VHD\0Alle Dateien (*.*)\0*.*\0" + IDS_4107 "Die Datei konnte nicht gelesen werden" + IDS_4108 "Die Datei konnte nicht beschrieben werden" + IDS_4109 "HDI- oder HDX-Images mit einer Sektorgröße größer als 512 kB werden nicht unterstützt." + IDS_4110 "USB wird noch nicht unterstützt" + IDS_4111 "Die Festplattenimagedatei existiert bereits" + IDS_4112 "Bitte geben Sie einen gültigen Dateinamen ein." + IDS_4113 "Disk-Image wurde erstellt" + IDS_4114 "Bitte stellen Sie sicher, dass die Datei existiert und lesbar ist." + IDS_4115 "Bitte stellen Sie sicher, dass die Datei in ein Verzeichnis mit Schreibberechtigungen gespeichert wird." + IDS_4116 "Festplattenimage ist zu groß" + IDS_4117 "Bitte denken Sie an das Partitionieren und Formatieren des neu erstellten Laufwerks." + IDS_4118 "Die ausgewählte Datei wird überschrieben. Möchten Sie diese Datei nutzen?" + IDS_4119 "Nicht unterstütztes Festplattenimage" + IDS_4120 "Überschreiben" + IDS_4121 "Nicht überschreiben" + IDS_4122 "Rohdatenimages (.img)" + IDS_4123 "HDI-Images (.hdi)" + IDS_4124 "HDX-Images (.hdx)" + IDS_4125 "VHD mit fester Größe (.vhd)" + IDS_4126 "VHD mit dynamischer Größe (.vhd)" + IDS_4127 "Differenzierende VHD (.vhd)" + IDS_4128 "Große Blöcke (2 MB)" + IDS_4129 "Kleine Blöcke (512 KB)" + IDS_4130 "VHD-Dateien (*.VHD)\0*.VHD\0Alle Dateien (*.*)\0*.*\0" + IDS_4131 "Eltern-VHD-Datei bitte auswählen" + IDS_4132 "Dies bedeutet, dass das Elternimage nach der Erstellung des differenzierenden Images erzeugt wurde.\n\nDies kann auch passieren, falls die Image-Dateien verschoben oder kopiert wurden. Ebenso kann auch dies durch einen Bug im Programm, welches das Image erstellt hat, passieren.\n\nMöchten Sie die Zeitstempel korrigieren?" + IDS_4133 "Die Zeitstempel der Eltern- und der Kindesplatte stimmen nicht überein" + IDS_4134 "Der Zeitstempel der VHD konnte nicht korrigiert werden." + IDS_4135 "%01i:%02i" IDS_4352 "MFM/RLL" IDS_4353 "XTA" @@ -562,56 +582,56 @@ BEGIN IDS_4356 "ATAPI" IDS_4357 "SCSI" - IDS_4608 "MFM/RLL (%01i:%01i)" - IDS_4609 "XTA (%01i:%01i)" - IDS_4610 "ESDI (%01i:%01i)" - IDS_4611 "IDE (%01i:%01i)" - IDS_4612 "ATAPI (%01i:%01i)" - IDS_4613 "SCSI (%01i:%02i)" + IDS_4608 "MFM/RLL (%01i:%01i)" + IDS_4609 "XTA (%01i:%01i)" + IDS_4610 "ESDI (%01i:%01i)" + IDS_4611 "IDE (%01i:%01i)" + IDS_4612 "ATAPI (%01i:%01i)" + IDS_4613 "SCSI (%01i:%02i)" - IDS_5120 "CD-ROM %i (%s): %s" + IDS_5120 "CD-ROM %i (%s): %s" - IDS_5376 "Deaktiviert" - IDS_5381 "ATAPI" + IDS_5376 "Deaktiviert" + IDS_5381 "ATAPI" IDS_5382 "SCSI" - IDS_5632 "Deaktiviert" - IDS_5637 "ATAPI (%01i:%01i)" + IDS_5632 "Deaktiviert" + IDS_5637 "ATAPI (%01i:%01i)" IDS_5638 "SCSI (%01i:%02i)" - IDS_5888 "160 kB" - IDS_5889 "180 kB" - IDS_5890 "320 kB" - IDS_5891 "360 kB" - IDS_5892 "640 kB" - IDS_5893 "720 kB" - IDS_5894 "1,2 MB" - IDS_5895 "1,25 MB" - IDS_5896 "1,44 MB" - IDS_5897 "DMF (1024 Cluster)" - IDS_5898 "DMF (2048 Cluster)" - IDS_5899 "2,88 MB" - IDS_5900 "ZIP 100" - IDS_5901 "ZIP 250" - IDS_5902 "3,5-Zoll 128 MB (ISO 10090)" - IDS_5903 "3,5-Zoll 230 MB (ISO 13963)" - IDS_5904 "3,5-Zoll 540 MB (ISO 15498)" - IDS_5905 "3,5-Zoll 640 MB (ISO 15498)" - IDS_5906 "3,5-Zoll 1,3 GB (GigaMO)" - IDS_5907 "3,5-Zoll 2,3 GB (GigaMO 2)" - IDS_5908 "5,25-Zoll 600 MB" - IDS_5909 "5,25-Zoll 650 MB" - IDS_5910 "5,25-Zoll 1 GB" - IDS_5911 "5,25-Zoll 1,3 GB" + IDS_5888 "160 kB" + IDS_5889 "180 kB" + IDS_5890 "320 kB" + IDS_5891 "360 kB" + IDS_5892 "640 kB" + IDS_5893 "720 kB" + IDS_5894 "1,2 MB" + IDS_5895 "1,25 MB" + IDS_5896 "1,44 MB" + IDS_5897 "DMF (1024 Cluster)" + IDS_5898 "DMF (2048 Cluster)" + IDS_5899 "2,88 MB" + IDS_5900 "ZIP 100" + IDS_5901 "ZIP 250" + IDS_5902 "3,5-Zoll 128 MB (ISO 10090)" + IDS_5903 "3,5-Zoll 230 MB (ISO 13963)" + IDS_5904 "3,5-Zoll 540 MB (ISO 15498)" + IDS_5905 "3,5-Zoll 640 MB (ISO 15498)" + IDS_5906 "3,5-Zoll 1,3 GB (GigaMO)" + IDS_5907 "3,5-Zoll 2,3 GB (GigaMO 2)" + IDS_5908 "5,25-Zoll 600 MB" + IDS_5909 "5,25-Zoll 650 MB" + IDS_5910 "5,25-Zoll 1 GB" + IDS_5911 "5,25-Zoll 1,3 GB" - IDS_6144 "Perfekte Drehzahl" - IDS_6145 "1% unterhalb der perfekten Drehzahl" - IDS_6146 "1,5% unterhalb der perfekten Drehzahl" - IDS_6147 "2% unterhalb der perfekten Drehzahl" + IDS_6144 "Perfekte Drehzahl" + IDS_6145 "1% unterhalb der perfekten Drehzahl" + IDS_6146 "1,5% unterhalb der perfekten Drehzahl" + IDS_6147 "2% unterhalb der perfekten Drehzahl" - IDS_7168 "(Systemstandard)" + IDS_7168 "(Systemstandard)" END -#define IDS_LANG_ENUS IDS_7168 +#define IDS_LANG_ENUS IDS_7168 // German (de-DE) resources ///////////////////////////////////////////////////////////////////////////// diff --git a/src/win/languages/dialogs.rc b/src/win/languages/dialogs.rc index 4a4c132fc..1daf46b4c 100644 --- a/src/win/languages/dialogs.rc +++ b/src/win/languages/dialogs.rc @@ -3,6 +3,8 @@ #define CFG_BTN_WIDTH 46 #define CFG_BTN_HEIGHT 14 #define CFG_PANE_LTEXT_PRI_WIDTH 85 +#define CFG_PANE_LTEXT_PRI_WIDTH_2 170 +#define CFG_PANE_LTEXT_PRI_WIDTH_3 255 #define CFG_PANE_LTEXT_HEIGHT 10 #define CFG_COMBO_BTN_WIDTH 212 #define CFG_COMBO_NOBTN_WIDTH CFG_COMBO_BTN_WIDTH + CFG_BTN_WIDTH + 8 @@ -232,20 +234,25 @@ BEGIN CFG_HMARGIN, 120, 120, CFG_CHECKBOX_HEIGHT #endif + CONTROL STR_SOFTFLOAT, IDC_CHECK_SOFTFLOAT, + "Button", BS_AUTOCHECKBOX | WS_TABSTOP, + CFG_HMARGIN, 135, 120, CFG_CHECKBOX_HEIGHT + + GROUPBOX STR_TIME_SYNC, IDC_TIME_SYNC, - CFG_HMARGIN, 135, 110, 56 + CFG_HMARGIN, 150, 110, 56 CONTROL STR_DISABLED, IDC_RADIO_TS_DISABLED, "Button", BS_AUTORADIOBUTTON | WS_GROUP | WS_TABSTOP, - 14, 147, CFG_CHECKBOX_PRI_WIDTH, CFG_CHECKBOX_HEIGHT + 14, 162, CFG_CHECKBOX_PRI_WIDTH, CFG_CHECKBOX_HEIGHT CONTROL STR_ENABLED_LOCAL, IDC_RADIO_TS_LOCAL, "Button", BS_AUTORADIOBUTTON | WS_TABSTOP, - 14, 161, CFG_CHECKBOX_PRI_WIDTH, CFG_CHECKBOX_HEIGHT + 14, 176, CFG_CHECKBOX_PRI_WIDTH, CFG_CHECKBOX_HEIGHT CONTROL STR_ENABLED_UTC, IDC_RADIO_TS_UTC, "Button", BS_AUTORADIOBUTTON | WS_TABSTOP, - 14, 175, CFG_CHECKBOX_PRI_WIDTH, CFG_CHECKBOX_HEIGHT + 14, 190, CFG_CHECKBOX_PRI_WIDTH, CFG_CHECKBOX_HEIGHT END DLG_CFG_VIDEO DIALOG DISCARDABLE CFG_PANE_LEFT, CFG_PANE_TOP, CFG_PANE_WIDTH, CFG_PANE_HEIGHT @@ -260,11 +267,29 @@ BEGIN PUSHBUTTON STR_CONFIGURE, IDC_CONFIGURE_VID, CFG_COMBO_BTN_LEFT, 6, CFG_BTN_WIDTH, CFG_BTN_HEIGHT + LTEXT STR_VIDEO_2, IDT_VIDEO_2, + CFG_HMARGIN, 28, CFG_PANE_LTEXT_PRI_WIDTH, CFG_PANE_LTEXT_HEIGHT + COMBOBOX IDC_COMBO_VIDEO_2, + CFG_COMBO_BOX_LEFT, 26, CFG_COMBO_BTN_WIDTH, CFG_COMBO_HEIGHT, + CBS_DROPDOWNLIST | WS_VSCROLL | WS_TABSTOP + PUSHBUTTON STR_CONFIGURE, IDC_CONFIGURE_VID_2, + CFG_COMBO_BTN_LEFT, 25, CFG_BTN_WIDTH, CFG_BTN_HEIGHT + CONTROL STR_VOODOO, IDC_CHECK_VOODOO, "Button", BS_AUTOCHECKBOX | WS_TABSTOP, - 7, 27, 199, CFG_CHECKBOX_HEIGHT + CFG_HMARGIN, 47, 199, CFG_CHECKBOX_HEIGHT PUSHBUTTON STR_CONFIGURE, IDC_BUTTON_VOODOO, - CFG_COMBO_BTN_LEFT, 25, CFG_BTN_WIDTH, CFG_BTN_HEIGHT + CFG_COMBO_BTN_LEFT, 45, CFG_BTN_WIDTH, CFG_BTN_HEIGHT + + CONTROL STR_IBM8514, IDC_CHECK_IBM8514, + "Button", BS_AUTOCHECKBOX | WS_TABSTOP, + CFG_HMARGIN, 66, 199, CFG_CHECKBOX_HEIGHT + + CONTROL STR_XGA, IDC_CHECK_XGA, + "Button", BS_AUTOCHECKBOX | WS_TABSTOP, + CFG_HMARGIN, 85, 199, CFG_CHECKBOX_HEIGHT + PUSHBUTTON STR_CONFIGURE, IDC_BUTTON_XGA, + CFG_COMBO_BTN_LEFT, 84, CFG_BTN_WIDTH, CFG_BTN_HEIGHT END DLG_CFG_INPUT DIALOG DISCARDABLE CFG_PANE_LEFT, CFG_PANE_TOP, CFG_PANE_WIDTH, CFG_PANE_HEIGHT @@ -302,58 +327,75 @@ DLG_CFG_SOUND DIALOG DISCARDABLE CFG_PANE_LEFT, CFG_PANE_TOP, CFG_PANE_WIDTH, C STYLE DS_CONTROL | WS_CHILD FONT FONT_SIZE, FONT_NAME BEGIN - LTEXT STR_SOUND, IDT_SOUND, + LTEXT STR_SOUND1, IDT_SOUND1, CFG_HMARGIN, CFG_VMARGIN, CFG_PANE_LTEXT_PRI_WIDTH, CFG_PANE_LTEXT_HEIGHT - COMBOBOX IDC_COMBO_SOUND, + COMBOBOX IDC_COMBO_SOUND1, CFG_COMBO_BOX_LEFT, 7, CFG_COMBO_BTN_WIDTH, CFG_COMBO_HEIGHT, CBS_DROPDOWNLIST | WS_VSCROLL | WS_TABSTOP - PUSHBUTTON STR_CONFIGURE, IDC_CONFIGURE_SND, + PUSHBUTTON STR_CONFIGURE, IDC_CONFIGURE_SND1, CFG_COMBO_BTN_LEFT, 6, CFG_BTN_WIDTH, CFG_BTN_HEIGHT - LTEXT STR_MIDI_OUT, IDT_MIDI_OUT, + LTEXT STR_SOUND2, IDT_SOUND2, CFG_HMARGIN, 28, CFG_PANE_LTEXT_PRI_WIDTH, CFG_PANE_LTEXT_HEIGHT - COMBOBOX IDC_COMBO_MIDI_OUT, + COMBOBOX IDC_COMBO_SOUND2, CFG_COMBO_BOX_LEFT, 26, CFG_COMBO_BTN_WIDTH, CFG_COMBO_HEIGHT, CBS_DROPDOWNLIST | WS_VSCROLL | WS_TABSTOP + PUSHBUTTON STR_CONFIGURE, IDC_CONFIGURE_SND2, + CFG_COMBO_BTN_LEFT, 25, CFG_BTN_WIDTH, CFG_BTN_HEIGHT + + LTEXT STR_SOUND3, IDT_SOUND3, + CFG_HMARGIN, 48, CFG_PANE_LTEXT_PRI_WIDTH, CFG_PANE_LTEXT_HEIGHT + COMBOBOX IDC_COMBO_SOUND3, + CFG_COMBO_BOX_LEFT, 46, CFG_COMBO_BTN_WIDTH, CFG_COMBO_HEIGHT, + CBS_DROPDOWNLIST | WS_VSCROLL | WS_TABSTOP + PUSHBUTTON STR_CONFIGURE, IDC_CONFIGURE_SND3, + CFG_COMBO_BTN_LEFT, 45, CFG_BTN_WIDTH, CFG_BTN_HEIGHT + + LTEXT STR_SOUND4, IDT_SOUND4, + CFG_HMARGIN, 68, CFG_PANE_LTEXT_PRI_WIDTH, CFG_PANE_LTEXT_HEIGHT + COMBOBOX IDC_COMBO_SOUND4, + CFG_COMBO_BOX_LEFT, 66, CFG_COMBO_BTN_WIDTH, CFG_COMBO_HEIGHT, + CBS_DROPDOWNLIST | WS_VSCROLL | WS_TABSTOP + PUSHBUTTON STR_CONFIGURE, IDC_CONFIGURE_SND4, + CFG_COMBO_BTN_LEFT, 65, CFG_BTN_WIDTH, CFG_BTN_HEIGHT + + LTEXT STR_MIDI_OUT, IDT_MIDI_OUT, + CFG_HMARGIN, 88, CFG_PANE_LTEXT_PRI_WIDTH, CFG_PANE_LTEXT_HEIGHT + COMBOBOX IDC_COMBO_MIDI_OUT, + CFG_COMBO_BOX_LEFT, 86, CFG_COMBO_BTN_WIDTH, CFG_COMBO_HEIGHT, + CBS_DROPDOWNLIST | WS_VSCROLL | WS_TABSTOP PUSHBUTTON STR_CONFIGURE, IDC_CONFIGURE_MIDI_OUT, - CFG_COMBO_BTN_LEFT, 25, CFG_BTN_WIDTH, CFG_BTN_HEIGHT + CFG_COMBO_BTN_LEFT, 85, CFG_BTN_WIDTH, CFG_BTN_HEIGHT LTEXT STR_MIDI_IN, IDT_MIDI_IN, - CFG_HMARGIN, 47, CFG_PANE_LTEXT_PRI_WIDTH, CFG_PANE_LTEXT_HEIGHT + CFG_HMARGIN, 108, CFG_PANE_LTEXT_PRI_WIDTH, CFG_PANE_LTEXT_HEIGHT COMBOBOX IDC_COMBO_MIDI_IN, - CFG_COMBO_BOX_LEFT, 45, CFG_COMBO_BTN_WIDTH, CFG_COMBO_HEIGHT, + CFG_COMBO_BOX_LEFT, 105, CFG_COMBO_BTN_WIDTH, CFG_COMBO_HEIGHT, CBS_DROPDOWNLIST | WS_VSCROLL | WS_TABSTOP PUSHBUTTON STR_CONFIGURE, IDC_CONFIGURE_MIDI_IN, - CFG_COMBO_BTN_LEFT, 44, CFG_BTN_WIDTH, CFG_BTN_HEIGHT + CFG_COMBO_BTN_LEFT, 105, CFG_BTN_WIDTH, CFG_BTN_HEIGHT CONTROL STR_MPU401,IDC_CHECK_MPU401, "Button", BS_AUTOCHECKBOX | WS_TABSTOP, - CFG_HMARGIN, 66, 199, CFG_CHECKBOX_HEIGHT + CFG_HMARGIN, 126, 199, CFG_CHECKBOX_HEIGHT PUSHBUTTON STR_CONFIGURE, IDC_CONFIGURE_MPU401, - CFG_COMBO_BTN_LEFT, 64, CFG_BTN_WIDTH, CFG_BTN_HEIGHT + CFG_COMBO_BTN_LEFT, 125, CFG_BTN_WIDTH, CFG_BTN_HEIGHT - CONTROL STR_SSI,IDC_CHECK_SSI, - "Button", BS_AUTOCHECKBOX | WS_TABSTOP, - CFG_HMARGIN, 84, 95, CFG_CHECKBOX_HEIGHT - PUSHBUTTON STR_CONFIGURE, IDC_CONFIGURE_SSI, - CFG_COMBO_BTN_LEFT, 82, CFG_BTN_WIDTH, CFG_BTN_HEIGHT - - CONTROL STR_CMS,IDC_CHECK_CMS, - "Button", BS_AUTOCHECKBOX | WS_TABSTOP, - CFG_HMARGIN, 102, CFG_CHECKBOX_PRI_WIDTH, CFG_CHECKBOX_HEIGHT - PUSHBUTTON STR_CONFIGURE, IDC_CONFIGURE_CMS, - CFG_COMBO_BTN_LEFT, 100, CFG_BTN_WIDTH, CFG_BTN_HEIGHT - - CONTROL STR_GUS,IDC_CHECK_GUS, - "Button", BS_AUTOCHECKBOX | WS_TABSTOP, - CFG_HMARGIN, 120, CFG_CHECKBOX_PRI_WIDTH, CFG_CHECKBOX_HEIGHT - PUSHBUTTON STR_CONFIGURE, IDC_CONFIGURE_GUS, - CFG_COMBO_BTN_LEFT, 118, CFG_BTN_WIDTH, CFG_BTN_HEIGHT - CONTROL STR_FLOAT, IDC_CHECK_FLOAT, "Button", BS_AUTOCHECKBOX | WS_TABSTOP, - CFG_HMARGIN, 138, 104, CFG_CHECKBOX_HEIGHT + CFG_HMARGIN, 138, 194, CFG_CHECKBOX_HEIGHT + + GROUPBOX STR_FM_DRIVER, IDC_FM_DRIVER, + CFG_HMARGIN, 154, 110, 42 + + CONTROL STR_FM_DRV_NUKED, IDC_RADIO_FM_DRV_NUKED, + "Button", BS_AUTORADIOBUTTON | WS_GROUP | WS_TABSTOP, + 14, 166, CFG_CHECKBOX_PRI_WIDTH, CFG_CHECKBOX_HEIGHT + + CONTROL STR_FM_DRV_YMFM, IDC_RADIO_FM_DRV_YMFM, + "Button", BS_AUTORADIOBUTTON | WS_TABSTOP, + 14, 180, CFG_CHECKBOX_PRI_WIDTH, CFG_CHECKBOX_HEIGHT END DLG_CFG_NETWORK DIALOG DISCARDABLE CFG_PANE_LEFT, CFG_PANE_TOP, CFG_PANE_WIDTH, CFG_PANE_HEIGHT @@ -362,23 +404,67 @@ FONT FONT_SIZE, FONT_NAME BEGIN LTEXT STR_NET_TYPE, IDT_NET_TYPE, CFG_HMARGIN, CFG_VMARGIN, CFG_PANE_LTEXT_PRI_WIDTH, CFG_PANE_LTEXT_HEIGHT - COMBOBOX IDC_COMBO_NET_TYPE, - CFG_COMBO_BOX_LEFT, 7, CFG_COMBO_NOBTN_WIDTH, CFG_COMBO_HEIGHT, - CBS_DROPDOWNLIST | WS_VSCROLL | WS_TABSTOP - LTEXT STR_PCAP, IDT_PCAP, - CFG_HMARGIN, 28, CFG_PANE_LTEXT_PRI_WIDTH, CFG_PANE_LTEXT_HEIGHT - COMBOBOX IDC_COMBO_PCAP, - CFG_COMBO_BOX_LEFT, 26, CFG_COMBO_NOBTN_WIDTH, CFG_COMBO_HEIGHT, + CFG_HMARGIN + CFG_PANE_LTEXT_PRI_WIDTH - 10, CFG_VMARGIN, CFG_PANE_LTEXT_PRI_WIDTH, CFG_PANE_LTEXT_HEIGHT + LTEXT STR_NET, IDT_NET, + CFG_HMARGIN + CFG_PANE_LTEXT_PRI_WIDTH_2 + 20, CFG_VMARGIN, CFG_PANE_LTEXT_PRI_WIDTH, CFG_PANE_LTEXT_HEIGHT + + COMBOBOX IDC_COMBO_NET1_TYPE, + CFG_HMARGIN, 28, 48, CFG_COMBO_HEIGHT, CBS_DROPDOWNLIST | WS_VSCROLL | WS_TABSTOP - LTEXT STR_NET, IDT_NET, - CFG_HMARGIN, 47, CFG_PANE_LTEXT_PRI_WIDTH, CFG_PANE_LTEXT_HEIGHT - COMBOBOX IDC_COMBO_NET, - CFG_COMBO_BOX_LEFT, 45, CFG_COMBO_BTN_WIDTH, CFG_COMBO_HEIGHT, + COMBOBOX IDC_COMBO_PCAP1, + CFG_HMARGIN + CFG_PANE_LTEXT_PRI_WIDTH - 10, 28, 110, CFG_COMBO_HEIGHT, CBS_DROPDOWNLIST | WS_VSCROLL | WS_TABSTOP - PUSHBUTTON STR_CONFIGURE, IDC_CONFIGURE_NET, - CFG_COMBO_BTN_LEFT, 44, CFG_BTN_WIDTH, CFG_BTN_HEIGHT + + COMBOBOX IDC_COMBO_NET1, + CFG_HMARGIN + CFG_PANE_LTEXT_PRI_WIDTH_2 + 20, 28, 110, CFG_COMBO_HEIGHT, + CBS_DROPDOWNLIST | WS_VSCROLL | WS_TABSTOP + PUSHBUTTON STR_CONFIGURE, IDC_CONFIGURE_NET1, + CFG_HMARGIN + CFG_PANE_LTEXT_PRI_WIDTH_3 + 50, 27, CFG_BTN_WIDTH, CFG_BTN_HEIGHT + + COMBOBOX IDC_COMBO_NET2_TYPE, + CFG_HMARGIN, 49, 48, CFG_COMBO_HEIGHT, + CBS_DROPDOWNLIST | WS_VSCROLL | WS_TABSTOP + + COMBOBOX IDC_COMBO_PCAP2, + CFG_HMARGIN + CFG_PANE_LTEXT_PRI_WIDTH - 10, 49, 110, CFG_COMBO_HEIGHT, + CBS_DROPDOWNLIST | WS_VSCROLL | WS_TABSTOP + + COMBOBOX IDC_COMBO_NET2, + CFG_HMARGIN + CFG_PANE_LTEXT_PRI_WIDTH_2 + 20, 49, 110, CFG_COMBO_HEIGHT, + CBS_DROPDOWNLIST | WS_VSCROLL | WS_TABSTOP + PUSHBUTTON STR_CONFIGURE, IDC_CONFIGURE_NET2, + CFG_HMARGIN + CFG_PANE_LTEXT_PRI_WIDTH_3 + 50, 48, CFG_BTN_WIDTH, CFG_BTN_HEIGHT + + COMBOBOX IDC_COMBO_NET3_TYPE, + CFG_HMARGIN, 70, 48, CFG_COMBO_HEIGHT, + CBS_DROPDOWNLIST | WS_VSCROLL | WS_TABSTOP + + COMBOBOX IDC_COMBO_PCAP3, + CFG_HMARGIN + CFG_PANE_LTEXT_PRI_WIDTH - 10, 70, 110, CFG_COMBO_HEIGHT, + CBS_DROPDOWNLIST | WS_VSCROLL | WS_TABSTOP + + COMBOBOX IDC_COMBO_NET3, + CFG_HMARGIN + CFG_PANE_LTEXT_PRI_WIDTH_2 + 20, 70, 110, CFG_COMBO_HEIGHT, + CBS_DROPDOWNLIST | WS_VSCROLL | WS_TABSTOP + PUSHBUTTON STR_CONFIGURE, IDC_CONFIGURE_NET3, + CFG_HMARGIN + CFG_PANE_LTEXT_PRI_WIDTH_3 + 50, 69, CFG_BTN_WIDTH, CFG_BTN_HEIGHT + + COMBOBOX IDC_COMBO_NET4_TYPE, + CFG_HMARGIN, 91, 48, CFG_COMBO_HEIGHT, + CBS_DROPDOWNLIST | WS_VSCROLL | WS_TABSTOP + + COMBOBOX IDC_COMBO_PCAP4, + CFG_HMARGIN + CFG_PANE_LTEXT_PRI_WIDTH - 10, 91, 110, CFG_COMBO_HEIGHT, + CBS_DROPDOWNLIST | WS_VSCROLL | WS_TABSTOP + + COMBOBOX IDC_COMBO_NET4, + CFG_HMARGIN + CFG_PANE_LTEXT_PRI_WIDTH_2 + 20, 91, 110, CFG_COMBO_HEIGHT, + CBS_DROPDOWNLIST | WS_VSCROLL | WS_TABSTOP + PUSHBUTTON STR_CONFIGURE, IDC_CONFIGURE_NET4, + CFG_HMARGIN + CFG_PANE_LTEXT_PRI_WIDTH_3 + 50, 90, CFG_BTN_WIDTH, CFG_BTN_HEIGHT + END DLG_CFG_PORTS DIALOG DISCARDABLE CFG_PANE_LEFT, CFG_PANE_TOP, CFG_PANE_WIDTH, CFG_PANE_HEIGHT @@ -418,54 +504,78 @@ BEGIN CBS_DROPDOWNLIST | WS_VSCROLL | WS_TABSTOP LTEXT STR_LPT2, IDT_LPT2, - CFG_HMARGIN, 28, CFG_PANE_LTEXT_PRI_WIDTH, CFG_PANE_LTEXT_HEIGHT + CFG_HMARGIN, 24, CFG_PANE_LTEXT_PRI_WIDTH, CFG_PANE_LTEXT_HEIGHT COMBOBOX IDC_COMBO_LPT2, - CFG_COMBO_BOX_LEFT, 26, CFG_COMBO_NOBTN_WIDTH, CFG_COMBO_HEIGHT, + CFG_COMBO_BOX_LEFT, 22, CFG_COMBO_NOBTN_WIDTH, CFG_COMBO_HEIGHT, CBS_DROPDOWNLIST | WS_VSCROLL | WS_TABSTOP LTEXT STR_LPT3, IDT_LPT3, - CFG_HMARGIN, 47, CFG_PANE_LTEXT_PRI_WIDTH, CFG_PANE_LTEXT_HEIGHT + CFG_HMARGIN, 39, CFG_PANE_LTEXT_PRI_WIDTH, CFG_PANE_LTEXT_HEIGHT COMBOBOX IDC_COMBO_LPT3, - CFG_COMBO_BOX_LEFT, 45, CFG_COMBO_NOBTN_WIDTH, CFG_COMBO_HEIGHT, + CFG_COMBO_BOX_LEFT, 37, CFG_COMBO_NOBTN_WIDTH, CFG_COMBO_HEIGHT, CBS_DROPDOWNLIST | WS_VSCROLL | WS_TABSTOP LTEXT STR_LPT4, IDT_LPT4, - CFG_HMARGIN, 66, CFG_PANE_LTEXT_PRI_WIDTH, CFG_PANE_LTEXT_HEIGHT + CFG_HMARGIN, 54, CFG_PANE_LTEXT_PRI_WIDTH, CFG_PANE_LTEXT_HEIGHT COMBOBOX IDC_COMBO_LPT4, - CFG_COMBO_BOX_LEFT, 64, CFG_COMBO_NOBTN_WIDTH, CFG_COMBO_HEIGHT, + CFG_COMBO_BOX_LEFT, 52, CFG_COMBO_NOBTN_WIDTH, CFG_COMBO_HEIGHT, CBS_DROPDOWNLIST | WS_VSCROLL | WS_TABSTOP CONTROL STR_SERIAL1, IDC_CHECK_SERIAL1, "Button", BS_AUTOCHECKBOX | WS_TABSTOP, - CFG_HMARGIN, 83, CFG_CHECKBOX_PRI_WIDTH, CFG_CHECKBOX_HEIGHT + CFG_HMARGIN, 71, CFG_CHECKBOX_PRI_WIDTH, CFG_CHECKBOX_HEIGHT CONTROL STR_SERIAL2, IDC_CHECK_SERIAL2, "Button", BS_AUTOCHECKBOX | WS_TABSTOP, - CFG_HMARGIN, 102, CFG_CHECKBOX_PRI_WIDTH, CFG_CHECKBOX_HEIGHT + CFG_HMARGIN, 86, CFG_CHECKBOX_PRI_WIDTH, CFG_CHECKBOX_HEIGHT CONTROL STR_SERIAL3, IDC_CHECK_SERIAL3, "Button", BS_AUTOCHECKBOX | WS_TABSTOP, - CFG_HMARGIN, 121, CFG_CHECKBOX_PRI_WIDTH, CFG_CHECKBOX_HEIGHT + CFG_HMARGIN, 101, CFG_CHECKBOX_PRI_WIDTH, CFG_CHECKBOX_HEIGHT CONTROL STR_SERIAL4, IDC_CHECK_SERIAL4, "Button", BS_AUTOCHECKBOX | WS_TABSTOP, - CFG_HMARGIN, 140, CFG_CHECKBOX_PRI_WIDTH, CFG_CHECKBOX_HEIGHT + CFG_HMARGIN, 116, CFG_CHECKBOX_PRI_WIDTH, CFG_CHECKBOX_HEIGHT CONTROL STR_PARALLEL1, IDC_CHECK_PARALLEL1, "Button", BS_AUTOCHECKBOX | WS_TABSTOP, - 167, 83, CFG_CHECKBOX_PRI_WIDTH, CFG_CHECKBOX_HEIGHT + 167, 71, CFG_CHECKBOX_PRI_WIDTH, CFG_CHECKBOX_HEIGHT CONTROL STR_PARALLEL2, IDC_CHECK_PARALLEL2, "Button", BS_AUTOCHECKBOX | WS_TABSTOP, - 167, 102, CFG_CHECKBOX_PRI_WIDTH, CFG_CHECKBOX_HEIGHT + 167, 86, CFG_CHECKBOX_PRI_WIDTH, CFG_CHECKBOX_HEIGHT CONTROL STR_PARALLEL3, IDC_CHECK_PARALLEL3, "Button", BS_AUTOCHECKBOX | WS_TABSTOP, - 167, 121, CFG_CHECKBOX_PRI_WIDTH, CFG_CHECKBOX_HEIGHT + 167, 101, CFG_CHECKBOX_PRI_WIDTH, CFG_CHECKBOX_HEIGHT CONTROL STR_PARALLEL4, IDC_CHECK_PARALLEL4, "Button", BS_AUTOCHECKBOX | WS_TABSTOP, - 167, 140, CFG_CHECKBOX_PRI_WIDTH, CFG_CHECKBOX_HEIGHT + 167, 116, CFG_CHECKBOX_PRI_WIDTH, CFG_CHECKBOX_HEIGHT + + CONTROL STR_SERIAL_PASS1, IDC_CHECK_SERIAL_PASS1, + "Button", BS_AUTOCHECKBOX | WS_TABSTOP, + CFG_HMARGIN, 134, CFG_CHECKBOX_PRI_WIDTH, CFG_CHECKBOX_HEIGHT + PUSHBUTTON STR_CONFIGURE, IDC_CONFIGURE_SERIAL_PASS1, + CFG_COMBO_BTN_LEFT, 131, CFG_BTN_WIDTH, CFG_BTN_HEIGHT + + CONTROL STR_SERIAL_PASS2, IDC_CHECK_SERIAL_PASS2, + "Button", BS_AUTOCHECKBOX | WS_TABSTOP, + CFG_HMARGIN, 150, CFG_CHECKBOX_PRI_WIDTH, CFG_CHECKBOX_HEIGHT + PUSHBUTTON STR_CONFIGURE, IDC_CONFIGURE_SERIAL_PASS2, + CFG_COMBO_BTN_LEFT, 147, CFG_BTN_WIDTH, CFG_BTN_HEIGHT + + CONTROL STR_SERIAL_PASS3, IDC_CHECK_SERIAL_PASS3, + "Button", BS_AUTOCHECKBOX | WS_TABSTOP, + CFG_HMARGIN, 165, CFG_CHECKBOX_PRI_WIDTH, CFG_CHECKBOX_HEIGHT + PUSHBUTTON STR_CONFIGURE, IDC_CONFIGURE_SERIAL_PASS3, + CFG_COMBO_BTN_LEFT, 162, CFG_BTN_WIDTH, CFG_BTN_HEIGHT + + CONTROL STR_SERIAL_PASS4, IDC_CHECK_SERIAL_PASS4, + "Button", BS_AUTOCHECKBOX | WS_TABSTOP, + CFG_HMARGIN, 180, CFG_CHECKBOX_PRI_WIDTH, CFG_CHECKBOX_HEIGHT + PUSHBUTTON STR_CONFIGURE, IDC_CONFIGURE_SERIAL_PASS4, + CFG_COMBO_BTN_LEFT, 177, CFG_BTN_WIDTH, CFG_BTN_HEIGHT END DLG_CFG_STORAGE DIALOG DISCARDABLE CFG_PANE_LEFT, CFG_PANE_TOP, CFG_PANE_WIDTH, CFG_PANE_HEIGHT @@ -555,22 +665,28 @@ BEGIN LTEXT STR_BUS,IDT_BUS, CFG_HMARGIN, 188, 24, CFG_PANE_LTEXT_HEIGHT COMBOBOX IDC_COMBO_HD_BUS, - 33, 186, 130, 12,CBS_DROPDOWNLIST | + 33, 186, 40, 12,CBS_DROPDOWNLIST | WS_VSCROLL | WS_TABSTOP LTEXT STR_CHANNEL, IDT_CHANNEL, - 181, 188, 38, CFG_PANE_LTEXT_HEIGHT + 91, 188, 38, CFG_PANE_LTEXT_HEIGHT COMBOBOX IDC_COMBO_HD_CHANNEL, - 221, 186, 140, 12, + 131, 186, 40, 12, CBS_DROPDOWNLIST | WS_VSCROLL | WS_TABSTOP COMBOBOX IDC_COMBO_HD_CHANNEL_IDE, - 221, 186, 140, 12, + 131, 186, 40, 12, CBS_DROPDOWNLIST | WS_VSCROLL | WS_TABSTOP LTEXT STR_ID, IDT_ID, - 181, 188, 38, CFG_PANE_LTEXT_HEIGHT + 91, 188, 38, CFG_PANE_LTEXT_HEIGHT COMBOBOX IDC_COMBO_HD_ID, - 221, 186, 140, 12, + 131, 186, 70, 12, + CBS_DROPDOWNLIST | WS_VSCROLL | WS_TABSTOP + + LTEXT STR_SPEED, IDT_SPEED, + 201, 188, 38, CFG_PANE_LTEXT_HEIGHT + COMBOBOX IDC_COMBO_HD_SPEED, + 241, 186, 70, 12, CBS_DROPDOWNLIST | WS_VSCROLL | WS_TABSTOP PUSHBUTTON STR_NEW, IDC_BUTTON_HDD_ADD_NEW, @@ -723,8 +839,15 @@ BEGIN LTEXT STR_CD_SPEED, IDT_CD_SPEED, CFG_HMARGIN, 207, 34, CFG_PANE_LTEXT_HEIGHT COMBOBOX IDC_COMBO_CD_SPEED, - 43, 205, 328, 12, + 33, 205, 140, 12, CBS_DROPDOWNLIST | WS_VSCROLL | WS_TABSTOP + + LTEXT STR_TYPE, IDT_CD_TYPE, + 181, 207, 34, CFG_PANE_LTEXT_HEIGHT + COMBOBOX IDC_COMBO_CD_TYPE, + 221, 205, 140, 12, + CBS_DROPDOWNLIST | WS_VSCROLL | WS_TABSTOP + END DLG_CFG_OTHER_REMOVABLE_DEVICES DIALOG DISCARDABLE CFG_PANE_LEFT, CFG_PANE_TOP, CFG_PANE_WIDTH, CFG_PANE_HEIGHT @@ -911,9 +1034,13 @@ END #undef STR_ENABLED_LOCAL #undef STR_ENABLED_UTC #undef STR_DYNAREC +#undef STR_SOFTFLOAT #undef STR_VIDEO +#undef STR_VIDEO_2 #undef STR_VOODOO +#undef STR_IBM8514 +#undef STR_XGA #undef STR_MOUSE #undef STR_JOYSTICK @@ -922,18 +1049,25 @@ END #undef STR_JOY3 #undef STR_JOY4 -#undef STR_SOUND +#undef STR_SOUND1 +#undef STR_SOUND2 +#undef STR_SOUND3 +#undef STR_SOUND4 #undef STR_MIDI_OUT #undef STR_MIDI_IN #undef STR_MPU401 -#undef STR_SSI -#undef STR_CMS -#undef STR_GUS #undef STR_FLOAT +#undef STR_FM_DRIVER +#undef STR_FM_DRV_NUKED +#undef STR_FM_DRV_YMFM #undef STR_NET_TYPE #undef STR_PCAP #undef STR_NET +#undef STR_NET1 +#undef STR_NET2 +#undef STR_NET3 +#undef STR_NET4 #undef STR_COM1 #undef STR_COM2 @@ -951,6 +1085,10 @@ END #undef STR_PARALLEL2 #undef STR_PARALLEL3 #undef STR_PARALLEL4 +#undef STR_SERIAL_PASS1 +#undef STR_SERIAL_PASS2 +#undef STR_SERIAL_PASS3 +#undef STR_SERIAL_PASS4 #undef STR_HDC #undef STR_FDC @@ -970,6 +1108,7 @@ END #undef STR_BUS #undef STR_CHANNEL #undef STR_ID +#undef STR_SPEED #undef STR_SPECIFY #undef STR_SECTORS @@ -985,6 +1124,7 @@ END #undef STR_CHECKBPB #undef STR_CDROM_DRIVES #undef STR_CD_SPEED +#undef STR_EARLY #undef STR_MO_DRIVES #undef STR_ZIP_DRIVES diff --git a/src/win/languages/en-GB.rc b/src/win/languages/en-GB.rc index ae2def0bd..01e18f71a 100644 --- a/src/win/languages/en-GB.rc +++ b/src/win/languages/en-GB.rc @@ -13,113 +13,122 @@ LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_UK // Menu // -MainMenu MENU DISCARDABLE +MainMenu MENU DISCARDABLE BEGIN POPUP "&Action" BEGIN - MENUITEM "&Keyboard requires capture", IDM_ACTION_KBD_REQ_CAPTURE - MENUITEM "&Right CTRL is left ALT", IDM_ACTION_RCTRL_IS_LALT + MENUITEM "&Keyboard requires capture", IDM_ACTION_KBD_REQ_CAPTURE + MENUITEM "&Right CTRL is left ALT", IDM_ACTION_RCTRL_IS_LALT MENUITEM SEPARATOR - MENUITEM "&Hard Reset...", IDM_ACTION_HRESET - MENUITEM "&Ctrl+Alt+Del\tCtrl+F12", IDM_ACTION_RESET_CAD + MENUITEM "&Hard Reset...", IDM_ACTION_HRESET + MENUITEM "&Ctrl+Alt+Del\tCtrl+F12", IDM_ACTION_RESET_CAD MENUITEM SEPARATOR - MENUITEM "Ctrl+Alt+&Esc", IDM_ACTION_CTRL_ALT_ESC + MENUITEM "Ctrl+Alt+&Esc", IDM_ACTION_CTRL_ALT_ESC MENUITEM SEPARATOR - MENUITEM "&Pause", IDM_ACTION_PAUSE + MENUITEM "&Pause", IDM_ACTION_PAUSE MENUITEM SEPARATOR - MENUITEM "E&xit...", IDM_ACTION_EXIT + MENUITEM "E&xit...", IDM_ACTION_EXIT END POPUP "&View" BEGIN - MENUITEM "&Hide status bar", IDM_VID_HIDE_STATUS_BAR - MENUITEM "Hide &toolbar", IDM_VID_HIDE_TOOLBAR + MENUITEM "&Hide status bar", IDM_VID_HIDE_STATUS_BAR + MENUITEM "Hide &toolbar", IDM_VID_HIDE_TOOLBAR MENUITEM SEPARATOR - MENUITEM "&Resizeable window", IDM_VID_RESIZE - MENUITEM "R&emember size && position", IDM_VID_REMEMBER + MENUITEM "&Show non-primary monitors", IDM_VID_MONITORS + MENUITEM "&Resizeable window", IDM_VID_RESIZE + MENUITEM "R&emember size && position", IDM_VID_REMEMBER MENUITEM SEPARATOR POPUP "Re&nderer" BEGIN - MENUITEM "&SDL (Software)", IDM_VID_SDL_SW - MENUITEM "SDL (&Hardware)", IDM_VID_SDL_HW - MENUITEM "SDL (&OpenGL)", IDM_VID_SDL_OPENGL - MENUITEM "Open&GL (3.0 Core)", IDM_VID_OPENGL_CORE + MENUITEM "&SDL (Software)", IDM_VID_SDL_SW + MENUITEM "SDL (&Hardware)", IDM_VID_SDL_HW + MENUITEM "SDL (&OpenGL)", IDM_VID_SDL_OPENGL + MENUITEM "Open&GL (3.0 Core)", IDM_VID_OPENGL_CORE #ifdef USE_VNC - MENUITEM "&VNC", IDM_VID_VNC + MENUITEM "&VNC", IDM_VID_VNC #endif END MENUITEM SEPARATOR - MENUITEM "Specify dimensions...", IDM_VID_SPECIFY_DIM - MENUITEM "F&orce 4:3 display ratio", IDM_VID_FORCE43 + MENUITEM "Specify dimensions...", IDM_VID_SPECIFY_DIM + MENUITEM "F&orce 4:3 display ratio", IDM_VID_FORCE43 POPUP "&Window scale factor" BEGIN - MENUITEM "&0.5x", IDM_VID_SCALE_1X - MENUITEM "&1x", IDM_VID_SCALE_2X - MENUITEM "1.&5x", IDM_VID_SCALE_3X - MENUITEM "&2x", IDM_VID_SCALE_4X + MENUITEM "&0.5x", IDM_VID_SCALE_1X + MENUITEM "&1x", IDM_VID_SCALE_2X + MENUITEM "1.&5x", IDM_VID_SCALE_3X + MENUITEM "&2x", IDM_VID_SCALE_4X + MENUITEM "&3x", IDM_VID_SCALE_5X + MENUITEM "&4x", IDM_VID_SCALE_6X + MENUITEM "&5x", IDM_VID_SCALE_7X + MENUITEM "&6x", IDM_VID_SCALE_8X + MENUITEM "&7x", IDM_VID_SCALE_9X + MENUITEM "&8x", IDM_VID_SCALE_10X END POPUP "Filter method" BEGIN - MENUITEM "&Nearest", IDM_VID_FILTER_NEAREST - MENUITEM "&Linear", IDM_VID_FILTER_LINEAR + MENUITEM "&Nearest", IDM_VID_FILTER_NEAREST + MENUITEM "&Linear", IDM_VID_FILTER_LINEAR END - MENUITEM "Hi&DPI scaling", IDM_VID_HIDPI + MENUITEM "Hi&DPI scaling", IDM_VID_HIDPI MENUITEM SEPARATOR - MENUITEM "&Fullscreen\tCtrl+Alt+PgUp", IDM_VID_FULLSCREEN + MENUITEM "&Fullscreen\tCtrl+Alt+PgUp", IDM_VID_FULLSCREEN POPUP "Fullscreen &stretch mode" BEGIN - MENUITEM "&Full screen stretch", IDM_VID_FS_FULL - MENUITEM "&4:3", IDM_VID_FS_43 + MENUITEM "&Full screen stretch", IDM_VID_FS_FULL + MENUITEM "&4:3", IDM_VID_FS_43 MENUITEM "&Square pixels (Keep ratio)", IDM_VID_FS_KEEPRATIO - MENUITEM "&Integer scale", IDM_VID_FS_INT + MENUITEM "&Integer scale", IDM_VID_FS_INT END POPUP "E&GA/(S)VGA settings" BEGIN - MENUITEM "&Inverted VGA monitor", IDM_VID_INVERT + MENUITEM "&Inverted VGA monitor", IDM_VID_INVERT POPUP "VGA screen &type" BEGIN - MENUITEM "RGB &Colour", IDM_VID_GRAY_RGB - MENUITEM "&RGB Greyscale", IDM_VID_GRAY_MONO - MENUITEM "&Amber monitor", IDM_VID_GRAY_AMBER - MENUITEM "&Green monitor", IDM_VID_GRAY_GREEN - MENUITEM "&White monitor", IDM_VID_GRAY_WHITE + MENUITEM "RGB &Colour", IDM_VID_GRAY_RGB + MENUITEM "&RGB Greyscale", IDM_VID_GRAY_MONO + MENUITEM "&Amber monitor", IDM_VID_GRAY_AMBER + MENUITEM "&Green monitor", IDM_VID_GRAY_GREEN + MENUITEM "&White monitor", IDM_VID_GRAY_WHITE END POPUP "Grayscale &conversion type" BEGIN - MENUITEM "BT&601 (NTSC/PAL)", IDM_VID_GRAYCT_601 - MENUITEM "BT&709 (HDTV)", IDM_VID_GRAYCT_709 - MENUITEM "&Average", IDM_VID_GRAYCT_AVE + MENUITEM "BT&601 (NTSC/PAL)", IDM_VID_GRAYCT_601 + MENUITEM "BT&709 (HDTV)", IDM_VID_GRAYCT_709 + MENUITEM "&Average", IDM_VID_GRAYCT_AVE END END MENUITEM SEPARATOR - MENUITEM "CGA/PCjr/Tandy/E&GA/(S)VGA overscan", IDM_VID_OVERSCAN + MENUITEM "CGA/PCjr/Tandy/E&GA/(S)VGA overscan", IDM_VID_OVERSCAN MENUITEM "Change contrast for &monochrome display", IDM_VID_CGACON END - MENUITEM "&Media", IDM_MEDIA + MENUITEM "&Media", IDM_MEDIA POPUP "&Tools" BEGIN - MENUITEM "&Settings...", IDM_CONFIG - MENUITEM "&Update status bar icons", IDM_UPDATE_ICONS + MENUITEM "&Settings...", IDM_CONFIG + MENUITEM "&Update status bar icons", IDM_UPDATE_ICONS MENUITEM SEPARATOR - MENUITEM "Take s&creenshot\tCtrl+F11", IDM_ACTION_SCREENSHOT + MENUITEM "Take s&creenshot\tCtrl+F11", IDM_ACTION_SCREENSHOT MENUITEM SEPARATOR - MENUITEM "&Preferences...", IDM_PREFERENCES + MENUITEM "&Preferences...", IDM_PREFERENCES +#ifdef DISCORD MENUITEM "Enable &Discord integration", IDM_DISCORD +#endif MENUITEM SEPARATOR - MENUITEM "Sound &gain...", IDM_SND_GAIN + MENUITEM "Sound &gain...", IDM_SND_GAIN #ifdef MTR_ENABLED MENUITEM SEPARATOR - MENUITEM "Begin trace\tCtrl+T", IDM_ACTION_BEGIN_TRACE - MENUITEM "End trace\tCtrl+T", IDM_ACTION_END_TRACE + MENUITEM "Begin trace\tCtrl+T", IDM_ACTION_BEGIN_TRACE + MENUITEM "End trace\tCtrl+T", IDM_ACTION_END_TRACE #endif END POPUP "&Help" BEGIN - MENUITEM "&Documentation...", IDM_DOCS - MENUITEM "&About 86Box...", IDM_ABOUT + MENUITEM "&Documentation...", IDM_DOCS + MENUITEM "&About 86Box...", IDM_ABOUT END END -StatusBarMenu MENU DISCARDABLE +StatusBarMenu MENU DISCARDABLE BEGIN MENUITEM SEPARATOR END @@ -128,17 +137,17 @@ CassetteSubmenu MENU DISCARDABLE BEGIN POPUP "" BEGIN - MENUITEM "&New image...", IDM_CASSETTE_IMAGE_NEW + MENUITEM "&New image...", IDM_CASSETTE_IMAGE_NEW MENUITEM SEPARATOR - MENUITEM "&Existing image...", IDM_CASSETTE_IMAGE_EXISTING - MENUITEM "Existing image (&Write-protected)...", IDM_CASSETTE_IMAGE_EXISTING_WP + MENUITEM "&Existing image...", IDM_CASSETTE_IMAGE_EXISTING + MENUITEM "Existing image (&Write-protected)...", IDM_CASSETTE_IMAGE_EXISTING_WP MENUITEM SEPARATOR - MENUITEM "&Record", IDM_CASSETTE_RECORD - MENUITEM "&Play", IDM_CASSETTE_PLAY - MENUITEM "&Rewind to the beginning", IDM_CASSETTE_REWIND - MENUITEM "&Fast forward to the end", IDM_CASSETTE_FAST_FORWARD + MENUITEM "&Record", IDM_CASSETTE_RECORD + MENUITEM "&Play", IDM_CASSETTE_PLAY + MENUITEM "&Rewind to the beginning", IDM_CASSETTE_REWIND + MENUITEM "&Fast forward to the end", IDM_CASSETTE_FAST_FORWARD MENUITEM SEPARATOR - MENUITEM "E&ject", IDM_CASSETTE_EJECT + MENUITEM "E&ject", IDM_CASSETTE_EJECT END END @@ -146,9 +155,9 @@ CartridgeSubmenu MENU DISCARDABLE BEGIN POPUP "" BEGIN - MENUITEM "&Image...", IDM_CARTRIDGE_IMAGE + MENUITEM "&Image...", IDM_CARTRIDGE_IMAGE MENUITEM SEPARATOR - MENUITEM "E&ject", IDM_CARTRIDGE_EJECT + MENUITEM "E&ject", IDM_CARTRIDGE_EJECT END END @@ -156,14 +165,14 @@ FloppySubmenu MENU DISCARDABLE BEGIN POPUP "" BEGIN - MENUITEM "&New image...", IDM_FLOPPY_IMAGE_NEW + MENUITEM "&New image...", IDM_FLOPPY_IMAGE_NEW MENUITEM SEPARATOR - MENUITEM "&Existing image...", IDM_FLOPPY_IMAGE_EXISTING - MENUITEM "Existing image (&Write-protected)...", IDM_FLOPPY_IMAGE_EXISTING_WP + MENUITEM "&Existing image...", IDM_FLOPPY_IMAGE_EXISTING + MENUITEM "Existing image (&Write-protected)...", IDM_FLOPPY_IMAGE_EXISTING_WP MENUITEM SEPARATOR - MENUITEM "E&xport to 86F...", IDM_FLOPPY_EXPORT_TO_86F + MENUITEM "E&xport to 86F...", IDM_FLOPPY_EXPORT_TO_86F MENUITEM SEPARATOR - MENUITEM "E&ject", IDM_FLOPPY_EJECT + MENUITEM "E&ject", IDM_FLOPPY_EJECT END END @@ -171,12 +180,13 @@ CdromSubmenu MENU DISCARDABLE BEGIN POPUP "" BEGIN - MENUITEM "&Mute", IDM_CDROM_MUTE + MENUITEM "&Mute", IDM_CDROM_MUTE MENUITEM SEPARATOR - MENUITEM "E&mpty", IDM_CDROM_EMPTY - MENUITEM "&Reload previous image", IDM_CDROM_RELOAD + MENUITEM "E&mpty", IDM_CDROM_EMPTY + MENUITEM "&Reload previous image", IDM_CDROM_RELOAD MENUITEM SEPARATOR - MENUITEM "&Image", IDM_CDROM_IMAGE + MENUITEM "&Image...", IDM_CDROM_IMAGE + MENUITEM "&Folder...", IDM_CDROM_DIR END END @@ -184,13 +194,13 @@ ZIPSubmenu MENU DISCARDABLE BEGIN POPUP "" BEGIN - MENUITEM "&New image...", IDM_ZIP_IMAGE_NEW + MENUITEM "&New image...", IDM_ZIP_IMAGE_NEW MENUITEM SEPARATOR - MENUITEM "&Existing image...", IDM_ZIP_IMAGE_EXISTING - MENUITEM "Existing image (&Write-protected)...", IDM_ZIP_IMAGE_EXISTING_WP + MENUITEM "&Existing image...", IDM_ZIP_IMAGE_EXISTING + MENUITEM "Existing image (&Write-protected)...", IDM_ZIP_IMAGE_EXISTING_WP MENUITEM SEPARATOR - MENUITEM "E&ject", IDM_ZIP_EJECT - MENUITEM "&Reload previous image", IDM_ZIP_RELOAD + MENUITEM "E&ject", IDM_ZIP_EJECT + MENUITEM "&Reload previous image", IDM_ZIP_RELOAD END END @@ -198,13 +208,13 @@ MOSubmenu MENU DISCARDABLE BEGIN POPUP "" BEGIN - MENUITEM "&New image...", IDM_MO_IMAGE_NEW + MENUITEM "&New image...", IDM_MO_IMAGE_NEW MENUITEM SEPARATOR - MENUITEM "&Existing image...", IDM_MO_IMAGE_EXISTING - MENUITEM "Existing image (&Write-protected)...", IDM_MO_IMAGE_EXISTING_WP + MENUITEM "&Existing image...", IDM_MO_IMAGE_EXISTING + MENUITEM "Existing image (&Write-protected)...", IDM_MO_IMAGE_EXISTING_WP MENUITEM SEPARATOR - MENUITEM "E&ject", IDM_MO_EJECT - MENUITEM "&Reload previous image", IDM_MO_RELOAD + MENUITEM "E&ject", IDM_MO_EJECT + MENUITEM "&Reload previous image", IDM_MO_RELOAD END END @@ -230,134 +240,150 @@ END // Dialog // -#define STR_PREFERENCES "Preferences" -#define STR_SND_GAIN "Sound Gain" -#define STR_NEW_FLOPPY "New Image" -#define STR_CONFIG "Settings" -#define STR_SPECIFY_DIM "Specify Main Window Dimensions" +#define STR_PREFERENCES "Preferences" +#define STR_SND_GAIN "Sound Gain" +#define STR_NEW_FLOPPY "New Image" +#define STR_CONFIG "Settings" +#define STR_SPECIFY_DIM "Specify Main Window Dimensions" -#define STR_OK "OK" -#define STR_CANCEL "Cancel" -#define STR_GLOBAL "Save these settings as &global defaults" -#define STR_DEFAULT "&Default" -#define STR_LANGUAGE "Language:" -#define STR_ICONSET "Icon set:" +#define STR_OK "OK" +#define STR_CANCEL "Cancel" +#define STR_GLOBAL "Save these settings as &global defaults" +#define STR_DEFAULT "&Default" +#define STR_LANGUAGE "Language:" +#define STR_ICONSET "Icon set:" -#define STR_GAIN "Gain" +#define STR_GAIN "Gain" -#define STR_FILE_NAME "File name:" -#define STR_DISK_SIZE "Disk size:" -#define STR_RPM_MODE "RPM mode:" -#define STR_PROGRESS "Progress:" +#define STR_FILE_NAME "File name:" +#define STR_DISK_SIZE "Disk size:" +#define STR_RPM_MODE "RPM mode:" +#define STR_PROGRESS "Progress:" -#define STR_WIDTH "Width:" -#define STR_HEIGHT "Height:" -#define STR_LOCK_TO_SIZE "Lock to this size" +#define STR_WIDTH "Width:" +#define STR_HEIGHT "Height:" +#define STR_LOCK_TO_SIZE "Lock to this size" -#define STR_MACHINE_TYPE "Machine type:" -#define STR_MACHINE "Machine:" -#define STR_CONFIGURE "Configure" -#define STR_CPU_TYPE "CPU type:" -#define STR_CPU_SPEED "Speed:" -#define STR_FPU "FPU:" -#define STR_WAIT_STATES "Wait states:" -#define STR_MB "MB" -#define STR_MEMORY "Memory:" -#define STR_TIME_SYNC "Time synchronization" -#define STR_DISABLED "Disabled" -#define STR_ENABLED_LOCAL "Enabled (local time)" -#define STR_ENABLED_UTC "Enabled (UTC)" -#define STR_DYNAREC "Dynamic Recompiler" +#define STR_MACHINE_TYPE "Machine type:" +#define STR_MACHINE "Machine:" +#define STR_CONFIGURE "Configure" +#define STR_CPU_TYPE "CPU type:" +#define STR_CPU_SPEED "Speed:" +#define STR_FPU "FPU:" +#define STR_WAIT_STATES "Wait states:" +#define STR_MB "MB" +#define STR_MEMORY "Memory:" +#define STR_TIME_SYNC "Time synchronization" +#define STR_DISABLED "Disabled" +#define STR_ENABLED_LOCAL "Enabled (local time)" +#define STR_ENABLED_UTC "Enabled (UTC)" +#define STR_DYNAREC "Dynamic Recompiler" +#define STR_SOFTFLOAT "Softfloat FPU" -#define STR_VIDEO "Video:" -#define STR_VOODOO "Voodoo Graphics" +#define STR_VIDEO "Video:" +#define STR_VIDEO_2 "Video 2:" +#define STR_VOODOO "Voodoo Graphics" +#define STR_IBM8514 "IBM 8514/a Graphics" +#define STR_XGA "XGA Graphics" -#define STR_MOUSE "Mouse:" -#define STR_JOYSTICK "Joystick:" -#define STR_JOY1 "Joystick 1..." -#define STR_JOY2 "Joystick 2..." -#define STR_JOY3 "Joystick 3..." -#define STR_JOY4 "Joystick 4..." +#define STR_MOUSE "Mouse:" +#define STR_JOYSTICK "Joystick:" +#define STR_JOY1 "Joystick 1..." +#define STR_JOY2 "Joystick 2..." +#define STR_JOY3 "Joystick 3..." +#define STR_JOY4 "Joystick 4..." -#define STR_SOUND "Sound card:" -#define STR_MIDI_OUT "MIDI Out Device:" -#define STR_MIDI_IN "MIDI In Device:" -#define STR_MPU401 "Standalone MPU-401" -#define STR_SSI "Innovation SSI-2001" -#define STR_CMS "CMS / Game Blaster" -#define STR_GUS "Gravis Ultrasound" -#define STR_FLOAT "Use FLOAT32 sound" +#define STR_SOUND1 "Sound card 1:" +#define STR_SOUND2 "Sound card 2:" +#define STR_SOUND3 "Sound card 3:" +#define STR_SOUND4 "Sound card 4:" +#define STR_MIDI_OUT "MIDI Out Device:" +#define STR_MIDI_IN "MIDI In Device:" +#define STR_MPU401 "Standalone MPU-401" +#define STR_FLOAT "Use FLOAT32 sound" +#define STR_FM_DRIVER "FM synth driver" +#define STR_FM_DRV_NUKED "Nuked (more accurate)" +#define STR_FM_DRV_YMFM "YMFM (faster)" -#define STR_NET_TYPE "Network type:" -#define STR_PCAP "PCap device:" -#define STR_NET "Network adapter:" +#define STR_NET_TYPE "Network type:" +#define STR_PCAP "PCap device:" +#define STR_NET "Network adapter:" +#define STR_NET1 "Network card 1:" +#define STR_NET2 "Network card 2:" +#define STR_NET3 "Network card 3:" +#define STR_NET4 "Network card 4:" -#define STR_COM1 "COM1 Device:" -#define STR_COM2 "COM2 Device:" -#define STR_COM3 "COM3 Device:" -#define STR_COM4 "COM4 Device:" -#define STR_LPT1 "LPT1 Device:" -#define STR_LPT2 "LPT2 Device:" -#define STR_LPT3 "LPT3 Device:" -#define STR_LPT4 "LPT4 Device:" -#define STR_SERIAL1 "Serial port 1" -#define STR_SERIAL2 "Serial port 2" -#define STR_SERIAL3 "Serial port 3" -#define STR_SERIAL4 "Serial port 4" -#define STR_PARALLEL1 "Parallel port 1" -#define STR_PARALLEL2 "Parallel port 2" -#define STR_PARALLEL3 "Parallel port 3" -#define STR_PARALLEL4 "Parallel port 4" +#define STR_COM1 "COM1 Device:" +#define STR_COM2 "COM2 Device:" +#define STR_COM3 "COM3 Device:" +#define STR_COM4 "COM4 Device:" +#define STR_LPT1 "LPT1 Device:" +#define STR_LPT2 "LPT2 Device:" +#define STR_LPT3 "LPT3 Device:" +#define STR_LPT4 "LPT4 Device:" +#define STR_SERIAL1 "Serial port 1" +#define STR_SERIAL2 "Serial port 2" +#define STR_SERIAL3 "Serial port 3" +#define STR_SERIAL4 "Serial port 4" +#define STR_PARALLEL1 "Parallel port 1" +#define STR_PARALLEL2 "Parallel port 2" +#define STR_PARALLEL3 "Parallel port 3" +#define STR_PARALLEL4 "Parallel port 4" +#define STR_SERIAL_PASS1 "Serial port passthrough 1" +#define STR_SERIAL_PASS2 "Serial port passthrough 2" +#define STR_SERIAL_PASS3 "Serial port passthrough 3" +#define STR_SERIAL_PASS4 "Serial port passthrough 4" -#define STR_HDC "HD Controller:" -#define STR_FDC "FD Controller:" -#define STR_IDE_TER "Tertiary IDE Controller" -#define STR_IDE_QUA "Quaternary IDE Controller" -#define STR_SCSI "SCSI" -#define STR_SCSI_1 "Controller 1:" -#define STR_SCSI_2 "Controller 2:" -#define STR_SCSI_3 "Controller 3:" -#define STR_SCSI_4 "Controller 4:" -#define STR_CASSETTE "Cassette" +#define STR_HDC "HD Controller:" +#define STR_FDC "FD Controller:" +#define STR_IDE_TER "Tertiary IDE Controller" +#define STR_IDE_QUA "Quaternary IDE Controller" +#define STR_SCSI "SCSI" +#define STR_SCSI_1 "Controller 1:" +#define STR_SCSI_2 "Controller 2:" +#define STR_SCSI_3 "Controller 3:" +#define STR_SCSI_4 "Controller 4:" +#define STR_CASSETTE "Cassette" -#define STR_HDD "Hard disks:" -#define STR_NEW "&New..." -#define STR_EXISTING "&Existing..." -#define STR_REMOVE "&Remove" -#define STR_BUS "Bus:" -#define STR_CHANNEL "Channel:" -#define STR_ID "ID:" +#define STR_HDD "Hard disks:" +#define STR_NEW "&New..." +#define STR_EXISTING "&Existing..." +#define STR_REMOVE "&Remove" +#define STR_BUS "Bus:" +#define STR_CHANNEL "Channel:" +#define STR_ID "ID:" +#define STR_SPEED "Speed:" -#define STR_SPECIFY "&Specify..." -#define STR_SECTORS "Sectors:" -#define STR_HEADS "Heads:" -#define STR_CYLS "Cylinders:" -#define STR_SIZE_MB "Size (MB):" -#define STR_TYPE "Type:" -#define STR_IMG_FORMAT "Image Format:" -#define STR_BLOCK_SIZE "Block Size:" +#define STR_SPECIFY "&Specify..." +#define STR_SECTORS "Sectors:" +#define STR_HEADS "Heads:" +#define STR_CYLS "Cylinders:" +#define STR_SIZE_MB "Size (MB):" +#define STR_TYPE "Type:" +#define STR_IMG_FORMAT "Image Format:" +#define STR_BLOCK_SIZE "Block Size:" -#define STR_FLOPPY_DRIVES "Floppy drives:" -#define STR_TURBO "Turbo timings" -#define STR_CHECKBPB "Check BPB" -#define STR_CDROM_DRIVES "CD-ROM drives:" -#define STR_CD_SPEED "Speed:" +#define STR_FLOPPY_DRIVES "Floppy drives:" +#define STR_TURBO "Turbo timings" +#define STR_CHECKBPB "Check BPB" +#define STR_CDROM_DRIVES "CD-ROM drives:" +#define STR_CD_SPEED "Speed:" -#define STR_MO_DRIVES "MO drives:" -#define STR_ZIP_DRIVES "ZIP drives:" -#define STR_250 "ZIP 250" +#define STR_MO_DRIVES "MO drives:" +#define STR_ZIP_DRIVES "ZIP drives:" +#define STR_250 "ZIP 250" -#define STR_ISARTC "ISA RTC:" -#define STR_ISAMEM "ISA Memory Expansion" -#define STR_ISAMEM_1 "Card 1:" -#define STR_ISAMEM_2 "Card 2:" -#define STR_ISAMEM_3 "Card 3:" -#define STR_ISAMEM_4 "Card 4:" -#define STR_BUGGER "ISABugger device" -#define STR_POSTCARD "POST card" +#define STR_ISARTC "ISA RTC:" +#define STR_ISAMEM "ISA Memory Expansion" +#define STR_ISAMEM_1 "Card 1:" +#define STR_ISAMEM_2 "Card 2:" +#define STR_ISAMEM_3 "Card 3:" +#define STR_ISAMEM_4 "Card 4:" +#define STR_BUGGER "ISABugger device" +#define STR_POSTCARD "POST card" -#define FONT_SIZE 9 -#define FONT_NAME "Segoe UI" +#define FONT_SIZE 9 +#define FONT_NAME "Segoe UI" #include "dialogs.rc" @@ -366,194 +392,188 @@ END // String Table // -STRINGTABLE DISCARDABLE +STRINGTABLE DISCARDABLE BEGIN - 2048 "86Box" - IDS_2049 "Error" - IDS_2050 "Fatal error" - IDS_2051 " - PAUSED" - IDS_2052 "Press Ctrl+Alt+PgDn to return to windowed mode." - IDS_2053 "Speed" - IDS_2054 "ZIP %03i %i (%s): %ls" - IDS_2055 "ZIP images (*.IM?;*.ZDI)\0*.IM?;*.ZDI\0" - IDS_2056 "86Box could not find any usable ROM images.\n\nPlease download a ROM set and extract it into the ""roms"" directory." - IDS_2057 "(empty)" - IDS_2058 "ZIP images (*.IM?;*.ZDI)\0*.IM?;*.ZDI\0All files (*.*)\0*.*\0" - IDS_2059 "Turbo" - IDS_2060 "On" - IDS_2061 "Off" - IDS_2062 "All images (*.86F;*.DSK;*.FLP;*.IM?;*.*FD?)\0*.86F;*.DSK;*.FLP;*.IM?;*.*FD?\0Basic sector images (*.DSK;*.FLP;*.IM?;*.*FD?)\0*.DSK;*.FLP;*.IM?;*.IMG;*.*FD?\0Surface images (*.86F)\0*.86F\0" - IDS_2063 "Machine ""%hs"" is not available due to missing ROMs in the roms/machines directory. Switching to an available machine." + 2048 "86Box" + IDS_2049 "Error" + IDS_2050 "Fatal error" + IDS_2051 " - PAUSED" + IDS_2052 "Press Ctrl+Alt+PgDn to return to windowed mode." + IDS_2053 "Speed" + IDS_2054 "ZIP %03i %i (%s): %ls" + IDS_2055 "ZIP images (*.IM?;*.ZDI)\0*.IM?;*.ZDI\0" + IDS_2056 "86Box could not find any usable ROM images.\n\nPlease download a ROM set and extract it into the ""roms"" directory." + IDS_2057 "(empty)" + IDS_2058 "ZIP images (*.IM?;*.ZDI)\0*.IM?;*.ZDI\0All files (*.*)\0*.*\0" + IDS_2059 "Turbo" + IDS_2060 "On" + IDS_2061 "Off" + IDS_2062 "All images (*.86F;*.DSK;*.FLP;*.IM?;*.*FD?)\0*.86F;*.DSK;*.FLP;*.IM?;*.*FD?\0Basic sector images (*.DSK;*.FLP;*.IM?;*.*FD?)\0*.DSK;*.FLP;*.IM?;*.IMG;*.*FD?\0Surface images (*.86F)\0*.86F\0" + IDS_2063 "Machine ""%hs"" is not available due to missing ROMs in the roms/machines directory. Switching to an available machine." END -STRINGTABLE DISCARDABLE +STRINGTABLE DISCARDABLE BEGIN - IDS_2064 "Video card ""%hs"" is not available due to missing ROMs in the roms/video directory. Switching to an available video card." - IDS_2065 "Machine" - IDS_2066 "Display" - IDS_2067 "Input devices" - IDS_2068 "Sound" - IDS_2069 "Network" - IDS_2070 "Ports (COM & LPT)" - IDS_2071 "Storage controllers" - IDS_2072 "Hard disks" - IDS_2073 "Floppy & CD-ROM drives" - IDS_2074 "Other removable devices" - IDS_2075 "Other peripherals" - IDS_2076 "Surface images (*.86F)\0*.86F\0" - IDS_2077 "Click to capture mouse" - IDS_2078 "Press F8+F12 to release mouse" - IDS_2079 "Press F8+F12 or middle button to release mouse" + IDS_2064 "Video card ""%hs"" is not available due to missing ROMs in the roms/video directory. Switching to an available video card." + IDS_2065 "Machine" + IDS_2066 "Display" + IDS_2067 "Input devices" + IDS_2068 "Sound" + IDS_2069 "Network" + IDS_2070 "Ports (COM & LPT)" + IDS_2071 "Storage controllers" + IDS_2072 "Hard disks" + IDS_2073 "Floppy & CD-ROM drives" + IDS_2074 "Other removable devices" + IDS_2075 "Other peripherals" + IDS_2076 "Surface images (*.86F)\0*.86F\0" + IDS_2077 "Click to capture mouse" + IDS_2078 "Press F8+F12 to release mouse" + IDS_2079 "Press F8+F12 or middle button to release mouse" END -STRINGTABLE DISCARDABLE +STRINGTABLE DISCARDABLE BEGIN - IDS_2080 "Unable to initialize FluidSynth" - IDS_2081 "Bus" - IDS_2082 "File" - IDS_2083 "C" - IDS_2084 "H" - IDS_2085 "S" - IDS_2086 "MB" - IDS_2087 "Check BPB" - IDS_2088 "KB" - IDS_2089 "Could not initialize the video renderer." - IDS_2090 "Default" - IDS_2091 "%i Wait state(s)" - IDS_2092 "Type" - IDS_2093 "Failed to set up PCap" - IDS_2094 "No PCap devices found" - IDS_2095 "Invalid PCap device" - IDS_2096 "Standard 2-button joystick(s)" - IDS_2097 "Standard 4-button joystick" - IDS_2098 "Standard 6-button joystick" - IDS_2099 "Standard 8-button joystick" - IDS_2100 "CH Flightstick Pro" - IDS_2101 "Microsoft SideWinder Pad" - IDS_2102 "Thrustmaster Flight Control System" - IDS_2103 "None" - IDS_2104 "Unable to load keyboard accelerators." - IDS_2105 "Unable to register raw input." - IDS_2106 "%u" - IDS_2107 "%u MB (CHS: %i, %i, %i)" - IDS_2108 "Floppy %i (%s): %ls" - IDS_2109 "All images (*.0??;*.1??;*.??0;*.86F;*.BIN;*.CQ?;*.D??;*.FLP;*.HDM;*.IM?;*.JSON;*.TD0;*.*FD?;*.MFM;*.XDF)\0*.0??;*.1??;*.??0;*.86F;*.BIN;*.CQ?;*.D??;*.FLP;*.HDM;*.IM?;*.JSON;*.TD0;*.*FD?;*.MFM;*.XDF\0Advanced sector images (*.IMD;*.JSON;*.TD0)\0*.IMD;*.JSON;*.TD0\0Basic sector images (*.0??;*.1??;*.??0;*.BIN;*.CQ?;*.D??;*.FLP;*.HDM;*.IM?;*.XDF;*.*FD?)\0*.0??;*.1??;*.??0;*.BIN;*.CQ?;*.D??;*.FLP;*.HDM;*.IM?;*.XDF;*.*FD?\0Flux images (*.FDI)\0*.FDI\0Surface images (*.86F;*.MFM)\0*.86F;*.MFM\0All files (*.*)\0*.*\0" - IDS_2110 "Unable to initialize FreeType" - IDS_2111 "Unable to initialize SDL, SDL2.dll is required" - IDS_2112 "Are you sure you want to hard reset the emulated machine?" - IDS_2113 "Are you sure you want to exit 86Box?" - IDS_2114 "Unable to initialize Ghostscript" - IDS_2115 "MO %i (%ls): %ls" - IDS_2116 "MO images (*.IM?;*.MDI)\0*.IM?;*.MDI\0All files (*.*)\0*.*\0" - IDS_2117 "Welcome to 86Box!" - IDS_2118 "Internal controller" - IDS_2119 "Exit" - IDS_2120 "No ROMs found" - IDS_2121 "Do you want to save the settings?" - IDS_2122 "This will hard reset the emulated machine." - IDS_2123 "Save" - IDS_2124 "About 86Box" - IDS_2125 "86Box v" EMU_VERSION + IDS_2081 "Bus" + IDS_2082 "File" + IDS_2083 "C" + IDS_2084 "H" + IDS_2085 "S" + IDS_2086 "MB" + IDS_2087 "Speed" + IDS_2088 "Check BPB" + IDS_2089 "KB" + IDS_2090 "Could not initialize the video renderer." + IDS_2091 "Default" + IDS_2092 "%i Wait state(s)" + IDS_2093 "Type" + IDS_2094 "Failed to set up PCap" + IDS_2095 "No PCap devices found" + IDS_2096 "Invalid PCap device" + IDS_2097 "Standard 2-button joystick(s)" + IDS_2098 "Standard 4-button joystick" + IDS_2099 "Standard 6-button joystick" + IDS_2100 "Standard 8-button joystick" + IDS_2101 "CH Flightstick Pro" + IDS_2102 "Microsoft SideWinder Pad" + IDS_2103 "Thrustmaster Flight Control System" + IDS_2104 "None" + IDS_2105 "Unable to load keyboard accelerators." + IDS_2106 "Unable to register raw input." + IDS_2107 "%u" + IDS_2108 "%u MB (CHS: %i, %i, %i)" + IDS_2109 "Floppy %i (%s): %ls" + IDS_2110 "All images (*.0??;*.1??;*.??0;*.86F;*.BIN;*.CQ?;*.D??;*.FLP;*.HDM;*.IM?;*.JSON;*.TD0;*.*FD?;*.MFM;*.XDF)\0*.0??;*.1??;*.??0;*.86F;*.BIN;*.CQ?;*.D??;*.FLP;*.HDM;*.IM?;*.JSON;*.TD0;*.*FD?;*.MFM;*.XDF\0Advanced sector images (*.IMD;*.JSON;*.TD0)\0*.IMD;*.JSON;*.TD0\0Basic sector images (*.0??;*.1??;*.??0;*.BIN;*.CQ?;*.D??;*.FLP;*.HDM;*.IM?;*.XDF;*.*FD?)\0*.0??;*.1??;*.??0;*.BIN;*.CQ?;*.D??;*.FLP;*.HDM;*.IM?;*.XDF;*.*FD?\0Flux images (*.FDI)\0*.FDI\0Surface images (*.86F;*.MFM)\0*.86F;*.MFM\0All files (*.*)\0*.*\0" + IDS_2112 "Unable to initialize SDL, SDL2.dll is required" + IDS_2113 "Are you sure you want to hard reset the emulated machine?" + IDS_2114 "Are you sure you want to exit 86Box?" + IDS_2115 "Unable to initialize Ghostscript" + IDS_2116 "MO %i (%ls): %ls" + IDS_2117 "MO images (*.IM?;*.MDI)\0*.IM?;*.MDI\0All files (*.*)\0*.*\0" + IDS_2118 "Welcome to 86Box!" + IDS_2119 "Internal controller" + IDS_2120 "Exit" + IDS_2121 "No ROMs found" + IDS_2122 "Do you want to save the settings?" + IDS_2123 "This will hard reset the emulated machine." + IDS_2124 "Save" + IDS_2125 "About 86Box" + IDS_2126 "86Box v" EMU_VERSION - IDS_2126 "An emulator of old computers\n\nAuthors: Sarah Walker, Miran Grca, Fred N. van Kempen (waltje), SA1988, Tiseno100, reenigne, leilei, JohnElliott, greatpsycho, and others.\n\nReleased under the GNU General Public License version 2 or later. See LICENSE for more information." - IDS_2127 "OK" - IDS_2128 "Hardware not available" + IDS_2127 "An emulator of old computers\n\nAuthors: Miran GrÄa (OBattler), RichardG867, Jasmine Iwanek, TC1995, coldbrewed, Teemu Korhonen (Manaatti), Joakim L. Gilje, Adrien Moulin (elyosh), Daniel Balsom (gloriouscow), Cacodemon345, Fred N. van Kempen (waltje), Tiseno100, reenigne, and others.\n\nWith previous core contributions from Sarah Walker, leilei, JohnElliott, greatpsycho, and others.\n\nReleased under the GNU General Public License version 2 or later. See LICENSE for more information." + IDS_2128 "OK" + IDS_2129 "Hardware not available" #ifdef _WIN32 #define LIB_NAME_PCAP "WinPcap" #else #define LIB_NAME_PCAP "libpcap" #endif - IDS_2129 "Make sure " LIB_NAME_PCAP " is installed and that you are on a " LIB_NAME_PCAP "-compatible network connection." - IDS_2130 "Invalid configuration" -#ifdef _WIN32 -#define LIB_NAME_FREETYPE "freetype.dll" -#else -#define LIB_NAME_FREETYPE "libfreetype" -#endif - IDS_2131 LIB_NAME_FREETYPE " is required for ESC/P printer emulation." + IDS_2130 "Make sure " LIB_NAME_PCAP " is installed and that you are on a " LIB_NAME_PCAP "-compatible network connection." + IDS_2131 "Invalid configuration" #ifdef _WIN32 #define LIB_NAME_GS "gsdll32.dll" #else #define LIB_NAME_GS "libgs" #endif - IDS_2132 LIB_NAME_GS " is required for automatic conversion of PostScript files to PDF.\n\nAny documents sent to the generic PostScript printer will be saved as PostScript (.ps) files." -#ifdef _WIN32 -#define LIB_NAME_FLUIDSYNTH "libfluidsynth.dll" -#else -#define LIB_NAME_FLUIDSYNTH "libfluidsynth" -#endif - IDS_2133 LIB_NAME_FLUIDSYNTH " is required for FluidSynth MIDI output." - IDS_2134 "Entering fullscreen mode" - IDS_2135 "Don't show this message again" - IDS_2136 "Don't exit" - IDS_2137 "Reset" - IDS_2138 "Don't reset" - IDS_2139 "MO images (*.IM?;*.MDI)\0*.IM?;*.MDI\0All files (*.*)\0*.*\0" - IDS_2140 "CD-ROM images (*.ISO;*.CUE)\0*.ISO;*.CUE\0All files (*.*)\0*.*\0" - IDS_2141 "%hs Device Configuration" - IDS_2142 "Monitor in sleep mode" - IDS_2143 "OpenGL Shaders (*.GLSL)\0*.GLSL\0All files (*.*)\0*.*\0" - IDS_2144 "OpenGL options" - IDS_2145 "You are loading an unsupported configuration" - IDS_2146 "CPU type filtering based on selected machine is disabled for this emulated machine.\n\nThis makes it possible to choose a CPU that is otherwise incompatible with the selected machine. However, you may run into incompatibilities with the machine BIOS or other software.\n\nEnabling this setting is not officially supported and any bug reports filed may be closed as invalid." - IDS_2147 "Continue" - IDS_2148 "Cassette: %s" - IDS_2149 "Cassette images (*.PCM;*.RAW;*.WAV;*.CAS)\0*.PCM;*.RAW;*.WAV;*.CAS\0All files (*.*)\0*.*\0" - IDS_2150 "Cartridge %i: %ls" - IDS_2151 "Cartridge images (*.A;*.B;*.JRC)\0*.A;*.B;*.JRC\0All files (*.*)\0*.*\0" - IDS_2152 "Error initializing renderer" - IDS_2153 "OpenGL (3.0 Core) renderer could not be initialized. Use another renderer." - IDS_2154 "Resume execution" - IDS_2155 "Pause execution" - IDS_2156 "Press Ctrl+Alt+Del" - IDS_2157 "Press Ctrl+Alt+Esc" - IDS_2158 "Hard reset" - IDS_2159 "ACPI shutdown" - IDS_2160 "Settings" + IDS_2133 LIB_NAME_GS " is required for automatic conversion of PostScript files to PDF.\n\nAny documents sent to the generic PostScript printer will be saved as PostScript (.ps) files." + IDS_2135 "Entering fullscreen mode" + IDS_2136 "Don't show this message again" + IDS_2137 "Don't exit" + IDS_2138 "Reset" + IDS_2139 "Don't reset" + IDS_2140 "MO images (*.IM?;*.MDI)\0*.IM?;*.MDI\0All files (*.*)\0*.*\0" + IDS_2141 "CD-ROM images (*.ISO;*.CUE)\0*.ISO;*.CUE\0All files (*.*)\0*.*\0" + IDS_2142 "%hs Device Configuration" + IDS_2143 "Monitor in sleep mode" + IDS_2144 "OpenGL Shaders (*.GLSL)\0*.GLSL\0All files (*.*)\0*.*\0" + IDS_2145 "OpenGL options" + IDS_2146 "You are loading an unsupported configuration" + IDS_2147 "CPU type filtering based on selected machine is disabled for this emulated machine.\n\nThis makes it possible to choose a CPU that is otherwise incompatible with the selected machine. However, you may run into incompatibilities with the machine BIOS or other software.\n\nEnabling this setting is not officially supported and any bug reports filed may be closed as invalid." + IDS_2148 "Continue" + IDS_2149 "Cassette: %s" + IDS_2150 "Cassette images (*.PCM;*.RAW;*.WAV;*.CAS)\0*.PCM;*.RAW;*.WAV;*.CAS\0All files (*.*)\0*.*\0" + IDS_2151 "Cartridge %i: %ls" + IDS_2152 "Cartridge images (*.A;*.B;*.JRC)\0*.A;*.B;*.JRC\0All files (*.*)\0*.*\0" + IDS_2153 "Error initializing renderer" + IDS_2154 "OpenGL (3.0 Core) renderer could not be initialized. Use another renderer." + IDS_2155 "Resume execution" + IDS_2156 "Pause execution" + IDS_2157 "Press Ctrl+Alt+Del" + IDS_2158 "Press Ctrl+Alt+Esc" + IDS_2159 "Hard reset" + IDS_2160 "ACPI shutdown" + IDS_2161 "Settings" + IDS_2162 "Type" + IDS_2163 "No Dynarec" + IDS_2164 "Old Dynarec" + IDS_2165 "New Dynarec" + IDS_2166 "Video card #2 ""%hs"" is not available due to missing ROMs in the roms/video directory. Disabling the second video card." + IDS_2167 "Failed to initialize network driver" + IDS_2168 "The network configuration will be switched to the null driver" END -STRINGTABLE DISCARDABLE +STRINGTABLE DISCARDABLE BEGIN IDS_4096 "Hard disk (%s)" - IDS_4097 "%01i:%01i" - IDS_4098 "%01i" - IDS_4099 "MFM/RLL or ESDI CD-ROM drives never existed" - IDS_4100 "Custom..." - IDS_4101 "Custom (large)..." - IDS_4102 "Add New Hard Disk" - IDS_4103 "Add Existing Hard Disk" - IDS_4104 "HDI disk images cannot be larger than 4 GB." - IDS_4105 "Disk images cannot be larger than 127 GB." - IDS_4106 "Hard disk images (*.HD?;*.IM?;*.VHD)\0*.HD?;*.IM?;*.VHD\0All files (*.*)\0*.*\0" - IDS_4107 "Unable to read file" - IDS_4108 "Unable to write file" - IDS_4109 "HDI or HDX images with a sector size other than 512 are not supported." - IDS_4110 "USB is not yet supported" - IDS_4111 "Disk image file already exists" - IDS_4112 "Please specify a valid file name." - IDS_4113 "Disk image created" - IDS_4114 "Make sure the file exists and is readable." - IDS_4115 "Make sure the file is being saved to a writable directory." - IDS_4116 "Disk image too large" - IDS_4117 "Remember to partition and format the newly-created drive." - IDS_4118 "The selected file will be overwritten. Are you sure you want to use it?" - IDS_4119 "Unsupported disk image" - IDS_4120 "Overwrite" - IDS_4121 "Don't overwrite" - IDS_4122 "Raw image (.img)" - IDS_4123 "HDI image (.hdi)" - IDS_4124 "HDX image (.hdx)" - IDS_4125 "Fixed-size VHD (.vhd)" - IDS_4126 "Dynamic-size VHD (.vhd)" - IDS_4127 "Differencing VHD (.vhd)" - IDS_4128 "Large blocks (2 MB)" - IDS_4129 "Small blocks (512 KB)" - IDS_4130 "VHD files (*.VHD)\0*.VHD\0All files (*.*)\0*.*\0" - IDS_4131 "Select the parent VHD" - IDS_4132 "This could mean that the parent image was modified after the differencing image was created.\n\nIt can also happen if the image files were moved or copied, or by a bug in the program that created this disk.\n\nDo you want to fix the timestamps?" - IDS_4133 "Parent and child disk timestamps do not match" - IDS_4134 "Could not fix VHD timestamp." - IDS_4135 "%01i:%02i" + IDS_4097 "%01i:%01i" + IDS_4098 "%01i" + IDS_4099 "MFM/RLL or ESDI CD-ROM drives never existed" + IDS_4100 "Custom..." + IDS_4101 "Custom (large)..." + IDS_4102 "Add New Hard Disk" + IDS_4103 "Add Existing Hard Disk" + IDS_4104 "HDI disk images cannot be larger than 4 GB." + IDS_4105 "Disk images cannot be larger than 127 GB." + IDS_4106 "Hard disk images (*.HD?;*.IM?;*.VHD)\0*.HD?;*.IM?;*.VHD\0All files (*.*)\0*.*\0" + IDS_4107 "Unable to read file" + IDS_4108 "Unable to write file" + IDS_4109 "HDI or HDX images with a sector size other than 512 are not supported." + IDS_4110 "USB is not yet supported" + IDS_4111 "Disk image file already exists" + IDS_4112 "Please specify a valid file name." + IDS_4113 "Disk image created" + IDS_4114 "Make sure the file exists and is readable." + IDS_4115 "Make sure the file is being saved to a writable directory." + IDS_4116 "Disk image too large" + IDS_4117 "Remember to partition and format the newly-created drive." + IDS_4118 "The selected file will be overwritten. Are you sure you want to use it?" + IDS_4119 "Unsupported disk image" + IDS_4120 "Overwrite" + IDS_4121 "Don't overwrite" + IDS_4122 "Raw image (.img)" + IDS_4123 "HDI image (.hdi)" + IDS_4124 "HDX image (.hdx)" + IDS_4125 "Fixed-size VHD (.vhd)" + IDS_4126 "Dynamic-size VHD (.vhd)" + IDS_4127 "Differencing VHD (.vhd)" + IDS_4128 "Large blocks (2 MB)" + IDS_4129 "Small blocks (512 KB)" + IDS_4130 "VHD files (*.VHD)\0*.VHD\0All files (*.*)\0*.*\0" + IDS_4131 "Select the parent VHD" + IDS_4132 "This could mean that the parent image was modified after the differencing image was created.\n\nIt can also happen if the image files were moved or copied, or by a bug in the program that created this disk.\n\nDo you want to fix the timestamps?" + IDS_4133 "Parent and child disk timestamps do not match" + IDS_4134 "Could not fix VHD timestamp." + IDS_4135 "%01i:%02i" IDS_4352 "MFM/RLL" IDS_4353 "XTA" @@ -562,56 +582,56 @@ BEGIN IDS_4356 "ATAPI" IDS_4357 "SCSI" - IDS_4608 "MFM/RLL (%01i:%01i)" - IDS_4609 "XTA (%01i:%01i)" - IDS_4610 "ESDI (%01i:%01i)" - IDS_4611 "IDE (%01i:%01i)" - IDS_4612 "ATAPI (%01i:%01i)" - IDS_4613 "SCSI (%01i:%02i)" + IDS_4608 "MFM/RLL (%01i:%01i)" + IDS_4609 "XTA (%01i:%01i)" + IDS_4610 "ESDI (%01i:%01i)" + IDS_4611 "IDE (%01i:%01i)" + IDS_4612 "ATAPI (%01i:%01i)" + IDS_4613 "SCSI (%01i:%02i)" - IDS_5120 "CD-ROM %i (%s): %s" + IDS_5120 "CD-ROM %i (%s): %s" - IDS_5376 "Disabled" - IDS_5381 "ATAPI" + IDS_5376 "Disabled" + IDS_5381 "ATAPI" IDS_5382 "SCSI" - IDS_5632 "Disabled" - IDS_5637 "ATAPI (%01i:%01i)" + IDS_5632 "Disabled" + IDS_5637 "ATAPI (%01i:%01i)" IDS_5638 "SCSI (%01i:%02i)" - IDS_5888 "160 kB" - IDS_5889 "180 kB" - IDS_5890 "320 kB" - IDS_5891 "360 kB" - IDS_5892 "640 kB" - IDS_5893 "720 kB" - IDS_5894 "1.2 MB" - IDS_5895 "1.25 MB" - IDS_5896 "1.44 MB" - IDS_5897 "DMF (cluster 1024)" - IDS_5898 "DMF (cluster 2048)" - IDS_5899 "2.88 MB" - IDS_5900 "ZIP 100" - IDS_5901 "ZIP 250" - IDS_5902 "3.5"" 128 MB (ISO 10090)" - IDS_5903 "3.5"" 230 MB (ISO 13963)" - IDS_5904 "3.5"" 540 MB (ISO 15498)" - IDS_5905 "3.5"" 640 MB (ISO 15498)" - IDS_5906 "3.5"" 1.3 GB (GigaMO)" - IDS_5907 "3.5"" 2.3 GB (GigaMO 2)" - IDS_5908 "5.25"" 600 MB" - IDS_5909 "5.25"" 650 MB" - IDS_5910 "5.25"" 1 GB" - IDS_5911 "5.25"" 1.3 GB" + IDS_5888 "160 kB" + IDS_5889 "180 kB" + IDS_5890 "320 kB" + IDS_5891 "360 kB" + IDS_5892 "640 kB" + IDS_5893 "720 kB" + IDS_5894 "1.2 MB" + IDS_5895 "1.25 MB" + IDS_5896 "1.44 MB" + IDS_5897 "DMF (cluster 1024)" + IDS_5898 "DMF (cluster 2048)" + IDS_5899 "2.88 MB" + IDS_5900 "ZIP 100" + IDS_5901 "ZIP 250" + IDS_5902 "3.5"" 128 MB (ISO 10090)" + IDS_5903 "3.5"" 230 MB (ISO 13963)" + IDS_5904 "3.5"" 540 MB (ISO 15498)" + IDS_5905 "3.5"" 640 MB (ISO 15498)" + IDS_5906 "3.5"" 1.3 GB (GigaMO)" + IDS_5907 "3.5"" 2.3 GB (GigaMO 2)" + IDS_5908 "5.25"" 600 MB" + IDS_5909 "5.25"" 650 MB" + IDS_5910 "5.25"" 1 GB" + IDS_5911 "5.25"" 1.3 GB" - IDS_6144 "Perfect RPM" - IDS_6145 "1% below perfect RPM" - IDS_6146 "1.5% below perfect RPM" - IDS_6147 "2% below perfect RPM" + IDS_6144 "Perfect RPM" + IDS_6145 "1% below perfect RPM" + IDS_6146 "1.5% below perfect RPM" + IDS_6147 "2% below perfect RPM" - IDS_7168 "(System Default)" + IDS_7168 "(System Default)" END -#define IDS_LANG_ENUS IDS_7168 +#define IDS_LANG_ENUS IDS_7168 // English (U.K.) resources ///////////////////////////////////////////////////////////////////////////// diff --git a/src/win/languages/en-US.rc b/src/win/languages/en-US.rc index 12afe10ce..6ca6945d6 100644 --- a/src/win/languages/en-US.rc +++ b/src/win/languages/en-US.rc @@ -13,113 +13,122 @@ LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US // Menu // -MainMenu MENU DISCARDABLE +MainMenu MENU DISCARDABLE BEGIN POPUP "&Action" BEGIN - MENUITEM "&Keyboard requires capture", IDM_ACTION_KBD_REQ_CAPTURE - MENUITEM "&Right CTRL is left ALT", IDM_ACTION_RCTRL_IS_LALT + MENUITEM "&Keyboard requires capture", IDM_ACTION_KBD_REQ_CAPTURE + MENUITEM "&Right CTRL is left ALT", IDM_ACTION_RCTRL_IS_LALT MENUITEM SEPARATOR - MENUITEM "&Hard Reset...", IDM_ACTION_HRESET - MENUITEM "&Ctrl+Alt+Del\tCtrl+F12", IDM_ACTION_RESET_CAD + MENUITEM "&Hard Reset...", IDM_ACTION_HRESET + MENUITEM "&Ctrl+Alt+Del\tCtrl+F12", IDM_ACTION_RESET_CAD MENUITEM SEPARATOR - MENUITEM "Ctrl+Alt+&Esc", IDM_ACTION_CTRL_ALT_ESC + MENUITEM "Ctrl+Alt+&Esc", IDM_ACTION_CTRL_ALT_ESC MENUITEM SEPARATOR - MENUITEM "&Pause", IDM_ACTION_PAUSE + MENUITEM "&Pause", IDM_ACTION_PAUSE MENUITEM SEPARATOR - MENUITEM "E&xit...", IDM_ACTION_EXIT + MENUITEM "E&xit...", IDM_ACTION_EXIT END POPUP "&View" BEGIN - MENUITEM "&Hide status bar", IDM_VID_HIDE_STATUS_BAR - MENUITEM "Hide &toolbar", IDM_VID_HIDE_TOOLBAR + MENUITEM "&Hide status bar", IDM_VID_HIDE_STATUS_BAR + MENUITEM "Hide &toolbar", IDM_VID_HIDE_TOOLBAR MENUITEM SEPARATOR - MENUITEM "&Resizeable window", IDM_VID_RESIZE - MENUITEM "R&emember size && position", IDM_VID_REMEMBER + MENUITEM "&Show non-primary monitors", IDM_VID_MONITORS + MENUITEM "&Resizeable window", IDM_VID_RESIZE + MENUITEM "R&emember size && position", IDM_VID_REMEMBER MENUITEM SEPARATOR POPUP "Re&nderer" BEGIN - MENUITEM "&SDL (Software)", IDM_VID_SDL_SW - MENUITEM "SDL (&Hardware)", IDM_VID_SDL_HW - MENUITEM "SDL (&OpenGL)", IDM_VID_SDL_OPENGL - MENUITEM "Open&GL (3.0 Core)", IDM_VID_OPENGL_CORE + MENUITEM "&SDL (Software)", IDM_VID_SDL_SW + MENUITEM "SDL (&Hardware)", IDM_VID_SDL_HW + MENUITEM "SDL (&OpenGL)", IDM_VID_SDL_OPENGL + MENUITEM "Open&GL (3.0 Core)", IDM_VID_OPENGL_CORE #ifdef USE_VNC - MENUITEM "&VNC", IDM_VID_VNC + MENUITEM "&VNC", IDM_VID_VNC #endif END MENUITEM SEPARATOR - MENUITEM "Specify dimensions...", IDM_VID_SPECIFY_DIM - MENUITEM "F&orce 4:3 display ratio", IDM_VID_FORCE43 + MENUITEM "Specify dimensions...", IDM_VID_SPECIFY_DIM + MENUITEM "F&orce 4:3 display ratio", IDM_VID_FORCE43 POPUP "&Window scale factor" BEGIN - MENUITEM "&0.5x", IDM_VID_SCALE_1X - MENUITEM "&1x", IDM_VID_SCALE_2X - MENUITEM "1.&5x", IDM_VID_SCALE_3X - MENUITEM "&2x", IDM_VID_SCALE_4X + MENUITEM "&0.5x", IDM_VID_SCALE_1X + MENUITEM "&1x", IDM_VID_SCALE_2X + MENUITEM "1.&5x", IDM_VID_SCALE_3X + MENUITEM "&2x", IDM_VID_SCALE_4X + MENUITEM "&3x", IDM_VID_SCALE_5X + MENUITEM "&4x", IDM_VID_SCALE_6X + MENUITEM "&5x", IDM_VID_SCALE_7X + MENUITEM "&6x", IDM_VID_SCALE_8X + MENUITEM "&7x", IDM_VID_SCALE_9X + MENUITEM "&8x", IDM_VID_SCALE_10X END POPUP "Filter method" BEGIN - MENUITEM "&Nearest", IDM_VID_FILTER_NEAREST - MENUITEM "&Linear", IDM_VID_FILTER_LINEAR + MENUITEM "&Nearest", IDM_VID_FILTER_NEAREST + MENUITEM "&Linear", IDM_VID_FILTER_LINEAR END - MENUITEM "Hi&DPI scaling", IDM_VID_HIDPI + MENUITEM "Hi&DPI scaling", IDM_VID_HIDPI MENUITEM SEPARATOR - MENUITEM "&Fullscreen\tCtrl+Alt+PgUp", IDM_VID_FULLSCREEN + MENUITEM "&Fullscreen\tCtrl+Alt+PgUp", IDM_VID_FULLSCREEN POPUP "Fullscreen &stretch mode" BEGIN - MENUITEM "&Full screen stretch", IDM_VID_FS_FULL - MENUITEM "&4:3", IDM_VID_FS_43 + MENUITEM "&Full screen stretch", IDM_VID_FS_FULL + MENUITEM "&4:3", IDM_VID_FS_43 MENUITEM "&Square pixels (Keep ratio)", IDM_VID_FS_KEEPRATIO - MENUITEM "&Integer scale", IDM_VID_FS_INT + MENUITEM "&Integer scale", IDM_VID_FS_INT END POPUP "E&GA/(S)VGA settings" BEGIN - MENUITEM "&Inverted VGA monitor", IDM_VID_INVERT + MENUITEM "&Inverted VGA monitor", IDM_VID_INVERT POPUP "VGA screen &type" BEGIN - MENUITEM "RGB &Color", IDM_VID_GRAY_RGB - MENUITEM "&RGB Grayscale", IDM_VID_GRAY_MONO - MENUITEM "&Amber monitor", IDM_VID_GRAY_AMBER - MENUITEM "&Green monitor", IDM_VID_GRAY_GREEN - MENUITEM "&White monitor", IDM_VID_GRAY_WHITE + MENUITEM "RGB &Color", IDM_VID_GRAY_RGB + MENUITEM "&RGB Grayscale", IDM_VID_GRAY_MONO + MENUITEM "&Amber monitor", IDM_VID_GRAY_AMBER + MENUITEM "&Green monitor", IDM_VID_GRAY_GREEN + MENUITEM "&White monitor", IDM_VID_GRAY_WHITE END POPUP "Grayscale &conversion type" BEGIN - MENUITEM "BT&601 (NTSC/PAL)", IDM_VID_GRAYCT_601 - MENUITEM "BT&709 (HDTV)", IDM_VID_GRAYCT_709 - MENUITEM "&Average", IDM_VID_GRAYCT_AVE + MENUITEM "BT&601 (NTSC/PAL)", IDM_VID_GRAYCT_601 + MENUITEM "BT&709 (HDTV)", IDM_VID_GRAYCT_709 + MENUITEM "&Average", IDM_VID_GRAYCT_AVE END END MENUITEM SEPARATOR - MENUITEM "CGA/PCjr/Tandy/E&GA/(S)VGA overscan", IDM_VID_OVERSCAN + MENUITEM "CGA/PCjr/Tandy/E&GA/(S)VGA overscan", IDM_VID_OVERSCAN MENUITEM "Change contrast for &monochrome display", IDM_VID_CGACON END - MENUITEM "&Media", IDM_MEDIA + MENUITEM "&Media", IDM_MEDIA POPUP "&Tools" BEGIN - MENUITEM "&Settings...", IDM_CONFIG - MENUITEM "&Update status bar icons", IDM_UPDATE_ICONS + MENUITEM "&Settings...", IDM_CONFIG + MENUITEM "&Update status bar icons", IDM_UPDATE_ICONS MENUITEM SEPARATOR - MENUITEM "Take s&creenshot\tCtrl+F11", IDM_ACTION_SCREENSHOT + MENUITEM "Take s&creenshot\tCtrl+F11", IDM_ACTION_SCREENSHOT MENUITEM SEPARATOR - MENUITEM "&Preferences...", IDM_PREFERENCES + MENUITEM "&Preferences...", IDM_PREFERENCES +#ifdef DISCORD MENUITEM "Enable &Discord integration", IDM_DISCORD +#endif MENUITEM SEPARATOR - MENUITEM "Sound &gain...", IDM_SND_GAIN + MENUITEM "Sound &gain...", IDM_SND_GAIN #ifdef MTR_ENABLED MENUITEM SEPARATOR - MENUITEM "Begin trace\tCtrl+T", IDM_ACTION_BEGIN_TRACE - MENUITEM "End trace\tCtrl+T", IDM_ACTION_END_TRACE + MENUITEM "Begin trace\tCtrl+T", IDM_ACTION_BEGIN_TRACE + MENUITEM "End trace\tCtrl+T", IDM_ACTION_END_TRACE #endif END POPUP "&Help" BEGIN - MENUITEM "&Documentation...", IDM_DOCS - MENUITEM "&About 86Box...", IDM_ABOUT + MENUITEM "&Documentation...", IDM_DOCS + MENUITEM "&About 86Box...", IDM_ABOUT END END -StatusBarMenu MENU DISCARDABLE +StatusBarMenu MENU DISCARDABLE BEGIN MENUITEM SEPARATOR END @@ -128,17 +137,17 @@ CassetteSubmenu MENU DISCARDABLE BEGIN POPUP "" BEGIN - MENUITEM "&New image...", IDM_CASSETTE_IMAGE_NEW + MENUITEM "&New image...", IDM_CASSETTE_IMAGE_NEW MENUITEM SEPARATOR - MENUITEM "&Existing image...", IDM_CASSETTE_IMAGE_EXISTING - MENUITEM "Existing image (&Write-protected)...", IDM_CASSETTE_IMAGE_EXISTING_WP + MENUITEM "&Existing image...", IDM_CASSETTE_IMAGE_EXISTING + MENUITEM "Existing image (&Write-protected)...", IDM_CASSETTE_IMAGE_EXISTING_WP MENUITEM SEPARATOR - MENUITEM "&Record", IDM_CASSETTE_RECORD - MENUITEM "&Play", IDM_CASSETTE_PLAY - MENUITEM "&Rewind to the beginning", IDM_CASSETTE_REWIND - MENUITEM "&Fast forward to the end", IDM_CASSETTE_FAST_FORWARD + MENUITEM "&Record", IDM_CASSETTE_RECORD + MENUITEM "&Play", IDM_CASSETTE_PLAY + MENUITEM "&Rewind to the beginning", IDM_CASSETTE_REWIND + MENUITEM "&Fast forward to the end", IDM_CASSETTE_FAST_FORWARD MENUITEM SEPARATOR - MENUITEM "E&ject", IDM_CASSETTE_EJECT + MENUITEM "E&ject", IDM_CASSETTE_EJECT END END @@ -146,9 +155,9 @@ CartridgeSubmenu MENU DISCARDABLE BEGIN POPUP "" BEGIN - MENUITEM "&Image...", IDM_CARTRIDGE_IMAGE + MENUITEM "&Image...", IDM_CARTRIDGE_IMAGE MENUITEM SEPARATOR - MENUITEM "E&ject", IDM_CARTRIDGE_EJECT + MENUITEM "E&ject", IDM_CARTRIDGE_EJECT END END @@ -156,14 +165,14 @@ FloppySubmenu MENU DISCARDABLE BEGIN POPUP "" BEGIN - MENUITEM "&New image...", IDM_FLOPPY_IMAGE_NEW + MENUITEM "&New image...", IDM_FLOPPY_IMAGE_NEW MENUITEM SEPARATOR - MENUITEM "&Existing image...", IDM_FLOPPY_IMAGE_EXISTING - MENUITEM "Existing image (&Write-protected)...", IDM_FLOPPY_IMAGE_EXISTING_WP + MENUITEM "&Existing image...", IDM_FLOPPY_IMAGE_EXISTING + MENUITEM "Existing image (&Write-protected)...", IDM_FLOPPY_IMAGE_EXISTING_WP MENUITEM SEPARATOR - MENUITEM "E&xport to 86F...", IDM_FLOPPY_EXPORT_TO_86F + MENUITEM "E&xport to 86F...", IDM_FLOPPY_EXPORT_TO_86F MENUITEM SEPARATOR - MENUITEM "E&ject", IDM_FLOPPY_EJECT + MENUITEM "E&ject", IDM_FLOPPY_EJECT END END @@ -171,12 +180,13 @@ CdromSubmenu MENU DISCARDABLE BEGIN POPUP "" BEGIN - MENUITEM "&Mute", IDM_CDROM_MUTE + MENUITEM "&Mute", IDM_CDROM_MUTE MENUITEM SEPARATOR - MENUITEM "E&mpty", IDM_CDROM_EMPTY - MENUITEM "&Reload previous image", IDM_CDROM_RELOAD + MENUITEM "E&mpty", IDM_CDROM_EMPTY + MENUITEM "&Reload previous image", IDM_CDROM_RELOAD MENUITEM SEPARATOR - MENUITEM "&Image", IDM_CDROM_IMAGE + MENUITEM "&Image...", IDM_CDROM_IMAGE + MENUITEM "&Folder...", IDM_CDROM_DIR END END @@ -184,13 +194,13 @@ ZIPSubmenu MENU DISCARDABLE BEGIN POPUP "" BEGIN - MENUITEM "&New image...", IDM_ZIP_IMAGE_NEW + MENUITEM "&New image...", IDM_ZIP_IMAGE_NEW MENUITEM SEPARATOR - MENUITEM "&Existing image...", IDM_ZIP_IMAGE_EXISTING - MENUITEM "Existing image (&Write-protected)...", IDM_ZIP_IMAGE_EXISTING_WP + MENUITEM "&Existing image...", IDM_ZIP_IMAGE_EXISTING + MENUITEM "Existing image (&Write-protected)...", IDM_ZIP_IMAGE_EXISTING_WP MENUITEM SEPARATOR - MENUITEM "E&ject", IDM_ZIP_EJECT - MENUITEM "&Reload previous image", IDM_ZIP_RELOAD + MENUITEM "E&ject", IDM_ZIP_EJECT + MENUITEM "&Reload previous image", IDM_ZIP_RELOAD END END @@ -198,13 +208,13 @@ MOSubmenu MENU DISCARDABLE BEGIN POPUP "" BEGIN - MENUITEM "&New image...", IDM_MO_IMAGE_NEW + MENUITEM "&New image...", IDM_MO_IMAGE_NEW MENUITEM SEPARATOR - MENUITEM "&Existing image...", IDM_MO_IMAGE_EXISTING - MENUITEM "Existing image (&Write-protected)...", IDM_MO_IMAGE_EXISTING_WP + MENUITEM "&Existing image...", IDM_MO_IMAGE_EXISTING + MENUITEM "Existing image (&Write-protected)...", IDM_MO_IMAGE_EXISTING_WP MENUITEM SEPARATOR - MENUITEM "E&ject", IDM_MO_EJECT - MENUITEM "&Reload previous image", IDM_MO_RELOAD + MENUITEM "E&ject", IDM_MO_EJECT + MENUITEM "&Reload previous image", IDM_MO_RELOAD END END @@ -230,134 +240,150 @@ END // Dialog // -#define STR_PREFERENCES "Preferences" -#define STR_SND_GAIN "Sound Gain" -#define STR_NEW_FLOPPY "New Image" -#define STR_CONFIG "Settings" -#define STR_SPECIFY_DIM "Specify Main Window Dimensions" +#define STR_PREFERENCES "Preferences" +#define STR_SND_GAIN "Sound Gain" +#define STR_NEW_FLOPPY "New Image" +#define STR_CONFIG "Settings" +#define STR_SPECIFY_DIM "Specify Main Window Dimensions" -#define STR_OK "OK" -#define STR_CANCEL "Cancel" -#define STR_GLOBAL "Save these settings as &global defaults" -#define STR_DEFAULT "&Default" -#define STR_LANGUAGE "Language:" -#define STR_ICONSET "Icon set:" +#define STR_OK "OK" +#define STR_CANCEL "Cancel" +#define STR_GLOBAL "Save these settings as &global defaults" +#define STR_DEFAULT "&Default" +#define STR_LANGUAGE "Language:" +#define STR_ICONSET "Icon set:" -#define STR_GAIN "Gain" +#define STR_GAIN "Gain" -#define STR_FILE_NAME "File name:" -#define STR_DISK_SIZE "Disk size:" -#define STR_RPM_MODE "RPM mode:" -#define STR_PROGRESS "Progress:" +#define STR_FILE_NAME "File name:" +#define STR_DISK_SIZE "Disk size:" +#define STR_RPM_MODE "RPM mode:" +#define STR_PROGRESS "Progress:" -#define STR_WIDTH "Width:" -#define STR_HEIGHT "Height:" -#define STR_LOCK_TO_SIZE "Lock to this size" +#define STR_WIDTH "Width:" +#define STR_HEIGHT "Height:" +#define STR_LOCK_TO_SIZE "Lock to this size" -#define STR_MACHINE_TYPE "Machine type:" -#define STR_MACHINE "Machine:" -#define STR_CONFIGURE "Configure" -#define STR_CPU_TYPE "CPU type:" -#define STR_CPU_SPEED "Speed:" -#define STR_FPU "FPU:" -#define STR_WAIT_STATES "Wait states:" -#define STR_MB "MB" -#define STR_MEMORY "Memory:" -#define STR_TIME_SYNC "Time synchronization" -#define STR_DISABLED "Disabled" -#define STR_ENABLED_LOCAL "Enabled (local time)" -#define STR_ENABLED_UTC "Enabled (UTC)" -#define STR_DYNAREC "Dynamic Recompiler" +#define STR_MACHINE_TYPE "Machine type:" +#define STR_MACHINE "Machine:" +#define STR_CONFIGURE "Configure" +#define STR_CPU_TYPE "CPU type:" +#define STR_CPU_SPEED "Speed:" +#define STR_FPU "FPU:" +#define STR_WAIT_STATES "Wait states:" +#define STR_MB "MB" +#define STR_MEMORY "Memory:" +#define STR_TIME_SYNC "Time synchronization" +#define STR_DISABLED "Disabled" +#define STR_ENABLED_LOCAL "Enabled (local time)" +#define STR_ENABLED_UTC "Enabled (UTC)" +#define STR_DYNAREC "Dynamic Recompiler" +#define STR_SOFTFLOAT "Softfloat FPU" -#define STR_VIDEO "Video:" -#define STR_VOODOO "Voodoo Graphics" +#define STR_VIDEO "Video:" +#define STR_VIDEO_2 "Video 2:" +#define STR_VOODOO "Voodoo Graphics" +#define STR_IBM8514 "IBM 8514/a Graphics" +#define STR_XGA "XGA Graphics" -#define STR_MOUSE "Mouse:" -#define STR_JOYSTICK "Joystick:" -#define STR_JOY1 "Joystick 1..." -#define STR_JOY2 "Joystick 2..." -#define STR_JOY3 "Joystick 3..." -#define STR_JOY4 "Joystick 4..." +#define STR_MOUSE "Mouse:" +#define STR_JOYSTICK "Joystick:" +#define STR_JOY1 "Joystick 1..." +#define STR_JOY2 "Joystick 2..." +#define STR_JOY3 "Joystick 3..." +#define STR_JOY4 "Joystick 4..." -#define STR_SOUND "Sound card:" -#define STR_MIDI_OUT "MIDI Out Device:" -#define STR_MIDI_IN "MIDI In Device:" -#define STR_MPU401 "Standalone MPU-401" -#define STR_SSI "Innovation SSI-2001" -#define STR_CMS "CMS / Game Blaster" -#define STR_GUS "Gravis Ultrasound" -#define STR_FLOAT "Use FLOAT32 sound" +#define STR_SOUND1 "Sound card 1:" +#define STR_SOUND2 "Sound card 2:" +#define STR_SOUND3 "Sound card 3:" +#define STR_SOUND4 "Sound card 4:" +#define STR_MIDI_OUT "MIDI Out Device:" +#define STR_MIDI_IN "MIDI In Device:" +#define STR_MPU401 "Standalone MPU-401" +#define STR_FLOAT "Use FLOAT32 sound" +#define STR_FM_DRIVER "FM synth driver" +#define STR_FM_DRV_NUKED "Nuked (more accurate)" +#define STR_FM_DRV_YMFM "YMFM (faster)" -#define STR_NET_TYPE "Network type:" -#define STR_PCAP "PCap device:" -#define STR_NET "Network adapter:" +#define STR_NET_TYPE "Network type:" +#define STR_PCAP "PCap device:" +#define STR_NET "Network adapter:" +#define STR_NET1 "Network card 1:" +#define STR_NET2 "Network card 2:" +#define STR_NET3 "Network card 3:" +#define STR_NET4 "Network card 4:" -#define STR_COM1 "COM1 Device:" -#define STR_COM2 "COM2 Device:" -#define STR_COM3 "COM3 Device:" -#define STR_COM4 "COM4 Device:" -#define STR_LPT1 "LPT1 Device:" -#define STR_LPT2 "LPT2 Device:" -#define STR_LPT3 "LPT3 Device:" -#define STR_LPT4 "LPT4 Device:" -#define STR_SERIAL1 "Serial port 1" -#define STR_SERIAL2 "Serial port 2" -#define STR_SERIAL3 "Serial port 3" -#define STR_SERIAL4 "Serial port 4" -#define STR_PARALLEL1 "Parallel port 1" -#define STR_PARALLEL2 "Parallel port 2" -#define STR_PARALLEL3 "Parallel port 3" -#define STR_PARALLEL4 "Parallel port 4" +#define STR_COM1 "COM1 Device:" +#define STR_COM2 "COM2 Device:" +#define STR_COM3 "COM3 Device:" +#define STR_COM4 "COM4 Device:" +#define STR_LPT1 "LPT1 Device:" +#define STR_LPT2 "LPT2 Device:" +#define STR_LPT3 "LPT3 Device:" +#define STR_LPT4 "LPT4 Device:" +#define STR_SERIAL1 "Serial port 1" +#define STR_SERIAL2 "Serial port 2" +#define STR_SERIAL3 "Serial port 3" +#define STR_SERIAL4 "Serial port 4" +#define STR_PARALLEL1 "Parallel port 1" +#define STR_PARALLEL2 "Parallel port 2" +#define STR_PARALLEL3 "Parallel port 3" +#define STR_PARALLEL4 "Parallel port 4" +#define STR_SERIAL_PASS1 "Serial port passthrough 1" +#define STR_SERIAL_PASS2 "Serial port passthrough 2" +#define STR_SERIAL_PASS3 "Serial port passthrough 3" +#define STR_SERIAL_PASS4 "Serial port passthrough 4" -#define STR_HDC "HD Controller:" -#define STR_FDC "FD Controller:" -#define STR_IDE_TER "Tertiary IDE Controller" -#define STR_IDE_QUA "Quaternary IDE Controller" -#define STR_SCSI "SCSI" -#define STR_SCSI_1 "Controller 1:" -#define STR_SCSI_2 "Controller 2:" -#define STR_SCSI_3 "Controller 3:" -#define STR_SCSI_4 "Controller 4:" -#define STR_CASSETTE "Cassette" +#define STR_HDC "HD Controller:" +#define STR_FDC "FD Controller:" +#define STR_IDE_TER "Tertiary IDE Controller" +#define STR_IDE_QUA "Quaternary IDE Controller" +#define STR_SCSI "SCSI" +#define STR_SCSI_1 "Controller 1:" +#define STR_SCSI_2 "Controller 2:" +#define STR_SCSI_3 "Controller 3:" +#define STR_SCSI_4 "Controller 4:" +#define STR_CASSETTE "Cassette" -#define STR_HDD "Hard disks:" -#define STR_NEW "&New..." -#define STR_EXISTING "&Existing..." -#define STR_REMOVE "&Remove" -#define STR_BUS "Bus:" -#define STR_CHANNEL "Channel:" -#define STR_ID "ID:" +#define STR_HDD "Hard disks:" +#define STR_NEW "&New..." +#define STR_EXISTING "&Existing..." +#define STR_REMOVE "&Remove" +#define STR_BUS "Bus:" +#define STR_CHANNEL "Channel:" +#define STR_ID "ID:" +#define STR_SPEED "Speed:" -#define STR_SPECIFY "&Specify..." -#define STR_SECTORS "Sectors:" -#define STR_HEADS "Heads:" -#define STR_CYLS "Cylinders:" -#define STR_SIZE_MB "Size (MB):" -#define STR_TYPE "Type:" -#define STR_IMG_FORMAT "Image Format:" -#define STR_BLOCK_SIZE "Block Size:" +#define STR_SPECIFY "&Specify..." +#define STR_SECTORS "Sectors:" +#define STR_HEADS "Heads:" +#define STR_CYLS "Cylinders:" +#define STR_SIZE_MB "Size (MB):" +#define STR_TYPE "Type:" +#define STR_IMG_FORMAT "Image Format:" +#define STR_BLOCK_SIZE "Block Size:" -#define STR_FLOPPY_DRIVES "Floppy drives:" -#define STR_TURBO "Turbo timings" -#define STR_CHECKBPB "Check BPB" -#define STR_CDROM_DRIVES "CD-ROM drives:" -#define STR_CD_SPEED "Speed:" +#define STR_FLOPPY_DRIVES "Floppy drives:" +#define STR_TURBO "Turbo timings" +#define STR_CHECKBPB "Check BPB" +#define STR_CDROM_DRIVES "CD-ROM drives:" +#define STR_CD_SPEED "Speed:" -#define STR_MO_DRIVES "MO drives:" -#define STR_ZIP_DRIVES "ZIP drives:" -#define STR_250 "ZIP 250" +#define STR_MO_DRIVES "MO drives:" +#define STR_ZIP_DRIVES "ZIP drives:" +#define STR_250 "ZIP 250" -#define STR_ISARTC "ISA RTC:" -#define STR_ISAMEM "ISA Memory Expansion" -#define STR_ISAMEM_1 "Card 1:" -#define STR_ISAMEM_2 "Card 2:" -#define STR_ISAMEM_3 "Card 3:" -#define STR_ISAMEM_4 "Card 4:" -#define STR_BUGGER "ISABugger device" -#define STR_POSTCARD "POST card" +#define STR_ISARTC "ISA RTC:" +#define STR_ISAMEM "ISA Memory Expansion" +#define STR_ISAMEM_1 "Card 1:" +#define STR_ISAMEM_2 "Card 2:" +#define STR_ISAMEM_3 "Card 3:" +#define STR_ISAMEM_4 "Card 4:" +#define STR_BUGGER "ISABugger device" +#define STR_POSTCARD "POST card" -#define FONT_SIZE 9 -#define FONT_NAME "Segoe UI" +#define FONT_SIZE 9 +#define FONT_NAME "Segoe UI" #include "dialogs.rc" @@ -366,194 +392,188 @@ END // String Table // -STRINGTABLE DISCARDABLE +STRINGTABLE DISCARDABLE BEGIN - 2048 "86Box" - IDS_2049 "Error" - IDS_2050 "Fatal error" - IDS_2051 " - PAUSED" - IDS_2052 "Press Ctrl+Alt+PgDn to return to windowed mode." - IDS_2053 "Speed" - IDS_2054 "ZIP %03i %i (%s): %ls" - IDS_2055 "ZIP images (*.IM?;*.ZDI)\0*.IM?;*.ZDI\0" - IDS_2056 "86Box could not find any usable ROM images.\n\nPlease download a ROM set and extract it into the ""roms"" directory." - IDS_2057 "(empty)" - IDS_2058 "ZIP images (*.IM?;*.ZDI)\0*.IM?;*.ZDI\0All files (*.*)\0*.*\0" - IDS_2059 "Turbo" - IDS_2060 "On" - IDS_2061 "Off" - IDS_2062 "All images (*.86F;*.DSK;*.FLP;*.IM?;*.*FD?)\0*.86F;*.DSK;*.FLP;*.IM?;*.*FD?\0Basic sector images (*.DSK;*.FLP;*.IM?;*.*FD?)\0*.DSK;*.FLP;*.IM?;*.IMG;*.*FD?\0Surface images (*.86F)\0*.86F\0" - IDS_2063 "Machine ""%hs"" is not available due to missing ROMs in the roms/machines directory. Switching to an available machine." + 2048 "86Box" + IDS_2049 "Error" + IDS_2050 "Fatal error" + IDS_2051 " - PAUSED" + IDS_2052 "Press Ctrl+Alt+PgDn to return to windowed mode." + IDS_2053 "Speed" + IDS_2054 "ZIP %03i %i (%s): %ls" + IDS_2055 "ZIP images (*.IM?;*.ZDI)\0*.IM?;*.ZDI\0" + IDS_2056 "86Box could not find any usable ROM images.\n\nPlease download a ROM set and extract it into the ""roms"" directory." + IDS_2057 "(empty)" + IDS_2058 "ZIP images (*.IM?;*.ZDI)\0*.IM?;*.ZDI\0All files (*.*)\0*.*\0" + IDS_2059 "Turbo" + IDS_2060 "On" + IDS_2061 "Off" + IDS_2062 "All images (*.86F;*.DSK;*.FLP;*.IM?;*.*FD?)\0*.86F;*.DSK;*.FLP;*.IM?;*.*FD?\0Basic sector images (*.DSK;*.FLP;*.IM?;*.*FD?)\0*.DSK;*.FLP;*.IM?;*.IMG;*.*FD?\0Surface images (*.86F)\0*.86F\0" + IDS_2063 "Machine ""%hs"" is not available due to missing ROMs in the roms/machines directory. Switching to an available machine." END -STRINGTABLE DISCARDABLE +STRINGTABLE DISCARDABLE BEGIN - IDS_2064 "Video card ""%hs"" is not available due to missing ROMs in the roms/video directory. Switching to an available video card." - IDS_2065 "Machine" - IDS_2066 "Display" - IDS_2067 "Input devices" - IDS_2068 "Sound" - IDS_2069 "Network" - IDS_2070 "Ports (COM & LPT)" - IDS_2071 "Storage controllers" - IDS_2072 "Hard disks" - IDS_2073 "Floppy & CD-ROM drives" - IDS_2074 "Other removable devices" - IDS_2075 "Other peripherals" - IDS_2076 "Surface images (*.86F)\0*.86F\0" - IDS_2077 "Click to capture mouse" - IDS_2078 "Press F8+F12 to release mouse" - IDS_2079 "Press F8+F12 or middle button to release mouse" + IDS_2064 "Video card ""%hs"" is not available due to missing ROMs in the roms/video directory. Switching to an available video card." + IDS_2065 "Machine" + IDS_2066 "Display" + IDS_2067 "Input devices" + IDS_2068 "Sound" + IDS_2069 "Network" + IDS_2070 "Ports (COM & LPT)" + IDS_2071 "Storage controllers" + IDS_2072 "Hard disks" + IDS_2073 "Floppy & CD-ROM drives" + IDS_2074 "Other removable devices" + IDS_2075 "Other peripherals" + IDS_2076 "Surface images (*.86F)\0*.86F\0" + IDS_2077 "Click to capture mouse" + IDS_2078 "Press F8+F12 to release mouse" + IDS_2079 "Press F8+F12 or middle button to release mouse" END -STRINGTABLE DISCARDABLE +STRINGTABLE DISCARDABLE BEGIN - IDS_2080 "Unable to initialize FluidSynth" - IDS_2081 "Bus" - IDS_2082 "File" - IDS_2083 "C" - IDS_2084 "H" - IDS_2085 "S" - IDS_2086 "MB" - IDS_2087 "Check BPB" - IDS_2088 "KB" - IDS_2089 "Could not initialize the video renderer." - IDS_2090 "Default" - IDS_2091 "%i Wait state(s)" - IDS_2092 "Type" - IDS_2093 "Failed to set up PCap" - IDS_2094 "No PCap devices found" - IDS_2095 "Invalid PCap device" - IDS_2096 "Standard 2-button joystick(s)" - IDS_2097 "Standard 4-button joystick" - IDS_2098 "Standard 6-button joystick" - IDS_2099 "Standard 8-button joystick" - IDS_2100 "CH Flightstick Pro" - IDS_2101 "Microsoft SideWinder Pad" - IDS_2102 "Thrustmaster Flight Control System" - IDS_2103 "None" - IDS_2104 "Unable to load keyboard accelerators." - IDS_2105 "Unable to register raw input." - IDS_2106 "%u" - IDS_2107 "%u MB (CHS: %i, %i, %i)" - IDS_2108 "Floppy %i (%s): %ls" - IDS_2109 "All images (*.0??;*.1??;*.??0;*.86F;*.BIN;*.CQ?;*.D??;*.FLP;*.HDM;*.IM?;*.JSON;*.TD0;*.*FD?;*.MFM;*.XDF)\0*.0??;*.1??;*.??0;*.86F;*.BIN;*.CQ?;*.D??;*.FLP;*.HDM;*.IM?;*.JSON;*.TD0;*.*FD?;*.MFM;*.XDF\0Advanced sector images (*.IMD;*.JSON;*.TD0)\0*.IMD;*.JSON;*.TD0\0Basic sector images (*.0??;*.1??;*.??0;*.BIN;*.CQ?;*.D??;*.FLP;*.HDM;*.IM?;*.XDF;*.*FD?)\0*.0??;*.1??;*.??0;*.BIN;*.CQ?;*.D??;*.FLP;*.HDM;*.IM?;*.XDF;*.*FD?\0Flux images (*.FDI)\0*.FDI\0Surface images (*.86F;*.MFM)\0*.86F;*.MFM\0All files (*.*)\0*.*\0" - IDS_2110 "Unable to initialize FreeType" - IDS_2111 "Unable to initialize SDL, SDL2.dll is required" - IDS_2112 "Are you sure you want to hard reset the emulated machine?" - IDS_2113 "Are you sure you want to exit 86Box?" - IDS_2114 "Unable to initialize Ghostscript" - IDS_2115 "MO %i (%ls): %ls" - IDS_2116 "MO images (*.IM?;*.MDI)\0*.IM?;*.MDI\0All files (*.*)\0*.*\0" - IDS_2117 "Welcome to 86Box!" - IDS_2118 "Internal controller" - IDS_2119 "Exit" - IDS_2120 "No ROMs found" - IDS_2121 "Do you want to save the settings?" - IDS_2122 "This will hard reset the emulated machine." - IDS_2123 "Save" - IDS_2124 "About 86Box" - IDS_2125 "86Box v" EMU_VERSION + IDS_2081 "Bus" + IDS_2082 "File" + IDS_2083 "C" + IDS_2084 "H" + IDS_2085 "S" + IDS_2086 "MB" + IDS_2087 "Speed" + IDS_2088 "Check BPB" + IDS_2089 "KB" + IDS_2090 "Could not initialize the video renderer." + IDS_2091 "Default" + IDS_2092 "%i Wait state(s)" + IDS_2093 "Type" + IDS_2094 "Failed to set up PCap" + IDS_2095 "No PCap devices found" + IDS_2096 "Invalid PCap device" + IDS_2097 "Standard 2-button joystick(s)" + IDS_2098 "Standard 4-button joystick" + IDS_2099 "Standard 6-button joystick" + IDS_2100 "Standard 8-button joystick" + IDS_2101 "CH Flightstick Pro" + IDS_2102 "Microsoft SideWinder Pad" + IDS_2103 "Thrustmaster Flight Control System" + IDS_2104 "None" + IDS_2105 "Unable to load keyboard accelerators." + IDS_2106 "Unable to register raw input." + IDS_2107 "%u" + IDS_2108 "%u MB (CHS: %i, %i, %i)" + IDS_2109 "Floppy %i (%s): %ls" + IDS_2110 "All images (*.0??;*.1??;*.??0;*.86F;*.BIN;*.CQ?;*.D??;*.FLP;*.HDM;*.IM?;*.JSON;*.TD0;*.*FD?;*.MFM;*.XDF)\0*.0??;*.1??;*.??0;*.86F;*.BIN;*.CQ?;*.D??;*.FLP;*.HDM;*.IM?;*.JSON;*.TD0;*.*FD?;*.MFM;*.XDF\0Advanced sector images (*.IMD;*.JSON;*.TD0)\0*.IMD;*.JSON;*.TD0\0Basic sector images (*.0??;*.1??;*.??0;*.BIN;*.CQ?;*.D??;*.FLP;*.HDM;*.IM?;*.XDF;*.*FD?)\0*.0??;*.1??;*.??0;*.BIN;*.CQ?;*.D??;*.FLP;*.HDM;*.IM?;*.XDF;*.*FD?\0Flux images (*.FDI)\0*.FDI\0Surface images (*.86F;*.MFM)\0*.86F;*.MFM\0All files (*.*)\0*.*\0" + IDS_2112 "Unable to initialize SDL, SDL2.dll is required" + IDS_2113 "Are you sure you want to hard reset the emulated machine?" + IDS_2114 "Are you sure you want to exit 86Box?" + IDS_2115 "Unable to initialize Ghostscript" + IDS_2116 "MO %i (%ls): %ls" + IDS_2117 "MO images (*.IM?;*.MDI)\0*.IM?;*.MDI\0All files (*.*)\0*.*\0" + IDS_2118 "Welcome to 86Box!" + IDS_2119 "Internal controller" + IDS_2120 "Exit" + IDS_2121 "No ROMs found" + IDS_2122 "Do you want to save the settings?" + IDS_2123 "This will hard reset the emulated machine." + IDS_2124 "Save" + IDS_2125 "About 86Box" + IDS_2126 "86Box v" EMU_VERSION - IDS_2126 "An emulator of old computers\n\nAuthors: Sarah Walker, Miran Grca, Fred N. van Kempen (waltje), SA1988, Tiseno100, reenigne, leilei, JohnElliott, greatpsycho, and others.\n\nReleased under the GNU General Public License version 2 or later. See LICENSE for more information." - IDS_2127 "OK" - IDS_2128 "Hardware not available" + IDS_2127 "An emulator of old computers\n\nAuthors: Miran GrÄa (OBattler), RichardG867, Jasmine Iwanek, TC1995, coldbrewed, Teemu Korhonen (Manaatti), Joakim L. Gilje, Adrien Moulin (elyosh), Daniel Balsom (gloriouscow), Cacodemon345, Fred N. van Kempen (waltje), Tiseno100, reenigne, and others.\n\nWith previous core contributions from Sarah Walker, leilei, JohnElliott, greatpsycho, and others.\n\nReleased under the GNU General Public License version 2 or later. See LICENSE for more information." + IDS_2128 "OK" + IDS_2129 "Hardware not available" #ifdef _WIN32 #define LIB_NAME_PCAP "WinPcap" #else #define LIB_NAME_PCAP "libpcap" #endif - IDS_2129 "Make sure " LIB_NAME_PCAP " is installed and that you are on a " LIB_NAME_PCAP "-compatible network connection." - IDS_2130 "Invalid configuration" -#ifdef _WIN32 -#define LIB_NAME_FREETYPE "freetype.dll" -#else -#define LIB_NAME_FREETYPE "libfreetype" -#endif - IDS_2131 LIB_NAME_FREETYPE " is required for ESC/P printer emulation." + IDS_2130 "Make sure " LIB_NAME_PCAP " is installed and that you are on a " LIB_NAME_PCAP "-compatible network connection." + IDS_2131 "Invalid configuration" #ifdef _WIN32 #define LIB_NAME_GS "gsdll32.dll" #else #define LIB_NAME_GS "libgs" #endif - IDS_2132 LIB_NAME_GS " is required for automatic conversion of PostScript files to PDF.\n\nAny documents sent to the generic PostScript printer will be saved as PostScript (.ps) files." -#ifdef _WIN32 -#define LIB_NAME_FLUIDSYNTH "libfluidsynth.dll" -#else -#define LIB_NAME_FLUIDSYNTH "libfluidsynth" -#endif - IDS_2133 LIB_NAME_FLUIDSYNTH " is required for FluidSynth MIDI output." - IDS_2134 "Entering fullscreen mode" - IDS_2135 "Don't show this message again" - IDS_2136 "Don't exit" - IDS_2137 "Reset" - IDS_2138 "Don't reset" - IDS_2139 "MO images (*.IM?;*.MDI)\0*.IM?;*.MDI\0All files (*.*)\0*.*\0" - IDS_2140 "CD-ROM images (*.ISO;*.CUE)\0*.ISO;*.CUE\0All files (*.*)\0*.*\0" - IDS_2141 "%hs Device Configuration" - IDS_2142 "Monitor in sleep mode" - IDS_2143 "OpenGL Shaders (*.GLSL)\0*.GLSL\0All files (*.*)\0*.*\0" - IDS_2144 "OpenGL options" - IDS_2145 "You are loading an unsupported configuration" - IDS_2146 "CPU type filtering based on selected machine is disabled for this emulated machine.\n\nThis makes it possible to choose a CPU that is otherwise incompatible with the selected machine. However, you may run into incompatibilities with the machine BIOS or other software.\n\nEnabling this setting is not officially supported and any bug reports filed may be closed as invalid." - IDS_2147 "Continue" - IDS_2148 "Cassette: %s" - IDS_2149 "Cassette images (*.PCM;*.RAW;*.WAV;*.CAS)\0*.PCM;*.RAW;*.WAV;*.CAS\0All files (*.*)\0*.*\0" - IDS_2150 "Cartridge %i: %ls" - IDS_2151 "Cartridge images (*.A;*.B;*.JRC)\0*.A;*.B;*.JRC\0All files (*.*)\0*.*\0" - IDS_2152 "Error initializing renderer" - IDS_2153 "OpenGL (3.0 Core) renderer could not be initialized. Use another renderer." - IDS_2154 "Resume execution" - IDS_2155 "Pause execution" - IDS_2156 "Press Ctrl+Alt+Del" - IDS_2157 "Press Ctrl+Alt+Esc" - IDS_2158 "Hard reset" - IDS_2159 "ACPI shutdown" - IDS_2160 "Settings" + IDS_2133 LIB_NAME_GS " is required for automatic conversion of PostScript files to PDF.\n\nAny documents sent to the generic PostScript printer will be saved as PostScript (.ps) files." + IDS_2135 "Entering fullscreen mode" + IDS_2136 "Don't show this message again" + IDS_2137 "Don't exit" + IDS_2138 "Reset" + IDS_2139 "Don't reset" + IDS_2140 "MO images (*.IM?;*.MDI)\0*.IM?;*.MDI\0All files (*.*)\0*.*\0" + IDS_2141 "CD-ROM images (*.ISO;*.CUE)\0*.ISO;*.CUE\0All files (*.*)\0*.*\0" + IDS_2142 "%hs Device Configuration" + IDS_2143 "Monitor in sleep mode" + IDS_2144 "OpenGL Shaders (*.GLSL)\0*.GLSL\0All files (*.*)\0*.*\0" + IDS_2145 "OpenGL options" + IDS_2146 "You are loading an unsupported configuration" + IDS_2147 "CPU type filtering based on selected machine is disabled for this emulated machine.\n\nThis makes it possible to choose a CPU that is otherwise incompatible with the selected machine. However, you may run into incompatibilities with the machine BIOS or other software.\n\nEnabling this setting is not officially supported and any bug reports filed may be closed as invalid." + IDS_2148 "Continue" + IDS_2149 "Cassette: %s" + IDS_2150 "Cassette images (*.PCM;*.RAW;*.WAV;*.CAS)\0*.PCM;*.RAW;*.WAV;*.CAS\0All files (*.*)\0*.*\0" + IDS_2151 "Cartridge %i: %ls" + IDS_2152 "Cartridge images (*.A;*.B;*.JRC)\0*.A;*.B;*.JRC\0All files (*.*)\0*.*\0" + IDS_2153 "Error initializing renderer" + IDS_2154 "OpenGL (3.0 Core) renderer could not be initialized. Use another renderer." + IDS_2155 "Resume execution" + IDS_2156 "Pause execution" + IDS_2157 "Press Ctrl+Alt+Del" + IDS_2158 "Press Ctrl+Alt+Esc" + IDS_2159 "Hard reset" + IDS_2160 "ACPI shutdown" + IDS_2161 "Settings" + IDS_2162 "Type" + IDS_2163 "No Dynarec" + IDS_2164 "Old Dynarec" + IDS_2165 "New Dynarec" + IDS_2166 "Video card #2 ""%hs"" is not available due to missing ROMs in the roms/video directory. Disabling the second video card." + IDS_2167 "Failed to initialize network driver" + IDS_2168 "The network configuration will be switched to the null driver" END -STRINGTABLE DISCARDABLE +STRINGTABLE DISCARDABLE BEGIN IDS_4096 "Hard disk (%s)" - IDS_4097 "%01i:%01i" - IDS_4098 "%01i" - IDS_4099 "MFM/RLL or ESDI CD-ROM drives never existed" - IDS_4100 "Custom..." - IDS_4101 "Custom (large)..." - IDS_4102 "Add New Hard Disk" - IDS_4103 "Add Existing Hard Disk" - IDS_4104 "HDI disk images cannot be larger than 4 GB." - IDS_4105 "Disk images cannot be larger than 127 GB." - IDS_4106 "Hard disk images (*.HD?;*.IM?;*.VHD)\0*.HD?;*.IM?;*.VHD\0All files (*.*)\0*.*\0" - IDS_4107 "Unable to read file" - IDS_4108 "Unable to write file" - IDS_4109 "HDI or HDX images with a sector size other than 512 are not supported." - IDS_4110 "USB is not yet supported" - IDS_4111 "Disk image file already exists" - IDS_4112 "Please specify a valid file name." - IDS_4113 "Disk image created" - IDS_4114 "Make sure the file exists and is readable." - IDS_4115 "Make sure the file is being saved to a writable directory." - IDS_4116 "Disk image too large" - IDS_4117 "Remember to partition and format the newly-created drive." - IDS_4118 "The selected file will be overwritten. Are you sure you want to use it?" - IDS_4119 "Unsupported disk image" - IDS_4120 "Overwrite" - IDS_4121 "Don't overwrite" - IDS_4122 "Raw image (.img)" - IDS_4123 "HDI image (.hdi)" - IDS_4124 "HDX image (.hdx)" - IDS_4125 "Fixed-size VHD (.vhd)" - IDS_4126 "Dynamic-size VHD (.vhd)" - IDS_4127 "Differencing VHD (.vhd)" - IDS_4128 "Large blocks (2 MB)" - IDS_4129 "Small blocks (512 KB)" - IDS_4130 "VHD files (*.VHD)\0*.VHD\0All files (*.*)\0*.*\0" - IDS_4131 "Select the parent VHD" - IDS_4132 "This could mean that the parent image was modified after the differencing image was created.\n\nIt can also happen if the image files were moved or copied, or by a bug in the program that created this disk.\n\nDo you want to fix the timestamps?" - IDS_4133 "Parent and child disk timestamps do not match" - IDS_4134 "Could not fix VHD timestamp." - IDS_4135 "%01i:%02i" + IDS_4097 "%01i:%01i" + IDS_4098 "%01i" + IDS_4099 "MFM/RLL or ESDI CD-ROM drives never existed" + IDS_4100 "Custom..." + IDS_4101 "Custom (large)..." + IDS_4102 "Add New Hard Disk" + IDS_4103 "Add Existing Hard Disk" + IDS_4104 "HDI disk images cannot be larger than 4 GB." + IDS_4105 "Disk images cannot be larger than 127 GB." + IDS_4106 "Hard disk images (*.HD?;*.IM?;*.VHD)\0*.HD?;*.IM?;*.VHD\0All files (*.*)\0*.*\0" + IDS_4107 "Unable to read file" + IDS_4108 "Unable to write file" + IDS_4109 "HDI or HDX images with a sector size other than 512 are not supported." + IDS_4110 "USB is not yet supported" + IDS_4111 "Disk image file already exists" + IDS_4112 "Please specify a valid file name." + IDS_4113 "Disk image created" + IDS_4114 "Make sure the file exists and is readable." + IDS_4115 "Make sure the file is being saved to a writable directory." + IDS_4116 "Disk image too large" + IDS_4117 "Remember to partition and format the newly-created drive." + IDS_4118 "The selected file will be overwritten. Are you sure you want to use it?" + IDS_4119 "Unsupported disk image" + IDS_4120 "Overwrite" + IDS_4121 "Don't overwrite" + IDS_4122 "Raw image (.img)" + IDS_4123 "HDI image (.hdi)" + IDS_4124 "HDX image (.hdx)" + IDS_4125 "Fixed-size VHD (.vhd)" + IDS_4126 "Dynamic-size VHD (.vhd)" + IDS_4127 "Differencing VHD (.vhd)" + IDS_4128 "Large blocks (2 MB)" + IDS_4129 "Small blocks (512 KB)" + IDS_4130 "VHD files (*.VHD)\0*.VHD\0All files (*.*)\0*.*\0" + IDS_4131 "Select the parent VHD" + IDS_4132 "This could mean that the parent image was modified after the differencing image was created.\n\nIt can also happen if the image files were moved or copied, or by a bug in the program that created this disk.\n\nDo you want to fix the timestamps?" + IDS_4133 "Parent and child disk timestamps do not match" + IDS_4134 "Could not fix VHD timestamp." + IDS_4135 "%01i:%02i" IDS_4352 "MFM/RLL" IDS_4353 "XTA" @@ -562,56 +582,56 @@ BEGIN IDS_4356 "ATAPI" IDS_4357 "SCSI" - IDS_4608 "MFM/RLL (%01i:%01i)" - IDS_4609 "XTA (%01i:%01i)" - IDS_4610 "ESDI (%01i:%01i)" - IDS_4611 "IDE (%01i:%01i)" - IDS_4612 "ATAPI (%01i:%01i)" - IDS_4613 "SCSI (%01i:%02i)" + IDS_4608 "MFM/RLL (%01i:%01i)" + IDS_4609 "XTA (%01i:%01i)" + IDS_4610 "ESDI (%01i:%01i)" + IDS_4611 "IDE (%01i:%01i)" + IDS_4612 "ATAPI (%01i:%01i)" + IDS_4613 "SCSI (%01i:%02i)" - IDS_5120 "CD-ROM %i (%s): %s" + IDS_5120 "CD-ROM %i (%s): %s" - IDS_5376 "Disabled" - IDS_5381 "ATAPI" + IDS_5376 "Disabled" + IDS_5381 "ATAPI" IDS_5382 "SCSI" - IDS_5632 "Disabled" - IDS_5637 "ATAPI (%01i:%01i)" + IDS_5632 "Disabled" + IDS_5637 "ATAPI (%01i:%01i)" IDS_5638 "SCSI (%01i:%02i)" - IDS_5888 "160 kB" - IDS_5889 "180 kB" - IDS_5890 "320 kB" - IDS_5891 "360 kB" - IDS_5892 "640 kB" - IDS_5893 "720 kB" - IDS_5894 "1.2 MB" - IDS_5895 "1.25 MB" - IDS_5896 "1.44 MB" - IDS_5897 "DMF (cluster 1024)" - IDS_5898 "DMF (cluster 2048)" - IDS_5899 "2.88 MB" - IDS_5900 "ZIP 100" - IDS_5901 "ZIP 250" - IDS_5902 "3.5"" 128 MB (ISO 10090)" - IDS_5903 "3.5"" 230 MB (ISO 13963)" - IDS_5904 "3.5"" 540 MB (ISO 15498)" - IDS_5905 "3.5"" 640 MB (ISO 15498)" - IDS_5906 "3.5"" 1.3 GB (GigaMO)" - IDS_5907 "3.5"" 2.3 GB (GigaMO 2)" - IDS_5908 "5.25"" 600 MB" - IDS_5909 "5.25"" 650 MB" - IDS_5910 "5.25"" 1 GB" - IDS_5911 "5.25"" 1.3 GB" + IDS_5888 "160 kB" + IDS_5889 "180 kB" + IDS_5890 "320 kB" + IDS_5891 "360 kB" + IDS_5892 "640 kB" + IDS_5893 "720 kB" + IDS_5894 "1.2 MB" + IDS_5895 "1.25 MB" + IDS_5896 "1.44 MB" + IDS_5897 "DMF (cluster 1024)" + IDS_5898 "DMF (cluster 2048)" + IDS_5899 "2.88 MB" + IDS_5900 "ZIP 100" + IDS_5901 "ZIP 250" + IDS_5902 "3.5"" 128 MB (ISO 10090)" + IDS_5903 "3.5"" 230 MB (ISO 13963)" + IDS_5904 "3.5"" 540 MB (ISO 15498)" + IDS_5905 "3.5"" 640 MB (ISO 15498)" + IDS_5906 "3.5"" 1.3 GB (GigaMO)" + IDS_5907 "3.5"" 2.3 GB (GigaMO 2)" + IDS_5908 "5.25"" 600 MB" + IDS_5909 "5.25"" 650 MB" + IDS_5910 "5.25"" 1 GB" + IDS_5911 "5.25"" 1.3 GB" - IDS_6144 "Perfect RPM" - IDS_6145 "1% below perfect RPM" - IDS_6146 "1.5% below perfect RPM" - IDS_6147 "2% below perfect RPM" + IDS_6144 "Perfect RPM" + IDS_6145 "1% below perfect RPM" + IDS_6146 "1.5% below perfect RPM" + IDS_6147 "2% below perfect RPM" - IDS_7168 "(System Default)" + IDS_7168 "(System Default)" END -#define IDS_LANG_ENUS IDS_7168 +#define IDS_LANG_ENUS IDS_7168 // English (U.S.) resources ///////////////////////////////////////////////////////////////////////////// diff --git a/src/win/languages/es-ES.rc b/src/win/languages/es-ES.rc index 350017861..1fd0bceff 100644 --- a/src/win/languages/es-ES.rc +++ b/src/win/languages/es-ES.rc @@ -13,113 +13,122 @@ LANGUAGE LANG_SPANISH, SUBLANG_SPANISH // Menu // -MainMenu MENU DISCARDABLE +MainMenu MENU DISCARDABLE BEGIN POPUP "&Acción" BEGIN - MENUITEM "&Teclado requiere captura", IDM_ACTION_KBD_REQ_CAPTURE - MENUITEM "CTRL &derecho es ALT izquierdo", IDM_ACTION_RCTRL_IS_LALT + MENUITEM "&Teclado requiere captura", IDM_ACTION_KBD_REQ_CAPTURE + MENUITEM "CTRL &derecho es ALT izquierdo", IDM_ACTION_RCTRL_IS_LALT MENUITEM SEPARATOR - MENUITEM "&Hard Reset...", IDM_ACTION_HRESET - MENUITEM "&Ctrl+Alt+Del\tCtrl+F12", IDM_ACTION_RESET_CAD + MENUITEM "&Hard Reset...", IDM_ACTION_HRESET + MENUITEM "&Ctrl+Alt+Del\tCtrl+F12", IDM_ACTION_RESET_CAD MENUITEM SEPARATOR - MENUITEM "Ctrl+Alt+&Esc", IDM_ACTION_CTRL_ALT_ESC + MENUITEM "Ctrl+Alt+&Esc", IDM_ACTION_CTRL_ALT_ESC MENUITEM SEPARATOR - MENUITEM "&Pausa", IDM_ACTION_PAUSE + MENUITEM "&Pausa", IDM_ACTION_PAUSE MENUITEM SEPARATOR - MENUITEM "&Salir...", IDM_ACTION_EXIT + MENUITEM "&Salir...", IDM_ACTION_EXIT END POPUP "&Vista" BEGIN - MENUITEM "&Ocultar barra de estado", IDM_VID_HIDE_STATUS_BAR - MENUITEM "Hide &toolbar", IDM_VID_HIDE_TOOLBAR + MENUITEM "&Ocultar barra de estado", IDM_VID_HIDE_STATUS_BAR + MENUITEM "Hide &toolbar", IDM_VID_HIDE_TOOLBAR MENUITEM SEPARATOR - MENUITEM "&Ventana redimensionable", IDM_VID_RESIZE - MENUITEM "&Recordar tamaño y posición", IDM_VID_REMEMBER + MENUITEM "&Show non-primary monitors", IDM_VID_MONITORS + MENUITEM "&Ventana redimensionable", IDM_VID_RESIZE + MENUITEM "&Recordar tamaño y posición", IDM_VID_REMEMBER MENUITEM SEPARATOR POPUP "Re&nderizador" BEGIN - MENUITEM "&SDL (Software)", IDM_VID_SDL_SW - MENUITEM "SDL (&Hardware)", IDM_VID_SDL_HW - MENUITEM "SDL (&OpenGL)", IDM_VID_SDL_OPENGL - MENUITEM "Open&GL (3.0 Core)", IDM_VID_OPENGL_CORE + MENUITEM "&SDL (Software)", IDM_VID_SDL_SW + MENUITEM "SDL (&Hardware)", IDM_VID_SDL_HW + MENUITEM "SDL (&OpenGL)", IDM_VID_SDL_OPENGL + MENUITEM "Open&GL (3.0 Core)", IDM_VID_OPENGL_CORE #ifdef USE_VNC - MENUITEM "&VNC", IDM_VID_VNC + MENUITEM "&VNC", IDM_VID_VNC #endif END MENUITEM SEPARATOR - MENUITEM "E&specificar dimensiones...", IDM_VID_SPECIFY_DIM - MENUITEM "F&orzar ratio 4:3", IDM_VID_FORCE43 + MENUITEM "E&specificar dimensiones...", IDM_VID_SPECIFY_DIM + MENUITEM "F&orzar ratio 4:3", IDM_VID_FORCE43 POPUP "&Factor de escalado de ventana" BEGIN - MENUITEM "&0.5x", IDM_VID_SCALE_1X - MENUITEM "&1x", IDM_VID_SCALE_2X - MENUITEM "1.&5x", IDM_VID_SCALE_3X - MENUITEM "&2x", IDM_VID_SCALE_4X + MENUITEM "&0.5x", IDM_VID_SCALE_1X + MENUITEM "&1x", IDM_VID_SCALE_2X + MENUITEM "1.&5x", IDM_VID_SCALE_3X + MENUITEM "&2x", IDM_VID_SCALE_4X + MENUITEM "&3x", IDM_VID_SCALE_5X + MENUITEM "&4x", IDM_VID_SCALE_6X + MENUITEM "&5x", IDM_VID_SCALE_7X + MENUITEM "&6x", IDM_VID_SCALE_8X + MENUITEM "&7x", IDM_VID_SCALE_9X + MENUITEM "&8x", IDM_VID_SCALE_10X END POPUP "&Método de filtrado" BEGIN - MENUITEM "&Más cercano", IDM_VID_FILTER_NEAREST - MENUITEM "&Lineal", IDM_VID_FILTER_LINEAR + MENUITEM "&Más cercano", IDM_VID_FILTER_NEAREST + MENUITEM "&Lineal", IDM_VID_FILTER_LINEAR END - MENUITEM "&Escalado alta densidad", IDM_VID_HIDPI + MENUITEM "&Escalado alta densidad", IDM_VID_HIDPI MENUITEM SEPARATOR - MENUITEM "&Pantalla completa\tCtrl+Alt+PgUp", IDM_VID_FULLSCREEN + MENUITEM "&Pantalla completa\tCtrl+Alt+PgUp", IDM_VID_FULLSCREEN POPUP "Escalado pantalla completa" BEGIN - MENUITEM "&Estirar", IDM_VID_FS_FULL - MENUITEM "&4:3", IDM_VID_FS_43 + MENUITEM "&Estirar", IDM_VID_FS_FULL + MENUITEM "&4:3", IDM_VID_FS_43 MENUITEM "&Píxeles cuadrados (Mant. aspecto)", IDM_VID_FS_KEEPRATIO - MENUITEM "&Escalado valor entero", IDM_VID_FS_INT + MENUITEM "&Escalado valor entero", IDM_VID_FS_INT END POPUP "&Ajustes EGA/(S)VGA" BEGIN - MENUITEM "&Monitor VGA invertido", IDM_VID_INVERT + MENUITEM "&Monitor VGA invertido", IDM_VID_INVERT POPUP "&Tipo de pantalla VGA" BEGIN - MENUITEM "RGB &Color", IDM_VID_GRAY_RGB - MENUITEM "RGB &Grises", IDM_VID_GRAY_MONO - MENUITEM "Monitor &Ãmbar", IDM_VID_GRAY_AMBER - MENUITEM "Monitor &Verde", IDM_VID_GRAY_GREEN - MENUITEM "Monitor &Blanco", IDM_VID_GRAY_WHITE + MENUITEM "RGB &Color", IDM_VID_GRAY_RGB + MENUITEM "RGB &Grises", IDM_VID_GRAY_MONO + MENUITEM "Monitor &Ãmbar", IDM_VID_GRAY_AMBER + MENUITEM "Monitor &Verde", IDM_VID_GRAY_GREEN + MENUITEM "Monitor &Blanco", IDM_VID_GRAY_WHITE END POPUP "&Conversión a grises" BEGIN - MENUITEM "BT&601 (NTSC/PAL)", IDM_VID_GRAYCT_601 - MENUITEM "BT&709 (HDTV)", IDM_VID_GRAYCT_709 - MENUITEM "&Media", IDM_VID_GRAYCT_AVE + MENUITEM "BT&601 (NTSC/PAL)", IDM_VID_GRAYCT_601 + MENUITEM "BT&709 (HDTV)", IDM_VID_GRAYCT_709 + MENUITEM "&Media", IDM_VID_GRAYCT_AVE END END MENUITEM SEPARATOR - MENUITEM "&Overscan CGA/PCjr/Tandy/EGA/(S)VGA", IDM_VID_OVERSCAN + MENUITEM "&Overscan CGA/PCjr/Tandy/EGA/(S)VGA", IDM_VID_OVERSCAN MENUITEM "Cambiar contraste para pantalla &monocroma", IDM_VID_CGACON END - MENUITEM "&Medios", IDM_MEDIA + MENUITEM "&Medios", IDM_MEDIA POPUP "&Herramientas" BEGIN - MENUITEM "&Ajustes...", IDM_CONFIG - MENUITEM "&Actualizar iconos en barra de estado", IDM_UPDATE_ICONS + MENUITEM "&Ajustes...", IDM_CONFIG + MENUITEM "&Actualizar iconos en barra de estado", IDM_UPDATE_ICONS MENUITEM SEPARATOR - MENUITEM "Tomar c&aptura\tCtrl+F11", IDM_ACTION_SCREENSHOT + MENUITEM "Tomar c&aptura\tCtrl+F11", IDM_ACTION_SCREENSHOT MENUITEM SEPARATOR - MENUITEM "&Preferencias...", IDM_PREFERENCES + MENUITEM "&Preferencias...", IDM_PREFERENCES +#ifdef DISCORD MENUITEM "Habilitar integración con &Discord", IDM_DISCORD +#endif MENUITEM SEPARATOR - MENUITEM "&Ganancia de sonido...", IDM_SND_GAIN + MENUITEM "&Ganancia de sonido...", IDM_SND_GAIN #ifdef MTR_ENABLED MENUITEM SEPARATOR - MENUITEM "Comenzar traza\tCtrl+T", IDM_ACTION_BEGIN_TRACE - MENUITEM "Terminar traza\tCtrl+T", IDM_ACTION_END_TRACE + MENUITEM "Comenzar traza\tCtrl+T", IDM_ACTION_BEGIN_TRACE + MENUITEM "Terminar traza\tCtrl+T", IDM_ACTION_END_TRACE #endif END POPUP "&Ayuda" BEGIN - MENUITEM "&Documentación...", IDM_DOCS - MENUITEM "&Acerca de 86Box...", IDM_ABOUT + MENUITEM "&Documentación...", IDM_DOCS + MENUITEM "&Acerca de 86Box...", IDM_ABOUT END END -StatusBarMenu MENU DISCARDABLE +StatusBarMenu MENU DISCARDABLE BEGIN MENUITEM SEPARATOR END @@ -128,17 +137,17 @@ CassetteSubmenu MENU DISCARDABLE BEGIN POPUP "" BEGIN - MENUITEM "&Nueva imagen...", IDM_CASSETTE_IMAGE_NEW + MENUITEM "&Nueva imagen...", IDM_CASSETTE_IMAGE_NEW MENUITEM SEPARATOR - MENUITEM "Imagen &Existente...", IDM_CASSETTE_IMAGE_EXISTING - MENUITEM "Imagen Existente (&Sólo-lectura)...", IDM_CASSETTE_IMAGE_EXISTING_WP + MENUITEM "Imagen &Existente...", IDM_CASSETTE_IMAGE_EXISTING + MENUITEM "Imagen Existente (&Sólo-lectura)...", IDM_CASSETTE_IMAGE_EXISTING_WP MENUITEM SEPARATOR - MENUITEM "&Grabar", IDM_CASSETTE_RECORD - MENUITEM "&Reproducir", IDM_CASSETTE_PLAY - MENUITEM "&Rebobinar al inicio", IDM_CASSETTE_REWIND - MENUITEM "&Avance rápido al final", IDM_CASSETTE_FAST_FORWARD + MENUITEM "&Grabar", IDM_CASSETTE_RECORD + MENUITEM "&Reproducir", IDM_CASSETTE_PLAY + MENUITEM "&Rebobinar al inicio", IDM_CASSETTE_REWIND + MENUITEM "&Avance rápido al final", IDM_CASSETTE_FAST_FORWARD MENUITEM SEPARATOR - MENUITEM "E&xtraer", IDM_CASSETTE_EJECT + MENUITEM "E&xtraer", IDM_CASSETTE_EJECT END END @@ -146,9 +155,9 @@ CartridgeSubmenu MENU DISCARDABLE BEGIN POPUP "" BEGIN - MENUITEM "&Imagen...", IDM_CARTRIDGE_IMAGE + MENUITEM "&Imagen...", IDM_CARTRIDGE_IMAGE MENUITEM SEPARATOR - MENUITEM "E&xtraer", IDM_CARTRIDGE_EJECT + MENUITEM "E&xtraer", IDM_CARTRIDGE_EJECT END END @@ -156,14 +165,14 @@ FloppySubmenu MENU DISCARDABLE BEGIN POPUP "" BEGIN - MENUITEM "&Nueva imagen...", IDM_FLOPPY_IMAGE_NEW + MENUITEM "&Nueva imagen...", IDM_FLOPPY_IMAGE_NEW MENUITEM SEPARATOR - MENUITEM "Imagen &existente...", IDM_FLOPPY_IMAGE_EXISTING - MENUITEM "Imagen existente (&sólo-lectura)...", IDM_FLOPPY_IMAGE_EXISTING_WP + MENUITEM "Imagen &existente...", IDM_FLOPPY_IMAGE_EXISTING + MENUITEM "Imagen existente (&sólo-lectura)...", IDM_FLOPPY_IMAGE_EXISTING_WP MENUITEM SEPARATOR - MENUITEM "E&xportar a 86F...", IDM_FLOPPY_EXPORT_TO_86F + MENUITEM "E&xportar a 86F...", IDM_FLOPPY_EXPORT_TO_86F MENUITEM SEPARATOR - MENUITEM "E&xtraer", IDM_FLOPPY_EJECT + MENUITEM "E&xtraer", IDM_FLOPPY_EJECT END END @@ -171,12 +180,13 @@ CdromSubmenu MENU DISCARDABLE BEGIN POPUP "" BEGIN - MENUITEM "&Silenciar", IDM_CDROM_MUTE + MENUITEM "&Silenciar", IDM_CDROM_MUTE MENUITEM SEPARATOR - MENUITEM "E&xtraer disco", IDM_CDROM_EMPTY - MENUITEM "&Recargar imagen previa", IDM_CDROM_RELOAD + MENUITEM "E&xtraer disco", IDM_CDROM_EMPTY + MENUITEM "&Recargar imagen previa", IDM_CDROM_RELOAD MENUITEM SEPARATOR - MENUITEM "&Imagen...", IDM_CDROM_IMAGE + MENUITEM "&Imagen...", IDM_CDROM_IMAGE + MENUITEM "&Carpeta...", IDM_CDROM_DIR END END @@ -184,13 +194,13 @@ ZIPSubmenu MENU DISCARDABLE BEGIN POPUP "" BEGIN - MENUITEM "&Nueva imagen...", IDM_ZIP_IMAGE_NEW + MENUITEM "&Nueva imagen...", IDM_ZIP_IMAGE_NEW MENUITEM SEPARATOR - MENUITEM "Imagen &existente...", IDM_ZIP_IMAGE_EXISTING - MENUITEM "Imagen existente (&sólo-lectura)...", IDM_ZIP_IMAGE_EXISTING_WP + MENUITEM "Imagen &existente...", IDM_ZIP_IMAGE_EXISTING + MENUITEM "Imagen existente (&sólo-lectura)...", IDM_ZIP_IMAGE_EXISTING_WP MENUITEM SEPARATOR - MENUITEM "E&xtraer", IDM_ZIP_EJECT - MENUITEM "&Recargar imagen previa", IDM_ZIP_RELOAD + MENUITEM "E&xtraer", IDM_ZIP_EJECT + MENUITEM "&Recargar imagen previa", IDM_ZIP_RELOAD END END @@ -198,13 +208,13 @@ MOSubmenu MENU DISCARDABLE BEGIN POPUP "" BEGIN - MENUITEM "&Nueva imagen...", IDM_MO_IMAGE_NEW + MENUITEM "&Nueva imagen...", IDM_MO_IMAGE_NEW MENUITEM SEPARATOR - MENUITEM "Imagen &existente...", IDM_MO_IMAGE_EXISTING - MENUITEM "Imagen existente (&sólo-lectura)...", IDM_MO_IMAGE_EXISTING_WP + MENUITEM "Imagen &existente...", IDM_MO_IMAGE_EXISTING + MENUITEM "Imagen existente (&sólo-lectura)...", IDM_MO_IMAGE_EXISTING_WP MENUITEM SEPARATOR - MENUITEM "E&xtraer", IDM_MO_EJECT - MENUITEM "&Recargar imagen previa", IDM_MO_RELOAD + MENUITEM "E&xtraer", IDM_MO_EJECT + MENUITEM "&Recargar imagen previa", IDM_MO_RELOAD END END @@ -230,134 +240,150 @@ END // Dialog // -#define STR_PREFERENCES "Preferencias" -#define STR_SND_GAIN "Ganancia de Sonido" -#define STR_NEW_FLOPPY "Nueva Imagen" -#define STR_CONFIG "Ajustes" -#define STR_SPECIFY_DIM "Especificar Dimensiones de la Ventana Principal" +#define STR_PREFERENCES "Preferencias" +#define STR_SND_GAIN "Ganancia de Sonido" +#define STR_NEW_FLOPPY "Nueva Imagen" +#define STR_CONFIG "Ajustes" +#define STR_SPECIFY_DIM "Especificar Dimensiones de la Ventana Principal" -#define STR_OK "Aceptar" -#define STR_CANCEL "Cancelar" -#define STR_GLOBAL "Salvar estos ajustes como por &defecto globalmente" -#define STR_DEFAULT "&Por defecto" -#define STR_LANGUAGE "Idioma:" -#define STR_ICONSET "Juego de iconos:" +#define STR_OK "Aceptar" +#define STR_CANCEL "Cancelar" +#define STR_GLOBAL "Salvar estos ajustes como por &defecto globalmente" +#define STR_DEFAULT "&Por defecto" +#define STR_LANGUAGE "Idioma:" +#define STR_ICONSET "Juego de iconos:" -#define STR_GAIN "Ganancia" +#define STR_GAIN "Ganancia" -#define STR_FILE_NAME "Nombre de archivo:" -#define STR_DISK_SIZE "Tamaño de disco:" -#define STR_RPM_MODE "Modo RPM:" -#define STR_PROGRESS "Progreso:" +#define STR_FILE_NAME "Nombre de archivo:" +#define STR_DISK_SIZE "Tamaño de disco:" +#define STR_RPM_MODE "Modo RPM:" +#define STR_PROGRESS "Progreso:" -#define STR_WIDTH "Ancho:" -#define STR_HEIGHT "Alto:" -#define STR_LOCK_TO_SIZE "Bloquear a este tamaño" +#define STR_WIDTH "Ancho:" +#define STR_HEIGHT "Alto:" +#define STR_LOCK_TO_SIZE "Bloquear a este tamaño" -#define STR_MACHINE_TYPE "Tipo de máquina:" -#define STR_MACHINE "Máquina:" -#define STR_CONFIGURE "Configurar" -#define STR_CPU_TYPE "Tipo de CPU:" -#define STR_CPU_SPEED "Velocidad:" -#define STR_FPU "FPU:" -#define STR_WAIT_STATES "Estados en espera:" -#define STR_MB "MB" -#define STR_MEMORY "Memoria:" -#define STR_TIME_SYNC "Sincronización horaria" -#define STR_DISABLED "Deshabilitado" -#define STR_ENABLED_LOCAL "Habilitado (hora local)" -#define STR_ENABLED_UTC "Habilitado (UTC)" -#define STR_DYNAREC "Recompilador Dinámico" +#define STR_MACHINE_TYPE "Tipo de máquina:" +#define STR_MACHINE "Máquina:" +#define STR_CONFIGURE "Configurar" +#define STR_CPU_TYPE "Tipo de CPU:" +#define STR_CPU_SPEED "Velocidad:" +#define STR_FPU "FPU:" +#define STR_WAIT_STATES "Estados en espera:" +#define STR_MB "MB" +#define STR_MEMORY "Memoria:" +#define STR_TIME_SYNC "Sincronización horaria" +#define STR_DISABLED "Deshabilitado" +#define STR_ENABLED_LOCAL "Habilitado (hora local)" +#define STR_ENABLED_UTC "Habilitado (UTC)" +#define STR_DYNAREC "Recompilador Dinámico" +#define STR_SOFTFLOAT "Softfloat FPU" -#define STR_VIDEO "Vídeo:" -#define STR_VOODOO "Voodoo Graphics" +#define STR_VIDEO "Vídeo:" +#define STR_VIDEO_2 "Vídeo 2:" +#define STR_VOODOO "Voodoo Graphics" +#define STR_IBM8514 "IBM 8514/a Graphics" +#define STR_XGA "XGA Graphics" -#define STR_MOUSE "Ratón:" -#define STR_JOYSTICK "Mando:" -#define STR_JOY1 "Mando 1..." -#define STR_JOY2 "Mando 2..." -#define STR_JOY3 "Mando 3..." -#define STR_JOY4 "Mando 4..." +#define STR_MOUSE "Ratón:" +#define STR_JOYSTICK "Mando:" +#define STR_JOY1 "Mando 1..." +#define STR_JOY2 "Mando 2..." +#define STR_JOY3 "Mando 3..." +#define STR_JOY4 "Mando 4..." -#define STR_SOUND "Tarjeta de sonido:" -#define STR_MIDI_OUT "Dispositivo MIDI de salida:" -#define STR_MIDI_IN "Dispositivo MIDI de entrada:" -#define STR_MPU401 "MPU-401 independiente" -#define STR_SSI "Innovation SSI-2001" -#define STR_CMS "CMS / Game Blaster" -#define STR_GUS "Gravis Ultrasound" -#define STR_FLOAT "Usar sonido FLOAT32" +#define STR_SOUND1 "Tarjeta de sonido 1:" +#define STR_SOUND2 "Tarjeta de sonido 2:" +#define STR_SOUND3 "Tarjeta de sonido 3:" +#define STR_SOUND4 "Tarjeta de sonido 4:" +#define STR_MIDI_OUT "Dispositivo MIDI de salida:" +#define STR_MIDI_IN "Dispositivo MIDI de entrada:" +#define STR_MPU401 "MPU-401 independiente" +#define STR_FLOAT "Usar sonido FLOAT32" +#define STR_FM_DRIVER "Controlador de sintet. FM" +#define STR_FM_DRV_NUKED "Nuked (más preciso)" +#define STR_FM_DRV_YMFM "YMFM (más rápido)" -#define STR_NET_TYPE "Tipo de red:" -#define STR_PCAP "Dispositivo PCap:" -#define STR_NET "Adaptador de red:" +#define STR_NET_TYPE "Tipo de red:" +#define STR_PCAP "Dispositivo PCap:" +#define STR_NET "Adaptador de red:" +#define STR_NET1 "Network card 1:" +#define STR_NET2 "Network card 2:" +#define STR_NET3 "Network card 3:" +#define STR_NET4 "Network card 4:" -#define STR_COM1 "Dispositivo COM1:" -#define STR_COM2 "Dispositivo COM2:" -#define STR_COM3 "Dispositivo COM3:" -#define STR_COM4 "Dispositivo COM4:" -#define STR_LPT1 "Dispositivo LPT1:" -#define STR_LPT2 "Dispositivo LPT2:" -#define STR_LPT3 "Dispositivo LPT3:" -#define STR_LPT4 "Dispositivo LPT4:" -#define STR_SERIAL1 "Puerto serie 1" -#define STR_SERIAL2 "Puerto serie 2" -#define STR_SERIAL3 "Puerto serie 3" -#define STR_SERIAL4 "Puerto serie 4" -#define STR_PARALLEL1 "Puerto paralelo 1" -#define STR_PARALLEL2 "Puerto paralelo 2" -#define STR_PARALLEL3 "Puerto paralelo 3" -#define STR_PARALLEL4 "Puerto paralelo 4" +#define STR_COM1 "Dispositivo COM1:" +#define STR_COM2 "Dispositivo COM2:" +#define STR_COM3 "Dispositivo COM3:" +#define STR_COM4 "Dispositivo COM4:" +#define STR_LPT1 "Dispositivo LPT1:" +#define STR_LPT2 "Dispositivo LPT2:" +#define STR_LPT3 "Dispositivo LPT3:" +#define STR_LPT4 "Dispositivo LPT4:" +#define STR_SERIAL1 "Puerto serie 1" +#define STR_SERIAL2 "Puerto serie 2" +#define STR_SERIAL3 "Puerto serie 3" +#define STR_SERIAL4 "Puerto serie 4" +#define STR_PARALLEL1 "Puerto paralelo 1" +#define STR_PARALLEL2 "Puerto paralelo 2" +#define STR_PARALLEL3 "Puerto paralelo 3" +#define STR_PARALLEL4 "Puerto paralelo 4" +#define STR_SERIAL_PASS1 "Serial port passthrough 1" +#define STR_SERIAL_PASS2 "Serial port passthrough 2" +#define STR_SERIAL_PASS3 "Serial port passthrough 3" +#define STR_SERIAL_PASS4 "Serial port passthrough 4" -#define STR_HDC "Controladora HD:" -#define STR_FDC "Controladora FD:" -#define STR_IDE_TER "Tercera controladora IDE" -#define STR_IDE_QUA "Cuarta controladora IDE" -#define STR_SCSI "SCSI" -#define STR_SCSI_1 "Controladora 1:" -#define STR_SCSI_2 "Controladora 2:" -#define STR_SCSI_3 "Controladora 3:" -#define STR_SCSI_4 "Controladora 4:" -#define STR_CASSETTE "Cassette" +#define STR_HDC "Controladora HD:" +#define STR_FDC "Controladora FD:" +#define STR_IDE_TER "Tercera controladora IDE" +#define STR_IDE_QUA "Cuarta controladora IDE" +#define STR_SCSI "SCSI" +#define STR_SCSI_1 "Controladora 1:" +#define STR_SCSI_2 "Controladora 2:" +#define STR_SCSI_3 "Controladora 3:" +#define STR_SCSI_4 "Controladora 4:" +#define STR_CASSETTE "Cassette" -#define STR_HDD "Discos duros:" -#define STR_NEW "&Nuevo..." -#define STR_EXISTING "&Existente..." -#define STR_REMOVE "E&liminar" -#define STR_BUS "Bus:" -#define STR_CHANNEL "Canal:" -#define STR_ID "ID:" +#define STR_HDD "Discos duros:" +#define STR_NEW "&Nuevo..." +#define STR_EXISTING "&Existente..." +#define STR_REMOVE "E&liminar" +#define STR_BUS "Bus:" +#define STR_CHANNEL "Canal:" +#define STR_ID "ID:" +#define STR_SPEED "Speed:" -#define STR_SPECIFY "E&specificar..." -#define STR_SECTORS "Sectores:" -#define STR_HEADS "Cabezas:" -#define STR_CYLS "Cilindros:" -#define STR_SIZE_MB "Tamaño (MB):" -#define STR_TYPE "Tipo:" -#define STR_IMG_FORMAT "Formato de imagen:" -#define STR_BLOCK_SIZE "Tamaño de bloque:" +#define STR_SPECIFY "E&specificar..." +#define STR_SECTORS "Sectores:" +#define STR_HEADS "Cabezas:" +#define STR_CYLS "Cilindros:" +#define STR_SIZE_MB "Tamaño (MB):" +#define STR_TYPE "Tipo:" +#define STR_IMG_FORMAT "Formato de imagen:" +#define STR_BLOCK_SIZE "Tamaño de bloque:" -#define STR_FLOPPY_DRIVES "Unidades de disquete:" -#define STR_TURBO "Temporizaciones Turbo" -#define STR_CHECKBPB "Chequear BPB" -#define STR_CDROM_DRIVES "Unidades de CD-ROM:" -#define STR_CD_SPEED "Velocidad:" +#define STR_FLOPPY_DRIVES "Unidades de disquete:" +#define STR_TURBO "Temporizaciones Turbo" +#define STR_CHECKBPB "Chequear BPB" +#define STR_CDROM_DRIVES "Unidades de CD-ROM:" +#define STR_CD_SPEED "Velocidad:" -#define STR_MO_DRIVES "Unidades MO:" -#define STR_ZIP_DRIVES "Unidades ZIP:" -#define STR_250 "ZIP 250" +#define STR_MO_DRIVES "Unidades MO:" +#define STR_ZIP_DRIVES "Unidades ZIP:" +#define STR_250 "ZIP 250" -#define STR_ISARTC "ISA RTC:" -#define STR_ISAMEM "Expansión de Memoria ISA" -#define STR_ISAMEM_1 "Tarjeta 1:" -#define STR_ISAMEM_2 "Tarjeta 2:" -#define STR_ISAMEM_3 "Tarjeta 3:" -#define STR_ISAMEM_4 "Tarjeta 4:" -#define STR_BUGGER "Dispositivo ISABugger" -#define STR_POSTCARD "Tarjeta POST" +#define STR_ISARTC "ISA RTC:" +#define STR_ISAMEM "Expansión de Memoria ISA" +#define STR_ISAMEM_1 "Tarjeta 1:" +#define STR_ISAMEM_2 "Tarjeta 2:" +#define STR_ISAMEM_3 "Tarjeta 3:" +#define STR_ISAMEM_4 "Tarjeta 4:" +#define STR_BUGGER "Dispositivo ISABugger" +#define STR_POSTCARD "Tarjeta POST" -#define FONT_SIZE 9 -#define FONT_NAME "Segoe UI" +#define FONT_SIZE 9 +#define FONT_NAME "Segoe UI" #include "dialogs.rc" @@ -366,194 +392,188 @@ END // String Table // -STRINGTABLE DISCARDABLE +STRINGTABLE DISCARDABLE BEGIN - 2048 "86Box" - IDS_2049 "Error" - IDS_2050 "Error fatal" - IDS_2051 " - PAUSED" - IDS_2052 "Pulsa Ctrl+Alt+PgDn para volver a modo ventana." - IDS_2053 "Velocidad" - IDS_2054 "ZIP %03i %i (%s): %ls" - IDS_2055 "Imagenes ZIP (*.IM?;*.ZDI)\0*.IM?;*.ZDI\0" - IDS_2056 "86Box no pudo encontrar ninguna imagen ROM usable.\n\nPor favor descarga un grupo de imágenes y extráelas en el directorio ""roms""." - IDS_2057 "(vacío)" - IDS_2058 "Imagenes ZIP (*.IM?;*.ZDI)\0*.IM?;*.ZDI\0All files (*.*)\0*.*\0" - IDS_2059 "Turbo" - IDS_2060 "On" - IDS_2061 "Off" - IDS_2062 "Todas las imagenes (*.86F;*.DSK;*.FLP;*.IM?;*.*FD?)\0*.86F;*.DSK;*.FLP;*.IM?;*.*FD?\0Basic sector images (*.DSK;*.FLP;*.IM?;*.*FD?)\0*.DSK;*.FLP;*.IM?;*.IMG;*.*FD?\0Surface images (*.86F)\0*.86F\0" - IDS_2063 "La máquina ""%hs"" no está disponible debido a ROMs faltantes en el directorio roms/machines. Cambiando a una máquina disponible." + 2048 "86Box" + IDS_2049 "Error" + IDS_2050 "Error fatal" + IDS_2051 " - PAUSED" + IDS_2052 "Pulsa Ctrl+Alt+PgDn para volver a modo ventana." + IDS_2053 "Velocidad" + IDS_2054 "ZIP %03i %i (%s): %ls" + IDS_2055 "Imagenes ZIP (*.IM?;*.ZDI)\0*.IM?;*.ZDI\0" + IDS_2056 "86Box no pudo encontrar ninguna imagen ROM usable.\n\nPor favor descarga un grupo de imágenes y extráelas en el directorio ""roms""." + IDS_2057 "(vacío)" + IDS_2058 "Imagenes ZIP (*.IM?;*.ZDI)\0*.IM?;*.ZDI\0All files (*.*)\0*.*\0" + IDS_2059 "Turbo" + IDS_2060 "On" + IDS_2061 "Off" + IDS_2062 "Todas las imagenes (*.86F;*.DSK;*.FLP;*.IM?;*.*FD?)\0*.86F;*.DSK;*.FLP;*.IM?;*.*FD?\0Basic sector images (*.DSK;*.FLP;*.IM?;*.*FD?)\0*.DSK;*.FLP;*.IM?;*.IMG;*.*FD?\0Surface images (*.86F)\0*.86F\0" + IDS_2063 "La máquina ""%hs"" no está disponible debido a ROMs faltantes en el directorio roms/machines. Cambiando a una máquina disponible." END -STRINGTABLE DISCARDABLE +STRINGTABLE DISCARDABLE BEGIN - IDS_2064 "La tarjeta de vídeo ""%hs"" no está disponible debido a ROMs faltantes en el directorio roms/machines. Cambiando a una tarjeta de vídeo disponible." - IDS_2065 "Máquina" - IDS_2066 "Vídeo" - IDS_2067 "Dispositivos de Entrada" - IDS_2068 "Sonido" - IDS_2069 "Red" - IDS_2070 "Puertos (COM y LPT)" - IDS_2071 "Controladoras de Almacenamiento" - IDS_2072 "Discos Duros" - IDS_2073 "Disquetes y unidades de CD-ROM" - IDS_2074 "Otros dispositivos extraíbles" - IDS_2075 "Otros periféricos" - IDS_2076 "Imágenes de superficie (*.86F)\0*.86F\0" - IDS_2077 "Haz click para capturar el ratón" - IDS_2078 "Pulsa F8+F12 para liberar el ratón" - IDS_2079 "Pulsa F8+F12 o el botón central para liberar el ratón" + IDS_2064 "La tarjeta de vídeo ""%hs"" no está disponible debido a ROMs faltantes en el directorio roms/machines. Cambiando a una tarjeta de vídeo disponible." + IDS_2065 "Máquina" + IDS_2066 "Vídeo" + IDS_2067 "Dispositivos de Entrada" + IDS_2068 "Sonido" + IDS_2069 "Red" + IDS_2070 "Puertos (COM y LPT)" + IDS_2071 "Controladoras de Almacenamiento" + IDS_2072 "Discos Duros" + IDS_2073 "Disquetes y unidades de CD-ROM" + IDS_2074 "Otros dispositivos extraíbles" + IDS_2075 "Otros periféricos" + IDS_2076 "Imágenes de superficie (*.86F)\0*.86F\0" + IDS_2077 "Haz click para capturar el ratón" + IDS_2078 "Pulsa F8+F12 para liberar el ratón" + IDS_2079 "Pulsa F8+F12 o el botón central para liberar el ratón" END -STRINGTABLE DISCARDABLE +STRINGTABLE DISCARDABLE BEGIN - IDS_2080 "Incapaz de inicializar FluidSynth" - IDS_2081 "Bus" - IDS_2082 "Archivo" - IDS_2083 "C" - IDS_2084 "H" - IDS_2085 "S" - IDS_2086 "MB" - IDS_2087 "Chequear BPB" - IDS_2088 "KB" - IDS_2089 "Incapaz de inicializar el renderizador de vídeo." - IDS_2090 "Por defecto" - IDS_2091 "%i estado(s) de Espera" - IDS_2092 "Tipo" - IDS_2093 "Incapaz de configurar PCap" - IDS_2094 "No se encontraron dispositivos PCap" - IDS_2095 "Dispositivo PCap inválido" - IDS_2096 "Mando(s) de 2 botones estándar" - IDS_2097 "Mando de 4 botones estándar" - IDS_2098 "Mando de 6 botones estándar" - IDS_2099 "Mando de 8 botones estándar" - IDS_2100 "CH Flightstick Pro" - IDS_2101 "Microsoft SideWinder Pad" - IDS_2102 "Thrustmaster Flight Control System" - IDS_2103 "Ninguno" - IDS_2104 "Incapaz de cargar aceleradores de teclado." - IDS_2105 "Incapaz de registrar entrada directa." - IDS_2106 "%u" - IDS_2107 "%u MB (CHS: %i, %i, %i)" - IDS_2108 "Disquete %i (%s): %ls" - IDS_2109 "Todas las Imágenes (*.0??;*.1??;*.??0;*.86F;*.BIN;*.CQ?;*.D??;*.FLP;*.HDM;*.IM?;*.JSON;*.TD0;*.*FD?;*.MFM;*.XDF)\0*.0??;*.1??;*.??0;*.86F;*.BIN;*.CQ?;*.D??;*.FLP;*.HDM;*.IM?;*.JSON;*.TD0;*.*FD?;*.MFM;*.XDF\0Advanced sector images (*.IMD;*.JSON;*.TD0)\0*.IMD;*.JSON;*.TD0\0Basic sector images (*.0??;*.1??;*.??0;*.BIN;*.CQ?;*.D??;*.FLP;*.HDM;*.IM?;*.XDF;*.*FD?)\0*.0??;*.1??;*.??0;*.BIN;*.CQ?;*.D??;*.FLP;*.HDM;*.IM?;*.XDF;*.*FD?\0Flux images (*.FDI)\0*.FDI\0Surface images (*.86F;*.MFM)\0*.86F;*.MFM\0All files (*.*)\0*.*\0" - IDS_2110 "Incapaz de inicializar FreeType" - IDS_2111 "Incapaz de inicializar SDL, se requiere SDL2.dll" - IDS_2112 "¿Seguro que quieres resetear la máquina emulada?" - IDS_2113 "¿Seguro que quieres cerrar 86Box?" - IDS_2114 "Incapaz de inicializar Ghostscript" - IDS_2115 "MO %i (%ls): %ls" - IDS_2116 "Imágenes de MO (*.IM?;*.MDI)\0*.IM?;*.MDI\0All files (*.*)\0*.*\0" - IDS_2117 "¡Bienvenido a 86Box!" - IDS_2118 "Controladora interna" - IDS_2119 "Salir" - IDS_2120 "No se encontraron ROMs" - IDS_2121 "¿Quieres guardar los ajustes?" - IDS_2122 "Se hará hard reset de la máquina emulada." - IDS_2123 "Guardar" - IDS_2124 "Acerca de 86Box" - IDS_2125 "86Box v" EMU_VERSION + IDS_2081 "Bus" + IDS_2082 "Archivo" + IDS_2083 "C" + IDS_2084 "H" + IDS_2085 "S" + IDS_2086 "MB" + IDS_2087 "Speed" + IDS_2088 "Chequear BPB" + IDS_2089 "KB" + IDS_2090 "Incapaz de inicializar el renderizador de vídeo." + IDS_2091 "Por defecto" + IDS_2092 "%i estado(s) de Espera" + IDS_2093 "Tipo" + IDS_2094 "Incapaz de configurar PCap" + IDS_2095 "No se encontraron dispositivos PCap" + IDS_2096 "Dispositivo PCap inválido" + IDS_2097 "Mando(s) de 2 botones estándar" + IDS_2098 "Mando de 4 botones estándar" + IDS_2099 "Mando de 6 botones estándar" + IDS_2100 "Mando de 8 botones estándar" + IDS_2101 "CH Flightstick Pro" + IDS_2102 "Microsoft SideWinder Pad" + IDS_2103 "Thrustmaster Flight Control System" + IDS_2104 "Ninguno" + IDS_2105 "Incapaz de cargar aceleradores de teclado." + IDS_2106 "Incapaz de registrar entrada directa." + IDS_2107 "%u" + IDS_2108 "%u MB (CHS: %i, %i, %i)" + IDS_2109 "Disquete %i (%s): %ls" + IDS_2110 "Todas las Imágenes (*.0??;*.1??;*.??0;*.86F;*.BIN;*.CQ?;*.D??;*.FLP;*.HDM;*.IM?;*.JSON;*.TD0;*.*FD?;*.MFM;*.XDF)\0*.0??;*.1??;*.??0;*.86F;*.BIN;*.CQ?;*.D??;*.FLP;*.HDM;*.IM?;*.JSON;*.TD0;*.*FD?;*.MFM;*.XDF\0Advanced sector images (*.IMD;*.JSON;*.TD0)\0*.IMD;*.JSON;*.TD0\0Basic sector images (*.0??;*.1??;*.??0;*.BIN;*.CQ?;*.D??;*.FLP;*.HDM;*.IM?;*.XDF;*.*FD?)\0*.0??;*.1??;*.??0;*.BIN;*.CQ?;*.D??;*.FLP;*.HDM;*.IM?;*.XDF;*.*FD?\0Flux images (*.FDI)\0*.FDI\0Surface images (*.86F;*.MFM)\0*.86F;*.MFM\0All files (*.*)\0*.*\0" + IDS_2112 "Incapaz de inicializar SDL, se requiere SDL2.dll" + IDS_2113 "¿Seguro que quieres resetear la máquina emulada?" + IDS_2114 "¿Seguro que quieres cerrar 86Box?" + IDS_2115 "Incapaz de inicializar Ghostscript" + IDS_2116 "MO %i (%ls): %ls" + IDS_2117 "Imágenes de MO (*.IM?;*.MDI)\0*.IM?;*.MDI\0All files (*.*)\0*.*\0" + IDS_2118 "¡Bienvenido a 86Box!" + IDS_2119 "Controladora interna" + IDS_2120 "Salir" + IDS_2121 "No se encontraron ROMs" + IDS_2122 "¿Quieres guardar los ajustes?" + IDS_2123 "Se hará hard reset de la máquina emulada." + IDS_2124 "Guardar" + IDS_2125 "Acerca de 86Box" + IDS_2126 "86Box v" EMU_VERSION - IDS_2126 "Un emulador de ordenadores antigüos\n\nAutores: Sarah Walker, Miran Grca, Fred N. van Kempen (waltje), SA1988, Tiseno100, reenigne, leilei, JohnElliott, greatpsycho, y otros.\n\nLiberado bajo la GNU General Public License versión 2 o posterior. Ver LICENSE para más información." - IDS_2127 "Aceptar" - IDS_2128 "Hardware no disponible" + IDS_2127 "Un emulador de ordenadores antigüos\n\nAutores: Miran GrÄa (OBattler), RichardG867, Jasmine Iwanek, TC1995, coldbrewed, Teemu Korhonen (Manaatti), Joakim L. Gilje, Adrien Moulin (elyosh), Daniel Balsom (gloriouscow), Cacodemon345, Fred N. van Kempen (waltje), Tiseno100, reenigne, y otros.\n\nWith previous core contributions from Sarah Walker, leilei, JohnElliott, greatpsycho, y otros.\n\nLiberado bajo la GNU General Public License versión 2 o posterior. Ver LICENSE para más información." + IDS_2128 "Aceptar" + IDS_2129 "Hardware no disponible" #ifdef _WIN32 #define LIB_NAME_PCAP "WinPcap" #else #define LIB_NAME_PCAP "libpcap" #endif - IDS_2129 "Asegúrate de que " LIB_NAME_PCAP " está instalado y de que estás en una conexión de red compatible con " LIB_NAME_PCAP "." - IDS_2130 "Configuración inválida" -#ifdef _WIN32 -#define LIB_NAME_FREETYPE "freetype.dll" -#else -#define LIB_NAME_FREETYPE "libfreetype" -#endif - IDS_2131 LIB_NAME_FREETYPE " es necesaria para emulación de impresión ESC/P." + IDS_2130 "Asegúrate de que " LIB_NAME_PCAP " está instalado y de que estás en una conexión de red compatible con " LIB_NAME_PCAP "." + IDS_2131 "Configuración inválida" #ifdef _WIN32 #define LIB_NAME_GS "gsdll32.dll" #else #define LIB_NAME_GS "libgs" #endif - IDS_2132 LIB_NAME_GS " es necesaria para la conversión automática de archivos PostScript a PDF.\n\nCualquier documento enviado a la impresora genérica postScript se guardará como archivo PostScript (.ps)." -#ifdef _WIN32 -#define LIB_NAME_FLUIDSYNTH "libfluidsynth.dll" -#else -#define LIB_NAME_FLUIDSYNTH "libfluidsynth" -#endif - IDS_2133 LIB_NAME_FLUIDSYNTH " es necesario para salida MIDI FluidSynth." - IDS_2134 "Entrando en modo pantalla completa" - IDS_2135 "No mostrar más este mensaje" - IDS_2136 "No salir" - IDS_2137 "Resetear" - IDS_2138 "No resetear" - IDS_2139 "Imágenes de MO (*.IM?;*.MDI)\0*.IM?;*.MDI\0All files (*.*)\0*.*\0" - IDS_2140 "Imágenes de CD-ROM (*.ISO;*.CUE)\0*.ISO;*.CUE\0All files (*.*)\0*.*\0" - IDS_2141 "%hs Configuración de Dispositivo" - IDS_2142 "Monitor en modo ahorro" - IDS_2143 "Shaders OpenGL (*.GLSL)\0*.GLSL\0All files (*.*)\0*.*\0" - IDS_2144 "Opciones OpenGL" - IDS_2145 "Estás cargando una configuración no soportada" - IDS_2146 "El Filtrado de tipo de CPU basado en máquina seleccionada está deshabilitado para la esta máquina.\n\nEsto hace posible seleccionar una CPU que sea incompatible con esta máquina. Por ello, pueden aparecer incompatibilidader con la BIOS de la máquina u otro software.\n\nActivar este ajuste no está oficialmente soportado y cualquier reporte de fallo puede ser cerrado como inválido." - IDS_2147 "Continuar" - IDS_2148 "Cassette: %s" - IDS_2149 "Imágenes de Cassette (*.PCM;*.RAW;*.WAV;*.CAS)\0*.PCM;*.RAW;*.WAV;*.CAS\0All files (*.*)\0*.*\0" - IDS_2150 "Cartucho %i: %ls" - IDS_2151 "Imágenes de Cartucho (*.A;*.B;*.JRC)\0*.A;*.B;*.JRC\0All files (*.*)\0*.*\0" - IDS_2152 "Error initializing renderer" - IDS_2153 "OpenGL (3.0 Core) renderer could not be initialized. Use another renderer." - IDS_2154 "Resume execution" - IDS_2155 "Pause execution" - IDS_2156 "Press Ctrl+Alt+Del" - IDS_2157 "Press Ctrl+Alt+Esc" - IDS_2158 "Hard reset" - IDS_2159 "ACPI shutdown" - IDS_2160 "Settings" + IDS_2133 LIB_NAME_GS " es necesaria para la conversión automática de archivos PostScript a PDF.\n\nCualquier documento enviado a la impresora genérica postScript se guardará como archivo PostScript (.ps)." + IDS_2135 "Entrando en modo pantalla completa" + IDS_2136 "No mostrar más este mensaje" + IDS_2137 "No salir" + IDS_2138 "Resetear" + IDS_2139 "No resetear" + IDS_2140 "Imágenes de MO (*.IM?;*.MDI)\0*.IM?;*.MDI\0All files (*.*)\0*.*\0" + IDS_2141 "Imágenes de CD-ROM (*.ISO;*.CUE)\0*.ISO;*.CUE\0All files (*.*)\0*.*\0" + IDS_2142 "%hs Configuración de Dispositivo" + IDS_2143 "Monitor en modo ahorro" + IDS_2144 "Shaders OpenGL (*.GLSL)\0*.GLSL\0All files (*.*)\0*.*\0" + IDS_2145 "Opciones OpenGL" + IDS_2146 "Estás cargando una configuración no soportada" + IDS_2147 "El Filtrado de tipo de CPU basado en máquina seleccionada está deshabilitado para la esta máquina.\n\nEsto hace posible seleccionar una CPU que sea incompatible con esta máquina. Por ello, pueden aparecer incompatibilidader con la BIOS de la máquina u otro software.\n\nActivar este ajuste no está oficialmente soportado y cualquier reporte de fallo puede ser cerrado como inválido." + IDS_2148 "Continuar" + IDS_2149 "Cassette: %s" + IDS_2150 "Imágenes de Cassette (*.PCM;*.RAW;*.WAV;*.CAS)\0*.PCM;*.RAW;*.WAV;*.CAS\0All files (*.*)\0*.*\0" + IDS_2151 "Cartucho %i: %ls" + IDS_2152 "Imágenes de Cartucho (*.A;*.B;*.JRC)\0*.A;*.B;*.JRC\0All files (*.*)\0*.*\0" + IDS_2153 "Error initializing renderer" + IDS_2154 "OpenGL (3.0 Core) renderer could not be initialized. Use another renderer." + IDS_2155 "Resume execution" + IDS_2156 "Pause execution" + IDS_2157 "Press Ctrl+Alt+Del" + IDS_2158 "Press Ctrl+Alt+Esc" + IDS_2159 "Hard reset" + IDS_2160 "ACPI shutdown" + IDS_2161 "Settings" + IDS_2162 "Type" + IDS_2163 "No Dynarec" + IDS_2164 "Old Dynarec" + IDS_2165 "New Dynarec" + IDS_2166 "Video card #2 ""%hs"" is not available due to missing ROMs in the roms/video directory. Disabling the second video card." + IDS_2167 "Failed to initialize network driver" + IDS_2168 "The network configuration will be switched to the null driver" END -STRINGTABLE DISCARDABLE +STRINGTABLE DISCARDABLE BEGIN IDS_4096 "Disco duro (%s)" - IDS_4097 "%01i:%01i" - IDS_4098 "%01i" - IDS_4099 "Nunca hubo unidades de CD-ROM MFM/RLL o ESDI" - IDS_4100 "A medida..." - IDS_4101 "A medida (grande)..." - IDS_4102 "Añadir Nuevo Disco Duro" - IDS_4103 "Añadir Disco Duro Existente" - IDS_4104 "Las imágenes de disco HDI no pueden superar los 4 GB." - IDS_4105 "Las imágenes de disco no pueden superar los 127 GB." - IDS_4106 "Imágenes de Disco Duro (*.HD?;*.IM?;*.VHD)\0*.HD?;*.IM?;*.VHD\0All files (*.*)\0*.*\0" - IDS_4107 "No se pudo leer el archivo" - IDS_4108 "No se pudo escribir el archivo" - IDS_4109 "No se soportan las imágenes HDI o HDX con un tamaño de sector diferente a 512." - IDS_4110 "No se soporta aún el USB" - IDS_4111 "La imagen de disco ya existe" - IDS_4112 "Por favor especifique un nombre de archivo válido." - IDS_4113 "Imagen de disco creada" - IDS_4114 "Asegúrese de que el archivo existe y es leíble." - IDS_4115 "Asegúrese de que el archivo en un directorio con permiso de escritura." - IDS_4116 "Imagen de disco demasiado grande" - IDS_4117 "Recuerde particionar y formatear la nueva unidad." - IDS_4118 "El archivo selecionado será sobreescrito. ¿Está seguro de querer usarlo?" - IDS_4119 "Imagen de disco no soportada" - IDS_4120 "Sobreescribir" - IDS_4121 "No sobreescribir" - IDS_4122 "Imagen plana (.img)" - IDS_4123 "Imagen HDI (.hdi)" - IDS_4124 "Imagen HDX (.hdx)" - IDS_4125 "VHD de tamaño fijo (.vhd)" - IDS_4126 "VHD de tamaño dinámico (.vhd)" - IDS_4127 "VHD diferencial (.vhd)" - IDS_4128 "Bloques grandes (2 MB)" - IDS_4129 "Bloques pequeños (512 KB)" - IDS_4130 "Archivos VHD (*.VHD)\0*.VHD\0All files (*.*)\0*.*\0" - IDS_4131 "Seleccione el VHD padre" - IDS_4132 "Esto puede deberse a que la imagen padre se modificó después de que la imagen diferencial se crease.\n\nTambién puede ocurrir si las imágenes fueron movidas o copiadas, o por un fallo en el programa que creó este disco.\n\n¿Quiere corregir los registros de tiempo?" - IDS_4133 "Las marcas de tiempo del padre e hijo no coinciden" - IDS_4134 "No se pudo corregir la marca de tiempo del VHD." - IDS_4135 "%01i:%02i" + IDS_4097 "%01i:%01i" + IDS_4098 "%01i" + IDS_4099 "Nunca hubo unidades de CD-ROM MFM/RLL o ESDI" + IDS_4100 "A medida..." + IDS_4101 "A medida (grande)..." + IDS_4102 "Añadir Nuevo Disco Duro" + IDS_4103 "Añadir Disco Duro Existente" + IDS_4104 "Las imágenes de disco HDI no pueden superar los 4 GB." + IDS_4105 "Las imágenes de disco no pueden superar los 127 GB." + IDS_4106 "Imágenes de Disco Duro (*.HD?;*.IM?;*.VHD)\0*.HD?;*.IM?;*.VHD\0All files (*.*)\0*.*\0" + IDS_4107 "No se pudo leer el archivo" + IDS_4108 "No se pudo escribir el archivo" + IDS_4109 "No se soportan las imágenes HDI o HDX con un tamaño de sector diferente a 512." + IDS_4110 "No se soporta aún el USB" + IDS_4111 "La imagen de disco ya existe" + IDS_4112 "Por favor especifique un nombre de archivo válido." + IDS_4113 "Imagen de disco creada" + IDS_4114 "Asegúrese de que el archivo existe y es leíble." + IDS_4115 "Asegúrese de que el archivo en un directorio con permiso de escritura." + IDS_4116 "Imagen de disco demasiado grande" + IDS_4117 "Recuerde particionar y formatear la nueva unidad." + IDS_4118 "El archivo selecionado será sobreescrito. ¿Está seguro de querer usarlo?" + IDS_4119 "Imagen de disco no soportada" + IDS_4120 "Sobreescribir" + IDS_4121 "No sobreescribir" + IDS_4122 "Imagen plana (.img)" + IDS_4123 "Imagen HDI (.hdi)" + IDS_4124 "Imagen HDX (.hdx)" + IDS_4125 "VHD de tamaño fijo (.vhd)" + IDS_4126 "VHD de tamaño dinámico (.vhd)" + IDS_4127 "VHD diferencial (.vhd)" + IDS_4128 "Bloques grandes (2 MB)" + IDS_4129 "Bloques pequeños (512 KB)" + IDS_4130 "Archivos VHD (*.VHD)\0*.VHD\0All files (*.*)\0*.*\0" + IDS_4131 "Seleccione el VHD padre" + IDS_4132 "Esto puede deberse a que la imagen padre se modificó después de que la imagen diferencial se crease.\n\nTambién puede ocurrir si las imágenes fueron movidas o copiadas, o por un fallo en el programa que creó este disco.\n\n¿Quiere corregir los registros de tiempo?" + IDS_4133 "Las marcas de tiempo del padre e hijo no coinciden" + IDS_4134 "No se pudo corregir la marca de tiempo del VHD." + IDS_4135 "%01i:%02i" IDS_4352 "MFM/RLL" IDS_4353 "XTA" @@ -562,56 +582,56 @@ BEGIN IDS_4356 "ATAPI" IDS_4357 "SCSI" - IDS_4608 "MFM/RLL (%01i:%01i)" - IDS_4609 "XTA (%01i:%01i)" - IDS_4610 "ESDI (%01i:%01i)" - IDS_4611 "IDE (%01i:%01i)" - IDS_4612 "ATAPI (%01i:%01i)" - IDS_4613 "SCSI (%01i:%02i)" + IDS_4608 "MFM/RLL (%01i:%01i)" + IDS_4609 "XTA (%01i:%01i)" + IDS_4610 "ESDI (%01i:%01i)" + IDS_4611 "IDE (%01i:%01i)" + IDS_4612 "ATAPI (%01i:%01i)" + IDS_4613 "SCSI (%01i:%02i)" - IDS_5120 "CD-ROM %i (%s): %s" + IDS_5120 "CD-ROM %i (%s): %s" - IDS_5376 "Deshabilitado" - IDS_5381 "ATAPI" + IDS_5376 "Deshabilitado" + IDS_5381 "ATAPI" IDS_5382 "SCSI" - IDS_5632 "Deshabilitado" - IDS_5637 "ATAPI (%01i:%01i)" + IDS_5632 "Deshabilitado" + IDS_5637 "ATAPI (%01i:%01i)" IDS_5638 "SCSI (%01i:%02i)" - IDS_5888 "160 kB" - IDS_5889 "180 kB" - IDS_5890 "320 kB" - IDS_5891 "360 kB" - IDS_5892 "640 kB" - IDS_5893 "720 kB" - IDS_5894 "1.2 MB" - IDS_5895 "1.25 MB" - IDS_5896 "1.44 MB" - IDS_5897 "DMF (cluster 1024)" - IDS_5898 "DMF (cluster 2048)" - IDS_5899 "2.88 MB" - IDS_5900 "ZIP 100" - IDS_5901 "ZIP 250" - IDS_5902 "3.5"" 128 MB (ISO 10090)" - IDS_5903 "3.5"" 230 MB (ISO 13963)" - IDS_5904 "3.5"" 540 MB (ISO 15498)" - IDS_5905 "3.5"" 640 MB (ISO 15498)" - IDS_5906 "3.5"" 1.3 GB (GigaMO)" - IDS_5907 "3.5"" 2.3 GB (GigaMO 2)" - IDS_5908 "5.25"" 600 MB" - IDS_5909 "5.25"" 650 MB" - IDS_5910 "5.25"" 1 GB" - IDS_5911 "5.25"" 1.3 GB" + IDS_5888 "160 kB" + IDS_5889 "180 kB" + IDS_5890 "320 kB" + IDS_5891 "360 kB" + IDS_5892 "640 kB" + IDS_5893 "720 kB" + IDS_5894 "1.2 MB" + IDS_5895 "1.25 MB" + IDS_5896 "1.44 MB" + IDS_5897 "DMF (cluster 1024)" + IDS_5898 "DMF (cluster 2048)" + IDS_5899 "2.88 MB" + IDS_5900 "ZIP 100" + IDS_5901 "ZIP 250" + IDS_5902 "3.5"" 128 MB (ISO 10090)" + IDS_5903 "3.5"" 230 MB (ISO 13963)" + IDS_5904 "3.5"" 540 MB (ISO 15498)" + IDS_5905 "3.5"" 640 MB (ISO 15498)" + IDS_5906 "3.5"" 1.3 GB (GigaMO)" + IDS_5907 "3.5"" 2.3 GB (GigaMO 2)" + IDS_5908 "5.25"" 600 MB" + IDS_5909 "5.25"" 650 MB" + IDS_5910 "5.25"" 1 GB" + IDS_5911 "5.25"" 1.3 GB" - IDS_6144 "RPM perfectas" - IDS_6145 "1% por debajo de RPM perfectas" - IDS_6146 "1.5% por debajo de RPM perfectas" - IDS_6147 "2% por debajo de RPM perfectas" + IDS_6144 "RPM perfectas" + IDS_6145 "1% por debajo de RPM perfectas" + IDS_6146 "1.5% por debajo de RPM perfectas" + IDS_6147 "2% por debajo de RPM perfectas" - IDS_7168 "(Por defecto del sistema)" + IDS_7168 "(Por defecto del sistema)" END -#define IDS_LANG_ESES IDS_7168 +#define IDS_LANG_ESES IDS_7168 // Spanish (Spain) resources ///////////////////////////////////////////////////////////////////////////// diff --git a/src/win/languages/fi-FI.rc b/src/win/languages/fi-FI.rc index 695c91353..3f875cb3d 100644 --- a/src/win/languages/fi-FI.rc +++ b/src/win/languages/fi-FI.rc @@ -17,105 +17,114 @@ MainMenu MENU DISCARDABLE BEGIN POPUP "&Toiminto" BEGIN - MENUITEM "&Vaadi näppäimistön kaappaus", IDM_ACTION_KBD_REQ_CAPTURE - MENUITEM "&Oikea CTRL on vasen ALT", IDM_ACTION_RCTRL_IS_LALT + MENUITEM "&Vaadi näppäimistön kaappaus", IDM_ACTION_KBD_REQ_CAPTURE + MENUITEM "&Oikea CTRL on vasen ALT", IDM_ACTION_RCTRL_IS_LALT MENUITEM SEPARATOR - MENUITEM "&Uudelleenkäynnistys (kylmä)...", IDM_ACTION_HRESET - MENUITEM "&Ctrl+Alt+Del\tCtrl+F12", IDM_ACTION_RESET_CAD + MENUITEM "&Uudelleenkäynnistys (kylmä)...", IDM_ACTION_HRESET + MENUITEM "&Ctrl+Alt+Del\tCtrl+F12", IDM_ACTION_RESET_CAD MENUITEM SEPARATOR - MENUITEM "Ctrl+Alt+&Esc", IDM_ACTION_CTRL_ALT_ESC + MENUITEM "Ctrl+Alt+&Esc", IDM_ACTION_CTRL_ALT_ESC MENUITEM SEPARATOR - MENUITEM "&Tauko", IDM_ACTION_PAUSE + MENUITEM "&Tauko", IDM_ACTION_PAUSE MENUITEM SEPARATOR - MENUITEM "&Poistu...", IDM_ACTION_EXIT + MENUITEM "&Poistu...", IDM_ACTION_EXIT END POPUP "&Näytä" BEGIN - MENUITEM "&Piilota tilapalkki", IDM_VID_HIDE_STATUS_BAR - MENUITEM "Hide &toolbar", IDM_VID_HIDE_TOOLBAR + MENUITEM "&Piilota tilapalkki", IDM_VID_HIDE_STATUS_BAR + MENUITEM "Piilota &työkalupalkki", IDM_VID_HIDE_TOOLBAR MENUITEM SEPARATOR - MENUITEM "&Salli koon muuttaminen", IDM_VID_RESIZE - MENUITEM "&Muista koko ja sijainti", IDM_VID_REMEMBER + MENUITEM "&Show non-primary monitors", IDM_VID_MONITORS + MENUITEM "&Salli koon muuttaminen", IDM_VID_RESIZE + MENUITEM "&Muista koko ja sijainti", IDM_VID_REMEMBER MENUITEM SEPARATOR POPUP "&Renderöijä" BEGIN - MENUITEM "&SDL (ohjelmistopohjainen)", IDM_VID_SDL_SW - MENUITEM "SDL (&laitteistokiihdytetty)", IDM_VID_SDL_HW - MENUITEM "SDL (&OpenGL)", IDM_VID_SDL_OPENGL - MENUITEM "Open&GL (3.0 Core)", IDM_VID_OPENGL_CORE + MENUITEM "&SDL (ohjelmistopohjainen)", IDM_VID_SDL_SW + MENUITEM "SDL (&laitteistokiihdytetty)", IDM_VID_SDL_HW + MENUITEM "SDL (&OpenGL)", IDM_VID_SDL_OPENGL + MENUITEM "Open&GL (3.0 Core)", IDM_VID_OPENGL_CORE #ifdef USE_VNC - MENUITEM "&VNC", IDM_VID_VNC + MENUITEM "&VNC", IDM_VID_VNC #endif END MENUITEM SEPARATOR - MENUITEM "&Määritä koko...", IDM_VID_SPECIFY_DIM - MENUITEM "Pakota 4:3 näyttösuhde", IDM_VID_FORCE43 + MENUITEM "&Määritä koko...", IDM_VID_SPECIFY_DIM + MENUITEM "Pakota 4:3-näyttösuhde", IDM_VID_FORCE43 POPUP "&Ikkunan kokokerroin" BEGIN - MENUITEM "&0.5x", IDM_VID_SCALE_1X - MENUITEM "&1x", IDM_VID_SCALE_2X - MENUITEM "1.&5x", IDM_VID_SCALE_3X - MENUITEM "&2x", IDM_VID_SCALE_4X + MENUITEM "&0.5x", IDM_VID_SCALE_1X + MENUITEM "&1x", IDM_VID_SCALE_2X + MENUITEM "1.&5x", IDM_VID_SCALE_3X + MENUITEM "&2x", IDM_VID_SCALE_4X + MENUITEM "&3x", IDM_VID_SCALE_5X + MENUITEM "&4x", IDM_VID_SCALE_6X + MENUITEM "&5x", IDM_VID_SCALE_7X + MENUITEM "&6x", IDM_VID_SCALE_8X + MENUITEM "&7x", IDM_VID_SCALE_9X + MENUITEM "&8x", IDM_VID_SCALE_10X END POPUP "&Suodatusmetodi" BEGIN - MENUITEM "&Lähin naapuri", IDM_VID_FILTER_NEAREST - MENUITEM "Li&neaarinen interpolaatio", IDM_VID_FILTER_LINEAR + MENUITEM "&Lähin naapuri", IDM_VID_FILTER_NEAREST + MENUITEM "Li&neaarinen interpolaatio", IDM_VID_FILTER_LINEAR END - MENUITEM "&Suuri DPI-skaalaus", IDM_VID_HIDPI + MENUITEM "&Suuri DPI-skaalaus", IDM_VID_HIDPI MENUITEM SEPARATOR - MENUITEM "&Koko näytön tila\tCtrl+Alt+PgUp", IDM_VID_FULLSCREEN + MENUITEM "&Koko näytön tila\tCtrl+Alt+PgUp", IDM_VID_FULLSCREEN POPUP "Koko näytön &skaalaustila" BEGIN - MENUITEM "&Venytä koko näyttöön", IDM_VID_FS_FULL - MENUITEM "&4:3", IDM_VID_FS_43 - MENUITEM "&Tasasivuiset kuvapisteet (säilytä kuvasuhde)", IDM_VID_FS_KEEPRATIO - MENUITEM "&Kokonaislukuskaalaus", IDM_VID_FS_INT + MENUITEM "&Venytä koko näyttöön", IDM_VID_FS_FULL + MENUITEM "&4:3", IDM_VID_FS_43 + MENUITEM "&Tasasivuiset kuvapisteet (säilytä kuvasuhde)", IDM_VID_FS_KEEPRATIO + MENUITEM "&Kokonaislukuskaalaus", IDM_VID_FS_INT END - POPUP "&EGA/(S)VGA asetukset" + POPUP "&EGA/(S)VGA-asetukset" BEGIN - MENUITEM "&VGA näyttö käänteisillä väreillä", IDM_VID_INVERT - POPUP "VGA näytön &tyyppi" + MENUITEM "&VGA-näyttö käänteisillä väreillä", IDM_VID_INVERT + POPUP "VGA-näytön &tyyppi" BEGIN - MENUITEM "RGB &värit", IDM_VID_GRAY_RGB - MENUITEM "&RGB harmaasävyinen", IDM_VID_GRAY_MONO - MENUITEM "&Meripihkanvärinen", IDM_VID_GRAY_AMBER - MENUITEM "V&ihreä", IDM_VID_GRAY_GREEN - MENUITEM "V&alkoinen", IDM_VID_GRAY_WHITE + MENUITEM "RGB, &värit", IDM_VID_GRAY_RGB + MENUITEM "&RGB, harmaasävy", IDM_VID_GRAY_MONO + MENUITEM "&Meripihkanvärinen", IDM_VID_GRAY_AMBER + MENUITEM "V&ihreä", IDM_VID_GRAY_GREEN + MENUITEM "V&alkoinen", IDM_VID_GRAY_WHITE END POPUP "&Harmaasävymuunnoksen tyyppi" BEGIN - MENUITEM "BT&601 (NTSC/PAL)", IDM_VID_GRAYCT_601 - MENUITEM "BT&709 (HDTV)", IDM_VID_GRAYCT_709 - MENUITEM "&Keskiarvo", IDM_VID_GRAYCT_AVE + MENUITEM "BT&601 (NTSC/PAL)", IDM_VID_GRAYCT_601 + MENUITEM "BT&709 (HDTV)", IDM_VID_GRAYCT_709 + MENUITEM "&Keskiarvo", IDM_VID_GRAYCT_AVE END END MENUITEM SEPARATOR - MENUITEM "CGA/PCjr/Tandy/E&GA/(S)VGA &yliskannaus", IDM_VID_OVERSCAN - MENUITEM "&Muuta harmaavärinäytön kontrastia", IDM_VID_CGACON + MENUITEM "CGA/PCjr/Tandy/E&GA/(S)VGA &yliskannaus", IDM_VID_OVERSCAN + MENUITEM "&Muuta harmaavärinäytön kontrastia", IDM_VID_CGACON END - MENUITEM "&Media", IDM_MEDIA - POPUP "&Työkalut" + MENUITEM "&Media", IDM_MEDIA + POPUP "Työ&kalut" BEGIN - MENUITEM "&Kokoonpano...", IDM_CONFIG - MENUITEM "&Päivitä tilapalkin kuvakkeita", IDM_UPDATE_ICONS + MENUITEM "&Kokoonpano...", IDM_CONFIG + MENUITEM "&Päivitä tilapalkin kuvakkeita", IDM_UPDATE_ICONS MENUITEM SEPARATOR - MENUITEM "Ota &kuvakaappaus\tCtrl+F11", IDM_ACTION_SCREENSHOT + MENUITEM "Ota &kuvakaappaus\tCtrl+F11", IDM_ACTION_SCREENSHOT MENUITEM SEPARATOR - MENUITEM "&Sovellusasetukset...", IDM_PREFERENCES - MENUITEM "Käytä &Discord integraatiota", IDM_DISCORD + MENUITEM "&Sovellusasetukset...", IDM_PREFERENCES +#ifdef DISCORD + MENUITEM "Käytä &Discord-integraatiota", IDM_DISCORD +#endif MENUITEM SEPARATOR - MENUITEM "&Äänen tulotaso...", IDM_SND_GAIN + MENUITEM "&Äänitasot...", IDM_SND_GAIN #ifdef MTR_ENABLED MENUITEM SEPARATOR - MENUITEM "Aloita jäljitys\tCtrl+T", IDM_ACTION_BEGIN_TRACE - MENUITEM "Lopeta jäljitys\tCtrl+T", IDM_ACTION_END_TRACE + MENUITEM "Aloita jäljitys\tCtrl+T", IDM_ACTION_BEGIN_TRACE + MENUITEM "Lopeta jäljitys\tCtrl+T", IDM_ACTION_END_TRACE #endif END POPUP "&Ohje" BEGIN - MENUITEM "&Dokumentaatio...", IDM_DOCS - MENUITEM "&Tietoja 86Box:sta...", IDM_ABOUT + MENUITEM "&Ohjekirja...", IDM_DOCS + MENUITEM "&Tietoja 86Boxista...", IDM_ABOUT END END @@ -128,17 +137,17 @@ CassetteSubmenu MENU DISCARDABLE BEGIN POPUP "" BEGIN - MENUITEM "&Uusi kasettikuva...", IDM_CASSETTE_IMAGE_NEW + MENUITEM "&Uusi kasettikuva...", IDM_CASSETTE_IMAGE_NEW MENUITEM SEPARATOR - MENUITEM "&Olemassaoleva kasettikuva...", IDM_CASSETTE_IMAGE_EXISTING - MENUITEM "Olemassaoleva kasettikuva (&kirjoitussuojattu)...", IDM_CASSETTE_IMAGE_EXISTING_WP + MENUITEM "&Olemassaoleva kasettikuva...", IDM_CASSETTE_IMAGE_EXISTING + MENUITEM "Olemassaoleva kasettikuva (&kirjoitussuojattu)...", IDM_CASSETTE_IMAGE_EXISTING_WP MENUITEM SEPARATOR - MENUITEM "&Nauhoita", IDM_CASSETTE_RECORD - MENUITEM "&Toista", IDM_CASSETTE_PLAY - MENUITEM "Kelaa &alkuun", IDM_CASSETTE_REWIND - MENUITEM "Kelaa &loppuun", IDM_CASSETTE_FAST_FORWARD + MENUITEM "&Nauhoita", IDM_CASSETTE_RECORD + MENUITEM "&Toista", IDM_CASSETTE_PLAY + MENUITEM "Kelaa &alkuun", IDM_CASSETTE_REWIND + MENUITEM "Kelaa &loppuun", IDM_CASSETTE_FAST_FORWARD MENUITEM SEPARATOR - MENUITEM "&Poista kasettipesästä", IDM_CASSETTE_EJECT + MENUITEM "&Poista kasettipesästä", IDM_CASSETTE_EJECT END END @@ -146,9 +155,9 @@ CartridgeSubmenu MENU DISCARDABLE BEGIN POPUP "" BEGIN - MENUITEM "&ROM-moduulikuva...", IDM_CARTRIDGE_IMAGE + MENUITEM "&ROM-moduulikuva...", IDM_CARTRIDGE_IMAGE MENUITEM SEPARATOR - MENUITEM "&Irrota", IDM_CARTRIDGE_EJECT + MENUITEM "&Irrota", IDM_CARTRIDGE_EJECT END END @@ -156,14 +165,14 @@ FloppySubmenu MENU DISCARDABLE BEGIN POPUP "" BEGIN - MENUITEM "&Uusi levykekuva...", IDM_FLOPPY_IMAGE_NEW + MENUITEM "&Uusi levykekuva...", IDM_FLOPPY_IMAGE_NEW MENUITEM SEPARATOR - MENUITEM "&Olemassaoleva levykekuva...", IDM_FLOPPY_IMAGE_EXISTING - MENUITEM "Olemassaoleva levykekuva (&kirjoitussuojattu)...", IDM_FLOPPY_IMAGE_EXISTING_WP + MENUITEM "&Olemassaoleva levykekuva...", IDM_FLOPPY_IMAGE_EXISTING + MENUITEM "Olemassaoleva levykekuva (&kirjoitussuojattu)...", IDM_FLOPPY_IMAGE_EXISTING_WP MENUITEM SEPARATOR - MENUITEM "&Vie 86F-tiedostoon...", IDM_FLOPPY_EXPORT_TO_86F + MENUITEM "&Vie 86F-tiedostoon...", IDM_FLOPPY_EXPORT_TO_86F MENUITEM SEPARATOR - MENUITEM "&Poista asemasta", IDM_FLOPPY_EJECT + MENUITEM "&Poista asemasta", IDM_FLOPPY_EJECT END END @@ -171,12 +180,13 @@ CdromSubmenu MENU DISCARDABLE BEGIN POPUP "" BEGIN - MENUITEM "&Mykistä", IDM_CDROM_MUTE + MENUITEM "&Mykistä", IDM_CDROM_MUTE MENUITEM SEPARATOR - MENUITEM "&Tyhjä", IDM_CDROM_EMPTY - MENUITEM "&Lataa edellinen levykuva uudelleen", IDM_CDROM_RELOAD + MENUITEM "&Tyhjä", IDM_CDROM_EMPTY + MENUITEM "&Lataa edellinen levykuva uudelleen", IDM_CDROM_RELOAD MENUITEM SEPARATOR - MENUITEM "L&evykuva", IDM_CDROM_IMAGE + MENUITEM "L&evykuva...", IDM_CDROM_IMAGE + MENUITEM "&Kansio...", IDM_CDROM_DIR END END @@ -184,13 +194,13 @@ ZIPSubmenu MENU DISCARDABLE BEGIN POPUP "" BEGIN - MENUITEM "&Uusi levykuva...", IDM_ZIP_IMAGE_NEW + MENUITEM "&Uusi levykuva...", IDM_ZIP_IMAGE_NEW MENUITEM SEPARATOR - MENUITEM "&Olemassaoleva levykuva...", IDM_ZIP_IMAGE_EXISTING - MENUITEM "Olemassaoleva levykuva (&kirjoitussuojattu)...", IDM_ZIP_IMAGE_EXISTING_WP + MENUITEM "&Olemassaoleva levykuva...", IDM_ZIP_IMAGE_EXISTING + MENUITEM "Olemassaoleva levykuva (&kirjoitussuojattu)...", IDM_ZIP_IMAGE_EXISTING_WP MENUITEM SEPARATOR - MENUITEM "&Poista asemasta", IDM_ZIP_EJECT - MENUITEM "&Lataa edellinen levykuva uudelleen", IDM_ZIP_RELOAD + MENUITEM "&Poista asemasta", IDM_ZIP_EJECT + MENUITEM "&Lataa edellinen levykuva uudelleen", IDM_ZIP_RELOAD END END @@ -198,13 +208,13 @@ MOSubmenu MENU DISCARDABLE BEGIN POPUP "" BEGIN - MENUITEM "&Uusi levykuva...", IDM_MO_IMAGE_NEW + MENUITEM "&Uusi levykuva...", IDM_MO_IMAGE_NEW MENUITEM SEPARATOR - MENUITEM "&Olemassaoleva levykuva...", IDM_MO_IMAGE_EXISTING - MENUITEM "Olemassaoleva levykuva (&kirjoitussuojattu)...", IDM_MO_IMAGE_EXISTING_WP + MENUITEM "&Olemassaoleva levykuva...", IDM_MO_IMAGE_EXISTING + MENUITEM "Olemassaoleva levykuva (&kirjoitussuojattu)...", IDM_MO_IMAGE_EXISTING_WP MENUITEM SEPARATOR - MENUITEM "&Poista asemasta", IDM_MO_EJECT - MENUITEM "&Lataa edellinen levykuva uudelleen", IDM_MO_RELOAD + MENUITEM "&Poista asemasta", IDM_MO_EJECT + MENUITEM "&Lataa edellinen levykuva uudelleen", IDM_MO_RELOAD END END @@ -212,16 +222,16 @@ VidGLSubMenu MENU DISCARDABLE BEGIN POPUP "&Kuvataajuustavoite" BEGIN - MENUITEM "&Synkronisoi videoon", IDM_VID_GL_FPS_BLITTER - MENUITEM "&25 ruutua/s", IDM_VID_GL_FPS_25 - MENUITEM "&30 ruutua/s", IDM_VID_GL_FPS_30 - MENUITEM "&50 ruutua/s", IDM_VID_GL_FPS_50 - MENUITEM "&60 ruutua/s", IDM_VID_GL_FPS_60 - MENUITEM "&75 ruutua/s", IDM_VID_GL_FPS_75 + MENUITEM "&Synkronisoi videoon", IDM_VID_GL_FPS_BLITTER + MENUITEM "&25 ruutua/s", IDM_VID_GL_FPS_25 + MENUITEM "&30 ruutua/s", IDM_VID_GL_FPS_30 + MENUITEM "&50 ruutua/s", IDM_VID_GL_FPS_50 + MENUITEM "&60 ruutua/s", IDM_VID_GL_FPS_60 + MENUITEM "&75 ruutua/s", IDM_VID_GL_FPS_75 END MENUITEM "&VSync", IDM_VID_GL_VSYNC - MENUITEM "Valitse varjostin&ohjelma...", IDM_VID_GL_SHADER - MENUITEM "&Poista varjostinohjelma", IDM_VID_GL_NOSHADER + MENUITEM "Valitse varjostin&ohjelma...", IDM_VID_GL_SHADER + MENUITEM "&Poista varjostinohjelma", IDM_VID_GL_NOSHADER END @@ -230,134 +240,150 @@ END // Dialog // -#define STR_PREFERENCES "Sovellusasetukset" -#define STR_SND_GAIN "Äänen tulotaso" -#define STR_NEW_FLOPPY "Uusi levykuva" -#define STR_CONFIG "Kokoonpano" -#define STR_SPECIFY_DIM "Määritä pääikkunan koko" +#define STR_PREFERENCES "Sovellusasetukset" +#define STR_SND_GAIN "Äänen taso" +#define STR_NEW_FLOPPY "Uusi levykuva" +#define STR_CONFIG "Kokoonpano" +#define STR_SPECIFY_DIM "Määritä pääikkunan koko" -#define STR_OK "OK" -#define STR_CANCEL "Peruuta" -#define STR_GLOBAL "Tallenna nämä asetukset &globaaleiksi oletuksiksi" -#define STR_DEFAULT "&Oletus" -#define STR_LANGUAGE "Kieli:" -#define STR_ICONSET "Kuvakkeet:" +#define STR_OK "OK" +#define STR_CANCEL "Peruuta" +#define STR_GLOBAL "Tallenna nämä asetukset &globaaleiksi oletuksiksi" +#define STR_DEFAULT "&Oletus" +#define STR_LANGUAGE "Kieli:" +#define STR_ICONSET "Kuvakkeet:" -#define STR_GAIN "Taso" +#define STR_GAIN "Taso" -#define STR_FILE_NAME "Tiedostonimi:" -#define STR_DISK_SIZE "Levyn koko:" -#define STR_RPM_MODE "RPM tila:" -#define STR_PROGRESS "Edistyminen:" +#define STR_FILE_NAME "Tiedostonimi:" +#define STR_DISK_SIZE "Levyn koko:" +#define STR_RPM_MODE "Kierroslukutila:" +#define STR_PROGRESS "Edistyminen:" -#define STR_WIDTH "Leveys:" -#define STR_HEIGHT "Korkeus:" -#define STR_LOCK_TO_SIZE "Lukitse tähän kokoon" +#define STR_WIDTH "Leveys:" +#define STR_HEIGHT "Korkeus:" +#define STR_LOCK_TO_SIZE "Lukitse tähän kokoon" -#define STR_MACHINE_TYPE "Tietokoneen tyyppi:" -#define STR_MACHINE "Tietokone:" -#define STR_CONFIGURE "Määritys" -#define STR_CPU_TYPE "Suorittimen tyyppi:" -#define STR_CPU_SPEED "Nopeus:" -#define STR_FPU "Apusuoritin:" -#define STR_WAIT_STATES "Odotustilat:" -#define STR_MB "Mt" -#define STR_MEMORY "Muisti:" -#define STR_TIME_SYNC "Kellon synkronointi" -#define STR_DISABLED "Ei käytössä" -#define STR_ENABLED_LOCAL "Käytössä (paikallinen)" -#define STR_ENABLED_UTC "Käytössä (UTC)" -#define STR_DYNAREC "Dynaaminen uudelleenkääntäjä" +#define STR_MACHINE_TYPE "Tietokoneen tyyppi:" +#define STR_MACHINE "Tietokone:" +#define STR_CONFIGURE "Määritys" +#define STR_CPU_TYPE "Suorittimen tyyppi:" +#define STR_CPU_SPEED "Nopeus:" +#define STR_FPU "Apusuoritin:" +#define STR_WAIT_STATES "Odotustilat:" +#define STR_MB "Mt" +#define STR_MEMORY "Muisti:" +#define STR_TIME_SYNC "Kellon synkronointi" +#define STR_DISABLED "Ei käytössä" +#define STR_ENABLED_LOCAL "Käytössä (paikallinen)" +#define STR_ENABLED_UTC "Käytössä (UTC)" +#define STR_DYNAREC "Dynaaminen uudelleenkääntäjä" +#define STR_SOFTFLOAT "Softfloat FPU" -#define STR_VIDEO "Näytönohjain:" -#define STR_VOODOO "Voodoo-grafiikkasuoritin" +#define STR_VIDEO "Näytönohjain:" +#define STR_VIDEO_2 "Näytönohjain 2:" +#define STR_VOODOO "Voodoo-grafiikkasuoritin" +#define STR_IBM8514 "IBM 8514/a-grafiikkasuoritin" +#define STR_XGA "XGA-grafiikkasuoritin" -#define STR_MOUSE "Hiiri:" -#define STR_JOYSTICK "Peliohjain:" -#define STR_JOY1 "Peliohjain 1..." -#define STR_JOY2 "Peliohjain 2..." -#define STR_JOY3 "Peliohjain 3..." -#define STR_JOY4 "Peliohjain 4..." +#define STR_MOUSE "Hiiri:" +#define STR_JOYSTICK "Peliohjain:" +#define STR_JOY1 "Peliohjain 1..." +#define STR_JOY2 "Peliohjain 2..." +#define STR_JOY3 "Peliohjain 3..." +#define STR_JOY4 "Peliohjain 4..." -#define STR_SOUND "Äänikortti:" -#define STR_MIDI_OUT "MIDI-ulostulo:" -#define STR_MIDI_IN "MIDI-sisääntulo:" -#define STR_MPU401 "Erillinen MPU-401" -#define STR_SSI "Innovation SSI-2001" -#define STR_CMS "CMS / Game Blaster" -#define STR_GUS "Gravis Ultrasound" -#define STR_FLOAT "Käytä FLOAT32-ääntä" +#define STR_SOUND1 "Äänikortti 1:" +#define STR_SOUND2 "Äänikortti 2:" +#define STR_SOUND3 "Äänikortti 3:" +#define STR_SOUND4 "Äänikortti 4:" +#define STR_MIDI_OUT "MIDI-ulostulo:" +#define STR_MIDI_IN "MIDI-sisääntulo:" +#define STR_MPU401 "Erillinen MPU-401" +#define STR_FLOAT "Käytä FLOAT32-ääntä" +#define STR_FM_DRIVER "FM-syntetisaattoriohjain" +#define STR_FM_DRV_NUKED "Nuked (tarkempi)" +#define STR_FM_DRV_YMFM "YMFM (nopeampi)" -#define STR_NET_TYPE "Verkon tyyppi:" -#define STR_PCAP "PCap-laite:" -#define STR_NET "Verkkokortti:" +#define STR_NET_TYPE "Verkon tyyppi:" +#define STR_PCAP "PCap-laite:" +#define STR_NET "Verkkokortti:" +#define STR_NET1 "Network card 1:" +#define STR_NET2 "Network card 2:" +#define STR_NET3 "Network card 3:" +#define STR_NET4 "Network card 4:" -#define STR_COM1 "COM1-laite:" -#define STR_COM2 "COM2-laite:" -#define STR_COM3 "COM3-laite:" -#define STR_COM4 "COM4-laite:" -#define STR_LPT1 "LPT1-laite:" -#define STR_LPT2 "LPT2-laite:" -#define STR_LPT3 "LPT3-laite:" -#define STR_LPT4 "LPT4-laite:" -#define STR_SERIAL1 "Sarjaportti 1" -#define STR_SERIAL2 "Sarjaportti 2" -#define STR_SERIAL3 "Sarjaportti 3" -#define STR_SERIAL4 "Sarjaportti 4" -#define STR_PARALLEL1 "Rinnakkaisportti 1" -#define STR_PARALLEL2 "Rinnakkaisportti 2" -#define STR_PARALLEL3 "Rinnakkaisportti 3" -#define STR_PARALLEL4 "Rinnakkaisportti 4" +#define STR_COM1 "COM1-laite:" +#define STR_COM2 "COM2-laite:" +#define STR_COM3 "COM3-laite:" +#define STR_COM4 "COM4-laite:" +#define STR_LPT1 "LPT1-laite:" +#define STR_LPT2 "LPT2-laite:" +#define STR_LPT3 "LPT3-laite:" +#define STR_LPT4 "LPT4-laite:" +#define STR_SERIAL1 "Sarjaportti 1" +#define STR_SERIAL2 "Sarjaportti 2" +#define STR_SERIAL3 "Sarjaportti 3" +#define STR_SERIAL4 "Sarjaportti 4" +#define STR_PARALLEL1 "Rinnakkaisportti 1" +#define STR_PARALLEL2 "Rinnakkaisportti 2" +#define STR_PARALLEL3 "Rinnakkaisportti 3" +#define STR_PARALLEL4 "Rinnakkaisportti 4" +#define STR_SERIAL_PASS1 "Serial port passthrough 1" +#define STR_SERIAL_PASS2 "Serial port passthrough 2" +#define STR_SERIAL_PASS3 "Serial port passthrough 3" +#define STR_SERIAL_PASS4 "Serial port passthrough 4" -#define STR_HDC "Kiintolevyohjain:" -#define STR_FDC "Levykeohjain:" -#define STR_IDE_TER "Tertinäärinen IDE-ohjain" -#define STR_IDE_QUA "Kvaternaarinen IDE-ohjain" -#define STR_SCSI "SCSI" -#define STR_SCSI_1 "Ohjain 1:" -#define STR_SCSI_2 "Ohjain 2:" -#define STR_SCSI_3 "Ohjain 3:" -#define STR_SCSI_4 "Ohjain 4:" -#define STR_CASSETTE "Kasettiasema" +#define STR_HDC "Kiintolevyohjain:" +#define STR_FDC "Levykeohjain:" +#define STR_IDE_TER "Kolmas IDE-ohjain" +#define STR_IDE_QUA "Neljäs IDE-ohjain" +#define STR_SCSI "SCSI" +#define STR_SCSI_1 "Ohjain 1:" +#define STR_SCSI_2 "Ohjain 2:" +#define STR_SCSI_3 "Ohjain 3:" +#define STR_SCSI_4 "Ohjain 4:" +#define STR_CASSETTE "Kasettiasema" -#define STR_HDD "Kiintolevyt:" -#define STR_NEW "&Uusi..." -#define STR_EXISTING "&Olemassaoleva..." -#define STR_REMOVE "&Poista" -#define STR_BUS "Väylä:" -#define STR_CHANNEL "Kanava:" -#define STR_ID "ID:" +#define STR_HDD "Kiintolevyt:" +#define STR_NEW "&Uusi..." +#define STR_EXISTING "&Olemassaoleva..." +#define STR_REMOVE "&Poista" +#define STR_BUS "Väylä:" +#define STR_CHANNEL "Kanava:" +#define STR_ID "ID:" +#define STR_SPEED "Speed:" -#define STR_SPECIFY "&Määritä..." -#define STR_SECTORS "Sektorit:" -#define STR_HEADS "Päät:" -#define STR_CYLS "Sylinterit:" -#define STR_SIZE_MB "Koko (Mt):" -#define STR_TYPE "Tyyppi:" -#define STR_IMG_FORMAT "Tiedostomuoto:" -#define STR_BLOCK_SIZE "Lohkon koko:" +#define STR_SPECIFY "&Määritä..." +#define STR_SECTORS "Sektorit:" +#define STR_HEADS "Lukupäät:" +#define STR_CYLS "Sylinterit:" +#define STR_SIZE_MB "Koko (Mt):" +#define STR_TYPE "Tyyppi:" +#define STR_IMG_FORMAT "Tiedostomuoto:" +#define STR_BLOCK_SIZE "Lohkon koko:" -#define STR_FLOPPY_DRIVES "Levykeasemat:" -#define STR_TURBO "Turbo-ajoitukset" -#define STR_CHECKBPB "Tarkista BPB" -#define STR_CDROM_DRIVES "CD-ROM-asemat:" -#define STR_CD_SPEED "Nopeus:" +#define STR_FLOPPY_DRIVES "Levykeasemat:" +#define STR_TURBO "Turbo-ajoitukset" +#define STR_CHECKBPB "Tarkista BPB" +#define STR_CDROM_DRIVES "CD-ROM-asemat:" +#define STR_CD_SPEED "Nopeus:" -#define STR_MO_DRIVES "Magneettisoptiset asemat (MO):" -#define STR_ZIP_DRIVES "ZIP-asemat:" -#define STR_250 "ZIP 250" +#define STR_MO_DRIVES "Magneettisoptiset asemat (MO):" +#define STR_ZIP_DRIVES "ZIP-asemat:" +#define STR_250 "ZIP 250" -#define STR_ISARTC "ISA-RTC (kello):" -#define STR_ISAMEM "ISA-muistilaajennus" -#define STR_ISAMEM_1 "Kortti 1:" -#define STR_ISAMEM_2 "Kortti 2:" -#define STR_ISAMEM_3 "Kortti 3:" -#define STR_ISAMEM_4 "Kortti 4:" -#define STR_BUGGER "ISABugger-laite" -#define STR_POSTCARD "POST-kortti" +#define STR_ISARTC "ISA-RTC (kello):" +#define STR_ISAMEM "ISA-muistilaajennus" +#define STR_ISAMEM_1 "Kortti 1:" +#define STR_ISAMEM_2 "Kortti 2:" +#define STR_ISAMEM_3 "Kortti 3:" +#define STR_ISAMEM_4 "Kortti 4:" +#define STR_BUGGER "ISABugger-laite" +#define STR_POSTCARD "POST-kortti" -#define FONT_SIZE 9 -#define FONT_NAME "Segoe UI" +#define FONT_SIZE 9 +#define FONT_NAME "Segoe UI" #include "dialogs.rc" @@ -368,15 +394,15 @@ END STRINGTABLE DISCARDABLE BEGIN - 2048 "86Box" + 2048 "86Box" IDS_2049 "Virhe" IDS_2050 "Vakava virhe" - IDS_2051 " - PAUSED" + IDS_2051 " - TAUKO" IDS_2052 "Paina Ctrl+Alt+PgDn palataksesi ikkunoituun tilaan." IDS_2053 "Nopeus" IDS_2054 "ZIP %03i %i (%s): %ls" IDS_2055 "ZIP-levykuvat (*.IM?;*.ZDI)\0*.IM?;*.ZDI\0" - IDS_2056 "86Box ei löytänyt käyttökelpoisia ROM-tiedostoja.\n\nVoit ladata ROM-paketin ja purkaa sen ""roms"" hakemistoon." + IDS_2056 "86Box ei löytänyt käyttökelpoisia ROM-tiedostoja.\n\nVoit ladata ROM-paketin ja purkaa sen ""roms""-hakemistoon." IDS_2057 "(tyhjä)" IDS_2058 "ZIP-levykuvat (*.IM?;*.ZDI)\0*.IM?;*.ZDI\0Kaikki tiedostot (*.*)\0*.*\0" IDS_2059 "Turbo" @@ -408,108 +434,102 @@ END STRINGTABLE DISCARDABLE BEGIN - IDS_2080 "FluidSynth:in alustus epäonnistui" IDS_2081 "Väylä" IDS_2082 "Tiedosto" IDS_2083 "C" IDS_2084 "H" IDS_2085 "S" IDS_2086 "Mt" - IDS_2087 "Tarkista BPB" - IDS_2088 "kt" - IDS_2089 "Video-renderöijän alustus epäonnistui" - IDS_2090 "Oletus" - IDS_2091 "%i odotustilaa" - IDS_2092 "Tyyppi" - IDS_2093 "PCap-asennus epäonnistui" - IDS_2094 "PCap-laitteita ei löytynyt" - IDS_2095 "Virheellinen PCap-laite" - IDS_2096 "Standardi 2-painikkeinen peliohjain/-ohjaimet" - IDS_2097 "Standardi 4-painikkeinen peliohjain" - IDS_2098 "Standardi 6-painikkeinen peliohjain" - IDS_2099 "Standardi 8-painikkeinen peliohjain" - IDS_2100 "CH Flightstick Pro" - IDS_2101 "Microsoft SideWinder Pad" - IDS_2102 "Thrustmaster Flight Control System" - IDS_2103 "Ei mikään" - IDS_2104 "Näppäinkiihdyttimien lataus epäonnistui" - IDS_2105 "Raakasyötteen rekisteröinti epäonnistui" - IDS_2106 "%u" - IDS_2107 "%u Mt (CHS: %i, %i, %i)" - IDS_2108 "Levyke %i (%s): %ls" - IDS_2109 "Kaikki levykuvat (*.0??;*.1??;*.??0;*.86F;*.BIN;*.CQ?;*.D??;*.FLP;*.HDM;*.IM?;*.JSON;*.TD0;*.*FD?;*.MFM;*.XDF)\0*.0??;*.1??;*.??0;*.86F;*.BIN;*.CQ?;*.D??;*.FLP;*.HDM;*.IM?;*.JSON;*.TD0;*.*FD?;*.MFM;*.XDF\0Kehittyneet sektorilevykuvat (*.IMD;*.JSON;*.TD0)\0*.IMD;*.JSON;*.TD0\0Perussektorilevykuvat (*.0??;*.1??;*.??0;*.BIN;*.CQ?;*.D??;*.FLP;*.HDM;*.IM?;*.XDF;*.*FD?)\0*.0??;*.1??;*.??0;*.BIN;*.CQ?;*.D??;*.FLP;*.HDM;*.IM?;*.XDF;*.*FD?\0Flux-levykuvat (*.FDI)\0*.FDI\0Pintalevykuvat (*.86F;*.MFM)\0*.86F;*.MFM\0Kaikki tiedostot (*.*)\0*.*\0" - IDS_2110 "FreeType:n alustus epäonnistui" - IDS_2111 "SDL:n alustus epäonnistui. Tarvitaan SDL2.dll" - IDS_2112 "Oletko varma, että haluat käynnistää emuloidun tietokoneen uudelleen?" - IDS_2113 "Haluatko varmasti sulkea 86Box:in?" - IDS_2114 "Ghostscript:in alustus epäonnistui" - IDS_2115 "MO %i (%ls): %ls" - IDS_2116 "MO-levykuvat (*.IM?;*.MDI)\0*.IM?;*.MDI\0Kaikki tiedostot (*.*)\0*.*\0" - IDS_2117 "Tervetuloa 86Box:iin!" - IDS_2118 "Sisäinen ohjain" - IDS_2119 "Poistu" - IDS_2120 "ROM-tiedostoja ei löytynyt" - IDS_2121 "Tallennetaanko asetukset?" - IDS_2122 "Tämä käynnistää emuloidun tietokoneen uudelleen." - IDS_2123 "Tallenna" - IDS_2124 "Tietoja 86Box:sta" - IDS_2125 "86Box v" EMU_VERSION + IDS_2087 "Speed" + IDS_2088 "Tarkista BPB" + IDS_2089 "kt" + IDS_2090 "Videorenderöijän alustus epäonnistui" + IDS_2091 "Oletus" + IDS_2092 "%i odotustilaa" + IDS_2093 "Tyyppi" + IDS_2094 "PCap-asennus epäonnistui" + IDS_2095 "PCap-laitteita ei löytynyt" + IDS_2096 "Virheellinen PCap-laite" + IDS_2097 "Standardi 2-painikkeinen peliohjain/-ohjaimet" + IDS_2098 "Standardi 4-painikkeinen peliohjain" + IDS_2099 "Standardi 6-painikkeinen peliohjain" + IDS_2100 "Standardi 8-painikkeinen peliohjain" + IDS_2101 "CH Flightstick Pro" + IDS_2102 "Microsoft SideWinder Pad" + IDS_2103 "Thrustmaster Flight Control System" + IDS_2104 "Ei mikään" + IDS_2105 "Näppäinkiihdyttimien lataus epäonnistui" + IDS_2106 "Raakasyötteen rekisteröinti epäonnistui" + IDS_2107 "%u" + IDS_2108 "%u Mt (CHS: %i, %i, %i)" + IDS_2109 "Levyke %i (%s): %ls" + IDS_2110 "Kaikki levykuvat (*.0??;*.1??;*.??0;*.86F;*.BIN;*.CQ?;*.D??;*.FLP;*.HDM;*.IM?;*.JSON;*.TD0;*.*FD?;*.MFM;*.XDF)\0*.0??;*.1??;*.??0;*.86F;*.BIN;*.CQ?;*.D??;*.FLP;*.HDM;*.IM?;*.JSON;*.TD0;*.*FD?;*.MFM;*.XDF\0Kehittyneet sektorilevykuvat (*.IMD;*.JSON;*.TD0)\0*.IMD;*.JSON;*.TD0\0Perussektorilevykuvat (*.0??;*.1??;*.??0;*.BIN;*.CQ?;*.D??;*.FLP;*.HDM;*.IM?;*.XDF;*.*FD?)\0*.0??;*.1??;*.??0;*.BIN;*.CQ?;*.D??;*.FLP;*.HDM;*.IM?;*.XDF;*.*FD?\0Flux-levykuvat (*.FDI)\0*.FDI\0Pintalevykuvat (*.86F;*.MFM)\0*.86F;*.MFM\0Kaikki tiedostot (*.*)\0*.*\0" + IDS_2112 "SDL:n alustus epäonnistui. Tarvitaan SDL2.dll" + IDS_2113 "Haluatko varmasti käynnistää emuloidun tietokoneen uudelleen?" + IDS_2114 "Haluatko varmasti sulkea 86Boxin?" + IDS_2115 "Ghostscriptin alustus epäonnistui" + IDS_2116 "MO %i (%ls): %ls" + IDS_2117 "MO-levykuvat (*.IM?;*.MDI)\0*.IM?;*.MDI\0Kaikki tiedostot (*.*)\0*.*\0" + IDS_2118 "Tervetuloa 86Boxiin!" + IDS_2119 "Sisäinen ohjain" + IDS_2120 "Poistu" + IDS_2121 "ROM-tiedostoja ei löytynyt" + IDS_2122 "Tallennetaanko asetukset?" + IDS_2123 "Tämä käynnistää emuloidun tietokoneen uudelleen." + IDS_2124 "Tallenna" + IDS_2125 "Tietoja 86Box:sta" + IDS_2126 "86Box v" EMU_VERSION - IDS_2126 "Vanhojen tietokoneiden emulaattori\n\nTekijät: Sarah Walker, Miran Grca, Fred N. van Kempen (waltje), SA1988, Tiseno100, reenigne, leilei, JohnElliott, greatpsycho ja muut.\n\nJulkaistu GNU General Public License 2. version tai myöhemmän alaisena. Tarkempia tietoja LICENSE-tiedostossa." - IDS_2127 "OK" - IDS_2128 "Laitteisto ei ole saatavilla" + IDS_2127 "Vanhojen tietokoneiden emulaattori\n\nTekijät: Miran GrÄa (OBattler), RichardG867, Jasmine Iwanek, TC1995, coldbrewed, Teemu Korhonen (Manaatti), Joakim L. Gilje, Adrien Moulin (elyosh), Daniel Balsom (gloriouscow), Cacodemon345, Fred N. van Kempen (waltje), Tiseno100, reenigne ja muut.\n\nWith previous core contributions from Sarah Walker, leilei, JohnElliott, greatpsycho ja muut.\n\nJulkaistu GNU General Public License 2. version tai myöhemmän alaisena. Tarkempia tietoja LICENSE-tiedostossa." + IDS_2128 "OK" + IDS_2129 "Laitteisto ei ole saatavilla" #ifdef _WIN32 #define LIB_NAME_PCAP "WinPcap" #else #define LIB_NAME_PCAP "libpcap" #endif - IDS_2129 "Varmista, että " LIB_NAME_PCAP " on asennettu ja että verkkoyhteytesi on " LIB_NAME_PCAP "-yhteensopiva." - IDS_2130 "Virheelliset määritykset" -#ifdef _WIN32 -#define LIB_NAME_FREETYPE "freetype.dll" -#else -#define LIB_NAME_FREETYPE "libfreetype" -#endif - IDS_2131 LIB_NAME_FREETYPE " vaaditaan ESC/P-tulostimen emuloimiseksi." + IDS_2130 "Varmista, että " LIB_NAME_PCAP " on asennettu ja että verkkoyhteytesi on " LIB_NAME_PCAP "-yhteensopiva." + IDS_2131 "Virheelliset määritykset" #ifdef _WIN32 #define LIB_NAME_GS "gsdll32.dll" #else #define LIB_NAME_GS "libgs" #endif - IDS_2132 LIB_NAME_GS " vaaditaan PostScript-tiedostojen automaattiseen muuntamiseen PDF-tiedostoiksi.\n\nKaikki geneeriselle PostScript-tulostimelle lähetetyt asiakirjat tallennetaan PostScript (.ps) -tiedostoina." -#ifdef _WIN32 -#define LIB_NAME_FLUIDSYNTH "libfluidsynth.dll" -#else -#define LIB_NAME_FLUIDSYNTH "libfluidsynth" -#endif - IDS_2133 LIB_NAME_FLUIDSYNTH " vaaditaan FluidSynth MIDI-ulostuloa varten." - IDS_2134 "Siirrytään koko näytön tilaan" - IDS_2135 "Älä näytä tätä viestiä uudelleen" - IDS_2136 "Älä poistu" - IDS_2137 "Käynnistä uudelleen" - IDS_2138 "Älä käynnistä uudelleen" - IDS_2139 "MO-levykuvat (*.IM?;*.MDI)\0*.IM?;*.MDI\0Kaikki tiedostot (*.*)\0*.*\0" - IDS_2140 "CD-ROM-levykuvat (*.ISO;*.CUE)\0*.ISO;*.CUE\0Kaikki tiedostot (*.*)\0*.*\0" - IDS_2141 "%hs - Laitteen määritykset" - IDS_2142 "Näyttö lepotilassa" - IDS_2143 "OpenGL-varjostinohjelmat (*.GLSL)\0*.GLSL\0Kaikki tiedostot (*.*)\0*.*\0" - IDS_2144 "OpenGL-asetukset" - IDS_2145 "Olet lataamassa ei-tuettuja määrittelyjä" - IDS_2146 "Valittuun tietokoneeseen perustuva suoritintyypin suodatus ei ole käytössä tällä emuloidulla koneella.\n\nTämä mahdollistaa muutoin yhteensopimattoman suorittimen valinnan kyseisen tietokoneen kanssa. Voit kuitenkin kohdata ongelmia tietokoneen BIOS:in tai muun ohjelmiston kanssa.\n\nTämän asetuksen käyttö ei ole virallisesti tuettua ja kaikki tehdyt virheraportit voidaan sulkea epäpätevinä." - IDS_2147 "Jatka" - IDS_2148 "Kasetti: %s" - IDS_2149 "Kasetti-tiedostot (*.PCM;*.RAW;*.WAV;*.CAS)\0*.PCM;*.RAW;*.WAV;*.CAS\0Kaikki tiedostot (*.*)\0*.*\0" - IDS_2150 "ROM-moduuli %i: %ls" - IDS_2151 "ROM-moduulikuvat (*.A;*.B;*.JRC)\0*.A;*.B;*.JRC\0Kaikki tiedostot (*.*)\0*.*\0" - IDS_2152 "Virhe renderöijän alustuksessa" - IDS_2153 "OpenGL (3.0 Core) renderöijän alustus epäonnistui. Käytä toista renderöijää." - IDS_2154 "Resume execution" - IDS_2155 "Pause execution" - IDS_2156 "Press Ctrl+Alt+Del" - IDS_2157 "Press Ctrl+Alt+Esc" - IDS_2158 "Hard reset" - IDS_2159 "ACPI shutdown" - IDS_2160 "Settings" + IDS_2133 LIB_NAME_GS " vaaditaan PostScript-tiedostojen automaattiseen muuntamiseen PDF-tiedostoiksi.\n\nKaikki geneeriselle PostScript-tulostimelle lähetetyt asiakirjat tallennetaan PostScript (.ps) -tiedostoina." + IDS_2135 "Siirrytään koko näytön tilaan" + IDS_2136 "Älä näytä tätä viestiä uudelleen" + IDS_2137 "Älä poistu" + IDS_2138 "Käynnistä uudelleen" + IDS_2139 "Älä käynnistä uudelleen" + IDS_2140 "MO-levykuvat (*.IM?;*.MDI)\0*.IM?;*.MDI\0Kaikki tiedostot (*.*)\0*.*\0" + IDS_2141 "CD-ROM-levykuvat (*.ISO;*.CUE)\0*.ISO;*.CUE\0Kaikki tiedostot (*.*)\0*.*\0" + IDS_2142 "%hs - Laitteen määritykset" + IDS_2143 "Näyttö lepotilassa" + IDS_2144 "OpenGL-varjostinohjelmat (*.GLSL)\0*.GLSL\0Kaikki tiedostot (*.*)\0*.*\0" + IDS_2145 "OpenGL-asetukset" + IDS_2146 "Olet lataamassa ei-tuettuja määrittelyjä" + IDS_2147 "Valittuun tietokoneeseen perustuva suoritintyypin suodatus ei ole käytössä tällä emuloidulla koneella.\n\nTämä mahdollistaa muutoin yhteensopimattoman suorittimen valinnan kyseisen tietokoneen kanssa. Voit kuitenkin kohdata ongelmia tietokoneen BIOS:in tai muun ohjelmiston kanssa.\n\nTämän asetuksen käyttö ei ole virallisesti tuettua ja kaikki tehdyt virheraportit voidaan sulkea epäpätevinä." + IDS_2148 "Jatka" + IDS_2149 "Kasetti: %s" + IDS_2150 "Kasettitiedostot (*.PCM;*.RAW;*.WAV;*.CAS)\0*.PCM;*.RAW;*.WAV;*.CAS\0Kaikki tiedostot (*.*)\0*.*\0" + IDS_2151 "ROM-moduuli %i: %ls" + IDS_2152 "ROM-moduulikuvat (*.A;*.B;*.JRC)\0*.A;*.B;*.JRC\0Kaikki tiedostot (*.*)\0*.*\0" + IDS_2153 "Virhe renderöijän alustuksessa" + IDS_2154 "OpenGL (3.0 Core) -renderöijän alustus epäonnistui. Käytä toista renderöijää." + IDS_2155 "Jatka suoritusta" + IDS_2156 "Pysäytä suoritus" + IDS_2157 "Paina Ctrl+Alt+Del" + IDS_2158 "Paina Ctrl+Alt+Esc" + IDS_2159 "Kylmä uudelleenkäynnistys" + IDS_2160 "ACPI-sammutus" + IDS_2161 "Asetukset" + IDS_2162 "Type" + IDS_2163 "No Dynarec" + IDS_2164 "Old Dynarec" + IDS_2165 "New Dynarec" + IDS_2166 "Video card #2 ""%hs"" is not available due to missing ROMs in the roms/video directory. Disabling the second video card." + IDS_2167 "Failed to initialize network driver" + IDS_2168 "The network configuration will be switched to the null driver" END STRINGTABLE DISCARDABLE @@ -517,12 +537,12 @@ BEGIN IDS_4096 "Kiintolevy (%s)" IDS_4097 "%01i:%01i" IDS_4098 "%01i" - IDS_4099 "MFM/RLL tai ESDI CD-ROM asemia ei ole koskaan ollut olemassa" + IDS_4099 "MFM/RLL- tai ESDI-CD-ROM-asemia ei ole koskaan ollut olemassa" IDS_4100 "Mukautettu..." IDS_4101 "Mukautettu (suuri)..." IDS_4102 "Lisää uusi kiintolevy" IDS_4103 "Lisää olemassaoleva kiintolevy" - IDS_4104 "HDI levykuvan suurin mahdollinen koko on 4 Gt." + IDS_4104 "HDI-levykuvan suurin mahdollinen koko on 4 Gt." IDS_4105 "Levykuvien suurin mahdollinen koko on 127 Gt." IDS_4106 "Kiintolevykuvat (*.HD?;*.IM?;*.VHD)\0*.HD?;*.IM?;*.VHD\0Kaikki tiedostot (*.*)\0*.*\0" IDS_4107 "Tiedostoa ei voi lukea" @@ -536,10 +556,10 @@ BEGIN IDS_4115 "Varmista, että tiedoston tallennuskansioon on kirjoitusoikeus" IDS_4116 "Liian suuri levykuva" IDS_4117 "Muista osioida ja alustaa juuri luomasi asema." - IDS_4118 "Valittu tiedosto ylikirjoitetaan. Oletko varma, että haluat käyttää sitä?" - IDS_4119 "Levynkuvaa ei tueta" - IDS_4120 "Ylikirjoita" - IDS_4121 "Älä ylikirjoita" + IDS_4118 "Valittu tiedosto korvataan. Oletko varma, että haluat käyttää sitä?" + IDS_4119 "Levykuvaa ei tueta" + IDS_4120 "Korvaa" + IDS_4121 "Älä korvaa" IDS_4122 "Raaka levykuva (.img)" IDS_4123 "HDI-levykuva (.hdi)" IDS_4124 "HDX-levykuva (.hdx)" @@ -611,7 +631,7 @@ BEGIN IDS_7168 "(Järjestelmän oletus)" END -#define IDS_LANG_ENUS IDS_7168 +#define IDS_LANG_ENUS IDS_7168 // English (U.S.) resources ///////////////////////////////////////////////////////////////////////////// diff --git a/src/win/languages/fr-FR.rc b/src/win/languages/fr-FR.rc index 7f76c649c..1ad5a4da1 100644 --- a/src/win/languages/fr-FR.rc +++ b/src/win/languages/fr-FR.rc @@ -13,113 +13,122 @@ LANGUAGE LANG_FRENCH, SUBLANG_FRENCH // Menu // -MainMenu MENU DISCARDABLE +MainMenu MENU DISCARDABLE BEGIN POPUP "&Action" BEGIN - MENUITEM "&Capturer le clavier", IDM_ACTION_KBD_REQ_CAPTURE - MENUITEM "CTRL &Droite devient ALT Gauche", IDM_ACTION_RCTRL_IS_LALT + MENUITEM "&Capturer le clavier", IDM_ACTION_KBD_REQ_CAPTURE + MENUITEM "CTRL &Droite devient ALT Gauche", IDM_ACTION_RCTRL_IS_LALT MENUITEM SEPARATOR - MENUITEM "&Hard Reset...", IDM_ACTION_HRESET - MENUITEM "&Ctrl+Alt+Del\tCtrl+F12", IDM_ACTION_RESET_CAD + MENUITEM "&Hard Reset...", IDM_ACTION_HRESET + MENUITEM "&Ctrl+Alt+Del\tCtrl+F12", IDM_ACTION_RESET_CAD MENUITEM SEPARATOR - MENUITEM "Ctrl+Alt+&Esc", IDM_ACTION_CTRL_ALT_ESC + MENUITEM "Ctrl+Alt+&Esc", IDM_ACTION_CTRL_ALT_ESC MENUITEM SEPARATOR - MENUITEM "&Pause", IDM_ACTION_PAUSE + MENUITEM "&Pause", IDM_ACTION_PAUSE MENUITEM SEPARATOR - MENUITEM "&Quitter...", IDM_ACTION_EXIT + MENUITEM "&Quitter...", IDM_ACTION_EXIT END POPUP "&Vue" BEGIN - MENUITEM "&Masquer la barre de status", IDM_VID_HIDE_STATUS_BAR - MENUITEM "Hide &toolbar", IDM_VID_HIDE_TOOLBAR + MENUITEM "&Masquer la barre de status", IDM_VID_HIDE_STATUS_BAR + MENUITEM "Hide &toolbar", IDM_VID_HIDE_TOOLBAR MENUITEM SEPARATOR - MENUITEM "Fenètre &Retaillable", IDM_VID_RESIZE - MENUITEM "S&auvegarder taille && position", IDM_VID_REMEMBER + MENUITEM "&Show non-primary monitors", IDM_VID_MONITORS + MENUITEM "Fenètre &Retaillable", IDM_VID_RESIZE + MENUITEM "S&auvegarder taille && position", IDM_VID_REMEMBER MENUITEM SEPARATOR POPUP "Moteur de &rendu vidéo" BEGIN - MENUITEM "&SDL (Logiciel)", IDM_VID_SDL_SW - MENUITEM "SDL (&Materiel)", IDM_VID_SDL_HW - MENUITEM "SDL (&OpenGL)", IDM_VID_SDL_OPENGL - MENUITEM "Open&GL (3.0 Core)", IDM_VID_OPENGL_CORE + MENUITEM "&SDL (Logiciel)", IDM_VID_SDL_SW + MENUITEM "SDL (&Materiel)", IDM_VID_SDL_HW + MENUITEM "SDL (&OpenGL)", IDM_VID_SDL_OPENGL + MENUITEM "Open&GL (3.0 Core)", IDM_VID_OPENGL_CORE #ifdef USE_VNC - MENUITEM "&VNC", IDM_VID_VNC + MENUITEM "&VNC", IDM_VID_VNC #endif END MENUITEM SEPARATOR - MENUITEM "Specifier dimensions...", IDM_VID_SPECIFY_DIM - MENUITEM "F&orcer 4:3", IDM_VID_FORCE43 + MENUITEM "Specifier dimensions...", IDM_VID_SPECIFY_DIM + MENUITEM "F&orcer 4:3", IDM_VID_FORCE43 POPUP "&Echelle facteur" BEGIN - MENUITEM "&0.5x", IDM_VID_SCALE_1X - MENUITEM "&1x", IDM_VID_SCALE_2X - MENUITEM "1.&5x", IDM_VID_SCALE_3X - MENUITEM "&2x", IDM_VID_SCALE_4X + MENUITEM "&0.5x", IDM_VID_SCALE_1X + MENUITEM "&1x", IDM_VID_SCALE_2X + MENUITEM "1.&5x", IDM_VID_SCALE_3X + MENUITEM "&2x", IDM_VID_SCALE_4X + MENUITEM "&3x", IDM_VID_SCALE_5X + MENUITEM "&4x", IDM_VID_SCALE_6X + MENUITEM "&5x", IDM_VID_SCALE_7X + MENUITEM "&6x", IDM_VID_SCALE_8X + MENUITEM "&7x", IDM_VID_SCALE_9X + MENUITEM "&8x", IDM_VID_SCALE_10X END POPUP "Methode Filtre" BEGIN - MENUITEM "&Plus proche", IDM_VID_FILTER_NEAREST - MENUITEM "&Lineaire", IDM_VID_FILTER_LINEAR + MENUITEM "&Plus proche", IDM_VID_FILTER_NEAREST + MENUITEM "&Lineaire", IDM_VID_FILTER_LINEAR END - MENUITEM "Mise à l'échelle Hi&DPI", IDM_VID_HIDPI + MENUITEM "Mise à l'échelle Hi&DPI", IDM_VID_HIDPI MENUITEM SEPARATOR - MENUITEM "&Plein Ecran\tCtrl+Alt+PgUp", IDM_VID_FULLSCREEN + MENUITEM "&Plein Ecran\tCtrl+Alt+PgUp", IDM_VID_FULLSCREEN POPUP "Mode &Elargi plein écran" BEGIN - MENUITEM "&Plein écran étiré", IDM_VID_FS_FULL - MENUITEM "&4:3", IDM_VID_FS_43 + MENUITEM "&Plein écran étiré", IDM_VID_FS_FULL + MENUITEM "&4:3", IDM_VID_FS_43 MENUITEM "pixels &Carrés(Keep ratio)", IDM_VID_FS_KEEPRATIO - MENUITEM "Echelle &Entière", IDM_VID_FS_INT + MENUITEM "Echelle &Entière", IDM_VID_FS_INT END POPUP "Réglages E&GA/(S)VGA" BEGIN - MENUITEM "Moniteur VGA &Inversé", IDM_VID_INVERT + MENUITEM "Moniteur VGA &Inversé", IDM_VID_INVERT POPUP "&Type Ecran VGA" BEGIN - MENUITEM "RGB &Couleur", IDM_VID_GRAY_RGB - MENUITEM "&RGB Ton de Gris", IDM_VID_GRAY_MONO - MENUITEM "Moniteur &Ambre", IDM_VID_GRAY_AMBER - MENUITEM "Moniteur &Vert", IDM_VID_GRAY_GREEN - MENUITEM "Moniteur &Blanc", IDM_VID_GRAY_WHITE + MENUITEM "RGB &Couleur", IDM_VID_GRAY_RGB + MENUITEM "&RGB Ton de Gris", IDM_VID_GRAY_MONO + MENUITEM "Moniteur &Ambre", IDM_VID_GRAY_AMBER + MENUITEM "Moniteur &Vert", IDM_VID_GRAY_GREEN + MENUITEM "Moniteur &Blanc", IDM_VID_GRAY_WHITE END POPUP "Grayscale &conversion type" BEGIN - MENUITEM "BT&601 (NTSC/PAL)", IDM_VID_GRAYCT_601 - MENUITEM "BT&709 (HDTV)", IDM_VID_GRAYCT_709 - MENUITEM "&Moyenne", IDM_VID_GRAYCT_AVE + MENUITEM "BT&601 (NTSC/PAL)", IDM_VID_GRAYCT_601 + MENUITEM "BT&709 (HDTV)", IDM_VID_GRAYCT_709 + MENUITEM "&Moyenne", IDM_VID_GRAYCT_AVE END END MENUITEM SEPARATOR - MENUITEM "CGA/PCjr/Tandy/E&GA/(S)VGA overscan", IDM_VID_OVERSCAN + MENUITEM "CGA/PCjr/Tandy/E&GA/(S)VGA overscan", IDM_VID_OVERSCAN MENUITEM "Modifier contraste affichage &monochrome", IDM_VID_CGACON END - MENUITEM "&Media", IDM_MEDIA + MENUITEM "&Media", IDM_MEDIA POPUP "Ou&tils" BEGIN - MENUITEM "&Réglages...", IDM_CONFIG - MENUITEM "Mettre à jour la barre de stat&us", IDM_UPDATE_ICONS + MENUITEM "&Réglages...", IDM_CONFIG + MENUITEM "Mettre à jour la barre de stat&us", IDM_UPDATE_ICONS MENUITEM SEPARATOR - MENUITEM "Copie &Ecran\tCtrl+F11", IDM_ACTION_SCREENSHOT + MENUITEM "Copie &Ecran\tCtrl+F11", IDM_ACTION_SCREENSHOT MENUITEM SEPARATOR - MENUITEM "&Préférences...", IDM_PREFERENCES + MENUITEM "&Préférences...", IDM_PREFERENCES +#ifdef DISCORD MENUITEM "Activer intégration &Discord", IDM_DISCORD +#endif MENUITEM SEPARATOR - MENUITEM "&Gain Son...", IDM_SND_GAIN + MENUITEM "&Gain Son...", IDM_SND_GAIN #ifdef MTR_ENABLED MENUITEM SEPARATOR - MENUITEM "Démarrer traces\tCtrl+T", IDM_ACTION_BEGIN_TRACE - MENUITEM "Finir traces\tCtrl+T", IDM_ACTION_END_TRACE + MENUITEM "Démarrer traces\tCtrl+T", IDM_ACTION_BEGIN_TRACE + MENUITEM "Finir traces\tCtrl+T", IDM_ACTION_END_TRACE #endif END POPUP "&Aide" BEGIN - MENUITEM "&Documentation...", IDM_DOCS - MENUITEM "&A Propos de 86Box...", IDM_ABOUT + MENUITEM "&Documentation...", IDM_DOCS + MENUITEM "&A Propos de 86Box...", IDM_ABOUT END END -StatusBarMenu MENU DISCARDABLE +StatusBarMenu MENU DISCARDABLE BEGIN MENUITEM SEPARATOR END @@ -128,17 +137,17 @@ CassetteSubmenu MENU DISCARDABLE BEGIN POPUP "" BEGIN - MENUITEM "&Nouvelle image...", IDM_CASSETTE_IMAGE_NEW + MENUITEM "&Nouvelle image...", IDM_CASSETTE_IMAGE_NEW MENUITEM SEPARATOR - MENUITEM "Image &Existante...", IDM_CASSETTE_IMAGE_EXISTING - MENUITEM "Image Existante(&Lecture seule)...", IDM_CASSETTE_IMAGE_EXISTING_WP + MENUITEM "Image &Existante...", IDM_CASSETTE_IMAGE_EXISTING + MENUITEM "Image Existante(&Lecture seule)...", IDM_CASSETTE_IMAGE_EXISTING_WP MENUITEM SEPARATOR - MENUITEM "En®istrer", IDM_CASSETTE_RECORD - MENUITEM "&Jouer", IDM_CASSETTE_PLAY - MENUITEM "&Revenir au debut", IDM_CASSETTE_REWIND - MENUITEM "Aller à la &Fin", IDM_CASSETTE_FAST_FORWARD + MENUITEM "En®istrer", IDM_CASSETTE_RECORD + MENUITEM "&Jouer", IDM_CASSETTE_PLAY + MENUITEM "&Revenir au debut", IDM_CASSETTE_REWIND + MENUITEM "Aller à la &Fin", IDM_CASSETTE_FAST_FORWARD MENUITEM SEPARATOR - MENUITEM "E&jecter", IDM_CASSETTE_EJECT + MENUITEM "E&jecter", IDM_CASSETTE_EJECT END END @@ -146,9 +155,9 @@ CartridgeSubmenu MENU DISCARDABLE BEGIN POPUP "" BEGIN - MENUITEM "&Image...", IDM_CARTRIDGE_IMAGE + MENUITEM "&Image...", IDM_CARTRIDGE_IMAGE MENUITEM SEPARATOR - MENUITEM "E&jecter", IDM_CARTRIDGE_EJECT + MENUITEM "E&jecter", IDM_CARTRIDGE_EJECT END END @@ -156,14 +165,14 @@ FloppySubmenu MENU DISCARDABLE BEGIN POPUP "" BEGIN - MENUITEM "&Nouvelle image...", IDM_FLOPPY_IMAGE_NEW + MENUITEM "&Nouvelle image...", IDM_FLOPPY_IMAGE_NEW MENUITEM SEPARATOR - MENUITEM "Image &Existante...", IDM_FLOPPY_IMAGE_EXISTING - MENUITEM "Image Existante(&Lecture seule)...", IDM_FLOPPY_IMAGE_EXISTING_WP + MENUITEM "Image &Existante...", IDM_FLOPPY_IMAGE_EXISTING + MENUITEM "Image Existante(&Lecture seule)...", IDM_FLOPPY_IMAGE_EXISTING_WP MENUITEM SEPARATOR - MENUITEM "E&xport vers 86F...", IDM_FLOPPY_EXPORT_TO_86F + MENUITEM "E&xport vers 86F...", IDM_FLOPPY_EXPORT_TO_86F MENUITEM SEPARATOR - MENUITEM "E&jecter", IDM_FLOPPY_EJECT + MENUITEM "E&jecter", IDM_FLOPPY_EJECT END END @@ -171,12 +180,13 @@ CdromSubmenu MENU DISCARDABLE BEGIN POPUP "" BEGIN - MENUITEM "&Couper", IDM_CDROM_MUTE + MENUITEM "&Couper", IDM_CDROM_MUTE MENUITEM SEPARATOR - MENUITEM "E&jecter", IDM_CDROM_EMPTY - MENUITEM "&Recharger image précedente", IDM_CDROM_RELOAD + MENUITEM "E&jecter", IDM_CDROM_EMPTY + MENUITEM "&Recharger image précedente", IDM_CDROM_RELOAD MENUITEM SEPARATOR - MENUITEM "&Image", IDM_CDROM_IMAGE + MENUITEM "&Image...", IDM_CDROM_IMAGE + MENUITEM "&Dossier...", IDM_CDROM_DIR END END @@ -184,13 +194,13 @@ ZIPSubmenu MENU DISCARDABLE BEGIN POPUP "" BEGIN - MENUITEM "&Nouvelle image...", IDM_ZIP_IMAGE_NEW + MENUITEM "&Nouvelle image...", IDM_ZIP_IMAGE_NEW MENUITEM SEPARATOR - MENUITEM "Image &Existante...", IDM_ZIP_IMAGE_EXISTING - MENUITEM "Image Existante (&Lecture Seule)...", IDM_ZIP_IMAGE_EXISTING_WP + MENUITEM "Image &Existante...", IDM_ZIP_IMAGE_EXISTING + MENUITEM "Image Existante (&Lecture Seule)...", IDM_ZIP_IMAGE_EXISTING_WP MENUITEM SEPARATOR - MENUITEM "E&jecter", IDM_ZIP_EJECT - MENUITEM "&Recharger image précédente", IDM_ZIP_RELOAD + MENUITEM "E&jecter", IDM_ZIP_EJECT + MENUITEM "&Recharger image précédente", IDM_ZIP_RELOAD END END @@ -198,13 +208,13 @@ MOSubmenu MENU DISCARDABLE BEGIN POPUP "" BEGIN - MENUITEM "&Nouvelle image...", IDM_MO_IMAGE_NEW + MENUITEM "&Nouvelle image...", IDM_MO_IMAGE_NEW MENUITEM SEPARATOR - MENUITEM "Image &Existante...", IDM_MO_IMAGE_EXISTING - MENUITEM "Image Existante (&Lecture Seule)...", IDM_MO_IMAGE_EXISTING_WP + MENUITEM "Image &Existante...", IDM_MO_IMAGE_EXISTING + MENUITEM "Image Existante (&Lecture Seule)...", IDM_MO_IMAGE_EXISTING_WP MENUITEM SEPARATOR - MENUITEM "E&jecter", IDM_MO_EJECT - MENUITEM "&Recharger image précédente", IDM_MO_RELOAD + MENUITEM "E&jecter", IDM_MO_EJECT + MENUITEM "&Recharger image précédente", IDM_MO_RELOAD END END @@ -230,134 +240,150 @@ END // Dialog // -#define STR_PREFERENCES "Préférences" -#define STR_SND_GAIN "Gain son" -#define STR_NEW_FLOPPY "Nouvelle image" -#define STR_CONFIG "Réglages" -#define STR_SPECIFY_DIM "Spécifier le détournement de la fenêtre principale" +#define STR_PREFERENCES "Préférences" +#define STR_SND_GAIN "Gain son" +#define STR_NEW_FLOPPY "Nouvelle image" +#define STR_CONFIG "Réglages" +#define STR_SPECIFY_DIM "Spécifier le détournement de la fenêtre principale" -#define STR_OK "OK" -#define STR_CANCEL "Annuler" -#define STR_GLOBAL "Sauvegarder ces paramètres comme valeurs par défaut &globales" -#define STR_DEFAULT "&Défaut" -#define STR_LANGUAGE "Langue:" -#define STR_ICONSET "Ensemble d'icônes:" +#define STR_OK "OK" +#define STR_CANCEL "Annuler" +#define STR_GLOBAL "Sauvegarder ces paramètres comme valeurs par défaut &globales" +#define STR_DEFAULT "&Défaut" +#define STR_LANGUAGE "Langue:" +#define STR_ICONSET "Ensemble d'icônes:" -#define STR_GAIN "Gain" +#define STR_GAIN "Gain" -#define STR_FILE_NAME "Nom fichier:" -#define STR_DISK_SIZE "Taille disque:" -#define STR_RPM_MODE "Mode RPM:" -#define STR_PROGRESS "Progrès:" +#define STR_FILE_NAME "Nom fichier:" +#define STR_DISK_SIZE "Taille disque:" +#define STR_RPM_MODE "Mode RPM:" +#define STR_PROGRESS "Progrès:" -#define STR_WIDTH "Largeur:" -#define STR_HEIGHT "Hauteur:" -#define STR_LOCK_TO_SIZE "Verrouiller à cette taille" +#define STR_WIDTH "Largeur:" +#define STR_HEIGHT "Hauteur:" +#define STR_LOCK_TO_SIZE "Verrouiller à cette taille" -#define STR_MACHINE_TYPE "Type de machine:" -#define STR_MACHINE "Machine:" -#define STR_CONFIGURE "Configurer" -#define STR_CPU_TYPE "Type du processeur:" -#define STR_CPU_SPEED "Vitesse:" -#define STR_FPU "FPU:" -#define STR_WAIT_STATES "États d'attente:" -#define STR_MB "Mo" -#define STR_MEMORY "Mémoire:" -#define STR_TIME_SYNC "Synchronisation du temps" -#define STR_DISABLED "Désactivé" -#define STR_ENABLED_LOCAL "Activé (heure locale)" -#define STR_ENABLED_UTC "Activé (UTC)" -#define STR_DYNAREC "Recompilateur dynamique" +#define STR_MACHINE_TYPE "Type de machine:" +#define STR_MACHINE "Machine:" +#define STR_CONFIGURE "Configurer" +#define STR_CPU_TYPE "Type du processeur:" +#define STR_CPU_SPEED "Vitesse:" +#define STR_FPU "FPU:" +#define STR_WAIT_STATES "États d'attente:" +#define STR_MB "Mo" +#define STR_MEMORY "Mémoire:" +#define STR_TIME_SYNC "Synchronisation du temps" +#define STR_DISABLED "Désactivé" +#define STR_ENABLED_LOCAL "Activé (heure locale)" +#define STR_ENABLED_UTC "Activé (UTC)" +#define STR_DYNAREC "Recompilateur dynamique" +#define STR_SOFTFLOAT "Softfloat FPU" -#define STR_VIDEO "Vidéo:" -#define STR_VOODOO "Graphique Voodoo" +#define STR_VIDEO "Vidéo:" +#define STR_VIDEO_2 "Vidéo 2:" +#define STR_VOODOO "Graphique Voodoo" +#define STR_IBM8514 "Graphique IBM 8514/a" +#define STR_XGA "Graphique XGA" -#define STR_MOUSE "Souris:" -#define STR_JOYSTICK "Manette de commande:" -#define STR_JOY1 "Manette 1..." -#define STR_JOY2 "Manette 2..." -#define STR_JOY3 "Manette 3..." -#define STR_JOY4 "Manette 4..." +#define STR_MOUSE "Souris:" +#define STR_JOYSTICK "Manette de commande:" +#define STR_JOY1 "Manette 1..." +#define STR_JOY2 "Manette 2..." +#define STR_JOY3 "Manette 3..." +#define STR_JOY4 "Manette 4..." -#define STR_SOUND "Carte son:" -#define STR_MIDI_OUT "Sortie MIDI:" -#define STR_MIDI_IN "Entrée MIDI:" -#define STR_MPU401 "MPU-401 autonome" -#define STR_SSI "Innovation SSI-2001" -#define STR_CMS "CMS / Game Blaster" -#define STR_GUS "Gravis Ultrasound" -#define STR_FLOAT "Utiliser le son FLOAT32" +#define STR_SOUND1 "Carte son 1:" +#define STR_SOUND2 "Carte son 2:" +#define STR_SOUND3 "Carte son 3:" +#define STR_SOUND4 "Carte son 4:" +#define STR_MIDI_OUT "Sortie MIDI:" +#define STR_MIDI_IN "Entrée MIDI:" +#define STR_MPU401 "MPU-401 autonome" +#define STR_FLOAT "Utiliser le son FLOAT32" +#define STR_FM_DRIVER "Pilote de synthétiseur FM" +#define STR_FM_DRV_NUKED "Nuked (plus précis)" +#define STR_FM_DRV_YMFM "YMFM (plus rapide)" -#define STR_NET_TYPE "Type de réseau:" -#define STR_PCAP "Dispositif PCap:" -#define STR_NET "Adaptateur de réseau:" +#define STR_NET_TYPE "Type de réseau:" +#define STR_PCAP "Dispositif PCap:" +#define STR_NET "Adaptateur de réseau:" +#define STR_NET1 "Network card 1:" +#define STR_NET2 "Network card 2:" +#define STR_NET3 "Network card 3:" +#define STR_NET4 "Network card 4:" -#define STR_COM1 "Dispositif COM1:" -#define STR_COM2 "Dispositif COM2:" -#define STR_COM3 "Dispositif COM3:" -#define STR_COM4 "Dispositif COM4:" -#define STR_LPT1 "Dispositif LPT1:" -#define STR_LPT2 "Dispositif LPT2:" -#define STR_LPT3 "Dispositif LPT3:" -#define STR_LPT4 "Dispositif LPT4:" -#define STR_SERIAL1 "Port série 1" -#define STR_SERIAL2 "Port série 2" -#define STR_SERIAL3 "Port série 3" -#define STR_SERIAL4 "Port série 4" -#define STR_PARALLEL1 "Port parallèle 1" -#define STR_PARALLEL2 "Port parallèle 2" -#define STR_PARALLEL3 "Port parallèle 3" -#define STR_PARALLEL4 "Port parallèle 4" +#define STR_COM1 "Dispositif COM1:" +#define STR_COM2 "Dispositif COM2:" +#define STR_COM3 "Dispositif COM3:" +#define STR_COM4 "Dispositif COM4:" +#define STR_LPT1 "Dispositif LPT1:" +#define STR_LPT2 "Dispositif LPT2:" +#define STR_LPT3 "Dispositif LPT3:" +#define STR_LPT4 "Dispositif LPT4:" +#define STR_SERIAL1 "Port série 1" +#define STR_SERIAL2 "Port série 2" +#define STR_SERIAL3 "Port série 3" +#define STR_SERIAL4 "Port série 4" +#define STR_PARALLEL1 "Port parallèle 1" +#define STR_PARALLEL2 "Port parallèle 2" +#define STR_PARALLEL3 "Port parallèle 3" +#define STR_PARALLEL4 "Port parallèle 4" +#define STR_SERIAL_PASS1 "Serial port passthrough 1" +#define STR_SERIAL_PASS2 "Serial port passthrough 2" +#define STR_SERIAL_PASS3 "Serial port passthrough 3" +#define STR_SERIAL_PASS4 "Serial port passthrough 4" -#define STR_HDC "Contrôleur HD:" -#define STR_FDC "Contrôleur FD:" -#define STR_IDE_TER "Contrôleur IDE tertiaire" -#define STR_IDE_QUA "Contrôleur IDE quaternair" -#define STR_SCSI "SCSI" -#define STR_SCSI_1 "Contrôleur 1:" -#define STR_SCSI_2 "Contrôleur 2:" -#define STR_SCSI_3 "Contrôleur 3:" -#define STR_SCSI_4 "Contrôleur 4:" -#define STR_CASSETTE "Cassette" +#define STR_HDC "Contrôleur HD:" +#define STR_FDC "Contrôleur FD:" +#define STR_IDE_TER "Contrôleur IDE tertiaire" +#define STR_IDE_QUA "Contrôleur IDE quaternair" +#define STR_SCSI "SCSI" +#define STR_SCSI_1 "Contrôleur 1:" +#define STR_SCSI_2 "Contrôleur 2:" +#define STR_SCSI_3 "Contrôleur 3:" +#define STR_SCSI_4 "Contrôleur 4:" +#define STR_CASSETTE "Cassette" -#define STR_HDD "Disques durs:" -#define STR_NEW "&Nouveau..." -#define STR_EXISTING "&Existant..." -#define STR_REMOVE "&Supprimer" -#define STR_BUS "Bus:" -#define STR_CHANNEL "Canal:" -#define STR_ID "ID:" +#define STR_HDD "Disques durs:" +#define STR_NEW "&Nouveau..." +#define STR_EXISTING "&Existant..." +#define STR_REMOVE "&Supprimer" +#define STR_BUS "Bus:" +#define STR_CHANNEL "Canal:" +#define STR_ID "ID:" +#define STR_SPEED "Speed:" -#define STR_SPECIFY "&Spécifier..." -#define STR_SECTORS "Secteurs:" -#define STR_HEADS "Têtes:" -#define STR_CYLS "Cylindres:" -#define STR_SIZE_MB "Taille (Mo):" -#define STR_TYPE "Type:" -#define STR_IMG_FORMAT "Format Image:" -#define STR_BLOCK_SIZE "Taille du bloc:" +#define STR_SPECIFY "&Spécifier..." +#define STR_SECTORS "Secteurs:" +#define STR_HEADS "Têtes:" +#define STR_CYLS "Cylindres:" +#define STR_SIZE_MB "Taille (Mo):" +#define STR_TYPE "Type:" +#define STR_IMG_FORMAT "Format Image:" +#define STR_BLOCK_SIZE "Taille du bloc:" -#define STR_FLOPPY_DRIVES "Lecteurs de disquettes:" -#define STR_TURBO "Turbo" -#define STR_CHECKBPB "Vérifier BPB" -#define STR_CDROM_DRIVES "Lecterus CD-ROM:" -#define STR_CD_SPEED "Vitesse:" +#define STR_FLOPPY_DRIVES "Lecteurs de disquettes:" +#define STR_TURBO "Turbo" +#define STR_CHECKBPB "Vérifier BPB" +#define STR_CDROM_DRIVES "Lecterus CD-ROM:" +#define STR_CD_SPEED "Vitesse:" -#define STR_MO_DRIVES "Lecteurs magnéto-optiques:" -#define STR_ZIP_DRIVES "Lecteurs ZIP:" -#define STR_250 "ZIP 250" +#define STR_MO_DRIVES "Lecteurs magnéto-optiques:" +#define STR_ZIP_DRIVES "Lecteurs ZIP:" +#define STR_250 "ZIP 250" -#define STR_ISARTC "Horloge temps réel ISA:" -#define STR_ISAMEM "Expansion de la mémoire ISA" -#define STR_ISAMEM_1 "Carte 1:" -#define STR_ISAMEM_2 "Carte 2:" -#define STR_ISAMEM_3 "Carte 3:" -#define STR_ISAMEM_4 "Carte 4:" -#define STR_BUGGER "Dispositif ISABugger" -#define STR_POSTCARD "Carte POST" +#define STR_ISARTC "Horloge temps réel ISA:" +#define STR_ISAMEM "Expansion de la mémoire ISA" +#define STR_ISAMEM_1 "Carte 1:" +#define STR_ISAMEM_2 "Carte 2:" +#define STR_ISAMEM_3 "Carte 3:" +#define STR_ISAMEM_4 "Carte 4:" +#define STR_BUGGER "Dispositif ISABugger" +#define STR_POSTCARD "Carte POST" -#define FONT_SIZE 9 -#define FONT_NAME "Segoe UI" +#define FONT_SIZE 9 +#define FONT_NAME "Segoe UI" #include "dialogs.rc" @@ -366,194 +392,188 @@ END // String Table // -STRINGTABLE DISCARDABLE +STRINGTABLE DISCARDABLE BEGIN - 2048 "86Box" - IDS_2049 "Erreur" - IDS_2050 "Erreur fatale" - IDS_2051 " - PAUSED" - IDS_2052 "Appuyez sur Ctrl+Alt+PgDn pour revenir au mode fenêtré." - IDS_2053 "Vitesse" - IDS_2054 "ZIP %03i %i (%s): %ls" - IDS_2055 "Images ZIP (*.IM?;*.ZDI)\0*.IM?;*.ZDI\0" - IDS_2056 "86Box n'a pas pu trouver d'images ROM utilisables.\n\nS'il vous plait, téléchargez un ensemble ROM et extrayez-le dans le répertoire ""roms""." - IDS_2057 "(vide)" - IDS_2058 "Images ZIP (*.IM?;*.ZDI)\0*.IM?;*.ZDI\0Tous les fichiers (*.*)\0*.*\0" - IDS_2059 "Turbo" - IDS_2060 "Activé" - IDS_2061 "Désactivé" - IDS_2062 "Tous les images (*.86F;*.DSK;*.FLP;*.IM?;*.*FD?)\0*.86F;*.DSK;*.FLP;*.IM?;*.*FD?\0Images basiques du secteur (*.DSK;*.FLP;*.IM?;*.*FD?)\0*.DSK;*.FLP;*.IM?;*.IMG;*.*FD?\0Images de la surface (*.86F)\0*.86F\0" - IDS_2063 "La machine ""%hs"" n'est pas disponible en raison de l'absence de ROMs dans le répertoire roms/machines. Basculer vers une machine disponible." + 2048 "86Box" + IDS_2049 "Erreur" + IDS_2050 "Erreur fatale" + IDS_2051 " - PAUSED" + IDS_2052 "Appuyez sur Ctrl+Alt+PgDn pour revenir au mode fenêtré." + IDS_2053 "Vitesse" + IDS_2054 "ZIP %03i %i (%s): %ls" + IDS_2055 "Images ZIP (*.IM?;*.ZDI)\0*.IM?;*.ZDI\0" + IDS_2056 "86Box n'a pas pu trouver d'images ROM utilisables.\n\nS'il vous plait, téléchargez un ensemble ROM et extrayez-le dans le répertoire ""roms""." + IDS_2057 "(vide)" + IDS_2058 "Images ZIP (*.IM?;*.ZDI)\0*.IM?;*.ZDI\0Tous les fichiers (*.*)\0*.*\0" + IDS_2059 "Turbo" + IDS_2060 "Activé" + IDS_2061 "Désactivé" + IDS_2062 "Tous les images (*.86F;*.DSK;*.FLP;*.IM?;*.*FD?)\0*.86F;*.DSK;*.FLP;*.IM?;*.*FD?\0Images basiques du secteur (*.DSK;*.FLP;*.IM?;*.*FD?)\0*.DSK;*.FLP;*.IM?;*.IMG;*.*FD?\0Images de la surface (*.86F)\0*.86F\0" + IDS_2063 "La machine ""%hs"" n'est pas disponible en raison de l'absence de ROMs dans le répertoire roms/machines. Basculer vers une machine disponible." END -STRINGTABLE DISCARDABLE +STRINGTABLE DISCARDABLE BEGIN - IDS_2064 "La carte vidéo ""%hs"" n'est pas disponible en raison de l'absence de ROMs dans le répertoire roms/video. Basculer vers une carte vidéo disponible." - IDS_2065 "Machine" - IDS_2066 "Affichage" - IDS_2067 "Dispositifs d'entrée" - IDS_2068 "Son" - IDS_2069 "Réseau" - IDS_2070 "Ports (COM et LPT)" - IDS_2071 "Contrôleurs de stockage" - IDS_2072 "Disques durs" - IDS_2073 "Lecteurs de disquette et CD-ROM" - IDS_2074 "Autres dispositifs amovibles" - IDS_2075 "Autres périfériques" - IDS_2076 "Images de surface (*.86F)\0*.86F\0" - IDS_2077 "Cliquer pour capturer la souris" - IDS_2078 "Appuyer sur F8+F12 pour libérer la souris" - IDS_2079 "Appuyer sur F8+F12 ou le bouton central pour libérer la souris" + IDS_2064 "La carte vidéo ""%hs"" n'est pas disponible en raison de l'absence de ROMs dans le répertoire roms/video. Basculer vers une carte vidéo disponible." + IDS_2065 "Machine" + IDS_2066 "Affichage" + IDS_2067 "Dispositifs d'entrée" + IDS_2068 "Son" + IDS_2069 "Réseau" + IDS_2070 "Ports (COM et LPT)" + IDS_2071 "Contrôleurs de stockage" + IDS_2072 "Disques durs" + IDS_2073 "Lecteurs de disquette et CD-ROM" + IDS_2074 "Autres dispositifs amovibles" + IDS_2075 "Autres périfériques" + IDS_2076 "Images de surface (*.86F)\0*.86F\0" + IDS_2077 "Cliquer pour capturer la souris" + IDS_2078 "Appuyer sur F8+F12 pour libérer la souris" + IDS_2079 "Appuyer sur F8+F12 ou le bouton central pour libérer la souris" END -STRINGTABLE DISCARDABLE +STRINGTABLE DISCARDABLE BEGIN - IDS_2080 "Impossible d'initialiser FluidSynth" - IDS_2081 "Bus" - IDS_2082 "File" - IDS_2083 "C" - IDS_2084 "T" - IDS_2085 "S" - IDS_2086 "Mo" - IDS_2087 "Vérifier BPB" - IDS_2088 "Ko" - IDS_2089 "Impossible d'initialiser le moteur de rendu vidéo." - IDS_2090 "Défaut" - IDS_2091 "%i état(s) d'attente" - IDS_2092 "Type" - IDS_2093 "Impossible d'initialiser PCap" - IDS_2094 "Aucun dispositif PCap trouvé" - IDS_2095 "Dispositif PCap non valide" - IDS_2096 "Manette(s) standard avec 2 boutons" - IDS_2097 "Manette standard avec 4 boutons" - IDS_2098 "Manette standard avec 6 boutons" - IDS_2099 "Manette standard avec 6 boutons" - IDS_2100 "CH Flightstick Pro" - IDS_2101 "Microsoft SideWinder Pad" - IDS_2102 "Système de contrôle de vol Thrustmaster" - IDS_2103 "Aucun" - IDS_2104 "Impossible de charger les accélérateurs de clavier." - IDS_2105 "Impossible de charger l'entrée raw." - IDS_2106 "%u" - IDS_2107 "%u Mo (CTS: %i, %i, %i)" - IDS_2108 "Disquette %i (%s): %ls" - IDS_2109 "Toutes les images (*.0??;*.1??;*.??0;*.86F;*.BIN;*.CQ?;*.D??;*.FLP;*.HDM;*.IM?;*.JSON;*.TD0;*.*FD?;*.MFM;*.XDF)\0*.0??;*.1??;*.??0;*.86F;*.BIN;*.CQ?;*.D??;*.FLP;*.HDM;*.IM?;*.JSON;*.TD0;*.*FD?;*.MFM;*.XDF\0Images du secteur avancés (*.IMD;*.JSON;*.TD0)\0*.IMD;*.JSON;*.TD0\0Images du secteur basiques (*.0??;*.1??;*.??0;*.BIN;*.CQ?;*.D??;*.FLP;*.HDM;*.IM?;*.XDF;*.*FD?)\0*.0??;*.1??;*.??0;*.BIN;*.CQ?;*.D??;*.FLP;*.HDM;*.IM?;*.XDF;*.*FD?\0Images du flux (*.FDI)\0*.FDI\0Images de surface (*.86F;*.MFM)\0*.86F;*.MFM\0Tous les fichiers (*.*)\0*.*\0" - IDS_2110 "Impossible d'initialiser FreeType" - IDS_2111 "Impossible d'initialiser SDL, SDL2.dll est nécessaire" - IDS_2112 "Etes-vous sûr de vouloir réinitialiser la machine émulée ?" - IDS_2113 "Etes-vous sûr de vouloir quitter 86Box?" - IDS_2114 "Impossible d'initialiser Ghostscript" - IDS_2115 "Magnéto-optique %i (%ls): %ls" - IDS_2116 "Images magnéto-optiques (*.IM?;*.MDI)\0*.IM?;*.MDI\0Tous les fichiers (*.*)\0*.*\0" - IDS_2117 "Bienvenue dans 86Box !" - IDS_2118 "Côntrolleur interne" - IDS_2119 "Sortir" - IDS_2120 "Pas de ROMs trouvées" - IDS_2121 "Voulez-vous sauvegarder les paramètres ?" - IDS_2122 "Cela entraînera la réinitialisation complète de la machine émulée." - IDS_2123 "Sauvegarder" - IDS_2124 "À propos de 86Box" - IDS_2125 "86Box v" EMU_VERSION + IDS_2081 "Bus" + IDS_2082 "File" + IDS_2083 "C" + IDS_2084 "T" + IDS_2085 "S" + IDS_2086 "Mo" + IDS_2087 "Speed" + IDS_2088 "Vérifier BPB" + IDS_2089 "Ko" + IDS_2090 "Impossible d'initialiser le moteur de rendu vidéo." + IDS_2091 "Défaut" + IDS_2092 "%i état(s) d'attente" + IDS_2093 "Type" + IDS_2094 "Impossible d'initialiser PCap" + IDS_2095 "Aucun dispositif PCap trouvé" + IDS_2096 "Dispositif PCap non valide" + IDS_2097 "Manette(s) standard avec 2 boutons" + IDS_2098 "Manette standard avec 4 boutons" + IDS_2099 "Manette standard avec 6 boutons" + IDS_2100 "Manette standard avec 6 boutons" + IDS_2101 "CH Flightstick Pro" + IDS_2102 "Microsoft SideWinder Pad" + IDS_2103 "Système de contrôle de vol Thrustmaster" + IDS_2104 "Aucun" + IDS_2105 "Impossible de charger les accélérateurs de clavier." + IDS_2106 "Impossible de charger l'entrée raw." + IDS_2107 "%u" + IDS_2108 "%u Mo (CTS: %i, %i, %i)" + IDS_2109 "Disquette %i (%s): %ls" + IDS_2110 "Toutes les images (*.0??;*.1??;*.??0;*.86F;*.BIN;*.CQ?;*.D??;*.FLP;*.HDM;*.IM?;*.JSON;*.TD0;*.*FD?;*.MFM;*.XDF)\0*.0??;*.1??;*.??0;*.86F;*.BIN;*.CQ?;*.D??;*.FLP;*.HDM;*.IM?;*.JSON;*.TD0;*.*FD?;*.MFM;*.XDF\0Images du secteur avancés (*.IMD;*.JSON;*.TD0)\0*.IMD;*.JSON;*.TD0\0Images du secteur basiques (*.0??;*.1??;*.??0;*.BIN;*.CQ?;*.D??;*.FLP;*.HDM;*.IM?;*.XDF;*.*FD?)\0*.0??;*.1??;*.??0;*.BIN;*.CQ?;*.D??;*.FLP;*.HDM;*.IM?;*.XDF;*.*FD?\0Images du flux (*.FDI)\0*.FDI\0Images de surface (*.86F;*.MFM)\0*.86F;*.MFM\0Tous les fichiers (*.*)\0*.*\0" + IDS_2112 "Impossible d'initialiser SDL, SDL2.dll est nécessaire" + IDS_2113 "Etes-vous sûr de vouloir réinitialiser la machine émulée ?" + IDS_2114 "Etes-vous sûr de vouloir quitter 86Box?" + IDS_2115 "Impossible d'initialiser Ghostscript" + IDS_2116 "Magnéto-optique %i (%ls): %ls" + IDS_2117 "Images magnéto-optiques (*.IM?;*.MDI)\0*.IM?;*.MDI\0Tous les fichiers (*.*)\0*.*\0" + IDS_2118 "Bienvenue dans 86Box !" + IDS_2119 "Côntrolleur interne" + IDS_2120 "Sortir" + IDS_2121 "Pas de ROMs trouvées" + IDS_2122 "Voulez-vous sauvegarder les paramètres ?" + IDS_2123 "Cela entraînera la réinitialisation complète de la machine émulée." + IDS_2124 "Sauvegarder" + IDS_2125 "À propos de 86Box" + IDS_2126 "86Box v" EMU_VERSION - IDS_2126 "Un émulateur de vieux ordinateurs\n\nAuteurs: Sarah Walker, Miran Grca, Fred N. van Kempen (waltje), SA1988, Tiseno100, reenigne, leilei, JohnElliott, greatpsycho, and others.\n\nLibéré sous la licence GNU General Public License version 2 ou ultérieure. Pour plus d'informations, voir le fichier LICENSE." - IDS_2127 "OK" - IDS_2128 "Matériel non disponible" + IDS_2127 "Un émulateur de vieux ordinateurs\n\nAuteurs: Miran GrÄa (OBattler), RichardG867, Jasmine Iwanek, TC1995, coldbrewed, Teemu Korhonen (Manaatti), Joakim L. Gilje, Adrien Moulin (elyosh), Daniel Balsom (gloriouscow), Cacodemon345, Fred N. van Kempen (waltje), Tiseno100, reenigne, and others.\n\nWith previous core contributions from Sarah Walker, leilei, JohnElliott, greatpsycho, and others.\n\nLibéré sous la licence GNU General Public License version 2 ou ultérieure. Pour plus d'informations, voir le fichier LICENSE." + IDS_2128 "OK" + IDS_2129 "Matériel non disponible" #ifdef _WIN32 #define LIB_NAME_PCAP "WinPcap" #else #define LIB_NAME_PCAP "libpcap" #endif - IDS_2129 "Assurez-vous que " LIB_NAME_PCAP " est installé et que vou utilisez une connexion réseau compatible avec " LIB_NAME_PCAP "." - IDS_2130 "Configuration non valide" -#ifdef _WIN32 -#define LIB_NAME_FREETYPE "freetype.dll" -#else -#define LIB_NAME_FREETYPE "libfreetype" -#endif - IDS_2131 LIB_NAME_FREETYPE " est nécessaire pour l'émulation de l'imprimante ESC/P." + IDS_2130 "Assurez-vous que " LIB_NAME_PCAP " est installé et que vou utilisez une connexion réseau compatible avec " LIB_NAME_PCAP "." + IDS_2131 "Configuration non valide" #ifdef _WIN32 #define LIB_NAME_GS "gsdll32.dll" #else #define LIB_NAME_GS "libgs" #endif - IDS_2132 LIB_NAME_GS " est nécessair pour la conversion automatique des fichiers PostScript dans PDF.\n\nTous les documents envoyés à l'imprimante générique PostScript seront sauvés comme des fichiers PostScript (.ps)." -#ifdef _WIN32 -#define LIB_NAME_FLUIDSYNTH "libfluidsynth.dll" -#else -#define LIB_NAME_FLUIDSYNTH "libfluidsynth" -#endif - IDS_2133 LIB_NAME_FLUIDSYNTH " est nécessaire pour la sortie MIDI FluidSynth." - IDS_2134 "Entrer en mode plein écran" - IDS_2135 "Ne pas montrer ce message à nouveau" - IDS_2136 "Ne pas sortir" - IDS_2137 "Réinitialiser" - IDS_2138 "Ne pas réinitialiser" - IDS_2139 "Images magnéto-optiques (*.IM?;*.MDI)\0*.IM?;*.MDI\0Tous les fichiers (*.*)\0*.*\0" - IDS_2140 "Images CD-ROM (*.ISO;*.CUE)\0*.ISO;*.CUE\0Tous les fichiers (*.*)\0*.*\0" - IDS_2141 "Configuration du dispositif %hs" - IDS_2142 "Moniteur en mode veille" - IDS_2143 "Shaders OpenGL (*.GLSL)\0*.GLSL\0Tous les fichiers (*.*)\0*.*\0" - IDS_2144 "Options OpenGL" - IDS_2145 "Vous chargez une configuration non prise en charge" - IDS_2146 "La filtrage du type du processeur sur la base de la machine sélectionné est désactivé pur cette machine émulée.\n\nCela permet de sélectionner une processeur que est sinon incompatible avec la machine sélectionné. Cependant, il pourrait y avoir des incompatibilités avec le BIOS de la machine ou autres logiciels.\n\nL'activatione de cette configuration non est officiellement prise en charge et tout rapport de bogue peut être fermé comme étant invalide." - IDS_2147 "Continuer" - IDS_2148 "Cassette: %s" - IDS_2149 "Images cassette (*.PCM;*.RAW;*.WAV;*.CAS)\0*.PCM;*.RAW;*.WAV;*.CAS\0Tous les fichiers (*.*)\0*.*\0" - IDS_2150 "Cartouche %i: %ls" - IDS_2151 "Images cartouche (*.A;*.B;*.JRC)\0*.A;*.B;*.JRC\0Tous les fichiers (*.*)\0*.*\0" - IDS_2152 "Error initializing renderer" - IDS_2153 "OpenGL (3.0 Core) renderer could not be initialized. Use another renderer." - IDS_2154 "Resume execution" - IDS_2155 "Pause execution" - IDS_2156 "Press Ctrl+Alt+Del" - IDS_2157 "Press Ctrl+Alt+Esc" - IDS_2158 "Hard reset" - IDS_2159 "ACPI shutdown" - IDS_2160 "Settings" + IDS_2133 LIB_NAME_GS " est nécessair pour la conversion automatique des fichiers PostScript dans PDF.\n\nTous les documents envoyés à l'imprimante générique PostScript seront sauvés comme des fichiers PostScript (.ps)." + IDS_2135 "Entrer en mode plein écran" + IDS_2136 "Ne pas montrer ce message à nouveau" + IDS_2137 "Ne pas sortir" + IDS_2138 "Réinitialiser" + IDS_2139 "Ne pas réinitialiser" + IDS_2140 "Images magnéto-optiques (*.IM?;*.MDI)\0*.IM?;*.MDI\0Tous les fichiers (*.*)\0*.*\0" + IDS_2141 "Images CD-ROM (*.ISO;*.CUE)\0*.ISO;*.CUE\0Tous les fichiers (*.*)\0*.*\0" + IDS_2142 "Configuration du dispositif %hs" + IDS_2143 "Moniteur en mode veille" + IDS_2144 "Shaders OpenGL (*.GLSL)\0*.GLSL\0Tous les fichiers (*.*)\0*.*\0" + IDS_2145 "Options OpenGL" + IDS_2146 "Vous chargez une configuration non prise en charge" + IDS_2147 "La filtrage du type du processeur sur la base de la machine sélectionné est désactivé pur cette machine émulée.\n\nCela permet de sélectionner une processeur que est sinon incompatible avec la machine sélectionné. Cependant, il pourrait y avoir des incompatibilités avec le BIOS de la machine ou autres logiciels.\n\nL'activatione de cette configuration non est officiellement prise en charge et tout rapport de bogue peut être fermé comme étant invalide." + IDS_2148 "Continuer" + IDS_2149 "Cassette: %s" + IDS_2150 "Images cassette (*.PCM;*.RAW;*.WAV;*.CAS)\0*.PCM;*.RAW;*.WAV;*.CAS\0Tous les fichiers (*.*)\0*.*\0" + IDS_2151 "Cartouche %i: %ls" + IDS_2152 "Images cartouche (*.A;*.B;*.JRC)\0*.A;*.B;*.JRC\0Tous les fichiers (*.*)\0*.*\0" + IDS_2153 "Error initializing renderer" + IDS_2154 "OpenGL (3.0 Core) renderer could not be initialized. Use another renderer." + IDS_2155 "Resume execution" + IDS_2156 "Pause execution" + IDS_2157 "Press Ctrl+Alt+Del" + IDS_2158 "Press Ctrl+Alt+Esc" + IDS_2159 "Hard reset" + IDS_2160 "ACPI shutdown" + IDS_2161 "Settings" + IDS_2162 "Type" + IDS_2163 "No Dynarec" + IDS_2164 "Old Dynarec" + IDS_2165 "New Dynarec" + IDS_2166 "Video card #2 ""%hs"" is not available due to missing ROMs in the roms/video directory. Disabling the second video card." + IDS_2167 "Failed to initialize network driver" + IDS_2168 "The network configuration will be switched to the null driver" END -STRINGTABLE DISCARDABLE +STRINGTABLE DISCARDABLE BEGIN IDS_4096 "Disque dur (%s)" - IDS_4097 "%01i:%01i" - IDS_4098 "%01i" - IDS_4099 "Les lecteurs de CD-ROM MFM/RLL ou ESDI n'ont jamais existé" - IDS_4100 "Personnalisé..." - IDS_4101 "Personnalisé (grand)..." - IDS_4102 "Ajouter un nouveau disque dur" - IDS_4103 "Ajouter un disque dur existant" - IDS_4104 "Les images de disque HDI ne peuvent pas avoir une taille supériure à Go." - IDS_4105 "Les images de disque ne peuvent pas avoir un taille supérieure à 127 Go." - IDS_4106 "Images de dique dur (*.HD?;*.IM?;*.VHD)\0*.HD?;*.IM?;*.VHD\0Tous les fichiers (*.*)\0*.*\0" - IDS_4107 "Impossible de lire le fichier" - IDS_4108 "Impossible d'écrire le fichier" - IDS_4109 "Les images HDI ou HDX avec une taille de secteur différente de 512 non sont pas prises en charge." - IDS_4110 "USB n'est pas encore pris en charge." - IDS_4111 "Le fichier de l'image disque existe déjà." - IDS_4112 "Veuillez spécifier un nom de fichier valide." - IDS_4113 "Image de disque créée" - IDS_4114 "Assurez-vous que le fichier existe et est lisible." - IDS_4115 "Assurez-vous que le fichier en cours d'enregistrement se trouve dans un répertoire accessible en écriture." - IDS_4116 "Image disque trop grande" - IDS_4117 "N'oubliez pas de partitionner et de formater le nouveau disque créé." - IDS_4118 "Le fichier sélectionné sera écrasé. Etes-vous sûr de vouloir l'utiliser?" - IDS_4119 "Image disque non prise en charge" - IDS_4120 "Écraser" - IDS_4121 "Ne pas écraser" - IDS_4122 "Image brute (.img)" - IDS_4123 "Image HDI (.hdi)" - IDS_4124 "Image HDX (.hdx)" - IDS_4125 "VHD à taille fixe (.vhd)" - IDS_4126 "VHD à taille dynamique (.vhd)" - IDS_4127 "VHD à différenciation (.vhd)" - IDS_4128 "Blocs grands (2 Mo)" - IDS_4129 "Blocs petits (512 Ko)" - IDS_4130 "Fichiers VHD (*.VHD)\0*.VHD\0Tous les fichiers (*.*)\0*.*\0" - IDS_4131 "Sélectionnez le VHD parent" - IDS_4132 "Il est possible que l'image parente a été modifié après la création de l'image à différenciation.\n\nIl est même possible que les fichiers de l'mage ont été déplacés ou copiés ou il existe un bogue dans le programme que a créé ce disque.\n\nVoulez-vous réparer l'horodatage?" - IDS_4133 "Les horodatages des disques parent et enfant ne correspondent pas" - IDS_4134 "Impossible de réparer l'horodatage du VHD." - IDS_4135 "%01i:%02i" + IDS_4097 "%01i:%01i" + IDS_4098 "%01i" + IDS_4099 "Les lecteurs de CD-ROM MFM/RLL ou ESDI n'ont jamais existé" + IDS_4100 "Personnalisé..." + IDS_4101 "Personnalisé (grand)..." + IDS_4102 "Ajouter un nouveau disque dur" + IDS_4103 "Ajouter un disque dur existant" + IDS_4104 "Les images de disque HDI ne peuvent pas avoir une taille supériure à Go." + IDS_4105 "Les images de disque ne peuvent pas avoir un taille supérieure à 127 Go." + IDS_4106 "Images de dique dur (*.HD?;*.IM?;*.VHD)\0*.HD?;*.IM?;*.VHD\0Tous les fichiers (*.*)\0*.*\0" + IDS_4107 "Impossible de lire le fichier" + IDS_4108 "Impossible d'écrire le fichier" + IDS_4109 "Les images HDI ou HDX avec une taille de secteur différente de 512 non sont pas prises en charge." + IDS_4110 "USB n'est pas encore pris en charge." + IDS_4111 "Le fichier de l'image disque existe déjà." + IDS_4112 "Veuillez spécifier un nom de fichier valide." + IDS_4113 "Image de disque créée" + IDS_4114 "Assurez-vous que le fichier existe et est lisible." + IDS_4115 "Assurez-vous que le fichier en cours d'enregistrement se trouve dans un répertoire accessible en écriture." + IDS_4116 "Image disque trop grande" + IDS_4117 "N'oubliez pas de partitionner et de formater le nouveau disque créé." + IDS_4118 "Le fichier sélectionné sera écrasé. Etes-vous sûr de vouloir l'utiliser?" + IDS_4119 "Image disque non prise en charge" + IDS_4120 "Écraser" + IDS_4121 "Ne pas écraser" + IDS_4122 "Image brute (.img)" + IDS_4123 "Image HDI (.hdi)" + IDS_4124 "Image HDX (.hdx)" + IDS_4125 "VHD à taille fixe (.vhd)" + IDS_4126 "VHD à taille dynamique (.vhd)" + IDS_4127 "VHD à différenciation (.vhd)" + IDS_4128 "Blocs grands (2 Mo)" + IDS_4129 "Blocs petits (512 Ko)" + IDS_4130 "Fichiers VHD (*.VHD)\0*.VHD\0Tous les fichiers (*.*)\0*.*\0" + IDS_4131 "Sélectionnez le VHD parent" + IDS_4132 "Il est possible que l'image parente a été modifié après la création de l'image à différenciation.\n\nIl est même possible que les fichiers de l'mage ont été déplacés ou copiés ou il existe un bogue dans le programme que a créé ce disque.\n\nVoulez-vous réparer l'horodatage?" + IDS_4133 "Les horodatages des disques parent et enfant ne correspondent pas" + IDS_4134 "Impossible de réparer l'horodatage du VHD." + IDS_4135 "%01i:%02i" IDS_4352 "MFM/RLL" IDS_4353 "XTA" @@ -562,56 +582,56 @@ BEGIN IDS_4356 "ATAPI" IDS_4357 "SCSI" - IDS_4608 "MFM/RLL (%01i:%01i)" - IDS_4609 "XTA (%01i:%01i)" - IDS_4610 "ESDI (%01i:%01i)" - IDS_4611 "IDE (%01i:%01i)" - IDS_4612 "ATAPI (%01i:%01i)" - IDS_4613 "SCSI (%01i:%02i)" + IDS_4608 "MFM/RLL (%01i:%01i)" + IDS_4609 "XTA (%01i:%01i)" + IDS_4610 "ESDI (%01i:%01i)" + IDS_4611 "IDE (%01i:%01i)" + IDS_4612 "ATAPI (%01i:%01i)" + IDS_4613 "SCSI (%01i:%02i)" - IDS_5120 "CD-ROM %i (%s): %s" + IDS_5120 "CD-ROM %i (%s): %s" - IDS_5376 "Désactivé" - IDS_5381 "ATAPI" + IDS_5376 "Désactivé" + IDS_5381 "ATAPI" IDS_5382 "SCSI" - IDS_5632 "Désactivé" - IDS_5637 "ATAPI (%01i:%01i)" + IDS_5632 "Désactivé" + IDS_5637 "ATAPI (%01i:%01i)" IDS_5638 "SCSI (%01i:%02i)" - IDS_5888 "160 Ko" - IDS_5889 "180 Ko" - IDS_5890 "320 Ko" - IDS_5891 "360 Ko" - IDS_5892 "640 Ko" - IDS_5893 "720 Ko" - IDS_5894 "1.2 Mo" - IDS_5895 "1.25 Mo" - IDS_5896 "1.44 Mo" - IDS_5897 "DMF (cluster 1024)" - IDS_5898 "DMF (cluster 2048)" - IDS_5899 "2.88 Mo" - IDS_5900 "ZIP 100" - IDS_5901 "ZIP 250" - IDS_5902 "3.5"" 128 Mo (ISO 10090)" - IDS_5903 "3.5"" 230 Mo (ISO 13963)" - IDS_5904 "3.5"" 540 Mo (ISO 15498)" - IDS_5905 "3.5"" 640 Mo (ISO 15498)" - IDS_5906 "3.5"" 1.3 Go (GigaMO)" - IDS_5907 "3.5"" 2.3 Go (GigaMO 2)" - IDS_5908 "5.25"" 600 Mo" - IDS_5909 "5.25"" 650 Mo" - IDS_5910 "5.25"" 1 Go" - IDS_5911 "5.25"" 1.3 Go" + IDS_5888 "160 Ko" + IDS_5889 "180 Ko" + IDS_5890 "320 Ko" + IDS_5891 "360 Ko" + IDS_5892 "640 Ko" + IDS_5893 "720 Ko" + IDS_5894 "1.2 Mo" + IDS_5895 "1.25 Mo" + IDS_5896 "1.44 Mo" + IDS_5897 "DMF (cluster 1024)" + IDS_5898 "DMF (cluster 2048)" + IDS_5899 "2.88 Mo" + IDS_5900 "ZIP 100" + IDS_5901 "ZIP 250" + IDS_5902 "3.5"" 128 Mo (ISO 10090)" + IDS_5903 "3.5"" 230 Mo (ISO 13963)" + IDS_5904 "3.5"" 540 Mo (ISO 15498)" + IDS_5905 "3.5"" 640 Mo (ISO 15498)" + IDS_5906 "3.5"" 1.3 Go (GigaMO)" + IDS_5907 "3.5"" 2.3 Go (GigaMO 2)" + IDS_5908 "5.25"" 600 Mo" + IDS_5909 "5.25"" 650 Mo" + IDS_5910 "5.25"" 1 Go" + IDS_5911 "5.25"" 1.3 Go" - IDS_6144 "RPM précis" - IDS_6145 "Précision RPM de moins 1%" - IDS_6146 "Précision RPM de moins 1.5%" - IDS_6147 "Précision RPM de moins 2%" + IDS_6144 "RPM précis" + IDS_6145 "Précision RPM de moins 1%" + IDS_6146 "Précision RPM de moins 1.5%" + IDS_6147 "Précision RPM de moins 2%" - IDS_7168 "(Défaut du système)" + IDS_7168 "(Défaut du système)" END -#define IDS_LANG_ENUS IDS_7168 +#define IDS_LANG_ENUS IDS_7168 // French (F.R.) resources ///////////////////////////////////////////////////////////////////////////// diff --git a/src/win/languages/hr-HR.rc b/src/win/languages/hr-HR.rc index d41441721..9497a7b0d 100644 --- a/src/win/languages/hr-HR.rc +++ b/src/win/languages/hr-HR.rc @@ -13,113 +13,122 @@ LANGUAGE LANG_CROATIAN, SUBLANG_DEFAULT // Menu // -MainMenu MENU DISCARDABLE +MainMenu MENU DISCARDABLE BEGIN POPUP "&Radnje" BEGIN - MENUITEM "&Tipkovnica zahtijeva hvatanje miÅ¡a", IDM_ACTION_KBD_REQ_CAPTURE - MENUITEM "&Desni CTRL je lijevi ALT", IDM_ACTION_RCTRL_IS_LALT + MENUITEM "&Tipkovnica zahtijeva hvatanje miÅ¡a", IDM_ACTION_KBD_REQ_CAPTURE + MENUITEM "&Desni CTRL je lijevi ALT", IDM_ACTION_RCTRL_IS_LALT MENUITEM SEPARATOR - MENUITEM "&Ponovno pokretanje...", IDM_ACTION_HRESET - MENUITEM "&Ctrl+Alt+Del\tCtrl+F12", IDM_ACTION_RESET_CAD + MENUITEM "&Ponovno pokretanje...", IDM_ACTION_HRESET + MENUITEM "&Ctrl+Alt+Del\tCtrl+F12", IDM_ACTION_RESET_CAD MENUITEM SEPARATOR - MENUITEM "Ctrl+Alt+&Esc", IDM_ACTION_CTRL_ALT_ESC + MENUITEM "Ctrl+Alt+&Esc", IDM_ACTION_CTRL_ALT_ESC MENUITEM SEPARATOR - MENUITEM "&Pauza", IDM_ACTION_PAUSE + MENUITEM "&Pauza", IDM_ACTION_PAUSE MENUITEM SEPARATOR - MENUITEM "Iz&laz...", IDM_ACTION_EXIT + MENUITEM "Iz&laz...", IDM_ACTION_EXIT END POPUP "&Pogled" BEGIN - MENUITEM "&Sakrij statusni redak", IDM_VID_HIDE_STATUS_BAR - MENUITEM "&Sakrij alatni redak", IDM_VID_HIDE_TOOLBAR + MENUITEM "&Sakrij statusni redak", IDM_VID_HIDE_STATUS_BAR + MENUITEM "&Sakrij alatni redak", IDM_VID_HIDE_TOOLBAR MENUITEM SEPARATOR - MENUITEM "&Prozor s promjenjivim veliÄinama", IDM_VID_RESIZE - MENUITEM "&Zapamtite veliÄinu i položaj", IDM_VID_REMEMBER + MENUITEM "&Show non-primary monitors", IDM_VID_MONITORS + MENUITEM "&Prozor s promjenjivim veliÄinama", IDM_VID_RESIZE + MENUITEM "&Zapamtite veliÄinu i položaj", IDM_VID_REMEMBER MENUITEM SEPARATOR POPUP "&Renderer" BEGIN - MENUITEM "&SDL (Softver)", IDM_VID_SDL_SW - MENUITEM "SDL (&Hardver)", IDM_VID_SDL_HW - MENUITEM "SDL (&OpenGL)", IDM_VID_SDL_OPENGL - MENUITEM "Open&GL (3.0 jezgra)", IDM_VID_OPENGL_CORE + MENUITEM "&SDL (Softver)", IDM_VID_SDL_SW + MENUITEM "SDL (&Hardver)", IDM_VID_SDL_HW + MENUITEM "SDL (&OpenGL)", IDM_VID_SDL_OPENGL + MENUITEM "Open&GL (3.0 jezgra)", IDM_VID_OPENGL_CORE #ifdef USE_VNC - MENUITEM "&VNC", IDM_VID_VNC + MENUITEM "&VNC", IDM_VID_VNC #endif END MENUITEM SEPARATOR - MENUITEM "Odrediti veliÄinu...", IDM_VID_SPECIFY_DIM - MENUITEM "&4:3 omjer prikaza", IDM_VID_FORCE43 + MENUITEM "Odrediti veliÄinu...", IDM_VID_SPECIFY_DIM + MENUITEM "&4:3 omjer prikaza", IDM_VID_FORCE43 POPUP "&Faktor skaliranja prozora" BEGIN - MENUITEM "&0,5x", IDM_VID_SCALE_1X - MENUITEM "&1x", IDM_VID_SCALE_2X - MENUITEM "1,&5x", IDM_VID_SCALE_3X - MENUITEM "&2x", IDM_VID_SCALE_4X + MENUITEM "&0,5x", IDM_VID_SCALE_1X + MENUITEM "&1x", IDM_VID_SCALE_2X + MENUITEM "1,&5x", IDM_VID_SCALE_3X + MENUITEM "&2x", IDM_VID_SCALE_4X + MENUITEM "&3x", IDM_VID_SCALE_5X + MENUITEM "&4x", IDM_VID_SCALE_6X + MENUITEM "&5x", IDM_VID_SCALE_7X + MENUITEM "&6x", IDM_VID_SCALE_8X + MENUITEM "&7x", IDM_VID_SCALE_9X + MENUITEM "&8x", IDM_VID_SCALE_10X END POPUP "Metoda filtriranja" BEGIN - MENUITEM "&Najbliža", IDM_VID_FILTER_NEAREST - MENUITEM "&Linearna", IDM_VID_FILTER_LINEAR + MENUITEM "&Najbliža", IDM_VID_FILTER_NEAREST + MENUITEM "&Linearna", IDM_VID_FILTER_LINEAR END - MENUITEM "&HiDPI skaliranje", IDM_VID_HIDPI + MENUITEM "&HiDPI skaliranje", IDM_VID_HIDPI MENUITEM SEPARATOR - MENUITEM "&Cijelozaslonski naÄin\tCtrl+Alt+PgUp", IDM_VID_FULLSCREEN + MENUITEM "&Cijelozaslonski naÄin\tCtrl+Alt+PgUp", IDM_VID_FULLSCREEN POPUP "&NaÄin cijelozaslonskog rastezanja" BEGIN - MENUITEM "&Razvuci na cijeli zaslona", IDM_VID_FS_FULL - MENUITEM "&4:3", IDM_VID_FS_43 + MENUITEM "&Razvuci na cijeli zaslona", IDM_VID_FS_FULL + MENUITEM "&4:3", IDM_VID_FS_43 MENUITEM "&Kvadratni pikseli (zadrži omjer)", IDM_VID_FS_KEEPRATIO - MENUITEM "&Cijelobrojno skaliranje", IDM_VID_FS_INT + MENUITEM "&Cijelobrojno skaliranje", IDM_VID_FS_INT END POPUP "E&GA/(S)VGA postavke" BEGIN - MENUITEM "&Obrni boje zaslona VGA", IDM_VID_INVERT + MENUITEM "&Obrni boje zaslona VGA", IDM_VID_INVERT POPUP "&Tip zaslona VGA" BEGIN - MENUITEM "RGB u &boji", IDM_VID_GRAY_RGB - MENUITEM "&RGB u nijansama sive boje", IDM_VID_GRAY_MONO - MENUITEM "&Jantarni zaslon", IDM_VID_GRAY_AMBER - MENUITEM "&Zeleni zaslon", IDM_VID_GRAY_GREEN - MENUITEM "&Bijeli zaslon", IDM_VID_GRAY_WHITE + MENUITEM "RGB u &boji", IDM_VID_GRAY_RGB + MENUITEM "&RGB u nijansama sive boje", IDM_VID_GRAY_MONO + MENUITEM "&Jantarni zaslon", IDM_VID_GRAY_AMBER + MENUITEM "&Zeleni zaslon", IDM_VID_GRAY_GREEN + MENUITEM "&Bijeli zaslon", IDM_VID_GRAY_WHITE END POPUP "&Vrsta konverzije nijansa sive boje" BEGIN - MENUITEM "BT&601 (NTSC/PAL)", IDM_VID_GRAYCT_601 - MENUITEM "BT&709 (HDTV)", IDM_VID_GRAYCT_709 - MENUITEM "&Prosjek", IDM_VID_GRAYCT_AVE + MENUITEM "BT&601 (NTSC/PAL)", IDM_VID_GRAYCT_601 + MENUITEM "BT&709 (HDTV)", IDM_VID_GRAYCT_709 + MENUITEM "&Prosjek", IDM_VID_GRAYCT_AVE END END MENUITEM SEPARATOR - MENUITEM "&ViÅ¡ak slike CGA/PCjr/Tandy/EGA/(S)VGA", IDM_VID_OVERSCAN + MENUITEM "&ViÅ¡ak slike CGA/PCjr/Tandy/EGA/(S)VGA", IDM_VID_OVERSCAN MENUITEM "&Promjeni kontrast za crno-bijeli zaslon", IDM_VID_CGACON END - MENUITEM "&Mediji", IDM_MEDIA + MENUITEM "&Mediji", IDM_MEDIA POPUP "&Alati" BEGIN - MENUITEM "&Opcije...", IDM_CONFIG - MENUITEM "&Ažuriraj ikone statusnog redka", IDM_UPDATE_ICONS + MENUITEM "&Opcije...", IDM_CONFIG + MENUITEM "&Ažuriraj ikone statusnog redka", IDM_UPDATE_ICONS MENUITEM SEPARATOR - MENUITEM "Napravi &snimku zaslona\tCtrl+F11", IDM_ACTION_SCREENSHOT + MENUITEM "Napravi &snimku zaslona\tCtrl+F11", IDM_ACTION_SCREENSHOT MENUITEM SEPARATOR - MENUITEM "&Postavke...", IDM_PREFERENCES + MENUITEM "&Postavke...", IDM_PREFERENCES +#ifdef DISCORD MENUITEM "Omogući integraciju sa programom &Discord", IDM_DISCORD +#endif MENUITEM SEPARATOR - MENUITEM "&PojaÄanje zvuka...", IDM_SND_GAIN + MENUITEM "&PojaÄanje zvuka...", IDM_SND_GAIN #ifdef MTR_ENABLED MENUITEM SEPARATOR - MENUITEM "Z&apoÄni praćenje\tCtrl+T", IDM_ACTION_BEGIN_TRACE - MENUITEM "&SvrÅ¡i praćenje\tCtrl+T", IDM_ACTION_END_TRACE + MENUITEM "Z&apoÄni praćenje\tCtrl+T", IDM_ACTION_BEGIN_TRACE + MENUITEM "&SvrÅ¡i praćenje\tCtrl+T", IDM_ACTION_END_TRACE #endif END POPUP "&Pomoć" BEGIN - MENUITEM "&Dokumentacija...", IDM_DOCS - MENUITEM "&O programu 86Box...", IDM_ABOUT + MENUITEM "&Dokumentacija...", IDM_DOCS + MENUITEM "&O programu 86Box...", IDM_ABOUT END END -StatusBarMenu MENU DISCARDABLE +StatusBarMenu MENU DISCARDABLE BEGIN MENUITEM SEPARATOR END @@ -128,17 +137,17 @@ CassetteSubmenu MENU DISCARDABLE BEGIN POPUP "" BEGIN - MENUITEM "&Nova slika...", IDM_CASSETTE_IMAGE_NEW + MENUITEM "&Nova slika...", IDM_CASSETTE_IMAGE_NEW MENUITEM SEPARATOR - MENUITEM "&Postojeća slika...", IDM_CASSETTE_IMAGE_EXISTING - MENUITEM "Postojeća slika (&zaÅ¡tićena od pisanja)...", IDM_CASSETTE_IMAGE_EXISTING_WP + MENUITEM "&Postojeća slika...", IDM_CASSETTE_IMAGE_EXISTING + MENUITEM "Postojeća slika (&zaÅ¡tićena od pisanja)...", IDM_CASSETTE_IMAGE_EXISTING_WP MENUITEM SEPARATOR - MENUITEM "&Snimi", IDM_CASSETTE_RECORD - MENUITEM "&Pokreni", IDM_CASSETTE_PLAY - MENUITEM "P&remotaj na poÄetak", IDM_CASSETTE_REWIND - MENUITEM "&PreskoÄi do kraja", IDM_CASSETTE_FAST_FORWARD + MENUITEM "&Snimi", IDM_CASSETTE_RECORD + MENUITEM "&Pokreni", IDM_CASSETTE_PLAY + MENUITEM "P&remotaj na poÄetak", IDM_CASSETTE_REWIND + MENUITEM "&PreskoÄi do kraja", IDM_CASSETTE_FAST_FORWARD MENUITEM SEPARATOR - MENUITEM "&Izbaci", IDM_CASSETTE_EJECT + MENUITEM "&Izbaci", IDM_CASSETTE_EJECT END END @@ -146,9 +155,9 @@ CartridgeSubmenu MENU DISCARDABLE BEGIN POPUP "" BEGIN - MENUITEM "&Slika...", IDM_CARTRIDGE_IMAGE + MENUITEM "&Slika...", IDM_CARTRIDGE_IMAGE MENUITEM SEPARATOR - MENUITEM "&Izbaci", IDM_CARTRIDGE_EJECT + MENUITEM "&Izbaci", IDM_CARTRIDGE_EJECT END END @@ -156,14 +165,14 @@ FloppySubmenu MENU DISCARDABLE BEGIN POPUP "" BEGIN - MENUITEM "&Nova slika...", IDM_FLOPPY_IMAGE_NEW + MENUITEM "&Nova slika...", IDM_FLOPPY_IMAGE_NEW MENUITEM SEPARATOR - MENUITEM "&Postojeća slika...", IDM_FLOPPY_IMAGE_EXISTING - MENUITEM "Postojeća slika (&zaÅ¡tićena od pisanja)...", IDM_FLOPPY_IMAGE_EXISTING_WP + MENUITEM "&Postojeća slika...", IDM_FLOPPY_IMAGE_EXISTING + MENUITEM "Postojeća slika (&zaÅ¡tićena od pisanja)...", IDM_FLOPPY_IMAGE_EXISTING_WP MENUITEM SEPARATOR - MENUITEM "&Izvozi u 86F...", IDM_FLOPPY_EXPORT_TO_86F + MENUITEM "&Izvozi u 86F...", IDM_FLOPPY_EXPORT_TO_86F MENUITEM SEPARATOR - MENUITEM "&Izbaci", IDM_FLOPPY_EJECT + MENUITEM "&Izbaci", IDM_FLOPPY_EJECT END END @@ -171,12 +180,13 @@ CdromSubmenu MENU DISCARDABLE BEGIN POPUP "" BEGIN - MENUITEM "&IskljuÄi zvuk", IDM_CDROM_MUTE + MENUITEM "&IskljuÄi zvuk", IDM_CDROM_MUTE MENUITEM SEPARATOR - MENUITEM "&Prazno", IDM_CDROM_EMPTY - MENUITEM "&Ponovo uÄitaj prethodnu sliku", IDM_CDROM_RELOAD + MENUITEM "&Prazno", IDM_CDROM_EMPTY + MENUITEM "&Ponovo uÄitaj prethodnu sliku", IDM_CDROM_RELOAD MENUITEM SEPARATOR - MENUITEM "&Slika", IDM_CDROM_IMAGE + MENUITEM "&Slika...", IDM_CDROM_IMAGE + MENUITEM "&Mapa...", IDM_CDROM_DIR END END @@ -184,13 +194,13 @@ ZIPSubmenu MENU DISCARDABLE BEGIN POPUP "" BEGIN - MENUITEM "&Nova slika...", IDM_ZIP_IMAGE_NEW + MENUITEM "&Nova slika...", IDM_ZIP_IMAGE_NEW MENUITEM SEPARATOR - MENUITEM "&Postojeća slika...", IDM_ZIP_IMAGE_EXISTING - MENUITEM "Postojeća slika (&zaÅ¡tićena od pisanja)...", IDM_ZIP_IMAGE_EXISTING_WP + MENUITEM "&Postojeća slika...", IDM_ZIP_IMAGE_EXISTING + MENUITEM "Postojeća slika (&zaÅ¡tićena od pisanja)...", IDM_ZIP_IMAGE_EXISTING_WP MENUITEM SEPARATOR - MENUITEM "&Izbaci", IDM_ZIP_EJECT - MENUITEM "&Ponovo uÄitaj prethodnu sliku", IDM_ZIP_RELOAD + MENUITEM "&Izbaci", IDM_ZIP_EJECT + MENUITEM "&Ponovo uÄitaj prethodnu sliku", IDM_ZIP_RELOAD END END @@ -198,13 +208,13 @@ MOSubmenu MENU DISCARDABLE BEGIN POPUP "" BEGIN - MENUITEM "&Nova slika...", IDM_MO_IMAGE_NEW + MENUITEM "&Nova slika...", IDM_MO_IMAGE_NEW MENUITEM SEPARATOR - MENUITEM "&Postojeća slika...", IDM_MO_IMAGE_EXISTING - MENUITEM "Postojeća slika (&zaÅ¡tićena od pisanja)...", IDM_MO_IMAGE_EXISTING_WP + MENUITEM "&Postojeća slika...", IDM_MO_IMAGE_EXISTING + MENUITEM "Postojeća slika (&zaÅ¡tićena od pisanja)...", IDM_MO_IMAGE_EXISTING_WP MENUITEM SEPARATOR - MENUITEM "&Izbaci", IDM_MO_EJECT - MENUITEM "&Ponovo uÄitaj prethodnu sliku", IDM_MO_RELOAD + MENUITEM "&Izbaci", IDM_MO_EJECT + MENUITEM "&Ponovo uÄitaj prethodnu sliku", IDM_MO_RELOAD END END @@ -230,134 +240,150 @@ END // Dialog // -#define STR_PREFERENCES "Postavke" -#define STR_SND_GAIN "PojaÄavanje zvuka" -#define STR_NEW_FLOPPY "Nova slika" -#define STR_CONFIG "Opcije" -#define STR_SPECIFY_DIM "Odredite glavne dimenzije prozora" +#define STR_PREFERENCES "Postavke" +#define STR_SND_GAIN "PojaÄavanje zvuka" +#define STR_NEW_FLOPPY "Nova slika" +#define STR_CONFIG "Opcije" +#define STR_SPECIFY_DIM "Odredite glavne dimenzije prozora" -#define STR_OK "U redu" -#define STR_CANCEL "Otkaži" -#define STR_GLOBAL "Spremite ove postavke kao &globalne zadane postavke" -#define STR_DEFAULT "Zadano" -#define STR_LANGUAGE "Jezik:" -#define STR_ICONSET "Paket ikona:" +#define STR_OK "U redu" +#define STR_CANCEL "Otkaži" +#define STR_GLOBAL "Spremite ove postavke kao &globalne zadane postavke" +#define STR_DEFAULT "Zadano" +#define STR_LANGUAGE "Jezik:" +#define STR_ICONSET "Paket ikona:" -#define STR_GAIN "PojaÄavanje" +#define STR_GAIN "PojaÄavanje" -#define STR_FILE_NAME "Ime datoteke:" -#define STR_DISK_SIZE "VeliÄina diska:" -#define STR_RPM_MODE "NaÄin broja okretaja:" -#define STR_PROGRESS "Napredak:" +#define STR_FILE_NAME "Ime datoteke:" +#define STR_DISK_SIZE "VeliÄina diska:" +#define STR_RPM_MODE "NaÄin broja okretaja:" +#define STR_PROGRESS "Napredak:" -#define STR_WIDTH "Å irina:" -#define STR_HEIGHT "Visina:" -#define STR_LOCK_TO_SIZE "ZakljuÄajte na ovu veliÄinu" +#define STR_WIDTH "Å irina:" +#define STR_HEIGHT "Visina:" +#define STR_LOCK_TO_SIZE "ZakljuÄajte na ovu veliÄinu" -#define STR_MACHINE_TYPE "Tip sistema:" -#define STR_MACHINE "Sistem:" -#define STR_CONFIGURE "Namjesti" -#define STR_CPU_TYPE "Tip procesora:" -#define STR_CPU_SPEED "Brzina:" -#define STR_FPU "FPU ureÄ‘aj:" -#define STR_WAIT_STATES "Stanja Äekanja:" -#define STR_MB "MB" -#define STR_MEMORY "Memorija:" -#define STR_TIME_SYNC "Sinkronizacija vremena" -#define STR_DISABLED "IskljuÄeno" -#define STR_ENABLED_LOCAL "UkljuÄeno (lokalno vrijeme)" -#define STR_ENABLED_UTC "UkljuÄeno (UTC)" -#define STR_DYNAREC "DinamiÄki rekompilator" +#define STR_MACHINE_TYPE "Tip sistema:" +#define STR_MACHINE "Sistem:" +#define STR_CONFIGURE "Namjesti" +#define STR_CPU_TYPE "Tip procesora:" +#define STR_CPU_SPEED "Brzina:" +#define STR_FPU "FPU ureÄ‘aj:" +#define STR_WAIT_STATES "Stanja Äekanja:" +#define STR_MB "MB" +#define STR_MEMORY "Memorija:" +#define STR_TIME_SYNC "Sinkronizacija vremena" +#define STR_DISABLED "IskljuÄeno" +#define STR_ENABLED_LOCAL "UkljuÄeno (lokalno vrijeme)" +#define STR_ENABLED_UTC "UkljuÄeno (UTC)" +#define STR_DYNAREC "DinamiÄki rekompilator" +#define STR_SOFTFLOAT "Softfloat FPU" -#define STR_VIDEO "Video:" -#define STR_VOODOO "Voodoo grafika" +#define STR_VIDEO "Video:" +#define STR_VIDEO_2 "Video 2:" +#define STR_VOODOO "Voodoo grafika" +#define STR_IBM8514 "IBM 8514/a grafika" +#define STR_XGA "XGA grafika" -#define STR_MOUSE "MiÅ¡:" -#define STR_JOYSTICK "Palica za igru:" -#define STR_JOY1 "Palica za igru 1..." -#define STR_JOY2 "Palica za igru 2..." -#define STR_JOY3 "Palica za igru 3..." -#define STR_JOY4 "Palica za igru 4..." +#define STR_MOUSE "MiÅ¡:" +#define STR_JOYSTICK "Palica za igru:" +#define STR_JOY1 "Palica za igru 1..." +#define STR_JOY2 "Palica za igru 2..." +#define STR_JOY3 "Palica za igru 3..." +#define STR_JOY4 "Palica za igru 4..." -#define STR_SOUND "ZvuÄna kartica:" -#define STR_MIDI_OUT "Izlazni ureÄ‘aj MIDI:" -#define STR_MIDI_IN "Ulazni ureÄ‘aj MIDI:" -#define STR_MPU401 "Samostalni MPU-401" -#define STR_SSI "Innovation SSI-2001" -#define STR_CMS "CMS / Game Blaster" -#define STR_GUS "Gravis Ultrasound" -#define STR_FLOAT "Koristi FLOAT32 za zvuk" +#define STR_SOUND1 "ZvuÄna kartica 1:" +#define STR_SOUND2 "ZvuÄna kartica 2:" +#define STR_SOUND3 "ZvuÄna kartica 3:" +#define STR_SOUND4 "ZvuÄna kartica 4:" +#define STR_MIDI_OUT "Izlazni ureÄ‘aj MIDI:" +#define STR_MIDI_IN "Ulazni ureÄ‘aj MIDI:" +#define STR_MPU401 "Samostalni MPU-401" +#define STR_FLOAT "Koristi FLOAT32 za zvuk" +#define STR_FM_DRIVER "Drajver za FM sintisajzer" +#define STR_FM_DRV_NUKED "Nuked (precizniji)" +#define STR_FM_DRV_YMFM "YMFM (brži)" -#define STR_NET_TYPE "Tip mreže:" -#define STR_PCAP "UreÄ‘aj PCap:" -#define STR_NET "Mrežna kartica:" +#define STR_NET_TYPE "Tip mreže:" +#define STR_PCAP "UreÄ‘aj PCap:" +#define STR_NET "Mrežna kartica:" +#define STR_NET1 "Network card 1:" +#define STR_NET2 "Network card 2:" +#define STR_NET3 "Network card 3:" +#define STR_NET4 "Network card 4:" -#define STR_COM1 "UreÄ‘aj COM1:" -#define STR_COM2 "UreÄ‘aj COM2:" -#define STR_COM3 "UreÄ‘aj COM3:" -#define STR_COM4 "UreÄ‘aj COM4:" -#define STR_LPT1 "UreÄ‘aj LPT1:" -#define STR_LPT2 "UreÄ‘aj LPT2:" -#define STR_LPT3 "UreÄ‘aj LPT3:" -#define STR_LPT4 "UreÄ‘aj LPT4:" -#define STR_SERIAL1 "Serijska vrata 1" -#define STR_SERIAL2 "Serijska vrata 2" -#define STR_SERIAL3 "Serijska vrata 3" -#define STR_SERIAL4 "Serijska vrata 4" -#define STR_PARALLEL1 "Paralelna vrata 1" -#define STR_PARALLEL2 "Paralelna vrata 2" -#define STR_PARALLEL3 "Paralelna vrata 3" -#define STR_PARALLEL4 "Paralelna vrata 4" +#define STR_COM1 "UreÄ‘aj COM1:" +#define STR_COM2 "UreÄ‘aj COM2:" +#define STR_COM3 "UreÄ‘aj COM3:" +#define STR_COM4 "UreÄ‘aj COM4:" +#define STR_LPT1 "UreÄ‘aj LPT1:" +#define STR_LPT2 "UreÄ‘aj LPT2:" +#define STR_LPT3 "UreÄ‘aj LPT3:" +#define STR_LPT4 "UreÄ‘aj LPT4:" +#define STR_SERIAL1 "Serijska vrata 1" +#define STR_SERIAL2 "Serijska vrata 2" +#define STR_SERIAL3 "Serijska vrata 3" +#define STR_SERIAL4 "Serijska vrata 4" +#define STR_PARALLEL1 "Paralelna vrata 1" +#define STR_PARALLEL2 "Paralelna vrata 2" +#define STR_PARALLEL3 "Paralelna vrata 3" +#define STR_PARALLEL4 "Paralelna vrata 4" +#define STR_SERIAL_PASS1 "Serial port passthrough 1" +#define STR_SERIAL_PASS2 "Serial port passthrough 2" +#define STR_SERIAL_PASS3 "Serial port passthrough 3" +#define STR_SERIAL_PASS4 "Serial port passthrough 4" -#define STR_HDC "Kontroler tvrdog diska:" -#define STR_FDC "Kontroler diskete:" -#define STR_IDE_TER "Tercijarni IDE kontroler" -#define STR_IDE_QUA "Kvaternarni IDE kontroler" -#define STR_SCSI "SCSI" -#define STR_SCSI_1 "Kontroler 1:" -#define STR_SCSI_2 "Kontroler 2:" -#define STR_SCSI_3 "Kontroler 3:" -#define STR_SCSI_4 "Kontroler 4:" -#define STR_CASSETTE "Audio kaseta" +#define STR_HDC "Kontroler tvrdog diska:" +#define STR_FDC "Kontroler diskete:" +#define STR_IDE_TER "Tercijarni IDE kontroler" +#define STR_IDE_QUA "Kvaternarni IDE kontroler" +#define STR_SCSI "SCSI" +#define STR_SCSI_1 "Kontroler 1:" +#define STR_SCSI_2 "Kontroler 2:" +#define STR_SCSI_3 "Kontroler 3:" +#define STR_SCSI_4 "Kontroler 4:" +#define STR_CASSETTE "Audio kaseta" -#define STR_HDD "Tvrdi diskovi:" -#define STR_NEW "&Novi..." -#define STR_EXISTING "&Postojeći..." -#define STR_REMOVE "&Ukloni" -#define STR_BUS "Sabirnica:" -#define STR_CHANNEL "Kanal:" -#define STR_ID "ID:" +#define STR_HDD "Tvrdi diskovi:" +#define STR_NEW "&Novi..." +#define STR_EXISTING "&Postojeći..." +#define STR_REMOVE "&Ukloni" +#define STR_BUS "Sabirnica:" +#define STR_CHANNEL "Kanal:" +#define STR_ID "ID:" +#define STR_SPEED "Speed:" -#define STR_SPECIFY "&Odredi..." -#define STR_SECTORS "Sektori:" -#define STR_HEADS "Glave:" -#define STR_CYLS "Cilindri:" -#define STR_SIZE_MB "VeliÄina (MB):" -#define STR_TYPE "Tip:" -#define STR_IMG_FORMAT "Format slike:" -#define STR_BLOCK_SIZE "VeliÄina slike:" +#define STR_SPECIFY "&Odredi..." +#define STR_SECTORS "Sektori:" +#define STR_HEADS "Glave:" +#define STR_CYLS "Cilindri:" +#define STR_SIZE_MB "VeliÄina (MB):" +#define STR_TYPE "Tip:" +#define STR_IMG_FORMAT "Format slike:" +#define STR_BLOCK_SIZE "VeliÄina slike:" -#define STR_FLOPPY_DRIVES "Disketni pogoni:" -#define STR_TURBO "Turbo vrijemena" -#define STR_CHECKBPB "Provjeraj BPB" -#define STR_CDROM_DRIVES "CD-ROM pogoni:" -#define STR_CD_SPEED "Brzina:" +#define STR_FLOPPY_DRIVES "Disketni pogoni:" +#define STR_TURBO "Turbo vrijemena" +#define STR_CHECKBPB "Provjeraj BPB" +#define STR_CDROM_DRIVES "CD-ROM pogoni:" +#define STR_CD_SPEED "Brzina:" -#define STR_MO_DRIVES "MO pogoni:" -#define STR_ZIP_DRIVES "ZIP pogoni:" -#define STR_250 "ZIP 250" +#define STR_MO_DRIVES "MO pogoni:" +#define STR_ZIP_DRIVES "ZIP pogoni:" +#define STR_250 "ZIP 250" -#define STR_ISARTC "Sat stvarnog vremena (RTC):" -#define STR_ISAMEM "ProÅ¡irenje memorije ISA" -#define STR_ISAMEM_1 "Kartica 1:" -#define STR_ISAMEM_2 "Kartica 2:" -#define STR_ISAMEM_3 "Kartica 3:" -#define STR_ISAMEM_4 "Kartica 4:" -#define STR_BUGGER "UreÄ‘aj ISABugger" -#define STR_POSTCARD "Kartica POST" +#define STR_ISARTC "Sat stvarnog vremena (RTC):" +#define STR_ISAMEM "ProÅ¡irenje memorije ISA" +#define STR_ISAMEM_1 "Kartica 1:" +#define STR_ISAMEM_2 "Kartica 2:" +#define STR_ISAMEM_3 "Kartica 3:" +#define STR_ISAMEM_4 "Kartica 4:" +#define STR_BUGGER "UreÄ‘aj ISABugger" +#define STR_POSTCARD "Kartica POST" -#define FONT_SIZE 9 -#define FONT_NAME "Segoe UI" +#define FONT_SIZE 9 +#define FONT_NAME "Segoe UI" #include "dialogs.rc" @@ -366,194 +392,188 @@ END // String Table // -STRINGTABLE DISCARDABLE +STRINGTABLE DISCARDABLE BEGIN - 2048 "86Box" - IDS_2049 "GreÅ¡ka" - IDS_2050 "Fatalna greÅ¡ka" - IDS_2051 " - PAUSED" - IDS_2052 "Pritisnite Ctrl+Alt+PgDn za povratak u prozorski naÄin rada." - IDS_2053 "Brzina" - IDS_2054 "ZIP %03i %i (%s): %ls" - IDS_2055 "ZIP slike (*.IM?;*.ZDI)\0*.IM?;*.ZDI\0" - IDS_2056 "86Box nije mogao pronaći upotrebljive ROM datoteke.\n\nMolimte posjetite sknite paket s ROM datotekama i ekstrahirajte paket u ""roms"" mapu." - IDS_2057 "(prazno)" - IDS_2058 "ZIP slike (*.IM?;*.ZDI)\0*.IM?;*.ZDI\0Sve datoteke (*.*)\0*.*\0" - IDS_2059 "Turbo" - IDS_2060 "UkljuÄeno" - IDS_2061 "IskljuÄeno" - IDS_2062 "Sve slike (*.86F;*.DSK;*.FLP;*.IM?;*.*FD?)\0*.86F;*.DSK;*.FLP;*.IM?;*.*FD?\0BOsnovne sektorske slike (*.DSK;*.FLP;*.IM?;*.*FD?)\0*.DSK;*.FLP;*.IM?;*.IMG;*.*FD?\0PovrÅ¡inske slike (*.86F)\0*.86F\0" - IDS_2063 "Sistem ""%hs"" nije dostupan jer ne postoje potrebni ROM-ovi u mapu roms/machines. Prebacivanje na dostupno raÄunalo." + 2048 "86Box" + IDS_2049 "GreÅ¡ka" + IDS_2050 "Fatalna greÅ¡ka" + IDS_2051 " - PAUSED" + IDS_2052 "Pritisnite Ctrl+Alt+PgDn za povratak u prozorski naÄin rada." + IDS_2053 "Brzina" + IDS_2054 "ZIP %03i %i (%s): %ls" + IDS_2055 "ZIP slike (*.IM?;*.ZDI)\0*.IM?;*.ZDI\0" + IDS_2056 "86Box nije mogao pronaći upotrebljive ROM datoteke.\n\nMolimte posjetite sknite paket s ROM datotekama i ekstrahirajte paket u ""roms"" mapu." + IDS_2057 "(prazno)" + IDS_2058 "ZIP slike (*.IM?;*.ZDI)\0*.IM?;*.ZDI\0Sve datoteke (*.*)\0*.*\0" + IDS_2059 "Turbo" + IDS_2060 "UkljuÄeno" + IDS_2061 "IskljuÄeno" + IDS_2062 "Sve slike (*.86F;*.DSK;*.FLP;*.IM?;*.*FD?)\0*.86F;*.DSK;*.FLP;*.IM?;*.*FD?\0BOsnovne sektorske slike (*.DSK;*.FLP;*.IM?;*.*FD?)\0*.DSK;*.FLP;*.IM?;*.IMG;*.*FD?\0PovrÅ¡inske slike (*.86F)\0*.86F\0" + IDS_2063 "Sistem ""%hs"" nije dostupan jer ne postoje potrebni ROM-ovi u mapu roms/machines. Prebacivanje na dostupno raÄunalo." END -STRINGTABLE DISCARDABLE +STRINGTABLE DISCARDABLE BEGIN - IDS_2064 "Video kartica ""%hs"" nije dostupna jer ne postoje potrebni ROM-ovi u mapu roms/video. Prebacivanje na dostupnu video karticu." - IDS_2065 "Sistem" - IDS_2066 "Video" - IDS_2067 "Ulazni ureÄ‘aji" - IDS_2068 "Zvuk" - IDS_2069 "Mreža" - IDS_2070 "Vrata (COM & LPT)" - IDS_2071 "Kontroleri za diskove" - IDS_2072 "Tvrdi diskovi" - IDS_2073 "Floppy & CD-ROM pogoni" - IDS_2074 "Ostali uklonjivi ureÄ‘aji" - IDS_2075 "Ostali periferni ureÄ‘aji" - IDS_2076 "PovrÅ¡inske slike (*.86F)\0*.86F\0" - IDS_2077 "Kliknite da uhvatite miÅ¡" - IDS_2078 "Pritisnite F8+F12 za otpustanje miÅ¡a" - IDS_2079 "Pritisnite F8+F12 ili srednji gumb miÅ¡a za otpuÅ¡tanje miÅ¡a" + IDS_2064 "Video kartica ""%hs"" nije dostupna jer ne postoje potrebni ROM-ovi u mapu roms/video. Prebacivanje na dostupnu video karticu." + IDS_2065 "Sistem" + IDS_2066 "Video" + IDS_2067 "Ulazni ureÄ‘aji" + IDS_2068 "Zvuk" + IDS_2069 "Mreža" + IDS_2070 "Vrata (COM & LPT)" + IDS_2071 "Kontroleri za diskove" + IDS_2072 "Tvrdi diskovi" + IDS_2073 "Floppy & CD-ROM pogoni" + IDS_2074 "Ostali uklonjivi ureÄ‘aji" + IDS_2075 "Ostali periferni ureÄ‘aji" + IDS_2076 "PovrÅ¡inske slike (*.86F)\0*.86F\0" + IDS_2077 "Kliknite da uhvatite miÅ¡" + IDS_2078 "Pritisnite F8+F12 za otpustanje miÅ¡a" + IDS_2079 "Pritisnite F8+F12 ili srednji gumb miÅ¡a za otpuÅ¡tanje miÅ¡a" END -STRINGTABLE DISCARDABLE +STRINGTABLE DISCARDABLE BEGIN - IDS_2080 "Nije moguće inicijalizirati FluidSynth" - IDS_2081 "Bus" - IDS_2082 "Datoteka" - IDS_2083 "C" - IDS_2084 "H" - IDS_2085 "S" - IDS_2086 "MB" - IDS_2087 "Provjeri BPB" - IDS_2088 "KB" - IDS_2089 "Nije moguće inicijalizirati renderer." - IDS_2090 "Standard" - IDS_2091 "%i stanje Äekanja" - IDS_2092 "Tip" - IDS_2093 "Postavljanje PCap-a nije uspjelo" - IDS_2094 "Nema PCap ureÄ‘aja" - IDS_2095 "Nevažeći PCap ureÄ‘aj" - IDS_2096 "Standardna palica za igru s 2 tipke" - IDS_2097 "Standardna palica za igru s 4 tipke" - IDS_2098 "Standardna palica za igru s 6 tipke" - IDS_2099 "Standardna palica za igru s 8 tipke" - IDS_2100 "CH Flightstick Pro" - IDS_2101 "Microsoft SideWinder Pad" - IDS_2102 "Thrustmaster Flight Control System" - IDS_2103 "Bez" - IDS_2104 "Nije moguće uÄitati ubrzivaÄe tipkovnice." - IDS_2105 "Nije moguće registrirati neobraÄ‘eni unos." - IDS_2106 "%u" - IDS_2107 "%u MB (CHS: %i, %i, %i)" - IDS_2108 "Disketa %i (%s): %ls" - IDS_2109 "Sve slike (*.0??;*.1??;*.??0;*.86F;*.BIN;*.CQ?;*.D??;*.FLP;*.HDM;*.IM?;*.JSON;*.TD0;*.*FD?;*.MFM;*.XDF)\0*.0??;*.1??;*.??0;*.86F;*.BIN;*.CQ?;*.D??;*.FLP;*.HDM;*.IM?;*.JSON;*.TD0;*.*FD?;*.MFM;*.XDF\0Napredne sektorske slike (*.IMD;*.JSON;*.TD0)\0*.IMD;*.JSON;*.TD0\0Osnovne sektorske slike (*.0??;*.1??;*.??0;*.BIN;*.CQ?;*.D??;*.FLP;*.HDM;*.IM?;*.XDF;*.*FD?)\0*.0??;*.1??;*.??0;*.BIN;*.CQ?;*.D??;*.FLP;*.HDM;*.IM?;*.XDF;*.*FD?\0Flux slike (*.FDI)\0*.FDI\0PovrÅ¡inske slike (*.86F;*.MFM)\0*.86F;*.MFM\0Sve datoteke (*.*)\0*.*\0" - IDS_2110 "Nije moguće inicijalizirati FreeType" - IDS_2111 "Nije moguće inicijalizirati SDL, SDL2.dll je potrebno" - IDS_2112 "Jeste li sigurni da želite hard resetirati emulirani sistem?" - IDS_2113 "Jeste li sigurni da želite zatvoriti 86Box?" - IDS_2114 "Nije moguće inicijalizirati GhostScript" - IDS_2115 "MO %i (%ls): %ls" - IDS_2116 "MO slike (*.IM?;*.MDI)\0*.IM?;*.MDI\0Svi datoteke (*.*)\0*.*\0" - IDS_2117 "DobrodoÅ¡li u 86Box!" - IDS_2118 "Uunutarnji kontroler" - IDS_2119 "Izlazi" - IDS_2120 "Nisu pronaÄ‘ene ROM datoteke" - IDS_2121 "Želite li spremiti postavke?" - IDS_2122 "Ovo će napraviti hard resetiranje emuliranog sistema." - IDS_2123 "Spremaj" - IDS_2124 "O programu 86Box" - IDS_2125 "86Box verzija " EMU_VERSION + IDS_2081 "Bus" + IDS_2082 "Datoteka" + IDS_2083 "C" + IDS_2084 "H" + IDS_2085 "S" + IDS_2086 "MB" + IDS_2087 "Speed" + IDS_2088 "Provjeri BPB" + IDS_2089 "KB" + IDS_2090 "Nije moguće inicijalizirati renderer." + IDS_2091 "Standard" + IDS_2092 "%i stanje Äekanja" + IDS_2093 "Tip" + IDS_2094 "Postavljanje PCap-a nije uspjelo" + IDS_2095 "Nema PCap ureÄ‘aja" + IDS_2096 "Nevažeći PCap ureÄ‘aj" + IDS_2097 "Standardna palica za igru s 2 tipke" + IDS_2098 "Standardna palica za igru s 4 tipke" + IDS_2099 "Standardna palica za igru s 6 tipke" + IDS_2100 "Standardna palica za igru s 8 tipke" + IDS_2101 "CH Flightstick Pro" + IDS_2102 "Microsoft SideWinder Pad" + IDS_2103 "Thrustmaster Flight Control System" + IDS_2104 "Bez" + IDS_2105 "Nije moguće uÄitati ubrzivaÄe tipkovnice." + IDS_2106 "Nije moguće registrirati neobraÄ‘eni unos." + IDS_2107 "%u" + IDS_2108 "%u MB (CHS: %i, %i, %i)" + IDS_2109 "Disketa %i (%s): %ls" + IDS_2110 "Sve slike (*.0??;*.1??;*.??0;*.86F;*.BIN;*.CQ?;*.D??;*.FLP;*.HDM;*.IM?;*.JSON;*.TD0;*.*FD?;*.MFM;*.XDF)\0*.0??;*.1??;*.??0;*.86F;*.BIN;*.CQ?;*.D??;*.FLP;*.HDM;*.IM?;*.JSON;*.TD0;*.*FD?;*.MFM;*.XDF\0Napredne sektorske slike (*.IMD;*.JSON;*.TD0)\0*.IMD;*.JSON;*.TD0\0Osnovne sektorske slike (*.0??;*.1??;*.??0;*.BIN;*.CQ?;*.D??;*.FLP;*.HDM;*.IM?;*.XDF;*.*FD?)\0*.0??;*.1??;*.??0;*.BIN;*.CQ?;*.D??;*.FLP;*.HDM;*.IM?;*.XDF;*.*FD?\0Flux slike (*.FDI)\0*.FDI\0PovrÅ¡inske slike (*.86F;*.MFM)\0*.86F;*.MFM\0Sve datoteke (*.*)\0*.*\0" + IDS_2112 "Nije moguće inicijalizirati SDL, SDL2.dll je potrebno" + IDS_2113 "Jeste li sigurni da želite hard resetirati emulirani sistem?" + IDS_2114 "Jeste li sigurni da želite zatvoriti 86Box?" + IDS_2115 "Nije moguće inicijalizirati GhostScript" + IDS_2116 "MO %i (%ls): %ls" + IDS_2117 "MO slike (*.IM?;*.MDI)\0*.IM?;*.MDI\0Svi datoteke (*.*)\0*.*\0" + IDS_2118 "DobrodoÅ¡li u 86Box!" + IDS_2119 "Uunutarnji kontroler" + IDS_2120 "Izlazi" + IDS_2121 "Nisu pronaÄ‘ene ROM datoteke" + IDS_2122 "Želite li spremiti postavke?" + IDS_2123 "Ovo će napraviti hard resetiranje emuliranog sistema." + IDS_2124 "Spremaj" + IDS_2125 "O programu 86Box" + IDS_2126 "86Box verzija " EMU_VERSION - IDS_2126 "Emulator starih raÄunala\n\nAutori: Sarah Walker, Miran Grca, Fred N. van Kempen (waltje), SA1988, Tiseno100, reenigne, leilei, JohnElliott, greatpsycho, i drugi.\n\nPreveo: dob205\n\nObjavljeno pod licencom GNU General Public License, verzija 2 ili novije. Za viÅ¡e informacija pogledajte datoteku LICENCE." - IDS_2127 "U redu" - IDS_2128 "Hardver nije dostupan" + IDS_2127 "Emulator starih raÄunala\n\nAutori: Miran GrÄa (OBattler), RichardG867, Jasmine Iwanek, TC1995, coldbrewed, Teemu Korhonen (Manaatti), Joakim L. Gilje, Adrien Moulin (elyosh), Daniel Balsom (gloriouscow), Cacodemon345, Fred N. van Kempen (waltje), Tiseno100, reenigne, i drugi.\n\nWith previous core contributions from Sarah Walker, leilei, JohnElliott, greatpsycho, i drugi.\n\nPreveo: dob205\n\nObjavljeno pod licencom GNU General Public License, verzija 2 ili novije. Za viÅ¡e informacija pogledajte datoteku LICENCE." + IDS_2128 "U redu" + IDS_2129 "Hardver nije dostupan" #ifdef _WIN32 #define LIB_NAME_PCAP "WinPcap" #else #define LIB_NAME_PCAP "libpcap" #endif - IDS_2129 "Provjerite je li " LIB_NAME_PCAP " instaliran i jeste li na mreži, kompadibilnoj s " LIB_NAME_PCAP "." - IDS_2130 "Nevažeća konfiguracija" -#ifdef _WIN32 -#define LIB_NAME_FREETYPE "freetype.dll" -#else -#define LIB_NAME_FREETYPE "libfreetype" -#endif - IDS_2131 LIB_NAME_FREETYPE " je potrebno za emuliranje ESC/P pisaÄa." + IDS_2130 "Provjerite je li " LIB_NAME_PCAP " instaliran i jeste li na mreži, kompadibilnoj s " LIB_NAME_PCAP "." + IDS_2131 "Nevažeća konfiguracija" #ifdef _WIN32 #define LIB_NAME_GS "gsdll32.dll" #else #define LIB_NAME_GS "libgs" #endif - IDS_2132 LIB_NAME_GS " je potrebno za automatsku konverziju PostScript datoteke u PDF datoteke.\n\nSvi dokumenti poslani na generiÄki PostScript pisaÄ bit će spremljeni kao PostScript (.ps) datoteke." -#ifdef _WIN32 -#define LIB_NAME_FLUIDSYNTH "libfluidsynth.dll" -#else -#define LIB_NAME_FLUIDSYNTH "libfluidsynth" -#endif - IDS_2133 LIB_NAME_FLUIDSYNTH " je potrebno za FluidSynth MIDI izlaz." - IDS_2134 "Ulazim u cijelozaslonski naÄin" - IDS_2135 "Ne pokazi viÅ¡e ovu poruku" - IDS_2136 "Ne izlazi" - IDS_2137 "Resetiraj" - IDS_2138 "Ne resetiraj" - IDS_2139 "MO slike (*.IM?;*.MDI)\0*.IM?;*.MDI\0Sve datoteke (*.*)\0*.*\0" - IDS_2140 "CD-ROM slike (*.ISO;*.CUE)\0*.ISO;*.CUE\0Sve datoteke (*.*)\0*.*\0" - IDS_2141 "Konfiguracija ureÄ‘aja %hs " - IDS_2142 "Ekran u stanju mirovanja" - IDS_2143 "OpenGL shaderi (*.GLSL)\0*.GLSL\0Sve datoteke (*.*)\0*.*\0" - IDS_2144 "OpenGL opcije" - IDS_2145 "UÄitavate nepodržanu konfiguraciju" - IDS_2146 "Filtriranje tipa CPU-a na temelju odabranog sistema onemogućeno je za ovaj emulirani sistem.\n\nOvo omogućuje odabir procesora koji inaÄe nisu kompatibilne s odabranog sistem. MeÄ‘utim, možete naići na na nekompatibilnosti s BIOS-om sustava ili drugim softverom.\n\nOmogućavanje ove postavke nije službeno podržano i sva prijava o greÅ¡kama mogu biti zatvorena kao ""invalid""." - IDS_2147 "Nastavi" - IDS_2148 "Audio kaseta: %s" - IDS_2149 "Slike audio kasete (*.PCM;*.RAW;*.WAV;*.CAS)\0*.PCM;*.RAW;*.WAV;*.CAS\0Sve datoteke (*.*)\0*.*\0" - IDS_2150 "Kaseta %i: %ls" - IDS_2151 "Slike kasete (*.A;*.B;*.JRC)\0*.A;*.B;*.JRC\0Sve datoteke (*.*)\0*.*\0" - IDS_2152 "Nije moguće inicijalizirati renderer" - IDS_2153 "Nije moguće inicijalizirati OpenGL (3.0 jezgra) renderer. Molimte koristite drugi renderer." - IDS_2154 "Nastavi" - IDS_2155 "Pauziraj" - IDS_2156 "Stisni Ctrl+Alt+Del" - IDS_2157 "Stisni Ctrl+Alt+Esc" - IDS_2158 "Ponovno pokretanje" - IDS_2159 "ACPI bazirano gaÅ¡enje" - IDS_2160 "Postavke" + IDS_2133 LIB_NAME_GS " je potrebno za automatsku konverziju PostScript datoteke u PDF datoteke.\n\nSvi dokumenti poslani na generiÄki PostScript pisaÄ bit će spremljeni kao PostScript (.ps) datoteke." + IDS_2135 "Ulazim u cijelozaslonski naÄin" + IDS_2136 "Ne pokazi viÅ¡e ovu poruku" + IDS_2137 "Ne izlazi" + IDS_2138 "Resetiraj" + IDS_2139 "Ne resetiraj" + IDS_2140 "MO slike (*.IM?;*.MDI)\0*.IM?;*.MDI\0Sve datoteke (*.*)\0*.*\0" + IDS_2141 "CD-ROM slike (*.ISO;*.CUE)\0*.ISO;*.CUE\0Sve datoteke (*.*)\0*.*\0" + IDS_2142 "Konfiguracija ureÄ‘aja %hs " + IDS_2143 "Ekran u stanju mirovanja" + IDS_2144 "OpenGL shaderi (*.GLSL)\0*.GLSL\0Sve datoteke (*.*)\0*.*\0" + IDS_2145 "OpenGL opcije" + IDS_2146 "UÄitavate nepodržanu konfiguraciju" + IDS_2147 "Filtriranje tipa CPU-a na temelju odabranog sistema onemogućeno je za ovaj emulirani sistem.\n\nOvo omogućuje odabir procesora koji inaÄe nisu kompatibilne s odabranog sistem. MeÄ‘utim, možete naići na na nekompatibilnosti s BIOS-om sustava ili drugim softverom.\n\nOmogućavanje ove postavke nije službeno podržano i sva prijava o greÅ¡kama mogu biti zatvorena kao ""invalid""." + IDS_2148 "Nastavi" + IDS_2149 "Audio kaseta: %s" + IDS_2150 "Slike audio kasete (*.PCM;*.RAW;*.WAV;*.CAS)\0*.PCM;*.RAW;*.WAV;*.CAS\0Sve datoteke (*.*)\0*.*\0" + IDS_2151 "Kaseta %i: %ls" + IDS_2152 "Slike kasete (*.A;*.B;*.JRC)\0*.A;*.B;*.JRC\0Sve datoteke (*.*)\0*.*\0" + IDS_2153 "Nije moguće inicijalizirati renderer" + IDS_2154 "Nije moguće inicijalizirati OpenGL (3.0 jezgra) renderer. Molimte koristite drugi renderer." + IDS_2155 "Nastavi" + IDS_2156 "Pauziraj" + IDS_2157 "Stisni Ctrl+Alt+Del" + IDS_2158 "Stisni Ctrl+Alt+Esc" + IDS_2159 "Ponovno pokretanje" + IDS_2160 "ACPI bazirano gaÅ¡enje" + IDS_2161 "Postavke" + IDS_2162 "Type" + IDS_2163 "No Dynarec" + IDS_2164 "Old Dynarec" + IDS_2165 "New Dynarec" + IDS_2166 "Video card #2 ""%hs"" is not available due to missing ROMs in the roms/video directory. Disabling the second video card." + IDS_2167 "Failed to initialize network driver" + IDS_2168 "The network configuration will be switched to the null driver" END -STRINGTABLE DISCARDABLE +STRINGTABLE DISCARDABLE BEGIN IDS_4096 "Tvrdi disk (%s)" - IDS_4097 "%01i:%01i" - IDS_4098 "%01i" - IDS_4099 "MFM/RLL ili ESDI CD-ROM pogoni nisu nikada postojali" - IDS_4100 "PrilagoÄ‘eno..." - IDS_4101 "PrilagoÄ‘eno (veliko)..." - IDS_4102 "Dodajte novi tvrdi disk" - IDS_4103 "Dodajte postojeći tvrdi disk" - IDS_4104 "HDI disk image datoteke ne mogu biti veće od 4 GB." - IDS_4105 "Slike tvrdog diska ne mogu biti veće od 127 GB." - IDS_4106 "Slike za tvrde diskove (*.HD?;*.IM?;*.VHD)\0*.HD?;*.IM?;*.VHD\0Sve datoteke (*.*)\0*.*\0" - IDS_4107 "Nije moguće proÄitati datoteku" - IDS_4108 "Nije moguće napisati datoteku" - IDS_4109 "HDI ili HDX slike s veliÄinom sektora koja nije 512 kB nisu podržane." - IDS_4110 "USB nije joÅ¡ podržano" - IDS_4111 "Slika diska već postoji" - IDS_4112 "Molimte unesite važeći naziv datoteke." - IDS_4113 "Slika je stvorena" - IDS_4114 "Provjerite je li postoji datoteka i je li Äitljiva." - IDS_4115 "Provjerite je li se datoteka sprema u mapu s dopuÅ¡tenjima za pisanje." - IDS_4116 "Slika diska je prevelika" - IDS_4117 "Ne zaboravite stvoriti particije i formatirati ih na novom disku." - IDS_4118 "Odabrana datoteka bit će prebrisana. Jeste li sigurni da želite koristiti ovu daoteku?" - IDS_4119 "Nepodržana slika diska" - IDS_4120 "PrepiÅ¡i" - IDS_4121 "Ne prepiÅ¡i" - IDS_4122 "Slika neobraÄ‘enih podataka (.img)" - IDS_4123 "HDI slika (.hdi)" - IDS_4124 "HDX slika (.hdx)" - IDS_4125 "VHD fiksne veliÄine (.vhd)" - IDS_4126 "VHD dinamiÄke veliÄine (.vhd)" - IDS_4127 "RazliÄiti VHD (.vhd)" - IDS_4128 "Veliki blokovi (2 MB)" - IDS_4129 "Mali blokovi (512 KB)" - IDS_4130 "VHD slike (*.VHD)\0*.VHD\0Sve datoteke (*.*)\0*.*\0" - IDS_4131 "Izaberi matiÄnu sliku VHD" - IDS_4132 "To bi moglo znaÄiti da je matiÄna slika promijenjena nakon Å¡to je stvorena razliÄita slika.\n\nTo se takoÄ‘er može dogoditi ako su slike premjeÅ¡tene ili kopirane, ili greÅ¡ka u programu koji je stvorio ovaj disk.\n\nŽelite li popraviti vremenske oznake?" - IDS_4133 "Vremenske ozanke matiÄne i poreÄ‘enog diska ne odgovaraju." - IDS_4134 "Ne mogu popraviti vremensku oznaku slike VHD." - IDS_4135 "%01i:%02i" + IDS_4097 "%01i:%01i" + IDS_4098 "%01i" + IDS_4099 "MFM/RLL ili ESDI CD-ROM pogoni nisu nikada postojali" + IDS_4100 "PrilagoÄ‘eno..." + IDS_4101 "PrilagoÄ‘eno (veliko)..." + IDS_4102 "Dodajte novi tvrdi disk" + IDS_4103 "Dodajte postojeći tvrdi disk" + IDS_4104 "HDI disk image datoteke ne mogu biti veće od 4 GB." + IDS_4105 "Slike tvrdog diska ne mogu biti veće od 127 GB." + IDS_4106 "Slike za tvrde diskove (*.HD?;*.IM?;*.VHD)\0*.HD?;*.IM?;*.VHD\0Sve datoteke (*.*)\0*.*\0" + IDS_4107 "Nije moguće proÄitati datoteku" + IDS_4108 "Nije moguće napisati datoteku" + IDS_4109 "HDI ili HDX slike s veliÄinom sektora koja nije 512 kB nisu podržane." + IDS_4110 "USB nije joÅ¡ podržano" + IDS_4111 "Slika diska već postoji" + IDS_4112 "Molimte unesite važeći naziv datoteke." + IDS_4113 "Slika je stvorena" + IDS_4114 "Provjerite je li postoji datoteka i je li Äitljiva." + IDS_4115 "Provjerite je li se datoteka sprema u mapu s dopuÅ¡tenjima za pisanje." + IDS_4116 "Slika diska je prevelika" + IDS_4117 "Ne zaboravite stvoriti particije i formatirati ih na novom disku." + IDS_4118 "Odabrana datoteka bit će prebrisana. Jeste li sigurni da želite koristiti ovu daoteku?" + IDS_4119 "Nepodržana slika diska" + IDS_4120 "PrepiÅ¡i" + IDS_4121 "Ne prepiÅ¡i" + IDS_4122 "Slika neobraÄ‘enih podataka (.img)" + IDS_4123 "HDI slika (.hdi)" + IDS_4124 "HDX slika (.hdx)" + IDS_4125 "VHD fiksne veliÄine (.vhd)" + IDS_4126 "VHD dinamiÄke veliÄine (.vhd)" + IDS_4127 "RazliÄiti VHD (.vhd)" + IDS_4128 "Veliki blokovi (2 MB)" + IDS_4129 "Mali blokovi (512 KB)" + IDS_4130 "VHD slike (*.VHD)\0*.VHD\0Sve datoteke (*.*)\0*.*\0" + IDS_4131 "Izaberi matiÄnu sliku VHD" + IDS_4132 "To bi moglo znaÄiti da je matiÄna slika promijenjena nakon Å¡to je stvorena razliÄita slika.\n\nTo se takoÄ‘er može dogoditi ako su slike premjeÅ¡tene ili kopirane, ili greÅ¡ka u programu koji je stvorio ovaj disk.\n\nŽelite li popraviti vremenske oznake?" + IDS_4133 "Vremenske ozanke matiÄne i poreÄ‘enog diska ne odgovaraju." + IDS_4134 "Ne mogu popraviti vremensku oznaku slike VHD." + IDS_4135 "%01i:%02i" IDS_4352 "MFM/RLL" IDS_4353 "XTA" @@ -562,56 +582,56 @@ BEGIN IDS_4356 "ATAPI" IDS_4357 "SCSI" - IDS_4608 "MFM/RLL (%01i:%01i)" - IDS_4609 "XTA (%01i:%01i)" - IDS_4610 "ESDI (%01i:%01i)" - IDS_4611 "IDE (%01i:%01i)" - IDS_4612 "ATAPI (%01i:%01i)" - IDS_4613 "SCSI (%01i:%02i)" + IDS_4608 "MFM/RLL (%01i:%01i)" + IDS_4609 "XTA (%01i:%01i)" + IDS_4610 "ESDI (%01i:%01i)" + IDS_4611 "IDE (%01i:%01i)" + IDS_4612 "ATAPI (%01i:%01i)" + IDS_4613 "SCSI (%01i:%02i)" - IDS_5120 "CD-ROM %i (%s): %s" + IDS_5120 "CD-ROM %i (%s): %s" - IDS_5376 "Deaktivirano" - IDS_5381 "ATAPI" + IDS_5376 "Deaktivirano" + IDS_5381 "ATAPI" IDS_5382 "SCSI" - IDS_5632 "Deaktivirano" - IDS_5637 "ATAPI (%01i:%01i)" + IDS_5632 "Deaktivirano" + IDS_5637 "ATAPI (%01i:%01i)" IDS_5638 "SCSI (%01i:%02i)" - IDS_5888 "160 kB" - IDS_5889 "180 kB" - IDS_5890 "320 kB" - IDS_5891 "360 kB" - IDS_5892 "640 kB" - IDS_5893 "720 kB" - IDS_5894 "1,2 MB" - IDS_5895 "1,25 MB" - IDS_5896 "1,44 MB" - IDS_5897 "DMF (1024 clusteri)" - IDS_5898 "DMF (2048 clusteri)" - IDS_5899 "2,88 MB" - IDS_5900 "ZIP 100" - IDS_5901 "ZIP 250" - IDS_5902 "3,5"" 128 MB (ISO 10090)" - IDS_5903 "3,5"" 230 MB (ISO 13963)" - IDS_5904 "3,5"" 540 MB (ISO 15498)" - IDS_5905 "3,5"" 640 MB (ISO 15498)" - IDS_5906 "3,5"" 1.3 GB (GigaMO)" - IDS_5907 "3,5"" 2.3 GB (GigaMO 2)" - IDS_5908 "5,25"" 600 MB" - IDS_5909 "5,25"" 650 MB" - IDS_5910 "5,25"" 1 GB" - IDS_5911 "5,25"" 1.3 GB" + IDS_5888 "160 kB" + IDS_5889 "180 kB" + IDS_5890 "320 kB" + IDS_5891 "360 kB" + IDS_5892 "640 kB" + IDS_5893 "720 kB" + IDS_5894 "1,2 MB" + IDS_5895 "1,25 MB" + IDS_5896 "1,44 MB" + IDS_5897 "DMF (1024 clusteri)" + IDS_5898 "DMF (2048 clusteri)" + IDS_5899 "2,88 MB" + IDS_5900 "ZIP 100" + IDS_5901 "ZIP 250" + IDS_5902 "3,5"" 128 MB (ISO 10090)" + IDS_5903 "3,5"" 230 MB (ISO 13963)" + IDS_5904 "3,5"" 540 MB (ISO 15498)" + IDS_5905 "3,5"" 640 MB (ISO 15498)" + IDS_5906 "3,5"" 1.3 GB (GigaMO)" + IDS_5907 "3,5"" 2.3 GB (GigaMO 2)" + IDS_5908 "5,25"" 600 MB" + IDS_5909 "5,25"" 650 MB" + IDS_5910 "5,25"" 1 GB" + IDS_5911 "5,25"" 1.3 GB" - IDS_6144 "SavrÅ¡eni broj okretaja u minuti" - IDS_6145 "1% ispod savrÅ¡enog broja okretaja" - IDS_6146 "1,5% ispod savrÅ¡enog broja okretaja" - IDS_6147 "2% ispod savrÅ¡enog broja okretaja" + IDS_6144 "SavrÅ¡eni broj okretaja u minuti" + IDS_6145 "1% ispod savrÅ¡enog broja okretaja" + IDS_6146 "1,5% ispod savrÅ¡enog broja okretaja" + IDS_6147 "2% ispod savrÅ¡enog broja okretaja" - IDS_7168 "(Zadana postavka operativnog sustava)" + IDS_7168 "(Zadana postavka operativnog sustava)" END -#define IDS_LANG_ENUS IDS_7168 +#define IDS_LANG_ENUS IDS_7168 // Croatian (hr-HR) resources ///////////////////////////////////////////////////////////////////////////// diff --git a/src/win/languages/hu-HU.rc b/src/win/languages/hu-HU.rc index d0cccad1a..ab91d43f5 100644 --- a/src/win/languages/hu-HU.rc +++ b/src/win/languages/hu-HU.rc @@ -18,113 +18,122 @@ LANGUAGE LANG_HUNGARIAN, SUBLANG_DEFAULT // Menu // -MainMenu MENU DISCARDABLE +MainMenu MENU DISCARDABLE BEGIN POPUP "&Művelet" BEGIN - MENUITEM "A &billentyűzet elfogást igényel", IDM_ACTION_KBD_REQ_CAPTURE - MENUITEM "A &jobb oldali CTRL a bal ALT", IDM_ACTION_RCTRL_IS_LALT + MENUITEM "A &billentyűzet elfogást igényel", IDM_ACTION_KBD_REQ_CAPTURE + MENUITEM "A &jobb oldali CTRL a bal ALT", IDM_ACTION_RCTRL_IS_LALT MENUITEM SEPARATOR - MENUITEM "Hardveres &újraindítás...", IDM_ACTION_HRESET - MENUITEM "&Ctrl+Alt+Del\tCtrl+F12", IDM_ACTION_RESET_CAD + MENUITEM "Hardveres &újraindítás...", IDM_ACTION_HRESET + MENUITEM "&Ctrl+Alt+Del\tCtrl+F12", IDM_ACTION_RESET_CAD MENUITEM SEPARATOR - MENUITEM "Ctrl+Alt+&Esc", IDM_ACTION_CTRL_ALT_ESC + MENUITEM "Ctrl+Alt+&Esc", IDM_ACTION_CTRL_ALT_ESC MENUITEM SEPARATOR - MENUITEM "&Szüneteltetés", IDM_ACTION_PAUSE + MENUITEM "&Szüneteltetés", IDM_ACTION_PAUSE MENUITEM SEPARATOR - MENUITEM "&Kilépés...", IDM_ACTION_EXIT + MENUITEM "&Kilépés...", IDM_ACTION_EXIT END POPUP "&Nézet" BEGIN - MENUITEM "Ãllapotsor &elrejtése", IDM_VID_HIDE_STATUS_BAR - MENUITEM "Hide &toolbar", IDM_VID_HIDE_TOOLBAR + MENUITEM "Ãllapotsor &elrejtése", IDM_VID_HIDE_STATUS_BAR + MENUITEM "Hide &toolbar", IDM_VID_HIDE_TOOLBAR MENUITEM SEPARATOR - MENUITEM "&ÃtméretezhetÅ‘ ablak", IDM_VID_RESIZE - MENUITEM "Méret és pozíció &megjegyzése", IDM_VID_REMEMBER + MENUITEM "&Show non-primary monitors", IDM_VID_MONITORS + MENUITEM "&ÃtméretezhetÅ‘ ablak", IDM_VID_RESIZE + MENUITEM "Méret és pozíció &megjegyzése", IDM_VID_REMEMBER MENUITEM SEPARATOR POPUP "&MegjelenítÅ‘" BEGIN - MENUITEM "&SDL (Szoftveres)", IDM_VID_SDL_SW - MENUITEM "SDL (&Hardveres)", IDM_VID_SDL_HW - MENUITEM "SDL (&OpenGL)", IDM_VID_SDL_OPENGL - MENUITEM "Open&GL (3.0 Core)", IDM_VID_OPENGL_CORE + MENUITEM "&SDL (Szoftveres)", IDM_VID_SDL_SW + MENUITEM "SDL (&Hardveres)", IDM_VID_SDL_HW + MENUITEM "SDL (&OpenGL)", IDM_VID_SDL_OPENGL + MENUITEM "Open&GL (3.0 Core)", IDM_VID_OPENGL_CORE #ifdef USE_VNC - MENUITEM "&VNC", IDM_VID_VNC + MENUITEM "&VNC", IDM_VID_VNC #endif END MENUITEM SEPARATOR - MENUITEM "Méretek kézi megadása...", IDM_VID_SPECIFY_DIM - MENUITEM "&Rögzített 4:3 képarány", IDM_VID_FORCE43 + MENUITEM "Méretek kézi megadása...", IDM_VID_SPECIFY_DIM + MENUITEM "&Rögzített 4:3 képarány", IDM_VID_FORCE43 POPUP "&Ablak méretezési tényezÅ‘" BEGIN - MENUITEM "&0,5x", IDM_VID_SCALE_1X - MENUITEM "&1x", IDM_VID_SCALE_2X - MENUITEM "1,&5x", IDM_VID_SCALE_3X - MENUITEM "&2x", IDM_VID_SCALE_4X + MENUITEM "&0,5x", IDM_VID_SCALE_1X + MENUITEM "&1x", IDM_VID_SCALE_2X + MENUITEM "1,&5x", IDM_VID_SCALE_3X + MENUITEM "&2x", IDM_VID_SCALE_4X + MENUITEM "&3x", IDM_VID_SCALE_5X + MENUITEM "&4x", IDM_VID_SCALE_6X + MENUITEM "&5x", IDM_VID_SCALE_7X + MENUITEM "&6x", IDM_VID_SCALE_8X + MENUITEM "&7x", IDM_VID_SCALE_9X + MENUITEM "&8x", IDM_VID_SCALE_10X END POPUP "Szűrési mód" BEGIN - MENUITEM "&Szomszédos", IDM_VID_FILTER_NEAREST - MENUITEM "&Lineáris", IDM_VID_FILTER_LINEAR + MENUITEM "&Szomszédos", IDM_VID_FILTER_NEAREST + MENUITEM "&Lineáris", IDM_VID_FILTER_LINEAR END - MENUITEM "Hi&DPI méretezés", IDM_VID_HIDPI + MENUITEM "Hi&DPI méretezés", IDM_VID_HIDPI MENUITEM SEPARATOR - MENUITEM "&Teljes képernyÅ‘\tCtrl+Alt+PgUp", IDM_VID_FULLSCREEN + MENUITEM "&Teljes képernyÅ‘\tCtrl+Alt+PgUp", IDM_VID_FULLSCREEN POPUP "Teljes képernyÅ‘s &méretezés" BEGIN - MENUITEM "&Nyújtás a teljes képernyÅ‘re", IDM_VID_FS_FULL - MENUITEM "&4:3", IDM_VID_FS_43 + MENUITEM "&Nyújtás a teljes képernyÅ‘re", IDM_VID_FS_FULL + MENUITEM "&4:3", IDM_VID_FS_43 MENUITEM "&Négyzetes képpontok (aránytartás)", IDM_VID_FS_KEEPRATIO - MENUITEM "&Egész tényezÅ‘s nagyítás", IDM_VID_FS_INT + MENUITEM "&Egész tényezÅ‘s nagyítás", IDM_VID_FS_INT END POPUP "E&GA/(S)VGA beállítások" BEGIN - MENUITEM "&Invertált VGA kijelzÅ‘", IDM_VID_INVERT + MENUITEM "&Invertált VGA kijelzÅ‘", IDM_VID_INVERT POPUP "VGA képernyÅ‘ &típusa" BEGIN - MENUITEM "RGB &színes", IDM_VID_GRAY_RGB - MENUITEM "&RGB szürkeárnyalatos", IDM_VID_GRAY_MONO - MENUITEM "&Gyömbér kijelzÅ‘", IDM_VID_GRAY_AMBER - MENUITEM "&Zöld kijelzÅ‘", IDM_VID_GRAY_GREEN - MENUITEM "&Fehér kijelzÅ‘", IDM_VID_GRAY_WHITE + MENUITEM "RGB &színes", IDM_VID_GRAY_RGB + MENUITEM "&RGB szürkeárnyalatos", IDM_VID_GRAY_MONO + MENUITEM "&Gyömbér kijelzÅ‘", IDM_VID_GRAY_AMBER + MENUITEM "&Zöld kijelzÅ‘", IDM_VID_GRAY_GREEN + MENUITEM "&Fehér kijelzÅ‘", IDM_VID_GRAY_WHITE END POPUP "Szürkéskála &konzerziós eljárás" BEGIN - MENUITEM "BT&601 (NTSC/PAL)", IDM_VID_GRAYCT_601 - MENUITEM "BT&709 (HDTV)", IDM_VID_GRAYCT_709 - MENUITEM "&Ãtlag szerint", IDM_VID_GRAYCT_AVE + MENUITEM "BT&601 (NTSC/PAL)", IDM_VID_GRAYCT_601 + MENUITEM "BT&709 (HDTV)", IDM_VID_GRAYCT_709 + MENUITEM "&Ãtlag szerint", IDM_VID_GRAYCT_AVE END END MENUITEM SEPARATOR - MENUITEM "CGA/PCjr/Tandy/E&GA/(S)VGA túlpásztázás", IDM_VID_OVERSCAN + MENUITEM "CGA/PCjr/Tandy/E&GA/(S)VGA túlpásztázás", IDM_VID_OVERSCAN MENUITEM "Kontraszt illesztése &monokróm kijelzÅ‘höz", IDM_VID_CGACON END - MENUITEM "&Média", IDM_MEDIA + MENUITEM "&Média", IDM_MEDIA POPUP "&Eszközök" BEGIN - MENUITEM "&Konfigurálás...", IDM_CONFIG - MENUITEM "Ãllapotsori ikonok &frissítése", IDM_UPDATE_ICONS + MENUITEM "&Konfigurálás...", IDM_CONFIG + MENUITEM "Ãllapotsori ikonok &frissítése", IDM_UPDATE_ICONS MENUITEM SEPARATOR - MENUITEM "&KépernyÅ‘kép készítése\tCtrl+F11", IDM_ACTION_SCREENSHOT + MENUITEM "&KépernyÅ‘kép készítése\tCtrl+F11", IDM_ACTION_SCREENSHOT MENUITEM SEPARATOR - MENUITEM "&Beállítások...", IDM_PREFERENCES + MENUITEM "&Beállítások...", IDM_PREFERENCES +#ifdef DISCORD MENUITEM "&Discord integráció engedélyezése", IDM_DISCORD +#endif MENUITEM SEPARATOR - MENUITEM "&HangerÅ‘szabályzó...", IDM_SND_GAIN + MENUITEM "&HangerÅ‘szabályzó...", IDM_SND_GAIN #ifdef MTR_ENABLED MENUITEM SEPARATOR - MENUITEM "Nyomkövetés megkezdése\tCtrl+T", IDM_ACTION_BEGIN_TRACE - MENUITEM "Nyomkövetés befejezése\tCtrl+T", IDM_ACTION_END_TRACE + MENUITEM "Nyomkövetés megkezdése\tCtrl+T", IDM_ACTION_BEGIN_TRACE + MENUITEM "Nyomkövetés befejezése\tCtrl+T", IDM_ACTION_END_TRACE #endif END POPUP "&Súgó" BEGIN - MENUITEM "&Dokumentáció...", IDM_DOCS - MENUITEM "A 86Box &névjegye...", IDM_ABOUT + MENUITEM "&Dokumentáció...", IDM_DOCS + MENUITEM "A 86Box &névjegye...", IDM_ABOUT END END -StatusBarMenu MENU DISCARDABLE +StatusBarMenu MENU DISCARDABLE BEGIN MENUITEM SEPARATOR END @@ -133,17 +142,17 @@ CassetteSubmenu MENU DISCARDABLE BEGIN POPUP "" BEGIN - MENUITEM "&Új képfájl létrehozása...", IDM_CASSETTE_IMAGE_NEW + MENUITEM "&Új képfájl létrehozása...", IDM_CASSETTE_IMAGE_NEW MENUITEM SEPARATOR - MENUITEM "MeglévÅ‘ képfájl &megnyitása...", IDM_CASSETTE_IMAGE_EXISTING - MENUITEM "MeglévÅ‘ képfájl megnyitása (&írásvédett)...", IDM_CASSETTE_IMAGE_EXISTING_WP + MENUITEM "MeglévÅ‘ képfájl &megnyitása...", IDM_CASSETTE_IMAGE_EXISTING + MENUITEM "MeglévÅ‘ képfájl megnyitása (&írásvédett)...", IDM_CASSETTE_IMAGE_EXISTING_WP MENUITEM SEPARATOR - MENUITEM "&Felvétel", IDM_CASSETTE_RECORD - MENUITEM "&Lejátszás", IDM_CASSETTE_PLAY - MENUITEM "&Visszatekerés az elejére", IDM_CASSETTE_REWIND - MENUITEM "&ElÅ‘retekerés a végére", IDM_CASSETTE_FAST_FORWARD + MENUITEM "&Felvétel", IDM_CASSETTE_RECORD + MENUITEM "&Lejátszás", IDM_CASSETTE_PLAY + MENUITEM "&Visszatekerés az elejére", IDM_CASSETTE_REWIND + MENUITEM "&ElÅ‘retekerés a végére", IDM_CASSETTE_FAST_FORWARD MENUITEM SEPARATOR - MENUITEM "&Kiadás", IDM_CASSETTE_EJECT + MENUITEM "&Kiadás", IDM_CASSETTE_EJECT END END @@ -151,9 +160,9 @@ CartridgeSubmenu MENU DISCARDABLE BEGIN POPUP "" BEGIN - MENUITEM "Kép&fájl...", IDM_CARTRIDGE_IMAGE + MENUITEM "Kép&fájl...", IDM_CARTRIDGE_IMAGE MENUITEM SEPARATOR - MENUITEM "&Kiadás", IDM_CARTRIDGE_EJECT + MENUITEM "&Kiadás", IDM_CARTRIDGE_EJECT END END @@ -161,14 +170,14 @@ FloppySubmenu MENU DISCARDABLE BEGIN POPUP "" BEGIN - MENUITEM "&Új képfájl létrehozása...", IDM_FLOPPY_IMAGE_NEW + MENUITEM "&Új képfájl létrehozása...", IDM_FLOPPY_IMAGE_NEW MENUITEM SEPARATOR - MENUITEM "MeglévÅ‘ képfájl &megnyitása...", IDM_FLOPPY_IMAGE_EXISTING - MENUITEM "MeglévÅ‘ képfájl megnyitása (&írásvédett)...", IDM_FLOPPY_IMAGE_EXISTING_WP + MENUITEM "MeglévÅ‘ képfájl &megnyitása...", IDM_FLOPPY_IMAGE_EXISTING + MENUITEM "MeglévÅ‘ képfájl megnyitása (&írásvédett)...", IDM_FLOPPY_IMAGE_EXISTING_WP MENUITEM SEPARATOR - MENUITEM "E&xportálás 86F formátumba...", IDM_FLOPPY_EXPORT_TO_86F + MENUITEM "E&xportálás 86F formátumba...", IDM_FLOPPY_EXPORT_TO_86F MENUITEM SEPARATOR - MENUITEM "&Kiadás", IDM_FLOPPY_EJECT + MENUITEM "&Kiadás", IDM_FLOPPY_EJECT END END @@ -176,12 +185,13 @@ CdromSubmenu MENU DISCARDABLE BEGIN POPUP "" BEGIN - MENUITEM "&Némítás", IDM_CDROM_MUTE + MENUITEM "&Némítás", IDM_CDROM_MUTE MENUITEM SEPARATOR - MENUITEM "&Kiadás", IDM_CDROM_EMPTY - MENUITEM "ElÅ‘zÅ‘ képfájl &újratöltése", IDM_CDROM_RELOAD + MENUITEM "&Kiadás", IDM_CDROM_EMPTY + MENUITEM "ElÅ‘zÅ‘ képfájl &újratöltése", IDM_CDROM_RELOAD MENUITEM SEPARATOR - MENUITEM "&MeglévÅ‘ képfájl &megnyitása...", IDM_CDROM_IMAGE + MENUITEM "&MeglévÅ‘ képfájl &megnyitása...", IDM_CDROM_IMAGE + MENUITEM "&Mappa...", IDM_CDROM_DIR END END @@ -189,13 +199,13 @@ ZIPSubmenu MENU DISCARDABLE BEGIN POPUP "" BEGIN - MENUITEM "&Új képfájl létrehozása...", IDM_ZIP_IMAGE_NEW + MENUITEM "&Új képfájl létrehozása...", IDM_ZIP_IMAGE_NEW MENUITEM SEPARATOR - MENUITEM "&MeglévÅ‘ képfájl &megnyitása...", IDM_ZIP_IMAGE_EXISTING - MENUITEM "MeglévÅ‘ képfájl megnyitása (&írásvédett)...", IDM_ZIP_IMAGE_EXISTING_WP + MENUITEM "&MeglévÅ‘ képfájl &megnyitása...", IDM_ZIP_IMAGE_EXISTING + MENUITEM "MeglévÅ‘ képfájl megnyitása (&írásvédett)...", IDM_ZIP_IMAGE_EXISTING_WP MENUITEM SEPARATOR - MENUITEM "Kiadás", IDM_ZIP_EJECT - MENUITEM "ElÅ‘zÅ‘ képfájl &újratöltése", IDM_ZIP_RELOAD + MENUITEM "Kiadás", IDM_ZIP_EJECT + MENUITEM "ElÅ‘zÅ‘ képfájl &újratöltése", IDM_ZIP_RELOAD END END @@ -203,13 +213,13 @@ MOSubmenu MENU DISCARDABLE BEGIN POPUP "" BEGIN - MENUITEM "&Új képfájl létrehozása...", IDM_MO_IMAGE_NEW + MENUITEM "&Új képfájl létrehozása...", IDM_MO_IMAGE_NEW MENUITEM SEPARATOR - MENUITEM "&MeglévÅ‘ képfájl &megnyitása...", IDM_MO_IMAGE_EXISTING - MENUITEM "MeglévÅ‘ képfájl megnyitása (&írásvédett)...", IDM_MO_IMAGE_EXISTING_WP + MENUITEM "&MeglévÅ‘ képfájl &megnyitása...", IDM_MO_IMAGE_EXISTING + MENUITEM "MeglévÅ‘ képfájl megnyitása (&írásvédett)...", IDM_MO_IMAGE_EXISTING_WP MENUITEM SEPARATOR - MENUITEM "Kiadás", IDM_MO_EJECT - MENUITEM "ElÅ‘zÅ‘ képfájl &újratöltése", IDM_MO_RELOAD + MENUITEM "Kiadás", IDM_MO_EJECT + MENUITEM "ElÅ‘zÅ‘ képfájl &újratöltése", IDM_MO_RELOAD END END @@ -235,134 +245,150 @@ END // Dialog // -#define STR_PREFERENCES "Beállítások" -#define STR_SND_GAIN "HangerÅ‘szabályzó" -#define STR_NEW_FLOPPY "Új képfájl létrehozása" -#define STR_CONFIG "Konfigurálás" -#define STR_SPECIFY_DIM "FÅ‘ablak méreteinek megadása" +#define STR_PREFERENCES "Beállítások" +#define STR_SND_GAIN "HangerÅ‘szabályzó" +#define STR_NEW_FLOPPY "Új képfájl létrehozása" +#define STR_CONFIG "Konfigurálás" +#define STR_SPECIFY_DIM "FÅ‘ablak méreteinek megadása" -#define STR_OK "OK" -#define STR_CANCEL "Mégse" -#define STR_GLOBAL "Beállítások mentése &globális alapértékként" -#define STR_DEFAULT "&Alapértelmezett" -#define STR_LANGUAGE "Nyelv:" -#define STR_ICONSET "Ikonkészlet:" +#define STR_OK "OK" +#define STR_CANCEL "Mégse" +#define STR_GLOBAL "Beállítások mentése &globális alapértékként" +#define STR_DEFAULT "&Alapértelmezett" +#define STR_LANGUAGE "Nyelv:" +#define STR_ICONSET "Ikonkészlet:" -#define STR_GAIN "HangerÅ‘" +#define STR_GAIN "HangerÅ‘" -#define STR_FILE_NAME "Fájlnév:" -#define STR_DISK_SIZE "Méret:" -#define STR_RPM_MODE "RPM-mód:" -#define STR_PROGRESS "Folyamat:" +#define STR_FILE_NAME "Fájlnév:" +#define STR_DISK_SIZE "Méret:" +#define STR_RPM_MODE "RPM-mód:" +#define STR_PROGRESS "Folyamat:" -#define STR_WIDTH "Szélesség:" -#define STR_HEIGHT "Magasság:" -#define STR_LOCK_TO_SIZE "Rögzítés a megadott méretre" +#define STR_WIDTH "Szélesség:" +#define STR_HEIGHT "Magasság:" +#define STR_LOCK_TO_SIZE "Rögzítés a megadott méretre" -#define STR_MACHINE_TYPE "Géptípus:" -#define STR_MACHINE "Számítógép:" -#define STR_CONFIGURE "Beállítások..." -#define STR_CPU_TYPE "Processzor:" -#define STR_CPU_SPEED "Seb.:" -#define STR_FPU "FPU-egység:" -#define STR_WAIT_STATES "Várak. ciklusok:" -#define STR_MB "MB" -#define STR_MEMORY "Memória:" -#define STR_TIME_SYNC "IdÅ‘ szinkronizáció" -#define STR_DISABLED "Letiltva" -#define STR_ENABLED_LOCAL "Engedélyezve (helyi idÅ‘)" -#define STR_ENABLED_UTC "Engedélyezve (UTC)" -#define STR_DYNAREC "Dinamikus újrafordítás" +#define STR_MACHINE_TYPE "Géptípus:" +#define STR_MACHINE "Számítógép:" +#define STR_CONFIGURE "Beállítások..." +#define STR_CPU_TYPE "Processzor:" +#define STR_CPU_SPEED "Seb.:" +#define STR_FPU "FPU-egység:" +#define STR_WAIT_STATES "Várak. ciklusok:" +#define STR_MB "MB" +#define STR_MEMORY "Memória:" +#define STR_TIME_SYNC "IdÅ‘ szinkronizáció" +#define STR_DISABLED "Letiltva" +#define STR_ENABLED_LOCAL "Engedélyezve (helyi idÅ‘)" +#define STR_ENABLED_UTC "Engedélyezve (UTC)" +#define STR_DYNAREC "Dinamikus újrafordítás" +#define STR_SOFTFLOAT "Softfloat FPU" -#define STR_VIDEO "Videokártya:" -#define STR_VOODOO "Voodoo-gyorsítókártya" +#define STR_VIDEO "Videokártya:" +#define STR_VIDEO_2 "Videokártya 2:" +#define STR_VOODOO "Voodoo-gyorsítókártya" +#define STR_IBM8514 "IBM 8514/a-gyorsítókártya" +#define STR_XGA "XGA-gyorsítókártya" -#define STR_MOUSE "Egér:" -#define STR_JOYSTICK "JátékvezérlÅ‘:" -#define STR_JOY1 "Játékvez. 1..." -#define STR_JOY2 "Játékvez. 2..." -#define STR_JOY3 "Játékvez. 3..." -#define STR_JOY4 "Játékvez. 4..." +#define STR_MOUSE "Egér:" +#define STR_JOYSTICK "JátékvezérlÅ‘:" +#define STR_JOY1 "Játékvez. 1..." +#define STR_JOY2 "Játékvez. 2..." +#define STR_JOY3 "Játékvez. 3..." +#define STR_JOY4 "Játékvez. 4..." -#define STR_SOUND "Hangkártya:" -#define STR_MIDI_OUT "MIDI-kimenet:" -#define STR_MIDI_IN "MIDI-bemenet:" -#define STR_MPU401 "Különálló MPU-401" -#define STR_SSI "Innovation SSI-2001" -#define STR_CMS "CMS / Game Blaster" -#define STR_GUS "Gravis Ultrasound" -#define STR_FLOAT "FLOAT32 használata" +#define STR_SOUND1 "Hangkártya 1:" +#define STR_SOUND2 "Hangkártya 2:" +#define STR_SOUND3 "Hangkártya 3:" +#define STR_SOUND4 "Hangkártya 4:" +#define STR_MIDI_OUT "MIDI-kimenet:" +#define STR_MIDI_IN "MIDI-bemenet:" +#define STR_MPU401 "Különálló MPU-401" +#define STR_FLOAT "FLOAT32 használata" +#define STR_FM_DRIVER "FM szintetizátor meghajtó" +#define STR_FM_DRV_NUKED "Nuked (pontosabb)" +#define STR_FM_DRV_YMFM "YMFM (gyorsabb)" -#define STR_NET_TYPE "Hálózati típusa:" -#define STR_PCAP "PCap eszköz:" -#define STR_NET "Hálózati kártya:" +#define STR_NET_TYPE "Hálózati típusa:" +#define STR_PCAP "PCap eszköz:" +#define STR_NET "Hálózati kártya:" +#define STR_NET1 "Network card 1:" +#define STR_NET2 "Network card 2:" +#define STR_NET3 "Network card 3:" +#define STR_NET4 "Network card 4:" -#define STR_COM1 "COM1 eszköz:" -#define STR_COM2 "COM2 eszköz:" -#define STR_COM3 "COM3 eszköz:" -#define STR_COM4 "COM4 eszköz:" -#define STR_LPT1 "LPT1 eszköz:" -#define STR_LPT2 "LPT2 eszköz:" -#define STR_LPT3 "LPT3 eszköz:" -#define STR_LPT4 "LPT4 eszköz:" -#define STR_SERIAL1 "Soros port 1" -#define STR_SERIAL2 "Soros port 2" -#define STR_SERIAL3 "Soros port 3" -#define STR_SERIAL4 "Soros port 4" -#define STR_PARALLEL1 "Párhuzamos port 1" -#define STR_PARALLEL2 "Párhuzamos port 2" -#define STR_PARALLEL3 "Párhuzamos port 3" -#define STR_PARALLEL4 "Párhuzamos port 4" +#define STR_COM1 "COM1 eszköz:" +#define STR_COM2 "COM2 eszköz:" +#define STR_COM3 "COM3 eszköz:" +#define STR_COM4 "COM4 eszköz:" +#define STR_LPT1 "LPT1 eszköz:" +#define STR_LPT2 "LPT2 eszköz:" +#define STR_LPT3 "LPT3 eszköz:" +#define STR_LPT4 "LPT4 eszköz:" +#define STR_SERIAL1 "Soros port 1" +#define STR_SERIAL2 "Soros port 2" +#define STR_SERIAL3 "Soros port 3" +#define STR_SERIAL4 "Soros port 4" +#define STR_PARALLEL1 "Párhuzamos port 1" +#define STR_PARALLEL2 "Párhuzamos port 2" +#define STR_PARALLEL3 "Párhuzamos port 3" +#define STR_PARALLEL4 "Párhuzamos port 4" +#define STR_SERIAL_PASS1 "Serial port passthrough 1" +#define STR_SERIAL_PASS2 "Serial port passthrough 2" +#define STR_SERIAL_PASS3 "Serial port passthrough 3" +#define STR_SERIAL_PASS4 "Serial port passthrough 4" -#define STR_HDC "Merevl.-vezérlÅ‘:" -#define STR_FDC "Floppy-vezérlÅ‘:" -#define STR_IDE_TER "Harmadlagos IDE-vezérlÅ‘" -#define STR_IDE_QUA "Negyedleges IDE-vezérlÅ‘" -#define STR_SCSI "SCSI" -#define STR_SCSI_1 "Gazdaadapt. 1:" -#define STR_SCSI_2 "Gazdaadapt. 2:" -#define STR_SCSI_3 "Gazdaadapt. 3:" -#define STR_SCSI_4 "Gazdaadapt. 4:" -#define STR_CASSETTE "Magnókazetta" +#define STR_HDC "Merevl.-vezérlÅ‘:" +#define STR_FDC "Floppy-vezérlÅ‘:" +#define STR_IDE_TER "Harmadlagos IDE-vezérlÅ‘" +#define STR_IDE_QUA "Negyedleges IDE-vezérlÅ‘" +#define STR_SCSI "SCSI" +#define STR_SCSI_1 "Gazdaadapt. 1:" +#define STR_SCSI_2 "Gazdaadapt. 2:" +#define STR_SCSI_3 "Gazdaadapt. 3:" +#define STR_SCSI_4 "Gazdaadapt. 4:" +#define STR_CASSETTE "Magnókazetta" -#define STR_HDD "Merevlemezek:" -#define STR_NEW "&Új..." -#define STR_EXISTING "&Megnyitás..." -#define STR_REMOVE "&Eltávolítás" -#define STR_BUS "Busz:" -#define STR_CHANNEL "Csatorna:" -#define STR_ID "ID:" +#define STR_HDD "Merevlemezek:" +#define STR_NEW "&Új..." +#define STR_EXISTING "&Megnyitás..." +#define STR_REMOVE "&Eltávolítás" +#define STR_BUS "Busz:" +#define STR_CHANNEL "Csatorna:" +#define STR_ID "ID:" +#define STR_SPEED "Speed:" -#define STR_SPECIFY "&Kiválasztás..." -#define STR_SECTORS "Szektor:" -#define STR_HEADS "Fej:" -#define STR_CYLS "Cilinder:" -#define STR_SIZE_MB "Méret (MB):" -#define STR_TYPE "Típus:" -#define STR_IMG_FORMAT "Formátum:" -#define STR_BLOCK_SIZE "Blokkméret:" +#define STR_SPECIFY "&Kiválasztás..." +#define STR_SECTORS "Szektor:" +#define STR_HEADS "Fej:" +#define STR_CYLS "Cilinder:" +#define STR_SIZE_MB "Méret (MB):" +#define STR_TYPE "Típus:" +#define STR_IMG_FORMAT "Formátum:" +#define STR_BLOCK_SIZE "Blokkméret:" -#define STR_FLOPPY_DRIVES "Floppy-meghajtók:" -#define STR_TURBO "Turbó idÅ‘zítés" -#define STR_CHECKBPB "BPB ellenÅ‘rzés" -#define STR_CDROM_DRIVES "CD-ROM meghajtók:" -#define STR_CD_SPEED "Seb.:" +#define STR_FLOPPY_DRIVES "Floppy-meghajtók:" +#define STR_TURBO "Turbó idÅ‘zítés" +#define STR_CHECKBPB "BPB ellenÅ‘rzés" +#define STR_CDROM_DRIVES "CD-ROM meghajtók:" +#define STR_CD_SPEED "Seb.:" -#define STR_MO_DRIVES "MO-meghajtók:" -#define STR_ZIP_DRIVES "ZIP-meghajtók:" -#define STR_250 "ZIP 250" +#define STR_MO_DRIVES "MO-meghajtók:" +#define STR_ZIP_DRIVES "ZIP-meghajtók:" +#define STR_250 "ZIP 250" -#define STR_ISARTC "ISA RTC (óra):" -#define STR_ISAMEM "ISA memóriabÅ‘vítÅ‘k" -#define STR_ISAMEM_1 "Kártya 1:" -#define STR_ISAMEM_2 "Kártya 2:" -#define STR_ISAMEM_3 "Kártya 3:" -#define STR_ISAMEM_4 "Kártya 4:" -#define STR_BUGGER "ISABugger eszköz" -#define STR_POSTCARD "POST kártya" +#define STR_ISARTC "ISA RTC (óra):" +#define STR_ISAMEM "ISA memóriabÅ‘vítÅ‘k" +#define STR_ISAMEM_1 "Kártya 1:" +#define STR_ISAMEM_2 "Kártya 2:" +#define STR_ISAMEM_3 "Kártya 3:" +#define STR_ISAMEM_4 "Kártya 4:" +#define STR_BUGGER "ISABugger eszköz" +#define STR_POSTCARD "POST kártya" -#define FONT_SIZE 9 -#define FONT_NAME "Segoe UI" +#define FONT_SIZE 9 +#define FONT_NAME "Segoe UI" #include "dialogs.rc" @@ -371,193 +397,187 @@ END // String Table // -STRINGTABLE DISCARDABLE +STRINGTABLE DISCARDABLE BEGIN - 2048 "86Box" - IDS_2049 "Hiba" - IDS_2050 "Végzetes hiba" - IDS_2051 " - PAUSED" - IDS_2052 "Használja a Ctrl+Alt+PgDn gombokat az ablakhoz való visszatéréshez." - IDS_2053 "Sebesség" - IDS_2054 "ZIP %03i %i (%s): %ls" - IDS_2055 "ZIP-lemezképek (*.IM?;*.ZDI)\0*.IM?;*.ZDI\0" - IDS_2056 "A 86Box nem talált használható ROM-képeket\n\nKérem töltse le a ROM készletet és bontsa ki a ""roms"" könyvtárba." - IDS_2057 "(üres)" - IDS_2058 "ZIP-lemezképek (*.IM?;*.ZDI)\0*.IM?;*.ZDI\0Minden fájl (*.*)\0*.*\0" - IDS_2059 "Turbó" - IDS_2060 "Bekapcsolva" - IDS_2061 "Kikapcsolva" - IDS_2062 "Minden képfájl (*.86F;*.DSK;*.FLP;*.IM?;*.*FD?)\0*.86F;*.DSK;*.FLP;*.IM?;*.*FD?\0AlapvetÅ‘ szektor képfájlok (*.DSK;*.FLP;*.IM?;*.*FD?)\0*.DSK;*.FLP;*.IM?;*.IMG;*.*FD?\0Felületi képfájlok (*.86F)\0*.86F\0" - IDS_2063 "A számítógép ""%hs"" nem elérhetÅ‘ a ""roms/machines"" mappából hiányzó ROM-képek miatt. Ehelyett egy másik gép kerül futtatásra." + 2048 "86Box" + IDS_2049 "Hiba" + IDS_2050 "Végzetes hiba" + IDS_2051 " - PAUSED" + IDS_2052 "Használja a Ctrl+Alt+PgDn gombokat az ablakhoz való visszatéréshez." + IDS_2053 "Sebesség" + IDS_2054 "ZIP %03i %i (%s): %ls" + IDS_2055 "ZIP-lemezképek (*.IM?;*.ZDI)\0*.IM?;*.ZDI\0" + IDS_2056 "A 86Box nem talált használható ROM-képeket\n\nKérem töltse le a ROM készletet és bontsa ki a ""roms"" könyvtárba." + IDS_2057 "(üres)" + IDS_2058 "ZIP-lemezképek (*.IM?;*.ZDI)\0*.IM?;*.ZDI\0Minden fájl (*.*)\0*.*\0" + IDS_2059 "Turbó" + IDS_2060 "Bekapcsolva" + IDS_2061 "Kikapcsolva" + IDS_2062 "Minden képfájl (*.86F;*.DSK;*.FLP;*.IM?;*.*FD?)\0*.86F;*.DSK;*.FLP;*.IM?;*.*FD?\0AlapvetÅ‘ szektor képfájlok (*.DSK;*.FLP;*.IM?;*.*FD?)\0*.DSK;*.FLP;*.IM?;*.IMG;*.*FD?\0Felületi képfájlok (*.86F)\0*.86F\0" + IDS_2063 "A számítógép ""%hs"" nem elérhetÅ‘ a ""roms/machines"" mappából hiányzó ROM-képek miatt. Ehelyett egy másik gép kerül futtatásra." END -STRINGTABLE DISCARDABLE +STRINGTABLE DISCARDABLE BEGIN - IDS_2064 "A videokártya ""%hs"" nem elérhetÅ‘ a ""roms/video"" mappából hiányzó ROM-képek miatt. Ehelyett egy másik kártya kerül futtatásra." - IDS_2065 "Számítógép" - IDS_2066 "MegjelenítÅ‘" - IDS_2067 "Beviteli eszközök" - IDS_2068 "Hang" - IDS_2069 "Hálózat" - IDS_2070 "Portok (COM és LPT)" - IDS_2071 "TárolóvezérlÅ‘k" - IDS_2072 "Merevlemezek" - IDS_2073 "Floppy és CD-ROM meghajtók" - IDS_2074 "Egyéb cserélhetÅ‘ tárolók" - IDS_2075 "Egyéb perifériák" - IDS_2076 "Felületi képfájlok (*.86F)\0*.86F\0" - IDS_2077 "Kattintson az egér elfogásához" - IDS_2078 "Nyomja meg az F8+F12-t az egér elengédéséhez" - IDS_2079 "Nyomja meg az F8+F12-t vagy a középsÅ‘ gombot az egér elengédéséhez" + IDS_2064 "A videokártya ""%hs"" nem elérhetÅ‘ a ""roms/video"" mappából hiányzó ROM-képek miatt. Ehelyett egy másik kártya kerül futtatásra." + IDS_2065 "Számítógép" + IDS_2066 "MegjelenítÅ‘" + IDS_2067 "Beviteli eszközök" + IDS_2068 "Hang" + IDS_2069 "Hálózat" + IDS_2070 "Portok (COM és LPT)" + IDS_2071 "TárolóvezérlÅ‘k" + IDS_2072 "Merevlemezek" + IDS_2073 "Floppy és CD-ROM meghajtók" + IDS_2074 "Egyéb cserélhetÅ‘ tárolók" + IDS_2075 "Egyéb perifériák" + IDS_2076 "Felületi képfájlok (*.86F)\0*.86F\0" + IDS_2077 "Kattintson az egér elfogásához" + IDS_2078 "Nyomja meg az F8+F12-t az egér elengédéséhez" + IDS_2079 "Nyomja meg az F8+F12-t vagy a középsÅ‘ gombot az egér elengédéséhez" END -STRINGTABLE DISCARDABLE +STRINGTABLE DISCARDABLE BEGIN - IDS_2080 "Nem sikerült a FluidSynth inicializálása" - IDS_2081 "Busz" - IDS_2082 "Fájl" - IDS_2083 "C" - IDS_2084 "H" - IDS_2085 "S" - IDS_2086 "MB" - IDS_2087 "BPB ellenÅ‘rzése" - IDS_2088 "KB" - IDS_2089 "Nem sikerült inicializálni a videó megjelenítÅ‘t." - IDS_2090 "Alapértelmezett" - IDS_2091 "%i várakozási ciklus(ok)" - IDS_2092 "Típus" - IDS_2093 "Nem sikerült a PCap beállítása" - IDS_2094 "Nem találhatóak PCap eszközök" - IDS_2095 "Érvénytelen PCap eszköz" - IDS_2096 "Szabványos 2-gombos játékvezérlÅ‘(k)" - IDS_2097 "Szabványos 4-gombos játékvezérlÅ‘" - IDS_2098 "Szabványos 6-gombos játékvezérlÅ‘" - IDS_2099 "Szabványos 8-gombos játékvezérlÅ‘" - IDS_2100 "CH Flightstick Pro" - IDS_2101 "Microsoft SideWinder Pad" - IDS_2102 "Thrustmaster Flight Control System" - IDS_2103 "Nincs" - IDS_2104 "Nem lehet betölteni a billentyűzetgyorsítókat." - IDS_2105 "A közvetlen nyers bevitel regisztrálása nem sikerült." - IDS_2106 "%u" - IDS_2107 "%u MB (CHS: %i, %i, %i)" - IDS_2108 "Floppy %i (%s): %ls" - IDS_2109 "Minden képfájl (*.0??;*.1??;*.??0;*.86F;*.BIN;*.CQ?;*.D??;*.FLP;*.HDM;*.IM?;*.JSON;*.TD0;*.*FD?;*.MFM;*.XDF)\0*.0??;*.1??;*.??0;*.86F;*.BIN;*.CQ?;*.D??;*.FLP;*.HDM;*.IM?;*.JSON;*.TD0;*.*FD?;*.MFM;*.XDF\0Továbbfejlesztett szektor képek (*.IMD;*.JSON;*.TD0)\0*.IMD;*.JSON;*.TD0\0AlapvetÅ‘ szektor képek (*.0??;*.1??;*.??0;*.BIN;*.CQ?;*.D??;*.FLP;*.HDM;*.IM?;*.XDF;*.*FD?)\0*.0??;*.1??;*.??0;*.BIN;*.CQ?;*.D??;*.FLP;*.HDM;*.IM?;*.XDF;*.*FD?\0Flux képekfájlok (*.FDI)\0*.FDI\0Felületi képfájlok (*.86F;*.MFM)\0*.86F;*.MFM\0Minden fájl (*.*)\0*.*\0" - IDS_2110 "A FreeType inicializálása nem lehetséges" - IDS_2111 "Az SDL inicializálása nem lehetséges, az SDL2.dll fájl szükséges" - IDS_2112 "Biztosan szeretné újraindítani az emulált gépet?" - IDS_2113 "Biztos benne, hogy ki szeretne lépni a 86Box-ból?" - IDS_2114 "Nem sikerült inicializálni a Ghostscript-et" - IDS_2115 "MO %i (%ls): %ls" - IDS_2116 "MO-képfájlok (*.IM?;*.MDI)\0*.IM?;*.MDI\0Minden fájl (*.*)\0*.*\0" - IDS_2117 "Üdvözli önt az 86Box!" - IDS_2118 "Integrált vezérlÅ‘" - IDS_2119 "Kilépés" - IDS_2120 "Nem találhatóak meg a ROM-képek" - IDS_2121 "Szeretné menteni a beállításokat?" - IDS_2122 "Ezzel hardveresen újraindítja az emulált gépet." - IDS_2123 "Mentés" - IDS_2124 "A 86Box névjegye" - IDS_2125 "86Box v" EMU_VERSION - IDS_2126 "Régi számítógépek emulátora\n\nFejlesztÅ‘k: Sarah Walker, Miran Grca, Fred N. van Kempen (waltje), SA1988, Tiseno100, reenigne, leilei, JohnElliott, greatpsycho, and others.\n\nFordította: Laci bá'\n\nMegjelent a GNU General Public License v2 vagy újabb alatt. További információért lásd a LICENSE fájlt." - IDS_2127 "OK" - IDS_2128 "Hardver nem elérhetÅ‘" + IDS_2081 "Busz" + IDS_2082 "Fájl" + IDS_2083 "C" + IDS_2084 "H" + IDS_2085 "S" + IDS_2086 "MB" + IDS_2087 "Speed" + IDS_2088 "BPB ellenÅ‘rzése" + IDS_2089 "KB" + IDS_2090 "Nem sikerült inicializálni a videó megjelenítÅ‘t." + IDS_2091 "Alapértelmezett" + IDS_2092 "%i várakozási ciklus(ok)" + IDS_2093 "Típus" + IDS_2094 "Nem sikerült a PCap beállítása" + IDS_2095 "Nem találhatóak PCap eszközök" + IDS_2096 "Érvénytelen PCap eszköz" + IDS_2097 "Szabványos 2-gombos játékvezérlÅ‘(k)" + IDS_2098 "Szabványos 4-gombos játékvezérlÅ‘" + IDS_2099 "Szabványos 6-gombos játékvezérlÅ‘" + IDS_2100 "Szabványos 8-gombos játékvezérlÅ‘" + IDS_2101 "CH Flightstick Pro" + IDS_2102 "Microsoft SideWinder Pad" + IDS_2103 "Thrustmaster Flight Control System" + IDS_2104 "Nincs" + IDS_2105 "Nem lehet betölteni a billentyűzetgyorsítókat." + IDS_2106 "A közvetlen nyers bevitel regisztrálása nem sikerült." + IDS_2107 "%u" + IDS_2108 "%u MB (CHS: %i, %i, %i)" + IDS_2109 "Floppy %i (%s): %ls" + IDS_2110 "Minden képfájl (*.0??;*.1??;*.??0;*.86F;*.BIN;*.CQ?;*.D??;*.FLP;*.HDM;*.IM?;*.JSON;*.TD0;*.*FD?;*.MFM;*.XDF)\0*.0??;*.1??;*.??0;*.86F;*.BIN;*.CQ?;*.D??;*.FLP;*.HDM;*.IM?;*.JSON;*.TD0;*.*FD?;*.MFM;*.XDF\0Továbbfejlesztett szektor képek (*.IMD;*.JSON;*.TD0)\0*.IMD;*.JSON;*.TD0\0AlapvetÅ‘ szektor képek (*.0??;*.1??;*.??0;*.BIN;*.CQ?;*.D??;*.FLP;*.HDM;*.IM?;*.XDF;*.*FD?)\0*.0??;*.1??;*.??0;*.BIN;*.CQ?;*.D??;*.FLP;*.HDM;*.IM?;*.XDF;*.*FD?\0Flux képekfájlok (*.FDI)\0*.FDI\0Felületi képfájlok (*.86F;*.MFM)\0*.86F;*.MFM\0Minden fájl (*.*)\0*.*\0" + IDS_2112 "Az SDL inicializálása nem lehetséges, az SDL2.dll fájl szükséges" + IDS_2113 "Biztosan szeretné újraindítani az emulált gépet?" + IDS_2114 "Biztos benne, hogy ki szeretne lépni a 86Box-ból?" + IDS_2115 "Nem sikerült inicializálni a Ghostscript-et" + IDS_2116 "MO %i (%ls): %ls" + IDS_2117 "MO-képfájlok (*.IM?;*.MDI)\0*.IM?;*.MDI\0Minden fájl (*.*)\0*.*\0" + IDS_2118 "Üdvözli önt az 86Box!" + IDS_2119 "Integrált vezérlÅ‘" + IDS_2120 "Kilépés" + IDS_2121 "Nem találhatóak meg a ROM-képek" + IDS_2122 "Szeretné menteni a beállításokat?" + IDS_2123 "Ezzel hardveresen újraindítja az emulált gépet." + IDS_2124 "Mentés" + IDS_2125 "A 86Box névjegye" + IDS_2126 "86Box v" EMU_VERSION + IDS_2127 "Régi számítógépek emulátora\n\nFejlesztÅ‘k: Miran GrÄa (OBattler), RichardG867, Jasmine Iwanek, TC1995, coldbrewed, Teemu Korhonen (Manaatti), Joakim L. Gilje, Adrien Moulin (elyosh), Daniel Balsom (gloriouscow), Cacodemon345, Fred N. van Kempen (waltje), Tiseno100, reenigne, and others.\n\nWith previous core contributions from Sarah Walker, leilei, JohnElliott, greatpsycho, and others.\n\nFordította: Laci bá'\n\nMegjelent a GNU General Public License v2 vagy újabb alatt. További információért lásd a LICENSE fájlt." + IDS_2128 "OK" + IDS_2129 "Hardver nem elérhetÅ‘" #ifdef _WIN32 #define LIB_NAME_PCAP "WinPcap" #else #define LIB_NAME_PCAP "libpcap" #endif - IDS_2129 "GyÅ‘zÅ‘djön meg hogy a(z) " LIB_NAME_PCAP " telepítve van és jelenleg a " LIB_NAME_PCAP "-kompatibilis kapcsolatot használja." - IDS_2130 "Érvénytelen konfiguráció" -#ifdef _WIN32 -#define LIB_NAME_FREETYPE "freetype.dll" -#else -#define LIB_NAME_FREETYPE "libfreetype" -#endif - IDS_2131 LIB_NAME_FREETYPE " szükséges az ESC/P nyomtató emulációhoz." + IDS_2130 "GyÅ‘zÅ‘djön meg hogy a(z) " LIB_NAME_PCAP " telepítve van és jelenleg a " LIB_NAME_PCAP "-kompatibilis kapcsolatot használja." + IDS_2131 "Érvénytelen konfiguráció" #ifdef _WIN32 #define LIB_NAME_GS "gsdll32.dll" #else #define LIB_NAME_GS "libgs" #endif - IDS_2132 LIB_NAME_GS " szükséges a PostScript fájlok PDF formátumba való automatikus konvertálásához.\n\nAz általános PostScript nyomtatóra küldött dokumentumok PostScript (.ps) fájlként kerülnek mentésre." -#ifdef _WIN32 -#define LIB_NAME_FLUIDSYNTH "libfluidsynth.dll" -#else -#define LIB_NAME_FLUIDSYNTH "libfluidsynth" -#endif - IDS_2133 LIB_NAME_FLUIDSYNTH " szükséges a FluidSynth MIDI kimenethez." - IDS_2134 "Teljes képernyÅ‘s módra váltás" - IDS_2135 "Ne jelenítse meg újra ezt az üzenetet " - IDS_2136 "Ne lépjen ki" - IDS_2137 "Újraindítás" - IDS_2138 "Ne indítsa újra" - IDS_2139 "MO-képfájlok (*.IM?;*.MDI)\0*.IM?;*.MDI\0Minden fájl (*.*)\0*.*\0" - IDS_2140 "CD-ROM-képek (*.ISO;*.CUE)\0*.ISO;*.CUE\0Minden fájl (*.*)\0*.*\0" - IDS_2141 "%hs eszközkonfiguráció" - IDS_2142 "KépernyÅ‘ alvó módban" - IDS_2143 "OpenGL Shaderek (*.GLSL)\0*.GLSL\0Minden fájl (*.*)\0*.*\0" - IDS_2144 "OpenGL beállítások" - IDS_2145 "Egy nem támogatott konfigurációt tölt be" - IDS_2146 "A kiválasztott gépen alapuló CPU-típusszűrés le van tiltva ezen az emulált gépen.\n\nEz lehetÅ‘vé teszi olyan CPU kiválasztását, amely egyébként nem kompatibilis a kiválasztott géppel. ElÅ‘fordulhat azonban, hogy nem kompatibilis a gép BIOS-ával vagy más szoftverekkel.\n\nA beállítás engedélyezése hivatalosan nem támogatott, és a benyújtott hibajelentéseket érvénytelenként lezárhatjuk." - IDS_2147 "Folytatás" - IDS_2148 "Magnókazetta: %s" - IDS_2149 "Magnókazetta-képek (*.PCM;*.RAW;*.WAV;*.CAS)\0*.PCM;*.RAW;*.WAV;*.CAS\0Minden fájl (*.*)\0*.*\0" - IDS_2150 "ROM-kazetta %i: %ls" - IDS_2151 "ROM-kazetta képek (*.A;*.B;*.JRC)\0*.A;*.B;*.JRC\0Minden fájl (*.*)\0*.*\0" - IDS_2152 "Hiba történt a renderelÅ‘ inicializálásakor" - IDS_2153 "Az OpenGL (3.0 Core) megjelenítÅ‘-motort nem sikerült inicializálni. Kérem használjon másik renderelÅ‘t." - IDS_2154 "Resume execution" - IDS_2155 "Pause execution" - IDS_2156 "Press Ctrl+Alt+Del" - IDS_2157 "Press Ctrl+Alt+Esc" - IDS_2158 "Hard reset" - IDS_2159 "ACPI shutdown" - IDS_2160 "Settings" + IDS_2133 LIB_NAME_GS " szükséges a PostScript fájlok PDF formátumba való automatikus konvertálásához.\n\nAz általános PostScript nyomtatóra küldött dokumentumok PostScript (.ps) fájlként kerülnek mentésre." + IDS_2135 "Teljes képernyÅ‘s módra váltás" + IDS_2136 "Ne jelenítse meg újra ezt az üzenetet " + IDS_2137 "Ne lépjen ki" + IDS_2138 "Újraindítás" + IDS_2139 "Ne indítsa újra" + IDS_2140 "MO-képfájlok (*.IM?;*.MDI)\0*.IM?;*.MDI\0Minden fájl (*.*)\0*.*\0" + IDS_2141 "CD-ROM-képek (*.ISO;*.CUE)\0*.ISO;*.CUE\0Minden fájl (*.*)\0*.*\0" + IDS_2142 "%hs eszközkonfiguráció" + IDS_2143 "KépernyÅ‘ alvó módban" + IDS_2144 "OpenGL Shaderek (*.GLSL)\0*.GLSL\0Minden fájl (*.*)\0*.*\0" + IDS_2145 "OpenGL beállítások" + IDS_2146 "Egy nem támogatott konfigurációt tölt be" + IDS_2147 "A kiválasztott gépen alapuló CPU-típusszűrés le van tiltva ezen az emulált gépen.\n\nEz lehetÅ‘vé teszi olyan CPU kiválasztását, amely egyébként nem kompatibilis a kiválasztott géppel. ElÅ‘fordulhat azonban, hogy nem kompatibilis a gép BIOS-ával vagy más szoftverekkel.\n\nA beállítás engedélyezése hivatalosan nem támogatott, és a benyújtott hibajelentéseket érvénytelenként lezárhatjuk." + IDS_2148 "Folytatás" + IDS_2149 "Magnókazetta: %s" + IDS_2150 "Magnókazetta-képek (*.PCM;*.RAW;*.WAV;*.CAS)\0*.PCM;*.RAW;*.WAV;*.CAS\0Minden fájl (*.*)\0*.*\0" + IDS_2151 "ROM-kazetta %i: %ls" + IDS_2152 "ROM-kazetta képek (*.A;*.B;*.JRC)\0*.A;*.B;*.JRC\0Minden fájl (*.*)\0*.*\0" + IDS_2153 "Hiba történt a renderelÅ‘ inicializálásakor" + IDS_2154 "Az OpenGL (3.0 Core) megjelenítÅ‘-motort nem sikerült inicializálni. Kérem használjon másik renderelÅ‘t." + IDS_2155 "Resume execution" + IDS_2156 "Pause execution" + IDS_2157 "Press Ctrl+Alt+Del" + IDS_2158 "Press Ctrl+Alt+Esc" + IDS_2159 "Hard reset" + IDS_2160 "ACPI shutdown" + IDS_2161 "Settings" + IDS_2162 "Type" + IDS_2163 "No Dynarec" + IDS_2164 "Old Dynarec" + IDS_2165 "New Dynarec" + IDS_2166 "Video card #2 ""%hs"" is not available due to missing ROMs in the roms/video directory. Disabling the second video card." + IDS_2167 "Failed to initialize network driver" + IDS_2168 "The network configuration will be switched to the null driver" END -STRINGTABLE DISCARDABLE +STRINGTABLE DISCARDABLE BEGIN IDS_4096 "Merevlemez (%s)" - IDS_4097 "%01i:%01i" - IDS_4098 "%01i" - IDS_4099 "MFM/RLL vagy ESDI CD-ROM meghajtók soha nem léteztek" - IDS_4100 "Egyéni..." - IDS_4101 "Egyéni (nagy)..." - IDS_4102 "Új merevlemez hozzáadása" - IDS_4103 "MeglévÅ‘ merevlemez hozzáadása" - IDS_4104 "A HDI lemezképek nem lehetnek nagyobbak 4 GB-nál." - IDS_4105 "A lemezképek mérete nem haladhatja meg a 127 GB-ot." - IDS_4106 "Merevlemez-képfájlok (*.HD?;*.IM?;*.VHD)\0*.HD?;*.IM?;*.VHD\0Minden fájl (*.*)\0*.*\0" - IDS_4107 "A fájl nem olvasható" - IDS_4108 "A fájl nem írható" - IDS_4109 "Az 512-tÅ‘l eltérÅ‘ szektorméretű HDI vagy HDX képek nem támogatottak." - IDS_4110 "Az USB még nem támogatott" - IDS_4111 "A lemezképfájl már létezik" - IDS_4112 "Adjon meg egy érvényes fájlnevet." - IDS_4113 "A lemezképfájl létrehozásra került" - IDS_4114 "GyÅ‘zÅ‘djön meg arról, hogy a fájl létezik és olvasható." - IDS_4115 "GyÅ‘zÅ‘djön meg arról, hogy a fájlt egy írható könyvtárba menti." - IDS_4116 "A lemezképfájl túl nagy" - IDS_4117 "Ne felejtse el particionálni és formázni az újonnan létrehozott meghajtót." - IDS_4118 "A kiválasztott fájl felülírásra kerül. Biztos, hogy ezt kívánja használni?" - IDS_4119 "Nem támogatott lemezkép" - IDS_4120 "Felülírás" - IDS_4121 "Ne írja felül" - IDS_4122 "Nyers lemezkép (.img)" - IDS_4123 "HDI-lemezkép (.hdi)" - IDS_4124 "HDX-lemezkép (.hdx)" - IDS_4125 "Rögzített méretű VHD (.vhd)" - IDS_4126 "Dinamikusan bÅ‘vülÅ‘ VHD (.vhd)" - IDS_4127 "Különbség-VHD (.vhd)" - IDS_4128 "Nagy blokkméret (2 MB)" - IDS_4129 "Kis blokkméret (512 KB)" - IDS_4130 "VHD fájlok (*.VHD)\0*.VHD\0Minden fájl (*.*)\0*.*\0" - IDS_4131 "Válassza ki a szülÅ‘ VHD-t" - IDS_4132 "Ez azt jelentheti, hogy a szülÅ‘kép módosult az eltérÅ‘ kép létrehozása után.\n\nEz akkor is elÅ‘fordulhat, ha a képfájlokat áthelyezték vagy másolták, vagy a lemezt létrehozó program hibája miatt.\n\nSzeretné kijavítani az idÅ‘bélyegeket?" - IDS_4133 "A szülÅ‘- és a gyermeklemez idÅ‘bélyegei nem egyeznek" - IDS_4134 "Nem sikerült kijavítani a VHD idÅ‘bélyegét." - IDS_4135 "%01i:%02i" + IDS_4097 "%01i:%01i" + IDS_4098 "%01i" + IDS_4099 "MFM/RLL vagy ESDI CD-ROM meghajtók soha nem léteztek" + IDS_4100 "Egyéni..." + IDS_4101 "Egyéni (nagy)..." + IDS_4102 "Új merevlemez hozzáadása" + IDS_4103 "MeglévÅ‘ merevlemez hozzáadása" + IDS_4104 "A HDI lemezképek nem lehetnek nagyobbak 4 GB-nál." + IDS_4105 "A lemezképek mérete nem haladhatja meg a 127 GB-ot." + IDS_4106 "Merevlemez-képfájlok (*.HD?;*.IM?;*.VHD)\0*.HD?;*.IM?;*.VHD\0Minden fájl (*.*)\0*.*\0" + IDS_4107 "A fájl nem olvasható" + IDS_4108 "A fájl nem írható" + IDS_4109 "Az 512-tÅ‘l eltérÅ‘ szektorméretű HDI vagy HDX képek nem támogatottak." + IDS_4110 "Az USB még nem támogatott" + IDS_4111 "A lemezképfájl már létezik" + IDS_4112 "Adjon meg egy érvényes fájlnevet." + IDS_4113 "A lemezképfájl létrehozásra került" + IDS_4114 "GyÅ‘zÅ‘djön meg arról, hogy a fájl létezik és olvasható." + IDS_4115 "GyÅ‘zÅ‘djön meg arról, hogy a fájlt egy írható könyvtárba menti." + IDS_4116 "A lemezképfájl túl nagy" + IDS_4117 "Ne felejtse el particionálni és formázni az újonnan létrehozott meghajtót." + IDS_4118 "A kiválasztott fájl felülírásra kerül. Biztos, hogy ezt kívánja használni?" + IDS_4119 "Nem támogatott lemezkép" + IDS_4120 "Felülírás" + IDS_4121 "Ne írja felül" + IDS_4122 "Nyers lemezkép (.img)" + IDS_4123 "HDI-lemezkép (.hdi)" + IDS_4124 "HDX-lemezkép (.hdx)" + IDS_4125 "Rögzített méretű VHD (.vhd)" + IDS_4126 "Dinamikusan bÅ‘vülÅ‘ VHD (.vhd)" + IDS_4127 "Különbség-VHD (.vhd)" + IDS_4128 "Nagy blokkméret (2 MB)" + IDS_4129 "Kis blokkméret (512 KB)" + IDS_4130 "VHD fájlok (*.VHD)\0*.VHD\0Minden fájl (*.*)\0*.*\0" + IDS_4131 "Válassza ki a szülÅ‘ VHD-t" + IDS_4132 "Ez azt jelentheti, hogy a szülÅ‘kép módosult az eltérÅ‘ kép létrehozása után.\n\nEz akkor is elÅ‘fordulhat, ha a képfájlokat áthelyezték vagy másolták, vagy a lemezt létrehozó program hibája miatt.\n\nSzeretné kijavítani az idÅ‘bélyegeket?" + IDS_4133 "A szülÅ‘- és a gyermeklemez idÅ‘bélyegei nem egyeznek" + IDS_4134 "Nem sikerült kijavítani a VHD idÅ‘bélyegét." + IDS_4135 "%01i:%02i" IDS_4352 "MFM/RLL" IDS_4353 "XTA" @@ -566,56 +586,56 @@ BEGIN IDS_4356 "ATAPI" IDS_4357 "SCSI" - IDS_4608 "MFM/RLL (%01i:%01i)" - IDS_4609 "XTA (%01i:%01i)" - IDS_4610 "ESDI (%01i:%01i)" - IDS_4611 "IDE (%01i:%01i)" - IDS_4612 "ATAPI (%01i:%01i)" - IDS_4613 "SCSI (%01i:%02i)" + IDS_4608 "MFM/RLL (%01i:%01i)" + IDS_4609 "XTA (%01i:%01i)" + IDS_4610 "ESDI (%01i:%01i)" + IDS_4611 "IDE (%01i:%01i)" + IDS_4612 "ATAPI (%01i:%01i)" + IDS_4613 "SCSI (%01i:%02i)" - IDS_5120 "CD-ROM %i (%s): %s" + IDS_5120 "CD-ROM %i (%s): %s" - IDS_5376 "Letiltva" - IDS_5381 "ATAPI" + IDS_5376 "Letiltva" + IDS_5381 "ATAPI" IDS_5382 "SCSI" - IDS_5632 "Letiltva" - IDS_5637 "ATAPI (%01i:%01i)" + IDS_5632 "Letiltva" + IDS_5637 "ATAPI (%01i:%01i)" IDS_5638 "SCSI (%01i:%02i)" - IDS_5888 "160 kB" - IDS_5889 "180 kB" - IDS_5890 "320 kB" - IDS_5891 "360 kB" - IDS_5892 "640 kB" - IDS_5893 "720 kB" - IDS_5894 "1.2 MB" - IDS_5895 "1.25 MB" - IDS_5896 "1.44 MB" - IDS_5897 "DMF (1024 klaszter)" - IDS_5898 "DMF (2048 klaszter)" - IDS_5899 "2.88 MB" - IDS_5900 "ZIP 100" - IDS_5901 "ZIP 250" - IDS_5902 "3.5"" 128 MB (ISO 10090)" - IDS_5903 "3.5"" 230 MB (ISO 13963)" - IDS_5904 "3.5"" 540 MB (ISO 15498)" - IDS_5905 "3.5"" 640 MB (ISO 15498)" - IDS_5906 "3.5"" 1.3 GB (GigaMO)" - IDS_5907 "3.5"" 2.3 GB (GigaMO 2)" - IDS_5908 "5.25"" 600 MB" - IDS_5909 "5.25"" 650 MB" - IDS_5910 "5.25"" 1 GB" - IDS_5911 "5.25"" 1.3 GB" + IDS_5888 "160 kB" + IDS_5889 "180 kB" + IDS_5890 "320 kB" + IDS_5891 "360 kB" + IDS_5892 "640 kB" + IDS_5893 "720 kB" + IDS_5894 "1.2 MB" + IDS_5895 "1.25 MB" + IDS_5896 "1.44 MB" + IDS_5897 "DMF (1024 klaszter)" + IDS_5898 "DMF (2048 klaszter)" + IDS_5899 "2.88 MB" + IDS_5900 "ZIP 100" + IDS_5901 "ZIP 250" + IDS_5902 "3.5"" 128 MB (ISO 10090)" + IDS_5903 "3.5"" 230 MB (ISO 13963)" + IDS_5904 "3.5"" 540 MB (ISO 15498)" + IDS_5905 "3.5"" 640 MB (ISO 15498)" + IDS_5906 "3.5"" 1.3 GB (GigaMO)" + IDS_5907 "3.5"" 2.3 GB (GigaMO 2)" + IDS_5908 "5.25"" 600 MB" + IDS_5909 "5.25"" 650 MB" + IDS_5910 "5.25"" 1 GB" + IDS_5911 "5.25"" 1.3 GB" - IDS_6144 "Tökéletes RPM" - IDS_6145 "1%-kal a tökéletes RPM alatt" - IDS_6146 "1.5%-kal a tökéletes RPM alatt" - IDS_6147 "2%-kal a tökéletes RPM alatt" + IDS_6144 "Tökéletes RPM" + IDS_6145 "1%-kal a tökéletes RPM alatt" + IDS_6146 "1.5%-kal a tökéletes RPM alatt" + IDS_6147 "2%-kal a tökéletes RPM alatt" - IDS_7168 "(A rendszer nyelve)" + IDS_7168 "(A rendszer nyelve)" END -#define IDS_LANG_ENUS IDS_7168 +#define IDS_LANG_ENUS IDS_7168 // Hungarian resources ///////////////////////////////////////////////////////////////////////////// diff --git a/src/win/languages/it-IT.rc b/src/win/languages/it-IT.rc index 9e31ffabd..cb6e7afa1 100644 --- a/src/win/languages/it-IT.rc +++ b/src/win/languages/it-IT.rc @@ -14,113 +14,122 @@ LANGUAGE LANG_ITALIAN, SUBLANG_ITALIAN // Menu // -MainMenu MENU DISCARDABLE +MainMenu MENU DISCARDABLE BEGIN POPUP "&Azione" BEGIN - MENUITEM "&Tastiera richiede la cattura", IDM_ACTION_KBD_REQ_CAPTURE - MENUITEM "&CTRL destro è ALT sinistro", IDM_ACTION_RCTRL_IS_LALT + MENUITEM "&Tastiera richiede la cattura", IDM_ACTION_KBD_REQ_CAPTURE + MENUITEM "&CTRL destro è ALT sinistro", IDM_ACTION_RCTRL_IS_LALT MENUITEM SEPARATOR - MENUITEM "&Riavvia...", IDM_ACTION_HRESET - MENUITEM "&Ctrl+Alt+Del\tCtrl+F12", IDM_ACTION_RESET_CAD + MENUITEM "&Riavvia...", IDM_ACTION_HRESET + MENUITEM "&Ctrl+Alt+Del\tCtrl+F12", IDM_ACTION_RESET_CAD MENUITEM SEPARATOR - MENUITEM "Ctrl+Alt+&Esc", IDM_ACTION_CTRL_ALT_ESC + MENUITEM "Ctrl+Alt+&Esc", IDM_ACTION_CTRL_ALT_ESC MENUITEM SEPARATOR - MENUITEM "&Pausa", IDM_ACTION_PAUSE + MENUITEM "&Pausa", IDM_ACTION_PAUSE MENUITEM SEPARATOR - MENUITEM "E&sci...", IDM_ACTION_EXIT + MENUITEM "E&sci...", IDM_ACTION_EXIT END POPUP "&Visualizza" BEGIN - MENUITEM "&Nascondi barra di stato", IDM_VID_HIDE_STATUS_BAR - MENUITEM "Hide &toolbar", IDM_VID_HIDE_TOOLBAR + MENUITEM "&Nascondi barra di stato", IDM_VID_HIDE_STATUS_BAR + MENUITEM "Hide &toolbar", IDM_VID_HIDE_TOOLBAR MENUITEM SEPARATOR - MENUITEM "&Finestra ridimensionabile", IDM_VID_RESIZE - MENUITEM "R&icorda dimensioni e posizione", IDM_VID_REMEMBER + MENUITEM "&Show non-primary monitors", IDM_VID_MONITORS + MENUITEM "&Finestra ridimensionabile", IDM_VID_RESIZE + MENUITEM "R&icorda dimensioni e posizione", IDM_VID_REMEMBER MENUITEM SEPARATOR POPUP "Re&nderer" BEGIN - MENUITEM "&SDL (Software)", IDM_VID_SDL_SW - MENUITEM "SDL (&Hardware)", IDM_VID_SDL_HW - MENUITEM "SDL (&OpenGL)", IDM_VID_SDL_OPENGL - MENUITEM "Open&GL (3.0 Core)", IDM_VID_OPENGL_CORE + MENUITEM "&SDL (Software)", IDM_VID_SDL_SW + MENUITEM "SDL (&Hardware)", IDM_VID_SDL_HW + MENUITEM "SDL (&OpenGL)", IDM_VID_SDL_OPENGL + MENUITEM "Open&GL (3.0 Core)", IDM_VID_OPENGL_CORE #ifdef USE_VNC - MENUITEM "&VNC", IDM_VID_VNC + MENUITEM "&VNC", IDM_VID_VNC #endif END MENUITEM SEPARATOR - MENUITEM "Specifica dimensioni...", IDM_VID_SPECIFY_DIM - MENUITEM "F&orza display 4:3", IDM_VID_FORCE43 + MENUITEM "Specifica dimensioni...", IDM_VID_SPECIFY_DIM + MENUITEM "F&orza display 4:3", IDM_VID_FORCE43 POPUP "&Fattore scalare della finestra" BEGIN - MENUITEM "&0.5x", IDM_VID_SCALE_1X - MENUITEM "&1x", IDM_VID_SCALE_2X - MENUITEM "1.&5x", IDM_VID_SCALE_3X - MENUITEM "&2x", IDM_VID_SCALE_4X + MENUITEM "&0.5x", IDM_VID_SCALE_1X + MENUITEM "&1x", IDM_VID_SCALE_2X + MENUITEM "1.&5x", IDM_VID_SCALE_3X + MENUITEM "&2x", IDM_VID_SCALE_4X + MENUITEM "&3x", IDM_VID_SCALE_5X + MENUITEM "&4x", IDM_VID_SCALE_6X + MENUITEM "&5x", IDM_VID_SCALE_7X + MENUITEM "&6x", IDM_VID_SCALE_8X + MENUITEM "&7x", IDM_VID_SCALE_9X + MENUITEM "&8x", IDM_VID_SCALE_10X END POPUP "Metodo filtro" BEGIN - MENUITEM "&Dal più vicino", IDM_VID_FILTER_NEAREST - MENUITEM "&Lineare", IDM_VID_FILTER_LINEAR + MENUITEM "&Dal più vicino", IDM_VID_FILTER_NEAREST + MENUITEM "&Lineare", IDM_VID_FILTER_LINEAR END - MENUITEM "Scala Hi&DPI", IDM_VID_HIDPI + MENUITEM "Scala Hi&DPI", IDM_VID_HIDPI MENUITEM SEPARATOR - MENUITEM "&Schermo intero\tCtrl+Alt+PgUp", IDM_VID_FULLSCREEN + MENUITEM "&Schermo intero\tCtrl+Alt+PgUp", IDM_VID_FULLSCREEN POPUP "Modalità adattamento &schermo intero" BEGIN - MENUITEM "&Adatta a schermo intero", IDM_VID_FS_FULL - MENUITEM "&4:3", IDM_VID_FS_43 + MENUITEM "&Adatta a schermo intero", IDM_VID_FS_FULL + MENUITEM "&4:3", IDM_VID_FS_43 MENUITEM "&Pixel quadrati (mantiene l'aspetto)", IDM_VID_FS_KEEPRATIO - MENUITEM "&Scala intera", IDM_VID_FS_INT + MENUITEM "&Scala intera", IDM_VID_FS_INT END POPUP "Impostazioni E&GA/(S)VGA" BEGIN - MENUITEM "&Invertire monitor VGA", IDM_VID_INVERT + MENUITEM "&Invertire monitor VGA", IDM_VID_INVERT POPUP "Schermi VGA &" BEGIN - MENUITEM "RGB &Color", IDM_VID_GRAY_RGB - MENUITEM "&RGB Monocroma", IDM_VID_GRAY_MONO - MENUITEM "&Monitor ambra", IDM_VID_GRAY_AMBER - MENUITEM "&Monitor verde", IDM_VID_GRAY_GREEN - MENUITEM "&Monitor bianco", IDM_VID_GRAY_WHITE + MENUITEM "RGB &Color", IDM_VID_GRAY_RGB + MENUITEM "&RGB Monocroma", IDM_VID_GRAY_MONO + MENUITEM "&Monitor ambra", IDM_VID_GRAY_AMBER + MENUITEM "&Monitor verde", IDM_VID_GRAY_GREEN + MENUITEM "&Monitor bianco", IDM_VID_GRAY_WHITE END POPUP "Conversione &scala grigia" BEGIN - MENUITEM "BT&601 (NTSC/PAL)", IDM_VID_GRAYCT_601 - MENUITEM "BT&709 (HDTV)", IDM_VID_GRAYCT_709 - MENUITEM "&AMedia", IDM_VID_GRAYCT_AVE + MENUITEM "BT&601 (NTSC/PAL)", IDM_VID_GRAYCT_601 + MENUITEM "BT&709 (HDTV)", IDM_VID_GRAYCT_709 + MENUITEM "&AMedia", IDM_VID_GRAYCT_AVE END END MENUITEM SEPARATOR - MENUITEM "Sovrascansione CGA/PCjr/Tandy/E&GA/(S)VGA", IDM_VID_OVERSCAN + MENUITEM "Sovrascansione CGA/PCjr/Tandy/E&GA/(S)VGA", IDM_VID_OVERSCAN MENUITEM "Cambia il contrasto per &display monocromatici", IDM_VID_CGACON END - MENUITEM "&Dispositivi", IDM_MEDIA + MENUITEM "&Dispositivi", IDM_MEDIA POPUP "&Strumenti" BEGIN - MENUITEM "&Impostazioni...", IDM_CONFIG - MENUITEM "&Aggiorna icone della barra di stato", IDM_UPDATE_ICONS + MENUITEM "&Impostazioni...", IDM_CONFIG + MENUITEM "&Aggiorna icone della barra di stato", IDM_UPDATE_ICONS MENUITEM SEPARATOR - MENUITEM "Cattura schermata\tCtrl+F11", IDM_ACTION_SCREENSHOT + MENUITEM "Cattura schermata\tCtrl+F11", IDM_ACTION_SCREENSHOT MENUITEM SEPARATOR - MENUITEM "&Preferenze...", IDM_PREFERENCES + MENUITEM "&Preferenze...", IDM_PREFERENCES +#ifdef DISCORD MENUITEM "Abilita &integrazione Discord", IDM_DISCORD +#endif MENUITEM SEPARATOR - MENUITEM "Guadagno &suono...", IDM_SND_GAIN + MENUITEM "Guadagno &suono...", IDM_SND_GAIN #ifdef MTR_ENABLED MENUITEM SEPARATOR - MENUITEM "Inizia traccia\tCtrl+T", IDM_ACTION_BEGIN_TRACE - MENUITEM "Ferma traccia\tCtrl+T", IDM_ACTION_END_TRACE + MENUITEM "Inizia traccia\tCtrl+T", IDM_ACTION_BEGIN_TRACE + MENUITEM "Ferma traccia\tCtrl+T", IDM_ACTION_END_TRACE #endif END POPUP "&?" BEGIN - MENUITEM "&Documentazione...", IDM_DOCS - MENUITEM "&Informazioni su 86Box...", IDM_ABOUT + MENUITEM "&Documentazione...", IDM_DOCS + MENUITEM "&Informazioni su 86Box...", IDM_ABOUT END END -StatusBarMenu MENU DISCARDABLE +StatusBarMenu MENU DISCARDABLE BEGIN MENUITEM SEPARATOR END @@ -129,17 +138,17 @@ CassetteSubmenu MENU DISCARDABLE BEGIN POPUP "" BEGIN - MENUITEM "&Nuova immagine...", IDM_CASSETTE_IMAGE_NEW + MENUITEM "&Nuova immagine...", IDM_CASSETTE_IMAGE_NEW MENUITEM SEPARATOR - MENUITEM "&Immagine esistente...", IDM_CASSETTE_IMAGE_EXISTING - MENUITEM "Immagine esistente (&protezione contro scrittura)...", IDM_CASSETTE_IMAGE_EXISTING_WP + MENUITEM "&Immagine esistente...", IDM_CASSETTE_IMAGE_EXISTING + MENUITEM "Immagine esistente (&protezione contro scrittura)...", IDM_CASSETTE_IMAGE_EXISTING_WP MENUITEM SEPARATOR - MENUITEM "&Registra", IDM_CASSETTE_RECORD - MENUITEM "R&iproduci", IDM_CASSETTE_PLAY - MENUITEM "Ri&avvolgi all'inizio", IDM_CASSETTE_REWIND - MENUITEM "A&vanti veloce alla fine", IDM_CASSETTE_FAST_FORWARD + MENUITEM "&Registra", IDM_CASSETTE_RECORD + MENUITEM "R&iproduci", IDM_CASSETTE_PLAY + MENUITEM "Ri&avvolgi all'inizio", IDM_CASSETTE_REWIND + MENUITEM "A&vanti veloce alla fine", IDM_CASSETTE_FAST_FORWARD MENUITEM SEPARATOR - MENUITEM "&Espelli", IDM_CASSETTE_EJECT + MENUITEM "&Espelli", IDM_CASSETTE_EJECT END END @@ -147,9 +156,9 @@ CartridgeSubmenu MENU DISCARDABLE BEGIN POPUP "" BEGIN - MENUITEM "&Immagine...", IDM_CARTRIDGE_IMAGE + MENUITEM "&Immagine...", IDM_CARTRIDGE_IMAGE MENUITEM SEPARATOR - MENUITEM "&Espelli", IDM_CARTRIDGE_EJECT + MENUITEM "&Espelli", IDM_CARTRIDGE_EJECT END END @@ -157,14 +166,14 @@ FloppySubmenu MENU DISCARDABLE BEGIN POPUP "" BEGIN - MENUITEM "&Nuova immagine...", IDM_FLOPPY_IMAGE_NEW + MENUITEM "&Nuova immagine...", IDM_FLOPPY_IMAGE_NEW MENUITEM SEPARATOR - MENUITEM "&Immagine esistente...", IDM_FLOPPY_IMAGE_EXISTING - MENUITEM "Immagine esistente (&protezione contro scrittura)...", IDM_FLOPPY_IMAGE_EXISTING_WP + MENUITEM "&Immagine esistente...", IDM_FLOPPY_IMAGE_EXISTING + MENUITEM "Immagine esistente (&protezione contro scrittura)...", IDM_FLOPPY_IMAGE_EXISTING_WP MENUITEM SEPARATOR - MENUITEM "E&sporta in 86F...", IDM_FLOPPY_EXPORT_TO_86F + MENUITEM "E&sporta in 86F...", IDM_FLOPPY_EXPORT_TO_86F MENUITEM SEPARATOR - MENUITEM "&Espelli", IDM_FLOPPY_EJECT + MENUITEM "&Espelli", IDM_FLOPPY_EJECT END END @@ -172,12 +181,13 @@ CdromSubmenu MENU DISCARDABLE BEGIN POPUP "" BEGIN - MENUITEM "&Muto", IDM_CDROM_MUTE + MENUITEM "&Muto", IDM_CDROM_MUTE MENUITEM SEPARATOR - MENUITEM "&Espelli", IDM_CDROM_EMPTY - MENUITEM "&Ricarica l'immagine precedente", IDM_CDROM_RELOAD + MENUITEM "&Espelli", IDM_CDROM_EMPTY + MENUITEM "&Ricarica l'immagine precedente", IDM_CDROM_RELOAD MENUITEM SEPARATOR - MENUITEM "&Immagine", IDM_CDROM_IMAGE + MENUITEM "&Immagine...", IDM_CDROM_IMAGE + MENUITEM "&Cartella...", IDM_CDROM_DIR END END @@ -185,13 +195,13 @@ ZIPSubmenu MENU DISCARDABLE BEGIN POPUP "" BEGIN - MENUITEM "&Nuova immagine...", IDM_ZIP_IMAGE_NEW + MENUITEM "&Nuova immagine...", IDM_ZIP_IMAGE_NEW MENUITEM SEPARATOR - MENUITEM "&Immagine esistente...", IDM_ZIP_IMAGE_EXISTING - MENUITEM "Immagine esistente (&protezione contro scrittura)...", IDM_ZIP_IMAGE_EXISTING_WP + MENUITEM "&Immagine esistente...", IDM_ZIP_IMAGE_EXISTING + MENUITEM "Immagine esistente (&protezione contro scrittura)...", IDM_ZIP_IMAGE_EXISTING_WP MENUITEM SEPARATOR - MENUITEM "&Espelli", IDM_ZIP_EJECT - MENUITEM "&Ricarica l'immagine precedente", IDM_ZIP_RELOAD + MENUITEM "&Espelli", IDM_ZIP_EJECT + MENUITEM "&Ricarica l'immagine precedente", IDM_ZIP_RELOAD END END @@ -199,13 +209,13 @@ MOSubmenu MENU DISCARDABLE BEGIN POPUP "" BEGIN - MENUITEM "&Nuova immagine...", IDM_MO_IMAGE_NEW + MENUITEM "&Nuova immagine...", IDM_MO_IMAGE_NEW MENUITEM SEPARATOR - MENUITEM "&Immagine esistente...", IDM_MO_IMAGE_EXISTING - MENUITEM "Immagine esistente (&protezione contro scrittura)...", IDM_MO_IMAGE_EXISTING_WP + MENUITEM "&Immagine esistente...", IDM_MO_IMAGE_EXISTING + MENUITEM "Immagine esistente (&protezione contro scrittura)...", IDM_MO_IMAGE_EXISTING_WP MENUITEM SEPARATOR - MENUITEM "&Espelli", IDM_MO_EJECT - MENUITEM "&Ricarica l'immagine precedente", IDM_MO_RELOAD + MENUITEM "&Espelli", IDM_MO_EJECT + MENUITEM "&Ricarica l'immagine precedente", IDM_MO_RELOAD END END @@ -231,134 +241,150 @@ END // Dialog // -#define STR_PREFERENCES "Preferenze" -#define STR_SND_GAIN "Guadagno del suono" -#define STR_NEW_FLOPPY "Nuova immagine" -#define STR_CONFIG "Impostazioni" -#define STR_SPECIFY_DIM "Specifica dimensioni della finestra principale" +#define STR_PREFERENCES "Preferenze" +#define STR_SND_GAIN "Guadagno del suono" +#define STR_NEW_FLOPPY "Nuova immagine" +#define STR_CONFIG "Impostazioni" +#define STR_SPECIFY_DIM "Specifica dimensioni della finestra principale" -#define STR_OK "OK" -#define STR_CANCEL "Annulla" -#define STR_GLOBAL "Salva queste impostazioni come &predefinite globali" -#define STR_DEFAULT "&Predefinito" -#define STR_LANGUAGE "Lingua:" -#define STR_ICONSET "Pacchetto di icone:" +#define STR_OK "OK" +#define STR_CANCEL "Annulla" +#define STR_GLOBAL "Salva queste impostazioni come &predefinite globali" +#define STR_DEFAULT "&Predefinito" +#define STR_LANGUAGE "Lingua:" +#define STR_ICONSET "Pacchetto di icone:" -#define STR_GAIN "Guadagno" +#define STR_GAIN "Guadagno" -#define STR_FILE_NAME "Nome file:" -#define STR_DISK_SIZE "Dimensioni disco:" -#define STR_RPM_MODE "Modalità RPM:" -#define STR_PROGRESS "Progresso:" +#define STR_FILE_NAME "Nome file:" +#define STR_DISK_SIZE "Dimensioni disco:" +#define STR_RPM_MODE "Modalità RPM:" +#define STR_PROGRESS "Progresso:" -#define STR_WIDTH "Larghezza:" -#define STR_HEIGHT "Altezza:" -#define STR_LOCK_TO_SIZE "Blocca in queste dimensioni" +#define STR_WIDTH "Larghezza:" +#define STR_HEIGHT "Altezza:" +#define STR_LOCK_TO_SIZE "Blocca in queste dimensioni" -#define STR_MACHINE_TYPE "Tipo di piastra madre:" -#define STR_MACHINE "Piastra madre:" -#define STR_CONFIGURE "Configura" -#define STR_CPU_TYPE "Tipo del CPU:" -#define STR_CPU_SPEED "Veloc.:" -#define STR_FPU "FPU:" -#define STR_WAIT_STATES "Stati di attesa:" -#define STR_MB "MB" -#define STR_MEMORY "Memoria:" -#define STR_TIME_SYNC "Sincronizzazione dell'ora" -#define STR_DISABLED "Disabilitata" -#define STR_ENABLED_LOCAL "Abilitata (ora locale)" -#define STR_ENABLED_UTC "Abilitata (UTC)" -#define STR_DYNAREC "Ricompilatore dinamico" +#define STR_MACHINE_TYPE "Tipo di piastra madre:" +#define STR_MACHINE "Piastra madre:" +#define STR_CONFIGURE "Configura" +#define STR_CPU_TYPE "Tipo del CPU:" +#define STR_CPU_SPEED "Veloc.:" +#define STR_FPU "FPU:" +#define STR_WAIT_STATES "Stati di attesa:" +#define STR_MB "MB" +#define STR_MEMORY "Memoria:" +#define STR_TIME_SYNC "Sincronizzazione dell'ora" +#define STR_DISABLED "Disabilitata" +#define STR_ENABLED_LOCAL "Abilitata (ora locale)" +#define STR_ENABLED_UTC "Abilitata (UTC)" +#define STR_DYNAREC "Ricompilatore dinamico" +#define STR_SOFTFLOAT "Softfloat FPU" -#define STR_VIDEO "Video:" -#define STR_VOODOO "Grafica Voodoo" +#define STR_VIDEO "Video:" +#define STR_VIDEO_2 "Video 2:" +#define STR_VOODOO "Grafica Voodoo" +#define STR_IBM8514 "Grafica IBM 8514/a" +#define STR_XGA "Grafica XGA" -#define STR_MOUSE "Mouse:" -#define STR_JOYSTICK "Joystick:" -#define STR_JOY1 "Joystick 1..." -#define STR_JOY2 "Joystick 2..." -#define STR_JOY3 "Joystick 3..." -#define STR_JOY4 "Joystick 4..." +#define STR_MOUSE "Mouse:" +#define STR_JOYSTICK "Joystick:" +#define STR_JOY1 "Joystick 1..." +#define STR_JOY2 "Joystick 2..." +#define STR_JOY3 "Joystick 3..." +#define STR_JOY4 "Joystick 4..." -#define STR_SOUND "Scheda audio:" -#define STR_MIDI_OUT "Uscita MIDI:" -#define STR_MIDI_IN "Entrata MIDI:" -#define STR_MPU401 "MPU-401 autonomo" -#define STR_SSI "Innovation SSI-2001" -#define STR_CMS "CMS / Game Blaster" -#define STR_GUS "Gravis Ultrasound" -#define STR_FLOAT "Usa suono FLOAT32" +#define STR_SOUND1 "Scheda audio 1:" +#define STR_SOUND2 "Scheda audio 2:" +#define STR_SOUND3 "Scheda audio 3:" +#define STR_SOUND4 "Scheda audio 4:" +#define STR_MIDI_OUT "Uscita MIDI:" +#define STR_MIDI_IN "Entrata MIDI:" +#define STR_MPU401 "MPU-401 autonomo" +#define STR_FLOAT "Usa suono FLOAT32" +#define STR_FM_DRIVER "Driver sint. FM" +#define STR_FM_DRV_NUKED "Nuked (più accurato)" +#define STR_FM_DRV_YMFM "YMFM (più veloce)" -#define STR_NET_TYPE "Tipo di rete:" -#define STR_PCAP "Dispositivo PCap:" -#define STR_NET "Scheda di rete:" +#define STR_NET_TYPE "Tipo di rete:" +#define STR_PCAP "Dispositivo PCap:" +#define STR_NET "Scheda di rete:" +#define STR_NET1 "Network card 1:" +#define STR_NET2 "Network card 2:" +#define STR_NET3 "Network card 3:" +#define STR_NET4 "Network card 4:" -#define STR_COM1 "Dispositivo COM1:" -#define STR_COM2 "Dispositivo COM2:" -#define STR_COM3 "Dispositivo COM3:" -#define STR_COM4 "Dispositivo COM4:" -#define STR_LPT1 "Dispositivo LPT1:" -#define STR_LPT2 "Dispositivo LPT2:" -#define STR_LPT3 "Dispositivo LPT3:" -#define STR_LPT4 "Dispositivo LPT4:" -#define STR_SERIAL1 "Porta seriale 1" -#define STR_SERIAL2 "Porta seriale 2" -#define STR_SERIAL3 "Porta seriale 3" -#define STR_SERIAL4 "Porta seriale 4" -#define STR_PARALLEL1 "Porta parallela 1" -#define STR_PARALLEL2 "Porta parallela 2" -#define STR_PARALLEL3 "Porta parallela 3" -#define STR_PARALLEL4 "Porta parallela 4" +#define STR_COM1 "Dispositivo COM1:" +#define STR_COM2 "Dispositivo COM2:" +#define STR_COM3 "Dispositivo COM3:" +#define STR_COM4 "Dispositivo COM4:" +#define STR_LPT1 "Dispositivo LPT1:" +#define STR_LPT2 "Dispositivo LPT2:" +#define STR_LPT3 "Dispositivo LPT3:" +#define STR_LPT4 "Dispositivo LPT4:" +#define STR_SERIAL1 "Porta seriale 1" +#define STR_SERIAL2 "Porta seriale 2" +#define STR_SERIAL3 "Porta seriale 3" +#define STR_SERIAL4 "Porta seriale 4" +#define STR_PARALLEL1 "Porta parallela 1" +#define STR_PARALLEL2 "Porta parallela 2" +#define STR_PARALLEL3 "Porta parallela 3" +#define STR_PARALLEL4 "Porta parallela 4" +#define STR_SERIAL_PASS1 "Serial port passthrough 1" +#define STR_SERIAL_PASS2 "Serial port passthrough 2" +#define STR_SERIAL_PASS3 "Serial port passthrough 3" +#define STR_SERIAL_PASS4 "Serial port passthrough 4" -#define STR_HDC "Controller HD:" -#define STR_FDC "Controller FD:" -#define STR_IDE_TER "Controller IDE terziario" -#define STR_IDE_QUA "Controller IDE quaternario" -#define STR_SCSI "SCSI" -#define STR_SCSI_1 "Controller 1:" -#define STR_SCSI_2 "Controller 2:" -#define STR_SCSI_3 "Controller 3:" -#define STR_SCSI_4 "Controller 4:" -#define STR_CASSETTE "Cassetta" +#define STR_HDC "Controller HD:" +#define STR_FDC "Controller FD:" +#define STR_IDE_TER "Controller IDE terziario" +#define STR_IDE_QUA "Controller IDE quaternario" +#define STR_SCSI "SCSI" +#define STR_SCSI_1 "Controller 1:" +#define STR_SCSI_2 "Controller 2:" +#define STR_SCSI_3 "Controller 3:" +#define STR_SCSI_4 "Controller 4:" +#define STR_CASSETTE "Cassetta" -#define STR_HDD "Hard disk:" -#define STR_NEW "&Nuovo..." -#define STR_EXISTING "&Esistente..." -#define STR_REMOVE "&Rimouvi" -#define STR_BUS "Bus:" -#define STR_CHANNEL "Canale:" -#define STR_ID "ID:" +#define STR_HDD "Hard disk:" +#define STR_NEW "&Nuovo..." +#define STR_EXISTING "&Esistente..." +#define STR_REMOVE "&Rimouvi" +#define STR_BUS "Bus:" +#define STR_CHANNEL "Canale:" +#define STR_ID "ID:" +#define STR_SPEED "Speed:" -#define STR_SPECIFY "&Specifica..." -#define STR_SECTORS "Settori:" -#define STR_HEADS "Testine:" -#define STR_CYLS "Cilindri:" -#define STR_SIZE_MB "Dimensioni (MB):" -#define STR_TYPE "Tipo:" -#define STR_IMG_FORMAT "Formato immagine:" -#define STR_BLOCK_SIZE "Dimensioni blocco:" +#define STR_SPECIFY "&Specifica..." +#define STR_SECTORS "Settori:" +#define STR_HEADS "Testine:" +#define STR_CYLS "Cilindri:" +#define STR_SIZE_MB "Dimensioni (MB):" +#define STR_TYPE "Tipo:" +#define STR_IMG_FORMAT "Formato immagine:" +#define STR_BLOCK_SIZE "Dimensioni blocco:" -#define STR_FLOPPY_DRIVES "Unità floppy:" -#define STR_TURBO "Turbo" -#define STR_CHECKBPB "Verifica BPB" -#define STR_CDROM_DRIVES "Unità CD-ROM:" -#define STR_CD_SPEED "Veloc.:" +#define STR_FLOPPY_DRIVES "Unità floppy:" +#define STR_TURBO "Turbo" +#define STR_CHECKBPB "Verifica BPB" +#define STR_CDROM_DRIVES "Unità CD-ROM:" +#define STR_CD_SPEED "Veloc.:" -#define STR_MO_DRIVES "Unità magneto-ottiche:" -#define STR_ZIP_DRIVES "Unità ZIP:" -#define STR_250 "ZIP 250" +#define STR_MO_DRIVES "Unità magneto-ottiche:" +#define STR_ZIP_DRIVES "Unità ZIP:" +#define STR_250 "ZIP 250" -#define STR_ISARTC "RTC ISA:" -#define STR_ISAMEM "Espansione memoria ISA" -#define STR_ISAMEM_1 "Scheda 1:" -#define STR_ISAMEM_2 "Scheda 2:" -#define STR_ISAMEM_3 "Scheda 3:" -#define STR_ISAMEM_4 "Scheda 4:" -#define STR_BUGGER "Dispositivo ISABugger" -#define STR_POSTCARD "Scheda POST" +#define STR_ISARTC "RTC ISA:" +#define STR_ISAMEM "Espansione memoria ISA" +#define STR_ISAMEM_1 "Scheda 1:" +#define STR_ISAMEM_2 "Scheda 2:" +#define STR_ISAMEM_3 "Scheda 3:" +#define STR_ISAMEM_4 "Scheda 4:" +#define STR_BUGGER "Dispositivo ISABugger" +#define STR_POSTCARD "Scheda POST" -#define FONT_SIZE 9 -#define FONT_NAME "Segoe UI" +#define FONT_SIZE 9 +#define FONT_NAME "Segoe UI" #include "dialogs.rc" @@ -367,194 +393,188 @@ END // String Table // -STRINGTABLE DISCARDABLE +STRINGTABLE DISCARDABLE BEGIN - 2048 "86Box" - IDS_2049 "Errore" - IDS_2050 "Errore fatale" - IDS_2051 " - PAUSED" - IDS_2052 "Usa Ctrl+Alt+PgDn per tornare alla modalità finestra." - IDS_2053 "Velocità" - IDS_2054 "ZIP %03i %i (%s): %ls" - IDS_2055 "Immagini ZIP (*.IM?;*.ZDI)\0*.IM?;*.ZDI\0" - IDS_2056 "86Box non può trovare immagini ROM utilizzabili.\n\nPlease download a ROM set and extract it into the ""roms"" directory." - IDS_2057 "(empty)" - IDS_2058 "Immagini ZIP (*.IM?;*.ZDI)\0*.IM?;*.ZDI\0Tutti i file (*.*)\0*.*\0" - IDS_2059 "Turbo" - IDS_2060 "Acceso" - IDS_2061 "Spento" - IDS_2062 "Tutte le immagini (*.86F;*.DSK;*.FLP;*.IM?;*.*FD?)\0*.86F;*.DSK;*.FLP;*.IM?;*.*FD?\0Immagini di settori base (*.DSK;*.FLP;*.IM?;*.*FD?)\0*.DSK;*.FLP;*.IM?;*.IMG;*.*FD?\0Immagini di superficie (*.86F)\0*.86F\0" - IDS_2063 "La macchina ""%hs"" non è disponibile a causa di immagini ROM mancanti nella directory roms/machines. Cambiando ad una macchina disponibile." + 2048 "86Box" + IDS_2049 "Errore" + IDS_2050 "Errore fatale" + IDS_2051 " - PAUSED" + IDS_2052 "Usa Ctrl+Alt+PgDn per tornare alla modalità finestra." + IDS_2053 "Velocità" + IDS_2054 "ZIP %03i %i (%s): %ls" + IDS_2055 "Immagini ZIP (*.IM?;*.ZDI)\0*.IM?;*.ZDI\0" + IDS_2056 "86Box non può trovare immagini ROM utilizzabili.\n\nPlease download a ROM set and extract it into the ""roms"" directory." + IDS_2057 "(empty)" + IDS_2058 "Immagini ZIP (*.IM?;*.ZDI)\0*.IM?;*.ZDI\0Tutti i file (*.*)\0*.*\0" + IDS_2059 "Turbo" + IDS_2060 "Acceso" + IDS_2061 "Spento" + IDS_2062 "Tutte le immagini (*.86F;*.DSK;*.FLP;*.IM?;*.*FD?)\0*.86F;*.DSK;*.FLP;*.IM?;*.*FD?\0Immagini di settori base (*.DSK;*.FLP;*.IM?;*.*FD?)\0*.DSK;*.FLP;*.IM?;*.IMG;*.*FD?\0Immagini di superficie (*.86F)\0*.86F\0" + IDS_2063 "La macchina ""%hs"" non è disponibile a causa di immagini ROM mancanti nella directory roms/machines. Cambiando ad una macchina disponibile." END -STRINGTABLE DISCARDABLE +STRINGTABLE DISCARDABLE BEGIN - IDS_2064 "La scheda video ""%hs"" non è disponibile a causa di immagini ROM mancanti nella directory roms/video. Cambiando ad una scheda video disponibile." - IDS_2065 "Piastra madre" - IDS_2066 "Schermo" - IDS_2067 "Dispositivi di entrata" - IDS_2068 "Audio" - IDS_2069 "Rete" - IDS_2070 "Porte (COM & LPT)" - IDS_2071 "Controller memoria" - IDS_2072 "Hard disk" - IDS_2073 "Unità CD-ROM e Floppy" - IDS_2074 "Altri dispositivi rimuovibili" - IDS_2075 "Altre periferiche" - IDS_2076 "Immagini di superficie (*.86F)\0*.86F\0" - IDS_2077 "Fare clic per catturare mouse" - IDS_2078 "Premi F8+F12 per rilasciare il mouse" - IDS_2079 "Premi F8+F12 o pulsante centrale per rilasciare il mouse" + IDS_2064 "La scheda video ""%hs"" non è disponibile a causa di immagini ROM mancanti nella directory roms/video. Cambiando ad una scheda video disponibile." + IDS_2065 "Piastra madre" + IDS_2066 "Schermo" + IDS_2067 "Dispositivi di entrata" + IDS_2068 "Audio" + IDS_2069 "Rete" + IDS_2070 "Porte (COM & LPT)" + IDS_2071 "Controller memoria" + IDS_2072 "Hard disk" + IDS_2073 "Unità CD-ROM e Floppy" + IDS_2074 "Altri dispositivi rimuovibili" + IDS_2075 "Altre periferiche" + IDS_2076 "Immagini di superficie (*.86F)\0*.86F\0" + IDS_2077 "Fare clic per catturare mouse" + IDS_2078 "Premi F8+F12 per rilasciare il mouse" + IDS_2079 "Premi F8+F12 o pulsante centrale per rilasciare il mouse" END -STRINGTABLE DISCARDABLE +STRINGTABLE DISCARDABLE BEGIN - IDS_2080 "Impossibile inizializzare FluidSynth" - IDS_2081 "Bus" - IDS_2082 "File" - IDS_2083 "C" - IDS_2084 "H" - IDS_2085 "S" - IDS_2086 "MB" - IDS_2087 "Verifica BPB" - IDS_2088 "KB" - IDS_2089 "Impossibile inizializzare il renderer video." - IDS_2090 "Predefinito" - IDS_2091 "%i stati d'attesa" - IDS_2092 "Tipo" - IDS_2093 "Impossibile impostare PCap" - IDS_2094 "Nessun dispositivo PCap trovato" - IDS_2095 "Dispositivo PCap invalido" - IDS_2096 "Joystick comune da 2 pulsanti" - IDS_2097 "Joystick comune da 4 pulsanti" - IDS_2098 "Joystick comune da 6 pulsanti" - IDS_2099 "Joystick comune da 8 pulsanti" - IDS_2100 "CH Flightstick Pro" - IDS_2101 "Microsoft SideWinder Pad" - IDS_2102 "Thrustmaster Flight Control System" - IDS_2103 "Nessuno" - IDS_2104 "Impossibile caricare gli acceleratori da tastiera." - IDS_2105 "Impossibile registrare input raw." - IDS_2106 "%u" - IDS_2107 "%u MB (CHS: %i, %i, %i)" - IDS_2108 "Floppy %i (%s): %ls" - IDS_2109 "Tutte le immagini (*.0??;*.1??;*.??0;*.86F;*.BIN;*.CQ?;*.D??;*.FLP;*.HDM;*.IM?;*.JSON;*.TD0;*.*FD?;*.MFM;*.XDF)\0*.0??;*.1??;*.??0;*.86F;*.BIN;*.CQ?;*.D??;*.FLP;*.HDM;*.IM?;*.JSON;*.TD0;*.*FD?;*.MFM;*.XDF\0Immagini da settori avanzati (*.IMD;*.JSON;*.TD0)\0*.IMD;*.JSON;*.TD0\0Imagini da settori basilari (*.0??;*.1??;*.??0;*.BIN;*.CQ?;*.D??;*.FLP;*.HDM;*.IM?;*.XDF;*.*FD?)\0*.0??;*.1??;*.??0;*.BIN;*.CQ?;*.D??;*.FLP;*.HDM;*.IM?;*.XDF;*.*FD?\0Immagini flusso (*.FDI)\0*.FDI\0Immagini da superficie (*.86F;*.MFM)\0*.86F;*.MFM\0Tutti i file (*.*)\0*.*\0" - IDS_2110 "Impossibile inizializzare FreeType" - IDS_2111 "Impossibile inizializzare SDL, SDL2.dll è necessario" - IDS_2112 "Sei sicuro di voler riavviare la macchina emulata?" - IDS_2113 "Sei sicuro di voler uscire da 86Box?" - IDS_2114 "Impossibile inizializzare Ghostscript" - IDS_2115 "MO %i (%ls): %ls" - IDS_2116 "Immagini MO (*.IM?;*.MDI)\0*.IM?;*.MDI\0Tutti i file (*.*)\0*.*\0" - IDS_2117 "Benvenuti in 86Box!" - IDS_2118 "Controller interno" - IDS_2119 "Esci" - IDS_2120 "Nessune immagini ROM trovate" - IDS_2121 "Vuole salvare queste impostazioni?" - IDS_2122 "Questo riavvierà la macchina emulata." - IDS_2123 "Salva" - IDS_2124 "Informazioni su 86Box" - IDS_2125 "86Box v" EMU_VERSION + IDS_2081 "Bus" + IDS_2082 "File" + IDS_2083 "C" + IDS_2084 "H" + IDS_2085 "S" + IDS_2086 "MB" + IDS_2087 "Speed" + IDS_2088 "Verifica BPB" + IDS_2089 "KB" + IDS_2090 "Impossibile inizializzare il renderer video." + IDS_2091 "Predefinito" + IDS_2092 "%i stati d'attesa" + IDS_2093 "Tipo" + IDS_2094 "Impossibile impostare PCap" + IDS_2095 "Nessun dispositivo PCap trovato" + IDS_2096 "Dispositivo PCap invalido" + IDS_2097 "Joystick comune da 2 pulsanti" + IDS_2098 "Joystick comune da 4 pulsanti" + IDS_2099 "Joystick comune da 6 pulsanti" + IDS_2100 "Joystick comune da 8 pulsanti" + IDS_2101 "CH Flightstick Pro" + IDS_2102 "Microsoft SideWinder Pad" + IDS_2103 "Thrustmaster Flight Control System" + IDS_2104 "Nessuno" + IDS_2105 "Impossibile caricare gli acceleratori da tastiera." + IDS_2106 "Impossibile registrare input raw." + IDS_2107 "%u" + IDS_2108 "%u MB (CHS: %i, %i, %i)" + IDS_2109 "Floppy %i (%s): %ls" + IDS_2110 "Tutte le immagini (*.0??;*.1??;*.??0;*.86F;*.BIN;*.CQ?;*.D??;*.FLP;*.HDM;*.IM?;*.JSON;*.TD0;*.*FD?;*.MFM;*.XDF)\0*.0??;*.1??;*.??0;*.86F;*.BIN;*.CQ?;*.D??;*.FLP;*.HDM;*.IM?;*.JSON;*.TD0;*.*FD?;*.MFM;*.XDF\0Immagini da settori avanzati (*.IMD;*.JSON;*.TD0)\0*.IMD;*.JSON;*.TD0\0Imagini da settori basilari (*.0??;*.1??;*.??0;*.BIN;*.CQ?;*.D??;*.FLP;*.HDM;*.IM?;*.XDF;*.*FD?)\0*.0??;*.1??;*.??0;*.BIN;*.CQ?;*.D??;*.FLP;*.HDM;*.IM?;*.XDF;*.*FD?\0Immagini flusso (*.FDI)\0*.FDI\0Immagini da superficie (*.86F;*.MFM)\0*.86F;*.MFM\0Tutti i file (*.*)\0*.*\0" + IDS_2112 "Impossibile inizializzare SDL, SDL2.dll è necessario" + IDS_2113 "Sei sicuro di voler riavviare la macchina emulata?" + IDS_2114 "Sei sicuro di voler uscire da 86Box?" + IDS_2115 "Impossibile inizializzare Ghostscript" + IDS_2116 "MO %i (%ls): %ls" + IDS_2117 "Immagini MO (*.IM?;*.MDI)\0*.IM?;*.MDI\0Tutti i file (*.*)\0*.*\0" + IDS_2118 "Benvenuti in 86Box!" + IDS_2119 "Controller interno" + IDS_2120 "Esci" + IDS_2121 "Nessune immagini ROM trovate" + IDS_2122 "Vuole salvare queste impostazioni?" + IDS_2123 "Questo riavvierà la macchina emulata." + IDS_2124 "Salva" + IDS_2125 "Informazioni su 86Box" + IDS_2126 "86Box v" EMU_VERSION - IDS_2126 "Un emulatore di computer vecchi\n\nAutori: Sarah Walker, Miran Grca, Fred N. van Kempen (waltje), SA1988, Tiseno100, reenigne, leilei, JohnElliott, greatpsycho, and others.\n\nTradotto da: explorerdotexe\n\nRilasciato sotto la Licenza Pubblica GNU versione 2 o dopo. Vedi LICENSE per maggior informazioni." - IDS_2127 "OK" - IDS_2128 "Hardware non disponibile" + IDS_2127 "Un emulatore di computer vecchi\n\nAutori: Miran GrÄa (OBattler), RichardG867, Jasmine Iwanek, TC1995, coldbrewed, Teemu Korhonen (Manaatti), Joakim L. Gilje, Adrien Moulin (elyosh), Daniel Balsom (gloriouscow), Cacodemon345, Fred N. van Kempen (waltje), Tiseno100, reenigne, and others.\n\nWith previous core contributions from Sarah Walker, leilei, JohnElliott, greatpsycho, and others.\n\nTradotto da: explorerdotexe\n\nRilasciato sotto la Licenza Pubblica GNU versione 2 o dopo. Vedi LICENSE per maggior informazioni." + IDS_2128 "OK" + IDS_2129 "Hardware non disponibile" #ifdef _WIN32 #define LIB_NAME_PCAP "WinPcap" #else #define LIB_NAME_PCAP "libpcap" #endif - IDS_2129 "Controlla se " LIB_NAME_PCAP " è installato e che tu sia connesso ad una connessione " LIB_NAME_PCAP " compatibile." - IDS_2130 "Configurazione invalida" -#ifdef _WIN32 -#define LIB_NAME_FREETYPE "freetype.dll" -#else -#define LIB_NAME_FREETYPE "libfreetype" -#endif - IDS_2131 LIB_NAME_FREETYPE " è richesto per l'emuazione di stampanti ESC/P." + IDS_2130 "Controlla se " LIB_NAME_PCAP " è installato e che tu sia connesso ad una connessione " LIB_NAME_PCAP " compatibile." + IDS_2131 "Configurazione invalida" #ifdef _WIN32 #define LIB_NAME_GS "gsdll32.dll" #else #define LIB_NAME_GS "libgs" #endif - IDS_2132 LIB_NAME_GS " è richiesto per la conversione automatica di file PostScript a file PDF.\n\nQualsiasi documento mandato alla stampante generica PostScript sarà salvato come file PostScript. (.ps)" -#ifdef _WIN32 -#define LIB_NAME_FLUIDSYNTH "libfluidsynth.dll" -#else -#define LIB_NAME_FLUIDSYNTH "libfluidsynth" -#endif - IDS_2133 LIB_NAME_FLUIDSYNTH " è richiesto per l'output FluidSynth MIDI." - IDS_2134 "Entrando nella modalità schermo intero" - IDS_2135 "Non mostrare più questo messaggio" - IDS_2136 "Non uscire" - IDS_2137 "Riavvia" - IDS_2138 "Non riavviare" - IDS_2139 "Immagini MO (*.IM?;*.MDI)\0*.IM?;*.MDI\0Tutti i file (*.*)\0*.*\0" - IDS_2140 "Immagini CD-ROM (*.ISO;*.CUE)\0*.ISO;*.CUE\0Tutti i file (*.*)\0*.*\0" - IDS_2141 "Configurazione del dispositivo %hs" - IDS_2142 "Monitor in modalità riposo" - IDS_2143 "Shader OpenGL (*.GLSL)\0*.GLSL\0Tutti i file (*.*)\0*.*\0" - IDS_2144 "Impostazioni OpenGL" - IDS_2145 "Stai caricando una configurazione non supportata" - IDS_2146 "Il filtraggio della tipologia di CPU è disabilitato per la macchina selezionata.\n\nQuesto lo rende possibile scegliere un CPU che è altrimenti incompatibile con la macchina selezionata. Tuttavia, portresti incorrere in incompatibilità con il BIOS della macchina o altri programmi. \n\nL'abilitare di questa impostazione non è ufficialmente supportato e tutte le segnalazioni di errori saranno considerate invalide." - IDS_2147 "Continua" - IDS_2148 "Cassetta: %s" - IDS_2149 "Immagini cassetta (*.PCM;*.RAW;*.WAV;*.CAS)\0*.PCM;*.RAW;*.WAV;*.CAS\0Tutti i file (*.*)\0*.*\0" - IDS_2150 "Cartuccia %i: %ls" - IDS_2151 "Immagini cartuccia (*.A;*.B;*.JRC)\0*.A;*.B;*.JRC\0Tutti i file (*.*)\0*.*\0" - IDS_2152 "Error initializing renderer" - IDS_2153 "OpenGL (3.0 Core) renderer could not be initialized. Use another renderer." - IDS_2154 "Resume execution" - IDS_2155 "Pause execution" - IDS_2156 "Press Ctrl+Alt+Del" - IDS_2157 "Press Ctrl+Alt+Esc" - IDS_2158 "Hard reset" - IDS_2159 "ACPI shutdown" - IDS_2160 "Settings" + IDS_2133 LIB_NAME_GS " è richiesto per la conversione automatica di file PostScript a file PDF.\n\nQualsiasi documento mandato alla stampante generica PostScript sarà salvato come file PostScript. (.ps)" + IDS_2135 "Entrando nella modalità schermo intero" + IDS_2136 "Non mostrare più questo messaggio" + IDS_2137 "Non uscire" + IDS_2138 "Riavvia" + IDS_2139 "Non riavviare" + IDS_2140 "Immagini MO (*.IM?;*.MDI)\0*.IM?;*.MDI\0Tutti i file (*.*)\0*.*\0" + IDS_2141 "Immagini CD-ROM (*.ISO;*.CUE)\0*.ISO;*.CUE\0Tutti i file (*.*)\0*.*\0" + IDS_2142 "Configurazione del dispositivo %hs" + IDS_2143 "Monitor in modalità riposo" + IDS_2144 "Shader OpenGL (*.GLSL)\0*.GLSL\0Tutti i file (*.*)\0*.*\0" + IDS_2145 "Impostazioni OpenGL" + IDS_2146 "Stai caricando una configurazione non supportata" + IDS_2147 "Il filtraggio della tipologia di CPU è disabilitato per la macchina selezionata.\n\nQuesto lo rende possibile scegliere un CPU che è altrimenti incompatibile con la macchina selezionata. Tuttavia, portresti incorrere in incompatibilità con il BIOS della macchina o altri programmi. \n\nL'abilitare di questa impostazione non è ufficialmente supportato e tutte le segnalazioni di errori saranno considerate invalide." + IDS_2148 "Continua" + IDS_2149 "Cassetta: %s" + IDS_2150 "Immagini cassetta (*.PCM;*.RAW;*.WAV;*.CAS)\0*.PCM;*.RAW;*.WAV;*.CAS\0Tutti i file (*.*)\0*.*\0" + IDS_2151 "Cartuccia %i: %ls" + IDS_2152 "Immagini cartuccia (*.A;*.B;*.JRC)\0*.A;*.B;*.JRC\0Tutti i file (*.*)\0*.*\0" + IDS_2153 "Error initializing renderer" + IDS_2154 "OpenGL (3.0 Core) renderer could not be initialized. Use another renderer." + IDS_2155 "Resume execution" + IDS_2156 "Pause execution" + IDS_2157 "Press Ctrl+Alt+Del" + IDS_2158 "Press Ctrl+Alt+Esc" + IDS_2159 "Hard reset" + IDS_2160 "ACPI shutdown" + IDS_2161 "Settings" + IDS_2162 "Type" + IDS_2163 "No Dynarec" + IDS_2164 "Old Dynarec" + IDS_2165 "New Dynarec" + IDS_2166 "Video card #2 ""%hs"" is not available due to missing ROMs in the roms/video directory. Disabling the second video card." + IDS_2167 "Failed to initialize network driver" + IDS_2168 "The network configuration will be switched to the null driver" END -STRINGTABLE DISCARDABLE +STRINGTABLE DISCARDABLE BEGIN IDS_4096 "Hard disk (%s)" - IDS_4097 "%01i:%01i" - IDS_4098 "%01i" - IDS_4099 "Le unità CD-ROM MFM/RLL o ESDI non sono mai esistite." - IDS_4100 "Personalizzata..." - IDS_4101 "Personalizzata (grande)..." - IDS_4102 "Aggiungi un nuovo disco rigido" - IDS_4103 "Aggiungi un disco rigido esistente" - IDS_4104 "Le immagini HDI non possono essere più grandi di 4 GB." - IDS_4105 "Le immmagini disco non possono essere più grandi di 127 GB." - IDS_4106 "Immagini disco rigido (*.HD?;*.IM?;*.VHD)\0*.HD?;*.IM?;*.VHD\0Tutti i file (*.*)\0*.*\0" - IDS_4107 "Impossibile leggere il file" - IDS_4108 "Impossibile scrivere al file" - IDS_4109 "Le immagini HDI o HDX con settori di dimensioni diverse da 512 non sono supportati." - IDS_4110 "USB non è ancora supportato" - IDS_4111 "Immagine disco già esiste" - IDS_4112 "Specifica un nome file valido." - IDS_4113 "Immagine disco creata" - IDS_4114 "Controlla che il file esiste e che sia leggibile." - IDS_4115 "Controlla che il file viene salvato ad un percorso con diritti di scrittura" - IDS_4116 "Immagine disco troppo grande" - IDS_4117 "Ricordati di partizionare e formattare il disco appena creato." - IDS_4118 "Il file selezionato sarà sovrascritto, sei sicuro di volerlo usare?" - IDS_4119 "Immagine disco non supportata" - IDS_4120 "Sovrascrivi" - IDS_4121 "Non sovrascrivere" - IDS_4122 "Immagine raw (.img)" - IDS_4123 "Immagine HDI (.hdi)" - IDS_4124 "Immagine HDX (.hdx)" - IDS_4125 "VHD di dimensioni fisse (.vhd)" - IDS_4126 "VHD di dimensioni dinamiche (.vhd)" - IDS_4127 "VHD differenziato (.vhd)" - IDS_4128 "Blocchi larghi (2 MB)" - IDS_4129 "Blocchi piccoli (512 KB)" - IDS_4130 "File VHD (*.VHD)\0*.VHD\0Tutti i file (*.*)\0*.*\0" - IDS_4131 "Seleziona il VHD padre." - IDS_4132 "Questo potrebbe significare che l'immagine padre sia stata modificata dopo la creazione dell'immagine di differenziazione.\n\nPuò anche succedere se i file immagini sono stati spostati o copiati, o da un errore nel programma che ha creato questo disco.\n\nVuoi aggiustare le marcature di tempo?" - IDS_4133 "Le marcature di tempo padre e figlio non corrispondono" - IDS_4134 "Impossibile aggiustare marcature di tempo VHD." - IDS_4135 "%01i:%02i" + IDS_4097 "%01i:%01i" + IDS_4098 "%01i" + IDS_4099 "Le unità CD-ROM MFM/RLL o ESDI non sono mai esistite." + IDS_4100 "Personalizzata..." + IDS_4101 "Personalizzata (grande)..." + IDS_4102 "Aggiungi un nuovo disco rigido" + IDS_4103 "Aggiungi un disco rigido esistente" + IDS_4104 "Le immagini HDI non possono essere più grandi di 4 GB." + IDS_4105 "Le immmagini disco non possono essere più grandi di 127 GB." + IDS_4106 "Immagini disco rigido (*.HD?;*.IM?;*.VHD)\0*.HD?;*.IM?;*.VHD\0Tutti i file (*.*)\0*.*\0" + IDS_4107 "Impossibile leggere il file" + IDS_4108 "Impossibile scrivere al file" + IDS_4109 "Le immagini HDI o HDX con settori di dimensioni diverse da 512 non sono supportati." + IDS_4110 "USB non è ancora supportato" + IDS_4111 "Immagine disco già esiste" + IDS_4112 "Specifica un nome file valido." + IDS_4113 "Immagine disco creata" + IDS_4114 "Controlla che il file esiste e che sia leggibile." + IDS_4115 "Controlla che il file viene salvato ad un percorso con diritti di scrittura" + IDS_4116 "Immagine disco troppo grande" + IDS_4117 "Ricordati di partizionare e formattare il disco appena creato." + IDS_4118 "Il file selezionato sarà sovrascritto, sei sicuro di volerlo usare?" + IDS_4119 "Immagine disco non supportata" + IDS_4120 "Sovrascrivi" + IDS_4121 "Non sovrascrivere" + IDS_4122 "Immagine raw (.img)" + IDS_4123 "Immagine HDI (.hdi)" + IDS_4124 "Immagine HDX (.hdx)" + IDS_4125 "VHD di dimensioni fisse (.vhd)" + IDS_4126 "VHD di dimensioni dinamiche (.vhd)" + IDS_4127 "VHD differenziato (.vhd)" + IDS_4128 "Blocchi larghi (2 MB)" + IDS_4129 "Blocchi piccoli (512 KB)" + IDS_4130 "File VHD (*.VHD)\0*.VHD\0Tutti i file (*.*)\0*.*\0" + IDS_4131 "Seleziona il VHD padre." + IDS_4132 "Questo potrebbe significare che l'immagine padre sia stata modificata dopo la creazione dell'immagine di differenziazione.\n\nPuò anche succedere se i file immagini sono stati spostati o copiati, o da un errore nel programma che ha creato questo disco.\n\nVuoi aggiustare le marcature di tempo?" + IDS_4133 "Le marcature di tempo padre e figlio non corrispondono" + IDS_4134 "Impossibile aggiustare marcature di tempo VHD." + IDS_4135 "%01i:%02i" IDS_4352 "MFM/RLL" IDS_4353 "XTA" @@ -563,56 +583,56 @@ BEGIN IDS_4356 "ATAPI" IDS_4357 "SCSI" - IDS_4608 "MFM/RLL (%01i:%01i)" - IDS_4609 "XTA (%01i:%01i)" - IDS_4610 "ESDI (%01i:%01i)" - IDS_4611 "IDE (%01i:%01i)" - IDS_4612 "ATAPI (%01i:%01i)" - IDS_4613 "SCSI (%01i:%02i)" + IDS_4608 "MFM/RLL (%01i:%01i)" + IDS_4609 "XTA (%01i:%01i)" + IDS_4610 "ESDI (%01i:%01i)" + IDS_4611 "IDE (%01i:%01i)" + IDS_4612 "ATAPI (%01i:%01i)" + IDS_4613 "SCSI (%01i:%02i)" - IDS_5120 "CD-ROM %i (%s): %s" + IDS_5120 "CD-ROM %i (%s): %s" - IDS_5376 "Disabilitato" - IDS_5381 "ATAPI" + IDS_5376 "Disabilitato" + IDS_5381 "ATAPI" IDS_5382 "SCSI" - IDS_5632 "Disabilitato" - IDS_5637 "ATAPI (%01i:%01i)" + IDS_5632 "Disabilitato" + IDS_5637 "ATAPI (%01i:%01i)" IDS_5638 "SCSI (%01i:%02i)" - IDS_5888 "160 kB" - IDS_5889 "180 kB" - IDS_5890 "320 kB" - IDS_5891 "360 kB" - IDS_5892 "640 kB" - IDS_5893 "720 kB" - IDS_5894 "1.2 MB" - IDS_5895 "1.25 MB" - IDS_5896 "1.44 MB" - IDS_5897 "DMF (cluster 1024)" - IDS_5898 "DMF (cluster 2048)" - IDS_5899 "2.88 MB" - IDS_5900 "ZIP 100" - IDS_5901 "ZIP 250" - IDS_5902 "3.5"" 128 MB (ISO 10090)" - IDS_5903 "3.5"" 230 MB (ISO 13963)" - IDS_5904 "3.5"" 540 MB (ISO 15498)" - IDS_5905 "3.5"" 640 MB (ISO 15498)" - IDS_5906 "3.5"" 1.3 GB (GigaMO)" - IDS_5907 "3.5"" 2.3 GB (GigaMO 2)" - IDS_5908 "5.25"" 600 MB" - IDS_5909 "5.25"" 650 MB" - IDS_5910 "5.25"" 1 GB" - IDS_5911 "5.25"" 1.3 GB" + IDS_5888 "160 kB" + IDS_5889 "180 kB" + IDS_5890 "320 kB" + IDS_5891 "360 kB" + IDS_5892 "640 kB" + IDS_5893 "720 kB" + IDS_5894 "1.2 MB" + IDS_5895 "1.25 MB" + IDS_5896 "1.44 MB" + IDS_5897 "DMF (cluster 1024)" + IDS_5898 "DMF (cluster 2048)" + IDS_5899 "2.88 MB" + IDS_5900 "ZIP 100" + IDS_5901 "ZIP 250" + IDS_5902 "3.5"" 128 MB (ISO 10090)" + IDS_5903 "3.5"" 230 MB (ISO 13963)" + IDS_5904 "3.5"" 540 MB (ISO 15498)" + IDS_5905 "3.5"" 640 MB (ISO 15498)" + IDS_5906 "3.5"" 1.3 GB (GigaMO)" + IDS_5907 "3.5"" 2.3 GB (GigaMO 2)" + IDS_5908 "5.25"" 600 MB" + IDS_5909 "5.25"" 650 MB" + IDS_5910 "5.25"" 1 GB" + IDS_5911 "5.25"" 1.3 GB" - IDS_6144 "RPM perfette" - IDS_6145 "RPM 1% sotto perfezione" - IDS_6146 "RPM 1.5% sotto perfezione" - IDS_6147 "RPM 2% sotto perfezione" + IDS_6144 "RPM perfette" + IDS_6145 "RPM 1% sotto perfezione" + IDS_6146 "RPM 1.5% sotto perfezione" + IDS_6147 "RPM 2% sotto perfezione" - IDS_7168 "(Predefinito del sistema)" + IDS_7168 "(Predefinito del sistema)" END -#define IDS_LANG_ENUS IDS_7168 +#define IDS_LANG_ENUS IDS_7168 // Italian (IT-it) resources ///////////////////////////////////////////////////////////////////////////// diff --git a/src/win/languages/ja-JP.rc b/src/win/languages/ja-JP.rc index 3917f59c4..bf9509453 100644 --- a/src/win/languages/ja-JP.rc +++ b/src/win/languages/ja-JP.rc @@ -13,113 +13,122 @@ LANGUAGE LANG_JAPANESE, SUBLANG_DEFAULT // Menu // -MainMenu MENU DISCARDABLE +MainMenu MENU DISCARDABLE BEGIN - POPUP "動作(&A)" + POPUP "æ“作(&A)" BEGIN - MENUITEM "キーボードã¯ã‚­ãƒ£ãƒ—ãƒãƒ£ãŒå¿…è¦(&K)", IDM_ACTION_KBD_REQ_CAPTURE - MENUITEM "å³CTRLã‚’å·¦ALTã¸(&R)", IDM_ACTION_RCTRL_IS_LALT + MENUITEM "キーボードã¯ã‚­ãƒ£ãƒ—ãƒãƒ£ãŒå¿…è¦(&K)", IDM_ACTION_KBD_REQ_CAPTURE + MENUITEM "å³CTRLã‚’å·¦ALTã¸å¤‰æ›(&R)", IDM_ACTION_RCTRL_IS_LALT MENUITEM SEPARATOR - MENUITEM "ãƒãƒ¼ãƒ‰ãƒªã‚»ãƒƒãƒˆ(&H)...", IDM_ACTION_HRESET - MENUITEM "Ctrl+Alt+Del(&C)\tCtrl+F12", IDM_ACTION_RESET_CAD + MENUITEM "ãƒãƒ¼ãƒ‰ リセット(&H)...", IDM_ACTION_HRESET + MENUITEM "Ctrl+Alt+Del(&C)\tCtrl+F12", IDM_ACTION_RESET_CAD MENUITEM SEPARATOR - MENUITEM "Ctrl+Alt+Esc(&E)", IDM_ACTION_CTRL_ALT_ESC + MENUITEM "Ctrl+Alt+Esc(&E)", IDM_ACTION_CTRL_ALT_ESC MENUITEM SEPARATOR - MENUITEM "ä¸€æ™‚åœæ­¢(&P)", IDM_ACTION_PAUSE + MENUITEM "ä¸€æ™‚åœæ­¢(&P)", IDM_ACTION_PAUSE MENUITEM SEPARATOR - MENUITEM "終了(&X)...", IDM_ACTION_EXIT + MENUITEM "終了(&X)...", IDM_ACTION_EXIT END POPUP "表示(&V)" BEGIN - MENUITEM "ステータスãƒãƒ¼ã‚’éš ã™(&H)", IDM_VID_HIDE_STATUS_BAR - MENUITEM "ツールãƒãƒ¼ã‚’éš ã™(&T)", IDM_VID_HIDE_TOOLBAR + MENUITEM "ステータスãƒãƒ¼ã‚’éš ã™(&H)", IDM_VID_HIDE_STATUS_BAR + MENUITEM "ツールãƒãƒ¼ã‚’éš ã™(&T)", IDM_VID_HIDE_TOOLBAR MENUITEM SEPARATOR - MENUITEM "ウィンドウã®ã‚µã‚¤ã‚ºã‚’リサイズå¯èƒ½(&R)", IDM_VID_RESIZE - MENUITEM "ウィンドウã®ã‚µã‚¤ã‚ºã¨ä½ç½®ã‚’記憶(&E)", IDM_VID_REMEMBER + MENUITEM "プライマリ以外ã®ãƒ¢ãƒ‹ã‚¿ãƒ¼ã‚’表示(&S)", IDM_VID_MONITORS + MENUITEM "ウィンドウã®ã‚µã‚¤ã‚ºã‚’変更å¯èƒ½(&R)", IDM_VID_RESIZE + MENUITEM "ウィンドウã®ã‚µã‚¤ã‚ºã¨ä½ç½®ã‚’ä¿å­˜(&E)", IDM_VID_REMEMBER MENUITEM SEPARATOR POPUP "レンダラー(&N)" BEGIN - MENUITEM "SDL (ソフトウェア)(&S)", IDM_VID_SDL_SW - MENUITEM "SDL (ãƒãƒ¼ãƒ‰ã‚¦ã‚§ã‚¢)(&H)", IDM_VID_SDL_HW - MENUITEM "SDL (OpenGL)(&O)", IDM_VID_SDL_OPENGL - MENUITEM "OpenGL (3.0コア)(&G)", IDM_VID_OPENGL_CORE + MENUITEM "SDL (ソフトウェア)(&S)", IDM_VID_SDL_SW + MENUITEM "SDL (ãƒãƒ¼ãƒ‰ã‚¦ã‚§ã‚¢)(&H)", IDM_VID_SDL_HW + MENUITEM "SDL (OpenGL)(&O)", IDM_VID_SDL_OPENGL + MENUITEM "OpenGL (3.0コア)(&G)", IDM_VID_OPENGL_CORE #ifdef USE_VNC - MENUITEM "VNC(&V)", IDM_VID_VNC + MENUITEM "VNC(&V)", IDM_VID_VNC #endif END MENUITEM SEPARATOR - MENUITEM "ウィンドウã®ã‚µã‚¤ã‚ºã‚’指定...", IDM_VID_SPECIFY_DIM - MENUITEM "4:3アスペクト比を固定(&O)", IDM_VID_FORCE43 + MENUITEM "ディメンションを指定...", IDM_VID_SPECIFY_DIM + MENUITEM "4:3ã®ç¸¦æ¨ªæ¯”を強制表示(&O)", IDM_VID_FORCE43 POPUP "ウィンドウã®è¡¨ç¤ºå€çއ(&W)" BEGIN - MENUITEM "0.5x(&0)", IDM_VID_SCALE_1X - MENUITEM "1x(&1)", IDM_VID_SCALE_2X - MENUITEM "1.5x(&5)", IDM_VID_SCALE_3X - MENUITEM "2x(&2)", IDM_VID_SCALE_4X + MENUITEM "0.5x(&0)", IDM_VID_SCALE_1X + MENUITEM "1x(&1)", IDM_VID_SCALE_2X + MENUITEM "1.5x(&5)", IDM_VID_SCALE_3X + MENUITEM "2x(&2)", IDM_VID_SCALE_4X + MENUITEM "&3x", IDM_VID_SCALE_5X + MENUITEM "&4x", IDM_VID_SCALE_6X + MENUITEM "&5x", IDM_VID_SCALE_7X + MENUITEM "&6x", IDM_VID_SCALE_8X + MENUITEM "&7x", IDM_VID_SCALE_9X + MENUITEM "&8x", IDM_VID_SCALE_10X END POPUP "フィルター方å¼" BEGIN - MENUITEM "最近å‚補間(&N)", IDM_VID_FILTER_NEAREST - MENUITEM "線形補間(&L)", IDM_VID_FILTER_LINEAR + MENUITEM "最近å‚補間(&N)", IDM_VID_FILTER_NEAREST + MENUITEM "線形補間(&L)", IDM_VID_FILTER_LINEAR END - MENUITEM "HiDPIスケーリング(&D)", IDM_VID_HIDPI + MENUITEM "HiDPIスケーリング(&D)", IDM_VID_HIDPI MENUITEM SEPARATOR - MENUITEM "フルスクリーン(&F)\tCtrl+Alt+PgUp", IDM_VID_FULLSCREEN - POPUP "フルスクリーンã®ã‚¹ã‚±ãƒ¼ãƒ«(&S)" + MENUITEM "全画é¢è¡¨ç¤º(&F)\tCtrl+Alt+PgUp", IDM_VID_FULLSCREEN + POPUP "全画é¢ã®æ‹¡å¤§è¡¨ç¤ºãƒ¢ãƒ¼ãƒ‰(&S)" BEGIN - MENUITEM "ãƒ•ãƒ«ã‚¹ã‚¯ãƒªãƒ¼ãƒ³ã«æ‹¡å¤§(&F)", IDM_VID_FS_FULL - MENUITEM "4:3(&4)", IDM_VID_FS_43 + MENUITEM "ストレッムモード(&F)", IDM_VID_FS_FULL + MENUITEM "4:3(&4)", IDM_VID_FS_43 MENUITEM "正方形ピクセル(アスペクト比を維æŒ)(&S)", IDM_VID_FS_KEEPRATIO - MENUITEM "æ•´æ•°å€(&I)", IDM_VID_FS_INT + MENUITEM "æ•´æ•°å€(&I)", IDM_VID_FS_INT END POPUP "E&GA/(S)VGAã®è¨­å®š" BEGIN - MENUITEM "色をå転(&I)", IDM_VID_INVERT + MENUITEM "色å転(&I)", IDM_VID_INVERT POPUP "ç”»é¢ã‚¿ã‚¤ãƒ—(&T)" BEGIN - MENUITEM "RGB(カラー)(&C)", IDM_VID_GRAY_RGB - MENUITEM "RGB(グレースケール)(&R)", IDM_VID_GRAY_MONO - MENUITEM "モニター(ç¥ç€è‰²)(&A)", IDM_VID_GRAY_AMBER - MENUITEM "モニター(緑色)(&G)", IDM_VID_GRAY_GREEN - MENUITEM "モニター(白色)(&W)", IDM_VID_GRAY_WHITE + MENUITEM "RGB(カラー)(&C)", IDM_VID_GRAY_RGB + MENUITEM "RGB(グレースケール)(&R)", IDM_VID_GRAY_MONO + MENUITEM "モニター(黄色)(&A)", IDM_VID_GRAY_AMBER + MENUITEM "モニター(緑色)(&G)", IDM_VID_GRAY_GREEN + MENUITEM "モニター(白色)(&W)", IDM_VID_GRAY_WHITE END POPUP "グレースケール変æ›ã‚¿ã‚¤ãƒ—(&C)" BEGIN - MENUITEM "BT601 (NTSC/PAL)(&6)", IDM_VID_GRAYCT_601 - MENUITEM "BT709 (HDTV)(&7)", IDM_VID_GRAYCT_709 - MENUITEM "å¹³å‡(&A)", IDM_VID_GRAYCT_AVE + MENUITEM "BT601 (NTSC/PAL)(&6)", IDM_VID_GRAYCT_601 + MENUITEM "BT709 (HDTV)(&7)", IDM_VID_GRAYCT_709 + MENUITEM "å¹³å‡(&A)", IDM_VID_GRAYCT_AVE END END MENUITEM SEPARATOR - MENUITEM "CGA/PCjr/Tandy/EGA/(S)VGAオーãƒãƒ¼ã‚¹ã‚­ãƒ£ãƒ³(&G)", IDM_VID_OVERSCAN + MENUITEM "CGA/PCjr/Tandy/EGA/(S)VGAオーãƒãƒ¼ã‚¹ã‚­ãƒ£ãƒ³(&G)", IDM_VID_OVERSCAN MENUITEM "å˜è‰²ãƒ¢ãƒ‹ã‚¿ãƒ¼ç”¨ã‚³ãƒ³ãƒˆãƒ©ã‚¹ãƒˆã‚’変更(&M)", IDM_VID_CGACON END - MENUITEM "メディア(&M)", IDM_MEDIA + MENUITEM "メディア(&M)", IDM_MEDIA POPUP "ツール(&T)" BEGIN - MENUITEM "設定(&S)...", IDM_CONFIG - MENUITEM "ステータスãƒãƒ¼ã®ã‚¢ã‚¤ã‚³ãƒ³ã‚’æ›´æ–°(&U)", IDM_UPDATE_ICONS + MENUITEM "設定(&S)...", IDM_CONFIG + MENUITEM "ステータスãƒãƒ¼ã®ã‚¢ã‚¤ã‚³ãƒ³ã‚’æ›´æ–°(&U)", IDM_UPDATE_ICONS MENUITEM SEPARATOR - MENUITEM "スクリーンショットを撮る(&C)\tCtrl+F11", IDM_ACTION_SCREENSHOT + MENUITEM "スクリーンショットを撮る(&C)\tCtrl+F11", IDM_ACTION_SCREENSHOT MENUITEM SEPARATOR - MENUITEM "環境設定(&P)...", IDM_PREFERENCES - MENUITEM "Discordã¨ã®é€£æºæ©Ÿèƒ½(&D)", IDM_DISCORD + MENUITEM "環境設定(&P)...", IDM_PREFERENCES +#ifdef DISCORD + MENUITEM "Discordé€£æºæ©Ÿèƒ½(&D)", IDM_DISCORD +#endif MENUITEM SEPARATOR - MENUITEM "音é‡ã‚’調節(&G)...", IDM_SND_GAIN + MENUITEM "音é‡èª¿æ•´(&G)...", IDM_SND_GAIN #ifdef MTR_ENABLED MENUITEM SEPARATOR - MENUITEM "トレース開始\tCtrl+T", IDM_ACTION_BEGIN_TRACE - MENUITEM "トレース終了\tCtrl+T", IDM_ACTION_END_TRACE + MENUITEM "トレース開始\tCtrl+T", IDM_ACTION_BEGIN_TRACE + MENUITEM "トレース終了\tCtrl+T", IDM_ACTION_END_TRACE #endif END POPUP "ヘルプ(&H)" BEGIN - MENUITEM "ドキュメント(&D)...", IDM_DOCS - MENUITEM "86Boxã®ãƒãƒ¼ã‚¸ãƒ§ãƒ³æƒ…å ±(&A)...", IDM_ABOUT + MENUITEM "文書(&D)...", IDM_DOCS + MENUITEM "86Boxã®ãƒãƒ¼ã‚¸ãƒ§ãƒ³æƒ…å ±(&A)...", IDM_ABOUT END END -StatusBarMenu MENU DISCARDABLE +StatusBarMenu MENU DISCARDABLE BEGIN MENUITEM SEPARATOR END @@ -128,17 +137,17 @@ CassetteSubmenu MENU DISCARDABLE BEGIN POPUP "" BEGIN - MENUITEM "æ–°è¦ã‚¤ãƒ¡ãƒ¼ã‚¸(&N)...", IDM_CASSETTE_IMAGE_NEW + MENUITEM "æ–°è¦ã‚¤ãƒ¡ãƒ¼ã‚¸(&N)...", IDM_CASSETTE_IMAGE_NEW MENUITEM SEPARATOR - MENUITEM "既存ã®ã‚¤ãƒ¡ãƒ¼ã‚¸ã‚’é–‹ã(&E)...", IDM_CASSETTE_IMAGE_EXISTING - MENUITEM "既存ã®ã‚¤ãƒ¡ãƒ¼ã‚¸ã‚’é–‹ã(書ãè¾¼ã¿ä¿è­·)(&W)...", IDM_CASSETTE_IMAGE_EXISTING_WP + MENUITEM "既存ã®ã‚¤ãƒ¡ãƒ¼ã‚¸ã‚’é–‹ã(&E)...", IDM_CASSETTE_IMAGE_EXISTING + MENUITEM "既存ã®ã‚¤ãƒ¡ãƒ¼ã‚¸ã‚’é–‹ã(書ãè¾¼ã¿ç¦æ­¢)(&W)...", IDM_CASSETTE_IMAGE_EXISTING_WP MENUITEM SEPARATOR - MENUITEM "録音(&R)", IDM_CASSETTE_RECORD - MENUITEM "å†ç”Ÿ(&P)", IDM_CASSETTE_PLAY - MENUITEM "冒頭ã«å·»ã戻ã™(&R)", IDM_CASSETTE_REWIND - MENUITEM "最後ã¾ã§æ—©é€ã‚Š(&F)", IDM_CASSETTE_FAST_FORWARD + MENUITEM "記録(&R)", IDM_CASSETTE_RECORD + MENUITEM "å†ç”Ÿ(&P)", IDM_CASSETTE_PLAY + MENUITEM "先頭ã¾ã§å·»ã戻ã™(&R)", IDM_CASSETTE_REWIND + MENUITEM "最後ã¾ã§æ—©é€ã‚Š(&F)", IDM_CASSETTE_FAST_FORWARD MENUITEM SEPARATOR - MENUITEM "å–り出ã™(&J)", IDM_CASSETTE_EJECT + MENUITEM "å–り出ã™(&J)", IDM_CASSETTE_EJECT END END @@ -146,9 +155,9 @@ CartridgeSubmenu MENU DISCARDABLE BEGIN POPUP "" BEGIN - MENUITEM "イメージ(&I)...", IDM_CARTRIDGE_IMAGE + MENUITEM "イメージ(&I)...", IDM_CARTRIDGE_IMAGE MENUITEM SEPARATOR - MENUITEM "å–り出ã™(&J)", IDM_CARTRIDGE_EJECT + MENUITEM "å–り出ã™(&J)", IDM_CARTRIDGE_EJECT END END @@ -156,14 +165,14 @@ FloppySubmenu MENU DISCARDABLE BEGIN POPUP "" BEGIN - MENUITEM "æ–°è¦ã‚¤ãƒ¡ãƒ¼ã‚¸(&N)...", IDM_FLOPPY_IMAGE_NEW + MENUITEM "æ–°è¦ã‚¤ãƒ¡ãƒ¼ã‚¸(&N)...", IDM_FLOPPY_IMAGE_NEW MENUITEM SEPARATOR - MENUITEM "既存ã®ã‚¤ãƒ¡ãƒ¼ã‚¸ã‚’é–‹ã(&E)...", IDM_FLOPPY_IMAGE_EXISTING - MENUITEM "既存ã®ã‚¤ãƒ¡ãƒ¼ã‚¸ã‚’é–‹ã(書ãè¾¼ã¿ä¿è­·)(&W)...", IDM_FLOPPY_IMAGE_EXISTING_WP + MENUITEM "既存ã®ã‚¤ãƒ¡ãƒ¼ã‚¸ã‚’é–‹ã(&E)...", IDM_FLOPPY_IMAGE_EXISTING + MENUITEM "既存ã®ã‚¤ãƒ¡ãƒ¼ã‚¸ã‚’é–‹ã(書ãè¾¼ã¿ç¦æ­¢)(&W)...", IDM_FLOPPY_IMAGE_EXISTING_WP MENUITEM SEPARATOR - MENUITEM "86Fイメージã«ã‚¨ã‚¯ã‚¹ãƒãƒ¼ãƒˆ(&X)...", IDM_FLOPPY_EXPORT_TO_86F + MENUITEM "86Fイメージã«ã‚¨ã‚¯ã‚¹ãƒãƒ¼ãƒˆ(&X)...", IDM_FLOPPY_EXPORT_TO_86F MENUITEM SEPARATOR - MENUITEM "å–り出ã™(&J)", IDM_FLOPPY_EJECT + MENUITEM "å–り出ã™(&J)", IDM_FLOPPY_EJECT END END @@ -171,12 +180,13 @@ CdromSubmenu MENU DISCARDABLE BEGIN POPUP "" BEGIN - MENUITEM "ミュート(&M)", IDM_CDROM_MUTE + MENUITEM "ミュート(&M)", IDM_CDROM_MUTE MENUITEM SEPARATOR - MENUITEM "空(&M)", IDM_CDROM_EMPTY - MENUITEM "å‰ã®ã‚¤ãƒ¡ãƒ¼ã‚¸ã‚’å†èª­ã¿è¾¼ã¿(&R)", IDM_CDROM_RELOAD + MENUITEM "空(&M)", IDM_CDROM_EMPTY + MENUITEM "å‰ã®ã‚¤ãƒ¡ãƒ¼ã‚¸ã‚’å†èª­ã¿è¾¼ã¿(&R)", IDM_CDROM_RELOAD MENUITEM SEPARATOR - MENUITEM "イメージ(&I)", IDM_CDROM_IMAGE + MENUITEM "イメージ(&I)...", IDM_CDROM_IMAGE + MENUITEM "フォルダ(&F)...", IDM_CDROM_DIR END END @@ -184,13 +194,13 @@ ZIPSubmenu MENU DISCARDABLE BEGIN POPUP "" BEGIN - MENUITEM "æ–°è¦ã‚¤ãƒ¡ãƒ¼ã‚¸(&N)...", IDM_ZIP_IMAGE_NEW + MENUITEM "æ–°è¦ã‚¤ãƒ¡ãƒ¼ã‚¸(&N)...", IDM_ZIP_IMAGE_NEW MENUITEM SEPARATOR - MENUITEM "既存ã®ã‚¤ãƒ¡ãƒ¼ã‚¸ã‚’é–‹ã(&E)...", IDM_ZIP_IMAGE_EXISTING - MENUITEM "既存ã®ã‚¤ãƒ¡ãƒ¼ã‚¸ã‚’é–‹ã(書ãè¾¼ã¿ä¿è­·)(&W)...", IDM_ZIP_IMAGE_EXISTING_WP + MENUITEM "既存ã®ã‚¤ãƒ¡ãƒ¼ã‚¸ã‚’é–‹ã(&E)...", IDM_ZIP_IMAGE_EXISTING + MENUITEM "既存ã®ã‚¤ãƒ¡ãƒ¼ã‚¸ã‚’é–‹ã(書ãè¾¼ã¿ç¦æ­¢)(&W)...", IDM_ZIP_IMAGE_EXISTING_WP MENUITEM SEPARATOR - MENUITEM "å–り出ã™(&J)", IDM_ZIP_EJECT - MENUITEM "å‰ã®ã‚¤ãƒ¡ãƒ¼ã‚¸ã‚’å†èª­ã¿è¾¼ã¿(&R)", IDM_ZIP_RELOAD + MENUITEM "å–り出ã™(&J)", IDM_ZIP_EJECT + MENUITEM "å‰ã®ã‚¤ãƒ¡ãƒ¼ã‚¸ã‚’å†èª­ã¿è¾¼ã¿(&R)", IDM_ZIP_RELOAD END END @@ -198,13 +208,13 @@ MOSubmenu MENU DISCARDABLE BEGIN POPUP "" BEGIN - MENUITEM "æ–°è¦ã‚¤ãƒ¡ãƒ¼ã‚¸(&N)...", IDM_MO_IMAGE_NEW + MENUITEM "æ–°è¦ã‚¤ãƒ¡ãƒ¼ã‚¸(&N)...", IDM_MO_IMAGE_NEW MENUITEM SEPARATOR - MENUITEM "既存ã®ã‚¤ãƒ¡ãƒ¼ã‚¸ã‚’é–‹ã(&E)...", IDM_MO_IMAGE_EXISTING - MENUITEM "既存ã®ã‚¤ãƒ¡ãƒ¼ã‚¸ã‚’é–‹ã(書ãè¾¼ã¿ä¿è­·)(&W)...", IDM_MO_IMAGE_EXISTING_WP + MENUITEM "既存ã®ã‚¤ãƒ¡ãƒ¼ã‚¸ã‚’é–‹ã(&E)...", IDM_MO_IMAGE_EXISTING + MENUITEM "既存ã®ã‚¤ãƒ¡ãƒ¼ã‚¸ã‚’é–‹ã(書ãè¾¼ã¿ç¦æ­¢)(&W)...", IDM_MO_IMAGE_EXISTING_WP MENUITEM SEPARATOR - MENUITEM "å–り出ã™(&J)", IDM_MO_EJECT - MENUITEM "å‰ã®ã‚¤ãƒ¡ãƒ¼ã‚¸ã‚’å†èª­ã¿è¾¼ã¿(&R)", IDM_MO_RELOAD + MENUITEM "å–り出ã™(&J)", IDM_MO_EJECT + MENUITEM "å‰ã®ã‚¤ãƒ¡ãƒ¼ã‚¸ã‚’å†èª­ã¿è¾¼ã¿(&R)", IDM_MO_RELOAD END END @@ -230,134 +240,150 @@ END // Dialog // -#define STR_PREFERENCES "環境設定" -#define STR_SND_GAIN "音é‡ã‚²ã‚¤ãƒ³" -#define STR_NEW_FLOPPY "æ–°è¦ã®ã‚¤ãƒ¡ãƒ¼ã‚¸" -#define STR_CONFIG "設定" -#define STR_SPECIFY_DIM "メインウィンドウã®ã‚µã‚¤ã‚ºæŒ‡å®š" +#define STR_PREFERENCES "環境設定" +#define STR_SND_GAIN "音é‡èª¿æ•´" +#define STR_NEW_FLOPPY "æ–°è¦ã®ã‚¤ãƒ¡ãƒ¼ã‚¸" +#define STR_CONFIG "設定" +#define STR_SPECIFY_DIM "メイン ウィンドウã®ã‚µã‚¤ã‚ºæŒ‡å®š" -#define STR_OK "OK" -#define STR_CANCEL "キャンセル" -#define STR_GLOBAL "ã“れらã®è¨­å®šã‚’グローãƒãƒ«æ—¢å®šå€¤ã¨ã—ã¦ä¿å­˜ã™ã‚‹(&G)" -#define STR_DEFAULT "既定値(&D)" -#define STR_LANGUAGE "言語:" -#define STR_ICONSET "アイコンセット:" +#define STR_OK "OK" +#define STR_CANCEL "キャンセル" +#define STR_GLOBAL "ã“れらã®è¨­å®šã‚’グローãƒãƒ«æ—¢å®šå€¤ã¨ã—ã¦ä¿å­˜(&G)" +#define STR_DEFAULT "既定値(&D)" +#define STR_LANGUAGE "言語:" +#define STR_ICONSET "アイコン セット:" -#define STR_GAIN "ゲイン値" +#define STR_GAIN "音é‡" -#define STR_FILE_NAME "ファイルå:" -#define STR_DISK_SIZE "ディスクサイズ:" -#define STR_RPM_MODE "回転数モード:" -#define STR_PROGRESS "進行状æ³:" +#define STR_FILE_NAME "ファイルå:" +#define STR_DISK_SIZE "ディスク サイズ:" +#define STR_RPM_MODE "RPMモード:" +#define STR_PROGRESS "進行状æ³:" -#define STR_WIDTH "å¹…:" -#define STR_HEIGHT "高ã•:" -#define STR_LOCK_TO_SIZE "ã“ã®ã‚µã‚¤ã‚ºã‚’ロックã™ã‚‹" +#define STR_WIDTH "å¹…:" +#define STR_HEIGHT "高ã•:" +#define STR_LOCK_TO_SIZE "サイズを固定" -#define STR_MACHINE_TYPE "マシンタイプ:" -#define STR_MACHINE "マシン:" -#define STR_CONFIGURE "設定" -#define STR_CPU_TYPE "CPUタイプ:" -#define STR_CPU_SPEED "速度:" -#define STR_FPU "FPU:" -#define STR_WAIT_STATES "待機状態:" -#define STR_MB "MB" -#define STR_MEMORY "メモリ:" -#define STR_TIME_SYNC "æ™‚åˆ»åŒæœŸæ©Ÿèƒ½" -#define STR_DISABLED "無効ã«ã™ã‚‹" -#define STR_ENABLED_LOCAL "有効ã«ã™ã‚‹ (ç¾åœ°æ™‚é–“)" -#define STR_ENABLED_UTC "有効ã«ã™ã‚‹ (UTC)" -#define STR_DYNAREC "動的リコンパイラ" +#define STR_MACHINE_TYPE "マシン タイプ:" +#define STR_MACHINE "マシン:" +#define STR_CONFIGURE "設定" +#define STR_CPU_TYPE "CPUタイプ:" +#define STR_CPU_SPEED "速度:" +#define STR_FPU "FPU:" +#define STR_WAIT_STATES "ウェイト ステート:" +#define STR_MB "MB" +#define STR_MEMORY "メモリ:" +#define STR_TIME_SYNC "æ™‚åˆ»åŒæœŸæ©Ÿèƒ½" +#define STR_DISABLED "無効" +#define STR_ENABLED_LOCAL "有効(ç¾åœ°æ™‚é–“)" +#define STR_ENABLED_UTC "有効(UTC)" +#define STR_DYNAREC "å‹•çš„å†ã‚³ãƒ³ãƒ‘イル" +#define STR_SOFTFLOAT "Softfloat FPU" -#define STR_VIDEO "ビデオカード:" -#define STR_VOODOO "Voodooグラフィック" +#define STR_VIDEO "ビデオカード:" +#define STR_VIDEO_2 "ビデオカード2:" +#define STR_VOODOO "Voodooグラフィック" +#define STR_IBM8514 "IBM 8514/aグラフィック" +#define STR_XGA "XGAグラフィック" -#define STR_MOUSE "マウス:" -#define STR_JOYSTICK "ジョイスティック:" -#define STR_JOY1 "ジョイスティック1..." -#define STR_JOY2 "ジョイスティック2..." -#define STR_JOY3 "ジョイスティック3..." -#define STR_JOY4 "ジョイスティック4..." +#define STR_MOUSE "マウス:" +#define STR_JOYSTICK "ジョイスティック:" +#define STR_JOY1 "ジョイスティック1..." +#define STR_JOY2 "ジョイスティック2..." +#define STR_JOY3 "ジョイスティック3..." +#define STR_JOY4 "ジョイスティック4..." -#define STR_SOUND "サウンドカード:" -#define STR_MIDI_OUT "MIDI出力デãƒã‚¤ã‚¹:" -#define STR_MIDI_IN "MIDI入力デãƒã‚¤ã‚¹:" -#define STR_MPU401 "独立型MPU-401" -#define STR_SSI "Innovation SSI-2001" -#define STR_CMS "CMS / Game Blaster" -#define STR_GUS "Gravis Ultrasound" -#define STR_FLOAT "FLOAT32サウンドを使用ã™ã‚‹" +#define STR_SOUND1 "サウンド カード1:" +#define STR_SOUND2 "サウンド カード2:" +#define STR_SOUND3 "サウンド カード3:" +#define STR_SOUND4 "サウンド カード4:" +#define STR_MIDI_OUT "MIDI出力デãƒã‚¤ã‚¹:" +#define STR_MIDI_IN "MIDI入力デãƒã‚¤ã‚¹:" +#define STR_MPU401 "独立型MPU-401" +#define STR_FLOAT "FLOAT32サウンドを使用" +#define STR_FM_DRIVER "FMシンセドライãƒãƒ¼" +#define STR_FM_DRV_NUKED "Nuked(高精度化)" +#define STR_FM_DRV_YMFM "YMFM(より速ã)" -#define STR_NET_TYPE "ãƒãƒƒãƒˆãƒ¯ãƒ¼ã‚¯ã‚¿ã‚¤ãƒ—:" -#define STR_PCAP "PCapデãƒã‚¤ã‚¹:" -#define STR_NET "ãƒãƒƒãƒˆãƒ¯ãƒ¼ã‚¯ã‚¢ãƒ€ãƒ—ター:" +#define STR_NET_TYPE "ãƒãƒƒãƒˆãƒ¯ãƒ¼ã‚¯ã‚¿ã‚¤ãƒ—:" +#define STR_PCAP "PCapデãƒã‚¤ã‚¹:" +#define STR_NET "ãƒãƒƒãƒˆãƒ¯ãƒ¼ã‚¯ã‚¢ãƒ€ãƒ—ター:" +#define STR_NET1 "ãƒãƒƒãƒˆãƒ¯ãƒ¼ã‚¯ カード1:" +#define STR_NET2 "ãƒãƒƒãƒˆãƒ¯ãƒ¼ã‚¯ カード2:" +#define STR_NET3 "ãƒãƒƒãƒˆãƒ¯ãƒ¼ã‚¯ カード3:" +#define STR_NET4 "ãƒãƒƒãƒˆãƒ¯ãƒ¼ã‚¯ カード4:" -#define STR_COM1 "COM1デãƒã‚¤ã‚¹:" -#define STR_COM2 "COM2デãƒã‚¤ã‚¹:" -#define STR_COM3 "COM3デãƒã‚¤ã‚¹:" -#define STR_COM4 "COM4デãƒã‚¤ã‚¹:" -#define STR_LPT1 "LPT1デãƒã‚¤ã‚¹:" -#define STR_LPT2 "LPT2デãƒã‚¤ã‚¹:" -#define STR_LPT3 "LPT3デãƒã‚¤ã‚¹:" -#define STR_LPT4 "LPT4デãƒã‚¤ã‚¹:" -#define STR_SERIAL1 "シリアルãƒãƒ¼ãƒˆ1" -#define STR_SERIAL2 "シリアルãƒãƒ¼ãƒˆ2" -#define STR_SERIAL3 "シリアルãƒãƒ¼ãƒˆ3" -#define STR_SERIAL4 "シリアルãƒãƒ¼ãƒˆ4" -#define STR_PARALLEL1 "パラレルãƒãƒ¼ãƒˆ1" -#define STR_PARALLEL2 "パラレルãƒãƒ¼ãƒˆ2" -#define STR_PARALLEL3 "パラレルãƒãƒ¼ãƒˆ3" -#define STR_PARALLEL4 "パラレルãƒãƒ¼ãƒˆ4" +#define STR_COM1 "COM1デãƒã‚¤ã‚¹:" +#define STR_COM2 "COM2デãƒã‚¤ã‚¹:" +#define STR_COM3 "COM3デãƒã‚¤ã‚¹:" +#define STR_COM4 "COM4デãƒã‚¤ã‚¹:" +#define STR_LPT1 "LPT1デãƒã‚¤ã‚¹:" +#define STR_LPT2 "LPT2デãƒã‚¤ã‚¹:" +#define STR_LPT3 "LPT3デãƒã‚¤ã‚¹:" +#define STR_LPT4 "LPT4デãƒã‚¤ã‚¹:" +#define STR_SERIAL1 "シリアル ãƒãƒ¼ãƒˆ1" +#define STR_SERIAL2 "シリアル ãƒãƒ¼ãƒˆ2" +#define STR_SERIAL3 "シリアル ãƒãƒ¼ãƒˆ3" +#define STR_SERIAL4 "シリアル ãƒãƒ¼ãƒˆ4" +#define STR_PARALLEL1 "パラレル ãƒãƒ¼ãƒˆ1" +#define STR_PARALLEL2 "パラレル ãƒãƒ¼ãƒˆ2" +#define STR_PARALLEL3 "パラレル ãƒãƒ¼ãƒˆ3" +#define STR_PARALLEL4 "パラレル ãƒãƒ¼ãƒˆ4" +#define STR_SERIAL_PASS1 "シリアル ãƒãƒ¼ãƒˆ パススルー対応1" +#define STR_SERIAL_PASS2 "シリアル ãƒãƒ¼ãƒˆ パススルー対応2" +#define STR_SERIAL_PASS3 "シリアル ãƒãƒ¼ãƒˆ パススルー対応3" +#define STR_SERIAL_PASS4 "シリアル ãƒãƒ¼ãƒˆ パススルー対応4" -#define STR_HDC "HDコントローラー:" -#define STR_FDC "FDコントローラー:" -#define STR_IDE_TER "第三ã®IDEコントローラー" -#define STR_IDE_QUA "第四ã®IDEコントローラー" -#define STR_SCSI "SCSI" -#define STR_SCSI_1 "コントローラー1:" -#define STR_SCSI_2 "コントローラー2:" -#define STR_SCSI_3 "コントローラー3:" -#define STR_SCSI_4 "コントローラー4:" -#define STR_CASSETTE "カセット" +#define STR_HDC "HDDコントローラー:" +#define STR_FDC "FDDコントローラー:" +#define STR_IDE_TER "第三IDEコントローラー" +#define STR_IDE_QUA "第四IDEコントローラー" +#define STR_SCSI "SCSI" +#define STR_SCSI_1 "コントローラー1:" +#define STR_SCSI_2 "コントローラー2:" +#define STR_SCSI_3 "コントローラー3:" +#define STR_SCSI_4 "コントローラー4:" +#define STR_CASSETTE "カセット" -#define STR_HDD "ãƒãƒ¼ãƒ‰ãƒ‡ã‚£ã‚¹ã‚¯:" -#define STR_NEW "æ–°è¦(&N)..." -#define STR_EXISTING "既定(&E)..." -#define STR_REMOVE "除去(&R)" -#define STR_BUS "ãƒã‚¹:" -#define STR_CHANNEL "ãƒãƒ£ãƒ³ãƒãƒ«:" -#define STR_ID "ID:" +#define STR_HDD "ãƒãƒ¼ãƒ‰ ディスク:" +#define STR_NEW "æ–°è¦(&N)..." +#define STR_EXISTING "既定(&E)..." +#define STR_REMOVE "除去(&R)" +#define STR_BUS "ãƒã‚¹:" +#define STR_CHANNEL "ãƒãƒ£ãƒ³ãƒãƒ«:" +#define STR_ID "ID:" +#define STR_SPEED "速度:" -#define STR_SPECIFY "å‚ç…§(&S)..." -#define STR_SECTORS "セクター:" -#define STR_HEADS "ヘッド:" -#define STR_CYLS "シリンダー:" -#define STR_SIZE_MB "サイズ(MB):" -#define STR_TYPE "タイプ:" -#define STR_IMG_FORMAT "イメージ形å¼:" -#define STR_BLOCK_SIZE "ブロックサイズ:" +#define STR_SPECIFY "å‚ç…§(&S)..." +#define STR_SECTORS "セクター:" +#define STR_HEADS "ヘッド:" +#define STR_CYLS "シリンダー:" +#define STR_SIZE_MB "サイズ(MB):" +#define STR_TYPE "タイプ:" +#define STR_IMG_FORMAT "イメージ形å¼:" +#define STR_BLOCK_SIZE "ブロック サイズ:" -#define STR_FLOPPY_DRIVES "フロッピードライブ:" -#define STR_TURBO "高速タイミング" -#define STR_CHECKBPB "BPBã‚’ãƒã‚§ãƒƒã‚¯" -#define STR_CDROM_DRIVES "CD-ROMドライブ:" -#define STR_CD_SPEED "速度:" +#define STR_FLOPPY_DRIVES "フロッピー ドライブ:" +#define STR_TURBO "高速タイミング" +#define STR_CHECKBPB "BPBãƒã‚§ãƒƒã‚¯" +#define STR_CDROM_DRIVES "CD-ROMドライブ:" +#define STR_CD_SPEED "速度:" -#define STR_MO_DRIVES "å…‰ç£æ°—ドライブ:" -#define STR_ZIP_DRIVES "ZIPドライブ:" -#define STR_250 "ZIP 250" +#define STR_MO_DRIVES "å…‰ç£æ°—ドライブ:" +#define STR_ZIP_DRIVES "ZIPドライブ:" +#define STR_250 "ZIP 250" -#define STR_ISARTC "ISA RTCカード:" -#define STR_ISAMEM "ISAメモリー拡張カード" -#define STR_ISAMEM_1 "カード1:" -#define STR_ISAMEM_2 "カード2:" -#define STR_ISAMEM_3 "カード3:" -#define STR_ISAMEM_4 "カード4:" -#define STR_BUGGER "ISABuggerデãƒã‚¤ã‚¹" -#define STR_POSTCARD "POSTカード" +#define STR_ISARTC "ISA RTCカード:" +#define STR_ISAMEM "ISAメモリ拡張カード" +#define STR_ISAMEM_1 "カード1:" +#define STR_ISAMEM_2 "カード2:" +#define STR_ISAMEM_3 "カード3:" +#define STR_ISAMEM_4 "カード4:" +#define STR_BUGGER "ISABuggerデãƒã‚¤ã‚¹" +#define STR_POSTCARD "POSTカード" -#define FONT_SIZE 9 -#define FONT_NAME "Meiryo UI" +#define FONT_SIZE 9 +#define FONT_NAME "Meiryo UI" #include "dialogs.rc" @@ -366,194 +392,188 @@ END // String Table // -STRINGTABLE DISCARDABLE +STRINGTABLE DISCARDABLE BEGIN - 2048 "86Box" - IDS_2049 "エラー" - IDS_2050 "致命的ãªã‚¨ãƒ©ãƒ¼" - IDS_2051 " - ä¸€æ™‚åœæ­¢" - IDS_2052 "Ctrl+Alt+PgDnã§ã‚¦ã‚£ãƒ³ãƒ‰ã‚¦ãƒ¢ãƒ¼ãƒ‰ã«æˆ»ã‚Šã¾ã™ã€‚" - IDS_2053 "速度" - IDS_2054 "ZIP %03i %i (%s): %ls" - IDS_2055 "ZIPイメージ (*.IM?;*.ZDI)\0*.IM?;*.ZDI\0" - IDS_2056 "86Boxã§ä½¿ç”¨å¯èƒ½ãªROMイメージãŒè¦‹ã¤ã‹ã‚Šã¾ã›ã‚“ã§ã—ãŸã€‚\n\nROMセットをダウンロードã—ã¦ã€ã€Œromsã€ãƒ‡ã‚£ãƒ¬ã‚¯ãƒˆãƒªã«è§£å‡ã—ã¦ãã ã•ã„。" - IDS_2057 "(空)" - IDS_2058 "ZIPイメージ (*.IM?;*.ZDI)\0*.IM?;*.ZDI\0ã™ã¹ã¦ã®ãƒ•ァイル (*.*)\0*.*\0" - IDS_2059 "高速" - IDS_2060 "オン" - IDS_2061 "オフ" - IDS_2062 "ã™ã¹ã¦ã®ã‚¤ãƒ¡ãƒ¼ã‚¸ (*.86F;*.DSK;*.FLP;*.IM?;*.*FD?)\0*.86F;*.DSK;*.FLP;*.IM?;*.*FD?\0基本的ãªã‚»ã‚¯ã‚¿ãƒ¼ã‚¤ãƒ¡ãƒ¼ã‚¸ (*.DSK;*.FLP;*.IM?;*.*FD?)\0*.DSK;*.FLP;*.IM?;*.IMG;*.*FD?\0表é¢ã‚¤ãƒ¡ãƒ¼ã‚¸ (*.86F)\0*.86F\0" - IDS_2063 "roms/machinesディレクトリã«ROMãŒãªã„ãŸã‚ã€ãƒžã‚·ãƒ³ã€Œ%hsã€ã¯ä½¿ç”¨ã§ãã¾ã›ã‚“。使用å¯èƒ½ãªãƒžã‚·ãƒ³ã«åˆ‡ã‚Šæ›¿ãˆã¾ã™ã€‚" + 2048 "86Box" + IDS_2049 "エラー" + IDS_2050 "致命的ãªã‚¨ãƒ©ãƒ¼" + IDS_2051 " - ä¸€æ™‚åœæ­¢" + IDS_2052 "Ctrl+Alt+PgDnã§ã‚¦ã‚£ãƒ³ãƒ‰ã‚¦ãƒ¢ãƒ¼ãƒ‰ã«æˆ»ã‚Šã¾ã™ã€‚" + IDS_2053 "速度" + IDS_2054 "ZIP %03i %i (%s): %ls" + IDS_2055 "ZIPイメージ (*.IM?;*.ZDI)\0*.IM?;*.ZDI\0" + IDS_2056 "86Boxã§ä½¿ç”¨å¯èƒ½ãªROMイメージãŒè¦‹ã¤ã‹ã‚Šã¾ã›ã‚“。\n\nROMセットをダウンロードã—ã¦ã€ã€Œromsã€ãƒ‡ã‚£ãƒ¬ã‚¯ãƒˆãƒªã«è§£å‡ã—ã¦ãã ã•ã„。" + IDS_2057 "(空)" + IDS_2058 "ZIPイメージ (*.IM?;*.ZDI)\0*.IM?;*.ZDI\0ã™ã¹ã¦ã®ãƒ•ァイル (*.*)\0*.*\0" + IDS_2059 "高速" + IDS_2060 "オン" + IDS_2061 "オフ" + IDS_2062 "ã™ã¹ã¦ã®ã‚¤ãƒ¡ãƒ¼ã‚¸ (*.86F;*.DSK;*.FLP;*.IM?;*.*FD?)\0*.86F;*.DSK;*.FLP;*.IM?;*.*FD?\0ベーシック セクター イメージ (*.DSK;*.FLP;*.IM?;*.*FD?)\0*.DSK;*.FLP;*.IM?;*.IMG;*.*FD?\0サーフェス イメージ (*.86F)\0*.86F\0" + IDS_2063 "roms/machines ディレクトリã«ROMãŒãªã„ãŸã‚ã€ãƒžã‚·ãƒ³ã€Œ%hsã€ã¯ä½¿ç”¨ã§ãã¾ã›ã‚“。使用å¯èƒ½ãªãƒžã‚·ãƒ³ã«åˆ‡ã‚Šæ›¿ãˆã¾ã™ã€‚" END -STRINGTABLE DISCARDABLE +STRINGTABLE DISCARDABLE BEGIN - IDS_2064 "roms/videoディレクトリã«ROMãŒãªã„ãŸã‚ã€ãƒ“デオカード「%hsã€ã¯ä½¿ç”¨ã§ãã¾ã›ã‚“。使用å¯èƒ½ãªãƒ“デオカードã«åˆ‡ã‚Šæ›¿ãˆã¾ã™ã€‚" - IDS_2065 "マシン" - IDS_2066 "ç”»é¢è¡¨ç¤º" - IDS_2067 "入力デãƒã‚¤ã‚¹" - IDS_2068 "サウンド" - IDS_2069 "ãƒãƒƒãƒˆãƒ¯ãƒ¼ã‚¯" - IDS_2070 "ãƒãƒ¼ãƒˆ (COM & LPT)" - IDS_2071 "ストレージコントローラ" - IDS_2072 "ãƒãƒ¼ãƒ‰ãƒ‡ã‚£ã‚¹ã‚¯" - IDS_2073 "フロッピー/CD-ROMドライブ" - IDS_2074 "ãã®ä»–ã®ãƒªãƒ ãƒ¼ãƒãƒ–ルデãƒã‚¤ã‚¹" - IDS_2075 "ãã®ä»–ã®å‘¨è¾ºè£…ç½®" - IDS_2076 "表é¢ã‚¤ãƒ¡ãƒ¼ã‚¸ (*.86F)\0*.86F\0" - IDS_2077 "クリックã™ã‚‹ã¨ãƒžã‚¦ã‚¹ã‚’キャプãƒãƒ£ã—ã¾ã™" - IDS_2078 "F8+F12キーã§ãƒžã‚¦ã‚¹ã‚’解放ã—ã¾ã™" - IDS_2079 "F8+F12キーã¾ãŸã¯ä¸­ãƒœã‚¿ãƒ³ã§ãƒžã‚¦ã‚¹ã‚’解放ã—ã¾ã™" + IDS_2064 "roms/video ディレクトリã«ROMãŒãªã„ãŸã‚ã€ãƒ“デオカード「%hsã€ã¯ä½¿ç”¨ã§ãã¾ã›ã‚“。使用å¯èƒ½ãªãƒ“デオカードã«åˆ‡ã‚Šæ›¿ãˆã¾ã™ã€‚" + IDS_2065 "マシン" + IDS_2066 "ディスプレイ" + IDS_2067 "入力デãƒã‚¤ã‚¹" + IDS_2068 "サウンド" + IDS_2069 "ãƒãƒƒãƒˆãƒ¯ãƒ¼ã‚¯" + IDS_2070 "ãƒãƒ¼ãƒˆ (COM/LPT)" + IDS_2071 "ストレージ コントローラ" + IDS_2072 "ãƒãƒ¼ãƒ‰ ディスク" + IDS_2073 "フロッピーï¼CD-ROMドライブ" + IDS_2074 "ä»–ã®ãƒªãƒ ãƒ¼ãƒãƒ–ル デãƒã‚¤ã‚¹" + IDS_2075 "ä»–ã®å‘¨è¾ºãƒ‡ãƒã‚¤ã‚¹" + IDS_2076 "サーフェス イメージ (*.86F)\0*.86F\0" + IDS_2077 "左クリックã§ãƒžã‚¦ã‚¹ã‚’キャプãƒãƒ£ã—ã¾ã™" + IDS_2078 "F8+F12キーを押ã—ã¦ãƒžã‚¦ã‚¹ã‚’解放ã—ã¾ã™" + IDS_2079 "F8+F12キーã¾ãŸã¯ä¸­ã‚¯ãƒªãƒƒã‚¯ã§ãƒžã‚¦ã‚¹ã‚’解放ã—ã¾ã™" END -STRINGTABLE DISCARDABLE +STRINGTABLE DISCARDABLE BEGIN - IDS_2080 "FluidSynthãŒåˆæœŸåŒ–ã§ãã¾ã›ã‚“" - IDS_2081 "ãƒã‚¹" - IDS_2082 "ファイル" - IDS_2083 "C" - IDS_2084 "H" - IDS_2085 "S" - IDS_2086 "MB" - IDS_2087 "BPBã‚’ãƒã‚§ãƒƒã‚¯" - IDS_2088 "KB" - IDS_2089 "ビデオレンダラーãŒåˆæœŸåŒ–ã§ãã¾ã›ã‚“。" - IDS_2090 "既定値" - IDS_2091 "%iã¤ã®å¾…機状態" - IDS_2092 "タイプ" - IDS_2093 "PCapã®ã‚»ãƒƒãƒˆã‚¢ãƒƒãƒ—ã«å¤±æ•—ã—ã¾ã—ãŸ" - IDS_2094 "PCapデãƒã‚¤ã‚¹ãŒã‚りã¾ã›ã‚“" - IDS_2095 "䏿­£ãªPCapデãƒã‚¤ã‚¹ã§ã™" - IDS_2096 "標準ジョイスティック(2ボタン)" - IDS_2097 "標準ジョイスティック(4ボタン)" - IDS_2098 "標準ジョイスティック(6ボタン)" - IDS_2099 "標準ジョイスティック(8ボタン)" - IDS_2100 "CH Flightstick Pro" - IDS_2101 "Microsoft SideWinder Pad" - IDS_2102 "Thrustmaster Flight Control System" - IDS_2103 "ãªã—" - IDS_2104 "キーボードアクセラレータを読ã¿è¾¼ã‚ã¾ã›ã‚“。" - IDS_2105 "生ã®å…¥åŠ›ãŒç™»éŒ²ã§ãã¾ã›ã‚“。" - IDS_2106 "%u" - IDS_2107 "%u MB (CHS: %i, %i, %i)" - IDS_2108 "フロッピー %i (%s): %ls" - IDS_2109 "ã™ã¹ã¦ã®ã‚¤ãƒ¡ãƒ¼ã‚¸ (*.0??;*.1??;*.??0;*.86F;*.BIN;*.CQ?;*.D??;*.FLP;*.HDM;*.IM?;*.JSON;*.TD0;*.*FD?;*.MFM;*.XDF)\0*.0??;*.1??;*.??0;*.86F;*.BIN;*.CQ?;*.D??;*.FLP;*.HDM;*.IM?;*.JSON;*.TD0;*.*FD?;*.MFM;*.XDF\0アドãƒãƒ³ã‚¹ãƒ‰ã‚»ã‚¯ã‚¿ãƒ¼ã‚¤ãƒ¡ãƒ¼ã‚¸ (*.IMD;*.JSON;*.TD0)\0*.IMD;*.JSON;*.TD0\0基本セクターイメージ (*.0??;*.1??;*.??0;*.BIN;*.CQ?;*.D??;*.FLP;*.HDM;*.IM?;*.XDF;*.*FD?)\0*.0??;*.1??;*.??0;*.BIN;*.CQ?;*.D??;*.FLP;*.HDM;*.IM?;*.XDF;*.*FD?\0フラックスイメージ (*.FDI)\0*.FDI\0表é¢ã‚¤ãƒ¡ãƒ¼ã‚¸ (*.86F;*.MFM)\0*.86F;*.MFM\0ã™ã¹ã¦ã®ãƒ•ァイル (*.*)\0*.*\0" - IDS_2110 "FreeTypeãŒåˆæœŸåŒ–ã§ãã¾ã›ã‚“" - IDS_2111 "SDLãŒåˆæœŸåŒ–ã§ãã¾ã›ã‚“。SDL2.dllãŒå¿…è¦ã§ã™" - IDS_2112 "使用中ã®ãƒžã‚·ãƒ³ã‚’ãƒãƒ¼ãƒ‰ãƒªã‚»ãƒƒãƒˆã—ã¾ã™ã‹ï¼Ÿ" - IDS_2113 "86Boxを終了ã—ã¾ã™ã‹ï¼Ÿ" - IDS_2114 "GhostscriptãŒåˆæœŸåŒ–ã§ãã¾ã›ã‚“" - IDS_2115 "å…‰ç£æ°— %i (%ls): %ls" - IDS_2116 "å…‰ç£æ°—イメージ (*.IM?;*.MDI)\0*.IM?;*.MDI\0ã™ã¹ã¦ã®ãƒ•ァイル (*.*)\0*.*\0" - IDS_2117 "86Boxã¸ã‚ˆã†ã“ãï¼" - IDS_2118 "内蔵コントローラー" - IDS_2119 "終了" - IDS_2120 "ROMãŒè¦‹ã¤ã‹ã‚Šã¾ã›ã‚“" - IDS_2121 "設定をä¿å­˜ã—ã¾ã™ã‹ï¼Ÿ" - IDS_2122 "ä¿å­˜ã™ã‚‹ã¨ä½¿ç”¨ä¸­ã®ãƒžã‚·ãƒ³ãŒãƒãƒ¼ãƒ‰ãƒªã‚»ãƒƒãƒˆã•れã¾ã™ã€‚" - IDS_2123 "ä¿å­˜" - IDS_2124 "86Boxã®ãƒãƒ¼ã‚¸ãƒ§ãƒ³æƒ…å ±" - IDS_2125 "86Box v" EMU_VERSION + IDS_2081 "ãƒã‚¹" + IDS_2082 "ファイル" + IDS_2083 "C" + IDS_2084 "H" + IDS_2085 "S" + IDS_2086 "MB" + IDS_2087 "Speed" + IDS_2088 "BPBãƒã‚§ãƒƒã‚¯" + IDS_2089 "KB" + IDS_2090 "ビデオレンダラーãŒåˆæœŸåŒ–ã§ãã¾ã›ã‚“。" + IDS_2091 "既定値" + IDS_2092 "%iã¤ã®ã‚¦ã‚§ã‚¤ãƒˆ ステート" + IDS_2093 "タイプ" + IDS_2094 "PCapã®ã‚»ãƒƒãƒˆã‚¢ãƒƒãƒ—ã«å¤±æ•—ã—ã¾ã—ãŸ" + IDS_2095 "PCapデãƒã‚¤ã‚¹ãŒã‚りã¾ã›ã‚“" + IDS_2096 "䏿­£ãªPCapデãƒã‚¤ã‚¹" + IDS_2097 "標準ジョイスティック(2ボタン)" + IDS_2098 "標準ジョイスティック(4ボタン)" + IDS_2099 "標準ジョイスティック(6ボタン)" + IDS_2100 "標準ジョイスティック(8ボタン)" + IDS_2101 "CH Flightstick Pro" + IDS_2102 "Microsoft SideWinderパッド" + IDS_2103 "Thrustmaster飛行制御システム" + IDS_2104 "ãªã—" + IDS_2105 "キーボード アクセラレータを読ã¿è¾¼ã‚ã¾ã›ã‚“。" + IDS_2106 "生入力ãŒç™»éŒ²ã§ãã¾ã›ã‚“。" + IDS_2107 "%u" + IDS_2108 "%u MB (CHS値: %iã€%iã€%i)" + IDS_2109 "フロッピー %i (%s): %ls" + IDS_2110 "ã™ã¹ã¦ã®ã‚¤ãƒ¡ãƒ¼ã‚¸ (*.0??;*.1??;*.??0;*.86F;*.BIN;*.CQ?;*.D??;*.FLP;*.HDM;*.IM?;*.JSON;*.TD0;*.*FD?;*.MFM;*.XDF)\0*.0??;*.1??;*.??0;*.86F;*.BIN;*.CQ?;*.D??;*.FLP;*.HDM;*.IM?;*.JSON;*.TD0;*.*FD?;*.MFM;*.XDF\0アドãƒãƒ³ã‚¹ãƒ‰ セクター イメージ (*.IMD;*.JSON;*.TD0)\0*.IMD;*.JSON;*.TD0\0ベーシック セクター イメージ (*.0??;*.1??;*.??0;*.BIN;*.CQ?;*.D??;*.FLP;*.HDM;*.IM?;*.XDF;*.*FD?)\0*.0??;*.1??;*.??0;*.BIN;*.CQ?;*.D??;*.FLP;*.HDM;*.IM?;*.XDF;*.*FD?\0フラックスイメージ (*.FDI)\0*.FDI\0サーフェス イメージ (*.86F;*.MFM)\0*.86F;*.MFM\0ã™ã¹ã¦ã®ãƒ•ァイル (*.*)\0*.*\0" + IDS_2112 "SDLãŒåˆæœŸåŒ–ã§ãã¾ã›ã‚“。SDL2.dllãŒå¿…è¦ã§ã™" + IDS_2113 "使用中ã®ãƒžã‚·ãƒ³ã‚’ãƒãƒ¼ãƒ‰ãƒª セットã—ã¾ã™ã‹ï¼Ÿ" + IDS_2114 "86Boxを終了ã—ã¾ã™ã‹ï¼Ÿ" + IDS_2115 "GhostscriptãŒåˆæœŸåŒ–ã§ãã¾ã›ã‚“" + IDS_2116 "å…‰ç£æ°— %i (%ls): %ls" + IDS_2117 "å…‰ç£æ°—イメージ (*.IM?;*.MDI)\0*.IM?;*.MDI\0ã™ã¹ã¦ã®ãƒ•ァイル (*.*)\0*.*\0" + IDS_2118 "86Boxã¸ã‚ˆã†ã“ãï¼" + IDS_2119 "内蔵コントローラー" + IDS_2120 "終了" + IDS_2121 "ROMãŒè¦‹ã¤ã‹ã‚Šã¾ã›ã‚“" + IDS_2122 "設定をä¿å­˜ã—ã¾ã™ã‹ï¼Ÿ" + IDS_2123 "使用中ã®ãƒžã‚·ãƒ³ãŒãƒãƒ¼ãƒ‰ãƒª セットã•れã¾ã™ã€‚" + IDS_2124 "ä¿å­˜" + IDS_2125 "86Boxã®ãƒãƒ¼ã‚¸ãƒ§ãƒ³æƒ…å ±" + IDS_2126 "86Box v" EMU_VERSION - IDS_2126 "å¤ã„パソコンã®ã‚¨ãƒŸãƒ¥ãƒ¬ãƒ¼ã‚¿ãƒ¼\n\n著者: Sarah Walker, Miran Grca, Fred N. van Kempen (waltje), SA1988, Tiseno100, reenigne, leilei, JohnElliott, greatpsycho, and others.\n\nGNU General Public License version 2以é™ã§ãƒªãƒªãƒ¼ã‚¹ã•れã¦ã„ã¾ã™ã€‚詳ã—ã㯠LICENSE ã‚’ã”覧ãã ã•ã„。" - IDS_2127 "OK" - IDS_2128 "ãƒãƒ¼ãƒ‰ã‚¦ã‚§ã‚¢ãŒåˆ©ç”¨ã§ãã¾ã›ã‚“" + IDS_2127 "å¤ã„パソコンã®ã‚¨ãƒŸãƒ¥ãƒ¬ãƒ¼ã‚¿ãƒ¼\n\n著者: Miran GrÄa (OBattler), RichardG867, Jasmine Iwanek, TC1995, coldbrewed, Teemu Korhonen (Manaatti), Joakim L. Gilje, Adrien Moulin (elyosh), Daniel Balsom (gloriouscow), Cacodemon345, Fred N. van Kempen (waltje), Tiseno100, reenigne, and others.\n\nWith previous core contributions from Sarah Walker, leilei, JohnElliott, greatpsycho, and others.\n\nGNU General Public License version 2以é™ã§ãƒªãƒªãƒ¼ã‚¹ã•れã¦ã„ã¾ã™ã€‚詳ã—ã㯠LICENSE ã‚’ã”覧ãã ã•ã„。" + IDS_2128 "OK" + IDS_2129 "ãƒãƒ¼ãƒ‰ã‚¦ã‚§ã‚¢ãŒåˆ©ç”¨ã§ãã¾ã›ã‚“" #ifdef _WIN32 #define LIB_NAME_PCAP "WinPcap" #else #define LIB_NAME_PCAP "libpcap" #endif - IDS_2129 LIB_NAME_PCAP "ãŒã‚¤ãƒ³ã‚¹ãƒˆãƒ¼ãƒ«ã•れã¦ã‚‹ã‹ã€" LIB_NAME_PCAP "ã«å¯¾å¿œã—ãŸãƒãƒƒãƒˆãƒ¯ãƒ¼ã‚¯ã«æŽ¥ç¶šã•れã¦ã‚‹ã‹ç¢ºèªã—ã¦ãã ã•ã„。" - IDS_2130 "䏿­£ãªè¨­å®šã§ã™" -#ifdef _WIN32 -#define LIB_NAME_FREETYPE "freetype.dll" -#else -#define LIB_NAME_FREETYPE "libfreetype" -#endif - IDS_2131 "ESC/Pプリンタã®ã‚¨ãƒŸãƒ¥ãƒ¬ãƒ¼ã‚·ãƒ§ãƒ³ã«ã¯" LIB_NAME_FREETYPE "ãŒå¿…è¦ã§ã™ã€‚" + IDS_2130 LIB_NAME_PCAP "ãŒã‚¤ãƒ³ã‚¹ãƒˆãƒ¼ãƒ«ã•れã¦ã‚‹ã‹ã€" LIB_NAME_PCAP "ã«å¯¾å¿œã—ãŸãƒãƒƒãƒˆãƒ¯ãƒ¼ã‚¯ã«æŽ¥ç¶šã•れã¦ã‚‹ã‹ç¢ºèªã—ã¦ãã ã•ã„。" + IDS_2131 "無効ãªè¨­å®š" #ifdef _WIN32 #define LIB_NAME_GS "gsdll32.dll" #else #define LIB_NAME_GS "libgs" #endif - IDS_2132 "PostScriptファイルをPDFã«è‡ªå‹•変æ›ã™ã‚‹ã«ã¯" LIB_NAME_GS "ãŒå¿…è¦ã§ã™ã€‚\n\n汎用PostScriptプリンターã«é€ä¿¡ã•れãŸãƒ‰ã‚­ãƒ¥ãƒ¡ãƒ³ãƒˆã¯ã€PostScript(.ps)ファイルã¨ã—ã¦ä¿å­˜ã•れã¾ã™ã€‚" -#ifdef _WIN32 -#define LIB_NAME_FLUIDSYNTH "libfluidsynth.dll" -#else -#define LIB_NAME_FLUIDSYNTH "libfluidsynth" -#endif - IDS_2133 "FluidSynthã®MIDI出力ã«ã¯" LIB_NAME_FLUIDSYNTH "ãŒå¿…è¦ã§ã™ã€‚" - IDS_2134 "フルスクリーンã«åˆ‡ã‚Šæ›¿ãˆã¦ã„ã¾ã™" - IDS_2135 "今後ã€ã“ã®ãƒ¡ãƒƒã‚»ãƒ¼ã‚¸ã‚’表示ã—ãªã„" - IDS_2136 "終了ã—ãªã„" - IDS_2137 "リセット" - IDS_2138 "リセットã—ãªã„" - IDS_2139 "å…‰ç£æ°—イメージ (*.IM?;*.MDI)\0*.IM?;*.MDI\0ã™ã¹ã¦ã®ãƒ•ァイル (*.*)\0*.*\0" - IDS_2140 "CD-ROMイメージ (*.ISO;*.CUE)\0*.ISO;*.CUE\0ã™ã¹ã¦ã®ãƒ•ァイル (*.*)\0*.*\0" - IDS_2141 "%hs デãƒã‚¤ã‚¹ã®è¨­å®š" - IDS_2142 "モニターã®ã‚¹ãƒªãƒ¼ãƒ—モード" - IDS_2143 "OpenGLシェーダー (*.GLSL)\0*.GLSL\0ã™ã¹ã¦ã®ãƒ•ァイル (*.*)\0*.*\0" - IDS_2144 "OpenGL設定" - IDS_2145 "サãƒãƒ¼ãƒˆã•れã¦ã„ãªã„設定を読ã¿è¾¼ã‚“ã§ã„ã¾ã™" - IDS_2146 "é¸æŠžã—ãŸãƒžã‚·ãƒ³ã«åŸºã¥ãCPUタイプã®ãƒ•ィルタリングã¯ã€ã“ã®ã‚¨ãƒŸãƒ¥ãƒ¬ãƒ¼ãƒˆã•れãŸãƒžã‚·ãƒ³ã§ã¯ç„¡åйã«ãªã£ã¦ã„ã¾ã™ã€‚\n\nã“れã«ã‚ˆã‚Šã€é¸æŠžã—ãŸãƒžã‚·ãƒ³ã¨äº’æ›æ€§ã®ãªã„CPUãŒé¸æŠžã§ãã¾ã™ã€‚ãŸã ã—ã€ãƒžã‚·ãƒ³ã®BIOSã¾ãŸã¯ä»–ã®ã‚½ãƒ•トウェアã¨ã®äº’æ›æ€§ãŒå¤±ã‚れるå¯èƒ½æ€§ãŒã‚りã¾ã™ã€‚\n\nã“ã®è¨­å®šã®æœ‰åŠ¹åŒ–ã¯å…¬å¼ã‚µãƒãƒ¼ãƒˆãŒã§ãã¾ã›ã‚“。ã¾ãŸã€ãƒã‚°ãƒ¬ãƒãƒ¼ãƒˆãŒç„¡åйã¨ã—ã¦é–‰ã˜ã‚‰ã‚Œã‚‹å ´åˆãŒã‚りã¾ã™ã€‚" - IDS_2147 "続行" - IDS_2148 "カセット: %s" - IDS_2149 "カセットイメージ (*.PCM;*.RAW;*.WAV;*.CAS)\0*.PCM;*.RAW;*.WAV;*.CAS\0ã™ã¹ã¦ã®ãƒ•ァイル (*.*)\0*.*\0" - IDS_2150 "カートリッジ %i: %ls" - IDS_2151 "カートリッジイメージ (*.A;*.B;*.JRC)\0*.A;*.B;*.JRC\0ã™ã¹ã¦ã®ãƒ•ァイル (*.*)\0*.*\0" - IDS_2152 "レンダラーã®åˆæœŸåŒ–エラー" - IDS_2153 "OpenGL (3.0コア) レンダラーãŒåˆæœŸåŒ–ã§ãã¾ã›ã‚“ã§ã—ãŸã€‚別ã®ãƒ¬ãƒ³ãƒ€ãƒ©ãƒ¼ã‚’使用ã—ã¦ãã ã•ã„。" - IDS_2154 "実行をå†é–‹" - IDS_2155 "å®Ÿè¡Œã‚’ä¸€æ™‚åœæ­¢" - IDS_2156 "Ctrl+Alt+DELを押ã—" - IDS_2157 "Ctrl+Alt+Escを押ã—" - IDS_2158 "ãƒãƒ¼ãƒ‰ãƒªã‚»ãƒƒãƒˆ" - IDS_2159 "ACPIシャットダウン" - IDS_2160 "設定" + IDS_2133 "PostScriptファイルをPDFã«è‡ªå‹•変æ›ã™ã‚‹ã«ã¯" LIB_NAME_GS "ãŒå¿…è¦ã§ã™ã€‚\n\n汎用PostScriptプリンターã«é€ä¿¡ã•ã‚ŒãŸæ–‡æ›¸ã¯ã€PostScript (.ps) ファイルã¨ã—ã¦ä¿å­˜ã•れã¾ã™ã€‚" + IDS_2135 "全画é¢ãƒ¢ãƒ¼ãƒ‰ã‚’入力" + IDS_2136 "今後ã€ã“ã®ãƒ¡ãƒƒã‚»ãƒ¼ã‚¸ã‚’表示ã—ãªã„" + IDS_2137 "終了ã—ãªã„" + IDS_2138 "リセット" + IDS_2139 "リセットã—ãªã„" + IDS_2140 "å…‰ç£æ°—イメージ (*.IM?;*.MDI)\0*.IM?;*.MDI\0ã™ã¹ã¦ã®ãƒ•ァイル (*.*)\0*.*\0" + IDS_2141 "CD-ROMイメージ (*.ISO;*.CUE)\0*.ISO;*.CUE\0ã™ã¹ã¦ã®ãƒ•ァイル (*.*)\0*.*\0" + IDS_2142 "%hs ã®ãƒ‡ãƒã‚¤ã‚¹è¨­å®š" + IDS_2143 "モニターã®ã‚¹ãƒªãƒ¼ãƒ— モード" + IDS_2144 "OpenGLシェーダー (*.GLSL)\0*.GLSL\0ã™ã¹ã¦ã®ãƒ•ァイル (*.*)\0*.*\0" + IDS_2145 "OpenGL設定" + IDS_2146 "読ã¿è¾¼ã‚“ã§ã„る設定ãŒã‚µãƒãƒ¼ãƒˆã•れã¾ã›ã‚“" + IDS_2147 "é¸æŠžã—ãŸãƒžã‚·ãƒ³ã«åŸºã¥ãCPUタイプã®ãƒ•ィルター機能ã¯ã€ä½¿ç”¨ä¸­ã®ãƒžã‚·ãƒ³ã§ã¯ç„¡åйã«ãªã£ã¦ã„ã¾ã™ã€‚\n\nã“れã«ã‚ˆã‚Šã€é¸æŠžã—ãŸãƒžã‚·ãƒ³ã¨äº’æ›æ€§ã®ãªã„CPUãŒé¸æŠžã§ãã¾ã™ã€‚ã—ã‹ã—ã€ãƒžã‚·ãƒ³ã®BIOSã‚„ä»–ã®ã‚½ãƒ•トウェアã¨äº’æ›æ€§ãŒãªã„å ´åˆãŒã‚りã¾ã™ã€‚\n\nã“ã®è¨­å®šã‚’有効ã«ã™ã‚‹ã“ã¨ã¯å…¬å¼ã«ã¯ã‚µãƒãƒ¼ãƒˆã•れã¦ãŠã‚‰ãšã€ãƒã‚°ãƒ¬ãƒãƒ¼ãƒˆã¯ç„¡åйã¨ã—ã¦ä¸­æ­¢ã•れるå¯èƒ½æ€§ãŒã‚りã¾ã™ã€‚" + IDS_2148 "続行" + IDS_2149 "カセット: %s" + IDS_2150 "カセット イメージ (*.PCM;*.RAW;*.WAV;*.CAS)\0*.PCM;*.RAW;*.WAV;*.CAS\0ã™ã¹ã¦ã®ãƒ•ァイル (*.*)\0*.*\0" + IDS_2151 "カートリッジ %i: %ls" + IDS_2152 "カートリッジ イメージ (*.A;*.B;*.JRC)\0*.A;*.B;*.JRC\0ã™ã¹ã¦ã®ãƒ•ァイル (*.*)\0*.*\0" + IDS_2153 "レンダラーã®åˆæœŸåŒ–エラー" + IDS_2154 "OpenGL (3.0コア) レンダラーãŒåˆæœŸåŒ–ã§ãã¾ã›ã‚“。別ã®ãƒ¬ãƒ³ãƒ€ãƒ©ãƒ¼ã‚’使用ã—ã¦ãã ã•ã„。" + IDS_2155 "実行をå†é–‹" + IDS_2156 "å®Ÿè¡Œã‚’ä¸€æ™‚åœæ­¢" + IDS_2157 "Ctrl+Alt+DELを押ã™" + IDS_2158 "Ctrl+Alt+Escを押ã™" + IDS_2159 "ãƒãƒ¼ãƒ‰ãƒªã‚»ãƒƒãƒˆ" + IDS_2160 "ACPIシャットダウン" + IDS_2161 "設定" + IDS_2162 "タイプ" + IDS_2163 "å‹•çš„å†ã‚³ãƒ³ãƒ‘ã‚¤ãƒ«ç¦æ­¢" + IDS_2164 "æ—§åž‹ã®å‹•çš„å†ã‚³ãƒ³ãƒ‘イル" + IDS_2165 "æ–°åž‹ã®å‹•çš„å†ã‚³ãƒ³ãƒ‘イル" + IDS_2166 "「roms/videoã€ãƒ‡ã‚£ãƒ¬ã‚¯ãƒˆãƒªã«ROMãŒãªã„ãŸã‚ã€ãƒ“デオカード#2「%hsã€ã¯ä½¿ç”¨ã§ãã¾ã›ã‚“。2æžšç›®ã®ãƒ“デオカードを無効ã«ã—ã¾ã™ã€‚" + IDS_2167 "ãƒãƒƒãƒˆãƒ¯ãƒ¼ã‚¯ ドライãƒã®åˆæœŸåŒ–ã«å¤±æ•—ã—ã¾ã—ãŸã€‚" + IDS_2168 "ãƒãƒƒãƒˆãƒ¯ãƒ¼ã‚¯è¨­å®šãŒãƒŒãƒ« ドライãƒã«åˆ‡ã‚Šæ›¿ãˆã‚‰ã‚Œã¾ã™" END -STRINGTABLE DISCARDABLE +STRINGTABLE DISCARDABLE BEGIN - IDS_4096 "ãƒãƒ¼ãƒ‰ãƒ‡ã‚£ã‚¹ã‚¯ (%s)" - IDS_4097 "%01i:%01i" - IDS_4098 "%01i" - IDS_4099 "MFM/RLLã¾ãŸã¯ESDIã®CD-ROMドライブãŒå­˜åœ¨ã—ã¾ã›ã‚“" - IDS_4100 "カスタム..." - IDS_4101 "カスタム (大型)..." - IDS_4102 "æ–°è¦ã®ãƒ‡ã‚£ã‚¹ã‚¯ã‚’追加" - IDS_4103 "既定ã®ãƒ‡ã‚£ã‚¹ã‚¯ã‚’追加" - IDS_4104 "HDIディスクイメージã¯4GBã‚’è¶…ãˆã‚‹ã“ã¨ã¯ã§ãã¾ã›ã‚“。" - IDS_4105 "ディスクイメージã¯127GBã‚’è¶…ãˆã‚‹ã“ã¨ã¯ã§ãã¾ã›ã‚“。" - IDS_4106 "ãƒãƒ¼ãƒ‰ãƒ‡ã‚£ã‚¹ã‚¯ã‚¤ãƒ¡ãƒ¼ã‚¸ (*.HD?;*.IM?;*.VHD)\0*.HD?;*.IM?;*.VHD\0ã™ã¹ã¦ã®ãƒ•ァイル (*.*)\0*.*\0" - IDS_4107 "ファイルã®èª­ã¿è¾¼ã¿ãŒã§ãã¾ã›ã‚“" - IDS_4108 "ãƒ•ã‚¡ã‚¤ãƒ«ã®æ›¸ãè¾¼ã¿ãŒã§ãã¾ã›ã‚“" - IDS_4109 "512以外ã®ã‚»ã‚¯ã‚¿ã‚µã‚¤ã‚ºã‚’æŒã¤HDIã¾ãŸã¯HDXイメージã¯ã‚µãƒãƒ¼ãƒˆã•れã¦ã„ã¾ã›ã‚“。" - IDS_4110 "USBã¯ã¾ã ã‚µãƒãƒ¼ãƒˆã•れã¦ã„ã¾ã›ã‚“" - IDS_4111 "ãƒ‡ã‚£ã‚¹ã‚¯ã‚¤ãƒ¡ãƒ¼ã‚¸ãƒ•ã‚¡ã‚¤ãƒ«ãŒæ—¢ã«å­˜åœ¨ã—ã¾ã™" - IDS_4112 "有効ãªãƒ•ァイルåを指定ã—ã¦ãã ã•ã„。" - IDS_4113 "ディスクイメージãŒä½œæˆã•れã¾ã—ãŸ" - IDS_4114 "ファイルãŒå­˜åœ¨ã—ã€èª­ã¿å–りå¯èƒ½ã§ã‚ã‚‹ã“ã¨ã‚’確èªã—ã¦ãã ã•ã„。" - IDS_4115 "ãƒ•ã‚¡ã‚¤ãƒ«ãŒæ›¸ãè¾¼ã¿å¯èƒ½ãªãƒ‡ã‚£ãƒ¬ã‚¯ãƒˆãƒªã«ä¿å­˜ã•れã¦ã„ã‚‹ã“ã¨ã‚’確èªã—ã¦ãã ã•ã„。" - IDS_4116 "ディスクイメージã®ã‚µã‚¤ã‚ºãŒå¤§ãã™ãŽã¾ã™" - IDS_4117 "æ–°è¦ãƒ‰ãƒ©ã‚¤ãƒ–をパーティション分割ã—ã€ãƒ•ォーマットを必ãšã—ã¨ã„ã¦ãã ã•ã„。" - IDS_4118 "é¸æŠžã—ãŸãƒ•ァイルãŒä¸Šæ›¸ãã•れã¾ã™ã€‚使ã£ã¦ã„ã„ã§ã™ã‹ï¼Ÿ" - IDS_4119 "サãƒãƒ¼ãƒˆã•れã¦ã„ãªã„ディスクイメージ" - IDS_4120 "上書ã" - IDS_4121 "上書ãã—ãªã„" - IDS_4122 "Rawイメージ (.img)" - IDS_4123 "HDIイメージ (.hdi)" - IDS_4124 "HDXイメージ (.hdx)" - IDS_4125 "VHD(容é‡å›ºå®š)(.vhd)" - IDS_4126 "VHD(容é‡å¯å¤‰)(.vhd)" - IDS_4127 "VHD(差分)(.vhd)" - IDS_4128 "大型ブロック (2 MB)" - IDS_4129 "å°åž‹ãƒ–ロック (512 KB)" - IDS_4130 "VHDファイル (*.VHD)\0*.VHD\0ã™ã¹ã¦ã®ãƒ•ァイル (*.*)\0*.*\0" - IDS_4131 "親VHDã®é¸æŠž" - IDS_4132 "親イメージãŒãƒ‡ã‚£ãƒ•ァレンシングイメージã®ä½œæˆã®å¾Œã«ä¿®æ­£ã—ãŸå¯èƒ½æ€§ãŒã‚りã¾ã™ã€‚\n\nイメージファイルã®ç§»å‹•ã€ã‚³ãƒ”ーã¾ãŸã¯ã“ã®ãƒ‡ã‚£ã‚¹ã‚¯ã‚’作æˆã—ãŸãƒ—ログラムã«ãƒã‚°ãŒç™ºç”Ÿã—ãŸå¯èƒ½æ€§ãŒã‚りã¾ã™ã€‚\n\nタイムスタンプを修正ã—ã¾ã™ã‹ï¼Ÿ" - IDS_4133 "親ディスクã¨å­ãƒ‡ã‚£ã‚¹ã‚¯ã®ã‚¿ã‚¤ãƒ ã‚¹ã‚¿ãƒ³ãƒ—ãŒä¸€è‡´ã—ã¾ã›ã‚“" - IDS_4134 "VHD ã®ã‚¿ã‚¤ãƒ ã‚¹ã‚¿ãƒ³ãƒ—を修正ã§ãã¾ã›ã‚“ã§ã—ãŸã€‚" - IDS_4135 "%01i:%02i" + IDS_4096 "ãƒãƒ¼ãƒ‰ ディスク (%s)" + IDS_4097 "%01i:%01i" + IDS_4098 "%01i" + IDS_4099 "MFM/RLLã‚„ESDI CD-ROMドライブãŒå­˜åœ¨ã—ã¾ã›ã‚“" + IDS_4100 "カスタム..." + IDS_4101 "カスタム (大容é‡)..." + IDS_4102 "æ–°è¦ã®ãƒ‡ã‚£ã‚¹ã‚¯ã‚’追加" + IDS_4103 "既定ã®ãƒ‡ã‚£ã‚¹ã‚¯ã‚’追加" + IDS_4104 "HDIディスク イメージã¯4GBã‚’è¶…ãˆã‚‹ã“ã¨ã¯ã§ãã¾ã›ã‚“。" + IDS_4105 "ディスク イメージã¯127GBã‚’è¶…ãˆã‚‹ã“ã¨ã¯ã§ãã¾ã›ã‚“。" + IDS_4106 "ãƒãƒ¼ãƒ‰ ディスク イメージ (*.HD?;*.IM?;*.VHD)\0*.HD?;*.IM?;*.VHD\0ã™ã¹ã¦ã®ãƒ•ァイル (*.*)\0*.*\0" + IDS_4107 "ファイルã®èª­ã¿è¾¼ã¿ãŒã§ãã¾ã›ã‚“" + IDS_4108 "ãƒ•ã‚¡ã‚¤ãƒ«ã®æ›¸ãè¾¼ã¿ãŒã§ãã¾ã›ã‚“" + IDS_4109 "512以外ã®ã‚»ã‚¯ã‚¿ サイズをæŒã¤HDIã¾ãŸã¯HDXイメージã¯å¯¾å¿œã—ã¦ã„ã¾ã›ã‚“。" + IDS_4110 "USBã¯ã¾ã éžå¯¾å¿œã§ã™" + IDS_4111 "ディスク イメージ ãƒ•ã‚¡ã‚¤ãƒ«ãŒæ—¢ã«å­˜åœ¨ã—ã¾ã™" + IDS_4112 "有効ãªãƒ•ァイルåを指定ã—ã¦ãã ã•ã„。" + IDS_4113 "ディスク イメージãŒä½œæˆã•れã¾ã—ãŸ" + IDS_4114 "ファイルãŒå­˜åœ¨ã—ã€èª­ã¿å–りå¯èƒ½ã§ã‚ã‚‹ã“ã¨ã‚’確èªã—ã¦ãã ã•ã„。" + IDS_4115 "ãƒ•ã‚¡ã‚¤ãƒ«ãŒæ›¸ãè¾¼ã¿å¯èƒ½ãªãƒ‡ã‚£ãƒ¬ã‚¯ãƒˆãƒªã«ä¿å­˜ã•れã¦ã„ã‚‹ã“ã¨ã‚’確èªã—ã¦ãã ã•ã„。" + IDS_4116 "ディスク イメージã®ã‚µã‚¤ã‚ºãŒå¤§ãã™ãŽã¾ã™" + IDS_4117 "æ–°è¦ãƒ‰ãƒ©ã‚¤ãƒ–をパーティション分割ã—ã€ãƒ•ォーマットを必ãšã—ã¨ã„ã¦ãã ã•ã„。" + IDS_4118 "é¸æŠžã—ãŸãƒ•ァイルã¯ä¸Šæ›¸ãã•れã¾ã™ã€‚よã‚ã—ã„ã§ã™ã‹ï¼Ÿ" + IDS_4119 "éžå¯¾å¿œã®ãƒ‡ã‚£ã‚¹ã‚¯ イメージ" + IDS_4120 "上書ã" + IDS_4121 "上書ãã—ãªã„" + IDS_4122 "Rawイメージ (.img)" + IDS_4123 "HDIイメージ (.hdi)" + IDS_4124 "HDXイメージ (.hdx)" + IDS_4125 "VHD (容é‡å›ºå®š) (.vhd)" + IDS_4126 "VHD (容é‡å¯å¤‰) (.vhd)" + IDS_4127 "VHD (差分) (.vhd)" + IDS_4128 "大型ブロック (2 MB)" + IDS_4129 "å°åž‹ãƒ–ロック (512 KB)" + IDS_4130 "VHDファイル (*.VHD)\0*.VHD\0ã™ã¹ã¦ã®ãƒ•ァイル (*.*)\0*.*\0" + IDS_4131 "親VHDã®é¸æŠž" + IDS_4132 "親イメージãŒå·®åˆ†ã‚¤ãƒ¡ãƒ¼ã‚¸ã®ä½œæˆã®å¾Œã«å¤‰æ›´ã•れるå¯èƒ½æ€§ãŒã‚りã¾ã™ã€‚\n\nイメージ ファイルãŒç§»å‹•ã¾ãŸã¯ã‚³ãƒ”ーã•れãŸã‹ã€ã‚¤ãƒ¡ãƒ¼ã‚¸ ファイルを作æˆã—ãŸãƒ—ログラムã«ãƒã‚°ãŒç™ºç”Ÿã—ãŸå¯èƒ½æ€§ãŒã‚りã¾ã™ã€‚\n\nタイム スタンプを修正ã—ã¾ã™ã‹ï¼Ÿ" + IDS_4133 "親ディスクã¨å­ãƒ‡ã‚£ã‚¹ã‚¯ã®ã‚¿ã‚¤ãƒ  スタンプãŒä¸€è‡´ã—ã¾ã›ã‚“" + IDS_4134 "VHD ã®ã‚¿ã‚¤ãƒ  スタンプを修正ã§ãã¾ã›ã‚“。" + IDS_4135 "%01i:%02i" IDS_4352 "MFM/RLL" IDS_4353 "XTA" @@ -562,56 +582,56 @@ BEGIN IDS_4356 "ATAPI" IDS_4357 "SCSI" - IDS_4608 "MFM/RLL (%01i:%01i)" - IDS_4609 "XTA (%01i:%01i)" - IDS_4610 "ESDI (%01i:%01i)" - IDS_4611 "IDE (%01i:%01i)" - IDS_4612 "ATAPI (%01i:%01i)" - IDS_4613 "SCSI (%01i:%02i)" + IDS_4608 "MFM/RLL (%01i:%01i)" + IDS_4609 "XTA (%01i:%01i)" + IDS_4610 "ESDI (%01i:%01i)" + IDS_4611 "IDE (%01i:%01i)" + IDS_4612 "ATAPI (%01i:%01i)" + IDS_4613 "SCSI (%01i:%02i)" - IDS_5120 "CD-ROM %i (%s): %s" + IDS_5120 "CD-ROM %i (%s): %s" - IDS_5376 "使用ã—ãªã„" - IDS_5381 "ATAPI" + IDS_5376 "使用ã—ãªã„" + IDS_5381 "ATAPI" IDS_5382 "SCSI" - IDS_5632 "使用ã—ãªã„" - IDS_5637 "ATAPI (%01i:%01i)" + IDS_5632 "使用ã—ãªã„" + IDS_5637 "ATAPI (%01i:%01i)" IDS_5638 "SCSI (%01i:%02i)" - IDS_5888 "160 kB" - IDS_5889 "180 kB" - IDS_5890 "320 kB" - IDS_5891 "360 kB" - IDS_5892 "640 kB" - IDS_5893 "720 kB" - IDS_5894 "1.2 MB" - IDS_5895 "1.25 MB" - IDS_5896 "1.44 MB" - IDS_5897 "DMF (クラスター1024)" - IDS_5898 "DMF (クラスター2048)" - IDS_5899 "2.88 MB" - IDS_5900 "ZIP 100" - IDS_5901 "ZIP 250" - IDS_5902 "3.5"" 128 MB (ISO 10090)" - IDS_5903 "3.5"" 230 MB (ISO 13963)" - IDS_5904 "3.5"" 540 MB (ISO 15498)" - IDS_5905 "3.5"" 640 MB (ISO 15498)" - IDS_5906 "3.5"" 1.3 GB (GigaMO)" - IDS_5907 "3.5"" 2.3 GB (GigaMO 2)" - IDS_5908 "5.25"" 600 MB" - IDS_5909 "5.25"" 650 MB" - IDS_5910 "5.25"" 1 GB" - IDS_5911 "5.25"" 1.3 GB" + IDS_5888 "160 kB" + IDS_5889 "180 kB" + IDS_5890 "320 kB" + IDS_5891 "360 kB" + IDS_5892 "640 kB" + IDS_5893 "720 kB" + IDS_5894 "1.2 MB" + IDS_5895 "1.25 MB" + IDS_5896 "1.44 MB" + IDS_5897 "DMF (クラスター1024)" + IDS_5898 "DMF (クラスター2048)" + IDS_5899 "2.88 MB" + IDS_5900 "ZIP 100" + IDS_5901 "ZIP 250" + IDS_5902 "3.5"" 128 MB (ISO 10090)" + IDS_5903 "3.5"" 230 MB (ISO 13963)" + IDS_5904 "3.5"" 540 MB (ISO 15498)" + IDS_5905 "3.5"" 640 MB (ISO 15498)" + IDS_5906 "3.5"" 1.3 GB (GigaMO)" + IDS_5907 "3.5"" 2.3 GB (GigaMO 2)" + IDS_5908 "5.25"" 600 MB" + IDS_5909 "5.25"" 650 MB" + IDS_5910 "5.25"" 1 GB" + IDS_5911 "5.25"" 1.3 GB" - IDS_6144 "è¦å®šã®å›žè»¢æ•°" - IDS_6145 "1%低ã„回転数" - IDS_6146 "1.5%低ã„回転数" - IDS_6147 "2%低ã„回転数" + IDS_6144 "既定RPM" + IDS_6145 "1%低ã„RPM" + IDS_6146 "1.5%低ã„RPM" + IDS_6147 "2%低ã„RPM" - IDS_7168 "(システム既定値)" + IDS_7168 "(システム既定値)" END -#define IDS_LANG_ENUS IDS_7168 +#define IDS_LANG_ENUS IDS_7168 // Japanese resources ///////////////////////////////////////////////////////////////////////////// diff --git a/src/win/languages/ko-KR.rc b/src/win/languages/ko-KR.rc index b9f68c3b4..360d6e36b 100644 --- a/src/win/languages/ko-KR.rc +++ b/src/win/languages/ko-KR.rc @@ -13,113 +13,122 @@ LANGUAGE LANG_KOREAN, SUBLANG_DEFAULT // Menu // -MainMenu MENU DISCARDABLE +MainMenu MENU DISCARDABLE BEGIN POPUP "ë™ìž‘(&A)" BEGIN - MENUITEM "키보드는 캡ì³ê°€ 필요함(&K)", IDM_ACTION_KBD_REQ_CAPTURE - MENUITEM "우측CTRL로 좌측ALT ìž…ë ¥(&R)", IDM_ACTION_RCTRL_IS_LALT + MENUITEM "키보드는 캡ì³ê°€ 필요함(&K)", IDM_ACTION_KBD_REQ_CAPTURE + MENUITEM "우측 CTRL로 좌측 ALT ìž…ë ¥(&R)", IDM_ACTION_RCTRL_IS_LALT MENUITEM SEPARATOR - MENUITEM "재시작(&H)...", IDM_ACTION_HRESET - MENUITEM "Ctrl+Alt+Del(&C)\tCtrl+F12", IDM_ACTION_RESET_CAD + MENUITEM "재시작(&H)...", IDM_ACTION_HRESET + MENUITEM "Ctrl+Alt+Del(&C)\tCtrl+F12", IDM_ACTION_RESET_CAD MENUITEM SEPARATOR - MENUITEM "Ctrl+Alt+Esc(&E)", IDM_ACTION_CTRL_ALT_ESC + MENUITEM "Ctrl+Alt+Esc(&E)", IDM_ACTION_CTRL_ALT_ESC MENUITEM SEPARATOR - MENUITEM "ì¼ì‹œì •ì§€(&P)", IDM_ACTION_PAUSE + MENUITEM "ì¼ì‹œì •ì§€(&P)", IDM_ACTION_PAUSE MENUITEM SEPARATOR - MENUITEM "ë내기(&X)...", IDM_ACTION_EXIT + MENUITEM "ë내기(&X)...", IDM_ACTION_EXIT END POPUP "표시(&V)" BEGIN - MENUITEM "ìƒíƒœ ë°” 숨기기(&H)", IDM_VID_HIDE_STATUS_BAR - MENUITEM "Hide &toolbar", IDM_VID_HIDE_TOOLBAR + MENUITEM "ìƒíƒœ ë°” 숨기기(&H)", IDM_VID_HIDE_STATUS_BAR + MENUITEM "툴바 숨기기", IDM_VID_HIDE_TOOLBAR MENUITEM SEPARATOR - MENUITEM "ì°½ í¬ê¸° ì¡°ì ˆ 가능하게 하기(&R)", IDM_VID_RESIZE - MENUITEM "ì°½ í¬ê¸°ì™€ 위치를 기억하기(&E)", IDM_VID_REMEMBER + MENUITEM "기본 모니터가 아닌 모니터 표시", IDM_VID_MONITORS + MENUITEM "ì°½ í¬ê¸° ì¡°ì ˆ 가능하게 하기(&R)", IDM_VID_RESIZE + MENUITEM "ì°½ í¬ê¸°ì™€ 위치를 기억하기(&E)", IDM_VID_REMEMBER MENUITEM SEPARATOR POPUP "ë Œë”러(&N)" BEGIN - MENUITEM "SDL (소프트웨어)(&S)", IDM_VID_SDL_SW - MENUITEM "SDL (하드웨어)(&H)", IDM_VID_SDL_HW - MENUITEM "SDL (OpenGL)(&O)", IDM_VID_SDL_OPENGL - MENUITEM "OpenGL (3.0 코어)(&G)", IDM_VID_OPENGL_CORE + MENUITEM "SDL (소프트웨어)(&S)", IDM_VID_SDL_SW + MENUITEM "SDL (하드웨어)(&H)", IDM_VID_SDL_HW + MENUITEM "SDL (OpenGL)(&O)", IDM_VID_SDL_OPENGL + MENUITEM "OpenGL (3.0 코어)(&G)", IDM_VID_OPENGL_CORE #ifdef USE_VNC - MENUITEM "VNC(&V)", IDM_VID_VNC + MENUITEM "VNC(&V)", IDM_VID_VNC #endif END MENUITEM SEPARATOR - MENUITEM "ì°½ í¬ê¸° 지정하기...", IDM_VID_SPECIFY_DIM - MENUITEM "화면 ë¹„ìœ¨ì„ 4:3으로 맞추기(&O)", IDM_VID_FORCE43 + MENUITEM "ì°½ í¬ê¸° 지정하기...", IDM_VID_SPECIFY_DIM + MENUITEM "화면 ë¹„ìœ¨ì„ 4:3으로 맞추기(&O)", IDM_VID_FORCE43 POPUP "ì°½ 표시 배율(&W)" BEGIN - MENUITEM "0.5ë°°(&0)", IDM_VID_SCALE_1X - MENUITEM "1ë°°(&1)", IDM_VID_SCALE_2X - MENUITEM "1.5ë°°(&5)", IDM_VID_SCALE_3X - MENUITEM "2ë°°(&2)", IDM_VID_SCALE_4X + MENUITEM "0.5ë°°(&0)", IDM_VID_SCALE_1X + MENUITEM "1ë°°(&1)", IDM_VID_SCALE_2X + MENUITEM "1.5ë°°(&5)", IDM_VID_SCALE_3X + MENUITEM "2ë°°(&2)", IDM_VID_SCALE_4X + MENUITEM "&3ë°°", IDM_VID_SCALE_5X + MENUITEM "&4ë°°", IDM_VID_SCALE_6X + MENUITEM "&5ë°°", IDM_VID_SCALE_7X + MENUITEM "&6ë°°", IDM_VID_SCALE_8X + MENUITEM "&7ë°°", IDM_VID_SCALE_9X + MENUITEM "&8ë°°", IDM_VID_SCALE_10X END POPUP "í•„í„° 형ì‹" BEGIN - MENUITEM "최근방 ì´ì›ƒ 보간법(&N)", IDM_VID_FILTER_NEAREST - MENUITEM "선형 보간법(&L)", IDM_VID_FILTER_LINEAR + MENUITEM "최근방 ì´ì›ƒ 보간법(&N)", IDM_VID_FILTER_NEAREST + MENUITEM "선형 보간법(&L)", IDM_VID_FILTER_LINEAR END - MENUITEM "HiDPI 스케ì¼ë§(&D)", IDM_VID_HIDPI + MENUITEM "HiDPI 스케ì¼ë§(&D)", IDM_VID_HIDPI MENUITEM SEPARATOR - MENUITEM "ì „ì²´ 화면(&F)\tCtrl+Alt+PgUp", IDM_VID_FULLSCREEN + MENUITEM "ì „ì²´ 화면(&F)\tCtrl+Alt+PgUp", IDM_VID_FULLSCREEN POPUP "ì „ì²´ 화면 비율(&S)" BEGIN - MENUITEM "ì „ì²´ 화면으로 확대(&F)", IDM_VID_FS_FULL - MENUITEM "4:3(&4)", IDM_VID_FS_43 + MENUITEM "ì „ì²´ 화면으로 확대(&F)", IDM_VID_FS_FULL + MENUITEM "4:3(&4)", IDM_VID_FS_43 MENUITEM "정사ê°í˜• 픽셀 (비율 유지)(&S)", IDM_VID_FS_KEEPRATIO - MENUITEM "정수배 확대(&I)", IDM_VID_FS_INT + MENUITEM "정수배 확대(&I)", IDM_VID_FS_INT END POPUP "E&GA/(S)VGA 설정" BEGIN - MENUITEM "ìƒ‰ìƒ ë°˜ì „ëœ VGA 모니터(&I)", IDM_VID_INVERT + MENUITEM "ìƒ‰ìƒ ë°˜ì „ëœ VGA 모니터(&I)", IDM_VID_INVERT POPUP "VGA 화면 종류(&T)" BEGIN - MENUITEM "RGB 천연색(&C)", IDM_VID_GRAY_RGB - MENUITEM "RGB 회색조(&R)", IDM_VID_GRAY_MONO - MENUITEM "주황색 모니터(&A)", IDM_VID_GRAY_AMBER - MENUITEM "녹색 모니터(&G)", IDM_VID_GRAY_GREEN - MENUITEM "í°ìƒ‰ 모니터(&W)", IDM_VID_GRAY_WHITE + MENUITEM "RGB 천연색(&C)", IDM_VID_GRAY_RGB + MENUITEM "RGB 회색조(&R)", IDM_VID_GRAY_MONO + MENUITEM "주황색 모니터(&A)", IDM_VID_GRAY_AMBER + MENUITEM "녹색 모니터(&G)", IDM_VID_GRAY_GREEN + MENUITEM "í°ìƒ‰ 모니터(&W)", IDM_VID_GRAY_WHITE END POPUP "회색조 표현방ì‹(&C)" BEGIN - MENUITEM "BT601 (NTSC/PAL)(&6)", IDM_VID_GRAYCT_601 - MENUITEM "BT709 (HDTV)(&7)", IDM_VID_GRAYCT_709 - MENUITEM "í‰ê· ê°’(&A)", IDM_VID_GRAYCT_AVE + MENUITEM "BT601 (NTSC/PAL)(&6)", IDM_VID_GRAYCT_601 + MENUITEM "BT709 (HDTV)(&7)", IDM_VID_GRAYCT_709 + MENUITEM "í‰ê· ê°’(&A)", IDM_VID_GRAYCT_AVE END END MENUITEM SEPARATOR - MENUITEM "CGA/PCjr/Tandy/EGA/(S)VGA 오버스캔(&G)", IDM_VID_OVERSCAN + MENUITEM "CGA/PCjr/Tandy/EGA/(S)VGA 오버스캔(&G)", IDM_VID_OVERSCAN MENUITEM "í‘ë°± 표시를 위한 ë°ê¸° ì¡°ì •(&M)", IDM_VID_CGACON END - MENUITEM "미디어(&M)", IDM_MEDIA + MENUITEM "미디어(&M)", IDM_MEDIA POPUP "ë„구(&T)" BEGIN - MENUITEM "설정(&S)...", IDM_CONFIG - MENUITEM "ìƒíƒœ ë°” ì•„ì´ì½˜ 갱신하기(&U)", IDM_UPDATE_ICONS + MENUITEM "설정(&S)...", IDM_CONFIG + MENUITEM "ìƒíƒœ ë°” ì•„ì´ì½˜ 갱신하기(&U)", IDM_UPDATE_ICONS MENUITEM SEPARATOR - MENUITEM "스í¬ë¦°ìƒ· ì°ê¸°(&C)\tCtrl+F11", IDM_ACTION_SCREENSHOT + MENUITEM "스í¬ë¦°ìƒ· ì°ê¸°(&C)\tCtrl+F11", IDM_ACTION_SCREENSHOT MENUITEM SEPARATOR - MENUITEM "환경설정(&P)...", IDM_PREFERENCES + MENUITEM "환경설정(&P)...", IDM_PREFERENCES +#ifdef DISCORD MENUITEM "디스코드 ì—°ë™ í™œì„±í™”í•˜ê¸°(&D)", IDM_DISCORD +#endif MENUITEM SEPARATOR - MENUITEM "ìŒëŸ‰ ì¦í­(&G)...", IDM_SND_GAIN + MENUITEM "ìŒëŸ‰ ì¦í­(&G)...", IDM_SND_GAIN #ifdef MTR_ENABLED MENUITEM SEPARATOR - MENUITEM "ì¶”ì  ì‹œìž‘í•˜ê¸°\tCtrl+T", IDM_ACTION_BEGIN_TRACE - MENUITEM "ì¶”ì  ë내기\tCtrl+T", IDM_ACTION_END_TRACE + MENUITEM "ì¶”ì  ì‹œìž‘í•˜ê¸°\tCtrl+T", IDM_ACTION_BEGIN_TRACE + MENUITEM "ì¶”ì  ë내기\tCtrl+T", IDM_ACTION_END_TRACE #endif END POPUP "ë„움ë§(&H)" BEGIN - MENUITEM "문서(&D)...", IDM_DOCS - MENUITEM "86Boxì— ëŒ€í•´(&A)...", IDM_ABOUT + MENUITEM "문서(&D)...", IDM_DOCS + MENUITEM "86Boxì— ëŒ€í•´(&A)...", IDM_ABOUT END END -StatusBarMenu MENU DISCARDABLE +StatusBarMenu MENU DISCARDABLE BEGIN MENUITEM SEPARATOR END @@ -128,17 +137,17 @@ CassetteSubmenu MENU DISCARDABLE BEGIN POPUP "" BEGIN - MENUITEM "새 ì´ë¯¸ì§€(&N)...", IDM_CASSETTE_IMAGE_NEW + MENUITEM "새 ì´ë¯¸ì§€(&N)...", IDM_CASSETTE_IMAGE_NEW MENUITEM SEPARATOR - MENUITEM "ì´ë¯¸ì§€ 불러오기(&E)...", IDM_CASSETTE_IMAGE_EXISTING - MENUITEM "ì´ë¯¸ì§€ 불러오기 (쓰기방지)(&W)...", IDM_CASSETTE_IMAGE_EXISTING_WP + MENUITEM "ì´ë¯¸ì§€ 불러오기(&E)...", IDM_CASSETTE_IMAGE_EXISTING + MENUITEM "ì´ë¯¸ì§€ 불러오기 (쓰기방지)(&W)...", IDM_CASSETTE_IMAGE_EXISTING_WP MENUITEM SEPARATOR - MENUITEM "ë…¹ìŒí•˜ê¸°(&R)", IDM_CASSETTE_RECORD - MENUITEM "재ìƒí•˜ê¸°(&P)", IDM_CASSETTE_PLAY - MENUITEM "맨앞으로 ë˜ê°ê¸°(&R)", IDM_CASSETTE_REWIND - MENUITEM "맨ë으로 빨리ê°ê¸°(&F)", IDM_CASSETTE_FAST_FORWARD + MENUITEM "ë…¹ìŒí•˜ê¸°(&R)", IDM_CASSETTE_RECORD + MENUITEM "재ìƒí•˜ê¸°(&P)", IDM_CASSETTE_PLAY + MENUITEM "맨앞으로 ë˜ê°ê¸°(&R)", IDM_CASSETTE_REWIND + MENUITEM "맨ë으로 빨리ê°ê¸°(&F)", IDM_CASSETTE_FAST_FORWARD MENUITEM SEPARATOR - MENUITEM "꺼내기(&J)", IDM_CASSETTE_EJECT + MENUITEM "꺼내기(&J)", IDM_CASSETTE_EJECT END END @@ -146,9 +155,9 @@ CartridgeSubmenu MENU DISCARDABLE BEGIN POPUP "" BEGIN - MENUITEM "ì´ë¯¸ì§€(&I)...", IDM_CARTRIDGE_IMAGE + MENUITEM "ì´ë¯¸ì§€(&I)...", IDM_CARTRIDGE_IMAGE MENUITEM SEPARATOR - MENUITEM "꺼내기(&J)", IDM_CARTRIDGE_EJECT + MENUITEM "꺼내기(&J)", IDM_CARTRIDGE_EJECT END END @@ -156,14 +165,14 @@ FloppySubmenu MENU DISCARDABLE BEGIN POPUP "" BEGIN - MENUITEM "새 ì´ë¯¸ì§€(&N)...", IDM_FLOPPY_IMAGE_NEW + MENUITEM "새 ì´ë¯¸ì§€(&N)...", IDM_FLOPPY_IMAGE_NEW MENUITEM SEPARATOR - MENUITEM "ì´ë¯¸ì§€ 불러오기(&E)...", IDM_FLOPPY_IMAGE_EXISTING - MENUITEM "ì´ë¯¸ì§€ 불러오기 (쓰기방지)(&W)...", IDM_FLOPPY_IMAGE_EXISTING_WP + MENUITEM "ì´ë¯¸ì§€ 불러오기(&E)...", IDM_FLOPPY_IMAGE_EXISTING + MENUITEM "ì´ë¯¸ì§€ 불러오기 (쓰기방지)(&W)...", IDM_FLOPPY_IMAGE_EXISTING_WP MENUITEM SEPARATOR - MENUITEM "86F로 보내기(&X)...", IDM_FLOPPY_EXPORT_TO_86F + MENUITEM "86F로 보내기(&X)...", IDM_FLOPPY_EXPORT_TO_86F MENUITEM SEPARATOR - MENUITEM "꺼내기(&J)", IDM_FLOPPY_EJECT + MENUITEM "꺼내기(&J)", IDM_FLOPPY_EJECT END END @@ -171,12 +180,13 @@ CdromSubmenu MENU DISCARDABLE BEGIN POPUP "" BEGIN - MENUITEM "ìŒì†Œê±°(&M)", IDM_CDROM_MUTE + MENUITEM "ìŒì†Œê±°(&M)", IDM_CDROM_MUTE MENUITEM SEPARATOR - MENUITEM "비었ìŒ(&M)", IDM_CDROM_EMPTY - MENUITEM "ì´ì „ ì´ë¯¸ì§€ 다시 불러오기(&R)", IDM_CDROM_RELOAD + MENUITEM "비었ìŒ(&M)", IDM_CDROM_EMPTY + MENUITEM "ì´ì „ ì´ë¯¸ì§€ 다시 불러오기(&R)", IDM_CDROM_RELOAD MENUITEM SEPARATOR - MENUITEM "ì´ë¯¸ì§€(&I)", IDM_CDROM_IMAGE + MENUITEM "ì´ë¯¸ì§€(&I)...", IDM_CDROM_IMAGE + MENUITEM "í´ë”(&F)...", IDM_CDROM_DIR END END @@ -184,13 +194,13 @@ ZIPSubmenu MENU DISCARDABLE BEGIN POPUP "" BEGIN - MENUITEM "새 ì´ë¯¸ì§€(&N)...", IDM_ZIP_IMAGE_NEW + MENUITEM "새 ì´ë¯¸ì§€(&N)...", IDM_ZIP_IMAGE_NEW MENUITEM SEPARATOR - MENUITEM "ì´ë¯¸ì§€ 불러오기(&E)...", IDM_ZIP_IMAGE_EXISTING - MENUITEM "ì´ë¯¸ì§€ 불러오기 (쓰기방지)(&W)...", IDM_ZIP_IMAGE_EXISTING_WP + MENUITEM "ì´ë¯¸ì§€ 불러오기(&E)...", IDM_ZIP_IMAGE_EXISTING + MENUITEM "ì´ë¯¸ì§€ 불러오기 (쓰기방지)(&W)...", IDM_ZIP_IMAGE_EXISTING_WP MENUITEM SEPARATOR - MENUITEM "꺼내기(&J)", IDM_ZIP_EJECT - MENUITEM "ì´ì „ ì´ë¯¸ì§€ 다시 불러오기(&R)", IDM_ZIP_RELOAD + MENUITEM "꺼내기(&J)", IDM_ZIP_EJECT + MENUITEM "ì´ì „ ì´ë¯¸ì§€ 다시 불러오기(&R)", IDM_ZIP_RELOAD END END @@ -198,13 +208,13 @@ MOSubmenu MENU DISCARDABLE BEGIN POPUP "" BEGIN - MENUITEM "새 ì´ë¯¸ì§€(&N)...", IDM_MO_IMAGE_NEW + MENUITEM "새 ì´ë¯¸ì§€(&N)...", IDM_MO_IMAGE_NEW MENUITEM SEPARATOR - MENUITEM "ì´ë¯¸ì§€ 불러오기(&E)...", IDM_MO_IMAGE_EXISTING - MENUITEM "ì´ë¯¸ì§€ 불러오기 (쓰기방지)(&W)...", IDM_MO_IMAGE_EXISTING_WP + MENUITEM "ì´ë¯¸ì§€ 불러오기(&E)...", IDM_MO_IMAGE_EXISTING + MENUITEM "ì´ë¯¸ì§€ 불러오기 (쓰기방지)(&W)...", IDM_MO_IMAGE_EXISTING_WP MENUITEM SEPARATOR - MENUITEM "꺼내기(&J)", IDM_MO_EJECT - MENUITEM "ì´ì „ ì´ë¯¸ì§€ 다시 불러오기(&R)", IDM_MO_RELOAD + MENUITEM "꺼내기(&J)", IDM_MO_EJECT + MENUITEM "ì´ì „ ì´ë¯¸ì§€ 다시 불러오기(&R)", IDM_MO_RELOAD END END @@ -230,134 +240,150 @@ END // Dialog // -#define STR_PREFERENCES "환경설정" -#define STR_SND_GAIN "ìŒëŸ‰ ì¦í­" -#define STR_NEW_FLOPPY "새 ì´ë¯¸ì§€" -#define STR_CONFIG "설정" -#define STR_SPECIFY_DIM "ì°½ í¬ê¸° 지정" +#define STR_PREFERENCES "환경설정" +#define STR_SND_GAIN "ìŒëŸ‰ ì¦í­" +#define STR_NEW_FLOPPY "새 ì´ë¯¸ì§€" +#define STR_CONFIG "설정" +#define STR_SPECIFY_DIM "ì°½ í¬ê¸° 지정" -#define STR_OK "확ì¸" -#define STR_CANCEL "취소" -#define STR_GLOBAL "ì´ ì„¤ì •ë“¤ì„ ì „ì—­ 기본값으로 저장하기(&G)" -#define STR_DEFAULT "기본값(&D)" -#define STR_LANGUAGE "언어:" -#define STR_ICONSET "ì•„ì´ì½˜ì…‹:" +#define STR_OK "확ì¸" +#define STR_CANCEL "취소" +#define STR_GLOBAL "ì´ ì„¤ì •ë“¤ì„ ì „ì—­ 기본값으로 저장하기(&G)" +#define STR_DEFAULT "기본값(&D)" +#define STR_LANGUAGE "언어:" +#define STR_ICONSET "ì•„ì´ì½˜ì…‹:" -#define STR_GAIN "ì¦ê°€ê°’" +#define STR_GAIN "ì¦ê°€ê°’" -#define STR_FILE_NAME "파ì¼ëª…:" -#define STR_DISK_SIZE "ë””ìŠ¤í¬ ìš©ëŸ‰:" -#define STR_RPM_MODE "RPM 모드:" -#define STR_PROGRESS "ì§„í–‰:" +#define STR_FILE_NAME "파ì¼ëª…:" +#define STR_DISK_SIZE "ë””ìŠ¤í¬ ìš©ëŸ‰:" +#define STR_RPM_MODE "RPM 모드:" +#define STR_PROGRESS "ì§„í–‰:" -#define STR_WIDTH "가로:" -#define STR_HEIGHT "세로:" -#define STR_LOCK_TO_SIZE "í¬ê¸° ê³ ì •" +#define STR_WIDTH "가로:" +#define STR_HEIGHT "세로:" +#define STR_LOCK_TO_SIZE "í¬ê¸° ê³ ì •" -#define STR_MACHINE_TYPE "머신 종류:" -#define STR_MACHINE "기종:" -#define STR_CONFIGURE "설정" -#define STR_CPU_TYPE "CPU 종류:" -#define STR_CPU_SPEED "ì†ë„:" -#define STR_FPU "FPU:" -#define STR_WAIT_STATES "대기 ìƒíƒœ:" -#define STR_MB "MB" -#define STR_MEMORY "메모리:" -#define STR_TIME_SYNC "시간 ë™ê¸°í™”" -#define STR_DISABLED "사용하지 않ìŒ" -#define STR_ENABLED_LOCAL "사용 (현지 시간)" -#define STR_ENABLED_UTC "사용 (UTC)" -#define STR_DYNAREC "ë™ì  재컴파ì¼" +#define STR_MACHINE_TYPE "머신 종류:" +#define STR_MACHINE "기종:" +#define STR_CONFIGURE "설정" +#define STR_CPU_TYPE "CPU 종류:" +#define STR_CPU_SPEED "ì†ë„:" +#define STR_FPU "FPU:" +#define STR_WAIT_STATES "대기 ìƒíƒœ:" +#define STR_MB "MB" +#define STR_MEMORY "메모리:" +#define STR_TIME_SYNC "시간 ë™ê¸°í™”" +#define STR_DISABLED "사용하지 않ìŒ" +#define STR_ENABLED_LOCAL "사용 (현지 시간)" +#define STR_ENABLED_UTC "사용 (UTC)" +#define STR_DYNAREC "ë™ì  재컴파ì¼" +#define STR_SOFTFLOAT "Softfloat FPU" -#define STR_VIDEO "비디오 카드:" -#define STR_VOODOO "Voodoo 그래픽" +#define STR_VIDEO "비디오 카드:" +#define STR_VIDEO_2 "비디오 카드 2:" +#define STR_VOODOO "Voodoo 그래픽" +#define STR_IBM8514 "IBM 8514/a 그래픽" +#define STR_XGA "XGA 그래픽" -#define STR_MOUSE "마우스:" -#define STR_JOYSTICK "ì¡°ì´ìŠ¤í‹±:" -#define STR_JOY1 "ì¡°ì´ìŠ¤í‹± 1..." -#define STR_JOY2 "ì¡°ì´ìŠ¤í‹± 2..." -#define STR_JOY3 "ì¡°ì´ìŠ¤í‹± 3..." -#define STR_JOY4 "ì¡°ì´ìŠ¤í‹± 4..." +#define STR_MOUSE "마우스:" +#define STR_JOYSTICK "ì¡°ì´ìŠ¤í‹±:" +#define STR_JOY1 "ì¡°ì´ìŠ¤í‹± 1..." +#define STR_JOY2 "ì¡°ì´ìŠ¤í‹± 2..." +#define STR_JOY3 "ì¡°ì´ìŠ¤í‹± 3..." +#define STR_JOY4 "ì¡°ì´ìŠ¤í‹± 4..." -#define STR_SOUND "사운드 카드:" -#define STR_MIDI_OUT "MIDI 출력 장치:" -#define STR_MIDI_IN "MIDI ìž…ë ¥ 장치:" -#define STR_MPU401 "MPU-401 ë‹¨ë… ì‚¬ìš©" -#define STR_SSI "Innovation SSI-2001" -#define STR_CMS "CMS / Game Blaster" -#define STR_GUS "Gravis Ultrasound" -#define STR_FLOAT "FLOAT32 사운드 사용" +#define STR_SOUND1 "사운드 카드 1:" +#define STR_SOUND2 "사운드 카드 2:" +#define STR_SOUND3 "사운드 카드 3:" +#define STR_SOUND4 "사운드 카드 4:" +#define STR_MIDI_OUT "MIDI 출력 장치:" +#define STR_MIDI_IN "MIDI ìž…ë ¥ 장치:" +#define STR_MPU401 "MPU-401 ë‹¨ë… ì‚¬ìš©" +#define STR_FLOAT "FLOAT32 사운드 사용" +#define STR_FM_DRIVER "FM 신디사ì´ì € 드ë¼ì´ë²„" +#define STR_FM_DRV_NUKED "Nuked (ë” ì •í™•í•œ)" +#define STR_FM_DRV_YMFM "YMFM (ë” ë¹ ë¥´ê²Œ)" -#define STR_NET_TYPE "ë„¤íŠ¸ì›Œí¬ ì¢…ë¥˜:" -#define STR_PCAP "PCap 장치:" -#define STR_NET "ë„¤íŠ¸ì›Œí¬ ì–´ëŒ‘í„°:" +#define STR_NET_TYPE "ë„¤íŠ¸ì›Œí¬ ì¢…ë¥˜:" +#define STR_PCAP "PCap 장치:" +#define STR_NET "ë„¤íŠ¸ì›Œí¬ ì–´ëŒ‘í„°:" +#define STR_NET1 "ë„¤íŠ¸ì›Œí¬ ì¹´ë“œ 1:" +#define STR_NET2 "ë„¤íŠ¸ì›Œí¬ ì¹´ë“œ 2:" +#define STR_NET3 "ë„¤íŠ¸ì›Œí¬ ì¹´ë“œ 3:" +#define STR_NET4 "ë„¤íŠ¸ì›Œí¬ ì¹´ë“œ 4:" -#define STR_COM1 "COM1 장치:" -#define STR_COM2 "COM2 장치:" -#define STR_COM3 "COM3 장치:" -#define STR_COM4 "COM4 장치:" -#define STR_LPT1 "LPT1 장치:" -#define STR_LPT2 "LPT2 장치:" -#define STR_LPT3 "LPT3 장치:" -#define STR_LPT4 "LPT4 장치:" -#define STR_SERIAL1 "ì§ë ¬ í¬íЏ 1" -#define STR_SERIAL2 "ì§ë ¬ í¬íЏ 2" -#define STR_SERIAL3 "ì§ë ¬ í¬íЏ 3" -#define STR_SERIAL4 "ì§ë ¬ í¬íЏ 4" -#define STR_PARALLEL1 "병렬 í¬íЏ 1" -#define STR_PARALLEL2 "병렬 í¬íЏ 2" -#define STR_PARALLEL3 "병렬 í¬íЏ 3" -#define STR_PARALLEL4 "병렬 í¬íЏ 4" +#define STR_COM1 "COM1 장치:" +#define STR_COM2 "COM2 장치:" +#define STR_COM3 "COM3 장치:" +#define STR_COM4 "COM4 장치:" +#define STR_LPT1 "LPT1 장치:" +#define STR_LPT2 "LPT2 장치:" +#define STR_LPT3 "LPT3 장치:" +#define STR_LPT4 "LPT4 장치:" +#define STR_SERIAL1 "ì§ë ¬ í¬íЏ 1" +#define STR_SERIAL2 "ì§ë ¬ í¬íЏ 2" +#define STR_SERIAL3 "ì§ë ¬ í¬íЏ 3" +#define STR_SERIAL4 "ì§ë ¬ í¬íЏ 4" +#define STR_PARALLEL1 "병렬 í¬íЏ 1" +#define STR_PARALLEL2 "병렬 í¬íЏ 2" +#define STR_PARALLEL3 "병렬 í¬íЏ 3" +#define STR_PARALLEL4 "병렬 í¬íЏ 4" +#define STR_SERIAL_PASS1 "ì§ë ¬ í¬íЏ 패스쓰루 1" +#define STR_SERIAL_PASS2 "ì§ë ¬ í¬íЏ 패스쓰루 2" +#define STR_SERIAL_PASS3 "ì§ë ¬ í¬íЏ 패스쓰루 3" +#define STR_SERIAL_PASS4 "ì§ë ¬ í¬íЏ 패스쓰루 4" -#define STR_HDC "HD 컨트롤러:" -#define STR_FDC "FD 컨트롤러:" -#define STR_IDE_TER "ì œ3ì˜ IDE 컨트롤러" -#define STR_IDE_QUA "ì œ4ì˜ IDE 컨트롤러" -#define STR_SCSI "SCSI" -#define STR_SCSI_1 "컨트롤러 1:" -#define STR_SCSI_2 "컨트롤러 2:" -#define STR_SCSI_3 "컨트롤러 3:" -#define STR_SCSI_4 "컨트롤러 4:" -#define STR_CASSETTE "카세트 í…Œì´í”„" +#define STR_HDC "HD 컨트롤러:" +#define STR_FDC "FD 컨트롤러:" +#define STR_IDE_TER "ì œ3ì˜ IDE 컨트롤러" +#define STR_IDE_QUA "ì œ4ì˜ IDE 컨트롤러" +#define STR_SCSI "SCSI" +#define STR_SCSI_1 "컨트롤러 1:" +#define STR_SCSI_2 "컨트롤러 2:" +#define STR_SCSI_3 "컨트롤러 3:" +#define STR_SCSI_4 "컨트롤러 4:" +#define STR_CASSETTE "카세트 í…Œì´í”„" -#define STR_HDD "하드 디스í¬:" -#define STR_NEW "새로 만들기(&N)..." -#define STR_EXISTING "불러오기(&E)..." -#define STR_REMOVE "목ë¡ì—서 제거(&R)" -#define STR_BUS "버스:" -#define STR_CHANNEL "채ë„:" -#define STR_ID "ID:" +#define STR_HDD "하드 디스í¬:" +#define STR_NEW "새로 만들기(&N)..." +#define STR_EXISTING "불러오기(&E)..." +#define STR_REMOVE "목ë¡ì—서 제거(&R)" +#define STR_BUS "버스:" +#define STR_CHANNEL "채ë„:" +#define STR_ID "ID:" +#define STR_SPEED "Speed:" -#define STR_SPECIFY "열기(&S)..." -#define STR_SECTORS "섹터:" -#define STR_HEADS "헤드:" -#define STR_CYLS "실린ë”:" -#define STR_SIZE_MB "용량(MB):" -#define STR_TYPE "형ì‹:" -#define STR_IMG_FORMAT "ì´ë¯¸ì§€ í¬ë§·:" -#define STR_BLOCK_SIZE "ë¸”ë¡ í¬ê¸°:" +#define STR_SPECIFY "열기(&S)..." +#define STR_SECTORS "섹터:" +#define STR_HEADS "헤드:" +#define STR_CYLS "실린ë”:" +#define STR_SIZE_MB "용량(MB):" +#define STR_TYPE "형ì‹:" +#define STR_IMG_FORMAT "ì´ë¯¸ì§€ í¬ë§·:" +#define STR_BLOCK_SIZE "ë¸”ë¡ í¬ê¸°:" -#define STR_FLOPPY_DRIVES "플로피 드ë¼ì´ë¸Œ:" -#define STR_TURBO "ê³ ì† ë™ìž‘" -#define STR_CHECKBPB "BPB 확ì¸" -#define STR_CDROM_DRIVES "CD-ROM 드ë¼ì´ë¸Œ:" -#define STR_CD_SPEED "ì†ë„:" +#define STR_FLOPPY_DRIVES "플로피 드ë¼ì´ë¸Œ:" +#define STR_TURBO "ê³ ì† ë™ìž‘" +#define STR_CHECKBPB "BPB 확ì¸" +#define STR_CDROM_DRIVES "CD-ROM 드ë¼ì´ë¸Œ:" +#define STR_CD_SPEED "ì†ë„:" -#define STR_MO_DRIVES "ê´‘ìžê¸° 드ë¼ì´ë¸Œ:" -#define STR_ZIP_DRIVES "ZIP 드ë¼ì´ë¸Œ:" -#define STR_250 "ZIP 250" +#define STR_MO_DRIVES "ê´‘ìžê¸° 드ë¼ì´ë¸Œ:" +#define STR_ZIP_DRIVES "ZIP 드ë¼ì´ë¸Œ:" +#define STR_250 "ZIP 250" -#define STR_ISARTC "ISA RTC 카드:" -#define STR_ISAMEM "ISA 메모리 확장 카드" -#define STR_ISAMEM_1 "카드 1:" -#define STR_ISAMEM_2 "카드 2:" -#define STR_ISAMEM_3 "카드 3:" -#define STR_ISAMEM_4 "카드 4:" -#define STR_BUGGER "ISABugger 장치" -#define STR_POSTCARD "POST 카드" +#define STR_ISARTC "ISA RTC 카드:" +#define STR_ISAMEM "ISA 메모리 확장 카드" +#define STR_ISAMEM_1 "카드 1:" +#define STR_ISAMEM_2 "카드 2:" +#define STR_ISAMEM_3 "카드 3:" +#define STR_ISAMEM_4 "카드 4:" +#define STR_BUGGER "ISABugger 장치" +#define STR_POSTCARD "POST 카드" -#define FONT_SIZE 9 -#define FONT_NAME "Malgun Gothic" +#define FONT_SIZE 9 +#define FONT_NAME "Malgun Gothic" #include "dialogs.rc" @@ -366,194 +392,188 @@ END // String Table // -STRINGTABLE DISCARDABLE +STRINGTABLE DISCARDABLE BEGIN - 2048 "86Box" - IDS_2049 "오류" - IDS_2050 "치명ì ì¸ 오류" - IDS_2051 " - PAUSED" - IDS_2052 "Ctrl+Alt+PgDn 키를 누르면 ì°½ 모드로 전환합니다." - IDS_2053 "ì†ë„" - IDS_2054 "ZIP %03i %i (%s): %ls" - IDS_2055 "ZIP ì´ë¯¸ì§€ (*.IM?;*.ZDI)\0*.IM?;*.ZDI\0" - IDS_2056 "86Boxì—서 사용 가능한 ROM ì´ë¯¸ì§€ë¥¼ ì°¾ì„ ìˆ˜ 없습니다.\n\nROM 세트를다운로드 후 ""roms"" ë””ë ‰í† ë¦¬ì— ì••ì¶•ì„ í’€ì–´ 주세요." - IDS_2057 "(비었ìŒ)" - IDS_2058 "ZIP ì´ë¯¸ì§€ (*.IM?;*.ZDI)\0*.IM?;*.ZDI\0모든 íŒŒì¼ (*.*)\0*.*\0" - IDS_2059 "í„°ë³´" - IDS_2060 "켜ì§" - IDS_2061 "꺼ì§" - IDS_2062 "모든 ì´ë¯¸ì§€ (*.86F;*.DSK;*.FLP;*.IM?;*.*FD?)\0*.86F;*.DSK;*.FLP;*.IM?;*.*FD?\0기본 섹터 ì´ë¯¸ì§€ (*.DSK;*.FLP;*.IM?;*.*FD?)\0*.DSK;*.FLP;*.IM?;*.IMG;*.*FD?\0표면 ì´ë¯¸ì§€ (*.86F)\0*.86F\0" - IDS_2063 "roms/machines ë””ë ‰í† ë¦¬ì— í•„ìš”í•œ 롬파ì¼ì´ 없어 기종 ""%hs""ì„(를) 사용할 수 없습니다. 사용 가능한 기종으로 변경합니다." + 2048 "86Box" + IDS_2049 "오류" + IDS_2050 "치명ì ì¸ 오류" + IDS_2051 " - ì¼ì‹œì¤‘ì§€" + IDS_2052 "Ctrl+Alt+PgDn 키를 누르면 ì°½ 모드로 전환합니다." + IDS_2053 "ì†ë„" + IDS_2054 "ZIP %03i %i (%s): %ls" + IDS_2055 "ZIP ì´ë¯¸ì§€ (*.IM?;*.ZDI)\0*.IM?;*.ZDI\0" + IDS_2056 "86Boxì—서 사용 가능한 ROM ì´ë¯¸ì§€ë¥¼ ì°¾ì„ ìˆ˜ 없습니다.\n\nROM 세트를다운로드 후 ""roms"" ë””ë ‰í† ë¦¬ì— ì••ì¶•ì„ í’€ì–´ 주세요." + IDS_2057 "(비었ìŒ)" + IDS_2058 "ZIP ì´ë¯¸ì§€ (*.IM?;*.ZDI)\0*.IM?;*.ZDI\0모든 íŒŒì¼ (*.*)\0*.*\0" + IDS_2059 "í„°ë³´" + IDS_2060 "켜ì§" + IDS_2061 "꺼ì§" + IDS_2062 "모든 ì´ë¯¸ì§€ (*.86F;*.DSK;*.FLP;*.IM?;*.*FD?)\0*.86F;*.DSK;*.FLP;*.IM?;*.*FD?\0기본 섹터 ì´ë¯¸ì§€ (*.DSK;*.FLP;*.IM?;*.*FD?)\0*.DSK;*.FLP;*.IM?;*.IMG;*.*FD?\0표면 ì´ë¯¸ì§€ (*.86F)\0*.86F\0" + IDS_2063 "roms/machines ë””ë ‰í† ë¦¬ì— í•„ìš”í•œ 롬파ì¼ì´ 없어 기종 ""%hs""ì„(를) 사용할 수 없습니다. 사용 가능한 기종으로 변경합니다." END -STRINGTABLE DISCARDABLE +STRINGTABLE DISCARDABLE BEGIN - IDS_2064 "roms/video ë””ë ‰í† ë¦¬ì— í•„ìš”í•œ 롬파ì¼ì´ 없어 비디오 카드 ""%hs""ì„(를) 사용할 수 없습니다. 사용 가능한 기종으로 변경합니다." - IDS_2065 "기종" - IDS_2066 "디스플레ì´" - IDS_2067 "ìž…ë ¥ 장치" - IDS_2068 "사운드" - IDS_2069 "네트워í¬" - IDS_2070 "í¬íЏ (COM & LPT)" - IDS_2071 "장치 컨트롤러" - IDS_2072 "하드 디스í¬" - IDS_2073 "플로피 / CD-ROM" - IDS_2074 "기타 ì´ë™ì‹ 저장장치" - IDS_2075 "기타 주변기기" - IDS_2076 "표면 ì´ë¯¸ì§€ (*.86F)\0*.86F\0" - IDS_2077 "ì´ ì°½ì„ í´ë¦­í•˜ë©´ 마우스를 사용합니다" - IDS_2078 "F12+F8키를 누르면 마우스를 해제합니다" - IDS_2079 "F12+F8키 ë˜ëŠ” ê°€ìš´ë° ë²„íŠ¼ì„ í´ë¦­í•˜ë©´ 마우스를 해제합니다" + IDS_2064 "roms/video ë””ë ‰í† ë¦¬ì— í•„ìš”í•œ 롬파ì¼ì´ 없어 비디오 카드 ""%hs""ì„(를) 사용할 수 없습니다. 사용 가능한 기종으로 변경합니다." + IDS_2065 "기종" + IDS_2066 "디스플레ì´" + IDS_2067 "ìž…ë ¥ 장치" + IDS_2068 "사운드" + IDS_2069 "네트워í¬" + IDS_2070 "í¬íЏ (COM & LPT)" + IDS_2071 "장치 컨트롤러" + IDS_2072 "하드 디스í¬" + IDS_2073 "플로피 / CD-ROM" + IDS_2074 "기타 ì´ë™ì‹ 저장장치" + IDS_2075 "기타 주변기기" + IDS_2076 "표면 ì´ë¯¸ì§€ (*.86F)\0*.86F\0" + IDS_2077 "ì´ ì°½ì„ í´ë¦­í•˜ë©´ 마우스를 사용합니다" + IDS_2078 "F12+F8키를 누르면 마우스를 해제합니다" + IDS_2079 "F12+F8키 ë˜ëŠ” ê°€ìš´ë° ë²„íŠ¼ì„ í´ë¦­í•˜ë©´ 마우스를 해제합니다" END -STRINGTABLE DISCARDABLE +STRINGTABLE DISCARDABLE BEGIN - IDS_2080 "FluidSynth를 초기화할 수 없습니다" - IDS_2081 "버스" - IDS_2082 "파ì¼" - IDS_2083 "C" - IDS_2084 "H" - IDS_2085 "S" - IDS_2086 "MB" - IDS_2087 "BPB 확ì¸" - IDS_2088 "KB" - IDS_2089 "비디오 ë Œë”러를 초기화할 수 없습니다." - IDS_2090 "기본값" - IDS_2091 "%i 대기 ìƒíƒœ" - IDS_2092 "형ì‹" - IDS_2093 "PCap ì„¤ì •ì— ì‹¤íŒ¨í–ˆìŠµë‹ˆë‹¤" - IDS_2094 "PCap 장치가 없습니다" - IDS_2095 "PCap 장치가 올바르지 않습니다" - IDS_2096 "표준 2버튼 ì¡°ì´ìŠ¤í‹±" - IDS_2097 "표준 4버튼 ì¡°ì´ìŠ¤í‹±" - IDS_2098 "표준 6버튼 ì¡°ì´ìŠ¤í‹±" - IDS_2099 "표준 8버튼 ì¡°ì´ìŠ¤í‹±" - IDS_2100 "CH Flightstick Pro" - IDS_2101 "Microsoft SideWinder Pad" - IDS_2102 "Thrustmaster Flight Control System" - IDS_2103 "ì—†ìŒ" - IDS_2104 "키보드 ê°€ì†ê¸°ë¥¼ 불러올 수 없습니다." - IDS_2105 "Raw ìž…ë ¥ì„ ë“±ë¡í•  수 없습니다." - IDS_2106 "%u" - IDS_2107 "%u MB (CHS: %i, %i, %i)" - IDS_2108 "플로피 %i (%s): %ls" - IDS_2109 "모든 ì´ë¯¸ì§€ (*.0??;*.1??;*.??0;*.86F;*.BIN;*.CQ?;*.D??;*.FLP;*.HDM;*.IM?;*.JSON;*.TD0;*.*FD?;*.MFM;*.XDF)\0*.0??;*.1??;*.??0;*.86F;*.BIN;*.CQ?;*.D??;*.FLP;*.HDM;*.IM?;*.JSON;*.TD0;*.*FD?;*.MFM;*.XDF\0어드밴스드 섹터 ì´ë¯¸ì§€ (*.IMD;*.JSON;*.TD0)\0*.IMD;*.JSON;*.TD0\0기본 섹터 ì´ë¯¸ì§€ (*.0??;*.1??;*.??0;*.BIN;*.CQ?;*.D??;*.FLP;*.HDM;*.IM?;*.XDF;*.*FD?)\0*.0??;*.1??;*.??0;*.BIN;*.CQ?;*.D??;*.FLP;*.HDM;*.IM?;*.XDF;*.*FD?\0플럭스 ì´ë¯¸ì§€ (*.FDI)\0*.FDI\0표면 ì´ë¯¸ì§€ (*.86F;*.MFM)\0*.86F;*.MFM\0모든 íŒŒì¼ (*.*)\0*.*\0" - IDS_2110 "FreeTypeì„ ì´ˆê¸°í™”í•  수 없습니다" - IDS_2111 "SDLì„ ì´ˆê¸°í™”í•  수 없습니다. SDL2.dllì´ í•„ìš”í•©ë‹ˆë‹¤" - IDS_2112 "ì‹¤í–‰ì¤‘ì¸ ë¨¸ì‹ ì„ ìž¬ì‹œìž‘í•˜ì‹œê² ìŠµë‹ˆê¹Œ?" - IDS_2113 "86Box를 ë내시겠습니까?" - IDS_2114 "Ghostscript를 초기화할 수 없습니다" - IDS_2115 "ê´‘ìžê¸° %i (%ls): %ls" - IDS_2116 "ê´‘ìžê¸° ì´ë¯¸ì§€ (*.IM?;*.MDI)\0*.IM?;*.MDI\0모든 íŒŒì¼ (*.*)\0*.*\0" - IDS_2117 "86Boxì— ì–´ì„œì˜¤ì„¸ìš”!" - IDS_2118 "ë‚´ë¶€ 컨트롤러" - IDS_2119 "ë내기" - IDS_2120 "ROMì„ ë¶ˆëŸ¬ì˜¬ 수 없습니다" - IDS_2121 "ì„¤ì •ì„ ì €ìž¥í•˜ì‹œê² ìŠµë‹ˆê¹Œ?" - IDS_2122 "ì‚¬ìš©ì¤‘ì¸ ë¨¸ì‹ ì´ ìž¬ë¶€íŒ…ë©ë‹ˆë‹¤." - IDS_2123 "저장" - IDS_2124 "86Boxì— ëŒ€í•´" - IDS_2125 "86Box v" EMU_VERSION + IDS_2081 "버스" + IDS_2082 "파ì¼" + IDS_2083 "C" + IDS_2084 "H" + IDS_2085 "S" + IDS_2086 "MB" + IDS_2087 "Speed" + IDS_2088 "BPB 확ì¸" + IDS_2089 "KB" + IDS_2090 "비디오 ë Œë”러를 초기화할 수 없습니다." + IDS_2091 "기본값" + IDS_2092 "%i 대기 ìƒíƒœ" + IDS_2093 "형ì‹" + IDS_2094 "PCap ì„¤ì •ì— ì‹¤íŒ¨í–ˆìŠµë‹ˆë‹¤" + IDS_2095 "PCap 장치가 없습니다" + IDS_2096 "PCap 장치가 올바르지 않습니다" + IDS_2097 "표준 2버튼 ì¡°ì´ìŠ¤í‹±" + IDS_2098 "표준 4버튼 ì¡°ì´ìŠ¤í‹±" + IDS_2099 "표준 6버튼 ì¡°ì´ìŠ¤í‹±" + IDS_2100 "표준 8버튼 ì¡°ì´ìŠ¤í‹±" + IDS_2101 "CH Flightstick Pro" + IDS_2102 "Microsoft SideWinder Pad" + IDS_2103 "Thrustmaster Flight Control System" + IDS_2104 "ì—†ìŒ" + IDS_2105 "키보드 ê°€ì†ê¸°ë¥¼ 불러올 수 없습니다." + IDS_2106 "Raw ìž…ë ¥ì„ ë“±ë¡í•  수 없습니다." + IDS_2107 "%u" + IDS_2108 "%u MB (CHS: %i, %i, %i)" + IDS_2109 "플로피 %i (%s): %ls" + IDS_2110 "모든 ì´ë¯¸ì§€ (*.0??;*.1??;*.??0;*.86F;*.BIN;*.CQ?;*.D??;*.FLP;*.HDM;*.IM?;*.JSON;*.TD0;*.*FD?;*.MFM;*.XDF)\0*.0??;*.1??;*.??0;*.86F;*.BIN;*.CQ?;*.D??;*.FLP;*.HDM;*.IM?;*.JSON;*.TD0;*.*FD?;*.MFM;*.XDF\0어드밴스드 섹터 ì´ë¯¸ì§€ (*.IMD;*.JSON;*.TD0)\0*.IMD;*.JSON;*.TD0\0기본 섹터 ì´ë¯¸ì§€ (*.0??;*.1??;*.??0;*.BIN;*.CQ?;*.D??;*.FLP;*.HDM;*.IM?;*.XDF;*.*FD?)\0*.0??;*.1??;*.??0;*.BIN;*.CQ?;*.D??;*.FLP;*.HDM;*.IM?;*.XDF;*.*FD?\0플럭스 ì´ë¯¸ì§€ (*.FDI)\0*.FDI\0표면 ì´ë¯¸ì§€ (*.86F;*.MFM)\0*.86F;*.MFM\0모든 íŒŒì¼ (*.*)\0*.*\0" + IDS_2112 "SDLì„ ì´ˆê¸°í™”í•  수 없습니다. SDL2.dllì´ í•„ìš”í•©ë‹ˆë‹¤" + IDS_2113 "ì‹¤í–‰ì¤‘ì¸ ë¨¸ì‹ ì„ ìž¬ì‹œìž‘í•˜ì‹œê² ìŠµë‹ˆê¹Œ?" + IDS_2114 "86Box를 ë내시겠습니까?" + IDS_2115 "Ghostscript를 초기화할 수 없습니다" + IDS_2116 "ê´‘ìžê¸° %i (%ls): %ls" + IDS_2117 "ê´‘ìžê¸° ì´ë¯¸ì§€ (*.IM?;*.MDI)\0*.IM?;*.MDI\0모든 íŒŒì¼ (*.*)\0*.*\0" + IDS_2118 "86Boxì— ì–´ì„œì˜¤ì„¸ìš”!" + IDS_2119 "ë‚´ë¶€ 컨트롤러" + IDS_2120 "ë내기" + IDS_2121 "ROMì„ ë¶ˆëŸ¬ì˜¬ 수 없습니다" + IDS_2122 "ì„¤ì •ì„ ì €ìž¥í•˜ì‹œê² ìŠµë‹ˆê¹Œ?" + IDS_2123 "ì‚¬ìš©ì¤‘ì¸ ë¨¸ì‹ ì´ ìž¬ë¶€íŒ…ë©ë‹ˆë‹¤." + IDS_2124 "저장" + IDS_2125 "86Boxì— ëŒ€í•´" + IDS_2126 "86Box v" EMU_VERSION - IDS_2126 "ê³ ì „ 컴퓨터 ì—뮬레ì´í„°\n\nì €ìž: Sarah Walker, Miran Grca, Fred N. van Kempen (waltje), SA1988, Tiseno100, reenigne, leilei, JohnElliott, greatpsycho, and others.\n\nGNU General Public ë¼ì´ì„ ìФ (버전 2 ì´ìƒ)ì— ì˜í•´ ë°°í¬ë˜ì—ˆìŠµë‹ˆë‹¤. ìžì„¸í•œ ë‚´ìš©ì€ LICENSE 파ì¼ì„ ì½ì–´ 주세요." - IDS_2127 "확ì¸" - IDS_2128 "하드웨어를 ì´ìš©í•  수 없습니다" + IDS_2127 "ê³ ì „ 컴퓨터 ì—뮬레ì´í„°\n\nì €ìž: Miran GrÄa (OBattler), RichardG867, Jasmine Iwanek, TC1995, coldbrewed, Teemu Korhonen (Manaatti), Joakim L. Gilje, Adrien Moulin (elyosh), Daniel Balsom (gloriouscow), Cacodemon345, Fred N. van Kempen (waltje), Tiseno100, reenigne, and others.\n\nWith previous core contributions from Sarah Walker, leilei, JohnElliott, greatpsycho, and others.\n\nGNU General Public ë¼ì´ì„ ìФ (버전 2 ì´ìƒ)ì— ì˜í•´ ë°°í¬ë˜ì—ˆìŠµë‹ˆë‹¤. ìžì„¸í•œ ë‚´ìš©ì€ LICENSE 파ì¼ì„ ì½ì–´ 주세요." + IDS_2128 "확ì¸" + IDS_2129 "하드웨어를 ì´ìš©í•  수 없습니다" #ifdef _WIN32 #define LIB_NAME_PCAP "WinPcap" #else #define LIB_NAME_PCAP "libpcap" #endif - IDS_2129 LIB_NAME_PCAP "ì´ ì„¤ì¹˜ë˜ì—ˆëŠ”ì§€ " LIB_NAME_PCAP "ì— ëŒ€ì‘하는 네트워í¬ì— ì ‘ì†ë˜ì–´ 있는지 확ì¸í•´ 주세요." - IDS_2130 "올바르지 ì•Šì€ ì„¤ì •ìž…ë‹ˆë‹¤" -#ifdef _WIN32 -#define LIB_NAME_FREETYPE "freetype.dll" -#else -#define LIB_NAME_FREETYPE "libfreetype" -#endif - IDS_2131 "ESC/P 프린터 ì—뮬레ì´ì…˜ì— " LIB_NAME_FREETYPE "ì´(ê°€) 필요합니다." + IDS_2130 LIB_NAME_PCAP "ì´ ì„¤ì¹˜ë˜ì—ˆëŠ”ì§€ " LIB_NAME_PCAP "ì— ëŒ€ì‘하는 네트워í¬ì— ì ‘ì†ë˜ì–´ 있는지 확ì¸í•´ 주세요." + IDS_2131 "올바르지 ì•Šì€ ì„¤ì •ìž…ë‹ˆë‹¤" #ifdef _WIN32 #define LIB_NAME_GS "gsdll32.dll" #else #define LIB_NAME_GS "libgs" #endif - IDS_2132 LIB_NAME_GS "ì€(는) PostScript 파ì¼ì„ PDF로 ìžë™ë³€í™˜í•˜ëŠ” ë°ì— 필요합니다.\n\n표준 PostScript 프린터로 ë³´ë‚´ì‹  ìž„ì˜ì˜ 문서는 PostScript (.ps) 파ì¼ë¡œ 저장ë©ë‹ˆë‹¤." -#ifdef _WIN32 -#define LIB_NAME_FLUIDSYNTH "libfluidsynth.dll" -#else -#define LIB_NAME_FLUIDSYNTH "libfluidsynth" -#endif - IDS_2133 "FluidSynthì˜ MIDI ì¶œë ¥ì— " LIB_NAME_FLUIDSYNTH "ì´(ê°€) 필요합니다." - IDS_2134 "ì „ì²´ 화면으로 전환" - IDS_2135 "ì´ ë©”ì‹œì§€ 그만 보기" - IDS_2136 "ëë‚´ì§€ 않기" - IDS_2137 "재시작" - IDS_2138 "재시작 안함" - IDS_2139 "ê´‘ìžê¸° ì´ë¯¸ì§€ (*.IM?;*.MDI)\0*.IM?;*.MDI\0모든 íŒŒì¼ (*.*)\0*.*\0" - IDS_2140 "CD-ROM ì´ë¯¸ì§€ (*.ISO;*.CUE)\0*.ISO;*.CUE\0모든 íŒŒì¼ (*.*)\0*.*\0" - IDS_2141 "%hs 장치 설정" - IDS_2142 "모니터 절전 모드" - IDS_2143 "OpenGL ì‰ì´ë” (*.GLSL)\0*.GLSL\0모든 íŒŒì¼ (*.*)\0*.*\0" - IDS_2144 "OpenGL 설정" - IDS_2145 "ì§€ì›í•˜ì§€ 않는 설정입니다" - IDS_2146 "ì´ ì—뮬레ì´íŠ¸ëœ ê¸°ì¢…ì— ëŒ€í•´ ì„ íƒí•œ ê¸°ì¢…ì„ ê¸°ë°˜ìœ¼ë¡œ 하는 CPU 종류 í•„í„°ë§ì´ 사용ë˜ì§€ 않ë„ë¡ ì„¤ì •ë˜ì—ˆìŠµë‹ˆë‹¤.\n\në”°ë¼ì„œ ì„ íƒëœ 머신과 호환ë˜ì§€ 않는 CPU를 ì„ íƒí•˜ì‹¤ 수 있습니다. 하지만 BIOS ë˜ëŠ” 다른 소프트웨어와 호환ë˜ì§€ ì•Šì„ ìˆ˜ 있습니다.\n\nì´ ì„¤ì •ì„ í™œì„±í™”í•˜ëŠ” ê²ƒì€ ê³µì‹ì ìœ¼ë¡œ ì§€ì›ë˜ì§€ 않으며, ì œì¶œëœ ë²„ê·¸ 보고서는 유효하지 않ìŒìœ¼ë¡œ ë‹«íž ìˆ˜ 있습니다." - IDS_2147 "계ì†" - IDS_2148 "카세트: %s" - IDS_2149 "카세트 ì´ë¯¸ì§€ (*.PCM;*.RAW;*.WAV;*.CAS)\0*.PCM;*.RAW;*.WAV;*.CAS\0모든 íŒŒì¼ (*.*)\0*.*\0" - IDS_2150 "카트리지 %i: %ls" - IDS_2151 "카트리지 ì´ë¯¸ì§€ (*.A;*.B;*.JRC)\0*.A;*.B;*.JRC\0모든 íŒŒì¼ (*.*)\0*.*\0" - IDS_2152 "Error initializing renderer" - IDS_2153 "OpenGL (3.0 Core) renderer could not be initialized. Use another renderer." - IDS_2154 "Resume execution" - IDS_2155 "Pause execution" - IDS_2156 "Press Ctrl+Alt+Del" - IDS_2157 "Press Ctrl+Alt+Esc" - IDS_2158 "Hard reset" - IDS_2159 "ACPI shutdown" - IDS_2160 "Settings" + IDS_2133 LIB_NAME_GS "ì€(는) PostScript 파ì¼ì„ PDF로 ìžë™ë³€í™˜í•˜ëŠ” ë°ì— 필요합니다.\n\n표준 PostScript 프린터로 ë³´ë‚´ì‹  ìž„ì˜ì˜ 문서는 PostScript (.ps) 파ì¼ë¡œ 저장ë©ë‹ˆë‹¤." + IDS_2135 "ì „ì²´ 화면으로 전환" + IDS_2136 "ì´ ë©”ì‹œì§€ 그만 보기" + IDS_2137 "ëë‚´ì§€ 않기" + IDS_2138 "재시작" + IDS_2139 "재시작 안함" + IDS_2140 "ê´‘ìžê¸° ì´ë¯¸ì§€ (*.IM?;*.MDI)\0*.IM?;*.MDI\0모든 íŒŒì¼ (*.*)\0*.*\0" + IDS_2141 "CD-ROM ì´ë¯¸ì§€ (*.ISO;*.CUE)\0*.ISO;*.CUE\0모든 íŒŒì¼ (*.*)\0*.*\0" + IDS_2142 "%hs 장치 설정" + IDS_2143 "모니터 절전 모드" + IDS_2144 "OpenGL ì‰ì´ë” (*.GLSL)\0*.GLSL\0모든 íŒŒì¼ (*.*)\0*.*\0" + IDS_2145 "OpenGL 설정" + IDS_2146 "ì§€ì›í•˜ì§€ 않는 설정입니다" + IDS_2147 "ì´ ì—뮬레ì´íŠ¸ëœ ê¸°ì¢…ì— ëŒ€í•´ ì„ íƒí•œ ê¸°ì¢…ì„ ê¸°ë°˜ìœ¼ë¡œ 하는 CPU 종류 í•„í„°ë§ì´ 사용ë˜ì§€ 않ë„ë¡ ì„¤ì •ë˜ì—ˆìŠµë‹ˆë‹¤.\n\në”°ë¼ì„œ ì„ íƒëœ 머신과 호환ë˜ì§€ 않는 CPU를 ì„ íƒí•˜ì‹¤ 수 있습니다. 하지만 BIOS ë˜ëŠ” 다른 소프트웨어와 호환ë˜ì§€ ì•Šì„ ìˆ˜ 있습니다.\n\nì´ ì„¤ì •ì„ í™œì„±í™”í•˜ëŠ” ê²ƒì€ ê³µì‹ì ìœ¼ë¡œ ì§€ì›ë˜ì§€ 않으며, ì œì¶œëœ ë²„ê·¸ 보고서는 유효하지 않ìŒìœ¼ë¡œ ë‹«íž ìˆ˜ 있습니다." + IDS_2148 "계ì†" + IDS_2149 "카세트: %s" + IDS_2150 "카세트 ì´ë¯¸ì§€ (*.PCM;*.RAW;*.WAV;*.CAS)\0*.PCM;*.RAW;*.WAV;*.CAS\0모든 íŒŒì¼ (*.*)\0*.*\0" + IDS_2151 "카트리지 %i: %ls" + IDS_2152 "카트리지 ì´ë¯¸ì§€ (*.A;*.B;*.JRC)\0*.A;*.B;*.JRC\0모든 íŒŒì¼ (*.*)\0*.*\0" + IDS_2153 "ë Œë”러 초기화 오류" + IDS_2154 "OpenGL (3.0 Core) ë Œë”러를 초기화할 수 없습니다. 다른 ë Œë”러를 사용하십시오." + IDS_2155 "실행 재개" + IDS_2156 "실행 ì¼ì‹œ 중지" + IDS_2157 "Ctrl+Alt+Del" + IDS_2158 "Ctrl+Alt+Esc" + IDS_2159 "재시작" + IDS_2160 "ACPI 종료" + IDS_2161 "설정" + IDS_2162 "Type" + IDS_2163 "No Dynarec" + IDS_2164 "Old Dynarec" + IDS_2165 "New Dynarec" + IDS_2166 "ë‘번째 비디오카드 ""%hs""는 roms/video 디렉토리ì—서 ROMì´ ëˆ„ë½ë˜ì–´ 사용할 수 없습니다. ë‘번째 비디오 카드를 비활성화 합니다." + IDS_2167 "Failed to initialize network driver" + IDS_2168 "The network configuration will be switched to the null driver" END -STRINGTABLE DISCARDABLE +STRINGTABLE DISCARDABLE BEGIN IDS_4096 "하드 ë””ìŠ¤í¬ (%s)" - IDS_4097 "%01i:%01i" - IDS_4098 "%01i" - IDS_4099 "MFM/RLL ë˜ëŠ” ESDI CD-ROM 드ë¼ì´ë¸Œê°€ 존재하지 않습니다" - IDS_4100 "ì‚¬ìš©ìž ì„¤ì •..." - IDS_4101 "ì‚¬ìš©ìž ì„¤ì • (대용량)..." - IDS_4102 "새로 ìƒì„±" - IDS_4103 "기존 ì´ë¯¸ì§€ 사용" - IDS_4104 "HDI ë””ìŠ¤í¬ ì´ë¯¸ì§€ëŠ” 4GB ì´ìƒìœ¼ë¡œ 지정할 수 없습니다" - IDS_4105 "ë””ìŠ¤í¬ ì´ë¯¸ì§€ëŠ” 127GB ì´ìƒìœ¼ë¡œ 지정할 수 없습니다" - IDS_4106 "하드 ë””ìŠ¤í¬ ì´ë¯¸ì§€ (*.HD?;*.IM?;*.VHD)\0*.HD?;*.IM?;*.VHD\0모든 íŒŒì¼ (*.*)\0*.*\0" - IDS_4107 "파ì¼ì„ ì½ì„ 수 없습니다" - IDS_4108 "파ì¼ì„ 저장할 수 없습니다" - IDS_4109 "512 ë°”ì´íЏ ì´ì™¸ì˜ 섹터 í¬ê¸°ë¥¼ 가진 HDI ë˜ëŠ” HDX 형ì‹ì˜ ì´ë¯¸ì§€ë¥¼ ìƒì„±í•  수 없습니다" - IDS_4110 "USB는 ì•„ì§ ì§€ì›í•˜ì§€ 않습니다" - IDS_4111 "ë””ìŠ¤í¬ ì´ë¯¸ì§€ 파ì¼ì´ ì´ë¯¸ 존재합니다" - IDS_4112 "올바른 파ì¼ëª…ì„ ì§€ì •í•´ 주세요." - IDS_4113 "ë””ìŠ¤í¬ ì´ë¯¸ì§€ê°€ ìƒì„±ë˜ì—ˆìŠµë‹ˆë‹¤" - IDS_4114 "파ì¼ì´ 존재하며 ì½ì„ 수 있는지 확ì¸í•©ë‹ˆë‹¤." - IDS_4115 "파ì¼ì´ 쓰기 가능한 ë””ë ‰í† ë¦¬ì— ì €ìž¥ë˜ê³  있는지 확ì¸í•©ë‹ˆë‹¤." - IDS_4116 "ë””ìŠ¤í¬ ì´ë¯¸ì§€ê°€ 너무 í½ë‹ˆë‹¤" - IDS_4117 "새로 ìƒì„±í•œ 드ë¼ì´ë¸Œì˜ 파티션 설정과 í¬ë§·ì„ ê¼­ 해주세요." - IDS_4118 "ì„ íƒí•˜ì‹  파ì¼ì„ ë®ì–´ì”Œì›ë‹ˆë‹¤. 사용하시겠습니까?" - IDS_4119 "ì§€ì›í•˜ì§€ 않는 ë””ìŠ¤í¬ ì´ë¯¸ì§€ìž…니다" - IDS_4120 "ë®ì–´ì“°ê¸°" - IDS_4121 "ë®ì–´ì“°ì§€ 않ìŒ" - IDS_4122 "Raw ì´ë¯¸ì§€ (.img)" - IDS_4123 "HDI ì´ë¯¸ì§€ (.hdi)" - IDS_4124 "HDX ì´ë¯¸ì§€ (.hdx)" - IDS_4125 "ê³ ì • 사ì´ì¦ˆ VHD (.vhd)" - IDS_4126 "ë™ì  사ì´ì¦ˆ VHD (.vhd)" - IDS_4127 "ë””í¼ëŸ°ì‹± VHD (.vhd)" - IDS_4128 "대형 ë¸”ë¡ (2 MB)" - IDS_4129 "소형 ë¸”ë¡ (512 KB)" - IDS_4130 "VHD íŒŒì¼ (*.VHD)\0*.VHD\0모든 íŒŒì¼ (*.*)\0*.*\0" - IDS_4131 "부모 VHD ì„ íƒ" - IDS_4132 "ì´ëŠ” ë””í¼ëŸ°ì‹± ì´ë¯¸ì§€ê°€ ìƒì„±ëœ 후 부모 ì´ë¯¸ì§€ê°€ 수정ë˜ì—ˆìŒì„ ì˜ë¯¸í•  수 있습니다.\n\nì´ë¯¸ì§€ 파ì¼ì´ ì´ë™ ë˜ëŠ” ë³µì‚¬ëœ ê²½ìš° ë˜ëŠ” ì´ ë””ìŠ¤í¬ë¥¼ 만든 í”„ë¡œê·¸ëž¨ì˜ ë²„ê·¸ë¡œ ì¸í•´ ë°œìƒí•  ìˆ˜ë„ ìžˆìŠµë‹ˆë‹¤.\n\n타임스탬프를 수정하시겠습니까?" - IDS_4133 "부모 디스í¬ì™€ ìžì‹ 디스í¬ì˜ 타임스탬프가 ì¼ì¹˜í•˜ì§€ 않습니다" - IDS_4134 "VHD 타임스탬프를 ê³ ì¹  수 없습니다" - IDS_4135 "%01i:%02i" + IDS_4097 "%01i:%01i" + IDS_4098 "%01i" + IDS_4099 "MFM/RLL ë˜ëŠ” ESDI CD-ROM 드ë¼ì´ë¸Œê°€ 존재하지 않습니다" + IDS_4100 "ì‚¬ìš©ìž ì„¤ì •..." + IDS_4101 "ì‚¬ìš©ìž ì„¤ì • (대용량)..." + IDS_4102 "새로 ìƒì„±" + IDS_4103 "기존 ì´ë¯¸ì§€ 사용" + IDS_4104 "HDI ë””ìŠ¤í¬ ì´ë¯¸ì§€ëŠ” 4GB ì´ìƒìœ¼ë¡œ 지정할 수 없습니다" + IDS_4105 "ë””ìŠ¤í¬ ì´ë¯¸ì§€ëŠ” 127GB ì´ìƒìœ¼ë¡œ 지정할 수 없습니다" + IDS_4106 "하드 ë””ìŠ¤í¬ ì´ë¯¸ì§€ (*.HD?;*.IM?;*.VHD)\0*.HD?;*.IM?;*.VHD\0모든 íŒŒì¼ (*.*)\0*.*\0" + IDS_4107 "파ì¼ì„ ì½ì„ 수 없습니다" + IDS_4108 "파ì¼ì„ 저장할 수 없습니다" + IDS_4109 "512 ë°”ì´íЏ ì´ì™¸ì˜ 섹터 í¬ê¸°ë¥¼ 가진 HDI ë˜ëŠ” HDX 형ì‹ì˜ ì´ë¯¸ì§€ë¥¼ ìƒì„±í•  수 없습니다" + IDS_4110 "USB는 ì•„ì§ ì§€ì›í•˜ì§€ 않습니다" + IDS_4111 "ë””ìŠ¤í¬ ì´ë¯¸ì§€ 파ì¼ì´ ì´ë¯¸ 존재합니다" + IDS_4112 "올바른 파ì¼ëª…ì„ ì§€ì •í•´ 주세요." + IDS_4113 "ë””ìŠ¤í¬ ì´ë¯¸ì§€ê°€ ìƒì„±ë˜ì—ˆìŠµë‹ˆë‹¤" + IDS_4114 "파ì¼ì´ 존재하며 ì½ì„ 수 있는지 확ì¸í•©ë‹ˆë‹¤." + IDS_4115 "파ì¼ì´ 쓰기 가능한 ë””ë ‰í† ë¦¬ì— ì €ìž¥ë˜ê³  있는지 확ì¸í•©ë‹ˆë‹¤." + IDS_4116 "ë””ìŠ¤í¬ ì´ë¯¸ì§€ê°€ 너무 í½ë‹ˆë‹¤" + IDS_4117 "새로 ìƒì„±í•œ 드ë¼ì´ë¸Œì˜ 파티션 설정과 í¬ë§·ì„ ê¼­ 해주세요." + IDS_4118 "ì„ íƒí•˜ì‹  파ì¼ì„ ë®ì–´ì”Œì›ë‹ˆë‹¤. 사용하시겠습니까?" + IDS_4119 "ì§€ì›í•˜ì§€ 않는 ë””ìŠ¤í¬ ì´ë¯¸ì§€ìž…니다" + IDS_4120 "ë®ì–´ì“°ê¸°" + IDS_4121 "ë®ì–´ì“°ì§€ 않ìŒ" + IDS_4122 "Raw ì´ë¯¸ì§€ (.img)" + IDS_4123 "HDI ì´ë¯¸ì§€ (.hdi)" + IDS_4124 "HDX ì´ë¯¸ì§€ (.hdx)" + IDS_4125 "ê³ ì • 사ì´ì¦ˆ VHD (.vhd)" + IDS_4126 "ë™ì  사ì´ì¦ˆ VHD (.vhd)" + IDS_4127 "ë””í¼ëŸ°ì‹± VHD (.vhd)" + IDS_4128 "대형 ë¸”ë¡ (2 MB)" + IDS_4129 "소형 ë¸”ë¡ (512 KB)" + IDS_4130 "VHD íŒŒì¼ (*.VHD)\0*.VHD\0모든 íŒŒì¼ (*.*)\0*.*\0" + IDS_4131 "부모 VHD ì„ íƒ" + IDS_4132 "ì´ëŠ” ë””í¼ëŸ°ì‹± ì´ë¯¸ì§€ê°€ ìƒì„±ëœ 후 부모 ì´ë¯¸ì§€ê°€ 수정ë˜ì—ˆìŒì„ ì˜ë¯¸í•  수 있습니다.\n\nì´ë¯¸ì§€ 파ì¼ì´ ì´ë™ ë˜ëŠ” ë³µì‚¬ëœ ê²½ìš° ë˜ëŠ” ì´ ë””ìŠ¤í¬ë¥¼ 만든 í”„ë¡œê·¸ëž¨ì˜ ë²„ê·¸ë¡œ ì¸í•´ ë°œìƒí•  ìˆ˜ë„ ìžˆìŠµë‹ˆë‹¤.\n\n타임스탬프를 수정하시겠습니까?" + IDS_4133 "부모 디스í¬ì™€ ìžì‹ 디스í¬ì˜ 타임스탬프가 ì¼ì¹˜í•˜ì§€ 않습니다" + IDS_4134 "VHD 타임스탬프를 ê³ ì¹  수 없습니다" + IDS_4135 "%01i:%02i" IDS_4352 "MFM/RLL" IDS_4353 "XTA" @@ -562,56 +582,56 @@ BEGIN IDS_4356 "ATAPI" IDS_4357 "SCSI" - IDS_4608 "MFM/RLL (%01i:%01i)" - IDS_4609 "XTA (%01i:%01i)" - IDS_4610 "ESDI (%01i:%01i)" - IDS_4611 "IDE (%01i:%01i)" - IDS_4612 "ATAPI (%01i:%01i)" - IDS_4613 "SCSI (%01i:%02i)" + IDS_4608 "MFM/RLL (%01i:%01i)" + IDS_4609 "XTA (%01i:%01i)" + IDS_4610 "ESDI (%01i:%01i)" + IDS_4611 "IDE (%01i:%01i)" + IDS_4612 "ATAPI (%01i:%01i)" + IDS_4613 "SCSI (%01i:%02i)" - IDS_5120 "CD-ROM %i (%s): %s" + IDS_5120 "CD-ROM %i (%s): %s" - IDS_5376 "사용하지 않ìŒ" - IDS_5381 "ATAPI" + IDS_5376 "사용하지 않ìŒ" + IDS_5381 "ATAPI" IDS_5382 "SCSI" - IDS_5632 "사용하지 않ìŒ" - IDS_5637 "ATAPI (%01i:%01i)" + IDS_5632 "사용하지 않ìŒ" + IDS_5637 "ATAPI (%01i:%01i)" IDS_5638 "SCSI (%01i:%02i)" - IDS_5888 "160 kB" - IDS_5889 "180 kB" - IDS_5890 "320 kB" - IDS_5891 "360 kB" - IDS_5892 "640 kB" - IDS_5893 "720 kB" - IDS_5894 "1.2 MB" - IDS_5895 "1.25 MB" - IDS_5896 "1.44 MB" - IDS_5897 "DMF (í´ëŸ¬ìŠ¤í„° 1024)" - IDS_5898 "DMF (í´ëŸ¬ìŠ¤í„° 2048)" - IDS_5899 "2.88 MB" - IDS_5900 "ZIP 100" - IDS_5901 "ZIP 250" - IDS_5902 "3.5"" 128 MB (ISO 10090)" - IDS_5903 "3.5"" 230 MB (ISO 13963)" - IDS_5904 "3.5"" 540 MB (ISO 15498)" - IDS_5905 "3.5"" 640 MB (ISO 15498)" - IDS_5906 "3.5"" 1.3 GB (GigaMO)" - IDS_5907 "3.5"" 2.3 GB (GigaMO 2)" - IDS_5908 "5.25"" 600 MB" - IDS_5909 "5.25"" 650 MB" - IDS_5910 "5.25"" 1 GB" - IDS_5911 "5.25"" 1.3 GB" + IDS_5888 "160 kB" + IDS_5889 "180 kB" + IDS_5890 "320 kB" + IDS_5891 "360 kB" + IDS_5892 "640 kB" + IDS_5893 "720 kB" + IDS_5894 "1.2 MB" + IDS_5895 "1.25 MB" + IDS_5896 "1.44 MB" + IDS_5897 "DMF (í´ëŸ¬ìŠ¤í„° 1024)" + IDS_5898 "DMF (í´ëŸ¬ìŠ¤í„° 2048)" + IDS_5899 "2.88 MB" + IDS_5900 "ZIP 100" + IDS_5901 "ZIP 250" + IDS_5902 "3.5"" 128 MB (ISO 10090)" + IDS_5903 "3.5"" 230 MB (ISO 13963)" + IDS_5904 "3.5"" 540 MB (ISO 15498)" + IDS_5905 "3.5"" 640 MB (ISO 15498)" + IDS_5906 "3.5"" 1.3 GB (GigaMO)" + IDS_5907 "3.5"" 2.3 GB (GigaMO 2)" + IDS_5908 "5.25"" 600 MB" + IDS_5909 "5.25"" 650 MB" + IDS_5910 "5.25"" 1 GB" + IDS_5911 "5.25"" 1.3 GB" - IDS_6144 "완벽한 회전수" - IDS_6145 "1% ë‚®ì€ íšŒì „ìˆ˜" - IDS_6146 "1.5% ë‚®ì€ íšŒì „ìˆ˜" - IDS_6147 "2% ë‚®ì€ íšŒì „ìˆ˜" + IDS_6144 "완벽한 회전수" + IDS_6145 "1% ë‚®ì€ íšŒì „ìˆ˜" + IDS_6146 "1.5% ë‚®ì€ íšŒì „ìˆ˜" + IDS_6147 "2% ë‚®ì€ íšŒì „ìˆ˜" - IDS_7168 "(시스템 기본값)" + IDS_7168 "(시스템 기본값)" END -#define IDS_LANG_ENUS IDS_7168 +#define IDS_LANG_ENUS IDS_7168 // Korean resources ///////////////////////////////////////////////////////////////////////////// diff --git a/src/win/languages/pl-PL.rc b/src/win/languages/pl-PL.rc index 45869d68b..f835ad9eb 100644 --- a/src/win/languages/pl-PL.rc +++ b/src/win/languages/pl-PL.rc @@ -13,113 +13,122 @@ LANGUAGE LANG_POLISH, SUBLANG_DEFAULT // Menu // -MainMenu MENU DISCARDABLE +MainMenu MENU DISCARDABLE BEGIN POPUP "&Akcje" BEGIN - MENUITEM "&Klawaitura wymaga przechwytu myszy", IDM_ACTION_KBD_REQ_CAPTURE - MENUITEM "&Prawy CTRL to lewy Alt", IDM_ACTION_RCTRL_IS_LALT + MENUITEM "&Klawaitura wymaga przechwytu myszy", IDM_ACTION_KBD_REQ_CAPTURE + MENUITEM "&Prawy CTRL to lewy Alt", IDM_ACTION_RCTRL_IS_LALT MENUITEM SEPARATOR - MENUITEM "&Twardy reset...", IDM_ACTION_HRESET - MENUITEM "&Ctrl+Alt+Del\tCtrl+F12", IDM_ACTION_RESET_CAD + MENUITEM "&Twardy reset...", IDM_ACTION_HRESET + MENUITEM "&Ctrl+Alt+Del\tCtrl+F12", IDM_ACTION_RESET_CAD MENUITEM SEPARATOR - MENUITEM "Ctrl+Alt+&Esc", IDM_ACTION_CTRL_ALT_ESC + MENUITEM "Ctrl+Alt+&Esc", IDM_ACTION_CTRL_ALT_ESC MENUITEM SEPARATOR - MENUITEM "&Pauza", IDM_ACTION_PAUSE + MENUITEM "&Pauza", IDM_ACTION_PAUSE MENUITEM SEPARATOR - MENUITEM "W&yjdź...", IDM_ACTION_EXIT + MENUITEM "W&yjdź...", IDM_ACTION_EXIT END POPUP "&Widok" BEGIN - MENUITEM "&Ukryj pasek statusu", IDM_VID_HIDE_STATUS_BAR - MENUITEM "Ukryj &pasek narzÄ™dzi", IDM_VID_HIDE_TOOLBAR + MENUITEM "&Ukryj pasek statusu", IDM_VID_HIDE_STATUS_BAR + MENUITEM "Ukryj &pasek narzÄ™dzi", IDM_VID_HIDE_TOOLBAR MENUITEM SEPARATOR - MENUITEM "&Okno o zmiennym rozmiarze", IDM_VID_RESIZE - MENUITEM "P&amiÄ™taj rozmiar &i pozycjÄ™", IDM_VID_REMEMBER + MENUITEM "&Show non-primary monitors", IDM_VID_MONITORS + MENUITEM "&Okno o zmiennym rozmiarze", IDM_VID_RESIZE + MENUITEM "P&amiÄ™taj rozmiar &i pozycjÄ™", IDM_VID_REMEMBER MENUITEM SEPARATOR POPUP "Re&nderer" BEGIN - MENUITEM "&SDL (Software)", IDM_VID_SDL_SW - MENUITEM "SDL (&Hardware)", IDM_VID_SDL_HW - MENUITEM "SDL (&OpenGL)", IDM_VID_SDL_OPENGL - MENUITEM "Open&GL (3.0 Core)", IDM_VID_OPENGL_CORE + MENUITEM "&SDL (Software)", IDM_VID_SDL_SW + MENUITEM "SDL (&Hardware)", IDM_VID_SDL_HW + MENUITEM "SDL (&OpenGL)", IDM_VID_SDL_OPENGL + MENUITEM "Open&GL (3.0 Core)", IDM_VID_OPENGL_CORE #ifdef USE_VNC - MENUITEM "&VNC", IDM_VID_VNC + MENUITEM "&VNC", IDM_VID_VNC #endif END MENUITEM SEPARATOR - MENUITEM "OkreÅ›l rozmiary...", IDM_VID_SPECIFY_DIM - MENUITEM "&WymuÅ› proporcje wyÅ›wietlania 4:3", IDM_VID_FORCE43 + MENUITEM "OkreÅ›l rozmiary...", IDM_VID_SPECIFY_DIM + MENUITEM "&WymuÅ› proporcje wyÅ›wietlania 4:3", IDM_VID_FORCE43 POPUP "&Czynnik skalowania okna" BEGIN - MENUITEM "&0.5x", IDM_VID_SCALE_1X - MENUITEM "&1x", IDM_VID_SCALE_2X - MENUITEM "1.&5x", IDM_VID_SCALE_3X - MENUITEM "&2x", IDM_VID_SCALE_4X + MENUITEM "&0.5x", IDM_VID_SCALE_1X + MENUITEM "&1x", IDM_VID_SCALE_2X + MENUITEM "1.&5x", IDM_VID_SCALE_3X + MENUITEM "&2x", IDM_VID_SCALE_4X + MENUITEM "&3x", IDM_VID_SCALE_5X + MENUITEM "&4x", IDM_VID_SCALE_6X + MENUITEM "&5x", IDM_VID_SCALE_7X + MENUITEM "&6x", IDM_VID_SCALE_8X + MENUITEM "&7x", IDM_VID_SCALE_9X + MENUITEM "&8x", IDM_VID_SCALE_10X END POPUP "Metoda filtrowania" BEGIN - MENUITEM "&Nearest", IDM_VID_FILTER_NEAREST - MENUITEM "&Linear", IDM_VID_FILTER_LINEAR + MENUITEM "&Nearest", IDM_VID_FILTER_NEAREST + MENUITEM "&Linear", IDM_VID_FILTER_LINEAR END - MENUITEM "Skalowanie Hi&DPI", IDM_VID_HIDPI + MENUITEM "Skalowanie Hi&DPI", IDM_VID_HIDPI MENUITEM SEPARATOR - MENUITEM "&PeÅ‚ny ekran\tCtrl+Alt+PgUp", IDM_VID_FULLSCREEN + MENUITEM "&PeÅ‚ny ekran\tCtrl+Alt+PgUp", IDM_VID_FULLSCREEN POPUP "Fullscreen &stretch mode" BEGIN - MENUITEM "&Tryb rozciÄ…gania na peÅ‚nym ekranie", IDM_VID_FS_FULL - MENUITEM "&4:3", IDM_VID_FS_43 + MENUITEM "&Tryb rozciÄ…gania na peÅ‚nym ekranie", IDM_VID_FS_FULL + MENUITEM "&4:3", IDM_VID_FS_43 MENUITEM "&Kwadratowe piksele (Zachowaj proporcje)", IDM_VID_FS_KEEPRATIO - MENUITEM "&Skalowanie caÅ‚kowite", IDM_VID_FS_INT + MENUITEM "&Skalowanie caÅ‚kowite", IDM_VID_FS_INT END POPUP "Ustawienia E&GA/(S)VGA" BEGIN - MENUITEM "&Odwrócony monitor VGA", IDM_VID_INVERT + MENUITEM "&Odwrócony monitor VGA", IDM_VID_INVERT POPUP "Rodzaj ekranu &VGA" BEGIN - MENUITEM "RGB - &Kolorowy", IDM_VID_GRAY_RGB - MENUITEM "&RGB - Skala szaroÅ›ci", IDM_VID_GRAY_MONO - MENUITEM "&Bursztynowy monitor", IDM_VID_GRAY_AMBER - MENUITEM "&Zielony monitor", IDM_VID_GRAY_GREEN - MENUITEM "&BiaÅ‚y monitor", IDM_VID_GRAY_WHITE + MENUITEM "RGB - &Kolorowy", IDM_VID_GRAY_RGB + MENUITEM "&RGB - Skala szaroÅ›ci", IDM_VID_GRAY_MONO + MENUITEM "&Bursztynowy monitor", IDM_VID_GRAY_AMBER + MENUITEM "&Zielony monitor", IDM_VID_GRAY_GREEN + MENUITEM "&BiaÅ‚y monitor", IDM_VID_GRAY_WHITE END POPUP "Typ konwersji &w skali szaroÅ›ci" BEGIN - MENUITEM "BT&601 (NTSC/PAL)", IDM_VID_GRAYCT_601 - MENUITEM "BT&709 (HDTV)", IDM_VID_GRAYCT_709 - MENUITEM "&Åšredni", IDM_VID_GRAYCT_AVE + MENUITEM "BT&601 (NTSC/PAL)", IDM_VID_GRAYCT_601 + MENUITEM "BT&709 (HDTV)", IDM_VID_GRAYCT_709 + MENUITEM "&Åšredni", IDM_VID_GRAYCT_AVE END END MENUITEM SEPARATOR - MENUITEM "Overscan dla CGA/PCjr/Tandy/E&GA/(S)VGA", IDM_VID_OVERSCAN + MENUITEM "Overscan dla CGA/PCjr/Tandy/E&GA/(S)VGA", IDM_VID_OVERSCAN MENUITEM "ZmieÅ„ kontrast dla &monochromatycznego ekranu", IDM_VID_CGACON END - MENUITEM "&NoÅ›nik", IDM_MEDIA + MENUITEM "&NoÅ›nik", IDM_MEDIA POPUP "&NarzÄ™dzia" BEGIN - MENUITEM "&Ustawienia...", IDM_CONFIG - MENUITEM "&Aktualizuj ikony na pasku statusu", IDM_UPDATE_ICONS + MENUITEM "&Ustawienia...", IDM_CONFIG + MENUITEM "&Aktualizuj ikony na pasku statusu", IDM_UPDATE_ICONS MENUITEM SEPARATOR - MENUITEM "Zrób &zrzut ekranu\tCtrl+F11", IDM_ACTION_SCREENSHOT + MENUITEM "Zrób &zrzut ekranu\tCtrl+F11", IDM_ACTION_SCREENSHOT MENUITEM SEPARATOR - MENUITEM "&Preferencje...", IDM_PREFERENCES + MENUITEM "&Preferencje...", IDM_PREFERENCES +#ifdef DISCORD MENUITEM "Włącz integracjÄ™ z &Discord", IDM_DISCORD +#endif MENUITEM SEPARATOR - MENUITEM "Wzmocnienie &dźwiÄ™ku...", IDM_SND_GAIN + MENUITEM "Wzmocnienie &dźwiÄ™ku...", IDM_SND_GAIN #ifdef MTR_ENABLED MENUITEM SEPARATOR - MENUITEM "Rozpocznij Å›ledzenie\tCtrl+T", IDM_ACTION_BEGIN_TRACE - MENUITEM "ZakoÅ„cz Å›ledzenie\tCtrl+T", IDM_ACTION_END_TRACE + MENUITEM "Rozpocznij Å›ledzenie\tCtrl+T", IDM_ACTION_BEGIN_TRACE + MENUITEM "ZakoÅ„cz Å›ledzenie\tCtrl+T", IDM_ACTION_END_TRACE #endif END POPUP "&Pomoc" BEGIN - MENUITEM "&Dokumentacja...", IDM_DOCS - MENUITEM "&O 86Box...", IDM_ABOUT + MENUITEM "&Dokumentacja...", IDM_DOCS + MENUITEM "&O 86Box...", IDM_ABOUT END END -StatusBarMenu MENU DISCARDABLE +StatusBarMenu MENU DISCARDABLE BEGIN MENUITEM SEPARATOR END @@ -128,17 +137,17 @@ CassetteSubmenu MENU DISCARDABLE BEGIN POPUP "" BEGIN - MENUITEM "&Nowy obraz...", IDM_CASSETTE_IMAGE_NEW + MENUITEM "&Nowy obraz...", IDM_CASSETTE_IMAGE_NEW MENUITEM SEPARATOR - MENUITEM "&IstniejÄ…cy obraz...", IDM_CASSETTE_IMAGE_EXISTING - MENUITEM "IstniejÄ…cy obraz (&Chroniony przed zapisem)...", IDM_CASSETTE_IMAGE_EXISTING_WP + MENUITEM "&IstniejÄ…cy obraz...", IDM_CASSETTE_IMAGE_EXISTING + MENUITEM "IstniejÄ…cy obraz (&Chroniony przed zapisem)...", IDM_CASSETTE_IMAGE_EXISTING_WP MENUITEM SEPARATOR - MENUITEM "&Nagraj", IDM_CASSETTE_RECORD - MENUITEM "&Odtwórz", IDM_CASSETTE_PLAY - MENUITEM "&PrzewiÅ„ do poczÄ…tku", IDM_CASSETTE_REWIND - MENUITEM "&PrzewiÅ„ do koÅ„ca", IDM_CASSETTE_FAST_FORWARD + MENUITEM "&Nagraj", IDM_CASSETTE_RECORD + MENUITEM "&Odtwórz", IDM_CASSETTE_PLAY + MENUITEM "&PrzewiÅ„ do poczÄ…tku", IDM_CASSETTE_REWIND + MENUITEM "&PrzewiÅ„ do koÅ„ca", IDM_CASSETTE_FAST_FORWARD MENUITEM SEPARATOR - MENUITEM "W&yjmij", IDM_CASSETTE_EJECT + MENUITEM "W&yjmij", IDM_CASSETTE_EJECT END END @@ -146,9 +155,9 @@ CartridgeSubmenu MENU DISCARDABLE BEGIN POPUP "" BEGIN - MENUITEM "&Obraz...", IDM_CARTRIDGE_IMAGE + MENUITEM "&Obraz...", IDM_CARTRIDGE_IMAGE MENUITEM SEPARATOR - MENUITEM "W&yjmij", IDM_CARTRIDGE_EJECT + MENUITEM "W&yjmij", IDM_CARTRIDGE_EJECT END END @@ -156,14 +165,14 @@ FloppySubmenu MENU DISCARDABLE BEGIN POPUP "" BEGIN - MENUITEM "&Nowy obraz...", IDM_FLOPPY_IMAGE_NEW + MENUITEM "&Nowy obraz...", IDM_FLOPPY_IMAGE_NEW MENUITEM SEPARATOR - MENUITEM "&IstniejÄ…cy obraz...", IDM_FLOPPY_IMAGE_EXISTING - MENUITEM "IstniejÄ…cy obraz (&Chroniony przed zapisem)...", IDM_FLOPPY_IMAGE_EXISTING_WP + MENUITEM "&IstniejÄ…cy obraz...", IDM_FLOPPY_IMAGE_EXISTING + MENUITEM "IstniejÄ…cy obraz (&Chroniony przed zapisem)...", IDM_FLOPPY_IMAGE_EXISTING_WP MENUITEM SEPARATOR - MENUITEM "E&ksportuj do 86F...", IDM_FLOPPY_EXPORT_TO_86F + MENUITEM "E&ksportuj do 86F...", IDM_FLOPPY_EXPORT_TO_86F MENUITEM SEPARATOR - MENUITEM "W&yjmij", IDM_FLOPPY_EJECT + MENUITEM "W&yjmij", IDM_FLOPPY_EJECT END END @@ -171,12 +180,13 @@ CdromSubmenu MENU DISCARDABLE BEGIN POPUP "" BEGIN - MENUITEM "&Åšcisz", IDM_CDROM_MUTE + MENUITEM "&Åšcisz", IDM_CDROM_MUTE MENUITEM SEPARATOR - MENUITEM "P&usty", IDM_CDROM_EMPTY - MENUITEM "&PrzeÅ‚aduj poprzedni obraz", IDM_CDROM_RELOAD + MENUITEM "P&usty", IDM_CDROM_EMPTY + MENUITEM "&PrzeÅ‚aduj poprzedni obraz", IDM_CDROM_RELOAD MENUITEM SEPARATOR - MENUITEM "&Obraz", IDM_CDROM_IMAGE + MENUITEM "&Obraz...", IDM_CDROM_IMAGE + MENUITEM "&Teczka...", IDM_CDROM_DIR END END @@ -184,13 +194,13 @@ ZIPSubmenu MENU DISCARDABLE BEGIN POPUP "" BEGIN - MENUITEM "&Nowy obraz...", IDM_ZIP_IMAGE_NEW + MENUITEM "&Nowy obraz...", IDM_ZIP_IMAGE_NEW MENUITEM SEPARATOR - MENUITEM "&IstniejÄ…cy obraz...", IDM_ZIP_IMAGE_EXISTING - MENUITEM "IstniejÄ…cy obraz (&Chroniony przed zapisem)...", IDM_ZIP_IMAGE_EXISTING_WP + MENUITEM "&IstniejÄ…cy obraz...", IDM_ZIP_IMAGE_EXISTING + MENUITEM "IstniejÄ…cy obraz (&Chroniony przed zapisem)...", IDM_ZIP_IMAGE_EXISTING_WP MENUITEM SEPARATOR - MENUITEM "W&yjmij", IDM_ZIP_EJECT - MENUITEM "&PrzeÅ‚aduj poprzedni obraz", IDM_ZIP_RELOAD + MENUITEM "W&yjmij", IDM_ZIP_EJECT + MENUITEM "&PrzeÅ‚aduj poprzedni obraz", IDM_ZIP_RELOAD END END @@ -198,13 +208,13 @@ MOSubmenu MENU DISCARDABLE BEGIN POPUP "" BEGIN - MENUITEM "&Nowy obraz...", IDM_MO_IMAGE_NEW + MENUITEM "&Nowy obraz...", IDM_MO_IMAGE_NEW MENUITEM SEPARATOR - MENUITEM "&IstniejÄ…cy obraz...", IDM_MO_IMAGE_EXISTING - MENUITEM "IstniejÄ…cy obraz (&Chroniony przed zapisem)...", IDM_MO_IMAGE_EXISTING_WP + MENUITEM "&IstniejÄ…cy obraz...", IDM_MO_IMAGE_EXISTING + MENUITEM "IstniejÄ…cy obraz (&Chroniony przed zapisem)...", IDM_MO_IMAGE_EXISTING_WP MENUITEM SEPARATOR - MENUITEM "W&yjmij", IDM_MO_EJECT - MENUITEM "&PrzeÅ‚aduj poprzedni obraz", IDM_MO_RELOAD + MENUITEM "W&yjmij", IDM_MO_EJECT + MENUITEM "&PrzeÅ‚aduj poprzedni obraz", IDM_MO_RELOAD END END @@ -230,134 +240,150 @@ END // Dialog // -#define STR_PREFERENCES "Preferencje" -#define STR_SND_GAIN "Wzmocnienie dźwiÄ™ku" -#define STR_NEW_FLOPPY "Nowy obraz" -#define STR_CONFIG "Ustawienia" -#define STR_SPECIFY_DIM "OkreÅ›l rozmiary okna" +#define STR_PREFERENCES "Preferencje" +#define STR_SND_GAIN "Wzmocnienie dźwiÄ™ku" +#define STR_NEW_FLOPPY "Nowy obraz" +#define STR_CONFIG "Ustawienia" +#define STR_SPECIFY_DIM "OkreÅ›l rozmiary okna" -#define STR_OK "OK" -#define STR_CANCEL "Anuluj" -#define STR_GLOBAL "Zapisz ustawienia jako &globalne ustawienia domyÅ›lne" -#define STR_DEFAULT "&DomyÅ›lny" -#define STR_LANGUAGE "JÄ™zyk:" -#define STR_ICONSET "Zestaw ikon:" +#define STR_OK "OK" +#define STR_CANCEL "Anuluj" +#define STR_GLOBAL "Zapisz ustawienia jako &globalne ustawienia domyÅ›lne" +#define STR_DEFAULT "&DomyÅ›lny" +#define STR_LANGUAGE "JÄ™zyk:" +#define STR_ICONSET "Zestaw ikon:" -#define STR_GAIN "Wzmacniacz" +#define STR_GAIN "Wzmacniacz" -#define STR_FILE_NAME "Nazwa pliku:" -#define STR_DISK_SIZE "Rozmiar dysku:" -#define STR_RPM_MODE "Tryb RPM:" -#define STR_PROGRESS "PostÄ™p:" +#define STR_FILE_NAME "Nazwa pliku:" +#define STR_DISK_SIZE "Rozmiar dysku:" +#define STR_RPM_MODE "Tryb RPM:" +#define STR_PROGRESS "PostÄ™p:" -#define STR_WIDTH "Szerokość:" -#define STR_HEIGHT "Wysokość:" -#define STR_LOCK_TO_SIZE "StaÅ‚y rozmiar" +#define STR_WIDTH "Szerokość:" +#define STR_HEIGHT "Wysokość:" +#define STR_LOCK_TO_SIZE "StaÅ‚y rozmiar" -#define STR_MACHINE_TYPE "Rodzaj maszyny:" -#define STR_MACHINE "Maszyna:" -#define STR_CONFIGURE "Konfiguruj" -#define STR_CPU_TYPE "Rodzaj procesora:" -#define STR_CPU_SPEED "Szybkość:" -#define STR_FPU "Jednostka FPU:" -#define STR_WAIT_STATES "Stany oczekiwania:" -#define STR_MB "MB" -#define STR_MEMORY "Pamięć:" -#define STR_TIME_SYNC "Synchronizacja czasu" -#define STR_DISABLED "Wyłączona" -#define STR_ENABLED_LOCAL "Włączona (czas lokalny)" -#define STR_ENABLED_UTC "Włączona (UTC)" -#define STR_DYNAREC "Dynamiczny rekompilator" +#define STR_MACHINE_TYPE "Rodzaj maszyny:" +#define STR_MACHINE "Maszyna:" +#define STR_CONFIGURE "Konfiguruj" +#define STR_CPU_TYPE "Rodzaj procesora:" +#define STR_CPU_SPEED "Szybkość:" +#define STR_FPU "Jednostka FPU:" +#define STR_WAIT_STATES "Stany oczekiwania:" +#define STR_MB "MB" +#define STR_MEMORY "Pamięć:" +#define STR_TIME_SYNC "Synchronizacja czasu" +#define STR_DISABLED "Wyłączona" +#define STR_ENABLED_LOCAL "Włączona (czas lokalny)" +#define STR_ENABLED_UTC "Włączona (UTC)" +#define STR_DYNAREC "Dynamiczny rekompilator" +#define STR_SOFTFLOAT "Softfloat FPU" -#define STR_VIDEO "Wideo:" -#define STR_VOODOO "Grafika Voodoo" +#define STR_VIDEO "Wideo:" +#define STR_VIDEO_2 "Wideo 2:" +#define STR_VOODOO "Grafika Voodoo" +#define STR_IBM8514 "Grafika IBM 8514/a" +#define STR_XGA "Grafika XGA" -#define STR_MOUSE "Mysz:" -#define STR_JOYSTICK "Joystick:" -#define STR_JOY1 "Joystick 1..." -#define STR_JOY2 "Joystick 2..." -#define STR_JOY3 "Joystick 3..." -#define STR_JOY4 "Joystick 4..." +#define STR_MOUSE "Mysz:" +#define STR_JOYSTICK "Joystick:" +#define STR_JOY1 "Joystick 1..." +#define STR_JOY2 "Joystick 2..." +#define STR_JOY3 "Joystick 3..." +#define STR_JOY4 "Joystick 4..." -#define STR_SOUND "Karta dźwiÄ™kowa:" -#define STR_MIDI_OUT "UrzÄ…dzenie wyjÅ›ciowe MIDI:" -#define STR_MIDI_IN "UrzÄ…dzenie wejÅ›ciowe MIDI:" -#define STR_MPU401 "Samodzielne urzÄ…dzenie MPU-401" -#define STR_SSI "Innovation SSI-2001" -#define STR_CMS "CMS / Game Blaster" -#define STR_GUS "Gravis Ultrasound" -#define STR_FLOAT "Użyj dźwiÄ™ku FLOAT32" +#define STR_SOUND1 "Karta dźwiÄ™kowa 1:" +#define STR_SOUND2 "Karta dźwiÄ™kowa 2:" +#define STR_SOUND3 "Karta dźwiÄ™kowa 3:" +#define STR_SOUND4 "Karta dźwiÄ™kowa 4:" +#define STR_MIDI_OUT "UrzÄ…dzenie wyjÅ›ciowe MIDI:" +#define STR_MIDI_IN "UrzÄ…dzenie wejÅ›ciowe MIDI:" +#define STR_MPU401 "Samodzielne urzÄ…dzenie MPU-401" +#define STR_FLOAT "Użyj dźwiÄ™ku FLOAT32" +#define STR_FM_DRIVER "Sterownik syntezy FM" +#define STR_FM_DRV_NUKED "Nuked (dokÅ‚adniejszy)" +#define STR_FM_DRV_YMFM "YMFM (szybszy)" -#define STR_NET_TYPE "Rodzaj sieci:" -#define STR_PCAP "UrzÄ…dzenie PCap:" -#define STR_NET "Karta sieciowa:" +#define STR_NET_TYPE "Rodzaj sieci:" +#define STR_PCAP "UrzÄ…dzenie PCap:" +#define STR_NET "Karta sieciowa:" +#define STR_NET1 "Network card 1:" +#define STR_NET2 "Network card 2:" +#define STR_NET3 "Network card 3:" +#define STR_NET4 "Network card 4:" -#define STR_COM1 "UrzÄ…dzenie COM1:" -#define STR_COM2 "UrzÄ…dzenie COM2:" -#define STR_COM3 "UrzÄ…dzenie COM3:" -#define STR_COM4 "UrzÄ…dzenie COM4:" -#define STR_LPT1 "UrzÄ…dzenie LPT1:" -#define STR_LPT2 "UrzÄ…dzenie LPT2:" -#define STR_LPT3 "UrzÄ…dzenie LPT3:" -#define STR_LPT4 "UrzÄ…dzenie LPT4:" -#define STR_SERIAL1 "Port szeregowy 1" -#define STR_SERIAL2 "Port szeregowy 2" -#define STR_SERIAL3 "Port szeregowy 3" -#define STR_SERIAL4 "Port Szeregowy 4" -#define STR_PARALLEL1 "Port równolegÅ‚y 1" -#define STR_PARALLEL2 "Port równolegÅ‚y 2" -#define STR_PARALLEL3 "Port równolegÅ‚y 3" -#define STR_PARALLEL4 "Port równolegÅ‚y 4" +#define STR_COM1 "UrzÄ…dzenie COM1:" +#define STR_COM2 "UrzÄ…dzenie COM2:" +#define STR_COM3 "UrzÄ…dzenie COM3:" +#define STR_COM4 "UrzÄ…dzenie COM4:" +#define STR_LPT1 "UrzÄ…dzenie LPT1:" +#define STR_LPT2 "UrzÄ…dzenie LPT2:" +#define STR_LPT3 "UrzÄ…dzenie LPT3:" +#define STR_LPT4 "UrzÄ…dzenie LPT4:" +#define STR_SERIAL1 "Port szeregowy 1" +#define STR_SERIAL2 "Port szeregowy 2" +#define STR_SERIAL3 "Port szeregowy 3" +#define STR_SERIAL4 "Port Szeregowy 4" +#define STR_PARALLEL1 "Port równolegÅ‚y 1" +#define STR_PARALLEL2 "Port równolegÅ‚y 2" +#define STR_PARALLEL3 "Port równolegÅ‚y 3" +#define STR_PARALLEL4 "Port równolegÅ‚y 4" +#define STR_SERIAL_PASS1 "Serial port passthrough 1" +#define STR_SERIAL_PASS2 "Serial port passthrough 2" +#define STR_SERIAL_PASS3 "Serial port passthrough 3" +#define STR_SERIAL_PASS4 "Serial port passthrough 4" -#define STR_HDC "Kontroler dysku twardego:" -#define STR_FDC "Kontroler dyskietek:" -#define STR_IDE_TER "TrzeciorzÄ™dowy kontroler IDE" -#define STR_IDE_QUA "CzwartorzÄ™dowy kontroler IDE" -#define STR_SCSI "SCSI" -#define STR_SCSI_1 "Kontroler 1:" -#define STR_SCSI_2 "Kontroler 2:" -#define STR_SCSI_3 "Kontroler 3:" -#define STR_SCSI_4 "Kontroler 4:" -#define STR_CASSETTE "Kaseta" +#define STR_HDC "Kontroler dysku twardego:" +#define STR_FDC "Kontroler dyskietek:" +#define STR_IDE_TER "TrzeciorzÄ™dowy kontroler IDE" +#define STR_IDE_QUA "CzwartorzÄ™dowy kontroler IDE" +#define STR_SCSI "SCSI" +#define STR_SCSI_1 "Kontroler 1:" +#define STR_SCSI_2 "Kontroler 2:" +#define STR_SCSI_3 "Kontroler 3:" +#define STR_SCSI_4 "Kontroler 4:" +#define STR_CASSETTE "Kaseta" -#define STR_HDD "Dyski twarde:" -#define STR_NEW "&Nowy..." -#define STR_EXISTING "&IstniejÄ…cy..." -#define STR_REMOVE "&UsuÅ„" -#define STR_BUS "Magistrala:" -#define STR_CHANNEL "KanaÅ‚:" -#define STR_ID "ID:" +#define STR_HDD "Dyski twarde:" +#define STR_NEW "&Nowy..." +#define STR_EXISTING "&IstniejÄ…cy..." +#define STR_REMOVE "&UsuÅ„" +#define STR_BUS "Magistrala:" +#define STR_CHANNEL "KanaÅ‚:" +#define STR_ID "ID:" +#define STR_SPEED "Speed:" -#define STR_SPECIFY "&OkreÅ›l..." -#define STR_SECTORS "Sektory:" -#define STR_HEADS "GÅ‚owice:" -#define STR_CYLS "Cylindry:" -#define STR_SIZE_MB "Rozmiar (MB):" -#define STR_TYPE "Rodzaj:" -#define STR_IMG_FORMAT "Format obrazu:" -#define STR_BLOCK_SIZE "Rozmiar bloku:" +#define STR_SPECIFY "&OkreÅ›l..." +#define STR_SECTORS "Sektory:" +#define STR_HEADS "GÅ‚owice:" +#define STR_CYLS "Cylindry:" +#define STR_SIZE_MB "Rozmiar (MB):" +#define STR_TYPE "Rodzaj:" +#define STR_IMG_FORMAT "Format obrazu:" +#define STR_BLOCK_SIZE "Rozmiar bloku:" -#define STR_FLOPPY_DRIVES "NapÄ™dy dyskietek:" -#define STR_TURBO "RozrzÄ…dy Turbo" -#define STR_CHECKBPB "Sprawdzaj BPB" -#define STR_CDROM_DRIVES "NapÄ™dy CD-ROM:" -#define STR_CD_SPEED "Szybkość:" +#define STR_FLOPPY_DRIVES "NapÄ™dy dyskietek:" +#define STR_TURBO "RozrzÄ…dy Turbo" +#define STR_CHECKBPB "Sprawdzaj BPB" +#define STR_CDROM_DRIVES "NapÄ™dy CD-ROM:" +#define STR_CD_SPEED "Szybkość:" -#define STR_MO_DRIVES "NapÄ™dy MO:" -#define STR_ZIP_DRIVES "NapÄ™dy ZIP:" -#define STR_250 "ZIP 250" +#define STR_MO_DRIVES "NapÄ™dy MO:" +#define STR_ZIP_DRIVES "NapÄ™dy ZIP:" +#define STR_250 "ZIP 250" -#define STR_ISARTC "ISA RTC:" -#define STR_ISAMEM "Rozszerzenie pamiÄ™ci ISA" -#define STR_ISAMEM_1 "Karta 1:" -#define STR_ISAMEM_2 "Karta 2:" -#define STR_ISAMEM_3 "Karta 3:" -#define STR_ISAMEM_4 "Karta 4:" -#define STR_BUGGER "UrzÄ…dzenie ISABugger" -#define STR_POSTCARD "Karta POST" +#define STR_ISARTC "ISA RTC:" +#define STR_ISAMEM "Rozszerzenie pamiÄ™ci ISA" +#define STR_ISAMEM_1 "Karta 1:" +#define STR_ISAMEM_2 "Karta 2:" +#define STR_ISAMEM_3 "Karta 3:" +#define STR_ISAMEM_4 "Karta 4:" +#define STR_BUGGER "UrzÄ…dzenie ISABugger" +#define STR_POSTCARD "Karta POST" -#define FONT_SIZE 9 -#define FONT_NAME "Segoe UI" +#define FONT_SIZE 9 +#define FONT_NAME "Segoe UI" #include "dialogs.rc" @@ -366,194 +392,188 @@ END // String Table // -STRINGTABLE DISCARDABLE +STRINGTABLE DISCARDABLE BEGIN - 2048 "86Box" - IDS_2049 "Błąd" - IDS_2050 "Fatalny błąd" - IDS_2051 " - PAUSED" - IDS_2052 "NaciÅ›nij klawisze Ctrl+Alt+PgDn aby wrócić to trybu okna." - IDS_2053 "Szybkość" - IDS_2054 "ZIP %03i %i (%s): %ls" - IDS_2055 "Obrazy ZIP (*.IM?;*.ZDI)\0*.IM?;*.ZDI\0" - IDS_2056 "86Box nie może znaleźć obrazów ROM nadajÄ…cych siÄ™ do użytku.\n\nProszÄ™ pobrać zestaw obrazów ROM ze strony download, i rozpakować je do katalogu ""roms""." - IDS_2057 "(pusty)" - IDS_2058 "Obrazy ZIP (*.IM?;*.ZDI)\0*.IM?;*.ZDI\0Wszystkie pliki (*.*)\0*.*\0" - IDS_2059 "Turbo" - IDS_2060 "Włącz" - IDS_2061 "Wyłącz" - IDS_2062 "Wszystkie obrazy (*.86F;*.DSK;*.FLP;*.IM?;*.*FD?)\0*.86F;*.DSK;*.FLP;*.IM?;*.*FD?\0Podstawowe obrazy sektorów(*.DSK;*.FLP;*.IM?;*.*FD?)\0*.DSK;*.FLP;*.IM?;*.IMG;*.*FD?\0Obrazy powierzchniowe (*.86F)\0*.86F\0" - IDS_2063 "Maszyna ""%hs"" nie jest dostÄ™pna, ponieważ brakuje obrazów ROM w katalogu roms/machines. Przełączanie na dostÄ™pnÄ… maszynÄ™." + 2048 "86Box" + IDS_2049 "Błąd" + IDS_2050 "Fatalny błąd" + IDS_2051 " - PAUSED" + IDS_2052 "NaciÅ›nij klawisze Ctrl+Alt+PgDn aby wrócić to trybu okna." + IDS_2053 "Szybkość" + IDS_2054 "ZIP %03i %i (%s): %ls" + IDS_2055 "Obrazy ZIP (*.IM?;*.ZDI)\0*.IM?;*.ZDI\0" + IDS_2056 "86Box nie może znaleźć obrazów ROM nadajÄ…cych siÄ™ do użytku.\n\nProszÄ™ pobrać zestaw obrazów ROM ze strony download, i rozpakować je do katalogu ""roms""." + IDS_2057 "(pusty)" + IDS_2058 "Obrazy ZIP (*.IM?;*.ZDI)\0*.IM?;*.ZDI\0Wszystkie pliki (*.*)\0*.*\0" + IDS_2059 "Turbo" + IDS_2060 "Włącz" + IDS_2061 "Wyłącz" + IDS_2062 "Wszystkie obrazy (*.86F;*.DSK;*.FLP;*.IM?;*.*FD?)\0*.86F;*.DSK;*.FLP;*.IM?;*.*FD?\0Podstawowe obrazy sektorów(*.DSK;*.FLP;*.IM?;*.*FD?)\0*.DSK;*.FLP;*.IM?;*.IMG;*.*FD?\0Obrazy powierzchniowe (*.86F)\0*.86F\0" + IDS_2063 "Maszyna ""%hs"" nie jest dostÄ™pna, ponieważ brakuje obrazów ROM w katalogu roms/machines. Przełączanie na dostÄ™pnÄ… maszynÄ™." END -STRINGTABLE DISCARDABLE +STRINGTABLE DISCARDABLE BEGIN - IDS_2064 "Karta wideo ""%hs"" nie jest dostÄ™pna, ponieważ brakuje obrazów ROM w katalogu roms/video. Przełączanie na dostÄ™pnÄ… kartÄ™ wideo." - IDS_2065 "Maszyna" - IDS_2066 "Ekran" - IDS_2067 "UrzÄ…dzenia wejÅ›ciowe" - IDS_2068 "DźwiÄ™k" - IDS_2069 "Sieć" - IDS_2070 "Porty (COM & LPT)" - IDS_2071 "Kontrolery pamiÄ™ci" - IDS_2072 "Dyski twarde" - IDS_2073 "NapÄ™dy dyskietek i CD-ROM" - IDS_2074 "Inne urzÄ…dzenia wymienne" - IDS_2075 "Inne urzÄ…dzenia peryferyjne" - IDS_2076 "Obrazy powierzchniowe (*.86F)\0*.86F\0" - IDS_2077 "Kliknij w celu przechwycenia myszy" - IDS_2078 "NaciÅ›nij klawisze F8+F12 w celu uwolnienia myszy" - IDS_2079 "NaciÅ›nij klawisze F8+F12 lub Å›rodkowy przycisk w celu uwolnienia myszy" + IDS_2064 "Karta wideo ""%hs"" nie jest dostÄ™pna, ponieważ brakuje obrazów ROM w katalogu roms/video. Przełączanie na dostÄ™pnÄ… kartÄ™ wideo." + IDS_2065 "Maszyna" + IDS_2066 "Ekran" + IDS_2067 "UrzÄ…dzenia wejÅ›ciowe" + IDS_2068 "DźwiÄ™k" + IDS_2069 "Sieć" + IDS_2070 "Porty (COM & LPT)" + IDS_2071 "Kontrolery pamiÄ™ci" + IDS_2072 "Dyski twarde" + IDS_2073 "NapÄ™dy dyskietek i CD-ROM" + IDS_2074 "Inne urzÄ…dzenia wymienne" + IDS_2075 "Inne urzÄ…dzenia peryferyjne" + IDS_2076 "Obrazy powierzchniowe (*.86F)\0*.86F\0" + IDS_2077 "Kliknij w celu przechwycenia myszy" + IDS_2078 "NaciÅ›nij klawisze F8+F12 w celu uwolnienia myszy" + IDS_2079 "NaciÅ›nij klawisze F8+F12 lub Å›rodkowy przycisk w celu uwolnienia myszy" END -STRINGTABLE DISCARDABLE +STRINGTABLE DISCARDABLE BEGIN - IDS_2080 "Nie można zainicjować FluidSynth" - IDS_2081 "Magistrala" - IDS_2082 "Plik" - IDS_2083 "C" - IDS_2084 "H" - IDS_2085 "S" - IDS_2086 "MB" - IDS_2087 "Sprawdzaj BPB" - IDS_2088 "KB" - IDS_2089 "Nie można zainicjować renderera wideo." - IDS_2090 "DomyÅ›lny" - IDS_2091 "%i Stany oczekiwania" - IDS_2092 "Rodzaj" - IDS_2093 "Nie udaÅ‚o siÄ™ ustawić PCap" - IDS_2094 "Nie znaleziono urzÄ…dzeÅ„ PCap" - IDS_2095 "NieprawidÅ‚owe urzÄ…dzenie PCap" - IDS_2096 "Standardowe joysticki 2-przyciskowe" - IDS_2097 "Standardowy joystick 4-przyciskowy" - IDS_2098 "Standardowy joystick 6-przyciskowy" - IDS_2099 "Standardowy joystick 8-przyciskowy" - IDS_2100 "CH Flightstick Pro" - IDS_2101 "Microsoft SideWinder Pad" - IDS_2102 "Thrustmaster Flight Control System" - IDS_2103 "Å»aden" - IDS_2104 "Nie można zaÅ‚adować akceleratorów klawiaturowych." - IDS_2105 "Nie można zarejestrować surowych danych wejÅ›ciowych." - IDS_2106 "%u" - IDS_2107 "%u MB (CHS: %i, %i, %i)" - IDS_2108 "Dyskietka %i (%s): %ls" - IDS_2109 "Wszystkie obrazy (*.0??;*.1??;*.??0;*.86F;*.BIN;*.CQ?;*.D??;*.FLP;*.HDM;*.IM?;*.JSON;*.TD0;*.*FD?;*.MFM;*.XDF)\0*.0??;*.1??;*.??0;*.86F;*.BIN;*.CQ?;*.D??;*.FLP;*.HDM;*.IM?;*.JSON;*.TD0;*.*FD?;*.MFM;*.XDF\0Zaawansowane obrazy sektorów (*.IMD;*.JSON;*.TD0)\0*.IMD;*.JSON;*.TD0\0Podstawowe obrazy sektorów (*.0??;*.1??;*.??0;*.BIN;*.CQ?;*.D??;*.FLP;*.HDM;*.IM?;*.XDF;*.*FD?)\0*.0??;*.1??;*.??0;*.BIN;*.CQ?;*.D??;*.FLP;*.HDM;*.IM?;*.XDF;*.*FD?\0Flux images (*.FDI)\0*.FDI\0Obrazy powierzchniowe (*.86F;*.MFM)\0*.86F;*.MFM\0All files (*.*)\0*.*\0" - IDS_2110 "Nie można zainicjować FreeType" - IDS_2111 "Nie można zainicjować SDL, wymagany SDL2.dll" - IDS_2112 "JesteÅ› pewien że chcesz wykonać twardy reset emulowanej maszyny?" - IDS_2113 "JesteÅ› pewien że chcesz zakoÅ„czyć 86Box?" - IDS_2114 "Nie można zainicjować Ghostscript" - IDS_2115 "MO %i (%ls): %ls" - IDS_2116 "Obrazy MO (*.IM?;*.MDI)\0*.IM?;*.MDI\0All files (*.*)\0*.*\0" - IDS_2117 "Witamy w 86Box!" - IDS_2118 "Kontroler wewnÄ™trzny" - IDS_2119 "ZakoÅ„cz" - IDS_2120 "Nie znaleziono obrazów ROM" - IDS_2121 "Czy chcesz zapisać ustawienia?" - IDS_2122 "To spowoduje twardy reset wirtualnej maszyny." - IDS_2123 "Zapisz" - IDS_2124 "O 86Box" - IDS_2125 "86Box v" EMU_VERSION + IDS_2081 "Magistrala" + IDS_2082 "Plik" + IDS_2083 "C" + IDS_2084 "H" + IDS_2085 "S" + IDS_2086 "MB" + IDS_2087 "Speed" + IDS_2088 "Sprawdzaj BPB" + IDS_2089 "KB" + IDS_2090 "Nie można zainicjować renderera wideo." + IDS_2091 "DomyÅ›lny" + IDS_2092 "%i Stany oczekiwania" + IDS_2093 "Rodzaj" + IDS_2094 "Nie udaÅ‚o siÄ™ ustawić PCap" + IDS_2095 "Nie znaleziono urzÄ…dzeÅ„ PCap" + IDS_2096 "NieprawidÅ‚owe urzÄ…dzenie PCap" + IDS_2097 "Standardowe joysticki 2-przyciskowe" + IDS_2098 "Standardowy joystick 4-przyciskowy" + IDS_2099 "Standardowy joystick 6-przyciskowy" + IDS_2100 "Standardowy joystick 8-przyciskowy" + IDS_2101 "CH Flightstick Pro" + IDS_2102 "Microsoft SideWinder Pad" + IDS_2103 "Thrustmaster Flight Control System" + IDS_2104 "Å»aden" + IDS_2105 "Nie można zaÅ‚adować akceleratorów klawiaturowych." + IDS_2106 "Nie można zarejestrować surowych danych wejÅ›ciowych." + IDS_2107 "%u" + IDS_2108 "%u MB (CHS: %i, %i, %i)" + IDS_2109 "Dyskietka %i (%s): %ls" + IDS_2110 "Wszystkie obrazy (*.0??;*.1??;*.??0;*.86F;*.BIN;*.CQ?;*.D??;*.FLP;*.HDM;*.IM?;*.JSON;*.TD0;*.*FD?;*.MFM;*.XDF)\0*.0??;*.1??;*.??0;*.86F;*.BIN;*.CQ?;*.D??;*.FLP;*.HDM;*.IM?;*.JSON;*.TD0;*.*FD?;*.MFM;*.XDF\0Zaawansowane obrazy sektorów (*.IMD;*.JSON;*.TD0)\0*.IMD;*.JSON;*.TD0\0Podstawowe obrazy sektorów (*.0??;*.1??;*.??0;*.BIN;*.CQ?;*.D??;*.FLP;*.HDM;*.IM?;*.XDF;*.*FD?)\0*.0??;*.1??;*.??0;*.BIN;*.CQ?;*.D??;*.FLP;*.HDM;*.IM?;*.XDF;*.*FD?\0Flux images (*.FDI)\0*.FDI\0Obrazy powierzchniowe (*.86F;*.MFM)\0*.86F;*.MFM\0All files (*.*)\0*.*\0" + IDS_2112 "Nie można zainicjować SDL, wymagany SDL2.dll" + IDS_2113 "JesteÅ› pewien że chcesz wykonać twardy reset emulowanej maszyny?" + IDS_2114 "JesteÅ› pewien że chcesz zakoÅ„czyć 86Box?" + IDS_2115 "Nie można zainicjować Ghostscript" + IDS_2116 "MO %i (%ls): %ls" + IDS_2117 "Obrazy MO (*.IM?;*.MDI)\0*.IM?;*.MDI\0All files (*.*)\0*.*\0" + IDS_2118 "Witamy w 86Box!" + IDS_2119 "Kontroler wewnÄ™trzny" + IDS_2120 "ZakoÅ„cz" + IDS_2121 "Nie znaleziono obrazów ROM" + IDS_2122 "Czy chcesz zapisać ustawienia?" + IDS_2123 "To spowoduje twardy reset wirtualnej maszyny." + IDS_2124 "Zapisz" + IDS_2125 "O 86Box" + IDS_2126 "86Box v" EMU_VERSION - IDS_2126 "Emulator starych komputerów\n\nAutorzy: Sarah Walker, Miran Grca, Fred N. van Kempen (waltje), SA1988, Tiseno100, reenigne, leilei, JohnElliott, greatpsycho, i inni.\n\nPrzetÅ‚umaczony przez: Fanta-Shokata\n\nWydany na licencji GNU General Public License w wersji 2 lub nowszej. Zobacz LICENSE aby uzyskać wiÄ™cej informacji." - IDS_2127 "OK" - IDS_2128 "SprzÄ™t niedostÄ™pny" + IDS_2127 "Emulator starych komputerów\n\nAutorzy: Miran GrÄa (OBattler), RichardG867, Jasmine Iwanek, TC1995, coldbrewed, Teemu Korhonen (Manaatti), Joakim L. Gilje, Adrien Moulin (elyosh), Daniel Balsom (gloriouscow), Cacodemon345, Fred N. van Kempen (waltje), Tiseno100, reenigne, i inni.\n\nWith previous core contributions from Sarah Walker, leilei, JohnElliott, greatpsycho, i inni.\n\nPrzetÅ‚umaczony przez: Fanta-Shokata\n\nWydany na licencji GNU General Public License w wersji 2 lub nowszej. Zobacz LICENSE aby uzyskać wiÄ™cej informacji." + IDS_2128 "OK" + IDS_2129 "SprzÄ™t niedostÄ™pny" #ifdef _WIN32 #define LIB_NAME_PCAP "WinPcap" #else #define LIB_NAME_PCAP "libpcap" #endif - IDS_2129 "Sprawdź, czy " LIB_NAME_PCAP " jest zainstalowany i czy posiadasz połączenie sieciowe kompatybilne z " LIB_NAME_PCAP "." - IDS_2130 "NieprawidÅ‚owa konfiguracja" -#ifdef _WIN32 -#define LIB_NAME_FREETYPE "freetype.dll" -#else -#define LIB_NAME_FREETYPE "libfreetype" -#endif - IDS_2131 LIB_NAME_FREETYPE " jest wymagany do emulacji drukarki ESC-P." + IDS_2130 "Sprawdź, czy " LIB_NAME_PCAP " jest zainstalowany i czy posiadasz połączenie sieciowe kompatybilne z " LIB_NAME_PCAP "." + IDS_2131 "NieprawidÅ‚owa konfiguracja" #ifdef _WIN32 #define LIB_NAME_GS "gsdll32.dll" #else #define LIB_NAME_GS "libgs" #endif - IDS_2132 LIB_NAME_GS " jest wymagany do automatycznej konwersji plików PostScript do PDF.\n\nDokumenty wysÅ‚ane do ogólnej drukarki PostScript zostanÄ… zapisane jako pliki PostScript (.ps)." -#ifdef _WIN32 -#define LIB_NAME_FLUIDSYNTH "libfluidsynth.dll" -#else -#define LIB_NAME_FLUIDSYNTH "libfluidsynth" -#endif - IDS_2133 LIB_NAME_FLUIDSYNTH " jest wymagany dla wyjÅ›cia FluidSynth MIDI." - IDS_2134 "Przechodzenie do trybu peÅ‚noekranowego" - IDS_2135 "Nie pokazuj wiÄ™cej tego komunikatu" - IDS_2136 "Nie koÅ„cz" - IDS_2137 "Przywróć" - IDS_2138 "Nie przywracaj" - IDS_2139 "Obrazy MO (*.IM?;*.MDI)\0*.IM?;*.MDI\0All files (*.*)\0*.*\0" - IDS_2140 "Obrazy CD-ROM (*.ISO;*.CUE)\0*.ISO;*.CUE\0All files (*.*)\0*.*\0" - IDS_2141 "Konfiguracja urzÄ…dzenia %hs" - IDS_2142 "Monitor w trybie czuwania" - IDS_2143 "Shadery OpenGL (*.GLSL)\0*.GLSL\0Wszystkie pliki (*.*)\0*.*\0" - IDS_2144 "Opcje OpenGL" - IDS_2145 "Åadujesz nieobsÅ‚ugiwanÄ… konfiguracjÄ™" - IDS_2146 "Wybór rodzaju procesora oparty na wybranej maszynie jest wyłączony dla tej emulowanej maszyny.\n\nPozwala to na wybór procesora który jest niekompatybilny z wybranÄ… maszynÄ…. Jednak możesz napotkać niezgodnoÅ›ci z BIOS-em maszyny lub innym oprogramowaniem.\n\nAktywacja tego ustawienia nie jest wspierana i każde zgÅ‚oszenie błędu może zostać zamkniÄ™te jako nieważne." - IDS_2147 "Kontynuuj" - IDS_2148 "Kaseta: %s" - IDS_2149 "Obrazy kaset (*.PCM;*.RAW;*.WAV;*.CAS)\0*.PCM;*.RAW;*.WAV;*.CAS\0Wszystkie pliki (*.*)\0*.*\0" - IDS_2150 "Kartrydż %i: %ls" - IDS_2151 "Obrazy kartrydżu (*.A;*.B;*.JRC)\0*.A;*.B;*.JRC\0Wszystkie pliki (*.*)\0*.*\0" - IDS_2152 "Błąd inicjalizacji renderera" - IDS_2153 "Nie można zainicjować renderera OpenGL (3.0 Core). Użyj innego." - IDS_2154 "Wznów wykonywanie" - IDS_2155 "Zatrzymaj wykonywanie" - IDS_2156 "NaciÅ›nij Ctrl+Alt+Del" - IDS_2157 "NaciÅ›nij Ctrl+Alt+Esc" - IDS_2158 "Twardy reset" - IDS_2159 "Wyłączenie ACPI" - IDS_2160 "Ustawienia" + IDS_2133 LIB_NAME_GS " jest wymagany do automatycznej konwersji plików PostScript do PDF.\n\nDokumenty wysÅ‚ane do ogólnej drukarki PostScript zostanÄ… zapisane jako pliki PostScript (.ps)." + IDS_2135 "Przechodzenie do trybu peÅ‚noekranowego" + IDS_2136 "Nie pokazuj wiÄ™cej tego komunikatu" + IDS_2137 "Nie koÅ„cz" + IDS_2138 "Przywróć" + IDS_2139 "Nie przywracaj" + IDS_2140 "Obrazy MO (*.IM?;*.MDI)\0*.IM?;*.MDI\0All files (*.*)\0*.*\0" + IDS_2141 "Obrazy CD-ROM (*.ISO;*.CUE)\0*.ISO;*.CUE\0All files (*.*)\0*.*\0" + IDS_2142 "Konfiguracja urzÄ…dzenia %hs" + IDS_2143 "Monitor w trybie czuwania" + IDS_2144 "Shadery OpenGL (*.GLSL)\0*.GLSL\0Wszystkie pliki (*.*)\0*.*\0" + IDS_2145 "Opcje OpenGL" + IDS_2146 "Åadujesz nieobsÅ‚ugiwanÄ… konfiguracjÄ™" + IDS_2147 "Wybór rodzaju procesora oparty na wybranej maszynie jest wyłączony dla tej emulowanej maszyny.\n\nPozwala to na wybór procesora który jest niekompatybilny z wybranÄ… maszynÄ…. Jednak możesz napotkać niezgodnoÅ›ci z BIOS-em maszyny lub innym oprogramowaniem.\n\nAktywacja tego ustawienia nie jest wspierana i każde zgÅ‚oszenie błędu może zostać zamkniÄ™te jako nieważne." + IDS_2148 "Kontynuuj" + IDS_2149 "Kaseta: %s" + IDS_2150 "Obrazy kaset (*.PCM;*.RAW;*.WAV;*.CAS)\0*.PCM;*.RAW;*.WAV;*.CAS\0Wszystkie pliki (*.*)\0*.*\0" + IDS_2151 "Kartrydż %i: %ls" + IDS_2152 "Obrazy kartrydżu (*.A;*.B;*.JRC)\0*.A;*.B;*.JRC\0Wszystkie pliki (*.*)\0*.*\0" + IDS_2153 "Błąd inicjalizacji renderera" + IDS_2154 "Nie można zainicjować renderera OpenGL (3.0 Core). Użyj innego." + IDS_2155 "Wznów wykonywanie" + IDS_2156 "Zatrzymaj wykonywanie" + IDS_2157 "NaciÅ›nij Ctrl+Alt+Del" + IDS_2158 "NaciÅ›nij Ctrl+Alt+Esc" + IDS_2159 "Twardy reset" + IDS_2160 "Wyłączenie ACPI" + IDS_2161 "Ustawienia" + IDS_2162 "Type" + IDS_2163 "No Dynarec" + IDS_2164 "Old Dynarec" + IDS_2165 "New Dynarec" + IDS_2166 "Video card #2 ""%hs"" is not available due to missing ROMs in the roms/video directory. Disabling the second video card." + IDS_2167 "Failed to initialize network driver" + IDS_2168 "The network configuration will be switched to the null driver" END -STRINGTABLE DISCARDABLE +STRINGTABLE DISCARDABLE BEGIN IDS_4096 "Dysk twardy (%s)" - IDS_4097 "%01i:%01i" - IDS_4098 "%01i" - IDS_4099 "NapÄ™dy CD-ROM MFM/RLL lub ESDI nigdy nie istniaÅ‚y" - IDS_4100 "Niestandardowy..." - IDS_4101 "Niestandardowy (duży)..." - IDS_4102 "Dodaj nowy dysk twardy" - IDS_4103 "Dodaj istniejÄ…cy dysk twardy" - IDS_4104 "Obrazy dysków HDI nie mogÄ… być wiÄ™ksze niż 4 GB." - IDS_4105 "Obrazy dysków nie mogÄ… być wiÄ™ksze niż 127 GB." - IDS_4106 "Obrazy dysku twardego (*.HD?;*.IM?;*.VHD)\0*.HD?;*.IM?;*.VHD\0Wszystkie pliki (*.*)\0*.*\0" - IDS_4107 "Nie można odczytać pliku" - IDS_4108 "Nie można zapisać pliku" - IDS_4109 "Obrazy HDI lub HDX z rozmiarem sektora innym niż 512 nie sÄ… wspierane." - IDS_4110 "USB nie jest jeszcze wspierane" - IDS_4111 "Plik obrazu dysku już istnieje" - IDS_4112 "OkreÅ›l prawidÅ‚owÄ… nazwÄ™ pliku." - IDS_4113 "Utworzono obraz dysku" - IDS_4114 "Sprawdź, czy plik istnieje i nadaje siÄ™ do odczytu." - IDS_4115 "Sprawdź, czy plik jest zapiyswany w katalogu z możliwoÅ›ciÄ… zapisu." - IDS_4116 "Obraz dysku jest za duży" - IDS_4117 "Nie zapomnij o partycjonowaniu i sformatowaniu nowo utworzego dysku" - IDS_4118 "Wybrany plik zostanie nadpisany. Czy na pewno chcesz użyć tego pliku?" - IDS_4119 "Niewspierany obraz dysku" - IDS_4120 "Nadpisz" - IDS_4121 "Nie nadpisuj" - IDS_4122 "Obraz surowy (.img)" - IDS_4123 "Obraz HDI (.hdi)" - IDS_4124 "Obraz HDX (.hdx)" - IDS_4125 "VHD o staÅ‚ym rozmiarze (.vhd)" - IDS_4126 "VHD o dynamicznym rozmiarze (.vhd)" - IDS_4127 "VHD różnicujÄ…cy (.vhd)" - IDS_4128 "Duże bloki (2 MB)" - IDS_4129 "MaÅ‚e bloki (512 KB)" - IDS_4130 "Pliki VHD (*.VHD)\0*.VHD\0Wszystkie pliki (*.*)\0*.*\0" - IDS_4131 "Wybierz nadrzÄ™dny plik VHD" - IDS_4132 "Może to oznaczać, że obraz nadrzÄ™dny zostaÅ‚ zmodyfikowany po utworzeniu obrazu różnicujÄ…cego.\n\nMoże siÄ™ to również zdarzyć, jeÅ›li pliki obrazów zostaÅ‚y przeniesione lub skopiowane, lub wystÄ…piÅ‚ błąd w programie, który utworzyÅ‚ ten dysk\n\nCzy chcesz naprawić sygnatury czasowe?" - IDS_4133 "Sygnatury czasowe dysku nadrzÄ™dnego i podrzÄ™dnego nie zgadzajÄ… siÄ™" - IDS_4134 "Nie można naprawić sygnatury czasowej VHD." - IDS_4135 "%01i:%02i" + IDS_4097 "%01i:%01i" + IDS_4098 "%01i" + IDS_4099 "NapÄ™dy CD-ROM MFM/RLL lub ESDI nigdy nie istniaÅ‚y" + IDS_4100 "Niestandardowy..." + IDS_4101 "Niestandardowy (duży)..." + IDS_4102 "Dodaj nowy dysk twardy" + IDS_4103 "Dodaj istniejÄ…cy dysk twardy" + IDS_4104 "Obrazy dysków HDI nie mogÄ… być wiÄ™ksze niż 4 GB." + IDS_4105 "Obrazy dysków nie mogÄ… być wiÄ™ksze niż 127 GB." + IDS_4106 "Obrazy dysku twardego (*.HD?;*.IM?;*.VHD)\0*.HD?;*.IM?;*.VHD\0Wszystkie pliki (*.*)\0*.*\0" + IDS_4107 "Nie można odczytać pliku" + IDS_4108 "Nie można zapisać pliku" + IDS_4109 "Obrazy HDI lub HDX z rozmiarem sektora innym niż 512 nie sÄ… wspierane." + IDS_4110 "USB nie jest jeszcze wspierane" + IDS_4111 "Plik obrazu dysku już istnieje" + IDS_4112 "OkreÅ›l prawidÅ‚owÄ… nazwÄ™ pliku." + IDS_4113 "Utworzono obraz dysku" + IDS_4114 "Sprawdź, czy plik istnieje i nadaje siÄ™ do odczytu." + IDS_4115 "Sprawdź, czy plik jest zapiyswany w katalogu z możliwoÅ›ciÄ… zapisu." + IDS_4116 "Obraz dysku jest za duży" + IDS_4117 "Nie zapomnij o partycjonowaniu i sformatowaniu nowo utworzego dysku" + IDS_4118 "Wybrany plik zostanie nadpisany. Czy na pewno chcesz użyć tego pliku?" + IDS_4119 "Niewspierany obraz dysku" + IDS_4120 "Nadpisz" + IDS_4121 "Nie nadpisuj" + IDS_4122 "Obraz surowy (.img)" + IDS_4123 "Obraz HDI (.hdi)" + IDS_4124 "Obraz HDX (.hdx)" + IDS_4125 "VHD o staÅ‚ym rozmiarze (.vhd)" + IDS_4126 "VHD o dynamicznym rozmiarze (.vhd)" + IDS_4127 "VHD różnicujÄ…cy (.vhd)" + IDS_4128 "Duże bloki (2 MB)" + IDS_4129 "MaÅ‚e bloki (512 KB)" + IDS_4130 "Pliki VHD (*.VHD)\0*.VHD\0Wszystkie pliki (*.*)\0*.*\0" + IDS_4131 "Wybierz nadrzÄ™dny plik VHD" + IDS_4132 "Może to oznaczać, że obraz nadrzÄ™dny zostaÅ‚ zmodyfikowany po utworzeniu obrazu różnicujÄ…cego.\n\nMoże siÄ™ to również zdarzyć, jeÅ›li pliki obrazów zostaÅ‚y przeniesione lub skopiowane, lub wystÄ…piÅ‚ błąd w programie, który utworzyÅ‚ ten dysk\n\nCzy chcesz naprawić sygnatury czasowe?" + IDS_4133 "Sygnatury czasowe dysku nadrzÄ™dnego i podrzÄ™dnego nie zgadzajÄ… siÄ™" + IDS_4134 "Nie można naprawić sygnatury czasowej VHD." + IDS_4135 "%01i:%02i" IDS_4352 "MFM/RLL" IDS_4353 "XTA" @@ -562,56 +582,56 @@ BEGIN IDS_4356 "ATAPI" IDS_4357 "SCSI" - IDS_4608 "MFM/RLL (%01i:%01i)" - IDS_4609 "XTA (%01i:%01i)" - IDS_4610 "ESDI (%01i:%01i)" - IDS_4611 "IDE (%01i:%01i)" - IDS_4612 "ATAPI (%01i:%01i)" - IDS_4613 "SCSI (%01i:%02i)" + IDS_4608 "MFM/RLL (%01i:%01i)" + IDS_4609 "XTA (%01i:%01i)" + IDS_4610 "ESDI (%01i:%01i)" + IDS_4611 "IDE (%01i:%01i)" + IDS_4612 "ATAPI (%01i:%01i)" + IDS_4613 "SCSI (%01i:%02i)" - IDS_5120 "CD-ROM %i (%s): %s" + IDS_5120 "CD-ROM %i (%s): %s" - IDS_5376 "Wyłączony" - IDS_5381 "ATAPI" + IDS_5376 "Wyłączony" + IDS_5381 "ATAPI" IDS_5382 "SCSI" - IDS_5632 "Wyłączony" - IDS_5637 "ATAPI (%01i:%01i)" + IDS_5632 "Wyłączony" + IDS_5637 "ATAPI (%01i:%01i)" IDS_5638 "SCSI (%01i:%02i)" - IDS_5888 "160 kB" - IDS_5889 "180 kB" - IDS_5890 "320 kB" - IDS_5891 "360 kB" - IDS_5892 "640 kB" - IDS_5893 "720 kB" - IDS_5894 "1,2 MB" - IDS_5895 "1,25 MB" - IDS_5896 "1,44 MB" - IDS_5897 "DMF (klaster 1024)" - IDS_5898 "DMF (klaster 2048)" - IDS_5899 "2,88 MB" - IDS_5900 "ZIP 100" - IDS_5901 "ZIP 250" - IDS_5902 "3.5"" 128 MB (ISO 10090)" - IDS_5903 "3.5"" 230 MB (ISO 13963)" - IDS_5904 "3.5"" 540 MB (ISO 15498)" - IDS_5905 "3.5"" 640 MB (ISO 15498)" - IDS_5906 "3.5"" 1,3 GB (GigaMO)" - IDS_5907 "3.5"" 2,3 GB (GigaMO 2)" - IDS_5908 "5.25"" 600 MB" - IDS_5909 "5.25"" 650 MB" - IDS_5910 "5.25"" 1 GB" - IDS_5911 "5.25"" 1,3 GB" + IDS_5888 "160 kB" + IDS_5889 "180 kB" + IDS_5890 "320 kB" + IDS_5891 "360 kB" + IDS_5892 "640 kB" + IDS_5893 "720 kB" + IDS_5894 "1,2 MB" + IDS_5895 "1,25 MB" + IDS_5896 "1,44 MB" + IDS_5897 "DMF (klaster 1024)" + IDS_5898 "DMF (klaster 2048)" + IDS_5899 "2,88 MB" + IDS_5900 "ZIP 100" + IDS_5901 "ZIP 250" + IDS_5902 "3.5"" 128 MB (ISO 10090)" + IDS_5903 "3.5"" 230 MB (ISO 13963)" + IDS_5904 "3.5"" 540 MB (ISO 15498)" + IDS_5905 "3.5"" 640 MB (ISO 15498)" + IDS_5906 "3.5"" 1,3 GB (GigaMO)" + IDS_5907 "3.5"" 2,3 GB (GigaMO 2)" + IDS_5908 "5.25"" 600 MB" + IDS_5909 "5.25"" 650 MB" + IDS_5910 "5.25"" 1 GB" + IDS_5911 "5.25"" 1,3 GB" - IDS_6144 "Idealne obroty" - IDS_6145 "1% poniżej idealnych obrotów" - IDS_6146 "1.5% poniżej idealnych obrotów" - IDS_6147 "2% poniżej idealnych obrotów" + IDS_6144 "Idealne obroty" + IDS_6145 "1% poniżej idealnych obrotów" + IDS_6146 "1.5% poniżej idealnych obrotów" + IDS_6147 "2% poniżej idealnych obrotów" - IDS_7168 "(DomyÅ›lne ustawienie systemowe)" + IDS_7168 "(DomyÅ›lne ustawienie systemowe)" END -#define IDS_LANG_ENUS IDS_7168 +#define IDS_LANG_ENUS IDS_7168 // Polish (pl-PL) resources ///////////////////////////////////////////////////////////////////////////// diff --git a/src/win/languages/pt-BR.rc b/src/win/languages/pt-BR.rc index 6f74e40d5..00e9c243d 100644 --- a/src/win/languages/pt-BR.rc +++ b/src/win/languages/pt-BR.rc @@ -16,113 +16,122 @@ LANGUAGE LANG_PORTUGUESE, SUBLANG_PORTUGUESE_BRAZILIAN // Menu // -MainMenu MENU DISCARDABLE +MainMenu MENU DISCARDABLE BEGIN POPUP "&Ação" BEGIN - MENUITEM "&Teclado requer captura", IDM_ACTION_KBD_REQ_CAPTURE - MENUITEM "CTRL &direito é o ALT esquerdo", IDM_ACTION_RCTRL_IS_LALT + MENUITEM "&Teclado requer captura", IDM_ACTION_KBD_REQ_CAPTURE + MENUITEM "CTRL &direito é o ALT esquerdo", IDM_ACTION_RCTRL_IS_LALT MENUITEM SEPARATOR - MENUITEM "&Reinicialização completa...", IDM_ACTION_HRESET - MENUITEM "&Ctrl+Alt+Del\tCtrl+F12", IDM_ACTION_RESET_CAD + MENUITEM "&Reinicialização completa...", IDM_ACTION_HRESET + MENUITEM "&Ctrl+Alt+Del\tCtrl+F12", IDM_ACTION_RESET_CAD MENUITEM SEPARATOR - MENUITEM "Ctrl+Alt+&Esc", IDM_ACTION_CTRL_ALT_ESC + MENUITEM "Ctrl+Alt+&Esc", IDM_ACTION_CTRL_ALT_ESC MENUITEM SEPARATOR - MENUITEM "&Pausar", IDM_ACTION_PAUSE + MENUITEM "&Pausar", IDM_ACTION_PAUSE MENUITEM SEPARATOR - MENUITEM "&Sair...", IDM_ACTION_EXIT + MENUITEM "&Sair...", IDM_ACTION_EXIT END POPUP "&Exibir" BEGIN - MENUITEM "&Ocultar barra de status", IDM_VID_HIDE_STATUS_BAR - MENUITEM "Ocultar &barra de ferramenta", IDM_VID_HIDE_TOOLBAR + MENUITEM "&Ocultar barra de status", IDM_VID_HIDE_STATUS_BAR + MENUITEM "Ocultar &barra de ferramenta", IDM_VID_HIDE_TOOLBAR MENUITEM SEPARATOR - MENUITEM "&Janela redimensionável", IDM_VID_RESIZE - MENUITEM "&Lembrar tamanho e posição", IDM_VID_REMEMBER + MENUITEM "&Mostrar monitores não-primários", IDM_VID_MONITORS + MENUITEM "&Janela redimensionável", IDM_VID_RESIZE + MENUITEM "&Lembrar tamanho e posição", IDM_VID_REMEMBER MENUITEM SEPARATOR POPUP "&Renderizador" BEGIN - MENUITEM "&SDL (Software)", IDM_VID_SDL_SW - MENUITEM "SDL (&Hardware)", IDM_VID_SDL_HW - MENUITEM "SDL (&OpenGL)", IDM_VID_SDL_OPENGL - MENUITEM "Open&GL (Núcleo 3.0)", IDM_VID_OPENGL_CORE + MENUITEM "&SDL (Software)", IDM_VID_SDL_SW + MENUITEM "SDL (&Hardware)", IDM_VID_SDL_HW + MENUITEM "SDL (&OpenGL)", IDM_VID_SDL_OPENGL + MENUITEM "Open&GL (Núcleo 3.0)", IDM_VID_OPENGL_CORE #ifdef USE_VNC - MENUITEM "&VNC", IDM_VID_VNC + MENUITEM "&VNC", IDM_VID_VNC #endif END MENUITEM SEPARATOR - MENUITEM "Especificar as dimensões...", IDM_VID_SPECIFY_DIM - MENUITEM "F&orçar proporção de tela em 4:3", IDM_VID_FORCE43 + MENUITEM "Especificar as dimensões...", IDM_VID_SPECIFY_DIM + MENUITEM "F&orçar proporção de tela em 4:3", IDM_VID_FORCE43 POPUP "&Fator de redimensionamento da janela" BEGIN - MENUITEM "&0,5x", IDM_VID_SCALE_1X - MENUITEM "&1x", IDM_VID_SCALE_2X - MENUITEM "1,&5x", IDM_VID_SCALE_3X - MENUITEM "&2x", IDM_VID_SCALE_4X + MENUITEM "&0,5x", IDM_VID_SCALE_1X + MENUITEM "&1x", IDM_VID_SCALE_2X + MENUITEM "1,&5x", IDM_VID_SCALE_3X + MENUITEM "&2x", IDM_VID_SCALE_4X + MENUITEM "&3x", IDM_VID_SCALE_5X + MENUITEM "&4x", IDM_VID_SCALE_6X + MENUITEM "&5x", IDM_VID_SCALE_7X + MENUITEM "&6x", IDM_VID_SCALE_8X + MENUITEM "&7x", IDM_VID_SCALE_9X + MENUITEM "&8x", IDM_VID_SCALE_10X END POPUP "Método de filtragem" BEGIN - MENUITEM "&Mais próximo", IDM_VID_FILTER_NEAREST - MENUITEM "&Linear", IDM_VID_FILTER_LINEAR + MENUITEM "&Mais próximo", IDM_VID_FILTER_NEAREST + MENUITEM "&Linear", IDM_VID_FILTER_LINEAR END - MENUITEM "Escala Hi&DPI", IDM_VID_HIDPI + MENUITEM "Escala Hi&DPI", IDM_VID_HIDPI MENUITEM SEPARATOR - MENUITEM "&Tela cheia\tCtrl+Alt+PgUp", IDM_VID_FULLSCREEN + MENUITEM "&Tela cheia\tCtrl+Alt+PgUp", IDM_VID_FULLSCREEN POPUP "Modo de &redimensionamento da tela cheia" BEGIN - MENUITEM "&Tela cheia esticada", IDM_VID_FS_FULL - MENUITEM "&4:3", IDM_VID_FS_43 + MENUITEM "&Tela cheia esticada", IDM_VID_FS_FULL + MENUITEM "&4:3", IDM_VID_FS_43 MENUITEM "Pixel&s quadrados (manter proporção)", IDM_VID_FS_KEEPRATIO - MENUITEM "&Redimensionamento com valores inteiros", IDM_VID_FS_INT + MENUITEM "&Redimensionamento com valores inteiros", IDM_VID_FS_INT END POPUP "Configurações E&GA/(S)VGA" BEGIN - MENUITEM "Monitor VGA &invertido", IDM_VID_INVERT + MENUITEM "Monitor VGA &invertido", IDM_VID_INVERT POPUP "&Tipo de tela VGA" BEGIN - MENUITEM "&Cor RGB", IDM_VID_GRAY_RGB - MENUITEM "Tons de cinza &RGB", IDM_VID_GRAY_MONO - MENUITEM "Monitor &âmbar", IDM_VID_GRAY_AMBER - MENUITEM "Monitor &verde", IDM_VID_GRAY_GREEN - MENUITEM "Monitor &branco", IDM_VID_GRAY_WHITE + MENUITEM "&Cores RGB", IDM_VID_GRAY_RGB + MENUITEM "Tons de cinza &RGB", IDM_VID_GRAY_MONO + MENUITEM "Monitor &âmbar", IDM_VID_GRAY_AMBER + MENUITEM "Monitor &verde", IDM_VID_GRAY_GREEN + MENUITEM "Monitor &branco", IDM_VID_GRAY_WHITE END POPUP "Tipo de &conversão de tons de cinza" BEGIN - MENUITEM "BT&601 (NTSC/PAL)", IDM_VID_GRAYCT_601 - MENUITEM "BT&709 (HDTV)", IDM_VID_GRAYCT_709 - MENUITEM "&Média", IDM_VID_GRAYCT_AVE + MENUITEM "BT&601 (NTSC/PAL)", IDM_VID_GRAYCT_601 + MENUITEM "BT&709 (HDTV)", IDM_VID_GRAYCT_709 + MENUITEM "&Média", IDM_VID_GRAYCT_AVE END END MENUITEM SEPARATOR - MENUITEM "Overscan do CGA/PCjr/Tandy/E&GA/(S)VGA", IDM_VID_OVERSCAN + MENUITEM "Overscan do CGA/PCjr/Tandy/E&GA/(S)VGA", IDM_VID_OVERSCAN MENUITEM "Alterar contraste para exibição &monocromática", IDM_VID_CGACON END - MENUITEM "&Mídia", IDM_MEDIA + MENUITEM "&Mídia", IDM_MEDIA POPUP "&Ferramentas" BEGIN - MENUITEM "&Configurações...", IDM_CONFIG - MENUITEM "&Atualizar ícones da barra de status", IDM_UPDATE_ICONS + MENUITEM "&Configurações...", IDM_CONFIG + MENUITEM "&Atualizar ícones da barra de status", IDM_UPDATE_ICONS MENUITEM SEPARATOR - MENUITEM "Capturar &tela\tCtrl+F11", IDM_ACTION_SCREENSHOT + MENUITEM "Capturar &tela\tCtrl+F11", IDM_ACTION_SCREENSHOT MENUITEM SEPARATOR - MENUITEM "&Preferências...", IDM_PREFERENCES + MENUITEM "&Preferências...", IDM_PREFERENCES +#ifdef DISCORD MENUITEM "Ativar integração com o &Discord", IDM_DISCORD +#endif MENUITEM SEPARATOR - MENUITEM "&Ganho de som...", IDM_SND_GAIN + MENUITEM "&Ganho de som...", IDM_SND_GAIN #ifdef MTR_ENABLED MENUITEM SEPARATOR - MENUITEM "Inicio do rastreamento\tCtrl+T", IDM_ACTION_BEGIN_TRACE - MENUITEM "Fim do rastreamento\tCtrl+T", IDM_ACTION_END_TRACE + MENUITEM "Inicio do rastreamento\tCtrl+T", IDM_ACTION_BEGIN_TRACE + MENUITEM "Fim do rastreamento\tCtrl+T", IDM_ACTION_END_TRACE #endif END POPUP "&Ajuda" BEGIN - MENUITEM "&Documentação...", IDM_DOCS - MENUITEM "&Sobre o 86Box...", IDM_ABOUT + MENUITEM "&Documentação...", IDM_DOCS + MENUITEM "&Sobre o 86Box...", IDM_ABOUT END END -StatusBarMenu MENU DISCARDABLE +StatusBarMenu MENU DISCARDABLE BEGIN MENUITEM SEPARATOR END @@ -131,17 +140,17 @@ CassetteSubmenu MENU DISCARDABLE BEGIN POPUP "" BEGIN - MENUITEM "&Nova imagem...", IDM_CASSETTE_IMAGE_NEW + MENUITEM "&Nova imagem...", IDM_CASSETTE_IMAGE_NEW MENUITEM SEPARATOR - MENUITEM "&Imagem existente...", IDM_CASSETTE_IMAGE_EXISTING - MENUITEM "Imagem existente (&protegida contra escrita)...", IDM_CASSETTE_IMAGE_EXISTING_WP + MENUITEM "&Imagem existente...", IDM_CASSETTE_IMAGE_EXISTING + MENUITEM "Imagem existente (&protegida contra escrita)...", IDM_CASSETTE_IMAGE_EXISTING_WP MENUITEM SEPARATOR - MENUITEM "&Gravar", IDM_CASSETTE_RECORD - MENUITEM "&Reproduzir", IDM_CASSETTE_PLAY - MENUITEM "&Rebobinar até o começo", IDM_CASSETTE_REWIND - MENUITEM "&Avançar até o fim", IDM_CASSETTE_FAST_FORWARD + MENUITEM "&Gravar", IDM_CASSETTE_RECORD + MENUITEM "&Reproduzir", IDM_CASSETTE_PLAY + MENUITEM "&Rebobinar até o começo", IDM_CASSETTE_REWIND + MENUITEM "&Avançar até o fim", IDM_CASSETTE_FAST_FORWARD MENUITEM SEPARATOR - MENUITEM "E&jetar", IDM_CASSETTE_EJECT + MENUITEM "E&jetar", IDM_CASSETTE_EJECT END END @@ -149,9 +158,9 @@ CartridgeSubmenu MENU DISCARDABLE BEGIN POPUP "" BEGIN - MENUITEM "&Imagem...", IDM_CARTRIDGE_IMAGE + MENUITEM "&Imagem...", IDM_CARTRIDGE_IMAGE MENUITEM SEPARATOR - MENUITEM "E&jetar", IDM_CARTRIDGE_EJECT + MENUITEM "E&jetar", IDM_CARTRIDGE_EJECT END END @@ -159,14 +168,14 @@ FloppySubmenu MENU DISCARDABLE BEGIN POPUP "" BEGIN - MENUITEM "&Nova imagem...", IDM_FLOPPY_IMAGE_NEW + MENUITEM "&Nova imagem...", IDM_FLOPPY_IMAGE_NEW MENUITEM SEPARATOR - MENUITEM "&Imagem existente...", IDM_FLOPPY_IMAGE_EXISTING - MENUITEM "Imagem existente (&protegida contra escrita)...", IDM_FLOPPY_IMAGE_EXISTING_WP + MENUITEM "&Imagem existente...", IDM_FLOPPY_IMAGE_EXISTING + MENUITEM "Imagem existente (&protegida contra escrita)...", IDM_FLOPPY_IMAGE_EXISTING_WP MENUITEM SEPARATOR - MENUITEM "E&xportar para 86F...", IDM_FLOPPY_EXPORT_TO_86F + MENUITEM "E&xportar para 86F...", IDM_FLOPPY_EXPORT_TO_86F MENUITEM SEPARATOR - MENUITEM "E&jetar", IDM_FLOPPY_EJECT + MENUITEM "E&jetar", IDM_FLOPPY_EJECT END END @@ -174,12 +183,13 @@ CdromSubmenu MENU DISCARDABLE BEGIN POPUP "" BEGIN - MENUITEM "&Sem som", IDM_CDROM_MUTE + MENUITEM "&Sem som", IDM_CDROM_MUTE MENUITEM SEPARATOR - MENUITEM "&Vazio", IDM_CDROM_EMPTY - MENUITEM "&Recarregar imagem anterior", IDM_CDROM_RELOAD + MENUITEM "&Vazio", IDM_CDROM_EMPTY + MENUITEM "&Recarregar imagem anterior", IDM_CDROM_RELOAD MENUITEM SEPARATOR - MENUITEM "&Imagem", IDM_CDROM_IMAGE + MENUITEM "&Imagem...", IDM_CDROM_IMAGE + MENUITEM "&Pasta...", IDM_CDROM_DIR END END @@ -187,13 +197,13 @@ ZIPSubmenu MENU DISCARDABLE BEGIN POPUP "" BEGIN - MENUITEM "&Nova imagem...", IDM_ZIP_IMAGE_NEW + MENUITEM "&Nova imagem...", IDM_ZIP_IMAGE_NEW MENUITEM SEPARATOR - MENUITEM "&Imagem existente...", IDM_ZIP_IMAGE_EXISTING - MENUITEM "Imagem existente (&protegida contra escrita)...", IDM_ZIP_IMAGE_EXISTING_WP + MENUITEM "&Imagem existente...", IDM_ZIP_IMAGE_EXISTING + MENUITEM "Imagem existente (&protegida contra escrita)...", IDM_ZIP_IMAGE_EXISTING_WP MENUITEM SEPARATOR - MENUITEM "E&jetar", IDM_ZIP_EJECT - MENUITEM "&Recarregar imagem anterior", IDM_ZIP_RELOAD + MENUITEM "E&jetar", IDM_ZIP_EJECT + MENUITEM "&Recarregar imagem anterior", IDM_ZIP_RELOAD END END @@ -201,13 +211,13 @@ MOSubmenu MENU DISCARDABLE BEGIN POPUP "" BEGIN - MENUITEM "&Nova imagem...", IDM_MO_IMAGE_NEW + MENUITEM "&Nova imagem...", IDM_MO_IMAGE_NEW MENUITEM SEPARATOR - MENUITEM "&Imagem existente...", IDM_MO_IMAGE_EXISTING - MENUITEM "Imagem existente (&protegida contra escrita)...", IDM_MO_IMAGE_EXISTING_WP + MENUITEM "&Imagem existente...", IDM_MO_IMAGE_EXISTING + MENUITEM "Imagem existente (&protegida contra escrita)...", IDM_MO_IMAGE_EXISTING_WP MENUITEM SEPARATOR - MENUITEM "E&jetar", IDM_MO_EJECT - MENUITEM "&Recarregar imagem anterior", IDM_MO_RELOAD + MENUITEM "E&jetar", IDM_MO_EJECT + MENUITEM "&Recarregar imagem anterior", IDM_MO_RELOAD END END @@ -233,134 +243,150 @@ END // Dialog // -#define STR_PREFERENCES "Preferências" -#define STR_SND_GAIN "Ganho de som" -#define STR_NEW_FLOPPY "Nova imagem de disquete" -#define STR_CONFIG "Configurações" -#define STR_SPECIFY_DIM "Especifique as dimensões da janela principal" +#define STR_PREFERENCES "Preferências" +#define STR_SND_GAIN "Ganho de som" +#define STR_NEW_FLOPPY "Nova imagem de disquete" +#define STR_CONFIG "Configurações" +#define STR_SPECIFY_DIM "Especifique as dimensões da janela principal" -#define STR_OK "OK" -#define STR_CANCEL "Cancelar" -#define STR_GLOBAL "Usar estas configurações como &padrões globais" -#define STR_DEFAULT "&Padrão" -#define STR_LANGUAGE "Idioma:" -#define STR_ICONSET "Pacote de ícones:" +#define STR_OK "OK" +#define STR_CANCEL "Cancelar" +#define STR_GLOBAL "Usar estas configurações como &padrões globais" +#define STR_DEFAULT "&Padrão" +#define STR_LANGUAGE "Idioma:" +#define STR_ICONSET "Pacote de ícones:" -#define STR_GAIN "Ganho" +#define STR_GAIN "Ganho" -#define STR_FILE_NAME "Nome:" -#define STR_DISK_SIZE "Tamanho:" -#define STR_RPM_MODE "Modo RPM:" -#define STR_PROGRESS "Progresso:" +#define STR_FILE_NAME "Nome:" +#define STR_DISK_SIZE "Tamanho:" +#define STR_RPM_MODE "Modo RPM:" +#define STR_PROGRESS "Progresso:" -#define STR_WIDTH "Largura:" -#define STR_HEIGHT "Altura:" -#define STR_LOCK_TO_SIZE "Travar nesse tamanho" +#define STR_WIDTH "Largura:" +#define STR_HEIGHT "Altura:" +#define STR_LOCK_TO_SIZE "Travar nesse tamanho" -#define STR_MACHINE_TYPE "Tipo de máquina:" -#define STR_MACHINE "Máquina:" -#define STR_CONFIGURE "Configurar" -#define STR_CPU_TYPE "Tipo de CPU:" -#define STR_CPU_SPEED "Veloc.:" -#define STR_FPU "FPU:" -#define STR_WAIT_STATES "Estados de espera:" -#define STR_MB "MB" -#define STR_MEMORY "Memória:" -#define STR_TIME_SYNC "Sincronização da hora" -#define STR_DISABLED "Desativada" -#define STR_ENABLED_LOCAL "Ativada (hora local)" -#define STR_ENABLED_UTC "Ativada (UTC)" -#define STR_DYNAREC "Recompilador dinâmico" +#define STR_MACHINE_TYPE "Tipo de máquina:" +#define STR_MACHINE "Máquina:" +#define STR_CONFIGURE "Configurar" +#define STR_CPU_TYPE "Tipo de CPU:" +#define STR_CPU_SPEED "Veloc.:" +#define STR_FPU "FPU:" +#define STR_WAIT_STATES "Estados de espera:" +#define STR_MB "MB" +#define STR_MEMORY "Memória:" +#define STR_TIME_SYNC "Sincronização da hora" +#define STR_DISABLED "Desativar" +#define STR_ENABLED_LOCAL "Ativar (hora local)" +#define STR_ENABLED_UTC "Ativar (UTC)" +#define STR_DYNAREC "Recompilador dinâmico" +#define STR_SOFTFLOAT "Softfloat FPU" -#define STR_VIDEO "Vídeo:" -#define STR_VOODOO "3DFX Voodoo" +#define STR_VIDEO "Vídeo:" +#define STR_VIDEO_2 "Vídeo 2:" +#define STR_VOODOO "3DFX Voodoo" +#define STR_IBM8514 "Gráficos IBM 8514/a" +#define STR_XGA "Gráficos XGA" -#define STR_MOUSE "Mouse:" -#define STR_JOYSTICK "Joystick:" -#define STR_JOY1 "Joystick 1..." -#define STR_JOY2 "Joystick 2..." -#define STR_JOY3 "Joystick 3..." -#define STR_JOY4 "Joystick 4..." +#define STR_MOUSE "Mouse:" +#define STR_JOYSTICK "Joystick:" +#define STR_JOY1 "Joystick 1..." +#define STR_JOY2 "Joystick 2..." +#define STR_JOY3 "Joystick 3..." +#define STR_JOY4 "Joystick 4..." -#define STR_SOUND "Placa de som:" -#define STR_MIDI_OUT "Disp. saída MIDI:" -#define STR_MIDI_IN "Disp. entrada MIDI:" -#define STR_MPU401 "MPU-401 autônomo" -#define STR_SSI "Innovation SSI-2001" -#define STR_CMS "CMS / Game Blaster" -#define STR_GUS "Gravis Ultrasound" -#define STR_FLOAT "Usar som FLOAT32" +#define STR_SOUND1 "Placa de som 1:" +#define STR_SOUND2 "Placa de som 2:" +#define STR_SOUND3 "Placa de som 3:" +#define STR_SOUND4 "Placa de som 4:" +#define STR_MIDI_OUT "Disp. saída MIDI:" +#define STR_MIDI_IN "Disp. entrada MIDI:" +#define STR_MPU401 "MPU-401 autônomo" +#define STR_FLOAT "Usar som FLOAT32" +#define STR_FM_DRIVER "Controlador de sint. FM" +#define STR_FM_DRV_NUKED "Nuked (mais preciso)" +#define STR_FM_DRV_YMFM "YMFM (mais rápido)" -#define STR_NET_TYPE "Tipo de rede:" -#define STR_PCAP "Dispositivo PCap:" -#define STR_NET "Adaptador de rede:" +#define STR_NET_TYPE "Tipo de rede:" +#define STR_PCAP "Dispositivo PCap:" +#define STR_NET "Adaptador de rede:" +#define STR_NET1 "Placa de rede 1:" +#define STR_NET2 "Placa de rede 2:" +#define STR_NET3 "Placa de rede 3:" +#define STR_NET4 "Placa de rede 4:" -#define STR_COM1 "Dispositivo COM1:" -#define STR_COM2 "Dispositivo COM2:" -#define STR_COM3 "Dispositivo COM3:" -#define STR_COM4 "Dispositivo COM4:" -#define STR_LPT1 "Dispositivo LPT1:" -#define STR_LPT2 "Dispositivo LPT2:" -#define STR_LPT3 "Dispositivo LPT3:" -#define STR_LPT4 "Dispositivo LPT4:" -#define STR_SERIAL1 "Porta serial 1" -#define STR_SERIAL2 "Porta serial 2" -#define STR_SERIAL3 "Porta serial 3" -#define STR_SERIAL4 "Porta serial 4" -#define STR_PARALLEL1 "Porta paralela 1" -#define STR_PARALLEL2 "Porta paralela 2" -#define STR_PARALLEL3 "Porta paralela 3" -#define STR_PARALLEL4 "Porta paralela 4" +#define STR_COM1 "Dispositivo COM1:" +#define STR_COM2 "Dispositivo COM2:" +#define STR_COM3 "Dispositivo COM3:" +#define STR_COM4 "Dispositivo COM4:" +#define STR_LPT1 "Dispositivo LPT1:" +#define STR_LPT2 "Dispositivo LPT2:" +#define STR_LPT3 "Dispositivo LPT3:" +#define STR_LPT4 "Dispositivo LPT4:" +#define STR_SERIAL1 "Porta serial 1" +#define STR_SERIAL2 "Porta serial 2" +#define STR_SERIAL3 "Porta serial 3" +#define STR_SERIAL4 "Porta serial 4" +#define STR_PARALLEL1 "Porta paralela 1" +#define STR_PARALLEL2 "Porta paralela 2" +#define STR_PARALLEL3 "Porta paralela 3" +#define STR_PARALLEL4 "Porta paralela 4" +#define STR_SERIAL_PASS1 "Encaminhamento de porta serial 1" +#define STR_SERIAL_PASS2 "Encaminhamento de porta serial 2" +#define STR_SERIAL_PASS3 "Encaminhamento de porta serial 3" +#define STR_SERIAL_PASS4 "Encaminhamento de porta serial 4" -#define STR_HDC "Controlador HD:" -#define STR_FDC "Controlador FD:" -#define STR_IDE_TER "Controlador IDE terciário" -#define STR_IDE_QUA "Controlador IDE quaternário" -#define STR_SCSI "SCSI" -#define STR_SCSI_1 "Controlador 1:" -#define STR_SCSI_2 "Controlador 2:" -#define STR_SCSI_3 "Controlador 3:" -#define STR_SCSI_4 "Controlador 4:" -#define STR_CASSETTE "Cassete" +#define STR_HDC "Controlador HD:" +#define STR_FDC "Controlador FD:" +#define STR_IDE_TER "Controlador IDE terciário" +#define STR_IDE_QUA "Controlador IDE quaternário" +#define STR_SCSI "SCSI" +#define STR_SCSI_1 "Controlador 1:" +#define STR_SCSI_2 "Controlador 2:" +#define STR_SCSI_3 "Controlador 3:" +#define STR_SCSI_4 "Controlador 4:" +#define STR_CASSETTE "Cassete" -#define STR_HDD "Discos rígidos:" -#define STR_NEW "&Novo..." -#define STR_EXISTING "&Existente..." -#define STR_REMOVE "&Remover" -#define STR_BUS "Bar.:" -#define STR_CHANNEL "Canal:" -#define STR_ID "ID:" +#define STR_HDD "Discos rígidos:" +#define STR_NEW "&Novo..." +#define STR_EXISTING "&Existente..." +#define STR_REMOVE "&Remover" +#define STR_BUS "Bar.:" +#define STR_CHANNEL "Canal:" +#define STR_ID "ID:" +#define STR_SPEED "Velocidade:" -#define STR_SPECIFY "&Especificar..." -#define STR_SECTORS "Setores:" -#define STR_HEADS "Cabeças:" -#define STR_CYLS "Cilindros:" -#define STR_SIZE_MB "Tamanho (MB):" -#define STR_TYPE "Tipo:" -#define STR_IMG_FORMAT "Formato:" -#define STR_BLOCK_SIZE "Bloco:" +#define STR_SPECIFY "&Especificar..." +#define STR_SECTORS "Setores:" +#define STR_HEADS "Cabeças:" +#define STR_CYLS "Cilindros:" +#define STR_SIZE_MB "Tamanho (MB):" +#define STR_TYPE "Tipo:" +#define STR_IMG_FORMAT "Formato:" +#define STR_BLOCK_SIZE "Blocos:" -#define STR_FLOPPY_DRIVES "Unidades de disquete:" -#define STR_TURBO "Turbo" -#define STR_CHECKBPB "Verificar BPB" -#define STR_CDROM_DRIVES "Unidades de CD-ROM:" -#define STR_CD_SPEED "Veloc.:" +#define STR_FLOPPY_DRIVES "Unidades de disquete:" +#define STR_TURBO "Turbo" +#define STR_CHECKBPB "Verificar BPB" +#define STR_CDROM_DRIVES "Unidades de CD-ROM:" +#define STR_CD_SPEED "Veloc.:" -#define STR_MO_DRIVES "Unidades magneto-ópticas:" -#define STR_ZIP_DRIVES "Unidades ZIP:" -#define STR_250 "ZIP 250" +#define STR_MO_DRIVES "Unidades magneto-ópticas:" +#define STR_ZIP_DRIVES "Unidades ZIP:" +#define STR_250 "ZIP 250" -#define STR_ISARTC "RTC ISA:" -#define STR_ISAMEM "Expansão de memória ISA" -#define STR_ISAMEM_1 "Placa 1:" -#define STR_ISAMEM_2 "Placa 2:" -#define STR_ISAMEM_3 "Placa 3:" -#define STR_ISAMEM_4 "Placa 4:" -#define STR_BUGGER "Dispositivo ISABugger" -#define STR_POSTCARD "Placa de diagnóstico" +#define STR_ISARTC "RTC ISA:" +#define STR_ISAMEM "Expansão de memória ISA" +#define STR_ISAMEM_1 "Placa 1:" +#define STR_ISAMEM_2 "Placa 2:" +#define STR_ISAMEM_3 "Placa 3:" +#define STR_ISAMEM_4 "Placa 4:" +#define STR_BUGGER "Dispositivo ISABugger" +#define STR_POSTCARD "Placa de diagnóstico" -#define FONT_SIZE 9 -#define FONT_NAME "Segoe UI" +#define FONT_SIZE 9 +#define FONT_NAME "Segoe UI" #include "dialogs.rc" @@ -369,194 +395,188 @@ END // String Table // -STRINGTABLE DISCARDABLE +STRINGTABLE DISCARDABLE BEGIN - 2048 "86Box" - IDS_2049 "Erro" - IDS_2050 "Erro fatal" - IDS_2051 " - PAUSED" - IDS_2052 "Use Ctrl+Alt+PgDn para retornar ao modo janela" - IDS_2053 "Velocidade" - IDS_2054 "ZIP %03i %i (%s): %ls" - IDS_2055 "Imagens ZIP (*.IM?;*.ZDI)\0*.IM?;*.ZDI\0" - IDS_2056 "O 86Box não conseguiu encontrar nenhuma imagem de ROM utilizável.\n\nPor favor, baixe um conjunto de ROM e extraia no diretório ""roms""." - IDS_2057 "(vazio)" - IDS_2058 "Imagens ZIP (*.IM?;*.ZDI)\0*.IM?;*.ZDI\0Todos os arquivos (*.*)\0*.*\0" - IDS_2059 "Turbo" - IDS_2060 "Lig." - IDS_2061 "Desl." - IDS_2062 "Todas as imagens (*.86F;*.DSK;*.FLP;*.IM?;*.*FD?)\0*.86F;*.DSK;*.FLP;*.IM?;*.*FD?\0Imagens de setor básico (*.DSK;*.FLP;*.IM?;*.*FD?)\0*.DSK;*.FLP;*.IM?;*.IMG;*.*FD?\0Imagens de superfície (*.86F)\0*.86F\0" - IDS_2063 "A máquina ""%hs"" não está disponível devido à falta de ROMs no diretório roms/machines. Mudando para uma máquina disponível." + 2048 "86Box" + IDS_2049 "Erro" + IDS_2050 "Erro fatal" + IDS_2051 " - PAUSADO" + IDS_2052 "Use Ctrl+Alt+PgDn para retornar ao modo janela" + IDS_2053 "Velocidade" + IDS_2054 "ZIP %03i %i (%s): %ls" + IDS_2055 "Imagens ZIP (*.IM?;*.ZDI)\0*.IM?;*.ZDI\0" + IDS_2056 "O 86Box não conseguiu encontrar nenhuma imagem de ROM utilizável.\n\nPor favor, baixe um conjunto de ROM e extraia no diretório ""roms""." + IDS_2057 "(vazio)" + IDS_2058 "Imagens ZIP (*.IM?;*.ZDI)\0*.IM?;*.ZDI\0Todos os arquivos (*.*)\0*.*\0" + IDS_2059 "Turbo" + IDS_2060 "Lig." + IDS_2061 "Desl." + IDS_2062 "Todas as imagens (*.86F;*.DSK;*.FLP;*.IM?;*.*FD?)\0*.86F;*.DSK;*.FLP;*.IM?;*.*FD?\0Imagens de setor básico (*.DSK;*.FLP;*.IM?;*.*FD?)\0*.DSK;*.FLP;*.IM?;*.IMG;*.*FD?\0Imagens de superfície (*.86F)\0*.86F\0" + IDS_2063 "A máquina ""%hs"" não está disponível devido à falta de ROMs no diretório roms/machines. Mudando para uma máquina disponível." END -STRINGTABLE DISCARDABLE +STRINGTABLE DISCARDABLE BEGIN - IDS_2064 "A placa de vídeo ""%hs"" não está disponível devido à falta de ROMs no diretório roms/video. Mudando para uma placa de vídeo disponível." - IDS_2065 "Máquina" - IDS_2066 "Vídeo" - IDS_2067 "Dispositivos de entrada" - IDS_2068 "Som" - IDS_2069 "Rede" - IDS_2070 "Portas (COM & LPT)" - IDS_2071 "Controladores de armaz." - IDS_2072 "Discos rígidos" - IDS_2073 "Disquete & CD-ROM" - IDS_2074 "Dispos. removíveis" - IDS_2075 "Outros periféricos" - IDS_2076 "Imagens de superfície (*.86F)\0*.86F\0" - IDS_2077 "Clique para capturar o mouse" - IDS_2078 "Aperte F8+F12 para liberar o mouse" - IDS_2079 "Aperte F8+F12 ou botão do meio para liberar o mouse" + IDS_2064 "A placa de vídeo ""%hs"" não está disponível devido à falta de ROMs no diretório roms/video. Mudando para uma placa de vídeo disponível." + IDS_2065 "Máquina" + IDS_2066 "Vídeo" + IDS_2067 "Dispositivos de entrada" + IDS_2068 "Som" + IDS_2069 "Rede" + IDS_2070 "Portas (COM & LPT)" + IDS_2071 "Controladores de armaz." + IDS_2072 "Discos rígidos" + IDS_2073 "Disquete & CD-ROM" + IDS_2074 "Dispos. removíveis" + IDS_2075 "Outros periféricos" + IDS_2076 "Imagens de superfície (*.86F)\0*.86F\0" + IDS_2077 "Clique para capturar o mouse" + IDS_2078 "Aperte F8+F12 para liberar o mouse" + IDS_2079 "Aperte F8+F12 ou botão do meio para liberar o mouse" END -STRINGTABLE DISCARDABLE +STRINGTABLE DISCARDABLE BEGIN - IDS_2080 "Não foi possível inicializar o FluidSynth" - IDS_2081 "Barramento" - IDS_2082 "Arquivo" - IDS_2083 "CI" - IDS_2084 "CA" - IDS_2085 "SE" - IDS_2086 "MB" - IDS_2087 "Verificar BPB" - IDS_2088 "KB" - IDS_2089 "Não foi possível inicializar o renderizador de vídeo." - IDS_2090 "Padrão" - IDS_2091 "%i estado(s) de espera" - IDS_2092 "Tipo" - IDS_2093 "Não foi possível configurar o PCap" - IDS_2094 "Nenhum dispositivo PCap encontrado" - IDS_2095 "Dispositivo PCap inválido" - IDS_2096 "Joystick padrão de 2 botões" - IDS_2097 "Joystick padrão de 4 botões" - IDS_2098 "Joystick padrão de 6 botões" - IDS_2099 "Joystick padrão de 8 botões" - IDS_2100 "CH Flightstick Pro" - IDS_2101 "Microsoft SideWinder Pad" - IDS_2102 "Thrustmaster Flight Control System" - IDS_2103 "Nada" - IDS_2104 "Não foi possível carregar os aceleradores do teclado." - IDS_2105 "Não foi possível registrar a entrada bruta." - IDS_2106 "%u" - IDS_2107 "%u MB (CHS: %i, %i, %i)" - IDS_2108 "Disquete %i (%s): %ls" - IDS_2109 "Todas as imagens (*.0??;*.1??;*.??0;*.86F;*.BIN;*.CQ?;*.D??;*.FLP;*.HDM;*.IM?;*.JSON;*.TD0;*.*FD?;*.MFM;*.XDF)\0*.0??;*.1??;*.??0;*.86F;*.BIN;*.CQ?;*.D??;*.FLP;*.HDM;*.IM?;*.JSON;*.TD0;*.*FD?;*.MFM;*.XDF\0Imagens de setor avançado (*.IMD;*.JSON;*.TD0)\0*.IMD;*.JSON;*.TD0\0Imagens de setor básico (*.0??;*.1??;*.??0;*.BIN;*.CQ?;*.D??;*.FLP;*.HDM;*.IM?;*.XDF;*.*FD?)\0*.0??;*.1??;*.??0;*.BIN;*.CQ?;*.D??;*.FLP;*.HDM;*.IM?;*.XDF;*.*FD?\0Imagens de fluxo (*.FDI)\0*.FDI\0Imagens de superfície (*.86F;*.MFM)\0*.86F;*.MFM\0Todos os arquivos (*.*)\0*.*\0" - IDS_2110 "Não foi possível inicializar o FreeType" - IDS_2111 "Não é possível inicializar o SDL, é necessário o SDL2.dll" - IDS_2112 "Tem certeza de que deseja reiniciar completamente a máquina emulada?" - IDS_2113 "Tem certeza de que deseja sair do 86Box?" - IDS_2114 "Não é possível inicializar o Ghostscript" - IDS_2115 "Magneto-óptico %i (%ls): %ls" - IDS_2116 "Imagens magneto-ópticas (*.IM?;*.MDI)\0*.IM?;*.MDI\0Todos os arquivos (*.*)\0*.*\0" - IDS_2117 "Bem-vindo ao 86Box!" - IDS_2118 "Controlador interno" - IDS_2119 "Sair" - IDS_2120 "Nenhum ROM encontrada" - IDS_2121 "Você deseja salvar as configurações?" - IDS_2122 "Isto fará com que a máquina emulada seja reinicializada." - IDS_2123 "Salvar" - IDS_2124 "Sobre o 86Box" - IDS_2125 "86Box versão" EMU_VERSION + IDS_2081 "Barramento" + IDS_2082 "Arquivo" + IDS_2083 "CI" + IDS_2084 "CA" + IDS_2085 "SE" + IDS_2086 "MB" + IDS_2087 "Velocidade" + IDS_2088 "Verificar BPB" + IDS_2089 "KB" + IDS_2090 "Não foi possível inicializar o renderizador de vídeo." + IDS_2091 "Padrão" + IDS_2092 "%i estado(s) de espera" + IDS_2093 "Tipo" + IDS_2094 "Não foi possível configurar o PCap" + IDS_2095 "Nenhum dispositivo PCap encontrado" + IDS_2096 "Dispositivo PCap inválido" + IDS_2097 "Joystick padrão de 2 botões" + IDS_2098 "Joystick padrão de 4 botões" + IDS_2099 "Joystick padrão de 6 botões" + IDS_2100 "Joystick padrão de 8 botões" + IDS_2101 "CH Flightstick Pro" + IDS_2102 "Microsoft SideWinder Pad" + IDS_2103 "Sistema de Controle de Voo Thrustmaster" + IDS_2104 "Nada" + IDS_2105 "Não foi possível carregar os aceleradores do teclado." + IDS_2106 "Não foi possível registrar a entrada bruta." + IDS_2107 "%u" + IDS_2108 "%u MB (CHS: %i, %i, %i)" + IDS_2109 "Disquete %i (%s): %ls" + IDS_2110 "Todas as imagens (*.0??;*.1??;*.??0;*.86F;*.BIN;*.CQ?;*.D??;*.FLP;*.HDM;*.IM?;*.JSON;*.TD0;*.*FD?;*.MFM;*.XDF)\0*.0??;*.1??;*.??0;*.86F;*.BIN;*.CQ?;*.D??;*.FLP;*.HDM;*.IM?;*.JSON;*.TD0;*.*FD?;*.MFM;*.XDF\0Imagens de setor avançado (*.IMD;*.JSON;*.TD0)\0*.IMD;*.JSON;*.TD0\0Imagens de setor básico (*.0??;*.1??;*.??0;*.BIN;*.CQ?;*.D??;*.FLP;*.HDM;*.IM?;*.XDF;*.*FD?)\0*.0??;*.1??;*.??0;*.BIN;*.CQ?;*.D??;*.FLP;*.HDM;*.IM?;*.XDF;*.*FD?\0Imagens de fluxo (*.FDI)\0*.FDI\0Imagens de superfície (*.86F;*.MFM)\0*.86F;*.MFM\0Todos os arquivos (*.*)\0*.*\0" + IDS_2112 "Não é possível inicializar o SDL, é necessário o SDL2.dll" + IDS_2113 "Tem certeza de que deseja reiniciar completamente a máquina emulada?" + IDS_2114 "Tem certeza de que deseja sair do 86Box?" + IDS_2115 "Não é possível inicializar o Ghostscript" + IDS_2116 "Magneto-óptico %i (%ls): %ls" + IDS_2117 "Imagens magneto-ópticas (*.IM?;*.MDI)\0*.IM?;*.MDI\0Todos os arquivos (*.*)\0*.*\0" + IDS_2118 "Bem-vindo ao 86Box!" + IDS_2119 "Controlador interno" + IDS_2120 "Sair" + IDS_2121 "Nenhum ROM encontrada" + IDS_2122 "Você deseja salvar as configurações?" + IDS_2123 "Isto fará com que a máquina emulada seja reinicializada." + IDS_2124 "Salvar" + IDS_2125 "Sobre o 86Box" + IDS_2126 "86Box versão" EMU_VERSION - IDS_2126 "Um emulador de computadores antigos\n\nAutores: Sarah Walker, Miran Grca, Fred N. van Kempen (waltje), SA1988, Tiseno100, reenigne, leilei, JohnElliott, greatpsycho, e outros.\n\nTraduzido por: Altieres Lima da Silva\n\nLançado sob a Licença Pública Geral GNU versão 2 ou posterior. Veja o arquivo LICENSE para mais informações." - IDS_2127 "OK" - IDS_2128 "Hardware não disponível" + IDS_2127 "Um emulador de computadores antigos\n\nAutores: Miran GrÄa (OBattler), RichardG867, Jasmine Iwanek, TC1995, coldbrewed, Teemu Korhonen (Manaatti), Joakim L. Gilje, Adrien Moulin (elyosh), Daniel Balsom (gloriouscow), Cacodemon345, Fred N. van Kempen (waltje), Tiseno100, reenigne, e outros.\n\nWith previous core contributions from Sarah Walker, leilei, JohnElliott, greatpsycho, e outros.\n\nTraduzido por: Altieres Lima da Silva\n\nLançado sob a Licença Pública Geral GNU versão 2 ou posterior. Veja o arquivo LICENSE para mais informações." + IDS_2128 "OK" + IDS_2129 "Hardware não disponível" #ifdef _WIN32 #define LIB_NAME_PCAP "WinPcap" #else #define LIB_NAME_PCAP "libpcap" #endif - IDS_2129 "Certifique-se de que " LIB_NAME_PCAP " esteja instalado e que você tenha uma conexão de rede compatível com " LIB_NAME_PCAP "." - IDS_2130 "Configuração inválida" -#ifdef _WIN32 -#define LIB_NAME_FREETYPE "freetype.dll" -#else -#define LIB_NAME_FREETYPE "libfreetype" -#endif - IDS_2131 LIB_NAME_FREETYPE " é necessário para emulação de impressora ESC/P." + IDS_2130 "Certifique-se de que " LIB_NAME_PCAP " esteja instalado e que você tenha uma conexão de rede compatível com " LIB_NAME_PCAP "." + IDS_2131 "Configuração inválida" #ifdef _WIN32 #define LIB_NAME_GS "gsdll32.dll" #else #define LIB_NAME_GS "libgs" #endif - IDS_2132 LIB_NAME_GS " é necessário para a conversão automática de arquivos PostScript para PDF.\n\nQualquer documento enviado para a impressora genérica PostScript será salvo como arquivos PostScript (.ps)." -#ifdef _WIN32 -#define LIB_NAME_FLUIDSYNTH "libfluidsynth.dll" -#else -#define LIB_NAME_FLUIDSYNTH "libfluidsynth" -#endif - IDS_2133 LIB_NAME_FLUIDSYNTH " é necessário para a saída MIDI FluidSynth." - IDS_2134 "Entrando no modo de tela cheia" - IDS_2135 "Não exibir esta mensagem novamente" - IDS_2136 "Não sair" - IDS_2137 "Reiniciar" - IDS_2138 "Não reiniciar" - IDS_2139 "Imagens magneto-ópticas (*.IM?;*.MDI)\0*.IM?;*.MDI\0Todos os arquivos (*.*)\0*.*\0" - IDS_2140 "Imagens de CD-ROM (*.ISO;*.CUE)\0*.ISO;*.CUE\0Todos os arquivos (*.*)\0*.*\0" - IDS_2141 "Configuração do dispositivo %hs" - IDS_2142 "Monitor em modo de suspensão" - IDS_2143 "Shaders OpenGL (*.GLSL)\0*.GLSL\0Todos os arquivos (*.*)\0*.*\0" - IDS_2144 "Opções do OpenGL" - IDS_2145 "Você está carregando uma configuração não suportada" - IDS_2146 "A filtragem do tipo CPU baseada na máquina selecionada é desativada para esta máquina emulada.\n\nIsto torna possível escolher uma CPU que de outra forma seria incompatível com a máquina selecionada. Entretanto, você pode encontrar incompatibilidades com a BIOS da máquina ou outro software.\n\nA ativação desta configuração não é oficialmente suportada e qualquer relatório de erro arquivado pode ser fechado como inválido." - IDS_2147 "Continuar" - IDS_2148 "Cassete: %s" - IDS_2149 "Imagens de cassete (*.PCM;*.RAW;*.WAV;*.CAS)\0*.PCM;*.RAW;*.WAV;*.CAS\0Todos os arquivos (*.*)\0*.*\0" - IDS_2150 "Cartucho %i: %ls" - IDS_2151 "Imagens de cartucho (*.A;*.B;*.JRC)\0*.A;*.B;*.JRC\0Todos os arquivos (*.*)\0*.*\0" - IDS_2152 "Erro ao inicializar o renderizador" - IDS_2153 "O renderizador OpenGL (Núcleo 3.0) não pôde ser inicializado. Use outro renderizador." - IDS_2154 "Continuar a execução" - IDS_2155 "Pausar a execução" - IDS_2156 "Pressionar Ctrl+Alt+Del" - IDS_2157 "Pressionar Ctrl+Alt+Esc" - IDS_2158 "Reinicialização completa" - IDS_2159 "Desligamento por ACPI" - IDS_2160 "Configurações" + IDS_2133 LIB_NAME_GS " é necessário para a conversão automática de arquivos PostScript para PDF.\n\nQualquer documento enviado para a impressora genérica PostScript será salvo como arquivos PostScript (.ps)." + IDS_2135 "Entrando no modo de tela cheia" + IDS_2136 "Não exibir esta mensagem novamente" + IDS_2137 "Não sair" + IDS_2138 "Reiniciar" + IDS_2139 "Não reiniciar" + IDS_2140 "Imagens magneto-ópticas (*.IM?;*.MDI)\0*.IM?;*.MDI\0Todos os arquivos (*.*)\0*.*\0" + IDS_2141 "Imagens de CD-ROM (*.ISO;*.CUE)\0*.ISO;*.CUE\0Todos os arquivos (*.*)\0*.*\0" + IDS_2142 "Configuração do dispositivo %hs" + IDS_2143 "Monitor em modo de suspensão" + IDS_2144 "Shaders OpenGL (*.GLSL)\0*.GLSL\0Todos os arquivos (*.*)\0*.*\0" + IDS_2145 "Opções do OpenGL" + IDS_2146 "Você está carregando uma configuração não suportada" + IDS_2147 "A filtragem do tipo CPU baseada na máquina selecionada é desativada para esta máquina emulada.\n\nIsto torna possível escolher uma CPU que de outra forma seria incompatível com a máquina selecionada. Entretanto, você pode encontrar incompatibilidades com a BIOS da máquina ou outro software.\n\nA ativação desta configuração não é oficialmente suportada e qualquer relatório de erro arquivado pode ser fechado como inválido." + IDS_2148 "Continuar" + IDS_2149 "Cassete: %s" + IDS_2150 "Imagens de cassete (*.PCM;*.RAW;*.WAV;*.CAS)\0*.PCM;*.RAW;*.WAV;*.CAS\0Todos os arquivos (*.*)\0*.*\0" + IDS_2151 "Cartucho %i: %ls" + IDS_2152 "Imagens de cartucho (*.A;*.B;*.JRC)\0*.A;*.B;*.JRC\0Todos os arquivos (*.*)\0*.*\0" + IDS_2153 "Erro ao inicializar o renderizador" + IDS_2154 "O renderizador OpenGL (Núcleo 3.0) não pôde ser inicializado. Use outro renderizador." + IDS_2155 "Continuar a execução" + IDS_2156 "Pausar a execução" + IDS_2157 "Pressionar Ctrl+Alt+Del" + IDS_2158 "Pressionar Ctrl+Alt+Esc" + IDS_2159 "Reinicialização completa" + IDS_2160 "Desligamento por ACPI" + IDS_2161 "Configurações" + IDS_2162 "Tipo" + IDS_2163 "Sem recompilador dinâmico" + IDS_2164 "Recompilador dinâmico antigo" + IDS_2165 "Novo recompilador dinâmico" + IDS_2166 "A placa de vídeo #2 ""%hs"" não está disponível devido à ausência de ROMs no diretório roms/video. Desabilitando a segunda placa de vídeo." + IDS_2167 "Falha ao inicializar o driver de rede" + IDS_2168 "A configuração de rede será alterada para o driver nulo" END -STRINGTABLE DISCARDABLE +STRINGTABLE DISCARDABLE BEGIN IDS_4096 "Disco rígido (%s)" - IDS_4097 "%01i:%01i" - IDS_4098 "%01i" - IDS_4099 "As unidades de CD-ROM MFM/RLL ou ESDI nunca existiram" - IDS_4100 "Personalizado..." - IDS_4101 "Personalizado (grande)..." - IDS_4102 "Adicionar novo disco rígido" - IDS_4103 "Adicionar disco rígido existente" - IDS_4104 "As imagens de disco HDI não podem ser maiores do que 4GB." - IDS_4105 "As imagens de disco não podem ser maiores do que 127GB." - IDS_4106 "Imagens de disco rígido (*.HD?;*.IM?;*.VHD)\0*.HD?;*.IM?;*.VHD\0Todos os arquivos (*.*)\0*.*\0" - IDS_4107 "Não foi possível ler o arquivo" - IDS_4108 "Não foi possível escrever o arquivo" - IDS_4109 "Imagens HDI ou HDX com um tamanho de setor que não seja 512 não são suportadas." - IDS_4110 "O USB ainda não é suportado" - IDS_4111 "Esta imagem existe" - IDS_4112 "Digite um nome de arquivo válido." - IDS_4113 "A imagem foi criada com sucesso" - IDS_4114 "Certifique-se de que o arquivo existe e é legível." - IDS_4115 "Certifique-se de que o arquivo está sendo salvo em um diretório gravável." - IDS_4116 "A imagem do disco é muito grande" - IDS_4117 "Lembre-se de particionar e formatar a unidade recém-criada." - IDS_4118 "O arquivo selecionado será sobrescrito. Você tem certeza de que deseja usá-lo?" - IDS_4119 "Imagem de disco sem suporte" - IDS_4120 "Sobrescrever" - IDS_4121 "Não sobrescrever" - IDS_4122 "Imagem bruta (.img)" - IDS_4123 "Imagem HDI (.hdi)" - IDS_4124 "Imagem HDX (.hdx)" - IDS_4125 "VHD de tamanho fixo (.vhd)" - IDS_4126 "VHD de tamanho dinâmico (.vhd)" - IDS_4127 "VHD diferencial (.vhd)" - IDS_4128 "Blocos grandes (2 MB)" - IDS_4129 "Blocos pequenos (512 KB)" - IDS_4130 "Arquivos VHD (*.VHD)\0*.VHD\0Todos os arquivos (*.*)\0*.*\0" - IDS_4131 "Selecione o VHD pai" - IDS_4132 "Isto pode significar que a imagem de origem foi modificada após a criação da imagem diferencial.\n\nTambém pode acontecer caso os arquivos de imagem tenham sido movidos ou copiados, ou por um erro no programa que criou este disco.\n\nVocê quer consertar os marcadores de tempo?" - IDS_4133 "A data/hora dos arquivos de pais e filhos não correspondem" - IDS_4134 "Não foi possível consertar o carimbo de data/hora da VHD." - IDS_4135 "%01i:%02i" + IDS_4097 "%01i:%01i" + IDS_4098 "%01i" + IDS_4099 "As unidades de CD-ROM MFM/RLL ou ESDI nunca existiram" + IDS_4100 "Personalizado..." + IDS_4101 "Personalizado (grande)..." + IDS_4102 "Adicionar novo disco rígido" + IDS_4103 "Adicionar disco rígido existente" + IDS_4104 "As imagens de disco HDI não podem ser maiores do que 4GB." + IDS_4105 "As imagens de disco não podem ser maiores do que 127GB." + IDS_4106 "Imagens de disco rígido (*.HD?;*.IM?;*.VHD)\0*.HD?;*.IM?;*.VHD\0Todos os arquivos (*.*)\0*.*\0" + IDS_4107 "Não foi possível ler o arquivo" + IDS_4108 "Não foi possível escrever o arquivo" + IDS_4109 "Imagens HDI ou HDX com um tamanho de setor que não seja 512 não são suportadas." + IDS_4110 "O USB ainda não é suportado" + IDS_4111 "Esta imagem existe" + IDS_4112 "Digite um nome de arquivo válido." + IDS_4113 "A imagem foi criada com sucesso" + IDS_4114 "Certifique-se de que o arquivo existe e é legível." + IDS_4115 "Certifique-se de que o arquivo está sendo salvo em um diretório gravável." + IDS_4116 "A imagem do disco é muito grande" + IDS_4117 "Lembre-se de particionar e formatar a unidade recém-criada." + IDS_4118 "O arquivo selecionado será sobrescrito. Você tem certeza de que deseja usá-lo?" + IDS_4119 "Imagem de disco sem suporte" + IDS_4120 "Sobrescrever" + IDS_4121 "Não sobrescrever" + IDS_4122 "Imagem bruta (.img)" + IDS_4123 "Imagem HDI (.hdi)" + IDS_4124 "Imagem HDX (.hdx)" + IDS_4125 "VHD de tamanho fixo (.vhd)" + IDS_4126 "VHD de tamanho dinâmico (.vhd)" + IDS_4127 "VHD diferencial (.vhd)" + IDS_4128 "Blocos grandes (2 MB)" + IDS_4129 "Blocos pequenos (512 KB)" + IDS_4130 "Arquivos VHD (*.VHD)\0*.VHD\0Todos os arquivos (*.*)\0*.*\0" + IDS_4131 "Selecione o VHD pai" + IDS_4132 "Isto pode significar que a imagem de origem foi modificada após a criação da imagem diferencial.\n\nTambém pode acontecer caso os arquivos de imagem tenham sido movidos ou copiados, ou por um erro no programa que criou este disco.\n\nVocê quer consertar os marcadores de tempo?" + IDS_4133 "A data/hora dos arquivos de pais e filhos não correspondem" + IDS_4134 "Não foi possível consertar o carimbo de data/hora da VHD." + IDS_4135 "%01i:%02i" IDS_4352 "MFM/RLL" IDS_4353 "XTA" @@ -565,56 +585,56 @@ BEGIN IDS_4356 "ATAPI" IDS_4357 "SCSI" - IDS_4608 "MFM/RLL (%01i:%01i)" - IDS_4609 "XTA (%01i:%01i)" - IDS_4610 "ESDI (%01i:%01i)" - IDS_4611 "IDE (%01i:%01i)" - IDS_4612 "ATAPI (%01i:%01i)" - IDS_4613 "SCSI (%01i:%02i)" + IDS_4608 "MFM/RLL (%01i:%01i)" + IDS_4609 "XTA (%01i:%01i)" + IDS_4610 "ESDI (%01i:%01i)" + IDS_4611 "IDE (%01i:%01i)" + IDS_4612 "ATAPI (%01i:%01i)" + IDS_4613 "SCSI (%01i:%02i)" - IDS_5120 "CD-ROM %i (%s): %s" + IDS_5120 "CD-ROM %i (%s): %s" - IDS_5376 "Desativado" - IDS_5381 "ATAPI" + IDS_5376 "Desativado" + IDS_5381 "ATAPI" IDS_5382 "SCSI" - IDS_5632 "Desativado" - IDS_5637 "ATAPI (%01i:%01i)" + IDS_5632 "Desativado" + IDS_5637 "ATAPI (%01i:%01i)" IDS_5638 "SCSI (%01i:%02i)" - IDS_5888 "160 kB" - IDS_5889 "180 kB" - IDS_5890 "320 kB" - IDS_5891 "360 kB" - IDS_5892 "640 kB" - IDS_5893 "720 kB" - IDS_5894 "1.2 MB" - IDS_5895 "1.25 MB" - IDS_5896 "1.44 MB" - IDS_5897 "DMF (cluster 1024)" - IDS_5898 "DMF (cluster 2048)" - IDS_5899 "2.88 MB" - IDS_5900 "ZIP 100" - IDS_5901 "ZIP 250" - IDS_5902 "3.5"" 128 MB (ISO 10090)" - IDS_5903 "3.5"" 230 MB (ISO 13963)" - IDS_5904 "3.5"" 540 MB (ISO 15498)" - IDS_5905 "3.5"" 640 MB (ISO 15498)" - IDS_5906 "3.5"" 1.3 GB (GigaMO)" - IDS_5907 "3.5"" 2.3 GB (GigaMO 2)" - IDS_5908 "5.25"" 600 MB" - IDS_5909 "5.25"" 650 MB" - IDS_5910 "5.25"" 1 GB" - IDS_5911 "5.25"" 1.3 GB" + IDS_5888 "160 kB" + IDS_5889 "180 kB" + IDS_5890 "320 kB" + IDS_5891 "360 kB" + IDS_5892 "640 kB" + IDS_5893 "720 kB" + IDS_5894 "1.2 MB" + IDS_5895 "1.25 MB" + IDS_5896 "1.44 MB" + IDS_5897 "DMF (cluster 1024)" + IDS_5898 "DMF (cluster 2048)" + IDS_5899 "2.88 MB" + IDS_5900 "ZIP 100" + IDS_5901 "ZIP 250" + IDS_5902 "3.5"" 128 MB (ISO 10090)" + IDS_5903 "3.5"" 230 MB (ISO 13963)" + IDS_5904 "3.5"" 540 MB (ISO 15498)" + IDS_5905 "3.5"" 640 MB (ISO 15498)" + IDS_5906 "3.5"" 1.3 GB (GigaMO)" + IDS_5907 "3.5"" 2.3 GB (GigaMO 2)" + IDS_5908 "5.25"" 600 MB" + IDS_5909 "5.25"" 650 MB" + IDS_5910 "5.25"" 1 GB" + IDS_5911 "5.25"" 1.3 GB" - IDS_6144 "RPM perfeita" - IDS_6145 "1% abaixo das RPM perfeita" - IDS_6146 "1.5% abaixo das RPM perfeita" - IDS_6147 "2% abaixo das RPM perfeita" + IDS_6144 "RPM perfeita" + IDS_6145 "1% abaixo das RPM perfeita" + IDS_6146 "1.5% abaixo das RPM perfeita" + IDS_6147 "2% abaixo das RPM perfeita" - IDS_7168 "(Padrão do sistema)" + IDS_7168 "(Padrão do sistema)" END -#define IDS_LANG_ENUS IDS_7168 +#define IDS_LANG_ENUS IDS_7168 // Portuguese (pt-BR) resources ///////////////////////////////////////////////////////////////////////////// diff --git a/src/win/languages/pt-PT.rc b/src/win/languages/pt-PT.rc index 009e3f0df..88db4f18c 100644 --- a/src/win/languages/pt-PT.rc +++ b/src/win/languages/pt-PT.rc @@ -13,113 +13,122 @@ LANGUAGE LANG_PORTUGUESE, SUBLANG_PORTUGUESE // Menu // -MainMenu MENU DISCARDABLE +MainMenu MENU DISCARDABLE BEGIN POPUP "&Ação" BEGIN - MENUITEM "&Teclado requere captura", IDM_ACTION_KBD_REQ_CAPTURE + MENUITEM "&Teclado requere captura", IDM_ACTION_KBD_REQ_CAPTURE MENUITEM "&CTRL direito é ALT esquerdo",IDM_ACTION_RCTRL_IS_LALT MENUITEM SEPARATOR MENUITEM "&Reinicialização completa...",IDM_ACTION_HRESET - MENUITEM "&Ctrl+Alt+Del\tCtrl+F12", IDM_ACTION_RESET_CAD + MENUITEM "&Ctrl+Alt+Del\tCtrl+F12", IDM_ACTION_RESET_CAD MENUITEM SEPARATOR - MENUITEM "Ctrl+Alt+&Esc", IDM_ACTION_CTRL_ALT_ESC + MENUITEM "Ctrl+Alt+&Esc", IDM_ACTION_CTRL_ALT_ESC MENUITEM SEPARATOR - MENUITEM "&Pausa", IDM_ACTION_PAUSE + MENUITEM "&Pausa", IDM_ACTION_PAUSE MENUITEM SEPARATOR - MENUITEM "&Sair...", IDM_ACTION_EXIT + MENUITEM "&Sair...", IDM_ACTION_EXIT END POPUP "&Ver" BEGIN - MENUITEM "&Ocultar barra de estado", IDM_VID_HIDE_STATUS_BAR - MENUITEM "Hide &toolbar", IDM_VID_HIDE_TOOLBAR + MENUITEM "&Ocultar barra de estado", IDM_VID_HIDE_STATUS_BAR + MENUITEM "Hide &toolbar", IDM_VID_HIDE_TOOLBAR MENUITEM SEPARATOR - MENUITEM "&Janela redimensionável", IDM_VID_RESIZE - MENUITEM "&Lembrar tamanho e posição", IDM_VID_REMEMBER + MENUITEM "&Show non-primary monitors", IDM_VID_MONITORS + MENUITEM "&Janela redimensionável", IDM_VID_RESIZE + MENUITEM "&Lembrar tamanho e posição", IDM_VID_REMEMBER MENUITEM SEPARATOR POPUP "&Renderizador" BEGIN - MENUITEM "&SDL (Software)", IDM_VID_SDL_SW - MENUITEM "SDL (&Hardware)", IDM_VID_SDL_HW - MENUITEM "SDL (&OpenGL)", IDM_VID_SDL_OPENGL - MENUITEM "Open&GL (Núcleo 3.0)", IDM_VID_OPENGL_CORE + MENUITEM "&SDL (Software)", IDM_VID_SDL_SW + MENUITEM "SDL (&Hardware)", IDM_VID_SDL_HW + MENUITEM "SDL (&OpenGL)", IDM_VID_SDL_OPENGL + MENUITEM "Open&GL (Núcleo 3.0)", IDM_VID_OPENGL_CORE #ifdef USE_VNC - MENUITEM "&VNC", IDM_VID_VNC + MENUITEM "&VNC", IDM_VID_VNC #endif END MENUITEM SEPARATOR - MENUITEM "&Especificar dimensões...", IDM_VID_SPECIFY_DIM - MENUITEM "&Forçar rácio de visualização 4:3", IDM_VID_FORCE43 + MENUITEM "&Especificar dimensões...", IDM_VID_SPECIFY_DIM + MENUITEM "&Forçar rácio de visualização 4:3", IDM_VID_FORCE43 POPUP "F&actor de escala de janela" BEGIN - MENUITEM "&0.5x", IDM_VID_SCALE_1X - MENUITEM "&1x", IDM_VID_SCALE_2X - MENUITEM "1.&5x", IDM_VID_SCALE_3X - MENUITEM "&2x", IDM_VID_SCALE_4X + MENUITEM "&0.5x", IDM_VID_SCALE_1X + MENUITEM "&1x", IDM_VID_SCALE_2X + MENUITEM "1.&5x", IDM_VID_SCALE_3X + MENUITEM "&2x", IDM_VID_SCALE_4X + MENUITEM "&3x", IDM_VID_SCALE_5X + MENUITEM "&4x", IDM_VID_SCALE_6X + MENUITEM "&5x", IDM_VID_SCALE_7X + MENUITEM "&6x", IDM_VID_SCALE_8X + MENUITEM "&7x", IDM_VID_SCALE_9X + MENUITEM "&8x", IDM_VID_SCALE_10X END POPUP "Método de filtragem" BEGIN - MENUITEM "&Mais próximo", IDM_VID_FILTER_NEAREST - MENUITEM "&Linear", IDM_VID_FILTER_LINEAR + MENUITEM "&Mais próximo", IDM_VID_FILTER_NEAREST + MENUITEM "&Linear", IDM_VID_FILTER_LINEAR END - MENUITEM "Escala Hi&DPI", IDM_VID_HIDPI + MENUITEM "Escala Hi&DPI", IDM_VID_HIDPI MENUITEM SEPARATOR - MENUITEM "E&crã cheio\tCtrl+Alt+PgUp", IDM_VID_FULLSCREEN + MENUITEM "E&crã cheio\tCtrl+Alt+PgUp", IDM_VID_FULLSCREEN POPUP "Modo &de estiramento em ecrã cheio" BEGIN - MENUITEM "&Estiramento em ecrã cheio", IDM_VID_FS_FULL - MENUITEM "&4:3", IDM_VID_FS_43 + MENUITEM "&Estiramento em ecrã cheio", IDM_VID_FS_FULL + MENUITEM "&4:3", IDM_VID_FS_43 MENUITEM "Pixels &quadrados (Manter rácio)", IDM_VID_FS_KEEPRATIO - MENUITEM "Escala &inteira", IDM_VID_FS_INT + MENUITEM "Escala &inteira", IDM_VID_FS_INT END POPUP "Definições E&GA/(S)VGA" BEGIN - MENUITEM "Monitor VGA &invertido", IDM_VID_INVERT + MENUITEM "Monitor VGA &invertido", IDM_VID_INVERT POPUP "&Tipo de ecrã VGA" BEGIN - MENUITEM "&Cores RGB", IDM_VID_GRAY_RGB - MENUITEM "&RGB em escala de cinzentos", IDM_VID_GRAY_MONO - MENUITEM "Monitor âmb&ar", IDM_VID_GRAY_AMBER - MENUITEM "Monitor &verde", IDM_VID_GRAY_GREEN - MENUITEM "Monitor &branco", IDM_VID_GRAY_WHITE + MENUITEM "&Cores RGB", IDM_VID_GRAY_RGB + MENUITEM "&RGB em escala de cinzentos", IDM_VID_GRAY_MONO + MENUITEM "Monitor âmb&ar", IDM_VID_GRAY_AMBER + MENUITEM "Monitor &verde", IDM_VID_GRAY_GREEN + MENUITEM "Monitor &branco", IDM_VID_GRAY_WHITE END POPUP "Tipo de &conversão para escala de cinzentos" BEGIN - MENUITEM "BT&601 (NTSC/PAL)", IDM_VID_GRAYCT_601 - MENUITEM "BT&709 (HDTV)", IDM_VID_GRAYCT_709 - MENUITEM "&Media", IDM_VID_GRAYCT_AVE + MENUITEM "BT&601 (NTSC/PAL)", IDM_VID_GRAYCT_601 + MENUITEM "BT&709 (HDTV)", IDM_VID_GRAYCT_709 + MENUITEM "&Media", IDM_VID_GRAYCT_AVE END END MENUITEM SEPARATOR - MENUITEM "Overscan de CGA/PCjr/Tandy/E&GA/(S)VGA", IDM_VID_OVERSCAN + MENUITEM "Overscan de CGA/PCjr/Tandy/E&GA/(S)VGA", IDM_VID_OVERSCAN MENUITEM "Mudar &contraste para ecrã monocromático", IDM_VID_CGACON END - MENUITEM "&Media", IDM_MEDIA + MENUITEM "&Media", IDM_MEDIA POPUP "&Ferramentas" BEGIN - MENUITEM "&Definições...", IDM_CONFIG - MENUITEM "&Atualizar ícones da barra de estado", IDM_UPDATE_ICONS + MENUITEM "&Definições...", IDM_CONFIG + MENUITEM "&Atualizar ícones da barra de estado", IDM_UPDATE_ICONS MENUITEM SEPARATOR - MENUITEM "Gravar imagem de ecrã\tCtrl+F11", IDM_ACTION_SCREENSHOT + MENUITEM "Gravar imagem de ecrã\tCtrl+F11", IDM_ACTION_SCREENSHOT MENUITEM SEPARATOR - MENUITEM "&Preferências...", IDM_PREFERENCES + MENUITEM "&Preferências...", IDM_PREFERENCES +#ifdef DISCORD MENUITEM "Ativar integração com &Discord", IDM_DISCORD +#endif MENUITEM SEPARATOR - MENUITEM "&Ganho de som...", IDM_SND_GAIN + MENUITEM "&Ganho de som...", IDM_SND_GAIN #ifdef MTR_ENABLED MENUITEM SEPARATOR - MENUITEM "Iniciar o rastreio\tCtrl+T", IDM_ACTION_BEGIN_TRACE - MENUITEM "Terminar o rastreio\tCtrl+T", IDM_ACTION_END_TRACE + MENUITEM "Iniciar o rastreio\tCtrl+T", IDM_ACTION_BEGIN_TRACE + MENUITEM "Terminar o rastreio\tCtrl+T", IDM_ACTION_END_TRACE #endif END POPUP "&Ajuda" BEGIN - MENUITEM "&Documentação...", IDM_DOCS - MENUITEM "&Acerca do 86Box...", IDM_ABOUT + MENUITEM "&Documentação...", IDM_DOCS + MENUITEM "&Acerca do 86Box...", IDM_ABOUT END END -StatusBarMenu MENU DISCARDABLE +StatusBarMenu MENU DISCARDABLE BEGIN MENUITEM SEPARATOR END @@ -128,17 +137,17 @@ CassetteSubmenu MENU DISCARDABLE BEGIN POPUP "" BEGIN - MENUITEM "&Nova imagem...", IDM_CASSETTE_IMAGE_NEW + MENUITEM "&Nova imagem...", IDM_CASSETTE_IMAGE_NEW MENUITEM SEPARATOR - MENUITEM "Imagem &existente...", IDM_CASSETTE_IMAGE_EXISTING - MENUITEM "Imagem existente (&Proteção contra escrita)...", IDM_CASSETTE_IMAGE_EXISTING_WP + MENUITEM "Imagem &existente...", IDM_CASSETTE_IMAGE_EXISTING + MENUITEM "Imagem existente (&Proteção contra escrita)...", IDM_CASSETTE_IMAGE_EXISTING_WP MENUITEM SEPARATOR - MENUITEM "&Gravar", IDM_CASSETTE_RECORD - MENUITEM "&Reproduzir", IDM_CASSETTE_PLAY - MENUITEM "Re&bobinar para o início", IDM_CASSETTE_REWIND - MENUITEM "&Avanço rápido para o fim", IDM_CASSETTE_FAST_FORWARD + MENUITEM "&Gravar", IDM_CASSETTE_RECORD + MENUITEM "&Reproduzir", IDM_CASSETTE_PLAY + MENUITEM "Re&bobinar para o início", IDM_CASSETTE_REWIND + MENUITEM "&Avanço rápido para o fim", IDM_CASSETTE_FAST_FORWARD MENUITEM SEPARATOR - MENUITEM "E&jetar", IDM_CASSETTE_EJECT + MENUITEM "E&jetar", IDM_CASSETTE_EJECT END END @@ -146,9 +155,9 @@ CartridgeSubmenu MENU DISCARDABLE BEGIN POPUP "" BEGIN - MENUITEM "&Imagem...", IDM_CARTRIDGE_IMAGE + MENUITEM "&Imagem...", IDM_CARTRIDGE_IMAGE MENUITEM SEPARATOR - MENUITEM "E&jetar", IDM_CARTRIDGE_EJECT + MENUITEM "E&jetar", IDM_CARTRIDGE_EJECT END END @@ -156,14 +165,14 @@ FloppySubmenu MENU DISCARDABLE BEGIN POPUP "" BEGIN - MENUITEM "&Nova imagem...", IDM_FLOPPY_IMAGE_NEW + MENUITEM "&Nova imagem...", IDM_FLOPPY_IMAGE_NEW MENUITEM SEPARATOR - MENUITEM "Imagem &existente...", IDM_FLOPPY_IMAGE_EXISTING - MENUITEM "Imagem existente (&Proteção contra escrita)...", IDM_FLOPPY_IMAGE_EXISTING_WP + MENUITEM "Imagem &existente...", IDM_FLOPPY_IMAGE_EXISTING + MENUITEM "Imagem existente (&Proteção contra escrita)...", IDM_FLOPPY_IMAGE_EXISTING_WP MENUITEM SEPARATOR - MENUITEM "E&xportar para 86F...", IDM_FLOPPY_EXPORT_TO_86F + MENUITEM "E&xportar para 86F...", IDM_FLOPPY_EXPORT_TO_86F MENUITEM SEPARATOR - MENUITEM "E&jetar", IDM_FLOPPY_EJECT + MENUITEM "E&jetar", IDM_FLOPPY_EJECT END END @@ -171,12 +180,13 @@ CdromSubmenu MENU DISCARDABLE BEGIN POPUP "" BEGIN - MENUITEM "&Mute", IDM_CDROM_MUTE + MENUITEM "&Mute", IDM_CDROM_MUTE MENUITEM SEPARATOR - MENUITEM "&CDROM vazio", IDM_CDROM_EMPTY - MENUITEM "&Recarregar imagem anterior", IDM_CDROM_RELOAD + MENUITEM "&CDROM vazio", IDM_CDROM_EMPTY + MENUITEM "&Recarregar imagem anterior", IDM_CDROM_RELOAD MENUITEM SEPARATOR - MENUITEM "&Imagem", IDM_CDROM_IMAGE + MENUITEM "&Imagem...", IDM_CDROM_IMAGE + MENUITEM "&Pasta...", IDM_CDROM_DIR END END @@ -184,13 +194,13 @@ ZIPSubmenu MENU DISCARDABLE BEGIN POPUP "" BEGIN - MENUITEM "&Nova imagem...", IDM_ZIP_IMAGE_NEW + MENUITEM "&Nova imagem...", IDM_ZIP_IMAGE_NEW MENUITEM SEPARATOR - MENUITEM "Imagem &existente...", IDM_ZIP_IMAGE_EXISTING - MENUITEM "Imagem existente (&Proteção contra escrita)...", IDM_ZIP_IMAGE_EXISTING_WP + MENUITEM "Imagem &existente...", IDM_ZIP_IMAGE_EXISTING + MENUITEM "Imagem existente (&Proteção contra escrita)...", IDM_ZIP_IMAGE_EXISTING_WP MENUITEM SEPARATOR - MENUITEM "E&jetar", IDM_ZIP_EJECT - MENUITEM "&Recarregar imagem anterior", IDM_ZIP_RELOAD + MENUITEM "E&jetar", IDM_ZIP_EJECT + MENUITEM "&Recarregar imagem anterior", IDM_ZIP_RELOAD END END @@ -198,13 +208,13 @@ MOSubmenu MENU DISCARDABLE BEGIN POPUP "" BEGIN - MENUITEM "&Nova imagem...", IDM_MO_IMAGE_NEW + MENUITEM "&Nova imagem...", IDM_MO_IMAGE_NEW MENUITEM SEPARATOR - MENUITEM "Imagem &existente...", IDM_MO_IMAGE_EXISTING - MENUITEM "Imagem existente (&Proteção contra escrita)...", IDM_MO_IMAGE_EXISTING_WP + MENUITEM "Imagem &existente...", IDM_MO_IMAGE_EXISTING + MENUITEM "Imagem existente (&Proteção contra escrita)...", IDM_MO_IMAGE_EXISTING_WP MENUITEM SEPARATOR - MENUITEM "E&jetar", IDM_MO_EJECT - MENUITEM "&Recarregar imagem anterior", IDM_MO_RELOAD + MENUITEM "E&jetar", IDM_MO_EJECT + MENUITEM "&Recarregar imagem anterior", IDM_MO_RELOAD END END @@ -230,134 +240,150 @@ END // Dialog // -#define STR_PREFERENCES "Preferências" -#define STR_SND_GAIN "Ganho de som" -#define STR_NEW_FLOPPY "Nova imagem" -#define STR_CONFIG "Definições" -#define STR_SPECIFY_DIM "Especificar dimensões da janela principal" +#define STR_PREFERENCES "Preferências" +#define STR_SND_GAIN "Ganho de som" +#define STR_NEW_FLOPPY "Nova imagem" +#define STR_CONFIG "Definições" +#define STR_SPECIFY_DIM "Especificar dimensões da janela principal" -#define STR_OK "OK" -#define STR_CANCEL "Cancelar" -#define STR_GLOBAL "Guardar estas definições como padrões &globais" -#define STR_DEFAULT "&Padrão" -#define STR_LANGUAGE "Idioma:" -#define STR_ICONSET "Pacote de ícones:" +#define STR_OK "OK" +#define STR_CANCEL "Cancelar" +#define STR_GLOBAL "Guardar estas definições como padrões &globais" +#define STR_DEFAULT "&Padrão" +#define STR_LANGUAGE "Idioma:" +#define STR_ICONSET "Pacote de ícones:" -#define STR_GAIN "Ganho" +#define STR_GAIN "Ganho" -#define STR_FILE_NAME "Nome:" -#define STR_DISK_SIZE "Tamanho:" -#define STR_RPM_MODE "Modo RPM:" -#define STR_PROGRESS "Progresso:" +#define STR_FILE_NAME "Nome:" +#define STR_DISK_SIZE "Tamanho:" +#define STR_RPM_MODE "Modo RPM:" +#define STR_PROGRESS "Progresso:" -#define STR_WIDTH "Largura:" -#define STR_HEIGHT "Altura:" -#define STR_LOCK_TO_SIZE "Fixar neste tamanho" +#define STR_WIDTH "Largura:" +#define STR_HEIGHT "Altura:" +#define STR_LOCK_TO_SIZE "Fixar neste tamanho" -#define STR_MACHINE_TYPE "Tipo de máquina:" -#define STR_MACHINE "Máquina:" -#define STR_CONFIGURE "Configurar" -#define STR_CPU_TYPE "Tipo do CPU:" -#define STR_CPU_SPEED "Velocidade:" -#define STR_FPU "FPU:" -#define STR_WAIT_STATES "Estados de espera:" -#define STR_MB "MB" -#define STR_MEMORY "Memória:" -#define STR_TIME_SYNC "Sincronização da hora" -#define STR_DISABLED "Desativada" -#define STR_ENABLED_LOCAL "Ativada (hora local)" -#define STR_ENABLED_UTC "Ativada (UTC)" -#define STR_DYNAREC "Recompilador dinâmico" +#define STR_MACHINE_TYPE "Tipo de máquina:" +#define STR_MACHINE "Máquina:" +#define STR_CONFIGURE "Configurar" +#define STR_CPU_TYPE "Tipo do CPU:" +#define STR_CPU_SPEED "Velocidade:" +#define STR_FPU "FPU:" +#define STR_WAIT_STATES "Estados de espera:" +#define STR_MB "MB" +#define STR_MEMORY "Memória:" +#define STR_TIME_SYNC "Sincronização da hora" +#define STR_DISABLED "Desativada" +#define STR_ENABLED_LOCAL "Ativada (hora local)" +#define STR_ENABLED_UTC "Ativada (UTC)" +#define STR_DYNAREC "Recompilador dinâmico" +#define STR_SOFTFLOAT "Softfloat FPU" -#define STR_VIDEO "Vídeo:" -#define STR_VOODOO "Gráficos Voodoo" +#define STR_VIDEO "Vídeo:" +#define STR_VIDEO_2 "Vídeo 2:" +#define STR_VOODOO "Gráficos Voodoo" +#define STR_IBM8514 "Gráficos IBM 8514/a" +#define STR_XGA "Gráficos XGA" -#define STR_MOUSE "Rato:" -#define STR_JOYSTICK "Joystick:" -#define STR_JOY1 "Joystick 1..." -#define STR_JOY2 "Joystick 2..." -#define STR_JOY3 "Joystick 3..." -#define STR_JOY4 "Joystick 4..." +#define STR_MOUSE "Rato:" +#define STR_JOYSTICK "Joystick:" +#define STR_JOY1 "Joystick 1..." +#define STR_JOY2 "Joystick 2..." +#define STR_JOY3 "Joystick 3..." +#define STR_JOY4 "Joystick 4..." -#define STR_SOUND "Placa de som:" -#define STR_MIDI_OUT "Disp. saída MIDI:" -#define STR_MIDI_IN "Disp. entrada MIDI:" -#define STR_MPU401 "MPU-401 autónomo" -#define STR_SSI "Innovation SSI-2001" -#define STR_CMS "CMS / Game Blaster" -#define STR_GUS "Gravis Ultrasound" -#define STR_FLOAT "Utilizar som FLOAT32" +#define STR_SOUND1 "Placa de som 1:" +#define STR_SOUND2 "Placa de som 2:" +#define STR_SOUND3 "Placa de som 3:" +#define STR_SOUND4 "Placa de som 4:" +#define STR_MIDI_OUT "Disp. saída MIDI:" +#define STR_MIDI_IN "Disp. entrada MIDI:" +#define STR_MPU401 "MPU-401 autónomo" +#define STR_FLOAT "Utilizar som FLOAT32" +#define STR_FM_DRIVER "Controlador de sint. FM" +#define STR_FM_DRV_NUKED "Nuked (mais exacto)" +#define STR_FM_DRV_YMFM "YMFM (mais rápido)" -#define STR_NET_TYPE "Tipo de rede:" -#define STR_PCAP "Dispositivo PCap:" -#define STR_NET "Placa de rede:" +#define STR_NET_TYPE "Tipo de rede:" +#define STR_PCAP "Dispositivo PCap:" +#define STR_NET "Placa de rede:" +#define STR_NET1 "Network card 1:" +#define STR_NET2 "Network card 2:" +#define STR_NET3 "Network card 3:" +#define STR_NET4 "Network card 4:" -#define STR_COM1 "Dispositivo COM1:" -#define STR_COM2 "Dispositivo COM2:" -#define STR_COM3 "Dispositivo COM3:" -#define STR_COM4 "Dispositivo COM4:" -#define STR_LPT1 "Dispositivo LPT1:" -#define STR_LPT2 "Dispositivo LPT2:" -#define STR_LPT3 "Dispositivo LPT3:" -#define STR_LPT4 "Dispositivo LPT4:" -#define STR_SERIAL1 "Porta de série 1" -#define STR_SERIAL2 "Porta de série 2" -#define STR_SERIAL3 "Porta de série 3" -#define STR_SERIAL4 "Porta de série 4" -#define STR_PARALLEL1 "Porta paralela 1" -#define STR_PARALLEL2 "Porta paralela 2" -#define STR_PARALLEL3 "Porta paralela 3" -#define STR_PARALLEL4 "Porta paralela 4" +#define STR_COM1 "Dispositivo COM1:" +#define STR_COM2 "Dispositivo COM2:" +#define STR_COM3 "Dispositivo COM3:" +#define STR_COM4 "Dispositivo COM4:" +#define STR_LPT1 "Dispositivo LPT1:" +#define STR_LPT2 "Dispositivo LPT2:" +#define STR_LPT3 "Dispositivo LPT3:" +#define STR_LPT4 "Dispositivo LPT4:" +#define STR_SERIAL1 "Porta de série 1" +#define STR_SERIAL2 "Porta de série 2" +#define STR_SERIAL3 "Porta de série 3" +#define STR_SERIAL4 "Porta de série 4" +#define STR_PARALLEL1 "Porta paralela 1" +#define STR_PARALLEL2 "Porta paralela 2" +#define STR_PARALLEL3 "Porta paralela 3" +#define STR_PARALLEL4 "Porta paralela 4" +#define STR_SERIAL_PASS1 "Serial port passthrough 1" +#define STR_SERIAL_PASS2 "Serial port passthrough 2" +#define STR_SERIAL_PASS3 "Serial port passthrough 3" +#define STR_SERIAL_PASS4 "Serial port passthrough 4" -#define STR_HDC "Controlador HD:" -#define STR_FDC "Controlador FD:" -#define STR_IDE_TER "Controlador IDE terciário" -#define STR_IDE_QUA "Controlador IDE quaternário" -#define STR_SCSI "SCSI" -#define STR_SCSI_1 "Controlador 1:" -#define STR_SCSI_2 "Controlador 2:" -#define STR_SCSI_3 "Controlador 3:" -#define STR_SCSI_4 "Controlador 4:" -#define STR_CASSETTE "Cassete" +#define STR_HDC "Controlador HD:" +#define STR_FDC "Controlador FD:" +#define STR_IDE_TER "Controlador IDE terciário" +#define STR_IDE_QUA "Controlador IDE quaternário" +#define STR_SCSI "SCSI" +#define STR_SCSI_1 "Controlador 1:" +#define STR_SCSI_2 "Controlador 2:" +#define STR_SCSI_3 "Controlador 3:" +#define STR_SCSI_4 "Controlador 4:" +#define STR_CASSETTE "Cassete" -#define STR_HDD "Discos rígidos:" -#define STR_NEW "&Novo..." -#define STR_EXISTING "&Existente..." -#define STR_REMOVE "&Remover" -#define STR_BUS "Barram.:" -#define STR_CHANNEL "Canal:" -#define STR_ID "ID:" +#define STR_HDD "Discos rígidos:" +#define STR_NEW "&Novo..." +#define STR_EXISTING "&Existente..." +#define STR_REMOVE "&Remover" +#define STR_BUS "Barram.:" +#define STR_CHANNEL "Canal:" +#define STR_ID "ID:" +#define STR_SPEED "Speed:" -#define STR_SPECIFY "&Especificar..." -#define STR_SECTORS "Sectores:" -#define STR_HEADS "Cabeças:" -#define STR_CYLS "Cilindros:" -#define STR_SIZE_MB "Tamanho (MB):" -#define STR_TYPE "Tipo:" -#define STR_IMG_FORMAT "Formato de imagem:" -#define STR_BLOCK_SIZE "Tamanho de bloco:" +#define STR_SPECIFY "&Especificar..." +#define STR_SECTORS "Sectores:" +#define STR_HEADS "Cabeças:" +#define STR_CYLS "Cilindros:" +#define STR_SIZE_MB "Tamanho (MB):" +#define STR_TYPE "Tipo:" +#define STR_IMG_FORMAT "Formato de imagem:" +#define STR_BLOCK_SIZE "Tamanho de bloco:" -#define STR_FLOPPY_DRIVES "Unidades de disquete:" -#define STR_TURBO "Velocidade turbo" -#define STR_CHECKBPB "Verificar BPB" -#define STR_CDROM_DRIVES "Unidades CD-ROM:" -#define STR_CD_SPEED "Velocidade:" +#define STR_FLOPPY_DRIVES "Unidades de disquete:" +#define STR_TURBO "Velocidade turbo" +#define STR_CHECKBPB "Verificar BPB" +#define STR_CDROM_DRIVES "Unidades CD-ROM:" +#define STR_CD_SPEED "Velocidade:" -#define STR_MO_DRIVES "Unidades magneto-ópticas:" -#define STR_ZIP_DRIVES "Unidades ZIP:" -#define STR_250 "ZIP 250" +#define STR_MO_DRIVES "Unidades magneto-ópticas:" +#define STR_ZIP_DRIVES "Unidades ZIP:" +#define STR_250 "ZIP 250" -#define STR_ISARTC "ISA RTC:" -#define STR_ISAMEM "Expansão de memória ISA" -#define STR_ISAMEM_1 "Placa 1:" -#define STR_ISAMEM_2 "Placa 2:" -#define STR_ISAMEM_3 "Placa 3:" -#define STR_ISAMEM_4 "Placa 4:" -#define STR_BUGGER "Dispositivo ISABugger" -#define STR_POSTCARD "Placa POST" +#define STR_ISARTC "ISA RTC:" +#define STR_ISAMEM "Expansão de memória ISA" +#define STR_ISAMEM_1 "Placa 1:" +#define STR_ISAMEM_2 "Placa 2:" +#define STR_ISAMEM_3 "Placa 3:" +#define STR_ISAMEM_4 "Placa 4:" +#define STR_BUGGER "Dispositivo ISABugger" +#define STR_POSTCARD "Placa POST" -#define FONT_SIZE 9 -#define FONT_NAME "Segoe UI" +#define FONT_SIZE 9 +#define FONT_NAME "Segoe UI" #include "dialogs.rc" @@ -366,194 +392,188 @@ END // String Table // -STRINGTABLE DISCARDABLE +STRINGTABLE DISCARDABLE BEGIN - 2048 "86Box" - IDS_2049 "Erro" - IDS_2050 "Erro fatal" - IDS_2051 " - PAUSED" - IDS_2052 "Pressione Ctrl+Alt+PgDn para voltar ao modo de janela." - IDS_2053 "Velocidade" - IDS_2054 "ZIP %03i %i (%s): %ls" - IDS_2055 "Imagens ZIP (*.IM?;*.ZDI)\0*.IM?;*.ZDI\0" - IDS_2056 "O 86Box não conseguiu encontrar nenhuma imagem ROM utilizável.\n\nPor favor, vá a href=""https://github.com/86Box/roms/releases/latest"">descarregue um pacote ROM e instale-o na pasta ""roms""." - IDS_2057 "(empty)" - IDS_2058 "Imagens ZIP (*.IM?;*.ZDI)\0*.IM?;*.ZDI\0Todos os ficheiros (*.*)\0*.*\0" - IDS_2059 "Turbo" - IDS_2060 "Ativado" - IDS_2061 "Desativado" - IDS_2062 "Todas as imagens (*.86F;*.DSK;*.FLP;*.IM?;*.*FD?)\0*.86F;*.DSK;*.FLP;*.IM?;*.*FD?\0Imagens básicas de sector (*.DSK;*.FLP;*.IM?;*.*FD?)\0*.DSK;*.FLP;*.IM?;*.IMG;*.*FD?\0Imagens de superfície (*.86F)\0*.86F\0" - IDS_2063 "A máquina ""%hs"" não está disponível devido à falta de ROMs na pasta roms/machines. A mudar para uma máquina disponível." + 2048 "86Box" + IDS_2049 "Erro" + IDS_2050 "Erro fatal" + IDS_2051 " - PAUSED" + IDS_2052 "Pressione Ctrl+Alt+PgDn para voltar ao modo de janela." + IDS_2053 "Velocidade" + IDS_2054 "ZIP %03i %i (%s): %ls" + IDS_2055 "Imagens ZIP (*.IM?;*.ZDI)\0*.IM?;*.ZDI\0" + IDS_2056 "O 86Box não conseguiu encontrar nenhuma imagem ROM utilizável.\n\nPor favor, vá a href=""https://github.com/86Box/roms/releases/latest"">descarregue um pacote ROM e instale-o na pasta ""roms""." + IDS_2057 "(empty)" + IDS_2058 "Imagens ZIP (*.IM?;*.ZDI)\0*.IM?;*.ZDI\0Todos os ficheiros (*.*)\0*.*\0" + IDS_2059 "Turbo" + IDS_2060 "Ativado" + IDS_2061 "Desativado" + IDS_2062 "Todas as imagens (*.86F;*.DSK;*.FLP;*.IM?;*.*FD?)\0*.86F;*.DSK;*.FLP;*.IM?;*.*FD?\0Imagens básicas de sector (*.DSK;*.FLP;*.IM?;*.*FD?)\0*.DSK;*.FLP;*.IM?;*.IMG;*.*FD?\0Imagens de superfície (*.86F)\0*.86F\0" + IDS_2063 "A máquina ""%hs"" não está disponível devido à falta de ROMs na pasta roms/machines. A mudar para uma máquina disponível." END -STRINGTABLE DISCARDABLE +STRINGTABLE DISCARDABLE BEGIN - IDS_2064 "A placa vídeo ""%hs"" não está disponível devido à falta de ROMs na pasta roms/video. A mudar para uma placa vídeo disponível." - IDS_2065 "Máquina" - IDS_2066 "Apresentação" - IDS_2067 "Dispositivos de entrada" - IDS_2068 "Som" - IDS_2069 "Rede" - IDS_2070 "Portas (COM e LPT)" - IDS_2071 "Dispositivos de armazenamento" - IDS_2072 "Discos rígidos" - IDS_2073 "Unidades de disquete e CD-ROM" - IDS_2074 "Outros dispostivos removíveis" - IDS_2075 "Outros dispositivos" - IDS_2076 "Imagens de superfície (*.86F)\0*.86F\0" - IDS_2077 "Clique para capturar o rato" - IDS_2078 "Pressione F8+F12 para soltar o rato" - IDS_2079 "Pressione F8+F12 ou tecla média para soltar o rato" + IDS_2064 "A placa vídeo ""%hs"" não está disponível devido à falta de ROMs na pasta roms/video. A mudar para uma placa vídeo disponível." + IDS_2065 "Máquina" + IDS_2066 "Apresentação" + IDS_2067 "Dispositivos de entrada" + IDS_2068 "Som" + IDS_2069 "Rede" + IDS_2070 "Portas (COM e LPT)" + IDS_2071 "Dispositivos de armazenamento" + IDS_2072 "Discos rígidos" + IDS_2073 "Unidades de disquete e CD-ROM" + IDS_2074 "Outros dispostivos removíveis" + IDS_2075 "Outros dispositivos" + IDS_2076 "Imagens de superfície (*.86F)\0*.86F\0" + IDS_2077 "Clique para capturar o rato" + IDS_2078 "Pressione F8+F12 para soltar o rato" + IDS_2079 "Pressione F8+F12 ou tecla média para soltar o rato" END -STRINGTABLE DISCARDABLE +STRINGTABLE DISCARDABLE BEGIN - IDS_2080 "Não foi possível inicializar o FluidSynth" - IDS_2081 "Barramento" - IDS_2082 "Ficheiro" - IDS_2083 "C" - IDS_2084 "C" - IDS_2085 "S" - IDS_2086 "MB" - IDS_2087 "Verificar BPB" - IDS_2088 "KB" - IDS_2089 "Não foi possível inicializar o renderizador vídeo." - IDS_2090 "Padrão" - IDS_2091 "%i estado(s) de espera" - IDS_2092 "Tipo" - IDS_2093 "Falha na configuração de PCap" - IDS_2094 "Não foi encontrado um dispositivo PCap" - IDS_2095 "Dispositivo PCap inválido" - IDS_2096 "Joystick(s) standard de 2 botões" - IDS_2097 "Joystick(s) standard de 4 botões" - IDS_2098 "Joystick(s) standard de 6 botões" - IDS_2099 "Joystick(s) standard de 8 botões" - IDS_2100 "CH Flightstick Pro" - IDS_2101 "Microsoft SideWinder Pad" - IDS_2102 "Thrustmaster Flight Control System" - IDS_2103 "Nenhum" - IDS_2104 "Não foi possível inicializar os aceleradores de teclado." - IDS_2105 "Não foi possível registar a entrada bruta." - IDS_2106 "%u" - IDS_2107 "%u MB (CCS: %i, %i, %i)" - IDS_2108 "Disquete %i (%s): %ls" - IDS_2109 "Todas as imagens (*.0??;*.1??;*.??0;*.86F;*.BIN;*.CQ?;*.D??;*.FLP;*.HDM;*.IM?;*.JSON;*.TD0;*.*FD?;*.MFM;*.XDF)\0*.0??;*.1??;*.??0;*.86F;*.BIN;*.CQ?;*.D??;*.FLP;*.HDM;*.IM?;*.JSON;*.TD0;*.*FD?;*.MFM;*.XDF\0Imagens avançadas de sector (*.IMD;*.JSON;*.TD0)\0*.IMD;*.JSON;*.TD0\0Imagens básicas de sector (*.0??;*.1??;*.??0;*.BIN;*.CQ?;*.D??;*.FLP;*.HDM;*.IM?;*.XDF;*.*FD?)\0*.0??;*.1??;*.??0;*.BIN;*.CQ?;*.D??;*.FLP;*.HDM;*.IM?;*.XDF;*.*FD?\0Imagens de fluxo (*.FDI)\0*.FDI\0Imagens de superfície (*.86F;*.MFM)\0*.86F;*.MFM\0Todos os ficheiros (*.*)\0*.*\0" - IDS_2110 "Não foi possível inicializar o FreeType" - IDS_2111 "Não foi possível inicializar o SDL. O ficheiro SDL2.dll é necessário!" - IDS_2112 "Tem a certeza de que quer um reinício completo da máquina emulada?" - IDS_2113 "Tem a certeza de que quer sair do 86Box?" - IDS_2114 "Não foi possível inicializar o Ghostscript" - IDS_2115 "Magneto-óptico %i (%ls): %ls" - IDS_2116 "Imagens magneto-ópticas (*.IM?;*.MDI)\0*.IM?;*.MDI\0Todas as imagens (*.*)\0*.*\0" - IDS_2117 "Bem-vindos ao 86Box!" - IDS_2118 "Controlador interno" - IDS_2119 "Sair" - IDS_2120 "Não foi encontrada nenhuma ROM" - IDS_2121 "Deseja guardar as definições?" - IDS_2122 "Isto irá causar um reinício completo da máquina emulada." - IDS_2123 "Guardar" - IDS_2124 "Acerca do 86Box" - IDS_2125 "86Box v" EMU_VERSION + IDS_2081 "Barramento" + IDS_2082 "Ficheiro" + IDS_2083 "C" + IDS_2084 "C" + IDS_2085 "S" + IDS_2086 "MB" + IDS_2087 "Speed" + IDS_2088 "Verificar BPB" + IDS_2089 "KB" + IDS_2090 "Não foi possível inicializar o renderizador vídeo." + IDS_2091 "Padrão" + IDS_2092 "%i estado(s) de espera" + IDS_2093 "Tipo" + IDS_2094 "Falha na configuração de PCap" + IDS_2095 "Não foi encontrado um dispositivo PCap" + IDS_2096 "Dispositivo PCap inválido" + IDS_2097 "Joystick(s) standard de 2 botões" + IDS_2098 "Joystick(s) standard de 4 botões" + IDS_2099 "Joystick(s) standard de 6 botões" + IDS_2100 "Joystick(s) standard de 8 botões" + IDS_2101 "CH Flightstick Pro" + IDS_2102 "Microsoft SideWinder Pad" + IDS_2103 "Thrustmaster Flight Control System" + IDS_2104 "Nenhum" + IDS_2105 "Não foi possível inicializar os aceleradores de teclado." + IDS_2106 "Não foi possível registar a entrada bruta." + IDS_2107 "%u" + IDS_2108 "%u MB (CCS: %i, %i, %i)" + IDS_2109 "Disquete %i (%s): %ls" + IDS_2110 "Todas as imagens (*.0??;*.1??;*.??0;*.86F;*.BIN;*.CQ?;*.D??;*.FLP;*.HDM;*.IM?;*.JSON;*.TD0;*.*FD?;*.MFM;*.XDF)\0*.0??;*.1??;*.??0;*.86F;*.BIN;*.CQ?;*.D??;*.FLP;*.HDM;*.IM?;*.JSON;*.TD0;*.*FD?;*.MFM;*.XDF\0Imagens avançadas de sector (*.IMD;*.JSON;*.TD0)\0*.IMD;*.JSON;*.TD0\0Imagens básicas de sector (*.0??;*.1??;*.??0;*.BIN;*.CQ?;*.D??;*.FLP;*.HDM;*.IM?;*.XDF;*.*FD?)\0*.0??;*.1??;*.??0;*.BIN;*.CQ?;*.D??;*.FLP;*.HDM;*.IM?;*.XDF;*.*FD?\0Imagens de fluxo (*.FDI)\0*.FDI\0Imagens de superfície (*.86F;*.MFM)\0*.86F;*.MFM\0Todos os ficheiros (*.*)\0*.*\0" + IDS_2112 "Não foi possível inicializar o SDL. O ficheiro SDL2.dll é necessário!" + IDS_2113 "Tem a certeza de que quer um reinício completo da máquina emulada?" + IDS_2114 "Tem a certeza de que quer sair do 86Box?" + IDS_2115 "Não foi possível inicializar o Ghostscript" + IDS_2116 "Magneto-óptico %i (%ls): %ls" + IDS_2117 "Imagens magneto-ópticas (*.IM?;*.MDI)\0*.IM?;*.MDI\0Todas as imagens (*.*)\0*.*\0" + IDS_2118 "Bem-vindos ao 86Box!" + IDS_2119 "Controlador interno" + IDS_2120 "Sair" + IDS_2121 "Não foi encontrada nenhuma ROM" + IDS_2122 "Deseja guardar as definições?" + IDS_2123 "Isto irá causar um reinício completo da máquina emulada." + IDS_2124 "Guardar" + IDS_2125 "Acerca do 86Box" + IDS_2126 "86Box v" EMU_VERSION - IDS_2126 "Um emulador de computadores antigos\n\nAutores: Sarah Walker, Miran Grca, Fred N. van Kempen (waltje), SA1988, Tiseno100, reenigne, leilei, JohnElliott, greatpsycho, and others.\n\nUsado sob a licença GNU General Public License versão 2 ou posterior. Veja o ficheiro LICENSE para mais informações." - IDS_2127 "OK" - IDS_2128 "Hardware não disponível" + IDS_2127 "Um emulador de computadores antigos\n\nAutores: Miran GrÄa (OBattler), RichardG867, Jasmine Iwanek, TC1995, coldbrewed, Teemu Korhonen (Manaatti), Joakim L. Gilje, Adrien Moulin (elyosh), Daniel Balsom (gloriouscow), Cacodemon345, Fred N. van Kempen (waltje), Tiseno100, reenigne, and others.\n\nWith previous core contributions from Sarah Walker, leilei, JohnElliott, greatpsycho, and others.\n\nUsado sob a licença GNU General Public License versão 2 ou posterior. Veja o ficheiro LICENSE para mais informações." + IDS_2128 "OK" + IDS_2129 "Hardware não disponível" #ifdef _WIN32 #define LIB_NAME_PCAP "WinPcap" #else #define LIB_NAME_PCAP "libpcap" #endif - IDS_2129 "Certifique-se de que a biblioteca " LIB_NAME_PCAP " está instalada e de que está a utilizar uma ligação de rede compatível com a biblioteca " LIB_NAME_PCAP "." - IDS_2130 "Configuração inválida" -#ifdef _WIN32 -#define LIB_NAME_FREETYPE "freetype.dll" -#else -#define LIB_NAME_FREETYPE "libfreetype" -#endif - IDS_2131 LIB_NAME_FREETYPE " é requerida para a emulação de impressora ESC/P." + IDS_2130 "Certifique-se de que a biblioteca " LIB_NAME_PCAP " está instalada e de que está a utilizar uma ligação de rede compatível com a biblioteca " LIB_NAME_PCAP "." + IDS_2131 "Configuração inválida" #ifdef _WIN32 #define LIB_NAME_GS "gsdll32.dll" #else #define LIB_NAME_GS "libgs" #endif - IDS_2132 LIB_NAME_GS " é requerido para a conversão automática de ficheiros PostScript para ficheiros PDF.\n\nQualquer documento enviado para a impressora PostScript genérica será gravado como um ficheiro PostScript (.ps)." -#ifdef _WIN32 -#define LIB_NAME_FLUIDSYNTH "libfluidsynth.dll" -#else -#define LIB_NAME_FLUIDSYNTH "libfluidsynth" -#endif - IDS_2133 LIB_NAME_FLUIDSYNTH " é necessário para a saída MIDI FluidSynth MIDI." - IDS_2134 "A entrar no modo de ecrã cheio" - IDS_2135 "Não mostrar mais esta mensagem" - IDS_2136 "Não sair" - IDS_2137 "Reiniciar" - IDS_2138 "Não reiniciar" - IDS_2139 "Imagens magneto-ópticas (*.IM?;*.MDI)\0*.IM?;*.MDI\0Todos os ficheiros (*.*)\0*.*\0" - IDS_2140 "Imagens CD-ROM (*.ISO;*.CUE)\0*.ISO;*.CUE\0Todos os ficheiros (*.*)\0*.*\0" - IDS_2141 "Configuração de dispositivo %hs" - IDS_2142 "Ecrã em modo de sono" - IDS_2143 "Shaders OpenGL (*.GLSL)\0*.GLSL\0Todos os ficheiros (*.*)\0*.*\0" - IDS_2144 "Opções de OpenGL" - IDS_2145 "Está a carregar uma configuração sem suporte!" - IDS_2146 "A filtragem do tipo de CPU baseada na máquina escolhida está desativada para esta máquina emulada.\n\nIsto torna possível escolher um CPU que, de outra forma, não seria compatível com a máquina escolhida. No entanto, pode não ser compatível com a BIOS da máquina ou outros programas.\n\nA activação desta definição não tem suporte oficial e qualquer relatório de erros pode ser fechado como inválido." - IDS_2147 "Continuar" - IDS_2148 "Cassete: %s" - IDS_2149 "Imagens de cassete (*.PCM;*.RAW;*.WAV;*.CAS)\0*.PCM;*.RAW;*.WAV;*.CAS\0Todos os ficheiros (*.*)\0*.*\0" - IDS_2150 "Cartucho %i: %ls" - IDS_2151 "Imagens de cartucho (*.A;*.B;*.JRC)\0*.A;*.B;*.JRC\0Todos os ficheiros (*.*)\0*.*\0" - IDS_2152 "Error initializing renderer" - IDS_2153 "OpenGL (3.0 Core) renderer could not be initialized. Use another renderer." - IDS_2154 "Resume execution" - IDS_2155 "Pause execution" - IDS_2156 "Press Ctrl+Alt+Del" - IDS_2157 "Press Ctrl+Alt+Esc" - IDS_2158 "Hard reset" - IDS_2159 "ACPI shutdown" - IDS_2160 "Settings" + IDS_2133 LIB_NAME_GS " é requerido para a conversão automática de ficheiros PostScript para ficheiros PDF.\n\nQualquer documento enviado para a impressora PostScript genérica será gravado como um ficheiro PostScript (.ps)." + IDS_2135 "A entrar no modo de ecrã cheio" + IDS_2136 "Não mostrar mais esta mensagem" + IDS_2137 "Não sair" + IDS_2138 "Reiniciar" + IDS_2139 "Não reiniciar" + IDS_2140 "Imagens magneto-ópticas (*.IM?;*.MDI)\0*.IM?;*.MDI\0Todos os ficheiros (*.*)\0*.*\0" + IDS_2141 "Imagens CD-ROM (*.ISO;*.CUE)\0*.ISO;*.CUE\0Todos os ficheiros (*.*)\0*.*\0" + IDS_2142 "Configuração de dispositivo %hs" + IDS_2143 "Ecrã em modo de sono" + IDS_2144 "Shaders OpenGL (*.GLSL)\0*.GLSL\0Todos os ficheiros (*.*)\0*.*\0" + IDS_2145 "Opções de OpenGL" + IDS_2146 "Está a carregar uma configuração sem suporte!" + IDS_2147 "A filtragem do tipo de CPU baseada na máquina escolhida está desativada para esta máquina emulada.\n\nIsto torna possível escolher um CPU que, de outra forma, não seria compatível com a máquina escolhida. No entanto, pode não ser compatível com a BIOS da máquina ou outros programas.\n\nA activação desta definição não tem suporte oficial e qualquer relatório de erros pode ser fechado como inválido." + IDS_2148 "Continuar" + IDS_2149 "Cassete: %s" + IDS_2150 "Imagens de cassete (*.PCM;*.RAW;*.WAV;*.CAS)\0*.PCM;*.RAW;*.WAV;*.CAS\0Todos os ficheiros (*.*)\0*.*\0" + IDS_2151 "Cartucho %i: %ls" + IDS_2152 "Imagens de cartucho (*.A;*.B;*.JRC)\0*.A;*.B;*.JRC\0Todos os ficheiros (*.*)\0*.*\0" + IDS_2153 "Erro na inicialização do renderizador" + IDS_2154 "Não foi possível inicializar o renderizador OpenGL (3.0 Core). Utilize outro renderizador." + IDS_2155 "Retomar execução" + IDS_2156 "Pausar execução" + IDS_2157 "Ctrl+Alt+Del" + IDS_2158 "Ctrl+Alt+Esc" + IDS_2159 "Reinicialização completa" + IDS_2160 "Encerramento ACPI" + IDS_2161 "Definições" + IDS_2162 "Type" + IDS_2163 "No Dynarec" + IDS_2164 "Old Dynarec" + IDS_2165 "New Dynarec" + IDS_2166 "Video card #2 ""%hs"" is not available due to missing ROMs in the roms/video directory. Disabling the second video card." + IDS_2167 "Failed to initialize network driver" + IDS_2168 "The network configuration will be switched to the null driver" END -STRINGTABLE DISCARDABLE +STRINGTABLE DISCARDABLE BEGIN IDS_4096 "Disco rígido (%s)" - IDS_4097 "%01i:%01i" - IDS_4098 "%01i" - IDS_4099 "Unidades CD-ROM com barramento MFM/RLL ou ESDI nunca existiram!" - IDS_4100 "Personalizado..." - IDS_4101 "Personalizado (grande)..." - IDS_4102 "Adicionar novo disco rígido" - IDS_4103 "Adicionar disco rígido existente" - IDS_4104 "As imagens de disco HDI não podem ter mais de 4 GB." - IDS_4105 "As imagens de disco não podem ter mais de 127 GB." - IDS_4106 "Imagens de disco rígido (*.HD?;*.IM?;*.VHD)\0*.HD?;*.IM?;*.VHD\0Todos os ficheiros (*.*)\0*.*\0" - IDS_4107 "Não foi possível ler o ficheiro" - IDS_4108 "Não foi possível escrever o ficheiro" - IDS_4109 "Imagens HDI ou HDX com um tamanho de sector diferente de 512 não são suportadas." - IDS_4110 "O barramento USB ainda não tem suporte" - IDS_4111 "A imagem de disco já existe" - IDS_4112 "Por favor, especifique um nome de ficheiro válido." - IDS_4113 "Imagem de disco criada" - IDS_4114 "Certifique-se de que o ficheiro existe e é legível." - IDS_4115 "Certifique-se de que o ficheiro está a ser guardado numa pasta editável." - IDS_4116 "Imagem de disco muito grande" - IDS_4117 "Lembre-se de particionar e formatar o novo disco criado." - IDS_4118 "O ficheiro selecionado será sobrescrito. Tem a certeza de que quer utilizá-lo?" - IDS_4119 "Imagem de disco sem suporte" - IDS_4120 "Sobrescrever" - IDS_4121 "Não sobrescrever" - IDS_4122 "Imagem bruta (.img)" - IDS_4123 "Imagem HDI (.hdi)" - IDS_4124 "Imagem HDX (.hdx)" - IDS_4125 "VHD com tamanho fixo (.vhd)" - IDS_4126 "VHD com tamanho dinâmico (.vhd)" - IDS_4127 "VHD diferenciador (.vhd)" - IDS_4128 "Blocos grandes (2 MB)" - IDS_4129 "Blocos pequenos (512 KB)" - IDS_4130 "Ficheiros VHD (*.VHD)\0*.VHD\0Todos os ficheiros (*.*)\0*.*\0" - IDS_4131 "Seleccione o VHD pai" - IDS_4132 "Isto pode significar que a imagem pai foi modificada depois da criação da imagem diferenciadora.\n\nTambém pode acontecer se os ficheiros da imagem foram movidos ou copiados ou por causa de um erro no programa que criou este disco.\n\nQuer corrigir os carimbos de data/hora?" - IDS_4133 "Os carimbos de data/hora dos discos pai e filho não correspondem!" - IDS_4134 "Não foi possível corrigir o carimbo de data/hora do VHD." - IDS_4135 "%01i:%02i" + IDS_4097 "%01i:%01i" + IDS_4098 "%01i" + IDS_4099 "Unidades CD-ROM com barramento MFM/RLL ou ESDI nunca existiram!" + IDS_4100 "Personalizado..." + IDS_4101 "Personalizado (grande)..." + IDS_4102 "Adicionar novo disco rígido" + IDS_4103 "Adicionar disco rígido existente" + IDS_4104 "As imagens de disco HDI não podem ter mais de 4 GB." + IDS_4105 "As imagens de disco não podem ter mais de 127 GB." + IDS_4106 "Imagens de disco rígido (*.HD?;*.IM?;*.VHD)\0*.HD?;*.IM?;*.VHD\0Todos os ficheiros (*.*)\0*.*\0" + IDS_4107 "Não foi possível ler o ficheiro" + IDS_4108 "Não foi possível escrever o ficheiro" + IDS_4109 "Imagens HDI ou HDX com um tamanho de sector diferente de 512 não são suportadas." + IDS_4110 "O barramento USB ainda não tem suporte" + IDS_4111 "A imagem de disco já existe" + IDS_4112 "Por favor, especifique um nome de ficheiro válido." + IDS_4113 "Imagem de disco criada" + IDS_4114 "Certifique-se de que o ficheiro existe e é legível." + IDS_4115 "Certifique-se de que o ficheiro está a ser guardado numa pasta editável." + IDS_4116 "Imagem de disco muito grande" + IDS_4117 "Lembre-se de particionar e formatar o novo disco criado." + IDS_4118 "O ficheiro selecionado será sobrescrito. Tem a certeza de que quer utilizá-lo?" + IDS_4119 "Imagem de disco sem suporte" + IDS_4120 "Sobrescrever" + IDS_4121 "Não sobrescrever" + IDS_4122 "Imagem bruta (.img)" + IDS_4123 "Imagem HDI (.hdi)" + IDS_4124 "Imagem HDX (.hdx)" + IDS_4125 "VHD com tamanho fixo (.vhd)" + IDS_4126 "VHD com tamanho dinâmico (.vhd)" + IDS_4127 "VHD diferenciador (.vhd)" + IDS_4128 "Blocos grandes (2 MB)" + IDS_4129 "Blocos pequenos (512 KB)" + IDS_4130 "Ficheiros VHD (*.VHD)\0*.VHD\0Todos os ficheiros (*.*)\0*.*\0" + IDS_4131 "Seleccione o VHD pai" + IDS_4132 "Isto pode significar que a imagem pai foi modificada depois da criação da imagem diferenciadora.\n\nTambém pode acontecer se os ficheiros da imagem foram movidos ou copiados ou por causa de um erro no programa que criou este disco.\n\nQuer corrigir os carimbos de data/hora?" + IDS_4133 "Os carimbos de data/hora dos discos pai e filho não correspondem!" + IDS_4134 "Não foi possível corrigir o carimbo de data/hora do VHD." + IDS_4135 "%01i:%02i" IDS_4352 "MFM/RLL" IDS_4353 "XTA" @@ -562,56 +582,56 @@ BEGIN IDS_4356 "ATAPI" IDS_4357 "SCSI" - IDS_4608 "MFM/RLL (%01i:%01i)" - IDS_4609 "XTA (%01i:%01i)" - IDS_4610 "ESDI (%01i:%01i)" - IDS_4611 "IDE (%01i:%01i)" - IDS_4612 "ATAPI (%01i:%01i)" - IDS_4613 "SCSI (%01i:%02i)" + IDS_4608 "MFM/RLL (%01i:%01i)" + IDS_4609 "XTA (%01i:%01i)" + IDS_4610 "ESDI (%01i:%01i)" + IDS_4611 "IDE (%01i:%01i)" + IDS_4612 "ATAPI (%01i:%01i)" + IDS_4613 "SCSI (%01i:%02i)" - IDS_5120 "CD-ROM %i (%s): %s" + IDS_5120 "CD-ROM %i (%s): %s" - IDS_5376 "Desativado" - IDS_5381 "ATAPI" + IDS_5376 "Desativado" + IDS_5381 "ATAPI" IDS_5382 "SCSI" - IDS_5632 "Desativado" - IDS_5637 "ATAPI (%01i:%01i)" + IDS_5632 "Desativado" + IDS_5637 "ATAPI (%01i:%01i)" IDS_5638 "SCSI (%01i:%02i)" - IDS_5888 "160 kB" - IDS_5889 "180 kB" - IDS_5890 "320 kB" - IDS_5891 "360 kB" - IDS_5892 "640 kB" - IDS_5893 "720 kB" - IDS_5894 "1.2 MB" - IDS_5895 "1.25 MB" - IDS_5896 "1.44 MB" - IDS_5897 "DMF (cluster 1024)" - IDS_5898 "DMF (cluster 2048)" - IDS_5899 "2.88 MB" - IDS_5900 "ZIP 100" - IDS_5901 "ZIP 250" - IDS_5902 "3.5"" 128 MB (ISO 10090)" - IDS_5903 "3.5"" 230 MB (ISO 13963)" - IDS_5904 "3.5"" 540 MB (ISO 15498)" - IDS_5905 "3.5"" 640 MB (ISO 15498)" - IDS_5906 "3.5"" 1.3 GB (GigaMO)" - IDS_5907 "3.5"" 2.3 GB (GigaMO 2)" - IDS_5908 "5.25"" 600 MB" - IDS_5909 "5.25"" 650 MB" - IDS_5910 "5.25"" 1 GB" - IDS_5911 "5.25"" 1.3 GB" + IDS_5888 "160 kB" + IDS_5889 "180 kB" + IDS_5890 "320 kB" + IDS_5891 "360 kB" + IDS_5892 "640 kB" + IDS_5893 "720 kB" + IDS_5894 "1.2 MB" + IDS_5895 "1.25 MB" + IDS_5896 "1.44 MB" + IDS_5897 "DMF (cluster 1024)" + IDS_5898 "DMF (cluster 2048)" + IDS_5899 "2.88 MB" + IDS_5900 "ZIP 100" + IDS_5901 "ZIP 250" + IDS_5902 "3.5"" 128 MB (ISO 10090)" + IDS_5903 "3.5"" 230 MB (ISO 13963)" + IDS_5904 "3.5"" 540 MB (ISO 15498)" + IDS_5905 "3.5"" 640 MB (ISO 15498)" + IDS_5906 "3.5"" 1.3 GB (GigaMO)" + IDS_5907 "3.5"" 2.3 GB (GigaMO 2)" + IDS_5908 "5.25"" 600 MB" + IDS_5909 "5.25"" 650 MB" + IDS_5910 "5.25"" 1 GB" + IDS_5911 "5.25"" 1.3 GB" - IDS_6144 "RPM perfeito" - IDS_6145 "RPM 1% abaixo do RPM perfeito" - IDS_6146 "RPM 1.5% abaixo do RPM perfeito" - IDS_6147 "RPM 2% abaixo do RPM perfeito" + IDS_6144 "RPM perfeito" + IDS_6145 "RPM 1% abaixo do RPM perfeito" + IDS_6146 "RPM 1.5% abaixo do RPM perfeito" + IDS_6147 "RPM 2% abaixo do RPM perfeito" - IDS_7168 "(Padrão do sistema)" + IDS_7168 "(Padrão do sistema)" END -#define IDS_LANG_ENUS IDS_7168 +#define IDS_LANG_ENUS IDS_7168 // Portuguese (Portugal) resources ///////////////////////////////////////////////////////////////////////////// diff --git a/src/win/languages/ru-RU.rc b/src/win/languages/ru-RU.rc index 10d7a3f5e..647b43d44 100644 --- a/src/win/languages/ru-RU.rc +++ b/src/win/languages/ru-RU.rc @@ -13,113 +13,122 @@ LANGUAGE LANG_RUSSIAN, SUBLANG_DEFAULT // Menu // -MainMenu MENU DISCARDABLE +MainMenu MENU DISCARDABLE BEGIN POPUP "&ДейÑтвие" BEGIN - MENUITEM "&Клавиатура требует захвата", IDM_ACTION_KBD_REQ_CAPTURE - MENUITEM "&Правый CTRL - Ñто левый ALT", IDM_ACTION_RCTRL_IS_LALT + MENUITEM "&Клавиатура требует захвата", IDM_ACTION_KBD_REQ_CAPTURE + MENUITEM "&Правый CTRL - Ñто левый ALT", IDM_ACTION_RCTRL_IS_LALT MENUITEM SEPARATOR - MENUITEM "&Ð¥Ð¾Ð»Ð¾Ð´Ð½Ð°Ñ Ð¿ÐµÑ€ÐµÐ·Ð°Ð³Ñ€ÑƒÐ·ÐºÐ°...", IDM_ACTION_HRESET - MENUITEM "&Ctrl+Alt+Del\tCtrl+F12", IDM_ACTION_RESET_CAD + MENUITEM "&Ð¥Ð¾Ð»Ð¾Ð´Ð½Ð°Ñ Ð¿ÐµÑ€ÐµÐ·Ð°Ð³Ñ€ÑƒÐ·ÐºÐ°...", IDM_ACTION_HRESET + MENUITEM "&Ctrl+Alt+Del\tCtrl+F12", IDM_ACTION_RESET_CAD MENUITEM SEPARATOR - MENUITEM "Ctrl+Alt+&Esc", IDM_ACTION_CTRL_ALT_ESC + MENUITEM "Ctrl+Alt+&Esc", IDM_ACTION_CTRL_ALT_ESC MENUITEM SEPARATOR - MENUITEM "&Пауза", IDM_ACTION_PAUSE + MENUITEM "&Пауза", IDM_ACTION_PAUSE MENUITEM SEPARATOR - MENUITEM "&Выход...", IDM_ACTION_EXIT + MENUITEM "&Выход...", IDM_ACTION_EXIT END POPUP "&Вид" BEGIN - MENUITEM "&Скрыть Ñтроку ÑоÑтоÑниÑ", IDM_VID_HIDE_STATUS_BAR - MENUITEM "С&крыть панель инÑтрументов", IDM_VID_HIDE_TOOLBAR + MENUITEM "&Скрыть Ñтроку ÑоÑтоÑниÑ", IDM_VID_HIDE_STATUS_BAR + MENUITEM "С&крыть панель инÑтрументов", IDM_VID_HIDE_TOOLBAR MENUITEM SEPARATOR - MENUITEM "&ИзменÑемый размер окна", IDM_VID_RESIZE - MENUITEM "&Запомнить размер и положение", IDM_VID_REMEMBER + MENUITEM "&Show non-primary monitors", IDM_VID_MONITORS + MENUITEM "&ИзменÑемый размер окна", IDM_VID_RESIZE + MENUITEM "&Запомнить размер и положение", IDM_VID_REMEMBER MENUITEM SEPARATOR POPUP "&Рендеринг" BEGIN - MENUITEM "&SDL (Software)", IDM_VID_SDL_SW - MENUITEM "SDL (&Hardware)", IDM_VID_SDL_HW - MENUITEM "SDL (&OpenGL)", IDM_VID_SDL_OPENGL - MENUITEM "Open&GL (3.0)", IDM_VID_OPENGL_CORE + MENUITEM "&SDL (Software)", IDM_VID_SDL_SW + MENUITEM "SDL (&Hardware)", IDM_VID_SDL_HW + MENUITEM "SDL (&OpenGL)", IDM_VID_SDL_OPENGL + MENUITEM "Open&GL (3.0)", IDM_VID_OPENGL_CORE #ifdef USE_VNC - MENUITEM "&VNC", IDM_VID_VNC + MENUITEM "&VNC", IDM_VID_VNC #endif END MENUITEM SEPARATOR - MENUITEM "&Указать размеры...", IDM_VID_SPECIFY_DIM - MENUITEM "У&Ñтановить Ñоотношение Ñторон 4:3", IDM_VID_FORCE43 + MENUITEM "&Указать размеры...", IDM_VID_SPECIFY_DIM + MENUITEM "У&Ñтановить Ñоотношение Ñторон 4:3", IDM_VID_FORCE43 POPUP "&МаÑштаб окна" BEGIN - MENUITEM "&0.5x", IDM_VID_SCALE_1X - MENUITEM "&1x", IDM_VID_SCALE_2X - MENUITEM "1.&5x", IDM_VID_SCALE_3X - MENUITEM "&2x", IDM_VID_SCALE_4X + MENUITEM "&0.5x", IDM_VID_SCALE_1X + MENUITEM "&1x", IDM_VID_SCALE_2X + MENUITEM "1.&5x", IDM_VID_SCALE_3X + MENUITEM "&2x", IDM_VID_SCALE_4X + MENUITEM "&3x", IDM_VID_SCALE_5X + MENUITEM "&4x", IDM_VID_SCALE_6X + MENUITEM "&5x", IDM_VID_SCALE_7X + MENUITEM "&6x", IDM_VID_SCALE_8X + MENUITEM "&7x", IDM_VID_SCALE_9X + MENUITEM "&8x", IDM_VID_SCALE_10X END POPUP "Метод фильтрации" BEGIN - MENUITEM "&Ближайший", IDM_VID_FILTER_NEAREST - MENUITEM "&Линейный", IDM_VID_FILTER_LINEAR + MENUITEM "&Ближайший", IDM_VID_FILTER_NEAREST + MENUITEM "&Линейный", IDM_VID_FILTER_LINEAR END - MENUITEM "МаÑштабирование Hi&DPI", IDM_VID_HIDPI + MENUITEM "МаÑштабирование Hi&DPI", IDM_VID_HIDPI MENUITEM SEPARATOR - MENUITEM "&ПолноÑкранный режим\tCtrl+Alt+PgUp", IDM_VID_FULLSCREEN + MENUITEM "&ПолноÑкранный режим\tCtrl+Alt+PgUp", IDM_VID_FULLSCREEN POPUP "&РаÑÑ‚Ñгивание в полноÑкранном режиме" BEGIN - MENUITEM "&Ðа веÑÑŒ Ñкран", IDM_VID_FS_FULL - MENUITEM "&4:3", IDM_VID_FS_43 + MENUITEM "&Ðа веÑÑŒ Ñкран", IDM_VID_FS_FULL + MENUITEM "&4:3", IDM_VID_FS_43 MENUITEM "&Квадратные пикÑели (Ñохранить Ñоотношение)", IDM_VID_FS_KEEPRATIO - MENUITEM "&ЦелочиÑленное маÑштабирование", IDM_VID_FS_INT + MENUITEM "&ЦелочиÑленное маÑштабирование", IDM_VID_FS_INT END POPUP "ÐаÑтройки E&GA/(S)VGA" BEGIN - MENUITEM "&Инвертировать цвета VGA", IDM_VID_INVERT + MENUITEM "&Инвертировать цвета VGA", IDM_VID_INVERT POPUP "&Тип Ñкрана VGA" BEGIN - MENUITEM "RGB &цветной", IDM_VID_GRAY_RGB - MENUITEM "&RGB монохромный", IDM_VID_GRAY_MONO - MENUITEM "&Янтарный оттенок", IDM_VID_GRAY_AMBER - MENUITEM "&Зелёный оттенок", IDM_VID_GRAY_GREEN - MENUITEM "&Белый оттенок", IDM_VID_GRAY_WHITE + MENUITEM "RGB &цветной", IDM_VID_GRAY_RGB + MENUITEM "&RGB монохромный", IDM_VID_GRAY_MONO + MENUITEM "&Янтарный оттенок", IDM_VID_GRAY_AMBER + MENUITEM "&Зелёный оттенок", IDM_VID_GRAY_GREEN + MENUITEM "&Белый оттенок", IDM_VID_GRAY_WHITE END POPUP "Тип монохромного &конвертированиÑ" BEGIN - MENUITEM "BT&601 (NTSC/PAL)", IDM_VID_GRAYCT_601 - MENUITEM "BT&709 (HDTV)", IDM_VID_GRAYCT_709 - MENUITEM "&УÑреднённый", IDM_VID_GRAYCT_AVE + MENUITEM "BT&601 (NTSC/PAL)", IDM_VID_GRAYCT_601 + MENUITEM "BT&709 (HDTV)", IDM_VID_GRAYCT_709 + MENUITEM "&УÑреднённый", IDM_VID_GRAYCT_AVE END END MENUITEM SEPARATOR - MENUITEM "Вылеты развёртки CGA/PCjr/Tandy/E&GA/(S)VGA", IDM_VID_OVERSCAN + MENUITEM "Вылеты развёртки CGA/PCjr/Tandy/E&GA/(S)VGA", IDM_VID_OVERSCAN MENUITEM "Изменить контраÑтноÑть &монохромного диÑплеÑ", IDM_VID_CGACON END - MENUITEM "&ÐоÑители", IDM_MEDIA + MENUITEM "&ÐоÑители", IDM_MEDIA POPUP "&ИнÑтрументы" BEGIN - MENUITEM "&ÐаÑтройки машины...", IDM_CONFIG - MENUITEM "&Обновление значков Ñтроки ÑоÑтоÑниÑ", IDM_UPDATE_ICONS + MENUITEM "&ÐаÑтройки машины...", IDM_CONFIG + MENUITEM "&Обновление значков Ñтроки ÑоÑтоÑниÑ", IDM_UPDATE_ICONS MENUITEM SEPARATOR - MENUITEM "Сделать Ñ&криншот\tCtrl+F11", IDM_ACTION_SCREENSHOT + MENUITEM "Сделать Ñ&криншот\tCtrl+F11", IDM_ACTION_SCREENSHOT MENUITEM SEPARATOR - MENUITEM "&Параметры...", IDM_PREFERENCES + MENUITEM "&Параметры...", IDM_PREFERENCES +#ifdef DISCORD MENUITEM "Включить интеграцию &Discord", IDM_DISCORD +#endif MENUITEM SEPARATOR - MENUITEM "&УÑиление звука...", IDM_SND_GAIN + MENUITEM "&УÑиление звука...", IDM_SND_GAIN #ifdef MTR_ENABLED MENUITEM SEPARATOR - MENUITEM "Ðачать траÑÑировку\tCtrl+T", IDM_ACTION_BEGIN_TRACE - MENUITEM "Завершить траÑÑировку\tCtrl+T", IDM_ACTION_END_TRACE + MENUITEM "Ðачать траÑÑировку\tCtrl+T", IDM_ACTION_BEGIN_TRACE + MENUITEM "Завершить траÑÑировку\tCtrl+T", IDM_ACTION_END_TRACE #endif END POPUP "&Помощь" BEGIN - MENUITEM "&ДокументациÑ...", IDM_DOCS - MENUITEM "&О программе 86Box...", IDM_ABOUT + MENUITEM "&ДокументациÑ...", IDM_DOCS + MENUITEM "&О программе 86Box...", IDM_ABOUT END END -StatusBarMenu MENU DISCARDABLE +StatusBarMenu MENU DISCARDABLE BEGIN MENUITEM SEPARATOR END @@ -128,17 +137,17 @@ CassetteSubmenu MENU DISCARDABLE BEGIN POPUP "" BEGIN - MENUITEM "&Ðовый образ...", IDM_CASSETTE_IMAGE_NEW + MENUITEM "&Ðовый образ...", IDM_CASSETTE_IMAGE_NEW MENUITEM SEPARATOR - MENUITEM "&Выбрать образ...", IDM_CASSETTE_IMAGE_EXISTING - MENUITEM "Выбрать образ (&Защита от запиÑи)...", IDM_CASSETTE_IMAGE_EXISTING_WP + MENUITEM "&Выбрать образ...", IDM_CASSETTE_IMAGE_EXISTING + MENUITEM "Выбрать образ (&Защита от запиÑи)...", IDM_CASSETTE_IMAGE_EXISTING_WP MENUITEM SEPARATOR - MENUITEM "&ЗапиÑÑŒ", IDM_CASSETTE_RECORD - MENUITEM "&ВоÑпроизведение", IDM_CASSETTE_PLAY - MENUITEM "&Перемотка на начало", IDM_CASSETTE_REWIND - MENUITEM "&Перемотка в конец", IDM_CASSETTE_FAST_FORWARD + MENUITEM "&ЗапиÑÑŒ", IDM_CASSETTE_RECORD + MENUITEM "&ВоÑпроизведение", IDM_CASSETTE_PLAY + MENUITEM "&Перемотка на начало", IDM_CASSETTE_REWIND + MENUITEM "&Перемотка в конец", IDM_CASSETTE_FAST_FORWARD MENUITEM SEPARATOR - MENUITEM "И&звлечь", IDM_CASSETTE_EJECT + MENUITEM "И&звлечь", IDM_CASSETTE_EJECT END END @@ -146,9 +155,9 @@ CartridgeSubmenu MENU DISCARDABLE BEGIN POPUP "" BEGIN - MENUITEM "&Образ...", IDM_CARTRIDGE_IMAGE + MENUITEM "&Образ...", IDM_CARTRIDGE_IMAGE MENUITEM SEPARATOR - MENUITEM "И&звлечь", IDM_CARTRIDGE_EJECT + MENUITEM "И&звлечь", IDM_CARTRIDGE_EJECT END END @@ -156,14 +165,14 @@ FloppySubmenu MENU DISCARDABLE BEGIN POPUP "" BEGIN - MENUITEM "&Ðовый образ...", IDM_FLOPPY_IMAGE_NEW + MENUITEM "&Ðовый образ...", IDM_FLOPPY_IMAGE_NEW MENUITEM SEPARATOR - MENUITEM "&Выбрать образ...", IDM_FLOPPY_IMAGE_EXISTING - MENUITEM "Выбрать образ (&Защита от запиÑи)...", IDM_FLOPPY_IMAGE_EXISTING_WP + MENUITEM "&Выбрать образ...", IDM_FLOPPY_IMAGE_EXISTING + MENUITEM "Выбрать образ (&Защита от запиÑи)...", IDM_FLOPPY_IMAGE_EXISTING_WP MENUITEM SEPARATOR - MENUITEM "Э&кÑпорт в 86F...", IDM_FLOPPY_EXPORT_TO_86F + MENUITEM "Э&кÑпорт в 86F...", IDM_FLOPPY_EXPORT_TO_86F MENUITEM SEPARATOR - MENUITEM "И&звлечь", IDM_FLOPPY_EJECT + MENUITEM "И&звлечь", IDM_FLOPPY_EJECT END END @@ -171,12 +180,13 @@ CdromSubmenu MENU DISCARDABLE BEGIN POPUP "" BEGIN - MENUITEM "О&тключить звук", IDM_CDROM_MUTE + MENUITEM "О&тключить звук", IDM_CDROM_MUTE MENUITEM SEPARATOR - MENUITEM "П&уÑтой", IDM_CDROM_EMPTY - MENUITEM "&Снова загрузить предыдущий образ", IDM_CDROM_RELOAD + MENUITEM "П&уÑтой", IDM_CDROM_EMPTY + MENUITEM "&Снова загрузить предыдущий образ", IDM_CDROM_RELOAD MENUITEM SEPARATOR - MENUITEM "&Образ...", IDM_CDROM_IMAGE + MENUITEM "&Образ...", IDM_CDROM_IMAGE + MENUITEM "&Папка...", IDM_CDROM_DIR END END @@ -184,13 +194,13 @@ ZIPSubmenu MENU DISCARDABLE BEGIN POPUP "" BEGIN - MENUITEM "&Ðовый образ...", IDM_ZIP_IMAGE_NEW + MENUITEM "&Ðовый образ...", IDM_ZIP_IMAGE_NEW MENUITEM SEPARATOR - MENUITEM "&Выбрать образ...", IDM_ZIP_IMAGE_EXISTING - MENUITEM "Выбрать образ (&Защита от запиÑи)...", IDM_ZIP_IMAGE_EXISTING_WP + MENUITEM "&Выбрать образ...", IDM_ZIP_IMAGE_EXISTING + MENUITEM "Выбрать образ (&Защита от запиÑи)...", IDM_ZIP_IMAGE_EXISTING_WP MENUITEM SEPARATOR - MENUITEM "И&звлечь", IDM_ZIP_EJECT - MENUITEM "&Снова загрузить предыдущий образ", IDM_ZIP_RELOAD + MENUITEM "И&звлечь", IDM_ZIP_EJECT + MENUITEM "&Снова загрузить предыдущий образ", IDM_ZIP_RELOAD END END @@ -198,13 +208,13 @@ MOSubmenu MENU DISCARDABLE BEGIN POPUP "" BEGIN - MENUITEM "&Ðовый образ...", IDM_MO_IMAGE_NEW + MENUITEM "&Ðовый образ...", IDM_MO_IMAGE_NEW MENUITEM SEPARATOR - MENUITEM "&Выбрать образ...", IDM_MO_IMAGE_EXISTING - MENUITEM "Выбрать образ (&Защита от запиÑи)...", IDM_MO_IMAGE_EXISTING_WP + MENUITEM "&Выбрать образ...", IDM_MO_IMAGE_EXISTING + MENUITEM "Выбрать образ (&Защита от запиÑи)...", IDM_MO_IMAGE_EXISTING_WP MENUITEM SEPARATOR - MENUITEM "И&звлечь", IDM_MO_EJECT - MENUITEM "&Снова загрузить предыдущий образ", IDM_MO_RELOAD + MENUITEM "И&звлечь", IDM_MO_EJECT + MENUITEM "&Снова загрузить предыдущий образ", IDM_MO_RELOAD END END @@ -230,134 +240,150 @@ END // Dialog // -#define STR_PREFERENCES "Параметры" -#define STR_SND_GAIN "УÑиление звука" -#define STR_NEW_FLOPPY "Ðовый образ" -#define STR_CONFIG "ÐаÑтройки" -#define STR_SPECIFY_DIM "Указать размеры главного окна" +#define STR_PREFERENCES "Параметры" +#define STR_SND_GAIN "УÑиление звука" +#define STR_NEW_FLOPPY "Ðовый образ" +#define STR_CONFIG "ÐаÑтройки" +#define STR_SPECIFY_DIM "Указать размеры главного окна" -#define STR_OK "OK" -#define STR_CANCEL "Отмена" -#define STR_GLOBAL "Сохранить Ñти параметры как &глобальные по умолчанию" -#define STR_DEFAULT "&По умолчанию" -#define STR_LANGUAGE "Язык:" -#define STR_ICONSET "Ðабор иконок:" +#define STR_OK "OK" +#define STR_CANCEL "Отмена" +#define STR_GLOBAL "Сохранить Ñти параметры как &глобальные по умолчанию" +#define STR_DEFAULT "&По умолчанию" +#define STR_LANGUAGE "Язык:" +#define STR_ICONSET "Ðабор иконок:" -#define STR_GAIN "УÑиление" +#define STR_GAIN "УÑиление" -#define STR_FILE_NAME "Ð˜Ð¼Ñ Ñ„Ð°Ð¹Ð»Ð°:" -#define STR_DISK_SIZE "Размер диÑка:" -#define STR_RPM_MODE "RPM режим:" -#define STR_PROGRESS "ПрогреÑÑ:" +#define STR_FILE_NAME "Ð˜Ð¼Ñ Ñ„Ð°Ð¹Ð»Ð°:" +#define STR_DISK_SIZE "Размер диÑка:" +#define STR_RPM_MODE "RPM режим:" +#define STR_PROGRESS "ПрогреÑÑ:" -#define STR_WIDTH "Ширина:" -#define STR_HEIGHT "Ð’Ñ‹Ñота:" -#define STR_LOCK_TO_SIZE "ЗафикÑировать размер" +#define STR_WIDTH "Ширина:" +#define STR_HEIGHT "Ð’Ñ‹Ñота:" +#define STR_LOCK_TO_SIZE "ЗафикÑировать размер" -#define STR_MACHINE_TYPE "Тип машины:" -#define STR_MACHINE "СиÑÑ‚ÐµÐ¼Ð½Ð°Ñ Ð¿Ð»Ð°Ñ‚Ð°:" -#define STR_CONFIGURE "ÐаÑтройка" -#define STR_CPU_TYPE "Тип ЦП:" -#define STR_CPU_SPEED "СкороÑть:" -#define STR_FPU "FPU:" -#define STR_WAIT_STATES "Циклы ожиданиÑ:" -#define STR_MB "МБ" -#define STR_MEMORY "ПамÑть:" -#define STR_TIME_SYNC "Ð¡Ð¸Ð½Ñ…Ñ€Ð¾Ð½Ð¸Ð·Ð°Ñ†Ð¸Ñ Ð²Ñ€ÐµÐ¼ÐµÐ½Ð¸" -#define STR_DISABLED "Отключить" -#define STR_ENABLED_LOCAL "Включить (меÑтное)" -#define STR_ENABLED_UTC "Включить (UTC)" -#define STR_DYNAREC "ДинамичеÑкий рекомпилÑтор" +#define STR_MACHINE_TYPE "Тип машины:" +#define STR_MACHINE "СиÑÑ‚ÐµÐ¼Ð½Ð°Ñ Ð¿Ð»Ð°Ñ‚Ð°:" +#define STR_CONFIGURE "ÐаÑтройка" +#define STR_CPU_TYPE "Тип ЦП:" +#define STR_CPU_SPEED "СкороÑть:" +#define STR_FPU "FPU:" +#define STR_WAIT_STATES "Циклы ожиданиÑ:" +#define STR_MB "МБ" +#define STR_MEMORY "ПамÑть:" +#define STR_TIME_SYNC "Ð¡Ð¸Ð½Ñ…Ñ€Ð¾Ð½Ð¸Ð·Ð°Ñ†Ð¸Ñ Ð²Ñ€ÐµÐ¼ÐµÐ½Ð¸" +#define STR_DISABLED "Отключить" +#define STR_ENABLED_LOCAL "Включить (меÑтное)" +#define STR_ENABLED_UTC "Включить (UTC)" +#define STR_DYNAREC "ДинамичеÑкий рекомпилÑтор" +#define STR_SOFTFLOAT "Softfloat FPU" -#define STR_VIDEO "Видеокарта:" -#define STR_VOODOO "УÑкоритель Voodoo" +#define STR_VIDEO "Видеокарта:" +#define STR_VIDEO_2 "Видеокарта 2:" +#define STR_VOODOO "УÑкоритель Voodoo" +#define STR_IBM8514 "УÑкоритель IBM 8514/a" +#define STR_XGA "УÑкоритель XGA" -#define STR_MOUSE "Мышь:" -#define STR_JOYSTICK "ДжойÑтик:" -#define STR_JOY1 "ДжойÑтик 1..." -#define STR_JOY2 "ДжойÑтик 2..." -#define STR_JOY3 "ДжойÑтик 3..." -#define STR_JOY4 "ДжойÑтик 4..." +#define STR_MOUSE "Мышь:" +#define STR_JOYSTICK "ДжойÑтик:" +#define STR_JOY1 "ДжойÑтик 1..." +#define STR_JOY2 "ДжойÑтик 2..." +#define STR_JOY3 "ДжойÑтик 3..." +#define STR_JOY4 "ДжойÑтик 4..." -#define STR_SOUND "Ð—Ð²ÑƒÐºÐ¾Ð²Ð°Ñ ÐºÐ°Ñ€Ñ‚Ð°:" -#define STR_MIDI_OUT "MIDI Out уÑтр-во:" -#define STR_MIDI_IN "MIDI In уÑтр-во:" -#define STR_MPU401 "Отдельный MPU-401" -#define STR_SSI "Innovation SSI-2001" -#define STR_CMS "CMS / Game Blaster" -#define STR_GUS "Gravis Ultrasound" -#define STR_FLOAT "FLOAT32 звук" +#define STR_SOUND1 "Ð—Ð²ÑƒÐºÐ¾Ð²Ð°Ñ ÐºÐ°Ñ€Ñ‚Ð° 1:" +#define STR_SOUND2 "Ð—Ð²ÑƒÐºÐ¾Ð²Ð°Ñ ÐºÐ°Ñ€Ñ‚Ð° 2:" +#define STR_SOUND3 "Ð—Ð²ÑƒÐºÐ¾Ð²Ð°Ñ ÐºÐ°Ñ€Ñ‚Ð° 3:" +#define STR_SOUND4 "Ð—Ð²ÑƒÐºÐ¾Ð²Ð°Ñ ÐºÐ°Ñ€Ñ‚Ð° 4:" +#define STR_MIDI_OUT "MIDI Out уÑтр-во:" +#define STR_MIDI_IN "MIDI In уÑтр-во:" +#define STR_MPU401 "Отдельный MPU-401" +#define STR_FLOAT "FLOAT32 звук" +#define STR_FM_DRIVER "Драйвер FM-Ñинтезатора" +#define STR_FM_DRV_NUKED "Nuked (более точный)" +#define STR_FM_DRV_YMFM "YMFM (быÑтрей)" -#define STR_NET_TYPE "Тип Ñети:" -#define STR_PCAP "УÑтройÑтво PCap:" -#define STR_NET "Ð¡ÐµÑ‚ÐµÐ²Ð°Ñ ÐºÐ°Ñ€Ñ‚Ð°:" +#define STR_NET_TYPE "Тип Ñети:" +#define STR_PCAP "УÑтройÑтво PCap:" +#define STR_NET "Ð¡ÐµÑ‚ÐµÐ²Ð°Ñ ÐºÐ°Ñ€Ñ‚Ð°:" +#define STR_NET1 "Network card 1:" +#define STR_NET2 "Network card 2:" +#define STR_NET3 "Network card 3:" +#define STR_NET4 "Network card 4:" -#define STR_COM1 "УÑтройÑтво COM1:" -#define STR_COM2 "УÑтройÑтво COM2:" -#define STR_COM3 "УÑтройÑтво COM3:" -#define STR_COM4 "УÑтройÑтво COM4:" -#define STR_LPT1 "УÑтройÑтво LPT1:" -#define STR_LPT2 "УÑтройÑтво LPT2:" -#define STR_LPT3 "УÑтройÑтво LPT3:" -#define STR_LPT4 "УÑтройÑтво LPT4:" -#define STR_SERIAL1 "ПоÑледов. порт COM1" -#define STR_SERIAL2 "ПоÑледов. порт COM2" -#define STR_SERIAL3 "ПоÑледов. порт COM3" -#define STR_SERIAL4 "ПоÑледов. порт COM4" -#define STR_PARALLEL1 "Параллельный порт LPT1" -#define STR_PARALLEL2 "Параллельный порт LPT2" -#define STR_PARALLEL3 "Параллельный порт LPT3" -#define STR_PARALLEL4 "Параллельный порт LPT4" +#define STR_COM1 "УÑтройÑтво COM1:" +#define STR_COM2 "УÑтройÑтво COM2:" +#define STR_COM3 "УÑтройÑтво COM3:" +#define STR_COM4 "УÑтройÑтво COM4:" +#define STR_LPT1 "УÑтройÑтво LPT1:" +#define STR_LPT2 "УÑтройÑтво LPT2:" +#define STR_LPT3 "УÑтройÑтво LPT3:" +#define STR_LPT4 "УÑтройÑтво LPT4:" +#define STR_SERIAL1 "ПоÑледов. порт COM1" +#define STR_SERIAL2 "ПоÑледов. порт COM2" +#define STR_SERIAL3 "ПоÑледов. порт COM3" +#define STR_SERIAL4 "ПоÑледов. порт COM4" +#define STR_PARALLEL1 "Параллельный порт LPT1" +#define STR_PARALLEL2 "Параллельный порт LPT2" +#define STR_PARALLEL3 "Параллельный порт LPT3" +#define STR_PARALLEL4 "Параллельный порт LPT4" +#define STR_SERIAL_PASS1 "Serial port passthrough 1" +#define STR_SERIAL_PASS2 "Serial port passthrough 2" +#define STR_SERIAL_PASS3 "Serial port passthrough 3" +#define STR_SERIAL_PASS4 "Serial port passthrough 4" -#define STR_HDC "Контроллер HD:" -#define STR_FDC "Контроллер FD:" -#define STR_IDE_TER "Третичный IDE контроллер" -#define STR_IDE_QUA "Четвертичный IDE контроллер" -#define STR_SCSI "SCSI" -#define STR_SCSI_1 "Контроллер 1:" -#define STR_SCSI_2 "Контроллер 2:" -#define STR_SCSI_3 "Контроллер 3:" -#define STR_SCSI_4 "Контроллер 4:" -#define STR_CASSETTE "КаÑÑета" +#define STR_HDC "Контроллер HD:" +#define STR_FDC "Контроллер FD:" +#define STR_IDE_TER "Третичный IDE контроллер" +#define STR_IDE_QUA "Четвертичный IDE контроллер" +#define STR_SCSI "SCSI" +#define STR_SCSI_1 "Контроллер 1:" +#define STR_SCSI_2 "Контроллер 2:" +#define STR_SCSI_3 "Контроллер 3:" +#define STR_SCSI_4 "Контроллер 4:" +#define STR_CASSETTE "КаÑÑета" -#define STR_HDD "ЖёÑткие диÑки:" -#define STR_NEW "&Создать..." -#define STR_EXISTING "&Выбрать..." -#define STR_REMOVE "&Убрать" -#define STR_BUS "Шина:" -#define STR_CHANNEL "Канал:" -#define STR_ID "ID:" +#define STR_HDD "ЖёÑткие диÑки:" +#define STR_NEW "&Создать..." +#define STR_EXISTING "&Выбрать..." +#define STR_REMOVE "&Убрать" +#define STR_BUS "Шина:" +#define STR_CHANNEL "Канал:" +#define STR_ID "ID:" +#define STR_SPEED "Speed:" -#define STR_SPECIFY "&Указать..." -#define STR_SECTORS "Сектора:" -#define STR_HEADS "Головки:" -#define STR_CYLS "Цилиндры:" -#define STR_SIZE_MB "Размер (МБ):" -#define STR_TYPE "Тип:" -#define STR_IMG_FORMAT "Тип образа:" -#define STR_BLOCK_SIZE "Размер блока:" +#define STR_SPECIFY "&Указать..." +#define STR_SECTORS "Сектора:" +#define STR_HEADS "Головки:" +#define STR_CYLS "Цилиндры:" +#define STR_SIZE_MB "Размер (МБ):" +#define STR_TYPE "Тип:" +#define STR_IMG_FORMAT "Тип образа:" +#define STR_BLOCK_SIZE "Размер блока:" -#define STR_FLOPPY_DRIVES "Гибкие диÑки:" -#define STR_TURBO "Турбо тайминги" -#define STR_CHECKBPB "ПроверÑть BPB" -#define STR_CDROM_DRIVES "ДиÑководы CD-ROM:" -#define STR_CD_SPEED "СкороÑть:" +#define STR_FLOPPY_DRIVES "Гибкие диÑки:" +#define STR_TURBO "Турбо тайминги" +#define STR_CHECKBPB "ПроверÑть BPB" +#define STR_CDROM_DRIVES "ДиÑководы CD-ROM:" +#define STR_CD_SPEED "СкороÑть:" -#define STR_MO_DRIVES "МагнитооптичеÑкие диÑководы:" -#define STR_ZIP_DRIVES "ZIP диÑководы:" -#define STR_250 "ZIP 250" +#define STR_MO_DRIVES "МагнитооптичеÑкие диÑководы:" +#define STR_ZIP_DRIVES "ZIP диÑководы:" +#define STR_250 "ZIP 250" -#define STR_ISARTC "ISA RTC:" -#define STR_ISAMEM "Карта раÑÑˆÐ¸Ñ€ÐµÐ½Ð¸Ñ Ð¿Ð°Ð¼Ñти (ISA)" -#define STR_ISAMEM_1 "Карта 1:" -#define STR_ISAMEM_2 "Карта 2:" -#define STR_ISAMEM_3 "Карта 3:" -#define STR_ISAMEM_4 "Карта 4:" -#define STR_BUGGER "УÑтройÑтво ISABugger" -#define STR_POSTCARD "Карта POST" +#define STR_ISARTC "ISA RTC:" +#define STR_ISAMEM "Карта раÑÑˆÐ¸Ñ€ÐµÐ½Ð¸Ñ Ð¿Ð°Ð¼Ñти (ISA)" +#define STR_ISAMEM_1 "Карта 1:" +#define STR_ISAMEM_2 "Карта 2:" +#define STR_ISAMEM_3 "Карта 3:" +#define STR_ISAMEM_4 "Карта 4:" +#define STR_BUGGER "УÑтройÑтво ISABugger" +#define STR_POSTCARD "Карта POST" -#define FONT_SIZE 9 -#define FONT_NAME "Segoe UI" +#define FONT_SIZE 9 +#define FONT_NAME "Segoe UI" #include "dialogs.rc" @@ -366,194 +392,188 @@ END // String Table // -STRINGTABLE DISCARDABLE +STRINGTABLE DISCARDABLE BEGIN - 2048 "86Box" - IDS_2049 "Ошибка" - IDS_2050 "ÐеуÑÑ‚Ñ€Ð°Ð½Ð¸Ð¼Ð°Ñ Ð¾ÑˆÐ¸Ð±ÐºÐ°" - IDS_2051 " - ПÐУЗÐ" - IDS_2052 "Ðажмите Ctrl+Alt+PgDn Ð´Ð»Ñ Ð²Ð¾Ð·Ð²Ñ€Ð°Ñ‚Ð° в оконный режим." - IDS_2053 "СкороÑть" - IDS_2054 "ZIP %03i %i (%s): %ls" - IDS_2055 "Образы ZIP (*.IM?;*.ZDI)\0*.IM?;*.ZDI\0" - IDS_2056 "86Box не Ñмог найти ни одного подходÑщего Ð´Ð»Ñ Ð¸ÑÐ¿Ð¾Ð»ÑŒÐ·Ð¾Ð²Ð°Ð½Ð¸Ñ Ñ„Ð°Ð¹Ð»Ð° Ñ ÐŸÐ—Ð£.\n\nПожалуйÑта Ñкачайте набор ПЗУ и извлеките его в каталог ""roms""." - IDS_2057 "(пуÑто)" - IDS_2058 "Образы ZIP (*.IM?;*.ZDI)\0*.IM?;*.ZDI\0Ð’Ñе файлы (*.*)\0*.*\0" - IDS_2059 "Турбо" - IDS_2060 "Вкл" - IDS_2061 "Выкл" - IDS_2062 "Ð’Ñе образы (*.86F;*.DSK;*.FLP;*.IM?;*.*FD?)\0*.86F;*.DSK;*.FLP;*.IM?;*.*FD?\0ПроÑтые поÑекторные образы (*.DSK;*.FLP;*.IM?;*.*FD?)\0*.DSK;*.FLP;*.IM?;*.IMG;*.*FD?\0Surface образы (*.86F)\0*.86F\0" - IDS_2063 "СиÑÑ‚ÐµÐ¼Ð½Ð°Ñ Ð¿Ð»Ð°Ñ‚Ð° ""%hs"" недоÑтупна из-за отÑутÑÑ‚Ð²Ð¸Ñ Ñ„Ð°Ð¹Ð»Ð° её ПЗУ в каталоге roms/machines. Переключение на доÑтупную ÑиÑтемную плату." + 2048 "86Box" + IDS_2049 "Ошибка" + IDS_2050 "ÐеуÑÑ‚Ñ€Ð°Ð½Ð¸Ð¼Ð°Ñ Ð¾ÑˆÐ¸Ð±ÐºÐ°" + IDS_2051 " - ПÐУЗÐ" + IDS_2052 "Ðажмите Ctrl+Alt+PgDn Ð´Ð»Ñ Ð²Ð¾Ð·Ð²Ñ€Ð°Ñ‚Ð° в оконный режим." + IDS_2053 "СкороÑть" + IDS_2054 "ZIP %03i %i (%s): %ls" + IDS_2055 "Образы ZIP (*.IM?;*.ZDI)\0*.IM?;*.ZDI\0" + IDS_2056 "86Box не Ñмог найти ни одного подходÑщего Ð´Ð»Ñ Ð¸ÑÐ¿Ð¾Ð»ÑŒÐ·Ð¾Ð²Ð°Ð½Ð¸Ñ Ñ„Ð°Ð¹Ð»Ð° Ñ ÐŸÐ—Ð£.\n\nПожалуйÑта Ñкачайте набор ПЗУ и извлеките его в каталог ""roms""." + IDS_2057 "(пуÑто)" + IDS_2058 "Образы ZIP (*.IM?;*.ZDI)\0*.IM?;*.ZDI\0Ð’Ñе файлы (*.*)\0*.*\0" + IDS_2059 "Турбо" + IDS_2060 "Вкл" + IDS_2061 "Выкл" + IDS_2062 "Ð’Ñе образы (*.86F;*.DSK;*.FLP;*.IM?;*.*FD?)\0*.86F;*.DSK;*.FLP;*.IM?;*.*FD?\0ПроÑтые поÑекторные образы (*.DSK;*.FLP;*.IM?;*.*FD?)\0*.DSK;*.FLP;*.IM?;*.IMG;*.*FD?\0Surface образы (*.86F)\0*.86F\0" + IDS_2063 "СиÑÑ‚ÐµÐ¼Ð½Ð°Ñ Ð¿Ð»Ð°Ñ‚Ð° ""%hs"" недоÑтупна из-за отÑутÑÑ‚Ð²Ð¸Ñ Ñ„Ð°Ð¹Ð»Ð° её ПЗУ в каталоге roms/machines. Переключение на доÑтупную ÑиÑтемную плату." END -STRINGTABLE DISCARDABLE +STRINGTABLE DISCARDABLE BEGIN - IDS_2064 "Видеокарта ""%hs"" недоÑтупна из-за отÑутÑÑ‚Ð²Ð¸Ñ Ñ„Ð°Ð¹Ð»Ð° её ПЗУ в каталоге roms/video. Переключение на доÑтупную видеокарту." - IDS_2065 "Компьютер" - IDS_2066 "ДиÑплей" - IDS_2067 "УÑтройÑтва ввода" - IDS_2068 "Звук" - IDS_2069 "Сеть" - IDS_2070 "Порты (COM и LPT)" - IDS_2071 "Контроллеры диÑков" - IDS_2072 "ЖёÑткие диÑки" - IDS_2073 "Гибкие диÑки и CD-ROM" - IDS_2074 "Другие Ñъёмные уÑтр-ва" - IDS_2075 "Ð”Ñ€ÑƒÐ³Ð°Ñ Ð¿ÐµÑ€Ð¸Ñ„ÐµÑ€Ð¸Ñ" - IDS_2076 "Образы Surface (*.86F)\0*.86F\0" - IDS_2077 "Щёлкните мышью Ð´Ð»Ñ Ð·Ð°Ñ…Ð²Ð°Ñ‚Ð° курÑора" - IDS_2078 "Ðажмите F8+F12 чтобы оÑвободить курÑор" - IDS_2079 "Ðажмите F8+F12 или Ñреднюю кнопку мыши чтобы оÑвободить курÑор" + IDS_2064 "Видеокарта ""%hs"" недоÑтупна из-за отÑутÑÑ‚Ð²Ð¸Ñ Ñ„Ð°Ð¹Ð»Ð° её ПЗУ в каталоге roms/video. Переключение на доÑтупную видеокарту." + IDS_2065 "Компьютер" + IDS_2066 "ДиÑплей" + IDS_2067 "УÑтройÑтва ввода" + IDS_2068 "Звук" + IDS_2069 "Сеть" + IDS_2070 "Порты (COM и LPT)" + IDS_2071 "Контроллеры диÑков" + IDS_2072 "ЖёÑткие диÑки" + IDS_2073 "Гибкие диÑки и CD-ROM" + IDS_2074 "Другие Ñъёмные уÑтр-ва" + IDS_2075 "Ð”Ñ€ÑƒÐ³Ð°Ñ Ð¿ÐµÑ€Ð¸Ñ„ÐµÑ€Ð¸Ñ" + IDS_2076 "Образы Surface (*.86F)\0*.86F\0" + IDS_2077 "Щёлкните мышью Ð´Ð»Ñ Ð·Ð°Ñ…Ð²Ð°Ñ‚Ð° курÑора" + IDS_2078 "Ðажмите F8+F12 чтобы оÑвободить курÑор" + IDS_2079 "Ðажмите F8+F12 или Ñреднюю кнопку мыши чтобы оÑвободить курÑор" END -STRINGTABLE DISCARDABLE +STRINGTABLE DISCARDABLE BEGIN - IDS_2080 "Ðевозможно инициализировать FluidSynth" - IDS_2081 "Шина" - IDS_2082 "Файл" - IDS_2083 "C" - IDS_2084 "H" - IDS_2085 "S" - IDS_2086 "МБ" - IDS_2087 "ПроверÑть BPB" - IDS_2088 "КБ" - IDS_2089 "Ðе удалоÑÑŒ инициализировать рендерер видео." - IDS_2090 "По умолчанию" - IDS_2091 "%i WS" - IDS_2092 "Тип" - IDS_2093 "Ðе удалоÑÑŒ наÑтроить PCap" - IDS_2094 "УÑтройÑтва PCap не найдены" - IDS_2095 "Ðеверное уÑтройÑтво PCap" - IDS_2096 "Стандартный 2-кнопочный джойÑтик" - IDS_2097 "Стандартный 4-кнопочный джойÑтик" - IDS_2098 "Стандартный 6-кнопочный джойÑтик" - IDS_2099 "Стандартный 8-кнопочный джойÑтик" - IDS_2100 "CH Flightstick Pro" - IDS_2101 "Microsoft SideWinder Pad" - IDS_2102 "СиÑтема ÑƒÐ¿Ñ€Ð°Ð²Ð»ÐµÐ½Ð¸Ñ Ð¿Ð¾Ð»ÐµÑ‚Ð¾Ð¼ Thrustmaster" - IDS_2103 "Ðет" - IDS_2104 "Ðевозможно загрузить уÑкорители клавиатуры." - IDS_2105 "Ðевозможно зарегиÑтрировать необработанный (RAW) ввод." - IDS_2106 "%u" - IDS_2107 "%u МБ (CHS: %i, %i, %i)" - IDS_2108 "ДиÑковод %i (%s): %ls" - IDS_2109 "Ð’Ñе образы (*.0??;*.1??;*.??0;*.86F;*.BIN;*.CQ?;*.D??;*.FLP;*.HDM;*.IM?;*.JSON;*.TD0;*.*FD?;*.MFM;*.XDF)\0*.0??;*.1??;*.??0;*.86F;*.BIN;*.CQ?;*.D??;*.FLP;*.HDM;*.IM?;*.JSON;*.TD0;*.*FD?;*.MFM;*.XDF\0РаÑширенные образы Ñекторов (*.IMD;*.JSON;*.TD0)\0*.IMD;*.JSON;*.TD0\0ОÑновные образы Ñекторов (*.0??;*.1??;*.??0;*.BIN;*.CQ?;*.D??;*.FLP;*.HDM;*.IM?;*.XDF;*.*FD?)\0*.0??;*.1??;*.??0;*.BIN;*.CQ?;*.D??;*.FLP;*.HDM;*.IM?;*.XDF;*.*FD?\0Образы Flux (*.FDI)\0*.FDI\0Образы Surface (*.86F;*.MFM)\0*.86F;*.MFM\0Ð’Ñе файлы (*.*)\0*.*\0" - IDS_2110 "Ðевозможно инициализировать FreeType" - IDS_2111 "Ðевозможно инициализировать SDL, требуетÑÑ SDL2.dll" - IDS_2112 "Ð’Ñ‹ уверены, что хотите выполнить холодную перезагрузку Ñмулируемой машины?" - IDS_2113 "Ð’Ñ‹ уверены, что хотите выйти из 86Box?" - IDS_2114 "Ðевозможно инициализировать Ghostscript" - IDS_2115 "МагнитооптичеÑкий %i (%ls): %ls" - IDS_2116 "Образы магнитооптичеÑких диÑков (*.IM?;*.MDI)\0*.IM?;*.MDI\0Ð’Ñе файлы (*.*)\0*.*\0" - IDS_2117 "Добро пожаловать в 86Box!" - IDS_2118 "Ð’Ñтроенный контроллер" - IDS_2119 "Выход" - IDS_2120 "ПЗУ не найдены" - IDS_2121 "Хотите ли вы Ñохранить наÑтройки?" - IDS_2122 "Это приведет к холодной перезагрузке Ñмулируемой машины." - IDS_2123 "Сохранить" - IDS_2124 "О 86Box" - IDS_2125 "86Box v." EMU_VERSION + IDS_2081 "Шина" + IDS_2082 "Файл" + IDS_2083 "C" + IDS_2084 "H" + IDS_2085 "S" + IDS_2086 "МБ" + IDS_2087 "Speed" + IDS_2088 "ПроверÑть BPB" + IDS_2089 "КБ" + IDS_2090 "Ðе удалоÑÑŒ инициализировать рендерер видео." + IDS_2091 "По умолчанию" + IDS_2092 "%i WS" + IDS_2093 "Тип" + IDS_2094 "Ðе удалоÑÑŒ наÑтроить PCap" + IDS_2095 "УÑтройÑтва PCap не найдены" + IDS_2096 "Ðеверное уÑтройÑтво PCap" + IDS_2097 "Стандартный 2-кнопочный джойÑтик" + IDS_2098 "Стандартный 4-кнопочный джойÑтик" + IDS_2099 "Стандартный 6-кнопочный джойÑтик" + IDS_2100 "Стандартный 8-кнопочный джойÑтик" + IDS_2101 "CH Flightstick Pro" + IDS_2102 "Microsoft SideWinder Pad" + IDS_2103 "СиÑтема ÑƒÐ¿Ñ€Ð°Ð²Ð»ÐµÐ½Ð¸Ñ Ð¿Ð¾Ð»ÐµÑ‚Ð¾Ð¼ Thrustmaster" + IDS_2104 "Ðет" + IDS_2105 "Ðевозможно загрузить уÑкорители клавиатуры." + IDS_2106 "Ðевозможно зарегиÑтрировать необработанный (RAW) ввод." + IDS_2107 "%u" + IDS_2108 "%u МБ (CHS: %i, %i, %i)" + IDS_2109 "ДиÑковод %i (%s): %ls" + IDS_2110 "Ð’Ñе образы (*.0??;*.1??;*.??0;*.86F;*.BIN;*.CQ?;*.D??;*.FLP;*.HDM;*.IM?;*.JSON;*.TD0;*.*FD?;*.MFM;*.XDF)\0*.0??;*.1??;*.??0;*.86F;*.BIN;*.CQ?;*.D??;*.FLP;*.HDM;*.IM?;*.JSON;*.TD0;*.*FD?;*.MFM;*.XDF\0РаÑширенные образы Ñекторов (*.IMD;*.JSON;*.TD0)\0*.IMD;*.JSON;*.TD0\0ОÑновные образы Ñекторов (*.0??;*.1??;*.??0;*.BIN;*.CQ?;*.D??;*.FLP;*.HDM;*.IM?;*.XDF;*.*FD?)\0*.0??;*.1??;*.??0;*.BIN;*.CQ?;*.D??;*.FLP;*.HDM;*.IM?;*.XDF;*.*FD?\0Образы Flux (*.FDI)\0*.FDI\0Образы Surface (*.86F;*.MFM)\0*.86F;*.MFM\0Ð’Ñе файлы (*.*)\0*.*\0" + IDS_2112 "Ðевозможно инициализировать SDL, требуетÑÑ SDL2.dll" + IDS_2113 "Ð’Ñ‹ уверены, что хотите выполнить холодную перезагрузку Ñмулируемой машины?" + IDS_2114 "Ð’Ñ‹ уверены, что хотите выйти из 86Box?" + IDS_2115 "Ðевозможно инициализировать Ghostscript" + IDS_2116 "МагнитооптичеÑкий %i (%ls): %ls" + IDS_2117 "Образы магнитооптичеÑких диÑков (*.IM?;*.MDI)\0*.IM?;*.MDI\0Ð’Ñе файлы (*.*)\0*.*\0" + IDS_2118 "Добро пожаловать в 86Box!" + IDS_2119 "Ð’Ñтроенный контроллер" + IDS_2120 "Выход" + IDS_2121 "ПЗУ не найдены" + IDS_2122 "Хотите ли вы Ñохранить наÑтройки?" + IDS_2123 "Это приведет к холодной перезагрузке Ñмулируемой машины." + IDS_2124 "Сохранить" + IDS_2125 "О 86Box" + IDS_2126 "86Box v." EMU_VERSION - IDS_2126 "ЭмулÑтор Ñтарых компьютеров\n\nÐвторы: Sarah Walker, Miran Grca, Fred N. van Kempen (waltje), SA1988, Tiseno100, reenigne, leilei, JohnElliott, greatpsycho, and others.\n\nВыпуÑкаетÑÑ Ð¿Ð¾Ð´ лицензией GNU General Public License верÑии 2 или более поздней. Дополнительную информацию Ñм. в файле LICENSE." - IDS_2127 "OK" - IDS_2128 "Оборудование недоÑтупно" + IDS_2127 "ЭмулÑтор Ñтарых компьютеров\n\nÐвторы: Miran GrÄa (OBattler), RichardG867, Jasmine Iwanek, TC1995, coldbrewed, Teemu Korhonen (Manaatti), Joakim L. Gilje, Adrien Moulin (elyosh), Daniel Balsom (gloriouscow), Cacodemon345, Fred N. van Kempen (waltje), Tiseno100, reenigne, and others.\n\nWith previous core contributions from Sarah Walker, leilei, JohnElliott, greatpsycho, and others.\n\nВыпуÑкаетÑÑ Ð¿Ð¾Ð´ лицензией GNU General Public License верÑии 2 или более поздней. Дополнительную информацию Ñм. в файле LICENSE." + IDS_2128 "OK" + IDS_2129 "Оборудование недоÑтупно" #ifdef _WIN32 #define LIB_NAME_PCAP "WinPcap" #else #define LIB_NAME_PCAP "libpcap" #endif - IDS_2129 "УбедитеÑÑŒ, что " LIB_NAME_PCAP " уÑтановлен и ваше Ñетевое Ñоединение, ÑовмеÑтимо Ñ " LIB_NAME_PCAP "." - IDS_2130 "ÐедопуÑÑ‚Ð¸Ð¼Ð°Ñ ÐºÐ¾Ð½Ñ„Ð¸Ð³ÑƒÑ€Ð°Ñ†Ð¸Ñ" -#ifdef _WIN32 -#define LIB_NAME_FREETYPE "freetype.dll" -#else -#define LIB_NAME_FREETYPE "libfreetype" -#endif - IDS_2131 "Ð”Ð»Ñ ÑмулÑции принтера ESC/P требуетÑÑ " LIB_NAME_FREETYPE "." + IDS_2130 "УбедитеÑÑŒ, что " LIB_NAME_PCAP " уÑтановлен и ваше Ñетевое Ñоединение, ÑовмеÑтимо Ñ " LIB_NAME_PCAP "." + IDS_2131 "ÐедопуÑÑ‚Ð¸Ð¼Ð°Ñ ÐºÐ¾Ð½Ñ„Ð¸Ð³ÑƒÑ€Ð°Ñ†Ð¸Ñ" #ifdef _WIN32 #define LIB_NAME_GS "gsdll32.dll" #else #define LIB_NAME_GS "libgs" #endif - IDS_2132 LIB_NAME_GS " требуетÑÑ Ð´Ð»Ñ Ð°Ð²Ñ‚Ð¾Ð¼Ð°Ñ‚Ð¸Ñ‡ÐµÑкого Ð¿Ñ€ÐµÐ¾Ð±Ñ€Ð°Ð·Ð¾Ð²Ð°Ð½Ð¸Ñ Ñ„Ð°Ð¹Ð»Ð¾Ð² PostScript в PDF.\n\nÐ’Ñе документы, отправленные на общий принтер PostScript, будут Ñохранены в виде файлов PostScript (.ps)." -#ifdef _WIN32 -#define LIB_NAME_FLUIDSYNTH "libfluidsynth.dll" -#else -#define LIB_NAME_FLUIDSYNTH "libfluidsynth" -#endif - IDS_2133 "Ð”Ð»Ñ FluidSynth MIDI-вывода требуетÑÑ " LIB_NAME_FLUIDSYNTH "." - IDS_2134 "Вход в полноÑкранный режим" - IDS_2135 "Больше не показывать Ñто Ñообщение" - IDS_2136 "Ðе выходить" - IDS_2137 "Перезагрузить" - IDS_2138 "Ðе перезагружать" - IDS_2139 "Образы магнитооптичеÑких диÑков (*.IM?;*.MDI)\0*.IM?;*.MDI\0Ð’Ñе файлы (*.*)\0*.*\0" - IDS_2140 "Образы CD-ROM (*.ISO;*.CUE)\0*.ISO;*.CUE\0Ð’Ñе файлы (*.*)\0*.*\0" - IDS_2141 "ÐšÐ¾Ð½Ñ„Ð¸Ð³ÑƒÑ€Ð°Ñ†Ð¸Ñ ÑƒÑтройÑтва %hs" - IDS_2142 "Монитор в ÑпÑщем режиме" - IDS_2143 "Шейдеры OpenGL (*.GLSL)\0*.GLSL\0Ð’Ñе файлы (*.*)\0*.*\0" - IDS_2144 "Параметры OpenGL" - IDS_2145 "Ð’Ñ‹ загружаете неподдерживаемую конфигурацию" - IDS_2146 "Выбор типов ЦП Ð´Ð»Ñ Ñтой ÑиÑтемной платы на данной Ñмулируемой машине отключен.\n\nЭто позволÑет выбрать процеÑÑор, который в противном Ñлучае неÑовмеÑтим Ñ Ð²Ñ‹Ð±Ñ€Ð°Ð½Ð½Ð¾Ð¹ материнÑкой платой. Однако, вы можете ÑтолкнутьÑÑ Ñ Ð½ÐµÑовмеÑтимоÑтью Ñ BIOS материнÑкой платы или другим ПО.\n\nВключение Ñтого параметра официально не поддерживаетÑÑ, и вÑе поданные отчеты об ошибках могут быть закрыты как недейÑтвительные." - IDS_2147 "Продолжить" - IDS_2148 "КаÑÑета: %s" - IDS_2149 "Образы каÑÑет (*.PCM;*.RAW;*.WAV;*.CAS)\0*.PCM;*.RAW;*.WAV;*.CAS\0Ð’Ñе файлы (*.*)\0*.*\0" - IDS_2150 "Картридж %i: %ls" - IDS_2151 "Образы картриджей (*.A;*.B;*.JRC)\0*.A;*.B;*.JRC\0Ð’Ñе файлы (*.*)\0*.*\0" - IDS_2152 "Ошибка инициализации рендерера" - IDS_2153 "Ðевозможно инициализировать рендерер OpenGL (3.0). ПожалуйÑта, иÑпользуйте другой рендерер." - IDS_2154 "Возобновить выполнение" - IDS_2155 "ПриоÑтановить выполнение" - IDS_2156 "Ðажать Ctrl+Alt+Del" - IDS_2157 "Ðажать Ctrl+Alt+Esc" - IDS_2158 "Ð¥Ð¾Ð»Ð¾Ð´Ð½Ð°Ñ Ð¿ÐµÑ€ÐµÐ·Ð°Ð³Ñ€ÑƒÐ·ÐºÐ°" - IDS_2159 "Сигнал Ð·Ð°Ð²ÐµÑ€ÑˆÐµÐ½Ð¸Ñ ACPI" - IDS_2160 "ÐаÑтройки машины" + IDS_2133 LIB_NAME_GS " требуетÑÑ Ð´Ð»Ñ Ð°Ð²Ñ‚Ð¾Ð¼Ð°Ñ‚Ð¸Ñ‡ÐµÑкого Ð¿Ñ€ÐµÐ¾Ð±Ñ€Ð°Ð·Ð¾Ð²Ð°Ð½Ð¸Ñ Ñ„Ð°Ð¹Ð»Ð¾Ð² PostScript в PDF.\n\nÐ’Ñе документы, отправленные на общий принтер PostScript, будут Ñохранены в виде файлов PostScript (.ps)." + IDS_2135 "Вход в полноÑкранный режим" + IDS_2136 "Больше не показывать Ñто Ñообщение" + IDS_2137 "Ðе выходить" + IDS_2138 "Перезагрузить" + IDS_2139 "Ðе перезагружать" + IDS_2140 "Образы магнитооптичеÑких диÑков (*.IM?;*.MDI)\0*.IM?;*.MDI\0Ð’Ñе файлы (*.*)\0*.*\0" + IDS_2141 "Образы CD-ROM (*.ISO;*.CUE)\0*.ISO;*.CUE\0Ð’Ñе файлы (*.*)\0*.*\0" + IDS_2142 "ÐšÐ¾Ð½Ñ„Ð¸Ð³ÑƒÑ€Ð°Ñ†Ð¸Ñ ÑƒÑтройÑтва %hs" + IDS_2143 "Монитор в ÑпÑщем режиме" + IDS_2144 "Шейдеры OpenGL (*.GLSL)\0*.GLSL\0Ð’Ñе файлы (*.*)\0*.*\0" + IDS_2145 "Параметры OpenGL" + IDS_2146 "Ð’Ñ‹ загружаете неподдерживаемую конфигурацию" + IDS_2147 "Выбор типов ЦП Ð´Ð»Ñ Ñтой ÑиÑтемной платы на данной Ñмулируемой машине отключен.\n\nЭто позволÑет выбрать процеÑÑор, который в противном Ñлучае неÑовмеÑтим Ñ Ð²Ñ‹Ð±Ñ€Ð°Ð½Ð½Ð¾Ð¹ материнÑкой платой. Однако, вы можете ÑтолкнутьÑÑ Ñ Ð½ÐµÑовмеÑтимоÑтью Ñ BIOS материнÑкой платы или другим ПО.\n\nВключение Ñтого параметра официально не поддерживаетÑÑ, и вÑе поданные отчеты об ошибках могут быть закрыты как недейÑтвительные." + IDS_2148 "Продолжить" + IDS_2149 "КаÑÑета: %s" + IDS_2150 "Образы каÑÑет (*.PCM;*.RAW;*.WAV;*.CAS)\0*.PCM;*.RAW;*.WAV;*.CAS\0Ð’Ñе файлы (*.*)\0*.*\0" + IDS_2151 "Картридж %i: %ls" + IDS_2152 "Образы картриджей (*.A;*.B;*.JRC)\0*.A;*.B;*.JRC\0Ð’Ñе файлы (*.*)\0*.*\0" + IDS_2153 "Ошибка инициализации рендерера" + IDS_2154 "Ðевозможно инициализировать рендерер OpenGL (3.0). ПожалуйÑта, иÑпользуйте другой рендерер." + IDS_2155 "Возобновить выполнение" + IDS_2156 "ПриоÑтановить выполнение" + IDS_2157 "Ðажать Ctrl+Alt+Del" + IDS_2158 "Ðажать Ctrl+Alt+Esc" + IDS_2159 "Ð¥Ð¾Ð»Ð¾Ð´Ð½Ð°Ñ Ð¿ÐµÑ€ÐµÐ·Ð°Ð³Ñ€ÑƒÐ·ÐºÐ°" + IDS_2160 "Сигнал Ð·Ð°Ð²ÐµÑ€ÑˆÐµÐ½Ð¸Ñ ACPI" + IDS_2161 "ÐаÑтройки машины" + IDS_2162 "Type" + IDS_2163 "No Dynarec" + IDS_2164 "Old Dynarec" + IDS_2165 "New Dynarec" + IDS_2166 "Video card #2 ""%hs"" is not available due to missing ROMs in the roms/video directory. Disabling the second video card." + IDS_2167 "Failed to initialize network driver" + IDS_2168 "The network configuration will be switched to the null driver" END -STRINGTABLE DISCARDABLE +STRINGTABLE DISCARDABLE BEGIN IDS_4096 "ЖёÑткий диÑк (%s)" - IDS_4097 "%01i:%01i" - IDS_4098 "%01i" - IDS_4099 "MFM/RLL или ESDI диÑководов CD-ROM никогда не ÑущеÑтвовало" - IDS_4100 "Задать вручную..." - IDS_4101 "Задать вручную (large)..." - IDS_4102 "Создать новый жёÑткий диÑк" - IDS_4103 "Выбрать ÑущеÑтвующий жёÑткий диÑк" - IDS_4104 "Размер образов диÑков HDI не может превышать 4 ГБ." - IDS_4105 "Размер образов диÑков не может превышать 127 ГБ." - IDS_4106 "Образы жёÑтких диÑков (*.HD?;*.IM?;*.VHD)\0*.HD?;*.IM?;*.VHD\0Ð’Ñе файлы (*.*)\0*.*\0" - IDS_4107 "Ðевозможно прочитать файл" - IDS_4108 "Ðевозможно запиÑать файл" - IDS_4109 "Образы HDI или HDX Ñ Ñ€Ð°Ð·Ð¼ÐµÑ€Ð¾Ð¼ Ñектора, отличным от 512, не поддерживаютÑÑ." - IDS_4110 "USB пока не поддерживаетÑÑ" - IDS_4111 "Файл образа диÑка уже ÑущеÑтвует" - IDS_4112 "ПожалуйÑта, укажите правильное Ð¸Ð¼Ñ Ñ„Ð°Ð¹Ð»Ð°." - IDS_4113 "Образ диÑка Ñоздан" - IDS_4114 "УбедитеÑÑŒ, что файл ÑущеÑтвует и доÑтупен Ð´Ð»Ñ Ñ‡Ñ‚ÐµÐ½Ð¸Ñ." - IDS_4115 "УбедитеÑÑŒ, что файл ÑохранÑетÑÑ Ð² директории доÑтупной Ð´Ð»Ñ Ð·Ð°Ð¿Ð¸Ñи." - IDS_4116 "Слишком большой образ диÑка" - IDS_4117 "Ðе забудьте разметить и отформатировать вновь Ñозданный диÑк." - IDS_4118 "Выбранный файл будет перезапиÑан. Ð’Ñ‹ уверены, что хотите иÑпользовать его?" - IDS_4119 "Ðеподдерживаемый образ диÑка" - IDS_4120 "ПерезапиÑать" - IDS_4121 "Ðе перезапиÑывать" - IDS_4122 "RAW образ (.img)" - IDS_4123 "Образ HDI (.hdi)" - IDS_4124 "Образ HDX (.hdx)" - IDS_4125 "VHD фикÑированного размера (.vhd)" - IDS_4126 "VHD динамичеÑкого размера (.vhd)" - IDS_4127 "Дифференцированный образ VHD (.vhd)" - IDS_4128 "Большие блоки (2 МБ)" - IDS_4129 "Маленькие блоки (512 КБ)" - IDS_4130 "Файлы VHD (*.VHD)\0*.VHD\0Ð’Ñе файлы (*.*)\0*.*\0" - IDS_4131 "Выберите родительÑкий VHD" - IDS_4132 "Это может означать, что родительÑкий образ был изменён поÑле того, как был Ñоздан дифференцированный образ.\n\nЭто также может произойти, еÑли файлы образа были перемещены или Ñкопированы, или из-за ошибки в программе, Ñоздавшей Ñтот диÑк.\n\nÐ’Ñ‹ хотите иÑправить временные метки?" - IDS_4133 "Временные метки родительÑкого и дочернего диÑков не Ñовпадают" - IDS_4134 "Ðе удалоÑÑŒ иÑправить временную метку VHD." - IDS_4135 "%01i:%02i" + IDS_4097 "%01i:%01i" + IDS_4098 "%01i" + IDS_4099 "MFM/RLL или ESDI диÑководов CD-ROM никогда не ÑущеÑтвовало" + IDS_4100 "Задать вручную..." + IDS_4101 "Задать вручную (large)..." + IDS_4102 "Создать новый жёÑткий диÑк" + IDS_4103 "Выбрать ÑущеÑтвующий жёÑткий диÑк" + IDS_4104 "Размер образов диÑков HDI не может превышать 4 ГБ." + IDS_4105 "Размер образов диÑков не может превышать 127 ГБ." + IDS_4106 "Образы жёÑтких диÑков (*.HD?;*.IM?;*.VHD)\0*.HD?;*.IM?;*.VHD\0Ð’Ñе файлы (*.*)\0*.*\0" + IDS_4107 "Ðевозможно прочитать файл" + IDS_4108 "Ðевозможно запиÑать файл" + IDS_4109 "Образы HDI или HDX Ñ Ñ€Ð°Ð·Ð¼ÐµÑ€Ð¾Ð¼ Ñектора, отличным от 512, не поддерживаютÑÑ." + IDS_4110 "USB пока не поддерживаетÑÑ" + IDS_4111 "Файл образа диÑка уже ÑущеÑтвует" + IDS_4112 "ПожалуйÑта, укажите правильное Ð¸Ð¼Ñ Ñ„Ð°Ð¹Ð»Ð°." + IDS_4113 "Образ диÑка Ñоздан" + IDS_4114 "УбедитеÑÑŒ, что файл ÑущеÑтвует и доÑтупен Ð´Ð»Ñ Ñ‡Ñ‚ÐµÐ½Ð¸Ñ." + IDS_4115 "УбедитеÑÑŒ, что файл ÑохранÑетÑÑ Ð² директории доÑтупной Ð´Ð»Ñ Ð·Ð°Ð¿Ð¸Ñи." + IDS_4116 "Слишком большой образ диÑка" + IDS_4117 "Ðе забудьте разметить и отформатировать вновь Ñозданный диÑк." + IDS_4118 "Выбранный файл будет перезапиÑан. Ð’Ñ‹ уверены, что хотите иÑпользовать его?" + IDS_4119 "Ðеподдерживаемый образ диÑка" + IDS_4120 "ПерезапиÑать" + IDS_4121 "Ðе перезапиÑывать" + IDS_4122 "RAW образ (.img)" + IDS_4123 "Образ HDI (.hdi)" + IDS_4124 "Образ HDX (.hdx)" + IDS_4125 "VHD фикÑированного размера (.vhd)" + IDS_4126 "VHD динамичеÑкого размера (.vhd)" + IDS_4127 "Дифференцированный образ VHD (.vhd)" + IDS_4128 "Большие блоки (2 МБ)" + IDS_4129 "Маленькие блоки (512 КБ)" + IDS_4130 "Файлы VHD (*.VHD)\0*.VHD\0Ð’Ñе файлы (*.*)\0*.*\0" + IDS_4131 "Выберите родительÑкий VHD" + IDS_4132 "Это может означать, что родительÑкий образ был изменён поÑле того, как был Ñоздан дифференцированный образ.\n\nЭто также может произойти, еÑли файлы образа были перемещены или Ñкопированы, или из-за ошибки в программе, Ñоздавшей Ñтот диÑк.\n\nÐ’Ñ‹ хотите иÑправить временные метки?" + IDS_4133 "Временные метки родительÑкого и дочернего диÑков не Ñовпадают" + IDS_4134 "Ðе удалоÑÑŒ иÑправить временную метку VHD." + IDS_4135 "%01i:%02i" IDS_4352 "MFM/RLL" IDS_4353 "XTA" @@ -562,56 +582,56 @@ BEGIN IDS_4356 "ATAPI" IDS_4357 "SCSI" - IDS_4608 "MFM/RLL (%01i:%01i)" - IDS_4609 "XTA (%01i:%01i)" - IDS_4610 "ESDI (%01i:%01i)" - IDS_4611 "IDE (%01i:%01i)" - IDS_4612 "ATAPI (%01i:%01i)" - IDS_4613 "SCSI (%01i:%02i)" + IDS_4608 "MFM/RLL (%01i:%01i)" + IDS_4609 "XTA (%01i:%01i)" + IDS_4610 "ESDI (%01i:%01i)" + IDS_4611 "IDE (%01i:%01i)" + IDS_4612 "ATAPI (%01i:%01i)" + IDS_4613 "SCSI (%01i:%02i)" - IDS_5120 "CD-ROM %i (%s): %s" + IDS_5120 "CD-ROM %i (%s): %s" - IDS_5376 "Отключён" - IDS_5381 "ATAPI" + IDS_5376 "Отключён" + IDS_5381 "ATAPI" IDS_5382 "SCSI" - IDS_5632 "Отключён" - IDS_5637 "ATAPI (%01i:%01i)" + IDS_5632 "Отключён" + IDS_5637 "ATAPI (%01i:%01i)" IDS_5638 "SCSI (%01i:%02i)" - IDS_5888 "160 кБ" - IDS_5889 "180 кБ" - IDS_5890 "320 кБ" - IDS_5891 "360 кБ" - IDS_5892 "640 кБ" - IDS_5893 "720 кБ" - IDS_5894 "1.2 МБ" - IDS_5895 "1.25 МБ" - IDS_5896 "1.44 МБ" - IDS_5897 "DMF (клаÑтер 1024)" - IDS_5898 "DMF (клаÑтер 2048)" - IDS_5899 "2.88 МБ" - IDS_5900 "ZIP 100" - IDS_5901 "ZIP 250" - IDS_5902 "3.5"" 128 МБ (ISO 10090)" - IDS_5903 "3.5"" 230 МБ (ISO 13963)" - IDS_5904 "3.5"" 540 МБ (ISO 15498)" - IDS_5905 "3.5"" 640 МБ (ISO 15498)" - IDS_5906 "3.5"" 1.3 ГБ (GigaMO)" - IDS_5907 "3.5"" 2.3 ГБ (GigaMO 2)" - IDS_5908 "5.25"" 600 МБ" - IDS_5909 "5.25"" 650 МБ" - IDS_5910 "5.25"" 1 ГБ" - IDS_5911 "5.25"" 1.3 ГБ" + IDS_5888 "160 кБ" + IDS_5889 "180 кБ" + IDS_5890 "320 кБ" + IDS_5891 "360 кБ" + IDS_5892 "640 кБ" + IDS_5893 "720 кБ" + IDS_5894 "1.2 МБ" + IDS_5895 "1.25 МБ" + IDS_5896 "1.44 МБ" + IDS_5897 "DMF (клаÑтер 1024)" + IDS_5898 "DMF (клаÑтер 2048)" + IDS_5899 "2.88 МБ" + IDS_5900 "ZIP 100" + IDS_5901 "ZIP 250" + IDS_5902 "3.5"" 128 МБ (ISO 10090)" + IDS_5903 "3.5"" 230 МБ (ISO 13963)" + IDS_5904 "3.5"" 540 МБ (ISO 15498)" + IDS_5905 "3.5"" 640 МБ (ISO 15498)" + IDS_5906 "3.5"" 1.3 ГБ (GigaMO)" + IDS_5907 "3.5"" 2.3 ГБ (GigaMO 2)" + IDS_5908 "5.25"" 600 МБ" + IDS_5909 "5.25"" 650 МБ" + IDS_5910 "5.25"" 1 ГБ" + IDS_5911 "5.25"" 1.3 ГБ" - IDS_6144 "Точный RPM" - IDS_6145 "Ðа 1% медленнее точного RPM" - IDS_6146 "Ðа 1.5% медленнее точного RPM" - IDS_6147 "Ðа 2% медленнее точного RPM" + IDS_6144 "Точный RPM" + IDS_6145 "Ðа 1% медленнее точного RPM" + IDS_6146 "Ðа 1.5% медленнее точного RPM" + IDS_6147 "Ðа 2% медленнее точного RPM" - IDS_7168 "(СиÑтемный)" + IDS_7168 "(СиÑтемный)" END -#define IDS_LANG_ENUS IDS_7168 +#define IDS_LANG_ENUS IDS_7168 // Russian resources ///////////////////////////////////////////////////////////////////////////// diff --git a/src/win/languages/sl-SI.rc b/src/win/languages/sl-SI.rc index 008b1a2c6..b3a00c9de 100644 --- a/src/win/languages/sl-SI.rc +++ b/src/win/languages/sl-SI.rc @@ -13,113 +13,122 @@ LANGUAGE LANG_SLOVENIAN, SUBLANG_DEFAULT // Menu // -MainMenu MENU DISCARDABLE +MainMenu MENU DISCARDABLE BEGIN POPUP "&Dejanja" BEGIN - MENUITEM "&Tipkovnica potrebuje zajem", IDM_ACTION_KBD_REQ_CAPTURE - MENUITEM "&Desni CTRL je levi ALT", IDM_ACTION_RCTRL_IS_LALT + MENUITEM "&Tipkovnica potrebuje zajem", IDM_ACTION_KBD_REQ_CAPTURE + MENUITEM "&Desni CTRL je levi ALT", IDM_ACTION_RCTRL_IS_LALT MENUITEM SEPARATOR - MENUITEM "&Ponovni zagon...", IDM_ACTION_HRESET - MENUITEM "&Ctrl+Alt+Del\tCtrl+F12", IDM_ACTION_RESET_CAD + MENUITEM "&Ponovni zagon...", IDM_ACTION_HRESET + MENUITEM "&Ctrl+Alt+Del\tCtrl+F12", IDM_ACTION_RESET_CAD MENUITEM SEPARATOR - MENUITEM "Ctrl+Alt+&Esc", IDM_ACTION_CTRL_ALT_ESC + MENUITEM "Ctrl+Alt+&Esc", IDM_ACTION_CTRL_ALT_ESC MENUITEM SEPARATOR - MENUITEM "&Premor", IDM_ACTION_PAUSE + MENUITEM "&Premor", IDM_ACTION_PAUSE MENUITEM SEPARATOR - MENUITEM "Iz&hod...", IDM_ACTION_EXIT + MENUITEM "Iz&hod...", IDM_ACTION_EXIT END POPUP "&Pogled" BEGIN - MENUITEM "&Skrij statusno vrstico", IDM_VID_HIDE_STATUS_BAR - MENUITEM "Hide &toolbar", IDM_VID_HIDE_TOOLBAR + MENUITEM "&Skrij statusno vrstico", IDM_VID_HIDE_STATUS_BAR + MENUITEM "Hide &toolbar", IDM_VID_HIDE_TOOLBAR MENUITEM SEPARATOR - MENUITEM "S&premenljiva velikost okna", IDM_VID_RESIZE - MENUITEM "&Zapomni si velikost in položaj", IDM_VID_REMEMBER + MENUITEM "&Show non-primary monitors", IDM_VID_MONITORS + MENUITEM "S&premenljiva velikost okna", IDM_VID_RESIZE + MENUITEM "&Zapomni si velikost in položaj", IDM_VID_REMEMBER MENUITEM SEPARATOR POPUP "&Upodabljanje" BEGIN - MENUITEM "&SDL (programsko)", IDM_VID_SDL_SW - MENUITEM "SDL (s&trojno)", IDM_VID_SDL_HW - MENUITEM "SDL (&OpenGL)", IDM_VID_SDL_OPENGL - MENUITEM "Open&GL (Jedro 3.0)", IDM_VID_OPENGL_CORE + MENUITEM "&SDL (programsko)", IDM_VID_SDL_SW + MENUITEM "SDL (s&trojno)", IDM_VID_SDL_HW + MENUITEM "SDL (&OpenGL)", IDM_VID_SDL_OPENGL + MENUITEM "Open&GL (Jedro 3.0)", IDM_VID_OPENGL_CORE #ifdef USE_VNC - MENUITEM "&VNC", IDM_VID_VNC + MENUITEM "&VNC", IDM_VID_VNC #endif END MENUITEM SEPARATOR - MENUITEM "&DoloÄi velikost...", IDM_VID_SPECIFY_DIM - MENUITEM "&Vsili 4:3 razmerje zaslona", IDM_VID_FORCE43 + MENUITEM "&DoloÄi velikost...", IDM_VID_SPECIFY_DIM + MENUITEM "&Vsili 4:3 razmerje zaslona", IDM_VID_FORCE43 POPUP "&Faktor velikosti okna" BEGIN - MENUITEM "&0.5x", IDM_VID_SCALE_1X - MENUITEM "&1x", IDM_VID_SCALE_2X - MENUITEM "1.&5x", IDM_VID_SCALE_3X - MENUITEM "&2x", IDM_VID_SCALE_4X + MENUITEM "&0.5x", IDM_VID_SCALE_1X + MENUITEM "&1x", IDM_VID_SCALE_2X + MENUITEM "1.&5x", IDM_VID_SCALE_3X + MENUITEM "&2x", IDM_VID_SCALE_4X + MENUITEM "&3x", IDM_VID_SCALE_5X + MENUITEM "&4x", IDM_VID_SCALE_6X + MENUITEM "&5x", IDM_VID_SCALE_7X + MENUITEM "&6x", IDM_VID_SCALE_8X + MENUITEM "&7x", IDM_VID_SCALE_9X + MENUITEM "&8x", IDM_VID_SCALE_10X END POPUP "&Metoda filtriranja" BEGIN - MENUITEM "&Najbližja", IDM_VID_FILTER_NEAREST - MENUITEM "&Linearna", IDM_VID_FILTER_LINEAR + MENUITEM "&Najbližja", IDM_VID_FILTER_NEAREST + MENUITEM "&Linearna", IDM_VID_FILTER_LINEAR END - MENUITEM "&Raztezanje za visok DPI", IDM_VID_HIDPI + MENUITEM "&Raztezanje za visok DPI", IDM_VID_HIDPI MENUITEM SEPARATOR - MENUITEM "&Celozaslonski naÄin\tCtrl+Alt+PgUp", IDM_VID_FULLSCREEN + MENUITEM "&Celozaslonski naÄin\tCtrl+Alt+PgUp", IDM_VID_FULLSCREEN POPUP "&NaÄin celozaslonskega raztezanja" BEGIN - MENUITEM "&Raztegni na celoten zaslon", IDM_VID_FS_FULL - MENUITEM "&4:3", IDM_VID_FS_43 + MENUITEM "&Raztegni na celoten zaslon", IDM_VID_FS_FULL + MENUITEM "&4:3", IDM_VID_FS_43 MENUITEM "&Kvadratni piksli (ohrani razmerje)", IDM_VID_FS_KEEPRATIO - MENUITEM "&CeloÅ¡tevilsko raztezanje", IDM_VID_FS_INT + MENUITEM "&CeloÅ¡tevilsko raztezanje", IDM_VID_FS_INT END POPUP "Nastavitve E&GA/(S)VGA" BEGIN - MENUITEM "&Obrni barve zaslona VGA", IDM_VID_INVERT + MENUITEM "&Obrni barve zaslona VGA", IDM_VID_INVERT POPUP "&Vrsta zaslona VGA" BEGIN - MENUITEM "&Barvni RGB", IDM_VID_GRAY_RGB - MENUITEM "&Sivinski RGB", IDM_VID_GRAY_MONO - MENUITEM "&Rumeni zaslon", IDM_VID_GRAY_AMBER - MENUITEM "&Zeleni zaslon", IDM_VID_GRAY_GREEN - MENUITEM "B&eli zaslon", IDM_VID_GRAY_WHITE + MENUITEM "&Barvni RGB", IDM_VID_GRAY_RGB + MENUITEM "&Sivinski RGB", IDM_VID_GRAY_MONO + MENUITEM "&Rumeni zaslon", IDM_VID_GRAY_AMBER + MENUITEM "&Zeleni zaslon", IDM_VID_GRAY_GREEN + MENUITEM "B&eli zaslon", IDM_VID_GRAY_WHITE END POPUP "V&rsta pretvorbe sivin" BEGIN - MENUITEM "BT&601 (NTSC/PAL)", IDM_VID_GRAYCT_601 - MENUITEM "BT&709 (HDTV)", IDM_VID_GRAYCT_709 - MENUITEM "&PovpreÄje", IDM_VID_GRAYCT_AVE + MENUITEM "BT&601 (NTSC/PAL)", IDM_VID_GRAYCT_601 + MENUITEM "BT&709 (HDTV)", IDM_VID_GRAYCT_709 + MENUITEM "&PovpreÄje", IDM_VID_GRAYCT_AVE END END MENUITEM SEPARATOR - MENUITEM "&Presežek slike CGA/PCjr/Tandy/EGA/(S)VGA", IDM_VID_OVERSCAN + MENUITEM "&Presežek slike CGA/PCjr/Tandy/EGA/(S)VGA", IDM_VID_OVERSCAN MENUITEM "&Spremeni contrast za Ärno-beli zaslon", IDM_VID_CGACON END - MENUITEM "&Mediji", IDM_MEDIA + MENUITEM "&Mediji", IDM_MEDIA POPUP "&Orodja" BEGIN - MENUITEM "&Nastavitve...", IDM_CONFIG - MENUITEM "&Posodabljaj ikone statusne vrstice", IDM_UPDATE_ICONS + MENUITEM "&Nastavitve...", IDM_CONFIG + MENUITEM "&Posodabljaj ikone statusne vrstice", IDM_UPDATE_ICONS MENUITEM SEPARATOR - MENUITEM "&Zajemi posnetek zaslona\tCtrl+F11", IDM_ACTION_SCREENSHOT + MENUITEM "&Zajemi posnetek zaslona\tCtrl+F11", IDM_ACTION_SCREENSHOT MENUITEM SEPARATOR - MENUITEM "&Možnosti...", IDM_PREFERENCES + MENUITEM "&Možnosti...", IDM_PREFERENCES +#ifdef DISCORD MENUITEM "OmogoÄi integracijo s programom &Discord", IDM_DISCORD +#endif MENUITEM SEPARATOR - MENUITEM "&OjaÄanje zvoka...", IDM_SND_GAIN + MENUITEM "&OjaÄanje zvoka...", IDM_SND_GAIN #ifdef MTR_ENABLED MENUITEM SEPARATOR - MENUITEM "Z&aÄni sledenje\tCtrl+T", IDM_ACTION_BEGIN_TRACE - MENUITEM "&KonÄaj sledenje\tCtrl+T", IDM_ACTION_END_TRACE + MENUITEM "Z&aÄni sledenje\tCtrl+T", IDM_ACTION_BEGIN_TRACE + MENUITEM "&KonÄaj sledenje\tCtrl+T", IDM_ACTION_END_TRACE #endif END POPUP "&PomoÄ" BEGIN - MENUITEM "&Dokumentacija...", IDM_DOCS - MENUITEM "&O programu 86Box...", IDM_ABOUT + MENUITEM "&Dokumentacija...", IDM_DOCS + MENUITEM "&O programu 86Box...", IDM_ABOUT END END -StatusBarMenu MENU DISCARDABLE +StatusBarMenu MENU DISCARDABLE BEGIN MENUITEM SEPARATOR END @@ -128,17 +137,17 @@ CassetteSubmenu MENU DISCARDABLE BEGIN POPUP "" BEGIN - MENUITEM "&Nova slika...", IDM_CASSETTE_IMAGE_NEW + MENUITEM "&Nova slika...", IDM_CASSETTE_IMAGE_NEW MENUITEM SEPARATOR - MENUITEM "&ObstojeÄa slika...", IDM_CASSETTE_IMAGE_EXISTING - MENUITEM "ObstojeÄa slika (&samo za branje)...", IDM_CASSETTE_IMAGE_EXISTING_WP + MENUITEM "&ObstojeÄa slika...", IDM_CASSETTE_IMAGE_EXISTING + MENUITEM "ObstojeÄa slika (&samo za branje)...", IDM_CASSETTE_IMAGE_EXISTING_WP MENUITEM SEPARATOR - MENUITEM "Snemaj", IDM_CASSETTE_RECORD - MENUITEM "Predvajaj", IDM_CASSETTE_PLAY - MENUITEM "Previj na zaÄetek", IDM_CASSETTE_REWIND - MENUITEM "PreskoÄi na konec", IDM_CASSETTE_FAST_FORWARD + MENUITEM "Snemaj", IDM_CASSETTE_RECORD + MENUITEM "Predvajaj", IDM_CASSETTE_PLAY + MENUITEM "Previj na zaÄetek", IDM_CASSETTE_REWIND + MENUITEM "PreskoÄi na konec", IDM_CASSETTE_FAST_FORWARD MENUITEM SEPARATOR - MENUITEM "Izvrzi", IDM_CASSETTE_EJECT + MENUITEM "Izvrzi", IDM_CASSETTE_EJECT END END @@ -146,9 +155,9 @@ CartridgeSubmenu MENU DISCARDABLE BEGIN POPUP "" BEGIN - MENUITEM "Slika...", IDM_CARTRIDGE_IMAGE + MENUITEM "Slika...", IDM_CARTRIDGE_IMAGE MENUITEM SEPARATOR - MENUITEM "Izvrzi", IDM_CARTRIDGE_EJECT + MENUITEM "Izvrzi", IDM_CARTRIDGE_EJECT END END @@ -156,14 +165,14 @@ FloppySubmenu MENU DISCARDABLE BEGIN POPUP "" BEGIN - MENUITEM "&Nova slika...", IDM_FLOPPY_IMAGE_NEW + MENUITEM "&Nova slika...", IDM_FLOPPY_IMAGE_NEW MENUITEM SEPARATOR - MENUITEM "&ObstojeÄa slika...", IDM_FLOPPY_IMAGE_EXISTING - MENUITEM "ObstojeÄa slika (&samo za branje)...", IDM_FLOPPY_IMAGE_EXISTING_WP + MENUITEM "&ObstojeÄa slika...", IDM_FLOPPY_IMAGE_EXISTING + MENUITEM "ObstojeÄa slika (&samo za branje)...", IDM_FLOPPY_IMAGE_EXISTING_WP MENUITEM SEPARATOR - MENUITEM "&Izvozi v 86F...", IDM_FLOPPY_EXPORT_TO_86F + MENUITEM "&Izvozi v 86F...", IDM_FLOPPY_EXPORT_TO_86F MENUITEM SEPARATOR - MENUITEM "I&zvrzi", IDM_FLOPPY_EJECT + MENUITEM "I&zvrzi", IDM_FLOPPY_EJECT END END @@ -171,12 +180,13 @@ CdromSubmenu MENU DISCARDABLE BEGIN POPUP "" BEGIN - MENUITEM "&UtiÅ¡aj", IDM_CDROM_MUTE + MENUITEM "&UtiÅ¡aj", IDM_CDROM_MUTE MENUITEM SEPARATOR - MENUITEM "&Prazen", IDM_CDROM_EMPTY - MENUITEM "&Naloži zadnjo sliko", IDM_CDROM_RELOAD + MENUITEM "&Prazen", IDM_CDROM_EMPTY + MENUITEM "&Naloži zadnjo sliko", IDM_CDROM_RELOAD MENUITEM SEPARATOR - MENUITEM "&Slika", IDM_CDROM_IMAGE + MENUITEM "&Slika...", IDM_CDROM_IMAGE + MENUITEM "&Mapa...", IDM_CDROM_DIR END END @@ -184,13 +194,13 @@ ZIPSubmenu MENU DISCARDABLE BEGIN POPUP "" BEGIN - MENUITEM "&Nova slika...", IDM_ZIP_IMAGE_NEW + MENUITEM "&Nova slika...", IDM_ZIP_IMAGE_NEW MENUITEM SEPARATOR - MENUITEM "&ObstojeÄa slika...", IDM_ZIP_IMAGE_EXISTING - MENUITEM "ObstojeÄa slika (&samo za branje)...", IDM_ZIP_IMAGE_EXISTING_WP + MENUITEM "&ObstojeÄa slika...", IDM_ZIP_IMAGE_EXISTING + MENUITEM "ObstojeÄa slika (&samo za branje)...", IDM_ZIP_IMAGE_EXISTING_WP MENUITEM SEPARATOR - MENUITEM "I&zvrzi", IDM_ZIP_EJECT - MENUITEM "&Naloži zadnjo sliko", IDM_ZIP_RELOAD + MENUITEM "I&zvrzi", IDM_ZIP_EJECT + MENUITEM "&Naloži zadnjo sliko", IDM_ZIP_RELOAD END END @@ -198,13 +208,13 @@ MOSubmenu MENU DISCARDABLE BEGIN POPUP "" BEGIN - MENUITEM "&Nova slika...", IDM_MO_IMAGE_NEW + MENUITEM "&Nova slika...", IDM_MO_IMAGE_NEW MENUITEM SEPARATOR - MENUITEM "&ObstojeÄa slika...", IDM_MO_IMAGE_EXISTING - MENUITEM "ObstojeÄa slika (&samo za branje)...", IDM_MO_IMAGE_EXISTING_WP + MENUITEM "&ObstojeÄa slika...", IDM_MO_IMAGE_EXISTING + MENUITEM "ObstojeÄa slika (&samo za branje)...", IDM_MO_IMAGE_EXISTING_WP MENUITEM SEPARATOR - MENUITEM "I&zvrzi", IDM_MO_EJECT - MENUITEM "&Naloži zadnjo sliko", IDM_MO_RELOAD + MENUITEM "I&zvrzi", IDM_MO_EJECT + MENUITEM "&Naloži zadnjo sliko", IDM_MO_RELOAD END END @@ -230,134 +240,150 @@ END // Dialog // -#define STR_PREFERENCES "Možnosti" -#define STR_SND_GAIN "OjaÄanje zvoka" -#define STR_NEW_FLOPPY "Nova slika" -#define STR_CONFIG "Nastavitve" -#define STR_SPECIFY_DIM "DoloÄi velikost glavnega okna" +#define STR_PREFERENCES "Možnosti" +#define STR_SND_GAIN "OjaÄanje zvoka" +#define STR_NEW_FLOPPY "Nova slika" +#define STR_CONFIG "Nastavitve" +#define STR_SPECIFY_DIM "DoloÄi velikost glavnega okna" -#define STR_OK "V redu" -#define STR_CANCEL "PrekliÄi" -#define STR_GLOBAL "Shrani te nastavitve kot globalne privzete" -#define STR_DEFAULT "Privzeto" -#define STR_LANGUAGE "Jezik:" -#define STR_ICONSET "Komplet ikon:" +#define STR_OK "V redu" +#define STR_CANCEL "PrekliÄi" +#define STR_GLOBAL "Shrani te nastavitve kot globalne privzete" +#define STR_DEFAULT "Privzeto" +#define STR_LANGUAGE "Jezik:" +#define STR_ICONSET "Komplet ikon:" -#define STR_GAIN "OjaÄanje" +#define STR_GAIN "OjaÄanje" -#define STR_FILE_NAME "Ime datoteke:" -#define STR_DISK_SIZE "Velikost diska:" -#define STR_RPM_MODE "NaÄin Å¡tevila obratov:" -#define STR_PROGRESS "Napredek:" +#define STR_FILE_NAME "Ime datoteke:" +#define STR_DISK_SIZE "Velikost diska:" +#define STR_RPM_MODE "NaÄin Å¡tevila obratov:" +#define STR_PROGRESS "Napredek:" -#define STR_WIDTH "Å irina:" -#define STR_HEIGHT "ViÅ¡ina:" -#define STR_LOCK_TO_SIZE "Zakleni na to velikost" +#define STR_WIDTH "Å irina:" +#define STR_HEIGHT "ViÅ¡ina:" +#define STR_LOCK_TO_SIZE "Zakleni na to velikost" -#define STR_MACHINE_TYPE "Vrsta sistema:" -#define STR_MACHINE "Sistem:" -#define STR_CONFIGURE "Nastavi" -#define STR_CPU_TYPE "Vrsta procesorja:" -#define STR_CPU_SPEED "Hitrost:" -#define STR_FPU "Procesor plavajoÄe vejice:" -#define STR_WAIT_STATES "ÄŒakalna stanja:" -#define STR_MB "MB" -#define STR_MEMORY "Spomin:" -#define STR_TIME_SYNC "Sinhronizacija Äasa" -#define STR_DISABLED "OnemogoÄeno" -#define STR_ENABLED_LOCAL "OmogoÄeno (lokalni Äas)" -#define STR_ENABLED_UTC "OmogoÄeno (UTC)" -#define STR_DYNAREC "DinamiÄni prevajalnik" +#define STR_MACHINE_TYPE "Vrsta sistema:" +#define STR_MACHINE "Sistem:" +#define STR_CONFIGURE "Nastavi" +#define STR_CPU_TYPE "Vrsta procesorja:" +#define STR_CPU_SPEED "Hitrost:" +#define STR_FPU "Procesor plavajoÄe vejice:" +#define STR_WAIT_STATES "ÄŒakalna stanja:" +#define STR_MB "MB" +#define STR_MEMORY "Spomin:" +#define STR_TIME_SYNC "Sinhronizacija Äasa" +#define STR_DISABLED "OnemogoÄeno" +#define STR_ENABLED_LOCAL "OmogoÄeno (lokalni Äas)" +#define STR_ENABLED_UTC "OmogoÄeno (UTC)" +#define STR_DYNAREC "DinamiÄni prevajalnik" +#define STR_SOFTFLOAT "Softfloat FPU" -#define STR_VIDEO "Video:" -#define STR_VOODOO "Voodoo grafika" +#define STR_VIDEO "Video:" +#define STR_VIDEO_2 "Video 2:" +#define STR_VOODOO "Voodoo grafika" +#define STR_IBM8514 "IBM 8514/a grafika" +#define STR_XGA "XGA grafika" -#define STR_MOUSE "MiÅ¡ka:" -#define STR_JOYSTICK "Igralna palica:" -#define STR_JOY1 "Igralna palica 1..." -#define STR_JOY2 "Igralna palica 2..." -#define STR_JOY3 "Igralna palica 3..." -#define STR_JOY4 "Igralna palica 4..." +#define STR_MOUSE "MiÅ¡ka:" +#define STR_JOYSTICK "Igralna palica:" +#define STR_JOY1 "Igralna palica 1..." +#define STR_JOY2 "Igralna palica 2..." +#define STR_JOY3 "Igralna palica 3..." +#define STR_JOY4 "Igralna palica 4..." -#define STR_SOUND "ZvoÄna kartica:" -#define STR_MIDI_OUT "Izhodna naprava MIDI:" -#define STR_MIDI_IN "Vhodna naprava MIDI:" -#define STR_MPU401 "Samostojen MPU-401" -#define STR_SSI "Innovation SSI-2001" -#define STR_CMS "CMS / Game Blaster" -#define STR_GUS "Gravis Ultrasound" -#define STR_FLOAT "Uporabi FLOAT32 za zvok" +#define STR_SOUND1 "ZvoÄna kartica 1:" +#define STR_SOUND2 "ZvoÄna kartica 2:" +#define STR_SOUND3 "ZvoÄna kartica 3:" +#define STR_SOUND4 "ZvoÄna kartica 4:" +#define STR_MIDI_OUT "Izhodna naprava MIDI:" +#define STR_MIDI_IN "Vhodna naprava MIDI:" +#define STR_MPU401 "Samostojen MPU-401" +#define STR_FLOAT "Uporabi FLOAT32 za zvok" +#define STR_FM_DRIVER "Gonilnik sintetizacije FM" +#define STR_FM_DRV_NUKED "Nuked (toÄnejÅ¡i)" +#define STR_FM_DRV_YMFM "YMFM (hitrejÅ¡i)" -#define STR_NET_TYPE "Vrsta omrežja:" -#define STR_PCAP "Naprava PCap:" -#define STR_NET "Omrežna kartica:" +#define STR_NET_TYPE "Vrsta omrežja:" +#define STR_PCAP "Naprava PCap:" +#define STR_NET "Omrežna kartica:" +#define STR_NET1 "Network card 1:" +#define STR_NET2 "Network card 2:" +#define STR_NET3 "Network card 3:" +#define STR_NET4 "Network card 4:" -#define STR_COM1 "Naprava COM1:" -#define STR_COM2 "Naprava COM2:" -#define STR_COM3 "Naprava COM3:" -#define STR_COM4 "Naprava COM4:" -#define STR_LPT1 "Naprava LPT1:" -#define STR_LPT2 "Naprava LPT2:" -#define STR_LPT3 "Naprava LPT3:" -#define STR_LPT4 "Naprava LPT4:" -#define STR_SERIAL1 "Serijska vrata 1" -#define STR_SERIAL2 "Serijska vrata 2" -#define STR_SERIAL3 "Serijska vrata 3" -#define STR_SERIAL4 "Serijska vrata 4" -#define STR_PARALLEL1 "Paralelna vrata 1" -#define STR_PARALLEL2 "Paralelna vrata 2" -#define STR_PARALLEL3 "Paralelna vrata 3" -#define STR_PARALLEL4 "Paralelna vrata 4" +#define STR_COM1 "Naprava COM1:" +#define STR_COM2 "Naprava COM2:" +#define STR_COM3 "Naprava COM3:" +#define STR_COM4 "Naprava COM4:" +#define STR_LPT1 "Naprava LPT1:" +#define STR_LPT2 "Naprava LPT2:" +#define STR_LPT3 "Naprava LPT3:" +#define STR_LPT4 "Naprava LPT4:" +#define STR_SERIAL1 "Serijska vrata 1" +#define STR_SERIAL2 "Serijska vrata 2" +#define STR_SERIAL3 "Serijska vrata 3" +#define STR_SERIAL4 "Serijska vrata 4" +#define STR_PARALLEL1 "Paralelna vrata 1" +#define STR_PARALLEL2 "Paralelna vrata 2" +#define STR_PARALLEL3 "Paralelna vrata 3" +#define STR_PARALLEL4 "Paralelna vrata 4" +#define STR_SERIAL_PASS1 "Serial port passthrough 1" +#define STR_SERIAL_PASS2 "Serial port passthrough 2" +#define STR_SERIAL_PASS3 "Serial port passthrough 3" +#define STR_SERIAL_PASS4 "Serial port passthrough 4" -#define STR_HDC "Krmilnik trdega diska:" -#define STR_FDC "Krmilnik disketnika:" -#define STR_IDE_TER "Terciarni krmilnik IDE" -#define STR_IDE_QUA "Kvartarni krmilnik IDE" -#define STR_SCSI "SCSI" -#define STR_SCSI_1 "Krmilnik 1:" -#define STR_SCSI_2 "Krmilnik 2:" -#define STR_SCSI_3 "Krmilnik 3:" -#define STR_SCSI_4 "Krmilnik 4:" -#define STR_CASSETTE "Kasetnik" +#define STR_HDC "Krmilnik trdega diska:" +#define STR_FDC "Krmilnik disketnika:" +#define STR_IDE_TER "Terciarni krmilnik IDE" +#define STR_IDE_QUA "Kvartarni krmilnik IDE" +#define STR_SCSI "SCSI" +#define STR_SCSI_1 "Krmilnik 1:" +#define STR_SCSI_2 "Krmilnik 2:" +#define STR_SCSI_3 "Krmilnik 3:" +#define STR_SCSI_4 "Krmilnik 4:" +#define STR_CASSETTE "Kasetnik" -#define STR_HDD "Trdi diski:" -#define STR_NEW "Nov..." -#define STR_EXISTING "ObstojeÄ..." -#define STR_REMOVE "Odstrani" -#define STR_BUS "Vodilo:" -#define STR_CHANNEL "Kanal:" -#define STR_ID "ID:" +#define STR_HDD "Trdi diski:" +#define STR_NEW "Nov..." +#define STR_EXISTING "ObstojeÄ..." +#define STR_REMOVE "Odstrani" +#define STR_BUS "Vodilo:" +#define STR_CHANNEL "Kanal:" +#define STR_ID "ID:" +#define STR_SPEED "Speed:" -#define STR_SPECIFY "DoloÄi..." -#define STR_SECTORS "Sektorji:" -#define STR_HEADS "Glave:" -#define STR_CYLS "Cilindri:" -#define STR_SIZE_MB "Velikost (MB):" -#define STR_TYPE "Vrsta:" -#define STR_IMG_FORMAT "Format slike:" -#define STR_BLOCK_SIZE "Velikost bloka:" +#define STR_SPECIFY "DoloÄi..." +#define STR_SECTORS "Sektorji:" +#define STR_HEADS "Glave:" +#define STR_CYLS "Cilindri:" +#define STR_SIZE_MB "Velikost (MB):" +#define STR_TYPE "Vrsta:" +#define STR_IMG_FORMAT "Format slike:" +#define STR_BLOCK_SIZE "Velikost bloka:" -#define STR_FLOPPY_DRIVES "Disketni pogoni:" -#define STR_TURBO "Turbo Äasovniki" -#define STR_CHECKBPB "Preverjaj BPB" -#define STR_CDROM_DRIVES "Pogoni CD-ROM:" -#define STR_CD_SPEED "Hitrost:" +#define STR_FLOPPY_DRIVES "Disketni pogoni:" +#define STR_TURBO "Turbo Äasovniki" +#define STR_CHECKBPB "Preverjaj BPB" +#define STR_CDROM_DRIVES "Pogoni CD-ROM:" +#define STR_CD_SPEED "Hitrost:" -#define STR_MO_DRIVES "Magnetno-optiÄni pogoni:" -#define STR_ZIP_DRIVES "Pogoni ZIP:" -#define STR_250 "ZIP 250" +#define STR_MO_DRIVES "Magnetno-optiÄni pogoni:" +#define STR_ZIP_DRIVES "Pogoni ZIP:" +#define STR_250 "ZIP 250" -#define STR_ISARTC "Ura v realnem Äasu ISA:" -#define STR_ISAMEM "RazÅ¡iritev spomina ISA" -#define STR_ISAMEM_1 "Kartica 1:" -#define STR_ISAMEM_2 "Kartica 2:" -#define STR_ISAMEM_3 "Kartica 3:" -#define STR_ISAMEM_4 "Kartica 4:" -#define STR_BUGGER "Naprava ISABugger" -#define STR_POSTCARD "Kartica POST" +#define STR_ISARTC "Ura v realnem Äasu ISA:" +#define STR_ISAMEM "RazÅ¡iritev spomina ISA" +#define STR_ISAMEM_1 "Kartica 1:" +#define STR_ISAMEM_2 "Kartica 2:" +#define STR_ISAMEM_3 "Kartica 3:" +#define STR_ISAMEM_4 "Kartica 4:" +#define STR_BUGGER "Naprava ISABugger" +#define STR_POSTCARD "Kartica POST" -#define FONT_SIZE 9 -#define FONT_NAME "Segoe UI" +#define FONT_SIZE 9 +#define FONT_NAME "Segoe UI" #include "dialogs.rc" @@ -366,194 +392,188 @@ END // String Table // -STRINGTABLE DISCARDABLE +STRINGTABLE DISCARDABLE BEGIN - 2048 "86Box" - IDS_2049 "Napaka" - IDS_2050 "KritiÄna napaka" - IDS_2051 " - PAUSED" - IDS_2052 "Pritisnite Ctrl+Alt+PgDn za povratek iz celozaslonskega naÄina." - IDS_2053 "Hitrost" - IDS_2054 "ZIP %03i %i (%s): %ls" - IDS_2055 "ZIP slike (*.IM?;*.ZDI)\0*.IM?;*.ZDI\0" - IDS_2056 "86Box ni naÅ¡el nobenih uporabnih ROM slik.\n\nProsim prenesite set ROM-ov in ga razÅ¡irite v mapo ""roms""." - IDS_2057 "(prazno)" - IDS_2058 "ZIP slike (*.IM?;*.ZDI)\0*.IM?;*.ZDI\0Vse datoteke (*.*)\0*.*\0" - IDS_2059 "Turbo" - IDS_2060 "VkljuÄeno" - IDS_2061 "IzkljuÄeno" - IDS_2062 "Vse slike (*.86F;*.DSK;*.FLP;*.IM?;*.*FD?)\0*.86F;*.DSK;*.FLP;*.IM?;*.*FD?\0Osnovne sektorske slike (*.DSK;*.FLP;*.IM?;*.*FD?)\0*.DSK;*.FLP;*.IM?;*.IMG;*.*FD?\0PovrÅ¡inske slike (*.86F)\0*.86F\0" - IDS_2063 "Sistem ""%hs"" ni na voljo zaradi manjkajoÄih ROM-ov v mapi roms/machines. Preklapljam na drug sistem, ki je na voljo." + 2048 "86Box" + IDS_2049 "Napaka" + IDS_2050 "KritiÄna napaka" + IDS_2051 " - PAUSED" + IDS_2052 "Pritisnite Ctrl+Alt+PgDn za povratek iz celozaslonskega naÄina." + IDS_2053 "Hitrost" + IDS_2054 "ZIP %03i %i (%s): %ls" + IDS_2055 "ZIP slike (*.IM?;*.ZDI)\0*.IM?;*.ZDI\0" + IDS_2056 "86Box ni naÅ¡el nobenih uporabnih ROM slik.\n\nProsim prenesite set ROM-ov in ga razÅ¡irite v mapo ""roms""." + IDS_2057 "(prazno)" + IDS_2058 "ZIP slike (*.IM?;*.ZDI)\0*.IM?;*.ZDI\0Vse datoteke (*.*)\0*.*\0" + IDS_2059 "Turbo" + IDS_2060 "VkljuÄeno" + IDS_2061 "IzkljuÄeno" + IDS_2062 "Vse slike (*.86F;*.DSK;*.FLP;*.IM?;*.*FD?)\0*.86F;*.DSK;*.FLP;*.IM?;*.*FD?\0Osnovne sektorske slike (*.DSK;*.FLP;*.IM?;*.*FD?)\0*.DSK;*.FLP;*.IM?;*.IMG;*.*FD?\0PovrÅ¡inske slike (*.86F)\0*.86F\0" + IDS_2063 "Sistem ""%hs"" ni na voljo zaradi manjkajoÄih ROM-ov v mapi roms/machines. Preklapljam na drug sistem, ki je na voljo." END -STRINGTABLE DISCARDABLE +STRINGTABLE DISCARDABLE BEGIN - IDS_2064 "GrafiÄna kartica ""%hs"" ni na voljo zaradi manjkajoÄih ROM-ov v mapi roms/video. Preklapljam na drugo grafiÄno kartico, ki je na voljo.." - IDS_2065 "Sistem" - IDS_2066 "Zaslon" - IDS_2067 "Vhodne naprave" - IDS_2068 "Zvok" - IDS_2069 "Omrežje" - IDS_2070 "Vrata (COM & LPT)" - IDS_2071 "Krmilniki shrambe" - IDS_2072 "Trdi diski" - IDS_2073 "Disketni in CD-ROM pogoni" - IDS_2074 "Druge odstranljive naprave" - IDS_2075 "Druga periferija" - IDS_2076 "PovrÅ¡inske slike (*.86F)\0*.86F\0" - IDS_2077 "Kliknite za zajem miÅ¡ke" - IDS_2078 "Pritisnite F8+F12 za izpust miÅ¡ke" - IDS_2079 "Pritisnite F8+F12 ali srednji gumb za izpust miÅ¡ke" + IDS_2064 "GrafiÄna kartica ""%hs"" ni na voljo zaradi manjkajoÄih ROM-ov v mapi roms/video. Preklapljam na drugo grafiÄno kartico, ki je na voljo.." + IDS_2065 "Sistem" + IDS_2066 "Zaslon" + IDS_2067 "Vhodne naprave" + IDS_2068 "Zvok" + IDS_2069 "Omrežje" + IDS_2070 "Vrata (COM & LPT)" + IDS_2071 "Krmilniki shrambe" + IDS_2072 "Trdi diski" + IDS_2073 "Disketni in CD-ROM pogoni" + IDS_2074 "Druge odstranljive naprave" + IDS_2075 "Druga periferija" + IDS_2076 "PovrÅ¡inske slike (*.86F)\0*.86F\0" + IDS_2077 "Kliknite za zajem miÅ¡ke" + IDS_2078 "Pritisnite F8+F12 za izpust miÅ¡ke" + IDS_2079 "Pritisnite F8+F12 ali srednji gumb za izpust miÅ¡ke" END -STRINGTABLE DISCARDABLE +STRINGTABLE DISCARDABLE BEGIN - IDS_2080 "Ne morem inicializirati FluidSynth" - IDS_2081 "Vodilo" - IDS_2082 "Datoteka" - IDS_2083 "C" - IDS_2084 "H" - IDS_2085 "S" - IDS_2086 "MB" - IDS_2087 "Preveri BPB" - IDS_2088 "KB" - IDS_2089 "Ne morem inicializirati pogona upodabljanja." - IDS_2090 "Privzeto" - IDS_2091 "%i stanj Äakanja" - IDS_2092 "Vrsta" - IDS_2093 "Nastavitev PCap ni uspela" - IDS_2094 "Nobena naprava PCap ni bila najdena" - IDS_2095 "Neveljavna naprava PCap" - IDS_2096 "Standardna krmilna palica z 2 gumboma" - IDS_2097 "Standardna krmilna palica s 4 gumbi" - IDS_2098 "Standardna krmilna palica s 6 gumbi" - IDS_2099 "Standardna krmilna palica z 8 gumbi" - IDS_2100 "CH Flightstick Pro" - IDS_2101 "Microsoft SideWinder Pad" - IDS_2102 "Thrustmaster Flight Control System" - IDS_2103 "Brez" - IDS_2104 "Ne morem naložiti pospeÅ¡evalnikov tipkovnice." - IDS_2105 "Ne morem registrirati neobdelanega vnosa." - IDS_2106 "%u" - IDS_2107 "%u MB (CHS: %i, %i, %i)" - IDS_2108 "Disketa %i (%s): %ls" - IDS_2109 "Vse slike (*.0??;*.1??;*.??0;*.86F;*.BIN;*.CQ?;*.D??;*.FLP;*.HDM;*.IM?;*.JSON;*.TD0;*.*FD?;*.MFM;*.XDF)\0*.0??;*.1??;*.??0;*.86F;*.BIN;*.CQ?;*.D??;*.FLP;*.HDM;*.IM?;*.JSON;*.TD0;*.*FD?;*.MFM;*.XDF\0Napredne sektorske slike (*.IMD;*.JSON;*.TD0)\0*.IMD;*.JSON;*.TD0\0Osnovne sektorske slike (*.0??;*.1??;*.??0;*.BIN;*.CQ?;*.D??;*.FLP;*.HDM;*.IM?;*.XDF;*.*FD?)\0*.0??;*.1??;*.??0;*.BIN;*.CQ?;*.D??;*.FLP;*.HDM;*.IM?;*.XDF;*.*FD?\0Tokovne slike (*.FDI)\0*.FDI\0PovrÅ¡inske slike (*.86F;*.MFM)\0*.86F;*.MFM\0Vse datoteke (*.*)\0*.*\0" - IDS_2110 "Ne morem inicializirati FreeType" - IDS_2111 "Ne morem inicializirati SDL, potrebna je knjižica SDL2.dll" - IDS_2112 "Ste prepriÄani, da želite ponovno zagnati emulirani sistem?" - IDS_2113 "Ste prepriÄani, da želite zapreti 86Box?" - IDS_2114 "Ne morem inicializirati Ghostscript" - IDS_2115 "MO %i (%ls): %ls" - IDS_2116 "Slike MO (*.IM?;*.MDI)\0*.IM?;*.MDI\0Vse datoteke (*.*)\0*.*\0" - IDS_2117 "DobrodoÅ¡li v 86Box!" - IDS_2118 "Notranji krmilnik" - IDS_2119 "Izhod" - IDS_2120 "Nobeni ROM-i niso bili najdeni" - IDS_2121 "Želite shraniti nastavitve?" - IDS_2122 "To bo ponovno zagnalo emuliran sistem." - IDS_2123 "Shrani" - IDS_2124 "O programu 86Box" - IDS_2125 "86Box v" EMU_VERSION + IDS_2081 "Vodilo" + IDS_2082 "Datoteka" + IDS_2083 "C" + IDS_2084 "H" + IDS_2085 "S" + IDS_2086 "MB" + IDS_2087 "Speed" + IDS_2088 "Preveri BPB" + IDS_2089 "KB" + IDS_2090 "Ne morem inicializirati pogona upodabljanja." + IDS_2091 "Privzeto" + IDS_2092 "%i stanj Äakanja" + IDS_2093 "Vrsta" + IDS_2094 "Nastavitev PCap ni uspela" + IDS_2095 "Nobena naprava PCap ni bila najdena" + IDS_2096 "Neveljavna naprava PCap" + IDS_2097 "Standardna krmilna palica z 2 gumboma" + IDS_2098 "Standardna krmilna palica s 4 gumbi" + IDS_2099 "Standardna krmilna palica s 6 gumbi" + IDS_2100 "Standardna krmilna palica z 8 gumbi" + IDS_2101 "CH Flightstick Pro" + IDS_2102 "Microsoft SideWinder Pad" + IDS_2103 "Thrustmaster Flight Control System" + IDS_2104 "Brez" + IDS_2105 "Ne morem naložiti pospeÅ¡evalnikov tipkovnice." + IDS_2106 "Ne morem registrirati neobdelanega vnosa." + IDS_2107 "%u" + IDS_2108 "%u MB (CHS: %i, %i, %i)" + IDS_2109 "Disketa %i (%s): %ls" + IDS_2110 "Vse slike (*.0??;*.1??;*.??0;*.86F;*.BIN;*.CQ?;*.D??;*.FLP;*.HDM;*.IM?;*.JSON;*.TD0;*.*FD?;*.MFM;*.XDF)\0*.0??;*.1??;*.??0;*.86F;*.BIN;*.CQ?;*.D??;*.FLP;*.HDM;*.IM?;*.JSON;*.TD0;*.*FD?;*.MFM;*.XDF\0Napredne sektorske slike (*.IMD;*.JSON;*.TD0)\0*.IMD;*.JSON;*.TD0\0Osnovne sektorske slike (*.0??;*.1??;*.??0;*.BIN;*.CQ?;*.D??;*.FLP;*.HDM;*.IM?;*.XDF;*.*FD?)\0*.0??;*.1??;*.??0;*.BIN;*.CQ?;*.D??;*.FLP;*.HDM;*.IM?;*.XDF;*.*FD?\0Tokovne slike (*.FDI)\0*.FDI\0PovrÅ¡inske slike (*.86F;*.MFM)\0*.86F;*.MFM\0Vse datoteke (*.*)\0*.*\0" + IDS_2112 "Ne morem inicializirati SDL, potrebna je knjižica SDL2.dll" + IDS_2113 "Ste prepriÄani, da želite ponovno zagnati emulirani sistem?" + IDS_2114 "Ste prepriÄani, da želite zapreti 86Box?" + IDS_2115 "Ne morem inicializirati Ghostscript" + IDS_2116 "MO %i (%ls): %ls" + IDS_2117 "Slike MO (*.IM?;*.MDI)\0*.IM?;*.MDI\0Vse datoteke (*.*)\0*.*\0" + IDS_2118 "DobrodoÅ¡li v 86Box!" + IDS_2119 "Notranji krmilnik" + IDS_2120 "Izhod" + IDS_2121 "Nobeni ROM-i niso bili najdeni" + IDS_2122 "Želite shraniti nastavitve?" + IDS_2123 "To bo ponovno zagnalo emuliran sistem." + IDS_2124 "Shrani" + IDS_2125 "O programu 86Box" + IDS_2126 "86Box v" EMU_VERSION - IDS_2126 "Emulator starih raÄunalnikov\n\nAvtorji: Sarah Walker, Miran Grca, Fred N. van Kempen (waltje), SA1988, Tiseno100, reenigne, leilei, JohnElliott, greatpsycho in drugi.\n\nIzdano pod licenco GNU General Public License razliÄica 2 ali novejÅ¡a. Glej datoteko LICENSE za veÄ informacij." - IDS_2127 "V redu" - IDS_2128 "Strojna oprema ni na voljo" + IDS_2127 "Emulator starih raÄunalnikov\n\nAvtorji: Miran GrÄa (OBattler), RichardG867, Jasmine Iwanek, TC1995, coldbrewed, Teemu Korhonen (Manaatti), Joakim L. Gilje, Adrien Moulin (elyosh), Daniel Balsom (gloriouscow), Cacodemon345, Fred N. van Kempen (waltje), Tiseno100, reenigne in drugi.\n\nWith previous core contributions from Sarah Walker, leilei, JohnElliott, greatpsycho in drugi.\n\nIzdano pod licenco GNU General Public License razliÄica 2 ali novejÅ¡a. Glej datoteko LICENSE za veÄ informacij." + IDS_2128 "V redu" + IDS_2129 "Strojna oprema ni na voljo" #ifdef _WIN32 #define LIB_NAME_PCAP "WinPcap" #else #define LIB_NAME_PCAP "libpcap" #endif - IDS_2129 "PrepiÄajte se, da je nameÅ¡Äen " LIB_NAME_PCAP " in da ste na omrežni povezavi, združljivi z " LIB_NAME_PCAP - IDS_2130 "Neveljavna konfiguracija" -#ifdef _WIN32 -#define LIB_NAME_FREETYPE "freetype.dll" -#else -#define LIB_NAME_FREETYPE "libfreetype" -#endif - IDS_2131 LIB_NAME_FREETYPE " je potreben za emuliranje ESC/P tiskalnika." + IDS_2130 "PrepiÄajte se, da je nameÅ¡Äen " LIB_NAME_PCAP " in da ste na omrežni povezavi, združljivi z " LIB_NAME_PCAP + IDS_2131 "Neveljavna konfiguracija" #ifdef _WIN32 #define LIB_NAME_GS "gsdll32.dll" #else #define LIB_NAME_GS "libgs" #endif - IDS_2132 LIB_NAME_GS " je potreben za samodejno pretvorbo PostScript datotek v PDF.\n\nVsi dokumenti, poslani generiÄnemu PostScript tiskalniku bodo shranjeni kot PostScript (.ps) datoteke." -#ifdef _WIN32 -#define LIB_NAME_FLUIDSYNTH "libfluidsynth.dll" -#else -#define LIB_NAME_FLUIDSYNTH "libfluidsynth" -#endif - IDS_2133 LIB_NAME_FLUIDSYNTH " je potreben za FluidSynth MIDI izhod." - IDS_2134 "Preklapljam v celozaslonski naÄin" - IDS_2135 "Ne pokaži veÄ tega sporoÄila" - IDS_2136 "PrekliÄi izhod" - IDS_2137 "Resetiraj" - IDS_2138 "Ne resetiraj" - IDS_2139 "Slike MO (*.IM?;*.MDI)\0*.IM?;*.MDI\0Vse datoteke (*.*)\0*.*\0" - IDS_2140 "Slike CD-ROM (*.ISO;*.CUE)\0*.ISO;*.CUE\0Vse datoteke (*.*)\0*.*\0" - IDS_2141 "Konfiguracija naprave %hs" - IDS_2142 "Zaslon v naÄinu spanja" - IDS_2143 "SenÄilniki OpenGL (*.GLSL)\0*.GLSL\0Vse datoteke (*.*)\0*.*\0" - IDS_2144 "Možnosti OpenGL" - IDS_2145 "Nalagate nepodprto konfiguracijo" - IDS_2146 "Filtriranje vrste procesorja glede na izbran sistem je onemogoÄeno za ta emuliran sistem.\n\nTako lahko izberete procesor, ki je sicer nezdružljiv z izbranim sistemom. Vendar lahko naletite na nezdružljivosti z BIOS-om sistema ali drugo programsko opremo\n\nOmogoÄanje te nastavitve ni uradno podprto, vsa poroÄila o hroÅ¡Äih iz tega naslova pa bodo zaprta kot neveljavna." - IDS_2147 "Nadaljuj" - IDS_2148 "Kaseta: %s" - IDS_2149 "Slike kaset (*.PCM;*.RAW;*.WAV;*.CAS)\0*.PCM;*.RAW;*.WAV;*.CAS\0Vse datoteke (*.*)\0*.*\0" - IDS_2150 "Spominski vložek %i: %ls" - IDS_2151 "Slike spominskega vložka (*.A;*.B;*.JRC)\0*.A;*.B;*.JRC\0Vse datoteke (*.*)\0*.*\0" - IDS_2152 "Error initializing renderer" - IDS_2153 "OpenGL (3.0 Core) renderer could not be initialized. Use another renderer." - IDS_2154 "Resume execution" - IDS_2155 "Pause execution" - IDS_2156 "Press Ctrl+Alt+Del" - IDS_2157 "Press Ctrl+Alt+Esc" - IDS_2158 "Hard reset" - IDS_2159 "ACPI shutdown" - IDS_2160 "Settings" + IDS_2133 LIB_NAME_GS " je potreben za samodejno pretvorbo PostScript datotek v PDF.\n\nVsi dokumenti, poslani generiÄnemu PostScript tiskalniku bodo shranjeni kot PostScript (.ps) datoteke." + IDS_2135 "Preklapljam v celozaslonski naÄin" + IDS_2136 "Ne pokaži veÄ tega sporoÄila" + IDS_2137 "PrekliÄi izhod" + IDS_2138 "Resetiraj" + IDS_2139 "Ne resetiraj" + IDS_2140 "Slike MO (*.IM?;*.MDI)\0*.IM?;*.MDI\0Vse datoteke (*.*)\0*.*\0" + IDS_2141 "Slike CD-ROM (*.ISO;*.CUE)\0*.ISO;*.CUE\0Vse datoteke (*.*)\0*.*\0" + IDS_2142 "Konfiguracija naprave %hs" + IDS_2143 "Zaslon v naÄinu spanja" + IDS_2144 "SenÄilniki OpenGL (*.GLSL)\0*.GLSL\0Vse datoteke (*.*)\0*.*\0" + IDS_2145 "Možnosti OpenGL" + IDS_2146 "Nalagate nepodprto konfiguracijo" + IDS_2147 "Filtriranje vrste procesorja glede na izbran sistem je onemogoÄeno za ta emuliran sistem.\n\nTako lahko izberete procesor, ki je sicer nezdružljiv z izbranim sistemom. Vendar lahko naletite na nezdružljivosti z BIOS-om sistema ali drugo programsko opremo\n\nOmogoÄanje te nastavitve ni uradno podprto, vsa poroÄila o hroÅ¡Äih iz tega naslova pa bodo zaprta kot neveljavna." + IDS_2148 "Nadaljuj" + IDS_2149 "Kaseta: %s" + IDS_2150 "Slike kaset (*.PCM;*.RAW;*.WAV;*.CAS)\0*.PCM;*.RAW;*.WAV;*.CAS\0Vse datoteke (*.*)\0*.*\0" + IDS_2151 "Spominski vložek %i: %ls" + IDS_2152 "Slike spominskega vložka (*.A;*.B;*.JRC)\0*.A;*.B;*.JRC\0Vse datoteke (*.*)\0*.*\0" + IDS_2153 "Napaka pri zagonu sistema za upodabljanje" + IDS_2154 "Sistema za upodabljanje OpenGL (3.0 Core) ni bilo mogoÄe zagnati. Uporabite drug sistem za upodabljanje." + IDS_2155 "Nadaljuj izvajanje" + IDS_2156 "Prekini izvajanje" + IDS_2157 "Press Ctrl+Alt+Del" + IDS_2158 "Press Ctrl+Alt+Esc" + IDS_2159 "Ponovni zagon" + IDS_2160 "Zaustavitev ACPI" + IDS_2161 "Nastavitve" + IDS_2162 "Type" + IDS_2163 "No Dynarec" + IDS_2164 "Old Dynarec" + IDS_2165 "New Dynarec" + IDS_2166 "Video card #2 ""%hs"" is not available due to missing ROMs in the roms/video directory. Disabling the second video card." + IDS_2167 "Failed to initialize network driver" + IDS_2168 "The network configuration will be switched to the null driver" END -STRINGTABLE DISCARDABLE +STRINGTABLE DISCARDABLE BEGIN IDS_4096 "Trdi disk (%s)" - IDS_4097 "%01i:%01i" - IDS_4098 "%01i" - IDS_4099 "MFM/RLL ali ESDI pogoni CD-ROM niso nikoli obstajali" - IDS_4100 "Po meri..." - IDS_4101 "Po meri (velik)..." - IDS_4102 "Dodaj nov trdi disk" - IDS_4103 "Dodaj obstojeÄ trdi disk" - IDS_4104 "Slike diska HDI ne morejo biti veÄje od 4 GB." - IDS_4105 "Slike diska ne morejo biti veÄje od 127 GB." - IDS_4106 "Slike trdega diska (*.HD?;*.IM?;*.VHD)\0*.HD?;*.IM?;*.VHD\0Vse datoteke (*.*)\0*.*\0" - IDS_4107 "Ne morem prebrati datoteke" - IDS_4108 "Ne morem pisati v datoteko" - IDS_4109 "Slike HDI ali HDX, ki nimajo sektorjev velikosti 512 bajtov, niso podprte." - IDS_4110 "USB Å¡e ni podprt" - IDS_4111 "Datoteka s sliko diska že obstaja" - IDS_4112 "Prosim, navedite veljavno ime datoteke." - IDS_4113 "Slika diska ustvarjena" - IDS_4114 "PrepriÄajte se, da datoteka obstaja in je berljiva." - IDS_4115 "PrepriÄajte se, da datoteko shranjujete v zapisljivo mapo." - IDS_4116 "Slika diska je prevelika" - IDS_4117 "Ne pozabite na novem disku ustvariti particij in jih formatirati." - IDS_4118 "Izbrana datoteka bo prepisana. Ali jo res želite uporabiti?" - IDS_4119 "Nepodprta slika diska" - IDS_4120 "PrepiÅ¡i" - IDS_4121 "Ne prepiÅ¡i" - IDS_4122 "Surova slika (.img)" - IDS_4123 "Slika HDI (.hdi)" - IDS_4124 "Slika HDX (.hdx)" - IDS_4125 "VHD fiksne velikosti (.vhd)" - IDS_4126 "DinamiÄen VHD (.vhd)" - IDS_4127 "Diferencialni VHD (.vhd)" - IDS_4128 "Veliki bloki (2 MB)" - IDS_4129 "Mali bloki (512 KB)" - IDS_4130 "Datoteke VHD (*.VHD)\0*.VHD\0Vse datoteke (*.*)\0*.*\0" - IDS_4131 "Izberite starÅ¡evsko sliko VHD" - IDS_4132 "To lahko pomeni, da je bila starÅ¡evska slika spremenjena potem, ko je že bila ustvarjena diferencialna slika.\n\nDo tega lahko pride tudi kadar so datoteke slik diska premaknjene ali kopirane, ali pa gre za hroÅ¡Äa v programu, ki je ustvaril ta disk.\n\nŽelite popraviti Äasovni žig?" - IDS_4133 "ÄŒasovna žiga starÅ¡evske slike diska in slike diska otroka se ne ujemata" - IDS_4134 "Ne morem popraviti Äasovnega žiga slike VHD." - IDS_4135 "%01i:%02i" + IDS_4097 "%01i:%01i" + IDS_4098 "%01i" + IDS_4099 "MFM/RLL ali ESDI pogoni CD-ROM niso nikoli obstajali" + IDS_4100 "Po meri..." + IDS_4101 "Po meri (velik)..." + IDS_4102 "Dodaj nov trdi disk" + IDS_4103 "Dodaj obstojeÄ trdi disk" + IDS_4104 "Slike diska HDI ne morejo biti veÄje od 4 GB." + IDS_4105 "Slike diska ne morejo biti veÄje od 127 GB." + IDS_4106 "Slike trdega diska (*.HD?;*.IM?;*.VHD)\0*.HD?;*.IM?;*.VHD\0Vse datoteke (*.*)\0*.*\0" + IDS_4107 "Ne morem prebrati datoteke" + IDS_4108 "Ne morem pisati v datoteko" + IDS_4109 "Slike HDI ali HDX, ki nimajo sektorjev velikosti 512 bajtov, niso podprte." + IDS_4110 "USB Å¡e ni podprt" + IDS_4111 "Datoteka s sliko diska že obstaja" + IDS_4112 "Prosim, navedite veljavno ime datoteke." + IDS_4113 "Slika diska ustvarjena" + IDS_4114 "PrepriÄajte se, da datoteka obstaja in je berljiva." + IDS_4115 "PrepriÄajte se, da datoteko shranjujete v zapisljivo mapo." + IDS_4116 "Slika diska je prevelika" + IDS_4117 "Ne pozabite na novem disku ustvariti particij in jih formatirati." + IDS_4118 "Izbrana datoteka bo prepisana. Ali jo res želite uporabiti?" + IDS_4119 "Nepodprta slika diska" + IDS_4120 "PrepiÅ¡i" + IDS_4121 "Ne prepiÅ¡i" + IDS_4122 "Surova slika (.img)" + IDS_4123 "Slika HDI (.hdi)" + IDS_4124 "Slika HDX (.hdx)" + IDS_4125 "VHD fiksne velikosti (.vhd)" + IDS_4126 "DinamiÄen VHD (.vhd)" + IDS_4127 "Diferencialni VHD (.vhd)" + IDS_4128 "Veliki bloki (2 MB)" + IDS_4129 "Mali bloki (512 KB)" + IDS_4130 "Datoteke VHD (*.VHD)\0*.VHD\0Vse datoteke (*.*)\0*.*\0" + IDS_4131 "Izberite starÅ¡evsko sliko VHD" + IDS_4132 "To lahko pomeni, da je bila starÅ¡evska slika spremenjena potem, ko je že bila ustvarjena diferencialna slika.\n\nDo tega lahko pride tudi kadar so datoteke slik diska premaknjene ali kopirane, ali pa gre za hroÅ¡Äa v programu, ki je ustvaril ta disk.\n\nŽelite popraviti Äasovni žig?" + IDS_4133 "ÄŒasovna žiga starÅ¡evske slike diska in slike diska otroka se ne ujemata" + IDS_4134 "Ne morem popraviti Äasovnega žiga slike VHD." + IDS_4135 "%01i:%02i" IDS_4352 "MFM/RLL" IDS_4353 "XTA" @@ -562,56 +582,56 @@ BEGIN IDS_4356 "ATAPI" IDS_4357 "SCSI" - IDS_4608 "MFM/RLL (%01i:%01i)" - IDS_4609 "XTA (%01i:%01i)" - IDS_4610 "ESDI (%01i:%01i)" - IDS_4611 "IDE (%01i:%01i)" - IDS_4612 "ATAPI (%01i:%01i)" - IDS_4613 "SCSI (%01i:%02i)" + IDS_4608 "MFM/RLL (%01i:%01i)" + IDS_4609 "XTA (%01i:%01i)" + IDS_4610 "ESDI (%01i:%01i)" + IDS_4611 "IDE (%01i:%01i)" + IDS_4612 "ATAPI (%01i:%01i)" + IDS_4613 "SCSI (%01i:%02i)" - IDS_5120 "CD-ROM %i (%s): %s" + IDS_5120 "CD-ROM %i (%s): %s" - IDS_5376 "OnemogoÄeno" - IDS_5381 "ATAPI" + IDS_5376 "OnemogoÄeno" + IDS_5381 "ATAPI" IDS_5382 "SCSI" - IDS_5632 "OnemogoÄeno" - IDS_5637 "ATAPI (%01i:%01i)" + IDS_5632 "OnemogoÄeno" + IDS_5637 "ATAPI (%01i:%01i)" IDS_5638 "SCSI (%01i:%02i)" - IDS_5888 "160 kB" - IDS_5889 "180 kB" - IDS_5890 "320 kB" - IDS_5891 "360 kB" - IDS_5892 "640 kB" - IDS_5893 "720 kB" - IDS_5894 "1.2 MB" - IDS_5895 "1.25 MB" - IDS_5896 "1.44 MB" - IDS_5897 "DMF (grozd 1024)" - IDS_5898 "DMF (grozd 2048)" - IDS_5899 "2.88 MB" - IDS_5900 "ZIP 100" - IDS_5901 "ZIP 250" - IDS_5902 "3.5"" 128 MB (ISO 10090)" - IDS_5903 "3.5"" 230 MB (ISO 13963)" - IDS_5904 "3.5"" 540 MB (ISO 15498)" - IDS_5905 "3.5"" 640 MB (ISO 15498)" - IDS_5906 "3.5"" 1.3 GB (GigaMO)" - IDS_5907 "3.5"" 2.3 GB (GigaMO 2)" - IDS_5908 "5.25"" 600 MB" - IDS_5909 "5.25"" 650 MB" - IDS_5910 "5.25"" 1 GB" - IDS_5911 "5.25"" 1.3 GB" + IDS_5888 "160 kB" + IDS_5889 "180 kB" + IDS_5890 "320 kB" + IDS_5891 "360 kB" + IDS_5892 "640 kB" + IDS_5893 "720 kB" + IDS_5894 "1.2 MB" + IDS_5895 "1.25 MB" + IDS_5896 "1.44 MB" + IDS_5897 "DMF (grozd 1024)" + IDS_5898 "DMF (grozd 2048)" + IDS_5899 "2.88 MB" + IDS_5900 "ZIP 100" + IDS_5901 "ZIP 250" + IDS_5902 "3.5"" 128 MB (ISO 10090)" + IDS_5903 "3.5"" 230 MB (ISO 13963)" + IDS_5904 "3.5"" 540 MB (ISO 15498)" + IDS_5905 "3.5"" 640 MB (ISO 15498)" + IDS_5906 "3.5"" 1.3 GB (GigaMO)" + IDS_5907 "3.5"" 2.3 GB (GigaMO 2)" + IDS_5908 "5.25"" 600 MB" + IDS_5909 "5.25"" 650 MB" + IDS_5910 "5.25"" 1 GB" + IDS_5911 "5.25"" 1.3 GB" - IDS_6144 "Popolni obrati na minuto" - IDS_6145 "1% pod popolnimi obrati" - IDS_6146 "1.5% pod popolnimi obrati" - IDS_6147 "2% pod popolnimi obrati" + IDS_6144 "Popolni obrati na minuto" + IDS_6145 "1% pod popolnimi obrati" + IDS_6146 "1.5% pod popolnimi obrati" + IDS_6147 "2% pod popolnimi obrati" - IDS_7168 "(Sistemsko privzeto)" + IDS_7168 "(Sistemsko privzeto)" END -#define IDS_LANG_ENUS IDS_7168 +#define IDS_LANG_ENUS IDS_7168 // Slovenian resources ///////////////////////////////////////////////////////////////////////////// diff --git a/src/win/languages/tr-TR.rc b/src/win/languages/tr-TR.rc index ac0ab6400..78e7b4b87 100644 --- a/src/win/languages/tr-TR.rc +++ b/src/win/languages/tr-TR.rc @@ -13,113 +13,122 @@ LANGUAGE LANG_TURKISH, SUBLANG_DEFAULT // Menu // -MainMenu MENU DISCARDABLE +MainMenu MENU DISCARDABLE BEGIN POPUP "&Komutlar" BEGIN - MENUITEM "&Klavye sadece fare yakalandığında çalışsın", IDM_ACTION_KBD_REQ_CAPTURE - MENUITEM "&SaÄŸ CTRL tuÅŸunu sol ALT tuÅŸu olarak ayarla", IDM_ACTION_RCTRL_IS_LALT + MENUITEM "&Klavye sadece fare yakalandığında çalışsın", IDM_ACTION_KBD_REQ_CAPTURE + MENUITEM "&SaÄŸ CTRL tuÅŸunu sol ALT tuÅŸu olarak ayarla", IDM_ACTION_RCTRL_IS_LALT MENUITEM SEPARATOR - MENUITEM "&Makineyi yeniden baÅŸlat...", IDM_ACTION_HRESET - MENUITEM "&Ctrl+Alt+Del\tCtrl+F12", IDM_ACTION_RESET_CAD + MENUITEM "&Makineyi yeniden baÅŸlat...", IDM_ACTION_HRESET + MENUITEM "&Ctrl+Alt+Del\tCtrl+F12", IDM_ACTION_RESET_CAD MENUITEM SEPARATOR - MENUITEM "Ctrl+Alt+&Esc", IDM_ACTION_CTRL_ALT_ESC + MENUITEM "Ctrl+Alt+&Esc", IDM_ACTION_CTRL_ALT_ESC MENUITEM SEPARATOR - MENUITEM "&Duraklat", IDM_ACTION_PAUSE + MENUITEM "&Duraklat", IDM_ACTION_PAUSE MENUITEM SEPARATOR - MENUITEM "Emülatörden &çık...", IDM_ACTION_EXIT + MENUITEM "Emülatörden &çık...", IDM_ACTION_EXIT END POPUP "&Görüntüleme" BEGIN - MENUITEM "&Durum çubuÄŸunu gizle", IDM_VID_HIDE_STATUS_BAR - MENUITEM "Hide &toolbar", IDM_VID_HIDE_TOOLBAR + MENUITEM "&Durum çubuÄŸunu gizle", IDM_VID_HIDE_STATUS_BAR + MENUITEM "Hide &toolbar", IDM_VID_HIDE_TOOLBAR MENUITEM SEPARATOR - MENUITEM "&Yeniden boyutlandırılabilir pencere", IDM_VID_RESIZE - MENUITEM "&Pencere boyut ve pozisyonunu hatırla", IDM_VID_REMEMBER + MENUITEM "&Show non-primary monitors", IDM_VID_MONITORS + MENUITEM "&Yeniden boyutlandırılabilir pencere", IDM_VID_RESIZE + MENUITEM "&Pencere boyut ve pozisyonunu hatırla", IDM_VID_REMEMBER MENUITEM SEPARATOR POPUP "&İşleyici" BEGIN - MENUITEM "&SDL (Yazılım)", IDM_VID_SDL_SW - MENUITEM "SDL (&Donanım)", IDM_VID_SDL_HW - MENUITEM "SDL (&OpenGL)", IDM_VID_SDL_OPENGL - MENUITEM "Open&GL (3.0 Core)", IDM_VID_OPENGL_CORE + MENUITEM "&SDL (Yazılım)", IDM_VID_SDL_SW + MENUITEM "SDL (&Donanım)", IDM_VID_SDL_HW + MENUITEM "SDL (&OpenGL)", IDM_VID_SDL_OPENGL + MENUITEM "Open&GL (3.0 Core)", IDM_VID_OPENGL_CORE #ifdef USE_VNC - MENUITEM "&VNC", IDM_VID_VNC + MENUITEM "&VNC", IDM_VID_VNC #endif END MENUITEM SEPARATOR - MENUITEM "Pencere &boyutunu belirle...", IDM_VID_SPECIFY_DIM - MENUITEM "&4:3 görüntüleme oranına zorla", IDM_VID_FORCE43 + MENUITEM "Pencere &boyutunu belirle...", IDM_VID_SPECIFY_DIM + MENUITEM "&4:3 görüntüleme oranına zorla", IDM_VID_FORCE43 POPUP "Pencere &ölçek çarpanı" BEGIN - MENUITEM "&0.5x", IDM_VID_SCALE_1X - MENUITEM "&1x", IDM_VID_SCALE_2X - MENUITEM "1.&5x", IDM_VID_SCALE_3X - MENUITEM "&2x", IDM_VID_SCALE_4X + MENUITEM "&0.5x", IDM_VID_SCALE_1X + MENUITEM "&1x", IDM_VID_SCALE_2X + MENUITEM "1.&5x", IDM_VID_SCALE_3X + MENUITEM "&2x", IDM_VID_SCALE_4X + MENUITEM "&3x", IDM_VID_SCALE_5X + MENUITEM "&4x", IDM_VID_SCALE_6X + MENUITEM "&5x", IDM_VID_SCALE_7X + MENUITEM "&6x", IDM_VID_SCALE_8X + MENUITEM "&7x", IDM_VID_SCALE_9X + MENUITEM "&8x", IDM_VID_SCALE_10X END POPUP "&Filtre metodu" BEGIN - MENUITEM "&Nearest (En yakın)", IDM_VID_FILTER_NEAREST - MENUITEM "&Linear (DoÄŸrusal)", IDM_VID_FILTER_LINEAR + MENUITEM "&Nearest (En yakın)", IDM_VID_FILTER_NEAREST + MENUITEM "&Linear (DoÄŸrusal)", IDM_VID_FILTER_LINEAR END - MENUITEM "Hi&DPI ölçeklemesi", IDM_VID_HIDPI + MENUITEM "Hi&DPI ölçeklemesi", IDM_VID_HIDPI MENUITEM SEPARATOR - MENUITEM "&Tam ekran\tCtrl+Alt+PgUp", IDM_VID_FULLSCREEN + MENUITEM "&Tam ekran\tCtrl+Alt+PgUp", IDM_VID_FULLSCREEN POPUP "Tam ekran &germe modu" BEGIN - MENUITEM "&Tam ekrana ger", IDM_VID_FS_FULL - MENUITEM "&4:3", IDM_VID_FS_43 + MENUITEM "&Tam ekrana ger", IDM_VID_FS_FULL + MENUITEM "&4:3", IDM_VID_FS_43 MENUITEM "&Kare piksel (ölçeÄŸi koru)", IDM_VID_FS_KEEPRATIO - MENUITEM "Tam &sayı ölçeklemesi", IDM_VID_FS_INT + MENUITEM "Tam &sayı ölçeklemesi", IDM_VID_FS_INT END POPUP "EGA/&(S)VGA ayarları" BEGIN - MENUITEM "Ters &renk VGA monitör", IDM_VID_INVERT + MENUITEM "Ters &renk VGA monitör", IDM_VID_INVERT POPUP "VGA ekran &tipi" BEGIN - MENUITEM "RGB (&renkli)", IDM_VID_GRAY_RGB - MENUITEM "RGB (&gri tonlama)", IDM_VID_GRAY_MONO - MENUITEM "&Kehribar rengi monitör", IDM_VID_GRAY_AMBER - MENUITEM "&YeÅŸil renk monitör", IDM_VID_GRAY_GREEN - MENUITEM "&Beyaz renk monitör", IDM_VID_GRAY_WHITE + MENUITEM "RGB (&renkli)", IDM_VID_GRAY_RGB + MENUITEM "RGB (&gri tonlama)", IDM_VID_GRAY_MONO + MENUITEM "&Kehribar rengi monitör", IDM_VID_GRAY_AMBER + MENUITEM "&YeÅŸil renk monitör", IDM_VID_GRAY_GREEN + MENUITEM "&Beyaz renk monitör", IDM_VID_GRAY_WHITE END POPUP "&Gri tonlama dönüştürme tipi" BEGIN - MENUITEM "BT&601 (NTSC/PAL)", IDM_VID_GRAYCT_601 - MENUITEM "BT&709 (HDTV)", IDM_VID_GRAYCT_709 - MENUITEM "&Ortalama", IDM_VID_GRAYCT_AVE + MENUITEM "BT&601 (NTSC/PAL)", IDM_VID_GRAYCT_601 + MENUITEM "BT&709 (HDTV)", IDM_VID_GRAYCT_709 + MENUITEM "&Ortalama", IDM_VID_GRAYCT_AVE END END MENUITEM SEPARATOR - MENUITEM "CGA/PCjr/Tandy/E&GA/(S)VGA aşırı taraması", IDM_VID_OVERSCAN + MENUITEM "CGA/PCjr/Tandy/E&GA/(S)VGA aşırı taraması", IDM_VID_OVERSCAN MENUITEM "Gri to&nlamalı görüntü için kontrastı deÄŸiÅŸtir", IDM_VID_CGACON END - MENUITEM "&Medya", IDM_MEDIA + MENUITEM "&Medya", IDM_MEDIA POPUP "&Araçlar" BEGIN - MENUITEM "&Ayarlar...", IDM_CONFIG - MENUITEM "Durum &çubuÄŸu ikonlarını güncelle", IDM_UPDATE_ICONS + MENUITEM "&Ayarlar...", IDM_CONFIG + MENUITEM "Durum &çubuÄŸu ikonlarını güncelle", IDM_UPDATE_ICONS MENUITEM SEPARATOR - MENUITEM "&Ekran görüntüsü al\tCtrl+F11", IDM_ACTION_SCREENSHOT + MENUITEM "&Ekran görüntüsü al\tCtrl+F11", IDM_ACTION_SCREENSHOT MENUITEM SEPARATOR - MENUITEM "&Tercihler...", IDM_PREFERENCES + MENUITEM "&Tercihler...", IDM_PREFERENCES +#ifdef DISCORD MENUITEM "&Discord entegrasyonunu etkinleÅŸtir", IDM_DISCORD +#endif MENUITEM SEPARATOR - MENUITEM "&Ses yükseltici...", IDM_SND_GAIN + MENUITEM "&Ses yükseltici...", IDM_SND_GAIN #ifdef MTR_ENABLED MENUITEM SEPARATOR - MENUITEM "Begin trace\tCtrl+T", IDM_ACTION_BEGIN_TRACE - MENUITEM "End trace\tCtrl+T", IDM_ACTION_END_TRACE + MENUITEM "Begin trace\tCtrl+T", IDM_ACTION_BEGIN_TRACE + MENUITEM "End trace\tCtrl+T", IDM_ACTION_END_TRACE #endif END POPUP "&Yardım" BEGIN - MENUITEM "&Dökümanlar...", IDM_DOCS - MENUITEM "&86Box Hakkında...", IDM_ABOUT + MENUITEM "&Dökümanlar...", IDM_DOCS + MENUITEM "&86Box Hakkında...", IDM_ABOUT END END -StatusBarMenu MENU DISCARDABLE +StatusBarMenu MENU DISCARDABLE BEGIN MENUITEM SEPARATOR END @@ -128,17 +137,17 @@ CassetteSubmenu MENU DISCARDABLE BEGIN POPUP "" BEGIN - MENUITEM "&Yeni imaj oluÅŸtur...", IDM_CASSETTE_IMAGE_NEW + MENUITEM "&Yeni imaj oluÅŸtur...", IDM_CASSETTE_IMAGE_NEW MENUITEM SEPARATOR - MENUITEM "&İmaj seç...", IDM_CASSETTE_IMAGE_EXISTING - MENUITEM "İmaj &seç (Yazma-korumalı)...", IDM_CASSETTE_IMAGE_EXISTING_WP + MENUITEM "&İmaj seç...", IDM_CASSETTE_IMAGE_EXISTING + MENUITEM "İmaj &seç (Yazma-korumalı)...", IDM_CASSETTE_IMAGE_EXISTING_WP MENUITEM SEPARATOR - MENUITEM "&Kaydet", IDM_CASSETTE_RECORD - MENUITEM "&Oynat", IDM_CASSETTE_PLAY - MENUITEM "&BaÅŸlangıca geri sar", IDM_CASSETTE_REWIND - MENUITEM "Sona doÄŸru &ileri sar", IDM_CASSETTE_FAST_FORWARD + MENUITEM "&Kaydet", IDM_CASSETTE_RECORD + MENUITEM "&Oynat", IDM_CASSETTE_PLAY + MENUITEM "&BaÅŸlangıca geri sar", IDM_CASSETTE_REWIND + MENUITEM "Sona doÄŸru &ileri sar", IDM_CASSETTE_FAST_FORWARD MENUITEM SEPARATOR - MENUITEM "&Çıkar", IDM_CASSETTE_EJECT + MENUITEM "&Çıkar", IDM_CASSETTE_EJECT END END @@ -146,9 +155,9 @@ CartridgeSubmenu MENU DISCARDABLE BEGIN POPUP "" BEGIN - MENUITEM "&İmaj...", IDM_CARTRIDGE_IMAGE + MENUITEM "&İmaj...", IDM_CARTRIDGE_IMAGE MENUITEM SEPARATOR - MENUITEM "&Çıkar", IDM_CARTRIDGE_EJECT + MENUITEM "&Çıkar", IDM_CARTRIDGE_EJECT END END @@ -156,14 +165,14 @@ FloppySubmenu MENU DISCARDABLE BEGIN POPUP "" BEGIN - MENUITEM "&Yeni imaj oluÅŸtur...", IDM_FLOPPY_IMAGE_NEW + MENUITEM "&Yeni imaj oluÅŸtur...", IDM_FLOPPY_IMAGE_NEW MENUITEM SEPARATOR - MENUITEM "&İmaj seç...", IDM_FLOPPY_IMAGE_EXISTING - MENUITEM "İmaj &seç (Yazma-korumalı)...", IDM_FLOPPY_IMAGE_EXISTING_WP + MENUITEM "&İmaj seç...", IDM_FLOPPY_IMAGE_EXISTING + MENUITEM "İmaj &seç (Yazma-korumalı)...", IDM_FLOPPY_IMAGE_EXISTING_WP MENUITEM SEPARATOR - MENUITEM "&86F dosyası olarak aktar...", IDM_FLOPPY_EXPORT_TO_86F + MENUITEM "&86F dosyası olarak aktar...", IDM_FLOPPY_EXPORT_TO_86F MENUITEM SEPARATOR - MENUITEM "&Çıkar", IDM_FLOPPY_EJECT + MENUITEM "&Çıkar", IDM_FLOPPY_EJECT END END @@ -171,12 +180,13 @@ CdromSubmenu MENU DISCARDABLE BEGIN POPUP "" BEGIN - MENUITEM "&Sesi kapat", IDM_CDROM_MUTE + MENUITEM "&Sesi kapat", IDM_CDROM_MUTE MENUITEM SEPARATOR - MENUITEM "İmajı &çıkar", IDM_CDROM_EMPTY - MENUITEM "&Önceki imajı seç", IDM_CDROM_RELOAD + MENUITEM "İmajı &çıkar", IDM_CDROM_EMPTY + MENUITEM "&Önceki imajı seç", IDM_CDROM_RELOAD MENUITEM SEPARATOR - MENUITEM "&İmaj seç", IDM_CDROM_IMAGE + MENUITEM "&İmaj seç...", IDM_CDROM_IMAGE + MENUITEM "&Klasör...", IDM_CDROM_DIR END END @@ -184,13 +194,13 @@ ZIPSubmenu MENU DISCARDABLE BEGIN POPUP "" BEGIN - MENUITEM "&Yeni imaj...", IDM_ZIP_IMAGE_NEW + MENUITEM "&Yeni imaj...", IDM_ZIP_IMAGE_NEW MENUITEM SEPARATOR - MENUITEM "&İmaj seç...", IDM_ZIP_IMAGE_EXISTING - MENUITEM "İmaj &seç (Yazma-korumalı)...", IDM_ZIP_IMAGE_EXISTING_WP + MENUITEM "&İmaj seç...", IDM_ZIP_IMAGE_EXISTING + MENUITEM "İmaj &seç (Yazma-korumalı)...", IDM_ZIP_IMAGE_EXISTING_WP MENUITEM SEPARATOR - MENUITEM "&Çıkar", IDM_ZIP_EJECT - MENUITEM "&Önceki imajı seç", IDM_ZIP_RELOAD + MENUITEM "&Çıkar", IDM_ZIP_EJECT + MENUITEM "&Önceki imajı seç", IDM_ZIP_RELOAD END END @@ -198,13 +208,13 @@ MOSubmenu MENU DISCARDABLE BEGIN POPUP "" BEGIN - MENUITEM "&Yeni imaj...", IDM_MO_IMAGE_NEW + MENUITEM "&Yeni imaj...", IDM_MO_IMAGE_NEW MENUITEM SEPARATOR - MENUITEM "&İmaj seç...", IDM_MO_IMAGE_EXISTING - MENUITEM "İmaj &seç (Yazma-korumalı)...", IDM_MO_IMAGE_EXISTING_WP + MENUITEM "&İmaj seç...", IDM_MO_IMAGE_EXISTING + MENUITEM "İmaj &seç (Yazma-korumalı)...", IDM_MO_IMAGE_EXISTING_WP MENUITEM SEPARATOR - MENUITEM "&Çıkar", IDM_MO_EJECT - MENUITEM "&Önceki imajı seç", IDM_MO_RELOAD + MENUITEM "&Çıkar", IDM_MO_EJECT + MENUITEM "&Önceki imajı seç", IDM_MO_RELOAD END END @@ -230,134 +240,150 @@ END // Dialog // -#define STR_PREFERENCES "Tercihler" -#define STR_SND_GAIN "Ses Artırma" -#define STR_NEW_FLOPPY "Yeni İmaj" -#define STR_CONFIG "Ayarlar" -#define STR_SPECIFY_DIM "Ana Pencere Boyutunu Belirle" +#define STR_PREFERENCES "Tercihler" +#define STR_SND_GAIN "Ses Artırma" +#define STR_NEW_FLOPPY "Yeni İmaj" +#define STR_CONFIG "Ayarlar" +#define STR_SPECIFY_DIM "Ana Pencere Boyutunu Belirle" -#define STR_OK "Tamam" -#define STR_CANCEL "İptal et" -#define STR_GLOBAL "Bu ayarları &varsayılan olarak kaydet" -#define STR_DEFAULT "&Varsayılan" -#define STR_LANGUAGE "Dil:" -#define STR_ICONSET "Simge seti:" +#define STR_OK "Tamam" +#define STR_CANCEL "İptal et" +#define STR_GLOBAL "Bu ayarları &varsayılan olarak kaydet" +#define STR_DEFAULT "&Varsayılan" +#define STR_LANGUAGE "Dil:" +#define STR_ICONSET "Simge seti:" -#define STR_GAIN "Artırma" +#define STR_GAIN "Artırma" -#define STR_FILE_NAME "Dosya adı:" -#define STR_DISK_SIZE "Disk boyutu:" -#define STR_RPM_MODE "RPM modu:" -#define STR_PROGRESS "İşlem:" +#define STR_FILE_NAME "Dosya adı:" +#define STR_DISK_SIZE "Disk boyutu:" +#define STR_RPM_MODE "RPM modu:" +#define STR_PROGRESS "İşlem:" -#define STR_WIDTH "GeniÅŸlik:" -#define STR_HEIGHT "Yükseklik:" -#define STR_LOCK_TO_SIZE "Bu boyuta kilitle" +#define STR_WIDTH "GeniÅŸlik:" +#define STR_HEIGHT "Yükseklik:" +#define STR_LOCK_TO_SIZE "Bu boyuta kilitle" -#define STR_MACHINE_TYPE "Makine türü:" -#define STR_MACHINE "Makine:" -#define STR_CONFIGURE "Ayarla" -#define STR_CPU_TYPE "CPU türü:" -#define STR_CPU_SPEED "Hız:" -#define STR_FPU "FPU:" -#define STR_WAIT_STATES "Bekleme süreleri:" -#define STR_MB "MB" -#define STR_MEMORY "Bellek:" -#define STR_TIME_SYNC "Zaman senkronizasyonu" -#define STR_DISABLED "Devre dışı" -#define STR_ENABLED_LOCAL "Etkin (yerel zaman)" -#define STR_ENABLED_UTC "Etkin (UTC)" -#define STR_DYNAREC "Dinamik Derleyici" +#define STR_MACHINE_TYPE "Makine türü:" +#define STR_MACHINE "Makine:" +#define STR_CONFIGURE "Ayarla" +#define STR_CPU_TYPE "CPU türü:" +#define STR_CPU_SPEED "Hız:" +#define STR_FPU "FPU:" +#define STR_WAIT_STATES "Bekleme süreleri:" +#define STR_MB "MB" +#define STR_MEMORY "Bellek:" +#define STR_TIME_SYNC "Zaman senkronizasyonu" +#define STR_DISABLED "Devre dışı" +#define STR_ENABLED_LOCAL "Etkin (yerel zaman)" +#define STR_ENABLED_UTC "Etkin (UTC)" +#define STR_DYNAREC "Dinamik Derleyici" +#define STR_SOFTFLOAT "Softfloat FPU" -#define STR_VIDEO "Ekran kartı:" -#define STR_VOODOO "Voodoo Grafikleri" +#define STR_VIDEO "Ekran kartı:" +#define STR_VIDEO_2 "Ekran kartı 2:" +#define STR_VOODOO "Voodoo Grafikleri" +#define STR_IBM8514 "IBM 8514/a Grafikleri" +#define STR_XGA "XGA Grafikleri" -#define STR_MOUSE "Fare:" -#define STR_JOYSTICK "Oyun kolu:" -#define STR_JOY1 "Oyun kolu 1..." -#define STR_JOY2 "Oyun kolu 2..." -#define STR_JOY3 "Oyun kolu 3..." -#define STR_JOY4 "Oyun kolu 4..." +#define STR_MOUSE "Fare:" +#define STR_JOYSTICK "Oyun kolu:" +#define STR_JOY1 "Oyun kolu 1..." +#define STR_JOY2 "Oyun kolu 2..." +#define STR_JOY3 "Oyun kolu 3..." +#define STR_JOY4 "Oyun kolu 4..." -#define STR_SOUND "Ses kartı:" -#define STR_MIDI_OUT "MIDI Çıkış Cihazı:" -#define STR_MIDI_IN "MIDI GiriÅŸ Cihazı:" -#define STR_MPU401 "Bağımsız MPU-401" -#define STR_SSI "Innovation SSI-2001" -#define STR_CMS "CMS / Game Blaster" -#define STR_GUS "Gravis Ultrasound" -#define STR_FLOAT "FLOAT32 ses kullan" +#define STR_SOUND1 "Ses kartı 1:" +#define STR_SOUND2 "Ses kartı 2:" +#define STR_SOUND3 "Ses kartı 3:" +#define STR_SOUND4 "Ses kartı 4:" +#define STR_MIDI_OUT "MIDI Çıkış Cihazı:" +#define STR_MIDI_IN "MIDI GiriÅŸ Cihazı:" +#define STR_MPU401 "Bağımsız MPU-401" +#define STR_FLOAT "FLOAT32 ses kullan" +#define STR_FM_DRIVER "FM sentez sürücüsü" +#define STR_FM_DRV_NUKED "Nuked (daha doÄŸru)" +#define STR_FM_DRV_YMFM "YMFM (daha hızlı)" -#define STR_NET_TYPE "AÄŸ tipi:" -#define STR_PCAP "PCap cihazı:" -#define STR_NET "AÄŸ cihazı:" +#define STR_NET_TYPE "AÄŸ tipi:" +#define STR_PCAP "PCap cihazı:" +#define STR_NET "AÄŸ cihazı:" +#define STR_NET1 "Network card 1:" +#define STR_NET2 "Network card 2:" +#define STR_NET3 "Network card 3:" +#define STR_NET4 "Network card 4:" -#define STR_COM1 "COM1 Cihazı:" -#define STR_COM2 "COM2 Cihazı:" -#define STR_COM3 "COM3 Cihazı:" -#define STR_COM4 "COM4 Cihazı:" -#define STR_LPT1 "LPT1 Cihazı:" -#define STR_LPT2 "LPT2 Cihazı:" -#define STR_LPT3 "LPT3 Cihazı:" -#define STR_LPT4 "LPT4 Cihazı:" -#define STR_SERIAL1 "Seri port 1" -#define STR_SERIAL2 "Seri port 2" -#define STR_SERIAL3 "Seri port 3" -#define STR_SERIAL4 "Seri port 4" -#define STR_PARALLEL1 "Paralel port 1" -#define STR_PARALLEL2 "Paralel port 2" -#define STR_PARALLEL3 "Paralel port 3" -#define STR_PARALLEL4 "Paralel port 4" +#define STR_COM1 "COM1 Cihazı:" +#define STR_COM2 "COM2 Cihazı:" +#define STR_COM3 "COM3 Cihazı:" +#define STR_COM4 "COM4 Cihazı:" +#define STR_LPT1 "LPT1 Cihazı:" +#define STR_LPT2 "LPT2 Cihazı:" +#define STR_LPT3 "LPT3 Cihazı:" +#define STR_LPT4 "LPT4 Cihazı:" +#define STR_SERIAL1 "Seri port 1" +#define STR_SERIAL2 "Seri port 2" +#define STR_SERIAL3 "Seri port 3" +#define STR_SERIAL4 "Seri port 4" +#define STR_PARALLEL1 "Paralel port 1" +#define STR_PARALLEL2 "Paralel port 2" +#define STR_PARALLEL3 "Paralel port 3" +#define STR_PARALLEL4 "Paralel port 4" +#define STR_SERIAL_PASS1 "Serial port passthrough 1" +#define STR_SERIAL_PASS2 "Serial port passthrough 2" +#define STR_SERIAL_PASS3 "Serial port passthrough 3" +#define STR_SERIAL_PASS4 "Serial port passthrough 4" -#define STR_HDC "HD Kontrolcüsü:" -#define STR_FDC "FD Kontrolcüsü:" -#define STR_IDE_TER "Üçlü IDE Kontrolcüsü" -#define STR_IDE_QUA "Dörtlü IDE Kontrolcüsü" -#define STR_SCSI "SCSI" -#define STR_SCSI_1 "Kontrolcü 1:" -#define STR_SCSI_2 "Kontrolcü 2:" -#define STR_SCSI_3 "Kontrolcü 3:" -#define STR_SCSI_4 "Kontrolcü 4:" -#define STR_CASSETTE "Kaset" +#define STR_HDC "HD Kontrolcüsü:" +#define STR_FDC "FD Kontrolcüsü:" +#define STR_IDE_TER "Üçlü IDE Kontrolcüsü" +#define STR_IDE_QUA "Dörtlü IDE Kontrolcüsü" +#define STR_SCSI "SCSI" +#define STR_SCSI_1 "Kontrolcü 1:" +#define STR_SCSI_2 "Kontrolcü 2:" +#define STR_SCSI_3 "Kontrolcü 3:" +#define STR_SCSI_4 "Kontrolcü 4:" +#define STR_CASSETTE "Kaset" -#define STR_HDD "Hard diskler:" -#define STR_NEW "&Yeni..." -#define STR_EXISTING "&Var olan..." -#define STR_REMOVE "&Kaldır" -#define STR_BUS "Veri yolu:" -#define STR_CHANNEL "Kanal:" -#define STR_ID "ID:" +#define STR_HDD "Hard diskler:" +#define STR_NEW "&Yeni..." +#define STR_EXISTING "&Var olan..." +#define STR_REMOVE "&Kaldır" +#define STR_BUS "Veri yolu:" +#define STR_CHANNEL "Kanal:" +#define STR_ID "ID:" +#define STR_SPEED "Speed:" -#define STR_SPECIFY "&Belirle..." -#define STR_SECTORS "Sektörler:" -#define STR_HEADS "Veri Kafaları:" -#define STR_CYLS "Silindirler:" -#define STR_SIZE_MB "Boyut (MB):" -#define STR_TYPE "Tip:" -#define STR_IMG_FORMAT "İmaj Düzeni:" -#define STR_BLOCK_SIZE "Blok Boyutu:" +#define STR_SPECIFY "&Belirle..." +#define STR_SECTORS "Sektörler:" +#define STR_HEADS "Veri Kafaları:" +#define STR_CYLS "Silindirler:" +#define STR_SIZE_MB "Boyut (MB):" +#define STR_TYPE "Tip:" +#define STR_IMG_FORMAT "İmaj Düzeni:" +#define STR_BLOCK_SIZE "Blok Boyutu:" -#define STR_FLOPPY_DRIVES "Disket sürücüleri:" -#define STR_TURBO "Turbo zamanlamaları" -#define STR_CHECKBPB "BPB'yi denetle" -#define STR_CDROM_DRIVES "CD-ROM sürücüleri:" -#define STR_CD_SPEED "Hız:" +#define STR_FLOPPY_DRIVES "Disket sürücüleri:" +#define STR_TURBO "Turbo zamanlamaları" +#define STR_CHECKBPB "BPB'yi denetle" +#define STR_CDROM_DRIVES "CD-ROM sürücüleri:" +#define STR_CD_SPEED "Hız:" -#define STR_MO_DRIVES "MO sürücüleri:" -#define STR_ZIP_DRIVES "ZIP sürücüleri:" -#define STR_250 "ZIP 250" +#define STR_MO_DRIVES "MO sürücüleri:" +#define STR_ZIP_DRIVES "ZIP sürücüleri:" +#define STR_250 "ZIP 250" -#define STR_ISARTC "ISA RTC:" -#define STR_ISAMEM "ISA Bellek Artırma" -#define STR_ISAMEM_1 "Kart 1:" -#define STR_ISAMEM_2 "Kart 2:" -#define STR_ISAMEM_3 "Kart 3:" -#define STR_ISAMEM_4 "Kart 4:" -#define STR_BUGGER "ISABugger cihazı" -#define STR_POSTCARD "POST kartı" +#define STR_ISARTC "ISA RTC:" +#define STR_ISAMEM "ISA Bellek Artırma" +#define STR_ISAMEM_1 "Kart 1:" +#define STR_ISAMEM_2 "Kart 2:" +#define STR_ISAMEM_3 "Kart 3:" +#define STR_ISAMEM_4 "Kart 4:" +#define STR_BUGGER "ISABugger cihazı" +#define STR_POSTCARD "POST kartı" -#define FONT_SIZE 9 -#define FONT_NAME "Segoe UI" +#define FONT_SIZE 9 +#define FONT_NAME "Segoe UI" #include "dialogs.rc" @@ -366,194 +392,188 @@ END // String Table // -STRINGTABLE DISCARDABLE +STRINGTABLE DISCARDABLE BEGIN - 2048 "86Box" - IDS_2049 "Hata" - IDS_2050 "Kritik hata" - IDS_2051 " - PAUSED" - IDS_2052 "Pencere moduna geri dönmek için Ctrl+Alt+PgDn tuÅŸlarına basın." - IDS_2053 "Hız" - IDS_2054 "ZIP %03i %i (%s): %ls" - IDS_2055 "ZIP imajları (*.IM?;*.ZDI)\0*.IM?;*.ZDI\0" - IDS_2056 "86Box hiç bir kullanılabilir ROM imajı bulamadı.\n\nLütfen ROM setini indirin ve onu ""Roms"" klasörüne çıkarın." - IDS_2057 "(empty)" - IDS_2058 "ZIP imajları (*.IM?;*.ZDI)\0*.IM?;*.ZDI\0All files (*.*)\0*.*\0" - IDS_2059 "Turbo" - IDS_2060 "Açık" - IDS_2061 "Kapalı" - IDS_2062 "Tüm imajlar (*.86F;*.DSK;*.FLP;*.IM?;*.*FD?)\0*.86F;*.DSK;*.FLP;*.IM?;*.*FD?\0Basit sektör imajları (*.DSK;*.FLP;*.IM?;*.*FD?)\0*.DSK;*.FLP;*.IM?;*.IMG;*.*FD?\0Yüzey imajları (*.86F)\0*.86F\0" - IDS_2063 """%hs"" makinesi roms/machines klasöründe mevcut olmayan ROM imajı yüzünden mevcut deÄŸil. Mevcut olan bir makineye geçiÅŸ yapılıyor." + 2048 "86Box" + IDS_2049 "Hata" + IDS_2050 "Kritik hata" + IDS_2051 " - PAUSED" + IDS_2052 "Pencere moduna geri dönmek için Ctrl+Alt+PgDn tuÅŸlarına basın." + IDS_2053 "Hız" + IDS_2054 "ZIP %03i %i (%s): %ls" + IDS_2055 "ZIP imajları (*.IM?;*.ZDI)\0*.IM?;*.ZDI\0" + IDS_2056 "86Box hiç bir kullanılabilir ROM imajı bulamadı.\n\nLütfen ROM setini indirin ve onu ""Roms"" klasörüne çıkarın." + IDS_2057 "(empty)" + IDS_2058 "ZIP imajları (*.IM?;*.ZDI)\0*.IM?;*.ZDI\0All files (*.*)\0*.*\0" + IDS_2059 "Turbo" + IDS_2060 "Açık" + IDS_2061 "Kapalı" + IDS_2062 "Tüm imajlar (*.86F;*.DSK;*.FLP;*.IM?;*.*FD?)\0*.86F;*.DSK;*.FLP;*.IM?;*.*FD?\0Basit sektör imajları (*.DSK;*.FLP;*.IM?;*.*FD?)\0*.DSK;*.FLP;*.IM?;*.IMG;*.*FD?\0Yüzey imajları (*.86F)\0*.86F\0" + IDS_2063 """%hs"" makinesi roms/machines klasöründe mevcut olmayan ROM imajı yüzünden mevcut deÄŸil. Mevcut olan bir makineye geçiÅŸ yapılıyor." END -STRINGTABLE DISCARDABLE +STRINGTABLE DISCARDABLE BEGIN - IDS_2064 """%hs"" ekran kartı roms/video klasöründe mevcut olmayan ROM imajı yüzünden mevcut deÄŸil. Mevcut olan bir ekran kartına geçiÅŸ yapılıyor." - IDS_2065 "Makine" - IDS_2066 "Görüntü" - IDS_2067 "GiriÅŸ aygıtları" - IDS_2068 "Ses" - IDS_2069 "AÄŸ" - IDS_2070 "Portlar (COM & LPT)" - IDS_2071 "Depolama kontrolcüleri" - IDS_2072 "Hard diskler" - IDS_2073 "Disket & CD-ROM sürücüleri" - IDS_2074 "DiÄŸer kaldırılabilir cihazlar" - IDS_2075 "DiÄŸer cihazlar" - IDS_2076 "Yüzey imajları (*.86F)\0*.86F\0" - IDS_2077 "Farenin yakalanması için tıklayın" - IDS_2078 "Farenin bırakılması için F8+F12 tuÅŸlarına basın" - IDS_2079 "Farenin bırakılması için F8+F12 veya farenin orta tuÅŸuna basın" + IDS_2064 """%hs"" ekran kartı roms/video klasöründe mevcut olmayan ROM imajı yüzünden mevcut deÄŸil. Mevcut olan bir ekran kartına geçiÅŸ yapılıyor." + IDS_2065 "Makine" + IDS_2066 "Görüntü" + IDS_2067 "GiriÅŸ aygıtları" + IDS_2068 "Ses" + IDS_2069 "AÄŸ" + IDS_2070 "Portlar (COM & LPT)" + IDS_2071 "Depolama kontrolcüleri" + IDS_2072 "Hard diskler" + IDS_2073 "Disket & CD-ROM sürücüleri" + IDS_2074 "DiÄŸer kaldırılabilir cihazlar" + IDS_2075 "DiÄŸer cihazlar" + IDS_2076 "Yüzey imajları (*.86F)\0*.86F\0" + IDS_2077 "Farenin yakalanması için tıklayın" + IDS_2078 "Farenin bırakılması için F8+F12 tuÅŸlarına basın" + IDS_2079 "Farenin bırakılması için F8+F12 veya farenin orta tuÅŸuna basın" END -STRINGTABLE DISCARDABLE +STRINGTABLE DISCARDABLE BEGIN - IDS_2080 "FluidSynth baÅŸlatılamadı" - IDS_2081 "Veri yolu" - IDS_2082 "Dosya" - IDS_2083 "C" - IDS_2084 "H" - IDS_2085 "S" - IDS_2086 "MB" - IDS_2087 "BPB'yi kontrol et" - IDS_2088 "KB" - IDS_2089 "Video iÅŸleyici baÅŸlatılamadı." - IDS_2090 "Varsayılan" - IDS_2091 "%i Bekleme durumları" - IDS_2092 "Tür" - IDS_2093 "PCap ayarlanamadı" - IDS_2094 "Herhangi bir PCap cihazı bulunamadı" - IDS_2095 "Geçersiz PCap cihazı" - IDS_2096 "Standart 2-button oyun kolları" - IDS_2097 "Standart 4-button oyun kolu" - IDS_2098 "Standart 6-button oyun kolu" - IDS_2099 "Standart 8-button oyun kolu" - IDS_2100 "CH Flightstick Pro" - IDS_2101 "Microsoft SideWinder Pad" - IDS_2102 "Thrustmaster Flight Kontrol Sistemi" - IDS_2103 "Hiçbiri" - IDS_2104 "Klavye ivdirgeçleri yüklenemedi." - IDS_2105 "Ham girdi kaydedilemedi." - IDS_2106 "%u" - IDS_2107 "%u MB (CHS: %i, %i, %i)" - IDS_2108 "Disket %i (%s): %ls" - IDS_2109 "Tüm imajlar (*.0??;*.1??;*.??0;*.86F;*.BIN;*.CQ?;*.D??;*.FLP;*.HDM;*.IM?;*.JSON;*.TD0;*.*FD?;*.MFM;*.XDF)\0*.0??;*.1??;*.??0;*.86F;*.BIN;*.CQ?;*.D??;*.FLP;*.HDM;*.IM?;*.JSON;*.TD0;*.*FD?;*.MFM;*.XDF\0GeliÅŸmiÅŸ sektör imajları (*.IMD;*.JSON;*.TD0)\0*.IMD;*.JSON;*.TD0\0Basit sektör imajları (*.0??;*.1??;*.??0;*.BIN;*.CQ?;*.D??;*.FLP;*.HDM;*.IM?;*.XDF;*.*FD?)\0*.0??;*.1??;*.??0;*.BIN;*.CQ?;*.D??;*.FLP;*.HDM;*.IM?;*.XDF;*.*FD?\0Flux images (*.FDI)\0*.FDI\0Yüzey imajları (*.86F;*.MFM)\0*.86F;*.MFM\0All files (*.*)\0*.*\0" - IDS_2110 "FreeType baÅŸlatılamadı" - IDS_2111 "SDL baÅŸlatılamadı, SDL2.dll gerekmektedir" - IDS_2112 "Emüle edilen makineyi yeniden baÅŸlatmak istediÄŸinizden emin misiniz?" - IDS_2113 "86Box'tan çıkmak istediÄŸinize emin misiniz?" - IDS_2114 "Ghostscript baÅŸlatılamadı" - IDS_2115 "MO %i (%ls): %ls" - IDS_2116 "MO imajları (*.IM?;*.MDI)\0*.IM?;*.MDI\0All files (*.*)\0*.*\0" - IDS_2117 "86Box'a hoÅŸgeldiniz!" - IDS_2118 "Dahili kontrolcü" - IDS_2119 "Çıkış" - IDS_2120 "Hiçbir ROM imajı bulunamadı" - IDS_2121 "Ayarları kaydetmek istediÄŸinizden emin misiniz?" - IDS_2122 "Bu makineyi yeniden baÅŸlatacak." - IDS_2123 "Kaydet" - IDS_2124 "86Box Hakkında" - IDS_2125 "86Box v" EMU_VERSION + IDS_2081 "Veri yolu" + IDS_2082 "Dosya" + IDS_2083 "C" + IDS_2084 "H" + IDS_2085 "S" + IDS_2086 "MB" + IDS_2087 "Speed" + IDS_2088 "BPB'yi kontrol et" + IDS_2089 "KB" + IDS_2090 "Video iÅŸleyici baÅŸlatılamadı." + IDS_2091 "Varsayılan" + IDS_2092 "%i Bekleme durumları" + IDS_2093 "Tür" + IDS_2094 "PCap ayarlanamadı" + IDS_2095 "Herhangi bir PCap cihazı bulunamadı" + IDS_2096 "Geçersiz PCap cihazı" + IDS_2097 "Standart 2-button oyun kolları" + IDS_2098 "Standart 4-button oyun kolu" + IDS_2099 "Standart 6-button oyun kolu" + IDS_2100 "Standart 8-button oyun kolu" + IDS_2101 "CH Flightstick Pro" + IDS_2102 "Microsoft SideWinder Pad" + IDS_2103 "Thrustmaster Flight Kontrol Sistemi" + IDS_2104 "Hiçbiri" + IDS_2105 "Klavye ivdirgeçleri yüklenemedi." + IDS_2106 "Ham girdi kaydedilemedi." + IDS_2107 "%u" + IDS_2108 "%u MB (CHS: %i, %i, %i)" + IDS_2109 "Disket %i (%s): %ls" + IDS_2110 "Tüm imajlar (*.0??;*.1??;*.??0;*.86F;*.BIN;*.CQ?;*.D??;*.FLP;*.HDM;*.IM?;*.JSON;*.TD0;*.*FD?;*.MFM;*.XDF)\0*.0??;*.1??;*.??0;*.86F;*.BIN;*.CQ?;*.D??;*.FLP;*.HDM;*.IM?;*.JSON;*.TD0;*.*FD?;*.MFM;*.XDF\0GeliÅŸmiÅŸ sektör imajları (*.IMD;*.JSON;*.TD0)\0*.IMD;*.JSON;*.TD0\0Basit sektör imajları (*.0??;*.1??;*.??0;*.BIN;*.CQ?;*.D??;*.FLP;*.HDM;*.IM?;*.XDF;*.*FD?)\0*.0??;*.1??;*.??0;*.BIN;*.CQ?;*.D??;*.FLP;*.HDM;*.IM?;*.XDF;*.*FD?\0Flux images (*.FDI)\0*.FDI\0Yüzey imajları (*.86F;*.MFM)\0*.86F;*.MFM\0All files (*.*)\0*.*\0" + IDS_2112 "SDL baÅŸlatılamadı, SDL2.dll gerekmektedir" + IDS_2113 "Emüle edilen makineyi yeniden baÅŸlatmak istediÄŸinizden emin misiniz?" + IDS_2114 "86Box'tan çıkmak istediÄŸinize emin misiniz?" + IDS_2115 "Ghostscript baÅŸlatılamadı" + IDS_2116 "MO %i (%ls): %ls" + IDS_2117 "MO imajları (*.IM?;*.MDI)\0*.IM?;*.MDI\0All files (*.*)\0*.*\0" + IDS_2118 "86Box'a hoÅŸgeldiniz!" + IDS_2119 "Dahili kontrolcü" + IDS_2120 "Çıkış" + IDS_2121 "Hiçbir ROM imajı bulunamadı" + IDS_2122 "Ayarları kaydetmek istediÄŸinizden emin misiniz?" + IDS_2123 "Bu makineyi yeniden baÅŸlatacak." + IDS_2124 "Kaydet" + IDS_2125 "86Box Hakkında" + IDS_2126 "86Box v" EMU_VERSION - IDS_2126 "Bir eski bilgisayar emülatörü\n\nYapanlar: Sarah Walker, Miran Grca, Fred N. van Kempen (waltje), SA1988, Tiseno100, reenigne, leilei, JohnElliott, greatpsycho, ve diÄŸerleri.\n\nGNU Genel Kamu Lisansı versiyon 2 veya sonrası altında yayınlanmıştır. Daha fazla bilgi için LICENSE'ı gözden geçirin." - IDS_2127 "Tamam" - IDS_2128 "Donanım mevcut deÄŸil" + IDS_2127 "Bir eski bilgisayar emülatörü\n\nYapanlar: Miran GrÄa (OBattler), RichardG867, Jasmine Iwanek, TC1995, coldbrewed, Teemu Korhonen (Manaatti), Joakim L. Gilje, Adrien Moulin (elyosh), Daniel Balsom (gloriouscow), Cacodemon345, Fred N. van Kempen (waltje), Tiseno100, reenigne, ve diÄŸerleri.\n\nWith previous core contributions from Sarah Walker, leilei, JohnElliott, greatpsycho, ve diÄŸerleri.\n\nGNU Genel Kamu Lisansı versiyon 2 veya sonrası altında yayınlanmıştır. Daha fazla bilgi için LICENSE'ı gözden geçirin." + IDS_2128 "Tamam" + IDS_2129 "Donanım mevcut deÄŸil" #ifdef _WIN32 #define LIB_NAME_PCAP "WinPcap" #else #define LIB_NAME_PCAP "libpcap" #endif - IDS_2129 "" LIB_NAME_PCAP " kurulu olduÄŸundan ve " LIB_NAME_PCAP "-uyumlu bir internet ağında bulunduÄŸunuzdan emin olun." - IDS_2130 "Geçersiz konfigürasyon" -#ifdef _WIN32 -#define LIB_NAME_FREETYPE "freetype.dll" -#else -#define LIB_NAME_FREETYPE "libfreetype" -#endif - IDS_2131 LIB_NAME_FREETYPE " ESC/P yazıcı emülasyonu için gereklidir." + IDS_2130 "" LIB_NAME_PCAP " kurulu olduÄŸundan ve " LIB_NAME_PCAP "-uyumlu bir internet ağında bulunduÄŸunuzdan emin olun." + IDS_2131 "Geçersiz konfigürasyon" #ifdef _WIN32 #define LIB_NAME_GS "gsdll32.dll" #else #define LIB_NAME_GS "libgs" #endif - IDS_2132 LIB_NAME_GS " PostScript dosyalarının otomatik olarak PDF dosyalarına çevirilmesi için gereklidir.\n\nGenel PostScript yazıcısına gönderilen tüm dökümanlar PostScript (.ps) dosyaları olarak kaydedilecektir." -#ifdef _WIN32 -#define LIB_NAME_FLUIDSYNTH "libfluidsynth.dll" -#else -#define LIB_NAME_FLUIDSYNTH "libfluidsynth" -#endif - IDS_2133 LIB_NAME_FLUIDSYNTH " FluidSynth MIDI çıkışı için gereklidir." - IDS_2134 "Tam ekran moduna geçiliyor" - IDS_2135 "Bu mesajı bir daha gösterme" - IDS_2136 "Çıkış yapma" - IDS_2137 "Yeniden baÅŸlat" - IDS_2138 "Yeniden baÅŸlatma" - IDS_2139 "MO imajları (*.IM?;*.MDI)\0*.IM?;*.MDI\0Tüm dosyalar (*.*)\0*.*\0" - IDS_2140 "CD-ROM imajları (*.ISO;*.CUE)\0*.ISO;*.CUE\0Tüm dosyalar (*.*)\0*.*\0" - IDS_2141 "%hs Cihaz Konfigürasyonu" - IDS_2142 "Monitör uyku modunda" - IDS_2143 "OpenGL Gölgelendiricileri (*.GLSL)\0*.GLSL\0Tüm dosyalar (*.*)\0*.*\0" - IDS_2144 "OpenGL ayarları" - IDS_2145 "Desteklenmeyen bir konfigürasyon yüklüyorsunuz" - IDS_2146 "SeçtiÄŸiniz makineye uygun CPU (iÅŸlemci) türü filtrelemesi bu emülasyon için devre dışı bırakıldı.\n\nBu, normalde seçilen makine ile uyumlu olmayan bir CPU seçmenizi mümkün kılmaktadır. Ancak, bundan dolayı seçilen makinenin BIOS'u veya diÄŸer yazılımlar ile uyumsuzluk sorunu yaÅŸayabilirsiniz.\n\nBu filtrelemeyi devre dışı bırakmak emülatör tarafından resmi olarak desteklenmemektedir ve açtığınız bug (hata) raporları geçersiz olarak kapatılabilir." - IDS_2147 "Devam et" - IDS_2148 "Kaset: %s" - IDS_2149 "Kaset imajları (*.PCM;*.RAW;*.WAV;*.CAS)\0*.PCM;*.RAW;*.WAV;*.CAS\0Tüm dosyalar (*.*)\0*.*\0" - IDS_2150 "KartuÅŸ %i: %ls" - IDS_2151 "KartuÅŸ imajları (*.A;*.B;*.JRC)\0*.A;*.B;*.JRC\0Tüm dosyalar (*.*)\0*.*\0" - IDS_2152 "Error initializing renderer" - IDS_2153 "OpenGL (3.0 Core) renderer could not be initialized. Use another renderer." - IDS_2154 "Resume execution" - IDS_2155 "Pause execution" - IDS_2156 "Press Ctrl+Alt+Del" - IDS_2157 "Press Ctrl+Alt+Esc" - IDS_2158 "Hard reset" - IDS_2159 "ACPI shutdown" - IDS_2160 "Settings" + IDS_2133 LIB_NAME_GS " PostScript dosyalarının otomatik olarak PDF dosyalarına çevirilmesi için gereklidir.\n\nGenel PostScript yazıcısına gönderilen tüm dökümanlar PostScript (.ps) dosyaları olarak kaydedilecektir." + IDS_2135 "Tam ekran moduna geçiliyor" + IDS_2136 "Bu mesajı bir daha gösterme" + IDS_2137 "Çıkış yapma" + IDS_2138 "Yeniden baÅŸlat" + IDS_2139 "Yeniden baÅŸlatma" + IDS_2140 "MO imajları (*.IM?;*.MDI)\0*.IM?;*.MDI\0Tüm dosyalar (*.*)\0*.*\0" + IDS_2141 "CD-ROM imajları (*.ISO;*.CUE)\0*.ISO;*.CUE\0Tüm dosyalar (*.*)\0*.*\0" + IDS_2142 "%hs Cihaz Konfigürasyonu" + IDS_2143 "Monitör uyku modunda" + IDS_2144 "OpenGL Gölgelendiricileri (*.GLSL)\0*.GLSL\0Tüm dosyalar (*.*)\0*.*\0" + IDS_2145 "OpenGL ayarları" + IDS_2146 "Desteklenmeyen bir konfigürasyon yüklüyorsunuz" + IDS_2147 "SeçtiÄŸiniz makineye uygun CPU (iÅŸlemci) türü filtrelemesi bu emülasyon için devre dışı bırakıldı.\n\nBu, normalde seçilen makine ile uyumlu olmayan bir CPU seçmenizi mümkün kılmaktadır. Ancak, bundan dolayı seçilen makinenin BIOS'u veya diÄŸer yazılımlar ile uyumsuzluk sorunu yaÅŸayabilirsiniz.\n\nBu filtrelemeyi devre dışı bırakmak emülatör tarafından resmi olarak desteklenmemektedir ve açtığınız bug (hata) raporları geçersiz olarak kapatılabilir." + IDS_2148 "Devam et" + IDS_2149 "Kaset: %s" + IDS_2150 "Kaset imajları (*.PCM;*.RAW;*.WAV;*.CAS)\0*.PCM;*.RAW;*.WAV;*.CAS\0Tüm dosyalar (*.*)\0*.*\0" + IDS_2151 "KartuÅŸ %i: %ls" + IDS_2152 "KartuÅŸ imajları (*.A;*.B;*.JRC)\0*.A;*.B;*.JRC\0Tüm dosyalar (*.*)\0*.*\0" + IDS_2153 "OluÅŸturucu baÅŸlatılırken hata oluÅŸtu" + IDS_2154 "OpenGL (3.0 Core) görüntüleyici baÅŸlatılamadı. BaÅŸka bir görüntüleyici kullanın." + IDS_2155 "Yürütmeye devam et" + IDS_2156 "Yürütmeyi duraklat" + IDS_2157 "Ctrl+Alt+Del" + IDS_2158 "Ctrl+Alt+Esc" + IDS_2159 "Makineyi yeniden baÅŸlat" + IDS_2160 "ACPI kapatma" + IDS_2161 "Ayarlar" + IDS_2162 "Type" + IDS_2163 "No Dynarec" + IDS_2164 "Old Dynarec" + IDS_2165 "New Dynarec" + IDS_2166 "Video card #2 ""%hs"" is not available due to missing ROMs in the roms/video directory. Disabling the second video card." + IDS_2167 "Failed to initialize network driver" + IDS_2168 "The network configuration will be switched to the null driver" END -STRINGTABLE DISCARDABLE +STRINGTABLE DISCARDABLE BEGIN IDS_4096 "Hard disk (%s)" - IDS_4097 "%01i:%01i" - IDS_4098 "%01i" - IDS_4099 "MFM/RLL veya ESDI CD-ROM sürücüleri hiçbir zaman var olmamıştır" - IDS_4100 "DiÄŸer..." - IDS_4101 "DiÄŸer (büyük)..." - IDS_4102 "Yeni Hard Disk Dosyası OluÅŸtur" - IDS_4103 "Var Olan Hard Disk Dosyası Ekle" - IDS_4104 "HDI disk imajları 4 GB'tan daha büyük olamaz." - IDS_4105 "Disk imajları 127 GB'tan daha büyük olamaz." - IDS_4106 "Hard disk imajları (*.HD?;*.IM?;*.VHD)\0*.HD?;*.IM?;*.VHD\0Tüm dosyalar (*.*)\0*.*\0" - IDS_4107 "Dosya okunamıyor" - IDS_4108 "Dosyanın üzerine yazılamıyor" - IDS_4109 "512 dışında sektör boyutu olan HDI veya HDX imajları desteklenmemektedir." - IDS_4110 "USB ÅŸu anda desteklenmemektedir" - IDS_4111 "Disk imaj dosyası zaten var olmakta" - IDS_4112 "Lütfen geçerli bir dosya ismi belirleyin." - IDS_4113 "Disk imajı oluÅŸturuldu" - IDS_4114 "Dosyanın var olduÄŸuna ve okunabildiÄŸine emin olun." - IDS_4115 "Dosyanın yazılabilir bir klasöre kaydedildiÄŸinden emin olun." - IDS_4116 "Disk imajı çok büyük" - IDS_4117 "Yeni oluÅŸturulan diski bölmeyi ve formatlamayı unutmayın." - IDS_4118 "Seçili dosyanın üzerine yazılacaktır. Bunu yapmak istediÄŸinizden emin misiniz?" - IDS_4119 "Desteklenmeyen disk imajı" - IDS_4120 "Üzerine yaz" - IDS_4121 "Üzerine yazma" - IDS_4122 "Ham imaj (.img)" - IDS_4123 "HDI imajı (.hdi)" - IDS_4124 "HDX imajı (.hdx)" - IDS_4125 "Sabit-boyutlu VHD (.vhd)" - IDS_4126 "Dinamik-boyutlu VHD (.vhd)" - IDS_4127 "Differencing VHD (.vhd)" - IDS_4128 "Büyük bloklar (2 MB)" - IDS_4129 "Küçük bloklar (512 KB)" - IDS_4130 "VHD dosyaları (*.VHD)\0*.VHD\0Tüm dosyalar (*.*)\0*.*\0" - IDS_4131 "Ana VHD dosyasını seçin" - IDS_4132 "Bu, farkı alınan imaj oluÅŸturulduktan sonra ana imaj dosyasının düzenlendiÄŸi anlamına geliyor olabilir.\n\nBu durum ayrıca imaj dosyaları kopyalandığında veya yerleri deÄŸiÅŸtirildiÄŸinde veya imaj dosyalarını oluÅŸturan programdaki bir hatadan dolayı olmuÅŸ olabilir.\n\nZaman damgalarını düzeltmek ister misiniz?" - IDS_4133 "Ana ve ek disk zaman damgaları uyuÅŸmuyor" - IDS_4134 "VHD zaman damgası düzeltilemedi." - IDS_4135 "%01i:%02i" + IDS_4097 "%01i:%01i" + IDS_4098 "%01i" + IDS_4099 "MFM/RLL veya ESDI CD-ROM sürücüleri hiçbir zaman var olmamıştır" + IDS_4100 "DiÄŸer..." + IDS_4101 "DiÄŸer (büyük)..." + IDS_4102 "Yeni Hard Disk Dosyası OluÅŸtur" + IDS_4103 "Var Olan Hard Disk Dosyası Ekle" + IDS_4104 "HDI disk imajları 4 GB'tan daha büyük olamaz." + IDS_4105 "Disk imajları 127 GB'tan daha büyük olamaz." + IDS_4106 "Hard disk imajları (*.HD?;*.IM?;*.VHD)\0*.HD?;*.IM?;*.VHD\0Tüm dosyalar (*.*)\0*.*\0" + IDS_4107 "Dosya okunamıyor" + IDS_4108 "Dosyanın üzerine yazılamıyor" + IDS_4109 "512 dışında sektör boyutu olan HDI veya HDX imajları desteklenmemektedir." + IDS_4110 "USB ÅŸu anda desteklenmemektedir" + IDS_4111 "Disk imaj dosyası zaten var olmakta" + IDS_4112 "Lütfen geçerli bir dosya ismi belirleyin." + IDS_4113 "Disk imajı oluÅŸturuldu" + IDS_4114 "Dosyanın var olduÄŸuna ve okunabildiÄŸine emin olun." + IDS_4115 "Dosyanın yazılabilir bir klasöre kaydedildiÄŸinden emin olun." + IDS_4116 "Disk imajı çok büyük" + IDS_4117 "Yeni oluÅŸturulan diski bölmeyi ve formatlamayı unutmayın." + IDS_4118 "Seçili dosyanın üzerine yazılacaktır. Bunu yapmak istediÄŸinizden emin misiniz?" + IDS_4119 "Desteklenmeyen disk imajı" + IDS_4120 "Üzerine yaz" + IDS_4121 "Üzerine yazma" + IDS_4122 "Ham imaj (.img)" + IDS_4123 "HDI imajı (.hdi)" + IDS_4124 "HDX imajı (.hdx)" + IDS_4125 "Sabit-boyutlu VHD (.vhd)" + IDS_4126 "Dinamik-boyutlu VHD (.vhd)" + IDS_4127 "Differencing VHD (.vhd)" + IDS_4128 "Büyük bloklar (2 MB)" + IDS_4129 "Küçük bloklar (512 KB)" + IDS_4130 "VHD dosyaları (*.VHD)\0*.VHD\0Tüm dosyalar (*.*)\0*.*\0" + IDS_4131 "Ana VHD dosyasını seçin" + IDS_4132 "Bu, farkı alınan imaj oluÅŸturulduktan sonra ana imaj dosyasının düzenlendiÄŸi anlamına geliyor olabilir.\n\nBu durum ayrıca imaj dosyaları kopyalandığında veya yerleri deÄŸiÅŸtirildiÄŸinde veya imaj dosyalarını oluÅŸturan programdaki bir hatadan dolayı olmuÅŸ olabilir.\n\nZaman damgalarını düzeltmek ister misiniz?" + IDS_4133 "Ana ve ek disk zaman damgaları uyuÅŸmuyor" + IDS_4134 "VHD zaman damgası düzeltilemedi." + IDS_4135 "%01i:%02i" IDS_4352 "MFM/RLL" IDS_4353 "XTA" @@ -562,56 +582,56 @@ BEGIN IDS_4356 "ATAPI" IDS_4357 "SCSI" - IDS_4608 "MFM/RLL (%01i:%01i)" - IDS_4609 "XTA (%01i:%01i)" - IDS_4610 "ESDI (%01i:%01i)" - IDS_4611 "IDE (%01i:%01i)" - IDS_4612 "ATAPI (%01i:%01i)" - IDS_4613 "SCSI (%01i:%02i)" + IDS_4608 "MFM/RLL (%01i:%01i)" + IDS_4609 "XTA (%01i:%01i)" + IDS_4610 "ESDI (%01i:%01i)" + IDS_4611 "IDE (%01i:%01i)" + IDS_4612 "ATAPI (%01i:%01i)" + IDS_4613 "SCSI (%01i:%02i)" - IDS_5120 "CD-ROM %i (%s): %s" + IDS_5120 "CD-ROM %i (%s): %s" - IDS_5376 "Devre dışı" - IDS_5381 "ATAPI" + IDS_5376 "Devre dışı" + IDS_5381 "ATAPI" IDS_5382 "SCSI" - IDS_5632 "Devre dışı" - IDS_5637 "ATAPI (%01i:%01i)" + IDS_5632 "Devre dışı" + IDS_5637 "ATAPI (%01i:%01i)" IDS_5638 "SCSI (%01i:%02i)" - IDS_5888 "160 kB" - IDS_5889 "180 kB" - IDS_5890 "320 kB" - IDS_5891 "360 kB" - IDS_5892 "640 kB" - IDS_5893 "720 kB" - IDS_5894 "1.2 MB" - IDS_5895 "1.25 MB" - IDS_5896 "1.44 MB" - IDS_5897 "DMF (cluster 1024)" - IDS_5898 "DMF (cluster 2048)" - IDS_5899 "2.88 MB" - IDS_5900 "ZIP 100" - IDS_5901 "ZIP 250" - IDS_5902 "3.5"" 128 MB (ISO 10090)" - IDS_5903 "3.5"" 230 MB (ISO 13963)" - IDS_5904 "3.5"" 540 MB (ISO 15498)" - IDS_5905 "3.5"" 640 MB (ISO 15498)" - IDS_5906 "3.5"" 1.3 GB (GigaMO)" - IDS_5907 "3.5"" 2.3 GB (GigaMO 2)" - IDS_5908 "5.25"" 600 MB" - IDS_5909 "5.25"" 650 MB" - IDS_5910 "5.25"" 1 GB" - IDS_5911 "5.25"" 1.3 GB" + IDS_5888 "160 kB" + IDS_5889 "180 kB" + IDS_5890 "320 kB" + IDS_5891 "360 kB" + IDS_5892 "640 kB" + IDS_5893 "720 kB" + IDS_5894 "1.2 MB" + IDS_5895 "1.25 MB" + IDS_5896 "1.44 MB" + IDS_5897 "DMF (cluster 1024)" + IDS_5898 "DMF (cluster 2048)" + IDS_5899 "2.88 MB" + IDS_5900 "ZIP 100" + IDS_5901 "ZIP 250" + IDS_5902 "3.5"" 128 MB (ISO 10090)" + IDS_5903 "3.5"" 230 MB (ISO 13963)" + IDS_5904 "3.5"" 540 MB (ISO 15498)" + IDS_5905 "3.5"" 640 MB (ISO 15498)" + IDS_5906 "3.5"" 1.3 GB (GigaMO)" + IDS_5907 "3.5"" 2.3 GB (GigaMO 2)" + IDS_5908 "5.25"" 600 MB" + IDS_5909 "5.25"" 650 MB" + IDS_5910 "5.25"" 1 GB" + IDS_5911 "5.25"" 1.3 GB" - IDS_6144 "Mükemmel RPM" - IDS_6145 "mükemmel RPM deÄŸerinin 1% altı" - IDS_6146 "mükemmel RPM deÄŸerinin 1.5% altı" - IDS_6147 "mükemmel RPM deÄŸerinin 2% altı" + IDS_6144 "Mükemmel RPM" + IDS_6145 "mükemmel RPM deÄŸerinin 1% altı" + IDS_6146 "mükemmel RPM deÄŸerinin 1.5% altı" + IDS_6147 "mükemmel RPM deÄŸerinin 2% altı" - IDS_7168 "(Sistem Varsayılanı)" + IDS_7168 "(Sistem Varsayılanı)" END -#define IDS_LANG_TRTR IDS_7168 +#define IDS_LANG_TRTR IDS_7168 // Turkish (TR) resources ///////////////////////////////////////////////////////////////////////////// diff --git a/src/win/languages/uk-UA.rc b/src/win/languages/uk-UA.rc index 3279e016d..41bf85f1a 100644 --- a/src/win/languages/uk-UA.rc +++ b/src/win/languages/uk-UA.rc @@ -13,113 +13,122 @@ LANGUAGE LANG_UKRAINIAN, SUBLANG_DEFAULT // Menu // -MainMenu MENU DISCARDABLE +MainMenu MENU DISCARDABLE BEGIN POPUP "&ДіÑ" BEGIN - MENUITEM "&Клавіатура потребує захвату", IDM_ACTION_KBD_REQ_CAPTURE - MENUITEM "&Правий CTRL - це лівий ALT", IDM_ACTION_RCTRL_IS_LALT + MENUITEM "&Клавіатура потребує захвату", IDM_ACTION_KBD_REQ_CAPTURE + MENUITEM "&Правий CTRL - це лівий ALT", IDM_ACTION_RCTRL_IS_LALT MENUITEM SEPARATOR - MENUITEM "&Холодне перезавантаженнÑ...", IDM_ACTION_HRESET - MENUITEM "&Ctrl+Alt+Del\tCtrl+F12", IDM_ACTION_RESET_CAD + MENUITEM "&Холодне перезавантаженнÑ...", IDM_ACTION_HRESET + MENUITEM "&Ctrl+Alt+Del\tCtrl+F12", IDM_ACTION_RESET_CAD MENUITEM SEPARATOR - MENUITEM "Ctrl+Alt+&Esc", IDM_ACTION_CTRL_ALT_ESC + MENUITEM "Ctrl+Alt+&Esc", IDM_ACTION_CTRL_ALT_ESC MENUITEM SEPARATOR - MENUITEM "&Пауза", IDM_ACTION_PAUSE + MENUITEM "&Пауза", IDM_ACTION_PAUSE MENUITEM SEPARATOR - MENUITEM "&Вихід...", IDM_ACTION_EXIT + MENUITEM "&Вихід...", IDM_ACTION_EXIT END POPUP "&ВиглÑд" BEGIN - MENUITEM "&Приховати Ñ€Ñдок Ñтану", IDM_VID_HIDE_STATUS_BAR - MENUITEM "&Приховати панель інÑтрументів", IDM_VID_HIDE_TOOLBAR + MENUITEM "&Приховати Ñ€Ñдок Ñтану", IDM_VID_HIDE_STATUS_BAR + MENUITEM "&Приховати панель інÑтрументів", IDM_VID_HIDE_TOOLBAR MENUITEM SEPARATOR - MENUITEM "&Змінний розмір вікна", IDM_VID_RESIZE - MENUITEM "&Запам'Ñтати розмір Ñ– Ñтановище", IDM_VID_REMEMBER + MENUITEM "&Show non-primary monitors", IDM_VID_MONITORS + MENUITEM "&Змінний розмір вікна", IDM_VID_RESIZE + MENUITEM "&Запам'Ñтати розмір Ñ– Ñтановище", IDM_VID_REMEMBER MENUITEM SEPARATOR POPUP "&Рендеринг" BEGIN - MENUITEM "&SDL (Software)", IDM_VID_SDL_SW - MENUITEM "SDL (&Hardware)", IDM_VID_SDL_HW - MENUITEM "SDL (&OpenGL)", IDM_VID_SDL_OPENGL - MENUITEM "Open&GL (3.0)", IDM_VID_OPENGL_CORE + MENUITEM "&SDL (Software)", IDM_VID_SDL_SW + MENUITEM "SDL (&Hardware)", IDM_VID_SDL_HW + MENUITEM "SDL (&OpenGL)", IDM_VID_SDL_OPENGL + MENUITEM "Open&GL (3.0)", IDM_VID_OPENGL_CORE #ifdef USE_VNC - MENUITEM "&VNC", IDM_VID_VNC + MENUITEM "&VNC", IDM_VID_VNC #endif END MENUITEM SEPARATOR - MENUITEM "&Вказати розміри...", IDM_VID_SPECIFY_DIM - MENUITEM "&Ð’Ñтановити Ð²Ñ–Ð´Ð½Ð¾ÑˆÐµÐ½Ð½Ñ Ñторін 4:3", IDM_VID_FORCE43 + MENUITEM "&Вказати розміри...", IDM_VID_SPECIFY_DIM + MENUITEM "&Ð’Ñтановити Ð²Ñ–Ð´Ð½Ð¾ÑˆÐµÐ½Ð½Ñ Ñторін 4:3", IDM_VID_FORCE43 POPUP "&МаÑштаб вікна" BEGIN - MENUITEM "&0.5x", IDM_VID_SCALE_1X - MENUITEM "&1x", IDM_VID_SCALE_2X - MENUITEM "1.&5x", IDM_VID_SCALE_3X - MENUITEM "&2x", IDM_VID_SCALE_4X + MENUITEM "&0.5x", IDM_VID_SCALE_1X + MENUITEM "&1x", IDM_VID_SCALE_2X + MENUITEM "1.&5x", IDM_VID_SCALE_3X + MENUITEM "&2x", IDM_VID_SCALE_4X + MENUITEM "&3x", IDM_VID_SCALE_5X + MENUITEM "&4x", IDM_VID_SCALE_6X + MENUITEM "&5x", IDM_VID_SCALE_7X + MENUITEM "&6x", IDM_VID_SCALE_8X + MENUITEM "&7x", IDM_VID_SCALE_9X + MENUITEM "&8x", IDM_VID_SCALE_10X END POPUP "Метод фільтрації" BEGIN - MENUITEM "&Ðайближчий", IDM_VID_FILTER_NEAREST - MENUITEM "&Лінійний", IDM_VID_FILTER_LINEAR + MENUITEM "&Ðайближчий", IDM_VID_FILTER_NEAREST + MENUITEM "&Лінійний", IDM_VID_FILTER_LINEAR END - MENUITEM "МаÑÑˆÑ‚Ð°Ð±ÑƒÐ²Ð°Ð½Ð½Ñ Hi&DPI", IDM_VID_HIDPI + MENUITEM "МаÑÑˆÑ‚Ð°Ð±ÑƒÐ²Ð°Ð½Ð½Ñ Hi&DPI", IDM_VID_HIDPI MENUITEM SEPARATOR - MENUITEM "&Повноекранний режим\tCtrl+Alt+PgUp", IDM_VID_FULLSCREEN + MENUITEM "&Повноекранний режим\tCtrl+Alt+PgUp", IDM_VID_FULLSCREEN POPUP "&РозÑÑ‚ÑÐ³ÑƒÐ²Ð°Ð½Ð½Ñ Ñƒ повноекранному режимі" BEGIN - MENUITEM "&Ðа веÑÑŒ екран", IDM_VID_FS_FULL - MENUITEM "&4:3", IDM_VID_FS_43 + MENUITEM "&Ðа веÑÑŒ екран", IDM_VID_FS_FULL + MENUITEM "&4:3", IDM_VID_FS_43 MENUITEM "&Квадратні пікÑелі (зберегти відношеннÑ)", IDM_VID_FS_KEEPRATIO - MENUITEM "&ЦіліÑночиÑленне маÑштабуваннÑ", IDM_VID_FS_INT + MENUITEM "&ЦіліÑночиÑленне маÑштабуваннÑ", IDM_VID_FS_INT END POPUP "ÐÐ°Ð»Ð°ÑˆÑ‚ÑƒÐ²Ð°Ð½Ð½Ñ E&GA/(S)VGA" BEGIN - MENUITEM "&Інвертувати кольори VGA", IDM_VID_INVERT + MENUITEM "&Інвертувати кольори VGA", IDM_VID_INVERT POPUP "&Тип екрана VGA" BEGIN - MENUITEM "RGB &кольоровий", IDM_VID_GRAY_RGB - MENUITEM "&RGB монохромний", IDM_VID_GRAY_MONO - MENUITEM "&Бурштиновий відтінок", IDM_VID_GRAY_AMBER - MENUITEM "&Зелений відтінок", IDM_VID_GRAY_GREEN - MENUITEM "&Білий відтінок", IDM_VID_GRAY_WHITE + MENUITEM "RGB &кольоровий", IDM_VID_GRAY_RGB + MENUITEM "&RGB монохромний", IDM_VID_GRAY_MONO + MENUITEM "&Бурштиновий відтінок", IDM_VID_GRAY_AMBER + MENUITEM "&Зелений відтінок", IDM_VID_GRAY_GREEN + MENUITEM "&Білий відтінок", IDM_VID_GRAY_WHITE END POPUP "Тип монохромного &конвертуваннÑ" BEGIN - MENUITEM "BT&601 (NTSC/PAL)", IDM_VID_GRAYCT_601 - MENUITEM "BT&709 (HDTV)", IDM_VID_GRAYCT_709 - MENUITEM "&УÑереднений", IDM_VID_GRAYCT_AVE + MENUITEM "BT&601 (NTSC/PAL)", IDM_VID_GRAYCT_601 + MENUITEM "BT&709 (HDTV)", IDM_VID_GRAYCT_709 + MENUITEM "&УÑереднений", IDM_VID_GRAYCT_AVE END END MENUITEM SEPARATOR - MENUITEM "Вильоти розгортки CGA/PCjr/Tandy/E&GA/(S)VGA", IDM_VID_OVERSCAN + MENUITEM "Вильоти розгортки CGA/PCjr/Tandy/E&GA/(S)VGA", IDM_VID_OVERSCAN MENUITEM "Змінити контраÑтніÑть &монохромного диÑплеÑ", IDM_VID_CGACON END - MENUITEM "&ÐоÑÑ–Ñ—", IDM_MEDIA + MENUITEM "&ÐоÑÑ–Ñ—", IDM_MEDIA POPUP "&ІнÑтрументи" BEGIN - MENUITEM "&ÐÐ°Ð»Ð°ÑˆÑ‚ÑƒÐ²Ð°Ð½Ð½Ñ Ð¼Ð°ÑˆÐ¸Ð½Ð¸...", IDM_CONFIG - MENUITEM "&ÐžÐ±Ð½Ð¾Ð²Ð»ÐµÐ½Ð½Ñ Ð·Ð½Ð°Ñ‡ÐºÑ–Ð² Ñ€Ñдка Ñтану", IDM_UPDATE_ICONS + MENUITEM "&ÐÐ°Ð»Ð°ÑˆÑ‚ÑƒÐ²Ð°Ð½Ð½Ñ Ð¼Ð°ÑˆÐ¸Ð½Ð¸...", IDM_CONFIG + MENUITEM "&ÐžÐ±Ð½Ð¾Ð²Ð»ÐµÐ½Ð½Ñ Ð·Ð½Ð°Ñ‡ÐºÑ–Ð² Ñ€Ñдка Ñтану", IDM_UPDATE_ICONS MENUITEM SEPARATOR - MENUITEM "Зробити &знімок\tCtrl+F11", IDM_ACTION_SCREENSHOT + MENUITEM "Зробити &знімок\tCtrl+F11", IDM_ACTION_SCREENSHOT MENUITEM SEPARATOR - MENUITEM "&Параметри...", IDM_PREFERENCES + MENUITEM "&Параметри...", IDM_PREFERENCES +#ifdef DISCORD MENUITEM "Увімкнути інтеграцію &Discord", IDM_DISCORD +#endif MENUITEM SEPARATOR - MENUITEM "&ПоÑÐ¸Ð»ÐµÐ½Ð½Ñ Ð·Ð²ÑƒÐºÑƒ...", IDM_SND_GAIN + MENUITEM "&ПоÑÐ¸Ð»ÐµÐ½Ð½Ñ Ð·Ð²ÑƒÐºÑƒ...", IDM_SND_GAIN #ifdef MTR_ENABLED MENUITEM SEPARATOR - MENUITEM "Почати траÑуваннÑ\tCtrl+T", IDM_ACTION_BEGIN_TRACE - MENUITEM "Завершити траÑуваннÑ\tCtrl+T", IDM_ACTION_END_TRACE + MENUITEM "Почати траÑуваннÑ\tCtrl+T", IDM_ACTION_BEGIN_TRACE + MENUITEM "Завершити траÑуваннÑ\tCtrl+T", IDM_ACTION_END_TRACE #endif END POPUP "&Допомога" BEGIN - MENUITEM "&ДокументаціÑ...", IDM_DOCS - MENUITEM "&Про програму 86Box...", IDM_ABOUT + MENUITEM "&ДокументаціÑ...", IDM_DOCS + MENUITEM "&Про програму 86Box...", IDM_ABOUT END END -StatusBarMenu MENU DISCARDABLE +StatusBarMenu MENU DISCARDABLE BEGIN MENUITEM SEPARATOR END @@ -128,17 +137,17 @@ CassetteSubmenu MENU DISCARDABLE BEGIN POPUP "" BEGIN - MENUITEM "&Ðовий образ...", IDM_CASSETTE_IMAGE_NEW + MENUITEM "&Ðовий образ...", IDM_CASSETTE_IMAGE_NEW MENUITEM SEPARATOR - MENUITEM "&Вибрати образ...", IDM_CASSETTE_IMAGE_EXISTING - MENUITEM "Вибрати образ (&ЗахиÑÑ‚ від запиÑу)...", IDM_CASSETTE_IMAGE_EXISTING_WP + MENUITEM "&Вибрати образ...", IDM_CASSETTE_IMAGE_EXISTING + MENUITEM "Вибрати образ (&ЗахиÑÑ‚ від запиÑу)...", IDM_CASSETTE_IMAGE_EXISTING_WP MENUITEM SEPARATOR - MENUITEM "&ЗапиÑ", IDM_CASSETTE_RECORD - MENUITEM "&ВідтвореннÑ", IDM_CASSETTE_PLAY - MENUITEM "&ÐŸÐµÑ€ÐµÐ¼Ð¾Ñ‚ÑƒÐ²Ð°Ð½Ð½Ñ Ð½Ð° початок", IDM_CASSETTE_REWIND - MENUITEM "&ÐŸÐµÑ€ÐµÐ¼Ð¾Ñ‚ÑƒÐ²Ð°Ð½Ð½Ñ Ñƒ кінець", IDM_CASSETTE_FAST_FORWARD + MENUITEM "&ЗапиÑ", IDM_CASSETTE_RECORD + MENUITEM "&ВідтвореннÑ", IDM_CASSETTE_PLAY + MENUITEM "&ÐŸÐµÑ€ÐµÐ¼Ð¾Ñ‚ÑƒÐ²Ð°Ð½Ð½Ñ Ð½Ð° початок", IDM_CASSETTE_REWIND + MENUITEM "&ÐŸÐµÑ€ÐµÐ¼Ð¾Ñ‚ÑƒÐ²Ð°Ð½Ð½Ñ Ñƒ кінець", IDM_CASSETTE_FAST_FORWARD MENUITEM SEPARATOR - MENUITEM "&Вилучити", IDM_CASSETTE_EJECT + MENUITEM "&Вилучити", IDM_CASSETTE_EJECT END END @@ -146,9 +155,9 @@ CartridgeSubmenu MENU DISCARDABLE BEGIN POPUP "" BEGIN - MENUITEM "&Образ...", IDM_CARTRIDGE_IMAGE + MENUITEM "&Образ...", IDM_CARTRIDGE_IMAGE MENUITEM SEPARATOR - MENUITEM "&Вилучити", IDM_CARTRIDGE_EJECT + MENUITEM "&Вилучити", IDM_CARTRIDGE_EJECT END END @@ -156,14 +165,14 @@ FloppySubmenu MENU DISCARDABLE BEGIN POPUP "" BEGIN - MENUITEM "&Ðовий образ...", IDM_FLOPPY_IMAGE_NEW + MENUITEM "&Ðовий образ...", IDM_FLOPPY_IMAGE_NEW MENUITEM SEPARATOR - MENUITEM "&Вибрати образ...", IDM_FLOPPY_IMAGE_EXISTING - MENUITEM "Вибрати образ (&ЗахиÑÑ‚ від запиÑу)...", IDM_FLOPPY_IMAGE_EXISTING_WP + MENUITEM "&Вибрати образ...", IDM_FLOPPY_IMAGE_EXISTING + MENUITEM "Вибрати образ (&ЗахиÑÑ‚ від запиÑу)...", IDM_FLOPPY_IMAGE_EXISTING_WP MENUITEM SEPARATOR - MENUITEM "&ЕкÑпорт в 86F...", IDM_FLOPPY_EXPORT_TO_86F + MENUITEM "&ЕкÑпорт в 86F...", IDM_FLOPPY_EXPORT_TO_86F MENUITEM SEPARATOR - MENUITEM "&Вилучити", IDM_FLOPPY_EJECT + MENUITEM "&Вилучити", IDM_FLOPPY_EJECT END END @@ -171,12 +180,13 @@ CdromSubmenu MENU DISCARDABLE BEGIN POPUP "" BEGIN - MENUITEM "&Відключити звук", IDM_CDROM_MUTE + MENUITEM "&Відключити звук", IDM_CDROM_MUTE MENUITEM SEPARATOR - MENUITEM "&ПуÑтий", IDM_CDROM_EMPTY - MENUITEM "&Знову завантажити попередній образ", IDM_CDROM_RELOAD + MENUITEM "&ПуÑтий", IDM_CDROM_EMPTY + MENUITEM "&Знову завантажити попередній образ", IDM_CDROM_RELOAD MENUITEM SEPARATOR - MENUITEM "&Образ...", IDM_CDROM_IMAGE + MENUITEM "&Образ...", IDM_CDROM_IMAGE + MENUITEM "&Тека...", IDM_CDROM_DIR END END @@ -184,13 +194,13 @@ ZIPSubmenu MENU DISCARDABLE BEGIN POPUP "" BEGIN - MENUITEM "&Ðовий образ...", IDM_ZIP_IMAGE_NEW + MENUITEM "&Ðовий образ...", IDM_ZIP_IMAGE_NEW MENUITEM SEPARATOR - MENUITEM "&Вибрати образ...", IDM_ZIP_IMAGE_EXISTING - MENUITEM "Вибрати образ (&ЗахиÑÑ‚ від запиÑу)...", IDM_ZIP_IMAGE_EXISTING_WP + MENUITEM "&Вибрати образ...", IDM_ZIP_IMAGE_EXISTING + MENUITEM "Вибрати образ (&ЗахиÑÑ‚ від запиÑу)...", IDM_ZIP_IMAGE_EXISTING_WP MENUITEM SEPARATOR - MENUITEM "&Вилучити", IDM_ZIP_EJECT - MENUITEM "&Знову завантажити попередній образ", IDM_ZIP_RELOAD + MENUITEM "&Вилучити", IDM_ZIP_EJECT + MENUITEM "&Знову завантажити попередній образ", IDM_ZIP_RELOAD END END @@ -198,13 +208,13 @@ MOSubmenu MENU DISCARDABLE BEGIN POPUP "" BEGIN - MENUITEM "&Ðовий образ...", IDM_MO_IMAGE_NEW + MENUITEM "&Ðовий образ...", IDM_MO_IMAGE_NEW MENUITEM SEPARATOR - MENUITEM "&Вибрати образ...", IDM_MO_IMAGE_EXISTING - MENUITEM "Вибрати образ (&ЗахиÑÑ‚ від запиÑу)...", IDM_MO_IMAGE_EXISTING_WP + MENUITEM "&Вибрати образ...", IDM_MO_IMAGE_EXISTING + MENUITEM "Вибрати образ (&ЗахиÑÑ‚ від запиÑу)...", IDM_MO_IMAGE_EXISTING_WP MENUITEM SEPARATOR - MENUITEM "&Вилучити", IDM_MO_EJECT - MENUITEM "&Знову завантажити попередній образ", IDM_MO_RELOAD + MENUITEM "&Вилучити", IDM_MO_EJECT + MENUITEM "&Знову завантажити попередній образ", IDM_MO_RELOAD END END @@ -230,134 +240,150 @@ END // Dialog // -#define STR_PREFERENCES "Параметри" -#define STR_SND_GAIN "ПоÑÐ¸Ð»ÐµÐ½Ð½Ñ Ð·Ð²ÑƒÐºÑƒ" -#define STR_NEW_FLOPPY "Ðовий образ" -#define STR_CONFIG "ÐалаштуваннÑ" -#define STR_SPECIFY_DIM "Вказати розміри головного вікна" +#define STR_PREFERENCES "Параметри" +#define STR_SND_GAIN "ПоÑÐ¸Ð»ÐµÐ½Ð½Ñ Ð·Ð²ÑƒÐºÑƒ" +#define STR_NEW_FLOPPY "Ðовий образ" +#define STR_CONFIG "ÐалаштуваннÑ" +#define STR_SPECIFY_DIM "Вказати розміри головного вікна" -#define STR_OK "OK" -#define STR_CANCEL "Відміна" -#define STR_GLOBAL "Зберегти ці параметри Ñк &глобальні за замовчуваннÑм" -#define STR_DEFAULT "&За замовчуваннÑм" -#define STR_LANGUAGE "Язык:" -#define STR_ICONSET "Ðабір іконок:" +#define STR_OK "OK" +#define STR_CANCEL "Відміна" +#define STR_GLOBAL "Зберегти ці параметри Ñк &глобальні за замовчуваннÑм" +#define STR_DEFAULT "&За замовчуваннÑм" +#define STR_LANGUAGE "Мова:" +#define STR_ICONSET "Ðабір іконок:" -#define STR_GAIN "ПоÑиленнÑ" +#define STR_GAIN "ПоÑиленнÑ" -#define STR_FILE_NAME "Ім'Ñ Ñ„Ð°Ð¹Ð»Ñƒ:" -#define STR_DISK_SIZE "Розмір диÑка:" -#define STR_RPM_MODE "RPM режим:" -#define STR_PROGRESS "ПрогреÑ:" +#define STR_FILE_NAME "Ім'Ñ Ñ„Ð°Ð¹Ð»Ñƒ:" +#define STR_DISK_SIZE "Розмір диÑка:" +#define STR_RPM_MODE "RPM режим:" +#define STR_PROGRESS "ПрогреÑ:" -#define STR_WIDTH "Ширина:" -#define STR_HEIGHT "ВиÑота:" -#define STR_LOCK_TO_SIZE "ЗафікÑувати розмір" +#define STR_WIDTH "Ширина:" +#define STR_HEIGHT "ВиÑота:" +#define STR_LOCK_TO_SIZE "ЗафікÑувати розмір" -#define STR_MACHINE_TYPE "Тип машини:" -#define STR_MACHINE "СиÑтемна плата:" -#define STR_CONFIGURE "ÐалаштуваннÑ" -#define STR_CPU_TYPE "Тип ЦП:" -#define STR_CPU_SPEED "ШвидкіÑть:" -#define STR_FPU "FPU:" -#define STR_WAIT_STATES "Цикли очікуваннÑ:" -#define STR_MB "МБ" -#define STR_MEMORY "Пам'Ñть:" -#define STR_TIME_SYNC "Ð¡Ð¸Ð½Ñ…Ñ€Ð¾Ð½Ñ–Ð·Ð°Ñ†Ñ–Ñ Ñ‡Ð°Ñу" -#define STR_DISABLED "Відключити" -#define STR_ENABLED_LOCAL "Увімкнути (міÑцеве)" -#define STR_ENABLED_UTC "Увімкнути (UTC)" -#define STR_DYNAREC "Динамічний рекомпілÑтор" +#define STR_MACHINE_TYPE "Тип машини:" +#define STR_MACHINE "СиÑтемна плата:" +#define STR_CONFIGURE "ÐалаштуваннÑ" +#define STR_CPU_TYPE "Тип ЦП:" +#define STR_CPU_SPEED "ШвидкіÑть:" +#define STR_FPU "FPU:" +#define STR_WAIT_STATES "Цикли очікуваннÑ:" +#define STR_MB "МБ" +#define STR_MEMORY "Пам'Ñть:" +#define STR_TIME_SYNC "Ð¡Ð¸Ð½Ñ…Ñ€Ð¾Ð½Ñ–Ð·Ð°Ñ†Ñ–Ñ Ñ‡Ð°Ñу" +#define STR_DISABLED "Відключити" +#define STR_ENABLED_LOCAL "Увімкнути (міÑцеве)" +#define STR_ENABLED_UTC "Увімкнути (UTC)" +#define STR_DYNAREC "Динамічний рекомпілÑтор" +#define STR_SOFTFLOAT "Softfloat FPU" -#define STR_VIDEO "Відеокарта:" -#define STR_VOODOO "ПриÑкорювач Voodoo" +#define STR_VIDEO "Відеокарта:" +#define STR_VIDEO_2 "Відеокарта 2:" +#define STR_VOODOO "ПриÑкорювач Voodoo" +#define STR_IBM8514 "ПриÑкорювач IBM 8514/a" +#define STR_XGA "ПриÑкорювач XGA" -#define STR_MOUSE "Миша:" -#define STR_JOYSTICK "ДжойÑтик:" -#define STR_JOY1 "ДжойÑтик 1..." -#define STR_JOY2 "ДжойÑтик 2..." -#define STR_JOY3 "ДжойÑтик 3..." -#define STR_JOY4 "ДжойÑтик 4..." +#define STR_MOUSE "Миша:" +#define STR_JOYSTICK "ДжойÑтик:" +#define STR_JOY1 "ДжойÑтик 1..." +#define STR_JOY2 "ДжойÑтик 2..." +#define STR_JOY3 "ДжойÑтик 3..." +#define STR_JOY4 "ДжойÑтик 4..." -#define STR_SOUND "Звукова карта:" -#define STR_MIDI_OUT "MIDI Out при-ій:" -#define STR_MIDI_IN "MIDI In при-ій:" -#define STR_MPU401 "Окремий MPU-401" -#define STR_SSI "Innovation SSI-2001" -#define STR_CMS "CMS / Game Blaster" -#define STR_GUS "Gravis Ultrasound" -#define STR_FLOAT "FLOAT32 звук" +#define STR_SOUND1 "Звукова карта 1:" +#define STR_SOUND2 "Звукова карта 2:" +#define STR_SOUND3 "Звукова карта 3:" +#define STR_SOUND4 "Звукова карта 4:" +#define STR_MIDI_OUT "MIDI Out при-ій:" +#define STR_MIDI_IN "MIDI In при-ій:" +#define STR_MPU401 "Окремий MPU-401" +#define STR_FLOAT "FLOAT32 звук" +#define STR_FM_DRIVER "Драйвер FM-Ñинтезатора" +#define STR_FM_DRV_NUKED "Nuked (більш точний)" +#define STR_FM_DRV_YMFM "YMFM (швидший)" -#define STR_NET_TYPE "Тип мережі:" -#define STR_PCAP "ПриÑтрій PCap:" -#define STR_NET "Мережева карта:" +#define STR_NET_TYPE "Тип мережі:" +#define STR_PCAP "ПриÑтрій PCap:" +#define STR_NET "Мережевий адаптер:" +#define STR_NET1 "Мережева карта 1:" +#define STR_NET2 "Мережева карта 2:" +#define STR_NET3 "Мережева карта 3:" +#define STR_NET4 "Мережева карта 4:" -#define STR_COM1 "ПриÑтрій COM1:" -#define STR_COM2 "ПриÑтрій COM2:" -#define STR_COM3 "ПриÑтрій COM3:" -#define STR_COM4 "ПриÑтрій COM4:" -#define STR_LPT1 "ПриÑтрій LPT1:" -#define STR_LPT2 "ПриÑтрій LPT2:" -#define STR_LPT3 "ПриÑтрій LPT3:" -#define STR_LPT4 "ПриÑтрій LPT4:" -#define STR_SERIAL1 "ПоÑлідов. порт COM1" -#define STR_SERIAL2 "ПоÑлідов. порт COM2" -#define STR_SERIAL3 "ПоÑлідов. порт COM3" -#define STR_SERIAL4 "ПоÑлідов. порт COM4" -#define STR_PARALLEL1 "Паралельний порт LPT1" -#define STR_PARALLEL2 "Паралельний порт LPT2" -#define STR_PARALLEL3 "Паралельний порт LPT3" -#define STR_PARALLEL4 "Паралельний порт LPT4" +#define STR_COM1 "ПриÑтрій COM1:" +#define STR_COM2 "ПриÑтрій COM2:" +#define STR_COM3 "ПриÑтрій COM3:" +#define STR_COM4 "ПриÑтрій COM4:" +#define STR_LPT1 "ПриÑтрій LPT1:" +#define STR_LPT2 "ПриÑтрій LPT2:" +#define STR_LPT3 "ПриÑтрій LPT3:" +#define STR_LPT4 "ПриÑтрій LPT4:" +#define STR_SERIAL1 "ПоÑлідов. порт COM1" +#define STR_SERIAL2 "ПоÑлідов. порт COM2" +#define STR_SERIAL3 "ПоÑлідов. порт COM3" +#define STR_SERIAL4 "ПоÑлідов. порт COM4" +#define STR_PARALLEL1 "Паралельний порт LPT1" +#define STR_PARALLEL2 "Паралельний порт LPT2" +#define STR_PARALLEL3 "Паралельний порт LPT3" +#define STR_PARALLEL4 "Паралельний порт LPT4" +#define STR_SERIAL_PASS1 "Serial port passthrough 1" +#define STR_SERIAL_PASS2 "Serial port passthrough 2" +#define STR_SERIAL_PASS3 "Serial port passthrough 3" +#define STR_SERIAL_PASS4 "Serial port passthrough 4" -#define STR_HDC "Контролер HD:" -#define STR_FDC "Контролер FD:" -#define STR_IDE_TER "Третинний IDE контролер" -#define STR_IDE_QUA "Четвертинний IDE контролер" -#define STR_SCSI "SCSI" -#define STR_SCSI_1 "Контролер 1:" -#define STR_SCSI_2 "Контролер 2:" -#define STR_SCSI_3 "Контролер 3:" -#define STR_SCSI_4 "Контролер 4:" -#define STR_CASSETTE "КаÑета" +#define STR_HDC "Контролер HD:" +#define STR_FDC "Контролер FD:" +#define STR_IDE_TER "Третинний IDE контролер" +#define STR_IDE_QUA "Четвертинний IDE контролер" +#define STR_SCSI "SCSI" +#define STR_SCSI_1 "Контролер 1:" +#define STR_SCSI_2 "Контролер 2:" +#define STR_SCSI_3 "Контролер 3:" +#define STR_SCSI_4 "Контролер 4:" +#define STR_CASSETTE "КаÑета" -#define STR_HDD "ЖорÑткі диÑки:" -#define STR_NEW "&Створити..." -#define STR_EXISTING "&Вибрати..." -#define STR_REMOVE "&Прибрати" -#define STR_BUS "Шина:" -#define STR_CHANNEL "Канал:" -#define STR_ID "ID:" +#define STR_HDD "ЖорÑткі диÑки:" +#define STR_NEW "&Створити..." +#define STR_EXISTING "&Вибрати..." +#define STR_REMOVE "&Прибрати" +#define STR_BUS "Шина:" +#define STR_CHANNEL "Канал:" +#define STR_ID "ID:" +#define STR_SPEED "Speed:" -#define STR_SPECIFY "&Вказати..." -#define STR_SECTORS "Сектора:" -#define STR_HEADS "Головки:" -#define STR_CYLS "Циліндри:" -#define STR_SIZE_MB "Розмір (МБ):" -#define STR_TYPE "Тип:" -#define STR_IMG_FORMAT "Тип образу:" -#define STR_BLOCK_SIZE "Розмір блоку:" +#define STR_SPECIFY "&Вказати..." +#define STR_SECTORS "Сектора:" +#define STR_HEADS "Головки:" +#define STR_CYLS "Циліндри:" +#define STR_SIZE_MB "Розмір (МБ):" +#define STR_TYPE "Тип:" +#define STR_IMG_FORMAT "Тип образу:" +#define STR_BLOCK_SIZE "Розмір блоку:" -#define STR_FLOPPY_DRIVES "Гнучкі диÑки:" -#define STR_TURBO "Турбо таймінги" -#define STR_CHECKBPB "ПеревірÑти BPB" -#define STR_CDROM_DRIVES "ДиÑководи CD-ROM:" -#define STR_CD_SPEED "ШвидкіÑть:" +#define STR_FLOPPY_DRIVES "Гнучкі диÑки:" +#define STR_TURBO "Турбо таймінги" +#define STR_CHECKBPB "ПеревірÑти BPB" +#define STR_CDROM_DRIVES "ДиÑководи CD-ROM:" +#define STR_CD_SPEED "ШвидкіÑть:" -#define STR_MO_DRIVES "Магнітооптичні диÑководи:" -#define STR_ZIP_DRIVES "ZIP диÑководи:" -#define STR_250 "ZIP 250" +#define STR_MO_DRIVES "Магнітооптичні диÑководи:" +#define STR_ZIP_DRIVES "ZIP диÑководи:" +#define STR_250 "ZIP 250" -#define STR_ISARTC "ISA RTC:" -#define STR_ISAMEM "Карта Ñ€Ð¾Ð·ÑˆÐ¸Ñ€ÐµÐ½Ð½Ñ Ð¿Ð°Ð¼'Ñті (ISA)" -#define STR_ISAMEM_1 "Карта 1:" -#define STR_ISAMEM_2 "Карта 2:" -#define STR_ISAMEM_3 "Карта 3:" -#define STR_ISAMEM_4 "Карта 4:" -#define STR_BUGGER "ПриÑтрій ISABugger" -#define STR_POSTCARD "Карта POST" +#define STR_ISARTC "ISA RTC:" +#define STR_ISAMEM "Карта Ñ€Ð¾Ð·ÑˆÐ¸Ñ€ÐµÐ½Ð½Ñ Ð¿Ð°Ð¼'Ñті (ISA)" +#define STR_ISAMEM_1 "Карта 1:" +#define STR_ISAMEM_2 "Карта 2:" +#define STR_ISAMEM_3 "Карта 3:" +#define STR_ISAMEM_4 "Карта 4:" +#define STR_BUGGER "ПриÑтрій ISABugger" +#define STR_POSTCARD "Карта POST" -#define FONT_SIZE 9 -#define FONT_NAME "Segoe UI" +#define FONT_SIZE 9 +#define FONT_NAME "Segoe UI" #include "dialogs.rc" @@ -366,250 +392,244 @@ END // String Table // -STRINGTABLE DISCARDABLE +STRINGTABLE DISCARDABLE BEGIN - 2048 "86Box" - IDS_2049 "Помилка" - IDS_2050 "Ðепереробна помилка" - IDS_2051 " - PAUSED" - IDS_2052 "ÐатиÑніть Ctrl+Alt+PgDn Ð´Ð»Ñ Ð¿Ð¾Ð²ÐµÑ€Ð½ÐµÐ½Ð½Ñ Ñƒ віконний режим." - IDS_2053 "ШвидкіÑть" - IDS_2054 "ZIP %03i %i (%s): %ls" - IDS_2055 "Образи ZIP (*.IM?;*.ZDI)\0*.IM?;*.ZDI\0" - IDS_2056 "86Box не зміг знайти жодного відповідного Ð´Ð»Ñ Ð²Ð¸ÐºÐ¾Ñ€Ð¸ÑÑ‚Ð°Ð½Ð½Ñ Ñ„Ð°Ð¹Ð»Ñƒ з ПЗУ.\n\nБудь лаÑка завантажте набір ПЗУ Ñ– витÑгніть його в каталог ""roms""." - IDS_2057 "(порожньо)" - IDS_2058 "Образи ZIP (*.IM?;*.ZDI)\0*.IM?;*.ZDI\0Ð’ÑÑ– файли (*.*)\0*.*\0" - IDS_2059 "Турбо" - IDS_2060 "Увімк" - IDS_2061 "Вимк" - IDS_2062 "Ð’ÑÑ– образи (*.86F;*.DSK;*.FLP;*.IM?;*.*FD?)\0*.86F;*.DSK;*.FLP;*.IM?;*.*FD?\0ПроÑті поÑекторні образи (*.DSK;*.FLP;*.IM?;*.*FD?)\0*.DSK;*.FLP;*.IM?;*.IMG;*.*FD?\0Образ поверхні (*.86F)\0*.86F\0" - IDS_2063 "СиÑтемна плата ""%hs"" недоÑтупна через відÑутніÑть файлу Ñ—Ñ— ПЗУ в каталозі roms/machines. ÐŸÐµÑ€ÐµÐºÐ»ÑŽÑ‡ÐµÐ½Ð½Ñ Ð½Ð° доÑтупну ÑиÑтемну плату." + 2048 "86Box" + IDS_2049 "Помилка" + IDS_2050 "Ðепереробна помилка" + IDS_2051 " - PAUSED" + IDS_2052 "ÐатиÑніть Ctrl+Alt+PgDn Ð´Ð»Ñ Ð¿Ð¾Ð²ÐµÑ€Ð½ÐµÐ½Ð½Ñ Ñƒ віконний режим." + IDS_2053 "ШвидкіÑть" + IDS_2054 "ZIP %03i %i (%s): %ls" + IDS_2055 "Образи ZIP (*.IM?;*.ZDI)\0*.IM?;*.ZDI\0" + IDS_2056 "86Box не зміг знайти жодного відповідного Ð´Ð»Ñ Ð²Ð¸ÐºÐ¾Ñ€Ð¸ÑÑ‚Ð°Ð½Ð½Ñ Ñ„Ð°Ð¹Ð»Ñƒ з ПЗУ.\n\nБудь лаÑка завантажте набір ПЗУ Ñ– витÑгніть його в каталог ""roms""." + IDS_2057 "(порожньо)" + IDS_2058 "Образи ZIP (*.IM?;*.ZDI)\0*.IM?;*.ZDI\0УÑÑ– файли (*.*)\0*.*\0" + IDS_2059 "Турбо" + IDS_2060 "Увімк" + IDS_2061 "Вимк" + IDS_2062 "УÑÑ– образи (*.86F;*.DSK;*.FLP;*.IM?;*.*FD?)\0*.86F;*.DSK;*.FLP;*.IM?;*.*FD?\0ПроÑті поÑекторні образи (*.DSK;*.FLP;*.IM?;*.*FD?)\0*.DSK;*.FLP;*.IM?;*.IMG;*.*FD?\0Образ поверхні (*.86F)\0*.86F\0" + IDS_2063 "СиÑтемна плата ""%hs"" недоÑтупна через відÑутніÑть файлу Ñ—Ñ— ПЗУ в каталозі roms/machines. ÐŸÐµÑ€ÐµÐºÐ»ÑŽÑ‡ÐµÐ½Ð½Ñ Ð½Ð° доÑтупну ÑиÑтемну плату." END -STRINGTABLE DISCARDABLE +STRINGTABLE DISCARDABLE BEGIN - IDS_2064 "Відеокарта ""%hs"" недоÑтупна через відÑутніÑть файлу Ñ—Ñ— ПЗУ в каталозі roms/video. ÐŸÐµÑ€ÐµÐºÐ»ÑŽÑ‡ÐµÐ½Ð½Ñ Ð½Ð° доÑтупну відеокарту." - IDS_2065 "Комп'ютер" - IDS_2066 "ДиÑплей" - IDS_2067 "ПриÑтрій введеннÑ" - IDS_2068 "Звук" - IDS_2069 "Мережа" - IDS_2070 "Порти (COM и LPT)" - IDS_2071 "Контролери диÑків" - IDS_2072 "ЖорÑткі диÑки" - IDS_2073 "Гнучкі диÑки Ñ– CD-ROM" - IDS_2074 "Інші знімні при-ої" - IDS_2075 "Інша периферіÑ" - IDS_2076 "Образи Surface (*.86F)\0*.86F\0" - IDS_2077 "Клацніть мишею Ð´Ð»Ñ Ð·Ð°Ñ…Ð²Ð°Ñ‚Ñƒ курÑора" - IDS_2078 "ÐатиÑніть F8+F12, щоб звільнити курÑор" - IDS_2079 "ÐатиÑніть F8+F12 або Ñередню кнопку миші, щоб звільнити курÑор" + IDS_2064 "Відеокарта ""%hs"" недоÑтупна через відÑутніÑть файлу Ñ—Ñ— ПЗУ в каталозі roms/video. ÐŸÐµÑ€ÐµÐºÐ»ÑŽÑ‡ÐµÐ½Ð½Ñ Ð½Ð° доÑтупну відеокарту." + IDS_2065 "Комп'ютер" + IDS_2066 "ДиÑплей" + IDS_2067 "ПриÑтрій введеннÑ" + IDS_2068 "Звук" + IDS_2069 "Мережа" + IDS_2070 "Порти (COM и LPT)" + IDS_2071 "Контролери диÑків" + IDS_2072 "ЖорÑткі диÑки" + IDS_2073 "Гнучкі диÑки Ñ– CD-ROM" + IDS_2074 "Інші знімні при-ої" + IDS_2075 "Інша периферіÑ" + IDS_2076 "Образи Surface (*.86F)\0*.86F\0" + IDS_2077 "Клацніть мишею Ð´Ð»Ñ Ð·Ð°Ñ…Ð²Ð°Ñ‚Ñƒ курÑора" + IDS_2078 "ÐатиÑніть F8+F12, щоб звільнити курÑор" + IDS_2079 "ÐатиÑніть F8+F12 або Ñередню кнопку миші, щоб звільнити курÑор" END -STRINGTABLE DISCARDABLE +STRINGTABLE DISCARDABLE BEGIN - IDS_2080 "Ðеможливо ініціалізувати FluidSynth" - IDS_2081 "Шина" - IDS_2082 "Файл" - IDS_2083 "C" - IDS_2084 "H" - IDS_2085 "S" - IDS_2086 "МБ" - IDS_2087 "ПеревірÑти BPB" - IDS_2088 "КБ" - IDS_2089 "Ðе вдалоÑÑ Ñ–Ð½Ñ–Ñ†Ñ–Ð°Ð»Ñ–Ð·ÑƒÐ²Ð°Ñ‚Ð¸ рендер відео." - IDS_2090 "За замовчуваннÑм" - IDS_2091 "%i WS" - IDS_2092 "Тип" - IDS_2093 "Ðе вдалоÑÑ Ð½Ð°Ð»Ð°ÑˆÑ‚ÑƒÐ²Ð°Ñ‚Ð¸ PCap" - IDS_2094 "ПриÑтрої PCap не знайдені" - IDS_2095 "Ðевірний приÑтрій PCap" - IDS_2096 "Стандартний 2-кнопковий джойÑтик" - IDS_2097 "Стандартний 4-кнопковий джойÑтик" - IDS_2098 "Стандартний 6-кнопковий джойÑтик" - IDS_2099 "Стандартний 8-кнопковий джойÑтик" - IDS_2100 "CH Flightstick Pro" - IDS_2101 "Microsoft SideWinder Pad" - IDS_2102 "СиÑтема ÑƒÐ¿Ñ€Ð°Ð²Ð»Ñ–Ð½Ð½Ñ Ð¿Ð¾Ð»ÑŒÐ¾Ñ‚Ð¾Ð¼ Thrustmaster" - IDS_2103 "ÐÑ–" - IDS_2104 "Ðеможливо завантажити приÑкорювачі клавіатури." - IDS_2105 "Ðеможливо зарреєÑтрувати необроблене (RAW) введеннÑ." - IDS_2106 "%u" - IDS_2107 "%u МБ (CHS: %i, %i, %i)" - IDS_2108 "ДиÑковод %i (%s): %ls" - IDS_2109 "Ð’ÑÑ– образи (*.0??;*.1??;*.??0;*.86F;*.BIN;*.CQ?;*.D??;*.FLP;*.HDM;*.IM?;*.JSON;*.TD0;*.*FD?;*.MFM;*.XDF)\0*.0??;*.1??;*.??0;*.86F;*.BIN;*.CQ?;*.D??;*.FLP;*.HDM;*.IM?;*.JSON;*.TD0;*.*FD?;*.MFM;*.XDF\0Розширені образи Ñекторів (*.IMD;*.JSON;*.TD0)\0*.IMD;*.JSON;*.TD0\0ОÑновні образи Ñекторів (*.0??;*.1??;*.??0;*.BIN;*.CQ?;*.D??;*.FLP;*.HDM;*.IM?;*.XDF;*.*FD?)\0*.0??;*.1??;*.??0;*.BIN;*.CQ?;*.D??;*.FLP;*.HDM;*.IM?;*.XDF;*.*FD?\0Образи Flux (*.FDI)\0*.FDI\0Образи Surface (*.86F;*.MFM)\0*.86F;*.MFM\0Ð’ÑÑ– файли (*.*)\0*.*\0" - IDS_2110 "Ðеможливо ініціалізувати FreeType" - IDS_2111 "Ðеможливо ініціалізувати SDL, потрібно SDL2.dll" - IDS_2112 "Ви впевнені, що хочете виконати холодне Ð¿ÐµÑ€ÐµÐ·Ð°Ð²Ð°Ð½Ñ‚Ð°Ð¶ÐµÐ½Ð½Ñ ÐµÐ¼ÑƒÐ»ÑŒÐ¾Ð²Ð°Ð½Ð¾Ñ— машини?" - IDS_2113 "Ви впевнені, що хочете вийти з 86Box?" - IDS_2114 "Ðеможливо ініціалізувати Ghostscript" - IDS_2115 "Магнітооптичний %i (%ls): %ls" - IDS_2116 "Образи магнітооптичних диÑків (*.IM?;*.MDI)\0*.IM?;*.MDI\0Ð’Ñе файлы (*.*)\0*.*\0" - IDS_2117 "ЛаÑкаво проÑимо в 86Box!" - IDS_2118 "Вбудований контролер" - IDS_2119 "Вихід" - IDS_2120 "ПЗУ не знайдені" - IDS_2121 "Чи бажаєте ви зберегти налаштуваннÑ?" - IDS_2122 "Це призведе до холодної перезагрузки емульованої машини." - IDS_2123 "Зберегти" - IDS_2124 "Про 86Box" - IDS_2125 "86Box v." EMU_VERSION + IDS_2081 "Шина" + IDS_2082 "Файл" + IDS_2083 "C" + IDS_2084 "H" + IDS_2085 "S" + IDS_2086 "МБ" + IDS_2087 "Speed" + IDS_2088 "ПеревірÑти BPB" + IDS_2089 "КБ" + IDS_2090 "Ðе вдалоÑÑ Ñ–Ð½Ñ–Ñ†Ñ–Ð°Ð»Ñ–Ð·ÑƒÐ²Ð°Ñ‚Ð¸ рендер відео." + IDS_2091 "За замовчуваннÑм" + IDS_2092 "%i WS" + IDS_2093 "Тип" + IDS_2094 "Ðе вдалоÑÑ Ð½Ð°Ð»Ð°ÑˆÑ‚ÑƒÐ²Ð°Ñ‚Ð¸ PCap" + IDS_2095 "ПриÑтрої PCap не знайдені" + IDS_2096 "Ðевірний приÑтрій PCap" + IDS_2097 "Стандартний 2-кнопковий джойÑтик" + IDS_2098 "Стандартний 4-кнопковий джойÑтик" + IDS_2099 "Стандартний 6-кнопковий джойÑтик" + IDS_2100 "Стандартний 8-кнопковий джойÑтик" + IDS_2101 "CH Flightstick Pro" + IDS_2102 "Microsoft SideWinder Pad" + IDS_2103 "СиÑтема ÑƒÐ¿Ñ€Ð°Ð²Ð»Ñ–Ð½Ð½Ñ Ð¿Ð¾Ð»ÑŒÐ¾Ñ‚Ð¾Ð¼ Thrustmaster" + IDS_2104 "ÐÑ–" + IDS_2105 "Ðеможливо завантажити приÑкорювачі клавіатури." + IDS_2106 "Ðеможливо зарреєÑтрувати необроблене (RAW) введеннÑ." + IDS_2107 "%u" + IDS_2108 "%u МБ (CHS: %i, %i, %i)" + IDS_2109 "ДиÑковод %i (%s): %ls" + IDS_2110 "УÑÑ– образи (*.0??;*.1??;*.??0;*.86F;*.BIN;*.CQ?;*.D??;*.FLP;*.HDM;*.IM?;*.JSON;*.TD0;*.*FD?;*.MFM;*.XDF)\0*.0??;*.1??;*.??0;*.86F;*.BIN;*.CQ?;*.D??;*.FLP;*.HDM;*.IM?;*.JSON;*.TD0;*.*FD?;*.MFM;*.XDF\0Розширені образи Ñекторів (*.IMD;*.JSON;*.TD0)\0*.IMD;*.JSON;*.TD0\0ОÑновні образи Ñекторів (*.0??;*.1??;*.??0;*.BIN;*.CQ?;*.D??;*.FLP;*.HDM;*.IM?;*.XDF;*.*FD?)\0*.0??;*.1??;*.??0;*.BIN;*.CQ?;*.D??;*.FLP;*.HDM;*.IM?;*.XDF;*.*FD?\0Образи Flux (*.FDI)\0*.FDI\0Образи Surface (*.86F;*.MFM)\0*.86F;*.MFM\0УÑÑ– файли (*.*)\0*.*\0" + IDS_2112 "Ðеможливо ініціалізувати SDL, потрібно SDL2.dll" + IDS_2113 "Ви впевнені, що хочете виконати холодне Ð¿ÐµÑ€ÐµÐ·Ð°Ð²Ð°Ð½Ñ‚Ð°Ð¶ÐµÐ½Ð½Ñ ÐµÐ¼ÑƒÐ»ÑŒÐ¾Ð²Ð°Ð½Ð¾Ñ— машини?" + IDS_2114 "Ви впевнені, що хочете вийти з 86Box?" + IDS_2115 "Ðеможливо ініціалізувати Ghostscript" + IDS_2116 "Магнітооптичний %i (%ls): %ls" + IDS_2117 "Образи магнітооптичних диÑків (*.IM?;*.MDI)\0*.IM?;*.MDI\0УÑÑ– файлі (*.*)\0*.*\0" + IDS_2118 "ЛаÑкаво проÑимо в 86Box!" + IDS_2119 "Вбудований контролер" + IDS_2120 "Вихід" + IDS_2121 "ПЗУ не знайдені" + IDS_2122 "Чи бажаєте ви зберегти налаштуваннÑ?" + IDS_2123 "Це призведе до холодної перезагрузки емульованої машини." + IDS_2124 "Зберегти" + IDS_2125 "Про 86Box" + IDS_2126 "86Box v." EMU_VERSION - IDS_2126 "ЕмулÑтор Ñтарих комп'ютерів\n\nÐвтори: Sarah Walker, Miran Grca, Fred N. van Kempen (waltje), SA1988, Tiseno100, reenigne, leilei, JohnElliott, greatpsycho, and others.\n\nВипуÑкаєтÑÑ Ð¿Ñ–Ð´ ліцензією GNU General Public License верÑÑ–Ñ— 2 або більше пізніше. Додадкову інформацію Ñм. у файлі LICENSE." - IDS_2127 "OK" - IDS_2128 "ÐžÐ±Ð»Ð°Ð´Ð½Ð°Ð½Ð½Ñ Ð½ÐµÐ´Ð¾Ñтупне" + IDS_2127 "ЕмулÑтор Ñтарих комп'ютерів\n\nÐвтори: Miran GrÄa (OBattler), RichardG867, Jasmine Iwanek, TC1995, coldbrewed, Teemu Korhonen (Manaatti), Joakim L. Gilje, Adrien Moulin (elyosh), Daniel Balsom (gloriouscow), Cacodemon345, Fred N. van Kempen (waltje), Tiseno100, reenigne, and others.\n\nWith previous core contributions from Sarah Walker, leilei, JohnElliott, greatpsycho, and others.\n\nВипуÑкаєтÑÑ Ð¿Ñ–Ð´ ліцензією GNU General Public License верÑÑ–Ñ— 2 або більше пізніше. Додадкову інформацію Ñм. у файлі LICENSE." + IDS_2128 "OK" + IDS_2129 "ÐžÐ±Ð»Ð°Ð´Ð½Ð°Ð½Ð½Ñ Ð½ÐµÐ´Ð¾Ñтупне" #ifdef _WIN32 #define LIB_NAME_PCAP "WinPcap" #else #define LIB_NAME_PCAP "libpcap" #endif - IDS_2129 "ПереконайтеÑÑŒ, що " LIB_NAME_PCAP " вÑтановлений Ñ– ваше мережеве з'єднаннÑ, ÑуміÑне з " LIB_NAME_PCAP "." - IDS_2130 "ÐеприпуÑтима конфігураціÑ" -#ifdef _WIN32 -#define LIB_NAME_FREETYPE "freetype.dll" -#else -#define LIB_NAME_FREETYPE "libfreetype" -#endif - IDS_2131 "Ð”Ð»Ñ ÐµÐ¼ÑƒÐ»Ñції принтера ESC/P потрібно " LIB_NAME_FREETYPE "." + IDS_2130 "ПереконайтеÑÑŒ, що " LIB_NAME_PCAP " вÑтановлений Ñ– ваше мережеве з'єднаннÑ, ÑуміÑне з " LIB_NAME_PCAP "." + IDS_2131 "ÐеприпуÑтима конфігураціÑ" #ifdef _WIN32 #define LIB_NAME_GS "gsdll32.dll" #else #define LIB_NAME_GS "libgs" #endif - IDS_2132 LIB_NAME_GS " потрібно Ð´Ð»Ñ Ð°Ð²Ñ‚Ð¾Ð¼Ð°Ñ‚Ð¸Ñ‡Ð½Ð¾Ð³Ð¾ Ð¿ÐµÑ€ÐµÑ‚Ð²Ð¾Ñ€ÐµÐ½Ð½Ñ Ñ„Ð°Ð¹Ð»Ñ–Ð² PostScript в PDF.\n\nÐ’ÑÑ– документи, відправлені на загальний принтер PostScript, будуть збережені у виглÑді файлів PostScript (.ps)." -#ifdef _WIN32 -#define LIB_NAME_FLUIDSYNTH "libfluidsynth.dll" -#else -#define LIB_NAME_FLUIDSYNTH "libfluidsynth" -#endif - IDS_2133 "Ð”Ð»Ñ FluidSynth MIDI-виÑновку потрібно " LIB_NAME_FLUIDSYNTH "." - IDS_2134 "Вхід у повноекранний режим" - IDS_2135 "Більше не показувати це повідомленнÑ" - IDS_2136 "Ðе виходити" - IDS_2137 "Перезавантажити" - IDS_2138 "Ðе перезавантажувати" - IDS_2139 "Образи магнітооптичних диÑків (*.IM?;*.MDI)\0*.IM?;*.MDI\0УÑÑ– файли (*.*)\0*.*\0" - IDS_2140 "Образи CD-ROM (*.ISO;*.CUE)\0*.ISO;*.CUE\0УÑÑ– файли (*.*)\0*.*\0" - IDS_2141 "ÐšÐ¾Ð½Ñ„Ñ–Ð³ÑƒÑ€Ð°Ñ†Ñ–Ñ Ð¿Ñ€Ð¸Ñтрою %hs" - IDS_2142 "Монітор у ÑплÑчому режимі" - IDS_2143 "Шейдери OpenGL (*.GLSL)\0*.GLSL\0УÑÑ– файли (*.*)\0*.*\0" - IDS_2144 "Параметри OpenGL" - IDS_2145 "Ви завантажуєте непідтримувану конфігурацію" - IDS_2146 "Вибір типів ЦП Ð´Ð»Ñ Ñ†Ñ–Ñ”Ñ— ÑиÑтемної плати на даній емульованій машині відключено.\n\nЦе дозволÑÑ” вибрати процеÑор, Ñкий в іншому випадку не ÑуміÑний з вибраною материнÑькою платою. Однак, ви можете зіткнутиÑÑ Ð· неÑуміÑніÑтю з BIOS материнÑької плати або іншим ПО.\n\nÐ’ÐºÐ»ÑŽÑ‡ÐµÐ½Ð½Ñ Ñ†ÑŒÐ¾Ð³Ð¾ параметра офіційно не підтримуєтьÑÑ, Ñ– вÑÑ– подані звіти про помилки можуть бути закриті Ñк недійÑні." - IDS_2147 "Продовжити" - IDS_2148 "КаÑета: %s" - IDS_2149 "Образи каÑет (*.PCM;*.RAW;*.WAV;*.CAS)\0*.PCM;*.RAW;*.WAV;*.CAS\0УÑÑ– файли (*.*)\0*. *\0" - IDS_2150 "Картридж %i: %ls" - IDS_2151 "Образи картриджів (*.A;*.B;*.JRC)\0*.A;*.B;*.JRC\0Ð’ÑÑ– файли (*.*)\0*.*\0" - IDS_2152 "Помилка ініціалізації рендерера" - IDS_2153 "Ðеможливо ініціалізувати рендерер OpenGL (3.0). Будь лаÑка, викориÑтовуйте інший рендерер." - IDS_2154 "Відновити виконаннÑ" - IDS_2155 "Призупинити виконаннÑ" - IDS_2156 "ÐатиÑнути Ctrl+Alt+Del" - IDS_2157 "ÐатиÑнути Ctrl+Alt+Esc" - IDS_2158 "Холодне перезавантаженнÑ" - IDS_2159 "Сигнал Ð·Ð°Ð²ÐµÑ€ÑˆÐµÐ½Ð½Ñ ACPI" - IDS_2160 "ÐÐ°Ð»Ð°ÑˆÑ‚ÑƒÐ²Ð°Ð½Ð½Ñ Ð¼Ð°ÑˆÐ¸Ð½Ð¸" + IDS_2133 LIB_NAME_GS " потрібно Ð´Ð»Ñ Ð°Ð²Ñ‚Ð¾Ð¼Ð°Ñ‚Ð¸Ñ‡Ð½Ð¾Ð³Ð¾ Ð¿ÐµÑ€ÐµÑ‚Ð²Ð¾Ñ€ÐµÐ½Ð½Ñ Ñ„Ð°Ð¹Ð»Ñ–Ð² PostScript в PDF.\n\nÑÑ– документи, відправлені на загальний принтер PostScript, будуть збережені у виглÑді файлів PostScript (.ps)." + IDS_2135 "Вхід у повноекранний режим" + IDS_2136 "Більше не показувати це повідомленнÑ" + IDS_2137 "Ðе виходити" + IDS_2138 "Перезавантажити" + IDS_2139 "Ðе перезавантажувати" + IDS_2140 "Образи магнітооптичних диÑків (*.IM?;*.MDI)\0*.IM?;*.MDI\0УÑÑ– файли (*.*)\0*.*\0" + IDS_2141 "Образи CD-ROM (*.ISO;*.CUE)\0*.ISO;*.CUE\0УÑÑ– файли (*.*)\0*.*\0" + IDS_2142 "ÐšÐ¾Ð½Ñ„Ñ–Ð³ÑƒÑ€Ð°Ñ†Ñ–Ñ Ð¿Ñ€Ð¸Ñтрою %hs" + IDS_2143 "Монітор у ÑплÑчому режимі" + IDS_2144 "Шейдери OpenGL (*.GLSL)\0*.GLSL\0УÑÑ– файли (*.*)\0*.*\0" + IDS_2145 "Параметри OpenGL" + IDS_2146 "Ви завантажуєте непідтримувану конфігурацію" + IDS_2147 "Вибір типів ЦП Ð´Ð»Ñ Ñ†Ñ–Ñ”Ñ— ÑиÑтемної плати на даній емульованій машині відключено.\n\nЦе дозволÑÑ” вибрати процеÑор, Ñкий в іншому випадку не ÑуміÑний з вибраною материнÑькою платою. Однак, ви можете зіткнутиÑÑ Ð· неÑуміÑніÑтю з BIOS материнÑької плати або іншим ПО.\n\nÐ’ÐºÐ»ÑŽÑ‡ÐµÐ½Ð½Ñ Ñ†ÑŒÐ¾Ð³Ð¾ параметра офіційно не підтримуєтьÑÑ, Ñ– вÑÑ– подані звіти про помилки можуть бути закриті Ñк недійÑні." + IDS_2148 "Продовжити" + IDS_2149 "КаÑета: %s" + IDS_2150 "Образи каÑет (*.PCM;*.RAW;*.WAV;*.CAS)\0*.PCM;*.RAW;*.WAV;*.CAS\0УÑÑ– файли (*.*)\0*. *\0" + IDS_2151 "Картридж %i: %ls" + IDS_2152 "Образи картриджів (*.A;*.B;*.JRC)\0*.A;*.B;*.JRC\0УÑÑ– файли (*.*)\0*.*\0" + IDS_2153 "Помилка ініціалізації рендерера" + IDS_2154 "Ðеможливо ініціалізувати рендерер OpenGL (3.0). Будь лаÑка, викориÑтовуйте інший рендерер." + IDS_2155 "Відновити виконаннÑ" + IDS_2156 "Призупинити виконаннÑ" + IDS_2157 "ÐатиÑнути Ctrl+Alt+Del" + IDS_2158 "ÐатиÑнути Ctrl+Alt+Esc" + IDS_2159 "Холодне перезавантаженнÑ" + IDS_2160 "Сигнал Ð·Ð°Ð²ÐµÑ€ÑˆÐµÐ½Ð½Ñ ACPI" + IDS_2161 "ÐÐ°Ð»Ð°ÑˆÑ‚ÑƒÐ²Ð°Ð½Ð½Ñ Ð¼Ð°ÑˆÐ¸Ð½Ð¸" + IDS_2162 "Type" + IDS_2163 "No Dynarec" + IDS_2164 "Old Dynarec" + IDS_2165 "New Dynarec" + IDS_2166 "Відеокарта #2 ""%hs"" недоÑтупна через відÑутніÑть файлу Ñ—Ñ— ПЗУ в каталозі roms/video. Ð’Ñ–Ð´ÐºÐ»ÑŽÑ‡ÐµÐ½Ð½Ñ Ð´Ñ€ÑƒÐ³Ð¾Ñ— відеокарти." + IDS_2167 "Failed to initialize network driver" + IDS_2168 "The network configuration will be switched to the null driver" END STRINGTABLE DISCARDABLE BEGIN - IDS_4096 "ЖорÑткий диÑк (%s)" - IDS_4097 "%01i:%01i" - IDS_4098 "%01i" - IDS_4099 "MFM/RLL або ESDI диÑководів CD-ROM ніколи не Ñ–Ñнувало" - IDS_4100 "Задати вручну..." - IDS_4101 "Задати вручну (large)..." - IDS_4102 "Створити новий жорÑткий диÑк" - IDS_4103 "Вибрати Ñ–Ñнуючий жорÑткий диÑк" - IDS_4104 "Розмір образів диÑків HDI не може перевищувати 4 ГБ." - IDS_4105 "Розмір образів диÑків не може перевищувати 127 ГБ." - IDS_4106 "Образи жорÑтких диÑків (*.HD?;*.IM?;*.VHD)\0*.HD?;*.IM?;*.VHD\0Ð’ÑÑ– файли (*.*)\0*.*\0 " - IDS_4107 "Ðеможливо прочитати файл" - IDS_4108 "Ðеможливо запиÑати файл" - IDS_4109 "Образи HDI або HDX з розміром Ñектора, відмінним від 512, не підтримуютьÑÑ." - IDS_4110 "USB поки не підтримуєтьÑÑ" - IDS_4111 "Файл образу диÑка вже Ñ–Ñнує" - IDS_4112 "Вкажіть правильне ім'Ñ Ñ„Ð°Ð¹Ð»Ñƒ." - IDS_4113 "Образ диÑку Ñтворено" - IDS_4114 "ПереконайтеÑÑ, що файл Ñ” доÑтупним Ð´Ð»Ñ Ñ‡Ð¸Ñ‚Ð°Ð½Ð½Ñ." - IDS_4115 "ПереконайтеÑÑ, що файл зберігаєтьÑÑ Ð² каталог, Ñкий Ñ” доÑтупним Ð´Ð»Ñ Ð·Ð°Ð¿Ð¸Ñу." - IDS_4116 "Занадто великий образ диÑка" - IDS_4117 "Ðе забудьте розмітити та відформатувати новоÑтворений диÑк." - IDS_4118 "Вибраний файл буде перезапиÑано. Ви впевнені, що хочете викориÑтовувати його?" - IDS_4119 "Образ диÑка, що не підтримуєтьÑÑ" - IDS_4120 "ПерезапиÑати" - IDS_4121 "Ðе перезапиÑувати" - IDS_4122 "RAW образ (.img)" - IDS_4123 "Образ HDI (.hdi)" - IDS_4124 "Образ HDX (.hdx)" - IDS_4125 "VHD фікÑованого розміру (.vhd)" - IDS_4126 "VHD динамічного розміру (.vhd)" - IDS_4127 "Диференційований образ VHD (.vhd)" - IDS_4128 "Великі блоки (2 МБ)" - IDS_4129 "Маленькі блоки (512 КБ)" - IDS_4130 "Файли VHD (*.VHD)\0*.VHD\0Ð’ÑÑ– файли (*.*)\0*.*\0" - IDS_4131 "Виберіть батьківÑький VHD" - IDS_4132 "Це може означати, що батьківÑький образ був змінений піÑÐ»Ñ Ñ‚Ð¾Ð³Ð¾, Ñк було Ñтворено диференційований образ.\n\nЦе також може ÑтатиÑÑ, Ñкщо файли Ð·Ð¾Ð±Ñ€Ð°Ð¶ÐµÐ½Ð½Ñ Ð±ÑƒÐ»Ð¸ переміщені або Ñкопійовані, або через помилку в програмі, що Ñтворила цей диÑк.\n \nВи хочете виправити тимчаÑові позначки?" - IDS_4133 "ТимчаÑові мітки батьківÑького та дочірнього диÑків не Ñпівпадають" - IDS_4134 "Ðе вдалоÑÑ Ð²Ð¸Ð¿Ñ€Ð°Ð²Ð¸Ñ‚Ð¸ тимчаÑову позначку VHD." - IDS_4135 "%01i:%02i" + IDS_4096 "ЖорÑткий диÑк (%s)" + IDS_4097 "%01i:%01i" + IDS_4098 "%01i" + IDS_4099 "MFM/RLL або ESDI диÑководів CD-ROM ніколи не Ñ–Ñнувало" + IDS_4100 "Задати вручну..." + IDS_4101 "Задати вручну (large)..." + IDS_4102 "Створити новий жорÑткий диÑк" + IDS_4103 "Вибрати Ñ–Ñнуючий жорÑткий диÑк" + IDS_4104 "Розмір образів диÑків HDI не може перевищувати 4 ГБ." + IDS_4105 "Розмір образів диÑків не може перевищувати 127 ГБ." + IDS_4106 "Образи жорÑтких диÑків (*.HD?;*.IM?;*.VHD)\0*.HD?;*.IM?;*.VHD\0УÑÑ– файли (*.*)\0*.*\0 " + IDS_4107 "Ðеможливо прочитати файл" + IDS_4108 "Ðеможливо запиÑати файл" + IDS_4109 "Образи HDI або HDX з розміром Ñектора, відмінним від 512, не підтримуютьÑÑ." + IDS_4110 "USB поки не підтримуєтьÑÑ" + IDS_4111 "Файл образу диÑка вже Ñ–Ñнує" + IDS_4112 "Вкажіть правильне ім'Ñ Ñ„Ð°Ð¹Ð»Ñƒ." + IDS_4113 "Образ диÑку Ñтворено" + IDS_4114 "ПереконайтеÑÑ, що файл Ñ” доÑтупним Ð´Ð»Ñ Ñ‡Ð¸Ñ‚Ð°Ð½Ð½Ñ." + IDS_4115 "ПереконайтеÑÑ, що файл зберігаєтьÑÑ Ð² каталог, Ñкий Ñ” доÑтупним Ð´Ð»Ñ Ð·Ð°Ð¿Ð¸Ñу." + IDS_4116 "Занадто великий образ диÑка" + IDS_4117 "Ðе забудьте розмітити та відформатувати новоÑтворений диÑк." + IDS_4118 "Вибраний файл буде перезапиÑано. Ви впевнені, що хочете викориÑтовувати його?" + IDS_4119 "Образ диÑка, що не підтримуєтьÑÑ" + IDS_4120 "ПерезапиÑати" + IDS_4121 "Ðе перезапиÑувати" + IDS_4122 "RAW образ (.img)" + IDS_4123 "Образ HDI (.hdi)" + IDS_4124 "Образ HDX (.hdx)" + IDS_4125 "VHD фікÑованого розміру (.vhd)" + IDS_4126 "VHD динамічного розміру (.vhd)" + IDS_4127 "Диференційований образ VHD (.vhd)" + IDS_4128 "Великі блоки (2 МБ)" + IDS_4129 "Маленькі блоки (512 КБ)" + IDS_4130 "Файли VHD (*.VHD)\0*.VHD\0УÑÑ– файли (*.*)\0*.*\0" + IDS_4131 "Виберіть батьківÑький VHD" + IDS_4132 "Це може означати, що батьківÑький образ був змінений піÑÐ»Ñ Ñ‚Ð¾Ð³Ð¾, Ñк було Ñтворено диференційований образ.\n\nЦе також може ÑтатиÑÑ, Ñкщо файли Ð·Ð¾Ð±Ñ€Ð°Ð¶ÐµÐ½Ð½Ñ Ð±ÑƒÐ»Ð¸ переміщені або Ñкопійовані, або через помилку в програмі, що Ñтворила цей диÑк.\n \nВи хочете виправити тимчаÑові позначки?" + IDS_4133 "ТимчаÑові мітки батьківÑького та дочірнього диÑків не Ñпівпадають" + IDS_4134 "Ðе вдалоÑÑ Ð²Ð¸Ð¿Ñ€Ð°Ð²Ð¸Ñ‚Ð¸ тимчаÑову позначку VHD." + IDS_4135 "%01i:%02i" - IDS_4352 "MFM/RLL" - IDS_4353 "XTA" - IDS_4354 "ESDI" - IDS_4355 "IDE" - IDS_4356 "ATAPI" - IDS_4357 "SCSI" + IDS_4352 "MFM/RLL" + IDS_4353 "XTA" + IDS_4354 "ESDI" + IDS_4355 "IDE" + IDS_4356 "ATAPI" + IDS_4357 "SCSI" - IDS_4608 "MFM/RLL (%01i:%01i)" - IDS_4609 "XTA (%01i:%01i)" - IDS_4610 "ESDI (%01i:%01i)" - IDS_4611 "IDE (%01i:%01i)" - IDS_4612 "ATAPI (%01i:%01i)" - IDS_4613 "SCSI (%01i:%02i)" + IDS_4608 "MFM/RLL (%01i:%01i)" + IDS_4609 "XTA (%01i:%01i)" + IDS_4610 "ESDI (%01i:%01i)" + IDS_4611 "IDE (%01i:%01i)" + IDS_4612 "ATAPI (%01i:%01i)" + IDS_4613 "SCSI (%01i:%02i)" - IDS_5120 "CD-ROM %i (%s): %s" + IDS_5120 "CD-ROM %i (%s): %s" - IDS_5376 "Відключено" - IDS_5381 "ATAPI" - IDS_5382 "SCSI" + IDS_5376 "Відключено" + IDS_5381 "ATAPI" + IDS_5382 "SCSI" - IDS_5632 "Відключено" - IDS_5637 "ATAPI (%01i:%01i)" - IDS_5638 "SCSI (%01i:%02i)" + IDS_5632 "Відключено" + IDS_5637 "ATAPI (%01i:%01i)" + IDS_5638 "SCSI (%01i:%02i)" - IDS_5888 "160 кБ" - IDS_5889 "180 кБ" - IDS_5890 "320 кБ" - IDS_5891 "360 кБ" - IDS_5892 "640 кБ" - IDS_5893 "720 кБ" - IDS_5894 "1.2 МБ" - IDS_5895 "1.25 МБ" - IDS_5896 "1.44 МБ" - IDS_5897 "DMF (клаÑтер 1024)" - IDS_5898 "DMF (клаÑтер 2048)" - IDS_5899 "2.88 МБ" - IDS_5900 "ZIP 100" - IDS_5901 "ZIP 250" - IDS_5902 "3.5"" 128 МБ (ISO 10090)" - IDS_5903 "3.5"" 230 МБ (ISO 13963)" - IDS_5904 "3.5"" 540 МБ (ISO 15498)" - IDS_5905 "3.5"" 640 МБ (ISO 15498)" - IDS_5906 "3.5"" 1.3 ГБ (GigaMO)" - IDS_5907 "3.5"" 2.3 ГБ (GigaMO 2)" - IDS_5908 "5.25"" 600 МБ" - IDS_5909 "5.25"" 650 МБ" - IDS_5910 "5.25"" 1 ГБ" - IDS_5911 "5.25"" 1.3 ГБ" + IDS_5888 "160 кБ" + IDS_5889 "180 кБ" + IDS_5890 "320 кБ" + IDS_5891 "360 кБ" + IDS_5892 "640 кБ" + IDS_5893 "720 кБ" + IDS_5894 "1.2 МБ" + IDS_5895 "1.25 МБ" + IDS_5896 "1.44 МБ" + IDS_5897 "DMF (клаÑтер 1024)" + IDS_5898 "DMF (клаÑтер 2048)" + IDS_5899 "2.88 МБ" + IDS_5900 "ZIP 100" + IDS_5901 "ZIP 250" + IDS_5902 "3.5"" 128 МБ (ISO 10090)" + IDS_5903 "3.5"" 230 МБ (ISO 13963)" + IDS_5904 "3.5"" 540 МБ (ISO 15498)" + IDS_5905 "3.5"" 640 МБ (ISO 15498)" + IDS_5906 "3.5"" 1.3 ГБ (GigaMO)" + IDS_5907 "3.5"" 2.3 ГБ (GigaMO 2)" + IDS_5908 "5.25"" 600 МБ" + IDS_5909 "5.25"" 650 МБ" + IDS_5910 "5.25"" 1 ГБ" + IDS_5911 "5.25"" 1.3 ГБ" - IDS_6144 "Точний RPM" - IDS_6145 "Ðа 1% повільніше точного RPM" - IDS_6146 "Ðа 1.5% повільніше точного RPM" - IDS_6147 "Ðа 2% повільніше точного RPM" + IDS_6144 "Точний RPM" + IDS_6145 "Ðа 1% повільніше точного RPM" + IDS_6146 "Ðа 1.5% повільніше точного RPM" + IDS_6147 "Ðа 2% повільніше точного RPM" - IDS_7168 "(СиÑтемний)" + IDS_7168 "(СиÑтемний)" END #define IDS_LANG_ENUS IDS_7168 diff --git a/src/win/languages/zh-CN.rc b/src/win/languages/zh-CN.rc index accc0dd47..92afaf86d 100644 --- a/src/win/languages/zh-CN.rc +++ b/src/win/languages/zh-CN.rc @@ -13,113 +13,122 @@ LANGUAGE LANG_CHINESE, SUBLANG_CHINESE_SIMPLIFIED // Menu // -MainMenu MENU DISCARDABLE +MainMenu MENU DISCARDABLE BEGIN POPUP "æ“作(&A)" BEGIN - MENUITEM "é”®ç›˜éœ€è¦æ•æ‰(&K)", IDM_ACTION_KBD_REQ_CAPTURE - MENUITEM "å°†å³ CTRL 键映射为左 ALT é”®(&R)", IDM_ACTION_RCTRL_IS_LALT + MENUITEM "é”®ç›˜éœ€è¦æ•æ‰(&K)", IDM_ACTION_KBD_REQ_CAPTURE + MENUITEM "å°†å³ CTRL 键映射为左 ALT é”®(&R)", IDM_ACTION_RCTRL_IS_LALT MENUITEM SEPARATOR - MENUITEM "硬é‡ç½®(&H)...", IDM_ACTION_HRESET - MENUITEM "Ctrl+Alt+Del(&C)\tCtrl+F12", IDM_ACTION_RESET_CAD + MENUITEM "硬é‡ç½®(&H)...", IDM_ACTION_HRESET + MENUITEM "Ctrl+Alt+Del(&C)\tCtrl+F12", IDM_ACTION_RESET_CAD MENUITEM SEPARATOR - MENUITEM "Ctrl+Alt+Esc(&E)", IDM_ACTION_CTRL_ALT_ESC + MENUITEM "Ctrl+Alt+Esc(&E)", IDM_ACTION_CTRL_ALT_ESC MENUITEM SEPARATOR - MENUITEM "æš‚åœ(&P)", IDM_ACTION_PAUSE + MENUITEM "æš‚åœ(&P)", IDM_ACTION_PAUSE MENUITEM SEPARATOR - MENUITEM "退出(&X)...", IDM_ACTION_EXIT + MENUITEM "退出(&X)...", IDM_ACTION_EXIT END POPUP "查看(&V)" BEGIN - MENUITEM "éšè—çŠ¶æ€æ (&H)", IDM_VID_HIDE_STATUS_BAR - MENUITEM "éšè—工具æ (&T)", IDM_VID_HIDE_TOOLBAR + MENUITEM "éšè—çŠ¶æ€æ (&H)", IDM_VID_HIDE_STATUS_BAR + MENUITEM "éšè—工具æ (&T)", IDM_VID_HIDE_TOOLBAR MENUITEM SEPARATOR - MENUITEM "窗å£å¤§å°å¯è°ƒ(&R)", IDM_VID_RESIZE - MENUITEM "è®°ä½çª—å£å¤§å°å’Œä½ç½®(&E)", IDM_VID_REMEMBER + MENUITEM "æ˜¾ç¤ºæ¬¡è¦æ˜¾ç¤ºå™¨(&S)", IDM_VID_MONITORS + MENUITEM "窗å£å¤§å°å¯è°ƒ(&R)", IDM_VID_RESIZE + MENUITEM "è®°ä½çª—å£å¤§å°å’Œä½ç½®(&E)", IDM_VID_REMEMBER MENUITEM SEPARATOR POPUP "渲染器(&N)" BEGIN - MENUITEM "SDL (软件)(&S)", IDM_VID_SDL_SW - MENUITEM "SDL (硬件)(&H)", IDM_VID_SDL_HW - MENUITEM "SDL (OpenGL)(&O)", IDM_VID_SDL_OPENGL - MENUITEM "OpenGL (3.0 核心)(&G)", IDM_VID_OPENGL_CORE + MENUITEM "SDL (软件)(&S)", IDM_VID_SDL_SW + MENUITEM "SDL (硬件)(&H)", IDM_VID_SDL_HW + MENUITEM "SDL (OpenGL)(&O)", IDM_VID_SDL_OPENGL + MENUITEM "OpenGL (3.0 核心)(&G)", IDM_VID_OPENGL_CORE #ifdef USE_VNC - MENUITEM "VNC(&V)", IDM_VID_VNC + MENUITEM "VNC(&V)", IDM_VID_VNC #endif END MENUITEM SEPARATOR - MENUITEM "指定窗å£å¤§å°...", IDM_VID_SPECIFY_DIM - MENUITEM "强制 4:3 显示比例(&O)", IDM_VID_FORCE43 + MENUITEM "指定窗å£å¤§å°...", IDM_VID_SPECIFY_DIM + MENUITEM "强制 4:3 显示比例(&O)", IDM_VID_FORCE43 POPUP "窗å£ç¼©æ”¾ç³»æ•°(&W)" BEGIN - MENUITEM "0.5x(&0)", IDM_VID_SCALE_1X - MENUITEM "1x(&1)", IDM_VID_SCALE_2X - MENUITEM "1.5x(&5)", IDM_VID_SCALE_3X - MENUITEM "2x(&2)", IDM_VID_SCALE_4X + MENUITEM "0.5x(&0)", IDM_VID_SCALE_1X + MENUITEM "1x(&1)", IDM_VID_SCALE_2X + MENUITEM "1.5x(&5)", IDM_VID_SCALE_3X + MENUITEM "2x(&2)", IDM_VID_SCALE_4X + MENUITEM "&3x", IDM_VID_SCALE_5X + MENUITEM "&4x", IDM_VID_SCALE_6X + MENUITEM "&5x", IDM_VID_SCALE_7X + MENUITEM "&6x", IDM_VID_SCALE_8X + MENUITEM "&7x", IDM_VID_SCALE_9X + MENUITEM "&8x", IDM_VID_SCALE_10X END POPUP "过滤方å¼" BEGIN - MENUITEM "邻近(&N)", IDM_VID_FILTER_NEAREST - MENUITEM "线性(&L)", IDM_VID_FILTER_LINEAR + MENUITEM "邻近(&N)", IDM_VID_FILTER_NEAREST + MENUITEM "线性(&L)", IDM_VID_FILTER_LINEAR END - MENUITEM "HiDPI 缩放(&D)", IDM_VID_HIDPI + MENUITEM "HiDPI 缩放(&D)", IDM_VID_HIDPI MENUITEM SEPARATOR - MENUITEM "å…¨å±(&F)\tCtrl+Alt+PgUp", IDM_VID_FULLSCREEN + MENUITEM "å…¨å±(&F)\tCtrl+Alt+PgUp", IDM_VID_FULLSCREEN POPUP "免屿‹‰ä¼¸æ¨¡å¼(&S)" BEGIN - MENUITEM "免屿‹‰ä¼¸(&F)", IDM_VID_FS_FULL - MENUITEM "4:3(&4)", IDM_VID_FS_43 + MENUITEM "免屿‹‰ä¼¸(&F)", IDM_VID_FS_FULL + MENUITEM "4:3(&4)", IDM_VID_FS_43 MENUITEM "ä¿æŒæ¯”例(&S)", IDM_VID_FS_KEEPRATIO - MENUITEM "整数比例(&I)", IDM_VID_FS_INT + MENUITEM "整数比例(&I)", IDM_VID_FS_INT END POPUP "EGA/(S)VGA 设置(&G)" BEGIN - MENUITEM "VGA 显示器å色显示(&I)", IDM_VID_INVERT + MENUITEM "VGA 显示器å色显示(&I)", IDM_VID_INVERT POPUP "VGA å±å¹•类型(&T)" BEGIN - MENUITEM "RGB 彩色(&C)", IDM_VID_GRAY_RGB - MENUITEM "RGB ç°åº¦(&R)", IDM_VID_GRAY_MONO - MENUITEM "ç¥ç€è‰²å•色显示器(&A)", IDM_VID_GRAY_AMBER - MENUITEM "绿色å•色显示器(&G)", IDM_VID_GRAY_GREEN - MENUITEM "白色å•色显示器(&W)", IDM_VID_GRAY_WHITE + MENUITEM "RGB 彩色(&C)", IDM_VID_GRAY_RGB + MENUITEM "RGB ç°åº¦(&R)", IDM_VID_GRAY_MONO + MENUITEM "ç¥ç€è‰²å•色显示器(&A)", IDM_VID_GRAY_AMBER + MENUITEM "绿色å•色显示器(&G)", IDM_VID_GRAY_GREEN + MENUITEM "白色å•色显示器(&W)", IDM_VID_GRAY_WHITE END POPUP "ç°åº¦è½¬æ¢ç±»åž‹(&C)" BEGIN - MENUITEM "BT601 (NTSC/PAL)(&6)", IDM_VID_GRAYCT_601 - MENUITEM "BT709 (HDTV)(&7)", IDM_VID_GRAYCT_709 - MENUITEM "å¹³å‡(&A)", IDM_VID_GRAYCT_AVE + MENUITEM "BT601 (NTSC/PAL)(&6)", IDM_VID_GRAYCT_601 + MENUITEM "BT709 (HDTV)(&7)", IDM_VID_GRAYCT_709 + MENUITEM "å¹³å‡(&A)", IDM_VID_GRAYCT_AVE END END MENUITEM SEPARATOR - MENUITEM "CGA/PCjr/Tandy/EGA/(S)VGA 过扫æ(&G)", IDM_VID_OVERSCAN + MENUITEM "CGA/PCjr/Tandy/EGA/(S)VGA 过扫æ(&G)", IDM_VID_OVERSCAN MENUITEM "更改å•色显示对比度(&M)", IDM_VID_CGACON END - MENUITEM "介质(&M)", IDM_MEDIA + MENUITEM "介质(&M)", IDM_MEDIA POPUP "工具(&T)" BEGIN - MENUITEM "设置(&S)...", IDM_CONFIG - MENUITEM "æ›´æ–°çŠ¶æ€æ å›¾æ ‡(&U)", IDM_UPDATE_ICONS + MENUITEM "设置(&S)...", IDM_CONFIG + MENUITEM "æ›´æ–°çŠ¶æ€æ å›¾æ ‡(&U)", IDM_UPDATE_ICONS MENUITEM SEPARATOR - MENUITEM "截图(&C)\tCtrl+F11", IDM_ACTION_SCREENSHOT + MENUITEM "截图(&C)\tCtrl+F11", IDM_ACTION_SCREENSHOT MENUITEM SEPARATOR - MENUITEM "首选项(&P)...", IDM_PREFERENCES + MENUITEM "首选项(&P)...", IDM_PREFERENCES +#ifdef DISCORD MENUITEM "å¯ç”¨ Discord 集æˆ(&D)", IDM_DISCORD +#endif MENUITEM SEPARATOR - MENUITEM "音é‡å¢žç›Š(&G)...", IDM_SND_GAIN + MENUITEM "音é‡å¢žç›Š(&G)...", IDM_SND_GAIN #ifdef MTR_ENABLED MENUITEM SEPARATOR - MENUITEM "开始追踪\tCtrl+T", IDM_ACTION_BEGIN_TRACE - MENUITEM "结æŸè¿½è¸ª\tCtrl+T", IDM_ACTION_END_TRACE + MENUITEM "开始追踪\tCtrl+T", IDM_ACTION_BEGIN_TRACE + MENUITEM "结æŸè¿½è¸ª\tCtrl+T", IDM_ACTION_END_TRACE #endif END POPUP "帮助(&H)" BEGIN - MENUITEM "文档(&D)...", IDM_DOCS - MENUITEM "关于 86Box(&A)...", IDM_ABOUT + MENUITEM "文档(&D)...", IDM_DOCS + MENUITEM "关于 86Box(&A)...", IDM_ABOUT END END -StatusBarMenu MENU DISCARDABLE +StatusBarMenu MENU DISCARDABLE BEGIN MENUITEM SEPARATOR END @@ -128,17 +137,17 @@ CassetteSubmenu MENU DISCARDABLE BEGIN POPUP "" BEGIN - MENUITEM "新建镜åƒ(&N)...", IDM_CASSETTE_IMAGE_NEW + MENUITEM "新建映åƒ(&N)...", IDM_CASSETTE_IMAGE_NEW MENUITEM SEPARATOR - MENUITEM "打开已存在的镜åƒ(&E)...", IDM_CASSETTE_IMAGE_EXISTING - MENUITEM "打开已存在的镜åƒå¹¶å†™ä¿æŠ¤(&W)...", IDM_CASSETTE_IMAGE_EXISTING_WP + MENUITEM "打开已存在的映åƒ(&E)...", IDM_CASSETTE_IMAGE_EXISTING + MENUITEM "打开已存在的映åƒå¹¶å†™ä¿æŠ¤(&W)...", IDM_CASSETTE_IMAGE_EXISTING_WP MENUITEM SEPARATOR - MENUITEM "录制(&R)", IDM_CASSETTE_RECORD - MENUITEM "播放(&P)", IDM_CASSETTE_PLAY - MENUITEM "倒带至起点(&R)", IDM_CASSETTE_REWIND - MENUITEM "快进至终点(&F)", IDM_CASSETTE_FAST_FORWARD + MENUITEM "录制(&R)", IDM_CASSETTE_RECORD + MENUITEM "播放(&P)", IDM_CASSETTE_PLAY + MENUITEM "倒带至起点(&R)", IDM_CASSETTE_REWIND + MENUITEM "快进至终点(&F)", IDM_CASSETTE_FAST_FORWARD MENUITEM SEPARATOR - MENUITEM "弹出(&J)", IDM_CASSETTE_EJECT + MENUITEM "弹出(&J)", IDM_CASSETTE_EJECT END END @@ -146,9 +155,9 @@ CartridgeSubmenu MENU DISCARDABLE BEGIN POPUP "" BEGIN - MENUITEM "镜åƒ(&I)...", IDM_CARTRIDGE_IMAGE + MENUITEM "映åƒ(&I)...", IDM_CARTRIDGE_IMAGE MENUITEM SEPARATOR - MENUITEM "弹出(&J)", IDM_CARTRIDGE_EJECT + MENUITEM "弹出(&J)", IDM_CARTRIDGE_EJECT END END @@ -156,14 +165,14 @@ FloppySubmenu MENU DISCARDABLE BEGIN POPUP "" BEGIN - MENUITEM "新建镜åƒ(&N)...", IDM_FLOPPY_IMAGE_NEW + MENUITEM "新建映åƒ(&N)...", IDM_FLOPPY_IMAGE_NEW MENUITEM SEPARATOR - MENUITEM "打开已存在的镜åƒ(&E)...", IDM_FLOPPY_IMAGE_EXISTING - MENUITEM "打开已存在的镜åƒå¹¶å†™ä¿æŠ¤(&W)...", IDM_FLOPPY_IMAGE_EXISTING_WP + MENUITEM "打开已存在的映åƒ(&E)...", IDM_FLOPPY_IMAGE_EXISTING + MENUITEM "打开已存在的映åƒå¹¶å†™ä¿æŠ¤(&W)...", IDM_FLOPPY_IMAGE_EXISTING_WP MENUITEM SEPARATOR - MENUITEM "导出为 86F æ ¼å¼(&x)...", IDM_FLOPPY_EXPORT_TO_86F + MENUITEM "导出为 86F æ ¼å¼(&x)...", IDM_FLOPPY_EXPORT_TO_86F MENUITEM SEPARATOR - MENUITEM "弹出(&J)", IDM_FLOPPY_EJECT + MENUITEM "弹出(&J)", IDM_FLOPPY_EJECT END END @@ -171,12 +180,13 @@ CdromSubmenu MENU DISCARDABLE BEGIN POPUP "" BEGIN - MENUITEM "é™éŸ³(&M)", IDM_CDROM_MUTE + MENUITEM "é™éŸ³(&M)", IDM_CDROM_MUTE MENUITEM SEPARATOR - MENUITEM "空置驱动器(&M)", IDM_CDROM_EMPTY - MENUITEM "载入上一个镜åƒ(&R)", IDM_CDROM_RELOAD + MENUITEM "空置驱动器(&M)", IDM_CDROM_EMPTY + MENUITEM "载入上一个映åƒ(&R)", IDM_CDROM_RELOAD MENUITEM SEPARATOR - MENUITEM "镜åƒ(&I)", IDM_CDROM_IMAGE + MENUITEM "映åƒ(&I)...", IDM_CDROM_IMAGE + MENUITEM "文件夹(&F)...", IDM_CDROM_DIR END END @@ -184,13 +194,13 @@ ZIPSubmenu MENU DISCARDABLE BEGIN POPUP "" BEGIN - MENUITEM "新建镜åƒ(&N)...", IDM_ZIP_IMAGE_NEW + MENUITEM "新建映åƒ(&N)...", IDM_ZIP_IMAGE_NEW MENUITEM SEPARATOR - MENUITEM "打开已存在的镜åƒ(&E)...", IDM_ZIP_IMAGE_EXISTING - MENUITEM "打开已存在的镜åƒå¹¶å†™ä¿æŠ¤(&W)...", IDM_ZIP_IMAGE_EXISTING_WP + MENUITEM "打开已存在的映åƒ(&E)...", IDM_ZIP_IMAGE_EXISTING + MENUITEM "打开已存在的映åƒå¹¶å†™ä¿æŠ¤(&W)...", IDM_ZIP_IMAGE_EXISTING_WP MENUITEM SEPARATOR - MENUITEM "弹出(&J)", IDM_ZIP_EJECT - MENUITEM "载入上一个镜åƒ(&R)", IDM_ZIP_RELOAD + MENUITEM "弹出(&J)", IDM_ZIP_EJECT + MENUITEM "载入上一个映åƒ(&R)", IDM_ZIP_RELOAD END END @@ -198,13 +208,13 @@ MOSubmenu MENU DISCARDABLE BEGIN POPUP "" BEGIN - MENUITEM "新建镜åƒ(&N)...", IDM_MO_IMAGE_NEW + MENUITEM "新建映åƒ(&N)...", IDM_MO_IMAGE_NEW MENUITEM SEPARATOR - MENUITEM "打开已存在的镜åƒ(&E)...", IDM_MO_IMAGE_EXISTING - MENUITEM "打开已存在的镜åƒå¹¶å†™ä¿æŠ¤(&W)...", IDM_MO_IMAGE_EXISTING_WP + MENUITEM "打开已存在的映åƒ(&E)...", IDM_MO_IMAGE_EXISTING + MENUITEM "打开已存在的映åƒå¹¶å†™ä¿æŠ¤(&W)...", IDM_MO_IMAGE_EXISTING_WP MENUITEM SEPARATOR - MENUITEM "弹出(&J)", IDM_MO_EJECT - MENUITEM "载入上一个镜åƒ(&R)", IDM_MO_RELOAD + MENUITEM "弹出(&J)", IDM_MO_EJECT + MENUITEM "载入上一个映åƒ(&R)", IDM_MO_RELOAD END END @@ -230,134 +240,150 @@ END // Dialog // -#define STR_PREFERENCES "首选项" -#define STR_SND_GAIN "音é‡å¢žç›Š" -#define STR_NEW_FLOPPY "新建镜åƒ" -#define STR_CONFIG "设置" -#define STR_SPECIFY_DIM "指定主窗å£å¤§å°" +#define STR_PREFERENCES "首选项" +#define STR_SND_GAIN "音é‡å¢žç›Š" +#define STR_NEW_FLOPPY "新建映åƒ" +#define STR_CONFIG "设置" +#define STR_SPECIFY_DIM "指定主窗å£å¤§å°" -#define STR_OK "确定" -#define STR_CANCEL "å–æ¶ˆ" -#define STR_GLOBAL "将以上设置存储为全局默认值(&G)" -#define STR_DEFAULT "默认(&D)" -#define STR_LANGUAGE "语言:" -#define STR_ICONSET "图标集:" +#define STR_OK "确定" +#define STR_CANCEL "å–æ¶ˆ" +#define STR_GLOBAL "将以上设置存储为全局默认值(&G)" +#define STR_DEFAULT "默认(&D)" +#define STR_LANGUAGE "语言:" +#define STR_ICONSET "图标集:" -#define STR_GAIN "增益" +#define STR_GAIN "增益" -#define STR_FILE_NAME "文件å:" -#define STR_DISK_SIZE "ç£ç›˜å¤§å°:" -#define STR_RPM_MODE "转速 (RPM) 模å¼:" -#define STR_PROGRESS "进度:" +#define STR_FILE_NAME "文件å:" +#define STR_DISK_SIZE "ç£ç›˜å¤§å°:" +#define STR_RPM_MODE "转速 (RPM) 模å¼:" +#define STR_PROGRESS "进度:" -#define STR_WIDTH "宽度:" -#define STR_HEIGHT "高度:" -#define STR_LOCK_TO_SIZE "é”定此大å°" +#define STR_WIDTH "宽度:" +#define STR_HEIGHT "高度:" +#define STR_LOCK_TO_SIZE "é”定此大å°" -#define STR_MACHINE_TYPE "机器类型:" -#define STR_MACHINE "机型:" -#define STR_CONFIGURE "é…ç½®" -#define STR_CPU_TYPE "CPU 类型:" -#define STR_CPU_SPEED "速度:" -#define STR_FPU "浮点处ç†å™¨ (FPU):" -#define STR_WAIT_STATES "ç­‰å¾…çŠ¶æ€ (WS):" -#define STR_MB "MB" -#define STR_MEMORY "内存:" -#define STR_TIME_SYNC "æ—¶é—´åŒæ­¥" -#define STR_DISABLED "ç¦ç”¨" -#define STR_ENABLED_LOCAL "å¯ç”¨ (本地时间)" -#define STR_ENABLED_UTC "å¯ç”¨ (UTC)" -#define STR_DYNAREC "动æ€é‡ç¼–译器" +#define STR_MACHINE_TYPE "机器类型:" +#define STR_MACHINE "机型:" +#define STR_CONFIGURE "é…ç½®" +#define STR_CPU_TYPE "CPU 类型:" +#define STR_CPU_SPEED "速度:" +#define STR_FPU "浮点处ç†å™¨ (FPU):" +#define STR_WAIT_STATES "ç­‰å¾…çŠ¶æ€ (WS):" +#define STR_MB "MB" +#define STR_MEMORY "内存:" +#define STR_TIME_SYNC "æ—¶é—´åŒæ­¥" +#define STR_DISABLED "ç¦ç”¨" +#define STR_ENABLED_LOCAL "å¯ç”¨ (本地时间)" +#define STR_ENABLED_UTC "å¯ç”¨ (å调世界时)" +#define STR_DYNAREC "动æ€é‡ç¼–译器" +#define STR_SOFTFLOAT "软浮点 FPU" -#define STR_VIDEO "显å¡:" -#define STR_VOODOO "Voodoo Graphics" +#define STR_VIDEO "显å¡:" +#define STR_VIDEO_2 "æ˜¾å¡ 2:" +#define STR_VOODOO "Voodoo 显å¡" +#define STR_IBM8514 "IBM 8514/a 显å¡" +#define STR_XGA "XGA 显å¡" -#define STR_MOUSE "é¼ æ ‡:" -#define STR_JOYSTICK "æ“纵æ†:" -#define STR_JOY1 "æ“çºµæ† 1..." -#define STR_JOY2 "æ“çºµæ† 2..." -#define STR_JOY3 "æ“çºµæ† 3..." -#define STR_JOY4 "æ“çºµæ† 4..." +#define STR_MOUSE "é¼ æ ‡:" +#define STR_JOYSTICK "æ“纵æ†:" +#define STR_JOY1 "æ“çºµæ† 1..." +#define STR_JOY2 "æ“çºµæ† 2..." +#define STR_JOY3 "æ“çºµæ† 3..." +#define STR_JOY4 "æ“çºµæ† 4..." -#define STR_SOUND "声å¡:" -#define STR_MIDI_OUT "MIDI 输出设备:" -#define STR_MIDI_IN "MIDI 输入设备:" -#define STR_MPU401 "独立 MPU-401" -#define STR_SSI "Innovation SSI-2001" -#define STR_CMS "CMS / Game Blaster" -#define STR_GUS "Gravis Ultrasound" -#define STR_FLOAT "使用å•精度浮点 (FLOAT32)" +#define STR_SOUND1 "å£°å¡ 1:" +#define STR_SOUND2 "å£°å¡ 2:" +#define STR_SOUND3 "å£°å¡ 3:" +#define STR_SOUND4 "å£°å¡ 4:" +#define STR_MIDI_OUT "MIDI 输出设备:" +#define STR_MIDI_IN "MIDI 输入设备:" +#define STR_MPU401 "独立 MPU-401" +#define STR_FLOAT "使用å•精度浮点 (FLOAT32)" +#define STR_FM_DRIVER "è°ƒé¢‘åˆæˆå™¨é©±åЍ噍" +#define STR_FM_DRV_NUKED "Nuked (更准确)" +#define STR_FM_DRV_YMFM "YMFM (æ›´å¿«)" -#define STR_NET_TYPE "网络类型:" -#define STR_PCAP "PCap 设备:" -#define STR_NET "网络适é…器:" +#define STR_NET_TYPE "网络类型:" +#define STR_PCAP "PCap 设备:" +#define STR_NET "网络适é…器:" +#define STR_NET1 "ç½‘å¡ 1:" +#define STR_NET2 "ç½‘å¡ 2:" +#define STR_NET3 "ç½‘å¡ 3:" +#define STR_NET4 "ç½‘å¡ 4:" -#define STR_COM1 "COM1 设备:" -#define STR_COM2 "COM2 设备:" -#define STR_COM3 "COM3 设备:" -#define STR_COM4 "COM4 设备:" -#define STR_LPT1 "LPT1 设备:" -#define STR_LPT2 "LPT2 设备:" -#define STR_LPT3 "LPT3 设备:" -#define STR_LPT4 "LPT4 设备:" -#define STR_SERIAL1 "ä¸²å£ 1" -#define STR_SERIAL2 "ä¸²å£ 2" -#define STR_SERIAL3 "ä¸²å£ 3" -#define STR_SERIAL4 "ä¸²å£ 4" -#define STR_PARALLEL1 "å¹¶å£ 1" -#define STR_PARALLEL2 "å¹¶å£ 2" -#define STR_PARALLEL3 "å¹¶å£ 3" -#define STR_PARALLEL4 "å¹¶å£ 4" +#define STR_COM1 "COM1 设备:" +#define STR_COM2 "COM2 设备:" +#define STR_COM3 "COM3 设备:" +#define STR_COM4 "COM4 设备:" +#define STR_LPT1 "LPT1 设备:" +#define STR_LPT2 "LPT2 设备:" +#define STR_LPT3 "LPT3 设备:" +#define STR_LPT4 "LPT4 设备:" +#define STR_SERIAL1 "ä¸²å£ 1" +#define STR_SERIAL2 "ä¸²å£ 2" +#define STR_SERIAL3 "ä¸²å£ 3" +#define STR_SERIAL4 "ä¸²å£ 4" +#define STR_PARALLEL1 "å¹¶å£ 1" +#define STR_PARALLEL2 "å¹¶å£ 2" +#define STR_PARALLEL3 "å¹¶å£ 3" +#define STR_PARALLEL4 "å¹¶å£ 4" +#define STR_SERIAL_PASS1 "串å£ç›´é€š 1" +#define STR_SERIAL_PASS2 "串å£ç›´é€š 2" +#define STR_SERIAL_PASS3 "串å£ç›´é€š 3" +#define STR_SERIAL_PASS4 "串å£ç›´é€š 4" -#define STR_HDC "硬盘控制器:" -#define STR_FDC "软盘控制器:" -#define STR_IDE_TER "第三 IDE 控制器" -#define STR_IDE_QUA "第四 IDE 控制器" -#define STR_SCSI "SCSI" -#define STR_SCSI_1 "控制器 1:" -#define STR_SCSI_2 "控制器 2:" -#define STR_SCSI_3 "控制器 3:" -#define STR_SCSI_4 "控制器 4:" -#define STR_CASSETTE "ç£å¸¦" +#define STR_HDC "硬盘控制器:" +#define STR_FDC "软盘控制器:" +#define STR_IDE_TER "第三 IDE 控制器" +#define STR_IDE_QUA "第四 IDE 控制器" +#define STR_SCSI "SCSI" +#define STR_SCSI_1 "控制器 1:" +#define STR_SCSI_2 "控制器 2:" +#define STR_SCSI_3 "控制器 3:" +#define STR_SCSI_4 "控制器 4:" +#define STR_CASSETTE "ç£å¸¦" -#define STR_HDD "硬盘:" -#define STR_NEW "新建(&N)..." -#define STR_EXISTING "已有镜åƒ(&E)..." -#define STR_REMOVE "移除(&R)" -#define STR_BUS "总线:" -#define STR_CHANNEL "通é“:" -#define STR_ID "ID:" +#define STR_HDD "硬盘:" +#define STR_NEW "新建(&N)..." +#define STR_EXISTING "已有映åƒ(&E)..." +#define STR_REMOVE "移除(&R)" +#define STR_BUS "总线:" +#define STR_CHANNEL "通é“:" +#define STR_ID "ID:" +#define STR_SPEED "速度:" -#define STR_SPECIFY "指定(&S)..." -#define STR_SECTORS "扇区(S):" -#define STR_HEADS "ç£å¤´(H):" -#define STR_CYLS "柱é¢(C):" -#define STR_SIZE_MB "å¤§å° (MB):" -#define STR_TYPE "类型:" -#define STR_IMG_FORMAT "é•œåƒæ ¼å¼:" -#define STR_BLOCK_SIZE "å—大å°:" +#define STR_SPECIFY "指定(&S)..." +#define STR_SECTORS "扇区(S):" +#define STR_HEADS "ç£å¤´(H):" +#define STR_CYLS "柱é¢(C):" +#define STR_SIZE_MB "å¤§å° (MB):" +#define STR_TYPE "类型:" +#define STR_IMG_FORMAT "æ˜ åƒæ ¼å¼:" +#define STR_BLOCK_SIZE "å—大å°:" -#define STR_FLOPPY_DRIVES "软盘驱动器:" -#define STR_TURBO "加速时åº" -#define STR_CHECKBPB "检查 BPB" -#define STR_CDROM_DRIVES "光盘驱动器:" -#define STR_CD_SPEED "速度:" +#define STR_FLOPPY_DRIVES "软盘驱动器:" +#define STR_TURBO "加速时åº" +#define STR_CHECKBPB "检查 BPB" +#define STR_CDROM_DRIVES "光盘驱动器:" +#define STR_CD_SPEED "速度:" -#define STR_MO_DRIVES "ç£å…‰ç›˜é©±åЍ噍:" -#define STR_ZIP_DRIVES "ZIP 驱动器:" -#define STR_250 "ZIP 250" +#define STR_MO_DRIVES "ç£å…‰ç›˜é©±åЍ噍:" +#define STR_ZIP_DRIVES "ZIP 驱动器:" +#define STR_250 "ZIP 250" -#define STR_ISARTC "ISA 实时时钟:" -#define STR_ISAMEM "ISA 内存扩充" -#define STR_ISAMEM_1 "æ‰©å±•å¡ 1:" -#define STR_ISAMEM_2 "æ‰©å±•å¡ 2:" -#define STR_ISAMEM_3 "æ‰©å±•å¡ 3:" -#define STR_ISAMEM_4 "æ‰©å±•å¡ 4:" -#define STR_BUGGER "ISABugger 设备" -#define STR_POSTCARD "自检 (POST) å¡" +#define STR_ISARTC "ISA 实时时钟:" +#define STR_ISAMEM "ISA 内存扩充" +#define STR_ISAMEM_1 "æ‰©å±•å¡ 1:" +#define STR_ISAMEM_2 "æ‰©å±•å¡ 2:" +#define STR_ISAMEM_3 "æ‰©å±•å¡ 3:" +#define STR_ISAMEM_4 "æ‰©å±•å¡ 4:" +#define STR_BUGGER "ISABugger 设备" +#define STR_POSTCARD "自检 (POST) å¡" -#define FONT_SIZE 9 -#define FONT_NAME "Microsoft YaHei" +#define FONT_SIZE 9 +#define FONT_NAME "Microsoft YaHei" #include "dialogs.rc" @@ -366,194 +392,188 @@ END // String Table // -STRINGTABLE DISCARDABLE +STRINGTABLE DISCARDABLE BEGIN - 2048 "86Box" - IDS_2049 "错误" - IDS_2050 "致命错误" - IDS_2051 " - 已暂åœ" - IDS_2052 "按下 Ctrl+Alt+PgDn è¿”å›žåˆ°çª—å£æ¨¡å¼ã€‚" - IDS_2053 "速度" - IDS_2054 "ZIP %03i %i (%s): %ls" - IDS_2055 "ZIP é•œåƒ (*.IM?;*.ZDI)\0*.IM?;*.ZDI\0" - IDS_2056 "86Box 找ä¸åˆ°ä»»ä½•å¯ç”¨çš„ ROM 镜åƒã€‚\n\n请下载ROM 包并将其解压到 ""roms"" 文件夹。" - IDS_2057 "(空)" - IDS_2058 "ZIP é•œåƒ (*.IM?;*.ZDI)\0*.IM?;*.ZDI\0所有文件 (*.*)\0*.*\0" - IDS_2059 "加速" - IDS_2060 "å¼€" - IDS_2061 "å…³" - IDS_2062 "æ‰€æœ‰é•œåƒ (*.86F;*.DSK;*.FLP;*.IM?;*.*FD?)\0*.86F;*.DSK;*.FLP;*.IM?;*.*FD?\0åŸºæœ¬æ‰‡åŒºé•œåƒ (*.DSK;*.FLP;*.IM?;*.*FD?)\0*.DSK;*.FLP;*.IM?;*.IMG;*.*FD?\0表é¢é•œåƒ (*.86F)\0*.86F\0" - IDS_2063 "由于 roms/machines 文件夹中缺少åˆé€‚çš„ ROM,机型 ""%hs"" ä¸å¯ç”¨ã€‚将切æ¢åˆ°å…¶ä»–å¯ç”¨æœºåž‹ã€‚" + 2048 "86Box" + IDS_2049 "错误" + IDS_2050 "致命错误" + IDS_2051 " - 已暂åœ" + IDS_2052 "按下 Ctrl+Alt+PgDn è¿”å›žåˆ°çª—å£æ¨¡å¼ã€‚" + IDS_2053 "速度" + IDS_2054 "ZIP %03i %i (%s): %ls" + IDS_2055 "ZIP æ˜ åƒ (*.IM?;*.ZDI)\0*.IM?;*.ZDI\0" + IDS_2056 "86Box 找ä¸åˆ°ä»»ä½•å¯ç”¨çš„ ROM 映åƒã€‚\n\n请下载ROM 包并将其解压到 ""roms"" 文件夹中。" + IDS_2057 "(空)" + IDS_2058 "ZIP æ˜ åƒ (*.IM?;*.ZDI)\0*.IM?;*.ZDI\0所有文件 (*.*)\0*.*\0" + IDS_2059 "加速" + IDS_2060 "å¼€" + IDS_2061 "å…³" + IDS_2062 "æ‰€æœ‰æ˜ åƒ (*.86F;*.DSK;*.FLP;*.IM?;*.*FD?)\0*.86F;*.DSK;*.FLP;*.IM?;*.*FD?\0åŸºæœ¬æ‰‡åŒºæ˜ åƒ (*.DSK;*.FLP;*.IM?;*.*FD?)\0*.DSK;*.FLP;*.IM?;*.IMG;*.*FD?\0è¡¨é¢æ˜ åƒ (*.86F)\0*.86F\0" + IDS_2063 "由于 roms/machines 文件夹中缺少åˆé€‚çš„ ROM,机型 ""%hs"" ä¸å¯ç”¨ã€‚将切æ¢åˆ°å…¶ä»–å¯ç”¨æœºåž‹ã€‚" END -STRINGTABLE DISCARDABLE +STRINGTABLE DISCARDABLE BEGIN - IDS_2064 "由于 roms/video 文件夹中缺少åˆé€‚çš„ ROMï¼Œæ˜¾å¡ ""%hs"" ä¸å¯ç”¨ã€‚将切æ¢åˆ°å…¶ä»–å¯ç”¨æ˜¾å¡ã€‚" - IDS_2065 "机型" - IDS_2066 "显示" - IDS_2067 "输入设备" - IDS_2068 "声音" - IDS_2069 "网络" - IDS_2070 "ç«¯å£ (COM å’Œ LPT)" - IDS_2071 "存储控制器" - IDS_2072 "硬盘" - IDS_2073 "软盘/光盘驱动器" - IDS_2074 "å…¶ä»–å¯ç§»åŠ¨è®¾å¤‡" - IDS_2075 "其他外围设备" - IDS_2076 "表é¢é•œåƒ (*.86F)\0*.86F\0" - IDS_2077 "å•å‡»çª—å£æ•æ‰é¼ æ ‡" - IDS_2078 "按下 F8+F12 释放鼠标" - IDS_2079 "按下 F8+F12 或鼠标中键释放鼠标" + IDS_2064 "由于 roms/video 文件夹中缺少åˆé€‚çš„ ROMï¼Œæ˜¾å¡ ""%hs"" ä¸å¯ç”¨ã€‚将切æ¢åˆ°å…¶ä»–å¯ç”¨æ˜¾å¡ã€‚" + IDS_2065 "机型" + IDS_2066 "显示" + IDS_2067 "输入设备" + IDS_2068 "声音" + IDS_2069 "网络" + IDS_2070 "ç«¯å£ (COM å’Œ LPT)" + IDS_2071 "存储控制器" + IDS_2072 "硬盘" + IDS_2073 "软盘/光盘驱动器" + IDS_2074 "å…¶ä»–å¯ç§»åŠ¨è®¾å¤‡" + IDS_2075 "其他外围设备" + IDS_2076 "è¡¨é¢æ˜ åƒ (*.86F)\0*.86F\0" + IDS_2077 "å•å‡»çª—å£æ•æ‰é¼ æ ‡" + IDS_2078 "按下 F8+F12 释放鼠标" + IDS_2079 "按下 F8+F12 或鼠标中键释放鼠标" END -STRINGTABLE DISCARDABLE +STRINGTABLE DISCARDABLE BEGIN - IDS_2080 "无法åˆå§‹åŒ– FluidSynth" - IDS_2081 "总线" - IDS_2082 "文件" - IDS_2083 "C" - IDS_2084 "H" - IDS_2085 "S" - IDS_2086 "MB" - IDS_2087 "检查 BPB" - IDS_2088 "KB" - IDS_2089 "无法åˆå§‹åŒ–视频渲染器。" - IDS_2090 "默认" - IDS_2091 "%i ç­‰å¾…çŠ¶æ€ (WS)" - IDS_2092 "类型" - IDS_2093 "设置 PCap 失败" - IDS_2094 "未找到 PCap 设备" - IDS_2095 "无效 PCap 设备" - IDS_2096 "标准 2 é”®æ“纵æ†" - IDS_2097 "标准 4 é”®æ“纵æ†" - IDS_2098 "标准 6 é”®æ“纵æ†" - IDS_2099 "标准 8 é”®æ“纵æ†" - IDS_2100 "CH Flightstick Pro" - IDS_2101 "Microsoft SideWinder Pad" - IDS_2102 "Thrustmaster Flight Control System" - IDS_2103 "æ— " - IDS_2104 "无法加载键盘加速器。" - IDS_2105 "无法注册原始输入。" - IDS_2106 "%u" - IDS_2107 "%u MB (CHS: %i, %i, %i)" - IDS_2108 "软盘 %i (%s): %ls" - IDS_2109 "æ‰€æœ‰é•œåƒ (*.0??;*.1??;*.??0;*.86F;*.BIN;*.CQ?;*.D??;*.FLP;*.HDM;*.IM?;*.JSON;*.TD0;*.*FD?;*.MFM;*.XDF)\0*.0??;*.1??;*.??0;*.86F;*.BIN;*.CQ?;*.D??;*.FLP;*.HDM;*.IM?;*.JSON;*.TD0;*.*FD?;*.MFM;*.XDF\0é«˜çº§æ‰‡åŒºé•œåƒ (*.IMD;*.JSON;*.TD0)\0*.IMD;*.JSON;*.TD0\0åŸºæœ¬æ‰‡åŒºé•œåƒ (*.0??;*.1??;*.??0;*.BIN;*.CQ?;*.D??;*.FLP;*.HDM;*.IM?;*.XDF;*.*FD?)\0*.0??;*.1??;*.??0;*.BIN;*.CQ?;*.D??;*.FLP;*.HDM;*.IM?;*.XDF;*.*FD?\0Flux é•œåƒ (*.FDI)\0*.FDI\0表é¢é•œåƒ (*.86F;*.MFM)\0*.86F;*.MFM\0所有文件 (*.*)\0*.*\0" - IDS_2110 "无法åˆå§‹åŒ– FreeType" - IDS_2111 "无法åˆå§‹åŒ– SDLï¼Œéœ€è¦ SDL2.dll" - IDS_2112 "确定è¦ç¡¬é‡ç½®æ¨¡æ‹Ÿå™¨å—?" - IDS_2113 "确定è¦é€€å‡º 86Box å—?" - IDS_2114 "无法åˆå§‹åŒ– Ghostscript" - IDS_2115 "ç£å…‰ç›˜ %i (%ls): %ls" - IDS_2116 "ç£å…‰ç›˜é•œåƒ (*.IM?;*.MDI)\0*.IM?;*.MDI\0所有文件 (*.*)\0*.*\0" - IDS_2117 "欢迎使用 86Boxï¼" - IDS_2118 "内部控制器" - IDS_2119 "退出" - IDS_2120 "找ä¸åˆ° ROM" - IDS_2121 "è¦ä¿å­˜è®¾ç½®å—?" - IDS_2122 "æ­¤æ“作将硬é‡ç½®æ¨¡æ‹Ÿå™¨ã€‚" - IDS_2123 "ä¿å­˜" - IDS_2124 "关于 86Box" - IDS_2125 "86Box v" EMU_VERSION + IDS_2081 "总线" + IDS_2082 "文件" + IDS_2083 "C" + IDS_2084 "H" + IDS_2085 "S" + IDS_2086 "MB" + IDS_2087 "速度" + IDS_2088 "检查 BPB" + IDS_2089 "KB" + IDS_2090 "无法åˆå§‹åŒ–视频渲染器。" + IDS_2091 "默认" + IDS_2092 "%i ç­‰å¾…çŠ¶æ€ (WS)" + IDS_2093 "类型" + IDS_2094 "设置 PCap 失败" + IDS_2095 "未找到 PCap 设备" + IDS_2096 "无效 PCap 设备" + IDS_2097 "标准 2 é”®æ“纵æ†" + IDS_2098 "标准 4 é”®æ“纵æ†" + IDS_2099 "标准 6 é”®æ“纵æ†" + IDS_2100 "标准 8 é”®æ“纵æ†" + IDS_2101 "CH Flightstick Pro" + IDS_2102 "Microsoft SideWinder Pad" + IDS_2103 "Thrustmaster Flight Control System" + IDS_2104 "æ— " + IDS_2105 "无法加载键盘加速器。" + IDS_2106 "无法注册原始输入。" + IDS_2107 "%u" + IDS_2108 "%u MB (CHS: %i, %i, %i)" + IDS_2109 "软盘 %i (%s): %ls" + IDS_2110 "æ‰€æœ‰æ˜ åƒ (*.0??;*.1??;*.??0;*.86F;*.BIN;*.CQ?;*.D??;*.FLP;*.HDM;*.IM?;*.JSON;*.TD0;*.*FD?;*.MFM;*.XDF)\0*.0??;*.1??;*.??0;*.86F;*.BIN;*.CQ?;*.D??;*.FLP;*.HDM;*.IM?;*.JSON;*.TD0;*.*FD?;*.MFM;*.XDF\0é«˜çº§æ‰‡åŒºæ˜ åƒ (*.IMD;*.JSON;*.TD0)\0*.IMD;*.JSON;*.TD0\0åŸºæœ¬æ‰‡åŒºæ˜ åƒ (*.0??;*.1??;*.??0;*.BIN;*.CQ?;*.D??;*.FLP;*.HDM;*.IM?;*.XDF;*.*FD?)\0*.0??;*.1??;*.??0;*.BIN;*.CQ?;*.D??;*.FLP;*.HDM;*.IM?;*.XDF;*.*FD?\0Flux æ˜ åƒ (*.FDI)\0*.FDI\0è¡¨é¢æ˜ åƒ (*.86F;*.MFM)\0*.86F;*.MFM\0所有文件 (*.*)\0*.*\0" + IDS_2112 "无法åˆå§‹åŒ– SDLï¼Œéœ€è¦ SDL2.dll" + IDS_2113 "确定è¦ç¡¬é‡ç½®æ¨¡æ‹Ÿå™¨å—?" + IDS_2114 "确定è¦é€€å‡º 86Box å—?" + IDS_2115 "无法åˆå§‹åŒ– Ghostscript" + IDS_2116 "ç£å…‰ç›˜ %i (%ls): %ls" + IDS_2117 "ç£å…‰ç›˜æ˜ åƒ (*.IM?;*.MDI)\0*.IM?;*.MDI\0所有文件 (*.*)\0*.*\0" + IDS_2118 "欢迎使用 86Boxï¼" + IDS_2119 "内部控制器" + IDS_2120 "退出" + IDS_2121 "找ä¸åˆ° ROM" + IDS_2122 "è¦ä¿å­˜è®¾ç½®å—?" + IDS_2123 "æ­¤æ“作将硬é‡ç½®æ¨¡æ‹Ÿå™¨ã€‚" + IDS_2124 "ä¿å­˜" + IDS_2125 "关于 86Box" + IDS_2126 "86Box v" EMU_VERSION - IDS_2126 "一个旧å¼è®¡ç®—机模拟器\n\n作者: Sarah Walkerã€Miran Grcaã€Fred N. van Kempen (waltje)ã€SA1988ã€Tiseno100ã€reenigneã€leileiã€JohnElliottã€greatpsycho 等人。\n\næœ¬è½¯ä»¶ä¾æ® GNU 通用公共许å¯è¯ç¬¬äºŒç‰ˆæˆ–更新版本å‘å¸ƒã€‚è¯¦æƒ…è§ LICENSE 文件。" - IDS_2127 "确定" - IDS_2128 "硬件ä¸å¯ç”¨" + IDS_2127 "一个旧å¼è®¡ç®—机模拟器\n\n作者: Miran GrÄa (OBattler)ã€RichardG867ã€Jasmine Iwanekã€TC1995ã€coldbrewedã€Teemu Korhonen (Manaatti)ã€Joakim L. Giljeã€Adrien Moulin (elyosh)ã€Daniel Balsom (gloriouscow)ã€Cacodemon345ã€Fred N. van Kempen (waltje)ã€Tiseno100ã€reenigne 等人。\n\nWith previous core contributions from Sarah Walker, leilei, JohnElliott, greatpsycho, and others.\n\næœ¬è½¯ä»¶ä¾æ® GNU 通用公共许å¯è¯ç¬¬äºŒç‰ˆæˆ–更新版本å‘å¸ƒã€‚è¯¦æƒ…è§ LICENSE 文件。" + IDS_2128 "确定" + IDS_2129 "硬件ä¸å¯ç”¨" #ifdef _WIN32 #define LIB_NAME_PCAP "WinPcap" #else #define LIB_NAME_PCAP "libpcap" #endif - IDS_2129 "请确认 " LIB_NAME_PCAP " 已安装且使用兼容 " LIB_NAME_PCAP " 的网络连接。" - IDS_2130 "无效é…ç½®" -#ifdef _WIN32 -#define LIB_NAME_FREETYPE "freetype.dll" -#else -#define LIB_NAME_FREETYPE "libfreetype" -#endif - IDS_2131 "ESC/P æ‰“å°æœºæ¨¡æ‹Ÿéœ€è¦" LIB_NAME_FREETYPE + IDS_2130 "请确认 " LIB_NAME_PCAP " 已安装且使用兼容 " LIB_NAME_PCAP " 的网络连接。" + IDS_2131 "无效é…ç½®" #ifdef _WIN32 #define LIB_NAME_GS "gsdll32.dll" #else #define LIB_NAME_GS "libgs" #endif - IDS_2132 LIB_NAME_GS " 是将 PostScript 文件转æ¢ä¸º PDF 所需è¦çš„库。\n\n使用通用 PostScript æ‰“å°æœºæ‰“å°çš„æ–‡æ¡£å°†è¢«ä¿å­˜ä¸º PostScript (.ps) 文件。" -#ifdef _WIN32 -#define LIB_NAME_FLUIDSYNTH "libfluidsynth.dll" -#else -#define LIB_NAME_FLUIDSYNTH "libfluidsynth" -#endif - IDS_2133 "FluidSynth MIDI 输出需è¦" LIB_NAME_FLUIDSYNTH - IDS_2134 "æ­£åœ¨è¿›å…¥å…¨å±æ¨¡å¼" - IDS_2135 "ä¸è¦å†æ˜¾ç¤ºæ­¤æ¶ˆæ¯" - IDS_2136 "ä¸é€€å‡º" - IDS_2137 "é‡ç½®" - IDS_2138 "ä¸é‡ç½®" - IDS_2139 "ç£å…‰ç›˜é•œåƒ (*.IM?;*.MDI)\0*.IM?;*.MDI\0所有文件 (*.*)\0*.*\0" - IDS_2140 "å…‰ç›˜é•œåƒ (*.ISO;*.CUE)\0*.ISO;*.CUE\0所有文件 (*.*)\0*.*\0" - IDS_2141 "%hs 设备é…ç½®" - IDS_2142 "显示器处在ç¡çœ çжæ€" - IDS_2143 "OpenGL ç€è‰²å™¨ (*.GLSL)\0*.GLSL\0所有文件 (*.*)\0*.*\0" - IDS_2144 "OpenGL 选项" - IDS_2145 "正在载入一个ä¸å—支æŒçš„é…ç½®" - IDS_2146 "此模拟计算机ç¦ç”¨äº†åŸºäºŽé€‰å®šè®¡ç®—机的 CPU 类型过滤。\n\n能够选中与所选机器本ä¸å…¼å®¹çš„ CPU,但是å¯èƒ½ä¼šé‡åˆ°ä¸Žæœºå™¨ BIOS 或其他软件ä¸å…¼å®¹çš„问题。\n\nå¯ç”¨æ­¤è®¾ç½®ä¸å—官方支æŒï¼Œå¹¶ä¸”æäº¤çš„任何错误报告å¯èƒ½ä¼šè§†ä¸ºæ— æ•ˆè€Œå…³é—­ã€‚" - IDS_2147 "ç»§ç»­" - IDS_2148 "ç£å¸¦: %s" - IDS_2149 "ç£å¸¦é•œåƒ (*.PCM;*.RAW;*.WAV;*.CAS)\0*.PCM;*.RAW;*.WAV;*.CAS\0所有文件 (*.*)\0*.*\0" - IDS_2150 "å¡å¸¦ %i: %ls" - IDS_2151 "å¡å¸¦é•œåƒ (*.A;*.B;*.JRC)\0*.A;*.B;*.JRC\0所有文件 (*.*)\0*.*\0" - IDS_2152 "åˆå§‹åŒ–渲染器时出错" - IDS_2153 "无法åˆå§‹åŒ– OpenGL (3.0 核心) 渲染器。请使用其他渲染器。" - IDS_2154 "æ¢å¤æ‰§è¡Œ" - IDS_2155 "æš‚åœæ‰§è¡Œ" - IDS_2156 "按下 Ctrl+Alt+Del" - IDS_2157 "按下 Ctrl+Alt+Esc" - IDS_2158 "硬é‡ç½®" - IDS_2159 "ACPI 关机" - IDS_2160 "设置" + IDS_2133 LIB_NAME_GS " 是将 PostScript 文件转æ¢ä¸º PDF 所需è¦çš„库。\n\n使用通用 PostScript æ‰“å°æœºæ‰“å°çš„æ–‡æ¡£å°†è¢«ä¿å­˜ä¸º PostScript (.ps) 文件。" + IDS_2135 "æ­£åœ¨è¿›å…¥å…¨å±æ¨¡å¼" + IDS_2136 "ä¸å†æ˜¾ç¤ºæ­¤æ¶ˆæ¯" + IDS_2137 "ä¸é€€å‡º" + IDS_2138 "é‡ç½®" + IDS_2139 "ä¸é‡ç½®" + IDS_2140 "ç£å…‰ç›˜æ˜ åƒ (*.IM?;*.MDI)\0*.IM?;*.MDI\0所有文件 (*.*)\0*.*\0" + IDS_2141 "å…‰ç›˜æ˜ åƒ (*.ISO;*.CUE)\0*.ISO;*.CUE\0所有文件 (*.*)\0*.*\0" + IDS_2142 "%hs 设备é…ç½®" + IDS_2143 "显示器处在ç¡çœ çжæ€" + IDS_2144 "OpenGL ç€è‰²å™¨ (*.GLSL)\0*.GLSL\0所有文件 (*.*)\0*.*\0" + IDS_2145 "OpenGL 选项" + IDS_2146 "正在载入一个ä¸å—支æŒçš„é…ç½®" + IDS_2147 "此模拟计算机ç¦ç”¨äº†åŸºäºŽé€‰å®šè®¡ç®—机的 CPU 类型过滤。\n\n能够选中与所选机器本ä¸å…¼å®¹çš„ CPU,但是å¯èƒ½ä¼šé‡åˆ°ä¸Žæœºå™¨ BIOS 或其他软件ä¸å…¼å®¹çš„问题。\n\nå¯ç”¨æ­¤è®¾ç½®ä¸å—官方支æŒï¼Œå¹¶ä¸”æäº¤çš„任何错误报告å¯èƒ½ä¼šè§†ä¸ºæ— æ•ˆè€Œå…³é—­ã€‚" + IDS_2148 "ç»§ç»­" + IDS_2149 "ç£å¸¦: %s" + IDS_2150 "ç£å¸¦æ˜ åƒ (*.PCM;*.RAW;*.WAV;*.CAS)\0*.PCM;*.RAW;*.WAV;*.CAS\0所有文件 (*.*)\0*.*\0" + IDS_2151 "å¡å¸¦ %i: %ls" + IDS_2152 "å¡å¸¦æ˜ åƒ (*.A;*.B;*.JRC)\0*.A;*.B;*.JRC\0所有文件 (*.*)\0*.*\0" + IDS_2153 "åˆå§‹åŒ–渲染器时出错" + IDS_2154 "无法åˆå§‹åŒ– OpenGL (3.0 核心) 渲染器。请使用其他渲染器。" + IDS_2155 "æ¢å¤æ‰§è¡Œ" + IDS_2156 "æš‚åœæ‰§è¡Œ" + IDS_2157 "按下 Ctrl+Alt+Del" + IDS_2158 "按下 Ctrl+Alt+Esc" + IDS_2159 "硬é‡ç½®" + IDS_2160 "ACPI 关机" + IDS_2161 "设置" + IDS_2162 "类型" + IDS_2163 "无动æ€é‡ç¼–译" + IDS_2164 "æ—§å¼åЍæ€é‡ç¼–译" + IDS_2165 "æ–°å¼åЍæ€é‡ç¼–译" + IDS_2166 "由于 roms/video 文件夹中缺少åˆé€‚çš„ ROMï¼Œæ˜¾å¡ #2 ""%hs"" ä¸å¯ç”¨ã€‚å°†ç¦ç”¨ç¬¬äºŒå¼ æ˜¾å¡ã€‚" + IDS_2167 "åˆå§‹åŒ–网络驱动程åºå¤±è´¥" + IDS_2168 "网络é…置将切æ¢ä¸ºç©ºé©±åŠ¨ç¨‹åº" END -STRINGTABLE DISCARDABLE +STRINGTABLE DISCARDABLE BEGIN IDS_4096 "硬盘 (%s)" - IDS_4097 "%01i:%01i" - IDS_4098 "%01i" - IDS_4099 "ä¸å­˜åœ¨ MFM/RLL 或 ESDI CD-ROM 驱动器" - IDS_4100 "自定义..." - IDS_4101 "自定义 (大容é‡)..." - IDS_4102 "添加新硬盘" - IDS_4103 "添加已存在的硬盘" - IDS_4104 "HDI ç£ç›˜é•œåƒä¸èƒ½è¶…过 4 GB。" - IDS_4105 "ç£ç›˜é•œåƒä¸èƒ½è¶…过 127 GB。" - IDS_4106 "ç¡¬ç›˜é•œåƒ (*.HD?;*.IM?;*.VHD)\0*.HD?;*.IM?;*.VHD\0所有文件 (*.*)\0*.*\0" - IDS_4107 "æ— æ³•è¯»å–æ–‡ä»¶" - IDS_4108 "无法写入文件" - IDS_4109 "䏿”¯æŒéž 512 字节扇区大å°çš„ HDI 或 HDX 镜åƒã€‚" - IDS_4110 "å°šæœªæ”¯æŒ USB" - IDS_4111 "ç£ç›˜é•œåƒæ–‡ä»¶å·²å­˜åœ¨" - IDS_4112 "请指定有效的文件å。" - IDS_4113 "已创建ç£ç›˜é•œåƒ" - IDS_4114 "请确定此文件已存在并å¯è¯»å–。" - IDS_4115 "请确定此文件ä¿å­˜åœ¨å¯å†™ç›®å½•中。" - IDS_4116 "ç£ç›˜é•œåƒå¤ªå¤§" - IDS_4117 "请记得为新创建的镜åƒåˆ†åŒºå¹¶æ ¼å¼åŒ–。" - IDS_4118 "选定的文件将被覆盖。确定继续使用此文件å—?" - IDS_4119 "䏿”¯æŒçš„ç£ç›˜é•œåƒ" - IDS_4120 "覆盖" - IDS_4121 "ä¸è¦†ç›–" - IDS_4122 "åŽŸå§‹é•œåƒ (.img)" - IDS_4123 "HDI é•œåƒ (.hdi)" - IDS_4124 "HDX é•œåƒ (.hdx)" - IDS_4125 "å›ºå®šå¤§å° VHD (.vhd)" - IDS_4126 "动æ€å¤§å° VHD (.vhd)" - IDS_4127 "差分 VHD (.vhd)" - IDS_4128 "å¤§å— (2 MB)" - IDS_4129 "å°å— (512 KB)" - IDS_4130 "VHD 文件 (*.VHD)\0*.VHD\0所有文件 (*.*)\0*.*\0" - IDS_4131 "选择父 VHD 文件" - IDS_4132 "父映åƒå¯èƒ½åœ¨åˆ›å»ºå·®å¼‚镜åƒåŽè¢«ä¿®æ”¹ã€‚\n\nå¦‚æžœé•œåƒæ–‡ä»¶è¢«ç§»åŠ¨æˆ–å¤åˆ¶ï¼Œæˆ–创建此ç£ç›˜çš„程åºä¸­å­˜åœ¨é”™è¯¯ï¼Œä¹Ÿå¯èƒ½å‘ç”Ÿè¿™ç§æƒ…况。\n\n是å¦éœ€è¦ä¿®å¤æ—¶é—´æˆ³ï¼Ÿ" - IDS_4133 "父盘与å­ç›˜çš„æ—¶é—´æˆ³ä¸åŒ¹é…" - IDS_4134 "æ— æ³•ä¿®å¤ VHD 时间戳。" - IDS_4135 "%01i:%02i" + IDS_4097 "%01i:%01i" + IDS_4098 "%01i" + IDS_4099 "ä¸å­˜åœ¨ MFM/RLL 或 ESDI CD-ROM 驱动器" + IDS_4100 "自定义..." + IDS_4101 "自定义 (大容é‡)..." + IDS_4102 "添加新硬盘" + IDS_4103 "添加已存在的硬盘" + IDS_4104 "HDI ç£ç›˜æ˜ åƒä¸èƒ½è¶…过 4 GB。" + IDS_4105 "ç£ç›˜æ˜ åƒä¸èƒ½è¶…过 127 GB。" + IDS_4106 "ç¡¬ç›˜æ˜ åƒ (*.HD?;*.IM?;*.VHD)\0*.HD?;*.IM?;*.VHD\0所有文件 (*.*)\0*.*\0" + IDS_4107 "æ— æ³•è¯»å–æ–‡ä»¶" + IDS_4108 "无法写入文件" + IDS_4109 "䏿”¯æŒéž 512 字节扇区大å°çš„ HDI 或 HDX 映åƒã€‚" + IDS_4110 "å°šæœªæ”¯æŒ USB" + IDS_4111 "ç£ç›˜æ˜ åƒæ–‡ä»¶å·²å­˜åœ¨" + IDS_4112 "请指定有效的文件å。" + IDS_4113 "已创建ç£ç›˜æ˜ åƒ" + IDS_4114 "请确定此文件已存在并å¯è¯»å–。" + IDS_4115 "请确定此文件ä¿å­˜åœ¨å¯å†™ç›®å½•中。" + IDS_4116 "ç£ç›˜æ˜ åƒå¤ªå¤§" + IDS_4117 "请记得为新创建的映åƒåˆ†åŒºå¹¶æ ¼å¼åŒ–。" + IDS_4118 "选定的文件将被覆盖。确定继续使用此文件å—?" + IDS_4119 "䏿”¯æŒçš„ç£ç›˜æ˜ åƒ" + IDS_4120 "覆盖" + IDS_4121 "ä¸è¦†ç›–" + IDS_4122 "åŽŸå§‹æ˜ åƒ (.img)" + IDS_4123 "HDI æ˜ åƒ (.hdi)" + IDS_4124 "HDX æ˜ åƒ (.hdx)" + IDS_4125 "å›ºå®šå¤§å° VHD (.vhd)" + IDS_4126 "动æ€å¤§å° VHD (.vhd)" + IDS_4127 "差分 VHD (.vhd)" + IDS_4128 "å¤§å— (2 MB)" + IDS_4129 "å°å— (512 KB)" + IDS_4130 "VHD 文件 (*.VHD)\0*.VHD\0所有文件 (*.*)\0*.*\0" + IDS_4131 "选择父 VHD 文件" + IDS_4132 "父映åƒå¯èƒ½åœ¨åˆ›å»ºå·®å¼‚映åƒåŽè¢«ä¿®æ”¹ã€‚\n\nå¦‚æžœæ˜ åƒæ–‡ä»¶è¢«ç§»åŠ¨æˆ–å¤åˆ¶ï¼Œæˆ–创建此ç£ç›˜çš„程åºä¸­å­˜åœ¨é”™è¯¯ï¼Œä¹Ÿå¯èƒ½å‘ç”Ÿè¿™ç§æƒ…况。\n\n是å¦éœ€è¦ä¿®å¤æ—¶é—´æˆ³ï¼Ÿ" + IDS_4133 "父盘与å­ç›˜çš„æ—¶é—´æˆ³ä¸åŒ¹é…" + IDS_4134 "æ— æ³•ä¿®å¤ VHD 时间戳。" + IDS_4135 "%01i:%02i" IDS_4352 "MFM/RLL" IDS_4353 "XTA" @@ -562,56 +582,56 @@ BEGIN IDS_4356 "ATAPI" IDS_4357 "SCSI" - IDS_4608 "MFM/RLL (%01i:%01i)" - IDS_4609 "XTA (%01i:%01i)" - IDS_4610 "ESDI (%01i:%01i)" - IDS_4611 "IDE (%01i:%01i)" - IDS_4612 "ATAPI (%01i:%01i)" - IDS_4613 "SCSI (%01i:%02i)" + IDS_4608 "MFM/RLL (%01i:%01i)" + IDS_4609 "XTA (%01i:%01i)" + IDS_4610 "ESDI (%01i:%01i)" + IDS_4611 "IDE (%01i:%01i)" + IDS_4612 "ATAPI (%01i:%01i)" + IDS_4613 "SCSI (%01i:%02i)" - IDS_5120 "光盘 %i (%s): %s" + IDS_5120 "光盘 %i (%s): %s" - IDS_5376 "ç¦ç”¨" - IDS_5381 "ATAPI" + IDS_5376 "ç¦ç”¨" + IDS_5381 "ATAPI" IDS_5382 "SCSI" - IDS_5632 "ç¦ç”¨" - IDS_5637 "ATAPI (%01i:%01i)" + IDS_5632 "ç¦ç”¨" + IDS_5637 "ATAPI (%01i:%01i)" IDS_5638 "SCSI (%01i:%02i)" - IDS_5888 "160 kB" - IDS_5889 "180 kB" - IDS_5890 "320 kB" - IDS_5891 "360 kB" - IDS_5892 "640 kB" - IDS_5893 "720 kB" - IDS_5894 "1.2 MB" - IDS_5895 "1.25 MB" - IDS_5896 "1.44 MB" - IDS_5897 "DMF (1024 ç°‡)" - IDS_5898 "DMF (2048 ç°‡)" - IDS_5899 "2.88 MB" - IDS_5900 "ZIP 100" - IDS_5901 "ZIP 250" - IDS_5902 "3.5 英寸 128 MB (ISO 10090)" - IDS_5903 "3.5 英寸 230 MB (ISO 13963)" - IDS_5904 "3.5 英寸 540 MB (ISO 15498)" - IDS_5905 "3.5 英寸 640 MB (ISO 15498)" - IDS_5906 "3.5 英寸 1.3 GB (GigaMO)" - IDS_5907 "3.5 英寸 2.3 GB (GigaMO 2)" - IDS_5908 "5.25 英寸 600 MB" - IDS_5909 "5.25 英寸 650 MB" - IDS_5910 "5.25 英寸 1 GB" - IDS_5911 "5.25 英寸 1.3 GB" + IDS_5888 "160 kB" + IDS_5889 "180 kB" + IDS_5890 "320 kB" + IDS_5891 "360 kB" + IDS_5892 "640 kB" + IDS_5893 "720 kB" + IDS_5894 "1.2 MB" + IDS_5895 "1.25 MB" + IDS_5896 "1.44 MB" + IDS_5897 "DMF (1024 ç°‡)" + IDS_5898 "DMF (2048 ç°‡)" + IDS_5899 "2.88 MB" + IDS_5900 "ZIP 100" + IDS_5901 "ZIP 250" + IDS_5902 "3.5 英寸 128 MB (ISO 10090)" + IDS_5903 "3.5 英寸 230 MB (ISO 13963)" + IDS_5904 "3.5 英寸 540 MB (ISO 15498)" + IDS_5905 "3.5 英寸 640 MB (ISO 15498)" + IDS_5906 "3.5 英寸 1.3 GB (GigaMO)" + IDS_5907 "3.5 英寸 2.3 GB (GigaMO 2)" + IDS_5908 "5.25 英寸 600 MB" + IDS_5909 "5.25 英寸 650 MB" + IDS_5910 "5.25 英寸 1 GB" + IDS_5911 "5.25 英寸 1.3 GB" - IDS_6144 "标准转速 (RPM)" - IDS_6145 "低于标准转速的 1%" - IDS_6146 "低于标准转速的 1.5%" - IDS_6147 "低于标准转速的 2%" + IDS_6144 "标准转速 (RPM)" + IDS_6145 "低于标准转速的 1%" + IDS_6146 "低于标准转速的 1.5%" + IDS_6147 "低于标准转速的 2%" - IDS_7168 "(系统默认)" + IDS_7168 "(系统默认)" END -#define IDS_LANG_ENUS IDS_7168 +#define IDS_LANG_ENUS IDS_7168 // Simplified Chinese resources ///////////////////////////////////////////////////////////////////////////// diff --git a/src/win/languages/zh-TW.rc b/src/win/languages/zh-TW.rc new file mode 100644 index 000000000..039993e5d --- /dev/null +++ b/src/win/languages/zh-TW.rc @@ -0,0 +1,637 @@ +//////////////////////////////////////////////////////////////////////////// +// Traditional Chinese resources + +#ifdef _WIN32 +LANGUAGE LANG_CHINESE, SUBLANG_CHINESE_TRADITIONAL +#pragma code_page(65001) +#endif //_WIN32 + +#define AUTHORS + +///////////////////////////////////////////////////////////////////////////// +// +// Menu +// + +MainMenu MENU DISCARDABLE +BEGIN + POPUP "動作(&A)" + BEGIN + MENUITEM "éµç›¤éœ€è¦æ•æ‰(&K)", IDM_ACTION_KBD_REQ_CAPTURE + MENUITEM "å°‡å³ CTRL 鵿˜ å°„為左 ALT éµ(&R)", IDM_ACTION_RCTRL_IS_LALT + MENUITEM SEPARATOR + MENUITEM "硬é‡è¨­(&H)...", IDM_ACTION_HRESET + MENUITEM "Ctrl+Alt+Del(&C)\tCtrl+F12", IDM_ACTION_RESET_CAD + MENUITEM SEPARATOR + MENUITEM "Ctrl+Alt+Esc(&E)", IDM_ACTION_CTRL_ALT_ESC + MENUITEM SEPARATOR + MENUITEM "æš«åœ(&P)", IDM_ACTION_PAUSE + MENUITEM SEPARATOR + MENUITEM "退出(&X)...", IDM_ACTION_EXIT + END + POPUP "檢視(&V)" + BEGIN + MENUITEM "éš±è—狀態列(&H)", IDM_VID_HIDE_STATUS_BAR + MENUITEM "éš±è—工具列(&T)", IDM_VID_HIDE_TOOLBAR + MENUITEM SEPARATOR + MENUITEM "Show non-primary monitors(&S)", IDM_VID_MONITORS + MENUITEM "視窗大å°å¯èª¿(&R)", IDM_VID_RESIZE + MENUITEM "記ä½è¦–窗大å°å’Œä½ç½®(&E)", IDM_VID_REMEMBER + MENUITEM SEPARATOR + POPUP "渲染器(&N)" + BEGIN + MENUITEM "SDL (軟體)(&S)", IDM_VID_SDL_SW + MENUITEM "SDL (硬體)(&H)", IDM_VID_SDL_HW + MENUITEM "SDL (OpenGL)(&O)", IDM_VID_SDL_OPENGL + MENUITEM "OpenGL (3.0 核心)(&G)", IDM_VID_OPENGL_CORE +#ifdef USE_VNC + MENUITEM "VNC(&V)", IDM_VID_VNC +#endif + END + MENUITEM SEPARATOR + MENUITEM "指定視窗大å°...", IDM_VID_SPECIFY_DIM + MENUITEM "強制 4:3 顯示比例(&O)", IDM_VID_FORCE43 + POPUP "視窗縮放係數(&W)" + BEGIN + MENUITEM "0.5x(&0)", IDM_VID_SCALE_1X + MENUITEM "1x(&1)", IDM_VID_SCALE_2X + MENUITEM "1.5x(&5)", IDM_VID_SCALE_3X + MENUITEM "2x(&2)", IDM_VID_SCALE_4X + MENUITEM "&3x", IDM_VID_SCALE_5X + MENUITEM "&4x", IDM_VID_SCALE_6X + MENUITEM "&5x", IDM_VID_SCALE_7X + MENUITEM "&6x", IDM_VID_SCALE_8X + MENUITEM "&7x", IDM_VID_SCALE_9X + MENUITEM "&8x", IDM_VID_SCALE_10X + END + POPUP "éŽæ¿¾æ–¹å¼" + BEGIN + MENUITEM "é„°è¿‘(&N)", IDM_VID_FILTER_NEAREST + MENUITEM "線性(&L)", IDM_VID_FILTER_LINEAR + END + MENUITEM "HiDPI 縮放(&D)", IDM_VID_HIDPI + MENUITEM SEPARATOR + MENUITEM "全螢幕(&F)\tCtrl+Alt+PgUp", IDM_VID_FULLSCREEN + POPUP "全螢幕拉伸模å¼(&S)" + BEGIN + MENUITEM "全螢幕拉伸(&F)", IDM_VID_FS_FULL + MENUITEM "4:3(&4)", IDM_VID_FS_43 + MENUITEM "ä¿æŒæ¯”例(&S)", IDM_VID_FS_KEEPRATIO + MENUITEM "整數比例(&I)", IDM_VID_FS_INT + END + POPUP "EGA/(S)VGA 設定(&G)" + BEGIN + MENUITEM "VGA 顯示器å色顯示(&I)", IDM_VID_INVERT + POPUP "VGA 螢幕類型(&T)" + BEGIN + MENUITEM "RGB 彩色(&C)", IDM_VID_GRAY_RGB + MENUITEM "RGB ç°åº¦(&R)", IDM_VID_GRAY_MONO + MENUITEM "ç¥ç€è‰²å–®è‰²é¡¯ç¤ºå™¨(&A)", IDM_VID_GRAY_AMBER + MENUITEM "綠色單色顯示器(&G)", IDM_VID_GRAY_GREEN + MENUITEM "白色單色顯示器(&W)", IDM_VID_GRAY_WHITE + END + POPUP "ç°åº¦è½‰æ›é¡žåž‹(&C)" + BEGIN + MENUITEM "BT601 (NTSC/PAL)(&6)", IDM_VID_GRAYCT_601 + MENUITEM "BT709 (HDTV)(&7)", IDM_VID_GRAYCT_709 + MENUITEM "å¹³å‡(&A)", IDM_VID_GRAYCT_AVE + END + END + MENUITEM SEPARATOR + MENUITEM "CGA/PCjr/Tandy/EGA/(S)VGA éŽæŽƒæ(&G)", IDM_VID_OVERSCAN + MENUITEM "è®Šæ›´å–®è‰²é¡¯ç¤ºå°æ¯”度(&M)", IDM_VID_CGACON + END + MENUITEM "介質(&M)", IDM_MEDIA + POPUP "工具(&T)" + BEGIN + MENUITEM "設定(&S)...", IDM_CONFIG + MENUITEM "更新狀態列圖示(&U)", IDM_UPDATE_ICONS + MENUITEM SEPARATOR + MENUITEM "擷圖(&C)\tCtrl+F11", IDM_ACTION_SCREENSHOT + MENUITEM SEPARATOR + MENUITEM "å好設定(&P)...", IDM_PREFERENCES +#ifdef DISCORD + MENUITEM "啟用 Discord æ•´åˆ(&D)", IDM_DISCORD +#endif + MENUITEM SEPARATOR + MENUITEM "音é‡å¢žç›Š(&G)...", IDM_SND_GAIN +#ifdef MTR_ENABLED + MENUITEM SEPARATOR + MENUITEM "開始追踪\tCtrl+T", IDM_ACTION_BEGIN_TRACE + MENUITEM "çµæŸè¿½è¸ª\tCtrl+T", IDM_ACTION_END_TRACE +#endif + END + POPUP "說明(&H)" + BEGIN + MENUITEM "文件(&D)...", IDM_DOCS + MENUITEM "關於 86Box(&A)...", IDM_ABOUT + END +END + +StatusBarMenu MENU DISCARDABLE +BEGIN + MENUITEM SEPARATOR +END + +CassetteSubmenu MENU DISCARDABLE +BEGIN + POPUP "" + BEGIN + MENUITEM "新增映åƒ(&N)...", IDM_CASSETTE_IMAGE_NEW + MENUITEM SEPARATOR + MENUITEM "開啟已存在的映åƒ(&E)...", IDM_CASSETTE_IMAGE_EXISTING + MENUITEM "開啟已存在的映åƒä¸¦å¯«ä¿è­·(&W)...", IDM_CASSETTE_IMAGE_EXISTING_WP + MENUITEM SEPARATOR + MENUITEM "錄製(&R)", IDM_CASSETTE_RECORD + MENUITEM "播放(&P)", IDM_CASSETTE_PLAY + MENUITEM "倒帶至起點(&R)", IDM_CASSETTE_REWIND + MENUITEM "快進至終點(&F)", IDM_CASSETTE_FAST_FORWARD + MENUITEM SEPARATOR + MENUITEM "退出(&J)", IDM_CASSETTE_EJECT + END +END + +CartridgeSubmenu MENU DISCARDABLE +BEGIN + POPUP "" + BEGIN + MENUITEM "映åƒ(&I)...", IDM_CARTRIDGE_IMAGE + MENUITEM SEPARATOR + MENUITEM "退出(&J)", IDM_CARTRIDGE_EJECT + END +END + +FloppySubmenu MENU DISCARDABLE +BEGIN + POPUP "" + BEGIN + MENUITEM "新增映åƒ(&N)...", IDM_FLOPPY_IMAGE_NEW + MENUITEM SEPARATOR + MENUITEM "開啟已存在的映åƒ(&E)...", IDM_FLOPPY_IMAGE_EXISTING + MENUITEM "開啟已存在的映åƒä¸¦å¯«ä¿è­·(&W)...", IDM_FLOPPY_IMAGE_EXISTING_WP + MENUITEM SEPARATOR + MENUITEM "匯出為 86F æ ¼å¼(&x)...", IDM_FLOPPY_EXPORT_TO_86F + MENUITEM SEPARATOR + MENUITEM "退出(&J)", IDM_FLOPPY_EJECT + END +END + +CdromSubmenu MENU DISCARDABLE +BEGIN + POPUP "" + BEGIN + MENUITEM "éœéŸ³(&M)", IDM_CDROM_MUTE + MENUITEM SEPARATOR + MENUITEM "空置光碟機(&M)", IDM_CDROM_EMPTY + MENUITEM "載入上一個映åƒ(&R)", IDM_CDROM_RELOAD + MENUITEM SEPARATOR + MENUITEM "映åƒ(&I)...", IDM_CDROM_IMAGE + MENUITEM "資料夾(&F)...", IDM_CDROM_DIR + END +END + +ZIPSubmenu MENU DISCARDABLE +BEGIN + POPUP "" + BEGIN + MENUITEM "新增映åƒ(&N)...", IDM_ZIP_IMAGE_NEW + MENUITEM SEPARATOR + MENUITEM "開啟已存在的映åƒ(&E)...", IDM_ZIP_IMAGE_EXISTING + MENUITEM "開啟已存在的映åƒä¸¦å¯«ä¿è­·(&W)...", IDM_ZIP_IMAGE_EXISTING_WP + MENUITEM SEPARATOR + MENUITEM "退出(&J)", IDM_ZIP_EJECT + MENUITEM "載入上一個映åƒ(&R)", IDM_ZIP_RELOAD + END +END + +MOSubmenu MENU DISCARDABLE +BEGIN + POPUP "" + BEGIN + MENUITEM "新增映åƒ(&N)...", IDM_MO_IMAGE_NEW + MENUITEM SEPARATOR + MENUITEM "開啟已存在的映åƒ(&E)...", IDM_MO_IMAGE_EXISTING + MENUITEM "開啟已存在的映åƒä¸¦å¯«ä¿è­·(&W)...", IDM_MO_IMAGE_EXISTING_WP + MENUITEM SEPARATOR + MENUITEM "退出(&J)", IDM_MO_EJECT + MENUITEM "載入上一個映åƒ(&R)", IDM_MO_RELOAD + END +END + +VidGLSubMenu MENU DISCARDABLE +BEGIN + POPUP "目標幀率(&F)" + BEGIN + MENUITEM "èˆ‡è¦–è¨ŠåŒæ­¥(&S)", IDM_VID_GL_FPS_BLITTER + MENUITEM "25 fps(&2)", IDM_VID_GL_FPS_25 + MENUITEM "30 fps(&3)", IDM_VID_GL_FPS_30 + MENUITEM "50 fps(&5)", IDM_VID_GL_FPS_50 + MENUITEM "60 fps(&6)", IDM_VID_GL_FPS_60 + MENUITEM "75 fps(&7)", IDM_VID_GL_FPS_75 + END + MENUITEM "åž‚ç›´åŒæ­¥(&V)", IDM_VID_GL_VSYNC + MENUITEM "é¸å–著色器(&S)...", IDM_VID_GL_SHADER + MENUITEM "移除著色器(&R)", IDM_VID_GL_NOSHADER +END + + +///////////////////////////////////////////////////////////////////////////// +// +// Dialog +// + +#define STR_PREFERENCES "å好設定" +#define STR_SND_GAIN "音é‡å¢žç›Š" +#define STR_NEW_FLOPPY "新增映åƒ" +#define STR_CONFIG "設定" +#define STR_SPECIFY_DIM "指定主視窗大å°" + +#define STR_OK "確定" +#define STR_CANCEL "å–æ¶ˆ" +#define STR_GLOBAL "將以上設定存儲為全局é è¨­å€¼(&G)" +#define STR_DEFAULT "é è¨­(&D)" +#define STR_LANGUAGE "語言:" +#define STR_ICONSET "圖示集:" + +#define STR_GAIN "增益" + +#define STR_FILE_NAME "檔案å:" +#define STR_DISK_SIZE "ç£ç¢Ÿå¤§å°:" +#define STR_RPM_MODE "轉速 (RPM) 模å¼:" +#define STR_PROGRESS "進度:" + +#define STR_WIDTH "寬度:" +#define STR_HEIGHT "高度:" +#define STR_LOCK_TO_SIZE "鎖定此大å°" + +#define STR_MACHINE_TYPE "機器類型:" +#define STR_MACHINE "機型:" +#define STR_CONFIGURE "設定" +#define STR_CPU_TYPE "CPU 類型:" +#define STR_CPU_SPEED "速度:" +#define STR_FPU "浮點處ç†å™¨ (FPU):" +#define STR_WAIT_STATES "等待狀態 (WS):" +#define STR_MB "MB" +#define STR_MEMORY "記憶體:" +#define STR_TIME_SYNC "æ™‚é–“åŒæ­¥" +#define STR_DISABLED "ç¦ç”¨" +#define STR_ENABLED_LOCAL "啟用 (本地時間)" +#define STR_ENABLED_UTC "啟用 (UTC)" +#define STR_DYNAREC "å‹•æ…‹é‡ç·¨è­¯å™¨" +#define STR_SOFTFLOAT "Softfloat FPU" + +#define STR_VIDEO "顯示å¡:" +#define STR_VIDEO_2 "é¡¯ç¤ºå¡ 2:" +#define STR_VOODOO "Voodoo Graphics" +#define STR_IBM8514 "IBM 8514/a Graphics" +#define STR_XGA "XGA Graphics" + +#define STR_MOUSE "滑鼠:" +#define STR_JOYSTICK "æ–æ¡¿:" +#define STR_JOY1 "æ–æ¡¿ 1..." +#define STR_JOY2 "æ–æ¡¿ 2..." +#define STR_JOY3 "æ–æ¡¿ 3..." +#define STR_JOY4 "æ–æ¡¿ 4..." + +#define STR_SOUND1 "éŸ³æ•ˆå¡ 1:" +#define STR_SOUND2 "éŸ³æ•ˆå¡ 2:" +#define STR_SOUND3 "éŸ³æ•ˆå¡ 3:" +#define STR_SOUND4 "éŸ³æ•ˆå¡ 4:" +#define STR_MIDI_OUT "MIDI 輸出è£ç½®:" +#define STR_MIDI_IN "MIDI 輸入è£ç½®:" +#define STR_MPU401 "ç¨ç«‹ MPU-401" +#define STR_FLOAT "使用單精度浮點 (FLOAT32)" +#define STR_FM_DRIVER "èª¿é »åˆæˆå™¨é©…動器" +#define STR_FM_DRV_NUKED "Nuked (更準確)" +#define STR_FM_DRV_YMFM "YMFM (æ›´å¿«)" + +#define STR_NET_TYPE "網路類型:" +#define STR_PCAP "PCap è£ç½®:" +#define STR_NET "ç¶²è·¯é…æŽ¥å™¨:" +#define STR_NET1 "ç¶²è·¯å¡ 1:" +#define STR_NET2 "ç¶²è·¯å¡ 2:" +#define STR_NET3 "ç¶²è·¯å¡ 3:" +#define STR_NET4 "ç¶²è·¯å¡ 4:" + +#define STR_COM1 "COM1 è£ç½®:" +#define STR_COM2 "COM2 è£ç½®:" +#define STR_COM3 "COM3 è£ç½®:" +#define STR_COM4 "COM4 è£ç½®:" +#define STR_LPT1 "LPT1 è£ç½®:" +#define STR_LPT2 "LPT2 è£ç½®:" +#define STR_LPT3 "LPT3 è£ç½®:" +#define STR_LPT4 "LPT4 è£ç½®:" +#define STR_SERIAL1 "åºåˆ—埠 1" +#define STR_SERIAL2 "åºåˆ—埠 2" +#define STR_SERIAL3 "åºåˆ—埠 3" +#define STR_SERIAL4 "åºåˆ—埠 4" +#define STR_PARALLEL1 "並列埠 1" +#define STR_PARALLEL2 "並列埠 2" +#define STR_PARALLEL3 "並列埠 3" +#define STR_PARALLEL4 "並列埠 4" +#define STR_SERIAL_PASS1 "åºåˆ—埠直通 1" +#define STR_SERIAL_PASS2 "åºåˆ—埠直通 2" +#define STR_SERIAL_PASS3 "åºåˆ—埠直通 3" +#define STR_SERIAL_PASS4 "åºåˆ—埠直通 4" + +#define STR_HDC "硬碟控制器:" +#define STR_FDC "軟碟控制器:" +#define STR_IDE_TER "第三 IDE 控制器" +#define STR_IDE_QUA "第四 IDE 控制器" +#define STR_SCSI "SCSI" +#define STR_SCSI_1 "控制器 1:" +#define STR_SCSI_2 "控制器 2:" +#define STR_SCSI_3 "控制器 3:" +#define STR_SCSI_4 "控制器 4:" +#define STR_CASSETTE "ç£å¸¶" + +#define STR_HDD "硬碟:" +#define STR_NEW "新增(&N)..." +#define STR_EXISTING "已有映åƒ(&E)..." +#define STR_REMOVE "移除(&R)" +#define STR_BUS "åŒ¯æµæŽ’:" +#define STR_CHANNEL "通é“:" +#define STR_ID "ID:" +#define STR_SPEED "Speed:" + +#define STR_SPECIFY "指定(&S)..." +#define STR_SECTORS "ç£å€(S):" +#define STR_HEADS "ç£é ­(H):" +#define STR_CYLS "ç£æŸ±(C):" +#define STR_SIZE_MB "å¤§å° (MB):" +#define STR_TYPE "類型:" +#define STR_IMG_FORMAT "æ˜ åƒæ ¼å¼:" +#define STR_BLOCK_SIZE "å€å¡Šå¤§å°:" + +#define STR_FLOPPY_DRIVES "軟碟機:" +#define STR_TURBO "加速時åº" +#define STR_CHECKBPB "檢查 BPB" +#define STR_CDROM_DRIVES "光碟機:" +#define STR_CD_SPEED "速度:" + +#define STR_MO_DRIVES "ç£å…‰ç¢Ÿæ©Ÿ:" +#define STR_ZIP_DRIVES "ZIP ç£ç¢Ÿæ©Ÿ:" +#define STR_250 "ZIP 250" + +#define STR_ISARTC "ISA 實時時é˜:" +#define STR_ISAMEM "ISA 記憶體擴充" +#define STR_ISAMEM_1 "æ“´å……å¡ 1:" +#define STR_ISAMEM_2 "æ“´å……å¡ 2:" +#define STR_ISAMEM_3 "æ“´å……å¡ 3:" +#define STR_ISAMEM_4 "æ“´å……å¡ 4:" +#define STR_BUGGER "ISABugger è£ç½®" +#define STR_POSTCARD "自檢 (POST) å¡" + +#define FONT_SIZE 9 +#define FONT_NAME "Microsoft JhengHei" + +#include "dialogs.rc" + +///////////////////////////////////////////////////////////////////////////// +// +// String Table +// + +STRINGTABLE DISCARDABLE +BEGIN + 2048 "86Box" + IDS_2049 "錯誤" + IDS_2050 "致命錯誤" + IDS_2051 " - 已暫åœ" + IDS_2052 "按下 Ctrl+Alt+PgDn 返回到視窗模å¼ã€‚" + IDS_2053 "速度" + IDS_2054 "ZIP %03i %i (%s): %ls" + IDS_2055 "ZIP æ˜ åƒ (*.IM?;*.ZDI)\0*.IM?;*.ZDI\0" + IDS_2056 "86Box 找ä¸åˆ°ä»»ä½•å¯ç”¨çš„ ROM 映åƒã€‚\n\n請下載 ROM 套件並將其解壓到 ""roms"" 資料夾。" + IDS_2057 "(空)" + IDS_2058 "ZIP æ˜ åƒ (*.IM?;*.ZDI)\0*.IM?;*.ZDI\0所有檔案 (*.*)\0*.*\0" + IDS_2059 "加速" + IDS_2060 "é–‹" + IDS_2061 "é—œ" + IDS_2062 "æ‰€æœ‰æ˜ åƒ (*.86F;*.DSK;*.FLP;*.IM?;*.*FD?)\0*.86F;*.DSK;*.FLP;*.IM?;*.*FD?\0基本ç£å€æ˜ åƒ (*.DSK;*.FLP;*.IM?;*.*FD?)\0*.DSK;*.FLP;*.IM?;*.IMG;*.*FD?\0è¡¨é¢æ˜ åƒ (*.86F)\0*.86F\0" + IDS_2063 "由於 roms/machines 資料夾中缺少åˆé©çš„ ROM,機型 ""%hs"" ä¸å¯ç”¨ã€‚將切æ›åˆ°å…¶ä»–å¯ç”¨æ©Ÿåž‹ã€‚" +END + +STRINGTABLE DISCARDABLE +BEGIN + IDS_2064 "由於 roms/video 資料夾中缺少åˆé©çš„ ROMï¼Œé¡¯ç¤ºå¡ ""%hs"" ä¸å¯ç”¨ã€‚將切æ›åˆ°å…¶ä»–å¯ç”¨é¡¯ç¤ºå¡ã€‚" + IDS_2065 "機型" + IDS_2066 "顯示" + IDS_2067 "輸入è£ç½®" + IDS_2068 "è²éŸ³" + IDS_2069 "網路" + IDS_2070 "連接埠 (COM å’Œ LPT)" + IDS_2071 "存儲控制器" + IDS_2072 "硬碟" + IDS_2073 "軟碟/光碟機" + IDS_2074 "å…¶ä»–å¯ç§»é™¤è£ç½®" + IDS_2075 "其他周邊è£ç½®" + IDS_2076 "è¡¨é¢æ˜ åƒ (*.86F)\0*.86F\0" + IDS_2077 "é»žæ“Šè¦–çª—æ•æ‰æ»‘é¼ " + IDS_2078 "按下 F8+F12 釋放滑鼠" + IDS_2079 "按下 F8+F12 或滑鼠中éµé‡‹æ”¾æ»‘é¼ " +END + +STRINGTABLE DISCARDABLE +BEGIN + IDS_2081 "åŒ¯æµæŽ’" + IDS_2082 "檔案" + IDS_2083 "C" + IDS_2084 "H" + IDS_2085 "S" + IDS_2086 "MB" + IDS_2087 "Speed" + IDS_2088 "檢查 BPB" + IDS_2089 "KB" + IDS_2090 "無法åˆå§‹åŒ–視訊渲染器。" + IDS_2091 "é è¨­" + IDS_2092 "%i 等待狀態 (WS)" + IDS_2093 "類型" + IDS_2094 "設定 PCap 失敗" + IDS_2095 "未找到 PCap è£ç½®" + IDS_2096 "無效 PCap è£ç½®" + IDS_2097 "標準 2 鵿–æ¡¿" + IDS_2098 "標準 4 鵿–æ¡¿" + IDS_2099 "標準 6 鵿–æ¡¿" + IDS_2100 "標準 8 鵿–æ¡¿" + IDS_2101 "CH Flightstick Pro" + IDS_2102 "Microsoft SideWinder Pad" + IDS_2103 "Thrustmaster Flight Control System" + IDS_2104 "ç„¡" + IDS_2105 "無法載入éµç›¤åŠ é€Ÿå™¨ã€‚" + IDS_2106 "無法註冊原始輸入。" + IDS_2107 "%u" + IDS_2108 "%u MB (CHS: %i, %i, %i)" + IDS_2109 "軟碟 %i (%s): %ls" + IDS_2110 "æ‰€æœ‰æ˜ åƒ (*.0??;*.1??;*.??0;*.86F;*.BIN;*.CQ?;*.D??;*.FLP;*.HDM;*.IM?;*.JSON;*.TD0;*.*FD?;*.MFM;*.XDF)\0*.0??;*.1??;*.??0;*.86F;*.BIN;*.CQ?;*.D??;*.FLP;*.HDM;*.IM?;*.JSON;*.TD0;*.*FD?;*.MFM;*.XDF\0進階ç£å€æ˜ åƒ (*.IMD;*.JSON;*.TD0)\0*.IMD;*.JSON;*.TD0\0基本ç£å€æ˜ åƒ (*.0??;*.1??;*.??0;*.BIN;*.CQ?;*.D??;*.FLP;*.HDM;*.IM?;*.XDF;*.*FD?)\0*.0??;*.1??;*.??0;*.BIN;*.CQ?;*.D??;*.FLP;*.HDM;*.IM?;*.XDF;*.*FD?\0Flux æ˜ åƒ (*.FDI)\0*.FDI\0è¡¨é¢æ˜ åƒ (*.86F;*.MFM)\0*.86F;*.MFM\0所有檔案 (*.*)\0*.*\0" + IDS_2112 "無法åˆå§‹åŒ– SDLï¼Œéœ€è¦ SDL2.dll" + IDS_2113 "確定è¦ç¡¬é‡è¨­æ¨¡æ“¬å™¨å—Žï¼Ÿ" + IDS_2114 "確定è¦é€€å‡º 86Box 嗎?" + IDS_2115 "無法åˆå§‹åŒ– Ghostscript" + IDS_2116 "ç£å…‰ç¢Ÿ %i (%ls): %ls" + IDS_2117 "ç£å…‰ç¢Ÿæ˜ åƒ (*.IM?;*.MDI)\0*.IM?;*.MDI\0所有檔案 (*.*)\0*.*\0" + IDS_2118 "歡迎使用 86Boxï¼" + IDS_2119 "內部控制器" + IDS_2120 "退出" + IDS_2121 "找ä¸åˆ° ROM" + IDS_2122 "è¦å„²å­˜è¨­å®šå—Žï¼Ÿ" + IDS_2123 "æ­¤æ“作將硬é‡è¨­æ¨¡æ“¬å™¨ã€‚" + IDS_2124 "儲存" + IDS_2125 "關於 86Box" + IDS_2126 "86Box v" EMU_VERSION + + IDS_2127 "一個舊å¼é›»è…¦æ¨¡æ“¬å™¨\n\n作者: Miran GrÄa (OBattler)ã€RichardG867ã€Jasmine Iwanekã€TC1995ã€coldbrewedã€Teemu Korhonen (Manaatti)ã€Joakim L. Giljeã€Adrien Moulin (elyosh)ã€Daniel Balsom (gloriouscow)ã€Cacodemon345ã€Fred N. van Kempen (waltje)ã€Tiseno100ã€reenigne 等人。\n\nWith previous core contributions from Sarah Walker, leilei, JohnElliott, greatpsycho, and others.\n\næœ¬è»Ÿé«”ä¾æ“š GNU 通用公共授權第二版或更新版本發布。詳情見 LICENSE 檔案。" + IDS_2128 "確定" + IDS_2129 "硬體ä¸å¯ç”¨" +#ifdef _WIN32 +#define LIB_NAME_PCAP "WinPcap" +#else +#define LIB_NAME_PCAP "libpcap" +#endif + IDS_2130 "è«‹ç¢ºèª " LIB_NAME_PCAP " 已安è£ä¸”使用相容 " LIB_NAME_PCAP " 的網路連線。" + IDS_2131 "無效設定" +#ifdef _WIN32 +#define LIB_NAME_GS "gsdll32.dll" +#else +#define LIB_NAME_GS "libgs" +#endif + IDS_2133 LIB_NAME_GS " 是將 PostScript 檔案轉æ›ç‚º PDF 所需è¦çš„庫。\n\n使用通用 PostScript å°è¡¨æ©Ÿåˆ—å°çš„æ–‡ä»¶å°‡è¢«å„²å­˜ç‚º PostScript (.ps) 檔案。" + IDS_2135 "正在進入全螢幕模å¼" + IDS_2136 "ä¸è¦å†é¡¯ç¤ºæ­¤æ¶ˆæ¯" + IDS_2137 "ä¸é€€å‡º" + IDS_2138 "é‡è¨­" + IDS_2139 "ä¸é‡è¨­" + IDS_2140 "ç£å…‰ç¢Ÿæ˜ åƒ (*.IM?;*.MDI)\0*.IM?;*.MDI\0所有檔案 (*.*)\0*.*\0" + IDS_2141 "å…‰ç¢Ÿæ˜ åƒ (*.ISO;*.CUE)\0*.ISO;*.CUE\0所有檔案 (*.*)\0*.*\0" + IDS_2142 "%hs è£ç½®è¨­å®š" + IDS_2143 "顯示器處在ç¡çœ ç‹€æ…‹" + IDS_2144 "OpenGL 著色器 (*.GLSL)\0*.GLSL\0所有檔案 (*.*)\0*.*\0" + IDS_2145 "OpenGL é¸é …" + IDS_2146 "正在載入一個ä¸å—支æ´çš„設定" + IDS_2147 "此模擬電腦ç¦ç”¨äº†åŸºæ–¼é¸å®šé›»è…¦çš„ CPU é¡žåž‹éŽæ¿¾ã€‚\n\n能夠é¸ä¸­èˆ‡æ‰€é¸æ©Ÿå™¨æœ¬ä¸ç›¸å®¹çš„ CPU,但是å¯èƒ½æœƒé‡åˆ°èˆ‡æ©Ÿå™¨ BIOS 或其他軟體ä¸ç›¸å®¹çš„å•題。\n\n啟用此設定ä¸å—官方支æ´ï¼Œä¸¦ä¸”æäº¤çš„任何錯誤報告å¯èƒ½æœƒè¦–為無效而關閉。" + IDS_2148 "繼續" + IDS_2149 "ç£å¸¶: %s" + IDS_2150 "ç£å¸¶æ˜ åƒ (*.PCM;*.RAW;*.WAV;*.CAS)\0*.PCM;*.RAW;*.WAV;*.CAS\0所有檔案 (*.*)\0*.*\0" + IDS_2151 "å¡å¸¶ %i: %ls" + IDS_2152 "å¡å¸¶æ˜ åƒ (*.A;*.B;*.JRC)\0*.A;*.B;*.JRC\0所有檔案 (*.*)\0*.*\0" + IDS_2153 "åˆå§‹åŒ–渲染器時出錯" + IDS_2154 "無法åˆå§‹åŒ– OpenGL (3.0 核心) 渲染器。請使用其他渲染器。" + IDS_2155 "æ¢å¾©åŸ·è¡Œ" + IDS_2156 "æš«åœåŸ·è¡Œ" + IDS_2157 "按下 Ctrl+Alt+Del" + IDS_2158 "按下 Ctrl+Alt+Esc" + IDS_2159 "硬é‡è¨­" + IDS_2160 "ACPI 關機" + IDS_2161 "設定" + IDS_2162 "Type" + IDS_2163 "No Dynarec" + IDS_2164 "Old Dynarec" + IDS_2165 "New Dynarec" + IDS_2166 "Video card #2 ""%hs"" is not available due to missing ROMs in the roms/video directory. Disabling the second video card." + IDS_2167 "Failed to initialize network driver" + IDS_2168 "The network configuration will be switched to the null driver" +END + +STRINGTABLE DISCARDABLE +BEGIN + IDS_4096 "硬碟 (%s)" + IDS_4097 "%01i:%01i" + IDS_4098 "%01i" + IDS_4099 "ä¸å­˜åœ¨ MFM/RLL 或 ESDI CD-ROM 光碟機" + IDS_4100 "自訂..." + IDS_4101 "自訂 (大容é‡)..." + IDS_4102 "增加新硬碟" + IDS_4103 "增加已存在的硬碟" + IDS_4104 "HDI ç£ç¢Ÿæ˜ åƒä¸èƒ½è¶…éŽ 4 GB。" + IDS_4105 "ç£ç¢Ÿæ˜ åƒä¸èƒ½è¶…éŽ 127 GB。" + IDS_4106 "ç¡¬ç¢Ÿæ˜ åƒ (*.HD?;*.IM?;*.VHD)\0*.HD?;*.IM?;*.VHD\0所有檔案 (*.*)\0*.*\0" + IDS_4107 "ç„¡æ³•è®€å–æª”案" + IDS_4108 "無法寫入檔案" + IDS_4109 "䏿”¯æ´éž 512 ä½å…ƒçµ„ç£å€å¤§å°çš„ HDI 或 HDX 映åƒã€‚" + IDS_4110 "å°šæœªæ”¯æ´ USB" + IDS_4111 "ç£ç¢Ÿæ˜ åƒæª”案已存在" + IDS_4112 "請指定有效的檔案å。" + IDS_4113 "已創建ç£ç¢Ÿæ˜ åƒ" + IDS_4114 "請確定此檔案已存在並å¯è®€å–。" + IDS_4115 "請確定此檔案儲存在å¯å¯«ç›®éŒ„中。" + IDS_4116 "ç£ç¢Ÿæ˜ åƒå¤ªå¤§" + IDS_4117 "請記得為新創建的映åƒåˆ†å€ä¸¦æ ¼å¼åŒ–。" + IDS_4118 "é¸å®šçš„æª”案將被覆蓋。確定繼續使用此檔案嗎?" + IDS_4119 "䏿”¯æ´çš„ç£ç¢Ÿæ˜ åƒ" + IDS_4120 "覆蓋" + IDS_4121 "ä¸è¦†è“‹" + IDS_4122 "åŽŸå§‹æ˜ åƒ (.img)" + IDS_4123 "HDI æ˜ åƒ (.hdi)" + IDS_4124 "HDX æ˜ åƒ (.hdx)" + IDS_4125 "å›ºå®šå¤§å° VHD (.vhd)" + IDS_4126 "å‹•æ…‹å¤§å° VHD (.vhd)" + IDS_4127 "差分 VHD (.vhd)" + IDS_4128 "大å€å¡Š (2 MB)" + IDS_4129 "å°å€å¡Š (512 KB)" + IDS_4130 "VHD 檔案 (*.VHD)\0*.VHD\0所有檔案 (*.*)\0*.*\0" + IDS_4131 "é¸å–父 VHD 檔案" + IDS_4132 "父映åƒå¯èƒ½åœ¨å‰µå»ºå·®ç•°æ˜ åƒå¾Œè¢«ä¿®æ”¹ã€‚\n\nå¦‚æžœæ˜ åƒæª”案被移動或複製,或創建此ç£ç¢Ÿçš„程å¼ä¸­å­˜åœ¨éŒ¯èª¤ï¼Œä¹Ÿå¯èƒ½ç™¼ç”Ÿé€™ç¨®æƒ…æ³ã€‚\n\n是å¦éœ€è¦ä¿®å¾©æ™‚間戳?" + IDS_4133 "父碟與å­ç¢Ÿçš„æ™‚間戳ä¸åŒ¹é…" + IDS_4134 "無法修復 VHD 時間戳。" + IDS_4135 "%01i:%02i" + + IDS_4352 "MFM/RLL" + IDS_4353 "XTA" + IDS_4354 "ESDI" + IDS_4355 "IDE" + IDS_4356 "ATAPI" + IDS_4357 "SCSI" + + IDS_4608 "MFM/RLL (%01i:%01i)" + IDS_4609 "XTA (%01i:%01i)" + IDS_4610 "ESDI (%01i:%01i)" + IDS_4611 "IDE (%01i:%01i)" + IDS_4612 "ATAPI (%01i:%01i)" + IDS_4613 "SCSI (%01i:%02i)" + + IDS_5120 "光碟 %i (%s): %s" + + IDS_5376 "ç¦ç”¨" + IDS_5381 "ATAPI" + IDS_5382 "SCSI" + + IDS_5632 "ç¦ç”¨" + IDS_5637 "ATAPI (%01i:%01i)" + IDS_5638 "SCSI (%01i:%02i)" + + IDS_5888 "160 kB" + IDS_5889 "180 kB" + IDS_5890 "320 kB" + IDS_5891 "360 kB" + IDS_5892 "640 kB" + IDS_5893 "720 kB" + IDS_5894 "1.2 MB" + IDS_5895 "1.25 MB" + IDS_5896 "1.44 MB" + IDS_5897 "DMF (1024 ç°‡)" + IDS_5898 "DMF (2048 ç°‡)" + IDS_5899 "2.88 MB" + IDS_5900 "ZIP 100" + IDS_5901 "ZIP 250" + IDS_5902 "3.5 è‹±å‹ 128 MB (ISO 10090)" + IDS_5903 "3.5 è‹±å‹ 230 MB (ISO 13963)" + IDS_5904 "3.5 è‹±å‹ 540 MB (ISO 15498)" + IDS_5905 "3.5 è‹±å‹ 640 MB (ISO 15498)" + IDS_5906 "3.5 è‹±å‹ 1.3 GB (GigaMO)" + IDS_5907 "3.5 è‹±å‹ 2.3 GB (GigaMO 2)" + IDS_5908 "5.25 è‹±å‹ 600 MB" + IDS_5909 "5.25 è‹±å‹ 650 MB" + IDS_5910 "5.25 è‹±å‹ 1 GB" + IDS_5911 "5.25 è‹±å‹ 1.3 GB" + + IDS_6144 "標準轉速 (RPM)" + IDS_6145 "低於標準轉速的 1%" + IDS_6146 "低於標準轉速的 1.5%" + IDS_6147 "低於標準轉速的 2%" + + IDS_7168 "(系統é è¨­)" +END +#define IDS_LANG_ENUS IDS_7168 + +// Traditional Chinese resources +///////////////////////////////////////////////////////////////////////////// diff --git a/src/win/win.c b/src/win/win.c index 66cf8a85e..21ff6646c 100644 --- a/src/win/win.c +++ b/src/win/win.c @@ -1,23 +1,24 @@ /* - * 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. + * 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. + * This file is part of the 86Box distribution. * - * Platform main support module for Windows. + * Platform main support module for Windows. * * * - * Authors: Sarah Walker, - * Miran Grca, - * Fred N. van Kempen, + * Authors: Sarah Walker, + * Miran Grca, + * Fred N. van Kempen, * - * Copyright 2008-2019 Sarah Walker. - * Copyright 2016-2019 Miran Grca. - * Copyright 2017-2019 Fred N. van Kempen. - * Copyright 2021 Laci bá' + * Copyright 2008-2019 Sarah Walker. + * Copyright 2016-2019 Miran Grca. + * Copyright 2017-2019 Fred N. van Kempen. + * Copyright 2021 Laci bá' + * Copyright 2021-2023 Jasmine Iwanek. */ #define UNICODE #define NTDDI_VERSION 0x06010000 @@ -45,106 +46,106 @@ #include <86box/timer.h> #include <86box/nvr.h> #include <86box/video.h> +#include <86box/mem.h> +#include <86box/rom.h> +#include <86box/path.h> #define GLOBAL #include <86box/plat.h> +#include <86box/thread.h> #include <86box/ui.h> #ifdef USE_VNC -# include <86box/vnc.h> +# include <86box/vnc.h> #endif #include <86box/win_sdl.h> #include <86box/win_opengl.h> #include <86box/win.h> #include <86box/version.h> +#include <86box/gdbstub.h> #ifdef MTR_ENABLED -#include +# include #endif -typedef struct { +typedef struct rc_str_t { WCHAR str[1024]; } rc_str_t; - /* Platform Public data, specific. */ -HINSTANCE hinstance; /* application instance */ -HANDLE ghMutex; -uint32_t lang_id, lang_sys; /* current and system language ID */ -DWORD dwSubLangID; -int acp_utf8; /* Windows supports UTF-8 codepage */ -volatile int cpu_thread_run = 1; - +HINSTANCE hinstance; /* application instance */ +HANDLE ghMutex; +uint32_t lang_id; /* current and system language ID */ +uint32_t lang_sys; /* current and system language ID */ +DWORD dwSubLangID; +int acp_utf8; /* Windows supports UTF-8 codepage */ +volatile int cpu_thread_run = 1; /* Local data. */ -static HANDLE thMain; -static rc_str_t *lpRCstr2048 = NULL, - *lpRCstr4096 = NULL, - *lpRCstr4352 = NULL, - *lpRCstr4608 = NULL, - *lpRCstr5120 = NULL, - *lpRCstr5376 = NULL, - *lpRCstr5632 = NULL, - *lpRCstr5888 = NULL, - *lpRCstr6144 = NULL, - *lpRCstr7168 = NULL; -static int vid_api_inited = 0; -static char *argbuf; -static int first_use = 1; -static LARGE_INTEGER StartingTime; -static LARGE_INTEGER Frequency; - +static HANDLE thMain; +static rc_str_t *lpRCstr2048 = NULL; +static rc_str_t *lpRCstr4096 = NULL; +static rc_str_t *lpRCstr4352 = NULL; +static rc_str_t *lpRCstr4608 = NULL; +static rc_str_t *lpRCstr5120 = NULL; +static rc_str_t *lpRCstr5376 = NULL; +static rc_str_t *lpRCstr5632 = NULL; +static rc_str_t *lpRCstr5888 = NULL; +static rc_str_t *lpRCstr6144 = NULL; +static rc_str_t *lpRCstr7168 = NULL; +static int vid_api_inited = 0; +static char *argbuf; +static int first_use = 1; +static LARGE_INTEGER StartingTime; +static LARGE_INTEGER Frequency; static const struct { - const char *name; - int local; - int (*init)(void *); - void (*close)(void); - void (*resize)(int x, int y); - int (*pause)(void); - void (*enable)(int enable); - void (*set_fs)(int fs); - void (*reload)(void); + const char *name; + int local; + int (*init)(void *); + void (*close)(void); + void (*resize)(int x, int y); + int (*pause)(void); + void (*enable)(int enable); + void (*set_fs)(int fs); + void (*reload)(void); } vid_apis[RENDERERS_NUM] = { - { "SDL_Software", 1, (int(*)(void*))sdl_inits, sdl_close, NULL, sdl_pause, sdl_enable, sdl_set_fs, sdl_reload }, - { "SDL_Hardware", 1, (int(*)(void*))sdl_inith, sdl_close, NULL, sdl_pause, sdl_enable, sdl_set_fs, sdl_reload }, - { "SDL_OpenGL", 1, (int(*)(void*))sdl_initho, sdl_close, NULL, sdl_pause, sdl_enable, sdl_set_fs, sdl_reload } - ,{ "OpenGL_Core", 1, (int(*)(void*))opengl_init, opengl_close, opengl_resize, opengl_pause, NULL, opengl_set_fs, opengl_reload} + { "SDL_Software", 1, (int (*)(void *)) sdl_inits, sdl_close, NULL, sdl_pause, sdl_enable, sdl_set_fs, sdl_reload }, + { "SDL_Hardware", 1, (int (*)(void *)) sdl_inith, sdl_close, NULL, sdl_pause, sdl_enable, sdl_set_fs, sdl_reload }, + { "SDL_OpenGL", 1, (int (*)(void *)) sdl_initho, sdl_close, NULL, sdl_pause, sdl_enable, sdl_set_fs, sdl_reload }, + { "OpenGL_Core", 1, (int (*)(void *)) opengl_init, opengl_close, opengl_resize, opengl_pause, NULL, opengl_set_fs, opengl_reload } #ifdef USE_VNC - ,{ "VNC", 0, vnc_init, vnc_close, vnc_resize, vnc_pause, NULL, NULL } + , + { "VNC", 0, vnc_init, vnc_close, vnc_resize, vnc_pause, NULL, NULL } #endif }; - extern int title_update; - #ifdef ENABLE_WIN_LOG int win_do_log = ENABLE_WIN_LOG; - static void win_log(const char *fmt, ...) { va_list ap; if (win_do_log) { - va_start(ap, fmt); - pclog_ex(fmt, ap); - va_end(ap); + va_start(ap, fmt); + pclog_ex(fmt, ap); + va_end(ap); } } #else -#define win_log(fmt, ...) +# define win_log(fmt, ...) #endif void free_string(rc_str_t **str) { if (*str != NULL) { - free(*str); - *str = NULL; + free(*str); + *str = NULL; } } - static void LoadCommonStrings(void) { @@ -172,136 +173,137 @@ LoadCommonStrings(void) lpRCstr6144 = calloc(STR_NUM_6144, sizeof(rc_str_t)); lpRCstr7168 = calloc(STR_NUM_7168, sizeof(rc_str_t)); - for (i=0; i 3)) - LoadString(hinstance, 5376+i, lpRCstr5376[i].str, 1024); + for (i = 0; i < STR_NUM_5376; i++) { + if ((i == 0) || (i > 3)) + LoadString(hinstance, 5376 + i, lpRCstr5376[i].str, 1024); } - for (i=0; i 3)) - LoadString(hinstance, 5632+i, lpRCstr5632[i].str, 1024); + for (i = 0; i < STR_NUM_5632; i++) { + if ((i == 0) || (i > 3)) + LoadString(hinstance, 5632 + i, lpRCstr5632[i].str, 1024); } - for (i=0; i= 2048) && (i <= 3071)) - str = lpRCstr2048[i-2048].str; + str = lpRCstr2048[i - 2048].str; else if ((i >= 4096) && (i <= 4351)) - str = lpRCstr4096[i-4096].str; + str = lpRCstr4096[i - 4096].str; else if ((i >= 4352) && (i <= 4607)) - str = lpRCstr4352[i-4352].str; + str = lpRCstr4352[i - 4352].str; else if ((i >= 4608) && (i <= 5119)) - str = lpRCstr4608[i-4608].str; + str = lpRCstr4608[i - 4608].str; else if ((i >= 5120) && (i <= 5375)) - str = lpRCstr5120[i-5120].str; + str = lpRCstr5120[i - 5120].str; else if ((i >= 5376) && (i <= 5631)) - str = lpRCstr5376[i-5376].str; + str = lpRCstr5376[i - 5376].str; else if ((i >= 5632) && (i <= 5887)) - str = lpRCstr5632[i-5632].str; + str = lpRCstr5632[i - 5632].str; else if ((i >= 5888) && (i <= 6143)) - str = lpRCstr5888[i-5888].str; + str = lpRCstr5888[i - 5888].str; else if ((i >= 6144) && (i <= 7167)) - str = lpRCstr6144[i-6144].str; + str = lpRCstr6144[i - 6144].str; else - str = lpRCstr7168[i-7168].str; + str = lpRCstr7168[i - 7168].str; - return((wchar_t *)str); + return str; } #ifdef MTR_ENABLED @@ -325,140 +327,141 @@ static void CreateConsole(int init) { HANDLE h; - FILE *fp; + FILE *fp; fpos_t p; - int i; + int i; - if (! init) { - if (force_debug) - FreeConsole(); - return; + if (!init) { + if (force_debug) + FreeConsole(); + return; } /* Are we logging to a file? */ p = 0; - (void)fgetpos(stdout, &p); - if (p != -1) return; + (void) fgetpos(stdout, &p); + if (p != -1) + return; /* Not logging to file, attach to console. */ - if (! AttachConsole(ATTACH_PARENT_PROCESS)) { - /* Parent has no console, create one. */ - if (! AllocConsole()) { - /* Cannot create console, just give up. */ - return; - } + if (!AttachConsole(ATTACH_PARENT_PROCESS)) { + /* Parent has no console, create one. */ + if (!AllocConsole()) { + /* Cannot create console, just give up. */ + return; + } } fp = NULL; if ((h = GetStdHandle(STD_OUTPUT_HANDLE)) != NULL) { - /* We got the handle, now open a file descriptor. */ - if ((i = _open_osfhandle((intptr_t)h, _O_TEXT)) != -1) { - /* We got a file descriptor, now allocate a new stream. */ - if ((fp = _fdopen(i, "w")) != NULL) { - /* Got the stream, re-initialize stdout without it. */ - (void)freopen("CONOUT$", "w", stdout); - setvbuf(stdout, NULL, _IONBF, 0); - fflush(stdout); - } - } + /* We got the handle, now open a file descriptor. */ + if ((i = _open_osfhandle((intptr_t) h, _O_TEXT)) != -1) { + /* We got a file descriptor, now allocate a new stream. */ + if ((fp = _fdopen(i, "w")) != NULL) { + /* Got the stream, re-initialize stdout without it. */ + (void) freopen("CONOUT$", "w", stdout); + setvbuf(stdout, NULL, _IONBF, 0); + fflush(stdout); + } + } } if (fp != NULL) { - fclose(fp); - fp = NULL; + fclose(fp); + fp = NULL; } } - static void CloseConsole(void) { CreateConsole(0); } - /* Process the commandline, and create standard argc/argv array. */ static int ProcessCommandLine(char ***argv) { char **args; - int argc_max; - int i, q, argc; + int argc_max; + int i; + int q; + int argc; if (acp_utf8) { - i = strlen(GetCommandLineA()) + 1; - argbuf = (char *)malloc(i); - strcpy(argbuf, GetCommandLineA()); + i = strlen(GetCommandLineA()) + 1; + argbuf = (char *) malloc(i); + strcpy(argbuf, GetCommandLineA()); } else { - i = c16stombs(NULL, GetCommandLineW(), 0) + 1; - argbuf = (char *)malloc(i); - c16stombs(argbuf, GetCommandLineW(), i); + i = c16stombs(NULL, GetCommandLineW(), 0) + 1; + argbuf = (char *) malloc(i); + c16stombs(argbuf, GetCommandLineW(), i); } - argc = 0; + argc = 0; argc_max = 64; - args = (char **)malloc(sizeof(char *) * argc_max); + args = (char **) malloc(sizeof(char *) * argc_max); if (args == NULL) { - free(argbuf); - return(0); + free(argbuf); + return 0; } /* parse commandline into argc/argv format */ i = 0; while (argbuf[i]) { - while (argbuf[i] == ' ') - i++; + while (argbuf[i] == ' ') + i++; - if (argbuf[i]) { - if ((argbuf[i] == '\'') || (argbuf[i] == '"')) { - q = argbuf[i++]; - if (!argbuf[i]) - break; - } else - q = 0; + if (argbuf[i]) { + if ((argbuf[i] == '\'') || (argbuf[i] == '"')) { + q = argbuf[i++]; + if (!argbuf[i]) + break; + } else + q = 0; - args[argc++] = &argbuf[i]; + args[argc++] = &argbuf[i]; - if (argc >= argc_max) { - argc_max += 64; - args = realloc(args, sizeof(char *)*argc_max); - if (args == NULL) { - free(argbuf); - return(0); - } - } + if (argc >= argc_max) { + argc_max += 64; + args = realloc(args, sizeof(char *) * argc_max); + if (args == NULL) { + free(argbuf); + return 0; + } + } - while ((argbuf[i]) && ((q) - ? (argbuf[i]!=q) : (argbuf[i]!=' '))) i++; + while ((argbuf[i]) && (q ? (argbuf[i] != q) : (argbuf[i] != ' '))) + i++; - if (argbuf[i]) { - argbuf[i] = 0; - i++; - } - } + if (argbuf[i]) { + argbuf[i] = 0; + i++; + } + } } args[argc] = NULL; - *argv = args; + *argv = args; - return(argc); + return argc; } - /* For the Windows platform, this is the start of the application. */ int WINAPI WinMain(HINSTANCE hInst, HINSTANCE hPrev, LPSTR lpszArg, int nCmdShow) { char **argv = NULL; - int argc, i; + int argc; + int i; /* Initialize the COM library for the main thread. */ CoInitializeEx(NULL, COINIT_MULTITHREADED); /* Check if Windows supports UTF-8 */ if (GetACP() == CP_UTF8) - acp_utf8 = 1; + acp_utf8 = 1; else - acp_utf8 = 0; + acp_utf8 = 0; /* Set this to the default value (windowed mode). */ video_fullscreen = 0; @@ -468,37 +471,36 @@ WinMain(HINSTANCE hInst, HINSTANCE hPrev, LPSTR lpszArg, int nCmdShow) /* Set the application version ID string. */ sprintf(emu_version, "%s v%s", EMU_NAME, EMU_VERSION_FULL); - - /* First, set our (default) language. */ - lang_sys = GetThreadUILanguage(); + + /* First, set our (default) language. */ + lang_sys = GetThreadUILanguage(); set_language(DEFAULT_LANGUAGE); /* Process the command line for options. */ argc = ProcessCommandLine(&argv); /* Pre-initialize the system, this loads the config file. */ - if (! pc_init(argc, argv)) { - /* Detach from console. */ - if (force_debug) - CreateConsole(0); + if (!pc_init(argc, argv)) { + /* Detach from console. */ + if (force_debug) + CreateConsole(0); - if (source_hwnd) - PostMessage((HWND) (uintptr_t) source_hwnd, WM_HAS_SHUTDOWN, (WPARAM) 0, (LPARAM) hwndMain); + if (source_hwnd) + PostMessage((HWND) (uintptr_t) source_hwnd, WM_HAS_SHUTDOWN, (WPARAM) 0, (LPARAM) hwndMain); - free(argbuf); - free(argv); - return(1); + free(argbuf); + free(argv); + return 1; } - /* Enable crash dump services. */ - if (enable_crashdump) - InitCrashDump(); + extern int gfxcard[2]; + gfxcard[1] = 0; /* Create console window. */ if (force_debug) { - CreateConsole(1); - atexit(CloseConsole); -} + CreateConsole(1); + atexit(CloseConsole); + } /* Handle our GUI. */ i = ui_init(nCmdShow); @@ -508,57 +510,62 @@ WinMain(HINSTANCE hInst, HINSTANCE hPrev, LPSTR lpszArg, int nCmdShow) free(argbuf); free(argv); - return(i); + return i; } - void main_thread(void *param) { - uint32_t old_time, new_time; - int drawits, frames; + uint32_t old_time; + uint32_t new_time; + int drawits; + int frames; - framecountx = 0; + framecountx = 0; title_update = 1; - old_time = GetTickCount(); + old_time = GetTickCount(); drawits = frames = 0; while (!is_quit && cpu_thread_run) { - /* See if it is time to run a frame of code. */ - new_time = GetTickCount(); - drawits += (new_time - old_time); - old_time = new_time; - if (drawits > 0 && !dopause) { - /* Yes, so do one frame now. */ - drawits -= 10; - if (drawits > 50) - drawits = 0; + /* See if it is time to run a frame of code. */ + new_time = GetTickCount(); +#ifdef USE_GDBSTUB + if (gdbstub_next_asap && (drawits <= 0)) + drawits = 10; + else +#endif + drawits += (new_time - old_time); + old_time = new_time; + if (drawits > 0 && !dopause) { + /* Yes, so do one frame now. */ + drawits -= 10; + if (drawits > 50) + drawits = 0; - /* Run a block of code. */ - pc_run(); + /* Run a block of code. */ + pc_run(); - /* Every 200 frames we save the machine status. */ - if (++frames >= 200 && nvr_dosave) { - nvr_save(); - nvr_dosave = 0; - frames = 0; - } - } else /* Just so we dont overload the host OS. */ - Sleep((drawits < -1) ? 1 : 0); - // Sleep(1); + /* Every 200 frames we save the machine status. */ + if (++frames >= 200 && nvr_dosave) { + nvr_save(); + nvr_dosave = 0; + frames = 0; + } + } else /* Just so we dont overload the host OS. */ + Sleep(1); - /* If needed, handle a screen resize. */ - if (!atomic_flag_test_and_set(&doresize) && !video_fullscreen && !is_quit) { - if (vid_resize & 2) - plat_resize(fixed_size_x, fixed_size_y); - else - plat_resize(scrnsz_x, scrnsz_y); - } + /* If needed, handle a screen resize. */ + if (atomic_load(&doresize_monitors[0]) && !video_fullscreen && !is_quit) { + if (vid_resize & 2) + plat_resize(fixed_size_x, fixed_size_y); + else + plat_resize(scrnsz_x, scrnsz_y); + atomic_store(&doresize_monitors[0], 0); + } } is_quit = 1; } - /* * We do this here since there is platform-specific stuff * going on here, and we do it in a function separate from @@ -583,7 +590,6 @@ do_start(void) SetThreadPriority(thMain, THREAD_PRIORITY_HIGHEST); } - /* Cleanly stop the emulator. */ void do_stop(void) @@ -598,112 +604,108 @@ do_stop(void) thMain = NULL; if (source_hwnd) - PostMessage((HWND) (uintptr_t) source_hwnd, WM_HAS_SHUTDOWN, (WPARAM) 0, (LPARAM) hwndMain); + PostMessage((HWND) (uintptr_t) source_hwnd, WM_HAS_SHUTDOWN, (WPARAM) 0, (LPARAM) hwndMain); } - void plat_get_exe_name(char *s, int size) { wchar_t *temp; if (acp_utf8) - GetModuleFileNameA(hinstance, s, size); + GetModuleFileNameA(hinstance, s, size); else { - temp = malloc(size * sizeof(wchar_t)); - GetModuleFileNameW(hinstance, temp, size); - c16stombs(s, temp, size); - free(temp); + temp = malloc(size * sizeof(wchar_t)); + GetModuleFileNameW(hinstance, temp, size); + c16stombs(s, temp, size); + free(temp); } } - void plat_tempfile(char *bufp, char *prefix, char *suffix) { SYSTEMTIME SystemTime; if (prefix != NULL) - sprintf(bufp, "%s-", prefix); - else - strcpy(bufp, ""); + sprintf(bufp, "%s-", prefix); + else + strcpy(bufp, ""); - GetSystemTime(&SystemTime); + GetLocalTime(&SystemTime); sprintf(&bufp[strlen(bufp)], "%d%02d%02d-%02d%02d%02d-%03d%s", - SystemTime.wYear, SystemTime.wMonth, SystemTime.wDay, - SystemTime.wHour, SystemTime.wMinute, SystemTime.wSecond, - SystemTime.wMilliseconds, - suffix); + SystemTime.wYear, SystemTime.wMonth, SystemTime.wDay, + SystemTime.wHour, SystemTime.wMinute, SystemTime.wSecond, + SystemTime.wMilliseconds, + suffix); } - int plat_getcwd(char *bufp, int max) { wchar_t *temp; if (acp_utf8) - (void)_getcwd(bufp, max); + (void) _getcwd(bufp, max); else { - temp = malloc(max * sizeof(wchar_t)); - (void)_wgetcwd(temp, max); - c16stombs(bufp, temp, max); - free(temp); + temp = malloc(max * sizeof(wchar_t)); + (void) _wgetcwd(temp, max); + c16stombs(bufp, temp, max); + free(temp); } - return(0); + return 0; } - int plat_chdir(char *path) { wchar_t *temp; - int len, ret; + int len; + int ret; if (acp_utf8) - return(_chdir(path)); + return (_chdir(path)); else { - len = mbstoc16s(NULL, path, 0) + 1; - temp = malloc(len * sizeof(wchar_t)); - mbstoc16s(temp, path, len); + len = mbstoc16s(NULL, path, 0) + 1; + temp = malloc(len * sizeof(wchar_t)); + mbstoc16s(temp, path, len); - ret = _wchdir(temp); + ret = _wchdir(temp); - free(temp); - return ret; + free(temp); + return ret; } } - FILE * plat_fopen(const char *path, const char *mode) { - wchar_t *pathw, *modew; - int len; - FILE *fp; + wchar_t *pathw; + wchar_t *modew; + int len; + FILE *fp; if (acp_utf8) - return fopen(path, mode); + return fopen(path, mode); else { - len = mbstoc16s(NULL, path, 0) + 1; - pathw = malloc(sizeof(wchar_t) * len); - mbstoc16s(pathw, path, len); + len = mbstoc16s(NULL, path, 0) + 1; + pathw = malloc(sizeof(wchar_t) * len); + mbstoc16s(pathw, path, len); - len = mbstoc16s(NULL, mode, 0) + 1; - modew = malloc(sizeof(wchar_t) * len); - mbstoc16s(modew, mode, len); + len = mbstoc16s(NULL, mode, 0) + 1; + modew = malloc(sizeof(wchar_t) * len); + mbstoc16s(modew, mode, len); - fp = _wfopen(pathw, modew); + fp = _wfopen(pathw, modew); - free(pathw); - free(modew); + free(pathw); + free(modew); - return fp; + return fp; } } - /* Open a file, using Unicode pathname, with 64bit pointers. */ FILE * plat_fopen64(const char *path, const char *mode) @@ -711,201 +713,247 @@ plat_fopen64(const char *path, const char *mode) return plat_fopen(path, mode); } - void plat_remove(char *path) { wchar_t *temp; - int len; + int len; if (acp_utf8) - remove(path); + remove(path); else { - len = mbstoc16s(NULL, path, 0) + 1; - temp = malloc(len * sizeof(wchar_t)); - mbstoc16s(temp, path, len); + len = mbstoc16s(NULL, path, 0) + 1; + temp = malloc(len * sizeof(wchar_t)); + mbstoc16s(temp, path, len); - _wremove(temp); + _wremove(temp); - free(temp); + free(temp); } } +void +path_normalize(UNUSED(char *path)) +{ + /* No-op */ +} /* Make sure a path ends with a trailing (back)slash. */ void -plat_path_slash(char *path) +path_slash(char *path) { - if ((path[strlen(path)-1] != '\\') && - (path[strlen(path)-1] != '/')) { - strcat(path, "\\"); - } + if ((path[strlen(path) - 1] != '\\') && (path[strlen(path) - 1] != '/')) + strcat(path, "\\"); } +/* Return a trailing (back)slash if necessary. */ +const char * +path_get_slash(char *path) +{ + char *ret = ""; + + if ((path[strlen(path) - 1] != '\\') && (path[strlen(path) - 1] != '/')) + ret = "\\"; + + return ret; +} /* Check if the given path is absolute or not. */ int -plat_path_abs(char *path) +path_abs(char *path) { if ((path[1] == ':') || (path[0] == '\\') || (path[0] == '/')) - return(1); + return 1; - return(0); + return 0; } - /* Return the last element of a pathname. */ char * plat_get_basename(const char *path) { - int c = (int)strlen(path); + int c = (int) strlen(path); while (c > 0) { - if (path[c] == '/' || path[c] == '\\') - return((char *)&path[c + 1]); - c--; + if (path[c] == '/' || path[c] == '\\') + return ((char *) &path[c + 1]); + c--; } - return((char *)path); + return ((char *) path); } - /* Return the 'directory' element of a pathname. */ void -plat_get_dirname(char *dest, const char *path) +path_get_dirname(char *dest, const char *path) { - int c = (int)strlen(path); - char *ptr; + int c = (int) strlen(path); + const char *ptr; - ptr = (char *)path; + ptr = (char *) path; while (c > 0) { - if (path[c] == '/' || path[c] == '\\') { - ptr = (char *)&path[c]; - break; - } - c--; + if (path[c] == '/' || path[c] == '\\') { + ptr = (char *) &path[c]; + break; + } + c--; } /* Copy to destination. */ while (path < ptr) - *dest++ = *path++; + *dest++ = *path++; *dest = '\0'; } - char * -plat_get_filename(char *s) +path_get_filename(char *s) { int c = strlen(s) - 1; while (c > 0) { - if (s[c] == '/' || s[c] == '\\') - return(&s[c+1]); - c--; + if (s[c] == '/' || s[c] == '\\') + return (&s[c + 1]); + c--; } - return(s); + return s; } - char * -plat_get_extension(char *s) +path_get_extension(char *s) { int c = strlen(s) - 1; if (c <= 0) - return(s); + return s; while (c && s[c] != '.') - c--; + c--; if (!c) - return(&s[strlen(s)]); + return (&s[strlen(s)]); - return(&s[c+1]); + return (&s[c + 1]); } - void -plat_append_filename(char *dest, const char *s1, const char *s2) +path_append_filename(char *dest, const char *s1, const char *s2) { strcpy(dest, s1); - plat_path_slash(dest); + path_slash(dest); strcat(dest, s2); } - void plat_put_backslash(char *s) { int c = strlen(s) - 1; if (s[c] != '/' && s[c] != '\\') - s[c] = '/'; + s[c] = '/'; } - int plat_dir_check(char *path) { - DWORD dwAttrib; - int len; + DWORD dwAttrib; + int len; wchar_t *temp; - - if (acp_utf8) - dwAttrib = GetFileAttributesA(path); + + if (acp_utf8) + dwAttrib = GetFileAttributesA(path); else { - len = mbstoc16s(NULL, path, 0) + 1; - temp = malloc(len * sizeof(wchar_t)); - mbstoc16s(temp, path, len); + len = mbstoc16s(NULL, path, 0) + 1; + temp = malloc(len * sizeof(wchar_t)); + mbstoc16s(temp, path, len); - dwAttrib = GetFileAttributesW(temp); + dwAttrib = GetFileAttributesW(temp); - free(temp); + free(temp); } - return(((dwAttrib != INVALID_FILE_ATTRIBUTES && - (dwAttrib & FILE_ATTRIBUTE_DIRECTORY))) ? 1 : 0); + return ((dwAttrib != INVALID_FILE_ATTRIBUTES && (dwAttrib & FILE_ATTRIBUTE_DIRECTORY)) ? 1 : 0); } - int plat_dir_create(char *path) { - int ret, len; + int ret; + int len; wchar_t *temp; - + if (acp_utf8) - return (int)SHCreateDirectoryExA(NULL, path, NULL); + return SHCreateDirectoryExA(NULL, path, NULL); else { - len = mbstoc16s(NULL, path, 0) + 1; - temp = malloc(len * sizeof(wchar_t)); - mbstoc16s(temp, path, len); + len = mbstoc16s(NULL, path, 0) + 1; + temp = malloc(len * sizeof(wchar_t)); + mbstoc16s(temp, path, len); - ret = (int)SHCreateDirectoryExW(NULL, temp, NULL); + ret = SHCreateDirectoryExW(NULL, temp, NULL); - free(temp); + free(temp); - return ret; + return ret; } } - void * plat_mmap(size_t size, uint8_t executable) { return VirtualAlloc(NULL, size, MEM_COMMIT, executable ? PAGE_EXECUTE_READWRITE : PAGE_READWRITE); } +void +plat_get_global_config_dir(char *strptr) +{ + wchar_t appdata_dir[1024] = { L'\0' }; + + if (_wgetenv(L"LOCALAPPDATA") && _wgetenv(L"LOCALAPPDATA")[0] != L'\0') { + size_t len = 0; + wcsncpy(appdata_dir, _wgetenv(L"LOCALAPPDATA"), 1024); + len = wcslen(appdata_dir); + if (appdata_dir[len - 1] != L'\\') { + appdata_dir[len] = L'\\'; + appdata_dir[len + 1] = L'\0'; + } + wcscat(appdata_dir, L"86box"); + CreateDirectoryW(appdata_dir, NULL); + wcscat(appdata_dir, L"\\"); + c16stombs(strptr, appdata_dir, 1024); + } +} void -plat_munmap(void *ptr, size_t size) +plat_init_rom_paths(void) +{ + wchar_t appdata_dir[1024] = { L'\0' }; + + if (_wgetenv(L"LOCALAPPDATA") && _wgetenv(L"LOCALAPPDATA")[0] != L'\0') { + char appdata_dir_a[1024] = { '\0' }; + size_t len = 0; + wcsncpy(appdata_dir, _wgetenv(L"LOCALAPPDATA"), 1024); + len = wcslen(appdata_dir); + if (appdata_dir[len - 1] != L'\\') { + appdata_dir[len] = L'\\'; + appdata_dir[len + 1] = L'\0'; + } + wcscat(appdata_dir, L"86box"); + CreateDirectoryW(appdata_dir, NULL); + wcscat(appdata_dir, L"\\roms"); + CreateDirectoryW(appdata_dir, NULL); + wcscat(appdata_dir, L"\\"); + c16stombs(appdata_dir_a, appdata_dir, 1024); + rom_add_path(appdata_dir_a); + } +} + +void +plat_munmap(void *ptr, UNUSED(size_t size)) { VirtualFree(ptr, 0, MEM_RELEASE); } - uint64_t plat_timer_read(void) { @@ -913,18 +961,19 @@ plat_timer_read(void) QueryPerformanceCounter(&li); - return(li.QuadPart); + return (li.QuadPart); } static LARGE_INTEGER plat_get_ticks_common(void) { - LARGE_INTEGER EndingTime, ElapsedMicroseconds; + LARGE_INTEGER EndingTime; + LARGE_INTEGER ElapsedMicroseconds; if (first_use) { - QueryPerformanceFrequency(&Frequency); - QueryPerformanceCounter(&StartingTime); - first_use = 0; + QueryPerformanceFrequency(&Frequency); + QueryPerformanceCounter(&StartingTime); + first_use = 0; } QueryPerformanceCounter(&EndingTime); @@ -944,13 +993,13 @@ plat_get_ticks_common(void) uint32_t plat_get_ticks(void) { - return (uint32_t)(plat_get_ticks_common().QuadPart / 1000); + return (uint32_t) (plat_get_ticks_common().QuadPart / 1000); } uint32_t plat_get_micro_ticks(void) { - return (uint32_t)plat_get_ticks_common().QuadPart; + return (uint32_t) plat_get_ticks_common().QuadPart; } void @@ -959,61 +1008,58 @@ plat_delay_ms(uint32_t count) Sleep(count); } - /* Return the VIDAPI number for the given name. */ int plat_vidapi(char *name) { - int i; - /* Default/System is SDL Hardware. */ - if (!strcasecmp(name, "default") || !strcasecmp(name, "system")) return(1); + if (!strcasecmp(name, "default") || !strcasecmp(name, "system")) + return 1; /* If DirectDraw or plain SDL was specified, return SDL Software. */ - if (!strcasecmp(name, "ddraw") || !strcasecmp(name, "sdl")) return(1); + if (!strcasecmp(name, "ddraw") || !strcasecmp(name, "sdl")) + return 1; - for (i = 0; i < RENDERERS_NUM; i++) { - if (vid_apis[i].name && - !strcasecmp(vid_apis[i].name, name)) return(i); + for (uint8_t i = 0; i < RENDERERS_NUM; i++) { + if (vid_apis[i].name && !strcasecmp(vid_apis[i].name, name)) + return i; } /* Default value. */ - return(1); + return 1; } - /* Return the VIDAPI name for the given number. */ char * plat_vidapi_name(int api) { char *name = "default"; - switch(api) { - case 0: - name = "sdl_software"; - break; - case 1: - break; - case 2: - name = "sdl_opengl"; - break; - case 3: - name = "opengl_core"; - break; + switch (api) { + case 0: + name = "sdl_software"; + break; + case 1: + break; + case 2: + name = "sdl_opengl"; + break; + case 3: + name = "opengl_core"; + break; #ifdef USE_VNC - case 4: - name = "vnc"; - break; + case 4: + name = "vnc"; + break; #endif - default: - fatal("Unknown renderer: %i\n", api); - break; + default: + fatal("Unknown renderer: %i\n", api); + break; } - return(name); + return name; } - int plat_setvid(int api) { @@ -1027,144 +1073,143 @@ plat_setvid(int api) vid_api = api; if (vid_apis[vid_api].local) - ShowWindow(hwndRender, SW_SHOW); - else - ShowWindow(hwndRender, SW_HIDE); + ShowWindow(hwndRender, SW_SHOW); + else + ShowWindow(hwndRender, SW_HIDE); /* Initialize the (new) API. */ - i = vid_apis[vid_api].init((void *)hwndRender); + i = vid_apis[vid_api].init((void *) hwndRender); endblit(); - if (! i) return(0); + if (!i) + return 0; device_force_redraw(); vid_api_inited = 1; - return(1); + return 1; } - /* Tell the renderers about a new screen resolution. */ void plat_vidsize(int x, int y) { - if (!vid_api_inited || !vid_apis[vid_api].resize) return; + if (!vid_api_inited || !vid_apis[vid_api].resize) + return; startblit(); vid_apis[vid_api].resize(x, y); endblit(); } - void plat_vidapi_enable(int enable) { int i = 1; if (!vid_api_inited || !vid_apis[vid_api].enable) - return; + return; vid_apis[vid_api].enable(enable != 0); - if (! i) - return; + if (!i) + return; if (enable) - device_force_redraw(); + device_force_redraw(); } - int get_vidpause(void) { - return(vid_apis[vid_api].pause()); + return (vid_apis[vid_api].pause()); } - void plat_setfullscreen(int on) { RECT rect; - int temp_x, temp_y; - int dpi = win_get_dpi(hwndMain); + int temp_x; + int temp_y; + int dpi = win_get_dpi(hwndMain); /* Are we changing from the same state to the same state? */ if ((!!(on & 1)) == (!!video_fullscreen)) - return; + return; if (on && video_fullscreen_first) { - video_fullscreen |= 2; - if (ui_msgbox_header(MBX_INFO | MBX_DONTASK, (wchar_t *) IDS_2134, (wchar_t *) IDS_2052) == 10) { - video_fullscreen_first = 0; - config_save(); - } - video_fullscreen &= 1; + video_fullscreen |= 2; + if (ui_msgbox_header(MBX_INFO | MBX_DONTASK, (wchar_t *) IDS_2135, (wchar_t *) IDS_2052) == 10) { + video_fullscreen_first = 0; + config_save(); + } + video_fullscreen &= 1; } /* OK, claim the video. */ if (!(on & 2)) - win_mouse_close(); + win_mouse_close(); /* Close the current mode, and open the new one. */ video_fullscreen = (on & 1) | 2; if (vid_apis[vid_api].set_fs) - vid_apis[vid_api].set_fs(on & 1); + vid_apis[vid_api].set_fs(on & 1); if (!(on & 1)) { - plat_resize(scrnsz_x, scrnsz_y); - if (vid_resize) { - /* scale the screen base on DPI */ - if (!(vid_resize & 2) && window_remember) { - MoveWindow(hwndMain, window_x, window_y, window_w, window_h, TRUE); - GetClientRect(hwndMain, &rect); + plat_resize(scrnsz_x, scrnsz_y); + if (vid_resize) { + /* scale the screen base on DPI */ + if (!(vid_resize & 2) && window_remember) { + MoveWindow(hwndMain, window_x, window_y, window_w, window_h, TRUE); + GetClientRect(hwndMain, &rect); - temp_x = rect.right - rect.left + 1; - temp_y = rect.bottom - rect.top + 1 - (hide_status_bar ? 0 : sbar_height) - (hide_tool_bar ? 0 : tbar_height); - } else { - if (dpi_scale) { - temp_x = MulDiv((vid_resize & 2) ? fixed_size_x : unscaled_size_x, dpi, 96); - temp_y = MulDiv((vid_resize & 2) ? fixed_size_y : unscaled_size_y, dpi, 96); - } else { - temp_x = (vid_resize & 2) ? fixed_size_x : unscaled_size_x; - temp_y = (vid_resize & 2) ? fixed_size_y : unscaled_size_y; - } + temp_x = rect.right - rect.left + 1; + temp_y = rect.bottom - rect.top + 1 - (hide_status_bar ? 0 : sbar_height) - (hide_tool_bar ? 0 : tbar_height); + } else { + if (dpi_scale) { + temp_x = MulDiv((vid_resize & 2) ? fixed_size_x : unscaled_size_x, dpi, 96); + temp_y = MulDiv((vid_resize & 2) ? fixed_size_y : unscaled_size_y, dpi, 96); + } else { + temp_x = (vid_resize & 2) ? fixed_size_x : unscaled_size_x; + temp_y = (vid_resize & 2) ? fixed_size_y : unscaled_size_y; + } - /* Main Window. */ - if (vid_resize >= 2) - MoveWindow(hwndMain, window_x, window_y, window_w, window_h, TRUE); + /* Main Window. */ + if (vid_resize >= 2) + MoveWindow(hwndMain, window_x, window_y, window_w, window_h, TRUE); - ResizeWindowByClientArea(hwndMain, temp_x, temp_y + (hide_status_bar ? 0 : sbar_height) + (hide_tool_bar ? 0 : tbar_height)); - } + ResizeWindowByClientArea(hwndMain, temp_x, temp_y + (hide_status_bar ? 0 : sbar_height) + (hide_tool_bar ? 0 : tbar_height)); + } - /* Toolbar. */ - MoveWindow(hwndRebar, 0, 0, temp_x, tbar_height, TRUE); + /* Toolbar. */ + MoveWindow(hwndRebar, 0, 0, temp_x, tbar_height, TRUE); - /* Render window. */ - MoveWindow(hwndRender, 0, hide_tool_bar ? 0 : tbar_height, temp_x, temp_y, TRUE); + /* Render window. */ + MoveWindow(hwndRender, 0, hide_tool_bar ? 0 : tbar_height, temp_x, temp_y, TRUE); - /* Status bar. */ - GetClientRect(hwndMain, &rect); - MoveWindow(hwndSBAR, 0, rect.bottom - sbar_height, temp_x, sbar_height, TRUE); + /* Status bar. */ + GetClientRect(hwndMain, &rect); + MoveWindow(hwndSBAR, 0, rect.bottom - sbar_height, temp_x, sbar_height, TRUE); - if (mouse_capture) - ClipCursor(&rect); + if (mouse_capture) + ClipCursor(&rect); - scrnsz_x = (vid_resize & 2) ? fixed_size_x : unscaled_size_x; - scrnsz_y = (vid_resize & 2) ? fixed_size_y : unscaled_size_y; - } + scrnsz_x = (vid_resize & 2) ? fixed_size_x : unscaled_size_x; + scrnsz_y = (vid_resize & 2) ? fixed_size_y : unscaled_size_y; + } } video_fullscreen &= 1; video_force_resize_set(1); if (!(on & 1)) - atomic_flag_clear(&doresize); + atomic_store(&doresize_monitors[0], 1); win_mouse_init(); if (!(on & 2)) { - /* Release video and make it redraw the screen. */ - device_force_redraw(); + /* Release video and make it redraw the screen. */ + device_force_redraw(); - /* Send a CTRL break code so CTRL does not get stuck. */ - keyboard_input(0, 0x01D); + /* Send a CTRL break code so CTRL does not get stuck. */ + keyboard_input(0, 0x01D); } /* Finally, handle the host's mouse cursor. */ @@ -1172,75 +1217,77 @@ plat_setfullscreen(int on) show_cursor(video_fullscreen ? 0 : -1); if (!(on & 2)) { - /* This is needed for OpenGL. */ - plat_vidapi_enable(0); - plat_vidapi_enable(1); + /* This is needed for OpenGL. */ + plat_vidapi_enable(0); + plat_vidapi_enable(1); } } - void plat_vid_reload_options(void) { - if (!vid_api_inited || !vid_apis[vid_api].reload) - return; + if (!vid_api_inited || !vid_apis[vid_api].reload) + return; - vid_apis[vid_api].reload(); + vid_apis[vid_api].reload(); } - void plat_vidapi_reload(void) { vid_apis[vid_api].reload(); } - /* Sets up the program language before initialization. */ -uint32_t -plat_language_code(char* langcode) +uint32_t +plat_language_code(char *langcode) { - if (!strcmp(langcode, "system")) - return 0xFFFF; - - int len = mbstoc16s(NULL, langcode, 0) + 1; - wchar_t *temp = malloc(len * sizeof(wchar_t)); - mbstoc16s(temp, langcode, len); + if (!strcmp(langcode, "system")) + return 0xFFFF; - LCID lcid = LocaleNameToLCID((LPWSTR)temp, 0); + int len = mbstoc16s(NULL, langcode, 0) + 1; + wchar_t *temp = malloc(len * sizeof(wchar_t)); + mbstoc16s(temp, langcode, len); - free(temp); - return lcid; + LCID lcid = LocaleNameToLCID(temp, 0); + + free(temp); + return lcid; } /* Converts back the language code to LCID */ void -plat_language_code_r(uint32_t lcid, char* outbuf, int len) +plat_language_code_r(uint32_t lcid, char *outbuf, int len) { - if (lcid == 0xFFFF) - { - strcpy(outbuf, "system"); - return; - } - - wchar_t buffer[LOCALE_NAME_MAX_LENGTH + 1]; - LCIDToLocaleName(lcid, buffer, LOCALE_NAME_MAX_LENGTH, 0); - - c16stombs(outbuf, buffer, len); + if (lcid == 0xFFFF) { + strcpy(outbuf, "system"); + return; + } + + wchar_t buffer[LOCALE_NAME_MAX_LENGTH + 1]; + LCIDToLocaleName(lcid, buffer, LOCALE_NAME_MAX_LENGTH, 0); + + c16stombs(outbuf, buffer, len); +} + +void +plat_get_cpu_string(char *outbuf, uint8_t len) { + char cpu_string[] = "Unknown"; + strncpy(outbuf, cpu_string, len); } void take_screenshot(void) { startblit(); - screenshots++; + monitors[0].mon_screenshots++; endblit(); device_force_redraw(); } - /* LPARAM interface to plat_get_string(). */ -LPARAM win_get_string(int id) +LPARAM +win_get_string(int id) { wchar_t *ret; @@ -1248,16 +1295,22 @@ LPARAM win_get_string(int id) return ((LPARAM) ret); } - -void /* plat_ */ +void /* plat_ */ startblit(void) { WaitForSingleObject(ghMutex, INFINITE); } - -void /* plat_ */ +void /* plat_ */ endblit(void) { ReleaseMutex(ghMutex); } + +double +plat_get_dpi(void) +{ + UINT dpi = win_get_dpi(hwndRender); + + return ((double) dpi) / 96.0; +} diff --git a/src/win/win_about.c b/src/win/win_about.c index c508c7b3c..7ba55f73e 100644 --- a/src/win/win_about.c +++ b/src/win/win_about.c @@ -1,20 +1,21 @@ /* - * 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. + * 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. + * This file is part of the 86Box distribution. * - * Handle the About dialog. + * Handle the About dialog. * * * - * Authors: Miran Grca, - * Fred N. van Kempen, + * Authors: Miran Grca, + * Fred N. van Kempen, * - * Copyright 2016-2018 Miran Grca. - * Copyright 2017,2018 Fred N. van Kempen. + * Copyright 2016-2018 Miran Grca. + * Copyright 2017-2018 Fred N. van Kempen. + * Copyright 2021-2023 Jasmine Iwanek. */ #define UNICODE #define BITMAP WINDOWS_BITMAP @@ -32,36 +33,48 @@ #include <86box/win.h> #include <86box/version.h> - void AboutDialogCreate(HWND hwnd) { - int i; - TASKDIALOGCONFIG tdconfig = {0}; + int i; + TASKDIALOGCONFIG tdconfig = { 0 }; TASKDIALOG_BUTTON tdbuttons[] = { - {IDOK, EMU_SITE_W}, - {IDCANCEL, MAKEINTRESOURCE(IDS_2127)} + {IDOK, EMU_SITE_W }, + { IDCANCEL, MAKEINTRESOURCE(IDS_2128)} }; wchar_t emu_version[256]; - i = swprintf(emu_version, sizeof(emu_version), L"%ls v%ls", EMU_NAME_W, EMU_VERSION_FULL_W); + i = swprintf(emu_version, sizeof_w(emu_version), L"%ls v%ls", EMU_NAME_W, EMU_VERSION_FULL_W); #ifdef EMU_GIT_HASH - swprintf(&emu_version[i], sizeof(emu_version) - i, L" [%ls]", EMU_GIT_HASH_W); + i += swprintf(&emu_version[i], sizeof_w(emu_version) - i, L" [%ls]", EMU_GIT_HASH_W); #endif - tdconfig.cbSize = sizeof(tdconfig); - tdconfig.hwndParent = hwnd; - tdconfig.hInstance = hinstance; - tdconfig.dwCommonButtons = 0; - tdconfig.pszWindowTitle = MAKEINTRESOURCE(IDS_2124); - tdconfig.pszMainIcon = (PCWSTR) 10; +#if defined(__arm__) || defined(__TARGET_ARCH_ARM) +# define ARCH_STR L"arm" +#elif defined(__aarch64__) || defined(_M_ARM64) +# define ARCH_STR L"arm64" +#elif defined(__i386) || defined(__i386__) || defined(_M_IX86) +# define ARCH_STR L"i386" +#elif defined(__x86_64) || defined(__x86_64__) || defined(__amd64) || defined(_M_X64) +# define ARCH_STR L"x86_64" +#else +# define ARCH_STR L"unknown" +#endif + swprintf(&emu_version[i], sizeof_w(emu_version) - i, L" [%ls, %ls]", ARCH_STR, plat_get_string(IDS_DYNAREC)); + + tdconfig.cbSize = sizeof(tdconfig); + tdconfig.hwndParent = hwnd; + tdconfig.hInstance = hinstance; + tdconfig.dwCommonButtons = 0; + tdconfig.pszWindowTitle = MAKEINTRESOURCE(IDS_2125); + tdconfig.pszMainIcon = (PCWSTR) 10; tdconfig.pszMainInstruction = emu_version; - tdconfig.pszContent = MAKEINTRESOURCE(IDS_2126); - tdconfig.cButtons = ARRAYSIZE(tdbuttons); - tdconfig.pButtons = tdbuttons; - tdconfig.nDefaultButton = IDCANCEL; + tdconfig.pszContent = MAKEINTRESOURCE(IDS_2127); + tdconfig.cButtons = ARRAYSIZE(tdbuttons); + tdconfig.pButtons = tdbuttons; + tdconfig.nDefaultButton = IDCANCEL; TaskDialogIndirect(&tdconfig, &i, NULL, NULL); if (i == IDOK) - ShellExecute(hwnd, L"open", L"https://" EMU_SITE_W, NULL, NULL, SW_SHOW); + ShellExecute(hwnd, L"open", L"https://" EMU_SITE_W, NULL, NULL, SW_SHOW); } diff --git a/src/win/win_cdrom.c b/src/win/win_cdrom.c index 8a32df295..37b741c29 100644 --- a/src/win/win_cdrom.c +++ b/src/win/win_cdrom.c @@ -1,21 +1,20 @@ /* - * 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. + * 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. + * This file is part of the 86Box distribution. * - * Handle the platform-side of CDROM/ZIP/MO drives. + * Handle the platform-side of CDROM/ZIP/MO drives. * + * Authors: Miran Grca, + * Fred N. van Kempen, + * Jasmine Iwanek, * - * - * Authors: Sarah Walker, - * Miran Grca, - * Fred N. van Kempen, - * - * Copyright 2016-2018 Miran Grca. - * Copyright 2017,2018 Fred N. van Kempen. + * Copyright 2016-2018 Miran Grca. + * Copyright 2017-2018 Fred N. van Kempen. + * Copyright 2021-2023 Jasmine Iwanek. */ #define UNICODE #define BITMAP WINDOWS_BITMAP @@ -44,7 +43,6 @@ #include <86box/ui.h> #include <86box/win.h> - void cassette_mount(char *fn, uint8_t wp) { @@ -53,14 +51,13 @@ cassette_mount(char *fn, uint8_t wp) cassette_ui_writeprot = wp; pc_cas_set_fname(cassette, fn); if (fn != NULL) - memcpy(cassette_fname, fn, MIN(511, strlen(fn))); + memcpy(cassette_fname, fn, MIN(511, strlen(fn))); ui_sb_update_icon_state(SB_CASSETTE, (fn == NULL) ? 1 : 0); media_menu_update_cassette(); ui_sb_update_tip(SB_CASSETTE); config_save(); } - void cassette_eject(void) { @@ -72,9 +69,8 @@ cassette_eject(void) config_save(); } - void -cartridge_mount(uint8_t id, char *fn, uint8_t wp) +cartridge_mount(uint8_t id, char *fn, UNUSED(uint8_t wp)) { cart_close(id); cart_load(id, fn); @@ -84,7 +80,6 @@ cartridge_mount(uint8_t id, char *fn, uint8_t wp) config_save(); } - void cartridge_eject(uint8_t id) { @@ -95,7 +90,6 @@ cartridge_eject(uint8_t id) config_save(); } - void floppy_mount(uint8_t id, char *fn, uint8_t wp) { @@ -108,7 +102,6 @@ floppy_mount(uint8_t id, char *fn, uint8_t wp) config_save(); } - void floppy_eject(uint8_t id) { @@ -119,20 +112,19 @@ floppy_eject(uint8_t id) config_save(); } - void -plat_cdrom_ui_update(uint8_t id, uint8_t reload) +plat_cdrom_ui_update(uint8_t id, UNUSED(uint8_t reload)) { - cdrom_t *drv = &cdrom[id]; + const cdrom_t *drv = &cdrom[id]; if (drv->host_drive == 0) { - ui_sb_update_icon_state(SB_CDROM|id, 1); + ui_sb_update_icon_state(SB_CDROM | id, 1); } else { - ui_sb_update_icon_state(SB_CDROM|id, 0); + ui_sb_update_icon_state(SB_CDROM | id, 0); } media_menu_update_cdrom(id); - ui_sb_update_tip(SB_CDROM|id); + ui_sb_update_tip(SB_CDROM | id); } void @@ -141,18 +133,18 @@ cdrom_mount(uint8_t id, char *fn) cdrom[id].prev_host_drive = cdrom[id].host_drive; strcpy(cdrom[id].prev_image_path, cdrom[id].image_path); if (cdrom[id].ops && cdrom[id].ops->exit) - cdrom[id].ops->exit(&(cdrom[id])); + cdrom[id].ops->exit(&(cdrom[id])); cdrom[id].ops = NULL; memset(cdrom[id].image_path, 0, sizeof(cdrom[id].image_path)); cdrom_image_open(&(cdrom[id]), fn); /* Signal media change to the emulated machine. */ if (cdrom[id].insert) - cdrom[id].insert(cdrom[id].priv); + cdrom[id].insert(cdrom[id].priv); cdrom[id].host_drive = (strlen(cdrom[id].image_path) == 0) ? 0 : 200; if (cdrom[id].host_drive == 200) { - ui_sb_update_icon_state(SB_CDROM | id, 0); + ui_sb_update_icon_state(SB_CDROM | id, 0); } else { - ui_sb_update_icon_state(SB_CDROM | id, 1); + ui_sb_update_icon_state(SB_CDROM | id, 1); } media_menu_update_cdrom(id); ui_sb_update_tip(SB_CDROM | id); @@ -166,8 +158,8 @@ mo_eject(uint8_t id) mo_disk_close(dev); if (mo_drives[id].bus_type) { - /* Signal disk change to the emulated machine. */ - mo_insert(dev); + /* Signal disk change to the emulated machine. */ + mo_insert(dev); } ui_sb_update_icon_state(SB_MO | id, 1); @@ -176,7 +168,6 @@ mo_eject(uint8_t id) config_save(); } - void mo_mount(uint8_t id, char *fn, uint8_t wp) { @@ -194,7 +185,6 @@ mo_mount(uint8_t id, char *fn, uint8_t wp) config_save(); } - void mo_reload(uint8_t id) { @@ -202,13 +192,13 @@ mo_reload(uint8_t id) mo_disk_reload(dev); if (strlen(mo_drives[id].image_path) == 0) { - ui_sb_update_icon_state(SB_MO|id, 1); + ui_sb_update_icon_state(SB_MO | id, 1); } else { - ui_sb_update_icon_state(SB_MO|id, 0); + ui_sb_update_icon_state(SB_MO | id, 0); } media_menu_update_mo(id); - ui_sb_update_tip(SB_MO|id); + ui_sb_update_tip(SB_MO | id); config_save(); } @@ -220,8 +210,8 @@ zip_eject(uint8_t id) zip_disk_close(dev); if (zip_drives[id].bus_type) { - /* Signal disk change to the emulated machine. */ - zip_insert(dev); + /* Signal disk change to the emulated machine. */ + zip_insert(dev); } ui_sb_update_icon_state(SB_ZIP | id, 1); @@ -230,7 +220,6 @@ zip_eject(uint8_t id) config_save(); } - void zip_mount(uint8_t id, char *fn, uint8_t wp) { @@ -248,7 +237,6 @@ zip_mount(uint8_t id, char *fn, uint8_t wp) config_save(); } - void zip_reload(uint8_t id) { @@ -256,13 +244,13 @@ zip_reload(uint8_t id) zip_disk_reload(dev); if (strlen(zip_drives[id].image_path) == 0) { - ui_sb_update_icon_state(SB_ZIP|id, 1); + ui_sb_update_icon_state(SB_ZIP | id, 1); } else { - ui_sb_update_icon_state(SB_ZIP|id, 0); + ui_sb_update_icon_state(SB_ZIP | id, 0); } media_menu_update_zip(id); - ui_sb_update_tip(SB_ZIP|id); + ui_sb_update_tip(SB_ZIP | id); config_save(); } diff --git a/src/win/win_crashdump.c b/src/win/win_crashdump.c deleted file mode 100644 index e1123c1e5..000000000 --- a/src/win/win_crashdump.c +++ /dev/null @@ -1,245 +0,0 @@ -/* - * 86Box A hypervisor and IBM PC system emulator that specializes in - * running old operating systems and software designed for IBM - * PC systems and compatibles from 1981 through fairly recent - * system designs based on the PCI bus. - * - * This file is part of the 86Box distribution. - * - * Handle generation of crash-dump reports. - * - * - * - * Authors: Riley - * Miran Grca, - * Fred N. van Kempen, - * - * Copyright 2016,2017 Riley. - * Copyright 2016,2017 Miran Grca. - * Copyright 2017 Fred N. van Kempen. - */ -#define _WIN32_WINNT 0x0501 -#include -#include -#include -#include -#include -#include -#include <86box/86box.h> -#include <86box/plat.h> -#include <86box/win.h> - - -#define ExceptionHandlerBufferSize (10240) - - -static PVOID hExceptionHandler; -static char *ExceptionHandlerBuffer, - *CurrentBufferPointer; - - -LONG CALLBACK MakeCrashDump(PEXCEPTION_POINTERS ExceptionInfo) -{ - SYSTEMTIME SystemTime; - HANDLE hDumpFile; - char *BufPtr; - - /* - * Win32-specific functions will be used wherever possible, - * just in case the C stdlib-equivalents try to allocate - * memory. - * (The Win32-specific functions are generally just wrappers - * over NT system calls anyway.) - */ - if ((ExceptionInfo->ExceptionRecord->ExceptionCode >> 28) != 0xC) { - /* - * ExceptionCode is not a fatal exception (high 4b of - * ntstatus = 0xC) Not going to crash, let's not make - * a crash dump. - */ - return(EXCEPTION_CONTINUE_SEARCH); - } - - /* - * So, the program is about to crash. Oh no what do? - * Let's create a crash dump file as a debugging-aid. - * - * First, get the path to the executable. - */ - GetModuleFileName(NULL,ExceptionHandlerBuffer,ExceptionHandlerBufferSize); - if (GetLastError() != ERROR_SUCCESS) { - /* Could not get full path, create in current directory. */ - BufPtr = ExceptionHandlerBuffer; - } else { - /* - * Walk through the string backwards looking for the - * last backslash, so as to remove the "86Box.exe" - * filename from the string. - */ - BufPtr = &ExceptionHandlerBuffer[strlen(ExceptionHandlerBuffer)]; - for (; BufPtr > ExceptionHandlerBuffer; BufPtr--) { - if (BufPtr[0] == '\\') { - /* Found backslash, terminate the string after it. */ - BufPtr[1] = 0; - break; - } - } - - BufPtr = &ExceptionHandlerBuffer[strlen(ExceptionHandlerBuffer)]; - } - - /* - * What would a good filename be? - * - * It should contain the current date and time so as - * to be (hopefully!) unique. - */ - GetSystemTime(&SystemTime); - sprintf(CurrentBufferPointer, - "86box-%d%02d%02d-%02d-%02d-%02d-%03d.dmp", - SystemTime.wYear, - SystemTime.wMonth, - SystemTime.wDay, - SystemTime.wHour, - SystemTime.wMinute, - SystemTime.wSecond, - SystemTime.wMilliseconds); - - /* Now the filename is in the buffer, the file can be created. */ - hDumpFile = CreateFile( - ExceptionHandlerBuffer, // The filename of the file to open. - GENERIC_WRITE, // The permissions to request. - 0, // Make sure other processes can't - // touch the crash dump at all - // while it's open. - NULL, // Leave the security descriptor - // undefined, it doesn't matter. - OPEN_ALWAYS, // Opens the file if it exists, - // creates a new file if it doesn't. - FILE_ATTRIBUTE_NORMAL, // File attributes / etc don't matter. - NULL); // A template file is not being used. - - /* Check to make sure the file was actually created. */ - if (hDumpFile == INVALID_HANDLE_VALUE) { - /* CreateFile() failed, so just do nothing more. */ - return(EXCEPTION_CONTINUE_SEARCH); - } - - /* - * Write the data we were passed out in a human-readable format. - * - * Get the name of the module where the exception occurred. - */ - HMODULE hMods[1024]; - MODULEINFO modInfo; - HMODULE ipModule = 0; - DWORD cbNeeded; - - /* Try to get a list of all loaded modules. */ - if (EnumProcessModules(GetCurrentProcess(), - hMods, sizeof(hMods), &cbNeeded)) { - /* Got it, now walk through all modules.. */ - for (DWORD i = 0; i < (cbNeeded / sizeof(HMODULE)); i++) { - /* For each module, get the module information. */ - GetModuleInformation(GetCurrentProcess(), - hMods[i], &modInfo, sizeof(MODULEINFO)); - /* If the exception address is in the range of this module.. */ - if ( (ExceptionInfo->ExceptionRecord->ExceptionAddress >= modInfo.lpBaseOfDll) && - (ExceptionInfo->ExceptionRecord->ExceptionAddress < (void*)((char*)modInfo.lpBaseOfDll + modInfo.SizeOfImage))) { - /* ...this is the module we're looking for! */ - ipModule = hMods[i]; - break; - } - } - } - - /* Start to put the crash-dump string into the buffer. */ - sprintf(ExceptionHandlerBuffer, - "#\r\n# %s\r\n#\r\n" - "# Crash on %d-%02d-%02d at %02d:%02d:%02d.%03d\r\n#\r\n" - "\r\n" - "Exception details:\r\n" - " NTSTATUS code: 0x%08lx\r\n Address: 0x%p", - emu_version, - SystemTime.wYear, SystemTime.wMonth, SystemTime.wDay, - SystemTime.wHour, SystemTime.wMinute, SystemTime.wSecond, - SystemTime.wMilliseconds, - ExceptionInfo->ExceptionRecord->ExceptionCode, - (void *)ExceptionInfo->ExceptionRecord->ExceptionAddress); - - /* - * If we found the correct module, get the full path to - * the module the exception occured at and include it. - */ - BufPtr = &ExceptionHandlerBuffer[strlen(ExceptionHandlerBuffer)]; - if (ipModule != 0) { - sprintf(BufPtr," ["); - GetModuleFileName(ipModule, &BufPtr[2], - ExceptionHandlerBufferSize - strlen(ExceptionHandlerBuffer)); - if (GetLastError() == ERROR_SUCCESS) { - BufPtr = &ExceptionHandlerBuffer[strlen(ExceptionHandlerBuffer)]; - sprintf(BufPtr,"]"); - BufPtr += 1; - } - } - - sprintf(BufPtr, - "\r\nNumber of parameters: %lu\r\nException parameters: ", - ExceptionInfo->ExceptionRecord->NumberParameters); - - for (int i = 0; i < ExceptionInfo->ExceptionRecord->NumberParameters; i++) { - BufPtr = &ExceptionHandlerBuffer[strlen(ExceptionHandlerBuffer)]; - sprintf(BufPtr,"0x%p ", - (void *)ExceptionInfo->ExceptionRecord->ExceptionInformation[i]); - } - BufPtr = &ExceptionHandlerBuffer[strlen(ExceptionHandlerBuffer) - 1]; - -#if defined(__i386__) && !defined(__x86_64) - PCONTEXT Registers = ExceptionInfo->ContextRecord; - - /* This binary is being compiled for x86, include a register dump. */ - sprintf(BufPtr, - "\r\n\r\nRegister dump:\r\n\r\n" - "EIP:0x%08lx\r\n" - "EAX:0x%08lx EBX:0x%08lx ECX:0x%08lx EDX:0x%08lx\r\n" - "EBP:0x%08lx ESP:0x%08lx ESI:0x%08lx EDI:0x%08lx\r\n\r\n", - Registers->Eip, - Registers->Eax, Registers->Ebx, Registers->Ecx, Registers->Edx, - Registers->Ebp, Registers->Esp, Registers->Esi, Registers->Edi); -#else - /* Register dump not supported by this architecture. */ - /* (MinGW headers seem to lack the x64 CONTEXT structure definition) */ - sprintf(BufPtr, "\r\n"); -#endif - - /* Write the string to disk. */ - WriteFile(hDumpFile, ExceptionHandlerBuffer, - strlen(ExceptionHandlerBuffer), NULL, NULL); - - /* Close the file. */ - CloseHandle(hDumpFile); - - /* Return, therefore causing the crash. */ - return(EXCEPTION_CONTINUE_SEARCH); -} - - -void -InitCrashDump(void) -{ - /* - * An exception handler should not allocate memory, - * so allocate 10kb for it to use if it gets called, - * an amount which should be more than enough. - */ - ExceptionHandlerBuffer = malloc(ExceptionHandlerBufferSize); - CurrentBufferPointer = ExceptionHandlerBuffer; - - /* - * Register the exception handler. - * Zero first argument means this exception handler gets - * called last, therefore, crash dump is only made, when - * a crash is going to happen. - */ - hExceptionHandler = AddVectoredExceptionHandler(0, MakeCrashDump); -} diff --git a/src/win/win_devconf.c b/src/win/win_devconf.c index c4de7d90b..92ab6b614 100644 --- a/src/win/win_devconf.c +++ b/src/win/win_devconf.c @@ -1,20 +1,21 @@ /* - * 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. + * 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. + * This file is part of the 86Box distribution. * - * Windows device configuration dialog implementation. + * Windows device configuration dialog implementation. * * * - * Authors: Sarah Walker, - * Miran Grca, + * Authors: Sarah Walker, + * Miran Grca, * - * Copyright 2008-2018 Sarah Walker. - * Copyright 2016-2018 Miran Grca. + * Copyright 2008-2018 Sarah Walker. + * Copyright 2016-2018 Miran Grca. + * Copyright 2021-2023 Jasmine Iwanek. */ #include #include @@ -22,675 +23,796 @@ #include #include #include <86box/86box.h> +#include <86box/ini.h> #include <86box/config.h> #include <86box/device.h> #include <86box/plat.h> +#include <86box/mem.h> +#include <86box/rom.h> #include <86box/midi_rtmidi.h> #include <86box/ui.h> #include <86box/win.h> #include - static device_context_t config_device; static uint8_t deviceconfig_changed = 0; - +static int combo_to_struct[256]; #if defined(__amd64__) || defined(__aarch64__) static LRESULT CALLBACK #else static BOOL CALLBACK #endif -deviceconfig_dlgproc(HWND hdlg, UINT message, WPARAM wParam, LPARAM lParam) +deviceconfig_dlgproc(HWND hdlg, UINT message, WPARAM wParam, UNUSED(LPARAM lParam)) { HWND h; - int val_int, id, c, d, num; - int changed, cid; - const device_config_t *config; + int val_int; + int id; + int c; + int d; + int p; + int q; +#ifdef USE_RTMIDI + int num; +#endif + int changed; + int cid; + const device_config_t *config; const device_config_selection_t *selection; - char s[512], file_filter[512]; - char *str; - wchar_t ws[512], *wstr; - LPTSTR lptsTemp; + const device_config_bios_t *bios; + char s[512]; + char file_filter[512]; + const char *str; + const char *val_str; + wchar_t ws[512]; + wchar_t *wstr; + LPTSTR lptsTemp; config = config_device.dev->config; switch (message) { - case WM_INITDIALOG: - id = IDC_CONFIG_BASE; - config = config_device.dev->config; + case WM_INITDIALOG: + id = IDC_CONFIG_BASE; + config = config_device.dev->config; - lptsTemp = (LPTSTR) malloc(512); + lptsTemp = (LPTSTR) malloc(512); + memset(combo_to_struct, 0, 256 * sizeof(int)); - while (config->type != -1) { - selection = config->selection; - h = GetDlgItem(hdlg, id); + while (config->type != -1) { + selection = config->selection; + bios = config->bios; + h = GetDlgItem(hdlg, id); - switch (config->type) { - case CONFIG_BINARY: - val_int = config_get_int((char *) config_device.name, - (char *) config->name, config->default_int); + switch (config->type) { + case CONFIG_BINARY: + val_int = config_get_int((char *) config_device.name, + (char *) config->name, config->default_int); - SendMessage(h, BM_SETCHECK, val_int, 0); + SendMessage(h, BM_SETCHECK, val_int, 0); - id++; - break; - case CONFIG_SELECTION: - val_int = config_get_int((char *) config_device.name, - (char *) config->name, config->default_int); + id++; + break; + case CONFIG_SELECTION: + val_int = config_get_int((char *) config_device.name, + (char *) config->name, config->default_int); - c = 0; - while (selection->description && selection->description[0]) { - mbstowcs(lptsTemp, selection->description, - strlen(selection->description) + 1); - SendMessage(h, CB_ADDSTRING, 0, (LPARAM)(LPCSTR)lptsTemp); - if (val_int == selection->value) - SendMessage(h, CB_SETCURSEL, c, 0); - selection++; - c++; - } + c = 0; + while (selection && selection->description && selection->description[0]) { + mbstowcs(lptsTemp, selection->description, + strlen(selection->description) + 1); + SendMessage(h, CB_ADDSTRING, 0, (LPARAM) (LPCSTR) lptsTemp); + if (val_int == selection->value) + SendMessage(h, CB_SETCURSEL, c, 0); + selection++; + c++; + } - id += 2; - break; - case CONFIG_MIDI: - val_int = config_get_int((char *) config_device.name, - (char *) config->name, config->default_int); + id += 2; + break; + case CONFIG_BIOS: + val_str = config_get_string((char *) config_device.name, + (char *) config->name, (char *) config->default_string); - num = rtmidi_get_num_devs(); - for (c = 0; c < num; c++) { - rtmidi_get_dev_name(c, s); - mbstowcs(lptsTemp, s, strlen(s) + 1); - SendMessage(h, CB_ADDSTRING, 0, (LPARAM)(LPCSTR)lptsTemp); - if (val_int == c) - SendMessage(h, CB_SETCURSEL, c, 0); - } + c = 0; + q = 0; + while (bios && (bios->files_no > 0)) { + mbstowcs(lptsTemp, bios->name, strlen(bios->name) + 1); + p = 0; + for (d = 0; d < bios->files_no; d++) + p += !!rom_present(bios->files[d]); + if (p == bios->files_no) { + SendMessage(h, CB_ADDSTRING, 0, (LPARAM) (LPCSTR) lptsTemp); + if (!strcmp(val_str, bios->internal_name)) + SendMessage(h, CB_SETCURSEL, c, 0); + combo_to_struct[c] = q; + c++; + } + q++; + bios++; + } - id += 2; - break; - case CONFIG_MIDI_IN: - val_int = config_get_int((char *) config_device.name, - (char *) config->name, config->default_int); + id += 2; + break; +#ifdef USE_RTMIDI + case CONFIG_MIDI_OUT: + val_int = config_get_int((char *) config_device.name, + (char *) config->name, config->default_int); - num = rtmidi_in_get_num_devs(); - for (c = 0; c < num; c++) { - rtmidi_in_get_dev_name(c, s); - mbstowcs(lptsTemp, s, strlen(s) + 1); - SendMessage(h, CB_ADDSTRING, 0, (LPARAM)(LPCSTR)lptsTemp); - if (val_int == c) - SendMessage(h, CB_SETCURSEL, c, 0); - } + num = rtmidi_out_get_num_devs(); + for (c = 0; c < num; c++) { + rtmidi_out_get_dev_name(c, s); + mbstowcs(lptsTemp, s, strlen(s) + 1); + SendMessage(h, CB_ADDSTRING, 0, (LPARAM) (LPCSTR) lptsTemp); + if (val_int == c) + SendMessage(h, CB_SETCURSEL, c, 0); + } - id += 2; - break; - case CONFIG_SPINNER: - val_int = config_get_int((char *) config_device.name, - (char *) config->name, config->default_int); + id += 2; + break; + case CONFIG_MIDI_IN: + val_int = config_get_int((char *) config_device.name, + (char *) config->name, config->default_int); - _swprintf(ws, L"%i", val_int); - SendMessage(h, WM_SETTEXT, 0, (LPARAM)ws); + num = rtmidi_in_get_num_devs(); + for (c = 0; c < num; c++) { + rtmidi_in_get_dev_name(c, s); + mbstowcs(lptsTemp, s, strlen(s) + 1); + SendMessage(h, CB_ADDSTRING, 0, (LPARAM) (LPCSTR) lptsTemp); + if (val_int == c) + SendMessage(h, CB_SETCURSEL, c, 0); + } - id += 2; - break; - case CONFIG_FNAME: - wstr = config_get_wstring((char *) config_device.name, - (char *) config->name, 0); - if (wstr) - SendMessage(h, WM_SETTEXT, 0, (LPARAM)wstr); - id += 3; - break; - case CONFIG_HEX16: - val_int = config_get_hex16((char *) config_device.name, - (char *) config->name, config->default_int); + id += 2; + break; +#endif + case CONFIG_SPINNER: + val_int = config_get_int((char *) config_device.name, + (char *) config->name, config->default_int); - c = 0; - while (selection->description && selection->description[0]) { - mbstowcs(lptsTemp, selection->description, - strlen(selection->description) + 1); - SendMessage(h, CB_ADDSTRING, 0, (LPARAM)(LPCSTR)lptsTemp); - if (val_int == selection->value) - SendMessage(h, CB_SETCURSEL, c, 0); - selection++; - c++; - } + _swprintf(ws, L"%i", val_int); + SendMessage(h, WM_SETTEXT, 0, (LPARAM) ws); - id += 2; - break; - case CONFIG_HEX20: - val_int = config_get_hex20((char *) config_device.name, - (char *) config->name, config->default_int); + id += 2; + break; + case CONFIG_FNAME: + case CONFIG_STRING: + wstr = config_get_wstring((char *) config_device.name, + (char *) config->name, 0); + if (wstr) + SendMessage(h, WM_SETTEXT, 0, (LPARAM) wstr); + id += 3; + break; + case CONFIG_HEX16: + val_int = config_get_hex16((char *) config_device.name, + (char *) config->name, config->default_int); - c = 0; - while (selection->description && selection->description[0]) { - mbstowcs(lptsTemp, selection->description, - strlen(selection->description) + 1); - SendMessage(h, CB_ADDSTRING, 0, (LPARAM)(LPCSTR)lptsTemp); - if (val_int == selection->value) - SendMessage(h, CB_SETCURSEL, c, 0); - selection++; - c++; - } + c = 0; + while (selection && selection->description && selection->description[0]) { + mbstowcs(lptsTemp, selection->description, + strlen(selection->description) + 1); + SendMessage(h, CB_ADDSTRING, 0, (LPARAM) (LPCSTR) lptsTemp); + if (val_int == selection->value) + SendMessage(h, CB_SETCURSEL, c, 0); + selection++; + c++; + } - id += 2; - break; - } - config++; - } - free(lptsTemp); - return TRUE; - case WM_COMMAND: - cid = LOWORD(wParam); - if (cid == IDOK) { - id = IDC_CONFIG_BASE; - config = config_device.dev->config; - changed = 0; - char s[512]; + id += 2; + break; + case CONFIG_HEX20: + val_int = config_get_hex20((char *) config_device.name, + (char *) config->name, config->default_int); - while (config->type != -1) { - const device_config_selection_t *selection = config->selection; - h = GetDlgItem(hdlg, id); + c = 0; + while (selection && selection->description && selection->description[0]) { + mbstowcs(lptsTemp, selection->description, + strlen(selection->description) + 1); + SendMessage(h, CB_ADDSTRING, 0, (LPARAM) (LPCSTR) lptsTemp); + if (val_int == selection->value) + SendMessage(h, CB_SETCURSEL, c, 0); + selection++; + c++; + } - switch (config->type) { - case CONFIG_BINARY: - val_int = config_get_int((char *) config_device.name, - (char *) config->name, config->default_int); + id += 2; + break; + } + config++; + } + free(lptsTemp); + return TRUE; + case WM_COMMAND: + cid = LOWORD(wParam); + if (cid == IDOK) { + id = IDC_CONFIG_BASE; + config = config_device.dev->config; + changed = 0; + char s[512]; - if (val_int != SendMessage(h, BM_GETCHECK, 0, 0)) - changed = 1; + while (config->type != -1) { + const device_config_selection_t *selection = config->selection; + h = GetDlgItem(hdlg, id); - id++; - break; - case CONFIG_SELECTION: - val_int = config_get_int((char *) config_device.name, - (char *) config->name, config->default_int); + switch (config->type) { + case CONFIG_BINARY: + val_int = config_get_int((char *) config_device.name, + (char *) config->name, config->default_int); - c = SendMessage(h, CB_GETCURSEL, 0, 0); + if (val_int != SendMessage(h, BM_GETCHECK, 0, 0)) + changed = 1; - for (; c > 0; c--) - selection++; + id++; + break; + case CONFIG_SELECTION: + val_int = config_get_int((char *) config_device.name, + (char *) config->name, config->default_int); - if (val_int != selection->value) - changed = 1; + c = SendMessage(h, CB_GETCURSEL, 0, 0); - id += 2; - break; - case CONFIG_MIDI: - val_int = config_get_int((char *) config_device.name, - (char *) config->name, config->default_int); + for (; c > 0; c--) + selection++; - c = SendMessage(h, CB_GETCURSEL, 0, 0); + if (val_int != selection->value) + changed = 1; - if (val_int != c) - changed = 1; + id += 2; + break; + case CONFIG_BIOS: + bios = config->bios; - id += 2; - break; - case CONFIG_MIDI_IN: - val_int = config_get_int((char *) config_device.name, - (char *) config->name, config->default_int); + val_str = config_get_string((char *) config_device.name, + (char *) config->name, (char *) config->default_string); - c = SendMessage(h, CB_GETCURSEL, 0, 0); + c = combo_to_struct[SendMessage(h, CB_GETCURSEL, 0, 0)]; - if (val_int != c) - changed = 1; + for (; c > 0; c--) + bios++; - id += 2; - break; - case CONFIG_FNAME: - str = config_get_string((char *) config_device.name, - (char *) config->name, (char*)""); - SendMessage(h, WM_GETTEXT, 511, (LPARAM)s); - if (strcmp(str, s)) - changed = 1; + if (strcmp(val_str, bios->internal_name)) + changed = 1; - id += 3; - break; - case CONFIG_SPINNER: - val_int = config_get_int((char *) config_device.name, - (char *) config->name, config->default_int); - if (val_int > config->spinner.max) - val_int = config->spinner.max; - else if (val_int < config->spinner.min) - val_int = config->spinner.min; + id += 2; + break; + case CONFIG_MIDI_OUT: + val_int = config_get_int((char *) config_device.name, + (char *) config->name, config->default_int); - SendMessage(h, WM_GETTEXT, 79, (LPARAM)ws); - wcstombs(s, ws, 512); - sscanf(s, "%i", &c); + c = SendMessage(h, CB_GETCURSEL, 0, 0); - if (val_int != c) - changed = 1; + if (val_int != c) + changed = 1; - id += 2; - break; - case CONFIG_HEX16: - val_int = config_get_hex16((char *) config_device.name, - (char *) config->name, config->default_int); + id += 2; + break; + case CONFIG_MIDI_IN: + val_int = config_get_int((char *) config_device.name, + (char *) config->name, config->default_int); - c = SendMessage(h, CB_GETCURSEL, 0, 0); + c = SendMessage(h, CB_GETCURSEL, 0, 0); - for (; c > 0; c--) - selection++; + if (val_int != c) + changed = 1; - if (val_int != selection->value) - changed = 1; + id += 2; + break; + case CONFIG_FNAME: + case CONFIG_STRING: + str = config_get_string((char *) config_device.name, + (char *) config->name, (char *) ""); + SendMessage(h, WM_GETTEXT, 511, (LPARAM) s); + if (strcmp(str, s)) + changed = 1; - id += 2; - break; - case CONFIG_HEX20: - val_int = config_get_hex20((char *) config_device.name, - (char *) config->name, config->default_int); + id += 3; + break; + case CONFIG_SPINNER: + val_int = config_get_int((char *) config_device.name, + (char *) config->name, config->default_int); + if (val_int > config->spinner.max) + val_int = config->spinner.max; + else if (val_int < config->spinner.min) + val_int = config->spinner.min; - c = SendMessage(h, CB_GETCURSEL, 0, 0); + SendMessage(h, WM_GETTEXT, 79, (LPARAM) ws); + wcstombs(s, ws, 512); + sscanf(s, "%i", &c); - for (; c > 0; c--) - selection++; + if (val_int != c) + changed = 1; - if (val_int != selection->value) - changed = 1; + id += 2; + break; + case CONFIG_HEX16: + val_int = config_get_hex16((char *) config_device.name, + (char *) config->name, config->default_int); - id += 2; - break; - } - config++; - } + c = SendMessage(h, CB_GETCURSEL, 0, 0); - if (!changed) { - deviceconfig_changed = 0; - EndDialog(hdlg, 0); - return TRUE; - } + for (; c > 0; c--) + selection++; - deviceconfig_changed = 1; + if (val_int != selection->value) + changed = 1; - id = IDC_CONFIG_BASE; - config = config_device.dev->config; + id += 2; + break; + case CONFIG_HEX20: + val_int = config_get_hex20((char *) config_device.name, + (char *) config->name, config->default_int); - while (config->type != -1) { - selection = config->selection; - h = GetDlgItem(hdlg, id); + c = SendMessage(h, CB_GETCURSEL, 0, 0); - switch (config->type) { - case CONFIG_BINARY: - config_set_int((char *) config_device.name, - (char *) config->name, SendMessage(h, BM_GETCHECK, 0, 0)); + for (; c > 0; c--) + selection++; - id++; - break; - case CONFIG_SELECTION: - c = SendMessage(h, CB_GETCURSEL, 0, 0); - for (; c > 0; c--) - selection++; - config_set_int((char *) config_device.name, (char *) config->name, selection->value); + if (val_int != selection->value) + changed = 1; - id += 2; - break; - case CONFIG_MIDI: - c = SendMessage(h, CB_GETCURSEL, 0, 0); - config_set_int((char *) config_device.name, (char *) config->name, c); + id += 2; + break; + } + config++; + } - id += 2; - break; - case CONFIG_MIDI_IN: - c = SendMessage(h, CB_GETCURSEL, 0, 0); - config_set_int((char *) config_device.name, (char *) config->name, c); + if (!changed) { + deviceconfig_changed = 0; + EndDialog(hdlg, 0); + return TRUE; + } - id += 2; - break; - case CONFIG_FNAME: - SendMessage(h, WM_GETTEXT, 511, (LPARAM)ws); - config_set_wstring((char *) config_device.name, (char *) config->name, ws); + deviceconfig_changed = 1; - id += 3; - break; - case CONFIG_SPINNER: - SendMessage(h, WM_GETTEXT, 79, (LPARAM)ws); - wcstombs(s, ws, 512); - sscanf(s, "%i", &c); - if (c > config->spinner.max) - c = config->spinner.max; - else if (c < config->spinner.min) - c = config->spinner.min; + id = IDC_CONFIG_BASE; + config = config_device.dev->config; - config_set_int((char *) config_device.name, (char *) config->name, c); + while (config->type != -1) { + selection = config->selection; + h = GetDlgItem(hdlg, id); - id += 2; - break; - case CONFIG_HEX16: - c = SendMessage(h, CB_GETCURSEL, 0, 0); - for (; c > 0; c--) - selection++; - config_set_hex16((char *) config_device.name, (char *) config->name, selection->value); + switch (config->type) { + case CONFIG_BINARY: + config_set_int((char *) config_device.name, + (char *) config->name, SendMessage(h, BM_GETCHECK, 0, 0)); - id += 2; - break; - case CONFIG_HEX20: - c = SendMessage(h, CB_GETCURSEL, 0, 0); - for (; c > 0; c--) - selection++; - config_set_hex20((char *) config_device.name, (char *) config->name, selection->value); + id++; + break; + case CONFIG_SELECTION: + c = SendMessage(h, CB_GETCURSEL, 0, 0); + for (; c > 0; c--) + selection++; + config_set_int((char *) config_device.name, (char *) config->name, selection->value); - id += 2; - break; - } - config++; - } + id += 2; + break; + case CONFIG_BIOS: + bios = config->bios; + c = combo_to_struct[SendMessage(h, CB_GETCURSEL, 0, 0)]; + for (; c > 0; c--) + bios++; + config_set_string((char *) config_device.name, (char *) config->name, (char *) bios->internal_name); - EndDialog(hdlg, 0); - return TRUE; - } else if (cid == IDCANCEL) { - deviceconfig_changed = 0; - EndDialog(hdlg, 0); - return TRUE; - } else { - id = IDC_CONFIG_BASE; - while (config->type != -1) { - switch (config->type) { - case CONFIG_BINARY: - id++; - break; - case CONFIG_SELECTION: - case CONFIG_MIDI: - case CONFIG_MIDI_IN: - case CONFIG_SPINNER: - id += 2; - break; - case CONFIG_FNAME: - if (cid == id+1) { - s[0] = 0; - h = GetDlgItem(hdlg, id); - SendMessage(h, WM_GETTEXT, 511, (LPARAM)s); - file_filter[0] = 0; + id += 2; + break; + case CONFIG_MIDI_OUT: + c = SendMessage(h, CB_GETCURSEL, 0, 0); + config_set_int((char *) config_device.name, (char *) config->name, c); - strcat(file_filter, config->file_filter); - strcat(file_filter, "|All files (*.*)|*.*|"); - mbstowcs(ws, file_filter, strlen(file_filter) + 1); - d = strlen(file_filter); + id += 2; + break; + case CONFIG_MIDI_IN: + c = SendMessage(h, CB_GETCURSEL, 0, 0); + config_set_int((char *) config_device.name, (char *) config->name, c); - /* replace | with \0 */ - for (c = 0; c < d; ++c) { - if (ws[c] == L'|') - ws[c] = 0; - } + id += 2; + break; + case CONFIG_FNAME: + case CONFIG_STRING: + SendMessage(h, WM_GETTEXT, 511, (LPARAM) ws); + config_set_wstring((char *) config_device.name, (char *) config->name, ws); - if (!file_dlg(hdlg, ws, s, NULL, 0)) - SendMessage(h, WM_SETTEXT, 0, (LPARAM)wopenfilestring); - } - break; - } - config++; - } - } - break; + id += 3; + break; + case CONFIG_SPINNER: + SendMessage(h, WM_GETTEXT, 79, (LPARAM) ws); + wcstombs(s, ws, 512); + sscanf(s, "%i", &c); + if (c > config->spinner.max) + c = config->spinner.max; + else if (c < config->spinner.min) + c = config->spinner.min; + + config_set_int((char *) config_device.name, (char *) config->name, c); + + id += 2; + break; + case CONFIG_HEX16: + c = SendMessage(h, CB_GETCURSEL, 0, 0); + for (; c > 0; c--) + selection++; + config_set_hex16((char *) config_device.name, (char *) config->name, selection->value); + + id += 2; + break; + case CONFIG_HEX20: + c = SendMessage(h, CB_GETCURSEL, 0, 0); + for (; c > 0; c--) + selection++; + config_set_hex20((char *) config_device.name, (char *) config->name, selection->value); + + id += 2; + break; + } + config++; + } + + EndDialog(hdlg, 0); + return TRUE; + } else if (cid == IDCANCEL) { + deviceconfig_changed = 0; + EndDialog(hdlg, 0); + return TRUE; + } else { + id = IDC_CONFIG_BASE; + while (config->type != -1) { + switch (config->type) { + case CONFIG_BINARY: + id++; + break; + case CONFIG_SELECTION: + case CONFIG_HEX16: + case CONFIG_HEX20: + case CONFIG_BIOS: + case CONFIG_MIDI_OUT: + case CONFIG_MIDI_IN: + case CONFIG_SPINNER: + case CONFIG_STRING: + id += 2; + break; + case CONFIG_FNAME: + if (cid == id + 1) { + s[0] = 0; + h = GetDlgItem(hdlg, id); + SendMessage(h, WM_GETTEXT, 511, (LPARAM) s); + file_filter[0] = 0; + + strcat(file_filter, config->file_filter); + strcat(file_filter, "|All files (*.*)|*.*|"); + mbstowcs(ws, file_filter, strlen(file_filter) + 1); + d = strlen(file_filter); + + /* replace | with \0 */ + for (c = 0; c < d; ++c) { + if (ws[c] == L'|') + ws[c] = 0; + } + + if (!file_dlg(hdlg, ws, s, NULL, 0)) + SendMessage(h, WM_SETTEXT, 0, (LPARAM) wopenfilestring); + } + break; + } + config++; + } + } + break; } return FALSE; } - uint8_t deviceconfig_inst_open(HWND hwnd, const device_t *device, int inst) { const device_config_t *config = device->config; - uint16_t *data_block; - uint16_t *data; - DLGTEMPLATE *dlg; - DLGITEMTEMPLATE *item; + uint16_t *data_block; + uint16_t *data; + DLGTEMPLATE *dlg; + DLGITEMTEMPLATE *item; data_block = malloc(16384); - dlg = (DLGTEMPLATE *)data_block; - int y = 10; - int id = IDC_CONFIG_BASE; + dlg = (DLGTEMPLATE *) data_block; + int y = 10; + int id = IDC_CONFIG_BASE; deviceconfig_changed = 0; memset(data_block, 0, 16384); dlg->style = DS_SETFONT | DS_MODALFRAME | DS_FIXEDSYS | WS_POPUP | WS_CAPTION | WS_SYSMENU; - dlg->x = 10; - dlg->y = 10; - dlg->cx = 220; - dlg->cy = 70; + dlg->x = 10; + dlg->y = 10; + dlg->cx = 220; + dlg->cy = 70; - data = (uint16_t *)(dlg + 1); + data = (uint16_t *) (dlg + 1); *data++ = 0; /*no menu*/ *data++ = 0; /*predefined dialog box class*/ - data += wsprintf(data, plat_get_string(IDS_2141), device->name) + 1; + data += wsprintf(data, plat_get_string(IDS_2142), device->name) + 1; *data++ = 9; /*Point*/ data += MultiByteToWideChar(CP_ACP, 0, "Segoe UI", -1, data, 120); - if (((uintptr_t)data) & 2) - data++; + if (((uintptr_t) data) & 2) + data++; while (config->type != -1) { - switch (config->type) { - case CONFIG_BINARY: - item = (DLGITEMTEMPLATE *)data; - item->x = 10; - item->y = y; - item->id = id++; + switch (config->type) { + case CONFIG_BINARY: + item = (DLGITEMTEMPLATE *) data; + item->x = 10; + item->y = y; + item->id = id++; - item->cx = 100; - item->cy = 15; + item->cx = 100; + item->cy = 15; - item->style = WS_CHILD | WS_VISIBLE | BS_AUTOCHECKBOX; + item->style = WS_CHILD | WS_VISIBLE | BS_AUTOCHECKBOX; - data = (uint16_t *)(item + 1); - *data++ = 0xFFFF; - *data++ = 0x0080; /* button class */ + data = (uint16_t *) (item + 1); + *data++ = 0xFFFF; + *data++ = 0x0080; /* button class */ - data += MultiByteToWideChar(CP_ACP, 0, config->description, -1, data, 256); - *data++ = 0; /* no creation data */ + data += MultiByteToWideChar(CP_ACP, 0, config->description, -1, data, 256); + *data++ = 0; /* no creation data */ - y += 20; - break; + y += 20; + break; - case CONFIG_SELECTION: - case CONFIG_MIDI: - case CONFIG_MIDI_IN: - case CONFIG_HEX16: - case CONFIG_HEX20: - /*Combo box*/ - item = (DLGITEMTEMPLATE *)data; - item->x = 70; - item->y = y; - item->id = id++; + case CONFIG_SELECTION: + case CONFIG_MIDI_OUT: + case CONFIG_MIDI_IN: + case CONFIG_HEX16: + case CONFIG_HEX20: + case CONFIG_BIOS: + /*Combo box*/ + item = (DLGITEMTEMPLATE *) data; + item->x = 70; + item->y = y; + item->id = id++; - item->cx = 140; - item->cy = 150; + item->cx = 140; + item->cy = 150; - item->style = WS_CHILD | WS_VISIBLE | CBS_DROPDOWNLIST | WS_VSCROLL; + item->style = WS_CHILD | WS_VISIBLE | CBS_DROPDOWNLIST | WS_VSCROLL; - data = (uint16_t *)(item + 1); - *data++ = 0xFFFF; - *data++ = 0x0085; /* combo box class */ + data = (uint16_t *) (item + 1); + *data++ = 0xFFFF; + *data++ = 0x0085; /* combo box class */ - data += MultiByteToWideChar(CP_ACP, 0, config->description, -1, data, 256); - *data++ = 0; /* no creation data */ + data += MultiByteToWideChar(CP_ACP, 0, config->description, -1, data, 256); + *data++ = 0; /* no creation data */ - if (((uintptr_t)data) & 2) - data++; + if (((uintptr_t) data) & 2) + data++; - /*Static text*/ - item = (DLGITEMTEMPLATE *)data; - item->x = 10; - item->y = y + 2; - item->id = id++; + /*Static text*/ + item = (DLGITEMTEMPLATE *) data; + item->x = 10; + item->y = y + 2; + item->id = id++; - item->cx = 60; - item->cy = 20; + item->cx = 60; + item->cy = 20; - item->style = WS_CHILD | WS_VISIBLE; + item->style = WS_CHILD | WS_VISIBLE; - data = (uint16_t *)(item + 1); - *data++ = 0xFFFF; - *data++ = 0x0082; /* static class */ + data = (uint16_t *) (item + 1); + *data++ = 0xFFFF; + *data++ = 0x0082; /* static class */ - data += MultiByteToWideChar(CP_ACP, 0, config->description, -1, data, 256); - *data++ = 0; /* no creation data */ + data += MultiByteToWideChar(CP_ACP, 0, config->description, -1, data, 256); + *data++ = 0; /* no creation data */ - if (((uintptr_t)data) & 2) - data++; + if (((uintptr_t) data) & 2) + data++; - y += 20; - break; - case CONFIG_SPINNER: - /*Spinner*/ - item = (DLGITEMTEMPLATE *)data; - item->x = 70; - item->y = y; - item->id = id++; + y += 20; + break; + case CONFIG_SPINNER: + /*Spinner*/ + item = (DLGITEMTEMPLATE *) data; + item->x = 70; + item->y = y; + item->id = id++; - item->cx = 140; - item->cy = 14; + item->cx = 140; + item->cy = 14; - item->style = WS_CHILD | WS_VISIBLE | ES_AUTOHSCROLL | ES_NUMBER; - item->dwExtendedStyle = WS_EX_CLIENTEDGE; + item->style = WS_CHILD | WS_VISIBLE | ES_AUTOHSCROLL | ES_NUMBER; + item->dwExtendedStyle = WS_EX_CLIENTEDGE; - data = (uint16_t *)(item + 1); - *data++ = 0xFFFF; - *data++ = 0x0081; /* edit text class */ + data = (uint16_t *) (item + 1); + *data++ = 0xFFFF; + *data++ = 0x0081; /* edit text class */ - data += MultiByteToWideChar(CP_ACP, 0, "", -1, data, 256); - *data++ = 0; /* no creation data */ + data += MultiByteToWideChar(CP_ACP, 0, "", -1, data, 256); + *data++ = 0; /* no creation data */ - if (((uintptr_t)data) & 2) - data++; + if (((uintptr_t) data) & 2) + data++; - /* TODO: add up down class */ - /*Static text*/ - item = (DLGITEMTEMPLATE *)data; - item->x = 10; - item->y = y + 2; - item->id = id++; + /* TODO: add up down class */ + /*Static text*/ + item = (DLGITEMTEMPLATE *) data; + item->x = 10; + item->y = y + 2; + item->id = id++; - item->cx = 60; - item->cy = 20; + item->cx = 60; + item->cy = 20; - item->style = WS_CHILD | WS_VISIBLE; + item->style = WS_CHILD | WS_VISIBLE; - data = (uint16_t *)(item + 1); - *data++ = 0xFFFF; - *data++ = 0x0082; /* static class */ + data = (uint16_t *) (item + 1); + *data++ = 0xFFFF; + *data++ = 0x0082; /* static class */ - data += MultiByteToWideChar(CP_ACP, 0, config->description, -1, data, 256); - *data++ = 0; /* no creation data */ + data += MultiByteToWideChar(CP_ACP, 0, config->description, -1, data, 256); + *data++ = 0; /* no creation data */ - if (((uintptr_t)data) & 2) - data++; + if (((uintptr_t) data) & 2) + data++; - y += 20; - break; - case CONFIG_FNAME: - /*File*/ - item = (DLGITEMTEMPLATE *)data; - item->x = 70; - item->y = y; - item->id = id++; + y += 20; + break; + case CONFIG_STRING: + /*Editable Text*/ + item = (DLGITEMTEMPLATE *) data; + item->x = 70; + item->y = y; + item->id = id++; - item->cx = 100; - item->cy = 14; + item->cx = 140; + item->cy = 14; - item->style = WS_CHILD | WS_VISIBLE | ES_READONLY; - item->dwExtendedStyle = WS_EX_CLIENTEDGE; + item->style = WS_CHILD | WS_VISIBLE | ES_READONLY; + item->dwExtendedStyle = WS_EX_CLIENTEDGE; - data = (uint16_t *)(item + 1); - *data++ = 0xFFFF; - *data++ = 0x0081; /* edit text class */ + data = (uint16_t *) (item + 1); + *data++ = 0xFFFF; + *data++ = 0x0081; /* edit text class */ - data += MultiByteToWideChar(CP_ACP, 0, "", -1, data, 256); - *data++ = 0; /* no creation data */ + data += MultiByteToWideChar(CP_ACP, 0, "", -1, data, 256); + *data++ = 0; /* no creation data */ - if (((uintptr_t)data) & 2) - data++; + if (((uintptr_t) data) & 2) + data++; - /* Button */ - item = (DLGITEMTEMPLATE *)data; - item->x = 175; - item->y = y; - item->id = id++; + /*Static text*/ + item = (DLGITEMTEMPLATE *) data; + item->x = 10; + item->y = y + 2; + item->id = id++; - item->cx = 35; - item->cy = 14; + item->cx = 60; + item->cy = 20; - item->style = WS_CHILD | WS_VISIBLE | BS_PUSHBUTTON; + item->style = WS_CHILD | WS_VISIBLE; - data = (uint16_t *)(item + 1); - *data++ = 0xFFFF; - *data++ = 0x0080; /* button class */ + data = (uint16_t *) (item + 1); + *data++ = 0xFFFF; + *data++ = 0x0082; /* static class */ - data += MultiByteToWideChar(CP_ACP, 0, "Browse", -1, data, 256); - *data++ = 0; /* no creation data */ + data += MultiByteToWideChar(CP_ACP, 0, config->description, -1, data, 256); + *data++ = 0; /* no creation data */ - if (((uintptr_t)data) & 2) - data++; + if (((uintptr_t) data) & 2) + data++; - /*Static text*/ - item = (DLGITEMTEMPLATE *)data; - item->x = 10; - item->y = y + 2; - item->id = id++; + y += 20; + break; + case CONFIG_FNAME: + /*File*/ + item = (DLGITEMTEMPLATE *) data; + item->x = 70; + item->y = y; + item->id = id++; - item->cx = 60; - item->cy = 20; + item->cx = 100; + item->cy = 14; - item->style = WS_CHILD | WS_VISIBLE; + item->style = WS_CHILD | WS_VISIBLE | ES_READONLY; + item->dwExtendedStyle = WS_EX_CLIENTEDGE; - data = (uint16_t *)(item + 1); - *data++ = 0xFFFF; - *data++ = 0x0082; /* static class */ + data = (uint16_t *) (item + 1); + *data++ = 0xFFFF; + *data++ = 0x0081; /* edit text class */ - data += MultiByteToWideChar(CP_ACP, 0, config->description, -1, data, 256); - *data++ = 0; /* no creation data */ + data += MultiByteToWideChar(CP_ACP, 0, "", -1, data, 256); + *data++ = 0; /* no creation data */ - if (((uintptr_t)data) & 2) - data++; + if (((uintptr_t) data) & 2) + data++; - y += 20; - break; - } + /* Button */ + item = (DLGITEMTEMPLATE *) data; + item->x = 175; + item->y = y; + item->id = id++; - if (((uintptr_t)data) & 2) - data++; + item->cx = 35; + item->cy = 14; - config++; + item->style = WS_CHILD | WS_VISIBLE | BS_PUSHBUTTON; + + data = (uint16_t *) (item + 1); + *data++ = 0xFFFF; + *data++ = 0x0080; /* button class */ + + data += MultiByteToWideChar(CP_ACP, 0, "Browse", -1, data, 256); + *data++ = 0; /* no creation data */ + + if (((uintptr_t) data) & 2) + data++; + + /*Static text*/ + item = (DLGITEMTEMPLATE *) data; + item->x = 10; + item->y = y + 2; + item->id = id++; + + item->cx = 60; + item->cy = 20; + + item->style = WS_CHILD | WS_VISIBLE; + + data = (uint16_t *) (item + 1); + *data++ = 0xFFFF; + *data++ = 0x0082; /* static class */ + + data += MultiByteToWideChar(CP_ACP, 0, config->description, -1, data, 256); + *data++ = 0; /* no creation data */ + + if (((uintptr_t) data) & 2) + data++; + + y += 20; + break; + } + + if (((uintptr_t) data) & 2) + data++; + + config++; } dlg->cdit = (id - IDC_CONFIG_BASE) + 2; - item = (DLGITEMTEMPLATE *)data; - item->x = 100; - item->y = y + 5; - item->cx = 50; - item->cy = 14; - item->id = IDOK; /* OK button identifier */ + item = (DLGITEMTEMPLATE *) data; + item->x = 100; + item->y = y + 5; + item->cx = 50; + item->cy = 14; + item->id = IDOK; /* OK button identifier */ item->style = WS_CHILD | WS_VISIBLE | BS_DEFPUSHBUTTON; - data = (uint16_t *)(item + 1); + data = (uint16_t *) (item + 1); *data++ = 0xFFFF; - *data++ = 0x0080; /* button class */ + *data++ = 0x0080; /* button class */ data += MultiByteToWideChar(CP_ACP, 0, "OK", -1, data, 50); - *data++ = 0; /* no creation data */ + *data++ = 0; /* no creation data */ - if (((uintptr_t)data) & 2) - data++; + if (((uintptr_t) data) & 2) + data++; - item = (DLGITEMTEMPLATE *)data; - item->x = 160; - item->y = y + 5; - item->cx = 50; - item->cy = 14; - item->id = IDCANCEL; /* OK button identifier */ + item = (DLGITEMTEMPLATE *) data; + item->x = 160; + item->y = y + 5; + item->cx = 50; + item->cy = 14; + item->id = IDCANCEL; /* OK button identifier */ item->style = WS_CHILD | WS_VISIBLE | BS_DEFPUSHBUTTON; - data = (uint16_t *)(item + 1); + data = (uint16_t *) (item + 1); *data++ = 0xFFFF; - *data++ = 0x0080; /* button class */ + *data++ = 0x0080; /* button class */ data += MultiByteToWideChar(CP_ACP, 0, "Cancel", -1, data, 50); - *data++ = 0; /* no creation data */ + *data++ = 0; /* no creation data */ dlg->cy = y + 25; @@ -703,7 +825,6 @@ deviceconfig_inst_open(HWND hwnd, const device_t *device, int inst) return deviceconfig_changed; } - uint8_t deviceconfig_open(HWND hwnd, const device_t *device) { diff --git a/src/win/win_dialog.c b/src/win/win_dialog.c index 9ae3edb1a..15b00bf3f 100644 --- a/src/win/win_dialog.c +++ b/src/win/win_dialog.c @@ -1,20 +1,21 @@ /* - * 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. + * 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. + * This file is part of the 86Box distribution. * - * Several dialogs for the application. + * Several dialogs for the application. * * * - * Author: Miran Grca, - * Fred N. van Kempen, + * Authors: Miran Grca, + * Fred N. van Kempen, * - * Copyright 2016-2019 Miran Grca. - * Copyright 2017-2019 Fred N. van Kempen. + * Copyright 2016-2019 Miran Grca. + * Copyright 2017-2019 Fred N. van Kempen. + * Copyright 2021-2023 Jasmine Iwanek. */ #define UNICODE #include @@ -33,15 +34,11 @@ #include <86box/ui.h> #include <86box/win.h> +#define STRING_OR_RESOURCE(s) ((!(s)) ? (NULL) : ((((uintptr_t) s) < ((uintptr_t) 65636)) ? (MAKEINTRESOURCE((uintptr_t) s)) : (s))) - -#define STRING_OR_RESOURCE(s) ((!(s)) ? (NULL) : ((((uintptr_t)s) < ((uintptr_t)65636)) ? (MAKEINTRESOURCE((uintptr_t)s)) : (s))) - - -WCHAR wopenfilestring[512]; -char openfilestring[512]; -uint8_t filterindex = 0; - +WCHAR wopenfilestring[512]; +char openfilestring[512]; +uint8_t filterindex = 0; int ui_msgbox(int flags, void *message) @@ -49,205 +46,211 @@ ui_msgbox(int flags, void *message) return ui_msgbox_ex(flags, NULL, message, NULL, NULL, NULL); } - int ui_msgbox_header(int flags, void *header, void *message) { return ui_msgbox_ex(flags, header, message, NULL, NULL, NULL); } - int -ui_msgbox_ex(int flags, void *header, void *message, void *btn1, void *btn2, void *btn3) { - WCHAR temp[512]; - TASKDIALOGCONFIG tdconfig = {0}; - TASKDIALOG_BUTTON tdbuttons[3], - tdb_yes = {IDYES, STRING_OR_RESOURCE(btn1)}, - tdb_no = {IDNO, STRING_OR_RESOURCE(btn2)}, - tdb_cancel = {IDCANCEL, STRING_OR_RESOURCE(btn3)}, - tdb_exit = {IDCLOSE, MAKEINTRESOURCE(IDS_2119)}; - int ret = 0, checked = 0; +ui_msgbox_ex(int flags, void *header, void *message, void *btn1, void *btn2, void *btn3) +{ + WCHAR temp[512]; + TASKDIALOGCONFIG tdconfig = { 0 }; + TASKDIALOG_BUTTON tdbuttons[3]; + TASKDIALOG_BUTTON tdb_yes = { IDYES, STRING_OR_RESOURCE(btn1) }; + TASKDIALOG_BUTTON tdb_no = { IDNO, STRING_OR_RESOURCE(btn2) }; + TASKDIALOG_BUTTON tdb_cancel = { IDCANCEL, STRING_OR_RESOURCE(btn3) }; + TASKDIALOG_BUTTON tdb_exit = { IDCLOSE, MAKEINTRESOURCE(IDS_2120) }; + int ret = 0; + int checked = 0; /* Configure the default OK button. */ tdconfig.cButtons = 0; if (btn1) - tdbuttons[tdconfig.cButtons++] = tdb_yes; + tdbuttons[tdconfig.cButtons++] = tdb_yes; else - tdconfig.dwCommonButtons = TDCBF_OK_BUTTON; + tdconfig.dwCommonButtons = TDCBF_OK_BUTTON; /* Configure the message type. */ - switch(flags & 0x1f) { - case MBX_INFO: /* just an informational message */ - tdconfig.pszMainIcon = TD_INFORMATION_ICON; - break; + switch (flags & 0x1f) { + case MBX_INFO: /* just an informational message */ + tdconfig.pszMainIcon = TD_INFORMATION_ICON; + break; - case MBX_ERROR: /* error message */ - if (flags & MBX_FATAL) { - tdconfig.pszMainIcon = TD_ERROR_ICON; - tdconfig.pszMainInstruction = MAKEINTRESOURCE(IDS_2050); /* "Fatal error" */ + case MBX_ERROR: /* error message */ + if (flags & MBX_FATAL) { + tdconfig.pszMainIcon = TD_ERROR_ICON; + tdconfig.pszMainInstruction = MAKEINTRESOURCE(IDS_2050); /* "Fatal error" */ - /* replace default "OK" button with "Exit" button */ - if (btn1) - tdconfig.cButtons = 0; - else - tdconfig.dwCommonButtons = 0; - tdbuttons[tdconfig.cButtons++] = tdb_exit; - } else { - tdconfig.pszMainIcon = TD_WARNING_ICON; - tdconfig.pszMainInstruction = MAKEINTRESOURCE(IDS_2049); /* "Error" */ - } - break; + /* replace default "OK" button with "Exit" button */ + if (btn1) + tdconfig.cButtons = 0; + else + tdconfig.dwCommonButtons = 0; + tdbuttons[tdconfig.cButtons++] = tdb_exit; + } else { + tdconfig.pszMainIcon = TD_WARNING_ICON; + tdconfig.pszMainInstruction = MAKEINTRESOURCE(IDS_2049); /* "Error" */ + } + break; - case MBX_QUESTION: /* question */ - case MBX_QUESTION_YN: - case MBX_QUESTION_OK: - if (!btn1) /* replace default "OK" button with "Yes" button */ - tdconfig.dwCommonButtons = (flags & MBX_QUESTION_OK) ? TDCBF_OK_BUTTON : TDCBF_YES_BUTTON; + case MBX_QUESTION: /* question */ + case MBX_QUESTION_YN: + case MBX_QUESTION_OK: + if (!btn1) /* replace default "OK" button with "Yes" button */ + tdconfig.dwCommonButtons = (flags & MBX_QUESTION_OK) ? TDCBF_OK_BUTTON : TDCBF_YES_BUTTON; - if (btn2) /* "No" button */ - tdbuttons[tdconfig.cButtons++] = tdb_no; - else - tdconfig.dwCommonButtons |= (flags & MBX_QUESTION_OK) ? TDCBF_CANCEL_BUTTON : TDCBF_NO_BUTTON; + if (btn2) /* "No" button */ + tdbuttons[tdconfig.cButtons++] = tdb_no; + else + tdconfig.dwCommonButtons |= (flags & MBX_QUESTION_OK) ? TDCBF_CANCEL_BUTTON : TDCBF_NO_BUTTON; - if (flags & MBX_QUESTION) { - if (btn3) /* "Cancel" button */ - tdbuttons[tdconfig.cButtons++] = tdb_cancel; - else - tdconfig.dwCommonButtons |= TDCBF_CANCEL_BUTTON; - } + if (flags & MBX_QUESTION) { + if (btn3) /* "Cancel" button */ + tdbuttons[tdconfig.cButtons++] = tdb_cancel; + else + tdconfig.dwCommonButtons |= TDCBF_CANCEL_BUTTON; + } - if (flags & MBX_WARNING) - tdconfig.pszMainIcon = TD_WARNING_ICON; - break; + if (flags & MBX_WARNING) + tdconfig.pszMainIcon = TD_WARNING_ICON; + break; } /* If the message is an ANSI string, convert it. */ tdconfig.pszContent = (WCHAR *) STRING_OR_RESOURCE(message); if (flags & MBX_ANSI) { - mbstoc16s(temp, (char *)message, strlen((char *)message)+1); - tdconfig.pszContent = temp; + mbstoc16s(temp, (char *) message, strlen((char *) message) + 1); + tdconfig.pszContent = temp; } /* Configure the rest of the TaskDialog. */ - tdconfig.cbSize = sizeof(tdconfig); + tdconfig.cbSize = sizeof(tdconfig); tdconfig.hwndParent = hwndMain; if (flags & MBX_LINKS) - tdconfig.dwFlags = TDF_USE_COMMAND_LINKS; + tdconfig.dwFlags = TDF_USE_COMMAND_LINKS; tdconfig.pszWindowTitle = MAKEINTRESOURCE(IDS_STRINGS); if (header) - tdconfig.pszMainInstruction = STRING_OR_RESOURCE(header); + tdconfig.pszMainInstruction = STRING_OR_RESOURCE(header); tdconfig.pButtons = tdbuttons; if (flags & MBX_DONTASK) - tdconfig.pszVerificationText = MAKEINTRESOURCE(IDS_2135); + tdconfig.pszVerificationText = MAKEINTRESOURCE(IDS_2136); /* Run the TaskDialog. */ TaskDialogIndirect(&tdconfig, &ret, NULL, &checked); /* Convert return values to generic ones. */ - if (ret == IDNO) ret = 1; - else if (ret == IDCANCEL) ret = -1; - else ret = 0; + if (ret == IDNO) + ret = 1; + else if (ret == IDCANCEL) + ret = -1; + else + ret = 0; /* 10 is added to the return value if "don't show again" is checked. */ - if (checked) ret += 10; + if (checked) + ret += 10; - return(ret); + return ret; } - int file_dlg_w(HWND hwnd, WCHAR *f, WCHAR *fn, WCHAR *title, int save) { OPENFILENAME ofn; - BOOL r; - /* DWORD err; */ + BOOL r; +#if 0 + DWORD err; +#endif int old_dopause; /* Initialize OPENFILENAME */ ZeroMemory(&ofn, sizeof(ofn)); ofn.lStructSize = sizeof(ofn); - ofn.hwndOwner = hwnd; - ofn.lpstrFile = wopenfilestring; + ofn.hwndOwner = hwnd; + ofn.lpstrFile = wopenfilestring; /* * Set lpstrFile[0] to '\0' so that GetOpenFileName does * not use the contents of szFile to initialize itself. */ memset(ofn.lpstrFile, 0x00, 512 * sizeof(WCHAR)); - memcpy(ofn.lpstrFile, fn, (wcslen(fn) << 1) + 2); - ofn.nMaxFile = sizeof_w(wopenfilestring); - ofn.lpstrFilter = f; - ofn.nFilterIndex = 1; - ofn.lpstrFileTitle = NULL; - ofn.nMaxFileTitle = 0; + if (fn) + memcpy(ofn.lpstrFile, fn, (wcslen(fn) << 1) + 2); + ofn.nMaxFile = sizeof_w(wopenfilestring); + ofn.lpstrFilter = f; + ofn.nFilterIndex = 1; + ofn.lpstrFileTitle = NULL; + ofn.nMaxFileTitle = 0; ofn.lpstrInitialDir = NULL; - ofn.Flags = OFN_PATHMUSTEXIST; - if (! save) - ofn.Flags |= OFN_FILEMUSTEXIST; + ofn.Flags = OFN_PATHMUSTEXIST; + if (!save) + ofn.Flags |= OFN_FILEMUSTEXIST; if (title) - ofn.lpstrTitle = title; + ofn.lpstrTitle = title; /* Display the Open dialog box. */ old_dopause = dopause; plat_pause(1); if (save) - r = GetSaveFileName(&ofn); + r = GetSaveFileName(&ofn); else - r = GetOpenFileName(&ofn); + r = GetOpenFileName(&ofn); plat_pause(old_dopause); plat_chdir(usr_path); if (r) { - c16stombs(openfilestring, wopenfilestring, sizeof(openfilestring)); - filterindex = ofn.nFilterIndex; + c16stombs(openfilestring, wopenfilestring, sizeof(openfilestring)); + filterindex = ofn.nFilterIndex; - return(0); + return 0; } - return(1); + return 1; } - int file_dlg(HWND hwnd, WCHAR *f, char *fn, char *title, int save) { - WCHAR ufn[512], title_buf[512]; + WCHAR ufn[512]; + WCHAR title_buf[512]; - mbstoc16s(ufn, fn, strlen(fn) + 1); + if (fn) + mbstoc16s(ufn, fn, strlen(fn) + 1); if (title) mbstoc16s(title_buf, title, sizeof title_buf); - return(file_dlg_w(hwnd, f, ufn, title ? title_buf : NULL, save)); + return (file_dlg_w(hwnd, f, fn ? ufn : NULL, title ? title_buf : NULL, save)); } - int file_dlg_mb(HWND hwnd, char *f, char *fn, char *title, int save) { - WCHAR uf[512], ufn[512], title_buf[512]; + WCHAR uf[512]; + WCHAR ufn[512]; + WCHAR title_buf[512]; mbstoc16s(uf, f, strlen(f) + 1); mbstoc16s(ufn, fn, strlen(fn) + 1); if (title) mbstoc16s(title_buf, title, sizeof title_buf); - return(file_dlg_w(hwnd, uf, ufn, title ? title_buf : NULL, save)); + return (file_dlg_w(hwnd, uf, ufn, title ? title_buf : NULL, save)); } - int file_dlg_w_st(HWND hwnd, int id, WCHAR *fn, char *title, int save) { WCHAR title_buf[512]; if (title) mbstoc16s(title_buf, title, sizeof title_buf); - return(file_dlg_w(hwnd, plat_get_string(id), fn, title ? title_buf : NULL, save)); + return (file_dlg_w(hwnd, plat_get_string(id), fn, title ? title_buf : NULL, save)); } - int file_dlg_st(HWND hwnd, int id, char *fn, char *title, int save) -{ - return(file_dlg(hwnd, plat_get_string(id), fn, title, save)); +{ + return (file_dlg(hwnd, plat_get_string(id), fn, title, save)); } diff --git a/src/win/win_dynld.c b/src/win/win_dynld.c index 98eb4739f..24690f2ba 100644 --- a/src/win/win_dynld.c +++ b/src/win/win_dynld.c @@ -1,18 +1,19 @@ /* - * 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. + * 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. + * This file is part of the 86Box distribution. * - * Try to load a support DLL. + * Try to load a support DLL. * * * - * Author: Fred N. van Kempen, + * Authors: Fred N. van Kempen, * - * Copyright 2017,2018 Fred N. van Kempen + * Copyright 2017-2018 Fred N. van Kempen + * Copyright 2021-2023 Jasmine Iwanek. */ #include #include @@ -25,63 +26,58 @@ #include <86box/86box.h> #include <86box/plat_dynld.h> - #ifdef ENABLE_DYNLD_LOG int dynld_do_log = ENABLE_DYNLD_LOG; - static void dynld_log(const char *fmt, ...) { va_list ap; if (dynld_do_log) { - va_start(ap, fmt); - pclog_ex(fmt, ap); - va_end(ap); + va_start(ap, fmt); + pclog_ex(fmt, ap); + va_end(ap); } } #else -#define dynld_log(fmt, ...) +# define dynld_log(fmt, ...) #endif - void * dynld_module(const char *name, dllimp_t *table) { - HMODULE h; - dllimp_t *imp; - void *func; + HMODULE h; + void *func; /* See if we can load the desired module. */ if ((h = LoadLibrary(name)) == NULL) { - dynld_log("DynLd(\"%s\"): library not found! (%08X)\n", name, GetLastError()); - return(NULL); + dynld_log("DynLd(\"%s\"): library not found! (%08X)\n", name, GetLastError()); + return (NULL); } /* Now load the desired function pointers. */ - for (imp=table; imp->name!=NULL; imp++) { - func = GetProcAddress(h, imp->name); - if (func == NULL) { - dynld_log("DynLd(\"%s\"): function '%s' not found! (%08X)\n", - name, imp->name, GetLastError()); - FreeLibrary(h); - return(NULL); - } + for (dllimp_t *imp = table; imp->name != NULL; imp++) { + func = GetProcAddress(h, imp->name); + if (func == NULL) { + dynld_log("DynLd(\"%s\"): function '%s' not found! (%08X)\n", + name, imp->name, GetLastError()); + FreeLibrary(h); + return (NULL); + } - /* To overcome typing issues.. */ - *(char **)imp->func = (char *)func; + /* To overcome typing issues.. */ + *(char **) imp->func = (char *) func; } /* All good. */ dynld_log("loaded %s\n", name); - return((void *)h); + return ((void *) h); } - void dynld_close(void *handle) { if (handle != NULL) - FreeLibrary((HMODULE)handle); + FreeLibrary((HMODULE) handle); } diff --git a/src/win/win_icon.c b/src/win/win_icon.c index 33a5932ef..f3426b8b5 100644 --- a/src/win/win_icon.c +++ b/src/win/win_icon.c @@ -1,19 +1,21 @@ /* - * 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. + * 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. + * This file is part of the 86Box distribution. * - * Implement the application's icon changing system. + * Implement the application's icon changing system. * * - * Authors: Laci bá' * - * Copyright 2021 Laci bá'. + * Authors: Laci bá' + * + * Copyright 2021 Laci bá'. + * Copyright 2021-2023 Jasmine Iwanek. */ - + #include #include #include @@ -23,142 +25,144 @@ #include #include <86box/86box.h> #include <86box/config.h> +#include <86box/path.h> #include <86box/plat.h> #include <86box/ui.h> #include <86box/win.h> - -HICON hIcon[256]; /* icon data loaded from resources */ -char icon_set[256] = ""; /* name of the iconset to be used */ -void win_clear_icon_set() +HICON hIcon[256]; /* icon data loaded from resources */ +char icon_set[256] = ""; /* name of the iconset to be used */ + +void +win_clear_icon_set(void) { - int i; - - for (i = 0; i < 256; i++) - if (hIcon[i] != 0) - { - DestroyIcon(hIcon[i]); - hIcon[i] = 0; - } + for (uint16_t i = 0; i < 256; i++) + if (hIcon[i] != 0) { + DestroyIcon(hIcon[i]); + hIcon[i] = 0; + } } -void win_system_icon_set() +void +win_system_icon_set(void) { - int i, x = win_get_system_metrics(SM_CXSMICON, dpi), y = win_get_system_metrics(SM_CYSMICON, dpi); + int x = win_get_system_metrics(SM_CXSMICON, dpi); + int y = win_get_system_metrics(SM_CYSMICON, dpi); - for (i = 0; i < 256; i++) - hIcon[i] = LoadImage(hinstance, MAKEINTRESOURCE(i), IMAGE_ICON, x, y, LR_DEFAULTCOLOR); + for (uint16_t i = 0; i < 256; i++) + hIcon[i] = LoadImage(hinstance, MAKEINTRESOURCE(i), IMAGE_ICON, x, y, LR_DEFAULTCOLOR); } typedef struct { - int id; - char* filename; + int id; + char *filename; } _ICON_DATA; -const _ICON_DATA icon_files[] = - { - {16, "floppy_525.ico"}, - {17, "floppy_525_active.ico"}, - {24, "floppy_35.ico"}, - {25, "floppy_35_active.ico"}, - {32, "cdrom.ico"}, - {33, "cdrom_active.ico"}, - {48, "zip.ico"}, - {49, "zip_active.ico"}, - {56, "mo.ico"}, - {57, "mo_active.ico"}, - {64, "cassette.ico"}, - {65, "cassette_active.ico"}, - {80, "hard_disk.ico"}, - {81, "hard_disk_active.ico"}, - {96, "network.ico"}, - {97, "network_active.ico"}, - {104, "cartridge.ico"}, - {144, "floppy_525_empty.ico"}, - {145, "floppy_525_empty_active.ico"}, - {152, "floppy_35_empty.ico"}, - {153, "floppy_35_empty_active.ico"}, - {160, "cdrom_empty.ico"}, - {161, "cdrom_empty_active.ico"}, - {176, "zip_empty.ico"}, - {177, "zip_empty_active.ico"}, - {184, "mo_empty.ico"}, - {185, "mo_empty_active.ico"}, - {192, "cassette_empty.ico"}, - {193, "cassette_empty_active.ico"}, - {200, "run.ico"}, - {201, "pause.ico"}, - {202, "send_cad.ico"}, - {203, "send_cae.ico"}, - {204, "hard_reset.ico"}, - {205, "acpi_shutdown.ico"}, - {206, "settings.ico"}, - {232, "cartridge_empty.ico"}, - {240, "machine.ico"}, - {241, "display.ico"}, - {242, "input_devices.ico"}, - {243, "sound.ico"}, - {244, "ports.ico"}, - {245, "other_peripherals.ico"}, - {246, "floppy_and_cdrom_drives.ico"}, - {247, "other_removable_devices.ico"}, - {248, "floppy_disabled.ico"}, - {249, "cdrom_disabled.ico"}, - {250, "zip_disabled.ico"}, - {251, "mo_disabled.ico"}, - {252, "storage_controllers.ico"} - }; +const _ICON_DATA icon_files[] = { + {16, "floppy_525.ico" }, + { 17, "floppy_525_active.ico" }, + { 24, "floppy_35.ico" }, + { 25, "floppy_35_active.ico" }, + { 32, "cdrom.ico" }, + { 33, "cdrom_active.ico" }, + { 48, "zip.ico" }, + { 49, "zip_active.ico" }, + { 56, "mo.ico" }, + { 57, "mo_active.ico" }, + { 64, "cassette.ico" }, + { 65, "cassette_active.ico" }, + { 80, "hard_disk.ico" }, + { 81, "hard_disk_active.ico" }, + { 96, "network.ico" }, + { 97, "network_active.ico" }, + { 104, "cartridge.ico" }, + { 144, "floppy_525_empty.ico" }, + { 145, "floppy_525_empty_active.ico"}, + { 152, "floppy_35_empty.ico" }, + { 153, "floppy_35_empty_active.ico" }, + { 160, "cdrom_empty.ico" }, + { 161, "cdrom_empty_active.ico" }, + { 176, "zip_empty.ico" }, + { 177, "zip_empty_active.ico" }, + { 184, "mo_empty.ico" }, + { 185, "mo_empty_active.ico" }, + { 192, "cassette_empty.ico" }, + { 193, "cassette_empty_active.ico" }, + { 200, "run.ico" }, + { 201, "pause.ico" }, + { 202, "send_cad.ico" }, + { 203, "send_cae.ico" }, + { 204, "hard_reset.ico" }, + { 205, "acpi_shutdown.ico" }, + { 206, "settings.ico" }, + { 232, "cartridge_empty.ico" }, + { 240, "machine.ico" }, + { 241, "display.ico" }, + { 242, "input_devices.ico" }, + { 243, "sound.ico" }, + { 244, "ports.ico" }, + { 245, "other_peripherals.ico" }, + { 246, "floppy_and_cdrom_drives.ico"}, + { 247, "other_removable_devices.ico"}, + { 248, "floppy_disabled.ico" }, + { 249, "cdrom_disabled.ico" }, + { 250, "zip_disabled.ico" }, + { 251, "mo_disabled.ico" }, + { 252, "storage_controllers.ico" } +}; -void win_get_icons_path(char* path_root) +void +win_get_icons_path(char *path_root) { - char roms_root[1024] = {0}; - if (rom_path[0]) - strcpy(roms_root, rom_path); - else - plat_append_filename(roms_root, exe_path, "roms"); - - plat_append_filename(path_root, roms_root, "icons"); - plat_path_slash(path_root); + char roms_root[1024] = { 0 }; + if (rom_path[0]) + strcpy(roms_root, rom_path); + else + path_append_filename(roms_root, exe_path, "roms"); + + path_append_filename(path_root, roms_root, "icons"); + path_slash(path_root); } -void win_load_icon_set() +void +win_load_icon_set(void) { - win_clear_icon_set(); - win_system_icon_set(); - - if (strlen(icon_set) == 0) { - ToolBarLoadIcons(); - return; - } + win_clear_icon_set(); + win_system_icon_set(); - char path_root[2048] = {0}, temp[2048] = {0}; - wchar_t wtemp[2048] = {0}; - - win_get_icons_path(path_root); - strcat(path_root, icon_set); - plat_path_slash(path_root); - - int i, count = sizeof(icon_files) / sizeof(_ICON_DATA), - x = win_get_system_metrics(SM_CXSMICON, dpi), y = win_get_system_metrics(SM_CYSMICON, dpi); - for (i = 0; i < count; i++) - { - plat_append_filename(temp, path_root, icon_files[i].filename); - mbstoc16s(wtemp, temp, strlen(temp) + 1); - - HICON ictemp; - ictemp = LoadImageW(NULL, (LPWSTR)wtemp, IMAGE_ICON, x, y, LR_LOADFROMFILE | LR_DEFAULTCOLOR); - if (ictemp) - { - if (hIcon[icon_files[i].id]) - DestroyIcon(hIcon[icon_files[i].id]); - hIcon[icon_files[i].id] = ictemp; - } - } - - uint32_t curr_lang = lang_id; - lang_id = 0; - set_language(curr_lang); + if (strlen(icon_set) == 0) { + ToolBarLoadIcons(); + return; + } - ToolBarLoadIcons(); -} \ No newline at end of file + char path_root[2048] = { 0 }; + char temp[2048] = { 0 }; + wchar_t wtemp[2048] = { 0 }; + + win_get_icons_path(path_root); + strcat(path_root, icon_set); + path_slash(path_root); + + int count = sizeof(icon_files) / sizeof(_ICON_DATA); + int x = win_get_system_metrics(SM_CXSMICON, dpi); + int y = win_get_system_metrics(SM_CYSMICON, dpi); + for (int i = 0; i < count; i++) { + path_append_filename(temp, path_root, icon_files[i].filename); + mbstoc16s(wtemp, temp, strlen(temp) + 1); + + HICON ictemp; + ictemp = LoadImageW(NULL, (LPWSTR) wtemp, IMAGE_ICON, x, y, LR_LOADFROMFILE | LR_DEFAULTCOLOR); + if (ictemp) { + if (hIcon[icon_files[i].id]) + DestroyIcon(hIcon[icon_files[i].id]); + hIcon[icon_files[i].id] = ictemp; + } + } + + uint32_t curr_lang = lang_id; + lang_id = 0; + set_language(curr_lang); + + ToolBarLoadIcons(); +} diff --git a/src/win/win_joystick.cpp b/src/win/win_joystick.cpp index 2615092d3..df8a99a05 100644 --- a/src/win/win_joystick.cpp +++ b/src/win/win_joystick.cpp @@ -1,20 +1,21 @@ /* - * 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. + * 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. + * This file is part of the 86Box distribution. * - * Joystick interface to host device. + * Joystick interface to host device. * * * - * Authors: Sarah Walker, - * Miran Grca, + * Authors: Sarah Walker, + * Miran Grca, * - * Copyright 2008-2019 Sarah Walker. - * Copyright 2016-2019 Miran Grca. + * Copyright 2008-2019 Sarah Walker. + * Copyright 2016-2019 Miran Grca. + * Copyright 2021-2023 Jasmine Iwanek. */ #define DIRECTINPUT_VERSION 0x0800 #include @@ -30,313 +31,294 @@ #include <86box/gameport.h> #include <86box/win.h> -#define DIDEVTYPE_JOYSTICK 4 - +#define DIDEVTYPE_JOYSTICK 4 plat_joystick_t plat_joystick_state[MAX_PLAT_JOYSTICKS]; -joystick_t joystick_state[MAX_JOYSTICKS]; -int joysticks_present = 0; - - -static LPDIRECTINPUT8 lpdi; -static LPDIRECTINPUTDEVICE8 lpdi_joystick[2] = {NULL, NULL}; -static GUID joystick_guids[MAX_JOYSTICKS]; +joystick_t joystick_state[MAX_JOYSTICKS]; +int joysticks_present = 0; +static LPDIRECTINPUT8 lpdi; +static LPDIRECTINPUTDEVICE8 lpdi_joystick[2] = { NULL, NULL }; +static GUID joystick_guids[MAX_JOYSTICKS]; #ifdef ENABLE_JOYSTICK_LOG int joystick_do_log = ENABLE_JOYSTICK_LOG; - static void joystick_log(const char *fmt, ...) { va_list ap; if (joystick_do_log) { - va_start(ap, fmt); - pclog_ex(fmt, ap); - va_end(ap); + va_start(ap, fmt); + pclog_ex(fmt, ap); + va_end(ap); } } #else -#define joystick_log(fmt, ...) +# define joystick_log(fmt, ...) #endif - -static BOOL CALLBACK joystick_enum_callback(LPCDIDEVICEINSTANCE lpddi, UNUSED(LPVOID data)) +static BOOL CALLBACK +joystick_enum_callback(LPCDIDEVICEINSTANCE lpddi, UNUSED(LPVOID data)) { - if (joysticks_present >= MAX_JOYSTICKS) - return DIENUM_STOP; - - joystick_log("joystick_enum_callback : found joystick %i : %s\n", joysticks_present, lpddi->tszProductName); - - joystick_guids[joysticks_present++] = lpddi->guidInstance; + if (joysticks_present >= MAX_JOYSTICKS) + return DIENUM_STOP; - if (joysticks_present >= MAX_JOYSTICKS) - return DIENUM_STOP; - - return DIENUM_CONTINUE; + joystick_log("joystick_enum_callback : found joystick %i : %s\n", joysticks_present, lpddi->tszProductName); + + joystick_guids[joysticks_present++] = lpddi->guidInstance; + + if (joysticks_present >= MAX_JOYSTICKS) + return DIENUM_STOP; + + return DIENUM_CONTINUE; } -BOOL CALLBACK DIEnumDeviceObjectsCallback( - LPCDIDEVICEOBJECTINSTANCE lpddoi, - LPVOID pvRef) +BOOL CALLBACK +DIEnumDeviceObjectsCallback( + LPCDIDEVICEOBJECTINSTANCE lpddoi, + LPVOID pvRef) { - plat_joystick_t *state = (plat_joystick_t *)pvRef; - - if (lpddoi->guidType == GUID_XAxis || lpddoi->guidType == GUID_YAxis || lpddoi->guidType == GUID_ZAxis || - lpddoi->guidType == GUID_RxAxis || lpddoi->guidType == GUID_RyAxis || lpddoi->guidType == GUID_RzAxis) - { - if (state->nr_axes < 8) - {memcpy(state->axis[state->nr_axes].name, lpddoi->tszName, strlen(lpddoi->tszName) + 1); - joystick_log("Axis %i : %s %x %x\n", state->nr_axes, state->axis[state->nr_axes].name, lpddoi->dwOfs, lpddoi->dwType); - if (lpddoi->guidType == GUID_XAxis) - state->axis[state->nr_axes].id = 0; - else if (lpddoi->guidType == GUID_YAxis) - state->axis[state->nr_axes].id = 1; - else if (lpddoi->guidType == GUID_ZAxis) - state->axis[state->nr_axes].id = 2; - else if (lpddoi->guidType == GUID_RxAxis) - state->axis[state->nr_axes].id = 3; - else if (lpddoi->guidType == GUID_RyAxis) - state->axis[state->nr_axes].id = 4; - else if (lpddoi->guidType == GUID_RzAxis) - state->axis[state->nr_axes].id = 5; - state->nr_axes++; - } + plat_joystick_t *state = (plat_joystick_t *) pvRef; + + if (lpddoi->guidType == GUID_XAxis || lpddoi->guidType == GUID_YAxis || lpddoi->guidType == GUID_ZAxis || lpddoi->guidType == GUID_RxAxis || lpddoi->guidType == GUID_RyAxis || lpddoi->guidType == GUID_RzAxis) { + if (state->nr_axes < 8) { + memcpy(state->axis[state->nr_axes].name, lpddoi->tszName, strlen(lpddoi->tszName) + 1); + joystick_log("Axis %i : %s %x %x\n", state->nr_axes, state->axis[state->nr_axes].name, lpddoi->dwOfs, lpddoi->dwType); + if (lpddoi->guidType == GUID_XAxis) + state->axis[state->nr_axes].id = 0; + else if (lpddoi->guidType == GUID_YAxis) + state->axis[state->nr_axes].id = 1; + else if (lpddoi->guidType == GUID_ZAxis) + state->axis[state->nr_axes].id = 2; + else if (lpddoi->guidType == GUID_RxAxis) + state->axis[state->nr_axes].id = 3; + else if (lpddoi->guidType == GUID_RyAxis) + state->axis[state->nr_axes].id = 4; + else if (lpddoi->guidType == GUID_RzAxis) + state->axis[state->nr_axes].id = 5; + state->nr_axes++; } - else if (lpddoi->guidType == GUID_Button) - { - if (state->nr_buttons < 32) - { - memcpy(state->button[state->nr_buttons].name, lpddoi->tszName, strlen(lpddoi->tszName) + 1); - joystick_log("Button %i : %s %x %x\n", state->nr_buttons, state->button[state->nr_buttons].name, lpddoi->dwOfs, lpddoi->dwType); - state->nr_buttons++; - } + } else if (lpddoi->guidType == GUID_Button) { + if (state->nr_buttons < 32) { + memcpy(state->button[state->nr_buttons].name, lpddoi->tszName, strlen(lpddoi->tszName) + 1); + joystick_log("Button %i : %s %x %x\n", state->nr_buttons, state->button[state->nr_buttons].name, lpddoi->dwOfs, lpddoi->dwType); + state->nr_buttons++; } - else if (lpddoi->guidType == GUID_POV) - { - if (state->nr_povs < 4) - { - memcpy(state->pov[state->nr_povs].name, lpddoi->tszName, strlen(lpddoi->tszName) + 1); - joystick_log("POV %i : %s %x %x\n", state->nr_povs, state->pov[state->nr_povs].name, lpddoi->dwOfs, lpddoi->dwType); - state->nr_povs++; - } - } - else if (lpddoi->guidType == GUID_Slider) - { - if (state->nr_sliders < 2) - { - memcpy(state->slider[state->nr_sliders].name, lpddoi->tszName, strlen(lpddoi->tszName) + 1); - state->slider[state->nr_sliders].id = state->nr_sliders | SLIDER; - joystick_log("Slider %i : %s %x %x\n", state->nr_sliders, state->slider[state->nr_sliders].name, lpddoi->dwOfs, lpddoi->dwType); - state->nr_sliders++; - } + } else if (lpddoi->guidType == GUID_POV) { + if (state->nr_povs < 4) { + memcpy(state->pov[state->nr_povs].name, lpddoi->tszName, strlen(lpddoi->tszName) + 1); + joystick_log("POV %i : %s %x %x\n", state->nr_povs, state->pov[state->nr_povs].name, lpddoi->dwOfs, lpddoi->dwType); + state->nr_povs++; } - - return DIENUM_CONTINUE; + } else if (lpddoi->guidType == GUID_Slider) { + if (state->nr_sliders < 2) { + memcpy(state->slider[state->nr_sliders].name, lpddoi->tszName, strlen(lpddoi->tszName) + 1); + state->slider[state->nr_sliders].id = state->nr_sliders | SLIDER; + joystick_log("Slider %i : %s %x %x\n", state->nr_sliders, state->slider[state->nr_sliders].name, lpddoi->dwOfs, lpddoi->dwType); + state->nr_sliders++; + } + } + + return DIENUM_CONTINUE; } -void joystick_init() +void +joystick_init() { - int c; + int c; - atexit(joystick_close); - - joysticks_present = 0; - - if (FAILED(DirectInput8Create(hinstance, DIRECTINPUT_VERSION, IID_IDirectInput8A, (void **) &lpdi, NULL))) - fatal("joystick_init : DirectInputCreate failed\n"); + atexit(joystick_close); - if (FAILED(lpdi->EnumDevices(DIDEVTYPE_JOYSTICK, joystick_enum_callback, NULL, DIEDFL_ATTACHEDONLY))) - fatal("joystick_init : EnumDevices failed\n"); + joysticks_present = 0; - joystick_log("joystick_init: joysticks_present=%i\n", joysticks_present); - - for (c = 0; c < joysticks_present; c++) - { - LPDIRECTINPUTDEVICE8 lpdi_joystick_temp = NULL; - DIPROPRANGE joy_axis_range; - DIDEVICEINSTANCE device_instance; - DIDEVCAPS devcaps; - - if (FAILED(lpdi->CreateDevice(joystick_guids[c], &lpdi_joystick_temp, NULL))) - fatal("joystick_init : CreateDevice failed\n"); - if (FAILED(lpdi_joystick_temp->QueryInterface(IID_IDirectInputDevice8, (void **)&lpdi_joystick[c]))) - fatal("joystick_init : CreateDevice failed\n"); - lpdi_joystick_temp->Release(); - - memset(&device_instance, 0, sizeof(device_instance)); - device_instance.dwSize = sizeof(device_instance); - if (FAILED(lpdi_joystick[c]->GetDeviceInfo(&device_instance))) - fatal("joystick_init : GetDeviceInfo failed\n"); - joystick_log("Joystick %i :\n", c); - joystick_log(" tszInstanceName = %s\n", device_instance.tszInstanceName); - joystick_log(" tszProductName = %s\n", device_instance.tszProductName); - memcpy(plat_joystick_state[c].name, device_instance.tszInstanceName, strlen(device_instance.tszInstanceName) + 1); + if (FAILED(DirectInput8Create(hinstance, DIRECTINPUT_VERSION, IID_IDirectInput8A, (void **) &lpdi, NULL))) + fatal("joystick_init : DirectInputCreate failed\n"); - memset(&devcaps, 0, sizeof(devcaps)); - devcaps.dwSize = sizeof(devcaps); - if (FAILED(lpdi_joystick[c]->GetCapabilities(&devcaps))) - fatal("joystick_init : GetCapabilities failed\n"); - joystick_log(" Axes = %i\n", devcaps.dwAxes); - joystick_log(" Buttons = %i\n", devcaps.dwButtons); - joystick_log(" POVs = %i\n", devcaps.dwPOVs); + if (FAILED(lpdi->EnumDevices(DIDEVTYPE_JOYSTICK, joystick_enum_callback, NULL, DIEDFL_ATTACHEDONLY))) + fatal("joystick_init : EnumDevices failed\n"); - lpdi_joystick[c]->EnumObjects(DIEnumDeviceObjectsCallback, &plat_joystick_state[c], DIDFT_ALL); - - if (FAILED(lpdi_joystick[c]->SetCooperativeLevel(hwndMain, DISCL_BACKGROUND | DISCL_NONEXCLUSIVE))) - fatal("joystick_init : SetCooperativeLevel failed\n"); - if (FAILED(lpdi_joystick[c]->SetDataFormat(&c_dfDIJoystick))) - fatal("joystick_init : SetDataFormat failed\n"); + joystick_log("joystick_init: joysticks_present=%i\n", joysticks_present); - joy_axis_range.lMin = -32768; - joy_axis_range.lMax = 32767; - joy_axis_range.diph.dwSize = sizeof(DIPROPRANGE); - joy_axis_range.diph.dwHeaderSize = sizeof(DIPROPHEADER); - joy_axis_range.diph.dwHow = DIPH_BYOFFSET; - joy_axis_range.diph.dwObj = DIJOFS_X; - lpdi_joystick[c]->SetProperty(DIPROP_RANGE, &joy_axis_range.diph); - joy_axis_range.diph.dwObj = DIJOFS_Y; - lpdi_joystick[c]->SetProperty(DIPROP_RANGE, &joy_axis_range.diph); - joy_axis_range.diph.dwObj = DIJOFS_Z; - lpdi_joystick[c]->SetProperty(DIPROP_RANGE, &joy_axis_range.diph); - joy_axis_range.diph.dwObj = DIJOFS_RX; - lpdi_joystick[c]->SetProperty(DIPROP_RANGE, &joy_axis_range.diph); - joy_axis_range.diph.dwObj = DIJOFS_RY; - lpdi_joystick[c]->SetProperty(DIPROP_RANGE, &joy_axis_range.diph); - joy_axis_range.diph.dwObj = DIJOFS_RZ; - lpdi_joystick[c]->SetProperty(DIPROP_RANGE, &joy_axis_range.diph); - joy_axis_range.diph.dwObj = DIJOFS_SLIDER(0); - lpdi_joystick[c]->SetProperty(DIPROP_RANGE, &joy_axis_range.diph); - joy_axis_range.diph.dwObj = DIJOFS_SLIDER(1); - lpdi_joystick[c]->SetProperty(DIPROP_RANGE, &joy_axis_range.diph); - - if (FAILED(lpdi_joystick[c]->Acquire())) - fatal("joystick_init : Acquire failed\n"); - } + for (c = 0; c < joysticks_present; c++) { + LPDIRECTINPUTDEVICE8 lpdi_joystick_temp = NULL; + DIPROPRANGE joy_axis_range; + DIDEVICEINSTANCE device_instance; + DIDEVCAPS devcaps; + + if (FAILED(lpdi->CreateDevice(joystick_guids[c], &lpdi_joystick_temp, NULL))) + fatal("joystick_init : CreateDevice failed\n"); + if (FAILED(lpdi_joystick_temp->QueryInterface(IID_IDirectInputDevice8, (void **) &lpdi_joystick[c]))) + fatal("joystick_init : CreateDevice failed\n"); + lpdi_joystick_temp->Release(); + + memset(&device_instance, 0, sizeof(device_instance)); + device_instance.dwSize = sizeof(device_instance); + if (FAILED(lpdi_joystick[c]->GetDeviceInfo(&device_instance))) + fatal("joystick_init : GetDeviceInfo failed\n"); + joystick_log("Joystick %i :\n", c); + joystick_log(" tszInstanceName = %s\n", device_instance.tszInstanceName); + joystick_log(" tszProductName = %s\n", device_instance.tszProductName); + memcpy(plat_joystick_state[c].name, device_instance.tszInstanceName, strlen(device_instance.tszInstanceName) + 1); + + memset(&devcaps, 0, sizeof(devcaps)); + devcaps.dwSize = sizeof(devcaps); + if (FAILED(lpdi_joystick[c]->GetCapabilities(&devcaps))) + fatal("joystick_init : GetCapabilities failed\n"); + joystick_log(" Axes = %i\n", devcaps.dwAxes); + joystick_log(" Buttons = %i\n", devcaps.dwButtons); + joystick_log(" POVs = %i\n", devcaps.dwPOVs); + + lpdi_joystick[c]->EnumObjects(DIEnumDeviceObjectsCallback, &plat_joystick_state[c], DIDFT_ALL); + + if (FAILED(lpdi_joystick[c]->SetCooperativeLevel(hwndMain, DISCL_BACKGROUND | DISCL_NONEXCLUSIVE))) + fatal("joystick_init : SetCooperativeLevel failed\n"); + if (FAILED(lpdi_joystick[c]->SetDataFormat(&c_dfDIJoystick))) + fatal("joystick_init : SetDataFormat failed\n"); + + joy_axis_range.lMin = -32768; + joy_axis_range.lMax = 32767; + joy_axis_range.diph.dwSize = sizeof(DIPROPRANGE); + joy_axis_range.diph.dwHeaderSize = sizeof(DIPROPHEADER); + joy_axis_range.diph.dwHow = DIPH_BYOFFSET; + joy_axis_range.diph.dwObj = DIJOFS_X; + lpdi_joystick[c]->SetProperty(DIPROP_RANGE, &joy_axis_range.diph); + joy_axis_range.diph.dwObj = DIJOFS_Y; + lpdi_joystick[c]->SetProperty(DIPROP_RANGE, &joy_axis_range.diph); + joy_axis_range.diph.dwObj = DIJOFS_Z; + lpdi_joystick[c]->SetProperty(DIPROP_RANGE, &joy_axis_range.diph); + joy_axis_range.diph.dwObj = DIJOFS_RX; + lpdi_joystick[c]->SetProperty(DIPROP_RANGE, &joy_axis_range.diph); + joy_axis_range.diph.dwObj = DIJOFS_RY; + lpdi_joystick[c]->SetProperty(DIPROP_RANGE, &joy_axis_range.diph); + joy_axis_range.diph.dwObj = DIJOFS_RZ; + lpdi_joystick[c]->SetProperty(DIPROP_RANGE, &joy_axis_range.diph); + joy_axis_range.diph.dwObj = DIJOFS_SLIDER(0); + lpdi_joystick[c]->SetProperty(DIPROP_RANGE, &joy_axis_range.diph); + joy_axis_range.diph.dwObj = DIJOFS_SLIDER(1); + lpdi_joystick[c]->SetProperty(DIPROP_RANGE, &joy_axis_range.diph); + + if (FAILED(lpdi_joystick[c]->Acquire())) + fatal("joystick_init : Acquire failed\n"); + } } -void joystick_close() +void +joystick_close() { - if (lpdi_joystick[1]) - { - lpdi_joystick[1]->Release(); - lpdi_joystick[1] = NULL; - } - if (lpdi_joystick[0]) - { - lpdi_joystick[0]->Release(); - lpdi_joystick[0] = NULL; - } + if (lpdi_joystick[1]) { + lpdi_joystick[1]->Release(); + lpdi_joystick[1] = NULL; + } + if (lpdi_joystick[0]) { + lpdi_joystick[0]->Release(); + lpdi_joystick[0] = NULL; + } } -static int joystick_get_axis(int joystick_nr, int mapping) +static int +joystick_get_axis(int joystick_nr, int mapping) { - if (mapping & POV_X) - { - int pov = plat_joystick_state[joystick_nr].p[mapping & 3]; + if (mapping & POV_X) { + int pov = plat_joystick_state[joystick_nr].p[mapping & 3]; - if (LOWORD(pov) == 0xFFFF) - return 0; - else - return sin((2*M_PI * (double)pov) / 36000.0) * 32767; - } - else if (mapping & POV_Y) - { - int pov = plat_joystick_state[joystick_nr].p[mapping & 3]; - - if (LOWORD(pov) == 0xFFFF) - return 0; - else - return -cos((2*M_PI * (double)pov) / 36000.0) * 32767; - } - else if (mapping & SLIDER) - { - return plat_joystick_state[joystick_nr].s[mapping & 3]; - } + if (LOWORD(pov) == 0xFFFF) + return 0; else - return plat_joystick_state[joystick_nr].a[plat_joystick_state[joystick_nr].axis[mapping].id]; + return sin((2 * M_PI * (double) pov) / 36000.0) * 32767; + } else if (mapping & POV_Y) { + int pov = plat_joystick_state[joystick_nr].p[mapping & 3]; + + if (LOWORD(pov) == 0xFFFF) + return 0; + else + return -cos((2 * M_PI * (double) pov) / 36000.0) * 32767; + } else if (mapping & SLIDER) { + return plat_joystick_state[joystick_nr].s[mapping & 3]; + } else + return plat_joystick_state[joystick_nr].a[plat_joystick_state[joystick_nr].axis[mapping].id]; } -void joystick_process(void) +void +joystick_process(void) { - int c, d; + int c; + int d; - if (!joystick_type) return; + if (!joystick_type) + return; - for (c = 0; c < joysticks_present; c++) - { - DIJOYSTATE joystate; - int b; - - if (FAILED(lpdi_joystick[c]->Poll())) - { - lpdi_joystick[c]->Acquire(); - lpdi_joystick[c]->Poll(); - } - if (FAILED(lpdi_joystick[c]->GetDeviceState(sizeof(DIJOYSTATE), (LPVOID)&joystate))) - { - lpdi_joystick[c]->Acquire(); - lpdi_joystick[c]->Poll(); - lpdi_joystick[c]->GetDeviceState(sizeof(DIJOYSTATE), (LPVOID)&joystate); - } - - plat_joystick_state[c].a[0] = joystate.lX; - plat_joystick_state[c].a[1] = joystate.lY; - plat_joystick_state[c].a[2] = joystate.lZ; - plat_joystick_state[c].a[3] = joystate.lRx; - plat_joystick_state[c].a[4] = joystate.lRy; - plat_joystick_state[c].a[5] = joystate.lRz; - plat_joystick_state[c].s[0] = joystate.rglSlider[0]; - plat_joystick_state[c].s[1] = joystate.rglSlider[1]; - - for (b = 0; b < 16; b++) - plat_joystick_state[c].b[b] = joystate.rgbButtons[b] & 0x80; + for (c = 0; c < joysticks_present; c++) { + DIJOYSTATE joystate; + int b; - for (b = 0; b < 4; b++) - plat_joystick_state[c].p[b] = joystate.rgdwPOV[b]; -// joystick_log("joystick %i - x=%i y=%i b[0]=%i b[1]=%i %i\n", c, joystick_state[c].x, joystick_state[c].y, joystick_state[c].b[0], joystick_state[c].b[1], joysticks_present); + if (FAILED(lpdi_joystick[c]->Poll())) { + lpdi_joystick[c]->Acquire(); + lpdi_joystick[c]->Poll(); + } + if (FAILED(lpdi_joystick[c]->GetDeviceState(sizeof(DIJOYSTATE), (LPVOID) &joystate))) { + lpdi_joystick[c]->Acquire(); + lpdi_joystick[c]->Poll(); + lpdi_joystick[c]->GetDeviceState(sizeof(DIJOYSTATE), (LPVOID) &joystate); } - - for (c = 0; c < joystick_get_max_joysticks(joystick_type); c++) - { - if (joystick_state[c].plat_joystick_nr) - { - int joystick_nr = joystick_state[c].plat_joystick_nr - 1; - - for (d = 0; d < joystick_get_axis_count(joystick_type); d++) - joystick_state[c].axis[d] = joystick_get_axis(joystick_nr, joystick_state[c].axis_mapping[d]); - for (d = 0; d < joystick_get_button_count(joystick_type); d++) - joystick_state[c].button[d] = plat_joystick_state[joystick_nr].b[joystick_state[c].button_mapping[d]]; - for (d = 0; d < joystick_get_pov_count(joystick_type); d++) - { - int x, y; - double angle, magnitude; + plat_joystick_state[c].a[0] = joystate.lX; + plat_joystick_state[c].a[1] = joystate.lY; + plat_joystick_state[c].a[2] = joystate.lZ; + plat_joystick_state[c].a[3] = joystate.lRx; + plat_joystick_state[c].a[4] = joystate.lRy; + plat_joystick_state[c].a[5] = joystate.lRz; + plat_joystick_state[c].s[0] = joystate.rglSlider[0]; + plat_joystick_state[c].s[1] = joystate.rglSlider[1]; - x = joystick_get_axis(joystick_nr, joystick_state[c].pov_mapping[d][0]); - y = joystick_get_axis(joystick_nr, joystick_state[c].pov_mapping[d][1]); - - angle = (atan2((double)y, (double)x) * 360.0) / (2*M_PI); - magnitude = sqrt((double)x*(double)x + (double)y*(double)y); - - if (magnitude < 16384) - joystick_state[c].pov[d] = -1; - else - joystick_state[c].pov[d] = ((int)angle + 90 + 360) % 360; - } - } + for (b = 0; b < 16; b++) + plat_joystick_state[c].b[b] = joystate.rgbButtons[b] & 0x80; + + for (b = 0; b < 4; b++) + plat_joystick_state[c].p[b] = joystate.rgdwPOV[b]; + // joystick_log("joystick %i - x=%i y=%i b[0]=%i b[1]=%i %i\n", c, joystick_state[c].x, joystick_state[c].y, joystick_state[c].b[0], joystick_state[c].b[1], joysticks_present); + } + + for (c = 0; c < joystick_get_max_joysticks(joystick_type); c++) { + if (joystick_state[c].plat_joystick_nr) { + int joystick_nr = joystick_state[c].plat_joystick_nr - 1; + + for (d = 0; d < joystick_get_axis_count(joystick_type); d++) + joystick_state[c].axis[d] = joystick_get_axis(joystick_nr, joystick_state[c].axis_mapping[d]); + for (d = 0; d < joystick_get_button_count(joystick_type); d++) + joystick_state[c].button[d] = plat_joystick_state[joystick_nr].b[joystick_state[c].button_mapping[d]]; + + for (d = 0; d < joystick_get_pov_count(joystick_type); d++) { + int x; + int y; + double angle; + double magnitude; + + x = joystick_get_axis(joystick_nr, joystick_state[c].pov_mapping[d][0]); + y = joystick_get_axis(joystick_nr, joystick_state[c].pov_mapping[d][1]); + + angle = (atan2((double) y, (double) x) * 360.0) / (2 * M_PI); + magnitude = sqrt((double) x * (double) x + (double) y * (double) y); + + if (magnitude < 16384) + joystick_state[c].pov[d] = -1; else - { - for (d = 0; d < joystick_get_axis_count(joystick_type); d++) - joystick_state[c].axis[d] = 0; - for (d = 0; d < joystick_get_button_count(joystick_type); d++) - joystick_state[c].button[d] = 0; - for (d = 0; d < joystick_get_pov_count(joystick_type); d++) - joystick_state[c].pov[d] = -1; - } + joystick_state[c].pov[d] = ((int) angle + 90 + 360) % 360; + } + } else { + for (d = 0; d < joystick_get_axis_count(joystick_type); d++) + joystick_state[c].axis[d] = 0; + for (d = 0; d < joystick_get_button_count(joystick_type); d++) + joystick_state[c].button[d] = 0; + for (d = 0; d < joystick_get_pov_count(joystick_type); d++) + joystick_state[c].pov[d] = -1; } + } } -void win_joystick_handle(PRAWINPUT raw) {} +void +win_joystick_handle(UNUSED(PRAWINPUT raw)) +{ + // Nothing to be done here, atleast currently +} diff --git a/src/win/win_joystick_rawinput.c b/src/win/win_joystick_rawinput.c index be808fc47..c5c2a3d6e 100644 --- a/src/win/win_joystick_rawinput.c +++ b/src/win/win_joystick_rawinput.c @@ -1,20 +1,22 @@ /* - * 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. + * 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. + * This file is part of the 86Box distribution. * - * RawInput joystick interface. + * RawInput joystick interface. * - * Authors: Sarah Walker, - * Miran Grca, - * GH Cao, * - * Copyright 2008-2018 Sarah Walker. - * Copyright 2016-2018 Miran Grca. - * Copyright 2020 GH Cao. + * + * Authors: Miran Grca, + * GH Cao, + * Jasmine Iwanek, + * + * Copyright 2016-2018 Miran Grca. + * Copyright 2020 GH Cao. + * Copyright 2021-2023 Jasmine Iwanek. */ #include #include @@ -36,436 +38,453 @@ #ifdef ENABLE_JOYSTICK_LOG int joystick_do_log = ENABLE_JOYSTICK_LOG; - static void joystick_log(const char *fmt, ...) { - va_list ap; + va_list ap; - if (joystick_do_log) { - va_start(ap, fmt); - pclog_ex(fmt, ap); - va_end(ap); - } + if (joystick_do_log) { + va_start(ap, fmt); + pclog_ex(fmt, ap); + va_end(ap); + } } #else -#define joystick_log(fmt, ...) +# define joystick_log(fmt, ...) #endif typedef struct { - HANDLE hdevice; - PHIDP_PREPARSED_DATA data; - - USAGE usage_button[256]; + HANDLE hdevice; + PHIDP_PREPARSED_DATA data; - struct raw_axis_t { - USAGE usage; - USHORT link; - USHORT bitsize; - LONG max; - LONG min; - } axis[8]; + USAGE usage_button[256]; - struct raw_pov_t { - USAGE usage; - USHORT link; - LONG max; - LONG min; - } pov[4]; + struct raw_axis_t { + USAGE usage; + USHORT link; + USHORT bitsize; + LONG max; + LONG min; + } axis[8]; + + struct raw_pov_t { + USAGE usage; + USHORT link; + LONG max; + LONG min; + } pov[4]; } raw_joystick_t; plat_joystick_t plat_joystick_state[MAX_PLAT_JOYSTICKS]; -joystick_t joystick_state[MAX_JOYSTICKS]; -int joysticks_present = 0; +joystick_t joystick_state[MAX_JOYSTICKS]; +int joysticks_present = 0; raw_joystick_t raw_joystick_state[MAX_PLAT_JOYSTICKS]; /* We only use the first 32 buttons reported, from Usage ID 1-128 */ -void joystick_add_button(raw_joystick_t* rawjoy, plat_joystick_t* joy, USAGE usage) { - if (joy->nr_buttons >= 32) return; - if (usage < 1 || usage > 128) return; - - rawjoy->usage_button[usage] = joy->nr_buttons; - sprintf(joy->button[joy->nr_buttons].name, "Button %d", usage); - joy->nr_buttons++; -} - -void joystick_add_axis(raw_joystick_t* rawjoy, plat_joystick_t* joy, PHIDP_VALUE_CAPS prop) { - if (joy->nr_axes >= 8) return; - - switch (prop->Range.UsageMin) { - case HID_USAGE_GENERIC_X: - sprintf(joy->axis[joy->nr_axes].name, "X"); - break; - case HID_USAGE_GENERIC_Y: - sprintf(joy->axis[joy->nr_axes].name, "Y"); - break; - case HID_USAGE_GENERIC_Z: - sprintf(joy->axis[joy->nr_axes].name, "Z"); - break; - case HID_USAGE_GENERIC_RX: - sprintf(joy->axis[joy->nr_axes].name, "RX"); - break; - case HID_USAGE_GENERIC_RY: - sprintf(joy->axis[joy->nr_axes].name, "RY"); - break; - case HID_USAGE_GENERIC_RZ: - sprintf(joy->axis[joy->nr_axes].name, "RZ"); - break; - default: - return; - } - - joy->axis[joy->nr_axes].id = joy->nr_axes; - rawjoy->axis[joy->nr_axes].usage = prop->Range.UsageMin; - rawjoy->axis[joy->nr_axes].link = prop->LinkCollection; - rawjoy->axis[joy->nr_axes].bitsize = prop->BitSize; - - /* Assume unsigned when min >= 0 */ - if (prop->LogicalMin < 0) { - rawjoy->axis[joy->nr_axes].max = prop->LogicalMax; - } else { - /* - * Some joysticks will send -1 in LogicalMax, like Xbox Controllers - * so we need to mask that to appropriate value (instead of 0xFFFFFFFF) - */ - rawjoy->axis[joy->nr_axes].max = prop->LogicalMax & ((1 << prop->BitSize) - 1); - } - rawjoy->axis[joy->nr_axes].min = prop->LogicalMin; - - joy->nr_axes++; -} - -void joystick_add_pov(raw_joystick_t* rawjoy, plat_joystick_t* joy, PHIDP_VALUE_CAPS prop) { - if (joy->nr_povs >= 4) return; - - sprintf(joy->pov[joy->nr_povs].name, "POV %d", joy->nr_povs+1); - rawjoy->pov[joy->nr_povs].usage = prop->Range.UsageMin; - rawjoy->pov[joy->nr_povs].link = prop->LinkCollection; - rawjoy->pov[joy->nr_povs].min = prop->LogicalMin; - rawjoy->pov[joy->nr_povs].max = prop->LogicalMax; - - joy->nr_povs++; -} - -void joystick_get_capabilities(raw_joystick_t* rawjoy, plat_joystick_t* joy) { - UINT size = 0; - PHIDP_BUTTON_CAPS btn_caps = NULL; - PHIDP_VALUE_CAPS val_caps = NULL; - - /* Get preparsed data (HID data format) */ - GetRawInputDeviceInfoW(rawjoy->hdevice, RIDI_PREPARSEDDATA, NULL, &size); - rawjoy->data = malloc(size); - if (GetRawInputDeviceInfoW(rawjoy->hdevice, RIDI_PREPARSEDDATA, rawjoy->data, &size) <= 0) - fatal("joystick_get_capabilities: Failed to get preparsed data.\n"); - - HIDP_CAPS caps; - HidP_GetCaps(rawjoy->data, &caps); - - /* Buttons */ - if (caps.NumberInputButtonCaps > 0) { - btn_caps = calloc(caps.NumberInputButtonCaps, sizeof(HIDP_BUTTON_CAPS)); - if (HidP_GetButtonCaps(HidP_Input, btn_caps, &caps.NumberInputButtonCaps, rawjoy->data) != HIDP_STATUS_SUCCESS) { - joystick_log("joystick_get_capabilities: Failed to query input buttons.\n"); - goto end; - } - /* We only detect generic stuff */ - for (int c=0; c 0) { - val_caps = calloc(caps.NumberInputValueCaps, sizeof(HIDP_VALUE_CAPS)); - if (HidP_GetValueCaps(HidP_Input, val_caps, &caps.NumberInputValueCaps, rawjoy->data) != HIDP_STATUS_SUCCESS) { - joystick_log("joystick_get_capabilities: Failed to query axes and povs.\n"); - goto end; - } - /* We only detect generic stuff */ - for (int c=0; chdevice, RIDI_DEVICENAME, device_name, &size); - device_name = calloc(size, sizeof(char)); - if (GetRawInputDeviceInfoA(rawjoy->hdevice, RIDI_DEVICENAME, device_name, &size) <= 0) - fatal("joystick_get_capabilities: Failed to get device name.\n"); - - HANDLE hDevObj = CreateFile(device_name, GENERIC_READ | GENERIC_WRITE, - FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING, 0, NULL); - if (hDevObj) { - HidD_GetProductString(hDevObj, device_desc_wide, sizeof(WCHAR) * 200); - CloseHandle(hDevObj); - } - free(device_name); - - int result = WideCharToMultiByte(CP_ACP, 0, device_desc_wide, 200, joy->name, 260, NULL, NULL); - if (result == 0 || strlen(joy->name) == 0) - sprintf(joy->name, - "RawInput %s, VID:%04lX PID:%04lX", - info->hid.usUsage == HID_USAGE_GENERIC_JOYSTICK ? "Joystick" : "Gamepad", - info->hid.dwVendorId, - info->hid.dwProductId); -} - -void joystick_init() +void +joystick_add_button(raw_joystick_t *rawjoy, plat_joystick_t *joy, USAGE usage) { - UINT size = 0; - atexit(joystick_close); + if (joy->nr_buttons >= 32) + return; + if (usage < 1 || usage > 128) + return; - joysticks_present = 0; - memset(raw_joystick_state, 0, sizeof(raw_joystick_t) * MAX_PLAT_JOYSTICKS); - - /* Get a list of raw input devices from Windows */ - UINT raw_devices = 0; - GetRawInputDeviceList(NULL, &raw_devices, sizeof(RAWINPUTDEVICELIST)); - PRAWINPUTDEVICELIST deviceList = calloc(raw_devices, sizeof(RAWINPUTDEVICELIST)); - GetRawInputDeviceList(deviceList, &raw_devices, sizeof(RAWINPUTDEVICELIST)); - - for (int i=0; i= MAX_PLAT_JOYSTICKS) break; - if (deviceList[i].dwType != RIM_TYPEHID) continue; - - /* Get device info: hardware IDs and usage IDs */ - GetRawInputDeviceInfoA(deviceList[i].hDevice, RIDI_DEVICEINFO, NULL, &size); - info = malloc(size); - info->cbSize = sizeof(RID_DEVICE_INFO); - if (GetRawInputDeviceInfoA(deviceList[i].hDevice, RIDI_DEVICEINFO, info, &size) <= 0) - goto end_loop; - - /* If this is not a joystick/gamepad, skip */ - if (info->hid.usUsagePage != HID_USAGE_PAGE_GENERIC) goto end_loop; - if (info->hid.usUsage != HID_USAGE_GENERIC_JOYSTICK && - info->hid.usUsage != HID_USAGE_GENERIC_GAMEPAD) goto end_loop; - - plat_joystick_t *joy = &plat_joystick_state[joysticks_present]; - raw_joystick_t *rawjoy = &raw_joystick_state[joysticks_present]; - rawjoy->hdevice = deviceList[i].hDevice; - - joystick_get_capabilities(rawjoy, joy); - joystick_get_device_name(rawjoy, joy, info); - - joystick_log("joystick_init: %s - %d buttons, %d axes, %d POVs\n", - joy->name, joy->nr_buttons, joy->nr_axes, joy->nr_povs); - - joysticks_present++; - - end_loop: - free(info); - } - - joystick_log("joystick_init: joysticks_present=%i\n", joysticks_present); - - /* Initialize the RawInput (joystick and gamepad) module. */ - RAWINPUTDEVICE ridev[2]; - ridev[0].dwFlags = 0; - ridev[0].hwndTarget = NULL; - ridev[0].usUsagePage = HID_USAGE_PAGE_GENERIC; - ridev[0].usUsage = HID_USAGE_GENERIC_JOYSTICK; - - ridev[1].dwFlags = 0; - ridev[1].hwndTarget = NULL; - ridev[1].usUsagePage = HID_USAGE_PAGE_GENERIC; - ridev[1].usUsage = HID_USAGE_GENERIC_GAMEPAD; - - if (!RegisterRawInputDevices(ridev, 2, sizeof(RAWINPUTDEVICE))) - fatal("plat_joystick_init: RegisterRawInputDevices failed\n"); + rawjoy->usage_button[usage] = joy->nr_buttons; + sprintf(joy->button[joy->nr_buttons].name, "Button %d", usage); + joy->nr_buttons++; } -void joystick_close() +void +joystick_add_axis(raw_joystick_t *rawjoy, plat_joystick_t *joy, PHIDP_VALUE_CAPS prop) { - RAWINPUTDEVICE ridev[2]; - ridev[0].dwFlags = RIDEV_REMOVE; - ridev[0].hwndTarget = NULL; - ridev[0].usUsagePage = HID_USAGE_PAGE_GENERIC; - ridev[0].usUsage = HID_USAGE_GENERIC_JOYSTICK; + if (joy->nr_axes >= 8) + return; - ridev[1].dwFlags = RIDEV_REMOVE; - ridev[1].hwndTarget = NULL; - ridev[1].usUsagePage = HID_USAGE_PAGE_GENERIC; - ridev[1].usUsage = HID_USAGE_GENERIC_GAMEPAD; + switch (prop->Range.UsageMin) { + case HID_USAGE_GENERIC_X: + sprintf(joy->axis[joy->nr_axes].name, "X"); + break; + case HID_USAGE_GENERIC_Y: + sprintf(joy->axis[joy->nr_axes].name, "Y"); + break; + case HID_USAGE_GENERIC_Z: + sprintf(joy->axis[joy->nr_axes].name, "Z"); + break; + case HID_USAGE_GENERIC_RX: + sprintf(joy->axis[joy->nr_axes].name, "RX"); + break; + case HID_USAGE_GENERIC_RY: + sprintf(joy->axis[joy->nr_axes].name, "RY"); + break; + case HID_USAGE_GENERIC_RZ: + sprintf(joy->axis[joy->nr_axes].name, "RZ"); + break; + default: + return; + } - RegisterRawInputDevices(ridev, 2, sizeof(RAWINPUTDEVICE)); + joy->axis[joy->nr_axes].id = joy->nr_axes; + rawjoy->axis[joy->nr_axes].usage = prop->Range.UsageMin; + rawjoy->axis[joy->nr_axes].link = prop->LinkCollection; + rawjoy->axis[joy->nr_axes].bitsize = prop->BitSize; + + /* Assume unsigned when min >= 0 */ + if (prop->LogicalMin < 0) { + rawjoy->axis[joy->nr_axes].max = prop->LogicalMax; + } else { + /* + * Some joysticks will send -1 in LogicalMax, like Xbox Controllers + * so we need to mask that to appropriate value (instead of 0xFFFFFFFF) + */ + rawjoy->axis[joy->nr_axes].max = prop->LogicalMax & ((1ULL << prop->BitSize) - 1); + } + rawjoy->axis[joy->nr_axes].min = prop->LogicalMin; + + joy->nr_axes++; } - -void win_joystick_handle(PRAWINPUT raw) +void +joystick_add_pov(raw_joystick_t *rawjoy, plat_joystick_t *joy, PHIDP_VALUE_CAPS prop) { - HRESULT r; - int j = -1; /* current joystick index, -1 when not found */ + if (joy->nr_povs >= 4) + return; - /* If the input is not from a known device, we ignore it */ - for (int i=0; iheader.hDevice) { - j = i; - break; - } - } - if (j == -1) return; - - /* Read buttons */ - USAGE usage_list[128] = {0}; - ULONG usage_length = plat_joystick_state[j].nr_buttons; - memset(plat_joystick_state[j].b, 0, 32 * sizeof(int)); + sprintf(joy->pov[joy->nr_povs].name, "POV %d", joy->nr_povs + 1); + rawjoy->pov[joy->nr_povs].usage = prop->Range.UsageMin; + rawjoy->pov[joy->nr_povs].link = prop->LinkCollection; + rawjoy->pov[joy->nr_povs].min = prop->LogicalMin; + rawjoy->pov[joy->nr_povs].max = prop->LogicalMax; - r = HidP_GetUsages(HidP_Input, HID_USAGE_PAGE_BUTTON, 0, usage_list, &usage_length, - raw_joystick_state[j].data, (PCHAR)raw->data.hid.bRawData, raw->data.hid.dwSizeHid); - - if (r == HIDP_STATUS_SUCCESS) { - for (int i=0; imax - axis->min + 1) / 2; - - r = HidP_GetUsageValue(HidP_Input, HID_USAGE_PAGE_GENERIC, axis->link, axis->usage, &uvalue, - raw_joystick_state[j].data, (PCHAR)raw->data.hid.bRawData, raw->data.hid.dwSizeHid); - - if (r == HIDP_STATUS_SUCCESS) { - if (axis->min < 0) { - /* extend signed uvalue to LONG */ - if (uvalue & (1 << (axis->bitsize-1))) { - ULONG mask = (1 << axis->bitsize) - 1; - value = -1U ^ mask; - value |= uvalue; - } else { - value = uvalue; - } - } else { - /* Assume unsigned when min >= 0, convert to a signed value */ - value = (LONG)uvalue - center; - } - if (abs(value) == 1) value = 0; - value = value * 32768 / center; - } - - plat_joystick_state[j].a[a] = value; - //joystick_log("%s %-06d ", plat_joystick_state[j].axis[a].name, plat_joystick_state[j].a[a]); - } - - /* read povs */ - for (int p=0; plink, pov->usage, &uvalue, - raw_joystick_state[j].data, (PCHAR)raw->data.hid.bRawData, raw->data.hid.dwSizeHid); - - if (r == HIDP_STATUS_SUCCESS && (uvalue >= pov->min && uvalue <= pov->max)) { - value = (uvalue - pov->min) * 36000; - value /= (pov->max - pov->min + 1); - value %= 36000; - } - - plat_joystick_state[j].p[p] = value; - - //joystick_log("%s %-3d ", plat_joystick_state[j].pov[p].name, plat_joystick_state[j].p[p]); - - } - //joystick_log("\n"); + joy->nr_povs++; } - -static int joystick_get_axis(int joystick_nr, int mapping) +void +joystick_get_capabilities(raw_joystick_t *rawjoy, plat_joystick_t *joy) { - if (mapping & POV_X) - { - int pov = plat_joystick_state[joystick_nr].p[mapping & 3]; - if (LOWORD(pov) == 0xFFFF) - return 0; - else - return sin((2*M_PI * (double)pov) / 36000.0) * 32767; - } - else if (mapping & POV_Y) - { - int pov = plat_joystick_state[joystick_nr].p[mapping & 3]; - - if (LOWORD(pov) == 0xFFFF) - return 0; - else - return -cos((2*M_PI * (double)pov) / 36000.0) * 32767; - } - else - return plat_joystick_state[joystick_nr].a[plat_joystick_state[joystick_nr].axis[mapping].id]; - + UINT size = 0; + PHIDP_BUTTON_CAPS btn_caps = NULL; + PHIDP_VALUE_CAPS val_caps = NULL; + + /* Get preparsed data (HID data format) */ + GetRawInputDeviceInfoW(rawjoy->hdevice, RIDI_PREPARSEDDATA, NULL, &size); + rawjoy->data = malloc(size); + if (GetRawInputDeviceInfoW(rawjoy->hdevice, RIDI_PREPARSEDDATA, rawjoy->data, &size) <= 0) + fatal("joystick_get_capabilities: Failed to get preparsed data.\n"); + + HIDP_CAPS caps; + HidP_GetCaps(rawjoy->data, &caps); + + /* Buttons */ + if (caps.NumberInputButtonCaps > 0) { + btn_caps = calloc(caps.NumberInputButtonCaps, sizeof(HIDP_BUTTON_CAPS)); + if (HidP_GetButtonCaps(HidP_Input, btn_caps, &caps.NumberInputButtonCaps, rawjoy->data) != HIDP_STATUS_SUCCESS) { + joystick_log("joystick_get_capabilities: Failed to query input buttons.\n"); + goto end; + } + /* We only detect generic stuff */ + for (int c = 0; c < caps.NumberInputButtonCaps; c++) { + if (btn_caps[c].UsagePage != HID_USAGE_PAGE_BUTTON) + continue; + + int button_count = btn_caps[c].Range.UsageMax - btn_caps[c].Range.UsageMin + 1; + for (int b = 0; b < button_count; b++) { + joystick_add_button(rawjoy, joy, b + btn_caps[c].Range.UsageMin); + } + } + } + + /* Values (axes and povs) */ + if (caps.NumberInputValueCaps > 0) { + val_caps = calloc(caps.NumberInputValueCaps, sizeof(HIDP_VALUE_CAPS)); + if (HidP_GetValueCaps(HidP_Input, val_caps, &caps.NumberInputValueCaps, rawjoy->data) != HIDP_STATUS_SUCCESS) { + joystick_log("joystick_get_capabilities: Failed to query axes and povs.\n"); + goto end; + } + /* We only detect generic stuff */ + for (int c = 0; c < caps.NumberInputValueCaps; c++) { + if (val_caps[c].UsagePage != HID_USAGE_PAGE_GENERIC) + continue; + + if (val_caps[c].Range.UsageMin == HID_USAGE_GENERIC_HATSWITCH) + joystick_add_pov(rawjoy, joy, &val_caps[c]); + else + joystick_add_axis(rawjoy, joy, &val_caps[c]); + } + } + +end: + free(btn_caps); + free(val_caps); } - -void joystick_process(void) +void +joystick_get_device_name(raw_joystick_t *rawjoy, plat_joystick_t *joy, PRID_DEVICE_INFO info) { - int c, d; + UINT size = 0; + WCHAR *device_name = NULL; + WCHAR device_desc_wide[200] = { 0 }; - if (joystick_type == 7) return; + GetRawInputDeviceInfoW(rawjoy->hdevice, RIDI_DEVICENAME, device_name, &size); + device_name = calloc(size, sizeof(WCHAR)); + if (GetRawInputDeviceInfoW(rawjoy->hdevice, RIDI_DEVICENAME, device_name, &size) <= 0) + fatal("joystick_get_capabilities: Failed to get device name.\n"); - for (c = 0; c < joystick_get_max_joysticks(joystick_type); c++) - { - if (joystick_state[c].plat_joystick_nr) - { - int joystick_nr = joystick_state[c].plat_joystick_nr - 1; - - for (d = 0; d < joystick_get_axis_count(joystick_type); d++) - joystick_state[c].axis[d] = joystick_get_axis(joystick_nr, joystick_state[c].axis_mapping[d]); - for (d = 0; d < joystick_get_button_count(joystick_type); d++) - joystick_state[c].button[d] = plat_joystick_state[joystick_nr].b[joystick_state[c].button_mapping[d]]; + HANDLE hDevObj = CreateFileW(device_name, GENERIC_READ | GENERIC_WRITE, + FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING, 0, NULL); + if (hDevObj) { + HidD_GetProductString(hDevObj, device_desc_wide, sizeof(WCHAR) * 200); + CloseHandle(hDevObj); + } + free(device_name); - for (d = 0; d < joystick_get_pov_count(joystick_type); d++) - { - int x, y; - double angle, magnitude; - - x = joystick_get_axis(joystick_nr, joystick_state[c].pov_mapping[d][0]); - y = joystick_get_axis(joystick_nr, joystick_state[c].pov_mapping[d][1]); - - angle = (atan2((double)y, (double)x) * 360.0) / (2*M_PI); - magnitude = sqrt((double)x*(double)x + (double)y*(double)y); - - if (magnitude < 16384) - joystick_state[c].pov[d] = -1; - else - joystick_state[c].pov[d] = ((int)angle + 90 + 360) % 360; - } - } - else - { - for (d = 0; d < joystick_get_axis_count(joystick_type); d++) - joystick_state[c].axis[d] = 0; - for (d = 0; d < joystick_get_button_count(joystick_type); d++) - joystick_state[c].button[d] = 0; - for (d = 0; d < joystick_get_pov_count(joystick_type); d++) - joystick_state[c].pov[d] = -1; - } - } + int result = WideCharToMultiByte(CP_ACP, 0, device_desc_wide, 200, joy->name, 260, NULL, NULL); + if (result == 0 || strlen(joy->name) == 0) + sprintf(joy->name, + "RawInput %s, VID:%04lX PID:%04lX", + info->hid.usUsage == HID_USAGE_GENERIC_JOYSTICK ? "Joystick" : "Gamepad", + info->hid.dwVendorId, + info->hid.dwProductId); } +void +joystick_init(void) +{ + UINT size = 0; + atexit(joystick_close); + + joysticks_present = 0; + memset(raw_joystick_state, 0, sizeof(raw_joystick_t) * MAX_PLAT_JOYSTICKS); + + /* Get a list of raw input devices from Windows */ + UINT raw_devices = 0; + GetRawInputDeviceList(NULL, &raw_devices, sizeof(RAWINPUTDEVICELIST)); + PRAWINPUTDEVICELIST deviceList = calloc(raw_devices, sizeof(RAWINPUTDEVICELIST)); + GetRawInputDeviceList(deviceList, &raw_devices, sizeof(RAWINPUTDEVICELIST)); + + for (int i = 0; i < raw_devices; i++) { + PRID_DEVICE_INFO info = NULL; + + if (joysticks_present >= MAX_PLAT_JOYSTICKS) + break; + if (deviceList[i].dwType != RIM_TYPEHID) + continue; + + /* Get device info: hardware IDs and usage IDs */ + GetRawInputDeviceInfoA(deviceList[i].hDevice, RIDI_DEVICEINFO, NULL, &size); + info = malloc(size); + info->cbSize = sizeof(RID_DEVICE_INFO); + if (GetRawInputDeviceInfoA(deviceList[i].hDevice, RIDI_DEVICEINFO, info, &size) <= 0) + goto end_loop; + + /* If this is not a joystick/gamepad, skip */ + if (info->hid.usUsagePage != HID_USAGE_PAGE_GENERIC) + goto end_loop; + if (info->hid.usUsage != HID_USAGE_GENERIC_JOYSTICK && info->hid.usUsage != HID_USAGE_GENERIC_GAMEPAD) + goto end_loop; + + plat_joystick_t *joy = &plat_joystick_state[joysticks_present]; + raw_joystick_t *rawjoy = &raw_joystick_state[joysticks_present]; + rawjoy->hdevice = deviceList[i].hDevice; + + joystick_get_capabilities(rawjoy, joy); + joystick_get_device_name(rawjoy, joy, info); + + joystick_log("joystick_init: %s - %d buttons, %d axes, %d POVs\n", + joy->name, joy->nr_buttons, joy->nr_axes, joy->nr_povs); + + joysticks_present++; + +end_loop: + free(info); + } + + joystick_log("joystick_init: joysticks_present=%i\n", joysticks_present); + + /* Initialize the RawInput (joystick and gamepad) module. */ + RAWINPUTDEVICE ridev[2]; + ridev[0].dwFlags = 0; + ridev[0].hwndTarget = NULL; + ridev[0].usUsagePage = HID_USAGE_PAGE_GENERIC; + ridev[0].usUsage = HID_USAGE_GENERIC_JOYSTICK; + + ridev[1].dwFlags = 0; + ridev[1].hwndTarget = NULL; + ridev[1].usUsagePage = HID_USAGE_PAGE_GENERIC; + ridev[1].usUsage = HID_USAGE_GENERIC_GAMEPAD; + + if (!RegisterRawInputDevices(ridev, 2, sizeof(RAWINPUTDEVICE))) + fatal("plat_joystick_init: RegisterRawInputDevices failed\n"); +} + +void +joystick_close(void) +{ + RAWINPUTDEVICE ridev[2]; + ridev[0].dwFlags = RIDEV_REMOVE; + ridev[0].hwndTarget = NULL; + ridev[0].usUsagePage = HID_USAGE_PAGE_GENERIC; + ridev[0].usUsage = HID_USAGE_GENERIC_JOYSTICK; + + ridev[1].dwFlags = RIDEV_REMOVE; + ridev[1].hwndTarget = NULL; + ridev[1].usUsagePage = HID_USAGE_PAGE_GENERIC; + ridev[1].usUsage = HID_USAGE_GENERIC_GAMEPAD; + + RegisterRawInputDevices(ridev, 2, sizeof(RAWINPUTDEVICE)); +} + +void +win_joystick_handle(PRAWINPUT raw) +{ + HRESULT r; + int j = -1; /* current joystick index, -1 when not found */ + + /* If the input is not from a known device, we ignore it */ + for (int i = 0; i < joysticks_present; i++) { + if (raw_joystick_state[i].hdevice == raw->header.hDevice) { + j = i; + break; + } + } + if (j == -1) + return; + + /* Read buttons */ + USAGE usage_list[128] = { 0 }; + ULONG usage_length = plat_joystick_state[j].nr_buttons; + memset(plat_joystick_state[j].b, 0, 32 * sizeof(int)); + + r = HidP_GetUsages(HidP_Input, HID_USAGE_PAGE_BUTTON, 0, usage_list, &usage_length, + raw_joystick_state[j].data, (PCHAR) raw->data.hid.bRawData, raw->data.hid.dwSizeHid); + + if (r == HIDP_STATUS_SUCCESS) { + for (int i = 0; i < usage_length; i++) { + int button = raw_joystick_state[j].usage_button[usage_list[i]]; + plat_joystick_state[j].b[button] = 128; + } + } + + /* Read axes */ + for (int a = 0; a < plat_joystick_state[j].nr_axes; a++) { + const struct raw_axis_t *axis = &raw_joystick_state[j].axis[a]; + ULONG uvalue = 0; + LONG value = 0; + LONG center = (axis->max - axis->min + 1) / 2; + + r = HidP_GetUsageValue(HidP_Input, HID_USAGE_PAGE_GENERIC, axis->link, axis->usage, &uvalue, + raw_joystick_state[j].data, (PCHAR) raw->data.hid.bRawData, raw->data.hid.dwSizeHid); + + if (r == HIDP_STATUS_SUCCESS) { + if (axis->min < 0) { + /* extend signed uvalue to LONG */ + if (uvalue & (1 << (axis->bitsize - 1))) { + ULONG mask = (1 << axis->bitsize) - 1; + value = -1U ^ mask; + value |= uvalue; + } else { + value = uvalue; + } + } else { + /* Assume unsigned when min >= 0, convert to a signed value */ + value = (LONG) uvalue - center; + } + if (abs(value) == 1) + value = 0; + value = value * 32768 / center; + } + + plat_joystick_state[j].a[a] = value; + // joystick_log("%s %-06d ", plat_joystick_state[j].axis[a].name, plat_joystick_state[j].a[a]); + } + + /* read povs */ + for (int p = 0; p < plat_joystick_state[j].nr_povs; p++) { + const struct raw_pov_t *pov = &raw_joystick_state[j].pov[p]; + ULONG uvalue = 0; + LONG value = -1; + + r = HidP_GetUsageValue(HidP_Input, HID_USAGE_PAGE_GENERIC, pov->link, pov->usage, &uvalue, + raw_joystick_state[j].data, (PCHAR) raw->data.hid.bRawData, raw->data.hid.dwSizeHid); + + if (r == HIDP_STATUS_SUCCESS && (uvalue >= pov->min && uvalue <= pov->max)) { + value = (uvalue - pov->min) * 36000; + value /= (pov->max - pov->min + 1); + value %= 36000; + } + + plat_joystick_state[j].p[p] = value; + +#if 0 + joystick_log("%s %-3d ", plat_joystick_state[j].pov[p].name, plat_joystick_state[j].p[p]); +#endif + } +#if 0 + joystick_log("\n"); +#endif +} + +static int +joystick_get_axis(int joystick_nr, int mapping) +{ + if (mapping & POV_X) { + int pov = plat_joystick_state[joystick_nr].p[mapping & 3]; + if (LOWORD(pov) == 0xFFFF) + return 0; + else + return sin((2 * M_PI * (double) pov) / 36000.0) * 32767; + } else if (mapping & POV_Y) { + int pov = plat_joystick_state[joystick_nr].p[mapping & 3]; + + if (LOWORD(pov) == 0xFFFF) + return 0; + else + return -cos((2 * M_PI * (double) pov) / 36000.0) * 32767; + } else + return plat_joystick_state[joystick_nr].a[plat_joystick_state[joystick_nr].axis[mapping].id]; +} + +void +joystick_process(void) +{ + int d; + + if (joystick_type == JS_TYPE_NONE) + return; + + for (int c = 0; c < joystick_get_max_joysticks(joystick_type); c++) { + if (joystick_state[c].plat_joystick_nr) { + int joystick_nr = joystick_state[c].plat_joystick_nr - 1; + + for (d = 0; d < joystick_get_axis_count(joystick_type); d++) + joystick_state[c].axis[d] = joystick_get_axis(joystick_nr, joystick_state[c].axis_mapping[d]); + for (d = 0; d < joystick_get_button_count(joystick_type); d++) + joystick_state[c].button[d] = plat_joystick_state[joystick_nr].b[joystick_state[c].button_mapping[d]]; + + for (d = 0; d < joystick_get_pov_count(joystick_type); d++) { + int x; + int y; + double angle; + double magnitude; + + x = joystick_get_axis(joystick_nr, joystick_state[c].pov_mapping[d][0]); + y = joystick_get_axis(joystick_nr, joystick_state[c].pov_mapping[d][1]); + + angle = (atan2((double) y, (double) x) * 360.0) / (2 * M_PI); + magnitude = sqrt((double) x * (double) x + (double) y * (double) y); + + if (magnitude < 16384) + joystick_state[c].pov[d] = -1; + else + joystick_state[c].pov[d] = ((int) angle + 90 + 360) % 360; + } + } else { + for (d = 0; d < joystick_get_axis_count(joystick_type); d++) + joystick_state[c].axis[d] = 0; + for (d = 0; d < joystick_get_button_count(joystick_type); d++) + joystick_state[c].button[d] = 0; + for (d = 0; d < joystick_get_pov_count(joystick_type); d++) + joystick_state[c].pov[d] = -1; + } + } +} diff --git a/src/win/win_joystick_xinput.c b/src/win/win_joystick_xinput.c index 4b7643c43..f313522a9 100644 --- a/src/win/win_joystick_xinput.c +++ b/src/win/win_joystick_xinput.c @@ -1,22 +1,22 @@ /* - * 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. + * 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. + * This file is part of the 86Box distribution. * - * Xinput joystick interface. + * Xinput joystick interface. * * * - * Authors: Sarah Walker, - * Miran Grca, - * GH Cao, + * Authors: Miran Grca, + * GH Cao, + * Jasmine Iwanek, * - * Copyright 2008-2018 Sarah Walker. - * Copyright 2016-2018 Miran Grca. - * Copyright 2019 GH Cao. + * Copyright 2016-2018 Miran Grca. + * Copyright 2019 GH Cao. + * Copyright 2021-2023 Jasmine Iwanek. */ #include #define _USE_MATH_DEFINES @@ -32,233 +32,237 @@ #include <86box/win.h> #define XINPUT_MAX_JOYSTICKS 4 -#define XINPUT_NAME "Xinput compatiable controller" -#define XINPUT_NAME_LX "Left Stick X" -#define XINPUT_NAME_LY "Left Stick Y" -#define XINPUT_NAME_RX "Right Stick X" -#define XINPUT_NAME_RY "Right Stick Y" -#define XINPUT_NAME_DPAD_X "D-pad X" -#define XINPUT_NAME_DPAD_Y "D-pad Y" -#define XINPUT_NAME_LB "LB" -#define XINPUT_NAME_RB "RB" -#define XINPUT_NAME_LT "LT" -#define XINPUT_NAME_RT "RT" -#define XINPUT_NAME_A "A" -#define XINPUT_NAME_B "B" -#define XINPUT_NAME_X "X" -#define XINPUT_NAME_Y "Y" -#define XINPUT_NAME_BACK "Back/View" -#define XINPUT_NAME_START "Start/Menu" -#define XINPUT_NAME_LS "Left Stick" -#define XINPUT_NAME_RS "Right Stick" +#define XINPUT_NAME "Xinput compatiable controller" +#define XINPUT_NAME_LX "Left Stick X" +#define XINPUT_NAME_LY "Left Stick Y" +#define XINPUT_NAME_RX "Right Stick X" +#define XINPUT_NAME_RY "Right Stick Y" +#define XINPUT_NAME_DPAD_X "D-pad X" +#define XINPUT_NAME_DPAD_Y "D-pad Y" +#define XINPUT_NAME_LB "LB" +#define XINPUT_NAME_RB "RB" +#define XINPUT_NAME_LT "LT" +#define XINPUT_NAME_RT "RT" +#define XINPUT_NAME_A "A" +#define XINPUT_NAME_B "B" +#define XINPUT_NAME_X "X" +#define XINPUT_NAME_Y "Y" +#define XINPUT_NAME_BACK "Back/View" +#define XINPUT_NAME_START "Start/Menu" +#define XINPUT_NAME_LS "Left Stick" +#define XINPUT_NAME_RS "Right Stick" #ifdef ENABLE_JOYSTICK_LOG int joystick_do_log = ENABLE_JOYSTICK_LOG; - static void joystick_log(const char *fmt, ...) { va_list ap; if (joystick_do_log) { - va_start(ap, fmt); - pclog_ex(fmt, ap); - va_end(ap); + va_start(ap, fmt); + pclog_ex(fmt, ap); + va_end(ap); } } #else -#define joystick_log(fmt, ...) +# define joystick_log(fmt, ...) #endif plat_joystick_t plat_joystick_state[MAX_PLAT_JOYSTICKS]; -joystick_t joystick_state[MAX_JOYSTICKS]; -int joysticks_present = 0; +joystick_t joystick_state[MAX_JOYSTICKS]; +int joysticks_present = 0; XINPUT_STATE controllers[XINPUT_MAX_JOYSTICKS]; -void joystick_init() +void +joystick_init() { - int c; + atexit(joystick_close); - atexit(joystick_close); - - joysticks_present = 0; - - memset(controllers, 0, sizeof(XINPUT_STATE) * XINPUT_MAX_JOYSTICKS); + joysticks_present = 0; - for (c=0; c 127) ? 128 : 0; - plat_joystick_state[c].b[7] = (controllers[c].Gamepad.bRightTrigger > 127) ? 128 : 0; - plat_joystick_state[c].b[8] = (controllers[c].Gamepad.wButtons & XINPUT_GAMEPAD_BACK) ? 128 : 0; - plat_joystick_state[c].b[9] = (controllers[c].Gamepad.wButtons & XINPUT_GAMEPAD_START) ? 128 : 0; - plat_joystick_state[c].b[10] = (controllers[c].Gamepad.wButtons & XINPUT_GAMEPAD_LEFT_THUMB) ? 128 : 0; - plat_joystick_state[c].b[11] = (controllers[c].Gamepad.wButtons & XINPUT_GAMEPAD_RIGHT_THUMB) ? 128 : 0; - - int dpad_x = 0, dpad_y = 0; - if (controllers[c].Gamepad.wButtons & XINPUT_GAMEPAD_DPAD_UP) - dpad_y-=32767; - if (controllers[c].Gamepad.wButtons & XINPUT_GAMEPAD_DPAD_DOWN) - dpad_y+=32767; - if (controllers[c].Gamepad.wButtons & XINPUT_GAMEPAD_DPAD_LEFT) - dpad_x-=32767; - if (controllers[c].Gamepad.wButtons & XINPUT_GAMEPAD_DPAD_RIGHT) - dpad_x+=32767; + plat_joystick_state[c].a[0] = controllers[c].Gamepad.sThumbLX; + plat_joystick_state[c].a[1] = -controllers[c].Gamepad.sThumbLY; + plat_joystick_state[c].a[3] = controllers[c].Gamepad.sThumbRX; + plat_joystick_state[c].a[4] = -controllers[c].Gamepad.sThumbRY; + plat_joystick_state[c].a[6] = (double) controllers[c].Gamepad.bLeftTrigger / 255 * 32767; + plat_joystick_state[c].a[7] = (double) controllers[c].Gamepad.bRightTrigger / 255 * 32767; - plat_joystick_state[c].a[2] = dpad_x; - plat_joystick_state[c].a[5] = dpad_y; + plat_joystick_state[c].b[0] = (controllers[c].Gamepad.wButtons & XINPUT_GAMEPAD_A) ? 128 : 0; + plat_joystick_state[c].b[1] = (controllers[c].Gamepad.wButtons & XINPUT_GAMEPAD_B) ? 128 : 0; + plat_joystick_state[c].b[2] = (controllers[c].Gamepad.wButtons & XINPUT_GAMEPAD_X) ? 128 : 0; + plat_joystick_state[c].b[3] = (controllers[c].Gamepad.wButtons & XINPUT_GAMEPAD_Y) ? 128 : 0; + plat_joystick_state[c].b[4] = (controllers[c].Gamepad.wButtons & XINPUT_GAMEPAD_LEFT_SHOULDER) ? 128 : 0; + plat_joystick_state[c].b[5] = (controllers[c].Gamepad.wButtons & XINPUT_GAMEPAD_RIGHT_SHOULDER) ? 128 : 0; + plat_joystick_state[c].b[6] = (controllers[c].Gamepad.bLeftTrigger > 127) ? 128 : 0; + plat_joystick_state[c].b[7] = (controllers[c].Gamepad.bRightTrigger > 127) ? 128 : 0; + plat_joystick_state[c].b[8] = (controllers[c].Gamepad.wButtons & XINPUT_GAMEPAD_BACK) ? 128 : 0; + plat_joystick_state[c].b[9] = (controllers[c].Gamepad.wButtons & XINPUT_GAMEPAD_START) ? 128 : 0; + plat_joystick_state[c].b[10] = (controllers[c].Gamepad.wButtons & XINPUT_GAMEPAD_LEFT_THUMB) ? 128 : 0; + plat_joystick_state[c].b[11] = (controllers[c].Gamepad.wButtons & XINPUT_GAMEPAD_RIGHT_THUMB) ? 128 : 0; - for (int a=0; a<8; a++) { - if (plat_joystick_state[c].a[a] == -32768) - plat_joystick_state[c].a[a] = -32767; - if (plat_joystick_state[c].a[a] == 32768) - plat_joystick_state[c].a[a] = 32767; - } + int dpad_x = 0; + int dpad_y = 0; + if (controllers[c].Gamepad.wButtons & XINPUT_GAMEPAD_DPAD_UP) + dpad_y -= 32767; + if (controllers[c].Gamepad.wButtons & XINPUT_GAMEPAD_DPAD_DOWN) + dpad_y += 32767; + if (controllers[c].Gamepad.wButtons & XINPUT_GAMEPAD_DPAD_LEFT) + dpad_x -= 32767; + if (controllers[c].Gamepad.wButtons & XINPUT_GAMEPAD_DPAD_RIGHT) + dpad_x += 32767; + + plat_joystick_state[c].a[2] = dpad_x; + plat_joystick_state[c].a[5] = dpad_y; + + for (int a = 0; a < 8; a++) { + if (plat_joystick_state[c].a[a] == -32768) + plat_joystick_state[c].a[a] = -32767; + if (plat_joystick_state[c].a[a] == 32768) + plat_joystick_state[c].a[a] = 32767; } + } } -static int joystick_get_axis(int joystick_nr, int mapping) +static int +joystick_get_axis(int joystick_nr, int mapping) { - if (mapping & POV_X) - { - int pov = plat_joystick_state[joystick_nr].p[mapping & 3]; + if (mapping & POV_X) { + int pov = plat_joystick_state[joystick_nr].p[mapping & 3]; - if (LOWORD(pov) == 0xFFFF) - return 0; - else - return sin((2*M_PI * (double)pov) / 36000.0) * 32767; - } - else if (mapping & POV_Y) - { - int pov = plat_joystick_state[joystick_nr].p[mapping & 3]; - - if (LOWORD(pov) == 0xFFFF) - return 0; - else - return -cos((2*M_PI * (double)pov) / 36000.0) * 32767; - } + if (LOWORD(pov) == 0xFFFF) + return 0; else - return plat_joystick_state[joystick_nr].a[plat_joystick_state[joystick_nr].axis[mapping].id]; + return sin((2 * M_PI * (double) pov) / 36000.0) * 32767; + } else if (mapping & POV_Y) { + int pov = plat_joystick_state[joystick_nr].p[mapping & 3]; + + if (LOWORD(pov) == 0xFFFF) + return 0; + else + return -cos((2 * M_PI * (double) pov) / 36000.0) * 32767; + } else + return plat_joystick_state[joystick_nr].a[plat_joystick_state[joystick_nr].axis[mapping].id]; } -void joystick_process(void) +void +joystick_process(void) { - int c, d; + int d; - if (!joystick_type) return; + if (!joystick_type) + return; - joystick_poll(); + joystick_poll(); - for (c = 0; c < joystick_get_max_joysticks(joystick_type); c++) - { - if (joystick_state[c].plat_joystick_nr) - { - int joystick_nr = joystick_state[c].plat_joystick_nr - 1; - - for (d = 0; d < joystick_get_axis_count(joystick_type); d++) - joystick_state[c].axis[d] = joystick_get_axis(joystick_nr, joystick_state[c].axis_mapping[d]); - for (d = 0; d < joystick_get_button_count(joystick_type); d++) - joystick_state[c].button[d] = plat_joystick_state[joystick_nr].b[joystick_state[c].button_mapping[d]]; + for (int c = 0; c < joystick_get_max_joysticks(joystick_type); c++) { + if (joystick_state[c].plat_joystick_nr) { + int joystick_nr = joystick_state[c].plat_joystick_nr - 1; - for (d = 0; d < joystick_get_pov_count(joystick_type); d++) - { - int x, y; - double angle, magnitude; + for (d = 0; d < joystick_get_axis_count(joystick_type); d++) + joystick_state[c].axis[d] = joystick_get_axis(joystick_nr, joystick_state[c].axis_mapping[d]); + for (d = 0; d < joystick_get_button_count(joystick_type); d++) + joystick_state[c].button[d] = plat_joystick_state[joystick_nr].b[joystick_state[c].button_mapping[d]]; - x = joystick_get_axis(joystick_nr, joystick_state[c].pov_mapping[d][0]); - y = joystick_get_axis(joystick_nr, joystick_state[c].pov_mapping[d][1]); - - angle = (atan2((double)y, (double)x) * 360.0) / (2*M_PI); - magnitude = sqrt((double)x*(double)x + (double)y*(double)y); - - if (magnitude < 16384) - joystick_state[c].pov[d] = -1; - else - joystick_state[c].pov[d] = ((int)angle + 90 + 360) % 360; - } - } + for (d = 0; d < joystick_get_pov_count(joystick_type); d++) { + int x; + int y; + double angle; + double magnitude; + + x = joystick_get_axis(joystick_nr, joystick_state[c].pov_mapping[d][0]); + y = joystick_get_axis(joystick_nr, joystick_state[c].pov_mapping[d][1]); + + angle = (atan2((double) y, (double) x) * 360.0) / (2 * M_PI); + magnitude = sqrt((double) x * (double) x + (double) y * (double) y); + + if (magnitude < 16384) + joystick_state[c].pov[d] = -1; else - { - for (d = 0; d < joystick_get_axis_count(joystick_type); d++) - joystick_state[c].axis[d] = 0; - for (d = 0; d < joystick_get_button_count(joystick_type); d++) - joystick_state[c].button[d] = 0; - for (d = 0; d < joystick_get_pov_count(joystick_type); d++) - joystick_state[c].pov[d] = -1; - } + joystick_state[c].pov[d] = ((int) angle + 90 + 360) % 360; + } + } else { + for (d = 0; d < joystick_get_axis_count(joystick_type); d++) + joystick_state[c].axis[d] = 0; + for (d = 0; d < joystick_get_button_count(joystick_type); d++) + joystick_state[c].button[d] = 0; + for (d = 0; d < joystick_get_pov_count(joystick_type); d++) + joystick_state[c].pov[d] = -1; } + } } -void win_joystick_handle(PRAWINPUT raw) {} +void +win_joystick_handle(UNUSED(PRAWINPUT raw)) +{ + // Nothing to be done here, atleast currently +} diff --git a/src/win/win_jsconf.c b/src/win/win_jsconf.c index 49e0c2184..190338d3e 100644 --- a/src/win/win_jsconf.c +++ b/src/win/win_jsconf.c @@ -14,151 +14,135 @@ #include <86box/plat.h> #include <86box/win.h> - static int joystick_nr; static int joystick_config_type; #define AXIS_STRINGS_MAX 3 -static char *axis_strings[AXIS_STRINGS_MAX] = {"X Axis", "Y Axis", "Z Axis"}; +static char *axis_strings[AXIS_STRINGS_MAX] = { "X Axis", "Y Axis", "Z Axis" }; static uint8_t joystickconfig_changed = 0; - -static void rebuild_axis_button_selections(HWND hdlg) +static void +rebuild_axis_button_selections(HWND hdlg) { - int id = IDC_CONFIG_BASE + 2; - HWND h; - int joystick; - int c, d; - char s[269]; + int id = IDC_CONFIG_BASE + 2; + HWND h; + int joystick; + int c; + int d; + char s[269]; - h = GetDlgItem(hdlg, IDC_CONFIG_BASE); - joystick = SendMessage(h, CB_GETCURSEL, 0, 0); + h = GetDlgItem(hdlg, IDC_CONFIG_BASE); + joystick = SendMessage(h, CB_GETCURSEL, 0, 0); - for (c = 0; c < joystick_get_axis_count(joystick_config_type); c++) - { - int sel = c; - - h = GetDlgItem(hdlg, id); - SendMessage(h, CB_RESETCONTENT, 0, 0); + for (c = 0; c < joystick_get_axis_count(joystick_config_type); c++) { + int sel = c; - if (joystick) - { - for (d = 0; d < plat_joystick_state[joystick-1].nr_axes; d++) - { - SendMessage(h, CB_ADDSTRING, 0, (LPARAM)(LPCSTR)plat_joystick_state[joystick-1].axis[d].name); - if (c < AXIS_STRINGS_MAX) - { - if (!stricmp(axis_strings[c], plat_joystick_state[joystick-1].axis[d].name)) - sel = d; - } - } - for (d = 0; d < plat_joystick_state[joystick-1].nr_povs; d++) - { - sprintf(s, "%s (X axis)", plat_joystick_state[joystick-1].pov[d].name); - SendMessage(h, CB_ADDSTRING, 0, (LPARAM)(LPCSTR)s); - sprintf(s, "%s (Y axis)", plat_joystick_state[joystick-1].pov[d].name); - SendMessage(h, CB_ADDSTRING, 0, (LPARAM)(LPCSTR)s); - } - for (d = 0; d < plat_joystick_state[joystick - 1].nr_sliders; d++) - { - SendMessage(h, CB_ADDSTRING, 0, (LPARAM)(LPCSTR)plat_joystick_state[joystick - 1].slider[d].name); - } - SendMessage(h, CB_SETCURSEL, sel, 0); - EnableWindow(h, TRUE); + h = GetDlgItem(hdlg, id); + SendMessage(h, CB_RESETCONTENT, 0, 0); + + if (joystick) { + for (d = 0; d < plat_joystick_state[joystick - 1].nr_axes; d++) { + SendMessage(h, CB_ADDSTRING, 0, (LPARAM) (LPCSTR) plat_joystick_state[joystick - 1].axis[d].name); + if (c < AXIS_STRINGS_MAX) { + if (!stricmp(axis_strings[c], plat_joystick_state[joystick - 1].axis[d].name)) + sel = d; } - else - EnableWindow(h, FALSE); - - id += 2; - } + } + for (d = 0; d < plat_joystick_state[joystick - 1].nr_povs; d++) { + sprintf(s, "%s (X axis)", plat_joystick_state[joystick - 1].pov[d].name); + SendMessage(h, CB_ADDSTRING, 0, (LPARAM) (LPCSTR) s); + sprintf(s, "%s (Y axis)", plat_joystick_state[joystick - 1].pov[d].name); + SendMessage(h, CB_ADDSTRING, 0, (LPARAM) (LPCSTR) s); + } + for (d = 0; d < plat_joystick_state[joystick - 1].nr_sliders; d++) { + SendMessage(h, CB_ADDSTRING, 0, (LPARAM) (LPCSTR) plat_joystick_state[joystick - 1].slider[d].name); + } + SendMessage(h, CB_SETCURSEL, sel, 0); + EnableWindow(h, TRUE); + } else + EnableWindow(h, FALSE); - for (c = 0; c < joystick_get_button_count(joystick_config_type); c++) - { - h = GetDlgItem(hdlg, id); - SendMessage(h, CB_RESETCONTENT, 0, 0); + id += 2; + } - if (joystick) - { - for (d = 0; d < plat_joystick_state[joystick-1].nr_buttons; d++) - SendMessage(h, CB_ADDSTRING, 0, (LPARAM)(LPCSTR)plat_joystick_state[joystick-1].button[d].name); - SendMessage(h, CB_SETCURSEL, c, 0); - EnableWindow(h, TRUE); - } - else - EnableWindow(h, FALSE); + for (c = 0; c < joystick_get_button_count(joystick_config_type); c++) { + h = GetDlgItem(hdlg, id); + SendMessage(h, CB_RESETCONTENT, 0, 0); - id += 2; - } + if (joystick) { + for (d = 0; d < plat_joystick_state[joystick - 1].nr_buttons; d++) + SendMessage(h, CB_ADDSTRING, 0, (LPARAM) (LPCSTR) plat_joystick_state[joystick - 1].button[d].name); + SendMessage(h, CB_SETCURSEL, c, 0); + EnableWindow(h, TRUE); + } else + EnableWindow(h, FALSE); - for (c = 0; c < joystick_get_pov_count(joystick_config_type)*2; c++) - { - int sel = c; - - h = GetDlgItem(hdlg, id); - SendMessage(h, CB_RESETCONTENT, 0, 0); + id += 2; + } - if (joystick) - { - for (d = 0; d < plat_joystick_state[joystick-1].nr_povs; d++) - { - sprintf(s, "%s (X axis)", plat_joystick_state[joystick-1].pov[d].name); - SendMessage(h, CB_ADDSTRING, 0, (LPARAM)(LPCSTR)s); - sprintf(s, "%s (Y axis)", plat_joystick_state[joystick-1].pov[d].name); - SendMessage(h, CB_ADDSTRING, 0, (LPARAM)(LPCSTR)s); - } - for (d = 0; d < plat_joystick_state[joystick-1].nr_axes; d++) - { - SendMessage(h, CB_ADDSTRING, 0, (LPARAM)(LPCSTR)plat_joystick_state[joystick-1].axis[d].name); - } - SendMessage(h, CB_SETCURSEL, sel, 0); - EnableWindow(h, TRUE); - } - else - EnableWindow(h, FALSE); - - id += 2; - } + for (c = 0; c < joystick_get_pov_count(joystick_config_type) * 2; c++) { + int sel = c; + h = GetDlgItem(hdlg, id); + SendMessage(h, CB_RESETCONTENT, 0, 0); + + if (joystick) { + for (d = 0; d < plat_joystick_state[joystick - 1].nr_povs; d++) { + sprintf(s, "%s (X axis)", plat_joystick_state[joystick - 1].pov[d].name); + SendMessage(h, CB_ADDSTRING, 0, (LPARAM) (LPCSTR) s); + sprintf(s, "%s (Y axis)", plat_joystick_state[joystick - 1].pov[d].name); + SendMessage(h, CB_ADDSTRING, 0, (LPARAM) (LPCSTR) s); + } + for (d = 0; d < plat_joystick_state[joystick - 1].nr_axes; d++) { + SendMessage(h, CB_ADDSTRING, 0, (LPARAM) (LPCSTR) plat_joystick_state[joystick - 1].axis[d].name); + } + SendMessage(h, CB_SETCURSEL, sel, 0); + EnableWindow(h, TRUE); + } else + EnableWindow(h, FALSE); + + id += 2; + } } -static int get_axis(HWND hdlg, int id) +static int +get_axis(HWND hdlg, int id) { - HWND h = GetDlgItem(hdlg, id); - int axis_sel = SendMessage(h, CB_GETCURSEL, 0, 0); - int nr_axes = plat_joystick_state[joystick_state[joystick_nr].plat_joystick_nr-1].nr_axes; - int nr_povs = plat_joystick_state[joystick_state[joystick_nr].plat_joystick_nr - 1].nr_povs; - - if (axis_sel < nr_axes) - return axis_sel; - - axis_sel -= nr_axes; - if (axis_sel < nr_povs * 2) - { - if (axis_sel & 1) - return POV_Y | (axis_sel >> 1); - else - return POV_X | (axis_sel >> 1); - } - axis_sel -= nr_povs; + HWND h = GetDlgItem(hdlg, id); + int axis_sel = SendMessage(h, CB_GETCURSEL, 0, 0); + int nr_axes = plat_joystick_state[joystick_state[joystick_nr].plat_joystick_nr - 1].nr_axes; + int nr_povs = plat_joystick_state[joystick_state[joystick_nr].plat_joystick_nr - 1].nr_povs; - return SLIDER | (axis_sel >> 1); + if (axis_sel < nr_axes) + return axis_sel; + + axis_sel -= nr_axes; + if (axis_sel < nr_povs * 2) { + if (axis_sel & 1) + return POV_Y | (axis_sel >> 1); + else + return POV_X | (axis_sel >> 1); + } + axis_sel -= nr_povs; + + return SLIDER | (axis_sel >> 1); } -static int get_pov(HWND hdlg, int id) +static int +get_pov(HWND hdlg, int id) { - HWND h = GetDlgItem(hdlg, id); - int axis_sel = SendMessage(h, CB_GETCURSEL, 0, 0); - int nr_povs = plat_joystick_state[joystick_state[joystick_nr].plat_joystick_nr-1].nr_povs*2; + HWND h = GetDlgItem(hdlg, id); + int axis_sel = SendMessage(h, CB_GETCURSEL, 0, 0); + int nr_povs = plat_joystick_state[joystick_state[joystick_nr].plat_joystick_nr - 1].nr_povs * 2; - if (axis_sel < nr_povs) - { - if (axis_sel & 1) - return POV_Y | (axis_sel >> 1); - else - return POV_X | (axis_sel >> 1); - } - - return axis_sel - nr_povs; + if (axis_sel < nr_povs) { + if (axis_sel & 1) + return POV_Y | (axis_sel >> 1); + else + return POV_X | (axis_sel >> 1); + } + + return axis_sel - nr_povs; } #if defined(__amd64__) || defined(__aarch64__) @@ -166,403 +150,389 @@ static LRESULT CALLBACK #else static BOOL CALLBACK #endif -joystickconfig_dlgproc(HWND hdlg, UINT message, WPARAM wParam, LPARAM lParam) +joystickconfig_dlgproc(HWND hdlg, UINT message, WPARAM wParam, UNUSED(LPARAM lParam)) { - HWND h; - int c; - int id; - int joystick; - int nr_axes; - int nr_povs; - int mapping; + HWND h; + int c; + int id; + int joystick; + int nr_axes; + int nr_povs; + int mapping; - switch (message) - { - case WM_INITDIALOG: - { - h = GetDlgItem(hdlg, IDC_CONFIG_BASE); - id = IDC_CONFIG_BASE + 2; - joystick = joystick_state[joystick_nr].plat_joystick_nr; + switch (message) { + case WM_INITDIALOG: + { + h = GetDlgItem(hdlg, IDC_CONFIG_BASE); + id = IDC_CONFIG_BASE + 2; + joystick = joystick_state[joystick_nr].plat_joystick_nr; - SendMessage(h, CB_ADDSTRING, 0, (LPARAM)(LPCSTR)"None"); + SendMessage(h, CB_ADDSTRING, 0, (LPARAM) (LPCSTR) "None"); - for (c = 0; c < joysticks_present; c++) - SendMessage(h, CB_ADDSTRING, 0, (LPARAM)(LPCSTR)plat_joystick_state[c].name); - - SendMessage(h, CB_SETCURSEL, joystick, 0); + for (c = 0; c < joysticks_present; c++) + SendMessage(h, CB_ADDSTRING, 0, (LPARAM) (LPCSTR) plat_joystick_state[c].name); + SendMessage(h, CB_SETCURSEL, joystick, 0); + + rebuild_axis_button_selections(hdlg); + + if (joystick_state[joystick_nr].plat_joystick_nr) { + nr_axes = plat_joystick_state[joystick - 1].nr_axes; + nr_povs = plat_joystick_state[joystick - 1].nr_povs; + + for (c = 0; c < joystick_get_axis_count(joystick_config_type); c++) { + int mapping = joystick_state[joystick_nr].axis_mapping[c]; + + h = GetDlgItem(hdlg, id); + if (mapping & POV_X) + SendMessage(h, CB_SETCURSEL, nr_axes + (mapping & 3) * 2, 0); + else if (mapping & POV_Y) + SendMessage(h, CB_SETCURSEL, nr_axes + (mapping & 3) * 2 + 1, 0); + else if (mapping & SLIDER) + SendMessage(h, CB_SETCURSEL, nr_axes + nr_povs * 2 + (mapping & 3), 0); + else + SendMessage(h, CB_SETCURSEL, mapping, 0); + id += 2; + } + for (c = 0; c < joystick_get_button_count(joystick_config_type); c++) { + h = GetDlgItem(hdlg, id); + SendMessage(h, CB_SETCURSEL, joystick_state[joystick_nr].button_mapping[c], 0); + id += 2; + } + for (c = 0; c < joystick_get_pov_count(joystick_config_type); c++) { + h = GetDlgItem(hdlg, id); + mapping = joystick_state[joystick_nr].pov_mapping[c][0]; + if (mapping & POV_X) + SendMessage(h, CB_SETCURSEL, (mapping & 3) * 2, 0); + else if (mapping & POV_Y) + SendMessage(h, CB_SETCURSEL, (mapping & 3) * 2 + 1, 0); + else + SendMessage(h, CB_SETCURSEL, mapping + nr_povs * 2, 0); + id += 2; + h = GetDlgItem(hdlg, id); + mapping = joystick_state[joystick_nr].pov_mapping[c][1]; + if (mapping & POV_X) + SendMessage(h, CB_SETCURSEL, (mapping & 3) * 2, 0); + else if (mapping & POV_Y) + SendMessage(h, CB_SETCURSEL, (mapping & 3) * 2 + 1, 0); + else + SendMessage(h, CB_SETCURSEL, mapping + nr_povs * 2, 0); + id += 2; + } + } + } + return TRUE; + + case WM_COMMAND: + switch (LOWORD(wParam)) { + case IDC_CONFIG_BASE: + if (HIWORD(wParam) == CBN_SELCHANGE) rebuild_axis_button_selections(hdlg); - - if (joystick_state[joystick_nr].plat_joystick_nr) - { - nr_axes = plat_joystick_state[joystick-1].nr_axes; - nr_povs = plat_joystick_state[joystick-1].nr_povs; - - for (c = 0; c < joystick_get_axis_count(joystick_config_type); c++) - { - int mapping = joystick_state[joystick_nr].axis_mapping[c]; - - h = GetDlgItem(hdlg, id); - if (mapping & POV_X) - SendMessage(h, CB_SETCURSEL, nr_axes + (mapping & 3)*2, 0); - else if (mapping & POV_Y) - SendMessage(h, CB_SETCURSEL, nr_axes + (mapping & 3)*2 + 1, 0); - else if (mapping & SLIDER) - SendMessage(h, CB_SETCURSEL, nr_axes + nr_povs * 2 + (mapping & 3), 0); - else - SendMessage(h, CB_SETCURSEL, mapping, 0); - id += 2; - } - for (c = 0; c < joystick_get_button_count(joystick_config_type); c++) - { - h = GetDlgItem(hdlg, id); - SendMessage(h, CB_SETCURSEL, joystick_state[joystick_nr].button_mapping[c], 0); - id += 2; - } - for (c = 0; c < joystick_get_pov_count(joystick_config_type); c++) - { - h = GetDlgItem(hdlg, id); - mapping = joystick_state[joystick_nr].pov_mapping[c][0]; - if (mapping & POV_X) - SendMessage(h, CB_SETCURSEL, (mapping & 3)*2, 0); - else if (mapping & POV_Y) - SendMessage(h, CB_SETCURSEL, (mapping & 3)*2 + 1, 0); - else - SendMessage(h, CB_SETCURSEL, mapping + nr_povs*2, 0); - id += 2; - h = GetDlgItem(hdlg, id); - mapping = joystick_state[joystick_nr].pov_mapping[c][1]; - if (mapping & POV_X) - SendMessage(h, CB_SETCURSEL, (mapping & 3)*2, 0); - else if (mapping & POV_Y) - SendMessage(h, CB_SETCURSEL, (mapping & 3)*2 + 1, 0); - else - SendMessage(h, CB_SETCURSEL, mapping + nr_povs*2, 0); - id += 2; - } + break; + + case IDOK: + { + id = IDC_CONFIG_BASE + 2; + + h = GetDlgItem(hdlg, IDC_CONFIG_BASE); + joystick_state[joystick_nr].plat_joystick_nr = SendMessage(h, CB_GETCURSEL, 0, 0); + + if (joystick_state[joystick_nr].plat_joystick_nr) { + for (c = 0; c < joystick_get_axis_count(joystick_config_type); c++) { + joystick_state[joystick_nr].axis_mapping[c] = get_axis(hdlg, id); + id += 2; + } + for (c = 0; c < joystick_get_button_count(joystick_config_type); c++) { + h = GetDlgItem(hdlg, id); + joystick_state[joystick_nr].button_mapping[c] = SendMessage(h, CB_GETCURSEL, 0, 0); + id += 2; + } + for (c = 0; c < joystick_get_button_count(joystick_config_type); c++) { + h = GetDlgItem(hdlg, id); + joystick_state[joystick_nr].pov_mapping[c][0] = get_pov(hdlg, id); + id += 2; + h = GetDlgItem(hdlg, id); + joystick_state[joystick_nr].pov_mapping[c][1] = get_pov(hdlg, id); + id += 2; + } } - } - return TRUE; - - case WM_COMMAND: - switch (LOWORD(wParam)) - { - case IDC_CONFIG_BASE: - if (HIWORD(wParam) == CBN_SELCHANGE) - rebuild_axis_button_selections(hdlg); - break; - - case IDOK: - { - id = IDC_CONFIG_BASE + 2; - - h = GetDlgItem(hdlg, IDC_CONFIG_BASE); - joystick_state[joystick_nr].plat_joystick_nr = SendMessage(h, CB_GETCURSEL, 0, 0); - - if (joystick_state[joystick_nr].plat_joystick_nr) - { - for (c = 0; c < joystick_get_axis_count(joystick_config_type); c++) - { - joystick_state[joystick_nr].axis_mapping[c] = get_axis(hdlg, id); - id += 2; - } - for (c = 0; c < joystick_get_button_count(joystick_config_type); c++) - { - h = GetDlgItem(hdlg, id); - joystick_state[joystick_nr].button_mapping[c] = SendMessage(h, CB_GETCURSEL, 0, 0); - id += 2; - } - for (c = 0; c < joystick_get_button_count(joystick_config_type); c++) - { - h = GetDlgItem(hdlg, id); - joystick_state[joystick_nr].pov_mapping[c][0] = get_pov(hdlg, id); - id += 2; - h = GetDlgItem(hdlg, id); - joystick_state[joystick_nr].pov_mapping[c][1] = get_pov(hdlg, id); - id += 2; - } - } - } - joystickconfig_changed = 1; - EndDialog(hdlg, 0); - return TRUE; - case IDCANCEL: - joystickconfig_changed = 0; - EndDialog(hdlg, 0); - return TRUE; - } - break; - } - return FALSE; + } + joystickconfig_changed = 1; + EndDialog(hdlg, 0); + return TRUE; + case IDCANCEL: + joystickconfig_changed = 0; + EndDialog(hdlg, 0); + return TRUE; + } + break; + } + return FALSE; } -uint8_t joystickconfig_open(HWND hwnd, int joy_nr, int type) +uint8_t +joystickconfig_open(HWND hwnd, int joy_nr, int type) { - uint16_t *data_block = malloc(16384); - uint16_t *data; - DLGTEMPLATE *dlg = (DLGTEMPLATE *)data_block; - DLGITEMTEMPLATE *item; - int y = 10; - int id = IDC_CONFIG_BASE; - int c; - char s[269]; + uint16_t *data_block = malloc(16384); + uint16_t *data; + DLGTEMPLATE *dlg = (DLGTEMPLATE *) data_block; + DLGITEMTEMPLATE *item; + int y = 10; + int id = IDC_CONFIG_BASE; + int c; + char s[269]; - joystickconfig_changed = 0; - - joystick_nr = joy_nr; - joystick_config_type = type; + joystickconfig_changed = 0; - memset(data_block, 0, 4096); - - dlg->style = DS_SETFONT | DS_MODALFRAME | DS_FIXEDSYS | WS_POPUP | WS_CAPTION | WS_SYSMENU; - dlg->x = 10; - dlg->y = 10; - dlg->cx = 220; - dlg->cy = 70; - - data = (uint16_t *)(dlg + 1); - - *data++ = 0; /*no menu*/ - *data++ = 0; /*predefined dialog box class*/ - data += MultiByteToWideChar(CP_ACP, 0, "Joystick Configuration", -1, data, 50); + joystick_nr = joy_nr; + joystick_config_type = type; - *data++ = 9; /*Point*/ - data += MultiByteToWideChar(CP_ACP, 0, "Segoe UI", -1, data, 50); - - if (((uintptr_t)data) & 2) - data++; + memset(data_block, 0, 4096); + dlg->style = DS_SETFONT | DS_MODALFRAME | DS_FIXEDSYS | WS_POPUP | WS_CAPTION | WS_SYSMENU; + dlg->x = 10; + dlg->y = 10; + dlg->cx = 220; + dlg->cy = 70; + data = (uint16_t *) (dlg + 1); + + *data++ = 0; /*no menu*/ + *data++ = 0; /*predefined dialog box class*/ + data += MultiByteToWideChar(CP_ACP, 0, "Joystick Configuration", -1, data, 50); + + *data++ = 9; /*Point*/ + data += MultiByteToWideChar(CP_ACP, 0, "Segoe UI", -1, data, 50); + + if (((uintptr_t) data) & 2) + data++; + + /*Combo box*/ + item = (DLGITEMTEMPLATE *) data; + item->x = 70; + item->y = y; + item->id = id++; + + item->cx = 140; + item->cy = 150; + + item->style = WS_CHILD | WS_VISIBLE | CBS_DROPDOWNLIST | WS_VSCROLL; + + data = (uint16_t *) (item + 1); + *data++ = 0xFFFF; + *data++ = 0x0085; /* combo box class */ + + data += MultiByteToWideChar(CP_ACP, 0, "Device", -1, data, 256); + *data++ = 0; /* no creation data */ + + if (((uintptr_t) data) & 2) + data++; + + /*Static text*/ + item = (DLGITEMTEMPLATE *) data; + item->x = 10; + item->y = y + 2; + item->id = id++; + + item->cx = 60; + item->cy = 15; + + item->style = WS_CHILD | WS_VISIBLE; + + data = (uint16_t *) (item + 1); + *data++ = 0xFFFF; + *data++ = 0x0082; /* static class */ + + data += MultiByteToWideChar(CP_ACP, 0, "Device", -1, data, 256); + *data++ = 0; /* no creation data */ + + if (((uintptr_t) data) & 2) + data++; + + y += 20; + + for (c = 0; c < joystick_get_axis_count(type); c++) { /*Combo box*/ - item = (DLGITEMTEMPLATE *)data; - item->x = 70; - item->y = y; + item = (DLGITEMTEMPLATE *) data; + item->x = 70; + item->y = y; item->id = id++; - + item->cx = 140; item->cy = 150; item->style = WS_CHILD | WS_VISIBLE | CBS_DROPDOWNLIST | WS_VSCROLL; - data = (uint16_t *)(item + 1); + data = (uint16_t *) (item + 1); *data++ = 0xFFFF; - *data++ = 0x0085; /* combo box class */ + *data++ = 0x0085; /* combo box class */ - data += MultiByteToWideChar(CP_ACP, 0, "Device", -1, data, 256); - *data++ = 0; /* no creation data */ - - if (((uintptr_t)data) & 2) - data++; + data += MultiByteToWideChar(CP_ACP, 0, joystick_get_axis_name(type, c), -1, data, 256); + *data++ = 0; /* no creation data */ + + if (((uintptr_t) data) & 2) + data++; /*Static text*/ - item = (DLGITEMTEMPLATE *)data; - item->x = 10; - item->y = y + 2; + item = (DLGITEMTEMPLATE *) data; + item->x = 10; + item->y = y + 2; item->id = id++; - + item->cx = 60; item->cy = 15; item->style = WS_CHILD | WS_VISIBLE; - data = (uint16_t *)(item + 1); + data = (uint16_t *) (item + 1); *data++ = 0xFFFF; - *data++ = 0x0082; /* static class */ + *data++ = 0x0082; /* static class */ - data += MultiByteToWideChar(CP_ACP, 0, "Device", -1, data, 256); - *data++ = 0; /* no creation data */ - - if (((uintptr_t)data) & 2) - data++; + data += MultiByteToWideChar(CP_ACP, 0, joystick_get_axis_name(type, c), -1, data, 256); + *data++ = 0; /* no creation data */ + + if (((uintptr_t) data) & 2) + data++; y += 20; + } + for (c = 0; c < joystick_get_button_count(type); c++) { + /*Combo box*/ + item = (DLGITEMTEMPLATE *) data; + item->x = 70; + item->y = y; + item->id = id++; - for (c = 0; c < joystick_get_axis_count(type); c++) - { - /*Combo box*/ - item = (DLGITEMTEMPLATE *)data; - item->x = 70; - item->y = y; - item->id = id++; - - item->cx = 140; - item->cy = 150; + item->cx = 140; + item->cy = 150; - item->style = WS_CHILD | WS_VISIBLE | CBS_DROPDOWNLIST | WS_VSCROLL; + item->style = WS_CHILD | WS_VISIBLE | CBS_DROPDOWNLIST | WS_VSCROLL; - data = (uint16_t *)(item + 1); - *data++ = 0xFFFF; - *data++ = 0x0085; /* combo box class */ - - data += MultiByteToWideChar(CP_ACP, 0, joystick_get_axis_name(type, c), -1, data, 256); - *data++ = 0; /* no creation data */ - - if (((uintptr_t)data) & 2) - data++; - - /*Static text*/ - item = (DLGITEMTEMPLATE *)data; - item->x = 10; - item->y = y + 2; - item->id = id++; - - item->cx = 60; - item->cy = 15; - - item->style = WS_CHILD | WS_VISIBLE; - - data = (uint16_t *)(item + 1); - *data++ = 0xFFFF; - *data++ = 0x0082; /* static class */ - - data += MultiByteToWideChar(CP_ACP, 0, joystick_get_axis_name(type, c), -1, data, 256); - *data++ = 0; /* no creation data */ - - if (((uintptr_t)data) & 2) - data++; - - y += 20; - } - - for (c = 0; c < joystick_get_button_count(type); c++) - { - /*Combo box*/ - item = (DLGITEMTEMPLATE *)data; - item->x = 70; - item->y = y; - item->id = id++; - - item->cx = 140; - item->cy = 150; - - item->style = WS_CHILD | WS_VISIBLE | CBS_DROPDOWNLIST | WS_VSCROLL; - - data = (uint16_t *)(item + 1); - *data++ = 0xFFFF; - *data++ = 0x0085; /* combo box class */ - - data += MultiByteToWideChar(CP_ACP, 0, joystick_get_button_name(type, c), -1, data, 256); - *data++ = 0; /* no creation data */ - - if (((uintptr_t)data) & 2) - data++; - - /*Static text*/ - item = (DLGITEMTEMPLATE *)data; - item->x = 10; - item->y = y + 2; - item->id = id++; - - item->cx = 60; - item->cy = 15; - - item->style = WS_CHILD | WS_VISIBLE; - - data = (uint16_t *)(item + 1); - *data++ = 0xFFFF; - *data++ = 0x0082; /* static class */ - - data += MultiByteToWideChar(CP_ACP, 0, joystick_get_button_name(type, c), -1, data, 256); - *data++ = 0; /* no creation data */ - - if (((uintptr_t)data) & 2) - data++; - - y += 20; - } - - for (c = 0; c < joystick_get_pov_count(type)*2; c++) - { - /*Combo box*/ - item = (DLGITEMTEMPLATE *)data; - item->x = 70; - item->y = y; - item->id = id++; - - item->cx = 140; - item->cy = 150; - - item->style = WS_CHILD | WS_VISIBLE | CBS_DROPDOWNLIST | WS_VSCROLL; - - data = (uint16_t *)(item + 1); - *data++ = 0xFFFF; - *data++ = 0x0085; /* combo box class */ - - if (c & 1) - sprintf(s, "%s (Y axis)", joystick_get_pov_name(type, c/2)); - else - sprintf(s, "%s (X axis)", joystick_get_pov_name(type, c/2)); - data += MultiByteToWideChar(CP_ACP, 0, s, -1, data, 256); - *data++ = 0; /* no creation data */ - - if (((uintptr_t)data) & 2) - data++; - - /*Static text*/ - item = (DLGITEMTEMPLATE *)data; - item->x = 10; - item->y = y + 2; - item->id = id++; - - item->cx = 60; - item->cy = 15; - - item->style = WS_CHILD | WS_VISIBLE; - - data = (uint16_t *)(item + 1); - *data++ = 0xFFFF; - *data++ = 0x0082; /* static class */ - - data += MultiByteToWideChar(CP_ACP, 0, s, -1, data, 256); - *data++ = 0; /* no creation data */ - - if (((uintptr_t)data) & 2) - data++; - - y += 20; - } - - dlg->cdit = (id - IDC_CONFIG_BASE) + 2; - - item = (DLGITEMTEMPLATE *)data; - item->x = 100; - item->y = y + 5; - item->cx = 50; - item->cy = 14; - item->id = IDOK; /* OK button identifier */ - item->style = WS_CHILD | WS_VISIBLE | BS_DEFPUSHBUTTON; - - data = (uint16_t *)(item + 1); + data = (uint16_t *) (item + 1); *data++ = 0xFFFF; - *data++ = 0x0080; /* button class */ + *data++ = 0x0085; /* combo box class */ - data += MultiByteToWideChar(CP_ACP, 0, "OK", -1, data, 50); - *data++ = 0; /* no creation data */ + data += MultiByteToWideChar(CP_ACP, 0, joystick_get_button_name(type, c), -1, data, 256); + *data++ = 0; /* no creation data */ + + if (((uintptr_t) data) & 2) + data++; + + /*Static text*/ + item = (DLGITEMTEMPLATE *) data; + item->x = 10; + item->y = y + 2; + item->id = id++; + + item->cx = 60; + item->cy = 15; - if (((uintptr_t)data) & 2) - data++; - - item = (DLGITEMTEMPLATE *)data; - item->x = 160; - item->y = y + 5; - item->cx = 50; - item->cy = 14; - item->id = IDCANCEL; /* Cancel button identifier */ item->style = WS_CHILD | WS_VISIBLE; - data = (uint16_t *)(item + 1); + data = (uint16_t *) (item + 1); *data++ = 0xFFFF; - *data++ = 0x0080; /* button class */ + *data++ = 0x0082; /* static class */ - data += MultiByteToWideChar(CP_ACP, 0, "Cancel", -1, data, 50); - *data++ = 0; /* no creation data */ + data += MultiByteToWideChar(CP_ACP, 0, joystick_get_button_name(type, c), -1, data, 256); + *data++ = 0; /* no creation data */ - dlg->cy = y + 25; + if (((uintptr_t) data) & 2) + data++; - DialogBoxIndirect(hinstance, dlg, hwnd, joystickconfig_dlgproc); + y += 20; + } - free(data_block); + for (c = 0; c < joystick_get_pov_count(type) * 2; c++) { + /*Combo box*/ + item = (DLGITEMTEMPLATE *) data; + item->x = 70; + item->y = y; + item->id = id++; - return joystickconfig_changed; + item->cx = 140; + item->cy = 150; + + item->style = WS_CHILD | WS_VISIBLE | CBS_DROPDOWNLIST | WS_VSCROLL; + + data = (uint16_t *) (item + 1); + *data++ = 0xFFFF; + *data++ = 0x0085; /* combo box class */ + + if (c & 1) + sprintf(s, "%s (Y axis)", joystick_get_pov_name(type, c / 2)); + else + sprintf(s, "%s (X axis)", joystick_get_pov_name(type, c / 2)); + data += MultiByteToWideChar(CP_ACP, 0, s, -1, data, 256); + *data++ = 0; /* no creation data */ + + if (((uintptr_t) data) & 2) + data++; + + /*Static text*/ + item = (DLGITEMTEMPLATE *) data; + item->x = 10; + item->y = y + 2; + item->id = id++; + + item->cx = 60; + item->cy = 15; + + item->style = WS_CHILD | WS_VISIBLE; + + data = (uint16_t *) (item + 1); + *data++ = 0xFFFF; + *data++ = 0x0082; /* static class */ + + data += MultiByteToWideChar(CP_ACP, 0, s, -1, data, 256); + *data++ = 0; /* no creation data */ + + if (((uintptr_t) data) & 2) + data++; + + y += 20; + } + + dlg->cdit = (id - IDC_CONFIG_BASE) + 2; + + item = (DLGITEMTEMPLATE *) data; + item->x = 100; + item->y = y + 5; + item->cx = 50; + item->cy = 14; + item->id = IDOK; /* OK button identifier */ + item->style = WS_CHILD | WS_VISIBLE | BS_DEFPUSHBUTTON; + + data = (uint16_t *) (item + 1); + *data++ = 0xFFFF; + *data++ = 0x0080; /* button class */ + + data += MultiByteToWideChar(CP_ACP, 0, "OK", -1, data, 50); + *data++ = 0; /* no creation data */ + + if (((uintptr_t) data) & 2) + data++; + + item = (DLGITEMTEMPLATE *) data; + item->x = 160; + item->y = y + 5; + item->cx = 50; + item->cy = 14; + item->id = IDCANCEL; /* Cancel button identifier */ + item->style = WS_CHILD | WS_VISIBLE; + + data = (uint16_t *) (item + 1); + *data++ = 0xFFFF; + *data++ = 0x0080; /* button class */ + + data += MultiByteToWideChar(CP_ACP, 0, "Cancel", -1, data, 50); + *data++ = 0; /* no creation data */ + + dlg->cy = y + 25; + + DialogBoxIndirect(hinstance, dlg, hwnd, joystickconfig_dlgproc); + + free(data_block); + + return joystickconfig_changed; } diff --git a/src/win/win_keyboard.c b/src/win/win_keyboard.c index e60da87d4..54be91e6c 100644 --- a/src/win/win_keyboard.c +++ b/src/win/win_keyboard.c @@ -1,22 +1,23 @@ /* - * 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. + * 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. + * This file is part of the 86Box distribution. * - * Windows raw keyboard input handler. + * Windows raw keyboard input handler. * * * - * Author: Miran Grca, + * Authors: Miran Grca, * - * Copyright 2016-2018 Miran Grca. + * Copyright 2016-2018 Miran Grca. + * Copyright 2021-2023 Jasmine Iwanek. */ #define UNICODE -#define _WIN32_WINNT 0x0501 -#define BITMAP WINDOWS_BITMAP +#define _WIN32_WINNT 0x0501 +#define BITMAP WINDOWS_BITMAP #include #include #undef BITMAP @@ -30,9 +31,7 @@ #include <86box/plat.h> #include <86box/win.h> - -static uint16_t scancode_map[768]; - +static uint16_t scancode_map[768]; /* This is so we can disambiguate scan codes that would otherwise conflict and get passed on incorrectly. */ @@ -40,34 +39,33 @@ static UINT16 convert_scan_code(UINT16 scan_code) { if ((scan_code & 0xff00) == 0xe000) - scan_code = (scan_code & 0xff) | 0x0100; + scan_code = (scan_code & 0xff) | 0x0100; if (scan_code == 0xE11D) - scan_code = 0x0100; + scan_code = 0x0100; /* E0 00 is sent by some USB keyboards for their special keys, as it is an invalid scan code (it has no untranslated set 2 equivalent), we mark it appropriately so it does not get passed through. */ else if ((scan_code > 0x01FF) || (scan_code == 0x0100)) - scan_code = 0xFFFF; + scan_code = 0xFFFF; return scan_code; } - void keyboard_getkeymap(void) { - WCHAR *keyName = L"SYSTEM\\CurrentControlSet\\Control\\Keyboard Layout"; - WCHAR *valueName = L"Scancode Map"; + const WCHAR *keyName = L"SYSTEM\\CurrentControlSet\\Control\\Keyboard Layout"; + const WCHAR *valueName = L"Scancode Map"; unsigned char buf[32768]; - DWORD bufSize; - HKEY hKey; - int j; - UINT32 *bufEx2; - int scMapCount; - UINT16 *bufEx; - int scancode_unmapped; - int scancode_mapped; + DWORD bufSize; + HKEY hKey; + int j; + const UINT32 *bufEx2; + int scMapCount; + const UINT16 *bufEx; + int scancode_unmapped; + int scancode_mapped; /* First, prepare the default scan code map list which is 1:1. * Remappings will be inserted directly into it. @@ -75,131 +73,126 @@ keyboard_getkeymap(void) * prefix. */ for (j = 0; j < 512; j++) - scancode_map[j] = j; + scancode_map[j] = j; /* Get the scan code remappings from: HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\Keyboard Layout */ bufSize = 32768; if (RegOpenKeyEx(HKEY_LOCAL_MACHINE, keyName, 0, 1, &hKey) == ERROR_SUCCESS) { - if (RegQueryValueEx(hKey, valueName, NULL, NULL, buf, &bufSize) == ERROR_SUCCESS) { - bufEx2 = (UINT32 *) buf; - scMapCount = bufEx2[2]; - if ((bufSize != 0) && (scMapCount != 0)) { - bufEx = (UINT16 *) (buf + 12); - for (j = 0; j < scMapCount*2; j += 2) { - /* Each scan code is 32-bit: 16 bits of remapped scan code, - and 16 bits of original scan code. */ - scancode_unmapped = bufEx[j + 1]; - scancode_mapped = bufEx[j]; + if (RegQueryValueEx(hKey, valueName, NULL, NULL, buf, &bufSize) == ERROR_SUCCESS) { + bufEx2 = (UINT32 *) buf; + scMapCount = bufEx2[2]; + if ((bufSize != 0) && (scMapCount != 0)) { + bufEx = (UINT16 *) (buf + 12); + for (j = 0; j < scMapCount * 2; j += 2) { + /* Each scan code is 32-bit: 16 bits of remapped scan code, + and 16 bits of original scan code. */ + scancode_unmapped = bufEx[j + 1]; + scancode_mapped = bufEx[j]; - scancode_unmapped = convert_scan_code(scancode_unmapped); - scancode_mapped = convert_scan_code(scancode_mapped); + scancode_unmapped = convert_scan_code(scancode_unmapped); + scancode_mapped = convert_scan_code(scancode_mapped); - /* Ignore source scan codes with prefixes other than E1 - that are not E1 1D. */ - if (scancode_unmapped != 0xFFFF) - scancode_map[scancode_unmapped] = scancode_mapped; - } - } - } - RegCloseKey(hKey); + /* Ignore source scan codes with prefixes other than E1 + that are not E1 1D. */ + if (scancode_unmapped != 0xFFFF) + scancode_map[scancode_unmapped] = scancode_mapped; + } + } + } + RegCloseKey(hKey); } } - void keyboard_handle(PRAWINPUT raw) { - USHORT scancode; - static int recv_lalt = 0, recv_ralt = 0, recv_tab = 0; + USHORT scancode; + static int recv_lalt = 0; + static int recv_ralt = 0; + static int recv_tab = 0; RAWKEYBOARD rawKB = raw->data.keyboard; - scancode = rawKB.MakeCode; + scancode = rawKB.MakeCode; if (kbd_req_capture && !mouse_capture && !video_fullscreen) - return; + return; /* If it's not a scan code that starts with 0xE1 */ if (!(rawKB.Flags & RI_KEY_E1)) { - if (rawKB.Flags & RI_KEY_E0) - scancode |= 0x100; + if (rawKB.Flags & RI_KEY_E0) + scancode |= 0x100; - /* Translate the scan code to 9-bit */ - scancode = convert_scan_code(scancode); + /* Translate the scan code to 9-bit */ + scancode = convert_scan_code(scancode); - /* Remap it according to the list from the Registry */ - if (scancode != scancode_map[scancode]) - pclog("Scan code remap: %03X -> %03X\n", scancode, scancode); - scancode = scancode_map[scancode]; + /* Remap it according to the list from the Registry */ + if (scancode != scancode_map[scancode]) + pclog("Scan code remap: %03X -> %03X\n", scancode, scancode); + scancode = scancode_map[scancode]; - /* If it's not 0xFFFF, send it to the emulated - keyboard. - We use scan code 0xFFFF to mean a mapping that - has a prefix other than E0 and that is not E1 1D, - which is, for our purposes, invalid. */ - if ((scancode == 0x00F) && - !(rawKB.Flags & RI_KEY_BREAK) && - (recv_lalt || recv_ralt) && - !mouse_capture) { - /* We received a TAB while ALT was pressed, while the mouse - is not captured, suppress the TAB and send an ALT key up. */ - if (recv_lalt) { - keyboard_input(0, 0x038); - /* Extra key press and release so the guest is not stuck in the - menu bar. */ - keyboard_input(1, 0x038); - keyboard_input(0, 0x038); - recv_lalt = 0; - } - if (recv_ralt) { - keyboard_input(0, 0x138); - /* Extra key press and release so the guest is not stuck in the - menu bar. */ - keyboard_input(1, 0x138); - keyboard_input(0, 0x138); - recv_ralt = 0; - } - } else if (((scancode == 0x038) || (scancode == 0x138)) && - !(rawKB.Flags & RI_KEY_BREAK) && - recv_tab && - !mouse_capture) { - /* We received an ALT while TAB was pressed, while the mouse - is not captured, suppress the ALT and send a TAB key up. */ - keyboard_input(0, 0x00F); - recv_tab = 0; - } else { - switch(scancode) { - case 0x00F: - recv_tab = !(rawKB.Flags & RI_KEY_BREAK); - break; - case 0x038: - recv_lalt = !(rawKB.Flags & RI_KEY_BREAK); - break; - case 0x138: - recv_ralt = !(rawKB.Flags & RI_KEY_BREAK); - break; - } + /* If it's not 0xFFFF, send it to the emulated + keyboard. + We use scan code 0xFFFF to mean a mapping that + has a prefix other than E0 and that is not E1 1D, + which is, for our purposes, invalid. */ + if ((scancode == 0x00f) && !(rawKB.Flags & RI_KEY_BREAK) && (recv_lalt || recv_ralt) && (!kbd_req_capture || mouse_capture)) { + /* We received a TAB while ALT was pressed, while the mouse + is not captured, suppress the TAB and send an ALT key up. */ + if (recv_lalt) { + keyboard_input(0, 0x038); + /* Extra key press and release so the guest is not stuck in the + menu bar. */ + keyboard_input(1, 0x038); + keyboard_input(0, 0x038); + recv_lalt = 0; + } + if (recv_ralt) { + keyboard_input(0, 0x138); + /* Extra key press and release so the guest is not stuck in the + menu bar. */ + keyboard_input(1, 0x138); + keyboard_input(0, 0x138); + recv_ralt = 0; + } + } else if (((scancode == 0x038) || (scancode == 0x138)) && !(rawKB.Flags & RI_KEY_BREAK) && recv_tab && (!kbd_req_capture || mouse_capture)) { + /* We received an ALT while TAB was pressed, while the mouse + is not captured, suppress the ALT and send a TAB key up. */ + keyboard_input(0, 0x00f); + recv_tab = 0; + } else { + switch (scancode) { + case 0x00f: + recv_tab = !(rawKB.Flags & RI_KEY_BREAK); + break; + case 0x038: + recv_lalt = !(rawKB.Flags & RI_KEY_BREAK); + break; + case 0x138: + recv_ralt = !(rawKB.Flags & RI_KEY_BREAK); + break; + } - /* Translate right CTRL to left ALT if the user has so - chosen. */ - if ((scancode == 0x11D) && rctrl_is_lalt) - scancode = 0x038; + /* Translate right CTRL to left ALT if the user has so + chosen. */ + if ((scancode == 0x11d) && rctrl_is_lalt) + scancode = 0x038; - /* Normal scan code pass through, pass it through as is if - it's not an invalid scan code. */ - if (scancode != 0xFFFF) - keyboard_input(!(rawKB.Flags & RI_KEY_BREAK), scancode); - } + /* Normal scan code pass through, pass it through as is if + it's not an invalid scan code. */ + if (scancode != 0xFFFF) + keyboard_input(!(rawKB.Flags & RI_KEY_BREAK), scancode); + } } else { - if (rawKB.MakeCode == 0x1D) { - scancode = scancode_map[0x100]; /* Translate E1 1D to 0x100 (which would - otherwise be E0 00 but that is invalid - anyway). - Also, take a potential mapping into - account. */ - } else - scancode = 0xFFFF; - if (scancode != 0xFFFF) - keyboard_input(!(rawKB.Flags & RI_KEY_BREAK), scancode); + if (rawKB.MakeCode == 0x1D) { + scancode = scancode_map[0x100]; /* Translate E1 1D to 0x100 (which would + otherwise be E0 00 but that is invalid + anyway). + Also, take a potential mapping into + account. */ + } else + scancode = 0xFFFF; + if (scancode != 0xFFFF) + keyboard_input(!(rawKB.Flags & RI_KEY_BREAK), scancode); } } diff --git a/src/win/win_media_menu.c b/src/win/win_media_menu.c index cf7974dd4..549a495b9 100644 --- a/src/win/win_media_menu.c +++ b/src/win/win_media_menu.c @@ -3,6 +3,7 @@ #include #include #include +#include #include <86box/86box.h> #include <86box/cdrom.h> #include <86box/config.h> @@ -24,22 +25,21 @@ #include <86box/zip.h> #include <86box/win.h> -#define MACHINE_HAS_IDE (machine_has_flags(machine, MACHINE_IDE_QUAD)) -#define MACHINE_HAS_SCSI (machine_has_flags(machine, MACHINE_SCSI_DUAL)) +#define MACHINE_HAS_IDE (machine_has_flags(machine, MACHINE_IDE_QUAD)) +#define MACHINE_HAS_SCSI (machine_has_flags(machine, MACHINE_SCSI)) -#define CASSETTE_FIRST 0 -#define CARTRIDGE_FIRST CASSETTE_FIRST + 1 -#define FDD_FIRST CARTRIDGE_FIRST + 2 -#define CDROM_FIRST FDD_FIRST + FDD_NUM -#define ZIP_FIRST CDROM_FIRST + CDROM_NUM -#define MO_FIRST ZIP_FIRST + ZIP_NUM +#define CASSETTE_FIRST 0 +#define CARTRIDGE_FIRST CASSETTE_FIRST + 1 +#define FDD_FIRST CARTRIDGE_FIRST + 2 +#define CDROM_FIRST FDD_FIRST + FDD_NUM +#define ZIP_FIRST CDROM_FIRST + CDROM_NUM +#define MO_FIRST ZIP_FIRST + ZIP_NUM +static HMENU media_menu; +static HMENU stbar_menu; +static HMENU menus[1 + 2 + FDD_NUM + CDROM_NUM + ZIP_NUM + MO_NUM]; -static HMENU media_menu, stbar_menu; -static HMENU menus[1 + 2 + FDD_NUM + CDROM_NUM + ZIP_NUM + MO_NUM]; - -static char index_map[255]; - +static char index_map[255]; static void media_menu_set_ids(HMENU hMenu, int id) @@ -47,18 +47,16 @@ media_menu_set_ids(HMENU hMenu, int id) int c = GetMenuItemCount(hMenu); MENUITEMINFO mii = { 0 }; - mii.fMask = MIIM_ID; - mii.cbSize = sizeof(mii); + mii.fMask = MIIM_ID; + mii.cbSize = sizeof(mii); - for(int i = 0; i < c; i++) - { - GetMenuItemInfo(hMenu, i, TRUE, &mii); - mii.wID |= id; - SetMenuItemInfo(hMenu, i, TRUE, &mii); + for (int i = 0; i < c; i++) { + GetMenuItemInfo(hMenu, i, TRUE, &mii); + mii.wID |= id; + SetMenuItemInfo(hMenu, i, TRUE, &mii); } } - /* Loads the submenu from resource by name */ static HMENU media_menu_load_resource(wchar_t *lpName) @@ -69,302 +67,301 @@ media_menu_load_resource(wchar_t *lpName) HMENU actual = GetSubMenu(loaded, 0); /* Now that we have our submenu, we can destroy the parent menu */ - RemoveMenu(loaded, (UINT_PTR)actual, MF_BYCOMMAND); + RemoveMenu(loaded, (UINT_PTR) actual, MF_BYCOMMAND); DestroyMenu(loaded); return actual; } - static void media_menu_set_name_cassette(void) { - wchar_t name[512], fn[512]; + wchar_t name[512]; + wchar_t fn[512]; MENUITEMINFO mii = { 0 }; if (strlen(cassette_fname) == 0) - _swprintf(name, plat_get_string(IDS_2148), plat_get_string(IDS_2057)); + _swprintf(name, plat_get_string(IDS_2149), plat_get_string(IDS_2057)); else { - mbstoc16s(fn, cassette_fname, sizeof_w(fn)); - _swprintf(name, plat_get_string(IDS_2148), fn); + mbstoc16s(fn, cassette_fname, sizeof_w(fn)); + _swprintf(name, plat_get_string(IDS_2149), fn); } - mii.cbSize = sizeof(mii); - mii.fMask = MIIM_STRING; + mii.cbSize = sizeof(mii); + mii.fMask = MIIM_STRING; mii.dwTypeData = name; - SetMenuItemInfo(media_menu, (UINT_PTR)menus[CASSETTE_FIRST], FALSE, &mii); + SetMenuItemInfo(media_menu, (UINT_PTR) menus[CASSETTE_FIRST], FALSE, &mii); } - static void media_menu_set_name_cartridge(int drive) { - wchar_t name[512], fn[512]; + wchar_t name[512]; + wchar_t fn[512]; MENUITEMINFO mii = { 0 }; if (strlen(cart_fns[drive]) == 0) { - _swprintf(name, plat_get_string(IDS_2150), - drive + 1, plat_get_string(IDS_2057)); + _swprintf(name, plat_get_string(IDS_2151), + drive + 1, plat_get_string(IDS_2057)); } else { - mbstoc16s(fn, cart_fns[drive], sizeof_w(fn)); - _swprintf(name, plat_get_string(IDS_2150), - drive + 1, fn); + mbstoc16s(fn, cart_fns[drive], sizeof_w(fn)); + _swprintf(name, plat_get_string(IDS_2151), + drive + 1, fn); } - mii.cbSize = sizeof(mii); - mii.fMask = MIIM_STRING; + mii.cbSize = sizeof(mii); + mii.fMask = MIIM_STRING; mii.dwTypeData = name; - SetMenuItemInfo(media_menu, (UINT_PTR)menus[CARTRIDGE_FIRST + drive], FALSE, &mii); + SetMenuItemInfo(media_menu, (UINT_PTR) menus[CARTRIDGE_FIRST + drive], FALSE, &mii); } - static void media_menu_set_name_floppy(int drive) { - wchar_t name[512], temp[512], fn[512]; + wchar_t name[512]; + wchar_t temp[512]; + wchar_t fn[512]; MENUITEMINFO mii = { 0 }; mbstoc16s(temp, fdd_getname(fdd_get_type(drive)), - strlen(fdd_getname(fdd_get_type(drive))) + 1); + strlen(fdd_getname(fdd_get_type(drive))) + 1); if (strlen(floppyfns[drive]) == 0) { - _swprintf(name, plat_get_string(IDS_2108), - drive + 1, temp, plat_get_string(IDS_2057)); + _swprintf(name, plat_get_string(IDS_2109), + drive + 1, temp, plat_get_string(IDS_2057)); } else { - mbstoc16s(fn, floppyfns[drive], sizeof_w(fn)); - _swprintf(name, plat_get_string(IDS_2108), - drive + 1, temp, fn); + mbstoc16s(fn, floppyfns[drive], sizeof_w(fn)); + _swprintf(name, plat_get_string(IDS_2109), + drive + 1, temp, fn); } - mii.cbSize = sizeof(mii); - mii.fMask = MIIM_STRING; + mii.cbSize = sizeof(mii); + mii.fMask = MIIM_STRING; mii.dwTypeData = name; - SetMenuItemInfo(media_menu, (UINT_PTR)menus[FDD_FIRST + drive], FALSE, &mii); + SetMenuItemInfo(media_menu, (UINT_PTR) menus[FDD_FIRST + drive], FALSE, &mii); } - static void media_menu_set_name_cdrom(int drive) { - wchar_t name[512], *temp, fn[512]; + wchar_t name[512]; + wchar_t *temp; + wchar_t fn[512]; MENUITEMINFO mii = { 0 }; int bus = cdrom[drive].bus_type; - int id = IDS_5377 + (bus - 1); + int id = IDS_5377 + (bus - 1); temp = plat_get_string(id); if (cdrom[drive].host_drive == 200) { - if (strlen(cdrom[drive].image_path) == 0) { - _swprintf(name, plat_get_string(IDS_5120), - drive+1, temp, plat_get_string(IDS_2057)); - } else { - mbstoc16s(fn, cdrom[drive].image_path, sizeof_w(fn)); - _swprintf(name, plat_get_string(IDS_5120), - drive+1, temp, fn); - } + if (strlen(cdrom[drive].image_path) == 0) { + _swprintf(name, plat_get_string(IDS_5120), + drive + 1, temp, plat_get_string(IDS_2057)); + } else { + mbstoc16s(fn, cdrom[drive].image_path, sizeof_w(fn)); + _swprintf(name, plat_get_string(IDS_5120), + drive + 1, temp, fn); + } } else - _swprintf(name, plat_get_string(IDS_5120), drive+1, temp, plat_get_string(IDS_2057)); + _swprintf(name, plat_get_string(IDS_5120), drive + 1, temp, plat_get_string(IDS_2057)); - mii.cbSize = sizeof(mii); - mii.fMask = MIIM_STRING; + mii.cbSize = sizeof(mii); + mii.fMask = MIIM_STRING; mii.dwTypeData = name; - SetMenuItemInfo(media_menu, (UINT_PTR)menus[CDROM_FIRST + drive], FALSE, &mii); + SetMenuItemInfo(media_menu, (UINT_PTR) menus[CDROM_FIRST + drive], FALSE, &mii); } - static void media_menu_set_name_zip(int drive) { - wchar_t name[512], *temp, fn[512]; + wchar_t name[512]; + wchar_t *temp; + wchar_t fn[512]; MENUITEMINFO mii = { 0 }; int bus = zip_drives[drive].bus_type; - int id = IDS_5377 + (bus - 1); + int id = IDS_5377 + (bus - 1); temp = plat_get_string(id); int type = zip_drives[drive].is_250 ? 250 : 100; if (strlen(zip_drives[drive].image_path) == 0) { - _swprintf(name, plat_get_string(IDS_2054), - type, drive+1, temp, plat_get_string(IDS_2057)); + _swprintf(name, plat_get_string(IDS_2054), + type, drive + 1, temp, plat_get_string(IDS_2057)); } else { - mbstoc16s(fn, zip_drives[drive].image_path, sizeof_w(fn)); - _swprintf(name, plat_get_string(IDS_2054), - type, drive+1, temp, fn); + mbstoc16s(fn, zip_drives[drive].image_path, sizeof_w(fn)); + _swprintf(name, plat_get_string(IDS_2054), + type, drive + 1, temp, fn); } - mii.cbSize = sizeof(mii); - mii.fMask = MIIM_STRING; + mii.cbSize = sizeof(mii); + mii.fMask = MIIM_STRING; mii.dwTypeData = name; - SetMenuItemInfo(media_menu, (UINT_PTR)menus[ZIP_FIRST + drive], FALSE, &mii); + SetMenuItemInfo(media_menu, (UINT_PTR) menus[ZIP_FIRST + drive], FALSE, &mii); } - static void media_menu_set_name_mo(int drive) { - wchar_t name[512], *temp, fn[512]; + wchar_t name[512]; + wchar_t *temp; + wchar_t fn[512]; MENUITEMINFO mii = { 0 }; int bus = mo_drives[drive].bus_type; - int id = IDS_5377 + (bus - 1); + int id = IDS_5377 + (bus - 1); temp = plat_get_string(id); if (strlen(mo_drives[drive].image_path) == 0) { - _swprintf(name, plat_get_string(IDS_2115), - drive+1, temp, plat_get_string(IDS_2057)); + _swprintf(name, plat_get_string(IDS_2116), + drive + 1, temp, plat_get_string(IDS_2057)); } else { - mbstoc16s(fn, mo_drives[drive].image_path, sizeof_w(fn)); - _swprintf(name, plat_get_string(IDS_2115), - drive+1, temp, fn); + mbstoc16s(fn, mo_drives[drive].image_path, sizeof_w(fn)); + _swprintf(name, plat_get_string(IDS_2116), + drive + 1, temp, fn); } - mii.cbSize = sizeof(mii); - mii.fMask = MIIM_STRING; + mii.cbSize = sizeof(mii); + mii.fMask = MIIM_STRING; mii.dwTypeData = name; - SetMenuItemInfo(media_menu, (UINT_PTR)menus[MO_FIRST + drive], FALSE, &mii); + SetMenuItemInfo(media_menu, (UINT_PTR) menus[MO_FIRST + drive], FALSE, &mii); } - void media_menu_update_cassette(void) { int i = CASSETTE_FIRST; if (strlen(cassette_fname) == 0) { - EnableMenuItem(menus[i], IDM_CASSETTE_EJECT, MF_BYCOMMAND | MF_GRAYED); - EnableMenuItem(menus[i], IDM_CASSETTE_RECORD, MF_BYCOMMAND | MF_GRAYED); - EnableMenuItem(menus[i], IDM_CASSETTE_PLAY, MF_BYCOMMAND | MF_GRAYED); - CheckMenuItem(menus[i], IDM_CASSETTE_RECORD, MF_BYCOMMAND | MF_UNCHECKED); - CheckMenuItem(menus[i], IDM_CASSETTE_PLAY, MF_BYCOMMAND | MF_UNCHECKED); - EnableMenuItem(menus[i], IDM_CASSETTE_REWIND, MF_BYCOMMAND | MF_GRAYED); - EnableMenuItem(menus[i], IDM_CASSETTE_FAST_FORWARD, MF_BYCOMMAND | MF_GRAYED); + EnableMenuItem(menus[i], IDM_CASSETTE_EJECT, MF_BYCOMMAND | MF_GRAYED); + EnableMenuItem(menus[i], IDM_CASSETTE_RECORD, MF_BYCOMMAND | MF_GRAYED); + EnableMenuItem(menus[i], IDM_CASSETTE_PLAY, MF_BYCOMMAND | MF_GRAYED); + CheckMenuItem(menus[i], IDM_CASSETTE_RECORD, MF_BYCOMMAND | MF_UNCHECKED); + CheckMenuItem(menus[i], IDM_CASSETTE_PLAY, MF_BYCOMMAND | MF_UNCHECKED); + EnableMenuItem(menus[i], IDM_CASSETTE_REWIND, MF_BYCOMMAND | MF_GRAYED); + EnableMenuItem(menus[i], IDM_CASSETTE_FAST_FORWARD, MF_BYCOMMAND | MF_GRAYED); } else { - EnableMenuItem(menus[i], IDM_CASSETTE_EJECT, MF_BYCOMMAND | MF_ENABLED); - EnableMenuItem(menus[i], IDM_CASSETTE_RECORD, MF_BYCOMMAND | MF_ENABLED); - EnableMenuItem(menus[i], IDM_CASSETTE_PLAY, MF_BYCOMMAND | MF_ENABLED); - if (strcmp(cassette_mode, "save") == 0) { - CheckMenuItem(menus[i], IDM_CASSETTE_RECORD, MF_BYCOMMAND | MF_CHECKED); - CheckMenuItem(menus[i], IDM_CASSETTE_PLAY, MF_BYCOMMAND | MF_UNCHECKED); - } else { - CheckMenuItem(menus[i], IDM_CASSETTE_RECORD, MF_BYCOMMAND | MF_UNCHECKED); - CheckMenuItem(menus[i], IDM_CASSETTE_PLAY, MF_BYCOMMAND | MF_CHECKED); - } - EnableMenuItem(menus[i], IDM_CASSETTE_REWIND, MF_BYCOMMAND | MF_ENABLED); - EnableMenuItem(menus[i], IDM_CASSETTE_FAST_FORWARD, MF_BYCOMMAND | MF_ENABLED); + EnableMenuItem(menus[i], IDM_CASSETTE_EJECT, MF_BYCOMMAND | MF_ENABLED); + EnableMenuItem(menus[i], IDM_CASSETTE_RECORD, MF_BYCOMMAND | MF_ENABLED); + EnableMenuItem(menus[i], IDM_CASSETTE_PLAY, MF_BYCOMMAND | MF_ENABLED); + if (strcmp(cassette_mode, "save") == 0) { + CheckMenuItem(menus[i], IDM_CASSETTE_RECORD, MF_BYCOMMAND | MF_CHECKED); + CheckMenuItem(menus[i], IDM_CASSETTE_PLAY, MF_BYCOMMAND | MF_UNCHECKED); + } else { + CheckMenuItem(menus[i], IDM_CASSETTE_RECORD, MF_BYCOMMAND | MF_UNCHECKED); + CheckMenuItem(menus[i], IDM_CASSETTE_PLAY, MF_BYCOMMAND | MF_CHECKED); + } + EnableMenuItem(menus[i], IDM_CASSETTE_REWIND, MF_BYCOMMAND | MF_ENABLED); + EnableMenuItem(menus[i], IDM_CASSETTE_FAST_FORWARD, MF_BYCOMMAND | MF_ENABLED); } media_menu_set_name_cassette(); } - void media_menu_update_cartridge(int id) { int i = CARTRIDGE_FIRST + id; if (strlen(cart_fns[id]) == 0) - EnableMenuItem(menus[i], IDM_CARTRIDGE_EJECT | id, MF_BYCOMMAND | MF_GRAYED); + EnableMenuItem(menus[i], IDM_CARTRIDGE_EJECT | id, MF_BYCOMMAND | MF_GRAYED); else - EnableMenuItem(menus[i], IDM_CARTRIDGE_EJECT | id, MF_BYCOMMAND | MF_ENABLED); + EnableMenuItem(menus[i], IDM_CARTRIDGE_EJECT | id, MF_BYCOMMAND | MF_ENABLED); media_menu_set_name_cartridge(id); } - void media_menu_update_floppy(int id) { int i = FDD_FIRST + id; if (strlen(floppyfns[id]) == 0) { - EnableMenuItem(menus[i], IDM_FLOPPY_EJECT | id, MF_BYCOMMAND | MF_GRAYED); - EnableMenuItem(menus[i], IDM_FLOPPY_EXPORT_TO_86F | id, MF_BYCOMMAND | MF_GRAYED); + EnableMenuItem(menus[i], IDM_FLOPPY_EJECT | id, MF_BYCOMMAND | MF_GRAYED); + EnableMenuItem(menus[i], IDM_FLOPPY_EXPORT_TO_86F | id, MF_BYCOMMAND | MF_GRAYED); } else { - EnableMenuItem(menus[i], IDM_FLOPPY_EJECT | id, MF_BYCOMMAND | MF_ENABLED); - EnableMenuItem(menus[i], IDM_FLOPPY_EXPORT_TO_86F | id, MF_BYCOMMAND | MF_ENABLED); + EnableMenuItem(menus[i], IDM_FLOPPY_EJECT | id, MF_BYCOMMAND | MF_ENABLED); + EnableMenuItem(menus[i], IDM_FLOPPY_EXPORT_TO_86F | id, MF_BYCOMMAND | MF_ENABLED); } media_menu_set_name_floppy(id); } - void media_menu_update_cdrom(int id) { int i = CDROM_FIRST + id; - if (! cdrom[id].sound_on) - CheckMenuItem(menus[i], IDM_CDROM_MUTE | id, MF_BYCOMMAND | MF_CHECKED); + if (!cdrom[id].sound_on) + CheckMenuItem(menus[i], IDM_CDROM_MUTE | id, MF_BYCOMMAND | MF_CHECKED); else - CheckMenuItem(menus[i], IDM_CDROM_MUTE | id, MF_BYCOMMAND | MF_UNCHECKED); + CheckMenuItem(menus[i], IDM_CDROM_MUTE | id, MF_BYCOMMAND | MF_UNCHECKED); if (cdrom[id].host_drive == 200) { - CheckMenuItem(menus[i], IDM_CDROM_IMAGE | id, MF_BYCOMMAND | MF_CHECKED); - CheckMenuItem(menus[i], IDM_CDROM_EMPTY | id, MF_BYCOMMAND | MF_UNCHECKED); + CheckMenuItem(menus[i], IDM_CDROM_IMAGE | id, MF_BYCOMMAND | (cdrom[id].is_dir ? MF_UNCHECKED : MF_CHECKED)); + CheckMenuItem(menus[i], IDM_CDROM_DIR | id, MF_BYCOMMAND | (cdrom[id].is_dir ? MF_CHECKED : MF_UNCHECKED)); + CheckMenuItem(menus[i], IDM_CDROM_EMPTY | id, MF_BYCOMMAND | MF_UNCHECKED); } else { - cdrom[id].host_drive = 0; - CheckMenuItem(menus[i], IDM_CDROM_IMAGE | id, MF_BYCOMMAND | MF_UNCHECKED); - CheckMenuItem(menus[i], IDM_CDROM_EMPTY | id, MF_BYCOMMAND | MF_CHECKED); + cdrom[id].host_drive = 0; + CheckMenuItem(menus[i], IDM_CDROM_IMAGE | id, MF_BYCOMMAND | MF_UNCHECKED); + CheckMenuItem(menus[i], IDM_CDROM_DIR | id, MF_BYCOMMAND | MF_UNCHECKED); + CheckMenuItem(menus[i], IDM_CDROM_EMPTY | id, MF_BYCOMMAND | MF_CHECKED); } - if(cdrom[id].prev_host_drive == 0) - EnableMenuItem(menus[i], IDM_CDROM_RELOAD | id, MF_BYCOMMAND | MF_GRAYED); + if (cdrom[id].prev_host_drive == 0) + EnableMenuItem(menus[i], IDM_CDROM_RELOAD | id, MF_BYCOMMAND | MF_GRAYED); else - EnableMenuItem(menus[i], IDM_CDROM_RELOAD | id, MF_BYCOMMAND | MF_ENABLED); + EnableMenuItem(menus[i], IDM_CDROM_RELOAD | id, MF_BYCOMMAND | MF_ENABLED); media_menu_set_name_cdrom(id); } - void media_menu_update_zip(int id) { int i = ZIP_FIRST + id; if (strlen(zip_drives[id].image_path) == 0) - EnableMenuItem(menus[i], IDM_ZIP_EJECT | id, MF_BYCOMMAND | MF_GRAYED); + EnableMenuItem(menus[i], IDM_ZIP_EJECT | id, MF_BYCOMMAND | MF_GRAYED); else - EnableMenuItem(menus[i], IDM_ZIP_EJECT | id, MF_BYCOMMAND | MF_ENABLED); + EnableMenuItem(menus[i], IDM_ZIP_EJECT | id, MF_BYCOMMAND | MF_ENABLED); - if(strlen(zip_drives[id].prev_image_path) == 0) - EnableMenuItem(menus[i], IDM_ZIP_RELOAD | id, MF_BYCOMMAND | MF_GRAYED); + if (strlen(zip_drives[id].prev_image_path) == 0) + EnableMenuItem(menus[i], IDM_ZIP_RELOAD | id, MF_BYCOMMAND | MF_GRAYED); else - EnableMenuItem(menus[i], IDM_ZIP_RELOAD | id, MF_BYCOMMAND | MF_ENABLED); + EnableMenuItem(menus[i], IDM_ZIP_RELOAD | id, MF_BYCOMMAND | MF_ENABLED); media_menu_set_name_zip(id); } - void media_menu_update_mo(int id) { int i = MO_FIRST + id; if (strlen(mo_drives[id].image_path) == 0) - EnableMenuItem(menus[i], IDM_MO_EJECT | id, MF_BYCOMMAND | MF_GRAYED); + EnableMenuItem(menus[i], IDM_MO_EJECT | id, MF_BYCOMMAND | MF_GRAYED); else - EnableMenuItem(menus[i], IDM_MO_EJECT | id, MF_BYCOMMAND | MF_ENABLED); + EnableMenuItem(menus[i], IDM_MO_EJECT | id, MF_BYCOMMAND | MF_ENABLED); - if(strlen(mo_drives[id].prev_image_path) == 0) - EnableMenuItem(menus[i], IDM_MO_RELOAD | id, MF_BYCOMMAND | MF_GRAYED); + if (strlen(mo_drives[id].prev_image_path) == 0) + EnableMenuItem(menus[i], IDM_MO_RELOAD | id, MF_BYCOMMAND | MF_GRAYED); else - EnableMenuItem(menus[i], IDM_MO_RELOAD | id, MF_BYCOMMAND | MF_ENABLED); + EnableMenuItem(menus[i], IDM_MO_RELOAD | id, MF_BYCOMMAND | MF_ENABLED); media_menu_set_name_mo(id); } - static void -media_menu_load_submenus() +media_menu_load_submenus(void) { memset(index_map, -1, sizeof(index_map)); @@ -373,185 +370,165 @@ media_menu_load_submenus() menus[curr] = media_menu_load_resource(CASSETTE_SUBMENU_NAME); media_menu_set_ids(menus[curr++], 0); - for(int i = 0; i < 2; i++) { - menus[curr] = media_menu_load_resource(CARTRIDGE_SUBMENU_NAME); - media_menu_set_ids(menus[curr++], i); + for (int i = 0; i < 2; i++) { + menus[curr] = media_menu_load_resource(CARTRIDGE_SUBMENU_NAME); + media_menu_set_ids(menus[curr++], i); } - for(int i = 0; i < FDD_NUM; i++) { - menus[curr] = media_menu_load_resource(FLOPPY_SUBMENU_NAME); - media_menu_set_ids(menus[curr++], i); + for (int i = 0; i < FDD_NUM; i++) { + menus[curr] = media_menu_load_resource(FLOPPY_SUBMENU_NAME); + media_menu_set_ids(menus[curr++], i); } - for(int i = 0; i < CDROM_NUM; i++) { - menus[curr] = media_menu_load_resource(CDROM_SUBMENU_NAME); - media_menu_set_ids(menus[curr++], i); + for (int i = 0; i < CDROM_NUM; i++) { + menus[curr] = media_menu_load_resource(CDROM_SUBMENU_NAME); + media_menu_set_ids(menus[curr++], i); } - for(int i = 0; i < ZIP_NUM; i++) { - menus[curr] = media_menu_load_resource(ZIP_SUBMENU_NAME); - media_menu_set_ids(menus[curr++], i); + for (int i = 0; i < ZIP_NUM; i++) { + menus[curr] = media_menu_load_resource(ZIP_SUBMENU_NAME); + media_menu_set_ids(menus[curr++], i); } - for(int i = 0; i < MO_NUM; i++) { - menus[curr] = media_menu_load_resource(MO_SUBMENU_NAME); - media_menu_set_ids(menus[curr++], i); + for (int i = 0; i < MO_NUM; i++) { + menus[curr] = media_menu_load_resource(MO_SUBMENU_NAME); + media_menu_set_ids(menus[curr++], i); } } - static inline int is_valid_cartridge(void) { return (machine_has_cartridge(machine)); } - static inline int is_valid_fdd(int i) { return fdd_get_type(i) != 0; } - static inline int is_valid_cdrom(int i) { - if ((cdrom[i].bus_type == CDROM_BUS_ATAPI) && !MACHINE_HAS_IDE && - memcmp(hdc_get_internal_name(hdc_current), "xtide", 5) && - memcmp(hdc_get_internal_name(hdc_current), "ide", 3)) - return 0; - if ((cdrom[i].bus_type == CDROM_BUS_SCSI) && !MACHINE_HAS_SCSI && - (scsi_card_current[0] == 0) && (scsi_card_current[1] == 0) && - (scsi_card_current[2] == 0) && (scsi_card_current[3] == 0)) - return 0; + if ((cdrom[i].bus_type == CDROM_BUS_ATAPI) && !MACHINE_HAS_IDE && memcmp(hdc_get_internal_name(hdc_current), "xtide", 5) && memcmp(hdc_get_internal_name(hdc_current), "ide", 3)) + return 0; + if ((cdrom[i].bus_type == CDROM_BUS_SCSI) && !MACHINE_HAS_SCSI && (scsi_card_current[0] == 0) && (scsi_card_current[1] == 0) && (scsi_card_current[2] == 0) && (scsi_card_current[3] == 0)) + return 0; return cdrom[i].bus_type != 0; } - static inline int is_valid_zip(int i) { - if ((zip_drives[i].bus_type == ZIP_BUS_ATAPI) && !MACHINE_HAS_IDE && - memcmp(hdc_get_internal_name(hdc_current), "xtide", 5) && - memcmp(hdc_get_internal_name(hdc_current), "ide", 3)) - return 0; - if ((zip_drives[i].bus_type == ZIP_BUS_SCSI) && !MACHINE_HAS_SCSI && - (scsi_card_current[0] == 0) && (scsi_card_current[1] == 0) && - (scsi_card_current[2] == 0) && (scsi_card_current[3] == 0)) - return 0; + if ((zip_drives[i].bus_type == ZIP_BUS_ATAPI) && !MACHINE_HAS_IDE && memcmp(hdc_get_internal_name(hdc_current), "xtide", 5) && memcmp(hdc_get_internal_name(hdc_current), "ide", 3)) + return 0; + if ((zip_drives[i].bus_type == ZIP_BUS_SCSI) && !MACHINE_HAS_SCSI && (scsi_card_current[0] == 0) && (scsi_card_current[1] == 0) && (scsi_card_current[2] == 0) && (scsi_card_current[3] == 0)) + return 0; return zip_drives[i].bus_type != 0; } - static inline int is_valid_mo(int i) { - if ((mo_drives[i].bus_type == MO_BUS_ATAPI) && !MACHINE_HAS_IDE && - memcmp(hdc_get_internal_name(hdc_current), "xtide", 5) && - memcmp(hdc_get_internal_name(hdc_current), "ide", 3)) - return 0; - if ((mo_drives[i].bus_type == MO_BUS_SCSI) && !MACHINE_HAS_SCSI && - (scsi_card_current[0] == 0) && (scsi_card_current[1] == 0) && - (scsi_card_current[2] == 0) && (scsi_card_current[3] == 0)) - return 0; + if ((mo_drives[i].bus_type == MO_BUS_ATAPI) && !MACHINE_HAS_IDE && memcmp(hdc_get_internal_name(hdc_current), "xtide", 5) && memcmp(hdc_get_internal_name(hdc_current), "ide", 3)) + return 0; + if ((mo_drives[i].bus_type == MO_BUS_SCSI) && !MACHINE_HAS_SCSI && (scsi_card_current[0] == 0) && (scsi_card_current[1] == 0) && (scsi_card_current[2] == 0) && (scsi_card_current[3] == 0)) + return 0; return mo_drives[i].bus_type != 0; } - void -media_menu_reset() +media_menu_reset(void) { /* Remove existing entries. */ int c = GetMenuItemCount(media_menu); - for(int i = 0; i < c; i++) - RemoveMenu(media_menu, 0, MF_BYPOSITION); + for (int i = 0; i < c; i++) + RemoveMenu(media_menu, 0, MF_BYPOSITION); /* Add new ones. */ int curr = 0; - if(cassette_enable) { - AppendMenu(media_menu, MF_POPUP | MF_STRING, (UINT_PTR)menus[curr], L"Test"); - media_menu_update_cassette(); + if (cassette_enable) { + AppendMenu(media_menu, MF_POPUP | MF_STRING, (UINT_PTR) menus[curr], L"Test"); + media_menu_update_cassette(); } curr++; - for(int i = 0; i < 2; i++) { - if(is_valid_cartridge()) { - AppendMenu(media_menu, MF_POPUP | MF_STRING, (UINT_PTR)menus[curr], L"Test"); - media_menu_update_cartridge(i); - } - curr++; + for (int i = 0; i < 2; i++) { + if (is_valid_cartridge()) { + AppendMenu(media_menu, MF_POPUP | MF_STRING, (UINT_PTR) menus[curr], L"Test"); + media_menu_update_cartridge(i); + } + curr++; } - for(int i = 0; i < FDD_NUM; i++) { - if(is_valid_fdd(i)) { - AppendMenu(media_menu, MF_POPUP | MF_STRING, (UINT_PTR)menus[curr], L"Test"); - media_menu_update_floppy(i); - } - curr++; + for (int i = 0; i < FDD_NUM; i++) { + if (is_valid_fdd(i)) { + AppendMenu(media_menu, MF_POPUP | MF_STRING, (UINT_PTR) menus[curr], L"Test"); + media_menu_update_floppy(i); + } + curr++; } - for(int i = 0; i < CDROM_NUM; i++) { - if(is_valid_cdrom(i)) { - AppendMenu(media_menu, MF_POPUP | MF_STRING, (UINT_PTR)menus[curr], L"Test"); - media_menu_update_cdrom(i); - } - curr++; + for (int i = 0; i < CDROM_NUM; i++) { + if (is_valid_cdrom(i)) { + AppendMenu(media_menu, MF_POPUP | MF_STRING, (UINT_PTR) menus[curr], L"Test"); + media_menu_update_cdrom(i); + } + curr++; } - for(int i = 0; i < ZIP_NUM; i++) { - if(is_valid_zip(i)) { - AppendMenu(media_menu, MF_POPUP | MF_STRING, (UINT_PTR)menus[curr], L"Test"); - media_menu_update_zip(i); - } - curr++; + for (int i = 0; i < ZIP_NUM; i++) { + if (is_valid_zip(i)) { + AppendMenu(media_menu, MF_POPUP | MF_STRING, (UINT_PTR) menus[curr], L"Test"); + media_menu_update_zip(i); + } + curr++; } - for(int i = 0; i < MO_NUM; i++) { - if(is_valid_mo(i)) { - AppendMenu(media_menu, MF_POPUP | MF_STRING, (UINT_PTR)menus[curr], L"Test"); - media_menu_update_mo(i); - } - curr++; + for (int i = 0; i < MO_NUM; i++) { + if (is_valid_mo(i)) { + AppendMenu(media_menu, MF_POPUP | MF_STRING, (UINT_PTR) menus[curr], L"Test"); + media_menu_update_mo(i); + } + curr++; } } - /* Initializes the Media menu in the main menu bar. */ static void -media_menu_main_init() +media_menu_main_init(void) { - HMENU hMenu; + HMENU hMenu; LPWSTR lpMenuName; - hMenu = GetMenu(hwndMain); + hMenu = GetMenu(hwndMain); media_menu = CreatePopupMenu(); /* Get the menu name */ - int len = GetMenuString(hMenu, IDM_MEDIA, NULL, 0, MF_BYCOMMAND); + int len = GetMenuString(hMenu, IDM_MEDIA, NULL, 0, MF_BYCOMMAND); lpMenuName = malloc((len + 1) * sizeof(WCHAR)); GetMenuString(hMenu, IDM_MEDIA, lpMenuName, len + 1, MF_BYCOMMAND); /* Replace the placeholder menu item */ - ModifyMenu(hMenu, IDM_MEDIA, MF_BYCOMMAND | MF_STRING | MF_POPUP, (UINT_PTR)media_menu, lpMenuName); + ModifyMenu(hMenu, IDM_MEDIA, MF_BYCOMMAND | MF_STRING | MF_POPUP, (UINT_PTR) media_menu, lpMenuName); /* Clean up */ DrawMenuBar(hwndMain); free(lpMenuName); } - void -media_menu_init() +media_menu_init(void) { /* Initialize the main menu bar menu */ media_menu_main_init(); /* Initialize the dummy status bar menu. */ stbar_menu = CreateMenu(); - AppendMenu(stbar_menu, MF_POPUP, (UINT_PTR)media_menu, NULL); + AppendMenu(stbar_menu, MF_POPUP, (UINT_PTR) media_menu, NULL); /* Load the submenus for each drive type. */ media_menu_load_submenus(); @@ -560,203 +537,228 @@ media_menu_init() media_menu_reset(); } - int media_menu_proc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam) { - int id = 0, ret = 0, wp = 0; + int id = 0; + int ret = 0; + int wp = 0; + +#ifdef __clang__ + BROWSEINFO bi; +#endif id = LOWORD(wParam) & 0x00ff; switch (LOWORD(wParam) & 0xff00) { - case IDM_CASSETTE_IMAGE_NEW: - ret = file_dlg_st(hwnd, IDS_2149, "", NULL, 1); - if (! ret) { - if (strlen(openfilestring) == 0) - cassette_mount(NULL, wp); - else - cassette_mount(openfilestring, wp); - } - break; + case IDM_CASSETTE_IMAGE_NEW: + ret = file_dlg_st(hwnd, IDS_2150, "", NULL, 1); + if (!ret) { + if (strlen(openfilestring) == 0) + cassette_mount(NULL, wp); + else + cassette_mount(openfilestring, wp); + } + break; - case IDM_CASSETTE_RECORD: - pc_cas_set_mode(cassette, 1); - CheckMenuItem(menus[CASSETTE_FIRST], IDM_CASSETTE_RECORD, MF_BYCOMMAND | MF_CHECKED); - CheckMenuItem(menus[CASSETTE_FIRST], IDM_CASSETTE_PLAY, MF_BYCOMMAND | MF_UNCHECKED); - break; - case IDM_CASSETTE_PLAY: - pc_cas_set_mode(cassette, 0); - CheckMenuItem(menus[CASSETTE_FIRST], IDM_CASSETTE_RECORD, MF_BYCOMMAND | MF_UNCHECKED); - CheckMenuItem(menus[CASSETTE_FIRST], IDM_CASSETTE_PLAY, MF_BYCOMMAND | MF_CHECKED); - break; - case IDM_CASSETTE_REWIND: - pc_cas_rewind(cassette); - break; - case IDM_CASSETTE_FAST_FORWARD: - pc_cas_append(cassette); - break; + case IDM_CASSETTE_RECORD: + pc_cas_set_mode(cassette, 1); + CheckMenuItem(menus[CASSETTE_FIRST], IDM_CASSETTE_RECORD, MF_BYCOMMAND | MF_CHECKED); + CheckMenuItem(menus[CASSETTE_FIRST], IDM_CASSETTE_PLAY, MF_BYCOMMAND | MF_UNCHECKED); + break; + case IDM_CASSETTE_PLAY: + pc_cas_set_mode(cassette, 0); + CheckMenuItem(menus[CASSETTE_FIRST], IDM_CASSETTE_RECORD, MF_BYCOMMAND | MF_UNCHECKED); + CheckMenuItem(menus[CASSETTE_FIRST], IDM_CASSETTE_PLAY, MF_BYCOMMAND | MF_CHECKED); + break; + case IDM_CASSETTE_REWIND: + pc_cas_rewind(cassette); + break; + case IDM_CASSETTE_FAST_FORWARD: + pc_cas_append(cassette); + break; - case IDM_CASSETTE_IMAGE_EXISTING_WP: - wp = 1; - /* FALLTHROUGH */ - case IDM_CASSETTE_IMAGE_EXISTING: - ret = file_dlg_st(hwnd, IDS_2149, cassette_fname, NULL, 0); - if (! ret) { - if (strlen(openfilestring) == 0) - cassette_mount(NULL, wp); - else - cassette_mount(openfilestring, wp); - } - break; + case IDM_CASSETTE_IMAGE_EXISTING_WP: + wp = 1; + /* FALLTHROUGH */ + case IDM_CASSETTE_IMAGE_EXISTING: + ret = file_dlg_st(hwnd, IDS_2150, cassette_fname, NULL, 0); + if (!ret) { + if (strlen(openfilestring) == 0) + cassette_mount(NULL, wp); + else + cassette_mount(openfilestring, wp); + } + break; - case IDM_CASSETTE_EJECT: - cassette_eject(); - break; + case IDM_CASSETTE_EJECT: + cassette_eject(); + break; - case IDM_CARTRIDGE_IMAGE: - ret = file_dlg_st(hwnd, IDS_2151, cart_fns[id], NULL, 0); - if (! ret) - cartridge_mount(id, openfilestring, wp); - break; + case IDM_CARTRIDGE_IMAGE: + ret = file_dlg_st(hwnd, IDS_2152, cart_fns[id], NULL, 0); + if (!ret) + cartridge_mount(id, openfilestring, wp); + break; - case IDM_CARTRIDGE_EJECT: - cartridge_eject(id); - break; + case IDM_CARTRIDGE_EJECT: + cartridge_eject(id); + break; - case IDM_FLOPPY_IMAGE_NEW: - NewFloppyDialogCreate(hwnd, id, 0); - break; + case IDM_FLOPPY_IMAGE_NEW: + NewFloppyDialogCreate(hwnd, id, 0); + break; - case IDM_FLOPPY_IMAGE_EXISTING_WP: - wp = 1; - /* FALLTHROUGH */ - case IDM_FLOPPY_IMAGE_EXISTING: - ret = file_dlg_st(hwnd, IDS_2109, floppyfns[id], NULL, 0); - if (! ret) - floppy_mount(id, openfilestring, wp); - break; + case IDM_FLOPPY_IMAGE_EXISTING_WP: + wp = 1; + /* FALLTHROUGH */ + case IDM_FLOPPY_IMAGE_EXISTING: + ret = file_dlg_st(hwnd, IDS_2110, floppyfns[id], NULL, 0); + if (!ret) + floppy_mount(id, openfilestring, wp); + break; - case IDM_FLOPPY_EJECT: - floppy_eject(id); - break; + case IDM_FLOPPY_EJECT: + floppy_eject(id); + break; - case IDM_FLOPPY_EXPORT_TO_86F: - ret = file_dlg_st(hwnd, IDS_2076, floppyfns[id], NULL, 1); - if (! ret) { - plat_pause(1); - ret = d86f_export(id, openfilestring); - if (!ret) - ui_msgbox_header(MBX_ERROR, (wchar_t *) IDS_4108, (wchar_t *) IDS_4115); - plat_pause(0); - } - break; + case IDM_FLOPPY_EXPORT_TO_86F: + ret = file_dlg_st(hwnd, IDS_2076, floppyfns[id], NULL, 1); + if (!ret) { + plat_pause(1); + ret = d86f_export(id, openfilestring); + if (!ret) + ui_msgbox_header(MBX_ERROR, (wchar_t *) IDS_4108, (wchar_t *) IDS_4115); + plat_pause(0); + } + break; - case IDM_CDROM_MUTE: - cdrom[id].sound_on ^= 1; - config_save(); - media_menu_update_cdrom(id); - sound_cd_thread_reset(); - break; + case IDM_CDROM_MUTE: + cdrom[id].sound_on ^= 1; + config_save(); + media_menu_update_cdrom(id); + sound_cd_thread_reset(); + break; - case IDM_CDROM_EMPTY: - cdrom_eject(id); - break; + case IDM_CDROM_EMPTY: + cdrom_eject(id); + break; - case IDM_CDROM_RELOAD: - cdrom_reload(id); - break; + case IDM_CDROM_RELOAD: + cdrom_reload(id); + break; - case IDM_CDROM_IMAGE: - if (!file_dlg_st(hwnd, IDS_2140, cdrom[id].image_path, NULL, 0)) { - cdrom_mount(id, openfilestring); - } - break; + case IDM_CDROM_IMAGE: + if (!file_dlg_st(hwnd, IDS_2141, cdrom[id].is_dir ? NULL : cdrom[id].image_path, NULL, 0)) { + cdrom_mount(id, openfilestring); + } + break; - case IDM_ZIP_IMAGE_NEW: - NewFloppyDialogCreate(hwnd, id | 0x80, 0); /* NewZIPDialogCreate */ - break; + case IDM_CDROM_DIR: +#ifndef __clang__ + BROWSEINFO bi = { + .hwndOwner = hwnd, + .ulFlags = BIF_EDITBOX + }; +#else + bi.hwndOwner = hwnd; + bi.ulFlags = BIF_EDITBOX; +#endif + OleInitialize(NULL); + int old_dopause = dopause; + plat_pause(1); + LPITEMIDLIST pidl = SHBrowseForFolder(&bi); + plat_pause(old_dopause); + plat_chdir(usr_path); + if (pidl) { + wchar_t wbuf[MAX_PATH + 1]; + if (SHGetPathFromIDList(pidl, wbuf)) { + char buf[MAX_PATH + 1]; + c16stombs(buf, wbuf, sizeof(buf) - 1); + cdrom_mount(id, buf); + } + } + break; - case IDM_ZIP_IMAGE_EXISTING_WP: - wp = 1; - /* FALLTHROUGH */ - case IDM_ZIP_IMAGE_EXISTING: - ret = file_dlg_st(hwnd, IDS_2058, zip_drives[id].image_path, NULL, 0); - if (! ret) - zip_mount(id, openfilestring, wp); - break; + case IDM_ZIP_IMAGE_NEW: + NewFloppyDialogCreate(hwnd, id | 0x80, 0); /* NewZIPDialogCreate */ + break; - case IDM_ZIP_EJECT: - zip_eject(id); - break; + case IDM_ZIP_IMAGE_EXISTING_WP: + wp = 1; + /* FALLTHROUGH */ + case IDM_ZIP_IMAGE_EXISTING: + ret = file_dlg_st(hwnd, IDS_2058, zip_drives[id].image_path, NULL, 0); + if (!ret) + zip_mount(id, openfilestring, wp); + break; - case IDM_ZIP_RELOAD: - zip_reload(id); - break; + case IDM_ZIP_EJECT: + zip_eject(id); + break; - case IDM_MO_IMAGE_NEW: - NewFloppyDialogCreate(hwnd, id | 0x100, 0); /* NewZIPDialogCreate */ - break; + case IDM_ZIP_RELOAD: + zip_reload(id); + break; - case IDM_MO_IMAGE_EXISTING_WP: - wp = 1; - /* FALLTHROUGH */ - case IDM_MO_IMAGE_EXISTING: - ret = file_dlg_st(hwnd, IDS_2116, mo_drives[id].image_path, NULL, 0); - if (! ret) - mo_mount(id, openfilestring, wp); - break; + case IDM_MO_IMAGE_NEW: + NewFloppyDialogCreate(hwnd, id | 0x100, 0); /* NewZIPDialogCreate */ + break; - case IDM_MO_EJECT: - mo_eject(id); - break; + case IDM_MO_IMAGE_EXISTING_WP: + wp = 1; + /* FALLTHROUGH */ + case IDM_MO_IMAGE_EXISTING: + ret = file_dlg_st(hwnd, IDS_2117, mo_drives[id].image_path, NULL, 0); + if (!ret) + mo_mount(id, openfilestring, wp); + break; - case IDM_MO_RELOAD: - mo_reload(id); - break; + case IDM_MO_EJECT: + mo_eject(id); + break; - default: - return(0); + case IDM_MO_RELOAD: + mo_reload(id); + break; + + default: + return 0; } - return(1); + return 1; } - HMENU media_menu_get_cassette(void) { return menus[CASSETTE_FIRST]; } - HMENU media_menu_get_cartridge(int id) { return menus[CARTRIDGE_FIRST + id]; } - HMENU media_menu_get_floppy(int id) { return menus[FDD_FIRST + id]; } - HMENU media_menu_get_cdrom(int id) { return menus[CDROM_FIRST + id]; } - HMENU media_menu_get_zip(int id) { return menus[ZIP_FIRST + id]; } - HMENU media_menu_get_mo(int id) { diff --git a/src/win/win_mouse.c b/src/win/win_mouse.c index 2e91085ec..f2b185eaa 100644 --- a/src/win/win_mouse.c +++ b/src/win/win_mouse.c @@ -1,42 +1,35 @@ /* - * 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. + * 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. + * This file is part of the 86Box distribution. * - * RawInput mouse interface. + * RawInput mouse interface. * - * Version: @(#)win_mouse_rawinput.cpp 1.0.0 2019/3/19 * - * Authors: Sarah Walker, - * Miran Grca, - * GH Cao, * - * Copyright 2008-2017 Sarah Walker. - * Copyright 2016,2017 Miran Grca. - * Copyright 2019 GH Cao. + * Authors: Miran Grca, + * GH Cao, + * Jasmine Iwanek, + * + * Copyright 2016-2017 Miran Grca. + * Copyright 2019 GH Cao. + * Copyright 2021-2023 Jasmine Iwanek. */ #include #include +#include #include #include #include <86box/86box.h> #include <86box/mouse.h> +#include <86box/pic.h> #include <86box/plat.h> #include <86box/win.h> -int mouse_capture; - -typedef struct { - int buttons; - int dx; - int dy; - int dwheel; -} MOUSESTATE; - -MOUSESTATE mousestate; +int mouse_capture; void win_mouse_init(void) @@ -45,92 +38,88 @@ win_mouse_init(void) mouse_capture = 0; - /* Initialize the RawInput (mouse) module. */ - RAWINPUTDEVICE ridev; - ridev.dwFlags = 0; - ridev.hwndTarget = NULL; - ridev.usUsagePage = 0x01; - ridev.usUsage = 0x02; - if (! RegisterRawInputDevices(&ridev, 1, sizeof(ridev))) - fatal("plat_mouse_init: RegisterRawInputDevices failed\n"); - - memset(&mousestate, 0, sizeof(MOUSESTATE)); + /* Initialize the RawInput (mouse) module. */ + RAWINPUTDEVICE ridev; + ridev.dwFlags = 0; + ridev.hwndTarget = NULL; + ridev.usUsagePage = 0x01; + ridev.usUsage = 0x02; + if (!RegisterRawInputDevices(&ridev, 1, sizeof(ridev))) + fatal("plat_mouse_init: RegisterRawInputDevices failed\n"); } void win_mouse_handle(PRAWINPUT raw) { - RAWMOUSE state = raw->data.mouse; - static int x, y; + RAWMOUSE state = raw->data.mouse; + static int x; + static int delta_x; + static int y; + static int delta_y; + static int b; + static int delta_z; - /* read mouse buttons and wheel */ - if (state.usButtonFlags & RI_MOUSE_LEFT_BUTTON_DOWN) - mousestate.buttons |= 1; - else if (state.usButtonFlags & RI_MOUSE_LEFT_BUTTON_UP) - mousestate.buttons &= ~1; + b = mouse_get_buttons_ex(); - if (state.usButtonFlags & RI_MOUSE_MIDDLE_BUTTON_DOWN) - mousestate.buttons |= 4; - else if (state.usButtonFlags & RI_MOUSE_MIDDLE_BUTTON_UP) - mousestate.buttons &= ~4; + /* read mouse buttons and wheel */ + if (state.usButtonFlags & RI_MOUSE_LEFT_BUTTON_DOWN) + b |= 1; + else if (state.usButtonFlags & RI_MOUSE_LEFT_BUTTON_UP) + b &= ~1; - if (state.usButtonFlags & RI_MOUSE_RIGHT_BUTTON_DOWN) - mousestate.buttons |= 2; - else if (state.usButtonFlags & RI_MOUSE_RIGHT_BUTTON_UP) - mousestate.buttons &= ~2; + if (state.usButtonFlags & RI_MOUSE_MIDDLE_BUTTON_DOWN) + b |= 4; + else if (state.usButtonFlags & RI_MOUSE_MIDDLE_BUTTON_UP) + b &= ~4; - if (state.usButtonFlags & RI_MOUSE_WHEEL) { - mousestate.dwheel += (SHORT)state.usButtonData / 120; - } + if (state.usButtonFlags & RI_MOUSE_RIGHT_BUTTON_DOWN) + b |= 2; + else if (state.usButtonFlags & RI_MOUSE_RIGHT_BUTTON_UP) + b &= ~2; + if (state.usButtonFlags & RI_MOUSE_BUTTON_4_DOWN) + b |= 8; + else if (state.usButtonFlags & RI_MOUSE_BUTTON_4_UP) + b &= ~8; + + if (state.usButtonFlags & RI_MOUSE_BUTTON_5_DOWN) + b |= 16; + else if (state.usButtonFlags & RI_MOUSE_BUTTON_5_UP) + b &= ~16; + + mouse_set_buttons_ex(b); + + if (state.usButtonFlags & RI_MOUSE_WHEEL) { + delta_z = (SHORT) state.usButtonData / 120; + mouse_set_z(delta_z); + } else + delta_z = 0; if (state.usFlags & MOUSE_MOVE_ABSOLUTE) { - /* absolute mouse, i.e. RDP or VNC - * seems to work fine for RDP on Windows 10 - * Not sure about other environments. - */ - mousestate.dx += (state.lLastX - x)/25; - mousestate.dy += (state.lLastY - y)/25; - x=state.lLastX; - y=state.lLastY; - } else { - /* relative mouse, i.e. regular mouse */ - mousestate.dx += state.lLastX; - mousestate.dy += state.lLastY; - } + /* absolute mouse, i.e. RDP or VNC + * seems to work fine for RDP on Windows 10 + * Not sure about other environments. + */ + delta_x = (state.lLastX - x) / 25; + delta_y = (state.lLastY - y) / 25; + x = state.lLastX; + y = state.lLastY; + } else { + /* relative mouse, i.e. regular mouse */ + delta_x = state.lLastX; + delta_y = state.lLastY; + } + + mouse_scale(delta_x, delta_y); } void win_mouse_close(void) { - RAWINPUTDEVICE ridev; - ridev.dwFlags = RIDEV_REMOVE; - ridev.hwndTarget = NULL; - ridev.usUsagePage = 0x01; - ridev.usUsage = 0x02; - RegisterRawInputDevices(&ridev, 1, sizeof(ridev)); -} - -void -mouse_poll(void) -{ - static int b = 0; - if (mouse_capture || video_fullscreen) { - if (mousestate.dx != 0 || mousestate.dy != 0 || mousestate.dwheel != 0) { - mouse_x += mousestate.dx; - mouse_y += mousestate.dy; - mouse_z = mousestate.dwheel; - - mousestate.dx=0; - mousestate.dy=0; - mousestate.dwheel=0; - - //pclog("dx=%d, dy=%d, dwheel=%d\n", mouse_x, mouse_y, mouse_z); - } - - if (b != mousestate.buttons) { - mouse_buttons = mousestate.buttons; - b = mousestate.buttons; - } - } + RAWINPUTDEVICE ridev; + ridev.dwFlags = RIDEV_REMOVE; + ridev.hwndTarget = NULL; + ridev.usUsagePage = 0x01; + ridev.usUsage = 0x02; + RegisterRawInputDevices(&ridev, 1, sizeof(ridev)); } diff --git a/src/win/win_new_floppy.c b/src/win/win_new_floppy.c index 0a4d0c5b6..d0a245a45 100644 --- a/src/win/win_new_floppy.c +++ b/src/win/win_new_floppy.c @@ -1,18 +1,19 @@ /* - * 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. + * 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. + * This file is part of the 86Box distribution. * - * Handle the New Floppy Image dialog. + * Handle the New Floppy Image dialog. * * * - * Authors: Miran Grca, + * Authors: Miran Grca, * - * Copyright 2016-2019 Miran Grca. + * Copyright 2016-2019 Miran Grca. + * Copyright 2021-2023 Jasmine Iwanek. */ #define UNICODE #define BITMAP WINDOWS_BITMAP @@ -26,6 +27,7 @@ #include #include #include <86box/86box.h> +#include <86box/disksizes.h> #include <86box/plat.h> #include <86box/random.h> #include <86box/ui.h> @@ -34,109 +36,71 @@ #include <86box/zip.h> #include <86box/win.h> - -typedef struct { - int hole; - int sides; - int data_rate; - int encoding; - int rpm; - int tracks; - int sectors; /* For IMG and Japanese FDI only. */ - int sector_len; /* For IMG and Japanese FDI only. */ - int media_desc; - int spc; - int num_fats; - int spfat; - int root_dir_entries; -} disk_size_t; - - -static const disk_size_t disk_sizes[14] = { -// { 1, 1, 2, 1, 1, 77, 26, 0, 0, 4, 2, 6, 68 }, /* 250k 8" */ -// { 1, 2, 2, 1, 1, 77, 26, 0, 0, 4, 2, 6, 68 }, /* 500k 8" */ -// { 1, 1, 2, 1, 1, 77, 8, 3, 0, 1, 2, 2, 192 }, /* 616k 8" */ -// { 1, 2, 0, 1, 1, 77, 8, 3, 0, 1, 2, 2, 192 }, /* 1232k 8" */ - { 0, 1, 2, 1, 0, 40, 8, 2, 0xfe, 1, 2, 1, 64 }, /* 160k */ - { 0, 1, 2, 1, 0, 40, 9, 2, 0xfc, 1, 2, 2, 64 }, /* 180k */ - { 0, 2, 2, 1, 0, 40, 8, 2, 0xff, 2, 2, 1, 112 }, /* 320k */ - { 0, 2, 2, 1, 0, 40, 9, 2, 0xfd, 2, 2, 2, 112 }, /* 360k */ - { 0, 2, 2, 1, 0, 80, 8, 2, 0xfb, 2, 2, 2, 112 }, /* 640k */ - { 0, 2, 2, 1, 0, 80, 9, 2, 0xf9, 2, 2, 3, 112 }, /* 720k */ - { 1, 2, 0, 1, 1, 80, 15, 2, 0xf9, 1, 2, 7, 224 }, /* 1.2M */ - { 1, 2, 0, 1, 1, 77, 8, 3, 0xfe, 1, 2, 2, 192 }, /* 1.25M */ - { 1, 2, 0, 1, 0, 80, 18, 2, 0xf0, 1, 2, 9, 224 }, /* 1.44M */ - { 1, 2, 0, 1, 0, 80, 21, 2, 0xf0, 2, 2, 5, 16 }, /* DMF cluster 1024 */ - { 1, 2, 0, 1, 0, 80, 21, 2, 0xf0, 4, 2, 3, 16 }, /* DMF cluster 2048 */ - { 2, 2, 3, 1, 0, 80, 36, 2, 0xf0, 2, 2, 9, 240 }, /* 2.88M */ - { 0, 64, 0, 0, 0, 96, 32, 2, 0, 0, 0, 0, 0 }, /* ZIP 100 */ - { 0, 64, 0, 0, 0, 239, 32, 2, 0, 0, 0, 0, 0 } }; /* ZIP 250 */ - -static unsigned char *empty; - +static unsigned char *empty; static int create_86f(char *file_name, disk_size_t disk_size, uint8_t rpm_mode) { - FILE *f; + FILE *fp; - uint32_t magic = 0x46423638; - uint16_t version = 0x020C; - uint16_t dflags = 0; - uint16_t tflags = 0; + uint32_t magic = 0x46423638; + uint16_t version = 0x020C; + uint16_t dflags = 0; + uint16_t tflags = 0; uint32_t index_hole_pos = 0; uint32_t tarray[512]; uint32_t array_size; - uint32_t track_base, track_size; - int i; + uint32_t track_base; + uint32_t track_size; + int i; uint32_t shift = 0; - dflags = 0; /* Has surface data? - Assume no for now. */ - dflags |= (disk_size.hole << 1); /* Hole */ - dflags |= ((disk_size.sides - 1) << 3); /* Sides. */ - dflags |= (0 << 4); /* Write protect? - Assume no for now. */ - dflags |= (rpm_mode << 5); /* RPM mode. */ - dflags |= (0 << 7); /* Has extra bit cells? - Assume no for now. */ + dflags = 0; /* Has surface data? - Assume no for now. */ + dflags |= (disk_size.hole << 1); /* Hole */ + dflags |= ((disk_size.sides - 1) << 3); /* Sides. */ + dflags |= (0 << 4); /* Write protect? - Assume no for now. */ + dflags |= (rpm_mode << 5); /* RPM mode. */ + dflags |= (0 << 7); /* Has extra bit cells? - Assume no for now. */ - tflags = disk_size.data_rate; /* Data rate. */ - tflags |= (disk_size.encoding << 3); /* Encoding. */ - tflags |= (disk_size.rpm << 5); /* RPM. */ + tflags = disk_size.data_rate; /* Data rate. */ + tflags |= (disk_size.encoding << 3); /* Encoding. */ + tflags |= (disk_size.rpm << 5); /* RPM. */ switch (disk_size.hole) { - case 0: - case 1: - default: - switch(rpm_mode) { - case 1: - array_size = 25250; - break; - case 2: - array_size = 25374; - break; - case 3: - array_size = 25750; - break; - default: - array_size = 25000; - break; - } - break; - case 2: - switch(rpm_mode) { - case 1: - array_size = 50500; - break; - case 2: - array_size = 50750; - break; - case 3: - array_size = 51000; - break; - default: - array_size = 50000; - break; - } - break; + default: + case 0: + case 1: + switch (rpm_mode) { + case 1: + array_size = 25250; + break; + case 2: + array_size = 25374; + break; + case 3: + array_size = 25750; + break; + default: + array_size = 25000; + break; + } + break; + case 2: + switch (rpm_mode) { + case 1: + array_size = 50500; + break; + case 2: + array_size = 50750; + break; + case 3: + array_size = 51000; + break; + default: + array_size = 50000; + break; + } + break; } empty = (unsigned char *) malloc(array_size); @@ -144,186 +108,182 @@ create_86f(char *file_name, disk_size_t disk_size, uint8_t rpm_mode) memset(tarray, 0, 2048); memset(empty, 0, array_size); - f = plat_fopen(file_name, "wb"); - if (!f) - return 0; + fp = plat_fopen(file_name, "wb"); + if (!fp) + return 0; - fwrite(&magic, 4, 1, f); - fwrite(&version, 2, 1, f); - fwrite(&dflags, 2, 1, f); + fwrite(&magic, 4, 1, fp); + fwrite(&version, 2, 1, fp); + fwrite(&dflags, 2, 1, fp); track_size = array_size + 6; track_base = 8 + ((disk_size.sides == 2) ? 2048 : 1024); if (disk_size.tracks <= 43) - shift = 1; + shift = 1; for (i = 0; i < (disk_size.tracks * disk_size.sides) << shift; i++) - tarray[i] = track_base + (i * track_size); + tarray[i] = track_base + (i * track_size); - fwrite(tarray, 1, (disk_size.sides == 2) ? 2048 : 1024, f); + fwrite(tarray, 1, (disk_size.sides == 2) ? 2048 : 1024, fp); for (i = 0; i < (disk_size.tracks * disk_size.sides) << shift; i++) { - fwrite(&tflags, 2, 1, f); - fwrite(&index_hole_pos, 4, 1, f); - fwrite(empty, 1, array_size, f); + fwrite(&tflags, 2, 1, fp); + fwrite(&index_hole_pos, 4, 1, fp); + fwrite(empty, 1, array_size, fp); } free(empty); - fclose(f); + fclose(fp); return 1; } - -static int is_zip; -static int is_mo; - +static int is_zip; +static int is_mo; static int create_sector_image(char *file_name, disk_size_t disk_size, uint8_t is_fdi) { - FILE *f; - uint32_t total_size = 0; - uint32_t total_sectors = 0; - uint32_t sector_bytes = 0; + FILE *fp; + uint32_t total_size = 0; + uint32_t total_sectors = 0; + uint32_t sector_bytes = 0; uint32_t root_dir_bytes = 0; - uint32_t fat_size = 0; - uint32_t fat1_offs = 0; - uint32_t fat2_offs = 0; - uint32_t zero_bytes = 0; - uint16_t base = 0x1000; - - f = plat_fopen(file_name, "wb"); - if (!f) - return 0; + uint32_t fat_size = 0; + uint32_t fat1_offs = 0; + uint32_t fat2_offs = 0; + uint32_t zero_bytes = 0; + uint16_t base = 0x1000; - sector_bytes = (128 << disk_size.sector_len); + fp = plat_fopen(file_name, "wb"); + if (!fp) + return 0; + + sector_bytes = (128 << disk_size.sector_len); total_sectors = disk_size.sides * disk_size.tracks * disk_size.sectors; if (total_sectors > ZIP_SECTORS) - total_sectors = ZIP_250_SECTORS; - total_size = total_sectors * sector_bytes; + total_sectors = ZIP_250_SECTORS; + total_size = total_sectors * sector_bytes; root_dir_bytes = (disk_size.root_dir_entries << 5); - fat_size = (disk_size.spfat * sector_bytes); - fat1_offs = sector_bytes; - fat2_offs = fat1_offs + fat_size; - zero_bytes = fat2_offs + fat_size + root_dir_bytes; + fat_size = (disk_size.spfat * sector_bytes); + fat1_offs = sector_bytes; + fat2_offs = fat1_offs + fat_size; + zero_bytes = fat2_offs + fat_size + root_dir_bytes; if (!is_zip && !is_mo && is_fdi) { - empty = (unsigned char *) malloc(base); - memset(empty, 0, base); + empty = (unsigned char *) malloc(base); + memset(empty, 0, base); - *(uint32_t *) &(empty[0x08]) = (uint32_t) base; - *(uint32_t *) &(empty[0x0C]) = total_size; - *(uint16_t *) &(empty[0x10]) = (uint16_t) sector_bytes; - *(uint8_t *) &(empty[0x14]) = (uint8_t) disk_size.sectors; - *(uint8_t *) &(empty[0x18]) = (uint8_t) disk_size.sides; - *(uint8_t *) &(empty[0x1C]) = (uint8_t) disk_size.tracks; + *(uint32_t *) &(empty[0x08]) = (uint32_t) base; + *(uint32_t *) &(empty[0x0C]) = total_size; + *(uint16_t *) &(empty[0x10]) = (uint16_t) sector_bytes; + *(uint8_t *) &(empty[0x14]) = (uint8_t) disk_size.sectors; + *(uint8_t *) &(empty[0x18]) = (uint8_t) disk_size.sides; + *(uint8_t *) &(empty[0x1C]) = (uint8_t) disk_size.tracks; - fwrite(empty, 1, base, f); - free(empty); + fwrite(empty, 1, base, fp); + free(empty); } empty = (unsigned char *) malloc(total_size); memset(empty, 0x00, zero_bytes); if (!is_zip && !is_mo) { - memset(empty + zero_bytes, 0xF6, total_size - zero_bytes); + memset(empty + zero_bytes, 0xF6, total_size - zero_bytes); - empty[0x00] = 0xEB; /* Jump to make MS-DOS happy. */ - empty[0x01] = 0x58; - empty[0x02] = 0x90; + empty[0x00] = 0xEB; /* Jump to make MS-DOS happy. */ + empty[0x01] = 0x58; + empty[0x02] = 0x90; - empty[0x03] = 0x38; /* '86BOX5.0' OEM ID. */ - empty[0x04] = 0x36; - empty[0x05] = 0x42; - empty[0x06] = 0x4F; - empty[0x07] = 0x58; - empty[0x08] = 0x35; - empty[0x09] = 0x2E; - empty[0x0A] = 0x30; + empty[0x03] = 0x38; /* '86BOX5.0' OEM ID. */ + empty[0x04] = 0x36; + empty[0x05] = 0x42; + empty[0x06] = 0x4F; + empty[0x07] = 0x58; + empty[0x08] = 0x35; + empty[0x09] = 0x2E; + empty[0x0A] = 0x30; - *(uint16_t *) &(empty[0x0B]) = (uint16_t) sector_bytes; - *(uint8_t *) &(empty[0x0D]) = (uint8_t) disk_size.spc; - *(uint16_t *) &(empty[0x0E]) = (uint16_t) 1; - *(uint8_t *) &(empty[0x10]) = (uint8_t) disk_size.num_fats; - *(uint16_t *) &(empty[0x11]) = (uint16_t) disk_size.root_dir_entries; - *(uint16_t *) &(empty[0x13]) = (uint16_t) total_sectors; - *(uint8_t *) &(empty[0x15]) = (uint8_t) disk_size.media_desc; - *(uint16_t *) &(empty[0x16]) = (uint16_t) disk_size.spfat; - *(uint8_t *) &(empty[0x18]) = (uint8_t) disk_size.sectors; - *(uint8_t *) &(empty[0x1A]) = (uint8_t) disk_size.sides; + *(uint16_t *) &(empty[0x0B]) = (uint16_t) sector_bytes; + *(uint8_t *) &(empty[0x0D]) = (uint8_t) disk_size.spc; + *(uint16_t *) &(empty[0x0E]) = (uint16_t) 1; + *(uint8_t *) &(empty[0x10]) = (uint8_t) disk_size.num_fats; + *(uint16_t *) &(empty[0x11]) = (uint16_t) disk_size.root_dir_entries; + *(uint16_t *) &(empty[0x13]) = (uint16_t) total_sectors; + *(uint8_t *) &(empty[0x15]) = (uint8_t) disk_size.media_desc; + *(uint16_t *) &(empty[0x16]) = (uint16_t) disk_size.spfat; + *(uint8_t *) &(empty[0x18]) = (uint8_t) disk_size.sectors; + *(uint8_t *) &(empty[0x1A]) = (uint8_t) disk_size.sides; - empty[0x26] = 0x29; /* ')' followed by randomly-generated volume serial number. */ - empty[0x27] = random_generate(); - empty[0x28] = random_generate(); - empty[0x29] = random_generate(); - empty[0x2A] = random_generate(); + empty[0x26] = 0x29; /* ')' followed by randomly-generated volume serial number. */ + empty[0x27] = random_generate(); + empty[0x28] = random_generate(); + empty[0x29] = random_generate(); + empty[0x2A] = random_generate(); - memset(&(empty[0x2B]), 0x20, 11); + memset(&(empty[0x2B]), 0x20, 11); - empty[0x36] = 'F'; - empty[0x37] = 'A'; - empty[0x38] = 'T'; - empty[0x39] = '1'; - empty[0x3A] = '2'; - memset(&(empty[0x3B]), 0x20, 0x0003); + empty[0x36] = 'F'; + empty[0x37] = 'A'; + empty[0x38] = 'T'; + empty[0x39] = '1'; + empty[0x3A] = '2'; + memset(&(empty[0x3B]), 0x20, 0x0003); - empty[0x1FE] = 0x55; - empty[0x1FF] = 0xAA; + empty[0x1FE] = 0x55; + empty[0x1FF] = 0xAA; - empty[fat1_offs + 0x00] = empty[fat2_offs + 0x00] = empty[0x15]; - empty[fat1_offs + 0x01] = empty[fat2_offs + 0x01] = 0xFF; - empty[fat1_offs + 0x02] = empty[fat2_offs + 0x02] = 0xFF; + empty[fat1_offs + 0x00] = empty[fat2_offs + 0x00] = empty[0x15]; + empty[fat1_offs + 0x01] = empty[fat2_offs + 0x01] = 0xFF; + empty[fat1_offs + 0x02] = empty[fat2_offs + 0x02] = 0xFF; } - fwrite(empty, 1, total_size, f); + fwrite(empty, 1, total_size, fp); free(empty); - fclose(f); + fclose(fp); return 1; } - static int create_zip_sector_image(char *file_name, disk_size_t disk_size, uint8_t is_zdi, HWND hwnd) { - HWND h; - FILE *f; - uint32_t total_size = 0; - uint32_t total_sectors = 0; - uint32_t sector_bytes = 0; + HWND h; + FILE *fp; + uint32_t total_size = 0; + uint32_t total_sectors = 0; + uint32_t sector_bytes = 0; uint32_t root_dir_bytes = 0; - uint32_t fat_size = 0; - uint32_t fat1_offs = 0; - uint32_t fat2_offs = 0; - uint32_t zero_bytes = 0; - uint16_t base = 0x1000; - uint32_t pbar_max = 0; - uint32_t i; - MSG msg; - - f = plat_fopen(file_name, "wb"); - if (!f) - return 0; + uint32_t fat_size = 0; + uint32_t fat1_offs = 0; + uint32_t fat2_offs = 0; + uint32_t zero_bytes = 0; + uint16_t base = 0x1000; + uint32_t pbar_max = 0; + MSG msg; - sector_bytes = (128 << disk_size.sector_len); + fp = plat_fopen(file_name, "wb"); + if (!fp) + return 0; + + sector_bytes = (128 << disk_size.sector_len); total_sectors = disk_size.sides * disk_size.tracks * disk_size.sectors; if (total_sectors > ZIP_SECTORS) - total_sectors = ZIP_250_SECTORS; - total_size = total_sectors * sector_bytes; + total_sectors = ZIP_250_SECTORS; + total_size = total_sectors * sector_bytes; root_dir_bytes = (disk_size.root_dir_entries << 5); - fat_size = (disk_size.spfat * sector_bytes); - fat1_offs = sector_bytes; - fat2_offs = fat1_offs + fat_size; - zero_bytes = fat2_offs + fat_size + root_dir_bytes; + fat_size = (disk_size.spfat * sector_bytes); + fat1_offs = sector_bytes; + fat2_offs = fat1_offs + fat_size; + zero_bytes = fat2_offs + fat_size + root_dir_bytes; pbar_max = total_size; if (is_zdi) - pbar_max += base; + pbar_max += base; pbar_max >>= 11; pbar_max--; @@ -346,207 +306,209 @@ create_zip_sector_image(char *file_name, disk_size_t disk_size, uint8_t is_zdi, pbar_max++; if (is_zdi) { - empty = (unsigned char *) malloc(base); - memset(empty, 0, base); + empty = (unsigned char *) malloc(base); + memset(empty, 0, base); - *(uint32_t *) &(empty[0x08]) = (uint32_t) base; - *(uint32_t *) &(empty[0x0C]) = total_size; - *(uint16_t *) &(empty[0x10]) = (uint16_t) sector_bytes; - *(uint8_t *) &(empty[0x14]) = (uint8_t) disk_size.sectors; - *(uint8_t *) &(empty[0x18]) = (uint8_t) disk_size.sides; - *(uint8_t *) &(empty[0x1C]) = (uint8_t) disk_size.tracks; + *(uint32_t *) &(empty[0x08]) = (uint32_t) base; + *(uint32_t *) &(empty[0x0C]) = total_size; + *(uint16_t *) &(empty[0x10]) = (uint16_t) sector_bytes; + *(uint8_t *) &(empty[0x14]) = (uint8_t) disk_size.sectors; + *(uint8_t *) &(empty[0x18]) = (uint8_t) disk_size.sides; + *(uint8_t *) &(empty[0x1C]) = (uint8_t) disk_size.tracks; - fwrite(empty, 1, 2048, f); - SendMessage(h, PBM_SETPOS, (WPARAM) 1, (LPARAM) 0); + fwrite(empty, 1, 2048, fp); + SendMessage(h, PBM_SETPOS, (WPARAM) 1, (LPARAM) 0); - while (PeekMessage(&msg, 0, 0, 0, PM_REMOVE | PM_NOYIELD)) { - TranslateMessage(&msg); - DispatchMessage(&msg); - } + while (PeekMessage(&msg, 0, 0, 0, PM_REMOVE | PM_NOYIELD)) { + TranslateMessage(&msg); + DispatchMessage(&msg); + } - fwrite(&empty[0x0800], 1, 2048, f); - free(empty); + fwrite(&empty[0x0800], 1, 2048, fp); + free(empty); - SendMessage(h, PBM_SETPOS, (WPARAM) 2, (LPARAM) 0); + SendMessage(h, PBM_SETPOS, (WPARAM) 2, (LPARAM) 0); - while (PeekMessage(&msg, 0, 0, 0, PM_REMOVE | PM_NOYIELD)) { - TranslateMessage(&msg); - DispatchMessage(&msg); - } + while (PeekMessage(&msg, 0, 0, 0, PM_REMOVE | PM_NOYIELD)) { + TranslateMessage(&msg); + DispatchMessage(&msg); + } - pbar_max -= 2; + pbar_max -= 2; } empty = (unsigned char *) malloc(total_size); memset(empty, 0x00, zero_bytes); if (total_sectors == ZIP_SECTORS) { - /* ZIP 100 */ - /* MBR */ - *(uint64_t *) &(empty[0x0000]) = 0x2054524150492EEBLL; - *(uint64_t *) &(empty[0x0008]) = 0x3930302065646F63LL; - *(uint64_t *) &(empty[0x0010]) = 0x67656D6F49202D20LL; - *(uint64_t *) &(empty[0x0018]) = 0x726F70726F432061LL; - *(uint64_t *) &(empty[0x0020]) = 0x202D206E6F697461LL; - *(uint64_t *) &(empty[0x0028]) = 0x30392F33322F3131LL; + /* ZIP 100 */ + /* MBR */ + *(uint64_t *) &(empty[0x0000]) = 0x2054524150492EEBLL; + *(uint64_t *) &(empty[0x0008]) = 0x3930302065646F63LL; + *(uint64_t *) &(empty[0x0010]) = 0x67656D6F49202D20LL; + *(uint64_t *) &(empty[0x0018]) = 0x726F70726F432061LL; + *(uint64_t *) &(empty[0x0020]) = 0x202D206E6F697461LL; + *(uint64_t *) &(empty[0x0028]) = 0x30392F33322F3131LL; - *(uint64_t *) &(empty[0x01AE]) = 0x0116010100E90644LL; - *(uint64_t *) &(empty[0x01B6]) = 0xED08BBE5014E0135LL; - *(uint64_t *) &(empty[0x01BE]) = 0xFFFFFE06FFFFFE80LL; - *(uint64_t *) &(empty[0x01C6]) = 0x0002FFE000000020LL; + *(uint64_t *) &(empty[0x01AE]) = 0x0116010100E90644LL; + *(uint64_t *) &(empty[0x01B6]) = 0xED08BBE5014E0135LL; + *(uint64_t *) &(empty[0x01BE]) = 0xFFFFFE06FFFFFE80LL; + *(uint64_t *) &(empty[0x01C6]) = 0x0002FFE000000020LL; - *(uint16_t *) &(empty[0x01FE]) = 0xAA55; + *(uint16_t *) &(empty[0x01FE]) = 0xAA55; - /* 31 sectors filled with 0x48 */ - memset(&(empty[0x0200]), 0x48, 0x3E00); + /* 31 sectors filled with 0x48 */ + memset(&(empty[0x0200]), 0x48, 0x3E00); - /* Boot sector */ - *(uint64_t *) &(empty[0x4000]) = 0x584F4236389058EBLL; - *(uint64_t *) &(empty[0x4008]) = 0x0008040200302E35LL; - *(uint64_t *) &(empty[0x4010]) = 0x00C0F80000020002LL; - *(uint64_t *) &(empty[0x4018]) = 0x0000002000FF003FLL; - *(uint32_t *) &(empty[0x4020]) = 0x0002FFE0; - *(uint16_t *) &(empty[0x4024]) = 0x0080; + /* Boot sector */ + *(uint64_t *) &(empty[0x4000]) = 0x584F4236389058EBLL; + *(uint64_t *) &(empty[0x4008]) = 0x0008040200302E35LL; + *(uint64_t *) &(empty[0x4010]) = 0x00C0F80000020002LL; + *(uint64_t *) &(empty[0x4018]) = 0x0000002000FF003FLL; + *(uint32_t *) &(empty[0x4020]) = 0x0002FFE0; + *(uint16_t *) &(empty[0x4024]) = 0x0080; - empty[0x4026] = 0x29; /* ')' followed by randomly-generated volume serial number. */ - empty[0x4027] = random_generate(); - empty[0x4028] = random_generate(); - empty[0x4029] = random_generate(); - empty[0x402A] = random_generate(); + empty[0x4026] = 0x29; /* ')' followed by randomly-generated volume serial number. */ + empty[0x4027] = random_generate(); + empty[0x4028] = random_generate(); + empty[0x4029] = random_generate(); + empty[0x402A] = random_generate(); - memset(&(empty[0x402B]), 0x00, 0x000B); - memset(&(empty[0x4036]), 0x20, 0x0008); + memset(&(empty[0x402B]), 0x00, 0x000B); + memset(&(empty[0x4036]), 0x20, 0x0008); - empty[0x4036] = 'F'; - empty[0x4037] = 'A'; - empty[0x4038] = 'T'; - empty[0x4039] = '1'; - empty[0x403A] = '6'; - memset(&(empty[0x403B]), 0x20, 0x0003); + empty[0x4036] = 'F'; + empty[0x4037] = 'A'; + empty[0x4038] = 'T'; + empty[0x4039] = '1'; + empty[0x403A] = '6'; + memset(&(empty[0x403B]), 0x20, 0x0003); - empty[0x41FE] = 0x55; - empty[0x41FF] = 0xAA; + empty[0x41FE] = 0x55; + empty[0x41FF] = 0xAA; - empty[0x5000] = empty[0x1D000] = empty[0x4015]; - empty[0x5001] = empty[0x1D001] = 0xFF; - empty[0x5002] = empty[0x1D002] = 0xFF; - empty[0x5003] = empty[0x1D003] = 0xFF; + empty[0x5000] = empty[0x1D000] = empty[0x4015]; + empty[0x5001] = empty[0x1D001] = 0xFF; + empty[0x5002] = empty[0x1D002] = 0xFF; + empty[0x5003] = empty[0x1D003] = 0xFF; - /* Root directory = 0x35000 - Data = 0x39000 */ + /* Root directory = 0x35000 + Data = 0x39000 */ } else { - /* ZIP 250 */ - /* MBR */ - *(uint64_t *) &(empty[0x0000]) = 0x2054524150492EEBLL; - *(uint64_t *) &(empty[0x0008]) = 0x3930302065646F63LL; - *(uint64_t *) &(empty[0x0010]) = 0x67656D6F49202D20LL; - *(uint64_t *) &(empty[0x0018]) = 0x726F70726F432061LL; - *(uint64_t *) &(empty[0x0020]) = 0x202D206E6F697461LL; - *(uint64_t *) &(empty[0x0028]) = 0x30392F33322F3131LL; + /* ZIP 250 */ + /* MBR */ + *(uint64_t *) &(empty[0x0000]) = 0x2054524150492EEBLL; + *(uint64_t *) &(empty[0x0008]) = 0x3930302065646F63LL; + *(uint64_t *) &(empty[0x0010]) = 0x67656D6F49202D20LL; + *(uint64_t *) &(empty[0x0018]) = 0x726F70726F432061LL; + *(uint64_t *) &(empty[0x0020]) = 0x202D206E6F697461LL; + *(uint64_t *) &(empty[0x0028]) = 0x30392F33322F3131LL; - *(uint64_t *) &(empty[0x01AE]) = 0x0116010100E900E9LL; - *(uint64_t *) &(empty[0x01B6]) = 0x2E32A7AC014E0135LL; + *(uint64_t *) &(empty[0x01AE]) = 0x0116010100E900E9LL; + *(uint64_t *) &(empty[0x01B6]) = 0x2E32A7AC014E0135LL; - *(uint64_t *) &(empty[0x01EE]) = 0xEE203F0600010180LL; - *(uint64_t *) &(empty[0x01F6]) = 0x000777E000000020LL; - *(uint16_t *) &(empty[0x01FE]) = 0xAA55; + *(uint64_t *) &(empty[0x01EE]) = 0xEE203F0600010180LL; + *(uint64_t *) &(empty[0x01F6]) = 0x000777E000000020LL; + *(uint16_t *) &(empty[0x01FE]) = 0xAA55; - /* 31 sectors filled with 0x48 */ - memset(&(empty[0x0200]), 0x48, 0x3E00); + /* 31 sectors filled with 0x48 */ + memset(&(empty[0x0200]), 0x48, 0x3E00); - /* The second sector begins with some strange data - in my reference image. */ - *(uint64_t *) &(empty[0x0200]) = 0x3831393230334409LL; - *(uint64_t *) &(empty[0x0208]) = 0x6A57766964483130LL; - *(uint64_t *) &(empty[0x0210]) = 0x3C3A34676063653FLL; - *(uint64_t *) &(empty[0x0218]) = 0x586A56A8502C4161LL; - *(uint64_t *) &(empty[0x0220]) = 0x6F2D702535673D6CLL; - *(uint64_t *) &(empty[0x0228]) = 0x255421B8602D3456LL; - *(uint64_t *) &(empty[0x0230]) = 0x577B22447B52603ELL; - *(uint64_t *) &(empty[0x0238]) = 0x46412CC871396170LL; - *(uint64_t *) &(empty[0x0240]) = 0x704F55237C5E2626LL; - *(uint64_t *) &(empty[0x0248]) = 0x6C7932C87D5C3C20LL; - *(uint64_t *) &(empty[0x0250]) = 0x2C50503E47543D6ELL; - *(uint64_t *) &(empty[0x0258]) = 0x46394E807721536ALL; - *(uint64_t *) &(empty[0x0260]) = 0x505823223F245325LL; - *(uint64_t *) &(empty[0x0268]) = 0x365C79B0393B5B6ELL; + /* The second sector begins with some strange data + in my reference image. */ + *(uint64_t *) &(empty[0x0200]) = 0x3831393230334409LL; + *(uint64_t *) &(empty[0x0208]) = 0x6A57766964483130LL; + *(uint64_t *) &(empty[0x0210]) = 0x3C3A34676063653FLL; + *(uint64_t *) &(empty[0x0218]) = 0x586A56A8502C4161LL; + *(uint64_t *) &(empty[0x0220]) = 0x6F2D702535673D6CLL; + *(uint64_t *) &(empty[0x0228]) = 0x255421B8602D3456LL; + *(uint64_t *) &(empty[0x0230]) = 0x577B22447B52603ELL; + *(uint64_t *) &(empty[0x0238]) = 0x46412CC871396170LL; + *(uint64_t *) &(empty[0x0240]) = 0x704F55237C5E2626LL; + *(uint64_t *) &(empty[0x0248]) = 0x6C7932C87D5C3C20LL; + *(uint64_t *) &(empty[0x0250]) = 0x2C50503E47543D6ELL; + *(uint64_t *) &(empty[0x0258]) = 0x46394E807721536ALL; + *(uint64_t *) &(empty[0x0260]) = 0x505823223F245325LL; + *(uint64_t *) &(empty[0x0268]) = 0x365C79B0393B5B6ELL; - /* Boot sector */ - *(uint64_t *) &(empty[0x4000]) = 0x584F4236389058EBLL; - *(uint64_t *) &(empty[0x4008]) = 0x0001080200302E35LL; - *(uint64_t *) &(empty[0x4010]) = 0x00EFF80000020002LL; - *(uint64_t *) &(empty[0x4018]) = 0x0000002000400020LL; - *(uint32_t *) &(empty[0x4020]) = 0x000777E0; - *(uint16_t *) &(empty[0x4024]) = 0x0080; + /* Boot sector */ + *(uint64_t *) &(empty[0x4000]) = 0x584F4236389058EBLL; + *(uint64_t *) &(empty[0x4008]) = 0x0001080200302E35LL; + *(uint64_t *) &(empty[0x4010]) = 0x00EFF80000020002LL; + *(uint64_t *) &(empty[0x4018]) = 0x0000002000400020LL; + *(uint32_t *) &(empty[0x4020]) = 0x000777E0; + *(uint16_t *) &(empty[0x4024]) = 0x0080; - empty[0x4026] = 0x29; /* ')' followed by randomly-generated volume serial number. */ - empty[0x4027] = random_generate(); - empty[0x4028] = random_generate(); - empty[0x4029] = random_generate(); - empty[0x402A] = random_generate(); + empty[0x4026] = 0x29; /* ')' followed by randomly-generated volume serial number. */ + empty[0x4027] = random_generate(); + empty[0x4028] = random_generate(); + empty[0x4029] = random_generate(); + empty[0x402A] = random_generate(); - memset(&(empty[0x402B]), 0x00, 0x000B); - memset(&(empty[0x4036]), 0x20, 0x0008); + memset(&(empty[0x402B]), 0x00, 0x000B); + memset(&(empty[0x4036]), 0x20, 0x0008); - empty[0x4036] = 'F'; - empty[0x4037] = 'A'; - empty[0x4038] = 'T'; - empty[0x4039] = '1'; - empty[0x403A] = '6'; - memset(&(empty[0x403B]), 0x20, 0x0003); + empty[0x4036] = 'F'; + empty[0x4037] = 'A'; + empty[0x4038] = 'T'; + empty[0x4039] = '1'; + empty[0x403A] = '6'; + memset(&(empty[0x403B]), 0x20, 0x0003); - empty[0x41FE] = 0x55; - empty[0x41FF] = 0xAA; + empty[0x41FE] = 0x55; + empty[0x41FF] = 0xAA; - empty[0x4200] = empty[0x22000] = empty[0x4015]; - empty[0x4201] = empty[0x22001] = 0xFF; - empty[0x4202] = empty[0x22002] = 0xFF; - empty[0x4203] = empty[0x22003] = 0xFF; + empty[0x4200] = empty[0x22000] = empty[0x4015]; + empty[0x4201] = empty[0x22001] = 0xFF; + empty[0x4202] = empty[0x22002] = 0xFF; + empty[0x4203] = empty[0x22003] = 0xFF; - /* Root directory = 0x3FE00 - Data = 0x38200 */ + /* Root directory = 0x3FE00 + Data = 0x38200 */ } - for (i = 0; i < pbar_max; i++) { - fwrite(&empty[i << 11], 1, 2048, f); - SendMessage(h, PBM_SETPOS, (WPARAM) i + 2, (LPARAM) 0); + for (uint32_t i = 0; i < pbar_max; i++) { + fwrite(&empty[i << 11], 1, 2048, fp); + SendMessage(h, PBM_SETPOS, (WPARAM) i + 2, (LPARAM) 0); - while (PeekMessage(&msg, 0, 0, 0, PM_REMOVE | PM_NOYIELD)) { - TranslateMessage(&msg); - DispatchMessage(&msg); - } + while (PeekMessage(&msg, 0, 0, 0, PM_REMOVE | PM_NOYIELD)) { + TranslateMessage(&msg); + DispatchMessage(&msg); + } } free(empty); - fclose(f); + fclose(fp); return 1; } - static int create_mo_sector_image(char *file_name, int8_t disk_size, uint8_t is_mdi, HWND hwnd) { - HWND h; - FILE *f; + HWND h; + FILE *fp; const mo_type_t *dp = &mo_types[disk_size]; - uint8_t *empty, *empty2 = NULL; - uint32_t total_size = 0, total_size2; - uint32_t total_sectors = 0; - uint32_t sector_bytes = 0; - uint16_t base = 0x1000; - uint32_t pbar_max = 0, blocks_num; - uint32_t i, j; - MSG msg; - - f = plat_fopen(file_name, "wb"); - if (!f) - return 0; + uint8_t *empty; + uint8_t *empty2 = NULL; + uint32_t total_size = 0; + uint32_t total_size2; + uint32_t total_sectors = 0; + uint32_t sector_bytes = 0; + uint16_t base = 0x1000; + uint32_t pbar_max = 0; + uint32_t blocks_num; + uint32_t j; + MSG msg; - sector_bytes = dp->bytes_per_sector; + fp = plat_fopen(file_name, "wb"); + if (!fp) + return 0; + + sector_bytes = dp->bytes_per_sector; total_sectors = dp->sectors; - total_size = total_sectors * sector_bytes; + total_size = total_sectors * sector_bytes; total_size2 = (total_size >> 20) << 20; total_size2 = total_size - total_size2; @@ -555,9 +517,9 @@ create_mo_sector_image(char *file_name, int8_t disk_size, uint8_t is_mdi, HWND h pbar_max >>= 20; blocks_num = pbar_max; if (is_mdi) - pbar_max++; + pbar_max++; if (total_size2 == 0) - pbar_max++; + pbar_max++; j = is_mdi ? 1 : 0; @@ -579,302 +541,302 @@ create_mo_sector_image(char *file_name, int8_t disk_size, uint8_t is_mdi, HWND h h = GetDlgItem(hwnd, IDC_PBAR_IMG_CREATE); if (is_mdi) { - empty = (unsigned char *) malloc(base); - memset(empty, 0, base); + empty = (unsigned char *) malloc(base); + memset(empty, 0, base); - *(uint32_t *) &(empty[0x08]) = (uint32_t) base; - *(uint32_t *) &(empty[0x0C]) = total_size; - *(uint16_t *) &(empty[0x10]) = (uint16_t) sector_bytes; - *(uint8_t *) &(empty[0x14]) = (uint8_t) 25; - *(uint8_t *) &(empty[0x18]) = (uint8_t) 64; - *(uint8_t *) &(empty[0x1C]) = (uint8_t) (dp->sectors / 64) / 25; + *(uint32_t *) &(empty[0x08]) = (uint32_t) base; + *(uint32_t *) &(empty[0x0C]) = total_size; + *(uint16_t *) &(empty[0x10]) = (uint16_t) sector_bytes; + *(uint8_t *) &(empty[0x14]) = (uint8_t) 25; + *(uint8_t *) &(empty[0x18]) = (uint8_t) 64; + *(uint8_t *) &(empty[0x1C]) = (uint8_t) (dp->sectors / 64) / 25; - fwrite(empty, 1, 2048, f); - SendMessage(h, PBM_SETPOS, (WPARAM) 1, (LPARAM) 0); + fwrite(empty, 1, 2048, fp); + SendMessage(h, PBM_SETPOS, (WPARAM) 1, (LPARAM) 0); - while (PeekMessage(&msg, 0, 0, 0, PM_REMOVE | PM_NOYIELD)) { - TranslateMessage(&msg); - DispatchMessage(&msg); - } + while (PeekMessage(&msg, 0, 0, 0, PM_REMOVE | PM_NOYIELD)) { + TranslateMessage(&msg); + DispatchMessage(&msg); + } - fwrite(&empty[0x0800], 1, 2048, f); - free(empty); + fwrite(&empty[0x0800], 1, 2048, fp); + free(empty); - SendMessage(h, PBM_SETPOS, (WPARAM) 1, (LPARAM) 0); + SendMessage(h, PBM_SETPOS, (WPARAM) 1, (LPARAM) 0); - while (PeekMessage(&msg, 0, 0, 0, PM_REMOVE | PM_NOYIELD)) { - TranslateMessage(&msg); - DispatchMessage(&msg); - } + while (PeekMessage(&msg, 0, 0, 0, PM_REMOVE | PM_NOYIELD)) { + TranslateMessage(&msg); + DispatchMessage(&msg); + } } empty = (unsigned char *) malloc(1048576); memset(empty, 0x00, 1048576); if (total_size2 > 0) { - empty2 = (unsigned char *) malloc(total_size2); - memset(empty, 0x00, total_size2); + empty2 = (unsigned char *) malloc(total_size2); + memset(empty, 0x00, total_size2); } - for (i = 0; i < blocks_num; i++) { - fwrite(empty, 1, 1048576, f); + for (uint32_t i = 0; i < blocks_num; i++) { + fwrite(empty, 1, 1048576, fp); - SendMessage(h, PBM_SETPOS, (WPARAM) i + j, (LPARAM) 0); + SendMessage(h, PBM_SETPOS, (WPARAM) i + j, (LPARAM) 0); - while (PeekMessage(&msg, 0, 0, 0, PM_REMOVE | PM_NOYIELD)) { - TranslateMessage(&msg); - DispatchMessage(&msg); - } + while (PeekMessage(&msg, 0, 0, 0, PM_REMOVE | PM_NOYIELD)) { + TranslateMessage(&msg); + DispatchMessage(&msg); + } } if (total_size2 > 0) { - fwrite(empty2, 1, total_size2, f); + fwrite(empty2, 1, total_size2, fp); - SendMessage(h, PBM_SETPOS, (WPARAM) pbar_max - 1, (LPARAM) 0); + SendMessage(h, PBM_SETPOS, (WPARAM) pbar_max - 1, (LPARAM) 0); - while (PeekMessage(&msg, 0, 0, 0, PM_REMOVE | PM_NOYIELD)) { - TranslateMessage(&msg); - DispatchMessage(&msg); - } + while (PeekMessage(&msg, 0, 0, 0, PM_REMOVE | PM_NOYIELD)) { + TranslateMessage(&msg); + DispatchMessage(&msg); + } } if (empty2 != NULL) - free(empty2); + free(empty2); free(empty); - fclose(f); + fclose(fp); return 1; } +static int fdd_id; +static int sb_part; -static int fdd_id, sb_part; - -static int file_type = 0; /* 0 = IMG, 1 = Japanese FDI, 2 = 86F */ -static char fd_file_name[1024]; - +static int file_type = 0; /* 0 = IMG, 1 = Japanese FDI, 2 = 86F */ +static char fd_file_name[1024]; /* Show a MessageBox dialog. This is nasty, I know. --FvK */ static int new_floppy_msgbox_header(HWND hwnd, int flags, void *header, void *message) { HWND h; - int i; + int i; - h = hwndMain; + h = hwndMain; hwndMain = hwnd; i = ui_msgbox_header(flags, header, message); hwndMain = h; - return(i); + return i; } - static int new_floppy_msgbox_ex(HWND hwnd, int flags, void *header, void *message, void *btn1, void *btn2, void *btn3) { HWND h; - int i; + int i; - h = hwndMain; + h = hwndMain; hwndMain = hwnd; i = ui_msgbox_ex(flags, header, message, btn1, btn2, btn3); hwndMain = h; - return(i); + return i; } - #if defined(__amd64__) || defined(__aarch64__) static LRESULT CALLBACK #else static BOOL CALLBACK #endif -NewFloppyDialogProcedure(HWND hdlg, UINT message, WPARAM wParam, LPARAM lParam) +NewFloppyDialogProcedure(HWND hdlg, UINT message, WPARAM wParam, UNUSED(LPARAM lParam)) { - HWND h; - int i = 0; - int wcs_len, ext_offs; - wchar_t *ext; - uint8_t disk_size, rpm_mode; - int ret; - FILE *f; - int zip_types, mo_types, floppy_types; - wchar_t *twcs; + HWND h; + int i = 0; + int wcs_len; + int ext_offs; + const wchar_t *ext; + uint8_t disk_size; + uint8_t rpm_mode; + int ret; + FILE *fp; + int zip_types; + int mo_types; + int floppy_types; + wchar_t *twcs; switch (message) { - case WM_INITDIALOG: - plat_pause(1); - memset(fd_file_name, 0, 1024); - h = GetDlgItem(hdlg, IDC_COMBO_DISK_SIZE); - if (is_zip) { - zip_types = zip_drives[fdd_id].is_250 ? 2 : 1; - for (i = 0; i < zip_types; i++) - SendMessage(h, CB_ADDSTRING, 0, win_get_string(IDS_5900 + i)); - } else if (is_mo) { - mo_types = 10; - /* TODO: Proper string ID's. */ - for (i = 0; i < mo_types; i++) - SendMessage(h, CB_ADDSTRING, 0, win_get_string(IDS_5902 + i)); - } else { - floppy_types = 12; - for (i = 0; i < floppy_types; i++) - SendMessage(h, CB_ADDSTRING, 0, win_get_string(IDS_5888 + i)); - } - SendMessage(h, CB_SETCURSEL, 0, 0); - EnableWindow(h, FALSE); - h = GetDlgItem(hdlg, IDC_COMBO_RPM_MODE); - for (i = 0; i < 4; i++) - SendMessage(h, CB_ADDSTRING, 0, win_get_string(IDS_6144 + i)); - SendMessage(h, CB_SETCURSEL, 0, 0); - EnableWindow(h, FALSE); - ShowWindow(h, SW_HIDE); - h = GetDlgItem(hdlg, IDT_FLP_RPM_MODE); - EnableWindow(h, FALSE); - ShowWindow(h, SW_HIDE); - h = GetDlgItem(hdlg, IDOK); - EnableWindow(h, FALSE); - h = GetDlgItem(hdlg, IDC_PBAR_IMG_CREATE); - EnableWindow(h, FALSE); - ShowWindow(h, SW_HIDE); - h = GetDlgItem(hdlg, IDT_FLP_PROGRESS); - EnableWindow(h, FALSE); - ShowWindow(h, SW_HIDE); - break; + case WM_INITDIALOG: + plat_pause(1); + memset(fd_file_name, 0, 1024); + h = GetDlgItem(hdlg, IDC_COMBO_DISK_SIZE); + if (is_zip) { + zip_types = zip_drives[fdd_id].is_250 ? 2 : 1; + for (i = 0; i < zip_types; i++) + SendMessage(h, CB_ADDSTRING, 0, win_get_string(IDS_5900 + i)); + } else if (is_mo) { + mo_types = 10; + /* TODO: Proper string ID's. */ + for (i = 0; i < mo_types; i++) + SendMessage(h, CB_ADDSTRING, 0, win_get_string(IDS_5902 + i)); + } else { + floppy_types = 12; + for (i = 0; i < floppy_types; i++) + SendMessage(h, CB_ADDSTRING, 0, win_get_string(IDS_5888 + i)); + } + SendMessage(h, CB_SETCURSEL, 0, 0); + EnableWindow(h, FALSE); + h = GetDlgItem(hdlg, IDC_COMBO_RPM_MODE); + for (i = 0; i < 4; i++) + SendMessage(h, CB_ADDSTRING, 0, win_get_string(IDS_6144 + i)); + SendMessage(h, CB_SETCURSEL, 0, 0); + EnableWindow(h, FALSE); + ShowWindow(h, SW_HIDE); + h = GetDlgItem(hdlg, IDT_FLP_RPM_MODE); + EnableWindow(h, FALSE); + ShowWindow(h, SW_HIDE); + h = GetDlgItem(hdlg, IDOK); + EnableWindow(h, FALSE); + h = GetDlgItem(hdlg, IDC_PBAR_IMG_CREATE); + EnableWindow(h, FALSE); + ShowWindow(h, SW_HIDE); + h = GetDlgItem(hdlg, IDT_FLP_PROGRESS); + EnableWindow(h, FALSE); + ShowWindow(h, SW_HIDE); + break; - case WM_COMMAND: - switch (LOWORD(wParam)) { - case IDOK: - h = GetDlgItem(hdlg, IDC_COMBO_DISK_SIZE); - disk_size = SendMessage(h, CB_GETCURSEL, 0, 0); - if (is_zip) - disk_size += 12; - if (!is_zip && !is_mo && (file_type == 2)) { - h = GetDlgItem(hdlg, IDC_COMBO_RPM_MODE); - rpm_mode = SendMessage(h, CB_GETCURSEL, 0, 0); - ret = create_86f(fd_file_name, disk_sizes[disk_size], rpm_mode); - } else { - if (is_zip) - ret = create_zip_sector_image(fd_file_name, disk_sizes[disk_size], file_type, hdlg); - if (is_mo) - ret = create_mo_sector_image(fd_file_name, disk_size, file_type, hdlg); - else - ret = create_sector_image(fd_file_name, disk_sizes[disk_size], file_type); - } - if (ret) { - if (is_zip) - zip_mount(fdd_id, fd_file_name, 0); - else if (is_mo) - mo_mount(fdd_id, fd_file_name, 0); - else - floppy_mount(fdd_id, fd_file_name, 0); - } else { - new_floppy_msgbox_header(hdlg, MBX_ERROR, (wchar_t *) IDS_4108, (wchar_t *) IDS_4115); - return TRUE; - } - /*FALLTHROUGH*/ - case IDCANCEL: - EndDialog(hdlg, 0); - plat_pause(0); - return TRUE; + case WM_COMMAND: + switch (LOWORD(wParam)) { + case IDOK: + h = GetDlgItem(hdlg, IDC_COMBO_DISK_SIZE); + disk_size = SendMessage(h, CB_GETCURSEL, 0, 0); + if (is_zip) + disk_size += 12; + if (!is_zip && !is_mo && (file_type == 2)) { + h = GetDlgItem(hdlg, IDC_COMBO_RPM_MODE); + rpm_mode = SendMessage(h, CB_GETCURSEL, 0, 0); + ret = create_86f(fd_file_name, disk_sizes[disk_size], rpm_mode); + } else { + if (is_zip) + ret = create_zip_sector_image(fd_file_name, disk_sizes[disk_size], file_type, hdlg); + if (is_mo) + ret = create_mo_sector_image(fd_file_name, disk_size, file_type, hdlg); + else + ret = create_sector_image(fd_file_name, disk_sizes[disk_size], file_type); + } + if (ret) { + if (is_zip) + zip_mount(fdd_id, fd_file_name, 0); + else if (is_mo) + mo_mount(fdd_id, fd_file_name, 0); + else + floppy_mount(fdd_id, fd_file_name, 0); + } else { + new_floppy_msgbox_header(hdlg, MBX_ERROR, (wchar_t *) IDS_4108, (wchar_t *) IDS_4115); + return TRUE; + } + fallthrough; + case IDCANCEL: + EndDialog(hdlg, 0); + plat_pause(0); + return TRUE; - case IDC_CFILE: - if (!file_dlg_w(hdlg, plat_get_string(is_mo ? IDS_2139 : (is_zip ? IDS_2055 : IDS_2062)), L"", NULL, 1)) { - if (!wcschr(wopenfilestring, L'.')) { - if (wcslen(wopenfilestring) && (wcslen(wopenfilestring) <= 256)) { - twcs = &wopenfilestring[wcslen(wopenfilestring)]; - twcs[0] = L'.'; - if (!is_zip && !is_mo && (filterindex == 3)) { - twcs[1] = L'8'; - twcs[2] = L'6'; - twcs[3] = L'f'; - } else { - twcs[1] = L'i'; - twcs[2] = L'm'; - twcs[3] = L'g'; - } - } - } - h = GetDlgItem(hdlg, IDC_EDIT_FILE_NAME); - f = _wfopen(wopenfilestring, L"rb"); - if (f != NULL) { - fclose(f); - if (new_floppy_msgbox_ex(hdlg, MBX_QUESTION, (wchar_t *) IDS_4111, (wchar_t *) IDS_4118, (wchar_t *) IDS_4120, (wchar_t *) IDS_4121, NULL) != 0) /* yes */ - return FALSE; - } - SendMessage(h, WM_SETTEXT, 0, (LPARAM) wopenfilestring); - memset(fd_file_name, 0, sizeof(fd_file_name)); - c16stombs(fd_file_name, wopenfilestring, sizeof(fd_file_name)); - h = GetDlgItem(hdlg, IDC_COMBO_DISK_SIZE); - if (!is_zip || zip_drives[fdd_id].is_250) - EnableWindow(h, TRUE); - wcs_len = wcslen(wopenfilestring); - ext_offs = wcs_len - 4; - ext = &(wopenfilestring[ext_offs]); - if (is_zip) { - if (((wcs_len >= 4) && !wcsicmp(ext, L".ZDI"))) - file_type = 1; - else - file_type = 0; - } else if (is_mo) { - if (((wcs_len >= 4) && !wcsicmp(ext, L".MDI"))) - file_type = 1; - else - file_type = 0; - } else { - if (((wcs_len >= 4) && !wcsicmp(ext, L".FDI"))) - file_type = 1; - else if ((((wcs_len >= 4) && !wcsicmp(ext, L".86F")) || (filterindex == 3))) - file_type = 2; - else - file_type = 0; - } - h = GetDlgItem(hdlg, IDT_FLP_RPM_MODE); - if (file_type == 2) { - EnableWindow(h, TRUE); - ShowWindow(h, SW_SHOW); - } else { - EnableWindow(h, FALSE); - ShowWindow(h, SW_HIDE); - } - h = GetDlgItem(hdlg, IDC_COMBO_RPM_MODE); - if (file_type == 2) { - EnableWindow(h, TRUE); - ShowWindow(h, SW_SHOW); - } else { - EnableWindow(h, FALSE); - ShowWindow(h, SW_HIDE); - } - h = GetDlgItem(hdlg, IDOK); - EnableWindow(h, TRUE); - return TRUE; - } else - return FALSE; + case IDC_CFILE: + if (!file_dlg_w(hdlg, plat_get_string(is_mo ? IDS_2140 : (is_zip ? IDS_2055 : IDS_2062)), L"", NULL, 1)) { + if (!wcschr(wopenfilestring, L'.')) { + if (wcslen(wopenfilestring) && (wcslen(wopenfilestring) <= 256)) { + twcs = &wopenfilestring[wcslen(wopenfilestring)]; + twcs[0] = L'.'; + if (!is_zip && !is_mo && (filterindex == 3)) { + twcs[1] = L'8'; + twcs[2] = L'6'; + twcs[3] = L'f'; + } else { + twcs[1] = L'i'; + twcs[2] = L'm'; + twcs[3] = L'g'; + } + } + } + h = GetDlgItem(hdlg, IDC_EDIT_FILE_NAME); + fp = _wfopen(wopenfilestring, L"rb"); + if (fp != NULL) { + fclose(fp); + if (new_floppy_msgbox_ex(hdlg, MBX_QUESTION, (wchar_t *) IDS_4111, (wchar_t *) IDS_4118, (wchar_t *) IDS_4120, (wchar_t *) IDS_4121, NULL) != 0) /* yes */ + return FALSE; + } + SendMessage(h, WM_SETTEXT, 0, (LPARAM) wopenfilestring); + memset(fd_file_name, 0, sizeof(fd_file_name)); + c16stombs(fd_file_name, wopenfilestring, sizeof(fd_file_name)); + h = GetDlgItem(hdlg, IDC_COMBO_DISK_SIZE); + if (!is_zip || zip_drives[fdd_id].is_250) + EnableWindow(h, TRUE); + wcs_len = wcslen(wopenfilestring); + ext_offs = wcs_len - 4; + ext = &(wopenfilestring[ext_offs]); + if (is_zip) { + if ((wcs_len >= 4) && !wcsicmp(ext, L".ZDI")) + file_type = 1; + else + file_type = 0; + } else if (is_mo) { + if ((wcs_len >= 4) && !wcsicmp(ext, L".MDI")) + file_type = 1; + else + file_type = 0; + } else { + if ((wcs_len >= 4) && !wcsicmp(ext, L".FDI")) + file_type = 1; + else if (((wcs_len >= 4) && !wcsicmp(ext, L".86F")) || (filterindex == 3)) + file_type = 2; + else + file_type = 0; + } + h = GetDlgItem(hdlg, IDT_FLP_RPM_MODE); + if (file_type == 2) { + EnableWindow(h, TRUE); + ShowWindow(h, SW_SHOW); + } else { + EnableWindow(h, FALSE); + ShowWindow(h, SW_HIDE); + } + h = GetDlgItem(hdlg, IDC_COMBO_RPM_MODE); + if (file_type == 2) { + EnableWindow(h, TRUE); + ShowWindow(h, SW_SHOW); + } else { + EnableWindow(h, FALSE); + ShowWindow(h, SW_HIDE); + } + h = GetDlgItem(hdlg, IDOK); + EnableWindow(h, TRUE); + return TRUE; + } else + return FALSE; - default: - break; - } - break; + default: + break; + } + break; } - return(FALSE); + return FALSE; } - void NewFloppyDialogCreate(HWND hwnd, int id, int part) { - fdd_id = id & 0x7f; + fdd_id = id & 0x7f; sb_part = part; - is_zip = !!(id & 0x80); - is_mo = !!(id & 0x100); + is_zip = !!(id & 0x80); + is_mo = !!(id & 0x100); if (is_zip && is_mo) { - fatal("Attempting to create a new image dialog that is for both ZIP and MO at the same time\n"); - return; + fatal("Attempting to create a new image dialog that is for both ZIP and MO at the same time\n"); + return; } - DialogBox(hinstance, (LPCTSTR)DLG_NEW_FLOPPY, hwnd, NewFloppyDialogProcedure); + DialogBox(hinstance, (LPCTSTR) DLG_NEW_FLOPPY, hwnd, NewFloppyDialogProcedure); } diff --git a/src/win/win_opendir.c b/src/win/win_opendir.c index 5339f0713..051ed20bb 100644 --- a/src/win/win_opendir.c +++ b/src/win/win_opendir.c @@ -1,21 +1,22 @@ /* - * 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. + * 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. + * This file is part of the 86Box distribution. * - * Implementation POSIX OpenDir(3) and friends for Win32 API. + * Implementation POSIX OpenDir(3) and friends for Win32 API. * - * Based on old original code @(#)dir_win32.c 1.2.0 2007/04/19 + * Based on old original code @(#)dir_win32.c 1.2.0 2007/04/19 * * * - * Author: Fred N. van Kempen, + * Authors: Fred N. van Kempen, * - * Copyright 1998-2007 MicroWalt Corporation - * Copyright 2017 Fred N. van Kempen + * Copyright 1998-2007 MicroWalt Corporation + * Copyright 2017 Fred N. van Kempen + * Copyright 2021-2023 Jasmine Iwanek. */ #include #include @@ -27,94 +28,70 @@ #include <86box/plat.h> #include <86box/plat_dir.h> - -#ifdef UNICODE -# define SUFFIX L"\\*" -# define FINDATA struct _wfinddata_t -# define FINDFIRST _wfindfirst -# define FINDNEXT _wfindnext -#else -# define SUFFIX "\\*" -# define FINDATA struct _finddata_t -# define FINDFIRST _findfirst -# define FINDNEXT _findnext -#endif - +#define SUFFIX "\\*" +#define FINDATA struct _finddata_t +#define FINDFIRST _findfirst +#define FINDNEXT _findnext /* Open a directory. */ DIR * -#ifdef UNICODE -opendirw(const wchar_t *name) -#else opendir(const char *name) -#endif { DIR *p; /* Create a new control structure. */ p = (DIR *) malloc(sizeof(DIR)); if (p == NULL) - return(NULL); + return (NULL); memset(p, 0x00, sizeof(DIR)); - p->flags = (DIR_F_LOWER | DIR_F_SANE); + p->flags = (DIR_F_LOWER | DIR_F_SANE); p->offset = 0; - p->sts = 0; + p->sts = 0; /* Create a work area. */ - p->dta = (char *)malloc(sizeof(FINDATA)); + p->dta = (char *) malloc(sizeof(FINDATA)); if (p->dta == NULL) { - free(p); - return(NULL); + free(p); + return (NULL); } memset(p->dta, 0x00, sizeof(struct _finddata_t)); /* Add search filespec. */ -#ifdef UNICODE - wcscpy(p->dir, name); - wcscat(p->dir, SUFFIX); -#else strcpy(p->dir, name); strcat(p->dir, SUFFIX); -#endif /* Special case: flag if we are in the root directory. */ -#ifdef UNICODE - if (wcslen(p->dir) == 3) -#else if (strlen(p->dir) == 3) -#endif - p->flags |= DIR_F_ISROOT; + p->flags |= DIR_F_ISROOT; /* Start the searching by doing a FindFirst. */ - p->handle = FINDFIRST(p->dir, (FINDATA *)p->dta); + p->handle = FINDFIRST(p->dir, (FINDATA *) p->dta); if (p->handle < 0L) { - free(p->dta); - free(p); - return(NULL); + free(p->dta); + free(p); + return (NULL); } /* All OK. */ - return(p); + return p; } - /* Close an open directory. */ int closedir(DIR *p) { if (p == NULL) - return(0); + return 0; _findclose(p->handle); if (p->dta != NULL) - free(p->dta); + free(p->dta); free(p); - return(0); + return 0; } - /* * Read the next entry from a directory. * Note that the DOS (FAT), Windows (FAT, FAT32) and Windows NTFS @@ -128,39 +105,26 @@ readdir(DIR *p) FINDATA *ffp; if (p == NULL || p->sts == 1) - return(NULL); + return (NULL); /* Format structure with current data. */ - ffp = (FINDATA *)p->dta; + ffp = (FINDATA *) p->dta; p->dent.d_ino = 1L; p->dent.d_off = p->offset++; - switch(p->offset) { - case 1: /* . */ -#ifdef UNICODE - wcsncpy(p->dent.d_name, L".", MAXNAMLEN+1); -#else - strncpy(p->dent.d_name, ".", MAXNAMLEN+1); -#endif - p->dent.d_reclen = 1; - break; + switch (p->offset) { + case 1: /* . */ + strncpy(p->dent.d_name, ".", MAXNAMLEN + 1); + p->dent.d_reclen = 1; + break; - case 2: /* .. */ -#ifdef UNICODE - wcsncpy(p->dent.d_name, L"..", MAXNAMLEN+1); -#else - strncpy(p->dent.d_name, "..", MAXNAMLEN+1); -#endif - p->dent.d_reclen = 2; - break; + case 2: /* .. */ + strncpy(p->dent.d_name, "..", MAXNAMLEN + 1); + p->dent.d_reclen = 2; + break; - default: /* regular entry. */ -#ifdef UNICODE - wcsncpy(p->dent.d_name, ffp->name, MAXNAMLEN+1); - p->dent.d_reclen = (char)wcslen(p->dent.d_name); -#else - strncpy(p->dent.d_name, ffp->name, MAXNAMLEN+1); - p->dent.d_reclen = (char)strlen(p->dent.d_name); -#endif + default: /* regular entry. */ + strncpy(p->dent.d_name, ffp->name, MAXNAMLEN + 1); + p->dent.d_reclen = (char) strlen(p->dent.d_name); } /* Read next entry. */ @@ -168,48 +132,47 @@ readdir(DIR *p) /* Fake the "." and ".." entries here.. */ if ((p->flags & DIR_F_ISROOT) && (p->offset <= 2)) - return(&(p->dent)); + return (&(p->dent)); /* Get the next entry if we did not fake the above. */ if (FINDNEXT(p->handle, ffp) < 0) - p->sts = 1; + p->sts = 1; - return(&(p->dent)); + return (&(p->dent)); } - /* Report current position within the directory. */ long telldir(DIR *p) { - return(p->offset); + return (p->offset); } - void seekdir(DIR *p, long newpos) { short pos; /* First off, rewind to start of directory. */ - p->handle = FINDFIRST(p->dir, (FINDATA *)p->dta); + p->handle = FINDFIRST(p->dir, (FINDATA *) p->dta); if (p->handle < 0L) { - p->sts = 1; - return; + p->sts = 1; + return; } p->offset = 0; - p->sts = 0; + p->sts = 0; /* If we are rewinding, that's all... */ - if (newpos == 0L) return; + if (newpos == 0L) + return; /* Nope.. read entries until we hit the right spot. */ pos = (short) newpos; while (p->offset != pos) { - p->offset++; - if (FINDNEXT(p->handle, (FINDATA *)p->dta) < 0) { - p->sts = 1; - return; - } + p->offset++; + if (FINDNEXT(p->handle, (FINDATA *) p->dta) < 0) { + p->sts = 1; + return; + } } } diff --git a/src/win/win_opengl.c b/src/win/win_opengl.c index 9bb13561d..094b3d063 100644 --- a/src/win/win_opengl.c +++ b/src/win/win_opengl.c @@ -1,24 +1,26 @@ /* - * 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. + * 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. + * This file is part of the 86Box distribution. + * + * Rendering module for OpenGL + * + * TODO: More shader features + * - scaling + * - multipass + * - previous frames + * (UI) options + * More error handling + * + * + * + * Authors: Teemu Korhonen + * + * Copyright 2021 Teemu Korhonen * - * Rendering module for OpenGL - * - * TODO: More shader features - * - scaling - * - multipass - * - previous frames - * (UI) options - * More error handling - * - * Authors: Teemu Korhonen - * - * Copyright 2021 Teemu Korhonen - * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 @@ -34,7 +36,7 @@ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #define UNICODE -#include +#include #include #include #include @@ -45,106 +47,106 @@ #include #if !defined(_MSC_VER) || defined(__clang__) -#include +# include #else typedef LONG atomic_flag; -#define atomic_flag_clear(OBJ) InterlockedExchange(OBJ, 0) -#define atomic_flag_test_and_set(OBJ) InterlockedExchange(OBJ, 1) +# define atomic_flag_clear(OBJ) InterlockedExchange(OBJ, 0) +# define atomic_flag_test_and_set(OBJ) InterlockedExchange(OBJ, 1) #endif #include <86box/86box.h> #include <86box/plat.h> +#include <86box/thread.h> #include <86box/video.h> #include <86box/win.h> #include <86box/language.h> #include <86box/win_opengl.h> #include <86box/win_opengl_glslp.h> -static const int INIT_WIDTH = 640; -static const int INIT_HEIGHT = 400; -static const int BUFFERPIXELS = 4194304; /* Same size as render_buffer, pow(2048+64,2). */ -static const int BUFFERBYTES = 16777216; /* Pixel is 4 bytes. */ -static const int BUFFERCOUNT = 3; /* How many buffers to use for pixel transfer (2-3 is commonly recommended). */ -static const int ROW_LENGTH = 2048; /* Source buffer row lenght (including padding) */ +static const int INIT_WIDTH = 640; +static const int INIT_HEIGHT = 400; +static const int BUFFERPIXELS = 4194304; /* Same size as render_buffer, pow(2048 + 64, 2). */ +static const int BUFFERBYTES = 16777216; /* Pixel is 4 bytes. */ +static const int BUFFERCOUNT = 3; /* How many buffers to use for pixel transfer (2-3 is commonly recommended). */ +static const int ROW_LENGTH = 2048; /* Source buffer row lenght (including padding) */ /** * @brief A dedicated OpenGL thread. * OpenGL context's don't handle multiple threads well. -*/ -static thread_t* thread = NULL; + */ +static thread_t *thread = NULL; /** * @brief A window usable with an OpenGL context -*/ -static SDL_Window* window = NULL; + */ +static SDL_Window *window = NULL; /** * @brief SDL window handle -*/ + */ static HWND window_hwnd = NULL; /** * @brief Parent window handle (hwndRender from win_ui) -*/ + */ static HWND parent = NULL; /** * @brief Events listened in OpenGL thread. -*/ -static union -{ - struct - { - HANDLE closing; - HANDLE resize; - HANDLE reload; - HANDLE blit_waiting; - }; - HANDLE asArray[4]; + */ +static union { + struct + { + HANDLE closing; + HANDLE resize; + HANDLE reload; + HANDLE blit_waiting; + }; + HANDLE asArray[4]; } sync_objects = { 0 }; /** * @brief Blit event parameters. -*/ + */ typedef struct { - int w, h; - void* buffer; /* Buffer for pixel transfer, allocated by gpu driver. */ - volatile atomic_flag in_use; /* Is buffer currently in use. */ - GLsync sync; /* Fence sync object used by opengl thread to track pixel transfer completion. */ + int w, h; + void *buffer; /* Buffer for pixel transfer, allocated by gpu driver. */ + volatile atomic_flag in_use; /* Is buffer currently in use. */ + GLsync sync; /* Fence sync object used by opengl thread to track pixel transfer completion. */ } blit_info_t; /** * @brief Array of blit_infos, one for each buffer. -*/ -static blit_info_t* blit_info = NULL; + */ +static blit_info_t *blit_info = NULL; /** * @brief Buffer index of next write operation. -*/ + */ static int write_pos = 0; /** * @brief Resize event parameters. -*/ + */ static struct { - int width, height, fullscreen, scaling_mode; - mutex_t* mutex; + int width, height, fullscreen, scaling_mode; + mutex_t *mutex; } resize_info = { 0 }; /** * @brief Renderer options -*/ + */ static struct { - int vsync; /* Vertical sync; 0 = off, 1 = on */ - int frametime; /* Frametime in microseconds, or -1 to sync with blitter */ - char shaderfile[512]; /* Shader file path. Match the length of openfilestring in win_dialog.c */ - int shaderfile_changed; /* Has shader file path changed. To prevent unnecessary shader recompilation. */ - int filter; /* 0 = Nearest, 1 = Linear */ - int filter_changed; /* Has filter changed. */ - mutex_t* mutex; + int vsync; /* Vertical sync; 0 = off, 1 = on */ + int frametime; /* Frametime in microseconds, or -1 to sync with blitter */ + char shaderfile[512]; /* Shader file path. Match the length of openfilestring in win_dialog.c */ + int shaderfile_changed; /* Has shader file path changed. To prevent unnecessary shader recompilation. */ + int filter; /* 0 = Nearest, 1 = Linear */ + int filter_changed; /* Has filter changed. */ + mutex_t *mutex; } options = { 0 }; /** @@ -152,894 +154,849 @@ static struct */ typedef struct { - GLuint vertexArrayID; - GLuint vertexBufferID; - GLuint textureID; - GLuint unpackBufferID; - GLuint shader_progID; + GLuint vertexArrayID; + GLuint vertexBufferID; + GLuint textureID; + GLuint unpackBufferID; + GLuint shader_progID; - /* Uniforms */ + /* Uniforms */ - GLint input_size; - GLint output_size; - GLint texture_size; - GLint frame_count; + GLint input_size; + GLint output_size; + GLint texture_size; + GLint frame_count; } gl_identifiers; /** * @brief Set or unset OpenGL context window as a child window. - * + * * Modifies the window style and sets the parent window. * WS_EX_NOACTIVATE keeps the window from stealing input focus. */ -static void set_parent_binding(int enable) +static void +set_parent_binding(int enable) { - long style = GetWindowLong(window_hwnd, GWL_STYLE); - long ex_style = GetWindowLong(window_hwnd, GWL_EXSTYLE); + long style = GetWindowLong(window_hwnd, GWL_STYLE); + long ex_style = GetWindowLong(window_hwnd, GWL_EXSTYLE); - if (enable) - { - style |= WS_CHILD; - ex_style |= WS_EX_NOACTIVATE; - } - else - { - style &= ~WS_CHILD; - ex_style &= ~WS_EX_NOACTIVATE; - } + if (enable) { + style |= WS_CHILD; + ex_style |= WS_EX_NOACTIVATE; + } else { + style &= ~WS_CHILD; + ex_style &= ~WS_EX_NOACTIVATE; + } - SetWindowLong(window_hwnd, GWL_STYLE, style); - SetWindowLong(window_hwnd, GWL_EXSTYLE, ex_style); + SetWindowLong(window_hwnd, GWL_STYLE, style); + SetWindowLong(window_hwnd, GWL_EXSTYLE, ex_style); - SetParent(window_hwnd, enable ? parent : NULL); + SetParent(window_hwnd, enable ? parent : NULL); } /** * @brief Windows message handler for our window. * @param message * @param wParam - * @param lParam + * @param lParam * @param fullscreen * @return Was message handled -*/ -static int handle_window_messages(UINT message, WPARAM wParam, LPARAM lParam, int fullscreen) + */ +static int +handle_window_messages(UINT message, WPARAM wParam, LPARAM lParam, int fullscreen) { - switch (message) - { - case WM_LBUTTONUP: - case WM_LBUTTONDOWN: - case WM_MBUTTONUP: - case WM_MBUTTONDOWN: - case WM_RBUTTONUP: - case WM_RBUTTONDOWN: - if (!fullscreen) - { - /* Bring main window to front. */ - SetForegroundWindow(GetAncestor(parent, GA_ROOT)); + switch (message) { + case WM_LBUTTONUP: + case WM_LBUTTONDOWN: + case WM_MBUTTONUP: + case WM_MBUTTONDOWN: + case WM_RBUTTONUP: + case WM_RBUTTONDOWN: + if (!fullscreen) { + /* Bring main window to front. */ + SetForegroundWindow(GetAncestor(parent, GA_ROOT)); - /* Mouse events that enter and exit capture. */ - PostMessage(parent, message, wParam, lParam); - } - return 1; - case WM_KEYDOWN: - case WM_KEYUP: - case WM_SYSKEYDOWN: - case WM_SYSKEYUP: - if (fullscreen) - { - PostMessage(parent, message, wParam, lParam); - } - return 1; - case WM_INPUT: - if (fullscreen) - { - /* Raw input handler from win_ui.c : input_proc */ + /* Mouse events that enter and exit capture. */ + PostMessage(parent, message, wParam, lParam); + } + return 1; + case WM_KEYDOWN: + case WM_KEYUP: + case WM_SYSKEYDOWN: + case WM_SYSKEYUP: + if (fullscreen) { + PostMessage(parent, message, wParam, lParam); + } + return 1; + case WM_INPUT: + if (fullscreen) { + /* Raw input handler from win_ui.c : input_proc */ - UINT size = 0; - PRAWINPUT raw = NULL; + UINT size = 0; + PRAWINPUT raw = NULL; - /* Here we read the raw input data */ - GetRawInputData((HRAWINPUT)(LPARAM)lParam, RID_INPUT, NULL, &size, sizeof(RAWINPUTHEADER)); - raw = (PRAWINPUT)malloc(size); - if (GetRawInputData((HRAWINPUT)(LPARAM)lParam, RID_INPUT, raw, &size, sizeof(RAWINPUTHEADER)) == size) { - switch (raw->header.dwType) - { - case RIM_TYPEKEYBOARD: - keyboard_handle(raw); - break; - case RIM_TYPEMOUSE: - win_mouse_handle(raw); - break; - case RIM_TYPEHID: - win_joystick_handle(raw); - break; - } - } - free(raw); - } - return 1; - case WM_MOUSELEAVE: - if (fullscreen) - { - /* Leave fullscreen if mouse leaves the renderer window. */ - PostMessage(GetAncestor(parent, GA_ROOT), WM_LEAVEFULLSCREEN, 0, 0); - } - return 0; - } + /* Here we read the raw input data */ + GetRawInputData((HRAWINPUT) lParam, RID_INPUT, NULL, &size, sizeof(RAWINPUTHEADER)); + raw = (PRAWINPUT) malloc(size); + if (GetRawInputData((HRAWINPUT) lParam, RID_INPUT, raw, &size, sizeof(RAWINPUTHEADER)) == size) { + switch (raw->header.dwType) { + case RIM_TYPEKEYBOARD: + keyboard_handle(raw); + break; + case RIM_TYPEMOUSE: + win_mouse_handle(raw); + break; + case RIM_TYPEHID: + win_joystick_handle(raw); + break; + } + } + free(raw); + } + return 1; + case WM_MOUSELEAVE: + if (fullscreen) { + /* Leave fullscreen if mouse leaves the renderer window. */ + PostMessage(GetAncestor(parent, GA_ROOT), WM_LEAVEFULLSCREEN, 0, 0); + } + return 0; + } - return 0; + return 0; } /** * @brief (Re-)apply shaders to OpenGL context. * @param gl Identifiers from initialize -*/ -static void apply_shaders(gl_identifiers* gl) + */ +static void +apply_shaders(gl_identifiers *gl) { - GLuint old_shader_ID = 0; + GLuint old_shader_ID = 0; - if (gl->shader_progID != 0) - old_shader_ID = gl->shader_progID; + if (gl->shader_progID != 0) + old_shader_ID = gl->shader_progID; - if (strlen(options.shaderfile) > 0) - gl->shader_progID = load_custom_shaders(options.shaderfile); - else - gl->shader_progID = 0; + if (strlen(options.shaderfile) > 0) + gl->shader_progID = load_custom_shaders(options.shaderfile); + else + gl->shader_progID = 0; - if (gl->shader_progID == 0) - gl->shader_progID = load_default_shaders(); + if (gl->shader_progID == 0) + gl->shader_progID = load_default_shaders(); - glUseProgram(gl->shader_progID); + glUseProgram(gl->shader_progID); - /* Delete old shader if one exists (changing shader) */ - if (old_shader_ID != 0) - glDeleteProgram(old_shader_ID); + /* Delete old shader if one exists (changing shader) */ + if (old_shader_ID != 0) + glDeleteProgram(old_shader_ID); - GLint vertex_coord = glGetAttribLocation(gl->shader_progID, "VertexCoord"); - if (vertex_coord != -1) - { - glEnableVertexAttribArray(vertex_coord); - glVertexAttribPointer(vertex_coord, 2, GL_FLOAT, GL_FALSE, 8 * sizeof(GLfloat), 0); - } + GLint vertex_coord = glGetAttribLocation(gl->shader_progID, "VertexCoord"); + if (vertex_coord != -1) { + glEnableVertexAttribArray(vertex_coord); + glVertexAttribPointer(vertex_coord, 2, GL_FLOAT, GL_FALSE, 8 * sizeof(GLfloat), 0); + } - GLint tex_coord = glGetAttribLocation(gl->shader_progID, "TexCoord"); - if (tex_coord != -1) - { - glEnableVertexAttribArray(tex_coord); - glVertexAttribPointer(tex_coord, 2, GL_FLOAT, GL_FALSE, 8 * sizeof(GLfloat), (void*)(2 * sizeof(GLfloat))); - } + GLint tex_coord = glGetAttribLocation(gl->shader_progID, "TexCoord"); + if (tex_coord != -1) { + glEnableVertexAttribArray(tex_coord); + glVertexAttribPointer(tex_coord, 2, GL_FLOAT, GL_FALSE, 8 * sizeof(GLfloat), (void *) (2 * sizeof(GLfloat))); + } - GLint color = glGetAttribLocation(gl->shader_progID, "Color"); - if (color != -1) - { - glEnableVertexAttribArray(color); - glVertexAttribPointer(color, 4, GL_FLOAT, GL_FALSE, 8 * sizeof(GLfloat), (void*)(4 * sizeof(GLfloat))); - } + GLint color = glGetAttribLocation(gl->shader_progID, "Color"); + if (color != -1) { + glEnableVertexAttribArray(color); + glVertexAttribPointer(color, 4, GL_FLOAT, GL_FALSE, 8 * sizeof(GLfloat), (void *) (4 * sizeof(GLfloat))); + } - GLint mvp_matrix = glGetUniformLocation(gl->shader_progID, "MVPMatrix"); - if (mvp_matrix != -1) - { - static const GLfloat mvp[] = { - 1.f, 0.f, 0.f, 0.f, - 0.f, 1.f, 0.f, 0.f, - 0.f, 0.f, 1.f, 0.f, - 0.f, 0.f, 0.f, 1.f - }; - glUniformMatrix4fv(mvp_matrix, 1, GL_FALSE, mvp); - } + GLint mvp_matrix = glGetUniformLocation(gl->shader_progID, "MVPMatrix"); + if (mvp_matrix != -1) { + static const GLfloat mvp[] = { + 1.f, 0.f, 0.f, 0.f, + 0.f, 1.f, 0.f, 0.f, + 0.f, 0.f, 1.f, 0.f, + 0.f, 0.f, 0.f, 1.f + }; + glUniformMatrix4fv(mvp_matrix, 1, GL_FALSE, mvp); + } - GLint frame_direction = glGetUniformLocation(gl->shader_progID, "FrameDirection"); - if (frame_direction != -1) - glUniform1i(frame_direction, 1); /* always forward */ + GLint frame_direction = glGetUniformLocation(gl->shader_progID, "FrameDirection"); + if (frame_direction != -1) + glUniform1i(frame_direction, 1); /* always forward */ - gl->input_size = glGetUniformLocation(gl->shader_progID, "InputSize"); - gl->output_size = glGetUniformLocation(gl->shader_progID, "OutputSize"); - gl->texture_size = glGetUniformLocation(gl->shader_progID, "TextureSize"); - gl->frame_count = glGetUniformLocation(gl->shader_progID, "FrameCount"); + gl->input_size = glGetUniformLocation(gl->shader_progID, "InputSize"); + gl->output_size = glGetUniformLocation(gl->shader_progID, "OutputSize"); + gl->texture_size = glGetUniformLocation(gl->shader_progID, "TextureSize"); + gl->frame_count = glGetUniformLocation(gl->shader_progID, "FrameCount"); } /** * @brief Initialize OpenGL context * @return Identifiers -*/ -static int initialize_glcontext(gl_identifiers* gl) + */ +static int +initialize_glcontext(gl_identifiers *gl) { - /* Vertex, texture 2d coordinates and color (white) making a quad as triangle strip */ - static const GLfloat surface[] = { - -1.f, 1.f, 0.f, 0.f, 1.f, 1.f, 1.f, 1.f, - 1.f, 1.f, 1.f, 0.f, 1.f, 1.f, 1.f, 1.f, - -1.f, -1.f, 0.f, 1.f, 1.f, 1.f, 1.f, 1.f, - 1.f, -1.f, 1.f, 1.f, 1.f, 1.f, 1.f, 1.f - }; + /* Vertex, texture 2d coordinates and color (white) making a quad as triangle strip */ + static const GLfloat surface[] = { + -1.f, 1.f, 0.f, 0.f, 1.f, 1.f, 1.f, 1.f, + 1.f, 1.f, 1.f, 0.f, 1.f, 1.f, 1.f, 1.f, + -1.f, -1.f, 0.f, 1.f, 1.f, 1.f, 1.f, 1.f, + 1.f, -1.f, 1.f, 1.f, 1.f, 1.f, 1.f, 1.f + }; - glGenVertexArrays(1, &gl->vertexArrayID); + glGenVertexArrays(1, &gl->vertexArrayID); - glBindVertexArray(gl->vertexArrayID); + glBindVertexArray(gl->vertexArrayID); - glGenBuffers(1, &gl->vertexBufferID); - glBindBuffer(GL_ARRAY_BUFFER, gl->vertexBufferID); - glBufferData(GL_ARRAY_BUFFER, sizeof(surface), surface, GL_STATIC_DRAW); + glGenBuffers(1, &gl->vertexBufferID); + glBindBuffer(GL_ARRAY_BUFFER, gl->vertexBufferID); + glBufferData(GL_ARRAY_BUFFER, sizeof(surface), surface, GL_STATIC_DRAW); - glGenTextures(1, &gl->textureID); - glBindTexture(GL_TEXTURE_2D, gl->textureID); + glGenTextures(1, &gl->textureID); + glBindTexture(GL_TEXTURE_2D, gl->textureID); - static const GLfloat border_color[] = { 0.f, 0.f, 0.f, 1.f }; - glTexParameterfv(GL_TEXTURE_2D, GL_TEXTURE_BORDER_COLOR, border_color); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_BORDER); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_BORDER); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, options.filter ? GL_LINEAR : GL_NEAREST); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, options.filter ? GL_LINEAR : GL_NEAREST); + static const GLfloat border_color[] = { 0.f, 0.f, 0.f, 1.f }; + glTexParameterfv(GL_TEXTURE_2D, GL_TEXTURE_BORDER_COLOR, border_color); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_BORDER); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_BORDER); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, options.filter ? GL_LINEAR : GL_NEAREST); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, options.filter ? GL_LINEAR : GL_NEAREST); - glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, INIT_WIDTH, INIT_HEIGHT, 0, GL_BGRA, GL_UNSIGNED_INT_8_8_8_8_REV, NULL); + glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, INIT_WIDTH, INIT_HEIGHT, 0, GL_BGRA, GL_UNSIGNED_INT_8_8_8_8_REV, NULL); - glGenBuffers(1, &gl->unpackBufferID); - glBindBuffer(GL_PIXEL_UNPACK_BUFFER, gl->unpackBufferID); + glGenBuffers(1, &gl->unpackBufferID); + glBindBuffer(GL_PIXEL_UNPACK_BUFFER, gl->unpackBufferID); - void* buf_ptr = NULL; + void *buf_ptr = NULL; - if (GLAD_GL_ARB_buffer_storage) - { - /* Create persistent buffer for pixel transfer. */ - glBufferStorage(GL_PIXEL_UNPACK_BUFFER, BUFFERBYTES * BUFFERCOUNT, NULL, GL_MAP_WRITE_BIT | GL_MAP_PERSISTENT_BIT | GL_MAP_COHERENT_BIT); + if (GLAD_GL_ARB_buffer_storage) { + /* Create persistent buffer for pixel transfer. */ + glBufferStorage(GL_PIXEL_UNPACK_BUFFER, BUFFERBYTES * BUFFERCOUNT, NULL, GL_MAP_WRITE_BIT | GL_MAP_PERSISTENT_BIT | GL_MAP_COHERENT_BIT); - buf_ptr = glMapBufferRange(GL_PIXEL_UNPACK_BUFFER, 0, BUFFERBYTES * BUFFERCOUNT, GL_MAP_WRITE_BIT | GL_MAP_PERSISTENT_BIT | GL_MAP_COHERENT_BIT); - } - else - { - /* Fallback; create our own buffer. */ - buf_ptr = malloc(BUFFERBYTES * BUFFERCOUNT); + buf_ptr = glMapBufferRange(GL_PIXEL_UNPACK_BUFFER, 0, BUFFERBYTES * BUFFERCOUNT, GL_MAP_WRITE_BIT | GL_MAP_PERSISTENT_BIT | GL_MAP_COHERENT_BIT); + } else { + /* Fallback; create our own buffer. */ + buf_ptr = malloc(BUFFERBYTES * BUFFERCOUNT); - glBufferData(GL_PIXEL_UNPACK_BUFFER, BUFFERBYTES * BUFFERCOUNT, NULL, GL_STREAM_DRAW); - } + glBufferData(GL_PIXEL_UNPACK_BUFFER, BUFFERBYTES * BUFFERCOUNT, NULL, GL_STREAM_DRAW); + } - if (buf_ptr == NULL) - return 0; /* Most likely out of memory. */ + if (buf_ptr == NULL) + return 0; /* Most likely out of memory. */ - /* Split the buffer area for each blit_info and set them available for use. */ - for (int i = 0; i < BUFFERCOUNT; i++) - { - blit_info[i].buffer = (byte*)buf_ptr + BUFFERBYTES * i; - atomic_flag_clear(&blit_info[i].in_use); - } + /* Split the buffer area for each blit_info and set them available for use. */ + for (int i = 0; i < BUFFERCOUNT; i++) { + blit_info[i].buffer = (byte *) buf_ptr + BUFFERBYTES * i; + atomic_flag_clear(&blit_info[i].in_use); + } - glClearColor(0.f, 0.f, 0.f, 1.f); + glClearColor(0.f, 0.f, 0.f, 1.f); - apply_shaders(gl); + apply_shaders(gl); - return 1; + return 1; } /** - * @brief Clean up OpenGL context - * @param gl Identifiers from initialize -*/ -static void finalize_glcontext(gl_identifiers* gl) + * @brief Clean up OpenGL context + * @param gl Identifiers from initialize + */ +static void +finalize_glcontext(gl_identifiers *gl) { - if (GLAD_GL_ARB_buffer_storage) - glUnmapBuffer(GL_PIXEL_UNPACK_BUFFER); - else - free(blit_info[0].buffer); + if (GLAD_GL_ARB_buffer_storage) + glUnmapBuffer(GL_PIXEL_UNPACK_BUFFER); + else + free(blit_info[0].buffer); - glDeleteProgram(gl->shader_progID); - glDeleteBuffers(1, &gl->unpackBufferID); - glDeleteTextures(1, &gl->textureID); - glDeleteBuffers(1, &gl->vertexBufferID); - glDeleteVertexArrays(1, &gl->vertexArrayID); + glDeleteProgram(gl->shader_progID); + glDeleteBuffers(1, &gl->unpackBufferID); + glDeleteTextures(1, &gl->textureID); + glDeleteBuffers(1, &gl->vertexBufferID); + glDeleteVertexArrays(1, &gl->vertexArrayID); } /** * @brief Renders a frame and swaps the buffer * @param gl Identifiers from initialize -*/ -static void render_and_swap(gl_identifiers* gl) + */ +static void +render_and_swap(gl_identifiers *gl) { - static int frame_counter = 0; + static int frame_counter = 0; - glClear(GL_COLOR_BUFFER_BIT); - glDrawArrays(GL_TRIANGLE_STRIP, 0, 4); + glClear(GL_COLOR_BUFFER_BIT); + glDrawArrays(GL_TRIANGLE_STRIP, 0, 4); - SDL_GL_SwapWindow(window); + SDL_GL_SwapWindow(window); - if (gl->frame_count != -1) - glUniform1i(gl->frame_count, frame_counter = (frame_counter + 1) & 1023); + if (gl->frame_count != -1) + glUniform1i(gl->frame_count, frame_counter = (frame_counter + 1) & 1023); } /** * @brief Handle failure in OpenGL thread. * Keeps the thread sleeping until closing. -*/ -static void opengl_fail() + */ +static void +opengl_fail(void) { - if (window != NULL) - { - SDL_DestroyWindow(window); - window = NULL; - } + if (window != NULL) { + SDL_DestroyWindow(window); + window = NULL; + } - wchar_t* message = plat_get_string(IDS_2152); - wchar_t* header = plat_get_string(IDS_2153); - MessageBox(parent, header, message, MB_OK); + const wchar_t *message = plat_get_string(IDS_2153); + const wchar_t *header = plat_get_string(IDS_2154); + MessageBox(parent, header, message, MB_OK); - WaitForSingleObject(sync_objects.closing, INFINITE); + WaitForSingleObject(sync_objects.closing, INFINITE); - _endthread(); + _endthread(); } -static void __stdcall opengl_debugmsg_callback(GLenum source, GLenum type, GLuint id, GLenum severity, GLsizei length, const GLchar* message, const void* userParam) +static void __stdcall opengl_debugmsg_callback(UNUSED(GLenum source), UNUSED(GLenum type), UNUSED(GLuint id), UNUSED(GLenum severity), UNUSED(GLsizei length), const GLchar *message, UNUSED(const void *userParam)) { - pclog("OpenGL: %s\n", message); + pclog("OpenGL: %s\n", message); } /** * @brief Main OpenGL thread proc. - * + * * OpenGL context should be accessed only from this single thread. * Events are used to synchronize communication. -*/ -static void opengl_main(void* param) + */ +static void +opengl_main(UNUSED(void *param)) { - /* Initialize COM library for this thread before SDL does so. */ - CoInitializeEx(NULL, COINIT_MULTITHREADED); - - SDL_InitSubSystem(SDL_INIT_VIDEO); - - SDL_SetHint(SDL_HINT_MOUSE_FOCUS_CLICKTHROUGH, "1"); /* Is this actually doing anything...? */ - - SDL_GL_SetAttribute(SDL_GL_CONTEXT_MAJOR_VERSION, 3); - SDL_GL_SetAttribute(SDL_GL_CONTEXT_MINOR_VERSION, 0); - SDL_GL_SetAttribute(SDL_GL_CONTEXT_PROFILE_MASK, SDL_GL_CONTEXT_PROFILE_CORE); - - if (GLAD_GL_ARB_debug_output && log_path[0] != '\0') - SDL_GL_SetAttribute(SDL_GL_CONTEXT_FLAGS, SDL_GL_CONTEXT_DEBUG_FLAG | SDL_GL_CONTEXT_FORWARD_COMPATIBLE_FLAG); - else - SDL_GL_SetAttribute(SDL_GL_CONTEXT_FLAGS, SDL_GL_CONTEXT_FORWARD_COMPATIBLE_FLAG); - - window = SDL_CreateWindow("86Box OpenGL Renderer", 0, 0, resize_info.width, resize_info.height, SDL_WINDOW_OPENGL | SDL_WINDOW_BORDERLESS); - - if (window == NULL) - { - pclog("OpenGL: failed to create OpenGL window.\n"); - opengl_fail(); - } - - /* Keep track of certain parameters, only changed in this thread to avoid race conditions */ - int fullscreen = resize_info.fullscreen, video_width = INIT_WIDTH, video_height = INIT_HEIGHT, - output_width = resize_info.width, output_height = resize_info.height, frametime = options.frametime; - - SDL_SysWMinfo wmi = { 0 }; - SDL_VERSION(&wmi.version); - SDL_GetWindowWMInfo(window, &wmi); - - if (wmi.subsystem != SDL_SYSWM_WINDOWS) - { - pclog("OpenGL: subsystem is not SDL_SYSWM_WINDOWS.\n"); - opengl_fail(); - } - - window_hwnd = wmi.info.win.window; - - if (!fullscreen) - set_parent_binding(1); - else - SDL_SetWindowFullscreen(window, SDL_WINDOW_FULLSCREEN_DESKTOP); - - SDL_GLContext context = SDL_GL_CreateContext(window); - - if (context == NULL) - { - pclog("OpenGL: failed to create OpenGL context.\n"); - opengl_fail(); - } - - SDL_GL_SetSwapInterval(options.vsync); - - if (!gladLoadGLLoader(SDL_GL_GetProcAddress)) - { - pclog("OpenGL: failed to set OpenGL loader.\n"); - SDL_GL_DeleteContext(context); - opengl_fail(); - } - - if (GLAD_GL_ARB_debug_output && log_path[0] != '\0') - { - glEnable(GL_DEBUG_OUTPUT_SYNCHRONOUS_ARB); - glDebugMessageControlARB(GL_DONT_CARE, GL_DEBUG_TYPE_PERFORMANCE_ARB, GL_DONT_CARE, 0, 0, GL_FALSE); - glDebugMessageCallbackARB(opengl_debugmsg_callback, NULL); - } - - pclog("OpenGL vendor: %s\n", glGetString(GL_VENDOR)); - pclog("OpenGL renderer: %s\n", glGetString(GL_RENDERER)); - pclog("OpenGL version: %s\n", glGetString(GL_VERSION)); - pclog("OpenGL shader language version: %s\n", glGetString(GL_SHADING_LANGUAGE_VERSION)); - - /* Check that the driver actually reports version 3.0 or later */ - GLint major = -1; - glGetIntegerv(GL_MAJOR_VERSION, &major); - if (major < 3) - { - pclog("OpenGL: Minimum OpenGL version 3.0 is required.\n"); - SDL_GL_DeleteContext(context); - opengl_fail(); - } - - /* Check if errors have been generated at this point */ - GLenum gl_error = glGetError(); - if (gl_error != GL_NO_ERROR) - { - /* Log up to 10 errors */ - int i = 0; - do - { - pclog("OpenGL: Error %u\n", gl_error); - i++; - } - while((gl_error = glGetError()) != GL_NO_ERROR && i < 10); - - SDL_GL_DeleteContext(context); - opengl_fail(); - } - - gl_identifiers gl = { 0 }; - - if (!initialize_glcontext(&gl)) - { - pclog("OpenGL: failed to initialize.\n"); - finalize_glcontext(&gl); - SDL_GL_DeleteContext(context); - opengl_fail(); - } - - if (gl.frame_count != -1) - glUniform1i(gl.frame_count, 0); - if (gl.output_size != -1) - glUniform2f(gl.output_size, output_width, output_height); - - uint32_t last_swap = plat_get_micro_ticks() - frametime; - - int read_pos = 0; /* Buffer index of next read operation. */ - - /* Render loop */ - int closing = 0; - while (!closing) - { - /* Rendering is done right after handling an event. */ - if (frametime < 0) - render_and_swap(&gl); - - DWORD wait_result = WAIT_TIMEOUT; - - do - { - /* Rendering is timed by frame capping. */ - if (frametime >= 0) - { - uint32_t ticks = plat_get_micro_ticks(); - - uint32_t elapsed = ticks - last_swap; - - if (elapsed + 1000 > frametime) - { - /* Spin the remaining time (< 1ms) to next frame */ - while (elapsed < frametime) - { - Sleep(0); /* Yield processor time */ - ticks = plat_get_micro_ticks(); - elapsed = ticks - last_swap; - } - - render_and_swap(&gl); - last_swap = ticks; - } - } - - if (GLAD_GL_ARB_sync) - { - /* Check if commands that use buffers have been completed. */ - for (int i = 0; i < BUFFERCOUNT; i++) - { - if (blit_info[i].sync != NULL && glClientWaitSync(blit_info[i].sync, GL_SYNC_FLUSH_COMMANDS_BIT, 0) != GL_TIMEOUT_EXPIRED) - { - glDeleteSync(blit_info[i].sync); - blit_info[i].sync = NULL; - atomic_flag_clear(&blit_info[i].in_use); - } - } - } - - /* Handle window messages */ - MSG msg; - while (PeekMessage(&msg, NULL, 0, 0, PM_REMOVE)) - { - if (msg.hwnd != window_hwnd || !handle_window_messages(msg.message, msg.wParam, msg.lParam, fullscreen)) - { - TranslateMessage(&msg); - DispatchMessage(&msg); - } - } - - /* Wait for synchronized events for 1ms before going back to window events */ - wait_result = WaitForMultipleObjects(sizeof(sync_objects) / sizeof(HANDLE), sync_objects.asArray, FALSE, 1); - - } while (wait_result == WAIT_TIMEOUT); - - HANDLE sync_event = sync_objects.asArray[wait_result - WAIT_OBJECT_0]; - - if (sync_event == sync_objects.closing) - { - closing = 1; - } - else if (sync_event == sync_objects.blit_waiting) - { - blit_info_t* info = &blit_info[read_pos]; - - if (video_width != info->w || video_height != info->h) - { - video_width = info->w; - video_height = info->h; - - /* Resize the texture */ - glBindBuffer(GL_PIXEL_UNPACK_BUFFER, 0); - glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, video_width, video_height, 0, GL_BGRA, GL_UNSIGNED_INT_8_8_8_8_REV, NULL); - glBindBuffer(GL_PIXEL_UNPACK_BUFFER, gl.unpackBufferID); - - if (fullscreen) - SetEvent(sync_objects.resize); - } - - if (!GLAD_GL_ARB_buffer_storage) - { - /* Fallback method, copy data to pixel buffer. */ - glBufferSubData(GL_PIXEL_UNPACK_BUFFER, BUFFERBYTES * read_pos, info->h * ROW_LENGTH * sizeof(uint32_t), info->buffer); - } - - /* Update texture from pixel buffer. */ - glPixelStorei(GL_UNPACK_SKIP_PIXELS, BUFFERPIXELS * read_pos); - glPixelStorei(GL_UNPACK_ROW_LENGTH, ROW_LENGTH); - glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, info->w, info->h, GL_BGRA, GL_UNSIGNED_INT_8_8_8_8_REV, NULL); - - if (GLAD_GL_ARB_sync) - { - /* Add fence to track when above gl commands are complete. */ - info->sync = glFenceSync(GL_SYNC_GPU_COMMANDS_COMPLETE, 0); - } - else - { - /* No sync objects; block until commands are complete. */ - glFinish(); - atomic_flag_clear(&info->in_use); - } - - read_pos = (read_pos + 1) % BUFFERCOUNT; - - /* Update uniforms */ - if (gl.input_size != -1) - glUniform2f(gl.input_size, video_width, video_height); - if (gl.texture_size != -1) - glUniform2f(gl.texture_size, video_width, video_height); - } - else if (sync_event == sync_objects.resize) - { - thread_wait_mutex(resize_info.mutex); - - if (fullscreen != resize_info.fullscreen) - { - fullscreen = resize_info.fullscreen; - - set_parent_binding(!fullscreen); - - SDL_SetWindowFullscreen(window, fullscreen ? SDL_WINDOW_FULLSCREEN_DESKTOP : 0); - - if (fullscreen) - { - SetForegroundWindow(window_hwnd); - SetFocus(window_hwnd); - - /* Clip cursor to prevent it moving to another monitor. */ - RECT rect; - GetWindowRect(window_hwnd, &rect); - ClipCursor(&rect); - } - else - ClipCursor(NULL); - } - - if (fullscreen) - { - int width, height, pad_x = 0, pad_y = 0, px_size = 1; - float ratio = 0; - const float ratio43 = 4.f / 3.f; - - SDL_GetWindowSize(window, &width, &height); - - if (video_width > 0 && video_height > 0) - { - switch (resize_info.scaling_mode) - { - case FULLSCR_SCALE_INT: - px_size = max(min(width / video_width, height / video_height), 1); - - pad_x = width - (video_width * px_size); - pad_y = height - (video_height * px_size); - break; - - case FULLSCR_SCALE_KEEPRATIO: - ratio = (float)video_width / (float)video_height; - case FULLSCR_SCALE_43: - if (ratio == 0) - ratio = ratio43; - if (ratio < ((float)width / (float)height)) - pad_x = width - (int)roundf((float)height * ratio); - else - pad_y = height - (int)roundf((float)width / ratio); - break; - - case FULLSCR_SCALE_FULL: - default: - break; - } - } - - output_width = width - pad_x; - output_height = height - pad_y; - - glViewport(pad_x / 2, pad_y / 2, output_width, output_height); - - if (gl.output_size != -1) - glUniform2f(gl.output_size, output_width, output_height); - } - else - { - SDL_SetWindowSize(window, resize_info.width, resize_info.height); - - /* SWP_NOZORDER is needed for child window and SDL doesn't enable it. */ - SetWindowPos(window_hwnd, parent, 0, 0, resize_info.width, resize_info.height, SWP_NOZORDER | SWP_NOCOPYBITS | SWP_NOMOVE | SWP_NOACTIVATE); - - output_width = resize_info.width; - output_height = resize_info.height; - - glViewport(0, 0, resize_info.width, resize_info.height); - - if (gl.output_size != -1) - glUniform2f(gl.output_size, resize_info.width, resize_info.height); - } - - thread_release_mutex(resize_info.mutex); - } - else if (sync_event == sync_objects.reload) - { - thread_wait_mutex(options.mutex); - - frametime = options.frametime; - - SDL_GL_SetSwapInterval(options.vsync); - - if (options.shaderfile_changed) - { - /* Change shader program. */ - apply_shaders(&gl); - - /* Uniforms need to be updated after proram change. */ - if (gl.input_size != -1) - glUniform2f(gl.input_size, video_width, video_height); - if (gl.output_size != -1) - glUniform2f(gl.output_size, output_width, output_height); - if (gl.texture_size != -1) - glUniform2f(gl.texture_size, video_width, video_height); - if (gl.frame_count != -1) - glUniform1i(gl.frame_count, 0); - - options.shaderfile_changed = 0; - } - - if (options.filter_changed) - { - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, options.filter ? GL_LINEAR : GL_NEAREST); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, options.filter ? GL_LINEAR : GL_NEAREST); - - options.filter_changed = 0; - } - - thread_release_mutex(options.mutex); - } - - /* Keep cursor hidden in full screen and mouse capture */ - int show_cursor = !(fullscreen || !!mouse_capture); - if (SDL_ShowCursor(-1) != show_cursor) - SDL_ShowCursor(show_cursor); - } - - if (GLAD_GL_ARB_sync) - { - for (int i = 0; i < BUFFERCOUNT; i++) - { - if (blit_info[i].sync != NULL) - glDeleteSync(blit_info[i].sync); - } - } - - finalize_glcontext(&gl); - - SDL_GL_DeleteContext(context); - - set_parent_binding(0); - - SDL_DestroyWindow(window); - - window = NULL; + /* Initialize COM library for this thread before SDL does so. */ + CoInitializeEx(NULL, COINIT_MULTITHREADED); + + SDL_InitSubSystem(SDL_INIT_VIDEO); + + SDL_SetHint(SDL_HINT_MOUSE_FOCUS_CLICKTHROUGH, "1"); /* Is this actually doing anything...? */ + + SDL_GL_SetAttribute(SDL_GL_CONTEXT_MAJOR_VERSION, 3); + SDL_GL_SetAttribute(SDL_GL_CONTEXT_MINOR_VERSION, 0); + SDL_GL_SetAttribute(SDL_GL_CONTEXT_PROFILE_MASK, SDL_GL_CONTEXT_PROFILE_CORE); + + if (GLAD_GL_ARB_debug_output && log_path[0] != '\0') + SDL_GL_SetAttribute(SDL_GL_CONTEXT_FLAGS, SDL_GL_CONTEXT_DEBUG_FLAG | SDL_GL_CONTEXT_FORWARD_COMPATIBLE_FLAG); + else + SDL_GL_SetAttribute(SDL_GL_CONTEXT_FLAGS, SDL_GL_CONTEXT_FORWARD_COMPATIBLE_FLAG); + + window = SDL_CreateWindow("86Box OpenGL Renderer", 0, 0, resize_info.width, resize_info.height, SDL_WINDOW_OPENGL | SDL_WINDOW_BORDERLESS); + + if (window == NULL) { + pclog("OpenGL: failed to create OpenGL window.\n"); + opengl_fail(); + } + + /* Keep track of certain parameters, only changed in this thread to avoid race conditions */ + int fullscreen = resize_info.fullscreen; + int video_width = INIT_WIDTH; + int video_height = INIT_HEIGHT; + int output_width = resize_info.width; + int output_height = resize_info.height; + int frametime = options.frametime; + + SDL_SysWMinfo wmi = { 0 }; + SDL_VERSION(&wmi.version); + SDL_GetWindowWMInfo(window, &wmi); + + if (wmi.subsystem != SDL_SYSWM_WINDOWS) { + pclog("OpenGL: subsystem is not SDL_SYSWM_WINDOWS.\n"); + opengl_fail(); + } + + window_hwnd = wmi.info.win.window; + + if (!fullscreen) + set_parent_binding(1); + else + SDL_SetWindowFullscreen(window, SDL_WINDOW_FULLSCREEN_DESKTOP); + + SDL_GLContext context = SDL_GL_CreateContext(window); + + if (context == NULL) { + pclog("OpenGL: failed to create OpenGL context.\n"); + opengl_fail(); + } + + SDL_GL_SetSwapInterval(options.vsync); + + if (!gladLoadGLLoader(SDL_GL_GetProcAddress)) { + pclog("OpenGL: failed to set OpenGL loader.\n"); + SDL_GL_DeleteContext(context); + opengl_fail(); + } + + if (GLAD_GL_ARB_debug_output && log_path[0] != '\0') { + glEnable(GL_DEBUG_OUTPUT_SYNCHRONOUS_ARB); + glDebugMessageControlARB(GL_DONT_CARE, GL_DEBUG_TYPE_PERFORMANCE_ARB, GL_DONT_CARE, 0, 0, GL_FALSE); + glDebugMessageCallbackARB(opengl_debugmsg_callback, NULL); + } + + pclog("OpenGL vendor: %s\n", glGetString(GL_VENDOR)); + pclog("OpenGL renderer: %s\n", glGetString(GL_RENDERER)); + pclog("OpenGL version: %s\n", glGetString(GL_VERSION)); + pclog("OpenGL shader language version: %s\n", glGetString(GL_SHADING_LANGUAGE_VERSION)); + + /* Check that the driver actually reports version 3.0 or later */ + GLint major = -1; + glGetIntegerv(GL_MAJOR_VERSION, &major); + if (major < 3) { + pclog("OpenGL: Minimum OpenGL version 3.0 is required.\n"); + SDL_GL_DeleteContext(context); + opengl_fail(); + } + + /* Check if errors have been generated at this point */ + GLenum gl_error = glGetError(); + if (gl_error != GL_NO_ERROR) { + /* Log up to 10 errors */ + int i = 0; + do { + pclog("OpenGL: Error %u\n", gl_error); + i++; + } while ((gl_error = glGetError()) != GL_NO_ERROR && i < 10); + + SDL_GL_DeleteContext(context); + opengl_fail(); + } + + gl_identifiers gl = { 0 }; + + if (!initialize_glcontext(&gl)) { + pclog("OpenGL: failed to initialize.\n"); + finalize_glcontext(&gl); + SDL_GL_DeleteContext(context); + opengl_fail(); + } + + if (gl.frame_count != -1) + glUniform1i(gl.frame_count, 0); + if (gl.output_size != -1) + glUniform2f(gl.output_size, output_width, output_height); + + uint32_t last_swap = plat_get_micro_ticks() - frametime; + + int read_pos = 0; /* Buffer index of next read operation. */ + + /* Render loop */ + int closing = 0; + while (!closing) { + /* Rendering is done right after handling an event. */ + if (frametime < 0) + render_and_swap(&gl); + + DWORD wait_result = WAIT_TIMEOUT; + + do { + /* Rendering is timed by frame capping. */ + if (frametime >= 0) { + uint32_t ticks = plat_get_micro_ticks(); + + uint32_t elapsed = ticks - last_swap; + + if (elapsed + 1000 > frametime) { + /* Spin the remaining time (< 1ms) to next frame */ + while (elapsed < frametime) { + Sleep(0); /* Yield processor time */ + ticks = plat_get_micro_ticks(); + elapsed = ticks - last_swap; + } + + render_and_swap(&gl); + last_swap = ticks; + } + } + + if (GLAD_GL_ARB_sync) { + /* Check if commands that use buffers have been completed. */ + for (int i = 0; i < BUFFERCOUNT; i++) { + if (blit_info[i].sync != NULL && glClientWaitSync(blit_info[i].sync, GL_SYNC_FLUSH_COMMANDS_BIT, 0) != GL_TIMEOUT_EXPIRED) { + glDeleteSync(blit_info[i].sync); + blit_info[i].sync = NULL; + atomic_flag_clear(&blit_info[i].in_use); + } + } + } + + /* Handle window messages */ + MSG msg; + while (PeekMessage(&msg, NULL, 0, 0, PM_REMOVE)) { + if (msg.hwnd != window_hwnd || !handle_window_messages(msg.message, msg.wParam, msg.lParam, fullscreen)) { + TranslateMessage(&msg); + DispatchMessage(&msg); + } + } + + /* Wait for synchronized events for 1ms before going back to window events */ + wait_result = WaitForMultipleObjects(sizeof(sync_objects) / sizeof(HANDLE), sync_objects.asArray, FALSE, 1); + + } while (wait_result == WAIT_TIMEOUT); + + const HANDLE sync_event = sync_objects.asArray[wait_result - WAIT_OBJECT_0]; + + if (sync_event == sync_objects.closing) { + closing = 1; + } else if (sync_event == sync_objects.blit_waiting) { + blit_info_t *info = &blit_info[read_pos]; + + if (video_width != info->w || video_height != info->h) { + video_width = info->w; + video_height = info->h; + + /* Resize the texture */ + glBindBuffer(GL_PIXEL_UNPACK_BUFFER, 0); + glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, video_width, video_height, 0, GL_BGRA, GL_UNSIGNED_INT_8_8_8_8_REV, NULL); + glBindBuffer(GL_PIXEL_UNPACK_BUFFER, gl.unpackBufferID); + + if (fullscreen) + SetEvent(sync_objects.resize); + } + + if (!GLAD_GL_ARB_buffer_storage) { + /* Fallback method, copy data to pixel buffer. */ + glBufferSubData(GL_PIXEL_UNPACK_BUFFER, BUFFERBYTES * read_pos, info->h * ROW_LENGTH * sizeof(uint32_t), info->buffer); + } + + /* Update texture from pixel buffer. */ + glPixelStorei(GL_UNPACK_SKIP_PIXELS, BUFFERPIXELS * read_pos); + glPixelStorei(GL_UNPACK_ROW_LENGTH, ROW_LENGTH); + glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, info->w, info->h, GL_BGRA, GL_UNSIGNED_INT_8_8_8_8_REV, NULL); + + if (GLAD_GL_ARB_sync) { + /* Add fence to track when above gl commands are complete. */ + info->sync = glFenceSync(GL_SYNC_GPU_COMMANDS_COMPLETE, 0); + } else { + /* No sync objects; block until commands are complete. */ + glFinish(); + atomic_flag_clear(&info->in_use); + } + + read_pos = (read_pos + 1) % BUFFERCOUNT; + + /* Update uniforms */ + if (gl.input_size != -1) + glUniform2f(gl.input_size, video_width, video_height); + if (gl.texture_size != -1) + glUniform2f(gl.texture_size, video_width, video_height); + } else if (sync_event == sync_objects.resize) { + thread_wait_mutex(resize_info.mutex); + + if (fullscreen != resize_info.fullscreen) { + fullscreen = resize_info.fullscreen; + + set_parent_binding(!fullscreen); + + SDL_SetWindowFullscreen(window, fullscreen ? SDL_WINDOW_FULLSCREEN_DESKTOP : 0); + + if (fullscreen) { + SetForegroundWindow(window_hwnd); + SetFocus(window_hwnd); + + /* Clip cursor to prevent it moving to another monitor. */ + RECT rect; + GetWindowRect(window_hwnd, &rect); + ClipCursor(&rect); + } else + ClipCursor(NULL); + } + + if (fullscreen) { + int width; + int height; + int pad_x = 0; + int pad_y = 0; + int px_size = 1; + float ratio = 0; + const float ratio43 = 4.f / 3.f; + + SDL_GetWindowSize(window, &width, &height); + + if (video_width > 0 && video_height > 0) { + switch (resize_info.scaling_mode) { + case FULLSCR_SCALE_INT: + px_size = max(min(width / video_width, height / video_height), 1); + + pad_x = width - (video_width * px_size); + pad_y = height - (video_height * px_size); + break; + + case FULLSCR_SCALE_KEEPRATIO: + ratio = (float) video_width / (float) video_height; + case FULLSCR_SCALE_43: + if (ratio == 0) + ratio = ratio43; + if (ratio < ((float) width / (float) height)) + pad_x = width - (int) roundf((float) height * ratio); + else + pad_y = height - (int) roundf((float) width / ratio); + break; + + case FULLSCR_SCALE_FULL: + default: + break; + } + } + + output_width = width - pad_x; + output_height = height - pad_y; + + glViewport(pad_x / 2, pad_y / 2, output_width, output_height); + + if (gl.output_size != -1) + glUniform2f(gl.output_size, output_width, output_height); + } else { + SDL_SetWindowSize(window, resize_info.width, resize_info.height); + + /* SWP_NOZORDER is needed for child window and SDL doesn't enable it. */ + SetWindowPos(window_hwnd, parent, 0, 0, resize_info.width, resize_info.height, SWP_NOZORDER | SWP_NOCOPYBITS | SWP_NOMOVE | SWP_NOACTIVATE); + + output_width = resize_info.width; + output_height = resize_info.height; + + glViewport(0, 0, resize_info.width, resize_info.height); + + if (gl.output_size != -1) + glUniform2f(gl.output_size, resize_info.width, resize_info.height); + } + + thread_release_mutex(resize_info.mutex); + } else if (sync_event == sync_objects.reload) { + thread_wait_mutex(options.mutex); + + frametime = options.frametime; + + SDL_GL_SetSwapInterval(options.vsync); + + if (options.shaderfile_changed) { + /* Change shader program. */ + apply_shaders(&gl); - CoUninitialize(); + /* Uniforms need to be updated after proram change. */ + if (gl.input_size != -1) + glUniform2f(gl.input_size, video_width, video_height); + if (gl.output_size != -1) + glUniform2f(gl.output_size, output_width, output_height); + if (gl.texture_size != -1) + glUniform2f(gl.texture_size, video_width, video_height); + if (gl.frame_count != -1) + glUniform1i(gl.frame_count, 0); + + options.shaderfile_changed = 0; + } + + if (options.filter_changed) { + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, options.filter ? GL_LINEAR : GL_NEAREST); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, options.filter ? GL_LINEAR : GL_NEAREST); + + options.filter_changed = 0; + } + + thread_release_mutex(options.mutex); + } + + /* Keep cursor hidden in full screen and mouse capture */ + int show_cursor = !(fullscreen || !!mouse_capture); + if (SDL_ShowCursor(-1) != show_cursor) + SDL_ShowCursor(show_cursor); + } + + if (GLAD_GL_ARB_sync) { + for (int i = 0; i < BUFFERCOUNT; i++) { + if (blit_info[i].sync != NULL) + glDeleteSync(blit_info[i].sync); + } + } + + finalize_glcontext(&gl); + + SDL_GL_DeleteContext(context); + + set_parent_binding(0); + + SDL_DestroyWindow(window); + + window = NULL; + + CoUninitialize(); } -static void opengl_blit(int x, int y, int w, int h) +static void +opengl_blit(int x, int y, int w, int h, int monitor_index) { - int row; + if ((x < 0) || (y < 0) || (w <= 0) || (h <= 0) || (w > 2048) || (h > 2048) || (buffer32 == NULL) || (thread == NULL) || atomic_flag_test_and_set(&blit_info[write_pos].in_use) || monitor_index >= 1) { + video_blit_complete_monitor(monitor_index); + return; + } - if ((x < 0) || (y < 0) || (w <= 0) || (h <= 0) || (w > 2048) || (h > 2048) || (buffer32 == NULL) || (thread == NULL) || - atomic_flag_test_and_set(&blit_info[write_pos].in_use)) - { - video_blit_complete(); - return; - } + for (int row = 0; row < h; ++row) + video_copy(&(((uint8_t *) blit_info[write_pos].buffer)[row * ROW_LENGTH * sizeof(uint32_t)]), &(buffer32->line[y + row][x]), w * sizeof(uint32_t)); - for (row = 0; row < h; ++row) - video_copy(&(((uint8_t *) blit_info[write_pos].buffer)[row * ROW_LENGTH * sizeof(uint32_t)]), &(buffer32->line[y + row][x]), w * sizeof(uint32_t)); + if (monitors[0].mon_screenshots) + video_screenshot(blit_info[write_pos].buffer, 0, 0, ROW_LENGTH); - if (screenshots) - video_screenshot(blit_info[write_pos].buffer, 0, 0, ROW_LENGTH); + video_blit_complete(); - video_blit_complete(); + blit_info[write_pos].w = w; + blit_info[write_pos].h = h; - blit_info[write_pos].w = w; - blit_info[write_pos].h = h; + write_pos = (write_pos + 1) % BUFFERCOUNT; - write_pos = (write_pos + 1) % BUFFERCOUNT; - - ReleaseSemaphore(sync_objects.blit_waiting, 1, NULL); + ReleaseSemaphore(sync_objects.blit_waiting, 1, NULL); } -static int framerate_to_frametime(int framerate) +static int +framerate_to_frametime(int framerate) { - if (framerate < 0) - return -1; + if (framerate < 0) + return -1; - return (int)ceilf(1.e6f / (float)framerate); + return (int) ceilf(1.e6f / (float) framerate); } -int opengl_init(HWND hwnd) +int +opengl_init(HWND hwnd) { - if (thread != NULL) - return 0; + if (thread != NULL) + return 0; - for (int i = 0; i < sizeof(sync_objects) / sizeof(HANDLE); i++) - sync_objects.asArray[i] = CreateEvent(NULL, FALSE, FALSE, NULL); + for (int i = 0; i < sizeof(sync_objects) / sizeof(HANDLE); i++) + sync_objects.asArray[i] = CreateEvent(NULL, FALSE, FALSE, NULL); - sync_objects.closing = CreateEvent(NULL, FALSE, FALSE, NULL); - sync_objects.resize = CreateEvent(NULL, FALSE, FALSE, NULL); - sync_objects.reload = CreateEvent(NULL, FALSE, FALSE, NULL); - sync_objects.blit_waiting = CreateSemaphore(NULL, 0, BUFFERCOUNT * 2, NULL); + sync_objects.closing = CreateEvent(NULL, FALSE, FALSE, NULL); + sync_objects.resize = CreateEvent(NULL, FALSE, FALSE, NULL); + sync_objects.reload = CreateEvent(NULL, FALSE, FALSE, NULL); + sync_objects.blit_waiting = CreateSemaphore(NULL, 0, BUFFERCOUNT * 2, NULL); - parent = hwnd; - - RECT parent_size; + parent = hwnd; - GetWindowRect(parent, &parent_size); + RECT parent_size; - resize_info.width = parent_size.right - parent_size.left; - resize_info.height = parent_size.bottom - parent_size.top; - resize_info.fullscreen = video_fullscreen & 1; - resize_info.scaling_mode = video_fullscreen_scale; - resize_info.mutex = thread_create_mutex(); + GetWindowRect(parent, &parent_size); - options.vsync = video_vsync; - options.frametime = framerate_to_frametime(video_framerate); - strcpy_s(options.shaderfile, sizeof(options.shaderfile), video_shader); - options.shaderfile_changed = 0; - options.filter = video_filter_method; - options.filter_changed = 0; - options.mutex = thread_create_mutex(); + resize_info.width = parent_size.right - parent_size.left; + resize_info.height = parent_size.bottom - parent_size.top; + resize_info.fullscreen = video_fullscreen & 1; + resize_info.scaling_mode = video_fullscreen_scale; + resize_info.mutex = thread_create_mutex(); - blit_info = (blit_info_t*)malloc(BUFFERCOUNT * sizeof(blit_info_t)); - memset(blit_info, 0, BUFFERCOUNT * sizeof(blit_info_t)); + options.vsync = video_vsync; + options.frametime = framerate_to_frametime(video_framerate); + strcpy_s(options.shaderfile, sizeof(options.shaderfile), video_shader); + options.shaderfile_changed = 0; + options.filter = video_filter_method; + options.filter_changed = 0; + options.mutex = thread_create_mutex(); - /* Buffers are not yet allocated, set them as in use. */ - for (int i = 0; i < BUFFERCOUNT; i++) - atomic_flag_test_and_set(&blit_info[i].in_use); + blit_info = (blit_info_t *) malloc(BUFFERCOUNT * sizeof(blit_info_t)); + memset(blit_info, 0, BUFFERCOUNT * sizeof(blit_info_t)); - write_pos = 0; + /* Buffers are not yet allocated, set them as in use. */ + for (int i = 0; i < BUFFERCOUNT; i++) + atomic_flag_test_and_set(&blit_info[i].in_use); - thread = thread_create(opengl_main, (void*)NULL); + write_pos = 0; - atexit(opengl_close); + thread = thread_create(opengl_main, NULL); - video_setblit(opengl_blit); + atexit(opengl_close); - return 1; + video_setblit(opengl_blit); + + return 1; } -int opengl_pause(void) +int +opengl_pause(void) { - return 0; + return 0; } -void opengl_close(void) +void +opengl_close(void) { - if (thread == NULL) - return; + if (thread == NULL) + return; - SetEvent(sync_objects.closing); + SetEvent(sync_objects.closing); - thread_wait(thread); + thread_wait(thread); - thread_close_mutex(resize_info.mutex); - thread_close_mutex(options.mutex); + thread_close_mutex(resize_info.mutex); + thread_close_mutex(options.mutex); - thread = NULL; + thread = NULL; - free(blit_info); + free(blit_info); - for (int i = 0; i < sizeof(sync_objects) / sizeof(HANDLE); i++) - { - CloseHandle(sync_objects.asArray[i]); - sync_objects.asArray[i] = (HANDLE)NULL; - } + for (int i = 0; i < sizeof(sync_objects) / sizeof(HANDLE); i++) { + CloseHandle(sync_objects.asArray[i]); + sync_objects.asArray[i] = NULL; + } - parent = NULL; + parent = NULL; } -void opengl_set_fs(int fs) +void +opengl_set_fs(int fs) { - if (thread == NULL) - return; + if (thread == NULL) + return; - thread_wait_mutex(resize_info.mutex); - - resize_info.fullscreen = fs; - resize_info.scaling_mode = video_fullscreen_scale; + thread_wait_mutex(resize_info.mutex); - thread_release_mutex(resize_info.mutex); + resize_info.fullscreen = fs; + resize_info.scaling_mode = video_fullscreen_scale; - SetEvent(sync_objects.resize); + thread_release_mutex(resize_info.mutex); + + SetEvent(sync_objects.resize); } -void opengl_resize(int w, int h) +void +opengl_resize(int w, int h) { - if (thread == NULL) - return; + if (thread == NULL) + return; - thread_wait_mutex(resize_info.mutex); + thread_wait_mutex(resize_info.mutex); - resize_info.width = w; - resize_info.height = h; - resize_info.scaling_mode = video_fullscreen_scale; + resize_info.width = w; + resize_info.height = h; + resize_info.scaling_mode = video_fullscreen_scale; - thread_release_mutex(resize_info.mutex); + thread_release_mutex(resize_info.mutex); - SetEvent(sync_objects.resize); + SetEvent(sync_objects.resize); } -void opengl_reload(void) +void +opengl_reload(void) { - if (thread == NULL) - return; + if (thread == NULL) + return; - thread_wait_mutex(options.mutex); + thread_wait_mutex(options.mutex); - options.vsync = video_vsync; - options.frametime = framerate_to_frametime(video_framerate); - - if (strcmp(video_shader, options.shaderfile) != 0) - { - strcpy_s(options.shaderfile, sizeof(options.shaderfile), video_shader); - options.shaderfile_changed = 1; - } + options.vsync = video_vsync; + options.frametime = framerate_to_frametime(video_framerate); - if (video_filter_method != options.filter) - { - options.filter = video_filter_method; - options.filter_changed = 1; - } + if (strcmp(video_shader, options.shaderfile) != 0) { + strcpy_s(options.shaderfile, sizeof(options.shaderfile), video_shader); + options.shaderfile_changed = 1; + } - thread_release_mutex(options.mutex); + if (video_filter_method != options.filter) { + options.filter = video_filter_method; + options.filter_changed = 1; + } - SetEvent(sync_objects.reload); -} \ No newline at end of file + thread_release_mutex(options.mutex); + + SetEvent(sync_objects.reload); +} diff --git a/src/win/win_opengl_glslp.c b/src/win/win_opengl_glslp.c index 0537da899..9689f3ab2 100644 --- a/src/win/win_opengl_glslp.c +++ b/src/win/win_opengl_glslp.c @@ -1,19 +1,21 @@ /* - * 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. + * 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. + * This file is part of the 86Box distribution. * - * File parser for .glslp and .glsl shader files - * in the format of libretro. + * File parser for .glslp and .glsl shader files + * in the format of libretro. * - * TODO: Read .glslp files for multipass shaders and settings. + * TODO: Read .glslp files for multipass shaders and settings. * - * Authors: Teemu Korhonen * - * Copyright 2021 Teemu Korhonen + * + * Authors: Teemu Korhonen + * + * Copyright 2021 Teemu Korhonen * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License @@ -40,233 +42,229 @@ #include <86box/plat.h> #include <86box/win_opengl_glslp.h> - /** - * @brief Default vertex shader. +/** + * @brief Default vertex shader. */ -static const GLchar* vertex_shader = "#version 130\n\ +static const GLchar *vertex_shader = "#version 130\n\ in vec2 VertexCoord;\n\ in vec2 TexCoord;\n\ out vec2 tex;\n\ void main(){\n\ - gl_Position = vec4(VertexCoord, 0.0, 1.0);\n\ - tex = TexCoord;\n\ + gl_Position = vec4(VertexCoord, 0.0, 1.0);\n\ + tex = TexCoord;\n\ }\n"; /** * @brief Default fragment shader. */ -static const GLchar* fragment_shader = "#version 130\n\ +static const GLchar *fragment_shader = "#version 130\n\ in vec2 tex;\n\ uniform sampler2D texsampler;\n\ out vec4 color;\n\ void main() {\n\ - color = texture(texsampler, tex);\n\ + color = texture(texsampler, tex);\n\ }\n"; /** * @brief OpenGL shader program build targets -*/ -typedef enum -{ - OPENGL_BUILD_TARGET_VERTEX, - OPENGL_BUILD_TARGET_FRAGMENT, - OPENGL_BUILD_TARGET_LINK + */ +typedef enum { + OPENGL_BUILD_TARGET_VERTEX, + OPENGL_BUILD_TARGET_FRAGMENT, + OPENGL_BUILD_TARGET_LINK } opengl_build_target_t; /** * @brief Reads a whole file into a null terminated string. * @param Path Path to the file relative to executable path. * @return Pointer to the string or NULL on error. Remember to free() after use. -*/ -static char* read_file_to_string(const char* path) + */ +static char * +read_file_to_string(const char *path) { - FILE* file_handle = plat_fopen(path, "rb"); + FILE *fp = plat_fopen(path, "rb"); - if (file_handle != NULL) - { - /* get file size */ - fseek(file_handle, 0, SEEK_END); - - size_t file_size = (size_t)ftell(file_handle); - - fseek(file_handle, 0, SEEK_SET); + if (fp != NULL) { + /* get file size */ + fseek(fp, 0, SEEK_END); - /* read to buffer and close */ - char* content = (char*)malloc(sizeof(char) * (file_size + 1)); + size_t file_size = (size_t) ftell(fp); - if (!content) - return NULL; + fseek(fp, 0, SEEK_SET); - size_t length = fread(content, sizeof(char), file_size, file_handle); + /* read to buffer and close */ + char *content = (char *) malloc(sizeof(char) * (file_size + 1)); - fclose(file_handle); + if (!content) + return NULL; - content[length] = 0; + size_t length = fread(content, sizeof(char), file_size, fp); - return content; - } - return NULL; + fclose(fp); + + content[length] = 0; + + return content; + } + return NULL; } -static int check_status(GLuint id, opengl_build_target_t build_target, const char* shader_path) +static int +check_status(GLuint id, opengl_build_target_t build_target, const char *shader_path) { - GLint status = GL_FALSE; + GLint status = GL_FALSE; - if (build_target != OPENGL_BUILD_TARGET_LINK) - glGetShaderiv(id, GL_COMPILE_STATUS, &status); - else - glGetProgramiv(id, GL_LINK_STATUS, &status); + if (build_target != OPENGL_BUILD_TARGET_LINK) + glGetShaderiv(id, GL_COMPILE_STATUS, &status); + else + glGetProgramiv(id, GL_LINK_STATUS, &status); - if (status == GL_FALSE) - { - int info_log_length; + if (status == GL_FALSE) { + int info_log_length; - if (build_target != OPENGL_BUILD_TARGET_LINK) - glGetShaderiv(id, GL_INFO_LOG_LENGTH, &info_log_length); - else - glGetProgramiv(id, GL_INFO_LOG_LENGTH, &info_log_length); + if (build_target != OPENGL_BUILD_TARGET_LINK) + glGetShaderiv(id, GL_INFO_LOG_LENGTH, &info_log_length); + else + glGetProgramiv(id, GL_INFO_LOG_LENGTH, &info_log_length); - GLchar* info_log_text = (GLchar*)malloc(sizeof(GLchar) * info_log_length); + GLchar *info_log_text = (GLchar *) malloc(sizeof(GLchar) * info_log_length); - if (build_target != OPENGL_BUILD_TARGET_LINK) - glGetShaderInfoLog(id, info_log_length, NULL, info_log_text); - else - glGetProgramInfoLog(id, info_log_length, NULL, info_log_text); + if (build_target != OPENGL_BUILD_TARGET_LINK) + glGetShaderInfoLog(id, info_log_length, NULL, info_log_text); + else + glGetProgramInfoLog(id, info_log_length, NULL, info_log_text); - const char* reason = NULL; + const char *reason = NULL; - switch (build_target) - { - case OPENGL_BUILD_TARGET_VERTEX: - reason = "compiling vertex shader"; - break; - case OPENGL_BUILD_TARGET_FRAGMENT: - reason = "compiling fragment shader"; - break; - case OPENGL_BUILD_TARGET_LINK: - reason = "linking shader program"; - break; - } + switch (build_target) { + case OPENGL_BUILD_TARGET_VERTEX: + reason = "compiling vertex shader"; + break; + case OPENGL_BUILD_TARGET_FRAGMENT: + reason = "compiling fragment shader"; + break; + case OPENGL_BUILD_TARGET_LINK: + reason = "linking shader program"; + break; + } - /* Shader compilation log can be lengthy, mark begin and end */ - const char* line = "--------------------"; + /* Shader compilation log can be lengthy, mark begin and end */ + const char *line = "--------------------"; - pclog("OpenGL: Error when %s in %s:\n%sBEGIN%s\n%s\n%s END %s\n", reason, shader_path, line, line, info_log_text, line, line); + pclog("OpenGL: Error when %s in %s:\n%sBEGIN%s\n%s\n%s END %s\n", reason, shader_path, line, line, info_log_text, line, line); - free(info_log_text); + free(info_log_text); - return 0; - } + return 0; + } - return 1; + return 1; } /** * @brief Compile custom shaders into a program. * @return Shader program identifier. -*/ -GLuint load_custom_shaders(const char* path) + */ +GLuint +load_custom_shaders(const char *path) { - char* shader = read_file_to_string(path); + char *shader = read_file_to_string(path); - if (shader != NULL) - { - int success = 1; + if (shader != NULL) { + int success = 1; - const char* vertex_sources[3] = { "#version 130\n", "#define VERTEX\n", shader }; - const char* fragment_sources[3] = { "#version 130\n", "#define FRAGMENT\n", shader }; + const char *vertex_sources[3] = { "#version 130\n", "#define VERTEX\n", shader }; + const char *fragment_sources[3] = { "#version 130\n", "#define FRAGMENT\n", shader }; - /* Check if the shader program defines version directive */ - char* version_start = strstr(shader, "#version"); + /* Check if the shader program defines version directive */ + char *version_start = strstr(shader, "#version"); - /* If the shader program contains a version directive, - it must be captured and placed as the first statement. */ - if (version_start != NULL) - { - /* Version directive found, search the line end */ - char* version_end = strchr(version_start, '\n'); + /* If the shader program contains a version directive, + it must be captured and placed as the first statement. */ + if (version_start != NULL) { + /* Version directive found, search the line end */ + const char *version_end = strchr(version_start, '\n'); - if (version_end != NULL) - { - char version[30] = ""; + if (version_end != NULL) { + char version[30] = ""; - size_t version_len = MIN(version_end - version_start + 1, 29); + size_t version_len = MIN(version_end - version_start + 1, 29); - strncat(version, version_start, version_len); + strncat(version, version_start, version_len); - /* replace the default version directive */ - vertex_sources[0] = version; - fragment_sources[0] = version; - } + /* replace the default version directive */ + vertex_sources[0] = version; + fragment_sources[0] = version; + } - /* Comment out the original version directive - as only one is allowed. */ - memset(version_start, '/', 2); - } + /* Comment out the original version directive + as only one is allowed. */ + memset(version_start, '/', 2); + } - GLuint vertex_id = glCreateShader(GL_VERTEX_SHADER); - GLuint fragment_id = glCreateShader(GL_FRAGMENT_SHADER); + GLuint vertex_id = glCreateShader(GL_VERTEX_SHADER); + GLuint fragment_id = glCreateShader(GL_FRAGMENT_SHADER); - glShaderSource(vertex_id, 3, vertex_sources, NULL); - glCompileShader(vertex_id); - success *= check_status(vertex_id, OPENGL_BUILD_TARGET_VERTEX, path); + glShaderSource(vertex_id, 3, vertex_sources, NULL); + glCompileShader(vertex_id); + success *= check_status(vertex_id, OPENGL_BUILD_TARGET_VERTEX, path); - glShaderSource(fragment_id, 3, fragment_sources, NULL); - glCompileShader(fragment_id); - success *= check_status(fragment_id, OPENGL_BUILD_TARGET_FRAGMENT, path); + glShaderSource(fragment_id, 3, fragment_sources, NULL); + glCompileShader(fragment_id); + success *= check_status(fragment_id, OPENGL_BUILD_TARGET_FRAGMENT, path); - free(shader); + free(shader); - GLuint prog_id = 0; + GLuint prog_id = 0; - if (success) - { - prog_id = glCreateProgram(); + if (success) { + prog_id = glCreateProgram(); - glAttachShader(prog_id, vertex_id); - glAttachShader(prog_id, fragment_id); - glLinkProgram(prog_id); - check_status(prog_id, OPENGL_BUILD_TARGET_LINK, path); + glAttachShader(prog_id, vertex_id); + glAttachShader(prog_id, fragment_id); + glLinkProgram(prog_id); + check_status(prog_id, OPENGL_BUILD_TARGET_LINK, path); - glDetachShader(prog_id, vertex_id); - glDetachShader(prog_id, fragment_id); - } + glDetachShader(prog_id, vertex_id); + glDetachShader(prog_id, fragment_id); + } - glDeleteShader(vertex_id); - glDeleteShader(fragment_id); + glDeleteShader(vertex_id); + glDeleteShader(fragment_id); - return prog_id; - } - return 0; + return prog_id; + } + return 0; } /** * @brief Compile default shaders into a program. * @return Shader program identifier. -*/ -GLuint load_default_shaders() + */ +GLuint +load_default_shaders(void) { - GLuint vertex_id = glCreateShader(GL_VERTEX_SHADER); - GLuint fragment_id = glCreateShader(GL_FRAGMENT_SHADER); + GLuint vertex_id = glCreateShader(GL_VERTEX_SHADER); + GLuint fragment_id = glCreateShader(GL_FRAGMENT_SHADER); - glShaderSource(vertex_id, 1, &vertex_shader, NULL); - glCompileShader(vertex_id); + glShaderSource(vertex_id, 1, &vertex_shader, NULL); + glCompileShader(vertex_id); - glShaderSource(fragment_id, 1, &fragment_shader, NULL); - glCompileShader(fragment_id); + glShaderSource(fragment_id, 1, &fragment_shader, NULL); + glCompileShader(fragment_id); - GLuint prog_id = glCreateProgram(); + GLuint prog_id = glCreateProgram(); - glAttachShader(prog_id, vertex_id); - glAttachShader(prog_id, fragment_id); + glAttachShader(prog_id, vertex_id); + glAttachShader(prog_id, fragment_id); - glLinkProgram(prog_id); + glLinkProgram(prog_id); - glDetachShader(prog_id, vertex_id); - glDetachShader(prog_id, fragment_id); + glDetachShader(prog_id, vertex_id); + glDetachShader(prog_id, fragment_id); - glDeleteShader(vertex_id); - glDeleteShader(fragment_id); + glDeleteShader(vertex_id); + glDeleteShader(fragment_id); - return prog_id; -} \ No newline at end of file + return prog_id; +} diff --git a/src/win/win_preferences.c b/src/win/win_preferences.c index 0c3e95892..ee93321a8 100644 --- a/src/win/win_preferences.c +++ b/src/win/win_preferences.c @@ -1,17 +1,19 @@ /* - * 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. + * 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. + * This file is part of the 86Box distribution. * - * Handle the dialog for changing the program's language and other global settings. + * Handle the dialog for changing the program's language and other global settings. * * - * Authors: Laci bá' * - * Copyright 2021 Laci bá' + * Authors: Laci bá' + * + * Copyright 2021 Laci bá' + * Copyright 2021-2023 Jasmine Iwanek. */ #define UNICODE #define BITMAP WINDOWS_BITMAP @@ -35,121 +37,119 @@ /* Language */ static LCID temp_language; -static char temp_icon_set[256] = {0}; +static char temp_icon_set[256] = { 0 }; -int enum_helper, c; +int enum_helper; +int c; HWND hwndPreferences; -BOOL CALLBACK -EnumResLangProc(HMODULE hModule, LPCTSTR lpszType, LPCTSTR lpszName, WORD wIDLanguage, LONG_PTR lParam) +BOOL CALLBACK +EnumResLangProc(UNUSED(HMODULE hModule), UNUSED(LPCTSTR lpszType), UNUSED(LPCTSTR lpszName), WORD wIDLanguage, LONG_PTR lParam) { - wchar_t temp[LOCALE_NAME_MAX_LENGTH + 1]; - LCIDToLocaleName(wIDLanguage, temp, LOCALE_NAME_MAX_LENGTH, 0); - wchar_t dispname[MAX_PATH + 1]; - GetLocaleInfoEx(temp, LOCALE_SENGLISHDISPLAYNAME, dispname, MAX_PATH); - SendMessage((HWND)lParam, CB_ADDSTRING, 0, (LPARAM)dispname); - SendMessage((HWND)lParam, CB_SETITEMDATA, c, (LPARAM)wIDLanguage); - - if (wIDLanguage == lang_id) - enum_helper = c; - c++; - - return 1; + wchar_t temp[LOCALE_NAME_MAX_LENGTH + 1]; + LCIDToLocaleName(wIDLanguage, temp, LOCALE_NAME_MAX_LENGTH, 0); + wchar_t dispname[MAX_PATH + 1]; + GetLocaleInfoEx(temp, LOCALE_SENGLISHDISPLAYNAME, dispname, MAX_PATH); + SendMessage((HWND) lParam, CB_ADDSTRING, 0, (LPARAM) dispname); + SendMessage((HWND) lParam, CB_SETITEMDATA, c, (LPARAM) wIDLanguage); + + if (wIDLanguage == lang_id) + enum_helper = c; + c++; + + return 1; } /* Load available languages */ static void preferences_fill_languages(HWND hdlg) { - temp_language = GetThreadUILanguage(); - HWND lang_combo = GetDlgItem(hdlg, IDC_COMBO_LANG); - - SendMessage(lang_combo, CB_RESETCONTENT, 0, 0); - SendMessage(lang_combo, CB_ADDSTRING, 0, win_get_string(IDS_7168)); - SendMessage(lang_combo, CB_SETITEMDATA, 0, 0xFFFF); - - enum_helper = 0; c = 1; - //if no one is selected, then it was 0xFFFF or unsupported language, in either case go with index enum_helper=0 - //also start enum index from c=1 - EnumResourceLanguages(hinstance, RT_MENU, L"MainMenu", &EnumResLangProc, (LPARAM)lang_combo); - - SendMessage(lang_combo, CB_SETCURSEL, enum_helper, 0); + temp_language = GetThreadUILanguage(); + HWND lang_combo = GetDlgItem(hdlg, IDC_COMBO_LANG); + + SendMessage(lang_combo, CB_RESETCONTENT, 0, 0); + SendMessage(lang_combo, CB_ADDSTRING, 0, win_get_string(IDS_7168)); + SendMessage(lang_combo, CB_SETITEMDATA, 0, 0xFFFF); + + enum_helper = 0; + c = 1; + // if no one is selected, then it was 0xFFFF or unsupported language, in either case go with index enum_helper=0 + // also start enum index from c=1 + EnumResourceLanguages(hinstance, RT_MENU, L"MainMenu", &EnumResLangProc, (LPARAM) lang_combo); + + SendMessage(lang_combo, CB_SETCURSEL, enum_helper, 0); } /* Load available iconsets */ static void preferences_fill_iconsets(HWND hdlg) { - HWND icon_combo = GetDlgItem(hdlg, IDC_COMBO_ICON); - - /* Add the default one */ - wchar_t buffer[512] = L"("; - wcscat(buffer, plat_get_string(IDS_2090)); - wcscat(buffer, L")"); - - SendMessage(icon_combo, CB_RESETCONTENT, 0, 0); - SendMessage(icon_combo, CB_ADDSTRING, 0, (LPARAM)buffer); - SendMessage(icon_combo, CB_SETITEMDATA, 0, (LPARAM)strdup("")); - - int combo_index = -1; - - /* Find for extra ones */ - HANDLE hFind; - WIN32_FIND_DATA data; - - char icon_path_root[512]; - win_get_icons_path(icon_path_root); - - wchar_t search[512]; - mbstoc16s(search, icon_path_root, strlen(icon_path_root) + 1); - wcscat(search, L"*.*"); - - hFind = FindFirstFile((LPCWSTR)search, &data); - - if (hFind != INVALID_HANDLE_VALUE) { - do { - if (wcscmp(data.cFileName, L".") && wcscmp(data.cFileName, L"..") && - (data.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)) - { - wchar_t temp[512] = {0}, dispname[512] = {0}; - mbstoc16s(temp, icon_path_root, strlen(icon_path_root) + 1); - wcscat(temp, data.cFileName); - wcscat(temp, L"\\iconinfo.txt"); - - wcscpy(dispname, data.cFileName); - FILE *fp = _wfopen(temp, L"r"); - if (fp) - { - char line[512] = {0}; - if (fgets(line, 511, fp)) - { - mbstoc16s(dispname, line, strlen(line) + 1); - } - - fclose(fp); - } - - char filename[512]; - c16stombs(filename, data.cFileName, 511); - - int index = SendMessage(icon_combo, CB_ADDSTRING, 0, (LPARAM)dispname); - SendMessage(icon_combo, CB_SETITEMDATA, index, (LPARAM)(strdup(filename))); - - if (!strcmp(filename, icon_set)) - combo_index = index; - } - } while (FindNextFile(hFind, &data)); - FindClose(hFind); - } - - if (combo_index == -1) - { - combo_index = 0; - strcpy(temp_icon_set, ""); - } - - SendMessage(icon_combo, CB_SETCURSEL, combo_index, 0); + HWND icon_combo = GetDlgItem(hdlg, IDC_COMBO_ICON); + + /* Add the default one */ + wchar_t buffer[512] = L"("; + wcscat(buffer, plat_get_string(IDS_DEFAULT)); + wcscat(buffer, L")"); + + SendMessage(icon_combo, CB_RESETCONTENT, 0, 0); + SendMessage(icon_combo, CB_ADDSTRING, 0, (LPARAM) buffer); + SendMessage(icon_combo, CB_SETITEMDATA, 0, (LPARAM) strdup("")); + + int combo_index = -1; + + /* Find for extra ones */ + HANDLE hFind; + WIN32_FIND_DATA data; + + char icon_path_root[512]; + win_get_icons_path(icon_path_root); + + wchar_t search[512]; + mbstoc16s(search, icon_path_root, strlen(icon_path_root) + 1); + wcscat(search, L"*.*"); + + hFind = FindFirstFile((LPCWSTR) search, &data); + + if (hFind != INVALID_HANDLE_VALUE) { + do { + if (wcscmp(data.cFileName, L".") && wcscmp(data.cFileName, L"..") && (data.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)) { + wchar_t temp[512] = { 0 }; + wchar_t dispname[512] = { 0 }; + mbstoc16s(temp, icon_path_root, strlen(icon_path_root) + 1); + wcscat(temp, data.cFileName); + wcscat(temp, L"\\iconinfo.txt"); + + wcscpy(dispname, data.cFileName); + FILE *fp = _wfopen(temp, L"r"); + if (fp) { + char line[512] = { 0 }; + if (fgets(line, 511, fp)) { + mbstoc16s(dispname, line, strlen(line) + 1); + } + + fclose(fp); + } + + char filename[512]; + c16stombs(filename, data.cFileName, 511); + + int index = SendMessage(icon_combo, CB_ADDSTRING, 0, (LPARAM) dispname); + SendMessage(icon_combo, CB_SETITEMDATA, index, (LPARAM) (strdup(filename))); + + if (!strcmp(filename, icon_set)) + combo_index = index; + } + } while (FindNextFile(hFind, &data)); + FindClose(hFind); + } + + if (combo_index == -1) { + combo_index = 0; + strcpy(temp_icon_set, ""); + } + + SendMessage(icon_combo, CB_SETCURSEL, combo_index, 0); } /* This returns 1 if any variable has changed, 0 if not. */ @@ -157,30 +157,29 @@ static int preferences_settings_changed(void) { int i = 0; - + /* Language */ i = i || has_language_changed(temp_language); i = i || strcmp(temp_icon_set, icon_set); - + return i; } /* IndexOf by ItemData */ -static int +static int preferences_indexof(HWND combo, LPARAM itemdata) { - int i; - for (i = 0; i < SendMessage(combo, CB_GETCOUNT, 0, 0); i++) + for (int i = 0; i < SendMessage(combo, CB_GETCOUNT, 0, 0); i++) if (SendMessage(combo, CB_GETITEMDATA, i, 0) == itemdata) return i; - + return -1; } /* This saves the settings back to the global variables. */ static void preferences_settings_save(void) -{ +{ /* Language */ set_language(temp_language); @@ -190,13 +189,13 @@ preferences_settings_save(void) /* Update title bar */ update_mouse_msg(); - + /* Update status bar */ - config_changed = 1; + config_changed = 1; ui_sb_set_ready(-1); ui_sb_update_panes(); ui_sb_update_text(); - + /* Save the language changes */ config_save(); } @@ -206,88 +205,86 @@ static LRESULT CALLBACK #else static BOOL CALLBACK #endif -PreferencesDlgProcedure(HWND hdlg, UINT message, WPARAM wParam, LPARAM lParam) +PreferencesDlgProcedure(HWND hdlg, UINT message, WPARAM wParam, UNUSED(LPARAM lParam)) { switch (message) { - case WM_INITDIALOG: - hwndPreferences = hdlg; - /* Language */ - temp_language = lang_id; - strcpy(temp_icon_set, icon_set); - preferences_fill_languages(hdlg); - preferences_fill_iconsets(hdlg); - break; + case WM_INITDIALOG: + hwndPreferences = hdlg; + /* Language */ + temp_language = lang_id; + strcpy(temp_icon_set, icon_set); + preferences_fill_languages(hdlg); + preferences_fill_iconsets(hdlg); + break; - case WM_COMMAND: - switch (LOWORD(wParam)) { - case IDOK: - if (preferences_settings_changed()) - preferences_settings_save(); - EndDialog(hdlg, 0); - return TRUE; + case WM_COMMAND: + switch (LOWORD(wParam)) { + case IDOK: + if (preferences_settings_changed()) + preferences_settings_save(); + EndDialog(hdlg, 0); + return TRUE; - case IDCANCEL: - EndDialog(hdlg, 0); - return TRUE; - - case IDC_COMBO_LANG: - if (HIWORD(wParam) == CBN_SELCHANGE) { - HWND combo = GetDlgItem(hdlg, IDC_COMBO_LANG); - int index = SendMessage(combo, CB_GETCURSEL, 0, 0); - temp_language = SendMessage(combo, CB_GETITEMDATA, index, 0); - } - break; - - case IDC_COMBO_ICON: - if (HIWORD(wParam) == CBN_SELCHANGE) { - HWND combo = GetDlgItem(hdlg, IDC_COMBO_ICON); - int index = SendMessage(combo, CB_GETCURSEL, 0, 0); - strcpy(temp_icon_set, (char*)SendMessage(combo, CB_GETITEMDATA, index, 0)); - } - break; - - case IDC_BUTTON_DEFAULT: { - HWND combo = GetDlgItem(hdlg, IDC_COMBO_LANG); - int index = preferences_indexof(combo, DEFAULT_LANGUAGE); - SendMessage(combo, CB_SETCURSEL, index, 0); - temp_language = DEFAULT_LANGUAGE; - break; - } - - case IDC_BUTTON_DEFICON: { - SendMessage(GetDlgItem(hdlg, IDC_COMBO_ICON), CB_SETCURSEL, 0, 0); - strcpy(temp_icon_set, ""); - break; - } - default: - break; - } - break; - - case WM_DESTROY: { - int i; - LRESULT temp; - HWND combo = GetDlgItem(hdlg, IDC_COMBO_ICON); - for (i = 0; i < SendMessage(combo, CB_GETCOUNT, 0, 0); i++) - { - temp = SendMessage(combo, CB_GETITEMDATA, i, 0); - if (temp) - { - free((void*)temp); - SendMessage(combo, CB_SETITEMDATA, i, 0); - } - } - } - break; - + case IDCANCEL: + EndDialog(hdlg, 0); + return TRUE; + + case IDC_COMBO_LANG: + if (HIWORD(wParam) == CBN_SELCHANGE) { + HWND combo = GetDlgItem(hdlg, IDC_COMBO_LANG); + int index = SendMessage(combo, CB_GETCURSEL, 0, 0); + temp_language = SendMessage(combo, CB_GETITEMDATA, index, 0); + } + break; + + case IDC_COMBO_ICON: + if (HIWORD(wParam) == CBN_SELCHANGE) { + HWND combo = GetDlgItem(hdlg, IDC_COMBO_ICON); + int index = SendMessage(combo, CB_GETCURSEL, 0, 0); + strcpy(temp_icon_set, (char *) SendMessage(combo, CB_GETITEMDATA, index, 0)); + } + break; + + case IDC_BUTTON_DEFAULT: + { + HWND combo = GetDlgItem(hdlg, IDC_COMBO_LANG); + int index = preferences_indexof(combo, DEFAULT_LANGUAGE); + SendMessage(combo, CB_SETCURSEL, index, 0); + temp_language = DEFAULT_LANGUAGE; + break; + } + + case IDC_BUTTON_DEFICON: + { + SendMessage(GetDlgItem(hdlg, IDC_COMBO_ICON), CB_SETCURSEL, 0, 0); + strcpy(temp_icon_set, ""); + break; + } + default: + break; + } + break; + + case WM_DESTROY: + { + LRESULT temp; + HWND combo = GetDlgItem(hdlg, IDC_COMBO_ICON); + for (int i = 0; i < SendMessage(combo, CB_GETCOUNT, 0, 0); i++) { + temp = SendMessage(combo, CB_GETITEMDATA, i, 0); + if (temp) { + free((void *) temp); + SendMessage(combo, CB_SETITEMDATA, i, 0); + } + } + } + break; } - return(FALSE); + return FALSE; } - void PreferencesDlgCreate(HWND hwnd) { - DialogBox(hinstance, (LPCTSTR)DLG_PREFERENCES, hwnd, PreferencesDlgProcedure); + DialogBox(hinstance, (LPCTSTR) DLG_PREFERENCES, hwnd, PreferencesDlgProcedure); } diff --git a/src/win/win_sdl.c b/src/win/win_sdl.c index cd4b26169..ea9c8455d 100644 --- a/src/win/win_sdl.c +++ b/src/win/win_sdl.c @@ -1,42 +1,42 @@ /* - * 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. + * 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. + * This file is part of the 86Box distribution. * - * Rendering module for libSDL2 + * Rendering module for libSDL2 * - * NOTE: Given all the problems reported with FULLSCREEN use of SDL, - * we will not use that, but, instead, use a new window which - * coverrs the entire desktop. + * NOTE: Given all the problems reported with FULLSCREEN use of SDL, + * we will not use that, but, instead, use a new window which + * covers the entire desktop. * * * - * Authors: Fred N. van Kempen, - * Michael Drüing, + * Authors: Fred N. van Kempen, + * Michael Drüing, * - * Copyright 2018-2020 Fred N. van Kempen. - * Copyright 2018-2020 Michael Drüing. + * Copyright 2018-2020 Fred N. van Kempen. + * Copyright 2018-2020 Michael Drüing. * - * Redistribution and use in source and binary forms, with - * or without modification, are permitted provided that the - * following conditions are met: + * Redistribution and use in source and binary forms, with + * or without modification, are permitted provided that the + * following conditions are met: * - * 1. Redistributions of source code must retain the entire - * above notice, this list of conditions and the following - * disclaimer. + * 1. Redistributions of source code must retain the entire + * above notice, this list of conditions and the following + * disclaimer. * - * 2. Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the - * following disclaimer in the documentation and/or other - * materials provided with the distribution. + * 2. Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the + * following disclaimer in the documentation and/or other + * materials provided with the distribution. * - * 3. Neither the name of the copyright holder nor the names - * of its contributors may be used to endorse or promote - * products derived from this software without specific - * prior written permission. + * 3. Neither the name of the copyright holder nor the names + * of its contributors may be used to endorse or promote + * products derived from this software without specific + * prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT @@ -54,6 +54,7 @@ #define WIN32_LEAN_AND_MEAN #include #include +#include #include #include @@ -72,48 +73,51 @@ #include <86box/win_sdl.h> #include <86box/version.h> +#define RENDERER_FULL_SCREEN 1 +#define RENDERER_HARDWARE 2 +#define RENDERER_OPENGL 4 -#define RENDERER_FULL_SCREEN 1 -#define RENDERER_HARDWARE 2 -#define RENDERER_OPENGL 4 - - -static SDL_Window *sdl_win = NULL; -static SDL_Renderer *sdl_render = NULL; -static SDL_Texture *sdl_tex = NULL; -static HWND sdl_parent_hwnd = NULL; -static int sdl_w, sdl_h; -static int sdl_fs, sdl_flags = -1; -static int cur_w, cur_h; -static int cur_wx = 0, cur_wy = 0, cur_ww =0, cur_wh = 0; -static volatile int sdl_enabled = 0; -static SDL_mutex* sdl_mutex = NULL; - +static SDL_Window *sdl_win = NULL; +static SDL_Renderer *sdl_render = NULL; +static SDL_Texture *sdl_tex = NULL; +static HWND sdl_parent_hwnd = NULL; +static int sdl_w; +static int sdl_h; +static int sdl_fs; +static int sdl_flags = -1; +static int cur_w; +static int cur_h; +static int cur_wx = 0; +static int cur_wy = 0; +static int cur_ww = 0; +static int cur_wh = 0; +static volatile int sdl_enabled = 0; +static SDL_mutex *sdl_mutex = NULL; typedef struct { - const void *magic; - Uint32 id; - char *title; + const void *magic; + Uint32 id; + char *title; SDL_Surface *icon; - int x, y; - int w, h; - int min_w, min_h; - int max_w, max_h; - Uint32 flags; - Uint32 last_fullscreen_flags; + int x, y; + int w, h; + int min_w, min_h; + int max_w, max_h; + Uint32 flags; + Uint32 last_fullscreen_flags; /* Stored position and size for windowed mode */ SDL_Rect windowed; SDL_DisplayMode fullscreen_mode; - float brightness; + float brightness; Uint16 *gamma; - Uint16 *saved_gamma; /* (just offset into gamma) */ + Uint16 *saved_gamma; /* (just offset into gamma) */ SDL_Surface *surface; - SDL_bool surface_valid; + SDL_bool surface_valid; SDL_bool is_hiding; SDL_bool is_destroying; @@ -121,7 +125,7 @@ typedef struct void *shaper; SDL_HitTest hit_test; - void *hit_test_data; + void *hit_test_data; void *data; @@ -131,112 +135,116 @@ typedef struct SDL_Window *next; } SDL_Window_Ex; - #ifdef ENABLE_SDL_LOG int sdl_do_log = ENABLE_SDL_LOG; - static void sdl_log(const char *fmt, ...) { va_list ap; if (sdl_do_log) { - va_start(ap, fmt); - pclog_ex(fmt, ap); - va_end(ap); + va_start(ap, fmt); + pclog_ex(fmt, ap); + va_end(ap); } } #else -#define sdl_log(fmt, ...) +# define sdl_log(fmt, ...) #endif - static void sdl_integer_scale(double *d, double *g) { double ratio; if (*d > *g) { - ratio = floor(*d / *g); - *d = *g * ratio; + ratio = floor(*d / *g); + *d = *g * ratio; } else { - ratio = ceil(*d / *g); - *d = *g / ratio; + ratio = ceil(*d / *g); + *d = *g / ratio; } } - static void sdl_stretch(int *w, int *h, int *x, int *y) { - double hw, gw, hh, gh, dx, dy, dw, dh, gsr, hsr; + double hw; + double gw; + double hh; + double gh; + double dx; + double dy; + double dw; + double dh; + double gsr; + double hsr; - hw = (double) sdl_w; - hh = (double) sdl_h; - gw = (double) *w; - gh = (double) *h; + hw = (double) sdl_w; + hh = (double) sdl_h; + gw = (double) *w; + gh = (double) *h; hsr = hw / hh; switch (video_fullscreen_scale) { - case FULLSCR_SCALE_FULL: - default: - *w = sdl_w; - *h = sdl_h; - *x = 0; - *y = 0; - break; - case FULLSCR_SCALE_43: - case FULLSCR_SCALE_KEEPRATIO: - if (video_fullscreen_scale == FULLSCR_SCALE_43) - gsr = 4.0 / 3.0; - else - gsr = gw / gh; - if (gsr <= hsr) { - dw = hh * gsr; - dh = hh; - } else { - dw = hw; - dh = hw / gsr; - } - dx = (hw - dw) / 2.0; - dy = (hh - dh) / 2.0; - *w = (int) dw; - *h = (int) dh; - *x = (int) dx; - *y = (int) dy; - break; - case FULLSCR_SCALE_INT: - gsr = gw / gh; - if (gsr <= hsr) { - dw = hh * gsr; - dh = hh; - } else { - dw = hw; - dh = hw / gsr; - } - sdl_integer_scale(&dw, &gw); - sdl_integer_scale(&dh, &gh); - dx = (hw - dw) / 2.0; - dy = (hh - dh) / 2.0; - *w = (int) dw; - *h = (int) dh; - *x = (int) dx; - *y = (int) dy; - break; + default: + case FULLSCR_SCALE_FULL: + *w = sdl_w; + *h = sdl_h; + *x = 0; + *y = 0; + break; + case FULLSCR_SCALE_43: + case FULLSCR_SCALE_KEEPRATIO: + if (video_fullscreen_scale == FULLSCR_SCALE_43) + gsr = 4.0 / 3.0; + else + gsr = gw / gh; + if (gsr <= hsr) { + dw = hh * gsr; + dh = hh; + } else { + dw = hw; + dh = hw / gsr; + } + dx = (hw - dw) / 2.0; + dy = (hh - dh) / 2.0; + *w = (int) dw; + *h = (int) dh; + *x = (int) dx; + *y = (int) dy; + break; + case FULLSCR_SCALE_INT: + gsr = gw / gh; + if (gsr <= hsr) { + dw = hh * gsr; + dh = hh; + } else { + dw = hw; + dh = hw / gsr; + } + sdl_integer_scale(&dw, &gw); + sdl_integer_scale(&dh, &gh); + dx = (hw - dw) / 2.0; + dy = (hh - dh) / 2.0; + *w = (int) dw; + *h = (int) dh; + *x = (int) dx; + *y = (int) dy; + break; } } - static void -sdl_blit(int x, int y, int w, int h) +sdl_blit(int x, int y, int w, int h, int monitor_index) { SDL_Rect r_src; - int ret; + int ret; - if (!sdl_enabled || (x < 0) || (y < 0) || (w <= 0) || (h <= 0) || (w > 2048) || (h > 2048) || (buffer32 == NULL) || (sdl_render == NULL) || (sdl_tex == NULL)) { - video_blit_complete(); - return; + if (!sdl_enabled || (x < 0) || (y < 0) || (w <= 0) || (h <= 0) || (w > 2048) || (h > 2048) || (buffer32 == NULL) || (sdl_render == NULL) || (sdl_tex == NULL) || monitor_index >= 1) { + video_blit_complete_monitor(monitor_index); + return; } SDL_LockMutex(sdl_mutex); @@ -247,8 +255,8 @@ sdl_blit(int x, int y, int w, int h) r_src.h = h; SDL_UpdateTexture(sdl_tex, &r_src, &(buffer32->line[y][x]), 2048 * sizeof(uint32_t)); - if (screenshots) - video_screenshot((uint32_t *) buffer32->dat, x, y, 2048); + if (monitors[0].mon_screenshots) + video_screenshot(buffer32->dat, x, y, 2048); video_blit_complete(); @@ -261,35 +269,34 @@ sdl_blit(int x, int y, int w, int h) ret = SDL_RenderCopy(sdl_render, sdl_tex, &r_src, 0); if (ret) - sdl_log("SDL: unable to copy texture to renderer (%s)\n", sdl_GetError()); + sdl_log("SDL: unable to copy texture to renderer (%s)\n", SDL_GetError()); SDL_RenderPresent(sdl_render); SDL_UnlockMutex(sdl_mutex); } - static void -sdl_blit_ex(int x, int y, int w, int h) +sdl_blit_ex(int x, int y, int w, int h, UNUSED(int monitor_index)) { SDL_Rect r_src; - void *pixeldata; - int pitch, ret; - int row; + void *pixeldata; + int pitch; + int ret; if (!sdl_enabled || (x < 0) || (y < 0) || (w <= 0) || (h <= 0) || (w > 2048) || (h > 2048) || (buffer32 == NULL) || (sdl_render == NULL) || (sdl_tex == NULL)) { - video_blit_complete(); - return; + video_blit_complete(); + return; } SDL_LockMutex(sdl_mutex); SDL_LockTexture(sdl_tex, 0, &pixeldata, &pitch); - for (row = 0; row < h; ++row) - video_copy(&(((uint8_t *) pixeldata)[row * 2048 * sizeof(uint32_t)]), &(buffer32->line[y + row][x]), w * sizeof(uint32_t)); + for (int row = 0; row < h; ++row) + video_copy(&(((uint8_t *) pixeldata)[row * 2048 * sizeof(uint32_t)]), &(buffer32->line[y + row][x]), w * sizeof(uint32_t)); - if (screenshots) - video_screenshot((uint32_t *) pixeldata, 0, 0, 2048); + if (monitors[0].mon_screenshots) + video_screenshot((uint32_t *) pixeldata, 0, 0, 2048); SDL_UnlockTexture(sdl_tex); @@ -304,54 +311,51 @@ sdl_blit_ex(int x, int y, int w, int h) ret = SDL_RenderCopy(sdl_render, sdl_tex, &r_src, 0); if (ret) - sdl_log("SDL: unable to copy texture to renderer (%s)\n", sdl_GetError()); + sdl_log("SDL: unable to copy texture to renderer (%s)\n", SDL_GetError()); SDL_RenderPresent(sdl_render); SDL_UnlockMutex(sdl_mutex); } - static void sdl_destroy_window(void) { if (sdl_win != NULL) { - SDL_DestroyWindow(sdl_win); - sdl_win = NULL; + SDL_DestroyWindow(sdl_win); + sdl_win = NULL; } } - static void sdl_destroy_texture(void) { if (sdl_tex != NULL) { - SDL_DestroyTexture(sdl_tex); - sdl_tex = NULL; + SDL_DestroyTexture(sdl_tex); + sdl_tex = NULL; } /* SDL_DestroyRenderer also automatically destroys all associated textures. */ if (sdl_render != NULL) { - SDL_DestroyRenderer(sdl_render); - sdl_render = NULL; + SDL_DestroyRenderer(sdl_render); + sdl_render = NULL; } } - void sdl_close(void) { if (sdl_mutex != NULL) - SDL_LockMutex(sdl_mutex); + SDL_LockMutex(sdl_mutex); /* Unregister our renderer! */ video_setblit(NULL); if (sdl_enabled) - sdl_enabled = 0; + sdl_enabled = 0; if (sdl_mutex != NULL) { - SDL_DestroyMutex(sdl_mutex); - sdl_mutex = NULL; + SDL_DestroyMutex(sdl_mutex); + sdl_mutex = NULL; } sdl_destroy_texture(); @@ -360,8 +364,8 @@ sdl_close(void) SetFocus(hwndMain); if (sdl_parent_hwnd != NULL) { - DestroyWindow(sdl_parent_hwnd); - sdl_parent_hwnd = NULL; + DestroyWindow(sdl_parent_hwnd); + sdl_parent_hwnd = NULL; } /* Quit. */ @@ -369,41 +373,35 @@ sdl_close(void) sdl_flags = -1; } - static int old_capture = 0; - static void sdl_select_best_hw_driver(void) { - int i; SDL_RendererInfo renderInfo; - for (i = 0; i < SDL_GetNumRenderDrivers(); ++i) - { - SDL_GetRenderDriverInfo(i, &renderInfo); - if (renderInfo.flags & SDL_RENDERER_ACCELERATED) { - SDL_SetHint(SDL_HINT_RENDER_DRIVER, renderInfo.name); - return; - } + for (int i = 0; i < SDL_GetNumRenderDrivers(); ++i) { + SDL_GetRenderDriverInfo(i, &renderInfo); + if (renderInfo.flags & SDL_RENDERER_ACCELERATED) { + SDL_SetHint(SDL_HINT_RENDER_DRIVER, renderInfo.name); + return; + } } } - static void sdl_init_texture(void) { if (sdl_flags & RENDERER_HARDWARE) { - sdl_render = SDL_CreateRenderer(sdl_win, -1, SDL_RENDERER_ACCELERATED); - SDL_SetHint(SDL_HINT_RENDER_SCALE_QUALITY, video_filter_method ? "1" : "0"); + sdl_render = SDL_CreateRenderer(sdl_win, -1, SDL_RENDERER_ACCELERATED); + SDL_SetHint(SDL_HINT_RENDER_SCALE_QUALITY, video_filter_method ? "1" : "0"); } else - sdl_render = SDL_CreateRenderer(sdl_win, -1, SDL_RENDERER_SOFTWARE); + sdl_render = SDL_CreateRenderer(sdl_win, -1, SDL_RENDERER_SOFTWARE); sdl_tex = SDL_CreateTexture(sdl_render, SDL_PIXELFORMAT_ARGB8888, - SDL_TEXTUREACCESS_STREAMING, 2048, 2048); + SDL_TEXTUREACCESS_STREAMING, 2048, 2048); } - static void sdl_reinit_texture(void) { @@ -414,70 +412,73 @@ sdl_reinit_texture(void) sdl_init_texture(); } - void sdl_set_fs(int fs) { - int w = 0, h = 0, x = 0, y = 0; + int w = 0; + int h = 0; + int x = 0; + int y = 0; RECT rect; SDL_LockMutex(sdl_mutex); sdl_enabled = 0; if (fs) { - ShowWindow(sdl_parent_hwnd, TRUE); - SetParent(hwndRender, sdl_parent_hwnd); - ShowWindow(hwndRender, TRUE); - MoveWindow(sdl_parent_hwnd, 0, 0, sdl_w, sdl_h, TRUE); + ShowWindow(sdl_parent_hwnd, TRUE); + SetParent(hwndRender, sdl_parent_hwnd); + ShowWindow(hwndRender, TRUE); + MoveWindow(sdl_parent_hwnd, 0, 0, sdl_w, sdl_h, TRUE); - /* Show the window, make it topmost, and give it focus. */ - w = unscaled_size_x; - h = efscrnsz_y; - sdl_stretch(&w, &h, &x, &y); - MoveWindow(hwndRender, x, y, w, h, TRUE); - ImmAssociateContext(sdl_parent_hwnd, NULL); - SetFocus(sdl_parent_hwnd); + /* Show the window, make it topmost, and give it focus. */ + w = unscaled_size_x; + h = efscrnsz_y; + sdl_stretch(&w, &h, &x, &y); + MoveWindow(hwndRender, x, y, w, h, TRUE); + ImmAssociateContext(sdl_parent_hwnd, NULL); + SetFocus(sdl_parent_hwnd); - /* Redirect RawInput to this new window. */ - old_capture = mouse_capture; - GetWindowRect(hwndRender, &rect); - ClipCursor(&rect); - mouse_capture = 1; + /* Redirect RawInput to this new window. */ + old_capture = mouse_capture; + GetWindowRect(hwndRender, &rect); + ClipCursor(&rect); + mouse_capture = 1; } else { - SetParent(hwndRender, hwndMain); - ShowWindow(sdl_parent_hwnd, FALSE); - ShowWindow(hwndRender, TRUE); - ImmAssociateContext(hwndMain, NULL); - SetFocus(hwndMain); - mouse_capture = old_capture; + SetParent(hwndRender, hwndMain); + ShowWindow(sdl_parent_hwnd, FALSE); + ShowWindow(hwndRender, TRUE); + ImmAssociateContext(hwndMain, NULL); + SetFocus(hwndMain); + mouse_capture = old_capture; - if (mouse_capture) { - GetWindowRect(hwndRender, &rect); - ClipCursor(&rect); - } else - ClipCursor(&oldclip); + if (mouse_capture) { + GetWindowRect(hwndRender, &rect); + ClipCursor(&rect); + } else + ClipCursor(&oldclip); } sdl_fs = fs; if (fs) - sdl_flags |= RENDERER_FULL_SCREEN; + sdl_flags |= RENDERER_FULL_SCREEN; else - sdl_flags &= ~RENDERER_FULL_SCREEN; + sdl_flags &= ~RENDERER_FULL_SCREEN; - // sdl_reinit_texture(); +#if 0 + sdl_reinit_texture(); +#endif sdl_enabled = 1; SDL_UnlockMutex(sdl_mutex); } - static int sdl_init_common(int flags) { - wchar_t temp[128]; + wchar_t temp[128]; SDL_version ver; - sdl_log("SDL: init (fs=%d)\n", fs); + sdl_log("SDL: init (flags=%d)\n", flags); /* Get and log the version of the DLL we are using. */ SDL_GetVersion(&ver); @@ -485,15 +486,15 @@ sdl_init_common(int flags) /* Initialize the SDL system. */ if (SDL_Init(SDL_INIT_VIDEO) < 0) { - sdl_log("SDL: initialization failed (%s)\n", sdl_GetError()); - return(0); + sdl_log("SDL: initialization failed (%s)\n", SDL_GetError()); + return 0; } if (flags & RENDERER_HARDWARE) { - if (flags & RENDERER_OPENGL) - SDL_SetHint(SDL_HINT_RENDER_DRIVER, "OpenGL"); - else - sdl_select_best_hw_driver(); + if (flags & RENDERER_OPENGL) + SDL_SetHint(SDL_HINT_RENDER_DRIVER, "OpenGL"); + else + sdl_select_best_hw_driver(); } /* Get the size of the (current) desktop. */ @@ -503,16 +504,16 @@ sdl_init_common(int flags) /* Create the desktop-covering window. */ _swprintf(temp, L"%s v%s", EMU_NAME_W, EMU_VERSION_FULL_W); sdl_parent_hwnd = CreateWindow(SDL_CLASS_NAME, temp, WS_POPUP, 0, 0, sdl_w, sdl_h, - HWND_DESKTOP, NULL, hinstance, NULL); + HWND_DESKTOP, NULL, hinstance, NULL); ShowWindow(sdl_parent_hwnd, FALSE); sdl_flags = flags; if (sdl_win == NULL) { - sdl_log("SDL: unable to CreateWindowFrom (%s)\n", SDL_GetError()); + sdl_log("SDL: unable to CreateWindowFrom (%s)\n", SDL_GetError()); } - sdl_win = SDL_CreateWindowFrom((void *)hwndRender); + sdl_win = SDL_CreateWindowFrom((void *) hwndRender); sdl_init_texture(); sdl_set_fs(video_fullscreen & 1); @@ -523,50 +524,48 @@ sdl_init_common(int flags) video_setblit((video_grayscale || invert_display) ? sdl_blit_ex : sdl_blit); sdl_enabled = 1; - sdl_mutex = SDL_CreateMutex(); + sdl_mutex = SDL_CreateMutex(); - return(1); + return 1; } - int -sdl_inits(HWND h) +sdl_inits(UNUSED(HWND h)) { return sdl_init_common(0); } - int -sdl_inith(HWND h) +sdl_inith(UNUSED(HWND h)) { return sdl_init_common(RENDERER_HARDWARE); } - int -sdl_initho(HWND h) +sdl_initho(UNUSED(HWND h)) { return sdl_init_common(RENDERER_HARDWARE | RENDERER_OPENGL); } - int sdl_pause(void) { - return(0); + return 0; } - void sdl_resize(int x, int y) { - int ww = 0, wh = 0, wx = 0, wy = 0; + int ww = 0; + int wh = 0; + int wx = 0; + int wy = 0; if (video_fullscreen & 2) - return; + return; if ((x == cur_w) && (y == cur_h)) - return; + return; SDL_LockMutex(sdl_mutex); @@ -574,8 +573,8 @@ sdl_resize(int x, int y) wh = y; if (sdl_fs) { - sdl_stretch(&ww, &wh, &wx, &wy); - MoveWindow(hwndRender, wx, wy, ww, wh, TRUE); + sdl_stretch(&ww, &wh, &wx, &wy); + MoveWindow(hwndRender, wx, wy, ww, wh, TRUE); } cur_w = x; @@ -594,35 +593,33 @@ sdl_resize(int x, int y) SDL_UnlockMutex(sdl_mutex); } - void sdl_enable(int enable) { if (sdl_flags == -1) - return; + return; SDL_LockMutex(sdl_mutex); sdl_enabled = !!enable; if (enable == 1) { - SDL_SetWindowSize(sdl_win, cur_ww, cur_wh); - sdl_reinit_texture(); + SDL_SetWindowSize(sdl_win, cur_ww, cur_wh); + sdl_reinit_texture(); } SDL_UnlockMutex(sdl_mutex); } - void sdl_reload(void) { if (sdl_flags & RENDERER_HARDWARE) { - SDL_LockMutex(sdl_mutex); + SDL_LockMutex(sdl_mutex); - SDL_SetHint(SDL_HINT_RENDER_SCALE_QUALITY, video_filter_method ? "1" : "0"); - sdl_reinit_texture(); + SDL_SetHint(SDL_HINT_RENDER_SCALE_QUALITY, video_filter_method ? "1" : "0"); + sdl_reinit_texture(); - SDL_UnlockMutex(sdl_mutex); + SDL_UnlockMutex(sdl_mutex); } video_setblit((video_grayscale || invert_display) ? sdl_blit_ex : sdl_blit); diff --git a/src/win/win_serial_passthrough.c b/src/win/win_serial_passthrough.c new file mode 100644 index 000000000..b2d09b1d0 --- /dev/null +++ b/src/win/win_serial_passthrough.c @@ -0,0 +1,238 @@ +/* + * 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. + * + * Definitions for platform specific serial to host passthrough + * + * + * Authors: Andreas J. Reichel , + * Jasmine Iwanek + * + * Copyright 2021 Andreas J. Reichel + * Copyright 2021-2023 Jasmine Iwanek + */ + +#define _XOPEN_SOURCE 500 +#include +#include +#include +#include +#include +#include + +#include <86box/86box.h> +#include <86box/log.h> +#include <86box/timer.h> +#include <86box/plat.h> +#include <86box/device.h> +#include <86box/serial_passthrough.h> +#include <86box/plat_serial_passthrough.h> +#include <86box/ui.h> + +#include + +#define LOG_PREFIX "serial_passthrough: " + +void +plat_serpt_close(void *priv) +{ + serial_passthrough_t *dev = (serial_passthrough_t *) priv; + +#if 0 + fclose(dev->master_fd); +#endif + FlushFileBuffers((HANDLE) dev->master_fd); + if (dev->mode == SERPT_MODE_VCON) + DisconnectNamedPipe((HANDLE) dev->master_fd); + if (dev->mode == SERPT_MODE_HOSTSER) { + SetCommState((HANDLE) dev->master_fd, (DCB *) dev->backend_priv); + free(dev->backend_priv); + } + CloseHandle((HANDLE) dev->master_fd); +} + +static void +plat_serpt_write_vcon(serial_passthrough_t *dev, uint8_t data) +{ +#if 0 + fd_set wrfds; + int res; +#endif + + /* We cannot use select here, this would block the hypervisor! */ +#if 0 + FD_ZERO(&wrfds); + FD_SET(ctx->master_fd, &wrfds); + + res = select(ctx->master_fd + 1, NULL, &wrfds, NULL, NULL); + + if (res <= 0) + return; +#endif + + /* just write it out */ +#if 0 + fwrite(dev->master_fd, &data, 1); +#endif + DWORD bytesWritten = 0; + WriteFile((HANDLE) dev->master_fd, &data, 1, &bytesWritten, NULL); +} + +void +plat_serpt_set_params(void *priv) +{ + const serial_passthrough_t *dev = (serial_passthrough_t *) priv; + + if (dev->mode == SERPT_MODE_HOSTSER) { + DCB serialattr = {}; + GetCommState((HANDLE) dev->master_fd, &serialattr); +#define BAUDRATE_RANGE(baud_rate, min, max) \ + if (baud_rate >= min && baud_rate < max) { \ + serialattr.BaudRate = min; \ + } + + BAUDRATE_RANGE(dev->baudrate, 110, 300); + BAUDRATE_RANGE(dev->baudrate, 300, 600); + BAUDRATE_RANGE(dev->baudrate, 600, 1200); + BAUDRATE_RANGE(dev->baudrate, 1200, 2400); + BAUDRATE_RANGE(dev->baudrate, 2400, 4800); + BAUDRATE_RANGE(dev->baudrate, 4800, 9600); + BAUDRATE_RANGE(dev->baudrate, 9600, 14400); + BAUDRATE_RANGE(dev->baudrate, 14400, 19200); + BAUDRATE_RANGE(dev->baudrate, 19200, 38400); + BAUDRATE_RANGE(dev->baudrate, 38400, 57600); + BAUDRATE_RANGE(dev->baudrate, 57600, 115200); + BAUDRATE_RANGE(dev->baudrate, 115200, 0xFFFFFFFF); + + serialattr.ByteSize = dev->data_bits; + serialattr.StopBits = (dev->serial->lcr & 0x04) ? TWOSTOPBITS : ONESTOPBIT; + if (!(dev->serial->lcr & 0x08)) { + serialattr.fParity = 0; + serialattr.Parity = NOPARITY; + } else { + serialattr.fParity = 1; + if (dev->serial->lcr & 0x20) { + serialattr.Parity = MARKPARITY + !!(dev->serial->lcr & 0x10); + } else { + serialattr.Parity = ODDPARITY + !!(dev->serial->lcr & 0x10); + } + } + + SetCommState((HANDLE) dev->master_fd, &serialattr); +#undef BAUDRATE_RANGE + } +} + +void +plat_serpt_write(void *priv, uint8_t data) +{ + serial_passthrough_t *dev = (serial_passthrough_t *) priv; + + switch (dev->mode) { + case SERPT_MODE_VCON: + case SERPT_MODE_HOSTSER: + plat_serpt_write_vcon(dev, data); + break; + default: + break; + } +} + +uint8_t +plat_serpt_read_vcon(serial_passthrough_t *dev, uint8_t *data) +{ + DWORD bytesRead = 0; + ReadFile((HANDLE) dev->master_fd, data, 1, &bytesRead, NULL); + return !!bytesRead; +} + +int +plat_serpt_read(void *priv, uint8_t *data) +{ + serial_passthrough_t *dev = (serial_passthrough_t *) priv; + int res = 0; + + switch (dev->mode) { + case SERPT_MODE_VCON: + case SERPT_MODE_HOSTSER: + res = plat_serpt_read_vcon(dev, data); + break; + default: + break; + } + return res; +} + +static int +open_pseudo_terminal(serial_passthrough_t *dev) +{ + char ascii_pipe_name[1024] = { 0 }; + strncpy(ascii_pipe_name, dev->named_pipe, sizeof(ascii_pipe_name)); + ascii_pipe_name[1023] = '\0'; + dev->master_fd = (intptr_t) CreateNamedPipeA(ascii_pipe_name, PIPE_ACCESS_DUPLEX, PIPE_TYPE_BYTE | PIPE_READMODE_BYTE | PIPE_NOWAIT, 1, 65536, 65536, NMPWAIT_USE_DEFAULT_WAIT, NULL); + if (dev->master_fd == (intptr_t) INVALID_HANDLE_VALUE) { + wchar_t errorMsg[1024] = { 0 }; + wchar_t finalMsg[1024] = { 0 }; + DWORD error = GetLastError(); + FormatMessageW(FORMAT_MESSAGE_FROM_SYSTEM, NULL, error, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), errorMsg, 1024, NULL); + swprintf(finalMsg, 1024, L"Named Pipe (server, named_pipe=\"%hs\", port=COM%d): %ls\n", ascii_pipe_name, dev->port + 1, errorMsg); + ui_msgbox(MBX_ERROR | MBX_FATAL, finalMsg); + return 0; + } + pclog("Named Pipe @ %s\n", ascii_pipe_name); + return 1; +} + +static int +open_host_serial_port(serial_passthrough_t *dev) +{ + COMMTIMEOUTS timeouts = { + .ReadIntervalTimeout = MAXDWORD, + .ReadTotalTimeoutConstant = 0, + .ReadTotalTimeoutMultiplier = 0, + .WriteTotalTimeoutMultiplier = 0, + .WriteTotalTimeoutConstant = 1000 + }; + DCB *serialattr = calloc(1, sizeof(DCB)); + if (!serialattr) + return 0; + dev->master_fd = (intptr_t) CreateFileA(dev->host_serial_path, GENERIC_READ | GENERIC_WRITE, 0, NULL, OPEN_EXISTING, FILE_FLAG_WRITE_THROUGH, NULL); + if (dev->master_fd == (intptr_t) INVALID_HANDLE_VALUE) { + free(serialattr); + return 0; + } + if (!SetCommTimeouts((HANDLE) dev->master_fd, &timeouts)) { + pclog(LOG_PREFIX "error setting COM port timeouts.\n"); + CloseHandle((HANDLE) dev->master_fd); + free(serialattr); + return 0; + } + GetCommState((HANDLE) dev->master_fd, serialattr); + dev->backend_priv = serialattr; + return 1; +} + +int +plat_serpt_open_device(void *priv) +{ + serial_passthrough_t *dev = (serial_passthrough_t *) priv; + + switch (dev->mode) { + case SERPT_MODE_VCON: + if (open_pseudo_terminal(dev)) { + return 0; + } + break; + case SERPT_MODE_HOSTSER: + if (open_host_serial_port(dev)) { + return 0; + } + default: + break; + } + return 1; +} diff --git a/src/win/win_settings.c b/src/win/win_settings.c index 4c044c07c..139c387a8 100644 --- a/src/win/win_settings.c +++ b/src/win/win_settings.c @@ -1,21 +1,23 @@ /* - * 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. + * 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. + * This file is part of the 86Box distribution. * - * Windows 86Box Settings dialog handler. + * Windows 86Box Settings dialog handler. * * * - * Authors: Miran Grca, - * David HrdliÄka, + * Authors: Miran Grca, + * David HrdliÄka, + * Jasmine Iwanek, * - * Copyright 2016-2019 Miran Grca. - * Copyright 2018,2019 David HrdliÄka. - * Copyright 2021 Laci bá' + * Copyright 2016-2019 Miran Grca. + * Copyright 2018-2019 David HrdliÄka. + * Copyright 2021 Laci bá' + * Copyright 2021-2023 Jasmine Iwanek. */ #define UNICODE #define BITMAP WINDOWS_BITMAP @@ -24,7 +26,7 @@ #include #undef BITMAP #ifdef ENABLE_SETTINGS_LOG -#include +# include #endif #include #include @@ -47,6 +49,7 @@ #include <86box/isartc.h> #include <86box/lpt.h> #include <86box/mouse.h> +#include <86box/serial.h> #include <86box/scsi.h> #include <86box/scsi_device.h> #include <86box/cdrom.h> @@ -58,52 +61,79 @@ #include <86box/fdd.h> #include <86box/fdc.h> #include <86box/fdc_ext.h> +#include <86box/thread.h> #include <86box/network.h> #include <86box/sound.h> #include <86box/midi.h> #include <86box/snd_mpu401.h> +#include <86box/snd_opl.h> #include <86box/video.h> +#include <86box/vid_xga_device.h> #include <86box/plat.h> #include <86box/ui.h> #include <86box/win.h> +#include <86box/serial_passthrough.h> #include "../disk/minivhd/minivhd.h" -#include "../disk/minivhd/minivhd_util.h" +/* Icon, Bus, File, C, H, S, Size, Speed */ +#define C_COLUMNS_HARD_DISKS 7 -/* Icon, Bus, File, C, H, S, Size */ -#define C_COLUMNS_HARD_DISKS 6 - +#define C_COLUMNS_FLOPPY_DRIVES 3 +#define C_COLUMNS_CDROM_DRIVES 3 +#define C_COLUMNS_MO_DRIVES 2 +#define C_COLUMNS_ZIP_DRIVES 2 static int first_cat = 0; /* Machine category */ -static int temp_machine_type, temp_machine, temp_cpu, temp_wait_states, temp_fpu, temp_sync; +static int temp_machine_type; +static int temp_machine; +static int temp_cpu; +static int temp_wait_states; +static int temp_fpu; +static int temp_sync; static cpu_family_t *temp_cpu_f; -static uint32_t temp_mem_size; +static uint32_t temp_mem_size; #ifdef USE_DYNAREC static int temp_dynarec; #endif +static int temp_fpu_softfloat; /* Video category */ -static int temp_gfxcard, temp_voodoo; +static int temp_gfxcard[2]; +static int temp_ibm8514; +static int temp_voodoo; +static int temp_xga; /* Input devices category */ -static int temp_mouse, temp_joystick; +static int temp_mouse; +static int temp_joystick; /* Sound category */ -static int temp_sound_card, temp_midi_device, temp_midi_input_device, temp_mpu401, temp_SSI2001, temp_GAMEBLASTER, temp_GUS; +static int temp_sound_card[SOUND_CARD_MAX]; +static int temp_midi_output_device; +static int temp_midi_input_device; +static int temp_mpu401; static int temp_float; +static int temp_fm_driver; /* Network category */ -static int temp_net_type, temp_net_card; -static char temp_pcap_dev[522]; +static int temp_net_type[NET_CARD_MAX]; +static uint16_t temp_net_card[NET_CARD_MAX]; +static char temp_pcap_dev[NET_CARD_MAX][128]; /* Ports category */ -static int temp_lpt_devices[PARALLEL_MAX]; -static int temp_serial[SERIAL_MAX], temp_lpt[PARALLEL_MAX]; +static int temp_lpt_devices[PARALLEL_MAX]; +static uint8_t temp_serial[SERIAL_MAX]; +static uint8_t temp_lpt[PARALLEL_MAX]; +static int temp_serial_passthrough_enabled[SERIAL_MAX]; /* Other peripherals category */ -static int temp_fdc_card, temp_hdc, temp_ide_ter, temp_ide_qua, temp_cassette; +static int temp_fdc_card; +static int temp_hdc; +static int temp_ide_ter; +static int temp_ide_qua; +static int temp_cassette; static int temp_scsi_card[SCSI_BUS_MAX]; static int temp_bugger; static int temp_postcard; @@ -121,35 +151,55 @@ static int temp_fdd_turbo[FDD_NUM]; static int temp_fdd_check_bpb[FDD_NUM]; /* Other removable devices category */ -static cdrom_t temp_cdrom[CDROM_NUM]; +static cdrom_t temp_cdrom[CDROM_NUM]; static zip_drive_t temp_zip_drives[ZIP_NUM]; -static mo_drive_t temp_mo_drives[MO_NUM]; +static mo_drive_t temp_mo_drives[MO_NUM]; -static HWND hwndParentDialog, hwndChildDialog; +static HWND hwndParentDialog; +static HWND hwndChildDialog; static uint32_t displayed_category = 0; extern int is486; -static int listtomachinetype[256], listtomachine[256]; -static int listtocpufamily[256], listtocpu[256]; -static int settings_list_to_device[2][256], settings_list_to_fdc[20]; -static int settings_list_to_midi[20], settings_list_to_midi_in[20]; +static int listtomachinetype[256]; +static int listtomachine[256]; +static int listtocpufamily[256]; +static int listtocpu[256]; +static int settings_list_to_device[2][256]; +static int settings_list_to_fdc[20]; +static int settings_list_to_midi[20]; +static int settings_list_to_midi_in[20]; static int settings_list_to_hdc[20]; -static int max_spt = 63, max_hpc = 255, max_tracks = 266305; -static uint64_t mfm_tracking, esdi_tracking, xta_tracking, ide_tracking, scsi_tracking[8]; +static int max_spt = 63; +static int max_hpc = 255; +static int max_tracks = 266305; +static uint64_t mfm_tracking; +static uint64_t esdi_tracking; +static uint64_t xta_tracking; +static uint64_t ide_tracking; +static uint64_t scsi_tracking[8]; static uint64_t size; -static int hd_listview_items, hdc_id_to_listview_index[HDD_NUM]; -static int no_update = 0, existing = 0, chs_enabled = 0; -static int lv1_current_sel, lv2_current_sel; -static int hard_disk_added = 0, next_free_id = 0, selection = 127; -static int spt, hpc, tracks, ignore_change = 0; +static int hd_listview_items; +static int hdc_id_to_listview_index[HDD_NUM]; +static int no_update = 0; +static int existing = 0; +static int chs_enabled = 0; +static int lv1_current_sel; +static int lv2_current_sel; +static int hard_disk_added = 0; +static int next_free_id = 0; +static int selection = 127; +static int spt; +static int hpc; +static int tracks; +static int ignore_change = 0; -static hard_disk_t new_hdd, *hdd_ptr; +static hard_disk_t new_hdd; +static hard_disk_t *hdd_ptr; static wchar_t hd_file_name[512]; -static WCHAR device_name[512]; - +static WCHAR device_name[512]; static int settings_get_check(HWND hdlg, int id) @@ -157,49 +207,42 @@ settings_get_check(HWND hdlg, int id) return SendMessage(GetDlgItem(hdlg, id), BM_GETCHECK, 0, 0); } - static int settings_get_cur_sel(HWND hdlg, int id) { return SendMessage(GetDlgItem(hdlg, id), CB_GETCURSEL, 0, 0); } - static void settings_set_check(HWND hdlg, int id, int val) { SendMessage(GetDlgItem(hdlg, id), BM_SETCHECK, val, 0); } - static void settings_set_cur_sel(HWND hdlg, int id, int val) { SendMessage(GetDlgItem(hdlg, id), CB_SETCURSEL, val, 0); } - static void settings_reset_content(HWND hdlg, int id) { SendMessage(GetDlgItem(hdlg, id), CB_RESETCONTENT, 0, 0); } - static void settings_add_string(HWND hdlg, int id, LPARAM string) { SendMessage(GetDlgItem(hdlg, id), CB_ADDSTRING, 0, string); } - static void settings_enable_window(HWND hdlg, int id, int condition) { EnableWindow(GetDlgItem(hdlg, id), condition ? TRUE : FALSE); } - static void settings_show_window(HWND hdlg, int id, int condition) { @@ -210,7 +253,6 @@ settings_show_window(HWND hdlg, int id, int condition) ShowWindow(h, condition ? SW_SHOW : SW_HIDE); } - static void settings_listview_enable_styles(HWND hdlg, int id) { @@ -221,7 +263,6 @@ settings_listview_enable_styles(HWND hdlg, int id) ListView_SetExtendedListViewStyle(h, LVS_EX_FULLROWSELECT | LVS_EX_DOUBLEBUFFER); } - static void settings_listview_select(HWND hdlg, int id, int selection) { @@ -231,42 +272,41 @@ settings_listview_select(HWND hdlg, int id, int selection) ListView_SetItemState(h, selection, LVIS_FOCUSED | LVIS_SELECTED, 0x000F); } - static void -settings_process_messages() +settings_process_messages(void) { MSG msg; while (PeekMessage(&msg, 0, 0, 0, PM_REMOVE | PM_NOYIELD)) { - TranslateMessage(&msg); - DispatchMessage(&msg); + TranslateMessage(&msg); + DispatchMessage(&msg); } } - static BOOL image_list_init(HWND hdlg, int id, const uint8_t *icon_ids) { - HICON hiconItem; + HICON hiconItem; HIMAGELIST hSmall; - HWND hwndList = GetDlgItem(hdlg, id); + HWND hwndList = GetDlgItem(hdlg, id); int i = 0; hSmall = ListView_GetImageList(hwndList, LVSIL_SMALL); - if (hSmall != 0) ImageList_Destroy(hSmall); + if (hSmall != 0) + ImageList_Destroy(hSmall); hSmall = ImageList_Create(win_get_system_metrics(SM_CXSMICON, dpi), - win_get_system_metrics(SM_CYSMICON, dpi), - ILC_MASK | ILC_COLOR32, 1, 1); + win_get_system_metrics(SM_CYSMICON, dpi), + ILC_MASK | ILC_COLOR32, 1, 1); - while(1) { - if (icon_ids[i] == 0) - break; + while (1) { + if (icon_ids[i] == 0) + break; - hiconItem = hIcon[icon_ids[i]]; - ImageList_AddIcon(hSmall, hiconItem); + hiconItem = hIcon[icon_ids[i]]; + ImageList_AddIcon(hSmall, hiconItem); - i++; + i++; } ListView_SetImageList(hwndList, hSmall, LVSIL_SMALL); @@ -274,42 +314,39 @@ image_list_init(HWND hdlg, int id, const uint8_t *icon_ids) return TRUE; } - /* Show a MessageBox dialog. This is nasty, I know. --FvK */ static int settings_msgbox_header(int flags, void *header, void *message) { HWND h; - int i; + int i; - h = hwndMain; + h = hwndMain; hwndMain = hwndParentDialog; i = ui_msgbox_header(flags, header, message); hwndMain = h; - return(i); + return i; } - static int settings_msgbox_ex(int flags, void *header, void *message, void *btn1, void *btn2, void *btn3) { HWND h; - int i; + int i; - h = hwndMain; + h = hwndMain; hwndMain = hwndParentDialog; i = ui_msgbox_ex(flags, header, message, btn1, btn2, btn3); hwndMain = h; - return(i); + return i; } - /* This does the initial read of global variables into the temporary ones. */ static void win_settings_init(void) @@ -318,128 +355,134 @@ win_settings_init(void) /* Machine category */ temp_machine_type = machine_get_type(machine); - temp_machine = machine; - temp_cpu_f = cpu_f; - temp_wait_states = cpu_waitstates; - temp_cpu = cpu; - temp_mem_size = mem_size; + temp_machine = machine; + temp_cpu_f = cpu_f; + temp_wait_states = cpu_waitstates; + temp_cpu = cpu; + temp_mem_size = mem_size; #ifdef USE_DYNAREC temp_dynarec = cpu_use_dynarec; #endif - temp_fpu = fpu_type; + temp_fpu_softfloat = fpu_softfloat; + temp_fpu = fpu_type; temp_sync = time_sync; /* Video category */ - temp_gfxcard = gfxcard; - temp_voodoo = voodoo_enabled; + temp_gfxcard[0] = gfxcard[0]; + temp_gfxcard[1] = gfxcard[1]; + temp_voodoo = voodoo_enabled; + temp_ibm8514 = ibm8514_standalone_enabled; + temp_xga = xga_standalone_enabled; /* Input devices category */ - temp_mouse = mouse_type; + temp_mouse = mouse_type; temp_joystick = joystick_type; /* Sound category */ - temp_sound_card = sound_card_current; - temp_midi_device = midi_device_current; - temp_midi_input_device = midi_input_device_current; - temp_mpu401 = mpu401_standalone_enable; - temp_SSI2001 = SSI2001; - temp_GAMEBLASTER = GAMEBLASTER; - temp_GUS = GUS; - temp_float = sound_is_float; + for (i = 0; i < SOUND_CARD_MAX; i++) + temp_sound_card[i] = sound_card_current[i]; + temp_midi_output_device = midi_output_device_current; + temp_midi_input_device = midi_input_device_current; + temp_mpu401 = mpu401_standalone_enable; + temp_float = sound_is_float; + temp_fm_driver = fm_driver; /* Network category */ - temp_net_type = network_type; - memset(temp_pcap_dev, 0, sizeof(temp_pcap_dev)); + for (i = 0; i < NET_CARD_MAX; i++) { + temp_net_type[i] = net_cards_conf[i].net_type; + memset(temp_pcap_dev[i], 0, sizeof(temp_pcap_dev[i])); #ifdef ENABLE_SETTINGS_LOG - assert(sizeof(temp_pcap_dev) == sizeof(network_host)); + assert(sizeof(temp_pcap_dev[i]) == sizeof(net_cards_conf[i].host_dev_name)); #endif - memcpy(temp_pcap_dev, network_host, sizeof(network_host)); - temp_net_card = network_card; + memcpy(temp_pcap_dev[i], net_cards_conf[i].host_dev_name, sizeof(net_cards_conf[i].host_dev_name)); + temp_net_card[i] = net_cards_conf[i].device_num; + } /* Ports category */ for (i = 0; i < PARALLEL_MAX; i++) { - temp_lpt_devices[i] = lpt_ports[i].device; - temp_lpt[i] = lpt_ports[i].enabled; + temp_lpt_devices[i] = lpt_ports[i].device; + temp_lpt[i] = lpt_ports[i].enabled; + } + for (i = 0; i < SERIAL_MAX; i++) { + temp_serial[i] = com_ports[i].enabled; + temp_serial_passthrough_enabled[i] = serial_passthrough_enabled[i]; } - for (i = 0; i < SERIAL_MAX; i++) - temp_serial[i] = serial_enabled[i]; /* Storage devices category */ for (i = 0; i < SCSI_BUS_MAX; i++) - temp_scsi_card[i] = scsi_card_current[i]; + temp_scsi_card[i] = scsi_card_current[i]; temp_fdc_card = fdc_type; - temp_hdc = hdc_current; - temp_ide_ter = ide_ter_enabled; - temp_ide_qua = ide_qua_enabled; + temp_hdc = hdc_current; + temp_ide_ter = ide_ter_enabled; + temp_ide_qua = ide_qua_enabled; temp_cassette = cassette_enable; mfm_tracking = xta_tracking = esdi_tracking = ide_tracking = 0; - for (i = 0; i < 8; i++) - scsi_tracking[i] = 0; + for (i = 0; i < SCSI_LUN_MAX; i++) + scsi_tracking[i] = 0; /* Hard disks category */ memcpy(temp_hdd, hdd, HDD_NUM * sizeof(hard_disk_t)); for (i = 0; i < HDD_NUM; i++) { - if (hdd[i].bus == HDD_BUS_MFM) - mfm_tracking |= (1 << (hdd[i].mfm_channel << 3)); - else if (hdd[i].bus == HDD_BUS_XTA) - xta_tracking |= (1 << (hdd[i].xta_channel << 3)); - else if (hdd[i].bus == HDD_BUS_ESDI) - esdi_tracking |= (1 << (hdd[i].esdi_channel << 3)); - else if ((hdd[i].bus == HDD_BUS_IDE) || (hdd[i].bus == HDD_BUS_ATAPI)) - ide_tracking |= (1 << (hdd[i].ide_channel << 3)); - else if (hdd[i].bus == HDD_BUS_SCSI) - scsi_tracking[hdd[i].scsi_id >> 3] |= (1 << ((hdd[i].scsi_id & 0x07) << 3)); + if (hdd[i].bus == HDD_BUS_MFM) + mfm_tracking |= (1 << (hdd[i].mfm_channel << 3)); + else if (hdd[i].bus == HDD_BUS_XTA) + xta_tracking |= (1 << (hdd[i].xta_channel << 3)); + else if (hdd[i].bus == HDD_BUS_ESDI) + esdi_tracking |= (1 << (hdd[i].esdi_channel << 3)); + else if ((hdd[i].bus == HDD_BUS_IDE) || (hdd[i].bus == HDD_BUS_ATAPI)) + ide_tracking |= (1 << (hdd[i].ide_channel << 3)); + else if (hdd[i].bus == HDD_BUS_SCSI) + scsi_tracking[hdd[i].scsi_id >> 3] |= (1 << ((hdd[i].scsi_id & 0x07) << 3)); } /* Floppy drives category */ for (i = 0; i < FDD_NUM; i++) { - temp_fdd_types[i] = fdd_get_type(i); - temp_fdd_turbo[i] = fdd_get_turbo(i); - temp_fdd_check_bpb[i] = fdd_get_check_bpb(i); + temp_fdd_types[i] = fdd_get_type(i); + temp_fdd_turbo[i] = fdd_get_turbo(i); + temp_fdd_check_bpb[i] = fdd_get_check_bpb(i); } /* Other removable devices category */ memcpy(temp_cdrom, cdrom, CDROM_NUM * sizeof(cdrom_t)); for (i = 0; i < CDROM_NUM; i++) { - if (cdrom[i].bus_type == CDROM_BUS_ATAPI) - ide_tracking |= (2 << (cdrom[i].ide_channel << 3)); - else if (cdrom[i].bus_type == CDROM_BUS_SCSI) - scsi_tracking[cdrom[i].scsi_device_id >> 3] |= (1 << ((cdrom[i].scsi_device_id & 0x07) << 3)); + if (cdrom[i].bus_type == CDROM_BUS_ATAPI) + ide_tracking |= (2 << (cdrom[i].ide_channel << 3)); + else if (cdrom[i].bus_type == CDROM_BUS_SCSI) + scsi_tracking[cdrom[i].scsi_device_id >> 3] |= (1 << ((cdrom[i].scsi_device_id & 0x07) << 3)); } memcpy(temp_zip_drives, zip_drives, ZIP_NUM * sizeof(zip_drive_t)); for (i = 0; i < ZIP_NUM; i++) { - if (zip_drives[i].bus_type == ZIP_BUS_ATAPI) - ide_tracking |= (4 << (zip_drives[i].ide_channel << 3)); - else if (zip_drives[i].bus_type == ZIP_BUS_SCSI) - scsi_tracking[zip_drives[i].scsi_device_id >> 3] |= (1 << ((zip_drives[i].scsi_device_id & 0x07) << 3)); + if (zip_drives[i].bus_type == ZIP_BUS_ATAPI) + ide_tracking |= (4 << (zip_drives[i].ide_channel << 3)); + else if (zip_drives[i].bus_type == ZIP_BUS_SCSI) + scsi_tracking[zip_drives[i].scsi_device_id >> 3] |= (1 << ((zip_drives[i].scsi_device_id & 0x07) << 3)); } memcpy(temp_mo_drives, mo_drives, MO_NUM * sizeof(mo_drive_t)); for (i = 0; i < MO_NUM; i++) { - if (mo_drives[i].bus_type == MO_BUS_ATAPI) - ide_tracking |= (1 << (mo_drives[i].ide_channel << 3)); - else if (mo_drives[i].bus_type == MO_BUS_SCSI) - scsi_tracking[mo_drives[i].scsi_device_id >> 3] |= (1 << ((mo_drives[i].scsi_device_id & 0x07) << 3)); + if (mo_drives[i].bus_type == MO_BUS_ATAPI) + ide_tracking |= (1 << (mo_drives[i].ide_channel << 3)); + else if (mo_drives[i].bus_type == MO_BUS_SCSI) + scsi_tracking[mo_drives[i].scsi_device_id >> 3] |= (1 << ((mo_drives[i].scsi_device_id & 0x07) << 3)); } /* Other peripherals category */ - temp_bugger = bugger_enabled; + temp_bugger = bugger_enabled; temp_postcard = postcard_enabled; - temp_isartc = isartc_type; + temp_isartc = isartc_type; /* ISA memory boards. */ for (i = 0; i < ISAMEM_MAX; i++) - temp_isamem[i] = isamem_type[i]; + temp_isamem[i] = isamem_type[i]; temp_deviceconfig = 0; } - /* This returns 1 if any variable has changed, 0 if not. */ static int win_settings_changed(void) { - int i = 0, j = 0; + int i = 0; /* Machine category */ i = i || (machine != temp_machine); @@ -450,43 +493,50 @@ win_settings_changed(void) #ifdef USE_DYNAREC i = i || (temp_dynarec != cpu_use_dynarec); #endif + i = i || (temp_fpu_softfloat != fpu_softfloat); i = i || (temp_fpu != fpu_type); i = i || (temp_sync != time_sync); /* Video category */ - i = i || (gfxcard != temp_gfxcard); + i = i || (gfxcard[0] != temp_gfxcard[0]); + i = i || (gfxcard[1] != temp_gfxcard[1]); i = i || (voodoo_enabled != temp_voodoo); + i = i || (ibm8514_standalone_enabled != temp_ibm8514); + i = i || (xga_standalone_enabled != temp_xga); /* Input devices category */ i = i || (mouse_type != temp_mouse); i = i || (joystick_type != temp_joystick); /* Sound category */ - i = i || (sound_card_current != temp_sound_card); - i = i || (midi_device_current != temp_midi_device); + for (uint8_t j = 0; j < SOUND_CARD_MAX; j++) + i = i || (sound_card_current[j] != temp_sound_card[j]); + i = i || (midi_output_device_current != temp_midi_output_device); i = i || (midi_input_device_current != temp_midi_input_device); i = i || (mpu401_standalone_enable != temp_mpu401); - i = i || (SSI2001 != temp_SSI2001); - i = i || (GAMEBLASTER != temp_GAMEBLASTER); - i = i || (GUS != temp_GUS); i = i || (sound_is_float != temp_float); + i = i || (fm_driver != temp_fm_driver); /* Network category */ - i = i || (network_type != temp_net_type); - i = i || strcmp(temp_pcap_dev, network_host); - i = i || (network_card != temp_net_card); + for (uint8_t j = 0; j < NET_CARD_MAX; j++) { + i = i || (net_cards_conf[j].net_type != temp_net_type[j]); + i = i || strcmp(temp_pcap_dev[j], net_cards_conf[j].host_dev_name); + i = i || (net_cards_conf[j].device_num != temp_net_card[j]); + } /* Ports category */ - for (j = 0; j < PARALLEL_MAX; j++) { - i = i || (temp_lpt_devices[j] != lpt_ports[j].device); - i = i || (temp_lpt[j] != lpt_ports[j].enabled); + for (uint8_t j = 0; j < PARALLEL_MAX; j++) { + i = i || (temp_lpt_devices[j] != lpt_ports[j].device); + i = i || (temp_lpt[j] != lpt_ports[j].enabled); + } + for (uint8_t j = 0; j < SERIAL_MAX; j++) { + i = i || (temp_serial[j] != com_ports[j].enabled); + i = i || (temp_serial_passthrough_enabled[i] != serial_passthrough_enabled[i]); } - for (j = 0; j < SERIAL_MAX; j++) - i = i || (temp_serial[j] != serial_enabled[j]); /* Storage devices category */ - for (j = 0; j < SCSI_BUS_MAX; j++) - i = i || (temp_scsi_card[j] != scsi_card_current[j]); + for (uint8_t j = 0; j < SCSI_BUS_MAX; j++) + i = i || (temp_scsi_card[j] != scsi_card_current[j]); i = i || (fdc_type != temp_fdc_card); i = i || (hdc_current != temp_hdc); i = i || (temp_ide_ter != ide_ter_enabled); @@ -497,10 +547,10 @@ win_settings_changed(void) i = i || memcmp(hdd, temp_hdd, HDD_NUM * sizeof(hard_disk_t)); /* Floppy drives category */ - for (j = 0; j < FDD_NUM; j++) { - i = i || (temp_fdd_types[j] != fdd_get_type(j)); - i = i || (temp_fdd_turbo[j] != fdd_get_turbo(j)); - i = i || (temp_fdd_check_bpb[j] != fdd_get_check_bpb(j)); + for (uint8_t j = 0; j < FDD_NUM; j++) { + i = i || (temp_fdd_types[j] != fdd_get_type(j)); + i = i || (temp_fdd_turbo[j] != fdd_get_turbo(j)); + i = i || (temp_fdd_check_bpb[j] != fdd_get_check_bpb(j)); } /* Other removable devices category */ @@ -514,119 +564,123 @@ win_settings_changed(void) i = i || (temp_isartc != isartc_type); /* ISA memory boards. */ - for (j = 0; j < ISAMEM_MAX; j++) - i = i || (temp_isamem[j] != isamem_type[j]); + for (uint8_t j = 0; j < ISAMEM_MAX; j++) + i = i || (temp_isamem[j] != isamem_type[j]); i = i || !!temp_deviceconfig; return i; } - /* This saves the settings back to the global variables. */ static void win_settings_save(void) { - int i = 0; - pc_reset_hard_close(); /* Machine category */ - machine = temp_machine; - cpu_f = temp_cpu_f; + machine = temp_machine; + cpu_f = temp_cpu_f; cpu_waitstates = temp_wait_states; - cpu = temp_cpu; - mem_size = temp_mem_size; + cpu = temp_cpu; + mem_size = temp_mem_size; #ifdef USE_DYNAREC cpu_use_dynarec = temp_dynarec; #endif - fpu_type = temp_fpu; + fpu_softfloat = temp_fpu_softfloat; + fpu_type = temp_fpu; time_sync = temp_sync; /* Video category */ - gfxcard = temp_gfxcard; - voodoo_enabled = temp_voodoo; + gfxcard[0] = temp_gfxcard[0]; + gfxcard[1] = temp_gfxcard[1]; + voodoo_enabled = temp_voodoo; + ibm8514_standalone_enabled = temp_ibm8514; + xga_standalone_enabled = temp_xga; /* Input devices category */ - mouse_type = temp_mouse; + mouse_type = temp_mouse; joystick_type = temp_joystick; /* Sound category */ - sound_card_current = temp_sound_card; - midi_device_current = temp_midi_device; - midi_input_device_current = temp_midi_input_device; - mpu401_standalone_enable = temp_mpu401; - SSI2001 = temp_SSI2001; - GAMEBLASTER = temp_GAMEBLASTER; - GUS = temp_GUS; - sound_is_float = temp_float; + for (uint8_t i = 0; i < SOUND_CARD_MAX; i++) + sound_card_current[i] = temp_sound_card[i]; + midi_output_device_current = temp_midi_output_device; + midi_input_device_current = temp_midi_input_device; + mpu401_standalone_enable = temp_mpu401; + sound_is_float = temp_float; + fm_driver = temp_fm_driver; /* Network category */ - network_type = temp_net_type; - memset(network_host, '\0', sizeof(network_host)); - strcpy(network_host, temp_pcap_dev); - network_card = temp_net_card; + for (uint8_t i = 0; i < NET_CARD_MAX; i++) { + net_cards_conf[i].net_type = temp_net_type[i]; + memset(net_cards_conf[i].host_dev_name, '\0', sizeof(net_cards_conf[i].host_dev_name)); + strcpy(net_cards_conf[i].host_dev_name, temp_pcap_dev[i]); + net_cards_conf[i].device_num = temp_net_card[i]; + } /* Ports category */ - for (i = 0; i < PARALLEL_MAX; i++) { - lpt_ports[i].device = temp_lpt_devices[i]; - lpt_ports[i].enabled = temp_lpt[i]; + for (uint8_t i = 0; i < PARALLEL_MAX; i++) { + lpt_ports[i].device = temp_lpt_devices[i]; + lpt_ports[i].enabled = temp_lpt[i]; + } + for (uint8_t i = 0; i < SERIAL_MAX; i++) { + com_ports[i].enabled = temp_serial[i]; + serial_passthrough_enabled[i] = temp_serial_passthrough_enabled[i]; } - for (i = 0; i < SERIAL_MAX; i++) - serial_enabled[i] = temp_serial[i]; /* Storage devices category */ - for (i = 0; i < SCSI_BUS_MAX; i++) - scsi_card_current[i] = temp_scsi_card[i]; - hdc_current = temp_hdc; - fdc_type = temp_fdc_card; + for (uint8_t i = 0; i < SCSI_BUS_MAX; i++) + scsi_card_current[i] = temp_scsi_card[i]; + hdc_current = temp_hdc; + fdc_type = temp_fdc_card; ide_ter_enabled = temp_ide_ter; ide_qua_enabled = temp_ide_qua; cassette_enable = temp_cassette; /* Hard disks category */ memcpy(hdd, temp_hdd, HDD_NUM * sizeof(hard_disk_t)); - for (i = 0; i < HDD_NUM; i++) - hdd[i].priv = NULL; + for (uint8_t i = 0; i < HDD_NUM; i++) + hdd[i].priv = NULL; /* Floppy drives category */ - for (i = 0; i < FDD_NUM; i++) { - fdd_set_type(i, temp_fdd_types[i]); - fdd_set_turbo(i, temp_fdd_turbo[i]); - fdd_set_check_bpb(i, temp_fdd_check_bpb[i]); + for (uint8_t i = 0; i < FDD_NUM; i++) { + fdd_set_type(i, temp_fdd_types[i]); + fdd_set_turbo(i, temp_fdd_turbo[i]); + fdd_set_check_bpb(i, temp_fdd_check_bpb[i]); } /* Removable devices category */ memcpy(cdrom, temp_cdrom, CDROM_NUM * sizeof(cdrom_t)); - for (i = 0; i < CDROM_NUM; i++) { - cdrom[i].img_fp = NULL; - cdrom[i].priv = NULL; - cdrom[i].ops = NULL; - cdrom[i].image = NULL; - cdrom[i].insert = NULL; - cdrom[i].close = NULL; - cdrom[i].get_volume = NULL; - cdrom[i].get_channel = NULL; + for (uint8_t i = 0; i < CDROM_NUM; i++) { + cdrom[i].is_dir = 0; + cdrom[i].priv = NULL; + cdrom[i].ops = NULL; + cdrom[i].image = NULL; + cdrom[i].insert = NULL; + cdrom[i].close = NULL; + cdrom[i].get_volume = NULL; + cdrom[i].get_channel = NULL; } memcpy(zip_drives, temp_zip_drives, ZIP_NUM * sizeof(zip_drive_t)); - for (i = 0; i < ZIP_NUM; i++) { - zip_drives[i].f = NULL; - zip_drives[i].priv = NULL; + for (uint8_t i = 0; i < ZIP_NUM; i++) { + zip_drives[i].fp = NULL; + zip_drives[i].priv = NULL; } memcpy(mo_drives, temp_mo_drives, MO_NUM * sizeof(mo_drive_t)); - for (i = 0; i < MO_NUM; i++) { - mo_drives[i].f = NULL; - mo_drives[i].priv = NULL; + for (uint8_t i = 0; i < MO_NUM; i++) { + mo_drives[i].fp = NULL; + mo_drives[i].priv = NULL; } /* Other peripherals category */ - bugger_enabled = temp_bugger; + bugger_enabled = temp_bugger; postcard_enabled = temp_postcard; - isartc_type = temp_isartc; + isartc_type = temp_isartc; /* ISA memory boards. */ - for (i = 0; i < ISAMEM_MAX; i++) - isamem_type[i] = temp_isamem[i]; + for (uint8_t i = 0; i < ISAMEM_MAX; i++) + isamem_type[i] = temp_isamem[i]; /* Mark configuration as changed. */ config_changed = 2; @@ -634,12 +688,24 @@ win_settings_save(void) pc_reset_hard_init(); } +static void +win_settings_machine_recalc_softfloat(HWND hdlg) +{ + if (temp_fpu == FPU_NONE) { + settings_set_check(hdlg, IDC_CHECK_SOFTFLOAT, FALSE); + settings_enable_window(hdlg, IDC_CHECK_SOFTFLOAT, FALSE); + } else { + settings_set_check(hdlg, IDC_CHECK_SOFTFLOAT, (machine_has_flags(temp_machine, MACHINE_SOFTFLOAT_ONLY) ? TRUE : temp_fpu_softfloat)); + settings_enable_window(hdlg, IDC_CHECK_SOFTFLOAT, (machine_has_flags(temp_machine, MACHINE_SOFTFLOAT_ONLY) ? FALSE : TRUE)); + } +} static void win_settings_machine_recalc_fpu(HWND hdlg) { - int c, type; - LPTSTR lptsTemp; + int c; + int type; + LPTSTR lptsTemp; const char *stransi; lptsTemp = (LPTSTR) malloc(512 * sizeof(WCHAR)); @@ -647,24 +713,25 @@ win_settings_machine_recalc_fpu(HWND hdlg) settings_reset_content(hdlg, IDC_COMBO_FPU); c = 0; while (1) { - stransi = (char *) fpu_get_name_from_index(temp_cpu_f, temp_cpu, c); - type = fpu_get_type_from_index(temp_cpu_f, temp_cpu, c); - if (!stransi) - break; + stransi = fpu_get_name_from_index(temp_cpu_f, temp_cpu, c); + type = fpu_get_type_from_index(temp_cpu_f, temp_cpu, c); + if (!stransi) + break; - mbstowcs(lptsTemp, stransi, strlen(stransi) + 1); - settings_add_string(hdlg, IDC_COMBO_FPU, (LPARAM)(LPCSTR)lptsTemp); - if (!c || (type == temp_fpu)) - settings_set_cur_sel(hdlg, IDC_COMBO_FPU, c); + mbstowcs(lptsTemp, stransi, strlen(stransi) + 1); + settings_add_string(hdlg, IDC_COMBO_FPU, (LPARAM) (LPCSTR) lptsTemp); + if (!c || (type == temp_fpu)) + settings_set_cur_sel(hdlg, IDC_COMBO_FPU, c); - c++; + c++; } settings_enable_window(hdlg, IDC_COMBO_FPU, c > 1); temp_fpu = fpu_get_type_from_index(temp_cpu_f, temp_cpu, settings_get_cur_sel(hdlg, IDC_COMBO_FPU)); -} + win_settings_machine_recalc_softfloat(hdlg); +} static void win_settings_machine_recalc_cpu(HWND hdlg) @@ -680,58 +747,61 @@ win_settings_machine_recalc_cpu(HWND hdlg) #ifdef USE_DYNAREC cpu_flags = temp_cpu_f->cpus[temp_cpu].cpu_flags; if (!(cpu_flags & CPU_SUPPORTS_DYNAREC) && (cpu_flags & CPU_REQUIRES_DYNAREC)) - fatal("Attempting to select a CPU that requires the recompiler and does not support it at the same time\n"); - if (!(cpu_flags & CPU_SUPPORTS_DYNAREC) || (cpu_flags & CPU_REQUIRES_DYNAREC)) { - if (!(cpu_flags & CPU_SUPPORTS_DYNAREC)) - temp_dynarec = 0; - if (cpu_flags & CPU_REQUIRES_DYNAREC) - temp_dynarec = 1; - settings_set_check(hdlg, IDC_CHECK_DYNAREC, temp_dynarec); - settings_enable_window(hdlg, IDC_CHECK_DYNAREC, FALSE); + fatal("Attempting to select a CPU that requires the recompiler and does not support it at the same time\n"); + if (!(cpu_flags & CPU_SUPPORTS_DYNAREC) || ((cpu_flags & CPU_REQUIRES_DYNAREC) && !cpu_override)) { + if (!(cpu_flags & CPU_SUPPORTS_DYNAREC)) + temp_dynarec = 0; + if (cpu_flags & CPU_REQUIRES_DYNAREC) + temp_dynarec = 1; + settings_set_check(hdlg, IDC_CHECK_DYNAREC, temp_dynarec); + settings_enable_window(hdlg, IDC_CHECK_DYNAREC, FALSE); } else { - settings_set_check(hdlg, IDC_CHECK_DYNAREC, temp_dynarec); - settings_enable_window(hdlg, IDC_CHECK_DYNAREC, TRUE); + settings_set_check(hdlg, IDC_CHECK_DYNAREC, temp_dynarec); + settings_enable_window(hdlg, IDC_CHECK_DYNAREC, TRUE); } #endif win_settings_machine_recalc_fpu(hdlg); } - static void win_settings_machine_recalc_cpu_m(HWND hdlg) { - int c, i, first_eligible = -1, current_eligible = 0, last_eligible = 0; - LPTSTR lptsTemp; - char *stransi; + int c; + int i; + int first_eligible = -1; + int current_eligible = 0; + int last_eligible = 0; + LPTSTR lptsTemp; + const char *stransi; lptsTemp = (LPTSTR) malloc(512 * sizeof(WCHAR)); settings_reset_content(hdlg, IDC_COMBO_CPU_SPEED); c = i = 0; while (temp_cpu_f->cpus[c].cpu_type != 0) { - if (cpu_is_eligible(temp_cpu_f, c, temp_machine)) { - stransi = (char *) temp_cpu_f->cpus[c].name; - mbstowcs(lptsTemp, stransi, strlen(stransi) + 1); - settings_add_string(hdlg, IDC_COMBO_CPU_SPEED, (LPARAM)(LPCSTR)lptsTemp); + if (cpu_is_eligible(temp_cpu_f, c, temp_machine)) { + stransi = (char *) temp_cpu_f->cpus[c].name; + mbstowcs(lptsTemp, stransi, strlen(stransi) + 1); + settings_add_string(hdlg, IDC_COMBO_CPU_SPEED, (LPARAM) (LPCSTR) lptsTemp); - if (first_eligible == -1) - first_eligible = i; - if (temp_cpu == c) - current_eligible = i; - last_eligible = i; + if (first_eligible == -1) + first_eligible = i; + if (temp_cpu == c) + current_eligible = i; + last_eligible = i; - listtocpu[i++] = c; - } - c++; + listtocpu[i++] = c; + } + c++; } if (i == 0) - fatal("No eligible CPUs for the selected family\n"); + fatal("No eligible CPUs for the selected family\n"); settings_enable_window(hdlg, IDC_COMBO_CPU_SPEED, i != 1); if (current_eligible < first_eligible) - current_eligible = first_eligible; + current_eligible = first_eligible; else if (current_eligible > last_eligible) - current_eligible = last_eligible; + current_eligible = last_eligible; temp_cpu = listtocpu[current_eligible]; settings_set_cur_sel(hdlg, IDC_COMBO_CPU_SPEED, current_eligible); @@ -740,78 +810,79 @@ win_settings_machine_recalc_cpu_m(HWND hdlg) free(lptsTemp); } - static void win_settings_machine_recalc_machine(HWND hdlg) { - HWND h; - int c, i, current_eligible; - LPTSTR lptsTemp; - char *stransi; - UDACCEL accel; - device_t *d; + HWND h; + int c; + int i; + int current_eligible; + LPTSTR lptsTemp; + char *stransi; + UDACCEL accel; + const device_t *d; lptsTemp = (LPTSTR) malloc(512 * sizeof(WCHAR)); - d = (device_t *) machine_getdevice(temp_machine); + d = (device_t *) machine_get_device(temp_machine); settings_enable_window(hdlg, IDC_CONFIGURE_MACHINE, d && d->config); settings_reset_content(hdlg, IDC_COMBO_CPU_TYPE); - c = i = 0; + c = i = 0; current_eligible = -1; while (cpu_families[c].package != 0) { - if (cpu_family_is_eligible(&cpu_families[c], temp_machine)) { - stransi = malloc(strlen((char *) cpu_families[c].manufacturer) + strlen((char *) cpu_families[c].name) + 2); - sprintf(stransi, "%s %s", (char *) cpu_families[c].manufacturer, (char *) cpu_families[c].name); - mbstowcs(lptsTemp, stransi, strlen(stransi) + 1); - free(stransi); - settings_add_string(hdlg, IDC_COMBO_CPU_TYPE, (LPARAM)(LPCSTR)lptsTemp); - if (&cpu_families[c] == temp_cpu_f) - current_eligible = i; - listtocpufamily[i++] = c; - } - c++; + if (cpu_family_is_eligible(&cpu_families[c], temp_machine)) { + stransi = malloc(strlen((char *) cpu_families[c].manufacturer) + strlen((char *) cpu_families[c].name) + 2); + sprintf(stransi, "%s %s", (char *) cpu_families[c].manufacturer, (char *) cpu_families[c].name); + mbstowcs(lptsTemp, stransi, strlen(stransi) + 1); + free(stransi); + settings_add_string(hdlg, IDC_COMBO_CPU_TYPE, (LPARAM) (LPCSTR) lptsTemp); + if (&cpu_families[c] == temp_cpu_f) + current_eligible = i; + listtocpufamily[i++] = c; + } + c++; } if (i == 0) - fatal("No eligible CPU families for the selected machine\n"); + fatal("No eligible CPU families for the selected machine\n"); settings_enable_window(hdlg, IDC_COMBO_CPU_TYPE, TRUE); if (current_eligible == -1) { - temp_cpu_f = (cpu_family_t *) &cpu_families[listtocpufamily[0]]; - settings_set_cur_sel(hdlg, IDC_COMBO_CPU_TYPE, 0); + temp_cpu_f = (cpu_family_t *) &cpu_families[listtocpufamily[0]]; + settings_set_cur_sel(hdlg, IDC_COMBO_CPU_TYPE, 0); } else { - settings_set_cur_sel(hdlg, IDC_COMBO_CPU_TYPE, current_eligible); + settings_set_cur_sel(hdlg, IDC_COMBO_CPU_TYPE, current_eligible); } settings_enable_window(hdlg, IDC_COMBO_CPU_TYPE, i != 1); win_settings_machine_recalc_cpu_m(hdlg); if (machine_get_ram_granularity(temp_machine) & 1023) { - /* KB granularity */ - h = GetDlgItem(hdlg, IDC_MEMSPIN); - SendMessage(h, UDM_SETRANGE, 0, (machine_get_min_ram(temp_machine) << 16) | machine_get_max_ram(temp_machine)); + /* KB granularity */ + h = GetDlgItem(hdlg, IDC_MEMSPIN); + SendMessage(h, UDM_SETRANGE, 0, (machine_get_min_ram(temp_machine) << 16) | machine_get_max_ram(temp_machine)); - accel.nSec = 0; - accel.nInc = machine_get_ram_granularity(temp_machine); - SendMessage(h, UDM_SETACCEL, 1, (LPARAM)&accel); + accel.nSec = 0; + accel.nInc = machine_get_ram_granularity(temp_machine); + SendMessage(h, UDM_SETACCEL, 1, (LPARAM) &accel); - SendMessage(h, UDM_SETPOS, 0, temp_mem_size); + SendMessage(h, UDM_SETPOS, 0, temp_mem_size); - h = GetDlgItem(hdlg, IDC_TEXT_MB); - SendMessage(h, WM_SETTEXT, 0, win_get_string(IDS_2088)); + h = GetDlgItem(hdlg, IDC_TEXT_MB); + SendMessage(h, WM_SETTEXT, 0, win_get_string(IDS_KB)); } else { - /* MB granularity */ - h = GetDlgItem(hdlg, IDC_MEMSPIN); - SendMessage(h, UDM_SETRANGE, 0, (machine_get_min_ram(temp_machine) << 6) | (machine_get_max_ram(temp_machine) >> 10)); + /* MB granularity */ + h = GetDlgItem(hdlg, IDC_MEMSPIN); + SendMessage(h, UDM_SETRANGE, 0, (machine_get_min_ram(temp_machine) << 6) | (machine_get_max_ram(temp_machine) >> 10)); - accel.nSec = 0; - accel.nInc = machine_get_ram_granularity(temp_machine) >> 10; + accel.nSec = 0; + accel.nInc = machine_get_ram_granularity(temp_machine) >> 10; - SendMessage(h, UDM_SETACCEL, 1, (LPARAM)&accel); + SendMessage(h, UDM_SETACCEL, 1, (LPARAM) &accel); - SendMessage(h, UDM_SETPOS, 0, temp_mem_size >> 10); + SendMessage(h, UDM_SETPOS, 0, temp_mem_size >> 10); - h = GetDlgItem(hdlg, IDC_TEXT_MB); - SendMessage(h, WM_SETTEXT, 0, win_get_string(IDS_2086)); + h = GetDlgItem(hdlg, IDC_TEXT_MB); + SendMessage(h, WM_SETTEXT, 0, win_get_string(IDS_MB)); } settings_enable_window(hdlg, IDC_MEMSPIN, machine_get_min_ram(temp_machine) != machine_get_max_ram(temp_machine)); @@ -820,453 +891,580 @@ win_settings_machine_recalc_machine(HWND hdlg) free(lptsTemp); } - static char * machine_type_get_internal_name(int id) { if (id < MACHINE_TYPE_MAX) - return ""; + return ""; else - return NULL; + return NULL; } - int machine_type_available(int id) { int c = 0; if ((id > 0) && (id < MACHINE_TYPE_MAX)) { - while (machine_get_internal_name_ex(c) != NULL) { - if (machine_available(c) && (machine_get_type(c) == id)) - return 1; - c++; - } + while (machine_get_internal_name_ex(c) != NULL) { + if (machine_available(c) && (machine_get_type(c) == id)) + return 1; + c++; + } } return 0; } - #if defined(__amd64__) || defined(__aarch64__) static LRESULT CALLBACK #else static BOOL CALLBACK #endif -win_settings_machine_proc(HWND hdlg, UINT message, WPARAM wParam, LPARAM lParam) +win_settings_machine_proc(HWND hdlg, UINT message, WPARAM wParam, UNUSED(LPARAM lParam)) { - HWND h, h2; - int c, d; - int old_machine_type; + HWND h; + HWND h2; + int c; + int d; + int old_machine_type; LPTSTR lptsTemp; - char *stransi; + char *stransi; switch (message) { - case WM_INITDIALOG: - lptsTemp = (LPTSTR) malloc(512 * sizeof(WCHAR)); + case WM_INITDIALOG: + lptsTemp = (LPTSTR) malloc(512 * sizeof(WCHAR)); - c = d = 0; - settings_reset_content(hdlg, IDC_COMBO_MACHINE_TYPE); - memset(listtomachinetype, 0x00, sizeof(listtomachinetype)); - while (machine_type_get_internal_name(c) != NULL) { - if (machine_type_available(c)) { - stransi = (char *)machine_types[c].name; - mbstowcs(lptsTemp, stransi, strlen(stransi) + 1); - settings_add_string(hdlg, IDC_COMBO_MACHINE_TYPE, (LPARAM) lptsTemp); - listtomachinetype[d] = c; - if (c == temp_machine_type) - settings_set_cur_sel(hdlg, IDC_COMBO_MACHINE_TYPE, d); - d++; - } - c++; - } + c = d = 0; + settings_reset_content(hdlg, IDC_COMBO_MACHINE_TYPE); + memset(listtomachinetype, 0x00, sizeof(listtomachinetype)); + while (machine_type_get_internal_name(c) != NULL) { + if (machine_type_available(c)) { + stransi = (char *) machine_types[c].name; + mbstowcs(lptsTemp, stransi, strlen(stransi) + 1); + settings_add_string(hdlg, IDC_COMBO_MACHINE_TYPE, (LPARAM) lptsTemp); + listtomachinetype[d] = c; + if (c == temp_machine_type) + settings_set_cur_sel(hdlg, IDC_COMBO_MACHINE_TYPE, d); + d++; + } + c++; + } - c = d = 0; - settings_reset_content(hdlg, IDC_COMBO_MACHINE); - memset(listtomachine, 0x00, sizeof(listtomachine)); - while (machine_get_internal_name_ex(c) != NULL) { - if (machine_available(c) && (machine_get_type(c) == temp_machine_type)) { - stransi = machine_getname_ex(c); - mbstowcs(lptsTemp, stransi, strlen(stransi) + 1); - settings_add_string(hdlg, IDC_COMBO_MACHINE, (LPARAM) lptsTemp); - listtomachine[d] = c; - if (c == temp_machine) - settings_set_cur_sel(hdlg, IDC_COMBO_MACHINE, d); - d++; - } - c++; - } + c = d = 0; + settings_reset_content(hdlg, IDC_COMBO_MACHINE); + memset(listtomachine, 0x00, sizeof(listtomachine)); + while (machine_get_internal_name_ex(c) != NULL) { + if (machine_available(c) && (machine_get_type(c) == temp_machine_type)) { + stransi = (char *) machine_getname_ex(c); + mbstowcs(lptsTemp, stransi, strlen(stransi) + 1); + settings_add_string(hdlg, IDC_COMBO_MACHINE, (LPARAM) lptsTemp); + listtomachine[d] = c; + if (c == temp_machine) + settings_set_cur_sel(hdlg, IDC_COMBO_MACHINE, d); + d++; + } + c++; + } - settings_add_string(hdlg, IDC_COMBO_WS, win_get_string(IDS_2090)); - for (c = 0; c < 8; c++) { - wsprintf(lptsTemp, plat_get_string(IDS_2091), c); - settings_add_string(hdlg, IDC_COMBO_WS, (LPARAM) lptsTemp); - } + settings_add_string(hdlg, IDC_COMBO_WS, win_get_string(IDS_DEFAULT)); + for (c = 0; c < 8; c++) { /* TODO */ + wsprintf(lptsTemp, plat_get_string(IDS_WS), c); + settings_add_string(hdlg, IDC_COMBO_WS, (LPARAM) lptsTemp); + } - settings_set_cur_sel(hdlg, IDC_COMBO_WS, temp_wait_states); + settings_set_cur_sel(hdlg, IDC_COMBO_WS, temp_wait_states); #ifdef USE_DYNAREC - settings_set_check(hdlg, IDC_CHECK_DYNAREC, 0); + settings_set_check(hdlg, IDC_CHECK_DYNAREC, 0); #endif - h = GetDlgItem(hdlg, IDC_MEMSPIN); - h2 = GetDlgItem(hdlg, IDC_MEMTEXT); - SendMessage(h, UDM_SETBUDDY, (WPARAM)h2, 0); + settings_set_check(hdlg, IDC_CHECK_SOFTFLOAT, 0); - if (temp_sync & TIME_SYNC_ENABLED) { - if (temp_sync & TIME_SYNC_UTC) - settings_set_check(hdlg, IDC_RADIO_TS_UTC, BST_CHECKED); - else - settings_set_check(hdlg, IDC_RADIO_TS_LOCAL, BST_CHECKED); - } else - settings_set_check(hdlg, IDC_RADIO_TS_DISABLED, BST_CHECKED); + h = GetDlgItem(hdlg, IDC_MEMSPIN); + h2 = GetDlgItem(hdlg, IDC_MEMTEXT); + SendMessage(h, UDM_SETBUDDY, (WPARAM) h2, 0); - win_settings_machine_recalc_machine(hdlg); + if (temp_sync & TIME_SYNC_ENABLED) { + if (temp_sync & TIME_SYNC_UTC) + settings_set_check(hdlg, IDC_RADIO_TS_UTC, BST_CHECKED); + else + settings_set_check(hdlg, IDC_RADIO_TS_LOCAL, BST_CHECKED); + } else + settings_set_check(hdlg, IDC_RADIO_TS_DISABLED, BST_CHECKED); - free(lptsTemp); + win_settings_machine_recalc_machine(hdlg); - return TRUE; + free(lptsTemp); - case WM_COMMAND: - switch (LOWORD(wParam)) { - case IDC_COMBO_MACHINE_TYPE: - if (HIWORD(wParam) == CBN_SELCHANGE) { - old_machine_type = temp_machine_type; - temp_machine_type = listtomachinetype[settings_get_cur_sel(hdlg, IDC_COMBO_MACHINE_TYPE)]; + return TRUE; - lptsTemp = (LPTSTR) malloc(512 * sizeof(WCHAR)); + case WM_COMMAND: + switch (LOWORD(wParam)) { + case IDC_COMBO_MACHINE_TYPE: + if (HIWORD(wParam) == CBN_SELCHANGE) { + old_machine_type = temp_machine_type; + temp_machine_type = listtomachinetype[settings_get_cur_sel(hdlg, IDC_COMBO_MACHINE_TYPE)]; - settings_reset_content(hdlg, IDC_COMBO_MACHINE); - c = d = 0; - memset(listtomachine, 0x00, sizeof(listtomachine)); - while (machine_get_internal_name_ex(c) != NULL) { - if (machine_available(c) && (machine_get_type(c) == temp_machine_type)) { - stransi = machine_getname_ex(c); - mbstowcs(lptsTemp, stransi, strlen(stransi) + 1); - settings_add_string(hdlg, IDC_COMBO_MACHINE, (LPARAM) lptsTemp); - listtomachine[d] = c; - if (c == temp_machine) - settings_set_cur_sel(hdlg, IDC_COMBO_MACHINE, d); - d++; - } - c++; - } - if (old_machine_type != temp_machine_type) { - settings_set_cur_sel(hdlg, IDC_COMBO_MACHINE, 0); - temp_machine = listtomachine[0]; + lptsTemp = (LPTSTR) malloc(512 * sizeof(WCHAR)); - win_settings_machine_recalc_machine(hdlg); - } + settings_reset_content(hdlg, IDC_COMBO_MACHINE); + c = d = 0; + memset(listtomachine, 0x00, sizeof(listtomachine)); + while (machine_get_internal_name_ex(c) != NULL) { + if (machine_available(c) && (machine_get_type(c) == temp_machine_type)) { + stransi = (char *) machine_getname_ex(c); + mbstowcs(lptsTemp, stransi, strlen(stransi) + 1); + settings_add_string(hdlg, IDC_COMBO_MACHINE, (LPARAM) lptsTemp); + listtomachine[d] = c; + if (c == temp_machine) + settings_set_cur_sel(hdlg, IDC_COMBO_MACHINE, d); + d++; + } + c++; + } + if (old_machine_type != temp_machine_type) { + settings_set_cur_sel(hdlg, IDC_COMBO_MACHINE, 0); + temp_machine = listtomachine[0]; - free(lptsTemp); - } - break; - case IDC_COMBO_MACHINE: - if (HIWORD(wParam) == CBN_SELCHANGE) { - temp_machine = listtomachine[settings_get_cur_sel(hdlg, IDC_COMBO_MACHINE)]; - win_settings_machine_recalc_machine(hdlg); - } - break; - case IDC_COMBO_CPU_TYPE: - if (HIWORD(wParam) == CBN_SELCHANGE) { - temp_cpu_f = (cpu_family_t *) &cpu_families[listtocpufamily[settings_get_cur_sel(hdlg, IDC_COMBO_CPU_TYPE)]]; - temp_cpu = 0; - win_settings_machine_recalc_cpu_m(hdlg); - } - break; - case IDC_COMBO_CPU_SPEED: - if (HIWORD(wParam) == CBN_SELCHANGE) { - temp_cpu = listtocpu[settings_get_cur_sel(hdlg, IDC_COMBO_CPU_SPEED)]; - win_settings_machine_recalc_cpu(hdlg); - } - break; - case IDC_COMBO_FPU: - if (HIWORD(wParam) == CBN_SELCHANGE) { - temp_fpu = fpu_get_type_from_index(temp_cpu_f, temp_cpu, - settings_get_cur_sel(hdlg, IDC_COMBO_FPU)); - } - break; - case IDC_CONFIGURE_MACHINE: - temp_machine = listtomachine[settings_get_cur_sel(hdlg, IDC_COMBO_MACHINE)]; - temp_deviceconfig |= deviceconfig_open(hdlg, (void *)machine_getdevice(temp_machine)); - break; - } + win_settings_machine_recalc_machine(hdlg); + } - return FALSE; + free(lptsTemp); + } + break; + case IDC_COMBO_MACHINE: + if (HIWORD(wParam) == CBN_SELCHANGE) { + temp_machine = listtomachine[settings_get_cur_sel(hdlg, IDC_COMBO_MACHINE)]; + win_settings_machine_recalc_machine(hdlg); + } + break; + case IDC_COMBO_CPU_TYPE: + if (HIWORD(wParam) == CBN_SELCHANGE) { + temp_cpu_f = (cpu_family_t *) &cpu_families[listtocpufamily[settings_get_cur_sel(hdlg, IDC_COMBO_CPU_TYPE)]]; + temp_cpu = 0; + win_settings_machine_recalc_cpu_m(hdlg); + } + break; + case IDC_COMBO_CPU_SPEED: + if (HIWORD(wParam) == CBN_SELCHANGE) { + temp_cpu = listtocpu[settings_get_cur_sel(hdlg, IDC_COMBO_CPU_SPEED)]; + win_settings_machine_recalc_cpu(hdlg); + } + break; + case IDC_COMBO_FPU: + if (HIWORD(wParam) == CBN_SELCHANGE) { + temp_fpu = fpu_get_type_from_index(temp_cpu_f, temp_cpu, + settings_get_cur_sel(hdlg, IDC_COMBO_FPU)); + } + win_settings_machine_recalc_softfloat(hdlg); + break; + case IDC_CONFIGURE_MACHINE: + temp_machine = listtomachine[settings_get_cur_sel(hdlg, IDC_COMBO_MACHINE)]; + temp_deviceconfig |= deviceconfig_open(hdlg, (void *) machine_get_device(temp_machine)); + break; + } - case WM_SAVESETTINGS: - lptsTemp = (LPTSTR) malloc(512 * sizeof(WCHAR)); - stransi = (char *)malloc(512); + return FALSE; + + case WM_SAVESETTINGS: + lptsTemp = (LPTSTR) malloc(512 * sizeof(WCHAR)); + stransi = (char *) malloc(512); #ifdef USE_DYNAREC - temp_dynarec = settings_get_check(hdlg, IDC_CHECK_DYNAREC); + temp_dynarec = settings_get_check(hdlg, IDC_CHECK_DYNAREC); #endif - if (settings_get_check(hdlg, IDC_RADIO_TS_DISABLED)) - temp_sync = TIME_SYNC_DISABLED; + temp_fpu_softfloat = settings_get_check(hdlg, IDC_CHECK_SOFTFLOAT); - if (settings_get_check(hdlg, IDC_RADIO_TS_LOCAL)) - temp_sync = TIME_SYNC_ENABLED; + if (settings_get_check(hdlg, IDC_RADIO_TS_DISABLED)) + temp_sync = TIME_SYNC_DISABLED; - if (settings_get_check(hdlg, IDC_RADIO_TS_UTC)) - temp_sync = TIME_SYNC_ENABLED | TIME_SYNC_UTC; + if (settings_get_check(hdlg, IDC_RADIO_TS_LOCAL)) + temp_sync = TIME_SYNC_ENABLED; - temp_wait_states = settings_get_cur_sel(hdlg, IDC_COMBO_WS); + if (settings_get_check(hdlg, IDC_RADIO_TS_UTC)) + temp_sync = TIME_SYNC_ENABLED | TIME_SYNC_UTC; - h = GetDlgItem(hdlg, IDC_MEMTEXT); - SendMessage(h, WM_GETTEXT, 255, (LPARAM) lptsTemp); - wcstombs(stransi, lptsTemp, 512); - sscanf(stransi, "%u", &temp_mem_size); - if (!(machine_get_ram_granularity(temp_machine) & 1023)) - temp_mem_size = temp_mem_size << 10; - temp_mem_size &= ~(machine_get_ram_granularity(temp_machine) - 1); - if (temp_mem_size < machine_get_min_ram(temp_machine)) - temp_mem_size = machine_get_min_ram(temp_machine); - else if (temp_mem_size > machine_get_max_ram(temp_machine)) - temp_mem_size = machine_get_max_ram(temp_machine); - free(stransi); - free(lptsTemp); + temp_wait_states = settings_get_cur_sel(hdlg, IDC_COMBO_WS); - default: - return FALSE; + h = GetDlgItem(hdlg, IDC_MEMTEXT); + SendMessage(h, WM_GETTEXT, 255, (LPARAM) lptsTemp); + wcstombs(stransi, lptsTemp, 512); + sscanf(stransi, "%u", &temp_mem_size); + if (!(machine_get_ram_granularity(temp_machine) & 1023)) + temp_mem_size = temp_mem_size << 10; + temp_mem_size &= ~(machine_get_ram_granularity(temp_machine) - 1); + if (temp_mem_size < machine_get_min_ram(temp_machine)) + temp_mem_size = machine_get_min_ram(temp_machine); + else if (temp_mem_size > machine_get_max_ram(temp_machine)) + temp_mem_size = machine_get_max_ram(temp_machine); + free(stransi); + free(lptsTemp); + + default: + return FALSE; } return FALSE; } - static void -generate_device_name(const device_t *device, char *internal_name, int bus) +generate_device_name(const device_t *device, const char *internal_name, int bus) { - char temp[512]; - WCHAR *wtemp; + char temp[512]; + const WCHAR *wtemp; memset(device_name, 0x00, 512 * sizeof(WCHAR)); memset(temp, 0x00, 512); if (!strcmp(internal_name, "none")) { - /* Translate "None". */ - wtemp = (WCHAR *) win_get_string(IDS_2103); - memcpy(device_name, wtemp, (wcslen(wtemp) + 1) * sizeof(WCHAR)); - return; + /* Translate "None". */ + wtemp = (WCHAR *) win_get_string(IDS_2104); + memcpy(device_name, wtemp, (wcslen(wtemp) + 1) * sizeof(WCHAR)); + return; } else if (!strcmp(internal_name, "internal")) - memcpy(temp, "Internal", 9); + memcpy(temp, "Internal", 9); else - device_get_name(device, bus, temp); + device_get_name(device, bus, temp); mbstowcs(device_name, temp, strlen(temp) + 1); } - #if defined(__amd64__) || defined(__aarch64__) static LRESULT CALLBACK #else static BOOL CALLBACK #endif -win_settings_video_proc(HWND hdlg, UINT message, WPARAM wParam, LPARAM lParam) +win_settings_video_proc(HWND hdlg, UINT message, WPARAM wParam, UNUSED(LPARAM lParam)) { - int c = 0, d = 0; + int c = 0; + int d = 0; int e; switch (message) { - case WM_INITDIALOG: - settings_reset_content(hdlg, IDC_COMBO_VIDEO); + case WM_INITDIALOG: + // Primary Video Card + settings_reset_content(hdlg, IDC_COMBO_VIDEO); - while (1) { - /* Skip "internal" if machine doesn't have it. */ - if ((c == 1) && !machine_has_flags(temp_machine, MACHINE_VIDEO)) { - c++; - continue; - } + while (1) { + /* Skip "internal" if machine doesn't have it. */ + if ((c == 1) && !machine_has_flags(temp_machine, MACHINE_VIDEO)) { + c++; + continue; + } - generate_device_name(video_card_getdevice(c), video_get_internal_name(c), 1); + generate_device_name(video_card_getdevice(c), video_get_internal_name(c), 1); - if (!device_name[0]) - break; + if (!device_name[0]) + break; - if (video_card_available(c) && - device_is_valid(video_card_getdevice(c), temp_machine)) { - if (c == 0) - settings_add_string(hdlg, IDC_COMBO_VIDEO, win_get_string(IDS_2103)); - else if (c == 1) - settings_add_string(hdlg, IDC_COMBO_VIDEO, win_get_string(IDS_2118)); - else - settings_add_string(hdlg, IDC_COMBO_VIDEO, (LPARAM) device_name); - settings_list_to_device[0][d] = c; - if ((c == 0) || (c == temp_gfxcard)) - settings_set_cur_sel(hdlg, IDC_COMBO_VIDEO, d); - d++; - } + if (video_card_available(c) && device_is_valid(video_card_getdevice(c), temp_machine)) { + if (c == 0) // "None" + settings_add_string(hdlg, IDC_COMBO_VIDEO, win_get_string(IDS_2104)); + else if (c == 1) // "Internal" + settings_add_string(hdlg, IDC_COMBO_VIDEO, win_get_string(IDS_2119)); + else + settings_add_string(hdlg, IDC_COMBO_VIDEO, (LPARAM) device_name); + settings_list_to_device[0][d] = c; + if ((c == 0) || (c == temp_gfxcard[0])) + settings_set_cur_sel(hdlg, IDC_COMBO_VIDEO, d); + d++; + } - c++; + c++; - settings_process_messages(); - } + settings_process_messages(); + } - settings_enable_window(hdlg, IDC_COMBO_VIDEO, !machine_has_flags(temp_machine, MACHINE_VIDEO_ONLY)); - e = settings_list_to_device[0][settings_get_cur_sel(hdlg, IDC_COMBO_VIDEO)]; - settings_enable_window(hdlg, IDC_CONFIGURE_VID, video_card_has_config(e)); - settings_enable_window(hdlg, IDC_CHECK_VOODOO, machine_has_bus(temp_machine, MACHINE_BUS_PCI)); - settings_set_check(hdlg, IDC_CHECK_VOODOO, temp_voodoo); - settings_enable_window(hdlg, IDC_BUTTON_VOODOO, machine_has_bus(temp_machine, MACHINE_BUS_PCI) && temp_voodoo); - return TRUE; + settings_enable_window(hdlg, IDC_COMBO_VIDEO, !machine_has_flags(temp_machine, MACHINE_VIDEO_ONLY)); + e = settings_list_to_device[0][settings_get_cur_sel(hdlg, IDC_COMBO_VIDEO)]; + settings_enable_window(hdlg, IDC_CONFIGURE_VID, video_card_has_config(e)); - case WM_COMMAND: - switch (LOWORD(wParam)) { - case IDC_COMBO_VIDEO: - temp_gfxcard = settings_list_to_device[0][settings_get_cur_sel(hdlg, IDC_COMBO_VIDEO)]; - settings_enable_window(hdlg, IDC_CONFIGURE_VID, video_card_has_config(temp_gfxcard)); - break; + // Secondary Video Card + c = d = 0; + settings_reset_content(hdlg, IDC_COMBO_VIDEO_2); - case IDC_CHECK_VOODOO: - temp_voodoo = settings_get_check(hdlg, IDC_CHECK_VOODOO); - settings_enable_window(hdlg, IDC_BUTTON_VOODOO, temp_voodoo); - break; + while (1) { + /* Skip "internal" if machine doesn't have it. */ + if ((c == 1) && !machine_has_flags(temp_machine, MACHINE_VIDEO)) { + c++; + continue; + } - case IDC_BUTTON_VOODOO: - temp_deviceconfig |= deviceconfig_open(hdlg, (void *)&voodoo_device); - break; + generate_device_name(video_card_getdevice(c), video_get_internal_name(c), 1); - case IDC_CONFIGURE_VID: - temp_gfxcard = settings_list_to_device[0][settings_get_cur_sel(hdlg, IDC_COMBO_VIDEO)]; - temp_deviceconfig |= deviceconfig_open(hdlg, (void *)video_card_getdevice(temp_gfxcard)); - break; - } - return FALSE; + if (!device_name[0]) + break; - case WM_SAVESETTINGS: - temp_gfxcard = settings_list_to_device[0][settings_get_cur_sel(hdlg, IDC_COMBO_VIDEO)]; - temp_voodoo = settings_get_check(hdlg, IDC_CHECK_VOODOO); + if ((c > 1) && (video_card_get_flags(c) == video_card_get_flags(temp_gfxcard[0]))) { + c++; + continue; + } - default: - return FALSE; + if (video_card_available(c) && device_is_valid(video_card_getdevice(c), temp_machine)) { + if (c == 0) // "None" + settings_add_string(hdlg, IDC_COMBO_VIDEO_2, win_get_string(IDS_2104)); + else if (c == 1) // "Internal" + settings_add_string(hdlg, IDC_COMBO_VIDEO_2, win_get_string(IDS_2119)); + else + settings_add_string(hdlg, IDC_COMBO_VIDEO_2, (LPARAM) device_name); + settings_list_to_device[1][d] = c; + if ((c == 0) || (c == temp_gfxcard[1])) + settings_set_cur_sel(hdlg, IDC_COMBO_VIDEO_2, d); + d++; + } + + c++; + + settings_process_messages(); + } + + settings_enable_window(hdlg, IDC_COMBO_VIDEO_2, !machine_has_flags(temp_machine, MACHINE_VIDEO_ONLY)); + e = settings_list_to_device[1][settings_get_cur_sel(hdlg, IDC_COMBO_VIDEO_2)]; + settings_enable_window(hdlg, IDC_CONFIGURE_VID_2, video_card_has_config(e)); + + settings_enable_window(hdlg, IDC_CHECK_VOODOO, machine_has_bus(temp_machine, MACHINE_BUS_PCI)); + settings_set_check(hdlg, IDC_CHECK_VOODOO, temp_voodoo); + settings_enable_window(hdlg, IDC_BUTTON_VOODOO, machine_has_bus(temp_machine, MACHINE_BUS_PCI) && temp_voodoo); + + settings_enable_window(hdlg, IDC_CHECK_IBM8514, machine_has_bus(temp_machine, MACHINE_BUS_ISA16) || machine_has_bus(temp_machine, MACHINE_BUS_MCA)); + settings_set_check(hdlg, IDC_CHECK_IBM8514, temp_ibm8514); + + settings_enable_window(hdlg, IDC_CHECK_XGA, machine_has_bus(temp_machine, MACHINE_BUS_ISA16) || machine_has_bus(temp_machine, MACHINE_BUS_MCA)); + settings_set_check(hdlg, IDC_CHECK_XGA, temp_xga); + settings_enable_window(hdlg, IDC_BUTTON_XGA, (machine_has_bus(temp_machine, MACHINE_BUS_ISA16) || machine_has_bus(temp_machine, MACHINE_BUS_MCA)) && temp_xga); + + return TRUE; + + case WM_COMMAND: + switch (LOWORD(wParam)) { + case IDC_COMBO_VIDEO: + temp_gfxcard[0] = settings_list_to_device[0][settings_get_cur_sel(hdlg, IDC_COMBO_VIDEO)]; + settings_enable_window(hdlg, IDC_CONFIGURE_VID, video_card_has_config(temp_gfxcard[0])); + + // Secondary Video Card + c = d = 0; + settings_reset_content(hdlg, IDC_COMBO_VIDEO_2); + + while (1) { + /* Skip "internal" if machine doesn't have it. */ + if ((c == 1) && !machine_has_flags(temp_machine, MACHINE_VIDEO)) { + c++; + continue; + } + + generate_device_name(video_card_getdevice(c), video_get_internal_name(c), 1); + + if (!device_name[0]) + break; + + if ((c > 1) && (video_card_get_flags(c) == video_card_get_flags(temp_gfxcard[0]))) { + c++; + continue; + } + + if (video_card_available(c) && device_is_valid(video_card_getdevice(c), temp_machine)) { + if (c == 0) // "None" + settings_add_string(hdlg, IDC_COMBO_VIDEO_2, win_get_string(IDS_2104)); + else if (c == 1) // "Internal" + settings_add_string(hdlg, IDC_COMBO_VIDEO_2, win_get_string(IDS_2119)); + else + settings_add_string(hdlg, IDC_COMBO_VIDEO_2, (LPARAM) device_name); + settings_list_to_device[1][d] = c; + if ((c == 0) || (c == temp_gfxcard[1])) + settings_set_cur_sel(hdlg, IDC_COMBO_VIDEO_2, d); + d++; + } + + c++; + + settings_process_messages(); + } + + settings_enable_window(hdlg, IDC_COMBO_VIDEO_2, !machine_has_flags(temp_machine, MACHINE_VIDEO_ONLY)); + e = settings_list_to_device[1][settings_get_cur_sel(hdlg, IDC_COMBO_VIDEO_2)]; + settings_enable_window(hdlg, IDC_CONFIGURE_VID_2, video_card_has_config(e)); + break; + + case IDC_COMBO_VIDEO_2: + temp_gfxcard[1] = settings_list_to_device[1][settings_get_cur_sel(hdlg, IDC_COMBO_VIDEO_2)]; + settings_enable_window(hdlg, IDC_CONFIGURE_VID_2, video_card_has_config(temp_gfxcard[1])); + break; + + case IDC_CHECK_VOODOO: + temp_voodoo = settings_get_check(hdlg, IDC_CHECK_VOODOO); + settings_enable_window(hdlg, IDC_BUTTON_VOODOO, temp_voodoo); + break; + + case IDC_CHECK_IBM8514: + temp_ibm8514 = settings_get_check(hdlg, IDC_CHECK_IBM8514); + break; + + case IDC_CHECK_XGA: + temp_xga = settings_get_check(hdlg, IDC_CHECK_XGA); + settings_enable_window(hdlg, IDC_BUTTON_XGA, temp_xga); + break; + + case IDC_BUTTON_VOODOO: + temp_deviceconfig |= deviceconfig_open(hdlg, (void *) &voodoo_device); + break; + + case IDC_BUTTON_XGA: + if (machine_has_bus(temp_machine, MACHINE_BUS_MCA) > 0) + temp_deviceconfig |= deviceconfig_open(hdlg, (void *) &xga_device); + else + temp_deviceconfig |= deviceconfig_open(hdlg, (void *) &xga_isa_device); + break; + + case IDC_CONFIGURE_VID: + temp_gfxcard[0] = settings_list_to_device[0][settings_get_cur_sel(hdlg, IDC_COMBO_VIDEO)]; + temp_deviceconfig |= deviceconfig_open(hdlg, (void *) video_card_getdevice(temp_gfxcard[0])); + break; + + case IDC_CONFIGURE_VID_2: + temp_gfxcard[1] = settings_list_to_device[1][settings_get_cur_sel(hdlg, IDC_COMBO_VIDEO_2)]; + temp_deviceconfig |= deviceconfig_open(hdlg, (void *) video_card_getdevice(temp_gfxcard[1])); + break; + } + return FALSE; + + case WM_SAVESETTINGS: + temp_gfxcard[0] = settings_list_to_device[0][settings_get_cur_sel(hdlg, IDC_COMBO_VIDEO)]; + temp_gfxcard[1] = settings_list_to_device[1][settings_get_cur_sel(hdlg, IDC_COMBO_VIDEO_2)]; + temp_voodoo = settings_get_check(hdlg, IDC_CHECK_VOODOO); + temp_ibm8514 = settings_get_check(hdlg, IDC_CHECK_IBM8514); + temp_xga = settings_get_check(hdlg, IDC_CHECK_XGA); + + default: + return FALSE; } return FALSE; } - static int mouse_valid(int num, int m) { const device_t *dev; - if ((num == MOUSE_TYPE_INTERNAL) && - !machine_has_flags(m, MACHINE_MOUSE)) return(0); + if ((num == MOUSE_TYPE_INTERNAL) && !machine_has_flags(m, MACHINE_MOUSE)) + return 0; dev = mouse_get_device(num); - return(device_is_valid(dev, m)); + return (device_is_valid(dev, m)); } - #if defined(__amd64__) || defined(__aarch64__) static LRESULT CALLBACK #else static BOOL CALLBACK #endif -win_settings_input_proc(HWND hdlg, UINT message, WPARAM wParam, LPARAM lParam) +win_settings_input_proc(HWND hdlg, UINT message, WPARAM wParam, UNUSED(LPARAM lParam)) { - wchar_t str[128]; - char *joy_name; - int c, d; + wchar_t str[128]; + const char *joy_name; + int c; + int d; switch (message) { - case WM_INITDIALOG: - c = d = 0; - settings_reset_content(hdlg, IDC_COMBO_MOUSE); - for (c = 0; c < mouse_get_ndev(); c++) { - if (mouse_valid(c, temp_machine)) { - generate_device_name(mouse_get_device(c), mouse_get_internal_name(c), 0); - if (c == 0) - settings_add_string(hdlg, IDC_COMBO_MOUSE, win_get_string(IDS_2103)); - else if (c == 1) - settings_add_string(hdlg, IDC_COMBO_MOUSE, win_get_string(IDS_2118)); - else - settings_add_string(hdlg, IDC_COMBO_MOUSE, (LPARAM) device_name); - settings_list_to_device[0][d] = c; - if ((c == 0) || (c == temp_mouse)) - settings_set_cur_sel(hdlg, IDC_COMBO_MOUSE, d); - d++; - } - } + case WM_INITDIALOG: + c = d = 0; + settings_reset_content(hdlg, IDC_COMBO_MOUSE); + for (c = 0; c < mouse_get_ndev(); c++) { + if (mouse_valid(c, temp_machine)) { + generate_device_name(mouse_get_device(c), mouse_get_internal_name(c), 0); + if (c == 0) + settings_add_string(hdlg, IDC_COMBO_MOUSE, win_get_string(IDS_2104)); + else if (c == 1) + settings_add_string(hdlg, IDC_COMBO_MOUSE, win_get_string(IDS_2119)); + else + settings_add_string(hdlg, IDC_COMBO_MOUSE, (LPARAM) device_name); + settings_list_to_device[0][d] = c; + if ((c == 0) || (c == temp_mouse)) + settings_set_cur_sel(hdlg, IDC_COMBO_MOUSE, d); + d++; + } + } - settings_enable_window(hdlg, IDC_CONFIGURE_MOUSE, mouse_has_config(temp_mouse)); + settings_enable_window(hdlg, IDC_CONFIGURE_MOUSE, mouse_has_config(temp_mouse)); - c = 0; - joy_name = joystick_get_name(c); - while (joy_name) - { - mbstowcs(str, joy_name, strlen(joy_name) + 1); - settings_add_string(hdlg, IDC_COMBO_JOYSTICK, (LPARAM) str); + c = 0; + joy_name = joystick_get_name(c); + while (joy_name) { + mbstowcs(str, joy_name, strlen(joy_name) + 1); + settings_add_string(hdlg, IDC_COMBO_JOYSTICK, (LPARAM) str); - c++; - joy_name = joystick_get_name(c); - } - settings_enable_window(hdlg, IDC_COMBO_JOYSTICK, TRUE); - settings_set_cur_sel(hdlg, IDC_COMBO_JOYSTICK, temp_joystick); + c++; + joy_name = joystick_get_name(c); + } + settings_enable_window(hdlg, IDC_COMBO_JOYSTICK, TRUE); + settings_set_cur_sel(hdlg, IDC_COMBO_JOYSTICK, temp_joystick); - for (c = 0; c < 4; c++) - settings_enable_window(hdlg, IDC_JOY1 + c, joystick_get_max_joysticks(temp_joystick) > c); + for (c = 0; c < 4; c++) + settings_enable_window(hdlg, IDC_JOY1 + c, joystick_get_max_joysticks(temp_joystick) > c); - return TRUE; + return TRUE; - case WM_COMMAND: - switch (LOWORD(wParam)) { - case IDC_COMBO_MOUSE: - temp_mouse = settings_list_to_device[0][settings_get_cur_sel(hdlg, IDC_COMBO_MOUSE)]; - settings_enable_window(hdlg, IDC_CONFIGURE_MOUSE, mouse_has_config(temp_mouse)); - break; + case WM_COMMAND: + switch (LOWORD(wParam)) { + case IDC_COMBO_MOUSE: + temp_mouse = settings_list_to_device[0][settings_get_cur_sel(hdlg, IDC_COMBO_MOUSE)]; + settings_enable_window(hdlg, IDC_CONFIGURE_MOUSE, mouse_has_config(temp_mouse)); + break; - case IDC_CONFIGURE_MOUSE: - temp_mouse = settings_list_to_device[0][settings_get_cur_sel(hdlg, IDC_COMBO_MOUSE)]; - temp_deviceconfig |= deviceconfig_open(hdlg, (void *)mouse_get_device(temp_mouse)); - break; + case IDC_CONFIGURE_MOUSE: + temp_mouse = settings_list_to_device[0][settings_get_cur_sel(hdlg, IDC_COMBO_MOUSE)]; + temp_deviceconfig |= deviceconfig_open(hdlg, (void *) mouse_get_device(temp_mouse)); + break; - case IDC_COMBO_JOYSTICK: - temp_joystick = settings_get_cur_sel(hdlg, IDC_COMBO_JOYSTICK); + case IDC_COMBO_JOYSTICK: + temp_joystick = settings_get_cur_sel(hdlg, IDC_COMBO_JOYSTICK); - for (c = 0; c < 4; c++) - settings_enable_window(hdlg, IDC_JOY1 + c, joystick_get_max_joysticks(temp_joystick) > c); - break; + for (c = 0; c < MAX_JOYSTICKS; c++) + settings_enable_window(hdlg, IDC_JOY1 + c, joystick_get_max_joysticks(temp_joystick) > c); + break; - case IDC_JOY1: case IDC_JOY2: case IDC_JOY3: case IDC_JOY4: - temp_joystick = settings_get_cur_sel(hdlg, IDC_COMBO_JOYSTICK); - temp_deviceconfig |= joystickconfig_open(hdlg, LOWORD(wParam) - IDC_JOY1, temp_joystick); - break; - } - return FALSE; + case IDC_JOY1: + case IDC_JOY2: + case IDC_JOY3: + case IDC_JOY4: + temp_joystick = settings_get_cur_sel(hdlg, IDC_COMBO_JOYSTICK); + temp_deviceconfig |= joystickconfig_open(hdlg, LOWORD(wParam) - IDC_JOY1, temp_joystick); + break; + } + return FALSE; - case WM_SAVESETTINGS: - temp_mouse = settings_list_to_device[0][settings_get_cur_sel(hdlg, IDC_COMBO_MOUSE)]; - temp_joystick = settings_get_cur_sel(hdlg, IDC_COMBO_JOYSTICK); + case WM_SAVESETTINGS: + temp_mouse = settings_list_to_device[0][settings_get_cur_sel(hdlg, IDC_COMBO_MOUSE)]; + temp_joystick = settings_get_cur_sel(hdlg, IDC_COMBO_JOYSTICK); - default: - return FALSE; + default: + return FALSE; } return FALSE; } - static int mpu401_present(void) { return temp_mpu401 ? 1 : 0; } - int mpu401_standalone_allow(void) { - char *md, *mdin; + const char *mdout; + const char *mdin; if (!machine_has_bus(temp_machine, MACHINE_BUS_ISA) && !machine_has_bus(temp_machine, MACHINE_BUS_MCA)) - return 0; + return 0; - md = midi_device_get_internal_name(temp_midi_device); - mdin = midi_in_device_get_internal_name(temp_midi_input_device); + mdout = midi_out_device_get_internal_name(temp_midi_output_device); + mdin = midi_in_device_get_internal_name(temp_midi_input_device); - if (md != NULL) { - if (!strcmp(md, "none") && !strcmp(mdin, "none")) - return 0; + if (mdout != NULL) { + if (!strcmp(mdout, "none") && !strcmp(mdin, "none")) + return 0; } return 1; @@ -1277,1033 +1475,1249 @@ static LRESULT CALLBACK #else static BOOL CALLBACK #endif -win_settings_sound_proc(HWND hdlg, UINT message, WPARAM wParam, LPARAM lParam) +win_settings_sound_proc(HWND hdlg, UINT message, WPARAM wParam, UNUSED(LPARAM lParam)) { - int c, d; - LPTSTR lptsTemp; - const device_t *sound_dev; + uint16_t c; + uint16_t d; + LPTSTR lptsTemp; + const device_t *sound_dev[SOUND_CARD_MAX]; switch (message) { - case WM_INITDIALOG: - lptsTemp = (LPTSTR) malloc(512 * sizeof(WCHAR)); + case WM_INITDIALOG: + lptsTemp = (LPTSTR) malloc(512 * sizeof(WCHAR)); - c = d = 0; - settings_reset_content(hdlg, IDC_COMBO_SOUND); - while (1) { - /* Skip "internal" if machine doesn't have it. */ - if ((c == 1) && !machine_has_flags(temp_machine, MACHINE_SOUND)) { - c++; - continue; - } + c = d = 0; + settings_reset_content(hdlg, IDC_COMBO_SOUND1); + while (1) { + /* Skip "internal" if machine doesn't have it. */ + if ((c == 1) && !machine_has_flags(temp_machine, MACHINE_SOUND)) { + c++; + continue; + } - generate_device_name(sound_card_getdevice(c), sound_card_get_internal_name(c), 1); + generate_device_name(sound_card_getdevice(c), sound_card_get_internal_name(c), 1); - if (!device_name[0]) - break; + if (!device_name[0]) + break; - if (sound_card_available(c)) { - sound_dev = sound_card_getdevice(c); + if (sound_card_available(c)) { + sound_dev[0] = sound_card_getdevice(c); - if (device_is_valid(sound_dev, temp_machine)) { - if (c == 0) - settings_add_string(hdlg, IDC_COMBO_SOUND, win_get_string(IDS_2103)); - else if (c == 1) - settings_add_string(hdlg, IDC_COMBO_SOUND, win_get_string(IDS_2118)); - else - settings_add_string(hdlg, IDC_COMBO_SOUND, (LPARAM) device_name); - settings_list_to_device[0][d] = c; - if ((c == 0) || (c == temp_sound_card)) - settings_set_cur_sel(hdlg, IDC_COMBO_SOUND, d); - d++; - } - } + if (device_is_valid(sound_dev[0], temp_machine)) { + if (c == 0) + settings_add_string(hdlg, IDC_COMBO_SOUND1, win_get_string(IDS_2104)); + else if (c == 1) + settings_add_string(hdlg, IDC_COMBO_SOUND1, win_get_string(IDS_2119)); + else + settings_add_string(hdlg, IDC_COMBO_SOUND1, (LPARAM) device_name); + settings_list_to_device[0][d] = c; + if ((c == 0) || (c == temp_sound_card[0])) + settings_set_cur_sel(hdlg, IDC_COMBO_SOUND1, d); + d++; + } + } - c++; - } + c++; + } - settings_enable_window(hdlg, IDC_COMBO_SOUND, d); - settings_enable_window(hdlg, IDC_CONFIGURE_SND, sound_card_has_config(temp_sound_card)); + settings_enable_window(hdlg, IDC_COMBO_SOUND1, d); + settings_enable_window(hdlg, IDC_CONFIGURE_SND1, sound_card_has_config(temp_sound_card[0])); - c = d = 0; - settings_reset_content(hdlg, IDC_COMBO_MIDI_OUT); - while (1) { - generate_device_name(midi_device_getdevice(c), midi_device_get_internal_name(c), 0); + c = d = 0; + settings_reset_content(hdlg, IDC_COMBO_SOUND2); + while (1) { + /* Skip "internal" */ + if (c == 1) { + c++; + continue; + } - if (!device_name[0]) - break; + generate_device_name(sound_card_getdevice(c), sound_card_get_internal_name(c), 1); - if (midi_device_available(c)) { - if (c == 0) - settings_add_string(hdlg, IDC_COMBO_MIDI_OUT, win_get_string(IDS_2103)); - else - settings_add_string(hdlg, IDC_COMBO_MIDI_OUT, (LPARAM) device_name); - settings_list_to_midi[d] = c; - if ((c == 0) || (c == temp_midi_device)) - settings_set_cur_sel(hdlg, IDC_COMBO_MIDI_OUT, d); - d++; - } + if (!device_name[0]) + break; - c++; - } + if (sound_card_available(c)) { + sound_dev[1] = sound_card_getdevice(c); - settings_enable_window(hdlg, IDC_CONFIGURE_MIDI_OUT, midi_device_has_config(temp_midi_device)); + if (device_is_valid(sound_dev[1], temp_machine)) { + if (c == 0) + settings_add_string(hdlg, IDC_COMBO_SOUND2, win_get_string(IDS_2104)); + else if (c == 1) + settings_add_string(hdlg, IDC_COMBO_SOUND2, win_get_string(IDS_2119)); + else + settings_add_string(hdlg, IDC_COMBO_SOUND2, (LPARAM) device_name); + settings_list_to_device[0][d] = c; + if ((c == 0) || (c == temp_sound_card[1])) + settings_set_cur_sel(hdlg, IDC_COMBO_SOUND2, d); + d++; + } + } - c = d = 0; - settings_reset_content(hdlg, IDC_COMBO_MIDI_IN); - while (1) { - generate_device_name(midi_in_device_getdevice(c), midi_in_device_get_internal_name(c), 0); + c++; + } - if (!device_name[0]) - break; + settings_enable_window(hdlg, IDC_COMBO_SOUND2, d); + settings_enable_window(hdlg, IDC_CONFIGURE_SND2, sound_card_has_config(temp_sound_card[1])); - if (midi_in_device_available(c)) { - if (c == 0) - settings_add_string(hdlg, IDC_COMBO_MIDI_IN, win_get_string(IDS_2103)); - else - settings_add_string(hdlg, IDC_COMBO_MIDI_IN, (LPARAM) device_name); - settings_list_to_midi_in[d] = c; - if ((c == 0) || (c == temp_midi_input_device)) - settings_set_cur_sel(hdlg, IDC_COMBO_MIDI_IN, d); - d++; - } + c = d = 0; + settings_reset_content(hdlg, IDC_COMBO_SOUND3); + while (1) { + /* Skip "internal" */ + if (c == 1) { + c++; + continue; + } - c++; - } + generate_device_name(sound_card_getdevice(c), sound_card_get_internal_name(c), 1); - settings_enable_window(hdlg, IDC_CONFIGURE_MIDI_IN, midi_in_device_has_config(temp_midi_input_device)); - settings_set_check(hdlg, IDC_CHECK_MPU401, temp_mpu401); - settings_enable_window(hdlg, IDC_CHECK_MPU401, mpu401_standalone_allow()); - settings_enable_window(hdlg, IDC_CONFIGURE_MPU401, mpu401_standalone_allow() && temp_mpu401); - settings_enable_window(hdlg, IDC_CHECK_CMS, machine_has_bus(temp_machine, MACHINE_BUS_ISA)); - settings_set_check(hdlg, IDC_CHECK_CMS, temp_GAMEBLASTER); - settings_enable_window(hdlg, IDC_CONFIGURE_CMS, machine_has_bus(temp_machine, MACHINE_BUS_ISA) && temp_GAMEBLASTER); - settings_enable_window(hdlg, IDC_CHECK_GUS, machine_has_bus(temp_machine, MACHINE_BUS_ISA16)); - settings_set_check(hdlg, IDC_CHECK_GUS, temp_GUS); - settings_enable_window(hdlg, IDC_CONFIGURE_GUS, machine_has_bus(temp_machine, MACHINE_BUS_ISA16) && temp_GUS); - settings_enable_window(hdlg, IDC_CHECK_SSI, machine_has_bus(temp_machine, MACHINE_BUS_ISA)); - settings_set_check(hdlg, IDC_CHECK_SSI, temp_SSI2001); - settings_enable_window(hdlg, IDC_CONFIGURE_SSI, machine_has_bus(temp_machine, MACHINE_BUS_ISA) && temp_SSI2001); - settings_set_check(hdlg, IDC_CHECK_FLOAT, temp_float); + if (!device_name[0]) + break; - free(lptsTemp); + if (sound_card_available(c)) { + sound_dev[2] = sound_card_getdevice(c); - return TRUE; + if (device_is_valid(sound_dev[2], temp_machine)) { + if (c == 0) + settings_add_string(hdlg, IDC_COMBO_SOUND3, win_get_string(IDS_2104)); + else if (c == 1) + settings_add_string(hdlg, IDC_COMBO_SOUND3, win_get_string(IDS_2119)); + else + settings_add_string(hdlg, IDC_COMBO_SOUND3, (LPARAM) device_name); + settings_list_to_device[0][d] = c; + if ((c == 0) || (c == temp_sound_card[2])) + settings_set_cur_sel(hdlg, IDC_COMBO_SOUND3, d); + d++; + } + } - case WM_COMMAND: - switch (LOWORD(wParam)) { - case IDC_COMBO_SOUND: - temp_sound_card = settings_list_to_device[0][settings_get_cur_sel(hdlg, IDC_COMBO_SOUND)]; - settings_enable_window(hdlg, IDC_CONFIGURE_SND, sound_card_has_config(temp_sound_card)); - settings_set_check(hdlg, IDC_CHECK_MPU401, temp_mpu401); - settings_enable_window(hdlg, IDC_CHECK_MPU401, mpu401_standalone_allow()); - settings_enable_window(hdlg, IDC_CONFIGURE_MPU401, mpu401_standalone_allow() && temp_mpu401); - break; + c++; + } - case IDC_CONFIGURE_SND: - temp_sound_card = settings_list_to_device[0][settings_get_cur_sel(hdlg, IDC_COMBO_SOUND)]; - temp_deviceconfig |= deviceconfig_open(hdlg, (void *)sound_card_getdevice(temp_sound_card)); - break; + settings_enable_window(hdlg, IDC_COMBO_SOUND3, d); + settings_enable_window(hdlg, IDC_CONFIGURE_SND3, sound_card_has_config(temp_sound_card[2])); - case IDC_COMBO_MIDI_OUT: - temp_midi_device = settings_list_to_midi[settings_get_cur_sel(hdlg, IDC_COMBO_MIDI_OUT)]; - settings_enable_window(hdlg, IDC_CONFIGURE_MIDI_OUT, midi_device_has_config(temp_midi_device)); - settings_set_check(hdlg, IDC_CHECK_MPU401, temp_mpu401); - settings_enable_window(hdlg, IDC_CHECK_MPU401, mpu401_standalone_allow()); - settings_enable_window(hdlg, IDC_CONFIGURE_MPU401, mpu401_standalone_allow() && temp_mpu401); - break; + c = d = 0; + settings_reset_content(hdlg, IDC_COMBO_SOUND4); + while (1) { + /* Skip "internal" */ + if (c == 1) { + c++; + continue; + } - case IDC_CONFIGURE_MIDI_OUT: - temp_midi_device = settings_list_to_midi[settings_get_cur_sel(hdlg, IDC_COMBO_MIDI_OUT)]; - temp_deviceconfig |= deviceconfig_open(hdlg, (void *)midi_device_getdevice(temp_midi_device)); - break; + generate_device_name(sound_card_getdevice(c), sound_card_get_internal_name(c), 1); - case IDC_COMBO_MIDI_IN: - temp_midi_input_device = settings_list_to_midi_in[settings_get_cur_sel(hdlg, IDC_COMBO_MIDI_IN)]; - settings_enable_window(hdlg, IDC_CONFIGURE_MIDI_IN, midi_in_device_has_config(temp_midi_input_device)); - settings_set_check(hdlg, IDC_CHECK_MPU401, temp_mpu401); - settings_enable_window(hdlg, IDC_CHECK_MPU401, mpu401_standalone_allow()); - settings_enable_window(hdlg, IDC_CONFIGURE_MPU401, mpu401_standalone_allow() && temp_mpu401); - break; + if (!device_name[0]) + break; - case IDC_CONFIGURE_MIDI_IN: - temp_midi_input_device = settings_list_to_midi_in[settings_get_cur_sel(hdlg, IDC_COMBO_MIDI_IN)]; - temp_deviceconfig |= deviceconfig_open(hdlg, (void *)midi_in_device_getdevice(temp_midi_input_device)); - break; + if (sound_card_available(c)) { + sound_dev[3] = sound_card_getdevice(c); - case IDC_CHECK_MPU401: - temp_mpu401 = settings_get_check(hdlg, IDC_CHECK_MPU401); + if (device_is_valid(sound_dev[3], temp_machine)) { + if (c == 0) + settings_add_string(hdlg, IDC_COMBO_SOUND4, win_get_string(IDS_2104)); + else if (c == 1) + settings_add_string(hdlg, IDC_COMBO_SOUND4, win_get_string(IDS_2119)); + else + settings_add_string(hdlg, IDC_COMBO_SOUND4, (LPARAM) device_name); + settings_list_to_device[0][d] = c; + if ((c == 0) || (c == temp_sound_card[3])) + settings_set_cur_sel(hdlg, IDC_COMBO_SOUND4, d); + d++; + } + } - settings_enable_window(hdlg, IDC_CONFIGURE_MPU401, mpu401_present()); - break; + c++; + } - case IDC_CONFIGURE_MPU401: - temp_deviceconfig |= deviceconfig_open(hdlg, machine_has_bus(temp_machine, MACHINE_BUS_MCA) ? - (void *)&mpu401_mca_device : (void *)&mpu401_device); - break; + settings_enable_window(hdlg, IDC_COMBO_SOUND4, d); + settings_enable_window(hdlg, IDC_CONFIGURE_SND4, sound_card_has_config(temp_sound_card[3])); - case IDC_CHECK_CMS: - temp_GAMEBLASTER = settings_get_check(hdlg, IDC_CHECK_CMS); + c = d = 0; + settings_reset_content(hdlg, IDC_COMBO_MIDI_OUT); + while (1) { + generate_device_name(midi_out_device_getdevice(c), midi_out_device_get_internal_name(c), 0); - settings_enable_window(hdlg, IDC_CONFIGURE_CMS, temp_GAMEBLASTER); - break; + if (!device_name[0]) + break; - case IDC_CONFIGURE_CMS: - temp_deviceconfig |= deviceconfig_open(hdlg, &cms_device); - break; + if (midi_out_device_available(c)) { + if (c == 0) + settings_add_string(hdlg, IDC_COMBO_MIDI_OUT, win_get_string(IDS_2104)); + else + settings_add_string(hdlg, IDC_COMBO_MIDI_OUT, (LPARAM) device_name); + settings_list_to_midi[d] = c; + if ((c == 0) || (c == temp_midi_output_device)) + settings_set_cur_sel(hdlg, IDC_COMBO_MIDI_OUT, d); + d++; + } - case IDC_CHECK_GUS: - temp_GUS = settings_get_check(hdlg, IDC_CHECK_GUS); - settings_enable_window(hdlg, IDC_CONFIGURE_GUS, temp_GUS); - break; + c++; + } - case IDC_CONFIGURE_GUS: - temp_deviceconfig |= deviceconfig_open(hdlg, (void *)&gus_device); - break; + settings_enable_window(hdlg, IDC_CONFIGURE_MIDI_OUT, midi_out_device_has_config(temp_midi_output_device)); - case IDC_CHECK_SSI: - temp_SSI2001 = settings_get_check(hdlg, IDC_CHECK_SSI); + c = d = 0; + settings_reset_content(hdlg, IDC_COMBO_MIDI_IN); + while (1) { + generate_device_name(midi_in_device_getdevice(c), midi_in_device_get_internal_name(c), 0); - settings_enable_window(hdlg, IDC_CONFIGURE_SSI, temp_SSI2001); - break; + if (!device_name[0]) + break; - case IDC_CONFIGURE_SSI: - temp_deviceconfig |= deviceconfig_open(hdlg, &ssi2001_device); - break; - } - return FALSE; + if (midi_in_device_available(c)) { + if (c == 0) + settings_add_string(hdlg, IDC_COMBO_MIDI_IN, win_get_string(IDS_2104)); + else + settings_add_string(hdlg, IDC_COMBO_MIDI_IN, (LPARAM) device_name); + settings_list_to_midi_in[d] = c; + if ((c == 0) || (c == temp_midi_input_device)) + settings_set_cur_sel(hdlg, IDC_COMBO_MIDI_IN, d); + d++; + } - case WM_SAVESETTINGS: - temp_sound_card = settings_list_to_device[0][settings_get_cur_sel(hdlg, IDC_COMBO_SOUND)]; - temp_midi_device = settings_list_to_midi[settings_get_cur_sel(hdlg, IDC_COMBO_MIDI_OUT)]; - temp_midi_input_device = settings_list_to_midi_in[settings_get_cur_sel(hdlg, IDC_COMBO_MIDI_IN)]; - temp_mpu401 = settings_get_check(hdlg, IDC_CHECK_MPU401); - temp_GAMEBLASTER = settings_get_check(hdlg, IDC_CHECK_CMS); - temp_GUS = settings_get_check(hdlg, IDC_CHECK_GUS); - temp_SSI2001 = settings_get_check(hdlg, IDC_CHECK_SSI); - temp_float = settings_get_check(hdlg, IDC_CHECK_FLOAT); + c++; + } - default: - return FALSE; + settings_enable_window(hdlg, IDC_CONFIGURE_MIDI_IN, midi_in_device_has_config(temp_midi_input_device)); + settings_set_check(hdlg, IDC_CHECK_MPU401, temp_mpu401); + settings_enable_window(hdlg, IDC_CHECK_MPU401, mpu401_standalone_allow()); + settings_enable_window(hdlg, IDC_CONFIGURE_MPU401, mpu401_standalone_allow() && temp_mpu401); + settings_set_check(hdlg, IDC_CHECK_FLOAT, temp_float); + + if (temp_fm_driver == FM_DRV_YMFM) + settings_set_check(hdlg, IDC_RADIO_FM_DRV_YMFM, BST_CHECKED); + else + settings_set_check(hdlg, IDC_RADIO_FM_DRV_NUKED, BST_CHECKED); + + free(lptsTemp); + + return TRUE; + + case WM_COMMAND: + switch (LOWORD(wParam)) { + case IDC_COMBO_SOUND1: + temp_sound_card[0] = settings_list_to_device[0][settings_get_cur_sel(hdlg, IDC_COMBO_SOUND1)]; + settings_enable_window(hdlg, IDC_CONFIGURE_SND1, sound_card_has_config(temp_sound_card[0])); + settings_set_check(hdlg, IDC_CHECK_MPU401, temp_mpu401); + settings_enable_window(hdlg, IDC_CHECK_MPU401, mpu401_standalone_allow()); + settings_enable_window(hdlg, IDC_CONFIGURE_MPU401, mpu401_standalone_allow() && temp_mpu401); + break; + + case IDC_CONFIGURE_SND1: + temp_sound_card[0] = settings_list_to_device[0][settings_get_cur_sel(hdlg, IDC_COMBO_SOUND1)]; + temp_deviceconfig |= deviceconfig_open(hdlg, (void *) sound_card_getdevice(temp_sound_card[0])); + break; + + case IDC_COMBO_SOUND2: + temp_sound_card[1] = settings_list_to_device[0][settings_get_cur_sel(hdlg, IDC_COMBO_SOUND2)]; + settings_enable_window(hdlg, IDC_CONFIGURE_SND2, sound_card_has_config(temp_sound_card[1])); + settings_set_check(hdlg, IDC_CHECK_MPU401, temp_mpu401); + settings_enable_window(hdlg, IDC_CHECK_MPU401, mpu401_standalone_allow()); + settings_enable_window(hdlg, IDC_CONFIGURE_MPU401, mpu401_standalone_allow() && temp_mpu401); + break; + + case IDC_CONFIGURE_SND2: + temp_sound_card[1] = settings_list_to_device[0][settings_get_cur_sel(hdlg, IDC_COMBO_SOUND2)]; + temp_deviceconfig |= deviceconfig_open(hdlg, (void *) sound_card_getdevice(temp_sound_card[1])); + break; + + case IDC_COMBO_SOUND3: + temp_sound_card[2] = settings_list_to_device[0][settings_get_cur_sel(hdlg, IDC_COMBO_SOUND3)]; + settings_enable_window(hdlg, IDC_CONFIGURE_SND3, sound_card_has_config(temp_sound_card[2])); + settings_set_check(hdlg, IDC_CHECK_MPU401, temp_mpu401); + settings_enable_window(hdlg, IDC_CHECK_MPU401, mpu401_standalone_allow()); + settings_enable_window(hdlg, IDC_CONFIGURE_MPU401, mpu401_standalone_allow() && temp_mpu401); + break; + + case IDC_CONFIGURE_SND3: + temp_sound_card[2] = settings_list_to_device[0][settings_get_cur_sel(hdlg, IDC_COMBO_SOUND3)]; + temp_deviceconfig |= deviceconfig_open(hdlg, (void *) sound_card_getdevice(temp_sound_card[2])); + break; + + case IDC_COMBO_SOUND4: + temp_sound_card[3] = settings_list_to_device[0][settings_get_cur_sel(hdlg, IDC_COMBO_SOUND4)]; + settings_enable_window(hdlg, IDC_CONFIGURE_SND4, sound_card_has_config(temp_sound_card[3])); + settings_set_check(hdlg, IDC_CHECK_MPU401, temp_mpu401); + settings_enable_window(hdlg, IDC_CHECK_MPU401, mpu401_standalone_allow()); + settings_enable_window(hdlg, IDC_CONFIGURE_MPU401, mpu401_standalone_allow() && temp_mpu401); + break; + + case IDC_CONFIGURE_SND4: + temp_sound_card[3] = settings_list_to_device[0][settings_get_cur_sel(hdlg, IDC_COMBO_SOUND4)]; + temp_deviceconfig |= deviceconfig_open(hdlg, (void *) sound_card_getdevice(temp_sound_card[3])); + break; + + case IDC_COMBO_MIDI_OUT: + temp_midi_output_device = settings_list_to_midi[settings_get_cur_sel(hdlg, IDC_COMBO_MIDI_OUT)]; + settings_enable_window(hdlg, IDC_CONFIGURE_MIDI_OUT, midi_out_device_has_config(temp_midi_output_device)); + settings_set_check(hdlg, IDC_CHECK_MPU401, temp_mpu401); + settings_enable_window(hdlg, IDC_CHECK_MPU401, mpu401_standalone_allow()); + settings_enable_window(hdlg, IDC_CONFIGURE_MPU401, mpu401_standalone_allow() && temp_mpu401); + break; + + case IDC_CONFIGURE_MIDI_OUT: + temp_midi_output_device = settings_list_to_midi[settings_get_cur_sel(hdlg, IDC_COMBO_MIDI_OUT)]; + temp_deviceconfig |= deviceconfig_open(hdlg, (void *) midi_out_device_getdevice(temp_midi_output_device)); + break; + + case IDC_COMBO_MIDI_IN: + temp_midi_input_device = settings_list_to_midi_in[settings_get_cur_sel(hdlg, IDC_COMBO_MIDI_IN)]; + settings_enable_window(hdlg, IDC_CONFIGURE_MIDI_IN, midi_in_device_has_config(temp_midi_input_device)); + settings_set_check(hdlg, IDC_CHECK_MPU401, temp_mpu401); + settings_enable_window(hdlg, IDC_CHECK_MPU401, mpu401_standalone_allow()); + settings_enable_window(hdlg, IDC_CONFIGURE_MPU401, mpu401_standalone_allow() && temp_mpu401); + break; + + case IDC_CONFIGURE_MIDI_IN: + temp_midi_input_device = settings_list_to_midi_in[settings_get_cur_sel(hdlg, IDC_COMBO_MIDI_IN)]; + temp_deviceconfig |= deviceconfig_open(hdlg, (void *) midi_in_device_getdevice(temp_midi_input_device)); + break; + + case IDC_CHECK_MPU401: + temp_mpu401 = settings_get_check(hdlg, IDC_CHECK_MPU401); + + settings_enable_window(hdlg, IDC_CONFIGURE_MPU401, mpu401_present()); + break; + + case IDC_CONFIGURE_MPU401: + temp_deviceconfig |= deviceconfig_open(hdlg, machine_has_bus(temp_machine, MACHINE_BUS_MCA) ? (void *) &mpu401_mca_device : (void *) &mpu401_device); + break; + } + return FALSE; + + case WM_SAVESETTINGS: + temp_sound_card[0] = settings_list_to_device[0][settings_get_cur_sel(hdlg, IDC_COMBO_SOUND1)]; + temp_sound_card[1] = settings_list_to_device[0][settings_get_cur_sel(hdlg, IDC_COMBO_SOUND2)]; + temp_sound_card[2] = settings_list_to_device[0][settings_get_cur_sel(hdlg, IDC_COMBO_SOUND3)]; + temp_sound_card[3] = settings_list_to_device[0][settings_get_cur_sel(hdlg, IDC_COMBO_SOUND4)]; + temp_midi_output_device = settings_list_to_midi[settings_get_cur_sel(hdlg, IDC_COMBO_MIDI_OUT)]; + temp_midi_input_device = settings_list_to_midi_in[settings_get_cur_sel(hdlg, IDC_COMBO_MIDI_IN)]; + temp_mpu401 = settings_get_check(hdlg, IDC_CHECK_MPU401); + temp_float = settings_get_check(hdlg, IDC_CHECK_FLOAT); + if (settings_get_check(hdlg, IDC_RADIO_FM_DRV_NUKED)) + temp_fm_driver = FM_DRV_NUKED; + if (settings_get_check(hdlg, IDC_RADIO_FM_DRV_YMFM)) + temp_fm_driver = FM_DRV_YMFM; + default: + return FALSE; } return FALSE; } - #if defined(__amd64__) || defined(__aarch64__) static LRESULT CALLBACK #else static BOOL CALLBACK #endif -win_settings_ports_proc(HWND hdlg, UINT message, WPARAM wParam, LPARAM lParam) +win_settings_ports_proc(HWND hdlg, UINT message, WPARAM wParam, UNUSED(LPARAM lParam)) { - int c, i; - char *s; - LPTSTR lptsTemp; + int c; + int i; + const char *s; + LPTSTR lptsTemp; switch (message) { - case WM_INITDIALOG: - lptsTemp = (LPTSTR) malloc(512 * sizeof(WCHAR)); + case WM_INITDIALOG: + lptsTemp = (LPTSTR) malloc(512 * sizeof(WCHAR)); - for (i = 0; i < PARALLEL_MAX; i++) { - c = 0; - while (1) { - s = lpt_device_get_name(c); + for (i = 0; i < PARALLEL_MAX; i++) { + c = 0; + while (1) { + s = (char *) lpt_device_get_name(c); - if (!s) - break; + if (!s) + break; - if (c == 0) - settings_add_string(hdlg, IDC_COMBO_LPT1 + i, win_get_string(IDS_2103)); - else { - mbstowcs(lptsTemp, s, strlen(s) + 1); - settings_add_string(hdlg, IDC_COMBO_LPT1 + i, (LPARAM) lptsTemp); - } + if (c == 0) + settings_add_string(hdlg, IDC_COMBO_LPT1 + i, win_get_string(IDS_2104)); + else { + mbstowcs(lptsTemp, s, strlen(s) + 1); + settings_add_string(hdlg, IDC_COMBO_LPT1 + i, (LPARAM) lptsTemp); + } - c++; - } - settings_set_cur_sel(hdlg, IDC_COMBO_LPT1 + i, temp_lpt_devices[i]); + c++; + } + settings_set_cur_sel(hdlg, IDC_COMBO_LPT1 + i, temp_lpt_devices[i]); - settings_set_check(hdlg, IDC_CHECK_PARALLEL1 + i, temp_lpt[i]); - settings_enable_window(hdlg, IDC_COMBO_LPT1 + i, temp_lpt[i]); - } + settings_set_check(hdlg, IDC_CHECK_PARALLEL1 + i, temp_lpt[i]); + settings_enable_window(hdlg, IDC_COMBO_LPT1 + i, temp_lpt[i]); + } - for (i = 0; i < SERIAL_MAX; i++) - settings_set_check(hdlg, IDC_CHECK_SERIAL1 + i, temp_serial[i]); + for (i = 0; i < SERIAL_MAX; i++) { + settings_set_check(hdlg, IDC_CHECK_SERIAL1 + i, temp_serial[i]); + settings_set_check(hdlg, IDC_CHECK_SERIAL_PASS1 + i, temp_serial_passthrough_enabled[i]); + } - free(lptsTemp); + free(lptsTemp); - return TRUE; + return TRUE; - case WM_COMMAND: - switch (LOWORD(wParam)) { - case IDC_CHECK_PARALLEL1: - case IDC_CHECK_PARALLEL2: - case IDC_CHECK_PARALLEL3: - case IDC_CHECK_PARALLEL4: - i = LOWORD(wParam) - IDC_CHECK_PARALLEL1; - settings_enable_window(hdlg, IDC_COMBO_LPT1 + i, - settings_get_check(hdlg, IDC_CHECK_PARALLEL1 + i) == BST_CHECKED); - break; - } - break; + case WM_COMMAND: + switch (LOWORD(wParam)) { + case IDC_CHECK_PARALLEL1: + case IDC_CHECK_PARALLEL2: + case IDC_CHECK_PARALLEL3: + case IDC_CHECK_PARALLEL4: + i = LOWORD(wParam) - IDC_CHECK_PARALLEL1; + settings_enable_window(hdlg, IDC_COMBO_LPT1 + i, + settings_get_check(hdlg, IDC_CHECK_PARALLEL1 + i) == BST_CHECKED); + break; + } + break; - case WM_SAVESETTINGS: - for (i = 0; i < PARALLEL_MAX; i++) { - temp_lpt_devices[i] = settings_get_cur_sel(hdlg, IDC_COMBO_LPT1 + i); - temp_lpt[i] = settings_get_check(hdlg, IDC_CHECK_PARALLEL1 + i); - } + case WM_SAVESETTINGS: + for (i = 0; i < PARALLEL_MAX; i++) { + temp_lpt_devices[i] = settings_get_cur_sel(hdlg, IDC_COMBO_LPT1 + i); + temp_lpt[i] = settings_get_check(hdlg, IDC_CHECK_PARALLEL1 + i); + } - for (i = 0; i < SERIAL_MAX; i++) - temp_serial[i] = settings_get_check(hdlg, IDC_CHECK_SERIAL1 + i); + for (i = 0; i < SERIAL_MAX; i++) { + temp_serial[i] = settings_get_check(hdlg, IDC_CHECK_SERIAL1 + i); + temp_serial_passthrough_enabled[i] = settings_get_check(hdlg, IDC_CHECK_SERIAL_PASS1 + i); + } - default: - return FALSE; + default: + return FALSE; } return FALSE; } - #if defined(__amd64__) || defined(__aarch64__) static LRESULT CALLBACK #else static BOOL CALLBACK #endif -win_settings_storage_proc(HWND hdlg, UINT message, WPARAM wParam, LPARAM lParam) +win_settings_storage_proc(HWND hdlg, UINT message, WPARAM wParam, UNUSED(LPARAM lParam)) { - int c, d; - int e, is_at; - LPTSTR lptsTemp; - char *stransi; - const device_t *scsi_dev, *fdc_dev; + int c; + int d; + int e; + int is_at; + LPTSTR lptsTemp; + char *stransi; + const device_t *scsi_dev; + const device_t *fdc_dev; const device_t *hdc_dev; switch (message) { - case WM_INITDIALOG: - lptsTemp = (LPTSTR) malloc(512 * sizeof(WCHAR)); - stransi = (char *) malloc(512); + case WM_INITDIALOG: + lptsTemp = (LPTSTR) malloc(512 * sizeof(WCHAR)); + stransi = (char *) malloc(512); - /*HD controller config*/ - c = d = 0; - settings_reset_content(hdlg, IDC_COMBO_HDC); - while (1) { - /* Skip "internal" if machine doesn't have it. */ - if ((c == 1) && !machine_has_flags(temp_machine, MACHINE_HDC)) { - c++; - continue; - } + /*HD controller config*/ + c = d = 0; + settings_reset_content(hdlg, IDC_COMBO_HDC); + while (1) { + /* Skip "internal" if machine doesn't have it. */ + if ((c == 1) && !machine_has_flags(temp_machine, MACHINE_HDC)) { + c++; + continue; + } - generate_device_name(hdc_get_device(c), hdc_get_internal_name(c), 1); + generate_device_name(hdc_get_device(c), hdc_get_internal_name(c), 1); - if (!device_name[0]) - break; + if (!device_name[0]) + break; - if (hdc_available(c)) { - hdc_dev = hdc_get_device(c); + if (hdc_available(c)) { + hdc_dev = hdc_get_device(c); - if (device_is_valid(hdc_dev, temp_machine)) { - if (c == 0) - settings_add_string(hdlg, IDC_COMBO_HDC, win_get_string(IDS_2103)); - else if (c == 1) - settings_add_string(hdlg, IDC_COMBO_HDC, win_get_string(IDS_2118)); - else - settings_add_string(hdlg, IDC_COMBO_HDC, (LPARAM) device_name); - settings_list_to_hdc[d] = c; - if ((c == 0) || (c == temp_hdc)) - settings_set_cur_sel(hdlg, IDC_COMBO_HDC, d); - d++; - } - } + if (device_is_valid(hdc_dev, temp_machine)) { + if (c == 0) + settings_add_string(hdlg, IDC_COMBO_HDC, win_get_string(IDS_2104)); + else if (c == 1) + settings_add_string(hdlg, IDC_COMBO_HDC, win_get_string(IDS_2119)); + else + settings_add_string(hdlg, IDC_COMBO_HDC, (LPARAM) device_name); + settings_list_to_hdc[d] = c; + if ((c == 0) || (c == temp_hdc)) + settings_set_cur_sel(hdlg, IDC_COMBO_HDC, d); + d++; + } + } - c++; - } + c++; + } - settings_enable_window(hdlg, IDC_COMBO_HDC, d); - settings_enable_window(hdlg, IDC_CONFIGURE_HDC, hdc_has_config(temp_hdc)); + settings_enable_window(hdlg, IDC_COMBO_HDC, d); + settings_enable_window(hdlg, IDC_CONFIGURE_HDC, hdc_has_config(temp_hdc)); - /*FD controller config*/ - c = d = 0; - settings_reset_content(hdlg, IDC_COMBO_FDC); - while (1) { - generate_device_name(fdc_card_getdevice(c), fdc_card_get_internal_name(c), 1); + /*FD controller config*/ + c = d = 0; + settings_reset_content(hdlg, IDC_COMBO_FDC); + while (1) { + generate_device_name(fdc_card_getdevice(c), fdc_card_get_internal_name(c), 1); - if (!device_name[0]) - break; + if (!device_name[0]) + break; - if (fdc_card_available(c)) { - fdc_dev = fdc_card_getdevice(c); + if (fdc_card_available(c)) { + fdc_dev = fdc_card_getdevice(c); - if (device_is_valid(fdc_dev, temp_machine)) { - if (c == 0) - settings_add_string(hdlg, IDC_COMBO_FDC, win_get_string(IDS_2118)); - else - settings_add_string(hdlg, IDC_COMBO_FDC, (LPARAM) device_name); - settings_list_to_fdc[d] = c; - if ((c == 0) || (c == temp_fdc_card)) - settings_set_cur_sel(hdlg, IDC_COMBO_FDC, d); - d++; - } - } + if (device_is_valid(fdc_dev, temp_machine)) { + if (c == 0) + settings_add_string(hdlg, IDC_COMBO_FDC, win_get_string(IDS_2119)); + else + settings_add_string(hdlg, IDC_COMBO_FDC, (LPARAM) device_name); + settings_list_to_fdc[d] = c; + if ((c == 0) || (c == temp_fdc_card)) + settings_set_cur_sel(hdlg, IDC_COMBO_FDC, d); + d++; + } + } - c++; - } + c++; + } - settings_enable_window(hdlg, IDC_COMBO_FDC, d); - settings_enable_window(hdlg, IDC_CONFIGURE_FDC, fdc_card_has_config(temp_fdc_card)); + settings_enable_window(hdlg, IDC_COMBO_FDC, d); + settings_enable_window(hdlg, IDC_CONFIGURE_FDC, fdc_card_has_config(temp_fdc_card)); - /*SCSI config*/ - c = d = 0; - for (e = 0; e < SCSI_BUS_MAX; e++) - settings_reset_content(hdlg, IDC_COMBO_SCSI_1 + e); - while (1) { - generate_device_name(scsi_card_getdevice(c), scsi_card_get_internal_name(c), 1); + /*SCSI config*/ + c = d = 0; + for (e = 0; e < SCSI_BUS_MAX; e++) + settings_reset_content(hdlg, IDC_COMBO_SCSI_1 + e); + while (1) { + generate_device_name(scsi_card_getdevice(c), scsi_card_get_internal_name(c), 1); - if (!device_name[0]) - break; + if (!device_name[0]) + break; - if (scsi_card_available(c)) { - scsi_dev = scsi_card_getdevice(c); + if (scsi_card_available(c)) { + scsi_dev = scsi_card_getdevice(c); - if (device_is_valid(scsi_dev, temp_machine)) { - for (e = 0; e < SCSI_BUS_MAX; e++) { - if (c == 0) - settings_add_string(hdlg, IDC_COMBO_SCSI_1 + e, win_get_string(IDS_2103)); - else - settings_add_string(hdlg, IDC_COMBO_SCSI_1 + e, (LPARAM) device_name); + if (device_is_valid(scsi_dev, temp_machine)) { + for (e = 0; e < SCSI_BUS_MAX; e++) { + if (c == 0) + settings_add_string(hdlg, IDC_COMBO_SCSI_1 + e, win_get_string(IDS_2104)); + else + settings_add_string(hdlg, IDC_COMBO_SCSI_1 + e, (LPARAM) device_name); - if ((c == 0) || (c == temp_scsi_card[e])) - settings_set_cur_sel(hdlg, IDC_COMBO_SCSI_1 + e, d); - } + if ((c == 0) || (c == temp_scsi_card[e])) + settings_set_cur_sel(hdlg, IDC_COMBO_SCSI_1 + e, d); + } - settings_list_to_device[0][d] = c; - d++; - } - } + settings_list_to_device[0][d] = c; + d++; + } + } - c++; - } + c++; + } - for (c = 0; c < SCSI_BUS_MAX; c++) { - settings_enable_window(hdlg, IDC_COMBO_SCSI_1 + c, d); - settings_enable_window(hdlg, IDC_CONFIGURE_SCSI_1 + c, scsi_card_has_config(temp_scsi_card[c])); - } - is_at = IS_AT(temp_machine); - settings_enable_window(hdlg, IDC_CHECK_IDE_TER, is_at); - settings_enable_window(hdlg, IDC_BUTTON_IDE_TER, is_at && temp_ide_ter); - settings_enable_window(hdlg, IDC_CHECK_IDE_QUA, is_at); - settings_enable_window(hdlg, IDC_BUTTON_IDE_QUA, is_at && temp_ide_qua); - settings_set_check(hdlg, IDC_CHECK_IDE_TER, temp_ide_ter); - settings_set_check(hdlg, IDC_CHECK_IDE_QUA, temp_ide_qua); - settings_set_check(hdlg, IDC_CHECK_CASSETTE, temp_cassette); + for (c = 0; c < SCSI_BUS_MAX; c++) { + settings_enable_window(hdlg, IDC_COMBO_SCSI_1 + c, d); + settings_enable_window(hdlg, IDC_CONFIGURE_SCSI_1 + c, scsi_card_has_config(temp_scsi_card[c])); + } + is_at = IS_AT(temp_machine); + settings_enable_window(hdlg, IDC_CHECK_IDE_TER, is_at); + settings_enable_window(hdlg, IDC_BUTTON_IDE_TER, is_at && temp_ide_ter); + settings_enable_window(hdlg, IDC_CHECK_IDE_QUA, is_at); + settings_enable_window(hdlg, IDC_BUTTON_IDE_QUA, is_at && temp_ide_qua); + settings_enable_window(hdlg, IDC_CHECK_CASSETTE, machine_has_bus(temp_machine, MACHINE_BUS_CASSETTE)); + settings_set_check(hdlg, IDC_CHECK_IDE_TER, temp_ide_ter); + settings_set_check(hdlg, IDC_CHECK_IDE_QUA, temp_ide_qua); + settings_set_check(hdlg, IDC_CHECK_CASSETTE, (temp_cassette && machine_has_bus(temp_machine, MACHINE_BUS_CASSETTE))); - free(stransi); - free(lptsTemp); + free(stransi); + free(lptsTemp); - return TRUE; + return TRUE; - case WM_COMMAND: - switch (LOWORD(wParam)) { - case IDC_CONFIGURE_FDC: - temp_fdc_card = settings_list_to_fdc[settings_get_cur_sel(hdlg, IDC_COMBO_FDC)]; - temp_deviceconfig |= deviceconfig_open(hdlg, (void *)fdc_card_getdevice(temp_fdc_card)); - break; + case WM_COMMAND: + switch (LOWORD(wParam)) { + case IDC_CONFIGURE_FDC: + temp_fdc_card = settings_list_to_fdc[settings_get_cur_sel(hdlg, IDC_COMBO_FDC)]; + temp_deviceconfig |= deviceconfig_open(hdlg, (void *) fdc_card_getdevice(temp_fdc_card)); + break; - case IDC_COMBO_FDC: - temp_fdc_card = settings_list_to_fdc[settings_get_cur_sel(hdlg, IDC_COMBO_FDC)]; - settings_enable_window(hdlg, IDC_CONFIGURE_FDC, fdc_card_has_config(temp_fdc_card)); - break; - - case IDC_CONFIGURE_HDC: - temp_hdc = settings_list_to_hdc[settings_get_cur_sel(hdlg, IDC_COMBO_HDC)]; - temp_deviceconfig |= deviceconfig_open(hdlg, (void *)hdc_get_device(temp_hdc)); - break; + case IDC_COMBO_FDC: + temp_fdc_card = settings_list_to_fdc[settings_get_cur_sel(hdlg, IDC_COMBO_FDC)]; + settings_enable_window(hdlg, IDC_CONFIGURE_FDC, fdc_card_has_config(temp_fdc_card)); + break; - case IDC_COMBO_HDC: - temp_hdc = settings_list_to_hdc[settings_get_cur_sel(hdlg, IDC_COMBO_HDC)]; - settings_enable_window(hdlg, IDC_CONFIGURE_HDC, hdc_has_config(temp_hdc)); - break; + case IDC_CONFIGURE_HDC: + temp_hdc = settings_list_to_hdc[settings_get_cur_sel(hdlg, IDC_COMBO_HDC)]; + temp_deviceconfig |= deviceconfig_open(hdlg, (void *) hdc_get_device(temp_hdc)); + break; - case IDC_CONFIGURE_SCSI_1 ... IDC_CONFIGURE_SCSI_4: - c = LOWORD(wParam) - IDC_CONFIGURE_SCSI_1; - temp_scsi_card[c] = settings_list_to_device[0][settings_get_cur_sel(hdlg, IDC_COMBO_SCSI_1 + c)]; - temp_deviceconfig |= deviceconfig_inst_open(hdlg, (void *)scsi_card_getdevice(temp_scsi_card[c]), c + 1); - break; + case IDC_COMBO_HDC: + temp_hdc = settings_list_to_hdc[settings_get_cur_sel(hdlg, IDC_COMBO_HDC)]; + settings_enable_window(hdlg, IDC_CONFIGURE_HDC, hdc_has_config(temp_hdc)); + break; - case IDC_COMBO_SCSI_1 ... IDC_COMBO_SCSI_4: - c = LOWORD(wParam) - IDC_COMBO_SCSI_1; - temp_scsi_card[c] = settings_list_to_device[0][settings_get_cur_sel(hdlg, IDC_COMBO_SCSI_1 + c)]; - settings_enable_window(hdlg, IDC_CONFIGURE_SCSI_1 + c, scsi_card_has_config(temp_scsi_card[c])); - break; + case IDC_CONFIGURE_SCSI_1 ... IDC_CONFIGURE_SCSI_4: + c = LOWORD(wParam) - IDC_CONFIGURE_SCSI_1; + temp_scsi_card[c] = settings_list_to_device[0][settings_get_cur_sel(hdlg, IDC_COMBO_SCSI_1 + c)]; + temp_deviceconfig |= deviceconfig_inst_open(hdlg, (void *) scsi_card_getdevice(temp_scsi_card[c]), c + 1); + break; - case IDC_CHECK_IDE_TER: - temp_ide_ter = settings_get_check(hdlg, IDC_CHECK_IDE_TER); - settings_enable_window(hdlg, IDC_BUTTON_IDE_TER, temp_ide_ter); - break; + case IDC_COMBO_SCSI_1 ... IDC_COMBO_SCSI_4: + c = LOWORD(wParam) - IDC_COMBO_SCSI_1; + temp_scsi_card[c] = settings_list_to_device[0][settings_get_cur_sel(hdlg, IDC_COMBO_SCSI_1 + c)]; + settings_enable_window(hdlg, IDC_CONFIGURE_SCSI_1 + c, scsi_card_has_config(temp_scsi_card[c])); + break; - case IDC_BUTTON_IDE_TER: - temp_deviceconfig |= deviceconfig_open(hdlg, (void *)&ide_ter_device); - break; + case IDC_CHECK_IDE_TER: + temp_ide_ter = settings_get_check(hdlg, IDC_CHECK_IDE_TER); + settings_enable_window(hdlg, IDC_BUTTON_IDE_TER, temp_ide_ter); + break; - case IDC_CHECK_IDE_QUA: - temp_ide_qua = settings_get_check(hdlg, IDC_CHECK_IDE_QUA); - settings_enable_window(hdlg, IDC_BUTTON_IDE_QUA, temp_ide_qua); - break; + case IDC_BUTTON_IDE_TER: + temp_deviceconfig |= deviceconfig_open(hdlg, (void *) &ide_ter_device); + break; - case IDC_BUTTON_IDE_QUA: - temp_deviceconfig |= deviceconfig_open(hdlg, (void *)&ide_qua_device); - break; - } - return FALSE; + case IDC_CHECK_IDE_QUA: + temp_ide_qua = settings_get_check(hdlg, IDC_CHECK_IDE_QUA); + settings_enable_window(hdlg, IDC_BUTTON_IDE_QUA, temp_ide_qua); + break; - case WM_SAVESETTINGS: - temp_hdc = settings_list_to_hdc[settings_get_cur_sel(hdlg, IDC_COMBO_HDC)]; - temp_fdc_card = settings_list_to_fdc[settings_get_cur_sel(hdlg, IDC_COMBO_FDC)]; - for (c = 0; c < SCSI_BUS_MAX; c++) - temp_scsi_card[c] = settings_list_to_device[0][settings_get_cur_sel(hdlg, IDC_COMBO_SCSI_1 + c)]; - temp_ide_ter = settings_get_check(hdlg, IDC_CHECK_IDE_TER); - temp_ide_qua = settings_get_check(hdlg, IDC_CHECK_IDE_QUA); - temp_cassette = settings_get_check(hdlg, IDC_CHECK_CASSETTE); + case IDC_BUTTON_IDE_QUA: + temp_deviceconfig |= deviceconfig_open(hdlg, (void *) &ide_qua_device); + break; + } + return FALSE; - default: - return FALSE; + case WM_SAVESETTINGS: + temp_hdc = settings_list_to_hdc[settings_get_cur_sel(hdlg, IDC_COMBO_HDC)]; + temp_fdc_card = settings_list_to_fdc[settings_get_cur_sel(hdlg, IDC_COMBO_FDC)]; + for (c = 0; c < SCSI_BUS_MAX; c++) + temp_scsi_card[c] = settings_list_to_device[0][settings_get_cur_sel(hdlg, IDC_COMBO_SCSI_1 + c)]; + temp_ide_ter = settings_get_check(hdlg, IDC_CHECK_IDE_TER); + temp_ide_qua = settings_get_check(hdlg, IDC_CHECK_IDE_QUA); + temp_cassette = settings_get_check(hdlg, IDC_CHECK_CASSETTE); + + default: + return FALSE; } return FALSE; } - -static void network_recalc_combos(HWND hdlg) +static void +network_recalc_combos(HWND hdlg) { ignore_change = 1; - settings_enable_window(hdlg, IDC_COMBO_PCAP, temp_net_type == NET_TYPE_PCAP); - settings_enable_window(hdlg, IDC_COMBO_NET, - (temp_net_type == NET_TYPE_SLIRP) || - ((temp_net_type == NET_TYPE_PCAP) && (network_dev_to_id(temp_pcap_dev) > 0))); - settings_enable_window(hdlg, IDC_CONFIGURE_NET, network_card_has_config(temp_net_card) && - ((temp_net_type == NET_TYPE_SLIRP) || - ((temp_net_type == NET_TYPE_PCAP) && (network_dev_to_id(temp_pcap_dev) > 0)))); + for (uint8_t i = 0; i < NET_CARD_MAX; i++) { + settings_enable_window(hdlg, IDC_COMBO_PCAP1 + i, temp_net_type[i] == NET_TYPE_PCAP); + settings_enable_window(hdlg, IDC_COMBO_NET1 + i, + (temp_net_type[i] == NET_TYPE_SLIRP) || ((temp_net_type[i] == NET_TYPE_PCAP) && (network_dev_to_id(temp_pcap_dev[i]) > 0))); + settings_enable_window(hdlg, IDC_CONFIGURE_NET1 + i, network_card_has_config(temp_net_card[i]) && ((temp_net_type[i] == NET_TYPE_SLIRP) || ((temp_net_type[i] == NET_TYPE_PCAP) && (network_dev_to_id(temp_pcap_dev[i]) > 0)))); + } ignore_change = 0; } - #if defined(__amd64__) || defined(__aarch64__) static LRESULT CALLBACK #else static BOOL CALLBACK #endif -win_settings_network_proc(HWND hdlg, UINT message, WPARAM wParam, LPARAM lParam) +win_settings_network_proc(HWND hdlg, UINT message, WPARAM wParam, UNUSED(LPARAM lParam)) { - int c, d; + int c; + int d; LPTSTR lptsTemp; switch (message) { - case WM_INITDIALOG: - lptsTemp = (LPTSTR) malloc(512 * sizeof(WCHAR)); + case WM_INITDIALOG: + lptsTemp = (LPTSTR) malloc(512 * sizeof(WCHAR)); - settings_add_string(hdlg, IDC_COMBO_NET_TYPE, (LPARAM) L"None"); - settings_add_string(hdlg, IDC_COMBO_NET_TYPE, (LPARAM) L"PCap"); - settings_add_string(hdlg, IDC_COMBO_NET_TYPE, (LPARAM) L"SLiRP"); - settings_set_cur_sel(hdlg, IDC_COMBO_NET_TYPE, temp_net_type); - settings_enable_window(hdlg, IDC_COMBO_PCAP, temp_net_type == NET_TYPE_PCAP); + for (uint8_t i = 0; i < NET_CARD_MAX; i++) { + settings_add_string(hdlg, IDC_COMBO_NET1_TYPE + i, (LPARAM) L"Null Driver"); + settings_add_string(hdlg, IDC_COMBO_NET1_TYPE + i, (LPARAM) L"SLiRP"); + settings_add_string(hdlg, IDC_COMBO_NET1_TYPE + i, (LPARAM) L"PCap"); + settings_set_cur_sel(hdlg, IDC_COMBO_NET1_TYPE + i, temp_net_type[i]); + settings_enable_window(hdlg, IDC_COMBO_PCAP1 + i, temp_net_type[i] == NET_TYPE_PCAP); - for (c = 0; c < network_ndev; c++) { - mbstowcs(lptsTemp, network_devs[c].description, strlen(network_devs[c].description) + 1); - settings_add_string(hdlg, IDC_COMBO_PCAP, (LPARAM) lptsTemp); - } - settings_set_cur_sel(hdlg, IDC_COMBO_PCAP, network_dev_to_id(temp_pcap_dev)); + for (c = 0; c < network_ndev; c++) { + mbstowcs(lptsTemp, network_devs[c].description, strlen(network_devs[c].description) + 1); + settings_add_string(hdlg, IDC_COMBO_PCAP1 + i, (LPARAM) lptsTemp); + } + settings_set_cur_sel(hdlg, IDC_COMBO_PCAP1 + i, network_dev_to_id(temp_pcap_dev[i])); - /* NIC config */ - c = d = 0; - settings_reset_content(hdlg, IDC_COMBO_NET); - while (1) { - generate_device_name(network_card_getdevice(c), network_card_get_internal_name(c), 1); + /* NIC config */ + c = d = 0; + settings_reset_content(hdlg, IDC_COMBO_NET1 + i); + while (1) { + generate_device_name(network_card_getdevice(c), network_card_get_internal_name(c), 1); - if (device_name[0] == L'\0') - break; + if (device_name[0] == L'\0') + break; - if (network_card_available(c) && device_is_valid(network_card_getdevice(c), temp_machine)) { - if (c == 0) - settings_add_string(hdlg, IDC_COMBO_NET, win_get_string(IDS_2103)); - else - settings_add_string(hdlg, IDC_COMBO_NET, (LPARAM) device_name); - settings_list_to_device[0][d] = c; - if ((c == 0) || (c == temp_net_card)) - settings_set_cur_sel(hdlg, IDC_COMBO_NET, d); - d++; - } + if (network_card_available(c) && device_is_valid(network_card_getdevice(c), temp_machine)) { + if (c == 0) + settings_add_string(hdlg, IDC_COMBO_NET1 + i, win_get_string(IDS_2104)); + else + settings_add_string(hdlg, IDC_COMBO_NET1 + i, (LPARAM) device_name); + settings_list_to_device[0][d] = c; + if ((c == 0) || (c == temp_net_card[i])) + settings_set_cur_sel(hdlg, IDC_COMBO_NET1 + i, d); + d++; + } - c++; - } + c++; + } - settings_enable_window(hdlg, IDC_COMBO_NET, d); - network_recalc_combos(hdlg); - free(lptsTemp); + settings_enable_window(hdlg, IDC_COMBO_NET1 + i, d); + network_recalc_combos(hdlg); + } + free(lptsTemp); + return TRUE; - return TRUE; + case WM_COMMAND: + switch (LOWORD(wParam)) { + case IDC_COMBO_NET1_TYPE: + if (ignore_change) + return FALSE; - case WM_COMMAND: - switch (LOWORD(wParam)) { - case IDC_COMBO_NET_TYPE: - if (ignore_change) - return FALSE; + temp_net_type[0] = settings_get_cur_sel(hdlg, IDC_COMBO_NET1_TYPE); + network_recalc_combos(hdlg); + break; + case IDC_COMBO_NET2_TYPE: + if (ignore_change) + return FALSE; - temp_net_type = settings_get_cur_sel(hdlg, IDC_COMBO_NET_TYPE); - network_recalc_combos(hdlg); - break; + temp_net_type[1] = settings_get_cur_sel(hdlg, IDC_COMBO_NET2_TYPE); + network_recalc_combos(hdlg); + break; + case IDC_COMBO_NET3_TYPE: + if (ignore_change) + return FALSE; - case IDC_COMBO_PCAP: - if (ignore_change) - return FALSE; + temp_net_type[2] = settings_get_cur_sel(hdlg, IDC_COMBO_NET3_TYPE); + network_recalc_combos(hdlg); + break; + case IDC_COMBO_NET4_TYPE: + if (ignore_change) + return FALSE; - memset(temp_pcap_dev, '\0', sizeof(temp_pcap_dev)); - strcpy(temp_pcap_dev, network_devs[settings_get_cur_sel(hdlg, IDC_COMBO_PCAP)].device); - network_recalc_combos(hdlg); - break; + temp_net_type[3] = settings_get_cur_sel(hdlg, IDC_COMBO_NET4_TYPE); + network_recalc_combos(hdlg); + break; - case IDC_COMBO_NET: - if (ignore_change) - return FALSE; + case IDC_COMBO_PCAP1: + if (ignore_change) + return FALSE; - temp_net_card = settings_list_to_device[0][settings_get_cur_sel(hdlg, IDC_COMBO_NET)]; - network_recalc_combos(hdlg); - break; + memset(temp_pcap_dev[0], '\0', sizeof(temp_pcap_dev[0])); + strcpy(temp_pcap_dev[0], network_devs[settings_get_cur_sel(hdlg, IDC_COMBO_PCAP1)].device); + network_recalc_combos(hdlg); + break; + case IDC_COMBO_PCAP2: + if (ignore_change) + return FALSE; - case IDC_CONFIGURE_NET: - if (ignore_change) - return FALSE; + memset(temp_pcap_dev[1], '\0', sizeof(temp_pcap_dev[1])); + strcpy(temp_pcap_dev[1], network_devs[settings_get_cur_sel(hdlg, IDC_COMBO_PCAP2)].device); + network_recalc_combos(hdlg); + break; + case IDC_COMBO_PCAP3: + if (ignore_change) + return FALSE; - temp_net_card = settings_list_to_device[0][settings_get_cur_sel(hdlg, IDC_COMBO_NET)]; - temp_deviceconfig |= deviceconfig_open(hdlg, (void *)network_card_getdevice(temp_net_card)); - break; - } - return FALSE; + memset(temp_pcap_dev[2], '\0', sizeof(temp_pcap_dev[2])); + strcpy(temp_pcap_dev[2], network_devs[settings_get_cur_sel(hdlg, IDC_COMBO_PCAP3)].device); + network_recalc_combos(hdlg); + break; + case IDC_COMBO_PCAP4: + if (ignore_change) + return FALSE; - case WM_SAVESETTINGS: - temp_net_type = settings_get_cur_sel(hdlg, IDC_COMBO_NET_TYPE); - memset(temp_pcap_dev, '\0', sizeof(temp_pcap_dev)); - strcpy(temp_pcap_dev, network_devs[settings_get_cur_sel(hdlg, IDC_COMBO_PCAP)].device); - temp_net_card = settings_list_to_device[0][settings_get_cur_sel(hdlg, IDC_COMBO_NET)]; + memset(temp_pcap_dev[3], '\0', sizeof(temp_pcap_dev[3])); + strcpy(temp_pcap_dev[3], network_devs[settings_get_cur_sel(hdlg, IDC_COMBO_PCAP4)].device); + network_recalc_combos(hdlg); + break; - default: - return FALSE; + case IDC_COMBO_NET1: + if (ignore_change) + return FALSE; + + temp_net_card[0] = settings_list_to_device[0][settings_get_cur_sel(hdlg, IDC_COMBO_NET1)]; + network_recalc_combos(hdlg); + break; + case IDC_COMBO_NET2: + if (ignore_change) + return FALSE; + + temp_net_card[1] = settings_list_to_device[0][settings_get_cur_sel(hdlg, IDC_COMBO_NET2)]; + network_recalc_combos(hdlg); + break; + case IDC_COMBO_NET3: + if (ignore_change) + return FALSE; + + temp_net_card[2] = settings_list_to_device[0][settings_get_cur_sel(hdlg, IDC_COMBO_NET3)]; + network_recalc_combos(hdlg); + break; + case IDC_COMBO_NET4: + if (ignore_change) + return FALSE; + + temp_net_card[3] = settings_list_to_device[0][settings_get_cur_sel(hdlg, IDC_COMBO_NET4)]; + network_recalc_combos(hdlg); + break; + + case IDC_CONFIGURE_NET1: + if (ignore_change) + return FALSE; + + temp_net_card[0] = settings_list_to_device[0][settings_get_cur_sel(hdlg, IDC_COMBO_NET1)]; + temp_deviceconfig |= deviceconfig_open(hdlg, (void *) network_card_getdevice(temp_net_card[0])); + break; + case IDC_CONFIGURE_NET2: + if (ignore_change) + return FALSE; + + temp_net_card[1] = settings_list_to_device[0][settings_get_cur_sel(hdlg, IDC_COMBO_NET2)]; + temp_deviceconfig |= deviceconfig_open(hdlg, (void *) network_card_getdevice(temp_net_card[1])); + break; + case IDC_CONFIGURE_NET3: + if (ignore_change) + return FALSE; + + temp_net_card[2] = settings_list_to_device[0][settings_get_cur_sel(hdlg, IDC_COMBO_NET3)]; + temp_deviceconfig |= deviceconfig_open(hdlg, (void *) network_card_getdevice(temp_net_card[2])); + break; + case IDC_CONFIGURE_NET4: + if (ignore_change) + return FALSE; + + temp_net_card[3] = settings_list_to_device[0][settings_get_cur_sel(hdlg, IDC_COMBO_NET4)]; + temp_deviceconfig |= deviceconfig_open(hdlg, (void *) network_card_getdevice(temp_net_card[3])); + break; + } + return FALSE; + + case WM_SAVESETTINGS: + for (uint8_t i = 0; i < NET_CARD_MAX; i++) { + temp_net_type[i] = settings_get_cur_sel(hdlg, IDC_COMBO_NET1_TYPE + i); + memset(temp_pcap_dev[i], '\0', sizeof(temp_pcap_dev[i])); + strcpy(temp_pcap_dev[i], network_devs[settings_get_cur_sel(hdlg, IDC_COMBO_PCAP1 + i)].device); + temp_net_card[i] = settings_list_to_device[0][settings_get_cur_sel(hdlg, IDC_COMBO_NET1 + i)]; + } + default: + return FALSE; } return FALSE; } - static void -normalize_hd_list() +normalize_hd_list(void) { hard_disk_t ihdd[HDD_NUM]; - int i, j; + int j = 0; - j = 0; memset(ihdd, 0x00, HDD_NUM * sizeof(hard_disk_t)); - for (i = 0; i < HDD_NUM; i++) { - if (temp_hdd[i].bus != HDD_BUS_DISABLED) { - memcpy(&(ihdd[j]), &(temp_hdd[i]), sizeof(hard_disk_t)); - j++; - } + for (uint8_t i = 0; i < HDD_NUM; i++) { + if (temp_hdd[i].bus != HDD_BUS_DISABLED) { + memcpy(&(ihdd[j]), &(temp_hdd[i]), sizeof(hard_disk_t)); + j++; + } } memcpy(temp_hdd, ihdd, HDD_NUM * sizeof(hard_disk_t)); } - static int get_selected_hard_disk(HWND hdlg) { - int hard_disk = -1; - int i, j = 0; + int hard_disk = -1; + int j = 0; HWND h; if (hd_listview_items == 0) - return 0; + return 0; - for (i = 0; i < hd_listview_items; i++) { - h = GetDlgItem(hdlg, IDC_LIST_HARD_DISKS); - j = ListView_GetItemState(h, i, LVIS_SELECTED); - if (j) - hard_disk = i; + for (int i = 0; i < hd_listview_items; i++) { + h = GetDlgItem(hdlg, IDC_LIST_HARD_DISKS); + j = ListView_GetItemState(h, i, LVIS_SELECTED); + if (j) + hard_disk = i; } return hard_disk; } - static void add_locations(HWND hdlg) { LPTSTR lptsTemp; - int i = 0; + int i = 0; lptsTemp = (LPTSTR) malloc(512 * sizeof(WCHAR)); for (i = 0; i < 6; i++) - settings_add_string(hdlg, IDC_COMBO_HD_BUS, win_get_string(IDS_4352 + i)); + settings_add_string(hdlg, IDC_COMBO_HD_BUS, win_get_string(IDS_4352 + i)); for (i = 0; i < 2; i++) { - wsprintf(lptsTemp, plat_get_string(IDS_4097), i >> 1, i & 1); - settings_add_string(hdlg, IDC_COMBO_HD_CHANNEL, (LPARAM) lptsTemp); + wsprintf(lptsTemp, plat_get_string(IDS_4097), i >> 1, i & 1); + settings_add_string(hdlg, IDC_COMBO_HD_CHANNEL, (LPARAM) lptsTemp); } - for (i = 0; i < 64; i++) { - wsprintf(lptsTemp, plat_get_string(IDS_4135), i >> 4, i & 15); - settings_add_string(hdlg, IDC_COMBO_HD_ID, (LPARAM) lptsTemp); + for (i = 0; i < (SCSI_BUS_MAX * SCSI_ID_MAX); i++) { + wsprintf(lptsTemp, plat_get_string(IDS_4135), i >> 4, i & 15); + settings_add_string(hdlg, IDC_COMBO_HD_ID, (LPARAM) lptsTemp); } - for (i = 0; i < 8; i++) { - wsprintf(lptsTemp, plat_get_string(IDS_4097), i >> 1, i & 1); - settings_add_string(hdlg, IDC_COMBO_HD_CHANNEL_IDE, (LPARAM) lptsTemp); + for (i = 0; i < (IDE_BUS_MAX * IDE_CHAN_MAX); i++) { + wsprintf(lptsTemp, plat_get_string(IDS_4097), i >> 1, i & 1); + settings_add_string(hdlg, IDC_COMBO_HD_CHANNEL_IDE, (LPARAM) lptsTemp); } free(lptsTemp); } - static uint8_t next_free_binary_channel(uint64_t *tracking) { - int64_t i; - - for (i = 0; i < 2; i++) { - if (!(*tracking & (0xffLL << (i << 3LL)))) - return i; + for (int64_t i = 0; i < 2; i++) { + if (!(*tracking & (0xffLL << (i << 3LL)))) + return i; } return 2; } - static uint8_t next_free_ide_channel(void) { - int64_t i; - - for (i = 0; i < 8; i++) { - if (!(ide_tracking & (0xffLL << (i << 3LL)))) - return i; + for (int64_t i = 0; i < (IDE_BUS_MAX * IDE_CHAN_MAX); i++) { + if (!(ide_tracking & (0xffLL << (i << 3LL)))) + return i; } return 7; } - static void next_free_scsi_id(uint8_t *id) { - int64_t i; - - for (i = 0; i < 64; i++) { - if (!(scsi_tracking[i >> 3] & (0xffLL << ((i & 0x07) << 3LL)))) { - *id = i; - return; - } + for (int64_t i = 0; i < (SCSI_BUS_MAX * SCSI_ID_MAX); i++) { + if (!(scsi_tracking[i >> 3] & (0xffLL << ((i & 0x07) << 3LL)))) { + *id = i; + return; + } } *id = 6; } - static void recalc_location_controls(HWND hdlg, int is_add_dlg, int assign_id) { - int i = 0, bus = 0; + int bus = 0; - for (i = IDT_CHANNEL; i <= IDT_ID; i++) - settings_show_window(hdlg, i, FALSE); + for (uint16_t i = IDT_CHANNEL; i <= IDT_ID; i++) + settings_show_window(hdlg, i, FALSE); settings_show_window(hdlg, IDC_COMBO_HD_CHANNEL, FALSE); settings_show_window(hdlg, IDC_COMBO_HD_ID, FALSE); settings_show_window(hdlg, IDC_COMBO_HD_CHANNEL_IDE, FALSE); if ((hd_listview_items > 0) || is_add_dlg) { - bus = settings_get_cur_sel(hdlg, IDC_COMBO_HD_BUS) + 1; + bus = settings_get_cur_sel(hdlg, IDC_COMBO_HD_BUS) + 1; - switch(bus) { - case HDD_BUS_MFM: /* MFM */ - settings_show_window(hdlg, IDT_CHANNEL, TRUE); - settings_show_window(hdlg, IDC_COMBO_HD_CHANNEL, TRUE); + switch (bus) { + case HDD_BUS_MFM: /* MFM */ + settings_show_window(hdlg, IDT_CHANNEL, TRUE); + settings_show_window(hdlg, IDC_COMBO_HD_CHANNEL, TRUE); - if (assign_id) - temp_hdd[lv1_current_sel].mfm_channel = next_free_binary_channel(&mfm_tracking); - settings_set_cur_sel(hdlg, IDC_COMBO_HD_CHANNEL, is_add_dlg ? new_hdd.mfm_channel : temp_hdd[lv1_current_sel].mfm_channel); - break; - case HDD_BUS_XTA: /* XTA */ - settings_show_window(hdlg, IDT_CHANNEL, TRUE); - settings_show_window(hdlg, IDC_COMBO_HD_CHANNEL, TRUE); + if (assign_id) + temp_hdd[lv1_current_sel].mfm_channel = next_free_binary_channel(&mfm_tracking); + settings_set_cur_sel(hdlg, IDC_COMBO_HD_CHANNEL, is_add_dlg ? new_hdd.mfm_channel : temp_hdd[lv1_current_sel].mfm_channel); + break; + case HDD_BUS_XTA: /* XTA */ + settings_show_window(hdlg, IDT_CHANNEL, TRUE); + settings_show_window(hdlg, IDC_COMBO_HD_CHANNEL, TRUE); - if (assign_id) - temp_hdd[lv1_current_sel].xta_channel = next_free_binary_channel(&xta_tracking); - settings_set_cur_sel(hdlg, IDC_COMBO_HD_CHANNEL, is_add_dlg ? new_hdd.xta_channel : temp_hdd[lv1_current_sel].xta_channel); - break; - case HDD_BUS_ESDI: /* ESDI */ - settings_show_window(hdlg, IDT_CHANNEL, TRUE); - settings_show_window(hdlg, IDC_COMBO_HD_CHANNEL, TRUE); + if (assign_id) + temp_hdd[lv1_current_sel].xta_channel = next_free_binary_channel(&xta_tracking); + settings_set_cur_sel(hdlg, IDC_COMBO_HD_CHANNEL, is_add_dlg ? new_hdd.xta_channel : temp_hdd[lv1_current_sel].xta_channel); + break; + case HDD_BUS_ESDI: /* ESDI */ + settings_show_window(hdlg, IDT_CHANNEL, TRUE); + settings_show_window(hdlg, IDC_COMBO_HD_CHANNEL, TRUE); - if (assign_id) - temp_hdd[lv1_current_sel].esdi_channel = next_free_binary_channel(&esdi_tracking); - settings_set_cur_sel(hdlg, IDC_COMBO_HD_CHANNEL, is_add_dlg ? new_hdd.esdi_channel : temp_hdd[lv1_current_sel].esdi_channel); - break; - case HDD_BUS_IDE: /* IDE */ - case HDD_BUS_ATAPI: /* ATAPI */ - settings_show_window(hdlg, IDT_CHANNEL, TRUE); - settings_show_window(hdlg, IDC_COMBO_HD_CHANNEL_IDE, TRUE); + if (assign_id) + temp_hdd[lv1_current_sel].esdi_channel = next_free_binary_channel(&esdi_tracking); + settings_set_cur_sel(hdlg, IDC_COMBO_HD_CHANNEL, is_add_dlg ? new_hdd.esdi_channel : temp_hdd[lv1_current_sel].esdi_channel); + break; + case HDD_BUS_IDE: /* IDE */ + case HDD_BUS_ATAPI: /* ATAPI */ + settings_show_window(hdlg, IDT_CHANNEL, TRUE); + settings_show_window(hdlg, IDC_COMBO_HD_CHANNEL_IDE, TRUE); - if (assign_id) - temp_hdd[lv1_current_sel].ide_channel = next_free_ide_channel(); - settings_set_cur_sel(hdlg, IDC_COMBO_HD_CHANNEL_IDE, is_add_dlg ? new_hdd.ide_channel : temp_hdd[lv1_current_sel].ide_channel); - break; - case HDD_BUS_SCSI: /* SCSI */ - settings_show_window(hdlg, IDT_ID, TRUE); - settings_show_window(hdlg, IDT_LUN, TRUE); - settings_show_window(hdlg, IDC_COMBO_HD_ID, TRUE); + if (assign_id) + temp_hdd[lv1_current_sel].ide_channel = next_free_ide_channel(); + settings_set_cur_sel(hdlg, IDC_COMBO_HD_CHANNEL_IDE, is_add_dlg ? new_hdd.ide_channel : temp_hdd[lv1_current_sel].ide_channel); + break; + case HDD_BUS_SCSI: /* SCSI */ + settings_show_window(hdlg, IDT_ID, TRUE); + settings_show_window(hdlg, IDT_LUN, TRUE); + settings_show_window(hdlg, IDC_COMBO_HD_ID, TRUE); - if (assign_id) - next_free_scsi_id((uint8_t *) (is_add_dlg ? &(new_hdd.scsi_id) : &(temp_hdd[lv1_current_sel].scsi_id))); - settings_set_cur_sel(hdlg, IDC_COMBO_HD_ID, is_add_dlg ? new_hdd.scsi_id : temp_hdd[lv1_current_sel].scsi_id); - } + if (assign_id) + next_free_scsi_id((is_add_dlg ? &(new_hdd.scsi_id) : &(temp_hdd[lv1_current_sel].scsi_id))); + settings_set_cur_sel(hdlg, IDC_COMBO_HD_ID, is_add_dlg ? new_hdd.scsi_id : temp_hdd[lv1_current_sel].scsi_id); + } } settings_show_window(hdlg, IDT_BUS, (hd_listview_items != 0) || is_add_dlg); settings_show_window(hdlg, IDC_COMBO_HD_BUS, (hd_listview_items != 0) || is_add_dlg); } - static int bus_full(uint64_t *tracking, int count) { int full = 0; - switch(count) { - case 2: - default: - full = (*tracking & 0xFF00LL); - full = full && (*tracking & 0x00FFLL); - break; - case 8: - full = (*tracking & 0xFF00000000000000LL); - full = full && (*tracking & 0x00FF000000000000LL); - full = full && (*tracking & 0x0000FF0000000000LL); - full = full && (*tracking & 0x000000FF00000000LL); - full = full && (*tracking & 0x00000000FF000000LL); - full = full && (*tracking & 0x0000000000FF0000LL); - full = full && (*tracking & 0x000000000000FF00LL); - full = full && (*tracking & 0x00000000000000FFLL); - break; + switch (count) { + default: + case 2: + full = (*tracking & 0xFF00LL); + full = full && (*tracking & 0x00FFLL); + break; + case 8: + full = (*tracking & 0xFF00000000000000LL); + full = full && (*tracking & 0x00FF000000000000LL); + full = full && (*tracking & 0x0000FF0000000000LL); + full = full && (*tracking & 0x000000FF00000000LL); + full = full && (*tracking & 0x00000000FF000000LL); + full = full && (*tracking & 0x0000000000FF0000LL); + full = full && (*tracking & 0x000000000000FF00LL); + full = full && (*tracking & 0x00000000000000FFLL); + break; } return full; } - static void recalc_next_free_id(HWND hdlg) { - int i, enable_add = 0; - int c_mfm = 0, c_esdi = 0; - int c_xta = 0, c_ide = 0; - int c_atapi = 0, c_scsi = 0; + int i; + int enable_add = 0; + int c_mfm = 0; + int c_esdi = 0; + int c_xta = 0; + int c_ide = 0; + int c_atapi = 0; + int c_scsi = 0; next_free_id = -1; for (i = 0; i < HDD_NUM; i++) { - if (temp_hdd[i].bus == HDD_BUS_MFM) - c_mfm++; - else if (temp_hdd[i].bus == HDD_BUS_ESDI) - c_esdi++; - else if (temp_hdd[i].bus == HDD_BUS_XTA) - c_xta++; - else if (temp_hdd[i].bus == HDD_BUS_IDE) - c_ide++; - else if (temp_hdd[i].bus == HDD_BUS_ATAPI) - c_atapi++; - else if (temp_hdd[i].bus == HDD_BUS_SCSI) - c_scsi++; + if (temp_hdd[i].bus == HDD_BUS_MFM) + c_mfm++; + else if (temp_hdd[i].bus == HDD_BUS_ESDI) + c_esdi++; + else if (temp_hdd[i].bus == HDD_BUS_XTA) + c_xta++; + else if (temp_hdd[i].bus == HDD_BUS_IDE) + c_ide++; + else if (temp_hdd[i].bus == HDD_BUS_ATAPI) + c_atapi++; + else if (temp_hdd[i].bus == HDD_BUS_SCSI) + c_scsi++; } for (i = 0; i < HDD_NUM; i++) { - if (temp_hdd[i].bus == HDD_BUS_DISABLED) { - next_free_id = i; - break; - } + if (temp_hdd[i].bus == HDD_BUS_DISABLED) { + next_free_id = i; + break; + } } enable_add = enable_add || (next_free_id >= 0); - enable_add = enable_add && ((c_mfm < MFM_NUM) || (c_esdi < ESDI_NUM) || (c_xta < XTA_NUM) || - (c_ide < IDE_NUM) || (c_ide < ATAPI_NUM) || (c_scsi < SCSI_NUM)); - enable_add = enable_add && !bus_full(&mfm_tracking, 2); - enable_add = enable_add && !bus_full(&esdi_tracking, 2); - enable_add = enable_add && !bus_full(&xta_tracking, 2); - enable_add = enable_add && !bus_full(&ide_tracking, 8); - for (i = 0; i < 2; i++) - enable_add = enable_add && !bus_full(&(scsi_tracking[i]), 8); + enable_add = enable_add && ((c_mfm < MFM_NUM) || (c_esdi < ESDI_NUM) || (c_xta < XTA_NUM) || (c_ide < IDE_NUM) || (c_ide < ATAPI_NUM) || (c_scsi < SCSI_NUM)); + enable_add = enable_add && (!bus_full(&mfm_tracking, 2) || !bus_full(&esdi_tracking, 2) || !bus_full(&xta_tracking, 2) || !bus_full(&ide_tracking, IDE_CHAN_MAX * IDE_BUS_MAX) || + !bus_full(&(scsi_tracking[0]), 8) || !bus_full(&(scsi_tracking[1]), 8) || !bus_full(&(scsi_tracking[2]), 8) || !bus_full(&(scsi_tracking[3]), 8) || + !bus_full(&(scsi_tracking[4]), 8) || !bus_full(&(scsi_tracking[5]), 8) || !bus_full(&(scsi_tracking[6]), 8) || !bus_full(&(scsi_tracking[7]), 8)); settings_enable_window(hdlg, IDC_BUTTON_HDD_ADD_NEW, enable_add); settings_enable_window(hdlg, IDC_BUTTON_HDD_ADD, enable_add); settings_enable_window(hdlg, IDC_BUTTON_HDD_REMOVE, - (c_mfm != 0) || (c_esdi != 0) || (c_xta != 0) || (c_ide != 0) || - (c_atapi != 0) || (c_scsi != 0)); + (c_mfm != 0) || (c_esdi != 0) || (c_xta != 0) || (c_ide != 0) || (c_atapi != 0) || (c_scsi != 0)); } - static void win_settings_hard_disks_update_item(HWND hdlg, int i, int column) { - HWND hwndList = GetDlgItem(hdlg, IDC_LIST_HARD_DISKS); + HWND hwndList = GetDlgItem(hdlg, IDC_LIST_HARD_DISKS); LVITEM lvI; - WCHAR szText[256]; + WCHAR szText[256]; - lvI.mask = LVIF_TEXT | LVIF_IMAGE | LVIF_STATE; + lvI.mask = LVIF_TEXT | LVIF_IMAGE | LVIF_STATE; lvI.stateMask = lvI.iSubItem = lvI.state = 0; lvI.iSubItem = column; - lvI.iItem = i; + lvI.iItem = i; - if (column == 0) { - switch(temp_hdd[i].bus) { - case HDD_BUS_MFM: - wsprintf(szText, plat_get_string(IDS_4608), temp_hdd[i].mfm_channel >> 1, temp_hdd[i].mfm_channel & 1); - break; - case HDD_BUS_XTA: - wsprintf(szText, plat_get_string(IDS_4609), temp_hdd[i].xta_channel >> 1, temp_hdd[i].xta_channel & 1); - break; - case HDD_BUS_ESDI: - wsprintf(szText, plat_get_string(IDS_4610), temp_hdd[i].esdi_channel >> 1, temp_hdd[i].esdi_channel & 1); - break; - case HDD_BUS_IDE: - wsprintf(szText, plat_get_string(IDS_4611), temp_hdd[i].ide_channel >> 1, temp_hdd[i].ide_channel & 1); - break; - case HDD_BUS_ATAPI: - wsprintf(szText, plat_get_string(IDS_4612), temp_hdd[i].ide_channel >> 1, temp_hdd[i].ide_channel & 1); - break; - case HDD_BUS_SCSI: - wsprintf(szText, plat_get_string(IDS_4613), temp_hdd[i].scsi_id >> 4, temp_hdd[i].scsi_id & 15); - break; - } - lvI.pszText = szText; - lvI.iImage = 0; - } else if (column == 1) { - if (!strnicmp(temp_hdd[i].fn, usr_path, strlen(usr_path))) - mbstoc16s(szText, temp_hdd[i].fn + strlen(usr_path), sizeof_w(szText)); - else - mbstoc16s(szText, temp_hdd[i].fn, sizeof_w(szText)); - lvI.pszText = szText; - lvI.iImage = 0; - } else if (column == 2) { - wsprintf(szText, plat_get_string(IDS_4098), temp_hdd[i].tracks); - lvI.pszText = szText; - lvI.iImage = 0; - } else if (column == 3) { - wsprintf(szText, plat_get_string(IDS_4098), temp_hdd[i].hpc); - lvI.pszText = szText; - lvI.iImage = 0; - } else if (column == 4) { - wsprintf(szText, plat_get_string(IDS_4098), temp_hdd[i].spt); - lvI.pszText = szText; - lvI.iImage = 0; - } else if (column == 5) { - wsprintf(szText, plat_get_string(IDS_4098), (temp_hdd[i].tracks * temp_hdd[i].hpc * temp_hdd[i].spt) >> 11); - lvI.pszText = szText; - lvI.iImage = 0; + if (column == 0) { /* Bus */ + switch (temp_hdd[i].bus) { + case HDD_BUS_MFM: + wsprintf(szText, plat_get_string(IDS_4608), temp_hdd[i].mfm_channel >> 1, temp_hdd[i].mfm_channel & 1); + break; + case HDD_BUS_XTA: + wsprintf(szText, plat_get_string(IDS_4609), temp_hdd[i].xta_channel >> 1, temp_hdd[i].xta_channel & 1); + break; + case HDD_BUS_ESDI: + wsprintf(szText, plat_get_string(IDS_4610), temp_hdd[i].esdi_channel >> 1, temp_hdd[i].esdi_channel & 1); + break; + case HDD_BUS_IDE: + wsprintf(szText, plat_get_string(IDS_4611), temp_hdd[i].ide_channel >> 1, temp_hdd[i].ide_channel & 1); + break; + case HDD_BUS_ATAPI: + wsprintf(szText, plat_get_string(IDS_4612), temp_hdd[i].ide_channel >> 1, temp_hdd[i].ide_channel & 1); + break; + case HDD_BUS_SCSI: + wsprintf(szText, plat_get_string(IDS_4613), temp_hdd[i].scsi_id >> 4, temp_hdd[i].scsi_id & 15); + break; + } + lvI.pszText = szText; + lvI.iImage = 0; + } else if (column == 1) { /* File */ + if (!strnicmp(temp_hdd[i].fn, usr_path, strlen(usr_path))) + mbstoc16s(szText, temp_hdd[i].fn + strlen(usr_path), sizeof_w(szText)); + else + mbstoc16s(szText, temp_hdd[i].fn, sizeof_w(szText)); + lvI.pszText = szText; + lvI.iImage = 0; + } else if (column == 2) { /* Cylinders */ + wsprintf(szText, plat_get_string(IDS_4098), temp_hdd[i].tracks); + lvI.pszText = szText; + lvI.iImage = 0; + } else if (column == 3) { /* Heads */ + wsprintf(szText, plat_get_string(IDS_4098), temp_hdd[i].hpc); + lvI.pszText = szText; + lvI.iImage = 0; + } else if (column == 4) { /* Sectors */ + wsprintf(szText, plat_get_string(IDS_4098), temp_hdd[i].spt); + lvI.pszText = szText; + lvI.iImage = 0; + } else if (column == 5) { /* Size (MB) */ + wsprintf(szText, plat_get_string(IDS_4098), (temp_hdd[i].tracks * temp_hdd[i].hpc * temp_hdd[i].spt) >> 11); + lvI.pszText = szText; + lvI.iImage = 0; + } else if (column == 6) { /* Speed (RPM) */ + mbstoc16s(szText, hdd_preset_getname(temp_hdd[i].speed_preset), sizeof_w(szText)); + lvI.pszText = szText; + lvI.iImage = 0; } if (ListView_SetItem(hwndList, &lvI) == -1) - return; + return; } - static BOOL win_settings_hard_disks_recalc_list(HWND hdlg) { LVITEM lvI; - int i, j = 0; - WCHAR szText[256], usr_path_w[1024]; - HWND hwndList = GetDlgItem(hdlg, IDC_LIST_HARD_DISKS); + int j = 0; + WCHAR szText[256]; + WCHAR usr_path_w[1024]; + HWND hwndList = GetDlgItem(hdlg, IDC_LIST_HARD_DISKS); mbstoc16s(usr_path_w, usr_path, sizeof_w(usr_path_w)); hd_listview_items = 0; - lv1_current_sel = -1; + lv1_current_sel = -1; ListView_DeleteAllItems(hwndList); - lvI.mask = LVIF_TEXT | LVIF_IMAGE | LVIF_STATE; + lvI.mask = LVIF_TEXT | LVIF_IMAGE | LVIF_STATE; lvI.stateMask = lvI.iSubItem = lvI.state = 0; - for (i = 0; i < HDD_NUM; i++) { - if (temp_hdd[i].bus > 0) { - hdc_id_to_listview_index[i] = j; - lvI.iSubItem = 0; - switch(temp_hdd[i].bus) { - case HDD_BUS_MFM: - wsprintf(szText, plat_get_string(IDS_4608), temp_hdd[i].mfm_channel >> 1, temp_hdd[i].mfm_channel & 1); - break; - case HDD_BUS_XTA: - wsprintf(szText, plat_get_string(IDS_4609), temp_hdd[i].xta_channel >> 1, temp_hdd[i].xta_channel & 1); - break; - case HDD_BUS_ESDI: - wsprintf(szText, plat_get_string(IDS_4610), temp_hdd[i].esdi_channel >> 1, temp_hdd[i].esdi_channel & 1); - break; - case HDD_BUS_IDE: - wsprintf(szText, plat_get_string(IDS_4611), temp_hdd[i].ide_channel >> 1, temp_hdd[i].ide_channel & 1); - break; - case HDD_BUS_ATAPI: - wsprintf(szText, plat_get_string(IDS_4612), temp_hdd[i].ide_channel >> 1, temp_hdd[i].ide_channel & 1); - break; - case HDD_BUS_SCSI: - wsprintf(szText, plat_get_string(IDS_4613), temp_hdd[i].scsi_id >> 4, temp_hdd[i].scsi_id & 15); - break; - } - lvI.pszText = szText; - lvI.iItem = j; - lvI.iImage = 0; + for (uint8_t i = 0; i < HDD_NUM; i++) { + if (temp_hdd[i].bus > 0) { + hdc_id_to_listview_index[i] = j; + lvI.iSubItem = 0; - if (ListView_InsertItem(hwndList, &lvI) == -1) - return FALSE; + /* Bus */ + switch (temp_hdd[i].bus) { + case HDD_BUS_MFM: + wsprintf(szText, plat_get_string(IDS_4608), temp_hdd[i].mfm_channel >> 1, temp_hdd[i].mfm_channel & 1); + break; + case HDD_BUS_XTA: + wsprintf(szText, plat_get_string(IDS_4609), temp_hdd[i].xta_channel >> 1, temp_hdd[i].xta_channel & 1); + break; + case HDD_BUS_ESDI: + wsprintf(szText, plat_get_string(IDS_4610), temp_hdd[i].esdi_channel >> 1, temp_hdd[i].esdi_channel & 1); + break; + case HDD_BUS_IDE: + wsprintf(szText, plat_get_string(IDS_4611), temp_hdd[i].ide_channel >> 1, temp_hdd[i].ide_channel & 1); + break; + case HDD_BUS_ATAPI: + wsprintf(szText, plat_get_string(IDS_4612), temp_hdd[i].ide_channel >> 1, temp_hdd[i].ide_channel & 1); + break; + case HDD_BUS_SCSI: + wsprintf(szText, plat_get_string(IDS_4613), temp_hdd[i].scsi_id >> 4, temp_hdd[i].scsi_id & 15); + break; + } + lvI.pszText = szText; + lvI.iItem = j; + lvI.iImage = 0; - lvI.iSubItem = 1; - if (!strnicmp(temp_hdd[i].fn, usr_path, strlen(usr_path))) - mbstoc16s(szText, temp_hdd[i].fn + strlen(usr_path), sizeof_w(szText)); - else - mbstoc16s(szText, temp_hdd[i].fn, sizeof_w(szText)); - lvI.pszText = szText; + if (ListView_InsertItem(hwndList, &lvI) == -1) + return FALSE; - if (ListView_SetItem(hwndList, &lvI) == -1) - return FALSE; + /* File */ + lvI.iSubItem = 1; + if (!strnicmp(temp_hdd[i].fn, usr_path, strlen(usr_path))) + mbstoc16s(szText, temp_hdd[i].fn + strlen(usr_path), sizeof_w(szText)); + else + mbstoc16s(szText, temp_hdd[i].fn, sizeof_w(szText)); + lvI.pszText = szText; - lvI.iSubItem = 2; - wsprintf(szText, plat_get_string(IDS_4098), temp_hdd[i].tracks); - lvI.pszText = szText; + if (ListView_SetItem(hwndList, &lvI) == -1) + return FALSE; - if (ListView_SetItem(hwndList, &lvI) == -1) - return FALSE; + /* Cylinders */ + lvI.iSubItem = 2; + wsprintf(szText, plat_get_string(IDS_4098), temp_hdd[i].tracks); + lvI.pszText = szText; - lvI.iSubItem = 3; - wsprintf(szText, plat_get_string(IDS_4098), temp_hdd[i].hpc); - lvI.pszText = szText; + if (ListView_SetItem(hwndList, &lvI) == -1) + return FALSE; - if (ListView_SetItem(hwndList, &lvI) == -1) - return FALSE; + /* Heads */ + lvI.iSubItem = 3; + wsprintf(szText, plat_get_string(IDS_4098), temp_hdd[i].hpc); + lvI.pszText = szText; - lvI.iSubItem = 4; - wsprintf(szText, plat_get_string(IDS_4098), temp_hdd[i].spt); - lvI.pszText = szText; + if (ListView_SetItem(hwndList, &lvI) == -1) + return FALSE; - if (ListView_SetItem(hwndList, &lvI) == -1) - return FALSE; + /* Sectors */ + lvI.iSubItem = 4; + wsprintf(szText, plat_get_string(IDS_4098), temp_hdd[i].spt); + lvI.pszText = szText; - lvI.iSubItem = 5; - wsprintf(szText, plat_get_string(IDS_4098), (temp_hdd[i].tracks * temp_hdd[i].hpc * temp_hdd[i].spt) >> 11); - lvI.pszText = szText; + if (ListView_SetItem(hwndList, &lvI) == -1) + return FALSE; - if (ListView_SetItem(hwndList, &lvI) == -1) - return FALSE; + /* Size (MB) */ + lvI.iSubItem = 5; + wsprintf(szText, plat_get_string(IDS_4098), (temp_hdd[i].tracks * temp_hdd[i].hpc * temp_hdd[i].spt) >> 11); + lvI.pszText = szText; - j++; - } else - hdc_id_to_listview_index[i] = -1; + if (ListView_SetItem(hwndList, &lvI) == -1) + return FALSE; + + /* Speed (RPM) */ + lvI.iSubItem = 6; + mbstoc16s(szText, hdd_preset_getname(temp_hdd[i].speed_preset), sizeof_w(szText)); + lvI.pszText = szText; + + if (ListView_SetItem(hwndList, &lvI) == -1) + return FALSE; + + j++; + } else + hdc_id_to_listview_index[i] = -1; } hd_listview_items = j; @@ -2311,82 +2725,98 @@ win_settings_hard_disks_recalc_list(HWND hdlg) return TRUE; } +#define C_COLUMNS_HARD_DISKS_BUS 104 +#define C_COLUMNS_HARD_DISKS_FILE 254 +#define C_COLUMNS_HARD_DISKS_CYLS 50 +#define C_COLUMNS_HARD_DISKS_HEADS 26 +#define C_COLUMNS_HARD_DISKS_SECT 32 +#define C_COLUMNS_HARD_DISKS_SIZE 50 +#define C_COLUMNS_HARD_DISKS_SPEED 100 static void win_settings_hard_disks_resize_columns(HWND hdlg) { /* Bus, File, Cylinders, Heads, Sectors, Size */ - int iCol, width[C_COLUMNS_HARD_DISKS] = {104, 354, 50, 26, 32, 50}; - int total = 0; + int width[C_COLUMNS_HARD_DISKS] = { + C_COLUMNS_HARD_DISKS_BUS, + C_COLUMNS_HARD_DISKS_FILE, + C_COLUMNS_HARD_DISKS_CYLS, + C_COLUMNS_HARD_DISKS_HEADS, + C_COLUMNS_HARD_DISKS_SECT, + C_COLUMNS_HARD_DISKS_SIZE, + C_COLUMNS_HARD_DISKS_SPEED + }; + int total = 0; HWND hwndList = GetDlgItem(hdlg, IDC_LIST_HARD_DISKS); RECT r; GetWindowRect(hwndList, &r); - for (iCol = 0; iCol < (C_COLUMNS_HARD_DISKS - 1); iCol++) { - width[iCol] = MulDiv(width[iCol], dpi, 96); - total += width[iCol]; - ListView_SetColumnWidth(hwndList, iCol, MulDiv(width[iCol], dpi, 96)); + for (int iCol = 0; iCol < (C_COLUMNS_HARD_DISKS - 1); iCol++) { + width[iCol] = MulDiv(width[iCol], dpi, 96); + total += width[iCol]; + ListView_SetColumnWidth(hwndList, iCol, MulDiv(width[iCol], dpi, 96)); } width[C_COLUMNS_HARD_DISKS - 1] = (r.right - r.left) - 4 - total; ListView_SetColumnWidth(hwndList, C_COLUMNS_HARD_DISKS - 1, width[C_COLUMNS_HARD_DISKS - 1]); } - static BOOL win_settings_hard_disks_init_columns(HWND hdlg) { LVCOLUMN lvc; - int iCol; - HWND hwndList = GetDlgItem(hdlg, IDC_LIST_HARD_DISKS); + HWND hwndList = GetDlgItem(hdlg, IDC_LIST_HARD_DISKS); lvc.mask = LVCF_FMT | LVCF_WIDTH | LVCF_TEXT | LVCF_SUBITEM; - for (iCol = 0; iCol < C_COLUMNS_HARD_DISKS; iCol++) { - lvc.iSubItem = iCol; - lvc.pszText = plat_get_string(IDS_2081 + iCol); + for (int iCol = 0; iCol < C_COLUMNS_HARD_DISKS; iCol++) { + lvc.iSubItem = iCol; + lvc.pszText = plat_get_string(IDS_BUS + iCol); - switch(iCol) { - case 0: /* Bus */ - lvc.cx = 104; - lvc.fmt = LVCFMT_LEFT; - break; - case 1: /* File */ - lvc.cx = 354; - lvc.fmt = LVCFMT_LEFT; - break; - case 2: /* Cylinders */ - lvc.cx = 50; - lvc.fmt = LVCFMT_RIGHT; - break; - case 3: /* Heads */ - lvc.cx = 26; - lvc.fmt = LVCFMT_RIGHT; - break; - case 4: /* Sectors */ - lvc.cx = 32; - lvc.fmt = LVCFMT_RIGHT; - break; - case 5: /* Size (MB) 8 */ - lvc.cx = 50; - lvc.fmt = LVCFMT_RIGHT; - break; - } + switch (iCol) { + case 0: /* Bus */ + lvc.cx = C_COLUMNS_HARD_DISKS_BUS; + lvc.fmt = LVCFMT_LEFT; + break; + case 1: /* File */ + lvc.cx = C_COLUMNS_HARD_DISKS_FILE; + lvc.fmt = LVCFMT_LEFT; + break; + case 2: /* Cylinders */ + lvc.cx = C_COLUMNS_HARD_DISKS_CYLS; + lvc.fmt = LVCFMT_RIGHT; + break; + case 3: /* Heads */ + lvc.cx = C_COLUMNS_HARD_DISKS_HEADS; + lvc.fmt = LVCFMT_RIGHT; + break; + case 4: /* Sectors */ + lvc.cx = C_COLUMNS_HARD_DISKS_SECT; + lvc.fmt = LVCFMT_RIGHT; + break; + case 5: /* Size (MB) */ + lvc.cx = C_COLUMNS_HARD_DISKS_SIZE; + lvc.fmt = LVCFMT_RIGHT; + break; + case 6: /* Speed (RPM) */ + lvc.cx = C_COLUMNS_HARD_DISKS_SPEED; + lvc.fmt = LVCFMT_RIGHT; + break; + } - if (ListView_InsertColumn(hwndList, iCol, &lvc) == -1) - return FALSE; + if (ListView_InsertColumn(hwndList, iCol, &lvc) == -1) + return FALSE; } win_settings_hard_disks_resize_columns(hdlg); return TRUE; } - static void get_edit_box_contents(HWND hdlg, int id, uint32_t *val) { - HWND h; + HWND h; WCHAR szText[256]; - char stransi[256]; + char stransi[256]; h = GetDlgItem(hdlg, id); SendMessage(h, WM_GETTEXT, 255, (LPARAM) szText); @@ -2394,47 +2824,47 @@ get_edit_box_contents(HWND hdlg, int id, uint32_t *val) sscanf(stransi, "%u", val); } - static void set_edit_box_contents(HWND hdlg, int id, uint32_t val) { - HWND h; + HWND h; WCHAR szText[256]; h = GetDlgItem(hdlg, id); - wsprintf(szText, plat_get_string(IDS_2106), val); - SendMessage(h, WM_SETTEXT, (WPARAM) wcslen(szText), (LPARAM) szText); + wsprintf(szText, plat_get_string(IDS_2107), val); + SendMessage(h, WM_SETTEXT, wcslen(szText), (LPARAM) szText); } -static void set_edit_box_text_contents(HWND hdlg, int id, WCHAR* text) +static void +set_edit_box_text_contents(HWND hdlg, int id, WCHAR *text) { - HWND h = GetDlgItem(hdlg, id); - SendMessage(h, WM_SETTEXT, (WPARAM) wcslen(text), (LPARAM) text); + HWND h = GetDlgItem(hdlg, id); + SendMessage(h, WM_SETTEXT, wcslen(text), (LPARAM) text); } -static void get_edit_box_text_contents(HWND hdlg, int id, WCHAR* text_buffer, int buffer_size) +static void +get_edit_box_text_contents(HWND hdlg, int id, WCHAR *text_buffer, int buffer_size) { - HWND h = GetDlgItem(hdlg, id); - SendMessage(h, WM_GETTEXT, (WPARAM) buffer_size, (LPARAM) text_buffer); + HWND h = GetDlgItem(hdlg, id); + SendMessage(h, WM_GETTEXT, (WPARAM) buffer_size, (LPARAM) text_buffer); } -static int hdconf_initialize_hdt_combo(HWND hdlg) +static int +hdconf_initialize_hdt_combo(HWND hdlg) { - int i = 0; uint64_t temp_size = 0; - uint32_t size_mb = 0; - WCHAR szText[256]; + uint32_t size_mb = 0; + WCHAR szText[256]; selection = 127; - for (i = 0; i < 127; i++) { - temp_size = ((uint64_t) hdd_table[i][0]) * hdd_table[i][1] * hdd_table[i][2]; - size_mb = (uint32_t) (temp_size >> 11LL); - wsprintf(szText, plat_get_string(IDS_2107), size_mb, hdd_table[i][0], hdd_table[i][1], hdd_table[i][2]); - settings_add_string(hdlg, IDC_COMBO_HD_TYPE, (LPARAM) szText); - if ((tracks == (int) hdd_table[i][0]) && (hpc == (int) hdd_table[i][1]) && - (spt == (int) hdd_table[i][2])) - selection = i; + for (uint8_t i = 0; i < 127; i++) { + temp_size = ((uint64_t) hdd_table[i][0]) * hdd_table[i][1] * hdd_table[i][2]; + size_mb = (uint32_t) (temp_size >> 11LL); + wsprintf(szText, plat_get_string(IDS_2108), size_mb, hdd_table[i][0], hdd_table[i][1], hdd_table[i][2]); + settings_add_string(hdlg, IDC_COMBO_HD_TYPE, (LPARAM) szText); + if ((tracks == (int) hdd_table[i][0]) && (hpc == (int) hdd_table[i][1]) && (spt == (int) hdd_table[i][2])) + selection = i; } settings_add_string(hdlg, IDC_COMBO_HD_TYPE, win_get_string(IDS_4100)); settings_add_string(hdlg, IDC_COMBO_HD_TYPE, win_get_string(IDS_4101)); @@ -2442,35 +2872,31 @@ static int hdconf_initialize_hdt_combo(HWND hdlg) return selection; } - static void recalc_selection(HWND hdlg) { - int i = 0; - selection = 127; - for (i = 0; i < 127; i++) { - if ((tracks == (int) hdd_table[i][0]) && - (hpc == (int) hdd_table[i][1]) && - (spt == (int) hdd_table[i][2])) - selection = i; + for (uint8_t i = 0; i < 127; i++) { + if ((tracks == (int) hdd_table[i][0]) && (hpc == (int) hdd_table[i][1]) && (spt == (int) hdd_table[i][2])) + selection = i; } if ((selection == 127) && (hpc == 16) && (spt == 63)) - selection = 128; + selection = 128; settings_set_cur_sel(hdlg, IDC_COMBO_HD_TYPE, selection); } HWND vhd_progress_hdlg; -static void vhd_progress_callback(uint32_t current_sector, uint32_t total_sectors) +static void +vhd_progress_callback(uint32_t current_sector, UNUSED(uint32_t total_sectors)) { - MSG msg; - HWND h = GetDlgItem(vhd_progress_hdlg, IDC_PBAR_IMG_CREATE); - SendMessage(h, PBM_SETPOS, (WPARAM) current_sector, (LPARAM) 0); - while (PeekMessage(&msg, 0, 0, 0, PM_REMOVE | PM_NOYIELD)) { - TranslateMessage(&msg); - DispatchMessage(&msg); - } + MSG msg; + HWND h = GetDlgItem(vhd_progress_hdlg, IDC_PBAR_IMG_CREATE); + SendMessage(h, PBM_SETPOS, current_sector, (LPARAM) 0); + while (PeekMessage(&msg, 0, 0, 0, PM_REMOVE | PM_NOYIELD)) { + TranslateMessage(&msg); + DispatchMessage(&msg); + } } /* If the disk geometry requested in the 86Box GUI is not compatible with the internal VHD geometry, @@ -2478,927 +2904,927 @@ static void vhd_progress_callback(uint32_t current_sector, uint32_t total_sector * of about 21 MB, and should only be necessary for VHDs larger than 31.5 GB, so should never be more * than a tenth of a percent change in size. */ -static void adjust_86box_geometry_for_vhd(MVHDGeom *_86box_geometry, MVHDGeom *vhd_geometry) +static void +adjust_86box_geometry_for_vhd(MVHDGeom *_86box_geometry, MVHDGeom *vhd_geometry) { - if (_86box_geometry->cyl <= 65535) { - vhd_geometry->cyl = _86box_geometry->cyl; - vhd_geometry->heads = _86box_geometry->heads; - vhd_geometry->spt = _86box_geometry->spt; - return; - } + if (_86box_geometry->cyl <= 65535) { + vhd_geometry->cyl = _86box_geometry->cyl; + vhd_geometry->heads = _86box_geometry->heads; + vhd_geometry->spt = _86box_geometry->spt; + return; + } - int desired_sectors = _86box_geometry->cyl * _86box_geometry->heads * _86box_geometry->spt; - if (desired_sectors > 267321600) - desired_sectors = 267321600; + int desired_sectors = _86box_geometry->cyl * _86box_geometry->heads * _86box_geometry->spt; + if (desired_sectors > 267321600) + desired_sectors = 267321600; - int remainder = desired_sectors % 85680; /* 8560 is the LCM of 1008 (63*16) and 4080 (255*16) */ - if (remainder > 0) - desired_sectors += (85680 - remainder); + int remainder = desired_sectors % 85680; /* 8560 is the LCM of 1008 (63*16) and 4080 (255*16) */ + if (remainder > 0) + desired_sectors += (85680 - remainder); - _86box_geometry->cyl = desired_sectors / (16 * 63); - _86box_geometry->heads = 16; - _86box_geometry->spt = 63; + _86box_geometry->cyl = desired_sectors / (16 * 63); + _86box_geometry->heads = 16; + _86box_geometry->spt = 63; - vhd_geometry->cyl = desired_sectors / (16 * 255); - vhd_geometry->heads = 16; - vhd_geometry->spt = 255; + vhd_geometry->cyl = desired_sectors / (16 * 255); + vhd_geometry->heads = 16; + vhd_geometry->spt = 255; } -static void adjust_vhd_geometry_for_86box(MVHDGeom *vhd_geometry) +static void +adjust_vhd_geometry_for_86box(MVHDGeom *vhd_geometry) { - if (vhd_geometry->spt <= 63) - return; + if (vhd_geometry->spt <= 63) + return; - int desired_sectors = vhd_geometry->cyl * vhd_geometry->heads * vhd_geometry->spt; - if (desired_sectors > 267321600) - desired_sectors = 267321600; + int desired_sectors = vhd_geometry->cyl * vhd_geometry->heads * vhd_geometry->spt; + if (desired_sectors > 267321600) + desired_sectors = 267321600; - int remainder = desired_sectors % 85680; /* 8560 is the LCM of 1008 (63*16) and 4080 (255*16) */ - if (remainder > 0) - desired_sectors -= remainder; + int remainder = desired_sectors % 85680; /* 8560 is the LCM of 1008 (63*16) and 4080 (255*16) */ + if (remainder > 0) + desired_sectors -= remainder; - vhd_geometry->cyl = desired_sectors / (16 * 63); - vhd_geometry->heads = 16; - vhd_geometry->spt = 63; + vhd_geometry->cyl = desired_sectors / (16 * 63); + vhd_geometry->heads = 16; + vhd_geometry->spt = 63; } -static MVHDGeom create_drive_vhd_fixed(char* filename, int cyl, int heads, int spt) +static MVHDGeom +create_drive_vhd_fixed(char *filename, int cyl, int heads, int spt) { - MVHDGeom _86box_geometry = { .cyl = cyl, .heads = heads, .spt = spt }; - MVHDGeom vhd_geometry; - adjust_86box_geometry_for_vhd(&_86box_geometry, &vhd_geometry); + MVHDGeom _86box_geometry = { .cyl = cyl, .heads = heads, .spt = spt }; + MVHDGeom vhd_geometry; + adjust_86box_geometry_for_vhd(&_86box_geometry, &vhd_geometry); - HWND h = GetDlgItem(vhd_progress_hdlg, IDC_PBAR_IMG_CREATE); - settings_show_window(vhd_progress_hdlg, IDT_FILE_NAME, FALSE); - settings_show_window(vhd_progress_hdlg, IDC_EDIT_HD_FILE_NAME, FALSE); - settings_show_window(vhd_progress_hdlg, IDC_CFILE, FALSE); - settings_show_window(vhd_progress_hdlg, IDC_PBAR_IMG_CREATE, TRUE); - settings_enable_window(vhd_progress_hdlg, IDT_PROGRESS, TRUE); - SendMessage(h, PBM_SETRANGE32, (WPARAM) 0, (LPARAM) vhd_geometry.cyl * vhd_geometry.heads * vhd_geometry.spt); - SendMessage(h, PBM_SETPOS, (WPARAM) 0, (LPARAM) 0); + HWND h = GetDlgItem(vhd_progress_hdlg, IDC_PBAR_IMG_CREATE); + settings_show_window(vhd_progress_hdlg, IDT_FILE_NAME, FALSE); + settings_show_window(vhd_progress_hdlg, IDC_EDIT_HD_FILE_NAME, FALSE); + settings_show_window(vhd_progress_hdlg, IDC_CFILE, FALSE); + settings_show_window(vhd_progress_hdlg, IDC_PBAR_IMG_CREATE, TRUE); + settings_enable_window(vhd_progress_hdlg, IDT_PROGRESS, TRUE); + SendMessage(h, PBM_SETRANGE32, (WPARAM) 0, (LPARAM) vhd_geometry.cyl * vhd_geometry.heads * vhd_geometry.spt); + SendMessage(h, PBM_SETPOS, (WPARAM) 0, (LPARAM) 0); - int vhd_error = 0; - MVHDMeta *vhd = mvhd_create_fixed(filename, vhd_geometry, &vhd_error, vhd_progress_callback); - if (vhd == NULL) { - _86box_geometry.cyl = 0; - _86box_geometry.heads = 0; - _86box_geometry.spt = 0; - } else { - mvhd_close(vhd); - } + int vhd_error = 0; + MVHDMeta *vhd = mvhd_create_fixed(filename, vhd_geometry, &vhd_error, vhd_progress_callback); + if (vhd == NULL) { + _86box_geometry.cyl = 0; + _86box_geometry.heads = 0; + _86box_geometry.spt = 0; + } else { + mvhd_close(vhd); + } - return _86box_geometry; + return _86box_geometry; } -static MVHDGeom create_drive_vhd_dynamic(char* filename, int cyl, int heads, int spt, int blocksize) +static MVHDGeom +create_drive_vhd_dynamic(char *filename, int cyl, int heads, int spt, int blocksize) { - MVHDGeom _86box_geometry = { .cyl = cyl, .heads = heads, .spt = spt }; - MVHDGeom vhd_geometry; - adjust_86box_geometry_for_vhd(&_86box_geometry, &vhd_geometry); - int vhd_error = 0; - MVHDCreationOptions options; - options.block_size_in_sectors = blocksize; - options.path = filename; - options.size_in_bytes = 0; - options.geometry = vhd_geometry; - options.type = MVHD_TYPE_DYNAMIC; + MVHDGeom _86box_geometry = { .cyl = cyl, .heads = heads, .spt = spt }; + MVHDGeom vhd_geometry; + adjust_86box_geometry_for_vhd(&_86box_geometry, &vhd_geometry); + int vhd_error = 0; + MVHDCreationOptions options; + options.block_size_in_sectors = blocksize; + options.path = filename; + options.size_in_bytes = 0; + options.geometry = vhd_geometry; + options.type = MVHD_TYPE_DYNAMIC; - MVHDMeta *vhd = mvhd_create_ex(options, &vhd_error); - if (vhd == NULL) { - _86box_geometry.cyl = 0; - _86box_geometry.heads = 0; - _86box_geometry.spt = 0; - } else { - mvhd_close(vhd); - } + MVHDMeta *vhd = mvhd_create_ex(options, &vhd_error); + if (vhd == NULL) { + _86box_geometry.cyl = 0; + _86box_geometry.heads = 0; + _86box_geometry.spt = 0; + } else { + mvhd_close(vhd); + } - return _86box_geometry; + return _86box_geometry; } -static MVHDGeom create_drive_vhd_diff(char* filename, char* parent_filename, int blocksize) +static MVHDGeom +create_drive_vhd_diff(char *filename, char *parent_filename, int blocksize) { - int vhd_error = 0; - MVHDCreationOptions options; - options.block_size_in_sectors = blocksize; - options.path = filename; - options.parent_path = parent_filename; - options.type = MVHD_TYPE_DIFF; + int vhd_error = 0; + MVHDCreationOptions options; + options.block_size_in_sectors = blocksize; + options.path = filename; + options.parent_path = parent_filename; + options.type = MVHD_TYPE_DIFF; - MVHDMeta *vhd = mvhd_create_ex(options, &vhd_error); - MVHDGeom vhd_geometry; - if (vhd == NULL) { - vhd_geometry.cyl = 0; - vhd_geometry.heads = 0; - vhd_geometry.spt = 0; - } else { - vhd_geometry = mvhd_get_geometry(vhd); + MVHDMeta *vhd = mvhd_create_ex(options, &vhd_error); + MVHDGeom vhd_geometry; + if (vhd == NULL) { + vhd_geometry.cyl = 0; + vhd_geometry.heads = 0; + vhd_geometry.spt = 0; + } else { + vhd_geometry = mvhd_get_geometry(vhd); - if (vhd_geometry.spt > 63) { - vhd_geometry.cyl = mvhd_calc_size_sectors(&vhd_geometry) / (16 * 63); - vhd_geometry.heads = 16; - vhd_geometry.spt = 63; - } + if (vhd_geometry.spt > 63) { + vhd_geometry.cyl = mvhd_calc_size_sectors(&vhd_geometry) / (16 * 63); + vhd_geometry.heads = 16; + vhd_geometry.spt = 63; + } - mvhd_close(vhd); - } + mvhd_close(vhd); + } - return vhd_geometry; + return vhd_geometry; } - #if defined(__amd64__) || defined(__aarch64__) static LRESULT CALLBACK #else static BOOL CALLBACK #endif -win_settings_hard_disks_add_proc(HWND hdlg, UINT message, WPARAM wParam, LPARAM lParam) +win_settings_hard_disks_add_proc(HWND hdlg, UINT message, WPARAM wParam, UNUSED(LPARAM lParam)) { - HWND h; - FILE *f; - uint32_t temp, i = 0, sector_size = 512; - uint32_t zero = 0, base = 0x1000; - uint64_t signature = 0xD778A82044445459ll; - uint64_t r = 0; - char *big_buf; - char hd_file_name_multibyte[1200]; - int b = 0; - int vhd_error = 0; - uint8_t channel = 0; - uint8_t id = 0; - wchar_t *twcs; - int img_format, block_size; - WCHAR text_buf[256]; - RECT rect; - POINT point; - int dlg_height_adjust; + HWND h; + FILE *fp; + uint32_t temp; + uint32_t i = 0; + uint32_t sector_size = 512; + uint32_t zero = 0; + uint32_t base = 0x1000; + uint64_t signature = 0xD778A82044445459LL; + uint64_t r = 0; + char *big_buf; + char hd_file_name_multibyte[1200]; + int b = 0; + int vhd_error = 0; + uint8_t channel = 0; + uint8_t id = 0; + wchar_t *twcs; + int img_format; + int block_size; + WCHAR text_buf[256]; + RECT rect; + POINT point; + int dlg_height_adjust; - switch (message) { - case WM_INITDIALOG: - memset(hd_file_name, 0, sizeof(hd_file_name)); + switch (message) { + case WM_INITDIALOG: + memset(hd_file_name, 0, sizeof(hd_file_name)); - hdd_ptr = &(temp_hdd[next_free_id]); + hdd_ptr = &(temp_hdd[next_free_id]); - SetWindowText(hdlg, plat_get_string((existing & 1) ? IDS_4103 : IDS_4102)); + SetWindowText(hdlg, plat_get_string((existing & 1) ? IDS_4103 : IDS_4102)); - no_update = 1; - spt = (existing & 1) ? 0 : 17; - set_edit_box_contents(hdlg, IDC_EDIT_HD_SPT, spt); - hpc = (existing & 1) ? 0 : 15; - set_edit_box_contents(hdlg, IDC_EDIT_HD_HPC, hpc); - tracks = (existing & 1) ? 0 : 1023; - set_edit_box_contents(hdlg, IDC_EDIT_HD_CYL, tracks); - size = (tracks * hpc * spt) << 9; - set_edit_box_contents(hdlg, IDC_EDIT_HD_SIZE, (uint32_t) (size >> 20LL)); - hdconf_initialize_hdt_combo(hdlg); + no_update = 1; + spt = (existing & 1) ? 0 : 17; + set_edit_box_contents(hdlg, IDC_EDIT_HD_SPT, spt); + hpc = (existing & 1) ? 0 : 15; + set_edit_box_contents(hdlg, IDC_EDIT_HD_HPC, hpc); + tracks = (existing & 1) ? 0 : 1023; + set_edit_box_contents(hdlg, IDC_EDIT_HD_CYL, tracks); + size = (tracks * hpc * spt) << 9; + set_edit_box_contents(hdlg, IDC_EDIT_HD_SIZE, (uint32_t) (size >> 20LL)); + hdconf_initialize_hdt_combo(hdlg); - settings_add_string(hdlg, IDC_COMBO_HD_IMG_FORMAT, win_get_string(IDS_4122)); - settings_add_string(hdlg, IDC_COMBO_HD_IMG_FORMAT, win_get_string(IDS_4123)); - settings_add_string(hdlg, IDC_COMBO_HD_IMG_FORMAT, win_get_string(IDS_4124)); - settings_add_string(hdlg, IDC_COMBO_HD_IMG_FORMAT, win_get_string(IDS_4125)); - settings_add_string(hdlg, IDC_COMBO_HD_IMG_FORMAT, win_get_string(IDS_4126)); - settings_add_string(hdlg, IDC_COMBO_HD_IMG_FORMAT, win_get_string(IDS_4127)); - settings_set_cur_sel(hdlg, IDC_COMBO_HD_IMG_FORMAT, 0); + settings_add_string(hdlg, IDC_COMBO_HD_IMG_FORMAT, win_get_string(IDS_4122)); + settings_add_string(hdlg, IDC_COMBO_HD_IMG_FORMAT, win_get_string(IDS_4123)); + settings_add_string(hdlg, IDC_COMBO_HD_IMG_FORMAT, win_get_string(IDS_4124)); + settings_add_string(hdlg, IDC_COMBO_HD_IMG_FORMAT, win_get_string(IDS_4125)); + settings_add_string(hdlg, IDC_COMBO_HD_IMG_FORMAT, win_get_string(IDS_4126)); + settings_add_string(hdlg, IDC_COMBO_HD_IMG_FORMAT, win_get_string(IDS_4127)); + settings_set_cur_sel(hdlg, IDC_COMBO_HD_IMG_FORMAT, 0); - settings_add_string(hdlg, IDC_COMBO_HD_BLOCK_SIZE, win_get_string(IDS_4128)); - settings_add_string(hdlg, IDC_COMBO_HD_BLOCK_SIZE, win_get_string(IDS_4129)); - settings_set_cur_sel(hdlg, IDC_COMBO_HD_BLOCK_SIZE, 0); + settings_add_string(hdlg, IDC_COMBO_HD_BLOCK_SIZE, win_get_string(IDS_4128)); + settings_add_string(hdlg, IDC_COMBO_HD_BLOCK_SIZE, win_get_string(IDS_4129)); + settings_set_cur_sel(hdlg, IDC_COMBO_HD_BLOCK_SIZE, 0); - settings_show_window(hdlg, IDC_COMBO_HD_BLOCK_SIZE, FALSE); - settings_show_window(hdlg, IDT_BLOCK_SIZE, FALSE); + settings_show_window(hdlg, IDC_COMBO_HD_BLOCK_SIZE, FALSE); + settings_show_window(hdlg, IDT_BLOCK_SIZE, FALSE); - if (existing & 1) { - settings_enable_window(hdlg, IDC_EDIT_HD_SPT, FALSE); - settings_enable_window(hdlg, IDC_EDIT_HD_HPC, FALSE); - settings_enable_window(hdlg, IDC_EDIT_HD_CYL, FALSE); - settings_enable_window(hdlg, IDC_EDIT_HD_SIZE, FALSE); - settings_enable_window(hdlg, IDC_COMBO_HD_TYPE, FALSE); - settings_show_window(hdlg, IDC_COMBO_HD_IMG_FORMAT, FALSE); - settings_show_window(hdlg, IDT_IMG_FORMAT, FALSE); + if (existing & 1) { + settings_enable_window(hdlg, IDC_EDIT_HD_SPT, FALSE); + settings_enable_window(hdlg, IDC_EDIT_HD_HPC, FALSE); + settings_enable_window(hdlg, IDC_EDIT_HD_CYL, FALSE); + settings_enable_window(hdlg, IDC_EDIT_HD_SIZE, FALSE); + settings_enable_window(hdlg, IDC_COMBO_HD_TYPE, FALSE); + settings_show_window(hdlg, IDC_COMBO_HD_IMG_FORMAT, FALSE); + settings_show_window(hdlg, IDT_IMG_FORMAT, FALSE); - /* adjust window size */ - GetWindowRect(hdlg, &rect); - OffsetRect(&rect, -rect.left, -rect.top); - dlg_height_adjust = rect.bottom / 5; - SetWindowPos(hdlg, NULL, 0, 0, rect.right, rect.bottom - dlg_height_adjust, SWP_NOMOVE | SWP_NOREPOSITION | SWP_NOZORDER); - h = GetDlgItem(hdlg, IDOK); - GetWindowRect(h, &rect); - point.x = rect.left; - point.y = rect.top; - ScreenToClient(hdlg, &point); - SetWindowPos(h, NULL, point.x, point.y - dlg_height_adjust, 0, 0, SWP_NOSIZE | SWP_NOREPOSITION | SWP_NOZORDER); - h = GetDlgItem(hdlg, IDCANCEL); - GetWindowRect(h, &rect); - point.x = rect.left; - point.y = rect.top; - ScreenToClient(hdlg, &point); - SetWindowPos(h, NULL, point.x, point.y - dlg_height_adjust, 0, 0, SWP_NOSIZE | SWP_NOREPOSITION | SWP_NOZORDER); + /* adjust window size */ + GetWindowRect(hdlg, &rect); + OffsetRect(&rect, -rect.left, -rect.top); + dlg_height_adjust = rect.bottom / 5; + SetWindowPos(hdlg, NULL, 0, 0, rect.right, rect.bottom - dlg_height_adjust, SWP_NOMOVE | SWP_NOREPOSITION | SWP_NOZORDER); + h = GetDlgItem(hdlg, IDOK); + GetWindowRect(h, &rect); + point.x = rect.left; + point.y = rect.top; + ScreenToClient(hdlg, &point); + SetWindowPos(h, NULL, point.x, point.y - dlg_height_adjust, 0, 0, SWP_NOSIZE | SWP_NOREPOSITION | SWP_NOZORDER); + h = GetDlgItem(hdlg, IDCANCEL); + GetWindowRect(h, &rect); + point.x = rect.left; + point.y = rect.top; + ScreenToClient(hdlg, &point); + SetWindowPos(h, NULL, point.x, point.y - dlg_height_adjust, 0, 0, SWP_NOSIZE | SWP_NOREPOSITION | SWP_NOZORDER); - chs_enabled = 0; - } else - chs_enabled = 1; + chs_enabled = 0; + } else + chs_enabled = 1; - add_locations(hdlg); - hdd_ptr->bus = HDD_BUS_IDE; - max_spt = 63; - max_hpc = 255; - settings_set_cur_sel(hdlg, IDC_COMBO_HD_BUS, hdd_ptr->bus - 1); - max_tracks = 266305; - recalc_location_controls(hdlg, 1, 0); + add_locations(hdlg); + hdd_ptr->bus = HDD_BUS_IDE; + max_spt = 255; + max_hpc = 255; + settings_set_cur_sel(hdlg, IDC_COMBO_HD_BUS, hdd_ptr->bus - 1); + max_tracks = 266305; + recalc_location_controls(hdlg, 1, 0); - channel = next_free_ide_channel(); - next_free_scsi_id(&id); - settings_set_cur_sel(hdlg, IDC_COMBO_HD_CHANNEL, 0); - settings_set_cur_sel(hdlg, IDC_COMBO_HD_ID, id); - settings_set_cur_sel(hdlg, IDC_COMBO_HD_CHANNEL_IDE, channel); + channel = next_free_ide_channel(); + next_free_scsi_id(&id); + settings_set_cur_sel(hdlg, IDC_COMBO_HD_CHANNEL, 0); + settings_set_cur_sel(hdlg, IDC_COMBO_HD_ID, id); + settings_set_cur_sel(hdlg, IDC_COMBO_HD_CHANNEL_IDE, channel); - new_hdd.mfm_channel = next_free_binary_channel(&mfm_tracking); - new_hdd.esdi_channel = next_free_binary_channel(&esdi_tracking); - new_hdd.xta_channel = next_free_binary_channel(&xta_tracking); - new_hdd.ide_channel = channel; - new_hdd.scsi_id = id; + new_hdd.mfm_channel = next_free_binary_channel(&mfm_tracking); + new_hdd.esdi_channel = next_free_binary_channel(&esdi_tracking); + new_hdd.xta_channel = next_free_binary_channel(&xta_tracking); + new_hdd.ide_channel = channel; + new_hdd.scsi_id = id; - settings_enable_window(hdlg, IDC_EDIT_HD_FILE_NAME, FALSE); - settings_show_window(hdlg, IDT_PROGRESS, FALSE); - settings_show_window(hdlg, IDC_PBAR_IMG_CREATE, FALSE); + settings_enable_window(hdlg, IDC_EDIT_HD_FILE_NAME, FALSE); + settings_show_window(hdlg, IDT_PROGRESS, FALSE); + settings_show_window(hdlg, IDC_PBAR_IMG_CREATE, FALSE); - no_update = 0; - return TRUE; + no_update = 0; + return TRUE; - case WM_COMMAND: - switch (LOWORD(wParam)) { - case IDOK: - hdd_ptr->bus = settings_get_cur_sel(hdlg, IDC_COMBO_HD_BUS) + 1; + case WM_COMMAND: + switch (LOWORD(wParam)) { + case IDOK: + hdd_ptr->bus = settings_get_cur_sel(hdlg, IDC_COMBO_HD_BUS) + 1; - /* Make sure no file name is allowed with removable SCSI hard disks. */ - if (wcslen(hd_file_name) == 0) { - hdd_ptr->bus = HDD_BUS_DISABLED; - settings_msgbox_header(MBX_ERROR, (wchar_t *) IDS_2130, (wchar_t *) IDS_4112); - return TRUE; - } + /* Make sure no file name is allowed with removable SCSI hard disks. */ + if (wcslen(hd_file_name) == 0) { + hdd_ptr->bus = HDD_BUS_DISABLED; + settings_msgbox_header(MBX_ERROR, (wchar_t *) IDS_2131, (wchar_t *) IDS_4112); + return TRUE; + } - get_edit_box_contents(hdlg, IDC_EDIT_HD_SPT, &(hdd_ptr->spt)); - get_edit_box_contents(hdlg, IDC_EDIT_HD_HPC, &(hdd_ptr->hpc)); - get_edit_box_contents(hdlg, IDC_EDIT_HD_CYL, &(hdd_ptr->tracks)); - spt = hdd_ptr->spt; - hpc = hdd_ptr->hpc; - tracks = hdd_ptr->tracks; + get_edit_box_contents(hdlg, IDC_EDIT_HD_SPT, &(hdd_ptr->spt)); + get_edit_box_contents(hdlg, IDC_EDIT_HD_HPC, &(hdd_ptr->hpc)); + get_edit_box_contents(hdlg, IDC_EDIT_HD_CYL, &(hdd_ptr->tracks)); + spt = hdd_ptr->spt; + hpc = hdd_ptr->hpc; + tracks = hdd_ptr->tracks; - switch(hdd_ptr->bus) { - case HDD_BUS_MFM: - hdd_ptr->mfm_channel = settings_get_cur_sel(hdlg, IDC_COMBO_HD_CHANNEL); - break; - case HDD_BUS_ESDI: - hdd_ptr->esdi_channel = settings_get_cur_sel(hdlg, IDC_COMBO_HD_CHANNEL); - break; - case HDD_BUS_XTA: - hdd_ptr->xta_channel = settings_get_cur_sel(hdlg, IDC_COMBO_HD_CHANNEL); - break; - case HDD_BUS_IDE: - case HDD_BUS_ATAPI: - hdd_ptr->ide_channel = settings_get_cur_sel(hdlg, IDC_COMBO_HD_CHANNEL_IDE); - break; - case HDD_BUS_SCSI: - hdd_ptr->scsi_id = settings_get_cur_sel(hdlg, IDC_COMBO_HD_ID); - break; - } + switch (hdd_ptr->bus) { + case HDD_BUS_MFM: + hdd_ptr->mfm_channel = settings_get_cur_sel(hdlg, IDC_COMBO_HD_CHANNEL); + break; + case HDD_BUS_ESDI: + hdd_ptr->esdi_channel = settings_get_cur_sel(hdlg, IDC_COMBO_HD_CHANNEL); + break; + case HDD_BUS_XTA: + hdd_ptr->xta_channel = settings_get_cur_sel(hdlg, IDC_COMBO_HD_CHANNEL); + break; + case HDD_BUS_IDE: + case HDD_BUS_ATAPI: + hdd_ptr->ide_channel = settings_get_cur_sel(hdlg, IDC_COMBO_HD_CHANNEL_IDE); + break; + case HDD_BUS_SCSI: + hdd_ptr->scsi_id = settings_get_cur_sel(hdlg, IDC_COMBO_HD_ID); + break; + } - memset(hdd_ptr->fn, 0, sizeof(hdd_ptr->fn)); - c16stombs(hdd_ptr->fn, hd_file_name, sizeof(hdd_ptr->fn)); - strcpy(hd_file_name_multibyte, hdd_ptr->fn); + memset(hdd_ptr->fn, 0, sizeof(hdd_ptr->fn)); + c16stombs(hdd_ptr->fn, hd_file_name, sizeof(hdd_ptr->fn)); + strcpy(hd_file_name_multibyte, hdd_ptr->fn); - sector_size = 512; + sector_size = 512; - if (!(existing & 1) && (wcslen(hd_file_name) > 0)) { - if (size > 0x1FFFFFFE00ll) { - settings_msgbox_header(MBX_ERROR, (wchar_t *) IDS_4116, (wchar_t *) IDS_4105); - return TRUE; - } + if (!(existing & 1) && (wcslen(hd_file_name) > 0)) { + if (size > 0x1FFFFFFE00LL) { + settings_msgbox_header(MBX_ERROR, (wchar_t *) IDS_4116, (wchar_t *) IDS_4105); + return TRUE; + } - img_format = settings_get_cur_sel(hdlg, IDC_COMBO_HD_IMG_FORMAT); - if (img_format < 3) { - f = _wfopen(hd_file_name, L"wb"); - } else { - f = (FILE *) 0; - } + img_format = settings_get_cur_sel(hdlg, IDC_COMBO_HD_IMG_FORMAT); + if (img_format < IMG_FMT_VHD_FIXED) { + fp = _wfopen(hd_file_name, L"wb"); + } else { + fp = (FILE *) 0; + } - if (img_format == 1) { /* HDI file */ - if (size >= 0x100000000ll) { - fclose(f); - settings_msgbox_header(MBX_ERROR, (wchar_t *) IDS_4116, (wchar_t *) IDS_4104); - return TRUE; - } + if (img_format == IMG_FMT_HDI) { /* HDI file */ + if (size >= 0x100000000LL) { + fclose(fp); + settings_msgbox_header(MBX_ERROR, (wchar_t *) IDS_4116, (wchar_t *) IDS_4104); + return TRUE; + } - fwrite(&zero, 1, 4, f); /* 00000000: Zero/unknown */ - fwrite(&zero, 1, 4, f); /* 00000004: Zero/unknown */ - fwrite(&base, 1, 4, f); /* 00000008: Offset at which data starts */ - fwrite(&size, 1, 4, f); /* 0000000C: Full size of the data (32-bit) */ - fwrite(§or_size, 1, 4, f); /* 00000010: Sector size in bytes */ - fwrite(&spt, 1, 4, f); /* 00000014: Sectors per cylinder */ - fwrite(&hpc, 1, 4, f); /* 00000018: Heads per cylinder */ - fwrite(&tracks, 1, 4, f); /* 0000001C: Cylinders */ + fwrite(&zero, 1, 4, fp); /* 00000000: Zero/unknown */ + fwrite(&zero, 1, 4, fp); /* 00000004: Zero/unknown */ + fwrite(&base, 1, 4, fp); /* 00000008: Offset at which data starts */ + fwrite(&size, 1, 4, fp); /* 0000000C: Full size of the data (32-bit) */ + fwrite(§or_size, 1, 4, fp); /* 00000010: Sector size in bytes */ + fwrite(&spt, 1, 4, fp); /* 00000014: Sectors per cylinder */ + fwrite(&hpc, 1, 4, fp); /* 00000018: Heads per cylinder */ + fwrite(&tracks, 1, 4, fp); /* 0000001C: Cylinders */ - for (i = 0; i < 0x3f8; i++) - fwrite(&zero, 1, 4, f); - } else if (img_format == 2) { /* HDX file */ - fwrite(&signature, 1, 8, f); /* 00000000: Signature */ - fwrite(&size, 1, 8, f); /* 00000008: Full size of the data (64-bit) */ - fwrite(§or_size, 1, 4, f); /* 00000010: Sector size in bytes */ - fwrite(&spt, 1, 4, f); /* 00000014: Sectors per cylinder */ - fwrite(&hpc, 1, 4, f); /* 00000018: Heads per cylinder */ - fwrite(&tracks, 1, 4, f); /* 0000001C: Cylinders */ - fwrite(&zero, 1, 4, f); /* 00000020: [Translation] Sectors per cylinder */ - fwrite(&zero, 1, 4, f); /* 00000004: [Translation] Heads per cylinder */ - } else if (img_format >= 3) { /* VHD file */ - MVHDGeom _86box_geometry; - block_size = settings_get_cur_sel(hdlg, IDC_COMBO_HD_BLOCK_SIZE) == 0 ? MVHD_BLOCK_LARGE : MVHD_BLOCK_SMALL; - switch (img_format) { - case 3: - vhd_progress_hdlg = hdlg; - _86box_geometry = create_drive_vhd_fixed(hd_file_name_multibyte, tracks, hpc, spt); - break; - case 4: - _86box_geometry = create_drive_vhd_dynamic(hd_file_name_multibyte, tracks, hpc, spt, block_size); - break; - case 5: - if (file_dlg_w(hdlg, plat_get_string(IDS_4130), L"", plat_get_string(IDS_4131), 0)) { - return TRUE; - } - _86box_geometry = create_drive_vhd_diff(hd_file_name_multibyte, openfilestring, block_size); - break; - } + for (i = 0; i < 0x3f8; i++) + fwrite(&zero, 1, 4, fp); + } else if (img_format == IMG_FMT_HDX) { /* HDX file */ + fwrite(&signature, 1, 8, fp); /* 00000000: Signature */ + fwrite(&size, 1, 8, fp); /* 00000008: Full size of the data (64-bit) */ + fwrite(§or_size, 1, 4, fp); /* 00000010: Sector size in bytes */ + fwrite(&spt, 1, 4, fp); /* 00000014: Sectors per cylinder */ + fwrite(&hpc, 1, 4, fp); /* 00000018: Heads per cylinder */ + fwrite(&tracks, 1, 4, fp); /* 0000001C: Cylinders */ + fwrite(&zero, 1, 4, fp); /* 00000020: [Translation] Sectors per cylinder */ + fwrite(&zero, 1, 4, fp); /* 00000004: [Translation] Heads per cylinder */ + } else if (img_format >= IMG_FMT_VHD_FIXED) { /* VHD file */ + MVHDGeom _86box_geometry; + block_size = settings_get_cur_sel(hdlg, IDC_COMBO_HD_BLOCK_SIZE) == 0 ? MVHD_BLOCK_LARGE : MVHD_BLOCK_SMALL; + switch (img_format) { + case IMG_FMT_VHD_FIXED: + vhd_progress_hdlg = hdlg; + _86box_geometry = create_drive_vhd_fixed(hd_file_name_multibyte, tracks, hpc, spt); + break; + case IMG_FMT_VHD_DYNAMIC: + _86box_geometry = create_drive_vhd_dynamic(hd_file_name_multibyte, tracks, hpc, spt, block_size); + break; + case IMG_FMT_VHD_DIFF: + if (file_dlg_w(hdlg, plat_get_string(IDS_4130), L"", plat_get_string(IDS_4131), 0)) { + return TRUE; + } + _86box_geometry = create_drive_vhd_diff(hd_file_name_multibyte, openfilestring, block_size); + break; + } - if (img_format != 5) - settings_msgbox_header(MBX_INFO, (wchar_t *) IDS_4113, (wchar_t *) IDS_4117); + if (img_format != IMG_FMT_VHD_DIFF) + settings_msgbox_header(MBX_INFO, (wchar_t *) IDS_4113, (wchar_t *) IDS_4117); - hdd_ptr->tracks = _86box_geometry.cyl; - hdd_ptr->hpc = _86box_geometry.heads; - hdd_ptr->spt = _86box_geometry.spt; + hdd_ptr->tracks = _86box_geometry.cyl; + hdd_ptr->hpc = _86box_geometry.heads; + hdd_ptr->spt = _86box_geometry.spt; - hard_disk_added = 1; - EndDialog(hdlg, 0); - return TRUE; - } + hard_disk_added = 1; + EndDialog(hdlg, 0); + return TRUE; + } - big_buf = (char *) malloc(1048576); - memset(big_buf, 0, 1048576); + big_buf = (char *) malloc(1048576); + memset(big_buf, 0, 1048576); - r = size >> 20; - size &= 0xfffff; + r = size >> 20; + size &= 0xfffff; - if (size || r) { - settings_show_window(hdlg, IDT_FILE_NAME, FALSE); - settings_show_window(hdlg, IDC_EDIT_HD_FILE_NAME, FALSE); - settings_show_window(hdlg, IDC_CFILE, FALSE); - settings_show_window(hdlg, IDC_PBAR_IMG_CREATE, TRUE); - settings_enable_window(hdlg, IDT_PROGRESS, TRUE); + if (size || r) { + settings_show_window(hdlg, IDT_FILE_NAME, FALSE); + settings_show_window(hdlg, IDC_EDIT_HD_FILE_NAME, FALSE); + settings_show_window(hdlg, IDC_CFILE, FALSE); + settings_show_window(hdlg, IDC_PBAR_IMG_CREATE, TRUE); + settings_enable_window(hdlg, IDT_PROGRESS, TRUE); - h = GetDlgItem(hdlg, IDC_PBAR_IMG_CREATE); - SendMessage(h, PBM_SETRANGE32, (WPARAM) 0, (LPARAM) r); - SendMessage(h, PBM_SETPOS, (WPARAM) 0, (LPARAM) 0); - } + h = GetDlgItem(hdlg, IDC_PBAR_IMG_CREATE); + SendMessage(h, PBM_SETRANGE32, (WPARAM) 0, (LPARAM) r); + SendMessage(h, PBM_SETPOS, (WPARAM) 0, (LPARAM) 0); + } - h = GetDlgItem(hdlg, IDC_PBAR_IMG_CREATE); + h = GetDlgItem(hdlg, IDC_PBAR_IMG_CREATE); - if (size) { - if (f) { - fwrite(big_buf, 1, size, f); - } - SendMessage(h, PBM_SETPOS, (WPARAM) 1, (LPARAM) 0); - } + if (size) { + if (fp) { + fwrite(big_buf, 1, size, fp); + } + SendMessage(h, PBM_SETPOS, (WPARAM) 1, (LPARAM) 0); + } - if (r) { - for (i = 0; i < r; i++) { - if (f) { - fwrite(big_buf, 1, 1048576, f); - } - SendMessage(h, PBM_SETPOS, (WPARAM) (i + 1), (LPARAM) 0); + if (r) { + for (i = 0; i < r; i++) { + if (fp) { + fwrite(big_buf, 1, 1048576, fp); + } + SendMessage(h, PBM_SETPOS, (i + 1), (LPARAM) 0); - settings_process_messages(); - } - } + settings_process_messages(); + } + } - free(big_buf); + free(big_buf); - if (f) { - fclose(f); - } - settings_msgbox_header(MBX_INFO, (wchar_t *) IDS_4113, (wchar_t *) IDS_4117); - } + if (fp) { + fclose(fp); + } + settings_msgbox_header(MBX_INFO, (wchar_t *) IDS_4113, (wchar_t *) IDS_4117); + } - hard_disk_added = 1; - EndDialog(hdlg, 0); - return TRUE; + hard_disk_added = 1; + EndDialog(hdlg, 0); + return TRUE; - case IDCANCEL: - hard_disk_added = 0; - hdd_ptr->bus = HDD_BUS_DISABLED; - EndDialog(hdlg, 0); - return TRUE; + case IDCANCEL: + hard_disk_added = 0; + hdd_ptr->bus = HDD_BUS_DISABLED; + EndDialog(hdlg, 0); + return TRUE; - case IDC_CFILE: - if (!file_dlg_w(hdlg, plat_get_string(IDS_4106), L"", NULL, !(existing & 1))) { - if (!wcschr(wopenfilestring, L'.')) { - if (wcslen(wopenfilestring) && (wcslen(wopenfilestring) <= 256)) { - twcs = &wopenfilestring[wcslen(wopenfilestring)]; - twcs[0] = L'.'; - twcs[1] = L'i'; - twcs[2] = L'm'; - twcs[3] = L'g'; - } - } + case IDC_CFILE: + if (!file_dlg_w(hdlg, plat_get_string(IDS_4106), L"", NULL, !(existing & 1))) { + if (!wcschr(wopenfilestring, L'.')) { + if (wcslen(wopenfilestring) && (wcslen(wopenfilestring) <= 256)) { + twcs = &wopenfilestring[wcslen(wopenfilestring)]; + twcs[0] = L'.'; + twcs[1] = L'i'; + twcs[2] = L'm'; + twcs[3] = L'g'; + } + } - if (!(existing & 1)) { - f = _wfopen(wopenfilestring, L"rb"); - if (f != NULL) { - fclose(f); - if (settings_msgbox_ex(MBX_QUESTION_YN, (wchar_t *) IDS_4111, (wchar_t *) IDS_4118, (wchar_t *) IDS_4120, (wchar_t *) IDS_4121, NULL) != 0) /* yes */ - return FALSE; - } - } + if (!(existing & 1)) { + fp = _wfopen(wopenfilestring, L"rb"); + if (fp != NULL) { + fclose(fp); + if (settings_msgbox_ex(MBX_QUESTION_YN, (wchar_t *) IDS_4111, (wchar_t *) IDS_4118, (wchar_t *) IDS_4120, (wchar_t *) IDS_4121, NULL) != 0) /* yes */ + return FALSE; + } + } - f = _wfopen(wopenfilestring, (existing & 1) ? L"rb" : L"wb"); - if (f == NULL) { + fp = _wfopen(wopenfilestring, (existing & 1) ? L"rb" : L"wb"); + if (fp == NULL) { hdd_add_file_open_error: - fclose(f); - settings_msgbox_header(MBX_ERROR, (existing & 1) ? (wchar_t *) IDS_4114 : (wchar_t *) IDS_4115, (existing & 1) ? (wchar_t *) IDS_4107 : (wchar_t *) IDS_4108); - return TRUE; - } - if (existing & 1) { - if (image_is_hdi(openfilestring) || image_is_hdx(openfilestring, 1)) { - fseeko64(f, 0x10, SEEK_SET); - fread(§or_size, 1, 4, f); - if (sector_size != 512) { - settings_msgbox_header(MBX_ERROR, (wchar_t *) IDS_4119, (wchar_t *) IDS_4109); - fclose(f); - return TRUE; - } - spt = hpc = tracks = 0; - fread(&spt, 1, 4, f); - fread(&hpc, 1, 4, f); - fread(&tracks, 1, 4, f); - } else if (image_is_vhd(openfilestring, 1)) { - fclose(f); - MVHDMeta* vhd = mvhd_open(openfilestring, 0, &vhd_error); - if (vhd == NULL) { - settings_msgbox_header(MBX_ERROR, (existing & 1) ? (wchar_t *) IDS_4114 : (wchar_t *) IDS_4115, (existing & 1) ? (wchar_t *) IDS_4107 : (wchar_t *) IDS_4108); - return TRUE; - } else if (vhd_error == MVHD_ERR_TIMESTAMP) { - if (settings_msgbox_ex(MBX_QUESTION_YN | MBX_WARNING, plat_get_string(IDS_4133), plat_get_string(IDS_4132), NULL, NULL, NULL) != 0) { - int ts_res = mvhd_diff_update_par_timestamp(vhd, &vhd_error); - if (ts_res != 0) { - settings_msgbox_header(MBX_ERROR, plat_get_string(IDS_2049), plat_get_string(IDS_4134)); - mvhd_close(vhd); - return TRUE; - } - } else { - mvhd_close(vhd); - return TRUE; - } - } + fclose(fp); + settings_msgbox_header(MBX_ERROR, (existing & 1) ? (wchar_t *) IDS_4114 : (wchar_t *) IDS_4115, (existing & 1) ? (wchar_t *) IDS_4107 : (wchar_t *) IDS_4108); + return TRUE; + } + if (existing & 1) { + if (image_is_hdi(openfilestring) || image_is_hdx(openfilestring, 1)) { + fseeko64(fp, 0x10, SEEK_SET); + fread(§or_size, 1, 4, fp); + if (sector_size != 512) { + settings_msgbox_header(MBX_ERROR, (wchar_t *) IDS_4119, (wchar_t *) IDS_4109); + fclose(fp); + return TRUE; + } + spt = hpc = tracks = 0; + fread(&spt, 1, 4, fp); + fread(&hpc, 1, 4, fp); + fread(&tracks, 1, 4, fp); + } else if (image_is_vhd(openfilestring, 1)) { + fclose(fp); + MVHDMeta *vhd = mvhd_open(openfilestring, 0, &vhd_error); + if (vhd == NULL) { + settings_msgbox_header(MBX_ERROR, (existing & 1) ? (wchar_t *) IDS_4114 : (wchar_t *) IDS_4115, (existing & 1) ? (wchar_t *) IDS_4107 : (wchar_t *) IDS_4108); + return TRUE; + } else if (vhd_error == MVHD_ERR_TIMESTAMP) { + if (settings_msgbox_ex(MBX_QUESTION_YN | MBX_WARNING, plat_get_string(IDS_4133), plat_get_string(IDS_4132), NULL, NULL, NULL) != 0) { + int ts_res = mvhd_diff_update_par_timestamp(vhd, &vhd_error); + if (ts_res != 0) { + settings_msgbox_header(MBX_ERROR, plat_get_string(IDS_2049), plat_get_string(IDS_4134)); + mvhd_close(vhd); + return TRUE; + } + } else { + mvhd_close(vhd); + return TRUE; + } + } - MVHDGeom vhd_geom = mvhd_get_geometry(vhd); - adjust_vhd_geometry_for_86box(&vhd_geom); - tracks = vhd_geom.cyl; - hpc = vhd_geom.heads; - spt = vhd_geom.spt; - size = (uint64_t)tracks * hpc * spt * 512; - mvhd_close(vhd); - } else { - fseeko64(f, 0, SEEK_END); - size = ftello64(f); - if (((size % 17) == 0) && (size <= 142606336)) { - spt = 17; - if (size <= 26738688) - hpc = 4; - else if (((size % 3072) == 0) && (size <= 53477376)) - hpc = 6; - else { - for (i = 5; i < 16; i++) { - if (((size % (i << 9)) == 0) && (size <= ((i * 17) << 19))) - break; - if (i == 5) - i++; - } - hpc = i; - } - } else { - spt = 63; - hpc = 16; - } + MVHDGeom vhd_geom = mvhd_get_geometry(vhd); + adjust_vhd_geometry_for_86box(&vhd_geom); + tracks = vhd_geom.cyl; + hpc = vhd_geom.heads; + spt = vhd_geom.spt; + size = (uint64_t) tracks * hpc * spt * 512; + mvhd_close(vhd); + } else { + fseeko64(fp, 0, SEEK_END); + size = ftello64(fp); + if (((size % 17) == 0) && (size <= 142606336)) { + spt = 17; + if (size <= 26738688) + hpc = 4; + else if (((size % 3072) == 0) && (size <= 53477376)) + hpc = 6; + else { + for (i = 5; i < 16; i++) { + if (((size % (i << 9)) == 0) && (size <= ((i * 17) << 19))) + break; + if (i == 5) + i++; + } + hpc = i; + } + } else { + spt = 63; + hpc = 16; + } - tracks = ((size >> 9) / hpc) / spt; - } + tracks = ((size >> 9) / hpc) / spt; + } - if ((spt > max_spt) || (hpc > max_hpc) || (tracks > max_tracks)) - goto hdd_add_file_open_error; - no_update = 1; + if ((spt > max_spt) || (hpc > max_hpc) || (tracks > max_tracks)) + goto hdd_add_file_open_error; + no_update = 1; - set_edit_box_contents(hdlg, IDC_EDIT_HD_SPT, spt); - set_edit_box_contents(hdlg, IDC_EDIT_HD_HPC, hpc); - set_edit_box_contents(hdlg, IDC_EDIT_HD_CYL, tracks); - set_edit_box_contents(hdlg, IDC_EDIT_HD_SIZE, size >> 20); - recalc_selection(hdlg); + set_edit_box_contents(hdlg, IDC_EDIT_HD_SPT, spt); + set_edit_box_contents(hdlg, IDC_EDIT_HD_HPC, hpc); + set_edit_box_contents(hdlg, IDC_EDIT_HD_CYL, tracks); + set_edit_box_contents(hdlg, IDC_EDIT_HD_SIZE, size >> 20); + recalc_selection(hdlg); - settings_enable_window(hdlg, IDC_EDIT_HD_SPT, TRUE); - settings_enable_window(hdlg, IDC_EDIT_HD_HPC, TRUE); - settings_enable_window(hdlg, IDC_EDIT_HD_CYL, TRUE); - settings_enable_window(hdlg, IDC_EDIT_HD_SIZE, TRUE); - settings_enable_window(hdlg, IDC_COMBO_HD_TYPE, TRUE); + settings_enable_window(hdlg, IDC_EDIT_HD_SPT, TRUE); + settings_enable_window(hdlg, IDC_EDIT_HD_HPC, TRUE); + settings_enable_window(hdlg, IDC_EDIT_HD_CYL, TRUE); + settings_enable_window(hdlg, IDC_EDIT_HD_SIZE, TRUE); + settings_enable_window(hdlg, IDC_COMBO_HD_TYPE, TRUE); - chs_enabled = 1; + chs_enabled = 1; - no_update = 0; - } + no_update = 0; + } - fclose(f); - } + fclose(fp); + } - h = GetDlgItem(hdlg, IDC_EDIT_HD_FILE_NAME); - SendMessage(h, WM_SETTEXT, 0, (LPARAM) wopenfilestring); - memset(hd_file_name, 0, sizeof(hd_file_name)); - wcscpy(hd_file_name, wopenfilestring); + h = GetDlgItem(hdlg, IDC_EDIT_HD_FILE_NAME); + SendMessage(h, WM_SETTEXT, 0, (LPARAM) wopenfilestring); + memset(hd_file_name, 0, sizeof(hd_file_name)); + wcscpy(hd_file_name, wopenfilestring); - return TRUE; + return TRUE; - case IDC_EDIT_HD_CYL: - if (no_update) - return FALSE; + case IDC_EDIT_HD_CYL: + if (no_update) + return FALSE; - no_update = 1; - get_edit_box_contents(hdlg, IDC_EDIT_HD_CYL, &temp); - if (tracks != (int64_t) temp) { - tracks = temp; - size = ((uint64_t) tracks * (uint64_t) hpc * (uint64_t) spt) << 9LL; - set_edit_box_contents(hdlg, IDC_EDIT_HD_SIZE, (uint32_t) (size >> 20)); - recalc_selection(hdlg); - } + no_update = 1; + get_edit_box_contents(hdlg, IDC_EDIT_HD_CYL, &temp); + if (tracks != (int64_t) temp) { + tracks = temp; + size = ((uint64_t) tracks * (uint64_t) hpc * (uint64_t) spt) << 9LL; + set_edit_box_contents(hdlg, IDC_EDIT_HD_SIZE, (uint32_t) (size >> 20)); + recalc_selection(hdlg); + } - if (tracks > max_tracks) { - tracks = max_tracks; - size = ((uint64_t) tracks * (uint64_t) hpc * (uint64_t) spt) << 9LL; - set_edit_box_contents(hdlg, IDC_EDIT_HD_CYL, (uint32_t) tracks); - set_edit_box_contents(hdlg, IDC_EDIT_HD_SIZE, (uint32_t) (size >> 20)); - recalc_selection(hdlg); - } + if (tracks > max_tracks) { + tracks = max_tracks; + size = ((uint64_t) tracks * (uint64_t) hpc * (uint64_t) spt) << 9LL; + set_edit_box_contents(hdlg, IDC_EDIT_HD_CYL, (uint32_t) tracks); + set_edit_box_contents(hdlg, IDC_EDIT_HD_SIZE, (uint32_t) (size >> 20)); + recalc_selection(hdlg); + } - no_update = 0; - break; + no_update = 0; + break; - case IDC_EDIT_HD_HPC: - if (no_update) - return FALSE; + case IDC_EDIT_HD_HPC: + if (no_update) + return FALSE; - no_update = 1; - get_edit_box_contents(hdlg, IDC_EDIT_HD_HPC, &temp); - if (hpc != (int64_t) temp) { - hpc = temp; - size = ((uint64_t) tracks * (uint64_t) hpc * (uint64_t) spt) << 9LL; - set_edit_box_contents(hdlg, IDC_EDIT_HD_SIZE, (uint32_t) (size >> 20)); - recalc_selection(hdlg); - } + no_update = 1; + get_edit_box_contents(hdlg, IDC_EDIT_HD_HPC, &temp); + if (hpc != (int64_t) temp) { + hpc = temp; + size = ((uint64_t) tracks * (uint64_t) hpc * (uint64_t) spt) << 9LL; + set_edit_box_contents(hdlg, IDC_EDIT_HD_SIZE, (uint32_t) (size >> 20)); + recalc_selection(hdlg); + } - if (hpc > max_hpc) { - hpc = max_hpc; - size = ((uint64_t) tracks * (uint64_t) hpc * (uint64_t) spt) << 9LL; - set_edit_box_contents(hdlg, IDC_EDIT_HD_HPC, (uint32_t) hpc); - set_edit_box_contents(hdlg, IDC_EDIT_HD_SIZE, (uint32_t) (size >> 20)); - recalc_selection(hdlg); - } + if (hpc > max_hpc) { + hpc = max_hpc; + size = ((uint64_t) tracks * (uint64_t) hpc * (uint64_t) spt) << 9LL; + set_edit_box_contents(hdlg, IDC_EDIT_HD_HPC, (uint32_t) hpc); + set_edit_box_contents(hdlg, IDC_EDIT_HD_SIZE, (uint32_t) (size >> 20)); + recalc_selection(hdlg); + } - no_update = 0; - break; + no_update = 0; + break; - case IDC_EDIT_HD_SPT: - if (no_update) - return FALSE; + case IDC_EDIT_HD_SPT: + if (no_update) + return FALSE; - no_update = 1; - get_edit_box_contents(hdlg, IDC_EDIT_HD_SPT, &temp); - if (spt != (int64_t) temp) { - spt = temp; - size = ((uint64_t) tracks * (uint64_t) hpc * (uint64_t) spt) << 9LL; - set_edit_box_contents(hdlg, IDC_EDIT_HD_SIZE, (uint32_t) (size >> 20)); - recalc_selection(hdlg); - } + no_update = 1; + get_edit_box_contents(hdlg, IDC_EDIT_HD_SPT, &temp); + if (spt != (int64_t) temp) { + spt = temp; + size = ((uint64_t) tracks * (uint64_t) hpc * (uint64_t) spt) << 9LL; + set_edit_box_contents(hdlg, IDC_EDIT_HD_SIZE, (uint32_t) (size >> 20)); + recalc_selection(hdlg); + } - if (spt > max_spt) { - spt = max_spt; - size = ((uint64_t) tracks * (uint64_t) hpc * (uint64_t) spt) << 9LL; - set_edit_box_contents(hdlg, IDC_EDIT_HD_SPT, spt); - set_edit_box_contents(hdlg, IDC_EDIT_HD_SIZE, (uint32_t) (size >> 20)); - recalc_selection(hdlg); - } + if (spt > max_spt) { + spt = max_spt; + size = ((uint64_t) tracks * (uint64_t) hpc * (uint64_t) spt) << 9LL; + set_edit_box_contents(hdlg, IDC_EDIT_HD_SPT, spt); + set_edit_box_contents(hdlg, IDC_EDIT_HD_SIZE, (uint32_t) (size >> 20)); + recalc_selection(hdlg); + } - no_update = 0; - break; + no_update = 0; + break; - case IDC_EDIT_HD_SIZE: - if (no_update) - return FALSE; + case IDC_EDIT_HD_SIZE: + if (no_update) + return FALSE; - no_update = 1; - get_edit_box_contents(hdlg, IDC_EDIT_HD_SIZE, &temp); - if (temp != (uint32_t) (size >> 20)) { - size = ((uint64_t) temp) << 20LL; - /* This is needed to ensure VHD standard compliance. */ - hdd_image_calc_chs((uint32_t *) &tracks, (uint32_t *) &hpc, (uint32_t *) &spt, temp); - set_edit_box_contents(hdlg, IDC_EDIT_HD_CYL, (uint32_t) tracks); - set_edit_box_contents(hdlg, IDC_EDIT_HD_HPC, (uint32_t) hpc); - set_edit_box_contents(hdlg, IDC_EDIT_HD_SPT, (uint32_t) spt); - recalc_selection(hdlg); - } + no_update = 1; + get_edit_box_contents(hdlg, IDC_EDIT_HD_SIZE, &temp); + if (temp != (uint32_t) (size >> 20)) { + size = ((uint64_t) temp) << 20LL; + /* This is needed to ensure VHD standard compliance. */ + hdd_image_calc_chs((uint32_t *) &tracks, (uint32_t *) &hpc, (uint32_t *) &spt, temp); + set_edit_box_contents(hdlg, IDC_EDIT_HD_CYL, (uint32_t) tracks); + set_edit_box_contents(hdlg, IDC_EDIT_HD_HPC, (uint32_t) hpc); + set_edit_box_contents(hdlg, IDC_EDIT_HD_SPT, (uint32_t) spt); + recalc_selection(hdlg); + } - if (tracks > max_tracks) { - tracks = max_tracks; - size = ((uint64_t) tracks * (uint64_t) hpc * (uint64_t) spt) << 9LL; - set_edit_box_contents(hdlg, IDC_EDIT_HD_CYL, (uint32_t) tracks); - set_edit_box_contents(hdlg, IDC_EDIT_HD_SIZE, (uint32_t) (size >> 20)); - recalc_selection(hdlg); - } + if (tracks > max_tracks) { + tracks = max_tracks; + size = ((uint64_t) tracks * (uint64_t) hpc * (uint64_t) spt) << 9LL; + set_edit_box_contents(hdlg, IDC_EDIT_HD_CYL, (uint32_t) tracks); + set_edit_box_contents(hdlg, IDC_EDIT_HD_SIZE, (uint32_t) (size >> 20)); + recalc_selection(hdlg); + } - if (hpc > max_hpc) { - hpc = max_hpc; - size = ((uint64_t) tracks * (uint64_t) hpc * (uint64_t) spt) << 9LL; - set_edit_box_contents(hdlg, IDC_EDIT_HD_HPC, (uint32_t) hpc); - set_edit_box_contents(hdlg, IDC_EDIT_HD_SIZE, (uint32_t) (size >> 20)); - recalc_selection(hdlg); - } + if (hpc > max_hpc) { + hpc = max_hpc; + size = ((uint64_t) tracks * (uint64_t) hpc * (uint64_t) spt) << 9LL; + set_edit_box_contents(hdlg, IDC_EDIT_HD_HPC, (uint32_t) hpc); + set_edit_box_contents(hdlg, IDC_EDIT_HD_SIZE, (uint32_t) (size >> 20)); + recalc_selection(hdlg); + } - if (spt > max_spt) { - spt = max_spt; - size = ((uint64_t) tracks * (uint64_t) hpc * (uint64_t) spt) << 9LL; - set_edit_box_contents(hdlg, IDC_EDIT_HD_SPT, (uint32_t) spt); - set_edit_box_contents(hdlg, IDC_EDIT_HD_SIZE, (uint32_t) (size >> 20)); - recalc_selection(hdlg); - } + if (spt > max_spt) { + spt = max_spt; + size = ((uint64_t) tracks * (uint64_t) hpc * (uint64_t) spt) << 9LL; + set_edit_box_contents(hdlg, IDC_EDIT_HD_SPT, (uint32_t) spt); + set_edit_box_contents(hdlg, IDC_EDIT_HD_SIZE, (uint32_t) (size >> 20)); + recalc_selection(hdlg); + } - no_update = 0; - break; + no_update = 0; + break; - case IDC_COMBO_HD_TYPE: - if (no_update) - return FALSE; + case IDC_COMBO_HD_TYPE: + if (no_update) + return FALSE; - no_update = 1; - temp = settings_get_cur_sel(hdlg, IDC_COMBO_HD_TYPE); - if ((temp != selection) && (temp != 127) && (temp != 128)) { - selection = temp; - tracks = hdd_table[selection][0]; - hpc = hdd_table[selection][1]; - spt = hdd_table[selection][2]; - size = ((uint64_t) tracks * (uint64_t) hpc * (uint64_t) spt) << 9LL; - set_edit_box_contents(hdlg, IDC_EDIT_HD_CYL, (uint32_t) tracks); - set_edit_box_contents(hdlg, IDC_EDIT_HD_HPC, (uint32_t) hpc); - set_edit_box_contents(hdlg, IDC_EDIT_HD_SPT, (uint32_t) spt); - set_edit_box_contents(hdlg, IDC_EDIT_HD_SIZE, (uint32_t) (size >> 20)); - } else if ((temp != selection) && (temp == 127)) - selection = temp; - else if ((temp != selection) && (temp == 128)) { - selection = temp; - hpc = 16; - spt = 63; - size = ((uint64_t) tracks * (uint64_t) hpc * (uint64_t) spt) << 9LL; - set_edit_box_contents(hdlg, IDC_EDIT_HD_HPC, (uint32_t) hpc); - set_edit_box_contents(hdlg, IDC_EDIT_HD_SPT, (uint32_t) spt); - set_edit_box_contents(hdlg, IDC_EDIT_HD_SIZE, (uint32_t) (size >> 20)); - } + no_update = 1; + temp = settings_get_cur_sel(hdlg, IDC_COMBO_HD_TYPE); + if ((temp != selection) && (temp != 127) && (temp != 128)) { + selection = temp; + tracks = hdd_table[selection][0]; + hpc = hdd_table[selection][1]; + spt = hdd_table[selection][2]; + size = ((uint64_t) tracks * (uint64_t) hpc * (uint64_t) spt) << 9LL; + set_edit_box_contents(hdlg, IDC_EDIT_HD_CYL, (uint32_t) tracks); + set_edit_box_contents(hdlg, IDC_EDIT_HD_HPC, (uint32_t) hpc); + set_edit_box_contents(hdlg, IDC_EDIT_HD_SPT, (uint32_t) spt); + set_edit_box_contents(hdlg, IDC_EDIT_HD_SIZE, (uint32_t) (size >> 20)); + } else if ((temp != selection) && (temp == 127)) + selection = temp; + else if ((temp != selection) && (temp == 128)) { + selection = temp; + hpc = 16; + spt = 63; + size = ((uint64_t) tracks * (uint64_t) hpc * (uint64_t) spt) << 9LL; + set_edit_box_contents(hdlg, IDC_EDIT_HD_HPC, (uint32_t) hpc); + set_edit_box_contents(hdlg, IDC_EDIT_HD_SPT, (uint32_t) spt); + set_edit_box_contents(hdlg, IDC_EDIT_HD_SIZE, (uint32_t) (size >> 20)); + } - if (spt > max_spt) { - spt = max_spt; - size = ((uint64_t) tracks * (uint64_t) hpc * (uint64_t) spt) << 9LL; - set_edit_box_contents(hdlg, IDC_EDIT_HD_SPT, (uint32_t) spt); - set_edit_box_contents(hdlg, IDC_EDIT_HD_SIZE, (uint32_t) (size >> 20)); - recalc_selection(hdlg); - } + if (spt > max_spt) { + spt = max_spt; + size = ((uint64_t) tracks * (uint64_t) hpc * (uint64_t) spt) << 9LL; + set_edit_box_contents(hdlg, IDC_EDIT_HD_SPT, (uint32_t) spt); + set_edit_box_contents(hdlg, IDC_EDIT_HD_SIZE, (uint32_t) (size >> 20)); + recalc_selection(hdlg); + } - if (hpc > max_hpc) { - hpc = max_hpc; - size = ((uint64_t) tracks * (uint64_t) hpc * (uint64_t) spt) << 9LL; - set_edit_box_contents(hdlg, IDC_EDIT_HD_HPC, (uint32_t) hpc); - set_edit_box_contents(hdlg, IDC_EDIT_HD_SIZE, (uint32_t) (size >> 20)); - recalc_selection(hdlg); - } + if (hpc > max_hpc) { + hpc = max_hpc; + size = ((uint64_t) tracks * (uint64_t) hpc * (uint64_t) spt) << 9LL; + set_edit_box_contents(hdlg, IDC_EDIT_HD_HPC, (uint32_t) hpc); + set_edit_box_contents(hdlg, IDC_EDIT_HD_SIZE, (uint32_t) (size >> 20)); + recalc_selection(hdlg); + } - if (tracks > max_tracks) { - tracks = max_tracks; - size = ((uint64_t) tracks * (uint64_t) hpc * (uint64_t) spt) << 9LL; - set_edit_box_contents(hdlg, IDC_EDIT_HD_CYL, (uint32_t) tracks); - set_edit_box_contents(hdlg, IDC_EDIT_HD_SIZE, (uint32_t) (size >> 20)); - recalc_selection(hdlg); - } + if (tracks > max_tracks) { + tracks = max_tracks; + size = ((uint64_t) tracks * (uint64_t) hpc * (uint64_t) spt) << 9LL; + set_edit_box_contents(hdlg, IDC_EDIT_HD_CYL, (uint32_t) tracks); + set_edit_box_contents(hdlg, IDC_EDIT_HD_SIZE, (uint32_t) (size >> 20)); + recalc_selection(hdlg); + } - no_update = 0; - break; + no_update = 0; + break; - case IDC_COMBO_HD_BUS: - if (no_update) - return FALSE; + case IDC_COMBO_HD_BUS: + if (no_update) + return FALSE; - no_update = 1; - recalc_location_controls(hdlg, 1, 0); - b = settings_get_cur_sel(hdlg, IDC_COMBO_HD_BUS) + 1; - if (b != hdd_ptr->bus) { - hdd_ptr->bus = b; + no_update = 1; + recalc_location_controls(hdlg, 1, 0); + b = settings_get_cur_sel(hdlg, IDC_COMBO_HD_BUS) + 1; + if (b != hdd_ptr->bus) { + hdd_ptr->bus = b; - switch(hdd_ptr->bus) { - case HDD_BUS_DISABLED: - default: - max_spt = max_hpc = max_tracks = 0; - break; - case HDD_BUS_MFM: - max_spt = 26; /* 17 for MFM, 26 for RLL. */ - max_hpc = 15; - max_tracks = 2047; - break; - case HDD_BUS_XTA: - max_spt = 63; - max_hpc = 16; - max_tracks = 1023; - break; - case HDD_BUS_ESDI: - max_spt = 99; /* ESDI drives usually had 32 to 43 sectors per track. */ - max_hpc = 16; - max_tracks = 266305; - break; - case HDD_BUS_IDE: - max_spt = 63; - max_hpc = 255; - max_tracks = 266305; - break; - case HDD_BUS_ATAPI: - case HDD_BUS_SCSI: - max_spt = 99; - max_hpc = 255; - max_tracks = 266305; - break; - } + switch (hdd_ptr->bus) { + default: + case HDD_BUS_DISABLED: + max_spt = max_hpc = max_tracks = 0; + break; + case HDD_BUS_MFM: + max_spt = 26; /* 17 for MFM, 26 for RLL. */ + max_hpc = 15; + max_tracks = 2047; + break; + case HDD_BUS_XTA: + max_spt = 63; + max_hpc = 16; + max_tracks = 1023; + break; + case HDD_BUS_ESDI: + max_spt = 99; /* ESDI drives usually had 32 to 43 sectors per track. */ + max_hpc = 16; + max_tracks = 266305; + break; + case HDD_BUS_IDE: + max_spt = 255; + max_hpc = 255; + max_tracks = 266305; + break; + case HDD_BUS_ATAPI: + case HDD_BUS_SCSI: + max_spt = 255; + max_hpc = 255; + max_tracks = 266305; + break; + } - if (!chs_enabled) { - settings_enable_window(hdlg, IDC_EDIT_HD_SPT, FALSE); - settings_enable_window(hdlg, IDC_EDIT_HD_HPC, FALSE); - settings_enable_window(hdlg, IDC_EDIT_HD_CYL, FALSE); - settings_enable_window(hdlg, IDC_EDIT_HD_SIZE, FALSE); - settings_enable_window(hdlg, IDC_COMBO_HD_TYPE, FALSE); - } + if (!chs_enabled) { + settings_enable_window(hdlg, IDC_EDIT_HD_SPT, FALSE); + settings_enable_window(hdlg, IDC_EDIT_HD_HPC, FALSE); + settings_enable_window(hdlg, IDC_EDIT_HD_CYL, FALSE); + settings_enable_window(hdlg, IDC_EDIT_HD_SIZE, FALSE); + settings_enable_window(hdlg, IDC_COMBO_HD_TYPE, FALSE); + } - if (spt > max_spt) { - spt = max_spt; - size = ((uint64_t) tracks * (uint64_t) hpc * (uint64_t) spt) << 9LL; - set_edit_box_contents(hdlg, IDC_EDIT_HD_SPT, (uint32_t) spt); - set_edit_box_contents(hdlg, IDC_EDIT_HD_SIZE, (uint32_t) (size >> 20)); - recalc_selection(hdlg); - } + if (spt > max_spt) { + spt = max_spt; + size = ((uint64_t) tracks * (uint64_t) hpc * (uint64_t) spt) << 9LL; + set_edit_box_contents(hdlg, IDC_EDIT_HD_SPT, (uint32_t) spt); + set_edit_box_contents(hdlg, IDC_EDIT_HD_SIZE, (uint32_t) (size >> 20)); + recalc_selection(hdlg); + } - if (hpc > max_hpc) { - hpc = max_hpc; - size = ((uint64_t) tracks * (uint64_t) hpc * (uint64_t) spt) << 9LL; - set_edit_box_contents(hdlg, IDC_EDIT_HD_HPC, (uint32_t) hpc); - set_edit_box_contents(hdlg, IDC_EDIT_HD_SIZE, (uint32_t) (size >> 20)); - recalc_selection(hdlg); - } + if (hpc > max_hpc) { + hpc = max_hpc; + size = ((uint64_t) tracks * (uint64_t) hpc * (uint64_t) spt) << 9LL; + set_edit_box_contents(hdlg, IDC_EDIT_HD_HPC, (uint32_t) hpc); + set_edit_box_contents(hdlg, IDC_EDIT_HD_SIZE, (uint32_t) (size >> 20)); + recalc_selection(hdlg); + } - if (tracks > max_tracks) { - tracks = max_tracks; - size = ((uint64_t) tracks * (uint64_t) hpc * (uint64_t) spt) << 9LL; - set_edit_box_contents(hdlg, IDC_EDIT_HD_CYL, (uint32_t) tracks); - set_edit_box_contents(hdlg, IDC_EDIT_HD_SIZE, (uint32_t) (size >> 20)); - recalc_selection(hdlg); - } - } + if (tracks > max_tracks) { + tracks = max_tracks; + size = ((uint64_t) tracks * (uint64_t) hpc * (uint64_t) spt) << 9LL; + set_edit_box_contents(hdlg, IDC_EDIT_HD_CYL, (uint32_t) tracks); + set_edit_box_contents(hdlg, IDC_EDIT_HD_SIZE, (uint32_t) (size >> 20)); + recalc_selection(hdlg); + } + } - no_update = 0; - break; - case IDC_COMBO_HD_IMG_FORMAT: - img_format = settings_get_cur_sel(hdlg, IDC_COMBO_HD_IMG_FORMAT); + no_update = 0; + break; + case IDC_COMBO_HD_IMG_FORMAT: + img_format = settings_get_cur_sel(hdlg, IDC_COMBO_HD_IMG_FORMAT); - no_update = 1; - if (img_format == 5) { /* They switched to a diff VHD; disable the geometry fields. */ - settings_enable_window(hdlg, IDC_EDIT_HD_SPT, FALSE); - set_edit_box_text_contents(hdlg, IDC_EDIT_HD_SPT, L"(N/A)"); - settings_enable_window(hdlg, IDC_EDIT_HD_HPC, FALSE); - set_edit_box_text_contents(hdlg, IDC_EDIT_HD_HPC, L"(N/A)"); - settings_enable_window(hdlg, IDC_EDIT_HD_CYL, FALSE); - set_edit_box_text_contents(hdlg, IDC_EDIT_HD_CYL, L"(N/A)"); - settings_enable_window(hdlg, IDC_EDIT_HD_SIZE, FALSE); - set_edit_box_text_contents(hdlg, IDC_EDIT_HD_SIZE, L"(N/A)"); - settings_enable_window(hdlg, IDC_COMBO_HD_TYPE, FALSE); - settings_reset_content(hdlg, IDC_COMBO_HD_TYPE); - settings_add_string(hdlg, IDC_COMBO_HD_TYPE, (LPARAM) L"(use parent)"); - settings_set_cur_sel(hdlg, IDC_COMBO_HD_TYPE, 0); - } else { - get_edit_box_text_contents(hdlg, IDC_EDIT_HD_SPT, text_buf, 256); - if (!wcscmp(text_buf, L"(N/A)")) { - settings_enable_window(hdlg, IDC_EDIT_HD_SPT, TRUE); - set_edit_box_contents(hdlg, IDC_EDIT_HD_SPT, 17); - spt = 17; - settings_enable_window(hdlg, IDC_EDIT_HD_HPC, TRUE); - set_edit_box_contents(hdlg, IDC_EDIT_HD_HPC, 15); - hpc = 15; - settings_enable_window(hdlg, IDC_EDIT_HD_CYL, TRUE); - set_edit_box_contents(hdlg, IDC_EDIT_HD_CYL, 1023); - tracks = 1023; - settings_enable_window(hdlg, IDC_EDIT_HD_SIZE, TRUE); - set_edit_box_contents(hdlg, IDC_EDIT_HD_SIZE, (uint32_t) ((uint64_t)17 * 15 * 1023 * 512 >> 20)); - size = (uint64_t)17 * 15 * 1023 * 512; - - settings_reset_content(hdlg, IDC_COMBO_HD_TYPE); - hdconf_initialize_hdt_combo(hdlg); - settings_enable_window(hdlg, IDC_COMBO_HD_TYPE, TRUE); - } - } - no_update = 0; + no_update = 1; + if (img_format == IMG_FMT_VHD_DIFF) { /* They switched to a diff VHD; disable the geometry fields. */ + settings_enable_window(hdlg, IDC_EDIT_HD_SPT, FALSE); + set_edit_box_text_contents(hdlg, IDC_EDIT_HD_SPT, L"(N/A)"); + settings_enable_window(hdlg, IDC_EDIT_HD_HPC, FALSE); + set_edit_box_text_contents(hdlg, IDC_EDIT_HD_HPC, L"(N/A)"); + settings_enable_window(hdlg, IDC_EDIT_HD_CYL, FALSE); + set_edit_box_text_contents(hdlg, IDC_EDIT_HD_CYL, L"(N/A)"); + settings_enable_window(hdlg, IDC_EDIT_HD_SIZE, FALSE); + set_edit_box_text_contents(hdlg, IDC_EDIT_HD_SIZE, L"(N/A)"); + settings_enable_window(hdlg, IDC_COMBO_HD_TYPE, FALSE); + settings_reset_content(hdlg, IDC_COMBO_HD_TYPE); + settings_add_string(hdlg, IDC_COMBO_HD_TYPE, (LPARAM) L"(use parent)"); + settings_set_cur_sel(hdlg, IDC_COMBO_HD_TYPE, 0); + } else { + get_edit_box_text_contents(hdlg, IDC_EDIT_HD_SPT, text_buf, 256); + if (!wcscmp(text_buf, L"(N/A)")) { + settings_enable_window(hdlg, IDC_EDIT_HD_SPT, TRUE); + set_edit_box_contents(hdlg, IDC_EDIT_HD_SPT, 17); + spt = 17; + settings_enable_window(hdlg, IDC_EDIT_HD_HPC, TRUE); + set_edit_box_contents(hdlg, IDC_EDIT_HD_HPC, 15); + hpc = 15; + settings_enable_window(hdlg, IDC_EDIT_HD_CYL, TRUE); + set_edit_box_contents(hdlg, IDC_EDIT_HD_CYL, 1023); + tracks = 1023; + settings_enable_window(hdlg, IDC_EDIT_HD_SIZE, TRUE); + set_edit_box_contents(hdlg, IDC_EDIT_HD_SIZE, (uint32_t) ((uint64_t) 17 * 15 * 1023 * 512 >> 20)); + size = (uint64_t) 17 * 15 * 1023 * 512; - if (img_format == 4 || img_format == 5) { /* For dynamic and diff VHDs, show the block size dropdown. */ - settings_show_window(hdlg, IDC_COMBO_HD_BLOCK_SIZE, TRUE); - settings_show_window(hdlg, IDT_BLOCK_SIZE, TRUE); - } else { /* Hide it otherwise. */ - settings_show_window(hdlg, IDC_COMBO_HD_BLOCK_SIZE, FALSE); - settings_show_window(hdlg, IDT_BLOCK_SIZE, FALSE); - } - break; - } + settings_reset_content(hdlg, IDC_COMBO_HD_TYPE); + hdconf_initialize_hdt_combo(hdlg); + settings_enable_window(hdlg, IDC_COMBO_HD_TYPE, TRUE); + } + } + no_update = 0; - return FALSE; - } + if (img_format == IMG_FMT_VHD_DYNAMIC || img_format == IMG_FMT_VHD_DIFF) { /* For dynamic and diff VHDs, show the block size dropdown. */ + settings_show_window(hdlg, IDC_COMBO_HD_BLOCK_SIZE, TRUE); + settings_show_window(hdlg, IDT_BLOCK_SIZE, TRUE); + } else { /* Hide it otherwise. */ + settings_show_window(hdlg, IDC_COMBO_HD_BLOCK_SIZE, FALSE); + settings_show_window(hdlg, IDT_BLOCK_SIZE, FALSE); + } + break; + } - return FALSE; + return FALSE; + } + + return FALSE; } - int hard_disk_was_added(void) { return hard_disk_added; } - void hard_disk_add_open(HWND hwnd, int is_existing) { - existing = is_existing; + existing = is_existing; hard_disk_added = 0; - DialogBox(hinstance, (LPCWSTR)DLG_CFG_HARD_DISKS_ADD, hwnd, win_settings_hard_disks_add_proc); + DialogBox(hinstance, (LPCWSTR) DLG_CFG_HARD_DISKS_ADD, hwnd, win_settings_hard_disks_add_proc); } - static void hard_disk_track(uint8_t id) { - switch(temp_hdd[id].bus) { - case HDD_BUS_MFM: - mfm_tracking |= (1 << (temp_hdd[id].mfm_channel << 3)); - break; - case HDD_BUS_ESDI: - esdi_tracking |= (1 << (temp_hdd[id].esdi_channel << 3)); - break; - case HDD_BUS_XTA: - xta_tracking |= (1 << (temp_hdd[id].xta_channel << 3)); - break; - case HDD_BUS_IDE: - case HDD_BUS_ATAPI: - ide_tracking |= (1 << (temp_hdd[id].ide_channel << 3)); - break; - case HDD_BUS_SCSI: - scsi_tracking[temp_hdd[id].scsi_id >> 3] |= (1 << ((temp_hdd[id].scsi_id & 0x07) << 3)); - break; + switch (temp_hdd[id].bus) { + case HDD_BUS_MFM: + mfm_tracking |= (1 << (temp_hdd[id].mfm_channel << 3)); + break; + case HDD_BUS_ESDI: + esdi_tracking |= (1 << (temp_hdd[id].esdi_channel << 3)); + break; + case HDD_BUS_XTA: + xta_tracking |= (1 << (temp_hdd[id].xta_channel << 3)); + break; + case HDD_BUS_IDE: + case HDD_BUS_ATAPI: + ide_tracking |= (1 << (temp_hdd[id].ide_channel << 3)); + break; + case HDD_BUS_SCSI: + scsi_tracking[temp_hdd[id].scsi_id >> 3] |= (1 << ((temp_hdd[id].scsi_id & 0x07) << 3)); + break; } } - static void hard_disk_untrack(uint8_t id) { - switch(temp_hdd[id].bus) { - case HDD_BUS_MFM: - mfm_tracking &= ~(1 << (temp_hdd[id].mfm_channel << 3)); - break; - case HDD_BUS_ESDI: - esdi_tracking &= ~(1 << (temp_hdd[id].esdi_channel << 3)); - break; - case HDD_BUS_XTA: - xta_tracking &= ~(1 << (temp_hdd[id].xta_channel << 3)); - break; - case HDD_BUS_IDE: - case HDD_BUS_ATAPI: - ide_tracking &= ~(1 << (temp_hdd[id].ide_channel << 3)); - break; - case HDD_BUS_SCSI: - scsi_tracking[temp_hdd[id].scsi_id >> 3] &= ~(1 << ((temp_hdd[id].scsi_id & 0x07) << 3)); - break; + switch (temp_hdd[id].bus) { + case HDD_BUS_MFM: + mfm_tracking &= ~(1 << (temp_hdd[id].mfm_channel << 3)); + break; + case HDD_BUS_ESDI: + esdi_tracking &= ~(1 << (temp_hdd[id].esdi_channel << 3)); + break; + case HDD_BUS_XTA: + xta_tracking &= ~(1 << (temp_hdd[id].xta_channel << 3)); + break; + case HDD_BUS_IDE: + case HDD_BUS_ATAPI: + ide_tracking &= ~(1 << (temp_hdd[id].ide_channel << 3)); + break; + case HDD_BUS_SCSI: + scsi_tracking[temp_hdd[id].scsi_id >> 3] &= ~(1 << ((temp_hdd[id].scsi_id & 0x07) << 3)); + break; } } - static void hard_disk_track_all(void) { - int i; - - for (i = 0; i < HDD_NUM; i++) - hard_disk_track(i); + for (uint8_t i = 0; i < HDD_NUM; i++) + hard_disk_track(i); } - #if defined(__amd64__) || defined(__aarch64__) static LRESULT CALLBACK #else @@ -3406,1067 +3832,1112 @@ static BOOL CALLBACK #endif win_settings_hard_disks_proc(HWND hdlg, UINT message, WPARAM wParam, LPARAM lParam) { - int old_sel = 0, b = 0, assign = 0; + int old_sel = 0; + int b = 0; + int assign = 0; const uint8_t hd_icons[2] = { 80, 0 }; switch (message) { - case WM_INITDIALOG: - ignore_change = 1; + case WM_INITDIALOG: + ignore_change = 1; - normalize_hd_list(); /* Normalize the hard disks so that non-disabled hard disks start from index 0, and so they are contiguous. - This will cause an emulator reset prompt on the first opening of this category with a messy hard disk list - (which can only happen by manually editing the configuration file). */ - win_settings_hard_disks_init_columns(hdlg); - image_list_init(hdlg, IDC_LIST_HARD_DISKS, (const uint8_t *) hd_icons); - win_settings_hard_disks_recalc_list(hdlg); - recalc_next_free_id(hdlg); - add_locations(hdlg); - if (hd_listview_items > 0) { - settings_listview_select(hdlg, IDC_LIST_HARD_DISKS, 0); - lv1_current_sel = 0; - settings_set_cur_sel(hdlg, IDC_COMBO_HD_BUS, temp_hdd[0].bus - 1); - } else - lv1_current_sel = -1; - recalc_location_controls(hdlg, 0, 0); + normalize_hd_list(); /* Normalize the hard disks so that non-disabled hard disks start from index 0, and so they are contiguous. + This will cause an emulator reset prompt on the first opening of this category with a messy hard disk list + (which can only happen by manually editing the configuration file). */ + win_settings_hard_disks_init_columns(hdlg); + image_list_init(hdlg, IDC_LIST_HARD_DISKS, (const uint8_t *) hd_icons); + win_settings_hard_disks_recalc_list(hdlg); + recalc_next_free_id(hdlg); + add_locations(hdlg); + if (hd_listview_items > 0) { + settings_listview_select(hdlg, IDC_LIST_HARD_DISKS, 0); + lv1_current_sel = 0; + settings_set_cur_sel(hdlg, IDC_COMBO_HD_BUS, temp_hdd[0].bus - 1); + } else + lv1_current_sel = -1; + recalc_location_controls(hdlg, 0, 0); - settings_listview_enable_styles(hdlg, IDC_LIST_HARD_DISKS); + settings_listview_enable_styles(hdlg, IDC_LIST_HARD_DISKS); - ignore_change = 0; - return TRUE; + ignore_change = 0; + return TRUE; - case WM_NOTIFY: - if ((hd_listview_items == 0) || ignore_change) - return FALSE; + case WM_NOTIFY: + if ((hd_listview_items == 0) || ignore_change) + return FALSE; - if ((((LPNMHDR)lParam)->code == LVN_ITEMCHANGED) && (((LPNMHDR)lParam)->idFrom == IDC_LIST_HARD_DISKS)) { - old_sel = lv1_current_sel; - lv1_current_sel = get_selected_hard_disk(hdlg); - if (lv1_current_sel == old_sel) - return FALSE; - ignore_change = 1; - settings_set_cur_sel(hdlg, IDC_COMBO_HD_BUS, temp_hdd[lv1_current_sel].bus - 1); - recalc_location_controls(hdlg, 0, 0); - ignore_change = 0; - } - break; + if ((((LPNMHDR) lParam)->code == LVN_ITEMCHANGED) && (((LPNMHDR) lParam)->idFrom == IDC_LIST_HARD_DISKS)) { + old_sel = lv1_current_sel; + lv1_current_sel = get_selected_hard_disk(hdlg); + if (lv1_current_sel == old_sel) + return FALSE; + ignore_change = 1; + settings_set_cur_sel(hdlg, IDC_COMBO_HD_BUS, temp_hdd[lv1_current_sel].bus - 1); + recalc_location_controls(hdlg, 0, 0); + ignore_change = 0; + } + break; - case WM_COMMAND: - if (ignore_change && (LOWORD(wParam) != IDC_BUTTON_HDD_ADD) && - (LOWORD(wParam) != IDC_BUTTON_HDD_ADD_NEW) && (LOWORD(wParam) != IDC_BUTTON_HDD_REMOVE)) - return FALSE; - switch (LOWORD(wParam)) { - case IDC_COMBO_HD_BUS: - ignore_change = 1; - b = settings_get_cur_sel(hdlg, IDC_COMBO_HD_BUS) + 1; - if (b != temp_hdd[lv1_current_sel].bus) { - hard_disk_untrack(lv1_current_sel); - assign = (temp_hdd[lv1_current_sel].bus == b) ? 0 : 1; - temp_hdd[lv1_current_sel].bus = b; - recalc_location_controls(hdlg, 0, assign); - hard_disk_track(lv1_current_sel); - win_settings_hard_disks_update_item(hdlg, lv1_current_sel, 0); - } - ignore_change = 0; - return FALSE; + case WM_COMMAND: + if (ignore_change && (LOWORD(wParam) != IDC_BUTTON_HDD_ADD) && (LOWORD(wParam) != IDC_BUTTON_HDD_ADD_NEW) && (LOWORD(wParam) != IDC_BUTTON_HDD_REMOVE)) + return FALSE; + switch (LOWORD(wParam)) { + case IDC_COMBO_HD_BUS: + ignore_change = 1; + b = settings_get_cur_sel(hdlg, IDC_COMBO_HD_BUS) + 1; + if (b != temp_hdd[lv1_current_sel].bus) { + hard_disk_untrack(lv1_current_sel); + assign = (temp_hdd[lv1_current_sel].bus == b) ? 0 : 1; + temp_hdd[lv1_current_sel].bus = b; + recalc_location_controls(hdlg, 0, assign); + hard_disk_track(lv1_current_sel); + win_settings_hard_disks_update_item(hdlg, lv1_current_sel, 0); + } + ignore_change = 0; + return FALSE; - case IDC_COMBO_HD_CHANNEL: - ignore_change = 1; - hard_disk_untrack(lv1_current_sel); - temp_hdd[lv1_current_sel].channel = settings_get_cur_sel(hdlg, IDC_COMBO_HD_CHANNEL); - hard_disk_track(lv1_current_sel); - win_settings_hard_disks_update_item(hdlg, lv1_current_sel, 0); - ignore_change = 0; - return FALSE; + case IDC_COMBO_HD_CHANNEL: + ignore_change = 1; + hard_disk_untrack(lv1_current_sel); + temp_hdd[lv1_current_sel].channel = settings_get_cur_sel(hdlg, IDC_COMBO_HD_CHANNEL); + hard_disk_track(lv1_current_sel); + win_settings_hard_disks_update_item(hdlg, lv1_current_sel, 0); + ignore_change = 0; + return FALSE; - case IDC_COMBO_HD_CHANNEL_IDE: - ignore_change = 1; - hard_disk_untrack(lv1_current_sel); - temp_hdd[lv1_current_sel].ide_channel = settings_get_cur_sel(hdlg, IDC_COMBO_HD_CHANNEL_IDE); - hard_disk_track(lv1_current_sel); - win_settings_hard_disks_update_item(hdlg, lv1_current_sel, 0); - ignore_change = 0; - return FALSE; + case IDC_COMBO_HD_CHANNEL_IDE: + ignore_change = 1; + hard_disk_untrack(lv1_current_sel); + temp_hdd[lv1_current_sel].ide_channel = settings_get_cur_sel(hdlg, IDC_COMBO_HD_CHANNEL_IDE); + hard_disk_track(lv1_current_sel); + win_settings_hard_disks_update_item(hdlg, lv1_current_sel, 0); + ignore_change = 0; + return FALSE; - case IDC_COMBO_HD_ID: - ignore_change = 1; - hard_disk_untrack(lv1_current_sel); - temp_hdd[lv1_current_sel].scsi_id = settings_get_cur_sel(hdlg, IDC_COMBO_HD_ID); - hard_disk_track(lv1_current_sel); - win_settings_hard_disks_update_item(hdlg, lv1_current_sel, 0); - ignore_change = 0; - return FALSE; + case IDC_COMBO_HD_ID: + ignore_change = 1; + hard_disk_untrack(lv1_current_sel); + temp_hdd[lv1_current_sel].scsi_id = settings_get_cur_sel(hdlg, IDC_COMBO_HD_ID); + hard_disk_track(lv1_current_sel); + win_settings_hard_disks_update_item(hdlg, lv1_current_sel, 0); + ignore_change = 0; + return FALSE; - case IDC_BUTTON_HDD_ADD: - case IDC_BUTTON_HDD_ADD_NEW: - hard_disk_add_open(hdlg, (LOWORD(wParam) == IDC_BUTTON_HDD_ADD)); - if (hard_disk_added) { - ignore_change = 1; - win_settings_hard_disks_recalc_list(hdlg); - recalc_next_free_id(hdlg); - hard_disk_track_all(); - ignore_change = 0; - } - return FALSE; + case IDC_BUTTON_HDD_ADD: + case IDC_BUTTON_HDD_ADD_NEW: + hard_disk_add_open(hdlg, (LOWORD(wParam) == IDC_BUTTON_HDD_ADD)); + if (hard_disk_added) { + ignore_change = 1; + win_settings_hard_disks_recalc_list(hdlg); + recalc_next_free_id(hdlg); + hard_disk_track_all(); + ignore_change = 0; + } + return FALSE; - case IDC_BUTTON_HDD_REMOVE: - temp_hdd[lv1_current_sel].fn[0] = '\0'; - hard_disk_untrack(lv1_current_sel); - temp_hdd[lv1_current_sel].bus = HDD_BUS_DISABLED; /* Only set the bus to zero, the list normalize code below will take care of turning this entire entry to a complete zero. */ - normalize_hd_list(); /* Normalize the hard disks so that non-disabled hard disks start from index 0, and so they are contiguous. */ - ignore_change = 1; - win_settings_hard_disks_recalc_list(hdlg); - recalc_next_free_id(hdlg); - if (hd_listview_items > 0) { - settings_listview_select(hdlg, IDC_LIST_HARD_DISKS, 0); - lv1_current_sel = 0; - settings_set_cur_sel(hdlg, IDC_COMBO_HD_BUS, temp_hdd[0].bus - 1); - } else - lv1_current_sel = -1; - recalc_location_controls(hdlg, 0, 0); - ignore_change = 0; - return FALSE; - } + case IDC_BUTTON_HDD_REMOVE: + temp_hdd[lv1_current_sel].fn[0] = '\0'; + hard_disk_untrack(lv1_current_sel); + temp_hdd[lv1_current_sel].bus = HDD_BUS_DISABLED; /* Only set the bus to zero, the list normalize code below will take care of turning this entire entry to a complete zero. */ + normalize_hd_list(); /* Normalize the hard disks so that non-disabled hard disks start from index 0, and so they are contiguous. */ + ignore_change = 1; + win_settings_hard_disks_recalc_list(hdlg); + recalc_next_free_id(hdlg); + if (hd_listview_items > 0) { + settings_listview_select(hdlg, IDC_LIST_HARD_DISKS, 0); + lv1_current_sel = 0; + settings_set_cur_sel(hdlg, IDC_COMBO_HD_BUS, temp_hdd[0].bus - 1); + } else + lv1_current_sel = -1; + recalc_location_controls(hdlg, 0, 0); + ignore_change = 0; + return FALSE; + } - case WM_DPICHANGED_AFTERPARENT: - win_settings_hard_disks_resize_columns(hdlg); - image_list_init(hdlg, IDC_LIST_HARD_DISKS, (const uint8_t *) hd_icons); - break; - default: - return FALSE; + case WM_DPICHANGED_AFTERPARENT: + win_settings_hard_disks_resize_columns(hdlg); + image_list_init(hdlg, IDC_LIST_HARD_DISKS, (const uint8_t *) hd_icons); + break; + default: + return FALSE; } return FALSE; } - static int combo_id_to_string_id(int combo_id) { return IDS_5376 + combo_id; } - static int combo_id_to_format_string_id(int combo_id) { return IDS_5632 + combo_id; } - static BOOL win_settings_floppy_drives_recalc_list(HWND hdlg) { - LVITEM lvI; - int i = 0; - char s[256], *t; - WCHAR szText[256]; - HWND hwndList = GetDlgItem(hdlg, IDC_LIST_FLOPPY_DRIVES); + LVITEM lvI; + char s[256]; + const char *t; + WCHAR szText[256]; + HWND hwndList = GetDlgItem(hdlg, IDC_LIST_FLOPPY_DRIVES); - lvI.mask = LVIF_TEXT | LVIF_IMAGE | LVIF_STATE; + lvI.mask = LVIF_TEXT | LVIF_IMAGE | LVIF_STATE; lvI.stateMask = lvI.state = 0; - for (i = 0; i < 4; i++) { - lvI.iSubItem = 0; - if (temp_fdd_types[i] > 0) { - t = fdd_getname(temp_fdd_types[i]); - strncpy(s, t, sizeof(s) - 1); - mbstowcs(szText, s, strlen(s) + 1); - lvI.pszText = szText; - } else - lvI.pszText = plat_get_string(IDS_5376); - lvI.iItem = i; - lvI.iImage = temp_fdd_types[i]; + for (uint8_t i = 0; i < FDD_NUM; i++) { + lvI.iSubItem = 0; + if (temp_fdd_types[i] > 0) { + t = fdd_getname(temp_fdd_types[i]); + strncpy(s, t, sizeof(s) - 1); + mbstowcs(szText, s, strlen(s) + 1); + lvI.pszText = szText; + } else + lvI.pszText = plat_get_string(IDS_5376); + lvI.iItem = i; + lvI.iImage = temp_fdd_types[i]; - if (ListView_InsertItem(hwndList, &lvI) == -1) - return FALSE; + if (ListView_InsertItem(hwndList, &lvI) == -1) + return FALSE; - lvI.iSubItem = 1; - lvI.pszText = plat_get_string(temp_fdd_turbo[i] ? IDS_2060 : IDS_2061); - lvI.iItem = i; - lvI.iImage = 0; + lvI.iSubItem = 1; + lvI.pszText = plat_get_string(temp_fdd_turbo[i] ? IDS_2060 : IDS_2061); + lvI.iItem = i; + lvI.iImage = 0; - if (ListView_SetItem(hwndList, &lvI) == -1) - return FALSE; + if (ListView_SetItem(hwndList, &lvI) == -1) + return FALSE; - lvI.iSubItem = 2; - lvI.pszText = plat_get_string(temp_fdd_check_bpb[i] ? IDS_2060 : IDS_2061); - lvI.iItem = i; - lvI.iImage = 0; + lvI.iSubItem = 2; + lvI.pszText = plat_get_string(temp_fdd_check_bpb[i] ? IDS_2060 : IDS_2061); + lvI.iItem = i; + lvI.iImage = 0; - if (ListView_SetItem(hwndList, &lvI) == -1) - return FALSE; + if (ListView_SetItem(hwndList, &lvI) == -1) + return FALSE; } return TRUE; } - static BOOL win_settings_cdrom_drives_recalc_list(HWND hdlg) { LVITEM lvI; - int i = 0, fsid = 0; - WCHAR szText[256]; - HWND hwndList = GetDlgItem(hdlg, IDC_LIST_CDROM_DRIVES); + int fsid = 0; + WCHAR szText[256]; + HWND hwndList = GetDlgItem(hdlg, IDC_LIST_CDROM_DRIVES); - lvI.mask = LVIF_TEXT | LVIF_IMAGE | LVIF_STATE; + lvI.mask = LVIF_TEXT | LVIF_IMAGE | LVIF_STATE; lvI.stateMask = lvI.iSubItem = lvI.state = 0; - for (i = 0; i < 4; i++) { - fsid = combo_id_to_format_string_id(temp_cdrom[i].bus_type); + for (uint8_t i = 0; i < CDROM_NUM; i++) { + fsid = combo_id_to_format_string_id(temp_cdrom[i].bus_type); - lvI.iSubItem = 0; - switch (temp_cdrom[i].bus_type) { - case CDROM_BUS_DISABLED: - default: - lvI.pszText = plat_get_string(fsid); - lvI.iImage = 0; - break; - case CDROM_BUS_ATAPI: - wsprintf(szText, plat_get_string(fsid), temp_cdrom[i].ide_channel >> 1, temp_cdrom[i].ide_channel & 1); - lvI.pszText = szText; - lvI.iImage = 1; - break; - case CDROM_BUS_SCSI: - wsprintf(szText, plat_get_string(fsid), temp_cdrom[i].scsi_device_id >> 4, temp_cdrom[i].scsi_device_id & 15); - lvI.pszText = szText; - lvI.iImage = 1; - break; - } + lvI.iSubItem = 0; + switch (temp_cdrom[i].bus_type) { + default: + case CDROM_BUS_DISABLED: + lvI.pszText = plat_get_string(fsid); + lvI.iImage = 0; + break; + case CDROM_BUS_ATAPI: + wsprintf(szText, plat_get_string(fsid), temp_cdrom[i].ide_channel >> 1, temp_cdrom[i].ide_channel & 1); + lvI.pszText = szText; + lvI.iImage = 1; + break; + case CDROM_BUS_SCSI: + wsprintf(szText, plat_get_string(fsid), temp_cdrom[i].scsi_device_id >> 4, temp_cdrom[i].scsi_device_id & 15); + lvI.pszText = szText; + lvI.iImage = 1; + break; + } - lvI.iItem = i; + lvI.iItem = i; - if (ListView_InsertItem(hwndList, &lvI) == -1) - return FALSE; + if (ListView_InsertItem(hwndList, &lvI) == -1) + return FALSE; - lvI.iSubItem = 1; - if (temp_cdrom[i].bus_type == CDROM_BUS_DISABLED) - lvI.pszText = plat_get_string(IDS_2103); - else { - wsprintf(szText, L"%ix", temp_cdrom[i].speed); - lvI.pszText = szText; - } - lvI.iItem = i; - lvI.iImage = 0; + lvI.iSubItem = 1; + if (temp_cdrom[i].bus_type == CDROM_BUS_DISABLED) + lvI.pszText = plat_get_string(IDS_2104); + else { + wsprintf(szText, L"%ix", temp_cdrom[i].speed); + lvI.pszText = szText; + } + lvI.iItem = i; + lvI.iImage = 0; - if (ListView_SetItem(hwndList, &lvI) == -1) - return FALSE; + if (ListView_SetItem(hwndList, &lvI) == -1) + return FALSE; + +#if 0 + lvI.iSubItem = 2; + lvI.pszText = plat_get_string(temp_cdrom[i].early ? IDS_2060 : IDS_2061); + lvI.iItem = i; + lvI.iImage = 0; + + if (ListView_SetItem(hwndList, &lvI) == -1) + return FALSE; +#endif } return TRUE; } - static BOOL win_settings_mo_drives_recalc_list(HWND hdlg) { LVITEM lvI; - int i = 0, fsid = 0; - WCHAR szText[256]; - char szType[30]; - HWND hwndList = GetDlgItem(hdlg, IDC_LIST_MO_DRIVES); + int fsid = 0; + WCHAR szText[256]; + char szType[30]; + HWND hwndList = GetDlgItem(hdlg, IDC_LIST_MO_DRIVES); - lvI.mask = LVIF_TEXT | LVIF_IMAGE | LVIF_STATE; - lvI.stateMask = lvI.iSubItem = lvI.state = 0; + lvI.mask = LVIF_TEXT | LVIF_IMAGE | LVIF_STATE; + lvI.stateMask = lvI.iSubItem = lvI.state = 0; - for (i = 0; i < MO_NUM; i++) { - fsid = combo_id_to_format_string_id(temp_mo_drives[i].bus_type); - - lvI.iSubItem = 0; - switch (temp_mo_drives[i].bus_type) { - case MO_BUS_DISABLED: - default: - lvI.pszText = plat_get_string(fsid); - lvI.iImage = 0; - break; - case MO_BUS_ATAPI: - wsprintf(szText, plat_get_string(fsid), temp_mo_drives[i].ide_channel >> 1, temp_mo_drives[i].ide_channel & 1); - lvI.pszText = szText; - lvI.iImage = 1; - break; - case MO_BUS_SCSI: - wsprintf(szText, plat_get_string(fsid), temp_mo_drives[i].scsi_device_id >> 4, temp_mo_drives[i].scsi_device_id & 15); - lvI.pszText = szText; - lvI.iImage = 1; - break; - } + for (uint8_t i = 0; i < MO_NUM; i++) { + fsid = combo_id_to_format_string_id(temp_mo_drives[i].bus_type); - lvI.iItem = i; + lvI.iSubItem = 0; + switch (temp_mo_drives[i].bus_type) { + default: + case MO_BUS_DISABLED: + lvI.pszText = plat_get_string(fsid); + lvI.iImage = 0; + break; + case MO_BUS_ATAPI: + wsprintf(szText, plat_get_string(fsid), temp_mo_drives[i].ide_channel >> 1, temp_mo_drives[i].ide_channel & 1); + lvI.pszText = szText; + lvI.iImage = 1; + break; + case MO_BUS_SCSI: + wsprintf(szText, plat_get_string(fsid), temp_mo_drives[i].scsi_device_id >> 4, temp_mo_drives[i].scsi_device_id & 15); + lvI.pszText = szText; + lvI.iImage = 1; + break; + } - if (ListView_InsertItem(hwndList, &lvI) == -1) - return FALSE; + lvI.iItem = i; - lvI.iSubItem = 1; - if (temp_mo_drives[i].bus_type == MO_BUS_DISABLED) - lvI.pszText = plat_get_string(IDS_2103); - else { - memset(szType, 0, 30); - memcpy(szType, mo_drive_types[temp_mo_drives[i].type].vendor, 8); - szType[strlen(szType)] = ' '; - memcpy(szType + strlen(szType), mo_drive_types[temp_mo_drives[i].type].model, 16); - szType[strlen(szType)] = ' '; - memcpy(szType + strlen(szType), mo_drive_types[temp_mo_drives[i].type].revision, 4); + if (ListView_InsertItem(hwndList, &lvI) == -1) + return FALSE; - mbstowcs(szText, szType, strlen(szType)+1); - lvI.pszText = szText; - } - lvI.iItem = i; - lvI.iImage = 0; + lvI.iSubItem = 1; + if (temp_mo_drives[i].bus_type == MO_BUS_DISABLED) + lvI.pszText = plat_get_string(IDS_2104); + else { + memset(szType, 0, 30); + memcpy(szType, mo_drive_types[temp_mo_drives[i].type].vendor, 8); + szType[strlen(szType)] = ' '; + memcpy(szType + strlen(szType), mo_drive_types[temp_mo_drives[i].type].model, 16); + szType[strlen(szType)] = ' '; + memcpy(szType + strlen(szType), mo_drive_types[temp_mo_drives[i].type].revision, 4); - if (ListView_SetItem(hwndList, &lvI) == -1) - return FALSE; + mbstowcs(szText, szType, strlen(szType) + 1); + lvI.pszText = szText; + } + lvI.iItem = i; + lvI.iImage = 0; + + if (ListView_SetItem(hwndList, &lvI) == -1) + return FALSE; } return TRUE; } - static BOOL win_settings_zip_drives_recalc_list(HWND hdlg) { LVITEM lvI; - int i = 0, fsid = 0; - WCHAR szText[256]; - HWND hwndList = GetDlgItem(hdlg, IDC_LIST_ZIP_DRIVES); + int fsid = 0; + WCHAR szText[256]; + HWND hwndList = GetDlgItem(hdlg, IDC_LIST_ZIP_DRIVES); - lvI.mask = LVIF_TEXT | LVIF_IMAGE | LVIF_STATE; + lvI.mask = LVIF_TEXT | LVIF_IMAGE | LVIF_STATE; lvI.stateMask = lvI.iSubItem = lvI.state = 0; - for (i = 0; i < ZIP_NUM; i++) { - fsid = combo_id_to_format_string_id(temp_zip_drives[i].bus_type); + for (uint8_t i = 0; i < ZIP_NUM; i++) { + fsid = combo_id_to_format_string_id(temp_zip_drives[i].bus_type); - lvI.iSubItem = 0; - switch (temp_zip_drives[i].bus_type) { - case ZIP_BUS_DISABLED: - default: - lvI.pszText = plat_get_string(fsid); - lvI.iImage = 0; - break; - case ZIP_BUS_ATAPI: - wsprintf(szText, plat_get_string(fsid), temp_zip_drives[i].ide_channel >> 1, temp_zip_drives[i].ide_channel & 1); - lvI.pszText = szText; - lvI.iImage = 1; - break; - case ZIP_BUS_SCSI: - wsprintf(szText, plat_get_string(fsid), temp_zip_drives[i].scsi_device_id >> 4, temp_zip_drives[i].scsi_device_id & 15); - lvI.pszText = szText; - lvI.iImage = 1; - break; - } + lvI.iSubItem = 0; + switch (temp_zip_drives[i].bus_type) { + default: + case ZIP_BUS_DISABLED: + lvI.pszText = plat_get_string(fsid); + lvI.iImage = 0; + break; + case ZIP_BUS_ATAPI: + wsprintf(szText, plat_get_string(fsid), temp_zip_drives[i].ide_channel >> 1, temp_zip_drives[i].ide_channel & 1); + lvI.pszText = szText; + lvI.iImage = 1; + break; + case ZIP_BUS_SCSI: + wsprintf(szText, plat_get_string(fsid), temp_zip_drives[i].scsi_device_id >> 4, temp_zip_drives[i].scsi_device_id & 15); + lvI.pszText = szText; + lvI.iImage = 1; + break; + } - lvI.iItem = i; + lvI.iItem = i; - if (ListView_InsertItem(hwndList, &lvI) == -1) - return FALSE; + if (ListView_InsertItem(hwndList, &lvI) == -1) + return FALSE; - lvI.iSubItem = 1; - lvI.pszText = plat_get_string(temp_zip_drives[i].is_250 ? IDS_5901 : IDS_5900); - lvI.iItem = i; - lvI.iImage = 0; + lvI.iSubItem = 1; + lvI.pszText = plat_get_string(temp_zip_drives[i].is_250 ? IDS_5901 : IDS_5900); + lvI.iItem = i; + lvI.iImage = 0; - if (ListView_SetItem(hwndList, &lvI) == -1) - return FALSE; + if (ListView_SetItem(hwndList, &lvI) == -1) + return FALSE; } return TRUE; } +#define C_COLUMNS_FLOPPY_DRIVES_TYPE 292 +#define C_COLUMNS_FLOPPY_DRIVES_TURBO 58 +#define C_COLUMNS_FLOPPY_DRIVES_BPB 89 static void win_settings_floppy_drives_resize_columns(HWND hdlg) { - int iCol, width[3] = {292, 58, 89}; - int total = 0; + int width[C_COLUMNS_FLOPPY_DRIVES] = { + C_COLUMNS_FLOPPY_DRIVES_TYPE, + C_COLUMNS_FLOPPY_DRIVES_TURBO, + C_COLUMNS_FLOPPY_DRIVES_BPB + }; + int total = 0; HWND hwndList = GetDlgItem(hdlg, IDC_LIST_FLOPPY_DRIVES); RECT r; GetWindowRect(hwndList, &r); - for (iCol = 0; iCol < 2; iCol++) { - width[iCol] = MulDiv(width[iCol], dpi, 96); - total += width[iCol]; - ListView_SetColumnWidth(hwndList, iCol, MulDiv(width[iCol], dpi, 96)); + for (uint8_t iCol = 0; iCol < C_COLUMNS_FLOPPY_DRIVES; iCol++) { + width[iCol] = MulDiv(width[iCol], dpi, 96); + total += width[iCol]; + ListView_SetColumnWidth(hwndList, iCol, MulDiv(width[iCol], dpi, 96)); } - width[2] = (r.right - r.left) - 4 - total; - ListView_SetColumnWidth(hwndList, 2, width[2]); + width[C_COLUMNS_FLOPPY_DRIVES - 1] = (r.right - r.left) - 4 - total; + ListView_SetColumnWidth(hwndList, 2, width[C_COLUMNS_FLOPPY_DRIVES - 1]); } - static BOOL win_settings_floppy_drives_init_columns(HWND hdlg) { LVCOLUMN lvc; - HWND hwndList = GetDlgItem(hdlg, IDC_LIST_FLOPPY_DRIVES); + HWND hwndList = GetDlgItem(hdlg, IDC_LIST_FLOPPY_DRIVES); lvc.mask = LVCF_FMT | LVCF_WIDTH | LVCF_TEXT | LVCF_SUBITEM; + /* Type */ lvc.iSubItem = 0; - lvc.pszText = plat_get_string(IDS_2092); + lvc.pszText = plat_get_string(IDS_TYPE); - lvc.cx = 292; + lvc.cx = C_COLUMNS_FLOPPY_DRIVES_TYPE; lvc.fmt = LVCFMT_LEFT; if (ListView_InsertColumn(hwndList, 0, &lvc) == -1) - return FALSE; + return FALSE; + /* Turbo */ lvc.iSubItem = 1; - lvc.pszText = plat_get_string(IDS_2059); + lvc.pszText = plat_get_string(IDS_2059); - lvc.cx = 58; + lvc.cx = C_COLUMNS_FLOPPY_DRIVES_TURBO; lvc.fmt = LVCFMT_LEFT; if (ListView_InsertColumn(hwndList, 1, &lvc) == -1) - return FALSE; + return FALSE; + /* Check BPB */ lvc.iSubItem = 2; - lvc.pszText = plat_get_string(IDS_2087); + lvc.pszText = plat_get_string(IDS_BPB); - lvc.cx = 89; + lvc.cx = C_COLUMNS_FLOPPY_DRIVES_BPB; lvc.fmt = LVCFMT_LEFT; if (ListView_InsertColumn(hwndList, 2, &lvc) == -1) - return FALSE; + return FALSE; win_settings_floppy_drives_resize_columns(hdlg); return TRUE; } +#define C_COLUMNS_CDROM_DRIVES_BUS 292 +#define C_COLUMNS_CDROM_DRIVES_SPEED 58 +#define C_COLUMNS_CDROM_DRIVES_EARLIER 89 static void win_settings_cdrom_drives_resize_columns(HWND hdlg) { - int width[2] = {292, 147}; + int width[C_COLUMNS_CDROM_DRIVES] = { + C_COLUMNS_CDROM_DRIVES_BUS, + C_COLUMNS_CDROM_DRIVES_SPEED, + C_COLUMNS_CDROM_DRIVES_EARLIER + }; + int total = 0; HWND hwndList = GetDlgItem(hdlg, IDC_LIST_CDROM_DRIVES); RECT r; GetWindowRect(hwndList, &r); - width[0] = MulDiv(width[0], dpi, 96); - ListView_SetColumnWidth(hwndList, 0, MulDiv(width[0], dpi, 96)); - width[1] = (r.right - r.left) - 4 - width[0]; - ListView_SetColumnWidth(hwndList, 1, width[1]); + for (uint8_t iCol = 0; iCol < C_COLUMNS_CDROM_DRIVES; iCol++) { + width[iCol] = MulDiv(width[iCol], dpi, 96); + total += width[iCol]; + ListView_SetColumnWidth(hwndList, iCol, MulDiv(width[iCol], dpi, 96)); + } + width[C_COLUMNS_CDROM_DRIVES - 1] = (r.right - r.left) - 4 - total; + ListView_SetColumnWidth(hwndList, 2, width[C_COLUMNS_CDROM_DRIVES - 1]); } - static BOOL win_settings_cdrom_drives_init_columns(HWND hdlg) { LVCOLUMN lvc; - HWND hwndList = GetDlgItem(hdlg, IDC_LIST_CDROM_DRIVES); + HWND hwndList = GetDlgItem(hdlg, IDC_LIST_CDROM_DRIVES); lvc.mask = LVCF_FMT | LVCF_WIDTH | LVCF_TEXT | LVCF_SUBITEM; + /* Bus */ lvc.iSubItem = 0; - lvc.pszText = plat_get_string(IDS_2081); + lvc.pszText = plat_get_string(IDS_BUS); - lvc.cx = 292; + lvc.cx = C_COLUMNS_CDROM_DRIVES_BUS; lvc.fmt = LVCFMT_LEFT; if (ListView_InsertColumn(hwndList, 0, &lvc) == -1) - return FALSE; + return FALSE; + /* Speed */ lvc.iSubItem = 1; - lvc.pszText = plat_get_string(IDS_2053); + lvc.pszText = plat_get_string(IDS_2053); - lvc.cx = 147; + lvc.cx = C_COLUMNS_CDROM_DRIVES_SPEED; lvc.fmt = LVCFMT_LEFT; if (ListView_InsertColumn(hwndList, 1, &lvc) == -1) - return FALSE; + return FALSE; + + /* Type */ + lvc.iSubItem = 2; + lvc.pszText = plat_get_string(IDS_2162); + + lvc.cx = C_COLUMNS_CDROM_DRIVES_EARLIER; + lvc.fmt = LVCFMT_LEFT; + + if (ListView_InsertColumn(hwndList, 2, &lvc) == -1) + return FALSE; win_settings_cdrom_drives_resize_columns(hdlg); return TRUE; } +#define C_COLUMNS_MO_DRIVES_BUS 292 +#define C_COLUMNS_MO_DRIVES_TYPE 147 static void win_settings_mo_drives_resize_columns(HWND hdlg) { - int width[2] = {292, 147}; - HWND hwndList = GetDlgItem(hdlg, IDC_LIST_MO_DRIVES); + int width[C_COLUMNS_MO_DRIVES] = { + C_COLUMNS_MO_DRIVES_BUS, + C_COLUMNS_MO_DRIVES_TYPE + }; + HWND hwndList = GetDlgItem(hdlg, IDC_LIST_MO_DRIVES); RECT r; GetWindowRect(hwndList, &r); width[0] = MulDiv(width[0], dpi, 96); ListView_SetColumnWidth(hwndList, 0, MulDiv(width[0], dpi, 96)); - width[1] = (r.right - r.left) - 4 - width[0]; - ListView_SetColumnWidth(hwndList, 1, width[1]); + width[C_COLUMNS_MO_DRIVES - 1] = (r.right - r.left) - 4 - width[0]; + ListView_SetColumnWidth(hwndList, 1, width[C_COLUMNS_MO_DRIVES - 1]); } - static BOOL win_settings_mo_drives_init_columns(HWND hdlg) { LVCOLUMN lvc; - HWND hwndList = GetDlgItem(hdlg, IDC_LIST_MO_DRIVES); + HWND hwndList = GetDlgItem(hdlg, IDC_LIST_MO_DRIVES); lvc.mask = LVCF_FMT | LVCF_WIDTH | LVCF_TEXT | LVCF_SUBITEM; + /* Bus */ lvc.iSubItem = 0; - lvc.pszText = plat_get_string(IDS_2081); + lvc.pszText = plat_get_string(IDS_BUS); - lvc.cx = 292; + lvc.cx = C_COLUMNS_MO_DRIVES_BUS; lvc.fmt = LVCFMT_LEFT; if (ListView_InsertColumn(hwndList, 0, &lvc) == -1) - return FALSE; + return FALSE; + /* Type */ lvc.iSubItem = 1; - lvc.pszText = plat_get_string(IDS_2092); + lvc.pszText = plat_get_string(IDS_TYPE); - lvc.cx = 147; + lvc.cx = C_COLUMNS_MO_DRIVES_TYPE; lvc.fmt = LVCFMT_LEFT; if (ListView_InsertColumn(hwndList, 1, &lvc) == -1) - return FALSE; + return FALSE; win_settings_mo_drives_resize_columns(hdlg); return TRUE; } +#define C_COLUMNS_ZIP_DRIVES_BUS 292 +#define C_COLUMNS_ZIP_DRIVES_TYPE 147 static void win_settings_zip_drives_resize_columns(HWND hdlg) { - int width[2] = {292, 147}; - HWND hwndList = GetDlgItem(hdlg, IDC_LIST_ZIP_DRIVES); + int width[C_COLUMNS_ZIP_DRIVES] = { + C_COLUMNS_ZIP_DRIVES_BUS, + C_COLUMNS_ZIP_DRIVES_TYPE + }; + HWND hwndList = GetDlgItem(hdlg, IDC_LIST_ZIP_DRIVES); RECT r; GetWindowRect(hwndList, &r); width[0] = MulDiv(width[0], dpi, 96); ListView_SetColumnWidth(hwndList, 0, MulDiv(width[0], dpi, 96)); - width[1] = (r.right - r.left) - 4 - width[0]; - ListView_SetColumnWidth(hwndList, 1, width[1]); + width[C_COLUMNS_ZIP_DRIVES - 1] = (r.right - r.left) - 4 - width[0]; + ListView_SetColumnWidth(hwndList, 1, width[C_COLUMNS_ZIP_DRIVES - 1]); } - static BOOL win_settings_zip_drives_init_columns(HWND hdlg) { LVCOLUMN lvc; - HWND hwndList = GetDlgItem(hdlg, IDC_LIST_ZIP_DRIVES); + HWND hwndList = GetDlgItem(hdlg, IDC_LIST_ZIP_DRIVES); lvc.mask = LVCF_FMT | LVCF_WIDTH | LVCF_TEXT | LVCF_SUBITEM; + /* Bus */ lvc.iSubItem = 0; - lvc.pszText = plat_get_string(IDS_2081); + lvc.pszText = plat_get_string(IDS_BUS); - lvc.cx = 292; + lvc.cx = C_COLUMNS_ZIP_DRIVES_BUS; lvc.fmt = LVCFMT_LEFT; if (ListView_InsertColumn(hwndList, 0, &lvc) == -1) - return FALSE; + return FALSE; + /* Type */ lvc.iSubItem = 1; - lvc.pszText = plat_get_string(IDS_2092); + lvc.pszText = plat_get_string(IDS_TYPE); - lvc.cx = 147; + lvc.cx = C_COLUMNS_ZIP_DRIVES_TYPE; lvc.fmt = LVCFMT_LEFT; if (ListView_InsertColumn(hwndList, 1, &lvc) == -1) - return FALSE; + return FALSE; win_settings_zip_drives_resize_columns(hdlg); return TRUE; } - static int -get_selected_drive(HWND hdlg, int id) +get_selected_drive(HWND hdlg, int id, int max) { - int drive = -1; - int i, j = 0; + int drive = -1; + int j = 0; HWND h; - for (i = 0; i < 4; i++) { - h = GetDlgItem(hdlg, id); - j = ListView_GetItemState(h, i, LVIS_SELECTED); - if (j) - drive = i; + for (int i = 0; i < max; i++) { + h = GetDlgItem(hdlg, id); + j = ListView_GetItemState(h, i, LVIS_SELECTED); + if (j) + drive = i; } return drive; } - static void win_settings_floppy_drives_update_item(HWND hdlg, int i) { - LVITEM lvI; - char s[256], *t; - WCHAR szText[256]; - HWND hwndList = GetDlgItem(hdlg, IDC_LIST_FLOPPY_DRIVES); + LVITEM lvI; + char s[256]; + const char *t; + WCHAR szText[256]; + HWND hwndList = GetDlgItem(hdlg, IDC_LIST_FLOPPY_DRIVES); - lvI.mask = LVIF_TEXT | LVIF_IMAGE | LVIF_STATE; + lvI.mask = LVIF_TEXT | LVIF_IMAGE | LVIF_STATE; lvI.stateMask = lvI.iSubItem = lvI.state = 0; lvI.iSubItem = 0; - lvI.iItem = i; + lvI.iItem = i; if (temp_fdd_types[i] > 0) { - t = fdd_getname(temp_fdd_types[i]); - strncpy(s, t, sizeof(s) - 1); - mbstowcs(szText, s, strlen(s) + 1); - lvI.pszText = szText; + t = fdd_getname(temp_fdd_types[i]); + strncpy(s, t, sizeof(s) - 1); + mbstowcs(szText, s, strlen(s) + 1); + lvI.pszText = szText; } else - lvI.pszText = plat_get_string(IDS_5376); + lvI.pszText = plat_get_string(IDS_5376); lvI.iImage = temp_fdd_types[i]; if (ListView_SetItem(hwndList, &lvI) == -1) - return; + return; lvI.iSubItem = 1; - lvI.pszText = plat_get_string(temp_fdd_turbo[i] ? IDS_2060 : IDS_2061); - lvI.iItem = i; - lvI.iImage = 0; + lvI.pszText = plat_get_string(temp_fdd_turbo[i] ? IDS_2060 : IDS_2061); + lvI.iItem = i; + lvI.iImage = 0; if (ListView_SetItem(hwndList, &lvI) == -1) - return; + return; lvI.iSubItem = 2; - lvI.pszText = plat_get_string(temp_fdd_check_bpb[i] ? IDS_2060 : IDS_2061); - lvI.iItem = i; - lvI.iImage = 0; + lvI.pszText = plat_get_string(temp_fdd_check_bpb[i] ? IDS_2060 : IDS_2061); + lvI.iItem = i; + lvI.iImage = 0; if (ListView_SetItem(hwndList, &lvI) == -1) - return; + return; } - static void win_settings_cdrom_drives_update_item(HWND hdlg, int i) { LVITEM lvI; - WCHAR szText[256]; - int fsid; - HWND hwndList = GetDlgItem(hdlg, IDC_LIST_CDROM_DRIVES); + WCHAR szText[256]; + int fsid; + HWND hwndList = GetDlgItem(hdlg, IDC_LIST_CDROM_DRIVES); - lvI.mask = LVIF_TEXT | LVIF_IMAGE | LVIF_STATE; + lvI.mask = LVIF_TEXT | LVIF_IMAGE | LVIF_STATE; lvI.stateMask = lvI.iSubItem = lvI.state = 0; lvI.iSubItem = 0; - lvI.iItem = i; + lvI.iItem = i; fsid = combo_id_to_format_string_id(temp_cdrom[i].bus_type); switch (temp_cdrom[i].bus_type) { - case CDROM_BUS_DISABLED: - default: - lvI.pszText = plat_get_string(fsid); - lvI.iImage = 0; - break; - case CDROM_BUS_ATAPI: - wsprintf(szText, plat_get_string(fsid), temp_cdrom[i].ide_channel >> 1, temp_cdrom[i].ide_channel & 1); - lvI.pszText = szText; - lvI.iImage = 1; - break; - case CDROM_BUS_SCSI: - wsprintf(szText, plat_get_string(fsid), temp_cdrom[i].scsi_device_id >> 4, temp_cdrom[i].scsi_device_id & 15); - lvI.pszText = szText; - lvI.iImage = 1; - break; + default: + case CDROM_BUS_DISABLED: + lvI.pszText = plat_get_string(fsid); + lvI.iImage = 0; + break; + case CDROM_BUS_ATAPI: + wsprintf(szText, plat_get_string(fsid), temp_cdrom[i].ide_channel >> 1, temp_cdrom[i].ide_channel & 1); + lvI.pszText = szText; + lvI.iImage = 1; + break; + case CDROM_BUS_SCSI: + wsprintf(szText, plat_get_string(fsid), temp_cdrom[i].scsi_device_id >> 4, temp_cdrom[i].scsi_device_id & 15); + lvI.pszText = szText; + lvI.iImage = 1; + break; } if (ListView_SetItem(hwndList, &lvI) == -1) - return; + return; lvI.iSubItem = 1; if (temp_cdrom[i].bus_type == CDROM_BUS_DISABLED) - lvI.pszText = plat_get_string(IDS_2103); + lvI.pszText = plat_get_string(IDS_2104); else { - wsprintf(szText, L"%ix", temp_cdrom[i].speed); - lvI.pszText = szText; + wsprintf(szText, L"%ix", temp_cdrom[i].speed); + lvI.pszText = szText; } - lvI.iItem = i; + lvI.iItem = i; lvI.iImage = 0; if (ListView_SetItem(hwndList, &lvI) == -1) - return; -} + return; +#if 0 + lvI.iSubItem = 2; + lvI.pszText = plat_get_string(temp_cdrom[i].early ? IDS_2060 : IDS_2061); + lvI.iItem = i; + lvI.iImage = 0; + + if (ListView_SetItem(hwndList, &lvI) == -1) + return; +#endif +} static void win_settings_mo_drives_update_item(HWND hdlg, int i) { LVITEM lvI; - WCHAR szText[256]; - char szType[30]; - int fsid; - HWND hwndList = GetDlgItem(hdlg, IDC_LIST_MO_DRIVES); + WCHAR szText[256]; + char szType[30]; + int fsid; + HWND hwndList = GetDlgItem(hdlg, IDC_LIST_MO_DRIVES); - lvI.mask = LVIF_TEXT | LVIF_IMAGE | LVIF_STATE; + lvI.mask = LVIF_TEXT | LVIF_IMAGE | LVIF_STATE; lvI.stateMask = lvI.iSubItem = lvI.state = 0; + /* Bus */ lvI.iSubItem = 0; - lvI.iItem = i; + lvI.iItem = i; fsid = combo_id_to_format_string_id(temp_mo_drives[i].bus_type); switch (temp_mo_drives[i].bus_type) { - case MO_BUS_DISABLED: - default: - lvI.pszText = plat_get_string(fsid); - lvI.iImage = 0; - break; - case MO_BUS_ATAPI: - wsprintf(szText, plat_get_string(fsid), temp_mo_drives[i].ide_channel >> 1, temp_mo_drives[i].ide_channel & 1); - lvI.pszText = szText; - lvI.iImage = 1; - break; - case MO_BUS_SCSI: - wsprintf(szText, plat_get_string(fsid), temp_mo_drives[i].scsi_device_id >> 4, temp_mo_drives[i].scsi_device_id & 15); - lvI.pszText = szText; - lvI.iImage = 1; - break; + default: + case MO_BUS_DISABLED: + lvI.pszText = plat_get_string(fsid); + lvI.iImage = 0; + break; + case MO_BUS_ATAPI: + wsprintf(szText, plat_get_string(fsid), temp_mo_drives[i].ide_channel >> 1, temp_mo_drives[i].ide_channel & 1); + lvI.pszText = szText; + lvI.iImage = 1; + break; + case MO_BUS_SCSI: + wsprintf(szText, plat_get_string(fsid), temp_mo_drives[i].scsi_device_id >> 4, temp_mo_drives[i].scsi_device_id & 15); + lvI.pszText = szText; + lvI.iImage = 1; + break; } if (ListView_SetItem(hwndList, &lvI) == -1) - return; + return; + /* Type */ lvI.iSubItem = 1; if (temp_mo_drives[i].bus_type == MO_BUS_DISABLED) - lvI.pszText = plat_get_string(IDS_2103); + lvI.pszText = plat_get_string(IDS_2104); else { - memset(szType, 0, 30); - memcpy(szType, mo_drive_types[temp_mo_drives[i].type].vendor, 8); - szType[strlen(szType)] = ' '; - memcpy(szType + strlen(szType), mo_drive_types[temp_mo_drives[i].type].model, 16); - szType[strlen(szType)] = ' '; - memcpy(szType + strlen(szType), mo_drive_types[temp_mo_drives[i].type].revision, 4); - mbstowcs(szText, szType, strlen(szType)+1); - lvI.pszText = szText; + memset(szType, 0, 30); + memcpy(szType, mo_drive_types[temp_mo_drives[i].type].vendor, 8); + szType[strlen(szType)] = ' '; + memcpy(szType + strlen(szType), mo_drive_types[temp_mo_drives[i].type].model, 16); + szType[strlen(szType)] = ' '; + memcpy(szType + strlen(szType), mo_drive_types[temp_mo_drives[i].type].revision, 4); + mbstowcs(szText, szType, strlen(szType) + 1); + lvI.pszText = szText; } - lvI.iItem = i; + lvI.iItem = i; lvI.iImage = 0; if (ListView_SetItem(hwndList, &lvI) == -1) - return; + return; } - static void win_settings_zip_drives_update_item(HWND hdlg, int i) { LVITEM lvI; - WCHAR szText[256]; - int fsid; - HWND hwndList = GetDlgItem(hdlg, IDC_LIST_ZIP_DRIVES); + WCHAR szText[256]; + int fsid; + HWND hwndList = GetDlgItem(hdlg, IDC_LIST_ZIP_DRIVES); - lvI.mask = LVIF_TEXT | LVIF_IMAGE | LVIF_STATE; + lvI.mask = LVIF_TEXT | LVIF_IMAGE | LVIF_STATE; lvI.stateMask = lvI.iSubItem = lvI.state = 0; lvI.iSubItem = 0; - lvI.iItem = i; + lvI.iItem = i; fsid = combo_id_to_format_string_id(temp_zip_drives[i].bus_type); switch (temp_zip_drives[i].bus_type) { - case ZIP_BUS_DISABLED: - default: - lvI.pszText = plat_get_string(fsid); - lvI.iImage = 0; - break; - case ZIP_BUS_ATAPI: - wsprintf(szText, plat_get_string(fsid), temp_zip_drives[i].ide_channel >> 1, temp_zip_drives[i].ide_channel & 1); - lvI.pszText = szText; - lvI.iImage = 1; - break; - case ZIP_BUS_SCSI: - wsprintf(szText, plat_get_string(fsid), temp_zip_drives[i].scsi_device_id >> 4, temp_zip_drives[i].scsi_device_id & 15); - lvI.pszText = szText; - lvI.iImage = 1; - break; + default: + case ZIP_BUS_DISABLED: + lvI.pszText = plat_get_string(fsid); + lvI.iImage = 0; + break; + case ZIP_BUS_ATAPI: + wsprintf(szText, plat_get_string(fsid), temp_zip_drives[i].ide_channel >> 1, temp_zip_drives[i].ide_channel & 1); + lvI.pszText = szText; + lvI.iImage = 1; + break; + case ZIP_BUS_SCSI: + wsprintf(szText, plat_get_string(fsid), temp_zip_drives[i].scsi_device_id >> 4, temp_zip_drives[i].scsi_device_id & 15); + lvI.pszText = szText; + lvI.iImage = 1; + break; } if (ListView_SetItem(hwndList, &lvI) == -1) - return; + return; lvI.iSubItem = 1; - lvI.pszText = plat_get_string(temp_zip_drives[i].is_250 ? IDS_5901 : IDS_5900); - lvI.iItem = i; - lvI.iImage = 0; + lvI.pszText = plat_get_string(temp_zip_drives[i].is_250 ? IDS_5901 : IDS_5900); + lvI.iItem = i; + lvI.iImage = 0; if (ListView_SetItem(hwndList, &lvI) == -1) - return; + return; } - static void cdrom_add_locations(HWND hdlg) { LPTSTR lptsTemp; - int i = 0; + int i = 0; lptsTemp = (LPTSTR) malloc(512 * sizeof(WCHAR)); for (i = CDROM_BUS_DISABLED; i <= CDROM_BUS_SCSI; i++) { - if ((i == CDROM_BUS_DISABLED) || (i >= CDROM_BUS_ATAPI)) - settings_add_string(hdlg, IDC_COMBO_CD_BUS, win_get_string(combo_id_to_string_id(i))); + if ((i == CDROM_BUS_DISABLED) || (i >= CDROM_BUS_ATAPI)) + settings_add_string(hdlg, IDC_COMBO_CD_BUS, win_get_string(combo_id_to_string_id(i))); } for (i = 1; i <= 72; i++) { - wsprintf(lptsTemp, L"%ix", i); - settings_add_string(hdlg, IDC_COMBO_CD_SPEED, (LPARAM) lptsTemp); + wsprintf(lptsTemp, L"%ix", i); + settings_add_string(hdlg, IDC_COMBO_CD_SPEED, (LPARAM) lptsTemp); } - for (i = 0; i < 64; i++) { - wsprintf(lptsTemp, plat_get_string(IDS_4135), i >> 4, i & 15); - settings_add_string(hdlg, IDC_COMBO_CD_ID, (LPARAM) lptsTemp); + for (i = 0; i < (SCSI_BUS_MAX * SCSI_ID_MAX); i++) { + wsprintf(lptsTemp, plat_get_string(IDS_4135), i >> 4, i & 15); + settings_add_string(hdlg, IDC_COMBO_CD_ID, (LPARAM) lptsTemp); } - for (i = 0; i < 8; i++) { - wsprintf(lptsTemp, plat_get_string(IDS_4097), i >> 1, i & 1); - settings_add_string(hdlg, IDC_COMBO_CD_CHANNEL_IDE, (LPARAM) lptsTemp); + for (i = 0; i < (IDE_BUS_MAX * IDE_CHAN_MAX); i++) { + wsprintf(lptsTemp, plat_get_string(IDS_4097), i >> 1, i & 1); + settings_add_string(hdlg, IDC_COMBO_CD_CHANNEL_IDE, (LPARAM) lptsTemp); } free(lptsTemp); } - static void cdrom_recalc_location_controls(HWND hdlg, int assign_id) { - int i = 0; int bus = temp_cdrom[lv2_current_sel].bus_type; - for (i = IDT_CD_ID; i <= (IDT_CD_LUN); i++) - settings_show_window(hdlg, i, FALSE); + for (uint16_t i = IDT_CD_ID; i <= IDT_CD_CHANNEL; i++) + settings_show_window(hdlg, i, FALSE); settings_show_window(hdlg, IDC_COMBO_CD_ID, FALSE); settings_show_window(hdlg, IDC_COMBO_CD_CHANNEL_IDE, FALSE); settings_show_window(hdlg, IDC_COMBO_CD_SPEED, bus != CDROM_BUS_DISABLED); settings_show_window(hdlg, IDT_CD_SPEED, bus != CDROM_BUS_DISABLED); +#if 0 + settings_show_window(hdlg, IDC_COMBO_CD_TYPE, bus != CDROM_BUS_DISABLED); +#endif + if (bus != CDROM_BUS_DISABLED) { + settings_set_cur_sel(hdlg, IDC_COMBO_CD_SPEED, temp_cdrom[lv2_current_sel].speed - 1); +#if 0 + settings_set_check(hdlg, IDC_COMBO_CD_TYPE, temp_cdrom[lv2_current_sel].early); +#endif + } - if (bus != CDROM_BUS_DISABLED) - settings_set_cur_sel(hdlg, IDC_COMBO_CD_SPEED, temp_cdrom[lv2_current_sel].speed - 1); + switch (bus) { + case CDROM_BUS_ATAPI: /* ATAPI */ + settings_show_window(hdlg, IDT_CD_CHANNEL, TRUE); + settings_show_window(hdlg, IDC_COMBO_CD_CHANNEL_IDE, TRUE); - switch(bus) { - case CDROM_BUS_ATAPI: /* ATAPI */ - settings_show_window(hdlg, IDT_CD_LUN, TRUE); - settings_show_window(hdlg, IDC_COMBO_CD_CHANNEL_IDE, TRUE); + if (assign_id) + temp_cdrom[lv2_current_sel].ide_channel = next_free_ide_channel(); - if (assign_id) - temp_cdrom[lv2_current_sel].ide_channel = next_free_ide_channel(); + settings_set_cur_sel(hdlg, IDC_COMBO_CD_CHANNEL_IDE, temp_cdrom[lv2_current_sel].ide_channel); + break; + case CDROM_BUS_SCSI: /* SCSI */ + settings_show_window(hdlg, IDT_CD_ID, TRUE); + settings_show_window(hdlg, IDC_COMBO_CD_ID, TRUE); - settings_set_cur_sel(hdlg, IDC_COMBO_CD_CHANNEL_IDE, temp_cdrom[lv2_current_sel].ide_channel); - break; - case CDROM_BUS_SCSI: /* SCSI */ - settings_show_window(hdlg, IDT_CD_ID, TRUE); - settings_show_window(hdlg, IDC_COMBO_CD_ID, TRUE); + if (assign_id) + next_free_scsi_id(&temp_cdrom[lv2_current_sel].scsi_device_id); - if (assign_id) - next_free_scsi_id((uint8_t *) &temp_cdrom[lv2_current_sel].scsi_device_id); - - settings_set_cur_sel(hdlg, IDC_COMBO_CD_ID, temp_cdrom[lv2_current_sel].scsi_device_id); - break; + settings_set_cur_sel(hdlg, IDC_COMBO_CD_ID, temp_cdrom[lv2_current_sel].scsi_device_id); + break; } } - static void mo_add_locations(HWND hdlg) { LPTSTR lptsTemp; - char *temp; - int i = 0; + char *temp; + int i = 0; lptsTemp = (LPTSTR) malloc(512 * sizeof(WCHAR)); - temp = (char*) malloc(30*sizeof(char)); + temp = (char *) malloc(30 * sizeof(char)); for (i = MO_BUS_DISABLED; i <= MO_BUS_SCSI; i++) { - if ((i == MO_BUS_DISABLED) || (i >= MO_BUS_ATAPI)) - settings_add_string(hdlg, IDC_COMBO_MO_BUS, win_get_string(combo_id_to_string_id(i))); + if ((i == MO_BUS_DISABLED) || (i >= MO_BUS_ATAPI)) + settings_add_string(hdlg, IDC_COMBO_MO_BUS, win_get_string(combo_id_to_string_id(i))); } - for (i = 0; i < 64; i++) { - wsprintf(lptsTemp, plat_get_string(IDS_4135), i >> 4, i & 15); - settings_add_string(hdlg, IDC_COMBO_MO_ID, (LPARAM) lptsTemp); + for (i = 0; i < (SCSI_BUS_MAX * SCSI_ID_MAX); i++) { + wsprintf(lptsTemp, plat_get_string(IDS_4135), i >> 4, i & 15); + settings_add_string(hdlg, IDC_COMBO_MO_ID, (LPARAM) lptsTemp); } - for (i = 0; i < 8; i++) { - wsprintf(lptsTemp, plat_get_string(IDS_4097), i >> 1, i & 1); - settings_add_string(hdlg, IDC_COMBO_MO_CHANNEL_IDE, (LPARAM) lptsTemp); + for (i = 0; i < (IDE_BUS_MAX * IDE_CHAN_MAX); i++) { + wsprintf(lptsTemp, plat_get_string(IDS_4097), i >> 1, i & 1); + settings_add_string(hdlg, IDC_COMBO_MO_CHANNEL_IDE, (LPARAM) lptsTemp); } for (int i = 0; i < KNOWN_MO_DRIVE_TYPES; i++) { - memset(temp, 0, 30); - memcpy(temp, mo_drive_types[i].vendor, 8); - temp[strlen(temp)] = ' '; - memcpy(temp + strlen(temp), mo_drive_types[i].model, 16); - temp[strlen(temp)] = ' '; - memcpy(temp + strlen(temp), mo_drive_types[i].revision, 4); + memset(temp, 0, 30); + memcpy(temp, mo_drive_types[i].vendor, 8); + temp[strlen(temp)] = ' '; + memcpy(temp + strlen(temp), mo_drive_types[i].model, 16); + temp[strlen(temp)] = ' '; + memcpy(temp + strlen(temp), mo_drive_types[i].revision, 4); - mbstowcs(lptsTemp, temp, strlen(temp)+1); - settings_add_string(hdlg, IDC_COMBO_MO_TYPE, (LPARAM) lptsTemp); + mbstowcs(lptsTemp, temp, strlen(temp) + 1); + settings_add_string(hdlg, IDC_COMBO_MO_TYPE, (LPARAM) lptsTemp); } free(temp); free(lptsTemp); } - static void mo_recalc_location_controls(HWND hdlg, int assign_id) { - int i = 0; int bus = temp_mo_drives[lv1_current_sel].bus_type; - for (i = IDT_MO_ID; i <= (IDT_MO_CHANNEL); i++) - settings_show_window(hdlg, i, FALSE); + for (int i = IDT_MO_ID; i <= IDT_MO_CHANNEL; i++) + settings_show_window(hdlg, i, FALSE); settings_show_window(hdlg, IDC_COMBO_MO_ID, FALSE); settings_show_window(hdlg, IDC_COMBO_MO_CHANNEL_IDE, FALSE); settings_show_window(hdlg, IDC_COMBO_MO_TYPE, bus != MO_BUS_DISABLED); settings_show_window(hdlg, IDT_MO_TYPE, bus != MO_BUS_DISABLED); if (bus != MO_BUS_DISABLED) - settings_set_cur_sel(hdlg, IDC_COMBO_MO_TYPE, temp_mo_drives[lv1_current_sel].type); + settings_set_cur_sel(hdlg, IDC_COMBO_MO_TYPE, temp_mo_drives[lv1_current_sel].type); - switch(bus) { - case MO_BUS_ATAPI: /* ATAPI */ - settings_show_window(hdlg, IDT_MO_CHANNEL, TRUE); - settings_show_window(hdlg, IDC_COMBO_MO_CHANNEL_IDE, TRUE); + switch (bus) { + case MO_BUS_ATAPI: /* ATAPI */ + settings_show_window(hdlg, IDT_MO_CHANNEL, TRUE); + settings_show_window(hdlg, IDC_COMBO_MO_CHANNEL_IDE, TRUE); - if (assign_id) - temp_mo_drives[lv1_current_sel].ide_channel = next_free_ide_channel(); + if (assign_id) + temp_mo_drives[lv1_current_sel].ide_channel = next_free_ide_channel(); - settings_set_cur_sel(hdlg, IDC_COMBO_MO_CHANNEL_IDE, temp_mo_drives[lv1_current_sel].ide_channel); - break; - case MO_BUS_SCSI: /* SCSI */ - settings_show_window(hdlg, IDT_MO_ID, TRUE); - settings_show_window(hdlg, IDC_COMBO_MO_ID, TRUE); + settings_set_cur_sel(hdlg, IDC_COMBO_MO_CHANNEL_IDE, temp_mo_drives[lv1_current_sel].ide_channel); + break; + case MO_BUS_SCSI: /* SCSI */ + settings_show_window(hdlg, IDT_MO_ID, TRUE); + settings_show_window(hdlg, IDC_COMBO_MO_ID, TRUE); - if (assign_id) - next_free_scsi_id((uint8_t *) &temp_mo_drives[lv1_current_sel].scsi_device_id); + if (assign_id) + next_free_scsi_id(&temp_mo_drives[lv1_current_sel].scsi_device_id); - settings_set_cur_sel(hdlg, IDC_COMBO_MO_ID, temp_mo_drives[lv1_current_sel].scsi_device_id); - break; + settings_set_cur_sel(hdlg, IDC_COMBO_MO_ID, temp_mo_drives[lv1_current_sel].scsi_device_id); + break; } } - static void zip_add_locations(HWND hdlg) { LPTSTR lptsTemp; - int i = 0; + int i = 0; lptsTemp = (LPTSTR) malloc(512 * sizeof(WCHAR)); for (i = ZIP_BUS_DISABLED; i <= ZIP_BUS_SCSI; i++) { - if ((i == ZIP_BUS_DISABLED) || (i >= ZIP_BUS_ATAPI)) - settings_add_string(hdlg, IDC_COMBO_ZIP_BUS, win_get_string(combo_id_to_string_id(i))); + if ((i == ZIP_BUS_DISABLED) || (i >= ZIP_BUS_ATAPI)) + settings_add_string(hdlg, IDC_COMBO_ZIP_BUS, win_get_string(combo_id_to_string_id(i))); } - for (i = 0; i < 64; i++) { - wsprintf(lptsTemp, plat_get_string(IDS_4135), i >> 4, i & 15); - settings_add_string(hdlg, IDC_COMBO_ZIP_ID, (LPARAM) lptsTemp); + for (i = 0; i < (SCSI_BUS_MAX * SCSI_LUN_MAX); i++) { + wsprintf(lptsTemp, plat_get_string(IDS_4135), i >> 4, i & 15); + settings_add_string(hdlg, IDC_COMBO_ZIP_ID, (LPARAM) lptsTemp); } - for (i = 0; i < 8; i++) { - wsprintf(lptsTemp, plat_get_string(IDS_4097), i >> 1, i & 1); - settings_add_string(hdlg, IDC_COMBO_ZIP_CHANNEL_IDE, (LPARAM) lptsTemp); + for (i = 0; i < (IDE_BUS_MAX * IDE_CHAN_MAX); i++) { + wsprintf(lptsTemp, plat_get_string(IDS_4097), i >> 1, i & 1); + settings_add_string(hdlg, IDC_COMBO_ZIP_CHANNEL_IDE, (LPARAM) lptsTemp); } free(lptsTemp); } - static void zip_recalc_location_controls(HWND hdlg, int assign_id) { - int i = 0; - int bus = temp_zip_drives[lv2_current_sel].bus_type; - for (i = IDT_ZIP_ID; i <= (IDT_ZIP_LUN); i++) - settings_show_window(hdlg, i, FALSE); + for (int i = IDT_ZIP_ID; i <= IDT_ZIP_LUN; i++) + settings_show_window(hdlg, i, FALSE); settings_show_window(hdlg, IDC_COMBO_ZIP_ID, FALSE); settings_show_window(hdlg, IDC_COMBO_ZIP_CHANNEL_IDE, FALSE); settings_show_window(hdlg, IDC_CHECK250, bus != ZIP_BUS_DISABLED); if (bus != ZIP_BUS_DISABLED) - settings_set_check(hdlg, IDC_CHECK250, temp_zip_drives[lv2_current_sel].is_250); + settings_set_check(hdlg, IDC_CHECK250, temp_zip_drives[lv2_current_sel].is_250); - switch(bus) { - case ZIP_BUS_ATAPI: /* ATAPI */ - settings_show_window(hdlg, IDT_ZIP_LUN, TRUE); - settings_show_window(hdlg, IDC_COMBO_ZIP_CHANNEL_IDE, TRUE); + switch (bus) { + case ZIP_BUS_ATAPI: /* ATAPI */ + settings_show_window(hdlg, IDT_ZIP_LUN, TRUE); + settings_show_window(hdlg, IDC_COMBO_ZIP_CHANNEL_IDE, TRUE); - if (assign_id) - temp_zip_drives[lv2_current_sel].ide_channel = next_free_ide_channel(); + if (assign_id) + temp_zip_drives[lv2_current_sel].ide_channel = next_free_ide_channel(); - settings_set_cur_sel(hdlg, IDC_COMBO_ZIP_CHANNEL_IDE, temp_zip_drives[lv2_current_sel].ide_channel); - break; - case ZIP_BUS_SCSI: /* SCSI */ - settings_show_window(hdlg, IDT_ZIP_ID, TRUE); - settings_show_window(hdlg, IDC_COMBO_ZIP_ID, TRUE); + settings_set_cur_sel(hdlg, IDC_COMBO_ZIP_CHANNEL_IDE, temp_zip_drives[lv2_current_sel].ide_channel); + break; + case ZIP_BUS_SCSI: /* SCSI */ + settings_show_window(hdlg, IDT_ZIP_ID, TRUE); + settings_show_window(hdlg, IDC_COMBO_ZIP_ID, TRUE); - if (assign_id) - next_free_scsi_id((uint8_t *) &temp_zip_drives[lv2_current_sel].scsi_device_id); + if (assign_id) + next_free_scsi_id(&temp_zip_drives[lv2_current_sel].scsi_device_id); - settings_set_cur_sel(hdlg, IDC_COMBO_ZIP_ID, temp_zip_drives[lv2_current_sel].scsi_device_id); - break; + settings_set_cur_sel(hdlg, IDC_COMBO_ZIP_ID, temp_zip_drives[lv2_current_sel].scsi_device_id); + break; } } - static void cdrom_track(uint8_t id) { if (temp_cdrom[id].bus_type == CDROM_BUS_ATAPI) - ide_tracking |= (2 << (temp_cdrom[id].ide_channel << 3)); + ide_tracking |= (2 << (temp_cdrom[id].ide_channel << 3)); else if (temp_cdrom[id].bus_type == CDROM_BUS_SCSI) - scsi_tracking[temp_cdrom[id].scsi_device_id >> 3] |= (1 << (temp_cdrom[id].scsi_device_id & 0x07)); + scsi_tracking[temp_cdrom[id].scsi_device_id >> 3] |= (1 << (temp_cdrom[id].scsi_device_id & 0x07)); } - static void cdrom_untrack(uint8_t id) { if (temp_cdrom[id].bus_type == CDROM_BUS_ATAPI) - ide_tracking &= ~(2 << (temp_cdrom[id].ide_channel << 3)); + ide_tracking &= ~(2 << (temp_cdrom[id].ide_channel << 3)); else if (temp_cdrom[id].bus_type == CDROM_BUS_SCSI) - scsi_tracking[temp_cdrom[id].scsi_device_id >> 3] &= ~(1 << (temp_cdrom[id].scsi_device_id & 0x07)); + scsi_tracking[temp_cdrom[id].scsi_device_id >> 3] &= ~(1 << (temp_cdrom[id].scsi_device_id & 0x07)); } - static void zip_track(uint8_t id) { if (temp_zip_drives[id].bus_type == ZIP_BUS_ATAPI) - ide_tracking |= (1 << temp_zip_drives[id].ide_channel); + ide_tracking |= (1 << temp_zip_drives[id].ide_channel); else if (temp_zip_drives[id].bus_type == ZIP_BUS_SCSI) - scsi_tracking[temp_zip_drives[id].scsi_device_id >> 3] |= (1 << (temp_zip_drives[id].scsi_device_id & 0x07)); + scsi_tracking[temp_zip_drives[id].scsi_device_id >> 3] |= (1 << (temp_zip_drives[id].scsi_device_id & 0x07)); } - static void zip_untrack(uint8_t id) { if (temp_zip_drives[id].bus_type == ZIP_BUS_ATAPI) - ide_tracking &= ~(1 << temp_zip_drives[id].ide_channel); + ide_tracking &= ~(1 << temp_zip_drives[id].ide_channel); else if (temp_zip_drives[id].bus_type == ZIP_BUS_SCSI) - scsi_tracking[temp_zip_drives[id].scsi_device_id >> 3] &= ~(1 << (temp_zip_drives[id].scsi_device_id & 0x07)); + scsi_tracking[temp_zip_drives[id].scsi_device_id >> 3] &= ~(1 << (temp_zip_drives[id].scsi_device_id & 0x07)); } - static void mo_track(uint8_t id) { if (temp_mo_drives[id].bus_type == MO_BUS_ATAPI) - ide_tracking |= (1 << (temp_zip_drives[id].ide_channel << 3)); + ide_tracking |= (1 << (temp_mo_drives[id].ide_channel << 3)); else if (temp_mo_drives[id].bus_type == MO_BUS_SCSI) - scsi_tracking[temp_mo_drives[id].scsi_device_id >> 3] |= (1 << (temp_mo_drives[id].scsi_device_id & 0x07)); + scsi_tracking[temp_mo_drives[id].scsi_device_id >> 3] |= (1 << (temp_mo_drives[id].scsi_device_id & 0x07)); } - static void mo_untrack(uint8_t id) { if (temp_mo_drives[id].bus_type == MO_BUS_ATAPI) - ide_tracking &= ~(1 << (temp_zip_drives[id].ide_channel << 3)); + ide_tracking &= ~(1 << (temp_mo_drives[id].ide_channel << 3)); else if (temp_mo_drives[id].bus_type == MO_BUS_SCSI) - scsi_tracking[temp_mo_drives[id].scsi_device_id >> 3] &= ~(1 << (temp_mo_drives[id].scsi_device_id & 0x07)); + scsi_tracking[temp_mo_drives[id].scsi_device_id >> 3] &= ~(1 << (temp_mo_drives[id].scsi_device_id & 0x07)); } - #if defined(__amd64__) || defined(__aarch64__) static LRESULT CALLBACK #else @@ -4474,184 +4945,192 @@ static BOOL CALLBACK #endif win_settings_floppy_and_cdrom_drives_proc(HWND hdlg, UINT message, WPARAM wParam, LPARAM lParam) { - int i = 0, old_sel = 0, b = 0, assign = 0; - uint32_t b2 = 0; - WCHAR szText[256]; + int old_sel = 0; + int b = 0; + int assign = 0; + uint32_t b2 = 0; + WCHAR szText[256]; const uint8_t fd_icons[15] = { 248, 16, 16, 16, 16, 16, 16, 24, 24, 24, 24, 24, 24, 24, 0 }; - const uint8_t cd_icons[3] = { 249, 32, 0 }; + const uint8_t cd_icons[3] = { 249, 32, 0 }; switch (message) { - case WM_INITDIALOG: - ignore_change = 1; + case WM_INITDIALOG: + ignore_change = 1; - lv1_current_sel = 0; - win_settings_floppy_drives_init_columns(hdlg); - image_list_init(hdlg, IDC_LIST_FLOPPY_DRIVES, (const uint8_t *) fd_icons); - win_settings_floppy_drives_recalc_list(hdlg); - settings_listview_select(hdlg, IDC_LIST_FLOPPY_DRIVES, 0); - for (i = 0; i < 14; i++) { - if (i == 0) - settings_add_string(hdlg, IDC_COMBO_FD_TYPE, win_get_string(IDS_5376)); - else { - mbstowcs(szText, fdd_getname(i), strlen(fdd_getname(i)) + 1); - settings_add_string(hdlg, IDC_COMBO_FD_TYPE, (LPARAM) szText); - } - } - settings_set_cur_sel(hdlg, IDC_COMBO_FD_TYPE, temp_fdd_types[lv1_current_sel]); + lv1_current_sel = 0; + win_settings_floppy_drives_init_columns(hdlg); + image_list_init(hdlg, IDC_LIST_FLOPPY_DRIVES, (const uint8_t *) fd_icons); + win_settings_floppy_drives_recalc_list(hdlg); + settings_listview_select(hdlg, IDC_LIST_FLOPPY_DRIVES, 0); + for (uint8_t i = 0; i < 14; i++) { + if (i == 0) + settings_add_string(hdlg, IDC_COMBO_FD_TYPE, win_get_string(IDS_5376)); + else { + mbstowcs(szText, fdd_getname(i), strlen(fdd_getname(i)) + 1); + settings_add_string(hdlg, IDC_COMBO_FD_TYPE, (LPARAM) szText); + } + } + settings_set_cur_sel(hdlg, IDC_COMBO_FD_TYPE, temp_fdd_types[lv1_current_sel]); - settings_set_check(hdlg, IDC_CHECKTURBO, temp_fdd_turbo[lv1_current_sel]); - settings_set_check(hdlg, IDC_CHECKBPB, temp_fdd_check_bpb[lv1_current_sel]); + settings_set_check(hdlg, IDC_CHECKTURBO, temp_fdd_turbo[lv1_current_sel]); + settings_set_check(hdlg, IDC_CHECKBPB, temp_fdd_check_bpb[lv1_current_sel]); - settings_listview_enable_styles(hdlg, IDC_LIST_FLOPPY_DRIVES); + settings_listview_enable_styles(hdlg, IDC_LIST_FLOPPY_DRIVES); - lv2_current_sel = 0; - win_settings_cdrom_drives_init_columns(hdlg); - image_list_init(hdlg, IDC_LIST_CDROM_DRIVES, (const uint8_t *) cd_icons); - win_settings_cdrom_drives_recalc_list(hdlg); - settings_listview_select(hdlg, IDC_LIST_CDROM_DRIVES, 0); - cdrom_add_locations(hdlg); + lv2_current_sel = 0; + win_settings_cdrom_drives_init_columns(hdlg); + image_list_init(hdlg, IDC_LIST_CDROM_DRIVES, (const uint8_t *) cd_icons); + win_settings_cdrom_drives_recalc_list(hdlg); + settings_listview_select(hdlg, IDC_LIST_CDROM_DRIVES, 0); + cdrom_add_locations(hdlg); - switch (temp_cdrom[lv2_current_sel].bus_type) { - case CDROM_BUS_DISABLED: - default: - b = 0; - break; - case CDROM_BUS_ATAPI: - b = 1; - break; - case CDROM_BUS_SCSI: - b = 2; - break; - } - settings_set_cur_sel(hdlg, IDC_COMBO_CD_BUS, b); - cdrom_recalc_location_controls(hdlg, 0); + switch (temp_cdrom[lv2_current_sel].bus_type) { + default: + case CDROM_BUS_DISABLED: + b = 0; + break; + case CDROM_BUS_ATAPI: + b = 1; + break; + case CDROM_BUS_SCSI: + b = 2; + break; + } + settings_set_cur_sel(hdlg, IDC_COMBO_CD_BUS, b); + cdrom_recalc_location_controls(hdlg, 0); - settings_listview_enable_styles(hdlg, IDC_LIST_CDROM_DRIVES); + settings_listview_enable_styles(hdlg, IDC_LIST_CDROM_DRIVES); - ignore_change = 0; - return TRUE; + ignore_change = 0; + return TRUE; - case WM_NOTIFY: - if (ignore_change) - return FALSE; + case WM_NOTIFY: + if (ignore_change) + return FALSE; - if ((((LPNMHDR)lParam)->code == LVN_ITEMCHANGED) && (((LPNMHDR)lParam)->idFrom == IDC_LIST_FLOPPY_DRIVES)) { - old_sel = lv1_current_sel; - lv1_current_sel = get_selected_drive(hdlg, IDC_LIST_FLOPPY_DRIVES); - if (lv1_current_sel == old_sel) - return FALSE; - ignore_change = 1; - settings_set_cur_sel(hdlg, IDC_COMBO_FD_TYPE, temp_fdd_types[lv1_current_sel]); - settings_set_check(hdlg, IDC_CHECKTURBO, temp_fdd_turbo[lv1_current_sel]); - settings_set_check(hdlg, IDC_CHECKBPB, temp_fdd_check_bpb[lv1_current_sel]); - ignore_change = 0; - } else if ((((LPNMHDR)lParam)->code == LVN_ITEMCHANGED) && (((LPNMHDR)lParam)->idFrom == IDC_LIST_CDROM_DRIVES)) { - old_sel = lv2_current_sel; - lv2_current_sel = get_selected_drive(hdlg, IDC_LIST_CDROM_DRIVES); - if (lv2_current_sel == old_sel) - return FALSE; - ignore_change = 1; + if ((((LPNMHDR) lParam)->code == LVN_ITEMCHANGED) && (((LPNMHDR) lParam)->idFrom == IDC_LIST_FLOPPY_DRIVES)) { + old_sel = lv1_current_sel; + lv1_current_sel = get_selected_drive(hdlg, IDC_LIST_FLOPPY_DRIVES, FDD_NUM); + if (lv1_current_sel == old_sel) + return FALSE; + ignore_change = 1; + settings_set_cur_sel(hdlg, IDC_COMBO_FD_TYPE, temp_fdd_types[lv1_current_sel]); + settings_set_check(hdlg, IDC_CHECKTURBO, temp_fdd_turbo[lv1_current_sel]); + settings_set_check(hdlg, IDC_CHECKBPB, temp_fdd_check_bpb[lv1_current_sel]); + ignore_change = 0; + } else if ((((LPNMHDR) lParam)->code == LVN_ITEMCHANGED) && (((LPNMHDR) lParam)->idFrom == IDC_LIST_CDROM_DRIVES)) { + old_sel = lv2_current_sel; + lv2_current_sel = get_selected_drive(hdlg, IDC_LIST_CDROM_DRIVES, CDROM_NUM); + if (lv2_current_sel == old_sel) + return FALSE; + ignore_change = 1; - switch (temp_cdrom[lv2_current_sel].bus_type) { - case CDROM_BUS_DISABLED: - default: - b = 0; - break; - case CDROM_BUS_ATAPI: - b = 1; - break; - case CDROM_BUS_SCSI: - b = 2; - break; - } - settings_set_cur_sel(hdlg, IDC_COMBO_CD_BUS, b); + switch (temp_cdrom[lv2_current_sel].bus_type) { + default: + case CDROM_BUS_DISABLED: + b = 0; + break; + case CDROM_BUS_ATAPI: + b = 1; + break; + case CDROM_BUS_SCSI: + b = 2; + break; + } + settings_set_cur_sel(hdlg, IDC_COMBO_CD_BUS, b); - cdrom_recalc_location_controls(hdlg, 0); - ignore_change = 0; - } - break; + cdrom_recalc_location_controls(hdlg, 0); + ignore_change = 0; + } + break; - case WM_COMMAND: - if (ignore_change) - return FALSE; + case WM_COMMAND: + if (ignore_change) + return FALSE; - ignore_change = 1; - switch (LOWORD(wParam)) { - case IDC_COMBO_FD_TYPE: - temp_fdd_types[lv1_current_sel] = settings_get_cur_sel(hdlg, IDC_COMBO_FD_TYPE); - win_settings_floppy_drives_update_item(hdlg, lv1_current_sel); - break; + ignore_change = 1; + switch (LOWORD(wParam)) { + case IDC_COMBO_FD_TYPE: + temp_fdd_types[lv1_current_sel] = settings_get_cur_sel(hdlg, IDC_COMBO_FD_TYPE); + win_settings_floppy_drives_update_item(hdlg, lv1_current_sel); + break; - case IDC_CHECKTURBO: - temp_fdd_turbo[lv1_current_sel] = settings_get_check(hdlg, IDC_CHECKTURBO); - win_settings_floppy_drives_update_item(hdlg, lv1_current_sel); - break; + case IDC_CHECKTURBO: + temp_fdd_turbo[lv1_current_sel] = settings_get_check(hdlg, IDC_CHECKTURBO); + win_settings_floppy_drives_update_item(hdlg, lv1_current_sel); + break; - case IDC_CHECKBPB: - temp_fdd_check_bpb[lv1_current_sel] = settings_get_check(hdlg, IDC_CHECKBPB); - win_settings_floppy_drives_update_item(hdlg, lv1_current_sel); - break; + case IDC_CHECKBPB: + temp_fdd_check_bpb[lv1_current_sel] = settings_get_check(hdlg, IDC_CHECKBPB); + win_settings_floppy_drives_update_item(hdlg, lv1_current_sel); + break; - case IDC_COMBO_CD_BUS: - b = settings_get_cur_sel(hdlg, IDC_COMBO_CD_BUS); - switch (b) { - case 0: - b2 = CDROM_BUS_DISABLED; - break; - case 1: - b2 = CDROM_BUS_ATAPI; - break; - case 2: - b2 = CDROM_BUS_SCSI; - break; - } - if (b2 == temp_cdrom[lv2_current_sel].bus_type) - break; - cdrom_untrack(lv2_current_sel); - assign = (temp_cdrom[lv2_current_sel].bus_type == b2) ? 0 : 1; - if (temp_cdrom[lv2_current_sel].bus_type == CDROM_BUS_DISABLED) - temp_cdrom[lv2_current_sel].speed = 8; - temp_cdrom[lv2_current_sel].bus_type = b2; - cdrom_recalc_location_controls(hdlg, assign); - cdrom_track(lv2_current_sel); - win_settings_cdrom_drives_update_item(hdlg, lv2_current_sel); - break; + case IDC_COMBO_CD_BUS: + b = settings_get_cur_sel(hdlg, IDC_COMBO_CD_BUS); + switch (b) { + case 0: + b2 = CDROM_BUS_DISABLED; + break; + case 1: + b2 = CDROM_BUS_ATAPI; + break; + case 2: + b2 = CDROM_BUS_SCSI; + break; + } + if (b2 == temp_cdrom[lv2_current_sel].bus_type) + break; + cdrom_untrack(lv2_current_sel); + assign = (temp_cdrom[lv2_current_sel].bus_type == b2) ? 0 : 1; + if (temp_cdrom[lv2_current_sel].bus_type == CDROM_BUS_DISABLED) + temp_cdrom[lv2_current_sel].speed = 8; + temp_cdrom[lv2_current_sel].bus_type = b2; + cdrom_recalc_location_controls(hdlg, assign); + cdrom_track(lv2_current_sel); + win_settings_cdrom_drives_update_item(hdlg, lv2_current_sel); + break; - case IDC_COMBO_CD_ID: - cdrom_untrack(lv2_current_sel); - temp_cdrom[lv2_current_sel].scsi_device_id = settings_get_cur_sel(hdlg, IDC_COMBO_CD_ID); - cdrom_track(lv2_current_sel); - win_settings_cdrom_drives_update_item(hdlg, lv2_current_sel); - break; + case IDC_COMBO_CD_ID: + cdrom_untrack(lv2_current_sel); + temp_cdrom[lv2_current_sel].scsi_device_id = settings_get_cur_sel(hdlg, IDC_COMBO_CD_ID); + cdrom_track(lv2_current_sel); + win_settings_cdrom_drives_update_item(hdlg, lv2_current_sel); + break; - case IDC_COMBO_CD_CHANNEL_IDE: - cdrom_untrack(lv2_current_sel); - temp_cdrom[lv2_current_sel].ide_channel = settings_get_cur_sel(hdlg, IDC_COMBO_CD_CHANNEL_IDE); - cdrom_track(lv2_current_sel); - win_settings_cdrom_drives_update_item(hdlg, lv2_current_sel); - break; + case IDC_COMBO_CD_CHANNEL_IDE: + cdrom_untrack(lv2_current_sel); + temp_cdrom[lv2_current_sel].ide_channel = settings_get_cur_sel(hdlg, IDC_COMBO_CD_CHANNEL_IDE); + cdrom_track(lv2_current_sel); + win_settings_cdrom_drives_update_item(hdlg, lv2_current_sel); + break; - case IDC_COMBO_CD_SPEED: - temp_cdrom[lv2_current_sel].speed = settings_get_cur_sel(hdlg, IDC_COMBO_CD_SPEED) + 1; - win_settings_cdrom_drives_update_item(hdlg, lv2_current_sel); - break; - } - ignore_change = 0; + case IDC_COMBO_CD_SPEED: + temp_cdrom[lv2_current_sel].speed = settings_get_cur_sel(hdlg, IDC_COMBO_CD_SPEED) + 1; + win_settings_cdrom_drives_update_item(hdlg, lv2_current_sel); + break; - case WM_DPICHANGED_AFTERPARENT: - win_settings_floppy_drives_resize_columns(hdlg); - image_list_init(hdlg, IDC_LIST_FLOPPY_DRIVES, (const uint8_t *) fd_icons); - win_settings_cdrom_drives_resize_columns(hdlg); - image_list_init(hdlg, IDC_LIST_CDROM_DRIVES, (const uint8_t *) cd_icons); - break; - default: - return FALSE; +#if 0 + case IDC_COMBO_CD_TYPE:: + temp_cdrom[lv2_current_sel].early = settings_get_check(hdlg, IDC_COMBO_CD_TYPE:); + win_settings_cdrom_drives_update_item(hdlg, lv2_current_sel); + break; +#endif + } + ignore_change = 0; + + case WM_DPICHANGED_AFTERPARENT: + win_settings_floppy_drives_resize_columns(hdlg); + image_list_init(hdlg, IDC_LIST_FLOPPY_DRIVES, (const uint8_t *) fd_icons); + win_settings_cdrom_drives_resize_columns(hdlg); + image_list_init(hdlg, IDC_LIST_CDROM_DRIVES, (const uint8_t *) cd_icons); + break; + default: + return FALSE; } return FALSE; } - #if defined(__amd64__) || defined(__aarch64__) static LRESULT CALLBACK #else @@ -4659,424 +5138,426 @@ static BOOL CALLBACK #endif win_settings_other_removable_devices_proc(HWND hdlg, UINT message, WPARAM wParam, LPARAM lParam) { - int old_sel = 0, b = 0, assign = 0; - uint32_t b2 = 0; - const uint8_t mo_icons[3] = { 251, 56, 0 }; + int old_sel = 0; + int b = 0; + int assign = 0; + uint32_t b2 = 0; + const uint8_t mo_icons[3] = { 251, 56, 0 }; const uint8_t zip_icons[3] = { 250, 48, 0 }; switch (message) { - case WM_INITDIALOG: - ignore_change = 1; + case WM_INITDIALOG: + ignore_change = 1; - lv1_current_sel = 0; - win_settings_mo_drives_init_columns(hdlg); - image_list_init(hdlg, IDC_LIST_MO_DRIVES, (const uint8_t *) mo_icons); - win_settings_mo_drives_recalc_list(hdlg); - settings_listview_select(hdlg, IDC_LIST_MO_DRIVES, 0); - mo_add_locations(hdlg); + lv1_current_sel = 0; + win_settings_mo_drives_init_columns(hdlg); + image_list_init(hdlg, IDC_LIST_MO_DRIVES, (const uint8_t *) mo_icons); + win_settings_mo_drives_recalc_list(hdlg); + settings_listview_select(hdlg, IDC_LIST_MO_DRIVES, 0); + mo_add_locations(hdlg); - switch (temp_mo_drives[lv1_current_sel].bus_type) { - case MO_BUS_DISABLED: - default: - b = 0; - break; - case MO_BUS_ATAPI: - b = 1; - break; - case MO_BUS_SCSI: - b = 2; - break; - } - settings_set_cur_sel(hdlg, IDC_COMBO_MO_BUS, b); - mo_recalc_location_controls(hdlg, 0); + switch (temp_mo_drives[lv1_current_sel].bus_type) { + default: + case MO_BUS_DISABLED: + b = 0; + break; + case MO_BUS_ATAPI: + b = 1; + break; + case MO_BUS_SCSI: + b = 2; + break; + } + settings_set_cur_sel(hdlg, IDC_COMBO_MO_BUS, b); + mo_recalc_location_controls(hdlg, 0); - settings_listview_enable_styles(hdlg, IDC_LIST_MO_DRIVES); + settings_listview_enable_styles(hdlg, IDC_LIST_MO_DRIVES); - lv2_current_sel = 0; - win_settings_zip_drives_init_columns(hdlg); - image_list_init(hdlg, IDC_LIST_ZIP_DRIVES, (const uint8_t *) zip_icons); - win_settings_zip_drives_recalc_list(hdlg); - settings_listview_select(hdlg, IDC_LIST_ZIP_DRIVES, 0); - zip_add_locations(hdlg); + lv2_current_sel = 0; + win_settings_zip_drives_init_columns(hdlg); + image_list_init(hdlg, IDC_LIST_ZIP_DRIVES, (const uint8_t *) zip_icons); + win_settings_zip_drives_recalc_list(hdlg); + settings_listview_select(hdlg, IDC_LIST_ZIP_DRIVES, 0); + zip_add_locations(hdlg); - switch (temp_zip_drives[lv2_current_sel].bus_type) { - case ZIP_BUS_DISABLED: - default: - b = 0; - break; - case ZIP_BUS_ATAPI: - b = 1; - break; - case ZIP_BUS_SCSI: - b = 2; - break; - } - settings_set_cur_sel(hdlg, IDC_COMBO_ZIP_BUS, b); - zip_recalc_location_controls(hdlg, 0); + switch (temp_zip_drives[lv2_current_sel].bus_type) { + default: + case ZIP_BUS_DISABLED: + b = 0; + break; + case ZIP_BUS_ATAPI: + b = 1; + break; + case ZIP_BUS_SCSI: + b = 2; + break; + } + settings_set_cur_sel(hdlg, IDC_COMBO_ZIP_BUS, b); + zip_recalc_location_controls(hdlg, 0); - settings_listview_enable_styles(hdlg, IDC_LIST_ZIP_DRIVES); + settings_listview_enable_styles(hdlg, IDC_LIST_ZIP_DRIVES); - ignore_change = 0; - return TRUE; + ignore_change = 0; + return TRUE; - case WM_NOTIFY: - if (ignore_change) - return FALSE; + case WM_NOTIFY: + if (ignore_change) + return FALSE; - if ((((LPNMHDR)lParam)->code == LVN_ITEMCHANGED) && (((LPNMHDR)lParam)->idFrom == IDC_LIST_MO_DRIVES)) { - old_sel = lv1_current_sel; - lv1_current_sel = get_selected_drive(hdlg, IDC_LIST_MO_DRIVES); - if (lv1_current_sel == old_sel) - return FALSE; - ignore_change = 1; + if ((((LPNMHDR) lParam)->code == LVN_ITEMCHANGED) && (((LPNMHDR) lParam)->idFrom == IDC_LIST_MO_DRIVES)) { + old_sel = lv1_current_sel; + lv1_current_sel = get_selected_drive(hdlg, IDC_LIST_MO_DRIVES, MO_NUM); + if (lv1_current_sel == old_sel) + return FALSE; + ignore_change = 1; - switch (temp_mo_drives[lv1_current_sel].bus_type) { - case MO_BUS_DISABLED: - default: - b = 0; - break; - case MO_BUS_ATAPI: - b = 1; - break; - case MO_BUS_SCSI: - b = 2; - break; - } - settings_set_cur_sel(hdlg, IDC_COMBO_MO_BUS, b); + switch (temp_mo_drives[lv1_current_sel].bus_type) { + default: + case MO_BUS_DISABLED: + b = 0; + break; + case MO_BUS_ATAPI: + b = 1; + break; + case MO_BUS_SCSI: + b = 2; + break; + } + settings_set_cur_sel(hdlg, IDC_COMBO_MO_BUS, b); - mo_recalc_location_controls(hdlg, 0); - ignore_change = 0; - } else if ((((LPNMHDR)lParam)->code == LVN_ITEMCHANGED) && (((LPNMHDR)lParam)->idFrom == IDC_LIST_ZIP_DRIVES)) { - old_sel = lv2_current_sel; - lv2_current_sel = get_selected_drive(hdlg, IDC_LIST_ZIP_DRIVES); - if (lv2_current_sel == old_sel) - return FALSE; - ignore_change = 1; + mo_recalc_location_controls(hdlg, 0); + ignore_change = 0; + } else if ((((LPNMHDR) lParam)->code == LVN_ITEMCHANGED) && (((LPNMHDR) lParam)->idFrom == IDC_LIST_ZIP_DRIVES)) { + old_sel = lv2_current_sel; + lv2_current_sel = get_selected_drive(hdlg, IDC_LIST_ZIP_DRIVES, ZIP_NUM); + if (lv2_current_sel == old_sel) + return FALSE; + ignore_change = 1; - switch (temp_zip_drives[lv2_current_sel].bus_type) { - case ZIP_BUS_DISABLED: - default: - b = 0; - break; - case ZIP_BUS_ATAPI: - b = 1; - break; - case ZIP_BUS_SCSI: - b = 2; - break; - } - settings_set_cur_sel(hdlg, IDC_COMBO_ZIP_BUS, b); + switch (temp_zip_drives[lv2_current_sel].bus_type) { + default: + case ZIP_BUS_DISABLED: + b = 0; + break; + case ZIP_BUS_ATAPI: + b = 1; + break; + case ZIP_BUS_SCSI: + b = 2; + break; + } + settings_set_cur_sel(hdlg, IDC_COMBO_ZIP_BUS, b); - zip_recalc_location_controls(hdlg, 0); - ignore_change = 0; - } - break; + zip_recalc_location_controls(hdlg, 0); + ignore_change = 0; + } + break; - case WM_COMMAND: - if (ignore_change) - return FALSE; + case WM_COMMAND: + if (ignore_change) + return FALSE; - ignore_change = 1; - switch (LOWORD(wParam)) { - case IDC_COMBO_MO_BUS: - b = settings_get_cur_sel(hdlg, IDC_COMBO_MO_BUS); - switch (b) { - case 0: - b2 = MO_BUS_DISABLED; - break; - case 1: - b2 = MO_BUS_ATAPI; - break; - case 2: - b2 = MO_BUS_SCSI; - break; - } - if (b2 == temp_mo_drives[lv1_current_sel].bus_type) - break; - mo_untrack(lv1_current_sel); - assign = (temp_mo_drives[lv1_current_sel].bus_type == b2) ? 0 : 1; - if (temp_mo_drives[lv1_current_sel].bus_type == MO_BUS_DISABLED) - temp_mo_drives[lv1_current_sel].type = 0; - temp_mo_drives[lv1_current_sel].bus_type = b2; - mo_recalc_location_controls(hdlg, assign); - mo_track(lv1_current_sel); - win_settings_mo_drives_update_item(hdlg, lv1_current_sel); - break; + ignore_change = 1; + switch (LOWORD(wParam)) { + case IDC_COMBO_MO_BUS: + b = settings_get_cur_sel(hdlg, IDC_COMBO_MO_BUS); + switch (b) { + case 0: + b2 = MO_BUS_DISABLED; + break; + case 1: + b2 = MO_BUS_ATAPI; + break; + case 2: + b2 = MO_BUS_SCSI; + break; + } + if (b2 == temp_mo_drives[lv1_current_sel].bus_type) + break; + mo_untrack(lv1_current_sel); + assign = (temp_mo_drives[lv1_current_sel].bus_type == b2) ? 0 : 1; + if (temp_mo_drives[lv1_current_sel].bus_type == MO_BUS_DISABLED) + temp_mo_drives[lv1_current_sel].type = 0; + temp_mo_drives[lv1_current_sel].bus_type = b2; + mo_recalc_location_controls(hdlg, assign); + mo_track(lv1_current_sel); + win_settings_mo_drives_update_item(hdlg, lv1_current_sel); + break; - case IDC_COMBO_MO_ID: - mo_untrack(lv1_current_sel); - temp_mo_drives[lv1_current_sel].scsi_device_id = settings_get_cur_sel(hdlg, IDC_COMBO_MO_ID); - mo_track(lv1_current_sel); - win_settings_mo_drives_update_item(hdlg, lv1_current_sel); - break; + case IDC_COMBO_MO_ID: + mo_untrack(lv1_current_sel); + temp_mo_drives[lv1_current_sel].scsi_device_id = settings_get_cur_sel(hdlg, IDC_COMBO_MO_ID); + mo_track(lv1_current_sel); + win_settings_mo_drives_update_item(hdlg, lv1_current_sel); + break; - case IDC_COMBO_MO_CHANNEL_IDE: - mo_untrack(lv1_current_sel); - temp_mo_drives[lv1_current_sel].ide_channel = settings_get_cur_sel(hdlg, IDC_COMBO_MO_CHANNEL_IDE); - mo_track(lv1_current_sel); - win_settings_mo_drives_update_item(hdlg, lv1_current_sel); - break; + case IDC_COMBO_MO_CHANNEL_IDE: + mo_untrack(lv1_current_sel); + temp_mo_drives[lv1_current_sel].ide_channel = settings_get_cur_sel(hdlg, IDC_COMBO_MO_CHANNEL_IDE); + mo_track(lv1_current_sel); + win_settings_mo_drives_update_item(hdlg, lv1_current_sel); + break; - case IDC_COMBO_MO_TYPE: - temp_mo_drives[lv1_current_sel].type = settings_get_cur_sel(hdlg, IDC_COMBO_MO_TYPE); - win_settings_mo_drives_update_item(hdlg, lv1_current_sel); - break; + case IDC_COMBO_MO_TYPE: + temp_mo_drives[lv1_current_sel].type = settings_get_cur_sel(hdlg, IDC_COMBO_MO_TYPE); + win_settings_mo_drives_update_item(hdlg, lv1_current_sel); + break; - case IDC_COMBO_ZIP_BUS: - b = settings_get_cur_sel(hdlg, IDC_COMBO_ZIP_BUS); - switch (b) { - case 0: - b2 = ZIP_BUS_DISABLED; - break; - case 1: - b2 = ZIP_BUS_ATAPI; - break; - case 2: - b2 = ZIP_BUS_SCSI; - break; - } - if (b2 == temp_zip_drives[lv2_current_sel].bus_type) - break; - zip_untrack(lv2_current_sel); - assign = (temp_zip_drives[lv2_current_sel].bus_type == b2) ? 0 : 1; - temp_zip_drives[lv2_current_sel].bus_type = b2; - zip_recalc_location_controls(hdlg, assign); - zip_track(lv2_current_sel); - win_settings_zip_drives_update_item(hdlg, lv2_current_sel); - break; + case IDC_COMBO_ZIP_BUS: + b = settings_get_cur_sel(hdlg, IDC_COMBO_ZIP_BUS); + switch (b) { + case 0: + b2 = ZIP_BUS_DISABLED; + break; + case 1: + b2 = ZIP_BUS_ATAPI; + break; + case 2: + b2 = ZIP_BUS_SCSI; + break; + } + if (b2 == temp_zip_drives[lv2_current_sel].bus_type) + break; + zip_untrack(lv2_current_sel); + assign = (temp_zip_drives[lv2_current_sel].bus_type == b2) ? 0 : 1; + temp_zip_drives[lv2_current_sel].bus_type = b2; + zip_recalc_location_controls(hdlg, assign); + zip_track(lv2_current_sel); + win_settings_zip_drives_update_item(hdlg, lv2_current_sel); + break; - case IDC_COMBO_ZIP_ID: - zip_untrack(lv2_current_sel); - temp_zip_drives[lv2_current_sel].scsi_device_id = settings_get_cur_sel(hdlg, IDC_COMBO_ZIP_ID); - zip_track(lv2_current_sel); - win_settings_zip_drives_update_item(hdlg, lv2_current_sel); - break; + case IDC_COMBO_ZIP_ID: + zip_untrack(lv2_current_sel); + temp_zip_drives[lv2_current_sel].scsi_device_id = settings_get_cur_sel(hdlg, IDC_COMBO_ZIP_ID); + zip_track(lv2_current_sel); + win_settings_zip_drives_update_item(hdlg, lv2_current_sel); + break; - case IDC_COMBO_ZIP_CHANNEL_IDE: - zip_untrack(lv2_current_sel); - temp_zip_drives[lv2_current_sel].ide_channel = settings_get_cur_sel(hdlg, IDC_COMBO_ZIP_CHANNEL_IDE); - zip_track(lv2_current_sel); - win_settings_zip_drives_update_item(hdlg, lv2_current_sel); - break; + case IDC_COMBO_ZIP_CHANNEL_IDE: + zip_untrack(lv2_current_sel); + temp_zip_drives[lv2_current_sel].ide_channel = settings_get_cur_sel(hdlg, IDC_COMBO_ZIP_CHANNEL_IDE); + zip_track(lv2_current_sel); + win_settings_zip_drives_update_item(hdlg, lv2_current_sel); + break; - case IDC_CHECK250: - temp_zip_drives[lv2_current_sel].is_250 = settings_get_check(hdlg, IDC_CHECK250); - win_settings_zip_drives_update_item(hdlg, lv2_current_sel); - break; - } - ignore_change = 0; + case IDC_CHECK250: + temp_zip_drives[lv2_current_sel].is_250 = settings_get_check(hdlg, IDC_CHECK250); + win_settings_zip_drives_update_item(hdlg, lv2_current_sel); + break; + } + ignore_change = 0; - case WM_DPICHANGED_AFTERPARENT: - win_settings_mo_drives_resize_columns(hdlg); - image_list_init(hdlg, IDC_LIST_MO_DRIVES, (const uint8_t *) mo_icons); - win_settings_zip_drives_resize_columns(hdlg); - image_list_init(hdlg, IDC_LIST_ZIP_DRIVES, (const uint8_t *) zip_icons); - break; - default: - return FALSE; + case WM_DPICHANGED_AFTERPARENT: + win_settings_mo_drives_resize_columns(hdlg); + image_list_init(hdlg, IDC_LIST_MO_DRIVES, (const uint8_t *) mo_icons); + win_settings_zip_drives_resize_columns(hdlg); + image_list_init(hdlg, IDC_LIST_ZIP_DRIVES, (const uint8_t *) zip_icons); + break; + default: + return FALSE; } return FALSE; } - #if defined(__amd64__) || defined(__aarch64__) static LRESULT CALLBACK #else static BOOL CALLBACK #endif -win_settings_peripherals_proc(HWND hdlg, UINT message, WPARAM wParam, LPARAM lParam) +win_settings_peripherals_proc(HWND hdlg, UINT message, WPARAM wParam, UNUSED(LPARAM lParam)) { - int c, d; - int e; - LPTSTR lptsTemp; - char *stransi; + int c; + int d; + int e; + LPTSTR lptsTemp; + char *stransi; const device_t *dev; switch (message) { - case WM_INITDIALOG: - lptsTemp = (LPTSTR) malloc(512 * sizeof(WCHAR)); - stransi = (char *) malloc(512); + case WM_INITDIALOG: + lptsTemp = (LPTSTR) malloc(512 * sizeof(WCHAR)); + stransi = (char *) malloc(512); - /* Populate the ISA RTC card dropdown. */ - e = 0; - settings_reset_content(hdlg, IDC_COMBO_ISARTC); - for (d = 0; ; d++) { - generate_device_name(isartc_get_device(d), isartc_get_internal_name(d), 0); + /* Populate the ISA RTC card dropdown. */ + e = 0; + settings_reset_content(hdlg, IDC_COMBO_ISARTC); + for (d = 0;; d++) { + generate_device_name(isartc_get_device(d), isartc_get_internal_name(d), 0); - if (!device_name[0]) - break; - dev = isartc_get_device(d); - if (device_is_valid(dev, temp_machine)) { - if (d == 0) { - settings_add_string(hdlg, IDC_COMBO_ISARTC, win_get_string(IDS_2103)); - settings_set_cur_sel(hdlg, IDC_COMBO_ISARTC, 0); - } else - settings_add_string(hdlg, IDC_COMBO_ISARTC, (LPARAM) device_name); - settings_list_to_device[1][e] = d; - if (d == temp_isartc) - settings_set_cur_sel(hdlg, IDC_COMBO_ISARTC, e); - e++; - } - } - settings_enable_window(hdlg, IDC_COMBO_ISARTC, machine_has_bus(temp_machine, MACHINE_BUS_ISA)); - settings_enable_window(hdlg, IDC_CONFIGURE_ISARTC, ((temp_isartc != 0) && machine_has_bus(temp_machine, MACHINE_BUS_ISA))); + if (!device_name[0]) + break; + dev = isartc_get_device(d); + if (device_is_valid(dev, temp_machine)) { + if (d == 0) { + settings_add_string(hdlg, IDC_COMBO_ISARTC, win_get_string(IDS_2104)); + settings_set_cur_sel(hdlg, IDC_COMBO_ISARTC, 0); + } else + settings_add_string(hdlg, IDC_COMBO_ISARTC, (LPARAM) device_name); + settings_list_to_device[1][e] = d; + if (d == temp_isartc) + settings_set_cur_sel(hdlg, IDC_COMBO_ISARTC, e); + e++; + } + } + settings_enable_window(hdlg, IDC_COMBO_ISARTC, machine_has_bus(temp_machine, MACHINE_BUS_ISA)); + settings_enable_window(hdlg, IDC_CONFIGURE_ISARTC, ((temp_isartc != 0) && machine_has_bus(temp_machine, MACHINE_BUS_ISA))); - /* Populate the ISA memory card dropdowns. */ - for (c = 0; c < ISAMEM_MAX; c++) { - e = 0; - settings_reset_content(hdlg, IDC_COMBO_ISAMEM_1 + c); - for (d = 0; ; d++) { - generate_device_name(isamem_get_device(d), (char *) isamem_get_internal_name(d), 0); + /* Populate the ISA memory card dropdowns. */ + for (c = 0; c < ISAMEM_MAX; c++) { + e = 0; + settings_reset_content(hdlg, IDC_COMBO_ISAMEM_1 + c); + for (d = 0;; d++) { + generate_device_name(isamem_get_device(d), (char *) isamem_get_internal_name(d), 0); - if (!device_name[0]) - break; + if (!device_name[0]) + break; - dev = isamem_get_device(d); - if (device_is_valid(dev, temp_machine)) { - if (d == 0) { - settings_add_string(hdlg, IDC_COMBO_ISAMEM_1 + c, win_get_string(IDS_2103)); - settings_set_cur_sel(hdlg, IDC_COMBO_ISAMEM_1 + c, 0); - } else - settings_add_string(hdlg, IDC_COMBO_ISAMEM_1 + c, (LPARAM) device_name); - settings_list_to_device[0][e] = d; - if (d == temp_isamem[c]) - settings_set_cur_sel(hdlg, IDC_COMBO_ISAMEM_1 + c, e); - e++; - } - } - settings_enable_window(hdlg, IDC_COMBO_ISAMEM_1 + c, machine_has_bus(temp_machine, MACHINE_BUS_ISA)); - settings_enable_window(hdlg, IDC_CONFIGURE_ISAMEM_1 + c, ((temp_isamem[c] != 0) && machine_has_bus(temp_machine, MACHINE_BUS_ISA))); - } + dev = isamem_get_device(d); + if (device_is_valid(dev, temp_machine)) { + if (d == 0) { + settings_add_string(hdlg, IDC_COMBO_ISAMEM_1 + c, win_get_string(IDS_2104)); + settings_set_cur_sel(hdlg, IDC_COMBO_ISAMEM_1 + c, 0); + } else + settings_add_string(hdlg, IDC_COMBO_ISAMEM_1 + c, (LPARAM) device_name); + settings_list_to_device[0][e] = d; + if (d == temp_isamem[c]) + settings_set_cur_sel(hdlg, IDC_COMBO_ISAMEM_1 + c, e); + e++; + } + } + settings_enable_window(hdlg, IDC_COMBO_ISAMEM_1 + c, machine_has_bus(temp_machine, MACHINE_BUS_ISA)); + settings_enable_window(hdlg, IDC_CONFIGURE_ISAMEM_1 + c, ((temp_isamem[c] != 0) && machine_has_bus(temp_machine, MACHINE_BUS_ISA))); + } - settings_enable_window(hdlg, IDC_CHECK_BUGGER, machine_has_bus(temp_machine, MACHINE_BUS_ISA)); - settings_set_check(hdlg, IDC_CHECK_BUGGER, temp_bugger); - settings_set_check(hdlg, IDC_CHECK_POSTCARD, temp_postcard); + settings_enable_window(hdlg, IDC_CHECK_BUGGER, machine_has_bus(temp_machine, MACHINE_BUS_ISA)); + settings_set_check(hdlg, IDC_CHECK_BUGGER, (temp_bugger && machine_has_bus(temp_machine, MACHINE_BUS_ISA))); + settings_set_check(hdlg, IDC_CHECK_POSTCARD, temp_postcard); - free(stransi); - free(lptsTemp); + free(stransi); + free(lptsTemp); - return TRUE; + return TRUE; - case WM_COMMAND: - switch (LOWORD(wParam)) { - case IDC_CONFIGURE_ISARTC: - temp_isartc = settings_list_to_device[1][settings_get_cur_sel(hdlg, IDC_COMBO_ISARTC)]; - temp_deviceconfig |= deviceconfig_open(hdlg, (void *)isartc_get_device(temp_isartc)); - break; + case WM_COMMAND: + switch (LOWORD(wParam)) { + case IDC_CONFIGURE_ISARTC: + temp_isartc = settings_list_to_device[1][settings_get_cur_sel(hdlg, IDC_COMBO_ISARTC)]; + temp_deviceconfig |= deviceconfig_open(hdlg, (void *) isartc_get_device(temp_isartc)); + break; - case IDC_COMBO_ISARTC: - temp_isartc = settings_list_to_device[1][settings_get_cur_sel(hdlg, IDC_COMBO_ISARTC)]; - settings_enable_window(hdlg, IDC_CONFIGURE_ISARTC, temp_isartc != 0); - break; + case IDC_COMBO_ISARTC: + temp_isartc = settings_list_to_device[1][settings_get_cur_sel(hdlg, IDC_COMBO_ISARTC)]; + settings_enable_window(hdlg, IDC_CONFIGURE_ISARTC, temp_isartc != 0); + break; - case IDC_COMBO_ISAMEM_1: case IDC_COMBO_ISAMEM_2: - case IDC_COMBO_ISAMEM_3: case IDC_COMBO_ISAMEM_4: - c = LOWORD(wParam) - IDC_COMBO_ISAMEM_1; - temp_isamem[c] = settings_list_to_device[0][settings_get_cur_sel(hdlg, LOWORD(wParam))]; - settings_enable_window(hdlg, IDC_CONFIGURE_ISAMEM_1 + c, temp_isamem[c] != 0); - break; + case IDC_COMBO_ISAMEM_1: + case IDC_COMBO_ISAMEM_2: + case IDC_COMBO_ISAMEM_3: + case IDC_COMBO_ISAMEM_4: + c = LOWORD(wParam) - IDC_COMBO_ISAMEM_1; + temp_isamem[c] = settings_list_to_device[0][settings_get_cur_sel(hdlg, LOWORD(wParam))]; + settings_enable_window(hdlg, IDC_CONFIGURE_ISAMEM_1 + c, temp_isamem[c] != 0); + break; - case IDC_CONFIGURE_ISAMEM_1: case IDC_CONFIGURE_ISAMEM_2: - case IDC_CONFIGURE_ISAMEM_3: case IDC_CONFIGURE_ISAMEM_4: - c = LOWORD(wParam) - IDC_CONFIGURE_ISAMEM_1; - temp_deviceconfig |= deviceconfig_inst_open(hdlg, (void *)isamem_get_device(temp_isamem[c]), c + 1); - break; - } - return FALSE; + case IDC_CONFIGURE_ISAMEM_1: + case IDC_CONFIGURE_ISAMEM_2: + case IDC_CONFIGURE_ISAMEM_3: + case IDC_CONFIGURE_ISAMEM_4: + c = LOWORD(wParam) - IDC_CONFIGURE_ISAMEM_1; + temp_deviceconfig |= deviceconfig_inst_open(hdlg, (void *) isamem_get_device(temp_isamem[c]), c + 1); + break; + } + return FALSE; - case WM_SAVESETTINGS: - temp_isartc = settings_list_to_device[1][settings_get_cur_sel(hdlg, IDC_COMBO_ISARTC)]; - for (c = 0; c < ISAMEM_MAX; c++) { - temp_isamem[c] = settings_list_to_device[0][settings_get_cur_sel(hdlg, IDC_COMBO_ISAMEM_1 + c)]; - } - temp_bugger = settings_get_check(hdlg, IDC_CHECK_BUGGER); - temp_postcard = settings_get_check(hdlg, IDC_CHECK_POSTCARD); + case WM_SAVESETTINGS: + temp_isartc = settings_list_to_device[1][settings_get_cur_sel(hdlg, IDC_COMBO_ISARTC)]; + for (c = 0; c < ISAMEM_MAX; c++) { + temp_isamem[c] = settings_list_to_device[0][settings_get_cur_sel(hdlg, IDC_COMBO_ISAMEM_1 + c)]; + } + temp_bugger = settings_get_check(hdlg, IDC_CHECK_BUGGER); + temp_postcard = settings_get_check(hdlg, IDC_CHECK_POSTCARD); - default: - return FALSE; + default: + return FALSE; } return FALSE; } - -void win_settings_show_child(HWND hwndParent, DWORD child_id) +void +win_settings_show_child(HWND hwndParent, DWORD child_id) { if (child_id == displayed_category) - return; + return; else - displayed_category = child_id; + displayed_category = child_id; SendMessage(hwndChildDialog, WM_SAVESETTINGS, 0, 0); DestroyWindow(hwndChildDialog); - switch(child_id) { - case SETTINGS_PAGE_MACHINE: - hwndChildDialog = CreateDialog(hinstance, (LPCWSTR)DLG_CFG_MACHINE, hwndParent, win_settings_machine_proc); - break; - case SETTINGS_PAGE_VIDEO: - hwndChildDialog = CreateDialog(hinstance, (LPCWSTR)DLG_CFG_VIDEO, hwndParent, win_settings_video_proc); - break; - case SETTINGS_PAGE_INPUT: - hwndChildDialog = CreateDialog(hinstance, (LPCWSTR)DLG_CFG_INPUT, hwndParent, win_settings_input_proc); - break; - case SETTINGS_PAGE_SOUND: - hwndChildDialog = CreateDialog(hinstance, (LPCWSTR)DLG_CFG_SOUND, hwndParent, win_settings_sound_proc); - break; - case SETTINGS_PAGE_NETWORK: - hwndChildDialog = CreateDialog(hinstance, (LPCWSTR)DLG_CFG_NETWORK, hwndParent, win_settings_network_proc); - break; - case SETTINGS_PAGE_PORTS: - hwndChildDialog = CreateDialog(hinstance, (LPCWSTR)DLG_CFG_PORTS, hwndParent, win_settings_ports_proc); - break; - case SETTINGS_PAGE_STORAGE: - hwndChildDialog = CreateDialog(hinstance, (LPCWSTR)DLG_CFG_STORAGE, hwndParent, win_settings_storage_proc); - break; - case SETTINGS_PAGE_HARD_DISKS: - hwndChildDialog = CreateDialog(hinstance, (LPCWSTR)DLG_CFG_HARD_DISKS, hwndParent, win_settings_hard_disks_proc); - break; - case SETTINGS_PAGE_FLOPPY_AND_CDROM_DRIVES: - hwndChildDialog = CreateDialog(hinstance, (LPCWSTR)DLG_CFG_FLOPPY_AND_CDROM_DRIVES, hwndParent, win_settings_floppy_and_cdrom_drives_proc); - break; - case SETTINGS_PAGE_OTHER_REMOVABLE_DEVICES: - hwndChildDialog = CreateDialog(hinstance, (LPCWSTR)DLG_CFG_OTHER_REMOVABLE_DEVICES, hwndParent, win_settings_other_removable_devices_proc); - break; - case SETTINGS_PAGE_PERIPHERALS: - hwndChildDialog = CreateDialog(hinstance, (LPCWSTR)DLG_CFG_PERIPHERALS, hwndParent, win_settings_peripherals_proc); - break; - default: - fatal("Invalid child dialog ID\n"); - return; + switch (child_id) { + case SETTINGS_PAGE_MACHINE: + hwndChildDialog = CreateDialog(hinstance, (LPCWSTR) DLG_CFG_MACHINE, hwndParent, win_settings_machine_proc); + break; + case SETTINGS_PAGE_VIDEO: + hwndChildDialog = CreateDialog(hinstance, (LPCWSTR) DLG_CFG_VIDEO, hwndParent, win_settings_video_proc); + break; + case SETTINGS_PAGE_INPUT: + hwndChildDialog = CreateDialog(hinstance, (LPCWSTR) DLG_CFG_INPUT, hwndParent, win_settings_input_proc); + break; + case SETTINGS_PAGE_SOUND: + hwndChildDialog = CreateDialog(hinstance, (LPCWSTR) DLG_CFG_SOUND, hwndParent, win_settings_sound_proc); + break; + case SETTINGS_PAGE_NETWORK: + hwndChildDialog = CreateDialog(hinstance, (LPCWSTR) DLG_CFG_NETWORK, hwndParent, win_settings_network_proc); + break; + case SETTINGS_PAGE_PORTS: + hwndChildDialog = CreateDialog(hinstance, (LPCWSTR) DLG_CFG_PORTS, hwndParent, win_settings_ports_proc); + break; + case SETTINGS_PAGE_STORAGE: + hwndChildDialog = CreateDialog(hinstance, (LPCWSTR) DLG_CFG_STORAGE, hwndParent, win_settings_storage_proc); + break; + case SETTINGS_PAGE_HARD_DISKS: + hwndChildDialog = CreateDialog(hinstance, (LPCWSTR) DLG_CFG_HARD_DISKS, hwndParent, win_settings_hard_disks_proc); + break; + case SETTINGS_PAGE_FLOPPY_AND_CDROM_DRIVES: + hwndChildDialog = CreateDialog(hinstance, (LPCWSTR) DLG_CFG_FLOPPY_AND_CDROM_DRIVES, hwndParent, win_settings_floppy_and_cdrom_drives_proc); + break; + case SETTINGS_PAGE_OTHER_REMOVABLE_DEVICES: + hwndChildDialog = CreateDialog(hinstance, (LPCWSTR) DLG_CFG_OTHER_REMOVABLE_DEVICES, hwndParent, win_settings_other_removable_devices_proc); + break; + case SETTINGS_PAGE_PERIPHERALS: + hwndChildDialog = CreateDialog(hinstance, (LPCWSTR) DLG_CFG_PERIPHERALS, hwndParent, win_settings_peripherals_proc); + break; + default: + fatal("Invalid child dialog ID\n"); + return; } ShowWindow(hwndChildDialog, SW_SHOWNORMAL); } - static BOOL win_settings_main_insert_categories(HWND hwndList) { LVITEM lvI; - int i = 0; - lvI.mask = LVIF_TEXT | LVIF_IMAGE | LVIF_STATE; + lvI.mask = LVIF_TEXT | LVIF_IMAGE | LVIF_STATE; lvI.stateMask = lvI.iSubItem = lvI.state = 0; - for (i = 0; i < 11; i++) { - lvI.pszText = plat_get_string(IDS_2065+i); - lvI.iItem = i; - lvI.iImage = i; + for (uint8_t i = 0; i < 11; i++) { + lvI.pszText = plat_get_string(IDS_2065 + i); + lvI.iItem = i; + lvI.iImage = i; - if (ListView_InsertItem(hwndList, &lvI) == -1) - return FALSE; + if (ListView_InsertItem(hwndList, &lvI) == -1) + return FALSE; } return TRUE; } - - #if defined(__amd64__) || defined(__aarch64__) static LRESULT CALLBACK #else @@ -5089,20 +5570,20 @@ win_settings_confirm(HWND hdlg) SendMessage(hwndChildDialog, WM_SAVESETTINGS, 0, 0); if (win_settings_changed()) { - if (confirm_save && !settings_only) - i = settings_msgbox_ex(MBX_QUESTION_OK | MBX_WARNING | MBX_DONTASK, (wchar_t *) IDS_2121, (wchar_t *) IDS_2122, (wchar_t *) IDS_2123, NULL, NULL); - else - i = 0; + if (confirm_save && !settings_only) + i = settings_msgbox_ex(MBX_QUESTION_OK | MBX_WARNING | MBX_DONTASK, (wchar_t *) IDS_2122, (wchar_t *) IDS_2123, (wchar_t *) IDS_2124, NULL, NULL); + else + i = 0; - if (i == 10) { - confirm_save = 0; - i = 0; - } + if (i == 10) { + confirm_save = 0; + i = 0; + } - if (i == 0) - win_settings_save(); - else - return FALSE; + if (i == 0) + win_settings_save(); + else + return FALSE; } DestroyWindow(hwndChildDialog); @@ -5111,7 +5592,6 @@ win_settings_confirm(HWND hdlg) return TRUE; } - static void win_settings_categories_resize_columns(HWND hdlg) { @@ -5122,30 +5602,28 @@ win_settings_categories_resize_columns(HWND hdlg) ListView_SetColumnWidth(hwndList, 0, (r.right - r.left) + 1 - 5); } - static BOOL win_settings_categories_init_columns(HWND hdlg) { LVCOLUMN lvc; - int iCol = 0; - HWND hwndList = GetDlgItem(hdlg, IDC_SETTINGSCATLIST); + int iCol = 0; + HWND hwndList = GetDlgItem(hdlg, IDC_SETTINGSCATLIST); lvc.mask = LVCF_FMT | LVCF_WIDTH | LVCF_TEXT | LVCF_SUBITEM; lvc.iSubItem = 0; - lvc.pszText = plat_get_string(2048); + lvc.pszText = plat_get_string(2048); - lvc.cx = 171; + lvc.cx = 171; lvc.fmt = LVCFMT_LEFT; if (ListView_InsertColumn(hwndList, iCol, &lvc) == -1) - return FALSE; + return FALSE; win_settings_categories_resize_columns(hdlg); return TRUE; } - #if defined(__amd64__) || defined(__aarch64__) static LRESULT CALLBACK #else @@ -5153,77 +5631,76 @@ static BOOL CALLBACK #endif win_settings_main_proc(HWND hdlg, UINT message, WPARAM wParam, LPARAM lParam) { - HWND h = NULL; - int category, i = 0, j = 0; + HWND h = NULL; + int category; + int j = 0; const uint8_t cat_icons[12] = { 240, 241, 242, 243, 96, 244, 252, 80, 246, 247, 245, 0 }; hwndParentDialog = hdlg; switch (message) { - case WM_INITDIALOG: - dpi = win_get_dpi(hdlg); - win_settings_init(); - displayed_category = -1; - h = GetDlgItem(hdlg, IDC_SETTINGSCATLIST); - win_settings_categories_init_columns(hdlg); - image_list_init(hdlg, IDC_SETTINGSCATLIST, (const uint8_t *) cat_icons); - win_settings_main_insert_categories(h); - settings_listview_select(hdlg, IDC_SETTINGSCATLIST, first_cat); - settings_listview_enable_styles(hdlg, IDC_SETTINGSCATLIST); - return TRUE; - case WM_NOTIFY: - if ((((LPNMHDR)lParam)->code == LVN_ITEMCHANGED) && (((LPNMHDR)lParam)->idFrom == IDC_SETTINGSCATLIST)) { - category = -1; - for (i = 0; i < 11; i++) { - h = GetDlgItem(hdlg, IDC_SETTINGSCATLIST); - j = ListView_GetItemState(h, i, LVIS_SELECTED); - if (j) - category = i; - } - if (category != -1) - win_settings_show_child(hdlg, category); - } - break; - case WM_CLOSE: - DestroyWindow(hwndChildDialog); - EndDialog(hdlg, 0); - win_notify_dlg_closed(); - return TRUE; - case WM_COMMAND: - switch (LOWORD(wParam)) { - case IDOK: - return win_settings_confirm(hdlg); - case IDCANCEL: - DestroyWindow(hwndChildDialog); - EndDialog(hdlg, 0); - win_notify_dlg_closed(); - return TRUE; - } - break; + case WM_INITDIALOG: + dpi = win_get_dpi(hdlg); + win_settings_init(); + displayed_category = -1; + h = GetDlgItem(hdlg, IDC_SETTINGSCATLIST); + win_settings_categories_init_columns(hdlg); + image_list_init(hdlg, IDC_SETTINGSCATLIST, (const uint8_t *) cat_icons); + win_settings_main_insert_categories(h); + settings_listview_select(hdlg, IDC_SETTINGSCATLIST, first_cat); + settings_listview_enable_styles(hdlg, IDC_SETTINGSCATLIST); + return TRUE; + case WM_NOTIFY: + if ((((LPNMHDR) lParam)->code == LVN_ITEMCHANGED) && (((LPNMHDR) lParam)->idFrom == IDC_SETTINGSCATLIST)) { + category = -1; + for (uint8_t i = 0; i < 11; i++) { + h = GetDlgItem(hdlg, IDC_SETTINGSCATLIST); + j = ListView_GetItemState(h, i, LVIS_SELECTED); + if (j) + category = i; + } + if (category != -1) + win_settings_show_child(hdlg, category); + } + break; + case WM_CLOSE: + DestroyWindow(hwndChildDialog); + EndDialog(hdlg, 0); + win_notify_dlg_closed(); + return TRUE; + case WM_COMMAND: + switch (LOWORD(wParam)) { + case IDOK: + return win_settings_confirm(hdlg); + case IDCANCEL: + DestroyWindow(hwndChildDialog); + EndDialog(hdlg, 0); + win_notify_dlg_closed(); + return TRUE; + } + break; - case WM_DPICHANGED: - dpi = HIWORD(wParam); - win_settings_categories_resize_columns(hdlg); - image_list_init(hdlg, IDC_SETTINGSCATLIST, (const uint8_t *) cat_icons); - break; - default: - return FALSE; + case WM_DPICHANGED: + dpi = HIWORD(wParam); + win_settings_categories_resize_columns(hdlg); + image_list_init(hdlg, IDC_SETTINGSCATLIST, (const uint8_t *) cat_icons); + break; + default: + return FALSE; } return FALSE; } - void win_settings_open_ex(HWND hwnd, int category) { win_notify_dlg_open(); first_cat = category; - DialogBox(hinstance, (LPCWSTR)DLG_CONFIG, hwnd, win_settings_main_proc); + DialogBox(hinstance, (LPCWSTR) DLG_CONFIG, hwnd, win_settings_main_proc); } - void win_settings_open(HWND hwnd) { diff --git a/src/win/win_snd_gain.c b/src/win/win_snd_gain.c index 85cc9e3b8..5297661bf 100644 --- a/src/win/win_snd_gain.c +++ b/src/win/win_snd_gain.c @@ -1,18 +1,19 @@ /* - * 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. + * 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. + * This file is part of the 86Box distribution. * - * Handle the sound gain dialog. + * Handle the sound gain dialog. * * * - * Authors: Miran Grca, + * Authors: Miran Grca, * - * Copyright 2016-2018 Miran Grca. + * Copyright 2016-2018 Miran Grca. + * Copyright 2021-2023 Jasmine Iwanek. */ #define UNICODE #define BITMAP WINDOWS_BITMAP @@ -31,62 +32,59 @@ #include <86box/sound.h> #include <86box/win.h> - -static uint8_t old_gain; - +static uint8_t old_gain; #if defined(__amd64__) || defined(__aarch64__) static LRESULT CALLBACK #else static BOOL CALLBACK #endif -SoundGainDialogProcedure(HWND hdlg, UINT message, WPARAM wParam, LPARAM lParam) +SoundGainDialogProcedure(HWND hdlg, UINT message, WPARAM wParam, UNUSED(LPARAM lParam)) { HWND h; switch (message) { - case WM_INITDIALOG: - old_gain = sound_gain; - h = GetDlgItem(hdlg, IDC_SLIDER_GAIN); - SendMessage(h, TBM_SETRANGE, (WPARAM)1, (LPARAM)MAKELONG(0, 9)); - SendMessage(h, TBM_SETPOS, (WPARAM)1, 9 - (sound_gain >> 1)); - SendMessage(h, TBM_SETTICFREQ, (WPARAM)1, 0); - SendMessage(h, TBM_SETLINESIZE, (WPARAM)0, 1); - SendMessage(h, TBM_SETPAGESIZE, (WPARAM)0, 2); - break; + case WM_INITDIALOG: + old_gain = sound_gain; + h = GetDlgItem(hdlg, IDC_SLIDER_GAIN); + SendMessage(h, TBM_SETRANGE, (WPARAM) 1, MAKELONG(0, 9)); + SendMessage(h, TBM_SETPOS, (WPARAM) 1, 9 - (sound_gain >> 1)); + SendMessage(h, TBM_SETTICFREQ, (WPARAM) 1, 0); + SendMessage(h, TBM_SETLINESIZE, (WPARAM) 0, 1); + SendMessage(h, TBM_SETPAGESIZE, (WPARAM) 0, 2); + break; - case WM_VSCROLL: - h = GetDlgItem(hdlg, IDC_SLIDER_GAIN); - sound_gain = (9 - SendMessage(h, TBM_GETPOS, (WPARAM)0, 0)) << 1; - break; + case WM_VSCROLL: + h = GetDlgItem(hdlg, IDC_SLIDER_GAIN); + sound_gain = (9 - SendMessage(h, TBM_GETPOS, (WPARAM) 0, 0)) << 1; + break; - case WM_COMMAND: - switch (LOWORD(wParam)) { - case IDOK: - h = GetDlgItem(hdlg, IDC_SLIDER_GAIN); - sound_gain = (9 - SendMessage(h, TBM_GETPOS, (WPARAM)0, 0)) << 1; - config_save(); - EndDialog(hdlg, 0); - return TRUE; + case WM_COMMAND: + switch (LOWORD(wParam)) { + case IDOK: + h = GetDlgItem(hdlg, IDC_SLIDER_GAIN); + sound_gain = (9 - SendMessage(h, TBM_GETPOS, (WPARAM) 0, 0)) << 1; + config_save(); + EndDialog(hdlg, 0); + return TRUE; - case IDCANCEL: - sound_gain = old_gain; - config_save(); - EndDialog(hdlg, 0); - return TRUE; + case IDCANCEL: + sound_gain = old_gain; + config_save(); + EndDialog(hdlg, 0); + return TRUE; - default: - break; - } - break; + default: + break; + } + break; } - return(FALSE); + return FALSE; } - void SoundGainDialogCreate(HWND hwnd) { - DialogBox(hinstance, (LPCTSTR)DLG_SND_GAIN, hwnd, SoundGainDialogProcedure); + DialogBox(hinstance, (LPCTSTR) DLG_SND_GAIN, hwnd, SoundGainDialogProcedure); } diff --git a/src/win/win_specify_dim.c b/src/win/win_specify_dim.c index 64a95cef4..5bedb846d 100644 --- a/src/win/win_specify_dim.c +++ b/src/win/win_specify_dim.c @@ -1,18 +1,19 @@ /* - * 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. + * 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. + * This file is part of the 86Box distribution. * - * Handle the dialog for specifying the dimensions of the main window. + * Handle the dialog for specifying the dimensions of the main window. * * * - * Authors: Miran Grca, + * Authors: Miran Grca, * - * Copyright 2016-2018 Miran Grca. + * Copyright 2016-2018 Miran Grca. + * Copyright 2021-2023 Jasmine Iwanek. */ #define UNICODE #define BITMAP WINDOWS_BITMAP @@ -28,10 +29,10 @@ #include <86box/86box.h> #include <86box/config.h> #include <86box/plat.h> +#include <86box/video.h> #include <86box/sound.h> #include <86box/win.h> - #if defined(__amd64__) || defined(__aarch64__) static LRESULT CALLBACK #else @@ -39,140 +40,149 @@ static BOOL CALLBACK #endif SpecifyDimensionsDialogProcedure(HWND hdlg, UINT message, WPARAM wParam, LPARAM lParam) { - HWND h, h2; - HMENU hmenu; - UDACCEL accel, accel2; - RECT r; - uint32_t temp_x = 0, temp_y = 0; - int dpi = 96, lock; - LPTSTR lptsTemp; - char *stransi; + HWND h; + HWND h2; + HMENU hmenu; + UDACCEL accel; + UDACCEL accel2; + RECT r; + uint32_t temp_x = 0; + uint32_t temp_y = 0; + int dpi = 96; + int lock; + LPTSTR lptsTemp; + char *stransi; switch (message) { - case WM_INITDIALOG: - GetWindowRect(hwndRender, &r); + case WM_INITDIALOG: + GetWindowRect(hwndRender, &r); - h = GetDlgItem(hdlg, IDC_WIDTHSPIN); - h2 = GetDlgItem(hdlg, IDC_EDIT_WIDTH); - SendMessage(h, UDM_SETBUDDY, (WPARAM)h2, 0); - SendMessage(h, UDM_SETRANGE, 0, (120 << 16) | 2048); - accel.nSec = 0; - accel.nInc = 8; - SendMessage(h, UDM_SETACCEL, 1, (LPARAM)&accel); - SendMessage(h, UDM_SETPOS, 0, r.right - r.left); + h = GetDlgItem(hdlg, IDC_WIDTHSPIN); + h2 = GetDlgItem(hdlg, IDC_EDIT_WIDTH); + SendMessage(h, UDM_SETBUDDY, (WPARAM) h2, 0); + SendMessage(h, UDM_SETRANGE, 0, (120 << 16) | 2048); + accel.nSec = 0; + accel.nInc = 8; + SendMessage(h, UDM_SETACCEL, 1, (LPARAM) &accel); + SendMessage(h, UDM_SETPOS, 0, r.right - r.left); - h = GetDlgItem(hdlg, IDC_HEIGHTSPIN); - h2 = GetDlgItem(hdlg, IDC_EDIT_HEIGHT); - SendMessage(h, UDM_SETBUDDY, (WPARAM)h2, 0); - SendMessage(h, UDM_SETRANGE, 0, (120 << 16) | 2048); - accel2.nSec = 0; - accel2.nInc = 8; - SendMessage(h, UDM_SETACCEL, 1, (LPARAM)&accel2); - SendMessage(h, UDM_SETPOS, 0, r.bottom - r.top); + h = GetDlgItem(hdlg, IDC_HEIGHTSPIN); + h2 = GetDlgItem(hdlg, IDC_EDIT_HEIGHT); + SendMessage(h, UDM_SETBUDDY, (WPARAM) h2, 0); + SendMessage(h, UDM_SETRANGE, 0, (120 << 16) | 2048); + accel2.nSec = 0; + accel2.nInc = 8; + SendMessage(h, UDM_SETACCEL, 1, (LPARAM) &accel2); + SendMessage(h, UDM_SETPOS, 0, r.bottom - r.top); - h = GetDlgItem(hdlg, IDC_CHECK_LOCK_SIZE); - SendMessage(h, BM_SETCHECK, !!(vid_resize & 2), 0); - break; + h = GetDlgItem(hdlg, IDC_CHECK_LOCK_SIZE); + SendMessage(h, BM_SETCHECK, !!(vid_resize & 2), 0); + break; - case WM_COMMAND: - switch (LOWORD(wParam)) { - case IDOK: - lptsTemp = (LPTSTR) malloc(512 * sizeof(WCHAR)); - stransi = (char *)malloc(512); + case WM_COMMAND: + switch (LOWORD(wParam)) { + case IDOK: + lptsTemp = (LPTSTR) malloc(512 * sizeof(WCHAR)); + stransi = (char *) malloc(512); - h = GetDlgItem(hdlg, IDC_EDIT_WIDTH); - SendMessage(h, WM_GETTEXT, 255, (LPARAM) lptsTemp); - wcstombs(stransi, lptsTemp, 512); - sscanf(stransi, "%u", &temp_x); - fixed_size_x = temp_x; + h = GetDlgItem(hdlg, IDC_EDIT_WIDTH); + SendMessage(h, WM_GETTEXT, 255, (LPARAM) lptsTemp); + wcstombs(stransi, lptsTemp, 512); + sscanf(stransi, "%u", &temp_x); + fixed_size_x = temp_x; - h = GetDlgItem(hdlg, IDC_EDIT_HEIGHT); - SendMessage(h, WM_GETTEXT, 255, (LPARAM) lptsTemp); - wcstombs(stransi, lptsTemp, 512); - sscanf(stransi, "%u", &temp_y); - fixed_size_y = temp_y; + h = GetDlgItem(hdlg, IDC_EDIT_HEIGHT); + SendMessage(h, WM_GETTEXT, 255, (LPARAM) lptsTemp); + wcstombs(stransi, lptsTemp, 512); + sscanf(stransi, "%u", &temp_y); + fixed_size_y = temp_y; - h = GetDlgItem(hdlg, IDC_CHECK_LOCK_SIZE); - lock = SendMessage(h, BM_GETCHECK, 0, 0); + h = GetDlgItem(hdlg, IDC_CHECK_LOCK_SIZE); + lock = SendMessage(h, BM_GETCHECK, 0, 0); - if (lock) { - vid_resize = 2; - window_remember = 0; - } else { - vid_resize = 1; - window_remember = 1; - } - hmenu = GetMenu(hwndMain); - CheckMenuItem(hmenu, IDM_VID_REMEMBER, (window_remember == 1) ? MF_CHECKED : MF_UNCHECKED); - CheckMenuItem(hmenu, IDM_VID_RESIZE, (vid_resize == 1) ? MF_CHECKED : MF_UNCHECKED); - EnableMenuItem(hmenu, IDM_VID_RESIZE, (vid_resize & 2) ? MF_GRAYED : MF_ENABLED); + if (lock) { + vid_resize = 2; + window_remember = 0; + } else { + vid_resize = 1; + window_remember = 1; + } + hmenu = GetMenu(hwndMain); + CheckMenuItem(hmenu, IDM_VID_REMEMBER, (window_remember == 1) ? MF_CHECKED : MF_UNCHECKED); + CheckMenuItem(hmenu, IDM_VID_RESIZE, (vid_resize == 1) ? MF_CHECKED : MF_UNCHECKED); + EnableMenuItem(hmenu, IDM_VID_RESIZE, (vid_resize & 2) ? MF_GRAYED : MF_ENABLED); - if (vid_resize == 1) - SetWindowLongPtr(hwndMain, GWL_STYLE, (WS_OVERLAPPEDWINDOW) | WS_VISIBLE); - else - SetWindowLongPtr(hwndMain, GWL_STYLE, (WS_OVERLAPPEDWINDOW & ~WS_SIZEBOX & ~WS_MAXIMIZEBOX) | WS_VISIBLE); + if (vid_resize == 1) + SetWindowLongPtr(hwndMain, GWL_STYLE, (WS_OVERLAPPEDWINDOW) | WS_VISIBLE); + else + SetWindowLongPtr(hwndMain, GWL_STYLE, (WS_OVERLAPPEDWINDOW & ~WS_SIZEBOX & ~WS_MAXIMIZEBOX) | WS_VISIBLE); - /* scale the screen base on DPI */ - if (dpi_scale) { - dpi = win_get_dpi(hwndMain); - temp_x = MulDiv(temp_x, dpi, 96); - temp_y = MulDiv(temp_y, dpi, 96); - } + /* scale the screen base on DPI */ + if (dpi_scale) { + dpi = win_get_dpi(hwndMain); + temp_x = MulDiv(temp_x, dpi, 96); + temp_y = MulDiv(temp_y, dpi, 96); + } - ResizeWindowByClientArea(hwndMain, temp_x, temp_y + sbar_height + tbar_height); + ResizeWindowByClientArea(hwndMain, temp_x, temp_y + sbar_height + tbar_height); - if (vid_resize) { - CheckMenuItem(hmenu, IDM_VID_SCALE_1X + scale, MF_UNCHECKED); - CheckMenuItem(hmenu, IDM_VID_SCALE_2X, MF_CHECKED); - scale = 1; - } - EnableMenuItem(hmenu, IDM_VID_SCALE_1X, vid_resize ? MF_GRAYED : MF_ENABLED); - EnableMenuItem(hmenu, IDM_VID_SCALE_2X, vid_resize ? MF_GRAYED : MF_ENABLED); - EnableMenuItem(hmenu, IDM_VID_SCALE_3X, vid_resize ? MF_GRAYED : MF_ENABLED); - EnableMenuItem(hmenu, IDM_VID_SCALE_4X, vid_resize ? MF_GRAYED : MF_ENABLED); + if (vid_resize) { + CheckMenuItem(hmenu, IDM_VID_SCALE_1X + scale, MF_UNCHECKED); + CheckMenuItem(hmenu, IDM_VID_SCALE_2X, MF_CHECKED); + scale = 1; + } + EnableMenuItem(hmenu, IDM_VID_SCALE_1X, vid_resize ? MF_GRAYED : MF_ENABLED); + EnableMenuItem(hmenu, IDM_VID_SCALE_2X, vid_resize ? MF_GRAYED : MF_ENABLED); + EnableMenuItem(hmenu, IDM_VID_SCALE_3X, vid_resize ? MF_GRAYED : MF_ENABLED); + EnableMenuItem(hmenu, IDM_VID_SCALE_4X, vid_resize ? MF_GRAYED : MF_ENABLED); + EnableMenuItem(hmenu, IDM_VID_SCALE_5X, vid_resize ? MF_GRAYED : MF_ENABLED); + EnableMenuItem(hmenu, IDM_VID_SCALE_6X, vid_resize ? MF_GRAYED : MF_ENABLED); + EnableMenuItem(hmenu, IDM_VID_SCALE_7X, vid_resize ? MF_GRAYED : MF_ENABLED); + EnableMenuItem(hmenu, IDM_VID_SCALE_8X, vid_resize ? MF_GRAYED : MF_ENABLED); + EnableMenuItem(hmenu, IDM_VID_SCALE_9X, vid_resize ? MF_GRAYED : MF_ENABLED); + EnableMenuItem(hmenu, IDM_VID_SCALE_10X, vid_resize ? MF_GRAYED : MF_ENABLED); - scrnsz_x = fixed_size_x; - scrnsz_y = fixed_size_y; - atomic_flag_clear(&doresize); + scrnsz_x = fixed_size_x; + scrnsz_y = fixed_size_y; + atomic_store(&doresize_monitors[0], 1); - GetWindowRect(hwndMain, &r); + GetWindowRect(hwndMain, &r); - if (mouse_capture) - ClipCursor(&r); + if (mouse_capture) + ClipCursor(&r); - if (window_remember || (vid_resize & 2)) { - window_x = r.left; - window_y = r.top; - if (!(vid_resize & 2)) { - window_w = r.right - r.left; - window_h = r.bottom - r.top; - } - } + if (window_remember || (vid_resize & 2)) { + window_x = r.left; + window_y = r.top; + if (!(vid_resize & 2)) { + window_w = r.right - r.left; + window_h = r.bottom - r.top; + } + } - config_save(); + config_save(); - free(stransi); - free(lptsTemp); + free(stransi); + free(lptsTemp); - EndDialog(hdlg, 0); - return TRUE; + EndDialog(hdlg, 0); + return TRUE; - case IDCANCEL: - EndDialog(hdlg, 0); - return TRUE; + case IDCANCEL: + EndDialog(hdlg, 0); + return TRUE; - default: - break; - } - break; + default: + break; + } + break; } - return(FALSE); + return FALSE; } - void SpecifyDimensionsDialogCreate(HWND hwnd) { - DialogBox(hinstance, (LPCTSTR)DLG_SPECIFY_DIM, hwnd, SpecifyDimensionsDialogProcedure); + DialogBox(hinstance, (LPCTSTR) DLG_SPECIFY_DIM, hwnd, SpecifyDimensionsDialogProcedure); } diff --git a/src/win/win_stbar.c b/src/win/win_stbar.c index bf2830456..2cf8d84f4 100644 --- a/src/win/win_stbar.c +++ b/src/win/win_stbar.c @@ -1,20 +1,21 @@ /* - * 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. + * 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. + * This file is part of the 86Box distribution. * - * Implement the application's Status Bar. + * Implement the application's Status Bar. * * * - * Authors: Miran Grca, - * Fred N. van Kempen, + * Authors: Miran Grca, + * Fred N. van Kempen, * - * Copyright 2016-2019 Miran Grca. - * Copyright 2017-2019 Fred N. van Kempen. + * Copyright 2016-2019 Miran Grca. + * Copyright 2017-2019 Fred N. van Kempen. + * Copyright 2021-2023 Jasmine Iwanek. */ #define UNICODE #define BITMAP WINDOWS_BITMAP @@ -47,6 +48,7 @@ #include <86box/mo.h> #include <86box/cdrom_image.h> #include <86box/scsi_disk.h> +#include <86box/thread.h> #include <86box/network.h> #include <86box/video.h> #include <86box/sound.h> @@ -54,22 +56,21 @@ #include <86box/ui.h> #include <86box/win.h> +HWND hwndSBAR; +int update_icons = 1; +int reset_occurred = 1; -HWND hwndSBAR; -int update_icons = 1, reset_occurred = 1; - - -static LONG_PTR OriginalProcedure; -static WCHAR **sbTips; -static int *iStatusWidths; -static int *sb_part_meanings; -static uint8_t *sb_part_icons; -static int sb_parts = 0; -static int sb_ready = 0; -static uint8_t sb_map[256]; -static int icon_width = 24; -static wchar_t sb_text[512] = L"\0"; -static wchar_t sb_bugtext[512] = L"\0"; +static LONG_PTR OriginalProcedure; +static WCHAR **sbTips; +static int *iStatusWidths; +static int *sb_part_meanings; +static uint8_t *sb_part_icons; +static int sb_parts = 0; +static int sb_ready = 0; +static uint8_t sb_map[256]; +static int icon_width = 24; +static wchar_t sb_text[512] = L"\0"; +static wchar_t sb_bugtext[512] = L"\0"; /* Also used by win_settings.c */ intptr_t @@ -77,62 +78,66 @@ fdd_type_to_icon(int type) { int ret = 248; - switch(type) { - case 0: - break; + switch (type) { + case 0: + break; - case 1: case 2: case 3: case 4: - case 5: case 6: - ret = 16; - break; + case 1: + case 2: + case 3: + case 4: + case 5: + case 6: + ret = 16; + break; - case 7: case 8: case 9: case 10: - case 11: case 12: case 13: - ret = 24; - break; + case 7: + case 8: + case 9: + case 10: + case 11: + case 12: + case 13: + ret = 24; + break; - default: - break; + default: + break; } - return(ret); + return ret; } - /* FIXME: should be hdd_count() in hdd.c */ static int hdd_count(int bus) { int c = 0; - int i; - for (i=0; i= SB_TEXT)) - return; + if ((tag & 0xf0) >= SB_TEXT) + return; found = sb_map[tag]; if ((found != 0xff) && ((sb_part_icons[found] ^ active) & 1) && active) { - sb_part_icons[found] |= 1; + sb_part_icons[found] |= 1; - PostMessage(hwndSBAR, SB_SETICON, found, - (LPARAM)hIcon[sb_part_icons[found]]); + PostMessage(hwndSBAR, SB_SETICON, found, + (LPARAM) hIcon[sb_part_icons[found]]); - reset_occurred = 2; - SetTimer(hwndMain, 0x8000 | found, 75, NULL); + reset_occurred = 2; + SetTimer(hwndMain, 0x8000 | found, 75, NULL); } } - - /* API: This is for the drive state indicator. */ void ui_sb_update_icon_state(int tag, int state) @@ -167,19 +170,18 @@ ui_sb_update_icon_state(int tag, int state) uint8_t found = 0xff; if (!sb_ready || ((tag & 0xf0) >= SB_HDD)) - return; + return; found = sb_map[tag]; if (found != 0xff) { - sb_part_icons[found] &= ~128; - sb_part_icons[found] |= (state ? 128 : 0); + sb_part_icons[found] &= ~128; + sb_part_icons[found] |= (state ? 128 : 0); - SendMessage(hwndSBAR, SB_SETICON, found, - (LPARAM)hIcon[sb_part_icons[found]]); + SendMessage(hwndSBAR, SB_SETICON, found, + (LPARAM) hIcon[sb_part_icons[found]]); } } - static void StatusBarCreateCassetteTip(int part) { @@ -187,46 +189,44 @@ StatusBarCreateCassetteTip(int part) WCHAR fn[512]; if (strlen(cassette_fname) == 0) - _swprintf(tempTip, plat_get_string(IDS_2148), plat_get_string(IDS_2057)); + _swprintf(tempTip, plat_get_string(IDS_2149), plat_get_string(IDS_2057)); else { - mbstoc16s(fn, cassette_fname, sizeof_w(fn)); - _swprintf(tempTip, plat_get_string(IDS_2148), fn); + mbstoc16s(fn, cassette_fname, sizeof_w(fn)); + _swprintf(tempTip, plat_get_string(IDS_2149), fn); } if (sbTips[part] != NULL) { - free(sbTips[part]); - sbTips[part] = NULL; + free(sbTips[part]); + sbTips[part] = NULL; } - sbTips[part] = (WCHAR *)malloc((wcslen(tempTip) << 1) + 2); + sbTips[part] = (WCHAR *) malloc((wcslen(tempTip) << 1) + 2); wcscpy(sbTips[part], tempTip); } - static void StatusBarCreateCartridgeTip(int part) { WCHAR tempTip[512]; WCHAR fn[512]; - int drive = sb_part_meanings[part] & 0xf; + int drive = sb_part_meanings[part] & 0xf; if (strlen(cart_fns[drive]) == 0) { - _swprintf(tempTip, plat_get_string(IDS_2150), - drive+1, plat_get_string(IDS_2057)); + _swprintf(tempTip, plat_get_string(IDS_2151), + drive + 1, plat_get_string(IDS_2057)); } else { - mbstoc16s(fn, cart_fns[drive], sizeof_w(fn)); - _swprintf(tempTip, plat_get_string(IDS_2150), - drive+1, fn); + mbstoc16s(fn, cart_fns[drive], sizeof_w(fn)); + _swprintf(tempTip, plat_get_string(IDS_2151), + drive + 1, fn); } if (sbTips[part] != NULL) { - free(sbTips[part]); - sbTips[part] = NULL; + free(sbTips[part]); + sbTips[part] = NULL; } - sbTips[part] = (WCHAR *)malloc((wcslen(tempTip) << 1) + 2); + sbTips[part] = (WCHAR *) malloc((wcslen(tempTip) << 1) + 2); wcscpy(sbTips[part], tempTip); } - static void StatusBarCreateFloppyTip(int part) { @@ -237,142 +237,137 @@ StatusBarCreateFloppyTip(int part) int drive = sb_part_meanings[part] & 0xf; mbstoc16s(wtext, fdd_getname(fdd_get_type(drive)), - strlen(fdd_getname(fdd_get_type(drive))) + 1); + strlen(fdd_getname(fdd_get_type(drive))) + 1); if (strlen(floppyfns[drive]) == 0) { - _swprintf(tempTip, plat_get_string(IDS_2108), - drive+1, wtext, plat_get_string(IDS_2057)); + _swprintf(tempTip, plat_get_string(IDS_2109), + drive + 1, wtext, plat_get_string(IDS_2057)); } else { - mbstoc16s(fn, floppyfns[drive], sizeof_w(fn)); - _swprintf(tempTip, plat_get_string(IDS_2108), - drive+1, wtext, fn); + mbstoc16s(fn, floppyfns[drive], sizeof_w(fn)); + _swprintf(tempTip, plat_get_string(IDS_2109), + drive + 1, wtext, fn); } if (sbTips[part] != NULL) { - free(sbTips[part]); - sbTips[part] = NULL; + free(sbTips[part]); + sbTips[part] = NULL; } - sbTips[part] = (WCHAR *)malloc((wcslen(tempTip) << 1) + 2); + sbTips[part] = (WCHAR *) malloc((wcslen(tempTip) << 1) + 2); wcscpy(sbTips[part], tempTip); } - static void StatusBarCreateCdromTip(int part) { - WCHAR tempTip[512]; + WCHAR tempTip[512]; WCHAR *szText; - WCHAR fn[512]; - int id; - int drive = sb_part_meanings[part] & 0xf; - int bus = cdrom[drive].bus_type; + WCHAR fn[512]; + int id; + int drive = sb_part_meanings[part] & 0xf; + int bus = cdrom[drive].bus_type; - id = IDS_5377 + (bus - 1); + id = IDS_5377 + (bus - 1); szText = plat_get_string(id); if (cdrom[drive].host_drive == 200) { - if (strlen(cdrom[drive].image_path) == 0) { - _swprintf(tempTip, plat_get_string(IDS_5120), - drive+1, szText, plat_get_string(IDS_2057)); - } else { - mbstoc16s(fn, cdrom[drive].image_path, sizeof_w(fn)); - _swprintf(tempTip, plat_get_string(IDS_5120), - drive+1, szText, fn); - } + if (strlen(cdrom[drive].image_path) == 0) { + _swprintf(tempTip, plat_get_string(IDS_5120), + drive + 1, szText, plat_get_string(IDS_2057)); + } else { + mbstoc16s(fn, cdrom[drive].image_path, sizeof_w(fn)); + _swprintf(tempTip, plat_get_string(IDS_5120), + drive + 1, szText, fn); + } } else - _swprintf(tempTip, plat_get_string(IDS_5120), drive+1, szText, plat_get_string(IDS_2057)); + _swprintf(tempTip, plat_get_string(IDS_5120), drive + 1, szText, plat_get_string(IDS_2057)); if (sbTips[part] != NULL) { - free(sbTips[part]); - sbTips[part] = NULL; + free(sbTips[part]); + sbTips[part] = NULL; } - sbTips[part] = (WCHAR *)malloc((wcslen(tempTip) << 1) + 4); + sbTips[part] = (WCHAR *) malloc((wcslen(tempTip) << 1) + 4); wcscpy(sbTips[part], tempTip); } - static void StatusBarCreateZIPTip(int part) { - WCHAR tempTip[512]; + WCHAR tempTip[512]; WCHAR *szText; - WCHAR fn[512]; - int id; - int drive = sb_part_meanings[part] & 0xf; - int bus = zip_drives[drive].bus_type; + WCHAR fn[512]; + int id; + int drive = sb_part_meanings[part] & 0xf; + int bus = zip_drives[drive].bus_type; - id = IDS_5377 + (bus - 1); + id = IDS_5377 + (bus - 1); szText = plat_get_string(id); int type = zip_drives[drive].is_250 ? 250 : 100; if (strlen(zip_drives[drive].image_path) == 0) { - _swprintf(tempTip, plat_get_string(IDS_2054), - type, drive+1, szText, plat_get_string(IDS_2057)); + _swprintf(tempTip, plat_get_string(IDS_2054), + type, drive + 1, szText, plat_get_string(IDS_2057)); } else { - mbstoc16s(fn, zip_drives[drive].image_path, sizeof_w(fn)); - _swprintf(tempTip, plat_get_string(IDS_2054), - type, drive+1, szText, fn); + mbstoc16s(fn, zip_drives[drive].image_path, sizeof_w(fn)); + _swprintf(tempTip, plat_get_string(IDS_2054), + type, drive + 1, szText, fn); } if (sbTips[part] != NULL) { - free(sbTips[part]); - sbTips[part] = NULL; + free(sbTips[part]); + sbTips[part] = NULL; } - sbTips[part] = (WCHAR *)malloc((wcslen(tempTip) << 1) + 2); + sbTips[part] = (WCHAR *) malloc((wcslen(tempTip) << 1) + 2); wcscpy(sbTips[part], tempTip); } - static void StatusBarCreateMOTip(int part) { - WCHAR tempTip[512]; + WCHAR tempTip[512]; WCHAR *szText; - WCHAR fn[512]; - int id; - int drive = sb_part_meanings[part] & 0xf; - int bus = mo_drives[drive].bus_type; + WCHAR fn[512]; + int id; + int drive = sb_part_meanings[part] & 0xf; + int bus = mo_drives[drive].bus_type; - id = IDS_5377 + (bus - 1); + id = IDS_5377 + (bus - 1); szText = plat_get_string(id); if (strlen(mo_drives[drive].image_path) == 0) { - _swprintf(tempTip, plat_get_string(IDS_2115), - drive+1, szText, plat_get_string(IDS_2057)); + _swprintf(tempTip, plat_get_string(IDS_2116), + drive + 1, szText, plat_get_string(IDS_2057)); } else { - mbstoc16s(fn, mo_drives[drive].image_path, sizeof_w(fn)); - _swprintf(tempTip, plat_get_string(IDS_2115), - drive+1, szText, fn); + mbstoc16s(fn, mo_drives[drive].image_path, sizeof_w(fn)); + _swprintf(tempTip, plat_get_string(IDS_2116), + drive + 1, szText, fn); } if (sbTips[part] != NULL) { - free(sbTips[part]); - sbTips[part] = NULL; + free(sbTips[part]); + sbTips[part] = NULL; } - sbTips[part] = (WCHAR *)malloc((wcslen(tempTip) << 1) + 2); + sbTips[part] = (WCHAR *) malloc((wcslen(tempTip) << 1) + 2); wcscpy(sbTips[part], tempTip); } - static void StatusBarCreateDiskTip(int part) { - WCHAR tempTip[512]; + WCHAR tempTip[512]; WCHAR *szText; - int id; - int bus = sb_part_meanings[part] & 0xf; + int id; + int bus = sb_part_meanings[part] & 0xf; - id = IDS_4352 + (bus - 1); + id = IDS_4352 + (bus - 1); szText = plat_get_string(id); _swprintf(tempTip, plat_get_string(IDS_4096), szText); if (sbTips[part] != NULL) - free(sbTips[part]); - sbTips[part] = (WCHAR *)malloc((wcslen(tempTip) << 1) + 2); + free(sbTips[part]); + sbTips[part] = (WCHAR *) malloc((wcslen(tempTip) << 1) + 2); wcscpy(sbTips[part], tempTip); } - static void StatusBarCreateNetworkTip(int part) { @@ -381,12 +376,11 @@ StatusBarCreateNetworkTip(int part) _swprintf(tempTip, plat_get_string(IDS_2069)); if (sbTips[part] != NULL) - free(sbTips[part]); - sbTips[part] = (WCHAR *)malloc((wcslen(tempTip) << 1) + 2); + free(sbTips[part]); + sbTips[part] = (WCHAR *) malloc((wcslen(tempTip) << 1) + 2); wcscpy(sbTips[part], tempTip); } - static void StatusBarCreateSoundTip(int part) { @@ -395,12 +389,11 @@ StatusBarCreateSoundTip(int part) _swprintf(tempTip, plat_get_string(IDS_2068)); if (sbTips[part] != NULL) - free(sbTips[part]); - sbTips[part] = (WCHAR *)malloc((wcslen(tempTip) << 1) + 2); + free(sbTips[part]); + sbTips[part] = (WCHAR *) malloc((wcslen(tempTip) << 1) + 2); wcscpy(sbTips[part], tempTip); } - /* API */ void ui_sb_update_tip(int meaning) @@ -408,486 +401,473 @@ ui_sb_update_tip(int meaning) uint8_t part = 0xff; if (!sb_ready || (sb_parts == 0) || (sb_part_meanings == NULL)) - return; + return; part = sb_map[meaning]; if (part != 0xff) { - switch(meaning & 0xf0) { - case SB_CASSETTE: - StatusBarCreateCassetteTip(part); - break; + switch (meaning & 0xf0) { + case SB_CASSETTE: + StatusBarCreateCassetteTip(part); + break; - case SB_CARTRIDGE: - StatusBarCreateCartridgeTip(part); - break; + case SB_CARTRIDGE: + StatusBarCreateCartridgeTip(part); + break; - case SB_FLOPPY: - StatusBarCreateFloppyTip(part); - break; + case SB_FLOPPY: + StatusBarCreateFloppyTip(part); + break; - case SB_CDROM: - StatusBarCreateCdromTip(part); - break; + case SB_CDROM: + StatusBarCreateCdromTip(part); + break; - case SB_ZIP: - StatusBarCreateZIPTip(part); - break; + case SB_ZIP: + StatusBarCreateZIPTip(part); + break; - case SB_MO: - StatusBarCreateMOTip(part); - break; + case SB_MO: + StatusBarCreateMOTip(part); + break; - case SB_HDD: - StatusBarCreateDiskTip(part); - break; + case SB_HDD: + StatusBarCreateDiskTip(part); + break; - case SB_NETWORK: - StatusBarCreateNetworkTip(part); - break; + case SB_NETWORK: + StatusBarCreateNetworkTip(part); + break; - case SB_SOUND: - StatusBarCreateSoundTip(part); - break; + case SB_SOUND: + StatusBarCreateSoundTip(part); + break; - default: - break; - } + default: + break; + } - SendMessage(hwndSBAR, SB_SETTIPTEXT, part, (LPARAM)sbTips[part]); + SendMessage(hwndSBAR, SB_SETTIPTEXT, part, (LPARAM) sbTips[part]); } } - static void StatusBarDestroyTips(void) { - int i; + if (sb_parts == 0) + return; - if (sb_parts == 0) return; + if (!sbTips) + return; - if (! sbTips) return; - - for (i=0; i 0) { - for (i = 0; i < sb_parts; i++) - SendMessage(hwndSBAR, SB_SETICON, i, (LPARAM)NULL); - SendMessage(hwndSBAR, SB_SETPARTS, (WPARAM)0, (LPARAM)NULL); + for (i = 0; i < sb_parts; i++) + SendMessage(hwndSBAR, SB_SETICON, i, (LPARAM) NULL); + SendMessage(hwndSBAR, SB_SETPARTS, (WPARAM) 0, (LPARAM) NULL); - if (iStatusWidths) { - free(iStatusWidths); - iStatusWidths = NULL; - } - if (sb_part_meanings) { - free(sb_part_meanings); - sb_part_meanings = NULL; - } - if (sb_part_icons) { - free(sb_part_icons); - sb_part_icons = NULL; - } - StatusBarDestroyTips(); + if (iStatusWidths) { + free(iStatusWidths); + iStatusWidths = NULL; + } + if (sb_part_meanings) { + free(sb_part_meanings); + sb_part_meanings = NULL; + } + if (sb_part_icons) { + free(sb_part_icons); + sb_part_icons = NULL; + } + StatusBarDestroyTips(); } memset(sb_map, 0xff, sizeof(sb_map)); sb_parts = 0; if (cassette_enable) - sb_parts++; + sb_parts++; if (cart_int) - sb_parts += 2; - for (i=0; i= (sb_parts - 1)) return; + if (id >= (sb_parts - 1)) + return; - pt.x = id * icon_width; /* Justify to the left. */ - pt.y = 0; /* Justify to the top. */ - ClientToScreen(hwnd, (LPPOINT) &pt); + pt.x = id * icon_width; /* Justify to the left. */ + pt.y = 0; /* Justify to the top. */ + ClientToScreen(hwnd, &pt); - switch(sb_part_meanings[id] & 0xF0) { - case SB_CASSETTE: - menu = media_menu_get_cassette(); - break; - case SB_CARTRIDGE: - menu = media_menu_get_cartridge(sb_part_meanings[id] & 0x0F); - break; - case SB_FLOPPY: - menu = media_menu_get_floppy(sb_part_meanings[id] & 0x0F); - break; - case SB_CDROM: - menu = media_menu_get_cdrom(sb_part_meanings[id] & 0x0F); - break; - case SB_ZIP: - menu = media_menu_get_zip(sb_part_meanings[id] & 0x0F); - break; - case SB_MO: - menu = media_menu_get_mo(sb_part_meanings[id] & 0x0F); - break; - default: - return; + switch (sb_part_meanings[id] & 0xF0) { + case SB_CASSETTE: + menu = media_menu_get_cassette(); + break; + case SB_CARTRIDGE: + menu = media_menu_get_cartridge(sb_part_meanings[id] & 0x0F); + break; + case SB_FLOPPY: + menu = media_menu_get_floppy(sb_part_meanings[id] & 0x0F); + break; + case SB_CDROM: + menu = media_menu_get_cdrom(sb_part_meanings[id] & 0x0F); + break; + case SB_ZIP: + menu = media_menu_get_zip(sb_part_meanings[id] & 0x0F); + break; + case SB_MO: + menu = media_menu_get_mo(sb_part_meanings[id] & 0x0F); + break; + default: + return; } TrackPopupMenu(menu, - TPM_LEFTALIGN | TPM_BOTTOMALIGN | TPM_LEFTBUTTON, - pt.x, pt.y, 0, hwndSBAR, NULL); + TPM_LEFTALIGN | TPM_BOTTOMALIGN | TPM_LEFTBUTTON, + pt.x, pt.y, 0, hwndSBAR, NULL); } /* API: Load status bar icons */ void -StatusBarLoadIcon(HINSTANCE hInst) { - win_load_icon_set(); +StatusBarLoadIcon(UNUSED(HINSTANCE hInst)) +{ + win_load_icon_set(); } /* Handle messages for the Status Bar window. */ @@ -898,77 +878,77 @@ static BOOL CALLBACK #endif StatusBarProcedure(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam) { - RECT rc; - POINT pt; - int item_id = 0; - int i; - HINSTANCE hInst; + RECT rc; + POINT pt; + int item_id = 0; + int i; + HINSTANCE hInst; switch (message) { - case WM_COMMAND: - media_menu_proc(hwnd, message, wParam, lParam); - return(0); + case WM_COMMAND: + media_menu_proc(hwnd, message, wParam, lParam); + return 0; - case WM_LBUTTONDOWN: - case WM_RBUTTONDOWN: - GetClientRect(hwnd, (LPRECT)& rc); - pt.x = GET_X_LPARAM(lParam); - pt.y = GET_Y_LPARAM(lParam); - if (PtInRect((LPRECT) &rc, pt)) - StatusBarPopupMenu(hwnd, pt, (pt.x / icon_width)); - break; + case WM_LBUTTONDOWN: + case WM_RBUTTONDOWN: + GetClientRect(hwnd, &rc); + pt.x = GET_X_LPARAM(lParam); + pt.y = GET_Y_LPARAM(lParam); + if (PtInRect(&rc, pt)) + StatusBarPopupMenu(hwnd, pt, (pt.x / icon_width)); + break; - case WM_LBUTTONDBLCLK: - GetClientRect(hwnd, (LPRECT)& rc); - pt.x = GET_X_LPARAM(lParam); - pt.y = GET_Y_LPARAM(lParam); - item_id = (pt.x / icon_width); - if (PtInRect((LPRECT) &rc, pt) && (item_id < sb_parts)) { - if (sb_part_meanings[item_id] == SB_SOUND) - SoundGainDialogCreate(hwndMain); - } - break; + case WM_LBUTTONDBLCLK: + GetClientRect(hwnd, &rc); + pt.x = GET_X_LPARAM(lParam); + pt.y = GET_Y_LPARAM(lParam); + item_id = (pt.x / icon_width); + if (PtInRect(&rc, pt) && (item_id < sb_parts)) { + if (sb_part_meanings[item_id] == SB_SOUND) + SoundGainDialogCreate(hwndMain); + } + break; - case WM_DPICHANGED_AFTERPARENT: - /* DPI changed, reload icons */ - hInst = (HINSTANCE)GetWindowLongPtr(hwnd, GWLP_HINSTANCE); - dpi = win_get_dpi(hwnd); - icon_width = MulDiv(SB_ICON_WIDTH, dpi, 96); - StatusBarLoadIcon(hInst); + case WM_DPICHANGED_AFTERPARENT: + /* DPI changed, reload icons */ + hInst = (HINSTANCE) GetWindowLongPtr(hwnd, GWLP_HINSTANCE); + dpi = win_get_dpi(hwnd); + icon_width = MulDiv(SB_ICON_WIDTH, dpi, 96); + StatusBarLoadIcon(hInst); - for (i=0; i - * Fred N. van Kempen, + * Authors: Sarah Walker, + * Fred N. van Kempen, * - * Copyright 2008-2018 Sarah Walker. - * Copyright 2017,2018 Fred N. van Kempen. + * Copyright 2008-2018 Sarah Walker. + * Copyright 2017-2018 Fred N. van Kempen. + * Copyright 2021-2023 Jasmine Iwanek. */ #define UNICODE #define BITMAP WINDOWS_BITMAP @@ -29,32 +30,40 @@ #include #include <86box/86box.h> #include <86box/plat.h> - +#include <86box/thread.h> typedef struct { HANDLE handle; } win_event_t; - thread_t * thread_create(void (*func)(void *param), void *param) { uintptr_t bt = _beginthread(func, 0, param); - return((thread_t *)bt); + return ((thread_t *) bt); } +int +thread_test_mutex(thread_t *arg) +{ + if (arg == NULL) + return 0; + + return (WaitForSingleObject(arg, 0) == WAIT_OBJECT_0) ? 1 : 0; +} int thread_wait(thread_t *arg) { - if (arg == NULL) return(0); + if (arg == NULL) + return 0; - if (WaitForSingleObject(arg, INFINITE)) return(1); + if (WaitForSingleObject(arg, INFINITE)) + return 1; - return(0); + return 0; } - event_t * thread_create_event(void) { @@ -62,66 +71,67 @@ thread_create_event(void) ev->handle = CreateEvent(NULL, FALSE, FALSE, NULL); - return((event_t *)ev); + return ((event_t *) ev); } - void thread_set_event(event_t *arg) { - win_event_t *ev = (win_event_t *)arg; + win_event_t *ev = (win_event_t *) arg; - if (arg == NULL) return; + if (arg == NULL) + return; SetEvent(ev->handle); } - void thread_reset_event(event_t *arg) { - win_event_t *ev = (win_event_t *)arg; + win_event_t *ev = (win_event_t *) arg; - if (arg == NULL) return; + if (arg == NULL) + return; ResetEvent(ev->handle); } - int thread_wait_event(event_t *arg, int timeout) { - win_event_t *ev = (win_event_t *)arg; + win_event_t *ev = (win_event_t *) arg; - if (arg == NULL) return(0); + if (arg == NULL) + return 0; - if (ev->handle == NULL) return(0); + if (ev->handle == NULL) + return 0; if (timeout == -1) - timeout = INFINITE; + timeout = INFINITE; - if (WaitForSingleObject(ev->handle, timeout)) return(1); + if (WaitForSingleObject(ev->handle, timeout)) + return 1; - return(0); + return 0; } - void thread_destroy_event(event_t *arg) { - win_event_t *ev = (win_event_t *)arg; + win_event_t *ev = (win_event_t *) arg; - if (arg == NULL) return; + if (arg == NULL) + return; CloseHandle(ev->handle); free(ev); } - mutex_t * thread_create_mutex(void) -{ +{ mutex_t *mutex = malloc(sizeof(CRITICAL_SECTION)); InitializeCriticalSection(mutex); @@ -129,39 +139,39 @@ thread_create_mutex(void) return mutex; } - int thread_wait_mutex(mutex_t *mutex) { - if (mutex == NULL) return(0); + if (mutex == NULL) + return 0; - LPCRITICAL_SECTION critsec = (LPCRITICAL_SECTION)mutex; + LPCRITICAL_SECTION critsec = (LPCRITICAL_SECTION) mutex; EnterCriticalSection(critsec); return 1; } - int thread_release_mutex(mutex_t *mutex) { - if (mutex == NULL) return(0); + if (mutex == NULL) + return 0; - LPCRITICAL_SECTION critsec = (LPCRITICAL_SECTION)mutex; + LPCRITICAL_SECTION critsec = (LPCRITICAL_SECTION) mutex; LeaveCriticalSection(critsec); return 1; } - void thread_close_mutex(mutex_t *mutex) { - if (mutex == NULL) return; + if (mutex == NULL) + return; - LPCRITICAL_SECTION critsec = (LPCRITICAL_SECTION)mutex; + LPCRITICAL_SECTION critsec = (LPCRITICAL_SECTION) mutex; DeleteCriticalSection(critsec); diff --git a/src/win/win_toolbar.c b/src/win/win_toolbar.c index a0291672f..5c8621eea 100644 --- a/src/win/win_toolbar.c +++ b/src/win/win_toolbar.c @@ -2,44 +2,43 @@ #include #include #include -#include -#include +#include +#include #include <86box/86box.h> #include <86box/plat.h> #include <86box/resource.h> #include <86box/ui.h> +#include <86box/video.h> #include <86box/win.h> -HWND hwndRebar = NULL; -static HWND hwndToolbar = NULL; -static HIMAGELIST hImageList = NULL; -static wchar_t wTitle[512] = { 0 }; -static WNDPROC pOriginalProcedure = NULL; - +HWND hwndRebar = NULL; +static HWND hwndToolbar = NULL; +static HIMAGELIST hImageList = NULL; +static wchar_t wTitle[512] = { 0 }; +static WNDPROC pOriginalProcedure = NULL; enum image_index { - RUN, - PAUSE, - CTRL_ALT_DEL, - CTRL_ALT_ESC, - HARD_RESET, - ACPI_SHUTDOWN, - SETTINGS + RUN, + PAUSE, + CTRL_ALT_DEL, + CTRL_ALT_ESC, + HARD_RESET, + ACPI_SHUTDOWN, + SETTINGS }; - void -ToolBarLoadIcons() +ToolBarLoadIcons(void) { if (!hwndToolbar) - return; + return; if (hImageList) - ImageList_Destroy(hImageList); + ImageList_Destroy(hImageList); hImageList = ImageList_Create(win_get_system_metrics(SM_CXSMICON, dpi), - win_get_system_metrics(SM_CYSMICON, dpi), - ILC_MASK | ILC_COLOR32, 1, 1); + win_get_system_metrics(SM_CYSMICON, dpi), + ILC_MASK | ILC_COLOR32, 1, 1); // The icons must be loaded in the same order as the `image_index` // enumeration above. @@ -55,55 +54,54 @@ ToolBarLoadIcons() SendMessage(hwndToolbar, TB_SETIMAGELIST, 0, (LPARAM) hImageList); } - int ToolBarProcedure(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam) { switch (message) { - case WM_NOTIFY: - switch (((LPNMHDR) lParam)->code) { - case TTN_GETDISPINFO: { - LPTOOLTIPTEXT lpttt = (LPTOOLTIPTEXT)lParam; - - // Set the instance of the module that contains the resource. - lpttt->hinst = hinstance; - - uintptr_t idButton = lpttt->hdr.idFrom; - - switch (idButton) { - case IDM_ACTION_PAUSE: - if (dopause) - lpttt->lpszText = MAKEINTRESOURCE(IDS_2154); - else - lpttt->lpszText = MAKEINTRESOURCE(IDS_2155); - break; - - case IDM_ACTION_RESET_CAD: - lpttt->lpszText = MAKEINTRESOURCE(IDS_2156); - break; + case WM_NOTIFY: + switch (((LPNMHDR) lParam)->code) { + case TTN_GETDISPINFO: + { + LPTOOLTIPTEXT lpttt = (LPTOOLTIPTEXT) lParam; - case IDM_ACTION_CTRL_ALT_ESC: - lpttt->lpszText = MAKEINTRESOURCE(IDS_2157); - break; + // Set the instance of the module that contains the resource. + lpttt->hinst = hinstance; - case IDM_ACTION_HRESET: - lpttt->lpszText = MAKEINTRESOURCE(IDS_2158); - break; - - case IDM_CONFIG: - lpttt->lpszText = MAKEINTRESOURCE(IDS_2160); - break; - } - - return TRUE; - } - } + uintptr_t idButton = lpttt->hdr.idFrom; + + switch (idButton) { + case IDM_ACTION_PAUSE: + if (dopause) + lpttt->lpszText = MAKEINTRESOURCE(IDS_2155); + else + lpttt->lpszText = MAKEINTRESOURCE(IDS_2156); + break; + + case IDM_ACTION_RESET_CAD: + lpttt->lpszText = MAKEINTRESOURCE(IDS_2157); + break; + + case IDM_ACTION_CTRL_ALT_ESC: + lpttt->lpszText = MAKEINTRESOURCE(IDS_2158); + break; + + case IDM_ACTION_HRESET: + lpttt->lpszText = MAKEINTRESOURCE(IDS_2159); + break; + + case IDM_CONFIG: + lpttt->lpszText = MAKEINTRESOURCE(IDS_2161); + break; + } + + return TRUE; + } + } } - return(CallWindowProc(pOriginalProcedure, hwnd, message, wParam, lParam)); + return (CallWindowProc(pOriginalProcedure, hwnd, message, wParam, lParam)); } - void ToolBarUpdatePause(int pause) { @@ -116,35 +114,29 @@ ToolBarUpdatePause(int pause) SendMessage(hwndToolbar, TB_SETBUTTONINFO, IDM_ACTION_PAUSE, (LPARAM) &tbbi); } - static TBBUTTON buttons[] = { - { PAUSE, IDM_ACTION_PAUSE, TBSTATE_ENABLED, BTNS_BUTTON, { 0 }, 0, 0 }, - { HARD_RESET, IDM_ACTION_HRESET, TBSTATE_ENABLED, BTNS_BUTTON, { 0 }, 0, 0 }, - { ACPI_SHUTDOWN, 0, TBSTATE_HIDDEN, BTNS_BUTTON, { 0 }, 0, 0 }, - { 0, 0, TBSTATE_INDETERMINATE, BTNS_SEP, { 0 }, 0, 0 }, - { CTRL_ALT_DEL, IDM_ACTION_RESET_CAD, TBSTATE_ENABLED, BTNS_BUTTON, { 0 }, 0, 0 }, - { CTRL_ALT_ESC, IDM_ACTION_CTRL_ALT_ESC, TBSTATE_ENABLED, BTNS_BUTTON, { 0 }, 0, 0 }, - { 0, 0, TBSTATE_INDETERMINATE, BTNS_SEP, { 0 }, 0, 0 }, - { SETTINGS, IDM_CONFIG, TBSTATE_ENABLED, BTNS_BUTTON, { 0 }, 0, 0 } + {PAUSE, IDM_ACTION_PAUSE, TBSTATE_ENABLED, BTNS_BUTTON, { 0 }, 0, 0}, + { HARD_RESET, IDM_ACTION_HRESET, TBSTATE_ENABLED, BTNS_BUTTON, { 0 }, 0, 0}, + { ACPI_SHUTDOWN, 0, TBSTATE_HIDDEN, BTNS_BUTTON, { 0 }, 0, 0}, + { 0, 0, TBSTATE_INDETERMINATE, BTNS_SEP, { 0 }, 0, 0}, + { CTRL_ALT_DEL, IDM_ACTION_RESET_CAD, TBSTATE_ENABLED, BTNS_BUTTON, { 0 }, 0, 0}, + { CTRL_ALT_ESC, IDM_ACTION_CTRL_ALT_ESC, TBSTATE_ENABLED, BTNS_BUTTON, { 0 }, 0, 0}, + { 0, 0, TBSTATE_INDETERMINATE, BTNS_SEP, { 0 }, 0, 0}, + { SETTINGS, IDM_CONFIG, TBSTATE_ENABLED, BTNS_BUTTON, { 0 }, 0, 0} }; - void ToolBarCreate(HWND hwndParent, HINSTANCE hInst) { - REBARINFO rbi = { 0 }; + REBARINFO rbi = { 0 }; REBARBANDINFO rbbi = { 0 }; - int btnSize; + int btnSize; // Create the toolbar. hwndToolbar = CreateWindowEx(WS_EX_PALETTEWINDOW, TOOLBARCLASSNAME, NULL, - WS_CHILD | WS_VISIBLE | WS_CLIPCHILDREN | - WS_CLIPSIBLINGS | TBSTYLE_TOOLTIPS | - TBSTYLE_FLAT | CCS_TOP | BTNS_AUTOSIZE | - CCS_NOPARENTALIGN | CCS_NORESIZE | - CCS_NODIVIDER, - 0, 0, 0, 0, - hwndParent, NULL, hInst, NULL); + WS_CHILD | WS_VISIBLE | WS_CLIPCHILDREN | WS_CLIPSIBLINGS | TBSTYLE_TOOLTIPS | TBSTYLE_FLAT | CCS_TOP | BTNS_AUTOSIZE | CCS_NOPARENTALIGN | CCS_NORESIZE | CCS_NODIVIDER, + 0, 0, 0, 0, + hwndParent, NULL, hInst, NULL); ToolBarLoadIcons(); @@ -153,41 +145,39 @@ ToolBarCreate(HWND hwndParent, HINSTANCE hInst) SendMessage(hwndToolbar, TB_ADDBUTTONS, sizeof(buttons) / sizeof(TBBUTTON), (LPARAM) &buttons); // Autosize the toolbar and determine its size. - btnSize = LOWORD(SendMessage(hwndToolbar, TB_GETBUTTONSIZE, 0,0)); + btnSize = LOWORD(SendMessage(hwndToolbar, TB_GETBUTTONSIZE, 0, 0)); // Replace the original procedure with ours. pOriginalProcedure = (WNDPROC) GetWindowLongPtr(hwndToolbar, GWLP_WNDPROC); - SetWindowLongPtr(hwndToolbar, GWLP_WNDPROC, (LONG_PTR)&ToolBarProcedure); + SetWindowLongPtr(hwndToolbar, GWLP_WNDPROC, (LONG_PTR) &ToolBarProcedure); // Make sure the Pause button is in the correct state. ToolBarUpdatePause(dopause); // Create the containing Rebar. hwndRebar = CreateWindowEx(0, REBARCLASSNAME, NULL, - WS_CHILD | WS_VISIBLE | WS_CLIPSIBLINGS | - WS_CLIPCHILDREN | RBS_VARHEIGHT | - CCS_NODIVIDER | CCS_NOPARENTALIGN, - 0, 0, scrnsz_x, 0, - hwndParent, NULL, hInst, NULL); + WS_CHILD | WS_VISIBLE | WS_CLIPSIBLINGS | WS_CLIPCHILDREN | RBS_VARHEIGHT | CCS_NODIVIDER | CCS_NOPARENTALIGN, + 0, 0, scrnsz_x, 0, + hwndParent, NULL, hInst, NULL); // Create and send the REBARINFO structure. rbi.cbSize = sizeof(rbi); - SendMessage(hwndRebar, RB_SETBARINFO, 0, (LPARAM)&rbi); + SendMessage(hwndRebar, RB_SETBARINFO, 0, (LPARAM) &rbi); // Add the toolbar to the rebar. - rbbi.cbSize = sizeof(rbbi); - rbbi.fMask = RBBIM_CHILD | RBBIM_CHILDSIZE | RBBIM_STYLE; - rbbi.hwndChild = hwndToolbar; + rbbi.cbSize = sizeof(rbbi); + rbbi.fMask = RBBIM_CHILD | RBBIM_CHILDSIZE | RBBIM_STYLE; + rbbi.hwndChild = hwndToolbar; rbbi.cxMinChild = 0; rbbi.cyMinChild = btnSize; - rbbi.fStyle = RBBS_NOGRIPPER; - SendMessage(hwndRebar, RB_INSERTBAND, -1, (LPARAM)&rbbi); + rbbi.fStyle = RBBS_NOGRIPPER; + SendMessage(hwndRebar, RB_INSERTBAND, -1, (LPARAM) &rbbi); // Add a label for machine information. - rbbi.fMask = RBBIM_TEXT | RBBIM_STYLE; + rbbi.fMask = RBBIM_TEXT | RBBIM_STYLE; rbbi.lpText = TEXT("Test"); rbbi.fStyle = RBBS_NOGRIPPER; - SendMessage(hwndRebar, RB_INSERTBAND, -1, (LPARAM)&rbbi); + SendMessage(hwndRebar, RB_INSERTBAND, -1, (LPARAM) &rbbi); SendMessage(hwndRebar, RB_MAXIMIZEBAND, 0, 0); ShowWindow(hwndRebar, TRUE); @@ -195,25 +185,24 @@ ToolBarCreate(HWND hwndParent, HINSTANCE hInst) return; } - wchar_t * ui_window_title(wchar_t *s) { REBARBANDINFO rbbi = { 0 }; - if (! video_fullscreen) { - if (s != NULL) { - wcsncpy(wTitle, s, sizeof_w(wTitle) - 1); - } else - s = wTitle; + if (!video_fullscreen) { + if (s != NULL) { + wcsncpy(wTitle, s, sizeof_w(wTitle) - 1); + } else + s = wTitle; - rbbi.cbSize = sizeof(rbbi); - rbbi.fMask = RBBIM_TEXT; - rbbi.lpText = s; - SendMessage(hwndRebar, RB_SETBANDINFO, 1, (LPARAM) &rbbi); + rbbi.cbSize = sizeof(rbbi); + rbbi.fMask = RBBIM_TEXT; + rbbi.lpText = s; + SendMessage(hwndRebar, RB_SETBANDINFO, 1, (LPARAM) &rbbi); } else { - if (s == NULL) - s = wTitle; + if (s == NULL) + s = wTitle; } - return(s); + return s; } diff --git a/src/win/win_ui.c b/src/win/win_ui.c index 0883e4e93..73119140c 100644 --- a/src/win/win_ui.c +++ b/src/win/win_ui.c @@ -1,24 +1,27 @@ /* - * 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. + * 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. + * This file is part of the 86Box distribution. * - * user Interface module for WinAPI on Windows. + * user Interface module for WinAPI on Windows. * * * - * Authors: Sarah Walker, - * Miran Grca, - * Fred N. van Kempen, + * Authors: Sarah Walker, + * Miran Grca, + * Fred N. van Kempen, + * Jasmine Iwanek, * - * Copyright 2008-2020 Sarah Walker. - * Copyright 2016-2020 Miran Grca. - * Copyright 2017-2020 Fred N. van Kempen. - * Copyright 2019,2020 GH Cao. + * Copyright 2008-2020 Sarah Walker. + * Copyright 2016-2020 Miran Grca. + * Copyright 2017-2020 Fred N. van Kempen. + * Copyright 2019-2020 GH Cao. + * Copyright 2021-2023 Jasmine Iwanek. */ +#include #define UNICODE #include #include @@ -38,83 +41,91 @@ #include <86box/timer.h> #include <86box/nvr.h> #include <86box/video.h> -#include <86box/vid_ega.h> // for update_overscan +#include <86box/vid_ega.h> // for update_overscan #include <86box/plat_dynld.h> #include <86box/ui.h> #include <86box/win.h> #include <86box/version.h> -#include <86box/discord.h> - -#ifdef MTR_ENABLED -#include +#ifdef DISCORD +# include <86box/discord.h> #endif -#define TIMER_1SEC 1 /* ID of the one-second timer */ +#ifdef MTR_ENABLED +# include +#endif +#define TIMER_1SEC 1 /* ID of the one-second timer */ /* Platform Public data, specific. */ -HWND hwndMain = NULL, /* application main window */ - hwndRender = NULL; /* machine render window */ -HMENU menuMain; /* application main menu */ -RECT oldclip; /* mouse rect */ -int sbar_height = 23; /* statusbar height */ -int tbar_height = 23; /* toolbar height */ -int minimized = 0; -int infocus = 1, button_down = 0; -int rctrl_is_lalt = 0; -int user_resize = 0; -int fixed_size_x = 0, fixed_size_y = 0; -int kbd_req_capture = 0; -int hide_status_bar = 0; -int hide_tool_bar = 0; -int status_icons_fullscreen = 0; /* unused. */ -int dpi = 96; +HWND hwndMain = NULL; /* application main window */ +HWND hwndRender = NULL; /* machine render window */ +HWND hwndRender2 = NULL; /* machine second screen render window */ +HMENU menuMain; /* application main menu */ +RECT oldclip; /* mouse rect */ +int sbar_height = 23; /* statusbar height */ +int tbar_height = 23; /* toolbar height */ +int minimized = 0; +int infocus = 1; +int button_down = 0; +int rctrl_is_lalt = 0; +int user_resize = 0; +int fixed_size_x = 0; +int fixed_size_y = 0; +int kbd_req_capture = 0; +int hide_status_bar = 0; +int hide_tool_bar = 0; +int dpi = 96; -extern char openfilestring[512]; -extern WCHAR wopenfilestring[512]; +int status_icons_fullscreen = 0; /* unused. */ +extern char openfilestring[512]; +extern WCHAR wopenfilestring[512]; /* Local data. */ -static int manager_wm = 0; -static int save_window_pos = 0, pause_state = 0; -static int padded_frame = 0; -static int vis = -1; +static int manager_wm = 0; +static int save_window_pos = 0; +static int pause_state = 0; +static int padded_frame = 0; +static int vis = -1; /* Per Monitor DPI Aware v2 APIs, Windows 10 v1703+ */ -void* user32_handle = NULL; -static UINT (WINAPI *pGetDpiForWindow)(HWND); -static UINT (WINAPI *pGetSystemMetricsForDpi)(int i, UINT dpi); -static DPI_AWARENESS_CONTEXT (WINAPI *pGetWindowDpiAwarenessContext)(HWND); -static BOOL (WINAPI *pAreDpiAwarenessContextsEqual)(DPI_AWARENESS_CONTEXT A, DPI_AWARENESS_CONTEXT B); +void *user32_handle = NULL; +static UINT(WINAPI *pGetDpiForWindow)(HWND); +static UINT(WINAPI *pGetSystemMetricsForDpi)(int i, UINT dpi); +static DPI_AWARENESS_CONTEXT(WINAPI *pGetWindowDpiAwarenessContext)(HWND); +static BOOL(WINAPI *pAreDpiAwarenessContextsEqual)(DPI_AWARENESS_CONTEXT A, DPI_AWARENESS_CONTEXT B); static dllimp_t user32_imports[] = { -{ "GetDpiForWindow", &pGetDpiForWindow }, -{ "GetSystemMetricsForDpi", &pGetSystemMetricsForDpi }, -{ "GetWindowDpiAwarenessContext", &pGetWindowDpiAwarenessContext }, -{ "AreDpiAwarenessContextsEqual", &pAreDpiAwarenessContextsEqual }, -{ NULL, NULL } + {"GetDpiForWindow", &pGetDpiForWindow }, + { "GetSystemMetricsForDpi", &pGetSystemMetricsForDpi }, + { "GetWindowDpiAwarenessContext", &pGetWindowDpiAwarenessContext}, + { "AreDpiAwarenessContextsEqual", &pAreDpiAwarenessContextsEqual}, + { NULL, NULL } }; /* Taskbar application ID API, Windows 7+ */ -void* shell32_handle = NULL; -static HRESULT (WINAPI *pSetCurrentProcessExplicitAppUserModelID)(PCWSTR AppID); -static dllimp_t shell32_imports[]= { -{ "SetCurrentProcessExplicitAppUserModelID", &pSetCurrentProcessExplicitAppUserModelID }, -{ NULL, NULL } +void *shell32_handle = NULL; +static HRESULT(WINAPI *pSetCurrentProcessExplicitAppUserModelID)(PCWSTR AppID); +static dllimp_t shell32_imports[] = { + {"SetCurrentProcessExplicitAppUserModelID", &pSetCurrentProcessExplicitAppUserModelID}, + { NULL, NULL } }; int -win_get_dpi(HWND hwnd) { +win_get_dpi(HWND hwnd) +{ if (user32_handle != NULL) { return pGetDpiForWindow(hwnd); } else { - HDC dc = GetDC(hwnd); + HDC dc = GetDC(hwnd); UINT dpi = GetDeviceCaps(dc, LOGPIXELSX); ReleaseDC(hwnd, dc); return dpi; } } -int win_get_system_metrics(int index, int dpi) { +int +win_get_system_metrics(int index, int dpi) +{ if (user32_handle != NULL) { /* Only call GetSystemMetricsForDpi when we are using PMv2 */ DPI_AWARENESS_CONTEXT c = pGetWindowDpiAwarenessContext(hwndMain); @@ -128,19 +139,19 @@ int win_get_system_metrics(int index, int dpi) { void ResizeWindowByClientArea(HWND hwnd, int width, int height) { - if ((vid_resize == 1) || padded_frame) { - int padding = win_get_system_metrics(SM_CXPADDEDBORDER, dpi); - width += (win_get_system_metrics(SM_CXFRAME, dpi) + padding) * 2; - height += (win_get_system_metrics(SM_CYFRAME, dpi) + padding) * 2; - } else { - width += win_get_system_metrics(SM_CXFIXEDFRAME, dpi) * 2; - height += win_get_system_metrics(SM_CYFIXEDFRAME, dpi) * 2; - } + if ((vid_resize == 1) || padded_frame) { + int padding = win_get_system_metrics(SM_CXPADDEDBORDER, dpi); + width += (win_get_system_metrics(SM_CXFRAME, dpi) + padding) * 2; + height += (win_get_system_metrics(SM_CYFRAME, dpi) + padding) * 2; + } else { + width += win_get_system_metrics(SM_CXFIXEDFRAME, dpi) * 2; + height += win_get_system_metrics(SM_CYFIXEDFRAME, dpi) * 2; + } - height += win_get_system_metrics(SM_CYCAPTION, dpi); - height += win_get_system_metrics(SM_CYBORDER, dpi) + win_get_system_metrics(SM_CYMENUSIZE, dpi); + height += win_get_system_metrics(SM_CYCAPTION, dpi); + height += win_get_system_metrics(SM_CYBORDER, dpi) + win_get_system_metrics(SM_CYMENUSIZE, dpi); - SetWindowPos(hwnd, NULL, 0, 0, width, height, SWP_NOMOVE); + SetWindowPos(hwnd, NULL, 0, 0, width, height, SWP_NOMOVE); } /* Set host cursor visible or not. */ @@ -148,13 +159,14 @@ void show_cursor(int val) { if (val == vis) - return; + return; if (val == 0) { - while (1) - if (ShowCursor(FALSE) < 0) break; + while (1) + if (ShowCursor(FALSE) < 0) + break; } else - ShowCursor(TRUE); + ShowCursor(TRUE); vis = val; } @@ -174,74 +186,66 @@ video_toggle_option(HMENU h, int *val, int id) static int delete_submenu(HMENU parent, HMENU target) { - for (int i = 0; i < GetMenuItemCount(parent); i++) - { - MENUITEMINFO mii; - mii.cbSize = sizeof(mii); - mii.fMask = MIIM_SUBMENU; + for (int i = 0; i < GetMenuItemCount(parent); i++) { + MENUITEMINFO mii; + mii.cbSize = sizeof(mii); + mii.fMask = MIIM_SUBMENU; - if (GetMenuItemInfo(parent, i, TRUE, &mii) != 0) - { - if (mii.hSubMenu == target) - { - DeleteMenu(parent, i, MF_BYPOSITION); - return 1; - } - else if (mii.hSubMenu != NULL) - { - if (delete_submenu(mii.hSubMenu, target)) - return 1; - } - } - } + if (GetMenuItemInfo(parent, i, TRUE, &mii) != 0) { + if (mii.hSubMenu == target) { + DeleteMenu(parent, i, MF_BYPOSITION); + return 1; + } else if (mii.hSubMenu != NULL) { + if (delete_submenu(mii.hSubMenu, target)) + return 1; + } + } + } - return 0; + return 0; } -static int menu_vidapi = -1; -static HMENU cur_menu = NULL; +static int menu_vidapi = -1; +static HMENU cur_menu = NULL; static void -show_render_options_menu() +show_render_options_menu(void) { - if (vid_api == menu_vidapi) - return; - - if (cur_menu != NULL) - { - if (delete_submenu(menuMain, cur_menu)) - cur_menu = NULL; - } - - if (cur_menu == NULL) - { - switch (IDM_VID_SDL_SW + vid_api) - { - case IDM_VID_OPENGL_CORE: - cur_menu = LoadMenu(hinstance, VID_GL_SUBMENU); - InsertMenu(GetSubMenu(menuMain, 1), 6, MF_BYPOSITION | MF_STRING | MF_POPUP, (UINT_PTR)cur_menu, plat_get_string(IDS_2144)); - CheckMenuItem(menuMain, IDM_VID_GL_FPS_BLITTER, video_framerate == -1 ? MF_CHECKED : MF_UNCHECKED); - CheckMenuItem(menuMain, IDM_VID_GL_FPS_25, video_framerate == 25 ? MF_CHECKED : MF_UNCHECKED); - CheckMenuItem(menuMain, IDM_VID_GL_FPS_30, video_framerate == 30 ? MF_CHECKED : MF_UNCHECKED); - CheckMenuItem(menuMain, IDM_VID_GL_FPS_50, video_framerate == 50 ? MF_CHECKED : MF_UNCHECKED); - CheckMenuItem(menuMain, IDM_VID_GL_FPS_60, video_framerate == 60 ? MF_CHECKED : MF_UNCHECKED); - CheckMenuItem(menuMain, IDM_VID_GL_FPS_75, video_framerate == 75 ? MF_CHECKED : MF_UNCHECKED); - CheckMenuItem(menuMain, IDM_VID_GL_VSYNC, video_vsync ? MF_CHECKED : MF_UNCHECKED); - EnableMenuItem(menuMain, IDM_VID_GL_NOSHADER, strlen(video_shader) > 0 ? MF_ENABLED : MF_DISABLED); - break; - } - } + if (vid_api == menu_vidapi) + return; - menu_vidapi = vid_api; + if (cur_menu != NULL) { + if (delete_submenu(menuMain, cur_menu)) + cur_menu = NULL; + } + + if (cur_menu == NULL) { + switch (IDM_VID_SDL_SW + vid_api) { + case IDM_VID_OPENGL_CORE: + cur_menu = LoadMenu(hinstance, VID_GL_SUBMENU); + InsertMenu(GetSubMenu(menuMain, 1), 6, MF_BYPOSITION | MF_STRING | MF_POPUP, (UINT_PTR) cur_menu, plat_get_string(IDS_2145)); + CheckMenuItem(menuMain, IDM_VID_GL_FPS_BLITTER, video_framerate == -1 ? MF_CHECKED : MF_UNCHECKED); + CheckMenuItem(menuMain, IDM_VID_GL_FPS_25, video_framerate == 25 ? MF_CHECKED : MF_UNCHECKED); + CheckMenuItem(menuMain, IDM_VID_GL_FPS_30, video_framerate == 30 ? MF_CHECKED : MF_UNCHECKED); + CheckMenuItem(menuMain, IDM_VID_GL_FPS_50, video_framerate == 50 ? MF_CHECKED : MF_UNCHECKED); + CheckMenuItem(menuMain, IDM_VID_GL_FPS_60, video_framerate == 60 ? MF_CHECKED : MF_UNCHECKED); + CheckMenuItem(menuMain, IDM_VID_GL_FPS_75, video_framerate == 75 ? MF_CHECKED : MF_UNCHECKED); + CheckMenuItem(menuMain, IDM_VID_GL_VSYNC, video_vsync ? MF_CHECKED : MF_UNCHECKED); + EnableMenuItem(menuMain, IDM_VID_GL_NOSHADER, strlen(video_shader) > 0 ? MF_ENABLED : MF_DISABLED); + break; + } + } + + menu_vidapi = vid_api; } static void -video_set_filter_menu(HMENU menu) +video_set_filter_menu(HMENU menu) { - CheckMenuItem(menu, IDM_VID_FILTER_NEAREST, vid_api == 0 || video_filter_method == 0 ? MF_CHECKED : MF_UNCHECKED); - CheckMenuItem(menu, IDM_VID_FILTER_LINEAR, vid_api != 0 && video_filter_method == 1 ? MF_CHECKED : MF_UNCHECKED); - EnableMenuItem(menu, IDM_VID_FILTER_NEAREST, vid_api == 0 ? MF_GRAYED : MF_ENABLED); - EnableMenuItem(menu, IDM_VID_FILTER_LINEAR, vid_api == 0 ? MF_GRAYED : MF_ENABLED); + CheckMenuItem(menu, IDM_VID_FILTER_NEAREST, vid_api == 0 || video_filter_method == 0 ? MF_CHECKED : MF_UNCHECKED); + CheckMenuItem(menu, IDM_VID_FILTER_LINEAR, vid_api != 0 && video_filter_method == 1 ? MF_CHECKED : MF_UNCHECKED); + EnableMenuItem(menu, IDM_VID_FILTER_NEAREST, vid_api == 0 ? MF_GRAYED : MF_ENABLED); + EnableMenuItem(menu, IDM_VID_FILTER_LINEAR, vid_api == 0 ? MF_GRAYED : MF_ENABLED); } void @@ -258,39 +262,46 @@ ResetAllMenus(void) CheckMenuItem(menuMain, IDM_VID_OVERSCAN, MF_UNCHECKED); CheckMenuItem(menuMain, IDM_VID_INVERT, MF_UNCHECKED); + CheckMenuItem(menuMain, IDM_VID_MONITORS, MF_UNCHECKED); CheckMenuItem(menuMain, IDM_VID_RESIZE, MF_UNCHECKED); CheckMenuItem(menuMain, IDM_VID_SDL_SW, MF_UNCHECKED); CheckMenuItem(menuMain, IDM_VID_SDL_HW, MF_UNCHECKED); CheckMenuItem(menuMain, IDM_VID_SDL_OPENGL, MF_UNCHECKED); CheckMenuItem(menuMain, IDM_VID_OPENGL_CORE, MF_UNCHECKED); - + menu_vidapi = -1; - cur_menu = NULL; + cur_menu = NULL; show_render_options_menu(); #ifdef USE_VNC CheckMenuItem(menuMain, IDM_VID_VNC, MF_UNCHECKED); #endif - CheckMenuItem(menuMain, IDM_VID_FS_FULL+0, MF_UNCHECKED); - CheckMenuItem(menuMain, IDM_VID_FS_FULL+1, MF_UNCHECKED); - CheckMenuItem(menuMain, IDM_VID_FS_FULL+2, MF_UNCHECKED); - CheckMenuItem(menuMain, IDM_VID_FS_FULL+3, MF_UNCHECKED); - CheckMenuItem(menuMain, IDM_VID_FS_FULL+4, MF_UNCHECKED); + CheckMenuItem(menuMain, IDM_VID_FS_FULL, MF_UNCHECKED); + CheckMenuItem(menuMain, IDM_VID_FS_43, MF_UNCHECKED); + CheckMenuItem(menuMain, IDM_VID_FS_KEEPRATIO, MF_UNCHECKED); + CheckMenuItem(menuMain, IDM_VID_FS_INT, MF_UNCHECKED); + CheckMenuItem(menuMain, IDM_VID_SPECIFY_DIM, MF_UNCHECKED); CheckMenuItem(menuMain, IDM_VID_REMEMBER, MF_UNCHECKED); - CheckMenuItem(menuMain, IDM_VID_SCALE_1X+0, MF_UNCHECKED); - CheckMenuItem(menuMain, IDM_VID_SCALE_1X+1, MF_UNCHECKED); - CheckMenuItem(menuMain, IDM_VID_SCALE_1X+2, MF_UNCHECKED); - CheckMenuItem(menuMain, IDM_VID_SCALE_1X+3, MF_UNCHECKED); - CheckMenuItem(menuMain, IDM_VID_HIDPI, MF_UNCHECKED); + CheckMenuItem(menuMain, IDM_VID_SCALE_1X, MF_UNCHECKED); + CheckMenuItem(menuMain, IDM_VID_SCALE_2X, MF_UNCHECKED); + CheckMenuItem(menuMain, IDM_VID_SCALE_3X, MF_UNCHECKED); + CheckMenuItem(menuMain, IDM_VID_SCALE_4X, MF_UNCHECKED); + CheckMenuItem(menuMain, IDM_VID_SCALE_5X, MF_UNCHECKED); + CheckMenuItem(menuMain, IDM_VID_SCALE_6X, MF_UNCHECKED); + CheckMenuItem(menuMain, IDM_VID_SCALE_7X, MF_UNCHECKED); + CheckMenuItem(menuMain, IDM_VID_SCALE_8X, MF_UNCHECKED); + CheckMenuItem(menuMain, IDM_VID_SCALE_9X, MF_UNCHECKED); + CheckMenuItem(menuMain, IDM_VID_SCALE_10X, MF_UNCHECKED); + CheckMenuItem(menuMain, IDM_VID_HIDPI, MF_UNCHECKED); CheckMenuItem(menuMain, IDM_VID_CGACON, MF_UNCHECKED); - CheckMenuItem(menuMain, IDM_VID_GRAYCT_601+0, MF_UNCHECKED); - CheckMenuItem(menuMain, IDM_VID_GRAYCT_601+1, MF_UNCHECKED); - CheckMenuItem(menuMain, IDM_VID_GRAYCT_601+2, MF_UNCHECKED); - CheckMenuItem(menuMain, IDM_VID_GRAY_RGB+0, MF_UNCHECKED); - CheckMenuItem(menuMain, IDM_VID_GRAY_RGB+1, MF_UNCHECKED); - CheckMenuItem(menuMain, IDM_VID_GRAY_RGB+2, MF_UNCHECKED); - CheckMenuItem(menuMain, IDM_VID_GRAY_RGB+3, MF_UNCHECKED); - CheckMenuItem(menuMain, IDM_VID_GRAY_RGB+4, MF_UNCHECKED); + CheckMenuItem(menuMain, IDM_VID_GRAYCT_601, MF_UNCHECKED); + CheckMenuItem(menuMain, IDM_VID_GRAYCT_709, MF_UNCHECKED); + CheckMenuItem(menuMain, IDM_VID_GRAYCT_AVE, MF_UNCHECKED); + CheckMenuItem(menuMain, IDM_VID_GRAY_RGB, MF_UNCHECKED); + CheckMenuItem(menuMain, IDM_VID_GRAY_MONO, MF_UNCHECKED); + CheckMenuItem(menuMain, IDM_VID_GRAY_AMBER, MF_UNCHECKED); + CheckMenuItem(menuMain, IDM_VID_GRAY_GREEN, MF_UNCHECKED); + CheckMenuItem(menuMain, IDM_VID_GRAY_WHITE, MF_UNCHECKED); CheckMenuItem(menuMain, IDM_ACTION_RCTRL_IS_LALT, rctrl_is_lalt ? MF_CHECKED : MF_UNCHECKED); CheckMenuItem(menuMain, IDM_ACTION_KBD_REQ_CAPTURE, kbd_req_capture ? MF_CHECKED : MF_UNCHECKED); @@ -299,69 +310,78 @@ ResetAllMenus(void) CheckMenuItem(menuMain, IDM_VID_HIDE_STATUS_BAR, hide_status_bar ? MF_CHECKED : MF_UNCHECKED); CheckMenuItem(menuMain, IDM_VID_HIDE_TOOLBAR, hide_tool_bar ? MF_CHECKED : MF_UNCHECKED); - CheckMenuItem(menuMain, IDM_VID_FORCE43, force_43?MF_CHECKED:MF_UNCHECKED); - CheckMenuItem(menuMain, IDM_VID_OVERSCAN, enable_overscan?MF_CHECKED:MF_UNCHECKED); + CheckMenuItem(menuMain, IDM_VID_FORCE43, force_43 ? MF_CHECKED : MF_UNCHECKED); + CheckMenuItem(menuMain, IDM_VID_OVERSCAN, enable_overscan ? MF_CHECKED : MF_UNCHECKED); CheckMenuItem(menuMain, IDM_VID_INVERT, invert_display ? MF_CHECKED : MF_UNCHECKED); - if (vid_resize == 1) - CheckMenuItem(menuMain, IDM_VID_RESIZE, MF_CHECKED); - CheckMenuItem(menuMain, IDM_VID_SDL_SW+vid_api, MF_CHECKED); - CheckMenuItem(menuMain, IDM_VID_FS_FULL+video_fullscreen_scale, MF_CHECKED); - CheckMenuItem(menuMain, IDM_VID_REMEMBER, window_remember?MF_CHECKED:MF_UNCHECKED); - CheckMenuItem(menuMain, IDM_VID_SCALE_1X+scale, MF_CHECKED); - CheckMenuItem(menuMain, IDM_VID_HIDPI, dpi_scale?MF_CHECKED:MF_UNCHECKED); + if (show_second_monitors == 1) + CheckMenuItem(menuMain, IDM_VID_MONITORS, MF_CHECKED); - CheckMenuItem(menuMain, IDM_VID_CGACON, vid_cga_contrast?MF_CHECKED:MF_UNCHECKED); - CheckMenuItem(menuMain, IDM_VID_GRAYCT_601+video_graytype, MF_CHECKED); - CheckMenuItem(menuMain, IDM_VID_GRAY_RGB+video_grayscale, MF_CHECKED); + if (vid_resize == 1) + CheckMenuItem(menuMain, IDM_VID_RESIZE, MF_CHECKED); + CheckMenuItem(menuMain, IDM_VID_SDL_SW + vid_api, MF_CHECKED); + CheckMenuItem(menuMain, IDM_VID_FS_FULL + video_fullscreen_scale, MF_CHECKED); + CheckMenuItem(menuMain, IDM_VID_REMEMBER, window_remember ? MF_CHECKED : MF_UNCHECKED); + CheckMenuItem(menuMain, IDM_VID_SCALE_1X + scale, MF_CHECKED); + CheckMenuItem(menuMain, IDM_VID_HIDPI, dpi_scale ? MF_CHECKED : MF_UNCHECKED); + + CheckMenuItem(menuMain, IDM_VID_CGACON, vid_cga_contrast ? MF_CHECKED : MF_UNCHECKED); + CheckMenuItem(menuMain, IDM_VID_GRAYCT_601 + video_graytype, MF_CHECKED); + CheckMenuItem(menuMain, IDM_VID_GRAY_RGB + video_grayscale, MF_CHECKED); video_set_filter_menu(menuMain); +#ifdef DISCORD if (discord_loaded) - CheckMenuItem(menuMain, IDM_DISCORD, enable_discord ? MF_CHECKED : MF_UNCHECKED); + CheckMenuItem(menuMain, IDM_DISCORD, enable_discord ? MF_CHECKED : MF_UNCHECKED); else - EnableMenuItem(menuMain, IDM_DISCORD, MF_DISABLED); + EnableMenuItem(menuMain, IDM_DISCORD, MF_DISABLED); +#endif + #ifdef MTR_ENABLED EnableMenuItem(menuMain, IDM_ACTION_END_TRACE, MF_DISABLED); #endif if (vid_resize) { - if (vid_resize >= 2) { - CheckMenuItem(menuMain, IDM_VID_RESIZE, MF_UNCHECKED); - EnableMenuItem(menuMain, IDM_VID_RESIZE, MF_GRAYED); - } + if (vid_resize >= 2) { + CheckMenuItem(menuMain, IDM_VID_RESIZE, MF_UNCHECKED); + EnableMenuItem(menuMain, IDM_VID_RESIZE, MF_GRAYED); + } - CheckMenuItem(menuMain, IDM_VID_SCALE_1X + scale, MF_UNCHECKED); - CheckMenuItem(menuMain, IDM_VID_SCALE_2X, MF_CHECKED); - EnableMenuItem(menuMain, IDM_VID_SCALE_1X, MF_GRAYED); - EnableMenuItem(menuMain, IDM_VID_SCALE_2X, MF_GRAYED); - EnableMenuItem(menuMain, IDM_VID_SCALE_3X, MF_GRAYED); - EnableMenuItem(menuMain, IDM_VID_SCALE_4X, MF_GRAYED); + CheckMenuItem(menuMain, IDM_VID_SCALE_1X + scale, MF_UNCHECKED); + CheckMenuItem(menuMain, IDM_VID_SCALE_2X, MF_CHECKED); + EnableMenuItem(menuMain, IDM_VID_SCALE_1X, MF_GRAYED); + EnableMenuItem(menuMain, IDM_VID_SCALE_2X, MF_GRAYED); + EnableMenuItem(menuMain, IDM_VID_SCALE_3X, MF_GRAYED); + EnableMenuItem(menuMain, IDM_VID_SCALE_4X, MF_GRAYED); + EnableMenuItem(menuMain, IDM_VID_SCALE_5X, MF_GRAYED); + EnableMenuItem(menuMain, IDM_VID_SCALE_6X, MF_GRAYED); + EnableMenuItem(menuMain, IDM_VID_SCALE_7X, MF_GRAYED); + EnableMenuItem(menuMain, IDM_VID_SCALE_8X, MF_GRAYED); + EnableMenuItem(menuMain, IDM_VID_SCALE_9X, MF_GRAYED); + EnableMenuItem(menuMain, IDM_VID_SCALE_10X, MF_GRAYED); } } - void win_notify_dlg_open(void) { - manager_wm = 1; + manager_wm = 1; pause_state = dopause; plat_pause(1); if (source_hwnd) - PostMessage((HWND) (uintptr_t) source_hwnd, WM_SENDDLGSTATUS, (WPARAM) 1, (LPARAM) hwndMain); + PostMessage((HWND) (uintptr_t) source_hwnd, WM_SENDDLGSTATUS, (WPARAM) 1, (LPARAM) hwndMain); } - void win_notify_dlg_closed(void) { if (source_hwnd) - PostMessage((HWND) (uintptr_t) source_hwnd, WM_SENDDLGSTATUS, (WPARAM) 0, (LPARAM) hwndMain); + PostMessage((HWND) (uintptr_t) source_hwnd, WM_SENDDLGSTATUS, (WPARAM) 0, (LPARAM) hwndMain); plat_pause(pause_state); manager_wm = 0; } - void plat_power_off(void) { @@ -378,18 +398,22 @@ plat_power_off(void) /* Cleanly terminate all of the emulator's components so as to avoid things like threads getting stuck. */ - // do_stop(); +#if 0 + do_stop(); +#endif cpu_thread_run = 0; - // exit(-1); +#if 0 + exit(-1); +#endif } #ifdef MTR_ENABLED static void handle_trace(HMENU hmenu, int trace) { - EnableMenuItem(hmenu, IDM_ACTION_BEGIN_TRACE, trace? MF_GRAYED : MF_ENABLED); - EnableMenuItem(hmenu, IDM_ACTION_END_TRACE, trace? MF_ENABLED : MF_GRAYED); + EnableMenuItem(hmenu, IDM_ACTION_BEGIN_TRACE, trace ? MF_GRAYED : MF_ENABLED); + EnableMenuItem(hmenu, IDM_ACTION_END_TRACE, trace ? MF_ENABLED : MF_GRAYED); if (trace) { init_trace(); } else { @@ -404,775 +428,796 @@ static LRESULT CALLBACK #else static BOOL CALLBACK #endif -input_proc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam) +input_proc(UNUSED(HWND hwnd), UINT message, UNUSED(WPARAM wParam), LPARAM lParam) { switch (message) { - case WM_INPUT: - if (infocus) { - UINT size = 0; - PRAWINPUT raw = NULL; + case WM_INPUT: + if (infocus) { + UINT size = 0; + PRAWINPUT raw = NULL; - /* Here we read the raw input data */ - GetRawInputData((HRAWINPUT)lParam, RID_INPUT, NULL, &size, sizeof(RAWINPUTHEADER)); - raw = (PRAWINPUT)malloc(size); - if (GetRawInputData((HRAWINPUT)lParam, RID_INPUT, raw, &size, sizeof(RAWINPUTHEADER)) == size) { - switch(raw->header.dwType) - { - case RIM_TYPEKEYBOARD: - keyboard_handle(raw); - break; - case RIM_TYPEMOUSE: - win_mouse_handle(raw); - break; - case RIM_TYPEHID: - win_joystick_handle(raw); - break; - } - } - free(raw); - } - break; - case WM_SETFOCUS: - infocus = 1; - break; + /* Here we read the raw input data */ + GetRawInputData((HRAWINPUT) lParam, RID_INPUT, NULL, &size, sizeof(RAWINPUTHEADER)); + raw = (PRAWINPUT) malloc(size); + if (GetRawInputData((HRAWINPUT) lParam, RID_INPUT, raw, &size, sizeof(RAWINPUTHEADER)) == size) { + switch (raw->header.dwType) { + case RIM_TYPEKEYBOARD: + keyboard_handle(raw); + break; + case RIM_TYPEMOUSE: + win_mouse_handle(raw); + break; + case RIM_TYPEHID: + win_joystick_handle(raw); + break; + } + } + free(raw); + } + break; + case WM_SETFOCUS: + infocus = 1; + break; - case WM_KILLFOCUS: - infocus = 0; - plat_mouse_capture(0); - break; + case WM_KILLFOCUS: + infocus = 0; + plat_mouse_capture(0); + break; - case WM_LBUTTONDOWN: - button_down |= 1; - break; + case WM_LBUTTONDOWN: + button_down |= 1; + break; - case WM_LBUTTONUP: - if ((button_down & 1) && !video_fullscreen) - plat_mouse_capture(1); - button_down &= ~1; - break; + case WM_LBUTTONUP: + if ((button_down & 1) && !video_fullscreen) + plat_mouse_capture(1); + button_down &= ~1; + break; - case WM_MBUTTONUP: - if (mouse_get_buttons() < 3) - plat_mouse_capture(0); - break; + case WM_MBUTTONUP: + if (mouse_get_buttons() < 3) + plat_mouse_capture(0); + break; - default: - return(1); - /* return(CallWindowProc((WNDPROC)input_orig_proc, - hwnd, message, wParam, lParam)); */ + default: + return 1; +#if 0 + return(CallWindowProc((WNDPROC)input_orig_proc, + hwnd, message, wParam, lParam)); +#endif } - return(0); + return 0; } - static LRESULT CALLBACK MainWindowProcedure(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam) { HMENU hmenu; - int i; - RECT rect, *rect_p; + int i; + RECT rect; + RECT *rect_p; WINDOWPOS *pos; - int temp_x, temp_y; + int temp_x; + int temp_y; if (input_proc(hwnd, message, wParam, lParam) == 0) - return(0); + return 0; switch (message) { - case WM_CREATE: - SetTimer(hwnd, TIMER_1SEC, 1000, NULL); - break; + case WM_CREATE: + SetTimer(hwnd, TIMER_1SEC, 1000, NULL); + break; - case WM_COMMAND: - hmenu = GetMenu(hwnd); - switch (LOWORD(wParam)) { - case IDM_ACTION_SCREENSHOT: - take_screenshot(); - break; + case WM_COMMAND: + hmenu = GetMenu(hwnd); + switch (LOWORD(wParam)) { + case IDM_ACTION_SCREENSHOT: + take_screenshot(); + break; #ifdef MTR_ENABLED - case IDM_ACTION_BEGIN_TRACE: - case IDM_ACTION_END_TRACE: - case IDM_ACTION_TRACE: - tracing_on = !tracing_on; - handle_trace(hmenu, tracing_on); - break; + case IDM_ACTION_BEGIN_TRACE: + case IDM_ACTION_END_TRACE: + case IDM_ACTION_TRACE: + tracing_on = !tracing_on; + handle_trace(hmenu, tracing_on); + break; #endif - case IDM_ACTION_HRESET: - win_notify_dlg_open(); - if (confirm_reset) - i = ui_msgbox_ex(MBX_QUESTION_YN | MBX_DONTASK, (wchar_t *) IDS_2112, NULL, (wchar_t *) IDS_2137, (wchar_t *) IDS_2138, NULL); - else - i = 0; - if ((i % 10) == 0) { - pc_reset_hard(); - if (i == 10) { - confirm_reset = 0; - nvr_save(); - config_save(); - } - } - win_notify_dlg_closed(); - break; + case IDM_ACTION_HRESET: + win_notify_dlg_open(); + if (confirm_reset) + i = ui_msgbox_ex(MBX_QUESTION_YN | MBX_DONTASK, (wchar_t *) IDS_2113, NULL, (wchar_t *) IDS_2138, (wchar_t *) IDS_2139, NULL); + else + i = 0; + if ((i % 10) == 0) { + pc_reset_hard(); + if (i == 10) { + confirm_reset = 0; + nvr_save(); + config_save(); + } + } + win_notify_dlg_closed(); + break; - case IDM_ACTION_RESET_CAD: - pc_send_cad(); - break; + case IDM_ACTION_RESET_CAD: + pc_send_cad(); + break; - case IDM_ACTION_EXIT: - win_notify_dlg_open(); - if (confirm_exit && confirm_exit_cmdl) - i = ui_msgbox_ex(MBX_QUESTION_YN | MBX_DONTASK, (wchar_t *) IDS_2113, NULL, (wchar_t *) IDS_2119, (wchar_t *) IDS_2136, NULL); - else - i = 0; - if ((i % 10) == 0) { - if (i == 10) { - confirm_exit = 0; - nvr_save(); - config_save(); - } - KillTimer(hwnd, TIMER_1SEC); - PostQuitMessage(0); - } - win_notify_dlg_closed(); - break; + case IDM_ACTION_EXIT: + win_notify_dlg_open(); + if (confirm_exit && confirm_exit_cmdl) + i = ui_msgbox_ex(MBX_QUESTION_YN | MBX_DONTASK, (wchar_t *) IDS_2114, NULL, (wchar_t *) IDS_2120, (wchar_t *) IDS_2137, NULL); + else + i = 0; + if ((i % 10) == 0) { + if (i == 10) { + confirm_exit = 0; + nvr_save(); + config_save(); + } + KillTimer(hwnd, TIMER_1SEC); + PostQuitMessage(0); + } + win_notify_dlg_closed(); + break; - case IDM_ACTION_CTRL_ALT_ESC: - pc_send_cae(); - break; + case IDM_ACTION_CTRL_ALT_ESC: + pc_send_cae(); + break; - case IDM_ACTION_RCTRL_IS_LALT: - rctrl_is_lalt ^= 1; - CheckMenuItem(hmenu, IDM_ACTION_RCTRL_IS_LALT, rctrl_is_lalt ? MF_CHECKED : MF_UNCHECKED); - config_save(); - break; + case IDM_ACTION_RCTRL_IS_LALT: + rctrl_is_lalt ^= 1; + CheckMenuItem(hmenu, IDM_ACTION_RCTRL_IS_LALT, rctrl_is_lalt ? MF_CHECKED : MF_UNCHECKED); + config_save(); + break; - case IDM_ACTION_KBD_REQ_CAPTURE: - kbd_req_capture ^= 1; - CheckMenuItem(hmenu, IDM_ACTION_KBD_REQ_CAPTURE, kbd_req_capture ? MF_CHECKED : MF_UNCHECKED); - config_save(); - break; + case IDM_ACTION_KBD_REQ_CAPTURE: + kbd_req_capture ^= 1; + CheckMenuItem(hmenu, IDM_ACTION_KBD_REQ_CAPTURE, kbd_req_capture ? MF_CHECKED : MF_UNCHECKED); + config_save(); + break; - case IDM_ACTION_PAUSE: - plat_pause(dopause ^ 1); - CheckMenuItem(menuMain, IDM_ACTION_PAUSE, dopause ? MF_CHECKED : MF_UNCHECKED); - break; + case IDM_ACTION_PAUSE: + plat_pause(dopause ^ 1); + CheckMenuItem(menuMain, IDM_ACTION_PAUSE, dopause ? MF_CHECKED : MF_UNCHECKED); + break; - case IDM_CONFIG: - win_settings_open(hwnd); - break; + case IDM_CONFIG: + win_settings_open(hwnd); + break; - case IDM_SND_GAIN: - SoundGainDialogCreate(hwnd); - break; + case IDM_SND_GAIN: + SoundGainDialogCreate(hwnd); + break; - case IDM_ABOUT: - AboutDialogCreate(hwnd); - break; + case IDM_ABOUT: + AboutDialogCreate(hwnd); + break; - case IDM_DOCS: - ShellExecute(hwnd, L"open", EMU_DOCS_URL_W, NULL, NULL, SW_SHOW); - break; + case IDM_DOCS: + ShellExecute(hwnd, L"open", EMU_DOCS_URL_W, NULL, NULL, SW_SHOW); + break; - case IDM_UPDATE_ICONS: - update_icons ^= 1; - CheckMenuItem(hmenu, IDM_UPDATE_ICONS, update_icons ? MF_CHECKED : MF_UNCHECKED); - config_save(); - break; + case IDM_UPDATE_ICONS: + update_icons ^= 1; + CheckMenuItem(hmenu, IDM_UPDATE_ICONS, update_icons ? MF_CHECKED : MF_UNCHECKED); + config_save(); + break; - case IDM_VID_HIDE_STATUS_BAR: - hide_status_bar ^= 1; - CheckMenuItem(hmenu, IDM_VID_HIDE_STATUS_BAR, hide_status_bar ? MF_CHECKED : MF_UNCHECKED); - ShowWindow(hwndSBAR, hide_status_bar ? SW_HIDE : SW_SHOW); - GetWindowRect(hwnd, &rect); - if (hide_status_bar) - MoveWindow(hwnd, rect.left, rect.top, rect.right - rect.left, rect.bottom - rect.top - sbar_height, TRUE); - else - MoveWindow(hwnd, rect.left, rect.top, rect.right - rect.left, rect.bottom - rect.top + sbar_height, TRUE); - config_save(); - break; + case IDM_VID_HIDE_STATUS_BAR: + hide_status_bar ^= 1; + CheckMenuItem(hmenu, IDM_VID_HIDE_STATUS_BAR, hide_status_bar ? MF_CHECKED : MF_UNCHECKED); + ShowWindow(hwndSBAR, hide_status_bar ? SW_HIDE : SW_SHOW); + GetWindowRect(hwnd, &rect); + if (hide_status_bar) + MoveWindow(hwnd, rect.left, rect.top, rect.right - rect.left, rect.bottom - rect.top - sbar_height, TRUE); + else + MoveWindow(hwnd, rect.left, rect.top, rect.right - rect.left, rect.bottom - rect.top + sbar_height, TRUE); + config_save(); + break; - case IDM_VID_HIDE_TOOLBAR: - hide_tool_bar ^= 1; - CheckMenuItem(hmenu, IDM_VID_HIDE_TOOLBAR, hide_tool_bar ? MF_CHECKED : MF_UNCHECKED); - ShowWindow(hwndRebar, hide_tool_bar ? SW_HIDE : SW_SHOW); - GetWindowRect(hwnd, &rect); - if (hide_tool_bar) { - MoveWindow(hwnd, rect.left, rect.top, rect.right - rect.left, rect.bottom - rect.top - tbar_height, TRUE); - SetWindowPos(hwndRender, NULL, 0, 0, 0, 0, SWP_NOSIZE | SWP_NOZORDER | SWP_NOACTIVATE); - } else { - MoveWindow(hwnd, rect.left, rect.top, rect.right - rect.left, rect.bottom - rect.top + tbar_height, TRUE); - SetWindowPos(hwndRender, NULL, 0, tbar_height, 0, 0, SWP_NOSIZE | SWP_NOZORDER | SWP_NOACTIVATE); - } - config_save(); - break; + case IDM_VID_HIDE_TOOLBAR: + hide_tool_bar ^= 1; + CheckMenuItem(hmenu, IDM_VID_HIDE_TOOLBAR, hide_tool_bar ? MF_CHECKED : MF_UNCHECKED); + ShowWindow(hwndRebar, hide_tool_bar ? SW_HIDE : SW_SHOW); + GetWindowRect(hwnd, &rect); + if (hide_tool_bar) { + MoveWindow(hwnd, rect.left, rect.top, rect.right - rect.left, rect.bottom - rect.top - tbar_height, TRUE); + SetWindowPos(hwndRender, NULL, 0, 0, 0, 0, SWP_NOSIZE | SWP_NOZORDER | SWP_NOACTIVATE); + } else { + MoveWindow(hwnd, rect.left, rect.top, rect.right - rect.left, rect.bottom - rect.top + tbar_height, TRUE); + SetWindowPos(hwndRender, NULL, 0, tbar_height, 0, 0, SWP_NOSIZE | SWP_NOZORDER | SWP_NOACTIVATE); + } + config_save(); + break; - case IDM_VID_RESIZE: - vid_resize ^= 1; - CheckMenuItem(hmenu, IDM_VID_RESIZE, (vid_resize & 1) ? MF_CHECKED : MF_UNCHECKED); + case IDM_VID_MONITORS: + show_second_monitors ^= 1; + CheckMenuItem(hmenu, IDM_VID_MONITORS, (show_second_monitors & 1) ? MF_CHECKED : MF_UNCHECKED); + break; - if (vid_resize == 1) - SetWindowLongPtr(hwnd, GWL_STYLE, (WS_OVERLAPPEDWINDOW) | WS_VISIBLE); - else - SetWindowLongPtr(hwnd, GWL_STYLE, (WS_OVERLAPPEDWINDOW & ~WS_SIZEBOX & ~WS_MAXIMIZEBOX) | WS_VISIBLE); + case IDM_VID_RESIZE: + vid_resize ^= 1; + CheckMenuItem(hmenu, IDM_VID_RESIZE, (vid_resize & 1) ? MF_CHECKED : MF_UNCHECKED); - /* scale the screen base on DPI */ - if (dpi_scale) { - temp_x = MulDiv(unscaled_size_x, dpi, 96); - temp_y = MulDiv(unscaled_size_y, dpi, 96); - } else { - temp_x = unscaled_size_x; - temp_y = unscaled_size_y; - } + if (vid_resize == 1) + SetWindowLongPtr(hwnd, GWL_STYLE, (WS_OVERLAPPEDWINDOW) | WS_VISIBLE); + else + SetWindowLongPtr(hwnd, GWL_STYLE, (WS_OVERLAPPEDWINDOW & ~WS_SIZEBOX & ~WS_MAXIMIZEBOX) | WS_VISIBLE); - ResizeWindowByClientArea(hwnd, temp_x, temp_y + (hide_status_bar ? 0 : sbar_height) + (hide_tool_bar ? 0 : tbar_height)); + /* scale the screen base on DPI */ + if (dpi_scale) { + temp_x = MulDiv(unscaled_size_x, dpi, 96); + temp_y = MulDiv(unscaled_size_y, dpi, 96); + } else { + temp_x = unscaled_size_x; + temp_y = unscaled_size_y; + } - if (mouse_capture) { - ClipCursor(&rect); - } + ResizeWindowByClientArea(hwnd, temp_x, temp_y + (hide_status_bar ? 0 : sbar_height) + (hide_tool_bar ? 0 : tbar_height)); - if (vid_resize) { - CheckMenuItem(hmenu, IDM_VID_SCALE_1X + scale, MF_UNCHECKED); - CheckMenuItem(hmenu, IDM_VID_SCALE_2X, MF_CHECKED); - scale = 1; - } - EnableMenuItem(hmenu, IDM_VID_SCALE_1X, vid_resize ? MF_GRAYED : MF_ENABLED); - EnableMenuItem(hmenu, IDM_VID_SCALE_2X, vid_resize ? MF_GRAYED : MF_ENABLED); - EnableMenuItem(hmenu, IDM_VID_SCALE_3X, vid_resize ? MF_GRAYED : MF_ENABLED); - EnableMenuItem(hmenu, IDM_VID_SCALE_4X, vid_resize ? MF_GRAYED : MF_ENABLED); + if (mouse_capture) { + ClipCursor(&rect); + } - scrnsz_x = unscaled_size_x; - scrnsz_y = unscaled_size_y; - atomic_flag_clear(&doresize); - config_save(); - break; + if (vid_resize) { + CheckMenuItem(hmenu, IDM_VID_SCALE_1X + scale, MF_UNCHECKED); + CheckMenuItem(hmenu, IDM_VID_SCALE_2X, MF_CHECKED); + scale = 1; + } + EnableMenuItem(hmenu, IDM_VID_SCALE_1X, vid_resize ? MF_GRAYED : MF_ENABLED); + EnableMenuItem(hmenu, IDM_VID_SCALE_2X, vid_resize ? MF_GRAYED : MF_ENABLED); + EnableMenuItem(hmenu, IDM_VID_SCALE_3X, vid_resize ? MF_GRAYED : MF_ENABLED); + EnableMenuItem(hmenu, IDM_VID_SCALE_4X, vid_resize ? MF_GRAYED : MF_ENABLED); + EnableMenuItem(hmenu, IDM_VID_SCALE_5X, vid_resize ? MF_GRAYED : MF_ENABLED); + EnableMenuItem(hmenu, IDM_VID_SCALE_6X, vid_resize ? MF_GRAYED : MF_ENABLED); + EnableMenuItem(hmenu, IDM_VID_SCALE_7X, vid_resize ? MF_GRAYED : MF_ENABLED); + EnableMenuItem(hmenu, IDM_VID_SCALE_8X, vid_resize ? MF_GRAYED : MF_ENABLED); + EnableMenuItem(hmenu, IDM_VID_SCALE_9X, vid_resize ? MF_GRAYED : MF_ENABLED); + EnableMenuItem(hmenu, IDM_VID_SCALE_10X, vid_resize ? MF_GRAYED : MF_ENABLED); - case IDM_VID_REMEMBER: - window_remember = !window_remember; - CheckMenuItem(hmenu, IDM_VID_REMEMBER, window_remember ? MF_CHECKED : MF_UNCHECKED); - GetWindowRect(hwnd, &rect); - if (window_remember || (vid_resize & 2)) { - window_x = rect.left; - window_y = rect.top; - if (!(vid_resize & 2)) { - window_w = rect.right - rect.left; - window_h = rect.bottom - rect.top; - } - } - config_save(); - break; + scrnsz_x = unscaled_size_x; + scrnsz_y = unscaled_size_y; + atomic_store(&doresize_monitors[0], 1); + config_save(); + break; - case IDM_VID_SDL_SW: - case IDM_VID_SDL_HW: - case IDM_VID_SDL_OPENGL: - case IDM_VID_OPENGL_CORE: + case IDM_VID_REMEMBER: + window_remember = !window_remember; + CheckMenuItem(hmenu, IDM_VID_REMEMBER, window_remember ? MF_CHECKED : MF_UNCHECKED); + GetWindowRect(hwnd, &rect); + if (window_remember || (vid_resize & 2)) { + window_x = rect.left; + window_y = rect.top; + if (!(vid_resize & 2)) { + window_w = rect.right - rect.left; + window_h = rect.bottom - rect.top; + } + } + config_save(); + break; + + case IDM_VID_SDL_SW: + case IDM_VID_SDL_HW: + case IDM_VID_SDL_OPENGL: + case IDM_VID_OPENGL_CORE: #ifdef USE_VNC - case IDM_VID_VNC: + case IDM_VID_VNC: #endif - CheckMenuItem(hmenu, IDM_VID_SDL_SW + vid_api, MF_UNCHECKED); - plat_setvid(LOWORD(wParam) - IDM_VID_SDL_SW); - CheckMenuItem(hmenu, IDM_VID_SDL_SW + vid_api, MF_CHECKED); - video_set_filter_menu(hmenu); - config_save(); - show_render_options_menu(); - break; + CheckMenuItem(hmenu, IDM_VID_SDL_SW + vid_api, MF_UNCHECKED); + plat_setvid(LOWORD(wParam) - IDM_VID_SDL_SW); + CheckMenuItem(hmenu, IDM_VID_SDL_SW + vid_api, MF_CHECKED); + video_set_filter_menu(hmenu); + config_save(); + show_render_options_menu(); + break; - case IDM_VID_GL_FPS_BLITTER: - case IDM_VID_GL_FPS_25: - case IDM_VID_GL_FPS_30: - case IDM_VID_GL_FPS_50: - case IDM_VID_GL_FPS_60: - case IDM_VID_GL_FPS_75: - { - static const int fps[] = { -1, 25, 30, 50, 60, 75 }; - int idx = 0; - for (; fps[idx] != video_framerate; idx++); - CheckMenuItem(hmenu, IDM_VID_GL_FPS_BLITTER + idx, MF_UNCHECKED); - video_framerate = fps[LOWORD(wParam) - IDM_VID_GL_FPS_BLITTER]; - CheckMenuItem(hmenu, LOWORD(wParam), MF_CHECKED); - plat_vid_reload_options(); - config_save(); - break; - } - case IDM_VID_GL_VSYNC: - video_vsync = !video_vsync; - CheckMenuItem(hmenu, IDM_VID_GL_VSYNC, video_vsync ? MF_CHECKED : MF_UNCHECKED); - plat_vid_reload_options(); - config_save(); - break; - case IDM_VID_GL_SHADER: - win_notify_dlg_open(); - if (file_dlg_st(hwnd, IDS_2143, video_shader, NULL, 0) == 0) - { - strcpy_s(video_shader, sizeof(video_shader), openfilestring); - EnableMenuItem(menuMain, IDM_VID_GL_NOSHADER, strlen(video_shader) > 0 ? MF_ENABLED : MF_DISABLED); - } - win_notify_dlg_closed(); - plat_vid_reload_options(); - break; - case IDM_VID_GL_NOSHADER: - video_shader[0] = '\0'; - EnableMenuItem(menuMain, IDM_VID_GL_NOSHADER, MF_DISABLED); - plat_vid_reload_options(); - break; + case IDM_VID_GL_FPS_BLITTER: + case IDM_VID_GL_FPS_25: + case IDM_VID_GL_FPS_30: + case IDM_VID_GL_FPS_50: + case IDM_VID_GL_FPS_60: + case IDM_VID_GL_FPS_75: + { + static const int fps[] = { -1, 25, 30, 50, 60, 75 }; + int idx = 0; + for (; fps[idx] != video_framerate; idx++) + ; + CheckMenuItem(hmenu, IDM_VID_GL_FPS_BLITTER + idx, MF_UNCHECKED); + video_framerate = fps[LOWORD(wParam) - IDM_VID_GL_FPS_BLITTER]; + CheckMenuItem(hmenu, LOWORD(wParam), MF_CHECKED); + plat_vid_reload_options(); + config_save(); + break; + } + case IDM_VID_GL_VSYNC: + video_vsync = !video_vsync; + CheckMenuItem(hmenu, IDM_VID_GL_VSYNC, video_vsync ? MF_CHECKED : MF_UNCHECKED); + plat_vid_reload_options(); + config_save(); + break; + case IDM_VID_GL_SHADER: + win_notify_dlg_open(); + if (file_dlg_st(hwnd, IDS_2144, video_shader, NULL, 0) == 0) { + strcpy_s(video_shader, sizeof(video_shader), openfilestring); + EnableMenuItem(menuMain, IDM_VID_GL_NOSHADER, strlen(video_shader) > 0 ? MF_ENABLED : MF_DISABLED); + } + win_notify_dlg_closed(); + plat_vid_reload_options(); + break; + case IDM_VID_GL_NOSHADER: + video_shader[0] = '\0'; + EnableMenuItem(menuMain, IDM_VID_GL_NOSHADER, MF_DISABLED); + plat_vid_reload_options(); + break; - case IDM_VID_FULLSCREEN: - plat_setfullscreen(1); - config_save(); - break; + case IDM_VID_FULLSCREEN: + plat_setfullscreen(1); + config_save(); + break; - case IDM_VID_FS_FULL: - case IDM_VID_FS_43: - case IDM_VID_FS_KEEPRATIO: - case IDM_VID_FS_INT: - CheckMenuItem(hmenu, IDM_VID_FS_FULL+video_fullscreen_scale, MF_UNCHECKED); - video_fullscreen_scale = LOWORD(wParam) - IDM_VID_FS_FULL; - CheckMenuItem(hmenu, IDM_VID_FS_FULL+video_fullscreen_scale, MF_CHECKED); - device_force_redraw(); - config_save(); - break; + case IDM_VID_FS_FULL: + case IDM_VID_FS_43: + case IDM_VID_FS_KEEPRATIO: + case IDM_VID_FS_INT: + CheckMenuItem(hmenu, IDM_VID_FS_FULL + video_fullscreen_scale, MF_UNCHECKED); + video_fullscreen_scale = LOWORD(wParam) - IDM_VID_FS_FULL; + CheckMenuItem(hmenu, IDM_VID_FS_FULL + video_fullscreen_scale, MF_CHECKED); + device_force_redraw(); + config_save(); + break; - case IDM_VID_SCALE_1X: - case IDM_VID_SCALE_2X: - case IDM_VID_SCALE_3X: - case IDM_VID_SCALE_4X: - CheckMenuItem(hmenu, IDM_VID_SCALE_1X+scale, MF_UNCHECKED); - scale = LOWORD(wParam) - IDM_VID_SCALE_1X; - CheckMenuItem(hmenu, IDM_VID_SCALE_1X+scale, MF_CHECKED); - reset_screen_size(); - device_force_redraw(); - video_force_resize_set(1); - atomic_flag_clear(&doresize); - config_save(); - break; + case IDM_VID_SCALE_1X: + case IDM_VID_SCALE_2X: + case IDM_VID_SCALE_3X: + case IDM_VID_SCALE_4X: + case IDM_VID_SCALE_5X: + case IDM_VID_SCALE_6X: + case IDM_VID_SCALE_7X: + case IDM_VID_SCALE_8X: + case IDM_VID_SCALE_9X: + case IDM_VID_SCALE_10X: + CheckMenuItem(hmenu, IDM_VID_SCALE_1X + scale, MF_UNCHECKED); + scale = LOWORD(wParam) - IDM_VID_SCALE_1X; + CheckMenuItem(hmenu, IDM_VID_SCALE_1X + scale, MF_CHECKED); + reset_screen_size(); + device_force_redraw(); + video_force_resize_set(1); + atomic_store(&doresize_monitors[0], 1); + config_save(); + break; - case IDM_VID_FILTER_NEAREST: - case IDM_VID_FILTER_LINEAR: - video_filter_method = LOWORD(wParam) - IDM_VID_FILTER_NEAREST; - video_set_filter_menu(hmenu); - plat_vid_reload_options(); - config_save(); - break; + case IDM_VID_FILTER_NEAREST: + case IDM_VID_FILTER_LINEAR: + video_filter_method = LOWORD(wParam) - IDM_VID_FILTER_NEAREST; + video_set_filter_menu(hmenu); + plat_vid_reload_options(); + config_save(); + break; - case IDM_VID_HIDPI: - dpi_scale = !dpi_scale; - CheckMenuItem(hmenu, IDM_VID_HIDPI, dpi_scale ? MF_CHECKED : MF_UNCHECKED); - atomic_flag_clear(&doresize); - config_save(); - break; - - case IDM_PREFERENCES: - PreferencesDlgCreate(hwnd); - break; + case IDM_VID_HIDPI: + dpi_scale = !dpi_scale; + CheckMenuItem(hmenu, IDM_VID_HIDPI, dpi_scale ? MF_CHECKED : MF_UNCHECKED); + atomic_store(&doresize_monitors[0], 1); + config_save(); + break; - case IDM_VID_SPECIFY_DIM: - SpecifyDimensionsDialogCreate(hwnd); - break; + case IDM_PREFERENCES: + PreferencesDlgCreate(hwnd); + break; - case IDM_VID_FORCE43: - video_toggle_option(hmenu, &force_43, IDM_VID_FORCE43); - video_force_resize_set(1); - break; + case IDM_VID_SPECIFY_DIM: + SpecifyDimensionsDialogCreate(hwnd); + break; - case IDM_VID_INVERT: - video_toggle_option(hmenu, &invert_display, IDM_VID_INVERT); - video_copy = (video_grayscale || invert_display) ? video_transform_copy : memcpy; - plat_vidapi_reload(); - break; + case IDM_VID_FORCE43: + video_toggle_option(hmenu, &force_43, IDM_VID_FORCE43); + video_force_resize_set(1); + break; - case IDM_VID_OVERSCAN: - update_overscan = 1; - video_toggle_option(hmenu, &enable_overscan, IDM_VID_OVERSCAN); - video_force_resize_set(1); - break; + case IDM_VID_INVERT: + video_toggle_option(hmenu, &invert_display, IDM_VID_INVERT); + video_copy = (video_grayscale || invert_display) ? video_transform_copy : memcpy; + plat_vidapi_reload(); + break; - case IDM_VID_CGACON: - vid_cga_contrast ^= 1; - CheckMenuItem(hmenu, IDM_VID_CGACON, vid_cga_contrast ? MF_CHECKED : MF_UNCHECKED); - cgapal_rebuild(); - config_save(); - break; + case IDM_VID_OVERSCAN: + update_overscan = 1; + video_toggle_option(hmenu, &enable_overscan, IDM_VID_OVERSCAN); + video_force_resize_set(1); + break; - case IDM_VID_GRAYCT_601: - case IDM_VID_GRAYCT_709: - case IDM_VID_GRAYCT_AVE: - CheckMenuItem(hmenu, IDM_VID_GRAYCT_601+video_graytype, MF_UNCHECKED); - video_graytype = LOWORD(wParam) - IDM_VID_GRAYCT_601; - CheckMenuItem(hmenu, IDM_VID_GRAYCT_601+video_graytype, MF_CHECKED); - device_force_redraw(); - config_save(); - break; + case IDM_VID_CGACON: + vid_cga_contrast ^= 1; + CheckMenuItem(hmenu, IDM_VID_CGACON, vid_cga_contrast ? MF_CHECKED : MF_UNCHECKED); + cgapal_rebuild(); + config_save(); + break; - case IDM_VID_GRAY_RGB: - case IDM_VID_GRAY_MONO: - case IDM_VID_GRAY_AMBER: - case IDM_VID_GRAY_GREEN: - case IDM_VID_GRAY_WHITE: - CheckMenuItem(hmenu, IDM_VID_GRAY_RGB+video_grayscale, MF_UNCHECKED); - video_grayscale = LOWORD(wParam) - IDM_VID_GRAY_RGB; - video_copy = (video_grayscale || invert_display) ? video_transform_copy : memcpy; - plat_vidapi_reload(); - CheckMenuItem(hmenu, IDM_VID_GRAY_RGB+video_grayscale, MF_CHECKED); - device_force_redraw(); - config_save(); - break; + case IDM_VID_GRAYCT_601: + case IDM_VID_GRAYCT_709: + case IDM_VID_GRAYCT_AVE: + CheckMenuItem(hmenu, IDM_VID_GRAYCT_601 + video_graytype, MF_UNCHECKED); + video_graytype = LOWORD(wParam) - IDM_VID_GRAYCT_601; + CheckMenuItem(hmenu, IDM_VID_GRAYCT_601 + video_graytype, MF_CHECKED); + device_force_redraw(); + config_save(); + break; - case IDM_DISCORD: - if (! discord_loaded) break; - enable_discord ^= 1; - CheckMenuItem(hmenu, IDM_DISCORD, enable_discord ? MF_CHECKED : MF_UNCHECKED); - if(enable_discord) { - discord_init(); - discord_update_activity(dopause); - } else - discord_close(); - break; + case IDM_VID_GRAY_RGB: + case IDM_VID_GRAY_MONO: + case IDM_VID_GRAY_AMBER: + case IDM_VID_GRAY_GREEN: + case IDM_VID_GRAY_WHITE: + CheckMenuItem(hmenu, IDM_VID_GRAY_RGB + video_grayscale, MF_UNCHECKED); + video_grayscale = LOWORD(wParam) - IDM_VID_GRAY_RGB; + video_copy = (video_grayscale || invert_display) ? video_transform_copy : memcpy; + plat_vidapi_reload(); + CheckMenuItem(hmenu, IDM_VID_GRAY_RGB + video_grayscale, MF_CHECKED); + device_force_redraw(); + config_save(); + break; - default: - media_menu_proc(hwnd, message, wParam, lParam); - break; - } - return(0); +#ifdef DISCORD + case IDM_DISCORD: + if (!discord_loaded) + break; + enable_discord ^= 1; + CheckMenuItem(hmenu, IDM_DISCORD, enable_discord ? MF_CHECKED : MF_UNCHECKED); + if (enable_discord) { + discord_init(); + discord_update_activity(dopause); + } else + discord_close(); + break; +#endif - case WM_ENTERMENULOOP: - break; + default: + media_menu_proc(hwnd, message, wParam, lParam); + break; + } + return 0; - case WM_DPICHANGED: - dpi = HIWORD(wParam); - GetWindowRect(hwndSBAR, &rect); - sbar_height = rect.bottom - rect.top; - GetWindowRect(hwndRebar, &rect); - tbar_height = rect.bottom - rect.top; - rect_p = (RECT*)lParam; - if (vid_resize == 1) - MoveWindow(hwnd, rect_p->left, rect_p->top, rect_p->right - rect_p->left, rect_p->bottom - rect_p->top, TRUE); - else if (vid_resize >= 2) { - temp_x = fixed_size_x; - temp_y = fixed_size_y; - if (dpi_scale) { - temp_x = MulDiv(temp_x, dpi, 96); - temp_y = MulDiv(temp_y, dpi, 96); - } + case WM_ENTERMENULOOP: + break; - /* Main Window. */ - ResizeWindowByClientArea(hwndMain, temp_x, temp_y + (hide_status_bar ? 0 : sbar_height) + (hide_tool_bar ? 0 : tbar_height)); - } else if (!user_resize) - atomic_flag_clear(&doresize); - break; + case WM_DPICHANGED: + dpi = HIWORD(wParam); + GetWindowRect(hwndSBAR, &rect); + sbar_height = rect.bottom - rect.top; + GetWindowRect(hwndRebar, &rect); + tbar_height = rect.bottom - rect.top; + rect_p = (RECT *) lParam; + if (vid_resize == 1) + MoveWindow(hwnd, rect_p->left, rect_p->top, rect_p->right - rect_p->left, rect_p->bottom - rect_p->top, TRUE); + else if (vid_resize >= 2) { + temp_x = fixed_size_x; + temp_y = fixed_size_y; + if (dpi_scale) { + temp_x = MulDiv(temp_x, dpi, 96); + temp_y = MulDiv(temp_y, dpi, 96); + } - case WM_WINDOWPOSCHANGED: - if (video_fullscreen & 1) - PostMessage(hwndMain, WM_LEAVEFULLSCREEN, 0, 0); + /* Main Window. */ + ResizeWindowByClientArea(hwndMain, temp_x, temp_y + (hide_status_bar ? 0 : sbar_height) + (hide_tool_bar ? 0 : tbar_height)); + } else if (!user_resize) + atomic_store(&doresize_monitors[0], 1); + break; - pos = (WINDOWPOS*)lParam; - GetClientRect(hwndMain, &rect); + case WM_WINDOWPOSCHANGED: + if (video_fullscreen & 1) + PostMessage(hwndMain, WM_LEAVEFULLSCREEN, 0, 0); - if (IsIconic(hwndMain)) { - plat_vidapi_enable(0); - minimized = 1; - return(0); - } else if (minimized) { - minimized = 0; - video_force_resize_set(1); - } + pos = (WINDOWPOS *) lParam; + GetClientRect(hwndMain, &rect); - if (!(pos->flags & SWP_NOSIZE) && (window_remember || (vid_resize & 2))) { - window_x = pos->x; - window_y = pos->y; - if (!(vid_resize & 2)) { - window_w = pos->cx; - window_h = pos->cy; - } - save_window_pos = 1; - config_save(); - } + if (IsIconic(hwndMain)) { + plat_vidapi_enable(0); + minimized = 1; + return 0; + } else if (minimized) { + minimized = 0; + video_force_resize_set(1); + } - if (!(pos->flags & SWP_NOSIZE) || !user_resize) { - plat_vidapi_enable(0); + if (!(pos->flags & SWP_NOSIZE) && (window_remember || (vid_resize & 2))) { + window_x = pos->x; + window_y = pos->y; + if (!(vid_resize & 2)) { + window_w = pos->cx; + window_h = pos->cy; + } + save_window_pos = 1; + config_save(); + } - if (!hide_status_bar) - MoveWindow(hwndSBAR, 0, rect.bottom - sbar_height, sbar_height, rect.right, TRUE); + if (!(pos->flags & SWP_NOSIZE) || !user_resize) { + plat_vidapi_enable(0); - if (!hide_tool_bar) - MoveWindow(hwndRebar, 0, 0, rect.right, tbar_height, TRUE); + if (!hide_status_bar) + MoveWindow(hwndSBAR, 0, rect.bottom - sbar_height, sbar_height, rect.right, TRUE); - MoveWindow(hwndRender, 0, hide_tool_bar ? 0 : tbar_height, rect.right, rect.bottom - (hide_status_bar ? 0 : sbar_height) - (hide_tool_bar ? 0 : tbar_height), TRUE); + if (!hide_tool_bar) + MoveWindow(hwndRebar, 0, 0, rect.right, tbar_height, TRUE); - GetClientRect(hwndRender, &rect); - if (dpi_scale) { - temp_x = MulDiv(rect.right, 96, dpi); - temp_y = MulDiv(rect.bottom, 96, dpi); + MoveWindow(hwndRender, 0, hide_tool_bar ? 0 : tbar_height, rect.right, rect.bottom - (hide_status_bar ? 0 : sbar_height) - (hide_tool_bar ? 0 : tbar_height), TRUE); - if (temp_x != scrnsz_x || temp_y != scrnsz_y) { - scrnsz_x = temp_x; - scrnsz_y = temp_y; - atomic_flag_clear(&doresize); - } - } else { - if (rect.right != scrnsz_x || rect.bottom != scrnsz_y) { - scrnsz_x = rect.right; - scrnsz_y = rect.bottom; - atomic_flag_clear(&doresize); - } - } + GetClientRect(hwndRender, &rect); + if (dpi_scale) { + temp_x = MulDiv(rect.right, 96, dpi); + temp_y = MulDiv(rect.bottom, 96, dpi); - plat_vidsize(rect.right, rect.bottom); + if (temp_x != scrnsz_x || temp_y != scrnsz_y) { + scrnsz_x = temp_x; + scrnsz_y = temp_y; + atomic_store(&doresize_monitors[0], 1); + } + } else { + if (rect.right != scrnsz_x || rect.bottom != scrnsz_y) { + scrnsz_x = rect.right; + scrnsz_y = rect.bottom; + atomic_store(&doresize_monitors[0], 1); + } + } - if (mouse_capture) { - GetWindowRect(hwndRender, &rect); - ClipCursor(&rect); - } + plat_vidsize(rect.right, rect.bottom); - plat_vidapi_enable(2); - } + if (mouse_capture) { + GetWindowRect(hwndRender, &rect); + ClipCursor(&rect); + } - return(0); + plat_vidapi_enable(2); + } - case WM_TIMER: - if (wParam == TIMER_1SEC) - pc_onesec(); - else if ((wParam >= 0x8000) && (wParam <= 0x80ff)) - ui_sb_timer_callback(wParam & 0xff); - break; + return 0; - case WM_LEAVEFULLSCREEN: - plat_setfullscreen(0); - config_save(); - break; + case WM_TIMER: + if (wParam == TIMER_1SEC) + pc_onesec(); + else if ((wParam >= 0x8000) && (wParam <= 0x80ff)) + ui_sb_timer_callback(wParam & 0xff); + break; - case WM_KEYDOWN: - case WM_KEYUP: - case WM_SYSKEYDOWN: - case WM_SYSKEYUP: - return(0); + case WM_LEAVEFULLSCREEN: + plat_setfullscreen(0); + config_save(); + break; - case WM_CLOSE: - win_notify_dlg_open(); - if (confirm_exit && confirm_exit_cmdl) - i = ui_msgbox_ex(MBX_QUESTION_YN | MBX_DONTASK, (wchar_t *) IDS_2113, NULL, (wchar_t *) IDS_2119, (wchar_t *) IDS_2136, NULL); - else - i = 0; - if ((i % 10) == 0) { - if (i == 10) { - confirm_exit = 0; - nvr_save(); - config_save(); - } - KillTimer(hwnd, TIMER_1SEC); - PostQuitMessage(0); - } - win_notify_dlg_closed(); - break; + case WM_KEYDOWN: + case WM_KEYUP: + case WM_SYSKEYDOWN: + case WM_SYSKEYUP: + return 0; - case WM_DESTROY: - win_clear_icon_set(); - KillTimer(hwnd, TIMER_1SEC); - PostQuitMessage(0); - break; + case WM_CLOSE: + win_notify_dlg_open(); + if (confirm_exit && confirm_exit_cmdl) + i = ui_msgbox_ex(MBX_QUESTION_YN | MBX_DONTASK, (wchar_t *) IDS_2114, NULL, (wchar_t *) IDS_2120, (wchar_t *) IDS_2137, NULL); + else + i = 0; + if ((i % 10) == 0) { + if (i == 10) { + confirm_exit = 0; + nvr_save(); + config_save(); + } + KillTimer(hwnd, TIMER_1SEC); + PostQuitMessage(0); + } + win_notify_dlg_closed(); + break; - case WM_SHOWSETTINGS: - if (manager_wm) - break; - manager_wm = 1; - win_settings_open(hwnd); - manager_wm = 0; - break; + case WM_DESTROY: + win_clear_icon_set(); + KillTimer(hwnd, TIMER_1SEC); + PostQuitMessage(0); + break; - case WM_PAUSE: - if (manager_wm) - break; - manager_wm = 1; - plat_pause(dopause ^ 1); - CheckMenuItem(menuMain, IDM_ACTION_PAUSE, dopause ? MF_CHECKED : MF_UNCHECKED); - manager_wm = 0; - break; + case WM_SHOWSETTINGS: + if (manager_wm) + break; + manager_wm = 1; + win_settings_open(hwnd); + manager_wm = 0; + break; - case WM_HARDRESET: - if (manager_wm) - break; - win_notify_dlg_open(); - if (confirm_reset) - i = ui_msgbox_ex(MBX_QUESTION_YN | MBX_DONTASK, (wchar_t *) IDS_2112, NULL, (wchar_t *) IDS_2137, (wchar_t *) IDS_2138, NULL); - else - i = 0; - if ((i % 10) == 0) { - pc_reset_hard(); - if (i == 10) { - confirm_reset = 0; - nvr_save(); - config_save(); - } - } - win_notify_dlg_closed(); - break; + case WM_PAUSE: + if (manager_wm) + break; + manager_wm = 1; + plat_pause(dopause ^ 1); + CheckMenuItem(menuMain, IDM_ACTION_PAUSE, dopause ? MF_CHECKED : MF_UNCHECKED); + manager_wm = 0; + break; - case WM_SHUTDOWN: - if (manager_wm) - break; - if (LOWORD(wParam) == 1) { - confirm_exit = 0; - nvr_save(); - config_save(); - KillTimer(hwnd, TIMER_1SEC); - PostQuitMessage(0); - } else { - win_notify_dlg_open(); - if (confirm_exit && confirm_exit_cmdl) - i = ui_msgbox_ex(MBX_QUESTION_YN | MBX_DONTASK, (wchar_t *) IDS_2113, NULL, (wchar_t *) IDS_2119, (wchar_t *) IDS_2136, NULL); - else - i = 0; - if ((i % 10) == 0) { - if (i == 10) { - confirm_exit = 0; - nvr_save(); - config_save(); - } - KillTimer(hwnd, TIMER_1SEC); - PostQuitMessage(0); - } - win_notify_dlg_closed(); - } - break; + case WM_HARDRESET: + if (manager_wm) + break; + win_notify_dlg_open(); + if (confirm_reset) + i = ui_msgbox_ex(MBX_QUESTION_YN | MBX_DONTASK, (wchar_t *) IDS_2113, NULL, (wchar_t *) IDS_2138, (wchar_t *) IDS_2139, NULL); + else + i = 0; + if ((i % 10) == 0) { + pc_reset_hard(); + if (i == 10) { + confirm_reset = 0; + nvr_save(); + config_save(); + } + } + win_notify_dlg_closed(); + break; - case WM_CTRLALTDEL: - if (manager_wm) - break; - manager_wm = 1; - pc_send_cad(); - manager_wm = 0; - break; + case WM_SHUTDOWN: + if (manager_wm) + break; + if (LOWORD(wParam) == 1) { + confirm_exit = 0; + nvr_save(); + config_save(); + KillTimer(hwnd, TIMER_1SEC); + PostQuitMessage(0); + } else { + win_notify_dlg_open(); + if (confirm_exit && confirm_exit_cmdl) + i = ui_msgbox_ex(MBX_QUESTION_YN | MBX_DONTASK, (wchar_t *) IDS_2114, NULL, (wchar_t *) IDS_2120, (wchar_t *) IDS_2137, NULL); + else + i = 0; + if ((i % 10) == 0) { + if (i == 10) { + confirm_exit = 0; + nvr_save(); + config_save(); + } + KillTimer(hwnd, TIMER_1SEC); + PostQuitMessage(0); + } + win_notify_dlg_closed(); + } + break; - case WM_SYSCOMMAND: - /* - * Disable ALT key *ALWAYS*, - * I don't think there's any use for - * reaching the menu that way. - */ - if (wParam == SC_KEYMENU && HIWORD(lParam) <= 0) { - return 0; /*disable ALT key for menu*/ - } + case WM_CTRLALTDEL: + if (manager_wm) + break; + manager_wm = 1; + pc_send_cad(); + manager_wm = 0; + break; - default: - return(DefWindowProc(hwnd, message, wParam, lParam)); + case WM_SYSCOMMAND: + /* + * Disable ALT key *ALWAYS*, + * I don't think there's any use for + * reaching the menu that way. + */ + if (wParam == SC_KEYMENU && HIWORD(lParam) <= 0) { + return 0; /*disable ALT key for menu*/ + } - case WM_SETFOCUS: - infocus = 1; - break; + default: + return (DefWindowProc(hwnd, message, wParam, lParam)); - case WM_KILLFOCUS: - infocus = 0; - plat_mouse_capture(0); - break; + case WM_SETFOCUS: + infocus = 1; + break; - case WM_ACTIVATE: - if ((wParam != WA_INACTIVE) && !(video_fullscreen & 2)) { - video_force_resize_set(1); - plat_vidapi_enable(0); - plat_vidapi_enable(1); - } - break; + case WM_KILLFOCUS: + infocus = 0; + plat_mouse_capture(0); + break; - case WM_ACTIVATEAPP: - /* Leave full screen on switching application except - for OpenGL Core and VNC renderers. */ - if (video_fullscreen & 1 && wParam == FALSE && vid_api < 3) - PostMessage(hwndMain, WM_LEAVEFULLSCREEN, 0, 0); - break; + case WM_ACTIVATE: + if ((wParam != WA_INACTIVE) && !(video_fullscreen & 2)) { + video_force_resize_set(1); + plat_vidapi_enable(0); + plat_vidapi_enable(1); + } + break; - case WM_ENTERSIZEMOVE: - user_resize = 1; - break; + case WM_ACTIVATEAPP: + /* Leave full screen on switching application except + for OpenGL Core and VNC renderers. */ + if (video_fullscreen & 1 && wParam == FALSE && vid_api < 3) + PostMessage(hwndMain, WM_LEAVEFULLSCREEN, 0, 0); + break; - case WM_EXITSIZEMOVE: - user_resize = 0; + case WM_ENTERSIZEMOVE: + user_resize = 1; + break; - /* If window is not resizable, then tell the main thread to - resize it, as sometimes, moves can mess up the window size. */ - if (!vid_resize) - atomic_flag_clear(&doresize); - break; + case WM_EXITSIZEMOVE: + user_resize = 0; + + /* If window is not resizable, then tell the main thread to + resize it, as sometimes, moves can mess up the window size. */ + if (!vid_resize) + atomic_store(&doresize_monitors[0], 1); + break; } - return(0); + return 0; } - static LRESULT CALLBACK SubWindowProcedure(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam) { switch (message) { - case WM_LBUTTONDOWN: - button_down |= 2; - break; + case WM_LBUTTONDOWN: + button_down |= 2; + break; - case WM_LBUTTONUP: - if ((button_down & 2) && !video_fullscreen) - plat_mouse_capture(1); - button_down &= ~2; - break; + case WM_LBUTTONUP: + if ((button_down & 2) && !video_fullscreen) + plat_mouse_capture(1); + button_down &= ~2; + break; - case WM_MBUTTONUP: - if (mouse_get_buttons() < 3) - plat_mouse_capture(0); - break; + case WM_MBUTTONUP: + if (mouse_get_buttons() < 3) + plat_mouse_capture(0); + break; - default: - return(DefWindowProc(hwnd, message, wParam, lParam)); + default: + return (DefWindowProc(hwnd, message, wParam, lParam)); } - return(0); + return 0; } - static LRESULT CALLBACK SDLMainWindowProcedure(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam) { if (input_proc(hwnd, message, wParam, lParam) == 0) - return(0); + return 0; - return(DefWindowProc(hwnd, message, wParam, lParam)); + return (DefWindowProc(hwnd, message, wParam, lParam)); } - static LRESULT CALLBACK SDLSubWindowProcedure(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam) { - return(DefWindowProc(hwnd, message, wParam, lParam)); + return (DefWindowProc(hwnd, message, wParam, lParam)); } - static HRESULT CALLBACK -TaskDialogProcedure(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam, LONG_PTR lpRefData) +TaskDialogProcedure(HWND hwnd, UINT message, UNUSED(WPARAM wParam), LPARAM lParam, UNUSED(LONG_PTR lpRefData)) { switch (message) { - case TDN_HYPERLINK_CLICKED: - /* open linked URL */ - ShellExecute(hwnd, L"open", (LPCWSTR) lParam, NULL, NULL, SW_SHOW); - break; + case TDN_HYPERLINK_CLICKED: + /* open linked URL */ + ShellExecute(hwnd, L"open", (LPCWSTR) lParam, NULL, NULL, SW_SHOW); + break; } return S_OK; } - int ui_init(int nCmdShow) { - WCHAR title[200]; - WNDCLASSEX wincl; /* buffer for main window's class */ - RAWINPUTDEVICE ridev; /* RawInput device */ - MSG messages = {0}; /* received-messages buffer */ - HWND hwnd = NULL; /* handle for our window */ - HACCEL haccel; /* handle to accelerator table */ - RECT rect; - int bRet; - TASKDIALOGCONFIG tdconfig = {0}; - TASKDIALOG_BUTTON tdbuttons[] = {{IDCANCEL, MAKEINTRESOURCE(IDS_2119)}}; + WCHAR title[200]; + WNDCLASSEX wincl; /* buffer for main window's class */ + RAWINPUTDEVICE ridev; /* RawInput device */ + MSG messages = { 0 }; /* received-messages buffer */ + HWND hwnd = NULL; /* handle for our window */ + HACCEL haccel; /* handle to accelerator table */ + RECT rect; + int bRet; + TASKDIALOGCONFIG tdconfig = { 0 }; + TASKDIALOG_BUTTON tdbuttons[] = { + {IDCANCEL, MAKEINTRESOURCE(IDS_2120)} + }; uint32_t helper_lang; + static int fs_on_signal = 0; + static int fs_off_signal = 0; /* Load DPI related Windows 10 APIs */ user32_handle = dynld_module("user32.dll", user32_imports); @@ -1180,101 +1225,102 @@ ui_init(int nCmdShow) /* Set the application ID for the taskbar. */ shell32_handle = dynld_module("shell32.dll", shell32_imports); if (shell32_handle) - pSetCurrentProcessExplicitAppUserModelID(L"86Box.86Box"); + pSetCurrentProcessExplicitAppUserModelID(L"86Box.86Box"); /* Set up TaskDialog configuration. */ - tdconfig.cbSize = sizeof(tdconfig); - tdconfig.dwFlags = TDF_ENABLE_HYPERLINKS; - tdconfig.dwCommonButtons = 0; - tdconfig.pszWindowTitle = MAKEINTRESOURCE(IDS_STRINGS); - tdconfig.pszMainIcon = TD_ERROR_ICON; + tdconfig.cbSize = sizeof(tdconfig); + tdconfig.dwFlags = TDF_ENABLE_HYPERLINKS; + tdconfig.dwCommonButtons = 0; + tdconfig.pszWindowTitle = MAKEINTRESOURCE(IDS_STRINGS); + tdconfig.pszMainIcon = TD_ERROR_ICON; tdconfig.pszMainInstruction = MAKEINTRESOURCE(IDS_2050); - tdconfig.cButtons = ARRAYSIZE(tdbuttons); - tdconfig.pButtons = tdbuttons; - tdconfig.pfCallback = TaskDialogProcedure; + tdconfig.cButtons = ARRAYSIZE(tdbuttons); + tdconfig.pButtons = tdbuttons; + tdconfig.pfCallback = TaskDialogProcedure; /* Load the desired iconset */ win_load_icon_set(); /* Start settings-only mode if requested. */ if (settings_only) { - if (! pc_init_modules()) { - /* Dang, no ROMs found at all! */ - tdconfig.pszMainInstruction = MAKEINTRESOURCE(IDS_2120); - tdconfig.pszContent = MAKEINTRESOURCE(IDS_2056); - TaskDialogIndirect(&tdconfig, NULL, NULL, NULL); - return(6); - } + if (!pc_init_modules()) { + /* Dang, no ROMs found at all! */ + tdconfig.pszMainInstruction = MAKEINTRESOURCE(IDS_2121); + tdconfig.pszContent = MAKEINTRESOURCE(IDS_2056); + TaskDialogIndirect(&tdconfig, NULL, NULL, NULL); + return 6; + } + /* Load the desired language */ + helper_lang = lang_id; + lang_id = 0; + set_language(helper_lang); - /* Load the desired language */ - helper_lang = lang_id; - lang_id = 0; - set_language(helper_lang); - - win_settings_open(NULL); - return(0); + win_settings_open(NULL); + return 0; } - if(! discord_load()) { - enable_discord = 0; +#ifdef DISCORD + if (!discord_load()) { + enable_discord = 0; } else if (enable_discord) { - /* Initialize the Discord API */ - discord_init(); + /* Initialize the Discord API */ + discord_init(); - /* Update Discord status */ - discord_update_activity(dopause); + /* Update Discord status */ + discord_update_activity(dopause); } +#endif /* Create our main window's class and register it. */ - wincl.hInstance = hinstance; + wincl.hInstance = hinstance; wincl.lpszClassName = CLASS_NAME; - wincl.lpfnWndProc = MainWindowProcedure; - wincl.style = CS_DBLCLKS; /* Catch double-clicks */ - wincl.cbSize = sizeof(WNDCLASSEX); - wincl.hIcon = NULL; - wincl.hIconSm = NULL; - wincl.hCursor = NULL; - wincl.lpszMenuName = NULL; - wincl.cbClsExtra = 0; - wincl.cbWndExtra = 0; - wincl.hbrBackground = CreateSolidBrush(RGB(0,0,0)); + wincl.lpfnWndProc = MainWindowProcedure; + wincl.style = CS_DBLCLKS; /* Catch double-clicks */ + wincl.cbSize = sizeof(WNDCLASSEX); + wincl.hIcon = NULL; + wincl.hIconSm = NULL; + wincl.hCursor = NULL; + wincl.lpszMenuName = NULL; + wincl.cbClsExtra = 0; + wincl.cbWndExtra = 0; + wincl.hbrBackground = CreateSolidBrush(RGB(0, 0, 0)); /* Load proper icons */ - wchar_t path[MAX_PATH + 1] = {0}; + wchar_t path[MAX_PATH + 1] = { 0 }; GetModuleFileNameW(hinstance, path, MAX_PATH); ExtractIconExW(path, 0, &wincl.hIcon, &wincl.hIconSm, 1); - if (! RegisterClassEx(&wincl)) - return(2); + if (!RegisterClassEx(&wincl)) + return 2; wincl.lpszClassName = SUB_CLASS_NAME; - wincl.lpfnWndProc = SubWindowProcedure; - if (! RegisterClassEx(&wincl)) - return(2); + wincl.lpfnWndProc = SubWindowProcedure; + if (!RegisterClassEx(&wincl)) + return 2; wincl.lpszClassName = SDL_CLASS_NAME; - wincl.lpfnWndProc = SDLMainWindowProcedure; - if (! RegisterClassEx(&wincl)) - return(2); + wincl.lpfnWndProc = SDLMainWindowProcedure; + if (!RegisterClassEx(&wincl)) + return 2; wincl.lpszClassName = SDL_SUB_CLASS_NAME; - wincl.lpfnWndProc = SDLSubWindowProcedure; - if (! RegisterClassEx(&wincl)) - return(2); + wincl.lpfnWndProc = SDLSubWindowProcedure; + if (!RegisterClassEx(&wincl)) + return 2; /* Now create our main window. */ swprintf_s(title, sizeof_w(title), L"%hs - %s %s", vm_name, EMU_NAME_W, EMU_VERSION_FULL_W); - hwnd = CreateWindowEx ( - 0, /* no extended possibilites */ - CLASS_NAME, /* class name */ - title, /* Title Text */ - (WS_OVERLAPPEDWINDOW & ~WS_SIZEBOX) | DS_3DLOOK, - CW_USEDEFAULT, /* Windows decides the position */ - CW_USEDEFAULT, /* where window ends up on the screen */ - scrnsz_x+(GetSystemMetrics(SM_CXFIXEDFRAME)*2), /* width */ - scrnsz_y+(GetSystemMetrics(SM_CYFIXEDFRAME)*2)+GetSystemMetrics(SM_CYMENUSIZE)+GetSystemMetrics(SM_CYCAPTION)+1, /* and height in pixels */ - HWND_DESKTOP, /* window is a child to desktop */ - NULL, /* no menu (yet) */ - hinstance, /* Program Instance handler */ - NULL); /* no Window Creation data */ + hwnd = CreateWindowEx( + 0, /* no extended possibilites */ + CLASS_NAME, /* class name */ + title, /* Title Text */ + (WS_OVERLAPPEDWINDOW & ~WS_SIZEBOX) | DS_3DLOOK, + CW_USEDEFAULT, /* Windows decides the position */ + CW_USEDEFAULT, /* where window ends up on the screen */ + scrnsz_x + (GetSystemMetrics(SM_CXFIXEDFRAME) * 2), /* width */ + scrnsz_y + (GetSystemMetrics(SM_CYFIXEDFRAME) * 2) + GetSystemMetrics(SM_CYMENUSIZE) + GetSystemMetrics(SM_CYCAPTION) + 1, /* and height in pixels */ + HWND_DESKTOP, /* window is a child to desktop */ + NULL, /* no menu (yet) */ + hinstance, /* Program Instance handler */ + NULL); /* no Window Creation data */ hwndMain = tdconfig.hwndParent = hwnd; ui_window_title(title); @@ -1292,55 +1338,53 @@ ui_init(int nCmdShow) GetWindowRect(hwndSBAR, &rect); sbar_height = rect.bottom - rect.top; if (hide_status_bar) - ShowWindow(hwndSBAR, SW_HIDE); + ShowWindow(hwndSBAR, SW_HIDE); /* Create the toolbar window. */ ToolBarCreate(hwndMain, hinstance); /* Get the actual height of the toolbar */ - GetWindowRect(hwndRebar, &rect); - tbar_height = rect.bottom - rect.top; + tbar_height = SendMessage(hwndRebar, RB_GETROWHEIGHT, 0, 0); if (hide_tool_bar) - ShowWindow(hwndRebar, SW_HIDE); + ShowWindow(hwndRebar, SW_HIDE); /* Set up main window for resizing if configured. */ if (vid_resize == 1) - SetWindowLongPtr(hwnd, GWL_STYLE, - (WS_OVERLAPPEDWINDOW)); + SetWindowLongPtr(hwnd, GWL_STYLE, + (WS_OVERLAPPEDWINDOW)); else - SetWindowLongPtr(hwnd, GWL_STYLE, - (WS_OVERLAPPEDWINDOW&~WS_SIZEBOX&~WS_THICKFRAME&~WS_MAXIMIZEBOX)); + SetWindowLongPtr(hwnd, GWL_STYLE, + (WS_OVERLAPPEDWINDOW & ~WS_SIZEBOX & ~WS_THICKFRAME & ~WS_MAXIMIZEBOX)); /* Create the Machine Rendering window. */ - hwndRender = CreateWindow(/*L"STATIC"*/ SUB_CLASS_NAME, NULL, WS_CHILD|SS_BITMAP, - 0, 0, 1, 1, hwnd, NULL, hinstance, NULL); + hwndRender = CreateWindow(/*L"STATIC"*/ SUB_CLASS_NAME, NULL, WS_CHILD | SS_BITMAP, + 0, 0, 1, 1, hwnd, NULL, hinstance, NULL); /* Initiate a resize in order to properly arrange all controls. Move to the last-saved position if needed. */ if ((vid_resize < 2) && window_remember) - MoveWindow(hwnd, window_x, window_y, window_w, window_h, TRUE); + MoveWindow(hwnd, window_x, window_y, window_w, window_h, TRUE); else { - if (vid_resize >= 2) { - MoveWindow(hwnd, window_x, window_y, window_w, window_h, TRUE); - scrnsz_x = fixed_size_x; - scrnsz_y = fixed_size_y; - } - ResizeWindowByClientArea(hwnd, scrnsz_x, scrnsz_y + (hide_status_bar ? 0 : sbar_height) + (hide_tool_bar ? 0 : tbar_height)); + if (vid_resize >= 2) { + MoveWindow(hwnd, window_x, window_y, window_w, window_h, TRUE); + scrnsz_x = fixed_size_x; + scrnsz_y = fixed_size_y; + } + ResizeWindowByClientArea(hwnd, scrnsz_x, scrnsz_y + (hide_status_bar ? 0 : sbar_height) + (hide_tool_bar ? 0 : tbar_height)); } /* Load the desired language */ helper_lang = lang_id; - lang_id = 0; + lang_id = 0; set_language(helper_lang); - + /* Make the window visible on the screen. */ ShowWindow(hwnd, nCmdShow); /* Warn the user about unsupported configs. */ - if (cpu_override && ui_msgbox_ex(MBX_WARNING | MBX_QUESTION_OK, (void*)IDS_2145, (void*)IDS_2146, (void*)IDS_2147, (void*)IDS_2119, NULL)) - { - DestroyWindow(hwnd); - return(0); + if (cpu_override && ui_msgbox_ex(MBX_WARNING | MBX_QUESTION_OK, (void *) IDS_2146, (void *) IDS_2147, (void *) IDS_2148, (void *) IDS_2120, NULL)) { + DestroyWindow(hwnd); + return 0; } GetClipCursor(&oldclip); @@ -1348,27 +1392,27 @@ ui_init(int nCmdShow) /* Initialize the RawInput (keyboard) module. */ memset(&ridev, 0x00, sizeof(ridev)); ridev.usUsagePage = 0x01; - ridev.usUsage = 0x06; - ridev.dwFlags = RIDEV_NOHOTKEYS; - ridev.hwndTarget = NULL; /* current focus window */ - if (! RegisterRawInputDevices(&ridev, 1, sizeof(ridev))) { - tdconfig.pszContent = MAKEINTRESOURCE(IDS_2105); - TaskDialogIndirect(&tdconfig, NULL, NULL, NULL); - return(4); + ridev.usUsage = 0x06; + ridev.dwFlags = RIDEV_NOHOTKEYS; + ridev.hwndTarget = NULL; /* current focus window */ + if (!RegisterRawInputDevices(&ridev, 1, sizeof(ridev))) { + tdconfig.pszContent = MAKEINTRESOURCE(IDS_2106); + TaskDialogIndirect(&tdconfig, NULL, NULL, NULL); + return 4; } keyboard_getkeymap(); /* Load the accelerator table */ haccel = LoadAccelerators(hinstance, ACCEL_NAME); if (haccel == NULL) { - tdconfig.pszContent = MAKEINTRESOURCE(IDS_2104); - TaskDialogIndirect(&tdconfig, NULL, NULL, NULL); - return(3); + tdconfig.pszContent = MAKEINTRESOURCE(IDS_2105); + TaskDialogIndirect(&tdconfig, NULL, NULL, NULL); + return 3; } /* Initialize the mouse module. */ if (!start_in_fullscreen) - win_mouse_init(); + win_mouse_init(); /* * Before we can create the Render window, we first have @@ -1377,30 +1421,30 @@ ui_init(int nCmdShow) ghMutex = CreateMutex(NULL, FALSE, NULL); /* All done, fire up the actual emulated machine. */ - if (! pc_init_modules()) { - /* Dang, no ROMs found at all! */ - tdconfig.pszMainInstruction = MAKEINTRESOURCE(IDS_2120); - tdconfig.pszContent = MAKEINTRESOURCE(IDS_2056); - TaskDialogIndirect(&tdconfig, NULL, NULL, NULL); - return(6); + if (!pc_init_modules()) { + /* Dang, no ROMs found at all! */ + tdconfig.pszMainInstruction = MAKEINTRESOURCE(IDS_2121); + tdconfig.pszContent = MAKEINTRESOURCE(IDS_2056); + TaskDialogIndirect(&tdconfig, NULL, NULL, NULL); + return 6; } /* Initialize the configured Video API. */ - if (! plat_setvid(vid_api)) { - tdconfig.pszContent = MAKEINTRESOURCE(IDS_2089); - TaskDialogIndirect(&tdconfig, NULL, NULL, NULL); - return(5); + if (!plat_setvid(vid_api)) { + tdconfig.pszContent = MAKEINTRESOURCE(IDS_2090); + TaskDialogIndirect(&tdconfig, NULL, NULL, NULL); + return 5; } /* Set up the current window size. */ if (vid_resize & 2) - plat_resize(fixed_size_x, fixed_size_y); + plat_resize(fixed_size_x, fixed_size_y); else - plat_resize(scrnsz_x, scrnsz_y); + plat_resize(scrnsz_x, scrnsz_y); /* Initialize the rendering window, or fullscreen. */ if (start_in_fullscreen) - plat_setfullscreen(3); + plat_setfullscreen(3); /* Fire up the machine. */ pc_reset_hard_init(); @@ -1413,7 +1457,7 @@ ui_init(int nCmdShow) * the hWnd and unique ID the application has given * us. */ if (source_hwnd) - PostMessage((HWND) (uintptr_t) source_hwnd, WM_SENDHWND, (WPARAM) unique_id, (LPARAM) hwndMain); + PostMessage((HWND) (uintptr_t) source_hwnd, WM_SENDHWND, (WPARAM) unique_id, (LPARAM) hwndMain); /* * Everything has been configured, and all seems to work, @@ -1424,51 +1468,61 @@ ui_init(int nCmdShow) do_start(); /* Run the message loop. It will run until GetMessage() returns 0 */ - while (! is_quit) { - bRet = GetMessage(&messages, NULL, 0, 0); - if ((bRet == 0) || is_quit) break; + while (!is_quit) { + bRet = GetMessage(&messages, NULL, 0, 0); + if ((bRet == 0) || is_quit) + break; - if (bRet == -1) { - fatal("bRet is -1\n"); - } - - /* On WM_QUIT, tell the CPU thread to stop running. That will then tell us - to stop running as well. */ - if (messages.message == WM_QUIT) - cpu_thread_run = 0; - - if (! TranslateAccelerator(hwnd, haccel, &messages)) - { - /* Don't process other keypresses. */ - if (messages.message == WM_SYSKEYDOWN || - messages.message == WM_SYSKEYUP || - messages.message == WM_KEYDOWN || - messages.message == WM_KEYUP) - continue; - - TranslateMessage(&messages); - DispatchMessage(&messages); - } - - if (mouse_capture && keyboard_ismsexit()) { - /* Release the in-app mouse. */ - plat_mouse_capture(0); + if (bRet == -1) { + fatal("bRet is -1\n"); } - if (video_fullscreen && keyboard_isfsexit()) { - /* Signal "exit fullscreen mode". */ - plat_setfullscreen(0); - } + /* On WM_QUIT, tell the CPU thread to stop running. That will then tell us + to stop running as well. */ + if (messages.message == WM_QUIT) + cpu_thread_run = 0; - /* Run Discord API callbacks */ - if (enable_discord) - discord_run_callbacks(); + if (!TranslateAccelerator(hwnd, haccel, &messages)) { + /* Don't process other keypresses. */ + if (messages.message == WM_SYSKEYDOWN || messages.message == WM_SYSKEYUP || messages.message == WM_KEYDOWN || messages.message == WM_KEYUP) + continue; + + TranslateMessage(&messages); + DispatchMessage(&messages); + } + + if (mouse_capture && keyboard_ismsexit()) { + /* Release the in-app mouse. */ + plat_mouse_capture(0); + } + + if (!fs_off_signal && video_fullscreen && keyboard_isfsexit()) { + /* Signal "exit fullscreen mode". */ + fs_off_signal = 1; + } else if (fs_off_signal && video_fullscreen && keyboard_isfsexit_up()) { + plat_setfullscreen(0); + fs_off_signal = 0; + } + + if (!fs_on_signal && !video_fullscreen && keyboard_isfsenter()) { + /* Signal "enter fullscreen mode". */ + fs_on_signal = 1; + } else if (fs_on_signal && !video_fullscreen && keyboard_isfsenter_up()) { + plat_setfullscreen(1); + fs_on_signal = 0; + } + +#ifdef DISCORD + /* Run Discord API callbacks */ + if (enable_discord) + discord_run_callbacks(); +#endif } timeEndPeriod(1); if (mouse_capture) - plat_mouse_capture(0); + plat_mouse_capture(0); /* Close down the emulator. */ do_stop(); @@ -1480,104 +1534,131 @@ ui_init(int nCmdShow) win_mouse_close(); +#ifdef DISCORD /* Shut down the Discord integration */ discord_close(); +#endif if (user32_handle != NULL) - dynld_close(user32_handle); + dynld_close(user32_handle); - return(messages.wParam); + return (messages.wParam); } - /* We should have the language ID as a parameter. */ void plat_pause(int p) { static wchar_t oldtitle[512]; - wchar_t title[512]; + wchar_t title[512]; /* If un-pausing, as the renderer if that's OK. */ if (p == 0) - p = get_vidpause(); + p = get_vidpause(); /* If already so, done. */ if (dopause == p) { - /* Send the WM to a manager if needed. */ - if (source_hwnd) - PostMessage((HWND) (uintptr_t) source_hwnd, WM_SENDSTATUS, (WPARAM) !!dopause, (LPARAM) hwndMain); + /* Send the WM to a manager if needed. */ + if (source_hwnd) + PostMessage((HWND) (uintptr_t) source_hwnd, WM_SENDSTATUS, (WPARAM) !!dopause, (LPARAM) hwndMain); - return; + return; } if (p) { - wcsncpy(oldtitle, ui_window_title(NULL), sizeof_w(oldtitle) - 1); - wcscpy(title, oldtitle); - wcscat(title, plat_get_string(IDS_2051)); - ui_window_title(title); - } else { - ui_window_title(oldtitle); - } + if (mouse_capture) + plat_mouse_capture(0); + + wcsncpy(oldtitle, ui_window_title(NULL), sizeof_w(oldtitle) - 1); + wcscpy(title, oldtitle); + wcscat(title, plat_get_string(IDS_2051)); + ui_window_title(title); + } else + ui_window_title(oldtitle); /* If un-pausing, synchronize the internal clock with the host's time. */ if ((p == 0) && (time_sync & TIME_SYNC_ENABLED)) - nvr_time_sync(); + nvr_time_sync(); dopause = p; /* Update the actual menu. */ CheckMenuItem(menuMain, IDM_ACTION_PAUSE, - (dopause) ? MF_CHECKED : MF_UNCHECKED); + dopause ? MF_CHECKED : MF_UNCHECKED); +#ifdef DISCORD /* Update Discord status */ if (enable_discord) - discord_update_activity(dopause); + discord_update_activity(dopause); +#endif /* Update the toolbar */ ToolBarUpdatePause(p); /* Send the WM to a manager if needed. */ if (source_hwnd) - PostMessage((HWND) (uintptr_t) source_hwnd, WM_SENDSTATUS, (WPARAM) !!dopause, (LPARAM) hwndMain); + PostMessage((HWND) (uintptr_t) source_hwnd, WM_SENDSTATUS, (WPARAM) !!dopause, (LPARAM) hwndMain); } - /* Tell the UI about a new screen resolution. */ void plat_resize(int x, int y) { /* First, see if we should resize the UI window. */ if (!vid_resize) { - /* scale the screen base on DPI */ - if (dpi_scale) { - x = MulDiv(x, dpi, 96); - y = MulDiv(y, dpi, 96); - } - ResizeWindowByClientArea(hwndMain, x, y + (hide_status_bar ? 0 : sbar_height) + (hide_tool_bar ? 0 : tbar_height)); + /* scale the screen base on DPI */ + if (dpi_scale) { + x = MulDiv(x, dpi, 96); + y = MulDiv(y, dpi, 96); + } + ResizeWindowByClientArea(hwndMain, x, y + (hide_status_bar ? 0 : sbar_height) + (hide_tool_bar ? 0 : tbar_height)); } } +void +plat_resize_request(int w, int h, int monitor_index) +{ + atomic_store((&doresize_monitors[monitor_index]), 1); +} void plat_mouse_capture(int on) { RECT rect; - if (!kbd_req_capture && (mouse_type == MOUSE_TYPE_NONE)) - return; + if (!kbd_req_capture && (mouse_type == MOUSE_TYPE_NONE) && !machine_has_mouse()) + return; if (on && !mouse_capture) { - /* Enable the in-app mouse. */ - GetClipCursor(&oldclip); - GetWindowRect(hwndRender, &rect); - ClipCursor(&rect); - show_cursor(0); - mouse_capture = 1; + /* Enable the in-app mouse. */ + GetClipCursor(&oldclip); + GetWindowRect(hwndRender, &rect); + ClipCursor(&rect); + show_cursor(0); + mouse_capture = 1; } else if (!on && mouse_capture) { - /* Disable the in-app mouse. */ - ClipCursor(&oldclip); - show_cursor(-1); + /* Disable the in-app mouse. */ + ClipCursor(&oldclip); + show_cursor(-1); - mouse_capture = 0; + mouse_capture = 0; } } + +void +ui_init_monitor(UNUSED(int monitor_index)) +{ + // Nothing done here yet +} + +void +ui_deinit_monitor(UNUSED(int monitor_index)) +{ + // Nothing done here yet +} + +void +ui_hard_reset_completed(void) +{ + // Nothing done here yet +} diff --git a/vcpkg.json b/vcpkg.json index 85295f1cf..9a21175ec 100644 --- a/vcpkg.json +++ b/vcpkg.json @@ -1,35 +1,58 @@ { - "name": "86box", - "version-string": "3.1", - "homepage": "https://86box.net/", - "documentation": "http://86box.readthedocs.io/", - "license": "GPL-2.0-or-later", - "dependencies": [ - "freetype", - "libpng", - "openal-soft", - "sdl2", - "rtmidi" - ], - "features": { - "qt-ui": { - "description": "Qt User Interface", - "dependencies": [ - "qt5-base", - "qt5-translations" - ] - }, - "munt": { - "description": "Roland MT-32 emulation", - "dependencies": [ - "libmt32emu" - ] - }, - "slirp": { - "description": "Slirp network support", - "dependencies": [ - "libslirp" - ] - } - } + "name": "86box", + "version-string": "4.0.2", + "homepage": "https://86box.net/", + "documentation": "https://86box.readthedocs.io/", + "license": "GPL-2.0-or-later", + "dependencies": [ + "freetype", + "libpng", + "sdl2", + "rtmidi", + "libslirp", + "fluidsynth" + ], + "features": { + "qt-ui": { + "description": "Qt User Interface", + "dependencies": [ + { + "name": "qtbase", + "default-features": false, + "features": [ + "concurrent", + "default-features", + "gui", + "opengl", + "harfbuzz", + "network", + "vulkan", + "widgets", + "png", + "zstd" + ] + }, + { + "name": "qttools", + "default-features": false, + "features": [ + "linguist" + ], + "host": true + } + ] + }, + "munt": { + "description": "Roland MT-32 emulation", + "dependencies": [ + "libmt32emu" + ] + }, + "openal": { + "description": "OpenAL sound backend", + "dependencies": [ + "openal-soft" + ] + } + } }